Index: /trunk/minix/LICENSE
===================================================================
--- /trunk/minix/LICENSE	(revision 9)
+++ /trunk/minix/LICENSE	(revision 9)
@@ -0,0 +1,52 @@
+
+License
+
+Copyright (c) 1987, 1997, 2006, Vrije Universiteit, Amsterdam,
+The Netherlands All rights reserved. Redistribution and use of the MINIX 3
+operating system in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+    * Neither the name of the Vrije Universiteit nor the names of the
+    software authors or contributors may be used to endorse or promote
+    products derived from this software without specific prior written
+    permission.
+
+    * Any deviations from these conditions require written permission
+    from the copyright holder in advance
+
+
+Disclaimer
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND
+ CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Aggregated Software
+
+In addition to MINIX 3 itself, the distribution CD-ROM and this Website
+contain additional software that is not part of MINIX 3 and is not
+covered by this license. The licensing conditions for this additional
+software are stated in the various packages. In particular, some of the
+additional software falls under the GPL, and you must take care to
+observe the conditions of the GPL with respect to this software. As
+clearly stated in Article 2 of the GPL, when GPL and nonGPL software are
+distributed together on the same medium, this aggregation does not cause
+the license of either part to apply to the other part.
Index: /trunk/minix/Makefile
===================================================================
--- /trunk/minix/Makefile	(revision 9)
+++ /trunk/minix/Makefile	(revision 9)
@@ -0,0 +1,71 @@
+# Master Makefile to compile everything in /usr/src except the system.
+
+MAKE	= exec make -$(MAKEFLAGS)
+
+usage:
+	@echo "" 
+	@echo "Master Makefile for MINIX commands and utilities." 
+	@echo "Root privileges are required for some actions." 
+	@echo "" 
+	@echo "Usage:" 
+	@echo "	make world      # Compile everything (libraries & commands)" 
+	@echo "	make includes   # Install include files from src/" 
+	@echo "	make libraries  # Compile and install libraries" 
+	@echo "	make cmds       # Compile all, commands, but don't install" 
+	@echo "	make install    # Compile and install commands" 
+	@echo "	make depend     # Generate required .depend files" 
+	@echo "	make clean      # Remove all compiler results" 
+	@echo "" 
+	@echo "Run 'make' in tools/ to create a new MINIX configuration." 
+	@echo "" 
+
+# world has to be able to make a new system, even if there
+# is no complete old system. it has to install commands, for which
+# it has to install libraries, for which it has to install includes,
+# for which it has to install /etc (for users and ownerships).
+# etcfiles also creates a directory hierarchy in its
+# 'make install' target.
+# 
+# etcfiles has to be done first.
+world: includes depend libraries cmds install postinstall
+
+includes:
+	cd include && $(MAKE) install gcc
+
+libraries:
+	cd lib && $(MAKE) all install
+
+cmds:
+	if [ -f commands/Makefile ] ; then cd commands && $(MAKE) all; fi
+
+install::
+	if [ -f commands/Makefile ] ; then cd commands && $(MAKE) install; fi
+
+depend::
+	mkdep kernel
+	mkdep servers
+	mkdep drivers
+	cd kernel && $(MAKE) $@
+	cd servers && $(MAKE) $@
+	cd drivers && $(MAKE) $@
+
+
+clean::
+	cd lib && $(MAKE) $@
+	test ! -f commands/Makefile || { cd commands && $(MAKE) $@; }
+
+etcfiles::
+	cd etc && $(MAKE) install
+
+clean::
+	cd test && $(MAKE) $@
+
+all install clean::
+	cd boot && $(MAKE) $@
+	cd man && $(MAKE) $@	# First manpages, then commands
+	test ! -f commands/Makefile || { cd commands && $(MAKE) $@; }
+	cd tools && $(MAKE) $@
+	cd servers && $(MAKE) $@
+
+postinstall:
+	cd etc && $(MAKE) $@
Index: /trunk/minix/boot/Makefile
===================================================================
--- /trunk/minix/boot/Makefile	(revision 9)
+++ /trunk/minix/boot/Makefile	(revision 9)
@@ -0,0 +1,116 @@
+# Makefile for the boot monitor package.
+
+SYS	= ..
+
+CC	= exec cc
+CC86	= exec cc -mi86 -Was-ncc
+CFLAGS	= -I$(SYS)
+LIBS	= -lsys
+LD	= $(CC) -s -.o
+LD86	= $(CC86) -.o
+BIN	= /usr/bin
+MDEC	= /usr/mdec
+
+all:	bootblock boot edparams masterboot jumpboot installboot addaout
+dos:	boot.com mkfile.com
+
+bootblock:	bootblock.s
+	$(LD86) -com -o $@ bootblock.s
+
+masterboot:	masterboot.s
+	$(LD86) -com -o $@ masterboot.s
+
+jumpboot:	jumpboot.s
+	$(LD86) -com -o $@ jumpboot.s
+
+boot.o:	boot.c
+	$(CC86) $(CFLAGS) -c boot.c
+
+bootimage.o:	bootimage.c
+	$(CC86) $(CFLAGS) -c bootimage.c
+
+rawfs86.o:	rawfs.c rawfs.o
+	ln -f rawfs.c rawfs86.c
+	$(CC86) $(CFLAGS) -c rawfs86.c
+	rm rawfs86.c
+	-cmp -s rawfs.o rawfs86.o && ln -f rawfs.o rawfs86.o
+
+boot:	boothead.s boot.o bootimage.o rawfs86.o
+	$(LD86) -o $@ \
+		boothead.s boot.o bootimage.o rawfs86.o $(LIBS)
+	install -S 8kb boot
+
+edparams.o:	boot.c
+	ln -f boot.c edparams.c
+	$(CC) $(CFLAGS) -DUNIX -c edparams.c
+	rm edparams.c
+
+edparams:	edparams.o rawfs.o
+	$(CC) $(CFLAGS) $(STRIP) -o $@ edparams.o rawfs.o
+	install -S 16kw edparams
+
+dosboot.o:	boot.c
+	$(CC86) $(CFLAGS) -DDOS -o $@ -c boot.c
+
+doshead.o:	doshead.s
+	$(CC) -mi386 -o $@ -c doshead.s
+
+dosboot:	doshead.o dosboot.o bootimage.o rawfs86.o
+	$(LD86) -com -o $@ \
+		doshead.o dosboot.o bootimage.o rawfs86.o $(LIBS)
+
+boot.com:	dosboot
+	./a.out2com dosboot boot.com
+
+mkfile:	mkfhead.s mkfile.c
+	$(LD) -.o -mi86 -com -o $@ mkfhead.s mkfile.c $(LIBS)
+
+mkfile.com:	mkfile
+	./a.out2com mkfile mkfile.com
+
+installboot:	installboot.o rawfs.o
+	$(CC) $(STRIP) -o installboot installboot.o rawfs.o
+	install -S 6kw installboot
+
+addaout:	addaout.o
+	$(CC) -o addaout addaout.o
+
+installboot.o bootimage.o: image.h
+boot.o bootimage.o dosboot.o edparams.o: boot.h
+rawfs.o rawfs86.o installboot.o boot.o bootimage.o: rawfs.h
+
+install:	$(MDEC)/bootblock $(MDEC)/boot $(MDEC)/masterboot \
+		$(MDEC)/jumpboot $(BIN)/installboot $(BIN)/edparams
+dosinstall:	$(MDEC)/boot.com $(MDEC)/mkfile.com
+
+$(MDEC)/bootblock:	bootblock
+	install -cs -o bin -m 644 $? $@
+
+$(MDEC)/boot:		boot
+	install -cs -o bin -m 644 $? $@
+
+$(MDEC)/boot.com:	boot.com
+	install -c -m 644 $? $@
+
+$(MDEC)/mkfile.com:	mkfile.com
+	install -c -m 644 $? $@
+
+$(MDEC)/masterboot:	masterboot
+	install -cs -o bin -m 644 $? $@
+
+$(MDEC)/jumpboot:	jumpboot
+	install -cs -o bin -m 644 $? $@
+
+$(BIN)/installboot:	installboot
+	install -cs -o bin $? $@
+
+$(BIN)/addaout:	addaout
+	install -cs -o bin $? $@
+
+$(BIN)/edparams:	edparams
+	install -cs -o bin $? $@
+
+clean:
+	rm -f *.bak *.o
+	rm -f bootblock addaout installboot boot masterboot jumpboot edparams 
+	rm -f dosboot boot.com mkfile mkfile.com
Index: /trunk/minix/boot/a.out2com
===================================================================
--- /trunk/minix/boot/a.out2com	(revision 9)
+++ /trunk/minix/boot/a.out2com	(revision 9)
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+#	a.out2com - Minix a.out to DOS .COM		Author: Kees J. Bot
+#								17 Jun 1995
+# Transform a Minix a.out to the COM format of MS-DOS,
+# the executable must be common I&D with 256 scratch bytes at the start of
+# the text segment to make space for the Program Segment Prefix.  The Minix
+# a.out header and these 256 bytes are removed to make a COM file.
+
+case $# in
+2)	aout="$1"
+	com="$2"
+	;;
+*)	echo "Usage: $0 <a.out> <dos.com>" >&2
+	exit 1
+esac
+
+size "$aout" >/dev/null || exit
+set `size "$aout" | sed 1d`
+count=`expr \( $1 + $2 - 256 + 31 \) / 32`
+
+exec dd if="$aout" of="$com" bs=32 skip=9 count=$count conv=silent
+
+#
+# $PchId: a.out2com,v 1.3 1998/08/01 09:13:01 philip Exp $
Index: /trunk/minix/boot/addaout.c
===================================================================
--- /trunk/minix/boot/addaout.c	(revision 9)
+++ /trunk/minix/boot/addaout.c	(revision 9)
@@ -0,0 +1,128 @@
+/* A small utility to append an a.out header to an arbitrary file. This allows
+ * inclusion of arbitrary data in the boot image, so that it is magically 
+ * loaded as a RAM disk. The a.out header is structured as follows:
+ *
+ *	a_flags:	A_IMG to indicate this is not an executable
+ *
+ * Created:	April 2005, Jorrit N. Herder
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <a.out.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <unistd.h>
+
+#define INPUT_FILE	1
+#define OUTPUT_FILE	2
+
+/* Report problems. */
+void report(char *problem, char *message) 
+{
+  fprintf(stderr, "%s:\n", problem);
+  fprintf(stderr, "   %s\n\n", message);
+}
+
+
+int copy_data(int srcfd, int dstfd) 
+{
+    char buf[8192];
+    ssize_t n;
+    int total=0;
+
+    /* Copy the little bytes themselves. (Source from cp.c). */
+    while ((n= read(srcfd, buf, sizeof(buf))) > 0) {
+	char *bp = buf;
+	ssize_t r;
+
+	while (n > 0 && (r= write(dstfd, bp, n)) > 0) {
+	    bp += r;
+	    n -= r;
+	    total += r;
+	}
+	if (r <= 0) {
+	    if (r == 0) {
+		fprintf(stderr, "Warning: EOF writing to output file.\n");
+		return(-1);
+	    }
+	}
+    }
+    return(total);
+}
+
+
+/* Main program. */
+int main(int argc, char **argv)
+{
+  struct exec aout;
+  struct stat stin;
+  int fdin, fdout;
+  char * bp;
+  int n,r;
+  int total_size=0;
+  int result;
+
+  /* Check if command line arguments are present, or print usage. */
+  if (argc!=3) {
+	printf("Invalid arguments. Usage:\n");
+	printf("    %s <input_file> <output_file>\n",argv[0]); 
+	return(1);
+  }
+
+  /* Check if we can open the input and output file. */
+  if (stat(argv[INPUT_FILE], &stin) != 0) {
+  	report("Couldn't get status of input file", strerror(errno));
+  	return(1);
+  }
+  if ((fdin = open(argv[INPUT_FILE], O_RDONLY)) < 0) {
+  	report("Couldn't open input file", strerror(errno));
+  	return(1);
+  }
+  if ((fdout = open(argv[OUTPUT_FILE], O_WRONLY|O_CREAT|O_TRUNC, 
+  		stin.st_mode & 0777)) < 0) {
+  	report("Couldn't open output file", strerror(errno));
+  	return(1);
+  }
+
+
+  /* Copy input file to output file, but leave space for a.out header. */ 
+  lseek(fdout, sizeof(aout), SEEK_SET);
+  total_size = copy_data(fdin, fdout);
+  if (total_size < 0) {
+  	report("Aborted", "Output file may be truncated.");
+  	return(1);
+  } else if (total_size == 0) {
+  	report("Aborted without prepending header", "No data in input file.");
+  	return(1);
+  }
+
+
+  /* Build a.out header and write to output file. */
+  memset(&aout, 0, sizeof(struct exec));
+  aout.a_magic[0] = A_MAGIC0;
+  aout.a_magic[1] = A_MAGIC1;
+  aout.a_flags |= A_IMG;
+  aout.a_hdrlen = sizeof(aout);
+  aout.a_text = 0;
+  aout.a_data = total_size;
+  aout.a_bss = 0;
+  aout.a_total = aout.a_hdrlen + aout.a_data;
+
+  bp = (char *) &aout;
+  n = sizeof(aout);
+  lseek(fdout, 0, SEEK_SET);
+  while (n > 0 && (r= write(fdout, bp, n)) > 0) {
+  	bp += r;
+  	n -= r;
+  }
+
+  printf("Prepended data file (%u bytes) with a.out header (%u bytes).\n", 
+	total_size, sizeof(aout));
+  printf("Done.\n");
+
+  return(0);
+}
+
Index: /trunk/minix/boot/boot.c
===================================================================
--- /trunk/minix/boot/boot.c	(revision 9)
+++ /trunk/minix/boot/boot.c	(revision 9)
@@ -0,0 +1,1957 @@
+/*	boot.c - Load and start Minix.			Author: Kees J. Bot
+ *								27 Dec 1991
+ */
+
+char version[]=		"2.20";
+
+#define BIOS	(!UNIX)		/* Either uses BIOS or UNIX syscalls. */
+
+#define nil 0
+#define _POSIX_SOURCE	1
+#define _MINIX		1
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <ibm/partition.h>
+#include <minix/config.h>
+#include <minix/type.h>
+#include <minix/com.h>
+#include <minix/dmap.h>
+#include <minix/const.h>
+#include <minix/minlib.h>
+#include <minix/syslib.h>
+#if BIOS
+#include <kernel/const.h>
+#include <kernel/type.h>
+#endif
+#if UNIX
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <termios.h>
+#endif
+#include "rawfs.h"
+#undef EXTERN
+#define EXTERN	/* Empty */
+#include "boot.h"
+
+#define arraysize(a)		(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)		((a) + arraysize(a))
+#define between(a, c, z)	((unsigned) ((c) - (a)) <= ((z) - (a)))
+
+int fsok= -1;		/* File system state.  Initially unknown. */
+
+static int block_size;
+
+#if BIOS
+
+/* this data is reserved for BIOS int 0x13 to put the 'specification packet'
+ * in. It has a structure of course, but we don't define a struct because
+ * of compiler padding. We fiddle out the bytes ourselves later.
+ */
+unsigned char boot_spec[24];
+
+char *bios_err(int err)
+/* Translate BIOS error code to a readable string.  (This is a rare trait
+ * known as error checking and reporting.  Take a good look at it, you won't
+ * see it often.)
+ */
+{
+	static struct errlist {
+		int	err;
+		char	*what;
+	} errlist[] = {
+#if !DOS
+		{ 0x00, "No error" },
+		{ 0x01, "Invalid command" },
+		{ 0x02, "Address mark not found" },
+		{ 0x03, "Disk write-protected" },
+		{ 0x04, "Sector not found" },
+		{ 0x05, "Reset failed" },
+		{ 0x06, "Floppy disk removed" },
+		{ 0x07, "Bad parameter table" },
+		{ 0x08, "DMA overrun" },
+		{ 0x09, "DMA crossed 64 KB boundary" },
+		{ 0x0A, "Bad sector flag" },
+		{ 0x0B, "Bad track flag" },
+		{ 0x0C, "Media type not found" },
+		{ 0x0D, "Invalid number of sectors on format" },
+		{ 0x0E, "Control data address mark detected" },
+		{ 0x0F, "DMA arbitration level out of range" },
+		{ 0x10, "Uncorrectable CRC or ECC data error" },
+		{ 0x11, "ECC corrected data error" },
+		{ 0x20, "Controller failed" },
+		{ 0x40, "Seek failed" },
+		{ 0x80, "Disk timed-out" },
+		{ 0xAA, "Drive not ready" },
+		{ 0xBB, "Undefined error" },
+		{ 0xCC, "Write fault" },
+		{ 0xE0, "Status register error" },
+		{ 0xFF, "Sense operation failed" }
+#else /* DOS */
+		{ 0x00, "No error" },
+		{ 0x01, "Function number invalid" },
+		{ 0x02, "File not found" },
+		{ 0x03, "Path not found" },
+		{ 0x04, "Too many open files" },
+		{ 0x05, "Access denied" },
+		{ 0x06, "Invalid handle" },
+		{ 0x0C, "Access code invalid" },
+#endif /* DOS */
+	};
+	struct errlist *errp;
+
+	for (errp= errlist; errp < arraylimit(errlist); errp++) {
+		if (errp->err == err) return errp->what;
+	}
+	return "Unknown error";
+}
+
+char *unix_err(int err)
+/* Translate the few errors rawfs can give. */
+{
+	switch (err) {
+	case ENOENT:	return "No such file or directory";
+	case ENOTDIR:	return "Not a directory";
+	default:	return "Unknown error";
+	}
+}
+
+void rwerr(char *rw, off_t sec, int err)
+{
+	printf("\n%s error 0x%02x (%s) at sector %ld absolute\n",
+		rw, err, bios_err(err), sec);
+}
+
+void readerr(off_t sec, int err)	{ rwerr("Read", sec, err); }
+void writerr(off_t sec, int err)	{ rwerr("Write", sec, err); }
+
+void readblock(off_t blk, char *buf, int block_size)
+/* Read blocks for the rawfs package. */
+{
+	int r;
+	u32_t sec= lowsec + blk * RATIO(block_size);
+
+	if(!block_size) {
+		printf("block_size 0\n");
+		exit(1);
+	}
+
+	if ((r= readsectors(mon2abs(buf), sec, 1 * RATIO(block_size))) != 0) {
+		readerr(sec, r); exit(1);
+	}
+}
+
+#define istty		(1)
+#define alarm(n)	(0)
+
+#endif /* BIOS */
+
+#if UNIX
+
+/* The Minix boot block must start with these bytes: */
+char boot_magic[] = { 0x31, 0xC0, 0x8E, 0xD8, 0xFA, 0x8E, 0xD0, 0xBC };
+
+struct biosdev {
+	char *name;		/* Name of device. */
+	int device;		/* Device to edit parameters. */
+} bootdev;
+
+struct termios termbuf;
+int istty;
+
+void quit(int status)
+{
+	if (istty) (void) tcsetattr(0, TCSANOW, &termbuf);
+	exit(status);
+}
+
+#define exit(s)	quit(s)
+
+void report(char *label)
+/* edparams: label: No such file or directory */
+{
+	fprintf(stderr, "edparams: %s: %s\n", label, strerror(errno));
+}
+
+void fatal(char *label)
+{
+	report(label);
+	exit(1);
+}
+
+void *alloc(void *m, size_t n)
+{
+	m= m == nil ? malloc(n) : realloc(m, n);
+	if (m == nil) fatal("");
+	return m;
+}
+
+#define malloc(n)	alloc(nil, n)
+#define realloc(m, n)	alloc(m, n)
+
+#define mon2abs(addr)	((void *) (addr))
+
+int rwsectors(int rw, void *addr, u32_t sec, int nsec)
+{
+	ssize_t r;
+	size_t len= nsec * SECTOR_SIZE;
+
+	if (lseek(bootdev.device, sec * SECTOR_SIZE, SEEK_SET) == -1)
+		return errno;
+
+	if (rw == 0) {
+		r= read(bootdev.device, (char *) addr, len);
+	} else {
+		r= write(bootdev.device, (char *) addr, len);
+	}
+	if (r == -1) return errno;
+	if (r != len) return EIO;
+	return 0;
+}
+
+#define readsectors(a, s, n)	 rwsectors(0, (a), (s), (n))
+#define writesectors(a, s, n)	 rwsectors(1, (a), (s), (n))
+#define readerr(sec, err)	(errno= (err), report(bootdev.name))
+#define writerr(sec, err)	(errno= (err), report(bootdev.name))
+#define putch(c)		putchar(c)
+#define unix_err(err)		strerror(err)
+
+void readblock(off_t blk, char *buf, int block_size)
+/* Read blocks for the rawfs package. */
+{
+	if(!block_size) fatal("block_size 0");
+	errno= EIO;
+	if (lseek(bootdev.device, blk * block_size, SEEK_SET) == -1
+		|| read(bootdev.device, buf, block_size) != block_size)
+	{
+		fatal(bootdev.name);
+	}
+}
+
+sig_atomic_t trapsig;
+
+void trap(int sig)
+{
+	trapsig= sig;
+	signal(sig, trap);
+}
+
+int escape(void)
+{
+	if (trapsig == SIGINT) {
+		trapsig= 0;
+		return 1;
+	}
+	return 0;
+}
+
+static unsigned char unchar;
+
+int getch(void)
+{
+	unsigned char c;
+
+	fflush(stdout);
+
+	if (unchar != 0) {
+		c= unchar;
+		unchar= 0;
+		return c;
+	}
+
+	switch (read(0, &c, 1)) {
+	case -1:
+		if (errno != EINTR) fatal("");
+		return(ESC);
+	case 0:
+		if (istty) putch('\n');
+		exit(0);
+	default:
+		if (istty && c == termbuf.c_cc[VEOF]) {
+			putch('\n');
+			exit(0);
+		}
+		return c;
+	}
+}
+
+#define ungetch(c)	((void) (unchar = (c)))
+
+#define get_tick()		((u32_t) time(nil))
+#define clear_screen()		printf("[clear]")
+#define boot_device(device)	printf("[boot %s]\n", device)
+#define ctty(line)		printf("[ctty %s]\n", line)
+#define bootminix()		(run_trailer() && printf("[boot]\n"))
+#define off()			printf("[off]")
+
+#endif /* UNIX */
+
+char *readline(void)
+/* Read a line including a newline with echoing. */
+{
+	char *line;
+	size_t i, z;
+	int c;
+
+	i= 0;
+	z= 20;
+	line= malloc(z * sizeof(char));
+
+	do {
+		c= getch();
+
+		if (strchr("\b\177\25\30", c) != nil) {
+			/* Backspace, DEL, ctrl-U, or ctrl-X. */
+			do {
+				if (i == 0) break;
+				printf("\b \b");
+				i--;
+			} while (c == '\25' || c == '\30');
+		} else
+		if (c < ' ' && c != '\n') {
+			putch('\7');
+		} else {
+			putch(c);
+			line[i++]= c;
+			if (i == z) {
+				z*= 2;
+				line= realloc(line, z * sizeof(char));
+			}
+		}
+	} while (c != '\n');
+	line[i]= 0;
+	return line;
+}
+
+int sugar(char *tok)
+/* Recognize special tokens. */
+{
+	return strchr("=(){};\n", tok[0]) != nil;
+}
+
+char *onetoken(char **aline)
+/* Returns a string with one token for tokenize. */
+{
+	char *line= *aline;
+	size_t n;
+	char *tok;
+
+	/* Skip spaces and runs of newlines. */
+	while (*line == ' ' || (*line == '\n' && line[1] == '\n')) line++;
+
+	*aline= line;
+
+	/* Don't do odd junk (nor the terminating 0!). */
+	if ((unsigned) *line < ' ' && *line != '\n') return nil;
+
+	if (*line == '(') {
+		/* Function argument, anything goes but () must match. */
+		int depth= 0;
+
+		while ((unsigned) *line >= ' ') {
+			if (*line == '(') depth++;
+			if (*line++ == ')' && --depth == 0) break;
+		}
+	} else
+	if (sugar(line)) {
+		/* Single character token. */
+		line++;
+	} else {
+		/* Multicharacter token. */
+		do line++; while ((unsigned) *line > ' ' && !sugar(line));
+	}
+	n= line - *aline;
+	tok= malloc((n + 1) * sizeof(char));
+	memcpy(tok, *aline, n);
+	tok[n]= 0;
+	if (tok[0] == '\n') tok[0]= ';';	/* ';' same as '\n' */
+
+	*aline= line;
+	return tok;
+}
+
+/* Typed commands form strings of tokens. */
+
+typedef struct token {
+	struct token	*next;	/* Next in a command chain. */
+	char		*token;
+} token;
+
+token **tokenize(token **acmds, char *line)
+/* Takes a line apart to form tokens.  The tokens are inserted into a command
+ * chain at *acmds.  Tokenize returns a reference to where another line could
+ * be added.  Tokenize looks at spaces as token separators, and recognizes only
+ * ';', '=', '{', '}', and '\n' as single character tokens.  One token is
+ * formed from '(' and ')' with anything in between as long as more () match.
+ */
+{
+	char *tok;
+	token *newcmd;
+
+	while ((tok= onetoken(&line)) != nil) {
+		newcmd= malloc(sizeof(*newcmd));
+		newcmd->token= tok;
+		newcmd->next= *acmds;
+		*acmds= newcmd;
+		acmds= &newcmd->next;
+	}
+	return acmds;
+}
+
+token *cmds;		/* String of commands to execute. */
+int err;		/* Set on an error. */
+
+char *poptoken(void)
+/* Pop one token off the command chain. */
+{
+	token *cmd= cmds;
+	char *tok= cmd->token;
+
+	cmds= cmd->next;
+	free(cmd);
+
+	return tok;
+}
+
+void voidtoken(void)
+/* Remove one token from the command chain. */
+{
+	free(poptoken());
+}
+
+void parse_code(char *code)
+/* Tokenize a string of monitor code, making sure there is a delimiter.  It is
+ * to be executed next.  (Prepended to the current input.)
+ */
+{
+	if (cmds != nil && cmds->token[0] != ';') (void) tokenize(&cmds, ";");
+	(void) tokenize(&cmds, code);
+}
+
+int interrupt(void)
+/* Clean up after an ESC has been typed. */
+{
+	if (escape()) {
+		printf("[ESC]\n");
+		err= 1;
+		return 1;
+	}
+	return 0;
+}
+
+#if BIOS
+
+int activate;
+
+struct biosdev {
+	char name[8];
+	int device, primary, secondary;
+} bootdev, tmpdev;
+
+int get_master(char *master, struct part_entry **table, u32_t pos)
+/* Read a master boot sector and its partition table. */
+{
+	int r, n;
+	struct part_entry *pe, **pt;
+
+	if ((r= readsectors(mon2abs(master), pos, 1)) != 0) return r;
+
+	pe= (struct part_entry *) (master + PART_TABLE_OFF);
+	for (pt= table; pt < table + NR_PARTITIONS; pt++) *pt= pe++;
+
+	/* DOS has the misguided idea that partition tables must be sorted. */
+	if (pos != 0) return 0;		/* But only the primary. */
+
+	n= NR_PARTITIONS;
+	do {
+		for (pt= table; pt < table + NR_PARTITIONS-1; pt++) {
+			if (pt[0]->sysind == NO_PART
+					|| pt[0]->lowsec > pt[1]->lowsec) {
+				pe= pt[0]; pt[0]= pt[1]; pt[1]= pe;
+			}
+		}
+	} while (--n > 0);
+	return 0;
+}
+
+void initialize(void)
+{
+	char master[SECTOR_SIZE];
+	struct part_entry *table[NR_PARTITIONS];
+	int r, p;
+	u32_t masterpos;
+	char *argp;
+
+	/* Copy the boot program to the far end of low memory, this must be
+	 * done to get out of the way of Minix, and to put the data area
+	 * cleanly inside a 64K chunk if using BIOS I/O (no DMA problems).
+	 */
+	u32_t oldaddr= caddr;
+	u32_t memend= mem[0].base + mem[0].size;
+	u32_t newaddr= (memend - runsize) & ~0x0000FL;
+#if !DOS
+	u32_t dma64k= (memend - 1) & ~0x0FFFFL;
+
+
+	/* Check if data segment crosses a 64K boundary. */
+	if (newaddr + (daddr - caddr) < dma64k)  {
+		newaddr= (dma64k - runsize) & ~0x0000FL;
+	}
+#endif
+
+	/* Set the new caddr for relocate. */
+	caddr= newaddr;
+
+	/* Copy code and data. */
+	raw_copy(newaddr, oldaddr, runsize);
+
+	/* Make the copy running. */
+	relocate();
+
+#if !DOS
+
+	/* Take the monitor out of the memory map if we have memory to spare,
+	 * and also keep the BIOS data area safe (1.5K), plus a bit extra for
+	 * where we may have to put a.out headers for older kernels.
+	 */
+	if (mon_return = (mem[1].size > 512*1024L)) mem[0].size = newaddr;
+	mem[0].base += 2048;
+	mem[0].size -= 2048;
+
+	/* Find out what the boot device and partition was. */
+	bootdev.name[0]= 0;
+	bootdev.device= device;
+	bootdev.primary= -1;
+	bootdev.secondary= -1;
+
+	if (device < 0x80) {
+		/* Floppy. */
+		strcpy(bootdev.name, "fd0");
+		bootdev.name[2] += bootdev.device;
+		return;
+	}
+
+	/* Disk: Get the partition table from the very first sector, and
+	 * determine the partition we booted from using the information from
+	 * the booted partition entry as passed on by the bootstrap (rem_part).
+	 * All we need from it is the partition offset.
+	 */
+	raw_copy(mon2abs(&lowsec),
+		vec2abs(&rem_part) + offsetof(struct part_entry, lowsec),
+		sizeof(lowsec));
+
+	masterpos= 0;	/* Master bootsector position. */
+
+	for (;;) {
+		/* Extract the partition table from the master boot sector. */
+		if ((r= get_master(master, table, masterpos)) != 0) {
+			readerr(masterpos, r); exit(1);
+		}
+
+		/* See if you can find "lowsec" back. */
+		for (p= 0; p < NR_PARTITIONS; p++) {
+			if (lowsec - table[p]->lowsec < table[p]->size) break;
+		}
+
+		if (lowsec == table[p]->lowsec) {	/* Found! */
+			if (bootdev.primary < 0)
+				bootdev.primary= p;
+			else
+				bootdev.secondary= p;
+			break;
+		}
+
+		if (p == NR_PARTITIONS || bootdev.primary >= 0
+					|| table[p]->sysind != MINIX_PART) {
+			/* The boot partition cannot be named, this only means
+			 * that "bootdev" doesn't work.
+			 */
+			bootdev.device= -1;
+			return;
+		}
+
+		/* See if the primary partition is subpartitioned. */
+		bootdev.primary= p;
+		masterpos= table[p]->lowsec;
+	}
+	strcpy(bootdev.name, "d0p0");
+	bootdev.name[1] += (device - 0x80);
+	bootdev.name[3] += bootdev.primary;
+	if (bootdev.secondary >= 0) {
+		strcat(bootdev.name, "s0");
+		bootdev.name[5] += bootdev.secondary;
+	}
+
+#else /* DOS */
+	/* Take the monitor out of the memory map if we have memory to spare,
+	 * note that only half our PSP is needed at the new place, the first
+	 * half is to be kept in its place.
+	 */
+	if (mem[1].size > 0) mem[0].size = newaddr + 0x80 - mem[0].base;
+
+	/* Parse the command line. */
+	argp= PSP + 0x81;
+	argp[PSP[0x80]]= 0;
+	while (between('\1', *argp, ' ')) argp++;
+	vdisk= argp;
+	while (!between('\0', *argp, ' ')) argp++;
+	while (between('\1', *argp, ' ')) *argp++= 0;
+	if (*vdisk == 0) {
+		printf("\nUsage: boot <vdisk> [commands ...]\n");
+		exit(1);
+	}
+	drun= *argp == 0 ? "main" : argp;
+
+	if ((r= dev_open()) != 0) {
+		printf("\n%s: Error %02x (%s)\n", vdisk, r, bios_err(r));
+		exit(1);
+	}
+
+	/* Find the active partition on the virtual disk. */
+	if ((r= get_master(master, table, 0)) != 0) {
+		readerr(0, r); exit(1);
+	}
+
+	strcpy(bootdev.name, "d0");
+	bootdev.primary= -1;
+	for (p= 0; p < NR_PARTITIONS; p++) {
+		if (table[p]->bootind != 0 && table[p]->sysind == MINIX_PART) {
+			bootdev.primary= p;
+			strcat(bootdev.name, "p0");
+			bootdev.name[3] += p;
+			lowsec= table[p]->lowsec;
+			break;
+		}
+	}
+#endif /* DOS */
+}
+
+#endif /* BIOS */
+
+/* Reserved names: */
+enum resnames {
+ 	R_NULL, R_BOOT, R_CTTY, R_DELAY, R_ECHO, R_EXIT, R_HELP,
+	R_LS, R_MENU, R_OFF, R_SAVE, R_SET, R_TRAP, R_UNSET
+};
+
+char resnames[][6] = {
+	"", "boot", "ctty", "delay", "echo", "exit", "help",
+	"ls", "menu", "off", "save", "set", "trap", "unset",
+};
+
+/* Using this for all null strings saves a lot of memory. */
+#define null (resnames[0])
+
+int reserved(char *s)
+/* Recognize reserved strings. */
+{
+	int r;
+
+	for (r= R_BOOT; r <= R_UNSET; r++) {
+		if (strcmp(s, resnames[r]) == 0) return r;
+	}
+	return R_NULL;
+}
+
+void sfree(char *s)
+/* Free a non-null string. */
+{
+	if (s != nil && s != null) free(s);
+}
+
+char *copystr(char *s)
+/* Copy a non-null string using malloc. */
+{
+	char *c;
+
+	if (*s == 0) return null;
+	c= malloc((strlen(s) + 1) * sizeof(char));
+	strcpy(c, s);
+	return c;
+}
+
+int is_default(environment *e)
+{
+	return (e->flags & E_SPECIAL) && e->defval == nil;
+}
+
+environment **searchenv(char *name)
+{
+	environment **aenv= &env;
+
+	while (*aenv != nil && strcmp((*aenv)->name, name) != 0) {
+		aenv= &(*aenv)->next;
+	}
+
+	return aenv;
+}
+
+#define b_getenv(name)	(*searchenv(name))
+/* Return the environment *structure* belonging to name, or nil if not found. */
+
+char *b_value(char *name)
+/* The value of a variable. */
+{
+	environment *e= b_getenv(name);
+
+	return e == nil || !(e->flags & E_VAR) ? nil : e->value;
+}
+
+char *b_body(char *name)
+/* The value of a function. */
+{
+	environment *e= b_getenv(name);
+
+	return e == nil || !(e->flags & E_FUNCTION) ? nil : e->value;
+}
+
+int b_setenv(int flags, char *name, char *arg, char *value)
+/* Change the value of an environment variable.  Returns the flags of the
+ * variable if you are not allowed to change it, 0 otherwise.
+ */
+{
+	environment **aenv, *e;
+
+	if (*(aenv= searchenv(name)) == nil) {
+		if (reserved(name)) return E_RESERVED;
+		e= malloc(sizeof(*e));
+		e->name= copystr(name);
+		e->flags= flags;
+		e->defval= nil;
+		e->next= nil;
+		*aenv= e;
+	} else {
+		e= *aenv;
+
+		/* Don't change special variables to functions or vv. */
+		if (e->flags & E_SPECIAL
+			&& (e->flags & E_FUNCTION) != (flags & E_FUNCTION)
+		) return e->flags;
+
+		e->flags= (e->flags & E_STICKY) | flags;
+		if (is_default(e)) {
+			e->defval= e->value;
+		} else {
+			sfree(e->value);
+		}
+		sfree(e->arg);
+	}
+	e->arg= copystr(arg);
+	e->value= copystr(value);
+
+	return 0;
+}
+
+int b_setvar(int flags, char *name, char *value)
+/* Set variable or simple function. */
+{
+	int r;
+
+	if((r=b_setenv(flags, name, null, value))) {
+		return r;
+	}
+
+	return r;
+}
+
+void b_unset(char *name)
+/* Remove a variable from the environment.  A special variable is reset to
+ * its default value.
+ */
+{
+	environment **aenv, *e;
+
+	if ((e= *(aenv= searchenv(name))) == nil) return;
+
+	if (e->flags & E_SPECIAL) {
+		if (e->defval != nil) {
+			sfree(e->arg);
+			e->arg= null;
+			sfree(e->value);
+			e->value= e->defval;
+			e->defval= nil;
+		}
+	} else {
+		sfree(e->name);
+		sfree(e->arg);
+		sfree(e->value);
+		*aenv= e->next;
+		free(e);
+	}
+}
+
+long a2l(char *a)
+/* Cheap atol(). */
+{
+	int sign= 1;
+	long n= 0;
+
+	if (*a == '-') { sign= -1; a++; }
+
+	while (between('0', *a, '9')) n= n * 10 + (*a++ - '0');
+
+	return sign * n;
+}
+
+char *ul2a(u32_t n, unsigned b)
+/* Transform a long number to ascii at base b, (b >= 8). */
+{
+	static char num[(CHAR_BIT * sizeof(n) + 2) / 3 + 1];
+	char *a= arraylimit(num) - 1;
+	static char hex[16] = "0123456789ABCDEF";
+
+	do *--a = hex[(int) (n % b)]; while ((n/= b) > 0);
+	return a;
+}
+
+char *ul2a10(u32_t n)
+/* Transform a long number to ascii at base 10. */
+{
+	return ul2a(n, 10);
+}
+
+unsigned a2x(char *a)
+/* Ascii to hex. */
+{
+	unsigned n= 0;
+	int c;
+
+	for (;;) {
+		c= *a;
+		if (between('0', c, '9')) c= c - '0' + 0x0;
+		else
+		if (between('A', c, 'F')) c= c - 'A' + 0xA;
+		else
+		if (between('a', c, 'f')) c= c - 'a' + 0xa;
+		else
+			break;
+		n= (n<<4) | c;
+		a++;
+	}
+	return n;
+}
+
+void get_parameters(void)
+{
+	char params[SECTOR_SIZE + 1];
+	token **acmds;
+	int r, bus, processor;
+	memory *mp;
+	static char bus_type[][4] = {
+		"xt", "at", "mca"
+	};
+	static char vid_type[][4] = {
+		"mda", "cga", "ega", "ega", "vga", "vga"
+	};
+	static char vid_chrome[][6] = {
+		"mono", "color"
+	};
+
+	/* Variables that Minix needs: */
+	b_setvar(E_SPECIAL|E_VAR|E_DEV, "rootdev", "ram");
+	b_setvar(E_SPECIAL|E_VAR|E_DEV, "ramimagedev", "bootdev");
+	b_setvar(E_SPECIAL|E_VAR, "ramsize", "0");
+#if BIOS
+	processor = getprocessor();
+	if(processor == 1586) processor = 686;
+	b_setvar(E_SPECIAL|E_VAR, "processor", ul2a10(processor));
+	b_setvar(E_SPECIAL|E_VAR, "bus", bus_type[get_bus()]);
+	b_setvar(E_SPECIAL|E_VAR, "video", vid_type[get_video()]);
+	b_setvar(E_SPECIAL|E_VAR, "chrome", vid_chrome[get_video() & 1]);
+	params[0]= 0;
+	for (mp= mem; mp < arraylimit(mem); mp++) {
+		if (mp->size == 0) continue;
+		if (params[0] != 0) strcat(params, ",");
+		strcat(params, ul2a(mp->base, 0x10));
+		strcat(params, ":");
+		strcat(params, ul2a(mp->size, 0x10));
+	}
+	b_setvar(E_SPECIAL|E_VAR, "memory", params);
+
+#if DOS
+	b_setvar(E_SPECIAL|E_VAR, "dosfile-d0", vdisk);
+#endif
+
+#endif
+#if UNIX
+	b_setvar(E_SPECIAL|E_VAR, "processor", "?");
+	b_setvar(E_SPECIAL|E_VAR, "bus", "?");
+	b_setvar(E_SPECIAL|E_VAR, "video", "?");
+	b_setvar(E_SPECIAL|E_VAR, "chrome", "?");
+	b_setvar(E_SPECIAL|E_VAR, "memory", "?");
+	b_setvar(E_SPECIAL|E_VAR, "c0", "?");
+#endif
+
+	/* Variables boot needs: */
+	b_setvar(E_SPECIAL|E_VAR, "image", "boot/image");
+	b_setvar(E_SPECIAL|E_FUNCTION, "leader", 
+		"echo --- Welcome to MINIX 3. This is the boot monitor. ---\\n");
+	b_setvar(E_SPECIAL|E_FUNCTION, "main", "menu");
+	b_setvar(E_SPECIAL|E_FUNCTION, "trailer", "");
+
+	/* Default hidden menu function: */
+	b_setenv(E_RESERVED|E_FUNCTION, null, "=,Start MINIX", "boot");
+
+	/* Tokenize bootparams sector. */
+	if ((r= readsectors(mon2abs(params), lowsec+PARAMSEC, 1)) != 0) {
+		readerr(lowsec+PARAMSEC, r);
+		exit(1);
+	}
+	params[SECTOR_SIZE]= 0;
+	acmds= tokenize(&cmds, params);
+
+	/* Stuff the default action into the command chain. */
+#if UNIX
+	(void) tokenize(acmds, ":;");
+#elif DOS
+	(void) tokenize(tokenize(acmds, ":;leader;"), drun);
+#else /* BIOS */
+	(void) tokenize(acmds, ":;leader;main");
+#endif
+}
+
+char *addptr;
+
+void addparm(char *n)
+{
+	while (*n != 0 && *addptr != 0) *addptr++ = *n++;
+}
+
+void save_parameters(void)
+/* Save nondefault environment variables to the bootparams sector. */
+{
+	environment *e;
+	char params[SECTOR_SIZE + 1];
+	int r;
+
+	/* Default filling: */
+	memset(params, '\n', SECTOR_SIZE);
+
+	/* Don't touch the 0! */
+	params[SECTOR_SIZE]= 0;
+	addptr= params;
+
+	for (e= env; e != nil; e= e->next) {
+		if (e->flags & E_RESERVED || is_default(e)) continue;
+
+		addparm(e->name);
+		if (e->flags & E_FUNCTION) {
+			addparm("(");
+			addparm(e->arg);
+			addparm(")");
+		} else {
+			addparm((e->flags & (E_DEV|E_SPECIAL)) != E_DEV
+							? "=" : "=d ");
+		}
+		addparm(e->value);
+		if (*addptr == 0) {
+			printf("The environment is too big\n");
+			return;
+		}
+		*addptr++= '\n';
+	}
+
+	/* Save the parameters on disk. */
+	if ((r= writesectors(mon2abs(params), lowsec+PARAMSEC, 1)) != 0) {
+		writerr(lowsec+PARAMSEC, r);
+		printf("Can't save environment\n");
+	}
+}
+
+void show_env(void)
+/* Show the environment settings. */
+{
+	environment *e;
+	unsigned more= 0;
+	int c;
+
+	for (e= env; e != nil; e= e->next) {
+		if (e->flags & E_RESERVED) continue;
+		if (!istty && is_default(e)) continue;
+
+		if (e->flags & E_FUNCTION) {
+			printf("%s(%s) %s\n", e->name, e->arg, e->value);
+		} else {
+			printf(is_default(e) ? "%s = (%s)\n" : "%s = %s\n",
+				e->name, e->value);
+		}
+
+		if (e->next != nil && istty && ++more % 20 == 0) {
+			printf("More? ");
+			c= getch();
+			if (c == ESC || c > ' ') {
+				putch('\n');
+				if (c > ' ') ungetch(c);
+				break;
+			}
+			printf("\b\b\b\b\b\b");
+		}
+	}
+}
+
+int numprefix(char *s, char **ps)
+/* True iff s is a string of digits.  *ps will be set to the first nondigit
+ * if non-nil, otherwise the string should end.
+ */
+{
+	char *n= s;
+
+	while (between('0', *n, '9')) n++;
+
+	if (n == s) return 0;
+
+	if (ps == nil) return *n == 0;
+
+	*ps= n;
+	return 1;
+}
+
+int numeric(char *s)
+{
+	return numprefix(s, (char **) nil);
+}
+
+#if BIOS
+
+/* Device numbers of standard MINIX devices. */
+#define DEV_FD0		0x0200
+static dev_t dev_cNd0[] = { 0x0300, 0x0800, 0x0A00, 0x0C00, 0x1000 };
+#define minor_p0s0	   128
+
+static int block_size;
+
+dev_t name2dev(char *name)
+/* Translate, say, /dev/c0d0p2 to a device number.  If the name can't be
+ * found on the boot device, then do some guesswork.  The global structure
+ * "tmpdev" will be filled in based on the name, so that "boot d1p0" knows
+ * what device to boot without interpreting device numbers.
+ */
+{
+	dev_t dev;
+	ino_t ino;
+	int drive;
+	struct stat st;
+	char *n, *s;
+
+	/* "boot *d0p2" means: make partition 2 active before you boot it. */
+	if ((activate= (name[0] == '*'))) name++;
+
+	/* The special name "bootdev" must be translated to the boot device. */
+	if (strcmp(name, "bootdev") == 0) {
+		if (bootdev.device == -1) {
+			printf("The boot device could not be named\n");
+			errno= 0;
+			return -1;
+		}
+		name= bootdev.name;
+	}
+
+	/* If our boot device doesn't have a file system, or we want to know
+	 * what a name means for the BIOS, then we need to interpret the
+	 * device name ourselves: "fd" = floppy, "c0d0" = hard disk, etc.
+	 */
+	tmpdev.device= tmpdev.primary= tmpdev.secondary= -1;
+	dev= -1;
+	n= name;
+	if (strncmp(n, "/dev/", 5) == 0) n+= 5;
+
+	if (strcmp(n, "ram") == 0) {
+		dev= DEV_RAM;
+	} else
+	if (strcmp(n, "boot") == 0) {
+		dev= DEV_BOOT;
+	} else
+	if (n[0] == 'f' && n[1] == 'd' && numeric(n+2)) {
+		/* Floppy. */
+		tmpdev.device= a2l(n+2);
+		dev= DEV_FD0 + tmpdev.device;
+	} else
+	if ((n[0] == 'h' || n[0] == 's') && n[1] == 'd' && numprefix(n+2, &s)
+		&& (*s == 0 || (between('a', *s, 'd') && s[1] == 0))
+	) {
+		/* Old style hard disk (backwards compatibility.) */
+		dev= a2l(n+2);
+		tmpdev.device= dev / (1 + NR_PARTITIONS);
+		tmpdev.primary= (dev % (1 + NR_PARTITIONS)) - 1;
+		if (*s != 0) {
+			/* Subpartition. */
+			tmpdev.secondary= *s - 'a';
+			dev= minor_p0s0
+				+ (tmpdev.device * NR_PARTITIONS
+					+ tmpdev.primary) * NR_PARTITIONS
+				+ tmpdev.secondary;
+		}
+		tmpdev.device+= 0x80;
+		dev+= n[0] == 'h' ? dev_cNd0[0] : dev_cNd0[2];
+	} else {
+		/* Hard disk. */
+		int ctrlr= 0;
+
+		if (n[0] == 'c' && between('0', n[1], '4')) {
+			ctrlr= (n[1] - '0');
+			tmpdev.device= 0;
+			n+= 2;
+		}
+		if (n[0] == 'd' && between('0', n[1], '7')) {
+			tmpdev.device= (n[1] - '0');
+			n+= 2;
+			if (n[0] == 'p' && between('0', n[1], '3')) {
+				tmpdev.primary= (n[1] - '0');
+				n+= 2;
+				if (n[0] == 's' && between('0', n[1], '3')) {
+					tmpdev.secondary= (n[1] - '0');
+					n+= 2;
+				}
+			}
+		}
+		if (*n == 0) {
+			dev= dev_cNd0[ctrlr];
+			if (tmpdev.secondary < 0) {
+				dev += tmpdev.device * (NR_PARTITIONS+1)
+					+ (tmpdev.primary + 1);
+			} else {
+				dev += minor_p0s0
+					+ (tmpdev.device * NR_PARTITIONS
+					    + tmpdev.primary) * NR_PARTITIONS
+					+ tmpdev.secondary;
+			}
+			tmpdev.device+= 0x80;
+		}
+	}
+
+	/* Look the name up on the boot device for the UNIX device number. */
+	if (fsok == -1) fsok= r_super(&block_size) != 0;
+	if (fsok) {
+		/* The current working directory is "/dev". */
+		ino= r_lookup(r_lookup(ROOT_INO, "dev"), name);
+
+		if (ino != 0) {
+			/* Name has been found, extract the device number. */
+			r_stat(ino, &st);
+			if (!S_ISBLK(st.st_mode)) {
+				printf("%s is not a block device\n", name);
+				errno= 0;
+				return (dev_t) -1;
+			}
+			dev= st.st_rdev;
+		}
+	}
+
+	if (tmpdev.primary < 0) activate= 0;	/* Careful now! */
+
+	if (dev == -1) {
+		printf("Can't recognize '%s' as a device\n", name);
+		errno= 0;
+	}
+	return dev;
+}
+
+#if DEBUG
+static void apm_perror(char *label, u16_t ax)
+{
+	unsigned ah;
+	char *str;
+
+	ah= (ax >> 8);
+	switch(ah)
+	{
+	case 0x01: str= "APM functionality disabled"; break;
+	case 0x03: str= "interface not connected"; break;
+	case 0x09: str= "unrecognized device ID"; break;
+	case 0x0A: str= "parameter value out of range"; break;
+	case 0x0B: str= "interface not engaged"; break;
+	case 0x60: str= "unable to enter requested state"; break;
+	case 0x86: str= "APM not present"; break;
+	default: printf("%s: error 0x%02x\n", label, ah); return;
+	}
+	printf("%s: %s\n", label, str);
+}
+
+#define apm_printf printf
+#else
+#define apm_perror(label, ax) ((void)0)
+#define apm_printf
+#endif
+
+static void off(void)
+{
+	bios_env_t be;
+	unsigned al, ah;
+
+	/* Try to switch off the system. Print diagnostic information
+	 * that can be useful if the operation fails.
+	 */
+
+	be.ax= 0x5300;	/* APM, Installation check */
+	be.bx= 0;	/* Device, APM BIOS */
+	int15(&be);
+	if (be.flags & FL_CARRY)
+	{
+		apm_perror("APM installation check failed", be.ax);
+		return;
+	}
+	if (be.bx != (('P' << 8) | 'M'))
+	{
+		apm_printf("APM signature not found (got 0x%04x)\n", be.bx);
+		return;
+	}
+
+	ah= be.ax >> 8;
+	if (ah > 9)
+		ah= (ah >> 4)*10 + (ah & 0xf);
+	al= be.ax & 0xff;
+	if (al > 9)
+		al= (al >> 4)*10 + (al & 0xf);
+	apm_printf("APM version %u.%u%s%s%s%s%s\n",
+		ah, al,
+		(be.cx & 0x1) ? ", 16-bit PM" : "",
+		(be.cx & 0x2) ? ", 32-bit PM" : "",
+		(be.cx & 0x4) ? ", CPU-Idle" : "",
+		(be.cx & 0x8) ? ", APM-disabled" : "",
+		(be.cx & 0x10) ? ", APM-disengaged" : "");
+
+	/* Connect */
+	be.ax= 0x5301;	/* APM, Real mode interface connect */
+	be.bx= 0x0000;	/* APM BIOS */
+	int15(&be);
+	if (be.flags & FL_CARRY)
+	{
+		apm_perror("APM real mode connect failed", be.ax);
+		return;
+	}
+
+	/* Ask for a seat upgrade */
+	be.ax= 0x530e;	/* APM, Driver Version */
+	be.bx= 0x0000;	/* BIOS */
+	be.cx= 0x0102;	/* version 1.2 */
+	int15(&be);
+	if (be.flags & FL_CARRY)
+	{
+		apm_perror("Set driver version failed", be.ax);
+		goto disco;
+	}
+
+	/* Is this version really worth reporting. Well, if the system
+	 * does switch off, you won't see it anyway.
+	 */
+	ah= be.ax >> 8;
+	if (ah > 9)
+		ah= (ah >> 4)*10 + (ah & 0xf);
+	al= be.ax & 0xff;
+	if (al > 9)
+		al= (al >> 4)*10 + (al & 0xf);
+	apm_printf("Got APM connection version %u.%u\n", ah, al);
+
+	/* Enable */
+	be.ax= 0x5308;	/* APM, Enable/disable power management */
+	be.bx= 0x0001;	/* All device managed by APM BIOS */
+#if 0
+	/* For old APM 1.0 systems, we need 0xffff. Assume that those
+	 * systems do not exist.
+	 */
+	be.bx= 0xffff;	/* All device managed by APM BIOS (compat) */
+#endif
+	be.cx= 0x0001;	/* Enable power management */
+	int15(&be);
+	if (be.flags & FL_CARRY)
+	{
+		apm_perror("Enable power management failed", be.ax);
+		goto disco;
+	}
+
+	/* Off */
+	be.ax= 0x5307;	/* APM, Set Power State */
+	be.bx= 0x0001;	/* All devices managed by APM */
+	be.cx= 0x0003;	/* Off */
+	int15(&be);
+	if (be.flags & FL_CARRY)
+	{
+		apm_perror("Set power state failed", be.ax);
+		goto disco;
+	}
+
+	apm_printf("Power off sequence successfully completed.\n\n");
+	apm_printf("Ha, ha, just kidding!\n");
+
+disco:
+	/* Disconnect */
+	be.ax= 0x5304;	/* APM, interface disconnect */
+	be.bx= 0x0000;	/* APM BIOS */
+	int15(&be);
+	if (be.flags & FL_CARRY)
+	{
+		apm_perror("APM interface disconnect failed", be.ax);
+		return;
+	}
+}
+
+#if !DOS
+#define B_NOSIG		-1	/* "No signature" error code. */
+
+int exec_bootstrap(void)
+/* Load boot sector from the disk or floppy described by tmpdev and execute it.
+ */
+{
+	int r, n, dirty= 0;
+	char master[SECTOR_SIZE];
+	struct part_entry *table[NR_PARTITIONS], dummy, *active= &dummy;
+	u32_t masterpos;
+
+	active->lowsec= 0;
+
+	/* Select a partition table entry. */
+	while (tmpdev.primary >= 0) {
+		masterpos= active->lowsec;
+
+		if ((r= get_master(master, table, masterpos)) != 0) return r;
+
+		active= table[tmpdev.primary];
+
+		/* How does one check a partition table entry? */
+		if (active->sysind == NO_PART) return B_NOSIG;
+
+		tmpdev.primary= tmpdev.secondary;
+		tmpdev.secondary= -1;
+	}
+
+	if (activate && !active->bootind) {
+		for (n= 0; n < NR_PARTITIONS; n++) table[n]->bootind= 0;
+		active->bootind= ACTIVE_FLAG;
+		dirty= 1;
+	}
+
+	/* Read the boot sector. */
+	if ((r= readsectors(BOOTPOS, active->lowsec, 1)) != 0) return r;
+
+	/* Check signature word. */
+	if (get_word(BOOTPOS+SIGNATOFF) != SIGNATURE) return B_NOSIG;
+
+	/* Write the partition table if a member must be made active. */
+	if (dirty && (r= writesectors(mon2abs(master), masterpos, 1)) != 0)
+		return r;
+
+	bootstrap(device, active);
+}
+
+void boot_device(char *devname)
+/* Boot the device named by devname. */
+{
+	dev_t dev= name2dev(devname);
+	int save_dev= device;
+	int r;
+	char *err;
+
+	if (tmpdev.device < 0) {
+		if (dev != -1) printf("Can't boot from %s\n", devname);
+		return;
+	}
+
+	/* Change current device and try to load and execute its bootstrap. */
+	device= tmpdev.device;
+
+	if ((r= dev_open()) == 0) r= exec_bootstrap();
+
+	err= r == B_NOSIG ? "Not bootable" : bios_err(r);
+	printf("Can't boot %s: %s\n", devname, err);
+
+	/* Restore boot device setting. */
+	device= save_dev;
+	(void) dev_open();
+}
+
+void ctty(char *line)
+{
+	if (between('0', line[0], '3') && line[1] == 0) {
+		serial_init(line[0] - '0');
+	} else {
+		printf("Bad serial line number: %s\n", line);
+	}
+}
+
+#else /* DOS */
+
+void boot_device(char *devname)
+/* No booting of other devices under DOS. */
+{
+	printf("Can't boot devices under DOS\n");
+}
+
+void ctty(char *line)
+/* Don't know how to handle serial lines under DOS. */
+{
+	printf("No serial line support under DOS\n");
+}
+
+#endif /* DOS */
+#endif /* BIOS */
+
+void ls(char *dir)
+/* List the contents of a directory. */
+{
+	ino_t ino;
+	struct stat st;
+	char name[NAME_MAX+1];
+
+	if (fsok == -1) fsok= r_super(&block_size) != 0;
+	if (!fsok) return;
+
+	/* (,) construct because r_stat returns void */
+	if ((ino= r_lookup(ROOT_INO, dir)) == 0 ||
+		(r_stat(ino, &st), r_readdir(name)) == -1)
+	{
+		printf("ls: %s: %s\n", dir, unix_err(errno));
+		return;
+	}
+	(void) r_readdir(name);	/* Skip ".." too. */
+
+	while ((ino= r_readdir(name)) != 0) printf("%s/%s\n", dir, name);
+}
+
+u32_t milli_time(void)
+{
+	return get_tick() * MSEC_PER_TICK;
+}
+
+u32_t milli_since(u32_t base)
+{
+	return (milli_time() + (TICKS_PER_DAY*MSEC_PER_TICK) - base)
+			% (TICKS_PER_DAY*MSEC_PER_TICK);
+}
+
+char *Thandler;
+u32_t Tbase, Tcount;
+
+void unschedule(void)
+/* Invalidate a waiting command. */
+{
+	alarm(0);
+
+	if (Thandler != nil) {
+		free(Thandler);
+		Thandler= nil;
+	}
+}
+
+void schedule(long msec, char *cmd)
+/* Schedule command at a certain time from now. */
+{
+	unschedule();
+	Thandler= cmd;
+	Tbase= milli_time();
+	Tcount= msec;
+	alarm(1);
+}
+
+int expired(void)
+/* Check if the timer expired for getch(). */
+{
+	return (Thandler != nil && milli_since(Tbase) >= Tcount);
+}
+
+void delay(char *msec)
+/* Delay for a given time. */
+{
+	u32_t base, count;
+
+	if ((count= a2l(msec)) == 0) return;
+	base= milli_time();
+
+	alarm(1);
+
+	do {
+		pause();
+	} while (!interrupt() && !expired() && milli_since(base) < count);
+}
+
+enum whatfun { NOFUN, SELECT, DEFFUN, USERFUN } menufun(environment *e)
+{
+	if (!(e->flags & E_FUNCTION) || e->arg[0] == 0) return NOFUN;
+	if (e->arg[1] != ',') return SELECT;
+	return e->flags & E_RESERVED ? DEFFUN : USERFUN;
+}
+
+void menu(void)
+/* By default:  Show a simple menu.
+ * Multiple kernels/images:  Show extra selection options.
+ * User defined function:  Kill the defaults and show these.
+ * Wait for a keypress and execute the given function.
+ */
+{
+	int c, def= 1;
+	char *choice= nil;
+	environment *e;
+
+	/* Just a default menu? */
+	for (e= env; e != nil; e= e->next) if (menufun(e) == USERFUN) def= 0;
+
+	printf("\nHit a key as follows:\n\n");
+
+	/* Show the choices. */
+	for (e= env; e != nil; e= e->next) {
+		switch (menufun(e)) {
+		case DEFFUN:
+			if (!def) break;
+			/*FALL THROUGH*/
+		case USERFUN:
+			printf("    %c  %s\n", e->arg[0], e->arg+2);
+			break;
+		case SELECT:
+			printf("    %c  Select %s kernel\n", e->arg[0],e->name);
+			break;
+		default:;
+		}
+	}
+
+	/* Wait for a keypress. */
+	do {
+		c= getch();
+		if (interrupt() || expired()) return;
+
+		unschedule();
+
+		for (e= env; e != nil; e= e->next) {
+			switch (menufun(e)) {
+			case DEFFUN:
+				if (!def) break;
+			case USERFUN:
+			case SELECT:
+				if (c == e->arg[0]) choice= e->value;
+			}
+		}
+	} while (choice == nil);
+
+	/* Execute the chosen function. */
+	printf("%c\n", c);
+	(void) tokenize(&cmds, choice);
+}
+
+void help(void)
+/* Not everyone is a rocket scientist. */
+{
+	struct help {
+		char	*thing;
+		char	*help;
+	} *pi;
+	static struct help info[] = {
+		{ nil,	"Names:" },
+		{ "rootdev",		"Root device" },
+		{ "ramimagedev",	"Device to use as RAM disk image " },
+		{ "ramsize",		"RAM disk size (if no image device) " },
+		{ "bootdev",		"Special name for the boot device" },
+		{ "fd0, d0p2, c0d0p1s0",	"Devices (as in /dev)" },
+		{ "image",		"Name of the boot image to use" },
+		{ "main",		"Startup function" },
+		{ "bootdelay",		"Delay in msec after loading image" },
+		{ nil,	"Commands:" },
+		{ "name = [device] value",  "Set environment variable" },
+		{ "name() { ... }",	    "Define function" },
+		{ "name(key,text) { ... }",
+			"A menu option like: minix(=,Start MINIX) {boot}" },
+		{ "name",		"Call function" },
+		{ "boot [device]",	"Boot Minix or another O.S." },
+		{ "ctty [line]",	"Duplicate to serial line" },
+		{ "delay [msec]",	"Delay (500 msec default)" },
+		{ "echo word ...",	"Display the words" },
+		{ "ls [directory]",	"List contents of directory" },
+		{ "menu",		"Show menu and choose menu option" },
+		{ "save / set",		"Save or show environment" },
+		{ "trap msec command",	"Schedule command " },
+		{ "unset name ...",	"Unset variable or set to default" },
+		{ "exit / off",		"Exit the Monitor / Power off" },
+	};
+
+	for (pi= info; pi < arraylimit(info); pi++) {
+		if (pi->thing != nil) printf("    %-24s- ", pi->thing);
+		printf("%s\n", pi->help);
+	}
+}
+
+void execute(void)
+/* Get one command from the command chain and execute it. */
+{
+	token *second, *third, *fourth, *sep;
+	char *name;
+	int res;
+	size_t n= 0;
+
+	if (err) {
+		/* An error occured, stop interpreting. */
+		while (cmds != nil) voidtoken();
+		return;
+	}
+
+	if (expired()) {	/* Timer expired? */
+		parse_code(Thandler);
+		unschedule();
+	}
+
+	/* There must be a separator lurking somewhere. */
+	for (sep= cmds; sep != nil && sep->token[0] != ';'; sep= sep->next) n++;
+
+	name= cmds->token;
+	res= reserved(name);
+	if ((second= cmds->next) != nil
+		&& (third= second->next) != nil)
+			fourth= third->next;
+
+		/* Null command? */
+	if (n == 0) {
+		voidtoken();
+		return;
+	} else
+		/* name = [device] value? */
+	if ((n == 3 || n == 4)
+		&& !sugar(name)
+		&& second->token[0] == '='
+		&& !sugar(third->token)
+		&& (n == 3 || (n == 4 && third->token[0] == 'd'
+					&& !sugar(fourth->token)
+	))) {
+		char *value= third->token;
+		int flags= E_VAR;
+
+		if (n == 4) { value= fourth->token; flags|= E_DEV; }
+
+		if ((flags= b_setvar(flags, name, value)) != 0) {
+			printf("%s is a %s\n", name,
+				flags & E_RESERVED ? "reserved word" :
+						"special function");
+			err= 1;
+		}
+		while (cmds != sep) voidtoken();
+		return;
+	} else
+		/* name '(arg)' ... ? */
+	if (n >= 3
+		&& !sugar(name)
+		&& second->token[0] == '('
+	) {
+		token *fun;
+		int c, flags, depth;
+		char *body;
+		size_t len;
+
+		sep= fun= third;
+		depth= 0;
+		len= 1;
+		while (sep != nil) {
+			if ((c= sep->token[0]) == ';' && depth == 0) break;
+			len+= strlen(sep->token) + 1;
+			sep= sep->next;
+			if (c == '{') depth++;
+			if (c == '}' && --depth == 0) break;
+		}
+
+		body= malloc(len * sizeof(char));
+		*body= 0;
+
+		while (fun != sep) {
+			strcat(body, fun->token);
+			if (!sugar(fun->token)
+				&& !sugar(fun->next->token)
+			) strcat(body, " ");
+			fun= fun->next;
+		}
+		second->token[strlen(second->token)-1]= 0;
+
+		if (depth != 0) {
+			printf("Missing '}'\n");
+			err= 1;
+		} else
+		if ((flags= b_setenv(E_FUNCTION, name,
+					second->token+1, body)) != 0) {
+			printf("%s is a %s\n", name,
+				flags & E_RESERVED ? "reserved word" :
+						"special variable");
+			err= 1;
+		}
+		while (cmds != sep) voidtoken();
+		free(body);
+		return;
+	} else
+		/* Grouping? */
+	if (name[0] == '{') {
+		token **acmds= &cmds->next;
+		char *t;
+		int depth= 1;
+
+		/* Find and remove matching '}' */
+		depth= 1;
+		while (*acmds != nil) {
+			t= (*acmds)->token;
+			if (t[0] == '{') depth++;
+			if (t[0] == '}' && --depth == 0) { t[0]= ';'; break; }
+			acmds= &(*acmds)->next;
+		}
+		voidtoken();
+		return;
+	} else
+		/* Command coming up, check if ESC typed. */
+	if (interrupt()) {
+		return;
+	} else
+		/* unset name ..., echo word ...? */
+	if (n >= 1 && (res == R_UNSET || res == R_ECHO)) {
+		char *arg= poptoken(), *p;
+
+		for (;;) {
+			free(arg);
+			if (cmds == sep) break;
+			arg= poptoken();
+			if (res == R_UNSET) {	/* unset arg */
+				b_unset(arg);
+			} else {		/* echo arg */
+				p= arg;
+				while (*p != 0) {
+					if (*p != '\\') {
+						putch(*p);
+					} else
+					switch (*++p) {
+					case 0:
+						if (cmds == sep) return;
+						continue;
+					case 'n':
+						putch('\n');
+						break;
+					case 'v':
+						printf(version);
+						break;
+					case 'c':
+						clear_screen();
+						break;
+					case 'w':
+						for (;;) {
+							if (interrupt())
+								return;
+							if (getch() == '\n')
+								break;
+						}
+						break;
+					default:
+						putch(*p);
+					}
+					p++;
+				}
+				putch(cmds != sep ? ' ' : '\n');
+			}
+		}
+		return;
+	} else
+		/* boot -opts? */
+	if (n == 2 && res == R_BOOT && second->token[0] == '-') {
+		static char optsvar[]= "bootopts";
+		(void) b_setvar(E_VAR, optsvar, second->token);
+		voidtoken();
+		voidtoken();
+		bootminix();
+		b_unset(optsvar);
+		return;
+	} else
+		/* boot device, ls dir, delay msec? */
+	if (n == 2 && (res == R_BOOT || res == R_CTTY
+			|| res == R_DELAY || res == R_LS)
+	) {
+		if (res == R_BOOT) boot_device(second->token);
+		if (res == R_CTTY) ctty(second->token);
+		if (res == R_DELAY) delay(second->token);
+		if (res == R_LS) ls(second->token);
+		voidtoken();
+		voidtoken();
+		return;
+	} else
+		/* trap msec command? */
+	if (n == 3 && res == R_TRAP && numeric(second->token)) {
+		long msec= a2l(second->token);
+
+		voidtoken();
+		voidtoken();
+		schedule(msec, poptoken());
+		return;
+	} else
+		/* Simple command. */
+	if (n == 1) {
+		char *body;
+		int ok= 0;
+
+		name= poptoken();
+
+		switch (res) {
+		case R_BOOT:	bootminix();	ok= 1;	break;
+		case R_DELAY:	delay("500");	ok= 1;	break;
+		case R_LS:	ls(null);	ok= 1;	break;
+		case R_MENU:	menu();		ok= 1;	break;
+		case R_SAVE:	save_parameters(); ok= 1;break;
+		case R_SET:	show_env();	ok= 1;	break;
+		case R_HELP:	help();		ok= 1;	break;
+		case R_EXIT:	exit(0);
+		case R_OFF:	off();		ok= 1;	break;
+		}
+
+		/* Command to check bootparams: */
+		if (strcmp(name, ":") == 0) ok= 1;
+
+		/* User defined function. */
+		if (!ok && (body= b_body(name)) != nil) {
+			(void) tokenize(&cmds, body);
+			ok= 1;
+		}
+		if (!ok) printf("%s: unknown function", name);
+		free(name);
+		if (ok) return;
+	} else {
+		/* Syntax error. */
+		printf("Can't parse:");
+		while (cmds != sep) {
+			printf(" %s", cmds->token); voidtoken();
+		}
+	}
+
+	/* Getting here means that the command is not understood. */
+	printf("\nTry 'help'\n");
+	err= 1;
+}
+
+int run_trailer(void)
+/* Run the trailer function between loading Minix and handing control to it.
+ * Return true iff there was no error.
+ */
+{
+	token *save_cmds= cmds;
+
+	cmds= nil;
+	(void) tokenize(&cmds, "trailer");
+	while (cmds != nil) execute();
+	cmds= save_cmds;
+	return !err;
+}
+
+void monitor(void)
+/* Read a line and tokenize it. */
+{
+	char *line;
+
+	unschedule();		/* Kill a trap. */
+	err= 0;			/* Clear error state. */
+
+	if (istty) printf("%s>", bootdev.name);
+	line= readline();
+	(void) tokenize(&cmds, line);
+	free(line);
+	(void) escape();	/* Forget if ESC typed. */
+}
+
+#if BIOS
+
+unsigned char cdspec[25];
+void bootcdinfo(u32_t, int *, int drive);
+
+void boot(void)
+/* Load Minix and start it, among other things. */
+{
+
+	/* Initialize tables. */
+	initialize();
+
+	/* Get environment variables from the parameter sector. */
+	get_parameters();
+
+	while (1) {
+		/* While there are commands, execute them! */
+
+		while (cmds != nil) execute();
+
+		/* The "monitor" is just a "read one command" thing. */
+		monitor();
+	}
+}
+#endif /* BIOS */
+
+#if UNIX
+
+void main(int argc, char **argv)
+/* Do not load or start anything, just edit parameters. */
+{
+	int i;
+	char bootcode[SECTOR_SIZE];
+	struct termios rawterm;
+
+	istty= (argc <= 2 && tcgetattr(0, &termbuf) == 0);
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: edparams device [command ...]\n");
+		exit(1);
+	}
+
+	/* Go over the arguments, changing control characters to spaces. */
+	for (i= 2; i < argc; i++) {
+		char *p;
+
+		for (p= argv[i]; *p != 0; p++) {
+			if ((unsigned) *p < ' ' && *p != '\n') *p= ' ';
+		}
+	}
+
+	bootdev.name= argv[1];
+	if (strncmp(bootdev.name, "/dev/", 5) == 0) bootdev.name+= 5;
+	if ((bootdev.device= open(argv[1], O_RDWR, 0666)) < 0)
+		fatal(bootdev.name);
+
+	/* Check if it is a bootable Minix device. */
+	if (readsectors(mon2abs(bootcode), lowsec, 1) != 0
+		|| memcmp(bootcode, boot_magic, sizeof(boot_magic)) != 0) {
+		fprintf(stderr, "edparams: %s: not a bootable Minix device\n",
+			bootdev.name);
+		exit(1);
+	}
+
+	/* Print greeting message.  */
+	if (istty) printf("Boot parameters editor.\n");
+
+	signal(SIGINT, trap);
+	signal(SIGALRM, trap);
+
+	if (istty) {
+		rawterm= termbuf;
+		rawterm.c_lflag&= ~(ICANON|ECHO|IEXTEN);
+		rawterm.c_cc[VINTR]= ESC;
+		if (tcsetattr(0, TCSANOW, &rawterm) < 0) fatal("");
+	}
+
+	/* Get environment variables from the parameter sector. */
+	get_parameters();
+
+	i= 2;
+	for (;;) {
+		/* While there are commands, execute them! */
+		while (cmds != nil || i < argc) {
+			if (cmds == nil) {
+				/* A command line command. */
+				parse_code(argv[i++]);
+			}
+			execute();
+
+			/* Bail out on errors if not interactive. */
+			if (err && !istty) exit(1);
+		}
+
+		/* Commands on the command line? */
+		if (argc > 2) break;
+
+		/* The "monitor" is just a "read one command" thing. */
+		monitor();
+	}
+	exit(0);
+}
+#endif /* UNIX */
+
+/*
+ * $PchId: boot.c,v 1.14 2002/02/27 19:46:14 philip Exp $
+ */
Index: /trunk/minix/boot/boot.h
===================================================================
--- /trunk/minix/boot/boot.h	(revision 9)
+++ /trunk/minix/boot/boot.h	(revision 9)
@@ -0,0 +1,212 @@
+/*	boot.h - Info between different parts of boot.	Author: Kees J. Bot
+ */
+
+#ifndef DEBUG
+#define DEBUG 0
+#endif
+
+/* Constants describing the metal: */
+
+#define SECTOR_SIZE	512
+#define SECTOR_SHIFT	9
+#define RATIO(b)		((b) / SECTOR_SIZE)
+
+#define PARAMSEC	1	/* Sector containing boot parameters. */
+
+#define DSKBASE		0x1E	/* Floppy disk parameter vector. */
+#define DSKPARSIZE	11	/* There are this many bytes of parameters. */
+
+#define ESC		'\33'	/* Escape key. */
+
+#define HEADERPOS      0x00600L	/* Place for an array of struct exec's. */
+
+#define FREEPOS	       0x08000L	/* Memory from FREEPOS to caddr is free to
+				 * play with.
+				 */
+#if BIOS
+#define MSEC_PER_TICK	  55	/* Clock does 18.2 ticks per second. */
+#define TICKS_PER_DAY 0x1800B0L	/* After 24 hours it wraps. */
+#endif
+
+#if UNIX
+#define MSEC_PER_TICK	1000	/* Clock does 18.2 ticks per second. */
+#define TICKS_PER_DAY  86400L	/* Doesn't wrap, but that doesn't matter. */
+#endif
+
+#define BOOTPOS	       0x07C00L	/* Bootstraps are loaded here. */
+#define SIGNATURE	0xAA55	/* Proper bootstraps have this signature. */
+#define SIGNATOFF	510	/* Offset within bootblock. */
+
+/* BIOS video modes. */
+#define MONO_MODE	0x07	/* 80x25 monochrome. */
+#define COLOR_MODE	0x03	/* 80x25 color. */
+
+
+/* Variables shared with boothead.s: */
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+typedef struct vector {		/* 8086 vector */
+	u16_t	offset;
+	u16_t	segment;
+} vector;
+
+EXTERN vector rem_part;		/* Boot partition table entry. */
+
+EXTERN u32_t caddr, daddr;	/* Code and data address of the boot program. */
+EXTERN u32_t runsize;		/* Size of this program. */
+
+EXTERN u16_t device;		/* Drive being booted from. */
+
+typedef struct {		/* One chunk of free memory. */
+	u32_t	base;		/* Start byte. */
+	u32_t	size;		/* Number of bytes. */
+} memory;
+
+EXTERN memory mem[3];		/* List of available memory. */
+EXTERN int mon_return;		/* Monitor stays in memory? */
+
+typedef struct bios_env
+{
+	u16_t ax;
+	u16_t bx;
+	u16_t cx;
+	u16_t flags;
+} bios_env_t;
+
+#define FL_CARRY	0x0001	/* carry flag */
+
+/* Functions defined by boothead.s: */
+
+void exit(int code);
+			/* Exit the monitor. */
+u32_t mon2abs(void *ptr);
+			/* Local monitor address to absolute address. */
+u32_t vec2abs(vector *vec);
+			/* Vector to absolute address. */
+void raw_copy(u32_t dstaddr, u32_t srcaddr, u32_t count);
+			/* Copy bytes from anywhere to anywhere. */
+u16_t get_word(u32_t addr);
+			/* Get a word from anywhere. */
+void put_word(u32_t addr, U16_t word);
+			/* Put a word anywhere. */
+void relocate(void);
+			/* Switch to a copy of this program. */
+int dev_open(void), dev_close(void);
+			/* Open device and determine params / close device. */
+int dev_boundary(u32_t sector);
+			/* True if sector is on a track boundary. */
+int readsectors(u32_t bufaddr, u32_t sector, U8_t count);
+			/* Read 1 or more sectors from "device". */
+int writesectors(u32_t bufaddr, u32_t sector, U8_t count);
+			/* Write 1 or more sectors to "device". */
+int getch(void);
+			/* Read a keypress. */
+void scan_keyboard(void);	
+			/* Read keypress directly from kb controller. */
+void ungetch(int c);
+			/* Undo a keypress. */
+int escape(void);
+			/* True if escape typed. */
+void putch(int c);
+			/* Send a character to the screen. */
+#if BIOS
+void pause(void);
+			/* Wait for an interrupt. */
+void serial_init(int line);
+#endif			/* Enable copying console I/O to a serial line. */
+
+void set_mode(unsigned mode);
+void clear_screen(void);
+			/* Set video mode / clear the screen. */
+
+u16_t get_bus(void);
+			/* System bus type, XT, AT, or MCA. */
+u16_t get_video(void);
+			/* Display type, MDA to VGA. */
+u32_t get_tick(void);
+			/* Current value of the clock tick counter. */
+
+void bootstrap(int device, struct part_entry *entry);
+			/* Execute a bootstrap routine for a different O.S. */
+void minix(u32_t koff, u32_t kcs, u32_t kds,
+				char *bootparams, size_t paramsize, u32_t aout);
+			/* Start Minix. */
+void int15(bios_env_t *);
+
+
+/* Shared between boot.c and bootimage.c: */
+
+/* Sticky attributes. */
+#define E_SPECIAL	0x01	/* These are known to the program. */
+#define E_DEV		0x02	/* The value is a device name. */
+#define E_RESERVED	0x04	/* May not be set by user, e.g. 'boot' */
+#define E_STICKY	0x07	/* Don't go once set. */
+
+/* Volatile attributes. */
+#define E_VAR		0x08	/* Variable */
+#define E_FUNCTION	0x10	/* Function definition. */
+
+/* Variables, functions, and commands. */
+typedef struct environment {
+	struct environment *next;
+	char	flags;
+	char	*name;		/* name = value */
+	char	*arg;		/* name(arg) {value} */
+	char	*value;
+	char	*defval;	/* Safehouse for default values. */
+} environment;
+
+EXTERN environment *env;	/* Lists the environment. */
+
+char *b_value(char *name);	/* Get/set the value of a variable. */
+int b_setvar(int flags, char *name, char *value);
+
+void parse_code(char *code);	/* Parse boot monitor commands. */
+
+extern int fsok;	/* True if the boot device contains an FS. */
+EXTERN u32_t lowsec;	/* Offset to the file system on the boot device. */
+
+/* Called by boot.c: */
+
+void bootminix(void);		/* Load and start a Minix image. */
+
+
+/* Called by bootimage.c: */
+
+void readerr(off_t sec, int err);
+			/* Report a read error. */
+char *ul2a(u32_t n, unsigned b), *ul2a10(u32_t n);
+			/* Transform u32_t to ASCII at base b or base 10. */
+long a2l(char *a);
+			/* Cheap atol(). */
+unsigned a2x(char *a);
+			/* ASCII to hex. */
+dev_t name2dev(char *name);
+			/* Translate a device name to a device number. */
+int numprefix(char *s, char **ps);
+			/* True for a numeric prefix. */
+int numeric(char *s);
+			/* True for a numeric string. */
+char *unix_err(int err);
+			/* Give a descriptive text for some UNIX errors. */
+int run_trailer(void);
+			/* Run the trailer function. */
+
+#if DOS
+/* The monitor runs under MS-DOS. */
+extern char PSP[256];	/* Program Segment Prefix. */
+EXTERN char *vdisk;	/* Name of the virtual disk. */
+EXTERN char *drun;	/* Initial command from DOS command line. */
+#else
+/* The monitor uses only the BIOS. */
+#define DOS	0
+#endif
+
+void readblock(off_t, char *, int);
+void delay(char *);
+
+/*
+ * $PchId: boot.h,v 1.12 2002/02/27 19:42:45 philip Exp $
+ */
Index: /trunk/minix/boot/bootblock.s
===================================================================
--- /trunk/minix/boot/bootblock.s	(revision 9)
+++ /trunk/minix/boot/bootblock.s	(revision 9)
@@ -0,0 +1,231 @@
+!	Bootblock 1.5 - Minix boot block.		Author: Kees J. Bot
+!					   			21 Dec 1991
+!
+! When the PC is powered on, it will try to read the first sector of floppy
+! disk 0 at address 0x7C00.  If this fails due to the absence of flexible
+! magnetic media, it will read the master boot record from the first sector
+! of the hard disk.  This sector not only contains executable code, but also
+! the partition table of the hard disk.  When executed, it will select the
+! active partition and load the first sector of that at address 0x7C00.
+! This file contains the code that is eventually read from either the floppy
+! disk, or the hard disk partition.  It is just smart enough to load /boot
+! from the boot device into memory at address 0x10000 and execute that.  The
+! disk addresses for /boot are patched into this code by installboot as 24-bit
+! sector numbers and 8-bit sector counts above enddata upwards.  /boot is in
+! turn smart enough to load the different parts of the Minix kernel into
+! memory and execute them to finally get Minix started.
+!
+
+	LOADOFF	   =	0x7C00	! 0x0000:LOADOFF is where this code is loaded
+	BOOTSEG    =	0x1000	! Secondary boot code segment.
+	BOOTOFF	   =	0x0030	! Offset into /boot above header
+	BUFFER	   =	0x0600	! First free memory
+	LOWSEC     =	     8	! Offset of logical first sector in partition
+				! table
+
+	! Variables addressed using bp register
+	device	   =	     0	! The boot device
+	lowsec	   =	     2	! Offset of boot partition within drive
+	secpcyl	   =	     6	! Sectors per cylinder = heads * sectors
+
+.text
+
+! Start boot procedure.
+
+boot:
+	xor	ax, ax		! ax = 0x0000, the vector segment
+	mov	ds, ax
+	cli			! Ignore interrupts while setting stack
+	mov	ss, ax		! ss = ds = vector segment
+	mov	sp, #LOADOFF	! Usual place for a bootstrap stack
+	sti
+
+	push	ax
+	push	ax		! Push a zero lowsec(bp)
+
+	push	dx		! Boot device in dl will be device(bp)
+	mov	bp, sp		! Using var(bp) is one byte cheaper then var.
+
+	push	es
+	push	si		! es:si = partition table entry if hard disk
+
+	mov	di, #LOADOFF+sectors	! char *di = sectors;
+
+	testb	dl, dl		! Winchester disks if dl >= 0x80
+	jge	floppy
+
+winchester:
+
+! Get the offset of the first sector of the boot partition from the partition
+! table.  The table is found at es:si, the lowsec parameter at offset LOWSEC.
+
+	eseg
+	les	ax, LOWSEC(si)	  ! es:ax = LOWSEC+2(si):LOWSEC(si)
+	mov	lowsec+0(bp), ax  ! Low 16 bits of partition's first sector
+	mov	lowsec+2(bp), es  ! High 16 bits of partition's first sector
+
+! Get the drive parameters, the number of sectors is bluntly written into the
+! floppy disk sectors/track array.
+
+	movb	ah, #0x08	! Code for drive parameters
+	int	0x13		! dl still contains drive
+	andb	cl, #0x3F	! cl = max sector number (1-origin)
+	movb	(di), cl	! Number of sectors per track
+	incb	dh		! dh = 1 + max head number (0-origin)
+	jmp	loadboot
+
+! Floppy:
+! Execute three read tests to determine the drive type.  Test for each floppy
+! type by reading the last sector on the first track.  If it fails, try a type
+! that has less sectors.  Therefore we start with 1.44M (18 sectors) then 1.2M
+! (15 sectors) ending with 720K/360K (both 9 sectors).
+
+next:	inc	di		! Next number of sectors per track
+
+floppy:	xorb	ah, ah		! Reset drive
+	int	0x13
+
+	movb	cl, (di)	! cl = number of last sector on track
+
+	cmpb	cl, #9		! No need to do the last 720K/360K test
+	je	success
+
+! Try to read the last sector on track 0
+
+	mov	es, lowsec(bp)	! es = vector segment (lowsec = 0)
+	mov	bx, #BUFFER	! es:bx buffer = 0x0000:0x0600
+	mov	ax, #0x0201	! Read sector, #sectors = 1
+	xorb	ch, ch		! Track 0, last sector
+	xorb	dh, dh		! Drive dl, head 0
+	int	0x13
+	jc	next		! Error, try the next floppy type
+
+success:movb	dh, #2		! Load number of heads for multiply
+
+loadboot:
+! Load /boot from the boot device
+
+	movb	al, (di)	! al = (di) = sectors per track
+	mulb	dh		! dh = heads, ax = heads * sectors
+	mov	secpcyl(bp), ax	! Sectors per cylinder = heads * sectors
+
+	mov	ax, #BOOTSEG	! Segment to load /boot into
+	mov	es, ax
+	xor	bx, bx		! Load first sector at es:bx = BOOTSEG:0x0000
+	mov	si, #LOADOFF+addresses	! Start of the boot code addresses
+load:
+	mov	ax, 1(si)	! Get next sector number: low 16 bits
+	movb	dl, 3(si)	! Bits 16-23 for your up to 8GB partition
+	xorb	dh, dh		! dx:ax = sector within partition
+	add	ax, lowsec+0(bp)
+	adc	dx, lowsec+2(bp)! dx:ax = sector within drive
+	cmp	dx, #[1024*255*63-255]>>16  ! Near 8G limit?
+	jae	bigdisk
+	div	secpcyl(bp)	! ax = cylinder, dx = sector within cylinder
+	xchg	ax, dx		! ax = sector within cylinder, dx = cylinder
+	movb	ch, dl		! ch = low 8 bits of cylinder
+	divb	(di)		! al = head, ah = sector (0-origin)
+	xorb	dl, dl		! About to shift bits 8-9 of cylinder into dl
+	shr	dx, #1
+	shr	dx, #1		! dl[6..7] = high cylinder
+	orb	dl, ah		! dl[0..5] = sector (0-origin)
+	movb	cl, dl		! cl[0..5] = sector, cl[6..7] = high cyl
+	incb	cl		! cl[0..5] = sector (1-origin)
+	movb	dh, al		! dh = al = head
+	movb	dl, device(bp)	! dl = device to read
+	movb	al, (di)	! Sectors per track - Sector number (0-origin)
+	subb	al, ah		! = Sectors left on this track
+	cmpb	al, (si)	! Compare with # sectors to read
+	jbe	read		! Can't read past the end of a cylinder?
+	movb	al, (si)	! (si) < sectors left on this track
+read:	push	ax		! Save al = sectors to read
+	movb	ah, #0x02	! Code for disk read (all registers in use now!)
+	int	0x13		! Call the BIOS for a read
+	pop	cx		! Restore al in cl
+	jmp	rdeval
+bigdisk:
+	movb	cl, (si)	! Number of sectors to read
+	push	si		! Save si
+	mov	si, #LOADOFF+ext_rw ! si = extended read/write parameter packet
+	movb	2(si), cl	! Fill in # blocks to transfer
+	mov	4(si), bx	! Buffer address
+	mov	8(si), ax	! Starting block number = dx:ax
+	mov	10(si), dx
+	movb	dl, device(bp)	! dl = device to read
+	movb	ah, #0x42	! Extended read
+	int	0x13
+	pop	si		! Restore si to point to the addresses array
+	!jmp	rdeval
+rdeval:
+	jc	error		! Jump on disk read error
+	movb	al, cl		! Restore al = sectors read
+	addb	bh, al		! bx += 2 * al * 256 (add bytes read)
+	addb	bh, al		! es:bx = where next sector must be read
+	add	1(si), ax	! Update address by sectors read
+	adcb	3(si), ah	! Don't forget bits 16-23 (add ah = 0)
+	subb	(si), al	! Decrement sector count by sectors read
+	jnz	load		! Not all sectors have been read
+	add	si, #4		! Next (address, count) pair
+	cmpb	ah, (si)	! Done when no sectors to read
+	jnz	load		! Read next chunk of /boot
+
+done:
+
+! Call /boot, assuming a long a.out header (48 bytes).  The a.out header is
+! usually short (32 bytes), but to be sure /boot has two entry points:
+! One at offset 0 for the long, and one at offset 16 for the short header.
+! Parameters passed in registers are:
+!
+!	dl	= Boot-device.
+!	es:si	= Partition table entry if hard disk.
+!
+	pop	si		! Restore es:si = partition table entry
+	pop	es		! dl is still loaded
+	jmpf	BOOTOFF, BOOTSEG  ! jmp to sec. boot (skipping header).
+
+! Read error: print message, hang forever
+error:
+	mov	si, #LOADOFF+errno+1
+prnum:	movb	al, ah		! Error number in ah
+	andb	al, #0x0F	! Low 4 bits
+	cmpb	al, #10		! A-F?
+	jb	digit		! 0-9!
+	addb	al, #7		! 'A' - ':'
+digit:	addb	(si), al	! Modify '0' in string
+	dec	si
+	movb	cl, #4		! Next 4 bits
+	shrb	ah, cl
+	jnz	prnum		! Again if digit > 0
+
+	mov	si, #LOADOFF+rderr  ! String to print
+print:	lodsb			! al = *si++ is char to be printed
+	testb	al, al		! Null byte marks end
+hang:	jz	hang		! Hang forever waiting for CTRL-ALT-DEL
+	movb	ah, #0x0E	! Print character in teletype mode
+	mov	bx, #0x0001	! Page 0, foreground color
+	int	0x10		! Call BIOS VIDEO_IO
+	jmp	print
+
+.data
+rderr:	.ascii	"Read error "
+errno:	.ascii	"00 \0"
+errend:
+
+! Floppy disk sectors per track for the 1.44M, 1.2M and 360K/720K types:
+sectors:
+	.data1	18, 15, 9
+
+! Extended read/write commands require a parameter packet.
+ext_rw:
+	.data1	0x10		! Length of extended r/w packet
+	.data1	0		! Reserved
+	.data2	0		! Blocks to transfer (to be filled in)
+	.data2	0		! Buffer address offset (tbfi)
+	.data2	BOOTSEG		! Buffer address segment
+	.data4	0		! Starting block number low 32 bits (tbfi)
+	.data4	0		! Starting block number high 32 bits
+
+	.align	2
+addresses:
+! The space below this is for disk addresses for a 38K /boot program (worst
+! case, i.e. file is completely fragmented).  It should be enough.
Index: /trunk/minix/boot/boothead.s
===================================================================
--- /trunk/minix/boot/boothead.s	(revision 9)
+++ /trunk/minix/boot/boothead.s	(revision 9)
@@ -0,0 +1,1513 @@
+!	Boothead.s - BIOS support for boot.c		Author: Kees J. Bot
+!
+!
+! This file contains the startup and low level support for the secondary
+! boot program.  It contains functions for disk, tty and keyboard I/O,
+! copying memory to arbitrary locations, etc.
+!
+! The primary bootstrap code supplies the following parameters in registers:
+!	dl	= Boot-device.
+!	es:si	= Partition table entry if hard disk.
+!
+.text
+
+	o32	    =	  0x66	! This assembler doesn't know 386 extensions
+	BOOTOFF	    =	0x7C00	! 0x0000:BOOTOFF load a bootstrap here
+	LOADSEG     =	0x1000	! Where this code is loaded.
+	BUFFER	    =	0x0600	! First free memory
+	PENTRYSIZE  =	    16	! Partition table entry size.
+	a_flags	    =	     2	! From a.out.h, struct exec
+	a_text	    =	     8
+	a_data	    =	    12
+	a_bss	    =	    16
+	a_total	    =	    24
+	A_SEP	    =	  0x20	! Separate I&D flag
+	K_I386	    =	0x0001	! Call Minix in 386 mode
+	K_RET	    =	0x0020	! Returns to the monitor on reboot
+	K_INT86	    =	0x0040	! Requires generic INT support
+	K_MEML	    =	0x0080	! Pass a list of free memory
+
+	DS_SELECTOR =	   3*8	! Kernel data selector
+	ES_SELECTOR =	   4*8	! Flat 4 Gb
+	SS_SELECTOR =	   5*8	! Monitor stack
+	CS_SELECTOR =	   6*8	! Kernel code
+	MCS_SELECTOR=	   7*8	! Monitor code
+
+	ESC	    =	  0x1B	! Escape character
+
+! Imported variables and functions:
+.extern _caddr, _daddr, _runsize, _edata, _end	! Runtime environment
+.extern _device					! BIOS device number
+.extern _rem_part				! To pass partition info
+.extern _k_flags				! Special kernel flags
+.extern _mem					! Free memory list
+
+.text
+
+! Set segment registers and stack pointer using the programs own header!
+! The header is either 32 bytes (short form) or 48 bytes (long form).  The
+! bootblock will jump to address 0x10030 in both cases, calling one of the
+! two jmpf instructions below.
+
+	jmpf	boot, LOADSEG+3	! Set cs right (skipping long a.out header)
+	.space	11		! jmpf + 11 = 16 bytes
+	jmpf	boot, LOADSEG+2	! Set cs right (skipping short a.out header)
+boot:
+	mov	ax, #LOADSEG
+	mov	ds, ax		! ds = header
+
+	movb	al, a_flags
+	testb	al, #A_SEP	! Separate I&D?
+	jnz	sepID
+comID:	xor	ax, ax
+	xchg	ax, a_text	! No text
+	add	a_data, ax	! Treat all text as data
+sepID:
+	mov	ax, a_total	! Total nontext memory usage
+	and	ax, #0xFFFE	! Round down to even
+	mov	a_total, ax	! total - text = data + bss + heap + stack
+	cli			! Ignore interrupts while stack in limbo
+	mov	sp, ax		! Set sp at the top of all that
+
+	mov	ax, a_text	! Determine offset of ds above cs
+	movb	cl, #4
+	shr	ax, cl
+	mov	cx, cs
+	add	ax, cx
+	mov	ds, ax		! ds = cs + text / 16
+	mov	ss, ax
+	sti			! Stack ok now
+	push	es		! Save es, we need it for the partition table
+	mov	es, ax
+	cld			! C compiler wants UP
+
+! Clear bss
+	xor	ax, ax		! Zero
+	mov	di, #_edata	! Start of bss is at end of data
+	mov	cx, #_end	! End of bss (begin of heap)
+	sub	cx, di		! Number of bss bytes
+	shr	cx, #1		! Number of words
+	rep
+	stos			! Clear bss
+
+! Copy primary boot parameters to variables.  (Can do this now that bss is
+! cleared and may be written into).
+	xorb	dh, dh
+	mov	_device, dx	! Boot device (probably 0x00 or 0x80)
+	mov	_rem_part+0, si	! Remote partition table offset
+	pop	_rem_part+2	! and segment (saved es)
+
+! Remember the current video mode for restoration on exit.
+	movb	ah, #0x0F	! Get current video mode
+	int	0x10
+	andb	al, #0x7F	! Mask off bit 7 (no blanking)
+	movb	old_vid_mode, al
+	movb	cur_vid_mode, al
+
+! Give C code access to the code segment, data segment and the size of this
+! process.
+	xor	ax, ax
+	mov	dx, cs
+	call	seg2abs
+	mov	_caddr+0, ax
+	mov	_caddr+2, dx
+	xor	ax, ax
+	mov	dx, ds
+	call	seg2abs
+	mov	_daddr+0, ax
+	mov	_daddr+2, dx
+	push	ds
+	mov	ax, #LOADSEG
+	mov	ds, ax		! Back to the header once more
+	mov	ax, a_total+0
+	mov	dx, a_total+2	! dx:ax = data + bss + heap + stack
+	add	ax, a_text+0
+	adc	dx, a_text+2	! dx:ax = text + data + bss + heap + stack
+	pop	ds
+	mov	_runsize+0, ax
+	mov	_runsize+2, dx	! 32 bit size of this process
+
+! Determine available memory as a list of (base,size) pairs as follows:
+! mem[0] = low memory, mem[1] = memory between 1M and 16M, mem[2] = memory
+! above 16M.  Last two coalesced into mem[1] if adjacent.
+	mov	di, #_mem	! di = memory list
+	int	0x12		! Returns low memory size (in K) in ax
+	mul	c1024
+	mov	4(di), ax	! mem[0].size = low memory size in bytes
+	mov	6(di), dx
+	call	_getprocessor
+	cmp	ax, #286	! Only 286s and above have extended memory
+	jb	no_ext
+	cmp	ax, #486	! Assume 486s were the first to have >64M
+	jb	small_ext	! (It helps to be paranoid when using the BIOS)
+big_ext:
+	mov	ax, #0xE801	! Code for get memory size for >64M
+	int	0x15		! ax = mem at 1M per 1K, bx = mem at 16M per 64K
+	jnc	got_ext
+small_ext:
+	movb	ah, #0x88	! Code for get extended memory size
+	clc			! Carry will stay clear if call exists
+	int	0x15		! Returns size (in K) in ax for AT's
+	jc	no_ext
+	test	ax, ax		! An AT with no extended memory?
+	jz	no_ext
+	xor	bx, bx		! bx = mem above 16M per 64K = 0
+got_ext:
+	mov	cx, ax		! cx = copy of ext mem at 1M
+	mov	10(di), #0x0010	! mem[1].base = 0x00100000 (1M)
+	mul	c1024
+	mov	12(di), ax	! mem[1].size = "ext mem at 1M" * 1024
+	mov	14(di), dx
+	test	bx, bx
+	jz	no_ext		! No more ext mem above 16M?
+	cmp	cx, #15*1024	! Chunks adjacent? (precisely 15M at 1M?)
+	je	adj_ext
+	mov	18(di), #0x0100	! mem[2].base = 0x01000000 (16M)
+	mov	22(di), bx	! mem[2].size = "ext mem at 16M" * 64K
+	jmp	no_ext
+adj_ext:
+	add	14(di), bx	! Add ext mem above 16M to mem below 16M
+no_ext:
+
+
+! Time to switch to a higher level language (not much higher)
+	call	_boot
+
+! void ..exit(int status)
+!	Exit the monitor by rebooting the system.
+.define	_exit, __exit, ___exit		! Make various compilers happy
+_exit:
+__exit:
+___exit:
+	mov	bx, sp
+	cmp	2(bx), #0		! Good exit status?
+	jz	reboot
+quit:	mov	ax, #any_key
+	push	ax
+	call	_printf
+	xorb	ah, ah			! Read character from keyboard
+	int	0x16
+reboot:	call	dev_reset
+	call	restore_video
+	int	0x19			! Reboot the system
+.data
+any_key:
+	.ascii	"\nHit any key to reboot\n\0"
+.text
+
+! u32_t mon2abs(void *ptr)
+!	Address in monitor data to absolute address.
+.define _mon2abs
+_mon2abs:
+	mov	bx, sp
+	mov	ax, 2(bx)	! ptr
+	mov	dx, ds		! Monitor data segment
+	jmp	seg2abs
+
+! u32_t vec2abs(vector *vec)
+!	8086 interrupt vector to absolute address.
+.define _vec2abs
+_vec2abs:
+	mov	bx, sp
+	mov	bx, 2(bx)
+	mov	ax, (bx)
+	mov	dx, 2(bx)	! dx:ax vector
+	!jmp	seg2abs		! Translate
+
+seg2abs:			! Translate dx:ax to the 32 bit address dx-ax
+	push	cx
+	movb	ch, dh
+	movb	cl, #4
+	shl	dx, cl
+	shrb	ch, cl		! ch-dx = dx << 4
+	add	ax, dx
+	adcb	ch, #0		! ch-ax = ch-dx + ax
+	movb	dl, ch
+	xorb	dh, dh		! dx-ax = ch-ax
+	pop	cx
+	ret
+
+abs2seg:			! Translate the 32 bit address dx-ax to dx:ax
+	push	cx
+	movb	ch, dl
+	mov	dx, ax		! ch-dx = dx-ax
+	and	ax, #0x000F	! Offset in ax
+	movb	cl, #4
+	shr	dx, cl
+	shlb	ch, cl
+	orb	dh, ch		! dx = ch-dx >> 4
+	pop	cx
+	ret
+
+! void raw_copy(u32_t dstaddr, u32_t srcaddr, u32_t count)
+!	Copy count bytes from srcaddr to dstaddr.  Don't do overlaps.
+!	Also handles copying words to or from extended memory.
+.define _raw_copy
+_raw_copy:
+	push	bp
+	mov	bp, sp
+	push	si
+	push	di		! Save C variable registers
+copy:
+	cmp	14(bp), #0
+	jnz	bigcopy
+	mov	cx, 12(bp)
+	jcxz	copydone	! Count is zero, end copy
+	cmp	cx, #0xFFF0
+	jb	smallcopy
+bigcopy:mov	cx, #0xFFF0	! Don't copy more than about 64K at once
+smallcopy:
+	push	cx		! Save copying count
+	mov	ax, 4(bp)
+	mov	dx, 6(bp)
+	cmp	dx, #0x0010	! Copy to extended memory?
+	jae	ext_copy
+	cmp	10(bp), #0x0010	! Copy from extended memory?
+	jae	ext_copy
+	call	abs2seg
+	mov	di, ax
+	mov	es, dx		! es:di = dstaddr
+	mov	ax, 8(bp)
+	mov	dx, 10(bp)
+	call	abs2seg
+	mov	si, ax
+	mov	ds, dx		! ds:si = srcaddr
+	shr	cx, #1		! Words to move
+	rep
+	movs			! Do the word copy
+	adc	cx, cx		! One more byte?
+	rep
+	movsb			! Do the byte copy
+	mov	ax, ss		! Restore ds and es from the remaining ss
+	mov	ds, ax
+	mov	es, ax
+	jmp	copyadjust
+ext_copy:
+	mov	x_dst_desc+2, ax
+	movb	x_dst_desc+4, dl ! Set base of destination segment
+	mov	ax, 8(bp)
+	mov	dx, 10(bp)
+	mov	x_src_desc+2, ax
+	movb	x_src_desc+4, dl ! Set base of source segment
+	mov	si, #x_gdt	! es:si = global descriptor table
+	shr	cx, #1		! Words to move
+	movb	ah, #0x87	! Code for extended memory move
+	int	0x15
+copyadjust:
+	pop	cx		! Restore count
+	add	4(bp), cx
+	adc	6(bp), #0	! srcaddr += copycount
+	add	8(bp), cx
+	adc	10(bp), #0	! dstaddr += copycount
+	sub	12(bp), cx
+	sbb	14(bp), #0	! count -= copycount
+	jmp	copy		! and repeat
+copydone:
+	pop	di
+	pop	si		! Restore C variable registers
+	pop	bp
+	ret
+
+! u16_t get_word(u32_t addr);
+! void put_word(u32_t addr, u16_t word);
+!	Read or write a 16 bits word at an arbitrary location.
+.define	_get_word, _put_word
+_get_word:
+	mov	bx, sp
+	call	gp_getaddr
+	mov	ax, (bx)	! Word to get from addr
+	jmp	gp_ret
+_put_word:
+	mov	bx, sp
+	push	6(bx)		! Word to store at addr
+	call	gp_getaddr
+	pop	(bx)		! Store the word
+	jmp	gp_ret
+gp_getaddr:
+	mov	ax, 2(bx)
+	mov	dx, 4(bx)
+	call	abs2seg
+	mov	bx, ax
+	mov	ds, dx		! ds:bx = addr
+	ret
+gp_ret:
+	push	es
+	pop	ds		! Restore ds
+	ret
+
+! void relocate(void);
+!	After the program has copied itself to a safer place, it needs to change
+!	the segment registers.  Caddr has already been set to the new location.
+.define _relocate
+_relocate:
+	pop	bx		! Return address
+	mov	ax, _caddr+0
+	mov	dx, _caddr+2
+	call	abs2seg
+	mov	cx, dx		! cx = new code segment
+	mov	ax, cs		! Old code segment
+	sub	ax, cx		! ax = -(new - old) = -Moving offset
+	mov	dx, ds
+	sub	dx, ax
+	mov	ds, dx		! ds += (new - old)
+	mov	es, dx
+	mov	ss, dx
+	xor	ax, ax
+	call	seg2abs
+	mov	_daddr+0, ax
+	mov	_daddr+2, dx	! New data address
+	push	cx		! New text segment
+	push	bx		! Return offset of this function
+	retf			! Relocate
+
+! void *brk(void *addr)
+! void *sbrk(size_t incr)
+!	Cannot fail implementations of brk(2) and sbrk(3), so we can use
+!	malloc(3).  They reboot on stack collision instead of returning -1.
+.data
+	.align	2
+break:	.data2	_end		! A fake heap pointer
+.text
+.define _brk, __brk, _sbrk, __sbrk
+_brk:
+__brk:				! __brk is for the standard C compiler
+	xor	ax, ax
+	jmp	sbrk		! break= 0; return sbrk(addr);
+_sbrk:
+__sbrk:
+	mov	ax, break	! ax= current break
+sbrk:	push	ax		! save it as future return value
+	mov	bx, sp		! Stack is now: (retval, retaddr, incr, ...)
+	add	ax, 4(bx)	! ax= break + increment
+	mov	break, ax	! Set new break
+	lea	dx, -1024(bx)	! sp minus a bit of breathing space
+	cmp	dx, ax		! Compare with the new break
+	jb	heaperr		! Suffocating noises
+	lea	dx, -4096(bx)	! A warning when heap+stack goes < 4K
+	cmp	dx, ax
+	jae	plenty		! No reason to complain
+	mov	ax, #memwarn
+	push	ax
+	call	_printf		! Warn about memory running low
+	pop	ax
+	movb	memwarn, #0	! No more warnings
+plenty:	pop	ax		! Return old break (0 for brk)
+	ret
+heaperr:mov	ax, #chmem
+	push	ax
+	mov	ax, #nomem
+	push	ax
+	call	_printf
+	jmp	quit
+.data
+nomem:	.ascii	"\nOut of%s\0"
+memwarn:.ascii	"\nLow on"
+chmem:	.ascii	" memory, use chmem to increase the heap\n\0"
+.text
+
+! int dev_open(void);
+!	Given the device "_device" figure out if it exists and what its number
+!	of heads and sectors may be.  Return the BIOS error code on error,
+!	otherwise 0.
+.define	_dev_open
+_dev_open:
+	call	dev_reset	! Optionally reset the disks
+	movb	dev_state, #0	! State is "closed"
+	push	es
+	push	di		! Save registers used by BIOS calls
+	movb	dl, _device	! The default device
+	cmpb	dl, #0x80	! Floppy < 0x80, winchester >= 0x80
+	jae	winchester
+floppy:
+	mov	di, #3		! Three tries to init drive by reading sector 0
+finit0:	xor	ax, ax
+	mov	es, ax
+	mov	bx, #BUFFER	! es:bx = scratch buffer
+	mov	ax, #0x0201	! Read sector, #sectors = 1
+	mov	cx, #0x0001	! Track 0, first sector
+	xorb	dh, dh		! Drive dl, head 0
+	int	0x13
+	jnc	finit0ok	! Sector 0 read ok?
+	cmpb	ah, #0x80	! Disk timed out?  (Floppy drive empty)
+	je	geoerr
+	dec	di
+	jz	geoerr
+	xorb	ah, ah		! Reset drive
+	int	0x13
+	jc	geoerr
+	jmp	finit0		! Retry once more, it may need to spin up
+finit0ok:
+	mov	di, #seclist	! List of per floppy type sectors/track
+flast:	movb	cl, (di)	! Sectors per track to test
+	cmpb	cl, #9		! No need to do the last 720K/360K test
+	je	ftestok
+	xor	ax, ax
+	mov	es, ax
+	mov	bx, #BUFFER	! es:bx = scratch buffer
+	mov	ax, #0x0201	! Read sector, #sectors = 1
+	xorb	ch, ch		! Track 0, last sector
+	xorb	dh, dh		! Drive dl, head 0
+	int	0x13
+	jnc	ftestok		! Sector cl read ok?
+	xorb	ah, ah		! Reset drive
+	int	0x13
+	jc	geoerr
+	inc	di		! Try next sec/track number
+	jmp	flast
+ftestok:
+	movb	dh, #2		! Floppies have two sides
+	jmp	geoboth
+winchester:
+	movb	ah, #0x08	! Code for drive parameters
+	int	0x13		! dl still contains drive
+	jc	geoerr		! No such drive?
+	andb	cl, #0x3F	! cl = max sector number (1-origin)
+	incb	dh		! dh = 1 + max head number (0-origin)
+geoboth:
+	movb	sectors, cl	! Sectors per track
+	movb	al, cl		! al = sectors per track
+	mulb	dh		! ax = heads * sectors
+	mov	secspcyl, ax	! Sectors per cylinder = heads * sectors
+	movb	dev_state, #1	! Device state is "open"
+	xor	ax, ax		! Code for success
+geodone:
+	pop	di
+	pop	es		! Restore di and es registers
+	ret
+geoerr:	movb	al, ah
+	xorb	ah, ah		! ax = BIOS error code
+	jmp	geodone
+.data
+seclist:
+	.data1	18, 15, 9	! 1.44M, 1.2M, and 360K/720K floppy sec/track
+.text
+
+! int dev_close(void);
+!	Close the current device.  Under the BIOS this does nothing much.
+.define	_dev_close
+_dev_close:
+	xor	ax, ax
+	movb	dev_state, al	! State is "closed"
+	ret
+
+! Reset the disks if needed.  Minix may have messed things up.
+dev_reset:
+	cmpb	dev_state, #0	! Need reset if dev_state < 0
+	jge	0f
+	xorb	ah, ah		! Reset (ah = 0)
+	movb	dl, #0x80	! All disks
+	int	0x13
+	movb	dev_state, #0	! State is "closed"
+0:	ret
+
+! int dev_boundary(u32_t sector);
+!	True if a sector is on a boundary, i.e. sector % sectors == 0.
+.define	_dev_boundary
+_dev_boundary:
+	mov	bx, sp
+	xor	dx, dx
+	mov	ax, 4(bx)	! divide high half of sector number
+	div	sectors
+	mov	ax, 2(bx)	! divide low half of sector number
+	div	sectors		! dx = sector % sectors
+	sub	dx, #1		! CF = dx == 0
+	sbb	ax, ax		! ax = -CF
+	neg	ax		! ax = (sector % sectors) == 0
+	ret
+
+! int readsectors(u32_t bufaddr, u32_t sector, u8_t count)
+! int writesectors(u32_t bufaddr, u32_t sector, u8_t count)
+!	Read/write several sectors from/to disk or floppy.  The buffer must
+!	be between 64K boundaries!  Count must fit in a byte.  The external
+!	variables _device, sectors and secspcyl describe the disk and its
+!	geometry.  Returns 0 for success, otherwise the BIOS error code.
+!
+.define _readsectors, _writesectors
+_writesectors:
+	push	bp
+	mov	bp, sp
+	movb	13(bp), #0x03	! Code for a disk write
+	jmp	rwsec
+_readsectors:
+	push	bp
+	mov	bp, sp
+	movb	13(bp), #0x02	! Code for a disk read
+rwsec:	push	si
+	push	di
+	push	es
+	cmpb	dev_state, #0	! Device state?
+	jg	0f		! >0 if open
+	call	_dev_open	! Initialize
+	test	ax, ax
+	jnz	badopen
+0:	mov	ax, 4(bp)
+	mov	dx, 6(bp)
+	call	abs2seg
+	mov	bx, ax
+	mov	es, dx		! es:bx = bufaddr
+	mov	di, #3		! Execute 3 resets on floppy error
+	cmpb	_device, #0x80
+	jb	nohd
+	mov	di, #1		! But only 1 reset on hard disk error
+nohd:	cmpb	12(bp), #0	! count equals zero?
+	jz	done
+more:	mov	ax, 8(bp)
+	mov	dx, 10(bp)	! dx:ax = abs sector.  Divide it by sectors/cyl
+	cmp	dx, #[1024*255*63-255]>>16  ! Near 8G limit?
+	jae	bigdisk
+	div	secspcyl	! ax = cylinder, dx = sector within cylinder
+	xchg	ax, dx		! ax = sector within cylinder, dx = cylinder
+	movb	ch, dl		! ch = low 8 bits of cylinder
+	divb	sectors		! al = head, ah = sector (0-origin)
+	xorb	dl, dl		! About to shift bits 8-9 of cylinder into dl
+	shr	dx, #1
+	shr	dx, #1		! dl[6..7] = high cylinder
+	orb	dl, ah		! dl[0..5] = sector (0-origin)
+	movb	cl, dl		! cl[0..5] = sector, cl[6..7] = high cyl
+	incb	cl		! cl[0..5] = sector (1-origin)
+	movb	dh, al		! dh = head
+	movb	dl, _device	! dl = device to use
+	movb	al, sectors	! Sectors per track - Sector number (0-origin)
+	subb	al, ah		! = Sectors left on this track
+	cmpb	al, 12(bp)	! Compare with # sectors to transfer
+	jbe	doit		! Can't go past the end of a cylinder?
+	movb	al, 12(bp)	! 12(bp) < sectors left on this track
+doit:	movb	ah, 13(bp)	! Code for disk read (0x02) or write (0x03)
+	push	ax		! Save al = sectors to read
+	int	0x13		! call the BIOS to do the transfer
+	pop	cx		! Restore al in cl
+	jmp	rdeval
+bigdisk:
+	mov	si, #ext_rw	! si = extended read/write parameter packet
+	movb	cl, 12(bp)
+	movb	2(si), cl	! Fill in # blocks to transfer
+	mov	4(si), bx	! Buffer address = es:bx
+	mov	6(si), es
+	mov	8(si), ax	! Starting block number = dx:ax
+	mov	10(si), dx
+	movb	dl, _device	! dl = device to use
+	mov	ax, #0x4000	! This, or-ed with 0x02 or 0x03 becomes
+	orb	ah, 13(bp)	! extended read (0x4200) or write (0x4300)
+	int	0x13
+	!jmp	rdeval
+rdeval:
+	jc	ioerr		! I/O error
+	movb	al, cl		! Restore al = sectors read
+	addb	bh, al		! bx += 2 * al * 256 (add bytes transferred)
+	addb	bh, al		! es:bx = where next sector is located
+	add	8(bp), ax	! Update address by sectors transferred
+	adc	10(bp), #0	! Don't forget high word
+	subb	12(bp), al	! Decrement sector count by sectors transferred
+	jnz	more		! Not all sectors have been transferred
+done:	xorb	ah, ah		! No error here!
+	jmp	finish
+ioerr:	cmpb	ah, #0x80	! Disk timed out?  (Floppy drive empty)
+	je	finish
+	cmpb	ah, #0x03	! Disk write protected?
+	je	finish
+	dec	di		! Do we allow another reset?
+	jl	finish		! No, report the error
+	xorb	ah, ah		! Code for a reset (0)
+	int	0x13
+	jnc	more		! Succesful reset, try request again
+finish:	movb	al, ah
+	xorb	ah, ah		! ax = error number
+badopen:pop	es
+	pop	di
+	pop	si
+	pop	bp
+	ret
+.data
+	.align	4
+! Extended read/write commands require a parameter packet.
+ext_rw:
+	.data1	0x10		! Length of extended r/w packet
+	.data1	0		! Reserved
+	.data2	0		! Blocks to transfer (to be filled in)
+	.data2	0		! Buffer address offset (tbfi)
+	.data2	0		! Buffer address segment (tbfi)
+	.data4	0		! Starting block number low 32 bits (tbfi)
+	.data4	0		! Starting block number high 32 bits
+.text
+
+! int getch(void);
+!	Read a character from the keyboard, and check for an expired timer.
+!	A carriage return is changed into a linefeed for UNIX compatibility.
+.define _getch
+_getch:
+	xor	ax, ax
+	xchg	ax, unchar	! Ungotten character?
+	test	ax, ax
+	jnz	gotch
+getch:
+	hlt			! Play dead until interrupted (see pause())
+	movb	ah, #0x01	! Keyboard status
+	int	0x16
+	jz	0f		! Nothing typed
+	xorb	ah, ah		! Read character from keyboard
+	int	0x16
+	jmp	press		! Keypress
+0:	mov	dx, line	! Serial line?
+	test	dx, dx
+	jz	0f
+	add	dx, #5		! Line Status Register
+	inb	dx
+	testb	al, #0x01	! Data Ready?
+	jz	0f
+	mov	dx, line
+	!add	dx, 0		! Receive Buffer Register
+	inb	dx		! Get character
+	jmp	press
+0:	call	_expired	! Timer expired?
+	test	ax, ax
+	jz	getch
+	mov	ax, #ESC	! Return ESC
+	ret
+press:
+	cmpb	al, #0x0D	! Carriage return?
+	jnz	nocr
+	movb	al, #0x0A	! Change to linefeed
+nocr:	cmpb	al, #ESC	! Escape typed?
+	jne	noesc
+	inc	escape		! Set flag
+noesc:	xorb	ah, ah		! ax = al
+gotch:	ret
+
+! int ungetch(void);
+!	Return a character to undo a getch().
+.define _ungetch
+_ungetch:
+	mov	bx, sp
+	mov	ax, 2(bx)
+	mov	unchar, ax
+	ret
+
+! int escape(void);
+!	True if ESC has been typed.
+.define _escape
+_escape:
+	movb	ah, #0x01	! Keyboard status
+	int	0x16
+	jz	escflg		! Keypress?
+	cmpb	al, #ESC	! Escape typed?
+	jne	escflg
+	xorb	ah, ah		! Discard the escape
+	int	0x16
+	inc	escape		! Set flag
+escflg:	xor	ax, ax
+	xchg	ax, escape	! Escape typed flag
+	ret
+
+! int putch(int c);
+!	Write a character in teletype mode.  The putk synonym is
+!	for the kernel printf function that uses it.
+!	Newlines are automatically preceded by a carriage return.
+!
+.define _putch, _putk
+_putch:
+_putk:	mov	bx, sp
+	movb	al, 2(bx)	! al = character to be printed
+	testb	al, al		! Kernel printf adds a null char to flush queue
+	jz	nulch
+	cmpb	al, #0x0A	! al = newline?
+	jnz	putc
+	movb	al, #0x0D
+	call	putc		! putc('\r')
+	movb	al, #0x0A	! Restore the '\n' and print it
+putc:	movb	ah, #0x0E	! Print character in teletype mode
+	mov	bx, #0x0001	! Page 0, foreground color
+	int	0x10
+	mov	bx, line	! Serial line?
+	test	bx, bx
+	jz	nulch
+	push	ax		! Save character to print
+	call	_get_tick	! Current clock tick counter
+	mov	cx, ax
+	add	cx, #2		! Don't want to see it count twice
+1:	lea	dx, 5(bx)	! Line Status Register
+	inb	dx
+	testb	al, #0x20	! Transmitter Holding Register Empty?
+	jnz	0f
+	call	_get_tick
+	cmp	ax, cx		! Clock ticked more than once?
+	jne	1b
+0:	pop	ax		! Restore character to print
+	mov	dx, bx		! Transmit Holding Register
+	outb	dx		! Send character down the serial line
+nulch:	ret
+
+! void pause(void);
+!	Wait for an interrupt using the HLT instruction.  This either saves
+!	power, or tells an x86 emulator that nothing is happening right now.
+.define _pause
+_pause:
+	hlt
+	ret
+
+! void set_mode(unsigned mode);
+! void clear_screen(void);
+!	Set video mode / clear the screen.
+.define _set_mode, _clear_screen
+_set_mode:
+	mov	bx, sp
+	mov	ax, 2(bx)	! Video mode
+	cmp	ax, cur_vid_mode
+	je	modeok		! Mode already as requested?
+	mov	cur_vid_mode, ax
+_clear_screen:
+	xor	ax, ax
+	mov	es, ax		! es = Vector segment
+	mov	ax, cur_vid_mode
+	movb	ch, ah		! Copy of the special flags
+	andb	ah, #0x0F	! Test bits 8-11, clear special flags
+	jnz	xvesa		! VESA extended mode?
+	int	0x10		! Reset video (ah = 0)
+	jmp	md_480
+xvesa:	mov	bx, ax		! bx = extended mode
+	mov	ax, #0x4F02	! Reset video
+	int	0x10
+md_480:				! Basic video mode is set, now build on it
+	testb	ch, #0x20	! 480 scan lines requested?
+	jz	md_14pt
+	mov	dx, #0x3CC	! Get CRTC port
+	inb	dx
+	movb	dl, #0xD4
+	testb	al, #1		! Mono or color?
+	jnz	0f
+	movb	dl, #0xB4
+0:	mov	ax, #0x110C	! Vertical sync end (also unlocks CR0-7)
+	call	out2
+	mov	ax, #0x060B	! Vertical total
+	call	out2
+	mov	ax, #0x073E	! (Vertical) overflow
+	call	out2
+	mov	ax, #0x10EA	! Vertical sync start
+	call	out2
+	mov	ax, #0x12DF	! Vertical display end
+	call	out2
+	mov	ax, #0x15E7	! Vertical blank start
+	call	out2
+	mov	ax, #0x1604	! Vertical blank end
+	call	out2
+	push	dx
+	movb	dl, #0xCC	! Misc output register (read)
+	inb	dx
+	movb	dl, #0xC2	! (write)
+	andb	al, #0x0D	! Preserve clock select bits and color bit
+	orb	al, #0xE2	! Set correct sync polarity
+	outb	dx
+	pop	dx		! Index register still in dx
+md_14pt:
+	testb	ch, #0x40	! 9x14 point font requested?
+	jz	md_8pt
+	mov	ax, #0x1111	! Load ROM 9 by 14 font
+	xorb	bl, bl		! Load block 0
+	int	0x10
+	testb	ch, #0x20	! 480 scan lines?
+	jz	md_8pt
+	mov	ax, #0x12DB	! VGA vertical display end
+	call	out2
+   eseg	movb	0x0484, #33	! Tell BIOS the last line number
+md_8pt:
+	testb	ch, #0x80	! 8x8 point font requested?
+	jz	setcur
+	mov	ax, #0x1112	! Load ROM 8 by 8 font
+	xorb	bl, bl		! Load block 0
+	int	0x10
+	testb	ch, #0x20	! 480 scan lines?
+	jz	setcur
+	mov	ax, #0x12DF	! VGA vertical display end
+	call	out2
+   eseg	movb	0x0484, #59	! Tell BIOS the last line number
+setcur:
+	xor	dx, dx		! dl = column = 0, dh = row = 0
+	xorb	bh, bh		! Page 0
+	movb	ah, #0x02	! Set cursor position
+	int	0x10
+	push	ss
+	pop	es		! Restore es
+modeok:	ret
+
+! Out to the usual [index, data] port pair that are common for VGA devices
+! dx = port, ah = index, al = data.
+out2:
+	push	dx
+	push	ax
+	movb	al, ah
+	outb	dx		! Set index
+	inc	dx
+	pop	ax
+	outb	dx		! Send data
+	pop	dx
+	ret
+
+restore_video:			! To restore the video mode on exit
+	mov	ax, old_vid_mode
+	push	ax
+	call	_set_mode
+	pop	ax
+	ret
+
+! void serial_init(int line)
+!	Initialize copying console I/O to a serial line.
+.define	_serial_init
+_serial_init:
+	mov	bx, sp
+	mov	dx, 2(bx)	! Line number
+	push	ds
+	xor	ax, ax
+	mov	ds, ax		! Vector and BIOS data segment
+	mov	bx, dx		! Line number
+	shl	bx, #1		! Word offset
+	mov	bx, 0x0400(bx)	! I/O port for the given line
+	pop	ds
+	mov	line, bx	! Remember I/O port
+serial_init:
+	mov	bx, line
+	test	bx, bx		! I/O port must be nonzero
+	jz	0f
+	mov	ax, #0x00E3	! 9600 N-8-1
+	int	0x14		! Initialize serial line dx
+	lea	dx, 4(bx)	! Modem Control Register
+	movb	al, #0x0B	! DTR, RTS, OUT2
+	outb	dx
+0:	ret
+
+! u32_t get_tick(void);
+!	Return the current value of the clock tick counter.  This counter
+!	increments 18.2 times per second.  Poll it to do delays.  Does not
+!	work on the original PC, but works on the PC/XT.
+.define _get_tick
+_get_tick:
+	push	cx
+	xorb	ah, ah		! Code for get tick count
+	int	0x1A
+	mov	ax, dx
+	mov	dx, cx		! dx:ax = cx:dx = tick count
+	pop	cx
+	ret
+
+
+! Functions used to obtain info about the hardware.  Boot uses this information
+! itself, but will also pass them on to a pure 386 kernel, because one can't
+! make BIOS calls from protected mode.  The video type could probably be
+! determined by the kernel too by looking at the hardware, but there is a small
+! chance on errors that the monitor allows you to correct by setting variables.
+
+.define _get_bus		! returns type of system bus
+.define _get_video		! returns type of display
+
+! u16_t get_bus(void)
+!	Return type of system bus, in order: XT, AT, MCA.
+_get_bus:
+	call	_getprocessor
+	xor	dx, dx		! Assume XT
+	cmp	ax, #286	! An AT has at least a 286
+	jb	got_bus
+	inc	dx		! Assume AT
+	movb	ah, #0xC0	! Code for get configuration
+	int	0x15
+	jc	got_bus		! Carry clear and ah = 00 if supported
+	testb	ah, ah
+	jne	got_bus
+	eseg
+	movb	al, 5(bx)	! Load feature byte #1
+	inc	dx		! Assume MCA
+	testb	al, #0x02	! Test bit 1 - "bus is Micro Channel"
+	jnz	got_bus
+	dec	dx		! Assume AT
+	testb	al, #0x40	! Test bit 6 - "2nd 8259 installed"
+	jnz	got_bus
+	dec	dx		! It is an XT
+got_bus:
+	push	ds
+	pop	es		! Restore es
+	mov	ax, dx		! Return bus code
+	mov	bus, ax		! Keep bus code, A20 handler likes to know
+	ret
+
+! u16_t get_video(void)
+!	Return type of display, in order: MDA, CGA, mono EGA, color EGA,
+!	mono VGA, color VGA.
+_get_video:
+	mov	ax, #0x1A00	! Function 1A returns display code
+	int	0x10		! al = 1A if supported
+	cmpb	al, #0x1A
+	jnz	no_dc		! No display code function supported
+
+	mov	ax, #2
+	cmpb	bl, #5		! Is it a monochrome EGA?
+	jz	got_video
+	inc	ax
+	cmpb	bl, #4		! Is it a color EGA?
+	jz	got_video
+	inc	ax
+	cmpb	bl, #7		! Is it a monochrome VGA?
+	jz	got_video
+	inc	ax
+	cmpb	bl, #8		! Is it a color VGA?
+	jz	got_video
+
+no_dc:	movb	ah, #0x12	! Get information about the EGA
+	movb	bl, #0x10
+	int	0x10
+	cmpb	bl, #0x10	! Did it come back as 0x10? (No EGA)
+	jz	no_ega
+
+	mov	ax, #2
+	cmpb	bh, #1		! Is it monochrome?
+	jz	got_video
+	inc	ax
+	jmp	got_video
+
+no_ega:	int	0x11		! Get bit pattern for equipment
+	and	ax, #0x30	! Isolate color/mono field
+	sub	ax, #0x30
+	jz	got_video	! Is it an MDA?
+	mov	ax, #1		! No it's CGA
+
+got_video:
+	ret
+
+
+! Functions to leave the boot monitor.
+.define _bootstrap		! Call another bootstrap
+.define _minix			! Call Minix
+
+! void _bootstrap(int device, struct part_entry *entry)
+!	Call another bootstrap routine to boot MS-DOS for instance.  (No real
+!	need for that anymore, now that you can format floppies under Minix).
+!	The bootstrap must have been loaded at BOOTSEG from "device".
+_bootstrap:
+	call	restore_video
+	mov	bx, sp
+	movb	dl, 2(bx)	! Device to boot from
+	mov	si, 4(bx)	! ds:si = partition table entry
+	xor	ax, ax
+	mov	es, ax		! Vector segment
+	mov	di, #BUFFER	! es:di = buffer in low core
+	mov	cx, #PENTRYSIZE	! cx = size of partition table entry
+ rep	movsb			! Copy the entry to low core
+	mov	si, #BUFFER	! es:si = partition table entry
+	mov	ds, ax		! Some bootstraps need zero segment registers
+	cli
+	mov	ss, ax
+	mov	sp, #BOOTOFF	! This should do it
+	sti
+	jmpf	BOOTOFF, 0	! Back to where the BIOS loads the boot code
+
+! void minix(u32_t koff, u32_t kcs, u32_t kds,
+!				char *bootparams, size_t paramsize, u32_t aout);
+!	Call Minix.
+_minix:
+	push	bp
+	mov	bp, sp		! Pointer to arguments
+
+	mov	dx, #0x03F2	! Floppy motor drive control bits
+	movb	al, #0x0C	! Bits 4-7 for floppy 0-3 are off
+	outb	dx		! Kill the motors
+	push	ds
+	xor	ax, ax		! Vector & BIOS data segments
+	mov	ds, ax
+	andb	0x043F, #0xF0	! Clear diskette motor status bits of BIOS
+	pop	ds
+	cli			! No more interruptions
+
+	test	_k_flags, #K_I386 ! Switch to 386 mode?
+	jnz	minix386
+
+! Call Minix in real mode.
+minix86:
+	test	_k_flags, #K_MEML ! New memory arrangements?
+	jz	0f
+	push	22(bp)		! Address of a.out headers
+	push	20(bp)
+0:
+	push	18(bp)		! # bytes of boot parameters
+	push	16(bp)		! Address of boot parameters
+
+	test	_k_flags, #K_RET ! Can the kernel return?
+	jz	noret86
+	xor	dx, dx		! If little ext mem then monitor not preserved
+	xor	ax, ax
+	cmp	_mon_return, ax	! Minix can return to the monitor?
+	jz	0f
+	mov	dx, cs		! Monitor far return address
+	mov	ax, #ret86
+0:	push	dx		! Push monitor far return address or zero
+	push	ax
+noret86:
+
+	mov	ax, 8(bp)
+	mov	dx, 10(bp)
+	call	abs2seg
+	push	dx		! Kernel code segment
+	push	4(bp)		! Kernel code offset
+	mov	ax, 12(bp)
+	mov	dx, 14(bp)
+	call	abs2seg
+	mov	ds, dx		! Kernel data segment
+	mov	es, dx		! Set es to kernel data too
+	retf			! Make a far call to the kernel
+
+! Call Minix in 386 mode.
+minix386:
+  cseg	mov	cs_real-2, cs	! Patch CS and DS into the instructions that
+  cseg	mov	ds_real-2, ds	! reload them when switching back to real mode
+	.data1	0x0F,0x20,0xC0	! mov	eax, cr0
+	orb	al, #0x01	! Set PE (protection enable) bit
+	.data1	o32
+	mov	msw, ax		! Save as protected mode machine status word
+
+	mov	dx, ds		! Monitor ds
+	mov	ax, #p_gdt	! dx:ax = Global descriptor table
+	call	seg2abs
+	mov	p_gdt_desc+2, ax
+	movb	p_gdt_desc+4, dl ! Set base of global descriptor table
+
+	mov	ax, 12(bp)
+	mov	dx, 14(bp)	! Kernel ds (absolute address)
+	mov	p_ds_desc+2, ax
+	movb	p_ds_desc+4, dl ! Set base of kernel data segment
+
+	mov	dx, ss		! Monitor ss
+	xor	ax, ax		! dx:ax = Monitor stack segment
+	call	seg2abs		! Minix starts with the stack of the monitor
+	mov	p_ss_desc+2, ax
+	movb	p_ss_desc+4, dl
+
+	mov	ax, 8(bp)
+	mov	dx, 10(bp)	! Kernel cs (absolute address)
+	mov	p_cs_desc+2, ax
+	movb	p_cs_desc+4, dl
+
+	mov	dx, cs		! Monitor cs
+	xor	ax, ax		! dx:ax = Monitor code segment
+	call	seg2abs
+	mov	p_mcs_desc+2, ax
+	movb	p_mcs_desc+4, dl
+
+	push	#MCS_SELECTOR
+	test	_k_flags, #K_INT86 ! Generic INT86 support?
+	jz	0f
+	push	#int86		! Far address to INT86 support
+	jmp	1f
+0:	push	#bios13		! Far address to BIOS int 13 support
+1:
+	test	_k_flags, #K_MEML ! New memory arrangements?
+	jz	0f
+	.data1	o32
+	push	20(bp)		! Address of a.out headers
+0:
+	push	#0
+	push	18(bp)		! 32 bit size of parameters on stack
+	push	#0
+	push	16(bp)		! 32 bit address of parameters (ss relative)
+
+	test	_k_flags, #K_RET ! Can the kernel return?
+	jz	noret386
+	push	#MCS_SELECTOR
+	push	#ret386		! Monitor far return address
+noret386:
+
+	push	#0
+	push	#CS_SELECTOR
+	push	6(bp)
+	push	4(bp)		! 32 bit far address to kernel entry point
+
+	call	real2prot	! Switch to protected mode
+	mov	ax, #DS_SELECTOR ! Kernel data
+	mov	ds, ax
+	mov	ax, #ES_SELECTOR ! Flat 4 Gb
+	mov	es, ax
+	.data1	o32		! Make a far call to the kernel
+	retf
+
+! Minix-86 returns here on a halt or reboot.
+ret86:
+	mov	_reboot_code+0, ax
+	mov	_reboot_code+2, dx	! Return value (obsolete method)
+	jmp	return
+
+! Minix-386 returns here on a halt or reboot.
+ret386:
+	.data1	o32
+	mov	_reboot_code, ax	! Return value (obsolete method)
+	call	prot2real	! Switch to real mode
+
+return:
+	mov	sp, bp		! Pop parameters
+	sti			! Can take interrupts again
+
+	call	_get_video	! MDA, CGA, EGA, ...
+	movb	dh, #24		! dh = row 24
+	cmp	ax, #2		! At least EGA?
+	jb	is25		! Otherwise 25 rows
+	push	ds
+	xor	ax, ax		! Vector & BIOS data segments
+	mov	ds, ax
+	movb	dh, 0x0484	! Number of rows on display minus one
+	pop	ds
+is25:
+	xorb	dl, dl		! dl = column 0
+	xorb	bh, bh		! Page 0
+	movb	ah, #0x02	! Set cursor position
+	int	0x10
+
+	movb	dev_state, #-1	! Minix may have upset the disks, must reset.
+	call	serial_init	! Likewise with our serial console
+
+	call	_getprocessor
+	cmp	ax, #286
+	jb	noclock
+	xorb	al, al
+tryclk:	decb	al
+	jz	noclock
+	movb	ah, #0x02	! Get real-time clock time (from CMOS clock)
+	int	0x1A
+	jc	tryclk		! Carry set, not running or being updated
+	movb	al, ch		! ch = hour in BCD
+	call	bcd		! al = (al >> 4) * 10 + (al & 0x0F)
+	mulb	c60		! 60 minutes in an hour
+	mov	bx, ax		! bx = hour * 60
+	movb	al, cl		! cl = minutes in BCD
+	call	bcd
+	add	bx, ax		! bx = hour * 60 + minutes
+	movb	al, dh		! dh = seconds in BCD
+	call	bcd
+	xchg	ax, bx		! ax = hour * 60 + minutes, bx = seconds
+	mul	c60		! dx-ax = (hour * 60 + minutes) * 60
+	add	bx, ax
+	adc	dx, #0		! dx-bx = seconds since midnight
+	mov	ax, dx
+	mul	c19663
+	xchg	ax, bx
+	mul	c19663
+	add	dx, bx		! dx-ax = dx-bx * (0x1800B0 / (2*2*2*2*5))
+	mov	cx, ax		! (0x1800B0 = ticks per day of BIOS clock)
+	mov	ax, dx
+	xor	dx, dx
+	div	c1080
+	xchg	ax, cx
+	div	c1080		! cx-ax = dx-ax / (24*60*60 / (2*2*2*2*5))
+	mov	dx, ax		! cx-dx = ticks since midnight
+	movb	ah, #0x01	! Set system time
+	int	0x1A
+noclock:
+
+	pop	bp
+	ret			! Return to monitor as if nothing much happened
+
+! Transform BCD number in al to a regular value in ax.
+bcd:	movb	ah, al
+	shrb	ah, #4
+	andb	al, #0x0F
+	.data1 0xD5,10 ! aad	! ax = (al >> 4) * 10 + (al & 0x0F)
+	ret			! (BUG: assembler messes up aad & aam!)
+
+! Support function for Minix-386 to make a BIOS int 13 call (disk I/O).
+bios13:
+	mov	bp, sp
+	call	prot2real
+	sti			! Enable interrupts
+
+	mov	ax, 8(bp)	! Load parameters
+	mov	bx, 10(bp)
+	mov	cx, 12(bp)
+	mov	dx, 14(bp)
+	mov	es, 16(bp)
+	int	0x13		! Make the BIOS call
+	mov	8(bp), ax	! Save results
+	mov	10(bp), bx
+	mov	12(bp), cx
+	mov	14(bp), dx
+	mov	16(bp), es
+
+	cli			! Disable interrupts
+	call	real2prot
+	mov	ax, #DS_SELECTOR ! Kernel data
+	mov	ds, ax
+	.data1	o32
+	retf			! Return to the kernel
+
+! Support function for Minix-386 to make an 8086 interrupt call.
+int86:
+	mov	bp, sp
+	call	prot2real
+
+	.data1	o32
+	xor	ax, ax
+	mov	es, ax		! Vector & BIOS data segments
+	.data1	o32
+   eseg	mov	0x046C, ax	! Clear BIOS clock tick counter
+
+	sti			! Enable interrupts
+
+	movb	al, #0xCD	! INT instruction
+	movb	ah, 8(bp)	! Interrupt number?
+	testb	ah, ah
+	jnz	0f		! Nonzero if INT, otherwise far call
+	push	cs
+	push	#intret+2	! Far return address
+	.data1	o32
+	push	12(bp)		! Far driver address
+	mov	ax, #0x90CB	! RETF; NOP
+0:
+ cseg	cmp	ax, intret	! Needs to be changed?
+	je	0f		! If not then avoid a huge I-cache stall
+   cseg	mov	intret, ax	! Patch 'INT n' or 'RETF; NOP' into code
+	jmp	.+2		! Clear instruction queue
+0:
+	mov	ds, 16(bp)	! Load parameters
+	mov	es, 18(bp)
+	.data1	o32
+	mov	ax, 20(bp)
+	.data1	o32
+	mov	bx, 24(bp)
+	.data1	o32
+	mov	cx, 28(bp)
+	.data1	o32
+	mov	dx, 32(bp)
+	.data1	o32
+	mov	si, 36(bp)
+	.data1	o32
+	mov	di, 40(bp)
+	.data1	o32
+	mov	bp, 44(bp)
+
+intret:	int	0xFF		! Do the interrupt or far call
+
+	.data1	o32		! Save results
+	push	bp
+	.data1	o32
+	pushf
+	mov	bp, sp
+	.data1	o32
+	pop	8+8(bp)		! eflags
+	mov	8+16(bp), ds
+	mov	8+18(bp), es
+	.data1	o32
+	mov	8+20(bp), ax
+	.data1	o32
+	mov	8+24(bp), bx
+	.data1	o32
+	mov	8+28(bp), cx
+	.data1	o32
+	mov	8+32(bp), dx
+	.data1	o32
+	mov	8+36(bp), si
+	.data1	o32
+	mov	8+40(bp), di
+	.data1	o32
+	pop	8+44(bp)	! ebp
+
+	cli			! Disable interrupts
+
+	xor	ax, ax
+	mov	ds, ax		! Vector & BIOS data segments
+	.data1	o32
+	mov	cx, 0x046C	! Collect lost clock ticks in ecx
+
+	mov	ax, ss
+	mov	ds, ax		! Restore monitor ds
+	call	real2prot
+	mov	ax, #DS_SELECTOR ! Kernel data
+	mov	ds, ax
+	.data1	o32
+	retf			! Return to the kernel
+
+! Switch from real to protected mode.
+real2prot:
+	movb	ah, #0x02	! Code for A20 enable
+	call	gate_A20
+
+	lgdt	p_gdt_desc	! Global descriptor table
+	.data1	o32
+	mov	ax, pdbr	! Load page directory base register
+	.data1	0x0F,0x22,0xD8	! mov	cr3, eax
+	.data1	0x0F,0x20,0xC0	! mov	eax, cr0
+	.data1	o32
+	xchg	ax, msw		! Exchange real mode msw for protected mode msw
+	.data1	0x0F,0x22,0xC0	! mov	cr0, eax
+	jmpf	cs_prot, MCS_SELECTOR ! Set code segment selector
+cs_prot:
+	mov	ax, #SS_SELECTOR ! Set data selectors
+	mov	ds, ax
+	mov	es, ax
+	mov	ss, ax
+	ret
+
+! Switch from protected to real mode.
+prot2real:
+	lidt	p_idt_desc	! Real mode interrupt vectors
+	.data1	0x0F,0x20,0xD8	! mov	eax, cr3
+	.data1	o32
+	mov	pdbr, ax	! Save page directory base register
+	.data1	0x0F,0x20,0xC0	! mov	eax, cr0
+	.data1	o32
+	xchg	ax, msw		! Exchange protected mode msw for real mode msw
+	.data1	0x0F,0x22,0xC0	! mov	cr0, eax
+	jmpf	cs_real, 0xDEAD	! Reload cs register
+cs_real:
+	mov	ax, #0xBEEF
+ds_real:
+	mov	ds, ax		! Reload data segment registers
+	mov	es, ax
+	mov	ss, ax
+
+	xorb	ah, ah		! Code for A20 disable
+	!jmp	gate_A20
+
+! Enable (ah = 0x02) or disable (ah = 0x00) the A20 address line.
+gate_A20:
+	cmp	bus, #2		! PS/2 bus?
+	je	gate_PS_A20
+	call	kb_wait
+	movb	al, #0xD1	! Tell keyboard that a command is coming
+	outb	0x64
+	call	kb_wait
+	movb	al, #0xDD	! 0xDD = A20 disable code if ah = 0x00
+	orb	al, ah		! 0xDF = A20 enable code if ah = 0x02
+	outb	0x60
+	call	kb_wait
+	movb	al, #0xFF	! Pulse output port
+	outb	0x64
+	call	kb_wait		! Wait for the A20 line to settle down
+	ret
+kb_wait:
+	inb	0x64
+	testb	al, #0x02	! Keyboard input buffer full?
+	jnz	kb_wait		! If so, wait
+	ret
+
+gate_PS_A20:		! The PS/2 can twiddle A20 using port A
+	inb	0x92		! Read port A
+	andb	al, #0xFD
+	orb	al, ah		! Set A20 bit to the required state
+	outb	0x92		! Write port A
+	jmp	.+2		! Small delay
+A20ok:	inb	0x92		! Check port A
+	andb	al, #0x02
+	cmpb	al, ah		! A20 line settled down to the new state?
+	jne	A20ok		! If not then wait
+	ret
+
+! void int15(bios_env_t *ep)
+!	Do an "INT 15" call, primarily for APM (Power Management).
+.define _int15
+_int15:
+	push	si		! Save callee-save register si
+	mov	si, sp
+	mov	si, 4(si)	! ep
+	mov	ax, (si)	! ep->ax
+	mov	bx, 2(si)	! ep->bx
+	mov	cx, 4(si)	! ep->cx
+	int	0x15		! INT 0x15 BIOS call
+	pushf			! Save flags
+	mov	(si), ax	! ep->ax
+	mov	2(si), bx	! ep->bx
+	mov	4(si), cx	! ep->cx
+	pop	6(si)		! ep->flags
+	pop	si		! Restore
+	ret
+
+! void scan_keyboard(void)
+!	Read keyboard character. Needs to be done in case one is waiting.
+.define _scan_keyboard
+_scan_keyboard:
+	inb	0x60
+	inb	0x61
+	movb	ah, al
+	orb	al, #0x80
+	outb	0x61
+	movb	al, ah
+	outb	0x61
+	ret
+
+.data
+	.ascii	"(null)\0"	! Just in case someone follows a null pointer
+	.align	2
+c60:	.data2	60		! Constants for MUL and DIV
+c1024:	.data2	1024
+c1080:	.data2	1080
+c19663:	.data2	19663
+
+! Global descriptor tables.
+	UNSET	= 0		! Must be computed
+
+! For "Extended Memory Block Move".
+x_gdt:
+x_null_desc:
+	! Null descriptor
+	.data2	0x0000, 0x0000
+	.data1	0x00, 0x00, 0x00, 0x00
+x_gdt_desc:
+	! Descriptor for this descriptor table
+	.data2	6*8-1, UNSET
+	.data1	UNSET, 0x00, 0x00, 0x00
+x_src_desc:
+	! Source segment descriptor
+	.data2	0xFFFF, UNSET
+	.data1	UNSET, 0x92, 0x00, 0x00
+x_dst_desc:
+	! Destination segment descriptor
+	.data2	0xFFFF, UNSET
+	.data1	UNSET, 0x92, 0x00, 0x00
+x_bios_desc:
+	! BIOS segment descriptor (scratch for int 0x15)
+	.data2	UNSET, UNSET
+	.data1	UNSET, UNSET, UNSET, UNSET
+x_ss_desc:
+	! BIOS stack segment descriptor (scratch for int 0x15)
+	.data2	UNSET, UNSET
+	.data1	UNSET, UNSET, UNSET, UNSET
+
+! Protected mode descriptor table.
+p_gdt:
+p_null_desc:
+	! Null descriptor
+	.data2	0x0000, 0x0000
+	.data1	0x00, 0x00, 0x00, 0x00
+p_gdt_desc:
+	! Descriptor for this descriptor table
+	.data2	8*8-1, UNSET
+	.data1	UNSET, 0x00, 0x00, 0x00
+p_idt_desc:
+	! Real mode interrupt descriptor table descriptor
+	.data2	0x03FF, 0x0000
+	.data1	0x00, 0x00, 0x00, 0x00
+p_ds_desc:
+	! Kernel data segment descriptor (4 Gb flat)
+	.data2	0xFFFF, UNSET
+	.data1	UNSET, 0x92, 0xCF, 0x00
+p_es_desc:
+	! Physical memory descriptor (4 Gb flat)
+	.data2	0xFFFF, 0x0000
+	.data1	0x00, 0x92, 0xCF, 0x00
+p_ss_desc:
+	! Monitor data segment descriptor (64 kb flat)
+	.data2	0xFFFF, UNSET
+	.data1	UNSET, 0x92, 0x00, 0x00
+p_cs_desc:
+	! Kernel code segment descriptor (4 Gb flat)
+	.data2	0xFFFF, UNSET
+	.data1	UNSET, 0x9A, 0xCF, 0x00
+p_mcs_desc:
+	! Monitor code segment descriptor (64 kb flat)
+	.data2	0xFFFF, UNSET
+	.data1	UNSET, 0x9A, 0x00, 0x00
+
+.bss
+	.comm	old_vid_mode, 2	! Video mode at startup
+	.comm	cur_vid_mode, 2	! Current video mode
+	.comm	dev_state, 2	! Device state: reset (-1), closed (0), open (1)
+	.comm	sectors, 2	! # sectors of current device
+	.comm	secspcyl, 2	! (Sectors * heads) of current device
+	.comm	msw, 4		! Saved machine status word (cr0)
+	.comm	pdbr, 4		! Saved page directory base register (cr3)
+	.comm	escape, 2	! Escape typed?
+	.comm	bus, 2		! Saved return value of _get_bus
+	.comm	unchar, 2	! Char returned by ungetch(c)
+	.comm	line, 2		! Serial line I/O port to copy console I/O to.
+
+
Index: /trunk/minix/boot/bootimage.c
===================================================================
--- /trunk/minix/boot/bootimage.c	(revision 9)
+++ /trunk/minix/boot/bootimage.c	(revision 9)
@@ -0,0 +1,723 @@
+/*	bootimage.c - Load an image and start it.	Author: Kees J. Bot
+ *								19 Jan 1992
+ */
+#define BIOS		1	/* Can only be used under the BIOS. */
+#define nil 0
+#define _POSIX_SOURCE	1
+#define _MINIX		1
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <a.out.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include <minix/syslib.h>
+#include <kernel/const.h>
+#include <kernel/type.h>
+#include <ibm/partition.h>
+#include "rawfs.h"
+#include "image.h"
+#include "boot.h"
+
+static int block_size = 0;
+
+#define click_shift	clck_shft	/* 7 char clash with click_size. */
+
+/* Some kernels have extra features: */
+#define K_I386	 0x0001	/* Make the 386 transition before you call me. */
+#define K_CLAIM	 0x0002	/* I will acquire my own bss pages, thank you. */
+#define K_CHMEM  0x0004	/* This kernel listens to chmem for its stack size. */
+#define K_HIGH   0x0008	/* Load mm, fs, etc. in extended memory. */
+#define K_HDR	 0x0010	/* No need to patch sizes, kernel uses the headers. */
+#define K_RET	 0x0020	/* Returns to the monitor on reboot. */
+#define K_INT86	 0x0040	/* Requires generic INT support. */
+#define K_MEML	 0x0080	/* Pass a list of free memory. */
+#define K_BRET	 0x0100	/* New monitor code on shutdown in boot parameters. */
+#define K_ALL	 0x01FF	/* All feature bits this monitor supports. */
+
+
+/* Data about the different processes. */
+
+#define PROCESS_MAX	16	/* Must match the space in kernel/mpx.x */
+#define KERNEL		0	/* The first process is the kernel. */
+#define FS		2	/* The third must be fs. */
+
+struct process {	/* Per-process memory adresses. */
+	u32_t	entry;		/* Entry point. */
+	u32_t	cs;		/* Code segment. */
+	u32_t	ds;		/* Data segment. */
+	u32_t	data;		/* To access the data segment. */
+	u32_t	end;		/* End of this process, size = (end - cs). */
+} process[PROCESS_MAX];
+int n_procs;			/* Number of processes. */
+
+/* Magic numbers in process' data space. */
+#define MAGIC_OFF	0	/* Offset of magic # in data seg. */
+#define CLICK_OFF	2	/* Offset in kernel text to click_shift. */
+#define FLAGS_OFF	4	/* Offset in kernel text to flags. */
+#define KERNEL_D_MAGIC	0x526F	/* Kernel magic number. */
+
+/* Offsets of sizes to be patched into kernel and fs. */
+#define P_SIZ_OFF	0	/* Process' sizes into kernel data. */
+#define P_INIT_OFF	4	/* Init cs & sizes into fs data. */
+
+
+#define between(a, c, z)	((unsigned) ((c) - (a)) <= ((z) - (a)))
+
+void pretty_image(char *image)
+/* Pretty print the name of the image to load.  Translate '/' and '_' to
+ * space, first letter goes uppercase.  An 'r' before a digit prints as
+ * 'revision'.  E.g. 'minix/1.6.16r10' -> 'Minix 1.6.16 revision 10'.
+ * The idea is that the part before the 'r' is the official Minix release
+ * and after the 'r' you can put version numbers for your own changes.
+ */
+{
+	int up= 0, c;
+
+	while ((c= *image++) != 0) {
+		if (c == '/' || c == '_') c= ' ';
+
+		if (c == 'r' && between('0', *image, '9')) {
+			printf(" revision ");
+			continue;
+		}
+		if (!up && between('a', c, 'z')) c= c - 'a' + 'A';
+
+		if (between('A', c, 'Z')) up= 1;
+
+		putch(c);
+	}
+}
+
+void raw_clear(u32_t addr, u32_t count)
+/* Clear "count" bytes at absolute address "addr". */
+{
+	static char zeros[128];
+	u32_t dst;
+	u32_t zct;
+
+	zct= sizeof(zeros);
+	if (zct > count) zct= count;
+	raw_copy(addr, mon2abs(&zeros), zct);
+	count-= zct;
+
+	while (count > 0) {
+		dst= addr + zct;
+		if (zct > count) zct= count;
+		raw_copy(dst, addr, zct);
+		count-= zct;
+		zct*= 2;
+	}
+}
+
+/* Align a to a multiple of n (a power of 2): */
+#define align(a, n)	(((u32_t)(a) + ((u32_t)(n) - 1)) & ~((u32_t)(n) - 1))
+unsigned click_shift;
+unsigned click_size;	/* click_size = Smallest kernel memory object. */
+unsigned k_flags;	/* Not all kernels are created equal. */
+u32_t reboot_code;	/* Obsolete reboot code return pointer. */
+
+int params2params(char *params, size_t psize)
+/* Repackage the environment settings for the kernel. */
+{
+	size_t i, n;
+	environment *e;
+	char *name, *value;
+	dev_t dev;
+
+	i= 0;
+	for (e= env; e != nil; e= e->next) {
+		name= e->name;
+		value= e->value;
+
+		if (!(e->flags & E_VAR)) continue;
+
+		if (e->flags & E_DEV) {
+			if ((dev= name2dev(value)) == -1) return 0;
+			value= ul2a10((u16_t) dev);
+		}
+
+		n= i + strlen(name) + 1 + strlen(value) + 1;
+		if (n < psize) {
+			strcpy(params + i, name);
+			strcat(params + i, "=");
+			strcat(params + i, value);
+		}
+		i= n;
+	}
+
+	if (!(k_flags & K_MEML)) {
+		/* Require old memory size variables. */
+
+		value= ul2a10((mem[0].base + mem[0].size) / 1024);
+		n= i + 7 + 1 + strlen(value) + 1;
+		if (n < psize) {
+			strcpy(params + i, "memsize=");
+			strcat(params + i, value);
+		}
+		i= n;
+		value= ul2a10(mem[1].size / 1024);
+		n= i + 7 + 1 + strlen(value) + 1;
+		if (n < psize) {
+			strcpy(params + i, "emssize=");
+			strcat(params + i, value);
+		}
+		i= n;
+	}
+
+	if (i >= psize) {
+		printf("Too many boot parameters\n");
+		return 0;
+	}
+	params[i]= 0;	/* End marked with empty string. */
+	return 1;
+}
+
+void patch_sizes(void)
+/* Patch sizes of each process into kernel data space, kernel ds into kernel
+ * text space, and sizes of init into data space of fs.  All the patched
+ * numbers are based on the kernel click size, not hardware segments.
+ */
+{
+	u16_t text_size, data_size;
+	int i;
+	struct process *procp, *initp;
+	u32_t doff;
+
+	if (k_flags & K_HDR) return;	/* Uses the headers. */
+
+	/* Patch text and data sizes of the processes into kernel data space.
+	 */
+	doff= process[KERNEL].data + P_SIZ_OFF;
+
+	for (i= 0; i < n_procs; i++) {
+		procp= &process[i];
+		text_size= (procp->ds - procp->cs) >> click_shift;
+		data_size= (procp->end - procp->ds) >> click_shift;
+
+		/* Two words per process, the text and data size: */
+		put_word(doff, text_size); doff+= 2;
+		put_word(doff, data_size); doff+= 2;
+
+		initp= procp;	/* The last process must be init. */
+	}
+
+	if (k_flags & (K_HIGH|K_MEML)) return;	/* Doesn't need FS patching. */
+
+	/* Patch cs and sizes of init into fs data. */
+	put_word(process[FS].data + P_INIT_OFF+0, initp->cs >> click_shift);
+	put_word(process[FS].data + P_INIT_OFF+2, text_size);
+	put_word(process[FS].data + P_INIT_OFF+4, data_size);
+}
+
+int selected(char *name)
+/* True iff name has no label or the proper label. */
+{
+	char *colon, *label;
+	int cmp;
+
+	if ((colon= strchr(name, ':')) == nil) return 1;
+	if ((label= b_value("label")) == nil) return 1;
+
+	*colon= 0;
+	cmp= strcmp(label, name);
+	*colon= ':';
+	return cmp == 0;
+}
+
+u32_t proc_size(struct image_header *hdr)
+/* Return the size of a process in sectors as found in an image. */
+{
+	u32_t len= hdr->process.a_text;
+
+	if (hdr->process.a_flags & A_PAL) len+= hdr->process.a_hdrlen;
+	if (hdr->process.a_flags & A_SEP) len= align(len, SECTOR_SIZE);
+	len= align(len + hdr->process.a_data, SECTOR_SIZE);
+
+	return len >> SECTOR_SHIFT;
+}
+
+off_t image_off, image_size;
+u32_t (*vir2sec)(u32_t vsec);	/* Where is a sector on disk? */
+
+u32_t file_vir2sec(u32_t vsec)
+/* Translate a virtual sector number to an absolute disk sector. */
+{
+	off_t blk;
+
+	if(!block_size) { errno = 0;  return -1; }
+
+	if ((blk= r_vir2abs(vsec / RATIO(block_size))) == -1) {
+		errno= EIO;
+		return -1;
+	}
+	return blk == 0 ? 0 : lowsec + blk * RATIO(block_size) + vsec % RATIO(block_size);
+}
+
+u32_t flat_vir2sec(u32_t vsec)
+/* Simply add an absolute sector offset to vsec. */
+{
+	return lowsec + image_off + vsec;
+}
+
+char *get_sector(u32_t vsec)
+/* Read a sector "vsec" from the image into memory and return its address.
+ * Return nil on error.  (This routine tries to read an entire track, so
+ * the next request is usually satisfied from the track buffer.)
+ */
+{
+	u32_t sec;
+	int r;
+#define SECBUFS 16
+	static char buf[SECBUFS * SECTOR_SIZE];
+	static size_t count;		/* Number of sectors in the buffer. */
+	static u32_t bufsec;		/* First Sector now in the buffer. */
+
+	if (vsec == 0) count= 0;	/* First sector; initialize. */
+
+	if ((sec= (*vir2sec)(vsec)) == -1) return nil;
+
+	if (sec == 0) {
+		/* A hole. */
+		count= 0;
+		memset(buf, 0, SECTOR_SIZE);
+		return buf;
+	}
+
+	/* Can we return a sector from the buffer? */
+	if ((sec - bufsec) < count) {
+		return buf + ((size_t) (sec - bufsec) << SECTOR_SHIFT);
+	}
+
+	/* Not in the buffer. */
+	count= 0;
+	bufsec= sec;
+
+	/* Read a whole track if possible. */
+	while (++count < SECBUFS && !dev_boundary(bufsec + count)) {
+		vsec++;
+		if ((sec= (*vir2sec)(vsec)) == -1) break;
+
+		/* Consecutive? */
+		if (sec != bufsec + count) break;
+	}
+
+	/* Actually read the sectors. */
+	if ((r= readsectors(mon2abs(buf), bufsec, count)) != 0) {
+		readerr(bufsec, r);
+		count= 0;
+		errno= 0;
+		return nil;
+	}
+	return buf;
+}
+
+int get_clickshift(u32_t ksec, struct image_header *hdr)
+/* Get the click shift and special flags from kernel text. */
+{
+	char *textp;
+
+	if ((textp= get_sector(ksec)) == nil) return 0;
+
+	if (hdr->process.a_flags & A_PAL) textp+= hdr->process.a_hdrlen;
+	click_shift= * (u16_t *) (textp + CLICK_OFF);
+	k_flags= * (u16_t *) (textp + FLAGS_OFF);
+
+	if ((k_flags & ~K_ALL) != 0) {
+		printf("%s requires features this monitor doesn't offer\n",
+			hdr->name);
+		return 0;
+	}
+
+	if (click_shift < HCLICK_SHIFT || click_shift > 16) {
+		printf("%s click size is bad\n", hdr->name);
+		errno= 0;
+		return 0;
+	}
+
+	click_size= 1 << click_shift;
+
+	return 1;
+}
+
+int get_segment(u32_t *vsec, long *size, u32_t *addr, u32_t limit)
+/* Read *size bytes starting at virtual sector *vsec to memory at *addr. */
+{
+	char *buf;
+	size_t cnt, n;
+
+	cnt= 0;
+	while (*size > 0) {
+		if (cnt == 0) {
+			if ((buf= get_sector((*vsec)++)) == nil) return 0;
+			cnt= SECTOR_SIZE;
+		}
+		if (*addr + click_size > limit) { errno= ENOMEM; return 0; }
+		n= click_size;
+		if (n > cnt) n= cnt;
+		raw_copy(*addr, mon2abs(buf), n);
+		*addr+= n;
+		*size-= n;
+		buf+= n;
+		cnt-= n;
+	}
+
+	/* Zero extend to a click. */
+	n= align(*addr, click_size) - *addr;
+	raw_clear(*addr, n);
+	*addr+= n;
+	*size-= n;
+	return 1;
+}
+
+void exec_image(char *image)
+/* Get a Minix image into core, patch it up and execute. */
+{
+	char *delayvalue;
+	int i;
+	struct image_header hdr;
+	char *buf;
+	u32_t vsec, addr, limit, aout, n;
+	struct process *procp;		/* Process under construction. */
+	long a_text, a_data, a_bss, a_stack;
+	int banner= 0;
+	long processor= a2l(b_value("processor"));
+	u16_t mode;
+	char *console;
+	char params[SECTOR_SIZE];
+	extern char *sbrk(int);
+
+	/* The stack is pretty deep here, so check if heap and stack collide. */
+	(void) sbrk(0);
+
+	printf("\nLoading ");
+	pretty_image(image);
+	printf(".\n\n");
+
+	vsec= 0;			/* Load this sector from image next. */
+	addr= mem[0].base;		/* Into this memory block. */
+	limit= mem[0].base + mem[0].size;
+	if (limit > caddr) limit= caddr;
+
+	/* Allocate and clear the area where the headers will be placed. */
+	aout = (limit -= PROCESS_MAX * A_MINHDR);
+
+	/* Clear the area where the headers will be placed. */
+	raw_clear(aout, PROCESS_MAX * A_MINHDR);
+
+	/* Read the many different processes: */
+	for (i= 0; vsec < image_size; i++) {
+		if (i == PROCESS_MAX) {
+			printf("There are more then %d programs in %s\n",
+				PROCESS_MAX, image);
+			errno= 0;
+			return;
+		}
+		procp= &process[i];
+
+		/* Read header. */
+		for (;;) {
+			if ((buf= get_sector(vsec++)) == nil) return;
+
+			memcpy(&hdr, buf, sizeof(hdr));
+
+			if (BADMAG(hdr.process)) { errno= ENOEXEC; return; }
+
+			/* Check the optional label on the process. */
+			if (selected(hdr.name)) break;
+
+			/* Bad label, skip this process. */
+			vsec+= proc_size(&hdr);
+		}
+
+		/* Sanity check: an 8086 can't run a 386 kernel. */
+		if (hdr.process.a_cpu == A_I80386 && processor < 386) {
+			printf("You can't run a 386 kernel on this 80%ld\n",
+				processor);
+			errno= 0;
+			return;
+		}
+
+		/* Get the click shift from the kernel text segment. */
+		if (i == KERNEL) {
+			if (!get_clickshift(vsec, &hdr)) return;
+			addr= align(addr, click_size);
+		}
+
+		/* Save a copy of the header for the kernel, with a_syms
+		 * misused as the address where the process is loaded at.
+		 */
+		hdr.process.a_syms= addr;
+		raw_copy(aout + i * A_MINHDR, mon2abs(&hdr.process), A_MINHDR);
+
+		if (!banner) {
+			printf("     cs       ds     text     data      bss");
+			if (k_flags & K_CHMEM) printf("    stack");
+			putch('\n');
+			banner= 1;
+		}
+
+		/* Segment sizes. */
+		a_text= hdr.process.a_text;
+		a_data= hdr.process.a_data;
+		a_bss= hdr.process.a_bss;
+		if (k_flags & K_CHMEM) {
+			a_stack= hdr.process.a_total - a_data - a_bss;
+			if (!(hdr.process.a_flags & A_SEP)) a_stack-= a_text;
+		} else {
+			a_stack= 0;
+		}
+
+		/* Collect info about the process to be. */
+		procp->cs= addr;
+
+		/* Process may be page aligned so that the text segment contains
+		 * the header, or have an unmapped zero page against vaxisms.
+		 */
+		procp->entry= hdr.process.a_entry;
+		if (hdr.process.a_flags & A_PAL) a_text+= hdr.process.a_hdrlen;
+		if (hdr.process.a_flags & A_UZP) procp->cs-= click_size;
+
+		/* Separate I&D: two segments.  Common I&D: only one. */
+		if (hdr.process.a_flags & A_SEP) {
+			/* Read the text segment. */
+			if (!get_segment(&vsec, &a_text, &addr, limit)) return;
+
+			/* The data segment follows. */
+			procp->ds= addr;
+			if (hdr.process.a_flags & A_UZP) procp->ds-= click_size;
+			procp->data= addr;
+		} else {
+			/* Add text to data to form one segment. */
+			procp->data= addr + a_text;
+			procp->ds= procp->cs;
+			a_data+= a_text;
+		}
+
+		/* Read the data segment. */
+		if (!get_segment(&vsec, &a_data, &addr, limit)) return;
+
+		/* Make space for bss and stack unless... */
+		if (i != KERNEL && (k_flags & K_CLAIM)) a_bss= a_stack= 0;
+
+		printf("%07lx  %07lx %8ld %8ld %8ld",
+			procp->cs, procp->ds,
+			hdr.process.a_text, hdr.process.a_data,
+			hdr.process.a_bss
+		);
+		if (k_flags & K_CHMEM) printf(" %8ld", a_stack);
+
+		printf("  %s\n", hdr.name);
+
+		/* Note that a_data may be negative now, but we can look at it
+		 * as -a_data bss bytes.
+		 */
+
+		/* Compute the number of bss clicks left. */
+		a_bss+= a_data;
+		n= align(a_bss, click_size);
+		a_bss-= n;
+
+		/* Zero out bss. */
+		if (addr + n > limit) { errno= ENOMEM; return; }
+		raw_clear(addr, n);
+		addr+= n;
+
+		/* And the number of stack clicks. */
+		a_stack+= a_bss;
+		n= align(a_stack, click_size);
+		a_stack-= n;
+
+		/* Add space for the stack. */
+		addr+= n;
+
+		/* Process endpoint. */
+		procp->end= addr;
+
+		if (i == 0 && (k_flags & K_HIGH)) {
+			/* Load the rest in extended memory. */
+			addr= mem[1].base;
+			limit= mem[1].base + mem[1].size;
+		}
+	}
+
+	if ((n_procs= i) == 0) {
+		printf("There are no programs in %s\n", image);
+		errno= 0;
+		return;
+	}
+
+	/* Check the kernel magic number. */
+	if (get_word(process[KERNEL].data + MAGIC_OFF) != KERNEL_D_MAGIC) {
+		printf("Kernel magic number is incorrect\n");
+		errno= 0;
+		return;
+	}
+
+	/* Patch sizes, etc. into kernel data. */
+	patch_sizes();
+
+#if !DOS
+	if (!(k_flags & K_MEML)) {
+		/* Copy the a.out headers to the old place. */
+		raw_copy(HEADERPOS, aout, PROCESS_MAX * A_MINHDR);
+	}
+#endif
+
+	/* Do delay if wanted. */
+	if((delayvalue = b_value("bootdelay")) != nil > 0) {
+		delay(delayvalue);
+	}
+
+	/* Run the trailer function just before starting Minix. */
+	if (!run_trailer()) { errno= 0; return; }
+
+	/* Translate the boot parameters to what Minix likes best. */
+	if (!params2params(params, sizeof(params))) { errno= 0; return; }
+
+	/* Set the video to the required mode. */
+	if ((console= b_value("console")) == nil || (mode= a2x(console)) == 0) {
+		mode= strcmp(b_value("chrome"), "color") == 0 ? COLOR_MODE :
+								MONO_MODE;
+	}
+	set_mode(mode);
+
+	/* Close the disk. */
+	(void) dev_close();
+
+	/* Minix. */
+	minix(process[KERNEL].entry, process[KERNEL].cs,
+			process[KERNEL].ds, params, sizeof(params), aout);
+
+	if (!(k_flags & K_BRET)) {
+		extern u32_t reboot_code;
+		raw_copy(mon2abs(params), reboot_code, sizeof(params));
+	}
+	parse_code(params);
+
+	/* Return from Minix.  Things may have changed, so assume nothing. */
+	fsok= -1;
+	errno= 0;
+
+	/* Read leftover character, if any. */
+	scan_keyboard();
+}
+
+ino_t latest_version(char *version, struct stat *stp)
+/* Recursively read the current directory, selecting the newest image on
+ * the way up.  (One can't use r_stat while reading a directory.)
+ */
+{
+	char name[NAME_MAX + 1];
+	ino_t ino, newest;
+	time_t mtime;
+
+	if ((ino= r_readdir(name)) == 0) { stp->st_mtime= 0; return 0; }
+
+	newest= latest_version(version, stp);
+	mtime= stp->st_mtime;
+	r_stat(ino, stp);
+
+	if (S_ISREG(stp->st_mode) && stp->st_mtime > mtime) {
+		newest= ino;
+		strcpy(version, name);
+	} else {
+		stp->st_mtime= mtime;
+	}
+	return newest;
+}
+
+char *select_image(char *image)
+/* Look image up on the filesystem, if it is a file then we're done, but
+ * if its a directory then we want the newest file in that directory.  If
+ * it doesn't exist at all, then see if it is 'number:number' and get the
+ * image from that absolute offset off the disk.
+ */
+{
+	ino_t image_ino;
+	struct stat st;
+
+	image= strcpy(malloc((strlen(image) + 1 + NAME_MAX + 1)
+						 * sizeof(char)), image);
+
+	fsok= r_super(&block_size) != 0;
+	if (!fsok || (image_ino= r_lookup(ROOT_INO, image)) == 0) {
+		char *size;
+
+		if (numprefix(image, &size) && *size++ == ':'
+						&& numeric(size)) {
+			vir2sec= flat_vir2sec;
+			image_off= a2l(image);
+			image_size= a2l(size);
+			strcpy(image, "Minix");
+			return image;
+		}
+		if (!fsok)
+			printf("No image selected\n");
+		else
+			printf("Can't load %s: %s\n", image, unix_err(errno));
+		goto bail_out;
+	}
+
+	r_stat(image_ino, &st);
+	if (!S_ISREG(st.st_mode)) {
+		char *version= image + strlen(image);
+		char dots[NAME_MAX + 1];
+
+		if (!S_ISDIR(st.st_mode)) {
+			printf("%s: %s\n", image, unix_err(ENOTDIR));
+			goto bail_out;
+		}
+		(void) r_readdir(dots);
+		(void) r_readdir(dots);	/* "." & ".." */
+		*version++= '/';
+		*version= 0;
+		if ((image_ino= latest_version(version, &st)) == 0) {
+			printf("There are no images in %s\n", image);
+			goto bail_out;
+		}
+		r_stat(image_ino, &st);
+	}
+	vir2sec= file_vir2sec;
+	image_size= (st.st_size + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
+	return image;
+bail_out:
+	free(image);
+	return nil;
+}
+
+void bootminix(void)
+/* Load Minix and run it.  (Given the size of this program it is surprising
+ * that it ever gets to that.)
+ */
+{
+	char *image;
+
+	if ((image= select_image(b_value("image"))) == nil) return;
+
+	exec_image(image);
+
+	switch (errno) {
+	case ENOEXEC:
+		printf("%s contains a bad program header\n", image);
+		break;
+	case ENOMEM:
+		printf("Not enough memory to load %s\n", image);
+		break;
+	case EIO:
+		printf("Unsuspected EOF on %s\n", image);
+	case 0:
+		/* No error or error already reported. */;
+	}
+	free(image);
+}
+
+/*
+ * $PchId: bootimage.c,v 1.10 2002/02/27 19:39:09 philip Exp $
+ */
Index: /trunk/minix/boot/doshead.s
===================================================================
--- /trunk/minix/boot/doshead.s	(revision 9)
+++ /trunk/minix/boot/doshead.s	(revision 9)
@@ -0,0 +1,1369 @@
+!	Doshead.s - DOS & BIOS support for boot.c	Author: Kees J. Bot
+!
+!
+! This file contains the startup and low level support for the secondary
+! boot program.  It contains functions for disk, tty and keyboard I/O,
+! copying memory to arbitrary locations, etc.
+!
+! This runs under MS-DOS as a .COM file.  A .COM file is what Minix calls
+! a common I&D executable, except that the first 256 bytes contains DOS
+! thingies.
+!
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+	K_I386	    =	0x0001	! Call Minix in 386 mode
+	STACK	    =	 16384	! Number of bytes for the stack
+
+	DS_SELECTOR =	   3*8	! Kernel data selector
+	ES_SELECTOR =	   4*8	! Flat 4 Gb
+	SS_SELECTOR =	   5*8	! Monitor stack
+	CS_SELECTOR =	   6*8	! Kernel code
+	MCS_SELECTOR=	   7*8	! Monitor code
+
+	ESC	    =	  0x1B	! Escape character
+
+! Imported variables and functions:
+.extern _caddr, _daddr, _runsize, _edata, _end	! Runtime environment
+.extern _k_flags				! Special kernel flags
+.extern _mem					! Free memory list
+.extern _vdisk					! Name of the virtual disk
+
+.sect .text
+
+.use16				! Tell 386 assembler we're in 16-bit mode
+
+.define _PSP
+_PSP:
+	.space	256		! Program Segment Prefix
+
+dosboot:
+	cld			! C compiler wants UP
+	xor	ax, ax		! Zero
+	mov	di, _edata	! Start of bss is at end of data
+	mov	cx, _end	! End of bss (begin of heap)
+	sub	cx, di		! Number of bss bytes
+	shr	cx, 1		! Number of words
+ rep	stos			! Clear bss
+	cmp	sp, _end+STACK
+	jb	0f
+	mov	sp, _end+STACK	! "chmem" to 16 kb
+0:
+
+! Are we called with the /U option?
+	movb	cl, (_PSP+0x80)	! Argument byte count
+	xorb	ch, ch
+	mov	bx, _PSP+0x81	! Argument string
+0:	jcxz	notuflag
+	cmpb	(bx), 0x20	! Whitespace?
+	ja	1f
+	inc	bx
+	dec	cx
+	jmp	0b
+1:	cmp	cx, 2		! '/U' is two bytes
+	jne	notuflag
+	cmpb	(bx), 0x2F	! '/'?
+	jne	notuflag
+	movb	al, 1(bx)
+	andb	al, ~0x20	! Ignore case
+	cmpb	al, 0x55	! 'U'?
+	jne	notuflag
+	jmp	keepumb		! Go grab an UMB
+notuflag:
+
+! Remember the current video mode for restoration on exit.
+	movb	ah, 0x0F	! Get current video mode
+	int	0x10
+	andb	al, 0x7F	! Mask off bit 7 (no blanking)
+	movb	(old_vid_mode), al
+	movb	(cur_vid_mode), al
+
+! We require at least MS-DOS 3.0.
+	mov	ax, 0x3000	! Get DOS version
+	int	0x21
+	cmpb	al, 3		! DOS 3.0+ ?
+	jae	dosok
+	push	tellbaddos
+	call	_printf
+	jmp	quit
+.sect	.rom
+tellbaddos:	.ascii	"MS-DOS 3.0 or better required\n\0"
+.sect	.text
+dosok:
+
+! Find out how much "low" memory there is available, where it starts and
+! where it ends.
+	mov	di, _mem		! di = memory list
+	mov	ax, _PSP+0x80		! From PSP:80 to next PSP is ours
+	mov	dx, ds
+	call	seg2abs
+	mov	(di), ax
+	mov	2(di), dx		! mem[0].base = ds * 16 + 0x80
+	xor	ax, ax
+	mov	dx, (_PSP+2)		! First in-use segment far above us
+	call	seg2abs
+	sub	ax, (di)
+	sbb	dx, 2(di)		! Minus base gives size
+	mov	4(di), ax
+	mov	6(di), dx		! mem[1].size = free low memory size
+
+! Give C code access to the code segment, data segment and the size of this
+! process.
+	xor	ax, ax
+	mov	dx, cs
+	call	seg2abs
+	mov	(_caddr+0), ax
+	mov	(_caddr+2), dx
+	xor	ax, ax
+	mov	dx, ds
+	call	seg2abs
+	mov	(_daddr+0), ax
+	mov	(_daddr+2), dx
+	mov	ax, sp
+	mov	dx, ss			! End of stack = end of program
+	call	seg2abs
+	sub	ax, (_caddr+0)
+	sbb	dx, (_caddr+2)		! Minus start of our code
+	mov	(_runsize+0), ax
+	mov	(_runsize+2), dx	! Is our size
+
+! Patch the regular _getprocessor library routine to jump to 'getprocessor',
+! that checks if we happen to be in a V8086 straightjacket by returning '86'.
+  cseg	movb	(_getprocessor+0), 0xE9
+	mov	ax, getprocessor
+	sub	ax, _getprocessor+3
+  cseg	mov	(_getprocessor+1), ax
+
+! Grab the largest chunk of extended memory available.
+	call	_getprocessor
+	cmp	ax, 286		! Only 286s and above have extended memory
+	jb	no_ext
+	mov	ax, 0x4300	! XMS driver check
+	int	0x2F
+	cmpb	al, 0x80	! XMS driver exists?
+	je	xmsthere
+get_ext:			! No driver, so can use all ext memory directly
+	call	_getprocessor
+	cmp	ax, 486		! Assume 486s were the first to have >64M
+	jb	small_ext	! (It helps to be paranoid when using the BIOS)
+big_ext:
+	mov	ax, 0xE801	! Code for get memory size for >64M
+	int	0x15		! ax = mem at 1M per 1K, bx = mem at 16M per 64K
+	jnc	got_ext
+small_ext:
+	movb	ah, 0x88	! Code for get extended memory size
+	clc			! Carry will stay clear if call exists
+	int	0x15		! Returns size (in K) in ax for AT's
+	jc	no_ext
+	test	ax, ax		! An AT with no extended memory?
+	jz	no_ext
+	xor	bx, bx		! bx = mem above 16M per 64K = 0
+got_ext:
+	mov	cx, ax		! cx = copy of ext mem at 1M
+	mov	10(di), 0x0010	! mem[1].base = 0x00100000 (1M)
+	mul	(c1024)
+	mov	12(di), ax	! mem[1].size = "ext mem at 1M" * 1024
+	mov	14(di), dx
+	test	bx, bx
+	jz	no_ext		! No more ext mem above 16M?
+	cmp	cx, 15*1024	! Chunks adjacent? (precisely 15M at 1M?)
+	je	adj_ext
+	mov	18(di), 0x0100	! mem[2].base = 0x01000000 (16M)
+	mov	22(di), bx	! mem[2].size = "ext mem at 16M" * 64K
+	jmp	no_ext
+adj_ext:
+	add	14(di), bx	! Add ext mem above 16M to mem below 16M
+no_ext:
+	jmp	gotxms
+
+xmsthere:
+	mov	ax, 0x4310		! Get XMS driver address
+	int	0x2F
+	mov	(xms_driver+0), bx
+	mov	(xms_driver+2), es
+	push	ds
+	pop	es
+	movb	ah, 0x08		! Query free extended memory
+	xorb	bl, bl
+	callf	(xms_driver)
+	testb	bl, bl
+	jnz	xmserr
+	push	ax			! ax = size of largest block in kb
+	mul	(c1024)
+	mov	12(di), ax
+	mov	14(di), dx		! mem[1].size = ax * 1024
+	pop	dx			! dx = size of largest block in kb
+	movb	ah, 0x09 		! Allocate XMS block of size dx
+	callf	(xms_driver)
+	test	ax, ax
+	jz	xmserr
+	mov	(xms_handle), dx	! Save handle
+	movb	ah, 0x0C		! Lock XMS block (handle in dx)
+	callf	(xms_driver)
+	test	ax, ax
+	jz	xmserr
+	mov	8(di), bx
+	mov	10(di), dx		! mem[1].base = Address of locked block
+gotxms:
+
+! If we're running in a DOS box then they're might be an Upper Memory Block
+! we can use.  Every little bit helps when in real mode.
+	mov	ax, 20(di)
+	or	ax, 22(di)		! Can we use mem[2]?
+	jnz	gotumb
+	mov	dx, 0xFFFF		! dx = Maximum size, i.e. gimme all
+	call	getumb			! Get UMB, dx = segment, cx = length
+	test	cx, cx			! Did we get a block?
+	jz	gotumb
+	xor	ax, ax			! dx:ax = memory block
+	call	seg2abs
+	mov	16(di), ax
+	mov	18(di), dx		! mem[2].base = memory block base
+	mov	dx, cx
+	xor	ax, ax			! dx:ax = length of memory block
+	call	seg2abs
+	mov	20(di), ax
+	mov	22(di), dx		! mem[2].size = memory block length
+gotumb:
+
+! Set up an INT 24 "critical error" handler that returns "fail".  This way
+! Minix won't suffer from "(A)bort, (R)etry, (I)nfluence with a large hammer?".
+	mov	(0x007C), 0x03B0	! movb al, 0x03 (fail code)
+	movb	(0x007E), 0xCF		! iret
+	movb	ah, 0x25		! Set interrupt vector
+	mov	dx, 0x007C		! ds:dx = ds:0x007C = interrupt handler
+	int	0x21
+
+! Time to switch to a higher level language (not much higher)
+	call	_boot
+
+! void ..exit(int status)
+!	Exit the monitor by returning to DOS.
+.define	_exit, __exit, ___exit		! Make various compilers happy
+_exit:
+__exit:
+___exit:
+	mov	dx, (xms_handle)
+	cmp	dx, -1			! Is there an ext mem block in use?
+	je	nohandle
+	movb	ah, 0x0D		! Unlock extended memory block
+	callf	(xms_driver)
+	mov	dx, (xms_handle)
+	movb	ah, 0x0A		! Free extended memory block
+	callf	(xms_driver)
+nohandle:
+	call	restore_video
+	pop	ax
+	pop	ax			! Return code in al
+	movb	ah, 0x4C		! Terminate with return code
+	int	0x21
+
+quit:					! exit(1)
+	movb	al, 1
+	push	ax
+	call	_exit
+
+xmserr:
+	xorb	bh, bh
+	push	bx
+	push	tellxmserr
+	call	_printf
+	jmp	quit
+.sect	.rom
+tellxmserr:	.ascii	"Extended memory problem, error 0x%02x\n\0"
+.sect	.text
+
+! int getprocessor(void)
+!	Prefix for the regular _getprocessor call that first checks if we're
+!	running in a virtual 8086 box.
+getprocessor:
+	push	sp		! Is pushed sp equal to sp?
+	pop	ax
+	cmp	ax, sp
+	jne	gettrueproc	! If not then it's a plain 8086 or 80186
+	.data1	0x0F,0x01,0xE0	! Use old 286 SMSW instruction to get the MSW
+	testb	al, 0x01	! Protected mode enabled?
+	jz	gettrueproc	! If not then a 286 or better in real mode
+	mov	ax, 86		! Forget fancy tricks, say it's an 8086
+	ret
+gettrueproc:			! Get the true processor type
+	push	bp		! _getprocessor prologue that is patched over.
+	mov	bp, sp
+	jmp	_getprocessor+3
+
+! Try to get an Upper Memory Block under MS-DOS 5+.  Try to get one up to size
+! dx, return segment of UMB found in dx and size in paragraphs in cx.
+getumb:
+	xor	cx, cx			! Initially nothing found
+	mov	ax, 0x3000		! Get DOS version
+	int	0x21
+	cmpb	al, 5			! MS-DOS 5.0 or better?
+	jb	retumb
+	mov	ax, 0x544D		! Get UMB kept by BOOT /U
+	int	0x15			! Returns dx = segment, cx = size
+	jc	0f
+	cmp	ax, 0x4D54		! Carry clear and ax byte swapped?
+	je	retumb
+0:	mov	ax, 0x5802		! Get UMB link state
+	int	0x21
+	xorb	ah, ah
+	push	ax			! Save UMB link state 
+	mov	ax, 0x5803		! Set UMB link state
+	mov	bx, 0x0001		! Add UMBs to DOS memory chain
+	int	0x21
+	mov	ax, 0x5800		! Get memory allocation strategy
+	int	0x21
+	push	ax			! Save allocation strategy
+	mov	ax, 0x5801		! Set memory allocation strategy
+	mov	bx, 0x0080		! First fit, try high then low memory
+	int	0x21
+	movb	ah, 0x48		! Allocate memory
+	mov	bx, dx			! Number of paragraphs wanted
+	int	0x21			! Fails with bx = size of largest
+	jnc	0f			! Succeeds with ax = allocated block
+	test	bx, bx			! Is there any?
+	jz	no_umb
+	movb	ah, 0x48		! Allocate memory
+	int	0x21
+	jc	no_umb			! Did we get some?
+0:	mov	dx, ax			! dx = segment
+	mov	cx, bx			! cx = size
+no_umb:	mov	ax, 0x5801		! Set memory allocation strategy
+	pop	bx			! bx = saved former strategy
+	int	0x21
+	mov	ax, 0x5803		! Set UMB link state
+	pop	bx			! bx = saved former link state
+	int	0x21
+retumb:	ret
+
+! 'BOOT /U' instructs this program to grab the biggest available UMB and to
+! sit on it until the next invocation of BOOT wants it back.  These shenanigans
+! are necessary because Windows 95 keeps all UMBs to itself unless you get hold
+! of them first.
+	umb =	0x80			! UMB base and size
+	old15 =	0x84			! Old 15 interrupt vector
+	new15 = 0x88			! New 15 interrupt handler
+keepumb:
+	mov	ax, 0x544D		! "Keep UMB" handler already present?
+	int	0x15
+	jc	0f
+	cmp	ax, 0x4D54
+	je	exitumb			! Already present, so quit
+0:
+	mov	si, new15start
+	mov	di, new15
+	mov	cx, new15end
+	sub	cx, si
+  rep	movsb				! Copy handler into place
+	add	di, 15
+	movb	cl, 4
+	shr	di, cl			! di = first segment above handler
+	mov	cx, cs
+	cmp	cx, 0xA000		! Are we loaded high perchance?
+	jb	nothigh
+werehigh:
+	add	cx, di
+	mov	(umb+0), cx		! Use my own memory as the UMB to keep
+	mov	ax, (_PSP+2)		! Up to the next in-use segment
+	sub	ax, dx			! ax = size of my free memory
+	cmp	ax, 0x1000		! At least 64K?
+	jb	exitumb			! Don't bother if less
+	mov	(umb+2), 0x1000		! Size of UMB
+	add	di, 0x1000		! Keep my code plus 64K when TSR
+	jmp	hook15
+nothigh:
+	mov	dx, 0x1000
+	call	getumb			! Grab an UMB of at most 64K
+	cmp	cx, 0x1000		! Did we get 64K?
+	jb	exitumb			! Otherwise don't bother
+	mov	(umb+0), dx
+	mov	(umb+2), cx
+hook15:
+	mov	ax, 0x3515		! Get interrupt vector
+	int	0x21
+	mov	(old15+0), bx
+	mov	(old15+2), es		! Old 15 interrupt
+	mov	ax, 0x2515		! Set interrupt vector
+	mov	dx, new15		! ds:dx = new 15 handler
+	int	0x21
+	mov	ax, 0x3100		! Terminate and stay resident
+	mov	dx, di			! dx = di = paragraphs we keep
+	int	0x21
+exitumb:
+	mov	ax, 0x4C00		! exit(0)
+	int	0x21
+
+new15start:				! New interrupt 15 handler
+	pushf
+	cmp	ax, 0x544D		! Is it my call?
+	je	my15
+	popf
+  cseg	jmpf	(old15)			! No, continue with old 15
+my15:	popf
+	push	bp
+	mov	bp, sp
+	andb	6(bp), ~0x01		! clear carry, call will succeed
+	xchgb	al, ah			! ax = 4D54, also means call works
+  cseg	mov	dx, (umb+0)		! dx = base of UMB
+  cseg	mov	cx, (umb+2)		! cx = size of UMB
+	pop	bp
+	iret				! return to caller
+new15end:
+
+! u32_t mon2abs(void *ptr)
+!	Address in monitor data to absolute address.
+.define _mon2abs
+_mon2abs:
+	mov	bx, sp
+	mov	ax, 2(bx)	! ptr
+	mov	dx, ds		! Monitor data segment
+	!jmp	seg2abs
+
+seg2abs:			! Translate dx:ax to the 32 bit address dx-ax
+	push	cx
+	movb	ch, dh
+	movb	cl, 4
+	shl	dx, cl
+	shrb	ch, cl		! ch-dx = dx << 4
+	add	ax, dx
+	adcb	ch, 0		! ch-ax = ch-dx + ax
+	movb	dl, ch
+	xorb	dh, dh		! dx-ax = ch-ax
+	pop	cx
+	ret
+
+abs2seg:			! Translate the 32 bit address dx-ax to dx:ax
+	push	cx
+	movb	ch, dl
+	mov	dx, ax		! ch-dx = dx-ax
+	and	ax, 0x000F	! Offset in ax
+	movb	cl, 4
+	shr	dx, cl
+	shlb	ch, cl
+	orb	dh, ch		! dx = ch-dx >> 4
+	pop	cx
+	ret
+
+! void raw_copy(u32_t dstaddr, u32_t srcaddr, u32_t count)
+!	Copy count bytes from srcaddr to dstaddr.  Don't do overlaps.
+!	Also handles copying words to or from extended memory.
+.define _raw_copy
+_raw_copy:
+	push	bp
+	mov	bp, sp
+	push	si
+	push	di		! Save C variable registers
+copy:
+	cmp	14(bp), 0
+	jnz	bigcopy
+	mov	cx, 12(bp)
+	jcxz	copydone	! Count is zero, end copy
+	cmp	cx, 0xFFF0
+	jb	smallcopy
+bigcopy:mov	cx, 0xFFF0	! Don't copy more than about 64K at once
+smallcopy:
+	push	cx		! Save copying count
+	mov	ax, 4(bp)
+	mov	dx, 6(bp)
+	cmp	dx, 0x0010	! Copy to extended memory?
+	jae	ext_copy
+	cmp	10(bp), 0x0010	! Copy from extended memory?
+	jae	ext_copy
+	call	abs2seg
+	mov	di, ax
+	mov	es, dx		! es:di = dstaddr
+	mov	ax, 8(bp)
+	mov	dx, 10(bp)
+	call	abs2seg
+	mov	si, ax
+	mov	ds, dx		! ds:si = srcaddr
+	shr	cx, 1		! Words to move
+ rep	movs			! Do the word copy
+	adc	cx, cx		! One more byte?
+ rep	movsb			! Do the byte copy
+	mov	ax, ss		! Restore ds and es from the remaining ss
+	mov	ds, ax
+	mov	es, ax
+ 	jmp	copyadjust
+ext_copy:
+	mov	(x_dst_desc+2), ax
+	movb	(x_dst_desc+4), dl ! Set base of destination segment
+	mov	ax, 8(bp)
+	mov	dx, 10(bp)
+	mov	(x_src_desc+2), ax
+	movb	(x_src_desc+4), dl ! Set base of source segment
+	mov	si, x_gdt	! es:si = global descriptor table
+	shr	cx, 1		! Words to move
+	movb	ah, 0x87	! Code for extended memory move
+	int	0x15
+copyadjust:
+	pop	cx		! Restore count
+	add	4(bp), cx
+	adc	6(bp), 0	! srcaddr += copycount
+	add	8(bp), cx
+	adc	10(bp), 0	! dstaddr += copycount
+	sub	12(bp), cx
+	sbb	14(bp), 0	! count -= copycount
+	jmp	copy		! and repeat
+copydone:
+	pop	di
+	pop	si		! Restore C variable registers
+	pop	bp
+	ret
+
+! u16_t get_word(u32_t addr);
+! void put_word(u32_t addr, u16_t word);
+!	Read or write a 16 bits word at an arbitrary location.
+.define	_get_word, _put_word
+_get_word:
+	mov	bx, sp
+	call	gp_getaddr
+	mov	ax, (bx)	! Word to get from addr
+	jmp	gp_ret
+_put_word:
+	mov	bx, sp
+	push	6(bx)		! Word to store at addr
+	call	gp_getaddr
+	pop	(bx)		! Store the word
+	jmp	gp_ret
+gp_getaddr:
+	mov	ax, 2(bx)
+	mov	dx, 4(bx)
+	call	abs2seg
+	mov	bx, ax
+	mov	ds, dx		! ds:bx = addr
+	ret
+gp_ret:
+	push	es
+	pop	ds		! Restore ds
+	ret
+
+! void relocate(void);
+!	After the program has copied itself to a safer place, it needs to change
+!	the segment registers.  Caddr has already been set to the new location.
+.define _relocate
+_relocate:
+	pop	bx		! Return address
+	mov	ax, (_caddr+0)
+	mov	dx, (_caddr+2)
+	call	abs2seg
+	mov	cx, dx		! cx = new code segment
+	mov	ax, cs		! Old code segment
+	sub	ax, cx		! ax = -(new - old) = -Moving offset
+	mov	dx, ds
+	sub	dx, ax
+	mov	ds, dx		! ds += (new - old)
+	mov	es, dx
+	mov	ss, dx
+	xor	ax, ax
+	call	seg2abs
+	mov	(_daddr+0), ax
+	mov	(_daddr+2), dx	! New data address
+	push	cx		! New text segment
+	push	bx		! Return offset of this function
+	retf			! Relocate
+
+! void *brk(void *addr)
+! void *sbrk(size_t incr)
+!	Cannot fail implementations of brk(2) and sbrk(3), so we can use
+!	malloc(3).  They reboot on stack collision instead of returning -1.
+.sect .data
+	.align	2
+break:	.data2	_end		! A fake heap pointer
+.sect .text
+.define _brk, __brk, _sbrk, __sbrk
+_brk:
+__brk:				! __brk is for the standard C compiler
+	xor	ax, ax
+	jmp	sbrk		! break= 0; return sbrk(addr);
+_sbrk:
+__sbrk:
+	mov	ax, (break)	! ax= current break
+sbrk:	push	ax		! save it as future return value
+	mov	bx, sp		! Stack is now: (retval, retaddr, incr, ...)
+	add	ax, 4(bx)	! ax= break + increment
+	mov	(break), ax	! Set new break
+	lea	dx, -1024(bx)	! sp minus a bit of breathing space
+	cmp	dx, ax		! Compare with the new break
+	jb	heaperr		! Suffocating noises
+	pop	ax		! Return old break (0 for brk)
+	ret
+heaperr:push	nomem
+	call	_printf
+	call	quit
+.sect .rom
+nomem:	.ascii	"\nOut of memory\n\0"
+.sect .text
+
+! int dev_open(void);
+!	Open file 'vdisk' to use as the Minix virtual disk.  Store handle in
+!	vfd.  Returns 0 for success, otherwise the DOS error code.
+.define _dev_open
+_dev_open:
+	call	_dev_close	! If already open then first close
+	mov	dx, (_vdisk)	! ds:dx = Address of file name
+	mov	ax, 0x3D22	! Open file read-write & deny write
+	int	0x21
+	jnc	opok		! Open succeeded?
+	cmp	ax, 5		! Open failed, "access denied"?
+	jne	opbad
+	mov	ax, 0x3D40	! Open file read-only
+	int	0x21
+	jc	opbad
+opok:	mov	(vfd), ax	! File handle to open file
+	xor	ax, ax		! Zero for success
+opbad:	ret
+
+! int dev_close(void);
+!	Close the dos virtual disk.
+.define _dev_close
+_dev_close:
+	mov	bx, -1
+	cmp	(vfd), bx	! Already closed?
+	je	1f
+	movb	ah, 0x3E	! Close file
+	xchg	bx, (vfd)	! bx = vfd; vfd = -1;
+	int	0x21
+	jc	0f
+1:	xor	ax, ax
+0:	ret
+
+! int dev_boundary(u32_t sector);
+!	Returns false; files have no visible boundaries.
+.define	_dev_boundary
+_dev_boundary:
+	xor	ax, ax
+	ret
+
+! int readsectors(u32_t bufaddr, u32_t sector, u8_t count)
+! int writesectors(u32_t bufaddr, u32_t sector, u8_t count)
+!	Read/write several sectors from/to the Minix virtual disk.  Count
+!	must fit in a byte.  The external variable vfd is the file handle.
+!	Returns 0 for success, otherwise the DOS error code.
+!
+.define _readsectors, _writesectors
+_writesectors:
+	push	bp
+	mov	bp, sp
+	movb	13(bp), 0x40	! Code for a file write
+	jmp	rwsec
+_readsectors:
+	push	bp
+	mov	bp, sp
+	movb	13(bp), 0x3F	! Code for a file read
+rwsec:
+	cmp	(vfd), -1	! Currently closed?
+	jne	0f
+	call	_dev_open	! Open file if needed
+	test	ax, ax
+	jnz	rwerr
+0:	mov	dx, 8(bp)
+	mov	bx, 10(bp)	! bx-dx = Sector number
+	mov	cx, 9
+mul512:	shl	dx, 1
+	rcl	bx, 1		! bx-dx *= 512
+	loop	mul512
+	mov	cx, bx		! cx-dx = Byte position in file
+	mov	bx, (vfd)	! bx = File handle
+	mov	ax, 0x4200	! Lseek absolute
+	int	0x21
+	jb	rwerr
+	mov	bx, (vfd)	! bx = File handle
+	mov	ax, 4(bp)
+	mov	dx, 6(bp)	! dx-ax = Address to transfer data to/from
+	call	abs2seg
+	mov	ds, dx
+	mov	dx, ax		! ds:dx = Address to transfer data to/from
+	xorb	cl, cl
+	movb	ch, 12(bp)	! ch = Number of sectors to transfer
+	shl	cx, 1		! cx = Number of bytes to transfer
+	push	cx		! Save count
+	movb	ah, 13(bp)	! Read or write
+	int	0x21
+	pop	cx		! Restore count
+	push	es
+	pop	ds		! Restore ds
+	jb	rwerr
+	cmp	ax, cx		! All bytes transferred?
+	je	rwall
+	mov	ax, 0x05	! The DOS code for "I/O error", but different
+	jmp	rwerr
+rwall:	call	wheel		! Display tricks
+	xor	ax, ax
+rwerr:	pop	bp
+	ret
+
+! int getch(void);
+!	Read a character from the keyboard, and check for an expired timer.
+!	A carriage return is changed into a linefeed for UNIX compatibility.
+.define _getch
+_getch:
+	xor	ax, ax
+	xchg	ax, (unchar)	! Ungotten character?
+	test	ax, ax
+	jnz	gotch
+getch:	hlt			! Play dead until interrupted (see pause())
+	movb	ah, 0x01	! Keyboard status
+	int	0x16
+	jnz	press		! Keypress?
+	call	_expired	! Timer expired?
+	test	ax, ax
+	jz	getch
+	mov	ax, ESC		! Return ESC
+	ret
+press:
+	xorb	ah, ah		! Read character from keyboard
+	int	0x16
+	cmpb	al, 0x0D	! Carriage return?
+	jnz	nocr
+	movb	al, 0x0A	! Change to linefeed
+nocr:	cmpb	al, ESC		! Escape typed?
+	jne	noesc
+	inc	(escape)	! Set flag
+noesc:	xorb	ah, ah		! ax = al
+gotch:	ret
+
+! int ungetch(void);
+!	Return a character to undo a getch().
+.define _ungetch
+_ungetch:
+	mov	bx, sp
+	mov	ax, 2(bx)
+	mov	(unchar), ax
+	ret
+
+! int escape(void);
+!	True if ESC has been typed.
+.define _escape
+_escape:
+	movb	ah, 0x01	! Keyboard status
+	int	0x16
+	jz	escflg		! Keypress?
+	cmpb	al, ESC		! Escape typed?
+	jne	escflg
+	xorb	ah, ah		! Discard the escape
+	int	0x16
+	inc	(escape)	! Set flag
+escflg:	xor	ax, ax
+	xchg	ax, (escape)	! Escape typed flag
+	ret
+
+! int putch(int c);
+!	Write a character in teletype mode.  The putk synonym is
+!	for the kernel printf function that uses it.
+!	Newlines are automatically preceded by a carriage return.
+!
+.define _putch, _putk
+_putch:
+_putk:	mov	bx, sp
+	movb	al, 2(bx)	! al = character to be printed
+	testb	al, al		! Kernel printf adds a null char to flush queue
+	jz	nulch
+	cmpb	al, 0x0A	! al = newline?
+	jnz	putc
+	movb	al, 0x20	! Erase wheel and do a carriage return
+	call	plotc		! plotc(' ');
+nodirt:	movb	al, 0x0D
+	call	putc		! putc('\r')
+	movb	al, 0x0A	! Restore the '\n' and print it
+putc:	movb	ah, 0x0E	! Print character in teletype mode
+	mov	bx, 0x0001	! Page 0, foreground color
+	int	0x10		! Call BIOS VIDEO_IO
+nulch:	ret
+
+! |/-\|/-\|/-\|/-\|/-\	(playtime)
+wheel:	mov	bx, (gp)
+	movb	al, (bx)
+	inc	bx		! al = *gp++;
+	cmp	bx, glyphs+4
+	jne	0f
+	mov	bx, glyphs
+0:	mov	(gp), bx	! gp= gp == glyphs + 4 ? glyphs : gp;
+	!jmp	plotc
+plotc:	movb	ah, 0x0A	! 0x0A = write character at cursor
+	mov	bx, 0x0001	! Page 0, foreground color
+	mov	cx, 0x0001	! Just one character
+	int	0x10
+	ret
+.sect .data
+	.align	2
+gp:	.data2	glyphs
+glyphs:	.ascii	"|/-\\"
+.sect .text
+
+! void pause(void);
+!	Wait for an interrupt using the HLT instruction.  This either saves
+!	power, or tells an x86 emulator that nothing is happening right now.
+.define _pause
+_pause:
+	hlt
+	ret
+
+! void set_mode(unsigned mode);
+! void clear_screen(void);
+!	Set video mode / clear the screen.
+.define _set_mode, _clear_screen
+_set_mode:
+	mov	bx, sp
+	mov	ax, 2(bx)	! Video mode
+	cmp	ax, (cur_vid_mode)
+	je	modeok		! Mode already as requested?
+	mov	(cur_vid_mode), ax
+_clear_screen:
+	mov	ax, (cur_vid_mode)
+	andb	ah, 0x7F	! Test bits 8-14, clear bit 15 (8x8 flag)
+	jnz	xvesa		! VESA extended mode?
+	int	0x10		! Reset video (ah = 0)
+	jmp	mdset
+xvesa:	mov	bx, ax		! bx = extended mode
+	mov	ax, 0x4F02	! Reset video
+	int	0x10
+mdset:	testb	(cur_vid_mode+1), 0x80
+	jz	setcur		! 8x8 font requested?
+	mov	ax, 0x1112	! Load ROM 8 by 8 double-dot patterns
+	xorb	bl, bl		! Load block 0
+	int	0x10
+setcur:	xor	dx, dx		! dl = column = 0, dh = row = 0
+	xorb	bh, bh		! Page 0
+	movb	ah, 0x02	! Set cursor position
+	int	0x10
+modeok:	ret
+
+restore_video:			! To restore the video mode on exit
+	movb	al, 0x20
+	call	plotc		! Erase wheel
+	push	(old_vid_mode)
+	call	_set_mode
+	pop	ax
+	ret
+
+! u32_t get_tick(void);
+!	Return the current value of the clock tick counter.  This counter
+!	increments 18.2 times per second.  Poll it to do delays.  Does not
+!	work on the original PC, but works on the PC/XT.
+.define _get_tick
+_get_tick:
+	xorb	ah, ah		! Code for get tick count
+	int	0x1A
+	mov	ax, dx
+	mov	dx, cx		! dx:ax = cx:dx = tick count
+	ret
+
+
+! Functions used to obtain info about the hardware.  Boot uses this information
+! itself, but will also pass them on to a pure 386 kernel, because one can't
+! make BIOS calls from protected mode.  The video type could probably be
+! determined by the kernel too by looking at the hardware, but there is a small
+! chance on errors that the monitor allows you to correct by setting variables.
+
+.define _get_bus		! returns type of system bus
+.define _get_video		! returns type of display
+
+! u16_t get_bus(void)
+!	Return type of system bus, in order: XT, AT, MCA.
+_get_bus:
+	call	gettrueproc
+	xor	dx, dx		! Assume XT
+	cmp	ax, 286		! An AT has at least a 286
+	jb	got_bus
+	inc	dx		! Assume AT
+	movb	ah, 0xC0	! Code for get configuration
+	int	0x15
+	jc	got_bus		! Carry clear and ah = 00 if supported
+	testb	ah, ah
+	jne	got_bus
+ eseg	movb	al, 5(bx)	! Load feature byte #1
+	inc	dx		! Assume MCA
+	testb	al, 0x02	! Test bit 1 - "bus is Micro Channel"
+	jnz	got_bus
+	dec	dx		! Assume AT
+	testb	al, 0x40	! Test bit 6 - "2nd 8259 installed"
+	jnz	got_bus
+	dec	dx		! It is an XT
+got_bus:
+	push	ds
+	pop	es		! Restore es
+	mov	ax, dx		! Return bus code
+	mov	(bus), ax	! Keep bus code, A20 handler likes to know
+	ret
+
+! u16_t get_video(void)
+!	Return type of display, in order: MDA, CGA, mono EGA, color EGA,
+!	mono VGA, color VGA.
+_get_video:
+	mov	ax, 0x1A00	! Function 1A returns display code
+	int	0x10		! al = 1A if supported
+	cmpb	al, 0x1A
+	jnz	no_dc		! No display code function supported
+
+	mov	ax, 2
+	cmpb	bl, 5		! Is it a monochrome EGA?
+	jz	got_video
+	inc	ax
+	cmpb	bl, 4		! Is it a color EGA?
+	jz	got_video
+	inc	ax
+	cmpb	bl, 7		! Is it a monochrome VGA?
+	jz	got_video
+	inc	ax
+	cmpb	bl, 8		! Is it a color VGA?
+	jz	got_video
+
+no_dc:	movb	ah, 0x12	! Get information about the EGA
+	movb	bl, 0x10
+	int	0x10
+	cmpb	bl, 0x10	! Did it come back as 0x10? (No EGA)
+	jz	no_ega
+
+	mov	ax, 2
+	cmpb	bh, 1		! Is it monochrome?
+	jz	got_video
+	inc	ax
+	jmp	got_video
+
+no_ega:	int	0x11		! Get bit pattern for equipment
+	and	ax, 0x30	! Isolate color/mono field
+	sub	ax, 0x30
+	jz	got_video	! Is it an MDA?
+	mov	ax, 1		! No it's CGA
+
+got_video:
+	ret
+
+
+! Function to leave the boot monitor and run Minix.
+.define _minix
+
+! void minix(u32_t koff, u32_t kcs, u32_t kds,
+!				char *bootparams, size_t paramsize, u32_t aout);
+_minix:
+	push	bp
+	mov	bp, sp		! Pointer to arguments
+
+	mov	dx, 0x03F2	! Floppy motor drive control bits
+	movb	al, 0x0C	! Bits 4-7 for floppy 0-3 are off
+	outb	dx		! Kill the motors
+	push	ds
+	xor	ax, ax		! Vector & BIOS data segments
+	mov	ds, ax
+	andb	(0x043F), 0xF0	! Clear diskette motor status bits of BIOS
+	pop	ds
+	cli			! No more interruptions
+
+	test	(_k_flags), K_I386 ! Minix-386?
+	jnz	minix386
+
+! Call Minix in real mode.
+minix86:
+	push	22(bp)		! Address of a.out headers
+	push	20(bp)
+
+	push	18(bp)		! # bytes of boot parameters
+	push	16(bp)		! Address of boot parameters
+
+	mov	dx, cs		! Monitor far return address
+	mov	ax, ret86
+	cmp	(_mem+14), 0	! Any extended memory?  (mem[1].size > 0 ?)
+	jnz	0f
+	xor	dx, dx		! If no ext mem then monitor not preserved
+	xor	ax, ax
+0:	push	dx		! Push monitor far return address or zero
+	push	ax
+
+	mov	ax, 8(bp)
+	mov	dx, 10(bp)
+	call	abs2seg
+	push	dx		! Kernel code segment
+	push	4(bp)		! Kernel code offset
+	mov	ax, 12(bp)
+	mov	dx, 14(bp)
+	call	abs2seg
+	mov	ds, dx		! Kernel data segment
+	mov	es, dx		! Set es to kernel data too
+	retf			! Make a far call to the kernel
+
+! Call 386 Minix in 386 mode.
+minix386:
+  cseg	mov	(cs_real-2), cs	! Patch CS and DS into the instructions that
+  cseg	mov	(ds_real-2), ds	! reload them when switching back to real mode
+	mov	eax, cr0
+	orb	al, 0x01	! Set PE (protection enable) bit
+   o32	mov	(msw), eax	! Save as protected mode machine status word
+
+	mov	dx, ds		! Monitor ds
+	mov	ax, p_gdt	! dx:ax = Global descriptor table
+	call	seg2abs
+	mov	(p_gdt_desc+2), ax
+	movb	(p_gdt_desc+4), dl ! Set base of global descriptor table
+
+	mov	ax, 12(bp)
+	mov	dx, 14(bp)	! Kernel ds (absolute address)
+	mov	(p_ds_desc+2), ax
+	movb	(p_ds_desc+4), dl ! Set base of kernel data segment
+
+	mov	dx, ss		! Monitor ss
+	xor	ax, ax		! dx:ax = Monitor stack segment
+	call	seg2abs		! Minix starts with the stack of the monitor
+	mov	(p_ss_desc+2), ax
+	movb	(p_ss_desc+4), dl
+
+	mov	ax, 8(bp)
+	mov	dx, 10(bp)	! Kernel cs (absolute address)
+	mov	(p_cs_desc+2), ax
+	movb	(p_cs_desc+4), dl
+
+	mov	dx, cs		! Monitor cs
+	xor	ax, ax		! dx:ax = Monitor code segment
+	call	seg2abs
+	mov	(p_mcs_desc+2), ax
+	movb	(p_mcs_desc+4), dl
+
+	push	MCS_SELECTOR
+	push	int86		! Far address to INT86 support
+
+   o32	push	20(bp)		! Address of a.out headers
+
+	push	0
+	push	18(bp)		! 32 bit size of parameters on stack
+	push	0
+	push	16(bp)		! 32 bit address of parameters (ss relative)
+
+	push	MCS_SELECTOR
+	push	ret386		! Monitor far return address
+
+	push	0
+	push	CS_SELECTOR
+	push	6(bp)
+	push	4(bp)		! 32 bit far address to kernel entry point
+
+	call	real2prot	! Switch to protected mode
+	mov	ax, DS_SELECTOR
+	mov	ds, ax		! Kernel data
+	mov	ax, ES_SELECTOR
+	mov	es, ax		! Flat 4 Gb
+   o32	retf			! Make a far call to the kernel
+
+! Minix-86 returns here on a halt or reboot.
+ret86:
+	mov	8(bp), ax
+	mov	10(bp), dx	! Return value
+	jmp	return
+
+! Minix-386 returns here on a halt or reboot.
+ret386:
+   o32	mov	8(bp), eax	! Return value
+	call	prot2real	! Switch to real mode
+
+return:
+	mov	sp, bp		! Pop parameters
+	sti			! Can take interrupts again
+
+	call	_get_video	! MDA, CGA, EGA, ...
+	movb	dh, 24		! dh = row 24
+	cmp	ax, 2		! At least EGA?
+	jb	is25		! Otherwise 25 rows
+	push	ds
+	xor	ax, ax		! Vector & BIOS data segments
+	mov	ds, ax
+	movb	dh, (0x0484)	! Number of rows on display minus one
+	pop	ds
+is25:
+	xorb	dl, dl		! dl = column 0
+	xorb	bh, bh		! Page 0
+	movb	ah, 0x02	! Set cursor position
+	int	0x10
+
+	xorb	ah, ah		! Whack the disk system, Minix may have messed
+	movb	dl, 0x80	! it up
+	int	0x13
+
+	call	gettrueproc
+	cmp	ax, 286
+	jb	noclock
+	xorb	al, al
+tryclk:	decb	al
+	jz	noclock
+	movb	ah, 0x02	! Get real-time clock time (from CMOS clock)
+	int	0x1A
+	jc	tryclk		! Carry set, not running or being updated
+	movb	al, ch		! ch = hour in BCD
+	call	bcd		! al = (al >> 4) * 10 + (al & 0x0F)
+	mulb	(c60)		! 60 minutes in an hour
+	mov	bx, ax		! bx = hour * 60
+	movb	al, cl		! cl = minutes in BCD
+	call	bcd
+	add	bx, ax		! bx = hour * 60 + minutes
+	movb	al, dh		! dh = seconds in BCD
+	call	bcd
+	xchg	ax, bx		! ax = hour * 60 + minutes, bx = seconds
+	mul	(c60)		! dx-ax = (hour * 60 + minutes) * 60
+	add	bx, ax
+	adc	dx, 0		! dx-bx = seconds since midnight
+	mov	ax, dx
+	mul	(c19663)
+	xchg	ax, bx
+	mul	(c19663)
+	add	dx, bx		! dx-ax = dx-bx * (0x1800B0 / (2*2*2*2*5))
+	mov	cx, ax		! (0x1800B0 = ticks per day of BIOS clock)
+	mov	ax, dx
+	xor	dx, dx
+	div	(c1080)
+	xchg	ax, cx
+	div	(c1080)		! cx-ax = dx-ax / (24*60*60 / (2*2*2*2*5))
+	mov	dx, ax		! cx-dx = ticks since midnight
+	movb	ah, 0x01	! Set system time
+	int	0x1A
+noclock:
+
+	mov	ax, 8(bp)
+	mov	dx, 10(bp)	! dx-ax = return value from the kernel
+	pop	bp
+	ret			! Return to monitor as if nothing much happened
+
+! Transform BCD number in al to a regular value in ax.
+bcd:	movb	ah, al
+	shrb	ah, 4
+	andb	al, 0x0F
+	aad			! ax = (al >> 4) * 10 + (al & 0x0F)
+	ret
+
+! Support function for Minix-386 to make an 8086 interrupt call.
+int86:
+	mov	bp, sp
+	call	prot2real
+
+   o32	xor	eax, eax
+	mov	es, ax		! Vector & BIOS data segments
+o32 eseg mov	(0x046C), eax	! Clear BIOS clock tick counter
+
+	sti			! Enable interrupts
+
+	movb	al, 0xCD	! INT instruction
+	movb	ah, 8(bp)	! Interrupt number?
+	testb	ah, ah
+	jnz	0f		! Nonzero if INT, otherwise far call
+	push	cs
+	push	intret+2	! Far return address
+   o32	push	12(bp)		! Far driver address
+	mov	ax, 0x90CB	! RETF; NOP
+0: cseg	mov	(intret), ax	! Patch 'INT n' or 'RETF; NOP' into code
+
+	mov	ds, 16(bp)	! Load parameters
+	mov	es, 18(bp)
+   o32	mov	eax, 20(bp)
+   o32	mov	ebx, 24(bp)
+   o32	mov	ecx, 28(bp)
+   o32	mov	edx, 32(bp)
+   o32	mov	esi, 36(bp)
+   o32	mov	edi, 40(bp)
+   o32	mov	ebp, 44(bp)
+
+intret:	int	0xFF		! Do the interrupt or far call
+
+   o32	push	ebp		! Save results
+   o32	pushf
+	mov	bp, sp
+   o32	pop	8+8(bp)		! eflags
+	mov	8+16(bp), ds
+	mov	8+18(bp), es
+   o32	mov	8+20(bp), eax
+   o32	mov	8+24(bp), ebx
+   o32	mov	8+28(bp), ecx
+   o32	mov	8+32(bp), edx
+   o32	mov	8+36(bp), esi
+   o32	mov	8+40(bp), edi
+   o32	pop	8+44(bp)	! ebp
+
+	cli			! Disable interrupts
+
+	xor	ax, ax
+	mov	ds, ax		! Vector & BIOS data segments
+   o32	mov	cx, (0x046C)	! Collect lost clock ticks in ecx
+
+	mov	ax, ss
+	mov	ds, ax		! Restore monitor ds
+	call	real2prot
+	mov	ax, DS_SELECTOR	! Kernel data
+	mov	ds, ax
+   o32	retf			! Return to the kernel
+
+! Switch from real to protected mode.
+real2prot:
+	movb	ah, 0x02	! Code for A20 enable
+	call	gate_A20
+
+	lgdt	(p_gdt_desc)	! Global descriptor table
+   o32	mov	eax, (pdbr)	! Load page directory base register
+	mov	cr3, eax
+	mov	eax, cr0
+   o32	xchg	eax, (msw)	! Exchange real mode msw for protected mode msw
+	mov	cr0, eax
+	jmpf	MCS_SELECTOR:cs_prot ! Set code segment selector
+cs_prot:
+	mov	ax, SS_SELECTOR	! Set data selectors
+	mov	ds, ax
+	mov	es, ax
+	mov	ss, ax
+	ret
+
+! Switch from protected to real mode.
+prot2real:
+	lidt	(p_idt_desc)	! Real mode interrupt vectors
+	mov	eax, cr3
+   o32	mov	(pdbr), eax	! Save page directory base register
+	mov	eax, cr0
+   o32	xchg	eax, (msw)	! Exchange protected mode msw for real mode msw
+	mov	cr0, eax
+	jmpf	0xDEAD:cs_real	! Reload cs register
+cs_real:
+	mov	ax, 0xBEEF
+ds_real:
+	mov	ds, ax		! Reload data segment registers
+	mov	es, ax
+	mov	ss, ax
+
+	xorb	ah, ah		! Code for A20 disable
+	!jmp	gate_A20
+
+! Enable (ah = 0x02) or disable (ah = 0x00) the A20 address line.
+gate_A20:
+	cmp	(bus), 2	! PS/2 bus?
+	je	gate_PS_A20
+	call	kb_wait
+	movb	al, 0xD1	! Tell keyboard that a command is coming
+	outb	0x64
+	call	kb_wait
+	movb	al, 0xDD	! 0xDD = A20 disable code if ah = 0x00
+	orb	al, ah		! 0xDF = A20 enable code if ah = 0x02
+	outb	0x60
+	call	kb_wait
+	movb	al, 0xFF	! Pulse output port
+	outb	0x64
+	call    kb_wait		! Wait for the A20 line to settle down
+	ret
+kb_wait:
+	inb	0x64
+	testb	al, 0x02	! Keyboard input buffer full?
+	jnz	kb_wait		! If so, wait
+	ret
+
+gate_PS_A20:		! The PS/2 can twiddle A20 using port A
+	inb	0x92		! Read port A
+	andb	al, 0xFD
+	orb	al, ah		! Set A20 bit to the required state
+	outb	0x92		! Write port A
+	jmp	.+2		! Small delay
+A20ok:	inb	0x92		! Check port A
+	andb	al, 0x02
+	cmpb	al, ah		! A20 line settled down to the new state?
+	jne	A20ok		! If not then wait
+	ret
+
+! void int15(bios_env_t *ep)
+!	Do an "INT 15" call, primarily for APM (Power Management).
+.define _int15
+_int15:
+	push	si		! Save callee-save register si
+	mov	si, sp
+	mov	si, 4(si)	! ep
+	mov	ax, (si)	! ep->ax
+	mov	bx, 2(si)	! ep->bx
+	mov	cx, 4(si)	! ep->cx
+	int	0x15		! INT 0x15 BIOS call
+	pushf			! Save flags
+	mov	(si), ax	! ep->ax
+	mov	2(si), bx	! ep->bx
+	mov	4(si), cx	! ep->cx
+	pop	6(si)		! ep->flags
+	pop	si		! Restore
+	ret
+
+.sect	.rom
+	.align	4
+c60:	.data2	60		! Constants for MUL and DIV
+c1024:	.data2	1024
+c1080:	.data2	1080
+c19663:	.data2	19663
+
+.sect .data
+	.align	4
+
+! Global descriptor tables.
+	UNSET	= 0		! Must be computed
+
+! For "Extended Memory Block Move".
+x_gdt:
+x_null_desc:
+	! Null descriptor
+	.data2	0x0000, 0x0000
+	.data1	0x00, 0x00, 0x00, 0x00
+x_gdt_desc:
+	! Descriptor for this descriptor table
+	.data2	6*8-1, UNSET
+	.data1	UNSET, 0x00, 0x00, 0x00
+x_src_desc:
+	! Source segment descriptor
+	.data2	0xFFFF, UNSET
+	.data1	UNSET, 0x92, 0x00, 0x00
+x_dst_desc:
+	! Destination segment descriptor
+	.data2	0xFFFF, UNSET
+	.data1	UNSET, 0x92, 0x00, 0x00
+x_bios_desc:
+	! BIOS segment descriptor (scratch for int 0x15)
+	.data2	UNSET, UNSET
+	.data1	UNSET, UNSET, UNSET, UNSET
+x_ss_desc:
+	! BIOS stack segment descriptor (scratch for int 0x15)
+	.data2	UNSET, UNSET
+	.data1	UNSET, UNSET, UNSET, UNSET
+
+! Protected mode descriptor table.
+p_gdt:
+p_null_desc:
+	! Null descriptor
+	.data2	0x0000, 0x0000
+	.data1	0x00, 0x00, 0x00, 0x00
+p_gdt_desc:
+	! Descriptor for this descriptor table
+	.data2	8*8-1, UNSET
+	.data1	UNSET, 0x00, 0x00, 0x00
+p_idt_desc:
+	! Real mode interrupt descriptor table descriptor
+	.data2	0x03FF, 0x0000
+	.data1	0x00, 0x00, 0x00, 0x00
+p_ds_desc:
+	! Kernel data segment descriptor (4Gb flat)
+	.data2	0xFFFF, UNSET
+	.data1	UNSET, 0x92, 0xCF, 0x00
+p_es_desc:
+	! Physical memory descriptor (4Gb flat)
+	.data2	0xFFFF, 0x0000
+	.data1	0x00, 0x92, 0xCF, 0x00
+p_ss_desc:
+	! Monitor data segment descriptor (64Kb flat)
+	.data2	0xFFFF, UNSET
+	.data1	UNSET, 0x92, 0x00, 0x00
+p_cs_desc:
+	! Kernel code segment descriptor (4Gb flat)
+	.data2	0xFFFF, UNSET
+	.data1	UNSET, 0x9A, 0xCF, 0x00
+p_mcs_desc:
+	! Monitor code segment descriptor (64 kb flat) (unused)
+	.data2	0xFFFF, UNSET
+	.data1	UNSET, 0x9A, 0x00, 0x00
+
+xms_handle:	.data2	-1		! Handle of allocated XMS block
+vfd:		.data2  -1		! Virtual disk file handle
+
+.sect .bss
+	.comm	xms_driver, 4	! Vector to XMS driver
+	.comm	old_vid_mode, 2	! Video mode at startup
+	.comm	cur_vid_mode, 2	! Current video mode
+	.comm	msw, 4		! Saved machine status word (cr0)
+	.comm	pdbr, 4		! Saved page directory base register (cr3)
+	.comm	escape, 2	! Escape typed?
+	.comm	bus, 2		! Saved return value of _get_bus
+	.comm	unchar, 2	! Char returned by ungetch(c)
+
+!
+! $PchId: doshead.ack.s,v 1.7 2002/02/27 19:37:52 philip Exp $
Index: /trunk/minix/boot/image.h
===================================================================
--- /trunk/minix/boot/image.h	(revision 9)
+++ /trunk/minix/boot/image.h	(revision 9)
@@ -0,0 +1,13 @@
+/*	image.h - Info between installboot and boot.	Author: Kees J. Bot
+ */
+
+#define IM_NAME_MAX	63
+
+struct image_header {
+	char		name[IM_NAME_MAX + 1];	/* Null terminated. */
+	struct exec	process;
+};
+
+/*
+ * $PchId: image.h,v 1.4 1995/11/27 22:23:12 philip Exp $
+ */
Index: /trunk/minix/boot/installboot.c
===================================================================
--- /trunk/minix/boot/installboot.c	(revision 9)
+++ /trunk/minix/boot/installboot.c	(revision 9)
@@ -0,0 +1,833 @@
+/*	installboot 3.0 - Make a device bootable	Author: Kees J. Bot
+ *								21 Dec 1991
+ *
+ * Either make a device bootable or make an image from kernel, mm, fs, etc.
+ */
+#define nil 0
+#define _POSIX_SOURCE	1
+#define _MINIX		1
+#include <stdio.h>
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <dirent.h>
+#include <a.out.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/partition.h>
+#include <minix/u64.h>
+#include "rawfs.h"
+#include "image.h"
+
+#define BOOTBLOCK	0	/* Of course */
+#define SECTOR_SIZE	512	/* Disk sector size. */
+#define RATIO(b)	((b)/SECTOR_SIZE)
+#define SIGNATURE	0xAA55	/* Boot block signature. */
+#define BOOT_MAX	64	/* Absolute maximum size of secondary boot */
+#define SIGPOS		510	/* Where to put signature word. */
+#define PARTPOS		446	/* Offset to the partition table in a master
+				 * boot block.
+				 */
+
+#define between(a, c, z)	((unsigned) ((c) - (a)) <= ((z) - (a)))
+#define control(c)		between('\0', (c), '\37')
+
+#define BOOT_BLOCK_SIZE 1024
+
+void report(char *label)
+/* installboot: label: No such file or directory */
+{
+	fprintf(stderr, "installboot: %s: %s\n", label, strerror(errno));
+}
+
+void fatal(char *label)
+{
+	report(label);
+	exit(1);
+}
+
+char *basename(char *name)
+/* Return the last component of name, stripping trailing slashes from name.
+ * Precondition: name != "/".  If name is prefixed by a label, then the
+ * label is copied to the basename too.
+ */
+{
+	static char base[IM_NAME_MAX];
+	char *p, *bp= base;
+
+	if ((p= strchr(name, ':')) != nil) {
+		while (name <= p && bp < base + IM_NAME_MAX - 1)
+			*bp++ = *name++;
+	}
+	for (;;) {
+		if ((p= strrchr(name, '/')) == nil) { p= name; break; }
+		if (*++p != 0) break;
+		*--p= 0;
+	}
+	while (*p != 0 && bp < base + IM_NAME_MAX - 1) *bp++ = *p++;
+	*bp= 0;
+	return base;
+}
+
+void bread(FILE *f, char *name, void *buf, size_t len)
+/* Read len bytes.  Don't dare return without them. */
+{
+	if (len > 0 && fread(buf, len, 1, f) != 1) {
+		if (ferror(f)) fatal(name);
+		fprintf(stderr, "installboot: Unexpected EOF on %s\n", name);
+		exit(1);
+	}
+}
+
+void bwrite(FILE *f, char *name, void *buf, size_t len)
+{
+	if (len > 0 && fwrite(buf, len, 1, f) != 1) fatal(name);
+}
+
+long total_text= 0, total_data= 0, total_bss= 0;
+int making_image= 0;
+
+void read_header(int talk, char *proc, FILE *procf, struct image_header *ihdr)
+/* Read the a.out header of a program and check it.  If procf happens to be
+ * nil then the header is already in *image_hdr and need only be checked.
+ */
+{
+	int n, big= 0;
+	static int banner= 0;
+	struct exec *phdr= &ihdr->process;
+
+	if (procf == nil) {
+		/* Header already present. */
+		n= phdr->a_hdrlen;
+	} else {
+		memset(ihdr, 0, sizeof(*ihdr));
+
+		/* Put the basename of proc in the header. */
+		strncpy(ihdr->name, basename(proc), IM_NAME_MAX);
+
+		/* Read the header. */
+		n= fread(phdr, sizeof(char), A_MINHDR, procf);
+		if (ferror(procf)) fatal(proc);
+	}
+
+	if (n < A_MINHDR || BADMAG(*phdr)) {
+		fprintf(stderr, "installboot: %s is not an executable\n", proc);
+		exit(1);
+	}
+
+	/* Get the rest of the exec header. */
+	if (procf != nil) {
+		bread(procf, proc, ((char *) phdr) + A_MINHDR,
+						phdr->a_hdrlen - A_MINHDR);
+	}
+
+	if (talk && !banner) {
+		printf("     text     data      bss      size\n");
+		banner= 1;
+	}
+
+	if (talk) {
+		printf(" %8ld %8ld %8ld %9ld  %s\n",
+			phdr->a_text, phdr->a_data, phdr->a_bss,
+			phdr->a_text + phdr->a_data + phdr->a_bss, proc);
+	}
+	total_text+= phdr->a_text;
+	total_data+= phdr->a_data;
+	total_bss+= phdr->a_bss;
+
+	if (phdr->a_cpu == A_I8086) {
+		long data= phdr->a_data + phdr->a_bss;
+
+		if (!(phdr->a_flags & A_SEP)) data+= phdr->a_text;
+
+		if (phdr->a_text >= 65536) big|= 1;
+		if (data >= 65536) big|= 2;
+	}
+	if (big) {
+		fprintf(stderr,
+			"%s will crash, %s%s%s segment%s larger then 64K\n",
+			proc,
+			big & 1 ? "text" : "",
+			big == 3 ? " and " : "",
+			big & 2 ? "data" : "",
+			big == 3 ? "s are" : " is");
+	}
+}
+
+void padimage(char *image, FILE *imagef, int n)
+/* Add n zeros to image to pad it to a sector boundary. */
+{
+	while (n > 0) {
+		if (putc(0, imagef) == EOF) fatal(image);
+		n--;
+	}
+}
+
+#define align(n)	(((n) + ((SECTOR_SIZE) - 1)) & ~((SECTOR_SIZE) - 1))
+
+void copyexec(char *proc, FILE *procf, char *image, FILE *imagef, long n)
+/* Copy n bytes from proc to image padded to fill a sector. */
+{
+	int pad, c;
+
+	/* Compute number of padding bytes. */
+	pad= align(n) - n;
+
+	while (n > 0) {
+		if ((c= getc(procf)) == EOF) {
+			if (ferror(procf)) fatal(proc);
+			fprintf(stderr,	"installboot: premature EOF on %s\n",
+									proc);
+			exit(1);
+		}
+		if (putc(c, imagef) == EOF) fatal(image);
+		n--;
+	}
+	padimage(image, imagef, pad);
+}
+
+void make_image(char *image, char **procv)
+/* Collect a set of files in an image, each "segment" is nicely padded out
+ * to SECTOR_SIZE, so it may be read from disk into memory without trickery.
+ */
+{
+	FILE *imagef, *procf;
+	char *proc, *file;
+	int procn;
+	struct image_header ihdr;
+	struct exec phdr;
+	struct stat st;
+
+	making_image= 1;
+
+	if ((imagef= fopen(image, "w")) == nil) fatal(image);
+
+	for (procn= 0; (proc= *procv++) != nil; procn++) {
+		/* Remove the label from the file name. */
+		if ((file= strchr(proc, ':')) != nil) file++; else file= proc;
+
+		/* Real files please, may need to seek. */
+		if (stat(file, &st) < 0
+			|| (errno= EISDIR, !S_ISREG(st.st_mode))
+			|| (procf= fopen(file, "r")) == nil
+		) fatal(proc);
+
+		/* Read a.out header. */
+		read_header(1, proc, procf, &ihdr);
+
+		/* Scratch. */
+		phdr= ihdr.process;
+
+		/* The symbol table is always stripped off. */
+		ihdr.process.a_syms= 0;
+		ihdr.process.a_flags &= ~A_NSYM;
+
+		/* Write header padded to fill a sector */
+		bwrite(imagef, image, &ihdr, sizeof(ihdr));
+
+		padimage(image, imagef, SECTOR_SIZE - sizeof(ihdr));
+
+		/* A page aligned executable needs the header in text. */
+		if (phdr.a_flags & A_PAL) {
+			rewind(procf);
+			phdr.a_text+= phdr.a_hdrlen;
+		}
+
+		/* Copy text and data of proc to image. */
+		if (phdr.a_flags & A_SEP) {
+			/* Separate I&D: pad text & data separately. */
+
+			copyexec(proc, procf, image, imagef, phdr.a_text);
+			copyexec(proc, procf, image, imagef, phdr.a_data);
+		} else {
+			/* Common I&D: keep text and data together. */
+
+			copyexec(proc, procf, image, imagef,
+						phdr.a_text + phdr.a_data);
+		}
+
+		/* Done with proc. */
+		(void) fclose(procf);
+	}
+	/* Done with image. */
+
+	if (fclose(imagef) == EOF) fatal(image);
+
+	printf("   ------   ------   ------   -------\n");
+	printf(" %8ld %8ld %8ld %9ld  total\n",
+		total_text, total_data, total_bss,
+		total_text + total_data + total_bss);
+}
+
+void extractexec(FILE *imagef, char *image, FILE *procf, char *proc,
+						long count, off_t *alen)
+/* Copy a segment of an executable.  It is padded to a sector in image. */
+{
+	char buf[SECTOR_SIZE];
+
+	while (count > 0) {
+		bread(imagef, image, buf, sizeof(buf));
+		*alen-= sizeof(buf);
+
+		bwrite(procf, proc, buf,
+			count < sizeof(buf) ? (size_t) count : sizeof(buf));
+		count-= sizeof(buf);
+	}
+}
+
+void extract_image(char *image)
+/* Extract the executables from an image. */
+{
+	FILE *imagef, *procf;
+	off_t len;
+	struct stat st;
+	struct image_header ihdr;
+	struct exec phdr;
+	char buf[SECTOR_SIZE];
+
+	if (stat(image, &st) < 0) fatal(image);
+
+	/* Size of the image. */
+	len= S_ISREG(st.st_mode) ? st.st_size : -1;
+
+	if ((imagef= fopen(image, "r")) == nil) fatal(image);
+
+	while (len != 0) {
+		/* Extract a program, first sector is an extended header. */
+		bread(imagef, image, buf, sizeof(buf));
+		len-= sizeof(buf);
+
+		memcpy(&ihdr, buf, sizeof(ihdr));
+		phdr= ihdr.process;
+
+		/* Check header. */
+		read_header(1, ihdr.name, nil, &ihdr);
+
+		if ((procf= fopen(ihdr.name, "w")) == nil) fatal(ihdr.name);
+
+		if (phdr.a_flags & A_PAL) {
+			/* A page aligned process contains a header in text. */
+			phdr.a_text+= phdr.a_hdrlen;
+		} else {
+			bwrite(procf, ihdr.name, &ihdr.process, phdr.a_hdrlen);
+		}
+
+		/* Extract text and data segments. */
+		if (phdr.a_flags & A_SEP) {
+			extractexec(imagef, image, procf, ihdr.name,
+						phdr.a_text, &len);
+			extractexec(imagef, image, procf, ihdr.name,
+						phdr.a_data, &len);
+		} else {
+			extractexec(imagef, image, procf, ihdr.name,
+				phdr.a_text + phdr.a_data, &len);
+		}
+
+		if (fclose(procf) == EOF) fatal(ihdr.name);
+	}
+}
+
+int rawfd;	/* File descriptor to open device. */
+char *rawdev;	/* Name of device. */
+
+void readblock(off_t blk, char *buf, int block_size)
+/* For rawfs, so that it can read blocks. */
+{
+	int n;
+
+	if (lseek(rawfd, blk * block_size, SEEK_SET) < 0
+		|| (n= read(rawfd, buf, block_size)) < 0
+	) fatal(rawdev);
+
+	if (n < block_size) {
+		fprintf(stderr, "installboot: Unexpected EOF on %s\n", rawdev);
+		exit(1);
+	}
+}
+
+void writeblock(off_t blk, char *buf, int block_size)
+/* Add a function to write blocks for local use. */
+{
+	if (lseek(rawfd, blk * block_size, SEEK_SET) < 0
+		|| write(rawfd, buf, block_size) < 0
+	) fatal(rawdev);
+}
+
+int raw_install(char *file, off_t *start, off_t *len, int block_size)
+/* Copy bootcode or an image to the boot device at the given absolute disk
+ * block number.  This "raw" installation is used to place bootcode and
+ * image on a disk without a filesystem to make a simple boot disk.  Useful
+ * in automated scripts for J. Random User.
+ * Note: *len == 0 when an image is read.  It is set right afterwards.
+ */
+{
+	static char buf[_MAX_BLOCK_SIZE];	/* Nonvolatile block buffer. */
+	FILE *f;
+	off_t sec;
+	unsigned long devsize;
+	static int banner= 0;
+	struct partition entry;
+
+	/* See if the device has a maximum size. */
+	devsize= -1;
+	if (ioctl(rawfd, DIOCGETP, &entry) == 0) devsize= cv64ul(entry.size);
+
+	if ((f= fopen(file, "r")) == nil) fatal(file);
+
+	/* Copy sectors from file onto the boot device. */
+	sec= *start;
+	do {
+		int off= sec % RATIO(BOOT_BLOCK_SIZE);
+
+		if (fread(buf + off * SECTOR_SIZE, 1, SECTOR_SIZE, f) == 0)
+			break;
+
+		if (sec >= devsize) {
+			fprintf(stderr,
+			"installboot: %s can't be attached to %s\n",
+				file, rawdev);
+			return 0;
+		}
+
+		if (off == RATIO(BOOT_BLOCK_SIZE) - 1) writeblock(sec / RATIO(BOOT_BLOCK_SIZE), buf, BOOT_BLOCK_SIZE);
+	} while (++sec != *start + *len);
+
+	if (ferror(f)) fatal(file);
+	(void) fclose(f);
+
+	/* Write a partial block, this may be the last image. */
+	if (sec % RATIO(BOOT_BLOCK_SIZE) != 0) writeblock(sec / RATIO(BOOT_BLOCK_SIZE), buf, BOOT_BLOCK_SIZE);
+
+	if (!banner) {
+		printf("  sector  length\n");
+		banner= 1;
+	}
+	*len= sec - *start;
+	printf("%8ld%8ld  %s\n", *start, *len, file);
+	*start= sec;
+	return 1;
+}
+
+enum howto { FS, BOOT };
+
+void make_bootable(enum howto how, char *device, char *bootblock,
+					char *bootcode, char **imagev)
+/* Install bootblock on the bootsector of device with the disk addresses to
+ * bootcode patched into the data segment of bootblock.  "How" tells if there
+ * should or shoudn't be a file system on the disk.  The images in the imagev
+ * vector are added to the end of the device.
+ */
+{
+	char buf[_MAX_BLOCK_SIZE + 256], *adrp, *parmp;
+	struct fileaddr {
+		off_t	address;
+		int	count;
+	} bootaddr[BOOT_MAX + 1], *bap= bootaddr;
+	struct exec boothdr;
+	struct image_header dummy;
+	struct stat st;
+	ino_t ino;
+	off_t sector, max_sector;
+	FILE *bootf;
+	off_t addr, fssize, pos, len;
+	char *labels, *label, *image;
+	int nolabel;
+	int block_size = 0;
+
+	/* Open device and set variables for readblock. */
+	if ((rawfd= open(rawdev= device, O_RDWR)) < 0) fatal(device);
+
+	/* Read and check the superblock. */
+	fssize= r_super(&block_size);
+
+	switch (how) {
+	case FS:
+		if (fssize == 0) {
+			fprintf(stderr,
+				"installboot: %s is not a Minix file system\n",
+				device);
+			exit(1);
+		}
+		break;
+	case BOOT:
+		if (fssize != 0) {
+			int s;
+			printf("%s contains a file system!\n", device);
+			printf("Scribbling in 10 seconds");
+			for (s= 0; s < 10; s++) {
+				fputc('.', stdout);
+				fflush(stdout);
+				sleep(1);
+			}
+			fputc('\n', stdout);
+		}
+		fssize= 1;	/* Just a boot block. */
+	}
+
+	if (how == FS) {
+		/* See if the boot code can be found on the file system. */
+		if ((ino= r_lookup(ROOT_INO, bootcode)) == 0) {
+			if (errno != ENOENT) fatal(bootcode);
+		}
+	} else {
+		/* Boot code must be attached at the end. */
+		ino= 0;
+	}
+
+	if (ino == 0) {
+		/* For a raw installation, we need to copy the boot code onto
+		 * the device, so we need to look at the file to be copied.
+		 */
+		if (stat(bootcode, &st) < 0) fatal(bootcode);
+
+		if ((bootf= fopen(bootcode, "r")) == nil) fatal(bootcode);
+	} else {
+		/* Boot code is present in the file system. */
+		r_stat(ino, &st);
+
+		/* Get the header from the first block. */
+		if ((addr= r_vir2abs((off_t) 0)) == 0) {
+			boothdr.a_magic[0]= !A_MAGIC0;
+		} else {
+			readblock(addr, buf, block_size);
+			memcpy(&boothdr, buf, sizeof(struct exec));
+		}
+		bootf= nil;
+		dummy.process= boothdr;
+	}
+	/* See if it is an executable (read_header does the check). */
+	read_header(0, bootcode, bootf, &dummy);
+	boothdr= dummy.process;
+
+	if (bootf != nil) fclose(bootf);
+
+	/* Get all the sector addresses of the secondary boot code. */
+	max_sector= (boothdr.a_hdrlen + boothdr.a_text
+			+ boothdr.a_data + SECTOR_SIZE - 1) / SECTOR_SIZE;
+
+	if (max_sector > BOOT_MAX * RATIO(block_size)) {
+		fprintf(stderr, "installboot: %s is way too big\n", bootcode);
+		exit(0);
+	}
+
+	/* Determine the addresses to the boot code to be patched into the
+	 * boot block.
+	 */
+	bap->count= 0;	/* Trick to get the address recording going. */
+
+	for (sector= 0; sector < max_sector; sector++) {
+		if (ino == 0) {
+			addr= fssize + (sector / RATIO(block_size));
+		} else
+		if ((addr= r_vir2abs(sector / RATIO(block_size))) == 0) {
+			fprintf(stderr, "installboot: %s has holes!\n",
+								bootcode);
+			exit(1);
+		}
+		addr= (addr * RATIO(block_size)) + (sector % RATIO(block_size));
+
+		/* First address of the addresses array? */
+		if (bap->count == 0) bap->address= addr;
+
+		/* Paste sectors together in a multisector read. */
+		if (bap->address + bap->count == addr)
+			bap->count++;
+		else {
+			/* New address. */
+			bap++;
+			bap->address= addr;
+			bap->count= 1;
+		}
+	}
+	(++bap)->count= 0;	/* No more. */
+
+	/* Get the boot block and patch the pieces in. */
+	readblock(BOOTBLOCK, buf, BOOT_BLOCK_SIZE);
+
+	if ((bootf= fopen(bootblock, "r")) == nil) fatal(bootblock);
+
+	read_header(0, bootblock, bootf, &dummy);
+	boothdr= dummy.process;
+
+	if (boothdr.a_text + boothdr.a_data +
+					 4 * (bap - bootaddr) + 1 > PARTPOS) {
+		fprintf(stderr,
+	"installboot: %s + addresses to %s don't fit in the boot sector\n",
+			bootblock, bootcode);
+		fprintf(stderr,
+		    "You can try copying/reinstalling %s to defragment it\n",
+			bootcode);
+		exit(1);
+	}
+
+	/* All checks out right.  Read bootblock into the boot block! */
+	bread(bootf, bootblock, buf, boothdr.a_text + boothdr.a_data);
+	(void) fclose(bootf);
+
+	/* Patch the addresses in. */
+	adrp= buf + (int) (boothdr.a_text + boothdr.a_data);
+	for (bap= bootaddr; bap->count != 0; bap++) {
+		*adrp++= bap->count;
+		*adrp++= (bap->address >>  0) & 0xFF;
+		*adrp++= (bap->address >>  8) & 0xFF;
+		*adrp++= (bap->address >> 16) & 0xFF;
+	}
+	/* Zero count stops bootblock's reading loop. */
+	*adrp++= 0;
+
+	if (bap > bootaddr+1) {
+		printf("%s and %d addresses to %s patched into %s\n",
+			bootblock, (int)(bap - bootaddr), bootcode, device);
+	}
+
+	/* Boot block signature. */
+	buf[SIGPOS+0]= (SIGNATURE >> 0) & 0xFF;
+	buf[SIGPOS+1]= (SIGNATURE >> 8) & 0xFF;
+
+	/* Sector 2 of the boot block is used for boot parameters, initially
+	 * filled with null commands (newlines).  Initialize it only if
+	 * necessary.
+	 */
+	for (parmp= buf + SECTOR_SIZE; parmp < buf + 2*SECTOR_SIZE; parmp++) {
+		if (*imagev != nil || (control(*parmp) && *parmp != '\n')) {
+			/* Param sector must be initialized. */
+			memset(buf + SECTOR_SIZE, '\n', SECTOR_SIZE);
+			break;
+		}
+	}
+
+	/* Offset to the end of the file system to add boot code and images. */
+	pos= fssize * RATIO(block_size);
+
+	if (ino == 0) {
+		/* Place the boot code onto the boot device. */
+		len= max_sector;
+		if (!raw_install(bootcode, &pos, &len, block_size)) {
+			if (how == FS) {
+				fprintf(stderr,
+	"\t(Isn't there a copy of %s on %s that can be used?)\n",
+					bootcode, device);
+			}
+			exit(1);
+		}
+	}
+
+	parmp= buf + SECTOR_SIZE;
+	nolabel= 0;
+
+	if (how == BOOT) {
+		/* A boot only disk needs to have floppies swapped. */
+		strcpy(parmp,
+	"trailer()echo \\nInsert the root diskette then hit RETURN\\n\\w\\c\n");
+		parmp+= strlen(parmp);
+	}
+
+	while ((labels= *imagev++) != nil) {
+		/* Place each kernel image on the boot device. */
+
+		if ((image= strchr(labels, ':')) != nil)
+			*image++= 0;
+		else {
+			if (nolabel) {
+				fprintf(stderr,
+			    "installboot: Only one image can be the default\n");
+				exit(1);
+			}
+			nolabel= 1;
+			image= labels;
+			labels= nil;
+		}
+		len= 0;
+		if (!raw_install(image, &pos, &len, block_size)) exit(1);
+
+		if (labels == nil) {
+			/* Let this image be the default. */
+			sprintf(parmp, "image=%ld:%ld\n", pos-len, len);
+			parmp+= strlen(parmp);
+		}
+
+		while (labels != nil) {
+			/* Image is prefixed by a comma separated list of
+			 * labels.  Define functions to select label and image.
+			 */
+			label= labels;
+			if ((labels= strchr(labels, ',')) != nil) *labels++ = 0;
+
+			sprintf(parmp,
+		"%s(%c){label=%s;image=%ld:%ld;echo %s kernel selected;menu}\n",
+				label,
+				between('A', label[0], 'Z')
+					? label[0]-'A'+'a' : label[0],
+				label, pos-len, len, label);
+			parmp+= strlen(parmp);
+		}
+
+		if (parmp > buf + block_size) {
+			fprintf(stderr,
+		"installboot: Out of parameter space, too many images\n");
+			exit(1);
+		}
+	}
+	/* Install boot block. */
+	writeblock((off_t) BOOTBLOCK, buf, 1024);
+
+	if (pos > fssize * RATIO(block_size)) {
+		/* Tell the total size of the data on the device. */
+		printf("%16ld  (%ld kb) total\n", pos,
+						(pos + RATIO(block_size) - 1) / RATIO(block_size));
+	}
+}
+
+void install_master(char *device, char *masterboot, char **guide)
+/* Booting a hard disk is a two stage process:  The master bootstrap in sector
+ * 0 loads the bootstrap from sector 0 of the active partition which in turn
+ * starts the operating system.  This code installs such a master bootstrap
+ * on a hard disk.  If guide[0] is non-null then the master bootstrap is
+ * guided into booting a certain device.
+ */
+{
+	FILE *masf;
+	unsigned long size;
+	struct stat st;
+	static char buf[_MAX_BLOCK_SIZE];
+
+	/* Open device. */
+	if ((rawfd= open(rawdev= device, O_RDWR)) < 0) fatal(device);
+
+	/* Open the master boot code. */
+	if ((masf= fopen(masterboot, "r")) == nil) fatal(masterboot);
+
+	/* See if the user is cloning a device. */
+	if (fstat(fileno(masf), &st) >=0 && S_ISBLK(st.st_mode))
+		size= PARTPOS;
+	else {
+		/* Read and check header otherwise. */
+		struct image_header ihdr;
+
+		read_header(1, masterboot, masf, &ihdr);
+		size= ihdr.process.a_text + ihdr.process.a_data;
+	}
+	if (size > PARTPOS) {
+		fprintf(stderr, "installboot: %s is too big\n", masterboot);
+		exit(1);
+	}
+
+	/* Read the master boot block, patch it, write. */
+	readblock(BOOTBLOCK, buf, BOOT_BLOCK_SIZE);
+
+	memset(buf, 0, PARTPOS);
+	(void) bread(masf, masterboot, buf, size);
+
+	if (guide[0] != nil) {
+		/* Fixate partition to boot. */
+		char *keys= guide[0];
+		char *logical= guide[1];
+		size_t i;
+		int logfd;
+		u32_t offset;
+		struct partition geometry;
+
+		/* A string of digits to be seen as keystrokes. */
+		i= 0;
+		do {
+			if (!between('0', keys[i], '9')) {
+				fprintf(stderr,
+					"installboot: bad guide keys '%s'\n",
+					keys);
+				exit(1);
+			}
+		} while (keys[++i] != 0);
+
+		if (size + i + 1 > PARTPOS) {
+			fprintf(stderr,
+			"installboot: not enough space after '%s' for '%s'\n",
+				masterboot, keys);
+			exit(1);
+		}
+		memcpy(buf + size, keys, i);
+		size += i;
+		buf[size]= '\r';
+
+		if (logical != nil) {
+			if ((logfd= open(logical, O_RDONLY)) < 0
+				|| ioctl(logfd, DIOCGETP, &geometry) < 0
+			) {
+				fatal(logical);
+			}
+			offset= div64u(geometry.base, SECTOR_SIZE);
+			if (size + 5 > PARTPOS) {
+				fprintf(stderr,
+					"installboot: not enough space "
+					"after '%s' for '%s' and an offset "
+					"to '%s'\n",
+					masterboot, keys, logical);
+				exit(1);
+			}
+			buf[size]= '#';
+			memcpy(buf+size+1, &offset, 4);
+		}
+	}
+
+	/* Install signature. */
+	buf[SIGPOS+0]= (SIGNATURE >> 0) & 0xFF;
+	buf[SIGPOS+1]= (SIGNATURE >> 8) & 0xFF;
+
+	writeblock(BOOTBLOCK, buf, BOOT_BLOCK_SIZE);
+}
+
+void usage(void)
+{
+	fprintf(stderr,
+	  "Usage: installboot -i(mage) image kernel mm fs ... init\n"
+	  "       installboot -(e)x(tract) image\n"
+	  "       installboot -d(evice) device bootblock boot [image ...]\n"
+	  "       installboot -b(oot) device bootblock boot image ...\n"
+	  "       installboot -m(aster) device masterboot [keys [logical]]\n");
+	exit(1);
+}
+
+int isoption(char *option, char *test)
+/* Check if the option argument is equals "test".  Also accept -i as short
+ * for -image, and the special case -x for -extract.
+ */
+{
+	if (strcmp(option, test) == 0) return 1;
+	if (option[0] != '-' && strlen(option) != 2) return 0;
+	if (option[1] == test[1]) return 1;
+	if (option[1] == 'x' && test[1] == 'e') return 1;
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	if (argc < 2) usage();
+
+	if (argc >= 4 && isoption(argv[1], "-image")) {
+		make_image(argv[2], argv + 3);
+	} else
+	if (argc == 3 && isoption(argv[1], "-extract")) {
+		extract_image(argv[2]);
+	} else
+	if (argc >= 5 && isoption(argv[1], "-device")) {
+		make_bootable(FS, argv[2], argv[3], argv[4], argv + 5);
+	} else
+	if (argc >= 6 && isoption(argv[1], "-boot")) {
+		make_bootable(BOOT, argv[2], argv[3], argv[4], argv + 5);
+	} else
+	if ((4 <= argc && argc <= 6) && isoption(argv[1], "-master")) {
+		install_master(argv[2], argv[3], argv + 4);
+	} else {
+		usage();
+	}
+	exit(0);
+}
+
+/*
+ * $PchId: installboot.c,v 1.10 2000/08/13 22:07:50 philip Exp $
+ */
Index: /trunk/minix/boot/jumpboot.s
===================================================================
--- /trunk/minix/boot/jumpboot.s	(revision 9)
+++ /trunk/minix/boot/jumpboot.s	(revision 9)
@@ -0,0 +1,261 @@
+!	jumpboot 1.0 - Jump to another bootstrap	Author: Kees J. Bot
+!								14 Apr 1999
+!
+! This code may be placed into any free boot sector, like the first sector
+! of an extended partition, a file system partition other than the root,
+! or even the master bootstrap.  It will load and run another bootstrap whose
+! disk, partition, and slice number (not necessarily all three) are patched
+! into this code by installboot.  If the ALT key is held down when this code
+! is booted then you can type the disk, partition, and slice numbers manually.
+! The manual interface is default if no numbers are patched in by installboot.
+!
+
+	o32	   =	  0x66	! This assembler doesn't know 386 extensions
+	LOADOFF	   =	0x7C00	! 0x0000:LOADOFF is where this code is loaded
+	BUFFER	   =	0x0600	! First free memory
+	PART_TABLE =	   446	! Location of partition table within master
+	PENTRYSIZE =	    16	! Size of one partition table entry
+	MAGIC	   =	   510	! Location of the AA55 magic number
+
+	! <ibm/partition.h>:
+	MINIX_PART =	  0x81
+	sysind	   =	     4
+	lowsec	   =	     8
+
+
+.text
+
+! Find and load another bootstrap and jump to it.
+jumpboot:
+	xor	ax, ax
+	mov	ds, ax
+	mov	es, ax
+	cli
+	mov	ss, ax			! ds = es = ss = Vector segment
+	mov	sp, #LOADOFF
+	sti
+
+! Move this code to safety, then jump to it.
+	mov	si, sp			! si = start of this code
+	mov	di, #BUFFER		! di = Buffer area
+	mov	cx, #512/2		! One sector
+	cld
+  rep	movs
+	jmpf	BUFFER+migrate, 0	! To safety
+migrate:
+
+	mov	bp, #BUFFER+guide	! Patched guiding characters
+altkey:
+	movb	ah, #0x02		! Keyboard shift status
+	int	0x16
+	testb	al, #0x08		! Bit 3 = ALT key
+	jz	noalt			! ALT key pressed?
+again:
+	mov	bp, #zero		! Ignore patched stuff
+noalt:
+
+! Follow guide characters to find the boot partition.
+	call	print
+	.ascii	"d?\b\0"		! Initial greeting
+
+! Disk number?
+disk:
+	movb	dl, #0x80 - 0x30	! Prepare to add an ASCII digit
+	call	getch			! Get number to tell which disk
+	addb	dl, al			! dl = 0x80 + (al - '0')
+	jns	n0nboot			! Result should be >= 0x80
+	mov	si, #BUFFER+zero-lowsec	! si = where lowsec(si) is zero
+	cmpb	(bp), #0x23		! Next guide character is '#'?
+	jne	notlogical
+	lea	si, 1-lowsec(bp)	! Logical sector offset follows '#'
+notlogical:
+	call	load			! Load chosen sector of chosen disk
+	cmpb	(bp), #0x23
+	je	boot			! Run bootstrap if a logical is chosen
+
+	call	print			! Intro to partition number
+	.ascii	"p?\b\0"
+
+part:
+	call	getch			! Get character to tell partition
+	call	gettable		! Get partition table
+	call	sort			! Sort partition table
+	call	choose_load		! Compute chosen entry and load
+
+	cmpb	sysind(si), #MINIX_PART	! Minix subpartition table possible?
+	jne	waitboot
+
+	call	print			! Intro to slice number
+	.ascii	"s?\b\0"
+
+slice:
+	call	getch			! Get character to tell slice
+	call	gettable		! Get partition table
+	call	choose_load		! Compute chosen entry and load
+
+waitboot:
+	call	print			! Intro to nothing
+	.ascii	" ?\b\0"
+	call	getch			! Supposed to type RETURN now
+n0nboot:jmp	nonboot			! Sorry, can't go further
+
+! Get a character, either the patched-in, or one from the keyboard.
+getch:
+	movb	al, (bp)	! Get patched-in character
+	testb	al, al
+	jz	getkey
+	inc	bp
+	jmp	gotkey
+getkey:	xorb	ah, ah		! Wait for keypress
+	int	0x16
+gotkey:	testb	dl, dl		! Ignore CR if disk number not yet set
+	jns	putch
+	cmpb	al, #0x0D	! Carriage return?
+	je	boot
+	!jmp	putch
+
+! Print a character
+putch:	movb	ah, #0x0E	! Print character in teletype mode
+	mov	bx, #0x0001	! Page 0, foreground color
+	int	0x10
+	ret
+
+! Print a message.
+print:	mov	cx, si		! Save si
+	pop	si		! si = String following 'call print'
+prnext:	lodsb			! al = *si++ is char to be printed
+	testb	al, al		! Null marks end
+	jz	prdone
+	call	putch
+	jmp	prnext
+prdone:	xchg	si, cx		! Restore si
+	jmp	(cx)		! Continue after the string
+
+! Return typed (or in patched data) means to run the bootstrap now in core!
+boot:
+	call	print		! Make line on screen look proper
+	.ascii	"\b  \r\n\0"
+	jmp	LOADOFF-BUFFER	! Jump to LOADOFF
+
+! Compute address of chosen partition entry from choice al into si, then
+! continue to load the boot sector of that partition.
+choose_load:
+	subb	al, #0x30		! al -= '0'
+	cmpb	al, #4			! Only four partitions
+	ja	n0nboot
+	movb	ah, #PENTRYSIZE
+	mulb	ah			! al *= PENTRYSIZE
+	add	ax, #BUFFER+PART_TABLE
+	mov	si, ax			! si = &part_table[al - '0']
+	movb	al, sysind(si)		! System indicator
+	testb	al, al			! Unused partition?
+	jz	n0nboot
+	!jmp	load			! Continue to load boot sector
+
+! Load boot sector of the current partition.
+load:
+	push	dx		! Save drive code
+	push	es		! Next call sets es
+	movb	ah, #0x08	! Code for drive parameters
+	int	0x13
+	pop	es
+	andb	cl, #0x3F	! cl = max sector number (1-origin)
+	incb	dh		! dh = 1 + max head number (0-origin)
+	movb	al, cl		! al = cl = sectors per track
+	mulb	dh		! dh = heads, ax = heads * sectors
+	mov	bx, ax		! bx = sectors per cylinder = heads * sectors
+	mov	ax, lowsec+0(si)
+	mov	dx, lowsec+2(si) ! dx:ax = sector within drive
+	cmp	dx, #[1024*255*63-255]>>16  ! Near 8G limit?
+	jae	bigdisk
+	div	bx		! ax = cylinder, dx = sector within cylinder
+	xchg	ax, dx		! ax = sector within cylinder, dx = cylinder
+	movb	ch, dl		! ch = low 8 bits of cylinder
+	divb	cl		! al = head, ah = sector (0-origin)
+	xorb	dl, dl		! About to shift bits 8-9 of cylinder into dl
+	shr	dx, #1
+	shr	dx, #1		! dl[6..7] = high cylinder
+	orb	dl, ah		! dl[0..5] = sector (0-origin)
+	movb	cl, dl		! cl[0..5] = sector, cl[6..7] = high cyl
+	incb	cl		! cl[0..5] = sector (1-origin)
+	pop	dx		! Restore drive code in dl
+	movb	dh, al		! dh = al = head
+	mov	bx, #LOADOFF	! es:bx = where sector is loaded
+	mov	ax, #0x0201	! ah = Code for read / al = one sector
+	int	0x13
+	jmp	rdeval		! Evaluate read result
+bigdisk:
+	mov	bx, dx		! bx:ax = dx:ax = sector to read
+	pop	dx		! Restore drive code in dl
+	push	si		! Save si
+	mov	si, #BUFFER+ext_rw ! si = extended read/write parameter packet
+	mov	8(si), ax	! Starting block number = bx:ax
+	mov	10(si), bx
+	movb	ah, #0x42	! Extended read
+	int	0x13
+	pop	si		! Restore si to point to partition entry
+	!jmp	rdeval
+rdeval:
+	jnc	rdok
+rderr:
+	call	print
+	.ascii	"\r\nRead error\r\n\0"
+	jmp	again
+rdok:
+	cmp	LOADOFF+MAGIC, #0xAA55
+	je	sigok		! Signature ok?
+nonboot:
+	call	print
+	.ascii	"\r\nNot bootable\r\n\0"
+	jmp	again
+sigok:
+	ret
+
+! Get the partition table into my space.
+gettable:
+	mov	si, #LOADOFF+PART_TABLE
+	mov	di, #BUFFER+PART_TABLE
+	mov	cx, #4*PENTRYSIZE/2
+  rep	movs
+	ret
+
+! Sort the partition table.
+sort:
+	mov	cx, #4			! Four times is enough to sort
+bubble:	mov	si, #BUFFER+PART_TABLE	! First table entry
+bubble1:lea	di, PENTRYSIZE(si)	! Next entry
+	cmpb	sysind(si), ch		! Partition type, nonzero when in use
+	jz	exchg			! Unused entries sort to the end
+inuse:	mov	bx, lowsec+0(di)
+	sub	bx, lowsec+0(si)	! Compute di->lowsec - si->lowsec
+	mov	bx, lowsec+2(di)
+	sbb	bx, lowsec+2(si)
+	jae	order			! In order if si->lowsec <= di->lowsec
+exchg:	movb	bl, (si)
+	xchgb	bl, PENTRYSIZE(si)	! Exchange entries byte by byte
+	movb	(si), bl
+	inc	si
+	cmp	si, di
+	jb	exchg
+order:	mov	si, di
+	cmp	si, #BUFFER+PART_TABLE+3*PENTRYSIZE
+	jb	bubble1
+	loop	bubble
+	ret
+
+.data
+
+! Extended read/write commands require a parameter packet.
+ext_rw:
+	.data1	0x10		! Length of extended r/w packet
+	.data1	0		! Reserved
+	.data2	1		! Blocks to transfer (just one)
+	.data2	LOADOFF		! Buffer address offset
+	.data2	0		! Buffer address segment
+	.data4	0		! Starting block number low 32 bits (tbfi)
+zero:	.data4	0		! Starting block number high 32 bits
+
+	.align	2
+guide:
+! Guide characters and possibly a logical partition number patched here by
+! installboot, up to 6 bytes maximum.
Index: /trunk/minix/boot/masterboot.s
===================================================================
--- /trunk/minix/boot/masterboot.s	(revision 9)
+++ /trunk/minix/boot/masterboot.s	(revision 9)
@@ -0,0 +1,218 @@
+!	masterboot 2.0 - Master boot block code		Author: Kees J. Bot
+!
+! This code may be placed in the first sector (the boot sector) of a floppy,
+! hard disk or hard disk primary partition.  There it will perform the
+! following actions at boot time:
+!
+! - If the booted device is a hard disk and one of the partitions is active
+!   then the active partition is booted.
+!
+! - Otherwise the next floppy or hard disk device is booted, trying them one
+!   by one.
+!
+! To make things a little clearer, the boot path might be:
+!	/dev/fd0	- Floppy disk containing data, tries fd1 then d0
+!	[/dev/fd1]	- Drive empty
+!	/dev/c0d0	- Master boot block, selects active partition 2
+!	/dev/c0d0p2	- Submaster, selects active subpartition 0
+!	/dev/c0d0p2s0	- Minix bootblock, reads Boot Monitor /boot
+!	Minix		- Started by /boot from a kernel image in /minix
+
+	LOADOFF	   =	0x7C00	! 0x0000:LOADOFF is where this code is loaded
+	BUFFER	   =	0x0600	! First free memory
+	PART_TABLE =	   446	! Location of partition table within this code
+	PENTRYSIZE =	    16	! Size of one partition table entry
+	MAGIC	   =	   510	! Location of the AA55 magic number
+
+	! <ibm/partition>.h:
+	bootind	   =	     0
+	sysind	   =	     4
+	lowsec	   =	     8
+
+
+.text
+
+! Find active (sub)partition, load its first sector, run it.
+
+master:
+	xor	ax, ax
+	mov	ds, ax
+	mov	es, ax
+	cli
+	mov	ss, ax			! ds = es = ss = Vector segment
+	mov	sp, #LOADOFF
+	sti
+
+! Copy this code to safety, then jump to it.
+	mov	si, sp			! si = start of this code
+	push	si			! Also where we'll return to eventually
+	mov	di, #BUFFER		! Buffer area
+	mov	cx, #512/2		! One sector
+	cld
+  rep	movs
+	jmpf	BUFFER+migrate, 0	! To safety
+migrate:
+
+! Find the active partition
+findactive:
+	testb	dl, dl
+	jns	nextdisk		! No bootable partitions on floppies
+	mov	si, #BUFFER+PART_TABLE
+find:	cmpb	sysind(si), #0		! Partition type, nonzero when in use
+	jz	nextpart
+	testb	bootind(si), #0x80	! Active partition flag in bit 7
+	jz	nextpart		! It's not active
+loadpart:
+	call	load			! Load partition bootstrap
+	jc	error1			! Not supposed to fail
+bootstrap:
+	ret				! Jump to the master bootstrap
+nextpart:
+	add	si, #PENTRYSIZE
+	cmp	si, #BUFFER+PART_TABLE+4*PENTRYSIZE
+	jb	find
+! No active partition, tell 'em
+	call	print
+	.ascii	"No active partition\0"
+	jmp	reboot
+
+! There are no active partitions on this drive, try the next drive.
+nextdisk:
+	incb	dl			! Increment dl for the next drive
+	testb	dl, dl
+	js	nexthd			! Hard disk if negative
+	int	0x11			! Get equipment configuration
+	shl	ax, #1			! Highest floppy drive # in bits 6-7
+	shl	ax, #1			! Now in bits 0-1 of ah
+	andb	ah, #0x03		! Extract bits
+	cmpb	dl, ah			! Must be dl <= ah for drive to exist
+	ja	nextdisk		! Otherwise try disk 0 eventually
+	call	load0			! Read the next floppy bootstrap
+	jc	nextdisk		! It failed, next disk please
+	ret				! Jump to the next master bootstrap
+nexthd:	call	load0			! Read the hard disk bootstrap
+error1:	jc	error			! No disk?
+	ret
+
+
+! Load sector 0 from the current device.  It's either a floppy bootstrap or
+! a hard disk master bootstrap.
+load0:
+	mov	si, #BUFFER+zero-lowsec	! si = where lowsec(si) is zero
+	!jmp	load
+
+! Load sector lowsec(si) from the current device.  The obvious head, sector,
+! and cylinder numbers are ignored in favour of the more trustworthy absolute
+! start of partition.
+load:
+	mov	di, #3		! Three retries for floppy spinup
+retry:	push	dx		! Save drive code
+	push	es
+	push	di		! Next call destroys es and di
+	movb	ah, #0x08	! Code for drive parameters
+	int	0x13
+	pop	di
+	pop	es
+	andb	cl, #0x3F	! cl = max sector number (1-origin)
+	incb	dh		! dh = 1 + max head number (0-origin)
+	movb	al, cl		! al = cl = sectors per track
+	mulb	dh		! dh = heads, ax = heads * sectors
+	mov	bx, ax		! bx = sectors per cylinder = heads * sectors
+	mov	ax, lowsec+0(si)
+	mov	dx, lowsec+2(si)! dx:ax = sector within drive
+	cmp	dx, #[1024*255*63-255]>>16  ! Near 8G limit?
+	jae	bigdisk
+	div	bx		! ax = cylinder, dx = sector within cylinder
+	xchg	ax, dx		! ax = sector within cylinder, dx = cylinder
+	movb	ch, dl		! ch = low 8 bits of cylinder
+	divb	cl		! al = head, ah = sector (0-origin)
+	xorb	dl, dl		! About to shift bits 8-9 of cylinder into dl
+	shr	dx, #1
+	shr	dx, #1		! dl[6..7] = high cylinder
+	orb	dl, ah		! dl[0..5] = sector (0-origin)
+	movb	cl, dl		! cl[0..5] = sector, cl[6..7] = high cyl
+	incb	cl		! cl[0..5] = sector (1-origin)
+	pop	dx		! Restore drive code in dl
+	movb	dh, al		! dh = al = head
+	mov	bx, #LOADOFF	! es:bx = where sector is loaded
+	mov	ax, #0x0201	! Code for read, just one sector
+	int	0x13		! Call the BIOS for a read
+	jmp	rdeval		! Evaluate read result
+bigdisk:
+	mov	bx, dx		! bx:ax = dx:ax = sector to read
+	pop	dx		! Restore drive code in dl
+	push	si		! Save si
+	mov	si, #BUFFER+ext_rw ! si = extended read/write parameter packet
+	mov	8(si), ax	! Starting block number = bx:ax
+	mov	10(si), bx
+	movb	ah, #0x42	! Extended read
+	int	0x13
+	pop	si		! Restore si to point to partition entry
+	!jmp	rdeval
+rdeval:
+	jnc	rdok		! Read succeeded
+	cmpb	ah, #0x80	! Disk timed out?  (Floppy drive empty)
+	je	rdbad
+	dec	di
+	jl	rdbad		! Retry count expired
+	xorb	ah, ah
+	int	0x13		! Reset
+	jnc	retry		! Try again
+rdbad:	stc			! Set carry flag
+	ret
+rdok:	cmp	LOADOFF+MAGIC, #0xAA55
+	jne	nosig		! Error if signature wrong
+	ret			! Return with carry still clear
+nosig:	call	print
+	.ascii	"Not bootable\0"
+	jmp	reboot
+
+! A read error occurred, complain and hang
+error:
+	mov	si, #LOADOFF+errno+1
+prnum:	movb	al, ah		! Error number in ah
+	andb	al, #0x0F	! Low 4 bits
+	cmpb	al, #10		! A-F?
+	jb	digit		! 0-9!
+	addb	al, #7		! 'A' - ':'
+digit:	addb	(si), al	! Modify '0' in string
+	dec	si
+	movb	cl, #4		! Next 4 bits
+	shrb	ah, cl
+	jnz	prnum		! Again if digit > 0
+	call	print
+	.ascii	"Read error "
+errno:	.ascii	"00\0"
+	!jmp	reboot
+
+reboot:
+	call	print
+	.ascii	".  Hit any key to reboot.\0"
+	xorb	ah, ah		! Wait for keypress
+	int	0x16
+	call	print
+	.ascii	"\r\n\0"
+	int	0x19
+
+! Print a message.
+print:	pop	si		! si = String following 'call print'
+prnext:	lodsb			! al = *si++ is char to be printed
+	testb	al, al		! Null marks end
+	jz	prdone
+	movb	ah, #0x0E	! Print character in teletype mode
+	mov	bx, #0x0001	! Page 0, foreground color
+	int	0x10
+	jmp	prnext
+prdone:	jmp	(si)		! Continue after the string
+
+.data
+
+! Extended read/write commands require a parameter packet.
+ext_rw:
+	.data1	0x10		! Length of extended r/w packet
+	.data1	0		! Reserved
+	.data2	1		! Blocks to transfer (just one)
+	.data2	LOADOFF		! Buffer address offset
+	.data2	0		! Buffer address segment
+	.data4	0		! Starting block number low 32 bits (tbfi)
+zero:	.data4	0		! Starting block number high 32 bits
Index: /trunk/minix/boot/mkfhead.s
===================================================================
--- /trunk/minix/boot/mkfhead.s	(revision 9)
+++ /trunk/minix/boot/mkfhead.s	(revision 9)
@@ -0,0 +1,137 @@
+!	Mkfhead.s - DOS & BIOS support for mkfile.c	Author: Kees J. Bot
+!								9 May 1998
+!
+! This file contains the startup and low level support for the MKFILE.COM
+! utility.  See doshead.ack.s for more comments on .COM files.
+!
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+
+.define _PSP
+_PSP:
+	.space	256			! Program Segment Prefix
+
+mkfile:
+	cld				! C compiler wants UP
+	xor	ax, ax			! Zero
+	mov	di, _edata		! Start of bss is at end of data
+	mov	cx, _end		! End of bss (begin of heap)
+	sub	cx, di			! Number of bss bytes
+	shr	cx, 1			! Number of words
+ rep	stos				! Clear bss
+
+	xor	cx, cx			! cx = argc
+	xor	bx, bx
+	push	bx			! argv[argc] = NULL
+	movb	bl, (_PSP+0x80)		! Argument byte count
+0:	movb	_PSP+0x81(bx), ch	! Null terminate
+	dec	bx
+	js	9f
+	cmpb	_PSP+0x81(bx), 0x20	! Whitespace?
+	jbe	0b
+1:	dec	bx			! One argument character
+	js	2f
+	cmpb	_PSP+0x81(bx), 0x20	! More argument characters?
+	ja	1b
+2:	lea	ax, _PSP+0x81+1(bx)	! Address of argument
+	push	ax			! argv[n]
+	inc	cx			! argc++;
+	test	bx, bx
+	jns	0b			! More arguments?
+9:	movb	_PSP+0x81(bx), ch	! Make a null string
+	lea	ax, _PSP+0x81(bx)
+	push	ax			! to use as argv[0]
+	inc	cx			! Final value of argc
+	mov	ax, sp
+	push	ax			! argv
+	push	cx			! argc
+	call	_main			! main(argc, argv)
+	push	ax
+	call	_exit			! exit(main(argc, argv))
+
+! int creat(const char *path, mode_t mode)
+!	Create a file with the old creat() call.
+.define _creat
+_creat:
+	mov	bx, sp
+	mov	dx, 2(bx)		! Filename
+	xor	cx, cx			! Ignore mode, always read-write
+	movb	ah, 0x3C		! "CREAT"
+dos:	int	0x21			! ax = creat(path, 0666);
+	jc	seterrno
+	ret
+
+seterrno:
+	mov	(_errno), ax		! Set errno to the DOS error code
+	mov	ax, -1
+	cwd				! return -1L;
+	ret
+
+! int open(const char *path, int oflag)
+!	Open a file with the oldfashioned two-argument open() call.
+.define _open
+_open:
+	mov	bx, sp
+	mov	dx, 2(bx)		! Filename
+	movb	al, 4(bx)		! O_RDONLY, O_WRONLY, O_RDWR
+	movb	ah, 0x3D		! "OPEN"
+	jmp	dos
+
+! int close(int fd)
+!	Close an open file.
+.define _close
+_close:
+	mov	bx, sp
+	mov	bx, 2(bx)		! bx = file handle
+	movb	ah, 0x3E		! "CLOSE"
+	jmp	dos
+
+! void exit(int status)
+! void _exit(int status)
+!	Return to DOS.
+.define _exit, __exit, ___exit
+_exit:
+__exit:
+___exit:
+	pop	ax
+	pop	ax			! al = status
+	movb	ah, 0x4C		! "EXIT"
+	int	0x21
+	hlt
+
+! ssize_t read(int fd, void *buf, size_t n)
+!	Read bytes from an open file.
+.define _read
+_read:
+	mov	bx, sp
+	mov	cx, 6(bx)
+	mov	dx, 4(bx)
+	mov	bx, 2(bx)
+	movb	ah, 0x3F		! "READ"
+	jmp	dos
+
+! ssize_t write(int fd, const void *buf, size_t n)
+!	Write bytes to an open file.
+.define _write
+_write:
+	mov	bx, sp
+	mov	cx, 6(bx)
+	mov	dx, 4(bx)
+	mov	bx, 2(bx)
+	movb	ah, 0x40		! "WRITE"
+	jmp	dos
+
+! off_t lseek(int fd, off_t offset, int whence)
+!	Set file position for read or write.
+.define _lseek
+_lseek:
+	mov	bx, sp
+	movb	al, 8(bx)		! SEEK_SET, SEEK_CUR, SEEK_END
+	mov	dx, 4(bx)
+	mov	cx, 6(bx)		! cx:dx = offset
+	mov	bx, 2(bx)
+	movb	ah, 0x42		! "LSEEK"
+	jmp	dos
+
+!
+! $PchId: mkfhead.ack.s,v 1.3 1999/01/14 21:17:06 philip Exp $
Index: /trunk/minix/boot/mkfile.c
===================================================================
--- /trunk/minix/boot/mkfile.c	(revision 9)
+++ /trunk/minix/boot/mkfile.c	(revision 9)
@@ -0,0 +1,180 @@
+/*	mkfile 1.0 - create a file under DOS for use as a Minix "disk".
+ *							Author: Kees J. Bot
+ *								9 May 1998
+ */
+#define nil 0
+#include <sys/types.h>
+#include <string.h>
+#include <limits.h>
+
+/* Stuff normally found in <unistd.h>, <errno.h>, etc. */
+extern int errno;
+int creat(const char *file, int mode);
+int open(const char *file, int oflag);
+off_t lseek(int fd, off_t offset, int whence);
+ssize_t write(int fd, const char *buf, size_t len);
+void exit(int status);
+int printf(const char *fmt, ...);
+
+#define O_WRONLY	1
+#define SEEK_SET	0
+#define SEEK_END	2
+
+/* Kernel printf requires a putk() function. */
+int putk(int c)
+{
+	char ch = c;
+
+	if (c == 0) return;
+	if (c == '\n') putk('\r');
+	(void) write(2, &ch, 1);
+}
+
+static void usage(void)
+{
+	printf("Usage: mkfile <size>[gmk] <file>\n"
+		"(Example sizes, all 50 meg: 52428800, 51200k, 50m)\n");
+	exit(1);
+}
+
+char *strerror(int err)
+/* Translate some DOS error numbers to text. */
+{
+	static struct errlist {
+		int	err;
+		char	*what;
+	} errlist[] = {
+		{  0, "No error" },
+		{  1, "Function number invalid" },
+		{  2, "File not found" },
+		{  3, "Path not found" },
+		{  4, "Too many open files" },
+		{  5, "Access denied" },
+		{  6, "Invalid handle" },
+		{ 12, "Access code invalid" },
+		{ 39, "Insufficient disk space" },
+	};
+	struct errlist *ep;
+	static char unknown[]= "Error 65535";
+	unsigned e;
+	char *p;
+
+	for (ep= errlist; ep < errlist + sizeof(errlist)/sizeof(errlist[0]);
+									ep++) {
+		if (ep->err == err) return ep->what;
+	}
+	p= unknown + sizeof(unknown) - 1;
+	e= err;
+	do *--p= '0' + (e % 10); while ((e /= 10) > 0);
+	strcpy(unknown + 6, p);
+	return unknown;
+}
+
+int main(int argc, char **argv)
+{
+	int i;
+	static char buf[512];
+	unsigned long size, mul;
+	off_t offset;
+	char *cp;
+	int fd;
+	char *file;
+
+	if (argc != 3) usage();
+
+	cp= argv[1];
+	size= 0;
+	while ((unsigned) (*cp - '0') < 10) {
+		unsigned d= *cp++ - '0';
+		if (size <= (ULONG_MAX-9) / 10) {
+			size= size * 10 + d;
+		} else {
+			size= ULONG_MAX;
+		}
+	}
+	if (cp == argv[1]) usage();
+	while (*cp != 0) {
+		mul = 1;
+		switch (*cp++) {
+		case 'G':
+		case 'g':	mul *= 1024;
+		case 'M':
+		case 'm':	mul *= 1024;
+		case 'K':
+		case 'k':	mul *= 1024;
+		case 'B':
+		case 'b':	break;
+		default:	usage();
+		}
+		if (size <= ULONG_MAX / mul) {
+			size *= mul;
+		} else {
+			size= ULONG_MAX;
+		}
+	}
+
+	if (size > 1024L*1024*1024) {
+		printf("mkfile: A file size over 1G is a bit too much\n");
+		exit(1);
+	}
+
+	/* Open existing file, or create a new file. */
+	file= argv[2];
+	if ((fd= open(file, O_WRONLY)) < 0) {
+		if (errno == 2) {
+			fd= creat(file, 0666);
+		}
+	}
+	if (fd < 0) {
+		printf("mkfile: Can't open %s: %s\n", file, strerror(errno));
+		exit(1);
+	}
+
+	/* How big is the file now? */
+	if ((offset= lseek(fd, 0, SEEK_END)) == -1) {
+		printf("mkfile: Can't seek in %s: %s\n", file, strerror(errno));
+		exit(1);
+	}
+
+	if (offset == 0 && size == 0) exit(0);	/* Huh? */
+
+	/* Write the first bit if the file is zero length.  This is necessary
+	 * to circumvent a DOS bug by extending a new file by lseek.  We also
+	 * want to make sure there are zeros in the first sector.
+	 */
+	if (offset == 0) {
+		if (write(fd, buf, sizeof(buf)) == -1) {
+			printf("mkfile: Can't write to %s: %s\n",
+				file, strerror(errno));
+			exit(1);
+		}
+	}
+
+	/* Seek to the required size and write 0 bytes to extend/truncate the
+	 * file to that size.
+	 */
+	if (lseek(fd, size, SEEK_SET) == -1) {
+		printf("mkfile: Can't seek in %s: %s\n", file, strerror(errno));
+		exit(1);
+	}
+	if (write(fd, buf, 0) == -1) {
+		printf("mkfile: Can't write to %s: %s\n",
+			file, strerror(errno));
+		exit(1);
+	}
+
+	/* Did the file become the required size? */
+	if ((offset= lseek(fd, 0, SEEK_END)) == -1) {
+		printf("mkfile: Can't seek in %s: %s\n", file, strerror(errno));
+		exit(1);
+	}
+	if (offset != size) {
+		printf("mkfile: Failed to extend %s.  Disk full?\n", file);
+		exit(1);
+	}
+	return 0;
+}
+
+/*
+ * $PchId: mkfile.c,v 1.4 2000/08/13 22:06:40 philip Exp $
+ */
Index: /trunk/minix/boot/rawfs.c
===================================================================
--- /trunk/minix/boot/rawfs.c	(revision 9)
+++ /trunk/minix/boot/rawfs.c	(revision 9)
@@ -0,0 +1,329 @@
+/*	rawfs.c - Raw Minix file system support.	Author: Kees J. Bot
+ *								23 Dec 1991
+ *					     Based on readfs by Paul Polderman
+ */
+#define nil 0
+#define _POSIX_SOURCE	1
+#define _MINIX		1
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include <servers/fs/const.h>
+#include <servers/fs/type.h>
+#include <servers/fs/buf.h>
+#include <servers/fs/super.h>
+#include <servers/fs/inode.h>
+#include "rawfs.h"
+
+void readblock(off_t blockno, char *buf, int);
+
+/* The following code handles two file system types: Version 1 with small
+ * inodes and 16-bit disk addresses and Version 2 with big inodes and 32-bit
+ * disk addresses.
+#ifdef FLEX
+ * To make matters worse, Minix-vmd knows about the normal Unix Version 7
+ * directories and directories with flexible entries.
+#endif
+ */
+
+/* File system parameters. */
+static unsigned nr_dzones;	/* Fill these in after reading superblock. */
+static unsigned nr_indirects;
+static unsigned inodes_per_block;
+static int block_size;
+#ifdef FLEX
+#include <dirent.h>
+#define direct _v7_direct
+#else
+#include <sys/dir.h>
+#endif
+
+#if __minix_vmd
+static struct v12_super_block super;	/* Superblock of file system */
+#define s_log_zone_size s_dummy		/* Zones are obsolete. */
+#else
+static struct super_block super;	/* Superblock of file system */
+#define SUPER_V1 SUPER_MAGIC		/* V1 magic has a weird name. */
+#endif
+
+static struct inode curfil;		/* Inode of file under examination */
+static char indir[_MAX_BLOCK_SIZE];	/* Single indirect block. */
+static char dindir[_MAX_BLOCK_SIZE];	/* Double indirect block. */
+static char dirbuf[_MAX_BLOCK_SIZE];	/* Scratch/Directory block. */
+#define scratch dirbuf
+
+static block_t a_indir, a_dindir;	/* Addresses of the indirects. */
+static off_t dirpos;			/* Reading pos in a dir. */
+
+#define fsbuf(b)	(* (struct buf *) (b))
+
+#define	zone_shift	(super.s_log_zone_size)	/* zone to block ratio */
+
+off_t r_super(int *bs)
+/* Initialize variables, return size of file system in blocks,
+ * (zero on error).
+ */
+{
+	/* Read superblock. (The superblock is always at 1kB offset,
+	 * that's why we lie to readblock and say the block size is 1024
+	 * and we want block number 1 (the 'second block', at offset 1kB).)
+	 */
+	readblock(1, scratch, 1024);
+
+	memcpy(&super, scratch, sizeof(super));
+
+	/* Is it really a MINIX file system ? */
+	if (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3) {
+		if(super.s_magic == SUPER_V2)
+			super.s_block_size = 1024;
+		*bs = block_size = super.s_block_size;
+		if(block_size < _MIN_BLOCK_SIZE ||
+			block_size > _MAX_BLOCK_SIZE) {
+			return 0;
+		}
+		nr_dzones= V2_NR_DZONES;
+		nr_indirects= V2_INDIRECTS(block_size);
+		inodes_per_block= V2_INODES_PER_BLOCK(block_size);
+		return (off_t) super.s_zones << zone_shift;
+	} else
+	if (super.s_magic == SUPER_V1) {
+		*bs = block_size = 1024;
+		nr_dzones= V1_NR_DZONES;
+		nr_indirects= V1_INDIRECTS;
+		inodes_per_block= V1_INODES_PER_BLOCK;
+		return (off_t) super.s_nzones << zone_shift;
+	} else {
+		/* Filesystem not recognized as Minix. */
+		return 0;
+	}
+}
+
+void r_stat(Ino_t inum, struct stat *stp)
+/* Return information about a file like stat(2) and remember it. */
+{
+	block_t block;
+	block_t ino_block;
+	ino_t ino_offset;
+
+	/* Calculate start of i-list */
+	block = START_BLOCK + super.s_imap_blocks + super.s_zmap_blocks;
+
+	/* Calculate block with inode inum */
+	ino_block = ((inum - 1) / inodes_per_block);
+	ino_offset = ((inum - 1) % inodes_per_block);
+	block += ino_block;
+
+	/* Fetch the block */
+	readblock(block, scratch, block_size);
+
+	if (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3) {
+		d2_inode *dip;
+		int i;
+
+		dip= &fsbuf(scratch).b_v2_ino[ino_offset];
+
+		curfil.i_mode= dip->d2_mode;
+		curfil.i_nlinks= dip->d2_nlinks;
+		curfil.i_uid= dip->d2_uid;
+		curfil.i_gid= dip->d2_gid;
+		curfil.i_size= dip->d2_size;
+		curfil.i_atime= dip->d2_atime;
+		curfil.i_mtime= dip->d2_mtime;
+		curfil.i_ctime= dip->d2_ctime;
+		for (i= 0; i < V2_NR_TZONES; i++)
+			curfil.i_zone[i]= dip->d2_zone[i];
+	} else {
+		d1_inode *dip;
+		int i;
+
+		dip= &fsbuf(scratch).b_v1_ino[ino_offset];
+
+		curfil.i_mode= dip->d1_mode;
+		curfil.i_nlinks= dip->d1_nlinks;
+		curfil.i_uid= dip->d1_uid;
+		curfil.i_gid= dip->d1_gid;
+		curfil.i_size= dip->d1_size;
+		curfil.i_atime= dip->d1_mtime;
+		curfil.i_mtime= dip->d1_mtime;
+		curfil.i_ctime= dip->d1_mtime;
+		for (i= 0; i < V1_NR_TZONES; i++)
+			curfil.i_zone[i]= dip->d1_zone[i];
+	}
+	curfil.i_dev= -1;	/* Can't fill this in alas. */
+	curfil.i_num= inum;
+
+	stp->st_dev= curfil.i_dev;
+	stp->st_ino= curfil.i_num;
+	stp->st_mode= curfil.i_mode;
+	stp->st_nlink= curfil.i_nlinks;
+	stp->st_uid= curfil.i_uid;
+	stp->st_gid= curfil.i_gid;
+	stp->st_rdev= (dev_t) curfil.i_zone[0];
+	stp->st_size= curfil.i_size;
+	stp->st_atime= curfil.i_atime;
+	stp->st_mtime= curfil.i_mtime;
+	stp->st_ctime= curfil.i_ctime;
+
+	a_indir= a_dindir= 0;
+	dirpos= 0;
+}
+
+ino_t r_readdir(char *name)
+/* Read next directory entry at "dirpos" from file "curfil". */
+{
+	ino_t inum= 0;
+	int blkpos;
+	struct direct *dp;
+
+	if (!S_ISDIR(curfil.i_mode)) { errno= ENOTDIR; return -1; }
+
+	if(!block_size) { errno = 0; return -1; }
+
+	while (inum == 0 && dirpos < curfil.i_size) {
+		if ((blkpos= (int) (dirpos % block_size)) == 0) {
+			/* Need to fetch a new directory block. */
+
+			readblock(r_vir2abs(dirpos / block_size), dirbuf, block_size);
+		}
+#ifdef FLEX
+		if (super.s_flags & S_FLEX) {
+			struct _fl_direct *dp;
+
+			dp= (struct _fl_direct *) (dirbuf + blkpos);
+			if ((inum= dp->d_ino) != 0) strcpy(name, dp->d_name);
+
+			dirpos+= (1 + dp->d_extent) * FL_DIR_ENTRY_SIZE;
+			continue;
+		}
+#endif
+		/* Let dp point to the next entry. */
+		dp= (struct direct *) (dirbuf + blkpos);
+
+		if ((inum= dp->d_ino) != 0) {
+			/* This entry is occupied, return name. */
+			strncpy(name, dp->d_name, sizeof(dp->d_name));
+			name[sizeof(dp->d_name)]= 0;
+		}
+		dirpos+= DIR_ENTRY_SIZE;
+	}
+	return inum;
+}
+
+off_t r_vir2abs(off_t virblk)
+/* Translate a block number in a file to an absolute disk block number.
+ * Returns 0 for a hole and -1 if block is past end of file.
+ */
+{
+	block_t b= virblk;
+	zone_t zone, ind_zone;
+	block_t z, zone_index;
+	int i;
+
+	if(!block_size) return -1;
+
+	/* Check if virblk within file. */
+	if (virblk * block_size >= curfil.i_size) return -1;
+
+	/* Calculate zone in which the datablock number is contained */
+	zone = (zone_t) (b >> zone_shift);
+
+	/* Calculate index of the block number in the zone */
+	zone_index = b - ((block_t) zone << zone_shift);
+
+	/* Go get the zone */
+	if (zone < (zone_t) nr_dzones) {	/* direct block */
+		zone = curfil.i_zone[(int) zone];
+		z = ((block_t) zone << zone_shift) + zone_index;
+		return z;
+	}
+
+	/* The zone is not a direct one */
+	zone -= (zone_t) nr_dzones;
+
+	/* Is it single indirect ? */
+	if (zone < (zone_t) nr_indirects) {	/* single indirect block */
+		ind_zone = curfil.i_zone[nr_dzones];
+	} else {			/* double indirect block */
+		/* Fetch the double indirect block */
+		if ((ind_zone = curfil.i_zone[nr_dzones + 1]) == 0) return 0;
+
+		z = (block_t) ind_zone << zone_shift;
+		if (a_dindir != z) {
+			readblock(z, dindir, block_size);
+			a_dindir= z;
+		}
+		/* Extract the indirect zone number from it */
+		zone -= (zone_t) nr_indirects;
+
+		i = zone / (zone_t) nr_indirects;
+		ind_zone = (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3)
+				? fsbuf(dindir).b_v2_ind[i]
+				: fsbuf(dindir).b_v1_ind[i];
+		zone %= (zone_t) nr_indirects;
+	}
+	if (ind_zone == 0) return 0;
+
+	/* Extract the datablock number from the indirect zone */
+	z = (block_t) ind_zone << zone_shift;
+	if (a_indir != z) {
+		readblock(z, indir, block_size);
+		a_indir= z;
+	}
+	zone = (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3)
+		? fsbuf(indir).b_v2_ind[(int) zone]
+		: fsbuf(indir).b_v1_ind[(int) zone];
+
+	/* Calculate absolute datablock number */
+	z = ((block_t) zone << zone_shift) + zone_index;
+	return z;
+}
+
+ino_t r_lookup(Ino_t cwd, char *path)
+/* Translates a pathname to an inode number.  This is just a nice utility
+ * function, it only needs r_stat and r_readdir.
+ */
+{
+	char name[NAME_MAX+1], r_name[NAME_MAX+1];
+	char *n;
+	struct stat st;
+	ino_t ino;
+
+	ino= path[0] == '/' ? ROOT_INO : cwd;
+
+	for (;;) {
+		if (ino == 0) {
+			errno= ENOENT;
+			return 0;
+		}
+
+		while (*path == '/') path++;
+
+		if (*path == 0) return ino;
+
+		r_stat(ino, &st);
+
+		if (!S_ISDIR(st.st_mode)) {
+			errno= ENOTDIR;
+			return 0;
+		}
+
+		n= name;
+		while (*path != 0 && *path != '/')
+			if (n < name + NAME_MAX) *n++ = *path++;
+		*n= 0;
+
+		while ((ino= r_readdir(r_name)) != 0
+					&& strcmp(name, r_name) != 0) {
+		}
+	}
+}
+
+/*
+ * $PchId: rawfs.c,v 1.8 1999/11/05 23:14:15 philip Exp $
+ */
Index: /trunk/minix/boot/rawfs.h
===================================================================
--- /trunk/minix/boot/rawfs.h	(revision 9)
+++ /trunk/minix/boot/rawfs.h	(revision 9)
@@ -0,0 +1,43 @@
+/*	rawfs.h - Raw Minix file system support.	Author: Kees J. Bot
+ *
+ *		off_t r_super(int *block_size);
+ *			Initialize variables, returns the size of a valid Minix
+ *			file system blocks, but zero on error. 
+ *
+ *		void r_stat(ino_t file, struct stat *stp);
+ *			Return information about a file like stat(2) and
+ *			remembers file for the next two calls.
+ *
+ *		off_t r_vir2abs(off_t virblockno);
+ *			Translate virtual block number in file to absolute
+ *			disk block number.  Returns 0 if the file contains
+ *			a hole, or -1 if the block lies past the end of file.
+ *
+ *		ino_t r_readdir(char *name);
+ *			Return next directory entry or 0 if there are no more.
+ *			Returns -1 and sets errno on error.
+ *
+ *		ino_t r_lookup(ino_t cwd, char *path);
+ *			A utility function that translates a pathname to an
+ *			inode number.  It starts from directory "cwd" unless
+ *			path starts with a '/', then from ROOT_INO.
+ *			Returns 0 and sets errno on error.
+ *
+ *	One function needs to be provided by the outside world:
+ *
+ *		void readblock(off_t blockno, char *buf, int block_size);
+ *			Read a block into the buffer.  Outside world handles
+ *			errors.
+ */
+
+#define ROOT_INO	((ino_t) 1)	/* Inode nr of root dir. */
+
+off_t r_super(int *);
+void r_stat(Ino_t file, struct stat *stp);
+off_t r_vir2abs(off_t virblockno);
+ino_t r_readdir(char *name);
+ino_t r_lookup(Ino_t cwd, char *path);
+
+/*
+ * $PchId: rawfs.h,v 1.4 1996/04/19 08:16:36 philip Exp $
+ */
Index: /trunk/minix/commands/Makefile
===================================================================
--- /trunk/minix/commands/Makefile	(revision 9)
+++ /trunk/minix/commands/Makefile	(revision 9)
@@ -0,0 +1,40 @@
+# Makefile for commands.
+
+MAKE	= exec make -$(MAKEFLAGS)
+BZIP2=bzip2-1.0.3
+
+SMALLPROGRAMS=`arch` aal advent ash autil awk bc byacc cawf cron de dhcpd dis88 elle elvis ftp ftpd200 httpd ibm indent m4 make mdb mined patch pax ps reboot rlogind scripts sh simple syslogd talk talkd telnet telnetd urlget yap zmodem
+
+usage:
+	@echo "Usage: make all          # Compile all commands" >&2
+	@echo "       make install      # Install the result (run as bin!)" >&2
+	@echo "       make clean        # Delete .o files and other junk" >&2
+	@echo "       make big          # Compile all big commands" >&2
+	@echo "       make biginstall   # Install all big commands" >&2
+	@echo "       make small        # Install all small commands" >&2
+	@echo "       make smallinstall # Install all small commands" >&2
+	@echo " "
+	@echo "big compiles the commands the require large compiler sizes."
+	@echo "small compiles the rest. all compiles all."
+	@false
+
+all: small big
+
+install: biginstall smallinstall
+
+big:
+	cd $(BZIP2) && /bin/sh build build
+
+biginstall: big
+	cd $(BZIP2) && make install
+
+clean::
+	cd $(BZIP2) && make clean
+	for p in $(SMALLPROGRAMS); do ( cd $$p && make clean ); done
+
+small::
+	set -e; for p in $(SMALLPROGRAMS); do ( cd $$p && make all ); done
+
+smallinstall::
+	set -e; for p in $(SMALLPROGRAMS); do ( cd $$p && make install ); done
+
Index: /trunk/minix/commands/aal/Makefile
===================================================================
--- /trunk/minix/commands/aal/Makefile	(revision 9)
+++ /trunk/minix/commands/aal/Makefile	(revision 9)
@@ -0,0 +1,56 @@
+# Makefile for aal
+
+CC=exec cc
+CFLAGS=-I. -wo -DAAL -DSTB -DNDEBUG -DDISTRIBUTION -D_POSIX_SOURCE -D_MINIX
+LDFLAGS=-i
+
+all:	aal
+
+OFILES=	archiver.o \
+	print.o \
+	rd.o \
+	rd_arhdr.o \
+	rd_unsig2.o \
+	sprint.o \
+	wr_arhdr.o \
+	wr_bytes.o \
+	wr_int2.o \
+	wr_long.o \
+	wr_ranlib.o \
+	format.o \
+	rd_bytes.o \
+	system.o \
+	write.o \
+	long2str.o
+
+aal: $(OFILES)
+	$(CC) $(LDFLAGS) -o aal $(OFILES)
+	install -S 512k $@
+
+install:	/usr/bin/aal /usr/bin/ar
+
+/usr/bin/aal:	aal
+	install -cs -o bin aal $@
+
+/usr/bin/ar:	/usr/bin/aal
+	install -l $? $@
+
+archiver.o:
+print.o:
+rd.o:
+rd_arhdr.o:
+rd_unsig2.o:
+sprint.o:
+wr_arhdr.o:
+wr_bytes.o:
+wr_int2.o:
+wr_long.o:
+wr_ranlib.o:
+format.o:
+rd_bytes.o:
+system.o:
+write.o:
+long2str.o:
+
+clean:	
+	rm -f *.o core *.bak aal
Index: /trunk/minix/commands/aal/arch.h
===================================================================
--- /trunk/minix/commands/aal/arch.h	(revision 9)
+++ /trunk/minix/commands/aal/arch.h	(revision 9)
@@ -0,0 +1,25 @@
+/* $Header: /cvsup/minix/src/commands/aal/arch.h,v 1.1.1.1 2005/04/21 14:53:57 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+
+#ifndef __ARCH_H_INCLUDED
+#define __ARCH_H_INCLUDED
+
+#define	ARMAG	0177545
+#define AALMAG	0177454
+
+struct	ar_hdr {
+	char	ar_name[14];
+	long	ar_date;
+	char	ar_uid;
+	char	ar_gid;
+	short	ar_mode;
+	long	ar_size;
+};
+
+#define AR_TOTAL	26
+#define AR_SIZE		22
+
+#endif /* __ARCH_H_INCLUDED */
Index: /trunk/minix/commands/aal/archiver.c
===================================================================
--- /trunk/minix/commands/aal/archiver.c	(revision 9)
+++ /trunk/minix/commands/aal/archiver.c	(revision 9)
@@ -0,0 +1,800 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* ar - archiver		Author: Michiel Huisjes */
+/* Made into arch/aal by Ceriel Jacobs
+ */
+
+static char RcsId[] = "$Header: /cvsup/minix/src/commands/aal/archiver.c,v 1.1.1.1 2005/04/21 14:53:57 beng Exp $";
+
+/*
+ * Usage: [arch|aal] [adprtvx] archive [file] ...
+ *	  v: verbose
+ *	  x: extract
+ *	  a: append
+ *	  r: replace (append when not in archive)
+ *	  d: delete
+ *	  t: print contents of archive
+ *	  p: print named files
+ *	  l: temporaries in current directory instead of /usr/tmp
+ *	  c: don't give "create" message
+ *	  u: replace only if dated later than member in archive
+#ifdef DISTRIBUTION
+ *	  D: make distribution: use distr_time, uid=2, gid=2, mode=0644
+#endif
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifndef	S_IREAD
+#define	S_IREAD		S_IRUSR
+#endif
+#ifndef	S_IWRITE
+#define	S_IWRITE	S_IWUSR
+#endif
+#ifndef	S_IEXEC
+#define	S_IEXEC		S_IXUSR
+#endif
+#include <signal.h>
+#include <arch.h>
+#ifdef AAL
+#include <ranlib.h>
+#include <out.h>
+#define MAGIC_NUMBER	AALMAG
+long	offset;
+struct ranlib *tab;
+unsigned int	tnum = 0;
+char	*tstrtab;
+unsigned int	tssiz = 0;
+char	*malloc(), *realloc(), *strcpy(), *strncpy();
+long	time();
+unsigned int tabsz, strtabsz;
+#else
+#define MAGIC_NUMBER	ARMAG
+#endif
+long	lseek();
+
+#define odd(nr)		(nr & 01)
+#define even(nr)	(odd(nr) ? nr + 1 : nr)
+
+typedef char BOOL;
+#define FALSE		0
+#define TRUE		1
+
+#define READ		0
+#define APPEND		2
+#define CREATE		1
+
+#define MEMBER		struct ar_hdr
+
+#define NIL_PTR		((char *) 0)
+#define NIL_MEM		((MEMBER *) 0)
+#define NIL_LONG	((long *) 0)
+
+#define IO_SIZE		(10 * 1024)
+
+#define equal(str1, str2)	(!strncmp((str1), (str2), 14))
+#ifndef S_ISDIR
+#define S_ISDIR(m)	(m & S_IFDIR)		/* is a directory */
+#endif
+
+BOOL verbose;
+BOOL app_fl;
+BOOL ex_fl;
+BOOL show_fl;
+BOOL pr_fl;
+BOOL rep_fl;
+BOOL del_fl;
+BOOL nocr_fl;
+BOOL local_fl;
+BOOL update_fl;
+#ifdef DISTRIBUTION
+BOOL distr_fl;
+long distr_time;
+#endif
+
+int ar_fd;
+
+char io_buffer[IO_SIZE];
+
+char *progname;
+
+char temp_buf[32];
+char *temp_arch = &temp_buf[0];
+extern char *mktemp();
+extern char *ctime();
+
+usage()
+{
+	error(TRUE, "usage: %s %s archive [file] ...\n",
+		progname,
+#ifdef AAL
+		"[acdrtxvlu]"
+#else
+		"[acdprtxvlu]"
+#endif
+		);
+}
+
+/*VARARGS2*/
+error(quit, str1, str2, str3, str4)
+BOOL quit;
+char *str1, *str2, *str3, *str4;
+{
+	char errbuf[256];
+
+	sprint(errbuf, str1, str2, str3, str4);
+	write(2, errbuf, strlen(errbuf));
+  	if (quit) {
+		unlink(temp_arch);
+		_exit(1);
+  	}
+}
+
+char *basename(path)
+char *path;
+{
+  register char *ptr = path;
+  register char *last = NIL_PTR;
+
+  while (*ptr != '\0') {
+	if (*ptr == '/')
+		last = ptr;
+	ptr++;
+  }
+  if (last == NIL_PTR)
+	return path;
+  if (*(last + 1) == '\0') {
+	*last = '\0';
+	return basename(path);
+  }
+  return last + 1;
+}
+
+extern unsigned int rd_unsigned2();
+
+open_archive(name, mode)
+register char *name;
+register int mode;
+{
+  unsigned short magic = 0;
+  int fd;
+
+  if (mode == CREATE) {
+	if ((fd = creat(name, 0666)) < 0)
+		error(TRUE, "cannot creat %s\n", name);
+	magic = MAGIC_NUMBER;
+	wr_int2(fd, magic);
+	return fd;
+  }
+
+  if ((fd = open(name, mode)) < 0) {
+	if (mode == APPEND) {
+		close(open_archive(name, CREATE));
+		if (!nocr_fl) error(FALSE, "%s: creating %s\n", progname, name);
+		return open_archive(name, APPEND);
+	}
+	error(TRUE, "cannot open %s\n", name);
+  }
+  lseek(fd, 0L, 0);
+  magic = rd_unsigned2(fd);
+  if (magic != AALMAG && magic != ARMAG)
+	error(TRUE, "%s is not in ar format\n", name);
+  
+  return fd;
+}
+
+#if __STDC__
+void catch(int sig)
+#else
+catch()
+#endif
+{
+	unlink(temp_arch);
+	_exit (2);
+}
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+  register char *ptr;
+  int needs_arg = 0;
+
+  progname = argv[0];
+
+  if (argc < 3)
+	usage();
+  
+  for (ptr = argv[1]; *ptr; ptr++) {
+	switch (*ptr) {
+		case 't' :
+			show_fl = TRUE;
+			break;
+		case 'v' :
+			verbose = TRUE;
+			break;
+		case 'x' :
+			ex_fl = TRUE;
+			break;
+		case 'a' :
+			needs_arg = 1;
+			app_fl = TRUE;
+			break;
+		case 'c' :
+			nocr_fl = TRUE;
+			break;
+#ifndef AAL
+		case 'p' :
+			needs_arg = 1;
+			pr_fl = TRUE;
+			break;
+#endif
+		case 'd' :
+			needs_arg = 1;
+			del_fl = TRUE;
+			break;
+		case 'r' :
+			needs_arg = 1;
+			rep_fl = TRUE;
+			break;
+		case 'l' :
+			local_fl = TRUE;
+			break;
+		case 'u' :
+			update_fl = TRUE;
+			break;
+#ifdef DISTRIBUTION
+		case 'D' :
+			distr_fl = TRUE;
+			break;
+#endif
+		default :
+			usage();
+	}
+  }
+
+  if (needs_arg && argc <= 3)
+	usage();
+#ifdef DISTRIBUTION
+  if (distr_fl) {
+	struct stat statbuf;
+
+	stat(progname, &statbuf);
+	distr_time = statbuf.st_mtime;
+  }
+#endif
+  if (local_fl) strcpy(temp_arch, "ar.XXXXXX");
+  else	strcpy(temp_arch, "/usr/tmp/ar.XXXXXX");
+
+  if (app_fl + ex_fl + del_fl + rep_fl + show_fl + pr_fl != 1)
+	usage();
+
+  if (update_fl && !rep_fl)
+	usage();
+
+  if (rep_fl || del_fl
+#ifdef AAL
+	|| app_fl
+#endif
+     ) {
+	mktemp(temp_arch);
+  }
+#ifdef AAL
+  tab = (struct ranlib *) malloc(512 * sizeof(struct ranlib));
+  tstrtab = malloc(4096);
+  if (!tab || !tstrtab) error(TRUE,"Out of core\n");
+  tabsz = 512;
+  strtabsz = 4096;
+#endif
+
+  signal(SIGINT, catch);
+  get(argc, argv);
+  
+  return 0;
+}
+
+MEMBER *
+get_member()
+{
+  static MEMBER member;
+
+again:
+  if (rd_arhdr(ar_fd, &member) == 0)
+	return NIL_MEM;
+  if (member.ar_size < 0) {
+	error(TRUE, "archive has member with negative size\n");
+  }
+#ifdef AAL
+  if (equal(SYMDEF, member.ar_name)) {
+	lseek(ar_fd, member.ar_size, 1);
+	goto again;
+  }
+#endif
+  return &member;
+}
+
+char *get_mode();
+
+get(argc, argv)
+int argc;
+register char *argv[];
+{
+  register MEMBER *member;
+  int i = 0;
+  int temp_fd, read_chars;
+
+  ar_fd = open_archive(argv[2], (show_fl || pr_fl || ex_fl) ? READ : APPEND);
+  if (rep_fl || del_fl
+#ifdef AAL
+	|| app_fl
+#endif
+  )
+	temp_fd = open_archive(temp_arch, CREATE);
+  while ((member = get_member()) != NIL_MEM) {
+	if (argc > 3) {
+		for (i = 3; i < argc; i++) {
+			if (equal(basename(argv[i]), member->ar_name))
+				break;
+		}
+		if (i == argc || app_fl) {
+			if (rep_fl || del_fl
+#ifdef AAL
+				|| app_fl
+#endif
+			) {
+#ifdef AAL
+				if (i != argc) {
+					print("%s: already in archive\n", argv[i]);
+					argv[i] = "";
+				}
+#endif
+				wr_arhdr(temp_fd, member);
+				copy_member(member, ar_fd, temp_fd, 0);
+			}
+			else {
+#ifndef AAL
+				if (app_fl && i != argc) {
+					print("%s: already in archive\n", argv[i]);
+					argv[i] = "";
+				}
+#endif
+				lseek(ar_fd, even(member->ar_size),1);
+			}
+			continue;
+		}
+	}
+	if (ex_fl || pr_fl)
+		extract(member);
+	else {
+		if (rep_fl) {
+			int isold = 0;
+			if(update_fl) {
+				struct stat status;
+				if (stat(argv[i], &status) >= 0) {
+					if(status.st_mtime <= member->ar_date)
+						isold = 1;
+				}
+			}
+			if(!isold)
+				add(argv[i], temp_fd, "r - %s\n");
+			else {
+				wr_arhdr(temp_fd, member);
+				copy_member(member, ar_fd, temp_fd, 0);
+				if(verbose)
+					show("r - %s (old)\n", member->ar_name);
+			}
+		}
+		else if (show_fl) {
+			char buf[sizeof(member->ar_name) + 2];
+			register char *p = buf, *q = member->ar_name;
+
+			while (q <= &member->ar_name[sizeof(member->ar_name)-1] && *q) {
+				*p++ = *q++;
+			}
+			*p++ = '\n';
+			*p = '\0';
+			if (verbose) {
+				char *mode = get_mode(member->ar_mode);
+				char *date = ctime(&(member->ar_date));
+
+				*(date + 16) = '\0';
+				*(date + 24) = '\0';
+
+				print("%s%3u/%u%7ld %s %s %s",
+					mode,
+					(unsigned) (member->ar_uid & 0377),
+					(unsigned) (member->ar_gid & 0377),
+					member->ar_size,
+					date+4,
+					date+20,
+					buf);
+			}
+			else	print(buf);
+		}
+		else if (del_fl)
+			show("d - %s\n", member->ar_name);
+		lseek(ar_fd, even(member->ar_size), 1);
+	}
+	argv[i] = "";
+  }
+
+  if (argc > 3) {
+	for (i = 3; i < argc; i++)
+		if (argv[i][0] != '\0') {
+#ifndef AAL
+			if (app_fl)
+				add(argv[i], ar_fd, "a - %s\n");
+			else
+#endif
+			if (rep_fl
+#ifdef AAL
+				|| app_fl
+#endif
+			)
+				add(argv[i], temp_fd, "a - %s\n");
+			else {
+				print("%s: not found\n", argv[i]);
+			}
+		}
+  }
+
+  if (rep_fl || del_fl
+#ifdef AAL
+		|| app_fl
+#endif
+  ) {
+	signal(SIGINT, SIG_IGN);
+	close(ar_fd);
+	close(temp_fd);
+	ar_fd = open_archive(argv[2], CREATE);
+	temp_fd = open_archive(temp_arch, APPEND);
+#ifdef AAL
+	write_symdef();
+#endif
+	while ((read_chars = read(temp_fd, io_buffer, IO_SIZE)) > 0)
+		mwrite(ar_fd, io_buffer, read_chars);
+	close(temp_fd);
+	unlink(temp_arch);
+  }
+  close(ar_fd);
+}
+
+add(name, fd, mess)
+char *name;
+int fd;
+char *mess;
+{
+  static MEMBER member;
+  register int read_chars;
+  struct stat status;
+  int src_fd;
+
+  if (stat(name, &status) < 0) {
+	error(FALSE, "cannot find %s\n", name);
+	return;
+  }
+  else if (S_ISDIR(status.st_mode)) {
+	error(FALSE, "%s is a directory (ignored)\n", name);
+	return;
+  }
+  else if ((src_fd = open(name, 0)) < 0) {
+	error(FALSE, "cannot open %s\n", name);
+	return;
+  }
+
+  strncpy (member.ar_name, basename (name), sizeof(member.ar_name));
+  member.ar_uid = status.st_uid;
+  member.ar_gid = status.st_gid;
+  member.ar_mode = status.st_mode;
+  member.ar_date = status.st_mtime;
+  member.ar_size = status.st_size;
+#ifdef DISTRIBUTION
+  if (distr_fl) {
+	member.ar_uid = 2;
+	member.ar_gid = 2;
+	member.ar_mode = 0644;
+	member.ar_date = distr_time;
+  }
+#endif
+  wr_arhdr(fd, &member);
+#ifdef AAL
+  do_object(src_fd, member.ar_size);
+  lseek(src_fd, 0L, 0);
+  offset += AR_TOTAL + even(member.ar_size);
+#endif
+  while (status.st_size > 0) {
+	int x = IO_SIZE;
+
+	read_chars = x;
+	if (status.st_size < x) {
+		x = status.st_size;
+		read_chars = x;
+		status.st_size = 0;
+		x = even(x);
+	}
+	else	status.st_size -= x;
+  	if (read(src_fd, io_buffer, read_chars) != read_chars) {
+		error(FALSE,"%s seems to shrink\n", name);
+		break;
+	}
+	mwrite(fd, io_buffer, x);
+  }
+
+  if (verbose)
+	show(mess, member.ar_name);
+  close(src_fd);
+}
+
+extract(member)
+register MEMBER *member;
+{
+  int fd = 1;
+  char buf[sizeof(member->ar_name) + 1];
+
+  strncpy(buf, member->ar_name, sizeof(member->ar_name));
+  buf[sizeof(member->ar_name)] = 0;
+  if (pr_fl == FALSE && (fd = creat(buf, 0666)) < 0) {
+	error(FALSE, "cannot create %s\n", buf);
+	fd = -1;
+  }
+
+  if (verbose) {
+	if (pr_fl == FALSE) show("x - %s\n", buf);
+	else show("\n<%s>\n\n", buf);
+  }
+
+  copy_member(member, ar_fd, fd, 1);
+
+  if (fd >= 0 && fd != 1)
+  	close(fd);
+  if (pr_fl == FALSE) chmod(buf, member->ar_mode);
+}
+
+copy_member(member, from, to, extracting)
+register MEMBER *member;
+int from, to;
+{
+  register int rest;
+  long mem_size = member->ar_size;
+  BOOL is_odd = odd(mem_size) ? TRUE : FALSE;
+
+#ifdef AAL
+  if (! extracting) {
+  	long pos = lseek(from, 0L, 1);
+
+	do_object(from, mem_size);
+	offset += AR_TOTAL + even(mem_size);
+  	lseek(from, pos, 0);
+  }
+#endif
+  do {
+	rest = mem_size > (long) IO_SIZE ? IO_SIZE : (int) mem_size;
+	if (read(from, io_buffer, rest) != rest) {
+		char buf[sizeof(member->ar_name) + 1];
+
+		strncpy(buf, member->ar_name, sizeof(member->ar_name));
+		buf[sizeof(member->ar_name)] = 0;
+		error(TRUE, "read error on %s\n", buf);
+	}
+	if (to >= 0) mwrite(to, io_buffer, rest);
+	mem_size -= (long) rest;
+  } while (mem_size > 0L);
+
+  if (is_odd) {
+	lseek(from, 1L, 1);
+	if (to >= 0 && ! extracting)
+		lseek(to, 1L, 1);
+  }
+}
+
+char *
+get_mode(mode)
+register int mode;
+{
+  static char mode_buf[11];
+  register int tmp = mode;
+  int i;
+
+  mode_buf[9] = ' ';
+  for (i = 0; i < 3; i++) {
+	mode_buf[i * 3] = (tmp & S_IREAD) ? 'r' : '-';
+	mode_buf[i * 3 + 1] = (tmp & S_IWRITE) ? 'w' : '-';
+	mode_buf[i * 3 + 2] = (tmp & S_IEXEC) ? 'x' : '-';
+	tmp <<= 3;
+  }
+  if (mode & S_ISUID)
+	mode_buf[2] = 's';
+  if (mode & S_ISGID)
+	mode_buf[5] = 's';
+  return mode_buf;
+}
+
+wr_fatal()
+{
+	error(TRUE, "write error\n");
+}
+
+rd_fatal()
+{
+	error(TRUE, "read error\n");
+}
+
+mwrite(fd, address, bytes)
+int fd;
+register char *address;
+register int bytes;
+{
+  if (write(fd, address, bytes) != bytes)
+	error(TRUE, "write error\n");
+}
+
+show(s, name)
+char *s, *name;
+{
+  MEMBER x;
+  char buf[sizeof(x.ar_name)+1];
+  register char *p = buf, *q = name;
+
+  while (q <= &name[sizeof(x.ar_name)-1] && *q) *p++ = *q++;
+  *p++ = '\0';
+  print(s, buf);
+}
+
+#ifdef AAL
+/*
+ * Write out the ranlib table: first 4 bytes telling how many ranlib structs
+ * there are, followed by the ranlib structs,
+ * then 4 bytes giving the size of the string table, followed by the string
+ * table itself.
+ */
+write_symdef()
+{
+	register struct ranlib	*ran;
+	register int	i;
+	register long	delta;
+	MEMBER	arbuf;
+
+	if (odd(tssiz))
+		tstrtab[tssiz++] = '\0';
+	for (i = 0; i < sizeof(arbuf.ar_name); i++)
+		arbuf.ar_name[i] = '\0';
+	strcpy(arbuf.ar_name, SYMDEF);
+	arbuf.ar_size = 4 + 2 * 4 * (long)tnum + 4 + (long)tssiz;
+	time(&arbuf.ar_date);
+	arbuf.ar_uid = getuid();
+	arbuf.ar_gid = getgid();
+	arbuf.ar_mode = 0444;
+#ifdef DISTRIBUTION
+	if (distr_fl) {
+		arbuf.ar_uid = 2;
+		arbuf.ar_gid = 2;
+		arbuf.ar_date = distr_time;
+	}
+#endif
+	wr_arhdr(ar_fd,&arbuf);
+	wr_long(ar_fd, (long) tnum);
+	/*
+	 * Account for the space occupied by the magic number
+	 * and the ranlib table.
+	 */
+	delta = 2 + AR_TOTAL + arbuf.ar_size;
+	for (ran = tab; ran < &tab[tnum]; ran++) {
+		ran->ran_pos += delta;
+	}
+
+	wr_ranlib(ar_fd, tab, (long) tnum);
+	wr_long(ar_fd, (long) tssiz);
+	wr_bytes(ar_fd, tstrtab, (long) tssiz);
+}
+
+/*
+ * Return whether the bytes in `buf' form a good object header. 
+ * The header is put in `headp'.
+ */
+int
+is_outhead(headp)
+	register struct outhead	*headp;
+{
+
+	return !BADMAGIC(*headp) && headp->oh_nname != 0;
+}
+
+do_object(f, size)
+	long size;
+{
+	struct outhead	headbuf;
+
+	if (size < SZ_HEAD) {
+		/* It can't be an object file. */
+		return;
+	}
+	/*
+	 * Read a header to see if it is an object file.
+	 */
+	if (! rd_fdopen(f)) {
+		rd_fatal();
+	}
+	rd_ohead(&headbuf);
+	if (!is_outhead(&headbuf)) {
+		return;
+	}
+	do_names(&headbuf);
+}
+
+/*
+ * First skip the names and read in the string table, then seek back to the
+ * name table and read and write the names one by one. Update the ranlib table
+ * accordingly.
+ */
+do_names(headp)
+	struct outhead	*headp;
+{
+	register char	*strings;
+	register int	nnames = headp->oh_nname;
+#define NNAMES 100
+	struct outname	namebuf[NNAMES];
+	long xxx = OFF_CHAR(*headp);
+
+	if (	headp->oh_nchar != (unsigned int)headp->oh_nchar ||
+		(strings = malloc((unsigned int)headp->oh_nchar)) == (char *)0
+	   ) {
+		error(TRUE, "string table too big\n");
+	}
+	rd_string(strings, headp->oh_nchar);
+	while (nnames) {
+		int i = nnames >= NNAMES ? NNAMES : nnames;
+		register struct outname *p = namebuf;
+
+		nnames -= i;
+		rd_name(namebuf, i);
+		while (i--) {
+			long off = p->on_foff - xxx;
+			if (p->on_foff == (long)0) {
+				p++;
+				continue; /* An unrecognizable name. */
+			}
+			p->on_mptr = strings + off;
+			/*
+			 * Only enter names that are exported and are really
+			 * defined. Also enter common names. Note, that
+			 * this might cause problems when the name is really
+			 * defined in a later file, with a value != 0.
+			 * However, this problem also exists on the Unix
+			 * ranlib archives.
+			 */
+			if (	(p->on_type & S_EXT) &&
+				(p->on_type & S_TYP) != S_UND
+			   )
+				enter_name(p);
+			p++;
+		}
+	}
+	free(strings);
+}
+
+enter_name(namep)
+	struct outname *namep;
+{
+	register char	*cp;
+
+	if (tnum >= tabsz) {
+		tab = (struct ranlib *)
+			realloc((char *) tab, (tabsz += 512) * sizeof(struct ranlib));
+		if (! tab) error(TRUE, "Out of core\n");
+	}
+	tab[tnum].ran_off = tssiz;
+	tab[tnum].ran_pos = offset;
+
+	for (cp = namep->on_mptr;; cp++) {
+		if (tssiz >= strtabsz) {
+			tstrtab = realloc(tstrtab, (strtabsz += 4096));
+			if (! tstrtab) error(TRUE, "string table overflow\n");
+		}
+		tstrtab[tssiz++]  = *cp;
+		if (!*cp) break;
+	}
+	tnum++;
+}
+#endif AAL
Index: /trunk/minix/commands/aal/build
===================================================================
--- /trunk/minix/commands/aal/build	(revision 9)
+++ /trunk/minix/commands/aal/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/aal/byte_order.h
===================================================================
--- /trunk/minix/commands/aal/byte_order.h	(revision 9)
+++ /trunk/minix/commands/aal/byte_order.h	(revision 9)
@@ -0,0 +1,9 @@
+#if defined(mc68020) || defined(mc68000) || defined(sparc)
+#define BYTES_REVERSED 1
+#define WORDS_REVERSED 1
+#define CHAR_UNSIGNED 0
+#else
+#define BYTES_REVERSED 0
+#define WORDS_REVERSED 0
+#define CHAR_UNSIGNED 0
+#endif
Index: /trunk/minix/commands/aal/format.c
===================================================================
--- /trunk/minix/commands/aal/format.c	(revision 9)
+++ /trunk/minix/commands/aal/format.c	(revision 9)
@@ -0,0 +1,112 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/commands/aal/format.c,v 1.1.1.1 2005/04/21 14:53:57 beng Exp $ */
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+extern char *long2str();
+
+static int
+integral(c)
+{
+	switch (c) {
+	case 'b':
+		return -2;
+	case 'd':
+		return 10;
+	case 'o':
+		return -8;
+	case 'u':
+		return -10;
+	case 'x':
+		return -16;
+	}
+	return 0;
+}
+
+/*VARARGS2*/
+/*FORMAT1 $
+	%s = char *
+	%l = long
+	%c = int
+	%[uxbo] = unsigned int
+	%d = int
+$ */
+int
+_format(buf, fmt, argp)
+	char *buf, *fmt;
+	register va_list argp;
+{
+	register char *pf = fmt;
+	register char *pb = buf;
+
+	while (*pf) {
+		if (*pf == '%') {
+			register width, base, pad, npad;
+			char *arg;
+			char cbuf[2];
+			char *badformat = "<bad format>";
+			
+			/* get padder */
+			if (*++pf == '0') {
+				pad = '0';
+				++pf;
+			}
+			else
+				pad = ' ';
+			
+			/* get width */
+			width = 0;
+			while (*pf >= '0' && *pf <= '9')
+				width = 10 * width + *pf++ - '0';
+			
+			if (*pf == 's') {
+				arg = va_arg(argp, char *);
+			}
+			else
+			if (*pf == 'c') {
+				cbuf[0] = va_arg(argp, int);
+				cbuf[1] = '\0';
+				arg = &cbuf[0];
+			}
+			else
+			if (*pf == 'l') {
+				/* alignment ??? */
+				if (base = integral(*++pf)) {
+					arg = long2str(va_arg(argp,long), base);
+				}
+				else {
+					pf--;
+					arg = badformat;
+				}
+			}
+			else
+			if (base = integral(*pf)) {
+				arg = long2str((long)va_arg(argp,int), base);
+			}
+			else
+			if (*pf == '%')
+				arg = "%";
+			else
+				arg = badformat;
+
+			npad = width - strlen(arg);
+
+			while (npad-- > 0)
+				*pb++ = pad;
+			
+			while (*pb++ = *arg++);
+			pb--;
+			pf++;
+		}
+		else
+			*pb++ = *pf++;
+	}
+	return pb - buf;
+}
Index: /trunk/minix/commands/aal/local.h
===================================================================
--- /trunk/minix/commands/aal/local.h	(revision 9)
+++ /trunk/minix/commands/aal/local.h	(revision 9)
@@ -0,0 +1,19 @@
+/* $Header: /cvsup/minix/src/commands/aal/local.h,v 1.1.1.1 2005/04/21 14:53:57 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* collection of options, selected by including or excluding 'defines' */
+
+/* Version number of the EM object code */
+#	define	VERSION		3	/* 16 bits number */
+
+/* The default machine used by ack, acc, apc */
+#	define	ACKM		"minix"
+
+/* size of local machine, either 0 (for 16 bit address space), or 1 */
+#	undef BIGMACHINE	1
+
+/* operating system, SYS_5, V7, BSD4_1 or BSD4_2; Do NOT delete the comment
+   in the next line! */
+#	define V7  1       /* SYSTEM */
Index: /trunk/minix/commands/aal/long2str.c
===================================================================
--- /trunk/minix/commands/aal/long2str.c	(revision 9)
+++ /trunk/minix/commands/aal/long2str.c	(revision 9)
@@ -0,0 +1,67 @@
+/* $Header: /cvsup/minix/src/commands/aal/long2str.c,v 1.1.1.1 2005/04/21 14:53:57 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* Integer to String translator
+	-> base is a value from [-16,-2] V [2,16]
+	-> base < 0: see 'val' as unsigned value
+	-> no checks for buffer overflow and illegal parameters
+	(1985, EHB)
+*/
+
+#define MAXWIDTH 32
+
+char *
+long2str(val, base)
+	register long val;
+	register base;
+{
+	static char numbuf[MAXWIDTH];
+	static char vec[] = "0123456789ABCDEF";
+	register char *p = &numbuf[MAXWIDTH];
+	int sign = (base > 0);
+
+	*--p = '\0';		/* null-terminate string	*/
+	if (val) {
+		if (base > 0) {
+			if (val < 0L) {
+				long v1 = -val;
+				if (v1 == val)
+					goto overflow;
+				val = v1;
+			}
+			else
+				sign = 0;
+		}
+		else
+		if (base < 0) {			/* unsigned */
+			base = -base;
+			if (val < 0L) {	/* taken from Amoeba src */
+				register mod, i;
+			overflow:
+				mod = 0;
+				for (i = 0; i < 8 * sizeof val; i++) {
+					mod <<= 1;
+					if (val < 0)
+						mod++;
+					val <<= 1;
+					if (mod >= base) {
+						mod -= base;
+						val++;
+					}
+				}
+				*--p = vec[mod];
+			}
+		}
+		do {
+			*--p = vec[(int) (val % base)];
+			val /= base;
+		} while (val != 0L);
+		if (sign)
+			*--p = '-';	/* don't forget it !!	*/
+	}
+	else
+		*--p = '0';		/* just a simple 0	*/
+	return p;
+}
Index: /trunk/minix/commands/aal/object.h
===================================================================
--- /trunk/minix/commands/aal/object.h	(revision 9)
+++ /trunk/minix/commands/aal/object.h	(revision 9)
@@ -0,0 +1,76 @@
+/* $Header: /cvsup/minix/src/commands/aal/object.h,v 1.1.1.1 2005/04/21 14:53:57 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#include "byte_order.h"
+#include <local.h>
+#include <stdio.h>
+
+#if CHAR_UNSIGNED
+#define Xchar(ch)	(ch)
+#else
+#define Xchar(ch)	((ch) & 0377)
+#endif
+
+#if ! defined(BYTES_REVERSED)
+#define BYTES_REVERSED 1
+#endif
+
+#if ! defined(WORDS_REVERSED)
+#define WORDS_REVERSED 1
+#endif
+
+#if BYTES_REVERSED
+#define uget2(c)	(Xchar((c)[0]) | ((unsigned) Xchar((c)[1]) << 8))
+#define Xput2(i, c)	(((c)[0] = (i)), ((c)[1] = (i) >> 8))
+#define put2(i, c)	{ register int j = (i); Xput2(j, c); }
+#else
+#define uget2(c)	(* ((unsigned short *) (c)))
+#define Xput2(i, c)	(* ((short *) (c)) = (i))
+#define put2(i, c)	Xput2(i, c)
+#endif
+
+#define get2(c)		((short) uget2(c))
+
+#if WORDS_REVERSED || BYTES_REVERSED
+#define get4(c)		(uget2(c) | ((long) uget2((c)+2) << 16))
+#define put4(l, c)	{ register long x=(l); \
+			  Xput2((int)x,c); \
+			  Xput2((int)(x>>16),(c)+2); \
+			}
+#else
+#define get4(c)		(* ((long *) (c)))
+#define put4(l, c)	(* ((long *) (c)) = (l))
+#endif
+
+#define SECTCNT	3	/* number of sections with own output buffer */
+#if BIGMACHINE
+#define WBUFSIZ	(8*BUFSIZ)
+#else
+#define WBUFSIZ	BUFSIZ
+#endif
+
+struct fil {
+	int	cnt;
+	char	*pnow;
+	char	*pbegin;
+	long	currpos;
+	int	fd;
+	char	pbuf[WBUFSIZ];
+};
+
+extern struct fil __parts[];
+
+#define	PARTEMIT	0
+#define	PARTRELO	(PARTEMIT+SECTCNT)
+#define	PARTNAME	(PARTRELO+1)
+#define	PARTCHAR	(PARTNAME+1)
+#ifdef SYMDBUG
+#define PARTDBUG	(PARTCHAR+1)
+#else
+#define PARTDBUG	(PARTCHAR+0)
+#endif
+#define	NPARTS		(PARTDBUG + 1)
+
+#define getsect(s)      (PARTEMIT+((s)>=(SECTCNT-1)?(SECTCNT-1):(s)))
Index: /trunk/minix/commands/aal/out.h
===================================================================
--- /trunk/minix/commands/aal/out.h	(revision 9)
+++ /trunk/minix/commands/aal/out.h	(revision 9)
@@ -0,0 +1,126 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/commands/aal/out.h,v 1.1.1.1 2005/04/21 14:53:57 beng Exp $ */
+
+#ifndef __OUT_H_INCLUDED
+#define __OUT_H_INCLUDED
+/*
+ * output format for ACK assemblers
+ */
+#ifndef ushort
+#define ushort	unsigned short
+#endif /* ushort */
+
+struct outhead {
+	ushort 	oh_magic;	/* magic number */
+	ushort 	oh_stamp;	/* version stamp */
+	ushort	oh_flags;	/* several format flags */
+	ushort	oh_nsect;	/* number of outsect structures */
+	ushort	oh_nrelo;	/* number of outrelo structures */
+	ushort	oh_nname;	/* number of outname structures */
+	long	oh_nemit;	/* sum of all os_flen */
+	long	oh_nchar;	/* size of string area */
+};
+
+#define O_MAGIC	0x0201		/* magic number of output file */
+#define	O_STAMP	0		/* version stamp */
+#define MAXSECT	64		/* Maximum number of sections */
+
+#define	HF_LINK	0x0004		/* unresolved references left */
+#define	HF_8086	0x0008		/* os_base specially encoded */
+
+struct outsect {
+	long 	os_base;	/* startaddress in machine */
+	long	os_size;	/* section size in machine */
+	long	os_foff;	/* startaddress in file */
+	long	os_flen;	/* section size in file */
+	long	os_lign;	/* section alignment */
+};
+
+struct outrelo {
+	char	or_type;	/* type of reference */
+	char	or_sect;	/* referencing section */
+	ushort	or_nami;	/* referenced symbol index */
+	long	or_addr;	/* referencing address */
+};
+
+struct outname {
+	union {
+	  char	*on_ptr;	/* symbol name (in core) */
+	  long	on_off;		/* symbol name (in file) */
+	}	on_u;
+#define on_mptr	on_u.on_ptr
+#define on_foff	on_u.on_off
+	ushort	on_type;	/* symbol type */
+	ushort	on_desc;	/* debug info */
+	long	on_valu;	/* symbol value */
+};
+
+/*
+ * relocation type bits
+ */
+#define RELSZ	0x07		/* relocation length */
+#define RELO1	   1		/* 1 byte */
+#define RELO2	   2		/* 2 bytes */
+#define RELO4	   4		/* 4 bytes */
+#define RELPC	0x08		/* pc relative */
+#define RELBR	0x10		/* High order byte lowest address. */
+#define RELWR	0x20		/* High order word lowest address. */
+
+/*
+ * section type bits and fields
+ */
+#define S_TYP	0x007F		/* undefined, absolute or relative */
+#define S_EXT	0x0080		/* external flag */
+#define S_ETC	0x7F00		/* for symbolic debug, bypassing 'as' */
+
+/*
+ * S_TYP field values
+ */
+#define S_UND	0x0000		/* undefined item */
+#define S_ABS	0x0001		/* absolute item */
+#define S_MIN	0x0002		/* first user section */
+#define S_MAX	(S_TYP-1)	/* last user section */
+#define S_CRS	S_TYP		/* on_valu is symbol index which contains value */
+
+/*
+ * S_ETC field values
+ */
+#define S_SCT	0x0100		/* section names */
+#define S_LIN	0x0200		/* hll source line item */
+#define S_FIL	0x0300		/* hll source file item */
+#define S_MOD	0x0400		/* ass source file item */
+#define S_COM	0x1000		/* Common name. */
+#define S_STB	0xe000		/* entries with any of these bits set are
+				   reserved for debuggers
+				*/
+
+/*
+ * structure format strings
+ */
+#define SF_HEAD		"22222244"
+#define SF_SECT		"44444"
+#define SF_RELO		"1124"
+#define SF_NAME		"4224"
+
+/*
+ * structure sizes (bytes in file; add digits in SF_*)
+ */
+#define SZ_HEAD		20
+#define SZ_SECT		20
+#define SZ_RELO		8
+#define SZ_NAME		12
+
+/*
+ * file access macros
+ */
+#define BADMAGIC(x)	((x).oh_magic!=O_MAGIC)
+#define OFF_SECT(x)	SZ_HEAD
+#define OFF_EMIT(x)	(OFF_SECT(x) + ((long)(x).oh_nsect * SZ_SECT))
+#define OFF_RELO(x)	(OFF_EMIT(x) + (x).oh_nemit)
+#define OFF_NAME(x)	(OFF_RELO(x) + ((long)(x).oh_nrelo * SZ_RELO))
+#define OFF_CHAR(x)	(OFF_NAME(x) + ((long)(x).oh_nname * SZ_NAME))
+
+#endif /* __OUT_H_INCLUDED */
Index: /trunk/minix/commands/aal/param.h
===================================================================
--- /trunk/minix/commands/aal/param.h	(revision 9)
+++ /trunk/minix/commands/aal/param.h	(revision 9)
@@ -0,0 +1,7 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/commands/aal/param.h,v 1.1.1.1 2005/04/21 14:53:57 beng Exp $ */
+
+#define SSIZE 1024
Index: /trunk/minix/commands/aal/print.c
===================================================================
--- /trunk/minix/commands/aal/print.c	(revision 9)
+++ /trunk/minix/commands/aal/print.c	(revision 9)
@@ -0,0 +1,42 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/commands/aal/print.c,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <system.h>
+#include "param.h"
+
+/*VARARGS*/
+/*FORMAT0v $
+	%s = char *
+	%l = long
+	%c = int
+	%[uxbo] = unsigned int
+	%d = int
+$ */
+int
+#if __STDC__
+print(char *fmt, ...)
+#else
+print(fmt, va_alist)
+	char *fmt;
+	va_dcl
+#endif
+{
+	va_list args;
+	char buf[SSIZE];
+
+#if __STDC__
+	va_start(args, fmt);
+#else
+	va_start(args);
+#endif
+	sys_write(STDOUT, buf, _format(buf, fmt, args));
+	va_end(args);
+}
Index: /trunk/minix/commands/aal/ranlib.h
===================================================================
--- /trunk/minix/commands/aal/ranlib.h	(revision 9)
+++ /trunk/minix/commands/aal/ranlib.h	(revision 9)
@@ -0,0 +1,34 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/commands/aal/ranlib.h,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+
+#ifndef __RANLIB_H_INCLUDED
+#define __RANLIB_H_INCLUDED
+
+#ifndef SYMDEF
+#	define SYMDEF	"__.SYMDEF"
+#endif /* SYMDEF */
+
+/*
+ * Structure of the SYMDEF table of contents for an archive.
+ * SYMDEF begins with a long giving the number of ranlib
+ * structures that immediately follow, and then continues with a string
+ * table consisting of a long giving the number of bytes of
+ * strings that follow and then the strings themselves.
+ */
+struct ranlib {
+	union {
+	  char	*ran__ptr;	/* symbol name (in core) */
+	  long	ran__off;	/* symbol name (in file) */
+	}	ran_u;
+#define ran_ptr ran_u.ran__ptr
+#define ran_off ran_u.ran__off
+	long	ran_pos;	/* library member is at this position */
+};
+
+#define SZ_RAN	8
+#define SF_RAN	"44"
+
+#endif /* __RANLIB_H_INCLUDED */
Index: /trunk/minix/commands/aal/rd.c
===================================================================
--- /trunk/minix/commands/aal/rd.c	(revision 9)
+++ /trunk/minix/commands/aal/rd.c	(revision 9)
@@ -0,0 +1,254 @@
+/* $Header: /cvsup/minix/src/commands/aal/rd.c,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#include <out.h>
+#include "object.h"
+
+extern long		lseek();
+
+/*
+ * Parts of the output file.
+ */
+#undef PARTEMIT
+#undef PARTRELO
+#undef PARTNAME
+#undef PARTCHAR
+#undef PARTDBUG
+#undef NPARTS
+
+#define	PARTEMIT	0
+#define	PARTRELO	1
+#define	PARTNAME	2
+#define	PARTCHAR	3
+#ifdef SYMDBUG
+#define PARTDBUG	4
+#else
+#define PARTDBUG	3
+#endif
+#define	NPARTS		(PARTDBUG + 1)
+
+static long		offset[MAXSECT];
+
+static int		outfile;
+static long		outseek[NPARTS];
+static long		currpos;
+static long		rd_base;
+#define OUTSECT(i) \
+	(outseek[PARTEMIT] = offset[i])
+#define BEGINSEEK(p, o) \
+	(outseek[(p)] = (o))
+
+static int sectionnr;
+
+static
+OUTREAD(p, b, n)
+	char *b;
+	long n;
+{
+	register long l = outseek[p];
+
+	if (currpos != l) {
+		lseek(outfile, l, 0);
+	}
+	rd_bytes(outfile, b, n);
+	l += n;
+	currpos = l;
+	outseek[p] = l;
+}
+
+/*
+ * Open the output file according to the chosen strategy.
+ */
+int
+rd_open(f)
+	char *f;
+{
+
+	if ((outfile = open(f, 0)) < 0)
+		return 0;
+	return rd_fdopen(outfile);
+}
+
+static int offcnt;
+
+rd_fdopen(fd)
+{
+	register int i;
+
+	for (i = 0; i < NPARTS; i++) outseek[i] = 0;
+	offcnt = 0;
+	rd_base = lseek(fd, 0L, 1);
+	if (rd_base < 0) {
+		return 0;
+	}
+	currpos = rd_base;
+	outseek[PARTEMIT] = currpos;
+	outfile = fd;
+	sectionnr = 0;
+	return 1;
+}
+
+rd_close()
+{
+
+	close(outfile);
+	outfile = -1;
+}
+
+rd_fd()
+{
+	return outfile;
+}
+
+rd_ohead(head)
+	register struct outhead	*head;
+{
+	register long off;
+
+	OUTREAD(PARTEMIT, (char *) head, (long) SZ_HEAD);
+#if ! (BYTES_REVERSED || WORDS_REVERSED)
+	if (sizeof(struct outhead) != SZ_HEAD)
+#endif
+	{
+		register char *c = (char *) head + (SZ_HEAD-4);
+		
+		head->oh_nchar = get4(c);
+		c -= 4; head->oh_nemit = get4(c);
+		c -= 2; head->oh_nname = uget2(c);
+		c -= 2; head->oh_nrelo = uget2(c);
+		c -= 2; head->oh_nsect = uget2(c);
+		c -= 2; head->oh_flags = uget2(c);
+		c -= 2; head->oh_stamp = uget2(c);
+		c -= 2; head->oh_magic = uget2(c);
+	}
+	off = OFF_RELO(*head) + rd_base;
+	BEGINSEEK(PARTRELO, off);
+	off += (long) head->oh_nrelo * SZ_RELO;
+	BEGINSEEK(PARTNAME, off);
+	off += (long) head->oh_nname * SZ_NAME;
+	BEGINSEEK(PARTCHAR, off);
+#ifdef SYMDBUG
+	off += head->oh_nchar;
+	BEGINSEEK(PARTDBUG, off);
+#endif
+}
+
+rd_rew_relos(head)
+	register struct outhead *head;
+{
+	register long off = OFF_RELO(*head) + rd_base;
+
+	BEGINSEEK(PARTRELO, off);
+}
+
+rd_sect(sect, cnt)
+	register struct outsect	*sect;
+	register unsigned int	cnt;
+{
+	register char *c = (char *) sect + cnt * SZ_SECT;
+
+	OUTREAD(PARTEMIT, (char *) sect, (long)cnt * SZ_SECT);
+	sect += cnt;
+	offcnt += cnt;
+	while (cnt--) {
+		sect--;
+#if ! (BYTES_REVERSED || WORDS_REVERSED)
+		if (sizeof(struct outsect) != SZ_SECT)
+#endif
+		{
+			c -= 4; sect->os_lign = get4(c);
+			c -= 4; sect->os_flen = get4(c);
+			c -= 4; sect->os_foff = get4(c);
+		}
+		offset[--offcnt] = sect->os_foff + rd_base;
+#if ! (BYTES_REVERSED || WORDS_REVERSED)
+		if (sizeof(struct outsect) != SZ_SECT)
+#endif
+		{
+			c -= 4; sect->os_size = get4(c);
+			c -= 4; sect->os_base = get4(c);
+		}
+	}
+}
+
+rd_outsect(s)
+{
+	OUTSECT(s);
+	sectionnr = s;
+}
+
+/*
+ * We don't have to worry about byte order here.
+ */
+rd_emit(emit, cnt)
+	char		*emit;
+	long		cnt;
+{
+	OUTREAD(PARTEMIT, emit, cnt);
+	offset[sectionnr] += cnt;
+}
+
+rd_relo(relo, cnt)
+	register struct outrelo	*relo;
+	register unsigned int cnt;
+{
+
+	OUTREAD(PARTRELO, (char *) relo, (long) cnt * SZ_RELO);
+#if ! (BYTES_REVERSED || WORDS_REVERSED)
+	if (sizeof(struct outrelo) != SZ_RELO)
+#endif
+	{
+		register char *c = (char *) relo + (long) cnt * SZ_RELO;
+
+		relo += cnt;
+		while (cnt--) {
+			relo--;
+			c -= 4; relo->or_addr = get4(c);
+			c -= 2; relo->or_nami = uget2(c);
+			relo->or_sect = *--c;
+			relo->or_type = *--c;
+		}
+	}
+}
+
+rd_name(name, cnt)
+	register struct outname	*name;
+	register unsigned int cnt;
+{
+
+	OUTREAD(PARTNAME, (char *) name, (long) cnt * SZ_NAME);
+#if ! (BYTES_REVERSED || WORDS_REVERSED)
+	if (sizeof(struct outname) != SZ_NAME)
+#endif
+	{
+		register char *c = (char *) name + (long) cnt * SZ_NAME;
+
+		name += cnt;
+		while (cnt--) {
+			name--;
+			c -= 4; name->on_valu = get4(c);
+			c -= 2; name->on_desc = uget2(c);
+			c -= 2; name->on_type = uget2(c);
+			c -= 4; name->on_foff = get4(c);
+		}
+	}
+}
+
+rd_string(addr, len)
+	char *addr;
+	long len;
+{
+	
+	OUTREAD(PARTCHAR, addr, len);
+}
+
+#ifdef SYMDBUG
+rd_dbug(buf, size)
+	char		*buf;
+	long		size;
+{
+	OUTREAD(PARTDBUG, buf, size);
+}
+#endif
Index: /trunk/minix/commands/aal/rd_arhdr.c
===================================================================
--- /trunk/minix/commands/aal/rd_arhdr.c	(revision 9)
+++ /trunk/minix/commands/aal/rd_arhdr.c	(revision 9)
@@ -0,0 +1,35 @@
+/* $Header: /cvsup/minix/src/commands/aal/rd_arhdr.c,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#include <arch.h>
+#include "object.h"
+
+int
+rd_arhdr(fd, arhdr)
+	register struct ar_hdr	*arhdr;
+{
+	char buf[AR_TOTAL];
+	register char *c = buf;
+	register char *p = arhdr->ar_name;
+	register int i;
+
+	i = read(fd, c, AR_TOTAL);
+	if (i == 0) return 0;
+	if (i != AR_TOTAL) {
+		rd_fatal();
+	}
+	i = 14;
+	while (i--) {
+		*p++ = *c++;
+	}
+	arhdr->ar_date = ((long) get2(c)) << 16; c += 2;
+	arhdr->ar_date |= ((long) get2(c)) & 0xffff; c += 2;
+	arhdr->ar_uid = *c++;
+	arhdr->ar_gid = *c++;
+	arhdr->ar_mode = get2(c); c += 2;
+	arhdr->ar_size = (long) get2(c) << 16; c += 2;
+	arhdr->ar_size |= (long) get2(c) & 0xffff;
+	return 1;
+}
Index: /trunk/minix/commands/aal/rd_bytes.c
===================================================================
--- /trunk/minix/commands/aal/rd_bytes.c	(revision 9)
+++ /trunk/minix/commands/aal/rd_bytes.c	(revision 9)
@@ -0,0 +1,32 @@
+/* $Header: /cvsup/minix/src/commands/aal/rd_bytes.c,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#define MININT		(1 << (sizeof(int) * 8 - 1))
+#define MAXCHUNK	(~MININT)	/* Highest count we read(2).	*/
+/* Unfortunately, MAXCHUNK is too large with some  compilers. Put it in
+   an int!
+*/
+
+static int maxchunk = MAXCHUNK;
+
+/*
+ * We don't have to worry about byte order here.
+ * Just read "cnt" bytes from file-descriptor "fd".
+ */
+int 
+rd_bytes(fd, string, cnt)
+	register char	*string;
+	register long	cnt;
+{
+
+	while (cnt) {
+		register int n = cnt >= maxchunk ? maxchunk : cnt;
+
+		if (read(fd, string, n) != n)
+			rd_fatal();
+		string += n;
+		cnt -= n;
+	}
+}
Index: /trunk/minix/commands/aal/rd_unsig2.c
===================================================================
--- /trunk/minix/commands/aal/rd_unsig2.c	(revision 9)
+++ /trunk/minix/commands/aal/rd_unsig2.c	(revision 9)
@@ -0,0 +1,15 @@
+/* $Header: /cvsup/minix/src/commands/aal/rd_unsig2.c,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#include "object.h"
+
+unsigned int
+rd_unsigned2(fd)
+{
+	char buf[2];
+
+	rd_bytes(fd, buf, 2L);
+	return uget2(buf);
+}
Index: /trunk/minix/commands/aal/sprint.c
===================================================================
--- /trunk/minix/commands/aal/sprint.c	(revision 9)
+++ /trunk/minix/commands/aal/sprint.c	(revision 9)
@@ -0,0 +1,42 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/commands/aal/sprint.c,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <system.h>
+#include "param.h"
+
+/*VARARGS*/
+/*FORMAT1v $
+	%s = char *
+	%l = long
+	%c = int
+	%[uxbo] = unsigned int
+	%d = int
+$ */
+char *
+#if __STDC__
+sprint(char *buf, char *fmt, ...)
+#else
+sprint(buf, fmt, va_alist)
+	char *buf, *fmt;
+	va_dcl
+#endif
+{
+	va_list args;
+
+#if __STDC__
+	va_start(args, fmt);
+#else
+	va_start(args);
+#endif
+	buf[_format(buf, fmt, args)] = '\0';
+	va_end(args);
+	return buf;
+}
Index: /trunk/minix/commands/aal/system.c
===================================================================
--- /trunk/minix/commands/aal/system.c	(revision 9)
+++ /trunk/minix/commands/aal/system.c	(revision 9)
@@ -0,0 +1,24 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* RCS: $Header: /cvsup/minix/src/commands/aal/system.c,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+
+#include <system.h>
+
+File _sys_ftab[SYS_NOPEN] = {
+	{ 0, OP_READ},
+	{ 1, OP_APPEND},
+	{ 2, OP_APPEND}
+};
+
+File *
+_get_entry()
+{
+	register File *fp;
+
+	for (fp = &_sys_ftab[0]; fp < &_sys_ftab[SYS_NOPEN]; fp++)
+		if (fp->o_flags == 0)
+			return fp;
+	return (File *)0;
+}
Index: /trunk/minix/commands/aal/system.h
===================================================================
--- /trunk/minix/commands/aal/system.h	(revision 9)
+++ /trunk/minix/commands/aal/system.h	(revision 9)
@@ -0,0 +1,47 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* RCS: $Header: /cvsup/minix/src/commands/aal/system.h,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+#ifndef __SYSTEM_INCLUDED__
+#define __SYSTEM_INCLUDED__
+
+struct _sys_fildes {
+	int o_fd;	/* UNIX filedescriptor */
+	int o_flags;	/* flags for open; 0 if not used */
+};
+
+typedef struct _sys_fildes File;
+
+extern File _sys_ftab[];
+
+/* flags for sys_open() */
+#define OP_READ		01
+#define OP_WRITE	02
+#define OP_APPEND	04
+
+/* flags for sys_access() */
+#define AC_EXIST	00
+#define AC_READ		04
+#define AC_WRITE	02
+#define AC_EXEC		01
+
+/* flags for sys_stop() */
+#define S_END	0
+#define S_EXIT	1
+#define S_ABORT	2
+
+/* standard file decsriptors */
+#define STDIN	&_sys_ftab[0]
+#define STDOUT	&_sys_ftab[1]
+#define STDERR	&_sys_ftab[2]
+
+/* maximum number of open files */
+#define SYS_NOPEN	20
+
+/* return value for sys_break */
+#define ILL_BREAK	((char *)0)
+
+/* system's idea of block */
+#define BUFSIZ	1024
+#endif __SYSTEM_INCLUDED__
Index: /trunk/minix/commands/aal/varargs.h
===================================================================
--- /trunk/minix/commands/aal/varargs.h	(revision 9)
+++ /trunk/minix/commands/aal/varargs.h	(revision 9)
@@ -0,0 +1,16 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/commands/aal/varargs.h,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+
+#ifndef _VARARGS_H
+#define _VARARGS_H
+
+typedef char *va_list;
+# define __va_sz(mode)	(((sizeof(mode) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+# define va_dcl int va_alist;
+# define va_start(list) (list = (char *) &va_alist)
+# define va_end(list)
+# define va_arg(list,mode) (*((mode *)((list += __va_sz(mode)) - __va_sz(mode))))
+#endif /* _VARARGS_H */
Index: /trunk/minix/commands/aal/wr_arhdr.c
===================================================================
--- /trunk/minix/commands/aal/wr_arhdr.c	(revision 9)
+++ /trunk/minix/commands/aal/wr_arhdr.c	(revision 9)
@@ -0,0 +1,28 @@
+/* $Header: /cvsup/minix/src/commands/aal/wr_arhdr.c,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#include <arch.h>
+#include "object.h"
+
+wr_arhdr(fd, arhdr)
+	register struct ar_hdr	*arhdr;
+{
+	char buf[AR_TOTAL];
+	register char *c = buf;
+	register char *p = arhdr->ar_name;
+	register int i = 14;
+
+	while (i--) {
+		*c++ = *p++;
+	}
+	put2((int)(arhdr->ar_date>>16),c); c += 2;
+	put2((int)(arhdr->ar_date),c); c += 2;
+	*c++ = arhdr->ar_uid;
+	*c++ = arhdr->ar_gid;
+	put2(arhdr->ar_mode,c); c += 2;
+	put2((int)(arhdr->ar_size>>16),c); c += 2;
+	put2((int)(arhdr->ar_size),c);
+	wr_bytes(fd, buf, (long) AR_TOTAL);
+}
Index: /trunk/minix/commands/aal/wr_bytes.c
===================================================================
--- /trunk/minix/commands/aal/wr_bytes.c	(revision 9)
+++ /trunk/minix/commands/aal/wr_bytes.c	(revision 9)
@@ -0,0 +1,30 @@
+/* $Header: /cvsup/minix/src/commands/aal/wr_bytes.c,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#define MININT		(1 << (sizeof(int) * 8 - 1))
+#define MAXCHUNK	(~MININT)	/* Highest count we write(2).	*/
+/* Notice that MAXCHUNK itself might be too large with some compilers.
+   You have to put it in an int!
+*/
+
+static int maxchunk = MAXCHUNK;
+
+/*
+ * Just write "cnt" bytes to file-descriptor "fd".
+ */
+wr_bytes(fd, string, cnt)
+	register char	*string;
+	register long	cnt;
+{
+
+	while (cnt) {
+		register int n = cnt >= maxchunk ? maxchunk : cnt;
+
+		if (write(fd, string, n) != n)
+			wr_fatal();
+		string += n;
+		cnt -= n;
+	}
+}
Index: /trunk/minix/commands/aal/wr_int2.c
===================================================================
--- /trunk/minix/commands/aal/wr_int2.c	(revision 9)
+++ /trunk/minix/commands/aal/wr_int2.c	(revision 9)
@@ -0,0 +1,14 @@
+/* $Header: /cvsup/minix/src/commands/aal/wr_int2.c,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#include "object.h"
+
+wr_int2(fd, i)
+{
+	char buf[2];
+
+	put2(i, buf);
+	wr_bytes(fd, buf, 2L);
+}
Index: /trunk/minix/commands/aal/wr_long.c
===================================================================
--- /trunk/minix/commands/aal/wr_long.c	(revision 9)
+++ /trunk/minix/commands/aal/wr_long.c	(revision 9)
@@ -0,0 +1,15 @@
+/* $Header: /cvsup/minix/src/commands/aal/wr_long.c,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#include "object.h"
+
+wr_long(fd, l)
+	long l;
+{
+	char buf[4];
+
+	put4(l, buf);
+	wr_bytes(fd, buf, 4L);
+}
Index: /trunk/minix/commands/aal/wr_ranlib.c
===================================================================
--- /trunk/minix/commands/aal/wr_ranlib.c	(revision 9)
+++ /trunk/minix/commands/aal/wr_ranlib.c	(revision 9)
@@ -0,0 +1,36 @@
+/* $Header: /cvsup/minix/src/commands/aal/wr_ranlib.c,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#include <ranlib.h>
+#include "object.h"
+
+wr_ranlib(fd, ran, cnt)
+	register struct ranlib	*ran;
+	register long	cnt;
+{
+#if ! (BYTES_REVERSED || WORDS_REVERSED)
+	if (sizeof (struct ranlib) != SZ_RAN)
+#endif
+	{
+		char buf[100 * SZ_RAN];
+
+		while (cnt) {
+			register int i = (cnt > 100) ? 100 : cnt;
+			register char *c = buf;
+			long j = i * SZ_RAN;
+
+			cnt -= i;
+			while (i--) {
+				put4(ran->ran_off,c); c += 4;
+				put4(ran->ran_pos,c); c += 4;
+				ran++;
+			}
+			wr_bytes(fd, buf, j);
+		}
+	}
+#if ! (BYTES_REVERSED || WORDS_REVERSED)
+	else	wr_bytes(fd, (char *) ran, cnt * SZ_RAN);
+#endif
+}
Index: /trunk/minix/commands/aal/write.c
===================================================================
--- /trunk/minix/commands/aal/write.c	(revision 9)
+++ /trunk/minix/commands/aal/write.c	(revision 9)
@@ -0,0 +1,17 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/commands/aal/write.c,v 1.1.1.1 2005/04/21 14:53:58 beng Exp $ */
+
+#include <system.h>
+
+int
+sys_write(fp, bufptr, nbytes)
+	File *fp;
+	char *bufptr;
+	int nbytes;
+{
+	if (! fp) return 0;
+	return write(fp->o_fd, bufptr, nbytes) == nbytes;
+}
Index: /trunk/minix/commands/advent/Makefile
===================================================================
--- /trunk/minix/commands/advent/Makefile	(revision 9)
+++ /trunk/minix/commands/advent/Makefile	(revision 9)
@@ -0,0 +1,63 @@
+# Makefile for advent
+
+# Where to put the adventure text files, and the binary executable.
+# Need the trailing "/"s.
+TEXTDIR	= /usr/lib/advent/
+BINDIR	= /usr/bin
+
+# Flags you may want to add to CFLAGS:
+# -DHAS_STDC=0 or 1	We have Standard C.  Default=1 iff __STDC__ is nonzero.
+
+CC	= exec cc
+CFLAGS	= -D_POSIX_SOURCE
+LDFLAGS	=  -i
+
+OBJS	= advent.o database.o english.o initial.o itverb.o score.o\
+	travel.o turn.o utility.o verb.o vocab.o
+
+DAT	= advent1.dat advent2.dat advent3.dat advent4.dat
+INSTDAT	= $(TEXTDIR)advent1.dat $(TEXTDIR)advent2.dat \
+	  $(TEXTDIR)advent3.dat $(TEXTDIR)advent4.dat
+
+all:	$(DAT) advent
+
+install:	$(TEXTDIR) $(INSTDAT) $(BINDIR)/advent
+
+$(TEXTDIR):
+	install -d -o bin $(TEXTDIR)
+
+$(TEXTDIR)advent1.dat:	advent1.dat
+	install -c -o bin $? $@
+
+$(TEXTDIR)advent2.dat:	advent2.dat
+	install -c -o bin $? $@
+
+$(TEXTDIR)advent3.dat:	advent3.dat
+	install -c -o bin $? $@
+
+$(TEXTDIR)advent4.dat:	advent4.dat
+	install -c -o bin $? $@
+
+$(BINDIR)/advent:	advent
+	install -cs -o bin $? $@
+
+advent:	$(OBJS)
+	$(CC) $(LDFLAGS) -o advent $(OBJS)
+
+setup: setup.c advent.h
+	$(CC) $(CFLAGS) $(LDFLAGS) -o setup setup.c
+ 
+advtext.h advent1.dat advent2.dat advent3.dat advent4.dat: \
+		setup advent1.txt advent2.txt advent3.txt advent4.txt
+	./setup
+
+advent.o: advent.h advdec.h advent.c
+	$(CC) -c $(CFLAGS) -DTEXTDIR='"$(TEXTDIR)"' advent.c
+
+database.o: advent.h advdec.h advtext.h
+travel.o: advent.h advdec.h advcave.h
+initial.o english.o itverb.o score.o turn.o utility.o\
+	verb.o vocab.o: advent.h advdec.h
+
+clean:	
+	@rm -f *.o *.BAK *.dat advtext.h core advent setup
Index: /trunk/minix/commands/advent/advcave.h
===================================================================
--- /trunk/minix/commands/advent/advcave.h	(revision 9)
+++ /trunk/minix/commands/advent/advcave.h	(revision 9)
@@ -0,0 +1,1357 @@
+/*	header ADVCAVE.H					*/
+
+
+/**	WARNING: the travel array for the cave is stored as an
+ *   array of 1.. LONG INTEGERS.  This requires 32 bit LONG INTEGERS.
+ *   These values are used in database.c "gettrav".
+ *   tcond*1000000 + tdest*1000 + tverb = value stored
+ */
+
+static long room1[] = {
+		       2002, 2044, 2029, 2056,
+		       3003, 3012, 3019, 3043,
+		       4005, 4013, 4014, 4046, 4030,
+		       5006, 5045, 5043,
+		       8063,
+		       147081,
+		       157052, 157084,
+		       0};
+static long room2[] = {
+		       1002, 1012, 1007, 1043, 1045, 1030,
+		       30146006,
+		       5006, 5045, 5046,
+		       146044,
+		       0};
+static long room3[] = {
+		       1011, 1032, 1044,
+		       11062,
+		       33065,
+		       467785085,
+		       202085,
+		       79005, 79014,
+		       238057, 238003, 238019,
+		       0};
+static long room4[] = {
+		       1004, 1012, 1045,
+		       5006, 5043, 5044, 5029,
+		       7005, 7046, 7030,
+		       8063,
+		       0};
+static long room5[] = {
+		       4009, 4043, 4030,
+		       50005006, 50005007, 50005045,
+		       6006,
+		       5044, 5046,
+		       0};
+static long room6[] = {
+		       1002, 1045,
+		       4009, 4043, 4044, 4030,
+		       5006, 5046,
+		       0};
+static long room7[] = {
+		       1012,
+		       4004, 4045,
+		       5006, 5043, 5044,
+		       8005, 8015, 8016, 8046,
+		       595060, 595014, 595030,
+		       0};
+static long room8[] = {
+		       5006, 5043, 5044, 5046,
+		       1012,
+		       7004, 7013, 7045,
+		       303009003, 303009019, 303009030,
+		       593003,
+		       0};
+static long room9[] = {
+		       303008011, 303008029,
+		       593011,
+		       10017, 10018, 10019, 10044,
+		       14031,
+		       11051,
+		       0};
+static long room10[] = {
+			9011, 9020, 9021, 9043,
+			11019, 11022, 11044, 11051,
+			14031,
+			0};
+static long room11[] = {
+			303008063,
+			9064,
+			10017, 10018, 10023, 10024, 10043,
+			12025, 12019, 12029, 12044,
+			3062,
+			14031,
+			0};
+static long room12[] = {
+			303008063,
+			9064,
+			11030, 11043, 11051,
+			13019, 13029, 13044,
+			14031,
+			0};
+static long room13[] = {
+			303008063,
+			9064,
+			11051,
+			12025, 12043,
+			14023, 14031, 14044,
+			0};
+static long room14[] = {
+			303008063,
+			9064,
+			11051,
+			13023, 13043,
+			150020030, 150020031, 150020034,
+			15030,
+			16033, 16044,
+			0};
+static long room15[] = {
+			18036, 18046,
+			17007, 17038, 17044,
+			19010, 19030, 19045,
+			150022029, 150022031, 150022034, 150022035,
+			150022023, 150022043, 150022056, 150022010,
+			14029,
+			33055,
+			0};
+static long room16[] = {
+			14001,
+			0};
+static long room17[] = {
+			15038, 15043,
+			312596039,
+			412021007,
+		412597041, 412597042, 412597044, 412597069, 412597089,
+			27041,
+			0};
+static long room18[] = {
+			15038, 15011, 15045,
+			0};
+static long room19[] = {
+			150237029, 150237031, 150237034, 150237035,
+			150237043, 150237056, 150237010,
+			15025,
+			15010, 15029, 15043,
+			75556047,
+			311143047,
+			311028045, 311028036,
+			311029046, 311029037,
+			311030044, 311030007,
+			32045,
+			15074049,
+			211032049,
+			74066,
+			0};
+static long room20[] = {
+			1,
+			0};
+static long room21[] = {
+			1,
+			0};
+static long room22[] = {
+			15001,
+			0};
+static long room23[] = {
+			67043, 67042,
+			68044, 68061,
+			25030, 25031,
+			648052,
+			0};
+static long room24[] = {
+			67029, 67011,
+			92027,
+			0};
+static long room25[] = {
+			23029, 23011,
+			724031056,
+			26056,
+			0};
+static long room26[] = {
+			88001,
+			0};
+static long room27[] = {
+			312596039,
+			412021007,
+		412597041, 412597042, 412597043, 412597069, 412597089,
+			17041,
+			40045,
+			41044,
+			0};
+static long room28[] = {
+			19038, 19011, 19046,
+			33045, 33055,
+			36030, 36052,
+			0};
+static long room29[] = {
+			19038, 19011, 19045,
+			0};
+static long room30[] = {
+			19038, 19011, 19043,
+			62044, 62029,
+			0};
+static long room31[] = {
+			524089001,
+			90001,
+			0};
+static long room32[] = {
+			19001,
+			0};
+static long room33[] = {
+			3065,
+			28046,
+			34043, 34053, 34054,
+			35044,
+			159302071,
+			100071,
+			0};
+static long room34[] = {
+			33030, 33055,
+			15029,
+			0};
+static long room35[] = {
+			33043, 33055,
+			20039,
+			0};
+static long room36[] = {
+			37043, 37017,
+			28029, 28052,
+			39044,
+			65070,
+			0};
+static long room37[] = {
+			36044, 36017,
+			38030, 38031, 38056,
+			0};
+static long room38[] = {
+			37056, 37029, 37011,
+			595060, 595014, 595030, 595004, 595005,
+			0};
+static long room39[] = {
+			36043, 36023,
+			64030, 64052, 64058,
+			65070,
+			0};
+static long room40[] = {
+			41001,
+			0};
+static long room41[] = {
+			42046, 42029, 42023, 42056,
+			27043,
+			59045,
+			60044, 60017,
+			0};
+static long room42[] = {
+			41029,
+			42045,
+			43043,
+			45046,
+			80044,
+			0};
+static long room43[] = {
+			42044,
+			44046,
+			45043,
+			0};
+static long room44[] = {
+			43043,
+			48030,
+			50046,
+			82045,
+			0};
+static long room45[] = {
+			42044,
+			43045,
+			46043,
+			47046,
+			87029, 87030,
+			0};
+static long room46[] = {
+			45044, 45011,
+			0};
+static long room47[] = {
+			45043, 45011,
+			0};
+static long room48[] = {
+			44029, 44011,
+			0};
+static long room49[] = {
+			50043,
+			51044,
+			0};
+static long room50[] = {
+			44043,
+			49044,
+			51030,
+			52046,
+			0};
+static long room51[] = {
+			49044,
+			50029,
+			52043,
+			53046,
+			0};
+static long room52[] = {
+			50044,
+			51043,
+			52046,
+			53029,
+			55045,
+			86030,
+			0};
+static long room53[] = {
+			51044,
+			52045,
+			54046,
+			0};
+static long room54[] = {
+			53044, 53011,
+			0};
+static long room55[] = {
+			52044,
+			55045,
+			56030,
+			57043,
+			0};
+static long room56[] = {
+			55029, 55011,
+			0};
+static long room57[] = {
+			13030, 13056,
+			55044,
+			58046,
+			83045,
+			84043,
+			0};
+static long room58[] = {
+			57043, 57011,
+			0};
+static long room59[] = {
+			27001,
+			0};
+static long room60[] = {
+			41043, 41029, 41017,
+			61044,
+			62045, 62030, 62052,
+			50191046, 50191033,
+			392173046, 392173033,
+			172046, 172033,
+			648056,
+			0};
+static long room61[] = {
+			60043,
+			62045,
+			100107046,
+			0};
+static long room62[] = {
+			60044,
+			63045,
+			30043,
+			61046,
+			0};
+static long room63[] = {
+			62046, 62011,
+			0};
+static long room64[] = {
+			39029, 39056, 39059,
+			65044, 65070,
+			103045, 103074,
+			106043,
+			0};
+static long room65[] = {
+			64043,
+			66044,
+			40556046,
+			68061,
+			40556029,
+			50070029,
+			39029,
+			40556045,
+			50072045,
+			71045,
+			50556030,
+			106030,
+			71025,
+			0};
+static long room66[] = {
+			65047,
+			67044,
+			80556046,
+			77025,
+			96043,
+			50556050,
+			97072,
+			0};
+static long room67[] = {
+			66043,
+			23044, 23042,
+			24030, 24031,
+			0};
+static long room68[] = {
+			23046,
+			69029, 69056,
+			65045,
+			0};
+static long room69[] = {
+			68030, 68061,
+			331120046,
+			119046,
+			109045,
+			113075,
+			0};
+static long room70[] = {
+			71045,
+			65030, 65023,
+			111046,
+			0};
+static long room71[] = {
+			65048,
+			70046,
+			110045,
+			0};
+static long room72[] = {
+			65070,
+			118047,
+			73045,
+			97049, 97072,
+			0};
+static long room73[] = {
+			72046, 72017, 72011,
+			0};
+static long room74[] = {
+			19043,
+			331120044,
+			121044,
+			75030,
+			0};
+static long room75[] = {
+			76046,
+			77045,
+			0};
+static long room76[] = {
+			75045,
+			0};
+static long room77[] = {
+			75043,
+			78044,
+			66045, 66017,
+			0};
+static long room78[] = {
+			77046,
+			0};
+static long room79[] = {
+			3001,
+			0};
+static long room80[] = {
+			42045,
+			80044, 80046,
+			81043,
+			0};
+static long room81[] = {
+			80044, 80011,
+			0};
+static long room82[] = {
+			44046, 44011,
+			0};
+static long room83[] = {
+			57046,
+			84043,
+			85044,
+			0};
+static long room84[] = {
+			57045,
+			83044,
+			114050,
+			0};
+static long room85[] = {
+			83043, 83011,
+			0};
+static long room86[] = {
+			52029, 52011,
+			0};
+static long room87[] = {
+			45029, 45030,
+			0};
+static long room88[] = {
+			25030, 25056, 25043,
+			20039,
+			92044, 92027,
+			0};
+static long room89[] = {
+			25001,
+			0};
+static long room90[] = {
+			23001,
+			0};
+static long room91[] = {
+			95045, 95073, 95023,
+			72030, 72056,
+			0};
+static long room92[] = {
+			88046,
+			93043,
+			94045,
+			0};
+static long room93[] = {
+			92046, 92027, 92011,
+			0};
+static long room94[] = {
+			92046, 92027, 92023,
+			341095045, 341095003, 341095073,
+			611045,
+			0};
+static long room95[] = {
+			94046, 94011,
+			92027,
+			91044,
+			145030, 145039, 145080, 145052,
+			0};
+static long room96[] = {
+			66044, 66011,
+			0};
+static long room97[] = {
+			66048,
+			72043, 72017,
+			98029, 98045, 98073,
+			0};
+static long room98[] = {
+			235047,
+			97046, 97072,
+			99044,
+			3142029, 3142049, 3142056, 3142079,
+			75702029, 75702049, 75702056, 75702079,
+			703029, 703049, 703056, 703079,
+			141078,
+			0};
+static long room99[] = {
+			98050, 98073,
+			301043, 301023,
+			100043,
+			0};
+static long room100[] = {
+			 301044, 301023, 301011,
+			 99044,
+			 159302071, 159302055,
+			 33071, 33055,
+			 101047, 101022,
+			 0};
+static long room101[] = {
+			 100046, 100071, 100011,
+			 0};
+static long room102[] = {
+			 103030, 103074, 103011,
+			 0};
+static long room103[] = {
+			 388196029, 388196038,
+			 102029, 102038,
+			 104030,
+			 114618046,
+			 115619046,
+			 64046,
+			 0};
+static long room104[] = {
+			 103029, 103074,
+			 105030,
+			 0};
+static long room105[] = {
+			 104029, 104011,
+			 103074,
+			 0};
+static long room106[] = {
+			 64029,
+			 65044,
+			 108043,
+			 0};
+static long room107[] = {
+			 131046,
+			 132049,
+			 133047,
+			 134048,
+			 135029,
+			 136050,
+			 137043,
+			 138044,
+			 139045,
+			 61030,
+			 0};
+static long room108[] = {
+			 90556043, 90556045, 90556046, 90556047,
+			 90556048, 90556049, 90556050, 90556029,
+			 90556030,
+			 106043,
+			 626044,
+			 0};
+static long room109[] = {
+			 69046,
+			 113045, 113075,
+			 0};
+static long room110[] = {
+			 71044,
+			 20039,
+			 0};
+static long room111[] = {
+			 70045,
+			 40050030, 40050039, 40050056,
+			 50053030,
+			 45030,
+			 0};
+static long room112[] = {
+			 131049,
+			 132045,
+			 133043,
+			 134050,
+			 135048,
+			 136047,
+			 137044,
+			 138030,
+			 139029,
+			 140046,
+			 0};
+static long room113[] = {
+			 109046, 109011,
+			 0};
+static long room114[] = {
+			 84048,
+			 0};
+static long room115[] = {
+			 116049, 116042, 116069,
+			 212019, 212003, 212045,
+			 0};
+static long room116[] = {
+			 115047, 115042, 115069,
+			 212019, 212003,
+			 593030,
+			 0};
+static long room117[] = {
+			 118049,
+		233660041, 233660042, 233660069, 233660047, 233660089,
+			 332661041,
+			 303041,
+			 332021039,
+			 596039,
+			 0};
+static long room118[] = {
+			 72030,
+			 117029,
+			 0};
+static long room119[] = {
+			 69045, 69011,
+			 653043, 65307,
+			 0};
+static long room120[] = {
+			 69045,
+			 74043,
+			 0};
+static long room121[] = {
+			 74043, 74011,
+			 653045, 653007,
+			 0};
+static long room122[] = {
+			 123047,
+		233660041, 233660042, 233660069, 233660049, 233660089,
+			 303041,
+			 596039,
+			 124077,
+			 126028,
+			 129040,
+			 0};
+static long room123[] = {
+			 122044,
+			 124043, 124077,
+			 126028,
+			 129040,
+			 0};
+static long room124[] = {
+			 123044,
+			 125047, 125036,
+			 128048, 128037, 128030,
+			 126028,
+			 129040,
+			 0};
+static long room125[] = {
+			 124046, 124077,
+			 126045, 126028,
+			 127043, 127017,
+			 0};
+static long room126[] = {
+			 125046, 125023, 125011,
+			 124077,
+			 610030, 610039,
+			 0};
+static long room127[] = {
+			 125044, 125011, 125017,
+			 124077,
+			 126028,
+			 0};
+static long room128[] = {
+			 124045, 124029, 124077,
+			 129046, 129030, 129040,
+			 126028,
+			 0};
+static long room129[] = {
+			 128044, 128029,
+			 124077,
+			 130043, 130019, 130040, 130003,
+			 126028,
+			 0};
+static long room130[] = {
+			 129044, 129011,
+			 124077,
+			 126028,
+			 0};
+static long room131[] = {
+			 107044,
+			 132048,
+			 133050,
+			 134049,
+			 135047,
+			 136029,
+			 137030,
+			 138045,
+			 139046,
+			 112043,
+			 0};
+static long room132[] = {
+			 107050,
+			 131029,
+			 133045,
+			 134046,
+			 135044,
+			 136049,
+			 137047,
+			 138043,
+			 139030,
+			 112048,
+			 0};
+static long room133[] = {
+			 107029,
+			 131030,
+			 132044,
+			 134047,
+			 135049,
+			 136043,
+			 137045,
+			 138050,
+			 139048,
+			 112046,
+			 0};
+static long room134[] = {
+			 107047,
+			 131045,
+			 132050,
+			 133048,
+			 135043,
+			 136030,
+			 137046,
+			 138029,
+			 139044,
+			 112049,
+			 0};
+static long room135[] = {
+			 107045,
+			 131048,
+			 132030,
+			 133046,
+			 134043,
+			 136044,
+			 137049,
+			 138047,
+			 139050,
+			 112029,
+			 0};
+static long room136[] = {
+			 107043,
+			 131044,
+			 132029,
+			 133049,
+			 134030,
+			 135046,
+			 137050,
+			 138048,
+			 139047,
+			 112045,
+			 0};
+static long room137[] = {
+			 107048,
+			 131047,
+			 132046,
+			 133030,
+			 134029,
+			 135050,
+			 136045,
+			 138049,
+			 139043,
+			 112044,
+			 0};
+static long room138[] = {
+			 107030,
+			 131043,
+			 132047,
+			 133029,
+			 134044,
+			 135045,
+			 136046,
+			 137048,
+			 139049,
+			 112050,
+			 0};
+static long room139[] = {
+			 107049,
+			 131050,
+			 132043,
+			 133044,
+			 134045,
+			 135030,
+			 136048,
+			 137029,
+			 138046,
+			 112047,
+			 0};
+static long room140[] = {
+			 112045, 112011,
+			 0};
+static long room141[] = {
+			 142029, 142043, 142056, 142078, 142079,
+			 0};
+static long room142[] = {
+			 98043, 98030, 98007, 98079,
+			 141008, 141044, 141078,
+			 0};
+static long room143[] = {
+			 19044, 19011,
+			 144043,
+			 0};
+static long room144[] = {
+			 143044, 143008,
+			 19011,
+			 0};
+static long room145[] = {
+			 141001,
+			 0};
+static long room146[] = {
+			 2043, 2029, 2002, 2056,
+			 50006046, 50006006,
+			 146046, 146006,
+			 147044,
+			 148045,
+			 0};
+static long room147[] = {
+			 146043, 146046,
+			 148045,
+			 153044,
+			 157052,
+			 3012,
+			 157084,
+			 0};
+static long room148[] = {
+			 50147046,
+			 146046,
+			 149043, 149044, 149045,
+			 3012,
+			 166091,
+			 0};
+static long room149[] = {
+			 149046,
+			 151043,
+			 150044,
+			 152045,
+			 0};
+static long room150[] = {
+			 151045, 151046,
+			 149043, 149044,
+			 0};
+static long room151[] = {
+			 148043,
+			 152044,
+			 150045,
+			 149046,
+			 0};
+static long room152[] = {
+			 151043,
+			 150046,
+			 0};
+static long room153[] = {
+			 154045,
+			 239046,
+			 147043,
+			 3012,
+			 0};
+static long room154[] = {
+			 50155045,
+			 157045, 157030,
+			 155029,
+			 153046,
+			 3012,
+			 0};
+static long room155[] = {
+			 154030, 154008, 154046,
+			 156039,
+			 3012,
+			 0};
+static long room156[] = {
+			 1,
+			 0};
+static long room157[] = {
+			 227019, 227043,
+			 154011, 154046, 154029,
+			 3012,
+			 0};
+static long room158[] = {
+			 229044, 229034, 229030,
+			 157011,
+			 161082,
+			 725056, 725029,
+			 726083,
+			 747003, 747019, 747043, 747064,
+			 0};
+static long room159[] = {
+			 732011, 732044, 732034,
+			 0};
+static long room160[] = {
+			 343167043, 343167019, 343167003,
+			 738043,
+			 162082,
+			 723044, 723056, 723030,
+			 165039,
+			 0};
+static long room161[] = {
+			 304001,
+			 0};
+static long room162[] = {
+			 304001,
+			 0};
+static long room163[] = {
+			 304001,
+			 0};
+static long room164[] = {
+			 304001,
+			 0};
+static long room165[] = {
+			 1,
+			 0};
+static long room166[] = {
+			 747003, 747011, 747019, 747044,
+			 148232043, 148232069, 148232041, 148232042,
+			 148169047,
+			 148233046,
+			 148234045,
+			 717043, 717069, 717041, 717042, 717047,
+			 448164082,
+			 720082,
+			 0};
+static long room167[] = {
+			 163082,
+			 343160044, 343160011, 343160003, 343160019,
+			 738044,
+			 722043, 722069, 722041, 722042,
+			 0};
+static long room168[] = {
+			 448170048, 448170029, 448170023,
+			 719048, 719029, 719023,
+			 148169045,
+			 148192046,
+			 148166044, 148166069, 148166041, 148166042,
+			 717044, 717045, 717046,
+			 0};
+static long room169[] = {
+			 148168046,
+			 148166049,
+			 717049, 717046,
+			 448179023, 448179043, 448179029,
+			 719023, 719029,
+			 0};
+static long room170[] = {
+			 171043, 171029,
+			 168044, 168030,
+			 0};
+static long room171[] = {
+			 170050, 170030,
+			 180043, 180029,
+			 0};
+static long room172[] = {
+			 60045,
+			 174046,
+			 0};
+static long room173[] = {
+			 60045,
+			 0};
+static long room174[] = {
+			 392178047,
+			 172047, 172033,
+			 175050,
+			 0};
+static long room175[] = {
+			 177045,
+			 174043,
+			 176031, 176030, 176056,
+			 0};
+static long room176[] = {
+			 175029, 175056, 175011, 175008,
+			 0};
+static long room177[] = {
+			 60030, 60056, 60039,
+			 175046, 175008,
+			 0};
+static long room178[] = {
+			 174001,
+			 0};
+static long room179[] = {
+			 169030, 169044,
+			 198029, 198043, 198014,
+			 0};
+static long room180[] = {
+			 171044,
+			 182029, 182056,
+			 213043,
+			 0};
+static long room181[] = {
+			 227001,
+			 0};
+static long room182[] = {
+			 180044,
+			 183043,
+			 0};
+static long room183[] = {
+			 182044,
+			 50184043,
+			 186043,
+			 185046,
+			 187045,
+			 0};
+static long room184[] = {
+			 183049,
+			 188048,
+			 0};
+static long room185[] = {
+			 183045,
+			 0};
+static long room186[] = {
+			 183050,
+			 188047,
+			 0};
+static long room187[] = {
+			 183044,
+			 188043,
+			 0};
+static long room188[] = {
+			 187045,
+			 184044,
+			 65190049, 65190030,
+			 186049,
+			 305019, 305003,
+			 0};
+static long room189[] = {
+			 188011, 188008,
+			 0};
+static long room190[] = {
+			 422306069, 422306045, 422306042, 422306089,
+			 661069,
+			 188029, 188008,
+			 0};
+static long room191[] = {
+			 60045,
+			 0};
+static long room192[] = {
+			 148166045,
+			 148168047,
+			 717045, 717047,
+			 448197043,
+			 720043,
+			 0};
+static long room193[] = {
+			 197044,
+			 0};
+static long room194[] = {
+			 224044,
+			 0};
+static long room195[] = {
+			 196052, 196053, 196046, 196069, 196036,
+			 224044,
+			 0};
+static long room196[] = {
+			 103030, 103074,
+			 114618052, 114618053, 114618045, 114618069,
+			 195052,
+			 0};
+static long room197[] = {
+			 193043,
+			 192044,
+			 0};
+static long room198[] = {
+			 179049, 179014, 179005, 179023,
+			 203030, 203043,
+			 402200046, 402200029,
+			 772046, 772029,
+			 0};
+static long room199[] = {
+			 198001,
+			 0};
+static long room200[] = {
+			 198044,
+			 201043, 201029,
+			 0};
+static long room201[] = {
+			 402200044, 402200030,
+			 772044, 772030,
+			 202043,
+			 230045,
+			 0};
+static long room202[] = {
+			 201044,
+			 467785085,
+			 205085,
+			 206043,
+			 0};
+static long room203[] = {
+			 447199030, 447199043, 447199088,
+			 204030, 204043, 204088,
+			 198029, 198044,
+			 0};
+static long room204[] = {
+			 203029, 203044, 203008, 203011,
+			 0};
+static long room205[] = {
+			 219045,
+			 467785085,
+			 202085,
+			 226039,
+			 0};
+static long room206[] = {
+			 207045, 207017,
+			 202044,
+			 648029, 648052,
+			 0};
+static long room207[] = {
+			 208045,
+			 206046,
+			 0};
+static long room208[] = {
+			 236043,
+			 207046, 207017,
+			 209044,
+			 793069, 793042, 793045,
+			 0};
+static long room209[] = {
+			 208043,
+			 210029, 210056,
+			 0};
+static long room210[] = {
+			 211030, 211043,
+			 209044,
+			 0};
+static long room211[] = {
+			 210029, 210008, 210044,
+			 72030, 72043,
+			 0};
+static long room212[] = {
+			 115011, 115008, 115046,
+			 0};
+static long room213[] = {
+			 206030, 206052,
+			 180044, 180008,
+			 0};
+static long room214[] = {
+			 148166046,
+			 148169048,
+			 717046, 717048,
+			 448215047,
+			 720047,
+			 0};
+static long room215[] = {
+			 214049,
+			 216029,
+			 0};
+static long room216[] = {
+			 215030,
+			 217043, 217029,
+			 0};
+static long room217[] = {
+			 216044, 216030, 216011,
+			 218043, 218031,
+			 0};
+static long room218[] = {
+			 217008, 217044,
+			 230029, 230056,
+			 0};
+static long room219[] = {
+			 205046, 205089,
+			 222045, 222090,
+			 220043,
+			 221044,
+			 3092,
+			 0};
+static long room220[] = {
+			 219044,
+			 225043,
+			 0};
+static long room221[] = {
+			 219043,
+			 0};
+static long room222[] = {
+			 219046,
+			 223029,
+			 3092,
+			 0};
+static long room223[] = {
+			 222030,
+			 224029,
+			 0};
+static long room224[] = {
+			 223030, 223052,
+			 338195043,
+			 194043,
+			 0};
+static long room225[] = {
+			 220044,
+			 0};
+static long room226[] = {
+			 1,
+			 0};
+static long room227[] = {
+			 157044, 157011, 157029,
+			 398228043, 398228019, 398228030,
+			 181043, 181019, 181030,
+			 0};
+static long room228[] = {
+			 792045, 792046, 792004, 792005, 792033,
+			 227029, 227044, 227011,
+			 229039,
+			 786043, 786019, 786042, 786069, 786041,
+			 0};
+static long room229[] = {
+			 792045, 792046, 792004, 792005, 792033,
+			 228039,
+			 786044, 786011, 786042, 786069, 796041,
+			 158043, 158019, 158034,
+			 0};
+static long room230[] = {
+			 65218030, 65218039,
+			 231030, 231039,
+			 201046, 201017,
+			 0};
+static long room231[] = {
+			 1,
+			 0};
+static long room232[] = {
+			 168001,
+			 0};
+static long room233[] = {
+			 192001,
+			 0};
+static long room234[] = {
+			 214001,
+			 0};
+static long room235[] = {
+			 422306069, 422306046, 422306042, 422306089,
+			 661069,
+			 98044,
+			 0};
+static long room236[] = {
+			 208044,
+			 0};
+static long room237[] = {
+			 19001,
+			 0};
+static long room238[] = {
+			 3011, 3064,
+			 0};
+static long room239[] = {
+			 153045, 153047,
+			 240093,
+			 0};
+static long room240[] = {
+			 239047, 239042, 239069, 239093,
+			 241030,
+			 0};
+static long room241[] = {
+			 240029,
+			 242044,
+			 0};
+static long room242[] = {
+			 241043,
+			 243049,
+			 244044,
+			 246050,
+			 0};
+static long room243[] = {
+			 242047,
+			 244045,
+			 247050,
+			 0};
+static long room244[] = {
+			 242043,
+			 243046,
+			 245044,
+			 246045,
+			 0};
+static long room245[] = {
+			 243046,
+			 244043,
+			 246045,
+			 247044,
+			 0};
+static long room246[] = {
+			 242048,
+			 245046,
+			 247049,
+			 0};
+static long room247[] = {
+			 243048,
+			 245043,
+			 246047,
+			 307044,
+			 0};
+static long room248[] = {
+			 247043,
+			 0};
+
+static long *cave[MAXLOC] = {
+			     room1, room2, room3, room4,
+			     room5, room6, room7, room8, room9,
+			     room10, room11, room12, room13, room14,
+			     room15, room16, room17, room18, room19,
+			     room20, room21, room22, room23, room24,
+			     room25, room26, room27, room28, room29,
+			     room30, room31, room32, room33, room34,
+			     room35, room36, room37, room38, room39,
+			     room40, room41, room42, room43, room44,
+			     room45, room46, room47, room48, room49,
+			     room50, room51, room52, room53, room54,
+			     room55, room56, room57, room58, room59,
+			     room60, room61, room62, room63, room64,
+			     room65, room66, room67, room68, room69,
+			     room70, room71, room72, room73, room74,
+			     room75, room76, room77, room78, room79,
+			     room80, room81, room82, room83, room84,
+			     room85, room86, room87, room88, room89,
+			     room90, room91, room92, room93, room94,
+			     room95, room96, room97, room98, room99,
+			  room100, room101, room102, room103, room104,
+			  room105, room106, room107, room108, room109,
+			  room110, room111, room112, room113, room114,
+			  room115, room116, room117, room118, room119,
+			  room120, room121, room122, room123, room124,
+			  room125, room126, room127, room128, room129,
+			  room130, room131, room132, room133, room134,
+			  room135, room136, room137, room138, room139,
+			  room140, room141, room142, room143, room144,
+			  room145, room146, room147, room148, room149,
+			  room150, room151, room152, room153, room154,
+			  room155, room156, room157, room158, room159,
+			  room160, room161, room162, room163, room164,
+			  room165, room166, room167, room168, room169,
+			  room170, room171, room172, room173, room174,
+			  room175, room176, room177, room178, room179,
+			  room180, room181, room182, room183, room184,
+			  room185, room186, room187, room188, room189,
+			  room190, room191, room192, room193, room194,
+			  room195, room196, room197, room198, room199,
+			  room200, room201, room202, room203, room204,
+			  room205, room206, room207, room208, room209,
+			  room210, room211, room212, room213, room214,
+			  room215, room216, room217, room218, room219,
+			  room220, room221, room222, room223, room224,
+			  room225, room226, room227, room228, room229,
+			  room230, room231, room232, room233, room234,
+			  room235, room236, room237, room238, room239,
+			  room240, room241, room242, room243, room244,
+			     room245, room246, room247, room248};
Index: /trunk/minix/commands/advent/advdec.h
===================================================================
--- /trunk/minix/commands/advent/advdec.h	(revision 9)
+++ /trunk/minix/commands/advent/advdec.h	(revision 9)
@@ -0,0 +1,71 @@
+/*	header ADVDEC.H						*
+ *	WARNING: GLOBAL (EXTERNAL) declarations for adventure	*/
+
+#ifndef EXTERN			/* #define as '' to define the variables */
+#define EXTERN extern
+#endif
+
+EXTERN boolean gaveup;		/* TRUE if he quits early	*/
+EXTERN FILE *fd1, *fd2, *fd3, *fd4;
+
+/*
+  English variables
+*/
+EXTERN char *vtxt[MAXWORDS], *iotxt[MAXITEMS], *otxt[MAXITEMS];
+EXTERN int verbs[MAXWORDS], objs[MAXITEMS], iobjs[MAXITEMS];
+EXTERN int vrbx, objx, iobx;
+EXTERN int verb, object, motion, iobj, prep;
+EXTERN boolean newtravel, is_wiz;
+
+/*
+  Play variables
+*/
+extern int plac[MAXOBJ];	/* initial location	 */
+extern int fixd[MAXOBJ];
+struct playinfo {
+  int turns;
+  int loc, oldloc, oldloc2, newloc;	/* location variables */
+  long loc_attrib[MAXLOC+1];	/* location status	 */
+  int place[MAXOBJ];		/* object location	 */
+  int fixed[MAXOBJ];		/* second object loc	 */
+  int weight[MAXOBJ];
+  int atloc[MAXLOC+1];
+  int link[MAXOBJ * 2];
+  int holder[MAXOBJ];
+  int hlink[MAXOBJ];
+  int visited[MAXLOC+1];		/* >0 if has been here	 */
+  int prop[MAXOBJ];		/* status of object	 */
+  long obj_state[MAXOBJ];
+  long points[MAXOBJ];
+  int hinted[HNTMAX+1];
+  int hints[HNTMAX+1][5];
+  int hintlc[HNTMAX+1];
+  int tally, tally2;		/* item counts		 */
+  int limit;			/* time limit		 */
+  int lmwarn;			/* lamp warning flag	 */
+  int wzdark, closing, closed;	/* game state flags	 */
+  int holding;			/* count of held items	 */
+  int detail;			/* LOOK count		 */
+  int knfloc;			/* knife location	 */
+  int clock, clock2, panic;	/* timing variables	 */
+  int dloc[DWARFMAX+1];		/* dwarf locations	 */
+  int dflag;			/* dwarf flag		 */
+  int dseen[DWARFMAX+1];	/* dwarf seen flag	 */
+  int odloc[DWARFMAX+1];	/* dwarf old locations	 */
+  int daltloc;			/* alternate appearance	 */
+  int dkill;			/* dwarves killed	 */
+  int chloc, chloc2;		/* chest locations	 */
+  int bonus;			/* to pass to end	 */
+  int numdie;			/* number of deaths	 */
+  int foobar;			/* fee fie foe foo...	 */
+  int combo;			/* combination for safe  */
+  boolean terse;
+  int abbnum;
+  int health;
+  int chase;
+  boolean flg239;
+
+
+  int lastglob;			/* to get space req.	 */
+};
+extern struct playinfo g;
Index: /trunk/minix/commands/advent/advent.c
===================================================================
--- /trunk/minix/commands/advent/advent.c	(revision 9)
+++ /trunk/minix/commands/advent/advent.c	(revision 9)
@@ -0,0 +1,136 @@
+/**     Adventure translated from Fortran to "C"
+  and ported to Minix by:
+  Robert R. Hall
+  San Diego,  Calif  92115
+  hall@crash.cts.com
+ */
+
+/**	program ADVENT.C					*
+ *		"advent.c" allocates GLOBAL storage space by	*
+ *		#defining EXTERN before #including "advdec.h".	*/
+
+
+#include        <string.h>
+#include	<ctype.h>
+#include	<stdlib.h>
+#include	<time.h>
+#include        <stdio.h>
+#include	<errno.h>
+#include	"advent.h"		/* #define preprocessor equates	 */
+#include	"advdec.h"
+
+#ifndef TEXTDIR
+#define TEXTDIR ""
+#endif
+
+char textdir[] = TEXTDIR;		/* directory where text files
+					   live. */
+
+_PROTOTYPE(int main, (int, char **));
+_PROTOTYPE(static void opentxt, (void));
+_PROTOTYPE(static void file_error, (char *));
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+    opentxt();
+    initialize();
+    rspeak(325);
+    if (argc == 2)
+	restore(argv[1]);
+    else {
+	g.hinted[3] = yes(65, 1, 0);
+	g.limit = (g.hinted[3] ? 800 : 550);
+    }
+    gaveup = FALSE;
+    srand((unsigned) time(NULL));	/* seed random	 */
+    while (!gaveup)
+	turn();
+    fclose(fd1);
+    fclose(fd2);
+    fclose(fd3);
+    fclose(fd4);
+    return (EXIT_SUCCESS);		/* exit = ok	 */
+}					/* main		 */
+
+/*
+  Open advent?.txt files
+*/
+static void opentxt()
+{
+    static char filename[sizeof(textdir) + 16];
+    static FILE **fp[] = {0, &fd1, &fd2, &fd3, &fd4};
+    int i;
+    for (i = 1; i <= 4; i++) {
+	sprintf(filename, "%sadvent%d.dat", textdir, i);
+	*fp[i] = fopen(filename, "r");
+	if (!*fp[i])
+	    file_error(filename);
+    }
+}
+
+/*
+  save adventure game
+*/
+void saveadv(username)
+char *username;
+{
+    int cnt;
+    FILE *savefd;
+
+    savefd = fopen(username, "wb");
+    if (savefd == NULL) {
+	perror(username);
+	return;
+    }
+    cnt = fwrite((void *) &g, 1, sizeof(struct playinfo), savefd);
+    if (cnt != sizeof(struct playinfo)) {
+	fprintf(stderr, "wrote %d of %u bytes\n",
+		cnt, (unsigned) sizeof(struct playinfo));
+	if (ferror(savefd)) {
+	    fprintf(stderr, "errno is: 0x%.4x\n", errno);
+	    perror(username);
+	}
+    }
+    if (fclose(savefd) == -1) {
+	perror(username);
+    }
+    printf("Saved in %s.\n", username);
+    return;
+}
+
+/*
+  restore saved game handler
+*/
+void restore(username)
+char *username;
+{
+    int cnt;
+    FILE *restfd;
+
+    restfd = fopen(username, "rb");
+    if (restfd == NULL)
+	file_error(username);
+    cnt = fread((void *) &g, 1, sizeof(struct playinfo), restfd);
+    if (cnt != sizeof(struct playinfo)) {
+	fprintf(stderr, "read %d bytes, expected %u\n",
+		cnt, (unsigned) sizeof(struct playinfo));
+	if (ferror(restfd)) {
+	    fprintf(stderr, "errno is: 0x%.4x\n", errno);
+	    perror(username);
+	}
+    }
+    if (fclose(restfd) == -1) {
+	perror(username);
+    }
+    printf("Restored from %s.\n", username);
+    return;
+}
+
+static void file_error(filename)
+char *filename;
+{
+    perror(filename);
+    exit(EXIT_FAILURE);
+}
Index: /trunk/minix/commands/advent/advent.h
===================================================================
--- /trunk/minix/commands/advent/advent.h	(revision 9)
+++ /trunk/minix/commands/advent/advent.h	(revision 9)
@@ -0,0 +1,405 @@
+/*	header ADVENT.H						*
+ *	WARNING: HEADER file for all adventure modules		*/
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE	1
+#define EXIT_SUCCESS	(!(EXIT_FAILURE))
+#endif
+
+#define INPUTBUFLEN	80	/* Max input line length	 */
+
+typedef int boolean;
+#define FALSE	(0)
+#define TRUE	(!FALSE)
+
+#define	MAXOBJ	123		/* max # of objects in cave	 */
+#define	MAXLOC	248		/* max # of cave locations	 */
+#define	WORDSIZE	20	/* max # of chars in commands	 */
+#define	MAXMSG	408		/* max # of long location descr	 */
+#define HNTMAX	 18		/* max # of hints		 */
+#define HNTMIN	  7		/* hints starting count		 */
+
+#define MAXWORDS 25
+#define MAXITEMS 45
+
+#define CLASS(word) ((word)<0 ? -((-(word)) / 1000) : (word) / 1000)
+#define VAL(word) ((word)<0 ? -((-(word)) % 1000) : (word) % 1000)
+#define	MAXTRAV	(23+1)		/* max # of travel directions from loc	 */
+ /* +1 for terminator travel[x].tdest=-1	 */
+#define	DWARFMAX	6	/* max # of nasty dwarves	 */
+#define	MAXDIE	3		/* max # of deaths before close	 */
+#define	MAXTRS	79		/* max # of			 */
+
+#define Y2	33
+/*
+  Object definitions
+*/
+#define ANVIL	91
+#define AXE	28
+#define BATTERIES 39
+#define BEAR	35
+#define BEES	87
+#define BILLBD	116
+#define BIRD	101
+#define BOAT	48
+#define BOOK	110
+#define BOOK2	BOOK + 1
+#define BOOTH	93
+#define BOTTLE	20
+#define BRUSH	114
+#define	CAGE	4
+#define CAKES	107
+#define CARVNG	115
+#define CASK	71
+#define CHAIN	64
+#define CHASM	21
+#define CHASM2	CHASM + 1
+#define CHEST	55
+#define	CLAM	14
+#define CLOAK	47
+#define COINS	54
+#define CROWN	66
+#define DOG	98
+#define	DOOR	41		/* giant door */
+#define DRAGON	31
+#define DWARF	17
+#define EGGS	56
+#define EMERALD 59
+#define FISSURE 12
+#define FLOWER	46
+#define FLY	69
+#define FOOD	19
+#define GNOME	105
+#define GRAIL	70
+#define GRATE	3
+#define HIVE	97
+#define HONEY	96
+#define HORN	52
+#define JEWELS	53
+#define KEYS	102
+#define KNIFE	18
+#define LAMP	2
+#define LYRE	68
+#define MAGAZINE 16
+#define MESSAGE 36
+#define MIRROR	23
+#define MUSHRM	106
+#define NUGGET	50
+#define OIL	83
+#define OIL2	OIL + 1
+#define OYSTER	15
+#define PLAGUE	125
+#define PEARL	61
+#define PHONE	94
+#define PILLOW	10
+#define PLANT	24
+#define PLANT2	PLANT + 1
+#define POLE	9
+#define POSTER	113
+#define PYRAMID 60
+#define RADIUM	119
+#define RING	72
+#define ROCKS	92
+#define ROD	5
+#define ROD2	ROD + 1
+#define RUG	62
+#define	SAFE	112
+#define SAPPHIRE 69
+#define SHIELD	118
+#define SHOES	67
+#define SKEY	90
+#define SLUGS	95
+#define SNAKE	11
+#define SPHERE	120
+#define SPICES	63
+#define SPIDER	121
+#define STEPS	7
+#define STICKS	49
+#define SWORD	65
+#define TABLET	13
+#define TDOOR	42		/* tiny door */
+#define TDOOR2	TDOOR + 1	/* wrought-iron door */
+#define PDOOR	TDOOR2 + 1	/* door to phone booth */
+#define TRIDENT	57
+#define TROLL	33
+#define TROLL2	TROLL + 1
+#define VASE	58
+#define VEND	38
+#define WALL	88
+#define WALL2	WALL + 1
+#define WATER	81		/* in bottle */
+#define WATER2	WATER + 1	/* in cask */
+#define	WINE	85		/* in bottle */
+#define WINE2	WINE + 1	/* in cask */
+#define WUMPUS	99
+
+/*
+  Verb definitions
+*/
+#define	BACK	8
+#define	CAVE	67
+#define	DEPRESSION	63
+#define	ENTRANCE	64
+#define EXIT	11
+#define	NULLX	21
+
+/*
+  Action verb definitions
+*/
+#define TAKE	1
+#define DROP	2
+#define SAY	3
+#define OPEN	4
+#define NOTHING 5
+#define CLOSE   6
+#define ON	7
+#define OFF	8
+#define WAVE	9
+#define CALM	10
+#define WALK	11
+#define KILL	12
+#define POUR	13
+#define EAT	14
+#define DRINK	15
+#define RUB	16
+#define	THROW	17
+#define QUIT	18
+#define FIND	19
+#define INVENTORY 20
+#define FEED	21
+#define FILL	22
+#define BLAST	23
+#define SCORE	24
+#define FOO	25
+#define BRIEF	26
+#define READ	27
+#define BREAK	28
+#define WAKE	29
+#define SUSPEND 30
+#define RESTORE	31
+#define YANK	32
+#define WEAR	33
+#define HIT	34
+#define ANSWER 35
+#define BLOW	36
+#define LEAVE	37
+#define YELL	38
+#define DIAL	39
+#define PLAY	40
+#define PICK	41
+#define PUT	42
+#define TURN	43
+#define GET	44
+#define INSRT	45
+#define REMOVE  46
+#define BURN	47
+#define GRIPE	48
+#define LOCK	49
+#define UNLOCK	50
+#define HEALTH	51
+#define LOOK	52
+#define COMBO	53
+#define SWEEP	54
+#define TERSE	55
+#define	WIZ	56
+#define MAP	57
+#define GATE	58
+#define PIRLOC	59
+
+#define GO	11
+#define SHUT    6
+#define LOG     33
+
+#define MOTION	0			/* CLASSD */
+#define NOUN	1			/* CLASSN */
+#define ACTION	2			/* CLASSA */
+#define MISC	3			/* CLASSM */
+#define PREPOSITION 4			/* CLASSP */
+#define ADJACTIVE   5			/* CLASSJ */
+#define CONJUNCTION 6			/* CLASSC */
+
+/*
+   and a few preposition.  prefix PREP to distinguish them from
+   verbs or nouns
+ */
+#define PREPAT	9
+#define PREPDN	8
+#define PREPIN	1
+#define PREPFR  5
+#define PREPOF  6
+#define PREPOFF 6
+#define PREPON	2
+
+/*
+  BIT mapping of "cond" array which indicates location status
+*/
+#define	LIGHT	1
+#define	WATOIL	2
+#define	LIQUID	4
+#define	NOPIRAT	16
+
+/* Object condition bit functions */
+#define OPENBT 2
+#define LOCKBT 4
+#define BURNBT 6
+#define DEADBT 10
+#define WEARBT 12
+/*
+  Structure definitions
+*/
+struct wac {
+  char *aword;
+  int acode;
+};
+
+struct trav {
+  int tdest;
+  int tverb;
+  int tcond;
+};
+
+/* Function prototypes.
+   "#if (__STDC__)" should have been be enough,
+   but some compilers are stupid, so allow Makefile to say -DHAS_STDC=whatever.
+*/
+#if defined(HAS_STDC) ? (HAS_STDC) : (__STDC__)
+#undef	HAS_STDC
+#define HAS_STDC 1
+#define	_PROTOTYPE(function, params)	function params
+#define _CONST				const
+#else
+#define	_PROTOTYPE(function, params)	function ()
+#define _CONST
+#endif
+
+/* Advent.c */
+
+_PROTOTYPE(void saveadv, (char *username));
+_PROTOTYPE(void restore, (char *username));
+
+/* Initialize.c */
+
+_PROTOTYPE(void initialize, (void));
+
+/* Database.c */
+
+_PROTOTYPE(int yes, (int msg1, int msg2, int msg3));
+_PROTOTYPE(void rspeak, (int msg));
+_PROTOTYPE(void pspeak, (int item, int state));
+_PROTOTYPE(void desclg, (int loc));
+_PROTOTYPE(void descsh, (int loc));
+
+/* English.c */
+
+_PROTOTYPE(int english, (void));
+_PROTOTYPE(int analyze, (char *word, int *type, int *value));
+
+/* Itverb.c */
+
+_PROTOTYPE(void itverb, (void));
+_PROTOTYPE(void ivblast, (void));
+_PROTOTYPE(void ivlook, (void));
+
+/* Turn.c */
+
+_PROTOTYPE(void turn, (void));
+_PROTOTYPE(void describe, (void));
+_PROTOTYPE(void descitem, (void));
+_PROTOTYPE(void dwarfend, (void));
+_PROTOTYPE(void normend, (void));
+_PROTOTYPE(void score, (int));
+_PROTOTYPE(void death, (void));
+_PROTOTYPE(char *probj, (void));
+_PROTOTYPE(void trobj, (void));
+_PROTOTYPE(void dwarves, (void));
+_PROTOTYPE(void dopirate, (void));
+_PROTOTYPE(int stimer, (void));
+
+/* Verb.c */
+
+_PROTOTYPE(void trverb, (void));
+_PROTOTYPE(void vtake, (void));
+_PROTOTYPE(void vdrop, (void));
+_PROTOTYPE(void vopen, (void));
+_PROTOTYPE(void vsay, (void));
+_PROTOTYPE(void von, (void));
+_PROTOTYPE(void voff, (void));
+_PROTOTYPE(void vwave, (void));
+_PROTOTYPE(void vkill, (void));
+_PROTOTYPE(void vpour, (void));
+_PROTOTYPE(void veat, (void));
+_PROTOTYPE(void vdrink, (void));
+_PROTOTYPE(void vthrow, (void));
+_PROTOTYPE(void vfind, (void));
+_PROTOTYPE(void vfill, (void));
+_PROTOTYPE(void vfeed, (void));
+_PROTOTYPE(void vread, (void));
+_PROTOTYPE(void vbreak, (void));
+_PROTOTYPE(void vwake, (void));
+_PROTOTYPE(void actspk, (int verb));
+_PROTOTYPE(void vyank, (void));
+_PROTOTYPE(void vwear, (void));
+_PROTOTYPE(void vlock, (void));
+_PROTOTYPE(void vunlock, (void));
+_PROTOTYPE(void vclose, (void));
+
+/* Utility.c */
+
+_PROTOTYPE(boolean ajar, (int));
+_PROTOTYPE(boolean at, (int item));
+_PROTOTYPE(boolean athand, (int));
+_PROTOTYPE(void bitoff, (int, int));
+_PROTOTYPE(void biton, (int, int));
+_PROTOTYPE(boolean bitset, (long, int));
+_PROTOTYPE(boolean blind, (void));
+_PROTOTYPE(int burden, (int));
+_PROTOTYPE(void carry, (int obj, int where));
+_PROTOTYPE(int confuz, (void));
+_PROTOTYPE(boolean dark, (void));
+_PROTOTYPE(boolean dcheck, (void));
+_PROTOTYPE(boolean dead, (int));
+_PROTOTYPE(void drop, (int obj, int where));
+_PROTOTYPE(void destroy, (int obj));
+_PROTOTYPE(boolean edible, (int));
+_PROTOTYPE(boolean enclosed, (int));
+_PROTOTYPE(void extract, (int));
+_PROTOTYPE(boolean forced, (int atloc));
+_PROTOTYPE(boolean here, (int item));
+_PROTOTYPE(boolean hinged, (int));
+_PROTOTYPE(boolean holding, (int));
+_PROTOTYPE(void insert, (int, int));
+_PROTOTYPE(boolean inside, (int));
+_PROTOTYPE(void juggle, (int loc));
+_PROTOTYPE(int liq, (int));
+_PROTOTYPE(int liqloc, (int loc));
+_PROTOTYPE(int liq2, (int pbottle));
+_PROTOTYPE(boolean living, (int));
+_PROTOTYPE(boolean locked, (int));
+_PROTOTYPE(boolean locks, (int));
+_PROTOTYPE(void lookin, (int));
+_PROTOTYPE(void move, (int obj, int where));
+_PROTOTYPE(int noway, (void));
+_PROTOTYPE(boolean opaque, (int));
+_PROTOTYPE(boolean outside, (int));
+_PROTOTYPE(boolean pct, (int x));
+_PROTOTYPE(boolean plural, (int));
+_PROTOTYPE(boolean portal, (int));
+_PROTOTYPE(boolean printed, (int));
+_PROTOTYPE(int put, (int obj, int where, int pval));
+_PROTOTYPE(int ranz, (int));
+_PROTOTYPE(boolean small, (int));
+_PROTOTYPE(boolean toting, (int item));
+_PROTOTYPE(boolean treasr, (int));
+_PROTOTYPE(boolean vessel, (int));
+_PROTOTYPE(boolean wearng, (int));
+_PROTOTYPE(boolean worn, (int));
+_PROTOTYPE(void bug, (unsigned int n));
+_PROTOTYPE(char *ask, (char *prompt, char *buf, int buflen));
+_PROTOTYPE(void panic, (char *msg, boolean save));
+
+/* travel.c */
+_PROTOTYPE(void domove, (void));
+_PROTOTYPE(void gettrav, (int loc, struct trav *travel));
+
+/* vocab.c */
+_PROTOTYPE(int vocab, (char *word, int val));
Index: /trunk/minix/commands/advent/advent1.txt
===================================================================
--- /trunk/minix/commands/advent/advent1.txt	(revision 9)
+++ /trunk/minix/commands/advent/advent1.txt	(revision 9)
@@ -0,0 +1,827 @@
+#1
+You are standing at the end of a road before a small brick building.
+Around you is a forest.  A small stream flows out of the building and
+down a gully.
+#2
+You have walked up a hill, still in the forest.  The road slopes back
+down the other side of the hill.  There is a building in the distance.
+#3
+You are inside a building, a well house for a large spring.  Off
+to one side is a small pantry.
+#4
+You are in a valley in the forest beside a stream tumbling along a
+rocky bed.
+#5
+You are in open forest, with a deep valley to one side.  Not far
+is a large billboard.
+#6
+You are in open forest near both a valley and a road.
+#7
+At your feet all the water of the stream splashes into a 2-inch slit
+in the rock.  Downstream the stream bed is bare rock.
+#8
+You are in a 20-foot depression floored with bare dirt.  Set into the
+dirt is a strong steel grate mounted in concrete.  A dry stream bed
+leads into the depression.
+#9
+You are in a small chamber beneath a 3x3 steel grate to the surface.
+A low crawl over cobbles leads inward to the west.
+#10
+You are crawling over cobbles in a low passage.  There is a dim light
+at the east end of the passage.
+#11
+You are in a debris room filled with stuff washed in from the surface.
+A low wide passage with cobbles becomes plugged with mud and debris
+here, but an awkward canyon leads upward and west.  A note on the wall
+says "Magic Word XYZZY".
+#12
+You are in an awkward sloping east/west canyon.
+#13
+You are in a splendid chamber thirty feet high.  The walls are frozen
+rivers of orange stone.  An awkward canyon and a good passage exit
+from east and west sides of the chamber.
+#14
+At your feet is a small pit breathing traces of white mist.  An east
+passage ends here except for a small crack leading on.
+#15
+You are at one end of a vast hall stretching forward out of sight to
+the west.  There are openings to either side.  Nearby, a wide stone
+staircase leads downward.  The hall is filled with wisps of white mist
+swaying to and fro almost as if alive.  A cold wind blows up the
+staircase.  There is a passage at the top of a dome behind you.
+#16
+The crack is far too small for you to follow.
+#17
+You are on the east bank of a fissure slicing clear across the hall.
+The mist is quite thick here, and the fissure is too wide to jump.
+#18
+This is a low room with a crude note on the wall.  The note says,
+"You won't get it up the steps".
+#19
+You are in the Hall of the Mountain King, with passages off in all
+directions.
+#20
+You are at the bottom of the pit with a broken neck.
+#21
+You didn't make it.
+#22
+The dome is unclimbable.
+#23
+You are at the west end of the Twopit Room.  There is a large hole in
+the wall above the pit at this end of the room.
+#24
+You are at the bottom of the eastern pit in the Twopit Room.  There is
+a small pool of oil in one corner of the pit.
+#25
+You are at the bottom of the western pit in the Twopit Room.  There is
+a large hole in the wall about 25 feet above you.
+#26
+You clamber up the plant and scurry through the hole at the top.
+#27
+You are on the west side of the fissure in the Hall of Mists.
+#28
+You are in a low N/S passage at a hole in the floor.  The hole goes
+down to an E/W passage.
+#29
+You are in the South Side Chamber.
+#30
+You are in the West Side Chamber of the Hall of the Mountain King.
+A passage continues west and up here.
+#31
+<$$<
+#32
+You can't get by the snake.
+#33
+You are in a large room, with a passage to the south, a passage to the
+west, and a wall of broken rock to the east.  There is a large "Y2" on
+a rock in the room's center.
+#34
+You are in a jumble of rock, with cracks everywhere.
+#35
+You're at a low window overlooking a huge pit, which extends up out of
+sight.  A floor is indistinctly visible over 50 feet below.  Traces of
+white mist cover the floor of the pit, becoming thicker to the right.
+Marks in the dust around the window would seem to indicate that
+someone has been here recently.  Directly across the pit from you and
+25 feet away there is a similar window looking into a lighted room.  A
+shadowy figure can be seen there peering back at you.
+#36
+You are in a dirty broken passage.  To the east is a crawl.  To the
+west is a large passage.  Above you is a hole to another passage.
+#37
+You are on the brink of a small clean climbable pit.  A crawl leads
+west.
+#38
+You are in the bottom of a small pit with a little stream, which
+enters and exits through tiny slits.
+#39
+You are in a large room full of dusty rocks.  There is a big hole in
+the floor.  There are cracks everywhere, and a passage leading east.
+#40
+You have crawled through a very low wide passage parallel to and north
+of the Hall of Mists.
+#41
+You are at the west end of Hall of Mists.  A low wide crawl continues
+west and another goes north.  To the south is a little passage 6 feet
+off the floor.
+#42
+You are in a maze of twisty little passages, all alike.
+#43
+You are in a maze of twisty little passages, all alike.
+#44
+You are in a maze of twisty little passages, all alike.
+#45
+You are in a maze of twisty little passages, all alike.
+#46
+Dead end.
+#47
+Dead end.
+#48
+Dead end.
+#49
+You are in a maze of twisty little passages, all alike.
+#50
+You are in a maze of twisty little passages, all alike.
+#51
+You are in a maze of twisty little passages, all alike.
+#52
+You are in a maze of twisty little passages, all alike.
+#53
+You are in a maze of twisty little passages, all alike.
+#54
+Dead end.
+#55
+You are in a maze of twisty little passages, all alike.
+#56
+Dead end.
+#57
+You are on the brink of a thirty foot pit with a massive orange column
+down one wall.  You could climb down here but you could not get back
+up.  The maze continues at this level.
+#58
+Dead end.
+#59
+You have crawled through a very low wide passage parallel to and north
+of the Hall of Mists.
+#60
+You are at the east end of a very long hall apparently without side
+chambers.  In the south wall are several wide cracks and a high
+hole, but the hole is far above your head.  To the east a wide
+crawl slants up.  To the north a round two foot hole slants down.
+#61
+You are at the west end of a very long featureless hall.  The hall
+joins up with a narrow north/south passage.
+#62
+You are at a crossover of a high N/S passage and a low E/W one.
+#63
+Dead end.
+#64
+You are at a complex junction.  A low hands and knees passage from the
+north joins a higher crawl from the east to make a walking passage
+going west.  There is also a large room above.  The air is damp here.
+#65
+You are in Bedquilt, a long east/west passage with holes everywhere.
+To explore at random select north, south, up, or down.
+#66
+You are in a room whose walls resemble swiss cheese.  Obvious passages
+go west, east, NE, and NW.  Part of the room is occupied by a large
+bedrock block.
+#67
+You are at the east end of the Twopit Room.  The floor here is
+littered with thin rock slabs, which make it easy to descend the pits.
+There is a path here bypassing the pits to connect passages from east
+and west.  There are holes all over, but the only big one is on the
+wall directly over the west pit where you can't get to it.
+#68
+You are in a large low circular chamber whose floor is an immense slab
+fallen from the ceiling (Slab Room).  East and west there once were
+large passages, but they are now filled with boulders.  Low small
+passages go north and south, and the south one quickly bends west
+around the boulders.
+#69
+You are in a secret N/S canyon above a large room.
+#70
+You are in a secret N/S canyon above a sizable passage.
+#71
+You are in a secret canyon at a junction of three canyons, bearing
+north, south, and SE.  The north one is as tall as the other two
+combined.
+#72
+You are in a large low room.  Crawls lead north, NE, and SW.
+#73
+Dead end crawl.
+#74
+You are in a secret canyon which here runs E/W.  It crosses over a
+very tight canyon 15 feet below.  If you go down you may not be able
+to get back up.
+#75
+You are at a wide place in a very tight N/S canyon.
+#76
+The canyon here becomes too tight to go further south.
+#77
+You are in a tall E/W canyon.  A low tight crawl goes 3 feet north and
+seems to open up.
+#78
+The canyon runs into a mass of boulders -- dead end.
+#79
+The stream flows out through a pair of 1 foot diameter sewer pipes.
+It would be advisable to use the exit.
+#80
+You are in a maze of twisty little passages, all alike.
+#81
+Dead end.
+#82
+Dead end.
+#83
+You are in a maze of twisty little passages, all alike.
+#84
+You are in a maze of twisty little passages, all alike.
+#85
+Dead end.
+#86
+Dead end.
+#87
+You are in a maze of twisty little passages, all alike.
+#88
+You are in a long, narrow corridor stretching out of sight to the
+west.  At the eastern end is a hole through which you can see a
+profusion of leaves.
+#89
+There is nothing here to climb.  Use "up" or "out" to leave the pit.
+#90
+You have climbed up the plant and out of the pit.
+#91
+You are at the top of a steep incline above a large room.  You could
+climb down here, but you would not be able to climb up.  There is a
+passage leading back to the north.
+#92
+You are in the Giant Room.  The ceiling here is too high up for your
+lamp to show it.  Cavernous passages lead east, north, and south.  On
+the west wall is scrawled the inscription, "FEE FIE FOE FOO" [sic].
+#93
+The passage here is blocked by a recent cave-in.
+#94
+You are at one end of an immense north/south passage.
+#95
+You are in a magnificent cavern with a rushing stream, which cascades
+over a sparkling waterfall into a roaring whirlpool which disappears
+through a hole in the floor.  Passages exit to the south and west.
+#96
+You are in the Soft Room.  The walls are covered with heavy curtains,
+the floor with a thick pile carpet.  Moss covers the ceiling.
+#97
+This is the Oriental Room.  Ancient oriental cave drawings cover the
+walls.  A gently sloping passage leads upward to the north, another
+passage leads SE, and a hands and knees crawl leads east.
+#98
+You are following a wide path around the outer edge of a large cavern.
+Far below, through a heavy white mist, strange splashing noises can be
+heard.  The mist rises up through a fissure in the ceiling.  The path
+hugs the cavern's rim to the NE and south, while another branch forks
+west.  A round chute with extremely smooth walls angles sharply up
+to the southwest.
+#99
+You are in an alcove.  A small NW path seems to widen after a short
+distance.  An extremely tight tunnel leads east.  It looks like a very
+tight squeeze.  An eerie light can be seen at the other end.
+#100
+You're in a small chamber lit by an eerie green light.  An extremely
+narrow tunnel exits to the west, and a dark corridor leads NE.
+#101
+You're in the Dark-Room.  A corridor leading south is the only exit.
+#102
+You are in an arched hall.  A coral passage once continued up and east
+from here, but is now blocked by debris.  The air smells of sea water.
+#103
+You're in a large room carved out of sedimentary rock.  The floor and
+walls are littered with bits of shells imbedded in the stone.  A
+shallow passage proceeds downward, and a somewhat steeper one leads
+up.  A low hands and knees passage enters from the south.
+#104
+You are in a long sloping corridor with ragged sharp walls.
+#105
+You are in a cul-de-sac about eight feet across.
+#106
+You are in an anteroom leading to a large passage to the east.  Small
+passages go west and up.  The remnants of recent digging are evident.
+A sign in midair here says "Cave under construction beyond this point.
+Proceed at own risk.  [Witt Construction Company]".
+#107
+You are in a maze of twisty little passages, all different.
+#108
+You are at Witt's End.  Passages lead off in *ALL* directions.
+#109
+You are in a north/south canyon about 25 feet across.  The floor is
+covered by white mist seeping in from the north.  The walls extend
+upward for well over 100 feet.  Suspended from some unseen point far
+above you, an enormous two-sided mirror is hanging parallel to and
+midway between the canyon walls.  (The mirror is obviously provided
+for the use of the dwarves, who as you know, are extremely vain.)  A
+small window can be seen in either wall, some fifty feet up.
+#110
+You're at a low window overlooking a huge pit, which extends up out of
+sight.  A floor is indistinctly visible over 50 feet below.  Traces of
+white mist cover the floor of the pit, becoming thicker to the left.
+Marks in the dust around the window would seem to indicate that
+someone has been here recently.  Directly across the pit from you and
+25 feet away there is a similar window looking into a lighted room.  A
+shadowy figure can be seen there peering back at you.
+#111
+A large stalactite extends from the roof and almost reaches the floor
+below.  You could climb down it, and jump from it to the floor, but
+having done so you would be unable to reach it to climb back up.
+#112
+You are in a little maze of twisting passages, all different.
+#113
+You are at the edge of a large underground reservoir.  An opaque cloud
+of white mist fills the room and rises rapidly upward.  The lake is
+fed by a stream, which tumbles out of a hole in the wall about 10 feet
+overhead and splashes noisily into the water somewhere within the
+mist.  The indistinct shape of the opposite shore can be dimly seen
+through the mist.  The only passage goes back toward the south.
+#114
+Dead end.
+#115
+You are at the northeast end of an immense room, even larger than the
+Giant Room.  It appears to be a repository for the "ADVENTURE"
+program.  Massive torches far overhead bathe the room with smoky
+yellow light.  Scattered about you can be seen a pile of bottles (all
+of them empty), a nursery of young beanstalks murmuring quietly, a bed
+of oysters, a bundle of black rods with rusty stars on their ends, and
+a collection of brass lanterns.  Off to one side a great many dwarves
+are sleeping on the floor, snoring loudly.  A sign nearby reads: "Do
+not disturb the dwarves!"  An immense mirror is hanging against one
+wall, and stretches to the other end of the room, where various other
+sundry objects can be glimpsed dimly in the distance.  An unoccupied
+telephone booth stands against the north wall.
+#116
+You are at the southwest end of the repository.  To one side is a pit
+full of fierce green snakes.  On the other side is a row of small
+wicker cages, each of which contains a little sulking bird.  In one
+corner is a bundle of black rods with rusty marks on their ends.  A
+large number of velvet pillows are scattered about on the floor. 
+Beside one of the pillows is a large, dusty, leather-bound volume
+with the title "History of Adventure" embossed in pure gold.
+A vast mirror stretches off to the northeast, almost reaching the
+phone booth.  At your feet is a large steel grate, next to which is
+a sign which reads, "Treasure Vault. Keys in Main Office."
+#117
+You are on one side of a large, deep chasm.  A heavy white mist rising
+up from below obscures all view of the far side.  A SW path leads away
+from the chasm into a winding corridor.
+#118
+You are in a long winding corridor sloping out of sight in both
+directions.
+#119
+You are in a secret canyon which exits to the north and east.
+#120
+You are in a secret canyon which exits to the north and east.
+#121
+You are in a secret canyon which exits to the north and east.
+#122
+You are on the northeast side of a deep chasm.  A NE path leads away
+from the chasm on this side.
+#123
+You're in a long east/west corridor.  A faint rumbling noise can be
+heard in the distance.
+#124
+The path forks here.  The left fork leads northeast.  A dull rumbling
+seems to get louder in that direction.  The right fork leads southeast
+down a gentle slope.  The main corridor enters from the west.
+#125
+The walls are quite warm here.  From the north can be heard a steady
+roar, so loud that the entire cave seems to be trembling.  Another
+passage leads south, and a low crawl goes east.
+#126
+You are on the edge of a breathtaking view.  Far below you is an
+active volcano, from which great gouts of molten lava come surging
+out, cascading back down into the depths.  The glowing rock fills the
+farthest reaches of the cavern with a blood-red glare, giving every-
+thing an eerie, macabre appearance.  The air is filled with flickering
+sparks of ash and a heavy smell of brimstone.  The walls are hot to
+the touch, and the thundering of the volcano drowns out all other
+sounds.  Embedded in the jagged roof far overhead are myriad twisted
+formations composed of pure white alabaster, which scatter the murky
+light into sinister apparitions upon the walls.  To one side is a deep
+gorge, filled with a bizarre chaos of tortured rock which seems to
+have been crafted by the devil himself.  An immense river of fire
+crashes out from the depths of the volcano, burns its way through the
+gorge, and plummets into a bottomless pit far off to your left.  To
+the right, an immense geyser of blistering steam erupts continuously
+from a barren island in the center of a sulfurous lake, which bubbles
+ominously.  The far right wall is aflame with an incandescence of its
+own, which lends an additional infernal splendor to the already
+hellish scene.  A dark, foreboding passage exits to the south.
+#127
+You are in a small chamber filled with large boulders.  The walls are
+very warm, causing the air in the room to be almost stifling from the
+heat.  The only exit is a crawl heading west, through which is coming
+a low rumbling.
+#128
+You are walking along a gently sloping north/south passage lined with
+oddly shaped limestone formations.
+#129
+You are standing at the entrance to a large, barren room.  A sign
+posted above the entrance reads:  "Caution!  Bear in room!"
+#130
+You are inside a barren room.  The center of the room is completely
+empty except for some dust.  Marks in the dust lead away toward the
+far end of the room.  The only exit is the way you came in.
+#131
+You are in a maze of twisting little passages, all different.
+#132
+You are in a little maze of twisty passages, all different.
+#133
+You are in a twisting maze of little passages, all different.
+#134
+You are in a twisting little maze of passages, all different.
+#135
+You are in a twisty little maze of passages, all different.
+#136
+You are in a twisty maze of little passages, all different.
+#137
+You are in a little twisty maze of passages, all different.
+#138
+You are in a maze of little twisting passages, all different.
+#139
+You are in a maze of little twisty passages, all different.
+#140
+Dead end.
+#141
+You are on a narrow promontory at the foot of a waterfall, which
+spurts from an overhead hole in the rock wall and splashes into a
+large reservoir, sending up clouds of mist and spray.
+Through the thick white mist looms a polished marble slab, to
+which is affixed an enormous rusty iron anvil.  In golden letters
+are written the words: "Whoso Pulleth Out This Sword of This
+Stone and Anvil, is Right wise King-Born of All This Mountain."
+There is a narrow chimney on the east side of the promontory.
+#142
+You are on a narrow shelf above and east of the top of a very steep
+chimney.  A long smooth granite slide curves down out of sight
+to the east.  If you go down the slide, you may not be able to
+climb back up.
+#143
+You are in the private chamber of the Mountain King.  Hewn into the
+solid rock of the east wall of the chamber is an intricately-wrought
+throne of elvish design.  There is an exit to the west.
+#144
+You are on the east side of the throne room.  On the arm of the throne
+has been hung a sign which reads "Gone for the day: visiting
+sick snake. --M.K."
+#145
+You are dragged down, down, into the depths of the whirlpool.
+Just as you can no longer hold your breath, you are shot out over
+a waterfall into the shallow end of a large reservoir.  Gasping
+and sputtering, you crawl weakly towards the shore....
+#146
+You are in dense forest, with a hill to one side.  The trees appear
+to thin out towards the north and east.
+#147
+You are at the high point of a wide grassy knoll, partially surrounded
+by dense forest.  The land rises to the south and east, and drops off
+sharply to the north and west.  The air smells of sea water.
+#148
+You are at the edge of a trackless salt marsh.  Tall reeds obscure
+the view.
+#149
+You're in salt marsh.
+#150
+You're in salty marsh.
+#151
+You are in salt marsh.
+#152
+Dead end.
+#153
+You're on a sandy beach at the edge of the open sea.  The beach
+ends a short distance south and the land rises to a point. To
+the north, the beach ends cliffs and broken rocks.
+#154
+You are at a jumble of large broken rocks.  A gentle path leads up
+to the top of the nearby cliffs.  A narrow treacherous path
+disappears among the rocks at the foot of the cliff.
+#155
+You are on a high cliff overlooking the sea.  Far below the
+rolling breakers smash into a jumble of large broken rocks.
+The thunder of the surf is deafening.
+#156
+You're at the bottom of the cliff, smashed to smithereens by the
+pounding surf.
+#157
+You are at Thunder Hole, a funnel shaped cavern opening onto the sea.
+The noise of the surf pounding against the outer rocks of the cave is
+amplified by the peculiar shape of the cave, causing a thunder-like
+booming sound to reverberate throughout the cave.  Outside, a narrow
+path leads south towards some large rocks.
+#158
+You are at the top of some arched steps.  On one side is a blank wall
+with a tiny door at the base and a shelf overhead.  On the other side
+a westward passage leads to the sea.
+#159
+You are in a low cramped chamber at the back of a small cave.
+There is a shelf in the rock wall at about the height of your
+shoulder.
+#160
+You are on a wide ledge, bounded on one side by a rock wall,
+and on the other by a sheer cliff.  The only way past is through
+a large wrought-iron door.
+#161
+You feel dizzy...Everything around you is spinning, expanding,
+growing larger....  Dear me!  Is the cave bigger or are you smaller?
+#162
+You are again overcome by a sickening vertigo, but this time
+everything around you is shrinking...Shrinking...
+#163
+You are again overcome by a sickening vertigo, but this time
+everything is shrinking... I mean, you are growing.  This is
+terribly confusing!
+#164
+You feel dizzy...Everything around you is spinning, expanding,
+growing larger....
+#165
+You're at the bottom of the cliff with a broken neck.
+#166
+You are at the western tip of the Blue Grotto.  A large lake almost
+covers the cavern floor, except for where you are standing.  Small
+holes high in the rock wall to the east admit a dim light.  The
+reflection of the light from the water suffuses the cavern with
+a hazy bluish glow.
+#167
+You are on the shore of an underground sea.  A high wooden
+structure of vast proportions extends out into the water to the
+east.  The way west is through a wrought-iron door.
+#168
+You are on the eastern shore of the Blue Grotto.  An ascending
+tunnel disappears into the darkness to the SE.
+#169
+You are at a high rock on the NE side of a watery chamber at the mouth
+of a small brook.  An unknown gas bubbles up through the water from
+the chamber floor.  A bluish light can be seen to the southwest.
+#170
+You are in a windy tunnel between two large rooms.
+#171
+You are in the Bat Cave.  The walls and ceiling are covered with
+sleeping bats.  The floor is buried by a mass of dry, foul-smelling
+guano.  The stench is overpowering.  Exits to the NW and east.
+#172
+You are in a very tight N/S crack.  The passage seems to widen to
+the south.
+#173
+You are in a very tight N/S crack.  The passage south is blocked
+by a recent cave-in.
+#174
+You're in the Cloakroom.  This is where the dreaded Wumpus repairs
+to sleep off heavy meals.  (Adventurers are his favorite dinner!)
+Two very narrow passages exit NW and NE.
+#175
+You're in a room containing several small climbable pits.  Passages
+exit to the east and north.
+#176
+You are at the bottom of a small featureless pit.
+#177
+You are at a high hole in a rock wall.
+#178
+The NE passage is blocked by a recent cave-in.
+#179
+You are in a sloping muddy defile, next to a tumbling brook.
+#180
+You are in a level E/W passage partially blocked by an overhanging
+tongue of rock.  A steep scramble would take you up over the tongue,
+whence continues an upward crawl.
+#181
+The dog won't let you pass.
+#182
+You're in the Upper Passage, a long level E/W tunnel.
+#183
+You are in a star-shaped chamber.  Passages exit north, east, south,
+and west.
+#184
+You are at an elbow in a winding E/W passage.
+#185
+Dead end.
+#186
+You're at the intersection of two long tunnels.  One goes NW,
+the other NE.
+#187
+You're in a long narrow east-west passage which curves out of sight
+at both ends.
+#188
+You're in the Rotunda.  Corridors radiate in all directions.
+There is a telephone booth standing against the north wall.
+#189
+You are standing in a telephone booth at the side of a large chamber.
+Hung on the wall is a banged-up pay telephone of ancient design.
+#190
+You're at the Devil's Chair, a large crystallization shaped like a
+seat, at the edge of a black abyss.  You can't see the bottom.
+An upward path leads away from the abyss.
+#191
+You're in a dead-end crack.
+#192
+You're on a small gravel beach at the south wall of the Blue Grotto.
+A gravelly path leads east.
+#193
+You are in the Flower Room.  The walls are covered with colorful,
+intricate, flowerlike patterns of crystallized gypsum. A hole leads
+to the west.
+#194
+You are at the end of a short E/W corridor.
+#195
+You are looking west from the end of a short E/W corridor.  At your
+feet is a pile of loose rubble.  On your left is a hole into another
+chamber.
+#196
+You are in an arched hall.  The remnants of a now-plugged coral
+passage lie to the east.  The north wall has partially crumbled,
+exposing a large connecting hole to another room.
+#197
+You're in the Vestibule, a short east-west passage between two rooms.
+#198
+You are in the Fairy Grotto.  All around you innumerable stalactites,
+arranged in immense colonnades, form elegant arches.  On every side
+you hear the dripping of water, like the footsteps of a thousand
+fairies.  A small stream runs from the SW corner.  A bright glow
+emanates from the south side of the grotto, and a steep passage
+descends to the east.
+#199
+You have approached the lower end of a steep passage, but it is
+just too cold here to hang around, and you aren't properly equipped
+to continue.  With teeth chattering, you climb back up....
+#200
+You are in the Crystal Palace.  An overhead vein of phosphorescent
+quartz casts a luminous glow which is reflected by countless chips of
+mica embedded in both walls, which consist of some sort of highly
+reflective glass, apparently of volcanic origin.  A winding path
+of yellow sandstone leads west and rises steeply to the east.
+#201
+You are following a yellow sandstone path.  There is a glow
+to the west.
+#202
+You are in a very tall chamber whose walls are comprised of many
+different rock strata.  Layers of red and yellow sandstone
+intertwine with bright bands of calcareous limestone in a rainbow-
+like profusion of color.  The rainbow effect is so real, you
+are almost tempted to look for a pot of gold!  Poised far over
+your head, a gigantic slab, wedged tightly between the north and
+south walls, forms a natural bridge across the roof of the chamber.
+A trail leads east and west.
+#203
+You're in a steeply sloping passage.  It is very cold here.
+#204
+You are in the Hall of Ice, in the deepest part of the caverns.
+During winter, frigid outside air settles here, making this room
+extremely cold all year round.  The walls and ceilings are covered
+with a thick coating of ice.  An upward passage exits to the west.
+#205
+You are standing on a natural bridge far above the floor of a circular
+chamber whose walls are a rainbow of multicolored rock.  The bridge
+was formed eons ago by a huge slab which fell from the ceiling and
+is now jammed between the north and south walls of the chamber.
+#206
+You are in a low, wide room below another chamber.  A small green
+pond fills the center of the room.  The lake is apparently spring
+fed.  A small stream exits through a narrow passage to the north.
+A larger passage continues west.
+#207
+You are in a tight north/south crawl through a stratum of red
+colored rock.  The air is damp with mist.
+#208
+You are in a tall canyon on the south side of a swift, wide river.
+Written in the mud in crude letters are the words: "You Have Found
+Lost River."  A wide path leads east and west along the bank.  A tight
+crawl way would take you south out of the canyon.
+#209
+You are standing on a large flat rock table at the western end of
+Lost River Canyon.  Beneath your feet, the river disappears amidst
+foam and spray into a large sinkhole.  A gentle path leads east
+along the river's south shore.  Another leads sharply upward along
+the river's north side.
+#210
+You are at a niche in the canyon wall, far above a raging river.
+The air is filled with mist and spray, making it difficult to see
+ahead.  A downward sloping ledge narrows to the east. The path
+to the west is easier.
+#211
+The ledge is growing very narrow and treacherous, and falls off almost
+vertically.  You could go down, but you won't be able to climb back.
+#212
+You are standing in a telephone booth at the side of the Repository.
+#213
+You're at the east end of a level passage at a hole in the floor.
+#214
+You're at the north edge of a dark cove.
+#215
+You are in a dry granite basin, worn smooth eons ago by water
+swirling down from a now-dry spillway.
+#216
+You're in a dry spillway east of and above a smooth rock basin.
+#217
+You are in the Winery, a cool dark room which extends some
+distance off to the east.
+#218
+You are to the east of the Winery, where the room ends in a thicket
+of high, sharp, pointed, climbable limestone pinnacles.  There is a
+narrow ledge just above the top of the spires.  If you go up, it
+might be difficult to get back down.
+#219
+You are in a high-vaulted cavern whose roof rises over fifty
+meters to culminate in a series of pointed arches directly over
+your head.  There are also two low arches to either side, forming
+side portals.  The whole effect is that of a gothic cathedral.
+You can proceed north, south, east, or west.
+#220
+You're at the east portal of the Gothic Cathedral. The path leads
+east and west.
+#221
+You're at the west portal of the Gothic Cathedral.
+#222
+You are at the foot of the Altar, an immense, broad stalagmite.
+An opening leads south.
+#223
+You're on top of an enormous, broad stalagmite.  There is a hole
+in the ceiling overhead.
+#224
+You are in a room the size and shape of a small crypt.  A narrow
+cut exits east.  There is a hole in the floor.
+#225
+You are in the Gothic Chapel, a small chamber adjoining the Gothic
+Cathedral. A path leads west.
+#226
+You are on the floor of the Rainbow Room.  In fact, you are spread
+*ALL OVER* the floor of the Rainbow Room.
+#227
+You are in a dimly lit passage behind Thunder Hole.  Etched into
+the rock wall are the ominous words:
+*       "You are approaching the River Styx.      *
+*        Laciate Ogni Speranza Voi Ch'Entrate."   *
+#228
+You are at the River Styx, a narrow little stream cutting directly
+across the passageway.  The edge of the stream is littered with sticks
+and other debris washed in by a recent rainfall.  On the far side
+of the river, the passage continues east.
+#229
+You're on the east side of the river's sticks.
+#230
+You are on a ledge at the northern end of a long N/S crawl.  The
+ledge is above a large number of sharp vertical limestone spires.
+An attempt to climb down could be dangerous, if you get my *point*!
+#231
+You are very neatly skewered on the point of a sharp rock.
+#232
+You have poled your boat across the calm water.
+#233
+You have poled your boat across the dark water.
+#234
+You have poled your boat across the Blue Grotto.
+#235
+You're at Dante's Rest, on the north side of a yawning dark chasm.
+A passage continues west along the chasm's edge.
+#236
+You are at the east end of a river bank path in Lost River Canyon.
+#237
+The staircase is now unclimbable.
+#238
+You're in the caretaker's pantry.
+#239
+You are on a small rise overlooking a beautiful bay. In the center
+of the bay is the castle of the elves.
+#240
+You are on the highest pinnacle of the castle in the bay.
+Steps lead down into the garden.
+#241
+You are in the outer courtyard of the garden of the elves.
+Steps lead up to the tower, and to the west, separating you
+from the inner courtyard, is a maze of hedges, living things,
+but almost crystalline in their multicolored splendor.
+#242
+From the inside the maze looks like a kaleidoscope, with
+swatches of color dancing as you move. In this part the colors
+are produced by shining red berries on the branches.
+#243
+You are surrounded by a tall hedge with sharp iridescent leaves
+and metallic orange flowers.
+#244
+You are in the center of the living maze. The plants here are
+dormant this season, but still carry brilliant yellow leaves.
+#245
+Unlike the other areas of the hedge system, this area seems to 
+have no metallic gleam; nevertheless it is still breathtaking.
+The trees and bushes are all variegated shades of green, the
+evergreens being a rich dark shade while the seasonal bushes
+are a lighter yellowish green, making a startling contrast.
+#246
+You are near the edge of the maze. You sample the blueberries
+on the bushes. They are delicious.
+#247
+You are at the western end of the living maze. Beside the
+shrubs forming the walls are tastefully planted beds of
+violets and brilliant purple pansies.
+To the west is the inner garden.
+#248
+You are in the inner garden of the elves. In the center is
+a living tree, with shimmering silvery bark, glistening metallic
+green leaves, and flowers ripe with nectar. As the nectar falls
+to the ground it forms droplets of silver. Around the tree is
+a hedge of briars which cannot be crossed. Unfortunately for
+adventurers such as you, most of the nectar falls inside the hedge.
+The exit is to the east.
Index: /trunk/minix/commands/advent/advent2.txt
===================================================================
--- /trunk/minix/commands/advent/advent2.txt	(revision 9)
+++ /trunk/minix/commands/advent/advent2.txt	(revision 9)
@@ -0,0 +1,514 @@
+#1
+You're at end of road again.
+#2
+You're at hill in road.
+#3
+You're inside building.
+#4
+You're in valley.
+#5
+You're in forest.
+#6
+You're in forest.
+#7
+You're at slit in streambed.
+#8
+You're outside grate.
+#9
+You're below the grate.
+#10
+You're in cobble crawl.
+#11
+You're in Debris Room.
+#12
+You are in an awkward sloping east/west canyon.
+#13
+You're in Bird Chamber.
+#14
+You're at top of small pit.
+#15
+You're in Hall of Mists.
+#16
+The crack is far too small for you to follow.
+#17
+You're on east bank of fissure.
+#18
+You're in Nugget of Gold Room.
+#19
+You're in Hall of Mt King.
+#20
+You are at the bottom of the pit with a broken neck.
+#21
+You didn't make it.
+#22
+The dome is unclimbable.
+#23
+You're at west end of Twopit Room.
+#24
+You're in east pit.
+#25
+You're in west pit.
+#26
+You clamber up the plant and scurry through the hole at the top.
+#27
+You are on the west side of the fissure in the Hall of Mists.
+#28
+You are in a low N/S passage at a hole in the floor.  The hole goes
+down to an E/W passage.
+#29
+You are in the South Side Chamber.
+#30
+You are in the West Side Chamber of the Hall of the Mountain King.
+#31
+<$$<
+#32
+You can't get by the snake.
+#33
+You're at "Y2".
+#34
+You are in a jumble of rock, with cracks everywhere.
+#35
+You're at window on pit.
+#36
+You're in dirty passage.
+#37
+You are on the brink of a small clean climbable pit.
+#38
+You are in the bottom of a small pit with a little stream.
+#39
+You're in dusty rock room.
+#40
+You have crawled through a very low wide passage parallel.
+#41
+You're at west end of Hall of Mists.
+#42
+You are in a maze of twisty little passages, all alike.
+#43
+You are in a maze of twisty little passages, all alike.
+#44
+You are in a maze of twisty little passages, all alike.
+#45
+You are in a maze of twisty little passages, all alike.
+#46
+Dead end.
+#47
+Dead end.
+#48
+Dead end.
+#49
+You are in a maze of twisty little passages, all alike.
+#50
+You are in a maze of twisty little passages, all alike.
+#51
+You are in a maze of twisty little passages, all alike.
+#52
+You are in a maze of twisty little passages, all alike.
+#53
+You are in a maze of twisty little passages, all alike.
+#54
+Dead end.
+#55
+You are in a maze of twisty little passages, all alike.
+#56
+Dead end.
+#57
+You're at brink of pit.
+#58
+Dead end.
+#59
+You have crawled through a very low wide passage.
+#60
+You're at east end of Long Hall.
+#61
+You're at west end of Long Hall.
+#62
+You are at a crossover of a high N/S passage and a low E/W one.
+#63
+Dead end.
+#64
+You're at Complex Junction.
+#65
+You are in Bedquilt.
+#66
+You're in Swiss Cheese Room.
+#67
+You're at east end of Twopit Room.
+#68
+You're in Slab Room.
+#69
+You are in a secret N/S canyon above a large room.
+#70
+You are in a secret N/S canyon above a sizable passage.
+#71
+You're at junction of three secret canyons.
+#72
+You are in a large low room.  Crawls lead north, NE, and SW.
+#73
+Dead end crawl.
+#74
+You're in secret E/W canyon above tight canyon.
+#75
+You are at a wide place in a very tight N/S canyon.
+#76
+The canyon here becomes too tight to go further south.
+#77
+You are in a tall E/W canyon.
+#78
+The canyon runs into a mass of boulders -- dead end.
+#79
+The stream flows out through a pair of 1 foot diameter sewer pipes.
+#80
+You are in a maze of twisty little passages, all alike.
+#81
+Dead end.
+#82
+Dead end.
+#83
+You are in a maze of twisty little passages, all alike.
+#84
+You are in a maze of twisty little passages, all alike.
+#85
+Dead end.
+#86
+Dead end.
+#87
+You are in a maze of twisty little passages, all alike.
+#88
+You're in narrow corridor.
+#89
+There is nothing here to climb.  Use "up" or "out" to leave the pit.
+#90
+You have climbed up the plant and out of the pit.
+#91
+You're at steep incline above large room.
+#92
+You're in Giant Room.
+#93
+The passage here is blocked by a recent cave-in.
+#94
+You are at one end of an immense north/south passage.
+#95
+You're in cavern with waterfall.
+#96
+You're in Soft Room.
+#97
+You're in Oriental Room.
+#98
+You're in Misty Cavern.
+#99
+You're in Alcove.
+#100
+You're in Plover Room.
+#101
+You're in Dark-Room.
+#102
+You're in Arched Hall.
+#103
+You're in Shell Room.
+#104
+You are in a long sloping corridor with ragged sharp walls.
+#105
+You are in a cul-de-sac about eight feet across.
+#106
+You're in Anteroom.
+#107
+You are in a maze of twisty little passages, all different.
+#108
+You're at Witt's End.
+#109
+You're in Mirror Canyon.
+#110
+You're at window on pit.
+#111
+You're at top of stalactite.
+#112
+You are in a little maze of twisting passages, all different.
+#113
+You're at Reservoir.
+#114
+Dead end.
+#115
+You're at NE end.
+#116
+You're at SW end.
+#117
+You're on SW side of chasm.
+#118
+You're in sloping corridor.
+#119
+You are in a secret canyon which exits to the north and east.
+#120
+You are in a secret canyon which exits to the north and east.
+#121
+You are in a secret canyon which exits to the north and east.
+#122
+You're on NE side of chasm.
+#123
+You're in corridor.
+#124
+You're at fork in path.
+#125
+You're at junction with warm walls.
+#126
+You're at breath-taking view.
+#127
+You're in Chamber of Boulders.
+#128
+You're in Limestone Passage.
+#129
+You're in front of Barren Room.
+#130
+You're in Barren Room.
+#131
+You are in a maze of twisting little passages, all different.
+#132
+You are in a little maze of twisty passages, all different.
+#133
+You are in a twisting maze of little passages, all different.
+#134
+You are in a twisting little maze of passages, all different.
+#135
+You are in a twisty little maze of passages, all different.
+#136
+You are in a twisty maze of little passages, all different.
+#137
+You are in a little twisty maze of passages, all different.
+#138
+You are in a maze of little twisting passages, all different.
+#139
+You are in a maze of little twisty passages, all different.
+#140
+Dead end.
+#141
+You're at Sword Point.
+#142
+You're at top of slide.
+#143
+You're at entrance to Throne Room.
+#144
+You're on east side of Throne Room.
+#145
+<$$<
+#146
+You're in forest.
+#147
+You're on grassy knoll.
+#148
+You are at the edge of a trackless salt marsh.  Tall reeds obscure
+the view.
+#149
+You're in salt marsh.
+#150
+You're in salty marsh.
+#151
+You are in salt marsh.
+#152
+Dead end.
+#153
+You're on sandy beach.
+#154
+You're at broken rocks.
+#155
+You're at Ocean Vista.
+#156
+You're at the bottom of the cliff.
+#157
+You're at Thunder Hole.
+#158
+You're at top of steps in back of Thunder Hole.
+#159
+You're in cramped chamber.
+#160
+You're at ledge by wrought-iron door.
+#161
+You feel dizzy...Everything around you is spinning, expanding,
+growing larger....  Dear me!  Is the cave bigger or are you smaller?
+#162
+You are again overcome by a sickening vertigo, but this time
+everything around you is shrinking...Shrinking...
+#163
+You are again overcome by a sickening vertigo, but this time
+everything is shrinking... I mean, you are growing.  This is
+terribly confusing!
+#164
+You feel dizzy...Everything around you is spinning, expanding,
+growing larger....
+#165
+You're at the bottom of the cliff with a broken neck.
+#166
+You're at west wall of Blue Grotto.
+#167
+You're at underground sea.
+#168
+You're on east side of the Blue Grotto.
+#169
+You're in Bubble Chamber.
+#170
+You are in a windy tunnel between two large rooms.
+#171
+You're in Bat Cave.
+#172
+You are in a very tight N/S crack.
+#173
+You are in a very tight N/S crack.
+#174
+You're in the Cloakroom.
+#175
+You're in a room containing several small climbable pits.
+#176
+You are at the bottom of a small featureless pit.
+#177
+You are at a high hole in a rock wall.
+#178
+The NE passage is blocked by a recent cave-in.
+#179
+You are in a sloping muddy defile, next to a tumbling brook.
+#180
+You're at Tongue of Rock.
+#181
+The dog won't let you pass.
+#182
+You're in the Upper Passage, a long level E/W tunnel.
+#183
+You're in Star Chamber.
+#184
+You are at an elbow in a winding E/W passage.
+#185
+Dead end.
+#186
+You're at the intersection of two long tunnels.
+#187
+You're in a long narrow east-west passage.
+#188
+You're in Rotunda.
+#189
+You're in phone booth.
+#190
+You're at Devil's Chair.
+#191
+You're in a dead-end crack.
+#192
+You're on gravel beach.
+#193
+You're in Flower Room.
+#194
+You are at east end of short E/W corridor.
+#195
+You are at east end of short E/W corridor.
+#196
+You're in Arched Hall.
+#197
+You're in the Vestibule, a short east-west passage between two rooms.
+#198
+You're in the Fairy Grotto.
+#199
+You have approached the lower end of a steep passage.
+#200
+You're in the Crystal Palace.
+#201
+You are following a yellow sandstone path.
+#202
+You're in the Rainbow Room.
+#203
+You're in a steeply sloping passage.  It is very cold here.
+#204
+You're in the Hall of Ice.
+#205
+You are over the Rainbow (Room).
+#206
+You're in Green Lake Room.
+#207
+You're in red rock crawl.
+#208
+You're on south side of Lost River Canyon.
+#209
+You're at end of Lost River Canyon.
+#210
+You're at niche in ledge above Lost River.
+#211
+A very narrow and treacherous ledge.
+#212
+You're in phone booth.
+#213
+You're at the east end of a level passage at a hole in the floor.
+#214
+You're in dark cove.
+#215
+You're in dry basin.
+#216
+You're in old spillway.
+#217
+You're in the Winery.
+#218
+You're at limestone pinnacles.
+#219
+You're in Gothic Cathedral.
+#220
+You're at the east portal of the Gothic Cathedral.
+#221
+You're at the west portal of the Gothic Cathedral.
+#222
+You are at the foot of the Altar, an immense, broad stalagmite.
+#223
+You're on top of stalagmite.
+#224
+You're in the Crypt.
+#225
+You're in Gothic Chapel.
+#226
+You are on the floor of the Rainbow Room.
+#227
+You are at approach to River Styx.
+#228
+You're at the River Styx.
+#229
+You're on the east side of the river's sticks.
+#230
+You're on ledge above limestone pinnacles.
+#231
+You are very neatly skewered on the point of a sharp rock.
+#232
+You have poled your boat across the calm water.
+#233
+You have poled your boat across the dark water.
+#234
+You have poled your boat across the Blue Grotto.
+#235
+You're at Dante's Rest.
+#236
+You're at east end of Lost River Canyon.
+#237
+The staircase is now unclimbable.
+#238
+You're in the caretaker's pantry.
+#239
+You're on a small rise over the bay.
+#240
+You are on the highest pinnacle of the castle in the bay.
+Steps lead down into the garden.
+#241
+You are in the outer courtyard of the elves.
+#242
+You are in the living maze. There are red berries here.
+#243
+You are surrounded by a tall hedge with sharp iridescent leaves
+and metallic orange flowers.
+#244
+You are in the center of the living maze. The plants here are
+dormant this season, but still carry brilliant yellow leaves.
+#245
+Unlike the other areas of the hedge system, this area seems to 
+have no metallic gleam; nevertheless it is still breathtaking.
+The trees and bushes are all variegated shades of green, the
+evergreens being a rich dark shade while the seasonal bushes
+are a lighter yellowish green, making a startling contrast.
+#246
+You are near the edge of the maze. You sample the blueberries
+on the bushes. They are delicious.
+#247
+You are at the western end of the living maze. Beside the
+shrubs forming the walls are tastefully planted beds of
+violets and brilliant purple pansies.
+To the west is the inner garden.
+#248
+You're in the inner courtyard of the elves.
Index: /trunk/minix/commands/advent/advent3.txt
===================================================================
--- /trunk/minix/commands/advent/advent3.txt	(revision 9)
+++ /trunk/minix/commands/advent/advent3.txt	(revision 9)
@@ -0,0 +1,539 @@
+#1
+#2
+/Brass lantern
+/There is a shiny brass lamp nearby.
+/There is a lamp shining nearby.
+/
+#3
+/*Grate
+/The grate is locked.
+/The grate is open.
+/
+#4
+/Wicker cage
+/There is a small wicker cage discarded nearby.
+/
+#5
+/Black rod
+/A three foot black rod with a rusty star on an end lies nearby.
+/
+#6
+/Black rod
+/A three foot black rod with a rusty mark on an end lies nearby.
+/
+#7
+/*Steps
+/Rough stone steps lead down the pit.
+/Rough stone steps lead up the dome.
+/
+#8
+#9
+/Wooden pole
+/A wooden pole is lying nearby.
+/A wooden pole has been stuck in the mud here.
+/
+#10
+/Velvet pillow
+/A small velvet pillow lies on the floor.
+/
+#11
+/*Snake
+/A huge green fierce snake bars the way!
+/<$$<  (Chased away)
+/
+#12
+/*Fissure
+/<$$<
+/A crystal bridge now spans the fissure.
+/The crystal bridge has vanished!
+/
+#13
+/*Stone tablet
+/A massive stone tablet imbedded in the wall reads:
+"Congratulations on bringing light into the Dark-Room!"
+/
+#14
+/Giant clam  >grunt!<
+/There is an enormous clam here with its shell tightly closed.
+/
+#15
+/Giant oyster  >groan!<
+/There is an enormous oyster here with its shell tightly closed.
+/Interesting.  There seems to be something written on the underside of
+the oyster.
+/
+#16
+/"Spelunker Today"
+/There are a few recent issues of "Spelunker Today" magazine here.
+/
+#17
+#18
+#19
+/Tasty food
+/There is food here.
+/
+#20
+/Small bottle
+/There is a small bottle here.
+/There is an empty bottle here.
+/There is a small bottle here.
+/There is a broken bottle here.
+/There is a small bottle here.
+/
+#21
+/*Chasm - troll bridge
+/A rickety wooden bridge extends across the chasm, vanishing into the
+mist.  A sign posted on the bridge reads, "Stop! Pay troll!"
+/The wreckage of a bridge (and a dead bear) can be seen at the bottom
+of the chasm.
+/
+#22
+/*Chasm2 & decrepit natural bridge
+/A decrepit natural bridge spans the chasm.  A message scrawled into
+the rock wall reads: "Bridge out of repair.  Maximum load: 35 Foonts."
+/The remnants of a natural bridge partially overhang the chasm.
+/
+#23
+/*Mirror
+/<$$<
+/
+#24
+/*plant
+/There is a tiny little plant in the pit, murmuring "Water, water, ..."
+/The plant spurts into furious growth for a few seconds.
+/There is a 12-foot-tall beanstalk stretching up out of the pit,
+bellowing "Water!! Water!!"
+/The plant grows explosively, almost filling the bottom of the pit.
+/There is a gigantic beanstalk stretching all the way up to the hole.
+/You've over-watered the plant!  It's shriveling up!  It's, it's...
+/
+#25
+/*Phony plant (seen in twopit room only when tall enough)
+/<$$<
+/The top of a 12-foot-tall beanstalk is poking out of the west pit.
+/There is a huge beanstalk growing out of the west pit up to the hole.
+/
+#26
+/*Stalactite
+/<$$<
+/
+#27
+/*shadowy figure
+/The shadowy figure seems to be trying to attract your attention.
+/
+#28
+/Dwarf's axe
+/There is a little axe here.
+/There is a little axe lying beside the bear.
+/There is a little axe lying beside the Wumpus.
+/There is a little axe lying beside the dog.
+/
+#29
+/*Cave drawings
+/<$$<
+/
+#30
+/*pirate
+/<$$<
+/
+#31
+/*dragon
+/A huge green fierce dragon bars the way!
+/Congratulations!  You have just vanquished a dragon with your bare
+hands!  (Unbelievable, isn't it?)
+/The body of a huge green dead dragon is lying off to one side.
+/
+#32
+#33
+/*Troll
+/A burly troll stands by the bridge and insists you throw him a
+treasure before you may cross.
+/The troll steps out from beneath the bridge and blocks your way.
+/<$$<  (Chased away)
+/
+#34
+/*phony troll
+/The troll is nowhere to be seen.
+/
+#35
+/<$$<  (Bear uses rtext 141)
+/There is a ferocious cave bear eying you from the far end of the room!
+/There is a gentle cave bear sitting placidly in one corner.
+/There is a contented-looking bear wandering about nearby.
+/<$$<  (Dead)
+/
+#36
+/*Message in second maze
+/There is a message scrawled in the dust in a flowery script, reading:
+"This is not the maze where the pirate leaves his treasure chest."
+/
+#37
+/*Volcano and/or geyser
+/<$$<
+/
+#38
+/*Vending machine
+/There is a massive vending machine here.  The instructions on it
+read:  "Insert coins to receive fresh batteries."
+/There is a massive vending machine here.
+/
+#39
+/Batteries
+/There are fresh batteries here.
+/Some worn-out batteries have been discarded nearby.
+/Some worn-out batteries have been discarded nearby.
+/
+#40
+/*Carpet and/or moss
+/<$$<
+/
+#41
+/*Rusty door
+/The way north is barred by a massive, rusty, iron door.
+/The way north leads through a massive, rusty, iron door.
+/
+#42
+/*Tiny door
+/The only way past the wall is through a tiny locked door.
+/The only way past the wall is through a tiny open door.
+/
+#43
+/*Tiny door-2
+/The door is locked.
+/The door is open.
+/
+#44
+/*Phone booth door
+/<$$<
+/
+#45
+#46
+/Beautiful flowers
+/There are some beautiful flowers here!
+/On the other side of the room a swarm of bees eagerly buzzes over
+a bunch of fresh flowers.
+/
+#47
+/Silken cloak
+/There is a silken cloak here!
+/<$$<  (wearing cloak)
+/A lovely silken cloak lies partially buried under a pile of
+loose rocks.
+/
+#48
+/Wooden boat
+/There is a small wooden boat here.
+/You are in a wooden boat.
+/
+#49
+/*Sticks at Styx
+/<$$<
+/
+#50
+/Large gold nugget
+/There is a large sparkling nugget of gold here!
+/
+#51
+/Several diamonds
+/There are diamonds here!
+/
+#52
+/Silver horn
+/There is a silver horn here!
+/
+#53
+/Precious jewelry
+/There is precious jewelry here!
+/<$$<  (wearing jewelry)
+/
+#54
+/Rare coins
+/There are many coins here!
+/
+#55
+/Treasure chest
+/The pirate's treasure chest is here!
+/
+#56
+/Golden eggs
+/There is a large nest here, full of golden eggs!
+/The nest of golden eggs has vanished!
+/Done!
+/
+#57
+/Jeweled trident
+/There is a jewel-encrusted trident here!
+/
+#58
+/Ming vase
+/There is a delicate, precious, ming vase here!
+/The vase is now resting, delicately, on a velvet pillow.
+/The floor is littered with worthless shards of pottery.
+/The ming vase drops with a delicate crash.
+/
+#59
+/Egg-sized emerald
+/There is an emerald here the size of a plover's egg!
+/
+#60
+/Platinum pyramid
+/There is a platinum pyramid here, 8 inches on a side!
+/
+#61
+/Glistening pearl
+/Off to one side lies a glistening pearl!
+/
+#62
+/Persian rug
+/There is a persian rug spread out on the floor!
+/The dragon is sprawled out on a persian rug!!
+/
+#63
+/Rare spices
+/There are rare spices here!
+/
+#64
+/Golden chain
+/There is a golden chain lying in a heap on the floor!
+/The bear is locked to the wall with a golden chain!
+/There is a golden chain locked to the wall!
+/
+#65
+/Gleaming sword
+/There is a gleaming sword here!
+/A gleaming sword is stuck into the anvil!
+/You grasp the sword's handle and give a mighty heave, but with a
+loud clang the sword blade shatters into several fragments.
+/Rusty shards of a elven sword lie scattered about.
+/A very clean sword is stuck into the anvil!
+/An oily sword is stuck into the anvil.
+/
+#66
+/Elfin crown
+/An ancient crown of elfin kings lies here!
+/<$$<  (wearing crown)
+/
+#67
+/Ruby slippers
+/There is a pair of ruby slippers here.
+/<$$<  (wearing slippers)
+/There is a pair of ruby slippers here.
+/
+#68
+/Delicate lyre
+/There is a delicate lyre here!
+/
+#69
+/Star sapphire
+/There is a star sapphire here!
+/
+#70
+/Holy Grail
+/There is an ornate silver chalice here!
+/
+#71
+/Oaken cask
+/There is an oaken cask here.
+/There is an empty oaken cask here.
+/There is an oaken cask here.
+/<$$<  (Unused)
+/There is an oaken cask here.
+/
+#72
+/Golden ring
+/There is a small gold ring here.
+/<$$<  (wearing ring)
+/On the Wumpus' finger is a small gold ring.
+/
+#73
+/Four-leafed clover
+/There is a four-leafed clover here!
+/<$$<  (wearing clover)
+/
+#74
+/Gold tree
+/There is a gold statue of a tree here.
+/
+#75
+/Silver droplet
+/There is a single droplet of silver on the ground here.
+/
+#76
+#77
+#78
+#79
+#80
+#81
+/Clear water
+/
+#82
+/Cool water
+/
+#83
+/Thick, black oil
+/
+#84
+/Thick, black oil
+/
+#85
+/Vintage wine
+/
+#86
+/Vintage wine
+/
+#87
+/*Bumblebees
+/<$$<
+/Some bumblebees are swarming around a bunch of fresh flowers.
+/
+#88
+/*Hollow wall
+/Your footsteps echo hollowly throughout the chamber.
+/<$$<
+/
+#89
+/*Wall with safe
+/A steel safe is embedded in the wall.
+/
+#90
+/Tiny brass key
+/There is a tiny brass key here.
+/There is a tiny brass key on the shelf.
+/
+#91
+/*Anvil
+/<$$<
+/
+#92
+/*rocks on cloak
+/<$$<  (ON CLOAK)
+/<$$<  (AFTER ROCK SLIDE)
+/
+#93
+/*telephone booth
+/The telephone booth is empty.
+
+The phone is ringing.
+/The phone booth is occupied by a gnome.  He is talking excitedly
+to someone at the other end.
+/The telephone booth is empty.
+/<$$<
+/
+#94
+/*Telephone
+/The phone is ringing.
+/The telephone is out of order.
+/The telephone is out of order.  It is badly dented.
+/<$$<
+/
+#95
+/Lead slugs
+/There are some lead slugs here!
+/
+#96
+/Sweet honeycomb
+/There is a sweet honeycomb here!
+/
+#97
+/*Beehive
+/There is an active beehive nearby.  The bees hum protectively
+around the hive.
+/There is an empty beehive nearby.
+/
+#98
+/*Black dog
+/A hideous black dog bares his teeth and growls at your approach.
+/Nearby, a large black dog is in a deep slumber.
+/
+#99
+/*Dreaded Wumpus
+/In the corner, a Wumpus is sleeping peacefully.
+/A sleepy Wumpus is ambling towards you.  He wants to invite you to
+dinner.  He wants you to *be* the dinner!
+/The Wumpus is still on your trail!  And he's getting closer!!
+/The Wumpus is only a few steps behind you!  All this exercise is
+making him veerrrrry hungry!
+/The Wumpus almost has you in his grasp!  You can feel his hot breath
+on your neck!
+/"Chomp, chomp."  Crunch!  Chew!  Slurp!  Smack!  Yum!!!
+/Nearby is the smashed body of a defunct Wumpus.
+/
+#100
+#101
+/Little bird in cage
+/A cheerful little bird is sitting here singing.
+/There is a little bird in the cage.
+/
+#102
+/Set of keys
+/There are some keys on the ground here.
+/
+#103
+/*Fountain
+/There is a fountain of sparkling vintage wine here!
+/
+#104
+/*Bats & guano in bat-cave
+/<$$<
+/
+#105
+/*gnome in phone booth
+/<$$<
+/
+#106
+/Colored mushrooms
+/There are some oddly-colored mushrooms here.
+/
+#107
+/Tiny cakes
+/There are some tiny cakes on the shelf.
+/
+#108
+/Leather Sack
+/There is a leather sack here.
+/
+#109
+#110
+/Rare book
+/There is a dusty, leather-bound volume here.
+/
+#111
+/Rare book
+/There is a dusty, leather-bound volume here.
+/
+#112
+/Steel wall-safe
+/The safe door is locked.
+/The safe door is open.
+/
+#113
+/Faded poster
+/Taped to the wall is a faded poster.
+/There is a faded poster here.
+/
+#114
+/Whiskbroom
+/There is a small whiskbroom here.
+/
+#115
+/*Carving on dusty rocks
+/<$$<
+/<$$<
+/
+#116
+/*Billboard
+/
+/
+#117
+#118
+/Small metal canister
+/There is a heavy, grey, metal canister here.
+/
+#119
+/Glowing stone
+/Nearby, a strange, greenish stone is glowing brightly.
+/
+#120
+/Quartz sphere
+/There is a polished sphere of pure quartz here!
+/
Index: /trunk/minix/commands/advent/advent4.txt
===================================================================
--- /trunk/minix/commands/advent/advent4.txt	(revision 9)
+++ /trunk/minix/commands/advent/advent4.txt	(revision 9)
@@ -0,0 +1,1068 @@
+#1
+Somewhere nearby is Colossal Cave, where others have found fortunes in
+treasure and gold, though it is rumored that some who enter are never
+seen again.  Magic is said to work in the cave.  I will be your eyes
+and hands.  Direct me with natural English commands.  I should warn
+you that I look at all the letters of each word. Also you
+should enter "Northeast" as "NE" to distinguish it from "North".
+(Should you get stuck, type "HELP" or "?" for some general hints.)
+Good Luck!
+- - - -
+#2
+A little dwarf with a big knife blocks your way.
+#3
+A little dwarf just walked around a corner, saw you, threw a little
+axe at you which missed, cursed, and ran away.
+#4
+There is a threatening little dwarf in the room with you!
+#5
+One sharp nasty knife is thrown at you!
+#6
+None of them hit you!
+#7
+One of them gets you!
+#8
+A hollow voice says "Plugh".
+#9
+There is no way to go that direction.
+#10
+I am unsure how you are facing.  Use compass points or nearby objects.
+#11
+I don't know in from out here.  Use compass points or name something
+in the general direction you want to go.
+#12
+I don't know how to apply that word here.
+#13
+I don't understand that!
+#14
+I'm game.  Would you care to explain how?
+#15
+Sorry, but I am not allowed to give more detail.  I will repeat the
+long description of your location.
+#16
+It is now pitch dark.  If you proceed you will likely fall into a pit.
+#17
+If you prefer, simply type "W" rather than "West".
+#18
+Are you trying to catch the bird?
+#19
+The bird is frightened right now and you cannot catch it no matter
+what you try.  Perhaps you might try later.
+#20
+Are you trying to somehow deal with the snake?
+#21
+You can't kill the snake, or drive it away, or avoid it, or anything
+like that.  There is a way to get by, but you don't have the necessary
+resources right now.
+#22
+Do you really want to quit now?
+#23
+You fell into a pit and broke every bone in your body!
+#24
+You are already carrying it!
+#25
+You can't be serious!
+#26
+The bird was unafraid when you entered, but as you approach it becomes
+disturbed and you cannot catch it.
+#27
+You can catch the bird, but you cannot carry it.
+#28
+There is nothing here with a lock!
+#29
+You aren't carrying it!
+#30
+The little bird attacks the green snake, and in an astounding flurry
+drives the snake away.
+#31
+You have no keys!
+#32
+It has no lock.
+#33
+I don't know how to lock or unlock such a thing.
+#34
+It was already locked.
+#35
+The grate is now locked.
+#36
+The grate is now unlocked.
+#37
+It was already unlocked.
+#38
+You have no source of light.
+#39
+Your lamp is now on.
+#40
+Your lamp is now off.
+#41
+There is no way to get past the bear to unlock the chain, which is
+probably just as well.
+#42
+Nothing happens.
+#43
+Where?
+#44
+There is nothing here to attack.
+#45
+The little bird is now dead.  Its body disappears.
+#46
+Attacking the snake both doesn't work and is very dangerous.
+#47
+You killed a little dwarf.
+#48
+You attack a little dwarf, but he dodges out of the way.
+#49
+With what?  Your bare hands?
+#50
+Good try, but that is an old worn-out magic word.
+#51
+To move, try words like FOREST, BUILDING, DOWNSTREAM, IN, EAST, NORTH,
+UP, OR DOWN. Saying a place name may take you there, as may some
+magic words. You can say TAKE LAMP or DROP LAMP or PUT LAMP IN SACK.
+Some objects have side effects; for instance, the rod scares the bird.
+You can take or drop multiple objects by saying TAKE BOOK AND LAMP,
+etc. To list what you are currently holding, say INVENTORY, or just I.
+To reprint the detailed description of where you are, say LOOK
+or L. You can also LOOK IN or LOOK AT appropriate objects. Other
+useful commands are HEALTH, QUIT, SCORE, BRIEF, TERSE, UNBRIEF,
+UNTERSE, SAVE, and RESTORE. The latter two save or restore your
+current position. To get full credit for a treasure, you must have
+left it **safely** in the building. Some non-treasure items are best
+left near where you find them. There are clues for various problems
+lying about the cave: look and listen. If you seem to have found
+all the treasures, keep looking around a while, something else
+may happen to you (for a bonus!)
+(The word "give" doesn't exist, but you can say FEED BONE TO DOG or
+THROW BONE AT DOG. Also, you can use conveyances or animals(!)
+by TAKEing and DROPing them.)
+#52
+It misses!
+#53
+It gets you!
+#54
+Ok
+#55
+You can't unlock the keys.
+#56
+You have crawled around in some little holes and wound up back in the
+main passage.
+#57
+I don't know where the cave is, but hereabouts no stream can run on
+the surface for long.  I would try the stream.
+#58
+I need more detailed instructions to do that.
+#59
+I can only tell you what you see as you move about and manipulate
+things.  I cannot tell you where remote things are.
+#60
+I can't make any sense out of that.
+#61
+What?
+#62
+Are you trying to get into the cave?
+#63
+The grate is very solid and has a hardened steel lock.  You cannot
+enter without a key, and there are no keys nearby.  I would recommend
+looking elsewhere for the keys.
+#64
+The trees of the forest are large hardwood oak and maple, with an
+occasional grove of pine or spruce.  There is quite a bit of under-
+growth, largely birch and ash saplings plus nondescript bushes of
+various sorts.  This time of year visibility is quite restricted by
+all the leaves, but travel is quite easy if you detour around the
+spruce and berry bushes.
+#65
+
+
+		Welcome to ADVENTURE!
+
+
+	Original development by Willie Crowther.
+
+	Conversion to BDS  C by J. R. Jaeger
+
+	Unix standardization by Jerry D. Pohl.
+
+	Upgraded to version 6.6 by Robert R. Hall.
+
+
+		Would you like instructions?
+
+#66
+Digging without a shovel is quite impractical.  Even with a shovel
+progress is unlikely.
+#67
+Blasting requires dynamite.
+#68
+I'm as confused as you are.
+#69
+Mist is a white vapor, usually water, seen from time to time in
+caverns.  It can be found anywhere but is frequently a sign of a deep
+pit leading down to water.
+#70
+Your feet are now wet.
+#71
+I think I just lost my appetite.
+#72
+Thank you, it was delicious!
+#73
+You have taken a drink from the stream.  The water tastes strongly of
+minerals, but is not unpleasant.  It is extremely cold.
+#74
+The bottle is now empty.
+#75
+Rubbing the electric lamp is not particularly rewarding.  Anyway,
+nothing exciting happens.
+#76
+Peculiar.  Nothing unexpected happens.
+#77
+Your bottle is empty and the ground is wet.
+#78
+You can't pour that.
+#79
+Watch it!
+#80
+Which way?
+#81
+Oh dear, you seem to have gotten yourself killed.  I might be able to
+help you out, but I've never really done this before.  Do you want me
+to try to reincarnate you?
+#82
+All right.  But don't blame me if something goes wr......
+*                    --- POOF!! ---                    *
+You are engulfed in a cloud of orange smoke.  Coughing and gasping,
+you emerge from the smoke and find....
+
+#83
+You clumsy oaf, you've done it again!  I don't know how long I can
+keep this up.  Do you want me to try reincarnating you again?
+#84
+Okay, now where did I put my orange smoke?....  >POOF!<
+Everything disappears in a dense cloud of orange smoke.
+
+#85
+Now you've really done it!  I'm out of orange smoke!  You don't expect
+me to do a decent reincarnation without any orange smoke, do you?
+#86
+Okay, if you're so smart, do it yourself!  I'm leaving!
+#87
+#88
+#89
+#90
+>>> Messages 81 thru 90 are reserved for "Obituaries". <<<
+#91
+Sorry, but I no longer seem to remember how it was you got here.
+#92
+It's too heavy.  You'll have to drop something first.
+#93
+You can't go through a locked steel grate!
+#94
+I believe what you want is right here with you.
+#95
+You don't fit through a two-inch slit!
+#96
+I respectfully suggest you go across the bridge instead of jumping.
+#97
+There is no way across the fissure.
+#98
+You're not carrying anything.
+#99
+You are currently holding the following:
+#100
+It's not hungry (it's merely pining' for the fjords).  Besides, you
+have no bird seed.
+#101
+The snake has now devoured your bird.
+#102
+There's nothing here it wants to eat (except perhaps you).
+#103
+You fool, dwarves eat only coal!  Now you've made him *REALLY* mad!!
+#104
+Your cask is empty and the ground is soaked.
+#105
+You aren't carrying them!
+#106
+I don't need to, thank you.
+#107
+The ground is wet and the air is smelly.
+#108
+Your lamp is now on, but the glare from the walls is absolutely
+blinding.  If you proceed you are likely to fall into a pit.
+#109
+You haven't any matches.
+#110
+Don't be ridiculous!
+#111
+The door is extremely rusty and refuses to open.
+#112
+The plant indignantly shakes dry its leaves and asks, "Water?"
+#113
+The hinges are quite thoroughly rusted now and won't budge.
+#114
+The oil has freed up the hinges so that the door will now move,
+although it requires some effort.
+#115
+The plant has exceptionally deep roots and cannot be pulled free.
+#116
+The dwarves' knives vanish as they strike the walls of the cave.
+#117
+Something you're carrying won't fit through the tunnel with you.
+You'd best take inventory and drop something.
+#118
+You can't fit this five-foot clam through that little passage!
+#119
+You can't fit this five-foot oyster through that little passage!
+#120
+I advise you to put down the clam before opening it.  >Strain!<
+#121
+I advise you to put down the oyster before opening it.  >Wrench!<
+#122
+You don't have anything strong enough to open the clam.
+#123
+You don't have anything strong enough to open the oyster.
+#124
+A glistening pearl falls out of the clam and rolls away.  Goodness,
+this must really be an oyster.  (I never was very good at identifying
+bivalves.)  Whatever it is, it has now snapped shut again.
+#125
+The oyster creaks open, revealing nothing but oyster inside.  It
+promptly snaps shut again.
+#126
+You have crawled around in some little holes and found your way
+blocked by a recent cave-in.  You are now back in the main passage.
+#127
+There are faint rustling noises from the darkness behind you.
+#128
+Out from the shadows behind you pounces a bearded pirate!  "Har, har,"
+he chortles, "I'll just take all this booty and hide it away with me
+chest deep in the maze!"  He snatches your treasure and vanishes into
+the gloom.
+#129
+A sepulchral voice reverberating through the cave, says, "Cave closing
+soon.  All adventurers exit immediately through Main Office."
+#130
+A mysterious recorded voice groans into life and announces:
+   "This exit is closed.  Please leave via Main Office."
+
+#131
+It looks as though you're dead.  Well, seeing as how it's so close to
+closing time anyway, I think we'll just call it a day.
+
+#132
+The sepulchral voice intones, "The cave is now closed."  As the echoes
+fade, there is a blinding flash of light (and a small puff of orange
+smoke). . . .    As your eyes refocus, you look around and find...
+
+#133
+There is a loud explosion, and a twenty-foot hole appears in the far
+wall, burying the dwarves in the rubble.  You march through the hole
+and find yourself in the Main Office, where a cheering band of
+friendly elves carry the conquering adventurer off into the sunset.
+
+#134
+There is a loud explosion, and a twenty-foot hole appears in the far
+wall, burying the snakes in the rubble.  A river of molten lava pours
+in through the hole, destroying everything in its path, including you!
+
+#135
+There is a loud explosion, and you are suddenly splashed across the
+walls of the room.
+
+#136
+The resulting ruckus has awakened the dwarves.  There are now several
+threatening little dwarves in the room with you!  Most of them throw
+knives at you!  All of them get you!
+
+#137
+Oh, leave the poor unhappy bird alone.
+#138
+I dare say whatever you want is around here somewhere.
+#139
+I'm not sure what you mean by "Stop".  Use "Quit" if you want to give
+up.
+#140
+You can't get there from here.
+#141
+You are being followed by a very large, tame bear.
+#142
+-          *** THE HISTORY OF ADVENTURE (ABRIDGED) ***          -
+-                    ** By Ima Wimp **                          -
+ADVENTURE was originally developed by William Crowther, and later
+substantially rewritten and expanded by Don Woods at Stanford Univ.
+According to legend, Crowther's original version was modelled on an
+a real cavern, called Colossal Cave, which is a part of Kentucky's
+Mammoth Caverns.  That version of the game included the main maze
+and a portion of the third-level (Complex Junction - Bedquilt -
+Swiss Cheese rooms, etc.), but not much more.
+Don Woods and some others at Stanford later rewrote portions of
+the original program, and greatly expanded the cave.  That version
+of the game is recognizable by the maximum score of 350 points.
+Some major additions were done by David Long while at the University
+of Chicago, Graduate School of Business. Long's additions include the
+seaside entrance and all of the cave on the "far side" of Lost River
+(Rainbow Room - Crystal Palace - Blue Grotto, etc.).
+The castle problem was added in late 1984 by an anonymous writer.
+Thanks are owed to Roger Matus and David Feldman, both of U. of C.,
+for several suggestions, including the Rainbow Room, the telephone
+booth and the fearsome Wumpus. Most thanks (and apologies)
+go to Thomas Malory, Charles Dodgson, the Grimm Brothers, Dante,
+Homer, Frank Baum and especially Anon., the real authors of ADVENTURE.
+#143
+Do you indeed wish to quit now?
+#144
+There is nothing here with which to fill the vase.
+#145
+The sudden change in temperature has delicately shattered the vase.
+#146
+It is beyond your power to do that.
+#147
+I don't know how.
+#148
+It is too far up for you to reach.
+#149
+You killed a little dwarf.  The body vanishes in a cloud of greasy
+black smoke.
+#150
+The shell is very strong and is impervious to attack.
+#151
+What's the matter, can't you read?  Now you'd best start over.
+#152
+The axe bounces harmlessly off the dragon's thick scales.
+#153
+The dragon looks rather nasty.  You'd best not try to get by.
+#154
+The little bird attacks the green dragon, and in an astounding flurry
+gets burnt to a cinder.  The ashes blow away.
+#155
+On what?
+#156
+Okay, from now on I'll only describe a place in full the first time
+you come to it.  To get the full description, say "LOOK".
+#157
+Trolls are close relatives with the rocks and have skin as tough as
+that of a rhinoceros.  The troll fends off your blows effortlessly.
+#158
+The troll deftly catches the axe, examines it carefully, and tosses it
+back, declaring, "Good workmanship, but it's not valuable enough."
+#159
+The troll catches your treasure and scurries away out of sight.
+#160
+The troll refuses to let you cross.
+#161
+There is no longer any way across the chasm.
+#162
+Just as you reach the other side, the bridge buckles beneath the
+weight of the bear, which was still following you around.  You
+scrabble desperately for support, but as the bridge collapses you
+stumble back and fall into the chasm.
+#163
+The bear lumbers toward the troll, who lets out a startled shriek and
+scurries away.  The bear soon gives up the pursuit and wanders back.
+#164
+The axe misses and lands near the bear where you can't get at it.
+#165
+With what?  Your bare hands?  Against *HIS* bear hands??
+#166
+The bear is confused; he only wants to be your friend.
+#167
+For crying out loud, the poor thing is already dead!
+#168
+The bear eagerly licks up the honeycomb, after which he seems to calm
+down considerably and even becomes rather friendly.
+#169
+The bear is still chained to the wall.
+#170
+The chain is still locked.
+#171
+The chain is now unlocked.
+#172
+The chain is now locked.
+#173
+There is nothing here to which the chain can be locked.
+#174
+There is nothing here to eat.
+#175
+Do you want the hint?
+#176
+Do you need help getting out of the maze?
+#177
+You can make the passages look less alike by dropping things.
+#178
+Are you trying to explore beyond the Plover Room?
+#179
+There is a way to explore that region without having to worry about
+falling into a pit.  None of the objects available is immediately
+useful in discovering the secret.
+#180
+Do you need help getting out of here?
+#181
+Don't go west.
+#182
+Gluttony is not one of the troll's vices.  Avarice, however, is.
+#183
+Your lamp is getting dim.  You'd best start wrapping this up, unless
+you can find some fresh batteries.  I seem to recall there's a vending
+machine in the maze.  Bring some coins with you.
+#184
+Your lamp has run out of power.
+#185
+There's not much point in wandering around out here, and you can't
+explore the cave without a lamp.  So let's just call it a day.
+#186
+There are faint rustling noises from the darkness behind you.  As you
+turn toward them, the beam of your lamp falls across a bearded pirate.
+He is carrying a large chest.  "Shiver me timbers!", he cries, "I've
+been spotted!  I'd best hie meself off to the maze to hide me chest!"
+With that, he vanishes into the gloom.
+#187
+Your lamp is getting dim.  You'd best replace those batteries.
+#188
+Your lamp is now shining with renewed strength.
+#189
+Your lamp is getting dim, and you haven't any more coins.  You'd
+best start wrapping this up.
+#190
+I'm afraid the magazine is written in dwarvish.
+#191
+"This is not the maze where the pirate leaves his treasure chest."
+#192
+Hmmm, this looks like a clue, which means it'll cost you 10 points to
+read it.  Should I go ahead and read it anyway?
+#193
+It says, "Not all black rods are magic wands. Some are useful for
+other cave construction purposes. There might be some around here."
+#194
+It says the same thing it did before.
+#195
+I'm afraid I don't understand.
+#196
+"Congratulations on bringing light into the dark-room!"
+#197
+You strike the mirror a resounding blow, whereupon it shatters into a
+myriad tiny fragments.
+#198
+You have taken the vase and hurled it delicately to the ground.
+#199
+You prod the nearest dwarf, who wakes up grumpily, takes one look at
+you, curses, and grabs for his axe.
+#200
+Is this acceptable?
+#201
+There's no point in suspending a demonstration game.
+#202
+You managed to climb about halfway up before losing your hold and
+sliding back.
+#203
+You were only a few yards from the top when you slipped and tumbled
+all the way back down.
+#204
+Ok, ok.  No need to be grabby.
+#205
+Pulling an angry bear around is a good way to get your arm ripped off.
+#206
+The sword is now very clean.
+#207
+The sword is now covered with oil.
+#208
+The handle is now too slippery to grasp.
+#209
+You have no scabbard!
+#210
+You are already wearing it!
+#211
+Do you want to extract the sword from the anvil?
+#212
+If you could convince me of your royal blood, you might get somewhere.
+#213
+Are you trying to go up the slide?
+#214
+Maybe you'd better look for another way into the cave.
+#215
+You grasp the sword's handle and pull, but the sword won't budge.
+Do you want to try yanking it out?
+#216
+A tiny elf runs straight at you, shouts "Phuce!", and
+disappears into the forest.
+#217
+You can't swim.  You'd best go by boat.
+#218
+The boat's oars were stolen by the dwarves to play bing-bong.
+(That's dwarvish ping-pong -- with rocks!).  You have no way
+to propel the boat.
+#219
+You are still in the boat.  It is too heavy to carry.
+#220
+You had better leave the boat first.
+#221
+You are now sitting in a small boat.
+#222
+You couldn't possibly cross this sea without a large ship.
+#223
+The cliff is unscalable.
+#224
+Your keys are all too large for the lock.
+#225
+The wall is too smooth to climb.
+#226
+The shelf is beyond your reach.
+#227
+You are already wearing them!
+#228
+You thought maybe these were peyote??  You feel a little dizzy,
+but nothing happens.
+#229
+You are growing taller, expanding like a telescope!  Just before
+your head strikes the top of the chamber, the mysterious process
+stops as suddenly as it began.
+#230
+You are closing up like an accordion....shrinking..shrinking.  You
+are now your normal size.
+#231
+You have smashed your bottle all over the ground.
+#232
+You are now too big to leave the way you came in.
+#233
+This is obviously an elfin entrance.  Unless you can squeeze
+yourself through a six-inch door, you'll have to find another
+way into the cave.
+#234
+The wrought-iron door is now locked.
+#235
+The tiny door is now locked.
+#236
+The wrought-iron door is now unlocked.
+#237
+The tiny door is now unlocked.
+#238
+You are blocked by the wrought-iron door.
+#239
+<$$<
+#240
+The Wumpus looks at the food with distaste.  He looks at *YOU* with
+relish!
+#241
+You have jerked the cloak free of the rocks.  However, in doing
+so you have caused a small rock slide, blocking the entrance
+and making an unholy din.
+#242
+The cloak is stuck tight under the rocks.  You'll probably have to
+yank it out.
+#243
+The Wumpus grabs the axe, stops and picks his teeth with it for a few
+moments while looking thoughtfully at you.  When he finishes picking
+his teeth, he eats the axe, belches, farts... and starts after
+you again!
+#244
+As the bridge disappears, the Wumpus scrambles frantically to reach
+your side of the fissure.  He misses by inches, and with a horrible
+shriek plunges to his death in the depths of the fissure!
+#245
+You can't even hit a sleeping Wumpus!  The axe is now lying too near
+the Wumpus for you to retrieve it.
+#246
+The Wumpus is between you and the axe.  You can't reach it.
+#247
+You can't fit through a six-inch door!
+#248
+The dog easily dodges the axe, which lands beyond him where you can't
+get at it.
+#249
+The dog woofs (natch) down the food and looks around hungrily for
+more.  However, he does not appear to be any better disposed towards
+your presence.
+#250
+You've got to be kidding!
+#251
+It's attached to the wall!
+#252
+You can't put a thing into itself!
+#253
+The gnome firmly blocks the door of the booth.  You can't enter.
+#254
+The constant ringing has awakened the dwarves!
+There are now several threatening little dwarves in the room with
+you!  Most of them throw knives at you!  All of them get you!
+#255
+The telephone is out of order.
+#256
+The telephone is out of order and your hand is sore.
+#257
+A couple of lead slugs drop from the coin box.  (Gnomes are
+notoriously cheap....)  But you've broken the phone beyond
+all hope.
+#258
+He wants treasure, not gab.
+#259
+He didn't say anything!
+#260
+It isn't a parrot.  He didn't say anything.
+#261
+No one replies.  The line goes dead with a faint "Click".
+#262
+I think you are a little confused!
+#263
+As you move towards the phone booth, a gnome suddenly streaks
+around the corner, jumps into the booth and rudely slams the door
+in your face.  You can't get in.
+#264
+He isn't hungry.
+#265
+As the blast of the horn reverberates through the chamber, the
+seemingly solid rock wall crumbles away, revealing another room just
+beyond.  The wall was most likely worn thin by an ancient watercourse
+which dried up just before completely wearing away the rock.
+#266
+The chamber reverberates to the blast of the horn.
+(Satchmo you ain't!)
+#267
+The bees swarm over the fresh flowers, leaving the hive unguarded
+and revealing a sweet honeycomb.
+#268
+You are now out of breath.
+#269
+It isn't ringing!
+#270
+A hairy paw reaches out of the darkness and....
+#271
+You don't have the correct change.
+#272
+You go a short way down the bright passage, but the light
+grows to blinding intensity.  You can't continue.
+#273
+You know, if you type "BRIEF", I won't have to keep repeating these
+long descriptions of each room.
+#274
+Are you trying to reach the natural bridge?
+#275
+You can't get to it by climbing the walls or jumping or anything
+like that.  You could always put in a telephone call to the local
+spelunking club for advice, if you could find a phone.
+#276
+You turkey!!!  Now you've done it!  It took some effort, but you
+woke up the Wumpus.  He slowly opens one red eye, and then another,
+and then one more (!!), and looks at you sleepily.  He had been
+dreaming of a late snack.  If you don't act quickly, you'll
+be a *late* adventurer!
+#277
+The blast of your horn echoes throughout hill and dale.
+#278
+All you have are watercress sandwiches.  The bear is less than
+interested.
+#279
+You have smashed your sword to smithereens against a rock.
+#280
+Setting yourself adrift in the boat with no way to propel it would
+not be very smart.  Best to keep the pole.
+#281
+You're already in it!
+#282
+You've hit the jackpot!!  Hundreds of coins and slugs cascade from
+the telephone's coin return slot and spill all over the floor of
+the booth.
+#283
+Whoops!  The floor has opened out from under you!  It seems you
+have fallen into a bottomless pit.  As a matter of fact, you're
+still falling!  Well, I have better things to do than wait around
+for you to strike bottom, so let's just assume you're dead.
+Sorry about that, Chief.
+#284
+The telephone in the booth has begun to ring.
+#285
+I don't understand what you are trying to do!
+#286
+How do you propose to cross the river?
+#287
+The air is filled with beautiful music.
+#288
+The air fills with beautiful music.  The dog gradually becomes
+less fierce, and after a short while he lies down by the side of
+the cavern and falls into a deep sleep.
+#289
+Are you trying to get past the dog?
+#290
+The only person I can remember who managed to get past the dog
+was that singer, ummm, what's his name... Eurydice's friend....
+#291
+That wouldn't be wise.  It is best to let sleeping dogs lie.
+#292
+The stream flows out of one very small crack and into another.
+You can't go that way.
+#293
+The river is too wide and deep to cross.
+#294
+The glare is absolutely blinding.  If you proceed you are likely
+to fall into a pit.
+#295
+The hum of the bees rises to an angry buzz as you move towards
+the hive.
+#296
+The sticks and branches are all in a tangle and are stuck in the
+mud.  You'd need a shovel to dig them out.
+#297
+You're already carrying them!
+#298
+The chalice is slightly cracked.  It won't hold any liquids.
+#299
+The cask is now empty.
+#300
+The wine goes right to your head.  You reel around in a drunken
+stupor and finally pass out.  You awaken with a splitting headache,
+and try to focus your eyes....
+#301
+Yeeeecchhh!!
+#302
+Your bottle is already full.
+#303
+The cask is already full.
+#304
+There is nothing here with which to fill the bottle.
+#305
+There is nothing here which you would want to put into the cask.
+#306
+Your bottle is now full of water.
+#307
+The cask is now full of water.
+#308
+Your bottle is now full of oil.
+#309
+The cask is now full of oil.
+#310
+The bottle is now full of wine.
+#311
+The cask is now full of wine.
+#312
+You have nothing in which to carry it.
+#313
+You can't fill that.
+#314
+Do you want it in the bottle or the cask?
+#315
+Your containers are both full.
+#316
+It's empty.
+#317
+Hmmm, I see you have already gone through an extra set of batteries.
+I'll get rid of the trash for you.
+#318
+The bridge shakes as you cross.  Large hunks of clay and rock near
+the edge break off and hurtle far down into the chasm.  Several of
+the cracks on the bridge surface widen perceptibly.
+#319
+The load is too much for the bridge!  With a roar, the entire
+structure gives way, plunging you headlong into the raging river at
+the bottom of the chasm and scattering all your holdings.  As the
+icy waters close over your head, you flail and thrash with all your
+might, and with your last ounce of strength pull yourself onto the
+south bank of the river.
+#320
+You can't get at him.  He is inside the phone booth.
+#321
+Your lamp is already on.
+#322
+Your lamp is already off.
+#323
+Your lamp is again growing dim.  You'd better get some more batteries.
+#324
+You know, you are wasting your batteries by wandering around out
+here with your light on.
+#325
+<Generic Adventure -- Version:7.0, July 1994>
+#326
+Dead wumpi, as a rule, are light eaters.  Nothing happens.
+#327
+How do expect to feed a sleeping Wumpus?
+#328
+You aren't holding it!
+#329
+It won't fit!
+#330
+The coin drops into the slot with a dull "clunk".  There is no
+dial tone.
+#331
+It's already there.
+#332
+Please read the supplied documentation files to find out where to
+send complaints, suggestions, and bug reports.
+#333
+The chest is now unlocked.
+#334
+The chest is now locked.
+#335
+You can't get at it.
+#336
+It's already open.
+#337
+It's locked.
+#338
+It's already closed.
+#339
+You can't fill that.  It would leak all over the place.
+#340
+It's not inside anything.
+#341
+It isn't there!
+#342
+How?
+#343
+Taken.
+#344
+Dropped.
+#345
+I don't think I can.
+#346
+Interesting.  How?
+#347
+Huh?
+#348
+You are in perfect health.
+#349
+You are fit as a fiddle.
+#350
+Only wizards can do that!
+#351
+Are you kidding?  Do you want to suffocate the poor thing?
+#352
+Thrown.
+#353
+Left.
+#354
+You can't get close enough for a clean thrust.
+#355
+As you move in for the kill, the dwarf neatly slips a knife
+between your ribs.
+#356
+As you approach, the dwarf slashes out with his knife!
+#357
+It's too dark to see anything!
+#358
+It's not open.
+#359
+There's nothing inside.
+#360
+It contains:
+#361
+The billboard reads:
+"Visit Beautiful Colossal Cave.  Open Year Around.  Fun for
+the entire family, or at least for those who survive."
+Below the headline is an impossibly complicated map showing how
+to find Colossal Cave.  Not that it matters, because all the
+directions are written in Elvish.
+#362
+Hidden behind the poster is a steel safe, embedded in the wall.
+#363
+Brushing the dust from one of the larger rocks reveals some carved
+characters.
+#364
+Enough dusting, already!  You're making me sneeze.
+#365
+The safe door smoothly swings open.
+#366
+Maybe if you rubbed your fingertips with sandpaper....
+#367
+The safe's door clicks shut.
+#368
+This is a combination safe.  The keys won't help.
+#369
+I certainly can't read in this light.
+#370
+The poster has a picture of a thin man with a long white beard.
+He is wearing a high pointed cap embroidered with strange symbols,
+and he is pointing a finger at you.  Below the picture are the words:
+"I want you!--To report all good ideas for extensions to this game
+to me without delay.  Remember: ask not what ADVENTURE can do to
+you; ask what you can do for ADVENTURE."
+-                       *  *  *                              -
+"A public service of the John Dillinger Died for You Society."
+#371
+"Click."
+#372
+In the rock is carved the message "7-22-34".
+#373
+You can't get at them.
+#374
+Ok, I'll give you the full description whenever you enter a room
+for the first time.
+#375
+You don't have the right key.
+#376
+That's not strong enough to open the clam.
+#377
+That's not strong enough to open the oyster.
+#378
+Game suspension is no longer permitted!
+#379
+** Unused **
+#380
+>>> Messages 381 thru 389 are reserved for "Diagnoses". <<<
+#381
+You are a bit off top form, but nothing to worry about.
+#382
+You are weaker than usual.  Better avoid fights.
+#383
+You really ought to take a break.  You're in tough shape.
+#384
+You are on the edge of collapse.  Lots of sun and fresh air will
+speed your recovery.
+#385
+Your strength is nearly gone.  Only a miracle can save you now.
+#386
+** Unused **
+#387
+** Unused **
+#388
+** Unused **
+#389
+** Unused **
+#390
+>>> Messages 391 thru 399 are reserved for Radium Poisoning. <<<
+#391
+Is it hot in here?  You are flushed and sweating.
+#392
+You are feeling definitely peculiar, weak....
+#393
+You're dizzy, nauseous.  You can barely stand.
+#394
+You are really ill.  If you don't find an antidote soon, it's
+curtains.
+#395
+You are a walking wound.  You are very weak.  You'd better find out
+what's wrong before it's too late.
+#396
+Sheeesh!  What a mess!  Your hair has fallen out and your skin is
+covered with blisters.  And not an aspirin in sight!
+#397
+Well, you tried, but your strength is gone.  The agony is finally
+over.
+#398
+** Unused **
+#399
+** Unused **
+#400
+You feel rather disembodied, as if you were suddenly somewhere
+else entirely.
+#401
+You sense that you are in a dark place. The only thing in sight
+appears to be a companion to the crystal ball which holds your
+gaze. It seems to be searching the gloom for something to
+show you, but all it can see is itself: a brilliant blue
+six-pointed star suspended in space.
+#402
+Your gaze withdraws from the crystal ball, and you are now back
+in your normal senses.
+#403
+A large, stately elf walks up the rise, says the word
+"Saint-Michel", and is instantly transported to the castle.
+#404
+Are you trying to get to the castle?
+#405
+It's easy to get there if you know how. The elves cross over
+from here so perhaps you might watch an elf to see how.
+Of course they are a bit shy, so keep a good way off while you
+watch.
+#406
+You get a tingling feeling as you walk through the gate, and ...
+#407
+Fiddling with the bird in its cage is not useful.
+If you had it in your hand it would make a mess.
+#408
+Would you like a map?
Index: /trunk/minix/commands/advent/build
===================================================================
--- /trunk/minix/commands/advent/build	(revision 9)
+++ /trunk/minix/commands/advent/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/advent/database.c
===================================================================
--- /trunk/minix/commands/advent/database.c	(revision 9)
+++ /trunk/minix/commands/advent/database.c	(revision 9)
@@ -0,0 +1,141 @@
+/*	program DATABASE.C					*/
+
+#include	<string.h>
+#include	<stdio.h>
+#include	"advent.h"
+#include	"advdec.h"
+#include	"advtext.h"
+
+static char oline[256];
+
+_PROTOTYPE(void rdupto, (FILE *, int, int, char *));
+_PROTOTYPE(void rdskip, (FILE *, int, int));
+
+/*
+  Function to scan a file up to a specified
+  point and either print or return a string.
+*/
+void rdupto(fdi, uptoc, print, string)
+FILE *fdi;
+int uptoc, print;
+char *string;
+{
+    int c, i;
+    static _CONST unsigned char key[4] = {'c' | 0x80, 'L' | 0x80,
+					  'y' | 0x80, 'D' | 0x80};
+
+    i = 1;
+    while ((c = getc(fdi)) != uptoc && c != EOF) {
+	if (c == '\n')
+	    i = 1;
+	if (c >= 0x80)
+	    c ^= key[i++ & 3];
+	if (c == '\r')
+	    continue;
+	if (print)
+	    putchar(c);
+	else
+	    *string++ = (char) c;
+    }
+    if (!print)
+	*string = '\0';
+    return;
+}
+
+/*
+  Function to read a file skipping
+  a given character a specified number
+  of times, with or without repositioning
+  the file.
+*/
+void rdskip(fdi, skipc, n)
+FILE *fdi;
+int skipc, n;
+{
+    int c;
+
+    while (n--)
+	while ((c = getc(fdi)) != skipc)
+	    if (c == EOF)
+		bug(32);
+    return;
+}
+
+/*
+  Routine to request a yes or no answer to a question.
+*/
+boolean yes(msg1, msg2, msg3)
+int msg1, msg2, msg3;
+{
+    char answer[INPUTBUFLEN];
+
+    if (msg1)
+	rspeak(msg1);
+    do {
+	switch (*ask("\n> ", answer, sizeof(answer))) {
+	case 'n':
+	case 'N':
+	    if (msg3)
+		rspeak(msg3);
+	    return (FALSE);
+	case 'y':
+	case 'Y':
+	    if (msg2)
+		rspeak(msg2);
+	    return (TRUE);
+	default:
+	    fputs("Please answer Y (yes) or N (no).", stdout);
+	}
+    } while (TRUE);
+}
+
+/*
+  Print a location description from "advent4.txt"
+*/
+void rspeak(msg)
+int msg;
+{
+    if (msg == 54)
+	printf("ok.\n");
+    else {
+	fseek(fd4, idx4[msg - 1], 0);
+	rdupto(fd4, '#', 1, 0);
+    }
+    return;
+}
+
+/*
+  Print an item message for a given state from "advent3.txt"
+*/
+void pspeak(item, state)
+int item, state;
+{
+    fseek(fd3, idx3[item - 1], 0);
+    rdskip(fd3, '/', state + 2);
+    rdupto(fd3, '/', FALSE, oline);
+    if (strncmp(oline, "<$$<", 4) != 0)
+	printf("%s", oline);
+    return;
+}
+
+/*
+  Print a long location description from "advent1.txt"
+*/
+void desclg(loc)
+int loc;
+{
+    fseek(fd1, idx1[loc - 1], 0);
+    rdupto(fd1, '#', 1, 0);
+    return;
+}
+
+/*
+  Print a short location description from "advent2.txt"
+*/
+void descsh(loc)
+int loc;
+{
+    fseek(fd2, idx2[loc - 1], 0);
+    rdupto(fd2, '#', 1, 0);
+    return;
+}
Index: /trunk/minix/commands/advent/english.c
===================================================================
--- /trunk/minix/commands/advent/english.c	(revision 9)
+++ /trunk/minix/commands/advent/english.c	(revision 9)
@@ -0,0 +1,676 @@
+/*	program ENGLISH.C					*/
+
+
+#include	<stdio.h>
+#include	<string.h>
+#include	<ctype.h>
+#include	<stdlib.h>
+#include	"advent.h"
+#include	"advdec.h"
+
+#define ALL	109
+
+#define ENTER	 3
+#define CRAWL	17
+#define JUMP	39
+#define CLIMB	56
+#define XYZZY	62
+#define PLUGH	65
+#define PLOVER	71
+#define PHUCE	82
+
+_PROTOTYPE(static void getwords, (void));
+_PROTOTYPE(static void clrlin, (void));
+_PROTOTYPE(static void doobj, (int *));
+_PROTOTYPE(static boolean doiobj, (void));
+_PROTOTYPE(static boolean do_scoop_up, (void));
+_PROTOTYPE(static boolean check_next, (void));
+
+static char buffer[INPUTBUFLEN] = {'\0', '\0', '\0', '\0'};
+static char *txt[MAXWORDS] = {buffer, buffer, buffer, buffer};
+static char *cindex = buffer;
+static boolean pflag;
+static int vrbkey, words[MAXWORDS] = {0, 0, 0, 0}, word, wdx = 0;
+static int takdir[20] = {2,  6,  9, 10, 11, 13, 14, 17, 23, 25,
+			33, 34, 36, 37, 39, 78, 79, 80, 89, -1};
+
+static int vkey[60] = {
+     0,   199,     9,     0,   130,     0,   197,     0,     0,   243,
+     0,     0,    89,   140,     0,     5,     0,   227,     0,     0,
+     0,    31,    42,     0,     0,     0,     0,   172,     1,     0,
+     0,     0,   254,     0,    69,     0,     0,    92,     0,     0,
+   138,   137,   149,   239,    45,    74,   183,     0,     0,   112,
+   241,     0,   114,     0,    30,     0,     0,     0,     0,     0
+};
+
+static int ptab[260] = {
+     0,  3028,  3065,  3009, -3005,  5071,  5070,  5058, -5020, 19055,
+ 19108, 19038, 19020, 19071, 19070, 19058, 19004, 19048, 19091, 19094,
+ 19112, 19002, 19118,  2062,  2066,  2047,  2067,  2053,  2065, -2010,
+ -3114,  4034,  4011,  4101,  4035,  4099,  4098,  4017,  4104,  4014,
+  4015, -4087,  3083,  3085, -3081,  5055,  5108,  5020,  5071,  5070,
+  5058,  5004,  5048,  5091,  5112,  5099,  5118, 19055, 19108, 19020,
+ 19071, 19070, 19058, 19004, 19048, 19091, 19112, 19099,-19118,  3028,
+  3065,  3009,  3005, -3018, 19055, 19108, 19038, 19020, 19071, 19070,
+ 19058, 19004, 19004, 19048, 19091, 19094, 19112, 19002,-19118,  3028,
+  3065, -3018, 19055, 19108, 19038, 19020, 19071, 19070, 19058, 19004,
+ 19048, 19091, 19094, 19112, 19118,  2062,  2066,  2047,  2067,  2053,
+  2065, -2010,  3102, -3090, 19055, 19108, 19020, 19071, 19070, 19058,
+ 19004, 19048, 19091, 19014, 19015, 19112, 19118, 19120, 19120, -9999,
+  3090,  3102,  3028,  3057,  3065,  3009, -3005,-29999,  2052, -2068,
+  2024,  2065,  2091,  2042,  2073,  5071,  5070,  5058, -5020, 30999,
+  2062,  2066,  2047,  2067,  2053,  2065,  2010,  2073, 19055, 19108,
+ 19038, 19020, 19071, 19070, 19058, 19004, 19048, 19091, 19094, 19112,
+ 19002,-19118,  2014,  2015,  2013,  2999,  5014,  5015,  5013,  5999,
+  5110,  5113, -5999,  5055,  5108,  5020,  5071,  5070,  5058,  5004,
+  5048,  5091,  5014,  5015,  5112,  5099, -5118,  3102, -3090,  6066,
+  6047,  6067,  6053,  6072,  6073,  5055,  5108,  5020,  5071,  5070,
+  5004,  5004,  5048,  5091,  5112,  5099,  5118, 19055, 19108, 19020,
+ 19071, 19070, 19058, 19004, 19048, 19091,-19118,  4034,  4011,  4101,
+  4035,  4099,  4098,  4017,  4104,  4027,  4087,  9999,-30999,  2002,
+ -6002,  3102, -3090,  9999,  4034,  4011,  4101,  4035,  4099,  4087,
+  4098,  4017,  4104, -4027, -5999,     0,     0,     0,     0,     0,
+};
+
+static int adjkey[40] = {
+     0,    15,    38,    64,     4,    63,     1,    61,    62,    67,
+     9,    27,    53,    46,    47,    60,    31,    39,    40,     6,
+    43,    26,    32,    28,    34,    50,    49,    45,    44,    10,
+    20,    25,    21,    36,    37,    30,    33,     0,     0,     0
+};
+
+static int adjtab[70] = {
+     0,     5,    98,   -83,     2,   -90,    66,    41,   -90,   -39,
+    41,    14,    15,    50,   -11,    50,    64,    56,    72,   -74,
+   -19,   119,    59,    73,  -118,  -119,   -70,   -41,    95,  -118,
+  -118,   -58,   -71,  -120,   110,  -108,  -120,   -73,   -62,   -60,
+   110,    54,   -63,   -67,   -41,   -27,   -47,    52,   -75,   -69,
+    65,   112,    -3,    41,    72,    90,    20,   101,   107,  -118,
+   -55,   -10,   -38,    -4,    48,     9,   -71,   -39,     0,     0
+};
+
+/*
+  Analyze a two word sentence
+*/
+int english()
+{
+
+    char *ch_ptr, *word1, *word2;
+    int type, val, type2, val2, adj, k, kk;
+    static int iwest = 0;
+
+    if (!(words[++wdx])) {
+	getwords();
+	wdx = 0;
+    }
+    pflag = FALSE;
+    word = words[wdx];
+    if (word < 0) {			/* check first word	 */
+	printf("I didn't understand the word \"%s\"\n", txt[wdx]);
+	words[wdx+1] = 0;
+	return (FALSE);			/* didn't know it	 */
+    }
+    type2 = val2 = -1;
+    type = CLASS(word);
+    clrlin();
+    val = VAL(word);
+    if (words[wdx + 1] && CLASS(words[wdx + 1]) != CONJUNCTION) {
+
+	/* 'SAY' or 'CALL'.  If no next word, pass on to higher powers. */
+	if (type == ACTION && (val == SAY || val == YELL)) {
+	    word = words[++wdx];
+	    if (!(word == XYZZY || word == PLUGH
+		  || word == PLOVER || word == PHUCE)) {
+		if (val == SAY)
+		    printf("Okay, \"%s\".\n", txt[wdx]);
+		else {
+		    for (ch_ptr = txt[wdx]; *ch_ptr; ch_ptr++)
+			if (islower(*ch_ptr))
+			    *ch_ptr = toupper(*ch_ptr);
+		    printf("Okay, \"%s\"!!!!!\n", txt[wdx]);
+		}
+		return (FALSE);
+	    }
+	} else {
+	    word1 = txt[wdx];
+	    word2 = txt[wdx + 1];
+
+	    /* Special stuff for 'ENTER'.  Can't go into water. 'ENTER
+	       BOAT' means 'TAKE BOAT' */
+	    if (word == ENTER) {
+		if (CLASS(words[wdx + 1]) == NOUN && VAL(words[wdx + 1]) == BOAT)
+		    word = TAKE + 2000;
+		else if ((strcmp(word2, "stream") == 0)
+			 || (strcmp(word2, "water") == 0)
+			 || (strcmp(word2, "reservoir") == 0)
+			 || (strcmp(word2, "ocean") == 0)
+			 || (strcmp(word2, "sea") == 0)
+			 || (strcmp(word2, "pool") == 0)) {
+		    rspeak(liqloc(g.loc) == WATER ? 70 : 43);
+		    wdx++;
+		    return (FALSE);
+		}
+	    } else {
+		type2 = CLASS(words[wdx + 1]);
+		val2 = VAL(words[wdx + 1]);
+
+		/* 'LEAVE' is motion verb, unsless leaving an object.
+		   E.G., 'LEAVE BOAT' or 'LEAVE BOTTLE'.  BUt make sure
+		   to leave ('DROP') only totable objects. */
+		if (strcmp(word1, "leave") == 0 && type2 == NOUN) {
+		    if (!hinged(val2) || g.fixed[val2])
+			word = LEAVE + 2000;
+
+		    /* IF 'LIGHT LAMP', Light must be taken as an
+		       action verb, not a noun. */
+		} else if (strcmp(word1, "light") == 0
+			   && VAL(words[wdx + 1]) == LAMP) {
+		    word = ON + 2000;
+
+		    /* 'WATER PLANT' becomes 'POUR WATER', If we are at
+		       plant. 'OIL DOOR' becomes 'POUR OIL', etc., etc. */
+		} else if ((strcmp(word1, "water") == 0 || strcmp(word1, "oil") == 0)
+			   && (strcmp(word2, "plant") == 0 || strcmp(word2, "door") == 0
+			       || strcmp(word2, "sword") == 0 || strcmp(word2, "anvil") == 0)
+			   && at(val2)) {
+		    words[wdx + 1] = word;
+		    txt[wdx + 1] = txt[wdx];
+		    word = POUR + 2000;
+		}
+	    }
+	}
+
+    }
+    /* This is the 'inner' loop.  Dispatching of all word in a clause
+       after the first comes through here. */
+    do {
+	switch (CLASS(word)) {
+	case MOTION:
+	    {
+		boolean do_part2;
+		int i;
+
+		do_part2 = FALSE;
+		type = CLASS(verbs[vrbx]);
+		val = VAL(verbs[vrbx]);
+		if (!vrbx)
+		    do_part2 = TRUE;
+		else {
+		    if (type > ACTION) {
+			rspeak(confuz());
+			return (FALSE);
+		    }
+		}
+		if (type == ACTION) {
+		    if (val == GO)
+			do_part2 = TRUE;
+		    else {
+			if (val == TAKE) {
+			    for (i = 0; i < 20; i++)
+				if (takdir[i] == val)
+				    do_part2 = TRUE;
+			}
+			if (!do_part2) {
+			    word = vocab(txt[wdx], 1);
+			    if (word)
+				words[wdx--] = word;
+			}
+		    }
+		} else if (type != CRAWL && type != JUMP
+			   && type != CLIMB)
+		    do_part2 = TRUE;
+		if (do_part2) {
+		    verbs[1] = word;
+		    vrbx = 1;
+		    if (strcmp(txt[wdx], "west") == 0) {
+			iwest++;
+			if (iwest == 10)
+			    rspeak(17);
+		    }
+		}
+		break;
+	    }
+	case NOUN:
+	    if (pflag) {
+		if (!doiobj())
+		    return (FALSE);
+	    } else {
+		word = VAL(word);
+		if (word == ALL) {
+		    if (!do_scoop_up())
+			return (FALSE);
+		} else {
+		    doobj(&word);
+		    if (word > 0) {
+			objs[++objx] = word;
+			otxt[objx] = txt[wdx];
+		    } else {
+			clrlin();
+			pflag = FALSE;
+			wdx++;
+			while (words[wdx]) {
+			    if (CLASS(words[wdx]) == CONJUNCTION)
+				break;
+			    wdx++;
+			}
+			if (words[wdx] == 0)
+			    return (FALSE);
+		    }
+		}
+	    }
+	    break;
+	case ACTION:
+	    if (vrbx == 0)
+		vrbx++;
+	    else {
+		if (VAL(verbs[vrbx]) == TAKE) {
+		    val = VAL(word);
+		    if (val == DRINK || val == INVENTORY
+			|| val == SCORE || val == NOTHING
+			|| val == LOOK);
+		    else if (val == GO && (
+					 strcmp(txt[wdx], "walk") == 0
+				       || strcmp(txt[wdx], "run") == 0
+				   || strcmp(txt[wdx], "hike") == 0));
+		    else {
+			rspeak(confuz());
+			return (FALSE);
+		    }
+		} else if (objx || CLASS(words[wdx - 1]) == CONJUNCTION) {
+		    rspeak(confuz());
+		    return (FALSE);
+		}
+	    }
+	    verbs[vrbx] = word;
+	    vtxt[vrbx] = txt[wdx];
+	    break;
+	case MISC:
+	    if (vrbx) {
+		rspeak(confuz());
+		return (FALSE);
+	    }
+	    verbs[1] = word;
+	    vrbx = 1;
+	    break;
+	case PREPOSITION:
+	    if (CLASS(verbs[vrbx]) != ACTION || iobx) {
+		rspeak(confuz());
+		return (FALSE);
+	    }
+	    vrbkey = vkey[VAL(verbs[vrbx])];
+	    if (!vrbkey) {
+		rspeak(confuz());
+		return (FALSE);
+	    }
+	    prep = VAL(word);
+	    pflag = TRUE;
+	    break;
+	case ADJACTIVE:
+	    /* Adjective handler. Scarf the next word, make sure it is
+	       a valid object for this object.  Then call getobj to see
+	       if it is really there, Then link into object code. */
+	    adj = VAL(word);
+	    if (!check_next())
+		return (FALSE);
+	    else if (CLASS(word) == CONJUNCTION) {
+		printf("%s what?\n", txt[wdx - 1]);
+		return (FALSE);
+	    } else {
+		if (CLASS(word) != NOUN)
+		    word = vocab(txt[wdx], NOUN);
+		if (word == -1 || CLASS(word) != NOUN || VAL(word) == ALL) {
+		    rspeak(confuz());
+		    return (FALSE);
+		}
+		words[wdx] = word;
+		kk = VAL(word);
+		for (k = adjkey[adj]; adjtab[k] >= 0; k++) {
+		    if (kk == abs(adjtab[k]))
+			break;
+		}
+		if (adjtab[k] < 0) {
+		    rspeak(confuz());
+		    return (FALSE);
+		}
+	    }
+	    break;
+	case CONJUNCTION:
+	    if (!check_next())
+		return (FALSE);
+	    switch (CLASS(word)) {
+	    case MOTION:
+	    case ACTION:
+	    case MISC:
+		words[wdx--] = 0;
+		break;
+	    case NOUN:
+	    case ADJACTIVE:
+		break;
+	    case PREPOSITION:
+	    case CONJUNCTION:
+		rspeak(confuz());
+		return (FALSE);
+	    default:
+		bug(33);
+	    }
+	    break;
+	default:
+	    bug(33);
+	}
+	word = words[++wdx];
+	if (word < 0) {
+	    if (pct(50))
+		printf("I don't understand the word %s?\n", txt[wdx]);
+	    else
+		printf("Mumble ?  %s\n", txt[wdx]);
+
+	    words[wdx+1] = 0;
+	    return (FALSE);
+	}
+	type = CLASS(word);
+	if (type == NOUN) {
+	    /* It's not the first:  Make sure he included a comma or
+	       'and'. Differenctiate between direct & indirect objects.
+	       Check for special case of multiple ofjects: 'feed bear
+	       honey' or 'throw troll nugget'. */
+	    if ((pflag ? iobx : objx)
+		&& CLASS(words[wdx - 1]) != CONJUNCTION) {
+		val = VAL(verbs[vrbx]);
+		if (!living(objs[objx]) || (val != THROW && val != FEED)) {
+		    rspeak(confuz());
+		    return (FALSE);
+		}
+		iobx++;
+		iobjs[iobx] = objs[objx];
+		objs[objx] = 0;
+		objx++;
+	    }
+	}
+    } while (word);
+
+    if (verbs[1] == 0) {
+	if (objs[1] == 0) {
+	    rspeak(confuz());
+	    clrlin();
+	} else if (objs[2])
+	    printf("What do you want to do with them?\n");
+	else
+	    printf("What do you want to do with %s?\n", otxt[1]);
+	return (FALSE);
+    } else if (objx > 1 && iobx > 1) {
+	rspeak(confuz());
+	return (FALSE);
+    }
+    return (TRUE);
+
+}
+
+/*
+  retrieve input line (max INPUTBUFLEN chars), convert to lower case
+   & rescan for first two words (max. WORDSIZE-1 chars).
+*/
+static void getwords()
+{
+    static int wdx = 0;
+    int i, term_loc;
+    char terminator;
+
+    if (*cindex == '\0') {
+	while (!*ask("\n> ", buffer, sizeof(buffer))) ;
+	for (cindex = buffer; *cindex; cindex++)
+	    if (isupper(*cindex))
+		*cindex = tolower(*cindex);
+	cindex = buffer;
+    }
+    wdx = 0;
+    buffer[sizeof(buffer)-1] = '\0';
+    for (i = 0; i < MAXWORDS; i++) {
+	txt[i] = &buffer[sizeof(buffer)-1];
+	words[i] = 0;
+    }
+    do {
+	while (*cindex == ' ')
+	    cindex++;
+	txt[wdx] = cindex;
+	term_loc = strcspn(cindex, " ,.;\n");
+	cindex += term_loc;
+	terminator = *cindex;
+	*cindex++ = '\0';
+	if ((strcmp(txt[wdx], "a") != 0)
+	    && (strcmp(txt[wdx], "the") != 0)
+	    && (strcmp(txt[wdx], "an") != 0)) {
+	    words[wdx] = vocab(txt[wdx], 0);
+	    wdx++;
+	}
+	if (terminator == ',') {
+	    txt[wdx] = "and";
+	    words[wdx] = vocab(txt[wdx], 0);
+	    wdx++;
+	}
+    }
+    while ((terminator != ';') && (terminator != '.')
+	   && (terminator != '\0') && (terminator != '\n'));
+    if (terminator == '\0')
+	cindex--;
+    return;
+}
+
+/* CLRIN, clears out all surrent syntax args in preparation for
+ * new input line
+ */
+
+static void clrlin()
+{
+    int i;
+
+    for (i = 0; i < MAXWORDS; i++) {
+	verbs[i] = 0;
+	vtxt[i] = &buffer[sizeof(buffer)-1];
+    }
+
+    for (i = 0; i < MAXITEMS; i++) {
+	objs[i] = 0;
+	otxt[i] = &buffer[sizeof(buffer)-1];
+	iobjs[i] = 0;
+	iotxt[i] = &buffer[sizeof(buffer)-1];
+    }
+    vrbx = 0;
+    objx = 0;
+    iobx = 0;
+    prep = 0;
+}
+
+/*
+  Routine to process an object.
+*/
+static void doobj(object)
+int *object;
+{
+    int msg;
+
+    if (holding(*object))
+	return;
+    if (blind()) {
+	printf("I see no %s here.\n", txt[wdx]);
+	*object = 0;
+	return;
+    }
+    /* Is object here?  if so, transitive */
+    if (g.fixed[*object] == g.loc || athand(*object))
+	return;
+    else if (here(*object)) {
+	msg = plural(*object) ? 373 : 335;
+	*object = 0;
+	rspeak(msg);
+    }
+    /* Did he give grate as destination? */
+    else if (*object == GRATE) {
+	if (g.loc == 1 || g.loc == 4 || g.loc == 7) {
+	    verbs[1] = DEPRESSION;
+	    vrbx = 1;
+	    return;
+	} else if (g.loc > 9 && g.loc < 15) {
+	    verbs[1] = ENTRANCE;
+	    vrbx = 1;
+	    return;
+	}
+    }
+    /* Is it a dwarf he is after? */
+    else if (dcheck() && g.dflag >= 2) {
+	*object = DWARF;
+    }
+    /* Is he trying to get/use a liquid? */
+    else if (liqloc(g.loc) == *object
+	     || (liq(BOTTLE) == *object && athand(BOTTLE))
+	     || (liq(CASK) == *object && athand(CASK)));
+    else if (*object == PLANT && at(PLANT2) &&
+	     g.prop[PLANT2] == 0) {
+	*object = PLANT2;
+    } else if (*object == ROCKS && at(CARVNG)) {
+	*object = CARVNG;
+    }
+    /* Is he trying to grab a knife? */
+    else if (*object == KNIFE && g.knfloc == g.loc) {
+	rspeak(116);
+	g.knfloc = -1;
+    }
+    /* Is he trying to get at dynamite? */
+    else if (*object == ROD && athand(ROD2)) {
+	*object = ROD2;
+    } else if (*object == DOOR && (at(SAFE) || at(TDOOR)
+				   || at(TDOOR2) || at(PDOOR))) {
+	if (at(TDOOR2))
+	    *object = TDOOR2;
+	else if (at(PDOOR))
+	    *object = PDOOR;
+	else if (at(SAFE))
+	    *object = SAFE;
+	else
+	    *object = TDOOR;
+    } else if (*object == BOOK && athand(BOOK2)) {
+	*object = BOOK2;
+    } else if (!(verbs[vrbx] == FIND || verbs[vrbx] == INVENTORY)) {
+	*object = 0;
+	printf("I see no %s here.\n", txt[wdx]);
+    }
+    return;
+}
+
+static boolean doiobj()
+{
+    char dk[INPUTBUFLEN], dkk[INPUTBUFLEN];
+    int kk;
+    boolean ok;
+
+    /* checks object is valid for this preposition */
+    ok = TRUE;
+    word = VAL(word);
+    if (word != ALL) {
+	doobj(&word);
+	if (word > 0) {
+	    iobjs[++iobx] = word;
+	    iotxt[iobx] = txt[wdx];
+	} else
+	    ok = FALSE;
+    }
+    kk = abs(ptab[vrbkey]) / 1000;
+    if (kk == prep) {
+	/* preprosition is valid with this verb now check object of
+	   preprosition */
+
+	if (word == 0 || CLASS(word) == CONJUNCTION) {
+	    /* no object following prepresition: check special cases */
+
+	    pflag = FALSE;
+	    strcpy(dk, txt[--wdx]);
+	    strcpy(dkk, vtxt[vrbx]);
+	    ok = FALSE;
+	    if ((strcmp(dk, "on") == 0
+		 || strcmp(dk, "off") == 0)
+		&& (strcmp(dkk, "turn") == 0
+		    || objs[objx] == LAMP))
+		ok = TRUE;
+	    if (strcmp(dkk, "take") == 0
+		|| strcmp(dkk, "put") == 0)
+		ok = TRUE;
+	    if (strcmp(dk, "up") == 0
+		&& strcmp(dkk, "pick") == 0)
+		ok = TRUE;
+	    if (strcmp(dk, "down") == 0
+		 && (strcmp(dkk, "put") == 0 || verbs[vrbx] == THROW) )
+		ok = TRUE;
+	} else {
+	    /* object follows preposition See if it's plausible. */
+
+	    kk = abs(ptab[vrbkey]) % 1000;
+	    if (kk == word && kk == ALL) {
+		if (!do_scoop_up())
+		    return (FALSE);
+	    } else if (!(kk == word || kk == 999)) {
+		vrbkey++;
+		ok = ptab[vrbkey - 1] < 0 ? FALSE : TRUE;
+	    }
+	}
+    }
+    return (ok);
+}
+
+static boolean do_scoop_up()
+{
+    int i, val;
+
+    val = VAL(verbs[vrbx]);
+    if (val == DROP || val == PUT || val == LEAVE) {
+	for (i = 1; i < MAXOBJ; i++) {
+	    if (!athand(i) || g.fixed[i])
+		continue;
+	    if (i > WATER && i <= WINE + 1)
+		continue;
+	    if (toting(i)) {
+		objs[++objx] = i;
+		otxt[objx] = "BUG???";
+		if (objx >= 44)
+		    break;
+	    }
+	}
+    }
+    if (val == TAKE || val == PICK || val == GET) {
+	if (blind()) {
+	    rspeak(357);
+	    return (FALSE);
+	} else {
+	    for (i = 1; i < MAXOBJ; i++) {
+		if (!athand(i) || g.fixed[i])
+		    continue;
+		if (i > WATER && i <= WINE + 1)
+		    continue;
+		if (!toting(i)) {
+		    objs[++objx] = i;
+		    otxt[objx] = "BUG???";
+		    if (objx >= 44)
+			break;
+		}
+	    }
+	}
+    }
+    return (TRUE);
+}
+
+static boolean check_next()
+{
+
+    word = words[wdx + 1];
+    if (word > 0)
+	return (TRUE);
+    else if (word == 0)
+	rspeak(confuz());
+    else {
+	if (pct(50))
+	    printf("I don't understand the word %s?\n", txt[wdx]);
+	else
+	    printf("Mumble ?  %s\n", txt[wdx]);
+	words[wdx+1] = 0;
+    }
+
+    return (FALSE);
+}
Index: /trunk/minix/commands/advent/initial.c
===================================================================
--- /trunk/minix/commands/advent/initial.c	(revision 9)
+++ /trunk/minix/commands/advent/initial.c	(revision 9)
@@ -0,0 +1,264 @@
+/*
+  Initialization of adventure play variables
+*/
+#include	<string.h>
+#include	<stdio.h>
+#include	"advent.h"		/* #define preprocessor equates	 */
+#define EXTERN				/* define, not declare, in advdec.h */
+#include	"advdec.h"
+
+int plac[MAXOBJ] = {
+      0,   0,   3,   8,  10,  11,   0,  14,   0, 148,	/*   0 -   9 */
+     96,  19,  17, 101, 103,   0, 106,   0,   0, 238,	/*  10 -  19 */
+    238, 117, 190, 109,  25,  23, 111,  35,   0,  97,	/*  20 -  29 */
+      0, 119,   0, 117,   0, 130,   0, 126, 140,   0,	/*  30 -  39 */
+     96,  94, 158, 160, 188,   0, 155, 174, 166, 228,	/*  40 -  49 */
+     18, 204,  27,  29,  30,   0,  92, 168,  97, 100,	/*  50 -  59 */
+    101,   0, 119, 127, 130, 141, 144, 205,  28, 182,	/*  60 -  69 */
+    225, 230,   0, 147, 241, 248,   0,   0,   0,   0,	/*  70 -  79 */
+      0,   0,   0,   0,   0,   0,   0, 193, 102,   0,	/*  80 -  89 */
+    159, 141, 172, 188, 189,   0,   0, 193, 227, 174,	/*  90 -  99 */
+      0,  13, 238, 217, 171,   0, 146, 159,   3,   0,	/* 100 - 109 */
+      0,   0,   0,   3, 180,  39,   5,   0, 110, 169,	/* 110 - 119 */
+    200
+};
+
+int fixd[MAXOBJ] = {
+      0,   0,   0,   9,   0,   0,   0,  15,   0,   0,	/*   0 -   9 */
+      0,  -1,  27,  -1,   0,   0,   0,  -1,   0,   0,	/*  10 -  19 */
+      0, 122, 235,  -1,  -1,  67,  -1, 110,   0,  -1,	/*  20 -  29 */
+     -1, 121,   0, 122,   0,  -1,  -1,  -1,  -1,   0,	/*  30 -  39 */
+     -1,  -1, 166, 167, 189,   0,   0,  -1,   0, 229,	/*  40 -  49 */
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,	/*  50 -  59 */
+      0,   0, 121,   0,  -1,   0,   0,   0,   0,   0,	/*  60 -  69 */
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,	/*  70 -  79 */
+      0,   0,   0,   0,   0,   0,   0,  -1, 194,  -1,	/*  80 -  89 */
+      0,  -1, 174,  -1,  -1,   0,   0,  -1,  -1,  -1,	/*  90 -  99 */
+      0,   0,   0,  -1,  -1,  -1,   0,   0,   0,   0,	/* 100 - 109 */
+      0,   0,  -1,   0,   0,  -1,  -1,   0,   0,   0,	/* 110 - 119 */
+      0
+};
+
+struct playinfo g = {
+    0,							/* turns */
+    1,							/* loc */
+    1,							/* oldloc */
+    1,							/* oldloc2 */
+    1,							/* newloc */
+    {							/* loc_attrib[MAXLOC] */
+	  0,   73,   65,   73,   73,			/*   0 -   4 */
+	 65,   65,   73, 1601,   33,			/*   5 -   9 */
+	 32,   32,   32, 1824,   32,			/*  10 -  14 */
+	  0,    2,    0,    0, 2816,			/*  15 -  19 */
+	  2,    2,    2,    0,   10,			/*  20 -  24 */
+	  0,    2,    0,    0,    0,			/*  25 -  29 */
+	  0,    2,    2,    8,    0,			/*  30 -  34 */
+	  0,    0,    0,    8,    0,			/*  35 -  39 */
+	  2,    0,  256,  256,  256,			/*  40 -  44 */
+	256,  272,  272,  272,  256,			/*  45 -  49 */
+	256,    0,  256,  256,  272,			/*  50 -  54 */
+	256,  272,    0,   16,    2,			/*  55 -  59 */
+	  0,    0,    0,    0,    0,			/*  60 -  64 */
+	  0,    0,    0,    0,    0,			/*  65 -  69 */
+	  0,    0,    0,    0,    0,			/*  70 -  74 */
+	  0,    0,    0,    0,    2,			/*  75 -  79 */
+	256,  256,  272,    0,    0,			/*  80 -  84 */
+	 16,  272,    0,    0,    2,			/*  85 -  89 */
+	  2,    0,    0,    0,    0,			/*  90 -  94 */
+	  8,    0,    0, 1280,  513,			/*  95 -  99 */
+	513,  512,    0,    0,    0,			/*  00 -  04 */
+	  0,    0,    0,  768,    0,			/* 105 - 109 */
+	  0,    0,    0,    8,    0,			/* 110 - 114 */
+	  1,    1,    0,    0,    0,			/* 115 - 119 */
+	  0,    0,   16,   16,   16,			/* 120 - 124 */
+	 16,   17,   16,   16,   16,			/* 125 - 129 */
+	 16,    0,    0,    0,    0,			/* 130 - 134 */
+	  0,    0,    0,    0,    0,			/* 135 - 139 */
+	  0, 1040,   16,    0,    0,			/* 140 - 144 */
+	  2,   65,   65,   65,   65,			/* 145 - 149 */
+	 65,   65,   65,   65,   65,			/* 150 - 154 */
+	 65,    3, 2625, 2113,   65,			/* 155 - 159 */
+	 65,    3,    3,    3,    3,			/* 160 - 164 */
+	  3,   41,   41,    9,    9,			/* 165 - 169 */
+	  0,    0,    0,    0,    0,			/* 170 - 174 */
+	  0,    0,    0,    2,    0,			/* 175 - 179 */
+	  0,    2,    0,    0,    0,			/* 180 - 184 */
+	  0,    0,    0,    0,   16,			/* 185 - 189 */
+	  0,    0,    9,    0,    0,			/* 190 - 194 */
+	  0,    0,    0,    9,    2,			/* 195 - 199 */
+	  1,    1, 2304,    0,    0,			/* 200 - 204 */
+	  0,    8,    8,    8,    0,			/* 205 - 209 */
+	  0,    0,    1,    0,    9,			/* 210 - 214 */
+	  0,    0,   12,    0,    0,			/* 215 - 219 */
+	  0,    0,    0,    0,    0,			/* 220 - 224 */
+	  0,    2, 2625,   73,   73,			/* 225 - 229 */
+	  0,    2,    2,    2,    2,			/* 230 - 234 */
+	  0,    0,    2,   65, 3137,			/* 235 - 239 */
+	 65,   65,   65,   65,   65,			/* 240 - 244 */
+	 65,   65,   65,   65	  			/* 245 - 249 */
+    },							/* loc_attrib[MAXLOC] */
+    {0 },						/* place[MAXOBJ] */
+    {0 },						/* fixed[MAXOBJ] */
+    {							/* weight[MAXOBJ] */
+	0, 0, 1, 0, 1, 2, 2, 0, 0, 2,			/*   0 -   9 */
+	1, 0, 0, 0, 7, 7, 1, 0, 0, 2,			/*  10 -  19 */
+	1, 0, 0, 0, 0, 0, 0, 0, 3, 0,			/*  20 -  29 */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 3,			/*  30 -  39 */
+	0, 0, 0, 0, 0, 0, 1, 1, 0, 0,			/*  40 -  49 */
+	6, 1, 2, 2, 3, 5, 4, 3, 2, 3,			/*  50 -  59 */
+	4, 1, 3, 1, 3, 2, 1, 1, 2, 2,			/*  60 -  69 */
+	2, 3, 1, 1, 3, 1, 0, 0, 0, 0,			/*  70 -  79 */
+	0, 2, 2, 2, 2, 2, 2, 0, 0, 0,			/*  70 -  79 */
+	1, 0, 0, 0, 0, 3, 2, 0, 0, 0,			/*  80 -  89 */
+	0, 2, 1, 0, 0, 0, 1, 1, 2, 0,			/* 100 - 109 */
+	3, 3, 0, 1, 1, 0, 0, 0, 3, 1,			/* 110 - 119 */
+	2, 0, 0						/* 120 - 129 */
+    },							/* weight[MAXOBJ] */
+    {0 },						/* atloc[MAXLOC] */
+    {0 },						/* link[MAXOBJ * 2] */
+    {0 },						/* holder[MAXOBJ] */
+    {0 },						/* hlink[MAXOBJ] */
+    {0 },						/* visited[MAXLOC] */
+    {0 },						/* prop[MAXOBJ] */
+    {							/* obj_state[MAXOBJ] */
+	    0,     0, 32800,    26, 32770,		/*   0 -   4 */
+	   32,    32,  8192,     0,     0,		/*   5 -   9 */
+	   32,   512,     0,   256,   770,		/*  10 -  14 */
+	  770,   288,   512,     0,   160,		/*  15 -  19 */
+	32802,     0,     0,     0,   128,		/*  20 -  24 */
+	    0,     0,     0,    32,  8192,		/*  25 -  29 */
+	  512,   512,     0,   512,     0,		/*  30 -  34 */
+	  512,   256,     0, 32768,  8224,		/*  35 -  39 */
+	    0,    18,    26,    26,     2,		/*  40 -  44 */
+	    0,  8320, 18464, 32768,     0,		/*  45 -  49 */
+	16384, 16416, 16416, 26656, 24608,		/*  50 -  54 */
+	49240, 24608, 16384, 49184, 16416,		/*  55 -  59 */
+	16416, 16416, 16384, 16544, 16442,		/*  60 -  64 */
+	16416, 18464, 26656, 16416, 16416,		/*  65 -  69 */
+	49184, 49154, 18464, 18464, 16416,		/*  70 -  74 */
+	16416,     0,     0,     0,     0,		/*  75 -  79 */
+	    0,     0,     0,     0,     0,		/*  80 -  84 */
+	    0,     0,  8704,     0,     0,		/*  85 -  89 */
+	    0,     0,     0,     0, 32768,		/*  90 -  94 */
+	    0,   128,     0,     0,     0,		/*  95 -  99 */
+	    0,   160,  8224,     0,     0,		/* 100 - 104 */
+	    0,  8352,  8352, 32870,     0,		/* 105 - 109 */
+	16674,   258, 32858,   288,    32,		/* 110 - 114 */
+	  256,     0,     0, 32866, 16416,		/* 115 - 119 */
+	16416,     0,     0				/* 120 - 123 */
+    },							/* obj_state[MAXOBJ] */
+    {							/* points[MAXOBJ] */
+	   0,        0,        0,        0,        0,	/*   0 -   4 */
+	   0,        0,        0,        0,        0,	/*   5 -   9 */
+	   0,        0,        0,        0,        0,	/*  10 -  14 */
+	   0,  1000108,        0,        0,        0,	/*  15 -  19 */
+	   0,        0,        0,        0,        0,	/*  20 -  24 */
+	   0,        0,        0,        0,        0,	/*  25 -  29 */
+	   0,        0,        0,        0,        0,	/*  30 -  34 */
+	   0,        0,        0,        0,        0,	/*  35 -  39 */
+	   0,        0,        0,        0,        0,	/*  40 -  44 */
+	   0,        0, -3000112,        0,        0,	/*  45 -  49 */
+    -2000055, -2000112, -2000112, -1000112, -5000112,	/*  50 -  54 */
+     5000003, -3000112, -2000055,  2000003, -3000112,	/*  55 -  59 */
+    -4000112, -4000112,  3000003, -1000112, -4000112,	/*  60 -  64 */
+    -4000112, -2000112, -3000112, -1000112, -1000112,	/*  65 -  69 */
+    -2000112, -3012055, -4000112, -1000112, -5000112,	/*  70 -  74 */
+    -5000112,        0,        0,        0,        0,	/*  75 -  79 */
+	   0,        0,        0,        0,        0,	/*  80 -  84 */
+	   0,        0,        0,        0,        0,	/*  85 -  89 */
+	   0,        0,        0,        0,        0,	/*  90 -  94 */
+	   0,        0,        0,        0,        0,	/*  95 -  99 */
+	   0,        0,        0,        0,        0,	/* 100 - 104 */
+	   0,        0,        0,        0,        0,	/* 105 - 109 */
+    -2000112,        0,        0,        0,        0,	/* 110 - 114 */
+	   0,        0,        0,        0, -4000118,	/* 115 - 119 */
+    -2000112,        0					/* 120 - 122 */
+    },							/* points[MAXOBJ] */
+    {0 },						/* hinted[HNTMAX+1] */
+    {							/* hints[HNTMAX+1][5] */
+	{    0,    0,   0,   0,   0 },			/*  0 */
+	{    0, 9999,   4,   0,   0 },			/*  1 */
+        {    0, 9999,  10,   0,   0 },			/*  2 */
+        {    0, 9999,   5,   0,   0 },			/*  3 */
+	{    0,    0,   0,   0,   0 },			/*  4 */
+	{    0,    0,   0,   0,   0 },			/*  5 */
+	{    0,    0,   0,   0,   0 },			/*  6 */
+        {    0,   15,   4, 176, 177 },			/*  7 */
+        {    0,    8,   5, 178, 179 },			/*  8 */
+        {    0,   13,   3, 180, 181 },			/*  9 */
+        {    0,    6,  10, 211, 212 },			/* 10 */
+        {    0,    6,   5, 213, 214 },			/* 11 */
+	{    0,    4,   2,  62,  63 },			/* 12 */
+	{    0,    5,   2,  18,  19 },			/* 13 */
+	{    0,    4,   2,  62, 233 },			/* 14 */
+	{    0,    6,   5, 274, 275 },			/* 15 */
+	{    0,   10,   5, 289, 290 },			/* 16 */
+	{    0,    8,   2,  20,  21 },			/* 17 */
+	{    0,    5,   2, 404, 405 }			/* 18 */
+    },							/* hints[HNTMAX+1][5] */
+    {0 },						/* hintlc[HNTMAX+1] */
+    0,							/* tally */
+    0,							/* tally2 */
+    0,							/* limit */
+    0,							/* lmwarn */
+    0,							/* wzdark */
+    0,							/* closing */
+    0,							/* closed */
+    0,							/* holding */
+    0,							/* detail */
+    0,							/* knfloc */
+    30,							/* clock */
+    50,							/* clock2 */
+    0,							/* panic */
+    { 0, 19, 27, 33, 44, 64, 114 },			/* dloc[DWARFMAX+1] */
+    0,							/* dflag */
+    { 0, 0, 0, 0, 0, 0, 0 },				/* dseen[DWARFMAX+1] */
+    { 0, 0, 0, 0, 0, 0, 0 },				/* odloc[DWARFMAX+1] */
+    18,							/* daltloc */
+    0,							/* dkill */
+    114,						/* chloc */
+    140,						/* chloc2 */
+    0,							/* bonus */
+    0,							/* numdie */
+    0,							/* foobar */
+    0,							/* combo */
+    0,							/* terse */
+    5,							/* abbnum */
+    100,						/* health */
+    0,							/* chase */
+    FALSE,						/* flg239 */
+    0							/* lastglob */
+};
+
+/*
+  Initialization of adventure play variables
+*/
+void initialize()
+{
+    int i;
+
+    for (i = MAXOBJ; i > 0; i--) {
+	g.fixed[i] = fixd[i];
+	if (fixd[i] > 0) {
+	    drop(i + MAXOBJ, fixd[i]);
+	    drop(i, plac[i]);
+	}
+	if ((plac[i] != 0) && (fixd[i] <= 0))
+	    drop(i, plac[i]);
+    }
+
+    for (i = 1; i <= MAXOBJ; i++) {
+	if (treasr(i)) {
+	    g.prop[i] = -1;
+	    g.tally++;
+	}
+    }
+
+    newtravel = TRUE;
+    g.place[BOOK] = -1;
+    insert(BOOK, SAFE);
+    g.place[WATER] = -1;
+    insert(WATER, BOTTLE);
+    g.prop[BOTTLE] = 8;
+    return;
+}
Index: /trunk/minix/commands/advent/itverb.c
===================================================================
--- /trunk/minix/commands/advent/itverb.c	(revision 9)
+++ /trunk/minix/commands/advent/itverb.c	(revision 9)
@@ -0,0 +1,597 @@
+/*	program ITVERB.C					*/
+
+
+#include	<stdio.h>
+#include	"advent.h"
+#include	"advdec.h"
+
+_PROTOTYPE(void needobj, (void));
+_PROTOTYPE(void ivtake, (void));
+_PROTOTYPE(void ivopen, (void));
+_PROTOTYPE(void ivkill, (void));
+_PROTOTYPE(void ivdrink, (void));
+_PROTOTYPE(void ivquit, (void));
+_PROTOTYPE(void ivfoo, (void));
+_PROTOTYPE(void inventory, (void));
+_PROTOTYPE(void addobj, (int obj));
+_PROTOTYPE(void ivpour, (void));
+_PROTOTYPE(void ivfill, (void));
+_PROTOTYPE(void ivbrief, (void));
+_PROTOTYPE(void ivread, (void));
+_PROTOTYPE(void ivcombo, (void));
+_PROTOTYPE(void iveat, (void));
+/*
+  Routines to process intransitive verbs
+*/
+void itverb()
+{
+    int i;
+
+    newtravel = FALSE;
+    switch (verb) {
+    case DROP:
+    case SAY:
+    case WAVE:
+    case CALM:
+    case RUB:
+    case THROW:
+    case FIND:
+    case FEED:
+    case BREAK:
+    case WAKE:
+    case WEAR:
+    case HIT:
+    case DIAL:
+    case PLAY:
+    case PICK:
+    case PUT:
+    case TURN:		needobj();	break;
+    case TAKE:
+    case YANK:
+    case GET:
+    case INSRT:
+    case REMOVE:
+    case BURN:		ivtake();	break;
+    case OPEN:
+    case CLOSE:
+    case LOCK:
+    case UNLOCK:	ivopen();	break;
+    case NOTHING:	rspeak(54);	break;
+    case ON:
+    case OFF:		trverb();	break;
+    case WALK:		actspk(verb);	break;
+    case KILL:		ivkill();	break;
+    case POUR:		ivpour();	break;
+    case EAT:		iveat();	break;
+    case DRINK:		ivdrink();	break;
+    case QUIT:		ivquit();	break;
+    case INVENTORY:	inventory();	break;
+    case FILL:		ivfill();	break;
+    case BLAST:		ivblast();	break;
+    case SCORE:		score(TRUE);	break;
+    case FOO:		ivfoo();	break;
+    case BRIEF:		ivbrief();	break;
+    case READ:		ivread();	break;
+    case SUSPEND:
+	if (g.closing)
+	    rspeak(378);
+	else
+	    saveadv("advent.sav");
+	break;
+    case RESTORE:	restore("advent.sav");	break;
+    case ANSWER:
+	if ((g.loc != 189) || (g.prop[PHONE] != 0))
+	    needobj();
+	else {
+	    object = PHONE;
+	    itverb();
+	}
+	break;
+    case BLOW:		rspeak(268);	break;
+	/* Action verb 'LEAVE' has no object */
+    case LEAVE:		bug(29);	break;
+	/* Call if no phone is handy, yell. */
+    case YELL:
+	if (!here(PHONE))
+	    needobj();
+	else if (!g.closed)
+	    rspeak(271);
+	else {
+	    rspeak(283);
+	    normend();
+	}
+	break;
+	/* Health. give him a diagnosis. */
+    case HEALTH:
+	if (g.numdie)
+	    fprintf(stdout, "You have been killed %d times otherwise\n",
+		    g.numdie);
+	if (g.health >= 95) {
+	    if (pct(50))
+		rspeak(348);
+	    else
+		rspeak(349);
+	} else {
+	    fprintf(stdout,
+	       "Your health rating is %2d out of a possible 100.\n",
+		    g.health);
+	    rspeak(381 + (100 - g.health) / 20);
+	}
+	break;
+    case LOOK:		ivlook();	break;
+    case COMBO:
+	if (at(SAFE))
+	    ivcombo();
+	break;
+    case SWEEP:
+	/* Dust/sweep */
+	if (!at(CARVNG) || !athand(BRUSH) || (g.prop[CARVNG] == 1))
+	    rspeak(342);
+	else {
+	    g.prop[CARVNG] = 1;
+	    rspeak(363);
+	    rspeak(372);
+	}
+	break;
+    case TERSE:
+	/* Terse/unterse. supress all long_form descriptions. */
+	g.terse = !g.terse;
+	g.detail = 3;
+	rspeak(54);
+	break;
+    case WIZ:
+	is_wiz = !is_wiz;
+    case MAP:
+	rspeak(54);
+	break;
+    case GATE:
+	if (is_wiz) {
+	    static char buf[INPUTBUFLEN];
+	    sscanf(ask("Location ? ", buf, sizeof(buf)), "%d", &g.loc);
+	}
+	rspeak(54);
+	break;
+    case PIRLOC:
+	if (is_wiz) {
+	    fprintf(stdout, "The dwarfs are at locations:\n");
+	    for (i = 1; i < DWARFMAX; i++)
+		fprintf(stdout, "  %4d", g.dloc[i]);
+	    fprintf(stdout, "\nThe pirate is at location %4d\n",
+		    g.dloc[DWARFMAX]);
+	}
+	rspeak(54);
+	break;
+    default:
+	printf("This intransitive not implemented yet\n");
+    }
+    return;
+}
+
+/*
+  Routine to indicate no reasonable
+  object for verb found.  Used mostly by
+  intransitive verbs.
+*/
+void needobj()
+{
+    printf("%s what?\n", vtxt[vrbx]);
+    return;
+}
+
+/*
+  CARRY, TAKE etc.
+*/
+void ivtake()
+{
+    int anobj, item;
+
+    anobj = 0;
+    for (item = 1; item < MAXOBJ; ++item)
+	if (g.place[item] == g.loc)
+	    if (anobj == 0)
+		anobj = item;
+	    else {
+		needobj();
+		return;
+	    }
+
+    if (anobj == 0 || (dcheck() && g.dflag >= 2) || blind())
+	needobj();
+    else {
+	object = anobj;
+	if (verb == YANK)
+	    vyank();
+	else if (verb == WEAR)
+	    vwear();
+	else
+	    vtake();
+    }
+    return;
+}
+
+/*
+  OPEN, LOCK, UNLOCK
+*/
+void ivopen()
+{
+    int obj_cnt, item;
+
+    for (item = 1, obj_cnt = 0; item < MAXOBJ; item++) {
+	if ((g.place[item] == g.loc) && (hinged(item))) {
+	    object = item;
+	    obj_cnt++;
+	}
+    }
+    if (obj_cnt != 1)
+	needobj();
+    else if (verb == LOCK)
+	vlock();
+    else if (verb == UNLOCK)
+	vunlock();
+    else if (verb == SHUT)
+	vclose();
+    else
+	vopen();
+}
+
+/*
+  ATTACK, KILL etc
+*/
+boolean previous_obj;
+
+void ivkill()
+{
+    previous_obj = FALSE;
+    if (dcheck() && g.dflag >= 2)
+	object = DWARF;
+    if (here(SNAKE))
+	addobj(SNAKE);
+    if (at(DRAGON) && g.prop[DRAGON] == 0)
+	addobj(DRAGON);
+    if (at(TROLL))
+	addobj(TROLL);
+    if (here(GNOME))
+	addobj(GNOME);
+    if (here(BEAR) && g.prop[BEAR] == 0)
+	addobj(BEAR);
+    if (here(WUMPUS) && g.prop[WUMPUS] == 0)
+	addobj(WUMPUS);
+    /* Can't attack bird by throwing axe */
+    if (here(BIRD) && verb != THROW)
+	addobj(BIRD);
+    /* Clam and oyster both treated as clam for intransitive case; no
+       harm done. */
+    if (here(CLAM) || here(OYSTER))
+	addobj(CLAM);
+
+    if ((previous_obj) || (object == 0))
+	rspeak(44);
+    else
+	vkill();
+    return;
+}
+
+/*
+  POUR if no object, assume liq in container, if holding one.
+*/
+void ivpour()
+{
+    if ((holding(BOTTLE)) && (liq(BOTTLE) != 0) && !holding(CASK))
+	object = BOTTLE;
+    if ((holding(CASK)) && (liq(CASK) != 0) && !holding(BOTTLE))
+	object = CASK;
+
+    if (object == 0)
+	needobj();
+    else
+	trverb();
+}
+
+/*
+  EAT. intransitive: assume edible if present, else ask what.
+  If he as more than one edible, or none, 'EAT' is ambiguous
+  without an explicit object.
+*/
+void iveat()
+{
+    int i;
+
+    previous_obj = FALSE;
+    for (i = 1; i < MAXOBJ; i++) {
+	if ((here(i)) && (edible(i)))
+	    addobj(i);
+    }
+    if ((previous_obj) || (object == 0))
+	needobj();
+    else
+	trverb();
+}
+
+/*
+  DRINK.  If no object, assume water or wine and look for them here.
+  If potable is in bottle or cask, drink that.  If not, see if there
+  is something drinkable nearby (stream, lake, wine fountain, etc.),
+  and drink that.  If he has stuff in both containers, ask which.
+*/
+void ivdrink()
+{
+    int ll;
+
+    previous_obj = FALSE;
+    ll = liqloc(g.loc);
+    if ((ll == WATER) || (ll == WINE)) {
+	object = ll;
+	iobj = -1;
+    }
+    ll = liq(BOTTLE);
+    if ((athand(BOTTLE)) && ((ll == WATER) || (ll == WINE))) {
+	object = ll;
+	iobj = BOTTLE;
+    }
+    ll = liq(CASK);
+    if ((athand(CASK)) && ((ll == WATER) || (ll == WINE))
+	&& iobj != BOTTLE) {
+	object = ll;
+	iobj = CASK;
+    } else
+	object = 0;
+
+    if (object == 0)
+	needobj();
+    else
+	trverb();
+}
+
+/*
+  QUIT intransitive only. Verify intent and exit if that's what he wants
+*/
+void ivquit()
+{
+    gaveup = yes(22, 54, 54);
+    if (gaveup)
+	normend();
+    return;
+}
+
+/*
+  INVENTORY
+*/
+void inventory()
+{
+    int i, msg;
+    boolean init_msg;
+
+    init_msg = TRUE;
+    msg = 98;
+    for (i = 1; i < MAXOBJ; i++) {
+	if (!holding(i) || wearng(i) || i == BEAR || i == BOAT)
+	    continue;
+	if (init_msg)
+	    rspeak(99);
+	pspeak(i, -1);
+	init_msg = FALSE;
+	msg = 0;
+	lookin(i);
+    }
+
+    /* Tell him what he is wearing */
+    init_msg = TRUE;
+    for (i = 1; i < MAXOBJ; i++) {
+	if (wearng(i)) {
+	    if (init_msg)
+		fprintf(stdout, "\nYou are wearing:\n");
+	    fprintf(stdout, "     ");
+	    pspeak(i, -1);
+	    msg = 0;
+	    init_msg = FALSE;
+	}
+    }
+
+    if (holding(BOAT)) {
+	rspeak(221);
+	lookin(BOAT);
+    }
+    if (holding(BEAR))
+	msg = 141;
+
+    if (msg)
+	rspeak(msg);
+    return;
+}
+
+/*
+  FILL bottle or cask must be empty, and some liquid avaible
+*/
+void ivfill()
+{
+    if ((g.prop[CASK] == 1) && !here(CASK))
+	object = CASK;
+    if ((g.prop[BOTTLE] == 1) && !here(BOTTLE))
+	object = BOTTLE;
+
+    if ((here(BOTTLE) && here(CASK)) || (object == 0))
+	needobj();
+    else
+	trverb();
+}
+
+/*
+  BLAST etc.
+*/
+void ivblast()
+{
+    if (!g.closed)
+	actspk(verb);
+    else {
+	g.bonus = 135;
+	if (g.place[ROD2] == 212 && g.loc == 116)
+	    g.bonus = 133;
+	if (g.place[ROD2] == 116 && g.loc != 116)
+	    g.bonus = 134;
+	rspeak(g.bonus);
+	normend();
+    }
+    return;
+}
+
+/*
+  Handle fee fie foe foo...
+*/
+void ivfoo()
+{
+    int k;
+    int msg;
+
+    k = VAL(vocab(vtxt[vrbx], MISC));
+    if (g.foobar != 1 - k) {
+	if (g.foobar == 0)
+	    msg = 42;
+	else
+	    msg = 151;
+	rspeak(msg);
+	return;
+    }
+    g.foobar = k;
+    if (k != 4)
+	return;
+    g.foobar = 0;
+    if (g.place[EGGS] == plac[EGGS] ||
+	(toting(EGGS) && g.loc == plac[EGGS])) {
+	rspeak(42);
+	return;
+    }
+    /* Bring back troll if we steal the eggs back from him before
+       crossing */
+    if (g.place[EGGS] == 0 && g.place[TROLL] == 0 && g.prop[TROLL] == 0)
+	g.prop[TROLL] = 1;
+
+    if (here(EGGS))
+	k = 1;
+    else if (g.loc == plac[EGGS])
+	k = 0;
+    else
+	k = 2;
+    move(EGGS, plac[EGGS]);
+    pspeak(EGGS, k);
+    return;
+}
+
+/*
+  brief/unbrief. intransitive only.
+  suppress long descriptions after first time.
+*/
+void ivbrief()
+{
+    int msg;
+
+    g.detail = 3;
+    g.terse = FALSE;
+    if (g.abbnum != 10000) {
+	msg = 156;
+	g.abbnum = 10000;
+    } else {
+	msg = 374;
+	g.abbnum = 5;
+    }
+    rspeak(msg);
+}
+
+/*
+  read etc...
+*/
+void ivread()
+{
+    previous_obj = FALSE;
+    if (here(BOOK))
+	object = BOOK;
+    if (here(BOOK2))
+	addobj(BOOK2);
+    if (here(BILLBD))
+	addobj(BILLBD);
+    if (here(CARVNG))
+	addobj(CARVNG);
+    if (here(MAGAZINE))
+	addobj(MAGAZINE);
+    if (here(MESSAGE))
+	addobj(MESSAGE);
+    if (here(OYSTER))
+	addobj(OYSTER);
+    if (here(POSTER))
+	addobj(POSTER);
+    if (here(TABLET))
+	addobj(TABLET);
+
+    if (previous_obj || object == 0 || dark())
+	needobj();
+    else
+	vread();
+    return;
+}
+
+/*
+   LOOK. can't give more detail. Pretend it wasn't dark (though it may "now"
+   be dark) so he won't fall into a pit staring into the gloom.
+*/
+void ivlook()
+{
+    if (g.detail++ < 3)
+	rspeak(15);
+    g.wzdark = FALSE;
+    g.visited[g.loc] = 0;
+    g.newloc = g.loc;
+    newtravel = TRUE;
+    return;
+}
+
+/*
+  COMBO: trying to open safe. (see comments for fee fie foe foo)
+*/
+void ivcombo()
+{
+    int k, msg;
+
+    k = VAL(vocab(vtxt[vrbx], MISC)) - 10;
+    msg = 42;
+    if (g.combo != 1 - k) {
+	if (g.combo != 0)
+	    msg = 366;
+	rspeak(msg);
+	return;
+    }
+    g.combo = k;
+    if (k != 3)
+	rspeak(371);
+    else {
+	g.combo = 0;
+	bitoff(SAFE, LOCKBT);
+	biton(SAFE, OPENBT);
+	g.prop[SAFE] = 1;
+	if (g.prop[BOOK] < 0) {
+	    g.tally--;
+	    g.prop[BOOK] = 0;
+	    /* If remaining treasures too elusive, zap his lamp. this
+	       duplicates some code, must be done here since book is
+	       contained ins safe & tally stuff only works for thing
+	       deposited at a location. */
+	    if ((g.tally == g.tally2) && (g.tally != 0))
+		g.limit = (g.limit < 35) ? g.limit : 35;
+	}
+	rspeak(365);
+    }
+}
+
+/*
+  ensure uniqueness as objects are searched
+  out for an intransitive verb
+*/
+void addobj(obj)
+int obj;
+{
+    if (!previous_obj) {
+	if (object != 0)
+	    previous_obj = TRUE;
+	else
+	    object = obj;
+    }
+    return;
+}
Index: /trunk/minix/commands/advent/score.c
===================================================================
--- /trunk/minix/commands/advent/score.c	(revision 9)
+++ /trunk/minix/commands/advent/score.c	(revision 9)
@@ -0,0 +1,199 @@
+/**
+    SCORE
+
+   Calculate what the player's score would be if he quit now.
+   This may be the end of the game, or he may just be wondering
+   how he is doing.
+
+   The present scoring algorithm is as follows:
+   (treasure points are explained in a following comment)
+      objective:          points:        present total possible:
+   getting well into cave   25                    25
+   total possible for treasures (+mag)           426
+   reaching "closing"       20                    20
+   "closed": quit/killed    10
+             klutzed        20
+             wrong way      25
+             success        30                    30
+				total:   501
+   (points can also be deducted for using hints or deaths.)
+
+*/
+
+#include 	<stdio.h>
+#include	"advent.h"
+#include	"advdec.h"
+
+void score(scorng)
+boolean scorng;
+{
+    int cur_score, max_score, qk[3];
+    int obj, num_treas, k, i;
+    long t;
+    char *kk2c;
+
+    cur_score = 0;
+    max_score = 0;
+    num_treas = 0;
+
+/** First tally up the treasures.  Must be in building and not broken.
+   give the poor guy partial score just for finding each treasure.
+   Gets full score, qk[3], for obj if:
+        obj is at loc qk[1], and
+        obj has prop value of qk[2]
+
+                weight          total possible
+   magazine     1 (absolute)            1
+
+   all the following are multiplied by 5 (range 5-25):
+   book         2
+   cask         3 (with wine only)
+   chain        4 (must enter via styx)
+   chest        5
+   cloak        3
+   clover       1
+   coins        5
+   crown        2
+   crystal-ball 2
+   diamonds     2
+   eggs         3
+   emerald      3
+   grail        2
+   horn         2
+   jewels       1
+   lyre         1
+   nugget       2
+   pearl        4
+   pyramid      4
+   radium	4
+   ring         4
+   rug          3
+   sapphire     1
+   shoes        3
+   spices       1
+   sword        4
+   trident      2
+   vase         2
+   droplet	5
+   tree		5
+        total: 85 * 5 = 425 + 1 ==> 426
+*/
+
+    for (obj = 1; obj < MAXOBJ; obj++) {
+	if (g.points[obj] == 0)
+	    continue;
+	t = g.points[obj];
+ 	qk[0] = (int) (t < 0L ? -((t = -t) % 1000) : (t % 1000));
+ 	t /= 1000;
+	qk[1] = (int) (t % 1000);
+	qk[2] = (int) (t / 1000);
+	k = 0;
+	if (treasr(obj)) {
+	    num_treas++;
+	    k = qk[2] * 2;
+	    if (g.prop[obj] >= 0)
+		cur_score += k;
+	    qk[2] *= 5;
+	}
+	if ((g.place[obj] == qk[0]) && (g.prop[obj] == qk[1])
+	    && ((g.place[obj] != -CHEST) || (g.place[CHEST] == 3))
+	  && ((g.place[obj] != -SHIELD) || (g.place[SHIELD] == -SAFE))
+	    )
+	    cur_score += qk[2] - k;
+	max_score += qk[2];
+    }
+
+
+/**
+   Now look at how he finished and how far he got.  Maxdie and numdie tell us
+   how well he survived.  Gaveup says whether he exited via quit.  Dflag will
+   tell us if he ever got suitably deep into the cave.  Closing still indicates
+   whether he reached the endgame.  And if he got as far as "cave closed"
+   (indicated by "closed"), then bonus is zero for mundane exits or 133, 134,
+   135 if he blew it (so to speak).
+*/
+
+    if (g.dflag)
+	cur_score += 25;
+    max_score += 25;
+    if (g.closing)
+	cur_score += 20;
+    max_score += 20;
+    if (g.closed) {
+	if (g.bonus == 0)
+	    cur_score += 10;
+	else if (g.bonus == 135)
+	    cur_score += 20;
+	else if (g.bonus == 134)
+	    cur_score += 25;
+	else if (g.bonus == 133)
+	    cur_score += 30;
+    }
+    max_score += 30;
+
+/*  Deduct points for hints, deaths and quiting.
+    hints < hntmin are special; see database description
+*/
+    for (i = 1; i <= HNTMAX; i++)
+	if (g.hinted[i])
+	    cur_score -= g.hints[i][2];
+    cur_score -= g.numdie * 10;
+    if (gaveup)
+	cur_score -= 4;
+
+    fprintf(stdout, "You have found   %3d out of %3d Treasures,",
+	    num_treas - g.tally, num_treas);
+    fprintf(stdout, " using %4d turns\n", g.turns);
+    fprintf(stdout, "For a score of: %4d", cur_score);
+    fprintf(stdout, " out of a possible %4d\n", max_score);
+
+    if (cur_score < 110) {
+	fprintf(stdout, "You are obviously a rank amateur.");
+	if (!scorng)
+	    fprintf(stdout, "  Better luck next time.");
+	fputc('\n', stdout);
+	k = 110 - cur_score;
+    } else if (cur_score < 152) {
+	fprintf(stdout,
+	  "Your score qualifies you as a Novice Class Adventurer.\n");
+	k = 152 - cur_score;
+    } else if (cur_score < 200) {
+	fprintf(stdout,
+	"You have achieved the rating: \"Experienced Adventurer\".\n");
+	k = 200 - cur_score;
+    } else if (cur_score < 277) {
+	fprintf(stdout,
+	"You may now consider yourself a \"Seasoned Adventurer\".\n");
+	k = 277 - cur_score;
+    } else if (cur_score < 345) {
+	fprintf(stdout,
+		"You have reached \"Junior Master\" status.\n");
+	k = 345 - cur_score;
+    } else if (cur_score < 451) {
+	fprintf(stdout,
+		"Your score puts you in Master Adventurer Class C.\n");
+	k = 451 - cur_score;
+    } else if (cur_score < 471) {
+	fprintf(stdout,
+		"Your score puts you in Master Adventurer Class B.\n");
+	k = 471 - cur_score;
+    } else if (cur_score < 501) {
+	fprintf(stdout,
+		"Your score puts you in Master Adventurer Class A.\n");
+	k = 501 - cur_score;
+    } else {
+	fprintf(stdout,
+		"All of Adventuredom gives tribute to you, Adventurer Grandmaster!\n");
+	k = 0;
+    }
+
+    if (!scorng) {
+	kk2c = (k == 1) ? "." : "s.";
+	printf("\nTo acheive the next higher rating,");
+	if (cur_score == 501)
+	    printf(" would be a neat trick!\n\n  CONGRATULATIONS!!\n");
+	else
+	    printf(" you need %3d more point%s\n", k, kk2c);
+    }
+    return;
+}
Index: /trunk/minix/commands/advent/setup.c
===================================================================
--- /trunk/minix/commands/advent/setup.c	(revision 9)
+++ /trunk/minix/commands/advent/setup.c	(revision 9)
@@ -0,0 +1,99 @@
+/**	program SETUP.C  					*
+ *	execution will read the four adventure text files	*
+ *	files; "advent1.txt", "advent2.txt", "advent3.txt" &	*
+ *	"advent4.txt".  it will create the file "advtext.h"	*
+ *	which is an Index Sequential Access Method (ISAM)	*
+ *	header to be #included into "advent.c" before the	*
+ *	header "advdec.h" is #included.				*/
+
+
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	"advent.h"
+
+_PROTOTYPE(int main, (void));
+_PROTOTYPE(void file_error, (char *));
+_PROTOTYPE(void encode, (unsigned char *));
+
+int main()
+{
+
+    FILE *isam, *src, *dest;
+    char itxt[255];
+    int cnt, i;
+    long llen;
+    char filename[12];
+    static char *headername[] = {
+       "idx1[MAXLOC]", "idx2[MAXLOC]", "idx3[MAXOBJ]", "idx4[MAXMSG]",
+    };
+
+    long x29 = (1L << 29), x30 = (1L << 30);
+    if (!(x30 / 2 == x29 && 0L < x30 && x29 < x30)) {
+	fprintf(stderr, "Sorry, advent needs 32-bit `long int's.\n");
+	exit(EXIT_FAILURE);
+    }
+    isam = fopen("advtext.h", "w");
+    if (!isam) {
+	fprintf(stderr, "Sorry, I can't open advtext.h...\n");
+	exit(EXIT_FAILURE);
+    }
+    fprintf(isam, "\n/*\theader: ADVTEXT.H\t\t\t\t\t*/\n\n\n");
+
+    for (i = 1; i <= 4; i++) {
+	cnt = -1;
+	llen = 0L;
+	sprintf(filename, "advent%d.txt", i);
+	src = fopen(filename, "r");
+	if (!src)
+	    file_error(filename);
+	sprintf(filename, "advent%d.dat", i);
+	dest = fopen(filename, "w");
+	if (!dest)
+	    file_error(filename);
+	fprintf(isam, "long\t%s = {\n\t", headername[i - 1]);
+	while (fgets(itxt, 255, src)) {
+	    encode((unsigned char *) itxt);
+	    if (fprintf(dest, "%s\n", itxt) == EOF)
+		file_error(filename);
+	    if (itxt[0] == '#') {
+		if (llen)
+		    fprintf(isam, "%ld,%s\t", llen,
+			    &"\0\0\0\0\0\0\0\n"[++cnt & 7]);
+		llen = ftell(dest);
+		if (llen <= 0) {
+		    fprintf(stderr, "ftell err in %s\n", filename);
+		    exit(EXIT_FAILURE);
+		}			/* if (!llen)	 */
+	    }				/* if (itxt[0])	 */
+	}				/* while fgets	 */
+	if (fprintf(isam, "%ld\n\t};\n\n", llen) == EOF)
+	    file_error("advtext.h");
+	fclose(src);
+	if (fclose(dest) == EOF)
+	    file_error(filename);
+    }
+
+    if (fclose(isam) == EOF)
+	file_error("advtext.h");
+    return EXIT_SUCCESS;
+}					/* main		 */
+
+void file_error(filename)
+char *filename;
+{
+    perror(filename);
+    exit(EXIT_FAILURE);
+}
+
+_CONST unsigned char key[4] = {'c' | 0x80, 'L' | 0x80, 'y' | 0x80, 'D' | 0x80};
+
+void encode(msg)
+unsigned char *msg;
+{
+    register int i;
+
+    for (i = 1; msg[i]; i++)
+	msg[i] ^= key[i & 3];
+    msg[--i] = '\0';
+    return;
+}
Index: /trunk/minix/commands/advent/travel.c
===================================================================
--- /trunk/minix/commands/advent/travel.c	(revision 9)
+++ /trunk/minix/commands/advent/travel.c	(revision 9)
@@ -0,0 +1,336 @@
+/*	module TRAVEL.C						*
+ *      Routine to handle motion requests			*/
+
+
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	"advent.h"
+#include	"advdec.h"
+#include	"advcave.h"
+
+struct trav travel[MAXTRAV];
+static int kalflg;
+static int bcrossing = 0;
+static int phuce[2][4] = {158, 160, 167, 166,
+			  160, 158, 166, 167};
+
+_PROTOTYPE(static void goback, (void));
+_PROTOTYPE(static void ck_kal, (void));
+_PROTOTYPE(static void dotrav, (void));
+_PROTOTYPE(static void badmove, (void));
+_PROTOTYPE(static void spcmove, (int rdest));
+
+void domove()
+{
+    gettrav(g.loc, travel);
+    switch (motion) {
+    case NULLX:
+	break;
+    case BACK:
+	goback();
+	break;
+    case CAVE:
+	if (outside(g.loc))
+	    rspeak(57);
+	else
+	    rspeak(58);
+	break;
+    default:
+	g.oldloc2 = g.oldloc;
+	g.oldloc = g.loc;
+	dotrav();
+    }
+    newtravel = TRUE;
+    return;
+}
+
+/*
+  Routine to handle request to return
+  from whence we came!
+*/
+static void goback()
+{
+    int kk, k2, want, temp;
+    struct trav strav[MAXTRAV];
+
+    want = forced(g.oldloc) ? g.oldloc2 : g.oldloc;
+    g.oldloc2 = g.oldloc;
+    g.oldloc = g.loc;
+    k2 = 0;
+    if (want == g.loc) {
+	rspeak(91);
+	ck_kal();
+	return;
+    }
+    for (kk = 0; travel[kk].tdest != -1; ++kk) {
+	if (!travel[kk].tcond && travel[kk].tdest == want) {
+	    motion = travel[kk].tverb;
+	    dotrav();
+	    return;
+	}
+	if (!travel[kk].tcond) {
+	    temp = travel[kk].tdest;
+	    gettrav(temp, strav);
+	    if (forced(temp) && strav[0].tdest == want)
+		k2 = temp;
+	}
+    }
+    if (k2) {
+	motion = travel[k2].tverb;
+	dotrav();
+    } else
+	rspeak(140);
+    ck_kal();
+    return;
+}
+
+static void ck_kal()
+{
+    if (g.newloc >= 242 && g.newloc <= 247) {
+	if (g.newloc == 242)
+	    kalflg = 0;
+	else if (g.newloc == (g.oldloc + 1))
+	    kalflg++;
+	else
+	    kalflg = -10;
+    }
+}
+
+/*
+  Routine to figure out a new location
+  given current location and a motion.
+*/
+static void dotrav()
+{
+    unsigned char mvflag, hitflag, kk;
+    int rdest, rverb, rcond, robject;
+    int pctt;
+
+    g.newloc = g.loc;
+    mvflag = hitflag = 0;
+    pctt = ranz(100);
+
+    for (kk = 0; travel[kk].tdest >= 0 && !mvflag; ++kk) {
+	rdest = travel[kk].tdest;
+	rverb = travel[kk].tverb;
+	rcond = travel[kk].tcond;
+	robject = rcond % 100;
+
+	if ((rverb != 1) && (rverb != motion) && !hitflag)
+	    continue;
+	++hitflag;
+	switch (rcond / 100) {
+	case 0:
+	    if ((rcond == 0) || (pctt < rcond))
+		++mvflag;
+	    break;
+	case 1:
+	    if (robject == 0)
+		++mvflag;
+	    else if (toting(robject))
+		++mvflag;
+	    break;
+	case 2:
+	    if (toting(robject) || at(robject))
+		++mvflag;
+	    break;
+	case 3:
+	case 4:
+	case 5:
+	case 7:
+	    if (g.prop[robject] != (rcond / 100) - 3)
+		++mvflag;
+	    break;
+	default:
+	    bug(37);
+	}
+    }
+    if (!mvflag)
+	badmove();
+    else if (rdest > 500)
+	rspeak(rdest - 500);
+    else if (rdest > 300)
+	spcmove(rdest);
+    else {
+	g.newloc = rdest;
+	ck_kal();
+    }
+    newtravel = TRUE;
+    return;
+}
+
+/*
+  The player tried a poor move option.
+*/
+static void badmove()
+{
+    int msg;
+
+    msg = 12;
+    if (motion >= 43 && motion <= 50)
+	msg = 9;
+    if (motion == 29 || motion == 30)
+	msg = 9;
+    if (motion == 7 || motion == 36 || motion == 37)
+	msg = 10;
+    if (motion == 11 || motion == 19)
+	msg = 11;
+    if (motion == 62 || motion == 65 || motion == 82)
+	msg = 42;
+    if (motion == 17)
+	msg = 80;
+    rspeak(msg);
+    return;
+}
+
+/*
+  Routine to handle very special movement.
+*/
+static void spcmove(rdest)
+int rdest;
+{
+    int load, obj, k;
+
+    switch (rdest - 300) {
+    case 1:				/* plover movement via alcove */
+	load = burden(0);
+	if (!load || (load == burden(EMERALD) && holding(EMERALD)))
+	    g.newloc = (99 + 100) - g.loc;
+	else
+	    rspeak(117);
+	break;
+    case 2:				/* trying to remove plover, bad
+					   route */
+	if (enclosed(EMERALD))
+	    extract(EMERALD);
+	drop(EMERALD, g.loc);
+	g.newloc = 33;
+	break;
+    case 3:				/* troll bridge */
+	if (g.prop[TROLL] == 1) {
+	    pspeak(TROLL, 1);
+	    g.prop[TROLL] = 0;
+	    move(TROLL2, 0);
+	    move((TROLL2 + MAXOBJ), 0);
+	    move(TROLL, plac[TROLL]);
+	    move((TROLL + MAXOBJ), fixd[TROLL]);
+	    juggle(CHASM);
+	    g.newloc = g.loc;
+	} else {
+	    g.newloc = plac[TROLL] + fixd[TROLL] - g.loc;
+	    if (g.prop[TROLL] == 0)
+		g.prop[TROLL] = 1;
+	    if (toting(BEAR)) {
+		rspeak(162);
+		g.prop[CHASM] = 1;
+		g.prop[TROLL] = 2;
+		drop(BEAR, g.newloc);
+		g.fixed[BEAR] = -1;
+		g.prop[BEAR] = 3;
+		if (g.prop[SPICES] < 0)
+		    ++g.tally2;
+		g.oldloc2 = g.newloc;
+		death();
+	    }
+	}
+	break;
+    case 4:
+	/* Growing or shrinking in area of tiny door.  Each time he
+	   does this, everything must be moved to the new loc.
+	   Presumably, all his possesions are shrunk or streched along
+	   with him. Phuce[2][4] is an array containg four pairs of
+	   "here" (K) and "there" (KK) locations. */
+	k = phuce[0][g.loc - 161];
+	g.newloc = phuce[1][g.loc - 161];
+	for (obj = 1; obj < MAXOBJ; obj++) {
+	    if (obj == BOAT)
+		continue;
+	    if (g.place[obj] == k && (g.fixed[obj] == 0 || g.fixed[obj] == -1))
+		move(obj, g.newloc);
+	}
+	break;
+    case 5:
+	/* Phone booth in rotunda. Trying to shove past gnome, to get
+	   into phone booth. */
+	if ((g.prop[BOOTH] == 0 && pct(35)) || g.visited[g.loc] == 1) {
+	    rspeak(263);
+	    g.prop[BOOTH] = 1;
+	    move(GNOME, 188);
+	} else {
+	    if (g.prop[BOOTH] == 1)
+		rspeak(253);
+	    else
+		g.newloc = 189;
+	}
+	break;
+    case 6:
+	/* Collapsing clay bridge.  He can cross with three (or fewer)
+	   thing.  If more, of if carrying obviously heavy things, he
+	   may end up in the drink. */
+	g.newloc = g.loc == 235 ? 190 : 235;
+	bcrossing++;
+	load = burden(0);
+	if (load > 4) {
+	    k = (load + bcrossing) * 6 - 10;
+	    if (!pct(k))
+		rspeak(318);
+	    else {
+		rspeak(319);
+		g.newloc = 236;
+		if (holding(LAMP))
+		    move(LAMP, 236);
+		if (toting(AXE) && enclosed(AXE))
+		    extract(AXE);
+		if (holding(AXE))
+		    move(AXE, 208);
+		for (obj = 1; obj < MAXOBJ; obj++)
+		    if (toting(obj))
+			destroy(obj);
+		g.prop[CHASM2] = 1;
+	    }
+	}
+	break;
+    case 7:
+	/* Kaleidoscope code is here. */
+	if (kalflg == 5) {
+	    g.newloc = 248;
+	    g.oldloc = 247;
+	} else {
+	    g.newloc = 242 + ranz(5);
+	    g.oldloc = g.newloc - 1;
+	    kalflg = g.newloc == 242 ? 0 : -10;
+	}
+	break;
+    default:
+	bug(38);
+    }
+    return;
+}
+
+/*
+  Routine to fill travel array for a given location
+*/
+void gettrav(loc, travel)
+int loc;
+struct trav *travel;
+{
+    int i;
+    long t, *lptr;
+
+    lptr = cave[loc - 1];
+    for (i = 0; i < MAXTRAV; i++) {
+	t = *lptr++;
+	if (!(t)) {
+	    travel->tdest = -1;		/* end of array	 */
+	    return;			/* terminate for loop	 */
+	}
+	travel->tverb = (int) (t % 1000);
+	t /= 1000;
+	travel->tdest = (int) (t % 1000);
+	t /= 1000;
+	travel->tcond = (int) (t % 1000);
+	travel++;
+    }
+    bug(25);
+    return;
+}
Index: /trunk/minix/commands/advent/turn.c
===================================================================
--- /trunk/minix/commands/advent/turn.c	(revision 9)
+++ /trunk/minix/commands/advent/turn.c	(revision 9)
@@ -0,0 +1,729 @@
+/*	program TURN.C						*/
+
+
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	"advent.h"
+#include	"advdec.h"
+
+_PROTOTYPE(void descitem, (void));
+_PROTOTYPE(void domove, (void));
+_PROTOTYPE(void goback, (void));
+_PROTOTYPE(void copytrv, (struct trav *, struct trav *));
+_PROTOTYPE(void dotrav, (void));
+_PROTOTYPE(void badmove, (void));
+_PROTOTYPE(void spcmove, (int));
+_PROTOTYPE(void death, (void));
+_PROTOTYPE(void dwarves, (void));
+_PROTOTYPE(void dopirate, (void));
+_PROTOTYPE(int stimer, (void));
+_PROTOTYPE(void do_hint, (int));
+
+
+/*
+  Routine to take 1 turn
+*/
+void turn()
+{
+    int i, hint;
+    static int waste = 0;
+
+    if (newtravel) {
+	/* If closing, then he can't leave except via the main office. */
+	if (outside(g.newloc) && g.newloc != 0 && g.closing) {
+	    rspeak(130);
+	    g.newloc = g.loc;
+	    if (!g.panic)
+		g.clock2 = 15;
+	    g.panic = TRUE;
+	}
+	/* See if a dwarf has seen him and has come from where he wants
+	   to go. */
+	if (g.newloc != g.loc && !forced(g.loc) && g.loc_attrib[g.loc] & NOPIRAT == 0)
+	    for (i = 1; i < (DWARFMAX - 1); ++i)
+		if (g.odloc[i] == g.newloc && g.dseen[i]) {
+		    g.newloc = g.loc;
+		    rspeak(2);
+		    break;
+		}
+
+	g.loc = g.newloc;
+	dwarves();			/* & special dwarf(pirate who
+					   steals)	 */
+
+	/* Check for death */
+	if (g.loc == 0) {
+	    death();
+	    return;
+	}
+	/* Check for forced move */
+	if (forced(g.loc)) {
+	    desclg(g.loc);
+	    ++g.visited[g.loc];
+	    domove();
+	    return;
+	}
+	/* Check for wandering in dark */
+	if (g.wzdark && dark() && pct(35)) {
+	    rspeak(23);
+	    g.oldloc2 = g.loc;
+	    death();
+	    return;
+	}
+	/* see if he is wasting his batteies out in the open */
+	if (outside(g.loc) && g.prop[LAMP]) {
+	    waste++;
+	    if (waste > 11) {
+		rspeak(324);
+		waste = 0;
+	    }
+	} else
+	    waste = 0;
+
+	/* If wumpus is chasing stooge, see if wumpus gets him */
+	if (g.chase) {
+	    g.chase++;
+	    g.prop[WUMPUS] = g.chase / 2;
+	    move(WUMPUS, g.loc);
+	    if (g.chase >= 10) {
+		if (dark())
+		    rspeak(270);
+		pspeak(WUMPUS, 5);
+		death();
+		return;
+	    }
+	}
+	/* check for radiation poisoning. */
+	g.health += (outside(g.loc)) ? 3 : 1;
+	if (g.health > 100)
+	    g.health = 100;
+	if (here(RADIUM) && (g.place[RADIUM] != -SHIELD || ajar(SHIELD)))
+	    g.health -= 7;
+	if (g.health < 60) {
+	    rspeak(391 + (60 - g.health) / 10);
+	    if (g.health < 0) {
+		death();
+		return;
+	    }
+	}
+	if ((g.oldloc == 188) && (g.loc != 188 && g.loc != 189)
+	    && (g.prop[BOOTH] == 1)) {
+	    move(GNOME, 0);
+	    g.prop[BOOTH] = 0;
+	}
+	/* Describe his situation */
+	describe();
+	if (!blind()) {
+	    ++g.visited[g.loc];
+	    descitem();
+	}
+    }					/* end of newtravel start for
+					   second entry point */
+    /* Check if this location is eligible for any hints.  If been here
+       long enough, branch to help section. Ignore "hints" < HNTMIN
+       (special stuff, see database notes. */
+    for (hint = HNTMIN; hint <= HNTMAX; hint++) {
+	if (g.hinted[hint])
+	    continue;
+	if (g.loc_attrib[g.loc] / 256 != hint - 6)
+	    g.hintlc[hint] = -1;
+	g.hintlc[hint]++;
+	if (g.hintlc[hint] >= g.hints[hint][1])
+	    do_hint(hint);
+    }
+
+    if (g.closed) {
+	if (g.prop[OYSTER] < 0 && toting(OYSTER))
+	    pspeak(OYSTER, 1);
+	for (i = 1; i < MAXOBJ; ++i)
+	    if (toting(i) && g.prop[i] < 0)
+		g.prop[i] = -1 - g.prop[i];
+    }
+    g.wzdark = dark();
+    if (g.knfloc > 0 && g.knfloc != g.loc)
+	g.knfloc = 0;
+    ++g.turns;
+    i = rand();
+
+    if (stimer())			/* as the grains of sand slip
+					   by */
+	return;
+
+    while (!english())			/* retrieve player instructions	 */
+	;
+
+    vrbx = 1;
+    objx = objs[1] ? 1 : 0;
+    iobx = iobjs[1] ? 1 : 0;
+    verb = VAL(verbs[vrbx]);
+    do {
+	object = objx ? objs[objx] : 0;
+	iobj = iobx ? iobjs[iobx] : 0;
+	if (object && (objs[2] || iobjs[2])) {
+	    pspeak(object, -1);
+	    printf("      ");
+	}
+	switch (CLASS(verbs[vrbx])) {
+	case MOTION:
+	    motion = verb;
+	    domove();
+	    break;
+	case NOUN:
+	    bug(22);
+	case ACTION:
+	    if (object || iobj)
+		trverb();
+	    else
+		itverb();
+	    break;
+	case MISC:
+	    rspeak(verb);
+	    if (verb == 51)
+		g.hinted[1] = TRUE;
+	    break;
+	default:
+	    bug(22);
+	}
+	if (objx) {
+	    objx++;
+	    if (objs[objx] == 0)
+		objx = 0;
+	}
+	if ((!objx || !objs[objx]) && iobx) {
+	    iobx++;
+	    if (iobjs[iobx] == 0)
+		iobx = 0;
+	    if (iobx && iobjs[1])
+		objx = 1;
+	}
+    } while (objx || iobx);
+    return;
+}
+
+/*
+  Routine to describe current location
+*/
+void describe()
+{
+    if (toting(BEAR))
+	rspeak(141);
+    if (dark())
+	rspeak(16);
+    else if ((g.terse && verb != LOOK) || g.visited[g.loc] % g.abbnum)
+	descsh(g.loc);
+    else
+	desclg(g.loc);
+    if (g.loc == 33 && pct(25) && !g.closing)
+	rspeak(8);
+    if (g.loc == 147 && !g.visited[g.loc])
+	rspeak(216);
+    return;
+}
+
+/*
+  Routine to describe visible items
+*/
+void descitem()
+{
+    int i, state;
+
+    for (i = 1; i < MAXOBJ; ++i) {
+	if (at(i)) {
+	    if (i == STEPS && toting(NUGGET))
+		continue;
+	    if (g.prop[i] < 0) {
+		if (g.closed)
+		    continue;
+		else {
+		    g.prop[i] = 0;
+		    if (i == RUG || i == CHAIN
+			|| i == SWORD || i == CASK)
+			g.prop[i] = 1;
+		    if (i == CLOAK || i == RING)
+			g.prop[i] = 2;
+		    --g.tally;
+		}
+	    }
+	    if (i == STEPS && g.loc == g.fixed[STEPS])
+		state = 1;
+	    else
+		state = g.prop[i] % 8;
+	    pspeak(i, state);
+	    lookin(i);
+	}
+    }
+    /* If remaining treasures too elusive, zap his lamp */
+    if (g.tally == g.tally2 && g.tally != 0 && g.limit > 35)
+	g.limit = 35;
+    return;
+}
+
+/*
+  Routine to handle player's demise via
+  waking up the dwarves...
+*/
+void dwarfend()
+{
+    rspeak(136);
+    normend();
+    return;
+}
+
+/*
+  normal end of game
+*/
+void normend()
+{
+    score(FALSE);
+    gaveup = TRUE;
+    return;
+}
+
+/*
+  Routine to handle the passing on of one
+  of the player's incarnations...
+*/
+void death()
+{
+    int yea, j;
+
+    if (!g.closing) {
+	if (g.limit < 0) {
+	    rspeak(185);
+	    normend();
+	    return;
+	}
+	yea = yes(81 + g.numdie * 2, 82 + g.numdie * 2, 54);
+	if (++g.numdie >= MAXDIE || !yea)
+	    normend();
+	if (g.chase) {
+	    g.chase = FALSE;
+	    g.prop[WUMPUS] = 0;
+	    move(WUMPUS, 174);
+	}
+	if (toting(LAMP))
+	    g.prop[LAMP] = 0;
+	for (j = 1; j < MAXOBJ; ++j) {
+	    if (toting(j))
+		drop(j, j == LAMP ? 1 : g.oldloc2);
+	    if (wearng(j)) {
+		g.prop[j] = 0;
+		bitoff(j, WEARBT);
+	    }
+	}
+	g.newloc = 3;
+	g.oldloc = g.loc;
+	g.health = 100;
+	return;
+    }
+    /* Closing -- no resurrection... */
+    rspeak(131);
+    ++g.numdie;
+    normend();
+    return;
+}
+
+/*
+  dwarf stuff.
+*/
+void dwarves()
+{
+    int i, j, k, attack, stick, dtotal;
+
+    /* See if dwarves allowed here */
+    if (g.newloc == 0 || forced(g.newloc) || g.loc_attrib[g.newloc] & NOPIRAT)
+	return;
+
+    /* See if dwarves are active. */
+    if (!g.dflag) {
+	if (inside(g.newloc))
+	    ++g.dflag;
+	return;
+    }
+    /* If first close encounter (of 3rd kind) */
+    if (g.dflag == 1) {
+	if (!inside(g.newloc) || pct(85))
+	    return;
+	++g.dflag;
+
+	/* kill 0, 1 or 2 of the dwarfs */
+	for (i = 1; i < 3; ++i)
+	    if (pct(50))
+		g.dloc[(ranz(DWARFMAX - 1)) + 1] = 0;
+
+	/* If any of the survivors is at location, use alternate choise */
+	for (i = 1; i <= DWARFMAX; ++i) {
+	    if (g.dloc[i] == g.newloc)
+		g.dloc[i] = g.daltloc;
+	    g.odloc[i] = g.dloc[i];
+	}
+	rspeak(3);
+	drop(AXE, g.newloc);
+	return;
+    }
+    /* Things are in full swing.  Move each dwarf at random, except if
+       he's seen us then he sticks with us.  Dwarfs never go to
+       locations outside or meet the bear or following him into dead
+       end in maze.  And of couse, dead dwarves don't do much of
+       anything.  */
+
+    dtotal = attack = stick = 0;
+    for (i = 1; i <= DWARFMAX; ++i) {
+	if (g.dloc[i] == 0)
+	    continue;
+	/* Move a dwarf at random.  we don't have a matrix around to do
+	   it as in the original version... */
+	do
+	    j = ranz(106) + 15;
+	/* allowed area */
+	while (j == g.odloc[i] || j == g.dloc[i]
+	       || g.loc_attrib[j] & NOPIRAT);
+
+	if (j == 0)
+	    bug(36);
+	g.odloc[i] = g.dloc[i];
+	g.dloc[i] = j;
+
+	g.dseen[i] = ((g.dseen[i] && inside(g.newloc))
+		      || g.dloc[i] == g.newloc
+		      || g.odloc[i] == g.newloc);
+
+	if (g.dseen[i]) {
+	    g.dloc[i] = g.newloc;
+	    if (i == DWARFMAX)
+		dopirate();
+	    else {
+		++dtotal;
+		if (g.odloc[i] == g.dloc[i]) {
+		    ++attack;
+		    if (g.knfloc >= 0)
+			g.knfloc = g.newloc;
+		    if (ranz(1000) < (45 * (g.dflag - 2)))
+			++stick;
+		}
+	    }
+	}
+    }
+
+    /* Now we know shat's happing, let's tell the poor sucker about it */
+    if (dtotal == 0)
+	return;
+    if (dtotal > 1)
+	printf("There are %d threatening little dwarves in the room with you!\n", dtotal);
+    else
+	rspeak(4);
+    if (attack == 0)
+	return;
+    if (g.dflag == 2)
+	++g.dflag;
+    if (attack > 1) {
+	printf("%d of them throw knives at you!!\n", attack);
+	k = 6;
+    } else {
+	rspeak(5);
+	k = 52;
+    }
+    if (stick <= 1) {
+	rspeak(stick + k);
+	if (stick == 0)
+	    return;
+    } else
+	printf("%d of them get you !!!\n", stick);
+    g.oldloc2 = g.newloc;
+    death();
+    return;
+}
+
+/*
+  pirate stuff
+*/
+void dopirate()
+{
+    int j;
+    boolean k;
+
+    if (g.newloc == g.chloc || g.prop[CHEST] >= 0)
+	return;
+    k = FALSE;
+    /* Pirate won't take pyramid from plover room or dark room  (too
+       easy! ) */
+    for (j = 1; j < MAXOBJ; ++j)
+	if (treasr(j) && !(j == CASK && liq(CASK) == WINE)
+	    && !(j == PYRAMID && (g.newloc == g.place[PYRAMID]
+				  || g.newloc == g.place[EMERALD]))) {
+	    if (toting(j) && athand(j))
+		goto stealit;
+	    if (here(j))
+		k = TRUE;
+	}
+    if (g.tally == g.tally2 + 1 && k == FALSE && g.place[CHEST] == 0 &&
+	athand(LAMP) && g.prop[LAMP] == 1) {
+	rspeak(186);
+	move(CHEST, g.chloc);
+	move(MESSAGE, g.chloc2);
+	g.dloc[DWARFMAX] = g.chloc;
+	g.odloc[DWARFMAX] = g.chloc;
+	g.dseen[DWARFMAX] = 0;
+	return;
+    }
+    if (g.odloc[DWARFMAX] != g.dloc[DWARFMAX] && pct(30))
+	rspeak(127);
+    return;
+
+stealit:
+
+    rspeak(128);
+    /* don't steal chest back from troll! */
+    if (g.place[MESSAGE] == 0)
+	move(CHEST, g.chloc);
+    move(MESSAGE, g.chloc2);
+    for (j = 1; j < MAXOBJ; ++j) {
+	if (!treasr(j) || !athand(j)
+	    || (j == PYRAMID &&
+	     (g.newloc == plac[PYRAMID] || g.newloc == plac[EMERALD]))
+	    || (j == CASK && (liq(CASK) != WINE)))
+	    continue;
+	if (enclosed(j))
+	    extract(j);
+	if (wearng(j)) {
+	    g.prop[j] = 0;
+	    bitoff(j, WEARBT);
+	}
+	insert(j, CHEST);
+    }
+    g.dloc[DWARFMAX] = g.chloc;
+    g.odloc[DWARFMAX] = g.chloc;
+    g.dseen[DWARFMAX] = FALSE;
+    return;
+}
+
+/*
+  special time limit stuff...
+*/
+int stimer()
+{
+    int i, spk;
+    static int clock3;
+
+    g.foobar = g.foobar > 0 ? -g.foobar : 0;
+    g.combo = g.combo > 0 ? -g.combo : 0;
+    if (g.turns > 310 && g.abbnum != 10000 && !g.terse)
+	rspeak(273);
+
+    /* Bump all the right clocks for reconning battery life and closing */
+    if (g.closed) {
+	clock3--;
+	if (clock3 == 0) {
+	    g.prop[PHONE] = 0;
+	    g.prop[BOOTH] = 0;
+	    rspeak(284);
+	} else if (clock3 < -7) {
+	    rspeak(254);
+	    normend();
+	    return (TRUE);
+	}
+    }
+    if (g.tally == 0 && inside(g.loc) && g.loc != Y2)
+	--g.clock;
+    if (g.clock == 0) {
+	/* Start closing the cave */
+	g.prop[GRATE] = 0;
+	biton(GRATE, LOCKBT);
+	bitoff(GRATE, OPENBT);
+	g.prop[FISSURE] = 0;
+	g.prop[TDOOR] = 0;
+	biton(TDOOR, LOCKBT);
+	bitoff(TDOOR, OPENBT);
+	g.prop[TDOOR2] = 0;
+	biton(TDOOR2, LOCKBT);
+	bitoff(TDOOR2, OPENBT);
+	for (i = 1; i <= DWARFMAX; ++i) {
+	    g.dseen[i] = FALSE;
+	    g.dloc[i] = 0;
+	}
+	move(TROLL, 0);
+	move((TROLL + MAXOBJ), 0);
+	move(TROLL2, plac[TROLL]);
+	move((TROLL2 + MAXOBJ), fixd[TROLL]);
+	juggle(CHASM);
+	if (g.prop[BEAR] != 3)
+	    destroy(BEAR);
+	g.prop[CHAIN] = 0;
+	g.fixed[CHAIN] = 0;
+	g.prop[AXE] = 0;
+	g.fixed[AXE] = 0;
+	rspeak(129);
+	g.clock = -1;
+	g.closing = TRUE;
+	return (FALSE);
+    }
+    if (g.clock < 0)
+	--g.clock2;
+    if (g.clock2 == 0) {
+	/* Set up storage room... and close the cave... */
+	g.prop[BOTTLE] = put(BOTTLE, 115, 8);
+	g.holder[BOTTLE] = WATER;
+	g.place[WATER] = -BOTTLE;
+	g.hlink[WATER] = 0;
+	bitoff(BOTTLE, OPENBT);
+	g.prop[PLANT] = put(PLANT, 115, 0);
+	g.prop[OYSTER] = put(OYSTER, 115, 0);
+	g.prop[LAMP] = put(LAMP, 115, 0);
+	g.prop[ROD] = put(ROD, 115, 0);
+	g.prop[DWARF] = put(DWARF, 115, 0);
+	g.loc = 115;
+	g.oldloc = 115;
+	g.newloc = 115;
+	/* Leave the grate with normal (non-negative property). */
+	put(GRATE, 116, 0);
+	biton(GRATE, LOCKBT);
+	bitoff(GRATE, OPENBT);
+	g.prop[SNAKE] = put(SNAKE, 116, 1);
+	g.prop[BIRD] = put(BIRD, 116, 1);
+	g.prop[CAGE] = put(CAGE, 116, 0);
+	g.prop[ROD2] = put(ROD2, 116, 0);
+	g.prop[PILLOW] = put(PILLOW, 116, 0);
+
+	g.prop[BOOTH] = put(BOOTH, 116, -3);
+	g.fixed[BOOTH] = 115;
+	g.prop[PHONE] = put(PHONE, 212, -4);
+
+	g.prop[MIRROR] = put(MIRROR, 115, 0);
+	g.fixed[MIRROR] = 116;
+	g.prop[BOOK2] = put(BOOK2, 115, 0);
+
+	for (i = 1; i < MAXOBJ; ++i) {
+	    if (toting(i) && enclosed(i))
+		extract(i);
+	    if (toting(i))
+		destroy(i);
+	}
+	rspeak(132);
+	g.closed = TRUE;
+	clock3 = 20 + ranz(20);
+	newtravel = TRUE;
+	return (TRUE);
+    }
+    if (g.prop[LAMP] == 1)
+	--g.limit;
+    if (g.limit == 0) {
+	--g.limit;
+	g.prop[LAMP] = 0;
+	if (here(LAMP))
+	    rspeak(184);
+	return (FALSE);
+    }
+    if (g.limit < 0 && outside(g.loc)) {
+	rspeak(185);
+	normend();
+	return (TRUE);
+    }
+    if (g.limit <= 40) {
+	if (g.lmwarn || !here(LAMP))
+	    return (FALSE);
+	g.lmwarn = TRUE;
+	spk = 187;
+	if (g.prop[BATTERIES] == 1)
+	    spk = 323;
+	if (g.place[BATTERIES] == 0)
+	    spk = 183;
+	if (g.prop[VEND] == 1)
+	    spk = 189;
+	rspeak(spk);
+	return (FALSE);
+    }
+    return (FALSE);
+}
+
+/* HINTS
+   come here if he's been long enough at required location(s)
+   for some unused hint,  hint number is in variable "hint".
+   Branch to quick test for additional conditions, then
+   do neet stuff. If conditions are met and we want to offer
+   hint.  Clear hintlc if no action is taken.
+ */
+
+#define MASE 1
+#define DARK 2
+#define WITT 3
+#define H_SWORD 4
+#define SLIDE 5
+#define H_GRATE 6
+#define H_BIRD 7
+#define H_ELFIN 8
+#define RNBOW 9
+#define STYX  10
+#define H_SNAKE 11
+#define CASTLE 12
+
+void do_hint(hint)
+int hint;
+{
+    g.hintlc[hint] = 0;
+    switch (hint + 1 - HNTMIN) {
+    case MASE:
+	if (!at(g.loc) && !at(g.oldloc)
+	    && !at(g.loc) && burden(0) > 1)
+	    break;
+	else
+	    return;
+    case DARK:
+	if (g.prop[EMERALD] != -1 && g.prop[PYRAMID] == -1)
+	    break;
+	else
+	    return;
+    case WITT:
+	break;
+    case H_SWORD:
+	if ((g.prop[SWORD] == 1 || g.prop[SWORD] == 5)
+	    && !toting(CROWN))
+	    break;
+	else
+	    return;
+    case SLIDE:
+	break;
+    case H_GRATE:
+	if (g.prop[GRATE] == 0 && !athand(KEYS))
+	    break;
+	else
+	    return;
+    case H_BIRD:
+	if (here(BIRD) && athand(ROD) && object == BIRD)
+	    break;
+	else
+	    return;
+    case H_ELFIN:
+	if (!g.visited[159])
+	    break;
+	else
+	    return;
+    case RNBOW:
+	if (!toting(SHOES) || g.visited[205])
+	    break;
+	else
+	    return;
+    case STYX:
+	if (!athand(LYRE) && g.prop[DOG] != 1)
+	    break;
+	else
+	    return;
+    case H_SNAKE:
+	if (here(SNAKE) && !here(BIRD))
+	    break;
+	else
+	    return;
+    case CASTLE:
+	break;
+    default:
+	printf("  TRYING TO PRINT HINT # %d\n", hint);
+	bug(27);
+    }
+    if (!yes(g.hints[hint][3], 0, 54))
+	return;
+    printf("\nI am prepared to give you a hint,");
+    printf(" but it will cost you %2d points\n", g.hints[hint][2]);
+    g.hinted[hint] = yes(175, g.hints[hint][4], 54);
+    if (g.hinted[hint] && g.limit > 30)
+	g.limit += 30 * g.hints[hint][2];
+    return;
+}
Index: /trunk/minix/commands/advent/utility.c
===================================================================
--- /trunk/minix/commands/advent/utility.c	(revision 9)
+++ /trunk/minix/commands/advent/utility.c	(revision 9)
@@ -0,0 +1,749 @@
+/*
+  Utility Routines
+  the next logical funtions describe attributes of objects.
+  (ajar, hinged, opaque, printd, treasr, vessel, wearng)
+*/
+
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	<ctype.h>
+#include	<string.h>
+#include	"advent.h"
+#include	"advdec.h"
+
+/*
+  ajar .TRUE. if item is container and is open or unhinged
+*/
+boolean ajar(item)
+int item;
+{
+    return ((bitset(g.obj_state[item], OPENBT))
+	    || (vessel(item) && !hinged(item)));
+}
+
+/*
+  at .TRUE. To tell if player is on either side of a two sided object.
+*/
+boolean at(item)
+int item;
+{
+    if (item < 1 || item > MAXOBJ)
+	return (FALSE);
+    else
+	return (g.place[item] == g.loc || g.fixed[item] == g.loc);
+}
+
+/*
+  athand .TRUE. if item readily reachable
+  it can be lying here, in hand or in open container.
+*/
+boolean athand(item)
+int item;
+{
+    int contnr;
+    boolean aaa;
+
+    contnr = -g.place[item];
+    aaa = enclosed(item) && ajar(contnr);
+
+    return ((g.place[item] == g.loc) || holding(item)
+	    || (aaa && ((g.place[contnr] == g.loc)
+			|| (toting(item) && holding(contnr)))));
+}
+
+/*
+  bitoff turns off (sets to 0) a bit in obj_state word
+*/
+void bitoff(obj, bit)
+int obj, bit;
+{
+    long val;
+
+    val = 1L << bit;
+    g.obj_state[obj] &= ~val;
+}
+
+/*
+  biton turns on (sets to 1) a bit in obj_state word
+*/
+void biton(obj, bit)
+int obj, bit;
+{
+    long val;
+
+    val = 1L << bit;
+    g.obj_state[obj] |= val;
+}
+
+/*
+   bitset .TRUE. if object_state has bit N set
+*/
+boolean bitset(state, bit)
+long state;
+int bit;
+{
+    return (((state >> bit) & 1) == 1);
+}
+
+/*
+  blind .TRUE. if you can't see at this loc, (darkness of glare)
+*/
+boolean blind()
+{
+    return (dark() || (g.loc == 200
+		       && athand(LAMP) && (g.prop[LAMP] == 1)));
+}
+
+/*
+   burden .. returns weight of items being carried
+
+   if obj=0, burden calculates the total weight of the adventurer's burden
+   including everything in all containers (except the boat) that he is
+   carring.
+
+   if object is a container, calculate the weight of everything inside
+   the container (including the container itself). Since donkey FORTRAN
+   isn't recursive, we will only calculate weight of contained containers
+   one level down.  The only serious contained container would be the sack
+   The only thing we'll miss will be filled VS empty bottle or cage.
+
+   If object isn't a container, return its weight.
+*/
+int burden(obj)
+int obj;
+{
+    int i, sum, temp;
+
+    sum = 0;
+    if (obj == 0) {
+	for (i = 1; i < MAXOBJ; i++) {
+	    if (toting(i) && (g.place[i] != -BOAT))
+		sum += g.weight[i];
+	}
+    } else {
+	if (obj != BOAT) {
+	    sum = g.weight[obj];
+	    temp = g.holder[obj];
+	    while (temp != 0) {
+		sum += g.weight[temp];
+		temp = g.hlink[temp];
+	    }
+	}
+    }
+    return (sum);
+}
+
+/*
+  Routine to carry an object
+  start toting an object, removing it from the list of things
+  at its former location.  If object > MAXOBJ ( moving "FIXED"
+  or second loc), then don't change place.
+*/
+void carry(obj, where)
+int obj, where;
+{
+    int temp;
+
+    if (obj < MAXOBJ) {
+	if (g.place[obj] == -1)
+	    return;
+	g.place[obj] = -1;
+    }
+    if (g.atloc[where] == obj)
+	g.atloc[where] = g.link[obj];
+    else {
+	temp = g.atloc[where];
+	while (g.link[temp] != obj) {
+	    temp = g.link[temp];
+	    if (temp == 0)
+		bug(35);
+	}
+	g.link[temp] = g.link[obj];
+    }
+    return;
+}
+
+/*
+  confuz generates some variant of "Don't understand that" message.
+*/
+int confuz()
+{
+    int msg;
+
+    msg = 60;
+    if (pct(50))
+	msg = 61;
+    if (pct(33))
+	msg = 13;
+    if (pct(25))
+	msg = 347;
+    if (pct(20))
+	msg = 195;
+    return (msg);
+}
+
+/*
+  dark .TRUE. if there is no light here
+*/
+boolean dark()
+{
+    return (!(g.loc_attrib[g.loc] & LIGHT) &&
+	    (!g.prop[LAMP] || !athand(LAMP)));
+}
+
+/*
+  Routine to check for presence
+  of dwarves..
+*/
+int dcheck()
+{
+    int i;
+
+    for (i = 1; i < (DWARFMAX); ++i)
+	if (g.dloc[i] == g.loc)
+	    return (i);
+    return (0);
+}
+
+/*
+   dead .TRUE. if object is now dead
+*/
+boolean dead(obj)
+int obj;
+{
+    return (bitset(g.obj_state[obj], 10));
+}
+
+/*
+  drop Place an object at a given loc, prefixing it onto the atloc list.
+*/
+void drop(obj, where)
+int obj, where;
+{
+    if (obj > MAXOBJ)
+	g.fixed[obj - MAXOBJ] = where;
+    else
+	g.place[obj] = where;
+    if (where > 0) {
+	g.link[obj] = g.atloc[where];
+	g.atloc[where] = obj;
+    }
+    return;
+}
+
+/*
+  destroy Permanently eliminate "object" by moving it to
+  a non-existent location.
+*/
+void destroy(obj)
+int obj;
+{
+    move(obj, 0);
+    return;
+}
+
+/*
+   edible .TRUE. if obj can be eaten.
+*/
+boolean edible(obj)
+int obj;
+{
+    return (bitset(g.obj_state[obj], 7));
+}
+
+/*
+  enclosed .TRUE. If object is inside a container.
+*/
+boolean enclosed(item)
+int item;
+{
+    if (item < 1 || item > MAXOBJ)
+	return (FALSE);
+    else
+	return (g.place[item] < -1);
+}
+
+/*
+   extract remove "object" from a container.
+   origionally name "remove" but rename to avoid conflict with stdio.h
+*/
+void extract(obj)
+int obj;
+{
+    int contnr, temp;
+
+    contnr = -g.place[obj];
+    g.place[obj] = -1;
+    if (g.holder[contnr] == obj)
+	g.holder[contnr] = g.hlink[obj];
+    else {
+	temp = g.holder[contnr];
+	while (g.hlink[temp] != obj) {
+	    temp = g.hlink[temp];
+	    if (temp == 0)
+		bug(35);
+	}
+	g.hlink[temp] = g.hlink[obj];
+    }
+    return;
+}
+
+/*
+  forced To tell if a location will causes a forced move.
+  A forced location is one from which he is immediately bounced
+  to another.  Normal use is for death (forced to location zero)
+  and for description of journey from on place to another.
+*/
+int forced(at_loc)
+int at_loc;
+{
+    return ((g.loc_attrib[at_loc] & 10) == 2);
+}
+
+/*
+  here .TRUE. If an item is at location or is being carried.
+*/
+boolean here(item)
+int item;
+{
+    return (g.place[item] == g.loc || toting(item));
+}
+
+/*
+  hinged .TRUE. If object can be opened or shut.
+*/
+boolean hinged(object)
+int object;
+{
+    return (bitset(g.obj_state[object], 1));
+}
+
+/*
+  holding .TRUE. If the object is being carried in hand.
+*/
+boolean holding(item)
+int item;
+{
+    if (item < 1 || item > MAXOBJ)
+	return (FALSE);
+    else
+	return (g.place[item] == -1);
+}
+
+/*
+  insert
+*/
+void insert(obj, contnr)
+int obj, contnr;
+{
+    int temp;
+
+    if (contnr == obj)
+	bug(32);
+    carry(obj, g.loc);
+
+    temp = g.holder[contnr];
+    g.holder[contnr] = obj;
+    g.hlink[obj] = temp;
+    g.place[obj] = -contnr;
+}
+
+/*
+  inside = .TRUE. If location is well within cave
+*/
+boolean inside(loc)
+int loc;
+{
+    return (!outside(loc) && !portal(loc));
+}
+
+/*
+  Juggle an object by picking it up and putting it down again,
+  The purpose being to get the object to the front of the chain
+  at its loc.
+*/
+void juggle(obj)
+int obj;
+{
+    int i, j;
+
+    i = g.place[obj];
+    j = g.fixed[obj];
+    move(obj, i);
+    move(obj + MAXOBJ, j);
+    return;
+}
+
+/*
+  Determine liquid in the vessel
+*/
+int liq(item)
+int item;
+{
+    int liquid;
+
+    if ((item == BOTTLE) || (item == CASK))
+	liquid = liq2(((int) g.prop[item] >> 1) & 7);
+    else
+	liquid = 0;
+
+    return (liquid);
+}
+
+/*
+  Determine type of liquid in vessel
+*/
+int liq2(liquid)
+int liquid;
+{
+    switch (liquid) {
+    case 4:
+	return (WATER);
+    case 5:
+	return (OIL);
+    case 6:
+	return (WINE);
+    default:
+	return (0);			/* empty */
+    }
+}
+
+/*
+  Determine liquid at a location
+*/
+int liqloc(loc)
+int loc;
+{
+    return (liq2((int) ((g.loc_attrib[loc] >> 1) & 7)));
+}
+
+/*
+   living .TRUE. If object is living, bear for example
+*/
+boolean living(obj)
+int obj;
+{
+    return (bitset(g.obj_state[obj], 9));
+}
+
+/*
+   locked .TRUE. if lockable object is locked
+*/
+boolean locked(item)
+int item;
+{
+    return (bitset(g.obj_state[item], 4));
+}
+
+/*
+   locks .TRUE. if you can lock this object
+*/
+boolean locks(item)
+int item;
+{
+    return (bitset(g.obj_state[item], 3));
+}
+
+/*
+  LOOKIN list contents if obj is a container and is open or transparent.
+*/
+void lookin(contnr)
+int contnr;
+{
+    int temp;
+    boolean first_time;
+
+    if (vessel(contnr) && (ajar(contnr) || !opaque(contnr))) {
+	temp = g.holder[contnr];
+	first_time = TRUE;
+	while (temp != 0) {
+	    if (first_time)
+		rspeak(360);
+	    printf("     ");
+	    pspeak(temp, -1);
+	    temp = g.hlink[temp];
+	    first_time = FALSE;
+	}
+    }
+    return;
+}
+
+/*
+  Routine to move an object
+*/
+void move(obj, where)
+int obj, where;
+{
+    int from;
+
+    if (obj > MAXOBJ)
+	from = g.fixed[obj - MAXOBJ];
+    else {
+	if (enclosed(obj))
+	    extract(obj);
+	from = g.place[obj];
+    }
+    if ((from > 0) && (from < MAXOBJ * 2))
+	carry(obj, from);
+    drop(obj, where);
+    return;
+}
+
+/*
+  noway, generate's some variant of "can't do that" message.
+*/
+int noway()
+{
+    int msg;
+
+    msg = 14;
+    if (pct(50))
+	msg = 110;
+    if (pct(33))
+	msg = 147;
+    if (pct(25))
+	msg = 250;
+    if (pct(20))
+	msg = 262;
+    if (pct(17))
+	msg = 25;
+    if (pct(14))
+	msg = 345;
+    if (pct(12))
+	msg = 346;
+    return (msg);
+}
+
+/*
+  opaque .TRUE. If obj is non-transparent container
+*/
+boolean opaque(obj)
+int obj;
+{
+    return (bitset(g.obj_state[obj], 6));
+}
+
+/*
+   outsid .TRUE. If location is outside the cave
+*/
+boolean outside(loc)
+int loc;
+{
+    return (bitset(g.loc_attrib[loc], 6));
+}
+
+/*
+  Routine true x% of the time. (x an integer from 0 to 100)
+*/
+int pct(x)
+int x;
+{
+    return (ranz(100) < x);
+}
+
+/*
+   plural .TRUE. if object is multiple objects
+*/
+boolean plural(obj)
+int obj;
+{
+    return (bitset(g.obj_state[obj], 13));
+}
+
+/*
+   portal .TRUE. If location is a cave entrance
+*/
+boolean portal(loc)
+int loc;
+{
+    return (bitset(g.loc_attrib[loc], 5));
+}
+
+/*
+   printed .TRUE. If object can be read.
+*/
+boolean printed(obj)
+int obj;
+{
+    return (bitset(g.obj_state[obj], 8));
+}
+
+/*
+  put is the same as move, except it returns a
+  value used to set the negated prop values
+  for the repository objects.
+*/
+int put(obj, where, pval)
+int obj, where, pval;
+{
+    move(obj, where);
+    return ((-1) - pval);
+}
+
+/*
+  RANZ
+*/
+int ranz(range)
+int range;
+{
+    return (rand() % range);
+}
+
+/*
+   small .TRUE. If object fits in sack or small container
+*/
+boolean small(obj)
+int obj;
+{
+    return (bitset(g.obj_state[obj], 5));
+}
+
+/*
+  toting .TRUE. If an item is being caried.
+*/
+int toting(item)
+int item;
+{
+    boolean aaa, bbb, ccc;
+    int contnr, outer, outer2;
+
+    contnr = -g.place[item];
+    outer = -g.place[contnr];
+    outer2 = -g.place[outer];
+
+    aaa = holding(contnr);
+    bbb = enclosed(contnr) && holding(outer);
+    ccc = enclosed(outer) && holding(outer2);
+
+    return (holding(item) || (enclosed(item) && (aaa || bbb || ccc)));
+}
+
+/*
+  treasr .TRUE. If object is valuable for points
+*/
+boolean treasr(obj)
+int obj;
+{
+    return (bitset(g.obj_state[obj], 14));
+}
+
+/*
+  vessel .TRUE. if object can hold a liquid
+*/
+boolean vessel(obj)
+int obj;
+{
+    return (bitset(g.obj_state[obj], 15));
+}
+
+/*
+  wearng .TRUE. If wearing obj
+*/
+boolean wearng(item)
+int item;
+{
+    return (bitset(g.obj_state[item], WEARBT));
+}
+
+/*
+   worn .TRUE. if object is being worn
+*/
+boolean worn(obj)
+int obj;
+{
+    return (bitset(g.obj_state[obj], 11));
+}
+
+static char *e_msg[] = {
+			"message line > 70 characters",	/* 00 */
+			"null line in message",	/* 01 */
+			"too many words of messages",	/* 02 */
+			"too many travel options",	/* 03 */
+			"too many vocabulary words",	/* 04 */
+			"required vocabulary word not found",	/* 05 */
+			"too many rtext or mtext messages",	/* 06 */
+			"too many hints",	/* 07 */
+			"location has loc_attrib bit being set twice",	/* 08 */
+			"invalid section number in database",	/* 09 */
+			"out of order locs or rspeak entries.",	/* 10 */
+			"illegal motion word in travel table",	/* 11 */
+			"** unused **.",/* 12 */
+			"unknown or illegal word in adjective table.",	/* 13 */
+			"illegal word in prep/obj table",	/* 14 */
+			"too many entries in prep/obj table",	/* 15 */
+			"object has condition bit set twice",	/* 16 */
+			"object number too large",	/* 17 */
+			"too many entries in adjective/noun table.",	/* 18 */
+			"** unused **.",/* 19 */
+			"special travel (500>l>300) exceeds goto list",	/* 20 */
+			"ran off end of vocabulary table",	/* 21 */
+			"verb class (n/1000) not between 1 and 3",	/* 22 */
+			"intransitive action verb exceeds goto list",	/* 23 */
+			"transitive action verb exceeds goto list",	/* 24 */
+			"conditional travel entry with no alternative",	/* 25 */
+			"location has no travel entries",	/* 26 */
+			"hint number exceeds goto list",	/* 27 */
+			"invalid month returned by date function",	/* 28 */
+			"action verb 'leave' has no object.",	/* 29 */
+			"preposition found in unexpected table",	/* 30 */
+		 "received an unexpected word terminator from a1toa5",	/* 31 */
+		    "trying to put a container into itself (tricky!)",	/* 32 */
+			"unknown word class in getwds",	/* 33 */
+			"** unused **.",/* 34 */
+			"trying to carry a non-existent object"};	/* 35 */
+
+/*
+  Fatal error routine
+*/
+void bug(n)
+unsigned int n;
+{
+    if (n < 36 && *e_msg[n] != '*')
+	fprintf(stderr, "Fatal error, probable cause: %s\n", e_msg[n]);
+    else
+	fprintf(stderr, "Fatal error number %d - Unused error number!\n", n);
+    panic((char *) 0, TRUE);
+}
+
+/*
+  Prompt for input, strip leading and trailing spaces,
+  return &buf[first non-whitespace].
+  Does not return if end of input.
+*/
+char *
+ ask(prompt, buf, buflen)
+char *prompt, *buf;
+int buflen;
+{
+    fputs(prompt, stdout);
+    fflush(stdout);
+    if (!fgets(buf, buflen, stdin))
+	panic("end of input", FALSE);
+    if (*buf) {
+	int c;
+	char *end = buf + strlen(buf);
+	if (end[-1] != '\n')
+	    /* Skip to end of line */
+	    while ((c = getchar()) != '\n' && c != EOF);
+	while (*buf && isspace(*buf))
+	    buf++;
+	while (buf <= --end && isspace(*end))
+	    *end = '\0';
+    }
+    return buf;
+}
+
+/*
+  save and abort
+*/
+
+void panic(msg, save)
+char *msg;
+boolean save;
+{
+    fprintf(stderr, "\nPANIC: %s%s\n",
+	 msg ? msg : "", save ? ". Save..." : msg ? "" : "aborting.");
+    if (save)
+	saveadv("advpanic.sav");
+    exit(EXIT_FAILURE);
+}
Index: /trunk/minix/commands/advent/verb.c
===================================================================
--- /trunk/minix/commands/advent/verb.c	(revision 9)
+++ /trunk/minix/commands/advent/verb.c	(revision 9)
@@ -0,0 +1,2142 @@
+/*	program VERB.C						*/
+
+#include	"stdio.h"
+#include	"advent.h"
+#include	"advdec.h"
+
+ /* Initialize default verb messages */
+static _CONST int actmsg[56] = {
+     0,  24,  29,  0,  33,   0,  33,  38,  38,  42,
+    14,  43, 110, 29, 110,  73,  75,  29,  13,  59,
+    59, 174, 313, 67,  13, 147, 155, 369, 146, 110,
+    13,  13,  24, 25, 110, 262,  14,  29, 271,  14,
+    14,  24,  29, 38,  24, 331,  24, 109, 332,   0,
+     0, 348, 358,  0, 364,   0};
+
+_PROTOTYPE(static int ck_obj, (void));
+_PROTOTYPE(void von, (void));
+_PROTOTYPE(void voff, (void));
+_PROTOTYPE(void vwave, (void));
+_PROTOTYPE(void veat, (void));
+_PROTOTYPE(void vthrow, (void));
+_PROTOTYPE(void vfind, (void));
+_PROTOTYPE(void vfill, (void));
+_PROTOTYPE(void vfeed, (void));
+_PROTOTYPE(void vbreak, (void));
+_PROTOTYPE(void vwake, (void));
+_PROTOTYPE(void vdrop, (void));
+_PROTOTYPE(void vpour, (void));
+_PROTOTYPE(void vput, (void));
+_PROTOTYPE(void vread, (void));
+_PROTOTYPE(void vinsert, (void));
+_PROTOTYPE(void vextract, (void));
+_PROTOTYPE(static boolean do_battle, (int *));
+_PROTOTYPE(void vhit, (void));
+_PROTOTYPE(void vanswer, (void));
+_PROTOTYPE(void vblow, (void));
+_PROTOTYPE(void vdial, (void));
+_PROTOTYPE(void vplay, (void));
+_PROTOTYPE(void vpick, (void));
+_PROTOTYPE(void vput, (void));
+_PROTOTYPE(void vturn, (void));
+_PROTOTYPE(void vget, (void));
+_PROTOTYPE(void vlook, (void));
+
+
+/*
+  Routine to process a transitive verb
+*/
+void trverb()
+{
+    newtravel = FALSE;
+    switch (verb) {
+    case NOTHING:
+    case CALM:
+    case WALK:
+    case QUIT:
+    case SCORE:
+    case FOO:
+    case SUSPEND:			break;
+    case TAKE:		vtake();	break;
+    case DROP:		vdrop();	break;
+    case SAY:		bug(34);	break;
+    case OPEN:		vopen();	break;
+    case CLOSE:		vclose();	break;
+    case LOCK:		vlock();	break;
+    case UNLOCK:	vunlock();	break;
+    case ON:		von();		break;
+    case OFF:		voff();		break;
+    case WAVE:		vwave();	break;
+    case KILL:		vkill();	break;
+    case POUR:		vpour();	break;
+    case EAT:		veat();		break;
+    case DRINK:		vdrink();	break;
+    case RUB:
+	if (object != LAMP)
+	    rspeak(76);
+	else
+	    actspk(RUB);
+	break;
+    case THROW:
+	if (prep == PREPDN)
+	    vput();
+	else
+	    vthrow();
+	break;
+    case FEED:		vfeed();	break;
+    case FIND:
+    case INVENTORY:	vfind();	break;
+    case FILL:		vfill();	break;
+    case BLAST:		ivblast();	break;
+    case READ:		vread();	break;
+    case BREAK:		vbreak();	break;
+    case WAKE:		vwake();	break;
+    case REMOVE:	vextract();	break;
+    case YANK:		vyank();	break;
+    case WEAR:		vwear();	break;
+    case HIT:		vhit();		break;
+    case ANSWER:	vanswer();	break;
+    case BLOW:		vblow();	break;
+    case DIAL:		vdial();	break;
+    case PLAY:		vplay();	break;
+    case PICK:		vpick();	break;
+    case PUT:		vput();		break;
+    case TURN:		vturn();	break;
+    case GET:		vget();		break;
+    case INSRT:		vinsert();	break;
+    case LOOK:		vlook();	break;
+    default:
+	printf("This verb is not implemented yet.\n");
+    }
+    return;
+}
+
+/*
+  Routine to speak default verb message
+*/
+void actspk(verb)
+int verb;
+{
+    int i;
+
+    if (verb < 1 || verb > 55)
+	bug(39);
+    i = actmsg[verb];
+    if (i)
+	rspeak(i);
+    return;
+}
+
+/*
+  CARRY TAKE etc.
+*/
+void vtake()
+{
+    int msg;
+
+    msg = 0;
+    if (object == BIRD && !g.closed && athand(BIRD)
+	&& g.place[BIRD] != g.loc) {
+	rspeak(407);
+	return;
+    }
+    if (prep == PREPOF) {
+	if (object && iobj) {
+	    rspeak(confuz());
+	    return;
+	} else if (!object) {
+	    object = iobj;
+	    iobj = 0;
+	    vdrop();
+	    return;
+	}
+    }
+    msg = 24;
+    if (object == BOAT)
+	msg = 281;
+    if (plural(object))
+	msg = 297;
+    if (holding(object)) {
+	rspeak(msg);
+	return;
+    }
+    /* Special case objects and fixed objects */
+    msg = ck_obj();
+    if (g.fixed[object]) {
+	rspeak(msg);
+	return;
+    }
+    if (prep == PREPIN) {
+	vinsert();
+	return;
+    }
+    /* Special case for liquids */
+    if (object == WATER || object == OIL || object == WINE) {
+	if (here(BOTTLE) && here(CASK)) {
+	    rspeak(315);
+	    return;
+	}
+	iobj = object;
+	if (here(BOTTLE)) {
+	    object = BOTTLE;
+	    if (holding(BOTTLE))
+		vfill();
+	    else
+		rspeak(312);
+	    return;
+	} else if (here(CASK)) {
+	    object = CASK;
+	    if (holding(CASK))
+		vfill();
+	    else
+		rspeak(312);
+	    return;
+	} else {
+	    rspeak(312);
+	    return;
+	}
+    }
+    if (object != BEAR && ((burden(0) + burden(object)) > 15)) {
+	if (wearng(object)) {
+	    g.prop[object] = 0;
+	    bitoff(object, WEARBT);
+	}
+	rspeak(92);
+	return;
+    }
+    if (prep == PREPFR || enclosed(object)) {
+	vextract();
+	return;
+    }
+    msg = 343;
+    /* Poster: hides wall safe */
+    if (object == POSTER && g.place[SAFE] == 0) {
+	g.prop[POSTER] = 1;
+	msg = 362;
+	/* Move safe and wall containing safe into view */
+	drop(SAFE, g.loc);
+	drop(WALL2, g.loc);
+    }
+    /* Boat: need the pole to push it */
+    if (object == BOAT) {
+	if (!toting(POLE) && g.place[POLE] != -BOAT) {
+	    rspeak(218);
+	    return;
+	} else {
+	    g.prop[BOAT] = 1;
+	    msg = 221;
+	}
+    }
+    /* Special case for bird. */
+    if (object == BIRD && g.prop[BIRD] <= 0) {
+	if (athand(ROD)) {
+	    rspeak(26);
+	    return;
+	}
+	if (!holding(CAGE)) {
+	    rspeak(27);
+	    return;
+	}
+	if (!ajar(CAGE)) {
+	    rspeak(358);
+	    return;
+	}
+	insert(BIRD, CAGE);
+	bitoff(CAGE, OPENBT);
+	pspeak(object, -1);
+	rspeak(54);
+	return;
+    }
+    /* SWORD If in anvil, need crown & must yank */
+    if (object == SWORD && g.prop[SWORD] != 0) {
+	if (iobj && iobj != ANVIL) {
+	    rspeak(noway());
+	    return;
+	}
+	if (verb != YANK)
+	    if (!yes(215, 0, 54))
+		return;
+
+	if (!wearng(CROWN)) {
+	    g.fixed[SWORD] = -1;
+	    g.prop[SWORD] = 3;
+	    pspeak(SWORD, 2);
+	    return;
+	}
+    }
+    carry(object, g.loc);
+    if (object == POLE || object == SKEY || object == SWORD
+	 || ((object == CLOAK || object == RING) && !wearng(object)) )
+	g.prop[object] = 0;
+
+    if (verb == YANK || object == SWORD)
+	msg = 204;
+    rspeak(msg);
+    return;
+}
+
+static int ck_obj()
+{
+    int msg;
+
+    msg = noway();
+    if (object == PLANT && g.prop[PLANT] <= 0)
+	msg = 115;
+    if (object == BEAR && g.prop[BEAR] == 1)
+	msg = 169;
+    if (object == CHAIN && g.prop[BEAR] != 0)
+	msg = 170;
+    if (object == SWORD && g.prop[SWORD] == 5)
+	msg = 208;
+    if (object == CLOAK && g.prop[CLOAK] == 2)
+	msg = 242;
+    if (object == AXE && g.prop[AXE] == 2)
+	msg = 246;
+    if (object == PHONE)
+	msg = 251;
+    if (object == BEES || object == HIVE)
+	msg = 295;
+    if (object == STICKS)
+	msg = 296;
+    return (msg);
+}
+
+/*
+  DROP etc.
+*/
+void vdrop()
+{
+    int msg;
+
+    /* Check for dynamite */
+    if (holding(ROD2) && object == ROD && !holding(ROD))
+	object = ROD2;
+    if (plural(object))
+	msg = 105;
+    else
+	msg = 29;
+
+    if (object == liq(BOTTLE))
+	object = BOTTLE;
+    else if (object == liq(CASK))
+	object = CASK;
+
+    if (!toting(object)) {
+	rspeak(msg);
+	return;
+    }
+    if (prep == PREPIN) {
+	vinsert();
+	return;
+    }
+    /* Snake and bird */
+    if (object == BIRD && here(SNAKE)) {
+	rspeak(30);
+	if (g.closed) {
+	    dwarfend();
+	    return;
+	}
+	extract(BIRD);
+	destroy(SNAKE);
+	/* Set snake prop for use by travel options */
+	g.prop[SNAKE] = 1;
+	drop(BIRD, g.loc);
+	return;
+    }
+    msg = 344;
+    if (verb == LEAVE)
+	msg = 353;
+    if (verb == THROW)
+	msg = 352;
+    if (verb == TAKE)
+	msg = 54;
+    if (object == POLE && holding(BOAT)) {
+	rspeak(280);
+	return;
+    }
+    /* Coins and vending machine */
+    if (object == COINS && here(VEND)) {
+	destroy(COINS);
+	drop(BATTERIES, g.loc);
+	pspeak(BATTERIES, 0);
+	return;
+    }
+    /* Bird and dragon (ouch!!) */
+    if (object == BIRD && at(DRAGON) && g.prop[DRAGON] == 0) {
+	rspeak(154);
+	extract(BIRD);
+	destroy(BIRD);
+	if (g.place[SNAKE] == plac[SNAKE])
+	    g.tally2++;
+	return;
+    }
+    /* Bear and troll */
+    if (object == BEAR && at(TROLL)) {
+	msg = 163;
+	destroy(TROLL);
+	destroy(TROLL + MAXOBJ);
+	move(TROLL2, plac[TROLL]);
+	move((TROLL2 + MAXOBJ), fixd[TROLL]);
+	juggle(CHASM);
+	g.prop[TROLL] = 2;
+    }
+    /* Vase */
+    else if (object == VASE) {
+	if (g.loc == plac[PILLOW])
+	    msg = 54;
+	else {
+	    g.prop[VASE] = at(PILLOW) ? 0 : 2;
+	    pspeak(VASE, g.prop[VASE] + 1);
+	    if (g.prop[VASE] != 0)
+		g.fixed[VASE] = -1;
+	}
+    } else {
+	if (worn(object) || object == POLE || object == BOAT)
+	    g.prop[object] = 0;
+	if (worn(object))
+	    bitoff(object, WEARBT);
+	if (object == POLE)
+	    g.prop[BOAT] = 0;
+    }
+
+    if (enclosed(object))
+	extract(object);
+    drop(object, g.loc);
+    rspeak(msg);
+    return;
+}
+
+/*
+  OPEN. special stuff for opening clam/oyster.
+  The following can be opened without a key:
+  clam/oyster, door, pdoor, bottle, cask, cage
+*/
+void vopen()
+{
+    int msg, oyclam;
+
+    if (!hinged(object))
+	msg = noway();
+    else if (object == PDOOR && g.prop[PDOOR] == 1)
+	msg = 253;
+    else if (ajar(object))
+	msg = 336;
+    else if (locks(object) || iobj == KEYS || iobj == SKEY) {
+	vunlock();
+	return;
+    } else if (locked(object))
+	if (object == DOOR)
+	    msg = 111;
+	else
+	    msg = 337;
+    else if (object == CLAM || object == OYSTER) {
+	oyclam = (object == OYSTER ? 1 : 0);
+	msg = oyclam + holding(object) ? 120 : 124;
+	if (!athand(TRIDENT))
+	    msg = 122 + oyclam;
+	if (iobj != 0 && iobj != TRIDENT)
+	    msg = 376 + oyclam;
+
+	if (msg == 124) {
+	    destroy(CLAM);
+	    drop(OYSTER, g.loc);
+	    drop(PEARL, 105);
+	}
+    } else {
+	msg = 54;
+	biton(object, OPENBT);
+    }
+    rspeak(msg);
+    return;
+}
+
+/*
+   close, shut
+   the following can be closed without keys:
+   door, pdoor, bottle, cask, cage
+*/
+void vclose()
+{
+    if (!hinged(object))
+	rspeak(noway());
+    else if (!ajar(object))
+	rspeak(338);
+    else if (locks(object))
+	vlock();
+    else {
+	rspeak(54);
+	bitoff(object, OPENBT);
+    }
+}
+
+/*
+  Lamp ON.
+*/
+void von()
+{
+    if (!athand(LAMP))
+	actspk(verb);
+    else if (g.limit < 0)
+	rspeak(184);
+    else if (g.prop[LAMP] == 1)
+	rspeak(321);
+    else {
+	g.prop[LAMP] = 1;
+	if (g.loc == 200)
+	    rspeak(108);
+	else
+	    rspeak(39);
+	if (g.wzdark) {
+	    g.wzdark = 0;
+	    describe();
+	    descitem();
+	}
+    }
+    return;
+}
+
+/*
+  Lamp OFF.
+*/
+void voff()
+{
+    if (!athand(LAMP))
+	actspk(verb);
+    else if (g.prop[LAMP] == 0)
+	rspeak(322);
+    else {
+	g.prop[LAMP] = 0;
+	rspeak(40);
+	if (dark())
+	    rspeak(16);
+    }
+    return;
+}
+
+/*
+  WAVE. no effect unless waving rod at fissure.
+*/
+void vwave()
+{
+    if (!holding(object) &&
+	(object != ROD || !holding(ROD2)))
+	rspeak(29);
+    else if (object != ROD || !at(FISSURE) ||
+	     !holding(object) || g.closing)
+	actspk(verb);
+    else if (iobj != 0 && iobj != FISSURE)
+	actspk(verb);
+    else {
+	g.prop[FISSURE] = 1 - g.prop[FISSURE];
+	pspeak(FISSURE, 2 - g.prop[FISSURE]);
+	if (g.chase == 0 || g.prop[FISSURE] != 0)
+	    return;
+	if ((g.loc == 17 && g.oldloc != 27)
+	    || (g.loc == 27 && g.oldloc != 17))
+	    return;
+	/* Demise of the Wumpus.  Champ must have just crossed bridge */
+	rspeak(244);
+	g.chase = 0;
+	drop(RING, 209);
+	g.prop[WUMPUS] = 6;
+	move(WUMPUS, 209);
+	biton(WUMPUS, DEADBT);
+	if (g.place[AXE] != plac[WUMPUS])
+	    return;
+	g.fixed[AXE] = 0;
+	g.prop[AXE] = 0;
+
+    }
+    return;
+}
+
+/*
+  ATTACK, KILL etc.
+*/
+void vkill()
+{
+    int msg, i, k;
+    boolean survival;
+
+    survival = TRUE;
+    switch (object) {
+    case BIRD:
+	if (g.closed)
+	    msg = 137;
+	else {
+	    destroy(BIRD);
+	    g.prop[BIRD] = 0;
+	    if (g.place[SNAKE] == plac[SNAKE])
+		g.tally2++;
+	    msg = 45;
+	}
+	break;
+    case DWARF:
+	if (g.closed) {
+	    dwarfend();
+	    return;
+	}
+	survival = do_battle(&msg);
+	break;
+    case 0:
+	msg = 44;
+	break;
+    case CLAM:
+    case OYSTER:
+	msg = 150;
+	break;
+    case DOG:
+	if (g.prop[DOG] == 1)
+	    msg = 291;
+	else if (iobj == AXE) {
+	    object = AXE;
+	    iobj = DOG;
+	    vthrow();
+	    return;
+	} else
+	    msg = 110;
+	break;
+    case SNAKE:
+	msg = 46;
+	break;
+    case TROLL:
+	if (iobj == AXE)
+	    msg = 158;
+	else
+	    msg = 110;
+	break;
+    case BEAR:
+	msg = 165 + (g.prop[BEAR] + 1) / 2;
+	break;
+    case WUMPUS:
+	if (g.prop[WUMPUS] == 6)
+	    msg = 167;
+	else if (iobj == AXE) {
+	    object = AXE;
+	    iobj = WUMPUS;
+	    vthrow();
+	    return;
+	} else
+	    msg = 110;
+	break;
+    case GNOME:
+	msg = 320;
+	break;
+    case DRAGON:
+	if (g.prop[DRAGON] != 0) {
+	    msg = 167;
+	    break;
+	}
+	if (!yes(49, 0, 0))
+	    break;
+	pspeak(DRAGON, 1);
+	biton(DRAGON, DEADBT);
+	g.prop[DRAGON] = 2;
+	g.prop[RUG] = 0;
+	k = (plac[DRAGON] + fixd[DRAGON]) / 2;
+	move((DRAGON + MAXOBJ), -1);
+	move((RUG + MAXOBJ), 0);
+	move(DRAGON, k);
+	move(RUG, k);
+	for (i = 1; i < MAXOBJ; i++)
+	    if (g.place[i] == plac[DRAGON]
+		|| g.place[i] == fixd[DRAGON]
+		|| holding(i))
+		move(i, k);
+	g.loc = k;
+	g.newloc = k;
+	return;
+    default:
+	actspk(verb);
+	return;
+    }
+    rspeak(msg);
+    if (!survival) {
+	g.oldloc2 = g.loc;
+	death();
+    }
+    return;
+}
+
+static boolean do_battle(msg_ptr)
+int *msg_ptr;
+{
+    boolean survival;
+    int temp;
+
+    survival = TRUE;
+    if (iobj == 0)
+	*msg_ptr = 49;
+    else if (iobj != AXE && iobj != SWORD) {
+	*msg_ptr = 355;
+	survival = FALSE;
+    } else if (pct(25)) {
+	temp = iobj;
+	iobj = object;
+	object = temp;
+	vthrow();
+	return (TRUE);
+    } else if (pct(25)) {
+	*msg_ptr = 355;
+	survival = FALSE;
+    } else if (pct(36))
+	*msg_ptr = 354;
+    else {
+	rspeak(356);
+	if (pct(61))
+	    *msg_ptr = 52;
+	else {
+	    *msg_ptr = 53;
+	    survival = FALSE;
+	}
+    }
+    return (survival);
+}
+
+/*
+  POUR
+*/
+void vpour()
+{
+    int msg;
+
+    if (object == BOTTLE || object == CASK) {
+	iobj = object;
+	object = liq(iobj);
+	if (object == 0) {
+	    rspeak(316);
+	    return;
+	}
+    } else {
+	if (object < WATER || object > (WINE + 1)) {
+	    rspeak(78);
+	    return;
+	}
+    }
+    if (!holding(BOTTLE) && !holding(CASK)) {
+	rspeak(29);
+	return;
+    }
+    if (holding(BOTTLE) && liq(BOTTLE) == object)
+	iobj = BOTTLE;
+    if (holding(CASK) && liq(CASK) == object)
+	iobj = CASK;
+    if (iobj == 0) {
+	rspeak(29);
+	return;
+    }
+    if (!ajar(iobj)) {
+	rspeak(335);
+	return;
+    }
+    if (iobj == CASK)
+	object++;
+    g.prop[iobj] = 1;
+    extract(object);
+    g.place[object] = 0;
+    msg = 77;
+    if (iobj == CASK) {
+	object--;
+	msg = 104;
+    }
+    if (at(PLANT) || at(DOOR) || (at(SWORD) && g.prop[SWORD] != 0)) {
+	if (at(DOOR)) {
+	    g.prop[DOOR] = 0;
+	    if (object == OIL) {
+		g.prop[DOOR] = 1;
+		bitoff(DOOR, LOCKBT);
+		biton(DOOR, OPENBT);
+	    }
+	    msg = 113 + g.prop[DOOR];
+	} else if (at(SWORD)) {
+	    /* If sword is alread oily, don't let him clean it. No
+	       soap. */
+	    if (g.prop[SWORD] != 5) {
+		g.prop[SWORD] = 4;
+		if (object == OIL) {
+		    g.prop[SWORD] = 5;
+		    g.fixed[SWORD] = -1;
+		}
+		msg = 206 + g.prop[SWORD] - 4;
+	    }
+	} else {
+	    msg = 112;
+	    if (object == WATER) {
+		if (g.prop[PLANT] < 0)
+		    g.prop[PLANT] = -g.prop[PLANT] - 1;
+		pspeak(PLANT, g.prop[PLANT] + 1);
+		g.prop[PLANT] = (g.prop[PLANT] + 2) % 6;
+		g.prop[PLANT2] = g.prop[PLANT] / 2;
+		newtravel = TRUE;
+		return;
+	    }
+	}
+    }
+    rspeak(msg);
+    return;
+}
+
+/*
+  EAT
+  If he ate the right thing and is in the right place, move him to
+  the other place with all his junk.  Otherwise, narky message.
+*/
+void veat()
+{
+    int msg, i, k, ll, kk;
+
+    switch (object) {
+    case HONEY:
+	g.tally2++;
+    case FOOD:
+	destroy(object);
+	msg = 72;
+	break;
+    case BIRD:
+    case SNAKE:
+    case CLAM:
+    case OYSTER:
+    case FLOWER:
+	msg = 301;
+	break;
+    case DWARF:
+    case DRAGON:
+    case TROLL:
+    case DOG:
+    case WUMPUS:
+    case BEAR:
+    case GNOME:
+	msg = 250;
+	break;
+    case MUSHRM:
+    case CAKES:
+	k = object - MUSHRM;
+	ll = 229 + k;
+	k = 159 - k;
+	kk = SKEY;
+	if (object == MUSHRM) {
+	    kk = TDOOR;
+	    if (g.loc != 158)
+		g.tally2++;
+	}
+	destroy(object);
+	msg = 228;
+	if (!(here(kk) || g.fixed[kk] == g.loc))
+	    break;
+	msg = ll;
+	/* If he hasn't taken tiny key off shelf, don't let him get it
+	   for free! */
+	for (i = 1; i < MAXOBJ; i++) {
+	    if (i == SKEY && g.prop[SKEY] == 1)
+		continue;
+	    if (g.place[i] == plac[kk] && g.fixed[i] == 0)
+		move(i, k);
+	}
+	if (g.loc == plac[SKEY] && g.place[SKEY] == plac[SKEY])
+	    g.tally2++;
+	g.loc = k;
+	g.newloc = k;
+	newtravel = TRUE;
+	break;
+    default:
+	actspk(verb);
+	return;
+    }
+    rspeak(msg);
+    return;
+}
+
+/*
+  DRINK
+*/
+void vdrink()
+{
+    int msg, k, j;
+
+    if (object == 0 && (iobj == BOTTLE || iobj == CASK))
+	object = liq(iobj);
+    msg = 110;
+    if (object == OIL)
+	msg = 301;
+    if (object != WATER && object != WINE) {
+	rspeak(msg);
+	return;
+    }
+    if (iobj == 0) {
+	if (object == liqloc(g.loc))
+	    iobj = -1;
+	if (athand(CASK) && object == liq(CASK))
+	    iobj = CASK;
+	if (athand(BOTTLE) && object == liq(BOTTLE))
+	    iobj = BOTTLE;
+    }
+    msg = 73;
+    if (iobj != -1) {
+	if (iobj == CASK)
+	    object++;
+	extract(object);
+	g.place[object] = 0;
+	g.prop[iobj] = 1;
+	msg = (iobj == CASK) ? 299 : 74;
+    }
+    if (object == WATER || object == (WATER + 1)) {
+	rspeak(msg);
+	return;
+    }
+    /* UH-OH. He's a wino. Let him reap the rewards of incontinence.
+       He'll wander around for awhile, then wake up somewhere or other,
+       having dropped most of his stuff. */
+    rspeak(300);
+    if (g.prop[LAMP] == 1)
+	g.limit -= ranz(g.limit) / 2;
+    if (g.limit < 10)
+	g.limit = 25;
+    k = 0;
+    if (pct(15))
+	k = 49;
+    if (k == 0 && pct(15))
+	k = 53;
+    if (k == 0 && pct(25))
+	k = 132;
+    if (k == 0)
+	k = 175;
+    if (outside(g.loc))
+	k = 5;
+    if (k == g.loc) {
+	rspeak(msg);
+	return;
+    }
+    if (holding(AXE))
+	move(AXE, k);
+    if (holding(LAMP))
+	move(LAMP, k);
+    for (j = 1; j < MAXOBJ; j++) {
+	if (wearng(j))
+	    bitoff(j, WEARBT);
+	if (holding(j))
+	    drop(j, g.loc);
+    }
+    g.loc = k;
+    g.newloc = k;
+}
+
+/*
+  THROW etc.
+*/
+void vthrow()
+{
+    int msg, i, k, dwarfn;
+
+    if (holding(ROD2) && object == ROD && !holding(ROD))
+	object = ROD2;
+    if (!holding(object)) {
+	actspk(verb);
+	return;
+    }
+    if (object == BOAT || object == BEAR) {
+	rspeak(noway());
+	return;
+    }
+    dwarfn = dcheck();
+    if (iobj == 0) {
+	/* No indirect object was specified.  If a dwarf is present,
+	   assume it is the object. If not, look for other living
+	   thing. If no living things present, treat 'THROW' as 'DROP'. */
+
+	if (dwarfn)
+	    iobj = DWARF;
+	else {
+	    /* No dwarves present; figure out pausible object. */
+	    k = 0;
+	    for (i = 1; i < MAXOBJ; i++) {
+		if (at(i) && living(i)) {
+		    iobj = i;
+		    k++;
+		}
+	    }
+	    if (k == 0) {
+		vdrop();
+		return;
+	    }
+	    /* It is a beastie of some sort.  Is there more than one?
+	       Don't kill the bird by default. */
+	    if (k > 1) {
+		rspeak(43);
+		return;
+	    } else {
+		if (iobj == BIRD) {
+		    vdrop();
+		    return;
+		}
+		if (treasr(object) && at(TROLL))
+		    iobj = TROLL;
+	    }
+	}
+    }
+    if (object == SWORD || object == BOTTLE) {
+	vbreak();
+	return;
+    }
+    if (object == FLOWER && iobj == HIVE)
+	iobj = BEES;
+    if (edible(object) && living(iobj)) {
+	vfeed();
+	return;
+    }
+    /* If not axe, same as drop... */
+    if (object != AXE && iobj != TROLL) {
+	vdrop();
+	return;
+    }
+    /* AXE is THROWN */
+    msg = 48;
+    switch (iobj) {
+    case DRAGON:
+	if (g.prop[DRAGON] == 0)
+	    msg = 152;
+	break;
+    case DWARF:
+	/* At a dwarf... */
+	if (pct(75)) {
+	    g.dseen[dwarfn] = g.dloc[dwarfn] = 0;
+	    msg = 47;
+	    ++g.dkill;
+	    if (g.dkill == 1)
+		msg = 149;
+	}
+	break;
+    case BEAR:
+	/* This'll teach him to throw axe at the bear */
+	if (g.prop[BEAR] == 0) {
+	    msg = 164;
+	    drop(AXE, g.loc);
+	    g.fixed[AXE] = -1;
+	    g.prop[AXE] = 1;
+	    juggle(BEAR);
+	}
+	rspeak(msg);
+	return;
+    case WUMPUS:
+	/* Or the WUMPUS! */
+	if (g.prop[WUMPUS] == 6) {
+	    vdrop();
+	    return;
+	} else {
+	    msg = 245;
+	    g.prop[AXE] = 2;
+	    if (g.prop[WUMPUS] == 0) {
+		drop(AXE, g.loc);
+		g.fixed[AXE] = -1;
+		juggle(iobj);
+	    } else {
+		msg = 243;
+		destroy(AXE);
+	    }
+	}
+	rspeak(msg);
+	return;
+    case DOG:
+	/* Or the nice doggie! */
+	if (g.prop[DOG] != 1) {
+	    msg = 248;
+	    g.prop[AXE] = 3;
+	    drop(AXE, g.loc);
+	    g.fixed[AXE] = -1;
+	    juggle(iobj);
+	}
+	rspeak(msg);
+	return;
+    case TROLL:
+	/* Snarf a treasure for the troll */
+	if (object == AXE) {
+	    msg = 158;
+	} else if (!treasr(object) ||
+		   (object == CASK && (liq(CASK) != WINE))) {
+	    vdrop();
+	    return;
+	} else {
+	    msg = 159;
+	    drop(object, 0);
+	    if (object == CASK)
+		g.place[WINE + 1] = 0;
+	    move(TROLL, 0);
+	    move((TROLL + MAXOBJ), 0);
+	    drop(TROLL2, plac[TROLL]);
+	    drop((TROLL2 + MAXOBJ), fixd[TROLL]);
+	    juggle(CHASM);
+	    rspeak(msg);
+	    return;
+	}
+	break;
+
+    default:
+	/* Otherwise it is an attack */
+	verb = KILL;
+	object = iobj;
+	iobj = objs[objx];
+	vkill();
+	return;
+    }
+
+    rspeak(msg);
+    drop(AXE, g.loc);
+    g.newloc = g.loc;
+    describe();
+}
+
+/*
+  FIND might be carrying it, or it might be here. else give caveat.
+*/
+void vfind()
+{
+    int msg;
+
+    if (at(object) ||
+	(liq(BOTTLE) == object && at(BOTTLE)) ||
+	object == liqloc(g.loc))
+	msg = 94;
+    else if (dcheck() && g.dflag >= 2 && object == DWARF)
+	msg = 94;
+    else if (g.closed)
+	msg = 138;
+    else if (at(object))
+	msg = 24;
+    else {
+	actspk(verb);
+	return;
+    }
+    rspeak(msg);
+    return;
+}
+
+/*
+  FEED
+*/
+void vfeed()
+{
+    int msg;
+
+    if (iobj == 0 || !living(iobj)) {
+	int i, k, kk;
+
+	if (object == BIRD) {
+	    rspeak(100);
+	    return;
+	}
+	if (!living(object)) {
+	    rspeak(noway());
+	    return;
+	}
+	/* See if there is anything edible around here. */
+
+	kk = 0;
+	k = 0;
+	for (i = 1; i < MAXOBJ; i++)
+	    if (here(i) && edible(i)) {
+		k++;
+		kk = i;
+	    }
+	iobj = object;
+	object = kk;
+	if (k != 1 && !dead(iobj)) {
+	    printf("What do you want to feed the %s\n", otxt[objx]);
+	    objs[1] = 0;
+	    objx = 0;
+	    return;
+	}
+    }
+    /* Feed object ot indirect object */
+    msg = 102;
+    switch (iobj) {
+    case DRAGON:
+	if (g.prop[DRAGON] != 0)
+	    msg = noway();
+	break;
+    case TROLL:
+	msg = 182;
+	break;
+    case SNAKE:
+	if (object == BIRD && !g.closed) {
+	    msg = 101;
+	    destroy(BIRD);
+	    g.prop[BIRD] = 0;
+	    g.tally2++;
+	}
+	break;
+    case DWARF:
+	msg = 103;
+	g.dflag++;
+	break;
+    case BEAR:
+	if (g.prop[BEAR] == 3)
+	    msg = noway();
+	if (g.prop[BEAR] == 1 || g.prop[BEAR] == 2)
+	    msg = 264;
+	if (object == FOOD)
+	    msg = 278;
+	if (object == HONEY) {
+	    g.prop[BEAR] = 1;
+	    g.fixed[AXE] = 0;
+	    destroy(HONEY);
+	    msg = 168;
+	}
+	break;
+    case DOG:
+	msg = 291;
+	if (object == FOOD && g.prop[DOG] != 1) {
+	    msg = 249;
+	    destroy(FOOD);
+	}
+	break;
+    case WUMPUS:
+	if (g.prop[WUMPUS] == 6)
+	    msg = 326;
+	if (g.prop[WUMPUS] == 0)
+	    msg = 327;
+	if (object == FOOD)
+	    msg = 240;
+	break;
+    case BEES:
+	if (object == FLOWER) {
+	    if (enclosed(FLOWER))
+		extract(FLOWER);
+	    drop(FLOWER, g.loc);
+	    g.fixed[FLOWER] = -1;
+	    g.prop[FLOWER] = 1;
+	    drop(HONEY, g.loc);
+	    juggle(HONEY);
+	    msg = 267;
+	    g.prop[HIVE] = 1;
+	}
+    }
+    rspeak(msg);
+    return;
+}
+
+/*
+  FILL. object with iobj
+*/
+void vfill()
+{
+    int msg, k;
+
+    if (!vessel(object))
+	msg = 313;
+    else {
+	if (iobj == 0)
+	    iobj = liqloc(g.loc);
+	if (object == BOTTLE || object == CASK) {
+	    k = (object == CASK) ? 1 : 0;
+	    msg = 0;
+	    if (iobj == 0)
+		msg = 304 + k;
+	    if (liq(object) != 0)
+		msg = 302 + k;
+	    if (msg != 0) {
+		rspeak(msg);
+		return;
+	    }
+	    msg = 306 + k;
+	    if (iobj == OIL)
+		msg = 308 + k;
+	    if (iobj == WINE)
+		msg = 310 + k;
+	    g.prop[object] = (int) g.loc_attrib[g.loc] & 14;
+	    g.place[iobj + k] = -1;
+	    insert(iobj + k, object);
+	} else if (object == VASE) {
+	    if (iobj == 0 || !holding(VASE)) {
+		rspeak(144);
+		return;
+	    }
+	    msg = 145;
+	    g.prop[VASE] = 2;
+	    g.fixed[VASE] = -1;
+	    if (enclosed(object))
+		extract(object);
+	    drop(object, g.loc);
+	} else if (object == GRAIL)
+	    msg = 298;
+	else
+	    msg = 339;
+    }
+    rspeak(msg);
+}
+
+/*
+  READ. Magazine in dwarvish, message we've seen, and ... oyster?
+*/
+void vread()
+{
+    int msg;
+
+    if (blind()) {
+	actspk(verb);
+	return;
+    }
+    if (object && iobj) {
+	rspeak(confuz());
+	return;
+    }
+    msg = confuz();
+    if (!object)
+	object = iobj;
+    switch (object) {
+    case BOOK:
+    case BOOK2:
+	msg = 142;
+	break;
+    case BILLBD:
+	msg = 361;
+	break;
+    case CARVNG:
+	msg = 372;
+	break;
+    case MAGAZINE:
+	msg = 190;
+	break;
+    case MESSAGE:
+	msg = 191;
+	break;
+    case POSTER:
+	msg = 370;
+	break;
+    case TABLET:
+	msg = 196;
+	break;
+    case OYSTER:
+	if (g.hinted[2] && holding(OYSTER))
+	    msg = 194;
+	if (!g.hinted[2] && holding(OYSTER) && g.closed) {
+	    g.hinted[2] = yes(192, 193, 54);
+	    return;
+	}
+	break;
+    }
+    rspeak(msg);
+    return;
+}
+
+/*
+  BREAK. works for mirror in repository and, of course the
+  vase and bottle.  Also the sword is more brittle than it appears.
+*/
+void vbreak()
+{
+    int msg, k;
+    boolean it_broke;
+
+    it_broke = FALSE;
+    msg = 146;
+    switch (object) {
+    case MIRROR:
+	msg = 148;
+	if (g.closed) {
+	    rspeak(197);
+	    dwarfend();
+	    return;
+	}
+	break;
+    case VASE:
+	if (g.prop[VASE] == 0) {
+	    it_broke = TRUE;
+	    msg = 198;
+	    g.prop[VASE] = 2;
+	}
+	break;
+    case BOTTLE:
+	if (g.prop[BOTTLE] != 3) {
+	    it_broke = TRUE;
+	    k = liq(BOTTLE);
+	    msg = 231;
+	    g.prop[BOTTLE] = 3;
+	    if (k) {
+		extract(k);
+		g.place[k] = 0;
+	    }
+	}
+	break;
+    case SWORD:
+	msg = 29;
+	if (holding(SWORD)) {
+	    msg = 279;
+	    g.prop[SWORD] = 4;
+	    it_broke = TRUE;
+	}
+	break;
+    }
+    if (it_broke) {
+	if (enclosed(object))
+	    extract(object);
+	if (holding(object))
+	    drop(object, g.loc);
+	g.fixed[object] = -1;
+    }
+    rspeak(msg);
+    return;
+}
+
+/*
+  WAKE. only use is to disturb the dwarves or the Wumpus.
+  Other wumpus-wakers link here.
+*/
+void vwake()
+{
+    int msg;
+
+    msg = actmsg[verb];
+    if (at(WUMPUS)) {
+	g.chase = TRUE;
+	g.prop[WUMPUS] = 1;
+	msg = 276;
+    }
+    if (at(DOG) && g.prop[DOG] == 1)
+	msg = 291;
+    if (object == DWARF && g.closed) {
+	rspeak(199);
+	dwarfend();
+	return;
+    }
+    rspeak(msg);
+    return;
+}
+
+/*
+   YANK. A variant of 'CARRY'.  In general, not a good idea.
+   At most, it gets the cloak or a couple of snide comments.
+ */
+void vyank()
+{
+    if (toting(object))
+	vdrop();
+    else if (object == BEAR && g.prop[CHAIN])
+	rspeak(205);
+    else if (object == CLOAK && g.prop[CLOAK] == 2) {
+	/* Cloak. big trouble ahead. */
+	g.prop[ROCKS] = 1;
+	g.prop[CLOAK] = 0;
+	g.fixed[CLOAK] = 0;
+	carry(CLOAK, g.loc);
+	rspeak(241);
+	if (at(WUMPUS) && g.prop[WUMPUS] == 0) {
+	    g.chase = 1;
+	    g.prop[WUMPUS] = 1;
+	    rspeak(276);
+	}
+    } else
+	vtake();
+    return;
+}
+
+/*
+   WEAR.  Only good for jewels, ruby slippers, cloak & crown.
+   But he might try the sword.  Anything else is ridiculous.
+   Another variant of 'CARRY'.
+ */
+void vwear()
+{
+    int msg;
+
+    if (object == SWORD && g.prop[SWORD] != 3)
+	msg = 209;
+    else if (worn(object)) {
+	if (object == CLOAK && g.prop[CLOAK] == 2)
+	    msg = 242;
+	else if (wearng(object))
+	    msg = (object == SHOES) ? 227 : 210;
+	else {
+	    g.prop[object] = 1;
+	    biton(object, WEARBT);
+	    if (enclosed(object))
+		extract(object);
+	    if (holding(object))
+		msg = 54;
+	    else {
+		vtake();
+		return;
+	    }
+	}
+    } else {
+	printf("Just exactly how does one wear a %s\n", otxt[objx]);
+	return;
+    }
+    rspeak(msg);
+    return;
+}
+
+/*
+   HIT. If not punching out telephone, assume attack.
+ */
+void vhit()
+{
+    if (at(WUMPUS) && g.prop[WUMPUS] == 0) {
+	vwake();
+	return;
+    }
+    if (object != PHONE) {
+	vkill();
+	return;
+    } else {
+	if (g.closed) {
+	    rspeak(282);
+	    dwarfend();
+	    return;
+	}
+	if (g.prop[PHONE] == 2)
+	    rspeak(256);
+	else {
+	    drop(SLUGS, g.loc);
+	    g.prop[PHONE] = 2;
+	    g.prop[BOOTH] = 2;
+	    rspeak(257);
+	}
+    }
+    return;
+}
+
+/*
+   ANSWER (telephone). Smartass for anything else.
+ */
+void vanswer()
+{
+    int msg;
+
+    switch (object) {
+    case DWARF:
+    case WUMPUS:
+    case SNAKE:
+    case BEAR:
+    case DRAGON:
+	msg = 259;
+	break;
+    case TROLL:
+	msg = 258;
+	break;
+    case BIRD:
+	msg = 260;
+	break;
+    case PHONE:
+	if (g.prop[PHONE] != 0)
+	    msg = 269;
+	else if (g.closed) {
+	    rspeak(283);
+	    normend();
+	    return;
+	} else {
+	    msg = 261;
+	    g.prop[PHONE] = 1;
+	    g.prop[BOOTH] = 2;
+	}
+	break;
+    default:
+	msg = actmsg[verb];
+	break;
+    }
+    rspeak(msg);
+    return;
+}
+
+/*
+   BLOW. Joshua fit de battle of Jericho, and de walls ...
+ */
+void vblow()
+{
+    int msg, i, k;
+
+    msg = actmsg[verb];
+    if (object != 0 && iobj != 0) {
+	rspeak(msg);
+	return;
+    }
+    if (object == 0)
+	object = iobj;
+    iobj = 0;
+    if (object == 0)
+	msg = 268;
+    if (object == HORN) {
+	msg = outside(g.loc) ? 277 : 266;
+	if (at(WUMPUS)) {
+	    rspeak(msg);
+	    if (g.prop[WUMPUS] == 0)
+		vwake();
+	    return;
+	} else if (g.prop[WALL] != 1 && (g.loc == 102 || g.loc == 194)) {
+	    k = g.loc == 194 ? 195 : 196;
+	    msg = 265;
+	    g.prop[WALL] = 1;
+	    for (i = 1; i < MAXOBJ; i++)
+		if (g.place[i] == g.loc || g.fixed[i] == g.loc)
+		    move(i, k);
+	    g.newloc = k;
+	}
+    }
+    rspeak(msg);
+    return;
+}
+
+/*
+   DIAL. No effect unless at phone.
+ */
+void vdial()
+{
+    if (object != PHONE)
+	actspk(verb);
+    else if (g.closed) {
+	rspeak(283);
+	normend();
+    } else
+	rspeak(271);
+    return;
+}
+
+/*
+   PLAY.  Only for horn or lyre.
+ */
+void vplay()
+{
+    int msg;
+
+    msg = actmsg[verb];
+    if (object != 0 && iobj != 0) {
+	rspeak(confuz());
+	return;
+    }
+    if (object == 0)
+	object = iobj;
+    if (object == HORN) {
+	vblow();
+	return;
+    }
+    if (object == LYRE) {
+	msg = 287;
+	if (here(DOG) && !dead(DOG)) {
+	    g.prop[DOG] = 1;
+	    biton(DOG, DEADBT);
+	    g.fixed[AXE] = 0;
+	    g.prop[AXE] = 0;
+	    msg = 288;
+	}
+    }
+    rspeak(msg);
+    return;
+}
+
+/*
+   PICK/ PICK UP.  Can pick flower & mushrooms,
+   But must 'PICK UP' everything else.
+ */
+void vpick()
+{
+    if (object == 0)
+	object = iobj;
+    iobj = 0;
+    if (object == FLOWER || object == MUSHRM || prep != 0)
+	vtake();
+    else
+	rspeak(confuz());
+    return;
+}
+
+/*
+   PUT DOWN: equivalent to drop
+   PUT IN: if liquid, means fill
+   PUT ON: wear of drop
+ */
+void vput()
+{
+    if (prep == 0) {
+	printf("Where do you want to put the %s\n", otxt[objx]);
+	return;
+    }
+    if (prep == PREPIN)
+	vinsert();
+    else {
+	/* PUT ON: wear or put object on iobj */
+	if (prep == PREPON) {
+	    if (object == 0) {
+		object = iobj;
+		otxt[objx] = iotxt[iobx];
+		iobj = 0;
+	    }
+	    if (worn(object) || object == 0)
+		vwear();
+	    else
+		vdrop();
+	} else {
+	    /* PUT DOWN: "drop" */
+	    if (object == 0 && iobj == 0) {
+		if (object == 0)
+		    object = iobj;
+		iobj = 0;
+		vdrop();
+	    } else
+		rspeak(noway());
+	}
+    }
+    return;
+}
+
+/* turn on/off */
+void vturn()
+{
+    if (!prep)
+	rspeak(confuz());
+    else {
+	if (!object && iobj == LAMP)
+	    object = LAMP;
+	if (object != LAMP)
+	    rspeak(noway());
+	else if (prep == PREPON)
+	    von();
+	else
+	    voff();
+    }
+    return;
+}
+
+/*
+   GET (no prep): "take"
+   GET IN: "enter"
+   GET OUT: "leave"
+ */
+void vget()
+{
+    if (prep == 0 || prep == PREPFR)
+	vtake();
+    else if (object == 0) {
+	object = iobj;
+	iobj = 0;
+	prep = 0;
+	vtake();
+    }
+    return;
+}
+
+/*
+   INSERT/PUT IN
+ */
+void vinsert()
+{
+    int msg;
+
+    if (iobj == 0) {
+	printf("Where do you want to %s it?\n", vtxt[vrbx]);
+	return;
+    }
+    msg = noway();
+    if (object == SWORD && iobj == ANVIL && g.prop[SWORD] == 0)
+	msg = 350;
+    if (!vessel(iobj)) {
+	rspeak(msg);
+	return;
+    }
+    msg = ck_obj();
+    if (g.fixed[object]) {
+	rspeak(msg);
+	return;
+    }
+    if (object == iobj) {
+	rspeak(252);
+	return;
+    }
+    if (iobj == BOTTLE || iobj == CASK || iobj == VASE
+	|| iobj == GRAIL || (object >= WATER && object <= WINE + 1)) {
+	object = iobj;
+	iobj = objs[objx];
+	vfill();
+	return;
+    }
+    if (!ajar(iobj)) {
+	rspeak(358);
+	return;
+    }
+    if (iobj == CHEST) {
+	if (object == BOAT)
+	    msg = noway();
+	else {
+	    if (wearng(object))
+		bitoff(object, WEARBT);
+	    if (worn(object))
+		g.prop[object] = 0;
+	    if (enclosed(object))
+		extract(object);
+	    insert(object, iobj);
+	    msg = 54;
+	}
+	rspeak(msg);
+	return;
+    }
+    /* Bird goes into cage and only cage */
+    if (object == BIRD && iobj != CAGE) {
+	rspeak(351);
+	return;
+    }
+    if (object != BIRD && iobj == CAGE) {
+	rspeak(329);
+	return;
+    }
+    if (object == BIRD) {
+	prep = 0;
+	vtake();
+	return;
+    }
+    /* Bar vase & pillow from safe, to force putting down on florr */
+    if ((object == VASE || object == PILLOW) && iobj == SAFE) {
+	rspeak(329);
+	return;
+    }
+    if (object != RADIUM && iobj == SHIELD) {
+	rspeak(329);
+	return;
+    }
+    if (iobj == PHONE) {
+	if (object == COINS || object == SLUGS) {
+	    destroy(object);
+	    msg = 330;
+	} else
+	    msg = 329;
+	rspeak(msg);
+	return;
+    }
+    if (iobj == VEND) {
+	if (object == COINS || object == SLUGS) {
+	    destroy(object);
+	    move(BATTERIES, g.loc);
+	    if (g.prop[BATTERIES] == 1) {
+		rspeak(317);
+		g.prop[VEND] = 1;
+	    }
+	    g.prop[BATTERIES] = 0;
+	    pspeak(BATTERIES, 0);
+	} else
+	    rspeak(noway());
+	return;
+    }
+    /* Put batteries in lamp. There is a glitch here, in that if he
+       tries to get a third set of batteries before the second set has
+       been inserted, the second set disappears!
+       ***fix this some time ***
+     */
+    if (iobj == LAMP) {
+	if (object != BATTERIES || g.prop[BATTERIES] != 0)
+	    msg = noway();
+	else {
+	    g.prop[BATTERIES] = 1;
+	    if (enclosed(BATTERIES))
+		extract(BATTERIES);
+	    if (holding(BATTERIES))
+		drop(BATTERIES, g.loc);
+	    g.limit = 400;
+	    g.prop[LAMP] = 1;
+	    g.lmwarn = FALSE;
+	    msg = 188;
+	}
+	rspeak(msg);
+	return;
+    }
+    if (!small(object))
+	msg = 329;
+    else {
+	if (wearng(object))
+	    bitoff(object, WEARBT);
+	if (worn(object))
+	    g.prop[object] = 0;
+	if (enclosed(object))
+	    extract(object);
+	insert(object, iobj);
+	msg = 54;
+    }
+    rspeak(msg);
+    return;
+
+}
+
+/* Remove or take from */
+void vextract()
+{
+    int msg;
+
+    if (object == RING && g.prop[RING] == 2) {
+	prep = 0;
+	iobj = 0;
+	vtake();
+	return;
+    }
+    msg = 343;
+    if (iobj == 0) {
+	if (!enclosed(object))
+	    msg = 340;
+	iobj = -g.place[object];
+    }
+    if (g.place[object] != -iobj)
+	msg = 341;
+    if (!ajar(iobj))
+	msg = 335;
+    if (object == WATER || object == OIL || object == WINE)
+	msg = 342;
+    if (!toting(object) && ((burden(0) + burden(object)) > 15))
+	msg = 92;
+    if (msg == 343) {
+	if (object == BIRD) {
+	    vdrop();
+	    return;
+	}
+	extract(object);
+    }
+    rspeak(msg);
+    return;
+}
+
+/*
+   lock. chain, grate, chest, elfin door
+   Here are the current lock/unlock messages & numbers:
+   31	you have no keys.
+   32	it has no lock.
+   34	it's already locked.
+   35	the grate is now locked.
+   36	the grate is now unlocked.
+   37	it was allready unlocked.
+   55	you can't unlock the keys.
+   171	The chain is now unlocked.
+   172	The chain is now locked.
+   173	There is nothing here to which the chain can be locked.
+   224	Your keys are all too large.
+   234	The wrought-iron door is now locked.
+   235	The tiny door is now locked.
+   236	The wrought-iron door is now unlocked.
+   237	The tiny door is now unlocked.
+   375	You don't have the right key.
+   333	the chest is now locked.
+   334	the chest is now unlocked.
+   367	The safe's door swings shut.
+*/
+void vlock()
+{
+    int msg, k;
+
+    if (!hinged(object))
+    {
+	printf("I don't know how to lock or unlock the %s\n",
+	       otxt[objx]);
+	return;
+    }
+    else if (!locks(object))
+	msg = 32;
+    else if (locked(object))
+	msg = 34;
+    else if (!athand(KEYS) && !athand(SKEY) && object != SAFE)
+	msg = 31;
+    else {
+	msg = 375;
+	switch (object) {
+	case CHAIN:
+	    if (!athand(KEYS))
+		break;
+	    msg = 173;
+	    if (g.loc != plac[CHAIN])
+		break;
+	    msg = 172;
+	    g.prop[CHAIN] = 2;
+	    if (enclosed(CHAIN))
+		extract(CHAIN);
+	    if (holding(CHAIN))
+		drop(CHAIN, g.loc);
+	    g.fixed[CHAIN] = -1;
+	    biton(CHAIN, LOCKBT);
+	    bitoff(CHAIN, OPENBT);
+	    break;
+
+	case CHEST:
+	    if (!athand(KEYS))
+		break;
+	    msg = 334;
+	    biton(CHEST, LOCKBT);
+	    bitoff(CHEST, OPENBT);
+	    break;
+
+	case TDOOR:
+	case TDOOR2:
+	    msg = 224;
+	    if (!toting(SKEY))
+		break;
+	    g.prop[TDOOR] = 0;
+	    g.prop[TDOOR2] = 0;
+	    msg = 234 + (TDOOR2 - object);
+	    k = TDOOR + TDOOR2 - object;
+	    biton(k, LOCKBT);
+	    bitoff(k, OPENBT);
+	    biton(object, LOCKBT);
+	    bitoff(object, OPENBT);
+	    break;
+
+	case GRATE:
+	    if (!athand(KEYS))
+		break;
+	    g.prop[GRATE] = 0;
+	    msg = 35;
+	    biton(GRATE, LOCKBT);
+	    bitoff(GRATE, OPENBT);
+	    break;
+
+	case SAFE:
+	    g.prop[SAFE] = 0;
+	    msg = 367;
+	    biton(SAFE, LOCKBT);
+	    bitoff(SAFE, OPENBT);
+	    break;
+
+	}
+    }
+    rspeak(msg);
+}
+
+/*
+   UNLOCK. chain, grate, chest, elfin door.
+*/
+void vunlock()
+{
+    int msg, k;
+
+    if (object == KEYS || object == SKEY)
+	msg = 55;
+    else if (!hinged(object))
+    {
+	printf("I don't know how to lock or unlock the %s\n",
+	       otxt[objx]);
+	return;
+    }
+    else if (!locked(object))
+	msg = 37;
+    else if (!locks(object))
+	msg = 32;
+    else if (object == SAFE) {
+	if (iobj == KEYS || iobj == SKEY)
+	    msg = 368;
+	else
+	    msg = 342;
+    } else if (!athand(KEYS) && !athand(SKEY))
+	msg = 31;
+    else {
+	msg = 375;
+	switch (object) {
+	case CHAIN:
+	    if (!athand(KEYS))
+		break;
+	    if (g.prop[BEAR] == 0)
+		msg = 41;
+	    else {
+		msg = 171;
+		g.prop[CHAIN] = 0;
+		g.fixed[CHAIN] = 0;
+		if (g.prop[BEAR] != 3)
+		    g.prop[BEAR] = 2;
+		g.fixed[BEAR] = 2 - g.prop[BEAR];
+		bitoff(CHAIN, LOCKBT);
+		biton(CHAIN, OPENBT);
+	    }
+	    break;
+	case CHEST:
+	    if (athand(KEYS)) {
+		msg = 333;
+		bitoff(CHEST, LOCKBT);
+		biton(CHEST, OPENBT);
+	    }
+	    break;
+	case TDOOR:
+	case TDOOR2:
+	    /* Elvin door stuff to lock/unlock tiny door w/special key.
+	       the damn thing is really at four places, and we want the
+	       right messages if he only has 'BIG'keys (or no keys).
+	       Also, he can unlock it either while he is big or small. */
+	    msg = 224;
+	    if (!athand(SKEY))
+		break;
+	    if (g.closing) {
+		msg = 130;
+		if (!g.panic)
+		    g.clock2 = 15;
+		g.panic = TRUE;
+	    } else {
+		g.prop[TDOOR] = 1;
+		g.prop[TDOOR2] = 1;
+		msg = 234 + 2 + (TDOOR2 - object);
+		k = TDOOR + (TDOOR2 - object);
+		bitoff(k, LOCKBT);
+		biton(k, OPENBT);
+		bitoff(object, LOCKBT);
+		biton(object, OPENBT);
+	    }
+	    break;
+	case GRATE:
+	    if (!athand(KEYS))
+		break;
+	    if (g.closing) {
+		msg = 130;
+		if (!g.panic)
+		    g.clock2 = 15;
+		g.panic = TRUE;
+	    } else {
+		g.prop[GRATE] = 1;
+		msg = 36;
+		bitoff(GRATE, LOCKBT);
+		biton(GRATE, OPENBT);
+	    }
+	    break;
+	default:
+	    msg = 33;
+	}
+    }
+    rspeak(msg);
+}
+
+/*
+   LOOK.
+*/
+void vlook()
+{
+    int sloc;
+
+    if (object != 0) {
+	rspeak(confuz());
+	return;
+    }
+    /* Look into something (a container). */
+    if (vessel(iobj)) {
+	if (!ajar(iobj) && opaque(iobj))
+	    rspeak(actmsg[verb]);
+	else if (g.holder[iobj] == 0)
+	    rspeak(359);
+	else {
+	    putchar(' ');
+	    lookin(iobj);
+	}
+
+	/* Look at something. If written, read it. */
+    } else if (printed(iobj)) {
+	object = iobj;
+	iobj = 0;
+	vread();
+    } else if (iobj == SPHERE) {
+	if (!inside(g.loc) || athand(SAPPHIRE))
+	    rspeak(42);
+	else {
+	    rspeak(400);
+	    printf("  ");
+	    sloc = g.place[SAPPHIRE];
+	    if ((g.loc_attrib[sloc] % 2 == 0 || enclosed(SAPPHIRE))
+		&& sloc != 200
+		&& !g.place[LAMP] == sloc && g.prop[LAMP] != 0)
+		rspeak(401);
+	    else
+		desclg(sloc);
+	    if (sloc == 239 && !g.flg239) {
+		rspeak(403);
+		g.flg239 = TRUE;
+	    }
+	    printf("  ");
+	    rspeak(402);
+	}
+    } else
+	printf("I see nothing special about the %s?\n", iotxt[iobx]);
+    return;
+}
Index: /trunk/minix/commands/advent/vocab.c
===================================================================
--- /trunk/minix/commands/advent/vocab.c	(revision 9)
+++ /trunk/minix/commands/advent/vocab.c	(revision 9)
@@ -0,0 +1,594 @@
+
+/*
+  look-up vocabulary word in lex-ordered table.  words may have
+  two entries with different codes. if minimum acceptable type
+  = 0, then return minimum of different codes.  last word CANNOT
+  have two entries(due to binary sort).
+  word is the word to look up.
+  type  is the minimum acceptable value,
+  if != 0 return %1000
+*/
+
+#include	<string.h>
+#include	<stdio.h>
+#include	"advent.h"
+#include	"advdec.h"
+
+static _CONST struct wac wc[] = {
+				      "\"spelunker\"", 1016,
+				      "22", 2053,
+				      "22", 3012,
+				      "34", 2053,
+				      "34", 3013,
+				      "4-leafed", 5034,
+				      "7", 2053,
+				      "7", 3011,
+				      "?", 3051,
+				      "above", 29,
+				      "abra", 3050,
+				      "abracd", 3050,
+				      "across", 42,
+				      "alacaz", 3050,
+				      "all", 1109,
+				      "altar", 90,
+				      "and", 6001,
+				      "answer", 2035,
+				      "anvil", 1091,
+				      "ascend", 29,
+				      "at", 4009,
+				      "attack", 2012,
+				      "awaken", 2029,
+				      "awkward", 26,
+				      "axe", 1028,
+				      "back", 8,
+				      "ball", 1120,
+				      "barren", 40,
+				      "bat", 1104,
+				      "bats", 1104,
+				      "batshit", 1104,
+				      "batteries", 1039,
+				      "beans", 1024,
+				      "bear", 1035,
+				      "bed", 16,
+				      "bedquilt", 70,
+				      "bee", 1087,
+				      "beehive", 1097,
+				      "bees", 1087,
+				      "billboard", 1116,
+				      "bird", 1101,
+				      "bitch", 2048,
+				      "black", 5006,
+				      "blast", 2023,
+				      "blow", 2036,
+				      "blowup", 2023,
+				      "boat", 1048,
+				      "book", 1110,
+				      "booth", 1093,
+				      "bottle", 1020,
+				      "box", 1055,
+				      "brass", 5004,
+				      "break", 2028,
+				      "bridge", 89,
+				      "brief", 2026,
+				      "broken", 54,
+				      "broom", 1114,
+				      "brush", 1114,
+				      "brush", 2054,
+				      "building", 12,
+				      "bumble", 1087,
+				      "burn", 2047,
+				      "cage", 1004,
+				      "cake", 1107,	/* value must be
+							   mushrooms + 1 */
+				      "cakes", 1107,
+				      "call", 2038,
+				      "calm", 2010,
+				      "canister", 1118,
+				      "canyon", 25,
+				      "cape", 1047,
+				      "capture", 2001,
+				      "carpet", 1040,
+				      "carry", 2001,
+				      "carving", 1115,
+				      "cask", 1071,
+				      "catch", 2001,
+				      "cave", 67,
+				      "cavern", 73,
+				      "chain", 1064,
+				      "chalice", 1070,
+				      "chant", 2003,
+				      "chasm", 1021,	/* troll bridge */
+				      "chest", 1055,
+				      "chimney", 78,
+				      "clam", 1014,
+				      "click", 85,
+				      "climb", 56,
+				      "cloak", 1047,
+				      "close", 2006,
+				      "clover", 1073,
+				      "cobble", 18,
+				      "coins", 1054,
+				      "comb", 1096,
+				      "complain", 2048,
+				      "continue", 7,
+				      "continue", 2011,
+				      "crack", 33,
+				      "crap", 3106,
+				      "crap!", 3106,
+				      "crawl", 17,
+				      "cross", 69,
+				      "crown", 1066,
+				      "crystal", 5033,
+				      "cup", 1070,
+				      "cupcakes", 1107,
+				      "d", 30,
+				      "dark", 22,
+				      "debris", 51,
+				      "defile", 23,
+				      "depression", 63,
+				      "descend", 30,
+				      "describe", 2052,
+				      "detonate", 2023,
+				      "devour", 2014,
+				      "diagnose", 2051,
+				      "dial", 2039,
+				      "diamond", 1051,
+				      "diamonds", 1051,
+				      "dig", 3066,
+				      "discard", 2002,
+				      "disturb", 2029,
+				      "doff", 2002,
+				      "dog", 1098,
+				      "dome", 35,
+				      "don", 2033,
+				      "door", 1041,	/* giant door */
+				      "down", 30,
+				      "down", 4008,
+				      "downstream", 5,
+				      "downward", 30,
+				      "dragon", 1031,
+				      "drawing", 1029,
+				      "drink", 2015,
+				      "drop", 2002,
+				      "droplet", 1075,
+				      "dump", 2002,
+				      "dust", 2054,
+				      "dwarf", 1017,
+				      "dwarves", 1017,
+				      "e", 43,
+				      "east", 43,
+				      "eat", 2014,
+				      "egg", 1056,
+				      "eggs", 1056,
+				      "elfin", 5019,
+				      "emerald", 1059,
+				      "empty", 2013,
+				      "enter", 3,
+				      "entrance", 64,
+				      "everything", 1109,
+				      "examine", 2052,
+				      "excavate", 3066,
+				      "exit", 11,
+				      "explore", 2011,
+				      "extinguish", 2008,
+				      "fee", 2025,
+				      "fee", 3001,
+				      "feed", 2021,
+				      "fie", 2025,
+				      "fie", 3002,
+				      "fight", 2012,
+				      "figure", 1027,
+				      "fill", 2022,
+				      "find", 2019,
+				      "fissure", 1012,
+				      "fling", 2017,
+				      "floor", 58,
+				      "flower", 1046,
+				      "flowers", 1046,
+				      "foe", 2025,
+				      "foe", 3003,
+				      "follow", 2011,
+				      "foo", 2025,
+				      "foo", 3004,
+				      "food", 1019,
+				      "forcd", 1,
+				      "forest", 6,
+				      "fork", 77,
+				      "forward", 7,
+				      "fountain", 1103,
+				      "four-leafed", 5034,
+				      "free", 2002,
+				      "fresh", 5010,
+				      "from", 4005,
+				      "fuck", 3079,
+				      "fuck!", 3079,
+				      "fum", 2025,
+				      "fum", 3005,
+				      "gate", 2058,
+				      "get", 2044,
+				      "geyser", 1037,	/* same as volcano */
+				      "giant", 27,
+				      "giant", 5029,
+				      "glowing", 5031,
+				      "gnome", 1105,
+				      "go", 2011,
+				      "gold", 1050,
+				      "golden", 5001,
+				      "goto", 2011,
+				      "grab", 2032,
+				      "grail", 1070,
+				      "grate", 1003,
+				      "green", 5032,
+				      "grey", 5032,
+				      "gripe", 2048,
+				      "grotto", 91,
+				      "guano", 1104,
+				      "gully", 13,
+				      "h20", 1081,
+				      "hall", 38,
+				      "headlamp", 1002,
+				      "health", 2051,
+				      "heave", 2017,
+				      "heels", 1067,
+				      "help", 3051,
+				      "hike", 2011,
+				      "hill", 2,
+				      "hit", 2034,
+				      "hive", 1097,
+				      "hocus", 3050,
+				      "hole", 52,
+				      "holy", 5021,
+				      "honey", 1096,
+				      "honeycomb", 1096,
+				      "horn", 1052,
+				      "hound", 1098,
+				      "house", 12,
+				      "hurl", 2017,
+				      "i", 2020,
+				      "ice", 88,
+				      "ignite", 2023,
+				      "in", 19,
+				      "in", 4001,
+				      "insert", 2045,
+				      "inside", 19,
+				      "inside", 4001,
+				      "into", 4001,
+				      "inventory", 2020,
+				      "inward", 19,
+				      "iron", 5011,
+				      "issue", 1016,
+				      "jar", 1020,
+				      "jerk", 2032,
+				      "jewelry", 1053,
+				      "jewels", 1053,
+				      "jump", 39,
+				      "keep", 2001,
+				      "keg", 1071,
+				      "key", 1090,
+				      "keys", 1102,
+				      "kick", 2034,
+				      "kill", 2012,
+				      "knapsack", 1108,
+				      "knife", 1018,
+				      "knives", 1018,
+				      "knoll", 81,
+				      "l", 2052,
+				      "lamp", 1002,
+				      "lantern", 1002,
+				      "lead", 5023,
+				      "leaden", 5023,
+				      "leap", 39,
+				      "leather", 5024,
+				      "leave", 11,
+				      "leave", 2037,
+				      "ledge", 83,
+				      "left", 36,
+				      "light", 1002,
+				      "little", 5012,
+				      "lock", 2049,
+				      "look", 2052,
+				      "lost", 3068,
+				      "low", 24,
+				      "lyre", 1068,
+				      "machine", 1038,
+				      "magazine", 1016,
+				      "main", 76,
+				      "map", 2057,
+				      "message", 1036,
+				      "metal", 5035,
+				      "ming", 5016,
+				      "mirror", 1023,
+				      "mist", 3069,
+				      "moss", 1040,
+				      "mumble", 2003,
+				      "mushroom", 1106,
+				      "mushrooms", 1106,
+				      "n", 45,
+				      "ne", 47,
+				      "nest", 1056,
+				      "north", 45,
+				      "northeast", 47,
+				      "northwest", 50,
+				      "nothing", 2005,
+				      "nowhere", 21,
+				      "nugget", 1050,
+				      "null", 21,
+				      "nw", 50,
+				      "oak", 5022,
+				      "oaken", 5022,
+				      "off", 4006,
+				      "office", 76,
+				      "oil", 1083,	/* in bottle */
+				      "on", 4002,
+				      "onto", 4002,
+				      "onward", 7,
+				      "open", 2004,
+				      "opensesame", 3050,
+				      "oriental", 72,
+				      "out", 11,
+				      "outdoors", 32,
+				      "outside", 11,
+				      "over", 41,
+				      "oyster", 1015,
+				      "pantry", 57,
+				      "passage", 23,
+				      "pause", 2030,
+				      "pearl", 1061,
+				      "persian", 5002,
+				      "peruse", 2027,
+				      "peyote", 1106,
+				      "phone", 1094,
+				      "phonebooth", 1094,
+				      "phuce", 82,
+				      "pick", 2041,
+				      "pillow", 1010,
+				      "pirate", 1030,
+				      "pirloc", 2059,
+				      "piss", 3107,
+				      "piss!", 3107,
+				      "pit", 31,
+				      "placate", 2010,
+				      "plant", 1024,
+				      "platinum", 5017,
+				      "play", 2040,
+				      "plover", 71,
+				      "plugh", 65,
+				      "pocus", 3050,
+				      "pole", 1009,
+				      "pool", 80,
+				      "poster", 1113,
+				      "pottery", 1058,
+				      "pound", 2034,
+				      "pour", 2013,
+				      "pray", 92,
+				      "prayer", 92,
+				      "proceed", 2011,
+				      "pull", 2032,
+				      "punch", 2034,
+				      "put", 2042,
+				      "pyramid", 1060,
+				      "q", 2018,
+				      "quartz", 5036,
+				      "quit", 2018,
+				      "radium", 1119,
+				      "rare", 5018,
+				      "ration", 1019,
+				      "read", 2027,
+				      "refill", 2022,
+				      "release", 2002,
+				      "remove", 2046,
+				      "reply", 2035,
+				      "report", 2048,
+				      "reservoir", 75,
+				      "restore", 2031,
+				      "retreat", 8,
+				      "return", 8,
+				      "right", 37,
+				      "ring", 1072,
+				      "road", 2,
+				      "rock", 1119,
+				      "rock", 15,
+				      "rocks", 1092,
+				      "rocks", 1115,
+				      "rod", 1005,
+				      "room", 59,
+				      "rowboat", 1048,
+				      "rub", 2016,
+				      "ruby", 5020,
+				      "rug", 1062,
+				      "run", 2011,
+				      "rusty", 5028,
+				      "s", 46,
+				      "sack", 1108,
+				      "safe", 1112,
+				      "saint-michel", 93,
+				      "sandwich", 1019,
+				      "sapphire", 1069,
+				      "save", 2030,
+				      "say", 2003,
+				      "score", 2024,
+				      "se", 48,
+				      "secret", 66,
+				      "sesame", 3050,
+				      "shadowy", 5027,
+				      "shake", 2009,
+				      "shards", 1058,
+				      "shatter", 2028,
+				      "shazam", 3050,
+				      "shelf", 83,
+				      "shell", 74,
+				      "shield", 1118,
+				      "ship", 1048,
+				      "shit", 3106,
+				      "shit!", 3106,
+				      "shoes", 1067,
+				      "shut", 2006,
+				      "silk", 5013,
+				      "silken", 5013,
+				      "silver", 5014,
+				      "sing", 2003,
+				      "slab", 61,
+				      "slabroom", 61,
+				      "slay", 2012,
+				      "slide", 79,
+				      "slippers", 1067,
+				      "slit", 60,
+				      "slugs", 1095,
+				      "small", 5012,
+				      "smash", 2028,
+				      "snake", 1011,
+				      "south", 46,
+				      "southeast", 48,
+				      "southwest", 49,
+				      "spelunker", 1016,
+				      "sphere", 1120,
+				      "spices", 1063,
+				      "stair", 10,
+				      "stairs", 10,
+				      "stalagmite", 1026,
+				      "star", 5026,
+				      "statue", 1074,
+				      "steal", 2001,
+				      "steel", 5025,
+				      "steps", 1007,
+				      "steps", 34,
+				      "stick", 1049,
+				      "sticks", 1049,
+				      "stone", 1119,
+				      "stop", 3139,
+				      "stream", 14,
+				      "strike", 2034,
+				      "strum", 2040,
+				      "suggest", 2048,
+				      "surface", 20,
+				      "suspend", 2030,
+				      "sw", 49,
+				      "sweep", 2054,
+				      "swim", 3147,
+				      "swing", 2009,
+				      "sword", 1065,
+				      "tablet", 1013,
+				      "take", 2001,
+				      "tame", 2010,
+				      "tasty", 5030,
+				      "telephone", 1094,
+				      "terse", 2055,
+				      "then", 6002,
+				      "throw", 2017,
+				      "thunder", 84,
+				      "tiny", 5012,
+				      "to", 4004,
+				      "tome", 1110,
+				      "toss", 2017,
+				      "tote", 2001,
+				      "travel", 2011,
+				      "treasure", 5015,
+				      "tree", 1074,
+				      "tree", 3064,
+				      "trees", 3064,
+				      "trident", 1057,
+				      "troll", 1033,
+				      "tube", 1118,
+				      "tunnel", 23,
+				      "turn", 2043,
+				      "u", 29,
+				      "unbrief", 2026,
+				      "unlock", 2050,
+				      "unterse", 2055,
+				      "up", 29,
+				      "up", 4007,
+				      "upon", 4002,
+				      "upstream", 4,
+				      "upward", 29,
+				      "used", 5009,
+				      "utter", 2003,
+				      "valley", 9,
+				      "vase", 1058,
+				      "velvet", 5007,
+				      "vending", 5008,
+				      "view", 28,
+				      "volcano", 1037,
+				      "volume", 1110,
+				      "w", 44,
+				      "wake", 2029,
+				      "waken", 2029,
+				      "walk", 2011,
+				      "wall", 53,
+				      "wall", 1088,	/* in blue grotto */
+				      "wand", 1005,
+				      "water", 1081,	/* in bottle */
+				      "wave", 2009,
+				      "wear", 2033,
+				      "west", 44,
+				      "whack", 2034,
+				      "where", 2019,
+				      "whirl", 80,
+				      "whirlpool", 80,
+				      "whisk", 1114,
+				      "whiskbroom", 1114,
+				      "wicker", 5005,
+				      "wine", 1085,	/* in bottle */
+				      "with", 4003,
+				      "wiz", 2056,
+				      "wolf", 1098,
+				      "wooden", 5003,
+				      "worn", 5009,
+				      "worn-out", 5009,
+				      "wornout", 5009,
+				      "wumpus", 1099,
+				      "xyzzy", 62,
+				      "y2", 55,
+				      "yank", 2032
+};
+
+#define MAXWC	(sizeof(wc) / sizeof(struct wac))
+
+_PROTOTYPE(int binary, (char *));
+
+int vocab(word, type)
+char *word;
+int type;
+{
+    int v1, v2, temp;
+
+    if ((v1 = binary(word)) >= 0) {
+	if (v1 > 0 && strcmp(word, wc[v1 - 1].aword) == 0)
+	    v2 = v1 - 1;
+	else if (v1 < (MAXWC - 1) && strcmp(word, wc[v1 + 1].aword) == 0)
+	    v2 = v1 + 1;
+	else
+	    v2 = v1;
+	if (wc[v1].acode > wc[v2].acode) {
+	    temp = v1;
+	    v1 = v2;
+	    v2 = temp;
+	}
+	if (type <= CLASS(wc[v1].acode))
+	    return (wc[v1].acode);
+	else if (type <= CLASS(wc[v2].acode))
+	    return (wc[v2].acode);
+	else
+	    return (-1);
+    } else
+	return (-1);
+}
+
+int binary(w)
+char *w;
+{
+    int lo, mid, hi, check;
+
+    lo = 0;
+    hi = MAXWC - 1;
+    do {
+	mid = (lo + hi) / 2;
+	check = strcmp(w, wc[mid].aword);
+	if (check == 0)
+	    return (mid);
+	else if (check < 0)
+	    hi = mid - 1;
+	else
+	    lo = mid + 1;
+    } while (lo <= hi);
+    return (-1);
+}
Index: /trunk/minix/commands/ash/Makefile
===================================================================
--- /trunk/minix/commands/ash/Makefile	(revision 9)
+++ /trunk/minix/commands/ash/Makefile	(revision 9)
@@ -0,0 +1,105 @@
+# Makefile for ash.
+
+SRCS=	builtins.c cd.c dirent.c error.c eval.c exec.c expand.c input.c \
+	jobs.c mail.c main.c memalloc.c miscbltin.c mystring.c nodes.c \
+	options.c parser.c redir.c show.c signames.c syntax.c trap.c \
+	output.c var.c
+
+OBJS=	builtins.o cd.o dirent.o error.o eval.o exec.o expand.o input.o \
+	jobs.o mail.o main.o memalloc.o miscbltin.o mystring.o nodes.o \
+	options.o parser.o redir.o show.o signames.o syntax.o trap.o \
+	output.o var.o init.o \
+	bltin/echo.o bltin/expr.o bltin/operators.o bltin/regexp.o
+
+#
+# Set READLINE in shell.h and add -ledit to LIBS if you want to use the
+# editline package by Simmule Turner and Rich Salz.  (The big, bloated
+# and GPL contaminated FSF readline should work too.)
+#
+CPPFLAGS= -DSHELL -I. -D_MINIX -D_POSIX_SOURCE
+CFLAGS=	-wo -i $(CPPFLAGS)
+LIBS=	-ledit
+CC = exec cc
+
+CLEANFILES= $(OBJS) \
+	builtins.c builtins.h init.c mkinit mknodes mksignames mksyntax \
+	nodes.c nodes.h signames.c signames.h syntax.c syntax.h token.def \
+	bltin/operators.h bltin/operators.c
+
+all:	sh
+
+sh:	$(OBJS)
+	$(CC) $(CFLAGS) -o sh $(OBJS) $(LIBS)
+	install -S 100k sh
+
+install:	/usr/bin/ash /usr/bin/sh /bin/sh /bin/bigsh
+
+/usr/bin/ash:	sh
+	install -cs -o bin $? $@
+
+/usr/bin/sh:	/usr/bin/ash
+	install -l $? $@
+
+/bin/sh:	/usr/bin/ash
+	install -lcs $? $@
+
+/bin/bigsh:	/usr/bin/ash
+	install -S 1500000 -lcs $? $@
+
+clean:
+	rm -f $(CLEANFILES) sh core
+
+parser.o: token.def
+
+token.def: mktokens
+	sh mktokens
+
+builtins.c builtins.h: builtins.table shell.h
+	sh mkbuiltins shell.h builtins.table
+
+init.o: mkinit $(SRCS)
+	./mkinit '$(CC) -c $(CFLAGS) init.c' $(SRCS)
+
+mkinit: mkinit.c
+	$(CC) $(CFLAGS) mkinit.c -o $@
+
+nodes.c nodes.h: mknodes nodetypes nodes.c.pat
+	./mknodes nodetypes nodes.c.pat
+
+mknodes: mknodes.c
+	$(CC) $(CFLAGS) mknodes.c -o $@
+
+signames.c signames.h: mksignames
+	./mksignames
+
+mksignames: mksignames.c
+	$(CC) $(CFLAGS) mksignames.c -o $@
+
+syntax.c syntax.h: mksyntax
+	./mksyntax
+
+mksyntax: mksyntax.c parser.h
+	$(CC) $(CFLAGS) mksyntax.c -o $@
+
+bltin/operators.h:	bltin/mkexpr bltin/binary_op bltin/unary_op
+	cd bltin && sh mkexpr
+
+bltin/echo.o:	bltin/echo.c
+	cd bltin && $(CC) -I.. $(CFLAGS) -c echo.c
+
+bltin/expr.o:	bltin/expr.c
+	cd bltin && $(CC) -I.. $(CFLAGS) -c expr.c
+
+bltin/operators.o:	bltin/operators.c
+	cd bltin && $(CC) -I.. $(CFLAGS) -c operators.c
+
+bltin/regexp.o:	bltin/regexp.c
+	cd bltin && $(CC) -I.. $(CFLAGS) -c regexp.c
+
+# Dependencies you say?  This will have to do.
+$(OBJS): error.h eval.h exec.h expand.h init.h input.h \
+	jobs.h machdep.h mail.h main.h memalloc.h mystring.h options.h \
+	output.h parser.h redir.h shell.h trap.h var.h \
+	builtins.h nodes.h signames.h syntax.h
+
+bltin/expr.o bltin/operators.o:	bltin/operators.h
Index: /trunk/minix/commands/ash/TOUR
===================================================================
--- /trunk/minix/commands/ash/TOUR	(revision 9)
+++ /trunk/minix/commands/ash/TOUR	(revision 9)
@@ -0,0 +1,348 @@
+#	@(#)TOUR	5.1 (Berkeley) 3/7/91
+
+                       A Tour through Ash
+
+               Copyright 1989 by Kenneth Almquist.
+
+
+DIRECTORIES:  The subdirectory bltin contains commands which can
+be compiled stand-alone.  The rest of the source is in the main
+ash directory.
+
+SOURCE CODE GENERATORS:  Files whose names begin with "mk" are
+programs that generate source code.  A complete list of these
+programs is:
+
+        program         intput files        generates
+        -------         ------------        ---------
+        mkbuiltins      builtins            builtins.h builtins.c
+        mkinit          *.c                 init.c
+        mknodes         nodetypes           nodes.h nodes.c
+        mksignames          -               signames.h signames.c
+        mksyntax            -               syntax.h syntax.c
+        mktokens            -               token.def
+        bltin/mkexpr    unary_op binary_op  operators.h operators.c
+
+There are undoubtedly too many of these.  Mkinit searches all the
+C source files for entries looking like:
+
+        INIT {
+              x = 1;    /* executed during initialization */
+        }
+
+        RESET {
+              x = 2;    /* executed when the shell does a longjmp
+                           back to the main command loop */
+        }
+
+        SHELLPROC {
+              x = 3;    /* executed when the shell runs a shell procedure */
+        }
+
+It pulls this code out into routines which are when particular
+events occur.  The intent is to improve modularity by isolating
+the information about which modules need to be explicitly
+initialized/reset within the modules themselves.
+
+Mkinit recognizes several constructs for placing declarations in
+the init.c file.
+        INCLUDE "file.h"
+includes a file.  The storage class MKINIT makes a declaration
+available in the init.c file, for example:
+        MKINIT int funcnest;    /* depth of function calls */
+MKINIT alone on a line introduces a structure or union declara-
+tion:
+        MKINIT
+        struct redirtab {
+              short renamed[10];
+        };
+Preprocessor #define statements are copied to init.c without any
+special action to request this.
+
+INDENTATION:  The ash source is indented in multiples of six
+spaces.  The only study that I have heard of on the subject con-
+cluded that the optimal amount to indent is in the range of four
+to six spaces.  I use six spaces since it is not too big a jump
+from the widely used eight spaces.  If you really hate six space
+indentation, use the adjind (source included) program to change
+it to something else.
+
+EXCEPTIONS:  Code for dealing with exceptions appears in
+exceptions.c.  The C language doesn't include exception handling,
+so I implement it using setjmp and longjmp.  The global variable
+exception contains the type of exception.  EXERROR is raised by
+calling error.  EXINT is an interrupt.  EXSHELLPROC is an excep-
+tion which is raised when a shell procedure is invoked.  The pur-
+pose of EXSHELLPROC is to perform the cleanup actions associated
+with other exceptions.  After these cleanup actions, the shell
+can interpret a shell procedure itself without exec'ing a new
+copy of the shell.
+
+INTERRUPTS:  In an interactive shell, an interrupt will cause an
+EXINT exception to return to the main command loop.  (Exception:
+EXINT is not raised if the user traps interrupts using the trap
+command.)  The INTOFF and INTON macros (defined in exception.h)
+provide uninterruptable critical sections.  Between the execution
+of INTOFF and the execution of INTON, interrupt signals will be
+held for later delivery.  INTOFF and INTON can be nested.
+
+MEMALLOC.C:  Memalloc.c defines versions of malloc and realloc
+which call error when there is no memory left.  It also defines a
+stack oriented memory allocation scheme.  Allocating off a stack
+is probably more efficient than allocation using malloc, but the
+big advantage is that when an exception occurs all we have to do
+to free up the memory in use at the time of the exception is to
+restore the stack pointer.  The stack is implemented using a
+linked list of blocks.
+
+STPUTC:  If the stack were contiguous, it would be easy to store
+strings on the stack without knowing in advance how long the
+string was going to be:
+        p = stackptr;
+        *p++ = c;       /* repeated as many times as needed */
+        stackptr = p;
+The folloing three macros (defined in memalloc.h) perform these
+operations, but grow the stack if you run off the end:
+        STARTSTACKSTR(p);
+        STPUTC(c, p);   /* repeated as many times as needed */
+        grabstackstr(p);
+
+We now start a top-down look at the code:
+
+MAIN.C:  The main routine performs some initialization, executes
+the user's profile if necessary, and calls cmdloop.  Cmdloop is
+repeatedly parses and executes commands.
+
+OPTIONS.C:  This file contains the option processing code.  It is
+called from main to parse the shell arguments when the shell is
+invoked, and it also contains the set builtin.  The -i and -j op-
+tions (the latter turns on job control) require changes in signal
+handling.  The routines setjobctl (in jobs.c) and setinteractive
+(in trap.c) are called to handle changes to these options.
+
+PARSING:  The parser code is all in parser.c.  A recursive des-
+cent parser is used.  Syntax tables (generated by mksyntax) are
+used to classify characters during lexical analysis.  There are
+three tables:  one for normal use, one for use when inside single
+quotes, and one for use when inside double quotes.  The tables
+are machine dependent because they are indexed by character vari-
+ables and the range of a char varies from machine to machine.
+
+PARSE OUTPUT:  The output of the parser consists of a tree of
+nodes.  The various types of nodes are defined in the file node-
+types.
+
+Nodes of type NARG are used to represent both words and the con-
+tents of here documents.  An early version of ash kept the con-
+tents of here documents in temporary files, but keeping here do-
+cuments in memory typically results in significantly better per-
+formance.  It would have been nice to make it an option to use
+temporary files for here documents, for the benefit of small
+machines, but the code to keep track of when to delete the tem-
+porary files was complex and I never fixed all the bugs in it.
+(AT&T has been maintaining the Bourne shell for more than ten
+years, and to the best of my knowledge they still haven't gotten
+it to handle temporary files correctly in obscure cases.)
+
+The text field of a NARG structure points to the text of the
+word.  The text consists of ordinary characters and a number of
+special codes defined in parser.h.  The special codes are:
+
+        CTLVAR              Variable substitution
+        CTLENDVAR           End of variable substitution
+        CTLBACKQ            Command substitution
+        CTLBACKQ|CTLQUOTE   Command substitution inside double quotes
+        CTLESC              Escape next character
+
+A variable substitution contains the following elements:
+
+        CTLVAR type name '=' [ alternative-text CTLENDVAR ]
+
+The type field is a single character specifying the type of sub-
+stitution.  The possible types are:
+
+        VSNORMAL            $var
+        VSMINUS             ${var-text}
+        VSMINUS|VSNUL       ${var:-text}
+        VSPLUS              ${var+text}
+        VSPLUS|VSNUL        ${var:+text}
+        VSQUESTION          ${var?text}
+        VSQUESTION|VSNUL    ${var:?text}
+        VSASSIGN            ${var=text}
+        VSASSIGN|VSNUL      ${var=text}
+
+In addition, the type field will have the VSQUOTE flag set if the
+variable is enclosed in double quotes.  The name of the variable
+comes next, terminated by an equals sign.  If the type is not
+VSNORMAL, then the text field in the substitution follows, ter-
+minated by a CTLENDVAR byte.
+
+Commands in back quotes are parsed and stored in a linked list.
+The locations of these commands in the string are indicated by
+CTLBACKQ and CTLBACKQ+CTLQUOTE characters, depending upon whether
+the back quotes were enclosed in double quotes.
+
+The character CTLESC escapes the next character, so that in case
+any of the CTL characters mentioned above appear in the input,
+they can be passed through transparently.  CTLESC is also used to
+escape '*', '?', '[', and '!' characters which were quoted by the
+user and thus should not be used for file name generation.
+
+CTLESC characters have proved to be particularly tricky to get
+right.  In the case of here documents which are not subject to
+variable and command substitution, the parser doesn't insert any
+CTLESC characters to begin with (so the contents of the text
+field can be written without any processing).  Other here docu-
+ments, and words which are not subject to splitting and file name
+generation, have the CTLESC characters removed during the vari-
+able and command substitution phase.  Words which are subject
+splitting and file name generation have the CTLESC characters re-
+moved as part of the file name phase.
+
+EXECUTION:  Command execution is handled by the following files:
+        eval.c     The top level routines.
+        redir.c    Code to handle redirection of input and output.
+        jobs.c     Code to handle forking, waiting, and job control.
+        exec.c     Code to to path searches and the actual exec sys call.
+        expand.c   Code to evaluate arguments.
+        var.c      Maintains the variable symbol table.  Called from expand.c.
+
+EVAL.C:  Evaltree recursively executes a parse tree.  The exit
+status is returned in the global variable exitstatus.  The alter-
+native entry evalbackcmd is called to evaluate commands in back
+quotes.  It saves the result in memory if the command is a buil-
+tin; otherwise it forks off a child to execute the command and
+connects the standard output of the child to a pipe.
+
+JOBS.C:  To create a process, you call makejob to return a job
+structure, and then call forkshell (passing the job structure as
+an argument) to create the process.  Waitforjob waits for a job
+to complete.  These routines take care of process groups if job
+control is defined.
+
+REDIR.C:  Ash allows file descriptors to be redirected and then
+restored without forking off a child process.  This is accom-
+plished by duplicating the original file descriptors.  The redir-
+tab structure records where the file descriptors have be dupli-
+cated to.
+
+EXEC.C:  The routine find_command locates a command, and enters
+the command in the hash table if it is not already there.  The
+third argument specifies whether it is to print an error message
+if the command is not found.  (When a pipeline is set up,
+find_command is called for all the commands in the pipeline be-
+fore any forking is done, so to get the commands into the hash
+table of the parent process.  But to make command hashing as
+transparent as possible, we silently ignore errors at that point
+and only print error messages if the command cannot be found
+later.)
+
+The routine shellexec is the interface to the exec system call.
+
+EXPAND.C:  Arguments are processed in three passes.  The first
+(performed by the routine argstr) performs variable and command
+substitution.  The second (ifsbreakup) performs word splitting
+and the third (expandmeta) performs file name generation.  If the
+"/u" directory is simulated, then when "/u/username" is replaced
+by the user's home directory, the flag "didudir" is set.  This
+tells the cd command that it should print out the directory name,
+just as it would if the "/u" directory were implemented using
+symbolic links.
+
+VAR.C:  Variables are stored in a hash table.  Probably we should
+switch to extensible hashing.  The variable name is stored in the
+same string as the value (using the format "name=value") so that
+no string copying is needed to create the environment of a com-
+mand.  Variables which the shell references internally are preal-
+located so that the shell can reference the values of these vari-
+ables without doing a lookup.
+
+When a program is run, the code in eval.c sticks any environment
+variables which precede the command (as in "PATH=xxx command") in
+the variable table as the simplest way to strip duplicates, and
+then calls "environment" to get the value of the environment.
+There are two consequences of this.  First, if an assignment to
+PATH precedes the command, the value of PATH before the assign-
+ment must be remembered and passed to shellexec.  Second, if the
+program turns out to be a shell procedure, the strings from the
+environment variables which preceded the command must be pulled
+out of the table and replaced with strings obtained from malloc,
+since the former will automatically be freed when the stack (see
+the entry on memalloc.c) is emptied.
+
+BUILTIN COMMANDS:  The procedures for handling these are scat-
+tered throughout the code, depending on which location appears
+most appropriate.  They can be recognized because their names al-
+ways end in "cmd".  The mapping from names to procedures is
+specified in the file builtins, which is processed by the mkbuil-
+tins command.
+
+A builtin command is invoked with argc and argv set up like a
+normal program.  A builtin command is allowed to overwrite its
+arguments.  Builtin routines can call nextopt to do option pars-
+ing.  This is kind of like getopt, but you don't pass argc and
+argv to it.  Builtin routines can also call error.  This routine
+normally terminates the shell (or returns to the main command
+loop if the shell is interactive), but when called from a builtin
+command it causes the builtin command to terminate with an exit
+status of 2.
+
+The directory bltins contains commands which can be compiled in-
+dependently but can also be built into the shell for efficiency
+reasons.  The makefile in this directory compiles these programs
+in the normal fashion (so that they can be run regardless of
+whether the invoker is ash), but also creates a library named
+bltinlib.a which can be linked with ash.  The header file bltin.h
+takes care of most of the differences between the ash and the
+stand-alone environment.  The user should call the main routine
+"main", and #define main to be the name of the routine to use
+when the program is linked into ash.  This #define should appear
+before bltin.h is included; bltin.h will #undef main if the pro-
+gram is to be compiled stand-alone.
+
+CD.C:  This file defines the cd and pwd builtins.  The pwd com-
+mand runs /bin/pwd the first time it is invoked (unless the user
+has already done a cd to an absolute pathname), but then
+remembers the current directory and updates it when the cd com-
+mand is run, so subsequent pwd commands run very fast.  The main
+complication in the cd command is in the docd command, which
+resolves symbolic links into actual names and informs the user
+where the user ended up if he crossed a symbolic link.
+
+SIGNALS:  Trap.c implements the trap command.  The routine set-
+signal figures out what action should be taken when a signal is
+received and invokes the signal system call to set the signal ac-
+tion appropriately.  When a signal that a user has set a trap for
+is caught, the routine "onsig" sets a flag.  The routine dotrap
+is called at appropriate points to actually handle the signal.
+When an interrupt is caught and no trap has been set for that
+signal, the routine "onint" in error.c is called.
+
+OUTPUT:  Ash uses it's own output routines.  There are three out-
+put structures allocated.  "Output" represents the standard out-
+put, "errout" the standard error, and "memout" contains output
+which is to be stored in memory.  This last is used when a buil-
+tin command appears in backquotes, to allow its output to be col-
+lected without doing any I/O through the UNIX operating system.
+The variables out1 and out2 normally point to output and errout,
+respectively, but they are set to point to memout when appropri-
+ate inside backquotes.
+
+INPUT:  The basic input routine is pgetc, which reads from the
+current input file.  There is a stack of input files; the current
+input file is the top file on this stack.  The code allows the
+input to come from a string rather than a file.  (This is for the
+-c option and the "." and eval builtin commands.)  The global
+variable plinno is saved and restored when files are pushed and
+popped from the stack.  The parser routines store the number of
+the current line in this variable.
+
+DEBUGGING:  If DEBUG is defined in shell.h, then the shell will
+write debugging information to the file $HOME/trace.  Most of
+this is done using the TRACE macro, which takes a set of printf
+arguments inside two sets of parenthesis.  Example:
+"TRACE(("n=%d0, n))".  The double parenthesis are necessary be-
+cause the preprocessor can't handle functions with a variable
+number of arguments.  Defining DEBUG also causes the shell to
+generate a core dump if it is sent a quit signal.  The tracing
+code is in show.c.
Index: /trunk/minix/commands/ash/bltin/LICENSE
===================================================================
--- /trunk/minix/commands/ash/bltin/LICENSE	(revision 9)
+++ /trunk/minix/commands/ash/bltin/LICENSE	(revision 9)
@@ -0,0 +1,40 @@
+		    ASH GENERAL PUBLIC LICENSE
+
+  1. You may copy and distribute ash code or code derived from it in
+source or object form, provided that you conspicuously and appropriately
+publish on each copy a valid copyright notice "Copyright 1989 by Kenneth
+Almquist." (or with whatever year is appropriate); keep intact the
+notices on all files that refer to this License Agreement and to the
+absence of any warranty; and give any other recipients of the ash program
+a copy of this License Agreement along with the program.
+
+  2. You may not copy, sublicense, distribute or transfer ash except as
+expressly provided under this License Agreement.  Any attempt otherwise
+to copy, sublicense, distribute or transfer ash is void and your rights
+to use ash under this License agreement shall be automatically terminated.
+However, parties who have received computer software programs from you
+with this License Agreement will not have their licenses terminated so
+long as such parties remain in full compliance.
+
+
+			   NO WARRANTY
+
+  Because ash is licensed free of charge, I provide absolutely no
+warranty, to the extent permitted by applicable state law.  Except
+when otherwise stated in writing, Kenneth Almquist and/or other
+parties provide ash "as is" without warranty of any kind, either
+expressed or implied, including, but not limited to, the implied
+warranties of merchantability and fitness for a particular purpose.
+The entire risk as to the quality and performance of the program is
+with you.  Should the ash program prove defective, you assume the cost
+of all necessary servicing, repair or correction.
+
+ In no event unless required by applicable law will Kenneth Almquist
+and/or any other party who may modify and redistribute ash as permitted
+above, be liable to you for damages, including any lost profits, lost
+monies, or other special, incidental or consequential damages arising
+out of the use or inability to use (including but not limited to loss
+of data or data being rendered inaccurate or losses sustained by third
+parties or a failure of the program to operate with programs provided
+by other parties) the program, even if you have been advised of the
+possibility of such damages, or for any claim by any other party.
Index: /trunk/minix/commands/ash/bltin/binary_op
===================================================================
--- /trunk/minix/commands/ash/bltin/binary_op	(revision 9)
+++ /trunk/minix/commands/ash/bltin/binary_op	(revision 9)
@@ -0,0 +1,25 @@
+# List of binary operators used by test/expr.
+#
+# Copyright 1989 by Kenneth Almquist.  All rights reserved.
+# This file is part of ash, which is distributed under the terms specified
+# by the Ash General Public License.  See the file named LICENSE.
+
+OR1	 -o	1
+OR2	 |	1
+AND1	 -a	2
+AND2	 &	2
+STREQ	 =	4    OP_STRING
+STRNE	 !=	4    OP_STRING
+NEWER	 -newer	4    OP_STRING
+EQ	 -eq	4    OP_INT
+NE	 -ne	4    OP_INT
+GT	 -gt	4    OP_INT
+LT	 -lt	4    OP_INT
+LE	 -le	4    OP_INT
+GE	 -ge	4    OP_INT
+PLUS	 +	5    OP_INT
+MINUS	 -	5    OP_INT
+TIMES	 *	6    OP_INT
+DIVIDE	 /	6    OP_INT
+REM	 %	6    OP_INT
+MATCHPAT :	7    OP_STRING
Index: /trunk/minix/commands/ash/bltin/bltin.h
===================================================================
--- /trunk/minix/commands/ash/bltin/bltin.h	(revision 9)
+++ /trunk/minix/commands/ash/bltin/bltin.h	(revision 9)
@@ -0,0 +1,40 @@
+/*
+ * This file is included by programs which are optionally built into the
+ * shell.  If SHELL is defined, we try to map the standard UNIX library
+ * routines to ash routines using defines.
+ *
+ * Copyright (C) 1989 by Kenneth Almquist.  All rights reserved.
+ * This file is part of ash, which is distributed under the terms specified
+ * by the Ash General Public License.  See the file named LICENSE.
+ */
+
+#include "../shell.h"
+#include "../mystring.h"
+#ifdef SHELL
+#include "../output.h"
+#define stdout out1
+#define stderr out2
+#define printf out1fmt
+#define putc(c, file)	outc(c, file)
+#define putchar(c)	out1c(c)
+#define fprintf outfmt
+#define fputs outstr
+#define fflush flushout
+#define INITARGS(argv)
+#else
+#undef NULL
+#include <stdio.h>
+#undef main
+#define INITARGS(argv)	if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
+#endif
+
+#ifdef __STDC__
+pointer stalloc(int);
+void error(char *, ...);
+#else
+pointer stalloc();
+void error();
+#endif
+
+
+extern char *commandname;
Index: /trunk/minix/commands/ash/bltin/catf.c
===================================================================
--- /trunk/minix/commands/ash/bltin/catf.c	(revision 9)
+++ /trunk/minix/commands/ash/bltin/catf.c	(revision 9)
@@ -0,0 +1,88 @@
+/*
+ * Copy the files given as arguments to the standard output.  The file
+ * name "-" refers to the standard input.
+ *
+ * Copyright (C) 1989 by Kenneth Almquist.  All rights reserved.
+ * This file is part of ash, which is distributed under the terms specified
+ * by the Ash General Public License.  See the file named LICENSE.
+ */
+
+#define main catfcmd
+
+#include "bltin.h"
+#include "../error.h"
+#include <sys/param.h>
+#include <fcntl.h>
+
+
+#ifdef SBUFSIZE
+#define BUFSIZE() SBUFSIZE
+#else
+#ifdef MAXBSIZE
+#define BUFSIZE() MAXBSIZE
+#else
+#define BUFSIZE() BSIZE
+#endif
+#endif
+
+
+main(argc, argv)  char **argv; {
+      char *filename;
+      char *buf = stalloc(BUFSIZE());
+      int fd;
+      int i;
+#ifdef SHELL
+      volatile int input;
+      struct jmploc jmploc;
+      struct jmploc *volatile savehandler;
+#endif
+
+      INITARGS(argv);
+#ifdef SHELL
+      input = -1;
+      if (setjmp(jmploc.loc)) {
+	    close(input);
+	    handler = savehandler;
+	    longjmp(handler, 1);
+      }
+      savehandler = handler;
+      handler = &jmploc;
+#endif
+      while ((filename = *++argv) != NULL) {
+	    if (filename[0] == '-' && filename[1] == '\0') {
+		  fd = 0;
+	    } else {
+#ifdef SHELL
+		  INTOFF;
+		  if ((fd = open(filename, O_RDONLY)) < 0)
+			error("Can't open %s", filename);
+		  input = fd;
+		  INTON;
+#else
+		  if ((fd = open(filename, O_RDONLY)) < 0) {
+			fprintf(stderr, "catf: Can't open %s\n", filename);
+			exit(2);
+		  }
+#endif
+	    }
+	    while ((i = read(fd, buf, BUFSIZE())) > 0) {
+#ifdef SHELL
+		  if (out1 == &memout) {
+			register char *p;
+			for (p = buf ; --i >= 0 ; p++) {
+			      outc(*p, &memout);
+			}
+		  } else {
+			write(1, buf, i);
+		  }
+#else
+		  write(1, buf, i);
+#endif
+	    }
+	    if (fd != 0)
+		  close(fd);
+      }
+#ifdef SHELL
+      handler = savehandler;
+#endif
+}
Index: /trunk/minix/commands/ash/bltin/echo.c
===================================================================
--- /trunk/minix/commands/ash/bltin/echo.c	(revision 9)
+++ /trunk/minix/commands/ash/bltin/echo.c	(revision 9)
@@ -0,0 +1,74 @@
+/*
+ * Echo command.
+ *
+ * Copyright (C) 1989 by Kenneth Almquist.  All rights reserved.
+ * This file is part of ash, which is distributed under the terms specified
+ * by the Ash General Public License.  See the file named LICENSE.
+ */
+
+#define main echocmd
+
+#include "bltin.h"
+
+#undef eflag
+
+
+main(argc, argv)  char **argv; {
+      register char **ap;
+      register char *p;
+      register char c;
+      int count;
+      int nflag = 0;
+#ifndef eflag
+      int eflag = 0;
+#endif
+
+      ap = argv;
+      if (argc)
+	    ap++;
+      if ((p = *ap) != NULL) {
+	    if (equal(p, "--")) {
+		  ap++;
+	    }
+	    if (equal(p, "-n")) {
+		  nflag++;
+		  ap++;
+	    } else if (equal(p, "-e")) {
+#ifndef eflag
+		  eflag++;
+#endif
+		  ap++;
+	    }
+      }
+      while ((p = *ap++) != NULL) {
+	    while ((c = *p++) != '\0') {
+		  if (c == '\\' && eflag) {
+			switch (*p++) {
+			case 'b':  c = '\b';  break;
+			case 'c':  return 0;		/* exit */
+			case 'f':  c = '\f';  break;
+			case 'n':  c = '\n';  break;
+			case 'r':  c = '\r';  break;
+			case 't':  c = '\t';  break;
+			case 'v':  c = '\v';  break;
+			case '\\':  break;		/* c = '\\' */
+			case '0':
+			      c = 0;
+			      count = 3;
+			      while (--count >= 0 && (unsigned)(*p - '0') < 8)
+				    c = (c << 3) + (*p++ - '0');
+			      break;
+			default:
+			      p--;
+			      break;
+			}
+		  }
+		  putchar(c);
+	    }
+	    if (*ap)
+		  putchar(' ');
+      }
+      if (! nflag)
+	    putchar('\n');
+      return 0;
+}
Index: /trunk/minix/commands/ash/bltin/error.c
===================================================================
--- /trunk/minix/commands/ash/bltin/error.c	(revision 9)
+++ /trunk/minix/commands/ash/bltin/error.c	(revision 9)
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 1989 by Kenneth Almquist.  All rights reserved.
+ * This file is part of ash, which is distributed under the terms specified
+ * by the Ash General Public License.  See the file named LICENSE.
+ */
+
+#include <stdio.h>
+
+char *commandname;
+
+
+void
+#ifdef __STDC__
+error(char *msg, ...) {
+#else
+error(msg)
+      char *msg;
+      {
+#endif
+
+      fprintf(stderr, "%s: %s\n", commandname, msg);
+      exit(2);
+}
Index: /trunk/minix/commands/ash/bltin/expr.c
===================================================================
--- /trunk/minix/commands/ash/bltin/expr.c	(revision 9)
+++ /trunk/minix/commands/ash/bltin/expr.c	(revision 9)
@@ -0,0 +1,481 @@
+/*
+ * The expr and test commands.
+ *
+ * Copyright (C) 1989 by Kenneth Almquist.  All rights reserved.
+ * This file is part of ash, which is distributed under the terms specified
+ * by the Ash General Public License.  See the file named LICENSE.
+ */
+
+
+#define main exprcmd
+
+#include "bltin.h"
+#include "operators.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifndef S_ISLNK
+#define lstat		stat
+#define S_ISLNK(mode)	(0)
+#endif
+
+#define STACKSIZE 12
+#define NESTINCR 16
+
+/* data types */
+#define STRING 0
+#define INTEGER 1
+#define BOOLEAN 2
+
+
+/*
+ * This structure hold a value.  The type keyword specifies the type of
+ * the value, and the union u holds the value.  The value of a boolean
+ * is stored in u.num (1 = TRUE, 0 = FALSE).
+ */
+
+struct value {
+      int type;
+      union {
+	    char *string;
+	    long num;
+      } u;
+};
+
+
+struct operator {
+      short op;			/* which operator */
+      short pri;		/* priority of operator */
+};
+
+
+struct filestat {
+      int op;			/* OP_FILE or OP_LFILE */
+      char *name;		/* name of file */
+      int rcode;		/* return code from stat */
+      struct stat stat;		/* status info on file */
+};
+
+
+extern char *match_begin[10];	/* matched string */
+extern short match_length[10];	/* defined in regexp.c */
+extern short number_parens;	/* number of \( \) pairs */
+
+
+#ifdef __STDC__
+int expr_is_false(struct value *);
+void expr_operator(int, struct value *, struct filestat *);
+int lookup_op(char *, char *const*);
+char *re_compile(char *);	/* defined in regexp.c */
+int re_match(char *, char *);	/* defined in regexp.c */
+long atol(const char *);
+#else
+int expr_is_false();
+void expr_operator();
+int lookup_op();
+char *re_compile();	/* defined in regexp.c */
+int re_match();	/* defined in regexp.c */
+long atol();
+#endif
+
+
+
+main(argc, argv)  char **argv; {
+      char **ap;
+      char *opname;
+      char c;
+      char *p;
+      int print;
+      int nest;		/* parenthises nesting */
+      int op;
+      int pri;
+      int skipping;
+      int binary;
+      struct operator opstack[STACKSIZE];
+      struct operator *opsp;
+      struct value valstack[STACKSIZE + 1];
+      struct value *valsp;
+      struct filestat fs;
+
+      INITARGS(argv);
+      c = **argv;
+      print = 1;
+      if (c == 't')
+	    print = 0;
+      else if (c == '[') {
+	    if (! equal(argv[argc - 1], "]"))
+		  error("missing ]");
+	    argv[argc - 1] = NULL;
+	    print = 0;
+      }
+      ap = argv + 1;
+      fs.name = NULL;
+
+      /*
+       * We use operator precedence parsing, evaluating the expression
+       * as we parse it.  Parentheses are handled by bumping up the
+       * priority of operators using the variable "nest."  We use the
+       * variable "skipping" to turn off evaluation temporarily for the
+       * short circuit boolean operators.  (It is important do the short
+       * circuit evaluation because under NFS a stat operation can take
+       * infinitely long.)
+       */
+
+      nest = 0;
+      skipping = 0;
+      opsp = opstack + STACKSIZE;
+      valsp = valstack;
+      if (*ap == NULL) {
+	    valstack[0].type = BOOLEAN;
+	    valstack[0].u.num = 0;
+	    goto done;
+      }
+      for (;;) {
+	    opname = *ap++;
+	    if (opname == NULL)
+syntax:		  error("syntax error");
+	    if (opname[0] == '(' && opname[1] == '\0') {
+		  nest += NESTINCR;
+		  continue;
+	    } else if (*ap && (op = lookup_op(opname, unary_op)) >= 0) {
+		  if (opsp == &opstack[0])
+overflow:		error("Expression too complex");
+		  --opsp;
+		  opsp->op = op;
+		  opsp->pri = op_priority[op] + nest;
+		  continue;
+
+	    } else {
+		  valsp->type = STRING;
+		  valsp->u.string = opname;
+		  valsp++;
+	    }
+	    for (;;) {
+		  opname = *ap++;
+		  if (opname == NULL) {
+			if (nest != 0)
+			      goto syntax;
+			pri = 0;
+			break;
+		  }
+		  if (opname[0] != ')' || opname[1] != '\0') {
+			if ((op = lookup_op(opname, binary_op)) < 0)
+			      goto syntax;
+			op += FIRST_BINARY_OP;
+			pri = op_priority[op] + nest;
+			break;
+		  }
+		  if ((nest -= NESTINCR) < 0)
+			goto syntax;
+	    }
+	    while (opsp < &opstack[STACKSIZE] && opsp->pri >= pri) {
+		  binary = opsp->op;
+		  for (;;) {
+			valsp--;
+			c = op_argflag[opsp->op];
+			if (c == OP_INT) {
+			      if (valsp->type == STRING)
+				    valsp->u.num = atol(valsp->u.string);
+			      valsp->type = INTEGER;
+			} else if (c >= OP_STRING) { /* OP_STRING or OP_FILE */
+			      if (valsp->type == INTEGER) {
+				    p = stalloc(32);
+#ifdef SHELL
+				    fmtstr(p, 32, "%d", valsp->u.num);
+#else
+				    sprintf(p, "%d", valsp->u.num);
+#endif
+				    valsp->u.string = p;
+			      } else if (valsp->type == BOOLEAN) {
+				    if (valsp->u.num)
+					  valsp->u.string = "true";
+				    else
+					  valsp->u.string = "";
+			      }
+			      valsp->type = STRING;
+			      if (c >= OP_FILE
+			       && (fs.op != c
+			           || fs.name == NULL
+			           || ! equal(fs.name, valsp->u.string))) {
+				    fs.op = c;
+				    fs.name = valsp->u.string;
+				    if (c == OP_FILE) {
+					fs.rcode = stat(valsp->u.string,
+								&fs.stat);
+				    } else {
+					fs.rcode = lstat(valsp->u.string,
+								&fs.stat);
+				    }
+			      }
+			}
+			if (binary < FIRST_BINARY_OP)
+			      break;
+			binary = 0;
+		  }
+		  if (! skipping)
+			expr_operator(opsp->op, valsp, &fs);
+		  else if (opsp->op == AND1 || opsp->op == OR1)
+			skipping--;
+		  valsp++;		/* push value */
+		  opsp++;		/* pop operator */
+	    }
+	    if (opname == NULL)
+		  break;
+	    if (opsp == &opstack[0])
+		  goto overflow;
+	    if (op == AND1 || op == AND2) {
+		  op = AND1;
+		  if (skipping || expr_is_false(valsp - 1))
+			skipping++;
+	    }
+	    if (op == OR1 || op == OR2) {
+		  op = OR1;
+		  if (skipping || ! expr_is_false(valsp - 1))
+			skipping++;
+	    }
+	    opsp--;
+	    opsp->op = op;
+	    opsp->pri = pri;
+      }
+done:
+      if (print) {
+	    if (valstack[0].type == STRING)
+		  printf("%s\n", valstack[0].u.string);
+	    else if (valstack[0].type == INTEGER)
+		  printf("%ld\n", valstack[0].u.num);
+	    else if (valstack[0].u.num != 0)
+		  printf("true\n");
+      }
+      return expr_is_false(&valstack[0]);
+}
+
+
+int
+expr_is_false(val)
+      struct value *val;
+      {
+      if (val->type == STRING) {
+	    if (val->u.string[0] == '\0')
+		  return 1;
+      } else {	/* INTEGER or BOOLEAN */
+	    if (val->u.num == 0)
+		  return 1;
+      }
+      return 0;
+}
+
+
+/*
+ * Execute an operator.  Op is the operator.  Sp is the stack pointer;
+ * sp[0] refers to the first operand, sp[1] refers to the second operand
+ * (if any), and the result is placed in sp[0].  The operands are converted
+ * to the type expected by the operator before expr_operator is called.
+ * Fs is a pointer to a structure which holds the value of the last call
+ * to stat, to avoid repeated stat calls on the same file.
+ */
+
+void
+expr_operator(op, sp, fs)
+      int op;
+      struct value *sp;
+      struct filestat *fs;
+      {
+      int i;
+      struct stat st1, st2;
+
+      switch (op) {
+      case NOT:
+	    sp->u.num = expr_is_false(sp);
+	    sp->type = BOOLEAN;
+	    break;
+      case ISREAD:
+	    i = 04;
+	    goto permission;
+      case ISWRITE:
+	    i = 02;
+	    goto permission;
+      case ISEXEC:
+	    i = 01;
+permission:
+	    if (fs->stat.st_uid == geteuid())
+		  i <<= 6;
+	    else if (fs->stat.st_gid == getegid())
+		  i <<= 3;
+	    goto filebit;	/* true if (stat.st_mode & i) != 0 */
+      case ISFILE:
+	    i = S_IFREG;
+	    goto filetype;
+      case ISDIR:
+	    i = S_IFDIR;
+	    goto filetype;
+      case ISCHAR:
+	    i = S_IFCHR;
+	    goto filetype;
+      case ISBLOCK:
+	    i = S_IFBLK;
+	    goto filetype;
+      case ISFIFO:
+#ifdef S_IFIFO
+	    i = S_IFIFO;
+	    goto filetype;
+#else
+	    goto false;
+#endif
+filetype:
+	    if ((fs->stat.st_mode & S_IFMT) == i && fs->rcode >= 0) {
+true:
+		  sp->u.num = 1;
+	    } else {
+false:
+		  sp->u.num = 0;
+	    }
+	    sp->type = BOOLEAN;
+	    break;
+      case ISSETUID:
+	    i = S_ISUID;
+	    goto filebit;
+      case ISSETGID:
+	    i = S_ISGID;
+	    goto filebit;
+      case ISSTICKY:
+	    i = S_ISVTX;
+filebit:
+	    if (fs->stat.st_mode & i && fs->rcode >= 0)
+		  goto true;
+	    goto false;
+      case ISSIZE:
+	    sp->u.num = fs->rcode >= 0? fs->stat.st_size : 0L;
+	    sp->type = INTEGER;
+	    break;
+      case ISLINK1:
+      case ISLINK2:
+	    if (S_ISLNK(fs->stat.st_mode) && fs->rcode >= 0)
+		  goto true;
+	    fs->op = OP_FILE;	/* not a symlink, so expect a -d or so next */
+	    goto false;
+      case NEWER:
+	    if (stat(sp->u.string, &st1) != 0) {
+		  sp->u.num = 0;
+	    } else if (stat((sp + 1)->u.string, &st2) != 0) {
+		  sp->u.num = 1;
+	    } else {
+		  sp->u.num = st1.st_mtime >= st2.st_mtime;
+	    }
+	    sp->type = INTEGER;
+	    break;
+      case ISTTY:
+	    sp->u.num = isatty(sp->u.num);
+	    sp->type = BOOLEAN;
+	    break;
+      case NULSTR:
+	    if (sp->u.string[0] == '\0')
+		  goto true;
+	    goto false;
+      case STRLEN:
+	    sp->u.num = strlen(sp->u.string);
+	    sp->type = INTEGER;
+	    break;
+      case OR1:
+      case AND1:
+	    /*
+	     * These operators are mostly handled by the parser.  If we
+	     * get here it means that both operands were evaluated, so
+	     * the value is the value of the second operand.
+	     */
+	    *sp = *(sp + 1);
+	    break;
+      case STREQ:
+      case STRNE:
+	    i = 0;
+	    if (equal(sp->u.string, (sp + 1)->u.string))
+		  i++;
+	    if (op == STRNE)
+		  i = 1 - i;
+	    sp->u.num = i;
+	    sp->type = BOOLEAN;
+	    break;
+      case EQ:
+	    if (sp->u.num == (sp + 1)->u.num)
+		  goto true;
+	    goto false;
+      case NE:
+	    if (sp->u.num != (sp + 1)->u.num)
+		  goto true;
+	    goto false;
+      case GT:
+	    if (sp->u.num > (sp + 1)->u.num)
+		  goto true;
+	    goto false;
+      case LT:
+	    if (sp->u.num < (sp + 1)->u.num)
+		  goto true;
+	    goto false;
+      case LE:
+	    if (sp->u.num <= (sp + 1)->u.num)
+		  goto true;
+	    goto false;
+      case GE:
+	    if (sp->u.num >= (sp + 1)->u.num)
+		  goto true;
+	    goto false;
+      case PLUS:
+	    sp->u.num += (sp + 1)->u.num;
+	    break;
+      case MINUS:
+	    sp->u.num -= (sp + 1)->u.num;
+	    break;
+      case TIMES:
+	    sp->u.num *= (sp + 1)->u.num;
+	    break;
+      case DIVIDE:
+	    if ((sp + 1)->u.num == 0)
+		  error("Division by zero");
+	    sp->u.num /= (sp + 1)->u.num;
+	    break;
+      case REM:
+	    if ((sp + 1)->u.num == 0)
+		  error("Division by zero");
+	    sp->u.num %= (sp + 1)->u.num;
+	    break;
+      case MATCHPAT:
+	    {
+		  char *pat;
+
+		  pat = re_compile((sp + 1)->u.string);
+		  if (re_match(pat, sp->u.string)) {
+			if (number_parens > 0) {
+			      sp->u.string = match_begin[1];
+			      sp->u.string[match_length[1]] = '\0';
+			} else {
+			      sp->u.num = match_length[0];
+			      sp->type = INTEGER;
+			}
+		  } else {
+			if (number_parens > 0) {
+			      sp->u.string[0] = '\0';
+			} else {
+			      sp->u.num = 0;
+			      sp->type = INTEGER;
+			}
+		  }
+	    }
+	    break;
+      }
+}
+
+
+int
+lookup_op(name, table)
+      char *name;
+      char *const*table;
+      {
+      register char *const*tp;
+      register char const *p;
+      char c = name[1];
+
+      for (tp = table ; (p = *tp) != NULL ; tp++) {
+	    if (p[1] == c && equal(p, name))
+		  return tp - table;
+      }
+      return -1;
+}
Index: /trunk/minix/commands/ash/bltin/line.c
===================================================================
--- /trunk/minix/commands/ash/bltin/line.c	(revision 9)
+++ /trunk/minix/commands/ash/bltin/line.c	(revision 9)
@@ -0,0 +1,27 @@
+/*
+ * The line command.  Reads one line from the standard input and writes it
+ * to the standard output.
+ *
+ * Copyright (C) 1989 by Kenneth Almquist.  All rights reserved.
+ * This file is part of ash, which is distributed under the terms specified
+ * by the Ash General Public License.  See the file named LICENSE.
+ */
+
+#define main linecmd
+
+#include "bltin.h"
+
+
+main(argc, argv)  char **argv; {
+      char c;
+
+      for (;;) {
+	    if (read(0, &c, 1) != 1) {
+		  putchar('\n');
+		  return 1;
+	    }
+	    putchar(c);
+	    if (c == '\n')
+		  return 0;
+      }
+}
Index: /trunk/minix/commands/ash/bltin/makefile.not
===================================================================
--- /trunk/minix/commands/ash/bltin/makefile.not	(revision 9)
+++ /trunk/minix/commands/ash/bltin/makefile.not	(revision 9)
@@ -0,0 +1,71 @@
+# Copyright (C) 1989 by Kenneth Almquist.  All rights reserved.
+# This file is part of ash, which is distributed under the terms specified
+# by the Ash General Public License.  See the file named LICENSE.
+
+LIBFILES=catfcmd.o echocmd.o exprcmd.o linecmd.o nlechocmd.o\
+	operators.o regexp.o
+DEBUG=-g
+CFLAGS=$(DEBUG)
+#CC=gcc
+
+all:$P bltinlib.a catf echo expr line nlecho true umask
+
+bltinlib.a:$P $(LIBFILES)
+	ar rc $@ $(LIBFILES)
+
+catf: catf.c bltin.h ../shell.h ../error.h error.o stalloc.o
+	$(CC) $(CFLAGS) -o $@ catf.c error.o stalloc.o
+
+catfcmd.o: catf.c bltin.h ../shell.h ../error.h
+	$(CC) -DSHELL $(CFLAGS) -c catf.c
+	mv catf.o $@
+
+expr: expr.c bltin.h ../shell.h operators.h operators.o regexp.o error.o stalloc.o
+	$(CC) $(CFLAGS) -o $@ expr.c operators.o regexp.o error.o stalloc.o
+	-rm -f test '['
+	ln expr test
+	ln expr '['
+
+exprcmd.o: expr.c bltin.h ../shell.h operators.h
+	$(CC) -DSHELL $(CFLAGS) -c expr.c
+	mv expr.o $@
+
+operators.c operators.h: unary_op binary_op mkexpr
+	./mkexpr
+
+operators.o: ../shell.h operators.h
+
+regexp.o: bltin.h ../shell.h
+
+echo: echo.c bltin.h ../shell.h
+	$(CC) $(CFLAGS) -o $@ echo.c
+
+echocmd.o: echo.c bltin.h ../shell.h
+	$(CC) -DSHELL $(CFLAGS) -c echo.c
+	mv echo.o $@
+
+line: line.c bltin.h ../shell.h
+	$(CC) $(CFLAGS) -o $@ line.c
+
+linecmd.o: line.c bltin.h ../shell.h
+	$(CC) -DSHELL $(CFLAGS) -c line.c
+	mv line.o $@
+
+nlecho: nlecho.c bltin.h ../shell.h
+	$(CC) $(CFLAGS) -o $@ nlecho.c
+
+nlechocmd.o: nlecho.c bltin.h ../shell.h
+	$(CC) -DSHELL $(CFLAGS) -c nlecho.c
+	mv nlecho.o $@
+
+umask: umask.c bltin.h
+	$(CC) $(CFLAGS) -o $@ umask.c
+
+true:
+	> :
+	chmod 755 :
+	rm -f true
+	ln : true
+
+stalloc.o: ../shell.h
+
Index: /trunk/minix/commands/ash/bltin/mkexpr
===================================================================
--- /trunk/minix/commands/ash/bltin/mkexpr	(revision 9)
+++ /trunk/minix/commands/ash/bltin/mkexpr	(revision 9)
@@ -0,0 +1,66 @@
+# Copyright 1989 by Kenneth Almquist.  All rights reserved.
+#
+# This file is part of ash.  Ash is distributed under the terms specified
+# by the Ash General Public License.  See the file named LICENSE.
+
+# All calls to awk removed, because Minix bawk is deficient.  (kjb)
+
+exec > operators.h
+i=0
+sed -e '/^[^#]/!d' unary_op binary_op | while read line
+do
+	set -$- $line
+	echo "#define $1 $i"
+	i=`expr $i + 1`
+done
+echo
+echo "#define FIRST_BINARY_OP" `sed -e '/^[^#]/!d' unary_op | wc -l`
+echo '
+#define OP_INT 1		/* arguments to operator are integer */
+#define OP_STRING 2		/* arguments to operator are string */
+#define OP_FILE 3		/* argument is a file name */
+#define OP_LFILE 4		/* argument is a file name of a symlink? */
+
+extern char *const unary_op[];
+extern char *const binary_op[];
+extern const char op_priority[];
+extern const char op_argflag[];'
+
+exec > operators.c
+echo '/*
+ * Operators used in the expr/test command.
+ */
+
+#include "../shell.h"
+#include "operators.h"
+
+char *const unary_op[] = {'
+sed -e '/^[^#]/!d
+	s/[ 	][ 	]*/ /g
+	s/^[^ ][^ ]* \([^ ][^ ]*\).*/      "\1",/
+	' unary_op
+echo '      NULL
+};
+
+char *const binary_op[] = {'
+sed -e '/^[^#]/!d
+	s/[ 	][ 	]*/ /g
+	s/^[^ ][^ ]* \([^ ][^ ]*\).*/      "\1",/
+	' binary_op
+echo '      NULL
+};
+
+const char op_priority[] = {'
+sed -e '/^[^#]/!d
+	s/[ 	][ 	]*/ /g
+	s/^[^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\).*/      \1,/
+	' unary_op binary_op
+echo '};
+
+const char op_argflag[] = {'
+sed -e '/^[^#]/!d
+	s/[ 	][ 	]*/ /g
+	s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]*$/& 0/
+	s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\)/      \1,/
+	' unary_op binary_op
+echo '};'
Index: /trunk/minix/commands/ash/bltin/nlecho.c
===================================================================
--- /trunk/minix/commands/ash/bltin/nlecho.c	(revision 9)
+++ /trunk/minix/commands/ash/bltin/nlecho.c	(revision 9)
@@ -0,0 +1,25 @@
+/*
+ * Echo the command argument to the standard output, one line at a time.
+ * This command is useful for debugging th shell and whenever you what
+ * to output strings literally.
+ *
+ * Copyright (C) 1989 by Kenneth Almquist.  All rights reserved.
+ * This file is part of ash, which is distributed under the terms specified
+ * by the Ash General Public License.  See the file named LICENSE.
+ */
+
+
+#define main nlechocmd
+
+#include "bltin.h"
+
+
+main(argc, argv)  char **argv; {
+      register char **ap;
+
+      for (ap = argv + 1 ; *ap ; ap++) {
+	    fputs(*ap, stdout);
+	    putchar('\n');
+      }
+      return 0;
+}
Index: /trunk/minix/commands/ash/bltin/regexp.c
===================================================================
--- /trunk/minix/commands/ash/bltin/regexp.c	(revision 9)
+++ /trunk/minix/commands/ash/bltin/regexp.c	(revision 9)
@@ -0,0 +1,299 @@
+/*
+ * Regular expression matching for expr(1).  Bugs:  The upper bound of
+ * a range specified by the \{ feature cannot be zero.
+ *
+ * Copyright (C) 1989 by Kenneth Almquist.  All rights reserved.
+ * This file is part of ash, which is distributed under the terms specified
+ * by the Ash General Public License.  See the file named LICENSE.
+ */
+
+#include "bltin.h"
+
+
+#define RE_END 0		/* end of regular expression */
+#define RE_LITERAL 1		/* normal character follows */
+#define RE_DOT 2		/* "." */
+#define RE_CCL 3		/* "[...]" */
+#define RE_NCCL 4		/* "[^...]" */
+#define RE_LP 5			/* "\(" */
+#define RE_RP 6			/* "\)" */
+#define RE_MATCHED 7		/* "\digit" */
+#define RE_EOS 8		/* "$" matches end of string */
+#define RE_STAR 9		/* "*" */
+#define RE_RANGE 10		/* "\{num,num\}" */
+
+
+
+char *match_begin[10];
+short match_length[10];
+short number_parens;
+static int match();
+
+
+
+char *
+re_compile(pattern)
+	char *pattern;
+	{
+	register char *p;
+	register char c;
+	char *comp;
+	register char *q;
+	char *begin;
+	char *endp;
+	register int len;
+	int first;
+	int type;
+	char *stackp;
+	char stack[10];
+	int paren_num;
+	int i;
+	char *malloc();
+
+	p = pattern;
+	if (*p == '^')
+		p++;
+	comp = q = malloc(2 * strlen(p) + 1);
+	begin = q;
+	stackp = stack;
+	paren_num = 0;
+	for (;;) {
+		switch (c = *p++) {
+		case '\0':
+			*q = '\0';
+			goto out;
+		case '.':
+			*q++ = RE_DOT;
+			len = 1;
+			break;
+		case '[':
+			begin = q;
+			*q = RE_CCL;
+			if (*p == '^') {
+				*q = RE_NCCL;
+				p++;
+			}
+			q++;
+			first = 1;
+			while (*p != ']' || first == 1) {
+				if (p[1] == '-' && p[2] != ']') {
+					*q++ = '-';
+					*q++ = p[0];
+					*q++ = p[2];
+					p += 3;
+				} else if (*p == '-') {
+					*q++ = '-';
+					*q++ = '-';
+					*q++ = '-';
+					p++;
+				} else {
+					*q++ = *p++;
+				}
+				first = 0;
+			}
+			p++;
+			*q++ = '\0';
+			len = q - begin;
+			break;
+		case '$':
+			if (*p != '\0')
+				goto dft;
+			*q++ = RE_EOS;
+			break;
+		case '*':
+			if (len == 0)
+				goto dft;
+			type = RE_STAR;
+range:
+			i = (type == RE_RANGE)? 3 : 1;
+			endp = q + i;
+			begin = q - len;
+			do {
+				--q;
+				*(q + i) = *q;
+			} while (--len > 0);
+			q = begin;
+			*q++ = type;
+			if (type == RE_RANGE) {
+				i = 0;
+				while ((unsigned)(*p - '0') <= 9)
+					i = 10 * i + (*p++ - '0');
+				*q++ = i;
+				if (*p != ',') {
+					*q++ = i;
+				} else {
+					p++;
+					i = 0;
+					while ((unsigned)(*p - '0') <= 9)
+						i = 10 * i + (*p++ - '0');
+					*q++ = i;
+				}
+				if (*p != '\\' || *++p != '}')
+					error("RE error");
+				p++;
+			}
+			q = endp;
+			break;
+		case '\\':
+			if ((c = *p++) == '(') {
+				if (++paren_num > 9)
+					error("RE error");
+				*q++ = RE_LP;
+				*q++ = paren_num;
+				*stackp++ = paren_num;
+				len = 0;
+			} else if (c == ')') {
+				if (stackp == stack)
+					error("RE error");
+				*q++ = RE_RP;
+				*q++ = *--stackp;
+				len = 0;
+			} else if (c == '{') {
+				type = RE_RANGE;
+				goto range;
+			} else if ((unsigned)(c - '1') < 9) {
+				/* should check validity here */
+				*q++ = RE_MATCHED;
+				*q++ = c - '0';
+				len = 2;
+			} else {
+				goto dft;
+			}
+			break;
+		default:
+dft:			*q++ = RE_LITERAL;
+			*q++ = c;
+			len = 2;
+			break;
+		}
+	}
+out:
+	if (stackp != stack)
+		error("RE error");
+	number_parens = paren_num;
+	return comp;
+}
+
+
+
+re_match(pattern, string)
+	char *pattern;
+	char *string;
+	{
+	char **pp;
+
+	match_begin[0] = string;
+	for (pp = &match_begin[1] ; pp <= &match_begin[9] ; pp++)
+		*pp = 0;
+	return match(pattern, string);
+}
+
+
+
+static
+match(pattern, string)
+	char *pattern;
+	char *string;
+	{
+	register char *p, *q;
+	int counting;
+	int low, high, count;
+	char *curpat;
+	char *start_count;
+	int negate;
+	int found;
+	char *r;
+	int len;
+	char c;
+
+	p = pattern;
+	q = string;
+	counting = 0;
+	for (;;) {
+		if (counting) {
+			if (++count > high)
+				goto bad;
+			p = curpat;
+		}
+		switch (*p++) {
+		case RE_END:
+			match_length[0] = q - match_begin[0];
+			return 1;
+		case RE_LITERAL:
+			if (*q++ != *p++)
+				goto bad;
+			break;
+		case RE_DOT:
+			if (*q++ == '\0')
+				goto bad;
+			break;
+		case RE_CCL:
+			negate = 0;
+			goto ccl;
+		case RE_NCCL:
+			negate = 1;
+ccl:
+			found = 0;
+			c = *q++;
+			while (*p) {
+				if (*p == '-') {
+					if (c >= *++p && c <= *++p)
+						found = 1;
+				} else {
+					if (c == *p)
+						found = 1;
+				}
+				p++;
+			}
+			p++;
+			if (found == negate || c == 0)
+				goto bad;
+			break;
+		case RE_LP:
+			match_begin[*p++] = q;
+			break;
+		case RE_RP:
+			match_length[*p] = q - match_begin[*p];
+			p++;
+			break;
+		case RE_MATCHED:
+			r = match_begin[*p];
+			len = match_length[*p++];
+			while (--len >= 0) {
+				if (*q++ != *r++)
+					goto bad;
+			}
+			break;
+		case RE_EOS:
+			if (*q != '\0')
+				goto bad;
+			break;
+		case RE_STAR:
+			low = 0;
+			high = 32767;
+			goto range;
+		case RE_RANGE:
+			low = *p++;
+			high = *p++;
+			if (high == 0)
+				high = 32767;
+range:
+			curpat = p;
+			start_count = q;
+			count = 0;
+			counting++;
+			break;
+		}
+	}
+bad:
+	if (! counting)
+		return 0;
+	len = 1;
+	if (*curpat == RE_MATCHED)
+		len = match_length[curpat[1]];
+	while (--count >= low) {
+		if (match(p, start_count + count * len))
+			return 1;
+	}
+	return 0;
+}
Index: /trunk/minix/commands/ash/bltin/stalloc.c
===================================================================
--- /trunk/minix/commands/ash/bltin/stalloc.c	(revision 9)
+++ /trunk/minix/commands/ash/bltin/stalloc.c	(revision 9)
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 1989 by Kenneth Almquist.  All rights reserved.
+ * This file is part of ash, which is distributed under the terms specified
+ * by the Ash General Public License.  See the file named LICENSE.
+ */
+
+#include "../shell.h"
+
+
+void error();
+pointer malloc();
+
+
+pointer
+stalloc(nbytes) {
+      register pointer p;
+
+      if ((p = malloc(nbytes)) == NULL)
+	    error("Out of space");
+      return p;
+}
Index: /trunk/minix/commands/ash/bltin/umask.c
===================================================================
--- /trunk/minix/commands/ash/bltin/umask.c	(revision 9)
+++ /trunk/minix/commands/ash/bltin/umask.c	(revision 9)
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 1989 by Kenneth Almquist.  All rights reserved.
+ * This file is part of ash, which is distributed under the terms specified
+ * by the Ash General Public License.  See the file named LICENSE.
+ */
+
+#include <stdio.h>
+
+
+main(argc, argv)  char **argv; {
+      int mask;
+
+      if (argc > 1) {
+	    fprintf(stderr, "umask: only builtin version of umask can set value\n");
+	    exit(2);
+      }
+      printf("%.4o\n", umask(0));
+      return 0;
+}
Index: /trunk/minix/commands/ash/bltin/unary_op
===================================================================
--- /trunk/minix/commands/ash/bltin/unary_op	(revision 9)
+++ /trunk/minix/commands/ash/bltin/unary_op	(revision 9)
@@ -0,0 +1,24 @@
+# List of unary operators used by test/expr.
+#
+# Copyright (C) 1989 by Kenneth Almquist.  All rights reserved.
+# This file is part of ash, which is distributed under the terms specified
+# by the Ash General Public License.  See the file named LICENSE.
+
+NOT	 !	3
+ISREAD	 -r	12   OP_FILE
+ISWRITE  -w	12   OP_FILE
+ISEXEC	 -x	12   OP_FILE
+ISFILE	 -f	12   OP_FILE
+ISDIR	 -d	12   OP_FILE
+ISCHAR	 -c	12   OP_FILE
+ISBLOCK	 -b	12   OP_FILE
+ISFIFO	 -p	12   OP_FILE
+ISSETUID -u	12   OP_FILE
+ISSETGID -g	12   OP_FILE
+ISSTICKY -k	12   OP_FILE
+ISSIZE	 -s	12   OP_FILE
+ISLINK1  -h	12   OP_LFILE
+ISLINK2  -L	12   OP_LFILE
+ISTTY	 -t	12   OP_INT
+NULSTR	 -z	12   OP_STRING
+STRLEN	 -n	12   OP_STRING
Index: /trunk/minix/commands/ash/build
===================================================================
--- /trunk/minix/commands/ash/build	(revision 9)
+++ /trunk/minix/commands/ash/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/ash/builtins.table
===================================================================
--- /trunk/minix/commands/ash/builtins.table	(revision 9)
+++ /trunk/minix/commands/ash/builtins.table	(revision 9)
@@ -0,0 +1,83 @@
+#!/bin/sh -
+#
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)builtins	5.1 (Berkeley) 3/7/91
+
+#
+# This file lists all the builtin commands.  The first column is the name
+# of a C routine.  The -j flag, if present, specifies that this command
+# is to be excluded from systems without job control.  The rest of the line
+# specifies the command name or names used to run the command.  The entry
+# for nullcmd, which is run when the user does not specify a command, must
+# come first.
+#
+# Copyright (C) 1989 by Kenneth Almquist.  All rights reserved.
+# This file is part of ash, which is distributed under the terms specified
+# by the Ash General Public License.  See the file named LICENSE.
+
+bltincmd	command
+#alloccmd	alloc
+bgcmd -j	bg
+breakcmd	break continue
+#catfcmd	catf
+cdcmd		cd chdir
+dotcmd		.
+echocmd		echo
+evalcmd		eval
+execcmd		exec
+exitcmd		exit
+exportcmd	export readonly
+exprcmd		expr test [
+fgcmd -j	fg
+getoptscmd	getopts
+hashcmd		hash
+jobidcmd	jobid
+jobscmd		jobs
+#lccmd		lc
+#linecmd		line
+localcmd	local
+#nlechocmd	nlecho
+pwdcmd		pwd
+readcmd		read
+returncmd	return
+setcmd		set
+setvarcmd	setvar
+shiftcmd	shift
+trapcmd		trap
+truecmd		: true false
+umaskcmd	umask
+unsetcmd	unset
+waitcmd		wait
Index: /trunk/minix/commands/ash/cd.c
===================================================================
--- /trunk/minix/commands/ash/cd.c	(revision 9)
+++ /trunk/minix/commands/ash/cd.c	(revision 9)
@@ -0,0 +1,372 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)cd.c	5.2 (Berkeley) 3/13/91";
+#endif /* not lint */
+
+/*
+ * The cd and pwd commands.
+ */
+
+#include "shell.h"
+#include "var.h"
+#include "nodes.h"	/* for jobs.h */
+#include "jobs.h"
+#include "options.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+
+#ifdef __STDC__
+STATIC int docd(char *, int, int);
+STATIC void updatepwd(char *);
+STATIC void getpwd(void);
+STATIC char *getcomponent(void);
+#else
+STATIC int docd();
+STATIC void updatepwd();
+STATIC void getpwd();
+STATIC char *getcomponent();
+#endif
+
+
+char *curdir;			/* current working directory */
+STATIC char *cdcomppath;
+
+#if UDIR || TILDE
+extern int didudir;		/* set if /u/logname or ~logname expanded */
+#endif
+
+
+int
+cdcmd(argc, argv)  char **argv; {
+	char *dest;
+	char *path;
+	char *p;
+	struct stat statb;
+	char *padvance();
+	int tohome= 0;
+
+	nextopt(nullstr);
+	if ((dest = *argptr) == NULL) {
+		if ((dest = bltinlookup("HOME", 1)) == NULL)
+			error("HOME not set");
+		tohome = 1;
+	}
+	if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
+		path = nullstr;
+	while ((p = padvance(&path, dest)) != NULL) {
+		if (stat(p, &statb) >= 0
+		 && (statb.st_mode & S_IFMT) == S_IFDIR
+		 && docd(p, strcmp(p, dest), tohome) >= 0)
+			return 0;
+	}
+	error("can't cd to %s", dest);
+}
+
+
+/*
+ * Actually do the chdir.  If the name refers to symbolic links, we
+ * compute the actual directory name before doing the cd.  In an
+ * interactive shell, print the directory name if "print" is nonzero
+ * or if the name refers to a symbolic link.  We also print the name
+ * if "/u/logname" was expanded in it, since this is similar to a
+ * symbolic link.  (The check for this breaks if the user gives the
+ * cd command some additional, unused arguments.)
+ */
+
+#if SYMLINKS == 0
+STATIC int
+docd(dest, print, tohome)
+	char *dest;
+	{
+#if UDIR || TILDE
+	if (didudir)
+		print = 1;
+#endif
+	INTOFF;
+	if (chdir(dest) < 0) {
+		INTON;
+		return -1;
+	}
+	updatepwd(dest);
+	INTON;
+	if (print && iflag)
+		out1fmt("%s\n", stackblock());
+	return 0;
+}
+
+#else
+
+
+
+STATIC int
+docd(dest, print, tohome)
+	char *dest;
+	{
+	register char *p;
+	register char *q;
+	char *symlink;
+	char *component;
+	struct stat statb;
+	int first;
+	int i;
+
+	TRACE(("docd(\"%s\", %d, %d) called\n", dest, print, tohome));
+#if UDIR || TILDE
+	if (didudir)
+		print = 1;
+#endif
+
+top:
+	cdcomppath = dest;
+	STARTSTACKSTR(p);
+	if (*dest == '/') {
+		STPUTC('/', p);
+		cdcomppath++;
+	}
+	first = 1;
+	while ((q = getcomponent()) != NULL) {
+		if (q[0] == '\0' || q[0] == '.' && q[1] == '\0')
+			continue;
+		if (! first)
+			STPUTC('/', p);
+		first = 0;
+		component = q;
+		while (*q)
+			STPUTC(*q++, p);
+		if (equal(component, ".."))
+			continue;
+		STACKSTRNUL(p);
+		if (lstat(stackblock(), &statb) < 0)
+			error("lstat %s failed", stackblock());
+		if ((statb.st_mode & S_IFMT) != S_IFLNK)
+			continue;
+
+		/* Hit a symbolic link.  We have to start all over again. */
+		print = 1;
+		STPUTC('\0', p);
+		symlink = grabstackstr(p);
+		i = (int)statb.st_size + 2;		/* 2 for '/' and '\0' */
+		if (cdcomppath != NULL)
+			i += strlen(cdcomppath);
+		p = stalloc(i);
+		if (readlink(symlink, p, (int)statb.st_size) < 0) {
+			error("readlink %s failed", stackblock());
+		}
+		if (cdcomppath != NULL) {
+			p[(int)statb.st_size] = '/';
+			scopy(cdcomppath, p + (int)statb.st_size + 1);
+		} else {
+			p[(int)statb.st_size] = '\0';
+		}
+		if (p[0] != '/') {	/* relative path name */
+			char *r;
+			q = r = symlink;
+			while (*q) {
+				if (*q++ == '/')
+					r = q;
+			}
+			*r = '\0';
+			dest = stalloc(strlen(symlink) + strlen(p) + 1);
+			scopy(symlink, dest);
+			strcat(dest, p);
+		} else {
+			dest = p;
+		}
+		goto top;
+	}
+	STPUTC('\0', p);
+	p = grabstackstr(p);
+	INTOFF;
+	/* The empty string is not a legal argument to chdir on a POSIX 1003.1 
+	 * system. */
+	if (p[0] != '\0' && chdir(p) < 0) {
+		INTON;
+		return -1;
+	}
+	updatepwd(p);
+	INTON;
+	if (print && !tohome && iflag)
+		out1fmt("%s\n", p);
+	return 0;
+}
+#endif /* SYMLINKS */
+
+
+
+/*
+ * Get the next component of the path name pointed to by cdcomppath.
+ * This routine overwrites the string pointed to by cdcomppath.
+ */
+
+STATIC char *
+getcomponent() {
+	register char *p;
+	char *start;
+
+	if ((p = cdcomppath) == NULL)
+		return NULL;
+	start = cdcomppath;
+	while (*p != '/' && *p != '\0')
+		p++;
+	if (*p == '\0') {
+		cdcomppath = NULL;
+	} else {
+		*p++ = '\0';
+		cdcomppath = p;
+	}
+	return start;
+}
+
+
+
+/*
+ * Update curdir (the name of the current directory) in response to a
+ * cd command.  We also call hashcd to let the routines in exec.c know
+ * that the current directory has changed.
+ */
+
+void hashcd();
+
+STATIC void
+updatepwd(dir)
+	char *dir;
+	{
+	char *new;
+	char *p;
+
+	hashcd();				/* update command hash table */
+	cdcomppath = stalloc(strlen(dir) + 1);
+	scopy(dir, cdcomppath);
+	STARTSTACKSTR(new);
+	if (*dir != '/') {
+		if (curdir == NULL)
+			return;
+		p = curdir;
+		while (*p)
+			STPUTC(*p++, new);
+		if (p[-1] == '/')
+			STUNPUTC(new);
+	}
+	while ((p = getcomponent()) != NULL) {
+		if (equal(p, "..")) {
+			while (new > stackblock() && (STUNPUTC(new), *new) != '/');
+		} else if (*p != '\0' && ! equal(p, ".")) {
+			STPUTC('/', new);
+			while (*p)
+				STPUTC(*p++, new);
+		}
+	}
+	if (new == stackblock())
+		STPUTC('/', new);
+	STACKSTRNUL(new);
+	if (curdir)
+		ckfree(curdir);
+	curdir = savestr(stackblock());
+}
+
+
+
+int
+pwdcmd(argc, argv)  char **argv; {
+	getpwd();
+	out1str(curdir);
+	out1c('\n');
+	return 0;
+}
+
+
+
+/*
+ * Run /bin/pwd to find out what the current directory is.  We suppress
+ * interrupts throughout most of this, but the user can still break out
+ * of it by killing the pwd program.  If we already know the current
+ * directory, this routine returns immediately.
+ */
+
+#define MAXPWD 256
+
+STATIC void
+getpwd() {
+	char buf[MAXPWD];
+	char *p;
+	int i;
+	int status;
+	struct job *jp;
+	int pip[2];
+
+	if (curdir)
+		return;
+	INTOFF;
+	if (pipe(pip) < 0)
+		error("Pipe call failed");
+	jp = makejob((union node *)NULL, 1);
+	if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
+		close(pip[0]);
+		if (pip[1] != 1) {
+			close(1);
+			copyfd(pip[1], 1);
+			close(pip[1]);
+		}
+		execl("/bin/pwd", "pwd", (char *)0);
+		error("Cannot exec /bin/pwd");
+	}
+	close(pip[1]);
+	pip[1] = -1;
+	p = buf;
+	while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0
+	     || i == -1 && errno == EINTR) {
+		if (i > 0)
+			p += i;
+	}
+	close(pip[0]);
+	pip[0] = -1;
+	status = waitforjob(jp);
+	if (status != 0)
+		error((char *)0);
+	if (i < 0 || p == buf || p[-1] != '\n')
+		error("pwd command failed");
+	p[-1] = '\0';
+	curdir = savestr(buf);
+	INTON;
+}
Index: /trunk/minix/commands/ash/dirent.c
===================================================================
--- /trunk/minix/commands/ash/dirent.c	(revision 9)
+++ /trunk/minix/commands/ash/dirent.c	(revision 9)
@@ -0,0 +1,194 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)dirent.c	5.1 (Berkeley) 3/7/91";
+#endif /* not lint */
+
+#include "shell.h"	/* definitions for pointer, NULL, DIRENT, and BSD */
+
+#if ! DIRENT
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#ifndef S_ISDIR				/* macro to test for directory file */
+#define	S_ISDIR(mode)		(((mode) & S_IFMT) == S_IFDIR)
+#endif
+
+#ifdef BSD
+
+#ifdef __STDC__
+int stat(char *, struct stat *);
+#else
+int stat();
+#endif
+
+
+/*
+ * The BSD opendir routine doesn't check that what is being opened is a
+ * directory, so we have to include the check in a wrapper routine.
+ */
+
+#undef opendir
+
+DIR *
+myopendir(dirname)
+	char *dirname;			/* name of directory */
+	{
+	struct stat statb;
+
+	if (stat(dirname, &statb) != 0 || ! S_ISDIR(statb.st_mode)) {
+		errno = ENOTDIR;
+		return NULL;		/* not a directory */
+	}
+	return opendir(dirname);
+}
+
+#else /* not BSD */
+
+/*
+ * Dirent routines for old style file systems.
+ */
+
+#ifdef __STDC__
+pointer malloc(unsigned);
+void free(pointer);
+int open(char *, int, ...);
+int close(int);
+int fstat(int, struct stat *);
+#else
+pointer malloc();
+void free();
+int open();
+int close();
+int fstat();
+#endif
+
+
+DIR *
+opendir(dirname)
+	char		*dirname;	/* name of directory */
+	{
+	register DIR	*dirp;		/* -> malloc'ed storage */
+	register int	fd;		/* file descriptor for read */
+	struct stat	statb;		/* result of fstat() */
+
+#ifdef O_NDELAY
+	fd = open(dirname, O_RDONLY|O_NDELAY);
+#else
+	fd = open(dirname, O_RDONLY);
+#endif
+	if (fd < 0)
+		return NULL;		/* errno set by open() */
+
+	if (fstat(fd, &statb) != 0 || !S_ISDIR(statb.st_mode)) {
+		(void)close(fd);
+		errno = ENOTDIR;
+		return NULL;		/* not a directory */
+	}
+
+	if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
+		(void)close(fd);
+		errno = ENOMEM;
+		return NULL;		/* not enough memory */
+	}
+
+	dirp->dd_fd = fd;
+	dirp->dd_nleft = 0;		/* refill needed */
+
+	return dirp;
+}
+
+
+
+int
+closedir(dirp)
+	register DIR *dirp;		/* stream from opendir() */
+	{
+	register int fd;
+
+	if (dirp == NULL) {
+		errno = EFAULT;
+		return -1;			/* invalid pointer */
+	}
+
+	fd = dirp->dd_fd;
+	free((pointer)dirp);
+	return close(fd);
+}
+
+
+
+struct dirent *
+readdir(dirp)
+	register DIR *dirp;		/* stream from opendir() */
+	{
+	register struct direct *dp;
+	register char *p, *q;
+	register int i;
+
+	do {
+		if ((dirp->dd_nleft -= sizeof (struct direct)) < 0) {
+			if ((i = read(dirp->dd_fd,
+					   (char *)dirp->dd_buf,
+					   DIRBUFENT*sizeof(struct direct))) <= 0) {
+				if (i == 0)
+					errno = 0;	/* unnecessary */
+				return NULL;		/* EOF or error */
+			}
+			dirp->dd_loc = dirp->dd_buf;
+			dirp->dd_nleft = i - sizeof (struct direct);
+		}
+		dp = dirp->dd_loc++;
+	} while (dp->d_ino == 0);
+	dirp->dd_entry.d_ino = dp->d_ino;
+
+	/* now copy the name, nul terminating it */
+	p = dp->d_name;
+	q = dirp->dd_entry.d_name;
+	i = DIRSIZ;
+	while (--i >= 0 && *p != '\0')
+		*q++ = *p++;
+	*q = '\0';
+	return &dirp->dd_entry;
+}
+
+#endif /* BSD */
+#endif /* DIRENT */
Index: /trunk/minix/commands/ash/error.c
===================================================================
--- /trunk/minix/commands/ash/error.c	(revision 9)
+++ /trunk/minix/commands/ash/error.c	(revision 9)
@@ -0,0 +1,252 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)error.c	5.1 (Berkeley) 3/7/91";
+#endif /* not lint */
+
+/*
+ * Errors and exceptions.
+ */
+
+#include "shell.h"
+#include "main.h"
+#include "options.h"
+#include "output.h"
+#include "error.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef __STDC__
+#include "stdarg.h"
+#else
+#include <varargs.h>	
+#endif
+#include <errno.h>
+
+
+/*
+ * Code to handle exceptions in C.
+ */
+
+struct jmploc *handler;
+int exception;
+volatile int suppressint;
+volatile int intpending;
+char *commandname;
+
+
+/*
+ * Called to raise an exception.  Since C doesn't include exceptions, we
+ * just do a longjmp to the exception handler.  The type of exception is
+ * stored in the global variable "exception".
+ */
+
+void
+exraise(e) {
+	if (handler == NULL)
+		abort();
+	exception = e;
+	longjmp(handler->loc, 1);
+}
+
+
+/*
+ * Called from trap.c when a SIGINT is received.  (If the user specifies
+ * that SIGINT is to be trapped or ignored using the trap builtin, then
+ * this routine is not called.)  Suppressint is nonzero when interrupts
+ * are held using the INTOFF macro.  The call to _exit is necessary because
+ * there is a short period after a fork before the signal handlers are
+ * set to the appropriate value for the child.  (The test for iflag is
+ * just defensive programming.)
+ */
+
+void
+onint() {
+	if (suppressint) {
+		intpending++;
+		return;
+	}
+	intpending = 0;
+#ifdef BSD
+	sigsetmask(0);
+#endif
+	if (rootshell && iflag)
+		exraise(EXINT);
+	else
+		_exit(128 + SIGINT);
+}
+
+
+
+void
+error2(a, b)
+	char *a, *b;
+	{
+	error("%s: %s", a, b);
+}
+
+
+/*
+ * Error is called to raise the error exception.  If the first argument
+ * is not NULL then error prints an error message using printf style
+ * formatting.  It then raises the error exception.
+ */
+
+#ifdef __STDC__
+void
+error(char *msg, ...) {
+#else
+void
+error(va_alist)
+	va_dcl
+	{
+	char *msg;
+#endif
+	va_list ap;
+
+	CLEAR_PENDING_INT;
+	INTOFF;
+#ifdef __STDC__
+	va_start(ap, msg);
+#else
+	va_start(ap);
+	msg = va_arg(ap, char *);
+#endif
+#if DEBUG
+	if (msg)
+		TRACE(("error(\"%s\") pid=%d\n", msg, getpid()));
+	else
+		TRACE(("error(NULL) pid=%d\n", getpid()));
+#endif
+	if (msg) {
+		if (commandname)
+			outfmt(&errout, "%s: ", commandname);
+		doformat(&errout, msg, ap);
+		out2c('\n');
+	}
+	va_end(ap);
+	flushall();
+	exraise(EXERROR);
+}
+
+
+#ifdef notdef	/* These strange error messages only confuse. -- kjb */
+/*
+ * Table of error messages.
+ */
+
+struct errname {
+	short errcode;		/* error number */
+	short action;		/* operation which encountered the error */
+	char *msg;		/* text describing the error */
+};
+
+
+#define ALL (E_OPEN|E_CREAT|E_EXEC)
+
+STATIC const struct errname errormsg[] = {
+	EINTR, ALL,	"interrupted",
+	EACCES, ALL,	"permission denied",
+	EIO, ALL,		"I/O error",
+	ENOENT, E_OPEN,	"no such file",
+	ENOENT, E_CREAT,	"directory nonexistent",
+	ENOENT, E_EXEC,	"not found",
+	ENOTDIR, E_OPEN,	"no such file",
+	ENOTDIR, E_CREAT,	"directory nonexistent",
+	ENOTDIR, E_EXEC,	"not found",
+	ENOEXEC, ALL,	"not an executable",
+	EISDIR, ALL,	"is a directory",
+/*    EMFILE, ALL,	"too many open files", */
+	ENFILE, ALL,	"file table overflow",
+	ENOSPC, ALL,	"file system full",
+#ifdef EDQUOT
+	EDQUOT, ALL,	"disk quota exceeded",
+#endif
+#ifdef ENOSR
+	ENOSR, ALL,	"no streams resources",
+#endif
+	ENXIO, ALL,	"no such device or address",
+	EROFS, ALL,	"read-only file system",
+	ETXTBSY, ALL,	"text busy",
+#ifdef SYSV
+	EAGAIN, E_EXEC,	"not enough memory",
+#endif
+	ENOMEM, ALL,	"not enough memory",
+#ifdef ENOLINK
+	ENOLINK, ALL,	"remote access failed",
+#endif
+#ifdef EMULTIHOP
+	EMULTIHOP, ALL,	"remote access failed",
+#endif
+#ifdef ECOMM
+	ECOMM, ALL,	"remote access failed",
+#endif
+#ifdef ESTALE
+	ESTALE, ALL,	"remote access failed",
+#endif
+#ifdef ETIMEDOUT
+	ETIMEDOUT, ALL,	"remote access failed",
+#endif
+#ifdef ELOOP
+	ELOOP, ALL,	"symbolic link loop",
+#endif
+	E2BIG, E_EXEC,	"argument list too long",
+#ifdef ELIBACC
+	ELIBACC, E_EXEC,	"shared library missing",
+#endif
+	0, 0,		NULL
+};
+
+
+/*
+ * Return a string describing an error.  The returned string may be a
+ * pointer to a static buffer that will be overwritten on the next call.
+ * Action describes the operation that got the error.
+ */
+
+char *
+errmsg(e, action) {
+	const struct errname *ep;
+	static char buf[12];
+
+	for (ep = errormsg ; ep->errcode ; ep++) {
+		if (ep->errcode == e && (ep->action & action) != 0)
+			return ep->msg;
+	}
+	fmtstr(buf, sizeof buf, "error %d", e);
+	return buf;
+}
+#endif
Index: /trunk/minix/commands/ash/error.h
===================================================================
--- /trunk/minix/commands/ash/error.h	(revision 9)
+++ /trunk/minix/commands/ash/error.h	(revision 9)
@@ -0,0 +1,116 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)error.h	5.1 (Berkeley) 3/7/91
+ */
+
+/*
+ * Types of operations (passed to the errmsg routine).
+ */
+
+#define E_OPEN 01	/* opening a file */
+#define E_CREAT 02	/* creating a file */
+#define E_EXEC 04	/* executing a program */
+
+
+/*
+ * We enclose jmp_buf in a structure so that we can declare pointers to
+ * jump locations.  The global variable handler contains the location to
+ * jump to when an exception occurs, and the global variable exception
+ * contains a code identifying the exeception.  To implement nested
+ * exception handlers, the user should save the value of handler on entry
+ * to an inner scope, set handler to point to a jmploc structure for the
+ * inner scope, and restore handler on exit from the scope.
+ */
+
+#include <setjmp.h>
+
+struct jmploc {
+	jmp_buf loc;
+};
+
+extern struct jmploc *handler;
+extern int exception;
+
+/* exceptions */
+#define EXINT 0		/* SIGINT received */
+#define EXERROR 1	/* a generic error */
+#define EXSHELLPROC 2	/* execute a shell procedure */
+
+
+/*
+ * These macros allow the user to suspend the handling of interrupt signals
+ * over a period of time.  This is similar to SIGHOLD to or sigblock, but
+ * much more efficient and portable.  (But hacking the kernel is so much
+ * more fun than worrying about efficiency and portability. :-))
+ */
+
+extern volatile int suppressint;
+extern volatile int intpending;
+extern char *commandname;	/* name of command--printed on error */
+
+#define INTOFF suppressint++
+#define INTON if (--suppressint == 0 && intpending) onint(); else
+#define FORCEINTON {suppressint = 0; if (intpending) onint();}
+#define CLEAR_PENDING_INT intpending = 0
+#define int_pending() intpending
+
+#ifdef __STDC__
+void exraise(int);
+void onint(void);
+void error2(char *, char *);
+void error(char *, ...);
+char *errmsg(int, int);
+#else
+void exraise();
+void onint();
+void error2();
+void error();
+char *errmsg();
+#endif
+
+/* Errmsg uses confusingly different messages.  Prefer strerror().  -- kjb */
+#define errmsg(errno, action)	strerror(errno)
+
+
+/*
+ * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
+ * so we use _setjmp instead.
+ */
+
+#ifdef BSD
+#define setjmp(jmploc)	_setjmp(jmploc)
+#define longjmp(jmploc, val)	_longjmp(jmploc, val)
+#endif
Index: /trunk/minix/commands/ash/eval.c
===================================================================
--- /trunk/minix/commands/ash/eval.c	(revision 9)
+++ /trunk/minix/commands/ash/eval.c	(revision 9)
@@ -0,0 +1,939 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)eval.c	5.3 (Berkeley) 4/12/91";
+#endif /* not lint */
+
+/*
+ * Evaluate a command.
+ */
+
+#include "shell.h"
+#include "nodes.h"
+#include "syntax.h"
+#include "expand.h"
+#include "parser.h"
+#include "jobs.h"
+#include "eval.h"
+#include "builtins.h"
+#include "options.h"
+#include "exec.h"
+#include "redir.h"
+#include "input.h"
+#include "output.h"
+#include "trap.h"
+#include "var.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+#include <sys/types.h>
+#include <signal.h>
+
+
+/* flags in argument to evaltree */
+#define EV_EXIT 01		/* exit after evaluating tree */
+#define EV_TESTED 02		/* exit status is checked; ignore -e flag */
+#define EV_BACKCMD 04		/* command executing within back quotes */
+
+
+/* reasons for skipping commands (see comment on breakcmd routine) */
+#define SKIPBREAK 1
+#define SKIPCONT 2
+#define SKIPFUNC 3
+
+MKINIT int evalskip;		/* set if we are skipping commands */
+STATIC int skipcount;		/* number of levels to skip */
+MKINIT int loopnest;		/* current loop nesting level */
+int funcnest;			/* depth of function calls */
+
+
+char *commandname;
+struct strlist *cmdenviron;
+int exitstatus;			/* exit status of last command */
+int oexitstatus;		/* saved exit status */
+
+
+#ifdef __STDC__
+STATIC void evalloop(union node *);
+STATIC void evalfor(union node *);
+STATIC void evalcase(union node *, int);
+STATIC void evalsubshell(union node *, int);
+STATIC void expredir(union node *);
+STATIC void evalpipe(union node *);
+STATIC void evalcommand(union node *, int, struct backcmd *);
+STATIC void prehash(union node *);
+#else
+STATIC void evalloop();
+STATIC void evalfor();
+STATIC void evalcase();
+STATIC void evalsubshell();
+STATIC void expredir();
+STATIC void evalpipe();
+STATIC void evalcommand();
+STATIC void prehash();
+#endif
+
+
+
+/*
+ * Called to reset things after an exception.
+ */
+
+#ifdef mkinit
+INCLUDE "eval.h"
+
+RESET {
+	evalskip = 0;
+	loopnest = 0;
+	funcnest = 0;
+}
+
+SHELLPROC {
+	exitstatus = 0;
+}
+#endif
+
+
+
+/*
+ * The eval commmand.
+ */
+
+evalcmd(argc, argv)  
+	char **argv; 
+{
+        char *p;
+        char *concat;
+        char **ap;
+
+        if (argc > 1) {
+                p = argv[1];
+                if (argc > 2) {
+                        STARTSTACKSTR(concat);
+                        ap = argv + 2;
+                        for (;;) {
+                                while (*p)
+                                        STPUTC(*p++, concat);
+                                if ((p = *ap++) == NULL)
+                                        break;
+                                STPUTC(' ', concat);
+                        }
+                        STPUTC('\0', concat);
+                        p = grabstackstr(concat);
+                }
+                evalstring(p);
+        }
+        return exitstatus;
+}
+
+
+/*
+ * Execute a command or commands contained in a string.
+ */
+
+void
+evalstring(s)
+	char *s;
+	{
+	union node *n;
+	struct stackmark smark;
+
+	setstackmark(&smark);
+	setinputstring(s, 1);
+	while ((n = parsecmd(0)) != NEOF) {
+		evaltree(n, 0);
+		popstackmark(&smark);
+	}
+	popfile();
+	popstackmark(&smark);
+}
+
+
+
+/*
+ * Evaluate a parse tree.  The value is left in the global variable
+ * exitstatus.
+ */
+
+void
+evaltree(n, flags)
+	union node *n;
+	{
+	if (n == NULL) {
+		TRACE(("evaltree(NULL) called\n"));
+		return;
+	}
+	TRACE(("evaltree(0x%x: %d) called\n", (int)n, n->type));
+	switch (n->type) {
+	case NSEMI:
+		evaltree(n->nbinary.ch1, 0);
+		if (evalskip)
+			goto out;
+		evaltree(n->nbinary.ch2, flags);
+		break;
+	case NAND:
+		evaltree(n->nbinary.ch1, EV_TESTED);
+		if (evalskip || exitstatus != 0)
+			goto out;
+		evaltree(n->nbinary.ch2, flags);
+		break;
+	case NOR:
+		evaltree(n->nbinary.ch1, EV_TESTED);
+		if (evalskip || exitstatus == 0)
+			goto out;
+		evaltree(n->nbinary.ch2, flags);
+		break;
+	case NREDIR:
+		expredir(n->nredir.redirect);
+		redirect(n->nredir.redirect, REDIR_PUSH);
+		evaltree(n->nredir.n, flags);
+		popredir();
+		break;
+	case NSUBSHELL:
+		evalsubshell(n, flags);
+		break;
+	case NBACKGND:
+		evalsubshell(n, flags);
+		break;
+	case NIF: {
+		int status = 0; 
+
+		evaltree(n->nif.test, EV_TESTED);
+		if (evalskip)
+			goto out;
+		if (exitstatus == 0) {
+			evaltree(n->nif.ifpart, flags);
+			status = exitstatus;
+		} else if (n->nif.elsepart) {
+			evaltree(n->nif.elsepart, flags);
+			status = exitstatus;
+		}
+		exitstatus = status;
+		break;
+	}
+	case NWHILE:
+	case NUNTIL:
+		evalloop(n);
+		break;
+	case NFOR:
+		evalfor(n);
+		break;
+	case NCASE:
+		evalcase(n, flags);
+		break;
+	case NDEFUN:
+		defun(n->narg.text, n->narg.next);
+		exitstatus = 0;
+		break;
+	case NPIPE:
+		evalpipe(n);
+		break;
+	case NCMD:
+		evalcommand(n, flags, (struct backcmd *)NULL);
+		break;
+	default:
+		out1fmt("Node type = %d\n", n->type);
+		flushout(&output);
+		break;
+	}
+out:
+	if (pendingsigs)
+		dotrap();
+	if ((flags & EV_EXIT) || (eflag && exitstatus
+	  && !(flags & EV_TESTED) && (n->type == NCMD ||
+	  n->type == NSUBSHELL))) {
+		exitshell(exitstatus);
+	}
+}
+
+
+STATIC void
+evalloop(n)
+	union node *n;
+	{
+	int status;
+
+	loopnest++;
+	status = 0;
+	for (;;) {
+		evaltree(n->nbinary.ch1, EV_TESTED);
+		if (evalskip) {
+skipping:	  if (evalskip == SKIPCONT && --skipcount <= 0) {
+				evalskip = 0;
+				continue;
+			}
+			if (evalskip == SKIPBREAK && --skipcount <= 0)
+				evalskip = 0;
+			break;
+		}
+		if (n->type == NWHILE) {
+			if (exitstatus != 0)
+				break;
+		} else {
+			if (exitstatus == 0)
+				break;
+		}
+		evaltree(n->nbinary.ch2, 0);
+		status = exitstatus;
+		if (evalskip)
+			goto skipping;
+	}
+	loopnest--;
+	exitstatus = status;
+}
+
+
+
+STATIC void
+evalfor(n)
+	union node *n;
+	{
+	struct arglist arglist;
+	union node *argp;
+	struct strlist *sp;
+	struct stackmark smark;
+
+	setstackmark(&smark);
+	arglist.lastp = &arglist.list;
+	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
+		oexitstatus = exitstatus;
+		expandarg(argp, &arglist, 1);
+		if (evalskip)
+			goto out;
+	}
+	*arglist.lastp = NULL;
+
+	exitstatus = 0;
+	loopnest++;
+	for (sp = arglist.list ; sp ; sp = sp->next) {
+		setvar(n->nfor.var, sp->text, 0);
+		evaltree(n->nfor.body, 0);
+		if (evalskip) {
+			if (evalskip == SKIPCONT && --skipcount <= 0) {
+				evalskip = 0;
+				continue;
+			}
+			if (evalskip == SKIPBREAK && --skipcount <= 0)
+				evalskip = 0;
+			break;
+		}
+	}
+	loopnest--;
+out:
+	popstackmark(&smark);
+}
+
+
+
+STATIC void
+evalcase(n, flags)
+	union node *n;
+	{
+	union node *cp;
+	union node *patp;
+	struct arglist arglist;
+	struct stackmark smark;
+
+	setstackmark(&smark);
+	arglist.lastp = &arglist.list;
+        oexitstatus = exitstatus;
+	expandarg(n->ncase.expr, &arglist, 0);
+	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
+		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
+			if (casematch(patp, arglist.list->text)) {
+				if (evalskip == 0) {
+					evaltree(cp->nclist.body, flags);
+				}
+				goto out;
+			}
+		}
+	}
+out:
+	popstackmark(&smark);
+}
+
+
+
+/*
+ * Kick off a subshell to evaluate a tree.
+ */
+
+STATIC void
+evalsubshell(n, flags)
+	union node *n;
+	{
+	struct job *jp;
+	int backgnd = (n->type == NBACKGND);
+
+	expredir(n->nredir.redirect);
+	jp = makejob(n, 1);
+	if (forkshell(jp, n, backgnd) == 0) {
+		if (backgnd)
+			flags &=~ EV_TESTED;
+		redirect(n->nredir.redirect, 0);
+		evaltree(n->nredir.n, flags | EV_EXIT);	/* never returns */
+	}
+	if (! backgnd) {
+		INTOFF;
+		exitstatus = waitforjob(jp);
+		INTON;
+	}
+}
+
+
+
+/*
+ * Compute the names of the files in a redirection list.
+ */
+
+STATIC void
+expredir(n)
+	union node *n;
+	{
+	register union node *redir;
+
+	for (redir = n ; redir ; redir = redir->nfile.next) {
+		oexitstatus = exitstatus;
+		if (redir->type == NFROM
+		 || redir->type == NTO
+		 || redir->type == NAPPEND) {
+			struct arglist fn;
+			fn.lastp = &fn.list;
+			expandarg(redir->nfile.fname, &fn, 0);
+			redir->nfile.expfname = fn.list->text;
+		}
+	}
+}
+
+
+
+/*
+ * Evaluate a pipeline.  All the processes in the pipeline are children
+ * of the process creating the pipeline.  (This differs from some versions
+ * of the shell, which make the last process in a pipeline the parent
+ * of all the rest.)
+ */
+
+STATIC void
+evalpipe(n)
+	union node *n;
+	{
+	struct job *jp;
+	struct nodelist *lp;
+	int pipelen;
+	int prevfd;
+	int pip[2];
+
+	TRACE(("evalpipe(0x%x) called\n", (int)n));
+	pipelen = 0;
+	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
+		pipelen++;
+	INTOFF;
+	jp = makejob(n, pipelen);
+	prevfd = -1;
+	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
+		prehash(lp->n);
+		pip[1] = -1;
+		if (lp->next) {
+			if (pipe(pip) < 0) {
+				close(prevfd);
+				error("Pipe call failed");
+			}
+		}
+		if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
+			INTON;
+			if (prevfd > 0) {
+				close(0);
+				copyfd(prevfd, 0);
+				close(prevfd);
+			}
+			if (pip[1] >= 0) {
+				close(pip[0]);
+				if (pip[1] != 1) {
+					close(1);
+					copyfd(pip[1], 1);
+					close(pip[1]);
+				}
+			}
+			evaltree(lp->n, EV_EXIT);
+		}
+		if (prevfd >= 0)
+			close(prevfd);
+		prevfd = pip[0];
+		close(pip[1]);
+	}
+	INTON;
+	if (n->npipe.backgnd == 0) {
+		INTOFF;
+		exitstatus = waitforjob(jp);
+		TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
+		INTON;
+	}
+}
+
+
+
+/*
+ * Execute a command inside back quotes.  If it's a builtin command, we
+ * want to save its output in a block obtained from malloc.  Otherwise
+ * we fork off a subprocess and get the output of the command via a pipe.
+ * Should be called with interrupts off.
+ */
+
+void
+evalbackcmd(n, result)
+	union node *n;
+	struct backcmd *result;
+	{
+	int pip[2];
+	struct job *jp;
+	struct stackmark smark;		/* unnecessary */
+
+	setstackmark(&smark);
+	result->fd = -1;
+	result->buf = NULL;
+	result->nleft = 0;
+	result->jp = NULL;
+	if (n == NULL) {
+		/* `` */
+	} else
+	if (n->type == NCMD) {
+                exitstatus = oexitstatus;
+		evalcommand(n, EV_BACKCMD, result);
+	} else {
+		if (pipe(pip) < 0)
+			error("Pipe call failed");
+		jp = makejob(n, 1);
+		if (forkshell(jp, n, FORK_NOJOB) == 0) {
+			FORCEINTON;
+			close(pip[0]);
+			if (pip[1] != 1) {
+				close(1);
+				copyfd(pip[1], 1);
+				close(pip[1]);
+			}
+			evaltree(n, EV_EXIT);
+		}
+		close(pip[1]);
+		result->fd = pip[0];
+		result->jp = jp;
+	}
+	popstackmark(&smark);
+	TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
+		result->fd, result->buf, result->nleft, result->jp));
+}
+
+
+
+/*
+ * Execute a simple command.
+ */
+
+STATIC void
+evalcommand(cmd, flags, backcmd)
+	union node *cmd;
+	struct backcmd *backcmd;
+	{
+	struct stackmark smark;
+	union node *argp;
+	struct arglist arglist;
+	struct arglist varlist;
+	char **argv;
+	int argc;
+	char **envp;
+	int varflag;
+	struct strlist *sp;
+	register char *p;
+	int mode;
+	int pip[2];
+	struct cmdentry cmdentry;
+	struct job *jp;
+	struct jmploc jmploc;
+	struct jmploc *volatile savehandler;
+	char *volatile savecmdname;
+	volatile struct shparam saveparam;
+	struct localvar *volatile savelocalvars;
+	volatile int e;
+	char *lastarg;
+
+	/* First expand the arguments. */
+	TRACE(("evalcommand(0x%x, %d) called\n", (int)cmd, flags));
+	setstackmark(&smark);
+	arglist.lastp = &arglist.list;
+	varlist.lastp = &varlist.list;
+	varflag = 1;
+        oexitstatus = exitstatus;
+	exitstatus = 0;
+	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
+		p = argp->narg.text;
+		if (varflag && is_name(*p)) {
+			do {
+				p++;
+			} while (is_in_name(*p));
+			if (*p == '=') {
+				expandarg(argp, &varlist, 0);
+				continue;
+			}
+		}
+		expandarg(argp, &arglist, 1);
+		varflag = 0;
+	}
+	*arglist.lastp = NULL;
+	*varlist.lastp = NULL;
+	expredir(cmd->ncmd.redirect);
+	argc = 0;
+	for (sp = arglist.list ; sp ; sp = sp->next)
+		argc++;
+	argv = stalloc(sizeof (char *) * (argc + 1));
+	for (sp = arglist.list ; sp ; sp = sp->next)
+		*argv++ = sp->text;
+	*argv = NULL;
+	lastarg = NULL;
+	if (iflag && funcnest == 0 && argc > 0)
+		lastarg = argv[-1];
+	argv -= argc;
+
+	/* Print the command if xflag is set. */
+	if (xflag == 1) {
+		outc('+', &errout);
+		for (sp = varlist.list ; sp ; sp = sp->next) {
+			outc(' ', &errout);
+			out2str(sp->text);
+		}
+		for (sp = arglist.list ; sp ; sp = sp->next) {
+			outc(' ', &errout);
+			out2str(sp->text);
+		}
+		outc('\n', &errout);
+		flushout(&errout);
+	}
+
+	/* Now locate the command. */
+	if (argc == 0) {
+		cmdentry.cmdtype = CMDBUILTIN;
+		cmdentry.u.index = BLTINCMD;
+	} else {
+		find_command(argv[0], &cmdentry, 1);
+		if (cmdentry.cmdtype == CMDUNKNOWN) {	/* command not found */
+			exitstatus = 2;
+			flushout(&errout);
+			popstackmark(&smark);
+			return;
+		}
+		/* implement the bltin builtin here */
+		if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
+			for (;;) {
+				argv++;
+				if (--argc == 0)
+					break;
+				if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
+					outfmt(&errout, "%s: not found\n", *argv);
+					exitstatus = 2;
+					flushout(&errout);
+					popstackmark(&smark);
+					return;
+				}
+				if (cmdentry.u.index != BLTINCMD)
+					break;
+			}
+		}
+	}
+
+	/* Fork off a child process if necessary. */
+	if (cmd->ncmd.backgnd
+	 || cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0
+	 || (flags & EV_BACKCMD) != 0
+	    && (cmdentry.cmdtype != CMDBUILTIN
+		 || cmdentry.u.index == DOTCMD
+		 || cmdentry.u.index == EVALCMD)) {
+		jp = makejob(cmd, 1);
+		mode = cmd->ncmd.backgnd;
+		if (flags & EV_BACKCMD) {
+			mode = FORK_NOJOB;
+			if (pipe(pip) < 0)
+				error("Pipe call failed");
+		}
+		if (forkshell(jp, cmd, mode) != 0)
+			goto parent;	/* at end of routine */
+		if (flags & EV_BACKCMD) {
+			FORCEINTON;
+			close(pip[0]);
+			if (pip[1] != 1) {
+				close(1);
+				copyfd(pip[1], 1);
+				close(pip[1]);
+			}
+		}
+		flags |= EV_EXIT;
+	}
+
+	/* This is the child process if a fork occurred. */
+	/* Execute the command. */
+	if (cmdentry.cmdtype == CMDFUNCTION) {
+		trputs("Shell function:  ");  trargs(argv);
+		redirect(cmd->ncmd.redirect, REDIR_PUSH);
+		saveparam = shellparam;
+		shellparam.malloc = 0;
+		shellparam.nparam = argc - 1;
+		shellparam.p = argv + 1;
+		shellparam.optnext = NULL;
+		INTOFF;
+		savelocalvars = localvars;
+		localvars = NULL;
+		INTON;
+		if (setjmp(jmploc.loc)) {
+			if (exception == EXSHELLPROC)
+				freeparam((struct shparam *)&saveparam);
+			else {
+				freeparam(&shellparam);
+				shellparam = saveparam;
+			}
+			poplocalvars();
+			localvars = savelocalvars;
+			handler = savehandler;
+			longjmp(handler->loc, 1);
+		}
+		savehandler = handler;
+		handler = &jmploc;
+		for (sp = varlist.list ; sp ; sp = sp->next)
+			mklocal(sp->text);
+		funcnest++;
+		if (flags & EV_TESTED)
+			evaltree(cmdentry.u.func, EV_TESTED);
+		else
+			evaltree(cmdentry.u.func, 0);
+		funcnest--;
+		INTOFF;
+		poplocalvars();
+		localvars = savelocalvars;
+		freeparam(&shellparam);
+		shellparam = saveparam;
+		handler = savehandler;
+		popredir();
+		INTON;
+		if (evalskip == SKIPFUNC) {
+			evalskip = 0;
+			skipcount = 0;
+		}
+		if (flags & EV_EXIT)
+			exitshell(exitstatus);
+	} else if (cmdentry.cmdtype == CMDBUILTIN) {
+		trputs("builtin command:  ");  trargs(argv);
+		mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
+		if (flags == EV_BACKCMD) {
+			memout.nleft = 0;
+			memout.nextc = memout.buf;
+			memout.bufsize = 64;
+			mode |= REDIR_BACKQ;
+		}
+		redirect(cmd->ncmd.redirect, mode);
+		savecmdname = commandname;
+		cmdenviron = varlist.list;
+		e = -1;
+		if (setjmp(jmploc.loc)) {
+			e = exception;
+			exitstatus = (e == EXINT)? SIGINT+128 : 2;
+			goto cmddone;
+		}
+		savehandler = handler;
+		handler = &jmploc;
+		commandname = argv[0];
+		argptr = argv + 1;
+		optptr = NULL;			/* initialize nextopt */
+		exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
+		flushall();
+cmddone:
+		out1 = &output;
+		out2 = &errout;
+		freestdout();
+		if (e != EXSHELLPROC) {
+			commandname = savecmdname;
+			if (flags & EV_EXIT) {
+				exitshell(exitstatus);
+			}
+		}
+		handler = savehandler;
+		if (e != -1) {
+			if (e != EXERROR || cmdentry.u.index == BLTINCMD
+					       || cmdentry.u.index == DOTCMD
+					       || cmdentry.u.index == EVALCMD
+					       || cmdentry.u.index == EXECCMD)
+				exraise(e);
+			FORCEINTON;
+		}
+		if (cmdentry.u.index != EXECCMD)
+			popredir();
+		if (flags == EV_BACKCMD) {
+			backcmd->buf = memout.buf;
+			backcmd->nleft = memout.nextc - memout.buf;
+			memout.buf = NULL;
+		}
+	} else {
+		trputs("normal command:  ");  trargs(argv);
+		clearredir();
+		redirect(cmd->ncmd.redirect, 0);
+		if (varlist.list) {
+			p = stalloc(strlen(pathval()) + 1);
+			scopy(pathval(), p);
+		} else {
+			p = pathval();
+		}
+		for (sp = varlist.list ; sp ; sp = sp->next)
+			setvareq(sp->text, VEXPORT|VSTACK);
+		envp = environment();
+		shellexec(argv, envp, p, cmdentry.u.index);
+		/*NOTREACHED*/
+	}
+	goto out;
+
+parent:	/* parent process gets here (if we forked) */
+	if (mode == 0) {	/* argument to fork */
+		INTOFF;
+		exitstatus = waitforjob(jp);
+		INTON;
+	} else if (mode == 2) {
+		backcmd->fd = pip[0];
+		close(pip[1]);
+		backcmd->jp = jp;
+	}
+
+out:
+	if (lastarg)
+		setvar("_", lastarg, 0);
+	popstackmark(&smark);
+}
+
+
+
+/*
+ * Search for a command.  This is called before we fork so that the
+ * location of the command will be available in the parent as well as
+ * the child.  The check for "goodname" is an overly conservative
+ * check that the name will not be subject to expansion.
+ */
+
+STATIC void
+prehash(n)
+	union node *n;
+	{
+	struct cmdentry entry;
+
+	if (n->type == NCMD && goodname(n->ncmd.args->narg.text))
+		find_command(n->ncmd.args->narg.text, &entry, 0);
+}
+
+
+
+/*
+ * Builtin commands.  Builtin commands whose functions are closely
+ * tied to evaluation are implemented here.
+ */
+
+/*
+ * No command given, or a bltin command with no arguments.  Set the
+ * specified variables.
+ */
+
+bltincmd(argc, argv)  char **argv; {
+	listsetvar(cmdenviron);
+	return exitstatus;
+}
+
+
+/*
+ * Handle break and continue commands.  Break, continue, and return are
+ * all handled by setting the evalskip flag.  The evaluation routines
+ * above all check this flag, and if it is set they start skipping
+ * commands rather than executing them.  The variable skipcount is
+ * the number of loops to break/continue, or the number of function
+ * levels to return.  (The latter is always 1.)  It should probably
+ * be an error to break out of more loops than exist, but it isn't
+ * in the standard shell so we don't make it one here.
+ */
+
+breakcmd(argc, argv)  char **argv; {
+	int n;
+
+	n = 1;
+	if (argc > 1)
+		n = number(argv[1]);
+	if (n > loopnest)
+		n = loopnest;
+	if (n > 0) {
+		evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
+		skipcount = n;
+	}
+	return 0;
+}
+
+
+/*
+ * The return command.
+ */
+
+returncmd(argc, argv)  char **argv; {
+	int ret;
+
+	ret = oexitstatus;
+	if (argc > 1)
+		ret = number(argv[1]);
+	if (funcnest) {
+		evalskip = SKIPFUNC;
+		skipcount = 1;
+	}
+	return ret;
+}
+
+
+truecmd(argc, argv)  char **argv; {
+	return strcmp(argv[0], "false") == 0 ? 1 : 0;
+}
+
+
+execcmd(argc, argv)  char **argv; {
+	if (argc > 1) {
+		iflag = 0;		/* exit on error */
+		setinteractive(0);
+#if JOBS
+		jflag = 0;
+		setjobctl(0);
+#endif
+		shellexec(argv + 1, environment(), pathval(), 0);
+
+	}
+	return 0;
+}
Index: /trunk/minix/commands/ash/eval.h
===================================================================
--- /trunk/minix/commands/ash/eval.h	(revision 9)
+++ /trunk/minix/commands/ash/eval.h	(revision 9)
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)eval.h	5.2 (Berkeley) 4/12/91
+ */
+
+extern char *commandname;	/* currently executing command */
+extern int exitstatus;		/* exit status of last command */
+extern struct strlist *cmdenviron;  /* environment for builtin command */
+
+
+struct backcmd {		/* result of evalbackcmd */
+	int fd;			/* file descriptor to read from */
+	char *buf;		/* buffer */
+	int nleft;		/* number of chars in buffer */
+	struct job *jp;		/* job structure for command */
+};
+
+
+#ifdef __STDC__
+void evalstring(char *);
+union node;	/* BLETCH for ansi C */
+void evaltree(union node *, int);
+void evalbackcmd(union node *, struct backcmd *);
+#else
+void evalstring();
+void evaltree();
+void evalbackcmd();
+#endif
+
+/* in_function returns nonzero if we are currently evaluating a function */
+#define in_function()	funcnest
+extern int funcnest;
Index: /trunk/minix/commands/ash/exec.c
===================================================================
--- /trunk/minix/commands/ash/exec.c	(revision 9)
+++ /trunk/minix/commands/ash/exec.c	(revision 9)
@@ -0,0 +1,824 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)exec.c	5.2 (Berkeley) 3/13/91";
+#endif /* not lint */
+
+/*
+ * When commands are first encountered, they are entered in a hash table.
+ * This ensures that a full path search will not have to be done for them
+ * on each invocation.
+ *
+ * We should investigate converting to a linear search, even though that
+ * would make the command name "hash" a misnomer.
+ */
+
+#include "shell.h"
+#include "main.h"
+#include "nodes.h"
+#include "parser.h"
+#include "redir.h"
+#include "eval.h"
+#include "exec.h"
+#include "builtins.h"
+#include "var.h"
+#include "options.h"
+#include "input.h"
+#include "output.h"
+#include "syntax.h"
+#include "memalloc.h"
+#include "error.h"
+#include "init.h"
+#include "mystring.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+
+
+#define CMDTABLESIZE 31		/* should be prime */
+#define ARB 1			/* actual size determined at run time */
+
+
+
+struct tblentry {
+	struct tblentry *next;	/* next entry in hash chain */
+	union param param;	/* definition of builtin function */
+	short cmdtype;		/* index identifying command */
+	char rehash;		/* if set, cd done since entry created */
+	char cmdname[ARB];	/* name of command */
+};
+
+
+STATIC struct tblentry *cmdtable[CMDTABLESIZE];
+STATIC int builtinloc = -1;		/* index in path of %builtin, or -1 */
+
+
+#ifdef __STDC__
+STATIC void tryexec(char *, char **, char **);
+STATIC void execinterp(char **, char **);
+STATIC void printentry(struct tblentry *);
+STATIC void clearcmdentry(int);
+STATIC struct tblentry *cmdlookup(char *, int);
+STATIC void delete_cmd_entry(void);
+#else
+STATIC void tryexec();
+STATIC void execinterp();
+STATIC void printentry();
+STATIC void clearcmdentry();
+STATIC struct tblentry *cmdlookup();
+STATIC void delete_cmd_entry();
+#endif
+
+
+
+/*
+ * Exec a program.  Never returns.  If you change this routine, you may
+ * have to change the find_command routine as well.
+ */
+
+void
+shellexec(argv, envp, path, index)
+	char **argv, **envp;
+	char *path;
+	{
+	char *cmdname;
+	int e;
+
+	if (strchr(argv[0], '/') != NULL) {
+		tryexec(argv[0], argv, envp);
+		e = errno;
+	} else {
+		e = ENOENT;
+		while ((cmdname = padvance(&path, argv[0])) != NULL) {
+			if (--index < 0 && pathopt == NULL) {
+				tryexec(cmdname, argv, envp);
+				if (errno != ENOENT && errno != ENOTDIR)
+					e = errno;
+			}
+			stunalloc(cmdname);
+		}
+	}
+	error2(argv[0], errmsg(e, E_EXEC));
+}
+
+
+STATIC void
+tryexec(cmd, argv, envp)
+	char *cmd;
+	char **argv;
+	char **envp;
+	{
+	int e;
+	char *p;
+
+#ifdef SYSV
+	do {
+		execve(cmd, argv, envp);
+	} while (errno == EINTR);
+#else
+	execve(cmd, argv, envp);
+#endif
+#if HASHBANG
+	e = errno;
+	if (e == ENOEXEC) {
+		initshellproc();
+		setinputfile(cmd, 0);
+		commandname = arg0 = savestr(argv[0]);
+#ifndef BSD
+		pgetc(); pungetc();		/* fill up input buffer */
+		p = parsenextc;
+		if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
+			argv[0] = cmd;
+			execinterp(argv, envp);
+		}
+#endif
+		setparam(argv + 1);
+		exraise(EXSHELLPROC);
+		/*NOTREACHED*/
+	}
+	errno = e;
+#endif
+}
+
+
+#if !defined(BSD) && HASHBANG
+/*
+ * Execute an interpreter introduced by "#!", for systems where this
+ * feature has not been built into the kernel.  If the interpreter is
+ * the shell, return (effectively ignoring the "#!").  If the execution
+ * of the interpreter fails, exit.
+ *
+ * This code peeks inside the input buffer in order to avoid actually
+ * reading any input.  It would benefit from a rewrite.
+ */
+
+#define NEWARGS 5
+
+STATIC void
+execinterp(argv, envp)
+	char **argv, **envp;
+	{
+	int n;
+	char *inp;
+	char *outp;
+	char c;
+	char *p;
+	char **ap;
+	char *newargs[NEWARGS];
+	int i;
+	char **ap2;
+	char **new;
+
+	n = parsenleft - 2;
+	inp = parsenextc + 2;
+	ap = newargs;
+	for (;;) {
+		while (--n >= 0 && (*inp == ' ' || *inp == '\t'))
+			inp++;
+		if (n < 0)
+			goto bad;
+		if ((c = *inp++) == '\n')
+			break;
+		if (ap == &newargs[NEWARGS])
+bad:		  error("Bad #! line");
+		STARTSTACKSTR(outp);
+		do {
+			STPUTC(c, outp);
+		} while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n');
+		STPUTC('\0', outp);
+		n++, inp--;
+		*ap++ = grabstackstr(outp);
+	}
+#if !__minix
+	if (ap == newargs + 1) {	/* if no args, maybe no exec is needed */
+		p = newargs[0];
+		for (;;) {
+			if (equal(p, "sh") || equal(p, "ash")) {
+				return;
+			}
+			while (*p != '/') {
+				if (*p == '\0')
+					goto break2;
+				p++;
+			}
+			p++;
+		}
+break2:;
+	}
+#endif
+	i = (char *)ap - (char *)newargs;		/* size in bytes */
+	if (i == 0)
+		error("Bad #! line");
+	for (ap2 = argv ; *ap2++ != NULL ; );
+	new = ckmalloc(i + ((char *)ap2 - (char *)argv));
+	ap = newargs, ap2 = new;
+	while ((i -= sizeof (char **)) >= 0)
+		*ap2++ = *ap++;
+	ap = argv;
+	while (*ap2++ = *ap++);
+	shellexec(new, envp, pathval(), 0);
+}
+#endif
+
+
+
+/*
+ * Do a path search.  The variable path (passed by reference) should be
+ * set to the start of the path before the first call; padvance will update
+ * this value as it proceeds.  Successive calls to padvance will return
+ * the possible path expansions in sequence.  If an option (indicated by
+ * a percent sign) appears in the path entry then the global variable
+ * pathopt will be set to point to it; otherwise pathopt will be set to
+ * NULL.
+ */
+
+char *pathopt;
+
+char *
+padvance(path, name)
+	char **path;
+	char *name;
+	{
+	register char *p, *q;
+	char *start;
+	int len;
+
+	if (*path == NULL)
+		return NULL;
+	start = *path;
+	for (p = start ; *p && *p != ':' && *p != '%' ; p++);
+	len = p - start + strlen(name) + 2;	/* "2" is for '/' and '\0' */
+	while (stackblocksize() < len)
+		growstackblock();
+	q = stackblock();
+	if (p != start) {
+		bcopy(start, q, p - start);
+		q += p - start;
+		*q++ = '/';
+	}
+	strcpy(q, name);
+	pathopt = NULL;
+	if (*p == '%') {
+		pathopt = ++p;
+		while (*p && *p != ':')  p++;
+	}
+	if (*p == ':')
+		*path = p + 1;
+	else
+		*path = NULL;
+	return stalloc(len);
+}
+
+
+
+/*** Command hashing code ***/
+
+
+hashcmd(argc, argv)  char **argv; {
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+	int c;
+	int verbose;
+	struct cmdentry entry;
+	char *name;
+
+	if (argc <= 1) {
+		for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
+			for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+				printentry(cmdp);
+			}
+		}
+		return 0;
+	}
+	verbose = 0;
+	while ((c = nextopt("rv")) != '\0') {
+		if (c == 'r') {
+			clearcmdentry(0);
+		} else if (c == 'v') {
+			verbose++;
+		}
+	}
+	while ((name = *argptr) != NULL) {
+		if ((cmdp = cmdlookup(name, 0)) != NULL
+		 && (cmdp->cmdtype == CMDNORMAL
+		     || cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
+			delete_cmd_entry();
+		find_command(name, &entry, 1);
+		if (verbose) {
+			if (entry.cmdtype != CMDUNKNOWN) {	/* if no error msg */
+				cmdp = cmdlookup(name, 0);
+				printentry(cmdp);
+			}
+			flushall();
+		}
+		argptr++;
+	}
+	return 0;
+}
+
+
+STATIC void
+printentry(cmdp)
+	struct tblentry *cmdp;
+	{
+	int index;
+	char *path;
+	char *name;
+
+	if (cmdp->cmdtype == CMDNORMAL) {
+		index = cmdp->param.index;
+		path = pathval();
+		do {
+			name = padvance(&path, cmdp->cmdname);
+			stunalloc(name);
+		} while (--index >= 0);
+		out1str(name);
+	} else if (cmdp->cmdtype == CMDBUILTIN) {
+		out1fmt("builtin %s", cmdp->cmdname);
+	} else if (cmdp->cmdtype == CMDFUNCTION) {
+		out1fmt("function %s", cmdp->cmdname);
+#if DEBUG
+	} else {
+		error("internal error: cmdtype %d", cmdp->cmdtype);
+#endif
+	}
+	if (cmdp->rehash)
+		out1c('*');
+	out1c('\n');
+}
+
+
+
+/*
+ * Resolve a command name.  If you change this routine, you may have to
+ * change the shellexec routine as well.
+ */
+
+void
+find_command(name, entry, printerr)
+	char *name;
+	struct cmdentry *entry;
+	{
+	struct tblentry *cmdp;
+	int index;
+	int prev;
+	char *path;
+	char *fullname;
+	struct stat statb;
+	int e;
+	int i;
+
+	/* If name contains a slash, don't use the hash table */
+	if (strchr(name, '/') != NULL) {
+		entry->cmdtype = CMDNORMAL;
+		entry->u.index = 0;
+		return;
+	}
+
+	/* If name is in the table, and not invalidated by cd, we're done */
+	if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0)
+		goto success;
+
+	/* If %builtin not in path, check for builtin next */
+	if (builtinloc < 0 && (i = find_builtin(name)) >= 0) {
+		INTOFF;
+		cmdp = cmdlookup(name, 1);
+		cmdp->cmdtype = CMDBUILTIN;
+		cmdp->param.index = i;
+		INTON;
+		goto success;
+	}
+
+	/* We have to search path. */
+	prev = -1;		/* where to start */
+	if (cmdp) {		/* doing a rehash */
+		if (cmdp->cmdtype == CMDBUILTIN)
+			prev = builtinloc;
+		else
+			prev = cmdp->param.index;
+	}
+
+	path = pathval();
+	e = ENOENT;
+	index = -1;
+loop:
+	while ((fullname = padvance(&path, name)) != NULL) {
+		stunalloc(fullname);
+		index++;
+		if (pathopt) {
+			if (prefix("builtin", pathopt)) {
+				if ((i = find_builtin(name)) < 0)
+					goto loop;
+				INTOFF;
+				cmdp = cmdlookup(name, 1);
+				cmdp->cmdtype = CMDBUILTIN;
+				cmdp->param.index = i;
+				INTON;
+				goto success;
+			} else if (prefix("func", pathopt)) {
+				/* handled below */
+			} else {
+				goto loop;	/* ignore unimplemented options */
+			}
+		}
+		/* if rehash, don't redo absolute path names */
+		if (fullname[0] == '/' && index <= prev) {
+			if (index < prev)
+				goto loop;
+			TRACE(("searchexec \"%s\": no change\n", name));
+			goto success;
+		}
+		while (stat(fullname, &statb) < 0) {
+#ifdef SYSV
+			if (errno == EINTR)
+				continue;
+#endif
+			if (errno != ENOENT && errno != ENOTDIR)
+				e = errno;
+			goto loop;
+		}
+		e = EACCES;	/* if we fail, this will be the error */
+		if ((statb.st_mode & S_IFMT) != S_IFREG)
+			goto loop;
+		if (pathopt) {		/* this is a %func directory */
+			stalloc(strlen(fullname) + 1);
+			readcmdfile(fullname);
+			if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION)
+				error("%s not defined in %s", name, fullname);
+			stunalloc(fullname);
+			goto success;
+		}
+		if (statb.st_uid == geteuid()) {
+			if ((statb.st_mode & 0100) == 0)
+				goto loop;
+		} else if (statb.st_gid == getegid()) {
+			if ((statb.st_mode & 010) == 0)
+				goto loop;
+		} else {
+#if __minix_vmd || defined(BSD)
+			gid_t group_list[NGROUPS_MAX];
+			int ngroups, i;
+
+			ngroups = getgroups(NGROUPS_MAX, group_list);
+
+			for (i = 0; i < ngroups; i++) {
+				if (statb.st_gid == group_list[i]) break;
+			}
+			if (i < ngroups) {
+				if ((statb.st_mode & 010) == 0)
+					goto loop;
+			} else
+#endif
+			if ((statb.st_mode & 01) == 0)
+				goto loop;
+		}
+		TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
+		INTOFF;
+		cmdp = cmdlookup(name, 1);
+		cmdp->cmdtype = CMDNORMAL;
+		cmdp->param.index = index;
+		INTON;
+		goto success;
+	}
+
+	/* We failed.  If there was an entry for this command, delete it */
+	if (cmdp)
+		delete_cmd_entry();
+	if (printerr)
+		outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC));
+	entry->cmdtype = CMDUNKNOWN;
+	return;
+
+success:
+	cmdp->rehash = 0;
+	entry->cmdtype = cmdp->cmdtype;
+	entry->u = cmdp->param;
+}
+
+
+
+/*
+ * Search the table of builtin commands.
+ */
+
+int
+find_builtin(name)
+	char *name;
+	{
+	const register struct builtincmd *bp;
+
+	for (bp = builtincmd ; bp->name ; bp++) {
+		if (*bp->name == *name && equal(bp->name, name))
+			return bp->code;
+	}
+	return -1;
+}
+
+
+
+/*
+ * Called when a cd is done.  Marks all commands so the next time they
+ * are executed they will be rehashed.
+ */
+
+void
+hashcd() {
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+
+	for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
+		for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+			if (cmdp->cmdtype == CMDNORMAL
+			 || cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)
+				cmdp->rehash = 1;
+		}
+	}
+}
+
+
+
+/*
+ * Called before PATH is changed.  The argument is the new value of PATH;
+ * pathval() still returns the old value at this point.  Called with
+ * interrupts off.
+ */
+
+void
+changepath(newval)
+	char *newval;
+	{
+	char *old, *new;
+	int index;
+	int firstchange;
+	int bltin;
+
+	old = pathval();
+	new = newval;
+	firstchange = 9999;	/* assume no change */
+	index = 0;
+	bltin = -1;
+	for (;;) {
+		if (*old != *new) {
+			firstchange = index;
+			if (*old == '\0' && *new == ':'
+			 || *old == ':' && *new == '\0')
+				firstchange++;
+			old = new;	/* ignore subsequent differences */
+		}
+		if (*new == '\0')
+			break;
+		if (*new == '%' && bltin < 0 && prefix("builtin", new + 1))
+			bltin = index;
+		if (*new == ':') {
+			index++;
+		}
+		new++, old++;
+	}
+	if (builtinloc < 0 && bltin >= 0)
+		builtinloc = bltin;		/* zap builtins */
+	if (builtinloc >= 0 && bltin < 0)
+		firstchange = 0;
+	clearcmdentry(firstchange);
+	builtinloc = bltin;
+}
+
+
+/*
+ * Clear out command entries.  The argument specifies the first entry in
+ * PATH which has changed.
+ */
+
+STATIC void
+clearcmdentry(firstchange) {
+	struct tblentry **tblp;
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+
+	INTOFF;
+	for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
+		pp = tblp;
+		while ((cmdp = *pp) != NULL) {
+			if (cmdp->cmdtype == CMDNORMAL && cmdp->param.index >= firstchange
+			 || cmdp->cmdtype == CMDBUILTIN && builtinloc >= firstchange) {
+				*pp = cmdp->next;
+				ckfree(cmdp);
+			} else {
+				pp = &cmdp->next;
+			}
+		}
+	}
+	INTON;
+}
+
+
+/*
+ * Delete all functions.
+ */
+
+#ifdef mkinit
+MKINIT void deletefuncs();
+
+SHELLPROC {
+	deletefuncs();
+}
+#endif
+
+void
+deletefuncs() {
+	struct tblentry **tblp;
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+
+	INTOFF;
+	for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
+		pp = tblp;
+		while ((cmdp = *pp) != NULL) {
+			if (cmdp->cmdtype == CMDFUNCTION) {
+				*pp = cmdp->next;
+				freefunc(cmdp->param.func);
+				ckfree(cmdp);
+			} else {
+				pp = &cmdp->next;
+			}
+		}
+	}
+	INTON;
+}
+
+
+
+/*
+ * Locate a command in the command hash table.  If "add" is nonzero,
+ * add the command to the table if it is not already present.  The
+ * variable "lastcmdentry" is set to point to the address of the link
+ * pointing to the entry, so that delete_cmd_entry can delete the
+ * entry.
+ */
+
+struct tblentry **lastcmdentry;
+
+
+STATIC struct tblentry *
+cmdlookup(name, add)
+	char *name;
+	{
+	int hashval;
+	register char *p;
+	struct tblentry *cmdp;
+	struct tblentry **pp;
+
+	p = name;
+	hashval = *p << 4;
+	while (*p)
+		hashval += *p++;
+	hashval &= 0x7FFF;
+	pp = &cmdtable[hashval % CMDTABLESIZE];
+	for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+		if (equal(cmdp->cmdname, name))
+			break;
+		pp = &cmdp->next;
+	}
+	if (add && cmdp == NULL) {
+		INTOFF;
+		cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
+					+ strlen(name) + 1);
+		cmdp->next = NULL;
+		cmdp->cmdtype = CMDUNKNOWN;
+		cmdp->rehash = 0;
+		strcpy(cmdp->cmdname, name);
+		INTON;
+	}
+	lastcmdentry = pp;
+	return cmdp;
+}
+
+
+/*
+ * Delete the command entry returned on the last lookup.
+ */
+
+STATIC void
+delete_cmd_entry() {
+	struct tblentry *cmdp;
+
+	INTOFF;
+	cmdp = *lastcmdentry;
+	*lastcmdentry = cmdp->next;
+	ckfree(cmdp);
+	INTON;
+}
+
+
+
+#ifdef notdef
+void
+getcmdentry(name, entry)
+	char *name;
+	struct cmdentry *entry; 
+	{
+	struct tblentry *cmdp = cmdlookup(name, 0);
+
+	if (cmdp) {
+		entry->u = cmdp->param;
+		entry->cmdtype = cmdp->cmdtype;
+	} else {
+		entry->cmdtype = CMDUNKNOWN;
+		entry->u.index = 0;
+	}
+}
+#endif
+
+
+/*
+ * Add a new command entry, replacing any existing command entry for
+ * the same name.
+ */
+
+void
+addcmdentry(name, entry)
+	char *name;
+	struct cmdentry *entry;
+	{
+	struct tblentry *cmdp;
+
+	INTOFF;
+	cmdp = cmdlookup(name, 1);
+	if (cmdp->cmdtype == CMDFUNCTION) {
+		freefunc(cmdp->param.func);
+	}
+	cmdp->cmdtype = entry->cmdtype;
+	cmdp->param = entry->u;
+	INTON;
+}
+
+
+/*
+ * Define a shell function.
+ */
+
+void
+defun(name, func)
+	char *name;
+	union node *func;
+	{
+	struct cmdentry entry;
+
+	INTOFF;
+	entry.cmdtype = CMDFUNCTION;
+	entry.u.func = copyfunc(func);
+	addcmdentry(name, &entry);
+	INTON;
+}
+
+
+/*
+ * Delete a function if it exists.
+ */
+
+void
+unsetfunc(name)
+	char *name;
+	{
+	struct tblentry *cmdp;
+
+	if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
+		freefunc(cmdp->param.func);
+		delete_cmd_entry();
+	}
+}
Index: /trunk/minix/commands/ash/exec.h
===================================================================
--- /trunk/minix/commands/ash/exec.h	(revision 9)
+++ /trunk/minix/commands/ash/exec.h	(revision 9)
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)exec.h	5.1 (Berkeley) 3/7/91
+ */
+
+/* values of cmdtype */
+#define CMDUNKNOWN -1		/* no entry in table for command */
+#define CMDNORMAL 0		/* command is an executable program */
+#define CMDBUILTIN 1		/* command is a shell builtin */
+#define CMDFUNCTION 2		/* command is a shell function */
+
+
+struct cmdentry {
+	int cmdtype;
+	union param {
+		int index;
+		union node *func;
+	} u;
+};
+
+
+extern char *pathopt;		/* set by padvance */
+
+#ifdef __STDC__
+void shellexec(char **, char **, char *, int);
+char *padvance(char **, char *);
+void find_command(char *, struct cmdentry *, int);
+int find_builtin(char *);
+void hashcd(void);
+void changepath(char *);
+void defun(char *, union node *);
+void unsetfunc(char *);
+#else
+void shellexec();
+char *padvance();
+void find_command();
+int find_builtin();
+void hashcd();
+void changepath();
+void defun();
+void unsetfunc();
+#endif
Index: /trunk/minix/commands/ash/expand.c
===================================================================
--- /trunk/minix/commands/ash/expand.c	(revision 9)
+++ /trunk/minix/commands/ash/expand.c	(revision 9)
@@ -0,0 +1,1159 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)expand.c	5.1 (Berkeley) 3/7/91";
+#endif /* not lint */
+
+/*
+ * Routines to expand arguments to commands.  We have to deal with
+ * backquotes, shell variables, and file metacharacters.
+ */
+
+#include "shell.h"
+#include "main.h"
+#include "nodes.h"
+#include "eval.h"
+#include "expand.h"
+#include "syntax.h"
+#include "parser.h"
+#include "jobs.h"
+#include "options.h"
+#include "var.h"
+#include "input.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <dirent.h>
+#if USEGETPW
+#include <pwd.h>
+#endif
+
+/*
+ * Structure specifying which parts of the string should be searched
+ * for IFS characters.
+ */
+
+struct ifsregion {
+	struct ifsregion *next;	/* next region in list */
+	int begoff;		/* offset of start of region */
+	int endoff;		/* offset of end of region */
+	int nulonly;		/* search for nul bytes only */
+};
+
+
+char *expdest;			/* output of current string */
+struct nodelist *argbackq;	/* list of back quote expressions */
+struct ifsregion ifsfirst;	/* first struct in list of ifs regions */
+struct ifsregion *ifslastp;	/* last struct in list */
+struct arglist exparg;		/* holds expanded arg list */
+#if UDIR || TILDE
+/*
+ * Set if the last argument processed had /u/logname or ~logname expanded.
+ * This variable is read by the cd command.
+ */
+int didudir;
+#endif
+
+#ifdef __STDC__
+STATIC void argstr(char *, int);
+STATIC void expbackq(union node *, int, int);
+STATIC char *evalvar(char *, int);
+STATIC int varisset(int);
+STATIC void varvalue(int, int, int);
+STATIC void recordregion(int, int, int);
+STATIC void ifsbreakup(char *, struct arglist *);
+STATIC void expandmeta(struct strlist *);
+STATIC void expmeta(char *, char *);
+STATIC void addfname(char *);
+STATIC struct strlist *expsort(struct strlist *);
+STATIC struct strlist *msort(struct strlist *, int);
+STATIC int pmatch(char *, char *);
+#else
+STATIC void argstr();
+STATIC void expbackq();
+STATIC char *evalvar();
+STATIC int varisset();
+STATIC void varvalue();
+STATIC void recordregion();
+STATIC void ifsbreakup();
+STATIC void expandmeta();
+STATIC void expmeta();
+STATIC void addfname();
+STATIC struct strlist *expsort();
+STATIC struct strlist *msort();
+STATIC int pmatch();
+#endif
+#if UDIR || TILDE
+#ifdef __STDC__
+STATIC char *expudir(char *);
+#else
+STATIC char *expudir();
+#endif
+#endif /* UDIR || TILDE */
+
+
+
+/*
+ * Expand shell variables and backquotes inside a here document.
+ */
+
+void
+expandhere(arg, fd)
+	union node *arg;	/* the document */
+	int fd;			/* where to write the expanded version */
+	{
+	herefd = fd;
+	expandarg(arg, (struct arglist *)NULL, 0);
+	xwrite(fd, stackblock(), expdest - stackblock());
+}
+
+
+/*
+ * Perform variable substitution and command substitution on an argument,
+ * placing the resulting list of arguments in arglist.  If full is true,
+ * perform splitting and file name expansion.  When arglist is NULL, perform
+ * here document expansion.
+ */
+
+void
+expandarg(arg, arglist, full)
+	union node *arg;
+	struct arglist *arglist;
+	{
+	struct strlist *sp;
+	char *p;
+
+#if UDIR || TILDE
+	didudir = 0;
+#endif
+	argbackq = arg->narg.backquote;
+	STARTSTACKSTR(expdest);
+	ifsfirst.next = NULL;
+	ifslastp = NULL;
+	argstr(arg->narg.text, full);
+	if (arglist == NULL)
+		return;			/* here document expanded */
+	STPUTC('\0', expdest);
+	p = grabstackstr(expdest);
+	exparg.lastp = &exparg.list;
+	if (full) {
+		ifsbreakup(p, &exparg);
+		*exparg.lastp = NULL;
+		exparg.lastp = &exparg.list;
+		expandmeta(exparg.list);
+	} else {
+		sp = (struct strlist *)stalloc(sizeof (struct strlist));
+		sp->text = p;
+		*exparg.lastp = sp;
+		exparg.lastp = &sp->next;
+	}
+	while (ifsfirst.next != NULL) {
+		struct ifsregion *ifsp;
+		INTOFF;
+		ifsp = ifsfirst.next->next;
+		ckfree(ifsfirst.next);
+		ifsfirst.next = ifsp;
+		INTON;
+	}
+	*exparg.lastp = NULL;
+	if (exparg.list) {
+		*arglist->lastp = exparg.list;
+		arglist->lastp = exparg.lastp;
+	}
+}
+
+
+
+/*
+ * Perform variable and command substitution.  If full is set, output CTLESC
+ * characters to allow for further processing.  If full is not set, treat
+ * $@ like $* since no splitting will be performed.
+ */
+
+STATIC void
+argstr(p, full)
+	register char *p;
+	{
+	char c;
+
+	for (;;) {
+		switch (c = *p++) {
+		case '\0':
+		case CTLENDVAR:
+			goto breakloop;
+		case CTLESC:
+			if (full)
+				STPUTC(c, expdest);
+			c = *p++;
+			STPUTC(c, expdest);
+			break;
+		case CTLVAR:
+			p = evalvar(p, full);
+			break;
+		case CTLBACKQ:
+		case CTLBACKQ|CTLQUOTE:
+			expbackq(argbackq->n, c & CTLQUOTE, full);
+			argbackq = argbackq->next;
+			break;
+		default:
+			STPUTC(c, expdest);
+		}
+	}
+breakloop:;
+}
+
+
+/*
+ * Expand stuff in backwards quotes.
+ */
+
+STATIC void
+expbackq(cmd, quoted, full)
+	union node *cmd;
+	{
+	struct backcmd in;
+	int i;
+	char buf[128];
+	char *p;
+	char *dest = expdest;
+	struct ifsregion saveifs, *savelastp;
+	struct nodelist *saveargbackq;
+	char lastc;
+	int startloc = dest - stackblock();
+	char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
+	int saveherefd;
+
+	INTOFF;
+	saveifs = ifsfirst;
+	savelastp = ifslastp;
+	saveargbackq = argbackq;
+	saveherefd = herefd;      
+	herefd = -1;
+	p = grabstackstr(dest);
+	evalbackcmd(cmd, &in);
+	ungrabstackstr(p, dest);
+	ifsfirst = saveifs;
+	ifslastp = savelastp;
+	argbackq = saveargbackq;
+	herefd = saveherefd;
+
+	p = in.buf;
+	lastc = '\0';
+	for (;;) {
+		if (--in.nleft < 0) {
+			if (in.fd < 0)
+				break;
+			while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR);
+			TRACE(("expbackq: read returns %d\n", i));
+			if (i <= 0)
+				break;
+			p = buf;
+			in.nleft = i - 1;
+		}
+		lastc = *p++;
+		if (lastc != '\0') {
+			if (full && syntax[lastc] == CCTL)
+				STPUTC(CTLESC, dest);
+			STPUTC(lastc, dest);
+		}
+	}
+	if (lastc == '\n') {
+		STUNPUTC(dest);
+	}
+	if (in.fd >= 0)
+		close(in.fd);
+	if (in.buf)
+		ckfree(in.buf);
+	if (in.jp)
+		exitstatus = waitforjob(in.jp);
+	if (quoted == 0)
+		recordregion(startloc, dest - stackblock(), 0);
+	TRACE(("evalbackq: size=%d: \"%.*s\"\n",
+		(dest - stackblock()) - startloc,
+		(dest - stackblock()) - startloc,
+		stackblock() + startloc));
+	expdest = dest;
+	INTON;
+}
+
+
+
+/*
+ * Expand a variable, and return a pointer to the next character in the
+ * input string.
+ */
+
+STATIC char *
+evalvar(p, full)
+	char *p;
+	{
+	int subtype;
+	int flags;
+	char *var;
+	char *val;
+	int c;
+	int set;
+	int special;
+	int startloc;
+
+	flags = *p++;
+	subtype = flags & VSTYPE;
+	var = p;
+	special = 0;
+	if (! is_name(*p))
+		special = 1;
+	p = strchr(p, '=') + 1;
+again: /* jump here after setting a variable with ${var=text} */
+	if (special) {
+		set = varisset(*var);
+		val = NULL;
+	} else {
+		val = lookupvar(var);
+		if (val == NULL || (flags & VSNUL) && val[0] == '\0') {
+			val = NULL;
+			set = 0;
+		} else
+			set = 1;
+	}
+	startloc = expdest - stackblock();
+	if (set && subtype != VSPLUS) {
+		/* insert the value of the variable */
+		if (special) {
+			varvalue(*var, flags & VSQUOTE, full);
+		} else {
+			char const *syntax = (flags & VSQUOTE)? DQSYNTAX : BASESYNTAX;
+
+			while (*val) {
+				if (full && syntax[*val] == CCTL)
+					STPUTC(CTLESC, expdest);
+				STPUTC(*val++, expdest);
+			}
+		}
+	}
+	if (subtype == VSPLUS)
+		set = ! set;
+	if (((flags & VSQUOTE) == 0 || (*var == '@' && shellparam.nparam != 1))
+	 && (set || subtype == VSNORMAL))
+		recordregion(startloc, expdest - stackblock(), flags & VSQUOTE);
+	if (! set && subtype != VSNORMAL) {
+		if (subtype == VSPLUS || subtype == VSMINUS) {
+			argstr(p, full);
+		} else {
+			char *startp;
+			int saveherefd = herefd;
+			herefd = -1;
+			argstr(p, 0);
+			STACKSTRNUL(expdest);
+			herefd = saveherefd;
+			startp = stackblock() + startloc;
+			if (subtype == VSASSIGN) {
+				setvar(var, startp, 0);
+				STADJUST(startp - expdest, expdest);
+				flags &=~ VSNUL;
+				goto again;
+			}
+			/* subtype == VSQUESTION */
+			if (*p != CTLENDVAR) {
+				outfmt(&errout, "%s\n", startp);
+				error((char *)NULL);
+			}
+			error("%.*s: parameter %snot set", p - var - 1,
+				var, (flags & VSNUL)? "null or " : nullstr);
+		}
+	}
+	if (subtype != VSNORMAL) {	/* skip to end of alternative */
+		int nesting = 1;
+		for (;;) {
+			if ((c = *p++) == CTLESC)
+				p++;
+			else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
+				if (set) {
+					if (argbackq != NULL)
+						argbackq = argbackq->next;
+				}
+			} else if (c == CTLVAR) {
+				if ((*p++ & VSTYPE) != VSNORMAL)
+					nesting++;
+			} else if (c == CTLENDVAR) {
+				if (--nesting == 0)
+					break;
+			}
+		}
+	}
+	return p;
+}
+
+
+
+/*
+ * Test whether a specialized variable is set.
+ */
+
+STATIC int
+varisset(name)
+	char name;
+	{
+	char **ap;
+
+	if (name == '!') {
+		if (backgndpid == -1)
+			return 0;
+	} else if (name == '@' || name == '*') {
+		if (*shellparam.p == NULL)
+			return 0;
+	} else if ((unsigned)(name -= '1') <= '9' - '1') {
+		ap = shellparam.p;
+		do {
+			if (*ap++ == NULL)
+				return 0;
+		} while (--name >= 0);
+	}
+	return 1;
+}
+
+
+
+/*
+ * Add the value of a specialized variable to the stack string.
+ */
+
+STATIC void
+varvalue(name, quoted, allow_split)
+	char name;
+	{
+	int num;
+	char temp[32];
+	char *p;
+	int i;
+	extern int oexitstatus;
+	char sep;
+	char **ap;
+	char const *syntax;
+
+	switch (name) {
+	case '$':
+		num = rootpid;
+		goto numvar;
+	case '?':
+		num = oexitstatus;
+		goto numvar;
+	case '#':
+		num = shellparam.nparam;
+		goto numvar;
+	case '!':
+		num = backgndpid;
+numvar:
+		p = temp + 31;
+		temp[31] = '\0';
+		do {
+			*--p = num % 10 + '0';
+		} while ((num /= 10) != 0);
+		while (*p)
+			STPUTC(*p++, expdest);
+		break;
+	case '-':
+		for (i = 0 ; optchar[i] ; i++) {
+			if (optval[i])
+				STPUTC(optchar[i], expdest);
+		}
+		break;
+	case '@':
+		if (allow_split) {
+			sep = '\0';
+			goto allargs;
+		}
+		/* fall through */			
+	case '*':
+		sep = ' ';
+allargs:
+		/* Only emit CTLESC if we will do further processing,
+		   i.e. if allow_split is set.  */
+		syntax = quoted && allow_split ? DQSYNTAX : BASESYNTAX;
+		for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
+			/* should insert CTLESC characters */
+			while (*p) {
+				if (syntax[*p] == CCTL)
+					STPUTC(CTLESC, expdest);
+				STPUTC(*p++, expdest);
+			}
+			if (*ap)
+				STPUTC(sep, expdest);
+		}
+		break;
+	case '0':
+		p = arg0;
+string:
+		/* Only emit CTLESC if we will do further processing,
+		   i.e. if allow_split is set.  */
+		syntax = quoted && allow_split ? DQSYNTAX : BASESYNTAX;
+		while (*p) {
+			if (syntax[*p] == CCTL)
+				STPUTC(CTLESC, expdest);
+			STPUTC(*p++, expdest);
+		}
+		break;
+	default:
+		if ((unsigned)(name -= '1') <= '9' - '1') {
+			p = shellparam.p[name];
+			goto string;
+		}
+		break;
+	}
+}
+
+
+
+/*
+ * Record the the fact that we have to scan this region of the
+ * string for IFS characters.
+ */
+
+STATIC void
+recordregion(start, end, nulonly) {
+	register struct ifsregion *ifsp;
+
+	if (ifslastp == NULL) {
+		ifsp = &ifsfirst;
+	} else {
+		ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
+		ifslastp->next = ifsp;
+	}
+	ifslastp = ifsp;
+	ifslastp->next = NULL;
+	ifslastp->begoff = start;
+	ifslastp->endoff = end;
+	ifslastp->nulonly = nulonly;
+}
+
+
+
+/*
+ * Break the argument string into pieces based upon IFS and add the
+ * strings to the argument list.  The regions of the string to be
+ * searched for IFS characters have been stored by recordregion.
+ */
+
+STATIC void
+ifsbreakup(string, arglist)
+	char *string;
+	struct arglist *arglist;
+	{
+	struct ifsregion *ifsp;
+	struct strlist *sp;
+	char *start;
+	register char *p;
+	char *q;
+	char *ifs;
+
+	start = string;
+	if (ifslastp != NULL) {
+		ifsp = &ifsfirst;
+		do {
+			p = string + ifsp->begoff;
+			ifs = ifsp->nulonly? nullstr : ifsval();
+			while (p < string + ifsp->endoff) {
+				q = p;
+				if (*p == CTLESC)
+					p++;
+				if (strchr(ifs, *p++)) {
+					if (q > start || *ifs != ' ') {
+						*q = '\0';
+						sp = (struct strlist *)stalloc(sizeof *sp);
+						sp->text = start;
+						*arglist->lastp = sp;
+						arglist->lastp = &sp->next;
+					}
+					if (*ifs == ' ') {
+						for (;;) {
+							if (p >= string + ifsp->endoff)
+								break;
+							q = p;
+							if (*p == CTLESC)
+								p++;
+							if (strchr(ifs, *p++) == NULL) {
+								p = q;
+								break;
+							}
+						}
+					}
+					start = p;
+				}
+			}
+		} while ((ifsp = ifsp->next) != NULL);
+		if (*start || (*ifs != ' ' && start > string)) {
+			sp = (struct strlist *)stalloc(sizeof *sp);
+			sp->text = start;
+			*arglist->lastp = sp;
+			arglist->lastp = &sp->next;
+		}
+	} else {
+		sp = (struct strlist *)stalloc(sizeof *sp);
+		sp->text = start;
+		*arglist->lastp = sp;
+		arglist->lastp = &sp->next;
+	}
+}
+
+
+
+/*
+ * Expand shell metacharacters.  At this point, the only control characters
+ * should be escapes.  The results are stored in the list exparg.
+ */
+
+char *expdir;
+
+
+STATIC void
+expandmeta(str)
+	struct strlist *str;
+	{
+	char *p;
+	struct strlist **savelastp;
+	struct strlist *sp;
+	char c;
+
+	while (str) {
+		if (fflag)
+			goto nometa;
+		p = str->text;
+#if UDIR
+		if (p[0] == '/' && p[1] == 'u' && p[2] == '/')
+			str->text = p = expudir(p);
+#endif
+#if TILDE
+		if (p[0] == '~')
+			str->text = p = expudir(p);
+#endif
+		for (;;) {			/* fast check for meta chars */
+			if ((c = *p++) == '\0')
+				goto nometa;
+			if (c == '*' || c == '?' || c == '[' || c == '!')
+				break;
+		}
+		savelastp = exparg.lastp;
+		INTOFF;
+		if (expdir == NULL)
+		{
+			int i = strlen(str->text);
+			expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
+		}
+		expmeta(expdir, str->text);
+		ckfree(expdir);
+		expdir = NULL;
+		INTON;
+		if (exparg.lastp == savelastp) {
+			if (! zflag) {
+nometa:
+				*exparg.lastp = str;
+				rmescapes(str->text);
+				exparg.lastp = &str->next;
+			}
+		} else {
+			*exparg.lastp = NULL;
+			*savelastp = sp = expsort(*savelastp);
+			while (sp->next != NULL)
+				sp = sp->next;
+			exparg.lastp = &sp->next;
+		}
+		str = str->next;
+	}
+}
+
+
+#if UDIR || TILDE
+/*
+ * UDIR: Expand /u/username into the home directory for the specified user.
+ * TILDE: Expand ~username into the home directory for the specified user.
+ * We hope not to use the getpw stuff here, because then we would have to load
+ * in stdio and who knows what else.  With networked password files there is
+ * no choice alas.
+ */
+
+#define MAXLOGNAME 32
+#define MAXPWLINE 128
+
+char *pfgets();
+
+
+STATIC char *
+expudir(path)
+	char *path;
+	{
+	register char *p, *q, *r;
+	char name[MAXLOGNAME];
+	char line[MAXPWLINE];
+	int i;
+#if USEGETPW
+	struct passwd *pw;
+#endif
+
+	r = path;				/* result on failure */
+	p = r + (*r == '~' ? 1 : 3);	/* the 1 skips "~", 3 skips "/u/" */
+	q = name;
+	while (*p && *p != '/') {
+		if (q >= name + MAXLOGNAME - 1)
+			return r;		/* fail, name too long */
+		*q++ = *p++;
+	}
+	*q = '\0';
+
+#if TILDE
+	if (*name == 0 && *r == '~') {
+		/* null name, use $HOME */
+		if ((q = lookupvar("HOME")) == NULL)
+			return r;		/* fail, home not set */
+		i = strlen(q);
+		r = stalloc(i + strlen(p) + 1);
+		scopy(q, r);
+		scopy(p, r + i);
+		TRACE(("expudir converts %s to %s\n", path, r));
+		didudir = 1;
+		path = r;
+		return r;
+	}
+#endif
+#if !USEGETPW	/* can do without the bloat */
+	setinputfile("/etc/passwd", 1);
+	q = line + strlen(name);
+	while (pfgets(line, MAXPWLINE) != NULL) {
+		if (line[0] == name[0] && prefix(name, line) && *q == ':') {
+			/* skip to start of home directory */
+			i = 4;
+			do {
+				while (*++q && *q != ':');
+			} while (--i > 0);
+			if (*q == '\0')
+				break;		/* fail, corrupted /etc/passwd */
+			q++;
+			for (r = q ; *r && *r != '\n' && *r != ':' ; r++);
+			*r = '\0';		/* nul terminate home directory */
+			i = r - q;		/* i = strlen(q) */
+			r = stalloc(i + strlen(p) + 1);
+			scopy(q, r);
+			scopy(p, r + i);
+			TRACE(("expudir converts %s to %s\n", path, r));
+			didudir = 1;
+			path = r;		/* succeed */
+			break;
+		}
+	}
+	popfile();
+#else
+	if ((pw = getpwnam(name)) != NULL) {
+		/* user exists */
+		q = pw->pw_dir;
+		i = strlen(q);
+		r = stalloc(i + strlen(p) + 1);
+		scopy(q, r);
+		scopy(p, r + i);
+		TRACE(("expudir converts %s to %s\n", path, r));
+		didudir = 1;
+		path = r;
+	}
+	endpwent();
+#endif /* USEGETPW */
+
+	return r;
+}
+#endif
+
+
+/*
+ * Do metacharacter (i.e. *, ?, [...]) expansion.
+ */
+
+STATIC void
+expmeta(enddir, name)
+	char *enddir;
+	char *name;
+	{
+	register char *p;
+	char *q;
+	char *start;
+	char *endname;
+	int metaflag;
+	struct stat statb;
+	DIR *dirp;
+	struct dirent *dp;
+	int atend;
+	int matchdot;
+
+	metaflag = 0;
+	start = name;
+	for (p = name ; ; p++) {
+		if (*p == '*' || *p == '?')
+			metaflag = 1;
+		else if (*p == '[') {
+			q = p + 1;
+			if (*q == '!')
+				q++;
+			for (;;) {
+				if (*q == CTLESC)
+					q++;
+				if (*q == '/' || *q == '\0')
+					break;
+				if (*++q == ']') {
+					metaflag = 1;
+					break;
+				}
+			}
+		} else if (*p == '!' && p[1] == '!'	&& (p == name || p[-1] == '/')) {
+			metaflag = 1;
+		} else if (*p == '\0')
+			break;
+		else if (*p == CTLESC)
+			p++;
+		if (*p == '/') {
+			if (metaflag)
+				break;
+			start = p + 1;
+		}
+	}
+	if (metaflag == 0) {	/* we've reached the end of the file name */
+		if (enddir != expdir)
+			metaflag++;
+		for (p = name ; ; p++) {
+			if (*p == CTLESC)
+				p++;
+			*enddir++ = *p;
+			if (*p == '\0')
+				break;
+		}
+		if (metaflag == 0 || stat(expdir, &statb) >= 0)
+			addfname(expdir);
+		return;
+	}
+	endname = p;
+	if (start != name) {
+		p = name;
+		while (p < start) {
+			if (*p == CTLESC)
+				p++;
+			*enddir++ = *p++;
+		}
+	}
+	if (enddir == expdir) {
+		p = ".";
+	} else if (enddir == expdir + 1 && *expdir == '/') {
+		p = "/";
+	} else {
+		p = expdir;
+		enddir[-1] = '\0';
+	}
+	if ((dirp = opendir(p)) == NULL)
+		return;
+	if (enddir != expdir)
+		enddir[-1] = '/';
+	if (*endname == 0) {
+		atend = 1;
+	} else {
+		atend = 0;
+		*endname++ = '\0';
+	}
+	matchdot = 0;
+	if (start[0] == '.' || start[0] == CTLESC && start[1] == '.')
+		matchdot++;
+	while (! int_pending() && (dp = readdir(dirp)) != NULL) {
+		if (dp->d_name[0] == '.' && ! matchdot)
+			continue;
+		if (patmatch(start, dp->d_name)) {
+			if (atend) {
+				scopy(dp->d_name, enddir);
+				addfname(expdir);
+			} else {
+				char *q;
+				for (p = enddir, q = dp->d_name ; *p++ = *q++ ;);
+				p[-1] = '/';
+				expmeta(p, endname);
+			}
+		}
+	}
+	closedir(dirp);
+	if (! atend)
+		endname[-1] = '/';
+}
+
+
+/*
+ * Add a file name to the list.
+ */
+
+STATIC void
+addfname(name)
+	char *name;
+	{
+	char *p;
+	struct strlist *sp;
+
+	p = stalloc(strlen(name) + 1);
+	scopy(name, p);
+	sp = (struct strlist *)stalloc(sizeof *sp);
+	sp->text = p;
+	*exparg.lastp = sp;
+	exparg.lastp = &sp->next;
+}
+
+
+/*
+ * Sort the results of file name expansion.  It calculates the number of
+ * strings to sort and then calls msort (short for merge sort) to do the
+ * work.
+ */
+
+STATIC struct strlist *
+expsort(str)
+	struct strlist *str;
+	{
+	int len;
+	struct strlist *sp;
+
+	len = 0;
+	for (sp = str ; sp ; sp = sp->next)
+		len++;
+	return msort(str, len);
+}
+
+
+STATIC struct strlist *
+msort(list, len)
+	struct strlist *list;
+	{
+	struct strlist *p, *q;
+	struct strlist **lpp;
+	int half;
+	int n;
+
+	if (len <= 1)
+		return list;
+	half = len >> 1;      
+	p = list;
+	for (n = half ; --n >= 0 ; ) {
+		q = p;
+		p = p->next;
+	}
+	q->next = NULL;			/* terminate first half of list */
+	q = msort(list, half);		/* sort first half of list */
+	p = msort(p, len - half);		/* sort second half */
+	lpp = &list;
+	for (;;) {
+		if (strcmp(p->text, q->text) < 0) {
+			*lpp = p;
+			lpp = &p->next;
+			if ((p = *lpp) == NULL) {
+				*lpp = q;
+				break;
+			}
+		} else {
+			*lpp = q;
+			lpp = &q->next;
+			if ((q = *lpp) == NULL) {
+				*lpp = p;
+				break;
+			}
+		}
+	}
+	return list;
+}
+
+
+
+/*
+ * Returns true if the pattern matches the string.
+ */
+
+int
+patmatch(pattern, string)
+	char *pattern;
+	char *string;
+	{
+	if (pattern[0] == '!' && pattern[1] == '!')
+		return 1 - pmatch(pattern + 2, string);
+	else
+		return pmatch(pattern, string);
+}
+
+
+STATIC int
+pmatch(pattern, string)
+	char *pattern;
+	char *string;
+	{
+	register char *p, *q;
+	register char c;
+
+	p = pattern;
+	q = string;
+	for (;;) {
+		switch (c = *p++) {
+		case '\0':
+			goto breakloop;
+		case CTLESC:
+			if (*q++ != *p++)
+				return 0;
+			break;
+		case '?':
+			if (*q++ == '\0')
+				return 0;
+			break;
+		case '*':
+			c = *p;
+			if (c != CTLESC && c != '?' && c != '*' && c != '[') {
+				while (*q != c) {
+					if (*q == '\0')
+						return 0;
+					q++;
+				}
+			}
+			do {
+				if (pmatch(p, q))
+					return 1;
+			} while (*q++ != '\0');
+			return 0;
+		case '[': {
+			char *endp;
+			int invert, found;
+			char chr;
+
+			endp = p;
+			if (*endp == '!')
+				endp++;
+			for (;;) {
+				if (*endp == '\0')
+					goto dft;		/* no matching ] */
+				if (*endp == CTLESC)
+					endp++;
+				if (*++endp == ']')
+					break;
+			}
+			invert = 0;
+			if (*p == '!') {
+				invert++;
+				p++;
+			}
+			found = 0;
+			chr = *q++;
+			c = *p++;
+			do {
+				if (c == CTLESC)
+					c = *p++;
+				if (*p == '-' && p[1] != ']') {
+					p++;
+					if (*p == CTLESC)
+						p++;
+					if (chr >= c && chr <= *p)
+						found = 1;
+					p++;
+				} else {
+					if (chr == c)
+						found = 1;
+				}
+			} while ((c = *p++) != ']');
+			if (found == invert)
+				return 0;
+			break;
+		}
+dft:	    default:
+			if (*q++ != c)
+				return 0;
+			break;
+		}
+	}
+breakloop:
+	if (*q != '\0')
+		return 0;
+	return 1;
+}
+
+
+
+/*
+ * Remove any CTLESC characters from a string.
+ */
+
+void
+rmescapes(str)
+	char *str;
+	{
+	register char *p, *q;
+
+	p = str;
+	while (*p != CTLESC) {
+		if (*p++ == '\0')
+			return;
+	}
+	q = p;
+	while (*p) {
+		if (*p == CTLESC)
+			p++;
+		*q++ = *p++;
+	}
+	*q = '\0';
+}
+
+
+
+/*
+ * See if a pattern matches in a case statement.
+ */
+
+int
+casematch(pattern, val)
+	union node *pattern;
+	char *val;
+	{
+	struct stackmark smark;
+	int result;
+	char *p;
+
+	setstackmark(&smark);
+	argbackq = pattern->narg.backquote;
+	STARTSTACKSTR(expdest);
+	ifslastp = NULL;
+	/* Preserve any CTLESC characters inserted previously, so that
+	   we won't expand reg exps which are inside strings.  */
+	argstr(pattern->narg.text, 1);
+	STPUTC('\0', expdest);
+	p = grabstackstr(expdest);
+	result = patmatch(p, val);
+	popstackmark(&smark);
+	return result;
+}
Index: /trunk/minix/commands/ash/expand.h
===================================================================
--- /trunk/minix/commands/ash/expand.h	(revision 9)
+++ /trunk/minix/commands/ash/expand.h	(revision 9)
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)expand.h	5.1 (Berkeley) 3/7/91
+ */
+
+struct strlist {
+	struct strlist *next;
+	char *text;
+};
+
+
+struct arglist {
+	struct strlist *list;
+	struct strlist **lastp;
+};
+
+#ifdef __STDC__
+union node;
+void expandarg(union node *, struct arglist *, int);
+void expandhere(union node *, int);
+int patmatch(char *, char *);
+void rmescapes(char *);
+int casematch(union node *, char *);
+#else
+void expandarg();
+void expandhere();
+int patmatch();
+void rmescapes();
+int casematch();
+#endif
Index: /trunk/minix/commands/ash/funcs/cmv
===================================================================
--- /trunk/minix/commands/ash/funcs/cmv	(revision 9)
+++ /trunk/minix/commands/ash/funcs/cmv	(revision 9)
@@ -0,0 +1,49 @@
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)cmv	5.1 (Berkeley) 3/7/91
+
+# Conditional move--don't replace an existing file.
+
+cmv() {
+	if test $# != 2
+	then	echo "cmv: arg count"
+		return 2
+	fi
+	if test -f "$2" -o -w "$2"
+	then	echo "$2 exists"
+		return 2
+	fi
+	/bin/mv "$1" "$2"
+}
Index: /trunk/minix/commands/ash/funcs/dirs
===================================================================
--- /trunk/minix/commands/ash/funcs/dirs	(revision 9)
+++ /trunk/minix/commands/ash/funcs/dirs	(revision 9)
@@ -0,0 +1,73 @@
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)dirs	5.1 (Berkeley) 3/7/91
+
+# pushd, popd, and dirs --- written by Chris Bertin
+# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
+# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
+
+pushd () {
+	SAVE=`pwd`
+	if [ "$1" = "" ] 
+	then	if [ "$DSTACK" = "" ]
+		then	echo "pushd: directory stack empty."
+			return 1
+		fi
+		set $DSTACK
+		cd $1 || return
+		shift 1
+		DSTACK="$*"
+	else	cd $1 > /dev/null || return
+	fi
+	DSTACK="$SAVE $DSTACK"
+	dirs
+}
+
+popd () {
+	if [ "$DSTACK" = "" ] 
+	then	echo "popd: directory stack empty."
+		return 1
+	fi
+	set $DSTACK
+	cd $1
+	shift
+	DSTACK=$*
+	dirs
+}
+
+dirs () {
+	echo "`pwd` $DSTACK"
+	return 0
+}
Index: /trunk/minix/commands/ash/funcs/kill
===================================================================
--- /trunk/minix/commands/ash/funcs/kill	(revision 9)
+++ /trunk/minix/commands/ash/funcs/kill	(revision 9)
@@ -0,0 +1,49 @@
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)kill	5.1 (Berkeley) 3/7/91
+
+# Convert job names to process ids and then run /bin/kill.
+
+kill() {
+	local args x
+	args=
+	for x in "$@"
+	do	case $x in
+		%*)	x=`jobid "$x"` ;;
+		esac
+		args="$args $x"
+	done
+	/bin/kill $args
+}
Index: /trunk/minix/commands/ash/funcs/login
===================================================================
--- /trunk/minix/commands/ash/funcs/login	(revision 9)
+++ /trunk/minix/commands/ash/funcs/login	(revision 9)
@@ -0,0 +1,38 @@
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)login	5.1 (Berkeley) 3/7/91
+
+# replaces the login builtin in the BSD shell
+login () exec login "$@"
Index: /trunk/minix/commands/ash/funcs/newgrp
===================================================================
--- /trunk/minix/commands/ash/funcs/newgrp	(revision 9)
+++ /trunk/minix/commands/ash/funcs/newgrp	(revision 9)
@@ -0,0 +1,37 @@
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)newgrp	5.1 (Berkeley) 3/7/91
+
+newgrp() exec newgrp "$@"
Index: /trunk/minix/commands/ash/funcs/popd
===================================================================
--- /trunk/minix/commands/ash/funcs/popd	(revision 9)
+++ /trunk/minix/commands/ash/funcs/popd	(revision 9)
@@ -0,0 +1,73 @@
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)popd	5.1 (Berkeley) 3/7/91
+
+# pushd, popd, and dirs --- written by Chris Bertin
+# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
+# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
+
+pushd () {
+	SAVE=`pwd`
+	if [ "$1" = "" ] 
+	then	if [ "$DSTACK" = "" ]
+		then	echo "pushd: directory stack empty."
+			return 1
+		fi
+		set $DSTACK
+		cd $1 || return
+		shift 1
+		DSTACK="$*"
+	else	cd $1 > /dev/null || return
+	fi
+	DSTACK="$SAVE $DSTACK"
+	dirs
+}
+
+popd () {
+	if [ "$DSTACK" = "" ] 
+	then	echo "popd: directory stack empty."
+		return 1
+	fi
+	set $DSTACK
+	cd $1
+	shift
+	DSTACK=$*
+	dirs
+}
+
+dirs () {
+	echo "`pwd` $DSTACK"
+	return 0
+}
Index: /trunk/minix/commands/ash/funcs/pushd
===================================================================
--- /trunk/minix/commands/ash/funcs/pushd	(revision 9)
+++ /trunk/minix/commands/ash/funcs/pushd	(revision 9)
@@ -0,0 +1,73 @@
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)pushd	5.1 (Berkeley) 3/7/91
+
+# pushd, popd, and dirs --- written by Chris Bertin
+# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
+# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
+
+pushd () {
+	SAVE=`pwd`
+	if [ "$1" = "" ] 
+	then	if [ "$DSTACK" = "" ]
+		then	echo "pushd: directory stack empty."
+			return 1
+		fi
+		set $DSTACK
+		cd $1 || return
+		shift 1
+		DSTACK="$*"
+	else	cd $1 > /dev/null || return
+	fi
+	DSTACK="$SAVE $DSTACK"
+	dirs
+}
+
+popd () {
+	if [ "$DSTACK" = "" ] 
+	then	echo "popd: directory stack empty."
+		return 1
+	fi
+	set $DSTACK
+	cd $1
+	shift
+	DSTACK=$*
+	dirs
+}
+
+dirs () {
+	echo "`pwd` $DSTACK"
+	return 0
+}
Index: /trunk/minix/commands/ash/funcs/suspend
===================================================================
--- /trunk/minix/commands/ash/funcs/suspend	(revision 9)
+++ /trunk/minix/commands/ash/funcs/suspend	(revision 9)
@@ -0,0 +1,41 @@
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)suspend	5.1 (Berkeley) 3/7/91
+
+suspend() {
+	local -
+	set +j
+	kill -TSTP 0
+}
Index: /trunk/minix/commands/ash/init.h
===================================================================
--- /trunk/minix/commands/ash/init.h	(revision 9)
+++ /trunk/minix/commands/ash/init.h	(revision 9)
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)init.h	5.1 (Berkeley) 3/7/91
+ */
+
+#ifdef __STDC__
+void init(void);
+void reset(void);
+void initshellproc(void);
+#else
+void init();
+void reset();
+void initshellproc();
+#endif
Index: /trunk/minix/commands/ash/input.c
===================================================================
--- /trunk/minix/commands/ash/input.c	(revision 9)
+++ /trunk/minix/commands/ash/input.c	(revision 9)
@@ -0,0 +1,414 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)input.c	5.4 (Berkeley) 7/1/91";
+#endif /* not lint */
+
+/*
+ * This file implements the input routines used by the parser.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>	/* defines BUFSIZ */
+#include "shell.h"
+#include <fcntl.h>
+#include <errno.h>
+#include "syntax.h"
+#include "input.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+
+#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
+
+
+/*
+ * The parsefile structure pointed to by the global variable parsefile
+ * contains information about the current file being read.
+ */
+
+MKINIT
+struct parsefile {
+	int linno;		/* current line */
+	int fd;			/* file descriptor (or -1 if string) */
+	int nleft;		/* number of chars left in buffer */
+	char *nextc;		/* next char in buffer */
+	struct parsefile *prev;	/* preceding file on stack */
+	char *buf;		/* input buffer */
+};
+
+
+int plinno = 1;			/* input line number */
+MKINIT int parsenleft;		/* copy of parsefile->nleft */
+char *parsenextc;		/* copy of parsefile->nextc */
+MKINIT struct parsefile basepf;	/* top level input file */
+char basebuf[BUFSIZ];		/* buffer for top level input file */
+struct parsefile *parsefile = &basepf;	/* current input file */
+char *pushedstring;		/* copy of parsenextc when text pushed back */
+int pushednleft;		/* copy of parsenleft when text pushed back */
+
+#if READLINE
+char *readline __P((const char *prompt));
+char *r_use_prompt = NULL;	/* the prompt to use with readline */
+#endif
+
+#ifdef __STDC__
+STATIC void pushfile(void);
+#else
+STATIC void pushfile();
+#endif
+
+
+
+#ifdef mkinit
+INCLUDE "input.h"
+INCLUDE "error.h"
+
+INIT {
+	extern char basebuf[];
+
+	basepf.nextc = basepf.buf = basebuf;
+}
+
+RESET {
+	if (exception != EXSHELLPROC)
+		parsenleft = 0;            /* clear input buffer */
+	popallfiles();
+}
+
+SHELLPROC {
+	popallfiles();
+}
+#endif
+
+
+/*
+ * Read a line from the script.
+ */
+
+char *
+pfgets(line, len)
+	char *line;
+	{
+	register char *p = line;
+	int nleft = len;
+	int c;
+
+	while (--nleft > 0) {
+		c = pgetc_macro();
+		if (c == PEOF) {
+			if (p == line)
+				return NULL;
+			break;
+		}
+		*p++ = c;
+		if (c == '\n')
+			break;
+	}
+	*p = '\0';
+	return line;
+}
+
+
+
+/*
+ * Read a character from the script, returning PEOF on end of file.
+ * Nul characters in the input are silently discarded.
+ */
+
+int
+pgetc() {
+	return pgetc_macro();
+}
+
+
+/*
+ * Refill the input buffer and return the next input character:
+ *
+ * 1) If a string was pushed back on the input, switch back to the regular
+ *    buffer.
+ * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
+ *    from a string so we can't refill the buffer, return EOF.
+ * 3) Call read to read in the characters.
+ * 4) Delete all nul characters from the buffer.
+ */
+
+int
+preadbuffer() {
+	register char *p, *q;
+	register int i;
+
+	if (pushedstring) {
+		parsenextc = pushedstring;
+		pushedstring = NULL;
+		parsenleft = pushednleft;
+		if (--parsenleft >= 0)
+			return *parsenextc++;
+	}
+	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
+		return PEOF;
+	flushout(&output);
+	flushout(&errout);
+#if READLINE
+    /* Use the readline() call if a prompt is to be printed (interactive). */
+    if (r_use_prompt != NULL) {
+	char *prompt;
+	char *line;
+
+	p = parsenextc = parsefile->buf;
+
+	prompt = r_use_prompt;
+	r_use_prompt = NULL;
+
+	if ((line = readline(prompt)) == NULL) {
+                parsenleft = EOF_NLEFT;
+                return PEOF;
+	}
+	strcpy(p, line);
+	free(line);
+	i = strlen(p);
+	p[i++] = '\n';
+    } else {
+#endif
+retry:
+	p = parsenextc = parsefile->buf;
+	i = read(parsefile->fd, p, BUFSIZ);
+	if (i <= 0) {
+                if (i < 0) {
+                        if (errno == EINTR)
+                                goto retry;
+#ifdef EWOULDBLOCK
+                        if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
+                                int flags = fcntl(0, F_GETFL, 0);
+                                if (flags >= 0 && flags & O_NONBLOCK) {
+                                        flags &=~ O_NONBLOCK;
+                                        if (fcntl(0, F_SETFL, flags) >= 0) {
+						out2str("sh: turning off NDELAY mode\n");
+                                                goto retry;
+                                        }
+                                }
+                        }
+#endif
+                }
+                parsenleft = EOF_NLEFT;
+                return PEOF;
+	}
+#if READLINE
+    }
+#endif
+	parsenleft = i - 1;
+
+	/* delete nul characters */
+	for (;;) {
+		if (*p++ == '\0')
+			break;
+		if (--i <= 0)
+			return *parsenextc++;		/* no nul characters */
+	}
+	q = p - 1;
+	while (--i > 0) {
+		if (*p != '\0')
+			*q++ = *p;
+		p++;
+	}
+	if (q == parsefile->buf)
+		goto retry;			/* buffer contained nothing but nuls */
+	parsenleft = q - parsefile->buf - 1;
+	return *parsenextc++;
+}
+
+
+/*
+ * Undo the last call to pgetc.  Only one character may be pushed back.
+ * PEOF may be pushed back.
+ */
+
+void
+pungetc() {
+	parsenleft++;
+	parsenextc--;
+}
+
+
+/*
+ * Push a string back onto the input.  This code doesn't work if the user
+ * tries to push back more than one string at once.
+ */
+
+void
+ppushback(string, length)
+	char *string;
+	{
+	pushedstring = parsenextc;
+	pushednleft = parsenleft;
+	parsenextc = string;
+	parsenleft = length;
+}
+
+
+
+/*
+ * Set the input to take input from a file.  If push is set, push the
+ * old input onto the stack first.
+ */
+
+void
+setinputfile(fname, push)
+	char *fname;
+	{
+	int fd;
+	int fd2;
+
+	INTOFF;
+	if ((fd = open(fname, O_RDONLY)) < 0)
+		error("Can't open %s", fname);
+	if (fd < 10) {
+		fd2 = copyfd(fd, 10);
+		close(fd);
+		if (fd2 < 0)
+			error("Out of file descriptors");
+		fd = fd2;
+	}
+	setinputfd(fd, push);
+	INTON;
+}
+
+
+/*
+ * Like setinputfile, but takes an open file descriptor.  Call this with
+ * interrupts off.
+ */
+
+void
+setinputfd(fd, push) {
+	(void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+	if (push) {
+		pushfile();
+		parsefile->buf = ckmalloc(BUFSIZ);
+	}
+	if (parsefile->fd > 0)
+		close(parsefile->fd);
+	parsefile->fd = fd;
+	if (parsefile->buf == NULL)
+		parsefile->buf = ckmalloc(BUFSIZ);
+	parsenleft = 0;
+	plinno = 1;
+}
+
+
+/*
+ * Like setinputfile, but takes input from a string.
+ */
+
+void
+setinputstring(string, push)
+	char *string;
+	{
+	INTOFF;
+	if (push)
+		pushfile();
+	parsenextc = string;
+	parsenleft = strlen(string);
+	parsefile->buf = NULL;
+	plinno = 1;
+	INTON;
+}
+
+
+
+/*
+ * To handle the "." command, a stack of input files is used.  Pushfile
+ * adds a new entry to the stack and popfile restores the previous level.
+ */
+
+STATIC void
+pushfile() {
+	struct parsefile *pf;
+
+	parsefile->nleft = parsenleft;
+	parsefile->nextc = parsenextc;
+	parsefile->linno = plinno;
+	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
+	pf->prev = parsefile;
+	pf->fd = -1;
+	parsefile = pf;
+}
+
+
+void
+popfile() {
+	struct parsefile *pf = parsefile;
+
+	INTOFF;
+	if (pf->fd >= 0)
+		close(pf->fd);
+	if (pf->buf)
+		ckfree(pf->buf);
+	parsefile = pf->prev;
+	ckfree(pf);
+	parsenleft = parsefile->nleft;
+	parsenextc = parsefile->nextc;
+	plinno = parsefile->linno;
+	INTON;
+}
+
+
+/*
+ * Return to top level.
+ */
+
+void
+popallfiles() {
+	while (parsefile != &basepf)
+		popfile();
+}
+
+
+
+/*
+ * Close the file(s) that the shell is reading commands from.  Called
+ * after a fork is done.
+ */
+
+void
+closescript() {
+	popallfiles();
+	if (parsefile->fd > 0) {
+		close(parsefile->fd);
+		parsefile->fd = 0;
+	}
+}
Index: /trunk/minix/commands/ash/input.h
===================================================================
--- /trunk/minix/commands/ash/input.h	(revision 9)
+++ /trunk/minix/commands/ash/input.h	(revision 9)
@@ -0,0 +1,84 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)input.h	5.1 (Berkeley) 3/7/91
+ */
+
+/* PEOF (the end of file marker) is defined in syntax.h */
+
+/*
+ * The input line number.  Input.c just defines this variable, and saves
+ * and restores it when files are pushed and popped.  The user of this
+ * package must set its value.
+ */
+extern int plinno;
+extern int parsenleft;		/* number of characters left in input buffer */
+extern char *parsenextc;	/* next character in input buffer */
+
+
+#ifdef __STDC__
+char *pfgets(char *, int);
+int pgetc(void);
+int preadbuffer(void);
+void pungetc(void);
+void ppushback(char *, int);
+void setinputfile(char *, int);
+void setinputfd(int, int);
+void setinputstring(char *, int);
+void popfile(void);
+void popallfiles(void);
+void closescript(void);
+#else
+char *pfgets();
+int pgetc();
+int preadbuffer();
+void pungetc();
+void ppushback();
+void setinputfile();
+void setinputfd();
+void setinputstring();
+void popfile();
+void popallfiles();
+void closescript();
+#endif
+
+#define pgetc_macro()	(--parsenleft >= 0? *parsenextc++ : preadbuffer())
+
+#if READLINE
+/* The variable "r_use_prompt" indicates the prompt to use with readline,
+ * *and* that readline may only be used if non-NULL.
+ */
+extern char *r_use_prompt;
+#endif
Index: /trunk/minix/commands/ash/jobs.c
===================================================================
--- /trunk/minix/commands/ash/jobs.c	(revision 9)
+++ /trunk/minix/commands/ash/jobs.c	(revision 9)
@@ -0,0 +1,1035 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)jobs.c	5.1 (Berkeley) 3/7/91";
+#endif /* not lint */
+
+#include "shell.h"
+#if JOBS
+#include "sgtty.h"
+#undef CEOF			/* syntax.h redefines this */
+#endif
+#include "main.h"
+#include "parser.h"
+#include "nodes.h"
+#include "jobs.h"
+#include "options.h"
+#include "trap.h"
+#include "signames.h"
+#include "syntax.h"
+#include "input.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+#include "redir.h"
+#include <sys/types.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#ifdef BSD
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+#if POSIX
+#include <sys/wait.h>
+#endif
+
+
+
+struct job *jobtab;		/* array of jobs */
+int njobs;			/* size of array */
+MKINIT pid_t backgndpid = -1;	/* pid of last background process */
+#if JOBS
+int initialpgrp;		/* pgrp of shell on invocation */
+pid_t curjob;			/* current job */
+#endif
+
+#ifdef __STDC__
+STATIC void restartjob(struct job *);
+STATIC struct job *getjob(char *);
+STATIC void freejob(struct job *);
+STATIC int procrunning(int);
+STATIC int dowait(int, struct job *);
+STATIC int waitproc(int, int *);
+STATIC char *commandtext(union node *);
+#else
+STATIC void restartjob();
+STATIC struct job *getjob();
+STATIC void freejob();
+STATIC int procrunning();
+STATIC int dowait();
+STATIC int waitproc();
+STATIC char *commandtext();
+#endif
+
+
+ 
+#if JOBS
+/*
+ * Turn job control on and off.
+ *
+ * Note:  This code assumes that the third arg to ioctl is a character
+ * pointer, which is true on Berkeley systems but not System V.  Since
+ * System V doesn't have job control yet, this isn't a problem now.
+ */
+
+MKINIT int jobctl;
+
+void
+setjobctl(on) {
+	int ldisc;
+
+	if (on == jobctl || rootshell == 0)
+		return;
+	if (on) {
+		do { /* while we are in the background */
+			if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
+				out2str("ash: can't access tty; job control turned off\n");
+				jflag = 0;
+				return;
+			}
+			if (initialpgrp == -1)
+				initialpgrp = getpgrp(0);
+			else if (initialpgrp != getpgrp(0)) {
+				killpg(initialpgrp, SIGTTIN);
+				continue;
+			}
+		} while (0);
+		if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
+			out2str("ash: need new tty driver to run job control; job control turned off\n");
+			jflag = 0;
+			return;
+		}
+		setsignal(SIGTSTP);
+		setsignal(SIGTTOU);
+		setpgrp(0, rootpid);
+		ioctl(2, TIOCSPGRP, (char *)&rootpid);
+	} else { /* turning job control off */
+		setpgrp(0, initialpgrp);
+		ioctl(2, TIOCSPGRP, (char *)&initialpgrp);
+		setsignal(SIGTSTP);
+		setsignal(SIGTTOU);
+	}
+	jobctl = on;
+}
+#endif
+
+
+#ifdef mkinit
+
+SHELLPROC {
+	backgndpid = -1;
+#if JOBS
+	jobctl = 0;
+#endif
+}
+
+#endif
+
+
+
+#if JOBS
+fgcmd(argc, argv)  char **argv; {
+	struct job *jp;
+	int pgrp;
+	int status;
+
+	jp = getjob(argv[1]);
+	if (jp->jobctl == 0)
+		error("job not created under job control");
+	pgrp = jp->ps[0].pid;
+	ioctl(2, TIOCSPGRP, (char *)&pgrp);
+	restartjob(jp);
+	INTOFF;
+	status = waitforjob(jp);
+	INTON;
+	return status;
+}
+
+
+bgcmd(argc, argv)  char **argv; {
+	struct job *jp;
+
+	do {
+		jp = getjob(*++argv);
+		if (jp->jobctl == 0)
+			error("job not created under job control");
+		restartjob(jp);
+	} while (--argc > 1);
+	return 0;
+}
+
+
+STATIC void
+restartjob(jp)
+	struct job *jp;
+	{
+	struct procstat *ps;
+	int i;
+
+	if (jp->state == JOBDONE)
+		return;
+	INTOFF;
+	killpg(jp->ps[0].pid, SIGCONT);
+	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
+		if ((ps->status & 0377) == 0177) {
+			ps->status = -1;
+			jp->state = 0;
+		}
+	}
+	INTON;
+}
+#endif
+
+
+int
+jobscmd(argc, argv)  char **argv; {
+	showjobs(0);
+	return 0;
+}
+
+
+/*
+ * Print a list of jobs.  If "change" is nonzero, only print jobs whose
+ * statuses have changed since the last call to showjobs.
+ *
+ * If the shell is interrupted in the process of creating a job, the
+ * result may be a job structure containing zero processes.  Such structures
+ * will be freed here.
+ */
+
+void
+showjobs(change) {
+	int jobno;
+	int procno;
+	int i;
+	struct job *jp;
+	struct procstat *ps;
+	int col;
+	char s[64];
+
+	TRACE(("showjobs(%d) called\n", change));
+	while (dowait(0, (struct job *)NULL) > 0);
+	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
+		if (! jp->used)
+			continue;
+		if (jp->nprocs == 0) {
+			freejob(jp);
+			continue;
+		}
+		if (change && ! jp->changed)
+			continue;
+		procno = jp->nprocs;
+		for (ps = jp->ps ; ; ps++) {	/* for each process */
+			if (ps == jp->ps)
+				fmtstr(s, 64, "[%d] %d ", jobno, ps->pid);
+			else
+				fmtstr(s, 64, "    %d ", ps->pid);
+			out1str(s);
+			col = strlen(s);
+			s[0] = '\0';
+			if (ps->status == -1) {
+				/* don't print anything */
+			} else if ((ps->status & 0xFF) == 0) {
+				fmtstr(s, 64, "Exit %d", ps->status >> 8);
+			} else {
+				i = ps->status;
+#if JOBS
+				if ((i & 0xFF) == 0177)
+					i >>= 8;
+#endif
+				if ((i & 0x7F) <= MAXSIG && sigmesg[i & 0x7F])
+					scopy(sigmesg[i & 0x7F], s);
+				else
+					fmtstr(s, 64, "Signal %d", i & 0x7F);
+				if (i & 0x80)
+					strcat(s, " (core dumped)");
+			}
+			out1str(s);
+			col += strlen(s);
+			do {
+				out1c(' ');
+				col++;
+			} while (col < 30);
+			out1str(ps->cmd);
+			out1c('\n');
+			if (--procno <= 0)
+				break;
+		}
+		jp->changed = 0;
+		if (jp->state == JOBDONE) {
+			freejob(jp);
+		}
+	}
+}
+
+
+/*
+ * Mark a job structure as unused.
+ */
+
+STATIC void
+freejob(jp)
+	struct job *jp;
+	{
+	struct procstat *ps;
+	int i;
+
+	INTOFF;
+	for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
+		if (ps->cmd != nullstr)
+			ckfree(ps->cmd);
+	}
+	if (jp->ps != &jp->ps0)
+		ckfree(jp->ps);
+	jp->used = 0;
+#if JOBS
+	if (curjob == jp - jobtab + 1)
+		curjob = 0;
+#endif
+	INTON;
+}
+
+
+
+int
+waitcmd(argc, argv)  char **argv; {
+	struct job *job;
+	int status;
+	struct job *jp;
+
+	if (argc > 1) {
+		job = getjob(argv[1]);
+	} else {
+		job = NULL;
+	}
+	for (;;) {	/* loop until process terminated or stopped */
+		if (job != NULL) {
+			if (job->state) {
+				status = job->ps[job->nprocs - 1].status;
+				if ((status & 0xFF) == 0)
+					status = status >> 8 & 0xFF;
+#if JOBS
+				else if ((status & 0xFF) == 0177)
+					status = (status >> 8 & 0x7F) + 128;
+#endif
+				else
+					status = (status & 0x7F) + 128;
+				if (! iflag)
+					freejob(job);
+				return status;
+			}
+		} else {
+			for (jp = jobtab ; ; jp++) {
+				if (jp >= jobtab + njobs) {	/* no running procs */
+					return 0;
+				}
+				if (jp->used && jp->state == 0)
+					break;
+			}
+		}
+		dowait(1, (struct job *)NULL);
+	}
+}
+
+
+
+jobidcmd(argc, argv)  char **argv; {
+	struct job *jp;
+	int i;
+
+	jp = getjob(argv[1]);
+	for (i = 0 ; i < jp->nprocs ; ) {
+		out1fmt("%d", jp->ps[i].pid);
+		out1c(++i < jp->nprocs? ' ' : '\n');
+	}
+	return 0;
+}
+
+
+
+/*
+ * Convert a job name to a job structure.
+ */
+
+STATIC struct job *
+getjob(name)
+	char *name;
+	{
+	int jobno;
+	register struct job *jp;
+	int pid;
+	int i;
+
+	if (name == NULL) {
+#if JOBS
+currentjob:
+		if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
+			error("No current job");
+		return &jobtab[jobno - 1];
+#else
+		error("No current job");
+#endif
+	} else if (name[0] == '%') {
+		if (is_digit(name[1])) {
+			jobno = number(name + 1);
+			if (jobno > 0 && jobno <= njobs
+			 && jobtab[jobno - 1].used != 0)
+				return &jobtab[jobno - 1];
+#if JOBS
+		} else if (name[1] == '%' && name[2] == '\0') {
+			goto currentjob;
+#endif
+		} else {
+			register struct job *found = NULL;
+			for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
+				if (jp->used && jp->nprocs > 0
+				 && prefix(name + 1, jp->ps[0].cmd)) {
+					if (found)
+						error("%s: ambiguous", name);
+					found = jp;
+				}
+			}
+			if (found)
+				return found;
+		}
+	} else if (is_number(name)) {
+		pid = number(name);
+		for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
+			if (jp->used && jp->nprocs > 0
+			 && jp->ps[jp->nprocs - 1].pid == pid)
+				return jp;
+		}
+	}
+	error("No such job: %s", name);
+}
+
+
+
+/*
+ * Return a new job structure,
+ */
+
+struct job *
+makejob(node, nprocs)
+	union node *node;
+	{
+	int i;
+	struct job *jp;
+
+	for (i = njobs, jp = jobtab ; ; jp++) {
+		if (--i < 0) {
+			INTOFF;
+			if (njobs == 0) {
+				jobtab = ckmalloc(4 * sizeof jobtab[0]);
+			} else {
+				jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
+				bcopy(jobtab, jp, njobs * sizeof jp[0]);
+				for (i= 0; i<njobs; i++)
+				{
+					if (jobtab[i].ps == &jobtab[i].ps0)
+						jp[i].ps= &jp[i].ps0;
+				}
+				ckfree(jobtab);
+				jobtab = jp;
+			}
+			jp = jobtab + njobs;
+			for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
+			INTON;
+			break;
+		}
+		if (jp->used == 0)
+			break;
+	}
+	INTOFF;
+	jp->state = 0;
+	jp->used = 1;
+	jp->changed = 0;
+	jp->nprocs = 0;
+#if JOBS
+	jp->jobctl = jobctl;
+#endif
+	if (nprocs > 1) {
+		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
+	} else {
+		jp->ps = &jp->ps0;
+	}
+	INTON;
+	TRACE(("makejob(0x%x, %d) returns %%%d\n", (int)node, nprocs, jp - jobtab + 1));
+	return jp;
+}	
+
+
+/*
+ * Fork of a subshell.  If we are doing job control, give the subshell its
+ * own process group.  Jp is a job structure that the job is to be added to.
+ * N is the command that will be evaluated by the child.  Both jp and n may
+ * be NULL.  The mode parameter can be one of the following:
+ *	FORK_FG - Fork off a foreground process.
+ *	FORK_BG - Fork off a background process.
+ *	FORK_NOJOB - Like FORK_FG, but don't give the process its own
+ *		     process group even if job control is on.
+ *
+ * When job control is turned off, background processes have their standard
+ * input redirected to /dev/null (except for the second and later processes
+ * in a pipeline).
+ */
+
+int
+forkshell(jp, n, mode)
+	union node *n;
+	struct job *jp;
+	{
+	int pid;
+	int pgrp;
+
+	TRACE(("forkshell(%%%d, 0x%x, %d) called\n", jp - jobtab, (int)n, mode));
+	INTOFF;
+	pid = fork();
+	if (pid == -1) {
+		TRACE(("Fork failed, errno=%d\n", errno));
+		INTON;
+		error("Cannot fork");
+	}
+	if (pid == 0) {
+		struct job *p;
+		int wasroot;
+		int i;
+
+		TRACE(("Child shell %d\n", getpid()));
+		wasroot = rootshell;
+		rootshell = 0;
+		for (i = njobs, p = jobtab ; --i >= 0 ; p++)
+			if (p->used)
+				freejob(p);
+		closescript();
+		INTON;
+		clear_traps();
+#if JOBS
+		jobctl = 0;		/* do job control only in root shell */
+		if (wasroot && mode != FORK_NOJOB && jflag) {
+			if (jp == NULL || jp->nprocs == 0)
+				pgrp = getpid();
+			else
+				pgrp = jp->ps[0].pid;
+			setpgrp(0, pgrp);
+			if (mode == FORK_FG) {
+				/*** this causes superfluous TIOCSPGRPS ***/
+				if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
+					error("TIOCSPGRP failed, errno=%d\n", errno);
+			}
+			setsignal(SIGTSTP);
+			setsignal(SIGTTOU);
+		} else if (mode == FORK_BG) {
+			ignoresig(SIGINT);
+			ignoresig(SIGQUIT);
+			if ((jp == NULL || jp->nprocs == 0)
+			    && ! fd0_redirected_p ()) {
+				close(0);
+				if (open("/dev/null", O_RDONLY) != 0)
+					error("Can't open /dev/null");
+			}
+		}
+#else
+		if (mode == FORK_BG) {
+			ignoresig(SIGINT);
+			ignoresig(SIGQUIT);
+			if ((jp == NULL || jp->nprocs == 0)
+			    && ! fd0_redirected_p ()) {
+				close(0);
+				if (open("/dev/null", O_RDONLY) != 0)
+					error("Can't open /dev/null");
+			}
+		}
+#endif
+		if (wasroot && iflag) {
+			setsignal(SIGINT);
+			setsignal(SIGQUIT);
+			setsignal(SIGTERM);
+		}
+		return pid;
+	}
+	if (rootshell && mode != FORK_NOJOB && jflag) {
+		if (jp == NULL || jp->nprocs == 0)
+			pgrp = pid;
+		else
+			pgrp = jp->ps[0].pid;
+#if JOBS
+		setpgrp(pid, pgrp);
+#endif
+	}
+	if (mode == FORK_BG)
+		backgndpid = pid;		/* set $! */
+	if (jp) {
+		struct procstat *ps = &jp->ps[jp->nprocs++];
+		ps->pid = pid;
+		ps->status = -1;
+		ps->cmd = nullstr;
+		if (iflag && rootshell && n)
+			ps->cmd = commandtext(n);
+	}
+	INTON;
+	TRACE(("In parent shell:  child = %d\n", pid));
+	return pid;
+}
+
+
+
+/*
+ * Wait for job to finish.
+ *
+ * Under job control we have the problem that while a child process is
+ * running interrupts generated by the user are sent to the child but not
+ * to the shell.  This means that an infinite loop started by an inter-
+ * active user may be hard to kill.  With job control turned off, an
+ * interactive user may place an interactive program inside a loop.  If
+ * the interactive program catches interrupts, the user doesn't want
+ * these interrupts to also abort the loop.  The approach we take here
+ * is to have the shell ignore interrupt signals while waiting for a
+ * forground process to terminate, and then send itself an interrupt
+ * signal if the child process was terminated by an interrupt signal.
+ * Unfortunately, some programs want to do a bit of cleanup and then
+ * exit on interrupt; unless these processes terminate themselves by
+ * sending a signal to themselves (instead of calling exit) they will
+ * confuse this approach.
+ */
+
+int
+waitforjob(jp)
+	register struct job *jp;
+	{
+#if JOBS
+	int mypgrp = getpgrp(0);
+#endif
+	int status;
+	int st;
+
+	INTOFF;
+	TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
+	while (jp->state == 0 && dowait(1, jp) != -1) ;
+#if JOBS
+	if (jp->jobctl) {
+		if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
+			error("TIOCSPGRP failed, errno=%d\n", errno);
+	}
+	if (jp->state == JOBSTOPPED)
+		curjob = jp - jobtab + 1;
+#endif
+	status = jp->ps[jp->nprocs - 1].status;
+	/* convert to 8 bits */
+	if ((status & 0xFF) == 0)
+		st = status >> 8 & 0xFF;
+#if JOBS
+	else if ((status & 0xFF) == 0177)
+		st = (status >> 8 & 0x7F) + 128;
+#endif
+	else
+		st = (status & 0x7F) + 128;
+	if (! JOBS || jp->state == JOBDONE)
+		freejob(jp);
+	CLEAR_PENDING_INT;
+	if ((status & 0x7F) == SIGINT)
+		kill(getpid(), SIGINT);
+	INTON;
+	return st;
+}
+
+
+
+/*
+ * Wait for a process to terminate.
+ */
+
+STATIC int
+dowait(block, job)
+	struct job *job;
+	{
+	int pid;
+	int status;
+	struct procstat *sp;
+	struct job *jp;
+	struct job *thisjob;
+	int done;
+	int stopped;
+	int core;
+
+	TRACE(("dowait(%d) called\n", block));
+	do {
+		pid = waitproc(block, &status);
+		TRACE(("wait returns %d, status=%d, errno=%d\n",
+				pid, status, errno));
+	} while (pid == -1 && errno == EINTR);
+	if (pid <= 0)
+		return pid;
+	INTOFF;
+	thisjob = NULL;
+	for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
+		if (jp->used) {
+			done = 1;
+			stopped = 1;
+			for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
+				if (sp->pid == -1)
+					continue;
+				if (sp->pid == pid) {
+					TRACE(("Changin status of proc %d from 0x%x to 0x%x\n", pid, sp->status, status));
+					sp->status = status;
+					thisjob = jp;
+				}
+				if (sp->status == -1)
+					stopped = 0;
+				else if ((sp->status & 0377) == 0177)
+					done = 0;
+			}
+			if (stopped) {		/* stopped or done */
+				int state = done? JOBDONE : JOBSTOPPED;
+				if (jp->state != state) {
+					TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
+					jp->state = state;
+#if JOBS
+					if (done && curjob == jp - jobtab + 1)
+						curjob = 0;		/* no current job */
+#endif
+				}
+			}
+		}
+	}
+	INTON;
+	if (! rootshell || ! iflag || (job && thisjob == job)) {
+#if JOBS
+		if ((status & 0xFF) == 0177)
+			status >>= 8;
+#endif
+		core = status & 0x80;
+		status &= 0x7F;
+		if (status != 0 && status != SIGINT && status != SIGPIPE) {
+			if (thisjob != job)
+				outfmt(out2, "%d: ", pid);
+#if JOBS
+			if (status == SIGTSTP && rootshell && iflag)
+				outfmt(out2, "%%%d ", job - jobtab + 1);
+#endif
+			if (status <= MAXSIG && sigmesg[status])
+				out2str(sigmesg[status]);
+			else
+				outfmt(out2, "Signal %d", status);
+			if (core)
+				out2str(" - core dumped");
+			out2c('\n');
+			flushout(&errout);
+		} else {
+			TRACE(("Not printing status: status=%d\n", status));
+		}
+	} else {
+		TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job));
+		if (thisjob)
+			thisjob->changed = 1;
+	}
+	return pid;
+}
+
+
+
+/*
+ * Do a wait system call.  If job control is compiled in, we accept
+ * stopped processes.  If block is zero, we return a value of zero
+ * rather than blocking.
+ *
+ * System V doesn't have a non-blocking wait system call.  It does
+ * have a SIGCLD signal that is sent to a process when one of it's
+ * children dies.  The obvious way to use SIGCLD would be to install
+ * a handler for SIGCLD which simply bumped a counter when a SIGCLD
+ * was received, and have waitproc bump another counter when it got
+ * the status of a process.  Waitproc would then know that a wait
+ * system call would not block if the two counters were different.
+ * This approach doesn't work because if a process has children that
+ * have not been waited for, System V will send it a SIGCLD when it
+ * installs a signal handler for SIGCLD.  What this means is that when
+ * a child exits, the shell will be sent SIGCLD signals continuously
+ * until is runs out of stack space, unless it does a wait call before
+ * restoring the signal handler.  The code below takes advantage of
+ * this (mis)feature by installing a signal handler for SIGCLD and
+ * then checking to see whether it was called.  If there are any
+ * children to be waited for, it will be.
+ *
+ * If neither SYSV nor BSD is defined, we don't implement nonblocking
+ * waits at all.  In this case, the user will not be informed when
+ * a background process until the next time she runs a real program
+ * (as opposed to running a builtin command or just typing return),
+ * and the jobs command may give out of date information.
+ */
+
+#ifdef SYSV
+STATIC int gotsigchild;
+
+STATIC int onsigchild() {
+	gotsigchild = 1;
+}
+#endif
+
+
+STATIC int
+waitproc(block, status)
+	int *status;
+	{
+#ifdef BSD
+	int flags;
+
+#if JOBS
+	flags = WUNTRACED;
+#else
+	flags = 0;
+#endif
+	if (block == 0)
+		flags |= WNOHANG;
+	return wait3((union wait *)status, flags, (struct rusage *)NULL);
+#else
+#ifdef SYSV
+	int (*save)();
+
+	if (block == 0) {
+		gotsigchild = 0;
+		save = signal(SIGCLD, onsigchild);
+		signal(SIGCLD, save);
+		if (gotsigchild == 0)
+			return 0;
+	}
+	return wait(status);
+#else
+#if POSIX
+	return waitpid(-1, status, block == 0 ? WNOHANG : 0);
+#else
+	if (block == 0)
+		return 0;
+	return wait(status);
+#endif
+#endif
+#endif
+}
+
+
+
+/*
+ * Return a string identifying a command (to be printed by the
+ * jobs command.
+ */
+
+STATIC char *cmdnextc;
+STATIC int cmdnleft;
+STATIC void cmdtxt(), cmdputs();
+
+STATIC char *
+commandtext(n)
+	union node *n;
+	{
+	char *name;
+
+	cmdnextc = name = ckmalloc(50);
+	cmdnleft = 50 - 4;
+	cmdtxt(n);
+	*cmdnextc = '\0';
+	return name;
+}
+
+
+STATIC void
+cmdtxt(n)
+	union node *n;
+	{
+	union node *np;
+	struct nodelist *lp;
+	char *p;
+	int i;
+	char s[2];
+
+	if (n == NULL) return;
+
+	switch (n->type) {
+	case NSEMI:
+		cmdtxt(n->nbinary.ch1);
+		cmdputs("; ");
+		cmdtxt(n->nbinary.ch2);
+		break;
+	case NAND:
+		cmdtxt(n->nbinary.ch1);
+		cmdputs(" && ");
+		cmdtxt(n->nbinary.ch2);
+		break;
+	case NOR:
+		cmdtxt(n->nbinary.ch1);
+		cmdputs(" || ");
+		cmdtxt(n->nbinary.ch2);
+		break;
+	case NPIPE:
+		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
+			cmdtxt(lp->n);
+			if (lp->next)
+				cmdputs(" | ");
+		}
+		break;
+	case NSUBSHELL:
+		cmdputs("(");
+		cmdtxt(n->nredir.n);
+		cmdputs(")");
+		break;
+	case NREDIR:
+	case NBACKGND:
+		cmdtxt(n->nredir.n);
+		break;
+	case NIF:
+		cmdputs("if ");
+		cmdtxt(n->nif.test);
+		cmdputs("; then ");
+		cmdtxt(n->nif.ifpart);
+		cmdputs("...");
+		break;
+	case NWHILE:
+		cmdputs("while ");
+		goto until;
+	case NUNTIL:
+		cmdputs("until ");
+until:
+		cmdtxt(n->nbinary.ch1);
+		cmdputs("; do ");
+		cmdtxt(n->nbinary.ch2);
+		cmdputs("; done");
+		break;
+	case NFOR:
+		cmdputs("for ");
+		cmdputs(n->nfor.var);
+		cmdputs(" in ...");
+		break;
+	case NCASE:
+		cmdputs("case ");
+		cmdputs(n->ncase.expr->narg.text);
+		cmdputs(" in ...");
+		break;
+	case NDEFUN:
+		cmdputs(n->narg.text);
+		cmdputs("() ...");
+		break;
+	case NCMD:
+		for (np = n->ncmd.args ; np ; np = np->narg.next) {
+			cmdtxt(np);
+			if (np->narg.next)
+				cmdputs(" ");
+		}
+		for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
+			cmdputs(" ");
+			cmdtxt(np);
+		}
+		break;
+	case NARG:
+		cmdputs(n->narg.text);
+		break;
+	case NTO:
+		p = ">";  i = 1;  goto redir;
+	case NAPPEND:
+		p = ">>";  i = 1;  goto redir;
+	case NTOFD:
+		p = ">&";  i = 1;  goto redir;
+	case NFROM:
+		p = "<";  i = 0;  goto redir;
+	case NFROMFD:
+		p = "<&";  i = 0;  goto redir;
+redir:
+		if (n->nfile.fd != i) {
+			s[0] = n->nfile.fd + '0';
+			s[1] = '\0';
+			cmdputs(s);
+		}
+		cmdputs(p);
+		if (n->type == NTOFD || n->type == NFROMFD) {
+			s[0] = n->ndup.dupfd + '0';
+			s[1] = '\0';
+			cmdputs(s);
+		} else {
+			cmdtxt(n->nfile.fname);
+		}
+		break;
+	case NHERE:
+	case NXHERE:
+		cmdputs("<<...");
+		break;
+	default:
+		cmdputs("???");
+		break;
+	}
+}
+
+
+
+STATIC void
+cmdputs(s)
+	char *s;
+	{
+	register char *p, *q;
+	register char c;
+	int subtype = 0;
+
+	if (cmdnleft <= 0)
+		return;
+	p = s;
+	q = cmdnextc;
+	while ((c = *p++) != '\0') {
+		if (c == CTLESC)
+			*q++ = *p++;
+		else if (c == CTLVAR) {
+			*q++ = '$';
+			if (--cmdnleft > 0)
+				*q++ = '{';
+			subtype = *p++;
+		} else if (c == '=' && subtype != 0) {
+			*q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
+			subtype = 0;
+		} else if (c == CTLENDVAR) {
+			*q++ = '}';
+		} else if (c == CTLBACKQ | c == CTLBACKQ+CTLQUOTE)
+			cmdnleft++;		/* ignore it */
+		else
+			*q++ = c;
+		if (--cmdnleft <= 0) {
+			*q++ = '.';
+			*q++ = '.';
+			*q++ = '.';
+			break;
+		}
+	}
+	cmdnextc = q;
+}
Index: /trunk/minix/commands/ash/jobs.h
===================================================================
--- /trunk/minix/commands/ash/jobs.h	(revision 9)
+++ /trunk/minix/commands/ash/jobs.h	(revision 9)
@@ -0,0 +1,96 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)jobs.h	5.1 (Berkeley) 3/7/91
+ */
+
+/* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
+#define FORK_FG 0
+#define FORK_BG 1
+#define FORK_NOJOB 2
+
+
+/*
+ * A job structure contains information about a job.  A job is either a
+ * single process or a set of processes contained in a pipeline.  In the
+ * latter case, pidlist will be non-NULL, and will point to a -1 terminated
+ * array of pids.
+ */
+
+struct procstat {
+	pid_t pid;		/* process id */
+	short status;		/* status flags (defined above) */
+	char *cmd;		/* text of command being run */
+};
+
+
+/* states */
+#define JOBSTOPPED 1		/* all procs are stopped */
+#define JOBDONE 2		/* all procs are completed */
+
+
+struct job {
+	struct procstat ps0;	/* status of process */
+	struct procstat *ps;	/* status or processes when more than one */
+	pid_t nprocs;		/* number of processes */
+	pid_t pgrp;		/* process group of this job */
+	char state;		/* true if job is finished */
+	char used;		/* true if this entry is in used */
+	char changed;		/* true if status has changed */
+#if JOBS
+	char jobctl;		/* job running under job control */
+#endif
+};
+
+extern pid_t backgndpid;	/* pid of last background process */
+
+
+#ifdef __STDC__
+void setjobctl(int);
+void showjobs(int);
+struct job *makejob(union node *, int);
+int forkshell(struct job *, union node *, int);
+int waitforjob(struct job *);
+#else
+void setjobctl();
+void showjobs();
+struct job *makejob();
+int forkshell();
+int waitforjob();
+#endif
+
+#if ! JOBS
+#define setjobctl(on)	/* do nothing */
+#endif
Index: /trunk/minix/commands/ash/machdep.h
===================================================================
--- /trunk/minix/commands/ash/machdep.h	(revision 9)
+++ /trunk/minix/commands/ash/machdep.h	(revision 9)
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)machdep.h	5.1 (Berkeley) 3/7/91
+ */
+
+/*
+ * Most machines require the value returned from malloc to be aligned
+ * in some way.  The following macro will get this right on many machines.
+ */
+
+#ifndef ALIGN
+union align {
+	int i;
+	char *cp;
+};
+
+#define ALIGN(nbytes)	((nbytes) + sizeof(union align) - 1 &~ (sizeof(union align) - 1))
+#endif
Index: /trunk/minix/commands/ash/mail.c
===================================================================
--- /trunk/minix/commands/ash/mail.c	(revision 9)
+++ /trunk/minix/commands/ash/mail.c	(revision 9)
@@ -0,0 +1,108 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)mail.c	5.1 (Berkeley) 3/7/91";
+#endif /* not lint */
+
+/*
+ * Routines to check for mail.  (Perhaps make part of main.c?)
+ */
+
+#include "shell.h"
+#include "exec.h"	/* defines padvance() */
+#include "var.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+#define MAXMBOXES 10
+
+
+STATIC int nmboxes;			/* number of mailboxes */
+STATIC time_t mailtime[MAXMBOXES];	/* times of mailboxes */
+
+
+
+/*
+ * Print appropriate message(s) if mail has arrived.  If the argument is
+ * nozero, then the value of MAIL has changed, so we just update the
+ * values.
+ */
+
+void
+chkmail(silent) {
+	register int i;
+	char *mpath;
+	char *p;
+	register char *q;
+	struct stackmark smark;
+	struct stat statb;
+
+	if (silent)
+		nmboxes = 10;
+	if (nmboxes == 0)
+		return;
+	setstackmark(&smark);
+	mpath = mpathset()? mpathval() : mailval();
+	for (i = 0 ; i < nmboxes ; i++) {
+		p = padvance(&mpath, nullstr);
+		if (p == NULL)
+			break;
+		if (*p == '\0')
+			continue;
+		for (q = p ; *q ; q++);
+		if (q[-1] != '/')
+			abort();
+		q[-1] = '\0';			/* delete trailing '/' */
+		if (stat(p, &statb) < 0)
+			statb.st_mtime = 0;
+		if (!silent
+			&& statb.st_size > 0
+			&& statb.st_mtime > mailtime[i]
+			&& statb.st_mtime > statb.st_atime
+		) {
+			out2str(pathopt? pathopt : "You have mail");
+			out2c('\n');
+		}
+		mailtime[i] = statb.st_mtime;
+	}
+	nmboxes = i;
+	popstackmark(&smark);
+}
Index: /trunk/minix/commands/ash/mail.h
===================================================================
--- /trunk/minix/commands/ash/mail.h	(revision 9)
+++ /trunk/minix/commands/ash/mail.h	(revision 9)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)mail.h	5.1 (Berkeley) 3/7/91
+ */
+
+#ifdef __STDC__
+void chkmail(int);
+#else
+void chkmail();
+#endif
Index: /trunk/minix/commands/ash/main.c
===================================================================
--- /trunk/minix/commands/ash/main.c	(revision 9)
+++ /trunk/minix/commands/ash/main.c	(revision 9)
@@ -0,0 +1,359 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)main.c	5.2 (Berkeley) 3/13/91";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <signal.h>
+#include <fcntl.h>
+#include "shell.h"
+#include "main.h"
+#include "mail.h"
+#include "options.h"
+#include "output.h"
+#include "parser.h"
+#include "nodes.h"
+#include "eval.h"
+#include "jobs.h"
+#include "input.h"
+#include "trap.h"
+#if ATTY
+#include "var.h"
+#endif
+#include "memalloc.h"
+#include "error.h"
+#include "init.h"
+#include "mystring.h"
+
+#define PROFILE 0
+
+int rootpid;
+int rootshell;
+STATIC union node *curcmd;
+STATIC union node *prevcmd;
+extern int errno;
+#if PROFILE
+short profile_buf[16384];
+extern int etext();
+#endif
+
+#ifdef __STDC__
+STATIC void read_profile(char *);
+char *getenv(char *);
+#else
+STATIC void read_profile();
+char *getenv();
+#endif
+
+
+/*
+ * Main routine.  We initialize things, parse the arguments, execute
+ * profiles if we're a login shell, and then call cmdloop to execute
+ * commands.  The setjmp call sets up the location to jump to when an
+ * exception occurs.  When an exception occurs the variable "state"
+ * is used to figure out how far we had gotten.
+ */
+
+main(argc, argv)  char **argv; {
+	struct jmploc jmploc;
+	struct stackmark smark;
+	volatile int state;
+	char *shinit, *home;
+	char *profile = NULL, *ashrc = NULL;
+
+#if PROFILE
+	monitor(4, etext, profile_buf, sizeof profile_buf, 50);
+#endif
+	state = 0;
+	if (setjmp(jmploc.loc)) {
+		/*
+		 * When a shell procedure is executed, we raise the
+		 * exception EXSHELLPROC to clean up before executing
+		 * the shell procedure.
+		 */
+		if (exception == EXSHELLPROC) {
+			rootpid = getpid();
+			rootshell = 1;
+			minusc = NULL;
+			state = 3;
+		} else if (state == 0 || iflag == 0 || ! rootshell)
+			exitshell(2);
+		reset();
+#if ATTY
+		if (exception == EXINT
+		 && (! attyset() || equal(termval(), "emacs"))) {
+#else
+		if (exception == EXINT) {
+#endif
+			out2c('\n');
+			flushout(&errout);
+		}
+		popstackmark(&smark);
+		FORCEINTON;				/* enable interrupts */
+		if (state == 1)
+			goto state1;
+		else if (state == 2)
+			goto state2;
+		else if (state == 3)
+			goto state3;
+		else
+			goto state4;
+	}
+	handler = &jmploc;
+#if DEBUG
+	opentrace();
+	trputs("Shell args:  ");  trargs(argv);
+#endif
+	rootpid = getpid();
+	rootshell = 1;
+	init();
+	setstackmark(&smark);
+	procargs(argc, argv);
+	if (eflag) eflag = 2;	/* Truly enable [ex]flag after init. */
+	if (xflag) xflag = 2;
+	if (argv[0] && argv[0][0] == '-') {
+		state = 1;
+		read_profile("/etc/profile");
+state1:
+		state = 2;
+		if ((home = getenv("HOME")) != NULL
+		    && (profile = (char *) malloc(strlen(home) + 10)) != NULL)
+		{
+			strcpy(profile, home);
+			strcat(profile, "/.profile");
+			read_profile(profile);
+		} else {
+			read_profile(".profile");
+		}
+	} else if ((sflag || minusc) && (shinit = getenv("SHINIT")) != NULL) {
+		state = 2;
+		evalstring(shinit);
+	}
+state2:
+	if (profile != NULL) free(profile);
+
+	state = 3;
+	if (!argv[0] || argv[0][0] != '-') {
+		if ((home = getenv("HOME")) != NULL
+			&& (ashrc = (char *) malloc(strlen(home) + 8)) != NULL)
+		{
+			strcpy(ashrc, home);
+			strcat(ashrc, "/.ashrc");
+			read_profile(ashrc);
+		}
+	}
+state3:
+	if (ashrc != NULL) free(ashrc);
+	if (eflag) eflag = 1;	/* Init done, enable [ex]flag */
+	if (xflag) xflag = 1;
+	exitstatus = 0;		/* Init shouldn't influence initial $? */
+
+	state = 4;
+	if (minusc) {
+		evalstring(minusc);
+	}
+	if (sflag || minusc == NULL) {
+state4:
+		cmdloop(1);
+	}
+#if PROFILE
+	monitor(0);
+#endif
+	exitshell(exitstatus);
+}
+
+
+/*
+ * Read and execute commands.  "Top" is nonzero for the top level command
+ * loop; it turns on prompting if the shell is interactive.
+ */
+
+void
+cmdloop(top) {
+	union node *n;
+	struct stackmark smark;
+	int inter;
+	int numeof;
+
+	TRACE(("cmdloop(%d) called\n", top));
+	setstackmark(&smark);
+	numeof = 0;
+	for (;;) {
+		if (pendingsigs)
+			dotrap();
+		inter = 0;
+		if (iflag && top) {
+			inter++;
+			showjobs(1);
+			chkmail(0);
+			flushout(&output);
+		}
+		n = parsecmd(inter);
+#if DEBUG
+		/* showtree(n); */
+#endif
+		if (n == NEOF) {
+			if (Iflag == 0 || numeof >= 50)
+				break;
+			out2str("\nUse \"exit\" to leave shell.\n");
+			numeof++;
+		} else if (n != NULL && nflag == 0) {
+			if (inter) {
+				INTOFF;
+				if (prevcmd)
+					freefunc(prevcmd);
+				prevcmd = curcmd;
+				curcmd = copyfunc(n);
+				INTON;
+			}
+			evaltree(n, 0);
+#ifdef notdef
+			if (exitstatus)				      /*DEBUG*/
+				outfmt(&errout, "Exit status 0x%X\n", exitstatus);
+#endif
+		}
+		popstackmark(&smark);
+	}
+	popstackmark(&smark);		/* unnecessary */
+}
+
+
+
+/*
+ * Read /etc/profile or .profile.  Return on error.
+ */
+
+STATIC void
+read_profile(name)
+	char *name;
+	{
+	int fd;
+
+	INTOFF;
+	if ((fd = open(name, O_RDONLY)) >= 0)
+		setinputfd(fd, 1);
+	INTON;
+	if (fd < 0)
+		return;
+	cmdloop(0);
+	popfile();
+}
+
+
+
+/*
+ * Read a file containing shell functions.
+ */
+
+void
+readcmdfile(name)
+	char *name;
+	{
+	int fd;
+
+	INTOFF;
+	if ((fd = open(name, O_RDONLY)) >= 0)
+		setinputfd(fd, 1);
+	else
+		error("Can't open %s", name);
+	INTON;
+	cmdloop(0);
+	popfile();
+}
+
+
+/*
+ * Take commands from a file.  To be compatable we should do a path
+ * search for the file, but a path search doesn't make any sense.
+ */
+
+dotcmd(argc, argv)  char **argv; {
+	exitstatus = 0;
+	if (argc >= 2) {		/* That's what SVR2 does */
+		setinputfile(argv[1], 1);
+		commandname = argv[1];
+		cmdloop(0);
+		popfile();
+	}
+	return exitstatus;
+}
+
+
+exitcmd(argc, argv)  char **argv; {
+	extern int oexitstatus;
+	if (argc > 1)
+		exitstatus = number(argv[1]);
+	else
+		exitstatus = oexitstatus;
+	exitshell(exitstatus);
+}
+
+
+lccmd(argc, argv)  char **argv; {
+	if (argc > 1) {
+		defun(argv[1], prevcmd);
+		return 0;
+	} else {
+		INTOFF;
+		freefunc(curcmd);
+		curcmd = prevcmd;
+		prevcmd = NULL;
+		INTON;
+		evaltree(curcmd, 0);
+		return exitstatus;
+	}
+}
+
+
+
+#ifdef notdef
+/*
+ * Should never be called.
+ */
+
+void
+exit(exitstatus) {
+	_exit(exitstatus);
+}
+#endif
Index: /trunk/minix/commands/ash/main.h
===================================================================
--- /trunk/minix/commands/ash/main.h	(revision 9)
+++ /trunk/minix/commands/ash/main.h	(revision 9)
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)main.h	5.1 (Berkeley) 3/7/91
+ */
+
+extern int rootpid;	/* pid of main shell */
+extern int rootshell;	/* true if we aren't a child of the main shell */
+
+#ifdef __STDC__
+void readcmdfile(char *);
+void cmdloop(int);
+#else
+void readcmdfile();
+void cmdloop();
+#endif
Index: /trunk/minix/commands/ash/memalloc.c
===================================================================
--- /trunk/minix/commands/ash/memalloc.c	(revision 9)
+++ /trunk/minix/commands/ash/memalloc.c	(revision 9)
@@ -0,0 +1,292 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)memalloc.c	5.2 (Berkeley) 3/13/91";
+#endif /* not lint */
+
+#include "shell.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "machdep.h"
+#include "mystring.h"
+
+/*
+ * Like malloc, but returns an error when out of space.
+ */
+
+pointer
+ckmalloc(nbytes) {
+	register pointer p;
+	pointer malloc();
+
+	if ((p = malloc(nbytes)) == NULL)
+		error("Out of space");
+	return p;
+}
+
+
+/*
+ * Same for realloc.
+ */
+
+pointer
+ckrealloc(p, nbytes)
+	register pointer p;
+	{
+	pointer realloc();
+
+	if ((p = realloc(p, nbytes)) == NULL)
+		error("Out of space");
+	return p;
+}
+
+
+/*
+ * Make a copy of a string in safe storage.
+ */
+
+char *
+savestr(s)
+	char *s;
+	{
+	register char *p;
+
+	p = ckmalloc(strlen(s) + 1);
+	scopy(s, p);
+	return p;
+}
+
+
+/*
+ * Parse trees for commands are allocated in lifo order, so we use a stack
+ * to make this more efficient, and also to avoid all sorts of exception
+ * handling code to handle interrupts in the middle of a parse.
+ *
+ * The size 504 was chosen because the Ultrix malloc handles that size
+ * well.
+ */
+
+#define MINSIZE 504		/* minimum size of a block */
+
+
+struct stack_block {
+	struct stack_block *prev;
+	char space[MINSIZE];
+};
+
+struct stack_block stackbase;
+struct stack_block *stackp = &stackbase;
+char *stacknxt = stackbase.space;
+int stacknleft = MINSIZE;
+int sstrnleft;
+int herefd = -1;
+
+
+
+pointer
+stalloc(nbytes) {
+	register char *p;
+
+	nbytes = ALIGN(nbytes);
+	if (nbytes > stacknleft) {
+		int blocksize;
+		struct stack_block *sp;
+
+		blocksize = nbytes;
+		if (blocksize < MINSIZE)
+			blocksize = MINSIZE;
+		INTOFF;
+		sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
+		sp->prev = stackp;
+		stacknxt = sp->space;
+		stacknleft = blocksize;
+		stackp = sp;
+		INTON;
+	}
+	p = stacknxt;
+	stacknxt += nbytes;
+	stacknleft -= nbytes;
+	return p;
+}
+
+
+void
+stunalloc(p)
+	pointer p;
+	{
+	if (p == NULL) {		/*DEBUG */
+		write(2, "stunalloc\n", 10);
+		abort();
+	}
+	stacknleft += stacknxt - (char *)p;
+	stacknxt = p;
+}
+
+
+
+void
+setstackmark(mark)
+	struct stackmark *mark;
+	{
+	mark->stackp = stackp;
+	mark->stacknxt = stacknxt;
+	mark->stacknleft = stacknleft;
+}
+
+
+void
+popstackmark(mark)
+	struct stackmark *mark;
+	{
+	struct stack_block *sp;
+
+	INTOFF;
+	while (stackp != mark->stackp) {
+		sp = stackp;
+		stackp = sp->prev;
+		ckfree(sp);
+	}
+	stacknxt = mark->stacknxt;
+	stacknleft = mark->stacknleft;
+	INTON;
+}
+
+
+/*
+ * When the parser reads in a string, it wants to stick the string on the
+ * stack and only adjust the stack pointer when it knows how big the
+ * string is.  Stackblock (defined in stack.h) returns a pointer to a block
+ * of space on top of the stack and stackblocklen returns the length of
+ * this block.  Growstackblock will grow this space by at least one byte,
+ * possibly moving it (like realloc).  Grabstackblock actually allocates the
+ * part of the block that has been used.
+ */
+
+void
+growstackblock() {
+	char *p;
+	int newlen = stacknleft * 2 + 100;
+	char *oldspace = stacknxt;
+	int oldlen = stacknleft;
+	struct stack_block *sp;
+
+	if (stacknxt == stackp->space && stackp != &stackbase) {
+		INTOFF;
+		sp = stackp;
+		stackp = sp->prev;
+		sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
+		sp->prev = stackp;
+		stackp = sp;
+		stacknxt = sp->space;
+		stacknleft = newlen;
+		INTON;
+	} else {
+		p = stalloc(newlen);
+		bcopy(oldspace, p, oldlen);
+		stacknxt = p;			/* free the space */
+		stacknleft += newlen;		/* we just allocated */
+	}
+}
+
+
+
+void
+grabstackblock(len) {
+	len = ALIGN(len);
+	stacknxt += len;
+	stacknleft -= len;
+}
+
+
+
+/*
+ * The following routines are somewhat easier to use that the above.
+ * The user declares a variable of type STACKSTR, which may be declared
+ * to be a register.  The macro STARTSTACKSTR initializes things.  Then
+ * the user uses the macro STPUTC to add characters to the string.  In
+ * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
+ * grown as necessary.  When the user is done, she can just leave the
+ * string there and refer to it using stackblock().  Or she can allocate
+ * the space for it using grabstackstr().  If it is necessary to allow
+ * someone else to use the stack temporarily and then continue to grow
+ * the string, the user should use grabstack to allocate the space, and
+ * then call ungrabstr(p) to return to the previous mode of operation.
+ *
+ * USTPUTC is like STPUTC except that it doesn't check for overflow.
+ * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
+ * is space for at least one character.
+ */
+
+
+char *
+growstackstr() {
+	int len = stackblocksize();
+	if (herefd >= 0 && len >= 1024) {
+		xwrite(herefd, stackblock(), len);
+		sstrnleft = len - 1;
+		return stackblock();
+	}
+	growstackblock();
+	sstrnleft = stackblocksize() - len - 1;
+	return stackblock() + len;
+}
+
+
+/*
+ * Called from CHECKSTRSPACE.
+ */
+
+char *
+makestrspace() {
+	int len = stackblocksize() - sstrnleft;
+	growstackblock();
+	sstrnleft = stackblocksize() - len;
+	return stackblock() + len;
+}
+
+
+
+void
+ungrabstackstr(s, p)
+	char *s;
+	char *p;
+	{
+	stacknleft += stacknxt - s;
+	stacknxt = s;
+	sstrnleft = stacknleft - (p - s);
+}
Index: /trunk/minix/commands/ash/memalloc.h
===================================================================
--- /trunk/minix/commands/ash/memalloc.h	(revision 9)
+++ /trunk/minix/commands/ash/memalloc.h	(revision 9)
@@ -0,0 +1,95 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)memalloc.h	5.1 (Berkeley) 3/7/91
+ */
+
+struct stackmark {
+	struct stack_block *stackp;
+	char *stacknxt;
+	int stacknleft;
+};
+
+
+extern char *stacknxt;
+extern int stacknleft;
+extern int sstrnleft;
+extern int herefd;
+
+#ifdef __STDC__
+pointer ckmalloc(int);
+pointer ckrealloc(pointer, int);
+void free(pointer);		/* defined in C library */
+char *savestr(char *);
+pointer stalloc(int);
+void stunalloc(pointer);
+void setstackmark(struct stackmark *);
+void popstackmark(struct stackmark *);
+void growstackblock(void);
+void grabstackblock(int);
+char *growstackstr(void);
+char *makestrspace(void);
+void ungrabstackstr(char *, char *);
+#else
+pointer ckmalloc();
+pointer ckrealloc();
+void free();		/* defined in C library */
+char *savestr();
+pointer stalloc();
+void stunalloc();
+void setstackmark();
+void popstackmark();
+void growstackblock();
+void grabstackblock();
+char *growstackstr();
+char *makestrspace();
+void ungrabstackstr();
+#endif
+
+
+
+#define stackblock() stacknxt
+#define stackblocksize() stacknleft
+#define STARTSTACKSTR(p)	p = stackblock(), sstrnleft = stackblocksize()
+#define STPUTC(c, p)	(--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
+#define CHECKSTRSPACE(n, p)	if (sstrnleft < n) p = makestrspace(); else
+#define USTPUTC(c, p)	(--sstrnleft, *p++ = (c))
+#define STACKSTRNUL(p)	(sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
+#define STUNPUTC(p)	(++sstrnleft, --p)
+#define STTOPC(p)	p[-1]
+#define STADJUST(amount, p)	(p += (amount), sstrnleft -= (amount))
+#define grabstackstr(p)	stalloc(stackblocksize() - sstrnleft)
+
+#define ckfree(p)	free((pointer)(p))
Index: /trunk/minix/commands/ash/miscbltin.c
===================================================================
--- /trunk/minix/commands/ash/miscbltin.c	(revision 9)
+++ /trunk/minix/commands/ash/miscbltin.c	(revision 9)
@@ -0,0 +1,166 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)miscbltin.c	5.2 (Berkeley) 3/13/91";
+#endif /* not lint */
+
+/*
+ * Miscelaneous builtins.
+ */
+
+#include "shell.h"
+#include "options.h"
+#include "var.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+
+#undef eflag
+
+extern char **argptr;		/* argument list for builtin command */
+
+
+/*
+ * The read builtin.  The -e option causes backslashes to escape the
+ * following character.
+ *
+ * This uses unbuffered input, which may be avoidable in some cases.
+ */
+
+readcmd(argc, argv)  char **argv; {
+	char **ap;
+	int backslash;
+	char c;
+	int eflag;
+	char *prompt;
+	char *ifs;
+	char *p;
+	int startword;
+	int status;
+	int i;
+
+	eflag = 0;
+	prompt = NULL;
+	while ((i = nextopt("ep:")) != '\0') {
+		if (i == 'p')
+			prompt = optarg;
+		else
+			eflag = 1;
+	}
+	if (prompt && isatty(0)) {
+		out2str(prompt);
+		flushall();
+	}
+	if (*(ap = argptr) == NULL)
+		error("arg count");
+	if ((ifs = bltinlookup("IFS", 1)) == NULL)
+		ifs = nullstr;
+	status = 0;
+	startword = 1;
+	backslash = 0;
+	STARTSTACKSTR(p);
+	for (;;) {
+		if (read(0, &c, 1) != 1) {
+			status = 1;
+			break;
+		}
+		if (c == '\0')
+			continue;
+		if (backslash) {
+			backslash = 0;
+			if (c != '\n')
+				STPUTC(c, p);
+			continue;
+		}
+		if (eflag && c == '\\') {
+			backslash++;
+			continue;
+		}
+		if (c == '\n')
+			break;
+		if (startword && *ifs == ' ' && strchr(ifs, c)) {
+			continue;
+		}
+		startword = 0;
+		if (backslash && c == '\\') {
+			if (read(0, &c, 1) != 1) {
+				status = 1;
+				break;
+			}
+			STPUTC(c, p);
+		} else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
+			STACKSTRNUL(p);
+			setvar(*ap, stackblock(), 0);
+			ap++;
+			startword = 1;
+			STARTSTACKSTR(p);
+		} else {
+			STPUTC(c, p);
+		}
+	}
+	STACKSTRNUL(p);
+	setvar(*ap, stackblock(), 0);
+	while (*++ap != NULL)
+		setvar(*ap, nullstr, 0);
+	return status;
+}
+
+
+
+umaskcmd(argc, argv)  char **argv; {
+	int mask;
+	char *p;
+	int i;
+
+	if ((p = argv[1]) == NULL) {
+		INTOFF;
+		mask = umask(0);
+		umask(mask);
+		INTON;
+		out1fmt("%.4o\n", mask);	/* %#o might be better */
+	} else {
+		mask = 0;
+		do {
+			if ((unsigned)(i = *p - '0') >= 8)
+				error("Illegal number: %s", argv[1]);
+			mask = (mask << 3) + i;
+		} while (*++p != '\0');
+		umask(mask);
+	}
+	return 0;
+}
Index: /trunk/minix/commands/ash/mkbuiltins
===================================================================
--- /trunk/minix/commands/ash/mkbuiltins	(revision 9)
+++ /trunk/minix/commands/ash/mkbuiltins	(revision 9)
@@ -0,0 +1,123 @@
+#!/bin/sh -
+#
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)mkbuiltins	5.2 (Berkeley) 3/8/91
+
+# All calls to awk removed, because Minix bawk is deficient.  (kjb)
+
+if [ $# != 2 ]
+then
+	echo "USAGE: $0 shell.h builtins"
+	exit 1
+fi
+SHL=$1
+BLTINS=$2
+
+temp=/tmp/ka$$
+exec > builtins.c
+cat <<\!
+/*
+ * This file was generated by the mkbuiltins program.
+ */
+
+#include "shell.h"
+#include "builtins.h"
+
+!
+if grep '^#define JOBS[	 ]*1' $SHL > /dev/null
+then
+	# Job control.
+	sed -e '/^#/d
+		s/	/ /g
+		s/ #.*//
+		/^ *$/d
+		s/-j//' $BLTINS > $temp
+else
+	# No job control.
+	sed -e '/^#/d
+		s/	/ /g
+		s/ #.*//
+		/^ *$/d
+		/-j/d' $BLTINS > $temp
+fi
+sed -e 's/ .*//
+	s/\(.*\)/int \1();/' $temp
+echo '
+int (*const builtinfunc[])() = {'
+sed -e 's/ .*//
+	s/\(.*\)/	\1,/' $temp
+echo '};
+
+const struct builtincmd builtincmd[] = {'
+i=0
+while read line
+do
+	set -$- $line
+	shift
+	for fun
+	do
+		echo "	\"$fun\", $i,"
+	done
+	i=`expr $i + 1`
+done < $temp
+echo '	NULL, 0
+};'
+
+exec > builtins.h
+cat <<\!
+/*
+ * This file was generated by the mkbuiltins program.
+ */
+
+#include <sys/cdefs.h>
+!
+i=0
+tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ < $temp |
+	while read line
+	do
+		set -$- $line
+		echo "#define $1 $i"
+		i=`expr $i + 1`
+	done
+echo '
+struct builtincmd {
+      char *name;
+      int code;
+};
+
+extern int (*const builtinfunc[])();
+extern const struct builtincmd builtincmd[];'
+rm -f $temp
Index: /trunk/minix/commands/ash/mkinit.c
===================================================================
--- /trunk/minix/commands/ash/mkinit.c	(revision 9)
+++ /trunk/minix/commands/ash/mkinit.c	(revision 9)
@@ -0,0 +1,547 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)mkinit.c	5.3 (Berkeley) 3/13/91";
+#endif /* not lint */
+
+/*
+ * This program scans all the source files for code to handle various
+ * special events and combines this code into one file.  This (allegedly)
+ * improves the structure of the program since there is no need for
+ * anyone outside of a module to know that that module performs special
+ * operations on particular events.  The command is executed iff init.c
+ * is actually changed.
+ *
+ * Usage:  mkinit command sourcefile...
+ */
+
+
+#include <sys/cdefs.h>
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+
+/*
+ * OUTFILE is the name of the output file.  Output is initially written
+ * to the file OUTTEMP, which is then moved to OUTFILE if OUTTEMP and
+ * OUTFILE are different.
+ */
+
+#define OUTFILE "init.c"
+#define OUTTEMP "init.c.new"
+#define OUTOBJ "init.o"
+
+
+/*
+ * A text structure is basicly just a string that grows as more characters
+ * are added onto the end of it.  It is implemented as a linked list of
+ * blocks of characters.  The routines addstr and addchar append a string
+ * or a single character, respectively, to a text structure.  Writetext
+ * writes the contents of a text structure to a file.
+ */
+
+#define BLOCKSIZE 512
+
+struct text {
+	char *nextc;
+	int nleft;
+	struct block *start;
+	struct block *last;
+};      
+
+struct block {
+	struct block *next;
+	char text[BLOCKSIZE];
+};
+
+
+/*
+ * There is one event structure for each event that mkinit handles.
+ */
+
+struct event {
+	char *name;		/* name of event (e.g. INIT) */
+	char *routine;		/* name of routine called on event */
+	char *comment;		/* comment describing routine */
+	struct text code;		/* code for handling event */
+};
+
+
+char writer[] = "\
+/*\n\
+ * This file was generated by the mkinit program.\n\
+ */\n\
+\n";
+
+char init[] = "\
+/*\n\
+ * Initialization code.\n\
+ */\n";
+
+char reset[] = "\
+/*\n\
+ * This routine is called when an error or an interrupt occurs in an\n\
+ * interactive shell and control is returned to the main command loop.\n\
+ */\n";
+
+char shellproc[] = "\
+/*\n\
+ * This routine is called to initialize the shell to run a shell procedure.\n\
+ */\n";
+
+
+struct event event[] = {
+	{"INIT", "init", init},
+	{"RESET", "reset", reset},
+	{"SHELLPROC", "initshellproc", shellproc},
+	{NULL, NULL}
+};
+
+
+char *curfile;				/* current file */
+int linno;				/* current line */
+char *header_files[200];		/* list of header files */
+struct text defines;			/* #define statements */
+struct text decls;			/* declarations */
+int amiddecls;				/* for formatting */
+
+
+void readfile(), doevent(), doinclude(), dodecl(), output();
+void addstr(), addchar(), writetext();
+
+#define equal(s1, s2)	(strcmp(s1, s2) == 0)
+
+FILE *ckfopen();
+char *savestr();
+void *ckmalloc __P((int));
+void error();
+
+main(argc, argv)
+	char **argv;
+	{
+	char **ap;
+	int fd;
+	char c;
+
+	if (argc < 2)
+		error("Usage:  mkinit command file...");
+	header_files[0] = "\"shell.h\"";
+	header_files[1] = "\"mystring.h\"";
+	for (ap = argv + 2 ; *ap ; ap++)
+		readfile(*ap);
+	output();
+	if (file_changed()) {
+		unlink(OUTFILE);
+		link(OUTTEMP, OUTFILE);
+		unlink(OUTTEMP);
+	} else {
+		unlink(OUTTEMP);
+		if (touch(OUTOBJ))
+			exit(0);		/* no compilation necessary */
+	}
+	printf("%s\n", argv[1]);
+	execl("/bin/sh", "sh", "-c", argv[1], (char *)0);
+	error("Can't exec shell");
+}
+
+
+/*
+ * Parse an input file.
+ */
+
+void
+readfile(fname)
+	char *fname;
+	{
+	FILE *fp;
+	char line[1024];
+	struct event *ep;
+
+	fp = ckfopen(fname, "r");
+	curfile = fname;
+	linno = 0;
+	amiddecls = 0;
+	while (fgets(line, sizeof line, fp) != NULL) {
+		linno++;
+		for (ep = event ; ep->name ; ep++) {
+			if (line[0] == ep->name[0] && match(ep->name, line)) {
+				doevent(ep, fp, fname);
+				break;
+			}
+		}
+		if (line[0] == 'I' && match("INCLUDE", line))
+			doinclude(line);
+		if (line[0] == 'M' && match("MKINIT", line))
+			dodecl(line, fp);
+		if (line[0] == '#' && gooddefine(line))
+			addstr(line, &defines);
+	}
+	fclose(fp);
+}
+
+
+int
+match(name, line)
+	char *name;
+	char *line;
+	{
+	register char *p, *q;
+
+	p = name, q = line;
+	while (*p) {
+		if (*p++ != *q++)
+			return 0;
+	}
+	if (*q != '{' && *q != ' ' && *q != '\t' && *q != '\n')
+		return 0;
+	return 1;
+}
+
+
+int
+gooddefine(line)
+	char *line;
+	{
+	register char *p;
+
+	if (! match("#define", line))
+		return 0;			/* not a define */
+	p = line + 7;
+	while (*p == ' ' || *p == '\t')
+		p++;
+	while (*p != ' ' && *p != '\t') {
+		if (*p == '(')
+			return 0;		/* macro definition */
+		p++;
+	}
+	while (*p != '\n' && *p != '\0')
+		p++;
+	if (p[-1] == '\\')
+		return 0;			/* multi-line definition */
+	return 1;
+}
+
+
+void
+doevent(ep, fp, fname)
+	register struct event *ep;
+	FILE *fp;
+	char *fname;
+	{
+	char line[1024];
+	int indent;
+	char *p;
+
+	sprintf(line, "\n      /* from %s: */\n", fname);
+	addstr(line, &ep->code);
+	addstr("      {\n", &ep->code);
+	for (;;) {
+		linno++;
+		if (fgets(line, sizeof line, fp) == NULL)
+			error("Unexpected EOF");
+		if (equal(line, "}\n"))
+			break;
+		indent = 6;
+		for (p = line ; *p == '\t' ; p++)
+			indent += 8;
+		for ( ; *p == ' ' ; p++)
+			indent++;
+		if (*p == '\n' || *p == '#')
+			indent = 0;
+		while (indent >= 8) {
+			addchar('\t', &ep->code);
+			indent -= 8;
+		}
+		while (indent > 0) {
+			addchar(' ', &ep->code);
+			indent--;
+		}
+		addstr(p, &ep->code);
+	}
+	addstr("      }\n", &ep->code);
+}
+
+
+void
+doinclude(line)
+	char *line;
+	{
+	register char *p;
+	char *name;
+	register char **pp;
+
+	for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
+	if (*p == '\0')
+		error("Expecting '\"' or '<'");
+	name = p;
+	while (*p != ' ' && *p != '\t' && *p != '\n')
+		p++;
+	if (p[-1] != '"' && p[-1] != '>')
+		error("Missing terminator");
+	*p = '\0';
+
+	/* name now contains the name of the include file */
+	for (pp = header_files ; *pp && ! equal(*pp, name) ; pp++);
+	if (*pp == NULL)
+		*pp = savestr(name);
+}
+
+
+void
+dodecl(line1, fp)
+	char *line1;
+	FILE *fp;
+	{
+	char line[1024];
+	register char *p, *q;
+
+	if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
+		addchar('\n', &decls);
+		do {
+			linno++;
+			if (fgets(line, sizeof line, fp) == NULL)
+				error("Unterminated structure declaration");
+			addstr(line, &decls);
+		} while (line[0] != '}');
+		amiddecls = 0;
+	} else {
+		if (! amiddecls)
+			addchar('\n', &decls);
+		q = NULL;
+		for (p = line1 + 6 ; *p != '=' && *p != '/' ; p++);
+		if (*p == '=') {		/* eliminate initialization */
+			for (q = p ; *q && *q != ';' ; q++);
+			if (*q == '\0')
+				q = NULL;
+			else {
+				while (p[-1] == ' ')
+					p--;
+				*p = '\0';
+			}
+		}
+		addstr("extern", &decls);
+		addstr(line1 + 6, &decls);
+		if (q != NULL)
+			addstr(q, &decls);
+		amiddecls = 1;
+	}
+}
+
+
+
+/*
+ * Write the output to the file OUTTEMP.
+ */
+
+void
+output() {
+	FILE *fp;
+	char **pp;
+	struct event *ep;
+
+	fp = ckfopen(OUTTEMP, "w");
+	fputs(writer, fp);
+	for (pp = header_files ; *pp ; pp++)
+		fprintf(fp, "#include %s\n", *pp);
+	fputs("\n\n\n", fp);
+	writetext(&defines, fp);
+	fputs("\n\n", fp);
+	writetext(&decls, fp);
+	for (ep = event ; ep->name ; ep++) {
+		fputs("\n\n\n", fp);
+		fputs(ep->comment, fp);
+		fprintf(fp, "\nvoid\n%s() {\n", ep->routine);
+		writetext(&ep->code, fp);
+		fprintf(fp, "}\n");
+	}
+	fclose(fp);
+}
+
+
+/*
+ * Return true if the new output file is different from the old one.
+ */
+
+int
+file_changed() {
+	register FILE *f1, *f2;
+	register int c;
+
+	if ((f1 = fopen(OUTFILE, "r")) == NULL
+	 || (f2 = fopen(OUTTEMP, "r")) == NULL)
+		return 1;
+	while ((c = getc(f1)) == getc(f2)) {
+		if (c == EOF)
+			return 0;
+	}
+	return 1;
+}
+
+
+/*
+ * Touch a file.  Returns 0 on failure, 1 on success.
+ */
+
+int
+touch(file)
+	char *file;
+	{
+	int fd;
+	char c;
+
+	if ((fd = open(file, O_RDWR)) < 0)
+		return 0;
+	if (read(fd, &c, 1) != 1) {
+		close(fd);
+		return 0;
+	}
+	lseek(fd, 0L, 0);
+	write(fd, &c, 1);
+	close(fd);
+	return 1;
+}
+
+
+
+/*
+ * A text structure is simply a block of text that is kept in memory.
+ * Addstr appends a string to the text struct, and addchar appends a single
+ * character.
+ */
+
+void
+addstr(s, text)
+	register char *s;
+	register struct text *text;
+	{
+	while (*s) {
+		if (--text->nleft < 0)
+			addchar(*s++, text);
+		else
+			*text->nextc++ = *s++;
+	}
+}
+
+
+void
+addchar(c, text)
+	register struct text *text;
+	{
+	struct block *bp;
+
+	if (--text->nleft < 0) {
+		bp = ckmalloc(sizeof *bp);
+		if (text->start == NULL)
+			text->start = bp;
+		else
+			text->last->next = bp;
+		text->last = bp;
+		text->nextc = bp->text;
+		text->nleft = BLOCKSIZE - 1;
+	}
+	*text->nextc++ = c;
+}
+
+/*
+ * Write the contents of a text structure to a file.
+ */
+void
+writetext(text, fp)
+	struct text *text;
+	FILE *fp;
+	{
+	struct block *bp;
+
+	if (text->start != NULL) {
+		for (bp = text->start ; bp != text->last ; bp = bp->next)
+			fwrite(bp->text, sizeof (char), BLOCKSIZE, fp);
+		fwrite(bp->text, sizeof (char), BLOCKSIZE - text->nleft, fp);
+	}
+}
+
+FILE *
+ckfopen(file, mode)
+	char *file;
+	char *mode;
+	{
+	FILE *fp;
+
+	if ((fp = fopen(file, mode)) == NULL) {
+		fprintf(stderr, "Can't open %s\n", file);
+		exit(2);
+	}
+	return fp;
+}
+
+void *
+ckmalloc(nbytes) {
+	register char *p;
+	char *malloc();
+
+	if ((p = malloc(nbytes)) == NULL)
+		error("Out of space");
+	return p;
+}
+
+char *
+savestr(s)
+	char *s;
+	{
+	register char *p;
+
+	p = ckmalloc(strlen(s) + 1);
+	strcpy(p, s);
+	return p;
+}
+
+void
+error(msg)
+	char *msg;
+	{
+	if (curfile != NULL)
+		fprintf(stderr, "%s:%d: ", curfile, linno);
+	fprintf(stderr, "%s\n", msg);
+	exit(2);
+}
Index: /trunk/minix/commands/ash/mknodes.c
===================================================================
--- /trunk/minix/commands/ash/mknodes.c	(revision 9)
+++ /trunk/minix/commands/ash/mknodes.c	(revision 9)
@@ -0,0 +1,432 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)mknodes.c	5.1 (Berkeley) 3/7/91";
+#endif /* not lint */
+
+/*
+ * This program reads the nodetypes file and nodes.c.pat file.  It generates
+ * the files nodes.h and nodes.c.
+ */
+
+#include <stdio.h>
+
+
+#define MAXTYPES 50		/* max number of node types */
+#define MAXFIELDS 20		/* max fields in a structure */
+#define BUFLEN 100		/* size of character buffers */
+
+/* field types */
+#define T_NODE 1		/* union node *field */
+#define T_NODELIST 2		/* struct nodelist *field */
+#define T_STRING 3
+#define T_INT 4			/* int field */
+#define T_OTHER 5		/* other */
+#define T_TEMP 6		/* don't copy this field */
+
+
+struct field {			/* a structure field */
+	char *name;		/* name of field */
+	int type;			/* type of field */
+	char *decl;		/* declaration of field */
+};
+
+
+struct str {			/* struct representing a node structure */
+	char *tag;		/* structure tag */
+	int nfields;		/* number of fields in the structure */
+	struct field field[MAXFIELDS];	/* the fields of the structure */
+	int done;			/* set if fully parsed */
+};
+
+
+int ntypes;			/* number of node types */
+char *nodename[MAXTYPES];	/* names of the nodes */
+struct str *nodestr[MAXTYPES];	/* type of structure used by the node */
+int nstr;			/* number of structures */
+struct str str[MAXTYPES];	/* the structures */
+struct str *curstr;		/* current structure */
+
+
+FILE *infp = stdin;
+char line[1024];
+int linno;
+char *linep;
+
+
+char *savestr();
+#define equal(s1, s2)	(strcmp(s1, s2) == 0)
+
+
+main(argc, argv)
+	char **argv;
+	{
+	if (argc != 3)
+		error("usage: mknodes file\n");
+	if ((infp = fopen(argv[1], "r")) == NULL)
+		error("Can't open %s", argv[1]);
+	while (readline()) {
+		if (line[0] == ' ' || line[0] == '\t')
+			parsefield();
+		else if (line[0] != '\0')
+			parsenode();
+	}
+	output(argv[2]);
+	return 0;
+}
+
+
+
+parsenode() {
+	char name[BUFLEN];
+	char tag[BUFLEN];
+	struct str *sp;
+
+	if (curstr && curstr->nfields > 0)
+		curstr->done = 1;
+	nextfield(name);
+	if (! nextfield(tag))
+		error("Tag expected");
+	if (*linep != '\0')
+		error("Garbage at end of line");
+	nodename[ntypes] = savestr(name);
+	for (sp = str ; sp < str + nstr ; sp++) {
+		if (equal(sp->tag, tag))
+			break;
+	}
+	if (sp >= str + nstr) {
+		sp->tag = savestr(tag);
+		sp->nfields = 0;
+		curstr = sp;
+		nstr++;
+	}
+	nodestr[ntypes] = sp;
+	ntypes++;
+}
+
+
+parsefield() {
+	char name[BUFLEN];
+	char type[BUFLEN];
+	char decl[2 * BUFLEN];
+	struct field *fp;
+
+	if (curstr == NULL || curstr->done)
+		error("No current structure to add field to");
+	if (! nextfield(name))
+		error("No field name");
+	if (! nextfield(type))
+		error("No field type");
+	fp = &curstr->field[curstr->nfields];
+	fp->name = savestr(name);
+	if (equal(type, "nodeptr")) {
+		fp->type = T_NODE;
+		sprintf(decl, "union node *%s", name);
+	} else if (equal(type, "nodelist")) {
+		fp->type = T_NODELIST;
+		sprintf(decl, "struct nodelist *%s", name);
+	} else if (equal(type, "string")) {
+		fp->type = T_STRING;
+		sprintf(decl, "char *%s", name);
+	} else if (equal(type, "int")) {
+		fp->type = T_INT;
+		sprintf(decl, "int %s", name);
+	} else if (equal(type, "other")) {
+		fp->type = T_OTHER;
+	} else if (equal(type, "temp")) {
+		fp->type = T_TEMP;
+	} else {
+		error("Unknown type %s", type);
+	}
+	if (fp->type == T_OTHER || fp->type == T_TEMP) {
+		skipbl();
+		fp->decl = savestr(linep);
+	} else {
+		if (*linep)
+			error("Garbage at end of line");
+		fp->decl = savestr(decl);
+	}
+	curstr->nfields++;
+}
+
+
+char writer[] = "\
+/*\n\
+ * This file was generated by the mknodes program.\n\
+ */\n\
+\n";
+
+output(file)
+	char *file;
+	{
+	FILE *hfile;
+	FILE *cfile;
+	FILE *patfile;
+	int i;
+	struct str *sp;
+	struct field *fp;
+	char *p;
+
+	if ((patfile = fopen(file, "r")) == NULL)
+		error("Can't open %s", file);
+	if ((hfile = fopen("nodes.h", "w")) == NULL)
+		error("Can't create nodes.h");
+	if ((cfile = fopen("nodes.c", "w")) == NULL)
+		error("Can't create nodes.c");
+	fputs(writer, hfile);
+	for (i = 0 ; i < ntypes ; i++)
+		fprintf(hfile, "#define %s %d\n", nodename[i], i);
+	fputs("\n\n\n", hfile);
+	for (sp = str ; sp < &str[nstr] ; sp++) {
+		fprintf(hfile, "struct %s {\n", sp->tag);
+		for (i = sp->nfields, fp = sp->field ; --i >= 0 ; fp++) {
+			fprintf(hfile, "      %s;\n", fp->decl);
+		}
+		fputs("};\n\n\n", hfile);
+	}
+	fputs("union node {\n", hfile);
+	fprintf(hfile, "      int type;\n");
+	for (sp = str ; sp < &str[nstr] ; sp++) {
+		fprintf(hfile, "      struct %s %s;\n", sp->tag, sp->tag);
+	}
+	fputs("};\n\n\n", hfile);
+	fputs("struct nodelist {\n", hfile);
+	fputs("\tstruct nodelist *next;\n", hfile);
+	fputs("\tunion node *n;\n", hfile);
+	fputs("};\n\n\n", hfile);
+	fputs("#ifdef __STDC__\n", hfile);
+	fputs("union node *copyfunc(union node *);\n", hfile);
+	fputs("void freefunc(union node *);\n", hfile);
+	fputs("#else\n", hfile);
+	fputs("union node *copyfunc();\n", hfile);
+	fputs("void freefunc();\n", hfile);
+	fputs("#endif\n", hfile);
+
+	fputs(writer, cfile);
+	while (fgets(line, sizeof line, patfile) != NULL) {
+		for (p = line ; *p == ' ' || *p == '\t' ; p++);
+		if (equal(p, "%SIZES\n"))
+			outsizes(cfile);
+		else if (equal(p, "%CALCSIZE\n"))
+			outfunc(cfile, 1);
+		else if (equal(p, "%COPY\n"))
+			outfunc(cfile, 0);
+		else
+			fputs(line, cfile);
+	}
+}
+
+
+
+outsizes(cfile)
+	FILE *cfile;
+	{
+	int i;
+
+	fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes);
+	for (i = 0 ; i < ntypes ; i++) {
+		fprintf(cfile, "      ALIGN(sizeof (struct %s)),\n", nodestr[i]->tag);
+	}
+	fprintf(cfile, "};\n");
+}
+
+
+outfunc(cfile, calcsize)
+	FILE *cfile;
+	{
+	struct str *sp;
+	struct field *fp;
+	int i;
+
+	fputs("      if (n == NULL)\n", cfile);
+	if (calcsize)
+		fputs("	    return;\n", cfile);
+	else
+		fputs("	    return NULL;\n", cfile);
+	if (calcsize)
+		fputs("      funcblocksize += nodesize[n->type];\n", cfile);
+	else {
+		fputs("      new = funcblock;\n", cfile);
+		fputs("      *(char **)&funcblock += nodesize[n->type];\n", 
+									cfile);
+	}
+	fputs("      switch (n->type) {\n", cfile);
+	for (sp = str ; sp < &str[nstr] ; sp++) {
+		for (i = 0 ; i < ntypes ; i++) {
+			if (nodestr[i] == sp)
+				fprintf(cfile, "      case %s:\n", nodename[i]);
+		}
+		for (i = sp->nfields ; --i >= 1 ; ) {
+			fp = &sp->field[i];
+			switch (fp->type) {
+			case T_NODE:
+				if (calcsize) {
+					indent(12, cfile);
+					fprintf(cfile, "calcsize(n->%s.%s);\n",
+						sp->tag, fp->name);
+				} else {
+					indent(12, cfile);
+					fprintf(cfile, "new->%s.%s = copynode(n->%s.%s);\n",
+						sp->tag, fp->name, sp->tag, fp->name);
+				}
+				break;
+			case T_NODELIST:
+				if (calcsize) {
+					indent(12, cfile);
+					fprintf(cfile, "sizenodelist(n->%s.%s);\n",
+						sp->tag, fp->name);
+				} else {
+					indent(12, cfile);
+					fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s);\n",
+						sp->tag, fp->name, sp->tag, fp->name);
+				}
+				break;
+			case T_STRING:
+				if (calcsize) {
+					indent(12, cfile);
+					fprintf(cfile, "funcstringsize += strlen(n->%s.%s) + 1;\n",
+						sp->tag, fp->name);
+				} else {
+					indent(12, cfile);
+					fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s);\n",
+						sp->tag, fp->name, sp->tag, fp->name);
+				}
+				break;
+			case T_INT:
+			case T_OTHER:
+				if (! calcsize) {
+					indent(12, cfile);
+					fprintf(cfile, "new->%s.%s = n->%s.%s;\n",
+						sp->tag, fp->name, sp->tag, fp->name);
+				}
+				break;
+			}
+		}
+		indent(12, cfile);
+		fputs("break;\n", cfile);
+	}
+	fputs("      };\n", cfile);
+	if (! calcsize)
+		fputs("      new->type = n->type;\n", cfile);
+}
+
+
+indent(amount, fp)
+	FILE *fp;
+	{
+	while (amount >= 8) {
+		putc('\t', fp);
+		amount -= 8;
+	}
+	while (--amount >= 0) {
+		putc(' ', fp);
+	}
+}
+
+
+int
+nextfield(buf)
+	char *buf;
+	{
+	register char *p, *q;
+
+	p = linep;
+	while (*p == ' ' || *p == '\t')
+		p++;
+	q = buf;
+	while (*p != ' ' && *p != '\t' && *p != '\0')
+		*q++ = *p++;
+	*q = '\0';
+	linep = p;
+	return (q > buf);
+}
+
+
+skipbl() {
+	while (*linep == ' ' || *linep == '\t')
+		linep++;
+}
+
+
+int
+readline() {
+	register char *p;
+
+	if (fgets(line, 1024, infp) == NULL)
+		return 0;
+	for (p = line ; *p != '#' && *p != '\n' && *p != '\0' ; p++);
+	while (p > line && (p[-1] == ' ' || p[-1] == '\t'))
+		p--;
+	*p = '\0';
+	linep = line;
+	linno++;
+	if (p - line > BUFLEN)
+		error("Line too long");
+	return 1;
+}
+
+
+
+error(msg, a1, a2, a3, a4, a5, a6)
+	char *msg;
+	{
+	fprintf(stderr, "line %d: ", linno);
+	fprintf(stderr, msg, a1, a2, a3, a4, a5, a6);
+	putc('\n', stderr);
+	exit(2);
+}
+
+
+
+char *
+savestr(s)
+	char *s;
+	{
+	register char *p;
+	char *malloc();
+
+	if ((p = malloc(strlen(s) + 1)) == NULL)
+		error("Out of space");
+	strcpy(p, s);
+	return p;
+}
Index: /trunk/minix/commands/ash/mksignames.c
===================================================================
--- /trunk/minix/commands/ash/mksignames.c	(revision 9)
+++ /trunk/minix/commands/ash/mksignames.c	(revision 9)
@@ -0,0 +1,200 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)mksignames.c	5.1 (Berkeley) 3/7/91";
+#endif /* not lint */
+
+/*
+ * This program generates the signames.h and signames.c files.
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#include <signal.h>
+
+
+
+struct sig {
+	int signo;		/* signal number */
+	char *name;		/* signal name (without leading "SIG") */
+	char *mesg;		/* description */
+};
+
+
+struct sig sigtab[] = {
+	SIGHUP, "HUP", "Hangup",
+	SIGINT, "INT", "Interrupt",	/* normally don't print message */
+	SIGQUIT, "QUIT", "Quit",
+	SIGILL, "ILL", "Illegal instruction",
+	SIGTRAP, "TRAP", "Trace/BPT trap",
+#ifdef SIGABRT
+	SIGABRT, "ABRT", "abort",
+#endif
+#if defined(SIGIOT) && (! defined(SIGABRT) || SIGABRT != SIGIOT)
+	SIGIOT, "IOT", "abort",
+#endif
+#ifdef SIGEMT
+	SIGEMT, "EMT", "EMT trap",
+#endif
+	SIGFPE, "FPE", "Floating exception",
+	SIGKILL, "KILL", "Killed",
+	SIGBUS, "BUS", "Bus error",
+	SIGSEGV, "SEGV", "Memory fault",
+#ifdef SIGSYS
+	SIGSYS, "SYS", "Bad system call",
+#endif
+	SIGPIPE, "PIPE", "Broken pipe",	/* normally don't print message */
+	SIGALRM, "ALRM", "Alarm call",
+	SIGTERM, "TERM", "Terminated",
+#ifdef SIGUSR1
+	SIGUSR1, "USR1", "User signal 1",
+#endif
+#ifdef SIGUSR2
+	SIGUSR2, "USR2", "User signal 2",
+#endif
+#ifdef SIGCLD
+	SIGCLD, "CLD", NULL,
+#endif
+#if defined(SIGCHLD) && ! defined(SIGCLD)
+	SIGCHLD, "CLD", NULL,
+#endif
+#ifdef SIGPWR
+	SIGPWR, "PWR", "Power fail",
+#endif
+#ifdef SIGPOLL
+	SIGPOLL, "POLL", "Poll",
+#endif
+	/* Now for the BSD signals */
+#ifdef SIGURG
+	SIGURG, "URG", NULL,
+#endif
+#ifdef SIGSTOP
+	SIGSTOP, "STOP", "Stopped",
+#endif
+#ifdef SIGTSTP
+	SIGTSTP, "TSTP", "Stopped",
+#endif
+#ifdef SIGCONT
+	SIGCONT, "CONT", NULL,
+#endif
+#ifdef SIGTTIN
+	SIGTTIN, "TTIN", "Stopped (input)",
+#endif
+#ifdef SIGTTOU
+	SIGTTOU, "TTOU", "Stopped (output)",
+#endif
+#ifdef SIGIO
+	SIGIO, "IO", NULL,
+#endif
+#ifdef SIGXCPU
+	SIGXCPU, "XCPU", "Time limit exceeded",
+#endif
+#ifdef SIGXFSZ
+	SIGXFSZ, "XFSZ", NULL,
+#endif
+#ifdef SIGVTALARM
+	SIGVTALARM, "VTALARM", "Virtual alarm",
+#endif
+#ifdef SIGPROF
+	SIGPROF, "PROF", "Profiling alarm",
+#endif
+#ifdef SIGWINCH
+	SIGWINCH, "WINCH", NULL,
+#endif
+	0, NULL, NULL
+};
+
+
+#define MAXSIG 64
+
+
+char *sigmesg[MAXSIG + 1];
+
+
+char writer[] = "\
+/*\n\
+ * This file was generated by the mksignames program.\n\
+ */\n\
+\n";
+
+
+
+main(argc, argv)  char **argv; {
+	FILE *cfile, *hfile;	
+	struct sig *sigp;
+	int maxsig;
+	int i;
+
+	if ((cfile = fopen("signames.c", "w")) == NULL) {
+		fputs("Can't create signames.c\n", stderr);
+		exit(2);
+	}
+	if ((hfile = fopen("signames.h", "w")) == NULL) {
+		fputs("Can't create signames.h\n", stderr);
+		exit(2);
+	}
+	maxsig = 0;
+	for (sigp = sigtab ; sigp->signo != 0 ; sigp++) {
+		if (sigp->signo < 0 || sigp->signo > MAXSIG)
+			continue;
+		sigmesg[sigp->signo] = sigp->mesg;
+		if (maxsig < sigp->signo)
+			maxsig = sigp->signo;
+	}
+
+	fputs(writer, hfile);
+	fprintf(hfile, "#define MAXSIG %d\n\n", maxsig);
+	fprintf(hfile, "extern char *const sigmesg[MAXSIG+1];\n");
+
+	fputs(writer, cfile);
+	fprintf(cfile, "#include \"shell.h\"\n\n");
+	fprintf(cfile, "char *const sigmesg[%d] = {\n", maxsig + 1);
+	for (i = 0 ; i <= maxsig ; i++) {
+		if (sigmesg[i] == NULL) {
+			fprintf(cfile, "      0,\n");
+		} else {
+			fprintf(cfile, "      \"%s\",\n", sigmesg[i]);
+		}
+	}
+	fprintf(cfile, "};\n");
+	exit(0);
+}
Index: /trunk/minix/commands/ash/mksyntax.c
===================================================================
--- /trunk/minix/commands/ash/mksyntax.c	(revision 9)
+++ /trunk/minix/commands/ash/mksyntax.c	(revision 9)
@@ -0,0 +1,356 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)mksyntax.c	5.2 (Berkeley) 3/8/91";
+#endif /* not lint */
+
+/*
+ * This program creates syntax.h and syntax.c.
+ */
+
+#include <stdio.h>
+#include "parser.h"
+
+
+struct synclass {
+	char *name;
+	char *comment;
+};
+
+/* Syntax classes */
+struct synclass synclass[] = {
+	"CWORD",		"character is nothing special",
+	"CNL",		"newline character",
+	"CBACK",		"a backslash character",
+	"CSQUOTE",	"single quote",
+	"CDQUOTE",	"double quote",
+	"CENDQUOTE",	"a terminating quote",
+	"CBQUOTE",	"backwards single quote",
+	"CVAR",		"a dollar sign",
+	"CENDVAR",	"a '}' character",
+	"CEOF",		"end of file",
+	"CCTL",		"like CWORD, except it must be escaped",
+	"CSPCL",		"these terminate a word",
+	NULL, NULL
+};
+
+
+/*
+ * Syntax classes for is_ functions.  Warning:  if you add new classes
+ * you may have to change the definition of the is_in_name macro.
+ */
+struct synclass is_entry[] = {
+	"ISDIGIT",	"a digit",
+	"ISUPPER",	"an upper case letter",
+	"ISLOWER",	"a lower case letter",
+	"ISUNDER",	"an underscore",
+	"ISSPECL",	"the name of a special parameter",
+	NULL, NULL,
+};
+
+char writer[] = "\
+/*\n\
+ * This file was generated by the mksyntax program.\n\
+ */\n\
+\n";
+
+
+FILE *cfile;
+FILE *hfile;
+char *syntax[513];
+int base;
+int size;		/* number of values which a char variable can have */
+int nbits;		/* number of bits in a character */
+int digit_contig;	/* true if digits are contiguous */
+
+
+main() {
+	char c;
+	char d;
+	int sign;
+	int i;
+	char buf[80];
+	int pos;
+	static char digit[] = "0123456789";
+
+	/* Create output files */
+	if ((cfile = fopen("syntax.c", "w")) == NULL) {
+		perror("syntax.c");
+		exit(2);
+	}
+	if ((hfile = fopen("syntax.h", "w")) == NULL) {
+		perror("syntax.h");
+		exit(2);
+	}
+	fputs(writer, hfile);
+	fputs(writer, cfile);
+
+	/* Determine the characteristics of chars. */
+	c = -1;
+	if (c < 0)
+		sign = 1;
+	else
+		sign = 0;
+	for (nbits = 1 ; ; nbits++) {
+		d = (1 << nbits) - 1;
+		if (d == c)
+			break;
+	}
+	printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
+	if (nbits > 9) {
+		fputs("Characters can't have more than 9 bits\n", stderr);
+		exit(2);
+	}
+	size = (1 << nbits) + 1;
+	base = 1;
+	if (sign)
+		base += 1 << (nbits - 1);
+	digit_contig = 1;
+	for (i = 0 ; i < 10 ; i++) {
+		if (digit[i] != '0' + i)
+			digit_contig = 0;
+	}
+
+	fputs("#include <sys/cdefs.h>\n", hfile);
+
+	/* Generate the #define statements in the header file */
+	fputs("/* Syntax classes */\n", hfile);
+	for (i = 0 ; synclass[i].name ; i++) {
+		sprintf(buf, "#define %s %d", synclass[i].name, i);
+		fputs(buf, hfile);
+		for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
+			putc('\t', hfile);
+		fprintf(hfile, "/* %s */\n", synclass[i].comment);
+	}
+	putc('\n', hfile);
+	fputs("/* Syntax classes for is_ functions */\n", hfile);
+	for (i = 0 ; is_entry[i].name ; i++) {
+		sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
+		fputs(buf, hfile);
+		for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
+			putc('\t', hfile);
+		fprintf(hfile, "/* %s */\n", is_entry[i].comment);
+	}
+	putc('\n', hfile);
+	fprintf(hfile, "#define SYNBASE %d\n", base);
+	fprintf(hfile, "#define PEOF %d\n\n", -base);
+	putc('\n', hfile);
+	fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
+	fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
+	fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
+	putc('\n', hfile);
+	output_type_macros();		/* is_digit, etc. */
+	putc('\n', hfile);
+
+	/* Generate the syntax tables. */
+	fputs("#include \"shell.h\"\n", cfile);
+	fputs("#include \"syntax.h\"\n\n", cfile);
+	init();
+	fputs("/* syntax table used when not in quotes */\n", cfile);
+	add("\n", "CNL");
+	add("\\", "CBACK");
+	add("'", "CSQUOTE");
+	add("\"", "CDQUOTE");
+	add("`", "CBQUOTE");
+	add("$", "CVAR");
+	add("}", "CENDVAR");
+	add("<>();&| \t", "CSPCL");
+	print("basesyntax");
+	init();
+	fputs("\n/* syntax table used when in double quotes */\n", cfile);
+	add("\n", "CNL");
+	add("\\", "CBACK");
+	add("\"", "CENDQUOTE");
+	add("`", "CBQUOTE");
+	add("$", "CVAR");
+	add("}", "CENDVAR");
+	add("!*?[=", "CCTL");
+	print("dqsyntax");
+	init();
+	fputs("\n/* syntax table used when in single quotes */\n", cfile);
+	add("\n", "CNL");
+	add("'", "CENDQUOTE");
+	add("!*?[=", "CCTL");
+	print("sqsyntax");
+	filltable("0");
+	fputs("\n/* character classification table */\n", cfile);
+	add("0123456789", "ISDIGIT");
+	add("abcdefghijklmnopqrstucvwxyz", "ISLOWER");
+	add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER");
+	add("_", "ISUNDER");
+	add("#?$!-*@", "ISSPECL");
+	print("is_type");
+	if (! digit_contig)
+		digit_convert();
+	exit(0);
+}
+
+
+
+/*
+ * Clear the syntax table.
+ */
+
+filltable(dftval)
+	char *dftval;
+	{
+	int i;
+
+	for (i = 0 ; i < size ; i++)
+		syntax[i] = dftval;
+}
+
+
+/*
+ * Initialize the syntax table with default values.
+ */
+
+init() {
+	filltable("CWORD");
+	syntax[0] = "CEOF";
+	syntax[base + CTLESC] = "CCTL";
+	syntax[base + CTLVAR] = "CCTL";
+	syntax[base + CTLENDVAR] = "CCTL";
+	syntax[base + CTLBACKQ] = "CCTL";
+	syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
+}
+
+
+/*
+ * Add entries to the syntax table.
+ */
+
+add(p, type)
+	char *p, *type;
+	{
+	while (*p)
+		syntax[*p++ + base] = type;
+}
+
+
+
+/*
+ * Output the syntax table.
+ */
+
+print(name)
+	char *name;
+	{
+	int i;
+	int col;
+
+	fprintf(hfile, "extern const char %s[];\n", name);
+	fprintf(cfile, "const char %s[%d] = {\n", name, size);
+	col = 0;
+	for (i = 0 ; i < size ; i++) {
+		if (i == 0) {
+			fputs("      ", cfile);
+		} else if ((i & 03) == 0) {
+			fputs(",\n      ", cfile);
+			col = 0;
+		} else {
+			putc(',', cfile);
+			while (++col < 9 * (i & 03))
+				putc(' ', cfile);
+		}
+		fputs(syntax[i], cfile);
+		col += strlen(syntax[i]);
+	}
+	fputs("\n};\n", cfile);
+}
+
+
+
+/*
+ * Output character classification macros (e.g. is_digit).  If digits are
+ * contiguous, we can test for them quickly.
+ */
+
+char *macro[] = {
+	"#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
+	"#define is_alpha(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER))",
+	"#define is_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER))",
+	"#define is_in_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))",
+	"#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
+	NULL
+};
+
+output_type_macros() {
+	char **pp;
+
+	if (digit_contig)
+		macro[0] = "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)";
+	for (pp = macro ; *pp ; pp++)
+		fprintf(hfile, "%s\n", *pp);
+	if (digit_contig)
+		fputs("#define digit_val(c)\t((c) - '0')\n", hfile);
+	else
+		fputs("#define digit_val(c)\t(digit_value[c])\n", hfile);
+}
+
+
+
+/*
+ * Output digit conversion table (if digits are not contiguous).
+ */
+
+digit_convert() {
+	int maxdigit;
+	static char digit[] = "0123456789";
+	char *p;
+	int i;
+
+	maxdigit = 0;
+	for (p = digit ; *p ; p++)
+		if (*p > maxdigit)
+			maxdigit = *p;
+	fputs("extern const char digit_value[];\n", hfile);
+	fputs("\n\nconst char digit_value[] = {\n", cfile);
+	for (i = 0 ; i <= maxdigit ; i++) {
+		for (p = digit ; *p && *p != i ; p++);
+		if (*p == '\0')
+			p = digit;
+		fprintf(cfile, "      %d,\n", p - digit);
+	}
+	fputs("};\n", cfile);
+}
Index: /trunk/minix/commands/ash/mktokens
===================================================================
--- /trunk/minix/commands/ash/mktokens	(revision 9)
+++ /trunk/minix/commands/ash/mktokens	(revision 9)
@@ -0,0 +1,121 @@
+#!/bin/sh -
+#
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)mktokens	5.1 (Berkeley) 3/7/91
+
+# All calls to awk removed, because Minix bawk is deficient.  (kjb)
+
+# The following is a list of tokens.  The second column is nonzero if the
+# token marks the end of a list.  The third column is the name to print in
+# error messages.
+
+cat > /tmp/ka$$ <<\!
+TEOF	1	end of file
+TNL	0	newline
+TSEMI	0	";"
+TBACKGND 0	"&"
+TAND	0	"&&"
+TOR	0	"||"
+TPIPE	0	"|"
+TLP	0	"("
+TRP	1	")"
+TENDCASE 1	";;"
+TENDBQUOTE 1	"`"
+TREDIR	0	redirection
+TWORD	0	word
+TIF	0	"if"
+TTHEN	1	"then"
+TELSE	1	"else"
+TELIF	1	"elif"
+TFI	1	"fi"
+TWHILE	0	"while"
+TUNTIL	0	"until"
+TFOR	0	"for"
+TDO	1	"do"
+TDONE	1	"done"
+TBEGIN	0	"{"
+TEND	1	"}"
+TCASE	0	"case"
+TESAC	1	"esac"
+!
+nl=`wc -l /tmp/ka$$`
+exec > token.def
+i=0
+while read line
+do
+	set -$- $line
+	echo "#define $1 $i"
+	i=`expr $i + 1`
+done </tmp/ka$$
+echo '
+/* Array indicating which tokens mark the end of a list */
+const char tokendlist[] = {'
+while read line
+do
+	set -$- $line
+	echo "	$2,"
+done </tmp/ka$$
+echo '};
+
+char *const tokname[] = {'
+sed -e 's/"/\\"/g' \
+    -e 's/[^	 ]*[	 ][	 ]*[^	 ]*[	 ][	 ]*\(.*\)/	"\1",/' \
+    /tmp/ka$$
+echo '};
+'
+i=0
+go=
+sed 's/"//g' /tmp/ka$$ |
+	while read line
+	do
+		set -$- $line
+		if [ "$1" = TIF ]
+		then
+			echo "#define KWDOFFSET $i"
+			echo
+			echo "char *const parsekwd[] = {"
+			go=true
+		fi
+		if [ "$go" ]
+		then
+			echo "	\"$3\","
+		fi
+		i=`expr $i + 1`
+	done
+echo '	0
+};'
+
+rm /tmp/ka$$
Index: /trunk/minix/commands/ash/mystring.c
===================================================================
--- /trunk/minix/commands/ash/mystring.c	(revision 9)
+++ /trunk/minix/commands/ash/mystring.c	(revision 9)
@@ -0,0 +1,174 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)mystring.c	5.1 (Berkeley) 3/7/91";
+#endif /* not lint */
+
+/*
+ * String functions.
+ *
+ *	equal(s1, s2)		Return true if strings are equal.
+ *	scopy(from, to)		Copy a string.
+ *	scopyn(from, to, n)	Like scopy, but checks for overflow.
+ *	strchr(s, c)		Find first occurance of c in s.
+ *	bcopy(from, to, n)	Copy a block of memory.
+ *	number(s)		Convert a string of digits to an integer.
+ *	is_number(s)		Return true if s is a string of digits.
+ */
+
+#include "shell.h"
+#include "syntax.h"
+#include "error.h"
+#include "mystring.h"
+
+
+char nullstr[1];		/* zero length string */
+
+
+/*
+ * scopyn - copy a string from "from" to "to", truncating the string
+ *		if necessary.  "To" is always nul terminated, even if
+ *		truncation is performed.  "Size" is the size of "to".
+ */
+
+void
+scopyn(from, to, size)
+	register char const *from;
+	register char *to;
+	register int size;
+	{
+
+	while (--size > 0) {
+		if ((*to++ = *from++) == '\0')
+			return;
+	}
+	*to = '\0';
+}
+
+
+/*
+ * strchr - find first occurrence of a character in a string.
+ */
+
+#ifndef SYS5
+char *
+mystrchr(s, charwanted)
+	char const *s;
+	register char charwanted;
+	{
+	register char const *scan;
+
+	/*
+	 * The odd placement of the two tests is so NUL is findable.
+	 */
+	for (scan = s ; *scan != charwanted ; )	/* ++ moved down for opt. */
+		if (*scan++ == '\0')
+			return NULL;
+	return (char *)scan;
+}
+#endif
+
+
+
+/*
+ * bcopy - copy bytes
+ *
+ * This routine was derived from code by Henry Spencer.
+ */
+
+void
+mybcopy(src, dst, length)
+	pointer dst;
+	const pointer src;
+	register int length;
+	{
+	register char *d = dst;
+	register char *s = src;
+
+	while (--length >= 0)
+		*d++ = *s++;
+}
+
+
+/*
+ * prefix -- see if pfx is a prefix of string.
+ */
+
+int
+prefix(pfx, string)
+	register char const *pfx;
+	register char const *string;
+	{
+	while (*pfx) {
+		if (*pfx++ != *string++)
+			return 0;
+	}
+	return 1;
+}
+
+
+/*
+ * Convert a string of digits to an integer, printing an error message on
+ * failure.
+ */
+
+int
+number(s)
+	const char *s;
+	{
+
+	if (! is_number(s))
+		error2("Illegal number", (char *)s);
+	return atoi(s);
+}
+
+
+
+/*
+ * Check for a valid number.  This should be elsewhere.
+ */
+
+int
+is_number(p)
+	register const char *p;
+	{
+	do {
+		if (! is_digit(*p))
+			return 0;
+	} while (*++p != '\0');
+	return 1;
+}
Index: /trunk/minix/commands/ash/mystring.h
===================================================================
--- /trunk/minix/commands/ash/mystring.h	(revision 9)
+++ /trunk/minix/commands/ash/mystring.h	(revision 9)
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)mystring.h	5.1 (Berkeley) 3/7/91
+ */
+
+#ifndef SYSV
+#define strchr mystrchr
+#endif
+
+#ifdef __STDC__
+void scopyn(const char *, char *, int);
+char *strchr(const char *, int);
+void mybcopy(const pointer, pointer, int);
+int prefix(const char *, const char *);
+int number(const char *);
+int is_number(const char *);
+int strcmp(const char *, const char *);	/* from C library */
+char *strcpy(char *, const char *);	/* from C library */
+int strlen(const char *);		/* from C library */
+char *strcat(char *, const char *);	/* from C library */
+char *strerror(int);			/* from C library */
+#else
+void scopyn();
+char *strchr();
+void mybcopy();
+int prefix();
+int number();
+int is_number();
+int strcmp();
+char *strcpy();
+int strlen();
+char *strcat();
+char *strerror();
+#endif
+
+#define equal(s1, s2)	(strcmp(s1, s2) == 0)
+#define scopy(s1, s2)	((void)strcpy(s2, s1))
+#define bcopy(src, dst, n)	mybcopy((pointer)(src), (pointer)(dst), n)
Index: /trunk/minix/commands/ash/nodes.c.pat
===================================================================
--- /trunk/minix/commands/ash/nodes.c.pat	(revision 9)
+++ /trunk/minix/commands/ash/nodes.c.pat	(revision 9)
@@ -0,0 +1,177 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)nodes.c.pat	5.2 (Berkeley) 3/8/91
+ */
+
+/*
+ * Routine for dealing with parsed shell commands.
+ */
+
+#include "shell.h"
+#include "nodes.h"
+#include "memalloc.h"
+#include "machdep.h"
+#include "mystring.h"
+
+
+int funcblocksize;		/* size of structures in function */
+int funcstringsize;		/* size of strings in node */
+#ifdef __STDC__
+pointer funcblock;		/* block to allocate function from */
+#else
+char *funcblock;		/* block to allocate function from */
+#endif
+char *funcstring;		/* block to allocate strings from */
+
+%SIZES
+
+
+#ifdef __STDC__
+STATIC void calcsize(union node *);
+STATIC void sizenodelist(struct nodelist *);
+STATIC union node *copynode(union node *);
+STATIC struct nodelist *copynodelist(struct nodelist *);
+STATIC char *nodesavestr(char *);
+#else
+STATIC void calcsize();
+STATIC void sizenodelist();
+STATIC union node *copynode();
+STATIC struct nodelist *copynodelist();
+STATIC char *nodesavestr();
+#endif
+
+
+
+/*
+ * Make a copy of a parse tree.
+ */
+
+union node *
+copyfunc(n)
+      union node *n;
+      {
+      if (n == NULL)
+	    return NULL;
+      funcblocksize = 0;
+      funcstringsize = 0;
+      calcsize(n);
+      funcblock = ckmalloc(funcblocksize + funcstringsize);
+      funcstring = (char *)funcblock + funcblocksize;
+      return copynode(n);
+}
+
+
+
+STATIC void
+calcsize(n)
+      union node *n;
+      {
+      %CALCSIZE
+}
+
+
+
+STATIC void
+sizenodelist(lp)
+      struct nodelist *lp;
+      {
+      while (lp) {
+	    funcblocksize += ALIGN(sizeof (struct nodelist));
+	    calcsize(lp->n);
+	    lp = lp->next;
+      }
+}
+
+
+
+STATIC union node *
+copynode(n)
+      union node *n;
+      {
+      union node *new;
+
+      %COPY
+      return new;
+}
+
+
+STATIC struct nodelist *
+copynodelist(lp)
+      struct nodelist *lp;
+      {
+      struct nodelist *start;
+      struct nodelist **lpp;
+
+      lpp = &start;
+      while (lp) {
+	    *lpp = funcblock;
+	    *(char **)&funcblock += ALIGN(sizeof (struct nodelist));
+	    (*lpp)->n = copynode(lp->n);
+	    lp = lp->next;
+	    lpp = &(*lpp)->next;
+      }
+      *lpp = NULL;
+      return start;
+}
+
+
+
+STATIC char *
+nodesavestr(s)
+      char *s;
+      {
+      register char *p = s;
+      register char *q = funcstring;
+      char *rtn = funcstring;
+
+      while (*q++ = *p++);
+      funcstring = q;
+      return rtn;
+}
+
+
+
+/*
+ * Free a parse tree.
+ */
+
+void
+freefunc(n)
+      union node *n;
+      {
+      if (n)
+	    ckfree(n);
+}
Index: /trunk/minix/commands/ash/nodetypes
===================================================================
--- /trunk/minix/commands/ash/nodetypes	(revision 9)
+++ /trunk/minix/commands/ash/nodetypes	(revision 9)
@@ -0,0 +1,140 @@
+#!/bin/sh -
+#
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)nodetypes	5.1 (Berkeley) 3/7/91
+
+# This file describes the nodes used in parse trees.  Unindented lines
+# contain a node type followed by a structure tag.  Subsequent indented
+# lines specify the fields of the structure.  Several node types can share
+# the same structure, in which case the fields of the structure should be
+# specified only once.
+#
+# A field of a structure is described by the name of the field followed
+# by a type.  The currently implemented types are:
+#	nodeptr - a pointer to a node
+#	nodelist - a pointer to a list of nodes
+#	string - a pointer to a nul terminated string
+#	int - an integer
+#	other - any type that can be copied by assignment
+#	temp - a field that doesn't have to be copied when the node is copied
+# The last two types should be followed by the text of a C declaration for
+# the field.
+
+NSEMI nbinary			# two commands separated by a semicolon
+	type	  int
+	ch1	  nodeptr		# the first child
+	ch2	  nodeptr		# the second child
+
+NCMD ncmd			# a simple command
+	type	  int
+	backgnd	  int			# set to run command in background
+	args	  nodeptr		# the arguments
+	redirect  nodeptr		# list of file redirections
+
+NPIPE npipe			# a pipeline
+	type	  int
+	backgnd	  int			# set to run pipeline in background
+	cmdlist	  nodelist		# the commands in the pipeline
+
+NREDIR nredir			# redirection (of a compex command)
+	type	  int
+	n	  nodeptr		# the command
+	redirect  nodeptr		# list of file redirections
+
+NBACKGND nredir			# run command in background
+NSUBSHELL nredir		# run command in a subshell
+
+NAND nbinary			# the && operator
+NOR nbinary			# the || operator
+
+NIF nif				# the if statement.  Elif clauses are handled
+	type	  int		    # using multiple if nodes.
+	test	  nodeptr		# if test
+	ifpart	  nodeptr		# then ifpart
+	elsepart  nodeptr		# else elsepart
+
+NWHILE nbinary			# the while statement.  First child is the test
+NUNTIL nbinary			# the until statement
+
+NFOR nfor			# the for statement
+	type	  int
+	args	  nodeptr		# for var in args
+	body	  nodeptr		# do body; done
+	var	  string		# the for variable
+
+NCASE ncase			# a case statement
+	type	  int
+	expr	  nodeptr		# the word to switch on
+	cases	  nodeptr		# the list of cases (NCLIST nodes)
+
+NCLIST nclist			# a case
+	type	  int
+	next	  nodeptr		# the next case in list
+	pattern	  nodeptr		# list of patterns for this case
+	body	  nodeptr		# code to execute for this case
+
+
+NDEFUN narg			# define a function.  The "next" field contains
+				# the body of the function.
+
+NARG narg			# represents a word
+	type	  int
+	next	  nodeptr		# next word in list
+	text	  string		# the text of the word
+	backquote nodelist		# list of commands in back quotes
+
+NTO nfile			# fd> fname
+NFROM nfile			# fd< fname
+NAPPEND nfile			# fd>> fname
+	type	  int
+	next	  nodeptr		# next redirection in list
+	fd	  int			# file descriptor being redirected
+	fname	  nodeptr		# file name, in a NARG node
+	expfname  temp	char *expfname	# actual file name
+
+NTOFD ndup			# fd<&dupfd
+NFROMFD ndup			# fd>&dupfd
+	type	  int
+	next	  nodeptr		# next redirection in list
+	fd	  int			# file descriptor being redirected
+	dupfd	  int			# file descriptor to duplicate
+
+NHERE nhere			# fd<<\!
+NXHERE nhere			# fd<<!
+	type	  int
+	next	  nodeptr		# next redirection in list
+	fd	  int			# file descriptor being redirected
+	doc	  nodeptr		# input to command (NARG node)
Index: /trunk/minix/commands/ash/options.c
===================================================================
--- /trunk/minix/commands/ash/options.c	(revision 9)
+++ /trunk/minix/commands/ash/options.c	(revision 9)
@@ -0,0 +1,397 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)options.c	5.2 (Berkeley) 3/13/91";
+#endif /* not lint */
+
+#include "shell.h"
+#define DEFINE_OPTIONS
+#include "options.h"
+#undef DEFINE_OPTIONS
+#include "nodes.h"	/* for other header files */
+#include "eval.h"
+#include "jobs.h"
+#include "input.h"
+#include "output.h"
+#include "trap.h"
+#include "var.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+
+char *arg0;			/* value of $0 */
+struct shparam shellparam;	/* current positional parameters */
+char **argptr;			/* argument list for builtin commands */
+char *optarg;			/* set by nextopt (like getopt) */
+char *optptr;			/* used by nextopt */
+int editable;			/* isatty(0) && isatty(1) */
+
+char *minusc;			/* argument to -c option */
+
+
+#ifdef __STDC__
+STATIC void options(int);
+STATIC void setoption(int, int);
+#else
+STATIC void options();
+STATIC void setoption();
+#endif
+
+
+
+/*
+ * Process the shell command line arguments.
+ */
+
+void
+procargs(argc, argv)
+	char **argv;
+	{
+	char *p;
+
+	argptr = argv;
+	if (argc > 0)
+		argptr++;
+	for (p = optval ; p < optval + sizeof optval - 1 ; p++)
+		*p = 2;
+	options(1);
+	if (*argptr == NULL && minusc == NULL)
+		sflag = 1;
+	editable = (isatty(0) && isatty(1));
+	if (iflag == 2 && sflag == 1 && editable)
+		iflag = 1;
+	if (jflag == 2)
+		jflag = iflag;
+	for (p = optval ; p < optval + sizeof optval - 1 ; p++)
+		if (*p == 2)
+			*p = 0;
+	arg0 = argv[0];
+	if (sflag == 0) {
+		arg0 = *argptr++;
+		if (minusc == NULL) {
+			commandname = arg0;
+			setinputfile(commandname, 0);
+		}
+	}
+	shellparam.p = argptr;
+	/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
+	while (*argptr) {
+		shellparam.nparam++;
+		argptr++;
+	}
+	setinteractive(iflag);
+	setjobctl(jflag);
+}
+
+
+
+/*
+ * Process shell options.  The global variable argptr contains a pointer
+ * to the argument list; we advance it past the options.
+ */
+
+STATIC void
+options(cmdline) {
+	register char *p;
+	int val;
+	int c;
+
+	if (cmdline)
+		minusc = NULL;
+	while ((p = *argptr) != NULL) {
+		argptr++;
+		if ((c = *p++) == '-') {
+			val = 1;
+                        if (p[0] == '\0' || p[0] == '-' && p[1] == '\0') {
+                                if (!cmdline) {
+                                        /* "-" means turn off -x and -v */
+                                        if (p[0] == '\0')
+                                                xflag = vflag = 0;
+                                        /* "--" means reset params */
+                                        else if (*argptr == NULL)
+                                                setparam(argptr);
+                                }
+				break;	  /* "-" or  "--" terminates options */
+			}
+		} else if (c == '+') {
+			val = 0;
+		} else {
+			argptr--;
+			break;
+		}
+		while ((c = *p++) != '\0') {
+			if (c == 'c' && cmdline) {
+				char *q;
+#ifdef NOHACK	/* removing this code allows sh -ce 'foo' for compat */
+				if (*p == '\0')
+#endif
+					q = *argptr++;
+				if (q == NULL || minusc != NULL)
+					error("Bad -c option");
+				minusc = q;
+#ifdef NOHACK
+				break;
+#endif
+			} else {
+				setoption(c, val);
+			}
+		}
+		if (! cmdline)
+			break;
+	}
+}
+
+
+STATIC void
+setoption(flag, val)
+	char flag;
+	int val;
+	{
+	register char *p;
+
+	if ((p = strchr(optchar, flag)) == NULL)
+		error("Illegal option -%c", flag);
+	optval[p - optchar] = val;
+}
+
+
+
+#ifdef mkinit
+INCLUDE "options.h"
+
+SHELLPROC {
+	char *p;
+
+	for (p = optval ; p < optval + sizeof optval ; p++)
+		*p = 0;
+}
+#endif
+
+
+/*
+ * Set the shell parameters.
+ */
+
+void
+setparam(argv)
+	char **argv;
+	{
+	char **newparam;
+	char **ap;
+	int nparam;
+
+	for (nparam = 0 ; argv[nparam] ; nparam++);
+	ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
+	while (*argv) {
+		*ap++ = savestr(*argv++);
+	}
+	*ap = NULL;
+	freeparam(&shellparam);
+	shellparam.malloc = 1;
+	shellparam.nparam = nparam;
+	shellparam.p = newparam;
+	shellparam.optnext = NULL;
+}
+
+
+/*
+ * Free the list of positional parameters.
+ */
+
+void
+freeparam(param)
+	struct shparam *param;
+	{
+	char **ap;
+
+	if (param->malloc) {
+		for (ap = param->p ; *ap ; ap++)
+			ckfree(*ap);
+		ckfree(param->p);
+	}
+}
+
+
+
+/*
+ * The shift builtin command.
+ */
+
+shiftcmd(argc, argv)  char **argv; {
+	int n;
+	char **ap1, **ap2;
+
+	n = 1;
+	if (argc > 1)
+		n = number(argv[1]);
+	if (n > shellparam.nparam)
+		n = shellparam.nparam;
+	INTOFF;
+	shellparam.nparam -= n;
+	for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
+		if (shellparam.malloc)
+			ckfree(*ap1);
+	}
+	ap2 = shellparam.p;
+	while ((*ap2++ = *ap1++) != NULL);
+	shellparam.optnext = NULL;
+	INTON;
+	return 0;
+}
+
+
+
+/*
+ * The set command builtin.
+ */
+
+setcmd(argc, argv)  char **argv; {
+	if (argc == 1)
+		return showvarscmd(argc, argv);
+	INTOFF;
+	options(0);
+	setinteractive(iflag);
+	setjobctl(jflag);
+	if (*argptr != NULL) {
+		setparam(argptr);
+	}
+	INTON;
+	return 0;
+}
+
+
+/*
+ * The getopts builtin.  Shellparam.optnext points to the next argument
+ * to be processed.  Shellparam.optptr points to the next character to
+ * be processed in the current argument.  If shellparam.optnext is NULL,
+ * then it's the first time getopts has been called.
+ */
+
+getoptscmd(argc, argv)  char **argv; {
+	register char *p, *q;
+	char c;
+	char s[10];
+
+	if (argc != 3)
+		error("Usage: getopts optstring var");
+	if (shellparam.optnext == NULL) {
+		shellparam.optnext = shellparam.p;
+		shellparam.optptr = NULL;
+	}
+	if ((p = shellparam.optptr) == NULL || *p == '\0') {
+		p = *shellparam.optnext;
+		if (p == NULL || *p != '-' || *++p == '\0') {
+atend:
+			fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
+			setvar("OPTIND", s, 0);
+			shellparam.optnext = NULL;
+			return 1;
+		}
+		shellparam.optnext++;
+		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
+			goto atend;
+	}
+	c = *p++;
+	for (q = argv[1] ; *q != c ; ) {
+		if (*q == '\0') {
+			out1fmt("Illegal option -%c\n", c);
+			c = '?';
+			goto out;
+		}
+		if (*++q == ':')
+			q++;
+	}
+	if (*++q == ':') {
+		if (*p == '\0') {
+			if ((p = *shellparam.optnext) == NULL) {
+				out1fmt("No arg for -%c option\n", c);
+				c = '?';
+				goto out;
+			}
+			shellparam.optnext++;
+		}
+		setvar("OPTARG", p, 0);
+		p = "";
+	}
+out:
+	shellparam.optptr = p;
+	s[0] = c;
+	s[1] = '\0';
+	setvar(argv[2], s, 0);
+	fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
+	setvar("OPTIND", s, 0);
+	return 0;
+}
+
+/*
+ * Standard option processing (a la getopt) for builtin routines.  The
+ * only argument that is passed to nextopt is the option string; the
+ * other arguments are unnecessary.  It return the character, or '\0' on
+ * end of input.
+ */
+
+int
+nextopt(optstring)
+	char *optstring;
+	{
+	register char *p, *q;
+	char c;
+
+	if ((p = optptr) == NULL || *p == '\0') {
+		p = *argptr;
+		if (p == NULL || *p != '-' || *++p == '\0')
+			return '\0';
+		argptr++;
+		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
+			return '\0';
+	}
+	c = *p++;
+	for (q = optstring ; *q != c ; ) {
+		if (*q == '\0')
+			error("Illegal option -%c", c);
+		if (*++q == ':')
+			q++;
+	}
+	if (*++q == ':') {
+		if (*p == '\0' && (p = *argptr++) == NULL)
+			error("No arg for -%c option", c);
+		optarg = p;
+		p = NULL;
+	}
+	optptr = p;
+	return c;
+}
Index: /trunk/minix/commands/ash/options.h
===================================================================
--- /trunk/minix/commands/ash/options.h	(revision 9)
+++ /trunk/minix/commands/ash/options.h	(revision 9)
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)options.h	5.1 (Berkeley) 3/7/91
+ */
+
+struct shparam {
+	int nparam;	/* number of positional parameters (without $0) */
+	char malloc;	/* true if parameter list dynamicly allocated */
+	char **p;		/* parameter list */
+	char **optnext;	/* next parameter to be processed by getopts */
+	char *optptr;	/* used by getopts */
+};
+
+
+
+#define eflag optval[0]
+#define fflag optval[1]
+#define Iflag optval[2]
+#define iflag optval[3]
+#define jflag optval[4]
+#define nflag optval[5]
+#define sflag optval[6]
+#define xflag optval[7]
+#define zflag optval[8]
+#define vflag optval[9]
+
+#define NOPTS	10
+
+#ifdef DEFINE_OPTIONS
+const char optchar[NOPTS+1] = "efIijnsxzv";       /* shell flags */
+char optval[NOPTS+1];           /* values of option flags */
+#else
+extern const char optchar[NOPTS+1];
+extern char optval[NOPTS+1];
+#endif
+
+
+extern char *minusc;		/* argument to -c option */
+extern char *arg0;		/* $0 */
+extern struct shparam shellparam;  /* $@ */
+extern char **argptr;		/* argument list for builtin commands */
+extern char *optarg;		/* set by nextopt */
+extern char *optptr;		/* used by nextopt */
+extern int editable;		/* isatty(0) && isatty(1) */
+
+
+#ifdef __STDC__
+void procargs(int, char **);
+void setparam(char **);
+void freeparam(struct shparam *);
+int nextopt(char *);
+#else
+void procargs();
+void setparam();
+void freeparam();
+int nextopt();
+#endif
Index: /trunk/minix/commands/ash/output.c
===================================================================
--- /trunk/minix/commands/ash/output.c	(revision 9)
+++ /trunk/minix/commands/ash/output.c	(revision 9)
@@ -0,0 +1,531 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)output.c	5.1 (Berkeley) 3/7/91";
+#endif /* not lint */
+
+/*
+ * Shell output routines.  We use our own output routines because:
+ *	When a builtin command is interrupted we have to discard
+ *		any pending output.
+ *	When a builtin command appears in back quotes, we want to
+ *		save the output of the command in a region obtained
+ *		via malloc, rather than doing a fork and reading the
+ *		output of the command via a pipe.
+ *	Our output routines may be smaller than the stdio routines.
+ */
+
+#include <stdio.h>	/* defines BUFSIZ */
+#include "shell.h"
+#include "syntax.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#ifdef __STDC__
+#include "stdarg.h"
+#else
+#include <varargs.h>
+#endif
+#include <errno.h>
+
+
+#define OUTBUFSIZ BUFSIZ
+#define BLOCK_OUT -2		/* output to a fixed block of memory */
+#define MEM_OUT -3		/* output to dynamically allocated memory */
+#define OUTPUT_ERR 01		/* error occurred on output */
+
+
+struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
+struct output errout = {NULL, 0, NULL, 100, 2, 0};
+struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
+struct output *out1 = &output;
+struct output *out2 = &errout;
+
+
+
+#ifdef mkinit
+
+INCLUDE "output.h"
+INCLUDE "memalloc.h"
+
+RESET {
+	out1 = &output;
+	out2 = &errout;
+	if (memout.buf != NULL) {
+		ckfree(memout.buf);
+		memout.buf = NULL;
+	}
+}
+
+#endif
+
+
+#ifdef notdef	/* no longer used */
+/*
+ * Set up an output file to write to memory rather than a file.
+ */
+
+void
+open_mem(block, length, file)
+	char *block;
+	int length;
+	struct output *file;
+	{
+	file->nextc = block;
+	file->nleft = --length;
+	file->fd = BLOCK_OUT;
+	file->flags = 0;
+}
+#endif
+
+
+void
+out1str(p)
+	char *p;
+	{
+	outstr(p, out1);
+}
+
+
+void
+out2str(p)
+	char *p;
+	{
+	outstr(p, out2);
+}
+
+
+void
+outstr(p, file)
+	register char *p;
+	register struct output *file;
+	{
+	while (*p)
+		outc(*p++, file);
+}
+
+
+char out_junk[16];
+
+
+void
+emptyoutbuf(dest)
+	struct output *dest;
+	{
+	int offset;
+
+	if (dest->fd == BLOCK_OUT) {
+		dest->nextc = out_junk;
+		dest->nleft = sizeof out_junk;
+		dest->flags |= OUTPUT_ERR;
+	} else if (dest->buf == NULL) {
+		INTOFF;
+		dest->buf = ckmalloc(dest->bufsize);
+		dest->nextc = dest->buf;
+		dest->nleft = dest->bufsize;
+		INTON;
+	} else if (dest->fd == MEM_OUT) {
+		offset = dest->bufsize;
+		INTOFF;
+		dest->bufsize <<= 1;
+		dest->buf = ckrealloc(dest->buf, dest->bufsize);
+		dest->nleft = dest->bufsize - offset;
+		dest->nextc = dest->buf + offset;
+		INTON;
+	} else {
+		flushout(dest);
+	}
+	dest->nleft--;
+}
+
+
+void
+flushall() {
+	flushout(&output);
+	flushout(&errout);
+}
+
+
+void
+flushout(dest)
+	struct output *dest;
+	{
+
+	if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
+		return;
+	if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0)
+		dest->flags |= OUTPUT_ERR;
+	dest->nextc = dest->buf;
+	dest->nleft = dest->bufsize;
+}
+
+
+void
+freestdout() {
+	INTOFF;
+	if (output.buf) {
+		ckfree(output.buf);
+		output.buf = NULL;
+		output.nleft = 0;
+	}
+	INTON;
+}
+
+
+#ifdef __STDC__
+void
+outfmt(struct output *file, char *fmt, ...) {
+	va_list ap;
+
+	va_start(ap, fmt);
+	doformat(file, fmt, ap);
+	va_end(ap);
+}
+
+
+void
+out1fmt(char *fmt, ...) {
+	va_list ap;
+
+	va_start(ap, fmt);
+	doformat(out1, fmt, ap);
+	va_end(ap);
+}
+
+
+void
+fmtstr(char *outbuf, int length, char *fmt, ...) {
+	va_list ap;
+	struct output strout;
+
+	va_start(ap, fmt);
+	strout.nextc = outbuf;
+	strout.nleft = length;
+	strout.fd = BLOCK_OUT;
+	strout.flags = 0;
+	doformat(&strout, fmt, ap);
+	outc('\0', &strout);
+	if (strout.flags & OUTPUT_ERR)
+		outbuf[length - 1] = '\0';
+	va_end(ap);
+}
+
+#else /* not __STDC__ */
+
+void
+outfmt(va_alist)
+	va_dcl
+	{
+	va_list ap;
+	struct output *file;
+	char *fmt;
+
+	va_start(ap);
+	file = va_arg(ap, struct output *);
+	fmt = va_arg(ap, char *);
+	doformat(file, fmt, ap);
+	va_end(ap);
+}
+
+
+void
+out1fmt(va_alist)
+	va_dcl
+	{
+	va_list ap;
+	char *fmt;
+
+	va_start(ap);
+	fmt = va_arg(ap, char *);
+	doformat(out1, fmt, ap);
+	va_end(ap);
+}
+
+
+void
+fmtstr(va_alist)
+	va_dcl
+	{
+	va_list ap;
+	struct output strout;
+	char *outbuf;
+	int length;
+	char *fmt;
+
+	va_start(ap);
+	outbuf = va_arg(ap, char *);
+	length = va_arg(ap, int);
+	fmt = va_arg(ap, char *);
+	strout.nextc = outbuf;
+	strout.nleft = length;
+	strout.fd = BLOCK_OUT;
+	strout.flags = 0;
+	doformat(&strout, fmt, ap);
+	outc('\0', &strout);
+	if (strout.flags & OUTPUT_ERR)
+		outbuf[length - 1] = '\0';
+}
+#endif /* __STDC__ */
+
+
+/*
+ * Formatted output.  This routine handles a subset of the printf formats:
+ * - Formats supported: d, u, o, X, s, and c.
+ * - The x format is also accepted but is treated like X.
+ * - The l modifier is accepted.
+ * - The - and # flags are accepted; # only works with the o format.
+ * - Width and precision may be specified with any format except c.
+ * - An * may be given for the width or precision.
+ * - The obsolete practice of preceding the width with a zero to get
+ *   zero padding is not supported; use the precision field.
+ * - A % may be printed by writing %% in the format string.
+ */
+
+#define TEMPSIZE 24
+
+#ifdef __STDC__
+static const char digit[16] = "0123456789ABCDEF";
+#else
+static const char digit[17] = "0123456789ABCDEF";
+#endif
+
+
+void
+doformat(dest, f, ap)
+	register struct output *dest;
+	register char *f;		/* format string */
+	va_list ap;
+	{
+	register char c;
+	char temp[TEMPSIZE];
+	int flushleft;
+	int sharp;
+	int width;
+	int prec;
+	int islong;
+	char *p;
+	int sign;
+	long l;
+	unsigned long num;
+	unsigned base;
+	int len;
+	int size;
+	int pad;
+
+	while ((c = *f++) != '\0') {
+		if (c != '%') {
+			outc(c, dest);
+			continue;
+		}
+		flushleft = 0;
+		sharp = 0;
+		width = 0;
+		prec = -1;
+		islong = 0;
+		for (;;) {
+			if (*f == '-')
+				flushleft++;
+			else if (*f == '#')
+				sharp++;
+			else
+				break;
+			f++;
+		}
+		if (*f == '*') {
+			width = va_arg(ap, int);
+			f++;
+		} else {
+			while (is_digit(*f)) {
+				width = 10 * width + digit_val(*f++);
+			}
+		}
+		if (*f == '.') {
+			if (*++f == '*') {
+				prec = va_arg(ap, int);
+				f++;
+			} else {
+				prec = 0;
+				while (is_digit(*f)) {
+					prec = 10 * prec + digit_val(*f++);
+				}
+			}
+		}
+		if (*f == 'l') {
+			islong++;
+			f++;
+		}
+		switch (*f) {
+		case 'd':
+			if (islong)
+				l = va_arg(ap, long);
+			else
+				l = va_arg(ap, int);
+			sign = 0;
+			num = l;
+			if (l < 0) {
+				num = -l;
+				sign = 1;
+			}
+			base = 10;
+			goto number;
+		case 'u':
+			base = 10;
+			goto uns_number;
+		case 'o':
+			base = 8;
+			goto uns_number;
+		case 'x':
+			/* we don't implement 'x'; treat like 'X' */
+		case 'X':
+			base = 16;
+uns_number:	  /* an unsigned number */
+			sign = 0;
+			if (islong)
+				num = va_arg(ap, unsigned long);
+			else
+				num = va_arg(ap, unsigned int);
+number:		  /* process a number */
+			p = temp + TEMPSIZE - 1;
+			*p = '\0';
+			while (num) {
+				*--p = digit[num % base];
+				num /= base;
+			}
+			len = (temp + TEMPSIZE - 1) - p;
+			if (prec < 0)
+				prec = 1;
+			if (sharp && *f == 'o' && prec <= len)
+				prec = len + 1;
+			pad = 0;
+			if (width) {
+				size = len;
+				if (size < prec)
+					size = prec;
+				size += sign;
+				pad = width - size;
+				if (flushleft == 0) {
+					while (--pad >= 0)
+						outc(' ', dest);
+				}
+			}
+			if (sign)
+				outc('-', dest);
+			prec -= len;
+			while (--prec >= 0)
+				outc('0', dest);
+			while (*p)
+				outc(*p++, dest);
+			while (--pad >= 0)
+				outc(' ', dest);
+			break;
+		case 's':
+			p = va_arg(ap, char *);
+			pad = 0;
+			if (width) {
+				len = strlen(p);
+				if (prec >= 0 && len > prec)
+					len = prec;
+				pad = width - len;
+				if (flushleft == 0) {
+					while (--pad >= 0)
+						outc(' ', dest);
+				}
+			}
+			prec++;
+			while (--prec != 0 && *p)
+				outc(*p++, dest);
+			while (--pad >= 0)
+				outc(' ', dest);
+			break;
+		case 'c':
+			c = va_arg(ap, int);
+			outc(c, dest);
+			break;
+		default:
+			outc(*f, dest);
+			break;
+		}
+		f++;
+	}
+}
+
+
+
+/*
+ * Version of write which resumes after a signal is caught.
+ */
+
+int
+xwrite(fd, buf, nbytes)
+	int fd;
+	char *buf;
+	int nbytes;
+	{
+	int ntry;
+	int i;
+	int n;
+
+	n = nbytes;
+	ntry = 0;
+	for (;;) {
+		i = write(fd, buf, n);
+		if (i > 0) {
+			if ((n -= i) <= 0)
+				return nbytes;
+			buf += i;
+			ntry = 0;
+		} else if (i == 0) {
+			if (++ntry > 10)
+				return nbytes - n;
+		} else if (errno != EINTR) {
+			return -1;
+		}
+	}
+}
+
+
+/*
+ * Version of ioctl that retries after a signal is caught.
+ */
+
+int
+xioctl(fd, request, arg) {
+	int i;
+
+	while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
+	return i;
+}
Index: /trunk/minix/commands/ash/output.h
===================================================================
--- /trunk/minix/commands/ash/output.h	(revision 9)
+++ /trunk/minix/commands/ash/output.h	(revision 9)
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)output.h	5.1 (Berkeley) 3/7/91
+ */
+
+#ifndef OUTPUT_INCL
+
+struct output {
+	char *nextc;
+	int nleft;
+	char *buf;
+	int bufsize;
+	short fd;
+	short flags;
+};
+
+extern struct output output;
+extern struct output errout;
+extern struct output memout;
+extern struct output *out1;
+extern struct output *out2;
+
+
+#ifdef __STDC__
+void outstr(char *, struct output *);
+void out1str(char *);
+void out2str(char *);
+void outfmt(struct output *, char *, ...);
+void out1fmt(char *, ...);
+void fmtstr(char *, int, char *, ...);
+/* void doformat(struct output *, char *, va_list); */
+void doformat();
+void emptyoutbuf(struct output *);
+void flushall(void);
+void flushout(struct output *);
+void freestdout(void);
+int xwrite(int, char *, int);
+int xioctl(int, int, int);
+#else
+void outstr();
+void out1str();
+void out2str();
+void outfmt();
+void out1fmt();
+void fmtstr();
+/* void doformat(); */
+void doformat();
+void emptyoutbuf();
+void flushall();
+void flushout();
+void freestdout();
+int xwrite();
+int xioctl();
+#endif
+
+#define outc(c, file)	(--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
+#define out1c(c)	outc(c, out1);
+#define out2c(c)	outc(c, out2);
+
+#define OUTPUT_INCL
+#endif
Index: /trunk/minix/commands/ash/parser.c
===================================================================
--- /trunk/minix/commands/ash/parser.c	(revision 9)
+++ /trunk/minix/commands/ash/parser.c	(revision 9)
@@ -0,0 +1,1329 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)parser.c	5.3 (Berkeley) 4/12/91";
+#endif /* not lint */
+
+#include "shell.h"
+#include "parser.h"
+#include "nodes.h"
+#include "expand.h"	/* defines rmescapes() */
+#include "redir.h"	/* defines copyfd() */
+#include "syntax.h"
+#include "options.h"
+#include "input.h"
+#include "output.h"
+#include "var.h"
+#include "error.h"
+#include "memalloc.h"
+#include "mystring.h"
+
+
+/*
+ * Shell command parser.
+ */
+
+#define EOFMARKLEN 79
+
+/* values returned by readtoken */
+#include "token.def"
+
+
+
+struct heredoc {
+	struct heredoc *next;	/* next here document in list */
+	union node *here;		/* redirection node */
+	char *eofmark;		/* string indicating end of input */
+	int striptabs;		/* if set, strip leading tabs */
+};
+
+
+
+struct heredoc *heredoclist;	/* list of here documents to read */
+int parsebackquote;		/* nonzero if we are inside backquotes */
+int doprompt;			/* if set, prompt the user */
+int needprompt;			/* true if interactive and at start of line */
+int lasttoken;			/* last token read */
+MKINIT int tokpushback;		/* last token pushed back */
+char *wordtext;			/* text of last word returned by readtoken */
+int checkkwd;               /* 1 == check for kwds, 2 == also eat newlines */
+struct nodelist *backquotelist;
+union node *redirnode;
+struct heredoc *heredoc;
+int quoteflag;			/* set if (part of) last token was quoted */
+int startlinno;			/* line # where last token started */
+
+
+#define GDB_HACK 1 /* avoid local declarations which gdb can't handle */
+#ifdef GDB_HACK
+static const char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'};
+static const char types[] = "}-+?=";
+#endif
+
+
+STATIC union node *list __P((int));
+STATIC union node *andor __P((void));
+STATIC union node *pipeline __P((void));
+STATIC union node *command __P((void));
+STATIC union node *simplecmd __P((union node **, union node *));
+STATIC void parsefname __P((void));
+STATIC void parseheredoc __P((void));
+STATIC int readtoken __P((void));
+STATIC int readtoken1 __P((int, char const *, char *, int));
+STATIC void attyline __P((void));
+STATIC int noexpand __P((char *));
+STATIC void synexpect __P((int));
+STATIC void synerror __P((char *));
+
+#if ATTY || READLINE
+STATIC void putprompt __P((char *));
+#else /* not ATTY */
+#define putprompt(s)	out2str(s)
+#endif
+
+
+
+
+/*
+ * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
+ * valid parse tree indicating a blank line.)
+ */
+
+union node *
+parsecmd(interact) {
+	int t;
+	extern int exitstatus;
+
+	doprompt = interact;
+	if (doprompt)
+		putprompt(exitstatus == 0 ? ps1val() : pseval());
+	needprompt = 0;
+	if ((t = readtoken()) == TEOF)
+		return NEOF;
+	if (t == TNL)
+		return NULL;
+	tokpushback++;
+	return list(1);
+}
+
+
+STATIC union node *
+list(nlflag) {
+	union node *n1, *n2, *n3, **pn;
+	int first;
+
+	checkkwd = 2;
+	if (nlflag == 0 && tokendlist[peektoken()])
+		return NULL;
+	n1 = andor();
+	for (first = 1; ; first = 0) {
+		switch (readtoken()) {
+		case TBACKGND:
+			pn = &n1;
+			if (!first && n1->type == NSEMI) pn = &n1->nbinary.ch2;
+			if ((*pn)->type == NCMD || (*pn)->type == NPIPE) {
+				(*pn)->ncmd.backgnd = 1;
+			} else if ((*pn)->type == NREDIR) {
+				(*pn)->type = NBACKGND;
+			} else {
+				n3 = (union node *)stalloc(sizeof (struct nredir));
+				n3->type = NBACKGND;
+				n3->nredir.n = *pn;
+				n3->nredir.redirect = NULL;
+				*pn = n3;
+			}
+			goto tsemi;
+		case TNL:
+			tokpushback++;
+			/* fall through */
+tsemi:		case TSEMI:
+			if (readtoken() == TNL) {
+				parseheredoc();
+				if (nlflag)
+					return n1;
+			} else {
+				tokpushback++;
+			}
+			checkkwd = 2;
+			if (tokendlist[peektoken()])
+				return n1;
+			n2 = andor();
+			n3 = (union node *)stalloc(sizeof (struct nbinary));
+			n3->type = NSEMI;
+			n3->nbinary.ch1 = n1;
+			n3->nbinary.ch2 = n2;
+			n1 = n3;
+			break;
+		case TEOF:
+			if (heredoclist)
+				parseheredoc();
+			else
+				pungetc();		/* push back EOF on input */
+			return n1;
+		default:
+			if (nlflag)
+				synexpect(-1);
+			tokpushback++;
+			return n1;
+		}
+	}
+}
+
+
+
+STATIC union node *
+andor() {
+	union node *n1, *n2, *n3;
+	int t;
+
+	n1 = pipeline();
+	for (;;) {
+		if ((t = readtoken()) == TAND) {
+			t = NAND;
+		} else if (t == TOR) {
+			t = NOR;
+		} else {
+			tokpushback++;
+			return n1;
+		}
+		n2 = pipeline();
+		n3 = (union node *)stalloc(sizeof (struct nbinary));
+		n3->type = t;
+		n3->nbinary.ch1 = n1;
+		n3->nbinary.ch2 = n2;
+		n1 = n3;
+	}
+}
+
+
+
+STATIC union node *
+pipeline() {
+	union node *n1, *pipenode;
+	struct nodelist *lp, *prev;
+
+	n1 = command();
+	if (readtoken() == TPIPE) {
+		pipenode = (union node *)stalloc(sizeof (struct npipe));
+		pipenode->type = NPIPE;
+		pipenode->npipe.backgnd = 0;
+		lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+		pipenode->npipe.cmdlist = lp;
+		lp->n = n1;
+		do {
+			prev = lp;
+			lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+			lp->n = command();
+			prev->next = lp;
+		} while (readtoken() == TPIPE);
+		lp->next = NULL;
+		n1 = pipenode;
+	}
+	tokpushback++;
+	return n1;
+}
+
+
+
+STATIC union node *
+command() {
+	union node *n1, *n2;
+	union node *ap, **app;
+	union node *cp, **cpp;
+	union node *redir, **rpp;
+	int t;
+
+	checkkwd = 2;
+	redir = 0;
+	rpp = &redir;
+	/* Check for redirection which may precede command */
+	while (readtoken() == TREDIR) {
+		*rpp = n2 = redirnode;
+		rpp = &n2->nfile.next;
+		parsefname();
+	}
+	tokpushback++;
+
+	switch (readtoken()) {
+	case TIF:
+		n1 = (union node *)stalloc(sizeof (struct nif));
+		n1->type = NIF;
+		n1->nif.test = list(0);
+		if (readtoken() != TTHEN)
+			synexpect(TTHEN);
+		n1->nif.ifpart = list(0);
+		n2 = n1;
+		while (readtoken() == TELIF) {
+			n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
+			n2 = n2->nif.elsepart;
+			n2->type = NIF;
+			n2->nif.test = list(0);
+			if (readtoken() != TTHEN)
+				synexpect(TTHEN);
+			n2->nif.ifpart = list(0);
+		}
+		if (lasttoken == TELSE)
+			n2->nif.elsepart = list(0);
+		else {
+			n2->nif.elsepart = NULL;
+			tokpushback++;
+		}
+		if (readtoken() != TFI)
+			synexpect(TFI);
+		checkkwd = 1;
+		break;
+	case TWHILE:
+	case TUNTIL: {
+		int got;
+		n1 = (union node *)stalloc(sizeof (struct nbinary));
+		n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
+		n1->nbinary.ch1 = list(0);
+		if ((got=readtoken()) != TDO) {
+TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
+			synexpect(TDO);
+		}
+		n1->nbinary.ch2 = list(0);
+		if (readtoken() != TDONE)
+			synexpect(TDONE);
+		checkkwd = 1;
+		break;
+	}
+	case TFOR:
+		if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
+			synerror("Bad for loop variable");
+		n1 = (union node *)stalloc(sizeof (struct nfor));
+		n1->type = NFOR;
+		n1->nfor.var = wordtext;
+		if (readtoken() == TWORD && ! quoteflag && equal(wordtext, "in")) {
+			app = &ap;
+			while (readtoken() == TWORD) {
+				n2 = (union node *)stalloc(sizeof (struct narg));
+				n2->type = NARG;
+				n2->narg.text = wordtext;
+				n2->narg.backquote = backquotelist;
+				*app = n2;
+				app = &n2->narg.next;
+			}
+			*app = NULL;
+			n1->nfor.args = ap;
+			/* A newline or semicolon is required here to end
+			   the list.  */
+			if (lasttoken != TNL && lasttoken != TSEMI)
+				synexpect(-1);
+		} else {
+#ifndef GDB_HACK
+			static const char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
+								   '@', '=', '\0'};
+#endif
+			n2 = (union node *)stalloc(sizeof (struct narg));
+			n2->type = NARG;
+			n2->narg.text = (char *)argvars;
+			n2->narg.backquote = NULL;
+			n2->narg.next = NULL;
+			n1->nfor.args = n2;
+			/* A newline or semicolon is optional here. Anything
+			   else gets pushed back so we can read it again.  */
+			if (lasttoken != TNL && lasttoken != TSEMI)
+				tokpushback++;
+		}
+		checkkwd = 2;
+		if ((t = readtoken()) == TDO)
+			t = TDONE;
+		else if (t == TBEGIN)
+			t = TEND;
+		else
+			synexpect(-1);
+		n1->nfor.body = list(0);
+		if (readtoken() != t)
+			synexpect(t);
+		checkkwd = 1;
+		break;
+	case TCASE:
+		n1 = (union node *)stalloc(sizeof (struct ncase));
+		n1->type = NCASE;
+		if (readtoken() != TWORD)
+			synexpect(TWORD);
+		n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
+		n2->type = NARG;
+		n2->narg.text = wordtext;
+		n2->narg.backquote = backquotelist;
+		n2->narg.next = NULL;
+		while (readtoken() == TNL);
+		if (lasttoken != TWORD || ! equal(wordtext, "in"))
+			synerror("expecting \"in\"");
+		cpp = &n1->ncase.cases;
+		while (checkkwd = 2, readtoken() == TWORD) {
+			*cpp = cp = (union node *)stalloc(sizeof (struct nclist));
+			cp->type = NCLIST;
+			app = &cp->nclist.pattern;
+			for (;;) {
+				*app = ap = (union node *)stalloc(sizeof (struct narg));
+				ap->type = NARG;
+				ap->narg.text = wordtext;
+				ap->narg.backquote = backquotelist;
+				if (readtoken() != TPIPE)
+					break;
+				app = &ap->narg.next;
+				if (readtoken() != TWORD)
+					synexpect(TWORD);
+			}
+			ap->narg.next = NULL;
+			if (lasttoken != TRP)
+				synexpect(TRP);
+			cp->nclist.body = list(0);
+			if ((t = readtoken()) == TESAC)
+				tokpushback++;
+			else if (t != TENDCASE)
+				synexpect(TENDCASE);
+			cpp = &cp->nclist.next;
+		}
+		*cpp = NULL;
+		if (lasttoken != TESAC)
+			synexpect(TESAC);
+		checkkwd = 1;
+		break;
+	case TLP:
+		n1 = (union node *)stalloc(sizeof (struct nredir));
+		n1->type = NSUBSHELL;
+		n1->nredir.n = list(0);
+		n1->nredir.redirect = NULL;
+		if (readtoken() != TRP)
+			synexpect(TRP);
+		checkkwd = 1;
+		break;
+	case TBEGIN:
+		n1 = list(0);
+		if (readtoken() != TEND)
+			synexpect(TEND);
+		checkkwd = 1;
+		break;
+	/* Handle an empty command like other simple commands.  */
+	case TNL:
+	case TSEMI:
+	case TEND:
+	case TRP:
+	case TEOF:
+	case TWORD:
+		tokpushback++;
+		return simplecmd(rpp, redir);
+	default:
+		synexpect(-1);
+	}
+
+	/* Now check for redirection which may follow command */
+	while (readtoken() == TREDIR) {
+		*rpp = n2 = redirnode;
+		rpp = &n2->nfile.next;
+		parsefname();
+	}
+	tokpushback++;
+	*rpp = NULL;
+	if (redir) {
+		if (n1->type != NSUBSHELL) {
+			n2 = (union node *)stalloc(sizeof (struct nredir));
+			n2->type = NREDIR;
+			n2->nredir.n = n1;
+			n1 = n2;
+		}
+		n1->nredir.redirect = redir;
+	}
+	return n1;
+}
+
+
+STATIC union node *
+simplecmd(rpp, redir)
+	union node **rpp, *redir;
+	{
+	union node *args, **app;
+	union node **orig_rpp = rpp;
+	union node *n;
+
+	/* If we don't have any redirections already, then we must reset
+	   rpp to be the address of the local redir variable.  */
+	if (redir == 0)
+		rpp = &redir;
+
+	args = NULL;
+	app = &args;
+	/* We save the incoming value, because we need this for shell
+	   functions.  There can not be a redirect or an argument between
+	   the function name and the open parenthesis.  */
+	orig_rpp = rpp;
+	for (;;) {
+		if (readtoken() == TWORD) {
+			n = (union node *)stalloc(sizeof (struct narg));
+			n->type = NARG;
+			n->narg.text = wordtext;
+			n->narg.backquote = backquotelist;
+			*app = n;
+			app = &n->narg.next;
+		} else if (lasttoken == TREDIR) {
+			*rpp = n = redirnode;
+			rpp = &n->nfile.next;
+			parsefname();	/* read name of redirection file */
+		} else if (lasttoken == TLP && app == &args->narg.next
+					    && rpp == orig_rpp) {
+			/* We have a function */
+			if (readtoken() != TRP)
+				synexpect(TRP);
+#ifdef notdef
+			if (! goodname(n->narg.text))
+				synerror("Bad function name");
+#endif
+			n->type = NDEFUN;
+			n->narg.next = command();
+			return n;
+		} else {
+			tokpushback++;
+			break;
+		}
+	}
+	*app = NULL;
+	*rpp = NULL;
+	n = (union node *)stalloc(sizeof (struct ncmd));
+	n->type = NCMD;
+	n->ncmd.backgnd = 0;
+	n->ncmd.args = args;
+	n->ncmd.redirect = redir;
+	return n;
+}
+
+
+STATIC void
+parsefname() {
+	union node *n = redirnode;
+
+	if (readtoken() != TWORD)
+		synexpect(-1);
+	if (n->type == NHERE) {
+		struct heredoc *here = heredoc;
+		struct heredoc *p;
+		int i;
+
+		if (quoteflag == 0)
+			n->type = NXHERE;
+		TRACE(("Here document %d\n", n->type));
+		if (here->striptabs) {
+			while (*wordtext == '\t')
+				wordtext++;
+		}
+		if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
+			synerror("Illegal eof marker for << redirection");
+		rmescapes(wordtext);
+		here->eofmark = wordtext;
+		here->next = NULL;
+		if (heredoclist == NULL)
+			heredoclist = here;
+		else {
+			for (p = heredoclist ; p->next ; p = p->next);
+			p->next = here;
+		}
+	} else if (n->type == NTOFD || n->type == NFROMFD) {
+		if (is_digit(wordtext[0]))
+			n->ndup.dupfd = digit_val(wordtext[0]);
+		else if (wordtext[0] == '-')
+			n->ndup.dupfd = -1;
+		else
+			goto bad;
+		if (wordtext[1] != '\0') {
+bad:
+			synerror("Bad fd number");
+		}
+	} else {
+		n->nfile.fname = (union node *)stalloc(sizeof (struct narg));
+		n = n->nfile.fname;
+		n->type = NARG;
+		n->narg.next = NULL;
+		n->narg.text = wordtext;
+		n->narg.backquote = backquotelist;
+	}
+}
+
+
+/*
+ * Input any here documents.
+ */
+
+STATIC void
+parseheredoc() {
+	struct heredoc *here;
+	union node *n;
+
+	while (heredoclist) {
+		here = heredoclist;
+		heredoclist = here->next;
+		if (needprompt) {
+			putprompt(ps2val());
+			needprompt = 0;
+		}
+		readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
+				here->eofmark, here->striptabs);
+		n = (union node *)stalloc(sizeof (struct narg));
+		n->narg.type = NARG;
+		n->narg.next = NULL;
+		n->narg.text = wordtext;
+		n->narg.backquote = backquotelist;
+		here->here->nhere.doc = n;
+	}
+}
+
+STATIC int
+peektoken() {
+	int t;
+
+	t = readtoken();
+	tokpushback++;
+	return (t);
+}
+
+STATIC int xxreadtoken();
+
+STATIC int
+readtoken() {
+	int t;
+#if DEBUG
+	int alreadyseen = tokpushback;
+#endif
+	
+	t = xxreadtoken();
+
+	if (checkkwd) {
+		/*
+		 * eat newlines
+		 */
+		if (checkkwd == 2) {
+			checkkwd = 0;
+			while (t == TNL) {
+				parseheredoc();
+				t = xxreadtoken();
+			}
+		} else
+			checkkwd = 0;
+		/*
+		 * check for keywords
+		 */
+		if (t == TWORD && !quoteflag) {
+			register char *const *pp;
+
+			for (pp = parsekwd; *pp; pp++) {
+				if (**pp == *wordtext && equal(*pp, wordtext)) {
+					lasttoken = t = pp - parsekwd + KWDOFFSET;
+					TRACE(("keyword %s recognized\n", tokname[t]));
+					break;
+				}
+			}
+		}
+	}
+#if DEBUG
+	if (!alreadyseen)
+	    TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
+	else
+	    TRACE(("reread token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
+#endif
+	return (t);
+}
+
+
+/*
+ * Read the next input token.
+ * If the token is a word, we set backquotelist to the list of cmds in
+ *	backquotes.  We set quoteflag to true if any part of the word was
+ *	quoted.
+ * If the token is TREDIR, then we set redirnode to a structure containing
+ *	the redirection.
+ * In all cases, the variable startlinno is set to the number of the line
+ *	on which the token starts.
+ *
+ * [Change comment:  here documents and internal procedures]
+ * [Readtoken shouldn't have any arguments.  Perhaps we should make the
+ *  word parsing code into a separate routine.  In this case, readtoken
+ *  doesn't need to have any internal procedures, but parseword does.
+ *  We could also make parseoperator in essence the main routine, and
+ *  have parseword (readtoken1?) handle both words and redirection.]
+ */
+
+#define RETURN(token)	return lasttoken = token
+
+STATIC int
+xxreadtoken() {
+	register c;
+
+	if (tokpushback) {
+		tokpushback = 0;
+		return lasttoken;
+	}
+	if (needprompt) {
+		putprompt(ps2val());
+		needprompt = 0;
+	}
+	startlinno = plinno;
+	for (;;) {	/* until token or start of word found */
+		c = pgetc_macro();
+		if (c == ' ' || c == '\t')
+			continue;		/* quick check for white space first */
+		switch (c) {
+		case ' ': case '\t':
+			continue;
+		case '#':
+			while ((c = pgetc()) != '\n' && c != PEOF);
+			pungetc();
+			continue;
+		case '\\':
+			if (pgetc() == '\n') {
+				startlinno = ++plinno;
+				if (doprompt)
+					putprompt(ps2val());
+				continue;
+			}
+			pungetc();
+			goto breakloop;
+		case '\n':
+			plinno++;
+			needprompt = doprompt;
+			RETURN(TNL);
+		case PEOF:
+			RETURN(TEOF);
+		case '&':
+			if (pgetc() == '&')
+				RETURN(TAND);
+			pungetc();
+			RETURN(TBACKGND);
+		case '|':
+			if (pgetc() == '|')
+				RETURN(TOR);
+			pungetc();
+			RETURN(TPIPE);
+		case ';':
+			if (pgetc() == ';')
+				RETURN(TENDCASE);
+			pungetc();
+			RETURN(TSEMI);
+		case '(':
+			RETURN(TLP);
+		case ')':
+			RETURN(TRP);
+		default:
+			goto breakloop;
+		}
+	}
+breakloop:
+	return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
+#undef RETURN
+}
+
+
+
+/*
+ * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
+ * is not NULL, read a here document.  In the latter case, eofmark is the
+ * word which marks the end of the document and striptabs is true if
+ * leading tabs should be stripped from the document.  The argument firstc
+ * is the first character of the input token or document.
+ *
+ * Because C does not have internal subroutines, I have simulated them
+ * using goto's to implement the subroutine linkage.  The following macros
+ * will run code that appears at the end of readtoken1.
+ */
+
+#define CHECKEND()	{goto checkend; checkend_return:;}
+#define PARSEREDIR()	{goto parseredir; parseredir_return:;}
+#define PARSESUB()	{goto parsesub; parsesub_return:;}
+#define PARSEBACKQOLD()	{oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
+#define PARSEBACKQNEW()	{oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
+
+STATIC int
+readtoken1(firstc, syntax, eofmark, striptabs)
+	int firstc;
+	char const *syntax;
+	char *eofmark;
+	int striptabs;
+	{
+	register c = firstc;
+	register char *out;
+	int len;
+	char line[EOFMARKLEN + 1];
+	struct nodelist *bqlist;
+	int quotef;
+	int dblquote;
+	int varnest;
+	int oldstyle;
+
+	startlinno = plinno;
+	dblquote = 0;
+	if (syntax == DQSYNTAX)
+		dblquote = 1;
+	quotef = 0;
+	bqlist = NULL;
+	varnest = 0;
+	STARTSTACKSTR(out);
+	loop: {	/* for each line, until end of word */
+#if ATTY
+		if (c == '\034' && doprompt
+		 && attyset() && ! equal(termval(), "emacs")) {
+			attyline();
+			if (syntax == BASESYNTAX)
+				return readtoken();
+			c = pgetc();
+			goto loop;
+		}
+#endif
+		CHECKEND();	/* set c to PEOF if at end of here document */
+		for (;;) {	/* until end of line or end of word */
+			CHECKSTRSPACE(3, out);	/* permit 3 calls to USTPUTC */
+			switch(syntax[c]) {
+			case CNL:	/* '\n' */
+				if (syntax == BASESYNTAX)
+					goto endword;	/* exit outer loop */
+				USTPUTC(c, out);
+				plinno++;
+				if (doprompt) {
+					putprompt(ps2val());
+				}
+				c = pgetc();
+				goto loop;		/* continue outer loop */
+			case CWORD:
+				USTPUTC(c, out);
+				break;
+			case CCTL:
+				if (eofmark == NULL || dblquote)
+					USTPUTC(CTLESC, out);
+				USTPUTC(c, out);
+				break;
+			case CBACK:	/* backslash */
+				c = pgetc();
+				if (c == PEOF) {
+					USTPUTC('\\', out);
+					pungetc();
+				} else if (c == '\n') {
+					if (doprompt)
+						putprompt(ps2val());
+				} else {
+					if (dblquote && c != '\\' && c != '`' && c != '$'
+							 && (c != '"' || eofmark != NULL))
+						USTPUTC('\\', out);
+					if (SQSYNTAX[c] == CCTL)
+						USTPUTC(CTLESC, out);
+					USTPUTC(c, out);
+					quotef++;
+				}
+				break;
+			case CSQUOTE:
+				syntax = SQSYNTAX;
+				break;
+			case CDQUOTE:
+				syntax = DQSYNTAX;
+				dblquote = 1;
+				break;
+			case CENDQUOTE:
+				if (eofmark) {
+					USTPUTC(c, out);
+				} else {
+					syntax = BASESYNTAX;
+					quotef++;
+					dblquote = 0;
+				}
+				break;
+			case CVAR:	/* '$' */
+				PARSESUB();		/* parse substitution */
+				break;
+			case CENDVAR:	/* '}' */
+				if (varnest > 0) {
+					varnest--;
+					USTPUTC(CTLENDVAR, out);
+				} else {
+					USTPUTC(c, out);
+				}
+				break;
+			case CBQUOTE:	/* '`' */
+				PARSEBACKQOLD();
+				break;
+			case CEOF:
+				goto endword;		/* exit outer loop */
+			default:
+				if (varnest == 0)
+					goto endword;	/* exit outer loop */
+				USTPUTC(c, out);
+			}
+			c = pgetc_macro();
+		}
+	}
+endword:
+	if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
+		synerror("Unterminated quoted string");
+	if (varnest != 0) {
+		startlinno = plinno;
+		synerror("Missing '}'");
+	}
+	USTPUTC('\0', out);
+	len = out - stackblock();
+	out = stackblock();
+	if (eofmark == NULL) {
+		if ((c == '>' || c == '<')
+		 && quotef == 0
+		 && len <= 2
+		 && (*out == '\0' || is_digit(*out))) {
+			PARSEREDIR();
+			return lasttoken = TREDIR;
+		} else {
+			pungetc();
+		}
+	}
+	quoteflag = quotef;
+	backquotelist = bqlist;
+	grabstackblock(len);
+	wordtext = out;
+	return lasttoken = TWORD;
+/* end of readtoken routine */
+
+
+
+/*
+ * Check to see whether we are at the end of the here document.  When this
+ * is called, c is set to the first character of the next input line.  If
+ * we are at the end of the here document, this routine sets the c to PEOF.
+ */
+
+checkend: {
+	if (eofmark) {
+		if (striptabs) {
+			while (c == '\t')
+				c = pgetc();
+		}
+		if (c == *eofmark) {
+			if (pfgets(line, sizeof line) != NULL) {
+				register char *p, *q;
+
+				p = line;
+				for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
+				if (*p == '\n' && *q == '\0') {
+					c = PEOF;
+					plinno++;
+					needprompt = doprompt;
+				} else {
+					ppushback(line, strlen(line));
+				}
+			}
+		}
+	}
+	goto checkend_return;
+}
+
+
+/*
+ * Parse a redirection operator.  The variable "out" points to a string
+ * specifying the fd to be redirected.  The variable "c" contains the
+ * first character of the redirection operator.
+ */
+
+parseredir: {
+	char fd = *out;
+	union node *np;
+
+	np = (union node *)stalloc(sizeof (struct nfile));
+	if (c == '>') {
+		np->nfile.fd = 1;
+		c = pgetc();
+		if (c == '>')
+			np->type = NAPPEND;
+		else if (c == '&')
+			np->type = NTOFD;
+		else {
+			np->type = NTO;
+			pungetc();
+		}
+	} else {	/* c == '<' */
+		np->nfile.fd = 0;
+		c = pgetc();
+		if (c == '<') {
+			if (sizeof (struct nfile) != sizeof (struct nhere)) {
+				np = (union node *)stalloc(sizeof (struct nhere));
+				np->nfile.fd = 0;
+			}
+			np->type = NHERE;
+			heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
+			heredoc->here = np;
+			if ((c = pgetc()) == '-') {
+				heredoc->striptabs = 1;
+			} else {
+				heredoc->striptabs = 0;
+				pungetc();
+			}
+		} else if (c == '&')
+			np->type = NFROMFD;
+		else {
+			np->type = NFROM;
+			pungetc();
+		}
+	}
+	if (fd != '\0')
+		np->nfile.fd = digit_val(fd);
+	redirnode = np;
+	goto parseredir_return;
+}
+
+
+/*
+ * Parse a substitution.  At this point, we have read the dollar sign
+ * and nothing else.
+ */
+
+parsesub: {
+	int subtype;
+	int typeloc;
+	int flags;
+	char *p;
+#ifndef GDB_HACK
+	static const char types[] = "}-+?=";
+#endif
+
+	c = pgetc();
+	if (c != '(' && c != '{' && !is_name(c) && !is_special(c)) {
+		USTPUTC('$', out);
+		pungetc();
+	} else if (c == '(') {	/* $(command) */
+		PARSEBACKQNEW();
+	} else {
+		USTPUTC(CTLVAR, out);
+		typeloc = out - stackblock();
+		USTPUTC(VSNORMAL, out);
+		subtype = VSNORMAL;
+		if (c == '{') {
+			c = pgetc();
+			subtype = 0;
+		}
+		if (is_name(c)) {
+			do {
+				STPUTC(c, out);
+				c = pgetc();
+			} while (is_in_name(c));
+		} else {
+			if (! is_special(c))
+badsub:				synerror("Bad substitution");
+			USTPUTC(c, out);
+			c = pgetc();
+		}
+		STPUTC('=', out);
+		flags = 0;
+		if (subtype == 0) {
+			if (c == ':') {
+				flags = VSNUL;
+				c = pgetc();
+			}
+			p = strchr(types, c);
+			if (p == NULL)
+				goto badsub;
+			subtype = p - types + VSNORMAL;
+		} else {
+			pungetc();
+		}
+		if (dblquote)
+			flags |= VSQUOTE;
+		*(stackblock() + typeloc) = subtype | flags;
+		if (subtype != VSNORMAL)
+			varnest++;
+	}
+	goto parsesub_return;
+}
+
+
+/*
+ * Called to parse command substitutions.  Newstyle is set if the command
+ * is enclosed inside $(...); nlpp is a pointer to the head of the linked
+ * list of commands (passed by reference), and savelen is the number of
+ * characters on the top of the stack which must be preserved.
+ */
+
+parsebackq: {
+	struct nodelist **nlpp;
+	int savepbq;
+	union node *n;
+	char *volatile str;
+	struct jmploc jmploc;
+	struct jmploc *volatile savehandler;
+	int savelen;
+	int savedoprompt;
+
+	savepbq = parsebackquote;
+	if (setjmp(jmploc.loc)) {
+		if (str)
+			ckfree(str);
+		parsebackquote = 0;
+		handler = savehandler;
+		longjmp(handler->loc, 1);
+	}
+	INTOFF;
+	str = NULL;
+	savelen = out - stackblock();
+	if (savelen > 0) {
+		str = ckmalloc(savelen);
+		bcopy(stackblock(), str, savelen);
+	}
+	savehandler = handler;
+	handler = &jmploc;
+	INTON;
+	if (oldstyle) {
+		/* We must read until the closing backquote, giving special
+		   treatment to some slashes, and then push the string and
+		   reread it as input, interpreting it normally.  */
+		register char *out;
+		register c;
+		int savelen;
+		char *str;
+
+		STARTSTACKSTR(out);
+		while ((c = pgetc ()) != '`') {
+			if (c == '\\') {
+				c = pgetc ();
+				if (c != '\\' && c != '`' && c != '$'
+				    && (!dblquote || c != '"'))
+					STPUTC('\\', out);
+			}
+			if (c == '\n') {
+				plinno++;
+				if (doprompt)
+					putprompt(ps2val());
+			}
+			STPUTC(c, out);
+		}
+		STPUTC('\0', out);
+		savelen = out - stackblock();
+		if (savelen > 0) {
+			str = ckmalloc(savelen);
+			bcopy(stackblock(), str, savelen);
+		}
+		setinputstring(str, 1);
+		savedoprompt = doprompt;
+		doprompt = 0;	/* no prompts while rereading string */
+	}
+	nlpp = &bqlist;
+	while (*nlpp)
+		nlpp = &(*nlpp)->next;
+	*nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+	(*nlpp)->next = NULL;
+	parsebackquote = oldstyle;
+	n = list(0);
+	if (!oldstyle && (readtoken() != TRP))
+		synexpect(TRP);
+	(*nlpp)->n = n;
+	/* Start reading from old file again.  */
+	if (oldstyle) {
+		popfile();
+		doprompt = savedoprompt;
+	}
+	while (stackblocksize() <= savelen)
+		growstackblock();
+	STARTSTACKSTR(out);
+	if (str) {
+		bcopy(str, out, savelen);
+		STADJUST(savelen, out);
+		INTOFF;
+		ckfree(str);
+		str = NULL;
+		INTON;
+	}
+	parsebackquote = savepbq;
+	handler = savehandler;
+	USTPUTC(CTLBACKQ + dblquote, out);
+	if (oldstyle)
+		goto parsebackq_oldreturn;
+	else
+		goto parsebackq_newreturn;
+}
+
+} /* end of readtoken */
+
+
+
+#ifdef mkinit
+RESET {
+	tokpushback = 0;
+}
+#endif
+
+
+#if READLINE
+/*
+ * Remember a prompt for use with readline if input and output is a terminal.
+ */
+
+STATIC void
+putprompt(s)
+	char *s;
+	{
+	if (editable) {
+		r_use_prompt = s;
+	} else {
+		out2str(s);
+	}
+}
+#endif
+
+#if ATTY
+/*
+ * Called to process a command generated by atty.  We execute the line,
+ * and catch any errors that occur so they don't propagate outside of
+ * this routine.
+ */
+
+STATIC void
+attyline() {
+	char line[256];
+	struct stackmark smark;
+	struct jmploc jmploc;
+	struct jmploc *volatile savehandler;
+
+	if (pfgets(line, sizeof line) == NULL)
+		return;				/* "can't happen" */
+	if (setjmp(jmploc.loc)) {
+		if (exception == EXERROR)
+			out2str("\033]D\n");
+		handler = savehandler;
+		longjmp(handler->loc, 1);
+	}
+	savehandler = handler;
+	handler = &jmploc;
+	setstackmark(&smark);
+	evalstring(line);
+	popstackmark(&smark);
+	handler = savehandler;
+	doprompt = 1;
+}
+
+
+/*
+ * Output a prompt for atty.  We output the prompt as part of the
+ * appropriate escape sequence.  
+ */
+
+STATIC void
+putprompt(s)
+	char *s;
+	{
+	register char *p;
+
+	if (attyset() && ! equal(termval(), "emacs")) {
+		if (strchr(s, '\7'))
+			out2c('\7');
+		out2str("\033]P1;");
+		for (p = s ; *p ; p++) {
+			if ((unsigned)(*p - ' ') <= '~' - ' ')
+				out2c(*p);
+		}
+		out2c('\n');
+	} else {
+		out2str(s);
+	}
+}
+#endif
+
+
+
+/*
+ * Returns true if the text contains nothing to expand (no dollar signs
+ * or backquotes).
+ */
+
+STATIC int
+noexpand(text)
+	char *text;
+	{
+	register char *p;
+	register char c;
+
+	p = text;
+	while ((c = *p++) != '\0') {
+		if (c == CTLESC)
+			p++;
+		else if (BASESYNTAX[c] == CCTL)
+			return 0;
+	}
+	return 1;
+}
+
+
+/*
+ * Return true if the argument is a legal variable name (a letter or
+ * underscore followed by zero or more letters, underscores, and digits).
+ */
+
+int
+goodname(name)
+	char *name;
+	{
+	register char *p;
+
+	p = name;
+	if (! is_name(*p))
+		return 0;
+	while (*++p) {
+		if (! is_in_name(*p))
+			return 0;
+	}
+	return 1;
+}
+
+
+/*
+ * Called when an unexpected token is read during the parse.  The argument
+ * is the token that is expected, or -1 if more than one type of token can
+ * occur at this point.
+ */
+
+STATIC void
+synexpect(token) {
+	char msg[64];
+
+	if (token >= 0) {
+		fmtstr(msg, 64, "%s unexpected (expecting %s)",
+			tokname[lasttoken], tokname[token]);
+	} else {
+		fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]);
+	}
+	synerror(msg);
+}
+
+
+STATIC void
+synerror(msg)
+	char *msg;
+	{
+	if (commandname)
+		outfmt(&errout, "%s: %d: ", commandname, startlinno);
+	outfmt(&errout, "Syntax error: %s\n", msg);
+	error((char *)NULL);
+}
Index: /trunk/minix/commands/ash/parser.h
===================================================================
--- /trunk/minix/commands/ash/parser.h	(revision 9)
+++ /trunk/minix/commands/ash/parser.h	(revision 9)
@@ -0,0 +1,74 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)parser.h	5.1 (Berkeley) 3/7/91
+ */
+
+/* control characters in argument strings */
+#define CTLESC '\201'
+#define CTLVAR '\202'
+#define CTLENDVAR '\203'
+#define CTLBACKQ '\204'
+#define CTLQUOTE 01		/* ored with CTLBACKQ code if in quotes */
+
+/* variable substitution byte (follows CTLVAR) */
+#define VSTYPE 07		/* type of variable substitution */
+#define VSNUL 040		/* colon--treat the empty string as unset */
+#define VSQUOTE 0100		/* inside double quotes--suppress splitting */
+
+/* values of VSTYPE field */
+#define VSNORMAL 1		/* normal variable:  $var or ${var} */
+#define VSMINUS 2		/* ${var-text} */
+#define VSPLUS 3		/* ${var+text} */
+#define VSQUESTION 4		/* ${var?message} */
+#define VSASSIGN 5		/* ${var=text} */
+
+
+/*
+ * NEOF is returned by parsecmd when it encounters an end of file.  It
+ * must be distinct from NULL, so we use the address of a variable that
+ * happens to be handy.
+ */
+extern int tokpushback;
+#define NEOF ((union node *)&tokpushback)
+
+
+#ifdef __STDC__
+union node *parsecmd(int);
+int goodname(char *);
+#else
+union node *parsecmd();
+int goodname();
+#endif
Index: /trunk/minix/commands/ash/redir.c
===================================================================
--- /trunk/minix/commands/ash/redir.c	(revision 9)
+++ /trunk/minix/commands/ash/redir.c	(revision 9)
@@ -0,0 +1,370 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)redir.c	5.1 (Berkeley) 3/7/91";
+#endif /* not lint */
+
+/*
+ * Code for dealing with input/output redirection.
+ */
+
+#include "shell.h"
+#include "nodes.h"
+#include "jobs.h"
+#include "expand.h"
+#include "redir.h"
+#include "eval.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include <sys/types.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+
+
+#define EMPTY -2		/* marks an unused slot in redirtab */
+#define PIPESIZE 4096		/* amount of buffering in a pipe */
+
+
+MKINIT
+struct redirtab {
+	struct redirtab *next;
+	short renamed[10];
+};
+
+
+MKINIT struct redirtab *redirlist;
+
+/* We keep track of whether or not fd0 has been redirected.  This is for
+   background commands, where we want to redirect fd0 to /dev/null only
+   if it hasn't already been redirected.  */
+int fd0_redirected = 0;
+
+#ifdef __STDC__
+STATIC void openredirect(union node *, char *);
+STATIC int openhere(union node *);
+#else
+STATIC void openredirect();
+STATIC int openhere();
+#endif
+
+
+
+/*
+ * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
+ * old file descriptors are stashed away so that the redirection can be
+ * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
+ * standard output, and the standard error if it becomes a duplicate of
+ * stdout, is saved in memory.
+ */
+
+void
+redirect(redir, flags)
+	union node *redir;
+	int flags;
+	{
+	union node *n;
+	struct redirtab *sv;
+	int i;
+	int fd;
+	char memory[10];		/* file descriptors to write to memory */
+
+	for (i = 10 ; --i >= 0 ; )
+		memory[i] = 0;
+	memory[1] = flags & REDIR_BACKQ;
+	if (flags & REDIR_PUSH) {
+		sv = ckmalloc(sizeof (struct redirtab));
+		for (i = 0 ; i < 10 ; i++)
+			sv->renamed[i] = EMPTY;
+		sv->next = redirlist;
+		redirlist = sv;
+	}
+	for (n = redir ; n ; n = n->nfile.next) {
+		fd = n->nfile.fd;
+		if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
+			INTOFF;
+			if ((i = copyfd(fd, 10)) != EMPTY) {
+				sv->renamed[fd] = i;
+				close(fd);
+			}
+			INTON;
+			if (i == EMPTY)
+				error("Out of file descriptors");
+		} else {
+			close(fd);
+		}
+		if (fd == 0)
+			fd0_redirected++;
+		openredirect(n, memory);
+	}
+	if (memory[1])
+		out1 = &memout;
+	if (memory[2])
+		out2 = &memout;
+}
+
+
+STATIC void
+openredirect(redir, memory)
+	union node *redir;
+	char memory[10];
+	{
+	int fd = redir->nfile.fd;
+	char *fname;
+	int f;
+
+	/* Assume redirection succeeds. */
+	exitstatus = 0;
+
+	/*
+	 * We suppress interrupts so that we won't leave open file
+	 * descriptors around.  This may not be such a good idea because
+	 * an open of a device or a fifo can block indefinitely.
+	 */
+	INTOFF;
+	memory[fd] = 0;
+	switch (redir->nfile.type) {
+	case NFROM:
+		fname = redir->nfile.expfname;
+		if ((f = open(fname, O_RDONLY)) < 0)
+			error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
+movefd:
+		if (f != fd) {
+			copyfd(f, fd);
+			close(f);
+		}
+		break;
+	case NTO:
+		fname = redir->nfile.expfname;
+#ifdef O_CREAT
+		if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
+			error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
+#else
+		if ((f = creat(fname, 0666)) < 0)
+			error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
+#endif
+		goto movefd;
+	case NAPPEND:
+		fname = redir->nfile.expfname;
+#ifdef O_APPEND
+		if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
+			error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
+#else
+		if ((f = open(fname, O_WRONLY)) < 0
+		 && (f = creat(fname, 0666)) < 0)
+			error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
+		lseek(f, 0L, 2);
+#endif
+		goto movefd;
+	case NTOFD:
+	case NFROMFD:
+		if (redir->ndup.dupfd >= 0) {	/* if not ">&-" */
+			if (memory[redir->ndup.dupfd])
+				memory[fd] = 1;
+			else
+				copyfd(redir->ndup.dupfd, fd);
+		}
+		break;
+	case NHERE:
+	case NXHERE:
+		f = openhere(redir);
+		goto movefd;
+	default:
+		abort();
+	}
+	INTON;
+}
+
+
+/*
+ * Handle here documents.  Normally we fork off a process to write the
+ * data to a pipe.  If the document is short, we can stuff the data in
+ * the pipe without forking.
+ */
+
+STATIC int
+openhere(redir)
+	union node *redir;
+	{
+	int pip[2];
+	int len;
+
+	if (pipe(pip) < 0)
+		error("Pipe call failed");
+	if (redir->type == NHERE) {
+		len = strlen(redir->nhere.doc->narg.text);
+		if (len <= PIPESIZE) {
+			xwrite(pip[1], redir->nhere.doc->narg.text, len);
+			goto out;
+		}
+	}
+	if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
+		close(pip[0]);
+		signal(SIGINT, SIG_IGN);
+		signal(SIGQUIT, SIG_IGN);
+		signal(SIGHUP, SIG_IGN);
+#ifdef SIGTSTP
+		signal(SIGTSTP, SIG_IGN);
+#endif
+		signal(SIGPIPE, SIG_DFL);
+		if (redir->type == NHERE)
+			xwrite(pip[1], redir->nhere.doc->narg.text, len);
+		else
+			expandhere(redir->nhere.doc, pip[1]);
+		_exit(0);
+	}
+out:
+	close(pip[1]);
+	return pip[0];
+}
+
+
+
+/*
+ * Undo the effects of the last redirection.
+ */
+
+void
+popredir() {
+	register struct redirtab *rp = redirlist;
+	int i;
+
+	for (i = 0 ; i < 10 ; i++) {
+		if (rp->renamed[i] != EMPTY) {
+			if (i == 0)
+				fd0_redirected--;
+			close(i);
+			if (rp->renamed[i] >= 0) {
+				copyfd(rp->renamed[i], i);
+				close(rp->renamed[i]);
+			}
+		}
+	}
+	INTOFF;
+	redirlist = rp->next;
+	ckfree(rp);
+	INTON;
+}
+
+
+
+/*
+ * Undo all redirections.  Called on error or interrupt.
+ */
+
+#ifdef mkinit
+
+INCLUDE "redir.h"
+
+RESET {
+	while (redirlist)
+		popredir();
+}
+
+SHELLPROC {
+	clearredir();
+}
+
+#endif
+
+
+/*
+ * Discard all saved file descriptors.
+ */
+
+void
+clearredir() {
+	register struct redirtab *rp;
+	int i;
+
+	for (rp = redirlist ; rp ; rp = rp->next) {
+		for (i = 0 ; i < 10 ; i++) {
+			if (rp->renamed[i] >= 0) {
+				close(rp->renamed[i]);
+			}
+			rp->renamed[i] = EMPTY;
+		}
+	}
+}
+
+
+
+/*
+ * Copy a file descriptor, like the F_DUPFD option of fcntl.  Returns -1
+ * if the source file descriptor is closed, EMPTY if there are no unused
+ * file descriptors left.
+ */
+
+int
+copyfd(from, to) {
+#ifdef F_DUPFD
+	int newfd;
+
+	newfd = fcntl(from, F_DUPFD, to);
+	if (newfd < 0 && errno == EMFILE)
+		return EMPTY;
+	return newfd;
+#else
+	char toclose[32];
+	int i;
+	int newfd;
+	int e;
+
+	for (i = 0 ; i < to ; i++)
+		toclose[i] = 0;
+	INTOFF;
+	while ((newfd = dup(from)) >= 0 && newfd < to)
+		toclose[newfd] = 1;
+	e = errno;
+	for (i = 0 ; i < to ; i++) {
+		if (toclose[i])
+			close(i);
+	}
+	INTON;
+	if (newfd < 0 && e == EMFILE)
+		return EMPTY;
+	return newfd;
+#endif
+}
+
+/* Return true if fd 0 has already been redirected at least once.  */
+int
+fd0_redirected_p () {
+	return fd0_redirected != 0;
+}
Index: /trunk/minix/commands/ash/redir.h
===================================================================
--- /trunk/minix/commands/ash/redir.h	(revision 9)
+++ /trunk/minix/commands/ash/redir.h	(revision 9)
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)redir.h	5.1 (Berkeley) 3/7/91
+ */
+
+/* flags passed to redirect */
+#define REDIR_PUSH 01		/* save previous values of file descriptors */
+#define REDIR_BACKQ 02		/* save the command output in memory */
+
+#ifdef __STDC__
+union node;
+void redirect(union node *, int);
+void popredir(void);
+void clearredir(void);
+int copyfd(int, int);
+int fd0_redirected_p(void);
+#else
+void redirect();
+void popredir();
+void clearredir();
+int copyfd();
+int fd0_redirected_p();
+#endif
Index: /trunk/minix/commands/ash/shell.h
===================================================================
--- /trunk/minix/commands/ash/shell.h	(revision 9)
+++ /trunk/minix/commands/ash/shell.h	(revision 9)
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)shell.h	5.4 (Berkeley) 4/12/91
+ */
+
+/*
+ * The follow should be set to reflect the type of system you have:
+ *	JOBS -> 1 if you have Berkeley job control, 0 otherwise.
+ *	SYMLINKS -> 1 if your system includes symbolic links, 0 otherwise.
+ *	DIRENT -> 1 if your system has the SVR3 directory(3X) routines.
+ *	UDIR -> 1 if you want the shell to simulate the /u directory.
+ *	TILDE -> 1 if you want the shell to expand ~logname.
+ *	USEGETPW -> 1 if getpwnam() must be used to look up a name.
+ *	ATTY -> 1 to include code for atty(1).
+ *	SHORTNAMES -> 1 if your linker cannot handle long names.
+ *	READLINE -> 1 if line editing by readline() should be enabled.
+ *	define BSD if you are running 4.2 BSD or later.
+ *	define SYSV if you are running under System V.
+ *	define DEBUG=1 to compile in debugging (set global "debug" to turn on)
+ *	define DEBUG=2 to compile in and turn on debugging.
+ *
+ * When debugging is on, debugging info will be written to $HOME/trace and
+ * a quit signal will generate a core dump.
+ */
+
+
+#define JOBS	  0
+
+/* Set SYMLINKS to 0 by request of Giovanni Falzoni, who wrote the
+ * symlink patches for Minix; email to minix-devel-l of thu 3 nov.
+ */
+
+#if 0
+#define SYMLINKS  defined(S_ISLNK)
+#else
+#define SYMLINKS  0
+#endif
+
+#define DIRENT	  1
+#define UDIR	  0
+#define TILDE	  1
+#define USEGETPW  0
+#define ATTY	  0
+#define READLINE  1
+#define HASHBANG  0
+/* #define BSD */
+#define POSIX	  1
+#define DEBUG	  0
+
+#ifdef __STDC__
+typedef void *pointer;
+#ifndef NULL
+#define NULL (void *)0
+#endif
+#else /* not __STDC__ */
+typedef char *pointer;
+#ifndef NULL
+#define NULL 0
+#endif
+#endif /*  not __STDC__ */
+#define STATIC	/* empty */
+#define MKINIT	/* empty */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+extern char nullstr[1];		/* null string */
+
+
+#if DEBUG
+#define TRACE(param)	trace param
+#else
+#define TRACE(param)
+#endif
Index: /trunk/minix/commands/ash/show.c
===================================================================
--- /trunk/minix/commands/ash/show.c	(revision 9)
+++ /trunk/minix/commands/ash/show.c	(revision 9)
@@ -0,0 +1,377 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)show.c	5.2 (Berkeley) 4/12/91";
+#endif /* not lint */
+
+#include <stdio.h>
+#include <errno.h>
+#include "shell.h"
+#include "parser.h"
+#include "nodes.h"
+#include "mystring.h"
+
+
+#if DEBUG
+static shtree(), shcmd(), sharg(), indent();
+
+
+showtree(n)
+	union node *n;
+	{
+	trputs("showtree called\n");
+	shtree(n, 1, NULL, stdout);
+}
+
+
+static
+shtree(n, ind, pfx, fp)
+	union node *n;
+	char *pfx;
+	FILE *fp;
+	{
+	struct nodelist *lp;
+	char *s;
+
+	indent(ind, pfx, fp);
+	switch(n->type) {
+	case NSEMI:
+		s = "; ";
+		goto binop;
+	case NAND:
+		s = " && ";
+		goto binop;
+	case NOR:
+		s = " || ";
+binop:
+		shtree(n->nbinary.ch1, ind, NULL, fp);
+	   /*    if (ind < 0) */
+			fputs(s, fp);
+		shtree(n->nbinary.ch2, ind, NULL, fp);
+		break;
+	case NCMD:
+		shcmd(n, fp);
+		if (ind >= 0)
+			putc('\n', fp);
+		break;
+	case NPIPE:
+		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
+			shcmd(lp->n, fp);
+			if (lp->next)
+				fputs(" | ", fp);
+		}
+		if (n->npipe.backgnd)
+			fputs(" &", fp);
+		if (ind >= 0)
+			putc('\n', fp);
+		break;
+	default:
+		fprintf(fp, "<node type %d>", n->type);
+		if (ind >= 0)
+			putc('\n', fp);
+		break;
+	}
+}
+
+
+
+static
+shcmd(cmd, fp)
+	union node *cmd;
+	FILE *fp;
+	{
+	union node *np;
+	int first;
+	char *s;
+	int dftfd;
+
+	first = 1;
+	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
+		if (! first)
+			putchar(' ');
+		sharg(np, fp);
+		first = 0;
+	}
+	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
+		if (! first)
+			putchar(' ');
+		switch (np->nfile.type) {
+			case NTO:	s = ">";  dftfd = 1; break;
+			case NAPPEND:	s = ">>"; dftfd = 1; break;
+			case NTOFD:	s = ">&"; dftfd = 1; break;
+			case NFROM:	s = "<";  dftfd = 0; break;
+			case NFROMFD:	s = "<&"; dftfd = 0; break;
+		}
+		if (np->nfile.fd != dftfd)
+			fprintf(fp, "%d", np->nfile.fd);
+		fputs(s, fp);
+		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
+			fprintf(fp, "%d", np->ndup.dupfd);
+		} else {
+			sharg(np->nfile.fname, fp);
+		}
+		first = 0;
+	}
+}
+
+
+
+static
+sharg(arg, fp)
+	union node *arg;
+	FILE *fp;
+	{
+	char *p;
+	struct nodelist *bqlist;
+	int subtype;
+
+	if (arg->type != NARG) {
+		printf("<node type %d>\n", arg->type);
+		fflush(stdout);
+		abort();
+	}
+	bqlist = arg->narg.backquote;
+	for (p = arg->narg.text ; *p ; p++) {
+		switch (*p) {
+		case CTLESC:
+			putc(*++p, fp);
+			break;
+		case CTLVAR:
+			putc('$', fp);
+			putc('{', fp);
+			subtype = *++p;
+			while (*p != '=')
+				putc(*p++, fp);
+			if (subtype & VSNUL)
+				putc(':', fp);
+			switch (subtype & VSTYPE) {
+			case VSNORMAL:
+				putc('}', fp);
+				break;
+			case VSMINUS:
+				putc('-', fp);
+				break;
+			case VSPLUS:
+				putc('+', fp);
+				break;
+			case VSQUESTION:
+				putc('?', fp);
+				break;
+			case VSASSIGN:
+				putc('=', fp);
+				break;
+			default:
+				printf("<subtype %d>", subtype);
+			}
+			break;
+		case CTLENDVAR:
+		     putc('}', fp);
+		     break;
+		case CTLBACKQ:
+		case CTLBACKQ|CTLQUOTE:
+			putc('$', fp);
+			putc('(', fp);
+			shtree(bqlist->n, -1, NULL, fp);
+			putc(')', fp);
+			break;
+		default:
+			putc(*p, fp);
+			break;
+		}
+	}
+}
+
+
+static
+indent(amount, pfx, fp)
+	char *pfx;
+	FILE *fp;
+	{
+	int i;
+
+	for (i = 0 ; i < amount ; i++) {
+		if (pfx && i == amount - 1)
+			fputs(pfx, fp);
+		putc('\t', fp);
+	}
+}
+#endif
+
+
+
+/*
+ * Debugging stuff.
+ */
+
+
+FILE *tracefile;
+
+#if DEBUG == 2
+int debug = 1;
+#else
+int debug = 0;
+#endif
+
+
+trputc(c) {
+#if DEBUG
+	if (tracefile == NULL)
+		return;
+	putc(c, tracefile);
+	if (c == '\n')
+		fflush(tracefile);
+#endif
+}
+
+
+trace(fmt, a1, a2, a3, a4, a5, a6, a7, a8)
+	char *fmt;
+	{
+#if DEBUG
+	int e = errno;
+	if (tracefile == NULL)
+		return;
+	fprintf(tracefile, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
+	if (strchr(fmt, '\n'))
+		fflush(tracefile);
+	errno = e;
+#endif
+}
+
+
+trputs(s)
+	char *s;
+	{
+#if DEBUG
+	if (tracefile == NULL)
+		return;
+	fputs(s, tracefile);
+	if (strchr(s, '\n'))
+		fflush(tracefile);
+#endif
+}
+
+
+trstring(s)
+	char *s;
+	{
+	register char *p;
+	char c;
+
+#if DEBUG
+	if (tracefile == NULL)
+		return;
+	putc('"', tracefile);
+	for (p = s ; *p ; p++) {
+		switch (*p) {
+		case '\n':  c = 'n';  goto backslash;
+		case '\t':  c = 't';  goto backslash;
+		case '\r':  c = 'r';  goto backslash;
+		case '"':  c = '"';  goto backslash;
+		case '\\':  c = '\\';  goto backslash;
+		case CTLESC:  c = 'e';  goto backslash;
+		case CTLVAR:  c = 'v';  goto backslash;
+		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
+		case CTLBACKQ:  c = 'q';  goto backslash;
+		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
+backslash:	  putc('\\', tracefile);
+			putc(c, tracefile);
+			break;
+		default:
+			if (*p >= ' ' && *p <= '~')
+				putc(*p, tracefile);
+			else {
+				putc('\\', tracefile);
+				putc(*p >> 6 & 03, tracefile);
+				putc(*p >> 3 & 07, tracefile);
+				putc(*p & 07, tracefile);
+			}
+			break;
+		}
+	}
+	putc('"', tracefile);
+#endif
+}
+
+
+trargs(ap)
+	char **ap;
+	{
+#if DEBUG
+	if (tracefile == NULL)
+		return;
+	while (*ap) {
+		trstring(*ap++);
+		if (*ap)
+			putc(' ', tracefile);
+		else
+			putc('\n', tracefile);
+	}
+	fflush(tracefile);
+#endif
+}
+
+
+opentrace() {
+	char s[100];
+	char *p;
+	char *getenv();
+	int flags;
+
+#if DEBUG
+	if (!debug)
+		return;
+	if ((p = getenv("HOME")) == NULL) {
+		if (getuid() == 0)
+			p = "/";
+		else
+			p = "/tmp";
+	}
+	scopy(p, s);
+	strcat(s, "/trace");
+	if ((tracefile = fopen(s, "a")) == NULL) {
+		fprintf(stderr, "Can't open %s\n", s);
+		return;
+	}
+#ifdef O_APPEND
+	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
+		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
+#endif
+	fputs("\nTracing started.\n", tracefile);
+	fflush(tracefile);
+#endif
+}
Index: /trunk/minix/commands/ash/sys/cdefs.h
===================================================================
--- /trunk/minix/commands/ash/sys/cdefs.h	(revision 9)
+++ /trunk/minix/commands/ash/sys/cdefs.h	(revision 9)
@@ -0,0 +1,15 @@
+/*	Replacement for something BSD has in sys/cdefs.h. */
+
+#ifndef _ASH_SYS_CDEFS
+#define _ASH_SYS_CDEFS
+
+#if __STDC__
+#define	__P(params)			params
+#else
+#define	__P(params)			()
+#endif
+
+/*	Probably in sys/types.h. */
+typedef void (*sig_t) __P(( int ));
+
+#endif /* _ASH_SYS_CDEFS */
Index: /trunk/minix/commands/ash/test/malloc.c
===================================================================
--- /trunk/minix/commands/ash/test/malloc.c	(revision 9)
+++ /trunk/minix/commands/ash/test/malloc.c	(revision 9)
@@ -0,0 +1,1298 @@
+
+/**********************************************************/
+/*
+/*		 This was file READ_ME
+/*
+/**********************************************************/
+
+/*
+	PROGRAM
+		malloc(), free(), realloc()
+	AUTHOR
+		Dick Grune, Free University, Amsterdam
+		Modified by Ceriel Jacobs, Free University, Amsterdam,
+		to make it faster
+	VERSION
+		$Header: /cvsup/minix/src/commands/ash/test/malloc.c,v 1.1.1.1 2005/04/21 14:54:10 beng Exp $
+	DESCRIPTION
+	This is an independent rewrite of the malloc/free package; it is
+	fast and efficient.  Free blocks are kept in doubly linked lists,
+	list N holding blocks with sizes between 2**N and 2**(N+1)-1.
+	Consequently neither malloc nor free have to do any searching:
+	the cost of a call of malloc() (or free()) is constant, however
+	many blocks you have got.
+	
+	If you switch on the NON_STANDARD macro (see param.h) every block
+	costs 2 pointers overhead (otherwise it's 4).
+*/
+/*
+	There is an organisational problem here: during devellopment
+	I want the package divided into modules, which implies external
+	names for the communication.  The only external names I want in
+	the finished product are malloc, realloc and free.  This requires
+	some hanky-panky.
+*/
+
+
+/**********************************************************/
+/*
+/*		 This was file size_type.h
+/*
+/**********************************************************/
+
+#if	_EM_WSIZE == _EM_PSIZE
+typedef unsigned int size_type;
+#elif	_EM_LSIZE == _EM_PSIZE
+typedef unsigned long size_type;
+#else
+#error funny pointer size
+#endif
+#include	<stdlib.h>
+#include	<stdio.h>
+
+
+/**********************************************************/
+/*
+/*		 This was file param.h
+/*
+/**********************************************************/
+
+/* $Header: /cvsup/minix/src/commands/ash/test/malloc.c,v 1.1.1.1 2005/04/21 14:54:10 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+
+#	undef	NON_STANDARD	/*	If defined, the contents of a block
+					will NOT be left undisturbed after it
+					is freed, as opposed to what it says
+					in the manual (malloc(2)).
+					Setting this option reduces the memory
+					overhead considerably.  I personally
+					consider the specified behaviour an
+					artefact of the original
+					implementation.
+				*/
+
+#	define	ASSERT		/*	If defined, some inexpensive tests
+					will be made to ensure the
+					correctness of some sensitive data.
+					It often turns an uncontrolled crash
+					into a controlled one.
+				*/
+
+#	define	CHECK		/*	If defined, extensive and expensive
+					tests will be done, inculding a
+					checksum on the mallinks (chunk
+					information blocks).  The resulting
+					information will be printed on a file
+					called mal.out .
+					Additionally a function
+						maldump(n) int n;
+					will be defined, which will dump
+					pertinent info in pseudo-readable
+					form; it aborts afterwards if n != 0.
+				*/
+
+#	undef	EXTERN		/*	If defined, all static names will
+					become extern, which is a help in
+					using adb(1) or prof(1)
+				*/
+
+#	define	STORE		/*	If defined, separate free lists will
+					be kept of chunks with small sizes,
+					to speed things up a little.
+				*/
+
+#	undef SYSTEM		/*	If defined, the system module is used.
+					Otherwise, "sbrk" is called directly.
+				*/
+
+#define	ALIGNMENT	8	
+				/* alignment common to all types */
+#define	LOG_MIN_SIZE	3
+#define	LOG_MAX_SIZE	24
+
+
+/**********************************************************/
+/*
+/*		 This was file impl.h
+/*
+/**********************************************************/
+
+/* $Header: /cvsup/minix/src/commands/ash/test/malloc.c,v 1.1.1.1 2005/04/21 14:54:10 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/*	This file essentially describes how the mallink info block
+	is implemented.
+*/
+
+#define	MIN_SIZE	(1<<LOG_MIN_SIZE)
+#define	MAX_FLIST	(LOG_MAX_SIZE - LOG_MIN_SIZE)
+#if ALIGNMENT != 4 && ALIGNMENT != 8 && ALIGNMENT != 16
+#error ALIGNMENT must be 4, 8 or 16
+#elif ALIGNMENT % _EM_LSIZE
+/* since calloc() does it's initialization in longs */
+#error ALIGNMENT must be a multiple of the long size
+#endif
+#define align(n)	(((n) + (ALIGNMENT - 1)) & ~(ALIGNMENT - 1))
+
+union _inf {
+	union _inf *ptr;
+	size_type ui;
+};
+
+typedef union _inf mallink;
+#define	MAL_NULL	((mallink *)0)
+
+/*	Access macros; only these macros know where to find values.
+	They are also lvalues.
+*/
+#ifndef	NON_STANDARD
+#define	OFF_SET	0
+#else	/* def NON_STANDARD */
+#define	OFF_SET	2
+#endif	/* NON_STANDARD */
+
+#define	_log_prev_of(ml)	((ml)[-1+OFF_SET]).ptr
+#define	_log_next_of(ml)	((ml)[-2+OFF_SET]).ptr
+#define	_phys_prev_of(ml)	((ml)[-3+OFF_SET]).ptr
+#define	_this_size_of(ml)	((ml)[-4+OFF_SET]).ui
+#ifndef	CHECK
+#define	N_WORDS			4
+#else	/* ifdef	CHECK */
+#define	_checksum_of(ml)	((ml)[-5+OFF_SET]).ui
+#define	_print_of(ml)		((ml)[-6+OFF_SET]).ui
+#define	_mark_of(ml)		((ml)[-7+OFF_SET]).ui
+#define	N_WORDS			7
+#endif	/* CHECK */
+
+#define	mallink_size()		(size_t) \
+	align((N_WORDS - OFF_SET) * sizeof (mallink))
+
+#ifdef	CHECK
+#define	set_mark(ml,e)		(_mark_of(ml) = (e))
+#define	mark_of(ml)		(_mark_of(ml))
+
+#define	set_checksum(ml,e)	(_checksum_of(ml) = (e))
+#define	checksum_of(ml)		(_checksum_of(ml))
+#endif	/* CHECK */
+
+#define new_mallink(ml)		( _log_prev_of(ml) = 0, \
+				  _log_next_of(ml) = 0, \
+				  _phys_prev_of(ml) = 0, \
+				  _this_size_of(ml) = 0 )
+
+#define	block_of_mallink(ml)	((void *)ml)
+#define	mallink_of_block(addr)	((mallink *)addr)
+
+#define	public	extern
+#define	publicdata	extern
+#ifndef	EXTERN
+#define	private	static
+#define	privatedata	static
+#else	/* def	EXTERN */
+#define	private	extern
+#define	privatedata
+#endif	/* EXTERN */
+
+#ifdef	ASSERT
+private m_assert(const char *fn, int ln);
+#define	assert(b)		(!(b) ? m_assert(__FILE__, __LINE__) : 0)
+#else	/* ndef	ASSERT */
+#define	assert(b)		0
+#endif	/* ASSERT */
+
+
+/**********************************************************/
+/*
+/*		 This was file check.h
+/*
+/**********************************************************/
+
+/* $Header: /cvsup/minix/src/commands/ash/test/malloc.c,v 1.1.1.1 2005/04/21 14:54:10 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#ifdef	CHECK
+
+private check_mallinks(const char *s), calc_checksum(mallink *ml);
+private check_work_empty(const char *s);
+private started_working_on(mallink *ml), stopped_working_on(mallink *ml);
+
+#else	/* ifndef	CHECK */
+
+#define	maldump(n)		abort()
+#define	check_mallinks(s)	0
+#define	calc_checksum(ml)	0
+#define	started_working_on(ml)	0
+#define	stopped_working_on(ml)	0
+#define	check_work_empty(s)	0
+
+#endif	/* CHECK */
+
+
+/**********************************************************/
+/*
+/*		 This was file log.h
+/*
+/**********************************************************/
+
+/* $Header: /cvsup/minix/src/commands/ash/test/malloc.c,v 1.1.1.1 2005/04/21 14:54:10 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/*	Algorithms to manipulate the doubly-linked lists of free
+	chunks.
+*/
+
+private link_free_chunk(mallink *ml), unlink_free_chunk(mallink *ml);
+private mallink *first_present(int class);
+private mallink *search_free_list(int class, size_t n);
+
+#ifdef STORE
+#define in_store(ml)		((size_type)_phys_prev_of(ml) & STORE_BIT)
+#define set_store(ml, e) \
+	(_phys_prev_of(ml) = (mallink *) \
+		((e) ? (size_type) _phys_prev_of(ml) | STORE_BIT : \
+		       (size_type) _phys_prev_of(ml) & ~STORE_BIT))
+#endif
+#define	set_log_prev(ml,e)	(_log_prev_of(ml) = (e))
+#define	log_prev_of(ml)		(mallink *) (_log_prev_of(ml))
+
+#define	set_log_next(ml,e)	(_log_next_of(ml) = (e))
+#define	log_next_of(ml)		(mallink *) (_log_next_of(ml))
+
+
+
+/**********************************************************/
+/*
+/*		 This was file phys.h
+/*
+/**********************************************************/
+
+/* $Header: /cvsup/minix/src/commands/ash/test/malloc.c,v 1.1.1.1 2005/04/21 14:54:10 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/*	Algorithms to manipulate the doubly-linked list of physical
+	chunks.
+*/
+privatedata mallink *ml_last;
+
+#define FREE_BIT		01
+#ifdef STORE
+#define STORE_BIT		02
+#define BITS			(FREE_BIT|STORE_BIT)
+#else
+#define BITS			(FREE_BIT)
+#endif
+
+#define __bits(ml)		((int)((size_type)_phys_prev_of(ml) & BITS))
+#define	__free_of(ml)		((int)((size_type)_phys_prev_of(ml) & FREE_BIT))
+#define __phys_prev_of(ml)	((mallink *)((size_type)_phys_prev_of(ml) & ~BITS))
+#define prev_size_of(ml)	((char *)(ml) - \
+				 (char *)__phys_prev_of(ml) - \
+				 mallink_size() \
+				)
+#define	set_phys_prev(ml,e) \
+	(_phys_prev_of(ml) = (mallink *) ((char *)e + __bits(ml)))
+
+#ifdef	CHECK
+private Error(const char *fmt, const char *s, mallink *ml);
+#define	phys_prev_of(ml)	(mallink *) \
+	(first_mallink(ml) ? \
+		(char *)Error("phys_prev_of first_mallink %p", "somewhere", ml) : \
+		(char *)__phys_prev_of(ml) \
+	)
+#else	/* ndef	CHECK */
+#define	phys_prev_of(ml)	__phys_prev_of(ml)
+#endif	/* CHECK */
+
+#define	first_mallink(ml)	(int) (__phys_prev_of(ml) == 0)
+#define	last_mallink(ml)	(int) ((ml) == ml_last)
+
+/*	There is an ambiguity in the semantics of phys_next_of: sometimes
+	one wants it to return MAL_NULL if there is no next chunk, at
+	other times one wants the address of the virtual chunk at the
+	end of memory.  The present version returns the address of the
+	(virtual) chunk and relies on the user to test last_mallink(ml)
+	first.
+*/
+#define size_of(ml)		(_this_size_of(ml) - mallink_size())
+#define	set_phys_next(ml,e) \
+	(_this_size_of(ml) = (size_type)((char *)(e) - (char *)(ml)))
+#define	phys_next_of(ml)	(mallink *) ((char *)(ml) + _this_size_of(ml))
+
+#define	set_free(ml,e) \
+	(_phys_prev_of(ml) = (mallink *) \
+		((e) ? (size_type) _phys_prev_of(ml) | FREE_BIT : \
+		       (size_type) _phys_prev_of(ml) & ~FREE_BIT))
+#define	free_of(ml)		(__free_of(ml))
+
+#define coalesce_forw(ml,nxt)	( unlink_free_chunk(nxt), \
+				  combine_chunks((ml), (nxt)))
+
+#define coalesce_backw(ml,prv)	( unlink_free_chunk(prv), \
+				  stopped_working_on(ml), \
+				  combine_chunks((prv), (ml)), \
+				  started_working_on(prv))
+
+#ifdef	CHECK
+#define	set_print(ml,e)		(_print_of(ml) = (e))
+#define	print_of(ml)		(_print_of(ml))
+#endif	/* CHECK */
+
+private truncate(mallink *ml, size_t size);
+private combine_chunks(register mallink *ml1, register mallink *ml2);
+private mallink *create_chunk(void *p, size_t n);
+
+
+/**********************************************************/
+/*
+/*		 This was file mal.c
+/*
+/**********************************************************/
+
+/* $Header: /cvsup/minix/src/commands/ash/test/malloc.c,v 1.1.1.1 2005/04/21 14:54:10 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#include	<limits.h>
+#include	<stdlib.h>
+
+/*	Malloc space is traversed by N doubly-linked lists of chunks, each
+	containing a couple of house-keeping data addressed as a
+	'mallink' and a piece of useful space, called the block.
+	The N lists are accessed through their starting pointers in
+	free_list[].  Free_list[n] points to a list of chunks between
+	2**(n+LOG_MIN_SIZE) and 2**(n+LOG_MIN_SIZE+1)-1, which means
+	that the smallest chunk is 2**LOG_MIN_SIZE (== MIN_SIZE).
+*/
+
+#ifdef SYSTEM
+#include	<system.h>
+#define SBRK	sys_break
+#else
+#define SBRK	_sbrk
+#define	ILL_BREAK		(void *)(-1)	/* funny failure value */
+#endif
+extern void *SBRK(int incr);
+#ifdef STORE
+#define	MAX_STORE	32
+private do_free(mallink *ml), sell_out(void);
+privatedata mallink *store[MAX_STORE];
+#endif /* STORE */
+
+void *privious_free= (void *)-1;
+void *
+malloc(register size_t n)
+{check_mallinks("malloc entry");{
+	register mallink *ml;
+	register int min_class;
+	void *tmp;
+
+{ static int reent= 0; if (!reent) { reent++; printf("malloc\n"); reent--; } }
+privious_free= (void *)-1;
+	if (n == 0) {
+		return NULL;
+	}
+	if (n < MIN_SIZE) n = align(MIN_SIZE); else n = align(n);
+#ifdef STORE
+	if (n <= MAX_STORE*MIN_SIZE)	{
+		/* look in the store first */
+		register mallink **stp = &store[(n >> LOG_MIN_SIZE) - 1];
+		
+		if (ml = *stp)	{
+			*stp = log_next_of(ml);
+			set_store(ml, 0);
+			check_mallinks("malloc fast exit");
+			assert(! in_store(ml));
+			tmp= block_of_mallink(ml);
+{ static int reent= 0; if (!reent) { reent++; printf("= 0x%x\n", tmp);reent--; } }
+			return tmp;
+		}
+	}
+#endif /* STORE */
+
+	check_work_empty("malloc, entry");
+
+	/*	Acquire a chunk of at least size n if at all possible;
+		Try everything.
+	*/
+	{
+		/*	Inline substitution of "smallest".
+		*/
+		register size_t n1 = n;
+
+		assert(n1 < (1L << LOG_MAX_SIZE));
+		min_class = 0;
+
+		do {
+			n1 >>= 1;
+			min_class++;
+		} while (n1 >= MIN_SIZE);
+	}
+
+	if (min_class >= MAX_FLIST)
+		return NULL;		/* we don't deal in blocks that big */
+	ml = first_present(min_class);
+	if (ml == MAL_NULL)	{
+		/*	Try and extend */
+		register void *p;
+#define	GRABSIZE	4096		/* Power of 2 */
+		register size_t req =
+			((MIN_SIZE<<min_class)+ mallink_size() + GRABSIZE - 1) &
+				~(GRABSIZE-1);
+	
+		if (!ml_last)	{
+			/* first align SBRK() */
+		
+			p = SBRK(0);
+			SBRK((int) (align((size_type) p) - (size_type) p));
+		}
+
+		/* SBRK takes an int; sorry ... */
+		if ((int) req < 0) {
+			p = ILL_BREAK;
+		} else {
+			p = SBRK((int)req);
+		}
+		if (p == ILL_BREAK) {
+			req = n + mallink_size();
+			if ((int) req >= 0) p = SBRK((int)req);
+		}
+		if (p == ILL_BREAK)	{
+			/*	Now this is bad.  The system will not give us
+				more memory.  We can only liquidate our store
+				and hope it helps.
+			*/
+#ifdef STORE
+			sell_out();
+			ml = first_present(min_class);
+			if (ml == MAL_NULL)	{
+#endif /* STORE */
+				/* In this emergency we try to locate a suitable
+				   chunk in the free_list just below the safe
+				   one; some of these chunks may fit the job.
+				*/
+				ml = search_free_list(min_class - 1, n);
+				if (!ml)	/* really out of space */
+					return NULL;
+				started_working_on(ml);
+				unlink_free_chunk(ml);
+				check_mallinks("suitable_chunk, forced");
+#ifdef STORE
+			}
+			else started_working_on(ml);
+#endif /* STORE */
+		}
+		else {
+			assert((size_type)p == align((size_type)p));
+			ml = create_chunk(p, req);
+		}
+		check_mallinks("suitable_chunk, extended");
+	}
+	else started_working_on(ml);
+
+	/* we have a chunk */
+	set_free(ml, 0);
+	calc_checksum(ml);
+	check_mallinks("suitable_chunk, removed");
+	n += mallink_size();
+	if (n + MIN_SIZE <= size_of(ml)) {
+		truncate(ml, n);
+	}
+	stopped_working_on(ml);
+	check_mallinks("malloc exit");
+	check_work_empty("malloc exit");
+#ifdef STORE
+	assert(! in_store(ml));
+#endif
+	tmp= block_of_mallink(ml);
+{ static int reent= 0; if (!reent) { reent++; printf("= 0x%x\n", tmp);reent--; } }
+	return tmp;
+}}
+
+void
+free(void *addr)
+{check_mallinks("free entry");{
+	register mallink *ml;
+
+printf("free 0x%x\n", addr);
+if (privious_free == addr) { fflush(stdout); fflush(stderr); abort(); }
+privious_free= addr;
+	if (addr == NULL) {
+		check_mallinks("free(0) very fast exit");
+		return;
+	}
+
+	ml = mallink_of_block(addr);
+#ifdef STORE
+
+	if (free_of(ml) || in_store(ml))
+		return;				/* user frees free block */
+	if (size_of(ml) <= MAX_STORE*MIN_SIZE)	{
+		/* return to store */
+		mallink **stp = &store[(size_of(ml) >> LOG_MIN_SIZE) - 1];
+		
+		set_log_next(ml, *stp);
+		*stp = ml;
+		set_store(ml, 1);
+		calc_checksum(ml);
+		check_mallinks("free fast exit");
+	}
+	else	{
+		do_free(ml);
+		check_mallinks("free exit");
+	}
+}}
+
+private
+do_free(register mallink *ml)
+{{
+#endif
+
+#ifndef STORE
+	if (free_of(ml))	return;
+#endif /* STORE */
+	started_working_on(ml);
+	set_free(ml, 1);
+	calc_checksum(ml);
+	if (! last_mallink(ml)) {
+		register mallink *next = phys_next_of(ml);
+
+		if (free_of(next)) coalesce_forw(ml, next);
+	}
+
+	if (! first_mallink(ml)) {
+		register mallink *prev = phys_prev_of(ml);
+
+		if (free_of(prev)) {
+			coalesce_backw(ml, prev);
+			ml = prev;
+		}
+	}
+	link_free_chunk(ml);
+	stopped_working_on(ml);
+	check_work_empty("free");
+
+	/* Compile-time checks on param.h */
+	switch (0)	{
+	case MIN_SIZE < OFF_SET * sizeof(mallink):	break;
+	case 1:	break;
+	/*	If this statement does not compile due to duplicate case
+		entry, the minimum size block cannot hold the links for
+		the free blocks.  Either raise LOG_MIN_SIZE or switch
+		off NON_STANDARD.
+	*/
+	}
+	switch(0)	{
+	case sizeof(void *) != sizeof(size_type):	break;
+	case 1:	break;
+	/*	If this statement does not compile due to duplicate
+		case entry, size_type is not defined correctly.
+		Redefine and compile again.
+	*/
+	}
+}}
+
+void *
+realloc(void *addr, register size_t n)
+{check_mallinks("realloc entry");{
+	register mallink *ml, *ph_next;
+	register size_type size;
+
+printf("realloc 0x%x, %d\n", addr, n);
+	if (addr == NULL) {
+		/*	Behave like most Unix realloc's when handed a
+			null-pointer
+		*/
+		return malloc(n);
+	}
+	if (n == 0) {
+		free(addr);
+		return NULL;
+	}
+	ml = mallink_of_block(addr);
+	if (n < MIN_SIZE) n = align(MIN_SIZE); else n = align(n);
+#ifdef STORE
+	if (in_store(ml)) {
+		register mallink *stp = store[(size_of(ml) >> LOG_MIN_SIZE) - 1];
+		mallink *stp1 = NULL;
+		while (ml != stp)	{
+			stp1 = stp;
+			stp = log_next_of(stp);
+		}
+		stp = log_next_of(stp);
+		if (! stp1) store[(size_of(ml) >> LOG_MIN_SIZE) - 1] = stp;
+		else set_log_next(stp1, stp);
+		set_store(ml, 0);
+		calc_checksum(ml);
+	}
+#endif
+	if (free_of(ml)) {
+		unlink_free_chunk(ml);
+		set_free(ml, 0);		/* user reallocs free block */
+	}
+	started_working_on(ml);
+	size = size_of(ml);
+	if (	/* we can simplify the problem by adding the next chunk: */
+		n > size &&
+		!last_mallink(ml) &&
+		(ph_next = phys_next_of(ml), free_of(ph_next)) &&
+		n <= size + mallink_size() + size_of(ph_next)
+	)	{
+		/* add in the physically next chunk */
+		unlink_free_chunk(ph_next);
+		combine_chunks(ml, ph_next);
+		size = size_of(ml);
+		check_mallinks("realloc, combining");
+	}
+	if (n > size)	{		/* this didn't help */
+		void *new;
+		register char *l1, *l2 = addr;
+
+		stopped_working_on(ml);
+		if (!(new = l1 = malloc(n))) return NULL;	/* no way */
+		while (size--) *l1++ = *l2++;
+		free(addr);
+		check_work_empty("mv_realloc");
+#ifdef STORE
+		assert(! in_store(mallink_of_block(new)));
+#endif
+		return new;
+	}
+	/* it helped, but maybe too well */
+	n += mallink_size();
+	if (n + MIN_SIZE <= size_of(ml)) {
+		truncate(ml, n);
+	}
+	stopped_working_on(ml);
+	check_mallinks("realloc exit");
+	check_work_empty("realloc");
+#ifdef STORE
+	assert(! in_store(ml));
+#endif
+	return addr;
+}}
+
+void *
+calloc(size_t nmemb, size_t size)
+{check_mallinks("calloc entry");{
+	long *l1, *l2;
+	size_t n;
+
+printf("calloc\n");
+	if (size == 0) return NULL;
+	if (nmemb == 0) return NULL;
+
+	/* Check for overflow on the multiplication. The peephole-optimizer
+	 * will eliminate all but one of the possibilities.
+	 */
+	if (sizeof(size_t) == sizeof(int)) {
+		if (UINT_MAX / size < nmemb) return NULL;
+	} else if (sizeof(size_t) == sizeof(long)) {
+		if (ULONG_MAX / size < nmemb) return NULL;
+	} else return NULL;		/* can't happen, can it ? */
+
+	n = size * nmemb;
+	if (n < MIN_SIZE) n = align(MIN_SIZE); else n = align(n);
+	if (n >= (1L << LOG_MAX_SIZE)) return NULL;
+	l1 = (long *) malloc(n);
+	l2 = l1 + (n / sizeof(long));	/* n is at least long aligned */
+	while ( l2 != l1 ) *--l2 = 0;
+	check_mallinks("calloc exit");
+	check_work_empty("calloc exit");
+	return (void *)l1;
+}}
+/*	Auxiliary routines */
+
+#ifdef STORE
+private
+sell_out(void)	{
+	/*	Frees all block in store.
+	*/
+	register mallink **stp;
+	
+	for (stp = &store[0]; stp < &store[MAX_STORE]; stp++)	{
+		register mallink *ml = *stp;
+		
+		while (ml)	{
+			*stp = log_next_of(ml);
+			set_store(ml, 0);
+			do_free(ml);
+			ml = *stp;
+		}
+	}
+
+}
+#endif /* STORE */
+
+#ifdef	ASSERT
+private
+m_assert(const char *fn, int ln)
+{
+	char ch;
+	
+	while (*fn)
+		write(2, fn++, 1);
+	write(2, ": malloc assert failed in line ", 31);
+	ch = (ln / 100) + '0'; write(2, &ch, 1); ln %= 100;
+	ch = (ln / 10) + '0'; write(2, &ch, 1); ln %= 10;
+	ch = (ln / 1) + '0'; write(2, &ch, 1);
+	write(2, "\n", 1);
+	maldump(1);
+}
+#endif	/* ASSERT */
+
+
+/**********************************************************/
+/*
+/*		 This was file log.c
+/*
+/**********************************************************/
+
+/* $Header: /cvsup/minix/src/commands/ash/test/malloc.c,v 1.1.1.1 2005/04/21 14:54:10 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+
+/*	Logical manipulations.
+	The chunks are properly chained in the physical chain.
+*/
+
+privatedata mallink *free_list[MAX_FLIST];
+
+private
+link_free_chunk(register mallink *ml)
+{
+	/*	The free chunk ml is inserted in its proper logical
+		chain.
+	*/
+	register mallink **mlp = &free_list[-1];
+	register size_type n = size_of(ml);
+	register mallink *ml1;
+
+	assert(n < (1L << LOG_MAX_SIZE));
+
+	do {
+		n >>= 1;
+		mlp++;
+	}
+	while (n >= MIN_SIZE);
+
+	ml1 = *mlp;
+	set_log_prev(ml, MAL_NULL);
+	set_log_next(ml, ml1);
+	calc_checksum(ml);
+	if (ml1) {
+		/* link backwards
+		*/
+		set_log_prev(ml1, ml);
+		calc_checksum(ml1);
+	}
+	*mlp = ml;
+}
+
+private
+unlink_free_chunk(register mallink *ml)
+{
+	/*	Unlinks a free chunk from (the middle of) the
+		logical chain.
+	*/
+	register mallink *next = log_next_of(ml);
+	register mallink *prev = log_prev_of(ml);
+
+	if (!prev)	{
+		/* it is the first in the chain */
+		register mallink **mlp = &free_list[-1];
+		register size_type n = size_of(ml);
+
+		assert(n < (1L << LOG_MAX_SIZE));
+		do {
+			n >>= 1;
+			mlp++;
+		}
+		while (n >= MIN_SIZE);
+		*mlp = next;
+	}
+	else	{
+		set_log_next(prev, next);
+		calc_checksum(prev);
+	}
+	if (next) {
+		set_log_prev(next, prev);
+		calc_checksum(next);
+	}
+}
+
+private mallink *
+search_free_list(int class, size_t n)
+{
+	/*	Searches the free_list[class] for a chunk of at least size n;
+		since it is searching a slightly undersized list,
+		such a block may not be there.
+	*/
+	register mallink *ml;
+	
+	for (ml = free_list[class]; ml; ml = log_next_of(ml))
+		if (size_of(ml) >= n)
+			return ml;
+	return MAL_NULL;		/* nothing found */
+}
+
+private mallink *
+first_present(int class)
+{
+	/*	Find the index i in free_list[] such that:
+			i >= class && free_list[i] != MAL_NULL.
+		Return MAL_NULL if no such i exists;
+		Otherwise, return the first block of this list, after
+		unlinking it.
+	*/
+	register mallink **mlp, *ml;
+
+	for (mlp = &free_list[class]; mlp < &free_list[MAX_FLIST]; mlp++) {
+		if ((ml = *mlp) != MAL_NULL)	{
+	
+			*mlp = log_next_of(ml);	/* may be MAL_NULL */
+			if (*mlp) {
+				/* unhook backward link
+				*/
+				set_log_prev(*mlp, MAL_NULL);
+				calc_checksum(*mlp);
+			}
+			return ml;
+		}
+	}
+	return MAL_NULL;
+}
+
+#ifdef	CHECK
+private mallink *
+free_list_entry(int i)	{
+	/*	To allow maldump.c access to log.c's private data.
+	*/
+	return free_list[i];
+}
+#endif	/* CHECK */
+
+
+/**********************************************************/
+/*
+/*		 This was file phys.c
+/*
+/**********************************************************/
+
+/* $Header: /cvsup/minix/src/commands/ash/test/malloc.c,v 1.1.1.1 2005/04/21 14:54:10 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#include	<stdlib.h>
+
+/*	Physical manipulations.
+	The blocks concerned are not in any logical chain.
+*/
+
+private mallink *
+create_chunk(void *p, size_t n)
+{
+	/*	The newly acquired piece of memory at p, of length n,
+		is turned into a free chunk, properly chained in the
+		physical chain.
+		The address of the chunk is returned.
+	*/
+	register mallink *ml;
+	/*	All of malloc memory is followed by a virtual chunk, the
+		mallink of which starts mallink_size() bytes past the last
+		byte in memory.
+		Its use is prevented by testing for ml == ml_last first.
+	*/
+	register mallink *last = ml_last;
+	
+	assert(!last || p == (char *)phys_next_of(last) - mallink_size());
+	ml = (mallink *)((char *)p + mallink_size());	/* bump ml */
+	new_mallink(ml);
+	started_working_on(ml);
+	set_free(ml, 1);
+	set_phys_prev(ml, last);
+	ml_last = ml;
+
+	set_phys_next(ml, (mallink *)((char *)ml + n));
+	calc_checksum(ml);
+	assert(size_of(ml) + mallink_size() == n);
+	if (last && free_of(last)) {
+		coalesce_backw(ml, last);
+		ml = last;
+	}
+	check_mallinks("create_chunk, phys. linked");
+	return ml;
+}
+
+private
+truncate(register mallink *ml, size_t size)
+{
+	/*	The chunk ml is truncated.
+		The chunk at ml is split in two.
+		The remaining part is then freed.
+	*/
+	register mallink *new = (mallink *)((char *)ml + size);
+	register mallink *ph_next = phys_next_of(ml);
+
+	new_mallink(new);
+	set_free(new, 1);
+	set_phys_prev(new, ml);
+	set_phys_next(new, ph_next);
+	calc_checksum(new);
+	if (! last_mallink(ml))	{
+		set_phys_prev(ph_next, new);
+		calc_checksum(ph_next);
+		if (free_of(ph_next)) coalesce_forw(new, ph_next);
+	}
+	else	ml_last = new;
+	set_phys_next(ml, new);
+	calc_checksum(ml);
+
+	started_working_on(new);
+	link_free_chunk(new);
+	stopped_working_on(new);
+	check_mallinks("truncate");
+}
+
+private
+combine_chunks(register mallink *ml1, register mallink *ml2)
+{
+	/*	The chunks ml1 and ml2 are combined.
+	*/
+	register mallink *ml3 = phys_next_of(ml2);
+
+	set_phys_next(ml1, ml3);
+	calc_checksum(ml1);
+	if (!last_mallink(ml2))	{
+		set_phys_prev(ml3, ml1);
+		calc_checksum(ml3);
+	}
+	if (ml_last == ml2)
+		ml_last = ml1;
+}
+
+
+/**********************************************************/
+/*
+/*		 This was file check.c
+/*
+/**********************************************************/
+
+/* $Header: /cvsup/minix/src/commands/ash/test/malloc.c,v 1.1.1.1 2005/04/21 14:54:10 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#include	<stdio.h>
+
+#ifdef	CHECK			/* otherwise this whole file is skipped */
+
+/* ??? check these later */
+private acquire_malout(void), check_ml_last(const char *s);
+private dump_all_mallinks(void), dump_free_list(int i);
+private dump_mallink(const char *s, mallink *ml), print_loop(mallink *ml);
+private working_on(mallink *ml);
+private size_type checksum(mallink *ml);
+static FILE *malout;
+
+private mallink *free_list_entry(int i);
+
+#define	for_free_list(i,p) \
+	for (p = free_list_entry(i); p; p = log_next_of(p))
+
+#define	for_all_mallinks(ml)	/* backwards! */ \
+	for (ml = ml_last; ml; \
+		ml = first_mallink(ml) ? MAL_NULL : phys_prev_of(ml))
+
+/* Maldump */
+
+static int pr_cnt = 0;
+
+maldump(int n)	{
+	/*	Dump pertinent info in pseudo-readable format;
+		abort afterwards if n != 0.
+	*/
+	static int dumping = 0;
+	int i;
+	
+	if (dumping)
+		return;
+	dumping++;
+	acquire_malout();
+	fprintf(malout,
+		">>>>>>>>>>>>>>>> DUMP OF ALL MALLINKS <<<<<<<<<<<<<<<<");
+	fprintf(malout, "    ml_last = %p\n", ml_last);
+	if (++pr_cnt == 100) pr_cnt = 0;
+	dump_all_mallinks();
+	fprintf(malout,
+		">>>>>>>>>>>>>>>> DUMP OF FREE_LISTS <<<<<<<<<<<<<<<<\n");
+	if (++pr_cnt == 100) pr_cnt = 0;
+	for (i = 0; i < MAX_FLIST; i++)
+		dump_free_list(i);
+	fprintf(malout,
+		">>>>>>>>>>>>>>>> END OF DUMP <<<<<<<<<<<<<<<<\n");
+	fclose(malout);
+	dumping--;
+	if (n)
+		abort();
+}
+
+private
+acquire_malout(void)	{
+	static char buf[BUFSIZ];
+	
+	if (!malout)	{
+		malout = freopen("mal.out", "w", stderr);	
+		setbuf(malout, buf);
+	}
+}
+
+private
+dump_all_mallinks(void)	{
+	mallink *ml;
+	
+	for_all_mallinks (ml)	{
+		if (print_loop(ml))
+			return;
+		dump_mallink((char *)0, ml);
+	}
+}
+
+private
+dump_free_list(int i)	{
+	mallink *ml = free_list_entry(i);
+	
+	if (!ml)
+		return;
+	fprintf(malout, "%2d: ", i);
+	for_free_list(i, ml)	{
+		if (print_loop(ml))
+			return;
+		fprintf(malout, "%p ", ml);
+	}
+	fprintf(malout, "<\n");
+}
+
+private int
+print_loop(mallink *ml)	{
+	if (print_of(ml) == pr_cnt)	{
+		fprintf(malout, "... PRINT LOOP\n");
+		return 1;
+	}
+	set_print(ml, pr_cnt);
+	return 0;
+}
+
+private
+dump_mallink(const char *s, mallink *ml)	{
+	acquire_malout();
+	if (s)
+		fprintf(malout, "%s: ", s);
+	fprintf(malout, "@: %p;", ml);
+	if (ml && checksum_of(ml) != checksum(ml))
+		fprintf(malout, ">>>> CORRUPTED <<<<");
+	if (!ml)	{
+		fprintf(malout, "\n");
+		return;
+	}	
+	if (free_of(ml))	{
+		fprintf(malout, " l_p: %p;", _log_prev_of(ml));
+		fprintf(malout, " l_n: %p;", _log_next_of(ml));
+	}
+	fprintf(malout, " p_s: %p;", prev_size_of(ml));
+	fprintf(malout, " t_s: %p;", _this_size_of(ml));
+	fprintf(malout, " sz: %lu;", (unsigned long) size_of(ml));
+	fprintf(malout, " fr: %d;", free_of(ml));
+	fprintf(malout, "\n");
+}
+
+/*	Check_mallinks() checks the total data structure as accessible
+	through free_list[] and ml_last.  All check_sums should be OK,
+	except those held in the small array off_colour.  This is a
+	trick to allow to continue checking even when a few mallinks
+	are temporarily out of order.
+	Check_mallinks() tests for a lot of internal consistency.
+*/
+
+/* Some arbitrary constants */
+#define	IN_ML_LAST	93
+#define	IN_FREE_LIST	57		/* and in ml_last */
+#define	CLEAR		21
+
+#define	VRIJ		1
+#define	BEZET		2
+
+private
+check_mallinks(const char *s)	{
+	mallink *ml;
+	size_type size;
+	int i;
+	char stat;
+	
+	check_ml_last(s);
+	stat = BEZET;
+	for_all_mallinks(ml)	{
+		if (checksum_of(ml) != checksum(ml))
+			Error("mallink info at %p corrupted", s, ml);
+		if (working_on(ml))	{
+			stat = BEZET;
+			continue;
+		}
+		if (	!last_mallink(ml) &&
+			phys_prev_of(phys_next_of(ml)) != ml
+		)
+			Error("upward chain bad at %p", s, ml);
+		if (	!first_mallink(ml) &&
+			phys_next_of(phys_prev_of(ml)) != ml
+		)
+			Error("downward chain bad at %p", s, ml);
+		if (free_of(ml))	{
+			if (stat == VRIJ)
+				Error("free mallink at %p follows free mallink",
+								s, ml);
+			stat = VRIJ;
+		}
+		else
+			stat = BEZET;
+		set_mark(ml, IN_ML_LAST);
+	}
+	
+	for (i = 0, size = MIN_SIZE; i < MAX_FLIST; i++, size *= 2)	{
+		for_free_list(i, ml)	{
+			if (working_on(ml))
+				continue;
+			if (!free_of(ml))
+				Error("occupied mallink %p occurs in free_list", s, ml);
+			switch (mark_of(ml))	{
+			case IN_ML_LAST:
+				set_mark(ml, IN_FREE_LIST);
+				break;
+			case IN_FREE_LIST:
+				Error("mallink %p occurs in 2 free_lists",
+								s, ml);
+			default:
+				Error("unknown mallink %p in free_list",
+								s, ml);
+			}
+			if (size_of(ml) < size)
+				Error("size of mallink %p too small", s, ml);
+			if (size_of(ml) >= 2*size)
+				Error("size of mallink %p too large", s, ml);
+		}
+	}
+	for_all_mallinks (ml)	{
+		if (working_on(ml))
+			continue;
+		if (free_of(ml) && mark_of(ml) != IN_FREE_LIST)
+			Error("free mallink %p is in no free_list", s, ml);
+		set_mark(ml, CLEAR);
+	}
+}
+
+private
+check_ml_last(const char *s)	{
+	if (ml_last && _this_size_of(ml_last) == 0)
+		Error("size of ml_last == 0, at %p", s, ml_last);
+}
+
+private size_type
+checksum(mallink *ml)	{
+	size_type sum = 0;
+	
+	if (free_of(ml))	{
+		sum += (size_type)_log_prev_of(ml);
+		sum += (size_type)_log_next_of(ml);
+	}
+	sum += (size_type)prev_size_of(ml);
+	sum += (size_type)_this_size_of(ml);
+	return sum;
+}
+
+private
+calc_checksum(mallink *ml)	{
+	set_checksum(ml, checksum(ml));
+}
+
+#define	N_COLOUR	10
+static mallink *off_colour[N_COLOUR];
+
+private
+started_working_on(mallink *ml)	{
+	int i;
+	
+	for (i = 0; i < N_COLOUR; i++)
+		if (off_colour[i] == MAL_NULL)	{
+			off_colour[i] = ml;
+			return;
+		}
+	Error("out of off_colour array at %p", "started_working_on", ml);
+}
+
+private
+stopped_working_on(mallink *ml)	{
+	int i;
+	
+	for (i = 0; i < N_COLOUR; i++)
+		if (off_colour[i] == ml)	{
+			off_colour[i] = MAL_NULL;
+			return;
+		}
+	Error("stopped working on mallink %p", "stopped_working_on", ml);
+}
+
+private int
+working_on(mallink *ml)	{
+	int i;
+	
+	for (i = 0; i < N_COLOUR; i++)
+		if (off_colour[i] == ml)
+			return 1;
+	return 0;
+}
+
+private
+check_work_empty(const char *s)	{
+	int i;
+	int cnt = 0;
+	
+	for (i = 0; i < N_COLOUR; i++)
+		if (off_colour[i] != MAL_NULL)
+			cnt++;
+	if (cnt != 0)
+		Error("off_colour not empty", s, MAL_NULL);
+}
+
+private int
+Error(const char *fmt, const char *s, mallink *ml)	{
+	static int already_called = 0;
+
+	if (already_called++) return 0;
+	setbuf(stdout, (char *) 0);
+	printf("%s: ", s);
+	printf(fmt, (long)ml);
+	printf("\n");
+	acquire_malout();
+	fprintf(malout, "%s: ", s);
+	fprintf(malout, fmt, (long)ml);
+	fprintf(malout, "\n");
+	fflush(stdout);
+	maldump(1);
+	return 0;			/* to satisfy lint */
+}
+
+#endif	/* CHECK */
+
Index: /trunk/minix/commands/ash/trap.c
===================================================================
--- /trunk/minix/commands/ash/trap.c	(revision 9)
+++ /trunk/minix/commands/ash/trap.c	(revision 9)
@@ -0,0 +1,328 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)trap.c	5.2 (Berkeley) 4/12/91";
+#endif /* not lint */
+
+#include "shell.h"
+#include "main.h"
+#include "nodes.h"	/* for other headers */
+#include "eval.h"
+#include "jobs.h"
+#include "options.h"
+#include "syntax.h"
+#include "signames.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "trap.h"
+#include "mystring.h"
+#include <sys/types.h>
+#include <signal.h>
+
+
+/*
+ * Sigmode records the current value of the signal handlers for the various
+ * modes.  A value of zero means that the current handler is not known.
+ * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
+ */
+
+#define S_DFL 1			/* default signal handling (SIG_DFL) */
+#define S_CATCH 2		/* signal is caught */
+#define S_IGN 3			/* signal is ignored (SIG_IGN) */
+#define S_HARD_IGN 4		/* signal is ignored permenantly */
+
+
+extern char nullstr[1];		/* null string */
+
+char *trap[MAXSIG+1];		/* trap handler commands */
+MKINIT char sigmode[MAXSIG];	/* current value of signal */
+char gotsig[MAXSIG];		/* indicates specified signal received */
+int pendingsigs;			/* indicates some signal received */
+
+/*
+ * The trap builtin.
+ */
+
+trapcmd(argc, argv)  char **argv; {
+	char *action;
+	char **ap;
+	int signo;
+
+	if (argc <= 1) {
+		for (signo = 0 ; signo <= MAXSIG ; signo++) {
+			if (trap[signo] != NULL)
+				out1fmt("%d: %s\n", signo, trap[signo]);
+		}
+		return 0;
+	}
+	ap = argv + 1;
+	if (is_number(*ap))
+		action = NULL;
+	else
+		action = *ap++;
+	while (*ap) {
+		if ((signo = number(*ap)) < 0 || signo > MAXSIG)
+			error("%s: bad trap", *ap);
+		INTOFF;
+		if (action)
+			action = savestr(action);
+		if (trap[signo])
+			ckfree(trap[signo]);
+		trap[signo] = action;
+		if (signo != 0)
+			setsignal(signo);
+		INTON;
+		ap++;
+	}
+	return 0;
+}
+
+
+
+/*
+ * Clear traps on a fork.
+ */
+
+void
+clear_traps() {
+	char **tp;
+
+	for (tp = trap ; tp <= &trap[MAXSIG] ; tp++) {
+		if (*tp && **tp) {	/* trap not NULL or SIG_IGN */
+			INTOFF;
+			ckfree(*tp);
+			*tp = NULL;
+			if (tp != &trap[0])
+				setsignal(tp - trap);
+			INTON;
+		}
+	}
+}
+
+
+
+/*
+ * Set the signal handler for the specified signal.  The routine figures
+ * out what it should be set to.
+ */
+
+int
+setsignal(signo) {
+	int action;
+	sig_t sigact;
+	char *t;
+	extern void onsig();
+
+	if ((t = trap[signo]) == NULL)
+		action = S_DFL;
+	else if (*t != '\0')
+		action = S_CATCH;
+	else
+		action = S_IGN;
+	if (rootshell && action == S_DFL) {
+		switch (signo) {
+		case SIGINT:
+			if (iflag)
+				action = S_CATCH;
+			break;
+		case SIGQUIT:
+#if DEBUG
+			{
+			extern int debug;
+
+			if (debug)
+				break;
+			}
+#endif
+			/* FALLTHROUGH */
+		case SIGTERM:
+			if (iflag)
+				action = S_IGN;
+			break;
+#if JOBS
+		case SIGTSTP:
+		case SIGTTOU:
+			if (jflag)
+				action = S_IGN;
+			break;
+#endif
+		}
+	}
+	t = &sigmode[signo - 1];
+	if (*t == 0) {	/* current setting unknown */
+		/*
+		 * There is a race condition here if action is not S_IGN.
+		 * A signal can be ignored that shouldn't be.
+		 */
+		if ((int)(sigact = signal(signo, SIG_IGN)) == -1)
+			error("Signal system call failed");
+		if (sigact == SIG_IGN) {
+			*t = S_HARD_IGN;
+		} else {
+			*t = S_IGN;
+		}
+	}
+	if (*t == S_HARD_IGN || *t == action)
+		return 0;
+	switch (action) {
+		case S_DFL:	sigact = SIG_DFL;	break;
+		case S_CATCH:  	sigact = onsig;		break;
+		case S_IGN:	sigact = SIG_IGN;	break;
+	}
+	*t = action;
+	return (int)signal(signo, sigact);
+}
+
+
+/*
+ * Ignore a signal.
+ */
+
+void
+ignoresig(signo) {
+	if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
+		signal(signo, SIG_IGN);
+	}
+	sigmode[signo - 1] = S_HARD_IGN;
+}
+
+
+#ifdef mkinit
+INCLUDE "signames.h"
+INCLUDE "trap.h"
+
+SHELLPROC {
+	char *sm;
+
+	clear_traps();
+	for (sm = sigmode ; sm < sigmode + MAXSIG ; sm++) {
+		if (*sm == S_IGN)
+			*sm = S_HARD_IGN;
+	}
+}
+#endif
+
+
+
+/*
+ * Signal handler.
+ */
+
+void
+onsig(signo) {
+	signal(signo, onsig);
+	if (signo == SIGINT && trap[SIGINT] == NULL) {
+		onint();
+		return;
+	}
+	gotsig[signo - 1] = 1;
+	pendingsigs++;
+}
+
+
+
+/*
+ * Called to execute a trap.  Perhaps we should avoid entering new trap
+ * handlers while we are executing a trap handler.
+ */
+
+void
+dotrap() {
+	int i;
+	int savestatus;
+
+	for (;;) {
+		for (i = 1 ; ; i++) {
+			if (gotsig[i - 1])
+				break;
+			if (i >= MAXSIG)
+				goto done;
+		}
+		gotsig[i - 1] = 0;
+		savestatus=exitstatus;
+		evalstring(trap[i]);
+		exitstatus=savestatus;
+	}
+done:
+	pendingsigs = 0;
+}
+
+
+
+/*
+ * Controls whether the shell is interactive or not.
+ */
+
+int is_interactive;
+
+void
+setinteractive(on) {
+	if (on == is_interactive)
+		return;
+	setsignal(SIGINT);
+	setsignal(SIGQUIT);
+	setsignal(SIGTERM);
+	is_interactive = on;
+}
+
+
+
+/*
+ * Called to exit the shell.
+ */
+
+void
+exitshell(status) {
+	struct jmploc loc1, loc2;
+	char *p;
+
+	TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
+	if (setjmp(loc1.loc))  goto l1;
+	if (setjmp(loc2.loc))  goto l2;
+	handler = &loc1;
+	if ((p = trap[0]) != NULL && *p != '\0') {
+		trap[0] = NULL;
+		evalstring(p);
+	}
+l1:   handler = &loc2;			/* probably unnecessary */
+	flushall();
+#if JOBS
+	setjobctl(0);
+#endif
+l2:   _exit(status);
+}
Index: /trunk/minix/commands/ash/trap.h
===================================================================
--- /trunk/minix/commands/ash/trap.h	(revision 9)
+++ /trunk/minix/commands/ash/trap.h	(revision 9)
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)trap.h	5.1 (Berkeley) 3/7/91
+ */
+
+extern int pendingsigs;
+
+#ifdef __STDC__
+void clear_traps(void);
+int setsignal(int);
+void ignoresig(int);
+void dotrap(void);
+void setinteractive(int);
+void exitshell(int);
+#else
+void clear_traps();
+int setsignal();
+void ignoresig();
+void dotrap();
+void setinteractive();
+void exitshell();
+#endif
Index: /trunk/minix/commands/ash/var.c
===================================================================
--- /trunk/minix/commands/ash/var.c	(revision 9)
+++ /trunk/minix/commands/ash/var.c	(revision 9)
@@ -0,0 +1,651 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)var.c	5.3 (Berkeley) 4/12/91";
+#endif /* not lint */
+
+/*
+ * Shell variables.
+ */
+
+#include "shell.h"
+#include "output.h"
+#include "expand.h"
+#include "nodes.h"	/* for other headers */
+#include "eval.h"	/* defines cmdenviron */
+#include "exec.h"
+#include "syntax.h"
+#include "options.h"
+#include "mail.h"
+#include "var.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+
+
+#define VTABSIZE 39
+
+
+struct varinit {
+	struct var *var;
+	int flags;
+	char *text;
+};
+
+
+#if ATTY
+struct var vatty;
+#endif
+struct var vifs;
+struct var vmail;
+struct var vmpath;
+struct var vpath;
+struct var vps1;
+struct var vps2;
+struct var vpse;
+struct var vvers;
+#if ATTY
+struct var vterm;
+#endif
+
+const struct varinit varinit[] = {
+#if ATTY
+	{&vatty,	VSTRFIXED|VTEXTFIXED|VUNSET,	"ATTY="},
+#endif
+	{&vifs,	VSTRFIXED|VTEXTFIXED,		"IFS= \t\n"},
+	{&vmail,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAIL="},
+	{&vmpath,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAILPATH="},
+	{&vpath,	VSTRFIXED|VTEXTFIXED,		"PATH=:/bin:/usr/bin"},
+	/* 
+	 * vps1 depends on uid
+	 */
+	{&vps2,	VSTRFIXED|VTEXTFIXED,		"PS2=> "},
+	{&vpse,	VSTRFIXED|VTEXTFIXED,		"PSE=* "},
+#if ATTY
+	{&vterm,	VSTRFIXED|VTEXTFIXED|VUNSET,	"TERM="},
+#endif
+	{NULL,	0,				NULL}
+};
+
+struct var *vartab[VTABSIZE];
+
+STATIC void unsetvar __P((char *));
+STATIC struct var **hashvar __P((char *));
+STATIC int varequal __P((char *, char *));
+
+/*
+ * Initialize the varable symbol tables and import the environment
+ */
+
+#ifdef mkinit
+INCLUDE "var.h"
+INIT {
+	char **envp;
+	extern char **environ;
+
+	initvar();
+	for (envp = environ ; *envp ; envp++) {
+		if (strchr(*envp, '=')) {
+			setvareq(*envp, VEXPORT|VTEXTFIXED);
+		}
+	}
+}
+#endif
+
+
+/*
+ * This routine initializes the builtin variables.  It is called when the
+ * shell is initialized and again when a shell procedure is spawned.
+ */
+
+void
+initvar() {
+	const struct varinit *ip;
+	struct var *vp;
+	struct var **vpp;
+
+	for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
+		if ((vp->flags & VEXPORT) == 0) {
+			vpp = hashvar(ip->text);
+			vp->next = *vpp;
+			*vpp = vp;
+			vp->text = ip->text;
+			vp->flags = ip->flags;
+		}
+	}
+	/*
+	 * PS1 depends on uid
+	 */
+	if ((vps1.flags & VEXPORT) == 0) {
+		vpp = hashvar("PS1=");
+		vps1.next = *vpp;
+		*vpp = &vps1;
+		vps1.text = getuid() ? "PS1=$ " : "PS1=# ";
+		vps1.flags = VSTRFIXED|VTEXTFIXED;
+	}
+}
+
+/*
+ * Set the value of a variable.  The flags argument is ored with the
+ * flags of the variable.  If val is NULL, the variable is unset.
+ */
+
+void
+setvar(name, val, flags)
+	char *name, *val;
+	{
+	char *p, *q;
+	int len;
+	int namelen;
+	char *nameeq;
+	int isbad;
+
+	isbad = 0;
+	p = name;
+	if (! is_name(*p++))
+		isbad = 1;
+	for (;;) {
+		if (! is_in_name(*p)) {
+			if (*p == '\0' || *p == '=')
+				break;
+			isbad = 1;
+		}
+		p++;
+	}
+	namelen = p - name;
+	if (isbad)
+		error("%.*s: is read only", namelen, name);
+	len = namelen + 2;		/* 2 is space for '=' and '\0' */
+	if (val == NULL) {
+		flags |= VUNSET;
+	} else {
+		len += strlen(val);
+	}
+	p = nameeq = ckmalloc(len);
+	q = name;
+	while (--namelen >= 0)
+		*p++ = *q++;
+	*p++ = '=';
+	*p = '\0';
+	if (val)
+		scopy(val, p);
+	setvareq(nameeq, flags);
+}
+
+
+
+/*
+ * Same as setvar except that the variable and value are passed in
+ * the first argument as name=value.  Since the first argument will
+ * be actually stored in the table, it should not be a string that
+ * will go away.
+ */
+
+void
+setvareq(s, flags)
+	char *s;
+	{
+	struct var *vp, **vpp;
+
+	vpp = hashvar(s);
+	for (vp = *vpp ; vp ; vp = vp->next) {
+		if (varequal(s, vp->text)) {
+			if (vp->flags & VREADONLY) {
+				int len = strchr(s, '=') - s;
+				error("%.*s: is read only", len, s);
+			}
+			INTOFF;
+			if (vp == &vpath)
+				changepath(s + 5);	/* 5 = strlen("PATH=") */
+			if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
+				ckfree(vp->text);
+			vp->flags &=~ (VTEXTFIXED|VSTACK|VUNSET);
+			vp->flags |= flags;
+			vp->text = s;
+			if (vp == &vmpath || (vp == &vmail && ! mpathset()))
+				chkmail(1);
+			INTON;
+			return;
+		}
+	}
+	/* not found */
+	vp = ckmalloc(sizeof (*vp));
+	vp->flags = flags;
+	vp->text = s;
+	vp->next = *vpp;
+	*vpp = vp;
+}
+
+
+
+/*
+ * Process a linked list of variable assignments.
+ */
+
+void
+listsetvar(list)
+	struct strlist *list;
+	{
+	struct strlist *lp;
+
+	INTOFF;
+	for (lp = list ; lp ; lp = lp->next) {
+		setvareq(savestr(lp->text), 0);
+	}
+	INTON;
+}
+
+
+
+/*
+ * Find the value of a variable.  Returns NULL if not set.
+ */
+
+char *
+lookupvar(name)
+	char *name;
+	{
+	struct var *v;
+
+	for (v = *hashvar(name) ; v ; v = v->next) {
+		if (varequal(v->text, name)) {
+			if (v->flags & VUNSET)
+				return NULL;
+			return strchr(v->text, '=') + 1;
+		}
+	}
+	return NULL;
+}
+
+
+
+/*
+ * Search the environment of a builtin command.  If the second argument
+ * is nonzero, return the value of a variable even if it hasn't been
+ * exported.
+ */
+
+char *
+bltinlookup(name, doall)
+	char *name;
+	{
+	struct strlist *sp;
+	struct var *v;
+
+	for (sp = cmdenviron ; sp ; sp = sp->next) {
+		if (varequal(sp->text, name))
+			return strchr(sp->text, '=') + 1;
+	}
+	for (v = *hashvar(name) ; v ; v = v->next) {
+		if (varequal(v->text, name)) {
+			if (v->flags & VUNSET
+			 || ! doall && (v->flags & VEXPORT) == 0)
+				return NULL;
+			return strchr(v->text, '=') + 1;
+		}
+	}
+	return NULL;
+}
+
+
+
+/*
+ * Generate a list of exported variables.  This routine is used to construct
+ * the third argument to execve when executing a program.
+ */
+
+char **
+environment() {
+	int nenv;
+	struct var **vpp;
+	struct var *vp;
+	char **env, **ep;
+
+	nenv = 0;
+	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
+		for (vp = *vpp ; vp ; vp = vp->next)
+			if (vp->flags & VEXPORT)
+				nenv++;
+	}
+	ep = env = stalloc((nenv + 1) * sizeof *env);
+	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
+		for (vp = *vpp ; vp ; vp = vp->next)
+			if (vp->flags & VEXPORT)
+				*ep++ = vp->text;
+	}
+	*ep = NULL;
+	return env;
+}
+
+
+/*
+ * Called when a shell procedure is invoked to clear out nonexported
+ * variables.  It is also necessary to reallocate variables of with
+ * VSTACK set since these are currently allocated on the stack.
+ */
+
+#ifdef mkinit
+MKINIT void shprocvar();
+
+SHELLPROC {
+	shprocvar();
+}
+#endif
+
+void
+shprocvar() {
+	struct var **vpp;
+	struct var *vp, **prev;
+
+	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
+		for (prev = vpp ; (vp = *prev) != NULL ; ) {
+			if ((vp->flags & VEXPORT) == 0) {
+				*prev = vp->next;
+				if ((vp->flags & VTEXTFIXED) == 0)
+					ckfree(vp->text);
+				if ((vp->flags & VSTRFIXED) == 0)
+					ckfree(vp);
+			} else {
+				if (vp->flags & VSTACK) {
+					vp->text = savestr(vp->text);
+					vp->flags &=~ VSTACK;
+				}
+				prev = &vp->next;
+			}
+		}
+	}
+	initvar();
+}
+
+
+
+/*
+ * Command to list all variables which are set.  Currently this command
+ * is invoked from the set command when the set command is called without
+ * any variables.
+ */
+
+int
+showvarscmd(argc, argv)  char **argv; {
+	struct var **vpp;
+	struct var *vp;
+
+	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
+		for (vp = *vpp ; vp ; vp = vp->next) {
+			if ((vp->flags & VUNSET) == 0)
+				out1fmt("%s\n", vp->text);
+		}
+	}
+	return 0;
+}
+
+
+
+/*
+ * The export and readonly commands.
+ */
+
+int
+exportcmd(argc, argv)  char **argv; {
+	struct var **vpp;
+	struct var *vp;
+	char *name;
+	char *p;
+	int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
+
+	listsetvar(cmdenviron);
+	if (argc > 1) {
+		while ((name = *argptr++) != NULL) {
+			if ((p = strchr(name, '=')) != NULL) {
+				p++;
+			} else {
+				vpp = hashvar(name);
+				for (vp = *vpp ; vp ; vp = vp->next) {
+					if (varequal(vp->text, name)) {
+						vp->flags |= flag;
+						goto found;
+					}
+				}
+			}
+			setvar(name, p, flag);
+found:;
+		}
+	} else {
+		for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
+			for (vp = *vpp ; vp ; vp = vp->next) {
+				if (vp->flags & flag) {
+					for (p = vp->text ; *p != '=' ; p++)
+						out1c(*p);
+					out1c('\n');
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+
+/*
+ * The "local" command.
+ */
+
+localcmd(argc, argv)  char **argv; {
+	char *name;
+
+	if (! in_function())
+		error("Not in a function");
+	while ((name = *argptr++) != NULL) {
+		mklocal(name);
+	}
+	return 0;
+}
+
+
+/*
+ * Make a variable a local variable.  When a variable is made local, it's
+ * value and flags are saved in a localvar structure.  The saved values
+ * will be restored when the shell function returns.  We handle the name
+ * "-" as a special case.
+ */
+
+void
+mklocal(name)
+	char *name;
+	{
+	struct localvar *lvp;
+	struct var **vpp;
+	struct var *vp;
+
+	INTOFF;
+	lvp = ckmalloc(sizeof (struct localvar));
+	if (name[0] == '-' && name[1] == '\0') {
+		lvp->text = ckmalloc(sizeof optval);
+		bcopy(optval, lvp->text, sizeof optval);
+		vp = NULL;
+	} else {
+		vpp = hashvar(name);
+		for (vp = *vpp ; vp && ! varequal(vp->text, name) ; vp = vp->next);
+		if (vp == NULL) {
+			if (strchr(name, '='))
+				setvareq(savestr(name), VSTRFIXED);
+			else
+				setvar(name, NULL, VSTRFIXED);
+			vp = *vpp;	/* the new variable */
+			lvp->text = NULL;
+			lvp->flags = VUNSET;
+		} else {
+			lvp->text = vp->text;
+			lvp->flags = vp->flags;
+			vp->flags |= VSTRFIXED|VTEXTFIXED;
+			if (strchr(name, '='))
+				setvareq(savestr(name), 0);
+		}
+	}
+	lvp->vp = vp;
+	lvp->next = localvars;
+	localvars = lvp;
+	INTON;
+}
+
+
+/*
+ * Called after a function returns.
+ */
+
+void
+poplocalvars() {
+	struct localvar *lvp;
+	struct var *vp;
+
+	while ((lvp = localvars) != NULL) {
+		localvars = lvp->next;
+		vp = lvp->vp;
+		if (vp == NULL) {	/* $- saved */
+			bcopy(lvp->text, optval, sizeof optval);
+			ckfree(lvp->text);
+		} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
+			unsetvar(vp->text);
+		} else {
+			if ((vp->flags & VTEXTFIXED) == 0)
+				ckfree(vp->text);
+			vp->flags = lvp->flags;
+			vp->text = lvp->text;
+		}
+		ckfree(lvp);
+	}
+}
+
+
+setvarcmd(argc, argv)  char **argv; {
+	if (argc <= 2)
+		return unsetcmd(argc, argv);
+	else if (argc == 3)
+		setvar(argv[1], argv[2], 0);
+	else
+		error("List assignment not implemented");
+	return 0;
+}
+
+
+/*
+ * The unset builtin command.  We unset the function before we unset the
+ * variable to allow a function to be unset when there is a readonly variable
+ * with the same name.
+ */
+
+unsetcmd(argc, argv)  char **argv; {
+	char **ap;
+
+	for (ap = argv + 1 ; *ap ; ap++) {
+		unsetfunc(*ap);
+		unsetvar(*ap);
+	}
+	return 0;
+}
+
+
+/*
+ * Unset the specified variable.
+ */
+
+STATIC void
+unsetvar(s)
+	char *s;
+	{
+	struct var **vpp;
+	struct var *vp;
+
+	vpp = hashvar(s);
+	for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
+		if (varequal(vp->text, s)) {
+			INTOFF;
+			if (*(strchr(vp->text, '=') + 1) != '\0'
+			 || vp->flags & VREADONLY) {
+				setvar(s, nullstr, 0);
+			}
+			vp->flags &=~ VEXPORT;
+			vp->flags |= VUNSET;
+			if ((vp->flags & VSTRFIXED) == 0) {
+				if ((vp->flags & VTEXTFIXED) == 0)
+					ckfree(vp->text);
+				*vpp = vp->next;
+				ckfree(vp);
+			}
+			INTON;
+			return;
+		}
+	}
+}
+
+
+
+/*
+ * Find the appropriate entry in the hash table from the name.
+ */
+
+STATIC struct var **
+hashvar(p)
+	register char *p;
+	{
+	unsigned int hashval;
+
+	hashval = *p << 4;
+	while (*p && *p != '=')
+		hashval += *p++;
+	return &vartab[hashval % VTABSIZE];
+}
+
+
+
+/*
+ * Returns true if the two strings specify the same varable.  The first
+ * variable name is terminated by '='; the second may be terminated by
+ * either '=' or '\0'.
+ */
+
+STATIC int
+varequal(p, q)
+	register char *p, *q;
+	{
+	while (*p == *q++) {
+		if (*p++ == '=')
+			return 1;
+	}
+	if (*p == '=' && *(q - 1) == '\0')
+		return 1;
+	return 0;
+}
Index: /trunk/minix/commands/ash/var.h
===================================================================
--- /trunk/minix/commands/ash/var.h	(revision 9)
+++ /trunk/minix/commands/ash/var.h	(revision 9)
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)var.h	5.1 (Berkeley) 3/7/91
+ */
+
+/*
+ * Shell variables.
+ */
+
+/* flags */
+#define VEXPORT		01	/* variable is exported */
+#define VREADONLY	02	/* variable cannot be modified */
+#define VSTRFIXED	04	/* variable struct is staticly allocated */
+#define VTEXTFIXED	010	/* text is staticly allocated */
+#define VSTACK		020	/* text is allocated on the stack */
+#define VUNSET		040	/* the variable is not set */
+
+
+struct var {
+	struct var *next;		/* next entry in hash list */
+	int flags;		/* flags are defined above */
+	char *text;		/* name=value */
+};
+
+
+struct localvar {
+	struct localvar *next;	/* next local variable in list */
+	struct var *vp;		/* the variable that was made local */
+	int flags;		/* saved flags */
+	char *text;		/* saved text */
+};
+
+
+struct localvar *localvars;
+
+#if ATTY
+extern struct var vatty;
+#endif
+extern struct var vifs;
+extern struct var vmail;
+extern struct var vmpath;
+extern struct var vpath;
+extern struct var vps1;
+extern struct var vps2;
+extern struct var vpse;
+#if ATTY
+extern struct var vterm;
+#endif
+
+/*
+ * The following macros access the values of the above variables.
+ * They have to skip over the name.  They return the null string
+ * for unset variables.
+ */
+
+#define ifsval()	(vifs.text + 4)
+#define mailval()	(vmail.text + 5)
+#define mpathval()	(vmpath.text + 9)
+#define pathval()	(vpath.text + 5)
+#define ps1val()	(vps1.text + 4)
+#define ps2val()	(vps2.text + 4)
+#define pseval()	(vpse.text + 4)
+#if ATTY
+#define termval()	(vterm.text + 5)
+#endif
+
+#if ATTY
+#define attyset()	((vatty.flags & VUNSET) == 0)
+#endif
+#define mpathset()	((vmpath.flags & VUNSET) == 0)
+
+
+#ifdef __STDC__
+void initvar();
+void setvar(char *, char *, int);
+void setvareq(char *, int);
+struct strlist;
+void listsetvar(struct strlist *);
+char *lookupvar(char *);
+char *bltinlookup(char *, int);
+char **environment();
+int showvarscmd(int, char **);
+void mklocal(char *);
+void poplocalvars(void);
+#else
+void initvar();
+void setvar();
+void setvareq();
+void listsetvar();
+char *lookupvar();
+char *bltinlookup();
+char **environment();
+int showvarscmd();
+void mklocal();
+void poplocalvars();
+#endif
Index: /trunk/minix/commands/autil/Makefile
===================================================================
--- /trunk/minix/commands/autil/Makefile	(revision 9)
+++ /trunk/minix/commands/autil/Makefile	(revision 9)
@@ -0,0 +1,26 @@
+# Makefile for commands/autil
+
+CC = exec cc
+CFLAGS	= -I. -D_MINIX -D_POSIX_SOURCE -wo
+CCLD	= $(CC) -i $(CFLAGS)
+
+all:	anm asize
+
+anm:	anm.c rd.c rd_arhdr.c rd_bytes.c rd_unsig2.c
+	$(CCLD) -o $@ $?
+	install -S 32kw $@
+
+asize:	asize.c
+	$(CCLD) -o $@ $?
+	install -S 4kw $@
+
+install:	/usr/bin/anm /usr/bin/asize
+
+/usr/bin/anm:	anm
+	install -cs -o bin $? $@
+
+/usr/bin/asize:	asize
+	install -cs -o bin $? $@
+
+clean:
+	rm -f anm asize core
Index: /trunk/minix/commands/autil/anm.c
===================================================================
--- /trunk/minix/commands/autil/anm.c	(revision 9)
+++ /trunk/minix/commands/autil/anm.c	(revision 9)
@@ -0,0 +1,339 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Id: anm.c,v 1.2 2005/06/23 09:50:54 philip Exp $ */
+/*
+**	print symbol tables for
+**	ACK object files
+**
+**	anm [-gopruns] [name ...]
+*/
+
+#include	"out.h"
+#include	"arch.h"
+#include	"ranlib.h"
+
+#include	<stdio.h>
+#include	<ctype.h>
+
+int	numsort_flg;
+int	sectsort_flg;
+int	undef_flg;
+int	revsort_flg = 1;
+int	globl_flg;
+int	nosort_flg;
+int	arch_flg;
+int	prep_flg;
+int	read_error;
+struct	outhead	hbuf;
+struct	outsect	sbuf;
+long	off;
+char	*malloc();
+char	*realloc();
+long	s_base[S_MAX];	/* for specially encoded bases */
+char	*filename;
+int	narg;
+
+main(argc, argv)
+char **argv;
+{
+
+	if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) {
+		argv++;
+		while (*++*argv) switch (**argv) {
+		case 'n':		/* sort numerically */
+			numsort_flg++;
+			continue;
+
+		case 's':		/* sort in section order */
+			sectsort_flg++;
+			continue;
+
+		case 'g':		/* globl symbols only */
+			globl_flg++;
+			continue;
+
+		case 'u':		/* undefined symbols only */
+			undef_flg++;
+			continue;
+
+		case 'r':		/* sort in reverse order */
+			revsort_flg = -1;
+			continue;
+
+		case 'p':		/* don't sort -- symbol table order */
+			nosort_flg++;
+			continue;
+
+		case 'o':		/* prepend a name to each line */
+			prep_flg++;
+			continue;
+
+		default:		/* oops */
+			fprintf(stderr, "anm: invalid argument -%c\n", *argv[0]);
+			exit(1);
+		}
+		argc--;
+	}
+	if (argc == 0) {
+		argc = 1;
+		argv[1] = "a.out";
+	}
+	narg = argc;
+
+	while(argc--) {
+		int fd;
+
+		filename = *++argv;
+		if ((fd = open(filename, 0)) < 0) {
+			fprintf(stderr, "anm: cannot open %s\n", filename);
+			continue;
+		}
+		process(fd);
+		close(fd);
+	}
+	exit(0);
+}
+
+extern int rd_unsigned2();
+extern long lseek();
+extern char *strncpy();
+
+process(fd)
+	int	fd;
+{
+	unsigned int	magic;
+	long		nextpos;
+	struct ar_hdr	archive_header;
+	static char	buf[sizeof(archive_header.ar_name)+1];
+
+	if (narg > 1) printf("\n%s:\n", filename);
+
+	magic = rd_unsigned2(fd);
+	switch(magic) {
+	case O_MAGIC:
+		lseek(fd, 0L, 0);
+		do_file(fd);
+		break;
+	case ARMAG:
+	case AALMAG:
+		while (rd_arhdr(fd, &archive_header)) {
+			nextpos = lseek(fd, 0L, 1) + archive_header.ar_size;
+			if (nextpos & 1) nextpos++;
+			strncpy(buf,archive_header.ar_name,sizeof(archive_header.ar_name));
+			filename = buf;
+			if ( strcmp(filename, SYMDEF)) {
+				printf("\n%s:\n", filename);
+				do_file(fd);
+			}
+			lseek(fd, nextpos, 0);
+		}
+		break;
+	default:
+		fprintf(stderr, "anm: %s -- bad format\n", filename);
+		break;
+	}
+}
+
+do_file(fd)
+	int	fd;
+{
+	struct	outname	*nbufp = NULL;
+	struct	outname	nbuf;
+	char		*cbufp;
+	long		fi_to_co;
+	long		n;
+	unsigned	readcount;
+	int		i,j;
+	int		compare();
+
+	read_error = 0;
+	rd_fdopen(fd);
+
+	rd_ohead(&hbuf);
+	if (read_error) {
+		return;
+	}
+	if (BADMAGIC(hbuf)) {
+		return;
+	}
+
+	n = hbuf.oh_nname;
+	if (n == 0) {
+		fprintf(stderr, "anm: %s -- no name list\n", filename);
+		return;
+	}
+
+	if (hbuf.oh_nchar == 0) {
+		fprintf(stderr, "anm: %s -- no names\n", filename);
+		return;
+	}
+	if ((readcount = hbuf.oh_nchar) != hbuf.oh_nchar) {
+		fprintf(stderr, "anm: string area too big in %s\n", filename);
+		exit(2);
+	}
+
+	/* store special section bases ??? */
+	if (hbuf.oh_flags & HF_8086) {
+		rd_sect(&sbuf, hbuf.oh_nsect);
+		if (read_error) {
+			return;
+		}
+		for (i=0; i<hbuf.oh_nsect; i++) {
+			s_base[i+S_MIN] =
+				(sbuf.os_base>>12) & 03777760;
+		}
+	}
+
+	if ((cbufp = (char *)malloc(readcount)) == NULL) {
+		fprintf(stderr, "anm: out of memory on %s\n", filename);
+		exit(2);
+	}
+	rd_string(cbufp, hbuf.oh_nchar);
+	if (read_error) {
+		free(cbufp);
+		return;
+	}
+
+	fi_to_co = (long) (cbufp - OFF_CHAR(hbuf));
+	i = 0;
+	while (--n >= 0) {
+		rd_name(&nbuf, 1);
+		if (read_error) {
+			break;
+		}
+
+		if (globl_flg && (nbuf.on_type&S_EXT)==0)
+			continue;
+
+		if (undef_flg
+		    &&
+		    ((nbuf.on_type&S_TYP)!=S_UND || (nbuf.on_type&S_ETC)!=0))
+			continue;
+
+		if (nbuf.on_foff == 0) nbuf.on_mptr = 0;
+		else nbuf.on_mptr = (char *) (nbuf.on_foff + fi_to_co);
+
+		/* adjust value for specially encoded bases */
+		if (hbuf.oh_flags & HF_8086) {
+		    if (((nbuf.on_type&S_ETC) == 0) ||
+			((nbuf.on_type&S_ETC) == S_SCT)) {
+			j = nbuf.on_type&S_TYP;
+			if ((j>=S_MIN) && (j<=S_MAX))
+			    nbuf.on_valu += s_base[j];
+		    }
+		}
+
+		if (nbufp == NULL)
+			nbufp = (struct outname *)malloc(sizeof(struct outname));
+		else
+			nbufp = (struct outname *)realloc(nbufp, (i+1)*sizeof(struct outname));
+		if (nbufp == NULL) {
+			fprintf(stderr, "anm: out of memory on %s\n", filename);
+			exit(2);
+		}
+		nbufp[i++] = nbuf;
+	}
+
+	if (nbufp && nosort_flg==0)
+		qsort(nbufp, i, sizeof(struct outname), compare);
+
+	for (n=0; n<i; n++) {
+		char	cs1[4];
+		char	cs2[4];
+
+		if (prep_flg)
+			printf("%s:", filename);
+
+		switch(nbufp[n].on_type&S_ETC) {
+		case S_SCT:
+			sprintf(cs1, "%2d", (nbufp[n].on_type&S_TYP) - S_MIN);
+			sprintf(cs2, " S");
+			break;
+		case S_FIL:
+			sprintf(cs1, " -");
+			sprintf(cs2, " F");
+			break;
+		case S_MOD:
+			sprintf(cs1, " -");
+			sprintf(cs2, " M");
+			break;
+		case S_COM:
+			sprintf(cs1, " C");
+			if (nbufp[n].on_type&S_EXT)
+				sprintf(cs2, " E");
+			else
+				sprintf(cs2, " -");
+			break;
+		case 0:
+			if (nbufp[n].on_type&S_EXT)
+				sprintf(cs2, " E");
+			else
+				sprintf(cs2, " -");
+
+			switch(nbufp[n].on_type&S_TYP) {
+			case S_UND:
+				sprintf(cs1, " U");
+				break;
+			case S_ABS:
+				sprintf(cs1, " A");
+				break;
+			default:
+				sprintf(cs1, "%2d", (nbufp[n].on_type&S_TYP) - S_MIN);
+			}
+			break;
+		default:
+			sprintf(cs1, "??");
+			sprintf(cs2, " ?");
+		}
+
+		printf("%8lx %s %s %s\n",nbufp[n].on_valu,cs1,cs2,nbufp[n].on_mptr ? nbufp[n].on_mptr : "(NULL)");
+	}
+
+	if (nbufp)
+		free((char *)nbufp);
+	if (cbufp)
+		free((char *)cbufp);
+}
+
+compare(p1, p2)
+struct outname	*p1, *p2;
+{
+	int	i;
+
+	if (sectsort_flg) {
+		if ((p1->on_type&S_TYP) > (p2->on_type&S_TYP))
+			return(revsort_flg);
+		if ((p1->on_type&S_TYP) < (p2->on_type&S_TYP))
+			return(-revsort_flg);
+	}
+
+	if (numsort_flg) {
+		if (p1->on_valu > p2->on_valu)
+			return(revsort_flg);
+		if (p1->on_valu < p2->on_valu)
+			return(-revsort_flg);
+	}
+
+	if (! p1->on_mptr) {
+		if (! p2->on_mptr) return 0;
+		return -revsort_flg;
+	}
+	if (! p2->on_mptr) return revsort_flg;
+
+	i = strcmp(p1->on_mptr, p2->on_mptr);
+
+	if (i > 0)
+		return(revsort_flg);
+	if (i < 0)
+		return(-revsort_flg);
+
+	return(0);
+}
+
+rd_fatal()
+{
+	fprintf(stderr,"read error on %s\n", filename);
+	read_error = 1;
+}
Index: /trunk/minix/commands/autil/arch.h
===================================================================
--- /trunk/minix/commands/autil/arch.h	(revision 9)
+++ /trunk/minix/commands/autil/arch.h	(revision 9)
@@ -0,0 +1,25 @@
+/* $Id: arch.h,v 1.1 2005/06/23 09:50:54 philip Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+
+#ifndef __ARCH_H_INCLUDED
+#define __ARCH_H_INCLUDED
+
+#define	ARMAG	0177545
+#define AALMAG	0177454
+
+struct	ar_hdr {
+	char	ar_name[14];
+	long	ar_date;
+	char	ar_uid;
+	char	ar_gid;
+	short	ar_mode;
+	long	ar_size;
+};
+
+#define AR_TOTAL	26
+#define AR_SIZE		22
+
+#endif /* __ARCH_H_INCLUDED */
Index: /trunk/minix/commands/autil/asize.c
===================================================================
--- /trunk/minix/commands/autil/asize.c	(revision 9)
+++ /trunk/minix/commands/autil/asize.c	(revision 9)
@@ -0,0 +1,93 @@
+/* @(#)asize.c	1.4 */
+#define	ushort	unsigned short
+
+#include	<stdio.h>
+#include 	"out.h"
+
+/*
+	asize -- determine object size
+
+*/
+
+main(argc, argv)
+char **argv;
+{
+	struct outhead	buf;
+	struct outsect	sbuf;
+	ushort		nrsect;
+	long		sum;
+	int		gorp;
+	FILE		*f;
+
+	if (--argc == 0) {
+		argc = 1;
+		argv[1] = "a.out";
+	}
+	gorp = argc;
+
+	while(argc--) {
+		if ((f = fopen(*++argv, "r"))==NULL) {
+			fprintf(stderr, "asize: cannot open %s\n", *argv);
+			continue;
+		}
+		getofmt ((char *)&buf, SF_HEAD , f);
+		if(BADMAGIC(buf)) {
+			fprintf(stderr, "asize: %s-- bad format\n", *argv);
+			fclose(f);
+			continue;
+		}
+		nrsect = buf.oh_nsect;
+		if (nrsect == 0) {
+			fprintf(stderr, "asize: %s-- no sections\n", *argv);
+			fclose(f);
+			continue;
+		}
+		if (gorp > 1)
+			printf("%s: ", *argv);
+
+		sum = 0;
+		while (nrsect-- > 0) {
+			getofmt ((char *)&sbuf, SF_SECT , f);
+			printf("%ld", sbuf.os_size);
+			sum += sbuf.os_size;
+			if (nrsect > 0)
+				putchar('+');
+		}
+		printf(" = %ld = 0x%lx\n", sum, sum);
+		fclose(f);
+	}
+}
+
+getofmt(p, s, f)
+register char	*p;
+register char	*s;
+register FILE	*f;
+{
+	register i;
+	register long l;
+
+	for (;;) {
+		switch (*s++) {
+/*		case '0': p++; continue; */
+		case '1':
+			*p++ = getc(f);
+			continue;
+		case '2':
+			i = getc(f);
+			i |= (getc(f) << 8);
+			*((short *)p) = i; p += sizeof(short);
+			continue;
+		case '4':
+			l = (long)getc(f);
+			l |= ((long)getc(f) << 8);
+			l |= ((long)getc(f) << 16);
+			l |= ((long)getc(f) << 24);
+			*((long *)p) = l; p += sizeof(long);
+			continue;
+		default:
+		case '\0':
+			break;
+		}
+		break;
+	}
+}
Index: /trunk/minix/commands/autil/build
===================================================================
--- /trunk/minix/commands/autil/build	(revision 9)
+++ /trunk/minix/commands/autil/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/autil/obj.h
===================================================================
--- /trunk/minix/commands/autil/obj.h	(revision 9)
+++ /trunk/minix/commands/autil/obj.h	(revision 9)
@@ -0,0 +1,79 @@
+/* $Id: obj.h,v 1.1 2005/06/23 09:50:54 philip Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#include <local.h>
+#include <stdio.h>
+#include <out.h>
+#include <ranlib.h>
+#include <arch.h>
+#include "object.h"
+
+#if ! defined(CHAR_UNSIGNED)
+#define CHAR_UNSIGNED 0
+#endif
+
+#if CHAR_UNSIGNED
+#define Xchar(ch)	(ch)
+#else
+#define Xchar(ch)	((ch) & 0377)
+#endif
+
+#if ! defined(BYTE_ORDER)
+#define BYTE_ORDER 0x3210
+#endif
+
+#if (BYTE_ORDER == 0x3210 || BYTE_ORDER == 0x1032)
+#define uget2(c)	(Xchar((c)[0]) | ((unsigned) Xchar((c)[1]) << 8))
+#define Xput2(i, c)	(((c)[0] = (i)), ((c)[1] = (i) >> 8))
+#define put2(i, c)	{ register int j = (i); Xput2(j, c); }
+#else
+#define uget2(c)	(* ((unsigned short *) (c)))
+#define Xput2(i, c)	(* ((short *) (c)) = (i))
+#define put2(i, c)	Xput2(i, c)
+#endif
+
+#define get2(c)		((short) uget2(c))
+
+#if BYTE_ORDER != 0x0123
+#define get4(c)		(uget2(c) | ((long) uget2((c)+2) << 16))
+#define put4(l, c)	{ register long x=(l); \
+			  Xput2((int)x,c); \
+			  Xput2((int)(x>>16),(c)+2); \
+			}
+#else
+#define get4(c)		(* ((long *) (c)))
+#define put4(l, c)	(* ((long *) (c)) = (l))
+#endif
+
+#define SECTCNT	3	/* number of sections with own output buffer */
+#if BIGMACHINE
+#define WBUFSIZ	(8*BUFSIZ)
+#else
+#define WBUFSIZ	BUFSIZ
+#endif
+
+struct fil {
+	int	cnt;
+	char	*pnow;
+	char	*pbegin;
+	long	currpos;
+	int	fd;
+	char	pbuf[WBUFSIZ];
+};
+
+extern struct fil __parts[];
+
+#define	PARTEMIT	0
+#define	PARTRELO	(PARTEMIT+SECTCNT)
+#define	PARTNAME	(PARTRELO+1)
+#define	PARTCHAR	(PARTNAME+1)
+#ifdef SYMDBUG
+#define PARTDBUG	(PARTCHAR+1)
+#else
+#define PARTDBUG	(PARTCHAR+0)
+#endif
+#define	NPARTS		(PARTDBUG + 1)
+
+#define getsect(s)      (PARTEMIT+((s)>=(SECTCNT-1)?(SECTCNT-1):(s)))
Index: /trunk/minix/commands/autil/object.h
===================================================================
--- /trunk/minix/commands/autil/object.h	(revision 9)
+++ /trunk/minix/commands/autil/object.h	(revision 9)
@@ -0,0 +1,45 @@
+/* $Id: object.h,v 1.1 2005/06/23 09:50:54 philip Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+
+#include <ansi.h>
+
+#ifndef __OBJECT_INCLUDED__
+#define __OBJECT_INCLUDED__
+
+_PROTOTYPE(int wr_open, (char *f));
+_PROTOTYPE(void wr_close, (void));
+_PROTOTYPE(void wr_ohead, (struct outhead *h));
+_PROTOTYPE(void wr_sect, (struct outsect *s, unsigned int c));
+_PROTOTYPE(void wr_outsect, (int sectno));
+_PROTOTYPE(void wr_emit, (char *b, long c));
+_PROTOTYPE(void wr_putc, (int c));
+_PROTOTYPE(void wr_relo, (struct outrelo *r, unsigned int c));
+_PROTOTYPE(void wr_name, (struct outname *n, unsigned int c));
+_PROTOTYPE(void wr_string, (char *s, long c));
+_PROTOTYPE(void wr_arhdr, (int fd, struct ar_hdr *a));
+_PROTOTYPE(void wr_ranlib, (int fd, struct ranlib *r, long cnt));
+_PROTOTYPE(void wr_int2, (int fd, int i));
+_PROTOTYPE(void wr_long, (int fd, long l));
+_PROTOTYPE(void wr_bytes, (int fd, char *buf, long l));
+_PROTOTYPE(int rd_open, (char *f));
+_PROTOTYPE(int rd_fdopen, (int f));
+_PROTOTYPE(void rd_close, (void));
+_PROTOTYPE(void rd_ohead, (struct outhead *h));
+_PROTOTYPE(void rd_sect, (struct outsect *s, unsigned int c));
+_PROTOTYPE(void rd_outsect, (int sectno));
+_PROTOTYPE(void rd_emit, (char *b, long c));
+_PROTOTYPE(void rd_relo, (struct outrelo *r, unsigned int c));
+_PROTOTYPE(void rd_rew_relo, (struct outhead *head));
+_PROTOTYPE(void rd_name, (struct outname *n, unsigned int c));
+_PROTOTYPE(void rd_string, (char *s, long c));
+_PROTOTYPE(int rd_arhdr, (int fd, struct ar_hdr *a));
+_PROTOTYPE(void rd_ranlib, (int fd, struct ranlib *r, long cnt));
+_PROTOTYPE(int rd_int2, (int fd));
+_PROTOTYPE(long rd_long, (int fd));
+_PROTOTYPE(void rd_bytes, (int fd, char *buf, long l));
+_PROTOTYPE(int rd_fd, (void));
+
+#endif /* __OBJECT_INCLUDED__ */
Index: /trunk/minix/commands/autil/out.h
===================================================================
--- /trunk/minix/commands/autil/out.h	(revision 9)
+++ /trunk/minix/commands/autil/out.h	(revision 9)
@@ -0,0 +1,126 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/commands/autil/out.h,v 1.1.1.1 2005/04/21 14:54:10 beng Exp $ */
+
+#ifndef __OUT_H_INCLUDED
+#define __OUT_H_INCLUDED
+/*
+ * output format for ACK assemblers
+ */
+#ifndef ushort
+#define ushort	unsigned short
+#endif /* ushort */
+
+struct outhead {
+	ushort 	oh_magic;	/* magic number */
+	ushort 	oh_stamp;	/* version stamp */
+	ushort	oh_flags;	/* several format flags */
+	ushort	oh_nsect;	/* number of outsect structures */
+	ushort	oh_nrelo;	/* number of outrelo structures */
+	ushort	oh_nname;	/* number of outname structures */
+	long	oh_nemit;	/* sum of all os_flen */
+	long	oh_nchar;	/* size of string area */
+};
+
+#define O_MAGIC	0x0201		/* magic number of output file */
+#define	O_STAMP	0		/* version stamp */
+#define MAXSECT	64		/* Maximum number of sections */
+
+#define	HF_LINK	0x0004		/* unresolved references left */
+#define	HF_8086	0x0008		/* os_base specially encoded */
+
+struct outsect {
+	long 	os_base;	/* startaddress in machine */
+	long	os_size;	/* section size in machine */
+	long	os_foff;	/* startaddress in file */
+	long	os_flen;	/* section size in file */
+	long	os_lign;	/* section alignment */
+};
+
+struct outrelo {
+	char	or_type;	/* type of reference */
+	char	or_sect;	/* referencing section */
+	ushort	or_nami;	/* referenced symbol index */
+	long	or_addr;	/* referencing address */
+};
+
+struct outname {
+	union {
+	  char	*on_ptr;	/* symbol name (in core) */
+	  long	on_off;		/* symbol name (in file) */
+	}	on_u;
+#define on_mptr	on_u.on_ptr
+#define on_foff	on_u.on_off
+	ushort	on_type;	/* symbol type */
+	ushort	on_desc;	/* debug info */
+	long	on_valu;	/* symbol value */
+};
+
+/*
+ * relocation type bits
+ */
+#define RELSZ	0x07		/* relocation length */
+#define RELO1	   1		/* 1 byte */
+#define RELO2	   2		/* 2 bytes */
+#define RELO4	   4		/* 4 bytes */
+#define RELPC	0x08		/* pc relative */
+#define RELBR	0x10		/* High order byte lowest address. */
+#define RELWR	0x20		/* High order word lowest address. */
+
+/*
+ * section type bits and fields
+ */
+#define S_TYP	0x007F		/* undefined, absolute or relative */
+#define S_EXT	0x0080		/* external flag */
+#define S_ETC	0x7F00		/* for symbolic debug, bypassing 'as' */
+
+/*
+ * S_TYP field values
+ */
+#define S_UND	0x0000		/* undefined item */
+#define S_ABS	0x0001		/* absolute item */
+#define S_MIN	0x0002		/* first user section */
+#define S_MAX	(S_TYP-1)	/* last user section */
+#define S_CRS	S_TYP		/* on_valu is symbol index which contains value */
+
+/*
+ * S_ETC field values
+ */
+#define S_SCT	0x0100		/* section names */
+#define S_LIN	0x0200		/* hll source line item */
+#define S_FIL	0x0300		/* hll source file item */
+#define S_MOD	0x0400		/* ass source file item */
+#define S_COM	0x1000		/* Common name. */
+#define S_STB	0xe000		/* entries with any of these bits set are
+				   reserved for debuggers
+				*/
+
+/*
+ * structure format strings
+ */
+#define SF_HEAD		"22222244"
+#define SF_SECT		"44444"
+#define SF_RELO		"1124"
+#define SF_NAME		"4224"
+
+/*
+ * structure sizes (bytes in file; add digits in SF_*)
+ */
+#define SZ_HEAD		20
+#define SZ_SECT		20
+#define SZ_RELO		8
+#define SZ_NAME		12
+
+/*
+ * file access macros
+ */
+#define BADMAGIC(x)	((x).oh_magic!=O_MAGIC)
+#define OFF_SECT(x)	SZ_HEAD
+#define OFF_EMIT(x)	(OFF_SECT(x) + ((long)(x).oh_nsect * SZ_SECT))
+#define OFF_RELO(x)	(OFF_EMIT(x) + (x).oh_nemit)
+#define OFF_NAME(x)	(OFF_RELO(x) + ((long)(x).oh_nrelo * SZ_RELO))
+#define OFF_CHAR(x)	(OFF_NAME(x) + ((long)(x).oh_nname * SZ_NAME))
+
+#endif /* __OUT_H_INCLUDED */
Index: /trunk/minix/commands/autil/ranlib.h
===================================================================
--- /trunk/minix/commands/autil/ranlib.h	(revision 9)
+++ /trunk/minix/commands/autil/ranlib.h	(revision 9)
@@ -0,0 +1,34 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Id: ranlib.h,v 1.1 2005/06/23 09:50:54 philip Exp $ */
+
+#ifndef __RANLIB_H_INCLUDED
+#define __RANLIB_H_INCLUDED
+
+#ifndef SYMDEF
+#	define SYMDEF	"__.SYMDEF"
+#endif /* SYMDEF */
+
+/*
+ * Structure of the SYMDEF table of contents for an archive.
+ * SYMDEF begins with a long giving the number of ranlib
+ * structures that immediately follow, and then continues with a string
+ * table consisting of a long giving the number of bytes of
+ * strings that follow and then the strings themselves.
+ */
+struct ranlib {
+	union {
+	  char	*ran__ptr;	/* symbol name (in core) */
+	  long	ran__off;	/* symbol name (in file) */
+	}	ran_u;
+#define ran_ptr ran_u.ran__ptr
+#define ran_off ran_u.ran__off
+	long	ran_pos;	/* library member is at this position */
+};
+
+#define SZ_RAN	8
+#define SF_RAN	"44"
+
+#endif /* __RANLIB_H_INCLUDED */
Index: /trunk/minix/commands/autil/rd.c
===================================================================
--- /trunk/minix/commands/autil/rd.c	(revision 9)
+++ /trunk/minix/commands/autil/rd.c	(revision 9)
@@ -0,0 +1,260 @@
+/* $Id: rd.c,v 1.1 2005/06/23 09:50:54 philip Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#include "obj.h"
+
+extern long		lseek();
+
+/*
+ * Parts of the output file.
+ */
+#undef PARTEMIT
+#undef PARTRELO
+#undef PARTNAME
+#undef PARTCHAR
+#undef PARTDBUG
+#undef NPARTS
+
+#define	PARTEMIT	0
+#define	PARTRELO	1
+#define	PARTNAME	2
+#define	PARTCHAR	3
+#ifdef SYMDBUG
+#define PARTDBUG	4
+#else
+#define PARTDBUG	3
+#endif
+#define	NPARTS		(PARTDBUG + 1)
+
+static long		offset[MAXSECT];
+
+static int		outfile;
+static long		outseek[NPARTS];
+static long		currpos;
+static long		rd_base;
+#define OUTSECT(i) \
+	(outseek[PARTEMIT] = offset[i])
+#define BEGINSEEK(p, o) \
+	(outseek[(p)] = (o))
+
+static int sectionnr;
+
+static void
+OUTREAD(p, b, n)
+	char *b;
+	long n;
+{
+	register long l = outseek[p];
+
+	if (currpos != l) {
+		lseek(outfile, l, 0);
+	}
+	rd_bytes(outfile, b, n);
+	l += n;
+	currpos = l;
+	outseek[p] = l;
+}
+
+/*
+ * Open the output file according to the chosen strategy.
+ */
+int
+rd_open(f)
+	char *f;
+{
+
+	if ((outfile = open(f, 0)) < 0)
+		return 0;
+	return rd_fdopen(outfile);
+}
+
+static int offcnt;
+
+int
+rd_fdopen(fd)
+{
+	register int i;
+
+	for (i = 0; i < NPARTS; i++) outseek[i] = 0;
+	offcnt = 0;
+	rd_base = lseek(fd, 0L, 1);
+	if (rd_base < 0) {
+		return 0;
+	}
+	currpos = rd_base;
+	outseek[PARTEMIT] = currpos;
+	outfile = fd;
+	sectionnr = 0;
+	return 1;
+}
+
+void
+rd_close()
+{
+
+	close(outfile);
+	outfile = -1;
+}
+
+int
+rd_fd()
+{
+	return outfile;
+}
+
+void
+rd_ohead(head)
+	register struct outhead	*head;
+{
+	register long off;
+
+	OUTREAD(PARTEMIT, (char *) head, (long) SZ_HEAD);
+#if BYTE_ORDER == 0x0123
+	if (sizeof(struct outhead) != SZ_HEAD)
+#endif
+	{
+		register char *c = (char *) head + (SZ_HEAD-4);
+		
+		head->oh_nchar = get4(c);
+		c -= 4; head->oh_nemit = get4(c);
+		c -= 2; head->oh_nname = uget2(c);
+		c -= 2; head->oh_nrelo = uget2(c);
+		c -= 2; head->oh_nsect = uget2(c);
+		c -= 2; head->oh_flags = uget2(c);
+		c -= 2; head->oh_stamp = uget2(c);
+		c -= 2; head->oh_magic = uget2(c);
+	}
+	off = OFF_RELO(*head) + rd_base;
+	BEGINSEEK(PARTRELO, off);
+	off += (long) head->oh_nrelo * SZ_RELO;
+	BEGINSEEK(PARTNAME, off);
+	off += (long) head->oh_nname * SZ_NAME;
+	BEGINSEEK(PARTCHAR, off);
+#ifdef SYMDBUG
+	off += head->oh_nchar;
+	BEGINSEEK(PARTDBUG, off);
+#endif
+}
+
+void
+rd_rew_relos(head)
+	register struct outhead *head;
+{
+	register long off = OFF_RELO(*head) + rd_base;
+
+	BEGINSEEK(PARTRELO, off);
+}
+
+void
+rd_sect(sect, cnt)
+	register struct outsect	*sect;
+	register unsigned int	cnt;
+{
+	register char *c = (char *) sect + cnt * SZ_SECT;
+
+	OUTREAD(PARTEMIT, (char *) sect, (long)cnt * SZ_SECT);
+	sect += cnt;
+	offcnt += cnt;
+	while (cnt--) {
+		sect--;
+#if BYTE_ORDER == 0x0123
+		if (sizeof(struct outsect) != SZ_SECT)
+#endif
+		{
+			c -= 4; sect->os_lign = get4(c);
+			c -= 4; sect->os_flen = get4(c);
+			c -= 4; sect->os_foff = get4(c);
+			c -= 4; sect->os_size = get4(c);
+			c -= 4; sect->os_base = get4(c);
+		}
+		offset[--offcnt] = sect->os_foff + rd_base;
+	}
+}
+
+void
+rd_outsect(s)
+{
+	OUTSECT(s);
+	sectionnr = s;
+}
+
+/*
+ * We don't have to worry about byte order here.
+ */
+void
+rd_emit(emit, cnt)
+	char		*emit;
+	long		cnt;
+{
+	OUTREAD(PARTEMIT, emit, cnt);
+	offset[sectionnr] += cnt;
+}
+
+void
+rd_relo(relo, cnt)
+	register struct outrelo	*relo;
+	register unsigned int cnt;
+{
+
+	OUTREAD(PARTRELO, (char *) relo, (long) cnt * SZ_RELO);
+#if BYTE_ORDER == 0x0123
+	if (sizeof(struct outrelo) != SZ_RELO)
+#endif
+	{
+		register char *c = (char *) relo + (long) cnt * SZ_RELO;
+
+		relo += cnt;
+		while (cnt--) {
+			relo--;
+			c -= 4; relo->or_addr = get4(c);
+			c -= 2; relo->or_nami = uget2(c);
+			relo->or_sect = *--c;
+			relo->or_type = *--c;
+		}
+	}
+}
+
+void
+rd_name(name, cnt)
+	register struct outname	*name;
+	register unsigned int cnt;
+{
+
+	OUTREAD(PARTNAME, (char *) name, (long) cnt * SZ_NAME);
+#if BYTE_ORDER == 0x0123
+	if (sizeof(struct outname) != SZ_NAME)
+#endif
+	{
+		register char *c = (char *) name + (long) cnt * SZ_NAME;
+
+		name += cnt;
+		while (cnt--) {
+			name--;
+			c -= 4; name->on_valu = get4(c);
+			c -= 2; name->on_desc = uget2(c);
+			c -= 2; name->on_type = uget2(c);
+			c -= 4; name->on_foff = get4(c);
+		}
+	}
+}
+
+void
+rd_string(addr, len)
+	char *addr;
+	long len;
+{
+	
+	OUTREAD(PARTCHAR, addr, len);
+}
+
+#ifdef SYMDBUG
+void
+rd_dbug(buf, size)
+	char		*buf;
+	long		size;
+{
+	OUTREAD(PARTDBUG, buf, size);
+}
+#endif
Index: /trunk/minix/commands/autil/rd_arhdr.c
===================================================================
--- /trunk/minix/commands/autil/rd_arhdr.c	(revision 9)
+++ /trunk/minix/commands/autil/rd_arhdr.c	(revision 9)
@@ -0,0 +1,34 @@
+/* $Id: rd_arhdr.c,v 1.1 2005/06/23 09:50:54 philip Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#include "obj.h"
+
+int
+rd_arhdr(fd, arhdr)
+	register struct ar_hdr	*arhdr;
+{
+	char buf[AR_TOTAL];
+	register char *c = buf;
+	register char *p = arhdr->ar_name;
+	register int i;
+
+	i = read(fd, c, AR_TOTAL);
+	if (i == 0) return 0;
+	if (i != AR_TOTAL) {
+		rd_fatal();
+	}
+	i = 14;
+	while (i--) {
+		*p++ = *c++;
+	}
+	arhdr->ar_date = ((long) get2(c)) << 16; c += 2;
+	arhdr->ar_date |= ((long) get2(c)) & 0xffff; c += 2;
+	arhdr->ar_uid = *c++;
+	arhdr->ar_gid = *c++;
+	arhdr->ar_mode = get2(c); c += 2;
+	arhdr->ar_size = (long) get2(c) << 16; c += 2;
+	arhdr->ar_size |= (long) get2(c) & 0xffff;
+	return 1;
+}
Index: /trunk/minix/commands/autil/rd_bytes.c
===================================================================
--- /trunk/minix/commands/autil/rd_bytes.c	(revision 9)
+++ /trunk/minix/commands/autil/rd_bytes.c	(revision 9)
@@ -0,0 +1,35 @@
+/* $Id: rd_bytes.c,v 1.1 2005/06/23 09:50:54 philip Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+
+#include "obj.h"
+
+#define MININT		(1 << (sizeof(int) * 8 - 1))
+#define MAXCHUNK	(~MININT)	/* Highest count we read(2).	*/
+/* Unfortunately, MAXCHUNK is too large with some  compilers. Put it in
+   an int!
+*/
+
+static int maxchunk = MAXCHUNK;
+
+/*
+ * We don't have to worry about byte order here.
+ * Just read "cnt" bytes from file-descriptor "fd".
+ */
+void 
+rd_bytes(fd, string, cnt)
+	register char	*string;
+	register long	cnt;
+{
+
+	while (cnt) {
+		register int n = cnt >= maxchunk ? maxchunk : cnt;
+
+		if (read(fd, string, n) != n)
+			rd_fatal();
+		string += n;
+		cnt -= n;
+	}
+}
Index: /trunk/minix/commands/autil/rd_unsig2.c
===================================================================
--- /trunk/minix/commands/autil/rd_unsig2.c	(revision 9)
+++ /trunk/minix/commands/autil/rd_unsig2.c	(revision 9)
@@ -0,0 +1,15 @@
+/* $Id: rd_unsig2.c,v 1.1 2005/06/23 09:50:54 philip Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#include "obj.h"
+
+unsigned int
+rd_unsigned2(fd)
+{
+	char buf[2];
+
+	rd_bytes(fd, buf, 2L);
+	return uget2(buf);
+}
Index: /trunk/minix/commands/awk/Makefile
===================================================================
--- /trunk/minix/commands/awk/Makefile	(revision 9)
+++ /trunk/minix/commands/awk/Makefile	(revision 9)
@@ -0,0 +1,30 @@
+# Makefile for awk.
+
+CC = exec cc
+CFLAGS	= -D_MINIX -D_POSIX_SOURCE -wo -w
+LDFLAGS	= -i -f
+
+OBJS = m.o e.o n.o l.o r.o v.o y.o regexp.o k.o
+
+all:	awk
+
+awk:	$(OBJS)
+	$(CC) $(LDFLAGS) -o $@ $(OBJS) #-lm
+	install -S 32kw $@
+
+install:	/usr/bin/awk
+
+/usr/bin/awk:	awk
+	install -cs -o bin $? $@
+
+clean:
+	rm -f awk *.o a.out *.bak core
+
+e.o:	awk.h regexp.h
+l.o:	awk.h
+m.o:	awk.h
+n.o:	awk.h
+r.o:	awk.h regexp.h
+regexp.o:	regexp.h
+v.o:	awk.h regexp.h
+y.o:	awk.h
Index: /trunk/minix/commands/awk/NOTE
===================================================================
--- /trunk/minix/commands/awk/NOTE	(revision 9)
+++ /trunk/minix/commands/awk/NOTE	(revision 9)
@@ -0,0 +1,38 @@
+a small AWK clone
+
+	±ÌvOÍAMinix 1.2 pÉ¢œàÌÅ·B®¬_Zðg¢
+Ü·©çAMinix 1.5 ÈOÌ ACK-C ÅÍRpCÅ«Ü¹ñB»Ìœß makefile 
+ÅÍAPeter S. Housel³ñÌ®¬_pbP[Wðg€æ€ÉÈÁÄ¢Ü·B
+CFLAGS Ì -f ªA»ÌwŠÅ·B±Ì®¬_pbP[WÍAñíÉæ­Å«Ä
+¢Ü·ªAatan(x, y) Ìø«ÌªtÉÈÁÄ¢Ü·ÌÅAC³µÄš¢Ä­
+Ÿ³¢BŒÉàœ© Áœæ€ÈL¯ª èÜ·ªAYêÄµÜ¢ÜµœBàµAœ
+©âèª éæ€ÅµœçA²A¢œŸ¯êÎAª©ªÅgÁÄ¢éàÌðö\
+·éæ€ÉµÜ·B
+
+	±ÌvOÍAShift-JIS Ì¿R[hðµ€æ€ÉÈÁÄ¢Ü·B
+
+EUC ÉÎ³¹éêÍA³K\»Ìµ¢A¿R[hÉÖW·éªÌ·ªK
+vÅ·ªAåµœèÔÅÍ èÜ¹ñBÇÈœ©ÏX³êœêÍApb`ðpÓµ
+Ä¢œŸ¯éÆðµ¢Å·B
+
+	ÍAÌÌ awk ÌdlÉÈÁÄ¢ÜµœªAuAWK Programming Languagev
+ªoÅ³êAPOSIX 1003.2 Ì draft Åà nawk dlªÌp³êœÌð@ïÉAnawk 
+ÌdlÉ«·ŠÜµœBIWiÌ awk ÆáÁÄAparser à lexical analizer 
+à hand maid Å·©çA64K+64K ÌÉûÜÁÄ¢Ü·B
+
+	{ÍAMinix çµ¢A³ÞIÈvOÉ·×«Å·µA»€µœ©Á
+œÌÅ·ªAàÆàÆA©ªœ¿ªg€œßÉAàÆçžÉXN[ð©Èª
+ç¢ÄµÜÁœœßA«ê¢ÈR[fBOÉÈÁÄ¢Ü¹ñBµ©µA64K+64K 
+ÌÅgŠé awk ªŒÉ èÜ¹ñÌÅAÆè Šž»sÌóÔÅöJµÄš­
+±ÆÉµÜµœB
+
+	vO»ÌàÌÍA³K\»Ì]¿ÉË¶·éàÌð¢ÄAuAWK 
+Programming LanguagevÉfÚ³êÄ¢éeXgvOÉÊé±ÆðmFµÄ 
+èÜ·B
+
+
+	32-bit Minix ÌêÍAAT&T IWiÌ awk Æ© gawk, mawk Æ¢Áœ
+vOªgŠÜ·ªA®¬_ðT|[gµœAc386 Å±ÌvOðR
+pC·é±ÆàÅ«Ü·B
+
+œÑ _ê (kh@hiraide.mogami-wire.co.jp)  1995-01-29
Index: /trunk/minix/commands/awk/README
===================================================================
--- /trunk/minix/commands/awk/README	(revision 9)
+++ /trunk/minix/commands/awk/README	(revision 9)
@@ -0,0 +1,13 @@
+A small AWK clone for the 16-bit Minix
+
+	We have written this program for the Minix 1.2 to fit into 64K+64K
+memory.  When compiling this program, you need the Peter S. Housel's 
+Floating Math Package with corrected the atan() function.  Original atan()
+function has incorrect argument sequence.
+
+	This program supports Japanese Shift-JIS KANJI code and passes
+all the test program of the "AWK programming language" written by original
+AWK authors except some programs relied upon the way of regular expression 
+evaluation.
+
+Kouichi Hirabayashi (kh@mogami-wire.co.jp)
Index: /trunk/minix/commands/awk/awk.h
===================================================================
--- /trunk/minix/commands/awk/awk.h	(revision 9)
+++ /trunk/minix/commands/awk/awk.h	(revision 9)
@@ -0,0 +1,186 @@
+/*
+ * a small awk clone
+ *
+ * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
+ *
+ * Absolutely no warranty. Use this software with your own risk.
+ *
+ * Permission to use, copy, modify and distribute this software for any
+ * purpose and without fee is hereby granted, provided that the above
+ * copyright and disclaimer notice.
+ *
+ * This program was written to fit into 64K+64K memory of the Minix 1.2.
+ */
+
+/* lexical/parser tokens and executable statements */
+
+#define FIRSTP	256
+#define ARG	256
+#define ARITH	257
+#define ARRAY	258
+#define ASSIGN	259
+#define CALL	260
+#define CAT	261
+#define COND	262
+#define DELETE	263
+#define DO	264
+#define ELEMENT	265
+#define FIELD	266
+#define FOR	267
+#define FORIN	268
+#define GETLINE	269
+#define IF	270
+#define IN	271
+#define JUMP	272
+#define MATHFUN	273
+#define NULPROC	274
+#define P1STAT	275
+#define P2STAT	276
+#define PRINT	277
+#define PRINT0	278
+#define STRFUN	279
+#define SUBST	280
+#define USRFUN	281
+#define WHILE	282
+#define LASTP	282
+	/* lexical token */
+
+#define ADD	300	/* + */
+#define ADDEQ	301	/* += */
+#define AND	302	/* && */
+#define BEGIN	303	/* BEGIN */
+#define BINAND	304	/* & */
+#define BINOR	305	/* | */
+#define BREAK	306	/* break */
+#define CLOSE	307	/* close */
+#define CONTIN	308	/* continue */
+#define DEC	309	/* -- */
+#define DIV	310	/* / */
+#define DIVEQ	311	/* /= */
+#define	ELSE	312	/* else */
+#define END	313	/* END */
+#define EOL	314	/* ; or '\n' */
+#define EQ	315	/* == */
+#define EXIT	316	/* exit */
+#define FUNC	317	/* function */
+#define GE	318	/* >= */
+#define GT	319	/* > */
+#define IDENT	320	/* identifier */
+#define INC	321	/* ++ */
+#define LE	322	/* <= */
+#define LT	323	/* < */
+#define MATCH	324	/* ~ */
+#define MOD	325	/* % */
+#define MODEQ	326	/* %= */
+#define MULT	327	/* * */
+#define MULTEQ	328	/* *= */
+#define NE	329	/* != */
+#define NEXT	330	/* next */
+#define NOMATCH	331	/* !~ */
+#define NOT	332	/* ! */
+#define NUMBER	333	/* integer or floating number */
+#define OR	334	/* || */
+#define POWEQ	335	/* ^= */
+#define POWER	336	/* ^ */
+#define PRINTF	337	/* printf */
+#define REGEXP	338	/* /REG/ */
+#define RETURN	339	/* return */
+#define SHIFTL	340	/* << */
+#define SHIFTR	341	/* >> */
+#define SPRINT	342	/* sprint */
+#define SPRINTF	343	/* sprintf */
+#define STRING	344	/* ".." */
+#define SUB	345	/* - */
+#define SUBEQ	346	/* -= */
+#define SYSTEM	347	/* system */
+#define UMINUS	348	/* - */
+
+/* tokens in parser */
+
+#define VALUE	400	/* value node */
+#define INCDEC	401	/* ++, -- */
+#define PRE	402	/* pre incre/decre */
+#define POST	403	/* post incre/decre */
+
+/* redirect in print(f) statement */
+
+#define R_OUT	410	/* > */
+#define R_APD	411	/* >> */
+#define R_PIPE	412	/* | */
+#define R_IN	413	/* < */
+#define R_PIN	414	/* | getline */
+#define R_POUT	415	/* print | */
+
+/* function */
+
+#define ATAN2	500	/* atan2 */
+#define COS	501	/* cos */
+#define EXP	502	/* exp */
+#define INDEX	503	/* index */
+#define INT	504	/* int */
+#define LENGTH	505	/* length */
+#define LOG	506	/* log */
+#define RAND	507	/* rand */
+#define RGSUB	508	/* gsub */
+#define RMATCH	509	/* match */
+#define RSUB	510	/* sub */
+#define SIN	511	/* sin */
+#define SPLIT	512	/* split */
+#define SQRT	513	/* sqrt */
+#define SRAND	514	/* srand */
+#define SUBSTR	515	/* substr */
+
+/* print(f) options */
+
+#define FORMAT	1024	/* PRINTF, SPRINTF */
+#define STROUT	2048	/* SPRINTF */
+#define PRMASK	0x3ff	/* ~(FORMAT|STROUT) */
+
+	/* node - used in parsed tree */
+
+struct node {
+  int n_type;			/* node type */
+  struct node *n_next;		/* pointer to next node */
+  struct node *n_arg[1];	/* argument (variable length) */
+};
+
+typedef struct node NODE;
+
+	/* object cell */
+
+struct cell {
+  int c_type;		/* cell type */
+  char *c_sval;		/* string value */
+  double c_fval;	/* floating value */
+};
+
+typedef struct cell CELL;
+
+	/* cell type */
+
+#define UDF	0	/* pass parameter */
+#define VAR	1	/* variable */
+#define NUM	2	/* number */
+#define ARR	4	/* array */
+#define STR	8	/* string */
+#define REC	16	/* record */
+#define FLD	32	/* filed */
+#define PAT	64	/* pattern (compiled REGEXPR) */
+#define BRK	128	/* break */
+#define CNT	256	/* continue */
+#define NXT	512	/* next */
+#define EXT	1024	/* exit */
+#define RTN	2048	/* return */
+#define TMP	4096	/* temp cell */
+#define POS	8192	/* argument position */
+#define FUN	16384	/* function */
+
+	/* symbol cell - linked to symbol table */
+
+struct symbol {
+  char *s_name;
+  CELL *s_val;
+  struct symbol *s_next;
+};
+
+typedef struct symbol SYMBOL;
Index: /trunk/minix/commands/awk/build
===================================================================
--- /trunk/minix/commands/awk/build	(revision 9)
+++ /trunk/minix/commands/awk/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/awk/e.c
===================================================================
--- /trunk/minix/commands/awk/e.c	(revision 9)
+++ /trunk/minix/commands/awk/e.c	(revision 9)
@@ -0,0 +1,952 @@
+/*
+ * a small awk clone
+ *
+ * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
+ *
+ * Absolutely no warranty. Use this software with your own risk.
+ *
+ * Permission to use, copy, modify and distribute this software for any
+ * purpose and without fee is hereby granted, provided that the above
+ * copyright and disclaimer notice.
+ *
+ * This program was written to fit into 64K+64K memory of the Minix 1.2.
+ */
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include "awk.h"
+#include "regexp.h"
+
+extern char **FS, **OFS, **ORS, **OFMT;
+extern double *RSTART, *RLENGTH;
+extern char record[];
+extern CELL *field[];
+
+extern int r_start, r_length;
+
+double getfval(), atof();
+char *strsave(), *getsval(), *strcat(), *strstr();
+CELL *mkcell(), *mktmp();
+CELL *Field(), *Split(), *Forin();
+CELL *Arith(), *Assign(), *Stat(), *Mathfun(), *Strfun(), *Cond();
+CELL *Print(), *Cat(), *Array(), *Element();
+CELL *If(), *While(), *For(), *Do(), *Jump();
+CELL *P1stat(), *P2stat(), *Print0();
+CELL *Arg(), *Call(), *Ret();
+CELL *Subst(), *In(), *Getline(), *Delete(), *Close();
+CELL *Nulproc(), *Usrfun();
+CELL *_Arg();
+
+FILE *getfp();	/* r.c */
+
+CELL truecell = { NUM, NULL, 1.0 };
+CELL falsecell = { NUM, NULL, 0.0 };
+static CELL breakcell = { BRK, NULL, 0.0 };
+static CELL contcell = { CNT, NULL, 0.0 };
+static CELL nextcell = { NXT, NULL, 0.0 };
+static CELL retcell = { RTN, NULL, 0.0 };
+
+static CELL *retval;	/* function return value */
+
+int pateval;	/* used in P1STAT & P2STAT */
+static char *r_str;	/* STR in 'str ~ STR */
+static regexp *r_pat;	/* compiled pattern for STR */
+
+CELL *(*proctab[])() = {
+  Arg, Arith, Array, Assign, Call, Cat, Cond, Delete, Do, Element,
+  Field, For, Forin, Getline, If, In, Jump, Mathfun, Nulproc, P1stat,
+  P2stat, Print, Print0, Strfun, Subst, Usrfun, While
+};
+
+CELL *
+execute(p) NODE *p;
+{
+  int type, i;
+  CELL *r, *(*proc)();
+
+  type = p->n_type;
+  if (type == VALUE) {
+	if ((r = (CELL *) p->n_arg[0])->c_type & PAT && pateval) {
+		i = match(r->c_sval, (char *)record) ? 1 : 0;
+		r = mktmp(NUM, NULL, (double) i);
+	}
+	return r;
+  }
+  for ( ; p != NULL; p = p->n_next) {
+#if 0
+	if (p->n_type == VALUE) continue;	/* neglect */
+#endif
+/*
+	switch ((int) p->n_type) {
+	case ARRAY:
+		r = Array(p);
+		break;
+	case ARITH:
+		r = Arith(p);
+		break;
+	case ASSIGN:
+		r = Assign(p);
+		break;
+	case PRINT:
+		r = Print(p);
+		break;
+	case PRINT0:
+		r = Print0(p);
+		break;
+	case CAT:
+		r = Cat(p);
+		break;
+	case MATHFUN:
+		r = Mathfun(p);
+		break;
+	case STRFUN:
+		r = Strfun(p);
+		break;
+	case COND:
+		r = Cond(p);
+		break;
+	case IF:
+		r = If(p);
+		break;
+	case P1STAT:
+		r = P1stat(p);
+		break;
+	case P2STAT:
+		r = P2stat(p);
+		break;
+	case WHILE:
+		r = While(p);
+		break;
+	case DO:
+		r = Do(p);
+		break;
+	case FOR:
+		r = For(p);
+		break;
+	case FORIN:
+		r = Forin(p);
+		break;
+	case FIELD:
+		r = Field(p);
+		break;
+	case JUMP:
+		r = Jump(p);
+		break;
+	case ARG:
+		r = Arg(p);
+		break;
+	case CALL:
+		r = Call(p);
+		break;
+	case SUBST:
+		r = Subst(p);
+		break;
+	case ELEMENT:
+		r = Element(p);
+		break;
+	case IN:
+		r = In(p);
+		break;
+	case GETLINE:
+		r = Getline(p);
+		break;
+	case DELETE:
+		r = Delete(p);
+		break;
+	case NULPROC:
+		r = &truecell;
+		break;
+	default:
+		printf("PROGRAM ERROR ? ILLEGAL NODE TYPE(%d)\n", type);
+		exit(1);
+		break;
+	}
+*/
+	i = (int) p->n_type;
+	if (i < FIRSTP || i > LASTP)
+		error("ILLEGAL PROC (%d)", i);
+	proc = proctab[i - FIRSTP];
+	r = (*proc)(p);
+	if (r->c_type & (BRK|CNT|NXT|RTN))
+		return r;
+	if (p->n_next != NULL)
+		c_free(r);
+#ifdef DOS
+	kbhit();	/* needs in MS-DOS */
+#endif
+  }
+  return r;
+}
+
+static CELL *
+Arith(p) NODE *p;
+{
+  int op;
+  CELL *r, *u, *v, *execute();
+  double x, y, fmod(), pow();
+
+  op = (int) p->n_arg[0];
+  if (op == UMINUS) {
+	u = execute(p->n_arg[1]);
+	x = - getfval(u);
+  }
+  else if (op == INCDEC) {
+	u = execute(p->n_arg[1]);
+	x = getfval(u);
+	setfval(u, x + (int) p->n_arg[2]);
+	if ((int) p->n_arg[3] == PRE)
+		return u;
+	/* return dummy */
+  }
+  else {
+	u = execute(p->n_arg[1]);
+	v = execute(p->n_arg[2]);
+	x = getfval(u);
+	y = getfval(v);
+	if (op == DIV || op == MOD) {
+		if (y == 0.0)
+			fprintf(stderr, "divid by 0\n");
+	}
+	switch (op) {
+	case SUB: x -= y;break;
+	case ADD: x += y; break;
+	case MULT: x *= y; break;
+	case DIV:
+		if (y == 0.0)
+			error("division by zero in \"/\"", (char *)0);
+		x /= y; break;
+	case MOD:
+		if (y == 0.0)
+			error("division by zero in \"%%\"", (char *)0);
+		x = fmod(x, y); break;
+	case POWER: x = pow(x, y); break;
+	default: printf("UNSUPPORTED ARITH OPERATOR !\n"); break;
+	}
+	c_free(v);
+  }
+  c_free(u);
+  r = mktmp(NUM, NULL, x);
+  return r;
+}
+
+static CELL *
+Assign(p) NODE *p;
+{
+  CELL *u, *v, *execute();
+  int op;
+  double x, y, fmod(), pow();
+
+  op = (int) p->n_arg[0];
+  u = execute(p->n_arg[1]);
+
+#if 0
+  if (u->c_type == UDF)	/* fix up local var */
+	u->c_type |= VAR|STR;
+#endif
+  if (!(u->c_type & (VAR|FLD|REC)) && (u->c_type != UDF))
+	fprintf(stderr, "ASSIGN TO NON VARIABLE (%d)\n", u->c_type);
+  v = execute(p->n_arg[2]);
+
+  if (u == v)
+	goto rtn;	/* same node */
+
+  if (op == ASSIGN) {
+	if (v->c_type & NUM/* || isnum(v->c_sval)*/)
+		setfval(u, getfval(v));
+	else
+		setsval(u, getsval(v));
+  }
+  else {
+	x = getfval(u);
+	y = getfval(v);
+	switch (op) {
+	case ADDEQ:	x += y; break;
+	case SUBEQ:	x -= y; break;
+	case MULTEQ:	x *= y; break;
+	case DIVEQ:
+		if (y == 0.0)
+			error("division by zero in \"/=\"", (char *)0);
+		x /= y; break;
+	case MODEQ:
+		if (y == 0.0)
+			error("division by zero in \"%=\"", (char *)0);
+		x = fmod(x, y); break;
+	case POWEQ:	x = pow(x, y); break;
+	default:
+		synerr("illegal assign op (%d)", op);
+		break;
+	}
+	setfval(u, x);
+  }
+rtn:
+  c_free(v);
+  return u;
+}
+
+static CELL *
+Cat(p) NODE *p;
+{
+  CELL *u;
+  char *s, *t, str[BUFSIZ];
+
+  u = execute(p->n_arg[0]);
+  s = getsval(u);
+  for (t = str; *s; )
+	*t++ = *s++;
+  c_free(u);
+  u = execute(p->n_arg[1]);
+  s = getsval(u);
+  while (*s)
+	*t++ = *s++;
+  c_free(u);
+  *t = '\0';
+ return mktmp(STR, str, 0.0);
+}
+
+static CELL *
+Print(p) NODE *p;
+{
+  register int i, redir, typ;
+  CELL *u;
+  char *s, str[BUFSIZ];
+  char *file;
+  FILE *fp;
+
+  redir = (int) p->n_arg[0];
+  if (typ = redir & PRMASK) {	/* redirect */
+	u = execute(p->n_arg[1]);
+	file = getsval(u);
+	if (typ == R_PIPE)
+		typ = R_POUT;
+	fp = getfp(file, typ);
+	c_free(u);
+  }
+  else
+	fp = stdout;
+  if (redir & FORMAT)	/* format */
+	format(str, p);
+  else {
+	*str = '\0';
+	for (i = 2; p->n_arg[i] != NULL; i++) {
+		if (i > 2)
+			strcat(str, *OFS);
+		u = execute(p->n_arg[i]);
+		s = getsval(u);
+		strcat(str, s);
+		c_free(u);
+	}
+	strcat(str, *ORS);
+  }
+  if (redir & STROUT)	/* sprintf */
+	return mktmp(STR, str, 0.0);
+  fputs(str, fp);
+  fflush(fp);
+  return &truecell;
+}
+
+static CELL *
+Mathfun(p) NODE *p;
+{
+  CELL *u, *v;
+  double x, y;
+  double atan2(), cos(), exp(), log(), sin(), sqrt(), modf();
+
+  if ((int) p->n_arg[1] == 0) {
+	u = NULL;
+	x = 0.0;
+  }
+  else {
+	u = execute(p->n_arg[2]);
+	x = getfval(u);
+  }
+  switch ((int) p->n_arg[0]) {
+  case ATAN2:
+	if ((int) p->n_arg[1] == 2) {
+		v = execute(p->n_arg[3]);
+		y = getfval(v);
+		x = atan2(x, y);
+		c_free(v);
+	}
+	else
+		x = 0.0;
+	break;
+  case COS:	x = cos(x); break;
+  case EXP:	x = exp(x); break;
+  case INT:	y = modf(x, &x); break;
+  case LOG:	x = log(x); break;
+  case SIN:	x = sin(x); break;
+  case SQRT:	x = sqrt(x); break;
+  case RAND:	x = (double) rand() / 32768.0; break;
+  case SRAND:	if (x == 0.0)
+			x = (double) time(0);
+		x = (double) srand((int) x);
+		break;
+  default:
+	fprintf(stderr, "unknown math function (%d)\n", p->n_arg[2]);
+	break;
+  }
+  if (u != NULL)
+	c_free(u);
+  return mktmp(NUM, NULL, x);
+}
+
+static CELL *
+Strfun(p) NODE *p;
+{
+  CELL *u, *v, *r;
+  char *s, *t, str[BUFSIZ];
+  int i, m, n;
+  double x;
+  regexp *pat, *getpat();
+
+  n = (int) p->n_arg[1];
+  if (n > 0 && (int) p->n_arg[0] != SPLIT) {
+	u = execute(p->n_arg[2]);
+	s = getsval(u);
+  }
+  else {
+	s = "";
+	u = NULL;
+  }
+  switch ((int) p->n_arg[0]) {
+  case INDEX:
+	if (n > 1) {
+		v = execute(p->n_arg[3]);
+		t = getsval(v);
+		i = Index(s, t);
+		c_free(v);
+	}
+	else
+		i = 0;
+	r = mktmp(NUM, NULL, (double) i);
+	break;
+  case LENGTH:
+	i = (n > 0) ? jstrlen(s) : jstrlen(record);
+	r = mktmp(NUM, NULL, (double) i);
+	break;
+  case SPLIT:
+	r = Split(p);
+	break;
+  case SUBSTR:
+	if (n > 1) {
+		v = execute(p->n_arg[3]);
+		m = (int) getfval(v) - 1;
+		c_free(v);
+	}
+	else
+		m = 0;
+	if (n > 2) {
+		v = execute(p->n_arg[4]);
+		n = (int) getfval(v);
+		c_free(v);
+	}
+	else
+		n = jstrlen(s) - m;
+	for (t = str; *s && m-- > 0; s++)
+		if (isKanji(*s))
+			s++;
+	while (*s && n-- > 0) {
+		if (isKanji(*s))
+			*t++ = *s++;
+		*t++ = *s++;
+	}
+	*t = '\0';
+	r = mktmp(STR, str, 0.0);
+	break;
+  case RMATCH:
+	if (n > 1) {
+		v = execute(p->n_arg[3]);
+		pat = getpat(v);
+		match(pat, s);
+		c_free(v);
+		if (r_start) {	/* change only if match */
+			*RSTART = (double) r_start;
+			*RLENGTH = (double) r_length;
+		}
+		r = mktmp(NUM, NULL, (double) r_start);
+	}
+	else
+		error("missing regexpr in match(str, regexpr)");
+	break;
+  case CLOSE:
+	r = Close(s);
+	break;
+  case SYSTEM:
+	r = mktmp(NUM, NULL, system(s) == -1 ? 0.0 : 1.0);
+	break;
+  default:
+	fprintf(stderr, "unknown string function");
+	break;
+  }
+  c_free(u);
+  return r;
+}
+
+static regexp *
+getpat(r) CELL *r;
+{
+  regexp *pat, *mkpat();
+
+  if (r->c_type & PAT)
+	pat = (regexp *) r->c_sval;
+  else {
+	if (r_str && strcmp(r_str, r->c_sval) == 0)
+		pat = r_pat;
+	else {
+		sfree(r_str); sfree(r_pat);
+		r_str = strsave(getsval(r));
+		pat = r_pat = mkpat(r_str);
+	}
+  }
+  return pat;
+}
+
+static CELL *
+Subst(p) NODE *p;
+{
+  CELL *u, *v, *w;
+  char *s, *t, *r, str[BUFSIZ], *strcpy();
+  int i, n;
+
+  n = (int) p->n_arg[1];
+  if (n > 1) {
+	u = execute(p->n_arg[3]);	/* substitute string */
+	s = getsval(u);
+	v = execute(p->n_arg[2]);	/* expr */
+	if (n > 2) {
+		w = execute(p->n_arg[4]);
+		t = getsval(w);
+		r = str;
+	}
+	else {
+		t = r = record;
+		w = NULL;
+	}
+	i = (int) p->n_arg[0] == RGSUB ? 0 : 1;
+	if (v->c_type & (PAT|STR))
+		i = Sub(r, v->c_sval, (v->c_type & STR), s, t, i);
+	else
+		error("[g]sub(PAT, .. ) must be /../ or string (%d)",
+			w->c_type);
+	if (n > 2) {
+		if (w->c_type & REC) {
+			strcpy(record, str);
+			mkfld(record, *FS, field);
+		}
+		else
+			setsval(w, str);
+	}
+	else
+		mkfld(record, *FS, field);
+	c_free(u);
+	c_free(v);
+	c_free(w);
+  }
+  else
+	i = 0;
+  return mktmp(NUM, NULL, (double) i);
+}
+
+static CELL *
+Cond(p) NODE *p;
+{
+  CELL *u, *v;
+  double x, y;
+  int op, i, j;
+  char *s;
+  int save = pateval;
+
+  op = (int) p->n_arg[0];
+  u = execute(p->n_arg[1]);
+  x = getfval(u);
+/*
+printf("Cond(%d)(%s)\n", u->c_type, u->c_sval);
+*/
+  if (op == AND || op == OR || op == NOT) {
+	if (u->c_type & NUM)
+		i = (x != 0.0);
+	else {
+		s = getsval(u);
+		i = (s != (char *)NULL) && (*s != '\0');
+	}
+  }
+  if (op == AND && !i) {
+	c_free(u);
+	return &falsecell;
+  }
+  if (op == OR && i) {
+	c_free(u);
+	return &truecell;
+  }
+  if (op == NOT)
+	i = i == 0 ? 1 : 0;
+  else {
+	if (op == MATCH || op == NOMATCH)
+		pateval = 0;
+	v = execute(p->n_arg[2]);
+	y = getfval(v);
+	if (op == AND || op == OR || op == BINAND || op == BINOR) {
+		if (v->c_type & NUM)
+			j = (y != 0.0);
+		else {
+			s = getsval(v);
+			j = (s != (char *)NULL) && (*s != '\0');
+		}
+		switch (op) {
+		case AND:	i = i && j; break;
+		case OR:	i = i || j; break;
+		case BINAND:	i = i & j; break;
+		case BINOR:	i = i | j; break;
+		}
+	}
+	else if (op == MATCH || op == NOMATCH) {
+		char *s;
+		regexp *pat, *getpat();
+
+		s = getsval(u);
+		pat = getpat(v);
+		i = match(pat, s) == 0 ? 0 : 1;
+		if (op == NOMATCH)
+			i = i == 0 ? 1 : 0;
+	}
+	else {	/* relative operator */
+/*
+printf("Cond(%d)(%d)(%s)(%s)\n", u->c_type, v->c_type, u->c_sval, v->c_sval);
+*/
+		if ((u->c_type & NUM) && (v->c_type & NUM))
+			i = x < y ? -1 : (x > y ? 1 : 0);
+		else
+			i = strcmp(getsval(u), getsval(v));
+/*
+printf("Cond(%d)(%d)(%g)(%g)(%d)\n", u->c_type, v->c_type, x, y, i);
+*/
+
+		switch (op) {
+		case LT:	i = i < 0 ? 1 : 0; break;
+		case LE:	i = i <= 0 ? 1 : 0; break;
+		case EQ:	i = i == 0 ? 1 : 0; break;
+		case NE:	i = i != 0 ? 1 : 0; break;
+		case GT:	i = i > 0 ? 1 : 0; break;
+		case GE:	i = i >= 0 ? 1 : 0; break;
+		default:
+			fprintf(stderr, "unknown relative operator (%d)\n", op);
+			break;
+		}
+	}
+	c_free(v);
+  }
+  c_free(u);
+  pateval = save;
+  return mktmp(NUM, NULL, (double) i);
+}
+
+static CELL *
+If(p) NODE *p;
+{
+  CELL *u;
+  int i;
+  char *s;
+
+  u = execute(p->n_arg[0]);
+  if (u->c_type & NUM)
+	i = (getfval(u) != 0.0);
+  else {
+	s = getsval(u);
+	i = (s != (char *)NULL) && (*s != '\0');
+  }
+  c_free(u);
+  if (i)
+	u = execute(p->n_arg[1]);
+  else if (p->n_arg[2])
+	u = execute(p->n_arg[2]);
+  else
+	u = &truecell;
+  return u;
+}
+
+static CELL *
+While(p) NODE *p;
+{
+  CELL *u;
+  double x;
+
+  for (;;) {
+	u = execute(p->n_arg[0]);
+	x = getfval(u);
+	if (x == 0.0)
+		break;
+	c_free(u);
+	u = execute(p->n_arg[1]);
+	switch (u->c_type) {
+	case BRK:
+		goto rtn;
+	case NXT: case EXT: case RTN:
+		return u;
+	}
+	c_free(u);
+  }
+rtn:
+  c_free(u);
+  return &truecell;
+}
+
+static CELL *
+Do(p) NODE *p;
+{
+  CELL *u;
+  double x;
+
+  for (;;) {
+	u = execute(p->n_arg[0]);
+	switch (u->c_type) {
+	case BRK:
+		goto rtn;
+	case NXT: case EXT: case RTN:
+		return u;
+	}
+	c_free(u);
+	u = execute(p->n_arg[1]);
+	if(getfval(u) == 0.0)
+		break;
+	c_free(u);
+  }
+rtn:
+  c_free(u);
+  return &truecell;
+}
+
+static CELL *
+For(p) NODE *p;
+{
+  CELL *u;
+  double x;
+
+  if (p->n_arg[0] != NULL) {
+	u = execute(p->n_arg[0]);
+	c_free(u);
+  }
+  for (;;) {
+	if (p->n_arg[1] != NULL) {
+		u = execute(p->n_arg[1]);
+		x = getfval(u);
+		c_free(u);
+		if (x == 0.0)
+			break;
+	}
+	u = execute(p->n_arg[3]);
+	switch (u->c_type) {
+	case BRK:
+		c_free(u);
+		goto rtn;
+	case NXT: case EXT: case RTN:
+		return u;
+	}
+	if (p->n_arg[2] != NULL) {
+		u = execute(p->n_arg[2]);
+		c_free(u);
+	}
+  }
+rtn:
+  return &truecell;
+}
+
+static CELL *
+Jump(p) NODE *p;
+{
+  CELL *u;
+  int i;
+
+  switch ((int) p->n_arg[0]) {
+  case BREAK:	u = &breakcell; break;
+  case CONTIN:	u = &contcell;  break;
+  case EXIT:
+	if ((int) p->n_arg[1]) {
+		u = execute(p->n_arg[1]);
+		i = (int) getfval(u);
+	}
+	else
+		i = 0;
+	closeall();
+	exit(i);
+  case RETURN:
+	Return(p);
+	u = &retcell;
+	break;
+  case NEXT:	u = &nextcell; break;
+  }
+  return u;
+}
+
+static
+Return(p) NODE *p;
+{
+  CELL *u;
+  int i;
+  char *s, str[BUFSIZ];
+
+  c_free(retval);
+  if (p->n_arg[1] != NULL) {
+	if (p->n_arg[2] == NULL) {
+/*
+if (0) {
+*/
+		u = execute(p->n_arg[1]);
+		if (u->c_type == UDF)
+			retval = mktmp(STR, "", 0.0);
+		else
+			retval = mktmp(u->c_type, u->c_sval, u->c_fval);
+		c_free(u);
+	}
+	else {
+		for (i = 1; p->n_arg[i] != NULL; i++) {
+			if (i == 1)
+				*str = '\0';
+			else
+				strcat(str, *OFS);
+			u = execute(p->n_arg[i]);
+			s = getsval(u);
+			strcat(str, s);
+			c_free(u);
+		}
+/*
+printf("Ret(%s)(%d)\n", str, isnum(str));
+*/
+		if (isnum(str))
+			retval = mktmp(STR|NUM, str, atof(str));
+		else
+			retval = mktmp(STR, str, 0.0);
+	}
+  }
+  else
+	retval = &truecell;
+}
+
+#define MAXFRAME	100
+CELL **frame[MAXFRAME];
+static int framep;
+
+static CELL *
+Arg(p) NODE *p;
+{
+  CELL *u;
+  int i;
+
+  u = (CELL *)p->n_arg[0];
+  return _Arg((int)u->c_fval);
+}
+
+CELL *
+_Arg(i)
+{
+/*
+printf("Arg(%d)\n", i);
+*/
+  return frame[framep - 1][i];
+}
+
+static CELL *
+Call(p) NODE *p;
+{
+  CELL *u, *v, *r, **arg;
+  NODE *q;
+  int i, j, k, n;
+  char *emalloc();
+
+  if (framep >= MAXFRAME - 2)
+	error("stack frame overflow", (char *)0);
+  retval = &truecell;
+  r = (CELL *) p->n_arg[0];
+  if (r->c_type != FUN)
+	synerr("called function is not declared", (char *)0);
+  n = (int) r->c_fval;	/* # of params */
+  if (n > 0) {
+	arg = (CELL **) emalloc(sizeof(u) * n);
+	for (i = 2, j = 0, k = (int) p->n_arg[1]; j < k; i++) {
+		u = execute(p->n_arg[i]);
+/*
+printf("pass, j(%d)typ(%d)\n", j, u->c_type);
+*/
+		if (u->c_type & ARR)
+			v = u;	/* pass by reference */
+		else {	/* pass by value */
+			v = mkcell(UDF, u->c_sval, u->c_fval);
+			if (u->c_type != UDF) {
+#if 0
+				v->c_type = u->c_type;
+				if (v->c_type & (NUM|STR))
+					v->c_type |= VAR;
+				v->c_type &= ~TMP;	/* dont't free */
+#else
+				v->c_type |= (u->c_type & (NUM|STR))|VAR;
+				/*v->c_type &= ~TMP;*/
+#endif
+				/* Don't free original */
+			}
+/*
+printf("pass1, j(%d)typ(%d)\n", j, v->c_type);
+*/
+		}
+		arg[j++] = v;
+	}
+	for ( ; j < n; )	/* local var */
+		arg[j++] = mkcell(UDF, NULL, 0.0);
+  }
+  else
+	arg = NULL;
+
+  frame[framep] = arg;
+  framep++;
+
+  r = execute(r->c_sval);
+  c_free(r);
+  framep--;
+  if (n > 0) {
+	for (j = n - 1 ; j > k; j--) {	/* local var */
+		u = arg[j];
+		if (u->c_type & ARR)
+			a_free(u);
+		else
+			c_free(u);
+	}
+	for ( ; j >= 0; j--) {
+		u = arg[j];
+		if (!(u->c_type & ARR)) {
+/*			c_free(u);*/
+			sfree(u->c_sval);
+			sfree(u);
+		}
+		else {
+			v = execute(p->n_arg[j + 2]);
+			if (v->c_type == UDF) {	/* copy back */
+/*
+printf("copy_back_UDF(%d)(%d)\n", j, u->c_type);
+*/
+				v->c_type = u->c_type;
+				sfree(v->c_sval);
+				v->c_sval = u->c_sval;
+				v->c_fval = u->c_fval;
+				sfree(u);
+			}
+		}
+	}
+  }
+  sfree(arg);
+/*  return retval;*/
+  u = mktmp(retval->c_type, retval->c_sval, retval->c_fval);
+  return u;
+}
+
+CELL *Nulproc()
+{
+  return &truecell;
+}
+
+CELL *
+Usrfun(p) NODE *p;
+{
+  CELL *u;
+
+  u = execute(p);
+  return u;
+}
Index: /trunk/minix/commands/awk/k.c
===================================================================
--- /trunk/minix/commands/awk/k.c	(revision 9)
+++ /trunk/minix/commands/awk/k.c	(revision 9)
@@ -0,0 +1,43 @@
+/*
+ * a small awk clone
+ *
+ * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
+ *
+ * Absolutely no warranty. Use this software with your own risk.
+ *
+ * Permission to use, copy, modify and distribute this software for any
+ * purpose and without fee is hereby granted, provided that the above
+ * copyright and disclaimer notice.
+ *
+ * This program was written to fit into 64K+64K memory of the Minix 1.2.
+ */
+
+
+#include <stdio.h>
+
+isKanji(c)
+{
+  c &= 0xff;
+  return (c > 0x80 && c < 0xa0 || c > 0xdf && c < 0xfd);
+}
+
+jstrlen(s) char *s;
+{
+  int i;
+
+  for (i = 0; *s; i++, s++)
+	if (isKanji(*s))
+		s++;
+  return i;
+}
+
+char *
+jStrchr(s, c) char *s;
+{
+  for ( ; *s; s++)
+	if (isKanji(*s))
+		s++;
+	else if (*s == c)
+		return s;
+  return NULL;
+}
Index: /trunk/minix/commands/awk/l.c
===================================================================
--- /trunk/minix/commands/awk/l.c	(revision 9)
+++ /trunk/minix/commands/awk/l.c	(revision 9)
@@ -0,0 +1,333 @@
+/*
+ * a small awk clone
+ *
+ * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
+ *
+ * Absolutely no warranty. Use this software with your own risk.
+ *
+ * Permission to use, copy, modify and distribute this software for any
+ * purpose and without fee is hereby granted, provided that the above
+ * copyright and disclaimer notice.
+ *
+ * This program was written to fit into 64K+64K memory of the Minix 1.2.
+ */
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include "awk.h"
+
+extern char *srcprg;	/* inline program */
+extern FILE *pfp;	/* program file */
+
+int sym;	/* lexical token */
+int sym1;	/* auxiliary lexical token */
+int regexflg;	/* set by parser (y.c) to indicate parsing REGEXPR */
+int funflg;	/* set by parser (y.c) to indicate parsing FUNCTION */
+int printflg;	/* set by parser (y.c) to indicate parsing PRINT */
+int getlineflg;	/* set by parser (y.c) to indicate parsing GETLINE */
+char text[BUFSIZ];	/* lexical word */
+char line[BUFSIZ];	/* program line for error message (ring buffer) */
+char *linep = line;	/* line pointer */
+char funnam[128];	/* function name for error message */
+int lineno = 1;
+
+lex()
+{
+  int c, d;
+  char *s;
+
+  if (regexflg)
+	return sym = scanreg();
+next:
+  while ((c = Getc()) == ' ' || c == '\t')
+	;
+  while (c == '#')
+	for (c = Getc(); c != '\n'; c = Getc())
+		;
+  switch (c) {
+  case '\\':
+	if ((c = Getc()) == '\n') {
+		lineno++;
+		goto next;
+	}
+	break;
+  case '\n':
+	lineno++;
+	break;
+  }
+  switch (c) {
+  case EOF:	return sym = 0;
+  case '+':	return sym = follow2('=', '+', ADDEQ, INC, ADD);
+  case '-':	return sym = follow2('=', '-', SUBEQ, DEC, SUB);
+  case '*':	return sym = follow('=', MULTEQ, MULT);
+  case '/':	return sym = follow('=', DIVEQ, DIV);
+  case '%':	return sym = follow('=', MODEQ, MOD);
+  case '^':	return sym = follow('=', POWEQ, POWER);
+  case '=':	return sym = follow('=', EQ, ASSIGN);
+  case '!':	return sym = follow2('=', '~', NE, NOMATCH, NOT);
+  case '&':	return sym = follow('&', AND, BINAND);
+  case '|':	sym = follow('|', OR, BINOR);
+		if (printflg && sym == BINOR)
+			sym = R_POUT;
+		return sym;
+  case '<':	sym = follow2('=', '<', LE, SHIFTL, LT);
+		if (getlineflg && sym == LT)
+			sym = R_IN;
+		return sym;
+  case '>':	sym = follow2('=', '>', GE, SHIFTR, GT);
+		if (printflg) {
+			switch (sym) {
+			case GT: sym = R_OUT; break;
+			case SHIFTR: sym = R_APD; break;
+			}
+		}
+		return sym;
+  case '~':	return sym = MATCH; break;
+  case ';': case '\n':	return sym = EOL;
+  }
+  if (isalpha(c) || c == '_') {
+	for (s = text; isalnum(c) || c == '_'; ) {
+		*s++ = c; c = Getc();
+	}
+	Ungetc(c);
+	*s = '\0';
+	if ((d = iskeywd(text)) == 0 &&
+		(d = isbuiltin(text, &sym1)) == 0) {
+			if (c == '(')
+				return sym = CALL;
+			else if (funflg) {
+				if ((sym1 = isarg(text)) != -1)
+					return sym = ARG;
+			}
+	}
+	return sym = d ? d : IDENT;
+  }
+  else if (c == '.' || (isdigit(c))) {
+	Ungetc(c);
+	return sym = scannum(text);	/* NUMBER */
+  }
+  else if (c == '"')
+	return sym = scanstr(text);	/* STRING */
+  return sym = c;
+}
+
+static
+follow(c1, r1, r2)
+{
+  register int c;
+
+  if ((c = Getc()) == c1)
+	return r1;
+  else {
+	Ungetc(c);
+	return r2;
+  }
+}
+
+static
+follow2(c1, c2, r1, r2, r3)
+{
+  register int c;
+
+  if ((c = Getc()) == c1)
+	return r1;
+  else if (c == c2)
+	return r2;
+  else {
+	Ungetc(c);
+	return r3;
+  }
+}
+
+static
+iskeywd(s) char *s;
+{
+  static struct { char *kw; int token; } tab[] = {
+	"BEGIN", BEGIN,
+	"END", END,
+	"break", BREAK,
+	"continue", CONTIN,
+	"delete", DELETE,
+	"do", DO,
+	"else", ELSE,
+	"exit", EXIT,
+	"for", FOR,
+	"func", FUNC,
+	"function", FUNC,
+	"getline", GETLINE,
+	"if", IF,
+	"in", IN,
+	"next", NEXT,
+	"print", PRINT,
+	"printf", PRINTF,
+	"return", RETURN,
+	"sprint", SPRINT,
+	"sprintf", SPRINTF,
+	"while", WHILE,
+	"", 0, 0
+  };
+  register int i;
+
+  for (i = 0; tab[i].token; i++)
+	if (strcmp(tab[i].kw, s) == 0)
+		break;
+  return tab[i].token;
+}
+
+static
+isbuiltin(s, p) char *s; int *p;
+{
+  static struct { char *kw; int type; int token; } tab[] = {
+	"atan2", MATHFUN, ATAN2,
+	"close", STRFUN, CLOSE,
+	"cos", MATHFUN, COS,
+	"exp", MATHFUN, EXP,
+	"gsub", SUBST, RGSUB,
+	"index", STRFUN, INDEX,
+	"int", MATHFUN, INT,
+	"length", STRFUN, LENGTH,
+	"log", MATHFUN, LOG,
+	"match", STRFUN, RMATCH,
+	"sin", MATHFUN, SIN,
+	"sqrt", MATHFUN, SQRT,
+	"rand", MATHFUN, RAND,
+	"srand", MATHFUN, SRAND,
+	"split", STRFUN, SPLIT,
+	"sub", SUBST, RSUB,
+	"substr", STRFUN, SUBSTR,
+	"system", STRFUN, SYSTEM,
+	"", 0, 0
+  };
+  register int i;
+
+  for (i = 0; tab[i].token; i++)
+	if (strcmp(tab[i].kw, s) == 0)
+		break;
+  *p = tab[i].token;
+  return tab[i].type;
+}
+
+static
+scannum(s) char *s;
+{
+  register int c;
+  char *strchr();
+
+  if ((c = Getc()) && strchr("+-", c) != NULL) {
+	*s++ = c; c = Getc();
+  }
+  while (isdigit(c)) {
+	*s++ = c; c = Getc();
+  }
+  if (c == '.') {
+	*s++ = c; c = Getc();
+	while (isdigit(c)) {
+		*s++ = c; c = Getc();
+	}
+  }
+  if (c && strchr("eE", c) != NULL) {
+	*s++ = c; c = Getc();
+	if (c && strchr("+-", c) != NULL) {
+		*s++ = c; c = Getc();
+	}
+	while (isdigit(c)) {
+		*s++ = c; c = Getc();
+	}
+  }
+  *s = '\0';
+  Ungetc(c);
+  return NUMBER;
+}
+
+static
+scanstr(s) char *s;
+{
+  register int c, i, j;
+
+  for (c = Getc(); c != EOF & c != '"'; ) {
+	if (c == '\\') {
+		switch (c = Getc()) {
+		case 'b': c = '\b'; break;
+		case 'f': c = '\f'; break;
+		case 'n': c = '\n'; break;
+		case 'r': c = '\r'; break;
+		case 't': c = '\t'; break;
+		default:
+		if (isdigit(c)) {
+			for (i = j = 0; i < 3 && isdigit(c); c = Getc(), i++)
+				j = j * 8 + c - '0';
+			Ungetc(c);
+			c = j;
+		}
+		break;
+		}
+	}
+	*s++ = c;
+	if (isKanji(c))
+		*s++ = Getc();
+	c = Getc();
+  }
+  *s = '\0';
+  return STRING;
+}
+
+static
+scanreg()
+{
+  register int c;
+  register char *s;
+
+  for (s = text; (c = Getc()) != '/'; )
+	if (c == '\n')
+		error("newline in regular expression");
+	else {
+		if (isKanji(c) || c == '\\') {
+			*s++ = c; c = Getc();
+		}
+		*s++ = c;
+	}
+  *s = '\0';
+  return REGEXP;
+}
+
+static int c0;
+
+Ungetc(c)
+{
+  c0 = c;
+
+  if (linep > line) {
+	if (--linep < line)
+		linep == line + BUFSIZ - 1;
+  }
+}
+
+Getc()
+{
+  register int c;
+  char *s, *t;
+
+  if (c0) {
+	c = c0; c0 = 0;
+  }	
+  else if (srcprg)
+	c = *srcprg ? *srcprg++ : EOF;
+  else
+	c = fgetc(pfp);
+
+#if 0
+  if (linep - line == BUFSIZ) {
+printf("!!!\n");
+	for (s = line; *s != '\n' && ((s - line) <BUFSIZ); s++)
+		;
+printf("***(%d)***\n", *s);
+	for (t = line; s < linep; )
+		*t++ = *++s;
+  }
+#endif
+  *linep++ = c;
+  if ((linep - line) == BUFSIZ)
+	linep = line;
+  return c;
+}
Index: /trunk/minix/commands/awk/m.c
===================================================================
--- /trunk/minix/commands/awk/m.c	(revision 9)
+++ /trunk/minix/commands/awk/m.c	(revision 9)
@@ -0,0 +1,141 @@
+/*
+ * a small awk clone
+ *
+ * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
+ *
+ * Absolutely no warranty. Use this software with your own risk.
+ *
+ * Permission to use, copy, modify and distribute this software for any
+ * purpose and without fee is hereby granted, provided that the above
+ * copyright and disclaimer notice.
+ *
+ * This program was written to fit into 64K+64K memory of the Minix 1.2.
+ */
+
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <signal.h>
+#include "awk.h"
+
+extern char **FS, **FILENAME;
+extern char record[];
+extern FILE *ifp;
+
+NODE *parse();
+CELL *execute();
+FILE *efopen(), *fopen();
+char *strsave();
+
+int xargc;
+char **xargv;
+char *srcprg;
+FILE *pfp;
+char *cmd;
+#if 0
+int iflg;	/* interactive mode */
+#endif
+
+main(argc, argv) char **argv;
+{
+  char *s, *strpbrk(), *strchr();
+  void onint();
+
+#ifdef DOS
+  _sharg(&argc, &argv);
+#endif
+  signal(SIGINT, onint);
+  signal(SIGFPE, onint);
+  cmd = argv[0];
+  init();
+  while (--argc > 0 && (*++argv)[0] == '-')
+	for (s = argv[0]+1; *s; s++)
+		if (strcmp(argv[0], "-") == 0)
+			break;
+		else
+		switch (*s) {
+#if 0
+		case 'i':
+			iflg++;
+			pfp = stdin;
+			interactive();
+			/* no return */
+#endif
+		case 'F':
+			*FS = ++s;
+			break;
+		case 'f':
+			if (*(s+1))
+				s++;
+			else {
+				argc--; s = *++argv;
+			}
+			pfp = efopen(s, "r");
+			s += strlen(s) - 1;
+			break;
+		}
+  xargc = argc; xargv = argv;
+  if (pfp == NULL && xargc > 0) {
+	srcprg = *xargv++; xargc--;
+  }
+/*
+  if (pfp == NULL && xargc > 0) {
+	if (strpbrk(xargv[0], " !$^()={}[];<>,/~") != NULL) {
+		sprintf(record, "%s\n", xargv[0]);
+		srcprg = strsave(record);
+	}
+	else {
+		sprintf(record, "%s.awk", xargv[0]);
+		if ((pfp = fopen(record, "r")) == NULL)
+			error("can't open %s", record);
+	}
+	xargc--; xargv++;
+  }
+*/
+
+  while (*xargv != NULL && strchr(*xargv, '=') != NULL) {
+	setvar(*xargv++);
+	xargc--;
+  }
+
+  initarg(cmd, xargc, xargv);
+  if (xargc == 0) {
+	ifp = stdin; *FILENAME = "-";
+  }
+  parse();
+  closeall();
+  exit(0);
+}
+
+FILE *
+efopen(file, mode) char *file, *mode;
+{
+  FILE *fp, *fopen();
+
+  if ((fp = fopen(file, mode)) == NULL)
+	error("cannot open %s", file);
+  return fp;
+}
+
+error(s, t) char *s, *t;
+{
+  extern double *NR;
+
+  fprintf(stderr, "awk: ");
+  fprintf(stderr, s, t);
+  fprintf(stderr, "\n");
+  if (NR != NULL) {
+	fprintf(stderr, "record number %g\n", *NR);
+  }
+#ifdef DOS
+  closeall();
+#endif
+  exit(1);
+}
+
+void
+onint(i)
+{
+  closeall();
+  exit(0x80 | i);
+}
Index: /trunk/minix/commands/awk/n.c
===================================================================
--- /trunk/minix/commands/awk/n.c	(revision 9)
+++ /trunk/minix/commands/awk/n.c	(revision 9)
@@ -0,0 +1,149 @@
+/*
+ * a small awk clone
+ *
+ * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
+ *
+ * Absolutely no warranty. Use this software with your own risk.
+ *
+ * Permission to use, copy, modify and distribute this software for any
+ * purpose and without fee is hereby granted, provided that the above
+ * copyright and disclaimer notice.
+ *
+ * This program was written to fit into 64K+64K memory of the Minix 1.2.
+ */
+
+
+#include <stdio.h>
+#include "awk.h"
+
+NODE *
+node0(type)
+{
+  NODE *p;
+  char *emalloc();
+
+  p = (NODE *) emalloc(sizeof(*p) - sizeof(p));
+  p->n_type = type;
+  p->n_next = NULL;
+  return p;
+}
+
+NODE *
+node1(type, arg0) NODE *arg0;
+{
+  NODE *p;
+  char *emalloc();
+
+  p = (NODE *) emalloc(sizeof(*p));
+  p->n_type = type;
+  p->n_next = NULL;
+  p->n_arg[0] = (NODE *) arg0;
+  return p;
+}
+
+NODE *
+node2(type, arg0, arg1) NODE *arg0, *arg1;
+{
+  NODE *p;
+  char *emalloc();
+
+  p = (NODE *) emalloc(sizeof(*p) + sizeof(p) * 1);
+  p->n_type = type;
+  p->n_next = NULL;
+  p->n_arg[0] = (NODE *) arg0;
+  p->n_arg[1] = (NODE *) arg1;
+  return p;
+}
+
+NODE *
+node3(type, arg0, arg1, arg2) NODE *arg0, *arg1, *arg2;
+{
+  NODE *p;
+  char *emalloc();
+
+  p = (NODE *) emalloc(sizeof(*p) + sizeof(p) * 2);
+  p->n_type = type;
+  p->n_next = NULL;
+  p->n_arg[0] = (NODE *) arg0;
+  p->n_arg[1] = (NODE *) arg1;
+  p->n_arg[2] = (NODE *) arg2;
+  return p;
+}
+
+NODE *
+node4(type, arg0, arg1, arg2, arg3) NODE *arg0, *arg1, *arg2, *arg3;
+{
+  NODE *p;
+  char *emalloc();
+
+  p = (NODE *) emalloc(sizeof(*p) + sizeof(p) * 3);
+  p->n_type = type;
+  p->n_next = NULL;
+  p->n_arg[0] = (NODE *) arg0;
+  p->n_arg[1] = (NODE *) arg1;
+  p->n_arg[2] = (NODE *) arg2;
+  p->n_arg[3] = (NODE *) arg3;
+  return p;
+}
+
+CELL *
+mkcell(type, sval, fval) char *sval; double fval;
+{
+  CELL *p;
+  char *emalloc(), *strsave();
+
+  p = (CELL *) emalloc(sizeof(*p));
+  p->c_type = type;
+  if (sval == NULL)
+	p->c_sval = NULL;
+  else
+	p->c_sval = strsave(sval);
+  p->c_fval = fval;
+  return p;
+}
+
+#ifdef TMPCELL
+#define MAXTMP	25
+
+CELL tmpcell[MAXTMP];
+#endif
+
+CELL *
+mktmp(type, sval, fval) char *sval; double fval;
+{
+  register int i;
+  char *strsave();
+
+#ifdef TMPCELL
+  for (i = 0; i < MAXTMP; i++)
+	if (tmpcell[i].c_type == 0) {
+		tmpcell[i].c_type = type | TMP;
+		tmpcell[i].c_sval = strsave(sval);
+		tmpcell[i].c_fval = fval;
+		return &tmpcell[i];
+	}
+  error("formula too complex", (char *) 0);
+#else
+  return mkcell(type | TMP, sval, fval);
+#endif
+}
+
+c_free(p) CELL *p;
+{
+  if ((p != NULL) && (p->c_type & TMP)) {
+#ifdef TMPCELL
+	p->c_type = 0;
+	sfree(p->c_sval);
+	p->c_sval = (char *)NULL;
+	p->c_fval = 0.0;
+#else
+	if (p->c_sval != NULL) {
+		Free(p->c_sval);
+		p->c_sval = NULL;
+	}
+	p->c_type = 0;
+	Free(p);
+	p = NULL;
+#endif
+  }
+}
Index: /trunk/minix/commands/awk/r.c
===================================================================
--- /trunk/minix/commands/awk/r.c	(revision 9)
+++ /trunk/minix/commands/awk/r.c	(revision 9)
@@ -0,0 +1,627 @@
+/*
+ * a small awk clone
+ *
+ * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
+ *
+ * Absolutely no warranty. Use this software with your own risk.
+ *
+ * Permission to use, copy, modify and distribute this software for any
+ * purpose and without fee is hereby granted, provided that the above
+ * copyright and disclaimer notice.
+ *
+ * This program was written to fit into 64K+64K memory of the Minix 1.2.
+ */
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef DOS
+#include <process.h>
+#endif
+#include "awk.h"
+#include "regexp.h"
+
+#define MAXFLD	100
+
+extern char **FS, **RS, **OFS, **ORS, **FILENAME;
+extern double *NF, *NR;
+extern double *FNR;
+extern double *ARGC;
+extern SYMBOL *argtab[];
+extern CELL *getvar();
+
+char *strsave(), *strcpy(), *getsval(), *jStrchr(), *strchr();
+double getfval(), atof();
+CELL *mkcell(), *mktmp(), *execute(), *patexec();
+FILE *efopen();
+
+extern CELL truecell, falsecell;
+
+extern int pateval;
+
+int infileno = 1;
+FILE *ifp;
+char record[BUFSIZ];
+CELL *field[MAXFLD];
+
+char *fs_str;
+regexp *fs_pat;
+
+CELL *
+Getline(p) NODE *p;
+{
+  CELL *u;
+  char *fnam, *s, str[BUFSIZ];
+  int i;
+  FILE *fp, *getfp();
+
+  if ((int) p->n_arg[0])	/* read into var */
+	s = str;
+  else
+	s = NULL;
+  if ((int) p->n_arg[1]) {	/* file name */
+	u = execute(p->n_arg[1]);
+	fnam = getsval(u);
+	fp = getfp(fnam, (int) p->n_arg[2]);
+	c_free(u);
+	i = get1rec(s, fp);
+  }
+  else
+	i = Getrec(s);
+  if (s == str) {
+	u = execute(p->n_arg[0]);
+	setsval(u, str);
+  }
+  return mktmp(NUM, NULL, (double) i);
+}
+
+static
+get1rec(buf, fp) char *buf; FILE *fp;
+{
+  register int c;
+  register char rs, *s;
+  int mflg;
+
+  if (buf == NULL)
+	buf = record;
+  if ((rs = **RS) == '\0') {	/* multi line record */
+	mflg = 1;
+	rs = '\n';
+  }
+  else
+	mflg = 0;
+
+  if (feof(fp) || (c = getc(fp)) == EOF)
+	return 0;
+  for (s = buf; ; ) {
+	for ( ; c != rs && c != EOF; c = getc(fp)) {
+		if (isKanji(c)) {
+			*s++ = c; c = getc(fp);
+		}
+		*s++ = c;
+	}
+	if (mflg) {
+		if ((c = getc(fp)) == '\n' || c == EOF)
+			break;
+		*s++ = '\n';
+	}
+	else
+		break;
+  }
+  *s = '\0';
+#if 1
+  if (buf == record) {
+#else
+  if (buf == record && c != EOF) {
+#endif
+	mkfld(record, *FS, field);
+	(*NR)++;
+	(*FNR)++;
+  }
+  return s > buf || c != EOF ? 1 : 0;
+}
+
+Getrec(s) char *s;
+{
+  CELL *u;
+  char *file, str[8];
+
+  while (ifp == stdin || infileno < (int)*ARGC) {
+	if (ifp == NULL) {
+		*FNR = 0.0;
+		if (infileno == (int)*ARGC)
+			break;
+		sprintf(str, "%d", infileno);
+		u = getvar(str, argtab);
+		file = getsval(u);
+		if (strchr(file, '=') != NULL) {
+			setvar(file);
+			infileno++;
+			continue;
+		}
+		else if (strcmp(file, "") == 0) {
+/*
+if (infileno == (int)*ARGC - 1)
+			ifp = stdin;
+*/
+			infileno++;
+			continue;
+		}
+		else {
+			if (strcmp(file, "-") == 0)
+				ifp = stdin;
+			else
+				ifp = efopen(file, "r");
+			*FILENAME = file;
+		}
+	}
+	if (get1rec(s, ifp))
+		return 1;
+	else {
+		if (ifp != stdin)
+			fclose(ifp);
+		ifp = NULL;
+		infileno++;
+	}
+  }
+  ifp = stdin;	/* for further "getline" */
+  *FILENAME = "-";
+  return 0;	/* EOF */
+}
+
+mkfld(rec, sep, fld) char *rec, *sep; CELL *fld[];
+{
+  char *s, *t;
+  char str[BUFSIZ];
+  int i, j, n;
+  int skip = 0;
+
+  if (strlen(sep) > 1)
+	return r_mkfld(rec, sep, fld);
+
+  if (*sep == ' ' || *sep == '\0') {
+	sep = " \t\n"; skip++;
+  }
+  for (i = 1, n = (int) *NF; i <= n; i++) {
+	sfree(fld[i]->c_sval);
+	sfree(fld[i]);
+	fld[i] = NULL;
+  }
+  for (i = 0, s = rec; ; ) {
+	t = str;
+	if (skip) {
+		while (*s && strchr(" \t\n", *s))
+			s++;
+		if (*s == '\0')
+			break;
+	}
+	while (*s && !jStrchr(sep, *s)) {
+		if (isKanji(*s))
+			*t++ = *s++;
+		*t++ = *s++;
+	}
+	*t = '\0';
+	if (isnum(str))
+		fld[++i] =  mkcell(FLD|STR|NUM, str, atof(str));
+	else
+		fld[++i] =  mkcell(FLD|STR, str, 0.0);
+	if (*s)
+		s++;
+	else
+		break;
+  }
+  *NF = (double) i;
+  return i;
+}
+
+static
+r_mkfld(rec, sep, fld) char *rec, *sep; CELL *fld[];
+{
+  char *s, *t;
+  char str[BUFSIZ];
+  int i, n;
+  regexp *mkpat();
+  extern int r_start, r_length;
+
+  if (strcmp(*FS, fs_str) != 0) {
+	sfree(fs_str); sfree(fs_pat);
+	fs_str = strsave(*FS);
+	fs_pat = mkpat(fs_str);
+  }
+  for (i = 1, n = (int) *NF; i <= n; i++) {
+	sfree(fld[i]->c_sval);
+	sfree(fld[i]);
+	fld[i] = NULL;
+  }
+  for (i = 0, s = rec, t = str; *s; ) {
+	if (match(fs_pat, s)) {
+		for (n = r_start; --n > 0; )
+			*t++ = *s++;
+	}
+	else {
+		while (*s)
+			*t++ = *s++;
+	}
+	*t = '\0';
+	t = str;
+	fld[++i] = mkcell(FLD|STR, str, 0.0);
+	if (*s)
+		s += r_length;
+  }
+  *NF = (double) i;
+  return i;
+}
+
+mkrec(u) CELL *u;
+{
+  register char *s, *t;
+  register int i, j;
+
+  for (j = (int)*NF, i = 1; i <= j; i++)
+	if (field[i] == u)
+		break;
+  if (i > j) {
+	for ( ; i < MAXFLD; i++)
+		if (field[i] == u)
+			break;
+	if (i == MAXFLD)
+		error("too many field (%d)", i);
+	*NF = (double)i;
+  }
+  for (t = record, i = 1, j = (int) *NF; i <= j; i++) {
+	if (i > 1)
+		*t++ = **OFS;
+	for (s = getsval(field[i]); *s; )
+		*t++ = *s++;
+  }
+  *t++ = '\0';
+}
+
+CELL *
+Field(p) NODE *p;
+{
+  CELL *u;
+  int i, j;
+
+  u = execute(p->n_arg[0]);
+  i = (int) getfval(u);
+  c_free(u);
+  j = (int)*NF;
+  if (i > j)
+	for (++j; j <= i; j++) {
+		if (field[j] == NULL)
+			field[j] = mkcell(FLD|STR, "", 0.0);
+	}
+  return field[i];
+}
+
+CELL *
+P1stat(p) NODE *p;
+{
+  CELL *u;
+  double x;
+
+  pateval++;
+  u = execute(p->n_arg[0]);
+  pateval = 0;
+  x = getfval(u);
+  c_free(u);
+  if (x != 0.0)
+	u = execute(p->n_arg[1]);
+  else
+	u = &truecell;
+  return u;
+}
+
+CELL *
+P2stat(p) NODE *p;
+{
+  static stat = 0;
+  CELL *u, *v;
+  double x;
+
+  switch (stat) {
+  case 0:
+	pateval++;
+	u = execute(p->n_arg[0]);
+	pateval = 0;
+	x = getfval(u);
+	c_free(u);
+	if (x == 0.0) {
+		u = &truecell; break;
+	}
+	else
+		stat++;
+	/* fall through */
+  case 1:
+	u = execute(p->n_arg[2]);
+	c_free(u);
+	pateval++;
+	u = execute(p->n_arg[1]);
+	pateval = 0;
+	x = getfval(u);
+	if (x != 0.0)
+		stat = 0;
+	break;
+  default:
+	u = &truecell;
+	break;
+  }
+  return u;
+}
+
+CELL *
+Print0()
+{
+/*
+  int i, j;
+  char *s, str[BUFSIZ];
+
+  for (*str = '\0', i = 1, j = (int) *NF; i <= j; i++) {
+	if (i > 1)
+		strcat(str, *OFS);
+	s = getsval(field[i]);
+	strcat(str, s);
+  }
+  strcat(str, *ORS);
+  fputs(str, stdout);
+*/
+  fprintf(stdout, "%s%s", record, *ORS);
+  return &truecell;
+}
+
+char *
+format(t, p) char *t; NODE *p;
+{
+  CELL *u, *v;
+  char *r, *s, *s0, fmt[BUFSIZ];
+  double x;
+  int i;
+
+  u = execute(p->n_arg[2]);
+  s = s0 = getsval(u);
+/*
+printf("fmt(%s)\n", s);
+*/
+  for (i = 3; *s; s++) {
+	if (isKanji(*s)) {
+		*t++ = *s++; *t++ = *s; continue;
+	}
+	if (*s != '%') {
+		*t++ = *s; continue;
+	}
+	else if (*(s + 1) == '%') {
+		*t++ = *s++; continue;
+	}
+	for (r = fmt, *r++ = *s++; *r++ = *s; s++) {
+		if (strchr("%cdefgosux", *s))
+			break;
+	}
+	*r = '\0';
+	if (p->n_arg[i] == NULL)
+		error("not enough args in printf(%s)", s0);
+	v = execute(p->n_arg[i++]);
+	if (*s == 's')
+		r = getsval(v);
+	else
+		x = getfval(v);
+/*
+printf("val(%d)(%s)\n", v->c_type, v->c_sval);
+*/
+	switch (*s) {
+	case 'c':
+		sprintf(t, fmt, (int) x);
+		break;
+	case 'd':
+		if (*(s - 1) != 'l') {
+			*--r = 'l'; *++r = 'd'; *++r = '\0';
+		}
+		sprintf(t, fmt, (long) x);
+		break;
+	case 'e': case 'f': case 'g':
+		sprintf(t, fmt, x);
+		break;
+	case 'o': case 'u': case 'x':
+		if (*(s - 1) == 'l')
+			sprintf(t, fmt, (long) x);
+		else
+			sprintf(t, fmt, (int) x);
+		break;
+	case 's':
+		/*r = getsval(v);*/
+		sprintf(t, fmt, r);
+		break;
+	default:
+		strcpy(t, fmt);
+		break;
+	}
+	c_free(v);
+	t += strlen(t);
+  }
+  c_free(u);
+  *t = '\0';
+}
+
+#define MAXFILE	10
+struct {
+  char *f_name;	/* file name */
+  FILE *f_fp;
+  int f_type;
+} filetab[MAXFILE];
+
+FILE *
+getfp(file, type) char *file;
+{
+  register int i;
+  register char *name, *mode;
+  char *awktmp();
+  FILE *fp, *efopen(), *epopen();
+
+  for (i = 0; i < MAXFILE; i++)
+	if (filetab[i].f_name && strcmp(filetab[i].f_name, file) == 0)
+		return filetab[i].f_fp;
+  for (i = 0; i < MAXFILE; i++)
+	if (!filetab[i].f_fp)
+		break;
+  if (i == MAXFILE)
+	error("too many files to open");
+  name = file;
+  switch (type) {
+  case R_OUT:	mode = "w"; break;
+  case R_APD:	mode = "a"; break;
+  case R_POUT:
+#ifdef DOS
+	name = awktmp(i); mode = "w";	/* MS-DOS */
+#else
+	fp = epopen(file, "w");
+	goto g1;
+#endif
+	break;
+  case R_IN:	mode = "r"; break;
+  case R_PIN:
+#ifdef DOS
+	{
+		int savefd, fd, result;
+
+		name = awktmp(i);
+		if ((fd = open(name,
+		O_WRONLY|O_TEXT|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE)) == -1)
+			error("can't open %s", name);
+		savefd = dup(1); dup2(fd, 1); close(fd);
+		if ((result =
+			system(file)) == -1)
+			error("can't exec %s", file);
+		dup2(savefd, 1); close(savefd); close(fd);
+		mode = "r";
+	}
+#else
+	fp = epopen(file,"r");
+	goto g1;
+#endif
+	break;
+  }
+  fp = efopen(name, mode);
+g1:
+  filetab[i].f_name = strsave(file);
+  filetab[i].f_type = type;
+  filetab[i].f_fp = fp;
+  return fp;
+}
+
+closeall()
+{
+  register int i;
+
+  for (i = 0; i < MAXFILE; i++)
+	close1(i);
+}
+
+CELL *
+Close(s) char *s;
+{
+  register int i;
+
+  for (i = 0; i < MAXFILE; i++)
+	if (strcmp(s, filetab[i].f_name) == 0) {
+		close1(i);
+		break;
+	}
+  i = (i == MAXFILE) ? 0 : 1;
+  return mktmp(NUM, NULL, (double) i);
+}
+
+static
+close1(i)
+{
+  int fd, result, savefd;
+  char *awktmp();
+
+  if (filetab[i].f_fp == NULL)
+	return;
+  switch (filetab[i].f_type) {
+  case R_PIN:
+#ifdef DOS
+	fclose(filetab[i].f_fp);
+	unlink(awktmp(i));
+#else
+	pclose(filetab[i].f_fp);
+#endif
+	break;
+  case R_IN: case R_OUT: case R_APD:
+	fclose(filetab[i].f_fp);
+	break;
+  case R_POUT:
+#ifdef DOS
+	fclose(filetab[i].f_fp);
+	if ((fd = open(awktmp(i), O_RDONLY)) == NULL)
+		error("can't open %s", awktmp(i));
+	savefd = dup(0);
+	dup2(fd, 0);
+	close(fd);
+	if ((result =
+		system(filetab[i].f_name)) == -1)
+/*
+	spawnl(P_WAIT, "/usr/bin/sh", "sh", "-c", filetab[i].f_name, (char *) 0)) == -1)
+		fprintf(stderr, "can't spawn /bin/sh\n");
+*/
+		error("can't exec %s", filetab[i].f_name);
+	dup2(savefd, 0);
+	close(savefd);
+	unlink(awktmp(i));
+#else
+	pclose(filetab[i].f_fp);
+#endif
+	break;
+  }
+  sfree(filetab[i].f_name);
+  filetab[i].f_type = 0;
+  filetab[i].f_name = NULL;
+  filetab[i].f_fp = NULL;
+}
+
+#ifndef DOS
+FILE *
+epopen(file, mod) char *file, *mod;
+{
+  FILE *fp, *popen();
+
+  if ((fp = popen(file, mod)) == NULL)
+	error("can't poen %s", file);
+  return fp;
+}
+#endif
+
+static char *
+awktmp(i)
+{
+  static char str[16];
+
+  sprintf(str, "awk000%02d.tmp", i);
+  return str;
+}
+
+Index(s, t) char *s, *t;
+{
+  register char *u, *v;
+  register int i;
+
+  for (i = 1; *s; s++, i++) {
+	for (u = s, v = t; *v; u++, v++) {
+		if (isKanji(*v)) {
+			if (*u != *v)
+				break;
+			u++; v++;
+		}
+		if (*u != *v)
+			break;
+	}
+	if (*v == '\0')
+		return i;
+	if (isKanji(*s))
+		s++;
+  }
+  return 0;
+}
Index: /trunk/minix/commands/awk/regexp.c
===================================================================
--- /trunk/minix/commands/awk/regexp.c	(revision 9)
+++ /trunk/minix/commands/awk/regexp.c	(revision 9)
@@ -0,0 +1,1440 @@
+/*
+ * regcomp and regexec -- regsub and regerror are elsewhere
+ *
+ *	Copyright (c) 1986 by University of Toronto.
+ *	Written by Henry Spencer.  Not derived from licensed software.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to redistribute it freely,
+ *	subject to the following restrictions:
+ *
+ *	1. The author is not responsible for the consequences of use of
+ *		this software, no matter how awful, even if they arise
+ *		from defects in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *		by explicit claim or by omission.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *		be misrepresented as being the original software.
+ *
+ * Beware that some of this code is subtly aware of the way operator
+ * precedence is structured in regular expressions.  Serious changes in
+ * regular-expression syntax might require a total rethink.
+ *
+ *	Modified by K.Hirabayashi to accept KANJI code, memory allocation
+ *	and to add following functions.
+ *		isthere(), mkpat(), match(), regsub(), sjtok(), ktosj(),
+ *		Strchr(), Strncmp(), Strlen()
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "regexp.h"
+
+#define regerror(a)	error("regular expression error: %s", a)
+
+int r_start, r_length;
+
+/*
+ * The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte.
+ */
+#define	MAGIC	0234
+
+/*
+ * The "internal use only" fields in regexp.h are present to pass info from
+ * compile to execute that permits the execute phase to run lots faster on
+ * simple cases.  They are:
+ *
+ * regstart	char that must begin a match; '\0' if none obvious
+ * reganch	is the match anchored (at beginning-of-line only)?
+ * regmust	string (pointer into program) that match must include, or NULL
+ * regmlen	length of regmust string
+ *
+ * Regstart and reganch permit very fast decisions on suitable starting points
+ * for a match, cutting down the work a lot.  Regmust permits fast rejection
+ * of lines that cannot possibly match.  The regmust tests are costly enough
+ * that regcomp() supplies a regmust only if the r.e. contains something
+ * potentially expensive (at present, the only such thing detected is * or +
+ * at the start of the r.e., which can involve a lot of backup).  Regmlen is
+ * supplied because the test in regexec() needs it and regcomp() is computing
+ * it anyway.
+ */
+
+/*
+ * Structure for regexp "program".  This is essentially a linear encoding
+ * of a nondeterministic finite-state machine (aka syntax charts or
+ * "railroad normal form" in parsing technology).  Each node is an opcode
+ * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
+ * all nodes except BRANCH implement concatenation; a "next" pointer with
+ * a BRANCH on both ends of it is connecting two alternatives.  (Here we
+ * have one of the subtle syntax dependencies:  an individual BRANCH (as
+ * opposed to a collection of them) is never concatenated with anything
+ * because of operator precedence.)  The operand of some types of node is
+ * a literal string; for others, it is a node leading into a sub-FSM.  In
+ * particular, the operand of a BRANCH node is the first node of the branch.
+ * (NB this is *not* a tree structure:  the tail of the branch connects
+ * to the thing following the set of BRANCHes.)  The opcodes are:
+ */
+
+/* definition	number	opnd?	meaning */
+#define	END	0	/* no	End of program. */
+#define	BOL	1	/* no	Match "" at beginning of line. */
+#define	EOL	2	/* no	Match "" at end of line. */
+#define	ANY	3	/* no	Match any one character. */
+#define	ANYOF	4	/* str	Match any character in this string. */
+#define	ANYBUT	5	/* str	Match any character not in this string. */
+#define	BRANCH	6	/* node	Match this alternative, or the next... */
+#define	BACK	7	/* no	Match "", "next" ptr points backward. */
+#define	EXACTLY	8	/* str	Match this string. */
+#define	NOTHING	9	/* no	Match empty string. */
+#define	STAR	10	/* node	Match this (simple) thing 0 or more times. */
+#define	PLUS	11	/* node	Match this (simple) thing 1 or more times. */
+#define	OPEN	20	/* no	Mark this point in input as start of #n. */
+		/*	OPEN+1 is number 1, etc. */
+#define	CLOSE	30	/* no	Analogous to OPEN. */
+
+/*
+ * Opcode notes:
+ *
+ * BRANCH	The set of branches constituting a single choice are hooked
+ *		together with their "next" pointers, since precedence prevents
+ *		anything being concatenated to any individual branch.  The
+ *		"next" pointer of the last BRANCH in a choice points to the
+ *		thing following the whole choice.  This is also where the
+ *		final "next" pointer of each individual branch points; each
+ *		branch starts with the operand node of a BRANCH node.
+ *
+ * BACK		Normal "next" pointers all implicitly point forward; BACK
+ *		exists to make loop structures possible.
+ *
+ * STAR,PLUS	'?', and complex '*' and '+', are implemented as circular
+ *		BRANCH structures using BACK.  Simple cases (one character
+ *		per match) are implemented with STAR and PLUS for speed
+ *		and to minimize recursive plunges.
+ *
+ * OPEN,CLOSE	...are numbered at compile time.
+ */
+
+/*
+ * A node is one char of opcode followed by two chars of "next" pointer.
+ * "Next" pointers are stored as two 8-bit pieces, high order first.  The
+ * value is a positive offset from the opcode of the node containing it.
+ * An operand, if any, simply follows the node.  (Note that much of the
+ * code generation knows about this implicit relationship.)
+ *
+ * Using two bytes for the "next" pointer is vast overkill for most things,
+ * but allows patterns to get big without disasters.
+ */
+#define	OP(p)	(*(p))
+#define	NEXT(p)	(((*((p)+1)&0377)<<8) + *((p)+2)&0377)
+#define	OPERAND(p)	((p) + 3)
+
+
+
+/*
+ * Utility definitions.
+ */
+#ifndef CHARBITS
+#define	UCHARAT(p)	((int)*(ushort *)(p))
+#else
+#define	UCHARAT(p)	((int)*(p)&CHARBITS)
+#endif
+
+#define	FAIL(m)	{ regerror(m); return(NULL); }
+#define	ISMULT(c)	((c) == '*' || (c) == '+' || (c) == '?')
+#define	META	"^$.[()|?+*\\"
+
+/*
+ * Flags to be passed up and down.
+ */
+#define	HASWIDTH	01	/* Known never to match null string. */
+#define	SIMPLE		02	/* Simple enough to be STAR/PLUS operand. */
+#define	SPSTART		04	/* Starts with * or +. */
+#define	WORST		0	/* Worst case. */
+
+/*
+ * Global work variables for regcomp().
+ */
+static ushort *regparse;		/* Input-scan pointer. */
+static int regnpar;		/* () count. */
+static ushort regdummy;
+static ushort *regcode;		/* Code-emit pointer; &regdummy = don't. */
+static long regsize;		/* Code size. */
+
+/*
+ * Forward declarations for regcomp()'s friends.
+ */
+#ifndef STATIC
+#define	STATIC	static
+#endif
+STATIC ushort *reg();
+STATIC ushort *regbranch();
+STATIC ushort *regpiece();
+STATIC ushort *regatom();
+STATIC ushort *regnode();
+STATIC ushort *regnext();
+STATIC void regc();
+STATIC void reginsert();
+STATIC void regtail();
+STATIC void regoptail();
+STATIC int Strcspn();
+
+/*
+ - regcomp - compile a regular expression into internal code
+ *
+ * We can't allocate space until we know how big the compiled form will be,
+ * but we can't compile it (and thus know how big it is) until we've got a
+ * place to put the code.  So we cheat:  we compile it twice, once with code
+ * generation turned off and size counting turned on, and once "for real".
+ * This also means that we don't allocate space until we are sure that the
+ * thing really will compile successfully, and we never have to move the
+ * code and thus invalidate pointers into it.  (Note that it has to be in
+ * one piece because free() must be able to free it all.)
+ *
+ * Beware that the optimization-preparation code in here knows about some
+ * of the structure of the compiled regexp.
+ */
+regexp *
+regcomp(exp)
+ushort *exp;
+{
+  register regexp *r;
+  register ushort *scan;
+  register ushort *longest;
+  register int len;
+  int flags;
+  extern char *emalloc();
+
+  if (exp == NULL)
+	FAIL("NULL argument");
+
+  /* First pass: determine size, legality. */
+  regparse = exp;
+  regnpar = 1;
+  regsize = 0L;
+  regcode = &regdummy;
+  regc((ushort) MAGIC);
+  if (reg(0, &flags) == NULL)
+	return(NULL);
+
+  /* Small enough for pointer-storage convention? */
+  if (regsize >= 32767L)		/* Probably could be 65535L. */
+	FAIL("regexp too big");
+
+  /* Allocate space. */
+  r = (regexp *)emalloc(sizeof(regexp) + (unsigned)regsize * sizeof(ushort));
+
+  /* Second pass: emit code. */
+  regparse = exp;
+  regnpar = 1;
+  regcode = r->program;
+  regc((ushort) MAGIC);
+  if (reg(0, &flags) == NULL)
+	return(NULL);
+
+  /* Dig out information for optimizations. */
+  r->regstart = '\0';	/* Worst-case defaults. */
+  r->reganch = 0;
+  r->regmust = NULL;
+  r->regmlen = 0;
+  scan = r->program+1;			/* First BRANCH. */
+  if (OP(regnext(scan)) == END) {		/* Only one top-level choice. */
+	scan = OPERAND(scan);
+
+	/* Starting-point info. */
+	if (OP(scan) == EXACTLY)
+		r->regstart = *OPERAND(scan);
+	else if (OP(scan) == BOL)
+		r->reganch++;
+
+	/*
+	 * If there's something expensive in the r.e., find the
+	 * longest literal string that must appear and make it the
+	 * regmust.  Resolve ties in favor of later strings, since
+	 * the regstart check works with the beginning of the r.e.
+	 * and avoiding duplication strengthens checking.  Not a
+	 * strong reason, but sufficient in the absence of others.
+	 */
+	if (flags&SPSTART) {
+		longest = NULL;
+		len = 0;
+		for (; scan != NULL; scan = regnext(scan))
+			if (OP(scan) == EXACTLY && Strlen(OPERAND(scan)) >= len) {
+				longest = OPERAND(scan);
+				len = Strlen(OPERAND(scan));
+			}
+		r->regmust = longest;
+		r->regmlen = len;
+	}
+  }
+
+  return(r);
+}
+
+/*
+ - reg - regular expression, i.e. main body or parenthesized thing
+ *
+ * Caller must absorb opening parenthesis.
+ *
+ * Combining parenthesis handling with the base level of regular expression
+ * is a trifle forced, but the need to tie the tails of the branches to what
+ * follows makes it hard to avoid.
+ */
+static ushort *
+reg(paren, flagp)
+int paren;			/* Parenthesized? */
+int *flagp;
+{
+  register ushort *ret;
+  register ushort *br;
+  register ushort *ender;
+  register int parno;
+  int flags;
+
+  *flagp = HASWIDTH;	/* Tentatively. */
+
+  /* Make an OPEN node, if parenthesized. */
+  if (paren) {
+	if (regnpar >= NSUBEXP)
+		FAIL("too many ()");
+	parno = regnpar;
+	regnpar++;
+	ret = regnode(OPEN+parno);
+  } else
+	ret = NULL;
+
+  /* Pick up the branches, linking them together. */
+  br = regbranch(&flags);
+  if (br == NULL)
+	return(NULL);
+  if (ret != NULL)
+	regtail(ret, br);	/* OPEN -> first. */
+  else
+	ret = br;
+  if (!(flags&HASWIDTH))
+	*flagp &= ~HASWIDTH;
+  *flagp |= flags&SPSTART;
+  while (*regparse == '|') {
+	regparse++;
+	br = regbranch(&flags);
+	if (br == NULL)
+		return(NULL);
+	regtail(ret, br);	/* BRANCH -> BRANCH. */
+	if (!(flags&HASWIDTH))
+		*flagp &= ~HASWIDTH;
+	*flagp |= flags&SPSTART;
+  }
+
+  /* Make a closing node, and hook it on the end. */
+  ender = regnode((paren) ? CLOSE+parno : END);	
+  regtail(ret, ender);
+
+  /* Hook the tails of the branches to the closing node. */
+  for (br = ret; br != NULL; br = regnext(br))
+	regoptail(br, ender);
+
+  /* Check for proper termination. */
+  if (paren && *regparse++ != ')') {
+	FAIL("unmatched ()");
+  } else if (!paren && *regparse != '\0') {
+	if (*regparse == ')') {
+		FAIL("unmatched ()");
+	} else
+		FAIL("junk on end");	/* "Can't happen". */
+	/* NOTREACHED */
+  }
+
+  return(ret);
+}
+
+/*
+ - regbranch - one alternative of an | operator
+ *
+ * Implements the concatenation operator.
+ */
+static ushort *
+regbranch(flagp)
+int *flagp;
+{
+  register ushort *ret;
+  register ushort *chain;
+  register ushort *latest;
+  int flags;
+
+  *flagp = WORST;		/* Tentatively. */
+
+  ret = regnode(BRANCH);
+  chain = NULL;
+  while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
+	latest = regpiece(&flags);
+	if (latest == NULL)
+		return(NULL);
+	*flagp |= flags&HASWIDTH;
+	if (chain == NULL)	/* First piece. */
+		*flagp |= flags&SPSTART;
+	else
+		regtail(chain, latest);
+	chain = latest;
+  }
+  if (chain == NULL)	/* Loop ran zero times. */
+	(void) regnode(NOTHING);
+
+  return(ret);
+}
+
+/*
+ - regpiece - something followed by possible [*+?]
+ *
+ * Note that the branching code sequences used for ? and the general cases
+ * of * and + are somewhat optimized:  they use the same NOTHING node as
+ * both the endmarker for their branch list and the body of the last branch.
+ * It might seem that this node could be dispensed with entirely, but the
+ * endmarker role is not redundant.
+ */
+static ushort *
+regpiece(flagp)
+int *flagp;
+{
+  register ushort *ret;
+  register ushort op;
+  register ushort *next;
+  int flags;
+
+  ret = regatom(&flags);
+  if (ret == NULL)
+	return(NULL);
+
+  op = *regparse;
+  if (!ISMULT(op)) {
+	*flagp = flags;
+	return(ret);
+  }
+
+  if (!(flags&HASWIDTH) && op != '?')
+	FAIL("*+ operand could be empty");
+  *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
+
+  if (op == '*' && (flags&SIMPLE))
+	reginsert(STAR, ret);
+  else if (op == '*') {
+	/* Emit x* as (x&|), where & means "self". */
+	reginsert(BRANCH, ret);			/* Either x */
+	regoptail(ret, regnode(BACK));		/* and loop */
+	regoptail(ret, ret);			/* back */
+	regtail(ret, regnode(BRANCH));		/* or */
+	regtail(ret, regnode(NOTHING));		/* null. */
+  } else if (op == '+' && (flags&SIMPLE))
+	reginsert(PLUS, ret);
+  else if (op == '+') {
+	/* Emit x+ as x(&|), where & means "self". */
+	next = regnode(BRANCH);			/* Either */
+	regtail(ret, next);
+	regtail(regnode(BACK), ret);		/* loop back */
+	regtail(next, regnode(BRANCH));		/* or */
+	regtail(ret, regnode(NOTHING));		/* null. */
+  } else if (op == '?') {
+	/* Emit x? as (x|) */
+	reginsert(BRANCH, ret);			/* Either x */
+	regtail(ret, regnode(BRANCH));		/* or */
+	next = regnode(NOTHING);		/* null. */
+	regtail(ret, next);
+	regoptail(ret, next);
+  }
+  regparse++;
+  if (ISMULT(*regparse))
+	FAIL("nested *?+");
+
+  return(ret);
+}
+
+/*
+ - regatom - the lowest level
+ *
+ * Optimization:  gobbles an entire sequence of ordinary characters so that
+ * it can turn them into a single node, which is smaller to store and
+ * faster to run.  Backslashed characters are exceptions, each becoming a
+ * separate node; the code is simpler that way and it's not worth fixing.
+ */
+static ushort *
+regatom(flagp)
+int *flagp;
+{
+  register ushort *ret;
+  int flags;
+  ushort c, d;
+
+  *flagp = WORST;		/* Tentatively. */
+
+  switch ((int) *regparse++) {
+  case '^':
+	ret = regnode(BOL);
+	break;
+  case '$':
+	ret = regnode(EOL);
+	break;
+  case '.':
+	ret = regnode(ANY);
+	*flagp |= HASWIDTH|SIMPLE;
+	break;
+  case '[': {
+		register int class;
+		register int classend;
+		register int c;
+
+		if (*regparse == '^') {	/* Complement of range. */
+			ret = regnode(ANYBUT);
+			regparse++;
+		} else
+			ret = regnode(ANYOF);
+		if (*regparse == ']' || *regparse == '-')
+			regc(*regparse++);
+		while (*regparse != '\0' && *regparse != ']') {
+			if (*regparse == '-') {
+				regparse++;
+				if (*regparse == ']' || *regparse == '\0')
+					regc((ushort) '-');
+				else {
+					class = UCHARAT(regparse-2)+1;
+					classend = UCHARAT(regparse);
+					if (class > classend+1)
+						FAIL("invalid [] range");
+					regc((ushort) 0xffff);
+					regc((ushort) class);
+					regc((ushort) classend);
+					regparse++;
+				}
+			} else {
+				if ((c = *regparse++) == '\\') {
+					if ((c = *regparse++) == 'n')
+						c = '\n';
+					else if (c == 't')
+						c = '\t';
+				}
+				regc(c);
+			}
+		}
+		regc((ushort) 0);
+		if (*regparse != ']')
+			FAIL("unmatched []");
+		regparse++;
+		*flagp |= HASWIDTH|SIMPLE;
+	}
+	break;
+  case '(':
+	ret = reg(1, &flags);
+	if (ret == NULL)
+		return(NULL);
+	*flagp |= flags&(HASWIDTH|SPSTART);
+	break;
+  case '\0':
+  case '|':
+  case ')':
+	FAIL("internal urp");	/* Supposed to be caught earlier. */
+	break;
+  case '?':
+  case '+':
+  case '*':
+	FAIL("?+* follows nothing");
+	break;
+  case '\\':
+	if (*regparse == '\0')
+		FAIL("trailing \\");
+	ret = regnode(EXACTLY);
+/*
+	regc(*regparse++);
+*/
+	c = *regparse++;
+	if (c == 'n')
+		c = '\n';
+	else if (c == 't')
+		c = '\t';
+	else if (c == 'f')
+		c = '\f';
+	else if (c == '\r')
+		c = '\r';
+	else if (c == '\b')
+		c = '\b';
+	else if (IsDigid(c)) {
+		d = c - '0';
+		if (IsDigid(*regparse)) {
+			d = d * 8 + *regparse++ - '0';
+			if (IsDigid(*regparse))
+				d = d * 8 + *regparse++ - '0';
+		}
+		c = d;
+	}
+	regc(c);
+	regc((ushort) 0);
+	*flagp |= HASWIDTH|SIMPLE;
+	break;
+  default: {
+		register int len;
+		register char ender;
+
+		regparse--;
+		len = Strcspn(regparse, META);
+		if (len <= 0)
+			FAIL("internal disaster");
+		ender = *(regparse+len);
+		if (len > 1 && ISMULT(ender))
+			len--;		/* Back off clear of ?+* operand. */
+		*flagp |= HASWIDTH;
+		if (len == 1)
+			*flagp |= SIMPLE;
+		ret = regnode(EXACTLY);
+		while (len > 0) {
+			regc(*regparse++);
+			len--;
+		}
+		regc((ushort) 0);
+	}
+	break;
+  }
+
+  return(ret);
+}
+
+IsDigid(c) ushort c;
+{
+  return '0' <= c && c <= '9';
+}
+
+/*
+ - regnode - emit a node
+ */
+static ushort *			/* Location. */
+regnode(op)
+ushort op;
+{
+  register ushort *ret;
+  register ushort *ptr;
+
+  ret = regcode;
+  if (ret == &regdummy) {
+	regsize += 3;
+	return(ret);
+  }
+
+  ptr = ret;
+  *ptr++ = op;
+  *ptr++ = '\0';		/* Null "next" pointer. */
+  *ptr++ = '\0';
+  regcode = ptr;
+
+  return(ret);
+}
+
+/*
+ - regc - emit (if appropriate) a byte of code
+ */
+static void
+regc(b)
+ushort b;
+{
+  if (regcode != &regdummy)
+	*regcode++ = b;
+  else
+	regsize++;
+}
+
+/*
+ - reginsert - insert an operator in front of already-emitted operand
+ *
+ * Means relocating the operand.
+ */
+static void
+reginsert(op, opnd)
+ushort op;
+ushort *opnd;
+{
+  register ushort *src;
+  register ushort *dst;
+  register ushort *place;
+
+  if (regcode == &regdummy) {
+	regsize += 3;
+	return;
+  }
+
+  src = regcode;
+  regcode += 3;
+  dst = regcode;
+  while (src > opnd)
+	*--dst = *--src;
+
+  place = opnd;		/* Op node, where operand used to be. */
+  *place++ = op;
+  *place++ = '\0';
+  *place++ = '\0';
+}
+
+/*
+ - regtail - set the next-pointer at the end of a node chain
+ */
+static void
+regtail(p, val)
+ushort *p;
+ushort *val;
+{
+  register ushort *scan;
+  register ushort *temp;
+  register int offset;
+
+  if (p == &regdummy)
+	return;
+
+  /* Find last node. */
+  scan = p;
+  for (;;) {
+	temp = regnext(scan);
+	if (temp == NULL)
+		break;
+	scan = temp;
+  }
+
+  if (OP(scan) == BACK)
+	offset = scan - val;
+  else
+	offset = val - scan;
+  *(scan+1) = (offset>>8)&0377;
+  *(scan+2) = offset&0377;
+}
+
+/*
+ - regoptail - regtail on operand of first argument; nop if operandless
+ */
+static void
+regoptail(p, val)
+ushort *p;
+ushort *val;
+{
+  /* "Operandless" and "op != BRANCH" are synonymous in practice. */
+  if (p == NULL || p == &regdummy || OP(p) != BRANCH)
+	return;
+  regtail(OPERAND(p), val);
+}
+
+/*
+ * regexec and friends
+ */
+
+/*
+ * Global work variables for regexec().
+ */
+static ushort *reginput;		/* String-input pointer. */
+static ushort *regbol;		/* Beginning of input, for ^ check. */
+static ushort **regstartp;	/* Pointer to startp array. */
+static ushort **regendp;		/* Ditto for endp. */
+
+/*
+ * Forwards.
+ */
+STATIC int regtry();
+STATIC int regmatch();
+STATIC int regrepeat();
+
+#ifdef DEBUG
+int regnarrate = 0;
+void regdump();
+STATIC char *regprop();
+#endif
+
+/*
+ - regexec - match a regexp against a string
+ */
+int
+regexec(prog, string, bolflag)
+register regexp *prog;
+register ushort *string;
+int bolflag;
+{
+  register ushort *s;
+  extern ushort *Strchr();
+
+  /* Be paranoid... */
+  if (prog == NULL || string == NULL) {
+	regerror("NULL parameter");
+	return(0);
+  }
+
+  /* Check validity of program. */
+  if (prog->program[0] != MAGIC) {
+	regerror("corrupted program");
+	return(0);
+  }
+
+  /* If there is a "must appear" string, look for it. */
+  if (prog->regmust != NULL) {
+	s = string;
+	while ((s = Strchr(s, prog->regmust[0])) != NULL) {
+		if (Strncmp(s, prog->regmust, prog->regmlen) == 0)
+			break;	/* Found it. */
+		s++;
+	}
+	if (s == NULL)	/* Not present. */
+		return(0);
+  }
+
+  /* Mark beginning of line for ^ . */
+  if(bolflag)
+	regbol = string;
+  else
+	regbol = NULL;
+
+  /* Simplest case:  anchored match need be tried only once. */
+  if (prog->reganch)
+	return(regtry(prog, string));
+
+  /* Messy cases:  unanchored match. */
+  s = string;
+  if (prog->regstart != '\0') {
+	/* We know what char it must start with. */
+	while ((s = Strchr(s, prog->regstart)) != NULL) {
+		if (regtry(prog, s))
+			return(1);
+		s++;
+	}
+}
+  else
+	/* We don't -- general case. */
+	do {
+		if (regtry(prog, s))
+			return(1);
+	} while (*s++ != '\0');
+
+  /* Failure. */
+  return(0);
+}
+
+/*
+ - regtry - try match at specific point
+ */
+static int			/* 0 failure, 1 success */
+regtry(prog, string)
+regexp *prog;
+ushort *string;
+{
+  register int i;
+  register ushort **sp;
+  register ushort **ep;
+
+  reginput = string;
+  regstartp = prog->startp;
+  regendp = prog->endp;
+
+  sp = prog->startp;
+  ep = prog->endp;
+  for (i = NSUBEXP; i > 0; i--) {
+	*sp++ = NULL;
+	*ep++ = NULL;
+  }
+  if (regmatch(prog->program + 1)) {
+	prog->startp[0] = string;
+	prog->endp[0] = reginput;
+	return(1);
+  } else
+	return(0);
+}
+
+/*
+ - regmatch - main matching routine
+ *
+ * Conceptually the strategy is simple:  check to see whether the current
+ * node matches, call self recursively to see whether the rest matches,
+ * and then act accordingly.  In practice we make some effort to avoid
+ * recursion, in particular by going through "ordinary" nodes (that don't
+ * need to know whether the rest of the match failed) by a loop instead of
+ * by recursion.
+ */
+static int			/* 0 failure, 1 success */
+regmatch(prog)
+ushort *prog;
+{
+  register ushort *scan;	/* Current node. */
+  ushort *next;		/* Next node. */
+  extern ushort *Strchr();
+
+  scan = prog;
+#ifdef DEBUG
+  if (scan != NULL && regnarrate)
+	fprintf(stderr, "%s(\n", regprop(scan));
+#endif
+  while (scan != NULL) {
+#ifdef DEBUG
+	if (regnarrate)
+		fprintf(stderr, "%s...\n", regprop(scan));
+#endif
+	next = regnext(scan);
+
+	switch ((int) OP(scan)) {
+	case BOL:
+		if (reginput != regbol)
+			return(0);
+		break;
+	case EOL:
+		if (*reginput != '\0')
+			return(0);
+		break;
+	case ANY:
+		if (*reginput == '\0')
+			return(0);
+		reginput++;
+		break;
+	case EXACTLY: {
+			register int len;
+			register ushort *opnd;
+
+			opnd = OPERAND(scan);
+			/* Inline the first character, for speed. */
+			if (*opnd != *reginput)
+				return(0);
+			len = Strlen(opnd);
+			if (len > 1 && Strncmp(opnd, reginput, len) != 0)
+				return(0);
+			reginput += len;
+		}
+		break;
+	case ANYOF:
+		if (*reginput == '\0' || isthere(OPERAND(scan), *reginput) == 0)
+			return(0);
+		reginput++;
+		break;
+	case ANYBUT:
+		if (*reginput == '\0' || isthere(OPERAND(scan), *reginput) != 0)
+			return(0);
+		reginput++;
+		break;
+	case NOTHING:
+		break;
+	case BACK:
+		break;
+	case OPEN+1:
+	case OPEN+2:
+	case OPEN+3:
+	case OPEN+4:
+	case OPEN+5:
+	case OPEN+6:
+	case OPEN+7:
+	case OPEN+8:
+	case OPEN+9: {
+			register int no;
+			register ushort *save;
+
+			no = OP(scan) - OPEN;
+			save = reginput;
+
+			if (regmatch(next)) {
+				/*
+				 * Don't set startp if some later
+				 * invocation of the same parentheses
+				 * already has.
+				 */
+				if (regstartp[no] == NULL)
+					regstartp[no] = save;
+				return(1);
+			} else
+				return(0);
+		}
+		break;
+	case CLOSE+1:
+	case CLOSE+2:
+	case CLOSE+3:
+	case CLOSE+4:
+	case CLOSE+5:
+	case CLOSE+6:
+	case CLOSE+7:
+	case CLOSE+8:
+	case CLOSE+9: {
+			register int no;
+			register ushort *save;
+
+			no = OP(scan) - CLOSE;
+			save = reginput;
+
+			if (regmatch(next)) {
+				/*
+				 * Don't set endp if some later
+				 * invocation of the same parentheses
+				 * already has.
+				 */
+				if (regendp[no] == NULL)
+					regendp[no] = save;
+				return(1);
+			} else
+				return(0);
+		}
+		break;
+	case BRANCH: {
+			register ushort *save;
+
+			if (OP(next) != BRANCH)		/* No choice. */
+				next = OPERAND(scan);	/* Avoid recursion. */
+			else {
+				do {
+					save = reginput;
+					if (regmatch(OPERAND(scan)))
+						return(1);
+					reginput = save;
+					scan = regnext(scan);
+				} while (scan != NULL && OP(scan) == BRANCH);
+				return(0);
+				/* NOTREACHED */
+			}
+		}
+		break;
+	case STAR:
+	case PLUS: {
+			register ushort nextch;
+			register int no;
+			register ushort *save;
+			register int min;
+
+			/*
+			 * Lookahead to avoid useless match attempts
+			 * when we know what character comes next.
+			 */
+			nextch = '\0';
+			if (OP(next) == EXACTLY)
+				nextch = *OPERAND(next);
+			min = (OP(scan) == STAR) ? 0 : 1;
+			save = reginput;
+			no = regrepeat(OPERAND(scan));
+			while (no >= min) {
+				/* If it could work, try it. */
+				if (nextch == '\0' || *reginput == nextch)
+					if (regmatch(next))
+						return(1);
+				/* Couldn't or didn't -- back up. */
+				no--;
+				reginput = save + no;
+			}
+			return(0);
+		}
+		break;
+	case END:
+		return(1);	/* Success! */
+		break;
+	default:
+		regerror("memory corruption");
+		return(0);
+		break;
+	}
+
+	scan = next;
+  }
+
+  /*
+   * We get here only if there's trouble -- normally "case END" is
+   * the terminating point.
+   */
+  regerror("corrupted pointers");
+  return(0);
+}
+
+/*
+ - regrepeat - repeatedly match something simple, report how many
+ */
+static int
+regrepeat(p)
+ushort *p;
+{
+  register int count = 0;
+  register ushort *scan;
+  register ushort *opnd;
+
+  scan = reginput;
+  opnd = OPERAND(p);
+  switch (OP(p)) {
+  case ANY:
+	count = Strlen(scan);
+	scan += count;
+	break;
+  case EXACTLY:
+	while (*opnd == *scan) {
+		count++;
+		scan++;
+	}
+	break;
+  case ANYOF:
+	while (*scan != '\0' && isthere(opnd, *scan) != 0) {
+		count++;
+		scan++;
+	}
+	break;
+  case ANYBUT:
+	while (*scan != '\0' && isthere(opnd, *scan) == 0) {
+		count++;
+		scan++;
+	}
+	break;
+  default:		/* Oh dear.  Called inappropriately. */
+	regerror("internal foulup");
+	count = 0;	/* Best compromise. */
+	break;
+  }
+  reginput = scan;
+
+  return(count);
+}
+
+/*
+ - regnext - dig the "next" pointer out of a node
+ */
+static ushort *
+regnext(p)
+register ushort *p;
+{
+  register int offset;
+
+  if (p == &regdummy)
+	return(NULL);
+
+  offset = NEXT(p);
+  if (offset == 0)
+	return(NULL);
+
+  if (OP(p) == BACK)
+	return(p-offset);
+  else
+	return(p+offset);
+}
+
+#ifdef DEBUG
+
+STATIC char *regprop();
+
+/*
+ - regdump - dump a regexp onto stdout in vaguely comprehensible form
+ */
+void
+regdump(r)
+regexp *r;
+{
+  register ushort *s;
+  register ushort op = EXACTLY;	/* Arbitrary non-END op. */
+  register ushort *next;
+
+
+  s = r->program + 1;
+  while (op != END) {	/* While that wasn't END last time... */
+	op = OP(s);
+	printf("%2d%s", s-r->program, regprop(s));	/* Where, what. */
+	next = regnext(s);
+	if (next == NULL)		/* Next ptr. */
+		printf("(0)");
+	else 
+		printf("(%d)", (s-r->program)+(next-s));
+	s += 3;
+	if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
+		/* Literal string, where present. */
+		while (*s != '\0') {
+			if (*s == 0xffff) {	/* range */
+				kputchar(*++s); putchar('-'); ++s;
+			}
+			kputchar(*s++);
+		}
+		s++;
+	}
+	putchar('\n');
+  }
+
+  /* Header fields of interest. */
+  if (r->regstart != '\0') {
+	fputs("start `", stdout); kputchar(r->regstart); fputs("' ", stdout);
+  }
+  if (r->reganch)
+	printf("anchored ");
+  if (r->regmust != NULL) {
+	fputs("must have \"", stdout); kputs(r->regmust); putchar('"');
+  }
+  printf("\n");
+}
+
+kputchar(c) ushort c;
+{
+  if (c & 0xff00)
+	putchar(c >> 8);
+  putchar(c & 0xff);
+}
+
+kputs(s) ushort *s;
+{
+  while (*s)
+	kputchar(*s++);
+}
+
+/*
+ - regprop - printable representation of opcode
+ */
+static char *
+regprop(op)
+ushort *op;
+{
+  register char *p;
+  static char buf[50];
+
+  (void) strcpy(buf, ":");
+
+  switch ((int) OP(op)) {
+  case BOL:
+	p = "BOL";
+	break;
+  case EOL:
+	p = "EOL";
+	break;
+  case ANY:
+	p = "ANY";
+	break;
+  case ANYOF:
+	p = "ANYOF";
+	break;
+  case ANYBUT:
+	p = "ANYBUT";
+	break;
+  case BRANCH:
+	p = "BRANCH";
+	break;
+  case EXACTLY:
+	p = "EXACTLY";
+	break;
+  case NOTHING:
+	p = "NOTHING";
+	break;
+  case BACK:
+	p = "BACK";
+	break;
+  case END:
+	p = "END";
+	break;
+  case OPEN+1:
+  case OPEN+2:
+  case OPEN+3:
+  case OPEN+4:
+  case OPEN+5:
+  case OPEN+6:
+  case OPEN+7:
+  case OPEN+8:
+  case OPEN+9:
+	sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
+	p = NULL;
+	break;
+  case CLOSE+1:
+  case CLOSE+2:
+  case CLOSE+3:
+  case CLOSE+4:
+  case CLOSE+5:
+  case CLOSE+6:
+  case CLOSE+7:
+  case CLOSE+8:
+  case CLOSE+9:
+	sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
+	p = NULL;
+	break;
+  case STAR:
+	p = "STAR";
+	break;
+  case PLUS:
+	p = "PLUS";
+	break;
+  default:
+	regerror("corrupted opcode");
+	break;
+  }
+  if (p != NULL)
+	(void) strcat(buf, p);
+  return(buf);
+}
+#endif
+
+/*
+ * The following is provided for those people who do not have strcspn() in
+ * their C libraries.  They should get off their butts and do something
+ * about it; at least one public-domain implementation of those (highly
+ * useful) string routines has been published on Usenet.
+ */
+/*
+ * strcspn - find length of initial segment of s1 consisting entirely
+ * of characters not from s2
+ */
+
+static int
+Strcspn(s1, s2)
+ushort *s1;
+unsigned char *s2;
+{
+  register ushort *scan1;
+  register unsigned char *scan2;
+  register int count;
+
+  count = 0;
+  for (scan1 = s1; *scan1 != '\0'; scan1++) {
+	for (scan2 = s2; *scan2 != '\0';)	/* ++ moved down. */
+		if (*scan1 == *scan2++)
+			return(count);
+	count++;
+  }
+  return(count);
+}
+
+isthere(s, c) ushort *s, c;
+{
+  register unsigned int c1, c2;
+
+  for ( ; *s; s++) {
+	if (*s == 0xffff) {	/* range */
+		c1 = *++s; c2 = *++s;
+		if (c1 <= c && c <= c2)
+			return 1;
+	}
+	else if (*s == c)
+		return 1;
+  }
+  return 0;
+}
+
+ushort *
+Strchr(s, c) ushort *s, c;
+{
+  for ( ; *s; s++)
+	if (*s == c)
+		return s;
+  return NULL;
+}
+
+Strncmp(s, t, n) ushort *s, *t;
+{
+  for ( ; --n > 0 && *s == *t; s++, t++)
+	;
+  return *s - *t;
+}
+
+Strlen(s) ushort *s;
+{
+  int i;
+
+  for (i = 0; *s; i++, s++)
+	;
+  return i;
+}
+
+ushort kbuf[BUFSIZ];
+
+char *
+mkpat(s) char *s;
+{
+  sjtok(kbuf, s);
+  return (char *) regcomp(kbuf);
+}
+
+match(p, s) regexp *p; char *s;
+{
+  register int i;
+
+  sjtok(kbuf, s);
+  if (i = regexec(p, kbuf, 1)) {
+	r_start = p->startp[0] - kbuf + 1;
+	r_length = p->endp[0] - p->startp[0];
+  }
+  else
+	r_start = r_length = 0;
+  return i;
+}
+
+sjtok(s, t) ushort *s; unsigned char *t;
+{
+  register c;
+
+  for ( ; *t; t++) {
+	if (isKanji(c = *t))
+		c = (c << 8) | (*++t & 0xff);
+	*s++ = c;
+  }
+  *s = 0;
+}
+
+ktosj(s, t) unsigned char *s; ushort *t;
+{
+  register c;
+
+  while (*t) {
+	if ((c = *t++) & 0xff00)
+		*s++ = c >> 8;
+	*s++ = c & 0xff;
+  }
+  *s = '\0';
+}
+
+regsub(dst, exp, src, pat, pos) ushort *dst, *src, *pat; regexp *exp;
+{	/* dst <-- s/src/pat/pos	global substitution for pos == 0 */
+  register int c, i;
+  register ushort *loc1, *loc2, *s, *t, *u;
+  register int n = 0;
+
+  if (exp->program[0] != MAGIC) {
+	regerror("damaged regexp fed to regsub");
+	return 0;
+  }
+  while (*src) {
+next:
+	if (regexec(exp, src, 1) == 0)
+		break;
+	loc1 = exp->startp[0]; loc2 = exp->endp[0];
+	if (pos-- > 1) {
+		while (src < loc2)
+			*dst++ = *src++;
+		goto next;
+	}
+	while (src < loc1)
+		*dst++ = *src++;
+	for (s = pat; c = *s++; ) {
+		if (c == '&')
+			i = 0;
+		else if (c == '\\' && '0' <= *s && *s <= '9')
+			i = *s++ - '0';
+		else {
+			if (c == '\\' && (*s == '\\' || *s == '&'))
+				c = *s++;
+			*dst++ = c;
+			continue;
+		}
+		if ((t = exp->startp[i]) != NULL
+			&& (u = exp->endp[i]) != NULL) {
+			while (t < u)
+				*dst++ = *t++;
+		}
+	}
+	src = loc2;
+	n++;
+	if (pos == 0)
+		break;
+  }
+  while (*src)
+	*dst++ = *src++;
+  *dst++ = 0;
+  return n;
+}
+
+static ushort kbuf1[BUFSIZ], kbuf2[BUFSIZ];
+
+Sub(u, exp, str, s, t, pos) char *exp; char *s, *t, *u;
+{
+  register int i;
+  regexp *r;
+
+  if (str) {
+	sjtok(kbuf, exp);
+	r = regcomp(kbuf);
+  }
+  else
+	r = (regexp *) exp;
+  sjtok(kbuf, s);
+  sjtok(kbuf1, t);
+  i = regsub(kbuf2, r, kbuf1, kbuf, pos);
+  ktosj(u, kbuf2);
+  if (str)
+	sfree(r);
+
+  return i;
+}
Index: /trunk/minix/commands/awk/regexp.h
===================================================================
--- /trunk/minix/commands/awk/regexp.h	(revision 9)
+++ /trunk/minix/commands/awk/regexp.h	(revision 9)
@@ -0,0 +1,23 @@
+/*
+ * Definitions etc. for regexp(3) routines.
+ *
+ * Caveat:  this is V8 regexp(3) [actually, a reimplementation thereof],
+ * not the System V one.
+ */
+#define ushort	unsigned short
+#define CHARBITS 0xffff
+#define NSUBEXP  10
+typedef struct regexp {
+	ushort *startp[NSUBEXP];
+	ushort *endp[NSUBEXP];
+	ushort regstart;		/* Internal use only. */
+	ushort reganch;		/* Internal use only. */
+	ushort *regmust;		/* Internal use only. */
+	int regmlen;		/* Internal use only. */
+	ushort program[1];	/* Unwarranted chumminess with compiler. */
+} regexp;
+
+extern regexp *regcomp();
+extern int regexec();
+extern int regsub();
+extern int regerror();
Index: /trunk/minix/commands/awk/v.c
===================================================================
--- /trunk/minix/commands/awk/v.c	(revision 9)
+++ /trunk/minix/commands/awk/v.c	(revision 9)
@@ -0,0 +1,689 @@
+/*
+ * a small awk clone
+ *
+ * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
+ *
+ * Absolutely no warranty. Use this software with your own risk.
+ *
+ * Permission to use, copy, modify and distribute this software for any
+ * purpose and without fee is hereby granted, provided that the above
+ * copyright and disclaimer notice.
+ *
+ * This program was written to fit into 64K+64K memory of the Minix 1.2.
+ */
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include "awk.h"
+#include "regexp.h"
+
+#define PI	3.14159265358979323846
+
+#define HASHSIZE	50
+#define MAXFIELD	100
+
+double atof();
+char *getsval(), *jStrchar();
+extern CELL *execute(), *_Arg();
+
+extern char record[];
+extern CELL *field[];
+
+extern CELL truecell, falsecell;
+extern prmflg;
+
+SYMBOL *hashtab[HASHSIZE];
+SYMBOL *funtab[HASHSIZE];
+SYMBOL *argtab[HASHSIZE];
+
+char *strsave(), *emalloc(), *strchr();
+CELL *lookup(), *install(), *_install(), *mkcell(), *mktmp(), *getvar();
+
+char **FS, **RS, **OFS, **ORS, **OFMT, **FILENAME;
+char **SUBSEP;
+double *NR, *NF;
+double *FNR, *ARGC, *RSTART, *RLENGTH;
+
+init()
+{
+  FS = &install("FS", VAR|STR, " ", 0.0, hashtab)->c_sval;
+  RS = &install("RS", VAR|STR, "\n", 0.0, hashtab)->c_sval;
+  OFS = &install("OFS", VAR|STR , " ", 0.0, hashtab)->c_sval;
+  ORS = &install("ORS", VAR|STR, "\n", 0.0, hashtab)->c_sval;
+  OFMT = &install("OFMT", VAR|STR, "%.6g", 0.0, hashtab)->c_sval;
+  NR = &install("NR", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
+  NF = &install("NF", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
+  FILENAME = &install("FILENAME", VAR|STR, (char *)NULL, 0.0, hashtab)->c_sval;
+  install("PI", VAR|NUM, (char *)NULL, PI, hashtab);
+  field[0] = mkcell(REC|STR, (char *)NULL, 0.0);	/* $0 */
+  field[0]->c_sval = record;
+  SUBSEP = &install("SUBSEP", VAR|STR, "\034", 0.0, hashtab)->c_sval;
+  FNR = &install("FNR", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
+  RSTART = &install("RSTART", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
+  RLENGTH = &install("RLENGTH", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
+}
+
+setvar(s) char *s;
+{
+  CELL *u;
+  char *t;
+
+  for (t = s; *t && *t != '='; t++)
+	;
+  *t++ = '\0';
+  if ((u = lookup(s, hashtab)) == (CELL *)NULL) {
+	if (isnum(t))
+		install(s, VAR|NUM|STR, t, atof(t), hashtab);
+	else
+		install(s, VAR|STR, t, 0.0, hashtab);
+  }
+  else {
+	if (isnum(t))
+		setfval(u, atof(t));
+	else
+		setsval(u, t);
+  }
+}
+
+initarg(arg0, argc, argv) char *arg0, **argv;
+{
+  CELL *u;
+  register int i;
+  register char str[4];
+
+  ARGC = &install("ARGC", VAR|NUM, (char *)NULL, (double)argc+1, hashtab)->c_fval;
+  u = install("ARGV", ARR, (char *)NULL, 0.0, hashtab);
+  u->c_sval = (char *) argtab;
+  install("0", VAR|STR, arg0, 0.0, argtab);
+  for (i = 0; i < argc; i++) {
+	sprintf(str, "%d", i+1);
+	if (isnum(argv[i]))
+		install(str, VAR|STR|NUM, argv[i], atof(argv[i]), argtab);
+	else
+		install(str, VAR|STR, argv[i], 0.0, argtab);
+  }
+}
+
+static
+hash(s) unsigned char *s;
+{
+  register unsigned int h;
+
+  for (h = 0; *s; )
+	h += *s++;
+  return h % HASHSIZE;
+}
+
+CELL *
+lookup(s, h) char *s; SYMBOL *h[];
+{
+  register SYMBOL *p;
+
+  for (p = h[hash(s)]; p; p = p->s_next)
+	if (strcmp(s, p->s_name) == 0)
+		return p->s_val;
+  return (CELL *)NULL;
+}
+
+static CELL *
+install(name, type, sval, fval, h) char *name, *sval; double fval; SYMBOL *h[];
+{
+  CELL *u;
+
+  if ((u = lookup(name, h)) == (CELL *)NULL)
+	u = _install(name, type, sval, fval, h);
+  else
+	error("%s is doubly defined", name);
+  return u;
+}
+
+static CELL *
+_install(name, type, sval, fval, h) char *name, *sval; double fval; SYMBOL *h[];{
+  register SYMBOL *p;
+  CELL *u;
+  int hval;
+
+  p = (SYMBOL *) emalloc(sizeof(*p));
+  u = (CELL *) emalloc(sizeof(*u));
+  p->s_name = strsave(name);
+  p->s_val = u;
+  hval = hash(name);
+  p->s_next = h[hval];
+  h[hval] = p;
+  u->c_type = type;
+  u->c_sval = strsave(sval);
+#if 0
+  if (!(type & NUM) && isnum(sval)) {
+	u->c_fval = atof(sval);
+	u->c_type |= NUM;
+  }
+  else
+#endif
+	u->c_fval = fval;
+  return u;
+}
+
+CELL *
+getvar(s, h, typ) char *s; SYMBOL *h[];
+{
+  CELL *u;
+  SYMBOL *p;
+  char *t;
+  int i, hval;
+
+  if ((u = lookup(s, h)) == (CELL *)NULL) {
+	if (prmflg) {
+		u = _install(s, UDF, "", 0.0, h);
+		goto rtn;
+	}
+	else if (typ & ARR) {
+		t = emalloc(sizeof(SYMBOL *) * HASHSIZE);
+		for (i = 0; i < HASHSIZE; i++)
+			((SYMBOL **) t)[i] = (SYMBOL *)NULL;
+		u = (CELL *) emalloc(sizeof(*u));
+		u->c_type = typ;
+		u->c_sval = t;
+		u->c_fval = 0.0;
+		p = (SYMBOL *) emalloc(sizeof(*p));
+		p->s_name = strsave(s);
+		p->s_val = u;
+		hval = hash(s);
+		p->s_next = h[hval];
+		h[hval] = p;
+	}
+	else
+		u = _install(s, typ, "", 0.0, h);
+  }
+  else if (!prmflg && (u->c_type == UDF) && (typ != UDF)) {
+	/* fix up local_var/forward_function */
+	if (typ == ARR) {
+/*
+printf("getvar_correct_to_array\n");
+*/
+		u->c_type = typ;
+		sfree(u->c_sval);
+		u->c_sval = emalloc(sizeof(SYMBOL *) * HASHSIZE);
+		for (i = 0; i < HASHSIZE; i++)
+			((SYMBOL **) u->c_sval)[i] = (SYMBOL *)NULL;
+		u->c_fval = 0.0;
+	}
+	else if (typ != UDF) {
+		u->c_type = typ;
+	}
+ }
+rtn:
+  return u;
+}
+
+fixarray(u) CELL *u;
+{
+  int i;
+
+  if (u->c_type == UDF) {	/* fix up local var */
+/*
+printf("fixarray\n");
+*/
+	u->c_type = ARR;
+	sfree(u->c_sval);
+	u->c_sval = emalloc(sizeof(SYMBOL *) * HASHSIZE);
+	for (i = 0; i < HASHSIZE; i++)
+		((SYMBOL **) u->c_sval)[i] = (SYMBOL *)NULL;
+	u->c_fval = 0.0;
+  }
+}
+
+a_free(u) CELL *u;
+{	/* free local array */
+  SYMBOL **h, *q, *r;
+  CELL *v;
+  int i;
+
+  if (!(u->c_type & ARR))
+	error("try to free non array variable", (char *)0);
+  h = (SYMBOL **) u->c_sval;
+  for (i = 0; i < HASHSIZE; i++)
+	for (q = h[i]; q; q = r) {
+		r = q->s_next;
+		sfree(q->s_name);
+		v = q->s_val;	/* CELL */
+		c_free(v);
+		sfree(q);	/* SYMBOL */
+	}
+
+  sfree(u->c_sval);	/* symbol table */
+  c_free(u);
+}
+
+CELL *
+Array(p) NODE *p;
+{
+  CELL *u;
+  char str[BUFSIZ];
+  int i, n;
+
+  CELL *v;
+
+  u = (CELL *) p->n_arg[0];
+  if (u->c_type == POS) {
+	i = (int)u->c_fval;
+/*
+printf("**ARG_ARRAY(%d)*\n", i);
+*/
+	u = _Arg(i);
+	if (u->c_type == UDF) {	/* fix up local array */
+/*
+printf("local_var_to_array\n");
+*/
+		fixarray(u);
+	}
+  }
+  else if (!(u->c_type & ARR))
+	error("non array refference");
+  arrayelm(p, str);
+  u = getvar(str, u->c_sval, VAR|NUM|STR);	/* "rtsort in AWK book */
+  return u;
+}
+
+static
+arrayelm(p, s) NODE *p; char *s;
+{
+  CELL *u;
+  int i, n;
+  char *t;
+
+/*
+char *tt = s;
+*/
+  n = (int) p->n_arg[1] + 2;
+  for (i = 2; i < n; i++) {
+	if (i > 2)
+		*s++ = **SUBSEP;
+	u = execute(p->n_arg[i]);
+	for (t = getsval(u); *t; )
+		*s++ = *t++;
+	c_free(u);
+  }
+  *s = '\0';
+/*
+printf("array_elm(%s)\n", tt);
+*/
+}
+
+CELL *
+Element(p) NODE *p;
+{
+  char str[BUFSIZ];
+
+  arrayelm(p, str);
+  return mktmp(STR, str, 0.0);
+}
+
+CELL *
+Delete(p) NODE *p;
+{
+  CELL *u;
+  char str[BUFSIZ];
+  int i;
+  SYMBOL *q, *r, **h;
+
+  u = (CELL *) p->n_arg[0];
+  if (!(u->c_type & ARR))
+	error("can't delete non array variable");
+  arrayelm(p, str);
+  h = (SYMBOL **) u->c_sval;
+  for (r = (SYMBOL *)NULL, i = hash(str), q = h[i]; q; r = q, q = q->s_next)
+	if (strcmp(str, q->s_name) == 0)
+		break;
+  if (q) {
+	sfree(q->s_val->c_sval);
+	sfree(q->s_name);
+	if (r)
+		r->s_next = q->s_next;
+	if (q == h[i])
+		h[i] = (SYMBOL *)NULL;
+  }
+  return &truecell;
+}
+
+CELL *
+In(p) NODE *p;
+{
+  SYMBOL **h, *q;
+  CELL *u, *v;
+  char *s;
+  int i;
+
+  u = (CELL *) p->n_arg[1];	/* array */
+  if (!(u->c_type & ARR))
+	error("%s is not an array", u->c_sval);
+  h = (SYMBOL **) u->c_sval;
+  if (u->c_sval != (char *)NULL) {
+	v = execute(p->n_arg[0]);	/* var */
+	s = getsval(v);
+	for (i = 0; i < HASHSIZE; i++)
+		for (q = h[i]; q; q = q->s_next) {
+			if (strcmp(s, q->s_name) == 0) {
+				c_free(v);
+				return &truecell;
+			}
+		}
+	c_free(v);
+  }
+  return &falsecell;
+}
+
+CELL *
+Split(p) NODE *p;
+{
+  CELL *u, *v, *w;
+  char *s, *t, *h, *name, *sep;
+  int i, n, skip;
+  char elm[8], str[BUFSIZ];
+  static char *s_str;
+  static regexp *s_pat;
+  regexp *mkpat();
+  extern int r_start, r_length;
+
+  n = (int) p->n_arg[1];
+  if (n > 1) {
+	u = execute(p->n_arg[2]);
+	s = getsval(u);			/* str */
+	v = execute(p->n_arg[3]);	/* array */
+	if (!(v->c_type & ARR)) {
+/*
+printf("Split fix_to_array(%d)\n", v->c_type);
+*/
+		if (v->c_type == UDF)	/* fix up local array */
+			fixarray(v);
+		else
+			error("split to non array variable", (char *)0);
+	}
+	h = v->c_sval;
+	c_free(v);
+	if (n > 2) {
+		v = execute(p->n_arg[4]);
+		sep = getsval(v);
+	}
+	else {
+		v = (CELL *)NULL;
+		sep = *FS;
+	}
+	if (strlen(sep) > 1) {	/* reg_exp */
+		if (strcmp(sep, s_str) != 0) {
+			sfree(s_str); sfree(s_pat);
+			s_str = strsave(sep);
+			s_pat = mkpat(s_str);
+		}
+		for (i = 0, t = str; *s; ) {
+			if (match(s_pat, s)) {
+				for (n = r_start; --n > 0; )
+					*t++ = *s++;
+			}
+			else {
+				while(*s)
+					*t++ = *s++;
+			}
+			*t = '\0';
+			t = str;
+			sprintf(elm, "%d", ++i);
+			w = getvar(elm, h, VAR);
+			if (isnum(str))
+				setfval(w, atof(str));
+			else
+				setsval(w, str);
+			if (*s)
+				s += r_length;
+		}
+	}
+	else {
+		skip = *sep == ' ';
+		for (i = 0; t = str, *s; ) {
+			if (skip)
+				while (jStrchr(" \t\n", *s))
+					s++;
+			if (!(*s))
+				break;
+			while (*s && !jStrchr(sep, *s)) {
+				if (isKanji(*s))
+					*t++ = *s++;
+				*t++ = *s++;
+			}
+			*t = '\0';
+			sprintf(elm, "%d", ++i);
+			w = getvar(elm, h, VAR);
+			if (isnum(str))
+				setfval(w, atof(str));
+			else
+				setsval(w, str);
+			if (*s && !skip)
+				s++;
+		}
+	}
+	c_free(v);	/* sep */
+	c_free(u);	/* str may be CATed */
+  }
+  else
+	i = 0;
+  return mktmp(NUM, (char *)NULL, (double) i);
+}
+
+CELL *
+Forin(p) NODE *p;
+{
+  CELL *u, *v;
+  SYMBOL **h, *q;
+  char *name;
+  int i;
+
+  u = execute(p->n_arg[1]);
+  if (!(u->c_type & ARR))
+	synerr(
+	"non array variable is specified in 'for (. in var)'", (char *)0);
+  h = (SYMBOL **) u->c_sval;
+  c_free(u);
+  u = execute(p->n_arg[0]);
+  if (u->c_type == UDF) {
+/*
+printf("Forin_fix_to_VAR|NUM\n");
+*/
+	u->c_type = VAR|NUM;
+  }
+  if (!(u->c_type & VAR))
+	error("'for (VAR in .)' is not variable (%d)", name, u->c_type);
+  for (i = 0; i < HASHSIZE; i++) {
+	for (q = h[i]; q; q = q->s_next) {
+		setsval(u, q->s_name);
+		v = execute(p->n_arg[2]);
+		c_free(v);
+	}
+  }
+  c_free(u);
+  return &truecell;
+}
+
+char *
+strsave(s) char *s;
+{
+  register int n;
+  char *emalloc(), *strcpy();
+
+  if (s == (char *)NULL)
+	return (char *)NULL;
+  n = strlen(s) + 1;
+  return strcpy(emalloc(n), s);
+}
+
+sfree(p) char *p;
+{
+  if (p != (char *)NULL)
+	Free(p);
+}
+
+isnum(s) char *s;
+{
+  char *strchr();
+
+  if (s == NULL || *s == '\0' || !strcmp(s, "."))
+	return 0;
+  if (*s && strchr("+-", *s) != (char *)NULL)
+	s++;
+  if (*s == '\0')
+	return 0;
+  while (isdigit(*s))
+	s++;
+  if (*s == '.') {
+	s++;
+	while (isdigit(*s))
+		s++;
+  }
+  if (*s && strchr("eE", *s) != (char *)NULL) {
+	s++;
+	if (*s == '\0')
+		return 0;
+	if (*s && strchr("+-", *s) != (char *)NULL)
+		s++;
+	while (isdigit(*s))
+		s++;
+  }
+  return *s == '\0';
+}
+
+setfval(u, f) CELL *u; double f;
+{
+  if (u->c_type == UDF) {	/* fix up local var */
+/*
+printf("setfval_fix_to_VAR\n");
+*/
+	u->c_type |= VAR;
+  }
+  if (u->c_type & (VAR|FLD|REC|TMP)) {
+	u->c_type &= ~STR;
+	u->c_type |= NUM;
+	sfree(u->c_sval);
+	u->c_sval = (char *)NULL;
+	u->c_fval = f;
+	if (u->c_type & FLD)
+		mkrec(u);
+  }
+  else
+	fprintf(stderr, "assign to nonvariable (%d)\n", u->c_type);
+}
+
+setsval(u, s) CELL *u; char *s;
+{
+  double atof();
+
+  if (u->c_type == UDF) {	/* fix up local var */
+/*
+printf("setsval_fix_to_VAR\n");
+*/
+	u->c_type |= VAR;
+  }
+  if (u->c_type & (VAR|FLD|REC|TMP)) {
+	u->c_type &= ~NUM;
+	u->c_type |= STR;
+	sfree(u->c_sval);
+	u->c_sval = strsave(s);
+#if 0	/* "table2" in AWK book */
+	if (isnum(u->c_sval)) {
+		u->c_fval = atof(u->c_sval);
+		u->c_type |= NUM;
+	}
+	else
+#endif
+		u->c_fval = 0.0;
+	if (u->c_type & FLD)
+		mkrec(u);
+  }
+  else
+	fprintf(stderr, "assign to constant (%d)\n", u->c_type);
+}
+
+double
+getfval(u) CELL *u;
+{
+  double x, atof();
+
+  if (u->c_type == UDF) {	/* local var */
+	u->c_type |= VAR|STR|NUM;
+	u->c_sval = strsave("");
+	x = u->c_fval = 0.0;
+  }
+  else if (u->c_type & NUM)
+	x = u->c_fval;
+#if 1
+  else {
+	x = atof(u->c_sval);
+#else
+  else {
+	if (isnum(u->c_sval))
+		x = atof(u->c_sval);
+	else
+		x = 0.0;
+#endif
+  }
+  return x;
+}
+
+char *
+getsval(u) CELL *u;
+{
+  char *s, str[80];
+
+  if (u->c_type & STR)
+	s = u->c_sval;
+  else if (u->c_type & NUM) {
+/*	if (u->c_fval >= -2147483648.0 && u->c_fval <= 2147483647.0)*/
+	if ((long)u->c_fval == u->c_fval)
+		s = "%.16g";
+	else
+		s = *OFMT;
+	sprintf(str, s, u->c_fval);
+	sfree(u->c_sval);
+	s = u->c_sval = strsave(str);
+  }
+#if 1
+  else if (u->c_type == UDF) {	/* local var */
+/*
+printf("getsval_fix_to_VAR|STR\n");
+*/
+	u->c_type |= VAR|STR|NUM;
+	s = u->c_sval = strsave("");
+	u->c_fval = 0.0;
+  }
+#endif
+  else
+	fprintf(stderr, "abnormal value (STR|NUM == 0)(%d)\n", u->c_type);
+  return s;
+}
+
+char *
+emalloc(n) unsigned n;
+{
+  char *p;
+#if 0
+  char far *_fmalloc();
+#else
+  char *malloc();
+#endif
+
+#if 0
+  if ((p = _fmalloc(n)) == (char *)NULL)
+#else
+  if ((p = malloc(n)) == (char *)NULL)
+#endif
+	error("memory over");
+  return p;
+}
+
+Free(s) char *s;
+{
+#if DOS
+  void _ffree();
+
+  _ffree(s);
+#else
+  free(s);
+#endif
+}
Index: /trunk/minix/commands/awk/y.c
===================================================================
--- /trunk/minix/commands/awk/y.c	(revision 9)
+++ /trunk/minix/commands/awk/y.c	(revision 9)
@@ -0,0 +1,1087 @@
+/*
+ * a small awk clone
+ *
+ * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
+ *
+ * Absolutely no warranty. Use this software with your own risk.
+ *
+ * Permission to use, copy, modify and distribute this software for any
+ * purpose and without fee is hereby granted, provided that the above
+ * copyright and disclaimer notice.
+ *
+ * This program was written to fit into 64K+64K memory of the Minix 1.2.
+ */
+
+
+#include <stdio.h>
+#include "awk.h"
+
+extern char *mkpat();
+
+extern char *cmd;
+extern char text[];
+extern char funnam[];
+extern int sym;
+extern int sym1;
+extern int regexflg;
+extern int funflg;
+extern int printflg;
+extern int getlineflg;
+
+extern SYMBOL *hashtab[], *funtab[];
+
+extern CELL *field[];
+
+char *emalloc(), *strsave();
+NODE *node0(), *node1(), *node2(), *node3(), *node4();
+NODE *stat(), *pastat();
+NODE *expr(), *expr1(), *expr2(), *expr3(), *expr4();
+NODE *expr5(), *expr6(), *expr7(), *expr8(), *expr9(), *expr10();
+NODE *doprint(), *dofuncn(), *doif(), *dowhile(), *dofor(), *body();
+NODE *doassign(), *dodo(), *doarray(), *doreturn(), *doelement();
+CELL *mkcell(), *getvar();
+CELL *execute(), *lookup();
+
+int forflg;	/* parsing for(expr in array), inhibit 'expr in array' */
+int prmflg;	/* parsing pass parameters */
+NODE *begin, *loop, *End;
+
+parse()
+{
+  NODE *p, *q, *r, *stat();
+  CELL *u;
+
+  lex();
+  skipeol();
+  while (sym) {
+	switch (sym) {
+	case BEGIN:
+		lex();
+		begin = stat();
+		break;
+	case END:
+		lex();
+		if (End == NULL)
+			End = stat();
+		else {
+			for (p = End; p; p = q) {
+				if ((q = p->n_next) == NULL)
+					p->n_next = stat();
+			}
+		}
+		break;
+	case FUNC:
+		lex();
+		dousrfun();
+		break;
+	default:
+		q = loop = pastat();
+		skipeol();
+		while (sym &&  sym != BEGIN && sym != END && sym != FUNC) {
+			r = pastat();
+			q->n_next = r;
+			q = r;
+			skipeol();
+		}
+		break;
+	}
+	skipeol();
+  }
+  if (begin) {
+	u = execute(begin);
+	c_free(u);
+  }
+  if (End || loop)
+	while (Getrec(NULL)) {
+		if (loop) {
+			u = execute(loop);
+			c_free(u);
+		}
+	}
+  if (End) {
+	u = execute(End);
+	c_free(u);
+  }
+}
+
+#define MAXARG		100
+static char *argnam[MAXARG];
+static int narg;
+
+static
+dousrfun()
+{
+  CELL *u;
+
+  strcpy(funnam, text);
+  u = getvar(text, funtab, FUN);
+  lex();
+  if (sym != '(')
+	synerr("'(' expected");
+  for (lex(); sym != ')'; narg++) {
+	if (sym != IDENT)
+		synerr("argument expected");
+	argnam[narg] = strsave(text);
+	lex();
+	if (sym == ',')
+		lex();
+  }
+  u->c_fval = (double) narg;
+  lex();
+  skipeol();
+  funflg++;
+  u->c_sval = (char *) stat();
+  funflg--;
+  if (narg > 0) {
+	do {
+		sfree(argnam[--narg]);
+	} while (narg > 0);
+  }
+  skipeol();
+}
+
+isarg(s) char *s;
+{
+  int i;
+
+  if (narg > 0) {
+	for (i = narg - 1; i >= 0; i--)
+		if (strcmp(s, argnam[i]) == 0)
+			break;
+  }
+  else
+	i = -1;
+  return i;
+}
+
+/*
+interactive()
+{
+  NODE *p, *q;
+  CELL *u;
+
+  for (lex(); sym; lex()) {
+	p = stat();
+	if (p->n_type != PRINT && !iscntl(p->n_type)) {
+		q = (NODE *) emalloc(sizeof(NODE) + sizeof(NODE *) * 4);
+		q->n_type = PRINT;
+		q->n_arg[0] = q->n_arg[1] = q->n_arg[3] = NULL;
+		q->n_arg[2] = p;
+		q->n_next = NULL;
+		p = q;
+	}
+	u = execute(p);
+	printf("[%g(%s)]\n", u->c_fval, u->c_sval);
+	c_free(u);
+  }
+  closeall();
+  exit(0);
+}
+*/
+
+static
+iscntl(t)
+{
+  static int tab[] = {
+	IF, DO, WHILE, FOR, JUMP, GETLINE, 0
+  };
+  int i;
+
+  for (i = 0; tab[i]; i++)
+	if (t == tab[i])
+		break;
+  return tab[i];
+}
+
+static NODE *
+pastat()
+{
+  NODE *p, *q, *r;
+
+  if (sym == '{')	/* action only */
+	p = stat();
+  else {	/* exp [, expr] [{ .. }] */
+	p = expr();
+	if (sym == ',') {
+		lex();
+		q = expr();
+	}
+	else
+		q = NULL;
+	if (sym && sym != EOL)
+		r = stat();
+	else
+		r = node0(PRINT0);
+	if (q)
+		p = node3(P2STAT, p, q, r);
+	else
+		p = node2(P1STAT, p, r);
+  }
+  return p;
+}
+
+static NODE *
+stat()
+{
+  NODE *p, *q, *r;
+  CELL *u, *v;
+  int op;
+
+/*printf("@stat(%d)(%s)\n", sym, text);*/
+  while (sym == EOL)
+	lex();
+  switch(sym) {
+  case PRINT:
+	p = doprint(0);
+	break;
+  case PRINTF:
+	p = doprint(FORMAT);
+	break;
+  case IF:
+	p = doif();
+	break;
+  case WHILE:
+	p = dowhile();
+	break;
+  case DO:
+	p = dodo();
+	break;
+  case FOR:
+	p = dofor();
+	break;
+  case RETURN:
+	p = doreturn();
+	break;
+  case EXIT:
+	p = node2(JUMP, (NODE *)sym, (NODE *)NULL);
+	lex();
+	if (sym == IDENT || sym == NUMBER || sym == ARG)
+		p->n_arg[1] = expr();
+	break;
+  case BREAK: case CONTIN: case NEXT:
+	p = node1(JUMP, (NODE *)sym);
+	lex();
+	break;
+  case DELETE:
+	lex();
+	u = getvar(text, hashtab, ARR);
+	if (Getc() != '[')
+		synerr("'[' expected");
+	p = doarray(u);
+	p->n_type = DELETE;
+	lex();	/* ']' */
+	break;
+  case '{':
+	lex();
+	skipeol();
+	if (sym == '}')
+		p = node0(NULPROC);
+	else
+		p = q = stat();
+	skipeol();
+	while (sym != '}') {
+		r = stat();
+		q->n_next = r;
+		q = r;
+		skipeol();
+	}
+	lex();
+	break;
+  default:
+	p = expr();
+#if 0
+	if (sym == BINOR) {	/* expr | GETLINE */
+		lex();
+		if (sym != GETLINE)
+			synerr("'GETLINE' expected");
+		lex();
+		if (sym == IDENT || sym == STRING || sym == ARG) {
+			q = expr();
+		}
+		else
+			q = NULL;
+		p = node3(GETLINE, q, p, (NODE *)R_PIN);
+	}
+#endif
+	break;
+  }
+  if (p->n_type == VALUE)
+	synerr("statement expected");
+  return p;
+}
+
+static
+skipeol()
+{
+  while (sym == EOL)
+	lex();
+}
+
+static NODE *
+doprint(fmt)
+{
+  NODE *p, *q, *r;
+  CELL *u;
+  int i, op;
+  int n = 0;
+
+  printflg++;
+  lex();
+  if (sym == '(')
+	lex();
+  if (sym != '}' && sym != ')' && sym != EOL && sym != R_OUT && sym != R_APD
+	&& sym != R_POUT) {
+	p = q = expr(); n++;
+	while (sym == ',') {
+  		lex();
+		skipeol();
+	  	r = expr(); n++;
+		q->n_next = r;
+	  	q = r;
+	}
+  }
+  if (sym == ')')
+	lex();
+  if (sym == R_OUT || sym == R_APD || sym == R_POUT) {
+	op = sym;
+	lex();
+/*	q = expr10();*/
+	q = expr();	/* 94-04-02 */
+  }
+  else
+	q = (NODE *) (op = 0);	/* stdout */
+  printflg = 0;
+  r = (NODE *) emalloc(sizeof(*r) + sizeof(r) * (n + 3));
+  r->n_type = PRINT;	/* convert list to arg */
+  r->n_next = NULL;
+  r->n_arg[0] = (NODE *) (op | fmt);
+  r->n_arg[1] = q;
+  if (n == 0) {
+	p = node1(VALUE, (NODE *)field[0]);
+  }
+  for (i = 2; p != NULL; i++) {
+	r->n_arg[i] = p;
+	q = p->n_next;
+	p->n_next = NULL;
+	p = q;
+  }
+  r->n_arg[i] = NULL;
+  return r;
+}
+
+static NODE *
+doif()
+{
+  NODE *p, *q, *r;
+
+  lex();
+  if (sym != '(')
+	synerr("'(' expected");
+  lex();
+  p = expr();
+  if (sym != ')')
+	synerr("')' expected");
+  lex();
+  skipeol();
+  q = stat();
+  skipeol();
+  if (sym == ELSE) {
+	lex();
+	skipeol();
+	r = stat();
+  }
+  else
+	r = NULL;
+  return node3(IF, p, q, r);
+}
+
+static NODE *
+dowhile()
+{
+  NODE *p, *q;
+
+  lex();
+  if (sym != '(')
+	synerr("'(' expected");
+  lex();
+  p = stat();
+  if (sym != ')')
+	synerr("')' expected");
+  q = body();
+  return node2(WHILE, p, q);
+}
+
+static NODE *
+dofor()
+{
+  NODE *p, *q, *r, *s;
+  CELL *u;
+  int i;
+
+  lex();
+  if (sym != '(')
+	synerr("'(' expected");
+  lex();
+  if (sym != EOL) {
+	forflg++;	/* inhibit parsing 'expr IN array' */
+	p = expr();
+	forflg = 0;
+  }
+  else
+	p = NULL;
+  if (sym == IN) {
+	lex();
+	if (sym == ARG) {
+/*
+printf("***FOR_IN_ARG(%d)***\n", sym);
+*/
+		u = mkcell(POS, NULL, (double)sym1);
+		q = node1(ARG, u);
+	}
+	else {
+		u = getvar(text, hashtab, ARR);
+		q = node1(VALUE, u);
+	}
+	lex();
+	if (sym != ')')
+		synerr("')' expected");
+	lex();
+	skipeol();
+	s = stat();
+	r = node3(FORIN, p, q, s);
+  }
+  else {
+	if (sym != EOL)
+		synerr("'in' or ';' expected");
+	lex();
+	if (sym != EOL)
+		q = expr();
+	else
+		q = NULL;
+	if (sym != EOL)
+		synerr("';' expected");
+	lex();
+	if (sym != ')')
+		r = expr();
+	else
+		r = NULL;
+	if (sym != ')')
+		synerr("')' expected");
+	s = body();
+	r = node4(FOR, p, q, r, s);
+  }
+  return r;
+}
+
+static NODE *
+body()
+{
+  NODE *r;
+
+  while ((sym = Getc()) == '\n' || sym == ' ' || sym == '\t')
+	;
+  if (sym == ';') {
+	r = node0(NULPROC);
+	lex();
+  }
+  else {
+	Ungetc(sym);
+	lex();
+	r = stat();
+  }
+  return r;
+}
+
+static NODE *
+dodo()
+{
+  NODE *p, *q;
+
+  lex();
+  skipeol();
+  p = stat();
+  skipeol();
+  if (sym != WHILE)
+	synerr("'while' expected");
+  lex();
+  if (sym != '(')
+	synerr("'(' expected");
+  lex();
+  q = stat();
+  if (sym != ')')
+	synerr("')' expected");
+  lex();
+  return node2(DO, p, q);
+}
+
+static NODE *
+doreturn()
+{
+  NODE *p, *q, *r;
+  int i, n = 0;
+
+  if (lex() != EOL) {
+	p = q = expr(); n++;
+	while (sym == ',') {
+		lex(); skipeol();
+		r = expr(); n++;
+		q ->n_next = r;
+		q = r;
+	}
+  }
+  else
+	p = (NODE *)NULL;
+
+  r = (NODE *) emalloc(sizeof(*r) + sizeof (r) * (n + 1));
+  r->n_type = JUMP;
+  r->n_next = NULL;
+  r->n_arg[0] = (NODE *) RETURN;
+  for (i = 1; p != NULL; i++) {
+	r->n_arg[i] = p;
+	q = p->n_next;
+	p->n_next = NULL;
+	p = q;
+  }
+  r->n_arg[i] = NULL;
+  return r;
+}
+
+static NODE *
+expr()
+{
+  NODE *p;
+
+  p = expr1();
+  if (isassign(sym))
+	p = doassign(sym, p);
+  return p;
+}
+
+static isassign(sym)
+{
+  return (sym == ASSIGN || sym == ADDEQ || sym == SUBEQ || sym == MULTEQ
+  	|| sym == DIVEQ || sym == MODEQ || sym == POWEQ);
+}
+
+static NODE *
+doassign(op, p) NODE *p;
+{	/* evaluate right to left */
+  NODE *q;
+
+  lex();
+  q = expr();
+  if (isassign(sym))
+	q = doassign(sym, q);
+  return node3(ASSIGN, (NODE *)op, p, q);
+}
+
+static NODE *
+expr1()
+{
+  NODE *p, *q;
+
+/*
+printf("expr1(%d)(%s)\n", sym, text);
+*/
+  p = expr2();
+  if (sym == '?') {
+	lex();
+#if 0
+	q = stat();
+	if (sym != ':')
+		synerr("':' expected");
+	lex();
+	return node3(IF, p, q, stat());
+#else
+	q = expr();
+	if (sym != ':')
+		synerr("':' expected");
+	lex();
+	return node3(IF, p, q, expr());
+#endif
+  }
+  return p;	/* 930213 */
+}
+
+static NODE *
+expr2()
+{
+  NODE *p;
+
+/*
+printf("expr2(%d)(%s)\n", sym, text);
+*/
+  p = expr3();
+  while (sym == OR) {
+	lex();
+	skipeol();
+	p = node3(COND, (NODE *)OR, p, expr3());
+  }
+  return p;
+}
+
+static NODE *
+expr3()
+{
+  NODE *p;
+
+/*
+printf("expr3(%d)(%s)\n", sym, text);
+*/
+  p = expr4();
+  while (sym == AND) {
+	lex();
+	skipeol();
+	p = node3(COND, (NODE *)AND, p, expr4());
+  }
+  return p;
+}
+
+static NODE *
+expr4()
+{
+  NODE *p;
+  CELL *q;
+  int op;
+
+/*
+printf("expr4(%d)(%s)\n", sym, text);
+*/
+  p = expr5();
+  if (!forflg && sym == IN) {
+	lex();
+	q = getvar(text, hashtab, ARR);
+	lex();
+	return node2(IN, p, q);
+  }
+  while (sym == EQ || sym == NE || sym == LT || sym == LE  || sym == GT
+	|| sym == GE || sym == MATCH || sym == NOMATCH) {
+	op = sym;
+	lex();
+	p = node3(COND, (NODE *)op, p, expr5());
+  }
+  return p;
+}
+
+static NODE *
+expr5()
+{
+  NODE *p, *q;
+
+/*
+printf("expr5(%d)(%s)\n", sym, text);
+*/
+  p = expr6();
+  while (iscat(sym)) {
+	q = expr6();
+	p = node2(CAT, p, q);
+  }
+  return p;
+}
+
+static iscat(sym)
+{
+  static int ctab[] = {
+	ADD, SUB, MULT, DIV, MOD, INC, DEC, STRING, NUMBER, IDENT, '(',
+	MATHFUN, STRFUN, SPRINTF, '$', SUBST, ARG, CALL, 0
+	};
+  register int i, j;
+
+  for (i = 0; j = ctab[i]; i++)
+	if (sym == j)
+		break;
+  return j;
+}
+
+static NODE *
+expr6()
+{
+  register int sign = sym;
+  NODE *p, *q;
+
+/*
+printf("expr6(%d)(%s)\n", sym, text);
+*/
+  if (sym == SUB || sym == ADD)
+	lex();
+  p = expr7();
+  if (sign == SUB)
+	p = node2(ARITH, (NODE *)UMINUS, p);
+  while (sym == ADD || sym == SUB) {
+	sign = sym;
+	lex();
+	q = expr7();
+	if (sign == ADD) {
+		p = node3(ARITH, (NODE *)ADD, p, q);
+	}
+	else if (sign == SUB) {
+		p = node3(ARITH, (NODE *)SUB, p, q);
+	}
+	else
+		synerr("'+' or '-' expected");
+  }
+  return p;
+}
+
+static NODE *
+expr7()
+{
+  register int op;
+  NODE *p, *q;
+
+/*
+printf("expr7(%d)(%s)\n", sym, text);
+*/
+  p = expr8();
+  while (sym == MULT || sym == DIV || sym == MOD) {
+	op = sym;
+	lex();
+	q = expr8();
+	switch (op) {
+	case MULT:	p = node3(ARITH, (NODE *)MULT, p, q); break;
+	case DIV:	p = node3(ARITH, (NODE *)DIV, p, q); break;
+	case MOD:	p = node3(ARITH, (NODE *)MOD, p, q); break;
+	default:	synerr("'*', '/' or '%' expected"); break;
+	}
+  }
+  return p;
+}
+
+static NODE *
+expr8()
+{
+  NODE *p;
+  int op;
+
+/*
+printf("expr8(%d)(%s)\n", sym, text);
+*/
+  if (sym == NOT) {
+	lex();
+	p = node2(COND, (NODE *)NOT, expr9());
+  }
+  else {
+	p = expr9();
+	if (sym == POWER) {
+		lex();
+		p = node3(ARITH, (NODE *)POWER, p, expr9());
+	}
+  }
+  return p;
+}
+
+static NODE *
+expr9()
+{
+  NODE *p, *q;
+  int op, sym0;
+
+/*
+printf("expr9(%d)(%s)\n", sym, text);
+*/
+  if (op = isincdec(sym)) {
+	lex();
+	if (sym != IDENT && sym != ARG)
+		synerr("illegal '++/--' operator");
+	p = expr10();
+	p = node4(ARITH, (NODE *)INCDEC, p, (NODE *)op, (NODE *)PRE);
+  }
+  else {
+	sym0 = sym;
+	p = expr10();
+	if (op = isincdec(sym)) {
+/*printf("POST(%d)(%d)(%s)\n", sym, sym0, text);*/
+		if (sym0 == IDENT || sym0 == ARG) {
+			p = node4(ARITH, (NODE *)INCDEC, p, (NODE *)op,
+				(NODE *)POST);
+			lex();
+		}
+	}
+	if (sym == BINOR) {	/* | getline */
+		lex();
+		if (sym != GETLINE)
+			synerr("'GETLINE' expected");
+		lex();
+		if (sym == IDENT || sym == STRING || sym == ARG) {
+			q = expr();
+		}
+		else
+			q = NULL;
+		p = node3(GETLINE, q, p, (NODE *)R_PIN);
+	}
+  }
+  return p;
+}
+
+static isincdec(sym)
+{
+  return sym == INC ? 1 : (sym == DEC ? -1 : 0);
+}
+
+static NODE *
+expr10()
+{
+  NODE *p, *q;
+  CELL *u, *v;
+  int op;
+  int c;
+int gsave, psave;
+  double atof();
+
+/*
+printf("expr10(%d)(%s)\n", sym, text);
+*/
+  switch (sym) {
+  case STRING:
+	u = mkcell(STR, text, 0.0);
+	goto g1;
+  case NUMBER:
+	u = mkcell(NUM, NULL, atof(text));
+g1:
+	p = node1(VALUE, u);
+	lex();
+	break;
+  case IDENT: case ARG:
+	if ((c = Getc()) == '[') {	/* array */
+		/* 940403 */
+		if (sym == ARG) {
+			u = (CELL *)emalloc(sizeof(CELL));
+			u = mkcell(POS, NULL, (double)sym1);
+			p = doarray(u);
+		}
+		else {
+			u = getvar(text, hashtab, ARR);
+			p = doarray(u);
+		}
+	}
+	else {
+		Ungetc(c);
+		if (sym == ARG) {
+			u = mkcell(POS, NULL, (double)sym1);
+			p = node1(ARG, u);
+		}
+		else {	/* symple variable */
+			u = getvar(text, hashtab, VAR|STR|NUM);
+			p = node1(VALUE, u);
+		}
+	}
+	lex();
+	break;
+  case '(':
+	/* print >(x ? y : z) needs this */
+gsave = getlineflg; psave = printflg;
+getlineflg = printflg = 0;
+	lex();
+	p = expr();
+	if (sym == ',')	/* (expr, expr, .. ) */
+		p = doelement(p);
+	if (sym != ')')
+		synerr("')' expected");
+getlineflg = gsave; printflg = psave;
+	lex();
+	break;
+  case CALL:
+	p = dofuncn(sym, getvar(text, funtab, UDF));
+	break;
+  case MATHFUN: case STRFUN: case SUBST:
+	p = dofuncn(sym, (CELL *)sym1);
+	break;
+  case SPRINTF:
+	p = doprint(FORMAT|STROUT);
+	break;
+  case '$':
+	lex();
+	switch (sym) {
+	case NUMBER:
+		u = mkcell(NUM, NULL, atof(text));
+		p = node1(VALUE, u);
+		p = node1(FIELD, p);
+		lex();
+		break;
+	case IDENT: case ARG: case '(':
+		p = node1(FIELD, expr10());
+		break;
+	default:
+		synerr("number or identifier expected after '$'", (char *)0);
+	}
+	break;
+  case DIV:
+	regexflg++;
+	lex();
+	regexflg = 0;
+	u = mkcell(PAT, NULL, 0.0);
+	u->c_sval = (char *) mkpat(text);
+	p = node1(VALUE, u);
+	lex();
+	break;
+  case GETLINE:
+	getlineflg++;
+	lex();
+	if (sym == IDENT || sym == STRING || sym == ARG)
+		q = expr10();	/* read into var */
+	else
+		q = NULL;
+	getlineflg = 0;
+	if (sym == R_IN) {
+		op = R_IN;
+		lex();
+		p = expr10();
+	}
+	else
+		op = (int) (p = NULL);
+	p = node3(GETLINE, q, p, (NODE *)op);
+	break;
+  default:
+	synerr(
+	"identifier, number, string, argument, regexpr, call or '(' expected");
+	break;
+  }
+  return p;
+}
+
+static NODE *
+dofuncn(fun, op) CELL *op;
+{
+  NODE *p;
+  int i, j;
+  int n = 0;
+  NODE *a[100];
+
+  if (lex() == '(') {
+	prmflg++;
+	for (lex(); sym && (sym != ')'); n++) {
+		if ((int)op == SPLIT && n == 1) {
+/*
+printf("sym(%d)sym1(%d)(%d)\n", sym, sym1, isarg(text));
+*/
+			if (sym != ARG) {	/*isarg(text) == -1*/
+				/* make an array if not exist */
+				prmflg = 0;
+				getvar(text, hashtab, ARR);
+				prmflg++;
+			}
+		}
+		a[n] = expr();
+		if (sym == ',')
+			lex();
+		else if (sym != ')')
+			synerr("',' or ')' expected");
+	}
+	prmflg = 0;
+
+	if (sym == ')')
+		lex();
+	else
+		synerr("')' expected");
+  }
+  p = (NODE *) emalloc(sizeof(*p) + sizeof(p) * (n + 2));
+  p->n_type = fun;
+  p->n_next = NULL;
+  p->n_arg[0] = (NODE *) op;
+  p->n_arg[1] = (NODE *) n;
+  for (i = 0, j = 2; i < n; )
+	p->n_arg[j++] = a[i++];
+  p->n_arg[j] = NULL;
+  return p;
+}
+
+static NODE *
+doarray(u) CELL *u;
+{
+  NODE *p;
+  int i, j;
+  int n;
+  NODE *a[20];
+
+  for (lex(), n = 0; sym &&  sym != ']'; n++) {
+	a[n] = expr();
+	if (sym == ',')
+		lex();
+  }
+  if (sym != ']')
+	synerr("']' expected");
+  /* left ']' for expr10() */
+  p = (NODE *) emalloc(sizeof(*p) + sizeof(p) * (n + 1));
+  p->n_type = ARRAY;
+  p->n_next = NULL;
+  p->n_arg[0] = (NODE *)u;
+  p->n_arg[1] = (NODE *) n;
+  for (i = 0, j = 2; i < n; )
+	p->n_arg[j++] = a[i++];
+  return p;
+}
+
+static NODE *
+doelement(q) NODE *q;
+{
+  NODE *p;
+  int i, j;
+  int n;
+  NODE *a[20];
+
+  a[0] = q;
+  for (lex(), n = 1; sym &&  sym != ')'; n++) {
+	a[n] = expr();
+	if (sym == ',')
+		lex();
+	else if (sym != ')')
+		synerr("',' or ')' expected");
+  }
+  /* left ')' for expr10() */
+  p = (NODE *) emalloc(sizeof(*p) + sizeof(p) * (n + 1));
+  p->n_type = ELEMENT;
+  p->n_next = NULL;
+  p->n_arg[0] = NULL;
+  p->n_arg[1] = (NODE *) n;
+  for (i = 0, j = 2; i < n; )
+	p->n_arg[j++] = a[i++];
+  return p;
+}
+
+synerr(s, t) char *s, *t;
+{
+  extern int lineno;
+  extern char line[], *linep;
+  int c, i;
+  char *u, *v;
+
+  fprintf(stderr, "%s: Syntax error at line %d", cmd, lineno);
+  if (funflg)
+	fprintf(stderr, " in function %s", funnam);
+  fprintf(stderr, ":\n");
+  if ((v = linep - 1) < line)
+	v = line + BUFSIZ - 1;
+  for (i = 0, u = v - 1; ; --u) {
+	if (u < line) {
+		if (line[BUFSIZ - 1] == '\0')
+			break;
+		u = line + BUFSIZ - 1;
+	}
+	if (*u == '\n' && ++i == 2)
+		break;
+  }
+  if (u != v) {
+	while (u != v) {
+		fputc(*u, stderr);
+		if ((++u - line) == BUFSIZ)
+			u = line;
+	}
+	if (*u != '\n')
+		fputc(*u, stderr);
+	fprintf(stderr, " <--\n\n");
+/*
+	fprintf(stderr, " <-- ");
+	while ((c = Getc()) != EOF && c != '\n')
+		fputc(c, stderr);
+	fprintf(stderr, "\n");
+	if (c == EOF);
+		fprintf(stderr, "\n");
+*/
+  }
+  fprintf(stderr, s, t);
+  fprintf(stderr, "\n");
+#ifdef DOS
+  closeall();
+#endif
+  exit(1);
+}
Index: /trunk/minix/commands/bc/COPYING
===================================================================
--- /trunk/minix/commands/bc/COPYING	(revision 9)
+++ /trunk/minix/commands/bc/COPYING	(revision 9)
@@ -0,0 +1,346 @@
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
Index: /trunk/minix/commands/bc/Makefile
===================================================================
--- /trunk/minix/commands/bc/Makefile	(revision 9)
+++ /trunk/minix/commands/bc/Makefile	(revision 9)
@@ -0,0 +1,89 @@
+# Makefile for bc
+
+# A makefile for bc.  This is part of the bc/sbc distribution.
+#
+#
+#  Make sure these have the correct directories for your machine.
+#
+#  LIBDIR and BINDIR are where bc and libmath.b will be put.
+#
+PREFIX = /usr
+LIBDIR = $(PREFIX)/lib
+BINDIR = $(PREFIX)/bin
+#
+# Programs definitions for use by make.
+#
+SHELL = /bin/sh
+YACC = yacc
+#YACC = bison -y
+LEX = flex -I8
+#LEX = lex
+CC = exec cc
+CFLAGS = -D_POSIX_SOURCE
+LDFLAGS = -i
+#
+#
+OFILES = scan.o util.o main.o number.o storage.o load.o execute.o 
+#
+SUBDIRS = Examples Test
+#
+
+
+all: bc
+bc: $& config.h bc.o $(OFILES) global.o
+	$(CC) -o bc $(LDFLAGS) bc.o $(OFILES) global.o
+
+sbc: sbc.o $(OFILES) global.o
+	$(CC) -o sbc $(LDFLAGS) sbc.o $(OFILES) global.o
+
+math.h: libmath.b
+	$(MAKE) -$(MAKEFLAGS) fbc
+	./fbc -c libmath.b </dev/null >math.h
+	/bin/sh ./fix_math.h
+	rm -f ./fbc
+
+fbc: $(OFILES) bc.o
+	echo \"\" > math.h
+	$(CC) -c $(CFLAGS) global.c
+	$(CC) -o fbc $(LDFLAGS) bc.o $(OFILES) global.o
+
+install:	$(BINDIR)/bc $(LIBDIR)/libmath.b
+
+$(BINDIR)/bc:	bc
+	install -cs -o bin $? $@
+
+$(LIBDIR)/libmath.b:	libmath.b
+	install -c -o bin $? $@
+
+clean:
+	rm -f *.o *.bak core math.h bc sbc
+
+scan.c: scan.l
+	$(LEX) scan.l
+	mv lex.yy.c scan.c
+
+scan.o:	scan.c
+	$(CC) -c $(CFLAGS) -wa scan.c
+
+y.tab.h bc.c: bc.y
+	@echo "expect 1 shift/reduce conflict"
+	$(YACC) -d bc.y
+	mv y.tab.c bc.c
+
+sbc.c: sbc.y
+	$(YACC) -d sbc.y
+	mv y.tab.c sbc.c
+
+global.o: bcdefs.h global.h math.h
+bc.o:	bcdefs.h global.h 
+execute.o: bcdefs.h global.h
+load.o: bcdefs.h global.h 
+main.o: bcdefs.h global.h version.h
+number.o: bcdefs.h
+sbc.o: bcdefs.h global.h 
+scan.o: y.tab.h bcdefs.h global.h
+storage.o: bcdefs.h global.h
+util.o: bcdefs.h global.h version.h
+
+bcdefs.h: number.h const.h config.h
+	touch bcdefs.h
Index: /trunk/minix/commands/bc/bc.c
===================================================================
--- /trunk/minix/commands/bc/bc.c	(revision 9)
+++ /trunk/minix/commands/bc/bc.c	(revision 9)
@@ -0,0 +1,1373 @@
+#ifndef lint
+static char yysccsid[] = "@(#)yaccpar	1.9 (Berkeley) 02/21/93";
+#endif
+#define YYBYACC 1
+#define YYMAJOR 1
+#define YYMINOR 9
+#define yyclearin (yychar=(-1))
+#define yyerrok (yyerrflag=0)
+#define YYRECOVERING (yyerrflag!=0)
+#define YYPREFIX "yy"
+#line 2 "bc.y"
+/* bc.y: The grammar for a POSIX compatable bc processor with some
+         extensions to the language. */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include "global.h"
+#include "proto.h"
+#line 38 "bc.y"
+typedef union {
+	char	 *s_value;
+	char	  c_value;
+	int	  i_value;
+	arg_list *a_value;
+       } YYSTYPE;
+#line 52 "y.tab.c"
+#define NEWLINE 257
+#define AND 258
+#define OR 259
+#define NOT 260
+#define STRING 261
+#define NAME 262
+#define NUMBER 263
+#define MUL_OP 264
+#define ASSIGN_OP 265
+#define REL_OP 266
+#define INCR_DECR 267
+#define Define 268
+#define Break 269
+#define Quit 270
+#define Length 271
+#define Return 272
+#define For 273
+#define If 274
+#define While 275
+#define Sqrt 276
+#define Else 277
+#define Scale 278
+#define Ibase 279
+#define Obase 280
+#define Auto 281
+#define Read 282
+#define Warranty 283
+#define Halt 284
+#define Last 285
+#define Continue 286
+#define Print 287
+#define Limits 288
+#define UNARY_MINUS 289
+#define YYERRCODE 256
+short yylhs[] = {                                        -1,
+    0,    0,   10,   10,   10,   11,   11,   11,   11,   12,
+   12,   12,   12,   12,   12,   15,   15,   13,   13,   13,
+   13,   13,   13,   13,   13,   13,   13,   16,   17,   18,
+   19,   13,   20,   13,   22,   23,   13,   13,   25,   13,
+   24,   24,   26,   26,   21,   27,   21,   28,   14,    5,
+    5,    6,    6,    6,    7,    7,    7,    7,    8,    8,
+    9,    9,    9,    9,    4,    4,    2,    2,   29,    1,
+   30,    1,   31,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    3,    3,    3,    3,    3,    3,
+};
+short yylen[] = {                                         2,
+    0,    2,    2,    1,    2,    0,    1,    3,    2,    0,
+    1,    2,    3,    2,    3,    1,    2,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    4,    0,    0,    0,
+    0,   13,    0,    7,    0,    0,    7,    3,    0,    3,
+    1,    3,    1,    1,    0,    0,    3,    0,   12,    0,
+    1,    0,    3,    3,    1,    3,    3,    5,    0,    1,
+    1,    3,    3,    5,    0,    1,    0,    1,    0,    4,
+    0,    4,    0,    4,    2,    3,    3,    3,    3,    3,
+    2,    1,    1,    3,    4,    2,    2,    4,    4,    4,
+    3,    1,    4,    1,    1,    1,    1,
+};
+short yydefred[] = {                                      1,
+    0,    0,    0,   21,    0,   83,    0,    0,   22,   24,
+    0,    0,   28,    0,   35,    0,    0,   94,   95,    0,
+   18,   25,   97,   23,   39,   19,    0,    0,    0,    0,
+    0,    2,    0,   16,    4,    7,    5,   17,    0,    0,
+    0,    0,   96,   86,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,   81,    0,    0,    0,   11,   71,
+   73,    0,    0,    0,    0,    0,   69,   87,    3,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,   91,   43,    0,   40,    0,   84,
+    0,    0,   38,    0,    0,    0,    0,    0,    0,    0,
+    0,    8,    0,   85,    0,   93,    0,    0,    0,   88,
+   27,    0,    0,   33,    0,   89,   90,    0,   13,   15,
+    0,    0,    0,   62,    0,    0,    0,    0,    0,   29,
+    0,    0,   42,    0,   56,    0,    0,    0,    0,    0,
+   64,    0,    0,    0,   46,   34,   37,    0,   48,   58,
+   30,    0,    0,    0,    0,   47,   53,   54,    0,    0,
+    0,   31,   49,    0,   32,
+};
+short yydgoto[] = {                                       1,
+   30,   79,   31,  113,  108,  149,  109,   73,   74,   32,
+   33,   58,   34,   35,   59,   48,  138,  155,  164,  131,
+  146,   50,  132,   88,   54,   89,  152,  154,  101,   94,
+   95,
+};
+short yysindex[] = {                                      0,
+   -7,   58,  212,    0,  -22,    0, -233, -241,    0,    0,
+   -8,   -5,    0,   -4,    0,    2,    4,    0,    0,    9,
+    0,    0,    0,    0,    0,    0,  212,  212,   91,  725,
+ -240,    0,  -29,    0,    0,    0,    0,    0,   84,  245,
+  212,  -57,    0,    0,   10,  212,  212,   14,  212,   16,
+  212,  212,   23,  156,    0,  549,  127,  -52,    0,    0,
+    0,  212,  212,  212,  212,  212,    0,    0,    0,   91,
+  -17,  725,   24,   -3,  578, -205,  562,  725,   27,  212,
+  606,  212,  669,  716,    0,    0,  725,    0,   19,    0,
+   91,  127,    0,  212,  212,  -36,  -39,  -91,  -91,  -36,
+  212,    0,  166,    0,  277,    0,  -21,   36,   40,    0,
+    0,  725,   28,    0,  725,    0,    0,  156,    0,    0,
+   84,  540,  -39,    0,   -9,  725,   -2,  -37, -174,    0,
+  127,   48,    0,  346,    0, -167,    3,  212, -185,  127,
+    0, -188,    6,   37,    0,    0,    0, -205,    0,    0,
+    0,  127,  -42,   91,  212,    0,    0,    0,  -20,   54,
+   26,    0,    0,  127,    0,
+};
+short yyrindex[] = {                                      0,
+  -16,    0,    0,    0,  409,    0,    0,    0,    0,    0,
+    0,  -58,    0,    0,    0,    0,  426,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,  -50,   46,
+  470,    0,    0,    0,    0,    0,    0,    0,  661,   56,
+    0,  525,    0,    0,    0,    0,   59,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,   -6,
+  705,    7,    0,   60,    0,   61,    0,   63,    0,   49,
+    0,    0,    0,    0,    0,    0,   17,    0,   78,    0,
+  -47,  -45,    0,    0,    0,  537,  440,  620,  637,  594,
+    0,    0,    0,    0,    0,    0,  -33,    0,   66,    0,
+    0,  -19,    0,    0,   68,    0,    0,    0,    0,    0,
+  667,  680,  508,    0,  705,   18,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,  -31,   49,  -44,    0,
+    0,  -40,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    1,   69,    0,    0,    0,    0,    0,
+   13,    0,    0,    0,    0,
+};
+short yygindex[] = {                                      0,
+  958,    0,  104, -118,    0,    0,  -35,    0,    0,    0,
+    0,  -34,   22,    0,   15,    0,    0,    0,    0,    0,
+    0,    0,    0,   -1,    0,    0,    0,    0,    0,    0,
+    0,
+};
+#define YYTABLESIZE 1113
+short yytable[] = {                                      52,
+   26,  129,   66,   64,   52,   65,   92,   55,   10,   57,
+   55,   12,   57,   14,   45,   36,  158,   40,   52,  144,
+   45,   66,   40,   38,   67,   55,   68,   57,   42,   70,
+   40,   46,   28,   41,   47,   49,  160,   27,   92,   66,
+  105,   51,    6,   52,   43,   18,   19,   61,   53,   76,
+   61,   23,    9,   80,   66,   82,  107,   66,   63,   10,
+   44,   63,  118,   85,  104,   28,   26,  111,   41,  127,
+   27,   12,   93,  103,   10,   44,  128,   12,   38,   14,
+   45,  134,   52,  129,  102,  136,  130,  137,  140,  142,
+  135,  145,  148,  143,  162,  151,   59,   28,  150,   67,
+   60,   50,   27,   68,   20,  119,   51,   65,   36,   65,
+   44,    0,  153,  120,    0,   29,  133,    0,    0,  159,
+    0,    0,    0,    0,    0,    0,   64,    0,   65,    0,
+   28,    0,    0,    0,    0,   27,   41,    0,    0,    0,
+    0,   44,    0,    0,    0,    0,    0,    0,   29,    0,
+  163,    0,  139,    0,    0,    0,    0,    0,    0,    0,
+    0,  147,    0,    0,    0,    0,   28,    0,    0,    0,
+   20,   27,   62,  156,    0,  119,    0,   66,    0,    0,
+   29,    0,    0,    0,    0,  165,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,   28,    0,    0,   26,    0,
+   27,    0,   41,    0,   91,   28,   10,    0,    0,   12,
+   27,   14,   45,   29,  157,   52,   52,    0,   26,   52,
+   52,   52,   52,   55,   62,   57,   52,   69,   52,   52,
+   52,   52,   52,   52,   52,   52,  161,   52,   52,   52,
+    6,   52,   52,   52,   52,   52,   52,   52,    2,   29,
+    9,   28,    3,    4,    5,    6,   27,   10,  124,    7,
+    8,    9,   10,   11,   12,   13,   14,   15,   16,   12,
+   17,   18,   19,   44,   20,   21,   22,   23,   24,   25,
+   26,   57,    0,    0,   28,    3,    4,    5,    6,   27,
+    0,    0,    7,   44,    9,   10,   11,   12,   13,   14,
+   15,   16,   20,   17,   18,   19,    0,   20,   21,   22,
+   23,   24,   25,   26,   37,    0,   28,    3,    4,    5,
+    6,   27,   20,    0,    7,    0,    9,   10,   11,   12,
+   13,   14,   15,   16,   41,   17,   18,   19,    0,   20,
+   21,   22,   23,   24,   25,   26,   57,   62,    0,   63,
+    3,    4,    5,    6,   41,    0,    0,    7,    0,    9,
+   10,   11,   12,   13,   14,   15,   16,    0,   17,   18,
+   19,    0,   20,   21,   22,   23,   24,   25,   26,    0,
+    0,    0,    0,    0,    0,   28,    3,    4,    5,    6,
+   27,    0,    0,    7,    0,    9,   10,   11,   12,   13,
+   14,   15,   16,    0,   17,   18,   19,    0,   20,   21,
+   22,   23,   24,   25,   26,    3,   86,    5,    6,    0,
+    0,    0,    7,    0,    0,    3,   11,    5,    6,    0,
+    0,   16,    7,   17,   18,   19,   11,   20,  141,    0,
+   23,   16,    0,   17,   18,   19,    0,   20,    0,   92,
+   23,   92,   92,   92,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,   96,   92,   96,   96,
+   96,    3,    0,    5,    6,    0,    0,    0,    7,    0,
+   76,    0,   11,   76,   96,    0,    0,   16,    0,   17,
+   18,   19,    0,   20,    0,    0,   23,    0,   76,    0,
+    0,   92,   92,    0,    3,    0,   71,    6,    0,    0,
+   82,    7,   82,   82,   82,   11,    0,    0,   96,   96,
+   16,    0,   17,   18,   19,    0,   20,    0,   82,   23,
+    0,    0,   76,   92,    0,    0,    3,    0,  125,    6,
+    0,    0,    0,    7,    0,    0,    0,   11,   70,    0,
+   96,   70,   16,    0,   17,   18,   19,    0,   20,    0,
+    0,   23,   82,   82,   76,   92,   70,   92,   92,   92,
+    0,    0,    0,    0,    0,    0,    0,   79,    0,   79,
+   79,   79,   64,   92,   65,    0,    0,    0,    0,   90,
+    0,   64,    0,   65,   82,   79,    0,    0,    0,    0,
+   70,    0,  110,    0,   64,    3,   65,    5,    6,    0,
+    0,    0,    7,    0,    0,    0,   11,   92,   92,    0,
+   64,   16,   65,   17,   18,   19,    0,   20,    0,   79,
+   23,    0,   70,   66,   80,    0,   80,   80,   80,    0,
+    0,    0,   66,    0,    0,    0,  114,    0,   64,   92,
+   65,    0,   80,    0,    0,   66,    0,    0,    0,    0,
+   77,   79,   77,   77,   77,   92,   92,   92,    0,    0,
+  106,   66,   92,   92,   92,   92,    0,   78,   77,   78,
+   78,   78,   96,   96,   96,   92,   80,    0,    0,   96,
+   96,   96,   96,    0,    0,   78,   76,   76,   76,   66,
+    0,   75,   96,    0,   75,   76,    0,   72,    0,  116,
+   72,   64,   77,   65,    0,    0,   76,    0,   80,   75,
+   74,    0,    0,   74,    0,   72,   82,   82,   82,   78,
+    0,    0,    0,   82,    0,   82,    0,    0,   74,    0,
+    0,    0,    0,    0,   77,   92,   82,   92,   92,   92,
+    0,    0,    0,   75,    0,    0,  117,    0,   64,   72,
+   65,   78,   66,    0,   70,   70,   70,   64,    0,   65,
+    0,    0,   74,   70,    0,    0,    0,    0,    0,    0,
+    0,   92,   92,   92,   70,   75,    0,    0,   92,    0,
+   92,   72,    0,   79,   79,   79,    0,   60,   92,    0,
+   79,   92,   79,   62,   74,   63,   60,   61,    0,   66,
+    0,    0,   62,   79,   63,    0,    0,    0,   66,   60,
+   61,    0,    0,    0,    0,   62,    0,   63,    0,    0,
+    0,    0,    0,    0,    0,   60,   61,    0,    0,    0,
+    0,   62,    0,   63,    0,    0,    0,    0,    0,    0,
+   80,   80,   80,    0,    0,    0,    0,   80,    0,   80,
+    0,    0,    0,   60,   61,    0,    0,    0,    0,   62,
+   80,   63,    0,    0,    0,    0,   77,   77,   77,    0,
+    0,    0,    0,    0,    0,   77,    0,    0,    0,    0,
+    0,    0,    0,   78,   78,   78,   77,    0,    0,    0,
+    0,    0,   78,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,   78,    0,    0,    0,   75,   75,   75,
+    0,    0,    0,   72,   72,   72,   60,   61,    0,    0,
+    0,    0,   62,    0,   63,    0,   74,   75,   74,    0,
+    0,    0,    0,   72,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,   74,    0,    0,    0,
+   39,    0,   92,   92,    0,    0,    0,    0,   92,   92,
+   92,   92,    0,   60,   61,    0,    0,    0,    0,   62,
+    0,   63,   60,   61,   55,   56,    0,    0,   62,    0,
+   63,    0,    0,    0,    0,    0,    0,   72,   75,    0,
+    0,    0,    0,   77,   78,    0,   81,    0,   83,   84,
+    0,   87,    0,    0,    0,    0,    0,    0,    0,   96,
+   97,   98,   99,  100,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,  112,    0,  115,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,  121,  122,    0,    0,    0,    0,    0,  123,    0,
+   75,    0,  126,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,   87,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   75,    0,    0,    0,  112,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,  112,
+};
+short yycheck[] = {                                      40,
+   59,   44,   94,   43,   45,   45,   59,   41,   59,   41,
+   44,   59,   44,   59,   59,    1,   59,   40,   59,  138,
+  262,   41,   40,    2,  265,   59,  267,   59,  262,   59,
+   40,   40,   40,   91,   40,   40,  155,   45,   59,   59,
+   44,   40,   59,   40,  278,  279,  280,   41,   40,   40,
+   44,  285,   59,   40,   94,   40,  262,   94,   41,   59,
+   44,   44,   44,   41,   41,   40,  125,   41,   91,   91,
+   45,   59,  125,   91,  125,   59,   41,  125,   57,  125,
+  125,   91,  123,   44,   70,  123,   59,  262,   41,  257,
+   93,  277,  281,   91,   41,   59,   41,   40,   93,   41,
+   41,   41,   45,   41,   59,   91,   41,   59,   41,   41,
+    7,   -1,  148,   92,   -1,  123,  118,   -1,   -1,  154,
+   -1,   -1,   -1,   -1,   -1,   -1,   43,   -1,   45,   -1,
+   40,   -1,   -1,   -1,   -1,   45,   59,   -1,   -1,   -1,
+   -1,  125,   -1,   -1,   -1,   -1,   -1,   -1,  123,   -1,
+  125,   -1,  131,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,  140,   -1,   -1,   -1,   -1,   40,   -1,   -1,   -1,
+  125,   45,  264,  152,   -1,  161,   -1,   94,   -1,   -1,
+  123,   -1,   -1,   -1,   -1,  164,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   40,   -1,   -1,  257,   -1,
+   45,   -1,  125,   -1,  257,   40,  257,   -1,   -1,  257,
+   45,  257,  257,  123,  257,  256,  257,   -1,  277,  260,
+  261,  262,  263,  257,  264,  257,  267,  257,  269,  270,
+  271,  272,  273,  274,  275,  276,  257,  278,  279,  280,
+  257,  282,  283,  284,  285,  286,  287,  288,  256,  123,
+  257,   40,  260,  261,  262,  263,   45,  257,   93,  267,
+  268,  269,  270,  271,  272,  273,  274,  275,  276,  257,
+  278,  279,  280,  257,  282,  283,  284,  285,  286,  287,
+  288,  256,   -1,   -1,   40,  260,  261,  262,  263,   45,
+   -1,   -1,  267,  277,  269,  270,  271,  272,  273,  274,
+  275,  276,  257,  278,  279,  280,   -1,  282,  283,  284,
+  285,  286,  287,  288,  257,   -1,   40,  260,  261,  262,
+  263,   45,  277,   -1,  267,   -1,  269,  270,  271,  272,
+  273,  274,  275,  276,  257,  278,  279,  280,   -1,  282,
+  283,  284,  285,  286,  287,  288,  256,  264,   -1,  266,
+  260,  261,  262,  263,  277,   -1,   -1,  267,   -1,  269,
+  270,  271,  272,  273,  274,  275,  276,   -1,  278,  279,
+  280,   -1,  282,  283,  284,  285,  286,  287,  288,   -1,
+   -1,   -1,   -1,   -1,   -1,   40,  260,  261,  262,  263,
+   45,   -1,   -1,  267,   -1,  269,  270,  271,  272,  273,
+  274,  275,  276,   -1,  278,  279,  280,   -1,  282,  283,
+  284,  285,  286,  287,  288,  260,  261,  262,  263,   -1,
+   -1,   -1,  267,   -1,   -1,  260,  271,  262,  263,   -1,
+   -1,  276,  267,  278,  279,  280,  271,  282,   93,   -1,
+  285,  276,   -1,  278,  279,  280,   -1,  282,   -1,   41,
+  285,   43,   44,   45,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   41,   59,   43,   44,
+   45,  260,   -1,  262,  263,   -1,   -1,   -1,  267,   -1,
+   41,   -1,  271,   44,   59,   -1,   -1,  276,   -1,  278,
+  279,  280,   -1,  282,   -1,   -1,  285,   -1,   59,   -1,
+   -1,   93,   94,   -1,  260,   -1,  262,  263,   -1,   -1,
+   41,  267,   43,   44,   45,  271,   -1,   -1,   93,   94,
+  276,   -1,  278,  279,  280,   -1,  282,   -1,   59,  285,
+   -1,   -1,   93,  125,   -1,   -1,  260,   -1,  262,  263,
+   -1,   -1,   -1,  267,   -1,   -1,   -1,  271,   41,   -1,
+  125,   44,  276,   -1,  278,  279,  280,   -1,  282,   -1,
+   -1,  285,   93,   94,  125,   41,   59,   43,   44,   45,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   41,   -1,   43,
+   44,   45,   43,   59,   45,   -1,   -1,   -1,   -1,   41,
+   -1,   43,   -1,   45,  125,   59,   -1,   -1,   -1,   -1,
+   93,   -1,   41,   -1,   43,  260,   45,  262,  263,   -1,
+   -1,   -1,  267,   -1,   -1,   -1,  271,   93,   94,   -1,
+   43,  276,   45,  278,  279,  280,   -1,  282,   -1,   93,
+  285,   -1,  125,   94,   41,   -1,   43,   44,   45,   -1,
+   -1,   -1,   94,   -1,   -1,   -1,   41,   -1,   43,  125,
+   45,   -1,   59,   -1,   -1,   94,   -1,   -1,   -1,   -1,
+   41,  125,   43,   44,   45,  257,  258,  259,   -1,   -1,
+   93,   94,  264,  265,  266,  267,   -1,   41,   59,   43,
+   44,   45,  257,  258,  259,  277,   93,   -1,   -1,  264,
+  265,  266,  267,   -1,   -1,   59,  257,  258,  259,   94,
+   -1,   41,  277,   -1,   44,  266,   -1,   41,   -1,   41,
+   44,   43,   93,   45,   -1,   -1,  277,   -1,  125,   59,
+   41,   -1,   -1,   44,   -1,   59,  257,  258,  259,   93,
+   -1,   -1,   -1,  264,   -1,  266,   -1,   -1,   59,   -1,
+   -1,   -1,   -1,   -1,  125,   41,  277,   43,   44,   45,
+   -1,   -1,   -1,   93,   -1,   -1,   41,   -1,   43,   93,
+   45,  125,   94,   -1,  257,  258,  259,   43,   -1,   45,
+   -1,   -1,   93,  266,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,  257,  258,  259,  277,  125,   -1,   -1,  264,   -1,
+  266,  125,   -1,  257,  258,  259,   -1,  258,   94,   -1,
+  264,  277,  266,  264,  125,  266,  258,  259,   -1,   94,
+   -1,   -1,  264,  277,  266,   -1,   -1,   -1,   94,  258,
+  259,   -1,   -1,   -1,   -1,  264,   -1,  266,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,  258,  259,   -1,   -1,   -1,
+   -1,  264,   -1,  266,   -1,   -1,   -1,   -1,   -1,   -1,
+  257,  258,  259,   -1,   -1,   -1,   -1,  264,   -1,  266,
+   -1,   -1,   -1,  258,  259,   -1,   -1,   -1,   -1,  264,
+  277,  266,   -1,   -1,   -1,   -1,  257,  258,  259,   -1,
+   -1,   -1,   -1,   -1,   -1,  266,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,  257,  258,  259,  277,   -1,   -1,   -1,
+   -1,   -1,  266,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,  277,   -1,   -1,   -1,  257,  258,  259,
+   -1,   -1,   -1,  257,  258,  259,  258,  259,   -1,   -1,
+   -1,   -1,  264,   -1,  266,   -1,  257,  277,  259,   -1,
+   -1,   -1,   -1,  277,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,  277,   -1,   -1,   -1,
+    3,   -1,  258,  259,   -1,   -1,   -1,   -1,  264,  265,
+  266,  267,   -1,  258,  259,   -1,   -1,   -1,   -1,  264,
+   -1,  266,  258,  259,   27,   28,   -1,   -1,  264,   -1,
+  266,   -1,   -1,   -1,   -1,   -1,   -1,   40,   41,   -1,
+   -1,   -1,   -1,   46,   47,   -1,   49,   -1,   51,   52,
+   -1,   54,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   62,
+   63,   64,   65,   66,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   80,   -1,   82,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   94,   95,   -1,   -1,   -1,   -1,   -1,  101,   -1,
+  103,   -1,  105,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,  118,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,  134,   -1,   -1,   -1,  138,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,  155,
+};
+#define YYFINAL 1
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 289
+#if YYDEBUG
+char *yyname[] = {
+"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,"'('","')'",0,"'+'","','","'-'",0,0,0,0,0,0,0,0,0,0,0,0,0,"';'",0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'['",0,"']'","'^'",0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,"NEWLINE","AND","OR","NOT","STRING","NAME","NUMBER","MUL_OP",
+"ASSIGN_OP","REL_OP","INCR_DECR","Define","Break","Quit","Length","Return",
+"For","If","While","Sqrt","Else","Scale","Ibase","Obase","Auto","Read",
+"Warranty","Halt","Last","Continue","Print","Limits","UNARY_MINUS",
+};
+char *yyrule[] = {
+"$accept : program",
+"program :",
+"program : program input_item",
+"input_item : semicolon_list NEWLINE",
+"input_item : function",
+"input_item : error NEWLINE",
+"semicolon_list :",
+"semicolon_list : statement_or_error",
+"semicolon_list : semicolon_list ';' statement_or_error",
+"semicolon_list : semicolon_list ';'",
+"statement_list :",
+"statement_list : statement_or_error",
+"statement_list : statement_list NEWLINE",
+"statement_list : statement_list NEWLINE statement_or_error",
+"statement_list : statement_list ';'",
+"statement_list : statement_list ';' statement",
+"statement_or_error : statement",
+"statement_or_error : error statement",
+"statement : Warranty",
+"statement : Limits",
+"statement : expression",
+"statement : STRING",
+"statement : Break",
+"statement : Continue",
+"statement : Quit",
+"statement : Halt",
+"statement : Return",
+"statement : Return '(' return_expression ')'",
+"$$1 :",
+"$$2 :",
+"$$3 :",
+"$$4 :",
+"statement : For $$1 '(' opt_expression ';' $$2 opt_expression ';' $$3 opt_expression ')' $$4 statement",
+"$$5 :",
+"statement : If '(' expression ')' $$5 statement opt_else",
+"$$6 :",
+"$$7 :",
+"statement : While $$6 '(' expression $$7 ')' statement",
+"statement : '{' statement_list '}'",
+"$$8 :",
+"statement : Print $$8 print_list",
+"print_list : print_element",
+"print_list : print_element ',' print_list",
+"print_element : STRING",
+"print_element : expression",
+"opt_else :",
+"$$9 :",
+"opt_else : Else $$9 statement",
+"$$10 :",
+"function : Define NAME '(' opt_parameter_list ')' '{' NEWLINE opt_auto_define_list $$10 statement_list NEWLINE '}'",
+"opt_parameter_list :",
+"opt_parameter_list : define_list",
+"opt_auto_define_list :",
+"opt_auto_define_list : Auto define_list NEWLINE",
+"opt_auto_define_list : Auto define_list ';'",
+"define_list : NAME",
+"define_list : NAME '[' ']'",
+"define_list : define_list ',' NAME",
+"define_list : define_list ',' NAME '[' ']'",
+"opt_argument_list :",
+"opt_argument_list : argument_list",
+"argument_list : expression",
+"argument_list : NAME '[' ']'",
+"argument_list : argument_list ',' expression",
+"argument_list : argument_list ',' NAME '[' ']'",
+"opt_expression :",
+"opt_expression : expression",
+"return_expression :",
+"return_expression : expression",
+"$$11 :",
+"expression : named_expression ASSIGN_OP $$11 expression",
+"$$12 :",
+"expression : expression AND $$12 expression",
+"$$13 :",
+"expression : expression OR $$13 expression",
+"expression : NOT expression",
+"expression : expression REL_OP expression",
+"expression : expression '+' expression",
+"expression : expression '-' expression",
+"expression : expression MUL_OP expression",
+"expression : expression '^' expression",
+"expression : '-' expression",
+"expression : named_expression",
+"expression : NUMBER",
+"expression : '(' expression ')'",
+"expression : NAME '(' opt_argument_list ')'",
+"expression : INCR_DECR named_expression",
+"expression : named_expression INCR_DECR",
+"expression : Length '(' expression ')'",
+"expression : Sqrt '(' expression ')'",
+"expression : Scale '(' expression ')'",
+"expression : Read '(' ')'",
+"named_expression : NAME",
+"named_expression : NAME '[' expression ']'",
+"named_expression : Ibase",
+"named_expression : Obase",
+"named_expression : Scale",
+"named_expression : Last",
+};
+#endif
+#ifdef YYSTACKSIZE
+#undef YYMAXDEPTH
+#define YYMAXDEPTH YYSTACKSIZE
+#else
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 500
+#define YYMAXDEPTH 500
+#endif
+#endif
+int yydebug;
+int yynerrs;
+int yyerrflag;
+int yychar;
+short *yyssp;
+YYSTYPE *yyvsp;
+YYSTYPE yyval;
+YYSTYPE yylval;
+short yyss[YYSTACKSIZE];
+YYSTYPE yyvs[YYSTACKSIZE];
+#define yystacksize YYSTACKSIZE
+#define YYABORT goto yyabort
+#define YYREJECT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+int
+yyparse()
+{
+    register int yym, yyn, yystate;
+#if YYDEBUG
+    register char *yys;
+    extern char *getenv();
+
+    if (yys = getenv("YYDEBUG"))
+    {
+        yyn = *yys;
+        if (yyn >= '0' && yyn <= '9')
+            yydebug = yyn - '0';
+    }
+#endif
+
+    yynerrs = 0;
+    yyerrflag = 0;
+    yychar = (-1);
+
+    yyssp = yyss;
+    yyvsp = yyvs;
+    *yyssp = yystate = 0;
+
+yyloop:
+    if (yyn = yydefred[yystate]) goto yyreduce;
+    if (yychar < 0)
+    {
+        if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+        if (yydebug)
+        {
+            yys = 0;
+            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+            if (!yys) yys = "illegal-symbol";
+            printf("%sdebug: state %d, reading %d (%s)\n",
+                    YYPREFIX, yystate, yychar, yys);
+        }
+#endif
+    }
+    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+    {
+#if YYDEBUG
+        if (yydebug)
+            printf("%sdebug: state %d, shifting to state %d\n",
+                    YYPREFIX, yystate, yytable[yyn]);
+#endif
+        if (yyssp >= yyss + yystacksize - 1)
+        {
+            goto yyoverflow;
+        }
+        *++yyssp = yystate = yytable[yyn];
+        *++yyvsp = yylval;
+        yychar = (-1);
+        if (yyerrflag > 0)  --yyerrflag;
+        goto yyloop;
+    }
+    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+    {
+        yyn = yytable[yyn];
+        goto yyreduce;
+    }
+    if (yyerrflag) goto yyinrecovery;
+#ifdef lint
+    goto yynewerror;
+#endif
+yynewerror:
+    yyerror("syntax error");
+#ifdef lint
+    goto yyerrlab;
+#endif
+yyerrlab:
+    ++yynerrs;
+yyinrecovery:
+    if (yyerrflag < 3)
+    {
+        yyerrflag = 3;
+        for (;;)
+        {
+            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
+                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
+            {
+#if YYDEBUG
+                if (yydebug)
+                    printf("%sdebug: state %d, error recovery shifting\
+ to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
+#endif
+                if (yyssp >= yyss + yystacksize - 1)
+                {
+                    goto yyoverflow;
+                }
+                *++yyssp = yystate = yytable[yyn];
+                *++yyvsp = yylval;
+                goto yyloop;
+            }
+            else
+            {
+#if YYDEBUG
+                if (yydebug)
+                    printf("%sdebug: error recovery discarding state %d\n",
+                            YYPREFIX, *yyssp);
+#endif
+                if (yyssp <= yyss) goto yyabort;
+                --yyssp;
+                --yyvsp;
+            }
+        }
+    }
+    else
+    {
+        if (yychar == 0) goto yyabort;
+#if YYDEBUG
+        if (yydebug)
+        {
+            yys = 0;
+            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+            if (!yys) yys = "illegal-symbol";
+            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
+                    YYPREFIX, yystate, yychar, yys);
+        }
+#endif
+        yychar = (-1);
+        goto yyloop;
+    }
+yyreduce:
+#if YYDEBUG
+    if (yydebug)
+        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
+                YYPREFIX, yystate, yyn, yyrule[yyn]);
+#endif
+    yym = yylen[yyn];
+    yyval = yyvsp[1-yym];
+    switch (yyn)
+    {
+case 1:
+#line 106 "bc.y"
+{
+			      yyval.i_value = 0;
+			      if (interactive)
+				{
+				  printf ("%s\n", BC_VERSION);
+				  welcome ();
+				}
+			    }
+break;
+case 3:
+#line 117 "bc.y"
+{ run_code (); }
+break;
+case 4:
+#line 119 "bc.y"
+{ run_code (); }
+break;
+case 5:
+#line 121 "bc.y"
+{
+			      yyerrok;
+			      init_gen ();
+			    }
+break;
+case 6:
+#line 127 "bc.y"
+{ yyval.i_value = 0; }
+break;
+case 10:
+#line 133 "bc.y"
+{ yyval.i_value = 0; }
+break;
+case 17:
+#line 142 "bc.y"
+{ yyval.i_value = yyvsp[0].i_value; }
+break;
+case 18:
+#line 145 "bc.y"
+{ warranty (""); }
+break;
+case 19:
+#line 147 "bc.y"
+{ limits (); }
+break;
+case 20:
+#line 149 "bc.y"
+{
+			      if (yyvsp[0].i_value & 2)
+				warn ("comparison in expression");
+			      if (yyvsp[0].i_value & 1)
+				generate ("W");
+			      else 
+				generate ("p");
+			    }
+break;
+case 21:
+#line 158 "bc.y"
+{
+			      yyval.i_value = 0;
+			      generate ("w");
+			      generate (yyvsp[0].s_value);
+			      free (yyvsp[0].s_value);
+			    }
+break;
+case 22:
+#line 165 "bc.y"
+{
+			      if (break_label == 0)
+				yyerror ("Break outside a for/while");
+			      else
+				{
+				  sprintf (genstr, "J%1d:", break_label);
+				  generate (genstr);
+				}
+			    }
+break;
+case 23:
+#line 175 "bc.y"
+{
+			      warn ("Continue statement");
+			      if (continue_label == 0)
+				yyerror ("Continue outside a for");
+			      else
+				{
+				  sprintf (genstr, "J%1d:", continue_label);
+				  generate (genstr);
+				}
+			    }
+break;
+case 24:
+#line 186 "bc.y"
+{ exit (0); }
+break;
+case 25:
+#line 188 "bc.y"
+{ generate ("h"); }
+break;
+case 26:
+#line 190 "bc.y"
+{ generate ("0R"); }
+break;
+case 27:
+#line 192 "bc.y"
+{ generate ("R"); }
+break;
+case 28:
+#line 194 "bc.y"
+{
+			      yyvsp[0].i_value = break_label; 
+			      break_label = next_label++;
+			    }
+break;
+case 29:
+#line 199 "bc.y"
+{
+			      if (yyvsp[-1].i_value > 1)
+				warn ("Comparison in first for expression");
+			      yyvsp[-1].i_value = next_label++;
+			      if (yyvsp[-1].i_value < 0)
+				sprintf (genstr, "N%1d:", yyvsp[-1].i_value);
+			      else
+				sprintf (genstr, "pN%1d:", yyvsp[-1].i_value);
+			      generate (genstr);
+			    }
+break;
+case 30:
+#line 210 "bc.y"
+{
+			      if (yyvsp[-1].i_value < 0) generate ("1");
+			      yyvsp[-1].i_value = next_label++;
+			      sprintf (genstr, "B%1d:J%1d:", yyvsp[-1].i_value, break_label);
+			      generate (genstr);
+			      yyval.i_value = continue_label;
+			      continue_label = next_label++;
+			      sprintf (genstr, "N%1d:", continue_label);
+			      generate (genstr);
+			    }
+break;
+case 31:
+#line 221 "bc.y"
+{
+			      if (yyvsp[-1].i_value > 1)
+				warn ("Comparison in third for expression");
+			      if (yyvsp[-1].i_value < 0)
+				sprintf (genstr, "J%1d:N%1d:", yyvsp[-7].i_value, yyvsp[-4].i_value);
+			      else
+				sprintf (genstr, "pJ%1d:N%1d:", yyvsp[-7].i_value, yyvsp[-4].i_value);
+			      generate (genstr);
+			    }
+break;
+case 32:
+#line 231 "bc.y"
+{
+			      sprintf (genstr, "J%1d:N%1d:",
+				       continue_label, break_label);
+			      generate (genstr);
+			      break_label = yyvsp[-12].i_value;
+			      continue_label = yyvsp[-4].i_value;
+			    }
+break;
+case 33:
+#line 239 "bc.y"
+{
+			      yyvsp[-1].i_value = if_label;
+			      if_label = next_label++;
+			      sprintf (genstr, "Z%1d:", if_label);
+			      generate (genstr);
+			    }
+break;
+case 34:
+#line 246 "bc.y"
+{
+			      sprintf (genstr, "N%1d:", if_label); 
+			      generate (genstr);
+			      if_label = yyvsp[-4].i_value;
+			    }
+break;
+case 35:
+#line 252 "bc.y"
+{
+			      yyvsp[0].i_value = next_label++;
+			      sprintf (genstr, "N%1d:", yyvsp[0].i_value);
+			      generate (genstr);
+			    }
+break;
+case 36:
+#line 258 "bc.y"
+{
+			      yyvsp[0].i_value = break_label; 
+			      break_label = next_label++;
+			      sprintf (genstr, "Z%1d:", break_label);
+			      generate (genstr);
+			    }
+break;
+case 37:
+#line 265 "bc.y"
+{
+			      sprintf (genstr, "J%1d:N%1d:", yyvsp[-6].i_value, break_label);
+			      generate (genstr);
+			      break_label = yyvsp[-3].i_value;
+			    }
+break;
+case 38:
+#line 271 "bc.y"
+{ yyval.i_value = 0; }
+break;
+case 39:
+#line 273 "bc.y"
+{  warn ("print statement"); }
+break;
+case 43:
+#line 280 "bc.y"
+{
+			      generate ("O");
+			      generate (yyvsp[0].s_value);
+			      free (yyvsp[0].s_value);
+			    }
+break;
+case 44:
+#line 286 "bc.y"
+{ generate ("P"); }
+break;
+case 46:
+#line 290 "bc.y"
+{
+			      warn ("else clause in if statement");
+			      yyvsp[0].i_value = next_label++;
+			      sprintf (genstr, "J%d:N%1d:", yyvsp[0].i_value, if_label); 
+			      generate (genstr);
+			      if_label = yyvsp[0].i_value;
+			    }
+break;
+case 48:
+#line 300 "bc.y"
+{
+			      /* Check auto list against parameter list? */
+			      check_params (yyvsp[-4].a_value,yyvsp[0].a_value);
+			      sprintf (genstr, "F%d,%s.%s[", lookup(yyvsp[-6].s_value,FUNCT), 
+				       arg_str (yyvsp[-4].a_value,TRUE), arg_str (yyvsp[0].a_value,TRUE));
+			      generate (genstr);
+			      free_args (yyvsp[-4].a_value);
+			      free_args (yyvsp[0].a_value);
+			      yyvsp[-7].i_value = next_label;
+			      next_label = 0;
+			    }
+break;
+case 49:
+#line 312 "bc.y"
+{
+			      generate ("0R]");
+			      next_label = yyvsp[-11].i_value;
+			    }
+break;
+case 50:
+#line 318 "bc.y"
+{ yyval.a_value = NULL; }
+break;
+case 52:
+#line 322 "bc.y"
+{ yyval.a_value = NULL; }
+break;
+case 53:
+#line 324 "bc.y"
+{ yyval.a_value = yyvsp[-1].a_value; }
+break;
+case 54:
+#line 326 "bc.y"
+{ yyval.a_value = yyvsp[-1].a_value; }
+break;
+case 55:
+#line 329 "bc.y"
+{ yyval.a_value = nextarg (NULL, lookup (yyvsp[0].s_value,SIMPLE)); }
+break;
+case 56:
+#line 331 "bc.y"
+{ yyval.a_value = nextarg (NULL, lookup (yyvsp[-2].s_value,ARRAY)); }
+break;
+case 57:
+#line 333 "bc.y"
+{ yyval.a_value = nextarg (yyvsp[-2].a_value, lookup (yyvsp[0].s_value,SIMPLE)); }
+break;
+case 58:
+#line 335 "bc.y"
+{ yyval.a_value = nextarg (yyvsp[-4].a_value, lookup (yyvsp[-2].s_value,ARRAY)); }
+break;
+case 59:
+#line 338 "bc.y"
+{ yyval.a_value = NULL; }
+break;
+case 61:
+#line 342 "bc.y"
+{
+			      if (yyvsp[0].i_value > 1) warn ("comparison in argument");
+			      yyval.a_value = nextarg (NULL,0);
+			    }
+break;
+case 62:
+#line 347 "bc.y"
+{
+			      sprintf (genstr, "K%d:", -lookup (yyvsp[-2].s_value,ARRAY));
+			      generate (genstr);
+			      yyval.a_value = nextarg (NULL,1);
+			    }
+break;
+case 63:
+#line 353 "bc.y"
+{
+			      if (yyvsp[0].i_value > 1) warn ("comparison in argument");
+			      yyval.a_value = nextarg (yyvsp[-2].a_value,0);
+			    }
+break;
+case 64:
+#line 358 "bc.y"
+{
+			      sprintf (genstr, "K%d:", -lookup (yyvsp[-2].s_value,ARRAY));
+			      generate (genstr);
+			      yyval.a_value = nextarg (yyvsp[-4].a_value,1);
+			    }
+break;
+case 65:
+#line 365 "bc.y"
+{
+			      yyval.i_value = -1;
+			      warn ("Missing expression in for statement");
+			    }
+break;
+case 67:
+#line 372 "bc.y"
+{
+			      yyval.i_value = 0;
+			      generate ("0");
+			    }
+break;
+case 68:
+#line 377 "bc.y"
+{
+			      if (yyvsp[0].i_value > 1)
+				warn ("comparison in return expresion");
+			    }
+break;
+case 69:
+#line 383 "bc.y"
+{
+			      if (yyvsp[0].c_value != '=')
+				{
+				  if (yyvsp[-1].i_value < 0)
+				    sprintf (genstr, "DL%d:", -yyvsp[-1].i_value);
+				  else
+				    sprintf (genstr, "l%d:", yyvsp[-1].i_value);
+				  generate (genstr);
+				}
+			    }
+break;
+case 70:
+#line 394 "bc.y"
+{
+			      if (yyvsp[0].i_value > 1) warn("comparison in assignment");
+			      if (yyvsp[-2].c_value != '=')
+				{
+				  sprintf (genstr, "%c", yyvsp[-2].c_value);
+				  generate (genstr);
+				}
+			      if (yyvsp[-3].i_value < 0)
+				sprintf (genstr, "S%d:", -yyvsp[-3].i_value);
+			      else
+				sprintf (genstr, "s%d:", yyvsp[-3].i_value);
+			      generate (genstr);
+			      yyval.i_value = 0;
+			    }
+break;
+case 71:
+#line 410 "bc.y"
+{
+			      warn("&& operator");
+			      yyvsp[0].i_value = next_label++;
+			      sprintf (genstr, "DZ%d:p", yyvsp[0].i_value);
+			      generate (genstr);
+			    }
+break;
+case 72:
+#line 417 "bc.y"
+{
+			      sprintf (genstr, "DZ%d:p1N%d:", yyvsp[-2].i_value, yyvsp[-2].i_value);
+			      generate (genstr);
+			      yyval.i_value = yyvsp[-3].i_value | yyvsp[0].i_value;
+			    }
+break;
+case 73:
+#line 423 "bc.y"
+{
+			      warn("|| operator");
+			      yyvsp[0].i_value = next_label++;
+			      sprintf (genstr, "B%d:", yyvsp[0].i_value);
+			      generate (genstr);
+			    }
+break;
+case 74:
+#line 430 "bc.y"
+{
+			      int tmplab;
+			      tmplab = next_label++;
+			      sprintf (genstr, "B%d:0J%d:N%d:1N%d:",
+				       yyvsp[-2].i_value, tmplab, yyvsp[-2].i_value, tmplab);
+			      generate (genstr);
+			      yyval.i_value = yyvsp[-3].i_value | yyvsp[0].i_value;
+			    }
+break;
+case 75:
+#line 439 "bc.y"
+{
+			      yyval.i_value = yyvsp[0].i_value;
+			      warn("! operator");
+			      generate ("!");
+			    }
+break;
+case 76:
+#line 445 "bc.y"
+{
+			      yyval.i_value = 3;
+			      switch (*(yyvsp[-1].s_value))
+				{
+				case '=':
+				  generate ("=");
+				  break;
+
+				case '!':
+				  generate ("#");
+				  break;
+
+				case '<':
+				  if (yyvsp[-1].s_value[1] == '=')
+				    generate ("{");
+				  else
+				    generate ("<");
+				  break;
+
+				case '>':
+				  if (yyvsp[-1].s_value[1] == '=')
+				    generate ("}");
+				  else
+				    generate (">");
+				  break;
+				}
+			    }
+break;
+case 77:
+#line 473 "bc.y"
+{
+			      generate ("+");
+			      yyval.i_value = yyvsp[-2].i_value | yyvsp[0].i_value;
+			    }
+break;
+case 78:
+#line 478 "bc.y"
+{
+			      generate ("-");
+			      yyval.i_value = yyvsp[-2].i_value | yyvsp[0].i_value;
+			    }
+break;
+case 79:
+#line 483 "bc.y"
+{
+			      genstr[0] = yyvsp[-1].c_value;
+			      genstr[1] = 0;
+			      generate (genstr);
+			      yyval.i_value = yyvsp[-2].i_value | yyvsp[0].i_value;
+			    }
+break;
+case 80:
+#line 490 "bc.y"
+{
+			      generate ("^");
+			      yyval.i_value = yyvsp[-2].i_value | yyvsp[0].i_value;
+			    }
+break;
+case 81:
+#line 495 "bc.y"
+{
+			      generate ("n");
+			      yyval.i_value = yyvsp[0].i_value;
+			    }
+break;
+case 82:
+#line 500 "bc.y"
+{
+			      yyval.i_value = 1;
+			      if (yyvsp[0].i_value < 0)
+				sprintf (genstr, "L%d:", -yyvsp[0].i_value);
+			      else
+				sprintf (genstr, "l%d:", yyvsp[0].i_value);
+			      generate (genstr);
+			    }
+break;
+case 83:
+#line 509 "bc.y"
+{
+			      int len = strlen(yyvsp[0].s_value);
+			      yyval.i_value = 1;
+			      if (len == 1 && *yyvsp[0].s_value == '0')
+				generate ("0");
+			      else if (len == 1 && *yyvsp[0].s_value == '1')
+				generate ("1");
+			      else
+				{
+				  generate ("K");
+				  generate (yyvsp[0].s_value);
+				  generate (":");
+				}
+			      free (yyvsp[0].s_value);
+			    }
+break;
+case 84:
+#line 525 "bc.y"
+{ yyval.i_value = yyvsp[-1].i_value | 1; }
+break;
+case 85:
+#line 527 "bc.y"
+{
+			      yyval.i_value = 1;
+			      if (yyvsp[-1].a_value != NULL)
+				{ 
+				  sprintf (genstr, "C%d,%s:",
+					   lookup (yyvsp[-3].s_value,FUNCT),
+					   arg_str (yyvsp[-1].a_value,FALSE));
+				  free_args (yyvsp[-1].a_value);
+				}
+			      else
+				{
+				  sprintf (genstr, "C%d:", lookup (yyvsp[-3].s_value,FUNCT));
+				}
+			      generate (genstr);
+			    }
+break;
+case 86:
+#line 543 "bc.y"
+{
+			      yyval.i_value = 1;
+			      if (yyvsp[0].i_value < 0)
+				{
+				  if (yyvsp[-1].c_value == '+')
+				    sprintf (genstr, "DA%d:L%d:", -yyvsp[0].i_value, -yyvsp[0].i_value);
+				  else
+				    sprintf (genstr, "DM%d:L%d:", -yyvsp[0].i_value, -yyvsp[0].i_value);
+				}
+			      else
+				{
+				  if (yyvsp[-1].c_value == '+')
+				    sprintf (genstr, "i%d:l%d:", yyvsp[0].i_value, yyvsp[0].i_value);
+				  else
+				    sprintf (genstr, "d%d:l%d:", yyvsp[0].i_value, yyvsp[0].i_value);
+				}
+			      generate (genstr);
+			    }
+break;
+case 87:
+#line 562 "bc.y"
+{
+			      yyval.i_value = 1;
+			      if (yyvsp[-1].i_value < 0)
+				{
+				  sprintf (genstr, "DL%d:x", -yyvsp[-1].i_value);
+				  generate (genstr); 
+				  if (yyvsp[0].c_value == '+')
+				    sprintf (genstr, "A%d:", -yyvsp[-1].i_value);
+				  else
+				      sprintf (genstr, "M%d:", -yyvsp[-1].i_value);
+				}
+			      else
+				{
+				  sprintf (genstr, "l%d:", yyvsp[-1].i_value);
+				  generate (genstr);
+				  if (yyvsp[0].c_value == '+')
+				    sprintf (genstr, "i%d:", yyvsp[-1].i_value);
+				  else
+				    sprintf (genstr, "d%d:", yyvsp[-1].i_value);
+				}
+			      generate (genstr);
+			    }
+break;
+case 88:
+#line 585 "bc.y"
+{ generate ("cL"); yyval.i_value = 1;}
+break;
+case 89:
+#line 587 "bc.y"
+{ generate ("cR"); yyval.i_value = 1;}
+break;
+case 90:
+#line 589 "bc.y"
+{ generate ("cS"); yyval.i_value = 1;}
+break;
+case 91:
+#line 591 "bc.y"
+{
+			      warn ("read function");
+			      generate ("cI"); yyval.i_value = 1;
+			    }
+break;
+case 92:
+#line 597 "bc.y"
+{ yyval.i_value = lookup(yyvsp[0].s_value,SIMPLE); }
+break;
+case 93:
+#line 599 "bc.y"
+{
+			      if (yyvsp[-1].i_value > 1) warn("comparison in subscript");
+			      yyval.i_value = lookup(yyvsp[-3].s_value,ARRAY);
+			    }
+break;
+case 94:
+#line 604 "bc.y"
+{ yyval.i_value = 0; }
+break;
+case 95:
+#line 606 "bc.y"
+{ yyval.i_value = 1; }
+break;
+case 96:
+#line 608 "bc.y"
+{ yyval.i_value = 2; }
+break;
+case 97:
+#line 610 "bc.y"
+{ yyval.i_value = 3; }
+break;
+#line 1318 "y.tab.c"
+    }
+    yyssp -= yym;
+    yystate = *yyssp;
+    yyvsp -= yym;
+    yym = yylhs[yyn];
+    if (yystate == 0 && yym == 0)
+    {
+#if YYDEBUG
+        if (yydebug)
+            printf("%sdebug: after reduction, shifting from state 0 to\
+ state %d\n", YYPREFIX, YYFINAL);
+#endif
+        yystate = YYFINAL;
+        *++yyssp = YYFINAL;
+        *++yyvsp = yyval;
+        if (yychar < 0)
+        {
+            if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+            if (yydebug)
+            {
+                yys = 0;
+                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+                if (!yys) yys = "illegal-symbol";
+                printf("%sdebug: state %d, reading %d (%s)\n",
+                        YYPREFIX, YYFINAL, yychar, yys);
+            }
+#endif
+        }
+        if (yychar == 0) goto yyaccept;
+        goto yyloop;
+    }
+    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
+        yystate = yytable[yyn];
+    else
+        yystate = yydgoto[yym];
+#if YYDEBUG
+    if (yydebug)
+        printf("%sdebug: after reduction, shifting from state %d \
+to state %d\n", YYPREFIX, *yyssp, yystate);
+#endif
+    if (yyssp >= yyss + yystacksize - 1)
+    {
+        goto yyoverflow;
+    }
+    *++yyssp = yystate;
+    *++yyvsp = yyval;
+    goto yyloop;
+yyoverflow:
+    yyerror("yacc stack overflow");
+yyabort:
+    return (1);
+yyaccept:
+    return (0);
+}
Index: /trunk/minix/commands/bc/bc.y
===================================================================
--- /trunk/minix/commands/bc/bc.y	(revision 9)
+++ /trunk/minix/commands/bc/bc.y	(revision 9)
@@ -0,0 +1,612 @@
+%{
+/* bc.y: The grammar for a POSIX compatable bc processor with some
+         extensions to the language. */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include "global.h"
+#include "proto.h"
+%}
+
+%start program
+
+%union {
+	char	 *s_value;
+	char	  c_value;
+	int	  i_value;
+	arg_list *a_value;
+       }
+
+/* Extensions over POSIX bc.
+   a) NAME was LETTER.  This grammer allows longer names.
+      Single letter names will still work.
+   b) Relational_expression allowed only one comparison.
+      This grammar has added boolean expressions with
+      && (and) || (or) and ! (not) and allowed all of them in
+      full expressions.
+   c) Added an else to the if.
+   d) Call by variable array parameters
+   e) read() procedure that reads a number under program control from stdin.
+   f) halt statement that halts the the program under program control.  It
+      is an executed statement.
+   g) continue statement for for loops.
+   h) optional expressions in the for loop.
+   i) print statement to print multiple numbers per line.
+   j) warranty statement to print an extended warranty notice.
+   j) limits statement to print the processor's limits.
+*/
+
+%token <i_value> NEWLINE AND OR NOT
+%token <s_value> STRING NAME NUMBER
+/*     '-', '+' are tokens themselves		*/
+%token <c_value> MUL_OP
+/*     '*', '/', '%' 				*/
+%token <c_value> ASSIGN_OP
+/*     '=', '+=',  '-=', '*=', '/=', '%=', '^=' */
+%token <s_value> REL_OP
+/*     '==', '<=', '>=', '!=', '<', '>' 	*/
+%token <c_value> INCR_DECR
+/*     '++', '--' 				*/
+%token <i_value> Define    Break    Quit    Length
+/*     'define', 'break', 'quit', 'length' 	*/
+%token <i_value> Return    For    If    While    Sqrt   Else
+/*     'return', 'for', 'if', 'while', 'sqrt', 'else' 	*/
+%token <i_value> Scale    Ibase    Obase    Auto  Read
+/*     'scale', 'ibase', 'obase', 'auto', 'read' 	*/
+%token <i_value> Warranty, Halt, Last, Continue, Print, Limits
+/*     'warranty', 'halt', 'last', 'continue', 'print', 'limits'   */
+
+/* Types of all other things. */
+%type <i_value> expression return_expression named_expression opt_expression
+%type <c_value> '+' '-' 
+%type <a_value> opt_parameter_list opt_auto_define_list define_list
+%type <a_value> opt_argument_list argument_list
+%type <i_value> program input_item semicolon_list statement_list
+%type <i_value> statement function   statement_or_error
+
+/* precedence */
+%left OR
+%left AND
+%nonassoc NOT
+%left REL_OP
+%right ASSIGN_OP
+%left '+' '-'
+%left MUL_OP
+%right '^'
+%nonassoc UNARY_MINUS
+%nonassoc INCR_DECR
+
+%%
+program			: /* empty */
+			    {
+			      $$ = 0;
+			      if (interactive)
+				{
+				  printf ("%s\n", BC_VERSION);
+				  welcome ();
+				}
+			    }
+			| program input_item
+			;
+input_item		: semicolon_list NEWLINE
+			    { run_code (); }
+			| function
+			    { run_code (); }
+			| error NEWLINE
+			    {
+			      yyerrok;
+			      init_gen ();
+			    }
+			;
+semicolon_list		: /* empty */
+			    { $$ = 0; }
+			| statement_or_error
+			| semicolon_list ';' statement_or_error
+			| semicolon_list ';'
+			;
+statement_list		: /* empty */
+			    { $$ = 0; }
+			| statement_or_error
+			| statement_list NEWLINE
+			| statement_list NEWLINE statement_or_error
+			| statement_list ';'
+			| statement_list ';' statement
+			;
+statement_or_error	: statement
+  			| error statement
+			    { $$ = $2; }
+			;
+statement 		: Warranty
+			    { warranty (""); }
+			| Limits
+			    { limits (); }
+			| expression
+			    {
+			      if ($1 & 2)
+				warn ("comparison in expression");
+			      if ($1 & 1)
+				generate ("W");
+			      else 
+				generate ("p");
+			    }
+			| STRING
+			    {
+			      $$ = 0;
+			      generate ("w");
+			      generate ($1);
+			      free ($1);
+			    }
+			| Break
+			    {
+			      if (break_label == 0)
+				yyerror ("Break outside a for/while");
+			      else
+				{
+				  sprintf (genstr, "J%1d:", break_label);
+				  generate (genstr);
+				}
+			    }
+			| Continue
+			    {
+			      warn ("Continue statement");
+			      if (continue_label == 0)
+				yyerror ("Continue outside a for");
+			      else
+				{
+				  sprintf (genstr, "J%1d:", continue_label);
+				  generate (genstr);
+				}
+			    }
+			| Quit
+			    { exit (0); }
+			| Halt
+			    { generate ("h"); }
+			| Return
+			    { generate ("0R"); }
+			| Return '(' return_expression ')'
+			    { generate ("R"); }
+			| For 
+			    {
+			      $1 = break_label; 
+			      break_label = next_label++;
+			    }
+			  '(' opt_expression ';'
+			    {
+			      if ($4 > 1)
+				warn ("Comparison in first for expression");
+			      $4 = next_label++;
+			      if ($4 < 0)
+				sprintf (genstr, "N%1d:", $4);
+			      else
+				sprintf (genstr, "pN%1d:", $4);
+			      generate (genstr);
+			    }
+			  opt_expression ';'
+			    {
+			      if ($7 < 0) generate ("1");
+			      $7 = next_label++;
+			      sprintf (genstr, "B%1d:J%1d:", $7, break_label);
+			      generate (genstr);
+			      $<i_value>$ = continue_label;
+			      continue_label = next_label++;
+			      sprintf (genstr, "N%1d:", continue_label);
+			      generate (genstr);
+			    }
+			  opt_expression ')'
+			    {
+			      if ($10 > 1)
+				warn ("Comparison in third for expression");
+			      if ($10 < 0)
+				sprintf (genstr, "J%1d:N%1d:", $4, $7);
+			      else
+				sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
+			      generate (genstr);
+			    }
+			  statement
+			    {
+			      sprintf (genstr, "J%1d:N%1d:",
+				       continue_label, break_label);
+			      generate (genstr);
+			      break_label = $1;
+			      continue_label = $<i_value>9;
+			    }
+			| If '(' expression ')' 
+			    {
+			      $3 = if_label;
+			      if_label = next_label++;
+			      sprintf (genstr, "Z%1d:", if_label);
+			      generate (genstr);
+			    }
+			  statement  opt_else
+			    {
+			      sprintf (genstr, "N%1d:", if_label); 
+			      generate (genstr);
+			      if_label = $3;
+			    }
+			| While 
+			    {
+			      $1 = next_label++;
+			      sprintf (genstr, "N%1d:", $1);
+			      generate (genstr);
+			    }
+			'(' expression 
+			    {
+			      $4 = break_label; 
+			      break_label = next_label++;
+			      sprintf (genstr, "Z%1d:", break_label);
+			      generate (genstr);
+			    }
+			')' statement
+			    {
+			      sprintf (genstr, "J%1d:N%1d:", $1, break_label);
+			      generate (genstr);
+			      break_label = $4;
+			    }
+			| '{' statement_list '}'
+			    { $$ = 0; }
+			| Print
+			    {  warn ("print statement"); }
+			  print_list
+			;
+print_list		: print_element
+ 			| print_element ',' print_list
+			;
+print_element		: STRING
+			    {
+			      generate ("O");
+			      generate ($1);
+			      free ($1);
+			    }
+			| expression
+			    { generate ("P"); }
+ 			;
+opt_else		: /* nothing */
+			| Else 
+			    {
+			      warn ("else clause in if statement");
+			      $1 = next_label++;
+			      sprintf (genstr, "J%d:N%1d:", $1, if_label); 
+			      generate (genstr);
+			      if_label = $1;
+			    }
+			  statement
+function 		: Define NAME '(' opt_parameter_list ')' '{'
+			  NEWLINE opt_auto_define_list 
+			    {
+			      /* Check auto list against parameter list? */
+			      check_params ($4,$8);
+			      sprintf (genstr, "F%d,%s.%s[", lookup($2,FUNCT), 
+				       arg_str ($4,TRUE), arg_str ($8,TRUE));
+			      generate (genstr);
+			      free_args ($4);
+			      free_args ($8);
+			      $1 = next_label;
+			      next_label = 0;
+			    }
+			  statement_list NEWLINE '}'
+			    {
+			      generate ("0R]");
+			      next_label = $1;
+			    }
+			;
+opt_parameter_list	: /* empty */ 
+			    { $$ = NULL; }
+			| define_list
+			;
+opt_auto_define_list 	: /* empty */ 
+			    { $$ = NULL; }
+			| Auto define_list NEWLINE
+			    { $$ = $2; } 
+			| Auto define_list ';'
+			    { $$ = $2; } 
+			;
+define_list 		: NAME
+			    { $$ = nextarg (NULL, lookup ($1,SIMPLE)); }
+			| NAME '[' ']'
+			    { $$ = nextarg (NULL, lookup ($1,ARRAY)); }
+			| define_list ',' NAME
+			    { $$ = nextarg ($1, lookup ($3,SIMPLE)); }
+			| define_list ',' NAME '[' ']'
+			    { $$ = nextarg ($1, lookup ($3,ARRAY)); }
+			;
+opt_argument_list	: /* empty */
+			    { $$ = NULL; }
+			| argument_list
+			;
+argument_list 		: expression
+			    {
+			      if ($1 > 1) warn ("comparison in argument");
+			      $$ = nextarg (NULL,0);
+			    }
+			| NAME '[' ']'
+			    {
+			      sprintf (genstr, "K%d:", -lookup ($1,ARRAY));
+			      generate (genstr);
+			      $$ = nextarg (NULL,1);
+			    }
+			| argument_list ',' expression
+			    {
+			      if ($3 > 1) warn ("comparison in argument");
+			      $$ = nextarg ($1,0);
+			    }
+			| argument_list ',' NAME '[' ']'
+			    {
+			      sprintf (genstr, "K%d:", -lookup ($3,ARRAY));
+			      generate (genstr);
+			      $$ = nextarg ($1,1);
+			    }
+			;
+opt_expression 		: /* empty */
+			    {
+			      $$ = -1;
+			      warn ("Missing expression in for statement");
+			    }
+			| expression
+			;
+return_expression	: /* empty */
+			    {
+			      $$ = 0;
+			      generate ("0");
+			    }
+			| expression
+			    {
+			      if ($1 > 1)
+				warn ("comparison in return expresion");
+			    }
+			;
+expression		:  named_expression ASSIGN_OP 
+			    {
+			      if ($2 != '=')
+				{
+				  if ($1 < 0)
+				    sprintf (genstr, "DL%d:", -$1);
+				  else
+				    sprintf (genstr, "l%d:", $1);
+				  generate (genstr);
+				}
+			    }
+			  expression
+			    {
+			      if ($4 > 1) warn("comparison in assignment");
+			      if ($2 != '=')
+				{
+				  sprintf (genstr, "%c", $2);
+				  generate (genstr);
+				}
+			      if ($1 < 0)
+				sprintf (genstr, "S%d:", -$1);
+			      else
+				sprintf (genstr, "s%d:", $1);
+			      generate (genstr);
+			      $$ = 0;
+			    }
+			;
+			| expression AND 
+			    {
+			      warn("&& operator");
+			      $2 = next_label++;
+			      sprintf (genstr, "DZ%d:p", $2);
+			      generate (genstr);
+			    }
+			  expression
+			    {
+			      sprintf (genstr, "DZ%d:p1N%d:", $2, $2);
+			      generate (genstr);
+			      $$ = $1 | $4;
+			    }
+			| expression OR
+			    {
+			      warn("|| operator");
+			      $2 = next_label++;
+			      sprintf (genstr, "B%d:", $2);
+			      generate (genstr);
+			    }
+			  expression
+ 			    {
+			      int tmplab;
+			      tmplab = next_label++;
+			      sprintf (genstr, "B%d:0J%d:N%d:1N%d:",
+				       $2, tmplab, $2, tmplab);
+			      generate (genstr);
+			      $$ = $1 | $4;
+			    }
+			| NOT expression
+			    {
+			      $$ = $2;
+			      warn("! operator");
+			      generate ("!");
+			    }
+			| expression REL_OP expression
+			    {
+			      $$ = 3;
+			      switch (*($2))
+				{
+				case '=':
+				  generate ("=");
+				  break;
+
+				case '!':
+				  generate ("#");
+				  break;
+
+				case '<':
+				  if ($2[1] == '=')
+				    generate ("{");
+				  else
+				    generate ("<");
+				  break;
+
+				case '>':
+				  if ($2[1] == '=')
+				    generate ("}");
+				  else
+				    generate (">");
+				  break;
+				}
+			    }
+			| expression '+' expression
+			    {
+			      generate ("+");
+			      $$ = $1 | $3;
+			    }
+			| expression '-' expression
+			    {
+			      generate ("-");
+			      $$ = $1 | $3;
+			    }
+			| expression MUL_OP expression
+			    {
+			      genstr[0] = $2;
+			      genstr[1] = 0;
+			      generate (genstr);
+			      $$ = $1 | $3;
+			    }
+			| expression '^' expression
+			    {
+			      generate ("^");
+			      $$ = $1 | $3;
+			    }
+			| '-' expression  %prec UNARY_MINUS
+			    {
+			      generate ("n");
+			      $$ = $2;
+			    }
+			| named_expression
+			    {
+			      $$ = 1;
+			      if ($1 < 0)
+				sprintf (genstr, "L%d:", -$1);
+			      else
+				sprintf (genstr, "l%d:", $1);
+			      generate (genstr);
+			    }
+			| NUMBER
+			    {
+			      int len = strlen($1);
+			      $$ = 1;
+			      if (len == 1 && *$1 == '0')
+				generate ("0");
+			      else if (len == 1 && *$1 == '1')
+				generate ("1");
+			      else
+				{
+				  generate ("K");
+				  generate ($1);
+				  generate (":");
+				}
+			      free ($1);
+			    }
+			| '(' expression ')'
+			    { $$ = $2 | 1; }
+			| NAME '(' opt_argument_list ')'
+			    {
+			      $$ = 1;
+			      if ($3 != NULL)
+				{ 
+				  sprintf (genstr, "C%d,%s:",
+					   lookup ($1,FUNCT),
+					   arg_str ($3,FALSE));
+				  free_args ($3);
+				}
+			      else
+				{
+				  sprintf (genstr, "C%d:", lookup ($1,FUNCT));
+				}
+			      generate (genstr);
+			    }
+			| INCR_DECR named_expression
+			    {
+			      $$ = 1;
+			      if ($2 < 0)
+				{
+				  if ($1 == '+')
+				    sprintf (genstr, "DA%d:L%d:", -$2, -$2);
+				  else
+				    sprintf (genstr, "DM%d:L%d:", -$2, -$2);
+				}
+			      else
+				{
+				  if ($1 == '+')
+				    sprintf (genstr, "i%d:l%d:", $2, $2);
+				  else
+				    sprintf (genstr, "d%d:l%d:", $2, $2);
+				}
+			      generate (genstr);
+			    }
+			| named_expression INCR_DECR
+			    {
+			      $$ = 1;
+			      if ($1 < 0)
+				{
+				  sprintf (genstr, "DL%d:x", -$1);
+				  generate (genstr); 
+				  if ($2 == '+')
+				    sprintf (genstr, "A%d:", -$1);
+				  else
+				      sprintf (genstr, "M%d:", -$1);
+				}
+			      else
+				{
+				  sprintf (genstr, "l%d:", $1);
+				  generate (genstr);
+				  if ($2 == '+')
+				    sprintf (genstr, "i%d:", $1);
+				  else
+				    sprintf (genstr, "d%d:", $1);
+				}
+			      generate (genstr);
+			    }
+			| Length '(' expression ')'
+			    { generate ("cL"); $$ = 1;}
+			| Sqrt '(' expression ')'
+			    { generate ("cR"); $$ = 1;}
+			| Scale '(' expression ')'
+			    { generate ("cS"); $$ = 1;}
+			| Read '(' ')'
+			    {
+			      warn ("read function");
+			      generate ("cI"); $$ = 1;
+			    }
+			;
+named_expression	: NAME
+			    { $$ = lookup($1,SIMPLE); }
+			| NAME '[' expression ']'
+			    {
+			      if ($3 > 1) warn("comparison in subscript");
+			      $$ = lookup($1,ARRAY);
+			    }
+			| Ibase
+			    { $$ = 0; }
+			| Obase
+			    { $$ = 1; }
+			| Scale
+			    { $$ = 2; }
+			| Last
+			    { $$ = 3; }
+			;
+%%
Index: /trunk/minix/commands/bc/bcdefs.h
===================================================================
--- /trunk/minix/commands/bc/bcdefs.h	(revision 9)
+++ /trunk/minix/commands/bc/bcdefs.h	(revision 9)
@@ -0,0 +1,154 @@
+/* bcdefs.h:  The single file to include all constants and type definitions. */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+/* Include the configuration file. */
+#include "config.h"
+
+/* Standard includes for all files. */
+#include <stdio.h>
+#include <sys/types.h>
+#include <ctype.h>
+#ifdef STRINGS_H
+#include <strings.h>
+#else
+#include <string.h>
+#endif
+#ifndef NO_LIMITS
+#include <limits.h>
+#endif
+
+/* Include the other definitions. */
+#include "const.h"
+#include "number.h"
+
+
+/* These definitions define all the structures used in
+   code and data storage.  This includes the representation of
+   labels.   The "guiding" principle is to make structures that
+   take a minimum of space when unused but can be built to contain
+   the full structures.  */
+
+/* Labels are first.  Labels are generated sequentially in functions
+   and full code.  They just "point" to a single bye in the code.  The
+   "address" is the byte number.  The byte number is used to get an
+   actual character pointer. */
+
+typedef struct bc_label_group
+    {
+      long l_adrs [ BC_LABEL_GROUP ];
+      struct bc_label_group *l_next;
+    } bc_label_group;
+
+
+/* Each function has its own code segments and labels.  There can be
+   no jumps between functions so labels are unique to a function. */
+
+typedef struct arg_list
+    {
+      int av_name;
+      struct arg_list *next;
+    } arg_list;
+
+typedef struct 
+    {
+      char f_defined;   /* Is this function defined yet. */
+      char *f_body[BC_MAX_SEGS];
+      int   f_code_size;
+      bc_label_group *f_label;
+      arg_list *f_params;
+      arg_list *f_autos;
+    } bc_function;
+
+/* Code addresses. */
+typedef struct {
+      int pc_func;
+      int pc_addr;
+    } program_counter;
+
+
+/* Variables are "pushable" (auto) and thus we need a stack mechanism.
+   This is built into the variable record. */
+
+typedef struct bc_var
+    {
+      bc_num v_value;
+      struct bc_var *v_next;
+    }  bc_var;
+
+
+/* bc arrays can also be "auto" variables and thus need the same
+   kind of stacking mechanisms. */
+
+typedef struct bc_array_node
+    {
+      union
+	{
+	  bc_num n_num [NODE_SIZE];
+	  struct bc_array_node *n_down [NODE_SIZE];
+	} n_items;
+    } bc_array_node;
+
+typedef struct bc_array
+    {
+      bc_array_node *a_tree;
+      short a_depth;
+    } bc_array;
+
+typedef struct bc_var_array
+    {
+      bc_array *a_value;
+      char      a_param;
+      struct bc_var_array *a_next;
+    } bc_var_array;
+
+
+/* For the stacks, execution and function, we need records to allow
+   for arbitrary size. */
+
+typedef struct estack_rec {
+	bc_num s_num;
+	struct estack_rec *s_next;
+} estack_rec;
+
+typedef struct fstack_rec {
+	int  s_val;
+	struct fstack_rec *s_next;
+} fstack_rec;
+
+
+/* The following are for the name tree. */
+
+typedef struct id_rec {
+	char  *id;      /* The program name. */
+			/* A name == 0 => nothing assigned yet. */
+	int   a_name;   /* The array variable name (number). */
+	int   f_name;   /* The function name (number).  */
+	int   v_name;   /* The variable name (number).  */
+        short balance;  /* For the balanced tree. */
+	struct id_rec *left, *right; /* Tree pointers. */
+} id_rec;
Index: /trunk/minix/commands/bc/build
===================================================================
--- /trunk/minix/commands/bc/build	(revision 9)
+++ /trunk/minix/commands/bc/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/bc/config.h
===================================================================
--- /trunk/minix/commands/bc/config.h	(revision 9)
+++ /trunk/minix/commands/bc/config.h	(revision 9)
@@ -0,0 +1,4 @@
+/* config.h */
+#define SMALL_BUF
+#define BC_MATH_FILE "/usr/lib/libmath.b"
+#define SHORTNAMES
Index: /trunk/minix/commands/bc/const.h
===================================================================
--- /trunk/minix/commands/bc/const.h	(revision 9)
+++ /trunk/minix/commands/bc/const.h	(revision 9)
@@ -0,0 +1,87 @@
+/* const.h: Constants for bc. */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+
+/* Define INT_MAX and LONG_MAX if not defined.  Assuming 32 bits... */
+
+#ifdef NO_LIMITS
+#define INT_MAX 0x7FFFFFFF
+#define LONG_MAX 0x7FFFFFFF
+#endif
+
+
+/* Define constants in some reasonable size.  The next 4 constants are
+   POSIX constants. */
+
+#define BC_BASE_MAX   INT_MAX
+#define BC_SCALE_MAX  INT_MAX
+#define BC_STRING_MAX INT_MAX
+
+
+/* Definitions for arrays. */
+
+#define BC_DIM_MAX    65535       /* this should be NODE_SIZE^NODE_DEPTH-1 */
+
+#define   NODE_SIZE        16     /* Must be a power of 2. */
+#define   NODE_MASK       0xf     /* Must be NODE_SIZE-1. */
+#define   NODE_SHIFT        4     /* Number of 1 bits in NODE_MASK. */
+#define   NODE_DEPTH        4
+
+
+/* Other BC limits defined but not part of POSIX. */
+
+#define BC_LABEL_GROUP 64
+#define BC_LABEL_LOG    6
+#define BC_MAX_SEGS    16    /* Code segments. */
+#define BC_SEG_SIZE  1024
+#define BC_SEG_LOG     10
+
+/* Maximum number of variables, arrays and functions and the
+   allocation increment for the dynamic arrays. */
+
+#define MAX_STORE   32767
+#define STORE_INCR     32
+
+/* Other interesting constants. */
+
+#define FALSE 0
+#define TRUE  1
+#define SIMPLE 0
+#define ARRAY  1
+#define FUNCT  2
+#define EXTERN extern
+#ifdef __STDC__
+#define CONST const
+#define VOID  void
+#else
+#define CONST
+#define VOID
+#endif
+
+/* Include the version definition. */
+#include "version.h"
Index: /trunk/minix/commands/bc/execute.c
===================================================================
--- /trunk/minix/commands/bc/execute.c	(revision 9)
+++ /trunk/minix/commands/bc/execute.c	(revision 9)
@@ -0,0 +1,783 @@
+/* execute.c - run a bc program. */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include <signal.h>
+#include "global.h"
+#include "proto.h"
+
+
+/* The SIGINT interrupt handling routine. */
+
+int had_sigint;
+
+void
+stop_execution (sig)
+     int sig;
+{
+  had_sigint = TRUE;
+  printf ("\n");
+  rt_error ("interrupted execution");
+}
+
+
+/* Get the current byte and advance the PC counter. */
+
+unsigned char
+byte (pc)
+     program_counter *pc;
+{
+  int seg, offset;
+    
+  seg = pc->pc_addr >> BC_SEG_LOG;
+  offset = pc->pc_addr++ % BC_SEG_SIZE;
+  return (functions[pc->pc_func].f_body[seg][offset]);
+}
+
+
+/* The routine that actually runs the machine. */
+
+void
+execute ()
+{
+  int label_num, l_gp, l_off;
+  bc_label_group *gp;
+  
+  char inst, ch;
+  int  new_func;
+  int  var_name;
+
+  int const_base;
+
+  bc_num temp_num;
+  arg_list *auto_list;
+
+  /* Initialize this run... */
+  pc.pc_func = 0;
+  pc.pc_addr = 0;
+  runtime_error = FALSE;
+  init_num (&temp_num);
+
+  /* Set up the interrupt mechanism for an interactive session. */
+  if (interactive)
+    {
+      signal (SIGINT, stop_execution);
+      had_sigint = FALSE;
+    }
+   
+  while (pc.pc_addr < functions[pc.pc_func].f_code_size && !runtime_error)
+    {
+      inst = byte(&pc);
+
+#if DEBUG > 3
+      { /* Print out address and the stack before each instruction.*/
+	int depth; estack_rec *temp = ex_stack;
+	
+	printf ("func=%d addr=%d inst=%c\n",pc.pc_func, pc.pc_addr, inst);
+	if (temp == NULL) printf ("empty stack.\n", inst);
+	else
+	  {
+	    depth = 1;
+	    while (temp != NULL)
+	      {
+		printf ("   %d = ", depth);
+		out_num (temp->s_num, 10, out_char);
+		depth++;
+		temp = temp->s_next;
+	      }
+	  }
+      }
+#endif
+
+    switch ( inst )
+      {
+
+      case 'A' : /* increment array variable (Add one). */
+	var_name = byte(&pc);
+	if ((var_name & 0x80) != 0)
+	  var_name = ((var_name << 8) & 0x7f) + byte(&pc);
+	incr_array (var_name);
+	break;
+
+      case 'B' : /* Branch to a label if TOS != 0. Remove value on TOS. */
+      case 'Z' : /* Branch to a label if TOS == 0. Remove value on TOS. */
+	c_code = !is_zero (ex_stack->s_num);
+	pop ();
+      case 'J' : /* Jump to a label. */
+	label_num = byte(&pc);  /* Low order bits first. */
+	label_num += byte(&pc) << 8;
+	if (inst == 'J' || (inst == 'B' && c_code)
+	    || (inst == 'Z' && !c_code)) {
+	  gp = functions[pc.pc_func].f_label;
+	  l_gp  = label_num >> BC_LABEL_LOG;
+	  l_off = label_num % BC_LABEL_GROUP;
+	  while (l_gp-- > 0) gp = gp->l_next;
+	  pc.pc_addr = gp->l_adrs[l_off];
+	}
+	break;
+
+      case 'C' : /* Call a function. */
+	/* Get the function number. */
+	new_func = byte(&pc);
+	if ((new_func & 0x80) != 0) 
+	  new_func = ((new_func << 8) & 0x7f) + byte(&pc);
+
+	/* Check to make sure it is defined. */
+	if (!functions[new_func].f_defined)
+	  {
+	    rt_error ("Function %s not defined.", f_names[new_func]);
+	    break;
+	  }
+
+	/* Check and push parameters. */
+	process_params (&pc, new_func);
+
+	/* Push auto variables. */
+	for (auto_list = functions[new_func].f_autos;
+	     auto_list != NULL;
+	     auto_list = auto_list->next)
+	  auto_var (auto_list->av_name);
+
+	/* Push pc and ibase. */
+	fpush (pc.pc_func);
+	fpush (pc.pc_addr);
+	fpush (i_base);
+
+	/* Reset pc to start of function. */
+	pc.pc_func = new_func;
+	pc.pc_addr = 0;
+	break;
+
+      case 'D' : /* Duplicate top of stack */
+	push_copy (ex_stack->s_num);
+	break;
+
+      case 'K' : /* Push a constant */
+	/* Get the input base and convert it to a bc number. */
+	if (pc.pc_func == 0) 
+	  const_base = i_base;
+	else
+	  const_base = fn_stack->s_val;
+	if (const_base == 10)
+	  push_b10_const (&pc);
+	else
+	  push_constant (prog_char, const_base);
+	break;
+
+      case 'L' : /* load array variable */
+	var_name = byte(&pc);
+	if ((var_name & 0x80) != 0)
+	  var_name = ((var_name << 8) & 0x7f) + byte(&pc);
+	load_array (var_name);
+	break;
+
+      case 'M' : /* decrement array variable (Minus!) */
+	var_name = byte(&pc);
+	if ((var_name & 0x80) != 0)
+	  var_name = ((var_name << 8) & 0x7f) + byte(&pc);
+	decr_array (var_name);
+	break;
+
+      case 'O' : /* Write a string to the output with processing. */
+	while ((ch = byte(&pc)) != '"')
+	  if (ch != '\\')
+	    out_char (ch);
+	  else
+	    {
+	      ch = byte(&pc);
+	      if (ch == '"') break;
+	      switch (ch)
+		{
+		case 'n':  out_char ('\n'); break;
+		case 't':  out_char ('\t'); break;
+		case 'r':  out_char ('\r'); break;
+		case 'b':  out_char (007); break;
+		case 'f':  out_char ('\f'); break;
+		case '\\': out_char ('\\'); break;
+		default:  break;
+		}
+	    }
+	if (interactive) fflush (stdout);
+	break;
+
+      case 'R' : /* Return from function */
+	if (pc.pc_func != 0)
+	  {
+	    /* "Pop" autos and parameters. */
+	    pop_vars(functions[pc.pc_func].f_autos);
+	    pop_vars(functions[pc.pc_func].f_params);
+	    /* reset the pc. */
+	    fpop ();
+	    pc.pc_addr = fpop ();
+	    pc.pc_func = fpop ();
+	  }
+	else
+	  rt_error ("Return from main program.");
+	break;
+
+      case 'S' : /* store array variable */
+	var_name = byte(&pc);
+	if ((var_name & 0x80) != 0)
+	  var_name = ((var_name << 8) & 0x7f) + byte(&pc);
+	store_array (var_name);
+	break;
+
+      case 'T' : /* Test tos for zero */
+	c_code = is_zero (ex_stack->s_num);
+	assign (c_code);
+	break;
+
+      case 'W' : /* Write the value on the top of the stack. */
+      case 'P' : /* Write the value on the top of the stack.  No newline. */
+	out_num (ex_stack->s_num, o_base, out_char);
+	if (inst == 'W') out_char ('\n');
+	store_var (3);  /* Special variable "last". */
+	if (interactive) fflush (stdout);
+	break;
+
+      case 'c' : /* Call special function. */
+	new_func = byte(&pc);
+
+      switch (new_func)
+	{
+	case 'L':  /* Length function. */
+	  /* For the number 0.xxxx,  0 is not significant. */
+	  if (ex_stack->s_num->n_len == 1 &&
+	      ex_stack->s_num->n_scale != 0 &&
+	      ex_stack->s_num->n_value[0] == 0 )
+	    int2num (&ex_stack->s_num, ex_stack->s_num->n_scale);
+	  else
+	    int2num (&ex_stack->s_num, ex_stack->s_num->n_len
+		     + ex_stack->s_num->n_scale);
+	  break;
+		
+	case 'S':  /* Scale function. */ 
+	  int2num (&ex_stack->s_num, ex_stack->s_num->n_scale);
+	  break;
+
+	case 'R':  /* Square Root function. */
+	  if (!bc_sqrt (&ex_stack->s_num, scale))
+	    rt_error ("Square root of a negative number");
+	  break;
+
+	case 'I': /* Read function. */
+	  push_constant (input_char, i_base);
+	  break;
+	}
+	break;
+
+      case 'd' : /* Decrement number */
+	var_name = byte(&pc);
+	if ((var_name & 0x80) != 0)
+	  var_name = ((var_name << 8) & 0x7f) + byte(&pc);
+	decr_var (var_name);
+	break;
+      
+      case 'h' : /* Halt the machine. */
+	exit (0);
+
+      case 'i' : /* increment number */
+	var_name = byte(&pc);
+	if ((var_name & 0x80) != 0)
+	  var_name = ((var_name << 8) & 0x7f) + byte(&pc);
+	incr_var (var_name);
+	break;
+
+      case 'l' : /* load variable */
+	var_name = byte(&pc);
+	if ((var_name & 0x80) != 0)
+	  var_name = ((var_name << 8) & 0x7f) + byte(&pc);
+	load_var (var_name);
+	break;
+
+      case 'n' : /* Negate top of stack. */
+	bc_sub (_zero_, ex_stack->s_num, &ex_stack->s_num);
+	break;
+
+      case 'p' : /* Pop the execution stack. */
+	pop ();
+	break;
+
+      case 's' : /* store variable */
+	var_name = byte(&pc);
+	if ((var_name & 0x80) != 0)
+	  var_name = ((var_name << 8) & 0x7f) + byte(&pc);
+	store_var (var_name);
+	break;
+
+      case 'w' : /* Write a string to the output. */
+	while ((ch = byte(&pc)) != '"') out_char (ch);
+	if (interactive) fflush (stdout);
+	break;
+		   
+      case 'x' : /* Exchange Top of Stack with the one under the tos. */
+	if (check_stack(2)) {
+	  bc_num temp = ex_stack->s_num;
+	  ex_stack->s_num = ex_stack->s_next->s_num;
+	  ex_stack->s_next->s_num = temp;
+	}
+	break;
+
+      case '0' : /* Load Constant 0. */
+	push_copy (_zero_);
+	break;
+
+      case '1' : /* Load Constant 0. */
+	push_copy (_one_);
+	break;
+
+      case '!' : /* Negate the boolean value on top of the stack. */
+	c_code = is_zero (ex_stack->s_num);
+	assign (c_code);
+	break;
+
+      case '&' : /* compare greater than */
+	if (check_stack(2))
+	  {
+	    c_code = !is_zero (ex_stack->s_next->s_num)
+	      && !is_zero (ex_stack->s_num);
+	    pop ();
+	    assign (c_code);
+	  }
+	break;
+
+      case '|' : /* compare greater than */
+	if (check_stack(2))
+	  {
+	    c_code = !is_zero (ex_stack->s_next->s_num)
+	      || !is_zero (ex_stack->s_num);
+	    pop ();
+	    assign (c_code);
+	  }
+	break;
+
+      case '+' : /* add */
+	if (check_stack(2))
+	  {
+	    bc_add (ex_stack->s_next->s_num, ex_stack->s_num, &temp_num);
+	    pop();
+	    pop();
+	    push_num (temp_num);
+	    init_num (&temp_num);
+	  }
+	break;
+
+      case '-' : /* subtract */
+	if (check_stack(2))
+	  {
+	    bc_sub (ex_stack->s_next->s_num, ex_stack->s_num, &temp_num);
+	    pop();
+	    pop();
+	    push_num (temp_num);
+	    init_num (&temp_num);
+	  }
+	break;
+
+      case '*' : /* multiply */
+	if (check_stack(2))
+	  {
+	    bc_multiply (ex_stack->s_next->s_num, ex_stack->s_num,
+			 &temp_num, scale);
+	    pop();
+	    pop();
+	    push_num (temp_num);
+	    init_num (&temp_num);
+	  }
+	break;
+
+      case '/' : /* divide */
+	if (check_stack(2))
+	  {
+	    if (bc_divide (ex_stack->s_next->s_num,
+			   ex_stack->s_num, &temp_num, scale) == 0)
+	      {
+		pop();
+		pop();
+		push_num (temp_num);
+		init_num (&temp_num);
+	      }
+	    else
+	      rt_error ("Divide by zero");
+	  }
+	break;
+
+      case '%' : /* remainder */
+	if (check_stack(2))
+	  {
+	    if (is_zero (ex_stack->s_num))
+	      rt_error ("Modulo by zero");
+	    else
+	      {
+		bc_modulo (ex_stack->s_next->s_num,
+			   ex_stack->s_num, &temp_num, scale);
+		pop();
+		pop();
+		push_num (temp_num);
+		init_num (&temp_num);
+	      }
+	  }
+	break;
+
+      case '^' : /* raise */
+	if (check_stack(2))
+	  {
+	    bc_raise (ex_stack->s_next->s_num,
+		      ex_stack->s_num, &temp_num, scale);
+	    if (is_zero (ex_stack->s_next->s_num) && is_neg (ex_stack->s_num))
+	      rt_error ("divide by zero");
+	    pop();
+	    pop();
+	    push_num (temp_num);
+	    init_num (&temp_num);
+	  }
+	break;
+
+      case '=' : /* compare equal */
+	if (check_stack(2))
+	  {
+	    c_code = bc_compare (ex_stack->s_next->s_num,
+				 ex_stack->s_num) == 0;
+	    pop ();
+	    assign (c_code);
+	  }
+	break;
+
+      case '#' : /* compare not equal */
+	if (check_stack(2))
+	  {
+	    c_code = bc_compare (ex_stack->s_next->s_num,
+				 ex_stack->s_num) != 0;
+	    pop ();
+	    assign (c_code);
+	  }
+	break;
+
+      case '<' : /* compare less than */
+	if (check_stack(2))
+	  {
+	    c_code = bc_compare (ex_stack->s_next->s_num,
+				 ex_stack->s_num) == -1;
+	    pop ();
+	    assign (c_code);
+	  }
+	break;
+
+      case '{' : /* compare less than or equal */
+	if (check_stack(2))
+	  {
+	    c_code = bc_compare (ex_stack->s_next->s_num,
+				 ex_stack->s_num) <= 0;
+	    pop ();
+	    assign (c_code);
+	  }
+	break;
+
+      case '>' : /* compare greater than */
+	if (check_stack(2))
+	  {
+	    c_code = bc_compare (ex_stack->s_next->s_num,
+				 ex_stack->s_num) == 1;
+	    pop ();
+	    assign (c_code);
+	  }
+	break;
+
+      case '}' : /* compare greater than or equal */
+	if (check_stack(2))
+	  {
+	    c_code = bc_compare (ex_stack->s_next->s_num,
+				 ex_stack->s_num) >= 0;
+	    pop ();
+	    assign (c_code);
+	  }
+	break;
+
+	default  : /* error! */
+	  rt_error ("bad instruction: inst=%c", inst);
+      }
+    }
+
+  /* Clean up the function stack and pop all autos/parameters. */
+  while (pc.pc_func != 0)
+    {
+      pop_vars(functions[pc.pc_func].f_autos);
+      pop_vars(functions[pc.pc_func].f_params);
+      fpop ();
+      pc.pc_addr = fpop ();
+      pc.pc_func = fpop ();
+    }
+
+  /* Clean up the execution stack. */ 
+  while (ex_stack != NULL) pop();
+
+  /* Clean up the interrupt stuff. */
+  if (interactive)
+    {
+      signal (SIGINT, use_quit);
+      if (had_sigint)
+	printf ("Interruption completed.\n");
+    }
+}
+
+
+/* Prog_char gets another byte from the program.  It is used for
+   conversion of text constants in the code to numbers. */
+
+char
+prog_char ()
+{
+  return byte(&pc);
+}
+
+
+/* Read a character from the standard input.  This function is used
+   by the "read" function. */
+
+char
+input_char ()
+{
+  char in_ch;
+  
+  /* Get a character from the standard input for the read function. */
+  in_ch = getchar();
+
+  /* Check for a \ quoted newline. */
+  if (in_ch == '\\')
+    {
+      in_ch = getchar();
+      if (in_ch == '\n')
+	in_ch = getchar();
+    }
+
+  /* Classify and preprocess the input character. */
+  if (isdigit(in_ch))
+    return (in_ch - '0');
+  if (in_ch >= 'A' && in_ch <= 'F')
+    return (in_ch + 10 - 'A');
+  if (in_ch >= 'a' && in_ch <= 'f')
+    return (in_ch + 10 - 'a');
+  if (in_ch == '.' || in_ch == '+' || in_ch == '-')
+    return (in_ch);
+  if (in_ch <= ' ')
+    return (' ');
+  
+  return (':');
+}
+
+
+/* Push_constant converts a sequence of input characters as returned
+   by IN_CHAR into a number.  The number is pushed onto the execution
+   stack.  The number is converted as a number in base CONV_BASE. */
+
+void
+push_constant (in_char, conv_base)
+   char (*in_char)(VOID);
+   int conv_base;
+{
+  int digits;
+  bc_num build, temp, result, mult, divisor;
+  char  in_ch, first_ch;
+  char  negative;
+
+  /* Initialize all bc numbers */
+  init_num (&temp);
+  init_num (&result);
+  init_num (&mult);
+  build = copy_num (_zero_);
+  negative = FALSE;
+
+  /* The conversion base. */
+  int2num (&mult, conv_base);
+  
+  /* Get things ready. */
+  in_ch = in_char();
+  while (in_ch == ' ')
+    in_ch = in_char();
+
+  if (in_ch == '+')
+    in_ch = in_char();
+  else
+    if (in_ch == '-')
+      {
+	negative = TRUE;
+	in_ch = in_char();
+      }
+
+  /* Check for the special case of a single digit. */
+  if (in_ch < 16)
+    {
+      first_ch = in_ch;
+      in_ch = in_char();
+      if (in_ch < 16 && first_ch >= conv_base)
+	first_ch = conv_base - 1;
+      int2num (&build, (int) first_ch);
+    }
+
+  /* Convert the integer part. */
+  while (in_ch < 16)
+    {
+      if (in_ch < 16 && in_ch >= conv_base) in_ch = conv_base-1;
+      bc_multiply (build, mult, &result, 0);
+      int2num (&temp, (int) in_ch);
+      bc_add (result, temp, &build);
+      in_ch = in_char();
+    }
+  if (in_ch == '.')
+    {
+      in_ch = in_char();
+      if (in_ch >= conv_base) in_ch = conv_base-1;
+      free_num (&result);
+      free_num (&temp);
+      divisor = copy_num (_one_);
+      result = copy_num (_zero_);
+      digits = 0;
+      while (in_ch < 16)
+	{
+	  bc_multiply (result, mult, &result, 0);
+	  int2num (&temp, (int) in_ch);
+	  bc_add (result, temp, &result);
+	  bc_multiply (divisor, mult, &divisor, 0);
+	  digits++;
+	  in_ch = in_char();
+	  if (in_ch < 16 && in_ch >= conv_base) in_ch = conv_base-1;
+	}
+      bc_divide (result, divisor, &result, digits);
+      bc_add (build, result, &build);
+    }
+  
+  /* Final work.  */
+  if (negative)
+    bc_sub (_zero_, build, &build);
+
+  push_num (build);
+  free_num (&temp);
+  free_num (&result);
+  free_num (&mult);
+}
+
+
+/* When converting base 10 constants from the program, we use this
+   more efficient way to convert them to numbers.  PC tells where
+   the constant starts and is expected to be advanced to after
+   the constant. */
+
+void
+push_b10_const (pc)
+     program_counter *pc;
+{
+  bc_num build;
+  program_counter look_pc;
+  int kdigits, kscale;
+  char inchar;
+  char *ptr;
+  
+  /* Count the digits and get things ready. */
+  look_pc = *pc;
+  kdigits = 0;
+  kscale  = 0;
+  inchar = byte (&look_pc);
+  while (inchar != '.' && inchar != ':')
+    {
+      kdigits++;
+      inchar = byte(&look_pc);
+    }
+  if (inchar == '.' )
+    {
+      inchar = byte(&look_pc);
+      while (inchar != ':')
+	{
+	  kscale++;
+	  inchar = byte(&look_pc);
+	}
+    }
+
+  /* Get the first character again and move the pc. */
+  inchar = byte(pc);
+  
+  /* Secial cases of 0, 1, and A-F single inputs. */
+  if (kdigits == 1 && kscale == 0)
+    {
+      if (inchar == 0)
+	{
+	  push_copy (_zero_);
+	  inchar = byte(pc);
+	  return;
+	}
+      if (inchar == 1) {
+      push_copy (_one_);
+      inchar = byte(pc);
+      return;
+    }
+    if (inchar > 9)
+      {
+	init_num (&build);
+	int2num (&build, inchar);
+	push_num (build);
+	inchar = byte(pc);
+	return;
+      }
+    }
+
+  /* Build the new number. */
+  if (kdigits == 0)
+    {
+      build = new_num (1,kscale);
+      ptr = build->n_value;
+      *ptr++ = 0;
+    }
+  else
+    {
+      build = new_num (kdigits,kscale);
+      ptr = build->n_value;
+    }
+
+  while (inchar != ':')
+    {
+      if (inchar != '.')
+	if (inchar > 9)
+	  *ptr++ = 9;
+	else
+	  *ptr++ = inchar;
+      inchar = byte(pc);
+    }
+  push_num (build);
+}
+
+
+/* Put the correct value on the stack for C_CODE.  Frees TOS num. */
+
+void
+assign (c_code)
+     char c_code;
+{
+  free_num (&ex_stack->s_num);
+  if (c_code)
+    ex_stack->s_num = copy_num (_one_);
+  else
+    ex_stack->s_num = copy_num (_zero_);
+}
Index: /trunk/minix/commands/bc/fix_math.h
===================================================================
--- /trunk/minix/commands/bc/fix_math.h	(revision 9)
+++ /trunk/minix/commands/bc/fix_math.h	(revision 9)
@@ -0,0 +1,9 @@
+#!/bin/sh
+ed - math.h <<EOS-EOS
+1,1s/^/"/
+1,\$s/\$/\\\\/
+\$,\$d
+\$,\$s/\\\\\$/"/
+w
+q
+EOS-EOS
Index: /trunk/minix/commands/bc/global.c
===================================================================
--- /trunk/minix/commands/bc/global.c	(revision 9)
+++ /trunk/minix/commands/bc/global.c	(revision 9)
@@ -0,0 +1,42 @@
+/* global.c:  This defines the global variables. */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+
+/* Since we want to define them here, we use the following define. */
+#undef EXTERN
+#define EXTERN
+
+/* Define all the global variables for bc. */
+#include "global.h"
+
+#ifndef BC_MATH_FILE
+CONST char libmath[] = 
+#include "math.h"
+;
+#endif 
Index: /trunk/minix/commands/bc/global.h
===================================================================
--- /trunk/minix/commands/bc/global.h	(revision 9)
+++ /trunk/minix/commands/bc/global.h	(revision 9)
@@ -0,0 +1,108 @@
+/* global.h:  The global variables for bc.  */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+
+/* For the current "break level" and if statements. */
+EXTERN int break_label;
+EXTERN int if_label;
+EXTERN int continue_label;
+
+/* Label numbers. */
+EXTERN int next_label;
+
+/* Used for "code" generation. */
+EXTERN char genstr[80];
+EXTERN int out_count;
+EXTERN char did_gen;
+
+/* Interactive and other flags. */
+EXTERN char interactive;
+EXTERN char compile_only;
+EXTERN char use_math;
+EXTERN char warn_not_std;
+EXTERN char std_only;
+
+/* global variables for the bc machine. All will be dynamic in size.*/
+/* Function storage. main is (0) and functions (1-f_count) */
+
+EXTERN bc_function *functions;
+EXTERN char **f_names;
+EXTERN int  f_count;
+
+/* Variable stoarge and reverse names. */
+
+EXTERN bc_var **variables;
+EXTERN char **v_names;
+EXTERN int  v_count;
+
+/* Array Variable storage and reverse names. */
+
+EXTERN bc_var_array **arrays;
+EXTERN char **a_names;
+EXTERN int  a_count;
+
+/* Execution stack. */
+EXTERN estack_rec *ex_stack;
+
+/* Function return stack. */
+EXTERN fstack_rec *fn_stack;
+
+/* Other "storage". */
+EXTERN int i_base;
+EXTERN int o_base;
+EXTERN int scale;
+EXTERN char c_code;
+EXTERN int out_col;
+EXTERN char runtime_error;
+EXTERN program_counter pc;
+
+/* Input Line numbers and other error information. */
+EXTERN int line_no;
+EXTERN int had_error;
+
+/* For larger identifiers, a tree, and how many "storage" locations
+   have been allocated. */
+
+EXTERN int next_array;
+EXTERN int next_func;
+EXTERN int next_var;
+
+EXTERN id_rec *name_tree;
+
+/* For error message production */
+EXTERN char **g_argv;
+EXTERN int    g_argc;
+EXTERN char   is_std_in;
+
+/* defined in number.c */
+extern bc_num _zero_;
+extern bc_num _one_;
+
+/* For use with getopt.  Do not declare them here.*/
+extern int optind;
+
Index: /trunk/minix/commands/bc/libmath.b
===================================================================
--- /trunk/minix/commands/bc/libmath.b	(revision 9)
+++ /trunk/minix/commands/bc/libmath.b	(revision 9)
@@ -0,0 +1,255 @@
+/* libmath.b for bc for minix.  */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+
+scale = 20
+
+/* Uses the fact that e^x = (e^(x/2))^2
+   When x is small enough, we use the series:
+     e^x = 1 + x + x^2/2! + x^3/3! + ...
+*/
+
+define e(x) {
+  auto  a, d, e, f, i, m, v, z
+
+  /* Check the sign of x. */
+  if (x<0) {
+    m = 1
+    x = -x
+  } 
+
+  /* Precondition x. */
+  z = scale;
+  scale = 4 + z + .44*x;
+  while (x > 1) {
+    f += 1;
+    x /= 2;
+  }
+
+  /* Initialize the variables. */
+  v = 1+x
+  a = x
+  d = 1
+
+  for (i=2; 1; i++) {
+    e = (a *= x) / (d *= i)
+    if (e == 0) {
+      if (f>0) while (f--)  v = v*v;
+      scale = z
+      if (m) return (1/v);
+      return (v/1);
+    }
+    v += e
+  }
+}
+
+/* Natural log. Uses the fact that ln(x^2) = 2*ln(x)
+    The series used is:
+       ln(x) = 2(a+a^3/3+a^5/5+...) where a=(x-1)/(x+1)
+*/
+
+define l(x) {
+  auto e, f, i, m, n, v, z
+
+  /* return something for the special case. */
+  if (x <= 0) return (1 - 10^scale)
+
+  /* Precondition x to make .5 < x < 2.0. */
+  z = scale;
+  scale += 4;
+  f = 2;
+  i=0
+  while (x >= 2) {  /* for large numbers */
+    f *= 2;
+    x = sqrt(x);
+  }
+  while (x <= .5) {  /* for small numbers */
+    f *= 2;
+    x = sqrt(x);
+  }
+
+  /* Set up the loop. */
+  v = n = (x-1)/(x+1)
+  m = n*n
+
+  /* Sum the series. */
+  for (i=3; 1; i+=2) {
+    e = (n *= m) / i
+    if (e == 0) {
+      v = f*v
+      scale = z
+      return (v/1)
+    }
+    v += e
+  }
+}
+
+/* Sin(x)  uses the standard series:
+   sin(x) = x - x^3/3! + x^5/5! - x^7/7! ... */
+
+define s(x) {
+  auto  e, i, m, n, s, v, z
+
+  /* precondition x. */
+  z = scale 
+  scale = 1.1*z + 1;
+  v = a(1)
+  if (x < 0) {
+    m = 1;
+    x = -x;
+  }
+  scale = 0
+  n = (x / v + 2 )/4
+  x = x - 4*n*v
+  if (n%2) x = -x
+
+  /* Do the loop. */
+  scale = z + 2;
+  v = e = x
+  s = -x*x
+  for (i=3; 1; i+=2) {
+    e *= s/(i*(i-1))
+    if (e == 0) {
+      scale = z
+      if (m) return (-v/1);
+      return (v/1);
+    }
+    v += e
+  }
+}
+
+/* Cosine : cos(x) = sin(x+pi/2) */
+define c(x) {
+  auto v;
+  scale += 1;
+  v = s(x+a(1)*2);
+  scale -= 1;
+  return (v/1);
+}
+
+/* Arctan: Using the formula:
+     atan(x) = atan(c) + atan((x-c)/(1+xc)) for a small c (.2 here)
+   For under .2, use the series:
+     atan(x) = x - x^3/3 + x^5/5 - x^7/7 + ...   */
+
+define a(x) {
+  auto a, e, f, i, m, n, s, v, z
+
+  /* Special case and for fast answers */
+  if (x==1) {
+    if (scale <= 25) return (.7853981633974483096156608/1)
+    if (scale <= 40) return (.7853981633974483096156608458198757210492/1)
+    if (scale <= 60) \
+      return (.785398163397448309615660845819875721049292349843776455243736/1)
+  }
+  if (x==.2) {
+    if (scale <= 25) return (.1973955598498807583700497/1)
+    if (scale <= 40) return (.1973955598498807583700497651947902934475/1)
+    if (scale <= 60) \
+      return (.197395559849880758370049765194790293447585103787852101517688/1)
+  }
+
+  /* Negative x? */
+  if (x<0) {
+    m = 1;
+    x = -x;
+  }
+
+  /* Save the scale. */
+  z = scale;
+
+  /* Note: a and f are known to be zero due to being auto vars. */
+  /* Calculate atan of a known number. */ 
+  if (x > .2)  {
+    scale = z+4;
+    a = a(.2);
+  }
+   
+  /* Precondition x. */
+  scale = z+2;
+  while (x > .2) {
+    f += 1;
+    x = (x-.2) / (1+x*.2);
+  }
+
+  /* Initialize the series. */
+  v = n = x;
+  s = -x*x;
+
+  /* Calculate the series. */
+  for (i=3; 1; i+=2) {
+    e = (n *= s) / i;
+    if (e == 0) {
+      scale = z;
+      if (m) return ((f*a+v)/-1);
+      return ((f*a+v)/1);
+    }
+    v += e
+  }
+}
+
+
+/* Bessel function of integer order.  Uses the following:
+   j(-n,x) = (-1)^n*j(n,x) 
+   j(n,x) = x^n/(2^n*n!) * (1 - x^2/(2^2*1!*(n+1)) + x^4/(2^4*2!*(n+1)*(n+2))
+            - x^6/(2^6*3!*(n+1)*(n+2)*(n+3)) .... )
+*/
+define j(n,x) {
+  auto a, d, e, f, i, m, s, v, z
+
+  /* Make n an integer and check for negative n. */
+  z = scale;
+  scale = 0;
+  n = n/1;
+  if (n<0) {
+    n = -n;
+    if (n%2 == 1) m = 1;
+  }
+
+  /* Compute the factor of x^n/(2^n*n!) */
+  f = 1;
+  for (i=2; i<=n; i++) f = f*i;
+  scale = 1.5*z;
+  f = x^n / 2^n / f;
+
+  /* Initialize the loop .*/
+  v = e = 1;
+  s = -x*x/4
+  scale = 1.5*z
+
+  /* The Loop.... */
+  for (i=1; 1; i++) {
+    e =  e * s / i / (n+i);
+    if (e == 0) {
+       scale = z
+       if (m) return (-f*v/1);
+       return (f*v/1);
+    }
+    v += e;
+  }
+}
Index: /trunk/minix/commands/bc/load.c
===================================================================
--- /trunk/minix/commands/bc/load.c	(revision 9)
+++ /trunk/minix/commands/bc/load.c	(revision 9)
@@ -0,0 +1,333 @@
+/* load.c:  This code "loads" code into the code segments. */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include "global.h"
+#include "proto.h"
+
+/* Load variables. */
+
+program_counter load_adr;
+char load_str;
+char load_const;
+
+/* Initialize the load sequence. */
+void
+init_load ()
+{
+  clear_func(0);
+  load_adr.pc_func = 0;
+  load_adr.pc_addr = 0;
+  load_str = FALSE;
+  load_const = FALSE;
+}
+
+/* addbyte adds one BYTE to the current code segment. */
+void
+addbyte (byte)
+     char byte;
+{
+  int seg, offset, func;
+
+  /* If there was an error, don't continue. */
+  if (had_error) return;
+
+  /* Calculate the segment and offset. */
+  seg = load_adr.pc_addr >> BC_SEG_LOG;
+  offset = load_adr.pc_addr++ % BC_SEG_SIZE;
+  func = load_adr.pc_func;
+
+  if (seg >= BC_MAX_SEGS)
+    {
+      yyerror ("Function too big.");
+      return;
+    }
+
+  if (functions[func].f_body[seg] == NULL)
+    functions[func].f_body[seg] = (char *) bc_malloc (BC_SEG_SIZE);
+
+  /* Store the byte. */
+  functions[func].f_body[seg][offset] = byte;
+  functions[func].f_code_size++;
+}
+
+
+/* Define a label LAB to be the current program counter. */
+
+void
+def_label (lab)
+     long lab;
+{
+  bc_label_group *temp;
+  int group, offset, func;
+    
+  /* Get things ready. */
+  group = lab >> BC_LABEL_LOG;
+  offset = lab % BC_LABEL_GROUP;
+  func = load_adr.pc_func;
+  
+  /* Make sure there is at least one label group. */
+  if (functions[func].f_label == NULL)
+    {
+      functions[func].f_label = 
+	(bc_label_group *) bc_malloc (sizeof(bc_label_group));
+      functions[func].f_label->l_next = NULL;
+    }
+
+  /* Add the label group. */
+  temp = functions[func].f_label;
+  while (group > 0)
+    {
+      if (temp->l_next == NULL)
+	{
+	  temp->l_next = (bc_label_group *) bc_malloc (sizeof(bc_label_group));
+	  temp->l_next->l_next = NULL;
+	}
+      temp = temp->l_next;
+      group --;
+    }
+
+  /* Define it! */
+  temp->l_adrs [offset] = load_adr.pc_addr;
+}
+
+/* Several instructions have integers in the code.  They
+   are all known to be legal longs.  So, no error code
+   is added.  STR is the pointer to the load string and
+   must be moved to the last non-digit character. */
+
+long
+long_val (str)
+     char **str;
+{ int  val = 0;
+  char neg = FALSE;
+
+  if (**str == '-')
+    {
+      neg = TRUE;
+      (*str)++;
+    }
+  while (isdigit(**str)) 
+    val = val*10 + *(*str)++ - '0';
+
+  if (neg)
+    return -val;
+  else
+    return val;
+}
+
+
+/* load_code loads the CODE into the machine. */
+
+void
+load_code (code)
+     char *code;
+{
+  char *str;
+  long  ap_name;	/* auto or parameter name. */
+  long  label_no;
+  long  vaf_name;	/* variable, array or function number. */
+  long  func;
+  program_counter save_adr;
+
+  /* Initialize. */
+  str = code;
+   
+  /* Scan the code. */
+  while (*str != 0)
+    {
+      /* If there was an error, don't continue. */
+      if (had_error) return;
+
+      if (load_str)
+	{
+	  if (*str == '"') load_str = FALSE;
+	  addbyte (*str++);
+	}
+      else
+	if (load_const)
+	  {
+	    if (*str == '\n') 
+	      str++;
+	    else
+	      {
+		if (*str == ':')
+		  {
+		    load_const = FALSE;
+		    addbyte (*str++);
+		  }
+		else
+		  if (*str == '.')
+		    addbyte (*str++);
+		  else
+		    if (*str >= 'A')
+		      addbyte (*str++ + 10 - 'A');
+		    else
+		      addbyte (*str++ - '0');
+	      }
+	  }
+	else
+	  {
+	    switch (*str)
+	      {
+
+	      case '"':	/* Starts a string. */
+		load_str = TRUE;
+		break;
+
+	      case 'N': /* A label */
+		str++;
+		label_no = long_val (&str);
+		def_label (label_no);
+		break;
+
+	      case 'B':  /* Branch to label. */
+	      case 'J':  /* Jump to label. */
+	      case 'Z':  /* Branch Zero to label. */
+		addbyte(*str++);
+		label_no = long_val (&str);
+		if (label_no > 65535L)
+		  {  /* Better message? */
+		    fprintf (stderr,"Program too big.\n");
+		    exit(1);
+		  }
+		addbyte ( (char) label_no & 0xFF);
+		addbyte ( (char) label_no >> 8);
+		break;
+
+	      case 'F':  /* A function, get the name and initialize it. */
+		str++;
+		func = long_val (&str);
+		clear_func (func);
+#if DEBUG > 2
+		printf ("Loading function number %d\n", func);
+#endif
+		/* get the parameters */
+		while (*str++ != '.')
+		  {
+		    if (*str == '.')
+		      {
+			str++;
+			break;
+		      }
+		    ap_name = long_val (&str);
+#if DEBUG > 2
+		    printf ("parameter number %d\n", ap_name);
+#endif
+		    functions[(int)func].f_params = 
+		      nextarg (functions[(int)func].f_params, ap_name);
+		  }
+
+		/* get the auto vars */
+		while (*str != '[')
+		  {
+		    if (*str == ',') str++;
+		    ap_name = long_val (&str);
+#if DEBUG > 2
+		    printf ("auto number %d\n", ap_name);
+#endif
+		    functions[(int)func].f_autos = 
+		      nextarg (functions[(int)func].f_autos, ap_name);
+		  }
+		save_adr = load_adr;
+		load_adr.pc_func = func;
+		load_adr.pc_addr = 0;
+		break;
+		
+	      case ']':  /* A function end */
+		functions[load_adr.pc_func].f_defined = TRUE;
+		load_adr = save_adr;
+		break;
+
+	      case 'C':  /* Call a function. */
+		addbyte (*str++);
+		func = long_val (&str);
+		if (func < 128)
+		  addbyte ( (char) func);
+		else
+		  {
+		    addbyte ((func >> 8) & 0xff | 0x80);
+		    addbyte (func & 0xff);
+		  }
+		if (*str == ',') str++;
+		while (*str != ':')
+		  addbyte (*str++);
+		addbyte (':');
+		break;
+		
+	      case 'c':  /* Call a special function. */
+		addbyte (*str++);
+		addbyte (*str);
+		break;
+
+	      case 'K':  /* A constant.... may have an "F" in it. */
+		addbyte (*str);
+		load_const = TRUE;
+		break;
+
+	      case 'd':  /* Decrement. */
+	      case 'i':  /* Increment. */
+	      case 'l':  /* Load. */
+	      case 's':  /* Store. */
+	      case 'A':  /* Array Increment */
+	      case 'M':  /* Array Decrement */
+	      case 'L':  /* Array Load */
+	      case 'S':  /* Array Store */
+		addbyte (*str++);
+		vaf_name = long_val (&str);
+		if (vaf_name < 128)
+		  addbyte (vaf_name);
+		else
+		  {
+		    addbyte ((vaf_name >> 8) & 0xff | 0x80);
+		    addbyte (vaf_name & 0xff);
+		  }
+		break;
+
+	      case '@':  /* A command! */
+		switch (*(++str))
+		  {
+		  case 'i':
+		    init_load ();
+		    break;
+		  case 'r':
+		    execute ();
+		    break;
+		  } 
+		break;
+
+	      case '\n':  /* Ignore the newlines */
+		break;
+		
+	      default:   /* Anything else */
+		addbyte (*str);	   
+	      }
+	    str++;
+	  }
+    }
+}
Index: /trunk/minix/commands/bc/main.c
===================================================================
--- /trunk/minix/commands/bc/main.c	(revision 9)
+++ /trunk/minix/commands/bc/main.c	(revision 9)
@@ -0,0 +1,204 @@
+/* main.c: The main program for bc.  */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include <signal.h>
+#include "global.h"
+#include "proto.h"
+
+/* Variables for processing multiple files. */
+char   first_file;
+extern FILE *yyin;
+
+
+/* The main program for bc. */
+int
+main (argc, argv)
+     int argc;
+     char *argv[];
+{
+  int  ch; 
+  
+  /* Initialize many variables. */
+  compile_only = FALSE;
+  use_math = FALSE;
+  warn_not_std = FALSE;
+  std_only = FALSE;
+  if (isatty(0) && isatty(1)) 
+    interactive = TRUE;
+  else
+    interactive = FALSE;
+
+  /* Parse the command line */
+  ch = getopt (argc, argv, "lcisvw");
+  while (ch != EOF)
+    {
+      switch (ch)
+	{
+	case 'c':  /* compile only */
+	  compile_only = TRUE;
+	  break;
+	case 'l':  /* math lib */
+	  use_math = TRUE;
+	  break;
+	case 'i':  /* force interactive */
+	  interactive = TRUE;
+	  break;
+	case 'w':  /* Non standard features give warnings. */
+	  warn_not_std = TRUE;
+	  break;
+	case 's':  /* Non standard features give errors. */
+	  std_only = TRUE;
+	  break;
+	case 'v':  /* Print the version. */
+	  printf ("%s\n", BC_VERSION);
+	  break;
+	}
+      ch = getopt (argc, argv, "lcisvw");
+    }
+
+  /* Initialize the machine.  */
+  init_storage();
+  init_load();
+
+  /* Set up interrupts to print a message. */
+  if (interactive)
+    signal (SIGINT, use_quit);
+
+  /* Initialize the front end. */
+  init_tree();
+  init_gen ();
+  g_argv = argv;
+  g_argc = argc;
+  is_std_in = FALSE;
+  first_file = TRUE;
+  if (!open_new_file ())
+    exit (1);
+
+  /* Do the parse. */
+  yyparse ();
+
+  /* End the compile only output with a newline. */
+  if (compile_only)
+    printf ("\n");
+
+  exit (0);
+}
+
+
+/* This is the function that opens all the files. 
+   It returns TRUE if the file was opened, otherwise
+   it returns FALSE. */
+
+int
+open_new_file ()
+{
+  FILE *new_file;
+
+  /* Set the line number. */
+  line_no = 1;
+
+  /* Check to see if we are done. */
+  if (is_std_in) return (FALSE);
+
+  /* Open the other files. */
+  if (use_math && first_file)
+    {
+#ifdef BC_MATH_FILE
+      /* Make the first file be the math library. */
+      new_file = fopen (BC_MATH_FILE, "r");
+      use_math = FALSE;
+      if (new_file != NULL)
+	{
+	  new_yy_file (new_file);
+	  return TRUE;
+	}	
+      else
+	{
+	  fprintf (stderr, "Math Library unavailable.\n");
+	  exit (1);
+	}
+#else
+      /* Load the code from a precompiled version of the math libarary. */
+      extern char libmath[];
+      char tmp;
+      /* These MUST be in the order of first mention of each function.
+	 That is why "a" comes before "c" even though "a" is defined after
+	 after "c".  "a" is used in "s"! */
+      tmp = lookup ("e", FUNCT);
+      tmp = lookup ("l", FUNCT);
+      tmp = lookup ("s", FUNCT);
+      tmp = lookup ("a", FUNCT);
+      tmp = lookup ("c", FUNCT);
+      tmp = lookup ("j", FUNCT);
+      load_code (libmath);
+#endif
+    }
+  
+  /* One of the argv values. */
+  while (optind < g_argc)
+    {
+      new_file = fopen (g_argv[optind], "r");
+      if (new_file != NULL)
+	{
+	  new_yy_file (new_file);
+	  optind++;
+	  return TRUE;
+	}
+      fprintf (stderr, "File %s is unavailable.\n", g_argv[optind++]);
+      exit (1);
+    }
+  
+  /* If we fall through to here, we should return stdin. */
+  new_yy_file (stdin);
+  is_std_in = TRUE;
+  return TRUE;
+}
+
+
+/* Set yyin to the new file. */
+
+void
+new_yy_file (file)
+     FILE *file;
+{
+  if (!first_file) fclose (yyin);
+  yyin = file;
+  first_file = FALSE;
+}
+
+
+/* Message to use quit.  */
+
+void
+use_quit (sig)
+     int sig;
+{
+  printf ("\n(interrupt) use quit to exit.\n");
+  signal (SIGINT, use_quit);
+}
Index: /trunk/minix/commands/bc/number.c
===================================================================
--- /trunk/minix/commands/bc/number.c	(revision 9)
+++ /trunk/minix/commands/bc/number.c	(revision 9)
@@ -0,0 +1,1405 @@
+/* number.c: Implements arbitrary precision numbers. */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include "proto.h"
+
+/* Storage used for special numbers. */
+bc_num _zero_;
+bc_num _one_;
+bc_num _two_;
+
+
+/* "Frees" a bc_num NUM.  Actually decreases reference count and only
+   frees the storage if reference count is zero. */
+
+void
+free_num (num)
+    bc_num *num;
+{
+  if (*num == NULL) return;
+  (*num)->n_refs--; 
+  if ((*num)->n_refs == 0) free(*num);
+  *num = NULL;
+}
+
+
+/* new_num allocates a number and sets fields to known values. */
+
+bc_num
+new_num (length, scale)
+     int length, scale;
+{
+  bc_num temp;
+
+  temp = (bc_num) malloc (sizeof(bc_struct)+length+scale);
+  if (temp == NULL) out_of_memory ();
+  temp->n_sign = PLUS;
+  temp->n_len = length;
+  temp->n_scale = scale;
+  temp->n_refs = 1;
+  temp->n_value[0] = 0;
+  return temp;
+}
+
+
+/* Intitialize the number package! */
+
+void
+init_numbers ()
+{
+  _zero_ = new_num (1,0);
+  _one_  = new_num (1,0);
+  _one_->n_value[0] = 1;
+  _two_  = new_num (1,0);
+  _two_->n_value[0] = 2;
+}
+
+
+/* Make a copy of a number!  Just increments the reference count! */
+
+bc_num
+copy_num (num)
+     bc_num num;
+{
+  num->n_refs++;
+  return num;
+}
+
+
+/* Initialize a number NUM by making it a copy of zero. */
+
+void
+init_num (num)
+     bc_num *num;
+{
+  *num = copy_num (_zero_);
+}
+
+
+/* Convert an integer VAL to a bc number NUM. */
+
+void
+int2num (num, val)
+     bc_num *num;
+     int val;
+{
+  char buffer[30];
+  char *bptr, *vptr;
+  int  ix = 1;
+  char neg = 0;
+  
+  /* Sign. */
+  if (val < 0)
+    {
+      neg = 1;
+      val = -val;
+    }
+  
+  /* Get things going. */
+  bptr = buffer;
+  *bptr++ = val % 10;
+  val = val / 10;
+  
+  /* Extract remaining digits. */
+  while (val != 0)
+    {
+      *bptr++ = val % 10;
+      val = val / 10;
+      ix++; 		/* Count the digits. */
+    }
+  
+  /* Make the number. */
+  free_num (num);
+  *num = new_num (ix, 0);
+  if (neg) (*num)->n_sign = MINUS;
+  
+  /* Assign the digits. */
+  vptr = (*num)->n_value;
+  while (ix-- > 0)
+    *vptr++ = *--bptr;
+}
+
+
+/* Convert a number NUM to a long.  The function returns only the integer 
+   part of the number.  For numbers that are too large to represent as
+   a long, this function returns a zero.  This can be detected by checking
+   the NUM for zero after having a zero returned. */
+
+long
+num2long (num)
+     bc_num num;
+{
+  long val;
+  char *nptr;
+  int  index;
+
+  /* Extract the int value, ignore the fraction. */
+  val = 0;
+  nptr = num->n_value;
+  for (index=num->n_len; (index>0) && (val<=(LONG_MAX/10)); index--)
+    val = val*10 + *nptr++;
+  
+  /* Check for overflow.  If overflow, return zero. */
+  if (index>0) val = 0;
+  if (val < 0) val = 0;
+ 
+  /* Return the value. */
+  if (num->n_sign == PLUS)
+    return (val);
+  else
+    return (-val);
+}
+
+
+/* The following are some math routines for numbers. */
+_PROTOTYPE(static int _do_compare, (bc_num n1, bc_num n2, int use_sign,
+				    int ignore_last));
+_PROTOTYPE(static void _rm_leading_zeros, (bc_num num));
+_PROTOTYPE(static bc_num _do_add, (bc_num n1, bc_num n2));
+_PROTOTYPE(static bc_num _do_sub, (bc_num n1, bc_num n2));
+_PROTOTYPE(static void _one_mult, (unsigned char *num, int size, int digit,
+				   unsigned char *result));
+
+
+
+/* Compare two bc numbers.  Return value is 0 if equal, -1 if N1 is less
+   than N2 and +1 if N1 is greater than N2.  If USE_SIGN is false, just
+   compare the magnitudes. */
+
+static int
+_do_compare (n1, n2, use_sign, ignore_last)
+     bc_num n1, n2;
+     int use_sign;
+     int ignore_last;
+{
+  char *n1ptr, *n2ptr;
+  int  count;
+  
+  /* First, compare signs. */
+  if (use_sign && n1->n_sign != n2->n_sign)
+    {
+      if (n1->n_sign == PLUS)
+	return (1);	/* Positive N1 > Negative N2 */
+      else
+	return (-1);	/* Negative N1 < Positive N1 */
+    }
+  
+  /* Now compare the magnitude. */
+  if (n1->n_len != n2->n_len)
+    {
+      if (n1->n_len > n2->n_len)
+	{
+	  /* Magnitude of n1 > n2. */
+	  if (!use_sign || n1->n_sign == PLUS)
+	    return (1);
+	  else
+	    return (-1);
+	}
+      else
+	{
+	  /* Magnitude of n1 < n2. */
+	  if (!use_sign || n1->n_sign == PLUS)
+	    return (-1);
+	  else
+	    return (1);
+	}
+    }
+
+  /* If we get here, they have the same number of integer digits.
+     check the integer part and the equal length part of the fraction. */
+  count = n1->n_len + MIN (n1->n_scale, n2->n_scale);
+  n1ptr = n1->n_value;
+  n2ptr = n2->n_value;
+
+  while ((count > 0) && (*n1ptr == *n2ptr))
+    {
+      n1ptr++;
+      n2ptr++;
+      count--;
+    }
+  if (ignore_last && count == 1 && n1->n_scale == n2->n_scale)
+    return (0);
+  if (count != 0)
+    {
+      if (*n1ptr > *n2ptr)
+	{
+	  /* Magnitude of n1 > n2. */
+	  if (!use_sign || n1->n_sign == PLUS)
+	    return (1);
+	  else
+	    return (-1);
+	}
+      else
+	{
+	  /* Magnitude of n1 < n2. */
+	  if (!use_sign || n1->n_sign == PLUS)
+	    return (-1);
+	  else
+	    return (1);
+	}
+    }
+
+  /* They are equal up to the last part of the equal part of the fraction. */
+  if (n1->n_scale != n2->n_scale) 
+    if (n1->n_scale > n2->n_scale)
+      {
+	for (count = n1->n_scale-n2->n_scale; count>0; count--)
+	  if (*n1ptr++ != 0)
+	    {
+	      /* Magnitude of n1 > n2. */
+	      if (!use_sign || n1->n_sign == PLUS)
+		return (1);
+	      else
+		return (-1);
+	    }
+      }
+    else
+      {
+	for (count = n2->n_scale-n1->n_scale; count>0; count--)
+	  if (*n2ptr++ != 0)
+	    {
+	      /* Magnitude of n1 < n2. */
+	      if (!use_sign || n1->n_sign == PLUS)
+		return (-1);
+	      else
+		return (1);
+	    }
+      }
+  
+  /* They must be equal! */
+  return (0);
+}
+
+
+/* This is the "user callable" routine to compare numbers N1 and N2. */
+
+int
+bc_compare (n1, n2)
+     bc_num n1, n2;
+{
+  return _do_compare (n1, n2, TRUE, FALSE);
+}
+
+
+/* In some places we need to check if the number NUM is zero. */
+
+char
+is_zero (num)
+     bc_num num;
+{
+  int  count;
+  char *nptr;
+
+  /* Quick check. */
+  if (num == _zero_) return TRUE;
+
+  /* Initialize */
+  count = num->n_len + num->n_scale;
+  nptr = num->n_value;
+
+  /* The check */
+  while ((count > 0) && (*nptr++ == 0)) count--;
+
+  if (count != 0)
+    return FALSE;
+  else 
+    return TRUE;
+}
+
+
+/* In some places we need to check if the number is negative. */
+
+char
+is_neg (num)
+     bc_num num;
+{
+  return num->n_sign == MINUS;
+}
+
+
+/* For many things, we may have leading zeros in a number NUM.
+   _rm_leading_zeros just moves the data to the correct
+   place and adjusts the length. */
+
+static void
+_rm_leading_zeros (num)
+     bc_num num;
+{
+  int bytes;
+  char *dst, *src;
+
+  /* Do a quick check to see if we need to do it. */
+  if (*num->n_value != 0) return;
+
+  /* The first digit is 0, find the first non-zero digit in the 10's or
+     greater place. */
+  bytes = num->n_len;
+  src = num->n_value;
+  while (bytes > 1 && *src == 0) src++, bytes--;
+  num->n_len = bytes;
+  bytes += num->n_scale;
+  dst = num->n_value;
+  while (bytes-- > 0) *dst++ = *src++;
+  
+}
+
+
+/* Perform addition: N1 is added to N2 and the value is
+   returned.  The signs of N1 and N2 are ignored. */
+
+static bc_num
+_do_add (n1, n2)
+     bc_num n1, n2;
+{
+  bc_num sum;
+  int sum_scale, sum_digits;
+  char *n1ptr, *n2ptr, *sumptr;
+  int carry, n1bytes, n2bytes;
+
+  /* Prepare sum. */
+  sum_scale = MAX (n1->n_scale, n2->n_scale);
+  sum_digits = MAX (n1->n_len, n2->n_len) + 1;
+  sum = new_num (sum_digits,sum_scale);
+
+  /* Start with the fraction part.  Initialize the pointers. */
+  n1bytes = n1->n_scale;
+  n2bytes = n2->n_scale;
+  n1ptr = (char *) (n1->n_value + n1->n_len + n1bytes - 1);
+  n2ptr = (char *) (n2->n_value + n2->n_len + n2bytes - 1);
+  sumptr = (char *) (sum->n_value + sum_scale + sum_digits - 1);
+
+  /* Add the fraction part.  First copy the longer fraction.*/
+  if (n1bytes != n2bytes)
+    {
+      if (n1bytes > n2bytes)
+	while (n1bytes>n2bytes)
+	  { *sumptr-- = *n1ptr--; n1bytes--;}
+      else
+	while (n2bytes>n1bytes)
+	  { *sumptr-- = *n2ptr--; n2bytes--;}
+    }
+
+  /* Now add the remaining fraction part and equal size integer parts. */
+  n1bytes += n1->n_len;
+  n2bytes += n2->n_len;
+  carry = 0;
+  while ((n1bytes > 0) && (n2bytes > 0))
+    {
+      *sumptr = *n1ptr-- + *n2ptr-- + carry;
+      if (*sumptr > 9)
+	{
+	   carry = 1;
+	   *sumptr -= 10;
+	}
+      else
+	carry = 0;
+      sumptr--;
+      n1bytes--;
+      n2bytes--;
+    }
+
+  /* Now add carry the longer integer part. */
+  if (n1bytes == 0)
+    { n1bytes = n2bytes; n1ptr = n2ptr; }
+  while (n1bytes-- > 0)
+    {
+      *sumptr = *n1ptr-- + carry;
+      if (*sumptr > 9)
+	{
+	   carry = 1;
+	   *sumptr -= 10;
+	 }
+      else
+	carry = 0;
+      sumptr--;
+    }
+
+  /* Set final carry. */
+  if (carry == 1)
+    *sumptr += 1;
+  
+  /* Adjust sum and return. */
+  _rm_leading_zeros (sum);
+  return sum;  
+}
+
+
+/* Perform subtraction: N2 is subtracted from N1 and the value is
+   returned.  The signs of N1 and N2 are ignored.  Also, N1 is
+   assumed to be larger than N2.  */
+
+static bc_num
+_do_sub (n1, n2)
+     bc_num n1, n2;
+{
+  bc_num diff;
+  int diff_scale, diff_len;
+  int min_scale, min_len;
+  char *n1ptr, *n2ptr, *diffptr;
+  int borrow, count, val;
+
+  /* Allocate temporary storage. */
+  diff_len = MAX (n1->n_len, n2->n_len);
+  diff_scale = MAX (n1->n_scale, n2->n_scale);
+  min_len = MIN  (n1->n_len, n2->n_len);
+  min_scale = MIN (n1->n_scale, n2->n_scale);
+  diff = new_num (diff_len, diff_scale);
+
+  /* Initialize the subtract. */
+  n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale -1);
+  n2ptr = (char *) (n2->n_value + n2->n_len + n2->n_scale -1);
+  diffptr = (char *) (diff->n_value + diff_len + diff_scale -1);
+
+  /* Subtract the numbers. */
+  borrow = 0;
+  
+  /* Take care of the longer scaled number. */
+  if (n1->n_scale != min_scale)
+    {
+      /* n1 has the longer scale */
+      for (count = n1->n_scale - min_scale; count > 0; count--)
+	*diffptr-- = *n1ptr--;
+    }
+  else
+    {
+      /* n2 has the longer scale */
+      for (count = n2->n_scale - min_scale; count > 0; count--)
+	{
+	  val = - *n2ptr-- - borrow;
+	  if (val < 0)
+	    {
+	      val += 10;
+	      borrow = 1;
+	    }
+	  else
+	    borrow = 0;
+	  *diffptr-- = val;
+	}
+    }
+  
+  /* Now do the equal length scale and integer parts. */
+  
+  for (count = 0; count < min_len + min_scale; count++)
+    {
+      val = *n1ptr-- - *n2ptr-- - borrow;
+      if (val < 0)
+	{
+	  val += 10;
+	  borrow = 1;
+	}
+      else
+	borrow = 0;
+      *diffptr-- = val;
+    }
+
+  /* If n1 has more digits then n2, we now do that subtract. */
+  if (diff_len != min_len)
+    {
+      for (count = diff_len - min_len; count > 0; count--)
+	{
+	  val = *n1ptr-- - borrow;
+	  if (val < 0)
+	    {
+	      val += 10;
+	      borrow = 1;
+	    }
+	  else
+	    borrow = 0;
+	  *diffptr-- = val;
+	}
+    }
+
+  /* Clean up and return. */
+  _rm_leading_zeros (diff);
+  return diff;
+}
+
+
+/* Here is the full add routine that takes care of negative numbers.
+   N1 is added to N2 and the result placed into RESULT. */
+
+void
+bc_add ( n1, n2, result)
+     bc_num n1, n2, *result;
+{
+  bc_num sum;
+  int cmp_res;
+
+  if (n1->n_sign == n2->n_sign)
+    {
+      sum = _do_add (n1, n2);
+      sum->n_sign = n1->n_sign;
+    }
+  else
+    {
+      /* subtraction must be done. */
+      cmp_res = _do_compare (n1, n2, FALSE, FALSE);  /* Compare magnitudes. */
+      switch (cmp_res)
+	{
+	case -1:
+	  /* n1 is less than n2, subtract n1 from n2. */
+	  sum = _do_sub (n2, n1);
+	  sum->n_sign = n2->n_sign;
+	  break;
+	case  0:
+	  /* They are equal! return zero! */
+	  sum = copy_num (_zero_);   
+	  break;
+	case  1:
+	  /* n2 is less than n1, subtract n2 from n1. */
+	  sum = _do_sub (n1, n2);
+	  sum->n_sign = n1->n_sign;
+	}
+    }
+
+  /* Clean up and return. */
+  free_num (result);
+  *result = sum;
+}
+
+
+/* Here is the full subtract routine that takes care of negative numbers.
+   N2 is subtracted from N1 and the result placed in RESULT. */
+
+void
+bc_sub ( n1, n2, result)
+     bc_num n1, n2, *result;
+{
+  bc_num diff;
+  int cmp_res;
+
+  if (n1->n_sign != n2->n_sign)
+    {
+      diff = _do_add (n1, n2);
+      diff->n_sign = n1->n_sign;
+    }
+  else
+    {
+      /* subtraction must be done. */
+      cmp_res = _do_compare (n1, n2, FALSE, FALSE);  /* Compare magnitudes. */
+      switch (cmp_res)
+	{
+	case -1:
+	  /* n1 is less than n2, subtract n1 from n2. */
+	  diff = _do_sub (n2, n1);
+	  diff->n_sign = (n2->n_sign == PLUS ? MINUS : PLUS);
+	  break;
+	case  0:
+	  /* They are equal! return zero! */
+	  diff = copy_num (_zero_);   
+	  break;
+	case  1:
+	  /* n2 is less than n1, subtract n2 from n1. */
+	  diff = _do_sub (n1, n2);
+	  diff->n_sign = n1->n_sign;
+	  break;
+	}
+    }
+  
+  /* Clean up and return. */
+  free_num (result);
+  *result = diff;
+}
+
+
+/* The multiply routine.  N2 time N1 is put int PROD with the scale of
+   the result being MIN(N2 scale+N1 scale, MAX (SCALE, N2 scale, N1 scale)).
+   */
+
+void
+bc_multiply (n1, n2, prod, scale)
+     bc_num n1, n2, *prod;
+     int scale;
+{
+  bc_num pval;			/* For the working storage. */
+  char *n1ptr, *n2ptr, *pvptr;	/* Work pointers. */
+  char *n1end, *n2end;		/* To the end of n1 and n2. */
+
+  int indx;
+  int len1, len2, total_digits;
+  long sum;
+  int full_scale, prod_scale;
+  int toss;
+
+  /* Initialize things. */
+  len1 = n1->n_len + n1->n_scale;
+  len2 = n2->n_len + n2->n_scale;
+  total_digits = len1 + len2;
+  full_scale = n1->n_scale + n2->n_scale;
+  prod_scale = MIN(full_scale,MAX(scale,MAX(n1->n_scale,n2->n_scale)));
+  toss = full_scale - prod_scale;
+  pval =  new_num (total_digits-full_scale, prod_scale);
+  pval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS );
+  n1end = (char *) (n1->n_value + len1 - 1);
+  n2end = (char *) (n2->n_value + len2 - 1);
+  pvptr = (char *) (pval->n_value + total_digits - toss - 1);
+  sum = 0;
+
+  /* Here are the loops... */
+  for (indx = 0; indx < toss; indx++)
+    {
+      n1ptr = (char *) (n1end - MAX(0, indx-len2+1));
+      n2ptr = (char *) (n2end - MIN(indx, len2-1));
+      while ((n1ptr >= n1->n_value) && (n2ptr <= n2end))
+	sum += *n1ptr-- * *n2ptr++;
+      sum = sum / 10;
+    }
+  for ( ; indx < total_digits-1; indx++)
+    {
+      n1ptr = (char *) (n1end - MAX(0, indx-len2+1));
+      n2ptr = (char *) (n2end - MIN(indx, len2-1));
+      while ((n1ptr >= n1->n_value) && (n2ptr <= n2end))
+	sum += *n1ptr-- * *n2ptr++;
+      *pvptr-- = sum % 10;
+      sum = sum / 10;
+    }
+  *pvptr-- = sum;
+
+  /* Assign to prod and clean up the number. */
+  free_num (prod);
+  *prod = pval;
+  _rm_leading_zeros (*prod);
+  if (is_zero (*prod)) 
+    (*prod)->n_sign = PLUS;
+}
+
+
+/* Some utility routines for the divide:  First a one digit multiply.
+   NUM (with SIZE digits) is multiplied by DIGIT and the result is
+   placed into RESULT.  It is written so that NUM and RESULT can be
+   the same pointers.  */
+
+static void
+_one_mult (num, size, digit, result)
+     unsigned char *num;
+     int size, digit;
+     unsigned char *result;
+{
+  int carry, value;
+  unsigned char *nptr, *rptr;
+
+  if (digit == 0)
+    memset (result, 0, size);
+  else
+    {
+      if (digit == 1)
+	memcpy (result, num, size);
+      else
+	{
+	  /* Initialize */
+	  nptr = (unsigned char *) (num+size-1);
+	  rptr = (unsigned char *) (result+size-1);
+	  carry = 0;
+
+	  while (size-- > 0)
+	    {
+	      value = *nptr-- * digit + carry;
+	      *rptr-- = value % 10;
+	      carry = value / 10;
+	    }
+  
+	  if (carry != 0) *rptr = carry;
+	}
+    }
+}
+
+
+/* The full division routine. This computes N1 / N2.  It returns
+   0 if the division is ok and the result is in QUOT.  The number of
+   digits after the decimal point is SCALE. It returns -1 if division
+   by zero is tried.  The algorithm is found in Knuth Vol 2. p237. */
+
+int
+bc_divide (n1, n2, quot, scale)
+     bc_num n1, n2, *quot;
+     int scale;
+{ 
+  bc_num qval;
+  unsigned char *num1, *num2;
+  unsigned char *ptr1, *ptr2, *n2ptr, *qptr;
+  int  scale1, val;
+  unsigned int  len1, len2, scale2, qdigits, extra, count;
+  unsigned int  qdig, qguess, borrow, carry;
+  unsigned char *mval;
+  char zero;
+  unsigned int  norm;
+
+  /* Test for divide by zero. */
+  if (is_zero (n2)) return -1;
+
+  /* Test for divide by 1.  If it is we must truncate. */
+  if (n2->n_scale == 0)
+    {
+      if (n2->n_len == 1 && *n2->n_value == 1)
+	{
+	  qval = new_num (n1->n_len, scale);
+	  qval->n_sign = (n1->n_sign == n2->n_sign ? PLUS : MINUS);
+	  memset (&qval->n_value[n1->n_len],0,scale);
+	  memcpy (qval->n_value, n1->n_value,
+		  n1->n_len + MIN(n1->n_scale,scale));
+	  free_num (quot);
+	  *quot = qval;
+	}
+    }
+  
+  /* Set up the divide.  Move the decimal point on n1 by n2's scale.
+     Remember, zeros on the end of num2 are wasted effort for dividing. */
+  scale2 = n2->n_scale;
+  n2ptr = (unsigned char *) n2->n_value+n2->n_len+scale2-1;
+  while ((scale2 > 0) && (*n2ptr-- == 0)) scale2--;
+
+  len1 = n1->n_len + scale2;
+  scale1 = n1->n_scale - scale2;
+  if (scale1 < scale)
+    extra = scale - scale1;
+  else
+    extra = 0;
+  num1 = (unsigned char *) malloc (n1->n_len+n1->n_scale+extra+2);
+  if (num1 == NULL) out_of_memory();
+  memset (num1, 0, n1->n_len+n1->n_scale+extra+2);
+  memcpy (num1+1, n1->n_value, n1->n_len+n1->n_scale);
+
+  len2 = n2->n_len + scale2;
+  num2 = (unsigned char *) malloc (len2+1);
+  if (num2 == NULL) out_of_memory();
+  memcpy (num2, n2->n_value, len2);
+  *(num2+len2) = 0;
+  n2ptr = num2;
+  while (*n2ptr == 0)
+    {
+      n2ptr++;
+      len2--;
+    }
+
+  /* Calculate the number of quotient digits. */
+  if (len2 > len1+scale)
+    {
+      qdigits = scale+1;
+      zero = TRUE;
+    }
+  else
+    {
+      zero = FALSE;
+      if (len2>len1)
+	qdigits = scale+1;  	/* One for the zero integer part. */
+      else
+	qdigits = len1-len2+scale+1;
+    }
+
+  /* Allocate and zero the storage for the quotient. */
+  qval = new_num (qdigits-scale,scale);
+  memset (qval->n_value, 0, qdigits);
+
+  /* Allocate storage for the temporary storage mval. */
+  mval = (unsigned char *) malloc (len2+1);
+  if (mval == NULL) out_of_memory ();
+
+  /* Now for the full divide algorithm. */
+  if (!zero)
+    {
+      /* Normalize */
+      norm =  10 / ((int)*n2ptr + 1);
+      if (norm != 1)
+	{
+	  _one_mult (num1, len1+scale1+extra+1, norm, num1);
+	  _one_mult (n2ptr, len2, norm, n2ptr);
+	}
+
+      /* Initialize divide loop. */
+      qdig = 0;
+      if (len2 > len1)
+	qptr = (unsigned char *) qval->n_value+len2-len1;
+      else
+	qptr = (unsigned char *) qval->n_value;
+
+      /* Loop */
+      while (qdig <= len1+scale-len2)
+	{
+	  /* Calculate the quotient digit guess. */
+	  if (*n2ptr == num1[qdig])
+	    qguess = 9;
+	  else
+	    qguess = (num1[qdig]*10 + num1[qdig+1]) / *n2ptr;
+
+	  /* Test qguess. */
+	  if (n2ptr[1]*qguess >
+	      (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10
+	       + num1[qdig+2])
+	    {
+	      qguess--;
+	      /* And again. */
+	      if (n2ptr[1]*qguess >
+		  (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10
+		  + num1[qdig+2])
+		qguess--;
+	    }
+ 
+	  /* Multiply and subtract. */
+	  borrow = 0;
+	  if (qguess != 0)
+	    {
+	      *mval = 0;
+	      _one_mult (n2ptr, len2, qguess, mval+1);
+	      ptr1 = (unsigned char *) num1+qdig+len2;
+	      ptr2 = (unsigned char *) mval+len2;
+	      for (count = 0; count < len2+1; count++)
+		{
+		  val = (int) *ptr1 - (int) *ptr2-- - borrow;
+		  if (val < 0)
+		    {
+		      val += 10;
+		      borrow = 1;
+		    }
+		  else
+		    borrow = 0;
+		  *ptr1-- = val;
+		}
+	    }
+
+	  /* Test for negative result. */
+	  if (borrow == 1)
+	    {
+	      qguess--;
+	      ptr1 = (unsigned char *) num1+qdig+len2;
+	      ptr2 = (unsigned char *) n2ptr+len2-1;
+	      carry = 0;
+	      for (count = 0; count < len2; count++)
+		{
+		  val = (int) *ptr1 + (int) *ptr2-- + carry;
+		  if (val > 9)
+		    {
+		      val -= 10;
+		      carry = 1;
+		    }
+		  else
+		    carry = 0;
+		  *ptr1-- = val;
+		}
+	      if (carry == 1) *ptr1 = (*ptr1 + 1) % 10;
+	    }
+       
+	  /* We now know the quotient digit. */
+	  *qptr++ =  qguess;
+	  qdig++;
+	}
+    }
+
+  /* Clean up and return the number. */
+  qval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS );
+  if (is_zero (qval)) qval->n_sign = PLUS;
+  _rm_leading_zeros (qval);
+  free_num (quot);
+  *quot = qval;
+
+  /* Clean up temporary storage. */
+  free (mval);
+  free (num1);
+  free (num2);
+
+  return 0;	/* Everything is OK. */
+}
+
+
+/* Modulo for numbers.  This computes NUM1 % NUM2  and puts the
+   result in RESULT.   */
+
+int
+bc_modulo (num1, num2, result, scale)
+     bc_num num1, num2, *result;
+     int scale;
+{
+  bc_num temp;
+  int rscale;
+
+  /* Check for correct numbers. */
+  if (is_zero (num2)) return -1;
+
+  /* Calculate final scale. */
+  rscale = MAX (num1->n_scale, num2->n_scale+scale);
+  init_num (&temp);
+  
+  /* Calculate it. */
+  bc_divide (num1, num2, &temp, scale);
+  bc_multiply (temp, num2, &temp, rscale);
+  bc_sub (num1, temp, result);
+  free_num (&temp);
+
+  return 0;	/* Everything is OK. */
+}
+
+
+/* Raise NUM1 to the NUM2 power.  The result is placed in RESULT.
+   Maximum exponent is LONG_MAX.  If a NUM2 is not an integer,
+   only the integer part is used.  */
+
+void
+bc_raise (num1, num2, result, scale)
+     bc_num num1, num2, *result;
+     int scale;
+{
+   bc_num temp, power;
+   long exponent;
+   int rscale;
+   char neg;
+
+   /* Check the exponent for scale digits and convert to a long. */
+   if (num2->n_scale != 0)
+     rt_warn ("non-zero scale in exponent");
+   exponent = num2long (num2);
+   if (exponent == 0 && (num2->n_len > 1 || num2->n_value[0] != 0))
+       rt_error ("exponent too large in raise");
+
+   /* Special case if exponent is a zero. */
+   if (exponent == 0)
+     {
+       free_num (result);
+       *result = copy_num (_one_);
+       return;
+     }
+
+   /* Other initializations. */
+   if (exponent < 0)
+     {
+       neg = TRUE;
+       exponent = -exponent;
+       rscale = scale;
+     }
+   else
+     {
+       neg = FALSE;
+       rscale = MIN (num1->n_scale*exponent, MAX(scale, num1->n_scale));
+     }
+   temp = copy_num (_one_);
+   power = copy_num (num1);
+
+   /* Do the calculation. */
+   while (exponent != 0)
+     {
+       if (exponent & 1 != 0) 
+	 bc_multiply (temp, power, &temp, rscale);
+       bc_multiply (power, power, &power, rscale);
+       exponent = exponent >> 1;
+     }
+   
+   /* Assign the value. */
+   if (neg)
+     {
+       bc_divide (_one_, temp, result, rscale);
+       free_num (&temp);
+     }
+   else
+     {
+       free_num (result);
+       *result = temp;
+     }
+   free_num (&power);
+}
+
+
+/* Take the square root NUM and return it in NUM with SCALE digits
+   after the decimal place. */
+
+int 
+bc_sqrt (num, scale)
+     bc_num *num;
+     int scale;
+{
+  int rscale, cmp_res, done;
+  int cscale;
+  bc_num guess, guess1, point5;
+
+  /* Initial checks. */
+  cmp_res = bc_compare (*num, _zero_);
+  if (cmp_res < 0)
+    return 0;		/* error */
+  else
+    {
+      if (cmp_res == 0)
+	{
+	  free_num (num);
+	  *num = copy_num (_zero_);
+	  return 1;
+	}
+    }
+  cmp_res = bc_compare (*num, _one_);
+  if (cmp_res == 0)
+    {
+      free_num (num);
+      *num = copy_num (_one_);
+      return 1;
+    }
+
+  /* Initialize the variables. */
+  rscale = MAX (scale, (*num)->n_scale);
+  cscale = rscale + 2;
+  init_num (&guess);
+  init_num (&guess1);
+  point5 = new_num (1,1);
+  point5->n_value[1] = 5;
+  
+  
+  /* Calculate the initial guess. */
+  if (cmp_res < 0)
+    /* The number is between 0 and 1.  Guess should start at 1. */
+    guess = copy_num (_one_);
+  else
+    {
+      /* The number is greater than 1.  Guess should start at 10^(exp/2). */
+      int2num (&guess,10);
+      int2num (&guess1,(*num)->n_len);
+      bc_multiply (guess1, point5, &guess1, rscale);
+      guess1->n_scale = 0;
+      bc_raise (guess, guess1, &guess, rscale);
+      free_num (&guess1);
+    }
+  
+  /* Find the square root using Newton's algorithm. */
+  done = FALSE;
+  while (!done)
+    {
+      free_num (&guess1);
+      guess1 = copy_num (guess);
+      bc_divide (*num,guess,&guess,cscale);
+      bc_add (guess,guess1,&guess);
+      bc_multiply (guess,point5,&guess,cscale);
+      cmp_res = _do_compare (guess,guess1,FALSE,TRUE);
+      if (cmp_res == 0) done = TRUE;
+    }
+  
+  /* Assign the number and clean up. */
+  free_num (num);
+  bc_divide (guess,_one_,num,rscale);
+  free_num (&guess);
+  free_num (&guess1);
+  free_num (&point5);
+  return 1;
+}
+
+
+/* The following routines provide output for bcd numbers package
+   using the rules of POSIX bc for output. */
+
+/* This structure is used for saving digits in the conversion process. */
+typedef struct stk_rec {
+	long  digit;
+	struct stk_rec *next;
+} stk_rec;
+
+/* The reference string for digits. */
+char ref_str[] = "0123456789ABCDEF";
+
+
+/* A special output routine for "multi-character digits."  Exactly
+   SIZE characters must be output for the value VAL.  If SPACE is
+   non-zero, we must output one space before the number.  OUT_CHAR
+   is the actual routine for writing the characters. */
+
+void
+out_long (val, size, space, out_char)
+     long val;
+     int size, space;
+#ifdef __STDC__
+     void (*out_char)(int);
+#else
+     void (*out_char)();
+#endif
+{
+  char digits[40];
+  int len, ix;
+
+  if (space) (*out_char) (' ');
+  sprintf (digits, "%ld", val);
+  len = strlen (digits);
+  while (size > len)
+    {
+      (*out_char) ('0');
+      size--;
+    }
+  for (ix=0; ix < len; ix++)
+    (*out_char) (digits[ix]);
+}
+
+/* Output of a bcd number.  NUM is written in base O_BASE using OUT_CHAR
+   as the routine to do the actual output of the characters. */
+
+void
+out_num (num, o_base, out_char)
+     bc_num num;
+     int o_base;
+#ifdef __STDC__
+     void (*out_char)(int);
+#else
+     void (*out_char)();
+#endif
+{
+  char *nptr;
+  int  index, fdigit, pre_space;
+  stk_rec *digits, *temp;
+  bc_num int_part, frac_part, base, cur_dig, t_num, max_o_digit;
+
+  /* The negative sign if needed. */
+  if (num->n_sign == MINUS) (*out_char) ('-');
+
+  /* Output the number. */
+  if (is_zero (num))
+    (*out_char) ('0');
+  else
+    if (o_base == 10)
+      {
+	/* The number is in base 10, do it the fast way. */
+	nptr = num->n_value;
+	if (num->n_len > 1 || *nptr != 0)
+	  for (index=num->n_len; index>0; index--)
+	    (*out_char) (BCD_CHAR(*nptr++));
+	else
+	  nptr++;
+	
+	/* Now the fraction. */
+	if (num->n_scale > 0)
+	  {
+	    (*out_char) ('.');
+	    for (index=0; index<num->n_scale; index++)
+	      (*out_char) (BCD_CHAR(*nptr++));
+	  }
+      }
+    else
+      {
+	/* The number is some other base. */
+	digits = NULL;
+	init_num (&int_part);
+	bc_divide (num, _one_, &int_part, 0);
+	init_num (&frac_part);
+	init_num (&cur_dig);
+	init_num (&base);
+	bc_sub (num, int_part, &frac_part);
+	int2num (&base, o_base);
+	init_num (&max_o_digit);
+	int2num (&max_o_digit, o_base-1);
+
+
+	/* Get the digits of the integer part and push them on a stack. */
+	while (!is_zero (int_part))
+	  {
+	    bc_modulo (int_part, base, &cur_dig, 0);
+	    temp = (stk_rec *) malloc (sizeof(stk_rec));
+	    if (temp == NULL) out_of_memory();
+	    temp->digit = num2long (cur_dig);
+	    temp->next = digits;
+	    digits = temp;
+	    bc_divide (int_part, base, &int_part, 0);
+	  }
+
+	/* Print the digits on the stack. */
+	if (digits != NULL)
+	  {
+	    /* Output the digits. */
+	    while (digits != NULL)
+	      {
+		temp = digits;
+		digits = digits->next;
+		if (o_base <= 16) 
+		  (*out_char) (ref_str[ (int) temp->digit]);
+		else
+		  out_long (temp->digit, max_o_digit->n_len, 1, out_char);
+		free (temp);
+	      }
+	  }
+
+	/* Get and print the digits of the fraction part. */
+	if (num->n_scale > 0)
+	  {
+	    (*out_char) ('.');
+	    pre_space = 0;
+	    t_num = copy_num (_one_);
+	    while (t_num->n_len <= num->n_scale) {
+	      bc_multiply (frac_part, base, &frac_part, num->n_scale);
+	      fdigit = num2long (frac_part);
+	      int2num (&int_part, fdigit);
+	      bc_sub (frac_part, int_part, &frac_part);
+	      if (o_base <= 16)
+		(*out_char) (ref_str[fdigit]);
+	      else {
+		out_long (fdigit, max_o_digit->n_len, pre_space, out_char);
+		pre_space = 1;
+	      }
+	      bc_multiply (t_num, base, &t_num, 0);
+	    }
+	  }
+    
+	/* Clean up. */
+	free_num (&int_part);
+	free_num (&frac_part);
+	free_num (&base);
+	free_num (&cur_dig);
+      }
+}
+
+
+#if DEBUG > 0
+
+/* Debugging procedures.  Some are just so one can call them from the
+   debugger.  */
+
+/* p_n prints the number NUM in base 10. */
+
+void
+p_n (num)
+     bc_num num;
+{
+  out_num (num, 10, out_char);
+  return 0;
+}
+
+
+/* p_b prints a character array as if it was a string of bcd digits. */
+void
+p_v (name, num, len)
+     char *name;
+     unsigned char *num;
+     int len;
+{
+  int i;
+  printf ("%s=", name);
+  for (i=0; i<len; i++) printf ("%c",BCD_CHAR(num[i]));
+  printf ("\n");
+}
+
+
+/* Convert strings to bc numbers.  Base 10 only.*/
+
+void
+str2num (num, str, scale)
+     bc_num *num;
+     char *str;
+     int scale;
+{
+  int digits, strscale;
+  char *ptr, *nptr;
+  char zero_int;
+
+  /* Prepare num. */
+  free_num (num);
+
+  /* Check for valid number and count digits. */
+  ptr = str;
+  digits = 0;
+  strscale = 0;
+  zero_int = FALSE;
+  if ( (*ptr == '+') || (*ptr == '-'))  ptr++;  /* Sign */
+  while (*ptr == '0') ptr++;			/* Skip leading zeros. */
+  while (isdigit(*ptr)) ptr++, digits++;	/* digits */
+  if (*ptr == '.') ptr++;			/* decimal point */
+  while (isdigit(*ptr)) ptr++, strscale++;	/* digits */
+  if ((*ptr != '\0') || (digits+strscale == 0))
+    {
+      *num = copy_num (_zero_);
+      return;
+    }
+
+  /* Adjust numbers and allocate storage and initialize fields. */
+  strscale = MIN(strscale, scale);
+  if (digits == 0)
+    {
+      zero_int = TRUE;
+      digits = 1;
+    }
+  *num = new_num (digits, strscale);
+
+  /* Build the whole number. */
+  ptr = str;
+  if (*ptr == '-')
+    {
+      (*num)->n_sign = MINUS;
+      ptr++;
+    }
+  else
+    {
+      (*num)->n_sign = PLUS;
+      if (*ptr == '+') ptr++;
+    }
+  while (*ptr == '0') ptr++;			/* Skip leading zeros. */
+  nptr = (*num)->n_value;
+  if (zero_int)
+    {
+      *nptr++ = 0;
+      digits = 0;
+    }
+  for (;digits > 0; digits--)
+    *nptr++ = CH_VAL(*ptr++);
+
+  
+  /* Build the fractional part. */
+  if (strscale > 0)
+    {
+      ptr++;  /* skip the decimal point! */
+      for (;strscale > 0; strscale--)
+	*nptr++ = CH_VAL(*ptr++);
+    }
+}
+
+/* Convert a numbers to a string.  Base 10 only.*/
+
+char
+*num2str (num)
+      bc_num num;
+{
+  char *str, *sptr;
+  char *nptr;
+  int  index, signch;
+
+  /* Allocate the string memory. */
+  signch = ( num->n_sign == PLUS ? 0 : 1 );  /* Number of sign chars. */
+  if (num->n_scale > 0)
+    str = (char *) malloc (num->n_len + num->n_scale + 2 + signch);
+  else
+    str = (char *) malloc (num->n_len + 1 + signch);
+  if (str == NULL) out_of_memory();
+
+  /* The negative sign if needed. */
+  sptr = str;
+  if (signch) *sptr++ = '-';
+
+  /* Load the whole number. */
+  nptr = num->n_value;
+  for (index=num->n_len; index>0; index--)
+    *sptr++ = BCD_CHAR(*nptr++);
+
+  /* Now the fraction. */
+  if (num->n_scale > 0)
+    {
+      *sptr++ = '.';
+      for (index=0; index<num->n_scale; index++)
+	*sptr++ = BCD_CHAR(*nptr++);
+    }
+
+  /* Terminate the string and return it! */
+  *sptr = '\0';
+  return (str);
+}
+#endif
Index: /trunk/minix/commands/bc/number.h
===================================================================
--- /trunk/minix/commands/bc/number.h	(revision 9)
+++ /trunk/minix/commands/bc/number.h	(revision 9)
@@ -0,0 +1,60 @@
+/* number.h: Arbitrary precision numbers header file. */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+
+typedef enum {PLUS, MINUS} sign;
+
+typedef struct
+    {
+      sign n_sign;
+      int  n_len;	/* The number of digits before the decimal point. */
+      int  n_scale;	/* The number of digits after the decimal point. */
+      int  n_refs;      /* The number of pointers to this number. */
+      char n_value[1];  /* The storage. Not zero char terminated. It is 
+      			   allocated with all other fields.  */
+    } bc_struct;
+
+typedef bc_struct *bc_num;
+
+/*  Some useful macros and constants. */
+
+#define CH_VAL(c)     (c - '0')
+#define BCD_CHAR(d)   (d + '0')
+
+#ifdef MIN
+#undef MIN
+#undef MAX
+#endif
+#define MAX(a,b)      (a>b?a:b)
+#define MIN(a,b)      (a>b?b:a)
+#define ODD(a)        (a&1)
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
Index: /trunk/minix/commands/bc/proto.h
===================================================================
--- /trunk/minix/commands/bc/proto.h	(revision 9)
+++ /trunk/minix/commands/bc/proto.h	(revision 9)
@@ -0,0 +1,162 @@
+/* proto.h: Prototype function definitions for "external" functions. */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+/* For the pc version using k&r ACK. (minix1.5 and earlier.) */
+#ifdef SHORTNAMES
+#define init_numbers i_numbers
+#define push_constant push__constant
+#define load_const in_load_const
+#define yy_get_next_buffer yyget_next_buffer
+#define yy_init_buffer yyinit_buffer
+#define yy_last_accepting_state yylast_accepting_state
+#define arglist1 arg1list
+#endif
+
+/* Include the standard library header files. */
+#ifndef NO_UNISTD
+#include <unistd.h>
+#endif
+#ifndef NO_STDLIB
+#ifdef __STDC__
+#include <stdlib.h>
+#endif
+#endif
+
+/* Define the _PROTOTYPE macro if it is needed. */
+
+#ifndef _PROTOTYPE
+#ifdef __STDC__
+#define _PROTOTYPE(func, args) func args
+#else
+#define _PROTOTYPE(func, args) func()
+#endif
+#endif
+
+/* From execute.c */
+_PROTOTYPE(void stop_execution, (int));
+_PROTOTYPE(unsigned char byte, (program_counter *pc));
+_PROTOTYPE(void execute, (void));
+_PROTOTYPE(char prog_char, (void));
+_PROTOTYPE(char input_char, (void));
+_PROTOTYPE(void push_constant, (char (*in_char)(void), int conv_base));
+_PROTOTYPE(void push_b10_const, (program_counter *pc));
+_PROTOTYPE(void assign, (int c_code));
+
+/* From util.c */
+_PROTOTYPE(char *strcopyof, (char *str));
+_PROTOTYPE(arg_list *nextarg, (arg_list *args, int val));
+_PROTOTYPE(char *arg_str, (arg_list *args, int));
+_PROTOTYPE(void free_args, (arg_list *args));
+_PROTOTYPE(void check_params, (arg_list *params, arg_list *autos));
+_PROTOTYPE(void init_gen, (void));
+_PROTOTYPE(void generate, (char *str));
+_PROTOTYPE(void run_code, (void));
+_PROTOTYPE(void out_char, (int ch));
+_PROTOTYPE(id_rec *find_id, (id_rec *tree, char *id));
+_PROTOTYPE(int insert_id_rec, (id_rec **root, id_rec *new_id));
+_PROTOTYPE(void init_tree, (void));
+_PROTOTYPE(int lookup, (char *name, int namekind));
+_PROTOTYPE(char *bc_malloc, (int));
+_PROTOTYPE(void out_of_memory, (void));
+_PROTOTYPE(void welcome, (void));
+_PROTOTYPE(void warranty, (char *));
+_PROTOTYPE(void limits, (void));
+_PROTOTYPE(void yyerror, (char *str ,...));
+_PROTOTYPE(void warn, (char *mesg ,...));
+_PROTOTYPE(void rt_error, (char *mesg ,...));
+_PROTOTYPE(void rt_warn, (char *mesg ,...));
+
+/* From load.c */
+_PROTOTYPE(void init_load, (void));
+_PROTOTYPE(void addbyte, (int byte));
+_PROTOTYPE(void def_label, (long lab));
+_PROTOTYPE(long long_val, (char **str));
+_PROTOTYPE(void load_code, (char *code));
+
+/* From main.c */
+_PROTOTYPE(int main, (int argc , char *argv []));
+_PROTOTYPE(int open_new_file, (void));
+_PROTOTYPE(void new_yy_file, (FILE *file));
+_PROTOTYPE(void use_quit, (int));
+
+/* From number.c */
+_PROTOTYPE(void free_num, (bc_num *num));
+_PROTOTYPE(bc_num new_num, (int length, int scale));
+_PROTOTYPE(void init_numbers, (void));
+_PROTOTYPE(bc_num copy_num, (bc_num num));
+_PROTOTYPE(void init_num, (bc_num *num));
+_PROTOTYPE(void str2num, (bc_num *num, char *str, int scale));
+_PROTOTYPE(char *num2str, (bc_num num));
+_PROTOTYPE(void int2num, (bc_num *num, int val));
+_PROTOTYPE(long num2long, (bc_num num));
+_PROTOTYPE(int bc_compare, (bc_num n1, bc_num n2));
+_PROTOTYPE(char is_zero, (bc_num num));
+_PROTOTYPE(char is_neg, (bc_num num));
+_PROTOTYPE(void bc_add, (bc_num n1, bc_num n2, bc_num *result));
+_PROTOTYPE(void bc_sub, (bc_num n1, bc_num n2, bc_num *result));
+_PROTOTYPE(void bc_multiply, (bc_num n1, bc_num n2, bc_num *prod, int scale));
+_PROTOTYPE(int bc_divide, (bc_num n1, bc_num n2, bc_num *quot, int scale));
+_PROTOTYPE(int bc_modulo, (bc_num num1, bc_num num2, bc_num *result, int scale));
+_PROTOTYPE(void bc_raise, (bc_num num1, bc_num num2, bc_num *result, int scale));
+_PROTOTYPE(int bc_sqrt, (bc_num *num, int scale));
+_PROTOTYPE(void out_long, (long val, int size, int space,
+			   void (*out_char)(int)));
+_PROTOTYPE(void out_num, (bc_num num, int o_base, void (* out_char)(int)));
+
+
+/* From storage.c */
+_PROTOTYPE(void init_storage, (void));
+_PROTOTYPE(void more_functions, (void));
+_PROTOTYPE(void more_variables, (void));
+_PROTOTYPE(void more_arrays, (void));
+_PROTOTYPE(void clear_func, (int func ));
+_PROTOTYPE(int fpop, (void));
+_PROTOTYPE(void fpush, (int val ));
+_PROTOTYPE(void pop, (void));
+_PROTOTYPE(void push_copy, (bc_num num ));
+_PROTOTYPE(void push_num, (bc_num num ));
+_PROTOTYPE(char check_stack, (int depth ));
+_PROTOTYPE(bc_var *get_var, (int var_name ));
+_PROTOTYPE(bc_num *get_array_num, (int var_index, long index ));
+_PROTOTYPE(void store_var, (int var_name ));
+_PROTOTYPE(void store_array, (int var_name ));
+_PROTOTYPE(void load_var, (int var_name ));
+_PROTOTYPE(void load_array, (int var_name ));
+_PROTOTYPE(void decr_var, (int var_name ));
+_PROTOTYPE(void decr_array, (int var_name ));
+_PROTOTYPE(void incr_var, (int var_name ));
+_PROTOTYPE(void incr_array, (int var_name ));
+_PROTOTYPE(void auto_var, (int name ));
+_PROTOTYPE(void free_a_tree, (bc_array_node *root, int depth ));
+_PROTOTYPE(void pop_vars, (arg_list *list ));
+_PROTOTYPE(void process_params, (program_counter *pc, int func ));
+
+/* For the scanner and parser.... */
+_PROTOTYPE(int yyparse, (void));
+_PROTOTYPE(int yylex, (void)); 
+
Index: /trunk/minix/commands/bc/sbc.y
===================================================================
--- /trunk/minix/commands/bc/sbc.y	(revision 9)
+++ /trunk/minix/commands/bc/sbc.y	(revision 9)
@@ -0,0 +1,448 @@
+, %{
+/* sbc.y: A POSIX bc processor written for minix with no extensions.  */
+ 
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include "global.h"     /* To get the global variables. */
+#include "proto.h"
+%}
+
+%start program
+
+%union {
+	char *s_value;
+	char  c_value;
+	int   i_value;
+	arg_list *a_value;
+       }
+
+%token <i_value> NEWLINE AND OR NOT
+%token <s_value> STRING NAME NUMBER
+/*     '-', '+' are tokens themselves		*/
+%token <c_value> MUL_OP
+/*     '*', '/', '%' 				*/
+%token <c_value> ASSIGN_OP
+/*     '=', '+=',  '-=', '*=', '/=', '%=', '^=' */
+%token <s_value> REL_OP
+/*     '==', '<=', '>=', '!=', '<', '>' 	*/
+%token <c_value> INCR_DECR
+/*     '++', '--' 				*/
+%token <i_value> Define    Break    Quit    Length
+/*     'define', 'break', 'quit', 'length' 	*/
+%token <i_value> Return    For    If    While    Sqrt  Else
+/*     'return', 'for', 'if', 'while', 'sqrt',  'else' 	*/
+%token <i_value> Scale    Ibase    Obase    Auto  Read
+/*     'scale', 'ibase', 'obase', 'auto', 'read' 	*/
+%token <i_value> Warranty, Halt, Last, Continue, Print, Limits
+/*     'warranty', 'halt', 'last', 'continue', 'print', 'limits'  */
+
+/* The types of all other non-terminals. */
+%type <i_value> expression named_expression return_expression
+%type <a_value> opt_parameter_list parameter_list opt_auto_define_list
+%type <a_value> define_list opt_argument_list argument_list
+%type <i_value> program input_item semicolon_list statement_list
+%type <i_value> statement_or_error statement function relational_expression 
+
+/* precedence */
+%nonassoc REL_OP
+%right ASSIGN_OP
+%left '+' '-'
+%left MUL_OP
+%right '^'
+%nonassoc UNARY_MINUS
+%nonassoc INCR_DECR
+
+%%
+program			: /* empty */
+			    {
+			      $$ = 0;
+			      std_only = TRUE;
+			      if (interactive)
+				{
+				  printf ("s%s\n", BC_VERSION);
+				  welcome();
+				}
+			    }
+			| program input_item
+			;
+input_item		: semicolon_list NEWLINE
+			    { run_code(); }
+			| function
+			    { run_code(); }
+			| error NEWLINE
+			    {
+			      yyerrok; 
+			      init_gen() ;
+			    }
+			;
+semicolon_list		: /* empty */
+			    { $$ = 0; }
+			| statement_or_error
+			| semicolon_list ';' statement_or_error
+			| semicolon_list ';'
+			;
+statement_list		: /* empty */
+			    { $$ = 0; }
+			| statement
+			| statement_list NEWLINE
+			| statement_list NEWLINE statement
+			| statement_list ';'
+			| statement_list ';' statement
+			;
+statement_or_error	: statement
+			| error statement
+			    { $$ = $2; }
+			;
+statement 		: Warranty
+			    { warranty("s"); }
+			| expression
+			    {
+			      if ($1 & 1)
+				generate ("W");
+			      else
+				generate ("p");
+			    }
+			| STRING
+			    {
+			      $$ = 0;
+			      generate ("w");
+			      generate ($1);
+			      free ($1);
+			    }
+			| Break
+			    {
+			      if (break_label == 0)
+				yyerror ("Break outside a for/while");
+			      else
+				{
+				  sprintf (genstr, "J%1d:", break_label);
+				  generate (genstr);
+				}
+			    }
+			| Quit
+			    { exit(0); }
+			| Return
+			    { generate ("0R"); }
+			| Return '(' return_expression ')'
+			    { generate ("R"); }
+			| For 
+			    {
+			      $1 = break_label; 
+			      break_label = next_label++;
+			    }
+			  '(' expression ';'
+			    {
+			      $4 = next_label++;
+			      sprintf (genstr, "pN%1d:", $4);
+			      generate (genstr);
+			    }
+			  relational_expression ';'
+			    {
+			      $7 = next_label++;
+			      sprintf (genstr, "B%1d:J%1d:", $7, break_label);
+			      generate (genstr);
+			      $<i_value>$ = next_label++;
+			      sprintf (genstr, "N%1d:", $<i_value>$);
+			      generate (genstr);
+			    }
+			  expression ')'
+			    {
+			      sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
+			      generate (genstr);
+			    }
+			  statement
+			    {
+			      sprintf (genstr, "J%1d:N%1d:", $<i_value>9,
+				       break_label);
+			      generate (genstr);
+			      break_label = $1;
+			    }
+			| If '(' relational_expression ')' 
+			    {
+			      $3 = next_label++;
+			      sprintf (genstr, "Z%1d:", $3);
+			      generate (genstr);
+			    }
+			  statement
+			    {
+			      sprintf (genstr, "N%1d:", $3); 
+			      generate (genstr);
+			    }
+			| While 
+			    {
+			      $1 = next_label++;
+			      sprintf (genstr, "N%1d:", $1);
+			      generate (genstr);
+			    }
+			'(' relational_expression 
+			    {
+			      $4 = break_label; 
+			      break_label = next_label++;
+			      sprintf (genstr, "Z%1d:", break_label);
+			      generate (genstr);
+			    }
+			')' statement
+			    {
+			      sprintf (genstr, "J%1d:N%1d:", $1, break_label);
+			      generate (genstr);
+			      break_label = $4;
+			    }
+			| '{' statement_list '}'
+			    { $$ = 0; }
+			;
+function 		: Define NAME '(' opt_parameter_list ')' '{'
+       			  NEWLINE opt_auto_define_list 
+			    {
+			      check_params ($4,$8);
+			      sprintf (genstr, "F%d,%s.%s[", lookup($2,FUNCT),
+				       arg_str ($4,TRUE), arg_str ($8,TRUE));
+			      generate (genstr);
+			      free_args ($4);
+			      free_args ($8);
+			      $1 = next_label;
+			      next_label = 0;
+			    }
+			  statement_list NEWLINE '}'
+			    {
+			      generate ("0R]");
+			      next_label = $1;
+			    }
+			;
+opt_parameter_list	: /* empty */ 
+			    { $$ = NULL; }
+			| parameter_list
+			;
+parameter_list 		: NAME
+			    { $$ = nextarg (NULL, lookup($1,SIMPLE)); }
+			| define_list ',' NAME
+			    { $$ = nextarg ($1, lookup($3,SIMPLE)); }
+			;
+opt_auto_define_list 	: /* empty */ 
+			    { $$ = NULL; }
+			| Auto define_list NEWLINE
+			    { $$ = $2; } 
+			| Auto define_list ';'
+			    { $$ = $2; } 
+			;
+define_list 		: NAME
+			    { $$ = nextarg (NULL, lookup($1,SIMPLE)); }
+			| NAME '[' ']'
+			    { $$ = nextarg (NULL, lookup($1,ARRAY)); }
+			| define_list ',' NAME
+			    { $$ = nextarg ($1, lookup($3,SIMPLE)); }
+			| define_list ',' NAME '[' ']'
+			    { $$ = nextarg ($1, lookup($3,ARRAY)); }
+			;
+opt_argument_list	: /* empty */
+			    { $$ = NULL; }
+			| argument_list
+			;
+argument_list 		: expression
+			    { $$ = nextarg (NULL,0); }
+			| argument_list ',' expression
+			    { $$ = nextarg ($1,0); }
+			;
+relational_expression	: expression
+			    { $$ = 0; }
+			| expression REL_OP expression
+			    {
+			      $$ = 0;
+			      switch (*($2))
+				{
+				case '=':
+				  generate ("=");
+				  break;
+				case '!':
+				  generate ("#");
+				  break;
+				case '<':
+				  if ($2[1] == '=')
+				    generate ("{");
+				  else
+				    generate ("<");
+				  break;
+				case '>':
+				  if ($2[1] == '=')
+				    generate ("}");
+				  else
+				    generate (">");
+				  break;
+				}
+			    }
+			;
+return_expression	: /* empty */
+			    {
+			      $$ = 0;
+			      generate ("0");
+			    }
+			| expression
+			;
+expression		: named_expression ASSIGN_OP 
+			    {
+			      if ($2 != '=')
+				{
+				  if ($1 < 0)
+				    sprintf (genstr, "DL%d:", -$1);
+				  else
+				    sprintf (genstr, "l%d:", $1);
+				  generate (genstr);
+				}
+			    }
+			  expression
+			    {
+			      $$ = 0;
+			      if ($2 != '=')
+				{
+				  sprintf (genstr, "%c", $2);
+				  generate (genstr);
+				}
+			      if ($1 < 0)
+				sprintf (genstr, "S%d:", -$1);
+			      else
+				sprintf (genstr, "s%d:", $1);
+			      generate (genstr);
+			    }
+			| expression '+' expression
+			    { generate ("+"); }
+			| expression '-' expression
+			    { generate ("-"); }
+			| expression MUL_OP expression
+			    {
+			      genstr[0] = $2;
+			      genstr[1] = 0;
+			      generate (genstr);
+			    }
+			| expression '^' expression
+			    { generate ("^"); }
+			| '-' expression           %prec UNARY_MINUS
+			    { generate ("n"); $$ = 1;}
+			| named_expression
+			    {
+			      $$ = 1;
+			      if ($1 < 0)
+				sprintf (genstr, "L%d:", -$1);
+			      else
+				sprintf (genstr, "l%d:", $1);
+			      generate (genstr);
+			    }
+			| NUMBER
+			    {
+			      int len = strlen($1);
+			      $$ = 1;
+			      if (len == 1 && *$1 == '0')
+				generate ("0");
+			      else
+				{
+				  if (len == 1 && *$1 == '1')
+				    generate ("1");
+				  else
+				    {
+				      generate ("K");
+				      generate ($1);
+				      generate (":");
+				    }
+				  free ($1);
+				}
+			    }
+			| '(' expression ')'
+			    { $$ = 1; }
+			| NAME '(' opt_argument_list ')'
+			    {
+			      $$ = 1;
+			      if ($3 != NULL)
+				{ 
+				  sprintf (genstr, "C%d,%s:", lookup($1,FUNCT),
+					   arg_str ($3,FALSE));
+				  free_args ($3);
+				}
+			      else
+				  sprintf (genstr, "C%d:", lookup($1,FUNCT));
+			      generate (genstr);
+			    }
+			| INCR_DECR named_expression
+			    {
+			      $$ = 1;
+			      if ($2 < 0)
+				{
+				  if ($1 == '+')
+				    sprintf (genstr, "DA%d:L%d:", -$2, -$2);
+				  else
+				    sprintf (genstr, "DM%d:L%d:", -$2, -$2);
+				}
+			      else
+				{
+				  if ($1 == '+')
+				    sprintf (genstr, "i%d:l%d:", $2, $2);
+				  else
+				    sprintf (genstr, "d%d:l%d:", $2, $2);
+				}
+			      generate (genstr);
+			    }
+			| named_expression INCR_DECR
+			    {
+			      $$ = 1;
+			      if ($1 < 0)
+				{
+				  sprintf (genstr, "DL%d:x", -$1);
+				  generate (genstr); 
+				  if ($2 == '+')
+				    sprintf (genstr, "A%d:", -$1);
+				  else
+				    sprintf (genstr, "M%d:", -$1);
+				}
+			      else
+				{
+				  sprintf (genstr, "l%d:", $1);
+				  generate (genstr);
+				  if ($2 == '+')
+				    sprintf (genstr, "i%d:", $1);
+				  else
+				    sprintf (genstr, "d%d:", $1);
+				}
+			      generate (genstr);
+			    }
+			| Length '(' expression ')'
+			    { generate ("cL"); $$ = 1;}
+			| Sqrt '(' expression ')'
+			    { generate ("cR"); $$ = 1;}
+			| Scale '(' expression ')'
+			    { generate ("cS"); $$ = 1;}
+			;
+named_expression	: NAME
+			    { $$ = lookup($1,SIMPLE); }
+			| NAME '[' expression ']'
+			    { $$ = lookup($1,ARRAY); }
+			| Ibase
+			    { $$ = 0; }
+			| Obase
+			    { $$ = 1; }
+			| Scale
+			    { $$ = 2; }
+			;
+
+%%
Index: /trunk/minix/commands/bc/scan.c
===================================================================
--- /trunk/minix/commands/bc/scan.c	(revision 9)
+++ /trunk/minix/commands/bc/scan.c	(revision 9)
@@ -0,0 +1,1369 @@
+/* A lexical scanner generated by flex */
+
+/* scanner skeleton version:
+ * $Header: /cvsup/minix/src/commands/bc/scan.c,v 1.1.1.1 2005/04/21 14:54:15 beng Exp $
+ */
+
+#define FLEX_SCANNER
+
+#include <stdio.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <osfcn.h>
+
+/* use prototypes in function declarations */
+#define YY_USE_PROTOS
+
+/* the "const" storage-class-modifier is valid */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+#ifdef __STDC__
+
+#ifdef __GNUC__
+#include <stddef.h>
+void *malloc( size_t );
+void free( void* );
+#else
+#include <stdlib.h>
+#endif	/* __GNUC__ */
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif	/* __STDC__ */
+#endif	/* ! __cplusplus */
+
+
+#ifdef __TURBOC__
+#define YY_USE_CONST
+#endif
+
+
+#ifndef YY_USE_CONST
+#define const
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+/* we can't get here if it's an ANSI C compiler, or a C++ compiler,
+ * so it's got to be a K&R compiler, and therefore there's no standard
+ * place from which to include these definitions
+ */
+char *malloc();
+int free();
+int read();
+#endif
+
+
+/* amount of stuff to slurp up with each read */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* returned upon end-of-file */
+#define YY_END_TOK 0
+
+/* copy whatever the last rule matched to the standard output */
+
+/* cast to (char *) is because for 8-bit chars, yytext is (unsigned char *) */
+/* this used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite()
+ */
+#define ECHO (void) fwrite( (char *) yytext, yyleng, 1, yyout )
+
+/* gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#define YY_INPUT(buf,result,max_size) \
+	if ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
+	    YY_FATAL_ERROR( "read() in flex scanner failed" );
+#define YY_NULL 0
+
+/* no semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#define yyterminate() return ( YY_NULL )
+
+/* report a fatal error */
+
+/* The funky do-while is used to turn this macro definition into
+ * a single C statement (which needs a semi-colon terminator).
+ * This avoids problems with code like:
+ *
+ * 	if ( something_happens )
+ *		YY_FATAL_ERROR( "oops, the something happened" );
+ *	else
+ *		everything_okay();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the YY_FATAL_ERROR() call.
+ */
+
+#define YY_FATAL_ERROR(msg) \
+	do \
+		{ \
+		(void) fputs( msg, stderr ); \
+		(void) putc( '\n', stderr ); \
+		exit( 1 ); \
+		} \
+	while ( 0 )
+
+/* default yywrap function - always treat EOF as an EOF */
+#define yywrap() 1
+
+/* enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* action number for EOF rule of a given start state */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* special action meaning "start processing a new file" */
+#define YY_NEW_FILE \
+	do \
+		{ \
+		yy_init_buffer( yy_current_buffer, yyin ); \
+		yy_load_buffer_state(); \
+		} \
+	while ( 0 )
+
+/* default declaration of generated scanner - a define so the user can
+ * easily add parameters
+ */
+#define YY_DECL int yylex YY_PROTO(( void )) 
+
+/* code executed at the end of each rule */
+#define YY_BREAK break;
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE (YY_READ_BUF_SIZE * 2) /* size of default input buffer */
+#endif
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+#define YY_CHAR unsigned char
+# line 1 "scan.l"
+#define INITIAL 0
+# line 2 "scan.l"
+/* scan.l: the (f)lex description file for the scanner. */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include "y.tab.h"
+#include "global.h"
+#include "proto.h"
+
+/* Using flex, we can ask for a smaller input buffer.  With lex, this
+   does nothing! */
+
+#ifdef SMALL_BUF
+#undef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 512
+#endif
+
+/* We want to define our own yywrap. */
+#undef yywrap
+_PROTOTYPE(int yywrap, (void));
+
+/* MINIX returns from read with < 0 if SIGINT is  encountered.
+   In flex, we can redefine YY_INPUT to the following.  In lex, this
+   does nothing! */
+#include <errno.h>
+#undef  YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	while ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
+	    if (errno != EINTR) \
+		YY_FATAL_ERROR( "read() in flex scanner failed" );
+
+# line 60 "scan.l"
+
+/* done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext
+ */
+#define YY_DO_BEFORE_ACTION \
+	yytext = yy_bp; \
+	yyleng = yy_cp - yy_bp; \
+	yy_hold_char = *yy_cp; \
+	*yy_cp = '\0'; \
+	yy_c_buf_p = yy_cp;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* return all but the first 'n' matched characters back to the input stream */
+#define yyless(n) \
+	do \
+		{ \
+		/* undo effects of setting up yytext */ \
+		*yy_cp = yy_hold_char; \
+		yy_c_buf_p = yy_cp = yy_bp + n; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, yytext )
+
+
+struct yy_buffer_state
+    {
+    FILE *yy_input_file;
+
+    YY_CHAR *yy_ch_buf;		/* input buffer */
+    YY_CHAR *yy_buf_pos;	/* current position in input buffer */
+
+    /* size of input buffer in bytes, not including room for EOB characters*/
+    int yy_buf_size;	
+
+    /* number of characters read into yy_ch_buf, not including EOB characters */
+    int yy_n_chars;
+
+    int yy_eof_status;		/* whether we've seen an EOF on this buffer */
+#define EOF_NOT_SEEN 0
+    /* "pending" happens when the EOF has been seen but there's still
+     * some text process
+     */
+#define EOF_PENDING 1
+#define EOF_DONE 2
+    };
+
+static YY_BUFFER_STATE yy_current_buffer;
+
+/* we provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state"
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed */
+static YY_CHAR yy_hold_char;
+
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+
+
+
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+#ifndef YY_USER_INIT
+#define YY_USER_INIT
+#endif
+
+extern YY_CHAR *yytext;
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+YY_CHAR *yytext;
+int yyleng;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+#define YY_END_OF_BUFFER 40
+typedef int yy_state_type;
+static const short int yy_accept[144] =
+    {   0,
+        0,    0,   40,   38,   33,   31,   25,   38,   26,   38,
+       22,   26,   22,   22,   38,   26,   37,   29,   27,   29,
+       38,   22,   35,   35,   35,   35,   35,   35,   35,   35,
+       35,   35,   35,   35,   35,   35,   35,   35,   38,   33,
+       29,    0,   36,   27,   23,   30,   37,    0,   34,   37,
+       37,    0,   28,   32,   35,   35,   35,   35,   35,   35,
+       35,   35,   35,    7,   35,   35,   35,   35,   35,   35,
+       35,   35,   35,   35,   35,   24,   37,    0,    0,   37,
+        0,   35,   35,   35,   35,   35,    6,   35,   35,   35,
+       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
+
+       35,   13,   35,   35,   35,   14,   16,   35,   17,   35,
+       35,   35,   35,    3,   15,   35,   35,    9,   35,   35,
+        2,   35,   35,   11,   35,   35,   12,   20,   35,   10,
+       35,    8,   35,    1,    4,   21,    5,   35,   35,   35,
+       19,   18,    0
+    } ;
+
+static const YY_CHAR yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    4,    5,    1,    1,    6,    7,    1,    8,
+        9,   10,   11,   12,   13,   14,   15,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,    1,   17,   18,
+       19,   20,    1,    1,   21,   21,   21,   21,   21,   21,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+       22,   23,   24,   25,   26,    1,   27,   28,   29,   30,
+
+       31,   32,   33,   34,   35,   36,   37,   38,   39,   40,
+       41,   42,   43,   44,   45,   46,   47,   36,   48,   36,
+       49,   36,   50,   51,   52,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static const YY_CHAR yy_meta[53] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    2,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    2,    2,    2,    2,    2,
+        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+        2,    2,    2,    2,    2,    2,    2,    2,    2,    1,
+        1,    1
+    } ;
+
+static const short int yy_base[146] =
+    {   0,
+        0,    0,  193,  194,  190,  194,  172,  185,  170,  181,
+      194,  168,   42,   41,   41,   46,   52,  167,   61,  166,
+      181,  164,  135,  137,  139,  148,  140,  136,    0,  149,
+       27,   50,  147,  130,  126,  141,   40,   36,  120,  168,
+      194,  164,  194,  194,  194,  194,   66,  165,  194,   72,
+       76,  164,  194,  194,    0,  120,  134,  124,  131,  117,
+      117,  122,  132,    0,  113,  117,  117,  128,  119,  118,
+       52,  125,  107,  106,  114,  194,   80,  145,   84,   88,
+      144,  105,  118,   98,  108,  111,    0,   95,   95,   93,
+      105,  102,   91,   95,   88,  103,   85,   93,   84,   85,
+
+       90,    0,   90,   91,   85,    0,    0,   93,    0,   77,
+       76,   90,   74,    0,    0,   75,   87,    0,   90,   85,
+        0,   75,   83,    0,   76,   63,    0,    0,   66,    0,
+       62,    0,   47,    0,    0,    0,    0,   45,   53,   29,
+        0,    0,  194,  111,   56
+    } ;
+
+static const short int yy_def[146] =
+    {   0,
+      143,    1,  143,  143,  143,  143,  143,  144,  143,  143,
+      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  143,  143,
+      143,  144,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  143,  143,  143,  143,  143,
+      143,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,    0,  143,  143
+    } ;
+
+static const short int yy_nxt[247] =
+    {   0,
+        4,    5,    6,    7,    8,    9,   10,   11,   11,   12,
+       13,   11,   14,   15,   16,   17,   11,   18,   19,   20,
+       17,   11,   21,   11,   22,    4,   23,   24,   25,   26,
+       27,   28,   29,   30,   31,   29,   29,   32,   29,   29,
+       33,   34,   35,   36,   37,   29,   29,   38,   29,   11,
+       39,   11,   46,   46,   63,   49,   47,   55,   64,   44,
+       44,   47,   74,   48,   44,   50,   53,   51,   72,   75,
+       53,   53,   51,   53,   52,   53,   65,  142,   96,   41,
+       66,   77,   73,  141,   67,   53,   77,   80,   78,   50,
+      140,   51,   80,  139,   81,   77,   51,   97,   52,   47,
+
+       77,  138,   78,   80,   47,  137,   48,  136,   80,  135,
+       81,   42,   42,  134,  133,  132,  131,  130,  129,  128,
+      127,  126,  125,  124,  123,  122,  121,  120,  119,  118,
+      117,  116,  115,  114,  113,  112,  111,  110,  109,  108,
+      107,  106,  105,  104,  103,  102,   80,   77,  101,  100,
+       99,   98,   95,   94,   93,   92,   91,   90,   89,   88,
+       87,   86,   85,   84,   83,   82,   51,   79,   43,   40,
+       76,   71,   70,   69,   68,   62,   61,   60,   59,   58,
+       57,   56,   44,   54,   41,   41,   44,   45,   44,   43,
+       41,   40,  143,    3,  143,  143,  143,  143,  143,  143,
+
+      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143,  143,  143
+    } ;
+
+static const short int yy_chk[247] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,   13,   14,   31,   16,   15,  145,   31,   14,
+       13,   15,   38,   15,   16,   17,   19,   17,   37,   38,
+       19,   19,   17,   19,   17,   19,   32,  140,   71,   19,
+       32,   47,   37,  139,   32,   19,   47,   50,   47,   51,
+      138,   51,   50,  133,   50,   77,   51,   71,   51,   79,
+
+       77,  131,   77,   80,   79,  129,   79,  126,   80,  125,
+       80,  144,  144,  123,  122,  120,  119,  117,  116,  113,
+      112,  111,  110,  108,  105,  104,  103,  101,  100,   99,
+       98,   97,   96,   95,   94,   93,   92,   91,   90,   89,
+       88,   86,   85,   84,   83,   82,   81,   78,   75,   74,
+       73,   72,   70,   69,   68,   67,   66,   65,   63,   62,
+       61,   60,   59,   58,   57,   56,   52,   48,   42,   40,
+       39,   36,   35,   34,   33,   30,   28,   27,   26,   25,
+       24,   23,   22,   21,   20,   18,   12,   10,    9,    8,
+        7,    5,    3,  143,  143,  143,  143,  143,  143,  143,
+
+      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143,  143,  143
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static YY_CHAR *yy_last_accepting_cpos;
+
+/* the intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+
+/* these variables are all declared out here so that section 3 code can
+ * manipulate them
+ */
+/* points to current character in buffer */
+static YY_CHAR *yy_c_buf_p = (YY_CHAR *) 0;
+static int yy_init = 1;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yyunput YY_PROTO(( YY_CHAR c, YY_CHAR *buf_ptr ));
+void yyrestart YY_PROTO(( FILE *input_file ));
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+
+#define yy_new_buffer yy_create_buffer
+
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+
+YY_DECL
+    {
+    register yy_state_type yy_current_state;
+    register YY_CHAR *yy_cp, *yy_bp;
+    register int yy_act;
+
+
+
+    if ( yy_init )
+	{
+	YY_USER_INIT;
+
+	if ( ! yy_start )
+	    yy_start = 1;	/* first start state */
+
+	if ( ! yyin )
+	    yyin = stdin;
+
+	if ( ! yyout )
+	    yyout = stdout;
+
+	if ( yy_current_buffer )
+	    yy_init_buffer( yy_current_buffer, yyin );
+	else
+	    yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+	yy_load_buffer_state();
+
+	yy_init = 0;
+	}
+
+    while ( 1 )		/* loops until end-of-file is reached */
+	{
+	yy_cp = yy_c_buf_p;
+
+	/* support of yytext */
+	*yy_cp = yy_hold_char;
+
+	/* yy_bp points to the position in yy_ch_buf of the start of the
+	 * current run.
+	 */
+	yy_bp = yy_cp;
+
+	yy_current_state = yy_start;
+yy_match:
+	do
+	    {
+	    register YY_CHAR yy_c = yy_ec[*yy_cp];
+	    if ( yy_accept[yy_current_state] )
+		{
+		yy_last_accepting_state = yy_current_state;
+		yy_last_accepting_cpos = yy_cp;
+		}
+	    while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = yy_def[yy_current_state];
+		if ( yy_current_state >= 144 )
+		    yy_c = yy_meta[yy_c];
+		}
+	    yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+	    ++yy_cp;
+	    }
+	while ( yy_base[yy_current_state] != 194 );
+
+yy_find_action:
+	yy_act = yy_accept[yy_current_state];
+
+	YY_DO_BEFORE_ACTION;
+	YY_USER_ACTION;
+
+do_action:	/* this label is used only to access EOF actions */
+
+
+	switch ( yy_act )
+	    {
+	    case 0: /* must backtrack */
+	    /* undo the effects of YY_DO_BEFORE_ACTION */
+	    *yy_cp = yy_hold_char;
+	    yy_cp = yy_last_accepting_cpos;
+	    yy_current_state = yy_last_accepting_state;
+	    goto yy_find_action;
+
+case 1:
+# line 61 "scan.l"
+return(Define);
+	YY_BREAK
+case 2:
+# line 62 "scan.l"
+return(Break);
+	YY_BREAK
+case 3:
+# line 63 "scan.l"
+return(Quit);
+	YY_BREAK
+case 4:
+# line 64 "scan.l"
+return(Length);
+	YY_BREAK
+case 5:
+# line 65 "scan.l"
+return(Return);
+	YY_BREAK
+case 6:
+# line 66 "scan.l"
+return(For);
+	YY_BREAK
+case 7:
+# line 67 "scan.l"
+return(If);
+	YY_BREAK
+case 8:
+# line 68 "scan.l"
+return(While);
+	YY_BREAK
+case 9:
+# line 69 "scan.l"
+return(Sqrt);
+	YY_BREAK
+case 10:
+# line 70 "scan.l"
+return(Scale);
+	YY_BREAK
+case 11:
+# line 71 "scan.l"
+return(Ibase);
+	YY_BREAK
+case 12:
+# line 72 "scan.l"
+return(Obase);
+	YY_BREAK
+case 13:
+# line 73 "scan.l"
+return(Auto);
+	YY_BREAK
+case 14:
+# line 74 "scan.l"
+return(Else);
+	YY_BREAK
+case 15:
+# line 75 "scan.l"
+return(Read);
+	YY_BREAK
+case 16:
+# line 76 "scan.l"
+return(Halt);
+	YY_BREAK
+case 17:
+# line 77 "scan.l"
+return(Last);
+	YY_BREAK
+case 18:
+# line 78 "scan.l"
+return(Warranty);
+	YY_BREAK
+case 19:
+# line 79 "scan.l"
+return(Continue);
+	YY_BREAK
+case 20:
+# line 80 "scan.l"
+return(Print);
+	YY_BREAK
+case 21:
+# line 81 "scan.l"
+return(Limits);
+	YY_BREAK
+case 22:
+# line 82 "scan.l"
+{ yylval.c_value = yytext[0]; 
+					      return((int)yytext[0]); }
+	YY_BREAK
+case 23:
+# line 84 "scan.l"
+{ return(AND); }
+	YY_BREAK
+case 24:
+# line 85 "scan.l"
+{ return(OR); }
+	YY_BREAK
+case 25:
+# line 86 "scan.l"
+{ return(NOT); }
+	YY_BREAK
+case 26:
+# line 87 "scan.l"
+{ yylval.c_value = yytext[0]; return(MUL_OP); }
+	YY_BREAK
+case 27:
+# line 88 "scan.l"
+{ yylval.c_value = yytext[0]; return(ASSIGN_OP); }
+	YY_BREAK
+case 28:
+# line 89 "scan.l"
+{ 
+#ifdef OLD_EQ_OP
+			 char warn_save;
+			 warn_save = warn_not_std;
+			 warn_not_std = TRUE;
+			 warn ("Old fashioned =<op>");
+			 warn_not_std = warn_save;
+			 yylval.c_value = yytext[1];
+#else
+			 yylval.c_value = '=';
+			 yyless (1);
+#endif
+			 return(ASSIGN_OP);
+		       }
+	YY_BREAK
+case 29:
+# line 103 "scan.l"
+{ yylval.s_value = strcopyof((char *) yytext);
+			 return(REL_OP); }
+	YY_BREAK
+case 30:
+# line 105 "scan.l"
+{ yylval.c_value = yytext[0]; return(INCR_DECR); }
+	YY_BREAK
+case 31:
+# line 106 "scan.l"
+{ line_no++; return(NEWLINE); }
+	YY_BREAK
+case 32:
+# line 107 "scan.l"
+{  line_no++;  /* ignore a "quoted" newline */ }
+	YY_BREAK
+case 33:
+# line 108 "scan.l"
+{ /* ignore spaces and tabs */ }
+	YY_BREAK
+case 34:
+# line 109 "scan.l"
+{
+	int c;
+
+	for (;;)
+	  {
+	    while ( ((c=input()) != '*') && (c != EOF)) 
+	      /* eat it */
+	      if (c == '\n') line_no++;
+	    if (c == '*')
+ 	      {
+		while ( (c=input()) == '*') /* eat it*/;
+		if (c == '/') break; /* at end of comment */
+		if (c == '\n') line_no++;
+	      }
+	    if (c == EOF)
+	      {
+		fprintf (stderr,"EOF encountered in a comment.\n");
+		break;
+	      }
+	  }
+      }
+	YY_BREAK
+case 35:
+# line 130 "scan.l"
+{ yylval.s_value = strcopyof((char *) yytext); return(NAME); }
+	YY_BREAK
+case 36:
+# line 131 "scan.l"
+{
+ 	      unsigned char *look;
+	      int count = 0;
+	      yylval.s_value = strcopyof((char *) yytext);
+	      for (look = yytext; *look != 0; look++)
+		{
+		  if (*look == '\n') line_no++;
+		  if (*look == '"')  count++;
+		}
+	      if (count != 2) yyerror ("NUL character in string.");
+	      return(STRING);
+	    }
+	YY_BREAK
+case 37:
+# line 143 "scan.l"
+{
+	      unsigned char *src, *dst;
+	      int len;
+	      /* remove a trailing decimal point. */
+	      len = strlen((char *) yytext);
+	      if (yytext[len-1] == '.')
+	        yytext[len-1] = 0;
+	      /* remove leading zeros. */
+	      src = yytext;
+	      dst = yytext;
+	      while (*src == '0') src++;
+	      if (*src == 0) src--;
+	      /* Copy strings removing the newlines. */
+	      while (*src != 0)
+		{
+	          if (*src == '\\')
+		    {
+		      src++; src++;
+		      line_no++;
+		    }
+		  else
+		    *dst++ = *src++;
+	        }
+	      *dst = 0;
+	      yylval.s_value = strcopyof((char *) yytext); 
+	      return(NUMBER);
+	    }
+	YY_BREAK
+case 38:
+# line 170 "scan.l"
+{
+	  if (yytext[0] < ' ')
+	    yyerror ("illegal character: ^%c",yytext[0] + '@');
+	  else
+	    if (yytext[0] > '~')
+	      yyerror ("illegal character: \\%3d", (int) yytext[0]);
+	    else
+	      yyerror ("illegal character: %s",yytext);
+	}
+	YY_BREAK
+case 39:
+# line 179 "scan.l"
+ECHO;
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+    yyterminate();
+
+	    case YY_END_OF_BUFFER:
+		{
+		/* amount of text matched not including the EOB char */
+		int yy_amount_of_matched_text = yy_cp - yytext - 1;
+
+		/* undo the effects of YY_DO_BEFORE_ACTION */
+		*yy_cp = yy_hold_char;
+
+		/* note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the end-
+		 * of-buffer state).  Contrast this with the test in yyinput().
+		 */
+		if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+		    /* this was really a NUL */
+		    {
+		    yy_state_type yy_next_state;
+
+		    yy_c_buf_p = yytext + yy_amount_of_matched_text;
+
+		    yy_current_state = yy_get_previous_state();
+
+		    /* okay, we're now positioned to make the
+		     * NUL transition.  We couldn't have
+		     * yy_get_previous_state() go ahead and do it
+		     * for us because it doesn't know how to deal
+		     * with the possibility of jamming (and we
+		     * don't want to build jamming into it because
+		     * then it will run more slowly)
+		     */
+
+		    yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+		    yy_bp = yytext + YY_MORE_ADJ;
+
+		    if ( yy_next_state )
+			{
+			/* consume the NUL */
+			yy_cp = ++yy_c_buf_p;
+			yy_current_state = yy_next_state;
+			goto yy_match;
+			}
+
+		    else
+			{
+			goto yy_find_action;
+			}
+		    }
+
+		else switch ( yy_get_next_buffer() )
+		    {
+		    case EOB_ACT_END_OF_FILE:
+			{
+			yy_did_buffer_switch_on_eof = 0;
+
+			if ( yywrap() )
+			    {
+			    /* note: because we've taken care in
+			     * yy_get_next_buffer() to have set up yytext,
+			     * we can now set up yy_c_buf_p so that if some
+			     * total hoser (like flex itself) wants
+			     * to call the scanner after we return the
+			     * YY_NULL, it'll still work - another YY_NULL
+			     * will get returned.
+			     */
+			    yy_c_buf_p = yytext + YY_MORE_ADJ;
+
+			    yy_act = YY_STATE_EOF((yy_start - 1) / 2);
+			    goto do_action;
+			    }
+
+			else
+			    {
+			    if ( ! yy_did_buffer_switch_on_eof )
+				YY_NEW_FILE;
+			    }
+			}
+			break;
+
+		    case EOB_ACT_CONTINUE_SCAN:
+			yy_c_buf_p = yytext + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state();
+
+			yy_cp = yy_c_buf_p;
+			yy_bp = yytext + YY_MORE_ADJ;
+			goto yy_match;
+
+		    case EOB_ACT_LAST_MATCH:
+			yy_c_buf_p =
+			    &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+			yy_current_state = yy_get_previous_state();
+
+			yy_cp = yy_c_buf_p;
+			yy_bp = yytext + YY_MORE_ADJ;
+			goto yy_find_action;
+		    }
+		break;
+		}
+
+	    default:
+#ifdef FLEX_DEBUG
+		printf( "action # %d\n", yy_act );
+#endif
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	    }
+	}
+    }
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * synopsis
+ *     int yy_get_next_buffer();
+ *     
+ * returns a code representing an action
+ *     EOB_ACT_LAST_MATCH - 
+ *     EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *     EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+
+    {
+    register YY_CHAR *dest = yy_current_buffer->yy_ch_buf;
+    register YY_CHAR *source = yytext - 1; /* copy prev. char, too */
+    register int number_to_move, i;
+    int ret_val;
+
+    if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+	YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+    /* try to read more data */
+
+    /* first move last chars to start of buffer */
+    number_to_move = yy_c_buf_p - yytext;
+
+    for ( i = 0; i < number_to_move; ++i )
+	*(dest++) = *(source++);
+
+    if ( yy_current_buffer->yy_eof_status != EOF_NOT_SEEN )
+	/* don't do the read, it's not guaranteed to return an EOF,
+	 * just force an EOF
+	 */
+	yy_n_chars = 0;
+
+    else
+	{
+	int num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+	if ( num_to_read > YY_READ_BUF_SIZE )
+	    num_to_read = YY_READ_BUF_SIZE;
+
+	else if ( num_to_read <= 0 )
+	    YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" );
+
+	/* read in more data */
+	YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+		  yy_n_chars, num_to_read );
+	}
+
+    if ( yy_n_chars == 0 )
+	{
+	if ( number_to_move == 1 )
+	    {
+	    ret_val = EOB_ACT_END_OF_FILE;
+	    yy_current_buffer->yy_eof_status = EOF_DONE;
+	    }
+
+	else
+	    {
+	    ret_val = EOB_ACT_LAST_MATCH;
+	    yy_current_buffer->yy_eof_status = EOF_PENDING;
+	    }
+	}
+
+    else
+	ret_val = EOB_ACT_CONTINUE_SCAN;
+
+    yy_n_chars += number_to_move;
+    yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+    yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+    /* yytext begins at the second character in yy_ch_buf; the first
+     * character is the one which preceded it before reading in the latest
+     * buffer; it needs to be kept around in case it's a newline, so
+     * yy_get_previous_state() will have with '^' rules active
+     */
+
+    yytext = &yy_current_buffer->yy_ch_buf[1];
+
+    return ( ret_val );
+    }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached
+ *
+ * synopsis
+ *     yy_state_type yy_get_previous_state();
+ */
+
+static yy_state_type yy_get_previous_state()
+
+    {
+    register yy_state_type yy_current_state;
+    register YY_CHAR *yy_cp;
+
+    yy_current_state = yy_start;
+
+    for ( yy_cp = yytext + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+	{
+	register YY_CHAR yy_c = (*yy_cp ? yy_ec[*yy_cp] : 1);
+	if ( yy_accept[yy_current_state] )
+	    {
+	    yy_last_accepting_state = yy_current_state;
+	    yy_last_accepting_cpos = yy_cp;
+	    }
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+	    {
+	    yy_current_state = yy_def[yy_current_state];
+	    if ( yy_current_state >= 144 )
+		yy_c = yy_meta[yy_c];
+	    }
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+	}
+
+    return ( yy_current_state );
+    }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *     next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( register yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+register yy_state_type yy_current_state;
+#endif
+
+    {
+    register int yy_is_jam;
+    register YY_CHAR *yy_cp = yy_c_buf_p;
+
+    register YY_CHAR yy_c = 1;
+    if ( yy_accept[yy_current_state] )
+	{
+	yy_last_accepting_state = yy_current_state;
+	yy_last_accepting_cpos = yy_cp;
+	}
+    while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+	{
+	yy_current_state = yy_def[yy_current_state];
+	if ( yy_current_state >= 144 )
+	    yy_c = yy_meta[yy_c];
+	}
+    yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+    yy_is_jam = (yy_base[yy_current_state] == 194);
+
+    return ( yy_is_jam ? 0 : yy_current_state );
+    }
+
+
+#ifdef YY_USE_PROTOS
+static void yyunput( YY_CHAR c, register YY_CHAR *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+YY_CHAR c;
+register YY_CHAR *yy_bp;
+#endif
+
+    {
+    register YY_CHAR *yy_cp = yy_c_buf_p;
+
+    /* undo effects of setting up yytext */
+    *yy_cp = yy_hold_char;
+
+    if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+	{ /* need to shift things up to make room */
+	register int number_to_move = yy_n_chars + 2; /* +2 for EOB chars */
+	register YY_CHAR *dest =
+	    &yy_current_buffer->yy_ch_buf[yy_current_buffer->yy_buf_size + 2];
+	register YY_CHAR *source =
+	    &yy_current_buffer->yy_ch_buf[number_to_move];
+
+	while ( source > yy_current_buffer->yy_ch_buf )
+	    *--dest = *--source;
+
+	yy_cp += dest - source;
+	yy_bp += dest - source;
+	yy_n_chars = yy_current_buffer->yy_buf_size;
+
+	if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+	    YY_FATAL_ERROR( "flex scanner push-back overflow" );
+	}
+
+    if ( yy_cp > yy_bp && yy_cp[-1] == '\n' )
+	yy_cp[-2] = '\n';
+
+    *--yy_cp = c;
+
+    /* note: the formal parameter *must* be called "yy_bp" for this
+     *       macro to now work correctly
+     */
+    YY_DO_BEFORE_ACTION; /* set up yytext again */
+    }
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+
+    {
+    int c;
+    YY_CHAR *yy_cp = yy_c_buf_p;
+
+    *yy_cp = yy_hold_char;
+
+    if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+	{
+	/* yy_c_buf_p now points to the character we want to return.
+	 * If this occurs *before* the EOB characters, then it's a
+	 * valid NUL; if not, then we've hit the end of the buffer.
+	 */
+	if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+	    /* this was really a NUL */
+	    *yy_c_buf_p = '\0';
+
+	else
+	    { /* need more input */
+	    yytext = yy_c_buf_p;
+	    ++yy_c_buf_p;
+
+	    switch ( yy_get_next_buffer() )
+		{
+		case EOB_ACT_END_OF_FILE:
+		    {
+		    if ( yywrap() )
+			{
+			yy_c_buf_p = yytext + YY_MORE_ADJ;
+			return ( EOF );
+			}
+
+		    YY_NEW_FILE;
+
+#ifdef __cplusplus
+		    return ( yyinput() );
+#else
+		    return ( input() );
+#endif
+		    }
+		    break;
+
+		case EOB_ACT_CONTINUE_SCAN:
+		    yy_c_buf_p = yytext + YY_MORE_ADJ;
+		    break;
+
+		case EOB_ACT_LAST_MATCH:
+#ifdef __cplusplus
+		    YY_FATAL_ERROR( "unexpected last match in yyinput()" );
+#else
+		    YY_FATAL_ERROR( "unexpected last match in input()" );
+#endif
+		}
+	    }
+	}
+
+    c = *yy_c_buf_p;
+    yy_hold_char = *++yy_c_buf_p;
+
+    return ( c );
+    }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+
+    {
+    yy_init_buffer( yy_current_buffer, input_file );
+    yy_load_buffer_state();
+    }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+
+    {
+    if ( yy_current_buffer == new_buffer )
+	return;
+
+    if ( yy_current_buffer )
+	{
+	/* flush out information for old buffer */
+	*yy_c_buf_p = yy_hold_char;
+	yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+	yy_current_buffer->yy_n_chars = yy_n_chars;
+	}
+
+    yy_current_buffer = new_buffer;
+    yy_load_buffer_state();
+
+    /* we don't actually know whether we did this switch during
+     * EOF (yywrap()) processing, but the only time this flag
+     * is looked at is after yywrap() is called, so it's safe
+     * to go ahead and always set it.
+     */
+    yy_did_buffer_switch_on_eof = 1;
+    }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+
+    {
+    yy_n_chars = yy_current_buffer->yy_n_chars;
+    yytext = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+    yyin = yy_current_buffer->yy_input_file;
+    yy_hold_char = *yy_c_buf_p;
+    }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+
+    {
+    YY_BUFFER_STATE b;
+
+    b = (YY_BUFFER_STATE) malloc( sizeof( struct yy_buffer_state ) );
+
+    if ( ! b )
+	YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+    b->yy_buf_size = size;
+
+    /* yy_ch_buf has to be 2 characters longer than the size given because
+     * we need to put in 2 end-of-buffer characters.
+     */
+    b->yy_ch_buf = (YY_CHAR *) malloc( (unsigned) (b->yy_buf_size + 2) );
+
+    if ( ! b->yy_ch_buf )
+	YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+    yy_init_buffer( b, file );
+
+    return ( b );
+    }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+    {
+    if ( b == yy_current_buffer )
+	yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+    free( (char *) b->yy_ch_buf );
+    free( (char *) b );
+    }
+
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+    {
+    b->yy_input_file = file;
+
+    /* we put in the '\n' and start reading from [1] so that an
+     * initial match-at-newline will be true.
+     */
+
+    b->yy_ch_buf[0] = '\n';
+    b->yy_n_chars = 1;
+
+    /* we always need two end-of-buffer characters.  The first causes
+     * a transition to the end-of-buffer state.  The second causes
+     * a jam in that state.
+     */
+    b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+    b->yy_ch_buf[2] = YY_END_OF_BUFFER_CHAR;
+
+    b->yy_buf_pos = &b->yy_ch_buf[1];
+
+    b->yy_eof_status = EOF_NOT_SEEN;
+    }
+# line 179 "scan.l"
+
+
+
+
+/* This is the way to get multiple files input into lex. */
+
+int
+yywrap()
+{
+  if (!open_new_file ()) return (1);	/* EOF on standard in. */
+  return (0);				/* We have more input. */
+}
Index: /trunk/minix/commands/bc/scan.l
===================================================================
--- /trunk/minix/commands/bc/scan.l	(revision 9)
+++ /trunk/minix/commands/bc/scan.l	(revision 9)
@@ -0,0 +1,190 @@
+%{
+/* scan.l: the (f)lex description file for the scanner. */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include "y.tab.h"
+#include "global.h"
+#include "proto.h"
+
+/* Using flex, we can ask for a smaller input buffer.  With lex, this
+   does nothing! */
+
+#ifdef SMALL_BUF
+#undef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 512
+#endif
+
+/* We want to define our own yywrap. */
+#undef yywrap
+_PROTOTYPE(int yywrap, (void));
+
+/* MINIX returns from read with < 0 if SIGINT is  encountered.
+   In flex, we can redefine YY_INPUT to the following.  In lex, this
+   does nothing! */
+#include <errno.h>
+#undef  YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	while ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
+	    if (errno != EINTR) \
+		YY_FATAL_ERROR( "read() in flex scanner failed" );
+
+%}
+DIGIT [0-9A-F]
+LETTER [a-z]
+%%
+define return(Define);
+break  return(Break);
+quit   return(Quit);
+length return(Length);
+return return(Return);
+for    return(For);
+if     return(If);
+while  return(While);
+sqrt   return(Sqrt);
+scale  return(Scale);
+ibase  return(Ibase);
+obase  return(Obase);
+auto   return(Auto);
+else   return(Else);
+read   return(Read);
+halt   return(Halt);
+last   return(Last);
+warranty return(Warranty);
+continue return(Continue);
+print  return(Print);
+limits return(Limits);
+"+"|"-"|";"|"("|")"|"{"|"}"|"["|"]"|","|"^" { yylval.c_value = yytext[0]; 
+					      return((int)yytext[0]); }
+&& { return(AND); }
+\|\| { return(OR); }
+"!" { return(NOT); }
+"*"|"/"|"%" { yylval.c_value = yytext[0]; return(MUL_OP); }
+"="|\+=|-=|\*=|\/=|%=|\^=  { yylval.c_value = yytext[0]; return(ASSIGN_OP); }
+=\+|=-|=\*|=\/|=%|=\^  { 
+#ifdef OLD_EQ_OP
+			 char warn_save;
+			 warn_save = warn_not_std;
+			 warn_not_std = TRUE;
+			 warn ("Old fashioned =<op>");
+			 warn_not_std = warn_save;
+			 yylval.c_value = yytext[1];
+#else
+			 yylval.c_value = '=';
+			 yyless (1);
+#endif
+			 return(ASSIGN_OP);
+		       }
+==|\<=|\>=|\!=|"<"|">" { yylval.s_value = strcopyof((char *) yytext);
+			 return(REL_OP); }
+\+\+|-- { yylval.c_value = yytext[0]; return(INCR_DECR); }
+"\n" { line_no++; return(NEWLINE); }
+\\\n {  line_no++;  /* ignore a "quoted" newline */ }
+[ \t]+  { /* ignore spaces and tabs */ }
+"/*"  {
+	int c;
+
+	for (;;)
+	  {
+	    while ( ((c=input()) != '*') && (c != EOF)) 
+	      /* eat it */
+	      if (c == '\n') line_no++;
+	    if (c == '*')
+ 	      {
+		while ( (c=input()) == '*') /* eat it*/;
+		if (c == '/') break; /* at end of comment */
+		if (c == '\n') line_no++;
+	      }
+	    if (c == EOF)
+	      {
+		fprintf (stderr,"EOF encountered in a comment.\n");
+		break;
+	      }
+	  }
+      }
+[a-z][a-z0-9_]* { yylval.s_value = strcopyof((char *) yytext); return(NAME); }
+\"[^\"]*\"  {
+ 	      unsigned char *look;
+	      int count = 0;
+	      yylval.s_value = strcopyof((char *) yytext);
+	      for (look = yytext; *look != 0; look++)
+		{
+		  if (*look == '\n') line_no++;
+		  if (*look == '"')  count++;
+		}
+	      if (count != 2) yyerror ("NUL character in string.");
+	      return(STRING);
+	    }
+{DIGIT}({DIGIT}|\\\n)*("."({DIGIT}|\\\n)*)?|"."(\\\n)*{DIGIT}({DIGIT}|\\\n)* {
+	      unsigned char *src, *dst;
+	      int len;
+	      /* remove a trailing decimal point. */
+	      len = strlen((char *) yytext);
+	      if (yytext[len-1] == '.')
+	        yytext[len-1] = 0;
+	      /* remove leading zeros. */
+	      src = yytext;
+	      dst = yytext;
+	      while (*src == '0') src++;
+	      if (*src == 0) src--;
+	      /* Copy strings removing the newlines. */
+	      while (*src != 0)
+		{
+	          if (*src == '\\')
+		    {
+		      src++; src++;
+		      line_no++;
+		    }
+		  else
+		    *dst++ = *src++;
+	        }
+	      *dst = 0;
+	      yylval.s_value = strcopyof((char *) yytext); 
+	      return(NUMBER);
+	    }
+.       {
+	  if (yytext[0] < ' ')
+	    yyerror ("illegal character: ^%c",yytext[0] + '@');
+	  else
+	    if (yytext[0] > '~')
+	      yyerror ("illegal character: \\%3d", (int) yytext[0]);
+	    else
+	      yyerror ("illegal character: %s",yytext);
+	}
+%%
+
+
+
+/* This is the way to get multiple files input into lex. */
+
+int
+yywrap()
+{
+  if (!open_new_file ()) return (1);	/* EOF on standard in. */
+  return (0);				/* We have more input. */
+}
Index: /trunk/minix/commands/bc/storage.c
===================================================================
--- /trunk/minix/commands/bc/storage.c	(revision 9)
+++ /trunk/minix/commands/bc/storage.c	(revision 9)
@@ -0,0 +1,967 @@
+/* storage.c:  Code and data storage manipulations.  This includes labels. */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include "global.h"
+#include "proto.h"
+
+
+/* Initialize the storage at the beginning of the run. */
+
+void
+init_storage ()
+{
+
+  /* Functions: we start with none and ask for more. */
+  f_count = 0;
+  more_functions ();
+  f_names[0] = "(main)";
+
+  /* Variables. */
+  v_count = 0;
+  more_variables ();
+  
+  /* Arrays. */
+  a_count = 0;
+  more_arrays ();
+
+  /* Other things... */
+  ex_stack = NULL;
+  fn_stack = NULL;
+  i_base = 10;
+  o_base = 10;
+  scale  = 0;
+  c_code = FALSE;
+  init_numbers();
+}
+
+/* Three functions for increasing the number of functions, variables, or
+   arrays that are needed.  This adds another 32 of the requested object. */
+
+void
+more_functions (VOID)
+{
+  int old_count;
+  int indx1, indx2;
+  bc_function *old_f;
+  bc_function *f;
+  char **old_names;
+
+  /* Save old information. */
+  old_count = f_count;
+  old_f = functions;
+  old_names = f_names;
+
+  /* Add a fixed amount and allocate new space. */
+  f_count += STORE_INCR;
+  functions = (bc_function *) bc_malloc (f_count*sizeof (bc_function));
+  f_names = (char **) bc_malloc (f_count*sizeof (char *));
+
+  /* Copy old ones. */
+  for (indx1 = 0; indx1 < old_count; indx1++)
+    {
+      functions[indx1] = old_f[indx1];
+      f_names[indx1] = old_names[indx1];
+    }
+
+  /* Initialize the new ones. */
+  for (; indx1 < f_count; indx1++)
+    {
+      f = &functions[indx1];
+      f->f_defined = FALSE;
+      for (indx2 = 0; indx2 < BC_MAX_SEGS; indx2++)
+	f->f_body [indx2] = NULL;
+      f->f_code_size = 0;
+      f->f_label = NULL;
+      f->f_autos = NULL;
+      f->f_params = NULL;
+    }
+
+  /* Free the old elements. */
+  if (old_count != 0)
+    {
+      free (old_f);
+      free (old_names);
+    }
+}
+
+void
+more_variables ()
+{
+  int indx;
+  int old_count;
+  bc_var **old_var;
+  char **old_names;
+
+  /* Save the old values. */
+  old_count = v_count;
+  old_var = variables;
+  old_names = v_names;
+
+  /* Increment by a fixed amount and allocate. */
+  v_count += STORE_INCR;
+  variables = (bc_var **) bc_malloc (v_count*sizeof(bc_var *));
+  v_names = (char **) bc_malloc (v_count*sizeof(char *));
+
+  /* Copy the old variables. */
+  for (indx = 3; indx < old_count; indx++)
+    variables[indx] = old_var[indx];
+
+  /* Initialize the new elements. */
+  for (; indx < v_count; indx++)
+    variables[indx] = NULL;
+
+  /* Free the old elements. */
+  if (old_count != 0)
+    {
+      free (old_var);
+      free (old_names);
+    }
+}
+
+void
+more_arrays ()
+{
+  int indx;
+  int old_count;
+  bc_var_array **old_ary;
+  char **old_names;
+
+  /* Save the old values. */
+  old_count = a_count;
+  old_ary = arrays;
+  old_names = a_names;
+
+  /* Increment by a fixed amount and allocate. */
+  a_count += STORE_INCR;
+  arrays = (bc_var_array **) bc_malloc (a_count*sizeof(bc_var_array *));
+  a_names = (char **) bc_malloc (a_count*sizeof(char *));
+
+  /* Copy the old arrays. */
+  for (indx = 1; indx < old_count; indx++)
+    arrays[indx] = old_ary[indx];
+
+
+  /* Initialize the new elements. */
+  for (; indx < v_count; indx++)
+    arrays[indx] = NULL;
+
+  /* Free the old elements. */
+  if (old_count != 0)
+    {
+      free (old_ary);
+      free (old_names);
+    }
+}
+
+
+/* clear_func clears out function FUNC and makes it ready to redefine. */
+
+void
+clear_func (func)
+     char func;
+{
+  bc_function *f;
+  int indx;
+  bc_label_group *lg;
+
+  /* Set the pointer to the function. */
+  f = &functions[func];
+  f->f_defined = FALSE;
+
+  /* Clear the code segments. */
+  for (indx = 0; indx < BC_MAX_SEGS; indx++)
+    {
+      if (f->f_body[indx] != NULL)
+	{
+	  free (f->f_body[indx]);
+	  f->f_body[indx] = NULL;
+	}
+    }
+
+  f->f_code_size = 0;
+  if (f->f_autos != NULL)
+    {
+      free_args (f->f_autos);
+      f->f_autos = NULL;
+    }
+  if (f->f_params != NULL)
+    {
+      free_args (f->f_params);
+      f->f_params = NULL;
+    }
+  while (f->f_label != NULL)
+    {
+      lg = f->f_label->l_next;
+      free (f->f_label);
+      f->f_label = lg;
+    }
+}
+
+
+/*  Pop the function execution stack and return the top. */
+
+int
+fpop()
+{
+  fstack_rec *temp;
+  int retval;
+  
+  if (fn_stack != NULL)
+    {
+      temp = fn_stack;
+      fn_stack = temp->s_next;
+      retval = temp->s_val;
+      free (temp);
+    }
+  return (retval);
+}
+
+
+/* Push VAL on to the function stack. */
+
+void
+fpush (val)
+     int val;
+{
+  fstack_rec *temp;
+  
+  temp = (fstack_rec *) bc_malloc (sizeof (fstack_rec));
+  temp->s_next = fn_stack;
+  temp->s_val = val;
+  fn_stack = temp;
+}
+
+
+/* Pop and discard the top element of the regular execution stack. */
+
+void
+pop ()
+{
+  estack_rec *temp;
+  
+  if (ex_stack != NULL)
+    {
+      temp = ex_stack;
+      ex_stack = temp->s_next;
+      free_num (&temp->s_num);
+      free (temp);
+    }
+}
+
+
+/* Push a copy of NUM on to the regular execution stack. */
+
+void
+push_copy (num)
+     bc_num num;
+{
+  estack_rec *temp;
+
+  temp = (estack_rec *) bc_malloc (sizeof (estack_rec));
+  temp->s_num = copy_num (num);
+  temp->s_next = ex_stack;
+  ex_stack = temp;
+}
+
+
+/* Push NUM on to the regular execution stack.  Do NOT push a copy. */
+
+void
+push_num (num)
+     bc_num num;
+{
+  estack_rec *temp;
+
+  temp = (estack_rec *) bc_malloc (sizeof (estack_rec));
+  temp->s_num = num;
+  temp->s_next = ex_stack;
+  ex_stack = temp;
+}
+
+
+/* Make sure the ex_stack has at least DEPTH elements on it.
+   Return TRUE if it has at least DEPTH elements, otherwise
+   return FALSE. */
+
+char
+check_stack (depth)
+     int depth;
+{
+  estack_rec *temp;
+
+  temp = ex_stack;
+  while ((temp != NULL) && (depth > 0))
+    {
+      temp = temp->s_next;
+      depth--;
+    }
+  if (depth > 0)
+    {
+      rt_error ("Stack error.");
+      return FALSE;
+    }
+  return TRUE;
+}
+
+
+/* The following routines manipulate simple variables and
+   array variables. */
+
+/* get_var returns a pointer to the variable VAR_NAME.  If one does not
+   exist, one is created. */
+
+bc_var *
+get_var (var_name)
+     int var_name;
+{
+  bc_var *var_ptr;
+
+  var_ptr = variables[var_name];
+  if (var_ptr == NULL)
+    {
+      var_ptr = variables[var_name] = (bc_var *) bc_malloc (sizeof (bc_var));
+      init_num (&var_ptr->v_value);
+    }
+  return var_ptr;
+}
+
+
+/* get_array_num returns the address of the bc_num in the array
+   structure.  If more structure is requried to get to the index,
+   this routine does the work to create that structure. VAR_INDEX
+   is a zero based index into the arrays storage array. INDEX is
+   the index into the bc array. */
+
+bc_num *
+get_array_num (var_index, index)
+     int var_index;
+     long  index;
+{
+  bc_var_array *ary_ptr;
+  bc_array *a_var;
+  bc_array_node *temp;
+  int log, ix, ix1;
+  int sub [NODE_DEPTH];
+
+  /* Get the array entry. */
+  ary_ptr = arrays[var_index];
+  if (ary_ptr == NULL)
+    {
+      ary_ptr = arrays[var_index] =
+	(bc_var_array *) bc_malloc (sizeof (bc_var_array));
+      ary_ptr->a_value = NULL;
+      ary_ptr->a_next = NULL;
+      ary_ptr->a_param = FALSE;
+    }
+
+  a_var = ary_ptr->a_value;
+  if (a_var == NULL) {
+    a_var = ary_ptr->a_value = (bc_array *) bc_malloc (sizeof (bc_array));
+    a_var->a_tree = NULL;
+    a_var->a_depth = 0;
+  }
+
+  /* Get the index variable. */
+  sub[0] = index & NODE_MASK;
+  ix = index >> NODE_SHIFT;
+  log = 1;
+  while (ix > 0 || log < a_var->a_depth)
+    {
+      sub[log] = ix & NODE_MASK;
+      ix >>= NODE_SHIFT;
+      log++;
+    }
+  
+  /* Build any tree that is necessary. */
+  while (log > a_var->a_depth)
+    {
+      temp = (bc_array_node *) bc_malloc (sizeof(bc_array_node));
+      if (a_var->a_depth != 0)
+	{
+	  temp->n_items.n_down[0] = a_var->a_tree;
+	  for (ix=1; ix < NODE_SIZE; ix++)
+	    temp->n_items.n_down[ix] = NULL;
+	}
+      else
+	{
+	  for (ix=0; ix < NODE_SIZE; ix++)
+	    temp->n_items.n_num[ix] = copy_num(_zero_);
+	}
+      a_var->a_tree = temp;
+      a_var->a_depth++;
+    }
+  
+  /* Find the indexed variable. */
+  temp = a_var->a_tree;
+  while ( log-- > 1)
+    {
+      ix1 = sub[log];
+      if (temp->n_items.n_down[ix1] == NULL)
+	{
+	  temp->n_items.n_down[ix1] =
+	    (bc_array_node *) bc_malloc (sizeof(bc_array_node));
+	  temp = temp->n_items.n_down[ix1];
+	  if (log > 1)
+	    for (ix=0; ix < NODE_SIZE; ix++)
+	      temp->n_items.n_down[ix] = NULL;
+	  else
+	    for (ix=0; ix < NODE_SIZE; ix++)
+	      temp->n_items.n_num[ix] = copy_num(_zero_);
+	}
+      else
+	temp = temp->n_items.n_down[ix1];
+    }
+  
+  /* Return the address of the indexed variable. */
+  return &(temp->n_items.n_num[sub[0]]);
+}
+
+
+/* Store the top of the execution stack into VAR_NAME.  
+   This includes the special variables ibase, obase, and scale. */
+
+void
+store_var (var_name)
+     int var_name;
+{
+  bc_var *var_ptr;
+  long temp;
+  char toobig;
+
+  if (var_name > 2)
+    {
+      /* It is a simple variable. */
+      var_ptr = get_var (var_name);
+      if (var_ptr != NULL)
+	{
+	  free_num(&var_ptr->v_value);
+	  var_ptr->v_value = copy_num (ex_stack->s_num);
+	}
+    }
+  else
+    {
+      /* It is a special variable... */
+      toobig = FALSE;
+      if (is_neg (ex_stack->s_num))
+	{
+	  switch (var_name)
+	    {
+	    case 0:
+	      rt_warn ("negative ibase, set to 2");
+	      temp = 2;
+	      break;
+	    case 1:
+	      rt_warn ("negative obase, set to 2");
+	      temp = 2;
+	      break;
+	    case 2:
+	      rt_warn ("negative scale, set to 0");
+	      temp = 0;
+	      break;
+	    }
+	}
+      else
+	{
+	  temp = num2long (ex_stack->s_num);
+	  if (!is_zero (ex_stack->s_num) && temp == 0)
+	    toobig = TRUE;
+	}
+      switch (var_name)
+	{
+	case 0:
+	  if (temp < 2 && !toobig)
+	    {
+	      i_base = 2;
+	      rt_warn ("ibase too small, set to 2");
+	    }
+	  else
+	    if (temp > 16 || toobig)
+	      {
+		i_base = 16;
+		rt_warn ("ibase too large, set to 16");
+	      }
+	    else
+	      i_base = (int) temp;
+	  break;
+
+	case 1:
+	  if (temp < 2 && !toobig)
+	    {
+	      o_base = 2;
+	      rt_warn ("obase too small, set to 2");
+	    }
+	  else
+	    if (temp > BC_BASE_MAX || toobig)
+	      {
+		o_base = BC_BASE_MAX;
+		rt_warn ("obase too large, set to %d", BC_BASE_MAX);
+	      }
+	    else
+	      o_base = (int) temp;
+	  break;
+
+	case 2:
+	  /*  WARNING:  The following if statement may generate a compiler
+	      warning if INT_MAX == LONG_MAX.  This is NOT a problem. */
+	  if (temp > BC_SCALE_MAX || toobig )
+	    {
+	      scale = BC_SCALE_MAX;
+	      rt_warn ("scale too large, set to %d", BC_SCALE_MAX);
+	    }
+	  else
+	    scale = (int) temp;
+	}
+    }
+}
+
+
+/* Store the top of the execution stack into array VAR_NAME. 
+   VAR_NAME is the name of an array, and the next to the top
+   of stack for the index into the array. */
+
+void
+store_array (var_name)
+     int var_name;
+{
+  bc_num *num_ptr;
+  long index;
+
+  if (!check_stack(2)) return;
+  index = num2long (ex_stack->s_next->s_num);
+  if (index < 0 || index > BC_DIM_MAX ||
+      (index == 0 && !is_zero(ex_stack->s_next->s_num))) 
+    rt_error ("Array %s subscript out of bounds.", a_names[var_name]);
+  else
+    {
+      num_ptr = get_array_num (var_name, index);
+      if (num_ptr != NULL)
+	{
+	  free_num (num_ptr);
+	  *num_ptr = copy_num (ex_stack->s_num);
+	  free_num (&ex_stack->s_next->s_num);
+	  ex_stack->s_next->s_num = ex_stack->s_num;
+	  init_num (&ex_stack->s_num);
+	  pop();
+	}
+    }
+}
+
+
+/*  Load a copy of VAR_NAME on to the execution stack.  This includes
+    the special variables ibase, obase and scale.  */
+
+void
+load_var (var_name)
+     int var_name;
+{
+  bc_var *var_ptr;
+
+  switch (var_name)
+    {
+
+    case 0:
+      /* Special variable ibase. */
+      push_copy (_zero_);
+      int2num (&ex_stack->s_num, i_base);
+      break;
+
+    case 1:
+      /* Special variable obase. */
+      push_copy (_zero_);
+      int2num (&ex_stack->s_num, o_base);
+      break;
+
+    case 2:
+      /* Special variable scale. */
+      push_copy (_zero_);
+      int2num (&ex_stack->s_num, scale);
+      break;
+
+    default:
+      /* It is a simple variable. */
+      var_ptr = variables[var_name];
+      if (var_ptr != NULL)
+	push_copy (var_ptr->v_value);
+      else
+	push_copy (_zero_);
+    }
+}
+
+
+/*  Load a copy of VAR_NAME on to the execution stack.  This includes
+    the special variables ibase, obase and scale.  */
+
+void
+load_array (var_name)
+     int var_name;
+{
+  bc_num *num_ptr;
+  long   index;
+
+  if (!check_stack(1)) return;
+  index = num2long (ex_stack->s_num);
+  if (index < 0 || index > BC_DIM_MAX ||
+     (index == 0 && !is_zero(ex_stack->s_num))) 
+    rt_error ("Array %s subscript out of bounds.", a_names[var_name]);
+  else
+    {
+      num_ptr = get_array_num (var_name, index);
+      if (num_ptr != NULL)
+	{
+	  pop();
+	  push_copy (*num_ptr);
+	}
+    }
+}
+
+
+/* Decrement VAR_NAME by one.  This includes the special variables
+   ibase, obase, and scale. */
+
+void
+decr_var (var_name)
+     int var_name;
+{
+  bc_var *var_ptr;
+
+  switch (var_name)
+    {
+
+    case 0: /* ibase */
+      if (i_base > 2)
+	i_base--;
+      else
+	rt_warn ("ibase too small in --");
+      break;
+      
+    case 1: /* obase */
+      if (o_base > 2)
+	o_base--;
+      else
+	rt_warn ("obase too small in --");
+      break;
+
+    case 2: /* scale */
+      if (scale > 0)
+	scale--;
+      else
+	rt_warn ("scale can not be negative in -- ");
+      break;
+
+    default: /* It is a simple variable. */
+      var_ptr = get_var (var_name);
+      if (var_ptr != NULL)
+	bc_sub (var_ptr->v_value,_one_,&var_ptr->v_value);
+    }
+}
+
+
+/* Decrement VAR_NAME by one.  VAR_NAME is an array, and the top of
+   the execution stack is the index and it is popped off the stack. */
+
+void
+decr_array (var_name)
+     char var_name;
+{
+  bc_num *num_ptr;
+  long   index;
+
+  /* It is an array variable. */
+  if (!check_stack (1)) return;
+  index = num2long (ex_stack->s_num);
+  if (index < 0 || index > BC_DIM_MAX ||
+     (index == 0 && !is_zero (ex_stack->s_num))) 
+    rt_error ("Array %s subscript out of bounds.", a_names[var_name]);
+  else
+    {
+      num_ptr = get_array_num (var_name, index);
+      if (num_ptr != NULL)
+	{
+	  pop ();
+	  bc_sub (*num_ptr, _one_, num_ptr);
+	}
+    }
+}
+
+
+/* Increment VAR_NAME by one.  This includes the special variables
+   ibase, obase, and scale. */
+
+void
+incr_var (var_name)
+     int var_name;
+{
+  bc_var *var_ptr;
+
+  switch (var_name)
+    {
+
+    case 0: /* ibase */
+      if (i_base < 16)
+	i_base++;
+      else
+	rt_warn ("ibase too big in ++");
+      break;
+
+    case 1: /* obase */
+      if (o_base < BC_BASE_MAX)
+	o_base++;
+      else
+	rt_warn ("obase too big in ++");
+      break;
+
+    case 2:
+      if (scale < BC_SCALE_MAX)
+	scale++;
+      else
+	rt_warn ("Scale too big in ++");
+      break;
+
+    default:  /* It is a simple variable. */
+      var_ptr = get_var (var_name);
+      if (var_ptr != NULL)
+	bc_add (var_ptr->v_value, _one_, &var_ptr->v_value);
+
+    }
+}
+
+
+/* Increment VAR_NAME by one.  VAR_NAME is an array and top of
+   execution stack is the index and is popped off the stack. */
+
+void
+incr_array (var_name)
+     int var_name;
+{
+  bc_num *num_ptr;
+  long   index;
+
+  if (!check_stack (1)) return;
+  index = num2long (ex_stack->s_num);
+  if (index < 0 || index > BC_DIM_MAX ||
+      (index == 0 && !is_zero (ex_stack->s_num))) 
+    rt_error ("Array %s subscript out of bounds.", a_names[var_name]);
+  else
+    {
+      num_ptr = get_array_num (var_name, index);
+      if (num_ptr != NULL)
+	{
+	  pop ();
+	  bc_add (*num_ptr, _one_, num_ptr);
+	}
+    }
+}
+
+
+/* Routines for processing autos variables and parameters. */
+
+/* NAME is an auto variable that needs to be pushed on its stack. */
+
+void
+auto_var (name)
+     int name;
+{
+  bc_var *v_temp;
+  bc_var_array *a_temp;
+  int ix;
+
+  if (name > 0)
+    {
+      /* A simple variable. */
+      ix = name;
+      v_temp = (bc_var *) bc_malloc (sizeof (bc_var));
+      v_temp->v_next = variables[ix];
+      init_num (&v_temp->v_value);
+      variables[ix] = v_temp;
+    }
+  else
+    {
+      /* An array variable. */
+      ix = -name;
+      a_temp = (bc_var_array *) bc_malloc (sizeof (bc_var_array));
+      a_temp->a_next = arrays[ix];
+      a_temp->a_value = NULL;
+      a_temp->a_param = FALSE;
+      arrays[ix] = a_temp;
+    } 
+}
+
+
+/* Free_a_tree frees everything associated with an array variable tree.
+   This is used when popping an array variable off its auto stack.  */
+
+void
+free_a_tree ( root, depth )
+     bc_array_node *root;
+     int depth;
+{
+  int ix;
+
+  if (root != NULL)
+    {
+      if (depth > 1)
+	for (ix = 0; ix < NODE_SIZE; ix++)
+	  free_a_tree (root->n_items.n_down[ix], depth-1);
+      else
+	for (ix = 0; ix < NODE_SIZE; ix++)
+	  free_num ( &(root->n_items.n_num[ix]));
+      free (root);
+    }
+}
+
+
+/* LIST is an NULL terminated list of varible names that need to be
+   popped off their auto stacks. */
+
+void
+pop_vars (list)
+     arg_list *list;
+{
+  bc_var *v_temp;
+  bc_var_array *a_temp;
+  int    ix;
+
+  while (list != NULL)
+    {
+      ix = list->av_name;
+      if (ix > 0)
+	{
+	  /* A simple variable. */
+	  v_temp = variables[ix];
+	  if (v_temp != NULL)
+	    {
+	      variables[ix] = v_temp->v_next;
+	      free_num (&v_temp->v_value);
+	      free (v_temp);
+	    }
+	}
+      else
+	{
+	  /* An array variable. */
+	  ix = -ix;
+	  a_temp = arrays[ix];
+	  if (a_temp != NULL)
+	    {
+	      arrays[ix] = a_temp->a_next;
+	      if (!a_temp->a_param && a_temp->a_value != NULL)
+		{
+		  free_a_tree (a_temp->a_value->a_tree,
+			       a_temp->a_value->a_depth);
+		  free (a_temp->a_value);
+		}
+	      free (a_temp);
+	    }
+	} 
+      list = list->next;
+    }
+}
+
+
+/* A call is being made to FUNC.  The call types are at PC.  Process
+   the parameters by doing an auto on the parameter variable and then
+   store the value at the new variable or put a pointer the the array
+   variable. */
+
+void
+process_params (pc, func)
+     program_counter *pc;
+     int func;
+{
+  char ch;
+  arg_list *params;
+  char warned = FALSE;
+  int ix, ix1;
+  bc_var *v_temp;
+  bc_var_array *a_src, *a_dest;
+  bc_num *n_temp;
+  
+  /* Get the parameter names from the function. */
+  params = functions[func].f_params;
+
+  while ((ch = byte(pc)) != ':')
+    {
+      if (params != NULL)
+	{
+	  if ((ch == '0') && params->av_name > 0)
+	    {
+	      /* A simple variable. */
+	      ix = params->av_name;
+	      v_temp = (bc_var *) bc_malloc (sizeof(bc_var));
+	      v_temp->v_next = variables[ix];
+	      v_temp->v_value = ex_stack->s_num;
+	      init_num (&ex_stack->s_num);
+	      variables[ix] = v_temp;
+	    }
+	  else
+	    if ((ch == '1') && (params->av_name < 0))
+	      {
+		/* The variables is an array variable. */
+	
+		/* Compute source index and make sure some structure exists. */
+		ix = (int) num2long (ex_stack->s_num);
+		n_temp = get_array_num (ix, 0);    
+	
+		/* Push a new array and Compute Destination index */
+		auto_var (params->av_name);  
+		ix1 = -params->av_name;
+
+		/* Set up the correct pointers in the structure. */
+		if (ix == ix1) 
+		  a_src = arrays[ix]->a_next;
+		else
+		  a_src = arrays[ix];
+		a_dest = arrays[ix1];
+		a_dest->a_param = TRUE;
+		a_dest->a_value = a_src->a_value;
+	      }
+	    else
+	      {
+		if (params->av_name < 0)
+		  rt_error ("Parameter type mismatch parameter %s.",
+			    a_names[-params->av_name]);
+		else
+		  rt_error ("Parameter type mismatch, parameter %s.",
+			    v_names[params->av_name]);
+		params++;
+	      }
+	  pop ();
+	}
+      else
+	{
+	  if (!warned)
+	    {
+	      rt_error ("Parameter number mismatch");
+	      warned = TRUE;
+	    }
+	}
+      params = params->next;
+    }
+  if (params != NULL) 
+    rt_error ("Parameter number mismatch");
+}
Index: /trunk/minix/commands/bc/util.c
===================================================================
--- /trunk/minix/commands/bc/util.c	(revision 9)
+++ /trunk/minix/commands/bc/util.c	(revision 9)
@@ -0,0 +1,796 @@
+/* util.c: Utility routines for bc. */
+
+/*  This file is part of bc written for MINIX.
+    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License , or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    You may contact the author by:
+       e-mail:  phil@cs.wwu.edu
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+
+#include "bcdefs.h"
+#ifndef VARARGS
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "global.h"
+#include "proto.h"
+
+
+/* strcopyof mallocs new memory and copies a string to to the new
+   memory. */
+
+char *
+strcopyof (str)
+     char *str;
+{
+  char *temp;
+
+  temp = (char *) bc_malloc (strlen (str)+1);
+  return (strcpy (temp,str));
+}
+
+
+/* nextarg adds another value to the list of arguments. */
+
+arg_list *
+nextarg (args, val)
+     arg_list *args;
+     char val;
+{ arg_list *temp;
+
+  temp = (arg_list *) bc_malloc (sizeof (arg_list));
+  temp->av_name = val;
+  temp->next = args;
+ 
+  return (temp);
+}
+
+
+/* For generate, we must produce a string in the form
+    "val,val,...,val".  We also need a couple of static variables
+   for retaining old generated strings.  It also uses a recursive
+   function that builds the string. */
+
+static char *arglist1 = NULL, *arglist2 = NULL;
+
+
+/* make_arg_str does the actual construction of the argument string.
+   ARGS is the pointer to the list and LEN is the maximum number of
+   characters needed.  1 char is the minimum needed. COMMAS tells
+   if each number should be seperated by commas.*/
+
+_PROTOTYPE (static char *make_arg_str, (arg_list *args, int len, int commas));
+
+static char *
+make_arg_str (args, len, commas)
+      arg_list *args;
+      int len;
+      int commas;
+{
+  char *temp;
+  char sval[20];
+
+  /* Recursive call. */
+  if (args != NULL)
+    temp = make_arg_str (args->next, len+11, commas);
+  else
+    {
+      temp = (char *) bc_malloc (len);
+      *temp = 0;
+      return temp;
+    }
+
+  /* Add the current number to the end of the string. */
+  if (len != 1 && commas) 
+    sprintf (sval, "%d,", args->av_name);
+  else
+    sprintf (sval, "%d", args->av_name);
+  temp = strcat (temp, sval);
+  return (temp);
+}
+
+char *
+arg_str (args, commas)
+     arg_list *args;
+     int commas;
+{
+  if (arglist2 != NULL) 
+    free (arglist2);
+  arglist2 = arglist1;
+  arglist1 = make_arg_str (args, 1, commas);
+  return (arglist1);
+}
+
+
+/* free_args frees an argument list ARGS. */
+
+void
+free_args (args)
+      arg_list *args;
+{ 
+  arg_list *temp;
+ 
+  temp = args;
+  while (temp != NULL)
+    {
+      args = args->next;
+      free (temp);
+      temp = args;
+    }
+}
+
+
+/* Check for valid parameter (PARAMS) and auto (AUTOS) lists.
+   There must be no duplicates any where.  Also, this is where
+   warnings are generated for array parameters. */
+
+void
+check_params ( params, autos )
+     arg_list *params, *autos;
+{
+  arg_list *tmp1, *tmp2;
+
+  /* Check for duplicate parameters. */
+  if (params != NULL)
+    {
+      tmp1 = params;
+      while (tmp1 != NULL)
+	{
+	  tmp2 = tmp1->next;
+	  while (tmp2 != NULL)
+	    {
+	      if (tmp2->av_name == tmp1->av_name) 
+		yyerror ("duplicate parameter names");
+	      tmp2 = tmp2->next;
+	    }
+	  if (tmp1->av_name < 0)
+	    warn ("Array parameter");
+	  tmp1 = tmp1->next;
+	}
+    }
+
+  /* Check for duplicate autos. */
+  if (autos != NULL)
+    {
+      tmp1 = autos;
+      while (tmp1 != NULL)
+	{
+	  tmp2 = tmp1->next;
+	  while (tmp2 != NULL)
+	    {
+	      if (tmp2->av_name == tmp1->av_name) 
+		yyerror ("duplicate auto variable names");
+	      tmp2 = tmp2->next;
+	    }
+	  tmp1 = tmp1->next;
+	}
+    }
+
+  /* Check for duplicate between parameters and autos. */
+  if ((params != NULL) && (autos != NULL))
+    {
+      tmp1 = params;
+      while (tmp1 != NULL)
+	{
+	  tmp2 = autos;
+	  while (tmp2 != NULL)
+	    {
+	      if (tmp2->av_name == tmp1->av_name) 
+		yyerror ("variable in both parameter and auto lists");
+	      tmp2 = tmp2->next;
+	    }
+	  tmp1 = tmp1->next;
+	}
+    }
+}
+
+
+/* Initialize the code generator the parser. */
+
+void
+init_gen ()
+{
+  /* Get things ready. */
+  break_label = 0;
+  continue_label = 0;
+  next_label  = 1;
+  out_count = 2;
+  if (compile_only) 
+    printf ("@i");
+  else
+    init_load ();
+  had_error = FALSE;
+  did_gen = FALSE;
+}
+
+
+/* generate code STR for the machine. */
+
+void
+generate (str)
+      char *str;
+{
+  did_gen = TRUE;
+  if (compile_only)
+    {
+      printf ("%s",str);
+      out_count += strlen(str);
+      if (out_count > 60)
+	{
+	  printf ("\n");
+	  out_count = 0;
+	}
+    }
+  else
+    load_code (str);
+}
+
+
+/* Execute the current code as loaded. */
+
+void
+run_code()
+{
+  /* If no compile errors run the current code. */
+  if (!had_error && did_gen)
+    {
+      if (compile_only)
+	{
+	  printf ("@r\n"); 
+	  out_count = 0;
+	}
+      else
+	execute ();
+    }
+
+  /* Reinitialize the code generation and machine. */
+  if (did_gen)
+    init_gen();
+  else
+    had_error = FALSE;
+}
+
+
+/* Output routines: Write a character CH to the standard output.
+   It keeps track of the number of characters output and may
+   break the output with a "\<cr>". */
+
+void
+out_char (ch)
+     char ch;
+{
+  if (ch == '\n')
+    {
+      out_col = 0;
+      putchar ('\n');
+    }
+  else
+    {
+      out_col++;
+      if (out_col == 70)
+	{
+	  putchar ('\\');
+	  putchar ('\n');
+	  out_col = 1;
+	}
+      putchar (ch);
+    }
+}
+
+
+/* The following are "Symbol Table" routines for the parser. */
+
+/*  find_id returns a pointer to node in TREE that has the correct
+    ID.  If there is no node in TREE with ID, NULL is returned. */
+
+id_rec *
+find_id (tree, id)
+     id_rec *tree;
+     char   *id;
+{
+  int cmp_result;
+  
+  /* Check for an empty tree. */
+  if (tree == NULL)
+    return NULL;
+
+  /* Recursively search the tree. */
+  cmp_result = strcmp (id, tree->id);
+  if (cmp_result == 0)
+    return tree;  /* This is the item. */
+  else if (cmp_result < 0)
+    return find_id (tree->left, id);
+  else
+    return find_id (tree->right, id);  
+}
+
+
+/* insert_id_rec inserts a NEW_ID rec into the tree whose ROOT is
+   provided.  insert_id_rec returns TRUE if the tree height from
+   ROOT down is increased otherwise it returns FALSE.  This is a
+   recursive balanced binary tree insertion algorithm. */
+
+int insert_id_rec (root, new_id)
+     id_rec **root;
+     id_rec *new_id;
+{
+  id_rec *A, *B;
+
+  /* If root is NULL, this where it is to be inserted. */
+  if (*root == NULL)
+    {
+      *root = new_id;
+      new_id->left = NULL;
+      new_id->right = NULL;
+      new_id->balance = 0;
+      return (TRUE);
+    }
+
+  /* We need to search for a leaf. */
+  if (strcmp (new_id->id, (*root)->id) < 0)
+    {
+      /* Insert it on the left. */
+      if (insert_id_rec (&((*root)->left), new_id))
+	{
+	  /* The height increased. */
+	  (*root)->balance --;
+	  
+      switch ((*root)->balance)
+	{
+	case  0:  /* no height increase. */
+	  return (FALSE);
+	case -1:  /* height increase. */
+	  return (FALSE);
+	case -2:  /* we need to do a rebalancing act. */
+	  A = *root;
+	  B = (*root)->left;
+	  if (B->balance <= 0)
+	    {
+	      /* Single Rotate. */
+	      A->left = B->right;
+	      B->right = A;
+	      *root = B;
+	      A->balance = 0;
+	      B->balance = 0;
+	    }
+	  else
+	    {
+	      /* Double Rotate. */
+	      *root = B->right;
+	      B->right = (*root)->left;
+	      A->left = (*root)->right;
+	      (*root)->left = B;
+	      (*root)->right = A;
+	      switch ((*root)->balance)
+		{
+		case -1:
+		  A->balance = 1;
+		  B->balance = 0;
+		  break;
+		case  0:
+		  A->balance = 0;
+		  B->balance = 0;
+		  break;
+		case  1:
+		  A->balance = 0;
+		  B->balance = -1;
+		  break;
+		}
+	      (*root)->balance = 0;
+	    }
+	}     
+	} 
+    }
+  else
+    {
+      /* Insert it on the right. */
+      if (insert_id_rec (&((*root)->right), new_id))
+	{
+	  /* The height increased. */
+	  (*root)->balance ++;
+	  switch ((*root)->balance)
+	    {
+	    case 0:  /* no height increase. */
+	      return (FALSE);
+	    case 1:  /* height increase. */
+	      return (FALSE);
+	    case 2:  /* we need to do a rebalancing act. */
+	      A = *root;
+	      B = (*root)->right;
+	      if (B->balance >= 0)
+		{
+		  /* Single Rotate. */
+		  A->right = B->left;
+		  B->left = A;
+		  *root = B;
+		  A->balance = 0;
+		  B->balance = 0;
+		}
+	      else
+		{
+		  /* Double Rotate. */
+		  *root = B->left;
+		  B->left = (*root)->right;
+		  A->right = (*root)->left;
+		  (*root)->left = A;
+		  (*root)->right = B;
+		  switch ((*root)->balance)
+		    {
+		    case -1:
+		      A->balance = 0;
+		      B->balance = 1;
+		      break;
+		    case  0:
+		      A->balance = 0;
+		      B->balance = 0;
+		      break;
+		    case  1:
+		      A->balance = -1;
+		      B->balance = 0;
+		      break;
+		    }
+		  (*root)->balance = 0;
+		}
+	    }     
+	} 
+    }
+  
+  /* If we fall through to here, the tree did not grow in height. */
+  return (FALSE);
+}
+
+
+/* Initialize variables for the symbol table tree. */
+
+void
+init_tree()
+{
+  name_tree  = NULL;
+  next_array = 1;
+  next_func  = 1;
+  next_var   = 4;  /* 0 => ibase, 1 => obase, 2 => scale, 3 => last. */
+}
+
+
+/* Lookup routines for symbol table names. */
+
+int
+lookup (name, namekind)
+     char *name;
+     int  namekind;
+{
+  id_rec *id;
+
+  /* Warn about non-standard name. */
+  if (strlen(name) != 1)
+    warn ("multiple letter name - %s", name);
+
+  /* Look for the id. */
+  id = find_id (name_tree, name);
+  if (id == NULL)
+    {
+      /* We need to make a new item. */
+      id = (id_rec *) bc_malloc (sizeof (id_rec));
+      id->id = strcopyof (name);
+      id->a_name = 0;
+      id->f_name = 0;
+      id->v_name = 0;
+      insert_id_rec (&name_tree, id);
+    }
+
+  /* Return the correct value. */
+  switch (namekind)
+    {
+      
+    case ARRAY:
+      /* ARRAY variable numbers are returned as negative numbers. */
+      if (id->a_name != 0)
+	{
+	  free (name);
+	  return (-id->a_name);
+	}
+      id->a_name = next_array++;
+      a_names[id->a_name] = name;
+      if (id->a_name < MAX_STORE)
+	{
+	  if (id->a_name >= a_count)
+	    more_arrays ();
+	  return (-id->a_name);
+	}
+      yyerror ("Too many array variables");
+      exit (1);
+
+    case FUNCT:
+      if (id->f_name != 0)
+	{
+	  free(name);
+	  return (id->f_name);
+	}
+      id->f_name = next_func++;
+      f_names[id->f_name] = name;
+      if (id->f_name < MAX_STORE)
+	{
+	  if (id->f_name >= f_count)
+	    more_functions ();
+	  return (id->f_name);
+	}
+      yyerror ("Too many functions");
+      exit (1);
+
+    case SIMPLE:
+      if (id->v_name != 0)
+	{
+	  free(name);
+	  return (id->v_name);
+	}
+      id->v_name = next_var++;
+      v_names[id->v_name - 1] = name;
+      if (id->v_name <= MAX_STORE)
+	{
+	  if (id->v_name >= v_count)
+	    more_variables ();
+	  return (id->v_name);
+	}
+      yyerror ("Too many variables");
+      exit (1);
+    }
+}
+
+
+/* Print the welcome banner. */
+
+void 
+welcome()
+{
+#if !__minix
+  printf ("This is free software with ABSOLUTELY NO WARRANTY.\n");
+  printf ("For details type `warranty'. \n");
+#endif
+}
+
+
+/* Print out the warranty information. */
+
+void 
+warranty(prefix)
+     char *prefix;
+{
+  printf ("\n%s%s\n\n", prefix, BC_VERSION);
+  printf ("%s%s%s%s%s%s%s%s%s%s%s",
+"    This program is free software; you can redistribute it and/or modify\n",
+"    it under the terms of the GNU General Public License as published by\n",
+"    the Free Software Foundation; either version 2 of the License , or\n",
+"    (at your option) any later version.\n\n",
+"    This program is distributed in the hope that it will be useful,\n",
+"    but WITHOUT ANY WARRANTY; without even the implied warranty of\n",
+"    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n",
+"    GNU General Public License for more details.\n\n",
+"    You should have received a copy of the GNU General Public License\n",
+"    along with this program. If not, write to the Free Software\n",
+"    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\n\n");
+}
+
+/* Print out the limits of this program. */
+
+void
+limits()
+{
+  printf ("BC_BASE_MAX     = %d\n",  BC_BASE_MAX);
+  printf ("BC_DIM_MAX      = %ld\n", (long) BC_DIM_MAX);
+  printf ("BC_SCALE_MAX    = %d\n",  BC_SCALE_MAX);
+  printf ("BC_STRING_MAX   = %d\n",  BC_STRING_MAX);
+  printf ("MAX Exponent    = %ld\n", (long) LONG_MAX);
+  printf ("MAX code        = %ld\n", (long) BC_MAX_SEGS * (long) BC_SEG_SIZE);
+  printf ("multiply digits = %ld\n", (long) LONG_MAX / (long) 90);
+  printf ("Number of vars  = %ld\n", (long) MAX_STORE);
+#ifdef OLD_EQ_OP
+  printf ("Old assignment operatiors are valid. (=-, =+, ...)\n");
+#endif 
+}
+
+/* bc_malloc will check the return value so all other places do not
+   have to do it!  SIZE is the number of types to allocate. */
+
+char *
+bc_malloc (size)
+     int size;
+{
+  char *ptr;
+
+  ptr = (char *) malloc (size);
+  if (ptr == NULL)
+    out_of_memory ();
+
+  return ptr;
+}
+
+
+/* The following routines are error routines for various problems. */
+
+/* Malloc could not get enought memory. */
+
+void
+out_of_memory()
+{
+  fprintf (stderr, "Fatal error: Out of memory for malloc.\n");
+  exit (1);
+}
+
+
+
+/* The standard yyerror routine.  Built with variable number of argumnets. */
+
+#ifndef VARARGS
+#ifdef __STDC__
+void
+yyerror (char *str, ...)
+#else
+void
+yyerror (str)
+     char *str;
+#endif
+#else
+void
+yyerror (str, va_alist)
+     char *str;
+#endif
+{
+  char *name;
+  va_list args;
+
+#ifndef VARARGS   
+   va_start (args, str);
+#else
+   va_start (args);
+#endif
+  if (is_std_in)
+    name = "(standard_in)";
+  else
+    name = g_argv[optind-1];
+  fprintf (stderr,"%s %d: ",name,line_no);
+  vfprintf (stderr, str, args);
+  fprintf (stderr, "\n");
+  had_error = TRUE;
+  va_end (args);
+}
+
+
+/* The routine to produce warnings about non-standard features
+   found during parsing. */
+
+#ifndef VARARGS
+#ifdef __STDC__
+void 
+warn (char *mesg, ...)
+#else
+void
+warn (mesg)
+     char *mesg;
+#endif
+#else
+void
+warn (mesg, va_alist)
+     char *mesg;
+#endif
+{
+  char *name;
+  va_list args;
+
+#ifndef VARARGS   
+  va_start (args, mesg);
+#else
+  va_start (args);
+#endif
+  if (std_only)
+    {
+      if (is_std_in)
+	name = "(standard_in)";
+      else
+	name = g_argv[optind-1];
+      fprintf (stderr,"%s %d: ",name,line_no);
+      vfprintf (stderr, mesg, args);
+      fprintf (stderr, "\n");
+      had_error = TRUE;
+    }
+  else
+    if (warn_not_std)
+      {
+	if (is_std_in)
+	  name = "(standard_in)";
+	else
+	  name = g_argv[optind-1];
+	fprintf (stderr,"%s %d: (Warning) ",name,line_no);
+	vfprintf (stderr, mesg, args);
+	fprintf (stderr, "\n");
+      }
+  va_end (args);
+}
+
+/* Runtime error will  print a message and stop the machine. */
+
+#ifndef VARARGS
+#ifdef __STDC__
+void
+rt_error (char *mesg, ...)
+#else
+void
+rt_error (mesg)
+     char *mesg;
+#endif
+#else
+void
+rt_error (mesg, va_alist)
+     char *mesg;
+#endif
+{
+  va_list args;
+  char error_mesg [255];
+
+#ifndef VARARGS   
+  va_start (args, mesg);
+#else
+  va_start (args);
+#endif
+  vsprintf (error_mesg, mesg, args);
+  va_end (args);
+  
+  fprintf (stderr, "Runtime error (func=%s, adr=%d): %s\n",
+	   f_names[pc.pc_func], pc.pc_addr, error_mesg);
+  runtime_error = TRUE;
+}
+
+
+/* A runtime warning tells of some action taken by the processor that
+   may change the program execution but was not enough of a problem
+   to stop the execution. */
+
+#ifndef VARARGS
+#ifdef __STDC__
+void
+rt_warn (char *mesg, ...)
+#else
+void
+rt_warn (mesg)
+     char *mesg;
+#endif
+#else
+void
+rt_warn (mesg, va_alist)
+     char *mesg;
+#endif
+{
+  va_list args;
+  char error_mesg [255];
+
+#ifndef VARARGS   
+  va_start (args, mesg);
+#else
+  va_start (args);
+#endif
+  vsprintf (error_mesg, mesg, args);
+  va_end (args);
+
+  fprintf (stderr, "Runtime warning (func=%s, adr=%d): %s\n",
+	   f_names[pc.pc_func], pc.pc_addr, error_mesg);
+}
Index: /trunk/minix/commands/bc/version.h
===================================================================
--- /trunk/minix/commands/bc/version.h	(revision 9)
+++ /trunk/minix/commands/bc/version.h	(revision 9)
@@ -0,0 +1,3 @@
+#define BC_VERSION  \
+ "bc 1.02 (Mar 3, 92) Copyright (C) 1991, 1992 Free Software Foundation, Inc."
+
Index: /trunk/minix/commands/bc/y.tab.h
===================================================================
--- /trunk/minix/commands/bc/y.tab.h	(revision 9)
+++ /trunk/minix/commands/bc/y.tab.h	(revision 9)
@@ -0,0 +1,40 @@
+#define NEWLINE 257
+#define AND 258
+#define OR 259
+#define NOT 260
+#define STRING 261
+#define NAME 262
+#define NUMBER 263
+#define MUL_OP 264
+#define ASSIGN_OP 265
+#define REL_OP 266
+#define INCR_DECR 267
+#define Define 268
+#define Break 269
+#define Quit 270
+#define Length 271
+#define Return 272
+#define For 273
+#define If 274
+#define While 275
+#define Sqrt 276
+#define Else 277
+#define Scale 278
+#define Ibase 279
+#define Obase 280
+#define Auto 281
+#define Read 282
+#define Warranty 283
+#define Halt 284
+#define Last 285
+#define Continue 286
+#define Print 287
+#define Limits 288
+#define UNARY_MINUS 289
+typedef union {
+	char	 *s_value;
+	char	  c_value;
+	int	  i_value;
+	arg_list *a_value;
+       } YYSTYPE;
+extern YYSTYPE yylval;
Index: /trunk/minix/commands/byacc/ACKNOWLEDGEMEN
===================================================================
--- /trunk/minix/commands/byacc/ACKNOWLEDGEMEN	(revision 9)
+++ /trunk/minix/commands/byacc/ACKNOWLEDGEMEN	(revision 9)
@@ -0,0 +1,25 @@
+     Berkeley Yacc owes much to the unflagging efforts of Keith Bostic.
+His badgering kept me working on it long after I was ready to quit.
+
+     Berkeley Yacc is based on the excellent algorithm for computing LALR(1)
+lookaheads developed by Tom Pennello and Frank DeRemer.  The algorithm is
+described in their almost impenetrable article in TOPLAS 4,4.
+
+     Finally, much of the credit for the latest version must go to those
+who pointed out deficiencies of my earlier releases.  Among the most
+prolific contributors were
+
+	  Benson I. Margulies
+	  Dave Gentzel
+	  Antoine Verheijen
+	  Peter S. Housel
+	  Dale Smith
+	  Ozan Yigit
+	  John Campbell
+	  Bill Sommerfeld
+	  Paul Hilfinger
+	  Gary Bridgewater
+	  Dave Bakken
+	  Dan Lanciani
+	  Richard Sargent
+	  Parag Patel
Index: /trunk/minix/commands/byacc/MANIFEST
===================================================================
--- /trunk/minix/commands/byacc/MANIFEST	(revision 9)
+++ /trunk/minix/commands/byacc/MANIFEST	(revision 9)
@@ -0,0 +1,33 @@
+   File Name		Archive #	Description
+-----------------------------------------------------------
+ ACKNOWLEDGEMENTS           1	
+ CSU.diffs                  1	
+ MANIFEST                   1	This shipping list
+ Makefile                   1	
+ NEW_FEATURES               1	
+ NOTES                      1	
+ NO_WARRANTY                1	
+ README                     1	
+ closure.c                  1	
+ defs.h                     1	
+ error.c                    1	
+ lalr.c                     1	
+ lr0.c                      1	
+ main.c                     1	
+ mkpar.c                    1	
+ output.c                   2	
+ reader.c                   3	
+ skeleton.c                 1	
+ symtab.c                   1	
+ test                       1	
+ test/error.output          1	
+ test/error.tab.c           1	
+ test/error.tab.h           1	
+ test/error.y               1	
+ test/ftp.output            2	
+ test/ftp.tab.c             3	
+ test/ftp.tab.h             1	
+ test/ftp.y                 2	
+ verbose.c                  1	
+ warshall.c                 1	
+ yacc.1                     1	
Index: /trunk/minix/commands/byacc/Makefile
===================================================================
--- /trunk/minix/commands/byacc/Makefile	(revision 9)
+++ /trunk/minix/commands/byacc/Makefile	(revision 9)
@@ -0,0 +1,86 @@
+# Makefile for Berkeley yacc.
+
+BINDIR	      = /usr/bin
+
+HDRS	      = defs.h
+
+CFLAGS	      = -DNDEBUG -D_MINIX -D_POSIX_SOURCE -wo $(OPT)
+
+LDFLAGS	      = -i
+
+LIBS	      =
+
+CC = exec cc
+
+LINKER	      = $(CC)
+
+MAKEFILE      = Makefile
+
+OBJS	      = closure.o \
+		error.o \
+		lalr.o \
+		lr0.o \
+		main.o \
+		mkpar.o \
+		output.o \
+		reader.o \
+		skeleton.o \
+		symtab.o \
+		verbose.o \
+		warshall.o
+
+PRINT	      = pr -f -l88
+
+PROGRAM	      = yacc
+
+SRCS	      = closure.c \
+		error.c \
+		lalr.c \
+		lr0.c \
+		main.c \
+		mkpar.c \
+		output.c \
+		reader.c \
+		skeleton.c \
+		symtab.c \
+		verbose.c \
+		warshall.c
+
+all:		$(PROGRAM)
+
+$(PROGRAM):     $(OBJS) $(LIBS)
+		$(LINKER) $(LDFLAGS) -o $(PROGRAM) $(OBJS) $(LIBS)
+		install -S 484k $(PROGRAM)
+
+install:	$(BINDIR)/yacc
+
+$(BINDIR)/yacc:	$(PROGRAM)
+		install -cs -o bin $(PROGRAM) $@
+
+clean:;		rm -f $(OBJS) $(PROGRAM) core
+
+#depend:;	@mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) DEST=$(DEST)
+#
+#index:;	@ctags -wx $(HDRS) $(SRCS)
+#
+#listing:;	@$(PRINT) Makefile $(HDRS) $(SRCS) | lpr
+#
+#lint:;		@lint $(SRCS)
+#
+#program:        $(PROGRAM)
+#
+#tags:           $(HDRS) $(SRCS); @ctags $(HDRS) $(SRCS)
+
+###
+closure.o: defs.h
+error.o: defs.h
+lalr.o: defs.h
+lr0.o: defs.h
+main.o: defs.h
+mkpar.o: defs.h
+output.o: defs.h
+reader.o: defs.h
+skeleton.o: defs.h
+symtab.o: defs.h
+verbose.o: defs.h
+warshall.o: defs.h
Index: /trunk/minix/commands/byacc/NEW_FEATURES
===================================================================
--- /trunk/minix/commands/byacc/NEW_FEATURES	(revision 9)
+++ /trunk/minix/commands/byacc/NEW_FEATURES	(revision 9)
@@ -0,0 +1,46 @@
+     The -r option has been implemented.  The -r option tells Yacc to
+put the read-only tables in y.tab.c and the code and variables in
+y.code.c.  Keith Bostic asked for this option so that :yyfix could be
+eliminated.
+
+     The -l and -t options have been implemented.  The -l option tells
+Yacc not to include #line directives in the code it produces.  The -t
+option causes debugging code to be included in the compiled parser.
+
+     The code for error recovery has been changed to implement the same
+algorithm as AT&T Yacc.  There will still be differences in the way
+error recovery works because AT&T Yacc uses more default reductions
+than Berkeley Yacc.
+
+     The environment variable TMPDIR determines the directory where
+temporary files will be created.  If TMPDIR is defined, temporary files
+will be created in the directory whose pathname is the value of TMPDIR.
+By default, temporary files are created in /tmp.
+
+     The keywords are now case-insensitive.  For example, %nonassoc,
+%NONASSOC, %NonAssoc, and %nOnAsSoC are all equivalent.
+
+     Commas and semicolons that are not part of C code are treated as
+commentary.
+
+     Line-end comments, as in BCPL, are permitted.  Line-end comments
+begin with // and end at the next end-of-line.  Line-end comments are
+permitted in C code; they are converted to C comments on output.
+
+     The form of y.output files has been changed to look more like
+those produced by AT&T Yacc.
+
+     A new kind of declaration has been added.  The form of the declaration
+is
+
+	  %ident string
+
+where string is a sequence of characters begining with a double quote
+and ending with either a double quote or the next end-of-line, whichever
+comes first.  The declaration will cause a #ident directive to be written
+near the start of the output file.
+
+     If a parser has been compiled with debugging code, that code can be
+enabled by setting an environment variable.  If the environment variable
+YYDEBUG is set to 0, debugging output is suppressed.  If it is set to 1,
+debugging output is written to standard output.
Index: /trunk/minix/commands/byacc/NOTES
===================================================================
--- /trunk/minix/commands/byacc/NOTES	(revision 9)
+++ /trunk/minix/commands/byacc/NOTES	(revision 9)
@@ -0,0 +1,9 @@
+Berkeley Yacc reflects its origins.  The reason so many routines
+use exactly six register variables is that Berkeley Yacc was
+developed on a VAX using PCC.  PCC placed at most six variables
+in registers.  I went to considerable effort to find which six
+variables most belonged in registers.  Changes in machines and
+compilers make that effort worthless, perhaps even harmful.
+
+The code contains many instances where address calculations are
+performed in particular ways to optimize the code for the VAX.
Index: /trunk/minix/commands/byacc/NO_WARRANTY
===================================================================
--- /trunk/minix/commands/byacc/NO_WARRANTY	(revision 9)
+++ /trunk/minix/commands/byacc/NO_WARRANTY	(revision 9)
@@ -0,0 +1,3 @@
+     Berkeley Yacc is distributed with no warranty whatever.  The author
+and any other contributors take no responsibility for the consequences of
+its use.
Index: /trunk/minix/commands/byacc/README
===================================================================
--- /trunk/minix/commands/byacc/README	(revision 9)
+++ /trunk/minix/commands/byacc/README	(revision 9)
@@ -0,0 +1,23 @@
+    Berkeley Yacc is an LALR(1) parser generator.  Berkeley Yacc has been made
+as compatible as possible with AT&T Yacc.  Berkeley Yacc can accept any input
+specification that conforms to the AT&T Yacc documentation.  Specifications
+that take advantage of undocumented features of AT&T Yacc will probably be
+rejected.
+
+    Berkeley Yacc is distributed with no warranty whatever.  The code is certain
+to contain errors.  Neither the author nor any contributor takes responsibility
+for any consequences of its use.
+
+    Berkeley Yacc is in the public domain.  The data structures and algorithms
+used in Berkeley Yacc are all either taken from documents available to the
+general public or are inventions of the author.  Anyone may freely distribute
+source or binary forms of Berkeley Yacc whether unchanged or modified.
+Distributers may charge whatever fees they can obtain for Berkeley Yacc.
+Programs generated by Berkeley Yacc may be distributed freely.
+
+    Please report bugs to
+
+			robert.corbett@eng.Sun.COM
+
+Include a small example if possible.  Please include the banner string from
+skeleton.c with the bug report.  Do not expect rapid responses.
Index: /trunk/minix/commands/byacc/build
===================================================================
--- /trunk/minix/commands/byacc/build	(revision 9)
+++ /trunk/minix/commands/byacc/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/byacc/closure.c
===================================================================
--- /trunk/minix/commands/byacc/closure.c	(revision 9)
+++ /trunk/minix/commands/byacc/closure.c	(revision 9)
@@ -0,0 +1,255 @@
+#include "defs.h"
+
+short *itemset;
+short *itemsetend;
+unsigned *ruleset;
+
+static unsigned *first_derives;
+static unsigned *EFF;
+
+
+set_EFF()
+{
+    register unsigned *row;
+    register int symbol;
+    register short *sp;
+    register int rowsize;
+    register int i;
+    register int rule;
+
+    rowsize = WORDSIZE(nvars);
+    EFF = NEW2(nvars * rowsize, unsigned);
+
+    row = EFF;
+    for (i = start_symbol; i < nsyms; i++)
+    {
+	sp = derives[i];
+	for (rule = *sp; rule > 0; rule = *++sp)
+	{
+	    symbol = ritem[rrhs[rule]];
+	    if (ISVAR(symbol))
+	    {
+		symbol -= start_symbol;
+		SETBIT(row, symbol);
+	    }
+	}
+	row += rowsize;
+    }
+
+    reflexive_transitive_closure(EFF, nvars);
+
+#ifdef	DEBUG
+    print_EFF();
+#endif
+}
+
+
+set_first_derives()
+{
+    register unsigned *rrow;
+    register unsigned *vrow;
+    register int j;
+    register unsigned k;
+    register unsigned cword;
+    register short *rp;
+
+    int rule;
+    int i;
+    int rulesetsize;
+    int varsetsize;
+
+    rulesetsize = WORDSIZE(nrules);
+    varsetsize = WORDSIZE(nvars);
+    first_derives = NEW2(nvars * rulesetsize, unsigned) - ntokens * rulesetsize;
+
+    set_EFF();
+
+    rrow = first_derives + ntokens * rulesetsize;
+    for (i = start_symbol; i < nsyms; i++)
+    {
+	vrow = EFF + ((i - ntokens) * varsetsize);
+	k = BITS_PER_WORD;
+	for (j = start_symbol; j < nsyms; k++, j++)
+	{
+	    if (k >= BITS_PER_WORD)
+	    {
+		cword = *vrow++;
+		k = 0;
+	    }
+
+	    if (cword & (1 << k))
+	    {
+		rp = derives[j];
+		while ((rule = *rp++) >= 0)
+		{
+		    SETBIT(rrow, rule);
+		}
+	    }
+	}
+
+	vrow += varsetsize;
+	rrow += rulesetsize;
+    }
+
+#ifdef	DEBUG
+    print_first_derives();
+#endif
+
+    FREE(EFF);
+}
+
+
+closure(nucleus, n)
+short *nucleus;
+int n;
+{
+    register int ruleno;
+    register unsigned word;
+    register unsigned i;
+    register short *csp;
+    register unsigned *dsp;
+    register unsigned *rsp;
+    register int rulesetsize;
+
+    short *csend;
+    unsigned *rsend;
+    int symbol;
+    int itemno;
+
+    rulesetsize = WORDSIZE(nrules);
+    rsp = ruleset;
+    rsend = ruleset + rulesetsize;
+    for (rsp = ruleset; rsp < rsend; rsp++)
+	*rsp = 0;
+
+    csend = nucleus + n;
+    for (csp = nucleus; csp < csend; ++csp)
+    {
+	symbol = ritem[*csp];
+	if (ISVAR(symbol))
+	{
+	    dsp = first_derives + symbol * rulesetsize;
+	    rsp = ruleset;
+	    while (rsp < rsend)
+		*rsp++ |= *dsp++;
+	}
+    }
+
+    ruleno = 0;
+    itemsetend = itemset;
+    csp = nucleus;
+    for (rsp = ruleset; rsp < rsend; ++rsp)
+    {
+	word = *rsp;
+	if (word)
+	{
+	    for (i = 0; i < BITS_PER_WORD; ++i)
+	    {
+		if (word & (1 << i))
+		{
+		    itemno = rrhs[ruleno+i];
+		    while (csp < csend && *csp < itemno)
+			*itemsetend++ = *csp++;
+		    *itemsetend++ = itemno;
+		    while (csp < csend && *csp == itemno)
+			++csp;
+		}
+	    }
+	}
+	ruleno += BITS_PER_WORD;
+    }
+
+    while (csp < csend)
+	*itemsetend++ = *csp++;
+
+#ifdef	DEBUG
+  print_closure(n);
+#endif
+}
+
+
+
+finalize_closure()
+{
+  FREE(itemset);
+  FREE(ruleset);
+  FREE(first_derives + ntokens * WORDSIZE(nrules));
+}
+
+
+#ifdef	DEBUG
+
+print_closure(n)
+int n;
+{
+  register short *isp;
+
+  printf("\n\nn = %d\n\n", n);
+  for (isp = itemset; isp < itemsetend; isp++)
+    printf("   %d\n", *isp);
+}
+
+
+print_EFF()
+{
+    register int i, j;
+    register unsigned *rowp;
+    register unsigned word;
+    register unsigned k;
+
+    printf("\n\nEpsilon Free Firsts\n");
+
+    for (i = start_symbol; i < nsyms; i++)
+    {
+	printf("\n%s", symbol_name[i]);
+	rowp = EFF + ((i - start_symbol) * WORDSIZE(nvars));
+	word = *rowp++;
+
+	k = BITS_PER_WORD;
+	for (j = 0; j < nvars; k++, j++)
+	{
+	    if (k >= BITS_PER_WORD)
+	    {
+		word = *rowp++;
+		k = 0;
+	    }
+
+	    if (word & (1 << k))
+		printf("  %s", symbol_name[start_symbol + j]);
+	}
+    }
+}
+
+
+print_first_derives()
+{
+    register int i;
+    register int j;
+    register unsigned *rp;
+    register unsigned cword;
+    register unsigned k;
+
+    printf("\n\n\nFirst Derives\n");
+
+    for (i = start_symbol; i < nsyms; i++)
+    {
+	printf("\n%s derives\n", symbol_name[i]);
+	rp = first_derives + i * WORDSIZE(nrules);
+	k = BITS_PER_WORD;
+	for (j = 0; j <= nrules; k++, j++)
+        {
+	  if (k >= BITS_PER_WORD)
+	  {
+	      cword = *rp++;
+	      k = 0;
+	  }
+
+	  if (cword & (1 << k))
+	    printf("   %d\n", j);
+	}
+    }
+
+  fflush(stdout);
+}
+
+#endif
Index: /trunk/minix/commands/byacc/defs.h
===================================================================
--- /trunk/minix/commands/byacc/defs.h	(revision 9)
+++ /trunk/minix/commands/byacc/defs.h	(revision 9)
@@ -0,0 +1,298 @@
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+
+
+/*  machine-dependent definitions			*/
+/*  the following definitions are for the Tahoe		*/
+/*  they might have to be changed for other machines	*/
+
+/*  MAXCHAR is the largest unsigned character value	*/
+/*  MAXSHORT is the largest value of a C short		*/
+/*  MINSHORT is the most negative value of a C short	*/
+/*  MAXTABLE is the maximum table size			*/
+/*  BITS_PER_WORD is the number of bits in a C unsigned	*/
+/*  WORDSIZE computes the number of words needed to	*/
+/*	store n bits					*/
+/*  BIT returns the value of the n-th bit starting	*/
+/*	from r (0-indexed)				*/
+/*  SETBIT sets the n-th bit starting from r		*/
+
+#if !__STDC__
+#define	MAXCHAR		255
+#define	MAXSHORT	32767
+#define MINSHORT	-32768
+#define BITS_PER_WORD	32
+#else
+#include <limits.h>
+#define	MAXCHAR		UCHAR_MAX
+#define	MAXSHORT	SHRT_MAX
+#define MINSHORT	SHRT_MIN
+#define BITS_PER_WORD	(INT_MAX == 32767 ? 16 : 32)
+#define BITS_PER_BPW	(INT_MAX == 32767 ? 4 : 5)
+#endif
+#define MAXTABLE	32500
+#define	WORDSIZE(n)	(((n)+(BITS_PER_WORD-1))/BITS_PER_WORD)
+#define	BIT(r, n)	((((r)[(n)>>BITS_PER_BPW])>>((n)&(BITS_PER_WORD-1)))&1)
+#define	SETBIT(r, n)	((r)[(n)>>BITS_PER_BPW]|=((unsigned)1<<((n)&(BITS_PER_WORD-1))))
+
+
+/*  character names  */
+
+#define	NUL		'\0'    /*  the null character  */
+#define	NEWLINE		'\n'    /*  line feed  */
+#define	SP		' '     /*  space  */
+#define	BS		'\b'    /*  backspace  */
+#define	HT		'\t'    /*  horizontal tab  */
+#define	VT		'\013'  /*  vertical tab  */
+#define	CR		'\r'    /*  carriage return  */
+#define	FF		'\f'    /*  form feed  */
+#define	QUOTE		'\''    /*  single quote  */
+#define	DOUBLE_QUOTE	'\"'    /*  double quote  */
+#define	BACKSLASH	'\\'    /*  backslash  */
+
+
+/* defines for constructing filenames */
+
+#define CODE_SUFFIX	".code.c"
+#define	DEFINES_SUFFIX	".tab.h"
+#define	OUTPUT_SUFFIX	".tab.c"
+#define	VERBOSE_SUFFIX	".output"
+
+
+/* keyword codes */
+
+#define TOKEN 0
+#define LEFT 1
+#define RIGHT 2
+#define NONASSOC 3
+#define MARK 4
+#define TEXT 5
+#define TYPE 6
+#define START 7
+#define UNION 8
+#define IDENT 9
+
+
+/*  symbol classes  */
+
+#define UNKNOWN 0
+#define TERM 1
+#define NONTERM 2
+
+
+/*  the undefined value  */
+
+#define UNDEFINED (-1)
+
+
+/*  action codes  */
+
+#define SHIFT 1
+#define REDUCE 2
+
+
+/*  character macros  */
+
+#define IS_IDENT(c)	(isalnum(c) || (c) == '_' || (c) == '.' || (c) == '$')
+#define	IS_OCTAL(c)	((c) >= '0' && (c) <= '7')
+#define	NUMERIC_VALUE(c)	((c) - '0')
+
+
+/*  symbol macros  */
+
+#define ISTOKEN(s)	((s) < start_symbol)
+#define ISVAR(s)	((s) >= start_symbol)
+
+
+/*  storage allocation macros  */
+
+#define CALLOC(k,n)	(calloc((unsigned)(k),(unsigned)(n)))
+#define	FREE(x)		(free((char*)(x)))
+#define MALLOC(n)	(malloc((unsigned)(n)))
+#define	NEW(t)		((t*)allocate(sizeof(t)))
+#define	NEW2(n,t)	((t*)allocate((unsigned)((n)*sizeof(t))))
+#define REALLOC(p,n)	(realloc((char*)(p),(unsigned)(n)))
+
+
+/*  the structure of a symbol table entry  */
+
+typedef struct bucket bucket;
+struct bucket
+{
+    struct bucket *link;
+    struct bucket *next;
+    char *name;
+    char *tag;
+    short value;
+    short index;
+    short prec;
+    char class;
+    char assoc;
+};
+
+
+/*  the structure of the LR(0) state machine  */
+
+typedef struct core core;
+struct core
+{
+    struct core *next;
+    struct core *link;
+    short number;
+    short accessing_symbol;
+    short nitems;
+    short items[1];
+};
+
+
+/*  the structure used to record shifts  */
+
+typedef struct shifts shifts;
+struct shifts
+{
+    struct shifts *next;
+    short number;
+    short nshifts;
+    short shift[1];
+};
+
+
+/*  the structure used to store reductions  */
+
+typedef struct reductions reductions;
+struct reductions
+{
+    struct reductions *next;
+    short number;
+    short nreds;
+    short rules[1];
+};
+
+
+/*  the structure used to represent parser actions  */
+
+typedef struct action action;
+struct action
+{
+    struct action *next;
+    short symbol;
+    short number;
+    short prec;
+    char action_code;
+    char assoc;
+    char suppressed;
+};
+
+
+/* global variables */
+
+extern char dflag;
+extern char lflag;
+extern char rflag;
+extern char tflag;
+extern char vflag;
+extern char *symbol_prefix;
+
+extern char *myname;
+extern char *cptr;
+extern char *line;
+extern int lineno;
+extern int outline;
+
+extern char *banner[];
+extern char *tables[];
+extern char *header[];
+extern char *body[];
+extern char *trailer[];
+
+extern char *action_file_name;
+extern char *code_file_name;
+extern char *defines_file_name;
+extern char *input_file_name;
+extern char *output_file_name;
+extern char *text_file_name;
+extern char *union_file_name;
+extern char *verbose_file_name;
+
+extern FILE *action_file;
+extern FILE *code_file;
+extern FILE *defines_file;
+extern FILE *input_file;
+extern FILE *output_file;
+extern FILE *text_file;
+extern FILE *union_file;
+extern FILE *verbose_file;
+
+extern int nitems;
+extern int nrules;
+extern int nsyms;
+extern int ntokens;
+extern int nvars;
+extern int ntags;
+
+extern char unionized;
+extern char line_format[];
+
+extern int   start_symbol;
+extern char  **symbol_name;
+extern short *symbol_value;
+extern short *symbol_prec;
+extern char  *symbol_assoc;
+
+extern short *ritem;
+extern short *rlhs;
+extern short *rrhs;
+extern short *rprec;
+extern char  *rassoc;
+
+extern short **derives;
+extern char *nullable;
+
+extern bucket *first_symbol;
+extern bucket *last_symbol;
+
+extern int nstates;
+extern core *first_state;
+extern shifts *first_shift;
+extern reductions *first_reduction;
+extern short *accessing_symbol;
+extern core **state_table;
+extern shifts **shift_table;
+extern reductions **reduction_table;
+extern unsigned *LA;
+extern short *LAruleno;
+extern short *lookaheads;
+extern short *goto_map;
+extern short *from_state;
+extern short *to_state;
+
+extern action **parser;
+extern int SRtotal;
+extern int RRtotal;
+extern short *SRconflicts;
+extern short *RRconflicts;
+extern short *defred;
+extern short *rules_used;
+extern short nunused;
+extern short final_state;
+
+/* global functions */
+
+extern char *allocate();
+extern bucket *lookup();
+extern bucket *make_bucket();
+
+
+/* system variables */
+
+extern int errno;
+
+
+/* system functions */
+
+extern void free();
+extern char *calloc();
+extern char *malloc();
+extern char *realloc();
+extern char *strcpy();
Index: /trunk/minix/commands/byacc/error.c
===================================================================
--- /trunk/minix/commands/byacc/error.c	(revision 9)
+++ /trunk/minix/commands/byacc/error.c	(revision 9)
@@ -0,0 +1,317 @@
+/* routines for printing error messages  */
+
+#include "defs.h"
+
+
+fatal(msg)
+char *msg;
+{
+    fprintf(stderr, "%s: f - %s\n", myname, msg);
+    done(2);
+}
+
+
+no_space()
+{
+    fprintf(stderr, "%s: f - out of space\n", myname);
+    done(2);
+}
+
+
+open_error(filename)
+char *filename;
+{
+    fprintf(stderr, "%s: f - cannot open \"%s\"\n", myname, filename);
+    done(2);
+}
+
+
+unexpected_EOF()
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", unexpected end-of-file\n",
+	    myname, lineno, input_file_name);
+    done(1);
+}
+
+
+print_pos(st_line, st_cptr)
+char *st_line;
+char *st_cptr;
+{
+    register char *s;
+
+    if (st_line == 0) return;
+    for (s = st_line; *s != '\n'; ++s)
+    {
+	if (isprint(*s) || *s == '\t')
+	    putc(*s, stderr);
+	else
+	    putc('?', stderr);
+    }
+    putc('\n', stderr);
+    for (s = st_line; s < st_cptr; ++s)
+    {
+	if (*s == '\t')
+	    putc('\t', stderr);
+	else
+	    putc(' ', stderr);
+    }
+    putc('^', stderr);
+    putc('\n', stderr);
+}
+
+
+syntax_error(st_lineno, st_line, st_cptr)
+int st_lineno;
+char *st_line;
+char *st_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", syntax error\n",
+	    myname, st_lineno, input_file_name);
+    print_pos(st_line, st_cptr);
+    done(1);
+}
+
+
+unterminated_comment(c_lineno, c_line, c_cptr)
+int c_lineno;
+char *c_line;
+char *c_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", unmatched /*\n",
+	    myname, c_lineno, input_file_name);
+    print_pos(c_line, c_cptr);
+    done(1);
+}
+
+
+unterminated_string(s_lineno, s_line, s_cptr)
+int s_lineno;
+char *s_line;
+char *s_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", unterminated string\n",
+	    myname, s_lineno, input_file_name);
+    print_pos(s_line, s_cptr);
+    done(1);
+}
+
+
+unterminated_text(t_lineno, t_line, t_cptr)
+int t_lineno;
+char *t_line;
+char *t_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", unmatched %%{\n",
+	    myname, t_lineno, input_file_name);
+    print_pos(t_line, t_cptr);
+    done(1);
+}
+
+
+unterminated_union(u_lineno, u_line, u_cptr)
+int u_lineno;
+char *u_line;
+char *u_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", unterminated %%union \
+declaration\n", myname, u_lineno, input_file_name);
+    print_pos(u_line, u_cptr);
+    done(1);
+}
+
+
+over_unionized(u_cptr)
+char *u_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", too many %%union \
+declarations\n", myname, lineno, input_file_name);
+    print_pos(line, u_cptr);
+    done(1);
+}
+
+
+illegal_tag(t_lineno, t_line, t_cptr)
+int t_lineno;
+char *t_line;
+char *t_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", illegal tag\n",
+	    myname, t_lineno, input_file_name);
+    print_pos(t_line, t_cptr);
+    done(1);
+}
+
+
+illegal_character(c_cptr)
+char *c_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", illegal character\n",
+	    myname, lineno, input_file_name);
+    print_pos(line, c_cptr);
+    done(1);
+}
+
+
+used_reserved(s)
+char *s;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", illegal use of reserved symbol \
+%s\n", myname, lineno, input_file_name, s);
+    done(1);
+}
+
+
+tokenized_start(s)
+char *s;
+{
+     fprintf(stderr, "%s: e - line %d of \"%s\", the start symbol %s cannot be \
+declared to be a token\n", myname, lineno, input_file_name, s);
+     done(1);
+}
+
+
+retyped_warning(s)
+char *s;
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", the type of %s has been \
+redeclared\n", myname, lineno, input_file_name, s);
+}
+
+
+reprec_warning(s)
+char *s;
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", the precedence of %s has been \
+redeclared\n", myname, lineno, input_file_name, s);
+}
+
+
+revalued_warning(s)
+char *s;
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", the value of %s has been \
+redeclared\n", myname, lineno, input_file_name, s);
+}
+
+
+terminal_start(s)
+char *s;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", the start symbol %s is a \
+token\n", myname, lineno, input_file_name, s);
+    done(1);
+}
+
+
+restarted_warning()
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", the start symbol has been \
+redeclared\n", myname, lineno, input_file_name);
+}
+
+
+no_grammar()
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", no grammar has been \
+specified\n", myname, lineno, input_file_name);
+    done(1);
+}
+
+
+terminal_lhs(s_lineno)
+int s_lineno;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", a token appears on the lhs \
+of a production\n", myname, s_lineno, input_file_name);
+    done(1);
+}
+
+
+prec_redeclared()
+{
+    fprintf(stderr, "%s: w - line %d of  \"%s\", conflicting %%prec \
+specifiers\n", myname, lineno, input_file_name);
+}
+
+
+unterminated_action(a_lineno, a_line, a_cptr)
+int a_lineno;
+char *a_line;
+char *a_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", unterminated action\n",
+	    myname, a_lineno, input_file_name);
+    print_pos(a_line, a_cptr);
+    done(1);
+}
+
+
+dollar_warning(a_lineno, i)
+int a_lineno;
+int i;
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", $%d references beyond the \
+end of the current rule\n", myname, a_lineno, input_file_name, i);
+}
+
+
+dollar_error(a_lineno, a_line, a_cptr)
+int a_lineno;
+char *a_line;
+char *a_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", illegal $-name\n",
+	    myname, a_lineno, input_file_name);
+    print_pos(a_line, a_cptr);
+    done(1);
+}
+
+
+untyped_lhs()
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", $$ is untyped\n",
+	    myname, lineno, input_file_name);
+    done(1);
+}
+
+
+untyped_rhs(i, s)
+int i;
+char *s;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", $%d (%s) is untyped\n",
+	    myname, lineno, input_file_name, i, s);
+    done(1);
+}
+
+
+unknown_rhs(i)
+int i;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", $%d is untyped\n",
+	    myname, lineno, input_file_name, i);
+    done(1);
+}
+
+
+default_action_warning()
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", the default action assigns an \
+undefined value to $$\n", myname, lineno, input_file_name);
+}
+
+
+undefined_goal(s)
+char *s;
+{
+    fprintf(stderr, "%s: e - the start symbol %s is undefined\n", myname, s);
+    done(1);
+}
+
+
+undefined_symbol_warning(s)
+char *s;
+{
+    fprintf(stderr, "%s: w - the symbol %s is undefined\n", myname, s);
+}
Index: /trunk/minix/commands/byacc/lalr.c
===================================================================
--- /trunk/minix/commands/byacc/lalr.c	(revision 9)
+++ /trunk/minix/commands/byacc/lalr.c	(revision 9)
@@ -0,0 +1,638 @@
+#include "defs.h"
+
+typedef
+  struct shorts
+    {
+      struct shorts *next;
+      short value;
+    }
+  shorts;
+
+int tokensetsize;
+short *lookaheads;
+short *LAruleno;
+unsigned *LA;
+short *accessing_symbol;
+core **state_table;
+shifts **shift_table;
+reductions **reduction_table;
+short *goto_map;
+short *from_state;
+short *to_state;
+
+short **transpose();
+
+static int infinity;
+static int maxrhs;
+static int ngotos;
+static unsigned *F;
+static short **includes;
+static shorts **lookback;
+static short **R;
+static short *INDEX;
+static short *VERTICES;
+static int top;
+
+
+lalr()
+{
+    tokensetsize = WORDSIZE(ntokens);
+
+    set_state_table();
+    set_accessing_symbol();
+    set_shift_table();
+    set_reduction_table();
+    set_maxrhs();
+    initialize_LA();
+    set_goto_map();
+    initialize_F();
+    build_relations();
+    compute_FOLLOWS();
+    compute_lookaheads();
+}
+
+
+
+set_state_table()
+{
+    register core *sp;
+
+    state_table = NEW2(nstates, core *);
+    for (sp = first_state; sp; sp = sp->next)
+	state_table[sp->number] = sp;
+}
+
+
+
+set_accessing_symbol()
+{
+    register core *sp;
+
+    accessing_symbol = NEW2(nstates, short);
+    for (sp = first_state; sp; sp = sp->next)
+	accessing_symbol[sp->number] = sp->accessing_symbol;
+}
+
+
+
+set_shift_table()
+{
+    register shifts *sp;
+
+    shift_table = NEW2(nstates, shifts *);
+    for (sp = first_shift; sp; sp = sp->next)
+	shift_table[sp->number] = sp;
+}
+
+
+
+set_reduction_table()
+{
+    register reductions *rp;
+
+    reduction_table = NEW2(nstates, reductions *);
+    for (rp = first_reduction; rp; rp = rp->next)
+	reduction_table[rp->number] = rp;
+}
+
+
+
+set_maxrhs()
+{
+  register short *itemp;
+  register short *item_end;
+  register int length;
+  register int max;
+
+  length = 0;
+  max = 0;
+  item_end = ritem + nitems;
+  for (itemp = ritem; itemp < item_end; itemp++)
+    {
+      if (*itemp >= 0)
+	{
+	  length++;
+	}
+      else
+	{
+	  if (length > max) max = length;
+	  length = 0;
+	}
+    }
+
+  maxrhs = max;
+}
+
+
+
+initialize_LA()
+{
+  register int i, j, k;
+  register reductions *rp;
+
+  lookaheads = NEW2(nstates + 1, short);
+
+  k = 0;
+  for (i = 0; i < nstates; i++)
+    {
+      lookaheads[i] = k;
+      rp = reduction_table[i];
+      if (rp)
+	k += rp->nreds;
+    }
+  lookaheads[nstates] = k;
+
+  LA = NEW2(k * tokensetsize, unsigned);
+  LAruleno = NEW2(k, short);
+  lookback = NEW2(k, shorts *);
+
+  k = 0;
+  for (i = 0; i < nstates; i++)
+    {
+      rp = reduction_table[i];
+      if (rp)
+	{
+	  for (j = 0; j < rp->nreds; j++)
+	    {
+	      LAruleno[k] = rp->rules[j];
+	      k++;
+	    }
+	}
+    }
+}
+
+
+set_goto_map()
+{
+  register shifts *sp;
+  register int i;
+  register int symbol;
+  register int k;
+  register short *temp_map;
+  register int state2;
+  register int state1;
+
+  goto_map = NEW2(nvars + 1, short) - ntokens;
+  temp_map = NEW2(nvars + 1, short) - ntokens;
+
+  ngotos = 0;
+  for (sp = first_shift; sp; sp = sp->next)
+    {
+      for (i = sp->nshifts - 1; i >= 0; i--)
+	{
+	  symbol = accessing_symbol[sp->shift[i]];
+
+	  if (ISTOKEN(symbol)) break;
+
+	  if (ngotos == MAXSHORT)
+	    fatal("too many gotos");
+
+	  ngotos++;
+	  goto_map[symbol]++;
+        }
+    }
+
+  k = 0;
+  for (i = ntokens; i < nsyms; i++)
+    {
+      temp_map[i] = k;
+      k += goto_map[i];
+    }
+
+  for (i = ntokens; i < nsyms; i++)
+    goto_map[i] = temp_map[i];
+
+  goto_map[nsyms] = ngotos;
+  temp_map[nsyms] = ngotos;
+
+  from_state = NEW2(ngotos, short);
+  to_state = NEW2(ngotos, short);
+
+  for (sp = first_shift; sp; sp = sp->next)
+    {
+      state1 = sp->number;
+      for (i = sp->nshifts - 1; i >= 0; i--)
+	{
+	  state2 = sp->shift[i];
+	  symbol = accessing_symbol[state2];
+
+	  if (ISTOKEN(symbol)) break;
+
+	  k = temp_map[symbol]++;
+	  from_state[k] = state1;
+	  to_state[k] = state2;
+	}
+    }
+
+  FREE(temp_map + ntokens);
+}
+
+
+
+/*  Map_goto maps a state/symbol pair into its numeric representation.	*/
+
+int
+map_goto(state, symbol)
+int state;
+int symbol;
+{
+    register int high;
+    register int low;
+    register int middle;
+    register int s;
+
+    low = goto_map[symbol];
+    high = goto_map[symbol + 1];
+
+    for (;;)
+    {
+	assert(low <= high);
+	middle = (low + high) >> 1;
+	s = from_state[middle];
+	if (s == state)
+	    return (middle);
+	else if (s < state)
+	    low = middle + 1;
+	else
+	    high = middle - 1;
+    }
+}
+
+
+
+initialize_F()
+{
+  register int i;
+  register int j;
+  register int k;
+  register shifts *sp;
+  register short *edge;
+  register unsigned *rowp;
+  register short *rp;
+  register short **reads;
+  register int nedges;
+  register int stateno;
+  register int symbol;
+  register int nwords;
+
+  nwords = ngotos * tokensetsize;
+  F = NEW2(nwords, unsigned);
+
+  reads = NEW2(ngotos, short *);
+  edge = NEW2(ngotos + 1, short);
+  nedges = 0;
+
+  rowp = F;
+  for (i = 0; i < ngotos; i++)
+    {
+      stateno = to_state[i];
+      sp = shift_table[stateno];
+
+      if (sp)
+	{
+	  k = sp->nshifts;
+
+	  for (j = 0; j < k; j++)
+	    {
+	      symbol = accessing_symbol[sp->shift[j]];
+	      if (ISVAR(symbol))
+		break;
+	      SETBIT(rowp, symbol);
+	    }
+
+	  for (; j < k; j++)
+	    {
+	      symbol = accessing_symbol[sp->shift[j]];
+	      if (nullable[symbol])
+		edge[nedges++] = map_goto(stateno, symbol);
+	    }
+	
+	  if (nedges)
+	    {
+	      reads[i] = rp = NEW2(nedges + 1, short);
+
+	      for (j = 0; j < nedges; j++)
+		rp[j] = edge[j];
+
+	      rp[nedges] = -1;
+	      nedges = 0;
+	    }
+	}
+
+      rowp += tokensetsize;
+    }
+
+  SETBIT(F, 0);
+  digraph(reads);
+
+  for (i = 0; i < ngotos; i++)
+    {
+      if (reads[i])
+	FREE(reads[i]);
+    }
+
+  FREE(reads);
+  FREE(edge);
+}
+
+
+
+build_relations()
+{
+  register int i;
+  register int j;
+  register int k;
+  register short *rulep;
+  register short *rp;
+  register shifts *sp;
+  register int length;
+  register int nedges;
+  register int done;
+  register int state1;
+  register int stateno;
+  register int symbol1;
+  register int symbol2;
+  register short *shortp;
+  register short *edge;
+  register short *states;
+  register short **new_includes;
+
+  includes = NEW2(ngotos, short *);
+  edge = NEW2(ngotos + 1, short);
+  states = NEW2(maxrhs + 1, short);
+
+  for (i = 0; i < ngotos; i++)
+    {
+      nedges = 0;
+      state1 = from_state[i];
+      symbol1 = accessing_symbol[to_state[i]];
+
+      for (rulep = derives[symbol1]; *rulep >= 0; rulep++)
+	{
+	  length = 1;
+	  states[0] = state1;
+	  stateno = state1;
+
+	  for (rp = ritem + rrhs[*rulep]; *rp >= 0; rp++)
+	    {
+	      symbol2 = *rp;
+	      sp = shift_table[stateno];
+	      k = sp->nshifts;
+
+	      for (j = 0; j < k; j++)
+		{
+		  stateno = sp->shift[j];
+		  if (accessing_symbol[stateno] == symbol2) break;
+		}
+
+	      states[length++] = stateno;
+	    }
+
+	  add_lookback_edge(stateno, *rulep, i);
+
+	  length--;
+	  done = 0;
+	  while (!done)
+	    {
+	      done = 1;
+	      rp--;
+	      if (ISVAR(*rp))
+		{
+		  stateno = states[--length];
+		  edge[nedges++] = map_goto(stateno, *rp);
+		  if (nullable[*rp] && length > 0) done = 0;
+		}
+	    }
+	}
+
+      if (nedges)
+	{
+	  includes[i] = shortp = NEW2(nedges + 1, short);
+	  for (j = 0; j < nedges; j++)
+	    shortp[j] = edge[j];
+	  shortp[nedges] = -1;
+	}
+    }
+
+  new_includes = transpose(includes, ngotos);
+
+  for (i = 0; i < ngotos; i++)
+    if (includes[i])
+      FREE(includes[i]);
+
+  FREE(includes);
+
+  includes = new_includes;
+
+  FREE(edge);
+  FREE(states);
+}
+
+
+add_lookback_edge(stateno, ruleno, gotono)
+int stateno, ruleno, gotono;
+{
+    register int i, k;
+    register int found;
+    register shorts *sp;
+
+    i = lookaheads[stateno];
+    k = lookaheads[stateno + 1];
+    found = 0;
+    while (!found && i < k)
+    {
+	if (LAruleno[i] == ruleno)
+	    found = 1;
+	else
+	    ++i;
+    }
+    assert(found);
+
+    sp = NEW(shorts);
+    sp->next = lookback[i];
+    sp->value = gotono;
+    lookback[i] = sp;
+}
+
+
+
+short **
+transpose(R, n)
+short **R;
+int n;
+{
+  register short **new_R;
+  register short **temp_R;
+  register short *nedges;
+  register short *sp;
+  register int i;
+  register int k;
+
+  nedges = NEW2(n, short);
+
+  for (i = 0; i < n; i++)
+    {
+      sp = R[i];
+      if (sp)
+	{
+	  while (*sp >= 0)
+	    nedges[*sp++]++;
+	}
+    }
+
+  new_R = NEW2(n, short *);
+  temp_R = NEW2(n, short *);
+
+  for (i = 0; i < n; i++)
+    {
+      k = nedges[i];
+      if (k > 0)
+	{
+	  sp = NEW2(k + 1, short);
+	  new_R[i] = sp;
+	  temp_R[i] = sp;
+	  sp[k] = -1;
+	}
+    }
+
+  FREE(nedges);
+
+  for (i = 0; i < n; i++)
+    {
+      sp = R[i];
+      if (sp)
+	{
+	  while (*sp >= 0)
+	    *temp_R[*sp++]++ = i;
+	}
+    }
+
+  FREE(temp_R);
+
+  return (new_R);
+}
+
+
+
+compute_FOLLOWS()
+{
+  digraph(includes);
+}
+
+
+compute_lookaheads()
+{
+  register int i, n;
+  register unsigned *fp1, *fp2, *fp3;
+  register shorts *sp, *next;
+  register unsigned *rowp;
+
+  rowp = LA;
+  n = lookaheads[nstates];
+  for (i = 0; i < n; i++)
+    {
+      fp3 = rowp + tokensetsize;
+      for (sp = lookback[i]; sp; sp = sp->next)
+	{
+	  fp1 = rowp;
+	  fp2 = F + tokensetsize * sp->value;
+	  while (fp1 < fp3)
+	    *fp1++ |= *fp2++;
+	}
+      rowp = fp3;
+    }
+
+  for (i = 0; i < n; i++)
+    for (sp = lookback[i]; sp; sp = next)
+      {
+        next = sp->next;
+        FREE(sp);
+      }
+
+  FREE(lookback);
+  FREE(F);
+}
+
+
+digraph(relation)
+short **relation;
+{
+  register int i;
+
+  infinity = ngotos + 2;
+  INDEX = NEW2(ngotos + 1, short);
+  VERTICES = NEW2(ngotos + 1, short);
+  top = 0;
+
+  R = relation;
+
+  for (i = 0; i < ngotos; i++)
+    INDEX[i] = 0;
+
+  for (i = 0; i < ngotos; i++)
+    {
+      if (INDEX[i] == 0 && R[i])
+	traverse(i);
+    }
+
+  FREE(INDEX);
+  FREE(VERTICES);
+}
+
+
+
+traverse(i)
+register int i;
+{
+  register unsigned *fp1;
+  register unsigned *fp2;
+  register unsigned *fp3;
+  register int j;
+  register short *rp;
+
+  int height;
+  unsigned *base;
+
+  VERTICES[++top] = i;
+  INDEX[i] = height = top;
+
+  base = F + i * tokensetsize;
+  fp3 = base + tokensetsize;
+
+  rp = R[i];
+  if (rp)
+    {
+      while ((j = *rp++) >= 0)
+	{
+	  if (INDEX[j] == 0)
+	    traverse(j);
+
+	  if (INDEX[i] > INDEX[j])
+	    INDEX[i] = INDEX[j];
+
+	  fp1 = base;
+	  fp2 = F + j * tokensetsize;
+
+	  while (fp1 < fp3)
+	    *fp1++ |= *fp2++;
+	}
+    }
+
+  if (INDEX[i] == height)
+    {
+      for (;;)
+	{
+	  j = VERTICES[top--];
+	  INDEX[j] = infinity;
+
+	  if (i == j)
+	    break;
+
+	  fp1 = base;
+	  fp2 = F + j * tokensetsize;
+
+	  while (fp1 < fp3)
+	    *fp2++ = *fp1++;
+	}
+    }
+}
Index: /trunk/minix/commands/byacc/lr0.c
===================================================================
--- /trunk/minix/commands/byacc/lr0.c	(revision 9)
+++ /trunk/minix/commands/byacc/lr0.c	(revision 9)
@@ -0,0 +1,598 @@
+
+#include "defs.h"
+
+extern short *itemset;
+extern short *itemsetend;
+extern unsigned *ruleset;
+
+int nstates;
+core *first_state;
+shifts *first_shift;
+reductions *first_reduction;
+
+int get_state();
+core *new_state();
+
+static core **state_set;
+static core *this_state;
+static core *last_state;
+static shifts *last_shift;
+static reductions *last_reduction;
+
+static int nshifts;
+static short *shift_symbol;
+
+static short *redset;
+static short *shiftset;
+
+static short **kernel_base;
+static short **kernel_end;
+static short *kernel_items;
+
+
+allocate_itemsets()
+{
+    register short *itemp;
+    register short *item_end;
+    register int symbol;
+    register int i;
+    register int count;
+    register int max;
+    register short *symbol_count;
+
+    count = 0;
+    symbol_count = NEW2(nsyms, short);
+
+    item_end = ritem + nitems;
+    for (itemp = ritem; itemp < item_end; itemp++)
+    {
+	symbol = *itemp;
+	if (symbol >= 0)
+	{
+	    count++;
+	    symbol_count[symbol]++;
+	}
+    }
+
+    kernel_base = NEW2(nsyms, short *);
+    kernel_items = NEW2(count, short);
+
+    count = 0;
+    max = 0;
+    for (i = 0; i < nsyms; i++)
+    {
+	kernel_base[i] = kernel_items + count;
+	count += symbol_count[i];
+	if (max < symbol_count[i])
+	    max = symbol_count[i];
+    }
+
+    shift_symbol = symbol_count;
+    kernel_end = NEW2(nsyms, short *);
+}
+
+
+allocate_storage()
+{
+    allocate_itemsets();
+    shiftset = NEW2(nsyms, short);
+    redset = NEW2(nrules + 1, short);
+    state_set = NEW2(nitems, core *);
+}
+
+
+append_states()
+{
+    register int i;
+    register int j;
+    register int symbol;
+
+#ifdef	TRACE
+    fprintf(stderr, "Entering append_states()\n");
+#endif
+    for (i = 1; i < nshifts; i++)
+    {
+	symbol = shift_symbol[i];
+	j = i;
+	while (j > 0 && shift_symbol[j - 1] > symbol)
+	{
+	    shift_symbol[j] = shift_symbol[j - 1];
+	    j--;
+	}
+	shift_symbol[j] = symbol;
+    }
+
+    for (i = 0; i < nshifts; i++)
+    {
+	symbol = shift_symbol[i];
+	shiftset[i] = get_state(symbol);
+    }
+}
+
+
+free_storage()
+{
+    FREE(shift_symbol);
+    FREE(redset);
+    FREE(shiftset);
+    FREE(kernel_base);
+    FREE(kernel_end);
+    FREE(kernel_items);
+    FREE(state_set);
+}
+
+
+
+generate_states()
+{
+    allocate_storage();
+    itemset = NEW2(nitems, short);
+    ruleset = NEW2(WORDSIZE(nrules), unsigned);
+    set_first_derives();
+    initialize_states();
+
+    while (this_state)
+    {
+	closure(this_state->items, this_state->nitems);
+	save_reductions();
+	new_itemsets();
+	append_states();
+
+	if (nshifts > 0)
+	    save_shifts();
+
+	this_state = this_state->next;
+    }
+
+    finalize_closure();
+    free_storage();
+}
+
+
+
+int
+get_state(symbol)
+int symbol;
+{
+    register int key;
+    register short *isp1;
+    register short *isp2;
+    register short *iend;
+    register core *sp;
+    register int found;
+    register int n;
+
+#ifdef	TRACE
+    fprintf(stderr, "Entering get_state(%d)\n", symbol);
+#endif
+
+    isp1 = kernel_base[symbol];
+    iend = kernel_end[symbol];
+    n = iend - isp1;
+
+    key = *isp1;
+    assert(0 <= key && key < nitems);
+    sp = state_set[key];
+    if (sp)
+    {
+	found = 0;
+	while (!found)
+	{
+	    if (sp->nitems == n)
+	    {
+		found = 1;
+		isp1 = kernel_base[symbol];
+		isp2 = sp->items;
+
+		while (found && isp1 < iend)
+		{
+		    if (*isp1++ != *isp2++)
+			found = 0;
+		}
+	    }
+
+	    if (!found)
+	    {
+		if (sp->link)
+		{
+		    sp = sp->link;
+		}
+		else
+		{
+		    sp = sp->link = new_state(symbol);
+		    found = 1;
+		}
+	    }
+	}
+    }
+    else
+    {
+	state_set[key] = sp = new_state(symbol);
+    }
+
+    return (sp->number);
+}
+
+
+
+initialize_states()
+{
+    register int i;
+    register short *start_derives;
+    register core *p;
+
+    start_derives = derives[start_symbol];
+    for (i = 0; start_derives[i] >= 0; ++i)
+	continue;
+
+    p = (core *) MALLOC(sizeof(core) + i*sizeof(short));
+    if (p == 0) no_space();
+
+    p->next = 0;
+    p->link = 0;
+    p->number = 0;
+    p->accessing_symbol = 0;
+    p->nitems = i;
+
+    for (i = 0;  start_derives[i] >= 0; ++i)
+	p->items[i] = rrhs[start_derives[i]];
+
+    first_state = last_state = this_state = p;
+    nstates = 1;
+}
+
+
+new_itemsets()
+{
+    register int i;
+    register int shiftcount;
+    register short *isp;
+    register short *ksp;
+    register int symbol;
+
+    for (i = 0; i < nsyms; i++)
+	kernel_end[i] = 0;
+
+    shiftcount = 0;
+    isp = itemset;
+    while (isp < itemsetend)
+    {
+	i = *isp++;
+	symbol = ritem[i];
+	if (symbol > 0)
+	{
+	    ksp = kernel_end[symbol];
+	    if (!ksp)
+	    {
+		shift_symbol[shiftcount++] = symbol;
+		ksp = kernel_base[symbol];
+	    }
+
+	    *ksp++ = i + 1;
+	    kernel_end[symbol] = ksp;
+	}
+    }
+
+    nshifts = shiftcount;
+}
+
+
+
+core *
+new_state(symbol)
+int symbol;
+{
+    register int n;
+    register core *p;
+    register short *isp1;
+    register short *isp2;
+    register short *iend;
+
+#ifdef	TRACE
+    fprintf(stderr, "Entering new_state(%d)\n", symbol);
+#endif
+
+    if (nstates >= MAXSHORT)
+	fatal("too many states");
+
+    isp1 = kernel_base[symbol];
+    iend = kernel_end[symbol];
+    n = iend - isp1;
+
+    p = (core *) allocate((unsigned) (sizeof(core) + (n - 1) * sizeof(short)));
+    p->accessing_symbol = symbol;
+    p->number = nstates;
+    p->nitems = n;
+
+    isp2 = p->items;
+    while (isp1 < iend)
+	*isp2++ = *isp1++;
+
+    last_state->next = p;
+    last_state = p;
+
+    nstates++;
+
+    return (p);
+}
+
+
+/* show_cores is used for debugging */
+
+show_cores()
+{
+    core *p;
+    int i, j, k, n;
+    int itemno;
+
+    k = 0;
+    for (p = first_state; p; ++k, p = p->next)
+    {
+	if (k) printf("\n");
+	printf("state %d, number = %d, accessing symbol = %s\n",
+		k, p->number, symbol_name[p->accessing_symbol]);
+	n = p->nitems;
+	for (i = 0; i < n; ++i)
+	{
+	    itemno = p->items[i];
+	    printf("%4d  ", itemno);
+	    j = itemno;
+	    while (ritem[j] >= 0) ++j;
+	    printf("%s :", symbol_name[rlhs[-ritem[j]]]);
+	    j = rrhs[-ritem[j]];
+	    while (j < itemno)
+		printf(" %s", symbol_name[ritem[j++]]);
+	    printf(" .");
+	    while (ritem[j] >= 0)
+		printf(" %s", symbol_name[ritem[j++]]);
+	    printf("\n");
+	    fflush(stdout);
+	}
+    }
+}
+
+
+/* show_ritems is used for debugging */
+
+show_ritems()
+{
+    int i;
+
+    for (i = 0; i < nitems; ++i)
+	printf("ritem[%d] = %d\n", i, ritem[i]);
+}
+
+
+/* show_rrhs is used for debugging */
+show_rrhs()
+{
+    int i;
+
+    for (i = 0; i < nrules; ++i)
+	printf("rrhs[%d] = %d\n", i, rrhs[i]);
+}
+
+
+/* show_shifts is used for debugging */
+
+show_shifts()
+{
+    shifts *p;
+    int i, j, k;
+
+    k = 0;
+    for (p = first_shift; p; ++k, p = p->next)
+    {
+	if (k) printf("\n");
+	printf("shift %d, number = %d, nshifts = %d\n", k, p->number,
+		p->nshifts);
+	j = p->nshifts;
+	for (i = 0; i < j; ++i)
+	    printf("\t%d\n", p->shift[i]);
+    }
+}
+
+
+save_shifts()
+{
+    register shifts *p;
+    register short *sp1;
+    register short *sp2;
+    register short *send;
+
+    p = (shifts *) allocate((unsigned) (sizeof(shifts) +
+			(nshifts - 1) * sizeof(short)));
+
+    p->number = this_state->number;
+    p->nshifts = nshifts;
+
+    sp1 = shiftset;
+    sp2 = p->shift;
+    send = shiftset + nshifts;
+
+    while (sp1 < send)
+	*sp2++ = *sp1++;
+
+    if (last_shift)
+    {
+	last_shift->next = p;
+	last_shift = p;
+    }
+    else
+    {
+	first_shift = p;
+	last_shift = p;
+    }
+}
+
+
+
+save_reductions()
+{
+    register short *isp;
+    register short *rp1;
+    register short *rp2;
+    register int item;
+    register int count;
+    register reductions *p;
+    register short *rend;
+
+    count = 0;
+    for (isp = itemset; isp < itemsetend; isp++)
+    {
+	item = ritem[*isp];
+	if (item < 0)
+	{
+	    redset[count++] = -item;
+	}
+    }
+
+    if (count)
+    {
+	p = (reductions *) allocate((unsigned) (sizeof(reductions) +
+					(count - 1) * sizeof(short)));
+
+	p->number = this_state->number;
+	p->nreds = count;
+
+	rp1 = redset;
+	rp2 = p->rules;
+	rend = rp1 + count;
+
+	while (rp1 < rend)
+	    *rp2++ = *rp1++;
+
+	if (last_reduction)
+	{
+	    last_reduction->next = p;
+	    last_reduction = p;
+	}
+	else
+	{
+	    first_reduction = p;
+	    last_reduction = p;
+	}
+    }
+}
+
+
+set_derives()
+{
+    register int i, k;
+    register int lhs;
+    register short *rules;
+
+    derives = NEW2(nsyms, short *);
+    rules = NEW2(nvars + nrules, short);
+
+    k = 0;
+    for (lhs = start_symbol; lhs < nsyms; lhs++)
+    {
+	derives[lhs] = rules + k;
+	for (i = 0; i < nrules; i++)
+	{
+	    if (rlhs[i] == lhs)
+	    {
+		rules[k] = i;
+		k++;
+	    }
+	}
+	rules[k] = -1;
+	k++;
+    }
+
+#ifdef	DEBUG
+    print_derives();
+#endif
+}
+
+free_derives()
+{
+    FREE(derives[start_symbol]);
+    FREE(derives);
+}
+
+#ifdef	DEBUG
+print_derives()
+{
+    register int i;
+    register short *sp;
+
+    printf("\nDERIVES\n\n");
+
+    for (i = start_symbol; i < nsyms; i++)
+    {
+	printf("%s derives ", symbol_name[i]);
+	for (sp = derives[i]; *sp >= 0; sp++)
+	{
+	    printf("  %d", *sp);
+	}
+	putchar('\n');
+    }
+
+    putchar('\n');
+}
+#endif
+
+
+set_nullable()
+{
+    register int i, j;
+    register int empty;
+    int done;
+
+    nullable = MALLOC(nsyms);
+    if (nullable == 0) no_space();
+
+    for (i = 0; i < nsyms; ++i)
+	nullable[i] = 0;
+
+    done = 0;
+    while (!done)
+    {
+	done = 1;
+	for (i = 1; i < nitems; i++)
+	{
+	    empty = 1;
+	    while ((j = ritem[i]) >= 0)
+	    {
+		if (!nullable[j])
+		    empty = 0;
+		++i;
+	    }
+	    if (empty)
+	    {
+		j = rlhs[-j];
+		if (!nullable[j])
+		{
+		    nullable[j] = 1;
+		    done = 0;
+		}
+	    }
+	}
+    }
+
+#ifdef DEBUG
+    for (i = 0; i < nsyms; i++)
+    {
+	if (nullable[i])
+	    printf("%s is nullable\n", symbol_name[i]);
+	else
+	    printf("%s is not nullable\n", symbol_name[i]);
+    }
+#endif
+}
+
+
+free_nullable()
+{
+    FREE(nullable);
+}
+
+
+lr0()
+{
+    set_derives();
+    set_nullable();
+    generate_states();
+}
Index: /trunk/minix/commands/byacc/main.c
===================================================================
--- /trunk/minix/commands/byacc/main.c	(revision 9)
+++ /trunk/minix/commands/byacc/main.c	(revision 9)
@@ -0,0 +1,378 @@
+#include <sys/types.h>
+#include <signal.h>
+#include "defs.h"
+
+char dflag;
+char lflag;
+char rflag;
+char tflag;
+char vflag;
+
+char *symbol_prefix;
+char *file_prefix = "y";
+char *myname = "yacc";
+char *temp_form = "yacc.XXXXXXX";
+
+int lineno;
+int outline;
+
+char *action_file_name;
+char *code_file_name;
+char *defines_file_name;
+char *input_file_name = "";
+char *output_file_name;
+char *text_file_name;
+char *union_file_name;
+char *verbose_file_name;
+
+FILE *action_file;	/*  a temp file, used to save actions associated    */
+			/*  with rules until the parser is written	    */
+FILE *code_file;	/*  y.code.c (used when the -r option is specified) */
+FILE *defines_file;	/*  y.tab.h					    */
+FILE *input_file;	/*  the input file				    */
+FILE *output_file;	/*  y.tab.c					    */
+FILE *text_file;	/*  a temp file, used to save text until all	    */
+			/*  symbols have been defined			    */
+FILE *union_file;	/*  a temp file, used to save the union		    */
+			/*  definition until all symbol have been	    */
+			/*  defined					    */
+FILE *verbose_file;	/*  y.output					    */
+
+int nitems;
+int nrules;
+int nsyms;
+int ntokens;
+int nvars;
+
+int   start_symbol;
+char  **symbol_name;
+short *symbol_value;
+short *symbol_prec;
+char  *symbol_assoc;
+
+short *ritem;
+short *rlhs;
+short *rrhs;
+short *rprec;
+char  *rassoc;
+short **derives;
+char *nullable;
+
+extern char *mktemp();
+extern char *getenv();
+
+
+done(k)
+int k;
+{
+    if (action_file) { fclose(action_file); unlink(action_file_name); }
+    if (text_file) { fclose(text_file); unlink(text_file_name); }
+    if (union_file) { fclose(union_file); unlink(union_file_name); }
+    exit(k);
+}
+
+
+void
+onintr(signo)
+    int signo;
+{
+    done(1);
+}
+
+
+set_signals()
+{
+#ifdef SIGINT
+    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+	signal(SIGINT, onintr);
+#endif
+#ifdef SIGTERM
+    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
+	signal(SIGTERM, onintr);
+#endif
+#ifdef SIGHUP
+    if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
+	signal(SIGHUP, onintr);
+#endif
+}
+
+
+usage()
+{
+    fprintf(stderr, "usage: %s [-dlrtv] [-b file_prefix] [-p symbol_prefix] filename\n", myname);
+    exit(1);
+}
+
+
+getargs(argc, argv)
+int argc;
+char *argv[];
+{
+    register int i;
+    register char *s;
+
+    if (argc > 0) myname = argv[0];
+    for (i = 1; i < argc; ++i)
+    {
+	s = argv[i];
+	if (*s != '-') break;
+	switch (*++s)
+	{
+	case '\0':
+	    input_file = stdin;
+	    if (i + 1 < argc) usage();
+	    return;
+
+	case '-':
+	    ++i;
+	    goto no_more_options;
+
+	case 'b':
+	    if (*++s)
+		 file_prefix = s;
+	    else if (++i < argc)
+		file_prefix = argv[i];
+	    else
+		usage();
+	    continue;
+
+	case 'd':
+	    dflag = 1;
+	    break;
+
+	case 'l':
+	    lflag = 1;
+	    break;
+
+	case 'p':
+	    if (*++s)
+		symbol_prefix = s;
+	    else if (++i < argc)
+		symbol_prefix = argv[i];
+	    else
+		usage();
+	    continue;
+
+	case 'r':
+	    rflag = 1;
+	    break;
+
+	case 't':
+	    tflag = 1;
+	    break;
+
+	case 'v':
+	    vflag = 1;
+	    break;
+
+	default:
+	    usage();
+	}
+
+	for (;;)
+	{
+	    switch (*++s)
+	    {
+	    case '\0':
+		goto end_of_option;
+
+	    case 'd':
+		dflag = 1;
+		break;
+
+	    case 'l':
+		lflag = 1;
+		break;
+
+	    case 'r':
+		rflag = 1;
+		break;
+
+	    case 't':
+		tflag = 1;
+		break;
+
+	    case 'v':
+		vflag = 1;
+		break;
+
+	    default:
+		usage();
+	    }
+	}
+end_of_option:;
+    }
+
+no_more_options:;
+    if (i + 1 != argc) usage();
+    input_file_name = argv[i];
+}
+
+
+char *
+allocate(n)
+unsigned n;
+{
+    register char *p;
+
+    p = NULL;
+    if (n)
+    {
+	p = CALLOC(1, n);
+	if (!p) no_space();
+    }
+    return (p);
+}
+
+
+create_file_names()
+{
+    int i, len;
+    char *tmpdir;
+
+    tmpdir = getenv("TMPDIR");
+    if (tmpdir == 0) tmpdir = "/tmp";
+
+    len = strlen(tmpdir);
+    i = len + 13;
+    if (len && tmpdir[len-1] != '/')
+	++i;
+
+    action_file_name = MALLOC(i);
+    if (action_file_name == 0) no_space();
+    text_file_name = MALLOC(i);
+    if (text_file_name == 0) no_space();
+    union_file_name = MALLOC(i);
+    if (union_file_name == 0) no_space();
+
+    strcpy(action_file_name, tmpdir);
+    strcpy(text_file_name, tmpdir);
+    strcpy(union_file_name, tmpdir);
+
+    if (len && tmpdir[len - 1] != '/')
+    {
+	action_file_name[len] = '/';
+	text_file_name[len] = '/';
+	union_file_name[len] = '/';
+	++len;
+    }
+
+    strcpy(action_file_name + len, temp_form);
+    strcpy(text_file_name + len, temp_form);
+    strcpy(union_file_name + len, temp_form);
+
+    action_file_name[len + 5] = 'a';
+    text_file_name[len + 5] = 't';
+    union_file_name[len + 5] = 'u';
+
+    mktemp(action_file_name);
+    mktemp(text_file_name);
+    mktemp(union_file_name);
+
+    len = strlen(file_prefix);
+
+    output_file_name = MALLOC(len + 7);
+    if (output_file_name == 0)
+	no_space();
+    strcpy(output_file_name, file_prefix);
+    strcpy(output_file_name + len, OUTPUT_SUFFIX);
+
+    if (rflag)
+    {
+	code_file_name = MALLOC(len + 8);
+	if (code_file_name == 0)
+	    no_space();
+	strcpy(code_file_name, file_prefix);
+	strcpy(code_file_name + len, CODE_SUFFIX);
+    }
+    else
+	code_file_name = output_file_name;
+
+    if (dflag)
+    {
+	defines_file_name = MALLOC(len + 7);
+	if (defines_file_name == 0)
+	    no_space();
+	strcpy(defines_file_name, file_prefix);
+	strcpy(defines_file_name + len, DEFINES_SUFFIX);
+    }
+
+    if (vflag)
+    {
+	verbose_file_name = MALLOC(len + 8);
+	if (verbose_file_name == 0)
+	    no_space();
+	strcpy(verbose_file_name, file_prefix);
+	strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
+    }
+}
+
+
+open_files()
+{
+    create_file_names();
+
+    if (input_file == 0)
+    {
+	input_file = fopen(input_file_name, "r");
+	if (input_file == 0)
+	    open_error(input_file_name);
+    }
+
+    action_file = fopen(action_file_name, "w");
+    if (action_file == 0)
+	open_error(action_file_name);
+
+    text_file = fopen(text_file_name, "w");
+    if (text_file == 0)
+	open_error(text_file_name);
+
+    if (vflag)
+    {
+	verbose_file = fopen(verbose_file_name, "w");
+	if (verbose_file == 0)
+	    open_error(verbose_file_name);
+    }
+
+    if (dflag)
+    {
+	defines_file = fopen(defines_file_name, "w");
+	if (defines_file == 0)
+	    open_error(defines_file_name);
+	union_file = fopen(union_file_name, "w");
+	if (union_file ==  0)
+	    open_error(union_file_name);
+    }
+
+    output_file = fopen(output_file_name, "w");
+    if (output_file == 0)
+	open_error(output_file_name);
+
+    if (rflag)
+    {
+	code_file = fopen(code_file_name, "w");
+	if (code_file == 0)
+	    open_error(code_file_name);
+    }
+    else
+	code_file = output_file;
+}
+
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+    set_signals();
+    getargs(argc, argv);
+    open_files();
+    reader();
+    lr0();
+    lalr();
+    make_parser();
+    verbose();
+    output();
+    done(0);
+    /*NOTREACHED*/
+}
Index: /trunk/minix/commands/byacc/mkpar.c
===================================================================
--- /trunk/minix/commands/byacc/mkpar.c	(revision 9)
+++ /trunk/minix/commands/byacc/mkpar.c	(revision 9)
@@ -0,0 +1,357 @@
+
+#include "defs.h"
+
+action **parser;
+int SRtotal;
+int RRtotal;
+short *SRconflicts;
+short *RRconflicts;
+short *defred;
+short *rules_used;
+short nunused;
+short final_state;
+
+static int SRcount;
+static int RRcount;
+
+extern action *parse_actions();
+extern action *get_shifts();
+extern action *add_reductions();
+extern action *add_reduce();
+
+
+make_parser()
+{
+    register int i;
+
+    parser = NEW2(nstates, action *);
+    for (i = 0; i < nstates; i++)
+	parser[i] = parse_actions(i);
+
+    find_final_state();
+    remove_conflicts();
+    unused_rules();
+    if (SRtotal + RRtotal > 0) total_conflicts();
+    defreds();
+}
+
+
+action *
+parse_actions(stateno)
+register int stateno;
+{
+    register action *actions;
+
+    actions = get_shifts(stateno);
+    actions = add_reductions(stateno, actions);
+    return (actions);
+}
+
+
+action *
+get_shifts(stateno)
+int stateno;
+{
+    register action *actions, *temp;
+    register shifts *sp;
+    register short *to_state;
+    register int i, k;
+    register int symbol;
+
+    actions = 0;
+    sp = shift_table[stateno];
+    if (sp)
+    {
+	to_state = sp->shift;
+	for (i = sp->nshifts - 1; i >= 0; i--)
+	{
+	    k = to_state[i];
+	    symbol = accessing_symbol[k];
+	    if (ISTOKEN(symbol))
+	    {
+		temp = NEW(action);
+		temp->next = actions;
+		temp->symbol = symbol;
+		temp->number = k;
+		temp->prec = symbol_prec[symbol];
+		temp->action_code = SHIFT;
+		temp->assoc = symbol_assoc[symbol];
+		actions = temp;
+	    }
+	}
+    }
+    return (actions);
+}
+
+action *
+add_reductions(stateno, actions)
+int stateno;
+register action *actions;
+{
+    register int i, j, m, n;
+    register int ruleno, tokensetsize;
+    register unsigned *rowp;
+
+    tokensetsize = WORDSIZE(ntokens);
+    m = lookaheads[stateno];
+    n = lookaheads[stateno + 1];
+    for (i = m; i < n; i++)
+    {
+	ruleno = LAruleno[i];
+	rowp = LA + i * tokensetsize;
+	for (j = ntokens - 1; j >= 0; j--)
+	{
+	    if (BIT(rowp, j))
+		actions = add_reduce(actions, ruleno, j);
+	}
+    }
+    return (actions);
+}
+
+
+action *
+add_reduce(actions, ruleno, symbol)
+register action *actions;
+register int ruleno, symbol;
+{
+    register action *temp, *prev, *next;
+
+    prev = 0;
+    for (next = actions; next && next->symbol < symbol; next = next->next)
+	prev = next;
+
+    while (next && next->symbol == symbol && next->action_code == SHIFT)
+    {
+	prev = next;
+	next = next->next;
+    }
+
+    while (next && next->symbol == symbol &&
+	    next->action_code == REDUCE && next->number < ruleno)
+    {
+	prev = next;
+	next = next->next;
+    }
+
+    temp = NEW(action);
+    temp->next = next;
+    temp->symbol = symbol;
+    temp->number = ruleno;
+    temp->prec = rprec[ruleno];
+    temp->action_code = REDUCE;
+    temp->assoc = rassoc[ruleno];
+
+    if (prev)
+	prev->next = temp;
+    else
+	actions = temp;
+
+    return (actions);
+}
+
+
+find_final_state()
+{
+    register int goal, i;
+    register short *to_state;
+    register shifts *p;
+
+    p = shift_table[0];
+    to_state = p->shift;
+    goal = ritem[1];
+    for (i = p->nshifts - 1; i >= 0; --i)
+    {
+	final_state = to_state[i];
+	if (accessing_symbol[final_state] == goal) break;
+    }
+}
+
+
+unused_rules()
+{
+    register int i;
+    register action *p;
+
+    rules_used = (short *) MALLOC(nrules*sizeof(short));
+    if (rules_used == 0) no_space();
+
+    for (i = 0; i < nrules; ++i)
+	rules_used[i] = 0;
+
+    for (i = 0; i < nstates; ++i)
+    {
+	for (p = parser[i]; p; p = p->next)
+	{
+	    if (p->action_code == REDUCE && p->suppressed == 0)
+		rules_used[p->number] = 1;
+	}
+    }
+
+    nunused = 0;
+    for (i = 3; i < nrules; ++i)
+	if (!rules_used[i]) ++nunused;
+
+    if (nunused)
+	if (nunused == 1)
+	    fprintf(stderr, "%s: 1 rule never reduced\n", myname);
+	else
+	    fprintf(stderr, "%s: %d rules never reduced\n", myname, nunused);
+}
+
+
+remove_conflicts()
+{
+    register int i;
+    register int symbol;
+    register action *p, *pref;
+
+    SRtotal = 0;
+    RRtotal = 0;
+    SRconflicts = NEW2(nstates, short);
+    RRconflicts = NEW2(nstates, short);
+    for (i = 0; i < nstates; i++)
+    {
+	SRcount = 0;
+	RRcount = 0;
+	symbol = -1;
+	for (p = parser[i]; p; p = p->next)
+	{
+	    if (p->symbol != symbol)
+	    {
+		pref = p;
+		symbol = p->symbol;
+	    }
+	    else if (i == final_state && symbol == 0)
+	    {
+		SRcount++;
+		p->suppressed = 1;
+	    }
+	    else if (pref->action_code == SHIFT)
+	    {
+		if (pref->prec > 0 && p->prec > 0)
+		{
+		    if (pref->prec < p->prec)
+		    {
+			pref->suppressed = 2;
+			pref = p;
+		    }
+		    else if (pref->prec > p->prec)
+		    {
+			p->suppressed = 2;
+		    }
+		    else if (pref->assoc == LEFT)
+		    {
+			pref->suppressed = 2;
+			pref = p;
+		    }
+		    else if (pref->assoc == RIGHT)
+		    {
+			p->suppressed = 2;
+		    }
+		    else
+		    {
+			pref->suppressed = 2;
+			p->suppressed = 2;
+		    }
+		}
+		else
+		{
+		    SRcount++;
+		    p->suppressed = 1;
+		}
+	    }
+	    else
+	    {
+		RRcount++;
+		p->suppressed = 1;
+	    }
+	}
+	SRtotal += SRcount;
+	RRtotal += RRcount;
+	SRconflicts[i] = SRcount;
+	RRconflicts[i] = RRcount;
+    }
+}
+
+
+total_conflicts()
+{
+    fprintf(stderr, "%s: ", myname);
+    if (SRtotal == 1)
+	fprintf(stderr, "1 shift/reduce conflict");
+    else if (SRtotal > 1)
+	fprintf(stderr, "%d shift/reduce conflicts", SRtotal);
+
+    if (SRtotal && RRtotal)
+	fprintf(stderr, ", ");
+
+    if (RRtotal == 1)
+	fprintf(stderr, "1 reduce/reduce conflict");
+    else if (RRtotal > 1)
+	fprintf(stderr, "%d reduce/reduce conflicts", RRtotal);
+
+    fprintf(stderr, ".\n");
+}
+
+
+int
+sole_reduction(stateno)
+int stateno;
+{
+    register int count, ruleno;
+    register action *p;
+
+    count = 0;
+    ruleno = 0; 
+    for (p = parser[stateno]; p; p = p->next)
+    {
+	if (p->action_code == SHIFT && p->suppressed == 0)
+	    return (0);
+	else if (p->action_code == REDUCE && p->suppressed == 0)
+	{
+	    if (ruleno > 0 && p->number != ruleno)
+		return (0);
+	    if (p->symbol != 1)
+		++count;
+	    ruleno = p->number;
+	}
+    }
+
+    if (count == 0)
+	return (0);
+    return (ruleno);
+}
+
+
+defreds()
+{
+    register int i;
+
+    defred = NEW2(nstates, short);
+    for (i = 0; i < nstates; i++)
+	defred[i] = sole_reduction(i);
+}
+ 
+free_action_row(p)
+register action *p;
+{
+  register action *q;
+
+  while (p)
+    {
+      q = p->next;
+      FREE(p);
+      p = q;
+    }
+}
+
+free_parser()
+{
+  register int i;
+
+  for (i = 0; i < nstates; i++)
+    free_action_row(parser[i]);
+
+  FREE(parser);
+}
+
Index: /trunk/minix/commands/byacc/output.c
===================================================================
--- /trunk/minix/commands/byacc/output.c	(revision 9)
+++ /trunk/minix/commands/byacc/output.c	(revision 9)
@@ -0,0 +1,1210 @@
+#include "defs.h"
+
+static int nvectors;
+static int nentries;
+static short **froms;
+static short **tos;
+static short *tally;
+static short *width;
+static short *state_count;
+static short *order;
+static short *base;
+static short *pos;
+static int maxtable;
+static short *table;
+static short *check;
+static int lowzero;
+static int high;
+
+
+output()
+{
+    free_itemsets();
+    free_shifts();
+    free_reductions();
+    output_prefix();
+    output_stored_text();
+    output_defines();
+    output_rule_data();
+    output_yydefred();
+    output_actions();
+    free_parser();
+    output_debug();
+    output_stype();
+    if (rflag) write_section(tables);
+    write_section(header);
+    output_trailing_text();
+    write_section(body);
+    output_semantic_actions();
+    write_section(trailer);
+}
+
+
+output_prefix()
+{
+    if (symbol_prefix == NULL)
+	symbol_prefix = "yy";
+    else
+    {
+	++outline;
+	fprintf(code_file, "#define yyparse %sparse\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yylex %slex\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yyerror %serror\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yychar %schar\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yyval %sval\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yylval %slval\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yydebug %sdebug\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yynerrs %snerrs\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yyerrflag %serrflag\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yyss %sss\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yyssp %sssp\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yyvs %svs\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yyvsp %svsp\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yylhs %slhs\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yylen %slen\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yydefred %sdefred\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yydgoto %sdgoto\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yysindex %ssindex\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yyrindex %srindex\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yygindex %sgindex\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yytable %stable\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yycheck %scheck\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yyname %sname\n", symbol_prefix);
+	++outline;
+	fprintf(code_file, "#define yyrule %srule\n", symbol_prefix);
+    }
+    ++outline;
+    fprintf(code_file, "#define YYPREFIX \"%s\"\n", symbol_prefix);
+}
+
+
+output_rule_data()
+{
+    register int i;
+    register int j;
+
+  
+    fprintf(output_file, "short %slhs[] = {%42d,", symbol_prefix,
+	    symbol_value[start_symbol]);
+
+    j = 10;
+    for (i = 3; i < nrules; i++)
+    {
+	if (j >= 10)
+	{
+	    if (!rflag) ++outline;
+	    putc('\n', output_file);
+	    j = 1;
+	}
+        else
+	    ++j;
+
+        fprintf(output_file, "%5d,", symbol_value[rlhs[i]]);
+    }
+    if (!rflag) outline += 2;
+    fprintf(output_file, "\n};\n");
+
+    fprintf(output_file, "short %slen[] = {%42d,", symbol_prefix, 2);
+
+    j = 10;
+    for (i = 3; i < nrules; i++)
+    {
+	if (j >= 10)
+	{
+	    if (!rflag) ++outline;
+	    putc('\n', output_file);
+	    j = 1;
+	}
+	else
+	  j++;
+
+        fprintf(output_file, "%5d,", rrhs[i + 1] - rrhs[i] - 1);
+    }
+    if (!rflag) outline += 2;
+    fprintf(output_file, "\n};\n");
+}
+
+
+output_yydefred()
+{
+    register int i, j;
+
+    fprintf(output_file, "short %sdefred[] = {%39d,", symbol_prefix,
+	    (defred[0] ? defred[0] - 2 : 0));
+
+    j = 10;
+    for (i = 1; i < nstates; i++)
+    {
+	if (j < 10)
+	    ++j;
+	else
+	{
+	    if (!rflag) ++outline;
+	    putc('\n', output_file);
+	    j = 1;
+	}
+
+	fprintf(output_file, "%5d,", (defred[i] ? defred[i] - 2 : 0));
+    }
+
+    if (!rflag) outline += 2;
+    fprintf(output_file, "\n};\n");
+}
+
+
+output_actions()
+{
+    nvectors = 2*nstates + nvars;
+
+    froms = NEW2(nvectors, short *);
+    tos = NEW2(nvectors, short *);
+    tally = NEW2(nvectors, short);
+    width = NEW2(nvectors, short);
+
+    token_actions();
+    FREE(lookaheads);
+    FREE(LA);
+    FREE(LAruleno);
+    FREE(accessing_symbol);
+
+    goto_actions();
+    FREE(goto_map + ntokens);
+    FREE(from_state);
+    FREE(to_state);
+
+    sort_actions();
+    pack_table();
+    output_base();
+    output_table();
+    output_check();
+}
+
+
+token_actions()
+{
+    register int i, j;
+    register int shiftcount, reducecount;
+    register int max, min;
+    register short *actionrow, *r, *s;
+    register action *p;
+
+    actionrow = NEW2(2*ntokens, short);
+    for (i = 0; i < nstates; ++i)
+    {
+	if (parser[i])
+	{
+	    for (j = 0; j < 2*ntokens; ++j)
+	    actionrow[j] = 0;
+
+	    shiftcount = 0;
+	    reducecount = 0;
+	    for (p = parser[i]; p; p = p->next)
+	    {
+		if (p->suppressed == 0)
+		{
+		    if (p->action_code == SHIFT)
+		    {
+			++shiftcount;
+			actionrow[p->symbol] = p->number;
+		    }
+		    else if (p->action_code == REDUCE && p->number != defred[i])
+		    {
+			++reducecount;
+			actionrow[p->symbol + ntokens] = p->number;
+		    }
+		}
+	    }
+
+	    tally[i] = shiftcount;
+	    tally[nstates+i] = reducecount;
+	    width[i] = 0;
+	    width[nstates+i] = 0;
+	    if (shiftcount > 0)
+	    {
+		froms[i] = r = NEW2(shiftcount, short);
+		tos[i] = s = NEW2(shiftcount, short);
+		min = MAXSHORT;
+		max = 0;
+		for (j = 0; j < ntokens; ++j)
+		{
+		    if (actionrow[j])
+		    {
+			if (min > symbol_value[j])
+			    min = symbol_value[j];
+			if (max < symbol_value[j])
+			    max = symbol_value[j];
+			*r++ = symbol_value[j];
+			*s++ = actionrow[j];
+		    }
+		}
+		width[i] = max - min + 1;
+	    }
+	    if (reducecount > 0)
+	    {
+		froms[nstates+i] = r = NEW2(reducecount, short);
+		tos[nstates+i] = s = NEW2(reducecount, short);
+		min = MAXSHORT;
+		max = 0;
+		for (j = 0; j < ntokens; ++j)
+		{
+		    if (actionrow[ntokens+j])
+		    {
+			if (min > symbol_value[j])
+			    min = symbol_value[j];
+			if (max < symbol_value[j])
+			    max = symbol_value[j];
+			*r++ = symbol_value[j];
+			*s++ = actionrow[ntokens+j] - 2;
+		    }
+		}
+		width[nstates+i] = max - min + 1;
+	    }
+	}
+    }
+    FREE(actionrow);
+}
+
+goto_actions()
+{
+    register int i, j, k;
+
+    state_count = NEW2(nstates, short);
+
+    k = default_goto(start_symbol + 1);
+    fprintf(output_file, "short %sdgoto[] = {%40d,", symbol_prefix, k);
+    save_column(start_symbol + 1, k);
+
+    j = 10;
+    for (i = start_symbol + 2; i < nsyms; i++)
+    {
+	if (j >= 10)
+	{
+	    if (!rflag) ++outline;
+	    putc('\n', output_file);
+	    j = 1;
+	}
+	else
+	    ++j;
+
+	k = default_goto(i);
+	fprintf(output_file, "%5d,", k);
+	save_column(i, k);
+    }
+
+    if (!rflag) outline += 2;
+    fprintf(output_file, "\n};\n");
+    FREE(state_count);
+}
+
+int
+default_goto(symbol)
+int symbol;
+{
+    register int i;
+    register int m;
+    register int n;
+    register int default_state;
+    register int max;
+
+    m = goto_map[symbol];
+    n = goto_map[symbol + 1];
+
+    if (m == n) return (0);
+
+    for (i = 0; i < nstates; i++)
+	state_count[i] = 0;
+
+    for (i = m; i < n; i++)
+	state_count[to_state[i]]++;
+
+    max = 0;
+    default_state = 0;
+    for (i = 0; i < nstates; i++)
+    {
+	if (state_count[i] > max)
+	{
+	    max = state_count[i];
+	    default_state = i;
+	}
+    }
+
+    return (default_state);
+}
+
+
+
+save_column(symbol, default_state)
+int symbol;
+int default_state;
+{
+    register int i;
+    register int m;
+    register int n;
+    register short *sp;
+    register short *sp1;
+    register short *sp2;
+    register int count;
+    register int symno;
+
+    m = goto_map[symbol];
+    n = goto_map[symbol + 1];
+
+    count = 0;
+    for (i = m; i < n; i++)
+    {
+	if (to_state[i] != default_state)
+	    ++count;
+    }
+    if (count == 0) return;
+
+    symno = symbol_value[symbol] + 2*nstates;
+
+    froms[symno] = sp1 = sp = NEW2(count, short);
+    tos[symno] = sp2 = NEW2(count, short);
+
+    for (i = m; i < n; i++)
+    {
+	if (to_state[i] != default_state)
+	{
+	    *sp1++ = from_state[i];
+	    *sp2++ = to_state[i];
+	}
+    }
+
+    tally[symno] = count;
+    width[symno] = sp1[-1] - sp[0] + 1;
+}
+
+sort_actions()
+{
+  register int i;
+  register int j;
+  register int k;
+  register int t;
+  register int w;
+
+  order = NEW2(nvectors, short);
+  nentries = 0;
+
+  for (i = 0; i < nvectors; i++)
+    {
+      if (tally[i] > 0)
+	{
+	  t = tally[i];
+	  w = width[i];
+	  j = nentries - 1;
+
+	  while (j >= 0 && (width[order[j]] < w))
+	    j--;
+
+	  while (j >= 0 && (width[order[j]] == w) && (tally[order[j]] < t))
+	    j--;
+
+	  for (k = nentries - 1; k > j; k--)
+	    order[k + 1] = order[k];
+
+	  order[j + 1] = i;
+	  nentries++;
+	}
+    }
+}
+
+
+pack_table()
+{
+    register int i;
+    register int place;
+    register int state;
+
+    base = NEW2(nvectors, short);
+    pos = NEW2(nentries, short);
+
+    maxtable = BITS_PER_WORD == 16 ? 400 : 1000;
+    table = NEW2(maxtable, short);
+    check = NEW2(maxtable, short);
+
+    lowzero = 0;
+    high = 0;
+
+    for (i = 0; i < maxtable; i++)
+	check[i] = -1;
+
+    for (i = 0; i < nentries; i++)
+    {
+	state = matching_vector(i);
+
+	if (state < 0)
+	    place = pack_vector(i);
+	else
+	    place = base[state];
+
+	pos[i] = place;
+	base[order[i]] = place;
+    }
+
+    for (i = 0; i < nvectors; i++)
+    {
+	if (froms[i])
+	    FREE(froms[i]);
+	if (tos[i])
+	    FREE(tos[i]);
+    }
+
+    FREE(froms);
+    FREE(tos);
+    FREE(pos);
+}
+
+
+/*  The function matching_vector determines if the vector specified by	*/
+/*  the input parameter matches a previously considered	vector.  The	*/
+/*  test at the start of the function checks if the vector represents	*/
+/*  a row of shifts over terminal symbols or a row of reductions, or a	*/
+/*  column of shifts over a nonterminal symbol.  Berkeley Yacc does not	*/
+/*  check if a column of shifts over a nonterminal symbols matches a	*/
+/*  previously considered vector.  Because of the nature of LR parsing	*/
+/*  tables, no two columns can match.  Therefore, the only possible	*/
+/*  match would be between a row and a column.  Such matches are	*/
+/*  unlikely.  Therefore, to save time, no attempt is made to see if a	*/
+/*  column matches a previously considered vector.			*/
+/*									*/
+/*  Matching_vector is poorly designed.  The test could easily be made	*/
+/*  faster.  Also, it depends on the vectors being in a specific	*/
+/*  order.								*/
+
+int
+matching_vector(vector)
+int vector;
+{
+    register int i;
+    register int j;
+    register int k;
+    register int t;
+    register int w;
+    register int match;
+    register int prev;
+
+    i = order[vector];
+    if (i >= 2*nstates)
+	return (-1);
+
+    t = tally[i];
+    w = width[i];
+
+    for (prev = vector - 1; prev >= 0; prev--)
+    {
+	j = order[prev];
+	if (width[j] != w || tally[j] != t)
+	    return (-1);
+
+	match = 1;
+	for (k = 0; match && k < t; k++)
+	{
+	    if (tos[j][k] != tos[i][k] || froms[j][k] != froms[i][k])
+		match = 0;
+	}
+
+	if (match)
+	    return (j);
+    }
+
+    return (-1);
+}
+
+
+
+int
+pack_vector(vector)
+int vector;
+{
+    register int i, j, k, l;
+    register int t;
+    register int loc;
+    register int ok;
+    register short *from;
+    register short *to;
+    int newmax;
+
+    i = order[vector];
+    t = tally[i];
+    assert(t);
+
+    from = froms[i];
+    to = tos[i];
+
+    j = lowzero - from[0];
+    for (k = 1; k < t; ++k)
+	if (lowzero - from[k] > j)
+	    j = lowzero - from[k];
+    for (;; ++j)
+    {
+	if (j == 0)
+	    continue;
+	ok = 1;
+	for (k = 0; ok && k < t; k++)
+	{
+	    loc = j + from[k];
+	    if (loc >= maxtable)
+	    {
+		if (loc >= MAXTABLE)
+		    fatal("maximum table size exceeded");
+
+		newmax = maxtable;
+		do { newmax += 200; } while (newmax <= loc);
+		table = (short *) REALLOC(table, newmax*sizeof(short));
+		if (table == 0) no_space();
+		check = (short *) REALLOC(check, newmax*sizeof(short));
+		if (check == 0) no_space();
+		for (l  = maxtable; l < newmax; ++l)
+		{
+		    table[l] = 0;
+		    check[l] = -1;
+		}
+		maxtable = newmax;
+	    }
+
+	    if (check[loc] != -1)
+		ok = 0;
+	}
+	for (k = 0; ok && k < vector; k++)
+	{
+	    if (pos[k] == j)
+		ok = 0;
+	}
+	if (ok)
+	{
+	    for (k = 0; k < t; k++)
+	    {
+		loc = j + from[k];
+		table[loc] = to[k];
+		check[loc] = from[k];
+		if (loc > high) high = loc;
+	    }
+
+	    while (check[lowzero] != -1)
+		++lowzero;
+
+	    return (j);
+	}
+    }
+}
+
+
+
+output_base()
+{
+    register int i, j;
+
+    fprintf(output_file, "short %ssindex[] = {%39d,", symbol_prefix, base[0]);
+
+    j = 10;
+    for (i = 1; i < nstates; i++)
+    {
+	if (j >= 10)
+	{
+	    if (!rflag) ++outline;
+	    putc('\n', output_file);
+	    j = 1;
+	}
+	else
+	    ++j;
+
+	fprintf(output_file, "%5d,", base[i]);
+    }
+
+    if (!rflag) outline += 2;
+    fprintf(output_file, "\n};\nshort %srindex[] = {%39d,", symbol_prefix,
+	    base[nstates]);
+
+    j = 10;
+    for (i = nstates + 1; i < 2*nstates; i++)
+    {
+	if (j >= 10)
+	{
+	    if (!rflag) ++outline;
+	    putc('\n', output_file);
+	    j = 1;
+	}
+	else
+	    ++j;
+
+	fprintf(output_file, "%5d,", base[i]);
+    }
+
+    if (!rflag) outline += 2;
+    fprintf(output_file, "\n};\nshort %sgindex[] = {%39d,", symbol_prefix,
+	    base[2*nstates]);
+
+    j = 10;
+    for (i = 2*nstates + 1; i < nvectors - 1; i++)
+    {
+	if (j >= 10)
+	{
+	    if (!rflag) ++outline;
+	    putc('\n', output_file);
+	    j = 1;
+	}
+	else
+	    ++j;
+
+	fprintf(output_file, "%5d,", base[i]);
+    }
+
+    if (!rflag) outline += 2;
+    fprintf(output_file, "\n};\n");
+    FREE(base);
+}
+
+
+
+output_table()
+{
+    register int i;
+    register int j;
+
+    ++outline;
+    fprintf(code_file, "#define YYTABLESIZE %d\n", high);
+    fprintf(output_file, "short %stable[] = {%40d,", symbol_prefix,
+	    table[0]);
+
+    j = 10;
+    for (i = 1; i <= high; i++)
+    {
+	if (j >= 10)
+	{
+	    if (!rflag) ++outline;
+	    putc('\n', output_file);
+	    j = 1;
+	}
+	else
+	    ++j;
+
+	fprintf(output_file, "%5d,", table[i]);
+    }
+
+    if (!rflag) outline += 2;
+    fprintf(output_file, "\n};\n");
+    FREE(table);
+}
+
+
+
+output_check()
+{
+    register int i;
+    register int j;
+
+    fprintf(output_file, "short %scheck[] = {%40d,", symbol_prefix,
+	    check[0]);
+
+    j = 10;
+    for (i = 1; i <= high; i++)
+    {
+	if (j >= 10)
+	{
+	    if (!rflag) ++outline;
+	    putc('\n', output_file);
+	    j = 1;
+	}
+	else
+	    ++j;
+
+	fprintf(output_file, "%5d,", check[i]);
+    }
+
+    if (!rflag) outline += 2;
+    fprintf(output_file, "\n};\n");
+    FREE(check);
+}
+
+
+int
+is_C_identifier(name)
+char *name;
+{
+    register char *s;
+    register int c;
+
+    s = name;
+    c = *s;
+    if (c == '"')
+    {
+	c = *++s;
+	if (!isalpha(c) && c != '_' && c != '$')
+	    return (0);
+	while ((c = *++s) != '"')
+	{
+	    if (!isalnum(c) && c != '_' && c != '$')
+		return (0);
+	}
+	return (1);
+    }
+
+    if (!isalpha(c) && c != '_' && c != '$')
+	return (0);
+    while (c = *++s)
+    {
+	if (!isalnum(c) && c != '_' && c != '$')
+	    return (0);
+    }
+    return (1);
+}
+
+
+output_defines()
+{
+    register int c, i;
+    register char *s;
+
+    for (i = 2; i < ntokens; ++i)
+    {
+	s = symbol_name[i];
+	if (is_C_identifier(s))
+	{
+	    fprintf(code_file, "#define ");
+	    if (dflag) fprintf(defines_file, "#define ");
+	    c = *s;
+	    if (c == '"')
+	    {
+		while ((c = *++s) != '"')
+		{
+		    putc(c, code_file);
+		    if (dflag) putc(c, defines_file);
+		}
+	    }
+	    else
+	    {
+		do
+		{
+		    putc(c, code_file);
+		    if (dflag) putc(c, defines_file);
+		}
+		while (c = *++s);
+	    }
+	    ++outline;
+	    fprintf(code_file, " %d\n", symbol_value[i]);
+	    if (dflag) fprintf(defines_file, " %d\n", symbol_value[i]);
+	}
+    }
+
+    ++outline;
+    fprintf(code_file, "#define YYERRCODE %d\n", symbol_value[1]);
+
+    if (dflag && unionized)
+    {
+	fclose(union_file);
+	union_file = fopen(union_file_name, "r");
+	if (union_file == NULL) open_error(union_file_name);
+	while ((c = getc(union_file)) != EOF)
+	    putc(c, defines_file);
+	fprintf(defines_file, " YYSTYPE;\nextern YYSTYPE %slval;\n",
+		symbol_prefix);
+    }
+}
+
+
+output_stored_text()
+{
+    register int c;
+    register FILE *in, *out;
+
+    fclose(text_file);
+    text_file = fopen(text_file_name, "r");
+    if (text_file == NULL)
+	open_error(text_file_name);
+    in = text_file;
+    if ((c = getc(in)) == EOF)
+	return;
+    out = code_file;
+    if (c ==  '\n')
+	++outline;
+    putc(c, out);
+    while ((c = getc(in)) != EOF)
+    {
+	if (c == '\n')
+	    ++outline;
+	putc(c, out);
+    }
+    if (!lflag)
+	fprintf(out, line_format, ++outline + 1, code_file_name);
+}
+
+
+output_debug()
+{
+    register int i, j, k, max;
+    char **symnam, *s;
+
+    ++outline;
+    fprintf(code_file, "#define YYFINAL %d\n", final_state);
+    outline += 3;
+    fprintf(code_file, "#ifndef YYDEBUG\n#define YYDEBUG %d\n#endif\n",
+	    tflag);
+    if (rflag)
+	fprintf(output_file, "#ifndef YYDEBUG\n#define YYDEBUG %d\n#endif\n",
+		tflag);
+
+    max = 0;
+    for (i = 2; i < ntokens; ++i)
+	if (symbol_value[i] > max)
+	    max = symbol_value[i];
+    ++outline;
+    fprintf(code_file, "#define YYMAXTOKEN %d\n", max);
+
+    symnam = (char **) MALLOC((max+1)*sizeof(char *));
+    if (symnam == 0) no_space();
+
+    /* Note that it is  not necessary to initialize the element		*/
+    /* symnam[max].							*/
+    for (i = 0; i < max; ++i)
+	symnam[i] = 0;
+    for (i = ntokens - 1; i >= 2; --i)
+	symnam[symbol_value[i]] = symbol_name[i];
+    symnam[0] = "end-of-file";
+
+    if (!rflag) ++outline;
+    fprintf(output_file, "#if YYDEBUG\nchar *%sname[] = {", symbol_prefix);
+    j = 80;
+    for (i = 0; i <= max; ++i)
+    {
+	if (s = symnam[i])
+	{
+	    if (s[0] == '"')
+	    {
+		k = 7;
+		while (*++s != '"')
+		{
+		    ++k;
+		    if (*s == '\\')
+		    {
+			k += 2;
+			if (*++s == '\\')
+			    ++k;
+		    }
+		}
+		j += k;
+		if (j > 80)
+		{
+		    if (!rflag) ++outline;
+		    putc('\n', output_file);
+		    j = k;
+		}
+		fprintf(output_file, "\"\\\"");
+		s = symnam[i];
+		while (*++s != '"')
+		{
+		    if (*s == '\\')
+		    {
+			fprintf(output_file, "\\\\");
+			if (*++s == '\\')
+			    fprintf(output_file, "\\\\");
+			else
+			    putc(*s, output_file);
+		    }
+		    else
+			putc(*s, output_file);
+		}
+		fprintf(output_file, "\\\"\",");
+	    }
+	    else if (s[0] == '\'')
+	    {
+		if (s[1] == '"')
+		{
+		    j += 7;
+		    if (j > 80)
+		    {
+			if (!rflag) ++outline;
+			putc('\n', output_file);
+			j = 7;
+		    }
+		    fprintf(output_file, "\"'\\\"'\",");
+		}
+		else
+		{
+		    k = 5;
+		    while (*++s != '\'')
+		    {
+			++k;
+			if (*s == '\\')
+			{
+			    k += 2;
+			    if (*++s == '\\')
+				++k;
+			}
+		    }
+		    j += k;
+		    if (j > 80)
+		    {
+			if (!rflag) ++outline;
+			putc('\n', output_file);
+			j = k;
+		    }
+		    fprintf(output_file, "\"'");
+		    s = symnam[i];
+		    while (*++s != '\'')
+		    {
+			if (*s == '\\')
+			{
+			    fprintf(output_file, "\\\\");
+			    if (*++s == '\\')
+				fprintf(output_file, "\\\\");
+			    else
+				putc(*s, output_file);
+			}
+			else
+			    putc(*s, output_file);
+		    }
+		    fprintf(output_file, "'\",");
+		}
+	    }
+	    else
+	    {
+		k = strlen(s) + 3;
+		j += k;
+		if (j > 80)
+		{
+		    if (!rflag) ++outline;
+		    putc('\n', output_file);
+		    j = k;
+		}
+		putc('"', output_file);
+		do { putc(*s, output_file); } while (*++s);
+		fprintf(output_file, "\",");
+	    }
+	}
+	else
+	{
+	    j += 2;
+	    if (j > 80)
+	    {
+		if (!rflag) ++outline;
+		putc('\n', output_file);
+		j = 2;
+	    }
+	    fprintf(output_file, "0,");
+	}
+    }
+    if (!rflag) outline += 2;
+    fprintf(output_file, "\n};\n");
+    FREE(symnam);
+
+    if (!rflag) ++outline;
+    fprintf(output_file, "char *%srule[] = {\n", symbol_prefix);
+    for (i = 2; i < nrules; ++i)
+    {
+	fprintf(output_file, "\"%s :", symbol_name[rlhs[i]]);
+	for (j = rrhs[i]; ritem[j] > 0; ++j)
+	{
+	    s = symbol_name[ritem[j]];
+	    if (s[0] == '"')
+	    {
+		fprintf(output_file, " \\\"");
+		while (*++s != '"')
+		{
+		    if (*s == '\\')
+		    {
+			if (s[1] == '\\')
+			    fprintf(output_file, "\\\\\\\\");
+			else
+			    fprintf(output_file, "\\\\%c", s[1]);
+			++s;
+		    }
+		    else
+			putc(*s, output_file);
+		}
+		fprintf(output_file, "\\\"");
+	    }
+	    else if (s[0] == '\'')
+	    {
+		if (s[1] == '"')
+		    fprintf(output_file, " '\\\"'");
+		else if (s[1] == '\\')
+		{
+		    if (s[2] == '\\')
+			fprintf(output_file, " '\\\\\\\\");
+		    else
+			fprintf(output_file, " '\\\\%c", s[2]);
+		    s += 2;
+		    while (*++s != '\'')
+			putc(*s, output_file);
+		    putc('\'', output_file);
+		}
+		else
+		    fprintf(output_file, " '%c'", s[1]);
+	    }
+	    else
+		fprintf(output_file, " %s", s);
+	}
+	if (!rflag) ++outline;
+	fprintf(output_file, "\",\n");
+    }
+
+    if (!rflag) outline += 2;
+    fprintf(output_file, "};\n#endif\n");
+}
+
+
+output_stype()
+{
+    if (!unionized && ntags == 0)
+    {
+	outline += 3;
+	fprintf(code_file, "#ifndef YYSTYPE\ntypedef int YYSTYPE;\n#endif\n");
+    }
+}
+
+
+output_trailing_text()
+{
+    register int c, last;
+    register FILE *in, *out;
+
+    if (line == 0)
+	return;
+
+    in = input_file;
+    out = code_file;
+    c = *cptr;
+    if (c == '\n')
+    {
+	++lineno;
+	if ((c = getc(in)) == EOF)
+	    return;
+	if (!lflag)
+	{
+	    ++outline;
+	    fprintf(out, line_format, lineno, input_file_name);
+	}
+	if (c == '\n')
+	    ++outline;
+	putc(c, out);
+	last = c;
+    }
+    else
+    {
+	if (!lflag)
+	{
+	    ++outline;
+	    fprintf(out, line_format, lineno, input_file_name);
+	}
+	do { putc(c, out); } while ((c = *++cptr) != '\n');
+	++outline;
+	putc('\n', out);
+	last = '\n';
+    }
+
+    while ((c = getc(in)) != EOF)
+    {
+	if (c == '\n')
+	    ++outline;
+	putc(c, out);
+	last = c;
+    }
+
+    if (last != '\n')
+    {
+	++outline;
+	putc('\n', out);
+    }
+    if (!lflag)
+	fprintf(out, line_format, ++outline + 1, code_file_name);
+}
+
+
+output_semantic_actions()
+{
+    register int c, last;
+    register FILE *out;
+
+    fclose(action_file);
+    action_file = fopen(action_file_name, "r");
+    if (action_file == NULL)
+	open_error(action_file_name);
+
+    if ((c = getc(action_file)) == EOF)
+	return;
+
+    out = code_file;
+    last = c;
+    if (c == '\n')
+	++outline;
+    putc(c, out);
+    while ((c = getc(action_file)) != EOF)
+    {
+	if (c == '\n')
+	    ++outline;
+	putc(c, out);
+	last = c;
+    }
+
+    if (last != '\n')
+    {
+	++outline;
+	putc('\n', out);
+    }
+
+    if (!lflag)
+	fprintf(out, line_format, ++outline + 1, code_file_name);
+}
+
+
+free_itemsets()
+{
+    register core *cp, *next;
+
+    FREE(state_table);
+    for (cp = first_state; cp; cp = next)
+    {
+	next = cp->next;
+	FREE(cp);
+    }
+}
+
+
+free_shifts()
+{
+    register shifts *sp, *next;
+
+    FREE(shift_table);
+    for (sp = first_shift; sp; sp = next)
+    {
+	next = sp->next;
+	FREE(sp);
+    }
+}
+
+
+
+free_reductions()
+{
+    register reductions *rp, *next;
+
+    FREE(reduction_table);
+    for (rp = first_reduction; rp; rp = next)
+    {
+	next = rp->next;
+	FREE(rp);
+    }
+}
Index: /trunk/minix/commands/byacc/reader.c
===================================================================
--- /trunk/minix/commands/byacc/reader.c	(revision 9)
+++ /trunk/minix/commands/byacc/reader.c	(revision 9)
@@ -0,0 +1,1770 @@
+#include "defs.h"
+
+/*  The line size must be a positive integer.  One hundred was chosen	*/
+/*  because few lines in Yacc input grammars exceed 100 characters.	*/
+/*  Note that if a line exceeds LINESIZE characters, the line buffer	*/
+/*  will be expanded to accomodate it.					*/
+
+#define LINESIZE 100
+
+char *cache;
+int cinc, cache_size;
+
+int ntags, tagmax;
+char **tag_table;
+
+char saw_eof, unionized;
+char *cptr, *line;
+int linesize;
+
+bucket *goal;
+int prec;
+int gensym;
+char last_was_action;
+
+int maxitems;
+bucket **pitem;
+
+int maxrules;
+bucket **plhs;
+
+int name_pool_size;
+char *name_pool;
+
+char line_format[] = "#line %d \"%s\"\n";
+
+
+cachec(c)
+int c;
+{
+    assert(cinc >= 0);
+    if (cinc >= cache_size)
+    {
+	cache_size += 256;
+	cache = REALLOC(cache, cache_size);
+	if (cache == 0) no_space();
+    }
+    cache[cinc] = c;
+    ++cinc;
+}
+
+
+get_line()
+{
+    register FILE *f = input_file;
+    register int c;
+    register int i;
+
+    if (saw_eof || (c = getc(f)) == EOF)
+    {
+	if (line) { FREE(line); line = 0; }
+	cptr = 0;
+	saw_eof = 1;
+	return;
+    }
+
+    if (line == 0 || linesize != (LINESIZE + 1))
+    {
+	if (line) FREE(line);
+	linesize = LINESIZE + 1;
+	line = MALLOC(linesize);
+	if (line == 0) no_space();
+    }
+
+    i = 0;
+    ++lineno;
+    for (;;)
+    {
+	line[i]  =  c;
+	if (c == '\n') { cptr = line; return; }
+	if (++i >= linesize)
+	{
+	    linesize += LINESIZE;
+	    line = REALLOC(line, linesize);
+	    if (line ==  0) no_space();
+	}
+	c = getc(f);
+	if (c ==  EOF)
+	{
+	    line[i] = '\n';
+	    saw_eof = 1;
+	    cptr = line;
+	    return;
+	}
+    }
+}
+
+
+char *
+dup_line()
+{
+    register char *p, *s, *t;
+
+    if (line == 0) return (0);
+    s = line;
+    while (*s != '\n') ++s;
+    p = MALLOC(s - line + 1);
+    if (p == 0) no_space();
+
+    s = line;
+    t = p;
+    while ((*t++ = *s++) != '\n') continue;
+    return (p);
+}
+
+
+skip_comment()
+{
+    register char *s;
+
+    int st_lineno = lineno;
+    char *st_line = dup_line();
+    char *st_cptr = st_line + (cptr - line);
+
+    s = cptr + 2;
+    for (;;)
+    {
+	if (*s == '*' && s[1] == '/')
+	{
+	    cptr = s + 2;
+	    FREE(st_line);
+	    return;
+	}
+	if (*s == '\n')
+	{
+	    get_line();
+	    if (line == 0)
+		unterminated_comment(st_lineno, st_line, st_cptr);
+	    s = cptr;
+	}
+	else
+	    ++s;
+    }
+}
+
+
+int
+nextc()
+{
+    register char *s;
+
+    if (line == 0)
+    {
+	get_line();
+	if (line == 0)
+	    return (EOF);
+    }
+
+    s = cptr;
+    for (;;)
+    {
+	switch (*s)
+	{
+	case '\n':
+	    get_line();
+	    if (line == 0) return (EOF);
+	    s = cptr;
+	    break;
+
+	case ' ':
+	case '\t':
+	case '\f':
+	case '\r':
+	case '\v':
+	case ',':
+	case ';':
+	    ++s;
+	    break;
+
+	case '\\':
+	    cptr = s;
+	    return ('%');
+
+	case '/':
+	    if (s[1] == '*')
+	    {
+		cptr = s;
+		skip_comment();
+		s = cptr;
+		break;
+	    }
+	    else if (s[1] == '/')
+	    {
+		get_line();
+		if (line == 0) return (EOF);
+		s = cptr;
+		break;
+	    }
+	    /* fall through */
+
+	default:
+	    cptr = s;
+	    return (*s);
+	}
+    }
+}
+
+
+int
+keyword()
+{
+    register int c;
+    char *t_cptr = cptr;
+
+    c = *++cptr;
+    if (isalpha(c))
+    {
+	cinc = 0;
+	for (;;)
+	{
+	    if (isalpha(c))
+	    {
+		if (isupper(c)) c = tolower(c);
+		cachec(c);
+	    }
+	    else if (isdigit(c) || c == '_' || c == '.' || c == '$')
+		cachec(c);
+	    else
+		break;
+	    c = *++cptr;
+	}
+	cachec(NUL);
+
+	if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
+	    return (TOKEN);
+	if (strcmp(cache, "type") == 0)
+	    return (TYPE);
+	if (strcmp(cache, "left") == 0)
+	    return (LEFT);
+	if (strcmp(cache, "right") == 0)
+	    return (RIGHT);
+	if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
+	    return (NONASSOC);
+	if (strcmp(cache, "start") == 0)
+	    return (START);
+	if (strcmp(cache, "union") == 0)
+	    return (UNION);
+	if (strcmp(cache, "ident") == 0)
+	    return (IDENT);
+    }
+    else
+    {
+	++cptr;
+	if (c == '{')
+	    return (TEXT);
+	if (c == '%' || c == '\\')
+	    return (MARK);
+	if (c == '<')
+	    return (LEFT);
+	if (c == '>')
+	    return (RIGHT);
+	if (c == '0')
+	    return (TOKEN);
+	if (c == '2')
+	    return (NONASSOC);
+    }
+    syntax_error(lineno, line, t_cptr);
+    /*NOTREACHED*/
+}
+
+
+copy_ident()
+{
+    register int c;
+    register FILE *f = output_file;
+
+    c = nextc();
+    if (c == EOF) unexpected_EOF();
+    if (c != '"') syntax_error(lineno, line, cptr);
+    ++outline;
+    fprintf(f, "#ident \"");
+    for (;;)
+    {
+	c = *++cptr;
+	if (c == '\n')
+	{
+	    fprintf(f, "\"\n");
+	    return;
+	}
+	putc(c, f);
+	if (c == '"')
+	{
+	    putc('\n', f);
+	    ++cptr;
+	    return;
+	}
+    }
+}
+
+
+copy_text()
+{
+    register int c;
+    int quote;
+    register FILE *f = text_file;
+    int need_newline = 0;
+    int t_lineno = lineno;
+    char *t_line = dup_line();
+    char *t_cptr = t_line + (cptr - line - 2);
+
+    if (*cptr == '\n')
+    {
+	get_line();
+	if (line == 0)
+	    unterminated_text(t_lineno, t_line, t_cptr);
+    }
+    if (!lflag) fprintf(f, line_format, lineno, input_file_name);
+
+loop:
+    c = *cptr++;
+    switch (c)
+    {
+    case '\n':
+    next_line:
+	putc('\n', f);
+	need_newline = 0;
+	get_line();
+	if (line) goto loop;
+	unterminated_text(t_lineno, t_line, t_cptr);
+
+    case '\'':
+    case '"':
+	{
+	    int s_lineno = lineno;
+	    char *s_line = dup_line();
+	    char *s_cptr = s_line + (cptr - line - 1);
+
+	    quote = c;
+	    putc(c, f);
+	    for (;;)
+	    {
+		c = *cptr++;
+		putc(c, f);
+		if (c == quote)
+		{
+		    need_newline = 1;
+		    FREE(s_line);
+		    goto loop;
+		}
+		if (c == '\n')
+		    unterminated_string(s_lineno, s_line, s_cptr);
+		if (c == '\\')
+		{
+		    c = *cptr++;
+		    putc(c, f);
+		    if (c == '\n')
+		    {
+			get_line();
+			if (line == 0)
+			    unterminated_string(s_lineno, s_line, s_cptr);
+		    }
+		}
+	    }
+	}
+
+    case '/':
+	putc(c, f);
+	need_newline = 1;
+	c = *cptr;
+	if (c == '/')
+	{
+	    putc('*', f);
+	    while ((c = *++cptr) != '\n')
+	    {
+		if (c == '*' && cptr[1] == '/')
+		    fprintf(f, "* ");
+		else
+		    putc(c, f);
+	    }
+	    fprintf(f, "*/");
+	    goto next_line;
+	}
+	if (c == '*')
+	{
+	    int c_lineno = lineno;
+	    char *c_line = dup_line();
+	    char *c_cptr = c_line + (cptr - line - 1);
+
+	    putc('*', f);
+	    ++cptr;
+	    for (;;)
+	    {
+		c = *cptr++;
+		putc(c, f);
+		if (c == '*' && *cptr == '/')
+		{
+		    putc('/', f);
+		    ++cptr;
+		    FREE(c_line);
+		    goto loop;
+		}
+		if (c == '\n')
+		{
+		    get_line();
+		    if (line == 0)
+			unterminated_comment(c_lineno, c_line, c_cptr);
+		}
+	    }
+	}
+	need_newline = 1;
+	goto loop;
+
+    case '%':
+    case '\\':
+	if (*cptr == '}')
+	{
+	    if (need_newline) putc('\n', f);
+	    ++cptr;
+	    FREE(t_line);
+	    return;
+	}
+	/* fall through */
+
+    default:
+	putc(c, f);
+	need_newline = 1;
+	goto loop;
+    }
+}
+
+
+copy_union()
+{
+    register int c;
+    int quote;
+    int depth;
+    int u_lineno = lineno;
+    char *u_line = dup_line();
+    char *u_cptr = u_line + (cptr - line - 6);
+
+    if (unionized) over_unionized(cptr - 6);
+    unionized = 1;
+
+    if (!lflag)
+	fprintf(text_file, line_format, lineno, input_file_name);
+
+    fprintf(text_file, "typedef union");
+    if (dflag) fprintf(union_file, "typedef union");
+
+    depth = 0;
+loop:
+    c = *cptr++;
+    putc(c, text_file);
+    if (dflag) putc(c, union_file);
+    switch (c)
+    {
+    case '\n':
+    next_line:
+	get_line();
+	if (line == 0) unterminated_union(u_lineno, u_line, u_cptr);
+	goto loop;
+
+    case '{':
+	++depth;
+	goto loop;
+
+    case '}':
+	if (--depth == 0)
+	{
+	    fprintf(text_file, " YYSTYPE;\n");
+	    FREE(u_line);
+	    return;
+	}
+	goto loop;
+
+    case '\'':
+    case '"':
+	{
+	    int s_lineno = lineno;
+	    char *s_line = dup_line();
+	    char *s_cptr = s_line + (cptr - line - 1);
+
+	    quote = c;
+	    for (;;)
+	    {
+		c = *cptr++;
+		putc(c, text_file);
+		if (dflag) putc(c, union_file);
+		if (c == quote)
+		{
+		    FREE(s_line);
+		    goto loop;
+		}
+		if (c == '\n')
+		    unterminated_string(s_lineno, s_line, s_cptr);
+		if (c == '\\')
+		{
+		    c = *cptr++;
+		    putc(c, text_file);
+		    if (dflag) putc(c, union_file);
+		    if (c == '\n')
+		    {
+			get_line();
+			if (line == 0)
+			    unterminated_string(s_lineno, s_line, s_cptr);
+		    }
+		}
+	    }
+	}
+
+    case '/':
+	c = *cptr;
+	if (c == '/')
+	{
+	    putc('*', text_file);
+	    if (dflag) putc('*', union_file);
+	    while ((c = *++cptr) != '\n')
+	    {
+		if (c == '*' && cptr[1] == '/')
+		{
+		    fprintf(text_file, "* ");
+		    if (dflag) fprintf(union_file, "* ");
+		}
+		else
+		{
+		    putc(c, text_file);
+		    if (dflag) putc(c, union_file);
+		}
+	    }
+	    fprintf(text_file, "*/\n");
+	    if (dflag) fprintf(union_file, "*/\n");
+	    goto next_line;
+	}
+	if (c == '*')
+	{
+	    int c_lineno = lineno;
+	    char *c_line = dup_line();
+	    char *c_cptr = c_line + (cptr - line - 1);
+
+	    putc('*', text_file);
+	    if (dflag) putc('*', union_file);
+	    ++cptr;
+	    for (;;)
+	    {
+		c = *cptr++;
+		putc(c, text_file);
+		if (dflag) putc(c, union_file);
+		if (c == '*' && *cptr == '/')
+		{
+		    putc('/', text_file);
+		    if (dflag) putc('/', union_file);
+		    ++cptr;
+		    FREE(c_line);
+		    goto loop;
+		}
+		if (c == '\n')
+		{
+		    get_line();
+		    if (line == 0)
+			unterminated_comment(c_lineno, c_line, c_cptr);
+		}
+	    }
+	}
+	goto loop;
+
+    default:
+	goto loop;
+    }
+}
+
+
+int
+hexval(c)
+int c;
+{
+    if (c >= '0' && c <= '9')
+	return (c - '0');
+    if (c >= 'A' && c <= 'F')
+	return (c - 'A' + 10);
+    if (c >= 'a' && c <= 'f')
+	return (c - 'a' + 10);
+    return (-1);
+}
+
+
+bucket *
+get_literal()
+{
+    register int c, quote;
+    register int i;
+    register int n;
+    register char *s;
+    register bucket *bp;
+    int s_lineno = lineno;
+    char *s_line = dup_line();
+    char *s_cptr = s_line + (cptr - line);
+
+    quote = *cptr++;
+    cinc = 0;
+    for (;;)
+    {
+	c = *cptr++;
+	if (c == quote) break;
+	if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr);
+	if (c == '\\')
+	{
+	    char *c_cptr = cptr - 1;
+
+	    c = *cptr++;
+	    switch (c)
+	    {
+	    case '\n':
+		get_line();
+		if (line == 0) unterminated_string(s_lineno, s_line, s_cptr);
+		continue;
+
+	    case '0': case '1': case '2': case '3':
+	    case '4': case '5': case '6': case '7':
+		n = c - '0';
+		c = *cptr;
+		if (IS_OCTAL(c))
+		{
+		    n = (n << 3) + (c - '0');
+		    c = *++cptr;
+		    if (IS_OCTAL(c))
+		    {
+			n = (n << 3) + (c - '0');
+			++cptr;
+		    }
+		}
+		if (n > MAXCHAR) illegal_character(c_cptr);
+		c = n;
+	    	break;
+
+	    case 'x':
+		c = *cptr++;
+		n = hexval(c);
+		if (n < 0 || n >= 16)
+		    illegal_character(c_cptr);
+		for (;;)
+		{
+		    c = *cptr;
+		    i = hexval(c);
+		    if (i < 0 || i >= 16) break;
+		    ++cptr;
+		    n = (n << 4) + i;
+		    if (n > MAXCHAR) illegal_character(c_cptr);
+		}
+		c = n;
+		break;
+
+	    case 'a': c = 7; break;
+	    case 'b': c = '\b'; break;
+	    case 'f': c = '\f'; break;
+	    case 'n': c = '\n'; break;
+	    case 'r': c = '\r'; break;
+	    case 't': c = '\t'; break;
+	    case 'v': c = '\v'; break;
+	    }
+	}
+	cachec(c);
+    }
+    FREE(s_line);
+
+    n = cinc;
+    s = MALLOC(n);
+    if (s == 0) no_space();
+    
+    for (i = 0; i < n; ++i)
+	s[i] = cache[i];
+
+    cinc = 0;
+    if (n == 1)
+	cachec('\'');
+    else
+	cachec('"');
+
+    for (i = 0; i < n; ++i)
+    {
+	c = ((unsigned char *)s)[i];
+	if (c == '\\' || c == cache[0])
+	{
+	    cachec('\\');
+	    cachec(c);
+	}
+	else if (isprint(c))
+	    cachec(c);
+	else
+	{
+	    cachec('\\');
+	    switch (c)
+	    {
+	    case 7: cachec('a'); break;
+	    case '\b': cachec('b'); break;
+	    case '\f': cachec('f'); break;
+	    case '\n': cachec('n'); break;
+	    case '\r': cachec('r'); break;
+	    case '\t': cachec('t'); break;
+	    case '\v': cachec('v'); break;
+	    default:
+		cachec(((c >> 6) & 7) + '0');
+		cachec(((c >> 3) & 7) + '0');
+		cachec((c & 7) + '0');
+		break;
+	    }
+	}
+    }
+
+    if (n == 1)
+	cachec('\'');
+    else
+	cachec('"');
+
+    cachec(NUL);
+    bp = lookup(cache);
+    bp->class = TERM;
+    if (n == 1 && bp->value == UNDEFINED)
+	bp->value = *(unsigned char *)s;
+    FREE(s);
+
+    return (bp);
+}
+
+
+int
+is_reserved(name)
+char *name;
+{
+    char *s;
+
+    if (strcmp(name, ".") == 0 ||
+	    strcmp(name, "$accept") == 0 ||
+	    strcmp(name, "$end") == 0)
+	return (1);
+
+    if (name[0] == '$' && name[1] == '$' && isdigit(name[2]))
+    {
+	s = name + 3;
+	while (isdigit(*s)) ++s;
+	if (*s == NUL) return (1);
+    }
+
+    return (0);
+}
+
+
+bucket *
+get_name()
+{
+    register int c;
+
+    cinc = 0;
+    for (c = *cptr; IS_IDENT(c); c = *++cptr)
+	cachec(c);
+    cachec(NUL);
+
+    if (is_reserved(cache)) used_reserved(cache);
+
+    return (lookup(cache));
+}
+
+
+int
+get_number()
+{
+    register int c;
+    register int n;
+
+    n = 0;
+    for (c = *cptr; isdigit(c); c = *++cptr)
+	n = 10*n + (c - '0');
+
+    return (n);
+}
+
+
+char *
+get_tag()
+{
+    register int c;
+    register int i;
+    register char *s;
+    int t_lineno = lineno;
+    char *t_line = dup_line();
+    char *t_cptr = t_line + (cptr - line);
+
+    ++cptr;
+    c = nextc();
+    if (c == EOF) unexpected_EOF();
+    if (!isalpha(c) && c != '_' && c != '$')
+	illegal_tag(t_lineno, t_line, t_cptr);
+
+    cinc = 0;
+    do { cachec(c); c = *++cptr; } while (IS_IDENT(c));
+    cachec(NUL);
+
+    c = nextc();
+    if (c == EOF) unexpected_EOF();
+    if (c != '>')
+	illegal_tag(t_lineno, t_line, t_cptr);
+    ++cptr;
+
+    for (i = 0; i < ntags; ++i)
+    {
+	if (strcmp(cache, tag_table[i]) == 0)
+	    return (tag_table[i]);
+    }
+
+    if (ntags >= tagmax)
+    {
+	tagmax += 16;
+	tag_table = (char **)
+			(tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
+				   : MALLOC(tagmax*sizeof(char *)));
+	if (tag_table == 0) no_space();
+    }
+
+    s = MALLOC(cinc);
+    if  (s == 0) no_space();
+    strcpy(s, cache);
+    tag_table[ntags] = s;
+    ++ntags;
+    FREE(t_line);
+    return (s);
+}
+
+
+declare_tokens(assoc)
+int assoc;
+{
+    register int c;
+    register bucket *bp;
+    int value;
+    char *tag = 0;
+
+    if (assoc != TOKEN) ++prec;
+
+    c = nextc();
+    if (c == EOF) unexpected_EOF();
+    if (c == '<')
+    {
+	tag = get_tag();
+	c = nextc();
+	if (c == EOF) unexpected_EOF();
+    }
+
+    for (;;)
+    {
+	if (isalpha(c) || c == '_' || c == '.' || c == '$')
+	    bp = get_name();
+	else if (c == '\'' || c == '"')
+	    bp = get_literal();
+	else
+	    return;
+
+	if (bp == goal) tokenized_start(bp->name);
+	bp->class = TERM;
+
+	if (tag)
+	{
+	    if (bp->tag && tag != bp->tag)
+		retyped_warning(bp->name);
+	    bp->tag = tag;
+	}
+
+	if (assoc != TOKEN)
+	{
+	    if (bp->prec && prec != bp->prec)
+		reprec_warning(bp->name);
+	    bp->assoc = assoc;
+	    bp->prec = prec;
+	}
+
+	c = nextc();
+	if (c == EOF) unexpected_EOF();
+	value = UNDEFINED;
+	if (isdigit(c))
+	{
+	    value = get_number();
+	    if (bp->value != UNDEFINED && value != bp->value)
+		revalued_warning(bp->name);
+	    bp->value = value;
+	    c = nextc();
+	    if (c == EOF) unexpected_EOF();
+	}
+    }
+}
+
+
+declare_types()
+{
+    register int c;
+    register bucket *bp;
+    char *tag;
+
+    c = nextc();
+    if (c == EOF) unexpected_EOF();
+    if (c != '<') syntax_error(lineno, line, cptr);
+    tag = get_tag();
+
+    for (;;)
+    {
+	c = nextc();
+	if (isalpha(c) || c == '_' || c == '.' || c == '$')
+	    bp = get_name();
+	else if (c == '\'' || c == '"')
+	    bp = get_literal();
+	else
+	    return;
+
+	if (bp->tag && tag != bp->tag)
+	    retyped_warning(bp->name);
+	bp->tag = tag;
+    }
+}
+
+
+declare_start()
+{
+    register int c;
+    register bucket *bp;
+
+    c = nextc();
+    if (c == EOF) unexpected_EOF();
+    if (!isalpha(c) && c != '_' && c != '.' && c != '$')
+	syntax_error(lineno, line, cptr);
+    bp = get_name();
+    if (bp->class == TERM)
+	terminal_start(bp->name);
+    if (goal && goal != bp)
+	restarted_warning();
+    goal = bp;
+}
+
+
+read_declarations()
+{
+    register int c, k;
+
+    cache_size = 256;
+    cache = MALLOC(cache_size);
+    if (cache == 0) no_space();
+
+    for (;;)
+    {
+	c = nextc();
+	if (c == EOF) unexpected_EOF();
+	if (c != '%') syntax_error(lineno, line, cptr);
+	switch (k = keyword())
+	{
+	case MARK:
+	    return;
+
+	case IDENT:
+	    copy_ident();
+	    break;
+
+	case TEXT:
+	    copy_text();
+	    break;
+
+	case UNION:
+	    copy_union();
+	    break;
+
+	case TOKEN:
+	case LEFT:
+	case RIGHT:
+	case NONASSOC:
+	    declare_tokens(k);
+	    break;
+
+	case TYPE:
+	    declare_types();
+	    break;
+
+	case START:
+	    declare_start();
+	    break;
+	}
+    }
+}
+
+
+initialize_grammar()
+{
+    nitems = 4;
+    maxitems = 300;
+    pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *));
+    if (pitem == 0) no_space();
+    pitem[0] = 0;
+    pitem[1] = 0;
+    pitem[2] = 0;
+    pitem[3] = 0;
+
+    nrules = 3;
+    maxrules = 100;
+    plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
+    if (plhs == 0) no_space();
+    plhs[0] = 0;
+    plhs[1] = 0;
+    plhs[2] = 0;
+    rprec = (short *) MALLOC(maxrules*sizeof(short));
+    if (rprec == 0) no_space();
+    rprec[0] = 0;
+    rprec[1] = 0;
+    rprec[2] = 0;
+    rassoc = (char *) MALLOC(maxrules*sizeof(char));
+    if (rassoc == 0) no_space();
+    rassoc[0] = TOKEN;
+    rassoc[1] = TOKEN;
+    rassoc[2] = TOKEN;
+}
+
+
+expand_items()
+{
+    maxitems += 300;
+    pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
+    if (pitem == 0) no_space();
+}
+
+
+expand_rules()
+{
+    maxrules += 100;
+    plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
+    if (plhs == 0) no_space();
+    rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
+    if (rprec == 0) no_space();
+    rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
+    if (rassoc == 0) no_space();
+}
+
+
+advance_to_start()
+{
+    register int c;
+    register bucket *bp;
+    char *s_cptr;
+    int s_lineno;
+
+    for (;;)
+    {
+	c = nextc();
+	if (c != '%') break;
+	s_cptr = cptr;
+	switch (keyword())
+	{
+	case MARK:
+	    no_grammar();
+
+	case TEXT:
+	    copy_text();
+	    break;
+
+	case START:
+	    declare_start();
+	    break;
+
+	default:
+	    syntax_error(lineno, line, s_cptr);
+	}
+    }
+
+    c = nextc();
+    if (!isalpha(c) && c != '_' && c != '.' && c != '_')
+	syntax_error(lineno, line, cptr);
+    bp = get_name();
+    if (goal == 0)
+    {
+	if (bp->class == TERM)
+	    terminal_start(bp->name);
+	goal = bp;
+    }
+
+    s_lineno = lineno;
+    c = nextc();
+    if (c == EOF) unexpected_EOF();
+    if (c != ':') syntax_error(lineno, line, cptr);
+    start_rule(bp, s_lineno);
+    ++cptr;
+}
+
+
+start_rule(bp, s_lineno)
+register bucket *bp;
+int s_lineno;
+{
+    if (bp->class == TERM)
+	terminal_lhs(s_lineno);
+    bp->class = NONTERM;
+    if (nrules >= maxrules)
+	expand_rules();
+    plhs[nrules] = bp;
+    rprec[nrules] = UNDEFINED;
+    rassoc[nrules] = TOKEN;
+}
+
+
+end_rule()
+{
+    register int i;
+
+    if (!last_was_action && plhs[nrules]->tag)
+    {
+	for (i = nitems - 1; pitem[i]; --i) continue;
+	if (pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag)
+	    default_action_warning();
+    }
+
+    last_was_action = 0;
+    if (nitems >= maxitems) expand_items();
+    pitem[nitems] = 0;
+    ++nitems;
+    ++nrules;
+}
+
+
+insert_empty_rule()
+{
+    register bucket *bp, **bpp;
+
+    assert(cache);
+    sprintf(cache, "$$%d", ++gensym);
+    bp = make_bucket(cache);
+    last_symbol->next = bp;
+    last_symbol = bp;
+    bp->tag = plhs[nrules]->tag;
+    bp->class = NONTERM;
+
+    if ((nitems += 2) > maxitems)
+	expand_items();
+    bpp = pitem + nitems - 1;
+    *bpp-- = bp;
+    while (bpp[0] = bpp[-1]) --bpp;
+
+    if (++nrules >= maxrules)
+	expand_rules();
+    plhs[nrules] = plhs[nrules-1];
+    plhs[nrules-1] = bp;
+    rprec[nrules] = rprec[nrules-1];
+    rprec[nrules-1] = 0;
+    rassoc[nrules] = rassoc[nrules-1];
+    rassoc[nrules-1] = TOKEN;
+}
+
+
+add_symbol()
+{
+    register int c;
+    register bucket *bp;
+    int s_lineno = lineno;
+
+    c = *cptr;
+    if (c == '\'' || c == '"')
+	bp = get_literal();
+    else
+	bp = get_name();
+
+    c = nextc();
+    if (c == ':')
+    {
+	end_rule();
+	start_rule(bp, s_lineno);
+	++cptr;
+	return;
+    }
+
+    if (last_was_action)
+	insert_empty_rule();
+    last_was_action = 0;
+
+    if (++nitems > maxitems)
+	expand_items();
+    pitem[nitems-1] = bp;
+}
+
+
+copy_action()
+{
+    register int c;
+    register int i, n;
+    int depth;
+    int quote;
+    char *tag;
+    register FILE *f = action_file;
+    int a_lineno = lineno;
+    char *a_line = dup_line();
+    char *a_cptr = a_line + (cptr - line);
+
+    if (last_was_action)
+	insert_empty_rule();
+    last_was_action = 1;
+
+    fprintf(f, "case %d:\n", nrules - 2);
+    if (!lflag)
+	fprintf(f, line_format, lineno, input_file_name);
+    if (*cptr == '=') ++cptr;
+
+    n = 0;
+    for (i = nitems - 1; pitem[i]; --i) ++n;
+
+    depth = 0;
+loop:
+    c = *cptr;
+    if (c == '$')
+    {
+	if (cptr[1] == '<')
+	{
+	    int d_lineno = lineno;
+	    char *d_line = dup_line();
+	    char *d_cptr = d_line + (cptr - line);
+
+	    ++cptr;
+	    tag = get_tag();
+	    c = *cptr;
+	    if (c == '$')
+	    {
+		fprintf(f, "yyval.%s", tag);
+		++cptr;
+		FREE(d_line);
+		goto loop;
+	    }
+	    else if (isdigit(c))
+	    {
+		i = get_number();
+		if (i > n) dollar_warning(d_lineno, i);
+		fprintf(f, "yyvsp[%d].%s", i - n, tag);
+		FREE(d_line);
+		goto loop;
+	    }
+	    else if (c == '-' && isdigit(cptr[1]))
+	    {
+		++cptr;
+		i = -get_number() - n;
+		fprintf(f, "yyvsp[%d].%s", i, tag);
+		FREE(d_line);
+		goto loop;
+	    }
+	    else
+		dollar_error(d_lineno, d_line, d_cptr);
+	}
+	else if (cptr[1] == '$')
+	{
+	    if (ntags)
+	    {
+		tag = plhs[nrules]->tag;
+		if (tag == 0) untyped_lhs();
+		fprintf(f, "yyval.%s", tag);
+	    }
+	    else
+		fprintf(f, "yyval");
+	    cptr += 2;
+	    goto loop;
+	}
+	else if (isdigit(cptr[1]))
+	{
+	    ++cptr;
+	    i = get_number();
+	    if (ntags)
+	    {
+		if (i <= 0 || i > n)
+		    unknown_rhs(i);
+		tag = pitem[nitems + i - n - 1]->tag;
+		if (tag == 0) untyped_rhs(i, pitem[nitems + i - n - 1]->name);
+		fprintf(f, "yyvsp[%d].%s", i - n, tag);
+	    }
+	    else
+	    {
+		if (i > n)
+		    dollar_warning(lineno, i);
+		fprintf(f, "yyvsp[%d]", i - n);
+	    }
+	    goto loop;
+	}
+	else if (cptr[1] == '-')
+	{
+	    cptr += 2;
+	    i = get_number();
+	    if (ntags)
+		unknown_rhs(-i);
+	    fprintf(f, "yyvsp[%d]", -i - n);
+	    goto loop;
+	}
+    }
+    if (isalpha(c) || c == '_' || c == '$')
+    {
+	do
+	{
+	    putc(c, f);
+	    c = *++cptr;
+	} while (isalnum(c) || c == '_' || c == '$');
+	goto loop;
+    }
+    putc(c, f);
+    ++cptr;
+    switch (c)
+    {
+    case '\n':
+    next_line:
+	get_line();
+	if (line) goto loop;
+	unterminated_action(a_lineno, a_line, a_cptr);
+
+    case ';':
+	if (depth > 0) goto loop;
+	fprintf(f, "\nbreak;\n");
+	return;
+
+    case '{':
+	++depth;
+	goto loop;
+
+    case '}':
+	if (--depth > 0) goto loop;
+	fprintf(f, "\nbreak;\n");
+	return;
+
+    case '\'':
+    case '"':
+	{
+	    int s_lineno = lineno;
+	    char *s_line = dup_line();
+	    char *s_cptr = s_line + (cptr - line - 1);
+
+	    quote = c;
+	    for (;;)
+	    {
+		c = *cptr++;
+		putc(c, f);
+		if (c == quote)
+		{
+		    FREE(s_line);
+		    goto loop;
+		}
+		if (c == '\n')
+		    unterminated_string(s_lineno, s_line, s_cptr);
+		if (c == '\\')
+		{
+		    c = *cptr++;
+		    putc(c, f);
+		    if (c == '\n')
+		    {
+			get_line();
+			if (line == 0)
+			    unterminated_string(s_lineno, s_line, s_cptr);
+		    }
+		}
+	    }
+	}
+
+    case '/':
+	c = *cptr;
+	if (c == '/')
+	{
+	    putc('*', f);
+	    while ((c = *++cptr) != '\n')
+	    {
+		if (c == '*' && cptr[1] == '/')
+		    fprintf(f, "* ");
+		else
+		    putc(c, f);
+	    }
+	    fprintf(f, "*/\n");
+	    goto next_line;
+	}
+	if (c == '*')
+	{
+	    int c_lineno = lineno;
+	    char *c_line = dup_line();
+	    char *c_cptr = c_line + (cptr - line - 1);
+
+	    putc('*', f);
+	    ++cptr;
+	    for (;;)
+	    {
+		c = *cptr++;
+		putc(c, f);
+		if (c == '*' && *cptr == '/')
+		{
+		    putc('/', f);
+		    ++cptr;
+		    FREE(c_line);
+		    goto loop;
+		}
+		if (c == '\n')
+		{
+		    get_line();
+		    if (line == 0)
+			unterminated_comment(c_lineno, c_line, c_cptr);
+		}
+	    }
+	}
+	goto loop;
+
+    default:
+	goto loop;
+    }
+}
+
+
+int
+mark_symbol()
+{
+    register int c;
+    register bucket *bp;
+
+    c = cptr[1];
+    if (c == '%' || c == '\\')
+    {
+	cptr += 2;
+	return (1);
+    }
+
+    if (c == '=')
+	cptr += 2;
+    else if ((c == 'p' || c == 'P') &&
+	     ((c = cptr[2]) == 'r' || c == 'R') &&
+	     ((c = cptr[3]) == 'e' || c == 'E') &&
+	     ((c = cptr[4]) == 'c' || c == 'C') &&
+	     ((c = cptr[5], !IS_IDENT(c))))
+	cptr += 5;
+    else
+	syntax_error(lineno, line, cptr);
+
+    c = nextc();
+    if (isalpha(c) || c == '_' || c == '.' || c == '$')
+	bp = get_name();
+    else if (c == '\'' || c == '"')
+	bp = get_literal();
+    else
+    {
+	syntax_error(lineno, line, cptr);
+	/*NOTREACHED*/
+    }
+
+    if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
+	prec_redeclared();
+
+    rprec[nrules] = bp->prec;
+    rassoc[nrules] = bp->assoc;
+    return (0);
+}
+
+
+read_grammar()
+{
+    register int c;
+
+    initialize_grammar();
+    advance_to_start();
+
+    for (;;)
+    {
+	c = nextc();
+	if (c == EOF) break;
+	if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
+		c == '"')
+	    add_symbol();
+	else if (c == '{' || c == '=')
+	    copy_action();
+	else if (c == '|')
+	{
+	    end_rule();
+	    start_rule(plhs[nrules-1], 0);
+	    ++cptr;
+	}
+	else if (c == '%')
+	{
+	    if (mark_symbol()) break;
+	}
+	else
+	    syntax_error(lineno, line, cptr);
+    }
+    end_rule();
+}
+
+
+free_tags()
+{
+    register int i;
+
+    if (tag_table == 0) return;
+
+    for (i = 0; i < ntags; ++i)
+    {
+	assert(tag_table[i]);
+	FREE(tag_table[i]);
+    }
+    FREE(tag_table);
+}
+
+
+pack_names()
+{
+    register bucket *bp;
+    register char *p, *s, *t;
+
+    name_pool_size = 13;  /* 13 == sizeof("$end") + sizeof("$accept") */
+    for (bp = first_symbol; bp; bp = bp->next)
+	name_pool_size += strlen(bp->name) + 1;
+    name_pool = MALLOC(name_pool_size);
+    if (name_pool == 0) no_space();
+
+    strcpy(name_pool, "$accept");
+    strcpy(name_pool+8, "$end");
+    t = name_pool + 13;
+    for (bp = first_symbol; bp; bp = bp->next)
+    {
+	p = t;
+	s = bp->name;
+	while (*t++ = *s++) continue;
+	FREE(bp->name);
+	bp->name = p;
+    }
+}
+
+
+check_symbols()
+{
+    register bucket *bp;
+
+    if (goal->class == UNKNOWN)
+	undefined_goal(goal->name);
+
+    for (bp = first_symbol; bp; bp = bp->next)
+    {
+	if (bp->class == UNKNOWN)
+	{
+	    undefined_symbol_warning(bp->name);
+	    bp->class = TERM;
+	}
+    }
+}
+
+
+pack_symbols()
+{
+    register bucket *bp;
+    register bucket **v;
+    register int i, j, k, n;
+
+    nsyms = 2;
+    ntokens = 1;
+    for (bp = first_symbol; bp; bp = bp->next)
+    {
+	++nsyms;
+	if (bp->class == TERM) ++ntokens;
+    }
+    start_symbol = ntokens;
+    nvars = nsyms - ntokens;
+
+    symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
+    if (symbol_name == 0) no_space();
+    symbol_value = (short *) MALLOC(nsyms*sizeof(short));
+    if (symbol_value == 0) no_space();
+    symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
+    if (symbol_prec == 0) no_space();
+    symbol_assoc = MALLOC(nsyms);
+    if (symbol_assoc == 0) no_space();
+
+    v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
+    if (v == 0) no_space();
+
+    v[0] = 0;
+    v[start_symbol] = 0;
+
+    i = 1;
+    j = start_symbol + 1;
+    for (bp = first_symbol; bp; bp = bp->next)
+    {
+	if (bp->class == TERM)
+	    v[i++] = bp;
+	else
+	    v[j++] = bp;
+    }
+    assert(i == ntokens && j == nsyms);
+
+    for (i = 1; i < ntokens; ++i)
+	v[i]->index = i;
+
+    goal->index = start_symbol + 1;
+    k = start_symbol + 2;
+    while (++i < nsyms)
+	if (v[i] != goal)
+	{
+	    v[i]->index = k;
+	    ++k;
+	}
+
+    goal->value = 0;
+    k = 1;
+    for (i = start_symbol + 1; i < nsyms; ++i)
+    {
+	if (v[i] != goal)
+	{
+	    v[i]->value = k;
+	    ++k;
+	}
+    }
+
+    k = 0;
+    for (i = 1; i < ntokens; ++i)
+    {
+	n = v[i]->value;
+	if (n > 256)
+	{
+	    for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
+		symbol_value[j] = symbol_value[j-1];
+	    symbol_value[j] = n;
+	}
+    }
+
+    if (v[1]->value == UNDEFINED)
+	v[1]->value = 256;
+
+    j = 0;
+    n = 257;
+    for (i = 2; i < ntokens; ++i)
+    {
+	if (v[i]->value == UNDEFINED)
+	{
+	    while (j < k && n == symbol_value[j])
+	    {
+		while (++j < k && n == symbol_value[j]) continue;
+		++n;
+	    }
+	    v[i]->value = n;
+	    ++n;
+	}
+    }
+
+    symbol_name[0] = name_pool + 8;
+    symbol_value[0] = 0;
+    symbol_prec[0] = 0;
+    symbol_assoc[0] = TOKEN;
+    for (i = 1; i < ntokens; ++i)
+    {
+	symbol_name[i] = v[i]->name;
+	symbol_value[i] = v[i]->value;
+	symbol_prec[i] = v[i]->prec;
+	symbol_assoc[i] = v[i]->assoc;
+    }
+    symbol_name[start_symbol] = name_pool;
+    symbol_value[start_symbol] = -1;
+    symbol_prec[start_symbol] = 0;
+    symbol_assoc[start_symbol] = TOKEN;
+    for (++i; i < nsyms; ++i)
+    {
+	k = v[i]->index;
+	symbol_name[k] = v[i]->name;
+	symbol_value[k] = v[i]->value;
+	symbol_prec[k] = v[i]->prec;
+	symbol_assoc[k] = v[i]->assoc;
+    }
+
+    FREE(v);
+}
+
+
+pack_grammar()
+{
+    register int i, j;
+    int assoc, prec;
+
+    ritem = (short *) MALLOC(nitems*sizeof(short));
+    if (ritem == 0) no_space();
+    rlhs = (short *) MALLOC(nrules*sizeof(short));
+    if (rlhs == 0) no_space();
+    rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
+    if (rrhs == 0) no_space();
+    rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
+    if (rprec == 0) no_space();
+    rassoc = REALLOC(rassoc, nrules);
+    if (rassoc == 0) no_space();
+
+    ritem[0] = -1;
+    ritem[1] = goal->index;
+    ritem[2] = 0;
+    ritem[3] = -2;
+    rlhs[0] = 0;
+    rlhs[1] = 0;
+    rlhs[2] = start_symbol;
+    rrhs[0] = 0;
+    rrhs[1] = 0;
+    rrhs[2] = 1;
+
+    j = 4;
+    for (i = 3; i < nrules; ++i)
+    {
+	rlhs[i] = plhs[i]->index;
+	rrhs[i] = j;
+	assoc = TOKEN;
+	prec = 0;
+	while (pitem[j])
+	{
+	    ritem[j] = pitem[j]->index;
+	    if (pitem[j]->class == TERM)
+	    {
+		prec = pitem[j]->prec;
+		assoc = pitem[j]->assoc;
+	    }
+	    ++j;
+	}
+	ritem[j] = -i;
+	++j;
+	if (rprec[i] == UNDEFINED)
+	{
+	    rprec[i] = prec;
+	    rassoc[i] = assoc;
+	}
+    }
+    rrhs[i] = j;
+
+    FREE(plhs);
+    FREE(pitem);
+}
+
+
+print_grammar()
+{
+    register int i, j, k;
+    int spacing;
+    register FILE *f = verbose_file;
+
+    if (!vflag) return;
+
+    k = 1;
+    for (i = 2; i < nrules; ++i)
+    {
+	if (rlhs[i] != rlhs[i-1])
+	{
+	    if (i != 2) fprintf(f, "\n");
+	    fprintf(f, "%4d  %s :", i - 2, symbol_name[rlhs[i]]);
+	    spacing = strlen(symbol_name[rlhs[i]]) + 1;
+	}
+	else
+	{
+	    fprintf(f, "%4d  ", i - 2);
+	    j = spacing;
+	    while (--j >= 0) putc(' ', f);
+	    putc('|', f);
+	}
+
+	while (ritem[k] >= 0)
+	{
+	    fprintf(f, " %s", symbol_name[ritem[k]]);
+	    ++k;
+	}
+	++k;
+	putc('\n', f);
+    }
+}
+
+
+reader()
+{
+    write_section(banner);
+    create_symbol_table();
+    read_declarations();
+    read_grammar();
+    free_symbol_table();
+    free_tags();
+    pack_names();
+    check_symbols();
+    pack_symbols();
+    pack_grammar();
+    free_symbols();
+    print_grammar();
+}
Index: /trunk/minix/commands/byacc/skeleton.c
===================================================================
--- /trunk/minix/commands/byacc/skeleton.c	(revision 9)
+++ /trunk/minix/commands/byacc/skeleton.c	(revision 9)
@@ -0,0 +1,306 @@
+#include "defs.h"
+
+/*  The definition of yysccsid in the banner should be replaced with	*/
+/*  a #pragma ident directive if the target C compiler supports		*/
+/*  #pragma ident directives.						*/
+/*									*/
+/*  If the skeleton is changed, the banner should be changed so that	*/
+/*  the altered version can be easily distinguished from the original.	*/
+/*									*/
+/*  The #defines included with the banner are there because they are	*/
+/*  useful in subsequent code.  The macros #defined in the header or	*/
+/*  the body either are not useful outside of semantic actions or	*/
+/*  are conditional.							*/
+
+char *banner[] =
+{
+    "#ifndef lint",
+    "static char yysccsid[] = \"@(#)yaccpar	1.9 (Berkeley) 02/21/93\";",
+    "#endif",
+    "#define YYBYACC 1",
+    "#define YYMAJOR 1",
+    "#define YYMINOR 9",
+    "#define yyclearin (yychar=(-1))",
+    "#define yyerrok (yyerrflag=0)",
+    "#define YYRECOVERING (yyerrflag!=0)",
+    0
+};
+
+
+char *tables[] =
+{
+    "extern short yylhs[];",
+    "extern short yylen[];",
+    "extern short yydefred[];",
+    "extern short yydgoto[];",
+    "extern short yysindex[];",
+    "extern short yyrindex[];",
+    "extern short yygindex[];",
+    "extern short yytable[];",
+    "extern short yycheck[];",
+    "#if YYDEBUG",
+    "extern char *yyname[];",
+    "extern char *yyrule[];",
+    "#endif",
+    0
+};
+
+
+char *header[] =
+{
+    "#ifdef YYSTACKSIZE",
+    "#undef YYMAXDEPTH",
+    "#define YYMAXDEPTH YYSTACKSIZE",
+    "#else",
+    "#ifdef YYMAXDEPTH",
+    "#define YYSTACKSIZE YYMAXDEPTH",
+    "#else",
+    "#define YYSTACKSIZE 500",
+    "#define YYMAXDEPTH 500",
+    "#endif",
+    "#endif",
+    "int yydebug;",
+    "int yynerrs;",
+    "int yyerrflag;",
+    "int yychar;",
+    "short *yyssp;",
+    "YYSTYPE *yyvsp;",
+    "YYSTYPE yyval;",
+    "YYSTYPE yylval;",
+    "short yyss[YYSTACKSIZE];",
+    "YYSTYPE yyvs[YYSTACKSIZE];",
+    "#define yystacksize YYSTACKSIZE",
+    0
+};
+
+
+char *body[] =
+{
+    "#define YYABORT goto yyabort",
+    "#define YYREJECT goto yyabort",
+    "#define YYACCEPT goto yyaccept",
+    "#define YYERROR goto yyerrlab",
+    "int",
+    "yyparse()",
+    "{",
+    "    register int yym, yyn, yystate;",
+    "#if YYDEBUG",
+    "    register char *yys;",
+    "    extern char *getenv();",
+    "",
+    "    if (yys = getenv(\"YYDEBUG\"))",
+    "    {",
+    "        yyn = *yys;",
+    "        if (yyn >= '0' && yyn <= '9')",
+    "            yydebug = yyn - '0';",
+    "    }",
+    "#endif",
+    "",
+    "    yynerrs = 0;",
+    "    yyerrflag = 0;",
+    "    yychar = (-1);",
+    "",
+    "    yyssp = yyss;",
+    "    yyvsp = yyvs;",
+    "    *yyssp = yystate = 0;",
+    "",
+    "yyloop:",
+    "    if (yyn = yydefred[yystate]) goto yyreduce;",
+    "    if (yychar < 0)",
+    "    {",
+    "        if ((yychar = yylex()) < 0) yychar = 0;",
+    "#if YYDEBUG",
+    "        if (yydebug)",
+    "        {",
+    "            yys = 0;",
+    "            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];",
+    "            if (!yys) yys = \"illegal-symbol\";",
+    "            printf(\"%sdebug: state %d, reading %d (%s)\\n\",",
+    "                    YYPREFIX, yystate, yychar, yys);",
+    "        }",
+    "#endif",
+    "    }",
+    "    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&",
+    "            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)",
+    "    {",
+    "#if YYDEBUG",
+    "        if (yydebug)",
+    "            printf(\"%sdebug: state %d, shifting to state %d\\n\",",
+    "                    YYPREFIX, yystate, yytable[yyn]);",
+    "#endif",
+    "        if (yyssp >= yyss + yystacksize - 1)",
+    "        {",
+    "            goto yyoverflow;",
+    "        }",
+    "        *++yyssp = yystate = yytable[yyn];",
+    "        *++yyvsp = yylval;",
+    "        yychar = (-1);",
+    "        if (yyerrflag > 0)  --yyerrflag;",
+    "        goto yyloop;",
+    "    }",
+    "    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&",
+    "            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)",
+    "    {",
+    "        yyn = yytable[yyn];",
+    "        goto yyreduce;",
+    "    }",
+    "    if (yyerrflag) goto yyinrecovery;",
+    "#ifdef lint",
+    "    goto yynewerror;",
+    "#endif",
+    "yynewerror:",
+    "    yyerror(\"syntax error\");",
+    "#ifdef lint",
+    "    goto yyerrlab;",
+    "#endif",
+    "yyerrlab:",
+    "    ++yynerrs;",
+    "yyinrecovery:",
+    "    if (yyerrflag < 3)",
+    "    {",
+    "        yyerrflag = 3;",
+    "        for (;;)",
+    "        {",
+    "            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&",
+    "                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)",
+    "            {",
+    "#if YYDEBUG",
+    "                if (yydebug)",
+    "                    printf(\"%sdebug: state %d, error recovery shifting\\",
+    " to state %d\\n\", YYPREFIX, *yyssp, yytable[yyn]);",
+    "#endif",
+    "                if (yyssp >= yyss + yystacksize - 1)",
+    "                {",
+    "                    goto yyoverflow;",
+    "                }",
+    "                *++yyssp = yystate = yytable[yyn];",
+    "                *++yyvsp = yylval;",
+    "                goto yyloop;",
+    "            }",
+    "            else",
+    "            {",
+    "#if YYDEBUG",
+    "                if (yydebug)",
+    "                    printf(\"%sdebug: error recovery discarding state %d\
+\\n\",",
+    "                            YYPREFIX, *yyssp);",
+    "#endif",
+    "                if (yyssp <= yyss) goto yyabort;",
+    "                --yyssp;",
+    "                --yyvsp;",
+    "            }",
+    "        }",
+    "    }",
+    "    else",
+    "    {",
+    "        if (yychar == 0) goto yyabort;",
+    "#if YYDEBUG",
+    "        if (yydebug)",
+    "        {",
+    "            yys = 0;",
+    "            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];",
+    "            if (!yys) yys = \"illegal-symbol\";",
+    "            printf(\"%sdebug: state %d, error recovery discards token %d\
+ (%s)\\n\",",
+    "                    YYPREFIX, yystate, yychar, yys);",
+    "        }",
+    "#endif",
+    "        yychar = (-1);",
+    "        goto yyloop;",
+    "    }",
+    "yyreduce:",
+    "#if YYDEBUG",
+    "    if (yydebug)",
+    "        printf(\"%sdebug: state %d, reducing by rule %d (%s)\\n\",",
+    "                YYPREFIX, yystate, yyn, yyrule[yyn]);",
+    "#endif",
+    "    yym = yylen[yyn];",
+    "    yyval = yyvsp[1-yym];",
+    "    switch (yyn)",
+    "    {",
+    0
+};
+
+
+char *trailer[] =
+{
+    "    }",
+    "    yyssp -= yym;",
+    "    yystate = *yyssp;",
+    "    yyvsp -= yym;",
+    "    yym = yylhs[yyn];",
+    "    if (yystate == 0 && yym == 0)",
+    "    {",
+    "#if YYDEBUG",
+    "        if (yydebug)",
+    "            printf(\"%sdebug: after reduction, shifting from state 0 to\\",
+    " state %d\\n\", YYPREFIX, YYFINAL);",
+    "#endif",
+    "        yystate = YYFINAL;",
+    "        *++yyssp = YYFINAL;",
+    "        *++yyvsp = yyval;",
+    "        if (yychar < 0)",
+    "        {",
+    "            if ((yychar = yylex()) < 0) yychar = 0;",
+    "#if YYDEBUG",
+    "            if (yydebug)",
+    "            {",
+    "                yys = 0;",
+    "                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];",
+    "                if (!yys) yys = \"illegal-symbol\";",
+    "                printf(\"%sdebug: state %d, reading %d (%s)\\n\",",
+    "                        YYPREFIX, YYFINAL, yychar, yys);",
+    "            }",
+    "#endif",
+    "        }",
+    "        if (yychar == 0) goto yyaccept;",
+    "        goto yyloop;",
+    "    }",
+    "    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&",
+    "            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)",
+    "        yystate = yytable[yyn];",
+    "    else",
+    "        yystate = yydgoto[yym];",
+    "#if YYDEBUG",
+    "    if (yydebug)",
+    "        printf(\"%sdebug: after reduction, shifting from state %d \\",
+    "to state %d\\n\", YYPREFIX, *yyssp, yystate);",
+    "#endif",
+    "    if (yyssp >= yyss + yystacksize - 1)",
+    "    {",
+    "        goto yyoverflow;",
+    "    }",
+    "    *++yyssp = yystate;",
+    "    *++yyvsp = yyval;",
+    "    goto yyloop;",
+    "yyoverflow:",
+    "    yyerror(\"yacc stack overflow\");",
+    "yyabort:",
+    "    return (1);",
+    "yyaccept:",
+    "    return (0);",
+    "}",
+    0
+};
+
+
+write_section(section)
+char *section[];
+{
+    register int c;
+    register int i;
+    register char *s;
+    register FILE *f;
+
+    f = code_file;
+    for (i = 0; s = section[i]; ++i)
+    {
+	++outline;
+	while (c = *s)
+	{
+	    putc(c, f);
+	    ++s;
+	}
+	putc('\n', f);
+    }
+}
Index: /trunk/minix/commands/byacc/symtab.c
===================================================================
--- /trunk/minix/commands/byacc/symtab.c	(revision 9)
+++ /trunk/minix/commands/byacc/symtab.c	(revision 9)
@@ -0,0 +1,119 @@
+#include "defs.h"
+
+
+/* TABLE_SIZE is the number of entries in the symbol table. */
+/* TABLE_SIZE must be a power of two.			    */
+
+#define	TABLE_SIZE 1024
+
+
+bucket **symbol_table;
+bucket *first_symbol;
+bucket *last_symbol;
+
+
+int
+hash(name)
+char *name;
+{
+    register char *s;
+    register int c, k;
+
+    assert(name && *name);
+    s = name;
+    k = *s;
+    while (c = *++s)
+	k = (31*k + c) & (TABLE_SIZE - 1);
+
+    return (k);
+}
+
+
+bucket *
+make_bucket(name)
+char *name;
+{
+    register bucket *bp;
+
+    assert(name);
+    bp = (bucket *) MALLOC(sizeof(bucket));
+    if (bp == 0) no_space();
+    bp->link = 0;
+    bp->next = 0;
+    bp->name = MALLOC(strlen(name) + 1);
+    if (bp->name == 0) no_space();
+    bp->tag = 0;
+    bp->value = UNDEFINED;
+    bp->index = 0;
+    bp->prec = 0;
+    bp-> class = UNKNOWN;
+    bp->assoc = TOKEN;
+
+    if (bp->name == 0) no_space();
+    strcpy(bp->name, name);
+
+    return (bp);
+}
+
+
+bucket *
+lookup(name)
+char *name;
+{
+    register bucket *bp, **bpp;
+
+    bpp = symbol_table + hash(name);
+    bp = *bpp;
+
+    while (bp)
+    {
+	if (strcmp(name, bp->name) == 0) return (bp);
+	bpp = &bp->link;
+	bp = *bpp;
+    }
+
+    *bpp = bp = make_bucket(name);
+    last_symbol->next = bp;
+    last_symbol = bp;
+
+    return (bp);
+}
+
+
+create_symbol_table()
+{
+    register int i;
+    register bucket *bp;
+
+    symbol_table = (bucket **) MALLOC(TABLE_SIZE*sizeof(bucket *));
+    if (symbol_table == 0) no_space();
+    for (i = 0; i < TABLE_SIZE; i++)
+	symbol_table[i] = 0;
+
+    bp = make_bucket("error");
+    bp->index = 1;
+    bp->class = TERM;
+
+    first_symbol = bp;
+    last_symbol = bp;
+    symbol_table[hash("error")] = bp;
+}
+
+
+free_symbol_table()
+{
+    FREE(symbol_table);
+    symbol_table = 0;
+}
+
+
+free_symbols()
+{
+    register bucket *p, *q;
+
+    for (p = first_symbol; p; p = q)
+    {
+	q = p->next;
+	FREE(p);
+    }
+}
Index: /trunk/minix/commands/byacc/verbose.c
===================================================================
--- /trunk/minix/commands/byacc/verbose.c	(revision 9)
+++ /trunk/minix/commands/byacc/verbose.c	(revision 9)
@@ -0,0 +1,329 @@
+
+#include "defs.h"
+
+
+static short *null_rules;
+
+verbose()
+{
+    register int i;
+
+    if (!vflag) return;
+
+    null_rules = (short *) MALLOC(nrules*sizeof(short));
+    if (null_rules == 0) no_space();
+    fprintf(verbose_file, "\f\n");
+    for (i = 0; i < nstates; i++)
+	print_state(i);
+    FREE(null_rules);
+
+    if (nunused)
+	log_unused();
+    if (SRtotal || RRtotal)
+	log_conflicts();
+
+    fprintf(verbose_file, "\n\n%d terminals, %d nonterminals\n", ntokens,
+	    nvars);
+    fprintf(verbose_file, "%d grammar rules, %d states\n", nrules - 2, nstates);
+}
+
+
+log_unused()
+{
+    register int i;
+    register short *p;
+
+    fprintf(verbose_file, "\n\nRules never reduced:\n");
+    for (i = 3; i < nrules; ++i)
+    {
+	if (!rules_used[i])
+	{
+	    fprintf(verbose_file, "\t%s :", symbol_name[rlhs[i]]);
+	    for (p = ritem + rrhs[i]; *p >= 0; ++p)
+		fprintf(verbose_file, " %s", symbol_name[*p]);
+	    fprintf(verbose_file, "  (%d)\n", i - 2);
+	}
+    }
+}
+
+
+log_conflicts()
+{
+    register int i;
+
+    fprintf(verbose_file, "\n\n");
+    for (i = 0; i < nstates; i++)
+    {
+	if (SRconflicts[i] || RRconflicts[i])
+	{
+	    fprintf(verbose_file, "State %d contains ", i);
+	    if (SRconflicts[i] == 1)
+		fprintf(verbose_file, "1 shift/reduce conflict");
+	    else if (SRconflicts[i] > 1)
+		fprintf(verbose_file, "%d shift/reduce conflicts",
+			SRconflicts[i]);
+	    if (SRconflicts[i] && RRconflicts[i])
+		fprintf(verbose_file, ", ");
+	    if (RRconflicts[i] == 1)
+		fprintf(verbose_file, "1 reduce/reduce conflict");
+	    else if (RRconflicts[i] > 1)
+		fprintf(verbose_file, "%d reduce/reduce conflicts",
+			RRconflicts[i]);
+	    fprintf(verbose_file, ".\n");
+	}
+    }
+}
+
+
+print_state(state)
+int state;
+{
+    if (state)
+	fprintf(verbose_file, "\n\n");
+    if (SRconflicts[state] || RRconflicts[state])
+	print_conflicts(state);
+    fprintf(verbose_file, "state %d\n", state);
+    print_core(state);
+    print_nulls(state);
+    print_actions(state);
+}
+
+
+print_conflicts(state)
+int state;
+{
+    register int symbol, act, number;
+    register action *p;
+
+    symbol = -1;
+    for (p = parser[state]; p; p = p->next)
+    {
+	if (p->suppressed == 2)
+	    continue;
+
+	if (p->symbol != symbol)
+	{
+	    symbol = p->symbol;
+	    number = p->number;
+	    if (p->action_code == SHIFT)
+		act = SHIFT;
+	    else
+		act = REDUCE;
+	}
+	else if (p->suppressed == 1)
+	{
+	    if (state == final_state && symbol == 0)
+	    {
+		fprintf(verbose_file, "%d: shift/reduce conflict \
+(accept, reduce %d) on $end\n", state, p->number - 2);
+	    }
+	    else
+	    {
+		if (act == SHIFT)
+		{
+		    fprintf(verbose_file, "%d: shift/reduce conflict \
+(shift %d, reduce %d) on %s\n", state, number, p->number - 2,
+			    symbol_name[symbol]);
+		}
+		else
+		{
+		    fprintf(verbose_file, "%d: reduce/reduce conflict \
+(reduce %d, reduce %d) on %s\n", state, number - 2, p->number - 2,
+			    symbol_name[symbol]);
+		}
+	    }
+	}
+    }
+}
+
+
+print_core(state)
+int state;
+{
+    register int i;
+    register int k;
+    register int rule;
+    register core *statep;
+    register short *sp;
+    register short *sp1;
+
+    statep = state_table[state];
+    k = statep->nitems;
+
+    for (i = 0; i < k; i++)
+    {
+	sp1 = sp = ritem + statep->items[i];
+
+	while (*sp >= 0) ++sp;
+	rule = -(*sp);
+	fprintf(verbose_file, "\t%s : ", symbol_name[rlhs[rule]]);
+
+        for (sp = ritem + rrhs[rule]; sp < sp1; sp++)
+	    fprintf(verbose_file, "%s ", symbol_name[*sp]);
+
+	putc('.', verbose_file);
+
+	while (*sp >= 0)
+	{
+	    fprintf(verbose_file, " %s", symbol_name[*sp]);
+	    sp++;
+	}
+	fprintf(verbose_file, "  (%d)\n", -2 - *sp);
+    }
+}
+
+
+print_nulls(state)
+int state;
+{
+    register action *p;
+    register int i, j, k, nnulls;
+
+    nnulls = 0;
+    for (p = parser[state]; p; p = p->next)
+    {
+	if (p->action_code == REDUCE &&
+		(p->suppressed == 0 || p->suppressed == 1))
+	{
+	    i = p->number;
+	    if (rrhs[i] + 1 == rrhs[i+1])
+	    {
+		for (j = 0; j < nnulls && i > null_rules[j]; ++j)
+		    continue;
+
+		if (j == nnulls)
+		{
+		    ++nnulls;
+		    null_rules[j] = i;
+		}
+		else if (i != null_rules[j])
+		{
+		    ++nnulls;
+		    for (k = nnulls - 1; k > j; --k)
+			null_rules[k] = null_rules[k-1];
+		    null_rules[j] = i;
+		}
+	    }
+	}
+    }
+
+    for (i = 0; i < nnulls; ++i)
+    {
+	j = null_rules[i];
+	fprintf(verbose_file, "\t%s : .  (%d)\n", symbol_name[rlhs[j]],
+		j - 2);
+    }
+    fprintf(verbose_file, "\n");
+}
+
+
+print_actions(stateno)
+int stateno;
+{
+    register action *p;
+    register shifts *sp;
+    register int as;
+
+    if (stateno == final_state)
+	fprintf(verbose_file, "\t$end  accept\n");
+
+    p = parser[stateno];
+    if (p)
+    {
+	print_shifts(p);
+	print_reductions(p, defred[stateno]);
+    }
+
+    sp = shift_table[stateno];
+    if (sp && sp->nshifts > 0)
+    {
+	as = accessing_symbol[sp->shift[sp->nshifts - 1]];
+	if (ISVAR(as))
+	    print_gotos(stateno);
+    }
+}
+
+
+print_shifts(p)
+register action *p;
+{
+    register int count;
+    register action *q;
+
+    count = 0;
+    for (q = p; q; q = q->next)
+    {
+	if (q->suppressed < 2 && q->action_code == SHIFT)
+	    ++count;
+    }
+
+    if (count > 0)
+    {
+	for (; p; p = p->next)
+	{
+	    if (p->action_code == SHIFT && p->suppressed == 0)
+		fprintf(verbose_file, "\t%s  shift %d\n",
+			    symbol_name[p->symbol], p->number);
+	}
+    }
+}
+
+
+print_reductions(p, defred)
+register action *p;
+register int defred;
+{
+    register int k, anyreds;
+    register action *q;
+
+    anyreds = 0;
+    for (q = p; q ; q = q->next)
+    {
+	if (q->action_code == REDUCE && q->suppressed < 2)
+	{
+	    anyreds = 1;
+	    break;
+	}
+    }
+
+    if (anyreds == 0)
+	fprintf(verbose_file, "\t.  error\n");
+    else
+    {
+	for (; p; p = p->next)
+	{
+	    if (p->action_code == REDUCE && p->number != defred)
+	    {
+		k = p->number - 2;
+		if (p->suppressed == 0)
+		    fprintf(verbose_file, "\t%s  reduce %d\n",
+			    symbol_name[p->symbol], k);
+	    }
+	}
+
+        if (defred > 0)
+	    fprintf(verbose_file, "\t.  reduce %d\n", defred - 2);
+    }
+}
+
+
+print_gotos(stateno)
+int stateno;
+{
+    register int i, k;
+    register int as;
+    register short *to_state;
+    register shifts *sp;
+
+    putc('\n', verbose_file);
+    sp = shift_table[stateno];
+    to_state = sp->shift;
+    for (i = 0; i < sp->nshifts; ++i)
+    {
+	k = to_state[i];
+	as = accessing_symbol[k];
+	if (ISVAR(as))
+	    fprintf(verbose_file, "\t%s  goto %d\n", symbol_name[as], k);
+    }
+}
+
Index: /trunk/minix/commands/byacc/warshall.c
===================================================================
--- /trunk/minix/commands/byacc/warshall.c	(revision 9)
+++ /trunk/minix/commands/byacc/warshall.c	(revision 9)
@@ -0,0 +1,82 @@
+#include "defs.h"
+
+transitive_closure(R, n)
+unsigned *R;
+int n;
+{
+    register int rowsize;
+    register unsigned i;
+    register unsigned *rowj;
+    register unsigned *rp;
+    register unsigned *rend;
+    register unsigned *ccol;
+    register unsigned *relend;
+    register unsigned *cword;
+    register unsigned *rowi;
+
+    rowsize = WORDSIZE(n);
+    relend = R + n*rowsize;
+
+    cword = R;
+    i = 0;
+    rowi = R;
+    while (rowi < relend)
+    {
+	ccol = cword;
+	rowj = R;
+
+	while (rowj < relend)
+	{
+	    if (*ccol & (1 << i))
+	    {
+		rp = rowi;
+		rend = rowj + rowsize;
+		while (rowj < rend)
+		    *rowj++ |= *rp++;
+	    }
+	    else
+	    {
+		rowj += rowsize;
+	    }
+
+	    ccol += rowsize;
+	}
+
+	if (++i >= BITS_PER_WORD)
+	{
+	    i = 0;
+	    cword++;
+	}
+
+	rowi += rowsize;
+    }
+}
+
+reflexive_transitive_closure(R, n)
+unsigned *R;
+int n;
+{
+    register int rowsize;
+    register unsigned i;
+    register unsigned *rp;
+    register unsigned *relend;
+
+    transitive_closure(R, n);
+
+    rowsize = WORDSIZE(n);
+    relend = R + n*rowsize;
+
+    i = 0;
+    rp = R;
+    while (rp < relend)
+    {
+	*rp |= (1 << i);
+	if (++i >= BITS_PER_WORD)
+	{
+	    i = 0;
+	    rp++;
+	}
+
+	rp += rowsize;
+    }
+}
Index: /trunk/minix/commands/bzip2-1.0.3/CHANGES
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/CHANGES	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/CHANGES	(revision 9)
@@ -0,0 +1,275 @@
+
+
+0.9.0
+~~~~~
+First version.
+
+
+0.9.0a
+~~~~~~
+Removed 'ranlib' from Makefile, since most modern Unix-es 
+don't need it, or even know about it.
+
+
+0.9.0b
+~~~~~~
+Fixed a problem with error reporting in bzip2.c.  This does not effect
+the library in any way.  Problem is: versions 0.9.0 and 0.9.0a (of the
+program proper) compress and decompress correctly, but give misleading
+error messages (internal panics) when an I/O error occurs, instead of
+reporting the problem correctly.  This shouldn't give any data loss
+(as far as I can see), but is confusing.
+
+Made the inline declarations disappear for non-GCC compilers.
+
+
+0.9.0c
+~~~~~~
+Fixed some problems in the library pertaining to some boundary cases.
+This makes the library behave more correctly in those situations.  The
+fixes apply only to features (calls and parameters) not used by
+bzip2.c, so the non-fixedness of them in previous versions has no
+effect on reliability of bzip2.c.
+
+In bzlib.c:
+   * made zero-length BZ_FLUSH work correctly in bzCompress().
+   * fixed bzWrite/bzRead to ignore zero-length requests.
+   * fixed bzread to correctly handle read requests after EOF.
+   * wrong parameter order in call to bzDecompressInit in
+     bzBuffToBuffDecompress.  Fixed.
+
+In compress.c:
+   * changed setting of nGroups in sendMTFValues() so as to 
+     do a bit better on small files.  This _does_ effect
+     bzip2.c.
+
+
+0.9.5a
+~~~~~~
+Major change: add a fallback sorting algorithm (blocksort.c)
+to give reasonable behaviour even for very repetitive inputs.
+Nuked --repetitive-best and --repetitive-fast since they are
+no longer useful.
+
+Minor changes: mostly a whole bunch of small changes/
+bugfixes in the driver (bzip2.c).  Changes pertaining to the
+user interface are:
+
+   allow decompression of symlink'd files to stdout
+   decompress/test files even without .bz2 extension
+   give more accurate error messages for I/O errors
+   when compressing/decompressing to stdout, don't catch control-C
+   read flags from BZIP2 and BZIP environment variables
+   decline to break hard links to a file unless forced with -f
+   allow -c flag even with no filenames
+   preserve file ownerships as far as possible
+   make -s -1 give the expected block size (100k)
+   add a flag -q --quiet to suppress nonessential warnings
+   stop decoding flags after --, so files beginning in - can be handled
+   resolved inconsistent naming: bzcat or bz2cat ?
+   bzip2 --help now returns 0
+
+Programming-level changes are:
+
+   fixed syntax error in GET_LL4 for Borland C++ 5.02
+   let bzBuffToBuffDecompress return BZ_DATA_ERROR{_MAGIC}
+   fix overshoot of mode-string end in bzopen_or_bzdopen
+   wrapped bzlib.h in #ifdef __cplusplus ... extern "C" { ... }
+   close file handles under all error conditions
+   added minor mods so it compiles with DJGPP out of the box
+   fixed Makefile so it doesn't give problems with BSD make
+   fix uninitialised memory reads in dlltest.c
+
+0.9.5b
+~~~~~~
+Open stdin/stdout in binary mode for DJGPP.
+
+0.9.5c
+~~~~~~
+Changed BZ_N_OVERSHOOT to be ... + 2 instead of ... + 1.  The + 1
+version could cause the sorted order to be wrong in some extremely
+obscure cases.  Also changed setting of quadrant in blocksort.c.
+
+0.9.5d
+~~~~~~
+The only functional change is to make bzlibVersion() in the library
+return the correct string.  This has no effect whatsoever on the
+functioning of the bzip2 program or library.  Added a couple of casts
+so the library compiles without warnings at level 3 in MS Visual
+Studio 6.0.  Included a Y2K statement in the file Y2K_INFO.  All other
+changes are minor documentation changes.
+
+1.0
+~~~
+Several minor bugfixes and enhancements:
+
+* Large file support.  The library uses 64-bit counters to
+  count the volume of data passing through it.  bzip2.c 
+  is now compiled with -D_FILE_OFFSET_BITS=64 to get large
+  file support from the C library.  -v correctly prints out
+  file sizes greater than 4 gigabytes.  All these changes have
+  been made without assuming a 64-bit platform or a C compiler
+  which supports 64-bit ints, so, except for the C library
+  aspect, they are fully portable.
+
+* Decompression robustness.  The library/program should be
+  robust to any corruption of compressed data, detecting and
+  handling _all_ corruption, instead of merely relying on
+  the CRCs.  What this means is that the program should 
+  never crash, given corrupted data, and the library should
+  always return BZ_DATA_ERROR.
+
+* Fixed an obscure race-condition bug only ever observed on
+  Solaris, in which, if you were very unlucky and issued
+  control-C at exactly the wrong time, both input and output
+  files would be deleted.
+
+* Don't run out of file handles on test/decompression when
+  large numbers of files have invalid magic numbers.
+
+* Avoid library namespace pollution.  Prefix all exported 
+  symbols with BZ2_.
+
+* Minor sorting enhancements from my DCC2000 paper.
+
+* Advance the version number to 1.0, so as to counteract the
+  (false-in-this-case) impression some people have that programs 
+  with version numbers less than 1.0 are in some way, experimental,
+  pre-release versions.
+
+* Create an initial Makefile-libbz2_so to build a shared library.
+  Yes, I know I should really use libtool et al ...
+
+* Make the program exit with 2 instead of 0 when decompression
+  fails due to a bad magic number (ie, an invalid bzip2 header).
+  Also exit with 1 (as the manual claims :-) whenever a diagnostic
+  message would have been printed AND the corresponding operation 
+  is aborted, for example
+     bzip2: Output file xx already exists.
+  When a diagnostic message is printed but the operation is not 
+  aborted, for example
+     bzip2: Can't guess original name for wurble -- using wurble.out
+  then the exit value 0 is returned, unless some other problem is
+  also detected.
+
+  I think it corresponds more closely to what the manual claims now.
+
+
+1.0.1
+~~~~~
+* Modified dlltest.c so it uses the new BZ2_ naming scheme.
+* Modified makefile-msc to fix minor build probs on Win2k.
+* Updated README.COMPILATION.PROBLEMS.
+
+There are no functionality changes or bug fixes relative to version
+1.0.0.  This is just a documentation update + a fix for minor Win32
+build problems.  For almost everyone, upgrading from 1.0.0 to 1.0.1 is
+utterly pointless.  Don't bother.
+
+
+1.0.2
+~~~~~
+A bug fix release, addressing various minor issues which have appeared
+in the 18 or so months since 1.0.1 was released.  Most of the fixes
+are to do with file-handling or documentation bugs.  To the best of my
+knowledge, there have been no data-loss-causing bugs reported in the
+compression/decompression engine of 1.0.0 or 1.0.1.
+
+Note that this release does not improve the rather crude build system
+for Unix platforms.  The general plan here is to autoconfiscate/
+libtoolise 1.0.2 soon after release, and release the result as 1.1.0
+or perhaps 1.2.0.  That, however, is still just a plan at this point.
+
+Here are the changes in 1.0.2.  Bug-reporters and/or patch-senders in
+parentheses.
+
+* Fix an infinite segfault loop in 1.0.1 when a directory is
+  encountered in -f (force) mode.
+     (Trond Eivind Glomsrod, Nicholas Nethercote, Volker Schmidt)
+
+* Avoid double fclose() of output file on certain I/O error paths.
+     (Solar Designer)
+
+* Don't fail with internal error 1007 when fed a long stream (> 48MB)
+  of byte 251.  Also print useful message suggesting that 1007s may be
+  caused by bad memory.
+     (noticed by Juan Pedro Vallejo, fixed by me)
+
+* Fix uninitialised variable silly bug in demo prog dlltest.c.
+     (Jorj Bauer)
+
+* Remove 512-MB limitation on recovered file size for bzip2recover
+  on selected platforms which support 64-bit ints.  At the moment
+  all GCC supported platforms, and Win32.
+     (me, Alson van der Meulen)
+
+* Hard-code header byte values, to give correct operation on platforms
+  using EBCDIC as their native character set (IBM's OS/390).
+     (Leland Lucius)
+
+* Copy file access times correctly.
+     (Marty Leisner)
+
+* Add distclean and check targets to Makefile.
+     (Michael Carmack)
+
+* Parameterise use of ar and ranlib in Makefile.  Also add $(LDFLAGS).
+     (Rich Ireland, Bo Thorsen)
+
+* Pass -p (create parent dirs as needed) to mkdir during make install.
+     (Jeremy Fusco)
+
+* Dereference symlinks when copying file permissions in -f mode.
+     (Volker Schmidt)
+
+* Majorly simplify implementation of uInt64_qrm10.
+     (Bo Lindbergh)
+
+* Check the input file still exists before deleting the output one,
+  when aborting in cleanUpAndFail().
+     (Joerg Prante, Robert Linden, Matthias Krings)
+
+Also a bunch of patches courtesy of Philippe Troin, the Debian maintainer
+of bzip2:
+
+* Wrapper scripts (with manpages): bzdiff, bzgrep, bzmore.
+
+* Spelling changes and minor enhancements in bzip2.1.
+
+* Avoid race condition between creating the output file and setting its
+  interim permissions safely, by using fopen_output_safely().
+  No changes to bzip2recover since there is no issue with file
+  permissions there.
+
+* do not print senseless report with -v when compressing an empty
+  file.
+
+* bzcat -f works on non-bzip2 files.
+
+* do not try to escape shell meta-characters on unix (the shell takes
+  care of these).
+
+* added --fast and --best aliases for -1 -9 for gzip compatibility.
+
+
+1.0.3 (15 Feb 05)
+~~~~~~~~~~~~~~~~~
+Fixes some minor bugs since the last version, 1.0.2.
+
+* Further robustification against corrupted compressed data.
+  There are currently no known bitstreams which can cause the
+  decompressor to crash, loop or access memory which does not
+  belong to it.  If you are using bzip2 or the library to 
+  decompress bitstreams from untrusted sources, an upgrade
+  to 1.0.3 is recommended.
+
+* The documentation has been converted to XML, from which html
+  and pdf can be derived.
+
+* Various minor bugs in the documentation have been fixed.
+
+* Fixes for various compilation warnings with newer versions of
+  gcc, and on 64-bit platforms.
+
+* The BZ_NO_STDIO cpp symbol was not properly observed in 1.0.2.
+  This has been fixed.
Index: /trunk/minix/commands/bzip2-1.0.3/LICENSE
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/LICENSE	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/LICENSE	(revision 9)
@@ -0,0 +1,40 @@
+
+This program, "bzip2", the associated library "libbzip2", and all
+documentation, are copyright (C) 1996-2005 Julian R Seward.  All
+rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. The origin of this software must not be misrepresented; you must 
+   not claim that you wrote the original software.  If you use this 
+   software in a product, an acknowledgment in the product 
+   documentation would be appreciated but is not required.
+
+3. Altered source versions must be plainly marked as such, and must
+   not be misrepresented as being the original software.
+
+4. The name of the author may not be used to endorse or promote 
+   products derived from this software without specific prior written 
+   permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Julian Seward, Cambridge, UK.
+jseward@acm.org
+bzip2/libbzip2 version 1.0.3 of 15 February 2005
+
Index: /trunk/minix/commands/bzip2-1.0.3/Makefile
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/Makefile	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/Makefile	(revision 9)
@@ -0,0 +1,216 @@
+
+SHELL=/bin/sh
+
+# To assist in cross-compiling
+CC=exec cc
+AR=ar
+ARFLAGS=cr
+RANLIB=ranlib
+LDFLAGS=
+
+BIGFILES=#-D_FILE_OFFSET_BITS=64
+CFLAGS=-Wall -Winline -O -g $(BIGFILES) -Dlstat=stat -D_POSIX_SOURCE=1
+
+# Where you want it installed when you do 'make install'
+PREFIX=/usr/local
+PREFIX_BIN=$(PREFIX)/bin
+PREFIX_LIB=$(PREFIX)/lib
+PREFIX_MAN=$(PREFIX)/man
+PREFIX_INC=$(PREFIX)/include
+
+
+OBJS= blocksort.o  \
+      huffman.o    \
+      crctable.o   \
+      randtable.o  \
+      compress.o   \
+      decompress.o \
+      bzlib.o
+
+all: all_notest
+
+all_notest: libbz2.a bzip2 bzip2recover 
+	chmem =8000000 bzip2
+
+bzip2: libbz2.a bzip2.o
+	$(CC) $(CFLAGS) $(LDFLAGS) -o bzip2 bzip2.o -L. -lbz2
+
+bzip2recover: bzip2recover.o
+	$(CC) $(CFLAGS) $(LDFLAGS) -o bzip2recover bzip2recover.o
+
+libbz2.a: $(OBJS)
+	rm -f libbz2.a
+	$(AR) $(ARFLAGS) libbz2.a $(OBJS)
+	@if ( test -f $(RANLIB) -o -f /usr/bin/ranlib -o \
+		-f /bin/ranlib -o -f /usr/ccs/bin/ranlib ) ; then \
+		echo $(RANLIB) libbz2.a ; \
+		$(RANLIB) libbz2.a ; \
+	fi
+
+check: test
+test: bzip2 test_nodep
+
+test_nodep:
+	@cat words1
+	./bzip2 -1  < sample1.ref > sample1.rb2
+	./bzip2 -2  < sample2.ref > sample2.rb2
+	./bzip2 -3  < sample3.ref > sample3.rb2
+	./bzip2 -d  < sample1.bz2 > sample1.tst
+	./bzip2 -d  < sample2.bz2 > sample2.tst
+	./bzip2 -ds < sample3.bz2 > sample3.tst
+	cmp sample1.bz2 sample1.rb2 
+	cmp sample2.bz2 sample2.rb2
+	cmp sample3.bz2 sample3.rb2
+	cmp sample1.tst sample1.ref
+	cmp sample2.tst sample2.ref
+	cmp sample3.tst sample3.ref
+	@cat words3
+
+install: bzip2 bzip2recover
+	if ( test ! -d $(PREFIX_BIN) ) ; then mkdir -p $(PREFIX_BIN) ; fi
+	if ( test ! -d $(PREFIX_LIB) ) ; then mkdir -p $(PREFIX_LIB) ; fi
+	if ( test ! -d $(PREFIX_MAN) ) ; then mkdir -p $(PREFIX_MAN) ; fi
+	if ( test ! -d $(PREFIX_MAN)/man1 ) ; then mkdir -p $(PREFIX_MAN)/man1 ; fi
+	if ( test ! -d $(PREFIX_INC) ) ; then mkdir -p $(PREFIX_INC) ; fi
+	install -S 8M -o bin bzip2 $(PREFIX_BIN)/bzip2
+	install -S 4M -o bin bzip2 $(PREFIX_BIN)/bunzip2
+	install -S 2450k -o bin bzip2 $(PREFIX_BIN)/smallbunzip2
+	install -o bin bzip2 $(PREFIX_BIN)/bzcat
+	install -o bin bzip2recover $(PREFIX_BIN)/bzip2recover
+	chmod a+x $(PREFIX_BIN)/bzip2
+	chmod a+x $(PREFIX_BIN)/bunzip2
+	chmod a+x $(PREFIX_BIN)/bzcat
+	chmod a+x $(PREFIX_BIN)/bzip2recover
+	install -o bin bzip2.1 $(PREFIX_MAN)/man1
+	chmod a+r $(PREFIX_MAN)/man1/bzip2.1
+	install -o bin bzlib.h $(PREFIX_INC)
+	chmod a+r $(PREFIX_INC)/bzlib.h
+	install -o bin libbz2.a $(PREFIX_LIB)
+	chmod a+r $(PREFIX_LIB)/libbz2.a
+	install -o bin bzgrep $(PREFIX_BIN)/bzgrep
+	ln -f $(PREFIX_BIN)/bzgrep $(PREFIX_BIN)/bzegrep
+	ln -f $(PREFIX_BIN)/bzgrep $(PREFIX_BIN)/bzfgrep
+	chmod a+x $(PREFIX_BIN)/bzgrep
+	install -o bin bzmore $(PREFIX_BIN)/bzmore
+	ln -f $(PREFIX_BIN)/bzmore $(PREFIX_BIN)/bzless
+	chmod a+x $(PREFIX_BIN)/bzmore
+	install -o bin bzdiff $(PREFIX_BIN)/bzdiff
+	ln -f $(PREFIX_BIN)/bzdiff $(PREFIX_BIN)/bzcmp
+	chmod a+x $(PREFIX_BIN)/bzdiff
+	install -o bin bzgrep.1 bzmore.1 bzdiff.1 $(PREFIX_MAN)/man1
+	chmod a+r $(PREFIX_MAN)/man1/bzgrep.1
+	chmod a+r $(PREFIX_MAN)/man1/bzmore.1
+	chmod a+r $(PREFIX_MAN)/man1/bzdiff.1
+	echo ".so man1/bzgrep.1" > $(PREFIX_MAN)/man1/bzegrep.1
+	echo ".so man1/bzgrep.1" > $(PREFIX_MAN)/man1/bzfgrep.1
+	echo ".so man1/bzmore.1" > $(PREFIX_MAN)/man1/bzless.1
+	echo ".so man1/bzdiff.1" > $(PREFIX_MAN)/man1/bzcmp.1
+
+clean: 
+	rm -f *.o libbz2.a bzip2 bzip2recover \
+	sample1.rb2 sample2.rb2 sample3.rb2 \
+	sample1.tst sample2.tst sample3.tst
+
+blocksort.o: blocksort.c
+	@cat words0
+	$(CC) $(CFLAGS) -c blocksort.c
+huffman.o: huffman.c
+	$(CC) $(CFLAGS) -c huffman.c
+crctable.o: crctable.c
+	$(CC) $(CFLAGS) -c crctable.c
+randtable.o: randtable.c
+	$(CC) $(CFLAGS) -c randtable.c
+compress.o: compress.c
+	$(CC) $(CFLAGS) -c compress.c
+decompress.o: decompress.c
+	$(CC) $(CFLAGS) -c decompress.c
+bzlib.o: bzlib.c
+	$(CC) $(CFLAGS) -c bzlib.c
+bzip2.o: bzip2.c
+	$(CC) $(CFLAGS) -c bzip2.c
+bzip2recover.o: bzip2recover.c
+	$(CC) $(CFLAGS) -c bzip2recover.c
+
+
+distclean: clean
+	rm -f manual.ps manual.html manual.pdf
+
+DISTNAME=bzip2-1.0.3
+dist: check manual
+	rm -f $(DISTNAME)
+	ln -sf . $(DISTNAME)
+	tar cvf $(DISTNAME).tar \
+	   $(DISTNAME)/blocksort.c \
+	   $(DISTNAME)/huffman.c \
+	   $(DISTNAME)/crctable.c \
+	   $(DISTNAME)/randtable.c \
+	   $(DISTNAME)/compress.c \
+	   $(DISTNAME)/decompress.c \
+	   $(DISTNAME)/bzlib.c \
+	   $(DISTNAME)/bzip2.c \
+	   $(DISTNAME)/bzip2recover.c \
+	   $(DISTNAME)/bzlib.h \
+	   $(DISTNAME)/bzlib_private.h \
+	   $(DISTNAME)/Makefile \
+	   $(DISTNAME)/LICENSE \
+	   $(DISTNAME)/bzip2.1 \
+	   $(DISTNAME)/bzip2.1.preformatted \
+	   $(DISTNAME)/bzip2.txt \
+	   $(DISTNAME)/words0 \
+	   $(DISTNAME)/words1 \
+	   $(DISTNAME)/words2 \
+	   $(DISTNAME)/words3 \
+	   $(DISTNAME)/sample1.ref \
+	   $(DISTNAME)/sample2.ref \
+	   $(DISTNAME)/sample3.ref \
+	   $(DISTNAME)/sample1.bz2 \
+	   $(DISTNAME)/sample2.bz2 \
+	   $(DISTNAME)/sample3.bz2 \
+	   $(DISTNAME)/dlltest.c \
+	   $(DISTNAME)/manual.html \
+	   $(DISTNAME)/manual.pdf \
+	   $(DISTNAME)/manual.ps \
+	   $(DISTNAME)/README \
+	   $(DISTNAME)/README.COMPILATION.PROBLEMS \
+	   $(DISTNAME)/README.XML.STUFF \
+	   $(DISTNAME)/CHANGES \
+	   $(DISTNAME)/libbz2.def \
+	   $(DISTNAME)/libbz2.dsp \
+	   $(DISTNAME)/dlltest.dsp \
+	   $(DISTNAME)/makefile.msc \
+	   $(DISTNAME)/Y2K_INFO \
+	   $(DISTNAME)/unzcrash.c \
+	   $(DISTNAME)/spewG.c \
+	   $(DISTNAME)/mk251.c \
+	   $(DISTNAME)/bzdiff \
+	   $(DISTNAME)/bzdiff.1 \
+	   $(DISTNAME)/bzmore \
+	   $(DISTNAME)/bzmore.1 \
+	   $(DISTNAME)/bzgrep \
+	   $(DISTNAME)/bzgrep.1 \
+	   $(DISTNAME)/Makefile-libbz2_so \
+	   $(DISTNAME)/bz-common.xsl \
+	   $(DISTNAME)/bz-fo.xsl \
+	   $(DISTNAME)/bz-html.xsl \
+	   $(DISTNAME)/bzip.css \
+	   $(DISTNAME)/entities.xml \
+	   $(DISTNAME)/manual.xml \
+	   $(DISTNAME)/format.pl \
+	   $(DISTNAME)/xmlproc.sh
+	gzip -v $(DISTNAME).tar
+
+# For rebuilding the manual from sources on my SuSE 9.1 box
+
+MANUAL_SRCS= 	bz-common.xsl bz-fo.xsl bz-html.xsl bzip.css \
+		entities.xml manual.xml 
+
+manual: manual.html manual.ps manual.pdf
+
+manual.ps: $(MANUAL_SRCS)
+	./xmlproc.sh -ps manual.xml
+
+manual.pdf: $(MANUAL_SRCS)
+	./xmlproc.sh -pdf manual.xml
+
+manual.html: $(MANUAL_SRCS)
+	./xmlproc.sh -html manual.xml
Index: /trunk/minix/commands/bzip2-1.0.3/Makefile-libbz2_so
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/Makefile-libbz2_so	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/Makefile-libbz2_so	(revision 9)
@@ -0,0 +1,44 @@
+
+# This Makefile builds a shared version of the library, 
+# libbz2.so.1.0.3, with soname libbz2.so.1.0,
+# at least on x86-Linux (RedHat 7.2), 
+# with gcc-2.96 20000731 (Red Hat Linux 7.1 2.96-98).  
+# Please see the README file for some 
+# important info about building the library like this.
+
+SHELL=/bin/sh
+CC=gcc
+BIGFILES=-D_FILE_OFFSET_BITS=64
+CFLAGS=-fpic -fPIC -Wall -Winline -O -g
+
+OBJS= blocksort.o  \
+      huffman.o    \
+      crctable.o   \
+      randtable.o  \
+      compress.o   \
+      decompress.o \
+      bzlib.o
+
+all: $(OBJS)
+	$(CC) -shared -Wl,-soname -Wl,libbz2.so.1.0 -o libbz2.so.1.0.3 $(OBJS)
+	$(CC) $(CFLAGS) -o bzip2-shared bzip2.c libbz2.so.1.0.3
+	rm -f libbz2.so.1.0
+	ln -s libbz2.so.1.0.3 libbz2.so.1.0
+
+clean: 
+	rm -f $(OBJS) bzip2.o libbz2.so.1.0.3 libbz2.so.1.0 bzip2-shared
+
+blocksort.o: blocksort.c
+	$(CC) $(CFLAGS) -c blocksort.c
+huffman.o: huffman.c
+	$(CC) $(CFLAGS) -c huffman.c
+crctable.o: crctable.c
+	$(CC) $(CFLAGS) -c crctable.c
+randtable.o: randtable.c
+	$(CC) $(CFLAGS) -c randtable.c
+compress.o: compress.c
+	$(CC) $(CFLAGS) -c compress.c
+decompress.o: decompress.c
+	$(CC) $(CFLAGS) -c decompress.c
+bzlib.o: bzlib.c
+	$(CC) $(CFLAGS) -c bzlib.c
Index: /trunk/minix/commands/bzip2-1.0.3/README.COMPILATION.PROBLEMS
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/README.COMPILATION.PROBLEMS	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/README.COMPILATION.PROBLEMS	(revision 9)
@@ -0,0 +1,39 @@
+
+bzip2-1.0.3 should compile without problems on the vast majority of
+platforms.  Using the supplied Makefile, I've built and tested it
+myself for x86-linux and x86_64-linux.  With makefile.msc, Visual C++
+6.0 and nmake, you can build a native Win32 version too.  Large file
+support seems to work correctly on at least alpha-tru64unix and
+x86-cygwin32 (on Windows 2000).
+
+When I say "large file" I mean a file of size 2,147,483,648 (2^31)
+bytes or above.  Many older OSs can't handle files above this size,
+but many newer ones can.  Large files are pretty huge -- most files
+you'll encounter are not Large Files.
+
+Earlier versions of bzip2 (0.1, 0.9.0, 0.9.5) compiled on a wide
+variety of platforms without difficulty, and I hope this version will
+continue in that tradition.  However, in order to support large files,
+I've had to include the define -D_FILE_OFFSET_BITS=64 in the Makefile.
+This can cause problems.
+
+The technique of adding -D_FILE_OFFSET_BITS=64 to get large file
+support is, as far as I know, the Recommended Way to get correct large
+file support.  For more details, see the Large File Support
+Specification, published by the Large File Summit, at
+   http://ftp.sas.com/standards/large.file
+
+As a general comment, if you get compilation errors which you think
+are related to large file support, try removing the above define from
+the Makefile, ie, delete the line
+   BIGFILES=-D_FILE_OFFSET_BITS=64 
+from the Makefile, and do 'make clean ; make'.  This will give you a
+version of bzip2 without large file support, which, for most
+applications, is probably not a problem.  
+
+Alternatively, try some of the platform-specific hints listed below.
+
+You can use the spewG.c program to generate huge files to test bzip2's
+large file support, if you are feeling paranoid.  Be aware though that
+any compilation problems which affect bzip2 will also affect spewG.c,
+alas.
Index: /trunk/minix/commands/bzip2-1.0.3/README.MINIX
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/README.MINIX	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/README.MINIX	(revision 9)
@@ -0,0 +1,172 @@
+###############################################################################
+# Quick installation
+###############################################################################
+
+To build and install bzip into /usr/local, execute the following commands 
+as user bin:
+
+make
+make install
+
+To install into another directory use:
+make install PREFIX=<path>
+
+###############################################################################
+# bzip 1.0.3 for Minix
+###############################################################################
+The text below is taken from the original README file. The original file is
+available as README.ORIGINAL.
+
+This is the README for bzip2, a block-sorting file compressor, version
+1.0.3.  This version is fully compatible with the previous public
+releases, versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1 and 1.0.2.
+
+bzip2-1.0.3 is distributed under a BSD-style license.  For details,
+see the file LICENSE.
+
+Complete documentation is available in Postscript form (manual.ps),
+PDF (manual.pdf) or html (manual.html).  A plain-text version of the
+manual page is available as bzip2.txt.  A statement about Y2K issues
+is now included in the file Y2K_INFO.
+
+
+HOW TO BUILD -- MINIX
+
+Type `make'.  This builds the library libbz2.a and then the
+programs bzip2 and bzip2recover.  Six self-tests are run.
+If the self-tests complete ok, carry on to installation:
+
+To install in /usr/local/bin, /usr/local/lib, /usr/local/man and 
+   /usr/local/include, type
+   make install
+To install somewhere else, eg, /xxx/yyy/{bin,lib,man,include}, type 
+   make install PREFIX=/xxx/yyy
+If you are (justifiably) paranoid and want to see what 'make install'
+is going to do, you can first do
+   make -n install                      or
+   make -n install PREFIX=/xxx/yyy      respectively.
+The -n instructs make to show the commands it would execute, but
+not actually execute them.
+
+VALIDATION
+
+Correct operation, in the sense that a compressed file can always be
+decompressed to reproduce the original, is obviously of paramount
+importance.  To validate bzip2, I used a modified version of Mark
+Nelson's churn program.  Churn is an automated test driver which
+recursively traverses a directory structure, using bzip2 to compress
+and then decompress each file it encounters, and checking that the
+decompressed data is the same as the original.
+
+
+
+Please read and be aware of the following:
+
+WARNING:
+
+   This program (attempts to) compress data by performing several
+   non-trivial transformations on it.  Unless you are 100% familiar
+   with *all* the algorithms contained herein, and with the
+   consequences of modifying them, you should NOT meddle with the
+   compression or decompression machinery.  Incorrect changes can and
+   very likely *will* lead to disastrous loss of data.
+
+
+DISCLAIMER:
+
+   I TAKE NO RESPONSIBILITY FOR ANY LOSS OF DATA ARISING FROM THE
+   USE OF THIS PROGRAM, HOWSOEVER CAUSED.
+
+   Every compression of a file implies an assumption that the
+   compressed file can be decompressed to reproduce the original.
+   Great efforts in design, coding and testing have been made to
+   ensure that this program works correctly.  However, the complexity
+   of the algorithms, and, in particular, the presence of various
+   special cases in the code which occur with very low but non-zero
+   probability make it impossible to rule out the possibility of bugs
+   remaining in the program.  DO NOT COMPRESS ANY DATA WITH THIS
+   PROGRAM UNLESS YOU ARE PREPARED TO ACCEPT THE POSSIBILITY, HOWEVER
+   SMALL, THAT THE DATA WILL NOT BE RECOVERABLE.
+
+   That is not to say this program is inherently unreliable.  Indeed,
+   I very much hope the opposite is true.  bzip2 has been carefully
+   constructed and extensively tested.
+
+
+PATENTS:
+
+   To the best of my knowledge, bzip2 does not use any patented
+   algorithms.  However, I do not have the resources to carry out
+   a patent search.  Therefore I cannot give any guarantee of the
+   above statement.
+
+End of legalities.
+
+
+WHAT'S NEW IN 0.9.0 (as compared to 0.1pl2) ?
+
+   * Approx 10% faster compression, 30% faster decompression
+   * -t (test mode) is a lot quicker
+   * Can decompress concatenated compressed files
+   * Programming interface, so programs can directly read/write .bz2 files
+   * Less restrictive (BSD-style) licensing
+   * Flag handling more compatible with GNU gzip
+   * Much more documentation, i.e., a proper user manual
+   * Hopefully, improved portability (at least of the library)
+
+WHAT'S NEW IN 0.9.5 ?
+
+   * Compression speed is much less sensitive to the input
+     data than in previous versions.  Specifically, the very
+     slow performance caused by repetitive data is fixed.
+   * Many small improvements in file and flag handling.
+   * A Y2K statement.
+
+WHAT'S NEW IN 1.0.0 ?
+
+   See the CHANGES file.
+
+WHAT'S NEW IN 1.0.2 ?
+
+   See the CHANGES file.
+
+WHAT'S NEW IN 1.0.3 ?
+
+   See the CHANGES file.
+
+
+I hope you find bzip2 useful.  Feel free to contact me at
+   jseward@bzip.org
+if you have any suggestions or queries.  Many people mailed me with
+comments, suggestions and patches after the releases of bzip-0.15,
+bzip-0.21, and bzip2 versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1 and
+1.0.2, and the changes in bzip2 are largely a result of this feedback.
+I thank you for your comments.
+
+At least for the time being, bzip2's "home" is (or can be reached via)
+http://www.bzip.org
+
+Julian Seward
+jseward@bzip.org
+
+Cambridge, UK.
+
+18     July 1996 (version 0.15)
+25   August 1996 (version 0.21)
+ 7   August 1997 (bzip2, version 0.1)
+29   August 1997 (bzip2, version 0.1pl2)
+23   August 1998 (bzip2, version 0.9.0)
+ 8     June 1999 (bzip2, version 0.9.5)
+ 4     Sept 1999 (bzip2, version 0.9.5d)
+ 5      May 2000 (bzip2, version 1.0pre8)
+30 December 2001 (bzip2, version 1.0.2pre1)
+15 February 2005 (bzip2, version 1.0.3)
+
+###############################################################################
+# Changes to the source of version 1.0.3
+###############################################################################
+- Changed default installation to /usr/local
+- Adjusted Makefile to separate testing from building, to allow chmem in
+  between
+- Adjusted invocation of ar, as Minix ar does not support -q, even though the
+  documentation says it does
Index: /trunk/minix/commands/bzip2-1.0.3/README.ORIGINAL
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/README.ORIGINAL	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/README.ORIGINAL	(revision 9)
@@ -0,0 +1,185 @@
+
+This is the README for bzip2, a block-sorting file compressor, version
+1.0.3.  This version is fully compatible with the previous public
+releases, versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1 and 1.0.2.
+
+bzip2-1.0.3 is distributed under a BSD-style license.  For details,
+see the file LICENSE.
+
+Complete documentation is available in Postscript form (manual.ps),
+PDF (manual.pdf) or html (manual.html).  A plain-text version of the
+manual page is available as bzip2.txt.  A statement about Y2K issues
+is now included in the file Y2K_INFO.
+
+
+HOW TO BUILD -- UNIX
+
+Type `make'.  This builds the library libbz2.a and then the
+programs bzip2 and bzip2recover.  Six self-tests are run.
+If the self-tests complete ok, carry on to installation:
+
+To install in /usr/bin, /usr/lib, /usr/man and /usr/include, type
+   make install
+To install somewhere else, eg, /xxx/yyy/{bin,lib,man,include}, type 
+   make install PREFIX=/xxx/yyy
+If you are (justifiably) paranoid and want to see what 'make install'
+is going to do, you can first do
+   make -n install                      or
+   make -n install PREFIX=/xxx/yyy      respectively.
+The -n instructs make to show the commands it would execute, but
+not actually execute them.
+
+
+HOW TO BUILD -- UNIX, shared library libbz2.so.
+
+Do 'make -f Makefile-libbz2_so'.  This Makefile seems to work for
+Linux-ELF (RedHat 7.2 on an x86 box), with gcc.  I make no claims
+that it works for any other platform, though I suspect it probably
+will work for most platforms employing both ELF and gcc.
+
+bzip2-shared, a client of the shared library, is also built, but not
+self-tested.  So I suggest you also build using the normal Makefile,
+since that conducts a self-test.  A second reason to prefer the
+version statically linked to the library is that, on x86 platforms,
+building shared objects makes a valuable register (%ebx) unavailable
+to gcc, resulting in a slowdown of 10%-20%, at least for bzip2.
+
+Important note for people upgrading .so's from 0.9.0/0.9.5 to version
+1.0.X.  All the functions in the library have been renamed, from (eg)
+bzCompress to BZ2_bzCompress, to avoid namespace pollution.
+Unfortunately this means that the libbz2.so created by
+Makefile-libbz2_so will not work with any program which used an older
+version of the library.  Sorry.  I do encourage library clients to
+make the effort to upgrade to use version 1.0, since it is both faster
+and more robust than previous versions.
+
+
+HOW TO BUILD -- Windows 95, NT, DOS, Mac, etc.
+
+It's difficult for me to support compilation on all these platforms.
+My approach is to collect binaries for these platforms, and put them
+on the master web page (http://sources.redhat.com/bzip2).  Look there.
+However (FWIW), bzip2-1.0.X is very standard ANSI C and should compile
+unmodified with MS Visual C.  If you have difficulties building, you
+might want to read README.COMPILATION.PROBLEMS.
+
+At least using MS Visual C++ 6, you can build from the unmodified
+sources by issuing, in a command shell: 
+   nmake -f makefile.msc
+(you may need to first run the MSVC-provided script VCVARS32.BAT
+ so as to set up paths to the MSVC tools correctly).
+
+
+VALIDATION
+
+Correct operation, in the sense that a compressed file can always be
+decompressed to reproduce the original, is obviously of paramount
+importance.  To validate bzip2, I used a modified version of Mark
+Nelson's churn program.  Churn is an automated test driver which
+recursively traverses a directory structure, using bzip2 to compress
+and then decompress each file it encounters, and checking that the
+decompressed data is the same as the original.
+
+
+
+Please read and be aware of the following:
+
+WARNING:
+
+   This program (attempts to) compress data by performing several
+   non-trivial transformations on it.  Unless you are 100% familiar
+   with *all* the algorithms contained herein, and with the
+   consequences of modifying them, you should NOT meddle with the
+   compression or decompression machinery.  Incorrect changes can and
+   very likely *will* lead to disastrous loss of data.
+
+
+DISCLAIMER:
+
+   I TAKE NO RESPONSIBILITY FOR ANY LOSS OF DATA ARISING FROM THE
+   USE OF THIS PROGRAM, HOWSOEVER CAUSED.
+
+   Every compression of a file implies an assumption that the
+   compressed file can be decompressed to reproduce the original.
+   Great efforts in design, coding and testing have been made to
+   ensure that this program works correctly.  However, the complexity
+   of the algorithms, and, in particular, the presence of various
+   special cases in the code which occur with very low but non-zero
+   probability make it impossible to rule out the possibility of bugs
+   remaining in the program.  DO NOT COMPRESS ANY DATA WITH THIS
+   PROGRAM UNLESS YOU ARE PREPARED TO ACCEPT THE POSSIBILITY, HOWEVER
+   SMALL, THAT THE DATA WILL NOT BE RECOVERABLE.
+
+   That is not to say this program is inherently unreliable.  Indeed,
+   I very much hope the opposite is true.  bzip2 has been carefully
+   constructed and extensively tested.
+
+
+PATENTS:
+
+   To the best of my knowledge, bzip2 does not use any patented
+   algorithms.  However, I do not have the resources to carry out
+   a patent search.  Therefore I cannot give any guarantee of the
+   above statement.
+
+End of legalities.
+
+
+WHAT'S NEW IN 0.9.0 (as compared to 0.1pl2) ?
+
+   * Approx 10% faster compression, 30% faster decompression
+   * -t (test mode) is a lot quicker
+   * Can decompress concatenated compressed files
+   * Programming interface, so programs can directly read/write .bz2 files
+   * Less restrictive (BSD-style) licensing
+   * Flag handling more compatible with GNU gzip
+   * Much more documentation, i.e., a proper user manual
+   * Hopefully, improved portability (at least of the library)
+
+WHAT'S NEW IN 0.9.5 ?
+
+   * Compression speed is much less sensitive to the input
+     data than in previous versions.  Specifically, the very
+     slow performance caused by repetitive data is fixed.
+   * Many small improvements in file and flag handling.
+   * A Y2K statement.
+
+WHAT'S NEW IN 1.0.0 ?
+
+   See the CHANGES file.
+
+WHAT'S NEW IN 1.0.2 ?
+
+   See the CHANGES file.
+
+WHAT'S NEW IN 1.0.3 ?
+
+   See the CHANGES file.
+
+
+I hope you find bzip2 useful.  Feel free to contact me at
+   jseward@bzip.org
+if you have any suggestions or queries.  Many people mailed me with
+comments, suggestions and patches after the releases of bzip-0.15,
+bzip-0.21, and bzip2 versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1 and
+1.0.2, and the changes in bzip2 are largely a result of this feedback.
+I thank you for your comments.
+
+At least for the time being, bzip2's "home" is (or can be reached via)
+http://www.bzip.org
+
+Julian Seward
+jseward@bzip.org
+
+Cambridge, UK.
+
+18     July 1996 (version 0.15)
+25   August 1996 (version 0.21)
+ 7   August 1997 (bzip2, version 0.1)
+29   August 1997 (bzip2, version 0.1pl2)
+23   August 1998 (bzip2, version 0.9.0)
+ 8     June 1999 (bzip2, version 0.9.5)
+ 4     Sept 1999 (bzip2, version 0.9.5d)
+ 5      May 2000 (bzip2, version 1.0pre8)
+30 December 2001 (bzip2, version 1.0.2pre1)
+15 February 2005 (bzip2, version 1.0.3)
Index: /trunk/minix/commands/bzip2-1.0.3/README.XML.STUFF
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/README.XML.STUFF	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/README.XML.STUFF	(revision 9)
@@ -0,0 +1,31 @@
+The script xmlproc.sh takes an xml file as input,
+and processes it to create .pdf, .html or .ps output.
+It uses format.pl, a perl script to format <pre> blocks nicely,
+ and add CDATA tags so writers do not have to use eg. &lt; 
+
+The file "entities.xml" must be edited to reflect current
+version, year, etc.
+
+
+Usage:
+
+  xmlproc.sh -v manual.xml
+  Validates an xml file to ensure no dtd-compliance errors
+
+  xmlproc.sh -html manual.xml
+  Output: manual.html
+
+  xmlproc.sh -pdf manual.xml
+  Output: manual.pdf
+
+  xmlproc.sh -ps manual.xml
+  Output: manual.ps
+
+
+Notum bene: 
+- pdfxmltex barfs if given a filename with an underscore in it
+
+- xmltex won't work yet - there's a bug in passivetex
+    which we are all waiting for Sebastian to fix.
+  So we are going the xml -> pdf -> ps route for the time being,
+    using pdfxmltex.
Index: /trunk/minix/commands/bzip2-1.0.3/Y2K_INFO
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/Y2K_INFO	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/Y2K_INFO	(revision 9)
@@ -0,0 +1,34 @@
+
+Y2K status of bzip2 and libbzip2, versions 0.1, 0.9.0 and 0.9.5
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Informally speaking:
+   bzip2 is a compression program built on top of libbzip2, 
+   a library which does the real work of compression and 
+   decompression.  As far as I am aware, libbzip2 does not have 
+   any date-related code at all.
+
+   bzip2 itself copies dates from source to destination files 
+   when compressing or decompressing, using the 'stat' and 'utime' 
+   UNIX system calls.  It doesn't examine, manipulate or store the 
+   dates in any way.  So as far as I can see, there shouldn't be any 
+   problem with bzip2 providing 'stat' and 'utime' work correctly 
+   on your system.
+
+   On non-unix platforms (those for which BZ_UNIX in bzip2.c is
+   not set to 1), bzip2 doesn't even do the date copying.
+
+   Overall, informally speaking, I don't think bzip2 or libbzip2 
+   have a Y2K problem.
+
+Formally speaking:
+   I am not prepared to offer you any assurance whatsoever 
+   regarding Y2K issues in my software.  You alone assume the 
+   entire risk of using the software.  The disclaimer of liability 
+   in the LICENSE file in the bzip2 source distribution continues 
+   to apply on this issue as with every other issue pertaining 
+   to the software.
+
+Julian Seward
+Cambridge, UK
+25 August 1999
Index: /trunk/minix/commands/bzip2-1.0.3/blocksort.c
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/blocksort.c	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/blocksort.c	(revision 9)
@@ -0,0 +1,1141 @@
+
+/*-------------------------------------------------------------*/
+/*--- Block sorting machinery                               ---*/
+/*---                                           blocksort.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+
+  To get some idea how the block sorting algorithms in this file 
+  work, read my paper 
+     On the Performance of BWT Sorting Algorithms
+  in Proceedings of the IEEE Data Compression Conference 2000,
+  Snowbird, Utah, USA, 27-30 March 2000.  The main sort in this
+  file implements the algorithm called  cache  in the paper.
+--*/
+
+
+#include "bzlib_private.h"
+
+/*---------------------------------------------*/
+/*--- Fallback O(N log(N)^2) sorting        ---*/
+/*--- algorithm, for repetitive blocks      ---*/
+/*---------------------------------------------*/
+
+/*---------------------------------------------*/
+static 
+__inline__
+void fallbackSimpleSort ( UInt32* fmap, 
+                          UInt32* eclass, 
+                          Int32   lo, 
+                          Int32   hi )
+{
+   Int32 i, j, tmp;
+   UInt32 ec_tmp;
+
+   if (lo == hi) return;
+
+   if (hi - lo > 3) {
+      for ( i = hi-4; i >= lo; i-- ) {
+         tmp = fmap[i];
+         ec_tmp = eclass[tmp];
+         for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
+            fmap[j-4] = fmap[j];
+         fmap[j-4] = tmp;
+      }
+   }
+
+   for ( i = hi-1; i >= lo; i-- ) {
+      tmp = fmap[i];
+      ec_tmp = eclass[tmp];
+      for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
+         fmap[j-1] = fmap[j];
+      fmap[j-1] = tmp;
+   }
+}
+
+
+/*---------------------------------------------*/
+#define fswap(zz1, zz2) \
+   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
+
+#define fvswap(zzp1, zzp2, zzn)       \
+{                                     \
+   Int32 yyp1 = (zzp1);               \
+   Int32 yyp2 = (zzp2);               \
+   Int32 yyn  = (zzn);                \
+   while (yyn > 0) {                  \
+      fswap(fmap[yyp1], fmap[yyp2]);  \
+      yyp1++; yyp2++; yyn--;          \
+   }                                  \
+}
+
+
+#define fmin(a,b) ((a) < (b)) ? (a) : (b)
+
+#define fpush(lz,hz) { stackLo[sp] = lz; \
+                       stackHi[sp] = hz; \
+                       sp++; }
+
+#define fpop(lz,hz) { sp--;              \
+                      lz = stackLo[sp];  \
+                      hz = stackHi[sp]; }
+
+#define FALLBACK_QSORT_SMALL_THRESH 10
+#define FALLBACK_QSORT_STACK_SIZE   100
+
+
+static
+void fallbackQSort3 ( UInt32* fmap, 
+                      UInt32* eclass,
+                      Int32   loSt, 
+                      Int32   hiSt )
+{
+   Int32 unLo, unHi, ltLo, gtHi, n, m;
+   Int32 sp, lo, hi;
+   UInt32 med, r, r3;
+   Int32 stackLo[FALLBACK_QSORT_STACK_SIZE];
+   Int32 stackHi[FALLBACK_QSORT_STACK_SIZE];
+
+   r = 0;
+
+   sp = 0;
+   fpush ( loSt, hiSt );
+
+   while (sp > 0) {
+
+      AssertH ( sp < FALLBACK_QSORT_STACK_SIZE, 1004 );
+
+      fpop ( lo, hi );
+      if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
+         fallbackSimpleSort ( fmap, eclass, lo, hi );
+         continue;
+      }
+
+      /* Random partitioning.  Median of 3 sometimes fails to
+         avoid bad cases.  Median of 9 seems to help but 
+         looks rather expensive.  This too seems to work but
+         is cheaper.  Guidance for the magic constants 
+         7621 and 32768 is taken from Sedgewick's algorithms
+         book, chapter 35.
+      */
+      r = ((r * 7621) + 1) % 32768;
+      r3 = r % 3;
+      if (r3 == 0) med = eclass[fmap[lo]]; else
+      if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
+                   med = eclass[fmap[hi]];
+
+      unLo = ltLo = lo;
+      unHi = gtHi = hi;
+
+      while (1) {
+         while (1) {
+            if (unLo > unHi) break;
+            n = (Int32)eclass[fmap[unLo]] - (Int32)med;
+            if (n == 0) { 
+               fswap(fmap[unLo], fmap[ltLo]); 
+               ltLo++; unLo++; 
+               continue; 
+            };
+            if (n > 0) break;
+            unLo++;
+         }
+         while (1) {
+            if (unLo > unHi) break;
+            n = (Int32)eclass[fmap[unHi]] - (Int32)med;
+            if (n == 0) { 
+               fswap(fmap[unHi], fmap[gtHi]); 
+               gtHi--; unHi--; 
+               continue; 
+            };
+            if (n < 0) break;
+            unHi--;
+         }
+         if (unLo > unHi) break;
+         fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
+      }
+
+      AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
+
+      if (gtHi < ltLo) continue;
+
+      n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
+      m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
+
+      n = lo + unLo - ltLo - 1;
+      m = hi - (gtHi - unHi) + 1;
+
+      if (n - lo > hi - m) {
+         fpush ( lo, n );
+         fpush ( m, hi );
+      } else {
+         fpush ( m, hi );
+         fpush ( lo, n );
+      }
+   }
+}
+
+#undef fmin
+#undef fpush
+#undef fpop
+#undef fswap
+#undef fvswap
+#undef FALLBACK_QSORT_SMALL_THRESH
+#undef FALLBACK_QSORT_STACK_SIZE
+
+
+/*---------------------------------------------*/
+/* Pre:
+      nblock > 0
+      eclass exists for [0 .. nblock-1]
+      ((UChar*)eclass) [0 .. nblock-1] holds block
+      ptr exists for [0 .. nblock-1]
+
+   Post:
+      ((UChar*)eclass) [0 .. nblock-1] holds block
+      All other areas of eclass destroyed
+      fmap [0 .. nblock-1] holds sorted order
+      bhtab [ 0 .. 2+(nblock/32) ] destroyed
+*/
+
+#define       SET_BH(zz)  bhtab[(zz) >> 5] |= (1 << ((zz) & 31))
+#define     CLEAR_BH(zz)  bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31))
+#define     ISSET_BH(zz)  (bhtab[(zz) >> 5] & (1 << ((zz) & 31)))
+#define      WORD_BH(zz)  bhtab[(zz) >> 5]
+#define UNALIGNED_BH(zz)  ((zz) & 0x01f)
+
+static
+void fallbackSort ( UInt32* fmap, 
+                    UInt32* eclass, 
+                    UInt32* bhtab,
+                    Int32   nblock,
+                    Int32   verb )
+{
+   Int32 ftab[257];
+   Int32 ftabCopy[256];
+   Int32 H, i, j, k, l, r, cc, cc1;
+   Int32 nNotDone;
+   Int32 nBhtab;
+   UChar* eclass8 = (UChar*)eclass;
+
+   /*--
+      Initial 1-char radix sort to generate
+      initial fmap and initial BH bits.
+   --*/
+   if (verb >= 4)
+      VPrintf0 ( "        bucket sorting ...\n" );
+   for (i = 0; i < 257;    i++) ftab[i] = 0;
+   for (i = 0; i < nblock; i++) ftab[eclass8[i]]++;
+   for (i = 0; i < 256;    i++) ftabCopy[i] = ftab[i];
+   for (i = 1; i < 257;    i++) ftab[i] += ftab[i-1];
+
+   for (i = 0; i < nblock; i++) {
+      j = eclass8[i];
+      k = ftab[j] - 1;
+      ftab[j] = k;
+      fmap[k] = i;
+   }
+
+   nBhtab = 2 + (nblock / 32);
+   for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
+   for (i = 0; i < 256; i++) SET_BH(ftab[i]);
+
+   /*--
+      Inductively refine the buckets.  Kind-of an
+      "exponential radix sort" (!), inspired by the
+      Manber-Myers suffix array construction algorithm.
+   --*/
+
+   /*-- set sentinel bits for block-end detection --*/
+   for (i = 0; i < 32; i++) { 
+      SET_BH(nblock + 2*i);
+      CLEAR_BH(nblock + 2*i + 1);
+   }
+
+   /*-- the log(N) loop --*/
+   H = 1;
+   while (1) {
+
+      if (verb >= 4) 
+         VPrintf1 ( "        depth %6d has ", H );
+
+      j = 0;
+      for (i = 0; i < nblock; i++) {
+         if (ISSET_BH(i)) j = i;
+         k = fmap[i] - H; if (k < 0) k += nblock;
+         eclass[k] = j;
+      }
+
+      nNotDone = 0;
+      r = -1;
+      while (1) {
+
+	 /*-- find the next non-singleton bucket --*/
+         k = r + 1;
+         while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
+         if (ISSET_BH(k)) {
+            while (WORD_BH(k) == 0xffffffff) k += 32;
+            while (ISSET_BH(k)) k++;
+         }
+         l = k - 1;
+         if (l >= nblock) break;
+         while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
+         if (!ISSET_BH(k)) {
+            while (WORD_BH(k) == 0x00000000) k += 32;
+            while (!ISSET_BH(k)) k++;
+         }
+         r = k - 1;
+         if (r >= nblock) break;
+
+         /*-- now [l, r] bracket current bucket --*/
+         if (r > l) {
+            nNotDone += (r - l + 1);
+            fallbackQSort3 ( fmap, eclass, l, r );
+
+            /*-- scan bucket and generate header bits-- */
+            cc = -1;
+            for (i = l; i <= r; i++) {
+               cc1 = eclass[fmap[i]];
+               if (cc != cc1) { SET_BH(i); cc = cc1; };
+            }
+         }
+      }
+
+      if (verb >= 4) 
+         VPrintf1 ( "%6d unresolved strings\n", nNotDone );
+
+      H *= 2;
+      if (H > nblock || nNotDone == 0) break;
+   }
+
+   /*-- 
+      Reconstruct the original block in
+      eclass8 [0 .. nblock-1], since the
+      previous phase destroyed it.
+   --*/
+   if (verb >= 4)
+      VPrintf0 ( "        reconstructing block ...\n" );
+   j = 0;
+   for (i = 0; i < nblock; i++) {
+      while (ftabCopy[j] == 0) j++;
+      ftabCopy[j]--;
+      eclass8[fmap[i]] = (UChar)j;
+   }
+   AssertH ( j < 256, 1005 );
+}
+
+#undef       SET_BH
+#undef     CLEAR_BH
+#undef     ISSET_BH
+#undef      WORD_BH
+#undef UNALIGNED_BH
+
+
+/*---------------------------------------------*/
+/*--- The main, O(N^2 log(N)) sorting       ---*/
+/*--- algorithm.  Faster for "normal"       ---*/
+/*--- non-repetitive blocks.                ---*/
+/*---------------------------------------------*/
+
+/*---------------------------------------------*/
+static
+__inline__
+Bool mainGtU ( UInt32  i1, 
+               UInt32  i2,
+               UChar*  block, 
+               UInt16* quadrant,
+               UInt32  nblock,
+               Int32*  budget )
+{
+   Int32  k;
+   UChar  c1, c2;
+   UInt16 s1, s2;
+
+   AssertD ( i1 != i2, "mainGtU" );
+   /* 1 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 2 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 3 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 4 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 5 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 6 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 7 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 8 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 9 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 10 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 11 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 12 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+
+   k = nblock + 8;
+
+   do {
+      /* 1 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 2 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 3 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 4 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 5 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 6 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 7 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 8 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+
+      if (i1 >= nblock) i1 -= nblock;
+      if (i2 >= nblock) i2 -= nblock;
+
+      k -= 8;
+      (*budget)--;
+   }
+      while (k >= 0);
+
+   return False;
+}
+
+
+/*---------------------------------------------*/
+/*--
+   Knuth's increments seem to work better
+   than Incerpi-Sedgewick here.  Possibly
+   because the number of elems to sort is
+   usually small, typically <= 20.
+--*/
+static
+Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
+                   9841, 29524, 88573, 265720,
+                   797161, 2391484 };
+
+static
+void mainSimpleSort ( UInt32* ptr,
+                      UChar*  block,
+                      UInt16* quadrant,
+                      Int32   nblock,
+                      Int32   lo, 
+                      Int32   hi, 
+                      Int32   d,
+                      Int32*  budget )
+{
+   Int32 i, j, h, bigN, hp;
+   UInt32 v;
+
+   bigN = hi - lo + 1;
+   if (bigN < 2) return;
+
+   hp = 0;
+   while (incs[hp] < bigN) hp++;
+   hp--;
+
+   for (; hp >= 0; hp--) {
+      h = incs[hp];
+
+      i = lo + h;
+      while (True) {
+
+         /*-- copy 1 --*/
+         if (i > hi) break;
+         v = ptr[i];
+         j = i;
+         while ( mainGtU ( 
+                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
+                 ) ) {
+            ptr[j] = ptr[j-h];
+            j = j - h;
+            if (j <= (lo + h - 1)) break;
+         }
+         ptr[j] = v;
+         i++;
+
+         /*-- copy 2 --*/
+         if (i > hi) break;
+         v = ptr[i];
+         j = i;
+         while ( mainGtU ( 
+                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
+                 ) ) {
+            ptr[j] = ptr[j-h];
+            j = j - h;
+            if (j <= (lo + h - 1)) break;
+         }
+         ptr[j] = v;
+         i++;
+
+         /*-- copy 3 --*/
+         if (i > hi) break;
+         v = ptr[i];
+         j = i;
+         while ( mainGtU ( 
+                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
+                 ) ) {
+            ptr[j] = ptr[j-h];
+            j = j - h;
+            if (j <= (lo + h - 1)) break;
+         }
+         ptr[j] = v;
+         i++;
+
+         if (*budget < 0) return;
+      }
+   }
+}
+
+
+/*---------------------------------------------*/
+/*--
+   The following is an implementation of
+   an elegant 3-way quicksort for strings,
+   described in a paper "Fast Algorithms for
+   Sorting and Searching Strings", by Robert
+   Sedgewick and Jon L. Bentley.
+--*/
+
+#define mswap(zz1, zz2) \
+   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
+
+#define mvswap(zzp1, zzp2, zzn)       \
+{                                     \
+   Int32 yyp1 = (zzp1);               \
+   Int32 yyp2 = (zzp2);               \
+   Int32 yyn  = (zzn);                \
+   while (yyn > 0) {                  \
+      mswap(ptr[yyp1], ptr[yyp2]);    \
+      yyp1++; yyp2++; yyn--;          \
+   }                                  \
+}
+
+static 
+__inline__
+UChar mmed3 ( UChar a, UChar b, UChar c )
+{
+   UChar t;
+   if (a > b) { t = a; a = b; b = t; };
+   if (b > c) { 
+      b = c;
+      if (a > b) b = a;
+   }
+   return b;
+}
+
+#define mmin(a,b) ((a) < (b)) ? (a) : (b)
+
+#define mpush(lz,hz,dz) { stackLo[sp] = lz; \
+                          stackHi[sp] = hz; \
+                          stackD [sp] = dz; \
+                          sp++; }
+
+#define mpop(lz,hz,dz) { sp--;             \
+                         lz = stackLo[sp]; \
+                         hz = stackHi[sp]; \
+                         dz = stackD [sp]; }
+
+
+#define mnextsize(az) (nextHi[az]-nextLo[az])
+
+#define mnextswap(az,bz)                                        \
+   { Int32 tz;                                                  \
+     tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
+     tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
+     tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }
+
+
+#define MAIN_QSORT_SMALL_THRESH 20
+#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT)
+#define MAIN_QSORT_STACK_SIZE 100
+
+static
+void mainQSort3 ( UInt32* ptr,
+                  UChar*  block,
+                  UInt16* quadrant,
+                  Int32   nblock,
+                  Int32   loSt, 
+                  Int32   hiSt, 
+                  Int32   dSt,
+                  Int32*  budget )
+{
+   Int32 unLo, unHi, ltLo, gtHi, n, m, med;
+   Int32 sp, lo, hi, d;
+
+   Int32 stackLo[MAIN_QSORT_STACK_SIZE];
+   Int32 stackHi[MAIN_QSORT_STACK_SIZE];
+   Int32 stackD [MAIN_QSORT_STACK_SIZE];
+
+   Int32 nextLo[3];
+   Int32 nextHi[3];
+   Int32 nextD [3];
+
+   sp = 0;
+   mpush ( loSt, hiSt, dSt );
+
+   while (sp > 0) {
+
+      AssertH ( sp < MAIN_QSORT_STACK_SIZE, 1001 );
+
+      mpop ( lo, hi, d );
+      if (hi - lo < MAIN_QSORT_SMALL_THRESH || 
+          d > MAIN_QSORT_DEPTH_THRESH) {
+         mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
+         if (*budget < 0) return;
+         continue;
+      }
+
+      med = (Int32) 
+            mmed3 ( block[ptr[ lo         ]+d],
+                    block[ptr[ hi         ]+d],
+                    block[ptr[ (lo+hi)>>1 ]+d] );
+
+      unLo = ltLo = lo;
+      unHi = gtHi = hi;
+
+      while (True) {
+         while (True) {
+            if (unLo > unHi) break;
+            n = ((Int32)block[ptr[unLo]+d]) - med;
+            if (n == 0) { 
+               mswap(ptr[unLo], ptr[ltLo]); 
+               ltLo++; unLo++; continue; 
+            };
+            if (n >  0) break;
+            unLo++;
+         }
+         while (True) {
+            if (unLo > unHi) break;
+            n = ((Int32)block[ptr[unHi]+d]) - med;
+            if (n == 0) { 
+               mswap(ptr[unHi], ptr[gtHi]); 
+               gtHi--; unHi--; continue; 
+            };
+            if (n <  0) break;
+            unHi--;
+         }
+         if (unLo > unHi) break;
+         mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
+      }
+
+      AssertD ( unHi == unLo-1, "mainQSort3(2)" );
+
+      if (gtHi < ltLo) {
+         mpush(lo, hi, d+1 );
+         continue;
+      }
+
+      n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
+      m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
+
+      n = lo + unLo - ltLo - 1;
+      m = hi - (gtHi - unHi) + 1;
+
+      nextLo[0] = lo;  nextHi[0] = n;   nextD[0] = d;
+      nextLo[1] = m;   nextHi[1] = hi;  nextD[1] = d;
+      nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
+
+      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
+      if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
+      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
+
+      AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
+      AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
+
+      mpush (nextLo[0], nextHi[0], nextD[0]);
+      mpush (nextLo[1], nextHi[1], nextD[1]);
+      mpush (nextLo[2], nextHi[2], nextD[2]);
+   }
+}
+
+#undef mswap
+#undef mvswap
+#undef mpush
+#undef mpop
+#undef mmin
+#undef mnextsize
+#undef mnextswap
+#undef MAIN_QSORT_SMALL_THRESH
+#undef MAIN_QSORT_DEPTH_THRESH
+#undef MAIN_QSORT_STACK_SIZE
+
+
+/*---------------------------------------------*/
+/* Pre:
+      nblock > N_OVERSHOOT
+      block32 exists for [0 .. nblock-1 +N_OVERSHOOT]
+      ((UChar*)block32) [0 .. nblock-1] holds block
+      ptr exists for [0 .. nblock-1]
+
+   Post:
+      ((UChar*)block32) [0 .. nblock-1] holds block
+      All other areas of block32 destroyed
+      ftab [0 .. 65536 ] destroyed
+      ptr [0 .. nblock-1] holds sorted order
+      if (*budget < 0), sorting was abandoned
+*/
+
+#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
+#define SETMASK (1 << 21)
+#define CLEARMASK (~(SETMASK))
+
+static
+void mainSort ( UInt32* ptr, 
+                UChar*  block,
+                UInt16* quadrant, 
+                UInt32* ftab,
+                Int32   nblock,
+                Int32   verb,
+                Int32*  budget )
+{
+   Int32  i, j, k, ss, sb;
+   Int32  runningOrder[256];
+   Bool   bigDone[256];
+   Int32  copyStart[256];
+   Int32  copyEnd  [256];
+   UChar  c1;
+   Int32  numQSorted;
+   UInt16 s;
+   if (verb >= 4) VPrintf0 ( "        main sort initialise ...\n" );
+
+   /*-- set up the 2-byte frequency table --*/
+   for (i = 65536; i >= 0; i--) ftab[i] = 0;
+
+   j = block[0] << 8;
+   i = nblock-1;
+   for (; i >= 3; i -= 4) {
+      quadrant[i] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
+      ftab[j]++;
+      quadrant[i-1] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i-1]) << 8);
+      ftab[j]++;
+      quadrant[i-2] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i-2]) << 8);
+      ftab[j]++;
+      quadrant[i-3] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i-3]) << 8);
+      ftab[j]++;
+   }
+   for (; i >= 0; i--) {
+      quadrant[i] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
+      ftab[j]++;
+   }
+
+   /*-- (emphasises close relationship of block & quadrant) --*/
+   for (i = 0; i < BZ_N_OVERSHOOT; i++) {
+      block   [nblock+i] = block[i];
+      quadrant[nblock+i] = 0;
+   }
+
+   if (verb >= 4) VPrintf0 ( "        bucket sorting ...\n" );
+
+   /*-- Complete the initial radix sort --*/
+   for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
+
+   s = block[0] << 8;
+   i = nblock-1;
+   for (; i >= 3; i -= 4) {
+      s = (s >> 8) | (block[i] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i;
+      s = (s >> 8) | (block[i-1] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i-1;
+      s = (s >> 8) | (block[i-2] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i-2;
+      s = (s >> 8) | (block[i-3] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i-3;
+   }
+   for (; i >= 0; i--) {
+      s = (s >> 8) | (block[i] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i;
+   }
+
+   /*--
+      Now ftab contains the first loc of every small bucket.
+      Calculate the running order, from smallest to largest
+      big bucket.
+   --*/
+   for (i = 0; i <= 255; i++) {
+      bigDone     [i] = False;
+      runningOrder[i] = i;
+   }
+
+   {
+      Int32 vv;
+      Int32 h = 1;
+      do h = 3 * h + 1; while (h <= 256);
+      do {
+         h = h / 3;
+         for (i = h; i <= 255; i++) {
+            vv = runningOrder[i];
+            j = i;
+            while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
+               runningOrder[j] = runningOrder[j-h];
+               j = j - h;
+               if (j <= (h - 1)) goto zero;
+            }
+            zero:
+            runningOrder[j] = vv;
+         }
+      } while (h != 1);
+   }
+
+   /*--
+      The main sorting loop.
+   --*/
+
+   numQSorted = 0;
+
+   for (i = 0; i <= 255; i++) {
+
+      /*--
+         Process big buckets, starting with the least full.
+         Basically this is a 3-step process in which we call
+         mainQSort3 to sort the small buckets [ss, j], but
+         also make a big effort to avoid the calls if we can.
+      --*/
+      ss = runningOrder[i];
+
+      /*--
+         Step 1:
+         Complete the big bucket [ss] by quicksorting
+         any unsorted small buckets [ss, j], for j != ss.  
+         Hopefully previous pointer-scanning phases have already
+         completed many of the small buckets [ss, j], so
+         we don't have to sort them at all.
+      --*/
+      for (j = 0; j <= 255; j++) {
+         if (j != ss) {
+            sb = (ss << 8) + j;
+            if ( ! (ftab[sb] & SETMASK) ) {
+               Int32 lo = ftab[sb]   & CLEARMASK;
+               Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
+               if (hi > lo) {
+                  if (verb >= 4)
+                     VPrintf4 ( "        qsort [0x%x, 0x%x]   "
+                                "done %d   this %d\n",
+                                ss, j, numQSorted, hi - lo + 1 );
+                  mainQSort3 ( 
+                     ptr, block, quadrant, nblock, 
+                     lo, hi, BZ_N_RADIX, budget 
+                  );   
+                  numQSorted += (hi - lo + 1);
+                  if (*budget < 0) return;
+               }
+            }
+            ftab[sb] |= SETMASK;
+         }
+      }
+
+      AssertH ( !bigDone[ss], 1006 );
+
+      /*--
+         Step 2:
+         Now scan this big bucket [ss] so as to synthesise the
+         sorted order for small buckets [t, ss] for all t,
+         including, magically, the bucket [ss,ss] too.
+         This will avoid doing Real Work in subsequent Step 1's.
+      --*/
+      {
+         for (j = 0; j <= 255; j++) {
+            copyStart[j] =  ftab[(j << 8) + ss]     & CLEARMASK;
+            copyEnd  [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1;
+         }
+         for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) {
+            k = ptr[j]-1; if (k < 0) k += nblock;
+            c1 = block[k];
+            if (!bigDone[c1])
+               ptr[ copyStart[c1]++ ] = k;
+         }
+         for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) {
+            k = ptr[j]-1; if (k < 0) k += nblock;
+            c1 = block[k];
+            if (!bigDone[c1]) 
+               ptr[ copyEnd[c1]-- ] = k;
+         }
+      }
+
+      AssertH ( (copyStart[ss]-1 == copyEnd[ss])
+                || 
+                /* Extremely rare case missing in bzip2-1.0.0 and 1.0.1.
+                   Necessity for this case is demonstrated by compressing 
+                   a sequence of approximately 48.5 million of character 
+                   251; 1.0.0/1.0.1 will then die here. */
+                (copyStart[ss] == 0 && copyEnd[ss] == nblock-1),
+                1007 )
+
+      for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK;
+
+      /*--
+         Step 3:
+         The [ss] big bucket is now done.  Record this fact,
+         and update the quadrant descriptors.  Remember to
+         update quadrants in the overshoot area too, if
+         necessary.  The "if (i < 255)" test merely skips
+         this updating for the last bucket processed, since
+         updating for the last bucket is pointless.
+
+         The quadrant array provides a way to incrementally
+         cache sort orderings, as they appear, so as to 
+         make subsequent comparisons in fullGtU() complete
+         faster.  For repetitive blocks this makes a big
+         difference (but not big enough to be able to avoid
+         the fallback sorting mechanism, exponential radix sort).
+
+         The precise meaning is: at all times:
+
+            for 0 <= i < nblock and 0 <= j <= nblock
+
+            if block[i] != block[j], 
+
+               then the relative values of quadrant[i] and 
+                    quadrant[j] are meaningless.
+
+               else {
+                  if quadrant[i] < quadrant[j]
+                     then the string starting at i lexicographically
+                     precedes the string starting at j
+
+                  else if quadrant[i] > quadrant[j]
+                     then the string starting at j lexicographically
+                     precedes the string starting at i
+
+                  else
+                     the relative ordering of the strings starting
+                     at i and j has not yet been determined.
+               }
+      --*/
+      bigDone[ss] = True;
+
+      if (i < 255) {
+         Int32 bbStart  = ftab[ss << 8] & CLEARMASK;
+         Int32 bbSize   = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
+         Int32 shifts   = 0;
+
+         while ((bbSize >> shifts) > 65534) shifts++;
+
+         for (j = bbSize-1; j >= 0; j--) {
+            Int32 a2update     = ptr[bbStart + j];
+            UInt16 qVal        = (UInt16)(j >> shifts);
+            quadrant[a2update] = qVal;
+            if (a2update < BZ_N_OVERSHOOT)
+               quadrant[a2update + nblock] = qVal;
+         }
+         AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 );
+      }
+
+   }
+
+   if (verb >= 4)
+      VPrintf3 ( "        %d pointers, %d sorted, %d scanned\n",
+                 nblock, numQSorted, nblock - numQSorted );
+}
+
+#undef BIGFREQ
+#undef SETMASK
+#undef CLEARMASK
+
+
+/*---------------------------------------------*/
+/* Pre:
+      nblock > 0
+      arr2 exists for [0 .. nblock-1 +N_OVERSHOOT]
+      ((UChar*)arr2)  [0 .. nblock-1] holds block
+      arr1 exists for [0 .. nblock-1]
+
+   Post:
+      ((UChar*)arr2) [0 .. nblock-1] holds block
+      All other areas of block destroyed
+      ftab [ 0 .. 65536 ] destroyed
+      arr1 [0 .. nblock-1] holds sorted order
+*/
+void BZ2_blockSort ( EState* s )
+{
+   UInt32* ptr    = s->ptr; 
+   UChar*  block  = s->block;
+   UInt32* ftab   = s->ftab;
+   Int32   nblock = s->nblock;
+   Int32   verb   = s->verbosity;
+   Int32   wfact  = s->workFactor;
+   UInt16* quadrant;
+   Int32   budget;
+   Int32   budgetInit;
+   Int32   i;
+
+   if (nblock < 10000) {
+      fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
+   } else {
+      /* Calculate the location for quadrant, remembering to get
+         the alignment right.  Assumes that &(block[0]) is at least
+         2-byte aligned -- this should be ok since block is really
+         the first section of arr2.
+      */
+      i = nblock+BZ_N_OVERSHOOT;
+      if (i & 1) i++;
+      quadrant = (UInt16*)(&(block[i]));
+
+      /* (wfact-1) / 3 puts the default-factor-30
+         transition point at very roughly the same place as 
+         with v0.1 and v0.9.0.  
+         Not that it particularly matters any more, since the
+         resulting compressed stream is now the same regardless
+         of whether or not we use the main sort or fallback sort.
+      */
+      if (wfact < 1  ) wfact = 1;
+      if (wfact > 100) wfact = 100;
+      budgetInit = nblock * ((wfact-1) / 3);
+      budget = budgetInit;
+
+      mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget );
+      if (verb >= 3) 
+         VPrintf3 ( "      %d work, %d block, ratio %5.2f\n",
+                    budgetInit - budget,
+                    nblock, 
+                    (float)(budgetInit - budget) /
+                    (float)(nblock==0 ? 1 : nblock) ); 
+      if (budget < 0) {
+         if (verb >= 2) 
+            VPrintf0 ( "    too repetitive; using fallback"
+                       " sorting algorithm\n" );
+         fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
+      }
+   }
+
+   s->origPtr = -1;
+   for (i = 0; i < s->nblock; i++)
+      if (ptr[i] == 0)
+         { s->origPtr = i; break; };
+
+   AssertH( s->origPtr != -1, 1003 );
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                       blocksort.c ---*/
+/*-------------------------------------------------------------*/
Index: /trunk/minix/commands/bzip2-1.0.3/build
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/build	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/build	(revision 9)
@@ -0,0 +1,6 @@
+#!/bin/sh
+make clean
+make all
+if [ "$1" != build ]
+then make install
+fi
Index: /trunk/minix/commands/bzip2-1.0.3/bz-common.xsl
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bz-common.xsl	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bz-common.xsl	(revision 9)
@@ -0,0 +1,39 @@
+<?xml version="1.0"?> <!-- -*- sgml -*- -->
+<xsl:stylesheet 
+     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+<!-- we like '1.2 Title' -->
+<xsl:param name="section.autolabel" select="'1'"/> 
+<xsl:param name="section.label.includes.component.label" select="'1'"/>
+
+<!-- Do not put 'Chapter' at the start of eg 'Chapter 1. Doing This' -->
+<xsl:param name="local.l10n.xml" select="document('')"/> 
+<l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0"> 
+  <l:l10n language="en"> 
+    <l:context name="title-numbered">
+      <l:template name="chapter" text="%n.&#160;%t"/>
+    </l:context> 
+  </l:l10n>
+</l:i18n>
+
+<!-- don't generate sub-tocs for qanda sets -->
+<xsl:param name="generate.toc">
+set       toc,title
+book      toc,title,figure,table,example,equation
+chapter   toc,title
+section   toc
+sect1     toc
+sect2     toc
+sect3     toc
+sect4     nop
+sect5     nop
+qandaset  toc
+qandadiv  nop
+appendix  toc,title
+article/appendix  nop
+article   toc,title
+preface   toc,title
+reference toc,title
+</xsl:param>
+
+</xsl:stylesheet>
Index: /trunk/minix/commands/bzip2-1.0.3/bz-fo.xsl
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bz-fo.xsl	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bz-fo.xsl	(revision 9)
@@ -0,0 +1,257 @@
+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- sgml -*- -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
+     xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0">
+
+<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/fo/docbook.xsl"/>
+<xsl:import href="bz-common.xsl"/>
+
+<!-- set indent = yes while debugging, then change to NO -->
+<xsl:output method="xml" indent="yes"/>
+
+<!-- ensure only passivetex extensions are on -->
+<xsl:param name="stylesheet.result.type" select="'fo'"/>
+<!-- fo extensions: PDF bookmarks and index terms -->
+<xsl:param name="use.extensions" select="'1'"/>
+<xsl:param name="xep.extensions" select="0"/>      
+<xsl:param name="fop.extensions" select="0"/>     
+<xsl:param name="saxon.extensions" select="0"/>   
+<xsl:param name="passivetex.extensions" select="1"/>
+<xsl:param name="tablecolumns.extension" select="'1'"/>
+
+<!-- ensure we are using single sided -->
+<xsl:param name="double.sided" select="'0'"/> 
+
+<!-- insert cross references to page numbers -->
+<xsl:param name="insert.xref.page.number" select="1"/>
+
+<!-- <?custom-pagebreak?> inserts a page break at this point -->
+<xsl:template match="processing-instruction('custom-pagebreak')">
+  <fo:block break-before='page'/>
+</xsl:template>
+
+<!-- show links in color -->
+<xsl:attribute-set name="xref.properties">
+  <xsl:attribute name="color">blue</xsl:attribute>
+</xsl:attribute-set>
+
+<!-- make pre listings indented a bit + a bg colour -->
+<xsl:template match="programlisting | screen">
+  <fo:block start-indent="0.25in" wrap-option="no-wrap" 
+            white-space-collapse="false" text-align="start" 
+            font-family="monospace" background-color="#f2f2f9"
+            linefeed-treatment="preserve" 
+            xsl:use-attribute-sets="normal.para.spacing">
+    <xsl:apply-templates/>
+  </fo:block>
+</xsl:template>
+<!-- make verbatim output prettier -->
+<xsl:template match="literallayout">
+  <fo:block start-indent="0.25in" wrap-option="no-wrap" 
+            white-space-collapse="false" text-align="start" 
+            font-family="monospace" background-color="#edf7f4"
+            linefeed-treatment="preserve" 
+            space-before="0em" space-after="0em">
+    <xsl:apply-templates/>
+  </fo:block>
+</xsl:template>
+
+<!-- workaround bug in passivetex fo output for itemizedlist -->
+<xsl:template match="itemizedlist/listitem">
+  <xsl:variable name="id">
+  <xsl:call-template name="object.id"/></xsl:variable>
+  <xsl:variable name="itemsymbol">
+    <xsl:call-template name="list.itemsymbol">
+      <xsl:with-param name="node" select="parent::itemizedlist"/>
+    </xsl:call-template>
+  </xsl:variable>
+  <xsl:variable name="item.contents">
+    <fo:list-item-label end-indent="label-end()">
+      <fo:block>
+        <xsl:choose>
+          <xsl:when test="$itemsymbol='disc'">&#x2022;</xsl:when>
+          <xsl:when test="$itemsymbol='bullet'">&#x2022;</xsl:when>
+          <xsl:otherwise>&#x2022;</xsl:otherwise>
+        </xsl:choose>
+      </fo:block>
+    </fo:list-item-label>
+    <fo:list-item-body start-indent="body-start()">
+      <xsl:apply-templates/>    <!-- removed extra block wrapper -->
+    </fo:list-item-body>
+  </xsl:variable>
+  <xsl:choose>
+    <xsl:when test="parent::*/@spacing = 'compact'">
+      <fo:list-item id="{$id}" 
+          xsl:use-attribute-sets="compact.list.item.spacing">
+        <xsl:copy-of select="$item.contents"/>
+      </fo:list-item>
+    </xsl:when>
+    <xsl:otherwise>
+      <fo:list-item id="{$id}" xsl:use-attribute-sets="list.item.spacing">
+        <xsl:copy-of select="$item.contents"/>
+      </fo:list-item>
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
+<!-- workaround bug in passivetex fo output for orderedlist -->
+<xsl:template match="orderedlist/listitem">
+  <xsl:variable name="id">
+  <xsl:call-template name="object.id"/></xsl:variable>
+  <xsl:variable name="item.contents">
+    <fo:list-item-label end-indent="label-end()">
+      <fo:block>
+        <xsl:apply-templates select="." mode="item-number"/>
+      </fo:block>
+    </fo:list-item-label>
+    <fo:list-item-body start-indent="body-start()">
+      <xsl:apply-templates/>    <!-- removed extra block wrapper -->
+    </fo:list-item-body>
+  </xsl:variable>
+  <xsl:choose>
+    <xsl:when test="parent::*/@spacing = 'compact'">
+      <fo:list-item id="{$id}" 
+          xsl:use-attribute-sets="compact.list.item.spacing">
+        <xsl:copy-of select="$item.contents"/>
+      </fo:list-item>
+    </xsl:when>
+    <xsl:otherwise>
+      <fo:list-item id="{$id}" xsl:use-attribute-sets="list.item.spacing">
+        <xsl:copy-of select="$item.contents"/>
+      </fo:list-item>
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
+<!-- workaround bug in passivetex fo output for variablelist -->
+<xsl:param name="variablelist.as.blocks" select="1"/>
+<xsl:template match="varlistentry" mode="vl.as.blocks">
+  <xsl:variable name="id">
+    <xsl:call-template name="object.id"/></xsl:variable>
+  <fo:block id="{$id}" xsl:use-attribute-sets="list.item.spacing"  
+      keep-together.within-column="always" 
+      keep-with-next.within-column="always">
+    <xsl:apply-templates select="term"/>
+  </fo:block>
+  <fo:block start-indent="0.5in" end-indent="0in" 
+            space-after.minimum="0.2em" 
+            space-after.optimum="0.4em" 
+            space-after.maximum="0.6em">
+    <fo:block>
+      <xsl:apply-templates select="listitem"/>
+    </fo:block>
+  </fo:block>
+</xsl:template>
+
+
+<!-- workaround bug in footers: force right-align w/two 80|30 cols -->
+<xsl:template name="footer.table">
+  <xsl:param name="pageclass" select="''"/>
+  <xsl:param name="sequence" select="''"/>
+  <xsl:param name="gentext-key" select="''"/>
+  <xsl:choose>
+    <xsl:when test="$pageclass = 'index'">
+      <xsl:attribute name="margin-left">0pt</xsl:attribute>
+    </xsl:when>
+  </xsl:choose>
+  <xsl:variable name="candidate">
+    <fo:table table-layout="fixed" width="100%">
+      <fo:table-column column-number="1" column-width="80%"/>
+      <fo:table-column column-number="2" column-width="20%"/>
+      <fo:table-body>
+        <fo:table-row height="14pt">
+          <fo:table-cell text-align="left" display-align="after">
+            <xsl:attribute name="relative-align">baseline</xsl:attribute>
+            <fo:block> 
+              <fo:block> </fo:block><!-- empty cell -->
+            </fo:block>
+          </fo:table-cell>
+          <fo:table-cell text-align="center" display-align="after">
+            <xsl:attribute name="relative-align">baseline</xsl:attribute>
+            <fo:block>
+              <xsl:call-template name="footer.content">
+                <xsl:with-param name="pageclass" select="$pageclass"/>
+                <xsl:with-param name="sequence" select="$sequence"/>
+                <xsl:with-param name="position" select="'center'"/>
+                <xsl:with-param name="gentext-key" select="$gentext-key"/>
+              </xsl:call-template>
+            </fo:block>
+          </fo:table-cell>
+        </fo:table-row>
+      </fo:table-body>
+    </fo:table>
+  </xsl:variable>
+  <!-- Really output a footer? -->
+  <xsl:choose>
+    <xsl:when test="$pageclass='titlepage' and $gentext-key='book'
+                    and $sequence='first'">
+      <!-- no, book titlepages have no footers at all -->
+    </xsl:when>
+    <xsl:when test="$sequence = 'blank' and $footers.on.blank.pages = 0">
+      <!-- no output -->
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:copy-of select="$candidate"/>
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
+
+<!-- fix bug in headers: force right-align w/two 40|60 cols -->
+<xsl:template name="header.table">
+  <xsl:param name="pageclass" select="''"/>
+  <xsl:param name="sequence" select="''"/>
+  <xsl:param name="gentext-key" select="''"/>
+  <xsl:choose>
+    <xsl:when test="$pageclass = 'index'">
+      <xsl:attribute name="margin-left">0pt</xsl:attribute>
+    </xsl:when>
+  </xsl:choose>
+  <xsl:variable name="candidate">
+    <fo:table table-layout="fixed" width="100%">
+      <xsl:call-template name="head.sep.rule">
+        <xsl:with-param name="pageclass" select="$pageclass"/>
+        <xsl:with-param name="sequence" select="$sequence"/>
+        <xsl:with-param name="gentext-key" select="$gentext-key"/>
+      </xsl:call-template>
+      <fo:table-column column-number="1" column-width="40%"/>
+      <fo:table-column column-number="2" column-width="60%"/>
+      <fo:table-body>
+        <fo:table-row height="14pt">
+          <fo:table-cell text-align="left" display-align="before">
+            <xsl:attribute name="relative-align">baseline</xsl:attribute>
+            <fo:block>
+              <fo:block> </fo:block><!-- empty cell -->
+            </fo:block>
+          </fo:table-cell>
+          <fo:table-cell text-align="center" display-align="before">
+            <xsl:attribute name="relative-align">baseline</xsl:attribute>
+            <fo:block>
+              <xsl:call-template name="header.content">
+                <xsl:with-param name="pageclass" select="$pageclass"/>
+                <xsl:with-param name="sequence" select="$sequence"/>
+                <xsl:with-param name="position" select="'center'"/>
+                <xsl:with-param name="gentext-key" select="$gentext-key"/>
+              </xsl:call-template>
+            </fo:block>
+          </fo:table-cell>
+        </fo:table-row>
+      </fo:table-body>
+    </fo:table>
+  </xsl:variable>
+  <!-- Really output a header? -->
+  <xsl:choose>
+    <xsl:when test="$pageclass = 'titlepage' and $gentext-key = 'book'
+                    and $sequence='first'">
+      <!-- no, book titlepages have no headers at all -->
+    </xsl:when>
+    <xsl:when test="$sequence = 'blank' and $headers.on.blank.pages = 0">
+      <!-- no output -->
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:copy-of select="$candidate"/>
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
+
+</xsl:stylesheet>
Index: /trunk/minix/commands/bzip2-1.0.3/bz-html.xsl
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bz-html.xsl	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bz-html.xsl	(revision 9)
@@ -0,0 +1,20 @@
+<?xml version="1.0"?> <!-- -*- sgml -*- -->
+<!DOCTYPE xsl:stylesheet [ <!ENTITY bz-css SYSTEM "./bzip.css"> ]>
+
+<xsl:stylesheet 
+   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl"/>
+<xsl:import href="bz-common.xsl"/>
+
+<!-- use 8859-1 encoding -->
+<xsl:output method="html" encoding="ISO-8859-1" indent="yes"/>
+
+<!-- we include the css directly when generating one large file -->
+<xsl:template name="user.head.content">  
+  <style type="text/css" media="screen">
+    <xsl:text>&bz-css;</xsl:text>
+  </style>
+</xsl:template>
+
+</xsl:stylesheet>
Index: /trunk/minix/commands/bzip2-1.0.3/bzdiff
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bzdiff	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bzdiff	(revision 9)
@@ -0,0 +1,76 @@
+#!/bin/sh
+# sh is buggy on RS/6000 AIX 3.2. Replace above line with #!/bin/ksh
+
+# Bzcmp/diff wrapped for bzip2, 
+# adapted from zdiff by Philippe Troin <phil@fifi.org> for Debian GNU/Linux.
+
+# Bzcmp and bzdiff are used to invoke the cmp or the  diff  pro-
+# gram  on compressed files.  All options specified are passed
+# directly to cmp or diff.  If only 1 file is specified,  then
+# the  files  compared  are file1 and an uncompressed file1.gz.
+# If two files are specified, then they are  uncompressed  (if
+# necessary) and fed to cmp or diff.  The exit status from cmp
+# or diff is preserved.
+
+PATH="/usr/bin:$PATH"; export PATH
+prog=`echo $0 | sed 's|.*/||'`
+case "$prog" in
+  *cmp) comp=${CMP-cmp}   ;;
+  *)    comp=${DIFF-diff} ;;
+esac
+
+OPTIONS=
+FILES=
+for ARG
+do
+    case "$ARG" in
+    -*)	OPTIONS="$OPTIONS $ARG";;
+     *)	if test -f "$ARG"; then
+            FILES="$FILES $ARG"
+        else
+            echo "${prog}: $ARG not found or not a regular file"
+	    exit 1
+        fi ;;
+    esac
+done
+if test -z "$FILES"; then
+	echo "Usage: $prog [${comp}_options] file [file]"
+	exit 1
+fi
+tmp=`tempfile -d /tmp -p bz` || {
+      echo 'cannot create a temporary file' >&2
+      exit 1
+}
+set $FILES
+if test $# -eq 1; then
+	FILE=`echo "$1" | sed 's/.bz2$//'`
+	bzip2 -cd "$FILE.bz2" | $comp $OPTIONS - "$FILE"
+	STAT="$?"
+
+elif test $# -eq 2; then
+	case "$1" in
+        *.bz2)
+                case "$2" in
+	        *.bz2)
+			F=`echo "$2" | sed 's|.*/||;s|.bz2$||'`
+                        bzip2 -cdfq "$2" > $tmp
+                        bzip2 -cdfq "$1" | $comp $OPTIONS - $tmp
+                        STAT="$?"
+			/bin/rm -f $tmp;;
+
+                *)      bzip2 -cdfq "$1" | $comp $OPTIONS - "$2"
+                        STAT="$?";;
+                esac;;
+        *)      case "$2" in
+	        *.bz2)
+                        bzip2 -cdfq "$2" | $comp $OPTIONS "$1" -
+                        STAT="$?";;
+                *)      $comp $OPTIONS "$1" "$2"
+                        STAT="$?";;
+                esac;;
+	esac
+        exit "$STAT"
+else
+	echo "Usage: $prog [${comp}_options] file [file]"
+	exit 1
+fi
Index: /trunk/minix/commands/bzip2-1.0.3/bzdiff.1
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bzdiff.1	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bzdiff.1	(revision 9)
@@ -0,0 +1,47 @@
+\"Shamelessly copied from zmore.1 by Philippe Troin <phil@fifi.org>
+\"for Debian GNU/Linux
+.TH BZDIFF 1
+.SH NAME
+bzcmp, bzdiff \- compare bzip2 compressed files
+.SH SYNOPSIS
+.B bzcmp
+[ cmp_options ] file1
+[ file2 ]
+.br
+.B bzdiff
+[ diff_options ] file1
+[ file2 ]
+.SH DESCRIPTION
+.I  Bzcmp
+and 
+.I bzdiff
+are used to invoke the
+.I cmp
+or the
+.I diff
+program on bzip2 compressed files.  All options specified are passed
+directly to
+.I cmp
+or
+.IR diff "."
+If only 1 file is specified, then the files compared are
+.I file1
+and an uncompressed
+.IR file1 ".bz2."
+If two files are specified, then they are uncompressed if necessary and fed to
+.I cmp
+or
+.IR diff "."
+The exit status from 
+.I cmp
+or
+.I diff
+is preserved.
+.SH "SEE ALSO"
+cmp(1), diff(1), bzmore(1), bzless(1), bzgrep(1), bzip2(1)
+.SH BUGS
+Messages from the
+.I cmp
+or
+.I diff
+programs refer to temporary filenames instead of those specified.
Index: /trunk/minix/commands/bzip2-1.0.3/bzgrep
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bzgrep	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bzgrep	(revision 9)
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+# Bzgrep wrapped for bzip2, 
+# adapted from zgrep by Philippe Troin <phil@fifi.org> for Debian GNU/Linux.
+## zgrep notice:
+## zgrep -- a wrapper around a grep program that decompresses files as needed
+## Adapted from a version sent by Charles Levert <charles@comm.polymtl.ca>
+
+PATH="/usr/bin:$PATH"; export PATH
+
+prog=`echo $0 | sed 's|.*/||'`
+case "$prog" in
+	*egrep)	grep=${EGREP-egrep}	;;
+	*fgrep)	grep=${FGREP-fgrep}	;;
+	*)	grep=${GREP-grep}	;;
+esac
+pat=""
+while test $# -ne 0; do
+  case "$1" in
+  -e | -f) opt="$opt $1"; shift; pat="$1"
+           if test "$grep" = grep; then  # grep is buggy with -e on SVR4
+             grep=egrep
+           fi;;
+  -A | -B) opt="$opt $1 $2"; shift;;
+  -*)	   opt="$opt $1";;
+   *)      if test -z "$pat"; then
+	     pat="$1"
+	   else
+	     break;
+           fi;;
+  esac
+  shift
+done
+
+if test -z "$pat"; then
+  echo "grep through bzip2 files"
+  echo "usage: $prog [grep_options] pattern [files]"
+  exit 1
+fi
+
+list=0
+silent=0
+op=`echo "$opt" | sed -e 's/ //g' -e 's/-//g'`
+case "$op" in
+  *l*) list=1
+esac
+case "$op" in
+  *h*) silent=1
+esac
+
+if test $# -eq 0; then
+  bzip2 -cdfq | $grep $opt "$pat"
+  exit $?
+fi
+
+res=0
+for i do
+  if test -f "$i"; then :; else if test -f "$i.bz2"; then i="$i.bz2"; fi; fi
+  if test $list -eq 1; then
+    bzip2 -cdfq "$i" | $grep $opt "$pat" 2>&1 > /dev/null && echo $i
+    r=$?
+  elif test $# -eq 1 -o $silent -eq 1; then
+    bzip2 -cdfq "$i" | $grep $opt "$pat"
+    r=$?
+  else
+    bzip2 -cdfq "$i" | $grep $opt "$pat" | sed "s|^|${i}:|"
+    r=$?
+  fi
+  test "$r" -ne 0 && res="$r"
+done
+exit $res
Index: /trunk/minix/commands/bzip2-1.0.3/bzgrep.1
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bzgrep.1	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bzgrep.1	(revision 9)
@@ -0,0 +1,56 @@
+\"Shamelessly copied from zmore.1 by Philippe Troin <phil@fifi.org>
+\"for Debian GNU/Linux
+.TH BZGREP 1
+.SH NAME
+bzgrep, bzfgrep, bzegrep \- search possibly bzip2 compressed files for a regular expression
+.SH SYNOPSIS
+.B bzgrep
+[ grep_options ]
+.BI  [\ -e\ ] " pattern"
+.IR filename ".\|.\|."
+.br
+.B bzegrep
+[ egrep_options ]
+.BI  [\ -e\ ] " pattern"
+.IR filename ".\|.\|."
+.br
+.B bzfgrep
+[ fgrep_options ]
+.BI  [\ -e\ ] " pattern"
+.IR filename ".\|.\|."
+.SH DESCRIPTION
+.IR  Bzgrep
+is used to invoke the
+.I grep
+on bzip2-compressed files. All options specified are passed directly to
+.I grep.
+If no file is specified, then the standard input is decompressed
+if necessary and fed to grep.
+Otherwise the given files are uncompressed if necessary and fed to
+.I grep.
+.PP
+If
+.I bzgrep
+is invoked as
+.I bzegrep
+or
+.I bzfgrep
+then
+.I egrep
+or
+.I fgrep
+is used instead of
+.I grep.
+If the GREP environment variable is set,
+.I bzgrep
+uses it as the
+.I grep
+program to be invoked. For example:
+
+    for sh:  GREP=fgrep  bzgrep string files
+    for csh: (setenv GREP fgrep; bzgrep string files)
+.SH AUTHOR
+Charles Levert (charles@comm.polymtl.ca). Adapted to bzip2 by Philippe
+Troin <phil@fifi.org> for Debian GNU/Linux.
+.SH "SEE ALSO"
+grep(1), egrep(1), fgrep(1), bzdiff(1), bzmore(1), bzless(1), bzip2(1)
Index: /trunk/minix/commands/bzip2-1.0.3/bzip.css
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bzip.css	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bzip.css	(revision 9)
@@ -0,0 +1,74 @@
+/* Colours:
+#74240f  dark brown      h1, h2, h3, h4
+#336699  medium blue     links
+#339999  turquoise       link hover colour
+#202020  almost black    general text
+#761596  purple          md5sum text
+#626262  dark gray       pre border
+#eeeeee  very light gray pre background
+#f2f2f9  very light blue nav table background
+#3366cc  medium blue     nav table border
+*/
+
+a, a:link, a:visited, a:active { color: #336699; }
+a:hover { color: #339999; }
+
+body { font: 80%/126% sans-serif; }
+h1, h2, h3, h4 { color: #74240f; }
+
+dt { color: #336699; font-weight: bold }
+dd { 
+ margin-left: 1.5em; 
+ padding-bottom: 0.8em;
+}
+
+/* -- ruler -- */
+div.hr_blue { 
+  height:  3px; 
+  background:#ffffff url("/images/hr_blue.png") repeat-x; }
+div.hr_blue hr { display:none; }
+
+/* release styles */
+#release p { margin-top: 0.4em; }
+#release .md5sum { color: #761596; }
+
+
+/* ------ styles for docs|manuals|howto ------ */
+/* -- lists -- */
+ul  { 
+ margin:     0px 4px 16px 16px;
+ padding:    0px;
+ list-style: url("/images/li-blue.png"); 
+}
+ul li { 
+ margin-bottom: 10px;
+}
+ul ul	{ 
+ list-style-type:  none; 
+ list-style-image: none; 
+ margin-left:      0px; 
+}
+
+/* header / footer nav tables */
+table.nav {
+ border:     solid 1px #3366cc;
+ background: #f2f2f9;
+ background-color: #f2f2f9;
+ margin-bottom: 0.5em;
+}
+/* don't have underlined links in chunked nav menus */
+table.nav a { text-decoration: none; }
+table.nav a:hover { text-decoration: underline; }
+table.nav td { font-size: 85%; }
+
+code, tt, pre { font-size: 120%; }
+code, tt { color: #761596; }
+
+div.literallayout, pre.programlisting, pre.screen {
+ color:      #000000;
+ padding:    0.5em;
+ background: #eeeeee;
+ border:     1px solid #626262;
+ background-color: #eeeeee;
+ margin: 4px 0px 4px 0px; 
+}
Index: /trunk/minix/commands/bzip2-1.0.3/bzip2.1
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bzip2.1	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bzip2.1	(revision 9)
@@ -0,0 +1,454 @@
+.PU
+.TH bzip2 1
+.SH NAME
+bzip2, bunzip2 \- a block-sorting file compressor, v1.0.3
+.br
+bzcat \- decompresses files to stdout
+.br
+bzip2recover \- recovers data from damaged bzip2 files
+
+.SH SYNOPSIS
+.ll +8
+.B bzip2
+.RB [ " \-cdfkqstvzVL123456789 " ]
+[
+.I "filenames \&..."
+]
+.ll -8
+.br
+.B bunzip2
+.RB [ " \-fkvsVL " ]
+[ 
+.I "filenames \&..."
+]
+.br
+.B bzcat
+.RB [ " \-s " ]
+[ 
+.I "filenames \&..."
+]
+.br
+.B bzip2recover
+.I "filename"
+
+.SH DESCRIPTION
+.I bzip2
+compresses files using the Burrows-Wheeler block sorting
+text compression algorithm, and Huffman coding.  Compression is
+generally considerably better than that achieved by more conventional
+LZ77/LZ78-based compressors, and approaches the performance of the PPM
+family of statistical compressors.
+
+The command-line options are deliberately very similar to 
+those of 
+.I GNU gzip, 
+but they are not identical.
+
+.I bzip2
+expects a list of file names to accompany the
+command-line flags.  Each file is replaced by a compressed version of
+itself, with the name "original_name.bz2".  
+Each compressed file
+has the same modification date, permissions, and, when possible,
+ownership as the corresponding original, so that these properties can
+be correctly restored at decompression time.  File name handling is
+naive in the sense that there is no mechanism for preserving original
+file names, permissions, ownerships or dates in filesystems which lack
+these concepts, or have serious file name length restrictions, such as
+MS-DOS.
+
+.I bzip2
+and
+.I bunzip2
+will by default not overwrite existing
+files.  If you want this to happen, specify the \-f flag.
+
+If no file names are specified,
+.I bzip2
+compresses from standard
+input to standard output.  In this case,
+.I bzip2
+will decline to
+write compressed output to a terminal, as this would be entirely
+incomprehensible and therefore pointless.
+
+.I bunzip2
+(or
+.I bzip2 \-d) 
+decompresses all
+specified files.  Files which were not created by 
+.I bzip2
+will be detected and ignored, and a warning issued.  
+.I bzip2
+attempts to guess the filename for the decompressed file 
+from that of the compressed file as follows:
+
+       filename.bz2    becomes   filename
+       filename.bz     becomes   filename
+       filename.tbz2   becomes   filename.tar
+       filename.tbz    becomes   filename.tar
+       anyothername    becomes   anyothername.out
+
+If the file does not end in one of the recognised endings, 
+.I .bz2, 
+.I .bz, 
+.I .tbz2
+or
+.I .tbz, 
+.I bzip2 
+complains that it cannot
+guess the name of the original file, and uses the original name
+with
+.I .out
+appended.
+
+As with compression, supplying no
+filenames causes decompression from 
+standard input to standard output.
+
+.I bunzip2 
+will correctly decompress a file which is the
+concatenation of two or more compressed files.  The result is the
+concatenation of the corresponding uncompressed files.  Integrity
+testing (\-t) 
+of concatenated 
+compressed files is also supported.
+
+You can also compress or decompress files to the standard output by
+giving the \-c flag.  Multiple files may be compressed and
+decompressed like this.  The resulting outputs are fed sequentially to
+stdout.  Compression of multiple files 
+in this manner generates a stream
+containing multiple compressed file representations.  Such a stream
+can be decompressed correctly only by
+.I bzip2 
+version 0.9.0 or
+later.  Earlier versions of
+.I bzip2
+will stop after decompressing
+the first file in the stream.
+
+.I bzcat
+(or
+.I bzip2 -dc) 
+decompresses all specified files to
+the standard output.
+
+.I bzip2
+will read arguments from the environment variables
+.I BZIP2
+and
+.I BZIP,
+in that order, and will process them
+before any arguments read from the command line.  This gives a 
+convenient way to supply default arguments.
+
+Compression is always performed, even if the compressed 
+file is slightly
+larger than the original.  Files of less than about one hundred bytes
+tend to get larger, since the compression mechanism has a constant
+overhead in the region of 50 bytes.  Random data (including the output
+of most file compressors) is coded at about 8.05 bits per byte, giving
+an expansion of around 0.5%.
+
+As a self-check for your protection, 
+.I 
+bzip2
+uses 32-bit CRCs to
+make sure that the decompressed version of a file is identical to the
+original.  This guards against corruption of the compressed data, and
+against undetected bugs in
+.I bzip2
+(hopefully very unlikely).  The
+chances of data corruption going undetected is microscopic, about one
+chance in four billion for each file processed.  Be aware, though, that
+the check occurs upon decompression, so it can only tell you that
+something is wrong.  It can't help you 
+recover the original uncompressed
+data.  You can use 
+.I bzip2recover
+to try to recover data from
+damaged files.
+
+Return values: 0 for a normal exit, 1 for environmental problems (file
+not found, invalid flags, I/O errors, &c), 2 to indicate a corrupt
+compressed file, 3 for an internal consistency error (eg, bug) which
+caused
+.I bzip2
+to panic.
+
+.SH OPTIONS
+.TP
+.B \-c --stdout
+Compress or decompress to standard output.
+.TP
+.B \-d --decompress
+Force decompression.  
+.I bzip2, 
+.I bunzip2 
+and
+.I bzcat 
+are
+really the same program, and the decision about what actions to take is
+done on the basis of which name is used.  This flag overrides that
+mechanism, and forces 
+.I bzip2
+to decompress.
+.TP
+.B \-z --compress
+The complement to \-d: forces compression, regardless of the
+invocation name.
+.TP
+.B \-t --test
+Check integrity of the specified file(s), but don't decompress them.
+This really performs a trial decompression and throws away the result.
+.TP
+.B \-f --force
+Force overwrite of output files.  Normally,
+.I bzip2 
+will not overwrite
+existing output files.  Also forces 
+.I bzip2 
+to break hard links
+to files, which it otherwise wouldn't do.
+
+bzip2 normally declines to decompress files which don't have the
+correct magic header bytes.  If forced (-f), however, it will pass
+such files through unmodified.  This is how GNU gzip behaves.
+.TP
+.B \-k --keep
+Keep (don't delete) input files during compression
+or decompression.
+.TP
+.B \-s --small
+Reduce memory usage, for compression, decompression and testing.  Files
+are decompressed and tested using a modified algorithm which only
+requires 2.5 bytes per block byte.  This means any file can be
+decompressed in 2300k of memory, albeit at about half the normal speed.
+
+During compression, \-s selects a block size of 200k, which limits
+memory use to around the same figure, at the expense of your compression
+ratio.  In short, if your machine is low on memory (8 megabytes or
+less), use \-s for everything.  See MEMORY MANAGEMENT below.
+.TP
+.B \-q --quiet
+Suppress non-essential warning messages.  Messages pertaining to
+I/O errors and other critical events will not be suppressed.
+.TP
+.B \-v --verbose
+Verbose mode -- show the compression ratio for each file processed.
+Further \-v's increase the verbosity level, spewing out lots of
+information which is primarily of interest for diagnostic purposes.
+.TP
+.B \-L --license -V --version
+Display the software version, license terms and conditions.
+.TP
+.B \-1 (or \-\-fast) to \-9 (or \-\-best)
+Set the block size to 100 k, 200 k ..  900 k when compressing.  Has no
+effect when decompressing.  See MEMORY MANAGEMENT below.
+The \-\-fast and \-\-best aliases are primarily for GNU gzip 
+compatibility.  In particular, \-\-fast doesn't make things
+significantly faster.  
+And \-\-best merely selects the default behaviour.
+.TP
+.B \--
+Treats all subsequent arguments as file names, even if they start
+with a dash.  This is so you can handle files with names beginning
+with a dash, for example: bzip2 \-- \-myfilename.
+.TP
+.B \--repetitive-fast --repetitive-best
+These flags are redundant in versions 0.9.5 and above.  They provided
+some coarse control over the behaviour of the sorting algorithm in
+earlier versions, which was sometimes useful.  0.9.5 and above have an
+improved algorithm which renders these flags irrelevant.
+
+.SH MEMORY MANAGEMENT
+.I bzip2 
+compresses large files in blocks.  The block size affects
+both the compression ratio achieved, and the amount of memory needed for
+compression and decompression.  The flags \-1 through \-9
+specify the block size to be 100,000 bytes through 900,000 bytes (the
+default) respectively.  At decompression time, the block size used for
+compression is read from the header of the compressed file, and
+.I bunzip2
+then allocates itself just enough memory to decompress
+the file.  Since block sizes are stored in compressed files, it follows
+that the flags \-1 to \-9 are irrelevant to and so ignored
+during decompression.
+
+Compression and decompression requirements, 
+in bytes, can be estimated as:
+
+       Compression:   400k + ( 8 x block size )
+
+       Decompression: 100k + ( 4 x block size ), or
+                      100k + ( 2.5 x block size )
+
+Larger block sizes give rapidly diminishing marginal returns.  Most of
+the compression comes from the first two or three hundred k of block
+size, a fact worth bearing in mind when using
+.I bzip2
+on small machines.
+It is also important to appreciate that the decompression memory
+requirement is set at compression time by the choice of block size.
+
+For files compressed with the default 900k block size,
+.I bunzip2
+will require about 3700 kbytes to decompress.  To support decompression
+of any file on a 4 megabyte machine, 
+.I bunzip2
+has an option to
+decompress using approximately half this amount of memory, about 2300
+kbytes.  Decompression speed is also halved, so you should use this
+option only where necessary.  The relevant flag is -s.
+
+In general, try and use the largest block size memory constraints allow,
+since that maximises the compression achieved.  Compression and
+decompression speed are virtually unaffected by block size.
+
+Another significant point applies to files which fit in a single block
+-- that means most files you'd encounter using a large block size.  The
+amount of real memory touched is proportional to the size of the file,
+since the file is smaller than a block.  For example, compressing a file
+20,000 bytes long with the flag -9 will cause the compressor to
+allocate around 7600k of memory, but only touch 400k + 20000 * 8 = 560
+kbytes of it.  Similarly, the decompressor will allocate 3700k but only
+touch 100k + 20000 * 4 = 180 kbytes.
+
+Here is a table which summarises the maximum memory usage for different
+block sizes.  Also recorded is the total compressed size for 14 files of
+the Calgary Text Compression Corpus totalling 3,141,622 bytes.  This
+column gives some feel for how compression varies with block size.
+These figures tend to understate the advantage of larger block sizes for
+larger files, since the Corpus is dominated by smaller files.
+
+           Compress   Decompress   Decompress   Corpus
+    Flag     usage      usage       -s usage     Size
+
+     -1      1200k       500k         350k      914704
+     -2      2000k       900k         600k      877703
+     -3      2800k      1300k         850k      860338
+     -4      3600k      1700k        1100k      846899
+     -5      4400k      2100k        1350k      845160
+     -6      5200k      2500k        1600k      838626
+     -7      6100k      2900k        1850k      834096
+     -8      6800k      3300k        2100k      828642
+     -9      7600k      3700k        2350k      828642
+
+.SH RECOVERING DATA FROM DAMAGED FILES
+.I bzip2
+compresses files in blocks, usually 900kbytes long.  Each
+block is handled independently.  If a media or transmission error causes
+a multi-block .bz2
+file to become damaged, it may be possible to
+recover data from the undamaged blocks in the file.
+
+The compressed representation of each block is delimited by a 48-bit
+pattern, which makes it possible to find the block boundaries with
+reasonable certainty.  Each block also carries its own 32-bit CRC, so
+damaged blocks can be distinguished from undamaged ones.
+
+.I bzip2recover
+is a simple program whose purpose is to search for
+blocks in .bz2 files, and write each block out into its own .bz2 
+file.  You can then use
+.I bzip2 
+\-t
+to test the
+integrity of the resulting files, and decompress those which are
+undamaged.
+
+.I bzip2recover
+takes a single argument, the name of the damaged file, 
+and writes a number of files "rec00001file.bz2",
+"rec00002file.bz2", etc, containing the  extracted  blocks.
+The  output  filenames  are  designed  so  that the use of
+wildcards in subsequent processing -- for example,  
+"bzip2 -dc  rec*file.bz2 > recovered_data" -- processes the files in
+the correct order.
+
+.I bzip2recover
+should be of most use dealing with large .bz2
+files,  as  these will contain many blocks.  It is clearly
+futile to use it on damaged single-block  files,  since  a
+damaged  block  cannot  be recovered.  If you wish to minimise 
+any potential data loss through media  or  transmission errors, 
+you might consider compressing with a smaller
+block size.
+
+.SH PERFORMANCE NOTES
+The sorting phase of compression gathers together similar strings in the
+file.  Because of this, files containing very long runs of repeated
+symbols, like "aabaabaabaab ..."  (repeated several hundred times) may
+compress more slowly than normal.  Versions 0.9.5 and above fare much
+better than previous versions in this respect.  The ratio between
+worst-case and average-case compression time is in the region of 10:1.
+For previous versions, this figure was more like 100:1.  You can use the
+\-vvvv option to monitor progress in great detail, if you want.
+
+Decompression speed is unaffected by these phenomena.
+
+.I bzip2
+usually allocates several megabytes of memory to operate
+in, and then charges all over it in a fairly random fashion.  This means
+that performance, both for compressing and decompressing, is largely
+determined by the speed at which your machine can service cache misses.
+Because of this, small changes to the code to reduce the miss rate have
+been observed to give disproportionately large performance improvements.
+I imagine 
+.I bzip2
+will perform best on machines with very large caches.
+
+.SH CAVEATS
+I/O error messages are not as helpful as they could be.
+.I bzip2
+tries hard to detect I/O errors and exit cleanly, but the details of
+what the problem is sometimes seem rather misleading.
+
+This manual page pertains to version 1.0.3 of
+.I bzip2.  
+Compressed data created by this version is entirely forwards and
+backwards compatible with the previous public releases, versions
+0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1 and 1.0.2, but with the following
+exception: 0.9.0 and above can correctly decompress multiple
+concatenated compressed files.  0.1pl2 cannot do this; it will stop
+after decompressing just the first file in the stream.
+
+.I bzip2recover
+versions prior to 1.0.2 used 32-bit integers to represent
+bit positions in compressed files, so they could not handle compressed
+files more than 512 megabytes long.  Versions 1.0.2 and above use
+64-bit ints on some platforms which support them (GNU supported
+targets, and Windows).  To establish whether or not bzip2recover was
+built with such a limitation, run it without arguments.  In any event
+you can build yourself an unlimited version if you can recompile it
+with MaybeUInt64 set to be an unsigned 64-bit integer.
+
+
+
+.SH AUTHOR
+Julian Seward, jsewardbzip.org.
+
+http://www.bzip.org
+
+The ideas embodied in
+.I bzip2
+are due to (at least) the following
+people: Michael Burrows and David Wheeler (for the block sorting
+transformation), David Wheeler (again, for the Huffman coder), Peter
+Fenwick (for the structured coding model in the original
+.I bzip,
+and many refinements), and Alistair Moffat, Radford Neal and Ian Witten
+(for the arithmetic coder in the original
+.I bzip).  
+I am much
+indebted for their help, support and advice.  See the manual in the
+source distribution for pointers to sources of documentation.  Christian
+von Roques encouraged me to look for faster sorting algorithms, so as to
+speed up compression.  Bela Lubkin encouraged me to improve the
+worst-case compression performance.  
+Donna Robinson XMLised the documentation.
+The bz* scripts are derived from those of GNU gzip.
+Many people sent patches, helped
+with portability problems, lent machines, gave advice and were generally
+helpful.
Index: /trunk/minix/commands/bzip2-1.0.3/bzip2.1.preformatted
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bzip2.1.preformatted	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bzip2.1.preformatted	(revision 9)
@@ -0,0 +1,399 @@
+bzip2(1)                                                 bzip2(1)
+
+
+
+NNAAMMEE
+       bzip2, bunzip2 â a blockâsorting file compressor, v1.0.3
+       bzcat â decompresses files to stdout
+       bzip2recover â recovers data from damaged bzip2 files
+
+
+SSYYNNOOPPSSIISS
+       bbzziipp22 [ ââccddffkkqqssttvvzzVVLL112233445566778899 ] [ _f_i_l_e_n_a_m_e_s _._._.  ]
+       bbuunnzziipp22 [ ââffkkvvssVVLL ] [ _f_i_l_e_n_a_m_e_s _._._.  ]
+       bbzzccaatt [ ââss ] [ _f_i_l_e_n_a_m_e_s _._._.  ]
+       bbzziipp22rreeccoovveerr _f_i_l_e_n_a_m_e
+
+
+DDEESSCCRRIIPPTTIIOONN
+       _b_z_i_p_2  compresses  files  using  the BurrowsâWheeler block
+       sorting text compression algorithm,  and  Huffman  coding.
+       Compression  is  generally  considerably  better than that
+       achieved by more conventional LZ77/LZ78âbased compressors,
+       and  approaches  the performance of the PPM family of staÂ­
+       tistical compressors.
+
+       The commandâline options are deliberately very similar  to
+       those of _G_N_U _g_z_i_p_, but they are not identical.
+
+       _b_z_i_p_2  expects  a list of file names to accompany the comÂ­
+       mandâline flags.  Each file is replaced  by  a  compressed
+       version  of  itself,  with  the  name "original_name.bz2".
+       Each compressed file has the same modification date,  perÂ­
+       missions, and, when possible, ownership as the correspondÂ­
+       ing original, so that these properties  can  be  correctly
+       restored  at  decompression  time.   File name handling is
+       naive in the sense that there is no mechanism for preservÂ­
+       ing  original file names, permissions, ownerships or dates
+       in filesystems which lack these concepts, or have  serious
+       file name length restrictions, such as MSâDOS.
+
+       _b_z_i_p_2  and  _b_u_n_z_i_p_2 will by default not overwrite existing
+       files.  If you want this to happen, specify the âf flag.
+
+       If no file names  are  specified,  _b_z_i_p_2  compresses  from
+       standard  input  to  standard output.  In this case, _b_z_i_p_2
+       will decline to write compressed output to a terminal,  as
+       this  would  be  entirely  incomprehensible  and therefore
+       pointless.
+
+       _b_u_n_z_i_p_2 (or _b_z_i_p_2 _â_d_) decompresses  all  specified  files.
+       Files which were not created by _b_z_i_p_2 will be detected and
+       ignored, and a warning issued.  _b_z_i_p_2  attempts  to  guess
+       the  filename  for  the decompressed file from that of the
+       compressed file as follows:
+
+              filename.bz2    becomes   filename
+              filename.bz     becomes   filename
+              filename.tbz2   becomes   filename.tar
+              filename.tbz    becomes   filename.tar
+              anyothername    becomes   anyothername.out
+
+       If the file does not end in one of the recognised endings,
+       _._b_z_2_,  _._b_z_,  _._t_b_z_2 or _._t_b_z_, _b_z_i_p_2 complains that it cannot
+       guess the name of the original file, and uses the original
+       name with _._o_u_t appended.
+
+       As  with compression, supplying no filenames causes decomÂ­
+       pression from standard input to standard output.
+
+       _b_u_n_z_i_p_2 will correctly decompress a file which is the conÂ­
+       catenation of two or more compressed files.  The result is
+       the concatenation of the corresponding uncompressed files.
+       Integrity testing (ât) of concatenated compressed files is
+       also supported.
+
+       You can also compress or decompress files to the  standard
+       output  by giving the âc flag.  Multiple files may be comÂ­
+       pressed and decompressed like this.  The resulting outputs
+       are  fed  sequentially to stdout.  Compression of multiple
+       files in this manner generates a stream containing  multiÂ­
+       ple compressed file representations.  Such a stream can be
+       decompressed correctly only  by  _b_z_i_p_2  version  0.9.0  or
+       later.   Earlier  versions of _b_z_i_p_2 will stop after decomÂ­
+       pressing the first file in the stream.
+
+       _b_z_c_a_t (or _b_z_i_p_2 _â_d_c_) decompresses all specified  files  to
+       the standard output.
+
+       _b_z_i_p_2  will  read arguments from the environment variables
+       _B_Z_I_P_2 and _B_Z_I_P_, in  that  order,  and  will  process  them
+       before  any  arguments  read  from the command line.  This
+       gives a convenient way to supply default arguments.
+
+       Compression is always performed, even  if  the  compressed
+       file  is slightly larger than the original.  Files of less
+       than about one hundred bytes tend to get larger, since the
+       compression  mechanism  has  a  constant  overhead  in the
+       region of 50 bytes.  Random data (including the output  of
+       most  file  compressors)  is  coded at about 8.05 bits per
+       byte, giving an expansion of around 0.5%.
+
+       As a selfâcheck for your  protection,  _b_z_i_p_2  uses  32âbit
+       CRCs  to make sure that the decompressed version of a file
+       is identical to the original.  This guards against corrupÂ­
+       tion  of  the compressed data, and against undetected bugs
+       in _b_z_i_p_2 (hopefully very unlikely).  The chances  of  data
+       corruption  going  undetected  is  microscopic,  about one
+       chance in four billion for each file processed.  Be aware,
+       though,  that  the  check occurs upon decompression, so it
+       can only tell you that something is wrong.  It canât  help
+       you  recover  the original uncompressed data.  You can use
+       _b_z_i_p_2_r_e_c_o_v_e_r to try to recover data from damaged files.
+
+       Return values: 0 for a normal exit,  1  for  environmental
+       problems  (file not found, invalid flags, I/O errors, &c),
+       2 to indicate a corrupt compressed file, 3 for an internal
+       consistency error (eg, bug) which caused _b_z_i_p_2 to panic.
+
+
+OOPPTTIIOONNSS
+       ââcc ââââssttddoouutt
+              Compress or decompress to standard output.
+
+       ââdd ââââddeeccoommpprreessss
+              Force  decompression.  _b_z_i_p_2_, _b_u_n_z_i_p_2 and _b_z_c_a_t are
+              really the same program,  and  the  decision  about
+              what  actions to take is done on the basis of which
+              name is used.  This flag overrides that  mechanism,
+              and forces _b_z_i_p_2 to decompress.
+
+       ââzz ââââccoommpprreessss
+              The   complement   to   âd:   forces   compression,
+              regardless of the invocation name.
+
+       ââtt ââââtteesstt
+              Check integrity of the specified file(s), but donât
+              decompress  them.   This  really  performs  a trial
+              decompression and throws away the result.
+
+       ââff ââââffoorrccee
+              Force overwrite of output files.   Normally,  _b_z_i_p_2
+              will  not  overwrite  existing  output files.  Also
+              forces _b_z_i_p_2 to break hard links to files, which it
+              otherwise wouldnât do.
+
+              bzip2  normally  declines to decompress files which
+              donât have the  correct  magic  header  bytes.   If
+              forced  (âf),  however,  it  will  pass  such files
+              through unmodified.  This is how GNU gzip  behaves.
+
+       ââkk ââââkkeeeepp
+              Keep  (donât delete) input files during compression
+              or decompression.
+
+       ââss ââââssmmaallll
+              Reduce memory usage, for compression, decompression
+              and  testing.   Files  are  decompressed and tested
+              using a modified algorithm which only requires  2.5
+              bytes  per  block byte.  This means any file can be
+              decompressed in 2300k of memory,  albeit  at  about
+              half the normal speed.
+
+              During  compression,  âs  selects  a  block size of
+              200k, which limits memory use to  around  the  same
+              figure,  at  the expense of your compression ratio.
+              In short, if your  machine  is  low  on  memory  (8
+              megabytes  or  less),  use  âs for everything.  See
+              MEMORY MANAGEMENT below.
+
+       ââqq ââââqquuiieett
+              Suppress nonâessential warning messages.   Messages
+              pertaining  to I/O errors and other critical events
+              will not be suppressed.
+
+       ââvv ââââvveerrbboossee
+              Verbose mode ââ show the compression ratio for each
+              file  processed.   Further  âvâs  increase the verÂ­
+              bosity level, spewing out lots of information which
+              is primarily of interest for diagnostic purposes.
+
+       ââLL ââââlliicceennssee ââVV ââââvveerrssiioonn
+              Display  the  software  version,  license terms and
+              conditions.
+
+       ââ11 ((oorr ââââffaasstt)) ttoo ââ99 ((oorr ââââbbeesstt))
+              Set the block size to 100 k, 200 k ..  900  k  when
+              compressing.   Has  no  effect  when decompressing.
+              See MEMORY MANAGEMENT below.  The ââfast and ââbest
+              aliases  are  primarily for GNU gzip compatibility.
+              In particular, ââfast doesnât make things  signifiÂ­
+              cantly  faster.   And  ââbest  merely  selects  the
+              default behaviour.
+
+       ââââ     Treats all subsequent arguments as file names, even
+              if they start with a dash.  This is so you can hanÂ­
+              dle files with names beginning  with  a  dash,  for
+              example: bzip2 ââ âmyfilename.
+
+       âââârreeppeettiittiivveeââffaasstt âââârreeppeettiittiivveeââbbeesstt
+              These  flags  are  redundant  in versions 0.9.5 and
+              above.  They provided some coarse control over  the
+              behaviour  of the sorting algorithm in earlier verÂ­
+              sions, which was sometimes useful.  0.9.5 and above
+              have  an  improved  algorithm  which  renders these
+              flags irrelevant.
+
+
+MMEEMMOORRYY MMAANNAAGGEEMMEENNTT
+       _b_z_i_p_2 compresses large files in blocks.   The  block  size
+       affects  both  the  compression  ratio  achieved,  and the
+       amount of memory needed for compression and decompression.
+       The  flags  â1  through  â9  specify  the block size to be
+       100,000 bytes through 900,000 bytes (the default)  respecÂ­
+       tively.   At  decompression  time, the block size used for
+       compression is read from  the  header  of  the  compressed
+       file, and _b_u_n_z_i_p_2 then allocates itself just enough memory
+       to decompress the file.  Since block sizes are  stored  in
+       compressed  files,  it follows that the flags â1 to â9 are
+       irrelevant to and so ignored during decompression.
+
+       Compression and decompression requirements, in bytes,  can
+       be estimated as:
+
+              Compression:   400k + ( 8 x block size )
+
+              Decompression: 100k + ( 4 x block size ), or
+                             100k + ( 2.5 x block size )
+
+       Larger  block  sizes  give  rapidly  diminishing  marginal
+       returns.  Most of the compression comes from the first two
+       or  three hundred k of block size, a fact worth bearing in
+       mind when using _b_z_i_p_2  on  small  machines.   It  is  also
+       important  to  appreciate  that  the  decompression memory
+       requirement is set at compression time by  the  choice  of
+       block size.
+
+       For  files  compressed  with  the default 900k block size,
+       _b_u_n_z_i_p_2 will require about 3700 kbytes to decompress.   To
+       support decompression of any file on a 4 megabyte machine,
+       _b_u_n_z_i_p_2 has an option to  decompress  using  approximately
+       half this amount of memory, about 2300 kbytes.  DecompresÂ­
+       sion speed is also halved, so you should use  this  option
+       only where necessary.  The relevant flag is âs.
+
+       In general, try and use the largest block size memory conÂ­
+       straints  allow,  since  that  maximises  the  compression
+       achieved.   Compression and decompression speed are virtuÂ­
+       ally unaffected by block size.
+
+       Another significant point applies to files which fit in  a
+       single  block  ââ  that  means  most files youâd encounter
+       using a large block  size.   The  amount  of  real  memory
+       touched is proportional to the size of the file, since the
+       file is smaller than a block.  For example, compressing  a
+       file  20,000  bytes  long  with the flag â9 will cause the
+       compressor to allocate around 7600k of  memory,  but  only
+       touch 400k + 20000 * 8 = 560 kbytes of it.  Similarly, the
+       decompressor will allocate 3700k but  only  touch  100k  +
+       20000 * 4 = 180 kbytes.
+
+       Here  is a table which summarises the maximum memory usage
+       for different block sizes.  Also  recorded  is  the  total
+       compressed  size for 14 files of the Calgary Text CompresÂ­
+       sion Corpus totalling 3,141,622 bytes.  This column  gives
+       some  feel  for  how  compression  varies with block size.
+       These figures tend to understate the advantage  of  larger
+       block  sizes  for  larger files, since the Corpus is domiÂ­
+       nated by smaller files.
+
+                  Compress   Decompress   Decompress   Corpus
+           Flag     usage      usage       âs usage     Size
+
+            â1      1200k       500k         350k      914704
+            â2      2000k       900k         600k      877703
+            â3      2800k      1300k         850k      860338
+            â4      3600k      1700k        1100k      846899
+            â5      4400k      2100k        1350k      845160
+            â6      5200k      2500k        1600k      838626
+            â7      6100k      2900k        1850k      834096
+            â8      6800k      3300k        2100k      828642
+            â9      7600k      3700k        2350k      828642
+
+
+RREECCOOVVEERRIINNGG DDAATTAA FFRROOMM DDAAMMAAGGEEDD FFIILLEESS
+       _b_z_i_p_2 compresses files in blocks, usually 900kbytes  long.
+       Each block is handled independently.  If a media or transÂ­
+       mission error causes a multiâblock  .bz2  file  to  become
+       damaged,  it  may  be  possible  to  recover data from the
+       undamaged blocks in the file.
+
+       The compressed representation of each block  is  delimited
+       by  a  48âbit pattern, which makes it possible to find the
+       block boundaries with reasonable  certainty.   Each  block
+       also  carries its own 32âbit CRC, so damaged blocks can be
+       distinguished from undamaged ones.
+
+       _b_z_i_p_2_r_e_c_o_v_e_r is a  simple  program  whose  purpose  is  to
+       search  for blocks in .bz2 files, and write each block out
+       into its own .bz2 file.  You can then use _b_z_i_p_2 ât to test
+       the integrity of the resulting files, and decompress those
+       which are undamaged.
+
+       _b_z_i_p_2_r_e_c_o_v_e_r takes a single argument, the name of the damÂ­
+       aged    file,    and    writes    a    number   of   files
+       "rec00001file.bz2",  "rec00002file.bz2",  etc,  containing
+       the   extracted   blocks.   The   output   filenames   are
+       designed  so  that the use of wildcards in subsequent proÂ­
+       cessing  ââ for example, "bzip2 âdc  rec*file.bz2 > recovÂ­
+       ered_data" ââ processes the files in the correct order.
+
+       _b_z_i_p_2_r_e_c_o_v_e_r should be of most use dealing with large .bz2
+       files,  as  these will contain many blocks.  It is clearly
+       futile to use it on damaged singleâblock  files,  since  a
+       damaged  block  cannot  be recovered.  If you wish to minÂ­
+       imise any potential data loss through media  or  transmisÂ­
+       sion errors, you might consider compressing with a smaller
+       block size.
+
+
+PPEERRFFOORRMMAANNCCEE NNOOTTEESS
+       The sorting phase of compression gathers together  similar
+       strings  in  the  file.  Because of this, files containing
+       very long runs of  repeated  symbols,  like  "aabaabaabaab
+       ..."   (repeated  several hundred times) may compress more
+       slowly than normal.  Versions 0.9.5 and  above  fare  much
+       better  than previous versions in this respect.  The ratio
+       between worstâcase and averageâcase compression time is in
+       the  region  of  10:1.  For previous versions, this figure
+       was more like 100:1.  You can use the âvvvv option to monÂ­
+       itor progress in great detail, if you want.
+
+       Decompression speed is unaffected by these phenomena.
+
+       _b_z_i_p_2  usually  allocates  several  megabytes of memory to
+       operate in, and then charges all over it in a fairly  ranÂ­
+       dom  fashion.   This means that performance, both for comÂ­
+       pressing and decompressing, is largely determined  by  the
+       speed  at  which  your  machine  can service cache misses.
+       Because of this, small changes to the code to  reduce  the
+       miss  rate  have  been observed to give disproportionately
+       large performance improvements.  I imagine _b_z_i_p_2 will perÂ­
+       form best on machines with very large caches.
+
+
+CCAAVVEEAATTSS
+       I/O  error  messages  are not as helpful as they could be.
+       _b_z_i_p_2 tries hard to detect I/O errors  and  exit  cleanly,
+       but  the  details  of  what  the problem is sometimes seem
+       rather misleading.
+
+       This manual page pertains to version 1.0.3 of _b_z_i_p_2_.  ComÂ­
+       pressed  data created by this version is entirely forwards
+       and  backwards  compatible  with   the   previous   public
+       releases,  versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1 and
+       1.0.2, but with the following exception: 0.9.0  and  above
+       can  correctly decompress multiple concatenated compressed
+       files.  0.1pl2 cannot do this; it will stop  after  decomÂ­
+       pressing just the first file in the stream.
+
+       _b_z_i_p_2_r_e_c_o_v_e_r  versions prior to 1.0.2 used 32âbit integers
+       to represent bit positions in compressed  files,  so  they
+       could  not handle compressed files more than 512 megabytes
+       long.  Versions 1.0.2 and above use 64âbit  ints  on  some
+       platforms  which  support them (GNU supported targets, and
+       Windows).  To establish whether or  not  bzip2recover  was
+       built  with  such  a limitation, run it without arguments.
+       In any event you can build yourself an  unlimited  version
+       if  you  can  recompile  it  with MaybeUInt64 set to be an
+       unsigned 64âbit integer.
+
+
+
+
+AAUUTTHHOORR
+       Julian Seward, jsewardbzip.org.
+
+       http://www.bzip.org
+
+       The ideas embodied in _b_z_i_p_2 are due to (at least) the folÂ­
+       lowing  people: Michael Burrows and David Wheeler (for the
+       block sorting transformation), David Wheeler  (again,  for
+       the Huffman coder), Peter Fenwick (for the structured codÂ­
+       ing model in the original _b_z_i_p_, and many refinements), and
+       Alistair  Moffat,  Radford  Neal  and  Ian Witten (for the
+       arithmetic  coder  in  the  original  _b_z_i_p_)_.   I  am  much
+       indebted for their help, support and advice.  See the manÂ­
+       ual in the source distribution for pointers to sources  of
+       documentation.  Christian von Roques encouraged me to look
+       for faster sorting algorithms, so as to speed up  compresÂ­
+       sion.  Bela Lubkin encouraged me to improve the worstâcase
+       compression performance.  Donna Robinson XMLised the docuÂ­
+       mentation.   The bz* scripts are derived from those of GNU
+       gzip.  Many people sent patches, helped  with  portability
+       problems,  lent  machines,  gave advice and were generally
+       helpful.
+
+
+
+                                                         bzip2(1)
Index: /trunk/minix/commands/bzip2-1.0.3/bzip2.c
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bzip2.c	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bzip2.c	(revision 9)
@@ -0,0 +1,2111 @@
+
+/*-----------------------------------------------------------*/
+/*--- A block-sorting, lossless compressor        bzip2.c ---*/
+/*-----------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+
+/*----------------------------------------------------*/
+/*--- IMPORTANT                                    ---*/
+/*----------------------------------------------------*/
+
+/*--
+   WARNING:
+      This program and library (attempts to) compress data by 
+      performing several non-trivial transformations on it.  
+      Unless you are 100% familiar with *all* the algorithms 
+      contained herein, and with the consequences of modifying them, 
+      you should NOT meddle with the compression or decompression 
+      machinery.  Incorrect changes can and very likely *will* 
+      lead to disasterous loss of data.
+
+   DISCLAIMER:
+      I TAKE NO RESPONSIBILITY FOR ANY LOSS OF DATA ARISING FROM THE
+      USE OF THIS PROGRAM, HOWSOEVER CAUSED.
+
+      Every compression of a file implies an assumption that the
+      compressed file can be decompressed to reproduce the original.
+      Great efforts in design, coding and testing have been made to
+      ensure that this program works correctly.  However, the
+      complexity of the algorithms, and, in particular, the presence
+      of various special cases in the code which occur with very low
+      but non-zero probability make it impossible to rule out the
+      possibility of bugs remaining in the program.  DO NOT COMPRESS
+      ANY DATA WITH THIS PROGRAM AND/OR LIBRARY UNLESS YOU ARE PREPARED 
+      TO ACCEPT THE POSSIBILITY, HOWEVER SMALL, THAT THE DATA WILL 
+      NOT BE RECOVERABLE.
+
+      That is not to say this program is inherently unreliable.
+      Indeed, I very much hope the opposite is true.  bzip2/libbzip2
+      has been carefully constructed and extensively tested.
+
+   PATENTS:
+      To the best of my knowledge, bzip2/libbzip2 does not use any 
+      patented algorithms.  However, I do not have the resources 
+      available to carry out a full patent search.  Therefore I cannot 
+      give any guarantee of the above statement.
+--*/
+
+
+
+/*----------------------------------------------------*/
+/*--- and now for something much more pleasant :-) ---*/
+/*----------------------------------------------------*/
+
+/*---------------------------------------------*/
+/*--
+  Place a 1 beside your platform, and 0 elsewhere.
+--*/
+
+/*--
+  Generic 32-bit Unix.
+  Also works on 64-bit Unix boxes.
+  This is the default.
+--*/
+#define BZ_UNIX      1
+
+/*--
+  Win32, as seen by Jacob Navia's excellent
+  port of (Chris Fraser & David Hanson)'s excellent
+  lcc compiler.  Or with MS Visual C.
+  This is selected automatically if compiled by a compiler which
+  defines _WIN32, not including the Cygwin GCC.
+--*/
+#define BZ_LCCWIN32  0
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#undef  BZ_LCCWIN32
+#define BZ_LCCWIN32 1
+#undef  BZ_UNIX
+#define BZ_UNIX 0
+#endif
+
+
+/*---------------------------------------------*/
+/*--
+  Some stuff for all platforms.
+--*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <math.h>
+#include <errno.h>
+#include <ctype.h>
+#include "bzlib.h"
+
+#define ERROR_IF_EOF(i)       { if ((i) == EOF)  ioError(); }
+#define ERROR_IF_NOT_ZERO(i)  { if ((i) != 0)    ioError(); }
+#define ERROR_IF_MINUS_ONE(i) { if ((i) == (-1)) ioError(); }
+
+
+/*---------------------------------------------*/
+/*--
+   Platform-specific stuff.
+--*/
+
+#if BZ_UNIX
+#   include <fcntl.h>
+#   include <sys/types.h>
+#   include <utime.h>
+#   include <unistd.h>
+#   include <sys/stat.h>
+#   include <sys/times.h>
+
+#   define PATH_SEP    '/'
+#   define MY_LSTAT    lstat
+#   define MY_STAT     stat
+#   define MY_S_ISREG  S_ISREG
+#   define MY_S_ISDIR  S_ISDIR
+
+#   define APPEND_FILESPEC(root, name) \
+      root=snocString((root), (name))
+
+#   define APPEND_FLAG(root, name) \
+      root=snocString((root), (name))
+
+#   define SET_BINARY_MODE(fd) /**/
+
+#   ifdef __GNUC__
+#      define NORETURN __attribute__ ((noreturn))
+#   else
+#      define NORETURN /**/
+#   endif
+
+#   ifdef __DJGPP__
+#     include <io.h>
+#     include <fcntl.h>
+#     undef MY_LSTAT
+#     undef MY_STAT
+#     define MY_LSTAT stat
+#     define MY_STAT stat
+#     undef SET_BINARY_MODE
+#     define SET_BINARY_MODE(fd)                        \
+        do {                                            \
+           int retVal = setmode ( fileno ( fd ),        \
+                                  O_BINARY );           \
+           ERROR_IF_MINUS_ONE ( retVal );               \
+        } while ( 0 )
+#   endif
+
+#   ifdef __CYGWIN__
+#     include <io.h>
+#     include <fcntl.h>
+#     undef SET_BINARY_MODE
+#     define SET_BINARY_MODE(fd)                        \
+        do {                                            \
+           int retVal = setmode ( fileno ( fd ),        \
+                                  O_BINARY );           \
+           ERROR_IF_MINUS_ONE ( retVal );               \
+        } while ( 0 )
+#   endif
+#endif /* BZ_UNIX */
+
+
+
+#if BZ_LCCWIN32
+#   include <io.h>
+#   include <fcntl.h>
+#   include <sys\stat.h>
+
+#   define NORETURN       /**/
+#   define PATH_SEP       '\\'
+#   define MY_LSTAT       _stat
+#   define MY_STAT        _stat
+#   define MY_S_ISREG(x)  ((x) & _S_IFREG)
+#   define MY_S_ISDIR(x)  ((x) & _S_IFDIR)
+
+#   define APPEND_FLAG(root, name) \
+      root=snocString((root), (name))
+
+#   define APPEND_FILESPEC(root, name)                \
+      root = snocString ((root), (name))
+
+#   define SET_BINARY_MODE(fd)                        \
+      do {                                            \
+         int retVal = setmode ( fileno ( fd ),        \
+                                O_BINARY );           \
+         ERROR_IF_MINUS_ONE ( retVal );               \
+      } while ( 0 )
+
+#endif /* BZ_LCCWIN32 */
+
+
+/*---------------------------------------------*/
+/*--
+  Some more stuff for all platforms :-)
+--*/
+
+typedef char            Char;
+typedef unsigned char   Bool;
+typedef unsigned char   UChar;
+typedef int             Int32;
+typedef unsigned int    UInt32;
+typedef short           Int16;
+typedef unsigned short  UInt16;
+                                       
+#define True  ((Bool)1)
+#define False ((Bool)0)
+
+/*--
+  IntNative is your platform's `native' int size.
+  Only here to avoid probs with 64-bit platforms.
+--*/
+typedef int IntNative;
+
+
+/*---------------------------------------------------*/
+/*--- Misc (file handling) data decls             ---*/
+/*---------------------------------------------------*/
+
+Int32   verbosity;
+Bool    keepInputFiles, smallMode, deleteOutputOnInterrupt;
+Bool    forceOverwrite, testFailsExist, unzFailsExist, noisy;
+Int32   numFileNames, numFilesProcessed, blockSize100k;
+Int32   exitValue;
+
+/*-- source modes; F==file, I==stdin, O==stdout --*/
+#define SM_I2O           1
+#define SM_F2O           2
+#define SM_F2F           3
+
+/*-- operation modes --*/
+#define OM_Z             1
+#define OM_UNZ           2
+#define OM_TEST          3
+
+Int32   opMode;
+Int32   srcMode;
+
+#define FILE_NAME_LEN 1034
+
+Int32   longestFileName;
+Char    inName [FILE_NAME_LEN];
+Char    outName[FILE_NAME_LEN];
+Char    tmpName[FILE_NAME_LEN];
+Char    *progName;
+Char    progNameReally[FILE_NAME_LEN];
+FILE    *outputHandleJustInCase;
+Int32   workFactor;
+
+static void    panic                 ( Char* )   NORETURN;
+static void    ioError               ( void )    NORETURN;
+static void    outOfMemory           ( void )    NORETURN;
+static void    configError           ( void )    NORETURN;
+static void    crcError              ( void )    NORETURN;
+static void    cleanUpAndFail        ( Int32 )   NORETURN;
+static void    compressedStreamEOF   ( void )    NORETURN;
+
+static void    copyFileName ( Char*, Char* );
+static void*   myMalloc     ( Int32 );
+
+
+
+/*---------------------------------------------------*/
+/*--- An implementation of 64-bit ints.  Sigh.    ---*/
+/*--- Roll on widespread deployment of ANSI C9X ! ---*/
+/*---------------------------------------------------*/
+
+typedef
+   struct { UChar b[8]; } 
+   UInt64;
+
+
+static
+void uInt64_from_UInt32s ( UInt64* n, UInt32 lo32, UInt32 hi32 )
+{
+   n->b[7] = (UChar)((hi32 >> 24) & 0xFF);
+   n->b[6] = (UChar)((hi32 >> 16) & 0xFF);
+   n->b[5] = (UChar)((hi32 >> 8)  & 0xFF);
+   n->b[4] = (UChar) (hi32        & 0xFF);
+   n->b[3] = (UChar)((lo32 >> 24) & 0xFF);
+   n->b[2] = (UChar)((lo32 >> 16) & 0xFF);
+   n->b[1] = (UChar)((lo32 >> 8)  & 0xFF);
+   n->b[0] = (UChar) (lo32        & 0xFF);
+}
+
+
+static
+double uInt64_to_double ( UInt64* n )
+{
+   Int32  i;
+   double base = 1.0;
+   double sum  = 0.0;
+   for (i = 0; i < 8; i++) {
+      sum  += base * (double)(n->b[i]);
+      base *= 256.0;
+   }
+   return sum;
+}
+
+
+static
+Bool uInt64_isZero ( UInt64* n )
+{
+   Int32 i;
+   for (i = 0; i < 8; i++)
+      if (n->b[i] != 0) return 0;
+   return 1;
+}
+
+
+/* Divide *n by 10, and return the remainder.  */
+static 
+Int32 uInt64_qrm10 ( UInt64* n )
+{
+   UInt32 rem, tmp;
+   Int32  i;
+   rem = 0;
+   for (i = 7; i >= 0; i--) {
+      tmp = rem * 256 + n->b[i];
+      n->b[i] = tmp / 10;
+      rem = tmp % 10;
+   }
+   return rem;
+}
+
+
+/* ... and the Whole Entire Point of all this UInt64 stuff is
+   so that we can supply the following function.
+*/
+static
+void uInt64_toAscii ( char* outbuf, UInt64* n )
+{
+   Int32  i, q;
+   UChar  buf[32];
+   Int32  nBuf   = 0;
+   UInt64 n_copy = *n;
+   do {
+      q = uInt64_qrm10 ( &n_copy );
+      buf[nBuf] = q + '0';
+      nBuf++;
+   } while (!uInt64_isZero(&n_copy));
+   outbuf[nBuf] = 0;
+   for (i = 0; i < nBuf; i++) 
+      outbuf[i] = buf[nBuf-i-1];
+}
+
+
+/*---------------------------------------------------*/
+/*--- Processing of complete files and streams    ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------*/
+static 
+Bool myfeof ( FILE* f )
+{
+   Int32 c = fgetc ( f );
+   if (c == EOF) return True;
+   ungetc ( c, f );
+   return False;
+}
+
+
+/*---------------------------------------------*/
+static 
+void compressStream ( FILE *stream, FILE *zStream )
+{
+   BZFILE* bzf = NULL;
+   UChar   ibuf[5000];
+   Int32   nIbuf;
+   UInt32  nbytes_in_lo32, nbytes_in_hi32;
+   UInt32  nbytes_out_lo32, nbytes_out_hi32;
+   Int32   bzerr, bzerr_dummy, ret;
+
+   SET_BINARY_MODE(stream);
+   SET_BINARY_MODE(zStream);
+
+   if (ferror(stream)) goto errhandler_io;
+   if (ferror(zStream)) goto errhandler_io;
+
+   bzf = BZ2_bzWriteOpen ( &bzerr, zStream, 
+                           blockSize100k, verbosity, workFactor );   
+   if (bzerr != BZ_OK) goto errhandler;
+
+   if (verbosity >= 2) fprintf ( stderr, "\n" );
+
+   while (True) {
+
+      if (myfeof(stream)) break;
+      nIbuf = fread ( ibuf, sizeof(UChar), 5000, stream );
+      if (ferror(stream)) goto errhandler_io;
+      if (nIbuf > 0) BZ2_bzWrite ( &bzerr, bzf, (void*)ibuf, nIbuf );
+      if (bzerr != BZ_OK) goto errhandler;
+
+   }
+
+   BZ2_bzWriteClose64 ( &bzerr, bzf, 0, 
+                        &nbytes_in_lo32, &nbytes_in_hi32,
+                        &nbytes_out_lo32, &nbytes_out_hi32 );
+   if (bzerr != BZ_OK) goto errhandler;
+
+   if (ferror(zStream)) goto errhandler_io;
+   ret = fflush ( zStream );
+   if (ret == EOF) goto errhandler_io;
+   if (zStream != stdout) {
+      ret = fclose ( zStream );
+      outputHandleJustInCase = NULL;
+      if (ret == EOF) goto errhandler_io;
+   }
+   outputHandleJustInCase = NULL;
+   if (ferror(stream)) goto errhandler_io;
+   ret = fclose ( stream );
+   if (ret == EOF) goto errhandler_io;
+
+   if (verbosity >= 1) {
+      if (nbytes_in_lo32 == 0 && nbytes_in_hi32 == 0) {
+	 fprintf ( stderr, " no data compressed.\n");
+      } else {
+	 Char   buf_nin[32], buf_nout[32];
+	 UInt64 nbytes_in,   nbytes_out;
+	 double nbytes_in_d, nbytes_out_d;
+	 uInt64_from_UInt32s ( &nbytes_in, 
+			       nbytes_in_lo32, nbytes_in_hi32 );
+	 uInt64_from_UInt32s ( &nbytes_out, 
+			       nbytes_out_lo32, nbytes_out_hi32 );
+	 nbytes_in_d  = uInt64_to_double ( &nbytes_in );
+	 nbytes_out_d = uInt64_to_double ( &nbytes_out );
+	 uInt64_toAscii ( buf_nin, &nbytes_in );
+	 uInt64_toAscii ( buf_nout, &nbytes_out );
+	 fprintf ( stderr, "%6.3f:1, %6.3f bits/byte, "
+		   "%5.2f%% saved, %s in, %s out.\n",
+		   nbytes_in_d / nbytes_out_d,
+		   (8.0 * nbytes_out_d) / nbytes_in_d,
+		   100.0 * (1.0 - nbytes_out_d / nbytes_in_d),
+		   buf_nin,
+		   buf_nout
+		 );
+      }
+   }
+
+   return;
+
+   errhandler:
+   BZ2_bzWriteClose64 ( &bzerr_dummy, bzf, 1, 
+                        &nbytes_in_lo32, &nbytes_in_hi32,
+                        &nbytes_out_lo32, &nbytes_out_hi32 );
+   switch (bzerr) {
+      case BZ_CONFIG_ERROR:
+         configError(); break;
+      case BZ_MEM_ERROR:
+         outOfMemory (); break;
+      case BZ_IO_ERROR:
+         errhandler_io:
+         ioError(); break;
+      default:
+         panic ( "compress:unexpected error" );
+   }
+
+   panic ( "compress:end" );
+   /*notreached*/
+}
+
+
+
+/*---------------------------------------------*/
+static 
+Bool uncompressStream ( FILE *zStream, FILE *stream )
+{
+   BZFILE* bzf = NULL;
+   Int32   bzerr, bzerr_dummy, ret, nread, streamNo, i;
+   UChar   obuf[5000];
+   UChar   unused[BZ_MAX_UNUSED];
+   Int32   nUnused;
+   void*   unusedTmpV;
+   UChar*  unusedTmp;
+
+   nUnused = 0;
+   streamNo = 0;
+
+   SET_BINARY_MODE(stream);
+   SET_BINARY_MODE(zStream);
+
+   if (ferror(stream)) goto errhandler_io;
+   if (ferror(zStream)) goto errhandler_io;
+
+   while (True) {
+
+      bzf = BZ2_bzReadOpen ( 
+               &bzerr, zStream, verbosity, 
+               (int)smallMode, unused, nUnused
+            );
+      if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
+      streamNo++;
+
+      while (bzerr == BZ_OK) {
+         nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
+         if (bzerr == BZ_DATA_ERROR_MAGIC) goto trycat;
+         if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0)
+            fwrite ( obuf, sizeof(UChar), nread, stream );
+         if (ferror(stream)) goto errhandler_io;
+      }
+      if (bzerr != BZ_STREAM_END) goto errhandler;
+
+      BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused );
+      if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
+
+      unusedTmp = (UChar*)unusedTmpV;
+      for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
+
+      BZ2_bzReadClose ( &bzerr, bzf );
+      if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
+
+      if (nUnused == 0 && myfeof(zStream)) break;
+   }
+
+   closeok:
+   if (ferror(zStream)) goto errhandler_io;
+   ret = fclose ( zStream );
+   if (ret == EOF) goto errhandler_io;
+
+   if (ferror(stream)) goto errhandler_io;
+   ret = fflush ( stream );
+   if (ret != 0) goto errhandler_io;
+   if (stream != stdout) {
+      ret = fclose ( stream );
+      outputHandleJustInCase = NULL;
+      if (ret == EOF) goto errhandler_io;
+   }
+   outputHandleJustInCase = NULL;
+   if (verbosity >= 2) fprintf ( stderr, "\n    " );
+   return True;
+
+   trycat: 
+   if (forceOverwrite) {
+      rewind(zStream);
+      while (True) {
+      	 if (myfeof(zStream)) break;
+      	 nread = fread ( obuf, sizeof(UChar), 5000, zStream );
+      	 if (ferror(zStream)) goto errhandler_io;
+      	 if (nread > 0) fwrite ( obuf, sizeof(UChar), nread, stream );
+      	 if (ferror(stream)) goto errhandler_io;
+      }
+      goto closeok;
+   }
+  
+   errhandler:
+   BZ2_bzReadClose ( &bzerr_dummy, bzf );
+   switch (bzerr) {
+      case BZ_CONFIG_ERROR:
+         configError(); break;
+      case BZ_IO_ERROR:
+         errhandler_io:
+         ioError(); break;
+      case BZ_DATA_ERROR:
+         crcError();
+      case BZ_MEM_ERROR:
+         outOfMemory();
+      case BZ_UNEXPECTED_EOF:
+         compressedStreamEOF();
+      case BZ_DATA_ERROR_MAGIC:
+         if (zStream != stdin) fclose(zStream);
+         if (stream != stdout) fclose(stream);
+         if (streamNo == 1) {
+            return False;
+         } else {
+            if (noisy)
+            fprintf ( stderr, 
+                      "\n%s: %s: trailing garbage after EOF ignored\n",
+                      progName, inName );
+            return True;       
+         }
+      default:
+         panic ( "decompress:unexpected error" );
+   }
+
+   panic ( "decompress:end" );
+   return True; /*notreached*/
+}
+
+
+/*---------------------------------------------*/
+static 
+Bool testStream ( FILE *zStream )
+{
+   BZFILE* bzf = NULL;
+   Int32   bzerr, bzerr_dummy, ret, nread, streamNo, i;
+   UChar   obuf[5000];
+   UChar   unused[BZ_MAX_UNUSED];
+   Int32   nUnused;
+   void*   unusedTmpV;
+   UChar*  unusedTmp;
+
+   nUnused = 0;
+   streamNo = 0;
+
+   SET_BINARY_MODE(zStream);
+   if (ferror(zStream)) goto errhandler_io;
+
+   while (True) {
+
+      bzf = BZ2_bzReadOpen ( 
+               &bzerr, zStream, verbosity, 
+               (int)smallMode, unused, nUnused
+            );
+      if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
+      streamNo++;
+
+      while (bzerr == BZ_OK) {
+         nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
+         if (bzerr == BZ_DATA_ERROR_MAGIC) goto errhandler;
+      }
+      if (bzerr != BZ_STREAM_END) goto errhandler;
+
+      BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused );
+      if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
+
+      unusedTmp = (UChar*)unusedTmpV;
+      for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
+
+      BZ2_bzReadClose ( &bzerr, bzf );
+      if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
+      if (nUnused == 0 && myfeof(zStream)) break;
+
+   }
+
+   if (ferror(zStream)) goto errhandler_io;
+   ret = fclose ( zStream );
+   if (ret == EOF) goto errhandler_io;
+
+   if (verbosity >= 2) fprintf ( stderr, "\n    " );
+   return True;
+
+   errhandler:
+   BZ2_bzReadClose ( &bzerr_dummy, bzf );
+   if (verbosity == 0) 
+      fprintf ( stderr, "%s: %s: ", progName, inName );
+   switch (bzerr) {
+      case BZ_CONFIG_ERROR:
+         configError(); break;
+      case BZ_IO_ERROR:
+         errhandler_io:
+         ioError(); break;
+      case BZ_DATA_ERROR:
+         fprintf ( stderr,
+                   "data integrity (CRC) error in data\n" );
+         return False;
+      case BZ_MEM_ERROR:
+         outOfMemory();
+      case BZ_UNEXPECTED_EOF:
+         fprintf ( stderr,
+                   "file ends unexpectedly\n" );
+         return False;
+      case BZ_DATA_ERROR_MAGIC:
+         if (zStream != stdin) fclose(zStream);
+         if (streamNo == 1) {
+          fprintf ( stderr, 
+                    "bad magic number (file not created by bzip2)\n" );
+            return False;
+         } else {
+            if (noisy)
+            fprintf ( stderr, 
+                      "trailing garbage after EOF ignored\n" );
+            return True;       
+         }
+      default:
+         panic ( "test:unexpected error" );
+   }
+
+   panic ( "test:end" );
+   return True; /*notreached*/
+}
+
+
+/*---------------------------------------------------*/
+/*--- Error [non-] handling grunge                ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------*/
+static
+void setExit ( Int32 v )
+{
+   if (v > exitValue) exitValue = v;
+}
+
+
+/*---------------------------------------------*/
+static 
+void cadvise ( void )
+{
+   if (noisy)
+   fprintf (
+      stderr,
+      "\nIt is possible that the compressed file(s) have become corrupted.\n"
+        "You can use the -tvv option to test integrity of such files.\n\n"
+        "You can use the `bzip2recover' program to attempt to recover\n"
+        "data from undamaged sections of corrupted files.\n\n"
+    );
+}
+
+
+/*---------------------------------------------*/
+static 
+void showFileNames ( void )
+{
+   if (noisy)
+   fprintf (
+      stderr,
+      "\tInput file = %s, output file = %s\n",
+      inName, outName 
+   );
+}
+
+
+/*---------------------------------------------*/
+static 
+void cleanUpAndFail ( Int32 ec )
+{
+   IntNative      retVal;
+   struct MY_STAT statBuf;
+
+   if ( srcMode == SM_F2F 
+        && opMode != OM_TEST
+        && deleteOutputOnInterrupt ) {
+
+      /* Check whether input file still exists.  Delete output file
+         only if input exists to avoid loss of data.  Joerg Prante, 5
+         January 2002.  (JRS 06-Jan-2002: other changes in 1.0.2 mean
+         this is less likely to happen.  But to be ultra-paranoid, we
+         do the check anyway.)  */
+      retVal = MY_STAT ( inName, &statBuf );
+      if (retVal == 0) {
+         if (noisy)
+            fprintf ( stderr, 
+                      "%s: Deleting output file %s, if it exists.\n",
+                      progName, outName );
+         if (outputHandleJustInCase != NULL)
+            fclose ( outputHandleJustInCase );
+         retVal = remove ( outName );
+         if (retVal != 0)
+            fprintf ( stderr,
+                      "%s: WARNING: deletion of output file "
+                      "(apparently) failed.\n",
+                      progName );
+      } else {
+         fprintf ( stderr,
+                   "%s: WARNING: deletion of output file suppressed\n",
+                    progName );
+         fprintf ( stderr,
+                   "%s:    since input file no longer exists.  Output file\n",
+                   progName );
+         fprintf ( stderr,
+                   "%s:    `%s' may be incomplete.\n",
+                   progName, outName );
+         fprintf ( stderr, 
+                   "%s:    I suggest doing an integrity test (bzip2 -tv)"
+                   " of it.\n",
+                   progName );
+      }
+   }
+
+   if (noisy && numFileNames > 0 && numFilesProcessed < numFileNames) {
+      fprintf ( stderr, 
+                "%s: WARNING: some files have not been processed:\n"
+                "%s:    %d specified on command line, %d not processed yet.\n\n",
+                progName, progName,
+                numFileNames, numFileNames - numFilesProcessed );
+   }
+   setExit(ec);
+   exit(exitValue);
+}
+
+
+/*---------------------------------------------*/
+static 
+void panic ( Char* s )
+{
+   fprintf ( stderr,
+             "\n%s: PANIC -- internal consistency error:\n"
+             "\t%s\n"
+             "\tThis is a BUG.  Please report it to me at:\n"
+             "\tjseward@bzip.org\n",
+             progName, s );
+   showFileNames();
+   cleanUpAndFail( 3 );
+}
+
+
+/*---------------------------------------------*/
+static 
+void crcError ( void )
+{
+   fprintf ( stderr,
+             "\n%s: Data integrity error when decompressing.\n",
+             progName );
+   showFileNames();
+   cadvise();
+   cleanUpAndFail( 2 );
+}
+
+
+/*---------------------------------------------*/
+static 
+void compressedStreamEOF ( void )
+{
+  if (noisy) {
+    fprintf ( stderr,
+	      "\n%s: Compressed file ends unexpectedly;\n\t"
+	      "perhaps it is corrupted?  *Possible* reason follows.\n",
+	      progName );
+    perror ( progName );
+    showFileNames();
+    cadvise();
+  }
+  cleanUpAndFail( 2 );
+}
+
+
+/*---------------------------------------------*/
+static 
+void ioError ( void )
+{
+   fprintf ( stderr,
+             "\n%s: I/O or other error, bailing out.  "
+             "Possible reason follows.\n",
+             progName );
+   perror ( progName );
+   showFileNames();
+   cleanUpAndFail( 1 );
+}
+
+
+/*---------------------------------------------*/
+static 
+void mySignalCatcher ( IntNative n )
+{
+   fprintf ( stderr,
+             "\n%s: Control-C or similar caught, quitting.\n",
+             progName );
+   cleanUpAndFail(1);
+}
+
+
+/*---------------------------------------------*/
+static 
+void mySIGSEGVorSIGBUScatcher ( IntNative n )
+{
+   if (opMode == OM_Z)
+      fprintf ( 
+      stderr,
+      "\n%s: Caught a SIGSEGV or SIGBUS whilst compressing.\n"
+      "\n"
+      "   Possible causes are (most likely first):\n"
+      "   (1) This computer has unreliable memory or cache hardware\n"
+      "       (a surprisingly common problem; try a different machine.)\n"
+      "   (2) A bug in the compiler used to create this executable\n"
+      "       (unlikely, if you didn't compile bzip2 yourself.)\n"
+      "   (3) A real bug in bzip2 -- I hope this should never be the case.\n"
+      "   The user's manual, Section 4.3, has more info on (1) and (2).\n"
+      "   \n"
+      "   If you suspect this is a bug in bzip2, or are unsure about (1)\n"
+      "   or (2), feel free to report it to me at: jseward@bzip.org.\n"
+      "   Section 4.3 of the user's manual describes the info a useful\n"
+      "   bug report should have.  If the manual is available on your\n"
+      "   system, please try and read it before mailing me.  If you don't\n"
+      "   have the manual or can't be bothered to read it, mail me anyway.\n"
+      "\n",
+      progName );
+      else
+      fprintf ( 
+      stderr,
+      "\n%s: Caught a SIGSEGV or SIGBUS whilst decompressing.\n"
+      "\n"
+      "   Possible causes are (most likely first):\n"
+      "   (1) The compressed data is corrupted, and bzip2's usual checks\n"
+      "       failed to detect this.  Try bzip2 -tvv my_file.bz2.\n"
+      "   (2) This computer has unreliable memory or cache hardware\n"
+      "       (a surprisingly common problem; try a different machine.)\n"
+      "   (3) A bug in the compiler used to create this executable\n"
+      "       (unlikely, if you didn't compile bzip2 yourself.)\n"
+      "   (4) A real bug in bzip2 -- I hope this should never be the case.\n"
+      "   The user's manual, Section 4.3, has more info on (2) and (3).\n"
+      "   \n"
+      "   If you suspect this is a bug in bzip2, or are unsure about (2)\n"
+      "   or (3), feel free to report it to me at: jseward@bzip.org.\n"
+      "   Section 4.3 of the user's manual describes the info a useful\n"
+      "   bug report should have.  If the manual is available on your\n"
+      "   system, please try and read it before mailing me.  If you don't\n"
+      "   have the manual or can't be bothered to read it, mail me anyway.\n"
+      "\n",
+      progName );
+
+   showFileNames();
+   if (opMode == OM_Z)
+      cleanUpAndFail( 3 ); else
+      { cadvise(); cleanUpAndFail( 2 ); }
+}
+
+
+/*---------------------------------------------*/
+static 
+void outOfMemory ( void )
+{
+   fprintf ( stderr,
+             "\n%s: couldn't allocate enough memory\n",
+             progName );
+   showFileNames();
+   cleanUpAndFail(1);
+}
+
+
+/*---------------------------------------------*/
+static 
+void configError ( void )
+{
+   fprintf ( stderr,
+             "bzip2: I'm not configured correctly for this platform!\n"
+             "\tI require Int32, Int16 and Char to have sizes\n"
+             "\tof 4, 2 and 1 bytes to run properly, and they don't.\n"
+             "\tProbably you can fix this by defining them correctly,\n"
+             "\tand recompiling.  Bye!\n" );
+   setExit(3);
+   exit(exitValue);
+}
+
+
+/*---------------------------------------------------*/
+/*--- The main driver machinery                   ---*/
+/*---------------------------------------------------*/
+
+/* All rather crufty.  The main problem is that input files
+   are stat()d multiple times before use.  This should be
+   cleaned up. 
+*/
+
+/*---------------------------------------------*/
+static 
+void pad ( Char *s )
+{
+   Int32 i;
+   if ( (Int32)strlen(s) >= longestFileName ) return;
+   for (i = 1; i <= longestFileName - (Int32)strlen(s); i++)
+      fprintf ( stderr, " " );
+}
+
+
+/*---------------------------------------------*/
+static 
+void copyFileName ( Char* to, Char* from ) 
+{
+   if ( strlen(from) > FILE_NAME_LEN-10 )  {
+      fprintf (
+         stderr,
+         "bzip2: file name\n`%s'\n"
+         "is suspiciously (more than %d chars) long.\n"
+         "Try using a reasonable file name instead.  Sorry! :-)\n",
+         from, FILE_NAME_LEN-10
+      );
+      setExit(1);
+      exit(exitValue);
+   }
+
+  strncpy(to,from,FILE_NAME_LEN-10);
+  to[FILE_NAME_LEN-10]='\0';
+}
+
+
+/*---------------------------------------------*/
+static 
+Bool fileExists ( Char* name )
+{
+   FILE *tmp   = fopen ( name, "rb" );
+   Bool exists = (tmp != NULL);
+   if (tmp != NULL) fclose ( tmp );
+   return exists;
+}
+
+
+/*---------------------------------------------*/
+/* Open an output file safely with O_EXCL and good permissions.
+   This avoids a race condition in versions < 1.0.2, in which
+   the file was first opened and then had its interim permissions
+   set safely.  We instead use open() to create the file with
+   the interim permissions required. (--- --- rw-).
+
+   For non-Unix platforms, if we are not worrying about
+   security issues, simple this simply behaves like fopen.
+*/
+FILE* fopen_output_safely ( Char* name, const char* mode )
+{
+#  if BZ_UNIX
+   FILE*     fp;
+   IntNative fh;
+   fh = open(name, O_WRONLY|O_CREAT|O_EXCL, S_IWUSR|S_IRUSR);
+   if (fh == -1) return NULL;
+   fp = fdopen(fh, mode);
+   if (fp == NULL) close(fh);
+   return fp;
+#  else
+   return fopen(name, mode);
+#  endif
+}
+
+
+/*---------------------------------------------*/
+/*--
+  if in doubt, return True
+--*/
+static 
+Bool notAStandardFile ( Char* name )
+{
+   IntNative      i;
+   struct MY_STAT statBuf;
+
+   i = MY_LSTAT ( name, &statBuf );
+   if (i != 0) return True;
+   if (MY_S_ISREG(statBuf.st_mode)) return False;
+   return True;
+}
+
+
+/*---------------------------------------------*/
+/*--
+  rac 11/21/98 see if file has hard links to it
+--*/
+static 
+Int32 countHardLinks ( Char* name )
+{  
+   IntNative      i;
+   struct MY_STAT statBuf;
+
+   i = MY_LSTAT ( name, &statBuf );
+   if (i != 0) return 0;
+   return (statBuf.st_nlink - 1);
+}
+
+
+/*---------------------------------------------*/
+/* Copy modification date, access date, permissions and owner from the
+   source to destination file.  We have to copy this meta-info off
+   into fileMetaInfo before starting to compress / decompress it,
+   because doing it afterwards means we get the wrong access time.
+
+   To complicate matters, in compress() and decompress() below, the
+   sequence of tests preceding the call to saveInputFileMetaInfo()
+   involves calling fileExists(), which in turn establishes its result
+   by attempting to fopen() the file, and if successful, immediately
+   fclose()ing it again.  So we have to assume that the fopen() call
+   does not cause the access time field to be updated.
+
+   Reading of the man page for stat() (man 2 stat) on RedHat 7.2 seems
+   to imply that merely doing open() will not affect the access time.
+   Therefore we merely need to hope that the C library only does
+   open() as a result of fopen(), and not any kind of read()-ahead
+   cleverness.
+
+   It sounds pretty fragile to me.  Whether this carries across
+   robustly to arbitrary Unix-like platforms (or even works robustly
+   on this one, RedHat 7.2) is unknown to me.  Nevertheless ...  
+*/
+#if BZ_UNIX
+static 
+struct MY_STAT fileMetaInfo;
+#endif
+
+static 
+void saveInputFileMetaInfo ( Char *srcName )
+{
+#  if BZ_UNIX
+   IntNative retVal;
+   /* Note use of stat here, not lstat. */
+   retVal = MY_STAT( srcName, &fileMetaInfo );
+   ERROR_IF_NOT_ZERO ( retVal );
+#  endif
+}
+
+
+static 
+void applySavedMetaInfoToOutputFile ( Char *dstName )
+{
+#  if BZ_UNIX
+   IntNative      retVal;
+   struct utimbuf uTimBuf;
+
+   uTimBuf.actime = fileMetaInfo.st_atime;
+   uTimBuf.modtime = fileMetaInfo.st_mtime;
+
+   retVal = chmod ( dstName, fileMetaInfo.st_mode );
+   ERROR_IF_NOT_ZERO ( retVal );
+
+   retVal = utime ( dstName, &uTimBuf );
+   ERROR_IF_NOT_ZERO ( retVal );
+
+   retVal = chown ( dstName, fileMetaInfo.st_uid, fileMetaInfo.st_gid );
+   /* chown() will in many cases return with EPERM, which can
+      be safely ignored.
+   */
+#  endif
+}
+
+
+/*---------------------------------------------*/
+static 
+Bool containsDubiousChars ( Char* name )
+{
+#  if BZ_UNIX
+   /* On unix, files can contain any characters and the file expansion
+    * is performed by the shell.
+    */
+   return False;
+#  else /* ! BZ_UNIX */
+   /* On non-unix (Win* platforms), wildcard characters are not allowed in 
+    * filenames.
+    */
+   for (; *name != '\0'; name++)
+      if (*name == '?' || *name == '*') return True;
+   return False;
+#  endif /* BZ_UNIX */
+}
+
+
+/*---------------------------------------------*/
+#define BZ_N_SUFFIX_PAIRS 4
+
+Char* zSuffix[BZ_N_SUFFIX_PAIRS] 
+   = { ".bz2", ".bz", ".tbz2", ".tbz" };
+Char* unzSuffix[BZ_N_SUFFIX_PAIRS] 
+   = { "", "", ".tar", ".tar" };
+
+static 
+Bool hasSuffix ( Char* s, Char* suffix )
+{
+   Int32 ns = strlen(s);
+   Int32 nx = strlen(suffix);
+   if (ns < nx) return False;
+   if (strcmp(s + ns - nx, suffix) == 0) return True;
+   return False;
+}
+
+static 
+Bool mapSuffix ( Char* name, 
+                 Char* oldSuffix, Char* newSuffix )
+{
+   if (!hasSuffix(name,oldSuffix)) return False;
+   name[strlen(name)-strlen(oldSuffix)] = 0;
+   strcat ( name, newSuffix );
+   return True;
+}
+
+
+/*---------------------------------------------*/
+static 
+void compress ( Char *name )
+{
+   FILE  *inStr;
+   FILE  *outStr;
+   Int32 n, i;
+   struct MY_STAT statBuf;
+
+   deleteOutputOnInterrupt = False;
+
+   if (name == NULL && srcMode != SM_I2O)
+      panic ( "compress: bad modes\n" );
+
+   switch (srcMode) {
+      case SM_I2O: 
+         copyFileName ( inName, "(stdin)" );
+         copyFileName ( outName, "(stdout)" ); 
+         break;
+      case SM_F2F: 
+         copyFileName ( inName, name );
+         copyFileName ( outName, name );
+         strcat ( outName, ".bz2" ); 
+         break;
+      case SM_F2O: 
+         copyFileName ( inName, name );
+         copyFileName ( outName, "(stdout)" ); 
+         break;
+   }
+
+   if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
+      if (noisy)
+      fprintf ( stderr, "%s: There are no files matching `%s'.\n",
+                progName, inName );
+      setExit(1);
+      return;
+   }
+   if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
+      fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
+                progName, inName, strerror(errno) );
+      setExit(1);
+      return;
+   }
+   for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++) {
+      if (hasSuffix(inName, zSuffix[i])) {
+         if (noisy)
+         fprintf ( stderr, 
+                   "%s: Input file %s already has %s suffix.\n",
+                   progName, inName, zSuffix[i] );
+         setExit(1);
+         return;
+      }
+   }
+   if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
+      MY_STAT(inName, &statBuf);
+      if ( MY_S_ISDIR(statBuf.st_mode) ) {
+         fprintf( stderr,
+                  "%s: Input file %s is a directory.\n",
+                  progName,inName);
+         setExit(1);
+         return;
+      }
+   }
+   if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
+      if (noisy)
+      fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
+                progName, inName );
+      setExit(1);
+      return;
+   }
+   if ( srcMode == SM_F2F && fileExists ( outName ) ) {
+      if (forceOverwrite) {
+	 remove(outName);
+      } else {
+	 fprintf ( stderr, "%s: Output file %s already exists.\n",
+		   progName, outName );
+	 setExit(1);
+	 return;
+      }
+   }
+   if ( srcMode == SM_F2F && !forceOverwrite &&
+        (n=countHardLinks ( inName )) > 0) {
+      fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
+                progName, inName, n, n > 1 ? "s" : "" );
+      setExit(1);
+      return;
+   }
+
+   if ( srcMode == SM_F2F ) {
+      /* Save the file's meta-info before we open it.  Doing it later
+         means we mess up the access times. */
+      saveInputFileMetaInfo ( inName );
+   }
+
+   switch ( srcMode ) {
+
+      case SM_I2O:
+         inStr = stdin;
+         outStr = stdout;
+         if ( isatty ( fileno ( stdout ) ) ) {
+            fprintf ( stderr,
+                      "%s: I won't write compressed data to a terminal.\n",
+                      progName );
+            fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
+                              progName, progName );
+            setExit(1);
+            return;
+         };
+         break;
+
+      case SM_F2O:
+         inStr = fopen ( inName, "rb" );
+         outStr = stdout;
+         if ( isatty ( fileno ( stdout ) ) ) {
+            fprintf ( stderr,
+                      "%s: I won't write compressed data to a terminal.\n",
+                      progName );
+            fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
+                              progName, progName );
+            if ( inStr != NULL ) fclose ( inStr );
+            setExit(1);
+            return;
+         };
+         if ( inStr == NULL ) {
+            fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
+                      progName, inName, strerror(errno) );
+            setExit(1);
+            return;
+         };
+         break;
+
+      case SM_F2F:
+         inStr = fopen ( inName, "rb" );
+         outStr = fopen_output_safely ( outName, "wb" );
+         if ( outStr == NULL) {
+            fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
+                      progName, outName, strerror(errno) );
+            if ( inStr != NULL ) fclose ( inStr );
+            setExit(1);
+            return;
+         }
+         if ( inStr == NULL ) {
+            fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
+                      progName, inName, strerror(errno) );
+            if ( outStr != NULL ) fclose ( outStr );
+            setExit(1);
+            return;
+         };
+         break;
+
+      default:
+         panic ( "compress: bad srcMode" );
+         break;
+   }
+
+   if (verbosity >= 1) {
+      fprintf ( stderr,  "  %s: ", inName );
+      pad ( inName );
+      fflush ( stderr );
+   }
+
+   /*--- Now the input and output handles are sane.  Do the Biz. ---*/
+   outputHandleJustInCase = outStr;
+   deleteOutputOnInterrupt = True;
+   compressStream ( inStr, outStr );
+   outputHandleJustInCase = NULL;
+
+   /*--- If there was an I/O error, we won't get here. ---*/
+   if ( srcMode == SM_F2F ) {
+      applySavedMetaInfoToOutputFile ( outName );
+      deleteOutputOnInterrupt = False;
+      if ( !keepInputFiles ) {
+         IntNative retVal = remove ( inName );
+         ERROR_IF_NOT_ZERO ( retVal );
+      }
+   }
+
+   deleteOutputOnInterrupt = False;
+}
+
+
+/*---------------------------------------------*/
+static 
+void uncompress ( Char *name )
+{
+   FILE  *inStr;
+   FILE  *outStr;
+   Int32 n, i;
+   Bool  magicNumberOK;
+   Bool  cantGuess;
+   struct MY_STAT statBuf;
+
+   deleteOutputOnInterrupt = False;
+
+   if (name == NULL && srcMode != SM_I2O)
+      panic ( "uncompress: bad modes\n" );
+
+   cantGuess = False;
+   switch (srcMode) {
+      case SM_I2O: 
+         copyFileName ( inName, "(stdin)" );
+         copyFileName ( outName, "(stdout)" ); 
+         break;
+      case SM_F2F: 
+         copyFileName ( inName, name );
+         copyFileName ( outName, name );
+         for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++)
+            if (mapSuffix(outName,zSuffix[i],unzSuffix[i]))
+               goto zzz; 
+         cantGuess = True;
+         strcat ( outName, ".out" );
+         break;
+      case SM_F2O: 
+         copyFileName ( inName, name );
+         copyFileName ( outName, "(stdout)" ); 
+         break;
+   }
+
+   zzz:
+   if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
+      if (noisy)
+      fprintf ( stderr, "%s: There are no files matching `%s'.\n",
+                progName, inName );
+      setExit(1);
+      return;
+   }
+   if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
+      fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
+                progName, inName, strerror(errno) );
+      setExit(1);
+      return;
+   }
+   if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
+      MY_STAT(inName, &statBuf);
+      if ( MY_S_ISDIR(statBuf.st_mode) ) {
+         fprintf( stderr,
+                  "%s: Input file %s is a directory.\n",
+                  progName,inName);
+         setExit(1);
+         return;
+      }
+   }
+   if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
+      if (noisy)
+      fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
+                progName, inName );
+      setExit(1);
+      return;
+   }
+   if ( /* srcMode == SM_F2F implied && */ cantGuess ) {
+      if (noisy)
+      fprintf ( stderr, 
+                "%s: Can't guess original name for %s -- using %s\n",
+                progName, inName, outName );
+      /* just a warning, no return */
+   }   
+   if ( srcMode == SM_F2F && fileExists ( outName ) ) {
+      if (forceOverwrite) {
+	remove(outName);
+      } else {
+        fprintf ( stderr, "%s: Output file %s already exists.\n",
+                  progName, outName );
+        setExit(1);
+        return;
+      }
+   }
+   if ( srcMode == SM_F2F && !forceOverwrite &&
+        (n=countHardLinks ( inName ) ) > 0) {
+      fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
+                progName, inName, n, n > 1 ? "s" : "" );
+      setExit(1);
+      return;
+   }
+
+   if ( srcMode == SM_F2F ) {
+      /* Save the file's meta-info before we open it.  Doing it later
+         means we mess up the access times. */
+      saveInputFileMetaInfo ( inName );
+   }
+
+   switch ( srcMode ) {
+
+      case SM_I2O:
+         inStr = stdin;
+         outStr = stdout;
+         if ( isatty ( fileno ( stdin ) ) ) {
+            fprintf ( stderr,
+                      "%s: I won't read compressed data from a terminal.\n",
+                      progName );
+            fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
+                              progName, progName );
+            setExit(1);
+            return;
+         };
+         break;
+
+      case SM_F2O:
+         inStr = fopen ( inName, "rb" );
+         outStr = stdout;
+         if ( inStr == NULL ) {
+            fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
+                      progName, inName, strerror(errno) );
+            if ( inStr != NULL ) fclose ( inStr );
+            setExit(1);
+            return;
+         };
+         break;
+
+      case SM_F2F:
+         inStr = fopen ( inName, "rb" );
+         outStr = fopen_output_safely ( outName, "wb" );
+         if ( outStr == NULL) {
+            fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
+                      progName, outName, strerror(errno) );
+            if ( inStr != NULL ) fclose ( inStr );
+            setExit(1);
+            return;
+         }
+         if ( inStr == NULL ) {
+            fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
+                      progName, inName, strerror(errno) );
+            if ( outStr != NULL ) fclose ( outStr );
+            setExit(1);
+            return;
+         };
+         break;
+
+      default:
+         panic ( "uncompress: bad srcMode" );
+         break;
+   }
+
+   if (verbosity >= 1) {
+      fprintf ( stderr, "  %s: ", inName );
+      pad ( inName );
+      fflush ( stderr );
+   }
+
+   /*--- Now the input and output handles are sane.  Do the Biz. ---*/
+   outputHandleJustInCase = outStr;
+   deleteOutputOnInterrupt = True;
+   magicNumberOK = uncompressStream ( inStr, outStr );
+   outputHandleJustInCase = NULL;
+
+   /*--- If there was an I/O error, we won't get here. ---*/
+   if ( magicNumberOK ) {
+      if ( srcMode == SM_F2F ) {
+         applySavedMetaInfoToOutputFile ( outName );
+         deleteOutputOnInterrupt = False;
+         if ( !keepInputFiles ) {
+            IntNative retVal = remove ( inName );
+            ERROR_IF_NOT_ZERO ( retVal );
+         }
+      }
+   } else {
+      unzFailsExist = True;
+      deleteOutputOnInterrupt = False;
+      if ( srcMode == SM_F2F ) {
+         IntNative retVal = remove ( outName );
+         ERROR_IF_NOT_ZERO ( retVal );
+      }
+   }
+   deleteOutputOnInterrupt = False;
+
+   if ( magicNumberOK ) {
+      if (verbosity >= 1)
+         fprintf ( stderr, "done\n" );
+   } else {
+      setExit(2);
+      if (verbosity >= 1)
+         fprintf ( stderr, "not a bzip2 file.\n" ); else
+         fprintf ( stderr,
+                   "%s: %s is not a bzip2 file.\n",
+                   progName, inName );
+   }
+
+}
+
+
+/*---------------------------------------------*/
+static 
+void testf ( Char *name )
+{
+   FILE *inStr;
+   Bool allOK;
+   struct MY_STAT statBuf;
+
+   deleteOutputOnInterrupt = False;
+
+   if (name == NULL && srcMode != SM_I2O)
+      panic ( "testf: bad modes\n" );
+
+   copyFileName ( outName, "(none)" );
+   switch (srcMode) {
+      case SM_I2O: copyFileName ( inName, "(stdin)" ); break;
+      case SM_F2F: copyFileName ( inName, name ); break;
+      case SM_F2O: copyFileName ( inName, name ); break;
+   }
+
+   if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
+      if (noisy)
+      fprintf ( stderr, "%s: There are no files matching `%s'.\n",
+                progName, inName );
+      setExit(1);
+      return;
+   }
+   if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
+      fprintf ( stderr, "%s: Can't open input %s: %s.\n",
+                progName, inName, strerror(errno) );
+      setExit(1);
+      return;
+   }
+   if ( srcMode != SM_I2O ) {
+      MY_STAT(inName, &statBuf);
+      if ( MY_S_ISDIR(statBuf.st_mode) ) {
+         fprintf( stderr,
+                  "%s: Input file %s is a directory.\n",
+                  progName,inName);
+         setExit(1);
+         return;
+      }
+   }
+
+   switch ( srcMode ) {
+
+      case SM_I2O:
+         if ( isatty ( fileno ( stdin ) ) ) {
+            fprintf ( stderr,
+                      "%s: I won't read compressed data from a terminal.\n",
+                      progName );
+            fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
+                              progName, progName );
+            setExit(1);
+            return;
+         };
+         inStr = stdin;
+         break;
+
+      case SM_F2O: case SM_F2F:
+         inStr = fopen ( inName, "rb" );
+         if ( inStr == NULL ) {
+            fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
+                      progName, inName, strerror(errno) );
+            setExit(1);
+            return;
+         };
+         break;
+
+      default:
+         panic ( "testf: bad srcMode" );
+         break;
+   }
+
+   if (verbosity >= 1) {
+      fprintf ( stderr, "  %s: ", inName );
+      pad ( inName );
+      fflush ( stderr );
+   }
+
+   /*--- Now the input handle is sane.  Do the Biz. ---*/
+   outputHandleJustInCase = NULL;
+   allOK = testStream ( inStr );
+
+   if (allOK && verbosity >= 1) fprintf ( stderr, "ok\n" );
+   if (!allOK) testFailsExist = True;
+}
+
+
+/*---------------------------------------------*/
+static 
+void license ( void )
+{
+   fprintf ( stderr,
+
+    "bzip2, a block-sorting file compressor.  "
+    "Version %s.\n"
+    "   \n"
+    "   Copyright (C) 1996-2005 by Julian Seward.\n"
+    "   \n"
+    "   This program is free software; you can redistribute it and/or modify\n"
+    "   it under the terms set out in the LICENSE file, which is included\n"
+    "   in the bzip2-1.0 source distribution.\n"
+    "   \n"
+    "   This program is distributed in the hope that it will be useful,\n"
+    "   but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+    "   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+    "   LICENSE file for more details.\n"
+    "   \n",
+    BZ2_bzlibVersion()
+   );
+}
+
+
+/*---------------------------------------------*/
+static 
+void usage ( Char *fullProgName )
+{
+   fprintf (
+      stderr,
+      "bzip2, a block-sorting file compressor.  "
+      "Version %s.\n"
+      "\n   usage: %s [flags and input files in any order]\n"
+      "\n"
+      "   -h --help           print this message\n"
+      "   -d --decompress     force decompression\n"
+      "   -z --compress       force compression\n"
+      "   -k --keep           keep (don't delete) input files\n"
+      "   -f --force          overwrite existing output files\n"
+      "   -t --test           test compressed file integrity\n"
+      "   -c --stdout         output to standard out\n"
+      "   -q --quiet          suppress noncritical error messages\n"
+      "   -v --verbose        be verbose (a 2nd -v gives more)\n"
+      "   -L --license        display software version & license\n"
+      "   -V --version        display software version & license\n"
+      "   -s --small          use less memory (at most 2500k)\n"
+      "   -1 .. -9            set block size to 100k .. 900k\n"
+      "   --fast              alias for -1\n"
+      "   --best              alias for -9\n"
+      "\n"
+      "   If invoked as `bzip2', default action is to compress.\n"
+      "              as `bunzip2',  default action is to decompress.\n"
+      "              as `bzcat', default action is to decompress to stdout.\n"
+      "\n"
+      "   If no file names are given, bzip2 compresses or decompresses\n"
+      "   from standard input to standard output.  You can combine\n"
+      "   short flags, so `-v -4' means the same as -v4 or -4v, &c.\n"
+#     if BZ_UNIX
+      "\n"
+#     endif
+      ,
+
+      BZ2_bzlibVersion(),
+      fullProgName
+   );
+}
+
+
+/*---------------------------------------------*/
+static 
+void redundant ( Char* flag )
+{
+   fprintf ( 
+      stderr, 
+      "%s: %s is redundant in versions 0.9.5 and above\n",
+      progName, flag );
+}
+
+
+/*---------------------------------------------*/
+/*--
+  All the garbage from here to main() is purely to
+  implement a linked list of command-line arguments,
+  into which main() copies argv[1 .. argc-1].
+
+  The purpose of this exercise is to facilitate 
+  the expansion of wildcard characters * and ? in 
+  filenames for OSs which don't know how to do it
+  themselves, like MSDOS, Windows 95 and NT.
+
+  The actual Dirty Work is done by the platform-
+  specific macro APPEND_FILESPEC.
+--*/
+
+typedef
+   struct zzzz {
+      Char        *name;
+      struct zzzz *link;
+   }
+   Cell;
+
+
+/*---------------------------------------------*/
+static 
+void *myMalloc ( Int32 n )
+{
+   void* p;
+
+   p = malloc ( (size_t)n );
+   if (p == NULL) outOfMemory ();
+   return p;
+}
+
+
+/*---------------------------------------------*/
+static 
+Cell *mkCell ( void )
+{
+   Cell *c;
+
+   c = (Cell*) myMalloc ( sizeof ( Cell ) );
+   c->name = NULL;
+   c->link = NULL;
+   return c;
+}
+
+
+/*---------------------------------------------*/
+static 
+Cell *snocString ( Cell *root, Char *name )
+{
+   if (root == NULL) {
+      Cell *tmp = mkCell();
+      tmp->name = (Char*) myMalloc ( 5 + strlen(name) );
+      strcpy ( tmp->name, name );
+      return tmp;
+   } else {
+      Cell *tmp = root;
+      while (tmp->link != NULL) tmp = tmp->link;
+      tmp->link = snocString ( tmp->link, name );
+      return root;
+   }
+}
+
+
+/*---------------------------------------------*/
+static 
+void addFlagsFromEnvVar ( Cell** argList, Char* varName ) 
+{
+   Int32 i, j, k;
+   Char *envbase, *p;
+
+   envbase = getenv(varName);
+   if (envbase != NULL) {
+      p = envbase;
+      i = 0;
+      while (True) {
+         if (p[i] == 0) break;
+         p += i;
+         i = 0;
+         while (isspace((Int32)(p[0]))) p++;
+         while (p[i] != 0 && !isspace((Int32)(p[i]))) i++;
+         if (i > 0) {
+            k = i; if (k > FILE_NAME_LEN-10) k = FILE_NAME_LEN-10;
+            for (j = 0; j < k; j++) tmpName[j] = p[j];
+            tmpName[k] = 0;
+            APPEND_FLAG(*argList, tmpName);
+         }
+      }
+   }
+}
+
+
+/*---------------------------------------------*/
+#define ISFLAG(s) (strcmp(aa->name, (s))==0)
+
+IntNative main ( IntNative argc, Char *argv[] )
+{
+   Int32  i, j;
+   Char   *tmp;
+   Cell   *argList;
+   Cell   *aa;
+   Bool   decode;
+
+   /*-- Be really really really paranoid :-) --*/
+   if (sizeof(Int32) != 4 || sizeof(UInt32) != 4  ||
+       sizeof(Int16) != 2 || sizeof(UInt16) != 2  ||
+       sizeof(Char)  != 1 || sizeof(UChar)  != 1)
+      configError();
+
+   /*-- Initialise --*/
+   outputHandleJustInCase  = NULL;
+   smallMode               = False;
+   keepInputFiles          = False;
+   forceOverwrite          = False;
+   noisy                   = True;
+   verbosity               = 0;
+   blockSize100k           = 9;
+   testFailsExist          = False;
+   unzFailsExist           = False;
+   numFileNames            = 0;
+   numFilesProcessed       = 0;
+   workFactor              = 30;
+   deleteOutputOnInterrupt = False;
+   exitValue               = 0;
+   i = j = 0; /* avoid bogus warning from egcs-1.1.X */
+
+   /*-- Set up signal handlers for mem access errors --*/
+   signal (SIGSEGV, mySIGSEGVorSIGBUScatcher);
+#  if BZ_UNIX
+#  ifndef __DJGPP__
+   signal (SIGBUS,  mySIGSEGVorSIGBUScatcher);
+#  endif
+#  endif
+
+   copyFileName ( inName,  "(none)" );
+   copyFileName ( outName, "(none)" );
+
+   copyFileName ( progNameReally, argv[0] );
+   progName = &progNameReally[0];
+   for (tmp = &progNameReally[0]; *tmp != '\0'; tmp++)
+      if (*tmp == PATH_SEP) progName = tmp + 1;
+
+
+   /*-- Copy flags from env var BZIP2, and 
+        expand filename wildcards in arg list.
+   --*/
+   argList = NULL;
+   addFlagsFromEnvVar ( &argList,  "BZIP2" );
+   addFlagsFromEnvVar ( &argList,  "BZIP" );
+   for (i = 1; i <= argc-1; i++)
+      APPEND_FILESPEC(argList, argv[i]);
+
+
+   /*-- Find the length of the longest filename --*/
+   longestFileName = 7;
+   numFileNames    = 0;
+   decode          = True;
+   for (aa = argList; aa != NULL; aa = aa->link) {
+      if (ISFLAG("--")) { decode = False; continue; }
+      if (aa->name[0] == '-' && decode) continue;
+      numFileNames++;
+      if (longestFileName < (Int32)strlen(aa->name) )
+         longestFileName = (Int32)strlen(aa->name);
+   }
+
+
+   /*-- Determine source modes; flag handling may change this too. --*/
+   if (numFileNames == 0)
+      srcMode = SM_I2O; else srcMode = SM_F2F;
+
+
+   /*-- Determine what to do (compress/uncompress/test/cat). --*/
+   /*-- Note that subsequent flag handling may change this. --*/
+   opMode = OM_Z;
+
+   if ( (strstr ( progName, "unzip" ) != 0) ||
+        (strstr ( progName, "UNZIP" ) != 0) )
+      opMode = OM_UNZ;
+
+   if ( (strstr ( progName, "z2cat" ) != 0) ||
+        (strstr ( progName, "Z2CAT" ) != 0) ||
+        (strstr ( progName, "zcat" ) != 0)  ||
+        (strstr ( progName, "ZCAT" ) != 0) )  {
+      opMode = OM_UNZ;
+      srcMode = (numFileNames == 0) ? SM_I2O : SM_F2O;
+   }
+
+   if(strstr ( progName, "small" ) != 0) {
+   	smallMode = True;
+   }
+
+
+   /*-- Look at the flags. --*/
+   for (aa = argList; aa != NULL; aa = aa->link) {
+      if (ISFLAG("--")) break;
+      if (aa->name[0] == '-' && aa->name[1] != '-') {
+         for (j = 1; aa->name[j] != '\0'; j++) {
+            switch (aa->name[j]) {
+               case 'c': srcMode          = SM_F2O; break;
+               case 'd': opMode           = OM_UNZ; break;
+               case 'z': opMode           = OM_Z; break;
+               case 'f': forceOverwrite   = True; break;
+               case 't': opMode           = OM_TEST; break;
+               case 'k': keepInputFiles   = True; break;
+               case 's': smallMode        = True; break;
+               case 'q': noisy            = False; break;
+               case '1': blockSize100k    = 1; break;
+               case '2': blockSize100k    = 2; break;
+               case '3': blockSize100k    = 3; break;
+               case '4': blockSize100k    = 4; break;
+               case '5': blockSize100k    = 5; break;
+               case '6': blockSize100k    = 6; break;
+               case '7': blockSize100k    = 7; break;
+               case '8': blockSize100k    = 8; break;
+               case '9': blockSize100k    = 9; break;
+               case 'V':
+               case 'L': license();            break;
+               case 'v': verbosity++; break;
+               case 'h': usage ( progName );
+                         exit ( 0 );
+                         break;
+               default:  fprintf ( stderr, "%s: Bad flag `%s'\n",
+                                   progName, aa->name );
+                         usage ( progName );
+                         exit ( 1 );
+                         break;
+            }
+         }
+      }
+   }
+   
+   /*-- And again ... --*/
+   for (aa = argList; aa != NULL; aa = aa->link) {
+      if (ISFLAG("--")) break;
+      if (ISFLAG("--stdout"))            srcMode          = SM_F2O;  else
+      if (ISFLAG("--decompress"))        opMode           = OM_UNZ;  else
+      if (ISFLAG("--compress"))          opMode           = OM_Z;    else
+      if (ISFLAG("--force"))             forceOverwrite   = True;    else
+      if (ISFLAG("--test"))              opMode           = OM_TEST; else
+      if (ISFLAG("--keep"))              keepInputFiles   = True;    else
+      if (ISFLAG("--small"))             smallMode        = True;    else
+      if (ISFLAG("--quiet"))             noisy            = False;   else
+      if (ISFLAG("--version"))           license();                  else
+      if (ISFLAG("--license"))           license();                  else
+      if (ISFLAG("--exponential"))       workFactor = 1;             else 
+      if (ISFLAG("--repetitive-best"))   redundant(aa->name);        else
+      if (ISFLAG("--repetitive-fast"))   redundant(aa->name);        else
+      if (ISFLAG("--fast"))              blockSize100k = 1;          else
+      if (ISFLAG("--best"))              blockSize100k = 9;          else
+      if (ISFLAG("--verbose"))           verbosity++;                else
+      if (ISFLAG("--help"))              { usage ( progName ); exit ( 0 ); }
+         else
+         if (strncmp ( aa->name, "--", 2) == 0) {
+            fprintf ( stderr, "%s: Bad flag `%s'\n", progName, aa->name );
+            usage ( progName );
+            exit ( 1 );
+         }
+   }
+
+   if (verbosity > 4) verbosity = 4;
+   if (opMode == OM_Z && smallMode && blockSize100k > 2) 
+      blockSize100k = 2;
+
+   if (opMode == OM_TEST && srcMode == SM_F2O) {
+      fprintf ( stderr, "%s: -c and -t cannot be used together.\n",
+                progName );
+      exit ( 1 );
+   }
+
+   if (srcMode == SM_F2O && numFileNames == 0)
+      srcMode = SM_I2O;
+
+   if (opMode != OM_Z) blockSize100k = 0;
+
+   if (srcMode == SM_F2F) {
+      signal (SIGINT,  mySignalCatcher);
+      signal (SIGTERM, mySignalCatcher);
+#     if BZ_UNIX
+      signal (SIGHUP,  mySignalCatcher);
+#     endif
+   }
+
+   if (opMode == OM_Z) {
+     if (srcMode == SM_I2O) {
+        compress ( NULL );
+     } else {
+        decode = True;
+        for (aa = argList; aa != NULL; aa = aa->link) {
+           if (ISFLAG("--")) { decode = False; continue; }
+           if (aa->name[0] == '-' && decode) continue;
+           numFilesProcessed++;
+           compress ( aa->name );
+        }
+     }
+   } 
+   else
+
+   if (opMode == OM_UNZ) {
+      unzFailsExist = False;
+      if (srcMode == SM_I2O) {
+         uncompress ( NULL );
+      } else {
+         decode = True;
+         for (aa = argList; aa != NULL; aa = aa->link) {
+            if (ISFLAG("--")) { decode = False; continue; }
+            if (aa->name[0] == '-' && decode) continue;
+            numFilesProcessed++;
+            uncompress ( aa->name );
+         }      
+      }
+      if (unzFailsExist) { 
+         setExit(2); 
+         exit(exitValue);
+      }
+   } 
+
+   else {
+      testFailsExist = False;
+      if (srcMode == SM_I2O) {
+         testf ( NULL );
+      } else {
+         decode = True;
+         for (aa = argList; aa != NULL; aa = aa->link) {
+	    if (ISFLAG("--")) { decode = False; continue; }
+            if (aa->name[0] == '-' && decode) continue;
+            numFilesProcessed++;
+            testf ( aa->name );
+	 }
+      }
+      if (testFailsExist && noisy) {
+         fprintf ( stderr,
+           "\n"
+           "You can use the `bzip2recover' program to attempt to recover\n"
+           "data from undamaged sections of corrupted files.\n\n"
+         );
+         setExit(2);
+         exit(exitValue);
+      }
+   }
+
+   /* Free the argument list memory to mollify leak detectors 
+      (eg) Purify, Checker.  Serves no other useful purpose.
+   */
+   aa = argList;
+   while (aa != NULL) {
+      Cell* aa2 = aa->link;
+      if (aa->name != NULL) free(aa->name);
+      free(aa);
+      aa = aa2;
+   }
+
+   return exitValue;
+}
+
+
+/*-----------------------------------------------------------*/
+/*--- end                                         bzip2.c ---*/
+/*-----------------------------------------------------------*/
Index: /trunk/minix/commands/bzip2-1.0.3/bzip2.txt
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bzip2.txt	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bzip2.txt	(revision 9)
@@ -0,0 +1,391 @@
+
+NAME
+       bzip2, bunzip2 - a block-sorting file compressor, v1.0.3
+       bzcat - decompresses files to stdout
+       bzip2recover - recovers data from damaged bzip2 files
+
+
+SYNOPSIS
+       bzip2 [ -cdfkqstvzVL123456789 ] [ filenames ...  ]
+       bunzip2 [ -fkvsVL ] [ filenames ...  ]
+       bzcat [ -s ] [ filenames ...  ]
+       bzip2recover filename
+
+
+DESCRIPTION
+       bzip2  compresses  files  using  the Burrows-Wheeler block
+       sorting text compression algorithm,  and  Huffman  coding.
+       Compression  is  generally  considerably  better than that
+       achieved by more conventional LZ77/LZ78-based compressors,
+       and  approaches  the performance of the PPM family of sta-
+       tistical compressors.
+
+       The command-line options are deliberately very similar  to
+       those of GNU gzip, but they are not identical.
+
+       bzip2  expects  a list of file names to accompany the com-
+       mand-line flags.  Each file is replaced  by  a  compressed
+       version  of  itself,  with  the  name "original_name.bz2".
+       Each compressed file has the same modification date,  per-
+       missions, and, when possible, ownership as the correspond-
+       ing original, so that these properties  can  be  correctly
+       restored  at  decompression  time.   File name handling is
+       naive in the sense that there is no mechanism for preserv-
+       ing  original file names, permissions, ownerships or dates
+       in filesystems which lack these concepts, or have  serious
+       file name length restrictions, such as MS-DOS.
+
+       bzip2  and  bunzip2 will by default not overwrite existing
+       files.  If you want this to happen, specify the -f flag.
+
+       If no file names  are  specified,  bzip2  compresses  from
+       standard  input  to  standard output.  In this case, bzip2
+       will decline to write compressed output to a terminal,  as
+       this  would  be  entirely  incomprehensible  and therefore
+       pointless.
+
+       bunzip2 (or bzip2 -d) decompresses  all  specified  files.
+       Files which were not created by bzip2 will be detected and
+       ignored, and a warning issued.  bzip2  attempts  to  guess
+       the  filename  for  the decompressed file from that of the
+       compressed file as follows:
+
+              filename.bz2    becomes   filename
+              filename.bz     becomes   filename
+              filename.tbz2   becomes   filename.tar
+              filename.tbz    becomes   filename.tar
+              anyothername    becomes   anyothername.out
+
+       If the file does not end in one of the recognised endings,
+       .bz2,  .bz,  .tbz2 or .tbz, bzip2 complains that it cannot
+       guess the name of the original file, and uses the original
+       name with .out appended.
+
+       As  with compression, supplying no filenames causes decom-
+       pression from standard input to standard output.
+
+       bunzip2 will correctly decompress a file which is the con-
+       catenation of two or more compressed files.  The result is
+       the concatenation of the corresponding uncompressed files.
+       Integrity testing (-t) of concatenated compressed files is
+       also supported.
+
+       You can also compress or decompress files to the  standard
+       output  by giving the -c flag.  Multiple files may be com-
+       pressed and decompressed like this.  The resulting outputs
+       are  fed  sequentially to stdout.  Compression of multiple
+       files in this manner generates a stream containing  multi-
+       ple compressed file representations.  Such a stream can be
+       decompressed correctly only  by  bzip2  version  0.9.0  or
+       later.   Earlier  versions of bzip2 will stop after decom-
+       pressing the first file in the stream.
+
+       bzcat (or bzip2 -dc) decompresses all specified  files  to
+       the standard output.
+
+       bzip2  will  read arguments from the environment variables
+       BZIP2 and BZIP, in  that  order,  and  will  process  them
+       before  any  arguments  read  from the command line.  This
+       gives a convenient way to supply default arguments.
+
+       Compression is always performed, even  if  the  compressed
+       file  is slightly larger than the original.  Files of less
+       than about one hundred bytes tend to get larger, since the
+       compression  mechanism  has  a  constant  overhead  in the
+       region of 50 bytes.  Random data (including the output  of
+       most  file  compressors)  is  coded at about 8.05 bits per
+       byte, giving an expansion of around 0.5%.
+
+       As a self-check for your  protection,  bzip2  uses  32-bit
+       CRCs  to make sure that the decompressed version of a file
+       is identical to the original.  This guards against corrup-
+       tion  of  the compressed data, and against undetected bugs
+       in bzip2 (hopefully very unlikely).  The chances  of  data
+       corruption  going  undetected  is  microscopic,  about one
+       chance in four billion for each file processed.  Be aware,
+       though,  that  the  check occurs upon decompression, so it
+       can only tell you that something is wrong.  It can't  help
+       you  recover  the original uncompressed data.  You can use
+       bzip2recover to try to recover data from damaged files.
+
+       Return values: 0 for a normal exit,  1  for  environmental
+       problems  (file not found, invalid flags, I/O errors, &c),
+       2 to indicate a corrupt compressed file, 3 for an internal
+       consistency error (eg, bug) which caused bzip2 to panic.
+
+
+OPTIONS
+       -c --stdout
+              Compress or decompress to standard output.
+
+       -d --decompress
+              Force  decompression.  bzip2, bunzip2 and bzcat are
+              really the same program,  and  the  decision  about
+              what  actions to take is done on the basis of which
+              name is used.  This flag overrides that  mechanism,
+              and forces bzip2 to decompress.
+
+       -z --compress
+              The   complement   to   -d:   forces   compression,
+              regardless of the invocation name.
+
+       -t --test
+              Check integrity of the specified file(s), but don't
+              decompress  them.   This  really  performs  a trial
+              decompression and throws away the result.
+
+       -f --force
+              Force overwrite of output files.   Normally,  bzip2
+              will  not  overwrite  existing  output files.  Also
+              forces bzip2 to break hard links to files, which it
+              otherwise wouldn't do.
+
+              bzip2  normally  declines to decompress files which
+              don't have the  correct  magic  header  bytes.   If
+              forced  (-f),  however,  it  will  pass  such files
+              through unmodified.  This is how GNU gzip  behaves.
+
+       -k --keep
+              Keep  (don't delete) input files during compression
+              or decompression.
+
+       -s --small
+              Reduce memory usage, for compression, decompression
+              and  testing.   Files  are  decompressed and tested
+              using a modified algorithm which only requires  2.5
+              bytes  per  block byte.  This means any file can be
+              decompressed in 2300k of memory,  albeit  at  about
+              half the normal speed.
+
+              During  compression,  -s  selects  a  block size of
+              200k, which limits memory use to  around  the  same
+              figure,  at  the expense of your compression ratio.
+              In short, if your  machine  is  low  on  memory  (8
+              megabytes  or  less),  use  -s for everything.  See
+              MEMORY MANAGEMENT below.
+
+       -q --quiet
+              Suppress non-essential warning messages.   Messages
+              pertaining  to I/O errors and other critical events
+              will not be suppressed.
+
+       -v --verbose
+              Verbose mode -- show the compression ratio for each
+              file  processed.   Further  -v's  increase the ver-
+              bosity level, spewing out lots of information which
+              is primarily of interest for diagnostic purposes.
+
+       -L --license -V --version
+              Display  the  software  version,  license terms and
+              conditions.
+
+       -1 (or --fast) to -9 (or --best)
+              Set the block size to 100 k, 200 k ..  900  k  when
+              compressing.   Has  no  effect  when decompressing.
+              See MEMORY MANAGEMENT below.  The --fast and --best
+              aliases  are  primarily for GNU gzip compatibility.
+              In particular, --fast doesn't make things  signifi-
+              cantly  faster.   And  --best  merely  selects  the
+              default behaviour.
+
+       --     Treats all subsequent arguments as file names, even
+              if they start with a dash.  This is so you can han-
+              dle files with names beginning  with  a  dash,  for
+              example: bzip2 -- -myfilename.
+
+       --repetitive-fast --repetitive-best
+              These  flags  are  redundant  in versions 0.9.5 and
+              above.  They provided some coarse control over  the
+              behaviour  of the sorting algorithm in earlier ver-
+              sions, which was sometimes useful.  0.9.5 and above
+              have  an  improved  algorithm  which  renders these
+              flags irrelevant.
+
+
+MEMORY MANAGEMENT
+       bzip2 compresses large files in blocks.   The  block  size
+       affects  both  the  compression  ratio  achieved,  and the
+       amount of memory needed for compression and decompression.
+       The  flags  -1  through  -9  specify  the block size to be
+       100,000 bytes through 900,000 bytes (the default)  respec-
+       tively.   At  decompression  time, the block size used for
+       compression is read from  the  header  of  the  compressed
+       file, and bunzip2 then allocates itself just enough memory
+       to decompress the file.  Since block sizes are  stored  in
+       compressed  files,  it follows that the flags -1 to -9 are
+       irrelevant to and so ignored during decompression.
+
+       Compression and decompression requirements, in bytes,  can
+       be estimated as:
+
+              Compression:   400k + ( 8 x block size )
+
+              Decompression: 100k + ( 4 x block size ), or
+                             100k + ( 2.5 x block size )
+
+       Larger  block  sizes  give  rapidly  diminishing  marginal
+       returns.  Most of the compression comes from the first two
+       or  three hundred k of block size, a fact worth bearing in
+       mind when using bzip2  on  small  machines.   It  is  also
+       important  to  appreciate  that  the  decompression memory
+       requirement is set at compression time by  the  choice  of
+       block size.
+
+       For  files  compressed  with  the default 900k block size,
+       bunzip2 will require about 3700 kbytes to decompress.   To
+       support decompression of any file on a 4 megabyte machine,
+       bunzip2 has an option to  decompress  using  approximately
+       half this amount of memory, about 2300 kbytes.  Decompres-
+       sion speed is also halved, so you should use  this  option
+       only where necessary.  The relevant flag is -s.
+
+       In general, try and use the largest block size memory con-
+       straints  allow,  since  that  maximises  the  compression
+       achieved.   Compression and decompression speed are virtu-
+       ally unaffected by block size.
+
+       Another significant point applies to files which fit in  a
+       single  block  --  that  means  most files you'd encounter
+       using a large block  size.   The  amount  of  real  memory
+       touched is proportional to the size of the file, since the
+       file is smaller than a block.  For example, compressing  a
+       file  20,000  bytes  long  with the flag -9 will cause the
+       compressor to allocate around 7600k of  memory,  but  only
+       touch 400k + 20000 * 8 = 560 kbytes of it.  Similarly, the
+       decompressor will allocate 3700k but  only  touch  100k  +
+       20000 * 4 = 180 kbytes.
+
+       Here  is a table which summarises the maximum memory usage
+       for different block sizes.  Also  recorded  is  the  total
+       compressed  size for 14 files of the Calgary Text Compres-
+       sion Corpus totalling 3,141,622 bytes.  This column  gives
+       some  feel  for  how  compression  varies with block size.
+       These figures tend to understate the advantage  of  larger
+       block  sizes  for  larger files, since the Corpus is domi-
+       nated by smaller files.
+
+                  Compress   Decompress   Decompress   Corpus
+           Flag     usage      usage       -s usage     Size
+
+            -1      1200k       500k         350k      914704
+            -2      2000k       900k         600k      877703
+            -3      2800k      1300k         850k      860338
+            -4      3600k      1700k        1100k      846899
+            -5      4400k      2100k        1350k      845160
+            -6      5200k      2500k        1600k      838626
+            -7      6100k      2900k        1850k      834096
+            -8      6800k      3300k        2100k      828642
+            -9      7600k      3700k        2350k      828642
+
+
+RECOVERING DATA FROM DAMAGED FILES
+       bzip2 compresses files in blocks, usually 900kbytes  long.
+       Each block is handled independently.  If a media or trans-
+       mission error causes a multi-block  .bz2  file  to  become
+       damaged,  it  may  be  possible  to  recover data from the
+       undamaged blocks in the file.
+
+       The compressed representation of each block  is  delimited
+       by  a  48-bit pattern, which makes it possible to find the
+       block boundaries with reasonable  certainty.   Each  block
+       also  carries its own 32-bit CRC, so damaged blocks can be
+       distinguished from undamaged ones.
+
+       bzip2recover is a  simple  program  whose  purpose  is  to
+       search  for blocks in .bz2 files, and write each block out
+       into its own .bz2 file.  You can then use bzip2 -t to test
+       the integrity of the resulting files, and decompress those
+       which are undamaged.
+
+       bzip2recover takes a single argument, the name of the dam-
+       aged    file,    and    writes    a    number   of   files
+       "rec00001file.bz2",  "rec00002file.bz2",  etc,  containing
+       the   extracted   blocks.   The   output   filenames   are
+       designed  so  that the use of wildcards in subsequent pro-
+       cessing  -- for example, "bzip2 -dc  rec*file.bz2 > recov-
+       ered_data" -- processes the files in the correct order.
+
+       bzip2recover should be of most use dealing with large .bz2
+       files,  as  these will contain many blocks.  It is clearly
+       futile to use it on damaged single-block  files,  since  a
+       damaged  block  cannot  be recovered.  If you wish to min-
+       imise any potential data loss through media  or  transmis-
+       sion errors, you might consider compressing with a smaller
+       block size.
+
+
+PERFORMANCE NOTES
+       The sorting phase of compression gathers together  similar
+       strings  in  the  file.  Because of this, files containing
+       very long runs of  repeated  symbols,  like  "aabaabaabaab
+       ..."   (repeated  several hundred times) may compress more
+       slowly than normal.  Versions 0.9.5 and  above  fare  much
+       better  than previous versions in this respect.  The ratio
+       between worst-case and average-case compression time is in
+       the  region  of  10:1.  For previous versions, this figure
+       was more like 100:1.  You can use the -vvvv option to mon-
+       itor progress in great detail, if you want.
+
+       Decompression speed is unaffected by these phenomena.
+
+       bzip2  usually  allocates  several  megabytes of memory to
+       operate in, and then charges all over it in a fairly  ran-
+       dom  fashion.   This means that performance, both for com-
+       pressing and decompressing, is largely determined  by  the
+       speed  at  which  your  machine  can service cache misses.
+       Because of this, small changes to the code to  reduce  the
+       miss  rate  have  been observed to give disproportionately
+       large performance improvements.  I imagine bzip2 will per-
+       form best on machines with very large caches.
+
+
+CAVEATS
+       I/O  error  messages  are not as helpful as they could be.
+       bzip2 tries hard to detect I/O errors  and  exit  cleanly,
+       but  the  details  of  what  the problem is sometimes seem
+       rather misleading.
+
+       This manual page pertains to version 1.0.3 of bzip2.  Com-
+       pressed  data created by this version is entirely forwards
+       and  backwards  compatible  with   the   previous   public
+       releases,  versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1 and
+       1.0.2, but with the following exception: 0.9.0  and  above
+       can  correctly decompress multiple concatenated compressed
+       files.  0.1pl2 cannot do this; it will stop  after  decom-
+       pressing just the first file in the stream.
+
+       bzip2recover  versions prior to 1.0.2 used 32-bit integers
+       to represent bit positions in compressed  files,  so  they
+       could  not handle compressed files more than 512 megabytes
+       long.  Versions 1.0.2 and above use 64-bit  ints  on  some
+       platforms  which  support them (GNU supported targets, and
+       Windows).  To establish whether or  not  bzip2recover  was
+       built  with  such  a limitation, run it without arguments.
+       In any event you can build yourself an  unlimited  version
+       if  you  can  recompile  it  with MaybeUInt64 set to be an
+       unsigned 64-bit integer.
+
+
+AUTHOR
+       Julian Seward, jsewardbzip.org.
+
+       http://www.bzip.org
+
+       The ideas embodied in bzip2 are due to (at least) the fol-
+       lowing  people: Michael Burrows and David Wheeler (for the
+       block sorting transformation), David Wheeler  (again,  for
+       the Huffman coder), Peter Fenwick (for the structured cod-
+       ing model in the original bzip, and many refinements), and
+       Alistair  Moffat,  Radford  Neal  and  Ian Witten (for the
+       arithmetic  coder  in  the  original  bzip).   I  am  much
+       indebted for their help, support and advice.  See the man-
+       ual in the source distribution for pointers to sources  of
+       documentation.  Christian von Roques encouraged me to look
+       for faster sorting algorithms, so as to speed up  compres-
+       sion.  Bela Lubkin encouraged me to improve the worst-case
+       compression performance.  Donna Robinson XMLised the docu-
+       mentation.   The bz* scripts are derived from those of GNU
+       gzip.  Many people sent patches, helped  with  portability
+       problems,  lent  machines,  gave advice and were generally
+       helpful.
+
Index: /trunk/minix/commands/bzip2-1.0.3/bzip2recover.c
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bzip2recover.c	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bzip2recover.c	(revision 9)
@@ -0,0 +1,546 @@
+
+/*-----------------------------------------------------------*/
+/*--- Block recoverer program for bzip2                   ---*/
+/*---                                      bzip2recover.c ---*/
+/*-----------------------------------------------------------*/
+
+/*--
+  This program is bzip2recover, a program to attempt data 
+  salvage from damaged files created by the accompanying
+  bzip2-1.0.3 program.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0.3 of 15 February 2005
+--*/
+
+/*--
+  This program is a complete hack and should be rewritten
+  properly.  It isn't very complicated.
+--*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* This program records bit locations in the file to be recovered.
+   That means that if 64-bit ints are not supported, we will not
+   be able to recover .bz2 files over 512MB (2^32 bits) long.
+   On GNU supported platforms, we take advantage of the 64-bit
+   int support to circumvent this problem.  Ditto MSVC.
+
+   This change occurred in version 1.0.2; all prior versions have
+   the 512MB limitation.
+*/
+#ifdef __GNUC__
+   typedef  unsigned long long int  MaybeUInt64;
+#  define MaybeUInt64_FMT "%Lu"
+#else
+#ifdef _MSC_VER
+   typedef  unsigned __int64  MaybeUInt64;
+#  define MaybeUInt64_FMT "%I64u"
+#else
+   typedef  unsigned int   MaybeUInt64;
+#  define MaybeUInt64_FMT "%u"
+#endif
+#endif
+
+typedef  unsigned int   UInt32;
+typedef  int            Int32;
+typedef  unsigned char  UChar;
+typedef  char           Char;
+typedef  unsigned char  Bool;
+#define True    ((Bool)1)
+#define False   ((Bool)0)
+
+
+#define BZ_MAX_FILENAME 2000
+
+Char inFileName[BZ_MAX_FILENAME];
+Char outFileName[BZ_MAX_FILENAME];
+Char progName[BZ_MAX_FILENAME];
+
+MaybeUInt64 bytesOut = 0;
+MaybeUInt64 bytesIn  = 0;
+
+
+/*---------------------------------------------------*/
+/*--- Header bytes                                ---*/
+/*---------------------------------------------------*/
+
+#define BZ_HDR_B 0x42                         /* 'B' */
+#define BZ_HDR_Z 0x5a                         /* 'Z' */
+#define BZ_HDR_h 0x68                         /* 'h' */
+#define BZ_HDR_0 0x30                         /* '0' */
+ 
+
+/*---------------------------------------------------*/
+/*--- I/O errors                                  ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------*/
+void readError ( void )
+{
+   fprintf ( stderr,
+             "%s: I/O error reading `%s', possible reason follows.\n",
+            progName, inFileName );
+   perror ( progName );
+   fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
+             progName );
+   exit ( 1 );
+}
+
+
+/*---------------------------------------------*/
+void writeError ( void )
+{
+   fprintf ( stderr,
+             "%s: I/O error reading `%s', possible reason follows.\n",
+            progName, inFileName );
+   perror ( progName );
+   fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
+             progName );
+   exit ( 1 );
+}
+
+
+/*---------------------------------------------*/
+void mallocFail ( Int32 n )
+{
+   fprintf ( stderr,
+             "%s: malloc failed on request for %d bytes.\n",
+            progName, n );
+   fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
+             progName );
+   exit ( 1 );
+}
+
+
+/*---------------------------------------------*/
+void tooManyBlocks ( Int32 max_handled_blocks )
+{
+   fprintf ( stderr,
+             "%s: `%s' appears to contain more than %d blocks\n",
+            progName, inFileName, max_handled_blocks );
+   fprintf ( stderr,
+             "%s: and cannot be handled.  To fix, increase\n",
+             progName );
+   fprintf ( stderr, 
+             "%s: BZ_MAX_HANDLED_BLOCKS in bzip2recover.c, and recompile.\n",
+             progName );
+   exit ( 1 );
+}
+
+
+
+/*---------------------------------------------------*/
+/*--- Bit stream I/O                              ---*/
+/*---------------------------------------------------*/
+
+typedef
+   struct {
+      FILE*  handle;
+      Int32  buffer;
+      Int32  buffLive;
+      Char   mode;
+   }
+   BitStream;
+
+
+/*---------------------------------------------*/
+BitStream* bsOpenReadStream ( FILE* stream )
+{
+   BitStream *bs = malloc ( sizeof(BitStream) );
+   if (bs == NULL) mallocFail ( sizeof(BitStream) );
+   bs->handle = stream;
+   bs->buffer = 0;
+   bs->buffLive = 0;
+   bs->mode = 'r';
+   return bs;
+}
+
+
+/*---------------------------------------------*/
+BitStream* bsOpenWriteStream ( FILE* stream )
+{
+   BitStream *bs = malloc ( sizeof(BitStream) );
+   if (bs == NULL) mallocFail ( sizeof(BitStream) );
+   bs->handle = stream;
+   bs->buffer = 0;
+   bs->buffLive = 0;
+   bs->mode = 'w';
+   return bs;
+}
+
+
+/*---------------------------------------------*/
+void bsPutBit ( BitStream* bs, Int32 bit )
+{
+   if (bs->buffLive == 8) {
+      Int32 retVal = putc ( (UChar) bs->buffer, bs->handle );
+      if (retVal == EOF) writeError();
+      bytesOut++;
+      bs->buffLive = 1;
+      bs->buffer = bit & 0x1;
+   } else {
+      bs->buffer = ( (bs->buffer << 1) | (bit & 0x1) );
+      bs->buffLive++;
+   };
+}
+
+
+/*---------------------------------------------*/
+/*--
+   Returns 0 or 1, or 2 to indicate EOF.
+--*/
+Int32 bsGetBit ( BitStream* bs )
+{
+   if (bs->buffLive > 0) {
+      bs->buffLive --;
+      return ( ((bs->buffer) >> (bs->buffLive)) & 0x1 );
+   } else {
+      Int32 retVal = getc ( bs->handle );
+      if ( retVal == EOF ) {
+         if (errno != 0) readError();
+         return 2;
+      }
+      bs->buffLive = 7;
+      bs->buffer = retVal;
+      return ( ((bs->buffer) >> 7) & 0x1 );
+   }
+}
+
+
+/*---------------------------------------------*/
+void bsClose ( BitStream* bs )
+{
+   Int32 retVal;
+
+   if ( bs->mode == 'w' ) {
+      while ( bs->buffLive < 8 ) {
+         bs->buffLive++;
+         bs->buffer <<= 1;
+      };
+      retVal = putc ( (UChar) (bs->buffer), bs->handle );
+      if (retVal == EOF) writeError();
+      bytesOut++;
+      retVal = fflush ( bs->handle );
+      if (retVal == EOF) writeError();
+   }
+   retVal = fclose ( bs->handle );
+   if (retVal == EOF) {
+      if (bs->mode == 'w') writeError(); else readError();
+   }
+   free ( bs );
+}
+
+
+/*---------------------------------------------*/
+void bsPutUChar ( BitStream* bs, UChar c )
+{
+   Int32 i;
+   for (i = 7; i >= 0; i--)
+      bsPutBit ( bs, (((UInt32) c) >> i) & 0x1 );
+}
+
+
+/*---------------------------------------------*/
+void bsPutUInt32 ( BitStream* bs, UInt32 c )
+{
+   Int32 i;
+
+   for (i = 31; i >= 0; i--)
+      bsPutBit ( bs, (c >> i) & 0x1 );
+}
+
+
+/*---------------------------------------------*/
+Bool endsInBz2 ( Char* name )
+{
+   Int32 n = strlen ( name );
+   if (n <= 4) return False;
+   return
+      (name[n-4] == '.' &&
+       name[n-3] == 'b' &&
+       name[n-2] == 'z' &&
+       name[n-1] == '2');
+}
+
+
+/*---------------------------------------------------*/
+/*---                                             ---*/
+/*---------------------------------------------------*/
+
+/* This logic isn't really right when it comes to Cygwin. */
+#ifdef _WIN32
+#  define  BZ_SPLIT_SYM  '\\'  /* path splitter on Windows platform */
+#else
+#  define  BZ_SPLIT_SYM  '/'   /* path splitter on Unix platform */
+#endif
+
+#define BLOCK_HEADER_HI  0x00003141UL
+#define BLOCK_HEADER_LO  0x59265359UL
+
+#define BLOCK_ENDMARK_HI 0x00001772UL
+#define BLOCK_ENDMARK_LO 0x45385090UL
+
+/* Increase if necessary.  However, a .bz2 file with > 50000 blocks
+   would have an uncompressed size of at least 40GB, so the chances
+   are low you'll need to up this.
+*/
+#define BZ_MAX_HANDLED_BLOCKS 50000
+
+MaybeUInt64 bStart [BZ_MAX_HANDLED_BLOCKS];
+MaybeUInt64 bEnd   [BZ_MAX_HANDLED_BLOCKS];
+MaybeUInt64 rbStart[BZ_MAX_HANDLED_BLOCKS];
+MaybeUInt64 rbEnd  [BZ_MAX_HANDLED_BLOCKS];
+
+Int32 main ( Int32 argc, Char** argv )
+{
+   FILE*       inFile;
+   FILE*       outFile;
+   BitStream*  bsIn, *bsWr;
+   Int32       b, wrBlock, currBlock, rbCtr;
+   MaybeUInt64 bitsRead;
+
+   UInt32      buffHi, buffLo, blockCRC;
+   Char*       p;
+
+   strcpy ( progName, argv[0] );
+   inFileName[0] = outFileName[0] = 0;
+
+   fprintf ( stderr, 
+             "bzip2recover 1.0.3: extracts blocks from damaged .bz2 files.\n" );
+
+   if (argc != 2) {
+      fprintf ( stderr, "%s: usage is `%s damaged_file_name'.\n",
+                        progName, progName );
+      switch (sizeof(MaybeUInt64)) {
+         case 8:
+            fprintf(stderr, 
+                    "\trestrictions on size of recovered file: None\n");
+            break;
+         case 4:
+            fprintf(stderr, 
+                    "\trestrictions on size of recovered file: 512 MB\n");
+            fprintf(stderr, 
+                    "\tto circumvent, recompile with MaybeUInt64 as an\n"
+                    "\tunsigned 64-bit int.\n");
+            break;
+         default:
+            fprintf(stderr, 
+                    "\tsizeof(MaybeUInt64) is not 4 or 8 -- "
+                    "configuration error.\n");
+            break;
+      }
+      exit(1);
+   }
+
+   if (strlen(argv[1]) >= BZ_MAX_FILENAME-20) {
+      fprintf ( stderr, 
+                "%s: supplied filename is suspiciously (>= %d chars) long.  Bye!\n",
+                progName, (int)strlen(argv[1]) );
+      exit(1);
+   }
+
+   strcpy ( inFileName, argv[1] );
+
+   inFile = fopen ( inFileName, "rb" );
+   if (inFile == NULL) {
+      fprintf ( stderr, "%s: can't read `%s'\n", progName, inFileName );
+      exit(1);
+   }
+
+   bsIn = bsOpenReadStream ( inFile );
+   fprintf ( stderr, "%s: searching for block boundaries ...\n", progName );
+
+   bitsRead = 0;
+   buffHi = buffLo = 0;
+   currBlock = 0;
+   bStart[currBlock] = 0;
+
+   rbCtr = 0;
+
+   while (True) {
+      b = bsGetBit ( bsIn );
+      bitsRead++;
+      if (b == 2) {
+         if (bitsRead >= bStart[currBlock] &&
+            (bitsRead - bStart[currBlock]) >= 40) {
+            bEnd[currBlock] = bitsRead-1;
+            if (currBlock > 0)
+               fprintf ( stderr, "   block %d runs from " MaybeUInt64_FMT 
+                                 " to " MaybeUInt64_FMT " (incomplete)\n",
+                         currBlock,  bStart[currBlock], bEnd[currBlock] );
+         } else
+            currBlock--;
+         break;
+      }
+      buffHi = (buffHi << 1) | (buffLo >> 31);
+      buffLo = (buffLo << 1) | (b & 1);
+      if ( ( (buffHi & 0x0000ffff) == BLOCK_HEADER_HI 
+             && buffLo == BLOCK_HEADER_LO)
+           || 
+           ( (buffHi & 0x0000ffff) == BLOCK_ENDMARK_HI 
+             && buffLo == BLOCK_ENDMARK_LO)
+         ) {
+         if (bitsRead > 49) {
+            bEnd[currBlock] = bitsRead-49;
+         } else {
+            bEnd[currBlock] = 0;
+         }
+         if (currBlock > 0 &&
+	     (bEnd[currBlock] - bStart[currBlock]) >= 130) {
+            fprintf ( stderr, "   block %d runs from " MaybeUInt64_FMT 
+                              " to " MaybeUInt64_FMT "\n",
+                      rbCtr+1,  bStart[currBlock], bEnd[currBlock] );
+            rbStart[rbCtr] = bStart[currBlock];
+            rbEnd[rbCtr] = bEnd[currBlock];
+            rbCtr++;
+         }
+         if (currBlock >= BZ_MAX_HANDLED_BLOCKS)
+            tooManyBlocks(BZ_MAX_HANDLED_BLOCKS);
+         currBlock++;
+
+         bStart[currBlock] = bitsRead;
+      }
+   }
+
+   bsClose ( bsIn );
+
+   /*-- identified blocks run from 1 to rbCtr inclusive. --*/
+
+   if (rbCtr < 1) {
+      fprintf ( stderr,
+                "%s: sorry, I couldn't find any block boundaries.\n",
+                progName );
+      exit(1);
+   };
+
+   fprintf ( stderr, "%s: splitting into blocks\n", progName );
+
+   inFile = fopen ( inFileName, "rb" );
+   if (inFile == NULL) {
+      fprintf ( stderr, "%s: can't open `%s'\n", progName, inFileName );
+      exit(1);
+   }
+   bsIn = bsOpenReadStream ( inFile );
+
+   /*-- placate gcc's dataflow analyser --*/
+   blockCRC = 0; bsWr = 0;
+
+   bitsRead = 0;
+   outFile = NULL;
+   wrBlock = 0;
+   while (True) {
+      b = bsGetBit(bsIn);
+      if (b == 2) break;
+      buffHi = (buffHi << 1) | (buffLo >> 31);
+      buffLo = (buffLo << 1) | (b & 1);
+      if (bitsRead == 47+rbStart[wrBlock]) 
+         blockCRC = (buffHi << 16) | (buffLo >> 16);
+
+      if (outFile != NULL && bitsRead >= rbStart[wrBlock]
+                          && bitsRead <= rbEnd[wrBlock]) {
+         bsPutBit ( bsWr, b );
+      }
+
+      bitsRead++;
+
+      if (bitsRead == rbEnd[wrBlock]+1) {
+         if (outFile != NULL) {
+            bsPutUChar ( bsWr, 0x17 ); bsPutUChar ( bsWr, 0x72 );
+            bsPutUChar ( bsWr, 0x45 ); bsPutUChar ( bsWr, 0x38 );
+            bsPutUChar ( bsWr, 0x50 ); bsPutUChar ( bsWr, 0x90 );
+            bsPutUInt32 ( bsWr, blockCRC );
+            bsClose ( bsWr );
+         }
+         if (wrBlock >= rbCtr) break;
+         wrBlock++;
+      } else
+      if (bitsRead == rbStart[wrBlock]) {
+         /* Create the output file name, correctly handling leading paths. 
+            (31.10.2001 by Sergey E. Kusikov) */
+         Char* split;
+         Int32 ofs, k;
+         for (k = 0; k < BZ_MAX_FILENAME; k++) 
+            outFileName[k] = 0;
+         strcpy (outFileName, inFileName);
+         split = strrchr (outFileName, BZ_SPLIT_SYM);
+         if (split == NULL) {
+            split = outFileName;
+         } else {
+            ++split;
+	 }
+	 /* Now split points to the start of the basename. */
+         ofs  = split - outFileName;
+         sprintf (split, "rec%5d", wrBlock+1);
+         for (p = split; *p != 0; p++) if (*p == ' ') *p = '0';
+         strcat (outFileName, inFileName + ofs);
+
+         if ( !endsInBz2(outFileName)) strcat ( outFileName, ".bz2" );
+
+         fprintf ( stderr, "   writing block %d to `%s' ...\n",
+                           wrBlock+1, outFileName );
+
+         outFile = fopen ( outFileName, "wb" );
+         if (outFile == NULL) {
+            fprintf ( stderr, "%s: can't write `%s'\n",
+                      progName, outFileName );
+            exit(1);
+         }
+         bsWr = bsOpenWriteStream ( outFile );
+         bsPutUChar ( bsWr, BZ_HDR_B );    
+         bsPutUChar ( bsWr, BZ_HDR_Z );    
+         bsPutUChar ( bsWr, BZ_HDR_h );    
+         bsPutUChar ( bsWr, BZ_HDR_0 + 9 );
+         bsPutUChar ( bsWr, 0x31 ); bsPutUChar ( bsWr, 0x41 );
+         bsPutUChar ( bsWr, 0x59 ); bsPutUChar ( bsWr, 0x26 );
+         bsPutUChar ( bsWr, 0x53 ); bsPutUChar ( bsWr, 0x59 );
+      }
+   }
+
+   fprintf ( stderr, "%s: finished\n", progName );
+   return 0;
+}
+
+
+
+/*-----------------------------------------------------------*/
+/*--- end                                  bzip2recover.c ---*/
+/*-----------------------------------------------------------*/
Index: /trunk/minix/commands/bzip2-1.0.3/bzlib.c
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bzlib.c	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bzlib.c	(revision 9)
@@ -0,0 +1,1616 @@
+
+/*-------------------------------------------------------------*/
+/*--- Library top-level functions.                          ---*/
+/*---                                               bzlib.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+/*--
+   CHANGES
+   ~~~~~~~
+   0.9.0 -- original version.
+
+   0.9.0a/b -- no changes in this file.
+
+   0.9.0c
+      * made zero-length BZ_FLUSH work correctly in bzCompress().
+      * fixed bzWrite/bzRead to ignore zero-length requests.
+      * fixed bzread to correctly handle read requests after EOF.
+      * wrong parameter order in call to bzDecompressInit in
+        bzBuffToBuffDecompress.  Fixed.
+--*/
+
+#include "bzlib_private.h"
+
+
+/*---------------------------------------------------*/
+/*--- Compression stuff                           ---*/
+/*---------------------------------------------------*/
+
+
+/*---------------------------------------------------*/
+#ifndef BZ_NO_STDIO
+void BZ2_bz__AssertH__fail ( int errcode )
+{
+   fprintf(stderr, 
+      "\n\nbzip2/libbzip2: internal error number %d.\n"
+      "This is a bug in bzip2/libbzip2, %s.\n"
+      "Please report it to me at: jseward@bzip.org.  If this happened\n"
+      "when you were using some program which uses libbzip2 as a\n"
+      "component, you should also report this bug to the author(s)\n"
+      "of that program.  Please make an effort to report this bug;\n"
+      "timely and accurate bug reports eventually lead to higher\n"
+      "quality software.  Thanks.  Julian Seward, 15 February 2005.\n\n",
+      errcode,
+      BZ2_bzlibVersion()
+   );
+
+   if (errcode == 1007) {
+   fprintf(stderr,
+      "\n*** A special note about internal error number 1007 ***\n"
+      "\n"
+      "Experience suggests that a common cause of i.e. 1007\n"
+      "is unreliable memory or other hardware.  The 1007 assertion\n"
+      "just happens to cross-check the results of huge numbers of\n"
+      "memory reads/writes, and so acts (unintendedly) as a stress\n"
+      "test of your memory system.\n"
+      "\n"
+      "I suggest the following: try compressing the file again,\n"
+      "possibly monitoring progress in detail with the -vv flag.\n"
+      "\n"
+      "* If the error cannot be reproduced, and/or happens at different\n"
+      "  points in compression, you may have a flaky memory system.\n"
+      "  Try a memory-test program.  I have used Memtest86\n"
+      "  (www.memtest86.com).  At the time of writing it is free (GPLd).\n"
+      "  Memtest86 tests memory much more thorougly than your BIOSs\n"
+      "  power-on test, and may find failures that the BIOS doesn't.\n"
+      "\n"
+      "* If the error can be repeatably reproduced, this is a bug in\n"
+      "  bzip2, and I would very much like to hear about it.  Please\n"
+      "  let me know, and, ideally, save a copy of the file causing the\n"
+      "  problem -- without which I will be unable to investigate it.\n"
+      "\n"
+   );
+   }
+
+   exit(3);
+}
+#endif
+
+
+/*---------------------------------------------------*/
+static
+int bz_config_ok ( void )
+{
+   if (sizeof(int)   != 4) return 0;
+   if (sizeof(short) != 2) return 0;
+   if (sizeof(char)  != 1) return 0;
+   return 1;
+}
+
+
+/*---------------------------------------------------*/
+static
+void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
+{
+   void* v = malloc ( items * size );
+   return v;
+}
+
+static
+void default_bzfree ( void* opaque, void* addr )
+{
+   if (addr != NULL) free ( addr );
+}
+
+
+/*---------------------------------------------------*/
+static
+void prepare_new_block ( EState* s )
+{
+   Int32 i;
+   s->nblock = 0;
+   s->numZ = 0;
+   s->state_out_pos = 0;
+   BZ_INITIALISE_CRC ( s->blockCRC );
+   for (i = 0; i < 256; i++) s->inUse[i] = False;
+   s->blockNo++;
+}
+
+
+/*---------------------------------------------------*/
+static
+void init_RL ( EState* s )
+{
+   s->state_in_ch  = 256;
+   s->state_in_len = 0;
+}
+
+
+static
+Bool isempty_RL ( EState* s )
+{
+   if (s->state_in_ch < 256 && s->state_in_len > 0)
+      return False; else
+      return True;
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzCompressInit) 
+                    ( bz_stream* strm, 
+                     int        blockSize100k,
+                     int        verbosity,
+                     int        workFactor )
+{
+   Int32   n;
+   EState* s;
+
+   if (!bz_config_ok()) return BZ_CONFIG_ERROR;
+
+   if (strm == NULL || 
+       blockSize100k < 1 || blockSize100k > 9 ||
+       workFactor < 0 || workFactor > 250)
+     return BZ_PARAM_ERROR;
+
+   if (workFactor == 0) workFactor = 30;
+   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
+   if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
+
+   s = BZALLOC( sizeof(EState) );
+   if (s == NULL) return BZ_MEM_ERROR;
+   s->strm = strm;
+
+   s->arr1 = NULL;
+   s->arr2 = NULL;
+   s->ftab = NULL;
+
+   n       = 100000 * blockSize100k;
+   s->arr1 = BZALLOC( n                  * sizeof(UInt32) );
+   s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
+   s->ftab = BZALLOC( 65537              * sizeof(UInt32) );
+
+   if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
+      if (s->arr1 != NULL) BZFREE(s->arr1);
+      if (s->arr2 != NULL) BZFREE(s->arr2);
+      if (s->ftab != NULL) BZFREE(s->ftab);
+      if (s       != NULL) BZFREE(s);
+      return BZ_MEM_ERROR;
+   }
+
+   s->blockNo           = 0;
+   s->state             = BZ_S_INPUT;
+   s->mode              = BZ_M_RUNNING;
+   s->combinedCRC       = 0;
+   s->blockSize100k     = blockSize100k;
+   s->nblockMAX         = 100000 * blockSize100k - 19;
+   s->verbosity         = verbosity;
+   s->workFactor        = workFactor;
+
+   s->block             = (UChar*)s->arr2;
+   s->mtfv              = (UInt16*)s->arr1;
+   s->zbits             = NULL;
+   s->ptr               = (UInt32*)s->arr1;
+
+   strm->state          = s;
+   strm->total_in_lo32  = 0;
+   strm->total_in_hi32  = 0;
+   strm->total_out_lo32 = 0;
+   strm->total_out_hi32 = 0;
+   init_RL ( s );
+   prepare_new_block ( s );
+   return BZ_OK;
+}
+
+
+/*---------------------------------------------------*/
+static
+void add_pair_to_block ( EState* s )
+{
+   Int32 i;
+   UChar ch = (UChar)(s->state_in_ch);
+   for (i = 0; i < s->state_in_len; i++) {
+      BZ_UPDATE_CRC( s->blockCRC, ch );
+   }
+   s->inUse[s->state_in_ch] = True;
+   switch (s->state_in_len) {
+      case 1:
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         break;
+      case 2:
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         break;
+      case 3:
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         break;
+      default:
+         s->inUse[s->state_in_len-4] = True;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = ((UChar)(s->state_in_len-4));
+         s->nblock++;
+         break;
+   }
+}
+
+
+/*---------------------------------------------------*/
+static
+void flush_RL ( EState* s )
+{
+   if (s->state_in_ch < 256) add_pair_to_block ( s );
+   init_RL ( s );
+}
+
+
+/*---------------------------------------------------*/
+#define ADD_CHAR_TO_BLOCK(zs,zchh0)               \
+{                                                 \
+   UInt32 zchh = (UInt32)(zchh0);                 \
+   /*-- fast track the common case --*/           \
+   if (zchh != zs->state_in_ch &&                 \
+       zs->state_in_len == 1) {                   \
+      UChar ch = (UChar)(zs->state_in_ch);        \
+      BZ_UPDATE_CRC( zs->blockCRC, ch );          \
+      zs->inUse[zs->state_in_ch] = True;          \
+      zs->block[zs->nblock] = (UChar)ch;          \
+      zs->nblock++;                               \
+      zs->state_in_ch = zchh;                     \
+   }                                              \
+   else                                           \
+   /*-- general, uncommon cases --*/              \
+   if (zchh != zs->state_in_ch ||                 \
+      zs->state_in_len == 255) {                  \
+      if (zs->state_in_ch < 256)                  \
+         add_pair_to_block ( zs );                \
+      zs->state_in_ch = zchh;                     \
+      zs->state_in_len = 1;                       \
+   } else {                                       \
+      zs->state_in_len++;                         \
+   }                                              \
+}
+
+
+/*---------------------------------------------------*/
+static
+Bool copy_input_until_stop ( EState* s )
+{
+   Bool progress_in = False;
+
+   if (s->mode == BZ_M_RUNNING) {
+
+      /*-- fast track the common case --*/
+      while (True) {
+         /*-- block full? --*/
+         if (s->nblock >= s->nblockMAX) break;
+         /*-- no input? --*/
+         if (s->strm->avail_in == 0) break;
+         progress_in = True;
+         ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
+         s->strm->next_in++;
+         s->strm->avail_in--;
+         s->strm->total_in_lo32++;
+         if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
+      }
+
+   } else {
+
+      /*-- general, uncommon case --*/
+      while (True) {
+         /*-- block full? --*/
+         if (s->nblock >= s->nblockMAX) break;
+         /*-- no input? --*/
+         if (s->strm->avail_in == 0) break;
+         /*-- flush/finish end? --*/
+         if (s->avail_in_expect == 0) break;
+         progress_in = True;
+         ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
+         s->strm->next_in++;
+         s->strm->avail_in--;
+         s->strm->total_in_lo32++;
+         if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
+         s->avail_in_expect--;
+      }
+   }
+   return progress_in;
+}
+
+
+/*---------------------------------------------------*/
+static
+Bool copy_output_until_stop ( EState* s )
+{
+   Bool progress_out = False;
+
+   while (True) {
+
+      /*-- no output space? --*/
+      if (s->strm->avail_out == 0) break;
+
+      /*-- block done? --*/
+      if (s->state_out_pos >= s->numZ) break;
+
+      progress_out = True;
+      *(s->strm->next_out) = s->zbits[s->state_out_pos];
+      s->state_out_pos++;
+      s->strm->avail_out--;
+      s->strm->next_out++;
+      s->strm->total_out_lo32++;
+      if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+   }
+
+   return progress_out;
+}
+
+
+/*---------------------------------------------------*/
+static
+Bool handle_compress ( bz_stream* strm )
+{
+   Bool progress_in  = False;
+   Bool progress_out = False;
+   EState* s = strm->state;
+   
+   while (True) {
+
+      if (s->state == BZ_S_OUTPUT) {
+         progress_out |= copy_output_until_stop ( s );
+         if (s->state_out_pos < s->numZ) break;
+         if (s->mode == BZ_M_FINISHING && 
+             s->avail_in_expect == 0 &&
+             isempty_RL(s)) break;
+         prepare_new_block ( s );
+         s->state = BZ_S_INPUT;
+         if (s->mode == BZ_M_FLUSHING && 
+             s->avail_in_expect == 0 &&
+             isempty_RL(s)) break;
+      }
+
+      if (s->state == BZ_S_INPUT) {
+         progress_in |= copy_input_until_stop ( s );
+         if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
+            flush_RL ( s );
+            BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
+            s->state = BZ_S_OUTPUT;
+         }
+         else
+         if (s->nblock >= s->nblockMAX) {
+            BZ2_compressBlock ( s, False );
+            s->state = BZ_S_OUTPUT;
+         }
+         else
+         if (s->strm->avail_in == 0) {
+            break;
+         }
+      }
+
+   }
+
+   return progress_in || progress_out;
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
+{
+   Bool progress;
+   EState* s;
+   if (strm == NULL) return BZ_PARAM_ERROR;
+   s = strm->state;
+   if (s == NULL) return BZ_PARAM_ERROR;
+   if (s->strm != strm) return BZ_PARAM_ERROR;
+
+   preswitch:
+   switch (s->mode) {
+
+      case BZ_M_IDLE:
+         return BZ_SEQUENCE_ERROR;
+
+      case BZ_M_RUNNING:
+         if (action == BZ_RUN) {
+            progress = handle_compress ( strm );
+            return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
+         } 
+         else
+	 if (action == BZ_FLUSH) {
+            s->avail_in_expect = strm->avail_in;
+            s->mode = BZ_M_FLUSHING;
+            goto preswitch;
+         }
+         else
+         if (action == BZ_FINISH) {
+            s->avail_in_expect = strm->avail_in;
+            s->mode = BZ_M_FINISHING;
+            goto preswitch;
+         }
+         else 
+            return BZ_PARAM_ERROR;
+
+      case BZ_M_FLUSHING:
+         if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
+         if (s->avail_in_expect != s->strm->avail_in) 
+            return BZ_SEQUENCE_ERROR;
+         progress = handle_compress ( strm );
+         if (s->avail_in_expect > 0 || !isempty_RL(s) ||
+             s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
+         s->mode = BZ_M_RUNNING;
+         return BZ_RUN_OK;
+
+      case BZ_M_FINISHING:
+         if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
+         if (s->avail_in_expect != s->strm->avail_in) 
+            return BZ_SEQUENCE_ERROR;
+         progress = handle_compress ( strm );
+         if (!progress) return BZ_SEQUENCE_ERROR;
+         if (s->avail_in_expect > 0 || !isempty_RL(s) ||
+             s->state_out_pos < s->numZ) return BZ_FINISH_OK;
+         s->mode = BZ_M_IDLE;
+         return BZ_STREAM_END;
+   }
+   return BZ_OK; /*--not reached--*/
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm )
+{
+   EState* s;
+   if (strm == NULL) return BZ_PARAM_ERROR;
+   s = strm->state;
+   if (s == NULL) return BZ_PARAM_ERROR;
+   if (s->strm != strm) return BZ_PARAM_ERROR;
+
+   if (s->arr1 != NULL) BZFREE(s->arr1);
+   if (s->arr2 != NULL) BZFREE(s->arr2);
+   if (s->ftab != NULL) BZFREE(s->ftab);
+   BZFREE(strm->state);
+
+   strm->state = NULL;   
+
+   return BZ_OK;
+}
+
+
+/*---------------------------------------------------*/
+/*--- Decompression stuff                         ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzDecompressInit) 
+                     ( bz_stream* strm, 
+                       int        verbosity,
+                       int        small )
+{
+   DState* s;
+
+   if (!bz_config_ok()) return BZ_CONFIG_ERROR;
+
+   if (strm == NULL) return BZ_PARAM_ERROR;
+   if (small != 0 && small != 1) return BZ_PARAM_ERROR;
+   if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
+
+   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
+   if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
+
+   s = BZALLOC( sizeof(DState) );
+   if (s == NULL) return BZ_MEM_ERROR;
+   s->strm                  = strm;
+   strm->state              = s;
+   s->state                 = BZ_X_MAGIC_1;
+   s->bsLive                = 0;
+   s->bsBuff                = 0;
+   s->calculatedCombinedCRC = 0;
+   strm->total_in_lo32      = 0;
+   strm->total_in_hi32      = 0;
+   strm->total_out_lo32     = 0;
+   strm->total_out_hi32     = 0;
+   s->smallDecompress       = (Bool)small;
+   s->ll4                   = NULL;
+   s->ll16                  = NULL;
+   s->tt                    = NULL;
+   s->currBlockNo           = 0;
+   s->verbosity             = verbosity;
+
+   return BZ_OK;
+}
+
+
+/*---------------------------------------------------*/
+/* Return  True iff data corruption is discovered.
+   Returns False if there is no problem.
+*/
+static
+Bool unRLE_obuf_to_output_FAST ( DState* s )
+{
+   UChar k1;
+
+   if (s->blockRandomised) {
+
+      while (True) {
+         /* try to finish existing run */
+         while (True) {
+            if (s->strm->avail_out == 0) return False;
+            if (s->state_out_len == 0) break;
+            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
+            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
+            s->state_out_len--;
+            s->strm->next_out++;
+            s->strm->avail_out--;
+            s->strm->total_out_lo32++;
+            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+         }
+
+         /* can a new run be started? */
+         if (s->nblock_used == s->save_nblock+1) return False;
+               
+         /* Only caused by corrupt data stream? */
+         if (s->nblock_used > s->save_nblock+1)
+            return True;
+   
+         s->state_out_len = 1;
+         s->state_out_ch = s->k0;
+         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 2;
+         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 3;
+         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         s->state_out_len = ((Int32)k1) + 4;
+         BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; 
+         s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
+      }
+
+   } else {
+
+      /* restore */
+      UInt32        c_calculatedBlockCRC = s->calculatedBlockCRC;
+      UChar         c_state_out_ch       = s->state_out_ch;
+      Int32         c_state_out_len      = s->state_out_len;
+      Int32         c_nblock_used        = s->nblock_used;
+      Int32         c_k0                 = s->k0;
+      UInt32*       c_tt                 = s->tt;
+      UInt32        c_tPos               = s->tPos;
+      char*         cs_next_out          = s->strm->next_out;
+      unsigned int  cs_avail_out         = s->strm->avail_out;
+      /* end restore */
+
+      UInt32       avail_out_INIT = cs_avail_out;
+      Int32        s_save_nblockPP = s->save_nblock+1;
+      unsigned int total_out_lo32_old;
+
+      while (True) {
+
+         /* try to finish existing run */
+         if (c_state_out_len > 0) {
+            while (True) {
+               if (cs_avail_out == 0) goto return_notr;
+               if (c_state_out_len == 1) break;
+               *( (UChar*)(cs_next_out) ) = c_state_out_ch;
+               BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
+               c_state_out_len--;
+               cs_next_out++;
+               cs_avail_out--;
+            }
+            s_state_out_len_eq_one:
+            {
+               if (cs_avail_out == 0) { 
+                  c_state_out_len = 1; goto return_notr;
+               };
+               *( (UChar*)(cs_next_out) ) = c_state_out_ch;
+               BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
+               cs_next_out++;
+               cs_avail_out--;
+            }
+         }   
+         /* Only caused by corrupt data stream? */
+         if (c_nblock_used > s_save_nblockPP)
+            return True;
+
+         /* can a new run be started? */
+         if (c_nblock_used == s_save_nblockPP) {
+            c_state_out_len = 0; goto return_notr;
+         };   
+         c_state_out_ch = c_k0;
+         BZ_GET_FAST_C(k1); c_nblock_used++;
+         if (k1 != c_k0) { 
+            c_k0 = k1; goto s_state_out_len_eq_one; 
+         };
+         if (c_nblock_used == s_save_nblockPP) 
+            goto s_state_out_len_eq_one;
+   
+         c_state_out_len = 2;
+         BZ_GET_FAST_C(k1); c_nblock_used++;
+         if (c_nblock_used == s_save_nblockPP) continue;
+         if (k1 != c_k0) { c_k0 = k1; continue; };
+   
+         c_state_out_len = 3;
+         BZ_GET_FAST_C(k1); c_nblock_used++;
+         if (c_nblock_used == s_save_nblockPP) continue;
+         if (k1 != c_k0) { c_k0 = k1; continue; };
+   
+         BZ_GET_FAST_C(k1); c_nblock_used++;
+         c_state_out_len = ((Int32)k1) + 4;
+         BZ_GET_FAST_C(c_k0); c_nblock_used++;
+      }
+
+      return_notr:
+      total_out_lo32_old = s->strm->total_out_lo32;
+      s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
+      if (s->strm->total_out_lo32 < total_out_lo32_old)
+         s->strm->total_out_hi32++;
+
+      /* save */
+      s->calculatedBlockCRC = c_calculatedBlockCRC;
+      s->state_out_ch       = c_state_out_ch;
+      s->state_out_len      = c_state_out_len;
+      s->nblock_used        = c_nblock_used;
+      s->k0                 = c_k0;
+      s->tt                 = c_tt;
+      s->tPos               = c_tPos;
+      s->strm->next_out     = cs_next_out;
+      s->strm->avail_out    = cs_avail_out;
+      /* end save */
+   }
+   return False;
+}
+
+
+
+/*---------------------------------------------------*/
+__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
+{
+   Int32 nb, na, mid;
+   nb = 0;
+   na = 256;
+   do {
+      mid = (nb + na) >> 1;
+      if (indx >= cftab[mid]) nb = mid; else na = mid;
+   }
+   while (na - nb != 1);
+   return nb;
+}
+
+
+/*---------------------------------------------------*/
+/* Return  True iff data corruption is discovered.
+   Returns False if there is no problem.
+*/
+static
+Bool unRLE_obuf_to_output_SMALL ( DState* s )
+{
+   UChar k1;
+
+   if (s->blockRandomised) {
+
+      while (True) {
+         /* try to finish existing run */
+         while (True) {
+            if (s->strm->avail_out == 0) return False;
+            if (s->state_out_len == 0) break;
+            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
+            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
+            s->state_out_len--;
+            s->strm->next_out++;
+            s->strm->avail_out--;
+            s->strm->total_out_lo32++;
+            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+         }
+   
+         /* can a new run be started? */
+         if (s->nblock_used == s->save_nblock+1) return False;
+
+         /* Only caused by corrupt data stream? */
+         if (s->nblock_used > s->save_nblock+1)
+            return True;
+   
+         s->state_out_len = 1;
+         s->state_out_ch = s->k0;
+         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 2;
+         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 3;
+         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         s->state_out_len = ((Int32)k1) + 4;
+         BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; 
+         s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
+      }
+
+   } else {
+
+      while (True) {
+         /* try to finish existing run */
+         while (True) {
+            if (s->strm->avail_out == 0) return False;
+            if (s->state_out_len == 0) break;
+            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
+            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
+            s->state_out_len--;
+            s->strm->next_out++;
+            s->strm->avail_out--;
+            s->strm->total_out_lo32++;
+            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+         }
+   
+         /* can a new run be started? */
+         if (s->nblock_used == s->save_nblock+1) return False;
+
+         /* Only caused by corrupt data stream? */
+         if (s->nblock_used > s->save_nblock+1)
+            return True;
+   
+         s->state_out_len = 1;
+         s->state_out_ch = s->k0;
+         BZ_GET_SMALL(k1); s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 2;
+         BZ_GET_SMALL(k1); s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 3;
+         BZ_GET_SMALL(k1); s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         BZ_GET_SMALL(k1); s->nblock_used++;
+         s->state_out_len = ((Int32)k1) + 4;
+         BZ_GET_SMALL(s->k0); s->nblock_used++;
+      }
+
+   }
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
+{
+   Bool    corrupt;
+   DState* s;
+   if (strm == NULL) return BZ_PARAM_ERROR;
+   s = strm->state;
+   if (s == NULL) return BZ_PARAM_ERROR;
+   if (s->strm != strm) return BZ_PARAM_ERROR;
+
+   while (True) {
+      if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
+      if (s->state == BZ_X_OUTPUT) {
+         if (s->smallDecompress)
+            corrupt = unRLE_obuf_to_output_SMALL ( s ); else
+            corrupt = unRLE_obuf_to_output_FAST  ( s );
+         if (corrupt) return BZ_DATA_ERROR;
+         if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
+            BZ_FINALISE_CRC ( s->calculatedBlockCRC );
+            if (s->verbosity >= 3) 
+               VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, 
+                          s->calculatedBlockCRC );
+            if (s->verbosity >= 2) VPrintf0 ( "]" );
+            if (s->calculatedBlockCRC != s->storedBlockCRC)
+               return BZ_DATA_ERROR;
+            s->calculatedCombinedCRC 
+               = (s->calculatedCombinedCRC << 1) | 
+                    (s->calculatedCombinedCRC >> 31);
+            s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
+            s->state = BZ_X_BLKHDR_1;
+         } else {
+            return BZ_OK;
+         }
+      }
+      if (s->state >= BZ_X_MAGIC_1) {
+         Int32 r = BZ2_decompress ( s );
+         if (r == BZ_STREAM_END) {
+            if (s->verbosity >= 3)
+               VPrintf2 ( "\n    combined CRCs: stored = 0x%08x, computed = 0x%08x", 
+                          s->storedCombinedCRC, s->calculatedCombinedCRC );
+            if (s->calculatedCombinedCRC != s->storedCombinedCRC)
+               return BZ_DATA_ERROR;
+            return r;
+         }
+         if (s->state != BZ_X_OUTPUT) return r;
+      }
+   }
+
+   AssertH ( 0, 6001 );
+
+   return 0;  /*NOTREACHED*/
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzDecompressEnd)  ( bz_stream *strm )
+{
+   DState* s;
+   if (strm == NULL) return BZ_PARAM_ERROR;
+   s = strm->state;
+   if (s == NULL) return BZ_PARAM_ERROR;
+   if (s->strm != strm) return BZ_PARAM_ERROR;
+
+   if (s->tt   != NULL) BZFREE(s->tt);
+   if (s->ll16 != NULL) BZFREE(s->ll16);
+   if (s->ll4  != NULL) BZFREE(s->ll4);
+
+   BZFREE(strm->state);
+   strm->state = NULL;
+
+   return BZ_OK;
+}
+
+
+#ifndef BZ_NO_STDIO
+/*---------------------------------------------------*/
+/*--- File I/O stuff                              ---*/
+/*---------------------------------------------------*/
+
+#define BZ_SETERR(eee)                    \
+{                                         \
+   if (bzerror != NULL) *bzerror = eee;   \
+   if (bzf != NULL) bzf->lastErr = eee;   \
+}
+
+typedef 
+   struct {
+      FILE*     handle;
+      Char      buf[BZ_MAX_UNUSED];
+      Int32     bufN;
+      Bool      writing;
+      bz_stream strm;
+      Int32     lastErr;
+      Bool      initialisedOk;
+   }
+   bzFile;
+
+
+/*---------------------------------------------*/
+static Bool myfeof ( FILE* f )
+{
+   Int32 c = fgetc ( f );
+   if (c == EOF) return True;
+   ungetc ( c, f );
+   return False;
+}
+
+
+/*---------------------------------------------------*/
+BZFILE* BZ_API(BZ2_bzWriteOpen) 
+                    ( int*  bzerror,      
+                      FILE* f, 
+                      int   blockSize100k, 
+                      int   verbosity,
+                      int   workFactor )
+{
+   Int32   ret;
+   bzFile* bzf = NULL;
+
+   BZ_SETERR(BZ_OK);
+
+   if (f == NULL ||
+       (blockSize100k < 1 || blockSize100k > 9) ||
+       (workFactor < 0 || workFactor > 250) ||
+       (verbosity < 0 || verbosity > 4))
+      { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
+
+   if (ferror(f))
+      { BZ_SETERR(BZ_IO_ERROR); return NULL; };
+
+   bzf = malloc ( sizeof(bzFile) );
+   if (bzf == NULL)
+      { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
+
+   BZ_SETERR(BZ_OK);
+   bzf->initialisedOk = False;
+   bzf->bufN          = 0;
+   bzf->handle        = f;
+   bzf->writing       = True;
+   bzf->strm.bzalloc  = NULL;
+   bzf->strm.bzfree   = NULL;
+   bzf->strm.opaque   = NULL;
+
+   if (workFactor == 0) workFactor = 30;
+   ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, 
+                              verbosity, workFactor );
+   if (ret != BZ_OK)
+      { BZ_SETERR(ret); free(bzf); return NULL; };
+
+   bzf->strm.avail_in = 0;
+   bzf->initialisedOk = True;
+   return bzf;   
+}
+
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzWrite)
+             ( int*    bzerror, 
+               BZFILE* b, 
+               void*   buf, 
+               int     len )
+{
+   Int32 n, n2, ret;
+   bzFile* bzf = (bzFile*)b;
+
+   BZ_SETERR(BZ_OK);
+   if (bzf == NULL || buf == NULL || len < 0)
+      { BZ_SETERR(BZ_PARAM_ERROR); return; };
+   if (!(bzf->writing))
+      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+   if (ferror(bzf->handle))
+      { BZ_SETERR(BZ_IO_ERROR); return; };
+
+   if (len == 0)
+      { BZ_SETERR(BZ_OK); return; };
+
+   bzf->strm.avail_in = len;
+   bzf->strm.next_in  = buf;
+
+   while (True) {
+      bzf->strm.avail_out = BZ_MAX_UNUSED;
+      bzf->strm.next_out = bzf->buf;
+      ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
+      if (ret != BZ_RUN_OK)
+         { BZ_SETERR(ret); return; };
+
+      if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
+         n = BZ_MAX_UNUSED - bzf->strm.avail_out;
+         n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
+                       n, bzf->handle );
+         if (n != n2 || ferror(bzf->handle))
+            { BZ_SETERR(BZ_IO_ERROR); return; };
+      }
+
+      if (bzf->strm.avail_in == 0)
+         { BZ_SETERR(BZ_OK); return; };
+   }
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzWriteClose)
+                  ( int*          bzerror, 
+                    BZFILE*       b, 
+                    int           abandon,
+                    unsigned int* nbytes_in,
+                    unsigned int* nbytes_out )
+{
+   BZ2_bzWriteClose64 ( bzerror, b, abandon, 
+                        nbytes_in, NULL, nbytes_out, NULL );
+}
+
+
+void BZ_API(BZ2_bzWriteClose64)
+                  ( int*          bzerror, 
+                    BZFILE*       b, 
+                    int           abandon,
+                    unsigned int* nbytes_in_lo32,
+                    unsigned int* nbytes_in_hi32,
+                    unsigned int* nbytes_out_lo32,
+                    unsigned int* nbytes_out_hi32 )
+{
+   Int32   n, n2, ret;
+   bzFile* bzf = (bzFile*)b;
+
+   if (bzf == NULL)
+      { BZ_SETERR(BZ_OK); return; };
+   if (!(bzf->writing))
+      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+   if (ferror(bzf->handle))
+      { BZ_SETERR(BZ_IO_ERROR); return; };
+
+   if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
+   if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
+   if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
+   if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
+
+   if ((!abandon) && bzf->lastErr == BZ_OK) {
+      while (True) {
+         bzf->strm.avail_out = BZ_MAX_UNUSED;
+         bzf->strm.next_out = bzf->buf;
+         ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
+         if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
+            { BZ_SETERR(ret); return; };
+
+         if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
+            n = BZ_MAX_UNUSED - bzf->strm.avail_out;
+            n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
+                          n, bzf->handle );
+            if (n != n2 || ferror(bzf->handle))
+               { BZ_SETERR(BZ_IO_ERROR); return; };
+         }
+
+         if (ret == BZ_STREAM_END) break;
+      }
+   }
+
+   if ( !abandon && !ferror ( bzf->handle ) ) {
+      fflush ( bzf->handle );
+      if (ferror(bzf->handle))
+         { BZ_SETERR(BZ_IO_ERROR); return; };
+   }
+
+   if (nbytes_in_lo32 != NULL)
+      *nbytes_in_lo32 = bzf->strm.total_in_lo32;
+   if (nbytes_in_hi32 != NULL)
+      *nbytes_in_hi32 = bzf->strm.total_in_hi32;
+   if (nbytes_out_lo32 != NULL)
+      *nbytes_out_lo32 = bzf->strm.total_out_lo32;
+   if (nbytes_out_hi32 != NULL)
+      *nbytes_out_hi32 = bzf->strm.total_out_hi32;
+
+   BZ_SETERR(BZ_OK);
+   BZ2_bzCompressEnd ( &(bzf->strm) );
+   free ( bzf );
+}
+
+
+/*---------------------------------------------------*/
+BZFILE* BZ_API(BZ2_bzReadOpen) 
+                   ( int*  bzerror, 
+                     FILE* f, 
+                     int   verbosity,
+                     int   small,
+                     void* unused,
+                     int   nUnused )
+{
+   bzFile* bzf = NULL;
+   int     ret;
+
+   BZ_SETERR(BZ_OK);
+
+   if (f == NULL || 
+       (small != 0 && small != 1) ||
+       (verbosity < 0 || verbosity > 4) ||
+       (unused == NULL && nUnused != 0) ||
+       (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
+      { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
+
+   if (ferror(f))
+      { BZ_SETERR(BZ_IO_ERROR); return NULL; };
+
+   bzf = malloc ( sizeof(bzFile) );
+   if (bzf == NULL) 
+      { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
+
+   BZ_SETERR(BZ_OK);
+
+   bzf->initialisedOk = False;
+   bzf->handle        = f;
+   bzf->bufN          = 0;
+   bzf->writing       = False;
+   bzf->strm.bzalloc  = NULL;
+   bzf->strm.bzfree   = NULL;
+   bzf->strm.opaque   = NULL;
+   
+   while (nUnused > 0) {
+      bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
+      unused = ((void*)( 1 + ((UChar*)(unused))  ));
+      nUnused--;
+   }
+
+   ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
+   if (ret != BZ_OK)
+      { BZ_SETERR(ret); free(bzf); return NULL; };
+
+   bzf->strm.avail_in = bzf->bufN;
+   bzf->strm.next_in  = bzf->buf;
+
+   bzf->initialisedOk = True;
+   return bzf;   
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
+{
+   bzFile* bzf = (bzFile*)b;
+
+   BZ_SETERR(BZ_OK);
+   if (bzf == NULL)
+      { BZ_SETERR(BZ_OK); return; };
+
+   if (bzf->writing)
+      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+
+   if (bzf->initialisedOk)
+      (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
+   free ( bzf );
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzRead) 
+           ( int*    bzerror, 
+             BZFILE* b, 
+             void*   buf, 
+             int     len )
+{
+   Int32   n, ret;
+   bzFile* bzf = (bzFile*)b;
+
+   BZ_SETERR(BZ_OK);
+
+   if (bzf == NULL || buf == NULL || len < 0)
+      { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
+
+   if (bzf->writing)
+      { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
+
+   if (len == 0)
+      { BZ_SETERR(BZ_OK); return 0; };
+
+   bzf->strm.avail_out = len;
+   bzf->strm.next_out = buf;
+
+   while (True) {
+
+      if (ferror(bzf->handle)) 
+         { BZ_SETERR(BZ_IO_ERROR); return 0; };
+
+      if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
+         n = fread ( bzf->buf, sizeof(UChar), 
+                     BZ_MAX_UNUSED, bzf->handle );
+         if (ferror(bzf->handle))
+            { BZ_SETERR(BZ_IO_ERROR); return 0; };
+         bzf->bufN = n;
+         bzf->strm.avail_in = bzf->bufN;
+         bzf->strm.next_in = bzf->buf;
+      }
+
+      ret = BZ2_bzDecompress ( &(bzf->strm) );
+
+      if (ret != BZ_OK && ret != BZ_STREAM_END)
+         { BZ_SETERR(ret); return 0; };
+
+      if (ret == BZ_OK && myfeof(bzf->handle) && 
+          bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
+         { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
+
+      if (ret == BZ_STREAM_END)
+         { BZ_SETERR(BZ_STREAM_END);
+           return len - bzf->strm.avail_out; };
+      if (bzf->strm.avail_out == 0)
+         { BZ_SETERR(BZ_OK); return len; };
+      
+   }
+
+   return 0; /*not reached*/
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzReadGetUnused) 
+                     ( int*    bzerror, 
+                       BZFILE* b, 
+                       void**  unused, 
+                       int*    nUnused )
+{
+   bzFile* bzf = (bzFile*)b;
+   if (bzf == NULL)
+      { BZ_SETERR(BZ_PARAM_ERROR); return; };
+   if (bzf->lastErr != BZ_STREAM_END)
+      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+   if (unused == NULL || nUnused == NULL)
+      { BZ_SETERR(BZ_PARAM_ERROR); return; };
+
+   BZ_SETERR(BZ_OK);
+   *nUnused = bzf->strm.avail_in;
+   *unused = bzf->strm.next_in;
+}
+#endif
+
+
+/*---------------------------------------------------*/
+/*--- Misc convenience stuff                      ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzBuffToBuffCompress) 
+                         ( char*         dest, 
+                           unsigned int* destLen,
+                           char*         source, 
+                           unsigned int  sourceLen,
+                           int           blockSize100k, 
+                           int           verbosity, 
+                           int           workFactor )
+{
+   bz_stream strm;
+   int ret;
+
+   if (dest == NULL || destLen == NULL || 
+       source == NULL ||
+       blockSize100k < 1 || blockSize100k > 9 ||
+       verbosity < 0 || verbosity > 4 ||
+       workFactor < 0 || workFactor > 250) 
+      return BZ_PARAM_ERROR;
+
+   if (workFactor == 0) workFactor = 30;
+   strm.bzalloc = NULL;
+   strm.bzfree = NULL;
+   strm.opaque = NULL;
+   ret = BZ2_bzCompressInit ( &strm, blockSize100k, 
+                              verbosity, workFactor );
+   if (ret != BZ_OK) return ret;
+
+   strm.next_in = source;
+   strm.next_out = dest;
+   strm.avail_in = sourceLen;
+   strm.avail_out = *destLen;
+
+   ret = BZ2_bzCompress ( &strm, BZ_FINISH );
+   if (ret == BZ_FINISH_OK) goto output_overflow;
+   if (ret != BZ_STREAM_END) goto errhandler;
+
+   /* normal termination */
+   *destLen -= strm.avail_out;   
+   BZ2_bzCompressEnd ( &strm );
+   return BZ_OK;
+
+   output_overflow:
+   BZ2_bzCompressEnd ( &strm );
+   return BZ_OUTBUFF_FULL;
+
+   errhandler:
+   BZ2_bzCompressEnd ( &strm );
+   return ret;
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzBuffToBuffDecompress) 
+                           ( char*         dest, 
+                             unsigned int* destLen,
+                             char*         source, 
+                             unsigned int  sourceLen,
+                             int           small,
+                             int           verbosity )
+{
+   bz_stream strm;
+   int ret;
+
+   if (dest == NULL || destLen == NULL || 
+       source == NULL ||
+       (small != 0 && small != 1) ||
+       verbosity < 0 || verbosity > 4) 
+          return BZ_PARAM_ERROR;
+
+   strm.bzalloc = NULL;
+   strm.bzfree = NULL;
+   strm.opaque = NULL;
+   ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
+   if (ret != BZ_OK) return ret;
+
+   strm.next_in = source;
+   strm.next_out = dest;
+   strm.avail_in = sourceLen;
+   strm.avail_out = *destLen;
+
+   ret = BZ2_bzDecompress ( &strm );
+   if (ret == BZ_OK) goto output_overflow_or_eof;
+   if (ret != BZ_STREAM_END) goto errhandler;
+
+   /* normal termination */
+   *destLen -= strm.avail_out;
+   BZ2_bzDecompressEnd ( &strm );
+   return BZ_OK;
+
+   output_overflow_or_eof:
+   if (strm.avail_out > 0) {
+      BZ2_bzDecompressEnd ( &strm );
+      return BZ_UNEXPECTED_EOF;
+   } else {
+      BZ2_bzDecompressEnd ( &strm );
+      return BZ_OUTBUFF_FULL;
+   };      
+
+   errhandler:
+   BZ2_bzDecompressEnd ( &strm );
+   return ret; 
+}
+
+
+/*---------------------------------------------------*/
+/*--
+   Code contributed by Yoshioka Tsuneo
+   (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
+   to support better zlib compatibility.
+   This code is not _officially_ part of libbzip2 (yet);
+   I haven't tested it, documented it, or considered the
+   threading-safeness of it.
+   If this code breaks, please contact both Yoshioka and me.
+--*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+/*--
+   return version like "0.9.0c".
+--*/
+const char * BZ_API(BZ2_bzlibVersion)(void)
+{
+   return BZ_VERSION;
+}
+
+
+#ifndef BZ_NO_STDIO
+/*---------------------------------------------------*/
+
+#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
+#   include <fcntl.h>
+#   include <io.h>
+#   define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
+#else
+#   define SET_BINARY_MODE(file)
+#endif
+static
+BZFILE * bzopen_or_bzdopen
+               ( const char *path,   /* no use when bzdopen */
+                 int fd,             /* no use when bzdopen */
+                 const char *mode,
+                 int open_mode)      /* bzopen: 0, bzdopen:1 */
+{
+   int    bzerr;
+   char   unused[BZ_MAX_UNUSED];
+   int    blockSize100k = 9;
+   int    writing       = 0;
+   char   mode2[10]     = "";
+   FILE   *fp           = NULL;
+   BZFILE *bzfp         = NULL;
+   int    verbosity     = 0;
+   int    workFactor    = 30;
+   int    smallMode     = 0;
+   int    nUnused       = 0; 
+
+   if (mode == NULL) return NULL;
+   while (*mode) {
+      switch (*mode) {
+      case 'r':
+         writing = 0; break;
+      case 'w':
+         writing = 1; break;
+      case 's':
+         smallMode = 1; break;
+      default:
+         if (isdigit((int)(*mode))) {
+            blockSize100k = *mode-BZ_HDR_0;
+         }
+      }
+      mode++;
+   }
+   strcat(mode2, writing ? "w" : "r" );
+   strcat(mode2,"b");   /* binary mode */
+
+   if (open_mode==0) {
+      if (path==NULL || strcmp(path,"")==0) {
+        fp = (writing ? stdout : stdin);
+        SET_BINARY_MODE(fp);
+      } else {
+        fp = fopen(path,mode2);
+      }
+   } else {
+#ifdef BZ_STRICT_ANSI
+      fp = NULL;
+#else
+      fp = fdopen(fd,mode2);
+#endif
+   }
+   if (fp == NULL) return NULL;
+
+   if (writing) {
+      /* Guard against total chaos and anarchy -- JRS */
+      if (blockSize100k < 1) blockSize100k = 1;
+      if (blockSize100k > 9) blockSize100k = 9; 
+      bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
+                             verbosity,workFactor);
+   } else {
+      bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
+                            unused,nUnused);
+   }
+   if (bzfp == NULL) {
+      if (fp != stdin && fp != stdout) fclose(fp);
+      return NULL;
+   }
+   return bzfp;
+}
+
+
+/*---------------------------------------------------*/
+/*--
+   open file for read or write.
+      ex) bzopen("file","w9")
+      case path="" or NULL => use stdin or stdout.
+--*/
+BZFILE * BZ_API(BZ2_bzopen)
+               ( const char *path,
+                 const char *mode )
+{
+   return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
+}
+
+
+/*---------------------------------------------------*/
+BZFILE * BZ_API(BZ2_bzdopen)
+               ( int fd,
+                 const char *mode )
+{
+   return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
+{
+   int bzerr, nread;
+   if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
+   nread = BZ2_bzRead(&bzerr,b,buf,len);
+   if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
+      return nread;
+   } else {
+      return -1;
+   }
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
+{
+   int bzerr;
+
+   BZ2_bzWrite(&bzerr,b,buf,len);
+   if(bzerr == BZ_OK){
+      return len;
+   }else{
+      return -1;
+   }
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzflush) (BZFILE *b)
+{
+   /* do nothing now... */
+   return 0;
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzclose) (BZFILE* b)
+{
+   int bzerr;
+   FILE *fp = ((bzFile *)b)->handle;
+   
+   if (b==NULL) {return;}
+   if(((bzFile*)b)->writing){
+      BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
+      if(bzerr != BZ_OK){
+         BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
+      }
+   }else{
+      BZ2_bzReadClose(&bzerr,b);
+   }
+   if(fp!=stdin && fp!=stdout){
+      fclose(fp);
+   }
+}
+
+
+/*---------------------------------------------------*/
+/*--
+   return last error code 
+--*/
+static char *bzerrorstrings[] = {
+       "OK"
+      ,"SEQUENCE_ERROR"
+      ,"PARAM_ERROR"
+      ,"MEM_ERROR"
+      ,"DATA_ERROR"
+      ,"DATA_ERROR_MAGIC"
+      ,"IO_ERROR"
+      ,"UNEXPECTED_EOF"
+      ,"OUTBUFF_FULL"
+      ,"CONFIG_ERROR"
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+};
+
+
+const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
+{
+   int err = ((bzFile *)b)->lastErr;
+
+   if(err>0) err = 0;
+   *errnum = err;
+   return bzerrorstrings[err*-1];
+}
+#endif
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                           bzlib.c ---*/
+/*-------------------------------------------------------------*/
Index: /trunk/minix/commands/bzip2-1.0.3/bzlib.h
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bzlib.h	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bzlib.h	(revision 9)
@@ -0,0 +1,323 @@
+
+/*-------------------------------------------------------------*/
+/*--- Public header file for the library.                   ---*/
+/*---                                               bzlib.h ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+
+#ifndef _BZLIB_H
+#define _BZLIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BZ_RUN               0
+#define BZ_FLUSH             1
+#define BZ_FINISH            2
+
+#define BZ_OK                0
+#define BZ_RUN_OK            1
+#define BZ_FLUSH_OK          2
+#define BZ_FINISH_OK         3
+#define BZ_STREAM_END        4
+#define BZ_SEQUENCE_ERROR    (-1)
+#define BZ_PARAM_ERROR       (-2)
+#define BZ_MEM_ERROR         (-3)
+#define BZ_DATA_ERROR        (-4)
+#define BZ_DATA_ERROR_MAGIC  (-5)
+#define BZ_IO_ERROR          (-6)
+#define BZ_UNEXPECTED_EOF    (-7)
+#define BZ_OUTBUFF_FULL      (-8)
+#define BZ_CONFIG_ERROR      (-9)
+
+typedef 
+   struct {
+      char *next_in;
+      unsigned int avail_in;
+      unsigned int total_in_lo32;
+      unsigned int total_in_hi32;
+
+      char *next_out;
+      unsigned int avail_out;
+      unsigned int total_out_lo32;
+      unsigned int total_out_hi32;
+
+      void *state;
+
+      void *(*bzalloc)(void *,int,int);
+      void (*bzfree)(void *,void *);
+      void *opaque;
+   } 
+   bz_stream;
+
+
+#ifndef BZ_IMPORT
+#define BZ_EXPORT
+#endif
+
+#ifndef BZ_NO_STDIO
+/* Need a definitition for FILE */
+#include <stdio.h>
+#endif
+
+#ifdef _WIN32
+#   include <windows.h>
+#   ifdef small
+      /* windows.h define small to char */
+#      undef small
+#   endif
+#   ifdef BZ_EXPORT
+#   define BZ_API(func) WINAPI func
+#   define BZ_EXTERN extern
+#   else
+   /* import windows dll dynamically */
+#   define BZ_API(func) (WINAPI * func)
+#   define BZ_EXTERN
+#   endif
+#else
+#   define BZ_API(func) func
+#   define BZ_EXTERN extern
+#endif
+
+
+/*-- Core (low-level) library functions --*/
+
+BZ_EXTERN int BZ_API(BZ2_bzCompressInit) ( 
+      bz_stream* strm, 
+      int        blockSize100k, 
+      int        verbosity, 
+      int        workFactor 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzCompress) ( 
+      bz_stream* strm, 
+      int action 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) ( 
+      bz_stream* strm 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) ( 
+      bz_stream *strm, 
+      int       verbosity, 
+      int       small
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzDecompress) ( 
+      bz_stream* strm 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) ( 
+      bz_stream *strm 
+   );
+
+
+
+/*-- High(er) level library functions --*/
+
+#ifndef BZ_NO_STDIO
+#define BZ_MAX_UNUSED 5000
+
+typedef void BZFILE;
+
+BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) ( 
+      int*  bzerror,   
+      FILE* f, 
+      int   verbosity, 
+      int   small,
+      void* unused,    
+      int   nUnused 
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzReadClose) ( 
+      int*    bzerror, 
+      BZFILE* b 
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) ( 
+      int*    bzerror, 
+      BZFILE* b, 
+      void**  unused,  
+      int*    nUnused 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzRead) ( 
+      int*    bzerror, 
+      BZFILE* b, 
+      void*   buf, 
+      int     len 
+   );
+
+BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) ( 
+      int*  bzerror,      
+      FILE* f, 
+      int   blockSize100k, 
+      int   verbosity, 
+      int   workFactor 
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzWrite) ( 
+      int*    bzerror, 
+      BZFILE* b, 
+      void*   buf, 
+      int     len 
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzWriteClose) ( 
+      int*          bzerror, 
+      BZFILE*       b, 
+      int           abandon, 
+      unsigned int* nbytes_in, 
+      unsigned int* nbytes_out 
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) ( 
+      int*          bzerror, 
+      BZFILE*       b, 
+      int           abandon, 
+      unsigned int* nbytes_in_lo32, 
+      unsigned int* nbytes_in_hi32, 
+      unsigned int* nbytes_out_lo32, 
+      unsigned int* nbytes_out_hi32
+   );
+#endif
+
+
+/*-- Utility functions --*/
+
+BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) ( 
+      char*         dest, 
+      unsigned int* destLen,
+      char*         source, 
+      unsigned int  sourceLen,
+      int           blockSize100k, 
+      int           verbosity, 
+      int           workFactor 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) ( 
+      char*         dest, 
+      unsigned int* destLen,
+      char*         source, 
+      unsigned int  sourceLen,
+      int           small, 
+      int           verbosity 
+   );
+
+
+/*--
+   Code contributed by Yoshioka Tsuneo
+   (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
+   to support better zlib compatibility.
+   This code is not _officially_ part of libbzip2 (yet);
+   I haven't tested it, documented it, or considered the
+   threading-safeness of it.
+   If this code breaks, please contact both Yoshioka and me.
+--*/
+
+BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) (
+      void
+   );
+
+#ifndef BZ_NO_STDIO
+BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) (
+      const char *path,
+      const char *mode
+   );
+
+BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) (
+      int        fd,
+      const char *mode
+   );
+         
+BZ_EXTERN int BZ_API(BZ2_bzread) (
+      BZFILE* b, 
+      void* buf, 
+      int len 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzwrite) (
+      BZFILE* b, 
+      void*   buf, 
+      int     len 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzflush) (
+      BZFILE* b
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzclose) (
+      BZFILE* b
+   );
+
+BZ_EXTERN const char * BZ_API(BZ2_bzerror) (
+      BZFILE *b, 
+      int    *errnum
+   );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/*-------------------------------------------------------------*/
+/*--- end                                           bzlib.h ---*/
+/*-------------------------------------------------------------*/
Index: /trunk/minix/commands/bzip2-1.0.3/bzlib_private.h
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bzlib_private.h	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bzlib_private.h	(revision 9)
@@ -0,0 +1,537 @@
+
+/*-------------------------------------------------------------*/
+/*--- Private header file for the library.                  ---*/
+/*---                                       bzlib_private.h ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+
+#ifndef _BZLIB_PRIVATE_H
+#define _BZLIB_PRIVATE_H
+
+#include <stdlib.h>
+
+#ifndef BZ_NO_STDIO
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#endif
+
+#include "bzlib.h"
+
+
+
+/*-- General stuff. --*/
+
+#define BZ_VERSION  "1.0.3, 15-Feb-2005"
+
+typedef char            Char;
+typedef unsigned char   Bool;
+typedef unsigned char   UChar;
+typedef int             Int32;
+typedef unsigned int    UInt32;
+typedef short           Int16;
+typedef unsigned short  UInt16;
+
+#define True  ((Bool)1)
+#define False ((Bool)0)
+
+#ifndef __GNUC__
+#define __inline__  /* */
+#endif 
+
+#ifndef BZ_NO_STDIO
+extern void BZ2_bz__AssertH__fail ( int errcode );
+#define AssertH(cond,errcode) \
+   { if (!(cond)) BZ2_bz__AssertH__fail ( errcode ); }
+#if BZ_DEBUG
+#define AssertD(cond,msg) \
+   { if (!(cond)) {       \
+      fprintf ( stderr,   \
+        "\n\nlibbzip2(debug build): internal error\n\t%s\n", msg );\
+      exit(1); \
+   }}
+#else
+#define AssertD(cond,msg) /* */
+#endif
+#define VPrintf0(zf) \
+   fprintf(stderr,zf)
+#define VPrintf1(zf,za1) \
+   fprintf(stderr,zf,za1)
+#define VPrintf2(zf,za1,za2) \
+   fprintf(stderr,zf,za1,za2)
+#define VPrintf3(zf,za1,za2,za3) \
+   fprintf(stderr,zf,za1,za2,za3)
+#define VPrintf4(zf,za1,za2,za3,za4) \
+   fprintf(stderr,zf,za1,za2,za3,za4)
+#define VPrintf5(zf,za1,za2,za3,za4,za5) \
+   fprintf(stderr,zf,za1,za2,za3,za4,za5)
+#else
+extern void bz_internal_error ( int errcode );
+#define AssertH(cond,errcode) \
+   { if (!(cond)) bz_internal_error ( errcode ); }
+#define AssertD(cond,msg) /* */
+#define VPrintf0(zf) /* */
+#define VPrintf1(zf,za1) /* */
+#define VPrintf2(zf,za1,za2) /* */
+#define VPrintf3(zf,za1,za2,za3) /* */
+#define VPrintf4(zf,za1,za2,za3,za4) /* */
+#define VPrintf5(zf,za1,za2,za3,za4,za5) /* */
+#endif
+
+
+#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque,(nnn),1)
+#define BZFREE(ppp)  (strm->bzfree)(strm->opaque,(ppp))
+
+
+/*-- Header bytes. --*/
+
+#define BZ_HDR_B 0x42   /* 'B' */
+#define BZ_HDR_Z 0x5a   /* 'Z' */
+#define BZ_HDR_h 0x68   /* 'h' */
+#define BZ_HDR_0 0x30   /* '0' */
+  
+/*-- Constants for the back end. --*/
+
+#define BZ_MAX_ALPHA_SIZE 258
+#define BZ_MAX_CODE_LEN    23
+
+#define BZ_RUNA 0
+#define BZ_RUNB 1
+
+#define BZ_N_GROUPS 6
+#define BZ_G_SIZE   50
+#define BZ_N_ITERS  4
+
+#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE))
+
+
+
+/*-- Stuff for randomising repetitive blocks. --*/
+
+extern Int32 BZ2_rNums[512];
+
+#define BZ_RAND_DECLS                          \
+   Int32 rNToGo;                               \
+   Int32 rTPos                                 \
+
+#define BZ_RAND_INIT_MASK                      \
+   s->rNToGo = 0;                              \
+   s->rTPos  = 0                               \
+
+#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0)
+
+#define BZ_RAND_UPD_MASK                       \
+   if (s->rNToGo == 0) {                       \
+      s->rNToGo = BZ2_rNums[s->rTPos];         \
+      s->rTPos++;                              \
+      if (s->rTPos == 512) s->rTPos = 0;       \
+   }                                           \
+   s->rNToGo--;
+
+
+
+/*-- Stuff for doing CRCs. --*/
+
+extern UInt32 BZ2_crc32Table[256];
+
+#define BZ_INITIALISE_CRC(crcVar)              \
+{                                              \
+   crcVar = 0xffffffffL;                       \
+}
+
+#define BZ_FINALISE_CRC(crcVar)                \
+{                                              \
+   crcVar = ~(crcVar);                         \
+}
+
+#define BZ_UPDATE_CRC(crcVar,cha)              \
+{                                              \
+   crcVar = (crcVar << 8) ^                    \
+            BZ2_crc32Table[(crcVar >> 24) ^    \
+                           ((UChar)cha)];      \
+}
+
+
+
+/*-- States and modes for compression. --*/
+
+#define BZ_M_IDLE      1
+#define BZ_M_RUNNING   2
+#define BZ_M_FLUSHING  3
+#define BZ_M_FINISHING 4
+
+#define BZ_S_OUTPUT    1
+#define BZ_S_INPUT     2
+
+#define BZ_N_RADIX 2
+#define BZ_N_QSORT 12
+#define BZ_N_SHELL 18
+#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2)
+
+
+
+
+/*-- Structure holding all the compression-side stuff. --*/
+
+typedef
+   struct {
+      /* pointer back to the struct bz_stream */
+      bz_stream* strm;
+
+      /* mode this stream is in, and whether inputting */
+      /* or outputting data */
+      Int32    mode;
+      Int32    state;
+
+      /* remembers avail_in when flush/finish requested */
+      UInt32   avail_in_expect;
+
+      /* for doing the block sorting */
+      UInt32*  arr1;
+      UInt32*  arr2;
+      UInt32*  ftab;
+      Int32    origPtr;
+
+      /* aliases for arr1 and arr2 */
+      UInt32*  ptr;
+      UChar*   block;
+      UInt16*  mtfv;
+      UChar*   zbits;
+
+      /* for deciding when to use the fallback sorting algorithm */
+      Int32    workFactor;
+
+      /* run-length-encoding of the input */
+      UInt32   state_in_ch;
+      Int32    state_in_len;
+      BZ_RAND_DECLS;
+
+      /* input and output limits and current posns */
+      Int32    nblock;
+      Int32    nblockMAX;
+      Int32    numZ;
+      Int32    state_out_pos;
+
+      /* map of bytes used in block */
+      Int32    nInUse;
+      Bool     inUse[256];
+      UChar    unseqToSeq[256];
+
+      /* the buffer for bit stream creation */
+      UInt32   bsBuff;
+      Int32    bsLive;
+
+      /* block and combined CRCs */
+      UInt32   blockCRC;
+      UInt32   combinedCRC;
+
+      /* misc administratium */
+      Int32    verbosity;
+      Int32    blockNo;
+      Int32    blockSize100k;
+
+      /* stuff for coding the MTF values */
+      Int32    nMTF;
+      Int32    mtfFreq    [BZ_MAX_ALPHA_SIZE];
+      UChar    selector   [BZ_MAX_SELECTORS];
+      UChar    selectorMtf[BZ_MAX_SELECTORS];
+
+      UChar    len     [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      Int32    code    [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      Int32    rfreq   [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      /* second dimension: only 3 needed; 4 makes index calculations faster */
+      UInt32   len_pack[BZ_MAX_ALPHA_SIZE][4];
+
+   }
+   EState;
+
+
+
+/*-- externs for compression. --*/
+
+extern void 
+BZ2_blockSort ( EState* );
+
+extern void 
+BZ2_compressBlock ( EState*, Bool );
+
+extern void 
+BZ2_bsInitWrite ( EState* );
+
+extern void 
+BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 );
+
+extern void 
+BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 );
+
+
+
+/*-- states for decompression. --*/
+
+#define BZ_X_IDLE        1
+#define BZ_X_OUTPUT      2
+
+#define BZ_X_MAGIC_1     10
+#define BZ_X_MAGIC_2     11
+#define BZ_X_MAGIC_3     12
+#define BZ_X_MAGIC_4     13
+#define BZ_X_BLKHDR_1    14
+#define BZ_X_BLKHDR_2    15
+#define BZ_X_BLKHDR_3    16
+#define BZ_X_BLKHDR_4    17
+#define BZ_X_BLKHDR_5    18
+#define BZ_X_BLKHDR_6    19
+#define BZ_X_BCRC_1      20
+#define BZ_X_BCRC_2      21
+#define BZ_X_BCRC_3      22
+#define BZ_X_BCRC_4      23
+#define BZ_X_RANDBIT     24
+#define BZ_X_ORIGPTR_1   25
+#define BZ_X_ORIGPTR_2   26
+#define BZ_X_ORIGPTR_3   27
+#define BZ_X_MAPPING_1   28
+#define BZ_X_MAPPING_2   29
+#define BZ_X_SELECTOR_1  30
+#define BZ_X_SELECTOR_2  31
+#define BZ_X_SELECTOR_3  32
+#define BZ_X_CODING_1    33
+#define BZ_X_CODING_2    34
+#define BZ_X_CODING_3    35
+#define BZ_X_MTF_1       36
+#define BZ_X_MTF_2       37
+#define BZ_X_MTF_3       38
+#define BZ_X_MTF_4       39
+#define BZ_X_MTF_5       40
+#define BZ_X_MTF_6       41
+#define BZ_X_ENDHDR_2    42
+#define BZ_X_ENDHDR_3    43
+#define BZ_X_ENDHDR_4    44
+#define BZ_X_ENDHDR_5    45
+#define BZ_X_ENDHDR_6    46
+#define BZ_X_CCRC_1      47
+#define BZ_X_CCRC_2      48
+#define BZ_X_CCRC_3      49
+#define BZ_X_CCRC_4      50
+
+
+
+/*-- Constants for the fast MTF decoder. --*/
+
+#define MTFA_SIZE 4096
+#define MTFL_SIZE 16
+
+
+
+/*-- Structure holding all the decompression-side stuff. --*/
+
+typedef
+   struct {
+      /* pointer back to the struct bz_stream */
+      bz_stream* strm;
+
+      /* state indicator for this stream */
+      Int32    state;
+
+      /* for doing the final run-length decoding */
+      UChar    state_out_ch;
+      Int32    state_out_len;
+      Bool     blockRandomised;
+      BZ_RAND_DECLS;
+
+      /* the buffer for bit stream reading */
+      UInt32   bsBuff;
+      Int32    bsLive;
+
+      /* misc administratium */
+      Int32    blockSize100k;
+      Bool     smallDecompress;
+      Int32    currBlockNo;
+      Int32    verbosity;
+
+      /* for undoing the Burrows-Wheeler transform */
+      Int32    origPtr;
+      UInt32   tPos;
+      Int32    k0;
+      Int32    unzftab[256];
+      Int32    nblock_used;
+      Int32    cftab[257];
+      Int32    cftabCopy[257];
+
+      /* for undoing the Burrows-Wheeler transform (FAST) */
+      UInt32   *tt;
+
+      /* for undoing the Burrows-Wheeler transform (SMALL) */
+      UInt16   *ll16;
+      UChar    *ll4;
+
+      /* stored and calculated CRCs */
+      UInt32   storedBlockCRC;
+      UInt32   storedCombinedCRC;
+      UInt32   calculatedBlockCRC;
+      UInt32   calculatedCombinedCRC;
+
+      /* map of bytes used in block */
+      Int32    nInUse;
+      Bool     inUse[256];
+      Bool     inUse16[16];
+      UChar    seqToUnseq[256];
+
+      /* for decoding the MTF values */
+      UChar    mtfa   [MTFA_SIZE];
+      Int32    mtfbase[256 / MTFL_SIZE];
+      UChar    selector   [BZ_MAX_SELECTORS];
+      UChar    selectorMtf[BZ_MAX_SELECTORS];
+      UChar    len  [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+
+      Int32    limit  [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      Int32    base   [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      Int32    perm   [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      Int32    minLens[BZ_N_GROUPS];
+
+      /* save area for scalars in the main decompress code */
+      Int32    save_i;
+      Int32    save_j;
+      Int32    save_t;
+      Int32    save_alphaSize;
+      Int32    save_nGroups;
+      Int32    save_nSelectors;
+      Int32    save_EOB;
+      Int32    save_groupNo;
+      Int32    save_groupPos;
+      Int32    save_nextSym;
+      Int32    save_nblockMAX;
+      Int32    save_nblock;
+      Int32    save_es;
+      Int32    save_N;
+      Int32    save_curr;
+      Int32    save_zt;
+      Int32    save_zn; 
+      Int32    save_zvec;
+      Int32    save_zj;
+      Int32    save_gSel;
+      Int32    save_gMinlen;
+      Int32*   save_gLimit;
+      Int32*   save_gBase;
+      Int32*   save_gPerm;
+
+   }
+   DState;
+
+
+
+/*-- Macros for decompression. --*/
+
+#define BZ_GET_FAST(cccc)                     \
+    s->tPos = s->tt[s->tPos];                 \
+    cccc = (UChar)(s->tPos & 0xff);           \
+    s->tPos >>= 8;
+
+#define BZ_GET_FAST_C(cccc)                   \
+    c_tPos = c_tt[c_tPos];                    \
+    cccc = (UChar)(c_tPos & 0xff);            \
+    c_tPos >>= 8;
+
+#define SET_LL4(i,n)                                          \
+   { if (((i) & 0x1) == 0)                                    \
+        s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else    \
+        s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4);  \
+   }
+
+#define GET_LL4(i)                             \
+   ((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF)
+
+#define SET_LL(i,n)                          \
+   { s->ll16[i] = (UInt16)(n & 0x0000ffff);  \
+     SET_LL4(i, n >> 16);                    \
+   }
+
+#define GET_LL(i) \
+   (((UInt32)s->ll16[i]) | (GET_LL4(i) << 16))
+
+#define BZ_GET_SMALL(cccc)                            \
+      cccc = BZ2_indexIntoF ( s->tPos, s->cftab );    \
+      s->tPos = GET_LL(s->tPos);
+
+
+/*-- externs for decompression. --*/
+
+extern Int32 
+BZ2_indexIntoF ( Int32, Int32* );
+
+extern Int32 
+BZ2_decompress ( DState* );
+
+extern void 
+BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*,
+                           Int32,  Int32, Int32 );
+
+
+#endif
+
+
+/*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/
+
+#ifdef BZ_NO_STDIO
+#ifndef NULL
+#define NULL 0
+#endif
+#endif
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                   bzlib_private.h ---*/
+/*-------------------------------------------------------------*/
Index: /trunk/minix/commands/bzip2-1.0.3/bzmore
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bzmore	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bzmore	(revision 9)
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+# Bzmore wrapped for bzip2, 
+# adapted from zmore by Philippe Troin <phil@fifi.org> for Debian GNU/Linux.
+
+PATH="/usr/bin:$PATH"; export PATH
+
+prog=`echo $0 | sed 's|.*/||'`
+case "$prog" in
+	*less)	more=less	;;
+	*)	more=more       ;;
+esac
+
+if test "`echo -n a`" = "-n a"; then
+  # looks like a SysV system:
+  n1=''; n2='\c'
+else
+  n1='-n'; n2=''
+fi
+oldtty=`stty -g 2>/dev/null`
+if stty -cbreak 2>/dev/null; then
+  cb='cbreak'; ncb='-cbreak'
+else
+  # 'stty min 1' resets eof to ^a on both SunOS and SysV!
+  cb='min 1 -icanon'; ncb='icanon eof ^d'
+fi
+if test $? -eq 0 -a -n "$oldtty"; then
+   trap 'stty $oldtty 2>/dev/null; exit' 0 2 3 5 10 13 15
+else
+   trap 'stty $ncb echo 2>/dev/null; exit' 0 2 3 5 10 13 15
+fi
+
+if test $# = 0; then
+    if test -t 0; then
+	echo usage: $prog files...
+    else
+	bzip2 -cdfq | eval $more
+    fi
+else
+    FIRST=1
+    for FILE
+    do
+	if test $FIRST -eq 0; then
+		echo $n1 "--More--(Next file: $FILE)$n2"
+		stty $cb -echo 2>/dev/null
+		ANS=`dd bs=1 count=1 2>/dev/null` 
+		stty $ncb echo 2>/dev/null
+		echo " "
+		if test "$ANS" = 'e' -o "$ANS" = 'q'; then
+			exit
+		fi
+	fi
+	if test "$ANS" != 's'; then
+		echo "------> $FILE <------"
+		bzip2 -cdfq "$FILE" | eval $more
+	fi
+	if test -t; then
+		FIRST=0
+	fi
+    done
+fi
Index: /trunk/minix/commands/bzip2-1.0.3/bzmore.1
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/bzmore.1	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/bzmore.1	(revision 9)
@@ -0,0 +1,152 @@
+.\"Shamelessly copied from zmore.1 by Philippe Troin <phil@fifi.org>
+.\"for Debian GNU/Linux
+.TH BZMORE 1
+.SH NAME
+bzmore, bzless \- file perusal filter for crt viewing of bzip2 compressed text
+.SH SYNOPSIS
+.B bzmore
+[ name ...  ]
+.br
+.B bzless
+[ name ...  ]
+.SH NOTE
+In the following description,
+.I bzless
+and
+.I less
+can be used interchangeably with
+.I bzmore
+and
+.I more.
+.SH DESCRIPTION
+.I  Bzmore
+is a filter which allows examination of compressed or plain text files
+one screenful at a time on a soft-copy terminal.
+.I bzmore
+works on files compressed with
+.I bzip2
+and also on uncompressed files.
+If a file does not exist,
+.I bzmore
+looks for a file of the same name with the addition of a .bz2 suffix.
+.PP
+.I Bzmore
+normally pauses after each screenful, printing --More--
+at the bottom of the screen.
+If the user then types a carriage return, one more line is displayed.
+If the user hits a space,
+another screenful is displayed.  Other possibilities are enumerated later.
+.PP
+.I Bzmore
+looks in the file
+.I /etc/termcap
+to determine terminal characteristics,
+and to determine the default window size.
+On a terminal capable of displaying 24 lines,
+the default window size is 22 lines.
+Other sequences which may be typed when
+.I bzmore
+pauses, and their effects, are as follows (\fIi\fP is an optional integer
+argument, defaulting to 1) :
+.PP
+.IP \fIi\|\fP<space>
+display
+.I i
+more lines, (or another screenful if no argument is given)
+.PP
+.IP ^D
+display 11 more lines (a ``scroll'').
+If
+.I i
+is given, then the scroll size is set to \fIi\|\fP.
+.PP
+.IP d
+same as ^D (control-D)
+.PP
+.IP \fIi\|\fPz
+same as typing a space except that \fIi\|\fP, if present, becomes the new
+window size.  Note that the window size reverts back to the default at the
+end of the current file.
+.PP
+.IP \fIi\|\fPs
+skip \fIi\|\fP lines and print a screenful of lines
+.PP
+.IP \fIi\|\fPf
+skip \fIi\fP screenfuls and print a screenful of lines
+.PP
+.IP "q or Q"
+quit reading the current file; go on to the next (if any)
+.PP
+.IP "e or q"
+When the prompt --More--(Next file: 
+.IR file )
+is printed, this command causes bzmore to exit.
+.PP
+.IP s
+When the prompt --More--(Next file: 
+.IR file )
+is printed, this command causes bzmore to skip the next file and continue.
+.PP 
+.IP =
+Display the current line number.
+.PP
+.IP \fIi\|\fP/expr
+search for the \fIi\|\fP-th occurrence of the regular expression \fIexpr.\fP
+If the pattern is not found,
+.I bzmore
+goes on to the next file (if any).
+Otherwise, a screenful is displayed, starting two lines before the place
+where the expression was found.
+The user's erase and kill characters may be used to edit the regular
+expression.
+Erasing back past the first column cancels the search command.
+.PP
+.IP \fIi\|\fPn
+search for the \fIi\|\fP-th occurrence of the last regular expression entered.
+.PP
+.IP !command
+invoke a shell with \fIcommand\|\fP. 
+The character `!' in "command" are replaced with the
+previous shell command.  The sequence "\\!" is replaced by "!".
+.PP
+.IP ":q or :Q"
+quit reading the current file; go on to the next (if any)
+(same as q or Q).
+.PP
+.IP .
+(dot) repeat the previous command.
+.PP
+The commands take effect immediately, i.e., it is not necessary to
+type a carriage return.
+Up to the time when the command character itself is given,
+the user may hit the line kill character to cancel the numerical
+argument being formed.
+In addition, the user may hit the erase character to redisplay the
+--More-- message.
+.PP
+At any time when output is being sent to the terminal, the user can
+hit the quit key (normally control\-\\).
+.I Bzmore
+will stop sending output, and will display the usual --More--
+prompt.
+The user may then enter one of the above commands in the normal manner.
+Unfortunately, some output is lost when this is done, due to the
+fact that any characters waiting in the terminal's output queue
+are flushed when the quit signal occurs.
+.PP
+The terminal is set to
+.I noecho
+mode by this program so that the output can be continuous.
+What you type will thus not show on your terminal, except for the / and !
+commands.
+.PP
+If the standard output is not a teletype, then
+.I bzmore
+acts just like
+.I bzcat,
+except that a header is printed before each file.
+.SH FILES
+.DT
+/etc/termcap		Terminal data base
+.SH "SEE ALSO"
+more(1), less(1), bzip2(1), bzdiff(1), bzgrep(1)
Index: /trunk/minix/commands/bzip2-1.0.3/compress.c
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/compress.c	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/compress.c	(revision 9)
@@ -0,0 +1,716 @@
+
+/*-------------------------------------------------------------*/
+/*--- Compression machinery (not incl block sorting)        ---*/
+/*---                                            compress.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+/*--
+   CHANGES
+   ~~~~~~~
+   0.9.0 -- original version.
+
+   0.9.0a/b -- no changes in this file.
+
+   0.9.0c
+      * changed setting of nGroups in sendMTFValues() so as to 
+        do a bit better on small files
+--*/
+
+#include "bzlib_private.h"
+
+
+/*---------------------------------------------------*/
+/*--- Bit stream I/O                              ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+void BZ2_bsInitWrite ( EState* s )
+{
+   s->bsLive = 0;
+   s->bsBuff = 0;
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsFinishWrite ( EState* s )
+{
+   while (s->bsLive > 0) {
+      s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
+      s->numZ++;
+      s->bsBuff <<= 8;
+      s->bsLive -= 8;
+   }
+}
+
+
+/*---------------------------------------------------*/
+#define bsNEEDW(nz)                           \
+{                                             \
+   while (s->bsLive >= 8) {                   \
+      s->zbits[s->numZ]                       \
+         = (UChar)(s->bsBuff >> 24);          \
+      s->numZ++;                              \
+      s->bsBuff <<= 8;                        \
+      s->bsLive -= 8;                         \
+   }                                          \
+}
+
+
+/*---------------------------------------------------*/
+static
+__inline__
+void bsW ( EState* s, Int32 n, UInt32 v )
+{
+   bsNEEDW ( n );
+   s->bsBuff |= (v << (32 - s->bsLive - n));
+   s->bsLive += n;
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsPutUInt32 ( EState* s, UInt32 u )
+{
+   bsW ( s, 8, (u >> 24) & 0xffL );
+   bsW ( s, 8, (u >> 16) & 0xffL );
+   bsW ( s, 8, (u >>  8) & 0xffL );
+   bsW ( s, 8,  u        & 0xffL );
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsPutUChar ( EState* s, UChar c )
+{
+   bsW( s, 8, (UInt32)c );
+}
+
+
+/*---------------------------------------------------*/
+/*--- The back end proper                         ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+static
+void makeMaps_e ( EState* s )
+{
+   Int32 i;
+   s->nInUse = 0;
+   for (i = 0; i < 256; i++)
+      if (s->inUse[i]) {
+         s->unseqToSeq[i] = s->nInUse;
+         s->nInUse++;
+      }
+}
+
+
+/*---------------------------------------------------*/
+static
+void generateMTFValues ( EState* s )
+{
+   UChar   yy[256];
+   Int32   i, j;
+   Int32   zPend;
+   Int32   wr;
+   Int32   EOB;
+
+   /* 
+      After sorting (eg, here),
+         s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
+         and
+         ((UChar*)s->arr2) [ 0 .. s->nblock-1 ] 
+         holds the original block data.
+
+      The first thing to do is generate the MTF values,
+      and put them in
+         ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
+      Because there are strictly fewer or equal MTF values
+      than block values, ptr values in this area are overwritten
+      with MTF values only when they are no longer needed.
+
+      The final compressed bitstream is generated into the
+      area starting at
+         (UChar*) (&((UChar*)s->arr2)[s->nblock])
+
+      These storage aliases are set up in bzCompressInit(),
+      except for the last one, which is arranged in 
+      compressBlock().
+   */
+   UInt32* ptr   = s->ptr;
+   UChar* block  = s->block;
+   UInt16* mtfv  = s->mtfv;
+
+   makeMaps_e ( s );
+   EOB = s->nInUse+1;
+
+   for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
+
+   wr = 0;
+   zPend = 0;
+   for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
+
+   for (i = 0; i < s->nblock; i++) {
+      UChar ll_i;
+      AssertD ( wr <= i, "generateMTFValues(1)" );
+      j = ptr[i]-1; if (j < 0) j += s->nblock;
+      ll_i = s->unseqToSeq[block[j]];
+      AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
+
+      if (yy[0] == ll_i) { 
+         zPend++;
+      } else {
+
+         if (zPend > 0) {
+            zPend--;
+            while (True) {
+               if (zPend & 1) {
+                  mtfv[wr] = BZ_RUNB; wr++; 
+                  s->mtfFreq[BZ_RUNB]++; 
+               } else {
+                  mtfv[wr] = BZ_RUNA; wr++; 
+                  s->mtfFreq[BZ_RUNA]++; 
+               }
+               if (zPend < 2) break;
+               zPend = (zPend - 2) / 2;
+            };
+            zPend = 0;
+         }
+         {
+            register UChar  rtmp;
+            register UChar* ryy_j;
+            register UChar  rll_i;
+            rtmp  = yy[1];
+            yy[1] = yy[0];
+            ryy_j = &(yy[1]);
+            rll_i = ll_i;
+            while ( rll_i != rtmp ) {
+               register UChar rtmp2;
+               ryy_j++;
+               rtmp2  = rtmp;
+               rtmp   = *ryy_j;
+               *ryy_j = rtmp2;
+            };
+            yy[0] = rtmp;
+            j = ryy_j - &(yy[0]);
+            mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++;
+         }
+
+      }
+   }
+
+   if (zPend > 0) {
+      zPend--;
+      while (True) {
+         if (zPend & 1) {
+            mtfv[wr] = BZ_RUNB; wr++; 
+            s->mtfFreq[BZ_RUNB]++; 
+         } else {
+            mtfv[wr] = BZ_RUNA; wr++; 
+            s->mtfFreq[BZ_RUNA]++; 
+         }
+         if (zPend < 2) break;
+         zPend = (zPend - 2) / 2;
+      };
+      zPend = 0;
+   }
+
+   mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
+
+   s->nMTF = wr;
+}
+
+
+/*---------------------------------------------------*/
+#define BZ_LESSER_ICOST  0
+#define BZ_GREATER_ICOST 15
+
+static
+void sendMTFValues ( EState* s )
+{
+   Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
+   Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
+   Int32 nGroups, nBytes;
+
+   /*--
+   UChar  len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+   is a global since the decoder also needs it.
+
+   Int32  code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+   Int32  rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+   are also globals only used in this proc.
+   Made global to keep stack frame size small.
+   --*/
+
+
+   UInt16 cost[BZ_N_GROUPS];
+   Int32  fave[BZ_N_GROUPS];
+
+   UInt16* mtfv = s->mtfv;
+
+   if (s->verbosity >= 3)
+      VPrintf3( "      %d in block, %d after MTF & 1-2 coding, "
+                "%d+2 syms in use\n", 
+                s->nblock, s->nMTF, s->nInUse );
+
+   alphaSize = s->nInUse+2;
+   for (t = 0; t < BZ_N_GROUPS; t++)
+      for (v = 0; v < alphaSize; v++)
+         s->len[t][v] = BZ_GREATER_ICOST;
+
+   /*--- Decide how many coding tables to use ---*/
+   AssertH ( s->nMTF > 0, 3001 );
+   if (s->nMTF < 200)  nGroups = 2; else
+   if (s->nMTF < 600)  nGroups = 3; else
+   if (s->nMTF < 1200) nGroups = 4; else
+   if (s->nMTF < 2400) nGroups = 5; else
+                       nGroups = 6;
+
+   /*--- Generate an initial set of coding tables ---*/
+   { 
+      Int32 nPart, remF, tFreq, aFreq;
+
+      nPart = nGroups;
+      remF  = s->nMTF;
+      gs = 0;
+      while (nPart > 0) {
+         tFreq = remF / nPart;
+         ge = gs-1;
+         aFreq = 0;
+         while (aFreq < tFreq && ge < alphaSize-1) {
+            ge++;
+            aFreq += s->mtfFreq[ge];
+         }
+
+         if (ge > gs 
+             && nPart != nGroups && nPart != 1 
+             && ((nGroups-nPart) % 2 == 1)) {
+            aFreq -= s->mtfFreq[ge];
+            ge--;
+         }
+
+         if (s->verbosity >= 3)
+            VPrintf5( "      initial group %d, [%d .. %d], "
+                      "has %d syms (%4.1f%%)\n",
+                      nPart, gs, ge, aFreq, 
+                      (100.0 * (float)aFreq) / (float)(s->nMTF) );
+ 
+         for (v = 0; v < alphaSize; v++)
+            if (v >= gs && v <= ge) 
+               s->len[nPart-1][v] = BZ_LESSER_ICOST; else
+               s->len[nPart-1][v] = BZ_GREATER_ICOST;
+ 
+         nPart--;
+         gs = ge+1;
+         remF -= aFreq;
+      }
+   }
+
+   /*--- 
+      Iterate up to BZ_N_ITERS times to improve the tables.
+   ---*/
+   for (iter = 0; iter < BZ_N_ITERS; iter++) {
+
+      for (t = 0; t < nGroups; t++) fave[t] = 0;
+
+      for (t = 0; t < nGroups; t++)
+         for (v = 0; v < alphaSize; v++)
+            s->rfreq[t][v] = 0;
+
+      /*---
+        Set up an auxiliary length table which is used to fast-track
+	the common case (nGroups == 6). 
+      ---*/
+      if (nGroups == 6) {
+         for (v = 0; v < alphaSize; v++) {
+            s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v];
+            s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v];
+            s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v];
+	 }
+      }
+
+      nSelectors = 0;
+      totc = 0;
+      gs = 0;
+      while (True) {
+
+         /*--- Set group start & end marks. --*/
+         if (gs >= s->nMTF) break;
+         ge = gs + BZ_G_SIZE - 1; 
+         if (ge >= s->nMTF) ge = s->nMTF-1;
+
+         /*-- 
+            Calculate the cost of this group as coded
+            by each of the coding tables.
+         --*/
+         for (t = 0; t < nGroups; t++) cost[t] = 0;
+
+         if (nGroups == 6 && 50 == ge-gs+1) {
+            /*--- fast track the common case ---*/
+            register UInt32 cost01, cost23, cost45;
+            register UInt16 icv;
+            cost01 = cost23 = cost45 = 0;
+
+#           define BZ_ITER(nn)                \
+               icv = mtfv[gs+(nn)];           \
+               cost01 += s->len_pack[icv][0]; \
+               cost23 += s->len_pack[icv][1]; \
+               cost45 += s->len_pack[icv][2]; \
+
+            BZ_ITER(0);  BZ_ITER(1);  BZ_ITER(2);  BZ_ITER(3);  BZ_ITER(4);
+            BZ_ITER(5);  BZ_ITER(6);  BZ_ITER(7);  BZ_ITER(8);  BZ_ITER(9);
+            BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
+            BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
+            BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
+            BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
+            BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
+            BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
+            BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
+            BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
+
+#           undef BZ_ITER
+
+            cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
+            cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
+            cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
+
+         } else {
+	    /*--- slow version which correctly handles all situations ---*/
+            for (i = gs; i <= ge; i++) { 
+               UInt16 icv = mtfv[i];
+               for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv];
+            }
+         }
+ 
+         /*-- 
+            Find the coding table which is best for this group,
+            and record its identity in the selector table.
+         --*/
+         bc = 999999999; bt = -1;
+         for (t = 0; t < nGroups; t++)
+            if (cost[t] < bc) { bc = cost[t]; bt = t; };
+         totc += bc;
+         fave[bt]++;
+         s->selector[nSelectors] = bt;
+         nSelectors++;
+
+         /*-- 
+            Increment the symbol frequencies for the selected table.
+          --*/
+         if (nGroups == 6 && 50 == ge-gs+1) {
+            /*--- fast track the common case ---*/
+
+#           define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++
+
+            BZ_ITUR(0);  BZ_ITUR(1);  BZ_ITUR(2);  BZ_ITUR(3);  BZ_ITUR(4);
+            BZ_ITUR(5);  BZ_ITUR(6);  BZ_ITUR(7);  BZ_ITUR(8);  BZ_ITUR(9);
+            BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
+            BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
+            BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
+            BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
+            BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
+            BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
+            BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
+            BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
+
+#           undef BZ_ITUR
+
+         } else {
+	    /*--- slow version which correctly handles all situations ---*/
+            for (i = gs; i <= ge; i++)
+               s->rfreq[bt][ mtfv[i] ]++;
+         }
+
+         gs = ge+1;
+      }
+      if (s->verbosity >= 3) {
+         VPrintf2 ( "      pass %d: size is %d, grp uses are ", 
+                   iter+1, totc/8 );
+         for (t = 0; t < nGroups; t++)
+            VPrintf1 ( "%d ", fave[t] );
+         VPrintf0 ( "\n" );
+      }
+
+      /*--
+        Recompute the tables based on the accumulated frequencies.
+      --*/
+      /* maxLen was changed from 20 to 17 in bzip2-1.0.3.  See 
+         comment in huffman.c for details. */
+      for (t = 0; t < nGroups; t++)
+         BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]), 
+                                 alphaSize, 17 /*20*/ );
+   }
+
+
+   AssertH( nGroups < 8, 3002 );
+   AssertH( nSelectors < 32768 &&
+            nSelectors <= (2 + (900000 / BZ_G_SIZE)),
+            3003 );
+
+
+   /*--- Compute MTF values for the selectors. ---*/
+   {
+      UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
+      for (i = 0; i < nGroups; i++) pos[i] = i;
+      for (i = 0; i < nSelectors; i++) {
+         ll_i = s->selector[i];
+         j = 0;
+         tmp = pos[j];
+         while ( ll_i != tmp ) {
+            j++;
+            tmp2 = tmp;
+            tmp = pos[j];
+            pos[j] = tmp2;
+         };
+         pos[0] = tmp;
+         s->selectorMtf[i] = j;
+      }
+   };
+
+   /*--- Assign actual codes for the tables. --*/
+   for (t = 0; t < nGroups; t++) {
+      minLen = 32;
+      maxLen = 0;
+      for (i = 0; i < alphaSize; i++) {
+         if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
+         if (s->len[t][i] < minLen) minLen = s->len[t][i];
+      }
+      AssertH ( !(maxLen > 17 /*20*/ ), 3004 );
+      AssertH ( !(minLen < 1),  3005 );
+      BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]), 
+                          minLen, maxLen, alphaSize );
+   }
+
+   /*--- Transmit the mapping table. ---*/
+   { 
+      Bool inUse16[16];
+      for (i = 0; i < 16; i++) {
+          inUse16[i] = False;
+          for (j = 0; j < 16; j++)
+             if (s->inUse[i * 16 + j]) inUse16[i] = True;
+      }
+     
+      nBytes = s->numZ;
+      for (i = 0; i < 16; i++)
+         if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0);
+
+      for (i = 0; i < 16; i++)
+         if (inUse16[i])
+            for (j = 0; j < 16; j++) {
+               if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0);
+            }
+
+      if (s->verbosity >= 3) 
+         VPrintf1( "      bytes: mapping %d, ", s->numZ-nBytes );
+   }
+
+   /*--- Now the selectors. ---*/
+   nBytes = s->numZ;
+   bsW ( s, 3, nGroups );
+   bsW ( s, 15, nSelectors );
+   for (i = 0; i < nSelectors; i++) { 
+      for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1);
+      bsW(s,1,0);
+   }
+   if (s->verbosity >= 3)
+      VPrintf1( "selectors %d, ", s->numZ-nBytes );
+
+   /*--- Now the coding tables. ---*/
+   nBytes = s->numZ;
+
+   for (t = 0; t < nGroups; t++) {
+      Int32 curr = s->len[t][0];
+      bsW ( s, 5, curr );
+      for (i = 0; i < alphaSize; i++) {
+         while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ };
+         while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ };
+         bsW ( s, 1, 0 );
+      }
+   }
+
+   if (s->verbosity >= 3)
+      VPrintf1 ( "code lengths %d, ", s->numZ-nBytes );
+
+   /*--- And finally, the block data proper ---*/
+   nBytes = s->numZ;
+   selCtr = 0;
+   gs = 0;
+   while (True) {
+      if (gs >= s->nMTF) break;
+      ge = gs + BZ_G_SIZE - 1; 
+      if (ge >= s->nMTF) ge = s->nMTF-1;
+      AssertH ( s->selector[selCtr] < nGroups, 3006 );
+
+      if (nGroups == 6 && 50 == ge-gs+1) {
+            /*--- fast track the common case ---*/
+            UInt16 mtfv_i;
+            UChar* s_len_sel_selCtr 
+               = &(s->len[s->selector[selCtr]][0]);
+            Int32* s_code_sel_selCtr
+               = &(s->code[s->selector[selCtr]][0]);
+
+#           define BZ_ITAH(nn)                      \
+               mtfv_i = mtfv[gs+(nn)];              \
+               bsW ( s,                             \
+                     s_len_sel_selCtr[mtfv_i],      \
+                     s_code_sel_selCtr[mtfv_i] )
+
+            BZ_ITAH(0);  BZ_ITAH(1);  BZ_ITAH(2);  BZ_ITAH(3);  BZ_ITAH(4);
+            BZ_ITAH(5);  BZ_ITAH(6);  BZ_ITAH(7);  BZ_ITAH(8);  BZ_ITAH(9);
+            BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
+            BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
+            BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
+            BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
+            BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
+            BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
+            BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
+            BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
+
+#           undef BZ_ITAH
+
+      } else {
+	 /*--- slow version which correctly handles all situations ---*/
+         for (i = gs; i <= ge; i++) {
+            bsW ( s, 
+                  s->len  [s->selector[selCtr]] [mtfv[i]],
+                  s->code [s->selector[selCtr]] [mtfv[i]] );
+         }
+      }
+
+
+      gs = ge+1;
+      selCtr++;
+   }
+   AssertH( selCtr == nSelectors, 3007 );
+
+   if (s->verbosity >= 3)
+      VPrintf1( "codes %d\n", s->numZ-nBytes );
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_compressBlock ( EState* s, Bool is_last_block )
+{
+   if (s->nblock > 0) {
+
+      BZ_FINALISE_CRC ( s->blockCRC );
+      s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
+      s->combinedCRC ^= s->blockCRC;
+      if (s->blockNo > 1) s->numZ = 0;
+
+      if (s->verbosity >= 2)
+         VPrintf4( "    block %d: crc = 0x%08x, "
+                   "combined CRC = 0x%08x, size = %d\n",
+                   s->blockNo, s->blockCRC, s->combinedCRC, s->nblock );
+
+      BZ2_blockSort ( s );
+   }
+
+   s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]);
+
+   /*-- If this is the first block, create the stream header. --*/
+   if (s->blockNo == 1) {
+      BZ2_bsInitWrite ( s );
+      bsPutUChar ( s, BZ_HDR_B );
+      bsPutUChar ( s, BZ_HDR_Z );
+      bsPutUChar ( s, BZ_HDR_h );
+      bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) );
+   }
+
+   if (s->nblock > 0) {
+
+      bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 );
+      bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 );
+      bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 );
+
+      /*-- Now the block's CRC, so it is in a known place. --*/
+      bsPutUInt32 ( s, s->blockCRC );
+
+      /*-- 
+         Now a single bit indicating (non-)randomisation. 
+         As of version 0.9.5, we use a better sorting algorithm
+         which makes randomisation unnecessary.  So always set
+         the randomised bit to 'no'.  Of course, the decoder
+         still needs to be able to handle randomised blocks
+         so as to maintain backwards compatibility with
+         older versions of bzip2.
+      --*/
+      bsW(s,1,0);
+
+      bsW ( s, 24, s->origPtr );
+      generateMTFValues ( s );
+      sendMTFValues ( s );
+   }
+
+
+   /*-- If this is the last block, add the stream trailer. --*/
+   if (is_last_block) {
+
+      bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 );
+      bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 );
+      bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 );
+      bsPutUInt32 ( s, s->combinedCRC );
+      if (s->verbosity >= 2)
+         VPrintf1( "    final combined CRC = 0x%08x\n   ", s->combinedCRC );
+      bsFinishWrite ( s );
+   }
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                        compress.c ---*/
+/*-------------------------------------------------------------*/
Index: /trunk/minix/commands/bzip2-1.0.3/crctable.c
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/crctable.c	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/crctable.c	(revision 9)
@@ -0,0 +1,144 @@
+
+/*-------------------------------------------------------------*/
+/*--- Table for doing CRCs                                  ---*/
+/*---                                            crctable.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+
+#include "bzlib_private.h"
+
+/*--
+  I think this is an implementation of the AUTODIN-II,
+  Ethernet & FDDI 32-bit CRC standard.  Vaguely derived
+  from code by Rob Warnock, in Section 51 of the
+  comp.compression FAQ.
+--*/
+
+UInt32 BZ2_crc32Table[256] = {
+
+   /*-- Ugly, innit? --*/
+
+   0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L,
+   0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L,
+   0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L,
+   0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL,
+   0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L,
+   0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L,
+   0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L,
+   0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL,
+   0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L,
+   0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L,
+   0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L,
+   0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL,
+   0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L,
+   0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L,
+   0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L,
+   0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL,
+   0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL,
+   0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L,
+   0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L,
+   0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL,
+   0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL,
+   0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L,
+   0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L,
+   0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL,
+   0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL,
+   0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L,
+   0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L,
+   0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL,
+   0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL,
+   0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L,
+   0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L,
+   0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL,
+   0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L,
+   0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL,
+   0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL,
+   0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L,
+   0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L,
+   0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL,
+   0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL,
+   0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L,
+   0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L,
+   0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL,
+   0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL,
+   0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L,
+   0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L,
+   0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL,
+   0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL,
+   0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L,
+   0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L,
+   0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL,
+   0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L,
+   0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L,
+   0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L,
+   0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL,
+   0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L,
+   0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L,
+   0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L,
+   0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL,
+   0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L,
+   0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L,
+   0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L,
+   0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL,
+   0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L,
+   0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L
+};
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                        crctable.c ---*/
+/*-------------------------------------------------------------*/
Index: /trunk/minix/commands/bzip2-1.0.3/decompress.c
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/decompress.c	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/decompress.c	(revision 9)
@@ -0,0 +1,666 @@
+
+/*-------------------------------------------------------------*/
+/*--- Decompression machinery                               ---*/
+/*---                                          decompress.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+
+#include "bzlib_private.h"
+
+
+/*---------------------------------------------------*/
+static
+void makeMaps_d ( DState* s )
+{
+   Int32 i;
+   s->nInUse = 0;
+   for (i = 0; i < 256; i++)
+      if (s->inUse[i]) {
+         s->seqToUnseq[s->nInUse] = i;
+         s->nInUse++;
+      }
+}
+
+
+/*---------------------------------------------------*/
+#define RETURN(rrr)                               \
+   { retVal = rrr; goto save_state_and_return; };
+
+#define GET_BITS(lll,vvv,nnn)                     \
+   case lll: s->state = lll;                      \
+   while (True) {                                 \
+      if (s->bsLive >= nnn) {                     \
+         UInt32 v;                                \
+         v = (s->bsBuff >>                        \
+             (s->bsLive-nnn)) & ((1 << nnn)-1);   \
+         s->bsLive -= nnn;                        \
+         vvv = v;                                 \
+         break;                                   \
+      }                                           \
+      if (s->strm->avail_in == 0) RETURN(BZ_OK);  \
+      s->bsBuff                                   \
+         = (s->bsBuff << 8) |                     \
+           ((UInt32)                              \
+              (*((UChar*)(s->strm->next_in))));   \
+      s->bsLive += 8;                             \
+      s->strm->next_in++;                         \
+      s->strm->avail_in--;                        \
+      s->strm->total_in_lo32++;                   \
+      if (s->strm->total_in_lo32 == 0)            \
+         s->strm->total_in_hi32++;                \
+   }
+
+#define GET_UCHAR(lll,uuu)                        \
+   GET_BITS(lll,uuu,8)
+
+#define GET_BIT(lll,uuu)                          \
+   GET_BITS(lll,uuu,1)
+
+/*---------------------------------------------------*/
+#define GET_MTF_VAL(label1,label2,lval)           \
+{                                                 \
+   if (groupPos == 0) {                           \
+      groupNo++;                                  \
+      if (groupNo >= nSelectors)                  \
+         RETURN(BZ_DATA_ERROR);                   \
+      groupPos = BZ_G_SIZE;                       \
+      gSel = s->selector[groupNo];                \
+      gMinlen = s->minLens[gSel];                 \
+      gLimit = &(s->limit[gSel][0]);              \
+      gPerm = &(s->perm[gSel][0]);                \
+      gBase = &(s->base[gSel][0]);                \
+   }                                              \
+   groupPos--;                                    \
+   zn = gMinlen;                                  \
+   GET_BITS(label1, zvec, zn);                    \
+   while (1) {                                    \
+      if (zn > 20 /* the longest code */)         \
+         RETURN(BZ_DATA_ERROR);                   \
+      if (zvec <= gLimit[zn]) break;              \
+      zn++;                                       \
+      GET_BIT(label2, zj);                        \
+      zvec = (zvec << 1) | zj;                    \
+   };                                             \
+   if (zvec - gBase[zn] < 0                       \
+       || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE)  \
+      RETURN(BZ_DATA_ERROR);                      \
+   lval = gPerm[zvec - gBase[zn]];                \
+}
+
+
+/*---------------------------------------------------*/
+Int32 BZ2_decompress ( DState* s )
+{
+   UChar      uc;
+   Int32      retVal;
+   Int32      minLen, maxLen;
+   bz_stream* strm = s->strm;
+
+   /* stuff that needs to be saved/restored */
+   Int32  i;
+   Int32  j;
+   Int32  t;
+   Int32  alphaSize;
+   Int32  nGroups;
+   Int32  nSelectors;
+   Int32  EOB;
+   Int32  groupNo;
+   Int32  groupPos;
+   Int32  nextSym;
+   Int32  nblockMAX;
+   Int32  nblock;
+   Int32  es;
+   Int32  N;
+   Int32  curr;
+   Int32  zt;
+   Int32  zn; 
+   Int32  zvec;
+   Int32  zj;
+   Int32  gSel;
+   Int32  gMinlen;
+   Int32* gLimit;
+   Int32* gBase;
+   Int32* gPerm;
+
+   if (s->state == BZ_X_MAGIC_1) {
+      /*initialise the save area*/
+      s->save_i           = 0;
+      s->save_j           = 0;
+      s->save_t           = 0;
+      s->save_alphaSize   = 0;
+      s->save_nGroups     = 0;
+      s->save_nSelectors  = 0;
+      s->save_EOB         = 0;
+      s->save_groupNo     = 0;
+      s->save_groupPos    = 0;
+      s->save_nextSym     = 0;
+      s->save_nblockMAX   = 0;
+      s->save_nblock      = 0;
+      s->save_es          = 0;
+      s->save_N           = 0;
+      s->save_curr        = 0;
+      s->save_zt          = 0;
+      s->save_zn          = 0;
+      s->save_zvec        = 0;
+      s->save_zj          = 0;
+      s->save_gSel        = 0;
+      s->save_gMinlen     = 0;
+      s->save_gLimit      = NULL;
+      s->save_gBase       = NULL;
+      s->save_gPerm       = NULL;
+   }
+
+   /*restore from the save area*/
+   i           = s->save_i;
+   j           = s->save_j;
+   t           = s->save_t;
+   alphaSize   = s->save_alphaSize;
+   nGroups     = s->save_nGroups;
+   nSelectors  = s->save_nSelectors;
+   EOB         = s->save_EOB;
+   groupNo     = s->save_groupNo;
+   groupPos    = s->save_groupPos;
+   nextSym     = s->save_nextSym;
+   nblockMAX   = s->save_nblockMAX;
+   nblock      = s->save_nblock;
+   es          = s->save_es;
+   N           = s->save_N;
+   curr        = s->save_curr;
+   zt          = s->save_zt;
+   zn          = s->save_zn; 
+   zvec        = s->save_zvec;
+   zj          = s->save_zj;
+   gSel        = s->save_gSel;
+   gMinlen     = s->save_gMinlen;
+   gLimit      = s->save_gLimit;
+   gBase       = s->save_gBase;
+   gPerm       = s->save_gPerm;
+
+   retVal = BZ_OK;
+
+   switch (s->state) {
+
+      GET_UCHAR(BZ_X_MAGIC_1, uc);
+      if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC);
+
+      GET_UCHAR(BZ_X_MAGIC_2, uc);
+      if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC);
+
+      GET_UCHAR(BZ_X_MAGIC_3, uc)
+      if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC);
+
+      GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
+      if (s->blockSize100k < (BZ_HDR_0 + 1) || 
+          s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC);
+      s->blockSize100k -= BZ_HDR_0;
+
+      if (s->smallDecompress) {
+         s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
+         s->ll4  = BZALLOC( 
+                      ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar) 
+                   );
+         if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
+      } else {
+         s->tt  = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
+         if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
+      }
+
+      GET_UCHAR(BZ_X_BLKHDR_1, uc);
+
+      if (uc == 0x17) goto endhdr_2;
+      if (uc != 0x31) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_2, uc);
+      if (uc != 0x41) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_3, uc);
+      if (uc != 0x59) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_4, uc);
+      if (uc != 0x26) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_5, uc);
+      if (uc != 0x53) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_6, uc);
+      if (uc != 0x59) RETURN(BZ_DATA_ERROR);
+
+      s->currBlockNo++;
+      if (s->verbosity >= 2)
+         VPrintf1 ( "\n    [%d: huff+mtf ", s->currBlockNo );
+ 
+      s->storedBlockCRC = 0;
+      GET_UCHAR(BZ_X_BCRC_1, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_BCRC_2, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_BCRC_3, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_BCRC_4, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+
+      GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
+
+      s->origPtr = 0;
+      GET_UCHAR(BZ_X_ORIGPTR_1, uc);
+      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+      GET_UCHAR(BZ_X_ORIGPTR_2, uc);
+      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+      GET_UCHAR(BZ_X_ORIGPTR_3, uc);
+      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+
+      if (s->origPtr < 0)
+         RETURN(BZ_DATA_ERROR);
+      if (s->origPtr > 10 + 100000*s->blockSize100k) 
+         RETURN(BZ_DATA_ERROR);
+
+      /*--- Receive the mapping table ---*/
+      for (i = 0; i < 16; i++) {
+         GET_BIT(BZ_X_MAPPING_1, uc);
+         if (uc == 1) 
+            s->inUse16[i] = True; else 
+            s->inUse16[i] = False;
+      }
+
+      for (i = 0; i < 256; i++) s->inUse[i] = False;
+
+      for (i = 0; i < 16; i++)
+         if (s->inUse16[i])
+            for (j = 0; j < 16; j++) {
+               GET_BIT(BZ_X_MAPPING_2, uc);
+               if (uc == 1) s->inUse[i * 16 + j] = True;
+            }
+      makeMaps_d ( s );
+      if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
+      alphaSize = s->nInUse+2;
+
+      /*--- Now the selectors ---*/
+      GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
+      if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
+      GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
+      if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
+      for (i = 0; i < nSelectors; i++) {
+         j = 0;
+         while (True) {
+            GET_BIT(BZ_X_SELECTOR_3, uc);
+            if (uc == 0) break;
+            j++;
+            if (j >= nGroups) RETURN(BZ_DATA_ERROR);
+         }
+         s->selectorMtf[i] = j;
+      }
+
+      /*--- Undo the MTF values for the selectors. ---*/
+      {
+         UChar pos[BZ_N_GROUPS], tmp, v;
+         for (v = 0; v < nGroups; v++) pos[v] = v;
+   
+         for (i = 0; i < nSelectors; i++) {
+            v = s->selectorMtf[i];
+            tmp = pos[v];
+            while (v > 0) { pos[v] = pos[v-1]; v--; }
+            pos[0] = tmp;
+            s->selector[i] = tmp;
+         }
+      }
+
+      /*--- Now the coding tables ---*/
+      for (t = 0; t < nGroups; t++) {
+         GET_BITS(BZ_X_CODING_1, curr, 5);
+         for (i = 0; i < alphaSize; i++) {
+            while (True) {
+               if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
+               GET_BIT(BZ_X_CODING_2, uc);
+               if (uc == 0) break;
+               GET_BIT(BZ_X_CODING_3, uc);
+               if (uc == 0) curr++; else curr--;
+            }
+            s->len[t][i] = curr;
+         }
+      }
+
+      /*--- Create the Huffman decoding tables ---*/
+      for (t = 0; t < nGroups; t++) {
+         minLen = 32;
+         maxLen = 0;
+         for (i = 0; i < alphaSize; i++) {
+            if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
+            if (s->len[t][i] < minLen) minLen = s->len[t][i];
+         }
+         BZ2_hbCreateDecodeTables ( 
+            &(s->limit[t][0]), 
+            &(s->base[t][0]), 
+            &(s->perm[t][0]), 
+            &(s->len[t][0]),
+            minLen, maxLen, alphaSize
+         );
+         s->minLens[t] = minLen;
+      }
+
+      /*--- Now the MTF values ---*/
+
+      EOB      = s->nInUse+1;
+      nblockMAX = 100000 * s->blockSize100k;
+      groupNo  = -1;
+      groupPos = 0;
+
+      for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
+
+      /*-- MTF init --*/
+      {
+         Int32 ii, jj, kk;
+         kk = MTFA_SIZE-1;
+         for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
+            for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
+               s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
+               kk--;
+            }
+            s->mtfbase[ii] = kk + 1;
+         }
+      }
+      /*-- end MTF init --*/
+
+      nblock = 0;
+      GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
+
+      while (True) {
+
+         if (nextSym == EOB) break;
+
+         if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
+
+            es = -1;
+            N = 1;
+            do {
+               if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
+               if (nextSym == BZ_RUNB) es = es + (1+1) * N;
+               N = N * 2;
+               GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
+            }
+               while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
+
+            es++;
+            uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
+            s->unzftab[uc] += es;
+
+            if (s->smallDecompress)
+               while (es > 0) {
+                  if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+                  s->ll16[nblock] = (UInt16)uc;
+                  nblock++;
+                  es--;
+               }
+            else
+               while (es > 0) {
+                  if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+                  s->tt[nblock] = (UInt32)uc;
+                  nblock++;
+                  es--;
+               };
+
+            continue;
+
+         } else {
+
+            if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+
+            /*-- uc = MTF ( nextSym-1 ) --*/
+            {
+               Int32 ii, jj, kk, pp, lno, off;
+               UInt32 nn;
+               nn = (UInt32)(nextSym - 1);
+
+               if (nn < MTFL_SIZE) {
+                  /* avoid general-case expense */
+                  pp = s->mtfbase[0];
+                  uc = s->mtfa[pp+nn];
+                  while (nn > 3) {
+                     Int32 z = pp+nn;
+                     s->mtfa[(z)  ] = s->mtfa[(z)-1];
+                     s->mtfa[(z)-1] = s->mtfa[(z)-2];
+                     s->mtfa[(z)-2] = s->mtfa[(z)-3];
+                     s->mtfa[(z)-3] = s->mtfa[(z)-4];
+                     nn -= 4;
+                  }
+                  while (nn > 0) { 
+                     s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--; 
+                  };
+                  s->mtfa[pp] = uc;
+               } else { 
+                  /* general case */
+                  lno = nn / MTFL_SIZE;
+                  off = nn % MTFL_SIZE;
+                  pp = s->mtfbase[lno] + off;
+                  uc = s->mtfa[pp];
+                  while (pp > s->mtfbase[lno]) { 
+                     s->mtfa[pp] = s->mtfa[pp-1]; pp--; 
+                  };
+                  s->mtfbase[lno]++;
+                  while (lno > 0) {
+                     s->mtfbase[lno]--;
+                     s->mtfa[s->mtfbase[lno]] 
+                        = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
+                     lno--;
+                  }
+                  s->mtfbase[0]--;
+                  s->mtfa[s->mtfbase[0]] = uc;
+                  if (s->mtfbase[0] == 0) {
+                     kk = MTFA_SIZE-1;
+                     for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
+                        for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
+                           s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
+                           kk--;
+                        }
+                        s->mtfbase[ii] = kk + 1;
+                     }
+                  }
+               }
+            }
+            /*-- end uc = MTF ( nextSym-1 ) --*/
+
+            s->unzftab[s->seqToUnseq[uc]]++;
+            if (s->smallDecompress)
+               s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
+               s->tt[nblock]   = (UInt32)(s->seqToUnseq[uc]);
+            nblock++;
+
+            GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
+            continue;
+         }
+      }
+
+      /* Now we know what nblock is, we can do a better sanity
+         check on s->origPtr.
+      */
+      if (s->origPtr < 0 || s->origPtr >= nblock)
+         RETURN(BZ_DATA_ERROR);
+
+      /*-- Set up cftab to facilitate generation of T^(-1) --*/
+      s->cftab[0] = 0;
+      for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
+      for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
+      for (i = 0; i <= 256; i++) {
+         if (s->cftab[i] < 0 || s->cftab[i] > nblock) {
+            /* s->cftab[i] can legitimately be == nblock */
+            RETURN(BZ_DATA_ERROR);
+         }
+      }
+
+      s->state_out_len = 0;
+      s->state_out_ch  = 0;
+      BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
+      s->state = BZ_X_OUTPUT;
+      if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
+
+      if (s->smallDecompress) {
+
+         /*-- Make a copy of cftab, used in generation of T --*/
+         for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
+
+         /*-- compute the T vector --*/
+         for (i = 0; i < nblock; i++) {
+            uc = (UChar)(s->ll16[i]);
+            SET_LL(i, s->cftabCopy[uc]);
+            s->cftabCopy[uc]++;
+         }
+
+         /*-- Compute T^(-1) by pointer reversal on T --*/
+         i = s->origPtr;
+         j = GET_LL(i);
+         do {
+            Int32 tmp = GET_LL(j);
+            SET_LL(j, i);
+            i = j;
+            j = tmp;
+         }
+            while (i != s->origPtr);
+
+         s->tPos = s->origPtr;
+         s->nblock_used = 0;
+         if (s->blockRandomised) {
+            BZ_RAND_INIT_MASK;
+            BZ_GET_SMALL(s->k0); s->nblock_used++;
+            BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; 
+         } else {
+            BZ_GET_SMALL(s->k0); s->nblock_used++;
+         }
+
+      } else {
+
+         /*-- compute the T^(-1) vector --*/
+         for (i = 0; i < nblock; i++) {
+            uc = (UChar)(s->tt[i] & 0xff);
+            s->tt[s->cftab[uc]] |= (i << 8);
+            s->cftab[uc]++;
+         }
+
+         s->tPos = s->tt[s->origPtr] >> 8;
+         s->nblock_used = 0;
+         if (s->blockRandomised) {
+            BZ_RAND_INIT_MASK;
+            BZ_GET_FAST(s->k0); s->nblock_used++;
+            BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; 
+         } else {
+            BZ_GET_FAST(s->k0); s->nblock_used++;
+         }
+
+      }
+
+      RETURN(BZ_OK);
+
+
+
+    endhdr_2:
+
+      GET_UCHAR(BZ_X_ENDHDR_2, uc);
+      if (uc != 0x72) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_3, uc);
+      if (uc != 0x45) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_4, uc);
+      if (uc != 0x38) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_5, uc);
+      if (uc != 0x50) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_6, uc);
+      if (uc != 0x90) RETURN(BZ_DATA_ERROR);
+
+      s->storedCombinedCRC = 0;
+      GET_UCHAR(BZ_X_CCRC_1, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_CCRC_2, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_CCRC_3, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_CCRC_4, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+
+      s->state = BZ_X_IDLE;
+      RETURN(BZ_STREAM_END);
+
+      default: AssertH ( False, 4001 );
+   }
+
+   AssertH ( False, 4002 );
+
+   save_state_and_return:
+
+   s->save_i           = i;
+   s->save_j           = j;
+   s->save_t           = t;
+   s->save_alphaSize   = alphaSize;
+   s->save_nGroups     = nGroups;
+   s->save_nSelectors  = nSelectors;
+   s->save_EOB         = EOB;
+   s->save_groupNo     = groupNo;
+   s->save_groupPos    = groupPos;
+   s->save_nextSym     = nextSym;
+   s->save_nblockMAX   = nblockMAX;
+   s->save_nblock      = nblock;
+   s->save_es          = es;
+   s->save_N           = N;
+   s->save_curr        = curr;
+   s->save_zt          = zt;
+   s->save_zn          = zn;
+   s->save_zvec        = zvec;
+   s->save_zj          = zj;
+   s->save_gSel        = gSel;
+   s->save_gMinlen     = gMinlen;
+   s->save_gLimit      = gLimit;
+   s->save_gBase       = gBase;
+   s->save_gPerm       = gPerm;
+
+   return retVal;   
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                      decompress.c ---*/
+/*-------------------------------------------------------------*/
Index: /trunk/minix/commands/bzip2-1.0.3/dlltest.c
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/dlltest.c	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/dlltest.c	(revision 9)
@@ -0,0 +1,176 @@
+/*
+   minibz2
+      libbz2.dll test program.
+      by Yoshioka Tsuneo(QWF00133@nifty.ne.jp/tsuneo-y@is.aist-nara.ac.jp)
+      This file is Public Domain.
+      welcome any email to me.
+
+   usage: minibz2 [-d] [-{1,2,..9}] [[srcfilename] destfilename]
+*/
+
+#define BZ_IMPORT
+#include <stdio.h>
+#include <stdlib.h>
+#include "bzlib.h"
+#ifdef _WIN32
+#include <io.h>
+#endif
+
+
+#ifdef _WIN32
+
+#define BZ2_LIBNAME "libbz2-1.0.2.DLL" 
+
+#include <windows.h>
+static int BZ2DLLLoaded = 0;
+static HINSTANCE BZ2DLLhLib;
+int BZ2DLLLoadLibrary(void)
+{
+   HINSTANCE hLib;
+
+   if(BZ2DLLLoaded==1){return 0;}
+   hLib=LoadLibrary(BZ2_LIBNAME);
+   if(hLib == NULL){
+      fprintf(stderr,"Can't load %s\n",BZ2_LIBNAME);
+      return -1;
+   }
+   BZ2_bzlibVersion=GetProcAddress(hLib,"BZ2_bzlibVersion");
+   BZ2_bzopen=GetProcAddress(hLib,"BZ2_bzopen");
+   BZ2_bzdopen=GetProcAddress(hLib,"BZ2_bzdopen");
+   BZ2_bzread=GetProcAddress(hLib,"BZ2_bzread");
+   BZ2_bzwrite=GetProcAddress(hLib,"BZ2_bzwrite");
+   BZ2_bzflush=GetProcAddress(hLib,"BZ2_bzflush");
+   BZ2_bzclose=GetProcAddress(hLib,"BZ2_bzclose");
+   BZ2_bzerror=GetProcAddress(hLib,"BZ2_bzerror");
+
+   if (!BZ2_bzlibVersion || !BZ2_bzopen || !BZ2_bzdopen
+       || !BZ2_bzread || !BZ2_bzwrite || !BZ2_bzflush
+       || !BZ2_bzclose || !BZ2_bzerror) {
+      fprintf(stderr,"GetProcAddress failed.\n");
+      return -1;
+   }
+   BZ2DLLLoaded=1;
+   BZ2DLLhLib=hLib;
+   return 0;
+
+}
+int BZ2DLLFreeLibrary(void)
+{
+   if(BZ2DLLLoaded==0){return 0;}
+   FreeLibrary(BZ2DLLhLib);
+   BZ2DLLLoaded=0;
+}
+#endif /* WIN32 */
+
+void usage(void)
+{
+   puts("usage: minibz2 [-d] [-{1,2,..9}] [[srcfilename] destfilename]");
+}
+
+int main(int argc,char *argv[])
+{
+   int decompress = 0;
+   int level = 9;
+   char *fn_r = NULL;
+   char *fn_w = NULL;
+
+#ifdef _WIN32
+   if(BZ2DLLLoadLibrary()<0){
+      fprintf(stderr,"Loading of %s failed.  Giving up.\n", BZ2_LIBNAME);
+      exit(1);
+   }
+   printf("Loading of %s succeeded.  Library version is %s.\n",
+          BZ2_LIBNAME, BZ2_bzlibVersion() );
+#endif
+   while(++argv,--argc){
+      if(**argv =='-' || **argv=='/'){
+         char *p;
+
+         for(p=*argv+1;*p;p++){
+            if(*p=='d'){
+               decompress = 1;
+            }else if('1'<=*p && *p<='9'){
+               level = *p - '0';
+            }else{
+               usage();
+               exit(1);
+            }
+         }
+      }else{
+         break;
+      }
+   }
+   if(argc>=1){
+      fn_r = *argv;
+      argc--;argv++;
+   }else{
+      fn_r = NULL;
+   }
+   if(argc>=1){
+      fn_w = *argv;
+      argc--;argv++;
+   }else{
+      fn_w = NULL;
+   }
+   {
+      int len;
+      char buff[0x1000];
+      char mode[10];
+
+      if(decompress){
+         BZFILE *BZ2fp_r = NULL;
+         FILE *fp_w = NULL;
+
+         if(fn_w){
+            if((fp_w = fopen(fn_w,"wb"))==NULL){
+               printf("can't open [%s]\n",fn_w);
+               perror("reason:");
+               exit(1);
+            }
+         }else{
+            fp_w = stdout;
+         }
+         if((fn_r == NULL && (BZ2fp_r = BZ2_bzdopen(fileno(stdin),"rb"))==NULL)
+            || (fn_r != NULL && (BZ2fp_r = BZ2_bzopen(fn_r,"rb"))==NULL)){
+            printf("can't bz2openstream\n");
+            exit(1);
+         }
+         while((len=BZ2_bzread(BZ2fp_r,buff,0x1000))>0){
+            fwrite(buff,1,len,fp_w);
+         }
+         BZ2_bzclose(BZ2fp_r);
+         if(fp_w != stdout) fclose(fp_w);
+      }else{
+         BZFILE *BZ2fp_w = NULL;
+         FILE *fp_r = NULL;
+
+         if(fn_r){
+            if((fp_r = fopen(fn_r,"rb"))==NULL){
+               printf("can't open [%s]\n",fn_r);
+               perror("reason:");
+               exit(1);
+            }
+         }else{
+            fp_r = stdin;
+         }
+         mode[0]='w';
+         mode[1] = '0' + level;
+         mode[2] = '\0';
+
+         if((fn_w == NULL && (BZ2fp_w = BZ2_bzdopen(fileno(stdout),mode))==NULL)
+            || (fn_w !=NULL && (BZ2fp_w = BZ2_bzopen(fn_w,mode))==NULL)){
+            printf("can't bz2openstream\n");
+            exit(1);
+         }
+         while((len=fread(buff,1,0x1000,fp_r))>0){
+            BZ2_bzwrite(BZ2fp_w,buff,len);
+         }
+         BZ2_bzclose(BZ2fp_w);
+         if(fp_r!=stdin)fclose(fp_r);
+      }
+   }
+#ifdef _WIN32
+   BZ2DLLFreeLibrary();
+#endif
+   return 0;
+}
Index: /trunk/minix/commands/bzip2-1.0.3/dlltest.dsp
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/dlltest.dsp	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/dlltest.dsp	(revision 9)
@@ -0,0 +1,93 @@
+# Microsoft Developer Studio Project File - Name="dlltest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** ÒWµÈ¢Å­Ÿ³¢ **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=dlltest - Win32 Debug
+!MESSAGE ±êÍLøÈÒ²žÌ§²ÙÅÍ èÜ¹ñB ±ÌÌßÛŒÞªžÄðËÞÙÄÞ·éœßÉÍ NMAKE ðgpµÄ­Ÿ³¢B
+!MESSAGE [Ò²žÌ§²ÙÌŽžœÎß°Ä] ºÏÝÄÞðgpµÄÀsµÄ­Ÿ³¢
+!MESSAGE 
+!MESSAGE NMAKE /f "dlltest.mak".
+!MESSAGE 
+!MESSAGE NMAKE ÌÀsÉ\¬ðwèÅ«Ü·
+!MESSAGE ºÏÝÄÞ ×²ÝãÅÏžÛÌÝèðè`µÜ·Bá:
+!MESSAGE 
+!MESSAGE NMAKE /f "dlltest.mak" CFG="dlltest - Win32 Debug"
+!MESSAGE 
+!MESSAGE IðÂ\ÈËÞÙÄÞ Ó°ÄÞ:
+!MESSAGE 
+!MESSAGE "dlltest - Win32 Release" ("Win32 (x86) Console Application" p)
+!MESSAGE "dlltest - Win32 Debug" ("Win32 (x86) Console Application" p)
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "dlltest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x411 /d "NDEBUG"
+# ADD RSC /l 0x411 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"minibz2.exe"
+
+!ELSEIF  "$(CFG)" == "dlltest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "dlltest_"
+# PROP BASE Intermediate_Dir "dlltest_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "dlltest_"
+# PROP Intermediate_Dir "dlltest_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x411 /d "_DEBUG"
+# ADD RSC /l 0x411 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"minibz2.exe" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "dlltest - Win32 Release"
+# Name "dlltest - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\bzlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\dlltest.c
+# End Source File
+# End Target
+# End Project
Index: /trunk/minix/commands/bzip2-1.0.3/entities.xml
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/entities.xml	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/entities.xml	(revision 9)
@@ -0,0 +1,9 @@
+<!-- misc. strings -->
+<!ENTITY bz-url "http://www.bzip.org">
+<!ENTITY bz-email "jseward@bzip.org">
+<!ENTITY bz-lifespan "1996-2005">
+
+<!ENTITY bz-version "1.0.3">
+<!ENTITY bz-date "15 February 2005">
+
+<!ENTITY manual-title "bzip2 Manual">
Index: /trunk/minix/commands/bzip2-1.0.3/format.pl
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/format.pl	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/format.pl	(revision 9)
@@ -0,0 +1,53 @@
+#!/usr/bin/perl -w
+use strict;
+
+# get command line values:
+if ( $#ARGV !=1 ) {
+    die "Usage:  $0 xml_infile xml_outfile\n";
+}
+
+my $infile = shift;
+# check infile exists
+die "Can't find file \"$infile\""
+  unless -f $infile;
+# check we can read infile
+if (! -r $infile) {
+    die "Can't read input $infile\n";
+}
+# check we can open infile
+open( INFILE,"<$infile" ) or 
+    die "Can't input $infile $!";
+
+#my $outfile = 'fmt-manual.xml';
+my $outfile = shift;
+#print "Infile: $infile, Outfile: $outfile\n";
+# check we can write to outfile
+open( OUTFILE,">$outfile" ) or 
+    die "Can't output $outfile $! for writing";
+
+my ($prev, $curr, $str);
+$prev = ''; $curr = '';
+while ( <INFILE> ) {
+
+		print OUTFILE $prev;
+    $prev = $curr;
+    $curr = $_;
+    $str = '';
+
+    if ( $prev =~ /<programlisting>$|<screen>$/ ) {
+        chomp $prev;
+        $curr = join( '', $prev, "<![CDATA[", $curr );
+				$prev = '';
+        next;
+    }
+    elsif ( $curr =~ /<\/programlisting>|<\/screen>/ ) {
+        chomp $prev;
+        $curr = join( '', $prev, "]]>", $curr );
+				$prev = '';
+        next;
+    }
+}
+print OUTFILE $curr;
+close INFILE;
+close OUTFILE;
+exit;
Index: /trunk/minix/commands/bzip2-1.0.3/huffman.c
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/huffman.c	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/huffman.c	(revision 9)
@@ -0,0 +1,245 @@
+
+/*-------------------------------------------------------------*/
+/*--- Huffman coding low-level stuff                        ---*/
+/*---                                             huffman.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+
+#include "bzlib_private.h"
+
+/*---------------------------------------------------*/
+#define WEIGHTOF(zz0)  ((zz0) & 0xffffff00)
+#define DEPTHOF(zz1)   ((zz1) & 0x000000ff)
+#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
+
+#define ADDWEIGHTS(zw1,zw2)                           \
+   (WEIGHTOF(zw1)+WEIGHTOF(zw2)) |                    \
+   (1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2)))
+
+#define UPHEAP(z)                                     \
+{                                                     \
+   Int32 zz, tmp;                                     \
+   zz = z; tmp = heap[zz];                            \
+   while (weight[tmp] < weight[heap[zz >> 1]]) {      \
+      heap[zz] = heap[zz >> 1];                       \
+      zz >>= 1;                                       \
+   }                                                  \
+   heap[zz] = tmp;                                    \
+}
+
+#define DOWNHEAP(z)                                   \
+{                                                     \
+   Int32 zz, yy, tmp;                                 \
+   zz = z; tmp = heap[zz];                            \
+   while (True) {                                     \
+      yy = zz << 1;                                   \
+      if (yy > nHeap) break;                          \
+      if (yy < nHeap &&                               \
+          weight[heap[yy+1]] < weight[heap[yy]])      \
+         yy++;                                        \
+      if (weight[tmp] < weight[heap[yy]]) break;      \
+      heap[zz] = heap[yy];                            \
+      zz = yy;                                        \
+   }                                                  \
+   heap[zz] = tmp;                                    \
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_hbMakeCodeLengths ( UChar *len, 
+                             Int32 *freq,
+                             Int32 alphaSize,
+                             Int32 maxLen )
+{
+   /*--
+      Nodes and heap entries run from 1.  Entry 0
+      for both the heap and nodes is a sentinel.
+   --*/
+   Int32 nNodes, nHeap, n1, n2, i, j, k;
+   Bool  tooLong;
+
+   Int32 heap   [ BZ_MAX_ALPHA_SIZE + 2 ];
+   Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ];
+   Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ]; 
+
+   for (i = 0; i < alphaSize; i++)
+      weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
+
+   while (True) {
+
+      nNodes = alphaSize;
+      nHeap = 0;
+
+      heap[0] = 0;
+      weight[0] = 0;
+      parent[0] = -2;
+
+      for (i = 1; i <= alphaSize; i++) {
+         parent[i] = -1;
+         nHeap++;
+         heap[nHeap] = i;
+         UPHEAP(nHeap);
+      }
+
+      AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 );
+   
+      while (nHeap > 1) {
+         n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
+         n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
+         nNodes++;
+         parent[n1] = parent[n2] = nNodes;
+         weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]);
+         parent[nNodes] = -1;
+         nHeap++;
+         heap[nHeap] = nNodes;
+         UPHEAP(nHeap);
+      }
+
+      AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 );
+
+      tooLong = False;
+      for (i = 1; i <= alphaSize; i++) {
+         j = 0;
+         k = i;
+         while (parent[k] >= 0) { k = parent[k]; j++; }
+         len[i-1] = j;
+         if (j > maxLen) tooLong = True;
+      }
+      
+      if (! tooLong) break;
+
+      /* 17 Oct 04: keep-going condition for the following loop used
+         to be 'i < alphaSize', which missed the last element,
+         theoretically leading to the possibility of the compressor
+         looping.  However, this count-scaling step is only needed if
+         one of the generated Huffman code words is longer than
+         maxLen, which up to and including version 1.0.2 was 20 bits,
+         which is extremely unlikely.  In version 1.0.3 maxLen was
+         changed to 17 bits, which has minimal effect on compression
+         ratio, but does mean this scaling step is used from time to
+         time, enough to verify that it works.
+
+         This means that bzip2-1.0.3 and later will only produce
+         Huffman codes with a maximum length of 17 bits.  However, in
+         order to preserve backwards compatibility with bitstreams
+         produced by versions pre-1.0.3, the decompressor must still
+         handle lengths of up to 20. */
+
+      for (i = 1; i <= alphaSize; i++) {
+         j = weight[i] >> 8;
+         j = 1 + (j / 2);
+         weight[i] = j << 8;
+      }
+   }
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_hbAssignCodes ( Int32 *code,
+                         UChar *length,
+                         Int32 minLen,
+                         Int32 maxLen,
+                         Int32 alphaSize )
+{
+   Int32 n, vec, i;
+
+   vec = 0;
+   for (n = minLen; n <= maxLen; n++) {
+      for (i = 0; i < alphaSize; i++)
+         if (length[i] == n) { code[i] = vec; vec++; };
+      vec <<= 1;
+   }
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_hbCreateDecodeTables ( Int32 *limit,
+                                Int32 *base,
+                                Int32 *perm,
+                                UChar *length,
+                                Int32 minLen,
+                                Int32 maxLen,
+                                Int32 alphaSize )
+{
+   Int32 pp, i, j, vec;
+
+   pp = 0;
+   for (i = minLen; i <= maxLen; i++)
+      for (j = 0; j < alphaSize; j++)
+         if (length[j] == i) { perm[pp] = j; pp++; };
+
+   for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0;
+   for (i = 0; i < alphaSize; i++) base[length[i]+1]++;
+
+   for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1];
+
+   for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0;
+   vec = 0;
+
+   for (i = minLen; i <= maxLen; i++) {
+      vec += (base[i+1] - base[i]);
+      limit[i] = vec-1;
+      vec <<= 1;
+   }
+   for (i = minLen + 1; i <= maxLen; i++)
+      base[i] = ((limit[i-1] + 1) << 1) - base[i];
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                         huffman.c ---*/
+/*-------------------------------------------------------------*/
Index: /trunk/minix/commands/bzip2-1.0.3/libbz2.def
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/libbz2.def	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/libbz2.def	(revision 9)
@@ -0,0 +1,27 @@
+LIBRARY			LIBBZ2
+DESCRIPTION		"libbzip2: library for data compression"
+EXPORTS
+	BZ2_bzCompressInit
+	BZ2_bzCompress
+	BZ2_bzCompressEnd
+	BZ2_bzDecompressInit
+	BZ2_bzDecompress
+	BZ2_bzDecompressEnd
+	BZ2_bzReadOpen
+	BZ2_bzReadClose
+	BZ2_bzReadGetUnused
+	BZ2_bzRead
+	BZ2_bzWriteOpen
+	BZ2_bzWrite
+	BZ2_bzWriteClose
+	BZ2_bzWriteClose64
+	BZ2_bzBuffToBuffCompress
+	BZ2_bzBuffToBuffDecompress
+	BZ2_bzlibVersion
+	BZ2_bzopen
+	BZ2_bzdopen
+	BZ2_bzread
+	BZ2_bzwrite
+	BZ2_bzflush
+	BZ2_bzclose
+	BZ2_bzerror
Index: /trunk/minix/commands/bzip2-1.0.3/libbz2.dsp
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/libbz2.dsp	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/libbz2.dsp	(revision 9)
@@ -0,0 +1,130 @@
+# Microsoft Developer Studio Project File - Name="libbz2" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** ÒWµÈ¢Å­Ÿ³¢ **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=libbz2 - Win32 Debug
+!MESSAGE ±êÍLøÈÒ²žÌ§²ÙÅÍ èÜ¹ñB ±ÌÌßÛŒÞªžÄðËÞÙÄÞ·éœßÉÍ NMAKE ðgpµÄ­Ÿ³¢B
+!MESSAGE [Ò²žÌ§²ÙÌŽžœÎß°Ä] ºÏÝÄÞðgpµÄÀsµÄ­Ÿ³¢
+!MESSAGE 
+!MESSAGE NMAKE /f "libbz2.mak".
+!MESSAGE 
+!MESSAGE NMAKE ÌÀsÉ\¬ðwèÅ«Ü·
+!MESSAGE ºÏÝÄÞ ×²ÝãÅÏžÛÌÝèðè`µÜ·Bá:
+!MESSAGE 
+!MESSAGE NMAKE /f "libbz2.mak" CFG="libbz2 - Win32 Debug"
+!MESSAGE 
+!MESSAGE IðÂ\ÈËÞÙÄÞ Ó°ÄÞ:
+!MESSAGE 
+!MESSAGE "libbz2 - Win32 Release" ("Win32 (x86) Dynamic-Link Library" p)
+!MESSAGE "libbz2 - Win32 Debug" ("Win32 (x86) Dynamic-Link Library" p)
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "libbz2 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x411 /d "NDEBUG"
+# ADD RSC /l 0x411 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /out:"libbz2.dll"
+
+!ELSEIF  "$(CFG)" == "libbz2 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x411 /d "_DEBUG"
+# ADD RSC /l 0x411 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"libbz2.dll" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "libbz2 - Win32 Release"
+# Name "libbz2 - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\blocksort.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bzlib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bzlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\bzlib_private.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\compress.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crctable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\decompress.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\huffman.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\libbz2.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\randtable.c
+# End Source File
+# End Target
+# End Project
Index: /trunk/minix/commands/bzip2-1.0.3/makefile.msc
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/makefile.msc	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/makefile.msc	(revision 9)
@@ -0,0 +1,63 @@
+# Makefile for Microsoft Visual C++ 6.0
+# usage: nmake -f makefile.msc
+# K.M. Syring (syring@gsf.de)
+# Fixed up by JRS for bzip2-0.9.5d release.
+
+CC=cl
+CFLAGS= -DWIN32 -MD -Ox -D_FILE_OFFSET_BITS=64 -nologo
+
+OBJS= blocksort.obj  \
+      huffman.obj    \
+      crctable.obj   \
+      randtable.obj  \
+      compress.obj   \
+      decompress.obj \
+      bzlib.obj
+
+all: lib bzip2 test
+
+bzip2: lib
+	$(CC) $(CFLAGS) -o bzip2 bzip2.c libbz2.lib setargv.obj
+	$(CC) $(CFLAGS) -o bzip2recover bzip2recover.c
+
+lib: $(OBJS)
+	lib /out:libbz2.lib $(OBJS)
+
+test: bzip2
+	type words1
+	.\\bzip2 -1  < sample1.ref > sample1.rb2
+	.\\bzip2 -2  < sample2.ref > sample2.rb2
+	.\\bzip2 -3  < sample3.ref > sample3.rb2
+	.\\bzip2 -d  < sample1.bz2 > sample1.tst
+	.\\bzip2 -d  < sample2.bz2 > sample2.tst
+	.\\bzip2 -ds < sample3.bz2 > sample3.tst
+	@echo All six of the fc's should find no differences.
+	@echo If fc finds an error on sample3.bz2, this could be
+	@echo because WinZip's 'TAR file smart CR/LF conversion'
+	@echo is too clever for its own good.  Disable this option.
+	@echo The correct size for sample3.ref is 120,244.  If it
+	@echo is 150,251, WinZip has messed it up.
+	fc sample1.bz2 sample1.rb2 
+	fc sample2.bz2 sample2.rb2
+	fc sample3.bz2 sample3.rb2
+	fc sample1.tst sample1.ref
+	fc sample2.tst sample2.ref
+	fc sample3.tst sample3.ref
+
+
+
+clean: 
+	del *.obj
+	del libbz2.lib 
+	del bzip2.exe
+	del bzip2recover.exe
+	del sample1.rb2 
+	del sample2.rb2 
+	del sample3.rb2
+	del sample1.tst 
+	del sample2.tst
+	del sample3.tst
+
+.c.obj: 
+	$(CC) $(CFLAGS) -c $*.c -o $*.obj
+
Index: /trunk/minix/commands/bzip2-1.0.3/manual.html
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/manual.html	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/manual.html	(revision 9)
@@ -0,0 +1,2687 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>bzip2 and libbzip2, version 1.0.3</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.64.1">
+<style type="text/css" media="screen">/* Colours:
+#74240f  dark brown      h1, h2, h3, h4
+#336699  medium blue     links
+#339999  turquoise       link hover colour
+#202020  almost black    general text
+#761596  purple          md5sum text
+#626262  dark gray       pre border
+#eeeeee  very light gray pre background
+#f2f2f9  very light blue nav table background
+#3366cc  medium blue     nav table border
+*/
+
+a, a:link, a:visited, a:active { color: #336699; }
+a:hover { color: #339999; }
+
+body { font: 80%/126% sans-serif; }
+h1, h2, h3, h4 { color: #74240f; }
+
+dt { color: #336699; font-weight: bold }
+dd { 
+ margin-left: 1.5em; 
+ padding-bottom: 0.8em;
+}
+
+/* -- ruler -- */
+div.hr_blue { 
+  height:  3px; 
+  background:#ffffff url("/images/hr_blue.png") repeat-x; }
+div.hr_blue hr { display:none; }
+
+/* release styles */
+#release p { margin-top: 0.4em; }
+#release .md5sum { color: #761596; }
+
+
+/* ------ styles for docs|manuals|howto ------ */
+/* -- lists -- */
+ul  { 
+ margin:     0px 4px 16px 16px;
+ padding:    0px;
+ list-style: url("/images/li-blue.png"); 
+}
+ul li { 
+ margin-bottom: 10px;
+}
+ul ul	{ 
+ list-style-type:  none; 
+ list-style-image: none; 
+ margin-left:      0px; 
+}
+
+/* header / footer nav tables */
+table.nav {
+ border:     solid 1px #3366cc;
+ background: #f2f2f9;
+ background-color: #f2f2f9;
+ margin-bottom: 0.5em;
+}
+/* don't have underlined links in chunked nav menus */
+table.nav a { text-decoration: none; }
+table.nav a:hover { text-decoration: underline; }
+table.nav td { font-size: 85%; }
+
+code, tt, pre { font-size: 120%; }
+code, tt { color: #761596; }
+
+div.literallayout, pre.programlisting, pre.screen {
+ color:      #000000;
+ padding:    0.5em;
+ background: #eeeeee;
+ border:     1px solid #626262;
+ background-color: #eeeeee;
+ margin: 4px 0px 4px 0px; 
+}
+</style>
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book" lang="en">
+<div class="titlepage">
+<div>
+<div><h1 class="title">
+<a name="userman"></a>bzip2 and libbzip2, version 1.0.3</h1></div>
+<div><h2 class="subtitle">A program and library for data compression</h2></div>
+<div><div class="authorgroup"><div class="author">
+<h3 class="author">
+<span class="firstname">Julian</span> <span class="surname">Seward</span>
+</h3>
+<div class="affiliation"><span class="orgname">http://www.bzip.org<br></span></div>
+</div></div></div>
+<div><p class="releaseinfo">Version 1.0.3 of 15 February 2005</p></div>
+<div><p class="copyright">Copyright © 1996-2005 Julian Seward</p></div>
+<div><div class="legalnotice">
+<p>This program, <tt class="computeroutput">bzip2</tt>, the
+  associated library <tt class="computeroutput">libbzip2</tt>, and
+  all documentation, are copyright © 1996-2005 Julian Seward.
+  All rights reserved.</p>
+<p>Redistribution and use in source and binary forms, with
+  or without modification, are permitted provided that the
+  following conditions are met:</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p>Redistributions of source code must retain the
+   above copyright notice, this list of conditions and the
+   following disclaimer.</p></li>
+<li style="list-style-type: disc"><p>The origin of this software must not be
+   misrepresented; you must not claim that you wrote the original
+   software.  If you use this software in a product, an
+   acknowledgment in the product documentation would be
+   appreciated but is not required.</p></li>
+<li style="list-style-type: disc"><p>Altered source versions must be plainly marked
+   as such, and must not be misrepresented as being the original
+   software.</p></li>
+<li style="list-style-type: disc"><p>The name of the author may not be used to
+   endorse or promote products derived from this software without
+   specific prior written permission.</p></li>
+</ul></div>
+<p>THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY
+  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+  AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+  THE POSSIBILITY OF SUCH DAMAGE.</p>
+<p>PATENTS: To the best of my knowledge,
+ <tt class="computeroutput">bzip2</tt> and
+ <tt class="computeroutput">libbzip2</tt> do not use any patented
+ algorithms.  However, I do not have the resources to carry
+ out a patent search.  Therefore I cannot give any guarantee of
+ the above statement.
+ </p>
+</div></div>
+</div>
+<div></div>
+<hr>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="chapter"><a href="#intro">1. Introduction</a></span></dt>
+<dt><span class="chapter"><a href="#using">2. How to use bzip2</a></span></dt>
+<dd><dl>
+<dt><span class="sect1"><a href="#name">2.1. NAME</a></span></dt>
+<dt><span class="sect1"><a href="#synopsis">2.2. SYNOPSIS</a></span></dt>
+<dt><span class="sect1"><a href="#description">2.3. DESCRIPTION</a></span></dt>
+<dt><span class="sect1"><a href="#options">2.4. OPTIONS</a></span></dt>
+<dt><span class="sect1"><a href="#memory-management">2.5. MEMORY MANAGEMENT</a></span></dt>
+<dt><span class="sect1"><a href="#recovering">2.6. RECOVERING DATA FROM DAMAGED FILES</a></span></dt>
+<dt><span class="sect1"><a href="#performance">2.7. PERFORMANCE NOTES</a></span></dt>
+<dt><span class="sect1"><a href="#caveats">2.8. CAVEATS</a></span></dt>
+<dt><span class="sect1"><a href="#author">2.9. AUTHOR</a></span></dt>
+</dl></dd>
+<dt><span class="chapter"><a href="#libprog">3. 
+Programming with libbzip2
+</a></span></dt>
+<dd><dl>
+<dt><span class="sect1"><a href="#top-level">3.1. Top-level structure</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#ll-summary">3.1.1. Low-level summary</a></span></dt>
+<dt><span class="sect2"><a href="#hl-summary">3.1.2. High-level summary</a></span></dt>
+<dt><span class="sect2"><a href="#util-fns-summary">3.1.3. Utility functions summary</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#err-handling">3.2. Error handling</a></span></dt>
+<dt><span class="sect1"><a href="#low-level">3.3. Low-level interface</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#bzcompress-init">3.3.1. BZ2_bzCompressInit</a></span></dt>
+<dt><span class="sect2"><a href="#bzCompress">3.3.2. BZ2_bzCompress</a></span></dt>
+<dt><span class="sect2"><a href="#bzCompress-end">3.3.3. BZ2_bzCompressEnd</a></span></dt>
+<dt><span class="sect2"><a href="#bzDecompress-init">3.3.4. BZ2_bzDecompressInit</a></span></dt>
+<dt><span class="sect2"><a href="#bzDecompress">3.3.5. BZ2_bzDecompress</a></span></dt>
+<dt><span class="sect2"><a href="#bzDecompress-end">3.3.6. BZ2_bzDecompressEnd</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#hl-interface">3.4. High-level interface</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#bzreadopen">3.4.1. BZ2_bzReadOpen</a></span></dt>
+<dt><span class="sect2"><a href="#bzread">3.4.2. BZ2_bzRead</a></span></dt>
+<dt><span class="sect2"><a href="#bzreadgetunused">3.4.3. BZ2_bzReadGetUnused</a></span></dt>
+<dt><span class="sect2"><a href="#bzreadclose">3.4.4. BZ2_bzReadClose</a></span></dt>
+<dt><span class="sect2"><a href="#bzwriteopen">3.4.5. BZ2_bzWriteOpen</a></span></dt>
+<dt><span class="sect2"><a href="#bzwrite">3.4.6. BZ2_bzWrite</a></span></dt>
+<dt><span class="sect2"><a href="#bzwriteclose">3.4.7. BZ2_bzWriteClose</a></span></dt>
+<dt><span class="sect2"><a href="#embed">3.4.8. Handling embedded compressed data streams</a></span></dt>
+<dt><span class="sect2"><a href="#std-rdwr">3.4.9. Standard file-reading/writing code</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#util-fns">3.5. Utility functions</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#bzbufftobuffcompress">3.5.1. BZ2_bzBuffToBuffCompress</a></span></dt>
+<dt><span class="sect2"><a href="#bzbufftobuffdecompress">3.5.2. BZ2_bzBuffToBuffDecompress</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#zlib-compat">3.6. zlib compatibility functions</a></span></dt>
+<dt><span class="sect1"><a href="#stdio-free">3.7. Using the library in a stdio-free environment</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#stdio-bye">3.7.1. Getting rid of stdio</a></span></dt>
+<dt><span class="sect2"><a href="#critical-error">3.7.2. Critical error handling</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#win-dll">3.8. Making a Windows DLL</a></span></dt>
+</dl></dd>
+<dt><span class="chapter"><a href="#misc">4. Miscellanea</a></span></dt>
+<dd><dl>
+<dt><span class="sect1"><a href="#limits">4.1. Limitations of the compressed file format</a></span></dt>
+<dt><span class="sect1"><a href="#port-issues">4.2. Portability issues</a></span></dt>
+<dt><span class="sect1"><a href="#bugs">4.3. Reporting bugs</a></span></dt>
+<dt><span class="sect1"><a href="#package">4.4. Did you get the right package?</a></span></dt>
+<dt><span class="sect1"><a href="#reading">4.5. Further Reading</a></span></dt>
+</dl></dd>
+</dl>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title">
+<a name="intro"></a>1. Introduction</h2></div></div>
+<div></div>
+</div>
+<p><tt class="computeroutput">bzip2</tt> compresses files
+using the Burrows-Wheeler block-sorting text compression
+algorithm, and Huffman coding.  Compression is generally
+considerably better than that achieved by more conventional
+LZ77/LZ78-based compressors, and approaches the performance of
+the PPM family of statistical compressors.</p>
+<p><tt class="computeroutput">bzip2</tt> is built on top of
+<tt class="computeroutput">libbzip2</tt>, a flexible library for
+handling compressed data in the
+<tt class="computeroutput">bzip2</tt> format.  This manual
+describes both how to use the program and how to work with the
+library interface.  Most of the manual is devoted to this
+library, not the program, which is good news if your interest is
+only in the program.</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p><a href="#using">How to use bzip2</a> describes how to use
+ <tt class="computeroutput">bzip2</tt>; this is the only part
+ you need to read if you just want to know how to operate the
+ program.</p></li>
+<li style="list-style-type: disc"><p><a href="#libprog">Programming with libbzip2</a> describes the
+ programming interfaces in detail, and</p></li>
+<li style="list-style-type: disc"><p><a href="#misc">Miscellanea</a> records some
+ miscellaneous notes which I thought ought to be recorded
+ somewhere.</p></li>
+</ul></div>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title">
+<a name="using"></a>2. How to use bzip2</h2></div></div>
+<div></div>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a href="#name">2.1. NAME</a></span></dt>
+<dt><span class="sect1"><a href="#synopsis">2.2. SYNOPSIS</a></span></dt>
+<dt><span class="sect1"><a href="#description">2.3. DESCRIPTION</a></span></dt>
+<dt><span class="sect1"><a href="#options">2.4. OPTIONS</a></span></dt>
+<dt><span class="sect1"><a href="#memory-management">2.5. MEMORY MANAGEMENT</a></span></dt>
+<dt><span class="sect1"><a href="#recovering">2.6. RECOVERING DATA FROM DAMAGED FILES</a></span></dt>
+<dt><span class="sect1"><a href="#performance">2.7. PERFORMANCE NOTES</a></span></dt>
+<dt><span class="sect1"><a href="#caveats">2.8. CAVEATS</a></span></dt>
+<dt><span class="sect1"><a href="#author">2.9. AUTHOR</a></span></dt>
+</dl>
+</div>
+<p>This chapter contains a copy of the
+<tt class="computeroutput">bzip2</tt> man page, and nothing
+else.</p>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="name"></a>2.1. NAME</h2></div></div>
+<div></div>
+</div>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p><tt class="computeroutput">bzip2</tt>,
+  <tt class="computeroutput">bunzip2</tt> - a block-sorting file
+  compressor, v1.0.3</p></li>
+<li style="list-style-type: disc"><p><tt class="computeroutput">bzcat</tt> -
+   decompresses files to stdout</p></li>
+<li style="list-style-type: disc"><p><tt class="computeroutput">bzip2recover</tt> -
+   recovers data from damaged bzip2 files</p></li>
+</ul></div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="synopsis"></a>2.2. SYNOPSIS</h2></div></div>
+<div></div>
+</div>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p><tt class="computeroutput">bzip2</tt> [
+  -cdfkqstvzVL123456789 ] [ filenames ...  ]</p></li>
+<li style="list-style-type: disc"><p><tt class="computeroutput">bunzip2</tt> [
+  -fkvsVL ] [ filenames ...  ]</p></li>
+<li style="list-style-type: disc"><p><tt class="computeroutput">bzcat</tt> [ -s ] [
+  filenames ...  ]</p></li>
+<li style="list-style-type: disc"><p><tt class="computeroutput">bzip2recover</tt>
+  filename</p></li>
+</ul></div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="description"></a>2.3. DESCRIPTION</h2></div></div>
+<div></div>
+</div>
+<p><tt class="computeroutput">bzip2</tt> compresses files
+using the Burrows-Wheeler block sorting text compression
+algorithm, and Huffman coding.  Compression is generally
+considerably better than that achieved by more conventional
+LZ77/LZ78-based compressors, and approaches the performance of
+the PPM family of statistical compressors.</p>
+<p>The command-line options are deliberately very similar to
+those of GNU <tt class="computeroutput">gzip</tt>, but they are
+not identical.</p>
+<p><tt class="computeroutput">bzip2</tt> expects a list of
+file names to accompany the command-line flags.  Each file is
+replaced by a compressed version of itself, with the name
+<tt class="computeroutput">original_name.bz2</tt>.  Each
+compressed file has the same modification date, permissions, and,
+when possible, ownership as the corresponding original, so that
+these properties can be correctly restored at decompression time.
+File name handling is naive in the sense that there is no
+mechanism for preserving original file names, permissions,
+ownerships or dates in filesystems which lack these concepts, or
+have serious file name length restrictions, such as
+MS-DOS.</p>
+<p><tt class="computeroutput">bzip2</tt> and
+<tt class="computeroutput">bunzip2</tt> will by default not
+overwrite existing files.  If you want this to happen, specify
+the <tt class="computeroutput">-f</tt> flag.</p>
+<p>If no file names are specified,
+<tt class="computeroutput">bzip2</tt> compresses from standard
+input to standard output.  In this case,
+<tt class="computeroutput">bzip2</tt> will decline to write
+compressed output to a terminal, as this would be entirely
+incomprehensible and therefore pointless.</p>
+<p><tt class="computeroutput">bunzip2</tt> (or
+<tt class="computeroutput">bzip2 -d</tt>) decompresses all
+specified files.  Files which were not created by
+<tt class="computeroutput">bzip2</tt> will be detected and
+ignored, and a warning issued.
+<tt class="computeroutput">bzip2</tt> attempts to guess the
+filename for the decompressed file from that of the compressed
+file as follows:</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p><tt class="computeroutput">filename.bz2 </tt>
+  becomes
+  <tt class="computeroutput">filename</tt></p></li>
+<li style="list-style-type: disc"><p><tt class="computeroutput">filename.bz </tt>
+  becomes
+  <tt class="computeroutput">filename</tt></p></li>
+<li style="list-style-type: disc"><p><tt class="computeroutput">filename.tbz2</tt>
+  becomes
+  <tt class="computeroutput">filename.tar</tt></p></li>
+<li style="list-style-type: disc"><p><tt class="computeroutput">filename.tbz </tt>
+  becomes
+  <tt class="computeroutput">filename.tar</tt></p></li>
+<li style="list-style-type: disc"><p><tt class="computeroutput">anyothername </tt>
+  becomes
+  <tt class="computeroutput">anyothername.out</tt></p></li>
+</ul></div>
+<p>If the file does not end in one of the recognised endings,
+<tt class="computeroutput">.bz2</tt>,
+<tt class="computeroutput">.bz</tt>,
+<tt class="computeroutput">.tbz2</tt> or
+<tt class="computeroutput">.tbz</tt>,
+<tt class="computeroutput">bzip2</tt> complains that it cannot
+guess the name of the original file, and uses the original name
+with <tt class="computeroutput">.out</tt> appended.</p>
+<p>As with compression, supplying no filenames causes
+decompression from standard input to standard output.</p>
+<p><tt class="computeroutput">bunzip2</tt> will correctly
+decompress a file which is the concatenation of two or more
+compressed files.  The result is the concatenation of the
+corresponding uncompressed files.  Integrity testing
+(<tt class="computeroutput">-t</tt>) of concatenated compressed
+files is also supported.</p>
+<p>You can also compress or decompress files to the standard
+output by giving the <tt class="computeroutput">-c</tt> flag.
+Multiple files may be compressed and decompressed like this.  The
+resulting outputs are fed sequentially to stdout.  Compression of
+multiple files in this manner generates a stream containing
+multiple compressed file representations.  Such a stream can be
+decompressed correctly only by
+<tt class="computeroutput">bzip2</tt> version 0.9.0 or later.
+Earlier versions of <tt class="computeroutput">bzip2</tt> will
+stop after decompressing the first file in the stream.</p>
+<p><tt class="computeroutput">bzcat</tt> (or
+<tt class="computeroutput">bzip2 -dc</tt>) decompresses all
+specified files to the standard output.</p>
+<p><tt class="computeroutput">bzip2</tt> will read arguments
+from the environment variables
+<tt class="computeroutput">BZIP2</tt> and
+<tt class="computeroutput">BZIP</tt>, in that order, and will
+process them before any arguments read from the command line.
+This gives a convenient way to supply default arguments.</p>
+<p>Compression is always performed, even if the compressed
+file is slightly larger than the original.  Files of less than
+about one hundred bytes tend to get larger, since the compression
+mechanism has a constant overhead in the region of 50 bytes.
+Random data (including the output of most file compressors) is
+coded at about 8.05 bits per byte, giving an expansion of around
+0.5%.</p>
+<p>As a self-check for your protection,
+<tt class="computeroutput">bzip2</tt> uses 32-bit CRCs to make
+sure that the decompressed version of a file is identical to the
+original.  This guards against corruption of the compressed data,
+and against undetected bugs in
+<tt class="computeroutput">bzip2</tt> (hopefully very unlikely).
+The chances of data corruption going undetected is microscopic,
+about one chance in four billion for each file processed.  Be
+aware, though, that the check occurs upon decompression, so it
+can only tell you that something is wrong.  It can't help you
+recover the original uncompressed data.  You can use
+<tt class="computeroutput">bzip2recover</tt> to try to recover
+data from damaged files.</p>
+<p>Return values: 0 for a normal exit, 1 for environmental
+problems (file not found, invalid flags, I/O errors, etc.), 2
+to indicate a corrupt compressed file, 3 for an internal
+consistency error (eg, bug) which caused
+<tt class="computeroutput">bzip2</tt> to panic.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="options"></a>2.4. OPTIONS</h2></div></div>
+<div></div>
+</div>
+<div class="variablelist"><dl>
+<dt><span class="term"><tt class="computeroutput">-c --stdout</tt></span></dt>
+<dd><p>Compress or decompress to standard
+  output.</p></dd>
+<dt><span class="term"><tt class="computeroutput">-d --decompress</tt></span></dt>
+<dd><p>Force decompression.
+  <tt class="computeroutput">bzip2</tt>,
+  <tt class="computeroutput">bunzip2</tt> and
+  <tt class="computeroutput">bzcat</tt> are really the same
+  program, and the decision about what actions to take is done on
+  the basis of which name is used.  This flag overrides that
+  mechanism, and forces bzip2 to decompress.</p></dd>
+<dt><span class="term"><tt class="computeroutput">-z --compress</tt></span></dt>
+<dd><p>The complement to
+  <tt class="computeroutput">-d</tt>: forces compression,
+  regardless of the invokation name.</p></dd>
+<dt><span class="term"><tt class="computeroutput">-t --test</tt></span></dt>
+<dd><p>Check integrity of the specified file(s), but
+  don't decompress them.  This really performs a trial
+  decompression and throws away the result.</p></dd>
+<dt><span class="term"><tt class="computeroutput">-f --force</tt></span></dt>
+<dd>
+<p>Force overwrite of output files.  Normally,
+  <tt class="computeroutput">bzip2</tt> will not overwrite
+  existing output files.  Also forces
+  <tt class="computeroutput">bzip2</tt> to break hard links to
+  files, which it otherwise wouldn't do.</p>
+<p><tt class="computeroutput">bzip2</tt> normally declines
+  to decompress files which don't have the correct magic header
+  bytes. If forced (<tt class="computeroutput">-f</tt>),
+  however, it will pass such files through unmodified. This is
+  how GNU <tt class="computeroutput">gzip</tt> behaves.</p>
+</dd>
+<dt><span class="term"><tt class="computeroutput">-k --keep</tt></span></dt>
+<dd><p>Keep (don't delete) input files during
+  compression or decompression.</p></dd>
+<dt><span class="term"><tt class="computeroutput">-s --small</tt></span></dt>
+<dd>
+<p>Reduce memory usage, for compression,
+  decompression and testing.  Files are decompressed and tested
+  using a modified algorithm which only requires 2.5 bytes per
+  block byte.  This means any file can be decompressed in 2300k
+  of memory, albeit at about half the normal speed.</p>
+<p>During compression, <tt class="computeroutput">-s</tt>
+  selects a block size of 200k, which limits memory use to around
+  the same figure, at the expense of your compression ratio.  In
+  short, if your machine is low on memory (8 megabytes or less),
+  use <tt class="computeroutput">-s</tt> for everything.  See
+  <a href="#memory-management">MEMORY MANAGEMENT</a> below.</p>
+</dd>
+<dt><span class="term"><tt class="computeroutput">-q --quiet</tt></span></dt>
+<dd><p>Suppress non-essential warning messages.
+  Messages pertaining to I/O errors and other critical events
+  will not be suppressed.</p></dd>
+<dt><span class="term"><tt class="computeroutput">-v --verbose</tt></span></dt>
+<dd><p>Verbose mode -- show the compression ratio for
+  each file processed.  Further
+  <tt class="computeroutput">-v</tt>'s increase the verbosity
+  level, spewing out lots of information which is primarily of
+  interest for diagnostic purposes.</p></dd>
+<dt><span class="term"><tt class="computeroutput">-L --license -V --version</tt></span></dt>
+<dd><p>Display the software version, license terms and
+  conditions.</p></dd>
+<dt><span class="term"><tt class="computeroutput">-1</tt> (or
+ <tt class="computeroutput">--fast</tt>) to
+ <tt class="computeroutput">-9</tt> (or
+ <tt class="computeroutput">-best</tt>)</span></dt>
+<dd><p>Set the block size to 100 k, 200 k ...  900 k
+  when compressing.  Has no effect when decompressing.  See <a href="#memory-management">MEMORY MANAGEMENT</a> below.  The
+  <tt class="computeroutput">--fast</tt> and
+  <tt class="computeroutput">--best</tt> aliases are primarily
+  for GNU <tt class="computeroutput">gzip</tt> compatibility.
+  In particular, <tt class="computeroutput">--fast</tt> doesn't
+  make things significantly faster.  And
+  <tt class="computeroutput">--best</tt> merely selects the
+  default behaviour.</p></dd>
+<dt><span class="term"><tt class="computeroutput">--</tt></span></dt>
+<dd><p>Treats all subsequent arguments as file names,
+  even if they start with a dash.  This is so you can handle
+  files with names beginning with a dash, for example:
+  <tt class="computeroutput">bzip2 --
+  -myfilename</tt>.</p></dd>
+<dt>
+<span class="term"><tt class="computeroutput">--repetitive-fast</tt>, </span><span class="term"><tt class="computeroutput">--repetitive-best</tt>, </span>
+</dt>
+<dd><p>These flags are redundant in versions 0.9.5 and
+  above.  They provided some coarse control over the behaviour of
+  the sorting algorithm in earlier versions, which was sometimes
+  useful.  0.9.5 and above have an improved algorithm which
+  renders these flags irrelevant.</p></dd>
+</dl></div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="memory-management"></a>2.5. MEMORY MANAGEMENT</h2></div></div>
+<div></div>
+</div>
+<p><tt class="computeroutput">bzip2</tt> compresses large
+files in blocks.  The block size affects both the compression
+ratio achieved, and the amount of memory needed for compression
+and decompression.  The flags <tt class="computeroutput">-1</tt>
+through <tt class="computeroutput">-9</tt> specify the block
+size to be 100,000 bytes through 900,000 bytes (the default)
+respectively.  At decompression time, the block size used for
+compression is read from the header of the compressed file, and
+<tt class="computeroutput">bunzip2</tt> then allocates itself
+just enough memory to decompress the file.  Since block sizes are
+stored in compressed files, it follows that the flags
+<tt class="computeroutput">-1</tt> to
+<tt class="computeroutput">-9</tt> are irrelevant to and so
+ignored during decompression.</p>
+<p>Compression and decompression requirements, in bytes, can be
+estimated as:</p>
+<pre class="programlisting">Compression:   400k + ( 8 x block size )
+
+Decompression: 100k + ( 4 x block size ), or
+               100k + ( 2.5 x block size )</pre>
+<p>Larger block sizes give rapidly diminishing marginal
+returns.  Most of the compression comes from the first two or
+three hundred k of block size, a fact worth bearing in mind when
+using <tt class="computeroutput">bzip2</tt> on small machines.
+It is also important to appreciate that the decompression memory
+requirement is set at compression time by the choice of block
+size.</p>
+<p>For files compressed with the default 900k block size,
+<tt class="computeroutput">bunzip2</tt> will require about 3700
+kbytes to decompress.  To support decompression of any file on a
+4 megabyte machine, <tt class="computeroutput">bunzip2</tt> has
+an option to decompress using approximately half this amount of
+memory, about 2300 kbytes.  Decompression speed is also halved,
+so you should use this option only where necessary.  The relevant
+flag is <tt class="computeroutput">-s</tt>.</p>
+<p>In general, try and use the largest block size memory
+constraints allow, since that maximises the compression achieved.
+Compression and decompression speed are virtually unaffected by
+block size.</p>
+<p>Another significant point applies to files which fit in a
+single block -- that means most files you'd encounter using a
+large block size.  The amount of real memory touched is
+proportional to the size of the file, since the file is smaller
+than a block.  For example, compressing a file 20,000 bytes long
+with the flag <tt class="computeroutput">-9</tt> will cause the
+compressor to allocate around 7600k of memory, but only touch
+400k + 20000 * 8 = 560 kbytes of it.  Similarly, the decompressor
+will allocate 3700k but only touch 100k + 20000 * 4 = 180
+kbytes.</p>
+<p>Here is a table which summarises the maximum memory usage
+for different block sizes.  Also recorded is the total compressed
+size for 14 files of the Calgary Text Compression Corpus
+totalling 3,141,622 bytes.  This column gives some feel for how
+compression varies with block size.  These figures tend to
+understate the advantage of larger block sizes for larger files,
+since the Corpus is dominated by smaller files.</p>
+<pre class="programlisting">        Compress   Decompress   Decompress   Corpus
+Flag     usage      usage       -s usage     Size
+
+ -1      1200k       500k         350k      914704
+ -2      2000k       900k         600k      877703
+ -3      2800k      1300k         850k      860338
+ -4      3600k      1700k        1100k      846899
+ -5      4400k      2100k        1350k      845160
+ -6      5200k      2500k        1600k      838626
+ -7      6100k      2900k        1850k      834096
+ -8      6800k      3300k        2100k      828642
+ -9      7600k      3700k        2350k      828642</pre>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="recovering"></a>2.6. RECOVERING DATA FROM DAMAGED FILES</h2></div></div>
+<div></div>
+</div>
+<p><tt class="computeroutput">bzip2</tt> compresses files in
+blocks, usually 900kbytes long.  Each block is handled
+independently.  If a media or transmission error causes a
+multi-block <tt class="computeroutput">.bz2</tt> file to become
+damaged, it may be possible to recover data from the undamaged
+blocks in the file.</p>
+<p>The compressed representation of each block is delimited by
+a 48-bit pattern, which makes it possible to find the block
+boundaries with reasonable certainty.  Each block also carries
+its own 32-bit CRC, so damaged blocks can be distinguished from
+undamaged ones.</p>
+<p><tt class="computeroutput">bzip2recover</tt> is a simple
+program whose purpose is to search for blocks in
+<tt class="computeroutput">.bz2</tt> files, and write each block
+out into its own <tt class="computeroutput">.bz2</tt> file.  You
+can then use <tt class="computeroutput">bzip2 -t</tt> to test
+the integrity of the resulting files, and decompress those which
+are undamaged.</p>
+<p><tt class="computeroutput">bzip2recover</tt> takes a
+single argument, the name of the damaged file, and writes a
+number of files <tt class="computeroutput">rec0001file.bz2</tt>,
+<tt class="computeroutput">rec0002file.bz2</tt>, etc, containing
+the extracted blocks.  The output filenames are designed so that
+the use of wildcards in subsequent processing -- for example,
+<tt class="computeroutput">bzip2 -dc rec*file.bz2 &gt;
+recovered_data</tt> -- lists the files in the correct
+order.</p>
+<p><tt class="computeroutput">bzip2recover</tt> should be of
+most use dealing with large <tt class="computeroutput">.bz2</tt>
+files, as these will contain many blocks.  It is clearly futile
+to use it on damaged single-block files, since a damaged block
+cannot be recovered.  If you wish to minimise any potential data
+loss through media or transmission errors, you might consider
+compressing with a smaller block size.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="performance"></a>2.7. PERFORMANCE NOTES</h2></div></div>
+<div></div>
+</div>
+<p>The sorting phase of compression gathers together similar
+strings in the file.  Because of this, files containing very long
+runs of repeated symbols, like "aabaabaabaab ..."  (repeated
+several hundred times) may compress more slowly than normal.
+Versions 0.9.5 and above fare much better than previous versions
+in this respect.  The ratio between worst-case and average-case
+compression time is in the region of 10:1.  For previous
+versions, this figure was more like 100:1.  You can use the
+<tt class="computeroutput">-vvvv</tt> option to monitor progress
+in great detail, if you want.</p>
+<p>Decompression speed is unaffected by these
+phenomena.</p>
+<p><tt class="computeroutput">bzip2</tt> usually allocates
+several megabytes of memory to operate in, and then charges all
+over it in a fairly random fashion.  This means that performance,
+both for compressing and decompressing, is largely determined by
+the speed at which your machine can service cache misses.
+Because of this, small changes to the code to reduce the miss
+rate have been observed to give disproportionately large
+performance improvements.  I imagine
+<tt class="computeroutput">bzip2</tt> will perform best on
+machines with very large caches.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="caveats"></a>2.8. CAVEATS</h2></div></div>
+<div></div>
+</div>
+<p>I/O error messages are not as helpful as they could be.
+<tt class="computeroutput">bzip2</tt> tries hard to detect I/O
+errors and exit cleanly, but the details of what the problem is
+sometimes seem rather misleading.</p>
+<p>This manual page pertains to version 1.0.3 of
+<tt class="computeroutput">bzip2</tt>.  Compressed data created
+by this version is entirely forwards and backwards compatible
+with the previous public releases, versions 0.1pl2, 0.9.0 and
+0.9.5, 1.0.0, 1.0.1 and 1.0.2, but with the following exception: 0.9.0
+and above can correctly decompress multiple concatenated
+compressed files.  0.1pl2 cannot do this; it will stop after
+decompressing just the first file in the stream.</p>
+<p><tt class="computeroutput">bzip2recover</tt> versions
+prior to 1.0.2 used 32-bit integers to represent bit positions in
+compressed files, so it could not handle compressed files more
+than 512 megabytes long.  Versions 1.0.2 and above use 64-bit ints
+on some platforms which support them (GNU supported targets, and
+Windows). To establish whether or not
+<tt class="computeroutput">bzip2recover</tt> was built with such
+a limitation, run it without arguments. In any event you can
+build yourself an unlimited version if you can recompile it with
+<tt class="computeroutput">MaybeUInt64</tt> set to be an
+unsigned 64-bit integer.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="author"></a>2.9. AUTHOR</h2></div></div>
+<div></div>
+</div>
+<p>Julian Seward,
+<tt class="computeroutput">jseward@bzip.org</tt></p>
+<p>The ideas embodied in
+<tt class="computeroutput">bzip2</tt> are due to (at least) the
+following people: Michael Burrows and David Wheeler (for the
+block sorting transformation), David Wheeler (again, for the
+Huffman coder), Peter Fenwick (for the structured coding model in
+the original <tt class="computeroutput">bzip</tt>, and many
+refinements), and Alistair Moffat, Radford Neal and Ian Witten
+(for the arithmetic coder in the original
+<tt class="computeroutput">bzip</tt>).  I am much indebted for
+their help, support and advice.  See the manual in the source
+distribution for pointers to sources of documentation.  Christian
+von Roques encouraged me to look for faster sorting algorithms,
+so as to speed up compression.  Bela Lubkin encouraged me to
+improve the worst-case compression performance.  
+Donna Robinson XMLised the documentation.
+Many people sent
+patches, helped with portability problems, lent machines, gave
+advice and were generally helpful.</p>
+</div>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title">
+<a name="libprog"></a>3. 
+Programming with <tt class="computeroutput">libbzip2</tt>
+</h2></div></div>
+<div></div>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a href="#top-level">3.1. Top-level structure</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#ll-summary">3.1.1. Low-level summary</a></span></dt>
+<dt><span class="sect2"><a href="#hl-summary">3.1.2. High-level summary</a></span></dt>
+<dt><span class="sect2"><a href="#util-fns-summary">3.1.3. Utility functions summary</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#err-handling">3.2. Error handling</a></span></dt>
+<dt><span class="sect1"><a href="#low-level">3.3. Low-level interface</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#bzcompress-init">3.3.1. BZ2_bzCompressInit</a></span></dt>
+<dt><span class="sect2"><a href="#bzCompress">3.3.2. BZ2_bzCompress</a></span></dt>
+<dt><span class="sect2"><a href="#bzCompress-end">3.3.3. BZ2_bzCompressEnd</a></span></dt>
+<dt><span class="sect2"><a href="#bzDecompress-init">3.3.4. BZ2_bzDecompressInit</a></span></dt>
+<dt><span class="sect2"><a href="#bzDecompress">3.3.5. BZ2_bzDecompress</a></span></dt>
+<dt><span class="sect2"><a href="#bzDecompress-end">3.3.6. BZ2_bzDecompressEnd</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#hl-interface">3.4. High-level interface</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#bzreadopen">3.4.1. BZ2_bzReadOpen</a></span></dt>
+<dt><span class="sect2"><a href="#bzread">3.4.2. BZ2_bzRead</a></span></dt>
+<dt><span class="sect2"><a href="#bzreadgetunused">3.4.3. BZ2_bzReadGetUnused</a></span></dt>
+<dt><span class="sect2"><a href="#bzreadclose">3.4.4. BZ2_bzReadClose</a></span></dt>
+<dt><span class="sect2"><a href="#bzwriteopen">3.4.5. BZ2_bzWriteOpen</a></span></dt>
+<dt><span class="sect2"><a href="#bzwrite">3.4.6. BZ2_bzWrite</a></span></dt>
+<dt><span class="sect2"><a href="#bzwriteclose">3.4.7. BZ2_bzWriteClose</a></span></dt>
+<dt><span class="sect2"><a href="#embed">3.4.8. Handling embedded compressed data streams</a></span></dt>
+<dt><span class="sect2"><a href="#std-rdwr">3.4.9. Standard file-reading/writing code</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#util-fns">3.5. Utility functions</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#bzbufftobuffcompress">3.5.1. BZ2_bzBuffToBuffCompress</a></span></dt>
+<dt><span class="sect2"><a href="#bzbufftobuffdecompress">3.5.2. BZ2_bzBuffToBuffDecompress</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#zlib-compat">3.6. zlib compatibility functions</a></span></dt>
+<dt><span class="sect1"><a href="#stdio-free">3.7. Using the library in a stdio-free environment</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#stdio-bye">3.7.1. Getting rid of stdio</a></span></dt>
+<dt><span class="sect2"><a href="#critical-error">3.7.2. Critical error handling</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#win-dll">3.8. Making a Windows DLL</a></span></dt>
+</dl>
+</div>
+<p>This chapter describes the programming interface to
+<tt class="computeroutput">libbzip2</tt>.</p>
+<p>For general background information, particularly about
+memory use and performance aspects, you'd be well advised to read
+<a href="#using">How to use bzip2</a> as well.</p>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="top-level"></a>3.1. Top-level structure</h2></div></div>
+<div></div>
+</div>
+<p><tt class="computeroutput">libbzip2</tt> is a flexible
+library for compressing and decompressing data in the
+<tt class="computeroutput">bzip2</tt> data format.  Although
+packaged as a single entity, it helps to regard the library as
+three separate parts: the low level interface, and the high level
+interface, and some utility functions.</p>
+<p>The structure of
+<tt class="computeroutput">libbzip2</tt>'s interfaces is similar
+to that of Jean-loup Gailly's and Mark Adler's excellent
+<tt class="computeroutput">zlib</tt> library.</p>
+<p>All externally visible symbols have names beginning
+<tt class="computeroutput">BZ2_</tt>.  This is new in version
+1.0.  The intention is to minimise pollution of the namespaces of
+library clients.</p>
+<p>To use any part of the library, you need to
+<tt class="computeroutput">#include &lt;bzlib.h&gt;</tt>
+into your sources.</p>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="ll-summary"></a>3.1.1. Low-level summary</h3></div></div>
+<div></div>
+</div>
+<p>This interface provides services for compressing and
+decompressing data in memory.  There's no provision for dealing
+with files, streams or any other I/O mechanisms, just straight
+memory-to-memory work.  In fact, this part of the library can be
+compiled without inclusion of
+<tt class="computeroutput">stdio.h</tt>, which may be helpful
+for embedded applications.</p>
+<p>The low-level part of the library has no global variables
+and is therefore thread-safe.</p>
+<p>Six routines make up the low level interface:
+<tt class="computeroutput">BZ2_bzCompressInit</tt>,
+<tt class="computeroutput">BZ2_bzCompress</tt>, and
+<tt class="computeroutput">BZ2_bzCompressEnd</tt> for
+compression, and a corresponding trio
+<tt class="computeroutput">BZ2_bzDecompressInit</tt>,
+<tt class="computeroutput">BZ2_bzDecompress</tt> and
+<tt class="computeroutput">BZ2_bzDecompressEnd</tt> for
+decompression.  The <tt class="computeroutput">*Init</tt>
+functions allocate memory for compression/decompression and do
+other initialisations, whilst the
+<tt class="computeroutput">*End</tt> functions close down
+operations and release memory.</p>
+<p>The real work is done by
+<tt class="computeroutput">BZ2_bzCompress</tt> and
+<tt class="computeroutput">BZ2_bzDecompress</tt>.  These
+compress and decompress data from a user-supplied input buffer to
+a user-supplied output buffer.  These buffers can be any size;
+arbitrary quantities of data are handled by making repeated calls
+to these functions.  This is a flexible mechanism allowing a
+consumer-pull style of activity, or producer-push, or a mixture
+of both.</p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="hl-summary"></a>3.1.2. High-level summary</h3></div></div>
+<div></div>
+</div>
+<p>This interface provides some handy wrappers around the
+low-level interface to facilitate reading and writing
+<tt class="computeroutput">bzip2</tt> format files
+(<tt class="computeroutput">.bz2</tt> files).  The routines
+provide hooks to facilitate reading files in which the
+<tt class="computeroutput">bzip2</tt> data stream is embedded
+within some larger-scale file structure, or where there are
+multiple <tt class="computeroutput">bzip2</tt> data streams
+concatenated end-to-end.</p>
+<p>For reading files,
+<tt class="computeroutput">BZ2_bzReadOpen</tt>,
+<tt class="computeroutput">BZ2_bzRead</tt>,
+<tt class="computeroutput">BZ2_bzReadClose</tt> and 
+<tt class="computeroutput">BZ2_bzReadGetUnused</tt> are
+supplied.  For writing files,
+<tt class="computeroutput">BZ2_bzWriteOpen</tt>,
+<tt class="computeroutput">BZ2_bzWrite</tt> and
+<tt class="computeroutput">BZ2_bzWriteFinish</tt> are
+available.</p>
+<p>As with the low-level library, no global variables are used
+so the library is per se thread-safe.  However, if I/O errors
+occur whilst reading or writing the underlying compressed files,
+you may have to consult <tt class="computeroutput">errno</tt> to
+determine the cause of the error.  In that case, you'd need a C
+library which correctly supports
+<tt class="computeroutput">errno</tt> in a multithreaded
+environment.</p>
+<p>To make the library a little simpler and more portable,
+<tt class="computeroutput">BZ2_bzReadOpen</tt> and
+<tt class="computeroutput">BZ2_bzWriteOpen</tt> require you to
+pass them file handles (<tt class="computeroutput">FILE*</tt>s)
+which have previously been opened for reading or writing
+respectively.  That avoids portability problems associated with
+file operations and file attributes, whilst not being much of an
+imposition on the programmer.</p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="util-fns-summary"></a>3.1.3. Utility functions summary</h3></div></div>
+<div></div>
+</div>
+<p>For very simple needs,
+<tt class="computeroutput">BZ2_bzBuffToBuffCompress</tt> and
+<tt class="computeroutput">BZ2_bzBuffToBuffDecompress</tt> are
+provided.  These compress data in memory from one buffer to
+another buffer in a single function call.  You should assess
+whether these functions fulfill your memory-to-memory
+compression/decompression requirements before investing effort in
+understanding the more general but more complex low-level
+interface.</p>
+<p>Yoshioka Tsuneo
+(<tt class="computeroutput">QWF00133@niftyserve.or.jp</tt> /
+<tt class="computeroutput">tsuneo-y@is.aist-nara.ac.jp</tt>) has
+contributed some functions to give better
+<tt class="computeroutput">zlib</tt> compatibility.  These
+functions are <tt class="computeroutput">BZ2_bzopen</tt>,
+<tt class="computeroutput">BZ2_bzread</tt>,
+<tt class="computeroutput">BZ2_bzwrite</tt>,
+<tt class="computeroutput">BZ2_bzflush</tt>,
+<tt class="computeroutput">BZ2_bzclose</tt>,
+<tt class="computeroutput">BZ2_bzerror</tt> and
+<tt class="computeroutput">BZ2_bzlibVersion</tt>.  You may find
+these functions more convenient for simple file reading and
+writing, than those in the high-level interface.  These functions
+are not (yet) officially part of the library, and are minimally
+documented here.  If they break, you get to keep all the pieces.
+I hope to document them properly when time permits.</p>
+<p>Yoshioka also contributed modifications to allow the
+library to be built as a Windows DLL.</p>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="err-handling"></a>3.2. Error handling</h2></div></div>
+<div></div>
+</div>
+<p>The library is designed to recover cleanly in all
+situations, including the worst-case situation of decompressing
+random data.  I'm not 100% sure that it can always do this, so
+you might want to add a signal handler to catch segmentation
+violations during decompression if you are feeling especially
+paranoid.  I would be interested in hearing more about the
+robustness of the library to corrupted compressed data.</p>
+<p>Version 1.0.3 more robust in this respect than any
+previous version.  Investigations with Valgrind (a tool for detecting
+problems with memory management) indicate
+that, at least for the few files I tested, all single-bit errors
+in the decompressed data are caught properly, with no
+segmentation faults, no uses of uninitialised data, no out of
+range reads or writes, and no infinite looping in the decompressor.
+So it's certainly pretty robust, although
+I wouldn't claim it to be totally bombproof.</p>
+<p>The file <tt class="computeroutput">bzlib.h</tt> contains
+all definitions needed to use the library.  In particular, you
+should definitely not include
+<tt class="computeroutput">bzlib_private.h</tt>.</p>
+<p>In <tt class="computeroutput">bzlib.h</tt>, the various
+return values are defined.  The following list is not intended as
+an exhaustive description of the circumstances in which a given
+value may be returned -- those descriptions are given later.
+Rather, it is intended to convey the rough meaning of each return
+value.  The first five actions are normal and not intended to
+denote an error situation.</p>
+<div class="variablelist"><dl>
+<dt><span class="term"><tt class="computeroutput">BZ_OK</tt></span></dt>
+<dd><p>The requested action was completed
+   successfully.</p></dd>
+<dt><span class="term"><tt class="computeroutput">BZ_RUN_OK, BZ_FLUSH_OK,
+    BZ_FINISH_OK</tt></span></dt>
+<dd><p>In 
+   <tt class="computeroutput">BZ2_bzCompress</tt>, the requested
+   flush/finish/nothing-special action was completed
+   successfully.</p></dd>
+<dt><span class="term"><tt class="computeroutput">BZ_STREAM_END</tt></span></dt>
+<dd><p>Compression of data was completed, or the
+   logical stream end was detected during
+   decompression.</p></dd>
+</dl></div>
+<p>The following return values indicate an error of some
+kind.</p>
+<div class="variablelist"><dl>
+<dt><span class="term"><tt class="computeroutput">BZ_CONFIG_ERROR</tt></span></dt>
+<dd><p>Indicates that the library has been improperly
+   compiled on your platform -- a major configuration error.
+   Specifically, it means that
+   <tt class="computeroutput">sizeof(char)</tt>,
+   <tt class="computeroutput">sizeof(short)</tt> and
+   <tt class="computeroutput">sizeof(int)</tt> are not 1, 2 and
+   4 respectively, as they should be.  Note that the library
+   should still work properly on 64-bit platforms which follow
+   the LP64 programming model -- that is, where
+   <tt class="computeroutput">sizeof(long)</tt> and
+   <tt class="computeroutput">sizeof(void*)</tt> are 8.  Under
+   LP64, <tt class="computeroutput">sizeof(int)</tt> is still 4,
+   so <tt class="computeroutput">libbzip2</tt>, which doesn't
+   use the <tt class="computeroutput">long</tt> type, is
+   OK.</p></dd>
+<dt><span class="term"><tt class="computeroutput">BZ_SEQUENCE_ERROR</tt></span></dt>
+<dd><p>When using the library, it is important to call
+   the functions in the correct sequence and with data structures
+   (buffers etc) in the correct states.
+   <tt class="computeroutput">libbzip2</tt> checks as much as it
+   can to ensure this is happening, and returns
+   <tt class="computeroutput">BZ_SEQUENCE_ERROR</tt> if not.
+   Code which complies precisely with the function semantics, as
+   detailed below, should never receive this value; such an event
+   denotes buggy code which you should
+   investigate.</p></dd>
+<dt><span class="term"><tt class="computeroutput">BZ_PARAM_ERROR</tt></span></dt>
+<dd><p>Returned when a parameter to a function call is
+   out of range or otherwise manifestly incorrect.  As with
+   <tt class="computeroutput">BZ_SEQUENCE_ERROR</tt>, this
+   denotes a bug in the client code.  The distinction between
+   <tt class="computeroutput">BZ_PARAM_ERROR</tt> and
+   <tt class="computeroutput">BZ_SEQUENCE_ERROR</tt> is a bit
+   hazy, but still worth making.</p></dd>
+<dt><span class="term"><tt class="computeroutput">BZ_MEM_ERROR</tt></span></dt>
+<dd><p>Returned when a request to allocate memory
+   failed.  Note that the quantity of memory needed to decompress
+   a stream cannot be determined until the stream's header has
+   been read.  So
+   <tt class="computeroutput">BZ2_bzDecompress</tt> and
+   <tt class="computeroutput">BZ2_bzRead</tt> may return
+   <tt class="computeroutput">BZ_MEM_ERROR</tt> even though some
+   of the compressed data has been read.  The same is not true
+   for compression; once
+   <tt class="computeroutput">BZ2_bzCompressInit</tt> or
+   <tt class="computeroutput">BZ2_bzWriteOpen</tt> have
+   successfully completed,
+   <tt class="computeroutput">BZ_MEM_ERROR</tt> cannot
+   occur.</p></dd>
+<dt><span class="term"><tt class="computeroutput">BZ_DATA_ERROR</tt></span></dt>
+<dd><p>Returned when a data integrity error is
+   detected during decompression.  Most importantly, this means
+   when stored and computed CRCs for the data do not match.  This
+   value is also returned upon detection of any other anomaly in
+   the compressed data.</p></dd>
+<dt><span class="term"><tt class="computeroutput">BZ_DATA_ERROR_MAGIC</tt></span></dt>
+<dd><p>As a special case of
+   <tt class="computeroutput">BZ_DATA_ERROR</tt>, it is
+   sometimes useful to know when the compressed stream does not
+   start with the correct magic bytes (<tt class="computeroutput">'B' 'Z'
+   'h'</tt>).</p></dd>
+<dt><span class="term"><tt class="computeroutput">BZ_IO_ERROR</tt></span></dt>
+<dd><p>Returned by
+   <tt class="computeroutput">BZ2_bzRead</tt> and
+   <tt class="computeroutput">BZ2_bzWrite</tt> when there is an
+   error reading or writing in the compressed file, and by
+   <tt class="computeroutput">BZ2_bzReadOpen</tt> and
+   <tt class="computeroutput">BZ2_bzWriteOpen</tt> for attempts
+   to use a file for which the error indicator (viz,
+   <tt class="computeroutput">ferror(f)</tt>) is set.  On
+   receipt of <tt class="computeroutput">BZ_IO_ERROR</tt>, the
+   caller should consult <tt class="computeroutput">errno</tt>
+   and/or <tt class="computeroutput">perror</tt> to acquire
+   operating-system specific information about the
+   problem.</p></dd>
+<dt><span class="term"><tt class="computeroutput">BZ_UNEXPECTED_EOF</tt></span></dt>
+<dd><p>Returned by
+   <tt class="computeroutput">BZ2_bzRead</tt> when the
+   compressed file finishes before the logical end of stream is
+   detected.</p></dd>
+<dt><span class="term"><tt class="computeroutput">BZ_OUTBUFF_FULL</tt></span></dt>
+<dd><p>Returned by
+   <tt class="computeroutput">BZ2_bzBuffToBuffCompress</tt> and
+   <tt class="computeroutput">BZ2_bzBuffToBuffDecompress</tt> to
+   indicate that the output data will not fit into the output
+   buffer provided.</p></dd>
+</dl></div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="low-level"></a>3.3. Low-level interface</h2></div></div>
+<div></div>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bzcompress-init"></a>3.3.1. <tt class="computeroutput">BZ2_bzCompressInit</tt></h3></div></div>
+<div></div>
+</div>
+<pre class="programlisting">typedef struct {
+  char *next_in;
+  unsigned int avail_in;
+  unsigned int total_in_lo32;
+  unsigned int total_in_hi32;
+
+  char *next_out;
+  unsigned int avail_out;
+  unsigned int total_out_lo32;
+  unsigned int total_out_hi32;
+
+  void *state;
+
+  void *(*bzalloc)(void *,int,int);
+  void (*bzfree)(void *,void *);
+  void *opaque;
+} bz_stream;
+
+int BZ2_bzCompressInit ( bz_stream *strm, 
+                         int blockSize100k, 
+                         int verbosity,
+                         int workFactor );</pre>
+<p>Prepares for compression.  The
+<tt class="computeroutput">bz_stream</tt> structure holds all
+data pertaining to the compression activity.  A
+<tt class="computeroutput">bz_stream</tt> structure should be
+allocated and initialised prior to the call.  The fields of
+<tt class="computeroutput">bz_stream</tt> comprise the entirety
+of the user-visible data.  <tt class="computeroutput">state</tt>
+is a pointer to the private data structures required for
+compression.</p>
+<p>Custom memory allocators are supported, via fields
+<tt class="computeroutput">bzalloc</tt>,
+<tt class="computeroutput">bzfree</tt>, and
+<tt class="computeroutput">opaque</tt>.  The value
+<tt class="computeroutput">opaque</tt> is passed to as the first
+argument to all calls to <tt class="computeroutput">bzalloc</tt>
+and <tt class="computeroutput">bzfree</tt>, but is otherwise
+ignored by the library.  The call <tt class="computeroutput">bzalloc (
+opaque, n, m )</tt> is expected to return a pointer
+<tt class="computeroutput">p</tt> to <tt class="computeroutput">n *
+m</tt> bytes of memory, and <tt class="computeroutput">bzfree (
+opaque, p )</tt> should free that memory.</p>
+<p>If you don't want to use a custom memory allocator, set
+<tt class="computeroutput">bzalloc</tt>,
+<tt class="computeroutput">bzfree</tt> and
+<tt class="computeroutput">opaque</tt> to
+<tt class="computeroutput">NULL</tt>, and the library will then
+use the standard <tt class="computeroutput">malloc</tt> /
+<tt class="computeroutput">free</tt> routines.</p>
+<p>Before calling
+<tt class="computeroutput">BZ2_bzCompressInit</tt>, fields
+<tt class="computeroutput">bzalloc</tt>,
+<tt class="computeroutput">bzfree</tt> and
+<tt class="computeroutput">opaque</tt> should be filled
+appropriately, as just described.  Upon return, the internal
+state will have been allocated and initialised, and
+<tt class="computeroutput">total_in_lo32</tt>,
+<tt class="computeroutput">total_in_hi32</tt>,
+<tt class="computeroutput">total_out_lo32</tt> and
+<tt class="computeroutput">total_out_hi32</tt> will have been
+set to zero.  These four fields are used by the library to inform
+the caller of the total amount of data passed into and out of the
+library, respectively.  You should not try to change them.  As of
+version 1.0, 64-bit counts are maintained, even on 32-bit
+platforms, using the <tt class="computeroutput">_hi32</tt>
+fields to store the upper 32 bits of the count.  So, for example,
+the total amount of data in is <tt class="computeroutput">(total_in_hi32
+&lt;&lt; 32) + total_in_lo32</tt>.</p>
+<p>Parameter <tt class="computeroutput">blockSize100k</tt>
+specifies the block size to be used for compression.  It should
+be a value between 1 and 9 inclusive, and the actual block size
+used is 100000 x this figure.  9 gives the best compression but
+takes most memory.</p>
+<p>Parameter <tt class="computeroutput">verbosity</tt> should
+be set to a number between 0 and 4 inclusive.  0 is silent, and
+greater numbers give increasingly verbose monitoring/debugging
+output.  If the library has been compiled with
+<tt class="computeroutput">-DBZ_NO_STDIO</tt>, no such output
+will appear for any verbosity setting.</p>
+<p>Parameter <tt class="computeroutput">workFactor</tt>
+controls how the compression phase behaves when presented with
+worst case, highly repetitive, input data.  If compression runs
+into difficulties caused by repetitive data, the library switches
+from the standard sorting algorithm to a fallback algorithm.  The
+fallback is slower than the standard algorithm by perhaps a
+factor of three, but always behaves reasonably, no matter how bad
+the input.</p>
+<p>Lower values of <tt class="computeroutput">workFactor</tt>
+reduce the amount of effort the standard algorithm will expend
+before resorting to the fallback.  You should set this parameter
+carefully; too low, and many inputs will be handled by the
+fallback algorithm and so compress rather slowly, too high, and
+your average-to-worst case compression times can become very
+large.  The default value of 30 gives reasonable behaviour over a
+wide range of circumstances.</p>
+<p>Allowable values range from 0 to 250 inclusive.  0 is a
+special case, equivalent to using the default value of 30.</p>
+<p>Note that the compressed output generated is the same
+regardless of whether or not the fallback algorithm is
+used.</p>
+<p>Be aware also that this parameter may disappear entirely in
+future versions of the library.  In principle it should be
+possible to devise a good way to automatically choose which
+algorithm to use.  Such a mechanism would render the parameter
+obsolete.</p>
+<p>Possible return values:</p>
+<pre class="programlisting">BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if strm is NULL 
+  or blockSize &lt; 1 or blockSize &gt; 9
+  or verbosity &lt; 0 or verbosity &gt; 4
+  or workFactor &lt; 0 or workFactor &gt; 250
+BZ_MEM_ERROR 
+  if not enough memory is available
+BZ_OK 
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">BZ2_bzCompress
+  if BZ_OK is returned
+  no specific action needed in case of error</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bzCompress"></a>3.3.2. <tt class="computeroutput">BZ2_bzCompress</tt></h3></div></div>
+<div></div>
+</div>
+<pre class="programlisting">int BZ2_bzCompress ( bz_stream *strm, int action );</pre>
+<p>Provides more input and/or output buffer space for the
+library.  The caller maintains input and output buffers, and
+calls <tt class="computeroutput">BZ2_bzCompress</tt> to transfer
+data between them.</p>
+<p>Before each call to
+<tt class="computeroutput">BZ2_bzCompress</tt>,
+<tt class="computeroutput">next_in</tt> should point at the data
+to be compressed, and <tt class="computeroutput">avail_in</tt>
+should indicate how many bytes the library may read.
+<tt class="computeroutput">BZ2_bzCompress</tt> updates
+<tt class="computeroutput">next_in</tt>,
+<tt class="computeroutput">avail_in</tt> and
+<tt class="computeroutput">total_in</tt> to reflect the number
+of bytes it has read.</p>
+<p>Similarly, <tt class="computeroutput">next_out</tt> should
+point to a buffer in which the compressed data is to be placed,
+with <tt class="computeroutput">avail_out</tt> indicating how
+much output space is available.
+<tt class="computeroutput">BZ2_bzCompress</tt> updates
+<tt class="computeroutput">next_out</tt>,
+<tt class="computeroutput">avail_out</tt> and
+<tt class="computeroutput">total_out</tt> to reflect the number
+of bytes output.</p>
+<p>You may provide and remove as little or as much data as you
+like on each call of
+<tt class="computeroutput">BZ2_bzCompress</tt>.  In the limit,
+it is acceptable to supply and remove data one byte at a time,
+although this would be terribly inefficient.  You should always
+ensure that at least one byte of output space is available at
+each call.</p>
+<p>A second purpose of
+<tt class="computeroutput">BZ2_bzCompress</tt> is to request a
+change of mode of the compressed stream.</p>
+<p>Conceptually, a compressed stream can be in one of four
+states: IDLE, RUNNING, FLUSHING and FINISHING.  Before
+initialisation
+(<tt class="computeroutput">BZ2_bzCompressInit</tt>) and after
+termination (<tt class="computeroutput">BZ2_bzCompressEnd</tt>),
+a stream is regarded as IDLE.</p>
+<p>Upon initialisation
+(<tt class="computeroutput">BZ2_bzCompressInit</tt>), the stream
+is placed in the RUNNING state.  Subsequent calls to
+<tt class="computeroutput">BZ2_bzCompress</tt> should pass
+<tt class="computeroutput">BZ_RUN</tt> as the requested action;
+other actions are illegal and will result in
+<tt class="computeroutput">BZ_SEQUENCE_ERROR</tt>.</p>
+<p>At some point, the calling program will have provided all
+the input data it wants to.  It will then want to finish up -- in
+effect, asking the library to process any data it might have
+buffered internally.  In this state,
+<tt class="computeroutput">BZ2_bzCompress</tt> will no longer
+attempt to read data from
+<tt class="computeroutput">next_in</tt>, but it will want to
+write data to <tt class="computeroutput">next_out</tt>.  Because
+the output buffer supplied by the user can be arbitrarily small,
+the finishing-up operation cannot necessarily be done with a
+single call of
+<tt class="computeroutput">BZ2_bzCompress</tt>.</p>
+<p>Instead, the calling program passes
+<tt class="computeroutput">BZ_FINISH</tt> as an action to
+<tt class="computeroutput">BZ2_bzCompress</tt>.  This changes
+the stream's state to FINISHING.  Any remaining input (ie,
+<tt class="computeroutput">next_in[0 .. avail_in-1]</tt>) is
+compressed and transferred to the output buffer.  To do this,
+<tt class="computeroutput">BZ2_bzCompress</tt> must be called
+repeatedly until all the output has been consumed.  At that
+point, <tt class="computeroutput">BZ2_bzCompress</tt> returns
+<tt class="computeroutput">BZ_STREAM_END</tt>, and the stream's
+state is set back to IDLE.
+<tt class="computeroutput">BZ2_bzCompressEnd</tt> should then be
+called.</p>
+<p>Just to make sure the calling program does not cheat, the
+library makes a note of <tt class="computeroutput">avail_in</tt>
+at the time of the first call to
+<tt class="computeroutput">BZ2_bzCompress</tt> which has
+<tt class="computeroutput">BZ_FINISH</tt> as an action (ie, at
+the time the program has announced its intention to not supply
+any more input).  By comparing this value with that of
+<tt class="computeroutput">avail_in</tt> over subsequent calls
+to <tt class="computeroutput">BZ2_bzCompress</tt>, the library
+can detect any attempts to slip in more data to compress.  Any
+calls for which this is detected will return
+<tt class="computeroutput">BZ_SEQUENCE_ERROR</tt>.  This
+indicates a programming mistake which should be corrected.</p>
+<p>Instead of asking to finish, the calling program may ask
+<tt class="computeroutput">BZ2_bzCompress</tt> to take all the
+remaining input, compress it and terminate the current
+(Burrows-Wheeler) compression block.  This could be useful for
+error control purposes.  The mechanism is analogous to that for
+finishing: call <tt class="computeroutput">BZ2_bzCompress</tt>
+with an action of <tt class="computeroutput">BZ_FLUSH</tt>,
+remove output data, and persist with the
+<tt class="computeroutput">BZ_FLUSH</tt> action until the value
+<tt class="computeroutput">BZ_RUN</tt> is returned.  As with
+finishing, <tt class="computeroutput">BZ2_bzCompress</tt>
+detects any attempt to provide more input data once the flush has
+begun.</p>
+<p>Once the flush is complete, the stream returns to the
+normal RUNNING state.</p>
+<p>This all sounds pretty complex, but isn't really.  Here's a
+table which shows which actions are allowable in each state, what
+action will be taken, what the next state is, and what the
+non-error return values are.  Note that you can't explicitly ask
+what state the stream is in, but nor do you need to -- it can be
+inferred from the values returned by
+<tt class="computeroutput">BZ2_bzCompress</tt>.</p>
+<pre class="programlisting">IDLE/any
+  Illegal.  IDLE state only exists after BZ2_bzCompressEnd or
+  before BZ2_bzCompressInit.
+  Return value = BZ_SEQUENCE_ERROR
+
+RUNNING/BZ_RUN
+  Compress from next_in to next_out as much as possible.
+  Next state = RUNNING
+  Return value = BZ_RUN_OK
+
+RUNNING/BZ_FLUSH
+  Remember current value of next_in. Compress from next_in
+  to next_out as much as possible, but do not accept any more input.
+  Next state = FLUSHING
+  Return value = BZ_FLUSH_OK
+
+RUNNING/BZ_FINISH
+  Remember current value of next_in. Compress from next_in
+  to next_out as much as possible, but do not accept any more input.
+  Next state = FINISHING
+  Return value = BZ_FINISH_OK
+
+FLUSHING/BZ_FLUSH
+  Compress from next_in to next_out as much as possible, 
+  but do not accept any more input.
+  If all the existing input has been used up and all compressed
+  output has been removed
+    Next state = RUNNING; Return value = BZ_RUN_OK
+  else
+    Next state = FLUSHING; Return value = BZ_FLUSH_OK
+
+FLUSHING/other     
+  Illegal.
+  Return value = BZ_SEQUENCE_ERROR
+
+FINISHING/BZ_FINISH
+  Compress from next_in to next_out as much as possible,
+  but to not accept any more input.  
+  If all the existing input has been used up and all compressed
+  output has been removed
+    Next state = IDLE; Return value = BZ_STREAM_END
+  else
+    Next state = FINISHING; Return value = BZ_FINISHING
+
+FINISHING/other
+  Illegal.
+  Return value = BZ_SEQUENCE_ERROR</pre>
+<p>That still looks complicated?  Well, fair enough.  The
+usual sequence of calls for compressing a load of data is:</p>
+<div class="orderedlist"><ol type="1">
+<li><p>Get started with
+  <tt class="computeroutput">BZ2_bzCompressInit</tt>.</p></li>
+<li><p>Shovel data in and shlurp out its compressed form
+  using zero or more calls of
+  <tt class="computeroutput">BZ2_bzCompress</tt> with action =
+  <tt class="computeroutput">BZ_RUN</tt>.</p></li>
+<li><p>Finish up. Repeatedly call
+  <tt class="computeroutput">BZ2_bzCompress</tt> with action =
+  <tt class="computeroutput">BZ_FINISH</tt>, copying out the
+  compressed output, until
+  <tt class="computeroutput">BZ_STREAM_END</tt> is
+  returned.</p></li>
+<li><p>Close up and go home.  Call
+  <tt class="computeroutput">BZ2_bzCompressEnd</tt>.</p></li>
+</ol></div>
+<p>If the data you want to compress fits into your input
+buffer all at once, you can skip the calls of
+<tt class="computeroutput">BZ2_bzCompress ( ..., BZ_RUN )</tt>
+and just do the <tt class="computeroutput">BZ2_bzCompress ( ..., BZ_FINISH
+)</tt> calls.</p>
+<p>All required memory is allocated by
+<tt class="computeroutput">BZ2_bzCompressInit</tt>.  The
+compression library can accept any data at all (obviously).  So
+you shouldn't get any error return values from the
+<tt class="computeroutput">BZ2_bzCompress</tt> calls.  If you
+do, they will be
+<tt class="computeroutput">BZ_SEQUENCE_ERROR</tt>, and indicate
+a bug in your programming.</p>
+<p>Trivial other possible return values:</p>
+<pre class="programlisting">BZ_PARAM_ERROR
+  if strm is NULL, or strm-&gt;s is NULL</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bzCompress-end"></a>3.3.3. <tt class="computeroutput">BZ2_bzCompressEnd</tt></h3></div></div>
+<div></div>
+</div>
+<pre class="programlisting">int BZ2_bzCompressEnd ( bz_stream *strm );</pre>
+<p>Releases all memory associated with a compression
+stream.</p>
+<p>Possible return values:</p>
+<pre class="programlisting">BZ_PARAM_ERROR  if strm is NULL or strm-&gt;s is NULL
+BZ_OK           otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bzDecompress-init"></a>3.3.4. <tt class="computeroutput">BZ2_bzDecompressInit</tt></h3></div></div>
+<div></div>
+</div>
+<pre class="programlisting">int BZ2_bzDecompressInit ( bz_stream *strm, int verbosity, int small );</pre>
+<p>Prepares for decompression.  As with
+<tt class="computeroutput">BZ2_bzCompressInit</tt>, a
+<tt class="computeroutput">bz_stream</tt> record should be
+allocated and initialised before the call.  Fields
+<tt class="computeroutput">bzalloc</tt>,
+<tt class="computeroutput">bzfree</tt> and
+<tt class="computeroutput">opaque</tt> should be set if a custom
+memory allocator is required, or made
+<tt class="computeroutput">NULL</tt> for the normal
+<tt class="computeroutput">malloc</tt> /
+<tt class="computeroutput">free</tt> routines.  Upon return, the
+internal state will have been initialised, and
+<tt class="computeroutput">total_in</tt> and
+<tt class="computeroutput">total_out</tt> will be zero.</p>
+<p>For the meaning of parameter
+<tt class="computeroutput">verbosity</tt>, see
+<tt class="computeroutput">BZ2_bzCompressInit</tt>.</p>
+<p>If <tt class="computeroutput">small</tt> is nonzero, the
+library will use an alternative decompression algorithm which
+uses less memory but at the cost of decompressing more slowly
+(roughly speaking, half the speed, but the maximum memory
+requirement drops to around 2300k).  See <a href="#using">How to use bzip2</a>
+for more information on memory management.</p>
+<p>Note that the amount of memory needed to decompress a
+stream cannot be determined until the stream's header has been
+read, so even if
+<tt class="computeroutput">BZ2_bzDecompressInit</tt> succeeds, a
+subsequent <tt class="computeroutput">BZ2_bzDecompress</tt>
+could fail with
+<tt class="computeroutput">BZ_MEM_ERROR</tt>.</p>
+<p>Possible return values:</p>
+<pre class="programlisting">BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if ( small != 0 &amp;&amp; small != 1 )
+  or (verbosity &lt;; 0 || verbosity &gt; 4)
+BZ_MEM_ERROR
+  if insufficient memory is available</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">BZ2_bzDecompress
+  if BZ_OK was returned
+  no specific action required in case of error</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bzDecompress"></a>3.3.5. <tt class="computeroutput">BZ2_bzDecompress</tt></h3></div></div>
+<div></div>
+</div>
+<pre class="programlisting">int BZ2_bzDecompress ( bz_stream *strm );</pre>
+<p>Provides more input and/out output buffer space for the
+library.  The caller maintains input and output buffers, and uses
+<tt class="computeroutput">BZ2_bzDecompress</tt> to transfer
+data between them.</p>
+<p>Before each call to
+<tt class="computeroutput">BZ2_bzDecompress</tt>,
+<tt class="computeroutput">next_in</tt> should point at the
+compressed data, and <tt class="computeroutput">avail_in</tt>
+should indicate how many bytes the library may read.
+<tt class="computeroutput">BZ2_bzDecompress</tt> updates
+<tt class="computeroutput">next_in</tt>,
+<tt class="computeroutput">avail_in</tt> and
+<tt class="computeroutput">total_in</tt> to reflect the number
+of bytes it has read.</p>
+<p>Similarly, <tt class="computeroutput">next_out</tt> should
+point to a buffer in which the uncompressed output is to be
+placed, with <tt class="computeroutput">avail_out</tt>
+indicating how much output space is available.
+<tt class="computeroutput">BZ2_bzCompress</tt> updates
+<tt class="computeroutput">next_out</tt>,
+<tt class="computeroutput">avail_out</tt> and
+<tt class="computeroutput">total_out</tt> to reflect the number
+of bytes output.</p>
+<p>You may provide and remove as little or as much data as you
+like on each call of
+<tt class="computeroutput">BZ2_bzDecompress</tt>.  In the limit,
+it is acceptable to supply and remove data one byte at a time,
+although this would be terribly inefficient.  You should always
+ensure that at least one byte of output space is available at
+each call.</p>
+<p>Use of <tt class="computeroutput">BZ2_bzDecompress</tt> is
+simpler than
+<tt class="computeroutput">BZ2_bzCompress</tt>.</p>
+<p>You should provide input and remove output as described
+above, and repeatedly call
+<tt class="computeroutput">BZ2_bzDecompress</tt> until
+<tt class="computeroutput">BZ_STREAM_END</tt> is returned.
+Appearance of <tt class="computeroutput">BZ_STREAM_END</tt>
+denotes that <tt class="computeroutput">BZ2_bzDecompress</tt>
+has detected the logical end of the compressed stream.
+<tt class="computeroutput">BZ2_bzDecompress</tt> will not
+produce <tt class="computeroutput">BZ_STREAM_END</tt> until all
+output data has been placed into the output buffer, so once
+<tt class="computeroutput">BZ_STREAM_END</tt> appears, you are
+guaranteed to have available all the decompressed output, and
+<tt class="computeroutput">BZ2_bzDecompressEnd</tt> can safely
+be called.</p>
+<p>If case of an error return value, you should call
+<tt class="computeroutput">BZ2_bzDecompressEnd</tt> to clean up
+and release memory.</p>
+<p>Possible return values:</p>
+<pre class="programlisting">BZ_PARAM_ERROR
+  if strm is NULL or strm-&gt;s is NULL
+  or strm-&gt;avail_out &lt; 1
+BZ_DATA_ERROR
+  if a data integrity error is detected in the compressed stream
+BZ_DATA_ERROR_MAGIC
+  if the compressed stream doesn't begin with the right magic bytes
+BZ_MEM_ERROR
+  if there wasn't enough memory available
+BZ_STREAM_END
+  if the logical end of the data stream was detected and all
+  output in has been consumed, eg s--&gt;avail_out &gt; 0
+BZ_OK
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">BZ2_bzDecompress
+  if BZ_OK was returned
+BZ2_bzDecompressEnd
+  otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bzDecompress-end"></a>3.3.6. <tt class="computeroutput">BZ2_bzDecompressEnd</tt></h3></div></div>
+<div></div>
+</div>
+<pre class="programlisting">int BZ2_bzDecompressEnd ( bz_stream *strm );</pre>
+<p>Releases all memory associated with a decompression
+stream.</p>
+<p>Possible return values:</p>
+<pre class="programlisting">BZ_PARAM_ERROR
+  if strm is NULL or strm-&gt;s is NULL
+BZ_OK
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">  None.</pre>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="hl-interface"></a>3.4. High-level interface</h2></div></div>
+<div></div>
+</div>
+<p>This interface provides functions for reading and writing
+<tt class="computeroutput">bzip2</tt> format files.  First, some
+general points.</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p>All of the functions take an
+  <tt class="computeroutput">int*</tt> first argument,
+  <tt class="computeroutput">bzerror</tt>.  After each call,
+  <tt class="computeroutput">bzerror</tt> should be consulted
+  first to determine the outcome of the call.  If
+  <tt class="computeroutput">bzerror</tt> is
+  <tt class="computeroutput">BZ_OK</tt>, the call completed
+  successfully, and only then should the return value of the
+  function (if any) be consulted.  If
+  <tt class="computeroutput">bzerror</tt> is
+  <tt class="computeroutput">BZ_IO_ERROR</tt>, there was an
+  error reading/writing the underlying compressed file, and you
+  should then consult <tt class="computeroutput">errno</tt> /
+  <tt class="computeroutput">perror</tt> to determine the cause
+  of the difficulty.  <tt class="computeroutput">bzerror</tt>
+  may also be set to various other values; precise details are
+  given on a per-function basis below.</p></li>
+<li style="list-style-type: disc"><p>If <tt class="computeroutput">bzerror</tt> indicates
+  an error (ie, anything except
+  <tt class="computeroutput">BZ_OK</tt> and
+  <tt class="computeroutput">BZ_STREAM_END</tt>), you should
+  immediately call
+  <tt class="computeroutput">BZ2_bzReadClose</tt> (or
+  <tt class="computeroutput">BZ2_bzWriteClose</tt>, depending on
+  whether you are attempting to read or to write) to free up all
+  resources associated with the stream.  Once an error has been
+  indicated, behaviour of all calls except
+  <tt class="computeroutput">BZ2_bzReadClose</tt>
+  (<tt class="computeroutput">BZ2_bzWriteClose</tt>) is
+  undefined.  The implication is that (1)
+  <tt class="computeroutput">bzerror</tt> should be checked
+  after each call, and (2) if
+  <tt class="computeroutput">bzerror</tt> indicates an error,
+  <tt class="computeroutput">BZ2_bzReadClose</tt>
+  (<tt class="computeroutput">BZ2_bzWriteClose</tt>) should then
+  be called to clean up.</p></li>
+<li style="list-style-type: disc"><p>The <tt class="computeroutput">FILE*</tt> arguments
+  passed to <tt class="computeroutput">BZ2_bzReadOpen</tt> /
+  <tt class="computeroutput">BZ2_bzWriteOpen</tt> should be set
+  to binary mode.  Most Unix systems will do this by default, but
+  other platforms, including Windows and Mac, will not.  If you
+  omit this, you may encounter problems when moving code to new
+  platforms.</p></li>
+<li style="list-style-type: disc"><p>Memory allocation requests are handled by
+  <tt class="computeroutput">malloc</tt> /
+  <tt class="computeroutput">free</tt>.  At present there is no
+  facility for user-defined memory allocators in the file I/O
+  functions (could easily be added, though).</p></li>
+</ul></div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bzreadopen"></a>3.4.1. <tt class="computeroutput">BZ2_bzReadOpen</tt></h3></div></div>
+<div></div>
+</div>
+<pre class="programlisting">typedef void BZFILE;
+
+BZFILE *BZ2_bzReadOpen( int *bzerror, FILE *f, 
+                        int verbosity, int small,
+                        void *unused, int nUnused );</pre>
+<p>Prepare to read compressed data from file handle
+<tt class="computeroutput">f</tt>.
+<tt class="computeroutput">f</tt> should refer to a file which
+has been opened for reading, and for which the error indicator
+(<tt class="computeroutput">ferror(f)</tt>)is not set.  If
+<tt class="computeroutput">small</tt> is 1, the library will try
+to decompress using less memory, at the expense of speed.</p>
+<p>For reasons explained below,
+<tt class="computeroutput">BZ2_bzRead</tt> will decompress the
+<tt class="computeroutput">nUnused</tt> bytes starting at
+<tt class="computeroutput">unused</tt>, before starting to read
+from the file <tt class="computeroutput">f</tt>.  At most
+<tt class="computeroutput">BZ_MAX_UNUSED</tt> bytes may be
+supplied like this.  If this facility is not required, you should
+pass <tt class="computeroutput">NULL</tt> and
+<tt class="computeroutput">0</tt> for
+<tt class="computeroutput">unused</tt> and
+n<tt class="computeroutput">Unused</tt> respectively.</p>
+<p>For the meaning of parameters
+<tt class="computeroutput">small</tt> and
+<tt class="computeroutput">verbosity</tt>, see
+<tt class="computeroutput">BZ2_bzDecompressInit</tt>.</p>
+<p>The amount of memory needed to decompress a file cannot be
+determined until the file's header has been read.  So it is
+possible that <tt class="computeroutput">BZ2_bzReadOpen</tt>
+returns <tt class="computeroutput">BZ_OK</tt> but a subsequent
+call of <tt class="computeroutput">BZ2_bzRead</tt> will return
+<tt class="computeroutput">BZ_MEM_ERROR</tt>.</p>
+<p>Possible assignments to
+<tt class="computeroutput">bzerror</tt>:</p>
+<pre class="programlisting">BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if f is NULL
+  or small is neither 0 nor 1
+  or ( unused == NULL &amp;&amp; nUnused != 0 )
+  or ( unused != NULL &amp;&amp; !(0 &lt;= nUnused &lt;= BZ_MAX_UNUSED) )
+BZ_IO_ERROR
+  if ferror(f) is nonzero
+BZ_MEM_ERROR
+  if insufficient memory is available
+BZ_OK
+  otherwise.</pre>
+<p>Possible return values:</p>
+<pre class="programlisting">Pointer to an abstract BZFILE
+  if bzerror is BZ_OK
+NULL
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">BZ2_bzRead
+  if bzerror is BZ_OK
+BZ2_bzClose
+  otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bzread"></a>3.4.2. <tt class="computeroutput">BZ2_bzRead</tt></h3></div></div>
+<div></div>
+</div>
+<pre class="programlisting">int BZ2_bzRead ( int *bzerror, BZFILE *b, void *buf, int len );</pre>
+<p>Reads up to <tt class="computeroutput">len</tt>
+(uncompressed) bytes from the compressed file
+<tt class="computeroutput">b</tt> into the buffer
+<tt class="computeroutput">buf</tt>.  If the read was
+successful, <tt class="computeroutput">bzerror</tt> is set to
+<tt class="computeroutput">BZ_OK</tt> and the number of bytes
+read is returned.  If the logical end-of-stream was detected,
+<tt class="computeroutput">bzerror</tt> will be set to
+<tt class="computeroutput">BZ_STREAM_END</tt>, and the number of
+bytes read is returned.  All other
+<tt class="computeroutput">bzerror</tt> values denote an
+error.</p>
+<p><tt class="computeroutput">BZ2_bzRead</tt> will supply
+<tt class="computeroutput">len</tt> bytes, unless the logical
+stream end is detected or an error occurs.  Because of this, it
+is possible to detect the stream end by observing when the number
+of bytes returned is less than the number requested.
+Nevertheless, this is regarded as inadvisable; you should instead
+check <tt class="computeroutput">bzerror</tt> after every call
+and watch out for
+<tt class="computeroutput">BZ_STREAM_END</tt>.</p>
+<p>Internally, <tt class="computeroutput">BZ2_bzRead</tt>
+copies data from the compressed file in chunks of size
+<tt class="computeroutput">BZ_MAX_UNUSED</tt> bytes before
+decompressing it.  If the file contains more bytes than strictly
+needed to reach the logical end-of-stream,
+<tt class="computeroutput">BZ2_bzRead</tt> will almost certainly
+read some of the trailing data before signalling
+<tt class="computeroutput">BZ_SEQUENCE_END</tt>.  To collect the
+read but unused data once
+<tt class="computeroutput">BZ_SEQUENCE_END</tt> has appeared,
+call <tt class="computeroutput">BZ2_bzReadGetUnused</tt>
+immediately before
+<tt class="computeroutput">BZ2_bzReadClose</tt>.</p>
+<p>Possible assignments to
+<tt class="computeroutput">bzerror</tt>:</p>
+<pre class="programlisting">BZ_PARAM_ERROR
+  if b is NULL or buf is NULL or len &lt; 0
+BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzWriteOpen
+BZ_IO_ERROR
+  if there is an error reading from the compressed file
+BZ_UNEXPECTED_EOF
+  if the compressed file ended before 
+  the logical end-of-stream was detected
+BZ_DATA_ERROR
+  if a data integrity error was detected in the compressed stream
+BZ_DATA_ERROR_MAGIC
+  if the stream does not begin with the requisite header bytes 
+  (ie, is not a bzip2 data file).  This is really 
+  a special case of BZ_DATA_ERROR.
+BZ_MEM_ERROR
+  if insufficient memory was available
+BZ_STREAM_END
+  if the logical end of stream was detected.
+BZ_OK
+  otherwise.</pre>
+<p>Possible return values:</p>
+<pre class="programlisting">number of bytes read
+  if bzerror is BZ_OK or BZ_STREAM_END
+undefined
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">collect data from buf, then BZ2_bzRead or BZ2_bzReadClose
+  if bzerror is BZ_OK
+collect data from buf, then BZ2_bzReadClose or BZ2_bzReadGetUnused
+  if bzerror is BZ_SEQUENCE_END
+BZ2_bzReadClose
+  otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bzreadgetunused"></a>3.4.3. <tt class="computeroutput">BZ2_bzReadGetUnused</tt></h3></div></div>
+<div></div>
+</div>
+<pre class="programlisting">void BZ2_bzReadGetUnused( int* bzerror, BZFILE *b, 
+                          void** unused, int* nUnused );</pre>
+<p>Returns data which was read from the compressed file but
+was not needed to get to the logical end-of-stream.
+<tt class="computeroutput">*unused</tt> is set to the address of
+the data, and <tt class="computeroutput">*nUnused</tt> to the
+number of bytes.  <tt class="computeroutput">*nUnused</tt> will
+be set to a value between <tt class="computeroutput">0</tt> and
+<tt class="computeroutput">BZ_MAX_UNUSED</tt> inclusive.</p>
+<p>This function may only be called once
+<tt class="computeroutput">BZ2_bzRead</tt> has signalled
+<tt class="computeroutput">BZ_STREAM_END</tt> but before
+<tt class="computeroutput">BZ2_bzReadClose</tt>.</p>
+<p>Possible assignments to
+<tt class="computeroutput">bzerror</tt>:</p>
+<pre class="programlisting">BZ_PARAM_ERROR
+  if b is NULL
+  or unused is NULL or nUnused is NULL
+BZ_SEQUENCE_ERROR
+  if BZ_STREAM_END has not been signalled
+  or if b was opened with BZ2_bzWriteOpen
+BZ_OK
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">BZ2_bzReadClose</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bzreadclose"></a>3.4.4. <tt class="computeroutput">BZ2_bzReadClose</tt></h3></div></div>
+<div></div>
+</div>
+<pre class="programlisting">void BZ2_bzReadClose ( int *bzerror, BZFILE *b );</pre>
+<p>Releases all memory pertaining to the compressed file
+<tt class="computeroutput">b</tt>.
+<tt class="computeroutput">BZ2_bzReadClose</tt> does not call
+<tt class="computeroutput">fclose</tt> on the underlying file
+handle, so you should do that yourself if appropriate.
+<tt class="computeroutput">BZ2_bzReadClose</tt> should be called
+to clean up after all error situations.</p>
+<p>Possible assignments to
+<tt class="computeroutput">bzerror</tt>:</p>
+<pre class="programlisting">BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzOpenWrite
+BZ_OK
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">none</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bzwriteopen"></a>3.4.5. <tt class="computeroutput">BZ2_bzWriteOpen</tt></h3></div></div>
+<div></div>
+</div>
+<pre class="programlisting">BZFILE *BZ2_bzWriteOpen( int *bzerror, FILE *f, 
+                         int blockSize100k, int verbosity,
+                         int workFactor );</pre>
+<p>Prepare to write compressed data to file handle
+<tt class="computeroutput">f</tt>.
+<tt class="computeroutput">f</tt> should refer to a file which
+has been opened for writing, and for which the error indicator
+(<tt class="computeroutput">ferror(f)</tt>)is not set.</p>
+<p>For the meaning of parameters
+<tt class="computeroutput">blockSize100k</tt>,
+<tt class="computeroutput">verbosity</tt> and
+<tt class="computeroutput">workFactor</tt>, see
+<tt class="computeroutput">BZ2_bzCompressInit</tt>.</p>
+<p>All required memory is allocated at this stage, so if the
+call completes successfully,
+<tt class="computeroutput">BZ_MEM_ERROR</tt> cannot be signalled
+by a subsequent call to
+<tt class="computeroutput">BZ2_bzWrite</tt>.</p>
+<p>Possible assignments to
+<tt class="computeroutput">bzerror</tt>:</p>
+<pre class="programlisting">BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if f is NULL
+  or blockSize100k &lt; 1 or blockSize100k &gt; 9
+BZ_IO_ERROR
+  if ferror(f) is nonzero
+BZ_MEM_ERROR
+  if insufficient memory is available
+BZ_OK
+  otherwise</pre>
+<p>Possible return values:</p>
+<pre class="programlisting">Pointer to an abstract BZFILE
+  if bzerror is BZ_OK
+NULL
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">BZ2_bzWrite
+  if bzerror is BZ_OK
+  (you could go directly to BZ2_bzWriteClose, but this would be pretty pointless)
+BZ2_bzWriteClose
+  otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bzwrite"></a>3.4.6. <tt class="computeroutput">BZ2_bzWrite</tt></h3></div></div>
+<div></div>
+</div>
+<pre class="programlisting">void BZ2_bzWrite ( int *bzerror, BZFILE *b, void *buf, int len );</pre>
+<p>Absorbs <tt class="computeroutput">len</tt> bytes from the
+buffer <tt class="computeroutput">buf</tt>, eventually to be
+compressed and written to the file.</p>
+<p>Possible assignments to
+<tt class="computeroutput">bzerror</tt>:</p>
+<pre class="programlisting">BZ_PARAM_ERROR
+  if b is NULL or buf is NULL or len &lt; 0
+BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzReadOpen
+BZ_IO_ERROR
+  if there is an error writing the compressed file.
+BZ_OK
+  otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bzwriteclose"></a>3.4.7. <tt class="computeroutput">BZ2_bzWriteClose</tt></h3></div></div>
+<div></div>
+</div>
+<pre class="programlisting">void BZ2_bzWriteClose( int *bzerror, BZFILE* f,
+                       int abandon,
+                       unsigned int* nbytes_in,
+                       unsigned int* nbytes_out );
+
+void BZ2_bzWriteClose64( int *bzerror, BZFILE* f,
+                         int abandon,
+                         unsigned int* nbytes_in_lo32,
+                         unsigned int* nbytes_in_hi32,
+                         unsigned int* nbytes_out_lo32,
+                         unsigned int* nbytes_out_hi32 );</pre>
+<p>Compresses and flushes to the compressed file all data so
+far supplied by <tt class="computeroutput">BZ2_bzWrite</tt>.
+The logical end-of-stream markers are also written, so subsequent
+calls to <tt class="computeroutput">BZ2_bzWrite</tt> are
+illegal.  All memory associated with the compressed file
+<tt class="computeroutput">b</tt> is released.
+<tt class="computeroutput">fflush</tt> is called on the
+compressed file, but it is not
+<tt class="computeroutput">fclose</tt>'d.</p>
+<p>If <tt class="computeroutput">BZ2_bzWriteClose</tt> is
+called to clean up after an error, the only action is to release
+the memory.  The library records the error codes issued by
+previous calls, so this situation will be detected automatically.
+There is no attempt to complete the compression operation, nor to
+<tt class="computeroutput">fflush</tt> the compressed file.  You
+can force this behaviour to happen even in the case of no error,
+by passing a nonzero value to
+<tt class="computeroutput">abandon</tt>.</p>
+<p>If <tt class="computeroutput">nbytes_in</tt> is non-null,
+<tt class="computeroutput">*nbytes_in</tt> will be set to be the
+total volume of uncompressed data handled.  Similarly,
+<tt class="computeroutput">nbytes_out</tt> will be set to the
+total volume of compressed data written.  For compatibility with
+older versions of the library,
+<tt class="computeroutput">BZ2_bzWriteClose</tt> only yields the
+lower 32 bits of these counts.  Use
+<tt class="computeroutput">BZ2_bzWriteClose64</tt> if you want
+the full 64 bit counts.  These two functions are otherwise
+absolutely identical.</p>
+<p>Possible assignments to
+<tt class="computeroutput">bzerror</tt>:</p>
+<pre class="programlisting">BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzReadOpen
+BZ_IO_ERROR
+  if there is an error writing the compressed file
+BZ_OK
+  otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="embed"></a>3.4.8. Handling embedded compressed data streams</h3></div></div>
+<div></div>
+</div>
+<p>The high-level library facilitates use of
+<tt class="computeroutput">bzip2</tt> data streams which form
+some part of a surrounding, larger data stream.</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p>For writing, the library takes an open file handle,
+  writes compressed data to it,
+  <tt class="computeroutput">fflush</tt>es it but does not
+  <tt class="computeroutput">fclose</tt> it.  The calling
+  application can write its own data before and after the
+  compressed data stream, using that same file handle.</p></li>
+<li style="list-style-type: disc"><p>Reading is more complex, and the facilities are not as
+  general as they could be since generality is hard to reconcile
+  with efficiency.  <tt class="computeroutput">BZ2_bzRead</tt>
+  reads from the compressed file in blocks of size
+  <tt class="computeroutput">BZ_MAX_UNUSED</tt> bytes, and in
+  doing so probably will overshoot the logical end of compressed
+  stream.  To recover this data once decompression has ended,
+  call <tt class="computeroutput">BZ2_bzReadGetUnused</tt> after
+  the last call of <tt class="computeroutput">BZ2_bzRead</tt>
+  (the one returning
+  <tt class="computeroutput">BZ_STREAM_END</tt>) but before
+  calling
+  <tt class="computeroutput">BZ2_bzReadClose</tt>.</p></li>
+</ul></div>
+<p>This mechanism makes it easy to decompress multiple
+<tt class="computeroutput">bzip2</tt> streams placed end-to-end.
+As the end of one stream, when
+<tt class="computeroutput">BZ2_bzRead</tt> returns
+<tt class="computeroutput">BZ_STREAM_END</tt>, call
+<tt class="computeroutput">BZ2_bzReadGetUnused</tt> to collect
+the unused data (copy it into your own buffer somewhere).  That
+data forms the start of the next compressed stream.  To start
+uncompressing that next stream, call
+<tt class="computeroutput">BZ2_bzReadOpen</tt> again, feeding in
+the unused data via the <tt class="computeroutput">unused</tt> /
+<tt class="computeroutput">nUnused</tt> parameters.  Keep doing
+this until <tt class="computeroutput">BZ_STREAM_END</tt> return
+coincides with the physical end of file
+(<tt class="computeroutput">feof(f)</tt>).  In this situation
+<tt class="computeroutput">BZ2_bzReadGetUnused</tt> will of
+course return no data.</p>
+<p>This should give some feel for how the high-level interface
+can be used.  If you require extra flexibility, you'll have to
+bite the bullet and get to grips with the low-level
+interface.</p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="std-rdwr"></a>3.4.9. Standard file-reading/writing code</h3></div></div>
+<div></div>
+</div>
+<p>Here's how you'd write data to a compressed file:</p>
+<pre class="programlisting">FILE*   f;
+BZFILE* b;
+int     nBuf;
+char    buf[ /* whatever size you like */ ];
+int     bzerror;
+int     nWritten;
+
+f = fopen ( "myfile.bz2", "w" );
+if ( !f ) {
+ /* handle error */
+}
+b = BZ2_bzWriteOpen( &amp;bzerror, f, 9 );
+if (bzerror != BZ_OK) {
+ BZ2_bzWriteClose ( b );
+ /* handle error */
+}
+
+while ( /* condition */ ) {
+ /* get data to write into buf, and set nBuf appropriately */
+ nWritten = BZ2_bzWrite ( &amp;bzerror, b, buf, nBuf );
+ if (bzerror == BZ_IO_ERROR) { 
+   BZ2_bzWriteClose ( &amp;bzerror, b );
+   /* handle error */
+ }
+}
+
+BZ2_bzWriteClose( &amp;bzerror, b );
+if (bzerror == BZ_IO_ERROR) {
+ /* handle error */
+}</pre>
+<p>And to read from a compressed file:</p>
+<pre class="programlisting">FILE*   f;
+BZFILE* b;
+int     nBuf;
+char    buf[ /* whatever size you like */ ];
+int     bzerror;
+int     nWritten;
+
+f = fopen ( "myfile.bz2", "r" );
+if ( !f ) {
+  /* handle error */
+}
+b = BZ2_bzReadOpen ( &amp;bzerror, f, 0, NULL, 0 );
+if ( bzerror != BZ_OK ) {
+  BZ2_bzReadClose ( &amp;bzerror, b );
+  /* handle error */
+}
+
+bzerror = BZ_OK;
+while ( bzerror == BZ_OK &amp;&amp; /* arbitrary other conditions */) {
+  nBuf = BZ2_bzRead ( &amp;bzerror, b, buf, /* size of buf */ );
+  if ( bzerror == BZ_OK ) {
+    /* do something with buf[0 .. nBuf-1] */
+  }
+}
+if ( bzerror != BZ_STREAM_END ) {
+   BZ2_bzReadClose ( &amp;bzerror, b );
+   /* handle error */
+} else {
+   BZ2_bzReadClose ( &amp;bzerror );
+}</pre>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="util-fns"></a>3.5. Utility functions</h2></div></div>
+<div></div>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bzbufftobuffcompress"></a>3.5.1. <tt class="computeroutput">BZ2_bzBuffToBuffCompress</tt></h3></div></div>
+<div></div>
+</div>
+<pre class="programlisting">int BZ2_bzBuffToBuffCompress( char*         dest,
+                              unsigned int* destLen,
+                              char*         source,
+                              unsigned int  sourceLen,
+                              int           blockSize100k,
+                              int           verbosity,
+                              int           workFactor );</pre>
+<p>Attempts to compress the data in <tt class="computeroutput">source[0
+.. sourceLen-1]</tt> into the destination buffer,
+<tt class="computeroutput">dest[0 .. *destLen-1]</tt>.  If the
+destination buffer is big enough,
+<tt class="computeroutput">*destLen</tt> is set to the size of
+the compressed data, and <tt class="computeroutput">BZ_OK</tt>
+is returned.  If the compressed data won't fit,
+<tt class="computeroutput">*destLen</tt> is unchanged, and
+<tt class="computeroutput">BZ_OUTBUFF_FULL</tt> is
+returned.</p>
+<p>Compression in this manner is a one-shot event, done with a
+single call to this function.  The resulting compressed data is a
+complete <tt class="computeroutput">bzip2</tt> format data
+stream.  There is no mechanism for making additional calls to
+provide extra input data.  If you want that kind of mechanism,
+use the low-level interface.</p>
+<p>For the meaning of parameters
+<tt class="computeroutput">blockSize100k</tt>,
+<tt class="computeroutput">verbosity</tt> and
+<tt class="computeroutput">workFactor</tt>, see
+<tt class="computeroutput">BZ2_bzCompressInit</tt>.</p>
+<p>To guarantee that the compressed data will fit in its
+buffer, allocate an output buffer of size 1% larger than the
+uncompressed data, plus six hundred extra bytes.</p>
+<p><tt class="computeroutput">BZ2_bzBuffToBuffDecompress</tt>
+will not write data at or beyond
+<tt class="computeroutput">dest[*destLen]</tt>, even in case of
+buffer overflow.</p>
+<p>Possible return values:</p>
+<pre class="programlisting">BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if dest is NULL or destLen is NULL
+  or blockSize100k &lt; 1 or blockSize100k &gt; 9
+  or verbosity &lt; 0 or verbosity &gt; 4
+  or workFactor &lt; 0 or workFactor &gt; 250
+BZ_MEM_ERROR
+  if insufficient memory is available 
+BZ_OUTBUFF_FULL
+  if the size of the compressed data exceeds *destLen
+BZ_OK
+  otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bzbufftobuffdecompress"></a>3.5.2. <tt class="computeroutput">BZ2_bzBuffToBuffDecompress</tt></h3></div></div>
+<div></div>
+</div>
+<pre class="programlisting">int BZ2_bzBuffToBuffDecompress( char*         dest,
+                                unsigned int* destLen,
+                                char*         source,
+                                unsigned int  sourceLen,
+                                int           small,
+                                int           verbosity );</pre>
+<p>Attempts to decompress the data in <tt class="computeroutput">source[0
+.. sourceLen-1]</tt> into the destination buffer,
+<tt class="computeroutput">dest[0 .. *destLen-1]</tt>.  If the
+destination buffer is big enough,
+<tt class="computeroutput">*destLen</tt> is set to the size of
+the uncompressed data, and <tt class="computeroutput">BZ_OK</tt>
+is returned.  If the compressed data won't fit,
+<tt class="computeroutput">*destLen</tt> is unchanged, and
+<tt class="computeroutput">BZ_OUTBUFF_FULL</tt> is
+returned.</p>
+<p><tt class="computeroutput">source</tt> is assumed to hold
+a complete <tt class="computeroutput">bzip2</tt> format data
+stream.
+<tt class="computeroutput">BZ2_bzBuffToBuffDecompress</tt> tries
+to decompress the entirety of the stream into the output
+buffer.</p>
+<p>For the meaning of parameters
+<tt class="computeroutput">small</tt> and
+<tt class="computeroutput">verbosity</tt>, see
+<tt class="computeroutput">BZ2_bzDecompressInit</tt>.</p>
+<p>Because the compression ratio of the compressed data cannot
+be known in advance, there is no easy way to guarantee that the
+output buffer will be big enough.  You may of course make
+arrangements in your code to record the size of the uncompressed
+data, but such a mechanism is beyond the scope of this
+library.</p>
+<p><tt class="computeroutput">BZ2_bzBuffToBuffDecompress</tt>
+will not write data at or beyond
+<tt class="computeroutput">dest[*destLen]</tt>, even in case of
+buffer overflow.</p>
+<p>Possible return values:</p>
+<pre class="programlisting">BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if dest is NULL or destLen is NULL
+  or small != 0 &amp;&amp; small != 1
+  or verbosity &lt; 0 or verbosity &gt; 4
+BZ_MEM_ERROR
+  if insufficient memory is available 
+BZ_OUTBUFF_FULL
+  if the size of the compressed data exceeds *destLen
+BZ_DATA_ERROR
+  if a data integrity error was detected in the compressed data
+BZ_DATA_ERROR_MAGIC
+  if the compressed data doesn't begin with the right magic bytes
+BZ_UNEXPECTED_EOF
+  if the compressed data ends unexpectedly
+BZ_OK
+  otherwise</pre>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="zlib-compat"></a>3.6. <tt class="computeroutput">zlib</tt> compatibility functions</h2></div></div>
+<div></div>
+</div>
+<p>Yoshioka Tsuneo has contributed some functions to give
+better <tt class="computeroutput">zlib</tt> compatibility.
+These functions are <tt class="computeroutput">BZ2_bzopen</tt>,
+<tt class="computeroutput">BZ2_bzread</tt>,
+<tt class="computeroutput">BZ2_bzwrite</tt>,
+<tt class="computeroutput">BZ2_bzflush</tt>,
+<tt class="computeroutput">BZ2_bzclose</tt>,
+<tt class="computeroutput">BZ2_bzerror</tt> and
+<tt class="computeroutput">BZ2_bzlibVersion</tt>.  These
+functions are not (yet) officially part of the library.  If they
+break, you get to keep all the pieces.  Nevertheless, I think
+they work ok.</p>
+<pre class="programlisting">typedef void BZFILE;
+
+const char * BZ2_bzlibVersion ( void );</pre>
+<p>Returns a string indicating the library version.</p>
+<pre class="programlisting">BZFILE * BZ2_bzopen  ( const char *path, const char *mode );
+BZFILE * BZ2_bzdopen ( int        fd,    const char *mode );</pre>
+<p>Opens a <tt class="computeroutput">.bz2</tt> file for
+reading or writing, using either its name or a pre-existing file
+descriptor.  Analogous to <tt class="computeroutput">fopen</tt>
+and <tt class="computeroutput">fdopen</tt>.</p>
+<pre class="programlisting">int BZ2_bzread  ( BZFILE* b, void* buf, int len );
+int BZ2_bzwrite ( BZFILE* b, void* buf, int len );</pre>
+<p>Reads/writes data from/to a previously opened
+<tt class="computeroutput">BZFILE</tt>.  Analogous to
+<tt class="computeroutput">fread</tt> and
+<tt class="computeroutput">fwrite</tt>.</p>
+<pre class="programlisting">int  BZ2_bzflush ( BZFILE* b );
+void BZ2_bzclose ( BZFILE* b );</pre>
+<p>Flushes/closes a <tt class="computeroutput">BZFILE</tt>.
+<tt class="computeroutput">BZ2_bzflush</tt> doesn't actually do
+anything.  Analogous to <tt class="computeroutput">fflush</tt>
+and <tt class="computeroutput">fclose</tt>.</p>
+<pre class="programlisting">const char * BZ2_bzerror ( BZFILE *b, int *errnum )</pre>
+<p>Returns a string describing the more recent error status of
+<tt class="computeroutput">b</tt>, and also sets
+<tt class="computeroutput">*errnum</tt> to its numerical
+value.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="stdio-free"></a>3.7. Using the library in a <tt class="computeroutput">stdio</tt>-free environment</h2></div></div>
+<div></div>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="stdio-bye"></a>3.7.1. Getting rid of <tt class="computeroutput">stdio</tt></h3></div></div>
+<div></div>
+</div>
+<p>In a deeply embedded application, you might want to use
+just the memory-to-memory functions.  You can do this
+conveniently by compiling the library with preprocessor symbol
+<tt class="computeroutput">BZ_NO_STDIO</tt> defined.  Doing this
+gives you a library containing only the following eight
+functions:</p>
+<p><tt class="computeroutput">BZ2_bzCompressInit</tt>,
+<tt class="computeroutput">BZ2_bzCompress</tt>,
+<tt class="computeroutput">BZ2_bzCompressEnd</tt>
+<tt class="computeroutput">BZ2_bzDecompressInit</tt>,
+<tt class="computeroutput">BZ2_bzDecompress</tt>,
+<tt class="computeroutput">BZ2_bzDecompressEnd</tt>
+<tt class="computeroutput">BZ2_bzBuffToBuffCompress</tt>,
+<tt class="computeroutput">BZ2_bzBuffToBuffDecompress</tt></p>
+<p>When compiled like this, all functions will ignore
+<tt class="computeroutput">verbosity</tt> settings.</p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="critical-error"></a>3.7.2. Critical error handling</h3></div></div>
+<div></div>
+</div>
+<p><tt class="computeroutput">libbzip2</tt> contains a number
+of internal assertion checks which should, needless to say, never
+be activated.  Nevertheless, if an assertion should fail,
+behaviour depends on whether or not the library was compiled with
+<tt class="computeroutput">BZ_NO_STDIO</tt> set.</p>
+<p>For a normal compile, an assertion failure yields the
+message:</p>
+<div class="blockquote"><blockquote class="blockquote">
+<p>bzip2/libbzip2: internal error number N.</p>
+<p>This is a bug in bzip2/libbzip2, 1.0.3 of 15 February 2005.
+Please report it to me at: jseward@bzip.org.  If this happened
+when you were using some program which uses libbzip2 as a
+component, you should also report this bug to the author(s)
+of that program.  Please make an effort to report this bug;
+timely and accurate bug reports eventually lead to higher
+quality software.  Thanks.  Julian Seward, 15 February 2005.
+</p>
+</blockquote></div>
+<p>where <tt class="computeroutput">N</tt> is some error code
+number.  If <tt class="computeroutput">N == 1007</tt>, it also
+prints some extra text advising the reader that unreliable memory
+is often associated with internal error 1007. (This is a
+frequently-observed-phenomenon with versions 1.0.0/1.0.1).</p>
+<p><tt class="computeroutput">exit(3)</tt> is then
+called.</p>
+<p>For a <tt class="computeroutput">stdio</tt>-free library,
+assertion failures result in a call to a function declared
+as:</p>
+<pre class="programlisting">extern void bz_internal_error ( int errcode );</pre>
+<p>The relevant code is passed as a parameter.  You should
+supply such a function.</p>
+<p>In either case, once an assertion failure has occurred, any
+<tt class="computeroutput">bz_stream</tt> records involved can
+be regarded as invalid.  You should not attempt to resume normal
+operation with them.</p>
+<p>You may, of course, change critical error handling to suit
+your needs.  As I said above, critical errors indicate bugs in
+the library and should not occur.  All "normal" error situations
+are indicated via error return codes from functions, and can be
+recovered from.</p>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="win-dll"></a>3.8. Making a Windows DLL</h2></div></div>
+<div></div>
+</div>
+<p>Everything related to Windows has been contributed by
+Yoshioka Tsuneo
+(<tt class="computeroutput">QWF00133@niftyserve.or.jp</tt> /
+<tt class="computeroutput">tsuneo-y@is.aist-nara.ac.jp</tt>), so
+you should send your queries to him (but perhaps Cc: me,
+<tt class="computeroutput">jseward@bzip.org</tt>).</p>
+<p>My vague understanding of what to do is: using Visual C++
+5.0, open the project file
+<tt class="computeroutput">libbz2.dsp</tt>, and build.  That's
+all.</p>
+<p>If you can't open the project file for some reason, make a
+new one, naming these files:
+<tt class="computeroutput">blocksort.c</tt>,
+<tt class="computeroutput">bzlib.c</tt>,
+<tt class="computeroutput">compress.c</tt>,
+<tt class="computeroutput">crctable.c</tt>,
+<tt class="computeroutput">decompress.c</tt>,
+<tt class="computeroutput">huffman.c</tt>,
+<tt class="computeroutput">randtable.c</tt> and
+<tt class="computeroutput">libbz2.def</tt>.  You will also need
+to name the header files <tt class="computeroutput">bzlib.h</tt>
+and <tt class="computeroutput">bzlib_private.h</tt>.</p>
+<p>If you don't use VC++, you may need to define the
+proprocessor symbol
+<tt class="computeroutput">_WIN32</tt>.</p>
+<p>Finally, <tt class="computeroutput">dlltest.c</tt> is a
+sample program using the DLL.  It has a project file,
+<tt class="computeroutput">dlltest.dsp</tt>.</p>
+<p>If you just want a makefile for Visual C, have a look at
+<tt class="computeroutput">makefile.msc</tt>.</p>
+<p>Be aware that if you compile
+<tt class="computeroutput">bzip2</tt> itself on Win32, you must
+set <tt class="computeroutput">BZ_UNIX</tt> to 0 and
+<tt class="computeroutput">BZ_LCCWIN32</tt> to 1, in the file
+<tt class="computeroutput">bzip2.c</tt>, before compiling.
+Otherwise the resulting binary won't work correctly.</p>
+<p>I haven't tried any of this stuff myself, but it all looks
+plausible.</p>
+</div>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title">
+<a name="misc"></a>4. Miscellanea</h2></div></div>
+<div></div>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a href="#limits">4.1. Limitations of the compressed file format</a></span></dt>
+<dt><span class="sect1"><a href="#port-issues">4.2. Portability issues</a></span></dt>
+<dt><span class="sect1"><a href="#bugs">4.3. Reporting bugs</a></span></dt>
+<dt><span class="sect1"><a href="#package">4.4. Did you get the right package?</a></span></dt>
+<dt><span class="sect1"><a href="#reading">4.5. Further Reading</a></span></dt>
+</dl>
+</div>
+<p>These are just some random thoughts of mine.  Your mileage
+may vary.</p>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="limits"></a>4.1. Limitations of the compressed file format</h2></div></div>
+<div></div>
+</div>
+<p><tt class="computeroutput">bzip2-1.0.X</tt>,
+<tt class="computeroutput">0.9.5</tt> and
+<tt class="computeroutput">0.9.0</tt> use exactly the same file
+format as the original version,
+<tt class="computeroutput">bzip2-0.1</tt>.  This decision was
+made in the interests of stability.  Creating yet another
+incompatible compressed file format would create further
+confusion and disruption for users.</p>
+<p>Nevertheless, this is not a painless decision.  Development
+work since the release of
+<tt class="computeroutput">bzip2-0.1</tt> in August 1997 has
+shown complexities in the file format which slow down
+decompression and, in retrospect, are unnecessary.  These
+are:</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p>The run-length encoder, which is the first of the
+   compression transformations, is entirely irrelevant.  The
+   original purpose was to protect the sorting algorithm from the
+   very worst case input: a string of repeated symbols.  But
+   algorithm steps Q6a and Q6b in the original Burrows-Wheeler
+   technical report (SRC-124) show how repeats can be handled
+   without difficulty in block sorting.</p></li>
+<li style="list-style-type: disc">
+<p>The randomisation mechanism doesn't really need to be
+   there.  Udi Manber and Gene Myers published a suffix array
+   construction algorithm a few years back, which can be employed
+   to sort any block, no matter how repetitive, in O(N log N)
+   time.  Subsequent work by Kunihiko Sadakane has produced a
+   derivative O(N (log N)^2) algorithm which usually outperforms
+   the Manber-Myers algorithm.</p>
+<p>I could have changed to Sadakane's algorithm, but I find
+   it to be slower than <tt class="computeroutput">bzip2</tt>'s
+   existing algorithm for most inputs, and the randomisation
+   mechanism protects adequately against bad cases.  I didn't
+   think it was a good tradeoff to make.  Partly this is due to
+   the fact that I was not flooded with email complaints about
+   <tt class="computeroutput">bzip2-0.1</tt>'s performance on
+   repetitive data, so perhaps it isn't a problem for real
+   inputs.</p>
+<p>Probably the best long-term solution, and the one I have
+   incorporated into 0.9.5 and above, is to use the existing
+   sorting algorithm initially, and fall back to a O(N (log N)^2)
+   algorithm if the standard algorithm gets into
+   difficulties.</p>
+</li>
+<li style="list-style-type: disc"><p>The compressed file format was never designed to be
+   handled by a library, and I have had to jump though some hoops
+   to produce an efficient implementation of decompression.  It's
+   a bit hairy.  Try passing
+   <tt class="computeroutput">decompress.c</tt> through the C
+   preprocessor and you'll see what I mean.  Much of this
+   complexity could have been avoided if the compressed size of
+   each block of data was recorded in the data stream.</p></li>
+<li style="list-style-type: disc"><p>An Adler-32 checksum, rather than a CRC32 checksum,
+   would be faster to compute.</p></li>
+</ul></div>
+<p>It would be fair to say that the
+<tt class="computeroutput">bzip2</tt> format was frozen before I
+properly and fully understood the performance consequences of
+doing so.</p>
+<p>Improvements which I was able to incorporate into 0.9.0,
+despite using the same file format, are:</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p>Single array implementation of the inverse BWT.  This
+  significantly speeds up decompression, presumably because it
+  reduces the number of cache misses.</p></li>
+<li style="list-style-type: disc"><p>Faster inverse MTF transform for large MTF values.
+  The new implementation is based on the notion of sliding blocks
+  of values.</p></li>
+<li style="list-style-type: disc"><p><tt class="computeroutput">bzip2-0.9.0</tt> now reads
+  and writes files with <tt class="computeroutput">fread</tt>
+  and <tt class="computeroutput">fwrite</tt>; version 0.1 used
+  <tt class="computeroutput">putc</tt> and
+  <tt class="computeroutput">getc</tt>.  Duh!  Well, you live
+  and learn.</p></li>
+</ul></div>
+<p>Further ahead, it would be nice to be able to do random
+access into files.  This will require some careful design of
+compressed file formats.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="port-issues"></a>4.2. Portability issues</h2></div></div>
+<div></div>
+</div>
+<p>After some consideration, I have decided not to use GNU
+<tt class="computeroutput">autoconf</tt> to configure 0.9.5 or
+1.0.</p>
+<p><tt class="computeroutput">autoconf</tt>, admirable and
+wonderful though it is, mainly assists with portability problems
+between Unix-like platforms.  But
+<tt class="computeroutput">bzip2</tt> doesn't have much in the
+way of portability problems on Unix; most of the difficulties
+appear when porting to the Mac, or to Microsoft's operating
+systems.  <tt class="computeroutput">autoconf</tt> doesn't help
+in those cases, and brings in a whole load of new
+complexity.</p>
+<p>Most people should be able to compile the library and
+program under Unix straight out-of-the-box, so to speak,
+especially if you have a version of GNU C available.</p>
+<p>There are a couple of
+<tt class="computeroutput">__inline__</tt> directives in the
+code.  GNU C (<tt class="computeroutput">gcc</tt>) should be
+able to handle them.  If you're not using GNU C, your C compiler
+shouldn't see them at all.  If your compiler does, for some
+reason, see them and doesn't like them, just
+<tt class="computeroutput">#define</tt>
+<tt class="computeroutput">__inline__</tt> to be
+<tt class="computeroutput">/* */</tt>.  One easy way to do this
+is to compile with the flag
+<tt class="computeroutput">-D__inline__=</tt>, which should be
+understood by most Unix compilers.</p>
+<p>If you still have difficulties, try compiling with the
+macro <tt class="computeroutput">BZ_STRICT_ANSI</tt> defined.
+This should enable you to build the library in a strictly ANSI
+compliant environment.  Building the program itself like this is
+dangerous and not supported, since you remove
+<tt class="computeroutput">bzip2</tt>'s checks against
+compressing directories, symbolic links, devices, and other
+not-really-a-file entities.  This could cause filesystem
+corruption!</p>
+<p>One other thing: if you create a
+<tt class="computeroutput">bzip2</tt> binary for public distribution,
+please consider linking it statically (<tt class="computeroutput">gcc
+-static</tt>).  This avoids all sorts of library-version
+issues that others may encounter later on.</p>
+<p>If you build <tt class="computeroutput">bzip2</tt> on
+Win32, you must set <tt class="computeroutput">BZ_UNIX</tt> to 0
+and <tt class="computeroutput">BZ_LCCWIN32</tt> to 1, in the
+file <tt class="computeroutput">bzip2.c</tt>, before compiling.
+Otherwise the resulting binary won't work correctly.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bugs"></a>4.3. Reporting bugs</h2></div></div>
+<div></div>
+</div>
+<p>I tried pretty hard to make sure
+<tt class="computeroutput">bzip2</tt> is bug free, both by
+design and by testing.  Hopefully you'll never need to read this
+section for real.</p>
+<p>Nevertheless, if <tt class="computeroutput">bzip2</tt> dies
+with a segmentation fault, a bus error or an internal assertion
+failure, it will ask you to email me a bug report.  Experience from
+years of feedback of bzip2 users indicates that almost all these
+problems can be traced to either compiler bugs or hardware
+problems.</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc">
+<p>Recompile the program with no optimisation, and
+  see if it works.  And/or try a different compiler.  I heard all
+  sorts of stories about various flavours of GNU C (and other
+  compilers) generating bad code for
+  <tt class="computeroutput">bzip2</tt>, and I've run across two
+  such examples myself.</p>
+<p>2.7.X versions of GNU C are known to generate bad code
+  from time to time, at high optimisation levels.  If you get
+  problems, try using the flags
+  <tt class="computeroutput">-O2</tt>
+  <tt class="computeroutput">-fomit-frame-pointer</tt>
+  <tt class="computeroutput">-fno-strength-reduce</tt>.  You
+  should specifically <span class="emphasis"><em>not</em></span> use
+  <tt class="computeroutput">-funroll-loops</tt>.</p>
+<p>You may notice that the Makefile runs six tests as part
+  of the build process.  If the program passes all of these, it's
+  a pretty good (but not 100%) indication that the compiler has
+  done its job correctly.</p>
+</li>
+<li style="list-style-type: disc">
+<p>If <tt class="computeroutput">bzip2</tt>
+  crashes randomly, and the crashes are not repeatable, you may
+  have a flaky memory subsystem.
+  <tt class="computeroutput">bzip2</tt> really hammers your
+  memory hierarchy, and if it's a bit marginal, you may get these
+  problems.  Ditto if your disk or I/O subsystem is slowly
+  failing.  Yup, this really does happen.</p>
+<p>Try using a different machine of the same type, and see
+  if you can repeat the problem.</p>
+</li>
+<li style="list-style-type: disc"><p>This isn't really a bug, but ... If
+  <tt class="computeroutput">bzip2</tt> tells you your file is
+  corrupted on decompression, and you obtained the file via FTP,
+  there is a possibility that you forgot to tell FTP to do a
+  binary mode transfer.  That absolutely will cause the file to
+  be non-decompressible.  You'll have to transfer it
+  again.</p></li>
+</ul></div>
+<p>If you've incorporated
+<tt class="computeroutput">libbzip2</tt> into your own program
+and are getting problems, please, please, please, check that the
+parameters you are passing in calls to the library, are correct,
+and in accordance with what the documentation says is allowable.
+I have tried to make the library robust against such problems,
+but I'm sure I haven't succeeded.</p>
+<p>Finally, if the above comments don't help, you'll have to
+send me a bug report.  Now, it's just amazing how many people
+will send me a bug report saying something like:</p>
+<pre class="programlisting">bzip2 crashed with segmentation fault on my machine</pre>
+<p>and absolutely nothing else.  Needless to say, a such a
+report is <span class="emphasis"><em>totally, utterly, completely and
+comprehensively 100% useless; a waste of your time, my time, and
+net bandwidth</em></span>.  With no details at all, there's no way
+I can possibly begin to figure out what the problem is.</p>
+<p>The rules of the game are: facts, facts, facts.  Don't omit
+them because "oh, they won't be relevant".  At the bare
+minimum:</p>
+<pre class="programlisting">Machine type.  Operating system version.  
+Exact version of bzip2 (do bzip2 -V).  
+Exact version of the compiler used.  
+Flags passed to the compiler.</pre>
+<p>However, the most important single thing that will help me
+is the file that you were trying to compress or decompress at the
+time the problem happened.  Without that, my ability to do
+anything more than speculate about the cause, is limited.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="package"></a>4.4. Did you get the right package?</h2></div></div>
+<div></div>
+</div>
+<p><tt class="computeroutput">bzip2</tt> is a resource hog.
+It soaks up large amounts of CPU cycles and memory.  Also, it
+gives very large latencies.  In the worst case, you can feed many
+megabytes of uncompressed data into the library before getting
+any compressed output, so this probably rules out applications
+requiring interactive behaviour.</p>
+<p>These aren't faults of my implementation, I hope, but more
+an intrinsic property of the Burrows-Wheeler transform
+(unfortunately).  Maybe this isn't what you want.</p>
+<p>If you want a compressor and/or library which is faster,
+uses less memory but gets pretty good compression, and has
+minimal latency, consider Jean-loup Gailly's and Mark Adler's
+work, <tt class="computeroutput">zlib-1.2.1</tt> and
+<tt class="computeroutput">gzip-1.2.4</tt>.  Look for them at 
+<a href="http://www.zlib.org" target="_top">http://www.zlib.org</a> and 
+<a href="http://www.gzip.org" target="_top">http://www.gzip.org</a>
+respectively.</p>
+<p>For something faster and lighter still, you might try Markus F
+X J Oberhumer's <tt class="computeroutput">LZO</tt> real-time
+compression/decompression library, at 
+<a href="http://www.oberhumer.com/opensource" target="_top">http://www.oberhumer.com/opensource</a>.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="reading"></a>4.5. Further Reading</h2></div></div>
+<div></div>
+</div>
+<p><tt class="computeroutput">bzip2</tt> is not research
+work, in the sense that it doesn't present any new ideas.
+Rather, it's an engineering exercise based on existing
+ideas.</p>
+<p>Four documents describe essentially all the ideas behind
+<tt class="computeroutput">bzip2</tt>:</p>
+<div class="literallayout"><p>Michael Burrows and D. J. Wheeler:<br>
+  "A block-sorting lossless data compression algorithm"<br>
+   10th May 1994. <br>
+   Digital SRC Research Report 124.<br>
+   ftp://ftp.digital.com/pub/DEC/SRC/research-reports/SRC-124.ps.gz<br>
+   If you have trouble finding it, try searching at the<br>
+   New Zealand Digital Library, http://www.nzdl.org.<br>
+<br>
+Daniel S. Hirschberg and Debra A. LeLewer<br>
+  "Efficient Decoding of Prefix Codes"<br>
+   Communications of the ACM, April 1990, Vol 33, Number 4.<br>
+   You might be able to get an electronic copy of this<br>
+   from the ACM Digital Library.<br>
+<br>
+David J. Wheeler<br>
+   Program bred3.c and accompanying document bred3.ps.<br>
+   This contains the idea behind the multi-table Huffman coding scheme.<br>
+   ftp://ftp.cl.cam.ac.uk/users/djw3/<br>
+<br>
+Jon L. Bentley and Robert Sedgewick<br>
+  "Fast Algorithms for Sorting and Searching Strings"<br>
+   Available from Sedgewick's web page,<br>
+   www.cs.princeton.edu/~rs<br>
+</p></div>
+<p>The following paper gives valuable additional insights into
+the algorithm, but is not immediately the basis of any code used
+in bzip2.</p>
+<div class="literallayout"><p>Peter Fenwick:<br>
+   Block Sorting Text Compression<br>
+   Proceedings of the 19th Australasian Computer Science Conference,<br>
+     Melbourne, Australia.  Jan 31 - Feb 2, 1996.<br>
+   ftp://ftp.cs.auckland.ac.nz/pub/peter-f/ACSC96paper.ps</p></div>
+<p>Kunihiko Sadakane's sorting algorithm, mentioned above, is
+available from:</p>
+<div class="literallayout"><p>http://naomi.is.s.u-tokyo.ac.jp/~sada/papers/Sada98b.ps.gz<br>
+</p></div>
+<p>The Manber-Myers suffix array construction algorithm is
+described in a paper available from:</p>
+<div class="literallayout"><p>http://www.cs.arizona.edu/people/gene/PAPERS/suffix.ps<br>
+</p></div>
+<p>Finally, the following papers document some
+investigations I made into the performance of sorting
+and decompression algorithms:</p>
+<div class="literallayout"><p>Julian Seward<br>
+   On the Performance of BWT Sorting Algorithms<br>
+   Proceedings of the IEEE Data Compression Conference 2000<br>
+     Snowbird, Utah.  28-30 March 2000.<br>
+<br>
+Julian Seward<br>
+   Space-time Tradeoffs in the Inverse B-W Transform<br>
+   Proceedings of the IEEE Data Compression Conference 2001<br>
+     Snowbird, Utah.  27-29 March 2001.<br>
+</p></div>
+</div>
+</div>
+</div></body>
+</html>
Index: /trunk/minix/commands/bzip2-1.0.3/manual.xml
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/manual.xml	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/manual.xml	(revision 9)
@@ -0,0 +1,2966 @@
+<?xml version="1.0"?> <!-- -*- sgml -*- -->
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"[
+
+<!-- various strings, dates etc. common to all docs -->
+<!ENTITY % common-ents SYSTEM "entities.xml"> %common-ents;
+]>
+
+<book lang="en" id="userman" xreflabel="bzip2 Manual">
+
+ <bookinfo>
+  <title>bzip2 and libbzip2, version 1.0.3</title>
+  <subtitle>A program and library for data compression</subtitle>
+  <copyright>
+   <year>&bz-lifespan;</year>
+   <holder>Julian Seward</holder>
+  </copyright>
+  <releaseinfo>Version &bz-version; of &bz-date;</releaseinfo>
+
+  <authorgroup>
+   <author>
+    <firstname>Julian</firstname>
+    <surname>Seward</surname>
+    <affiliation>
+     <orgname>&bz-url;</orgname>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <legalnotice>
+
+  <para>This program, <computeroutput>bzip2</computeroutput>, the
+  associated library <computeroutput>libbzip2</computeroutput>, and
+  all documentation, are copyright &copy; &bz-lifespan; Julian Seward.
+  All rights reserved.</para>
+
+  <para>Redistribution and use in source and binary forms, with
+  or without modification, are permitted provided that the
+  following conditions are met:</para>
+
+  <itemizedlist mark='bullet'>
+
+   <listitem><para>Redistributions of source code must retain the
+   above copyright notice, this list of conditions and the
+   following disclaimer.</para></listitem>
+
+   <listitem><para>The origin of this software must not be
+   misrepresented; you must not claim that you wrote the original
+   software.  If you use this software in a product, an
+   acknowledgment in the product documentation would be
+   appreciated but is not required.</para></listitem>
+
+   <listitem><para>Altered source versions must be plainly marked
+   as such, and must not be misrepresented as being the original
+   software.</para></listitem>
+
+   <listitem><para>The name of the author may not be used to
+   endorse or promote products derived from this software without
+   specific prior written permission.</para></listitem>
+
+  </itemizedlist>
+
+  <para>THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY
+  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+  AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+  THE POSSIBILITY OF SUCH DAMAGE.</para>
+
+ <para>PATENTS: To the best of my knowledge,
+ <computeroutput>bzip2</computeroutput> and
+ <computeroutput>libbzip2</computeroutput> do not use any patented
+ algorithms.  However, I do not have the resources to carry
+ out a patent search.  Therefore I cannot give any guarantee of
+ the above statement.
+ </para>
+
+</legalnotice>
+
+</bookinfo>
+
+
+
+<chapter id="intro" xreflabel="Introduction">
+<title>Introduction</title>
+
+<para><computeroutput>bzip2</computeroutput> compresses files
+using the Burrows-Wheeler block-sorting text compression
+algorithm, and Huffman coding.  Compression is generally
+considerably better than that achieved by more conventional
+LZ77/LZ78-based compressors, and approaches the performance of
+the PPM family of statistical compressors.</para>
+
+<para><computeroutput>bzip2</computeroutput> is built on top of
+<computeroutput>libbzip2</computeroutput>, a flexible library for
+handling compressed data in the
+<computeroutput>bzip2</computeroutput> format.  This manual
+describes both how to use the program and how to work with the
+library interface.  Most of the manual is devoted to this
+library, not the program, which is good news if your interest is
+only in the program.</para>
+
+<itemizedlist mark='bullet'>
+
+ <listitem><para><xref linkend="using"/> describes how to use
+ <computeroutput>bzip2</computeroutput>; this is the only part
+ you need to read if you just want to know how to operate the
+ program.</para></listitem>
+
+ <listitem><para><xref linkend="libprog"/> describes the
+ programming interfaces in detail, and</para></listitem>
+
+ <listitem><para><xref linkend="misc"/> records some
+ miscellaneous notes which I thought ought to be recorded
+ somewhere.</para></listitem>
+
+</itemizedlist>
+
+</chapter>
+
+
+<chapter id="using" xreflabel="How to use bzip2">
+<title>How to use bzip2</title>
+
+<para>This chapter contains a copy of the
+<computeroutput>bzip2</computeroutput> man page, and nothing
+else.</para>
+
+<sect1 id="name" xreflabel="NAME">
+<title>NAME</title>
+
+<itemizedlist mark='bullet'>
+
+ <listitem><para><computeroutput>bzip2</computeroutput>,
+  <computeroutput>bunzip2</computeroutput> - a block-sorting file
+  compressor, v1.0.3</para></listitem>
+
+ <listitem><para><computeroutput>bzcat</computeroutput> -
+   decompresses files to stdout</para></listitem>
+
+ <listitem><para><computeroutput>bzip2recover</computeroutput> -
+   recovers data from damaged bzip2 files</para></listitem>
+
+</itemizedlist>
+
+</sect1>
+
+
+<sect1 id="synopsis" xreflabel="SYNOPSIS">
+<title>SYNOPSIS</title>
+
+<itemizedlist mark='bullet'>
+
+ <listitem><para><computeroutput>bzip2</computeroutput> [
+  -cdfkqstvzVL123456789 ] [ filenames ...  ]</para></listitem>
+
+ <listitem><para><computeroutput>bunzip2</computeroutput> [
+  -fkvsVL ] [ filenames ...  ]</para></listitem>
+
+ <listitem><para><computeroutput>bzcat</computeroutput> [ -s ] [
+  filenames ...  ]</para></listitem>
+
+ <listitem><para><computeroutput>bzip2recover</computeroutput>
+  filename</para></listitem>
+
+</itemizedlist>
+
+</sect1>
+
+
+<sect1 id="description" xreflabel="DESCRIPTION">
+<title>DESCRIPTION</title>
+
+<para><computeroutput>bzip2</computeroutput> compresses files
+using the Burrows-Wheeler block sorting text compression
+algorithm, and Huffman coding.  Compression is generally
+considerably better than that achieved by more conventional
+LZ77/LZ78-based compressors, and approaches the performance of
+the PPM family of statistical compressors.</para>
+
+<para>The command-line options are deliberately very similar to
+those of GNU <computeroutput>gzip</computeroutput>, but they are
+not identical.</para>
+
+<para><computeroutput>bzip2</computeroutput> expects a list of
+file names to accompany the command-line flags.  Each file is
+replaced by a compressed version of itself, with the name
+<computeroutput>original_name.bz2</computeroutput>.  Each
+compressed file has the same modification date, permissions, and,
+when possible, ownership as the corresponding original, so that
+these properties can be correctly restored at decompression time.
+File name handling is naive in the sense that there is no
+mechanism for preserving original file names, permissions,
+ownerships or dates in filesystems which lack these concepts, or
+have serious file name length restrictions, such as
+MS-DOS.</para>
+
+<para><computeroutput>bzip2</computeroutput> and
+<computeroutput>bunzip2</computeroutput> will by default not
+overwrite existing files.  If you want this to happen, specify
+the <computeroutput>-f</computeroutput> flag.</para>
+
+<para>If no file names are specified,
+<computeroutput>bzip2</computeroutput> compresses from standard
+input to standard output.  In this case,
+<computeroutput>bzip2</computeroutput> will decline to write
+compressed output to a terminal, as this would be entirely
+incomprehensible and therefore pointless.</para>
+
+<para><computeroutput>bunzip2</computeroutput> (or
+<computeroutput>bzip2 -d</computeroutput>) decompresses all
+specified files.  Files which were not created by
+<computeroutput>bzip2</computeroutput> will be detected and
+ignored, and a warning issued.
+<computeroutput>bzip2</computeroutput> attempts to guess the
+filename for the decompressed file from that of the compressed
+file as follows:</para>
+
+<itemizedlist mark='bullet'>
+
+ <listitem><para><computeroutput>filename.bz2 </computeroutput>
+  becomes
+  <computeroutput>filename</computeroutput></para></listitem>
+
+ <listitem><para><computeroutput>filename.bz </computeroutput>
+  becomes
+  <computeroutput>filename</computeroutput></para></listitem>
+
+ <listitem><para><computeroutput>filename.tbz2</computeroutput>
+  becomes
+  <computeroutput>filename.tar</computeroutput></para></listitem>
+
+ <listitem><para><computeroutput>filename.tbz </computeroutput>
+  becomes
+  <computeroutput>filename.tar</computeroutput></para></listitem>
+
+ <listitem><para><computeroutput>anyothername </computeroutput>
+  becomes
+  <computeroutput>anyothername.out</computeroutput></para></listitem>
+
+</itemizedlist>
+
+<para>If the file does not end in one of the recognised endings,
+<computeroutput>.bz2</computeroutput>,
+<computeroutput>.bz</computeroutput>,
+<computeroutput>.tbz2</computeroutput> or
+<computeroutput>.tbz</computeroutput>,
+<computeroutput>bzip2</computeroutput> complains that it cannot
+guess the name of the original file, and uses the original name
+with <computeroutput>.out</computeroutput> appended.</para>
+
+<para>As with compression, supplying no filenames causes
+decompression from standard input to standard output.</para>
+
+<para><computeroutput>bunzip2</computeroutput> will correctly
+decompress a file which is the concatenation of two or more
+compressed files.  The result is the concatenation of the
+corresponding uncompressed files.  Integrity testing
+(<computeroutput>-t</computeroutput>) of concatenated compressed
+files is also supported.</para>
+
+<para>You can also compress or decompress files to the standard
+output by giving the <computeroutput>-c</computeroutput> flag.
+Multiple files may be compressed and decompressed like this.  The
+resulting outputs are fed sequentially to stdout.  Compression of
+multiple files in this manner generates a stream containing
+multiple compressed file representations.  Such a stream can be
+decompressed correctly only by
+<computeroutput>bzip2</computeroutput> version 0.9.0 or later.
+Earlier versions of <computeroutput>bzip2</computeroutput> will
+stop after decompressing the first file in the stream.</para>
+
+<para><computeroutput>bzcat</computeroutput> (or
+<computeroutput>bzip2 -dc</computeroutput>) decompresses all
+specified files to the standard output.</para>
+
+<para><computeroutput>bzip2</computeroutput> will read arguments
+from the environment variables
+<computeroutput>BZIP2</computeroutput> and
+<computeroutput>BZIP</computeroutput>, in that order, and will
+process them before any arguments read from the command line.
+This gives a convenient way to supply default arguments.</para>
+
+<para>Compression is always performed, even if the compressed
+file is slightly larger than the original.  Files of less than
+about one hundred bytes tend to get larger, since the compression
+mechanism has a constant overhead in the region of 50 bytes.
+Random data (including the output of most file compressors) is
+coded at about 8.05 bits per byte, giving an expansion of around
+0.5%.</para>
+
+<para>As a self-check for your protection,
+<computeroutput>bzip2</computeroutput> uses 32-bit CRCs to make
+sure that the decompressed version of a file is identical to the
+original.  This guards against corruption of the compressed data,
+and against undetected bugs in
+<computeroutput>bzip2</computeroutput> (hopefully very unlikely).
+The chances of data corruption going undetected is microscopic,
+about one chance in four billion for each file processed.  Be
+aware, though, that the check occurs upon decompression, so it
+can only tell you that something is wrong.  It can't help you
+recover the original uncompressed data.  You can use
+<computeroutput>bzip2recover</computeroutput> to try to recover
+data from damaged files.</para>
+
+<para>Return values: 0 for a normal exit, 1 for environmental
+problems (file not found, invalid flags, I/O errors, etc.), 2
+to indicate a corrupt compressed file, 3 for an internal
+consistency error (eg, bug) which caused
+<computeroutput>bzip2</computeroutput> to panic.</para>
+
+</sect1>
+
+
+<sect1 id="options" xreflabel="OPTIONS">
+<title>OPTIONS</title>
+
+<variablelist>
+
+ <varlistentry>
+ <term><computeroutput>-c --stdout</computeroutput></term>
+ <listitem><para>Compress or decompress to standard
+  output.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>-d --decompress</computeroutput></term>
+ <listitem><para>Force decompression.
+  <computeroutput>bzip2</computeroutput>,
+  <computeroutput>bunzip2</computeroutput> and
+  <computeroutput>bzcat</computeroutput> are really the same
+  program, and the decision about what actions to take is done on
+  the basis of which name is used.  This flag overrides that
+  mechanism, and forces bzip2 to decompress.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>-z --compress</computeroutput></term>
+ <listitem><para>The complement to
+  <computeroutput>-d</computeroutput>: forces compression,
+  regardless of the invokation name.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>-t --test</computeroutput></term>
+ <listitem><para>Check integrity of the specified file(s), but
+  don't decompress them.  This really performs a trial
+  decompression and throws away the result.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>-f --force</computeroutput></term>
+ <listitem><para>Force overwrite of output files.  Normally,
+  <computeroutput>bzip2</computeroutput> will not overwrite
+  existing output files.  Also forces
+  <computeroutput>bzip2</computeroutput> to break hard links to
+  files, which it otherwise wouldn't do.</para>
+  <para><computeroutput>bzip2</computeroutput> normally declines
+  to decompress files which don't have the correct magic header
+  bytes. If forced (<computeroutput>-f</computeroutput>),
+  however, it will pass such files through unmodified. This is
+  how GNU <computeroutput>gzip</computeroutput> behaves.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>-k --keep</computeroutput></term>
+ <listitem><para>Keep (don't delete) input files during
+  compression or decompression.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>-s --small</computeroutput></term>
+ <listitem><para>Reduce memory usage, for compression,
+  decompression and testing.  Files are decompressed and tested
+  using a modified algorithm which only requires 2.5 bytes per
+  block byte.  This means any file can be decompressed in 2300k
+  of memory, albeit at about half the normal speed.</para>
+  <para>During compression, <computeroutput>-s</computeroutput>
+  selects a block size of 200k, which limits memory use to around
+  the same figure, at the expense of your compression ratio.  In
+  short, if your machine is low on memory (8 megabytes or less),
+  use <computeroutput>-s</computeroutput> for everything.  See
+  <xref linkend="memory-management"/> below.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>-q --quiet</computeroutput></term>
+ <listitem><para>Suppress non-essential warning messages.
+  Messages pertaining to I/O errors and other critical events
+  will not be suppressed.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>-v --verbose</computeroutput></term>
+ <listitem><para>Verbose mode -- show the compression ratio for
+  each file processed.  Further
+  <computeroutput>-v</computeroutput>'s increase the verbosity
+  level, spewing out lots of information which is primarily of
+  interest for diagnostic purposes.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>-L --license -V --version</computeroutput></term>
+ <listitem><para>Display the software version, license terms and
+  conditions.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>-1</computeroutput> (or
+ <computeroutput>--fast</computeroutput>) to
+ <computeroutput>-9</computeroutput> (or
+ <computeroutput>-best</computeroutput>)</term>
+ <listitem><para>Set the block size to 100 k, 200 k ...  900 k
+  when compressing.  Has no effect when decompressing.  See <xref
+  linkend="memory-management" /> below.  The
+  <computeroutput>--fast</computeroutput> and
+  <computeroutput>--best</computeroutput> aliases are primarily
+  for GNU <computeroutput>gzip</computeroutput> compatibility.
+  In particular, <computeroutput>--fast</computeroutput> doesn't
+  make things significantly faster.  And
+  <computeroutput>--best</computeroutput> merely selects the
+  default behaviour.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>--</computeroutput></term>
+ <listitem><para>Treats all subsequent arguments as file names,
+  even if they start with a dash.  This is so you can handle
+  files with names beginning with a dash, for example:
+  <computeroutput>bzip2 --
+  -myfilename</computeroutput>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><computeroutput>--repetitive-fast</computeroutput></term>
+ <term><computeroutput>--repetitive-best</computeroutput></term>
+ <listitem><para>These flags are redundant in versions 0.9.5 and
+  above.  They provided some coarse control over the behaviour of
+  the sorting algorithm in earlier versions, which was sometimes
+  useful.  0.9.5 and above have an improved algorithm which
+  renders these flags irrelevant.</para></listitem>
+ </varlistentry>
+
+</variablelist>
+
+</sect1>
+
+
+<sect1 id="memory-management" xreflabel="MEMORY MANAGEMENT">
+<title>MEMORY MANAGEMENT</title>
+
+<para><computeroutput>bzip2</computeroutput> compresses large
+files in blocks.  The block size affects both the compression
+ratio achieved, and the amount of memory needed for compression
+and decompression.  The flags <computeroutput>-1</computeroutput>
+through <computeroutput>-9</computeroutput> specify the block
+size to be 100,000 bytes through 900,000 bytes (the default)
+respectively.  At decompression time, the block size used for
+compression is read from the header of the compressed file, and
+<computeroutput>bunzip2</computeroutput> then allocates itself
+just enough memory to decompress the file.  Since block sizes are
+stored in compressed files, it follows that the flags
+<computeroutput>-1</computeroutput> to
+<computeroutput>-9</computeroutput> are irrelevant to and so
+ignored during decompression.</para>
+
+<para>Compression and decompression requirements, in bytes, can be
+estimated as:</para>
+<programlisting>
+Compression:   400k + ( 8 x block size )
+
+Decompression: 100k + ( 4 x block size ), or
+               100k + ( 2.5 x block size )
+</programlisting>
+
+<para>Larger block sizes give rapidly diminishing marginal
+returns.  Most of the compression comes from the first two or
+three hundred k of block size, a fact worth bearing in mind when
+using <computeroutput>bzip2</computeroutput> on small machines.
+It is also important to appreciate that the decompression memory
+requirement is set at compression time by the choice of block
+size.</para>
+
+<para>For files compressed with the default 900k block size,
+<computeroutput>bunzip2</computeroutput> will require about 3700
+kbytes to decompress.  To support decompression of any file on a
+4 megabyte machine, <computeroutput>bunzip2</computeroutput> has
+an option to decompress using approximately half this amount of
+memory, about 2300 kbytes.  Decompression speed is also halved,
+so you should use this option only where necessary.  The relevant
+flag is <computeroutput>-s</computeroutput>.</para>
+
+<para>In general, try and use the largest block size memory
+constraints allow, since that maximises the compression achieved.
+Compression and decompression speed are virtually unaffected by
+block size.</para>
+
+<para>Another significant point applies to files which fit in a
+single block -- that means most files you'd encounter using a
+large block size.  The amount of real memory touched is
+proportional to the size of the file, since the file is smaller
+than a block.  For example, compressing a file 20,000 bytes long
+with the flag <computeroutput>-9</computeroutput> will cause the
+compressor to allocate around 7600k of memory, but only touch
+400k + 20000 * 8 = 560 kbytes of it.  Similarly, the decompressor
+will allocate 3700k but only touch 100k + 20000 * 4 = 180
+kbytes.</para>
+
+<para>Here is a table which summarises the maximum memory usage
+for different block sizes.  Also recorded is the total compressed
+size for 14 files of the Calgary Text Compression Corpus
+totalling 3,141,622 bytes.  This column gives some feel for how
+compression varies with block size.  These figures tend to
+understate the advantage of larger block sizes for larger files,
+since the Corpus is dominated by smaller files.</para>
+
+<programlisting>
+        Compress   Decompress   Decompress   Corpus
+Flag     usage      usage       -s usage     Size
+
+ -1      1200k       500k         350k      914704
+ -2      2000k       900k         600k      877703
+ -3      2800k      1300k         850k      860338
+ -4      3600k      1700k        1100k      846899
+ -5      4400k      2100k        1350k      845160
+ -6      5200k      2500k        1600k      838626
+ -7      6100k      2900k        1850k      834096
+ -8      6800k      3300k        2100k      828642
+ -9      7600k      3700k        2350k      828642
+</programlisting>
+
+</sect1>
+
+
+<sect1 id="recovering" xreflabel="RECOVERING DATA FROM DAMAGED FILES">
+<title>RECOVERING DATA FROM DAMAGED FILES</title>
+
+<para><computeroutput>bzip2</computeroutput> compresses files in
+blocks, usually 900kbytes long.  Each block is handled
+independently.  If a media or transmission error causes a
+multi-block <computeroutput>.bz2</computeroutput> file to become
+damaged, it may be possible to recover data from the undamaged
+blocks in the file.</para>
+
+<para>The compressed representation of each block is delimited by
+a 48-bit pattern, which makes it possible to find the block
+boundaries with reasonable certainty.  Each block also carries
+its own 32-bit CRC, so damaged blocks can be distinguished from
+undamaged ones.</para>
+
+<para><computeroutput>bzip2recover</computeroutput> is a simple
+program whose purpose is to search for blocks in
+<computeroutput>.bz2</computeroutput> files, and write each block
+out into its own <computeroutput>.bz2</computeroutput> file.  You
+can then use <computeroutput>bzip2 -t</computeroutput> to test
+the integrity of the resulting files, and decompress those which
+are undamaged.</para>
+
+<para><computeroutput>bzip2recover</computeroutput> takes a
+single argument, the name of the damaged file, and writes a
+number of files <computeroutput>rec0001file.bz2</computeroutput>,
+<computeroutput>rec0002file.bz2</computeroutput>, etc, containing
+the extracted blocks.  The output filenames are designed so that
+the use of wildcards in subsequent processing -- for example,
+<computeroutput>bzip2 -dc rec*file.bz2 &#62;
+recovered_data</computeroutput> -- lists the files in the correct
+order.</para>
+
+<para><computeroutput>bzip2recover</computeroutput> should be of
+most use dealing with large <computeroutput>.bz2</computeroutput>
+files, as these will contain many blocks.  It is clearly futile
+to use it on damaged single-block files, since a damaged block
+cannot be recovered.  If you wish to minimise any potential data
+loss through media or transmission errors, you might consider
+compressing with a smaller block size.</para>
+
+</sect1>
+
+
+<sect1 id="performance" xreflabel="PERFORMANCE NOTES">
+<title>PERFORMANCE NOTES</title>
+
+<para>The sorting phase of compression gathers together similar
+strings in the file.  Because of this, files containing very long
+runs of repeated symbols, like "aabaabaabaab ..."  (repeated
+several hundred times) may compress more slowly than normal.
+Versions 0.9.5 and above fare much better than previous versions
+in this respect.  The ratio between worst-case and average-case
+compression time is in the region of 10:1.  For previous
+versions, this figure was more like 100:1.  You can use the
+<computeroutput>-vvvv</computeroutput> option to monitor progress
+in great detail, if you want.</para>
+
+<para>Decompression speed is unaffected by these
+phenomena.</para>
+
+<para><computeroutput>bzip2</computeroutput> usually allocates
+several megabytes of memory to operate in, and then charges all
+over it in a fairly random fashion.  This means that performance,
+both for compressing and decompressing, is largely determined by
+the speed at which your machine can service cache misses.
+Because of this, small changes to the code to reduce the miss
+rate have been observed to give disproportionately large
+performance improvements.  I imagine
+<computeroutput>bzip2</computeroutput> will perform best on
+machines with very large caches.</para>
+
+</sect1>
+
+
+
+<sect1 id="caveats" xreflabel="CAVEATS">
+<title>CAVEATS</title>
+
+<para>I/O error messages are not as helpful as they could be.
+<computeroutput>bzip2</computeroutput> tries hard to detect I/O
+errors and exit cleanly, but the details of what the problem is
+sometimes seem rather misleading.</para>
+
+<para>This manual page pertains to version &bz-version; of
+<computeroutput>bzip2</computeroutput>.  Compressed data created
+by this version is entirely forwards and backwards compatible
+with the previous public releases, versions 0.1pl2, 0.9.0 and
+0.9.5, 1.0.0, 1.0.1 and 1.0.2, but with the following exception: 0.9.0
+and above can correctly decompress multiple concatenated
+compressed files.  0.1pl2 cannot do this; it will stop after
+decompressing just the first file in the stream.</para>
+
+<para><computeroutput>bzip2recover</computeroutput> versions
+prior to 1.0.2 used 32-bit integers to represent bit positions in
+compressed files, so it could not handle compressed files more
+than 512 megabytes long.  Versions 1.0.2 and above use 64-bit ints
+on some platforms which support them (GNU supported targets, and
+Windows). To establish whether or not
+<computeroutput>bzip2recover</computeroutput> was built with such
+a limitation, run it without arguments. In any event you can
+build yourself an unlimited version if you can recompile it with
+<computeroutput>MaybeUInt64</computeroutput> set to be an
+unsigned 64-bit integer.</para>
+
+</sect1>
+
+
+
+<sect1 id="author" xreflabel="AUTHOR">
+<title>AUTHOR</title>
+
+<para>Julian Seward,
+<computeroutput>&bz-email;</computeroutput></para>
+
+<para>The ideas embodied in
+<computeroutput>bzip2</computeroutput> are due to (at least) the
+following people: Michael Burrows and David Wheeler (for the
+block sorting transformation), David Wheeler (again, for the
+Huffman coder), Peter Fenwick (for the structured coding model in
+the original <computeroutput>bzip</computeroutput>, and many
+refinements), and Alistair Moffat, Radford Neal and Ian Witten
+(for the arithmetic coder in the original
+<computeroutput>bzip</computeroutput>).  I am much indebted for
+their help, support and advice.  See the manual in the source
+distribution for pointers to sources of documentation.  Christian
+von Roques encouraged me to look for faster sorting algorithms,
+so as to speed up compression.  Bela Lubkin encouraged me to
+improve the worst-case compression performance.  
+Donna Robinson XMLised the documentation.
+Many people sent
+patches, helped with portability problems, lent machines, gave
+advice and were generally helpful.</para>
+
+</sect1>
+
+</chapter>
+
+
+
+<chapter id="libprog" xreflabel="Programming with libbzip2">
+<title>
+Programming with <computeroutput>libbzip2</computeroutput>
+</title>
+
+<para>This chapter describes the programming interface to
+<computeroutput>libbzip2</computeroutput>.</para>
+
+<para>For general background information, particularly about
+memory use and performance aspects, you'd be well advised to read
+<xref linkend="using"/> as well.</para>
+
+
+<sect1 id="top-level" xreflabel="Top-level structure">
+<title>Top-level structure</title>
+
+<para><computeroutput>libbzip2</computeroutput> is a flexible
+library for compressing and decompressing data in the
+<computeroutput>bzip2</computeroutput> data format.  Although
+packaged as a single entity, it helps to regard the library as
+three separate parts: the low level interface, and the high level
+interface, and some utility functions.</para>
+
+<para>The structure of
+<computeroutput>libbzip2</computeroutput>'s interfaces is similar
+to that of Jean-loup Gailly's and Mark Adler's excellent
+<computeroutput>zlib</computeroutput> library.</para>
+
+<para>All externally visible symbols have names beginning
+<computeroutput>BZ2_</computeroutput>.  This is new in version
+1.0.  The intention is to minimise pollution of the namespaces of
+library clients.</para>
+
+<para>To use any part of the library, you need to
+<computeroutput>#include &lt;bzlib.h&gt;</computeroutput>
+into your sources.</para>
+
+
+
+<sect2 id="ll-summary" xreflabel="Low-level summary">
+<title>Low-level summary</title>
+
+<para>This interface provides services for compressing and
+decompressing data in memory.  There's no provision for dealing
+with files, streams or any other I/O mechanisms, just straight
+memory-to-memory work.  In fact, this part of the library can be
+compiled without inclusion of
+<computeroutput>stdio.h</computeroutput>, which may be helpful
+for embedded applications.</para>
+
+<para>The low-level part of the library has no global variables
+and is therefore thread-safe.</para>
+
+<para>Six routines make up the low level interface:
+<computeroutput>BZ2_bzCompressInit</computeroutput>,
+<computeroutput>BZ2_bzCompress</computeroutput>, and
+<computeroutput>BZ2_bzCompressEnd</computeroutput> for
+compression, and a corresponding trio
+<computeroutput>BZ2_bzDecompressInit</computeroutput>,
+<computeroutput>BZ2_bzDecompress</computeroutput> and
+<computeroutput>BZ2_bzDecompressEnd</computeroutput> for
+decompression.  The <computeroutput>*Init</computeroutput>
+functions allocate memory for compression/decompression and do
+other initialisations, whilst the
+<computeroutput>*End</computeroutput> functions close down
+operations and release memory.</para>
+
+<para>The real work is done by
+<computeroutput>BZ2_bzCompress</computeroutput> and
+<computeroutput>BZ2_bzDecompress</computeroutput>.  These
+compress and decompress data from a user-supplied input buffer to
+a user-supplied output buffer.  These buffers can be any size;
+arbitrary quantities of data are handled by making repeated calls
+to these functions.  This is a flexible mechanism allowing a
+consumer-pull style of activity, or producer-push, or a mixture
+of both.</para>
+
+</sect2>
+
+
+<sect2 id="hl-summary" xreflabel="High-level summary">
+<title>High-level summary</title>
+
+<para>This interface provides some handy wrappers around the
+low-level interface to facilitate reading and writing
+<computeroutput>bzip2</computeroutput> format files
+(<computeroutput>.bz2</computeroutput> files).  The routines
+provide hooks to facilitate reading files in which the
+<computeroutput>bzip2</computeroutput> data stream is embedded
+within some larger-scale file structure, or where there are
+multiple <computeroutput>bzip2</computeroutput> data streams
+concatenated end-to-end.</para>
+
+<para>For reading files,
+<computeroutput>BZ2_bzReadOpen</computeroutput>,
+<computeroutput>BZ2_bzRead</computeroutput>,
+<computeroutput>BZ2_bzReadClose</computeroutput> and 
+<computeroutput>BZ2_bzReadGetUnused</computeroutput> are
+supplied.  For writing files,
+<computeroutput>BZ2_bzWriteOpen</computeroutput>,
+<computeroutput>BZ2_bzWrite</computeroutput> and
+<computeroutput>BZ2_bzWriteFinish</computeroutput> are
+available.</para>
+
+<para>As with the low-level library, no global variables are used
+so the library is per se thread-safe.  However, if I/O errors
+occur whilst reading or writing the underlying compressed files,
+you may have to consult <computeroutput>errno</computeroutput> to
+determine the cause of the error.  In that case, you'd need a C
+library which correctly supports
+<computeroutput>errno</computeroutput> in a multithreaded
+environment.</para>
+
+<para>To make the library a little simpler and more portable,
+<computeroutput>BZ2_bzReadOpen</computeroutput> and
+<computeroutput>BZ2_bzWriteOpen</computeroutput> require you to
+pass them file handles (<computeroutput>FILE*</computeroutput>s)
+which have previously been opened for reading or writing
+respectively.  That avoids portability problems associated with
+file operations and file attributes, whilst not being much of an
+imposition on the programmer.</para>
+
+</sect2>
+
+
+<sect2 id="util-fns-summary" xreflabel="Utility functions summary">
+<title>Utility functions summary</title>
+
+<para>For very simple needs,
+<computeroutput>BZ2_bzBuffToBuffCompress</computeroutput> and
+<computeroutput>BZ2_bzBuffToBuffDecompress</computeroutput> are
+provided.  These compress data in memory from one buffer to
+another buffer in a single function call.  You should assess
+whether these functions fulfill your memory-to-memory
+compression/decompression requirements before investing effort in
+understanding the more general but more complex low-level
+interface.</para>
+
+<para>Yoshioka Tsuneo
+(<computeroutput>QWF00133@niftyserve.or.jp</computeroutput> /
+<computeroutput>tsuneo-y@is.aist-nara.ac.jp</computeroutput>) has
+contributed some functions to give better
+<computeroutput>zlib</computeroutput> compatibility.  These
+functions are <computeroutput>BZ2_bzopen</computeroutput>,
+<computeroutput>BZ2_bzread</computeroutput>,
+<computeroutput>BZ2_bzwrite</computeroutput>,
+<computeroutput>BZ2_bzflush</computeroutput>,
+<computeroutput>BZ2_bzclose</computeroutput>,
+<computeroutput>BZ2_bzerror</computeroutput> and
+<computeroutput>BZ2_bzlibVersion</computeroutput>.  You may find
+these functions more convenient for simple file reading and
+writing, than those in the high-level interface.  These functions
+are not (yet) officially part of the library, and are minimally
+documented here.  If they break, you get to keep all the pieces.
+I hope to document them properly when time permits.</para>
+
+<para>Yoshioka also contributed modifications to allow the
+library to be built as a Windows DLL.</para>
+
+</sect2>
+
+</sect1>
+
+
+<sect1 id="err-handling" xreflabel="Error handling">
+<title>Error handling</title>
+
+<para>The library is designed to recover cleanly in all
+situations, including the worst-case situation of decompressing
+random data.  I'm not 100% sure that it can always do this, so
+you might want to add a signal handler to catch segmentation
+violations during decompression if you are feeling especially
+paranoid.  I would be interested in hearing more about the
+robustness of the library to corrupted compressed data.</para>
+
+<para>Version 1.0.3 more robust in this respect than any
+previous version.  Investigations with Valgrind (a tool for detecting
+problems with memory management) indicate
+that, at least for the few files I tested, all single-bit errors
+in the decompressed data are caught properly, with no
+segmentation faults, no uses of uninitialised data, no out of
+range reads or writes, and no infinite looping in the decompressor.
+So it's certainly pretty robust, although
+I wouldn't claim it to be totally bombproof.</para>
+
+<para>The file <computeroutput>bzlib.h</computeroutput> contains
+all definitions needed to use the library.  In particular, you
+should definitely not include
+<computeroutput>bzlib_private.h</computeroutput>.</para>
+
+<para>In <computeroutput>bzlib.h</computeroutput>, the various
+return values are defined.  The following list is not intended as
+an exhaustive description of the circumstances in which a given
+value may be returned -- those descriptions are given later.
+Rather, it is intended to convey the rough meaning of each return
+value.  The first five actions are normal and not intended to
+denote an error situation.</para>
+
+<variablelist>
+
+ <varlistentry>
+  <term><computeroutput>BZ_OK</computeroutput></term>
+  <listitem><para>The requested action was completed
+   successfully.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+  <term><computeroutput>BZ_RUN_OK, BZ_FLUSH_OK,
+    BZ_FINISH_OK</computeroutput></term>
+  <listitem><para>In 
+   <computeroutput>BZ2_bzCompress</computeroutput>, the requested
+   flush/finish/nothing-special action was completed
+   successfully.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+  <term><computeroutput>BZ_STREAM_END</computeroutput></term>
+  <listitem><para>Compression of data was completed, or the
+   logical stream end was detected during
+   decompression.</para></listitem>
+ </varlistentry>
+
+</variablelist>
+
+<para>The following return values indicate an error of some
+kind.</para>
+
+<variablelist>
+
+ <varlistentry>
+  <term><computeroutput>BZ_CONFIG_ERROR</computeroutput></term>
+  <listitem><para>Indicates that the library has been improperly
+   compiled on your platform -- a major configuration error.
+   Specifically, it means that
+   <computeroutput>sizeof(char)</computeroutput>,
+   <computeroutput>sizeof(short)</computeroutput> and
+   <computeroutput>sizeof(int)</computeroutput> are not 1, 2 and
+   4 respectively, as they should be.  Note that the library
+   should still work properly on 64-bit platforms which follow
+   the LP64 programming model -- that is, where
+   <computeroutput>sizeof(long)</computeroutput> and
+   <computeroutput>sizeof(void*)</computeroutput> are 8.  Under
+   LP64, <computeroutput>sizeof(int)</computeroutput> is still 4,
+   so <computeroutput>libbzip2</computeroutput>, which doesn't
+   use the <computeroutput>long</computeroutput> type, is
+   OK.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+  <term><computeroutput>BZ_SEQUENCE_ERROR</computeroutput></term>
+  <listitem><para>When using the library, it is important to call
+   the functions in the correct sequence and with data structures
+   (buffers etc) in the correct states.
+   <computeroutput>libbzip2</computeroutput> checks as much as it
+   can to ensure this is happening, and returns
+   <computeroutput>BZ_SEQUENCE_ERROR</computeroutput> if not.
+   Code which complies precisely with the function semantics, as
+   detailed below, should never receive this value; such an event
+   denotes buggy code which you should
+   investigate.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+  <term><computeroutput>BZ_PARAM_ERROR</computeroutput></term>
+  <listitem><para>Returned when a parameter to a function call is
+   out of range or otherwise manifestly incorrect.  As with
+   <computeroutput>BZ_SEQUENCE_ERROR</computeroutput>, this
+   denotes a bug in the client code.  The distinction between
+   <computeroutput>BZ_PARAM_ERROR</computeroutput> and
+   <computeroutput>BZ_SEQUENCE_ERROR</computeroutput> is a bit
+   hazy, but still worth making.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+  <term><computeroutput>BZ_MEM_ERROR</computeroutput></term>
+  <listitem><para>Returned when a request to allocate memory
+   failed.  Note that the quantity of memory needed to decompress
+   a stream cannot be determined until the stream's header has
+   been read.  So
+   <computeroutput>BZ2_bzDecompress</computeroutput> and
+   <computeroutput>BZ2_bzRead</computeroutput> may return
+   <computeroutput>BZ_MEM_ERROR</computeroutput> even though some
+   of the compressed data has been read.  The same is not true
+   for compression; once
+   <computeroutput>BZ2_bzCompressInit</computeroutput> or
+   <computeroutput>BZ2_bzWriteOpen</computeroutput> have
+   successfully completed,
+   <computeroutput>BZ_MEM_ERROR</computeroutput> cannot
+   occur.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+  <term><computeroutput>BZ_DATA_ERROR</computeroutput></term>
+  <listitem><para>Returned when a data integrity error is
+   detected during decompression.  Most importantly, this means
+   when stored and computed CRCs for the data do not match.  This
+   value is also returned upon detection of any other anomaly in
+   the compressed data.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+  <term><computeroutput>BZ_DATA_ERROR_MAGIC</computeroutput></term>
+  <listitem><para>As a special case of
+   <computeroutput>BZ_DATA_ERROR</computeroutput>, it is
+   sometimes useful to know when the compressed stream does not
+   start with the correct magic bytes (<computeroutput>'B' 'Z'
+   'h'</computeroutput>).</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+  <term><computeroutput>BZ_IO_ERROR</computeroutput></term>
+  <listitem><para>Returned by
+   <computeroutput>BZ2_bzRead</computeroutput> and
+   <computeroutput>BZ2_bzWrite</computeroutput> when there is an
+   error reading or writing in the compressed file, and by
+   <computeroutput>BZ2_bzReadOpen</computeroutput> and
+   <computeroutput>BZ2_bzWriteOpen</computeroutput> for attempts
+   to use a file for which the error indicator (viz,
+   <computeroutput>ferror(f)</computeroutput>) is set.  On
+   receipt of <computeroutput>BZ_IO_ERROR</computeroutput>, the
+   caller should consult <computeroutput>errno</computeroutput>
+   and/or <computeroutput>perror</computeroutput> to acquire
+   operating-system specific information about the
+   problem.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+  <term><computeroutput>BZ_UNEXPECTED_EOF</computeroutput></term>
+  <listitem><para>Returned by
+   <computeroutput>BZ2_bzRead</computeroutput> when the
+   compressed file finishes before the logical end of stream is
+   detected.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+  <term><computeroutput>BZ_OUTBUFF_FULL</computeroutput></term>
+  <listitem><para>Returned by
+   <computeroutput>BZ2_bzBuffToBuffCompress</computeroutput> and
+   <computeroutput>BZ2_bzBuffToBuffDecompress</computeroutput> to
+   indicate that the output data will not fit into the output
+   buffer provided.</para></listitem>
+ </varlistentry>
+
+</variablelist>
+
+</sect1>
+
+
+
+<sect1 id="low-level" xreflabel=">Low-level interface">
+<title>Low-level interface</title>
+
+
+<sect2 id="bzcompress-init" xreflabel="BZ2_bzCompressInit">
+<title><computeroutput>BZ2_bzCompressInit</computeroutput></title>
+
+<programlisting>
+typedef struct {
+  char *next_in;
+  unsigned int avail_in;
+  unsigned int total_in_lo32;
+  unsigned int total_in_hi32;
+
+  char *next_out;
+  unsigned int avail_out;
+  unsigned int total_out_lo32;
+  unsigned int total_out_hi32;
+
+  void *state;
+
+  void *(*bzalloc)(void *,int,int);
+  void (*bzfree)(void *,void *);
+  void *opaque;
+} bz_stream;
+
+int BZ2_bzCompressInit ( bz_stream *strm, 
+                         int blockSize100k, 
+                         int verbosity,
+                         int workFactor );
+</programlisting>
+
+<para>Prepares for compression.  The
+<computeroutput>bz_stream</computeroutput> structure holds all
+data pertaining to the compression activity.  A
+<computeroutput>bz_stream</computeroutput> structure should be
+allocated and initialised prior to the call.  The fields of
+<computeroutput>bz_stream</computeroutput> comprise the entirety
+of the user-visible data.  <computeroutput>state</computeroutput>
+is a pointer to the private data structures required for
+compression.</para>
+
+<para>Custom memory allocators are supported, via fields
+<computeroutput>bzalloc</computeroutput>,
+<computeroutput>bzfree</computeroutput>, and
+<computeroutput>opaque</computeroutput>.  The value
+<computeroutput>opaque</computeroutput> is passed to as the first
+argument to all calls to <computeroutput>bzalloc</computeroutput>
+and <computeroutput>bzfree</computeroutput>, but is otherwise
+ignored by the library.  The call <computeroutput>bzalloc (
+opaque, n, m )</computeroutput> is expected to return a pointer
+<computeroutput>p</computeroutput> to <computeroutput>n *
+m</computeroutput> bytes of memory, and <computeroutput>bzfree (
+opaque, p )</computeroutput> should free that memory.</para>
+
+<para>If you don't want to use a custom memory allocator, set
+<computeroutput>bzalloc</computeroutput>,
+<computeroutput>bzfree</computeroutput> and
+<computeroutput>opaque</computeroutput> to
+<computeroutput>NULL</computeroutput>, and the library will then
+use the standard <computeroutput>malloc</computeroutput> /
+<computeroutput>free</computeroutput> routines.</para>
+
+<para>Before calling
+<computeroutput>BZ2_bzCompressInit</computeroutput>, fields
+<computeroutput>bzalloc</computeroutput>,
+<computeroutput>bzfree</computeroutput> and
+<computeroutput>opaque</computeroutput> should be filled
+appropriately, as just described.  Upon return, the internal
+state will have been allocated and initialised, and
+<computeroutput>total_in_lo32</computeroutput>,
+<computeroutput>total_in_hi32</computeroutput>,
+<computeroutput>total_out_lo32</computeroutput> and
+<computeroutput>total_out_hi32</computeroutput> will have been
+set to zero.  These four fields are used by the library to inform
+the caller of the total amount of data passed into and out of the
+library, respectively.  You should not try to change them.  As of
+version 1.0, 64-bit counts are maintained, even on 32-bit
+platforms, using the <computeroutput>_hi32</computeroutput>
+fields to store the upper 32 bits of the count.  So, for example,
+the total amount of data in is <computeroutput>(total_in_hi32
+&#60;&#60; 32) + total_in_lo32</computeroutput>.</para>
+
+<para>Parameter <computeroutput>blockSize100k</computeroutput>
+specifies the block size to be used for compression.  It should
+be a value between 1 and 9 inclusive, and the actual block size
+used is 100000 x this figure.  9 gives the best compression but
+takes most memory.</para>
+
+<para>Parameter <computeroutput>verbosity</computeroutput> should
+be set to a number between 0 and 4 inclusive.  0 is silent, and
+greater numbers give increasingly verbose monitoring/debugging
+output.  If the library has been compiled with
+<computeroutput>-DBZ_NO_STDIO</computeroutput>, no such output
+will appear for any verbosity setting.</para>
+
+<para>Parameter <computeroutput>workFactor</computeroutput>
+controls how the compression phase behaves when presented with
+worst case, highly repetitive, input data.  If compression runs
+into difficulties caused by repetitive data, the library switches
+from the standard sorting algorithm to a fallback algorithm.  The
+fallback is slower than the standard algorithm by perhaps a
+factor of three, but always behaves reasonably, no matter how bad
+the input.</para>
+
+<para>Lower values of <computeroutput>workFactor</computeroutput>
+reduce the amount of effort the standard algorithm will expend
+before resorting to the fallback.  You should set this parameter
+carefully; too low, and many inputs will be handled by the
+fallback algorithm and so compress rather slowly, too high, and
+your average-to-worst case compression times can become very
+large.  The default value of 30 gives reasonable behaviour over a
+wide range of circumstances.</para>
+
+<para>Allowable values range from 0 to 250 inclusive.  0 is a
+special case, equivalent to using the default value of 30.</para>
+
+<para>Note that the compressed output generated is the same
+regardless of whether or not the fallback algorithm is
+used.</para>
+
+<para>Be aware also that this parameter may disappear entirely in
+future versions of the library.  In principle it should be
+possible to devise a good way to automatically choose which
+algorithm to use.  Such a mechanism would render the parameter
+obsolete.</para>
+
+<para>Possible return values:</para>
+
+<programlisting>
+BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if strm is NULL 
+  or blockSize < 1 or blockSize > 9
+  or verbosity < 0 or verbosity > 4
+  or workFactor < 0 or workFactor > 250
+BZ_MEM_ERROR 
+  if not enough memory is available
+BZ_OK 
+  otherwise
+</programlisting>
+
+<para>Allowable next actions:</para>
+
+<programlisting>
+BZ2_bzCompress
+  if BZ_OK is returned
+  no specific action needed in case of error
+</programlisting>
+
+</sect2>
+
+
+<sect2 id="bzCompress" xreflabel="BZ2_bzCompress">
+<title><computeroutput>BZ2_bzCompress</computeroutput></title>
+
+<programlisting>
+int BZ2_bzCompress ( bz_stream *strm, int action );
+</programlisting>
+
+<para>Provides more input and/or output buffer space for the
+library.  The caller maintains input and output buffers, and
+calls <computeroutput>BZ2_bzCompress</computeroutput> to transfer
+data between them.</para>
+
+<para>Before each call to
+<computeroutput>BZ2_bzCompress</computeroutput>,
+<computeroutput>next_in</computeroutput> should point at the data
+to be compressed, and <computeroutput>avail_in</computeroutput>
+should indicate how many bytes the library may read.
+<computeroutput>BZ2_bzCompress</computeroutput> updates
+<computeroutput>next_in</computeroutput>,
+<computeroutput>avail_in</computeroutput> and
+<computeroutput>total_in</computeroutput> to reflect the number
+of bytes it has read.</para>
+
+<para>Similarly, <computeroutput>next_out</computeroutput> should
+point to a buffer in which the compressed data is to be placed,
+with <computeroutput>avail_out</computeroutput> indicating how
+much output space is available.
+<computeroutput>BZ2_bzCompress</computeroutput> updates
+<computeroutput>next_out</computeroutput>,
+<computeroutput>avail_out</computeroutput> and
+<computeroutput>total_out</computeroutput> to reflect the number
+of bytes output.</para>
+
+<para>You may provide and remove as little or as much data as you
+like on each call of
+<computeroutput>BZ2_bzCompress</computeroutput>.  In the limit,
+it is acceptable to supply and remove data one byte at a time,
+although this would be terribly inefficient.  You should always
+ensure that at least one byte of output space is available at
+each call.</para>
+
+<para>A second purpose of
+<computeroutput>BZ2_bzCompress</computeroutput> is to request a
+change of mode of the compressed stream.</para>
+
+<para>Conceptually, a compressed stream can be in one of four
+states: IDLE, RUNNING, FLUSHING and FINISHING.  Before
+initialisation
+(<computeroutput>BZ2_bzCompressInit</computeroutput>) and after
+termination (<computeroutput>BZ2_bzCompressEnd</computeroutput>),
+a stream is regarded as IDLE.</para>
+
+<para>Upon initialisation
+(<computeroutput>BZ2_bzCompressInit</computeroutput>), the stream
+is placed in the RUNNING state.  Subsequent calls to
+<computeroutput>BZ2_bzCompress</computeroutput> should pass
+<computeroutput>BZ_RUN</computeroutput> as the requested action;
+other actions are illegal and will result in
+<computeroutput>BZ_SEQUENCE_ERROR</computeroutput>.</para>
+
+<para>At some point, the calling program will have provided all
+the input data it wants to.  It will then want to finish up -- in
+effect, asking the library to process any data it might have
+buffered internally.  In this state,
+<computeroutput>BZ2_bzCompress</computeroutput> will no longer
+attempt to read data from
+<computeroutput>next_in</computeroutput>, but it will want to
+write data to <computeroutput>next_out</computeroutput>.  Because
+the output buffer supplied by the user can be arbitrarily small,
+the finishing-up operation cannot necessarily be done with a
+single call of
+<computeroutput>BZ2_bzCompress</computeroutput>.</para>
+
+<para>Instead, the calling program passes
+<computeroutput>BZ_FINISH</computeroutput> as an action to
+<computeroutput>BZ2_bzCompress</computeroutput>.  This changes
+the stream's state to FINISHING.  Any remaining input (ie,
+<computeroutput>next_in[0 .. avail_in-1]</computeroutput>) is
+compressed and transferred to the output buffer.  To do this,
+<computeroutput>BZ2_bzCompress</computeroutput> must be called
+repeatedly until all the output has been consumed.  At that
+point, <computeroutput>BZ2_bzCompress</computeroutput> returns
+<computeroutput>BZ_STREAM_END</computeroutput>, and the stream's
+state is set back to IDLE.
+<computeroutput>BZ2_bzCompressEnd</computeroutput> should then be
+called.</para>
+
+<para>Just to make sure the calling program does not cheat, the
+library makes a note of <computeroutput>avail_in</computeroutput>
+at the time of the first call to
+<computeroutput>BZ2_bzCompress</computeroutput> which has
+<computeroutput>BZ_FINISH</computeroutput> as an action (ie, at
+the time the program has announced its intention to not supply
+any more input).  By comparing this value with that of
+<computeroutput>avail_in</computeroutput> over subsequent calls
+to <computeroutput>BZ2_bzCompress</computeroutput>, the library
+can detect any attempts to slip in more data to compress.  Any
+calls for which this is detected will return
+<computeroutput>BZ_SEQUENCE_ERROR</computeroutput>.  This
+indicates a programming mistake which should be corrected.</para>
+
+<para>Instead of asking to finish, the calling program may ask
+<computeroutput>BZ2_bzCompress</computeroutput> to take all the
+remaining input, compress it and terminate the current
+(Burrows-Wheeler) compression block.  This could be useful for
+error control purposes.  The mechanism is analogous to that for
+finishing: call <computeroutput>BZ2_bzCompress</computeroutput>
+with an action of <computeroutput>BZ_FLUSH</computeroutput>,
+remove output data, and persist with the
+<computeroutput>BZ_FLUSH</computeroutput> action until the value
+<computeroutput>BZ_RUN</computeroutput> is returned.  As with
+finishing, <computeroutput>BZ2_bzCompress</computeroutput>
+detects any attempt to provide more input data once the flush has
+begun.</para>
+
+<para>Once the flush is complete, the stream returns to the
+normal RUNNING state.</para>
+
+<para>This all sounds pretty complex, but isn't really.  Here's a
+table which shows which actions are allowable in each state, what
+action will be taken, what the next state is, and what the
+non-error return values are.  Note that you can't explicitly ask
+what state the stream is in, but nor do you need to -- it can be
+inferred from the values returned by
+<computeroutput>BZ2_bzCompress</computeroutput>.</para>
+
+<programlisting>
+IDLE/any
+  Illegal.  IDLE state only exists after BZ2_bzCompressEnd or
+  before BZ2_bzCompressInit.
+  Return value = BZ_SEQUENCE_ERROR
+
+RUNNING/BZ_RUN
+  Compress from next_in to next_out as much as possible.
+  Next state = RUNNING
+  Return value = BZ_RUN_OK
+
+RUNNING/BZ_FLUSH
+  Remember current value of next_in. Compress from next_in
+  to next_out as much as possible, but do not accept any more input.
+  Next state = FLUSHING
+  Return value = BZ_FLUSH_OK
+
+RUNNING/BZ_FINISH
+  Remember current value of next_in. Compress from next_in
+  to next_out as much as possible, but do not accept any more input.
+  Next state = FINISHING
+  Return value = BZ_FINISH_OK
+
+FLUSHING/BZ_FLUSH
+  Compress from next_in to next_out as much as possible, 
+  but do not accept any more input.
+  If all the existing input has been used up and all compressed
+  output has been removed
+    Next state = RUNNING; Return value = BZ_RUN_OK
+  else
+    Next state = FLUSHING; Return value = BZ_FLUSH_OK
+
+FLUSHING/other     
+  Illegal.
+  Return value = BZ_SEQUENCE_ERROR
+
+FINISHING/BZ_FINISH
+  Compress from next_in to next_out as much as possible,
+  but to not accept any more input.  
+  If all the existing input has been used up and all compressed
+  output has been removed
+    Next state = IDLE; Return value = BZ_STREAM_END
+  else
+    Next state = FINISHING; Return value = BZ_FINISHING
+
+FINISHING/other
+  Illegal.
+  Return value = BZ_SEQUENCE_ERROR
+</programlisting>
+
+
+<para>That still looks complicated?  Well, fair enough.  The
+usual sequence of calls for compressing a load of data is:</para>
+
+<orderedlist>
+
+ <listitem><para>Get started with
+  <computeroutput>BZ2_bzCompressInit</computeroutput>.</para></listitem>
+
+ <listitem><para>Shovel data in and shlurp out its compressed form
+  using zero or more calls of
+  <computeroutput>BZ2_bzCompress</computeroutput> with action =
+  <computeroutput>BZ_RUN</computeroutput>.</para></listitem>
+
+ <listitem><para>Finish up. Repeatedly call
+  <computeroutput>BZ2_bzCompress</computeroutput> with action =
+  <computeroutput>BZ_FINISH</computeroutput>, copying out the
+  compressed output, until
+  <computeroutput>BZ_STREAM_END</computeroutput> is
+  returned.</para></listitem> <listitem><para>Close up and go home.  Call
+  <computeroutput>BZ2_bzCompressEnd</computeroutput>.</para></listitem>
+
+</orderedlist>
+
+<para>If the data you want to compress fits into your input
+buffer all at once, you can skip the calls of
+<computeroutput>BZ2_bzCompress ( ..., BZ_RUN )</computeroutput>
+and just do the <computeroutput>BZ2_bzCompress ( ..., BZ_FINISH
+)</computeroutput> calls.</para>
+
+<para>All required memory is allocated by
+<computeroutput>BZ2_bzCompressInit</computeroutput>.  The
+compression library can accept any data at all (obviously).  So
+you shouldn't get any error return values from the
+<computeroutput>BZ2_bzCompress</computeroutput> calls.  If you
+do, they will be
+<computeroutput>BZ_SEQUENCE_ERROR</computeroutput>, and indicate
+a bug in your programming.</para>
+
+<para>Trivial other possible return values:</para>
+
+<programlisting>
+BZ_PARAM_ERROR
+  if strm is NULL, or strm->s is NULL
+</programlisting>
+
+</sect2>
+
+
+<sect2 id="bzCompress-end" xreflabel="BZ2_bzCompressEnd">
+<title><computeroutput>BZ2_bzCompressEnd</computeroutput></title>
+
+<programlisting>
+int BZ2_bzCompressEnd ( bz_stream *strm );
+</programlisting>
+
+<para>Releases all memory associated with a compression
+stream.</para>
+
+<para>Possible return values:</para>
+
+<programlisting>
+BZ_PARAM_ERROR  if strm is NULL or strm->s is NULL
+BZ_OK           otherwise
+</programlisting>
+
+</sect2>
+
+
+<sect2 id="bzDecompress-init" xreflabel="BZ2_bzDecompressInit">
+<title><computeroutput>BZ2_bzDecompressInit</computeroutput></title>
+
+<programlisting>
+int BZ2_bzDecompressInit ( bz_stream *strm, int verbosity, int small );
+</programlisting>
+
+<para>Prepares for decompression.  As with
+<computeroutput>BZ2_bzCompressInit</computeroutput>, a
+<computeroutput>bz_stream</computeroutput> record should be
+allocated and initialised before the call.  Fields
+<computeroutput>bzalloc</computeroutput>,
+<computeroutput>bzfree</computeroutput> and
+<computeroutput>opaque</computeroutput> should be set if a custom
+memory allocator is required, or made
+<computeroutput>NULL</computeroutput> for the normal
+<computeroutput>malloc</computeroutput> /
+<computeroutput>free</computeroutput> routines.  Upon return, the
+internal state will have been initialised, and
+<computeroutput>total_in</computeroutput> and
+<computeroutput>total_out</computeroutput> will be zero.</para>
+
+<para>For the meaning of parameter
+<computeroutput>verbosity</computeroutput>, see
+<computeroutput>BZ2_bzCompressInit</computeroutput>.</para>
+
+<para>If <computeroutput>small</computeroutput> is nonzero, the
+library will use an alternative decompression algorithm which
+uses less memory but at the cost of decompressing more slowly
+(roughly speaking, half the speed, but the maximum memory
+requirement drops to around 2300k).  See <xref linkend="using"/>
+for more information on memory management.</para>
+
+<para>Note that the amount of memory needed to decompress a
+stream cannot be determined until the stream's header has been
+read, so even if
+<computeroutput>BZ2_bzDecompressInit</computeroutput> succeeds, a
+subsequent <computeroutput>BZ2_bzDecompress</computeroutput>
+could fail with
+<computeroutput>BZ_MEM_ERROR</computeroutput>.</para>
+
+<para>Possible return values:</para>
+
+<programlisting>
+BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if ( small != 0 && small != 1 )
+  or (verbosity <; 0 || verbosity > 4)
+BZ_MEM_ERROR
+  if insufficient memory is available
+</programlisting>
+
+<para>Allowable next actions:</para>
+
+<programlisting>
+BZ2_bzDecompress
+  if BZ_OK was returned
+  no specific action required in case of error
+</programlisting>
+
+</sect2>
+
+
+<sect2 id="bzDecompress" xreflabel="BZ2_bzDecompress">
+<title><computeroutput>BZ2_bzDecompress</computeroutput></title>
+
+<programlisting>
+int BZ2_bzDecompress ( bz_stream *strm );
+</programlisting>
+
+<para>Provides more input and/out output buffer space for the
+library.  The caller maintains input and output buffers, and uses
+<computeroutput>BZ2_bzDecompress</computeroutput> to transfer
+data between them.</para>
+
+<para>Before each call to
+<computeroutput>BZ2_bzDecompress</computeroutput>,
+<computeroutput>next_in</computeroutput> should point at the
+compressed data, and <computeroutput>avail_in</computeroutput>
+should indicate how many bytes the library may read.
+<computeroutput>BZ2_bzDecompress</computeroutput> updates
+<computeroutput>next_in</computeroutput>,
+<computeroutput>avail_in</computeroutput> and
+<computeroutput>total_in</computeroutput> to reflect the number
+of bytes it has read.</para>
+
+<para>Similarly, <computeroutput>next_out</computeroutput> should
+point to a buffer in which the uncompressed output is to be
+placed, with <computeroutput>avail_out</computeroutput>
+indicating how much output space is available.
+<computeroutput>BZ2_bzCompress</computeroutput> updates
+<computeroutput>next_out</computeroutput>,
+<computeroutput>avail_out</computeroutput> and
+<computeroutput>total_out</computeroutput> to reflect the number
+of bytes output.</para>
+
+<para>You may provide and remove as little or as much data as you
+like on each call of
+<computeroutput>BZ2_bzDecompress</computeroutput>.  In the limit,
+it is acceptable to supply and remove data one byte at a time,
+although this would be terribly inefficient.  You should always
+ensure that at least one byte of output space is available at
+each call.</para>
+
+<para>Use of <computeroutput>BZ2_bzDecompress</computeroutput> is
+simpler than
+<computeroutput>BZ2_bzCompress</computeroutput>.</para>
+
+<para>You should provide input and remove output as described
+above, and repeatedly call
+<computeroutput>BZ2_bzDecompress</computeroutput> until
+<computeroutput>BZ_STREAM_END</computeroutput> is returned.
+Appearance of <computeroutput>BZ_STREAM_END</computeroutput>
+denotes that <computeroutput>BZ2_bzDecompress</computeroutput>
+has detected the logical end of the compressed stream.
+<computeroutput>BZ2_bzDecompress</computeroutput> will not
+produce <computeroutput>BZ_STREAM_END</computeroutput> until all
+output data has been placed into the output buffer, so once
+<computeroutput>BZ_STREAM_END</computeroutput> appears, you are
+guaranteed to have available all the decompressed output, and
+<computeroutput>BZ2_bzDecompressEnd</computeroutput> can safely
+be called.</para>
+
+<para>If case of an error return value, you should call
+<computeroutput>BZ2_bzDecompressEnd</computeroutput> to clean up
+and release memory.</para>
+
+<para>Possible return values:</para>
+
+<programlisting>
+BZ_PARAM_ERROR
+  if strm is NULL or strm->s is NULL
+  or strm->avail_out < 1
+BZ_DATA_ERROR
+  if a data integrity error is detected in the compressed stream
+BZ_DATA_ERROR_MAGIC
+  if the compressed stream doesn't begin with the right magic bytes
+BZ_MEM_ERROR
+  if there wasn't enough memory available
+BZ_STREAM_END
+  if the logical end of the data stream was detected and all
+  output in has been consumed, eg s-->avail_out > 0
+BZ_OK
+  otherwise
+</programlisting>
+
+<para>Allowable next actions:</para>
+
+<programlisting>
+BZ2_bzDecompress
+  if BZ_OK was returned
+BZ2_bzDecompressEnd
+  otherwise
+</programlisting>
+
+</sect2>
+
+
+<sect2 id="bzDecompress-end" xreflabel="BZ2_bzDecompressEnd">
+<title><computeroutput>BZ2_bzDecompressEnd</computeroutput></title>
+
+<programlisting>
+int BZ2_bzDecompressEnd ( bz_stream *strm );
+</programlisting>
+
+<para>Releases all memory associated with a decompression
+stream.</para>
+
+<para>Possible return values:</para>
+
+<programlisting>
+BZ_PARAM_ERROR
+  if strm is NULL or strm->s is NULL
+BZ_OK
+  otherwise
+</programlisting>
+
+<para>Allowable next actions:</para>
+
+<programlisting>
+  None.
+</programlisting>
+
+</sect2>
+
+</sect1>
+
+
+<sect1 id="hl-interface" xreflabel="High-level interface">
+<title>High-level interface</title>
+
+<para>This interface provides functions for reading and writing
+<computeroutput>bzip2</computeroutput> format files.  First, some
+general points.</para>
+
+<itemizedlist mark='bullet'>
+
+ <listitem><para>All of the functions take an
+  <computeroutput>int*</computeroutput> first argument,
+  <computeroutput>bzerror</computeroutput>.  After each call,
+  <computeroutput>bzerror</computeroutput> should be consulted
+  first to determine the outcome of the call.  If
+  <computeroutput>bzerror</computeroutput> is
+  <computeroutput>BZ_OK</computeroutput>, the call completed
+  successfully, and only then should the return value of the
+  function (if any) be consulted.  If
+  <computeroutput>bzerror</computeroutput> is
+  <computeroutput>BZ_IO_ERROR</computeroutput>, there was an
+  error reading/writing the underlying compressed file, and you
+  should then consult <computeroutput>errno</computeroutput> /
+  <computeroutput>perror</computeroutput> to determine the cause
+  of the difficulty.  <computeroutput>bzerror</computeroutput>
+  may also be set to various other values; precise details are
+  given on a per-function basis below.</para></listitem>
+
+ <listitem><para>If <computeroutput>bzerror</computeroutput> indicates
+  an error (ie, anything except
+  <computeroutput>BZ_OK</computeroutput> and
+  <computeroutput>BZ_STREAM_END</computeroutput>), you should
+  immediately call
+  <computeroutput>BZ2_bzReadClose</computeroutput> (or
+  <computeroutput>BZ2_bzWriteClose</computeroutput>, depending on
+  whether you are attempting to read or to write) to free up all
+  resources associated with the stream.  Once an error has been
+  indicated, behaviour of all calls except
+  <computeroutput>BZ2_bzReadClose</computeroutput>
+  (<computeroutput>BZ2_bzWriteClose</computeroutput>) is
+  undefined.  The implication is that (1)
+  <computeroutput>bzerror</computeroutput> should be checked
+  after each call, and (2) if
+  <computeroutput>bzerror</computeroutput> indicates an error,
+  <computeroutput>BZ2_bzReadClose</computeroutput>
+  (<computeroutput>BZ2_bzWriteClose</computeroutput>) should then
+  be called to clean up.</para></listitem>
+
+ <listitem><para>The <computeroutput>FILE*</computeroutput> arguments
+  passed to <computeroutput>BZ2_bzReadOpen</computeroutput> /
+  <computeroutput>BZ2_bzWriteOpen</computeroutput> should be set
+  to binary mode.  Most Unix systems will do this by default, but
+  other platforms, including Windows and Mac, will not.  If you
+  omit this, you may encounter problems when moving code to new
+  platforms.</para></listitem>
+
+ <listitem><para>Memory allocation requests are handled by
+  <computeroutput>malloc</computeroutput> /
+  <computeroutput>free</computeroutput>.  At present there is no
+  facility for user-defined memory allocators in the file I/O
+  functions (could easily be added, though).</para></listitem>
+
+</itemizedlist>
+
+
+
+<sect2 id="bzreadopen" xreflabel="BZ2_bzReadOpen">
+<title><computeroutput>BZ2_bzReadOpen</computeroutput></title>
+
+<programlisting>
+typedef void BZFILE;
+
+BZFILE *BZ2_bzReadOpen( int *bzerror, FILE *f, 
+                        int verbosity, int small,
+                        void *unused, int nUnused );
+</programlisting>
+
+<para>Prepare to read compressed data from file handle
+<computeroutput>f</computeroutput>.
+<computeroutput>f</computeroutput> should refer to a file which
+has been opened for reading, and for which the error indicator
+(<computeroutput>ferror(f)</computeroutput>)is not set.  If
+<computeroutput>small</computeroutput> is 1, the library will try
+to decompress using less memory, at the expense of speed.</para>
+
+<para>For reasons explained below,
+<computeroutput>BZ2_bzRead</computeroutput> will decompress the
+<computeroutput>nUnused</computeroutput> bytes starting at
+<computeroutput>unused</computeroutput>, before starting to read
+from the file <computeroutput>f</computeroutput>.  At most
+<computeroutput>BZ_MAX_UNUSED</computeroutput> bytes may be
+supplied like this.  If this facility is not required, you should
+pass <computeroutput>NULL</computeroutput> and
+<computeroutput>0</computeroutput> for
+<computeroutput>unused</computeroutput> and
+n<computeroutput>Unused</computeroutput> respectively.</para>
+
+<para>For the meaning of parameters
+<computeroutput>small</computeroutput> and
+<computeroutput>verbosity</computeroutput>, see
+<computeroutput>BZ2_bzDecompressInit</computeroutput>.</para>
+
+<para>The amount of memory needed to decompress a file cannot be
+determined until the file's header has been read.  So it is
+possible that <computeroutput>BZ2_bzReadOpen</computeroutput>
+returns <computeroutput>BZ_OK</computeroutput> but a subsequent
+call of <computeroutput>BZ2_bzRead</computeroutput> will return
+<computeroutput>BZ_MEM_ERROR</computeroutput>.</para>
+
+<para>Possible assignments to
+<computeroutput>bzerror</computeroutput>:</para>
+
+<programlisting>
+BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if f is NULL
+  or small is neither 0 nor 1
+  or ( unused == NULL && nUnused != 0 )
+  or ( unused != NULL && !(0 <= nUnused <= BZ_MAX_UNUSED) )
+BZ_IO_ERROR
+  if ferror(f) is nonzero
+BZ_MEM_ERROR
+  if insufficient memory is available
+BZ_OK
+  otherwise.
+</programlisting>
+
+<para>Possible return values:</para>
+
+<programlisting>
+Pointer to an abstract BZFILE
+  if bzerror is BZ_OK
+NULL
+  otherwise
+</programlisting>
+
+<para>Allowable next actions:</para>
+
+<programlisting>
+BZ2_bzRead
+  if bzerror is BZ_OK
+BZ2_bzClose
+  otherwise
+</programlisting>
+
+</sect2>
+
+
+<sect2 id="bzread" xreflabel="BZ2_bzRead">
+<title><computeroutput>BZ2_bzRead</computeroutput></title>
+
+<programlisting>
+int BZ2_bzRead ( int *bzerror, BZFILE *b, void *buf, int len );
+</programlisting>
+
+<para>Reads up to <computeroutput>len</computeroutput>
+(uncompressed) bytes from the compressed file
+<computeroutput>b</computeroutput> into the buffer
+<computeroutput>buf</computeroutput>.  If the read was
+successful, <computeroutput>bzerror</computeroutput> is set to
+<computeroutput>BZ_OK</computeroutput> and the number of bytes
+read is returned.  If the logical end-of-stream was detected,
+<computeroutput>bzerror</computeroutput> will be set to
+<computeroutput>BZ_STREAM_END</computeroutput>, and the number of
+bytes read is returned.  All other
+<computeroutput>bzerror</computeroutput> values denote an
+error.</para>
+
+<para><computeroutput>BZ2_bzRead</computeroutput> will supply
+<computeroutput>len</computeroutput> bytes, unless the logical
+stream end is detected or an error occurs.  Because of this, it
+is possible to detect the stream end by observing when the number
+of bytes returned is less than the number requested.
+Nevertheless, this is regarded as inadvisable; you should instead
+check <computeroutput>bzerror</computeroutput> after every call
+and watch out for
+<computeroutput>BZ_STREAM_END</computeroutput>.</para>
+
+<para>Internally, <computeroutput>BZ2_bzRead</computeroutput>
+copies data from the compressed file in chunks of size
+<computeroutput>BZ_MAX_UNUSED</computeroutput> bytes before
+decompressing it.  If the file contains more bytes than strictly
+needed to reach the logical end-of-stream,
+<computeroutput>BZ2_bzRead</computeroutput> will almost certainly
+read some of the trailing data before signalling
+<computeroutput>BZ_SEQUENCE_END</computeroutput>.  To collect the
+read but unused data once
+<computeroutput>BZ_SEQUENCE_END</computeroutput> has appeared,
+call <computeroutput>BZ2_bzReadGetUnused</computeroutput>
+immediately before
+<computeroutput>BZ2_bzReadClose</computeroutput>.</para>
+
+<para>Possible assignments to
+<computeroutput>bzerror</computeroutput>:</para>
+
+<programlisting>
+BZ_PARAM_ERROR
+  if b is NULL or buf is NULL or len < 0
+BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzWriteOpen
+BZ_IO_ERROR
+  if there is an error reading from the compressed file
+BZ_UNEXPECTED_EOF
+  if the compressed file ended before 
+  the logical end-of-stream was detected
+BZ_DATA_ERROR
+  if a data integrity error was detected in the compressed stream
+BZ_DATA_ERROR_MAGIC
+  if the stream does not begin with the requisite header bytes 
+  (ie, is not a bzip2 data file).  This is really 
+  a special case of BZ_DATA_ERROR.
+BZ_MEM_ERROR
+  if insufficient memory was available
+BZ_STREAM_END
+  if the logical end of stream was detected.
+BZ_OK
+  otherwise.
+</programlisting>
+
+<para>Possible return values:</para>
+
+<programlisting>
+number of bytes read
+  if bzerror is BZ_OK or BZ_STREAM_END
+undefined
+  otherwise
+</programlisting>
+
+<para>Allowable next actions:</para>
+
+<programlisting>
+collect data from buf, then BZ2_bzRead or BZ2_bzReadClose
+  if bzerror is BZ_OK
+collect data from buf, then BZ2_bzReadClose or BZ2_bzReadGetUnused
+  if bzerror is BZ_SEQUENCE_END
+BZ2_bzReadClose
+  otherwise
+</programlisting>
+
+</sect2>
+
+
+<sect2 id="bzreadgetunused" xreflabel="BZ2_bzReadGetUnused">
+<title><computeroutput>BZ2_bzReadGetUnused</computeroutput></title>
+
+<programlisting>
+void BZ2_bzReadGetUnused( int* bzerror, BZFILE *b, 
+                          void** unused, int* nUnused );
+</programlisting>
+
+<para>Returns data which was read from the compressed file but
+was not needed to get to the logical end-of-stream.
+<computeroutput>*unused</computeroutput> is set to the address of
+the data, and <computeroutput>*nUnused</computeroutput> to the
+number of bytes.  <computeroutput>*nUnused</computeroutput> will
+be set to a value between <computeroutput>0</computeroutput> and
+<computeroutput>BZ_MAX_UNUSED</computeroutput> inclusive.</para>
+
+<para>This function may only be called once
+<computeroutput>BZ2_bzRead</computeroutput> has signalled
+<computeroutput>BZ_STREAM_END</computeroutput> but before
+<computeroutput>BZ2_bzReadClose</computeroutput>.</para>
+
+<para>Possible assignments to
+<computeroutput>bzerror</computeroutput>:</para>
+
+<programlisting>
+BZ_PARAM_ERROR
+  if b is NULL
+  or unused is NULL or nUnused is NULL
+BZ_SEQUENCE_ERROR
+  if BZ_STREAM_END has not been signalled
+  or if b was opened with BZ2_bzWriteOpen
+BZ_OK
+  otherwise
+</programlisting>
+
+<para>Allowable next actions:</para>
+
+<programlisting>
+BZ2_bzReadClose
+</programlisting>
+
+</sect2>
+
+
+<sect2 id="bzreadclose" xreflabel="BZ2_bzReadClose">
+<title><computeroutput>BZ2_bzReadClose</computeroutput></title>
+
+<programlisting>
+void BZ2_bzReadClose ( int *bzerror, BZFILE *b );
+</programlisting>
+
+<para>Releases all memory pertaining to the compressed file
+<computeroutput>b</computeroutput>.
+<computeroutput>BZ2_bzReadClose</computeroutput> does not call
+<computeroutput>fclose</computeroutput> on the underlying file
+handle, so you should do that yourself if appropriate.
+<computeroutput>BZ2_bzReadClose</computeroutput> should be called
+to clean up after all error situations.</para>
+
+<para>Possible assignments to
+<computeroutput>bzerror</computeroutput>:</para>
+
+<programlisting>
+BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzOpenWrite
+BZ_OK
+  otherwise
+</programlisting>
+
+<para>Allowable next actions:</para>
+
+<programlisting>
+none
+</programlisting>
+
+</sect2>
+
+
+<sect2 id="bzwriteopen" xreflabel="BZ2_bzWriteOpen">
+<title><computeroutput>BZ2_bzWriteOpen</computeroutput></title>
+
+<programlisting>
+BZFILE *BZ2_bzWriteOpen( int *bzerror, FILE *f, 
+                         int blockSize100k, int verbosity,
+                         int workFactor );
+</programlisting>
+
+<para>Prepare to write compressed data to file handle
+<computeroutput>f</computeroutput>.
+<computeroutput>f</computeroutput> should refer to a file which
+has been opened for writing, and for which the error indicator
+(<computeroutput>ferror(f)</computeroutput>)is not set.</para>
+
+<para>For the meaning of parameters
+<computeroutput>blockSize100k</computeroutput>,
+<computeroutput>verbosity</computeroutput> and
+<computeroutput>workFactor</computeroutput>, see
+<computeroutput>BZ2_bzCompressInit</computeroutput>.</para>
+
+<para>All required memory is allocated at this stage, so if the
+call completes successfully,
+<computeroutput>BZ_MEM_ERROR</computeroutput> cannot be signalled
+by a subsequent call to
+<computeroutput>BZ2_bzWrite</computeroutput>.</para>
+
+<para>Possible assignments to
+<computeroutput>bzerror</computeroutput>:</para>
+
+<programlisting>
+BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if f is NULL
+  or blockSize100k < 1 or blockSize100k > 9
+BZ_IO_ERROR
+  if ferror(f) is nonzero
+BZ_MEM_ERROR
+  if insufficient memory is available
+BZ_OK
+  otherwise
+</programlisting>
+
+<para>Possible return values:</para>
+
+<programlisting>
+Pointer to an abstract BZFILE
+  if bzerror is BZ_OK
+NULL
+  otherwise
+</programlisting>
+
+<para>Allowable next actions:</para>
+
+<programlisting>
+BZ2_bzWrite
+  if bzerror is BZ_OK
+  (you could go directly to BZ2_bzWriteClose, but this would be pretty pointless)
+BZ2_bzWriteClose
+  otherwise
+</programlisting>
+
+</sect2>
+
+
+<sect2 id="bzwrite" xreflabel="BZ2_bzWrite">
+<title><computeroutput>BZ2_bzWrite</computeroutput></title>
+
+<programlisting>
+void BZ2_bzWrite ( int *bzerror, BZFILE *b, void *buf, int len );
+</programlisting>
+
+<para>Absorbs <computeroutput>len</computeroutput> bytes from the
+buffer <computeroutput>buf</computeroutput>, eventually to be
+compressed and written to the file.</para>
+
+<para>Possible assignments to
+<computeroutput>bzerror</computeroutput>:</para>
+
+<programlisting>
+BZ_PARAM_ERROR
+  if b is NULL or buf is NULL or len < 0
+BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzReadOpen
+BZ_IO_ERROR
+  if there is an error writing the compressed file.
+BZ_OK
+  otherwise
+</programlisting>
+
+</sect2>
+
+
+<sect2 id="bzwriteclose" xreflabel="BZ2_bzWriteClose">
+<title><computeroutput>BZ2_bzWriteClose</computeroutput></title>
+
+<programlisting>
+void BZ2_bzWriteClose( int *bzerror, BZFILE* f,
+                       int abandon,
+                       unsigned int* nbytes_in,
+                       unsigned int* nbytes_out );
+
+void BZ2_bzWriteClose64( int *bzerror, BZFILE* f,
+                         int abandon,
+                         unsigned int* nbytes_in_lo32,
+                         unsigned int* nbytes_in_hi32,
+                         unsigned int* nbytes_out_lo32,
+                         unsigned int* nbytes_out_hi32 );
+</programlisting>
+
+<para>Compresses and flushes to the compressed file all data so
+far supplied by <computeroutput>BZ2_bzWrite</computeroutput>.
+The logical end-of-stream markers are also written, so subsequent
+calls to <computeroutput>BZ2_bzWrite</computeroutput> are
+illegal.  All memory associated with the compressed file
+<computeroutput>b</computeroutput> is released.
+<computeroutput>fflush</computeroutput> is called on the
+compressed file, but it is not
+<computeroutput>fclose</computeroutput>'d.</para>
+
+<para>If <computeroutput>BZ2_bzWriteClose</computeroutput> is
+called to clean up after an error, the only action is to release
+the memory.  The library records the error codes issued by
+previous calls, so this situation will be detected automatically.
+There is no attempt to complete the compression operation, nor to
+<computeroutput>fflush</computeroutput> the compressed file.  You
+can force this behaviour to happen even in the case of no error,
+by passing a nonzero value to
+<computeroutput>abandon</computeroutput>.</para>
+
+<para>If <computeroutput>nbytes_in</computeroutput> is non-null,
+<computeroutput>*nbytes_in</computeroutput> will be set to be the
+total volume of uncompressed data handled.  Similarly,
+<computeroutput>nbytes_out</computeroutput> will be set to the
+total volume of compressed data written.  For compatibility with
+older versions of the library,
+<computeroutput>BZ2_bzWriteClose</computeroutput> only yields the
+lower 32 bits of these counts.  Use
+<computeroutput>BZ2_bzWriteClose64</computeroutput> if you want
+the full 64 bit counts.  These two functions are otherwise
+absolutely identical.</para>
+
+<para>Possible assignments to
+<computeroutput>bzerror</computeroutput>:</para>
+
+<programlisting>
+BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzReadOpen
+BZ_IO_ERROR
+  if there is an error writing the compressed file
+BZ_OK
+  otherwise
+</programlisting>
+
+</sect2>
+
+
+<sect2 id="embed" xreflabel="Handling embedded compressed data streams">
+<title>Handling embedded compressed data streams</title>
+
+<para>The high-level library facilitates use of
+<computeroutput>bzip2</computeroutput> data streams which form
+some part of a surrounding, larger data stream.</para>
+
+<itemizedlist mark='bullet'>
+
+ <listitem><para>For writing, the library takes an open file handle,
+  writes compressed data to it,
+  <computeroutput>fflush</computeroutput>es it but does not
+  <computeroutput>fclose</computeroutput> it.  The calling
+  application can write its own data before and after the
+  compressed data stream, using that same file handle.</para></listitem>
+
+ <listitem><para>Reading is more complex, and the facilities are not as
+  general as they could be since generality is hard to reconcile
+  with efficiency.  <computeroutput>BZ2_bzRead</computeroutput>
+  reads from the compressed file in blocks of size
+  <computeroutput>BZ_MAX_UNUSED</computeroutput> bytes, and in
+  doing so probably will overshoot the logical end of compressed
+  stream.  To recover this data once decompression has ended,
+  call <computeroutput>BZ2_bzReadGetUnused</computeroutput> after
+  the last call of <computeroutput>BZ2_bzRead</computeroutput>
+  (the one returning
+  <computeroutput>BZ_STREAM_END</computeroutput>) but before
+  calling
+  <computeroutput>BZ2_bzReadClose</computeroutput>.</para></listitem>
+
+</itemizedlist>
+
+<para>This mechanism makes it easy to decompress multiple
+<computeroutput>bzip2</computeroutput> streams placed end-to-end.
+As the end of one stream, when
+<computeroutput>BZ2_bzRead</computeroutput> returns
+<computeroutput>BZ_STREAM_END</computeroutput>, call
+<computeroutput>BZ2_bzReadGetUnused</computeroutput> to collect
+the unused data (copy it into your own buffer somewhere).  That
+data forms the start of the next compressed stream.  To start
+uncompressing that next stream, call
+<computeroutput>BZ2_bzReadOpen</computeroutput> again, feeding in
+the unused data via the <computeroutput>unused</computeroutput> /
+<computeroutput>nUnused</computeroutput> parameters.  Keep doing
+this until <computeroutput>BZ_STREAM_END</computeroutput> return
+coincides with the physical end of file
+(<computeroutput>feof(f)</computeroutput>).  In this situation
+<computeroutput>BZ2_bzReadGetUnused</computeroutput> will of
+course return no data.</para>
+
+<para>This should give some feel for how the high-level interface
+can be used.  If you require extra flexibility, you'll have to
+bite the bullet and get to grips with the low-level
+interface.</para>
+
+</sect2>
+
+
+<sect2 id="std-rdwr" xreflabel="Standard file-reading/writing code">
+<title>Standard file-reading/writing code</title>
+
+<para>Here's how you'd write data to a compressed file:</para>
+
+<programlisting>
+FILE*   f;
+BZFILE* b;
+int     nBuf;
+char    buf[ /* whatever size you like */ ];
+int     bzerror;
+int     nWritten;
+
+f = fopen ( "myfile.bz2", "w" );
+if ( !f ) {
+ /* handle error */
+}
+b = BZ2_bzWriteOpen( &bzerror, f, 9 );
+if (bzerror != BZ_OK) {
+ BZ2_bzWriteClose ( b );
+ /* handle error */
+}
+
+while ( /* condition */ ) {
+ /* get data to write into buf, and set nBuf appropriately */
+ nWritten = BZ2_bzWrite ( &bzerror, b, buf, nBuf );
+ if (bzerror == BZ_IO_ERROR) { 
+   BZ2_bzWriteClose ( &bzerror, b );
+   /* handle error */
+ }
+}
+
+BZ2_bzWriteClose( &bzerror, b );
+if (bzerror == BZ_IO_ERROR) {
+ /* handle error */
+}
+</programlisting>
+
+<para>And to read from a compressed file:</para>
+
+<programlisting>
+FILE*   f;
+BZFILE* b;
+int     nBuf;
+char    buf[ /* whatever size you like */ ];
+int     bzerror;
+int     nWritten;
+
+f = fopen ( "myfile.bz2", "r" );
+if ( !f ) {
+  /* handle error */
+}
+b = BZ2_bzReadOpen ( &bzerror, f, 0, NULL, 0 );
+if ( bzerror != BZ_OK ) {
+  BZ2_bzReadClose ( &bzerror, b );
+  /* handle error */
+}
+
+bzerror = BZ_OK;
+while ( bzerror == BZ_OK && /* arbitrary other conditions */) {
+  nBuf = BZ2_bzRead ( &bzerror, b, buf, /* size of buf */ );
+  if ( bzerror == BZ_OK ) {
+    /* do something with buf[0 .. nBuf-1] */
+  }
+}
+if ( bzerror != BZ_STREAM_END ) {
+   BZ2_bzReadClose ( &bzerror, b );
+   /* handle error */
+} else {
+   BZ2_bzReadClose ( &bzerror );
+}
+</programlisting>
+
+</sect2>
+
+</sect1>
+
+
+<sect1 id="util-fns" xreflabel="Utility functions">
+<title>Utility functions</title>
+
+
+<sect2 id="bzbufftobuffcompress" xreflabel="BZ2_bzBuffToBuffCompress">
+<title><computeroutput>BZ2_bzBuffToBuffCompress</computeroutput></title>
+
+<programlisting>
+int BZ2_bzBuffToBuffCompress( char*         dest,
+                              unsigned int* destLen,
+                              char*         source,
+                              unsigned int  sourceLen,
+                              int           blockSize100k,
+                              int           verbosity,
+                              int           workFactor );
+</programlisting>
+
+<para>Attempts to compress the data in <computeroutput>source[0
+.. sourceLen-1]</computeroutput> into the destination buffer,
+<computeroutput>dest[0 .. *destLen-1]</computeroutput>.  If the
+destination buffer is big enough,
+<computeroutput>*destLen</computeroutput> is set to the size of
+the compressed data, and <computeroutput>BZ_OK</computeroutput>
+is returned.  If the compressed data won't fit,
+<computeroutput>*destLen</computeroutput> is unchanged, and
+<computeroutput>BZ_OUTBUFF_FULL</computeroutput> is
+returned.</para>
+
+<para>Compression in this manner is a one-shot event, done with a
+single call to this function.  The resulting compressed data is a
+complete <computeroutput>bzip2</computeroutput> format data
+stream.  There is no mechanism for making additional calls to
+provide extra input data.  If you want that kind of mechanism,
+use the low-level interface.</para>
+
+<para>For the meaning of parameters
+<computeroutput>blockSize100k</computeroutput>,
+<computeroutput>verbosity</computeroutput> and
+<computeroutput>workFactor</computeroutput>, see
+<computeroutput>BZ2_bzCompressInit</computeroutput>.</para>
+
+<para>To guarantee that the compressed data will fit in its
+buffer, allocate an output buffer of size 1% larger than the
+uncompressed data, plus six hundred extra bytes.</para>
+
+<para><computeroutput>BZ2_bzBuffToBuffDecompress</computeroutput>
+will not write data at or beyond
+<computeroutput>dest[*destLen]</computeroutput>, even in case of
+buffer overflow.</para>
+
+<para>Possible return values:</para>
+
+<programlisting>
+BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if dest is NULL or destLen is NULL
+  or blockSize100k < 1 or blockSize100k > 9
+  or verbosity < 0 or verbosity > 4
+  or workFactor < 0 or workFactor > 250
+BZ_MEM_ERROR
+  if insufficient memory is available 
+BZ_OUTBUFF_FULL
+  if the size of the compressed data exceeds *destLen
+BZ_OK
+  otherwise
+</programlisting>
+
+</sect2>
+
+
+<sect2 id="bzbufftobuffdecompress" xreflabel="BZ2_bzBuffToBuffDecompress">
+<title><computeroutput>BZ2_bzBuffToBuffDecompress</computeroutput></title>
+
+<programlisting>
+int BZ2_bzBuffToBuffDecompress( char*         dest,
+                                unsigned int* destLen,
+                                char*         source,
+                                unsigned int  sourceLen,
+                                int           small,
+                                int           verbosity );
+</programlisting>
+
+<para>Attempts to decompress the data in <computeroutput>source[0
+.. sourceLen-1]</computeroutput> into the destination buffer,
+<computeroutput>dest[0 .. *destLen-1]</computeroutput>.  If the
+destination buffer is big enough,
+<computeroutput>*destLen</computeroutput> is set to the size of
+the uncompressed data, and <computeroutput>BZ_OK</computeroutput>
+is returned.  If the compressed data won't fit,
+<computeroutput>*destLen</computeroutput> is unchanged, and
+<computeroutput>BZ_OUTBUFF_FULL</computeroutput> is
+returned.</para>
+
+<para><computeroutput>source</computeroutput> is assumed to hold
+a complete <computeroutput>bzip2</computeroutput> format data
+stream.
+<computeroutput>BZ2_bzBuffToBuffDecompress</computeroutput> tries
+to decompress the entirety of the stream into the output
+buffer.</para>
+
+<para>For the meaning of parameters
+<computeroutput>small</computeroutput> and
+<computeroutput>verbosity</computeroutput>, see
+<computeroutput>BZ2_bzDecompressInit</computeroutput>.</para>
+
+<para>Because the compression ratio of the compressed data cannot
+be known in advance, there is no easy way to guarantee that the
+output buffer will be big enough.  You may of course make
+arrangements in your code to record the size of the uncompressed
+data, but such a mechanism is beyond the scope of this
+library.</para>
+
+<para><computeroutput>BZ2_bzBuffToBuffDecompress</computeroutput>
+will not write data at or beyond
+<computeroutput>dest[*destLen]</computeroutput>, even in case of
+buffer overflow.</para>
+
+<para>Possible return values:</para>
+
+<programlisting>
+BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if dest is NULL or destLen is NULL
+  or small != 0 && small != 1
+  or verbosity < 0 or verbosity > 4
+BZ_MEM_ERROR
+  if insufficient memory is available 
+BZ_OUTBUFF_FULL
+  if the size of the compressed data exceeds *destLen
+BZ_DATA_ERROR
+  if a data integrity error was detected in the compressed data
+BZ_DATA_ERROR_MAGIC
+  if the compressed data doesn't begin with the right magic bytes
+BZ_UNEXPECTED_EOF
+  if the compressed data ends unexpectedly
+BZ_OK
+  otherwise
+</programlisting>
+
+</sect2>
+
+</sect1>
+
+
+<sect1 id="zlib-compat" xreflabel="zlib compatibility functions">
+<title><computeroutput>zlib</computeroutput> compatibility functions</title>
+
+<para>Yoshioka Tsuneo has contributed some functions to give
+better <computeroutput>zlib</computeroutput> compatibility.
+These functions are <computeroutput>BZ2_bzopen</computeroutput>,
+<computeroutput>BZ2_bzread</computeroutput>,
+<computeroutput>BZ2_bzwrite</computeroutput>,
+<computeroutput>BZ2_bzflush</computeroutput>,
+<computeroutput>BZ2_bzclose</computeroutput>,
+<computeroutput>BZ2_bzerror</computeroutput> and
+<computeroutput>BZ2_bzlibVersion</computeroutput>.  These
+functions are not (yet) officially part of the library.  If they
+break, you get to keep all the pieces.  Nevertheless, I think
+they work ok.</para>
+
+<programlisting>
+typedef void BZFILE;
+
+const char * BZ2_bzlibVersion ( void );
+</programlisting>
+
+<para>Returns a string indicating the library version.</para>
+
+<programlisting>
+BZFILE * BZ2_bzopen  ( const char *path, const char *mode );
+BZFILE * BZ2_bzdopen ( int        fd,    const char *mode );
+</programlisting>
+
+<para>Opens a <computeroutput>.bz2</computeroutput> file for
+reading or writing, using either its name or a pre-existing file
+descriptor.  Analogous to <computeroutput>fopen</computeroutput>
+and <computeroutput>fdopen</computeroutput>.</para>
+
+<programlisting>
+int BZ2_bzread  ( BZFILE* b, void* buf, int len );
+int BZ2_bzwrite ( BZFILE* b, void* buf, int len );
+</programlisting>
+
+<para>Reads/writes data from/to a previously opened
+<computeroutput>BZFILE</computeroutput>.  Analogous to
+<computeroutput>fread</computeroutput> and
+<computeroutput>fwrite</computeroutput>.</para>
+
+<programlisting>
+int  BZ2_bzflush ( BZFILE* b );
+void BZ2_bzclose ( BZFILE* b );
+</programlisting>
+
+<para>Flushes/closes a <computeroutput>BZFILE</computeroutput>.
+<computeroutput>BZ2_bzflush</computeroutput> doesn't actually do
+anything.  Analogous to <computeroutput>fflush</computeroutput>
+and <computeroutput>fclose</computeroutput>.</para>
+
+<programlisting>
+const char * BZ2_bzerror ( BZFILE *b, int *errnum )
+</programlisting>
+
+<para>Returns a string describing the more recent error status of
+<computeroutput>b</computeroutput>, and also sets
+<computeroutput>*errnum</computeroutput> to its numerical
+value.</para>
+
+</sect1>
+
+
+<sect1 id="stdio-free" 
+       xreflabel="Using the library in a stdio-free environment">
+<title>Using the library in a <computeroutput>stdio</computeroutput>-free environment</title>
+
+
+<sect2 id="stdio-bye" xreflabel="Getting rid of stdio">
+<title>Getting rid of <computeroutput>stdio</computeroutput></title>
+
+<para>In a deeply embedded application, you might want to use
+just the memory-to-memory functions.  You can do this
+conveniently by compiling the library with preprocessor symbol
+<computeroutput>BZ_NO_STDIO</computeroutput> defined.  Doing this
+gives you a library containing only the following eight
+functions:</para>
+
+<para><computeroutput>BZ2_bzCompressInit</computeroutput>,
+<computeroutput>BZ2_bzCompress</computeroutput>,
+<computeroutput>BZ2_bzCompressEnd</computeroutput>
+<computeroutput>BZ2_bzDecompressInit</computeroutput>,
+<computeroutput>BZ2_bzDecompress</computeroutput>,
+<computeroutput>BZ2_bzDecompressEnd</computeroutput>
+<computeroutput>BZ2_bzBuffToBuffCompress</computeroutput>,
+<computeroutput>BZ2_bzBuffToBuffDecompress</computeroutput></para>
+
+<para>When compiled like this, all functions will ignore
+<computeroutput>verbosity</computeroutput> settings.</para>
+
+</sect2>
+
+
+<sect2 id="critical-error" xreflabel="Critical error handling">
+<title>Critical error handling</title>
+
+<para><computeroutput>libbzip2</computeroutput> contains a number
+of internal assertion checks which should, needless to say, never
+be activated.  Nevertheless, if an assertion should fail,
+behaviour depends on whether or not the library was compiled with
+<computeroutput>BZ_NO_STDIO</computeroutput> set.</para>
+
+<para>For a normal compile, an assertion failure yields the
+message:</para>
+
+<blockquote>
+<para>bzip2/libbzip2: internal error number N.</para>
+<para>This is a bug in bzip2/libbzip2, &bz-version; of &bz-date;.
+Please report it to me at: &bz-email;.  If this happened
+when you were using some program which uses libbzip2 as a
+component, you should also report this bug to the author(s)
+of that program.  Please make an effort to report this bug;
+timely and accurate bug reports eventually lead to higher
+quality software.  Thanks.  Julian Seward, &bz-date;.
+</para></blockquote>
+
+<para>where <computeroutput>N</computeroutput> is some error code
+number.  If <computeroutput>N == 1007</computeroutput>, it also
+prints some extra text advising the reader that unreliable memory
+is often associated with internal error 1007. (This is a
+frequently-observed-phenomenon with versions 1.0.0/1.0.1).</para>
+
+<para><computeroutput>exit(3)</computeroutput> is then
+called.</para>
+
+<para>For a <computeroutput>stdio</computeroutput>-free library,
+assertion failures result in a call to a function declared
+as:</para>
+
+<programlisting>
+extern void bz_internal_error ( int errcode );
+</programlisting>
+
+<para>The relevant code is passed as a parameter.  You should
+supply such a function.</para>
+
+<para>In either case, once an assertion failure has occurred, any
+<computeroutput>bz_stream</computeroutput> records involved can
+be regarded as invalid.  You should not attempt to resume normal
+operation with them.</para>
+
+<para>You may, of course, change critical error handling to suit
+your needs.  As I said above, critical errors indicate bugs in
+the library and should not occur.  All "normal" error situations
+are indicated via error return codes from functions, and can be
+recovered from.</para>
+
+</sect2>
+
+</sect1>
+
+
+<sect1 id="win-dll" xreflabel="Making a Windows DLL">
+<title>Making a Windows DLL</title>
+
+<para>Everything related to Windows has been contributed by
+Yoshioka Tsuneo
+(<computeroutput>QWF00133@niftyserve.or.jp</computeroutput> /
+<computeroutput>tsuneo-y@is.aist-nara.ac.jp</computeroutput>), so
+you should send your queries to him (but perhaps Cc: me,
+<computeroutput>&bz-email;</computeroutput>).</para>
+
+<para>My vague understanding of what to do is: using Visual C++
+5.0, open the project file
+<computeroutput>libbz2.dsp</computeroutput>, and build.  That's
+all.</para>
+
+<para>If you can't open the project file for some reason, make a
+new one, naming these files:
+<computeroutput>blocksort.c</computeroutput>,
+<computeroutput>bzlib.c</computeroutput>,
+<computeroutput>compress.c</computeroutput>,
+<computeroutput>crctable.c</computeroutput>,
+<computeroutput>decompress.c</computeroutput>,
+<computeroutput>huffman.c</computeroutput>,
+<computeroutput>randtable.c</computeroutput> and
+<computeroutput>libbz2.def</computeroutput>.  You will also need
+to name the header files <computeroutput>bzlib.h</computeroutput>
+and <computeroutput>bzlib_private.h</computeroutput>.</para>
+
+<para>If you don't use VC++, you may need to define the
+proprocessor symbol
+<computeroutput>_WIN32</computeroutput>.</para>
+
+<para>Finally, <computeroutput>dlltest.c</computeroutput> is a
+sample program using the DLL.  It has a project file,
+<computeroutput>dlltest.dsp</computeroutput>.</para>
+
+<para>If you just want a makefile for Visual C, have a look at
+<computeroutput>makefile.msc</computeroutput>.</para>
+
+<para>Be aware that if you compile
+<computeroutput>bzip2</computeroutput> itself on Win32, you must
+set <computeroutput>BZ_UNIX</computeroutput> to 0 and
+<computeroutput>BZ_LCCWIN32</computeroutput> to 1, in the file
+<computeroutput>bzip2.c</computeroutput>, before compiling.
+Otherwise the resulting binary won't work correctly.</para>
+
+<para>I haven't tried any of this stuff myself, but it all looks
+plausible.</para>
+
+</sect1>
+
+</chapter>
+
+
+
+<chapter id="misc" xreflabel="Miscellanea">
+<title>Miscellanea</title>
+
+<para>These are just some random thoughts of mine.  Your mileage
+may vary.</para>
+
+
+<sect1 id="limits" xreflabel="Limitations of the compressed file format">
+<title>Limitations of the compressed file format</title>
+
+<para><computeroutput>bzip2-1.0.X</computeroutput>,
+<computeroutput>0.9.5</computeroutput> and
+<computeroutput>0.9.0</computeroutput> use exactly the same file
+format as the original version,
+<computeroutput>bzip2-0.1</computeroutput>.  This decision was
+made in the interests of stability.  Creating yet another
+incompatible compressed file format would create further
+confusion and disruption for users.</para>
+
+<para>Nevertheless, this is not a painless decision.  Development
+work since the release of
+<computeroutput>bzip2-0.1</computeroutput> in August 1997 has
+shown complexities in the file format which slow down
+decompression and, in retrospect, are unnecessary.  These
+are:</para>
+
+<itemizedlist mark='bullet'>
+
+ <listitem><para>The run-length encoder, which is the first of the
+   compression transformations, is entirely irrelevant.  The
+   original purpose was to protect the sorting algorithm from the
+   very worst case input: a string of repeated symbols.  But
+   algorithm steps Q6a and Q6b in the original Burrows-Wheeler
+   technical report (SRC-124) show how repeats can be handled
+   without difficulty in block sorting.</para></listitem>
+
+ <listitem><para>The randomisation mechanism doesn't really need to be
+   there.  Udi Manber and Gene Myers published a suffix array
+   construction algorithm a few years back, which can be employed
+   to sort any block, no matter how repetitive, in O(N log N)
+   time.  Subsequent work by Kunihiko Sadakane has produced a
+   derivative O(N (log N)^2) algorithm which usually outperforms
+   the Manber-Myers algorithm.</para>
+
+   <para>I could have changed to Sadakane's algorithm, but I find
+   it to be slower than <computeroutput>bzip2</computeroutput>'s
+   existing algorithm for most inputs, and the randomisation
+   mechanism protects adequately against bad cases.  I didn't
+   think it was a good tradeoff to make.  Partly this is due to
+   the fact that I was not flooded with email complaints about
+   <computeroutput>bzip2-0.1</computeroutput>'s performance on
+   repetitive data, so perhaps it isn't a problem for real
+   inputs.</para>
+
+   <para>Probably the best long-term solution, and the one I have
+   incorporated into 0.9.5 and above, is to use the existing
+   sorting algorithm initially, and fall back to a O(N (log N)^2)
+   algorithm if the standard algorithm gets into
+   difficulties.</para></listitem>
+
+  <listitem><para>The compressed file format was never designed to be
+   handled by a library, and I have had to jump though some hoops
+   to produce an efficient implementation of decompression.  It's
+   a bit hairy.  Try passing
+   <computeroutput>decompress.c</computeroutput> through the C
+   preprocessor and you'll see what I mean.  Much of this
+   complexity could have been avoided if the compressed size of
+   each block of data was recorded in the data stream.</para></listitem>
+
+ <listitem><para>An Adler-32 checksum, rather than a CRC32 checksum,
+   would be faster to compute.</para></listitem>
+
+</itemizedlist>
+
+<para>It would be fair to say that the
+<computeroutput>bzip2</computeroutput> format was frozen before I
+properly and fully understood the performance consequences of
+doing so.</para>
+
+<para>Improvements which I was able to incorporate into 0.9.0,
+despite using the same file format, are:</para>
+
+<itemizedlist mark='bullet'>
+
+ <listitem><para>Single array implementation of the inverse BWT.  This
+  significantly speeds up decompression, presumably because it
+  reduces the number of cache misses.</para></listitem>
+
+ <listitem><para>Faster inverse MTF transform for large MTF values.
+  The new implementation is based on the notion of sliding blocks
+  of values.</para></listitem>
+
+ <listitem><para><computeroutput>bzip2-0.9.0</computeroutput> now reads
+  and writes files with <computeroutput>fread</computeroutput>
+  and <computeroutput>fwrite</computeroutput>; version 0.1 used
+  <computeroutput>putc</computeroutput> and
+  <computeroutput>getc</computeroutput>.  Duh!  Well, you live
+  and learn.</para></listitem>
+
+</itemizedlist>
+
+<para>Further ahead, it would be nice to be able to do random
+access into files.  This will require some careful design of
+compressed file formats.</para>
+
+</sect1>
+
+
+<sect1 id="port-issues" xreflabel="Portability issues">
+<title>Portability issues</title>
+
+<para>After some consideration, I have decided not to use GNU
+<computeroutput>autoconf</computeroutput> to configure 0.9.5 or
+1.0.</para>
+
+<para><computeroutput>autoconf</computeroutput>, admirable and
+wonderful though it is, mainly assists with portability problems
+between Unix-like platforms.  But
+<computeroutput>bzip2</computeroutput> doesn't have much in the
+way of portability problems on Unix; most of the difficulties
+appear when porting to the Mac, or to Microsoft's operating
+systems.  <computeroutput>autoconf</computeroutput> doesn't help
+in those cases, and brings in a whole load of new
+complexity.</para>
+
+<para>Most people should be able to compile the library and
+program under Unix straight out-of-the-box, so to speak,
+especially if you have a version of GNU C available.</para>
+
+<para>There are a couple of
+<computeroutput>__inline__</computeroutput> directives in the
+code.  GNU C (<computeroutput>gcc</computeroutput>) should be
+able to handle them.  If you're not using GNU C, your C compiler
+shouldn't see them at all.  If your compiler does, for some
+reason, see them and doesn't like them, just
+<computeroutput>#define</computeroutput>
+<computeroutput>__inline__</computeroutput> to be
+<computeroutput>/* */</computeroutput>.  One easy way to do this
+is to compile with the flag
+<computeroutput>-D__inline__=</computeroutput>, which should be
+understood by most Unix compilers.</para>
+
+<para>If you still have difficulties, try compiling with the
+macro <computeroutput>BZ_STRICT_ANSI</computeroutput> defined.
+This should enable you to build the library in a strictly ANSI
+compliant environment.  Building the program itself like this is
+dangerous and not supported, since you remove
+<computeroutput>bzip2</computeroutput>'s checks against
+compressing directories, symbolic links, devices, and other
+not-really-a-file entities.  This could cause filesystem
+corruption!</para>
+
+<para>One other thing: if you create a
+<computeroutput>bzip2</computeroutput> binary for public distribution,
+please consider linking it statically (<computeroutput>gcc
+-static</computeroutput>).  This avoids all sorts of library-version
+issues that others may encounter later on.</para>
+
+<para>If you build <computeroutput>bzip2</computeroutput> on
+Win32, you must set <computeroutput>BZ_UNIX</computeroutput> to 0
+and <computeroutput>BZ_LCCWIN32</computeroutput> to 1, in the
+file <computeroutput>bzip2.c</computeroutput>, before compiling.
+Otherwise the resulting binary won't work correctly.</para>
+
+</sect1>
+
+
+<sect1 id="bugs" xreflabel="Reporting bugs">
+<title>Reporting bugs</title>
+
+<para>I tried pretty hard to make sure
+<computeroutput>bzip2</computeroutput> is bug free, both by
+design and by testing.  Hopefully you'll never need to read this
+section for real.</para>
+
+<para>Nevertheless, if <computeroutput>bzip2</computeroutput> dies
+with a segmentation fault, a bus error or an internal assertion
+failure, it will ask you to email me a bug report.  Experience from
+years of feedback of bzip2 users indicates that almost all these
+problems can be traced to either compiler bugs or hardware
+problems.</para>
+
+<itemizedlist mark='bullet'>
+
+ <listitem><para>Recompile the program with no optimisation, and
+  see if it works.  And/or try a different compiler.  I heard all
+  sorts of stories about various flavours of GNU C (and other
+  compilers) generating bad code for
+  <computeroutput>bzip2</computeroutput>, and I've run across two
+  such examples myself.</para>
+
+  <para>2.7.X versions of GNU C are known to generate bad code
+  from time to time, at high optimisation levels.  If you get
+  problems, try using the flags
+  <computeroutput>-O2</computeroutput>
+  <computeroutput>-fomit-frame-pointer</computeroutput>
+  <computeroutput>-fno-strength-reduce</computeroutput>.  You
+  should specifically <emphasis>not</emphasis> use
+  <computeroutput>-funroll-loops</computeroutput>.</para>
+
+  <para>You may notice that the Makefile runs six tests as part
+  of the build process.  If the program passes all of these, it's
+  a pretty good (but not 100%) indication that the compiler has
+  done its job correctly.</para></listitem>
+
+ <listitem><para>If <computeroutput>bzip2</computeroutput>
+  crashes randomly, and the crashes are not repeatable, you may
+  have a flaky memory subsystem.
+  <computeroutput>bzip2</computeroutput> really hammers your
+  memory hierarchy, and if it's a bit marginal, you may get these
+  problems.  Ditto if your disk or I/O subsystem is slowly
+  failing.  Yup, this really does happen.</para>
+
+  <para>Try using a different machine of the same type, and see
+  if you can repeat the problem.</para></listitem>
+
+  <listitem><para>This isn't really a bug, but ... If
+  <computeroutput>bzip2</computeroutput> tells you your file is
+  corrupted on decompression, and you obtained the file via FTP,
+  there is a possibility that you forgot to tell FTP to do a
+  binary mode transfer.  That absolutely will cause the file to
+  be non-decompressible.  You'll have to transfer it
+  again.</para></listitem>
+
+</itemizedlist>
+
+<para>If you've incorporated
+<computeroutput>libbzip2</computeroutput> into your own program
+and are getting problems, please, please, please, check that the
+parameters you are passing in calls to the library, are correct,
+and in accordance with what the documentation says is allowable.
+I have tried to make the library robust against such problems,
+but I'm sure I haven't succeeded.</para>
+
+<para>Finally, if the above comments don't help, you'll have to
+send me a bug report.  Now, it's just amazing how many people
+will send me a bug report saying something like:</para>
+
+<programlisting>
+bzip2 crashed with segmentation fault on my machine
+</programlisting>
+
+<para>and absolutely nothing else.  Needless to say, a such a
+report is <emphasis>totally, utterly, completely and
+comprehensively 100% useless; a waste of your time, my time, and
+net bandwidth</emphasis>.  With no details at all, there's no way
+I can possibly begin to figure out what the problem is.</para>
+
+<para>The rules of the game are: facts, facts, facts.  Don't omit
+them because "oh, they won't be relevant".  At the bare
+minimum:</para>
+
+<programlisting>
+Machine type.  Operating system version.  
+Exact version of bzip2 (do bzip2 -V).  
+Exact version of the compiler used.  
+Flags passed to the compiler.
+</programlisting>
+
+<para>However, the most important single thing that will help me
+is the file that you were trying to compress or decompress at the
+time the problem happened.  Without that, my ability to do
+anything more than speculate about the cause, is limited.</para>
+
+</sect1>
+
+
+<sect1 id="package" xreflabel="Did you get the right package?">
+<title>Did you get the right package?</title>
+
+<para><computeroutput>bzip2</computeroutput> is a resource hog.
+It soaks up large amounts of CPU cycles and memory.  Also, it
+gives very large latencies.  In the worst case, you can feed many
+megabytes of uncompressed data into the library before getting
+any compressed output, so this probably rules out applications
+requiring interactive behaviour.</para>
+
+<para>These aren't faults of my implementation, I hope, but more
+an intrinsic property of the Burrows-Wheeler transform
+(unfortunately).  Maybe this isn't what you want.</para>
+
+<para>If you want a compressor and/or library which is faster,
+uses less memory but gets pretty good compression, and has
+minimal latency, consider Jean-loup Gailly's and Mark Adler's
+work, <computeroutput>zlib-1.2.1</computeroutput> and
+<computeroutput>gzip-1.2.4</computeroutput>.  Look for them at 
+<ulink url="http://www.zlib.org">http://www.zlib.org</ulink> and 
+<ulink url="http://www.gzip.org">http://www.gzip.org</ulink>
+respectively.</para>
+
+<para>For something faster and lighter still, you might try Markus F
+X J Oberhumer's <computeroutput>LZO</computeroutput> real-time
+compression/decompression library, at 
+<ulink url="http://www.oberhumer.com/opensource">http://www.oberhumer.com/opensource</ulink>.</para>
+
+</sect1>
+
+
+
+<sect1 id="reading" xreflabel="Further Reading">
+<title>Further Reading</title>
+
+<para><computeroutput>bzip2</computeroutput> is not research
+work, in the sense that it doesn't present any new ideas.
+Rather, it's an engineering exercise based on existing
+ideas.</para>
+
+<para>Four documents describe essentially all the ideas behind
+<computeroutput>bzip2</computeroutput>:</para>
+
+<literallayout>Michael Burrows and D. J. Wheeler:
+  "A block-sorting lossless data compression algorithm"
+   10th May 1994. 
+   Digital SRC Research Report 124.
+   ftp://ftp.digital.com/pub/DEC/SRC/research-reports/SRC-124.ps.gz
+   If you have trouble finding it, try searching at the
+   New Zealand Digital Library, http://www.nzdl.org.
+
+Daniel S. Hirschberg and Debra A. LeLewer
+  "Efficient Decoding of Prefix Codes"
+   Communications of the ACM, April 1990, Vol 33, Number 4.
+   You might be able to get an electronic copy of this
+   from the ACM Digital Library.
+
+David J. Wheeler
+   Program bred3.c and accompanying document bred3.ps.
+   This contains the idea behind the multi-table Huffman coding scheme.
+   ftp://ftp.cl.cam.ac.uk/users/djw3/
+
+Jon L. Bentley and Robert Sedgewick
+  "Fast Algorithms for Sorting and Searching Strings"
+   Available from Sedgewick's web page,
+   www.cs.princeton.edu/~rs
+</literallayout>
+
+<para>The following paper gives valuable additional insights into
+the algorithm, but is not immediately the basis of any code used
+in bzip2.</para>
+
+<literallayout>Peter Fenwick:
+   Block Sorting Text Compression
+   Proceedings of the 19th Australasian Computer Science Conference,
+     Melbourne, Australia.  Jan 31 - Feb 2, 1996.
+   ftp://ftp.cs.auckland.ac.nz/pub/peter-f/ACSC96paper.ps</literallayout>
+
+<para>Kunihiko Sadakane's sorting algorithm, mentioned above, is
+available from:</para>
+
+<literallayout>http://naomi.is.s.u-tokyo.ac.jp/~sada/papers/Sada98b.ps.gz
+</literallayout>
+
+<para>The Manber-Myers suffix array construction algorithm is
+described in a paper available from:</para>
+
+<literallayout>http://www.cs.arizona.edu/people/gene/PAPERS/suffix.ps
+</literallayout>
+
+<para>Finally, the following papers document some
+investigations I made into the performance of sorting
+and decompression algorithms:</para>
+
+<literallayout>Julian Seward
+   On the Performance of BWT Sorting Algorithms
+   Proceedings of the IEEE Data Compression Conference 2000
+     Snowbird, Utah.  28-30 March 2000.
+
+Julian Seward
+   Space-time Tradeoffs in the Inverse B-W Transform
+   Proceedings of the IEEE Data Compression Conference 2001
+     Snowbird, Utah.  27-29 March 2001.
+</literallayout>
+
+</sect1>
+
+</chapter>
+
+</book>
Index: /trunk/minix/commands/bzip2-1.0.3/mk251.c
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/mk251.c	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/mk251.c	(revision 9)
@@ -0,0 +1,16 @@
+
+/* Spew out a long sequence of the byte 251.  When fed to bzip2
+   versions 1.0.0 or 1.0.1, causes it to die with internal error
+   1007 in blocksort.c.  This assertion misses an extremely rare
+   case, which is fixed in this version (1.0.2) and above.
+*/
+
+#include <stdio.h>
+
+int main ()
+{
+   int i;
+   for (i = 0; i < 48500000 ; i++)
+     putchar(251);
+   return 0;
+}
Index: /trunk/minix/commands/bzip2-1.0.3/randtable.c
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/randtable.c	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/randtable.c	(revision 9)
@@ -0,0 +1,124 @@
+
+/*-------------------------------------------------------------*/
+/*--- Table for randomising repetitive blocks               ---*/
+/*---                                           randtable.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2005 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@bzip.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+
+#include "bzlib_private.h"
+
+
+/*---------------------------------------------*/
+Int32 BZ2_rNums[512] = { 
+   619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 
+   985, 724, 205, 454, 863, 491, 741, 242, 949, 214, 
+   733, 859, 335, 708, 621, 574, 73, 654, 730, 472, 
+   419, 436, 278, 496, 867, 210, 399, 680, 480, 51, 
+   878, 465, 811, 169, 869, 675, 611, 697, 867, 561, 
+   862, 687, 507, 283, 482, 129, 807, 591, 733, 623, 
+   150, 238, 59, 379, 684, 877, 625, 169, 643, 105, 
+   170, 607, 520, 932, 727, 476, 693, 425, 174, 647, 
+   73, 122, 335, 530, 442, 853, 695, 249, 445, 515, 
+   909, 545, 703, 919, 874, 474, 882, 500, 594, 612, 
+   641, 801, 220, 162, 819, 984, 589, 513, 495, 799, 
+   161, 604, 958, 533, 221, 400, 386, 867, 600, 782, 
+   382, 596, 414, 171, 516, 375, 682, 485, 911, 276, 
+   98, 553, 163, 354, 666, 933, 424, 341, 533, 870, 
+   227, 730, 475, 186, 263, 647, 537, 686, 600, 224, 
+   469, 68, 770, 919, 190, 373, 294, 822, 808, 206, 
+   184, 943, 795, 384, 383, 461, 404, 758, 839, 887, 
+   715, 67, 618, 276, 204, 918, 873, 777, 604, 560, 
+   951, 160, 578, 722, 79, 804, 96, 409, 713, 940, 
+   652, 934, 970, 447, 318, 353, 859, 672, 112, 785, 
+   645, 863, 803, 350, 139, 93, 354, 99, 820, 908, 
+   609, 772, 154, 274, 580, 184, 79, 626, 630, 742, 
+   653, 282, 762, 623, 680, 81, 927, 626, 789, 125, 
+   411, 521, 938, 300, 821, 78, 343, 175, 128, 250, 
+   170, 774, 972, 275, 999, 639, 495, 78, 352, 126, 
+   857, 956, 358, 619, 580, 124, 737, 594, 701, 612, 
+   669, 112, 134, 694, 363, 992, 809, 743, 168, 974, 
+   944, 375, 748, 52, 600, 747, 642, 182, 862, 81, 
+   344, 805, 988, 739, 511, 655, 814, 334, 249, 515, 
+   897, 955, 664, 981, 649, 113, 974, 459, 893, 228, 
+   433, 837, 553, 268, 926, 240, 102, 654, 459, 51, 
+   686, 754, 806, 760, 493, 403, 415, 394, 687, 700, 
+   946, 670, 656, 610, 738, 392, 760, 799, 887, 653, 
+   978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 
+   680, 879, 194, 572, 640, 724, 926, 56, 204, 700, 
+   707, 151, 457, 449, 797, 195, 791, 558, 945, 679, 
+   297, 59, 87, 824, 713, 663, 412, 693, 342, 606, 
+   134, 108, 571, 364, 631, 212, 174, 643, 304, 329, 
+   343, 97, 430, 751, 497, 314, 983, 374, 822, 928, 
+   140, 206, 73, 263, 980, 736, 876, 478, 430, 305, 
+   170, 514, 364, 692, 829, 82, 855, 953, 676, 246, 
+   369, 970, 294, 750, 807, 827, 150, 790, 288, 923, 
+   804, 378, 215, 828, 592, 281, 565, 555, 710, 82, 
+   896, 831, 547, 261, 524, 462, 293, 465, 502, 56, 
+   661, 821, 976, 991, 658, 869, 905, 758, 745, 193, 
+   768, 550, 608, 933, 378, 286, 215, 979, 792, 961, 
+   61, 688, 793, 644, 986, 403, 106, 366, 905, 644, 
+   372, 567, 466, 434, 645, 210, 389, 550, 919, 135, 
+   780, 773, 635, 389, 707, 100, 626, 958, 165, 504, 
+   920, 176, 193, 713, 857, 265, 203, 50, 668, 108, 
+   645, 990, 626, 197, 510, 357, 358, 850, 858, 364, 
+   936, 638
+};
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                       randtable.c ---*/
+/*-------------------------------------------------------------*/
Index: /trunk/minix/commands/bzip2-1.0.3/sample3.ref
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/sample3.ref	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/sample3.ref	(revision 9)
@@ -0,0 +1,30007 @@
+This file is exceedingly boring.  If you find yourself
+reading it, please (1) take it from me that you can safely
+guess what the rest of the file says, and (2) seek professional
+help.
+
+ps.  there are no further sarcastic remarks in this file.
+
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
+ugh
Index: /trunk/minix/commands/bzip2-1.0.3/spewG.c
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/spewG.c	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/spewG.c	(revision 9)
@@ -0,0 +1,39 @@
+
+/* spew out a thoroughly gigantic file designed so that bzip2
+   can compress it reasonably rapidly.  This is to help test
+   support for large files (> 2GB) in a reasonable amount of time.
+   I suggest you use the undocumented --exponential option to
+   bzip2 when compressing the resulting file; this saves a bit of
+   time.  Note: *don't* bother with --exponential when compressing 
+   Real Files; it'll just waste a lot of CPU time :-)
+   (but is otherwise harmless).
+*/
+
+#define _FILE_OFFSET_BITS 64
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* The number of megabytes of junk to spew out (roughly) */
+#define MEGABYTES 5000
+
+#define N_BUF 1000000
+char buf[N_BUF];
+
+int main ( int argc, char** argv )
+{
+   int ii, kk, p;
+   srandom(1);
+   setbuffer ( stdout, buf, N_BUF );
+   for (kk = 0; kk < MEGABYTES * 515; kk+=3) {
+      p = 25+random()%50;
+      for (ii = 0; ii < p; ii++)
+         printf ( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" );
+      for (ii = 0; ii < p-1; ii++)
+         printf ( "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" );
+      for (ii = 0; ii < p+1; ii++)
+         printf ( "ccccccccccccccccccccccccccccccccccccc" );
+   }
+   fflush(stdout);
+   return 0;
+}
Index: /trunk/minix/commands/bzip2-1.0.3/unzcrash.c
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/unzcrash.c	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/unzcrash.c	(revision 9)
@@ -0,0 +1,126 @@
+
+/* A test program written to test robustness to decompression of
+   corrupted data.  Usage is 
+       unzcrash filename
+   and the program will read the specified file, compress it (in memory),
+   and then repeatedly decompress it, each time with a different bit of
+   the compressed data inverted, so as to test all possible one-bit errors.
+   This should not cause any invalid memory accesses.  If it does, 
+   I want to know about it!
+
+   p.s.  As you can see from the above description, the process is
+   incredibly slow.  A file of size eg 5KB will cause it to run for
+   many hours.
+*/
+
+#include <stdio.h>
+#include <assert.h>
+#include "bzlib.h"
+
+#define M_BLOCK 1000000
+
+typedef unsigned char uchar;
+
+#define M_BLOCK_OUT (M_BLOCK + 1000000)
+uchar inbuf[M_BLOCK];
+uchar outbuf[M_BLOCK_OUT];
+uchar zbuf[M_BLOCK + 600 + (M_BLOCK / 100)];
+
+int nIn, nOut, nZ;
+
+static char *bzerrorstrings[] = {
+       "OK"
+      ,"SEQUENCE_ERROR"
+      ,"PARAM_ERROR"
+      ,"MEM_ERROR"
+      ,"DATA_ERROR"
+      ,"DATA_ERROR_MAGIC"
+      ,"IO_ERROR"
+      ,"UNEXPECTED_EOF"
+      ,"OUTBUFF_FULL"
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+};
+
+void flip_bit ( int bit )
+{
+   int byteno = bit / 8;
+   int bitno  = bit % 8;
+   uchar mask = 1 << bitno;
+   //fprintf ( stderr, "(byte %d  bit %d  mask %d)",
+   //          byteno, bitno, (int)mask );
+   zbuf[byteno] ^= mask;
+}
+
+int main ( int argc, char** argv )
+{
+   FILE* f;
+   int   r;
+   int   bit;
+   int   i;
+
+   if (argc != 2) {
+      fprintf ( stderr, "usage: unzcrash filename\n" );
+      return 1;
+   }
+
+   f = fopen ( argv[1], "r" );
+   if (!f) {
+      fprintf ( stderr, "unzcrash: can't open %s\n", argv[1] );
+      return 1;
+   }
+
+   nIn = fread ( inbuf, 1, M_BLOCK, f );
+   fprintf ( stderr, "%d bytes read\n", nIn );
+
+   nZ = M_BLOCK;
+   r = BZ2_bzBuffToBuffCompress (
+         zbuf, &nZ, inbuf, nIn, 9, 0, 30 );
+
+   assert (r == BZ_OK);
+   fprintf ( stderr, "%d after compression\n", nZ );
+
+   for (bit = 0; bit < nZ*8; bit++) {
+      fprintf ( stderr, "bit %d  ", bit );
+      flip_bit ( bit );
+      nOut = M_BLOCK_OUT;
+      r = BZ2_bzBuffToBuffDecompress (
+            outbuf, &nOut, zbuf, nZ, 0, 0 );
+      fprintf ( stderr, " %d  %s ", r, bzerrorstrings[-r] );
+
+      if (r != BZ_OK) {
+         fprintf ( stderr, "\n" );
+      } else {
+         if (nOut != nIn) {
+           fprintf(stderr, "nIn/nOut mismatch %d %d\n", nIn, nOut );
+           return 1;
+         } else {
+           for (i = 0; i < nOut; i++)
+             if (inbuf[i] != outbuf[i]) { 
+                fprintf(stderr, "mismatch at %d\n", i ); 
+                return 1; 
+           }
+           if (i == nOut) fprintf(stderr, "really ok!\n" );
+         }
+      }
+
+      flip_bit ( bit );
+   }
+
+#if 0
+   assert (nOut == nIn);
+   for (i = 0; i < nOut; i++) {
+     if (inbuf[i] != outbuf[i]) {
+        fprintf ( stderr, "difference at %d !\n", i );
+        return 1;
+     }
+   }
+#endif
+
+   fprintf ( stderr, "all ok\n" );
+   return 0;
+}
Index: /trunk/minix/commands/bzip2-1.0.3/words0
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/words0	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/words0	(revision 9)
@@ -0,0 +1,5 @@
+
+If compilation produces errors, or a large number of warnings, 
+please read README.COMPILATION.PROBLEMS -- you might be able to
+adjust the flags in this Makefile to improve matters.
+
Index: /trunk/minix/commands/bzip2-1.0.3/words1
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/words1	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/words1	(revision 9)
@@ -0,0 +1,4 @@
+
+Doing 6 tests (3 compress, 3 uncompress) ...
+If there's a problem, things might stop at this point.
+ 
Index: /trunk/minix/commands/bzip2-1.0.3/words2
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/words2	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/words2	(revision 9)
@@ -0,0 +1,5 @@
+
+Checking test results.  If any of the four "cmp"s which follow
+report any differences, something is wrong.  If you can't easily
+figure out what, please let me know (jseward@acm.org).
+
Index: /trunk/minix/commands/bzip2-1.0.3/words3
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/words3	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/words3	(revision 9)
@@ -0,0 +1,23 @@
+
+If you got this far and the "cmp"s didn't complain, it looks
+like you're in business.  
+
+To install in /usr/bin, /usr/lib, /usr/man and /usr/include, type
+   make install
+To install somewhere else, eg, /xxx/yyy/{bin,lib,man,include}, type 
+   make install PREFIX=/xxx/yyy
+If you are (justifiably) paranoid and want to see what 'make install'
+is going to do, you can first do
+   make -n install                      or
+   make -n install PREFIX=/xxx/yyy      respectively.
+The -n instructs make to show the commands it would execute, but
+not actually execute them.
+
+Instructions for use are in the preformatted manual page, in the file
+bzip2.txt.  For more detailed documentation, read the full manual.  
+It is available in Postscript form (manual.ps), PDF form (manual.pdf),
+and HTML form (manual_toc.html).
+
+You can also do "bzip2 --help" to see some helpful information. 
+"bzip2 -L" displays the software license.
+
Index: /trunk/minix/commands/bzip2-1.0.3/xmlproc.sh
===================================================================
--- /trunk/minix/commands/bzip2-1.0.3/xmlproc.sh	(revision 9)
+++ /trunk/minix/commands/bzip2-1.0.3/xmlproc.sh	(revision 9)
@@ -0,0 +1,99 @@
+#!/bin/bash
+# see the README in this directory for usage etc.
+
+usage() {
+  echo '';
+  echo 'Usage: xmlproc.sh -[option] <filename.xml>';
+  echo 'Specify a target from:';
+  echo '-v      verify xml file conforms to dtd';
+  echo '-html   output in html format (single file)';
+  echo '-ps     output in postscript format';
+  echo '-pdf    output in pdf format';
+  exit;
+}
+
+if test $# -ne 2; then
+  usage
+fi
+# assign the variable for the output type
+action=$1; shift
+# assign the output filename
+xmlfile=$1; shift
+# and check user input it correct
+if !(test -f $xmlfile); then
+  echo "No such file: $xmlfile";
+  exit;
+fi
+# some other stuff we will use
+OUT=output
+xsl_fo=bz-fo.xsl
+xsl_html=bz-html.xsl
+
+basename=$xmlfile
+basename=${basename//'.xml'/''}
+
+fofile="${basename}.fo"
+htmlfile="${basename}.html"
+pdffile="${basename}.pdf"
+psfile="${basename}.ps"
+xmlfmtfile="${basename}.fmt"
+
+# first process the xmlfile with CDATA tags
+./format.pl $xmlfile $xmlfmtfile
+# so the shell knows where the catalogs live
+export XML_CATALOG_FILES=/etc/xml/catalog
+
+# post-processing tidy up
+cleanup() {
+  echo "Cleaning up: # $@" 
+  while [ $# != 0 ]
+  do
+    arg=$1; shift;
+    echo "  deleting $arg";
+    rm $arg
+  done
+}
+
+case $action in
+  -v)
+   flags='--noout --xinclude --noblanks --postvalid'
+   dtd='--dtdvalid http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd'
+   xmllint $flags $dtd $xmlfmtfile 2> $OUT 
+   egrep 'error' $OUT 
+   rm $OUT
+  ;;
+
+  -html)
+   echo "Creating $htmlfile ..."
+   xsltproc --nonet --xinclude  -o $htmlfile $xsl_html $xmlfmtfile
+   cleanup $xmlfmtfile
+  ;;
+
+  -pdf)
+   echo "Creating $pdffile ..."
+   xsltproc --nonet --xinclude -o $fofile $xsl_fo $xmlfmtfile
+   pdfxmltex $fofile >$OUT </dev/null
+   pdfxmltex $fofile >$OUT </dev/null
+   pdfxmltex $fofile >$OUT </dev/null
+   cleanup $OUT $xmlfmtfile *.aux *.fo *.log *.out
+  ;;
+
+  -ps)
+   echo "Creating $psfile ..."
+   xsltproc --nonet --xinclude -o $fofile $xsl_fo $xmlfmtfile
+   pdfxmltex $fofile >$OUT </dev/null
+   pdfxmltex $fofile >$OUT </dev/null
+   pdfxmltex $fofile >$OUT </dev/null
+   pdftops $pdffile $psfile
+   cleanup $OUT $xmlfmtfile $pdffile *.aux *.fo *.log *.out
+#  passivetex is broken, so we can't go this route yet.
+#   xmltex $fofile >$OUT </dev/null
+#   xmltex $fofile >$OUT </dev/null
+#   xmltex $fofile >$OUT </dev/null
+#   dvips -R -q -o bzip-manual.ps *.dvi
+  ;;
+
+  *)
+  usage
+  ;;
+esac
Index: /trunk/minix/commands/cawf/Makefile
===================================================================
--- /trunk/minix/commands/cawf/Makefile	(revision 9)
+++ /trunk/minix/commands/cawf/Makefile	(revision 9)
@@ -0,0 +1,107 @@
+# 	Makefile for cawf
+
+#	Define UNIX for vanilla Unix systems -- e.g., older DYNIX.
+#
+#	Define UNIX and USG for System V, BSD 4.3 and for SunOS.
+#
+#	USG may also be needed if the required string function prototypes --
+#	e.g., for strrchr() -- are in <string.h> rather than <strings.h>.
+#
+#DEFS = -DUNIX -DUSG
+#
+#	Define STDLIB for systems that have <stdlib.h> -- e.g., AIX and
+#	SunOS.
+#
+#	Redefine CAWFLIB by adding -DCAWFLIB=\"...\" to DEFS.
+#
+#DEFS = -DUNIX -DUSG -DCAWFLIB=\"/usr/local/lib/cawf\"
+#
+#	Customize the install rule.
+#
+#	-ansi and -pedantic are ANSI compliance options for the gcc compiler.
+#	Remove them if your compiler objects.
+#
+#	If you're using xlc 2.1 on AIX 3.2 for the RISC/SYSTEM 6000, you
+#	must delete the definition of __STR__ (two leading and two trailing
+#	underscore characters), because the xlc 2.1 compiler incorrectly
+#	inlines string functions when compiling pass3.c.
+#
+#DEFS = -DUNIX -DSTDLIB -U__STR__
+#
+#	Unix systems that have a <malloc.h> need MALLOCH defined, unless
+#	they also have a <stdlib.h> that provides a function prototype for
+#	malloc() and its relatives (most do).
+#
+#DEFS = -DUNIX -DMALLOCH
+
+CC = exec cc
+
+DEFS = -DUNIX -DUSG -DSTDLIB
+
+CFLAGS = -i -f -wo -O ${DEFS}
+
+HDR = ansi.h cawf.h cawflib.h proto.h regexp.h regmagic.h
+
+SRC = cawf.c device.c error.c expand.c expr.c getopt.c macsup.c nreq.c \
+      output.c pass2.c pass3.c  regerror.c regexp.c store.c string.c
+
+OBJ = cawf.o device.o error.o expand.o expr.o getopt.o macsup.o nreq.o \
+      output.o pass2.o pass3.o  regerror.o regexp.o store.o string.o
+
+all:	bsfilt cawf
+
+bsfilt: bsfilt.c
+	${CC} ${CFLAGS} bsfilt.c -o $@
+	install -S 4kw $@
+
+cawf:	${OBJ}
+	${CC} ${CFLAGS} ${OBJ} -o $@
+	install -S 56k $@
+
+clean:
+	rm -f *.o a.out core *errs bsfilt cawf
+
+${OBJ}:	${HDR}
+
+install:	\
+	/usr/bin/bsfilt /usr/bin/colcrt /usr/bin/cawf \
+	/usr/bin/nroff /usr/lib/cawf /usr/lib/cawf/common \
+	/usr/lib/cawf/device.cf /usr/lib/cawf/dumb.dev \
+	/usr/lib/cawf/man.mac /usr/lib/cawf/me.mac \
+	/usr/lib/cawf/ms.mac /usr/lib/cawf/mnx.mac
+
+/usr/bin/bsfilt:	bsfilt
+	install -cs -o bin bsfilt $@
+
+/usr/bin/colcrt:	/usr/bin/bsfilt
+	install -l /usr/bin/bsfilt $@
+
+/usr/bin/cawf:	cawf
+	install -cs -o bin cawf $@
+
+/usr/bin/nroff:	/usr/bin/cawf
+	install -l /usr/bin/cawf $@
+
+/usr/lib/cawf:	
+	install -d -o bin /usr/lib/cawf
+
+/usr/lib/cawf/common:	common
+	install -c -o bin common $@
+
+/usr/lib/cawf/device.cf:	device.cf
+	install -c -o bin device.cf $@
+
+/usr/lib/cawf/dumb.dev:	dumb.dev
+	install -c -o bin dumb.dev $@
+
+/usr/lib/cawf/man.mac:	man.mac
+	install -c -o bin man.mac $@
+
+/usr/lib/cawf/me.mac:	me.mac
+	install -c -o bin me.mac $@
+
+/usr/lib/cawf/ms.mac:	ms.mac
+	install -c -o bin ms.mac $@
+
+/usr/lib/cawf/mnx.mac:	mnx.mac
+	install -c -o bin mnx.mac $@
Index: /trunk/minix/commands/cawf/README
===================================================================
--- /trunk/minix/commands/cawf/README	(revision 9)
+++ /trunk/minix/commands/cawf/README	(revision 9)
@@ -0,0 +1,264 @@
+Cawf - nroff-like text formatter
+
+Cawf is a C version of awf, Henry Spencer's Amazingly Workable (text)
+Formatter.  (Awf is written in awk and appears in comp.sources.unix,
+Volume 23, Issue 27.)  Cawf and awf provide a usable subset of raw nroff
+capabilities and the styles of the man(7), me(7) and ms(7) macro sets.
+One of cawf's virtues is that it will run on PC clones under MS-DOS.  It
+is also, like awf, totally independent of any licensed Unix source code.
+
+This distribution contains complete source, make files for Unix and
+MS-DOS, documentation (raw and formatted) and MS-DOS executables for cawf
+and a companion output filters, bsfilt.
+
+This is the fourth distribution of cawf.  Changes include:
+
+	*  Some rudimentary output device support has been added, via a device
+	   configuration file.
+
+	*  The code has been converted to use unsigned characters.
+
+	*  An attempt has been made to make the code ANSI C compliant.
+
+	*  The following bugs have been fixed:
+
+		A bug in the locating of the device file has been corrected,
+		so that the code performs as documented.
+
+		Null macro arguments are ignored.
+
+		Some unused arguments to local functions have been more
+		carefully type cast to avoid portability problems.
+
+	*  The .fl and .rn requests are now supported.
+
+	*  Limited support has been added for the non-break request control
+	   character, the acute accent (').
+
+	*  Argument count conditionals -- operating on \n(.$ -- may now use
+	   the >= and <= operators in addition to [<=>].
+
+	*  Macros may be terminated with "..", ".", "''" or "'".
+
+	*  String interpolation is performed if it is specified at the start
+	   of the .ds request argument.
+
+	*  The .tr request has been enhanced to handle named characters and
+	   string interpolation.
+
+	*  The SS macro is now included in man.mac.
+
+	*  The cawf version number is now displayed in the help output.
+
+	*  A limited -me macro set is included in me.mac.
+
+Changes to cawf to run under Minix:
+
+	*  The DOS binaries and make files have been removed.
+ 
+	*  Tabs stops changed from per 5 to per 8.
+
+	*  Bold and underline as it should be in device.cf.
+
+	*  Added .SB and .TA to man.mac.
+
+	*  Numerous prototypes added.
+
+
+CONTENTS
+--------
+
+This Minix distribution of cawf includes:
+
+	README		    this file
+	*.c and *.h	    source files to build cawf and bsfilt (bsfilt
+			    removes Backspaces from cawf output)
+	bsfilt.1	    nroff source for the bsfilt manual page
+	cawf.1		    nroff source for the cawf manual page
+	common		    initialization file for CAWFLIB library
+	device.cf	    output device configuration file for CAWFLIB
+			    library
+	dumb.dev	    device description file for CAWFLIB library
+	Makefile	    Unix-style make file
+	man.mac		    man(7) macros for CAWFLIB library
+	me.mac		    me(7) macros for CAWFLIB library
+	ms.mac		    ms(7) macros for CAWFLIB library
+	diffs		    Minix patches
+#ifdef PUTTING_IT_ON_THE_NET
+	cawf
+	bsfilt		    binaries compiled under Minix-PC 1.5 using the ACK
+			    ANSI C compiler using software floating point
+#endif
+
+
+LIBRARY
+-------
+
+To use cawf, you must select a location for the CAWFLIB library files.  The
+distributed cawf binary expects to find them in /usr/local/lib/cawf but you
+can alter that with the CAWFLIB environment variable, or you can change the
+CAWFLIB #define in cawf.h and rebuild cawf from the sources.
+
+CAWFLIB contains a minimum of six files:
+
+	common		common raw nroff commands to get cawf started
+	dumb.dev	a set of character definitions for a plain, "dumb"
+			ASCII device - e. g., the console display, a CRT or
+			a basic line printer
+	device.cf	the output device configuration file
+	man.mac		the man(7) macros
+	me.mac		the me(7) macros
+	ms.mac		the ms(7) macros
+
+You may want to add your own macro files to the library.  Just name them
+"m[your-name].mac", following the usual nroff naming convention for macro
+files.
+
+If you have fancy output devices with special character specifications, you
+may want to generate new *.dev files for them.  Follow the format of dumb.dev
+in making new character specifications.  To define characters for a new
+device, select a name prefix for it and create a file in CAWFLIB with the
+name "<prefix>.dev".  To use the new file, set the TERM environment variable
+to <prefix> - e. g., when I test cawf on Unix, I need a vt100.dev, because
+my TERM environment variable value is usually vt100.  All I do is make
+vt100.dev a symbolic link to dumb.dev.  Even that isn't even necessary,
+because cawf will use dumb.dev if it can't find TERM.dev.
+
+In addition to the character specifications possible through the *.dev files,
+cawf provides one-time font selection and bold or italic face support for
+output devices via its -d and -f options.  Cawf can be directed to issue
+specific device codes for bold and italic characters, and one font can be
+specified for the entire document.  Cawf has some built-in output device
+support, and addition support is contained in the device configuration file,
+device.cf.  Additional devices may be defined in device.cf.
+
+It is not necessary to generate a new *.dev file for each output device
+definition.  Only when you need special character definitions do you need to
+create a *.dev file.  The dumb.dev file is adequate for most devices you 
+define in device.cf.
+
+
+SOURCES
+-------
+
+The Unix make file has some definitions that help tune it to the local
+Unix environment:
+
+	CAWFLIB		is a string that can be used in lieu of changes
+			to cawf.h's CWFLIB #define.
+
+	MALLOCH		is a string that should be defined when a UNIX
+			environment has a <malloc.h>, unless it also has a
+			<stdlib.h> with protoypes for malloc() and its
+			relatives.  In the latter case, you should define
+			STDLIB, but you don't need to define MALLOCH.
+
+	STDLIB		indicates that standard library function prototype
+			definitions may be found in <stdlib.h>.
+
+			STDLIB must be defined for MS-DOS Quick C.
+
+			If STDLIB is not defined, the cawf sources try to
+			define their own library function return values.
+
+	__STR__		The definition of this string must be deleted when
+			using the xlc 1.2 compiler on the RISC/System 6000
+			under AIX 3.2.  Put
+
+				-U__STR__
+
+			in the Makefile DEFS string.  This must be done
+			because the xlc 1.2 compiler does not correctly inline
+			string functions when compiling pass3.c.
+
+	UNIX		switches the build environment to Unix.  You may also
+			have to decide about MALLOCH, STDLIB, __STR__ and USG
+			when you define UNIX.
+
+			Do not define UNIX for MS-DOS Quick-C; do define
+			STDLIB.
+
+	USG		adjusts for System V.  (UNIX must also be defined.)
+
+			You may also need to define USG to select the proper
+			header file for string function prototypes.  If UNIX
+			and USG are defined, "proto.h" selects <string.h>;
+			if only UNIX, <strings.h>.  Cawf needs the more
+			complete set of definitions, including strchr() and
+			strrchr().  If <string.h> #includes <strings.h>, as
+			is sometimes the case, define only UNIX.
+
+I have built and tested cawf in the UNIX context under AIX 3.2 (see the
+note above on __STR__), BSD4.3-Tahoe, Sequent DYNIX, ETAV (SYSV 3.0),
+NeXTStep 3.0, SunOS 4.1.1 and Ultrix 2.2.  If you build under another Unix
+variant, you may have to adjust the source code, header files and Makefile
+to fit.  Check the Makefile first for hints.
+
+
+ANSI C COMPLIANCE
+-----------------
+
+Some effort has been devoted to making the cawf sources ANSI C compliant.
+The header file proto.h contains function prototypes that enable ANSI C
+argument checking.  The state of definition of the __STDC__ symbol is used
+to select options that depend on strict adherence to the ANSI C standard --
+e.g., the need for the isascii() test before islower() or isupper().  If
+your ANSI compiler doesn't define this variable when it's acting in strict
+ANSI C mode, you may have to define it in the Makefile.
+
+
+MS-DOS CONSIDERATIONS
+---------------------
+
+The MS-DOS version of cawf was created to run under the KornShell of the
+Mortis Kern Systems Toolkit.  One ramification of using MKS' ksh is that it
+supports the separate standard error and standard output streams.  Hence,
+cawf blithely distributes its error messages to the standard error file, and
+assumes the user's shell is capable of separating them from standard output.
+
+If you don't use the MKS KornShell, but do want to separate the output
+streams, you'll have to modify the cawf source code.  As a rudimentary aid,
+cawf uses a separate stream pointer, Efs, for writing error output, but sets
+it to stderr.  You can change that process to open a separate error file and
+set Efs to point to it.
+
+
+COPYRIGHTS AND CREDITS
+----------------------
+
+The sources are copyrighted, but freely distributable under usual terms -
+retention of credit, etc.
+
+Please acknowledge:
+
+	AT&T for their public-domain release of getopt(3) at the 1985
+	UNIFORUM conference;
+
+	Chet Creider, Bob Hardy and Ted Campbell for their contributions
+	to font filtering;
+
+	Henry Spencer for awf and his regular expression package;
+
+	Andy Tanenbaum for his help in ANSI C compliance, including his
+	ansi.h header file from Minix.
+
+Henry says about awf, "I can't believe I really wrote this."  Those are
+my sentiments exactly about cawf, but I also understand that necessity
+sometimes forces us to do what we would prefer to avoid.
+
+
+BUGS AND ENHANCEMENTS
+---------------------
+
+I'll be glad to hear about bugs and needs for enhancements, but make no
+promises about delivering fixes or upgrades in response.
+
+Vic Abell <abe@cc.purdue.edu>
+24 November 1992
+
+
+MINIX SPECIFIC TINKERING
+------------------------
+
+Kees J. Bot <kjb@cs.vu.nl>
+26 November 1992
Index: /trunk/minix/commands/cawf/ansi.h
===================================================================
--- /trunk/minix/commands/cawf/ansi.h	(revision 9)
+++ /trunk/minix/commands/cawf/ansi.h	(revision 9)
@@ -0,0 +1,56 @@
+/* The <ansi.h> header attempts to decide whether the compiler has enough
+ * conformance to Standard C for Minix to take advantage of.  If so, the
+ * symbol _ANSI is defined (as 31415).  Otherwise _ANSI is not defined
+ * here, but it may be defined by applications that want to bend the rules.
+ * The magic number in the definition is to inhibit unnecessary bending
+ * of the rules.  (For consistency with the new '#ifdef _ANSI" tests in
+ * the headers, _ANSI should really be defined as nothing, but that would
+ * break many library routines that use "#if _ANSI".)
+
+ * If _ANSI ends up being defined, a macro
+ *
+ *	_PROTOTYPE(function, params)
+ *
+ * is defined.  This macro expands in different ways, generating either
+ * ANSI Standard C prototypes or old-style K&R (Kernighan & Ritchie)
+ * prototypes, as needed.  Finally, some programs use _CONST, _VOIDSTAR etc
+ * in such a way that they are portable over both ANSI and K&R compilers.
+ * The appropriate macros are defined here.
+ */
+
+#ifndef _ANSI_H
+#define _ANSI_H
+
+#if __STDC__ == 1
+#define _ANSI		31459	/* compiler claims full ANSI conformance */
+#endif
+
+#ifdef __GNUC__
+#define _ANSI		31459	/* gcc conforms enough even in non-ANSI mode */
+#endif
+
+#ifdef _ANSI
+
+/* Keep everything for ANSI prototypes. */
+#define	_PROTOTYPE(function, params)	function params
+
+#define	_VOIDSTAR	void *
+#define	_VOID		void
+#define	_CONST		const
+#define	_VOLATILE	volatile
+#define _SIZET		size_t
+
+#else
+
+/* Throw away the parameters for K&R prototypes. */
+#define	_PROTOTYPE(function, params)	function()
+
+#define	_VOIDSTAR	void *
+#define	_VOID		void
+#define	_CONST
+#define	_VOLATILE
+#define _SIZET		int
+
+#endif /* _ANSI */
+
+#endif /* ANSI_H */
Index: /trunk/minix/commands/cawf/bsfilt.c
===================================================================
--- /trunk/minix/commands/cawf/bsfilt.c	(revision 9)
+++ /trunk/minix/commands/cawf/bsfilt.c	(revision 9)
@@ -0,0 +1,211 @@
+/*
+ *	bsfilt.c - a colcrt-like processor for cawf(1)
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+#include <stdio.h>
+
+#ifdef UNIX
+# ifdef USG
+#include <string.h>
+# else	/* not USG */
+#include <strings.h>
+# endif	/* USG */
+#else	/* not UNIX */
+#include <string.h>
+#endif	/* UNIX */
+
+#include <sys/types.h>
+
+#include "ansi.h"
+
+#define MAXLL	2048			/* ridiculous maximum line length */
+
+int Dash = 1;				/* underline with dashes */
+int Dp = 0;				/* dash pending */
+int Lc = 0;				/* line count */
+char *Pname;				/* program name */
+unsigned char Ulb[MAXLL];		/* underline buffer */
+int Ulx = 0;				/* underline buffer index */
+
+_PROTOTYPE(void Putchar,(int ch));
+
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	int ax = 1;			/* argument index */
+	unsigned char c;		/* character buffer */
+	FILE *fs;			/* file stream */
+	int nf = 0;			/* number of files processed */
+	unsigned char pc;		/* previous character */
+	int under = 0;                  /* underline */
+/*
+ * Save program name.
+ */
+	if ((Pname = strrchr(argv[0], '/')) != NULL)
+		Pname++;
+	else if ((Pname = strrchr(argv[0], '\\')) != NULL)
+		Pname++;
+	else
+		Pname = argv[0];
+/*
+ * Process options.
+ */
+	if (argc > 1 && argv[1][0] == '-') {
+		switch (argv[1][1]) {
+	/*
+	 * "-U" - underline with dashes.
+	 */
+		case 'U':
+			Dash = 0;
+			under = 1;
+			break;
+	/*
+	 * "-" - do no  underlining at all.
+	 */
+		case '\0':
+			Dash = under = 0;
+			break;
+		default:
+			(void) fprintf(stderr,
+				"%s usage: [-] [-U] [file]\n", Pname);
+			exit(1);
+		}
+		ax++;
+	}
+/*
+ * Process files.  Read standard input if no files names.
+ */
+
+	while (ax < argc || nf == 0) {
+		if (ax >= argc)
+			fs = stdin;
+		else {
+#ifdef	UNIX
+			if ((fs = fopen(argv[ax], "r")) == NULL)
+#else
+			if ((fs = fopen(argv[ax], "rt")) == NULL)
+#endif
+			{
+				(void) fprintf(stderr, "%s: can't open %s\n",
+					Pname, argv[ax]);
+				exit(1);
+			}
+			ax++;
+		}
+		nf++;
+	/*
+	 * Read input a character at a time.
+	 */
+		for (pc = '\0';;) {
+			c = (unsigned char)fgetc(fs);
+			if (feof(fs))
+				break;
+			switch(c) {
+
+			case '\n':
+				if (pc)
+					Putchar((int)pc);
+				Putchar('\n');
+				pc = '\0';
+				break;
+
+			case '\b':
+				if (pc == '_') {
+					if (under) {
+						putchar(pc);
+						putchar('\b');
+					} else if (Dash)
+						Dp = 1;
+				}
+				pc = '\0';
+				break;
+
+			default:
+				if (pc)
+					Putchar((int)pc);
+				pc = c;
+			}
+		}
+		if (pc) {
+			Putchar((int)pc);
+			Putchar((int)'\n');
+		}
+	}
+	exit(0);
+}
+
+
+/*
+ * Putchar(ch) - put a character with possible underlining
+ */
+
+void
+Putchar(ch)
+	int ch;
+{
+	int i;					/* temporary index */
+
+	if ((unsigned char)ch == '\n') {
+/*
+ * Handle end of line.
+ */
+		putchar('\n');
+		if (Ulx) {
+			while (Ulx && Ulb[Ulx-1] == ' ')
+				Ulx--;
+			if (Ulx) {
+				for (i = 0; i < Ulx; i++)
+					putchar(Ulb[i]);
+				putchar('\n');
+			}
+		}
+		Dp = Ulx = 0;
+		Lc++;
+		return;
+	}
+/*
+ * Put "normal" character.
+ */
+	putchar((unsigned char)ch);
+	if (Dash) {
+
+	/*
+	 * Handle dash-type underlining.
+	 */
+		if (Ulx >= MAXLL) {
+			(void) fprintf(stderr,
+				"%s: underline for line %d > %d characters\n",
+				Pname, Lc, MAXLL);
+			exit(1);
+		}
+		Ulb[Ulx++] = Dp ? '-' : ' ';
+		Dp = 0;
+	}
+}
Index: /trunk/minix/commands/cawf/build
===================================================================
--- /trunk/minix/commands/cawf/build	(revision 9)
+++ /trunk/minix/commands/cawf/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/cawf/cawf.c
===================================================================
--- /trunk/minix/commands/cawf/cawf.c	(revision 9)
+++ /trunk/minix/commands/cawf/cawf.c	(revision 9)
@@ -0,0 +1,488 @@
+/*
+ *	cawf - a C version of Henry Spencer's awf(1), the Amazingly
+ *	       Workable (text) Formatter
+ *
+ *	V. Abell, Purdue University Computing Center
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+static char Version[] = "4.0";
+
+#include "cawf.h"
+
+#include <sys/stat.h>
+#ifndef	UNIX
+#include <io.h>
+#include <process.h>
+#include <string.h>
+#include <sys\types.h>
+#include <sys\stat.h>
+#endif
+
+
+main(argc, argv)
+	int     argc;
+	char    *argv[];
+{
+	char *ep;               	/* environment pointer */
+	int fff = 0;			/* final form feed status */
+	char **files;			/* file names */
+	int help = 0;			/* help status */
+	int i;	               		/* temporary index */
+	size_t l;                       /* length */
+	char *lib = CAWFLIB;		/* library path */
+	int libl;			/* library path length */
+	int mac = 0;			/* macro specification status */
+	int nf = 0;             	/* number of files */
+	char *np;               	/* name pointer */
+	int pc;                 	/* prolog count */
+	struct stat sbuf;               /* stat buffer */
+/*
+ * Save program name.
+ */
+	if ((Pname = strrchr(argv[0], '\\')) != NULL)
+		Pname++;
+	else if ((Pname = strrchr(argv[0], '/')) != NULL)
+		Pname++;
+	else
+		Pname = argv[0];
+/*
+ * Set error file stream pointer.
+ */
+	Efs = stderr;
+/*
+ * Get library name.
+ */
+	if ((np = getenv("CAWFLIB")) != NULL)
+		lib = np;
+	libl = strlen(lib);
+/*
+ * Get device file name.
+ */
+	for (ep = getenv("TERM");; ep = NULL) {
+		if (ep == NULL || *ep == '\0')
+			ep = "dumb";
+		l = libl + 1 + strlen(ep) + strlen(".dev") + 1;
+		if ((np = malloc(l)) == NULL)
+			Error(FATAL, NOLINE,
+				" no string space for device file: ", ep);
+		(void) sprintf(np, "%s/%s.dev", lib, ep);
+		if (stat(np, &sbuf) == 0)
+			break;
+		if (strcmp(ep, "dumb") == 0)
+			Error(FATAL, NOLINE, " no dumb.dev file in ", lib);
+		(void) free(np);
+	}
+	if ((files = malloc((argc + 2) * sizeof(files[0]))) == NULL)
+		Error(FATAL, NOLINE, " no space for file list",
+			NULL);
+	files[nf++] = np;
+/*
+ * Get common text file name.
+ */
+	l = libl + 1 + strlen("common") + 1;
+	if ((np = malloc(l)) == NULL)
+		Error(FATAL, NOLINE, " no string space for common file name",
+			NULL);
+	(void) sprintf(np, "%s/common", lib);
+	files[nf++] = np;
+/*
+ * Process options.
+ */
+	while ((i = getopt(argc, argv, "c:d:ef:hm:")) != EOF) {
+		switch (i) {
+	/*
+	 * -c<device_configuration_file_path>>
+	 */
+		case 'c':
+			Devconf = optarg;
+			break;
+	/*
+	 * -d<output_device_name> -- define output device name
+	 *
+	 * The default output device name is NORMAL -- i.e., a device that
+	 * does bold face with backspace and overprinting and italic face with
+	 * underscore.  NORMAL is usually a terminal device.
+	 *
+	 * There is a built-in device, named ANSI, that does bold face with
+	 * the ANSI shadow mode and italic face with the ANSI underscore mode.
+	 * ANSI is normally a terminal device that supports the ANSI shadow
+	 * and underscore modes.
+	 *
+	 * There is a built-in output device, named NONE, that does nothing
+	 * at all for the bold or italic faces.  This is usually a terminal
+	 * device.
+	 *
+	 * All other device names must match a stanza in the device
+	 * configuration file.
+	 */
+		case 'd':
+			Device = optarg;
+			break;
+	/*
+	 * -e -- eject: issue final form feed
+	 */
+		case 'e':
+			fff = 1;
+			break;
+	/*
+	 * -f<output_device_font_name> -- define font name for the output
+	 *				  device (from device configuration
+	 *				  file)
+	 */
+		case 'f':
+			Devfont = optarg;
+			break;
+	/*
+	 * -h -- display help (usage)
+	 */
+		case 'h':
+			help = 1;
+			break;
+	/*
+	 * -m<macro_file_name>
+	 *
+	 *  Special support is provided for -man, -me and -ms.
+	 */
+		case 'm':
+			if (mac) {
+				Error(WARN, NOLINE,
+					"multiple macro file declaration",
+					NULL);
+				break;
+			}
+			l = libl + 2 + strlen(optarg) + strlen(".mac") + 1;
+			if ((np = malloc(l)) == NULL)
+				Error(FATAL, NOLINE, " no string space for ",
+					argv[1]);
+			(void) sprintf(np, "%s/m%s.mac", lib, optarg);
+			files[nf++] = np;
+			if (strcmp(optarg, "an") == 0)
+				Marg = MANMACROS;
+			else if (strcmp(optarg, "s") == 0
+			     ||  strcmp(optarg, "e") == 0)
+				Marg = MSMACROS;
+			mac++;
+			break;
+	/*
+	 * Option not recognized by getopt().
+	 */
+		case '?':
+			Err = 1;
+		}
+	}
+	if (Defdev())
+		Err++;
+	if (help || Err) {
+	  (void) fprintf(stderr,
+	    "%s %s usage: [-c<c>] [-d<d>] [-e] [-f<f>] [-h] [-m<m>] file...\n",
+		Pname, Version);
+	  (void) fprintf(stderr,
+	    "\t-c<c>     <c> is the device configuration file path\n");
+	  (void) fprintf(stderr,
+	    "\t-d<d>     <d> is the output device name\n");
+	  (void) fprintf(stderr,
+	    "\t          (default = NORMAL, using \\b for bold and italic)\n");
+	  (void) fprintf(stderr,
+	    "\t          (built-ins = ANSI, NONE and NORMAL)\n");
+	  (void) fprintf(stderr,
+	    "\t-e        issue eject after last page\n");
+	  (void) fprintf(stderr,
+	    "\t-f<f>     <f> is the output device font name\n");
+	  (void) fprintf(stderr,
+	    "\t-h        display help (this output)\n");
+	  (void) fprintf(stderr,
+	    "\t-m<m>     m<m> is the macro file name\n");
+	  (void) fprintf(stderr,
+	    "\tfile ...  source file names\n");
+	  exit(Err);
+	}
+	if (mac == 0) {
+
+	    /*
+	     * No macroes - enable Bold, Italic, Roman and Courier fonts.
+	     */
+		for (i = 0; Fcode[i].nm; i++) {
+			switch (Fcode[i].nm) {
+			case 'B':
+			case 'I':
+			case 'R':
+			case 'C':
+				Fcode[i].status = '1';
+			}
+		}
+	}
+/*
+ * Add user-supplied file names.
+ */
+	pc = nf;
+	if (optind >= argc) {
+		files[nf++] = NULL;       /* STDIN */
+	} else {
+		while (optind < argc)
+			files[nf++] = argv[optind++];
+	}
+/*
+ * Make sure all input files are accessible.
+ */
+	for (i = 0; i < nf; i++) {
+		if (files[i] != NULL) {
+			if (stat(files[i], &sbuf) != 0)
+				Error(WARN, NOLINE, " can't find ", files[i]);
+		}
+	}
+	if (Err)
+		exit(1);
+/*
+ * Miscellaneous initialization.
+ */
+
+	for (i = 0; ; i++) {
+		if (Pat[i].re == NULL)
+			break;
+		if ((Pat[i].pat = regcomp(Pat[i].re)) == NULL)
+			Error(WARN, NOLINE, Pat[i].re, " regcomp failure");
+	}
+	if ((i = Findscale((int)'n', 0.0, 0)) < 0)
+		Error(WARN, NOLINE, " can't find Scale['n']", NULL);
+	Scalen = Scale[i].val;
+	if ((i = Findscale((int)'u', 0.0, 0)) < 0)
+		Error(WARN, NOLINE, " can't find Scale['u']", NULL);
+	Scaleu = Scale[i].val;
+	if ((i = Findscale((int)'v', 0.0, 0)) < 0)
+		Error(WARN, NOLINE, " can't find Scale['v']", NULL);
+	Scalev = Scale[i].val;
+	(void) Findstr((unsigned char *)"CH", (unsigned char *)"= % -", 1);
+	Cont = Newstr((unsigned char *)" ");
+	Contlen = 1;
+	if ((Trtbl = (unsigned char *)malloc(256)) == NULL)
+		Error(WARN, NOLINE, " can't allocate translate table space",
+			NULL);
+	else {
+		*Trtbl = ' ';
+		for (i = 1; i < 256; i++)
+			Trtbl[i] = (unsigned char) i;
+	}
+	if (Err)
+		exit(1);
+/*
+ * Here begins pass1 of awf - reading input lines and expanding macros.
+ */
+
+/*
+ * Output prolog.
+ */
+	if (Fstr.i) {
+		for (i = 0; i < Fstr.il; i++) {
+			Charput((int)Fstr.i[i]);
+		}
+	}
+	Macro((unsigned char *)".^x");
+	Macro((unsigned char *)".^b");
+	Macro((unsigned char *)".^# 1 <prolog>");
+/*
+ * Read input files.
+ */
+	for (i = 0; i < nf; i++) {
+		Dowarn = (i >= pc);
+		if (files[i] == NULL) {
+			np = "stdin";
+			Ifs = stdin;
+		} else {
+#ifdef	UNIX
+			if ((Ifs = fopen(files[i], "r")) == NULL)
+#else
+			if ((Ifs = fopen(files[i], "rt")) == NULL)
+#endif
+				Error(FATAL, NOLINE, " can't open ", files[i]);
+			np = files[i];
+		}
+		if (i >= pc) {
+			(void) sprintf((char *)Line, ".^# 1 %s", np);
+			Macro(Line);
+			NR = 0;
+		}
+		Fsp = 0;
+		do {
+			while (fgets((char *)Line, MAXLINE, Ifs) != NULL) {
+				NR++;
+				if ((np = strrchr((char *)Line, '\n')) != NULL)
+					*np = '\0';
+				else
+					Line[MAXLINE-1] = '\0';
+				Macro(Line);
+			}
+			if (i >= pc)
+				Macro((unsigned char *)".^e");
+			if (Ifs != stdin)
+				(void) fclose(Ifs);
+			if (Fsp > 0) {
+				Free(&Inname);
+				Inname = Inn_stk[Fsp-1];
+				NR = NR_stk[Fsp-1];
+				Ifs = Ifs_stk[Fsp-1];
+			}
+		} while (Fsp-- > 0);
+	}
+	Macro(NULL);
+	if (fff)
+		Charput((int)'\f');
+	exit(Err);
+}
+
+
+/*
+ * Macro(inp) - process a possible macro statement
+ *		pass non-macros and macros alike to pass 2
+ */
+
+void
+Macro(inp)
+	unsigned char *inp;		/* possible macro statement pointer */
+{
+	unsigned char c[2];		/* characters */
+	int endm;			/* end of macro status */
+	FILE *fs;			/* temporary file stream */
+	int i, j, k;                    /* temporary indexes */
+	int mx;                         /* Macrotab[] index */
+	int req;			/* request character status */
+	unsigned char *s1, *s2;		/* temporary string pointers */
+
+	if (inp == NULL) {
+		Pass2(NULL);
+		return;
+	}
+	req = (*inp == '.' || *inp == '\'') ? 1 : 0;
+/*
+ * Check for file name designator.
+ */
+	if (req && inp[1] == '^' && inp[2] == '#') {
+		Free(&Inname);
+		Inname = Field(3, inp, 1);
+		F = NULL;
+		Pass2(inp);
+		return;
+	}
+/*
+ * Check for source command - "^[.']so".
+ */
+	if (req && inp[1] == 's' && inp[2] == 'o') {
+		if ((s1 = Field(2, inp, 1)) == NULL) {
+			Error(WARN, LINE, " no file specified", NULL);
+			return;
+		}
+		if ((fs = fopen((char *)s1, "r")) == NULL) {
+			Error(WARN, LINE, " can't open", NULL);
+			return;
+		}
+		if (Fsp >= MAXFSTK) {
+			(void) fclose(fs);
+			Error(WARN, LINE, " nesting too deep", NULL);
+			return;
+		}
+		Ifs_stk[Fsp] = Ifs;
+		Ifs = fs;
+		Inn_stk[Fsp] = Inname;
+		Inname = F;
+		F = NULL;
+		NR_stk[Fsp++] = NR;
+		NR = 0;
+		return;
+	}
+ /*
+  * Check for ignore.
+  */
+	if (req && inp[1] == 'i' && inp[2] == 'g') {
+		while (fgets((char *)inp, MAXLINE, Ifs) != NULL) {
+			NR++;
+			if (inp[0] == '.' && inp[1] == '.') break;
+		}
+		return;
+	}
+ /*
+  * Check for start of macro definition.
+  */
+	if (req && inp[1] == 'd' && inp[2] == 'e') {
+		if (inp[3] != ' ' || inp[4] == '\0') {
+			Error(WARN, LINE, " illegal macro definition", NULL);
+			return;
+		}
+		c[0] = inp[4];
+		c[1] = inp[5];
+		Curmx = Findmacro(c, 1);
+		return;
+	}
+/*
+ * Check for macro text.  Remove double backslashes.
+ */
+	if (req && (inp[1] == '\0' || (inp[2] == '\0' && inp[0] == inp[1])))
+		endm = 1;
+	else
+		endm = 0;
+	if (Curmx >= 0 && !endm) {
+		if (Mtx >= MAXMTXT)
+			Error(FATAL, LINE, " out of macro text space", NULL);
+		if ((s1 = (unsigned char *)strchr((char *)inp, '\\')) == NULL)
+			Macrotxt[Mtx] = Newstr(inp);
+		else {
+			for (s1 = Pass1ln, s2 = inp;; s1++) {
+				if ((*s1 = *s2++) == '\0')
+					break;
+				if (*s1 == '\\' && *s2 == '\\')
+					s2++;
+			}
+			Macrotxt[Mtx] = Newstr(Pass1ln);
+		}
+		if (Macrotab[Curmx].bx == -1)
+			Macrotab[Curmx].bx = Mtx;
+		Mtx++;
+		Macrotab[Curmx].ct++;
+		return;
+	}
+/*
+ * Check for end of macro.
+ */
+	if (Curmx >= 0 && endm) {
+		Curmx = -1;
+		(void) sprintf((char *)Pass1ln, ".^# %d %s", NR, Inname);
+		Pass2(Pass1ln);
+		return;
+	}
+ /*
+  * Check for conditionals and macro expansions.
+  */
+	if (req
+	&&  (((mx = Findmacro(inp+1, 0)) != -1) || regexec(Pat[0].pat, inp))) {
+		Expand(inp);
+		return;
+	}
+/*
+ * None of the above: forward the line.
+ */
+	Pass2(inp);
+}
Index: /trunk/minix/commands/cawf/cawf.h
===================================================================
--- /trunk/minix/commands/cawf/cawf.h	(revision 9)
+++ /trunk/minix/commands/cawf/cawf.h	(revision 9)
@@ -0,0 +1,265 @@
+/*
+ *	cawf.h - definitions for cawf(1)
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+#include <stdio.h>
+#ifdef	UNIX
+#include <sys/types.h>
+#else
+#include <sys\types.h>
+#endif
+#include "regexp.h"
+#include "cawflib.h"
+#include "proto.h"
+
+#define	DEVCONFIG	"device.cf"		/* device configuration file */
+#define ESC		'\033'			/* ESCape character */
+#define MAXEXP          30                      /* maximum expressions
+						 * (and TABs) */
+#define MAXFSTK		5			/* maximum file stack
+						 * (for .so) */
+#define MAXHYCH		10			/* maximum hyphen characters */
+#define MAXLINE         512			/* maximum line length */
+#define MAXMACRO        100			/* maximum number of macros */
+#define MAXMTXT         1024			/* maximum macro text lines */
+#define MAXNHNR		10			/* maximum ".NH" numbers
+						 * (but 0 not used) */
+#define MAXNR		50			/* maximum number reg */
+#define MAXOLL		512			/* maximum output line length */
+#define	MAXSCH		256			/* maximum special characters */
+#define MAXSP		25			/* maximum stack pointer (for
+						 * nesting of macro calls) */
+#define MAXSTR		100			/* maximum ".ds" strings */
+
+/*
+ * Output line adjustment modes
+ */
+
+#define LEFTADJ		0
+#define RIGHTADJ	1
+#define BOTHADJ		2
+
+/*
+ * Error handling codes
+ */
+
+#define	FATAL		0			/* fatal error */
+#define	LINE		0			/* display line */
+#define	NOLINE		1			/* don't display line */
+#define WARN		1			/* warning error */
+
+/*
+ * Padding directions
+ */
+
+#define	PADLEFT		0			/* pad from left */
+#define PADRIGHT	1			/* pad from right */
+
+/*
+ * Pass 3 signal codes
+ */
+
+#define NOBREAK		-1
+#define DOBREAK		-2
+#define MESSAGE		-3
+
+/*
+ * Macro argument types
+ */
+
+#define	MANMACROS	1			/* -man */
+#define MSMACROS	2			/* -ms */
+
+
+struct fcode {
+	unsigned char nm;		/* font name character */
+	unsigned char status;		/* status */
+};
+
+struct fontstr {			/* font control strings */
+
+	unsigned char *i;		/* font initialization string */
+	int il;				/* length of *i */ 
+	unsigned char *b;		/* bold */
+	int bl;				/* length of *bb */
+	unsigned char *it;		/* italic */
+	int itl;			/* length of *itb */
+	unsigned char *r;		/* roman string */
+	int rl;				/* length of *r */
+}; 
+
+struct hytab {
+	unsigned char font;		/* font name character */
+	int len;			/* effective length */
+	unsigned char *str;		/* value string */
+};
+
+struct macro {
+        unsigned char name[2];		/* macro name */
+        int bx;				/* beginning Macrotxt[] index */
+	int ct;				/* index count */
+};
+
+struct nbr {
+	unsigned char nm[2];		/* register name */
+	int val;			/* value */
+};
+
+struct parms {
+	char nm[2];			/* parameter name */
+	char *cmd;			/* pass 3 command */
+	int val;                        /* current value */
+	int prev;                       /* previous value */
+};
+
+struct rx {
+	char *re;			/* regular expression */
+	struct regexp *pat;		/* compiled pattern */
+};
+
+struct scale {
+	unsigned char nm;		/* scale factor name */
+	double val;			/* value */
+};
+
+struct schtab {
+	unsigned char nm[2];		/* character name */
+	int len;			/* effective length */
+	unsigned char *str;		/* value string */
+};
+
+struct str {
+	unsigned char nm[2];		/* string name */
+	unsigned char *str;		/* string value */
+};
+
+extern int Adj;				/* output line adjustment mode */
+extern unsigned char *Aftnxt;		/* action after next line */
+extern unsigned char *Args[];		/* macro arguments */
+extern unsigned char *Argstack[];	/* stack for Expand()'s "args[]" */
+extern int Backc;                       /* last word ended with '\\c' */
+extern int Botmarg;			/* bottom margin */
+extern int Centering;                   /* centering count */
+extern int Condstack[];                 /* stack for Expand()'s "cond" */
+extern unsigned char *Cont;		/* continue line append */
+extern int Contlen;			/* continue line append length */
+extern int Curmx;                 	/* current macro name */
+extern char *Device;			/* output device name */
+extern char *Devconf;			/* device configuration file path */
+extern char *Devfont;			/* output device font */
+extern int Divert;			/* diversion status */
+extern FILE *Efs;			/* error file stream pointer */
+extern unsigned char *Eol;		/* end of line information */
+extern int Eollen;			/* end of line length */
+extern int Err;                         /* error flag */
+extern unsigned char *F;		/* field value */
+extern struct fcode Fcode[];		/* font codes */
+extern int Fill;			/* fill status */
+extern unsigned char Font[];		/* current font */
+extern int Fontctl;			/* output font control */
+extern char Fontstat;			/* output font status */
+extern int Fph;				/* first page header status */
+extern int Fsp;                         /* files stack pointer (for .so) */
+extern struct fontstr Fstr;		/* font control strings */
+extern unsigned char *Ftc;		/* center footer */
+extern unsigned char *Ftl;		/* left footer */
+extern unsigned char *Ftr;		/* right footer */
+extern unsigned char *Hdc;		/* center header */
+extern int Hdft;			/* header/footer status */
+extern unsigned char *Hdl;		/* left header */
+extern unsigned char *Hdr;		/* right header */
+extern FILE *Ifs;			/* input file stream */
+extern FILE *Ifs_stk[];			/* Ifs stack */
+extern int Ind;                         /* indentation amount */
+extern unsigned char *Inname;		/* input file name */
+extern unsigned char *Inn_stk[];	/* Inname stack */
+extern struct hytab Hychar[];           /* hyphen characters */
+extern int LL;				/* line length */
+extern unsigned char Line[];		/* input line */
+extern int Lockil;			/* pass 2 line number is locked
+					 * (processing is inside macro) */
+extern int Marg;                        /* macro argument - man, ms, etc. */
+extern struct macro Macrotab[];         /* macro table */
+extern int Macrostack[];                /* stack for Expand()'s "macro" */
+extern unsigned char *Macrotxt[];	/* macro text */
+extern int Mtx;                         /* macro text index */
+extern int Mxstack[];                   /* stack for Expand()'s "mx" */
+extern int Nhnr[];			/* ".NH" numbers */
+extern int Nhy;                         /* number of Hychar[] entries */
+extern int Nleftstack[];                /* stack for Expand()'s "nleft" */
+extern int Nmac;                        /* number of macros */
+extern int Nnr;                         /* number of Numb[] entries */
+extern int Nospmode;			/* no space mode */
+extern int Nparms;                      /* number of Parms[] entries */
+extern int NR;                          /* number of record, ala awk */
+extern int NR_stk[];			/* NR stack */
+extern int Nsch;                        /* number of Schar[] entries */
+extern int Nstr;                        /* number of entries in Str[] */
+extern int Ntabs;			/* number of TAB positions */
+extern struct nbr Numb[];		/* number registers */
+extern int Nxtln;			/* next line number */
+extern char *optarg;			/* getopt(3) argument pointer */
+extern int optind;			/* getopt(3) index */
+extern int Outll;			/* output line length */
+extern unsigned char Outln[];		/* output line */
+extern int Outlx;			/* output line index */
+extern int P2il;                        /* pass 2 input line number */
+extern unsigned char *P2name;		/* pass 2 input file name */
+extern int P3fill;			/* pass 3 fill status */
+extern int Padchar[];			/* padding character locations */
+extern int Padfrom;			/* which end to pad from */
+extern int Padx;			/* Padchar[] index */
+extern struct parms Parms[];            /* parameter registers */
+extern unsigned char Pass1ln[];		/* pass 1 output line */
+extern unsigned char Pass2ln[];		/* pass 2 output line */
+extern struct rx Pat[];			/* compiled regexp patterns */
+extern int Pglen;			/* page length */
+extern int Pgoff;			/* page offset */
+extern char *Pname;			/* program name */
+extern unsigned char Prevfont;		/* previous font */
+extern int Ptrstack[];                  /* stack for Expand()'s "ptr" */
+extern struct scale Scale[];		/* scaling factors */
+extern double Scalen;                   /* 'n' scaling factor */
+extern double Scaleu;                   /* 'u' scaling factor */
+extern double Scalev;                   /* 'v' scaling factor */
+extern struct schtab Schar[];           /* special characters */
+extern int Sp;				/* stack pointer */
+extern struct str Str[];		/* ".ds" strings */
+extern int Sx;				/* string index */
+extern int Tabs[];			/* TAB positions */
+extern int Thispg;			/* this page number */
+extern int Tind;			/* temporary indentation amount */
+extern int Topmarg;			/* top margin */
+extern unsigned char *Trtbl;		/* .tr table */
+extern int Uhyph;			/* hyphen usage state */
+extern int Vspace;                      /* vertical (inter-text-line) spacing */
+extern unsigned char Word[];		/* pass 2 word buffer */
+extern int Wordl;                       /* effective length of Word[] */
+extern int Wordx;                       /* Word[] index */
+extern int Dowarn;			/* Enables warnings when true */
Index: /trunk/minix/commands/cawf/cawflib.h
===================================================================
--- /trunk/minix/commands/cawf/cawflib.h	(revision 9)
+++ /trunk/minix/commands/cawf/cawflib.h	(revision 9)
@@ -0,0 +1,39 @@
+/*
+ *	cawflib.h - definition of cawf's library path
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+#ifndef	CAWFLIB
+#ifdef  UNIX
+#define CAWFLIB         "/usr/lib/cawf"		/* UNIX library location */
+#else
+#define CAWFLIB         "c:/sys/lib/cawf"       /* PC-DOS library location */
+#endif
+#endif
+						/* (CAWFLIB environment
+						 * variable over-rides it) */
Index: /trunk/minix/commands/cawf/common
===================================================================
--- /trunk/minix/commands/cawf/common	(revision 9)
+++ /trunk/minix/commands/cawf/common	(revision 9)
@@ -0,0 +1,7 @@
+.\" Common startup code, fully device-independent.
+.\" --------------------------------
+.fi
+.ce 0
+.ta +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8
+.in 0
+.ti 0
Index: /trunk/minix/commands/cawf/device.c
===================================================================
--- /trunk/minix/commands/cawf/device.c	(revision 9)
+++ /trunk/minix/commands/cawf/device.c	(revision 9)
@@ -0,0 +1,415 @@
+/*
+ *	device.c -- cawf(1) output device support functions
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+#include "cawf.h"
+#include <ctype.h>
+
+_PROTOTYPE(static unsigned char *Convstr,(char *s, int *len));
+_PROTOTYPE(static int Convfont,(char *nm, char *s, char **fn,
+	unsigned char **fi));
+
+#ifndef	UNIX
+#define	strcasecmp	strcmpi
+#endif
+
+
+
+/*
+ * Convstr(s, len) - convert a string
+ */
+
+static unsigned char *
+Convstr(s, len)
+	char *s;			/* input string */
+	int *len;			/* length of result */
+{
+	int c;				/* character assembly */
+	unsigned char *cp;		/* temporary character pointer */
+	char *em;			/* error message */
+	int i;				/* temporary index */
+	int l;				/* length */
+	unsigned char *r;		/* result string */
+/*
+ * Make space for the result.
+ */
+	if ((r = (unsigned char *)malloc(strlen((char *)s) + 1)) == NULL) {
+		(void) fprintf(stderr, "%s: out of string space at %s\n",
+			Pname, s);
+		return(NULL);
+	}
+/*
+ * Copy the input string to the result, processing '\\' escapes.
+ */
+	for (cp = r, l = 0; *s;) {
+		switch (*s) {
+
+		case '\\':
+			s++;
+			if (*s >= '0' && *s <= '7') {
+		/*
+		 * '\xxx' -- octal form
+		 */
+				for (c = i = 0; i < 3; i++, s++) {
+					if (*s < '0' || *s > '7') {
+						em = "non-octal char";
+bad_string:
+						(void) fprintf(stderr,
+							"%s: %s : %s\n",
+							Pname, em, (char *)r);
+						return(NULL);
+					}
+					c = (c << 3) + *s - '0';
+				}
+				if (c > 0377) {
+					em = "octal char > 0377";
+					goto bad_string;
+				}
+				*cp++ = c;
+				l++;
+			} else if (*s == 'x') {
+		/*
+		 * '\xyy' -- hexadecimal form
+		 */
+				s++;
+				for (c = i = 0; i < 2; i++, s++) {
+#if	defined(__STDC__)
+					if ( ! isalpha(*s) && ! isdigit(*s))
+#else
+					if ( ! isascii(*s) && ! isalpha(*s)
+					&&   ! isdigit(*s))
+#endif
+					{
+non_hex_char:
+						em = "non-hex char";
+						goto bad_string;
+					}
+					c = c << 4;
+					if (*s >= '0' && *s <= '9')
+						c += *s - '0';
+					else if ((*s >= 'a' && *s <= 'f')
+					     ||  (*s >= 'A' && *s <= 'F'))
+						c += *s + 10 -
+						     (isupper(*s) ? 'A' : 'a');
+					else
+						goto non_hex_char;
+				}
+				*cp++ = (unsigned char)c;
+				l++;
+			} else if (*s == 'E' || *s == 'e') {
+		/*
+		 * '\E' or '\e' -- ESCape
+		 */
+				*cp++ = ESC;
+				l++;
+				s++;
+			} else if (*s == '\0') {
+				em = "no char after \\";
+				goto bad_string;
+			} else {
+		/*
+		 * escaped character (for some reason)
+		 */
+				*cp++ = *s++;
+				l++;
+			}
+			break;
+	/*
+	 * Copy a "normal" character.
+	 */
+		default:
+			*cp++ = *s++;
+			l++;
+		}
+	}
+	*cp = '\0';
+	*len = l;
+	return(r);
+}
+
+
+/*
+ * Convfont(nm, s, fn, fi) - convert a font for a device
+ */
+
+static int
+Convfont(nm, s, fn, fi)
+	char *nm;			/* output device name */
+	char *s;			/* font definition string */
+	char **fn;			/* font name address */
+	unsigned char **fi;		/* initialization string address */
+{
+	char *cp;			/* temporary character pointer */
+	int len;			/* length */
+/*
+ * Get the font name, allocate space for it and allocate space for
+ * a font structure.
+ */
+	if ((cp = strchr(s, '=')) == NULL) {
+		(void) fprintf(stderr, "%s: bad %s font line format: %s\n",
+			Pname, nm, s);
+		return(0);
+	}
+	if ((*fn = (char *)malloc(cp - s + 1)) == NULL) {
+		(void) fprintf(stderr, "%s: no space for %s font name %s\n",
+			Pname, nm, s);
+		return(0);
+	}
+	(void) strncpy(*fn, s, cp - s);
+	(*fn)[cp - s] = '\0';
+/*
+ * Assmble the font initialization string.
+ */
+	if ((*fi = Convstr(cp + 1, &len)) == NULL)
+		return(0);
+	return(len);
+}
+
+
+/*
+ * Defdev() - define the output device
+ */
+
+int
+Defdev()
+{
+	unsigned char *fi = NULL;	/* last font initialization string */
+	char *fn = NULL;		/* font name */
+	int fd = 0;			/* found-device flag */
+	FILE *fs;			/* file stream */
+	int err = 0;			/* errror count */
+	int i;				/* temporary index */
+	int len;			/* length */
+	char line[MAXLINE];		/* line buffer */
+	char *p;			/* output device configuration file */
+	char *s;			/* temporary string pointer */
+/*
+ * Check for the built-in devices, ANSI, NONE or NORMAL (default).
+ */
+	Fstr.b = Fstr.i = Fstr.it = Fstr.r = NULL;
+	Fstr.bl = Fstr.il = Fstr.itl = Fstr.rl = 0;
+	if (Device == NULL || strcasecmp(Device, "normal") == 0) {
+		Fontctl = 0;
+check_font:
+		if (Devfont) {
+			(void) fprintf(stderr,
+				"%s: font %s for device %s illegal\n",
+				Pname, Devfont, Device ? Device : "NORMAL");
+			return(1);
+		}
+		return(0);
+	}
+	Fontctl = 1;
+	if (strcasecmp(Device, "ansi") == 0) {
+		Fstr.b = Newstr((unsigned char *)"x[1m");
+		Fstr.it = Newstr((unsigned char *)"x[4m");
+		Fstr.r = Newstr((unsigned char *)"x[0m");
+		Fstr.b[0] = Fstr.it[0] = Fstr.r[0] = ESC;
+		Fstr.bl = Fstr.itl = Fstr.rl = 4;
+		goto check_font;
+	}
+	if (strcasecmp(Device, "none") == 0)
+		goto check_font;
+/*
+ * If a device configuration file path is supplied, use it.
+ */
+	if (Devconf)
+		p = Devconf;
+	else {
+
+	/*
+	 * Use the CAWFLIB environment if it is defined.
+	 */
+		if ((p = getenv("CAWFLIB")) == NULL)	
+			p = CAWFLIB;
+		len = strlen(p) + 1 + strlen(DEVCONFIG) + 1;
+		if ((s = (char *)malloc(len)) == NULL) {
+			(void) fprintf(stderr, "%s: no space for %s name\n",
+				Pname, DEVCONFIG);
+			return(1);
+		}
+		(void) sprintf(s, "%s/%s", p, DEVCONFIG);
+		p = s;
+	}
+/*
+ * Open the configuration file.
+ */
+#ifdef	UNIX
+	if ((fs = fopen(p, "r")) == NULL)
+#else
+	if ((fs = fopen(p, "rt")) == NULL)
+#endif
+	{
+		(void) fprintf(stderr, "%s: can't open config file: %s\n",
+			Pname, p);
+		return(1);
+	}
+	*line = ' ';
+/*
+ * Look for a device definition line -- a line that begins with a name.
+ */
+	while ( ! feof(fs)) {
+		if (*line == '\t' || *line == '#' || *line == ' ') {
+			(void) fgets(line, MAXLINE, fs);
+			continue;
+		}
+		if ((s = strrchr(line, '\n')) != NULL)
+			*s = '\0';
+		else
+			line[MAXLINE-1] = '\0';
+	/*
+	 * Match device name.
+	 */
+		if (strcmp(Device, line) != 0) {
+			(void) fgets(line, MAXLINE, fs);
+			continue;
+		}
+		fd = 1;
+	/*
+	 * Read the parameter lines for the device.
+	 */
+		while (fgets(line, MAXLINE, fs) != NULL) {
+			if (*line == ' ') {
+				for (i = 1; line[i] == ' '; i++)
+					;
+			} else if (*line == '\t')
+				i = 1;
+			else
+				break;
+#if	defined(__STDC__)
+			if ( ! isalpha(line[i])
+#else
+			if ( ! isascii(line[i]) || ! isalpha(line[i])
+#endif
+			||   line[i+1] != '=')
+				break;
+			if ((s = strrchr(line, '\n')) != NULL)
+				*s = '\0';
+			else
+				line[MAXLINE-1] = '\0';
+			switch (line[i]) {
+		/*
+		 * \tb=<bolding_string>
+		 */
+			case 'b':
+				if (Fstr.b != NULL) {
+				    (void) fprintf(stderr,
+					"%s: dup bold for %s in %s: %s\n",
+					Pname, Device, p, line);
+					(void) free(Fstr.b);
+					Fstr.b = NULL;
+				}
+				if ((Fstr.b = Convstr(&line[i+2], &Fstr.bl))
+				== NULL)
+					err++;
+				break;
+		/*
+		 * \ti=<italicization_string>
+		 */
+			case 'i':
+				if (Fstr.it != NULL) {
+				    (void) fprintf(stderr,
+					"%s: dup italic for %s in %s: %s\n",
+					Pname, Device, p, line);
+					(void) free(Fstr.it);
+					Fstr.it = NULL;
+				}
+				if ((Fstr.it = Convstr(&line[i+2], &Fstr.itl))
+				== NULL)
+					err++;
+				break;
+		/*
+		 * \tr=<return_to_Roman_string>
+		 */
+			case 'r':
+				if (Fstr.r != NULL) {
+				    (void) fprintf(stderr,
+					"%s: dup roman for %s in %s: %s\n",
+					Pname, Device, p, line);
+					(void) free(Fstr.r);
+					Fstr.r = NULL;
+				}
+				if ((Fstr.r = Convstr(&line[i+2], &Fstr.rl))
+				== NULL)
+					err++;
+				break;
+		/*
+		 * \tf=<font_name>=<font_initialization_string>
+		 */
+			case 'f':
+				if ( ! Devfont || Fstr.i)
+					break;
+				if ((i = Convfont(Device, &line[i+2], &fn, &fi))
+				< 0)
+					err++;
+				else if (fn && strcmp(Devfont, fn) == 0) {
+					Fstr.i = fi;
+					Fstr.il = i;
+					fi = NULL;
+				}
+				if (fn) {
+					(void) free(fn);
+					fn = NULL;
+				}
+				if (fi) {
+					(void) free((char *)fi);
+					fi = NULL;
+				}
+				break;
+		/*
+		 * ????
+		 */
+			default:
+				(void) fprintf(stderr,
+					"%s: unknown device %s line: %s\n",
+					Pname, Device, line);
+				err++;
+			}
+		}
+		break;
+	}
+	(void) fclose(fs);
+	if (err)
+		return(1);
+/*
+ * See if the device stanza was located and the font exists.
+ */
+	if ( ! fd) {
+		(void) fprintf(stderr, "%s: can't find device %s in %s\n",
+			Pname, Device, p);
+		return(1);
+	}
+	if (Devfont && ! Fstr.i) {
+		(void) fprintf(stderr,
+			"%s: font %s for device %s not found in %s\n",
+			Pname, Devfont, Device, p);
+		return(1);
+	}
+	return(0);
+}
Index: /trunk/minix/commands/cawf/device.cf
===================================================================
--- /trunk/minix/commands/cawf/device.cf	(revision 9)
+++ /trunk/minix/commands/cawf/device.cf	(revision 9)
@@ -0,0 +1,89 @@
+# cawf(1) device configuration file
+#
+# device
+# \tb=bold_control_sequence
+# \ti=italic_control_sequence
+# \tr=roman_control_sequence
+# \tf=font_name=font_initialization
+#
+# The first font name is the default for the device.
+#
+# sorted in reverse alphabetical order by device name
+
+# VGA monochrome monitors
+#	italic = underline
+
+vgamono
+	b=\033[1m
+	i=\033[4m
+	r=\033[0m
+
+
+# HP LaserJet III
+
+lj3
+	b=\x1b(s7B
+	i=\x1b(s1S
+	r=\x1b(s0B\x1b(s0S
+	f=c10=\x1b&l0O\x1b(8U\x1b(s0p12h10v0s0b3T
+	f=c12ibm=\x1b&l0O\x1b(10U\x1b(s0p10.00h12.0v0s0b3T
+	f=lg12=\x1b&l0O\x1b(8U\x1b(s12h12v0s0b6T
+
+# Panasonic KX-P1180
+#	bold = Emphasized
+#
+#	all fonts are Near Letter Quality (NLQ)
+
+kxp1180
+	b=\033E
+	i=\0334
+	r=\0335\033F
+	f=c10=\033x1\033k0\033P
+	f=bps10=\033x1\033k6\033P
+	f=bps12=\033x1\033k6\033M
+	f=c12=\033x1\033k0\033M
+	f=p10=\033x1\033k3\033P
+	f=p12=\033x1\033k3\033M
+	f=ss10=\033x1\033k1\033P
+	f=ss12=\033x1\033k1\033M
+
+# Panasonic KX-P1124 (from Bob Hardy <hardy@lucid.com>)
+#       bold = Emphasized
+#
+#       all fonts are Near Letter Quality (NLQ)
+#
+#       The s10 and s12 fonts are Script, which is only available on the more
+#       deluxe models of the Panasonic KX-P1100 series -- e.g., Script is not
+#       supported on the KX-P1180, but is supported on the KX-P1124.
+
+kxp1124
+	b=\033E
+	i=\0334
+	r=\0335\033F
+	f=c10=\033x1\033k0\033P
+	f=bps10=\033x1\033k6\033P
+	f=bps12=\033x1\033k6\033M
+	f=c12=\033x1\033k0\033M
+	f=p10=\033x1\033k3\033P
+	f=p12=\033x1\033k3\033M
+	f=s10=\033x1\033k4\033P
+	f=s12=\033x1\033k4\033M
+	f=ss10=\033x1\033k1\033P
+	f=ss12=\033x1\033k1\033M
+
+# IBM Personal Printer Data Stream (PPDS) protocol
+#	bold = Double-strike
+#	italic = Underline
+
+ibmppds
+	b=\033G
+	i=\033-\001
+	r=\033-\000\033H
+
+# Epson FX-86e/FX-800
+#	bold = double strike
+
+epson
+	b=\033G
+	i=\0334
+	r=\0335\033H
Index: /trunk/minix/commands/cawf/diffs
===================================================================
--- /trunk/minix/commands/cawf/diffs	(revision 9)
+++ /trunk/minix/commands/cawf/diffs	(revision 9)
@@ -0,0 +1,211 @@
+diff -c1 ../4.0.2.dist/Makefile ./Makefile
+*** ../4.0.2.dist/Makefile	Thu Nov 26 09:06:28 1992
+--- ./Makefile	Thu Nov 26 09:17:08 1992
+***************
+*** 36,40 ****
+  
+! DEFS = -DUNIX -DSTDLIB -ansi -pedantic
+  
+! CFLAGS = -O ${DEFS}
+  
+--- 36,40 ----
+  
+! DEFS = -DUNIX -DUSG -DSTDLIB
+  
+! CFLAGS = -i -s -f -O ${DEFS}
+  
+diff -c1 ../4.0.2.dist/README ./README
+*** ../4.0.2.dist/README	Thu Nov 26 09:06:28 1992
+--- ./README	Thu Nov 26 09:19:26 1992
+***************
+*** 54,56 ****
+--- 54,68 ----
+  
++ Changes to cawf to run under Minix:
+  
++ 	*  The DOS binaries and make files have been removed.
++  
++ 	*  Tabs stops changed from per 5 to per 8.
++ 
++ 	*  Bold and underline as it should be in device.cf.
++ 
++ 	*  Added .SB and .TA to man.mac.
++ 
++ 	*  Numerous prototypes added.
++ 
++ 
+  CONTENTS
+***************
+*** 58,62 ****
+  
+! This Unix distribution of cawf includes:
+  
+! 	00readme	    this file
+  	*.c and *.h	    source files to build cawf and bsfilt (bsfilt
+--- 70,74 ----
+  
+! This Minix distribution of cawf includes:
+  
+! 	README		    this file
+  	*.c and *.h	    source files to build cawf and bsfilt (bsfilt
+***************
+*** 64,70 ****
+  	bsfilt.1	    nroff source for the bsfilt manual page
+- 	bsfilt.exe.uue	    uuencoded MS-DOS bsfilt executable
+- 	bsfilt.mak	    MS-DOS Quick-C make file for bsfilt
+  	cawf.1		    nroff source for the cawf manual page
+- 	cawf.exe.uue	    uuencoded MS-DOS cawf executable
+- 	cawf.mak	    MS-DOS Quick-C make file for cawf
+  	common		    initialization file for CAWFLIB library
+--- 76,78 ----
+***************
+*** 77,86 ****
+  	ms.mac		    ms(7) macros for CAWFLIB library
+  
+- Hint: to generate an MS-DOS executable, uudecode the *.exe.uue file -- e.g.
+  
+- 	$ uudecode cawf.exe.uue
+- 
+- yields a cawf.exe file.
+- 
+- 
+  LIBRARY
+--- 85,94 ----
+  	ms.mac		    ms(7) macros for CAWFLIB library
++ 	diffs		    Minix patches
++ #ifdef PUTTING_IT_ON_THE_NET
++ 	cawf
++ 	bsfilt		    binaries compiled under Minix-PC 1.5 using the ACK
++ 			    ANSI C compiler using software floating point
++ #endif
+  
+  
+  LIBRARY
+***************
+*** 89,92 ****
+  To use cawf, you must select a location for the CAWFLIB library files.  The
+! distributed cawf.exe expects to find them in c:\sys\lib\cawf, but you can
+! alter that with the CAWFLIB environment variable, or you can change the
+  CAWFLIB #define in cawf.h and rebuild cawf from the sources.
+--- 97,100 ----
+  To use cawf, you must select a location for the CAWFLIB library files.  The
+! distributed cawf binary expects to find them in /usr/local/lib/cawf but you
+! can alter that with the CAWFLIB environment variable, or you can change the
+  CAWFLIB #define in cawf.h and rebuild cawf from the sources.
+***************
+*** 135,139 ****
+  
+! A Unix make file and a cawf.mak file for version 2.5 of Microsoft MS-DOS
+! Quick-C are included.  The Unix make file has some definitions that help
+! tune it to the local Unix environment:
+  
+--- 143,146 ----
+  
+! The Unix make file has some definitions that help tune it to the local
+! Unix environment:
+  
+***************
+*** 251 ****
+--- 258,264 ----
+  
++ 
++ MINIX SPECIFIC TINKERING
++ ------------------------
++ 
++ Kees J. Bot <kjb@cs.vu.nl>
++ 26 November 1992
+diff -c1 ../4.0.2.dist/cawflib.h ./cawflib.h
+*** ../4.0.2.dist/cawflib.h	Thu Nov 26 09:06:35 1992
+--- ./cawflib.h	Thu Nov 26 09:17:10 1992
+***************
+*** 32,34 ****
+  #ifdef  UNIX
+! #define CAWFLIB         "/Homes/abe/lib/cawf"	/* UNIX library location */
+  #else
+--- 32,34 ----
+  #ifdef  UNIX
+! #define CAWFLIB         "/usr/local/lib/cawf"	/* UNIX library location */
+  #else
+diff -c1 ../4.0.2.dist/common ./common
+*** ../4.0.2.dist/common	Thu Nov 26 09:06:36 1992
+--- ./common	Thu Nov 26 09:17:10 1992
+***************
+*** 4,6 ****
+  .ce 0
+! .ta +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5
+  .in 0
+--- 4,6 ----
+  .ce 0
+! .ta +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8
+  .in 0
+diff -c1 ../4.0.2.dist/device.c ./device.c
+*** ../4.0.2.dist/device.c	Thu Nov 26 09:06:36 1992
+--- ./device.c	Thu Nov 26 09:34:09 1992
+***************
+*** 229,231 ****
+  	if (strcasecmp(Device, "ansi") == 0) {
+! 		Fstr.b = Newstr((unsigned char *)"x[7m");
+  		Fstr.it = Newstr((unsigned char *)"x[4m");
+--- 229,231 ----
+  	if (strcasecmp(Device, "ansi") == 0) {
+! 		Fstr.b = Newstr((unsigned char *)"x[1m");
+  		Fstr.it = Newstr((unsigned char *)"x[4m");
+diff -c1 ../4.0.2.dist/device.cf ./device.cf
+*** ../4.0.2.dist/device.cf	Thu Nov 26 09:06:37 1992
+--- ./device.cf	Thu Nov 26 09:21:17 1992
+***************
+*** 13,15 ****
+  # VGA monochrome monitors
+! #	italic = reverse video
+  
+--- 13,15 ----
+  # VGA monochrome monitors
+! #	italic = underline
+  
+***************
+*** 17,19 ****
+  	b=\033[1m
+! 	i=\033[7m
+  	r=\033[0m
+--- 17,19 ----
+  	b=\033[1m
+! 	i=\033[4m
+  	r=\033[0m
+Only in .: diffs
+diff -c1 ../4.0.2.dist/man.mac ./man.mac
+*** ../4.0.2.dist/man.mac	Thu Nov 26 09:06:42 1992
+--- ./man.mac	Thu Nov 26 09:17:12 1992
+***************
+*** 5,7 ****
+  .ds LH "\\$1(\\$2)
+! .ds CH "Unix Programmer's Manual
+  .ds RH "\\$1(\\$2)
+--- 5,7 ----
+  .ds LH "\\$1(\\$2)
+! .ds CH "Minix Programmer's Manual
+  .ds RH "\\$1(\\$2)
+***************
+*** 120,121 ****
+--- 120,128 ----
+  .\"-----------------
++ .de SB
++ .\" Can't reduce size, just do bold
++ .ft B
++ .it 1 fP
++ .if \\n(.$>0 \&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
++ ..
++ .\"-----------------
+  .de IR
+***************
+*** 150,152 ****
+  .de DT
+! .ta +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5
+  ..
+--- 157,163 ----
+  .de DT
+! .ta +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8
+! ..
+! .\"-----------------
+! .de TA
+! .ta \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+  ..
Index: /trunk/minix/commands/cawf/dumb.dev
===================================================================
--- /trunk/minix/commands/cawf/dumb.dev	(revision 9)
+++ /trunk/minix/commands/cawf/dumb.dev	(revision 9)
@@ -0,0 +1,158 @@
+.\" Device-dependent but not macro-set-dependent definitions.
+.\" --------------------------------
+.\" overall formatting initialization
+.\" 12 cpi horizontal exploits 80-column terminal well (6.5i@12 = 78)
+.^r cpi 12 6
+.\" call margin adjustment device-dependent for sake of some unusual cases
+.ad
+.\" page parameters
+.pl 10i
+.ll 6.5i
+.po 0
+.\" --------------------------------
+.\" fonts, and their hyphens, last font change doubled to set up \fP
+.^f R
+.ft R
+.^c hy 1 -
+.^f I
+.ft I
+.^c hy 1 -
+.^f B
+.ft B
+.^c hy 1 -\b-\b-
+.^f C
+.ft C
+.^c hy 1 -\b-\b-
+.ft R
+.ft R
+.\" --------------------------------
+.\" definitions of nroff special characters
+.\" The character definitions here operate on the "better ugly than invisible"
+.\" principle, and try to approximate the character *somehow*.  They were
+.\" tuned for a Teletype 40 line printer, but should give vaguely plausible
+.\" results on any overprinting ASCII device.
+.\"
+.\" first, things that nroff considered builtins
+.^c \ 1 \\
+.^c e 1 \\
+.^c ' 1 '
+.^c ` 1 `
+.^c - 1 -
+.\" some things seem to assume that \+ is like \-
+.^c + 1 +
+.\" we do not do backslash-space here, it can't be done with .^c, but the
+.\" other forms of space we can do
+.^c 0 1 " 
+.^c | 0
+.^c ^ 0
+.^c & 0
+.\"
+.\" and more normal characters
+.\" note, the hyphenation logic knows about em
+.^c em 2 --
+.^c en 1 -
+.\" hy is a special case, see above
+.^c bu 1 +\bo
+.^c sq 2 []
+.^c ru 1 _
+.^c 12 3 1/2
+.^c 14 3 1/4
+.^c 34 3 3/4
+.^c de 1 '\b`
+.^c dg 1 -\b!
+.^c fm 1 '
+.^c ct 1 /\bc
+.^c rg 3 (R)
+.^c co 3 (c)
+.^c pl 1 +
+.^c mi 1 -
+.^c eq 1 =
+.^c ** 1 *
+.^c sc 1 j\bf
+.^c aa 1 '
+.^c ga 1 `
+.^c ul 1 _
+.^c sl 1 /
+.^c *a 1 <\ba
+.^c *b 1 ,\bB
+.^c *g 1 ,\by
+.^c *d 1 S\bo
+.^c *e 1 -\bc
+.^c *z 1 ,\bL
+.^c *y 1 ,\bn
+.^c *h 1 -\b0
+.^c *i 1 ,\bi
+.^c *k 1 <\bK
+.^c *l 1 \\\b>
+.^c *m 1 ,\bu
+.^c *n 1 ,\bv
+.^c *c 1 ,\b3
+.^c *o 1 o
+.^c *p 1 -\bn
+.^c *r 1 p
+.^c *s 1 -\bo
+.^c ts 1 s
+.^c *t 1 ~\bt
+.^c *u 1 u
+.^c *f 1 /\bo
+.^c *x 1 /\b\\
+.^c *q 1 |\bu
+.^c *w 1 u\bw
+.^c *G 2 ~\b|~
+.^c *D 2 _\b/_\b\\
+.^c *H 1 -\bO
+.^c *L 2 /\\
+.^c *C 1 _\b-\b~
+.^c *P 2 ~\b|~\b|
+.^c *S 1 ~\b_\b>
+.^c *U 1 Y
+.^c *F 1 |\bO
+.^c *Q 1 |\bU
+.^c *W 2 _\b(_\b)
+.^c sr 2 \\/
+.^c rn 1 ~
+.^c >= 1 _\b>
+.^c <= 1 _\b<
+.^c == 1 _\b=
+.^c ~= 1 ~\b=
+.^c ap 1 ~
+.^c != 1 /\b=
+.^c -> 2 ->
+.^c <- 2 <-
+.^c ua 1 |\b^
+.^c da 1 |\bv
+.^c mu 1 x
+.^c di 1 -\b:
+.^c +- 1 _\b+
+.^c cu 1 U
+.^c ca 3 (^)
+.^c sb 2 (_\b~
+.^c sp 2 _\b~)
+.^c ib 2 (~\b_\b=
+.^c ip 2 ~\b_\b=)
+.^c if 2 oo
+.^c pd 1 3\bo
+.^c gr 1 ~\bV
+.^c no 1 -
+.^c is 1 '\b,\bI
+.^c pt 2 oc
+.^c es 1 /\bO
+.^c mo 1 -\bC
+.^c br 1 |
+.^c dd 1 I\b|
+.^c rh 1 =\b>
+.^c lh 1 =\b<
+.^c bs 4 (:-)
+.^c or 1 |
+.^c ci 1 O
+.^c lt 1 ~\b(
+.^c lb 1 _\b(
+.^c rt 1 ~\b)
+.^c rb 1 _\b)
+.^c lk 1 -\b(
+.^c rk 1 -\b)
+.^c bv 1 |
+.^c lf 1 _\b[
+.^c rf 1 _\b]
+.^c lc 1 ~\b[
+.^c rc 1 ~\b]
Index: /trunk/minix/commands/cawf/error.c
===================================================================
--- /trunk/minix/commands/cawf/error.c	(revision 9)
+++ /trunk/minix/commands/cawf/error.c	(revision 9)
@@ -0,0 +1,97 @@
+/*
+ *	error.c - error handling functions for cawf(1)
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+#include "cawf.h"
+
+
+/*
+ * Error(t, l, s1, s2) - issue error message
+ */
+
+void
+Error(t, l, s1, s2)
+	int t;				/* type: WARN or FATAL */
+	int l;				/* LINE: display Line[] */
+	char *s1, *s2;			/* optional text */
+{
+	char msg[MAXLINE];		/* message */
+
+	if (t == WARN && !Dowarn) return;
+
+	if (l == LINE)
+		(void) fprintf(Efs, "%s: (%s, %d):%s%s - %s\n",
+			Pname,
+			Inname,
+			NR,
+			(s1 == NULL) ? "" : s1,
+			(s2 == NULL) ? "" : s2,
+			Line);
+	else
+		(void) fprintf(Efs, "%s:%s%s\n",
+			Pname,
+			(s1 == NULL) ? "" : s1,
+			(s2 == NULL) ? "" : s2);
+	if (t == FATAL)
+		exit(1);
+	Err = 1;
+	return;
+}
+
+
+/*
+ * Error3(len, word, sarg, narg) - process error in pass3
+ */
+
+void
+Error3(len, word, sarg, narg, msg)
+	int len;			/* length (negative is special */
+        char *word;			/* word */
+        char *sarg;			/* string argument */
+        int narg;                       /* numeric argument */
+	char *msg;			/* message */
+{
+	if (len == MESSAGE) {
+		(void) fprintf(Efs, "%s: (%s, %d) %s\n",
+			Pname,
+			(word == NULL) ? "<none>" : word,
+			narg,
+			(sarg == NULL) ? "<none>" : sarg);
+		return;
+	}
+	(void) fprintf(Efs,
+		"%s: pass3, len=%d, word=\"%s\", sarg=\"%s\", narg=%d%s%s\n",
+		Pname, len,
+		(word == NULL) ? "" : word,
+		(sarg == NULL) ? "" : sarg,
+		narg,
+		(msg == NULL) ? "" : " - ",
+		(msg == NULL) ? "" : msg);
+	Err = 1;
+}
Index: /trunk/minix/commands/cawf/expand.c
===================================================================
--- /trunk/minix/commands/cawf/expand.c	(revision 9)
+++ /trunk/minix/commands/cawf/expand.c	(revision 9)
@@ -0,0 +1,308 @@
+/*
+ *	expand.c - macro expansion functions for cawf(1)
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+#include "cawf.h"
+
+/*
+ * Expand(line) - expand macro or if/ie/el line
+ */
+
+void
+Expand(line)
+	unsigned char *line;
+{
+	unsigned char buf[2*MAXLINE];	/* line buffer */
+	unsigned char cmd[4];		/* nroff command */
+	int cmdl;			/* command length */
+	int cmdx;			/* cmd index in Macrotab[] */
+	int cond = 0;			/* conditional statuses */
+	int i, j;			/* temporary indexes */
+	int iflen;			/* if statement length */
+	int invert;			/* inversion status */
+	unsigned char *lp;		/* line pointer */
+	int mx = -1;			/* Macrotab[] index */
+	int n1, n2;			/* temporary numbers */
+	int nargs = 0;			/* number of arguments */
+	int nleft = 0;			/* number of macro lines left */
+	char op;			/* comparison operator */
+	int prevcond;			/* previous condition (for else's) */
+	int ptr = -1;			/* Macrotxt[] index */
+	int quote;			/* quoted string status */
+	unsigned char *s1, *s2;		/* temporary string pointers */
+
+
+	(void) sprintf((char *)buf, ".^= %d %s", NR, (char *)Inname);
+	Pass2(buf);
+
+	for (lp = line; *lp; ) {
+		invert = regexec(Pat[1].pat, lp);
+		prevcond = cond;
+		cond = 0;
+		if (regexec(Pat[0].pat, lp) == 0) {
+	    /*
+	     * Not conditional: - ! "^[.'](i[ef]|el)"
+	     */
+			cond = 1;
+			iflen = 0;
+		}
+
+		else if (regexec(Pat[2].pat, lp)) {
+	    /*
+	     * Argument count comparison: -
+	     *		"^[.']i[ef] !?\\n\(\.\$(>|>=|=|<|<=)[0-9] "
+	     */
+			iflen = strlen(".if \\n(.$=n ") + invert;
+			s1 = lp + iflen - 3;
+			op = *s1++;
+			if (*s1 == '=' && (op == '>' || op == '<')) {
+				s1++;
+				op = (op == '>') ? 'G' : 'L';
+			}
+			n1 = (int)(*s1 - '0');
+			switch (op) {
+				case '=':
+					if ((nargs - 1) == n1)
+						cond = 1;
+					break;
+				case '<':
+					if ((nargs - 1) < n1)
+						cond = 1;
+					break;
+				case '>':
+					if ((nargs - 1) > n1)
+						cond = 1;
+					break;
+				case 'G':	/* >= */
+					if ((nargs - 1) >= n1)
+						cond = 1;
+					break;
+				case 'L':	/* <= */
+					if ((nargs - 1) <= n1)
+						cond = 1;
+			}
+		}
+		
+		else if (regexec(Pat[3].pat, lp)) {
+	    /*
+	     * Argument string comparison: - "^[.']i[ef] !?'\\\$[0-9]'[^']*' "
+	     */
+			iflen = strlen(".if '\\$n'") + invert;
+			n1 = (int)(*(lp + iflen - 2) - '0');
+			if (n1 >= 0 && n1 < nargs)
+				s1 = Args[n1];
+			else
+				s1 = (unsigned char *)"";
+			if ((s2 = (unsigned char *)strchr((char *)lp
+				  + iflen, '\''))
+			!= NULL) {
+				n2 = s2 - lp - iflen;
+				if (strncmp((char *)s1, (char *)lp + iflen, n2)
+				== 0)
+					cond = 1;
+				iflen += n2 + 2;
+			}
+		}
+		
+		else if (regexec(Pat[4].pat, lp)) {
+	    /*
+	     * Nroff or troff: - "^[.']i[ef] !?[nt] "
+	     */
+			iflen = strlen(".if n ") + invert;
+			if (*(lp + iflen - 2) == 'n')
+				cond = 1;
+		}
+		
+		else if ((*lp == '.' || *lp == '\'')
+		     &&  strncmp((char *)lp+1, "el ", 3) == 0) {
+	    /*
+	     * Else clause: - "^[.']el "
+	     */
+			cond = 1 - prevcond;
+			iflen = 4;
+		}
+		
+		else {
+	    /*
+	     * Unknown conditional:
+	     */
+			cond = 1;
+			iflen = 0;
+			(void) sprintf((char *)buf,
+				".tm unknown .if/.ie form: %s", (char *)lp);
+			lp = buf;
+		}
+	   /*
+	    * Handle conditional.  If case is true, locate predicate.
+	    * If predicate is an .i[ef], process it.
+	    */
+		if (invert)
+			cond = 1 - cond;
+		if (cond && iflen > 0) {
+			lp += iflen;
+			if (regexec(Pat[15].pat, lp))
+				continue;
+		}
+	    /*
+	     * Do argument substitution, as necessary.
+	     */
+		if (cond && regexec(Pat[5].pat, lp)) {      /* "\$[0-9]" ??? */
+			for (s1 = buf;;) {
+				if ((n1 = Pat[5].pat->startp[0] - lp) > 0) {
+					(void) strncpy((char *)s1, (char *)lp,
+						n1);
+					s1 += n1;
+				}
+				*s1 = '\0';
+				lp = Pat[5].pat->endp[0];
+				n1 = (int)(*(lp-1) - '0');
+				if (n1 >= 0 && n1 < nargs) {
+					(void) strcpy((char *)s1,
+						(char *)Args[n1]);
+					s1 += strlen((char *)Args[n1]);
+				}
+				if (*lp == '\0')
+					break;
+				if (regexec(Pat[5].pat, lp) == 0) {
+					(void) strcpy((char *)s1, (char *)lp);
+					break;
+				}
+			}
+			lp = buf;
+		}
+	    /*
+	     * Check for nroff command.
+	     */
+		if (cond) {
+			cmdl = 0;
+			if (cond && (*lp == '.' || *lp == '\'')) {
+				if ((*cmd = *(lp+1)) != '\0') {
+					cmdl++;
+					if ((*(cmd+1) = *(lp+2)) == ' ')
+						*(cmd+1) = '\0';
+					else
+						cmdl++;
+				}
+			}
+			cmd[cmdl] = '\0';
+		}
+		if (cond == 0)
+			i = i;		/* do nothing if condition is false */
+		else if (cmdl == 0 || ((cmdx = Findmacro(cmd, 0)) < 0))
+			Pass2(lp);
+		else if (Sp >= MAXSP) {
+			(void) sprintf((char *)buf, " macro nesting > %d",
+				MAXSP);
+			Error(WARN, LINE, (char *)buf, NULL);
+		} else {
+	    /*
+	     * Stack macros.
+	     */
+		  /*
+		   * Push stack.
+		   */
+			Sp++;
+			Nleftstack[Sp] = nleft;
+			Ptrstack[Sp] = ptr;
+			Mxstack[Sp] = mx;
+			Condstack[Sp] = cond;
+			for (i = 10*Sp, j = 0; j < 10; i++, j++) {
+				Argstack[i] = Args[j];
+				Args[j] = NULL;
+			}
+		   /*
+		    * Start new stack entry.
+		    */
+			mx = cmdx;
+			ptr = Macrotab[mx].bx;
+			cond = 0;
+			nleft = Macrotab[mx].ct;
+			Args[0] = Newstr(cmd);
+		   /*
+		    * Parse arguments.
+		    */
+			for (s1 = lp + cmdl + 1, nargs = 1; nargs < 10;) {
+				while (*s1 && (*s1 == ' ' || *s1 == '\t'))
+					s1++;
+				if (*s1 == '\0')
+					break;
+				if (*s1 == '"') {
+					s1++;
+					quote = 1;
+				} else
+					quote = 0;
+				for (s2 = buf;;) {
+				    if (!quote && (*s1 == ' ' || *s1 == '\t')) {
+					*s2 = '\0';
+					break;
+				    }
+				    if ((*s2 = *s1) == '\0')
+					break;
+				    s1++;
+				    if (quote && *s2 == '"') {
+					*s2 = '\0';
+					break;
+				    }
+				    s2++;
+			    	}
+				if (buf[0])
+					Args[nargs++] = Newstr(buf);
+			}
+			for (i = nargs; i < 10; i++) {
+				Args[i] = NULL;
+			}
+		}
+	    /*
+	     * Unstack completed macros.
+	     */
+		while (nleft <= 0 && Sp >= 0) {
+			nleft = Nleftstack[Sp];
+			mx = Mxstack[Sp];
+			ptr = Ptrstack[Sp];
+			cond = Condstack[Sp];
+			for (i = 10*Sp, j = 0, nargs = -1; j < 10; i++, j++) {
+				Free(&Args[j]);
+				if ((Args[j] = Argstack[i]) != NULL)
+					nargs = j;
+			}
+			Sp--;
+			nargs++;
+		}
+	    /*
+	     * Get next line.
+	     */
+		if (nleft > 0) {
+			lp = Macrotxt[ptr++];
+			nleft--;
+		} else
+			lp = (unsigned char *)"";
+	}
+	(void) sprintf((char *)buf, ".^# %d %s", NR, (char *)Inname);
+	Pass2(buf);
+}
Index: /trunk/minix/commands/cawf/expr.c
===================================================================
--- /trunk/minix/commands/cawf/expr.c	(revision 9)
+++ /trunk/minix/commands/cawf/expr.c	(revision 9)
@@ -0,0 +1,175 @@
+/*
+ *	expr.c - expression support functions for cawf(1)
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+#include "cawf.h"
+
+
+/*
+ * Asmcode(s, c) - assemble number/name code following backslash-character
+ *		   definition  - e. .g, "\\nPO"
+ */
+
+unsigned char *
+Asmcode(s, c)
+	unsigned char **s;		/* pointer to character after '\\' */
+	unsigned char *c;		/* code destination (c[3]) */
+{
+	unsigned char *s1;
+
+	s1 = *s + 1;
+	c[0] = c[1] = c[2] = '\0';
+	if ((c[0] = *s1) == '(') {
+		s1++;
+		if ((c[0] = *s1) != '\0') {
+			s1++;
+			c[1] = *s1;
+		}
+	}
+	return(s1);
+}
+
+
+/*
+ * Delnum(nx) - delete number
+ */
+
+void
+Delnum(nx)
+	int nx;				/* number index */
+{
+	unsigned char buf[MAXLINE];	/* message buffer */
+
+	if (nx >= Nnr) {
+		(void) sprintf((char *)buf, " bad Delnum(%d) index", nx);
+		Error(FATAL, LINE, (char *)buf, NULL);
+	}
+	while (nx < (Nnr - 1)) {
+		Numb[nx] = Numb[nx + 1];
+		nx++;
+	}
+	Nnr--;
+}
+
+
+/*
+ * Findnum(n, v, e) - find or optionally enter number value
+ */
+
+Findnum(n, v, e)
+	unsigned char *n;		/* register name */
+	int v;				/* value */
+	int e;				/* 0 = find, don't enter
+					 * 1 = enter, don't find */
+{
+	int cmp, low, hi, mid;		/* binary search controls */
+	unsigned char c[3];		/* name buffer */
+
+	c[0] = n[0];
+	c[1] = (n[1] == ' ' || n[1] == '\t') ? '\0' : n[1];
+	c[2] = '\0';
+	low = mid = 0;
+	hi = Nnr - 1;
+	while (low <= hi) {
+		mid = (low + hi) / 2;
+		if ((cmp = strncmp((char *)c, (char *)Numb[mid].nm, 2)) < 0)
+			hi = mid - 1;
+		else if (cmp > 0)
+			low = mid + 1;
+		else {
+			if (e)
+				Numb[mid].val = v;
+			return(mid);
+		}
+	}
+	if ( ! e)
+		return(-1);
+	if (Nnr >= MAXNR)
+		Error(FATAL, LINE, " out of number registers at ", (char *)c);
+	if (Nnr) {
+		if (cmp > 0)
+			mid++;
+		for (hi = Nnr - 1; hi >= mid; hi--)
+			Numb[hi+1] = Numb[hi];
+	}
+	Nnr++;
+	Numb[mid].nm[0] = c[0];
+	Numb[mid].nm[1] = c[1];
+	Numb[mid].val = v;
+	return(mid);
+}
+
+
+/*
+ * Findparms(n) - find parameter registers
+ */
+
+Findparms(n)
+	unsigned char *n;		/* parameter name */
+{
+	unsigned char c[3];		/* character buffer */
+	int i;				/* temporary index */
+
+	c[0] = n[0];
+	c[1] = (n[1] == ' ' || n[1] == '\t') ? '\0' : n[1];
+	c[2] = '\0';
+	for (i = 0; Parms[i].nm[0]; i++) {
+		if (c[0] == Parms[i].nm[0] && c[1] == Parms[i].nm[1])
+			return(i);
+	}
+	return(-1);
+}
+
+
+/*
+ * Findscale(n, v, e) - find and optionally enter scaling factor value
+ */
+
+Findscale(n, v, e)
+	int n;				/* scaling factor name */
+	double v;			/* value */
+	int e;				/* 0 = find, don't enter
+					 * 1 = enter, don't find */
+{
+	int i;
+	double *pval;
+
+	for (i = 0; Scale[i].nm; i++) {
+		if ((unsigned char )n == Scale[i].nm)
+			break;
+	}
+	if (Scale[i].nm) {
+		if (e) {
+			pval = &Scale[i].val;
+			*pval = v;
+		}
+		return(i);
+	}
+	return(-1);
+}
Index: /trunk/minix/commands/cawf/getopt.c
===================================================================
--- /trunk/minix/commands/cawf/getopt.c	(revision 9)
+++ /trunk/minix/commands/cawf/getopt.c	(revision 9)
@@ -0,0 +1,77 @@
+/*
+Newsgroups: mod.std.unix
+Subject: public domain AT&T getopt source
+Date: 3 Nov 85 19:34:15 GMT
+
+Here's something you've all been waiting for:  the AT&T public domain
+source for getopt(3).  It is the code which was given out at the 1985
+UNIFORUM conference in Dallas.  I obtained it by electronic mail
+directly from AT&T.  The people there assure me that it is indeed
+in the public domain.
+*/
+
+
+/*LINTLIBRARY*/
+#define NULL	0
+#define EOF	(-1)
+#define ERR(s, c)	if(opterr){\
+	extern int strlen(), write();\
+	char errbuf[2];\
+	errbuf[0] = c; errbuf[1] = '\n';\
+	(void) write(2, argv[0], (unsigned)strlen(argv[0]));\
+	(void) write(2, s, (unsigned)strlen(s));\
+	(void) write(2, errbuf, 2);}
+
+extern int strcmp();
+extern char *strchr();
+
+int	opterr = 1;
+int	optind = 1;
+int	optopt;
+char	*optarg;
+
+int
+getopt(argc, argv, opts)
+int	argc;
+char	**argv, *opts;
+{
+	static int sp = 1;
+	register int c;
+	register char *cp;
+
+	if(sp == 1)
+		if(optind >= argc ||
+		   argv[optind][0] != '-' || argv[optind][1] == '\0')
+			return(EOF);
+		else if(strcmp(argv[optind], "--") == NULL) {
+			optind++;
+			return(EOF);
+		}
+	optopt = c = argv[optind][sp];
+	if(c == ':' || (cp=strchr(opts, c)) == NULL) {
+		ERR(": illegal option -- ", c);
+		if(argv[optind][++sp] == '\0') {
+			optind++;
+			sp = 1;
+		}
+		return('?');
+	}
+	if(*++cp == ':') {
+		if(argv[optind][sp+1] != '\0')
+			optarg = &argv[optind++][sp+1];
+		else if(++optind >= argc) {
+			ERR(": option requires an argument -- ", c);
+			sp = 1;
+			return('?');
+		} else
+			optarg = argv[optind++];
+		sp = 1;
+	} else {
+		if(argv[optind][++sp] == '\0') {
+			sp = 1;
+			optind++;
+		}
+		optarg = NULL;
+	}
+	return(c);
+}
Index: /trunk/minix/commands/cawf/macsup.c
===================================================================
--- /trunk/minix/commands/cawf/macsup.c	(revision 9)
+++ /trunk/minix/commands/cawf/macsup.c	(revision 9)
@@ -0,0 +1,181 @@
+/*
+ *	macsup.c - macro processing support functions for cawf(1)
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+#include "cawf.h"
+
+
+/*
+ * Delmacro(mx) - delete macro
+ */
+
+Delmacro(mx)
+	int mx;				/* macro index */
+{
+	unsigned char buf[MAXLINE];	/* error message buffer */
+	int i, j;			/* temporary indexes */
+
+	if (mx >= Nmac) {
+		(void) sprintf((char *)buf, " bad Delmacro(%d) index", mx);
+		Error(FATAL, LINE, (char *)buf, NULL);
+	}
+	for (i = Macrotab[mx].bx, j = i + Macrotab[mx].ct; i < j; i++) {
+		Free(&Macrotxt[i]);
+	}
+	for (i = mx; i < (Nmac - 1); i++) {
+		Macrotab[i] = Macrotab[i+1];
+	}
+	Nmac--;
+}
+
+
+/*
+ * Field(n, p, c) - skip to field n in p and optionally return a copy
+ */
+
+unsigned char *
+Field(n, p, c)
+	int n;				/* field number */
+	unsigned char *p;		/* pointer to line containing fields */
+	int c;				/* 1: make a copy of the field */
+{
+	unsigned char *fs, *fe, *s;
+
+	if (c)
+		Free(&F);
+	fe = p;
+	while (n) {
+		while (*fe == ' ' || *fe == '\t')
+			fe++;
+		fs = fe;
+		while (*fe && *fe != ' ' && *fe != '\t')
+			fe++;
+		if (fs == fe)
+			return(NULL);
+		if (n == 1) {
+			if ( ! c)
+				return(fs);
+			if ((F = (unsigned char *)malloc((size_t)(fe - fs + 1)))
+			== NULL)
+				Error(FATAL, LINE, " Field out of string space",
+					NULL);
+			(void) strncpy((char *)F, (char *)fs, (fe - fs));
+			F[fe -fs] = '\0';
+			return(F);
+		}
+		n--;
+	}
+	return(NULL);
+}
+
+/*
+ * Findmacro(p, e) - find macro and optionally enter it
+ *
+ * return = Macrotab[] index or -1 if not found
+ */
+
+
+Findmacro(p, e)
+	unsigned char *p;	/* pointer to 2 character macro name  */
+	int e;			/* 0 = find, don't enter
+				 * 1 = enter, don't find */
+{
+	unsigned char c[3];
+	int cmp, hi, low, mid;
+
+	c[0] = p[0];
+	c[1] = (p[1] == ' ' || p[1] == '\t') ? '\0' : p[1];
+	c[2] = '\0';
+	low = mid = 0;
+	hi = Nmac - 1;
+	while (low <= hi) {
+		mid = (low + hi) / 2;
+		if ((cmp = strncmp((char *)c, (char *)Macrotab[mid].name, 2))
+		< 0)
+			hi = mid - 1;
+		else if (cmp > 0)
+			low = mid + 1;
+		else {
+			if ( ! e)
+				return(mid);
+			 Error(WARN, LINE, " duplicate macro ", (char *)c);
+			 hi = Macrotab[mid].bx + Macrotab[mid].ct;
+			 for (low = Macrotab[mid].bx; low < hi; low++) {
+				Free(&Macrotxt[low]);
+			 }
+			 goto new_macro;
+		}
+	}
+	if ( ! e)
+		return(-1);
+	if (Nmac >= MAXMACRO)
+		Error(FATAL, LINE, " macro table full at ", (char *)c);
+	if (Nmac) {
+		if (cmp > 0)
+			mid++;
+		for (hi = Nmac - 1; hi >= mid; hi--)
+			Macrotab[hi+1] = Macrotab[hi];
+	}
+	Nmac++;
+	Macrotab[mid].name[0] = c[0];
+	Macrotab[mid].name[1] = c[1];
+
+new_macro:
+
+	Macrotab[mid].bx = -1;
+	Macrotab[mid].ct = 0;
+	return(mid);
+}
+
+void
+Free(p)
+	unsigned char **p;
+{
+	if (*p != NULL) {
+		(void) free(*p);
+		*p = NULL;
+	}
+}
+
+/*
+ * Newstr(s) - allocate space for string
+ */
+
+unsigned char *
+Newstr(s)
+	unsigned char *s;
+{
+	unsigned char *ns;
+
+	if ((ns = (unsigned char *)malloc((size_t)(strlen((char *)s) + 1)))
+	== NULL)
+	    Error(FATAL, LINE, " Newstr out of malloc space at ", (char *)s);
+	(void) strcpy((char *)ns, (char *)s);
+	return(ns);
+}
Index: /trunk/minix/commands/cawf/man.mac
===================================================================
--- /trunk/minix/commands/cawf/man.mac	(revision 9)
+++ /trunk/minix/commands/cawf/man.mac	(revision 9)
@@ -0,0 +1,180 @@
+.^b HF 1
+.^b fh 1
+.\"-----------------
+.de TH
+.ds LH "\\$1(\\$2)
+.ds CH "Minix Programmer's Manual
+.ds RH "\\$1(\\$2)
+.ds LF "
+.ds CF "\\$3
+.ds RF "%
+..
+.\"-----------------
+.de AT
+..
+.\"-----------------
+.de IX
+..
+.\"-----------------
+.de NB
+.ds nb "\\$1
+.lF
+..
+.\"-----------------
+.de BY
+.ds by "\\$1
+.lF
+..
+.\"-----------------
+.de UC
+.BY "\\$1BSD"
+..
+.\"-----------------
+.\" common initialization for headers and paragraphs:  .In need
+.de In
+.ne \\$1
+.sp \\n(PDu
+.fi
+.in 0
+.ti 0
+.in \\n(inu
+.it
+.ft R
+.ns
+..
+.\"-----------------
+.de SH
+.In 6
+.in 0
+.ft B
+\&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.ft R
+.nr in 5n
+.in \\n(inu
+..
+.\"-----------------
+.de SS
+.In 6
+.in 2n
+.ft B
+\&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.ft R
+.in \\n(inu
+..
+.\"-----------------
+.de LP
+.In 4
+..
+.\"-----------------
+.de PP
+.LP
+..
+.\"-----------------
+.de P
+.LP
+..
+.\"-----------------
+.de HP
+.In 4
+.if \\n(.$>0 .ti 0-\\$1
+.if \\n(.$=0 .ti 0-\\n(tpu
+..
+.\"-----------------
+.de TP
+.In 4
+.if \\n(.$>0 .nr tp \\$1n
+.in \\n(inu+\\n(tpu
+.ti 0-\\n(tpu
+.it 1 tP
+..
+.\"-----------------
+.de IP
+.ie \\n(.$>1 .TP "\\$2"
+.el .TP
+\&\\$1
+..
+.\"-----------------
+.de I
+.ft I
+.it 1 fR
+.if \\n(.$>0 \&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\"-----------------
+.de B
+.ft B
+.it 1 fR
+.if \\n(.$>0 \&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\"-----------------
+.de SB
+.\" Can't reduce size, just do bold
+.ft B
+.it 1 fR
+.if \\n(.$>0 \&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\"-----------------
+.de IR
+\&\\fI\\$1\\fR\\$2\\fI\\$3\\fR\\$4\\fI\\$5\\fR\\$6\\fI\\$7\\fR\\$8\\fI\\$9\\fR
+..
+.\"-----------------
+.de RI
+\&\\$1\\fI\\$2\\fR\\$3\\fI\\$4\\fR\\$5\\fI\\$6\\fR\\$7\\fI\\$8\\fR\\$9
+..
+.\"-----------------
+.de BR
+\&\\fB\\$1\\fR\\$2\\fB\\$3\\fR\\$4\\fB\\$5\\fR\\$6\\fB\\$7\\fR\\$8\\fB\\$9\\fR
+..
+.\"-----------------
+.de RB
+\&\\$1\\fB\\$2\\fR\\$3\\fB\\$4\\fR\\$5\\fB\\$6\\fR\\$7\\fB\\$8\\fR\\$9
+..
+.\"-----------------
+.de BI
+\&\\fB\\$1\\fI\\$2\\fB\\$3\\fI\\$4\\fB\\$5\\fI\\$6\\fB\\$7\\fI\\$8\\fB\\$9\\fR
+..
+.\"-----------------
+.de IB
+\&\\fI\\$1\\fB\\$2\\fI\\$3\\fB\\$4\\fI\\$5\\fB\\$6\\fI\\$7\\fB\\$8\\fI\\$9\\fR
+..
+.\"-----------------
+.de SM
+.\" no-op
+.if \\n(.$>0 \&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\"-----------------
+.de DT
+.ta +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8
+..
+.\"-----------------
+.de TA
+.ta \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\"-----------------
+.de RS
+.in +5n
+..
+.\"-----------------
+.de RE
+.in -5n
+..
+.de DS
+.br
+..
+.de DE
+.br
+..
+.\"-----------------
+.de PD
+.ie \\n(.$=0 .nr PD 0.3v
+.el .nr PD \\$1n
+..
+.\"-----------------
+.\" misc. initialization
+.nr tp 5n
+.PD
+.ds lq \&"
+.ds rq \&"
+.ds R \(rg
+.ds S "
+.ds Tm (TM)
+.nr )P 1v
Index: /trunk/minix/commands/cawf/me.mac
===================================================================
--- /trunk/minix/commands/cawf/me.mac	(revision 9)
+++ /trunk/minix/commands/cawf/me.mac	(revision 9)
@@ -0,0 +1,199 @@
+.^b HF 1
+.^b fh 0
+.^b NH
+.\"-----------------
+.de r
+.ie \\n(.$=0 .ft R
+.el \\fR\\$1\\fP\\$2
+..
+.\"-----------------
+.de i
+.ie \\n(.$=0 .ft I
+.el \\fI\\$1\\fP\\$2
+..
+.\"-----------------
+.de b
+.ie \\n(.$=0 .ft B
+.el \\fB\\$1\\fP\\$2
+..
+.\"-----------------
+.de UX
+\\$2UNIX\\$1
+..
+.\"-----------------
+.de DA
+.ds DY "\\$1 \\$2 \\$3
+.\" keep trailing spaces out of CF
+.if \\n(.$=1 .ds CF "\\$1
+.if \\n(.$=2 .ds CF "\\$1 \\$2
+.if \\n(.$>2 .ds CF "\\$1 \\$2 \\$3
+..
+.\"-----------------
+.de ND
+.\" it's our default, ignore it
+..
+.\"-----------------
+.de TL
+.rs
+.sp 5
+.ft B
+.ce 9999
+..
+.\"-----------------
+.de AU
+.sp 2
+.ft R
+..
+.\"-----------------
+.de AI
+.sp
+.ft R
+..
+.\"-----------------
+.de AB
+.sp 2
+.ce 0
+.ll -7n
+.in +7n
+..
+.\"-----------------
+.de AE
+.sp
+.ll
+.in
+..
+.\" common initialization for headers and paragraphs:  .In need extraspace
+.de In
+.ne \\$1
+.sp \\n(Tsu
+.nr Ts 0
+.ie \\n(.$>1 .nr iN \\$2v
+.el .nr iN 0
+.sp \\n(psu+\\n(iNu
+.ce 0
+.ft R
+.in 0
+.ti 0
+.in \\n(inu
+.ll \\n(LLu
+.ns
+.fi
+..
+.\"-----------------
+.de uh
+.\" unnumbered section head
+.nr in 0
+.In 6 1
+.ie \\n(.$=0 .ft B
+.el \\fB\\$1\\fP\\$2
+..
+.\"-----------------
+.de sh
+.\" numbered section head
+.nr in 0
+.In 6 1
+.ft B
+.\" punt to awk code to get the header numbering right
+.nH \\$1
+.\" and pick up the result
+\&\\*(Nh \\$2
+.ft R
+..
+.\"-----------------
+.de lp
+.\" left-blocked paragraph
+.In 4
+..
+.\"-----------------
+.de pp
+.\" paragraph, first line indented
+.In 4
+.ti \\n(piu
+..
+.\"-----------------
+.de tp
+.In 4
+.if \\n(.$>0 .nr tp \\$1n
+.in \\n(inu+\\n(tpu
+.ti 0-\\n(tpu
+.\" .it 1 tP
+..
+.\"-----------------
+.de ip
+.\" indented paragraph
+.ie \\n(.$>1 .tp "\\$2"
+.el .tp 4n
+\&\\$1
+..
+.\"-----------------
+.de np
+.\" numbered paragraph
+.nr $p +1			\" increment paragraph number
+.ip (\n($p)
+..
+.\"-----------------
+.de bu
+.\" bulleted paragraph
+.ip \(bu
+..
+.\"-----------------
+.de (q
+.\" begin major quote
+.nr in +5n
+.nr LL -5n
+.In 4
+..
+.\"-----------------
+.de )q
+.\" end major quote
+.sp
+.nr in -5n
+.nr LL +5n
+.In 4
+..
+.\"-----------------
+.de (l
+.\" begin list
+.In 5
+.if '\\$1'C' .ce 9999
+.if '\\$1'' .in +5n
+.if '\\$1'L' .in 0
+.nf
+..
+.\"-----------------
+.de )l
+.\" end list
+.In 3
+.sp
+.rs
+..
+.\"-----------------
+.de u
+\&\\fI$1\\fP
+..
+.\"-----------------
+.de sm
+..
+.\"-----------------
+.\" exdented paragraph macro borrowed from Berkeley -ms
+.de XP	
+.lp
+.in \\n(piu
+.ti
+..
+.\"-----------------
+.\" the -ms accent strings
+.ds ' "'\b
+.ds ` "`\b
+.ds : ":\b
+.ds ^ "^\b
+.ds ~ "~\b
+.ds C "v\b
+.ds , ",\b
+.\" post-title spacing (set to 4v if using .TL macro)
+.nr Ts 0v
+.\" and parameter setup
+.nr LL 6i
+.ll \n(LLu
+.nr ps 0.3v
+.nr pi 5n
Index: /trunk/minix/commands/cawf/mnx.mac
===================================================================
--- /trunk/minix/commands/cawf/mnx.mac	(revision 9)
+++ /trunk/minix/commands/cawf/mnx.mac	(revision 9)
@@ -0,0 +1,137 @@
+.\" -mnx macros for the Minix "Book manual pages".	Author: Kees J. Bot
+.\"								19 Nov 1994
+.\" Uses -ms:
+.so /usr/lib/cawf/ms.mac
+.tr ~
+.ds OQ \&'
+.ds CQ \&'
+.ds SQ \&'
+.ds M0 MINIX
+.ds M1 \\s-1MINIX\\s+1
+.ds M2 \\s-2MINIX\\s+2
+.ds M9 \\s-1MINIX\\s+1
+.ds m0 minix
+.de MX
+\s-2MINIX\s+2\\$1
+..
+.de Ux
+\s-2UNIX\s+2\\$1
+..
+.ds Mx \\s-1MINIX\\s0
+.ds Mp \\s-1MINIX-PC\\s0
+.ds Ms \\s-1MINIX-ST\\s0
+.ds M0 MINIX
+.ds M1 MINIX
+.ds M2 MINIX
+.ds M9 MINIX
+.ds Mx MINIX
+.ds Mp MINIX-PC
+.ds Ms MINIX-ST
+.de CD
+.LP
+.ne 2
+.ta 11m 15m 36m
+.ds SX Syntax:
+.ds FL Flags:
+.ds EX Examples:
+.ds EY Example:
+.in +16m
+.ti -16m
+\\fBCommand:\&	\\$1\\fR
+.in -16m
+.br
+..
+.de SX
+.in +16m
+.ti -16m
+\\fB\*(SX\&	\\$1
+.in -16m
+.ds SX
+.br
+..
+.de FL
+.in +15m
+.ti -15m
+\\fB\*(FL\&	\\fB\\$1	\\fR\\$2
+.in -15m
+.ds FL
+.br
+..
+.de EX
+.br
+.in +38m
+.ti -38m
+\\fB\*(EX\&	\\fR\\$1		\\fR# \\$2
+.in -38m
+.ds EX
+.ds EY
+.br
+..
+.de EY
+.br
+.in +38m
+.ti -38m
+\\fB\*(EY\&	\\fR\\$1		\\fR# \\$2
+.in -38m
+.ds EX
+.ds EY
+.br
+..
+.de Cx
+.in +8
+.ft B
+\&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.ft R
+.in -8
+..
+.de DI
+.ft B
+\&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.ft R
+..
+.de SY
+\\$3\\$1\\$2
+..
+.de HS
+.sp 0.5
+..
+.de SP
+.sp
+..
+.\"	Major section (normally numbered)
+.de SE
+.sp 1
+\fB\\$1\fP
+.sp 1
+..
+.\"	Subsection (normally numbered)
+.de SS
+.sp 1
+\fB\\$1\fP
+..
+.de UU
+.SH
+\\$1
+.sp 1
+..
+.\"	Start list
+.de LI
+.in +0.25i
+.ll -0.25i
+.HS
+..
+.\"	End list
+.de LX
+.sp 1
+.in -0.25i
+.ll +0.25i
+.LP
+..
+.\"	List item
+.de IT
+.HS
+..
+.\"Short unnumbered lines
+.de UN
+.HS
+..
Index: /trunk/minix/commands/cawf/ms.mac
===================================================================
--- /trunk/minix/commands/cawf/ms.mac	(revision 9)
+++ /trunk/minix/commands/cawf/ms.mac	(revision 9)
@@ -0,0 +1,210 @@
+.^b HF 1
+.^b fh 0
+.^b NH
+.\"-----------------
+.de R
+.ie \\n(.$=0 .ft R
+.el \\fR\\$1\\fP\\$2
+..
+.\"-----------------
+.de I
+.ie \\n(.$=0 .ft I
+.el \\fI\\$1\\fP\\$2
+..
+.\"-----------------
+.de B
+.ie \\n(.$=0 .ft B
+.el \\fB\\$1\\fP\\$2
+..
+.\"-----------------
+.de UX
+\\$2UNIX\\$1
+..
+.\"-----------------
+.de DA
+.ds DY "\\$1 \\$2 \\$3
+.\" keep trailing spaces out of CF
+.if \\n(.$=1 .ds CF "\\$1
+.if \\n(.$=2 .ds CF "\\$1 \\$2
+.if \\n(.$>2 .ds CF "\\$1 \\$2 \\$3
+..
+.\"-----------------
+.de ND
+.\" it's our default, ignore it
+..
+.\"-----------------
+.de TL
+.rs
+.sp 5
+.ft B
+.ce 9999
+..
+.\"-----------------
+.de AU
+.sp 2
+.ft R
+..
+.\"-----------------
+.de AI
+.sp
+.ft R
+..
+.\"-----------------
+.de AB
+.sp 2
+.ce 0
+.ll -7n
+.in +7n
+..
+.\"-----------------
+.de AE
+.sp
+.ll
+.in
+..
+.\"-----------------
+.\" common initialization for headers and paragraphs:  .In need extraspace
+.de In
+.ne \\$1
+.sp \\n(Tsu
+.nr Ts 0
+.ie \\n(.$>1 .nr iN \\$2v
+.el .nr iN 0
+.sp \\n(PDu+\\n(iNu
+.ce 0
+.ft R
+.in 0
+.ti 0
+.in \\n(inu
+.ll \\n(LLu
+.ns
+.fi
+..
+.\"-----------------
+.de SH
+.nr in 0
+.In 6 1
+.ft B
+..
+.\"-----------------
+.de NH
+.nr in 0
+.In 6 1
+.ft B
+.\" punt to awk code to get the header numbering right
+.nH \\$1
+.\" and pick up the result
+\&\\*(Nh
+..
+.\"-----------------
+.de LP
+.In 4
+..
+.\"-----------------
+.de PP
+.In 4
+.ti \\n(PIu
+..
+.\"-----------------
+.de TP
+.In 4
+.if \\n(.$>0 .nr tp \\$1n
+.in \\n(inu+\\n(tpu
+.ti 0-\\n(tpu
+.it 1 tP
+..
+.\"-----------------
+.de IP
+.ie \\n(.$>1 .TP "\\$2"
+.el .TP 4n
+\&\\$1
+..
+.\"-----------------
+.de QP
+.In 4
+.in +5n
+.ll -5n
+..
+.\"-----------------
+.de QS
+.nr in +5n
+.nr LL -5n
+.In 4
+..
+.\"-----------------
+.de QE
+.nr in -5n
+.nr LL +5n
+.In 4
+..
+.\"-----------------
+.de DS
+.In 5
+.if '\\$1'C' .ce 9999
+.if '\\$1'' .in +5n
+.nf
+..
+.\"-----------------
+.de CD
+.In 5
+.ce 9999
+.nf
+..
+.\"-----------------
+.de LD
+.In 5
+.nf
+..
+.\"-----------------
+.de ID
+.In 5
+.in +5n
+.nf
+..
+.\"-----------------
+.de DE
+.In 3
+.rs
+..
+.\"-----------------
+.de RS
+.nr in +5n
+.in \\n(inu
+..
+.\"-----------------
+.de RE
+.nr in -5n
+.in \\n(inu
+..
+.\"-----------------
+.de UL
+\&\\fI$1\\fP
+..
+.\"-----------------
+.de RP
+..
+.\"-----------------
+.de LG
+..
+.\"-----------------
+.de SM
+..
+.\"-----------------
+.de NL
+..
+.\"-----------------
+.\" the -ms accent strings
+.ds ' "'\b
+.ds ` "`\b
+.ds : ":\b
+.ds ^ "^\b
+.ds ~ "~\b
+.ds C "v\b
+.ds , ",\b
+.\" post-title spacing
+.nr Ts 4v
+.\" and parameter setup
+.nr LL 6i
+.ll \n(LLu
+.nr PD 0.3v
+.nr PI 5n
Index: /trunk/minix/commands/cawf/nreq.c
===================================================================
--- /trunk/minix/commands/cawf/nreq.c	(revision 9)
+++ /trunk/minix/commands/cawf/nreq.c	(revision 9)
@@ -0,0 +1,880 @@
+/*
+ *	nreq.c - cawf(1) processing of nroff requests
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+#include "cawf.h"
+#include <ctype.h>
+
+
+/*
+ * Prototypes for request processing functions.
+ */
+
+_PROTOTYPE(static void nr_UL,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_Ub,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_Uc,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_Uf,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_Ur,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_ad,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_bp,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_br,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_ce,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_di,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_ds,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_fi,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_fl,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_ft,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_it,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_na,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_nf,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_ns,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_rm,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_rn,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_rr,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_rs,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_tm,(unsigned char *line, int brk));
+_PROTOTYPE(static void nr_tr,(unsigned char *line, int brk));
+
+_PROTOTYPE(static void nr_nil,(unsigned char *line, int brk));
+
+
+/*
+ * NrReqt[] - nroff request processing table
+ *
+ * CAUTION: place new entries in their proper alphabetical order, since
+ *	    this table is processed with a binary search.
+ */
+
+static struct nr_req {
+	char *nm;			/* nroff request */
+	void (*fun)();			/* processing function */
+} NrReqt[] = {
+	{ "\\\"",	nr_nil },	/* backslash-quote */
+	{ "^#",		nr_UL  },
+	{ "^=",		nr_UL  },
+	{ "^b",		nr_Ub  },
+	{ "^c",		nr_Uc  },
+	{ "^d",		nr_nil },
+	{ "^e",		nr_nil },
+	{ "^f",		nr_Uf  },
+	{ "^r",		nr_Ur  },
+	{ "^x",		nr_nil },
+	{ "ad",		nr_ad  },
+	{ "bp",		nr_bp  },
+	{ "br",		nr_br  },
+	{ "ce",		nr_ce  },
+	{ "di",		nr_di  },
+	{ "ds",		nr_ds  },
+	{ "fi",		nr_fi  },
+	{ "fl",		nr_fl  },
+	{ "ft",		nr_ft  },
+	{ "hy",		nr_nil },
+	{ "i0",		nr_nil },
+	{ "it",		nr_it  },
+	{ "lg",		nr_nil },
+	{ "li",		nr_nil },
+	{ "na",		nr_na  },
+	{ "nf",		nr_nf  },
+	{ "ns",		nr_ns  },
+	{ "ps",		nr_nil },
+	{ "rm",		nr_rm  },
+	{ "rn",		nr_rn  },
+	{ "rr",		nr_rr  },
+	{ "rs",		nr_rs  },
+	{ "tm",		nr_tm  },
+	{ "tr",		nr_tr  },
+	{ "vs",		nr_nil },
+};
+/*
+ * Nreq(line, brk) - process miscellaneous nroff requests from line
+ *		     buffer with request status of (brk)
+ */
+
+void
+Nreq(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	unsigned char c[3];		/* command buffer */
+	int cmp, hi, low, mid;		/* binary search indixes */
+
+	c[0] = c[1] = c[2] = '\0';
+	if ((c[0] = line[1]) != '\0')
+		c[1] = line[2];
+
+	low = mid = 0;
+	hi = sizeof(NrReqt) / sizeof(struct nr_req);
+	while (low <= hi) {
+		mid = (low + hi) / 2;
+		if ((cmp = strcmp((char *)c, NrReqt[mid].nm)) < 0)
+			hi = mid - 1;
+		else if (cmp > 0)
+			low = mid + 1;
+		else {
+			(void) (*NrReqt[mid].fun)(line, brk);
+			return;
+		}
+	}
+    /*
+     * Unknown request starting with a '.' or '\''..
+     */
+	Error(WARN, LINE, " unknown request", NULL);
+}
+
+
+/*
+ * Adjust - "^[.']ad"
+ */
+
+static void
+nr_ad(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	Pass3(NOBREAK, (unsigned char *)"both", NULL, 0);
+}
+
+
+/*
+* Begin new page - "^[.']bp"
+*/
+
+static void
+nr_bp(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	Pass3(brk, (unsigned char *)"need", NULL, 999);
+}
+
+
+/*
+* Break - "^[.']br"
+*/
+
+static void
+nr_br(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	Pass3(brk, (unsigned char *)"flush", NULL, 0);
+}
+
+
+/*
+ * Center - "^[.']ce"
+ */
+
+static void
+nr_ce(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	unsigned char *s;			/* string poiner */
+
+	if ((s = Field(2, line, 0)) != NULL)
+		Centering = atoi((char *)s);
+	else
+		Centering = 1;
+}
+
+
+/*
+ * Diversion on and off - "^[.']di"
+ */
+
+static void
+nr_di(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	Pass3(DOBREAK, (unsigned char *)"flush", NULL, 0);
+	Divert ^= 1;
+}
+
+
+/*
+ * Define string - "^[.']ds"
+ */
+
+static void
+nr_ds(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	unsigned char buf[MAXLINE];	/* temporary buffer */
+	unsigned char nm[4], nm1[4];	/* name buffers */
+	unsigned char *s1, *s2, *s3,	/* temporary string pointers */
+		       *s4;
+
+	if (Asmname(&line[3], nm) == 0) {
+		Error(WARN, LINE, " no name", NULL);
+		return;
+	}
+	s1 = Field(3, line, 0);
+	s2 = Findstr(nm, s1, 1);
+	while (*s2 == '\\' && *(s2 + 1) == '*') {
+		s2++;
+		s3 = Asmcode(&s2, nm1);
+		s2 = Findstr(nm1, NULL, 0);
+	}
+	if (Hdft) {
+
+	/*
+	 * Look for names LH, LF, CH, CF, RH, RF.
+	 */
+		if ((nm[0]=='L' || nm[0]=='C' || nm[0]=='R')
+		&&  (nm[1]=='F' || nm[1]=='H')) {
+			(void) sprintf((char *)buf, "%s", (char *)nm);
+			Pass3(NOBREAK, buf, s2, 0);
+		}
+	}
+}
+
+
+
+/*
+ * Fill - "^[.']fi"
+ */
+
+static void
+nr_fi(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	Fill = 1;
+	Pass3(brk, (unsigned char *)"flush", NULL, 0);
+}
+
+
+/*
+ * Flush - "^[.']fl"
+ */
+
+static void
+nr_fl(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	Pass3(brk, (unsigned char *)"flush", NULL, 0);
+}
+
+
+/*
+ * Font - "^[.']ft <font_name>"
+ */
+
+static void
+nr_ft(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	int i;				/* temporary index */
+
+	if (line[3] == '\0' || line[4] == '\0')
+		line[4] = 'P';
+	if (line[4] == 'P') {
+		Font[0] = Prevfont;
+		return;
+	}
+	for (i = 0; Fcode[i].nm; i++) {
+		if (Fcode[i].nm == line[4])
+		break;
+	}
+	if (Fcode[i].status == '\0') {
+		Error(WARN, LINE, " bad font code", NULL);
+		return;
+	}
+	Prevfont = Font[0];
+	Font[0] = line[4];
+}
+
+
+/*
+ * Input trap - "^[.']it [1 <request>]"
+ */
+
+static void
+nr_it(line, brk)
+	unsigned char *line;
+	int brk;
+
+{
+	unsigned char buf[MAXLINE];	/* temporary buffer */
+	int i;				/* temporary index */
+	unsigned char *s1, *s2;		/* temporary string pointers */
+
+	if ((s1 = Field(2, line, 0)) == NULL) {
+		Free(&Aftnxt);
+		return;
+	}
+	if ((i = atoi((char *)s1)) != 1) {
+		Error(WARN, LINE, " first .it arg must be 1", NULL);
+		return;
+	}
+	if ((s2 = Field(3, line, 0)) == NULL)
+		Free(&Aftnxt);
+	else {
+		(void) sprintf((char *)buf, "%s,%s",
+			(Aftnxt == NULL) ? "" : (char *)Aftnxt,
+			(char *)s2);
+		Free(&Aftnxt);
+		Aftnxt = Newstr(buf);
+	}
+}
+
+
+/*
+ * Comment - "^[.']\\" - do nothing
+ *
+ * Debug - "^[.']\^d" - do nothing
+ *
+ * Finalization - "[.']\^e" - do nothing
+ *
+ * Error file - "^[.']\^x <name>" - do nothing
+ *
+ * "^[.']i0", "^[.']lg" and "^[.']li" - do nothing
+ *
+ * Point size - "^[.']ps" - do nothing
+ *
+ * Vertical spacing - "^[.']vs" - do nothing
+ *
+ */
+
+static void
+nr_nil(line, brk)
+	unsigned char *line;
+	int brk;
+{
+}
+
+
+/*
+ * No adjust "^[.']na"
+ */
+
+static void
+nr_na(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	Pass3(NOBREAK, (unsigned char *)"left", NULL, 0);
+}
+
+
+/*
+ * No fill - "^[.']nf"
+ */
+
+static void
+nr_nf(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	Fill = 0;
+	Pass3(brk, (unsigned char *)"flush", NULL, 0);
+}
+
+
+/*
+ * No space - "^[.']ns"
+ */
+
+static void
+nr_ns(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	Pass3(NOBREAK, (unsigned char *)"nospace", NULL, 0);
+}
+
+
+/*
+ * Remove macro or string - "^[.']rm"
+ */
+
+static void
+nr_rm(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	int i;				/* temporary index */
+	unsigned char nm[4];		/* name buffer */
+
+	if (Asmname(&line[3], nm) == 0) {
+		Error(WARN, LINE, " no name", NULL);
+		return;
+	}
+	if ((i = Findmacro(nm, 0)) >= 0) {
+		Delmacro(i);
+		return;
+			}
+	(void) Findstr(nm, NULL, 0);
+		if (Sx >= 0) {
+			Delstr(Sx);
+			return;
+	}
+	Error(WARN, LINE, " no macro/string", NULL);
+}
+
+
+/*
+ * Rename macro or string - "^[.']rn"
+ */
+
+static void
+nr_rn(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	int i, j;			/* temporary indexes */
+	unsigned char nm[4], nm1[4];	/* name buffers */
+	unsigned char *s1;		/* temporary string pointer */
+
+	if ((s1 = Field(2, line, 0)) == NULL ||  Asmname(s1, nm) == 0) {
+		Error(WARN, LINE, " no name", NULL);
+		return;
+	}
+	if ((s1 = Field(3, line, 0)) == NULL ||  Asmname(s1, nm1) == 0) {
+		Error(WARN, LINE, " no new name", NULL);
+		return;
+	}
+	if ((i = Findmacro(nm, 0)) >= 0) {
+		if ((j = Findmacro(nm1, 0)) >= 0)
+			Delmacro(j);
+		j = Findmacro(nm1, 1);
+		Macrotab[j].bx = Macrotab[i].bx;
+		Macrotab[i].bx = -1;
+		Macrotab[j].ct = Macrotab[i].ct;
+		Macrotab[i].ct = 0;
+		Delmacro(i);
+		return;
+	}
+	(void) Findstr(nm, NULL, 0);
+	if ((i = Sx) >= 0) {
+		(void) Findstr(nm1, Str[i].str, 1);
+		Delstr(i);
+		return;
+	}
+	if (Findmacro(nm1, 0) < 0)
+		(void) Findmacro(nm1, 1);
+}
+
+
+/*
+ * Remove register - "^[.']rr"
+ */
+
+static void
+nr_rr(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	int i;				/* temporary index */
+	unsigned char nm[4];		/* name buffer */
+
+	if (Asmname(&line[3], nm) == 0) {
+		Error(WARN, LINE, " no name", NULL);
+		return;
+	}
+	if ((i = Findnum(nm, 0, 0)) < 0) {
+		Error(WARN, LINE, " no register", NULL);
+		return;
+	}
+	Delnum(i);
+}
+
+
+/*
+ * Resume space - "^[.']rs"
+ */
+
+static void
+nr_rs(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	Pass3(NOBREAK, (unsigned char *)"yesspace", NULL, 0);
+}
+
+
+/*
+ * Message - "^[.']tm"
+ */
+
+static void
+nr_tm(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	Pass3(MESSAGE, Inname, (line[3] == ' ') ? &line[4] : &line[3], NR);
+}
+
+
+/*
+ * Translate - "^[.']tr abcd..."
+ */
+
+static void
+nr_tr(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	unsigned char buf[MAXLINE];	/* temporary buffer */
+	int i, j;			/* temporary indexes */
+	unsigned char nm[4], nm1[4];	/* name buffers */
+	unsigned char *s1, *s2;		/* temporary string pointers */
+	int trin, trout;		/* types: 0 = char; 1 = named char */
+	unsigned char xbuf[MAXLINE];	/* temporary buffer */
+
+	if (line[3] != ' ') {
+		Error(WARN, LINE, " unknown translation", NULL);
+		return;
+	}
+	for (s1 = &line[4]; *s1;) {
+	    nm[1] = nm[2] = '\0';
+	    s2 = s1 + 1;
+	/*
+	 * Assemble the input value.
+	 */
+	    if (*s1 == '\\' && (*s2 == '*' || *s2 == '(')) {
+		if (*s2 == '(') {
+	    /*
+	     * Input is named character -- "\(xx".
+	     */
+		    trin = 1;
+		    s1 = s2 + 1;
+		    if ((nm[0] = *s1) != '\0') {
+			s1++;
+			if ((nm[1] = *s1) != '\0')
+			    s1++;
+		    }
+		} else {
+	    /*
+	     * Input is interpolated string -- "\*x" or "\*(xx".
+	     */
+		    s1 = Asmcode(&s2, nm);
+		    if (*s1)
+			s1++;
+		    s2 = Findstr(nm, NULL, 0);
+		    if (*s2 != '\0') {
+			if ((strlen((char *)s2) + strlen((char *)s1) + 1)
+			>= MAXLINE)
+			    Error(WARN, LINE, " string too long: ", (char *)nm);
+			else {
+			    (void) sprintf((char *)buf, "%s%s",
+				(char *)s2, (char *)s1);
+			    (void) strcpy((char *)xbuf, (char *)buf);
+			    s1 = xbuf;
+			}
+		    }
+		    continue;
+		}
+	    } else {
+
+	    /*
+	     * Input is a simple character.
+	     */
+		trin = 0;
+		if ((nm[0] = *s1) != '\0')
+		    s1++;
+	    }
+	/*
+	 * Assemble the output value.
+	 */
+
+assemble_output:
+	    nm1[1] = nm1[2] = '\0';
+	    if (*s1 == '\0') {
+
+	    /*
+	     * Supply a space if there is no output character.
+	     */
+		trout = 0;
+		nm1[0] = ' ';
+	    } else {
+		s2 = s1 + 1;
+		if (*s1 == '\\' && (*s2 == '(' || *s2 == '*')) {
+		    if (*s2 == '(') {
+		/*
+		 * The output is a named character -- "\(xx".
+		 */
+			trout = 1;
+			s1 = s2 + 1;
+			if ((nm1[0] = *s1) != '\0') {
+			    s1++;
+			    if ((nm1[1] = *s1) != '\0')
+				s1++;
+			}
+		    } else {
+		/*
+		 * The output is an interpolated string -- * "\*x" or "\*(xx".
+		 */
+			s1 = Asmcode(&s2, nm1);
+			if (*s1)
+			    s1++;
+			s2 = Findstr(nm1, NULL, 0);
+			if (*s2 != '\0') {
+		    /*
+		     * Interpolate a string value.
+		     */
+			    if ((strlen((char *)s2) + strlen((char *)s1) + 1)
+			    >= MAXLINE)
+				Error(WARN, LINE, " string too long: ",
+				    (char *)nm);
+			    else {
+				(void) sprintf((char *)buf, "%s%s", (char *)s2,
+				    (char *)s1);
+				(void) strcpy((char *)xbuf, (char *)buf);
+			        s1 = xbuf;
+			    }
+			}
+			goto assemble_output;
+		    }
+		} else {
+		    trout = 0;
+		    if ((nm1[0] = *s1) != '0')
+			s1++;
+		    else
+			nm1[0] = ' ';
+		}
+	    }
+	/*
+	 * Do the translation.
+	 */
+	    switch (trin) {
+
+	    case 0:			/* simple char */
+		switch (trout) {
+
+		case 0:			/* to simple char */
+		    Trtbl[(int)nm[0]] = nm1[0];
+		    break;
+		case 1:			/* to named char */
+		    if ((i = Findchar(nm1, 0, NULL, 0)) < 0
+		    ||  strlen((char *)Schar[i].str) != 1)
+			Error(WARN, LINE, " bad named character: ",
+			    (char *)nm1);
+		    else
+			Trtbl[(int)nm[0]] = *(Schar[i].str);
+		    break;
+		}
+		break;
+	    case 1:			/* named char */
+		if ((i = Findchar(nm, 0, NULL, 0)) < 0)
+		    Error(WARN, LINE, " unknown named character: ", (char *)nm);
+		else {
+		    switch (trout) {
+
+		    case 0:		/* to simple char */
+			Free(&Schar[i].str);
+			Schar[i].str = Newstr(nm1);
+			Schar[i].len = 1;
+			break;
+		    case 1:		/* to named char */
+			if ((j = Findchar(nm1, 0, NULL, 0)) < 0)
+			    Error(WARN, LINE, " unknown named character: ",
+				(char *)nm1);
+			else
+			    (void) Findchar(nm, Schar[j].len, Schar[j].str, 1);
+			break;
+		    }
+		}
+		break;
+	    }
+	}
+}
+
+
+/*
+ * Initialization - "^[.']\^b (fh|HF|NH) [01]"
+ *
+ * fh = first page header status
+ * HF = header/footer status
+ * NH = initialize number headers
+ */
+
+static void
+nr_Ub(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	int i;				/* temporary index */
+	unsigned char *s1, *s2;		/* temporary string pointers */
+
+	if ((s1 = Field(2, line, 0)) == NULL)
+		return;
+	if ((s2 = Field(3, line, 0)) == NULL)
+		i = 0;
+	else
+		i = atoi((char *)s2);
+	if (s1[0] == 'f' && s1[1] == 'h')
+		Pass3(NOBREAK, (unsigned char *)"fph", NULL, i);
+	else if (s1[0] == 'H' && s1[1] == 'F')
+		Hdft = i;
+	else if (s1[0] == 'N' && s1[1] == 'H') {
+		for (i = 0; i < MAXNHNR; i++)
+			Nhnr[i] = 0;
+	} else
+		Error(WARN, LINE, " unknown initialization", NULL);
+}
+
+
+/*
+ * Character definitions - "^[.']\^c"
+ */
+
+static void
+nr_Uc(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	unsigned char buf[MAXLINE];	/* temporary buffer */
+	int i;				/* temporary index */
+	unsigned char *s1, *s2, *s3,	/* temporary string pointers */
+		      *s4, *s5;
+
+	s2 = Field(2, line, 0);
+	i = atoi((char *)Field(3, line, 0));
+	s4 = Field(4, line, 0);
+	if (i < 0 || i > MAXLINE/2 || *s2 == '\0') {
+		Error(WARN, LINE, " bad character definition", NULL);
+		return;
+	}
+	if (s4 == NULL)
+		s4 = (unsigned char *)"";
+	else if (*s4 == '"')
+		s4++;
+	s1 = buf;
+	while ((s5 = (unsigned char *)strchr((char *)s4, '\\')) != NULL) {
+		while (s5 > s4)
+			*s1++ = *s4++;
+		s4 = ++s5;
+		if (*s5 == '\\')
+			*s1++ = '\\';
+		else if (*s5 == 'b')
+			*s1++ = '\b';
+		if (*s4)
+			s4++;
+	}
+	while (*s1++ = *s4++)
+		;
+	if (*s2 == 'h' && *(s2+1) == 'y')
+		(void) Findhy(buf, i, 1);
+	else
+		(void) Findchar(s2, i, buf, 1);
+}
+
+
+/*
+ * Font is OK - "[.']\^f <font_name_character>"
+ */
+
+static void
+nr_Uf(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	int i;				/* temporary index */
+
+	if (line[3] != '\0' && line[4] != '\0') {
+		for (i = 0; Fcode[i].nm; i++) {
+			if (line[4] == Fcode[i].nm) {
+				Fcode[i].status = '1';
+				return;
+			}
+		}
+	}
+	Error(WARN, LINE, " unknown font", NULL);
+}
+
+
+/*
+ * Resolutions - "[.']\^r cpi horizontal vertical"
+ */
+
+static void
+nr_Ur(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	unsigned char buf[MAXLINE];	/* temporary buffer */
+	int i, j;			/* temporary indexes */
+	double tval;			/* temporary value */
+
+	if ((i = atoi((char *)Field(3, line, 0))) <= 0
+	||  (j = atoi((char *)Field(4, line, 0))) <= 0) {
+		Error(WARN, LINE, " bad cpi resolutions", NULL);
+		return;
+	}
+	tval = (double) (240.0 / (double) i);
+	if (Findscale((int)'m', tval, 1) < 0)
+		Error(FATAL, LINE, " missing Scal['m']", NULL);
+	Scalen = tval;
+	if (Scalen <= 0.0) {
+		(void) sprintf((char *)buf, " bad Scale['n'] (%f)", Scalen);
+		Error(FATAL, LINE, (char *)buf, NULL);
+	}
+	if (Findscale((int)'n', tval, 1) < 0)
+		Error(FATAL, LINE, " missing Scale['n']", NULL);
+	Scalev = (double) (240.0 / (double) j);
+	if (Scalev <= 0.0) {
+		(void) sprintf((char *)buf, " bad Scale['v'] (%f)", Scalen);
+		Error(FATAL, LINE, (char *)buf, NULL);
+	}
+	if (Findscale((int)'v', Scalev, 1) < 0)
+		Error(FATAL, LINE, " missing Scale['v']", NULL);
+}
+
+
+/*
+ * Set line number and file name - "^[.']\^# <number> <file>"
+ *
+ * Lock line number and file name - "^[.']\^= <number> <file>"
+ */
+
+static void
+nr_UL(line, brk)
+	unsigned char *line;
+	int brk;
+{
+	unsigned char *s1;		/* temporary string pointer */
+
+	if ((s1 = Field(2, line, 0)) != NULL)
+		P2il = atoi((char *)s1) - 1;
+	else
+		P2il = 0;
+	Lockil = (line[2] == '#') ? 0 : 1;
+	Free(&P2name);
+	if (Field(3, line, 1) != NULL) {
+		P2name = F;
+		F = NULL;
+	} else
+		P2name = NULL;
+}
Index: /trunk/minix/commands/cawf/output.c
===================================================================
--- /trunk/minix/commands/cawf/output.c	(revision 9)
+++ /trunk/minix/commands/cawf/output.c	(revision 9)
@@ -0,0 +1,96 @@
+/*
+ *	output-c - output support functions for cawf(1)
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+#include "cawf.h"
+
+
+/*
+ * LenprtHF(s, p, t) - get length of print header or footer with page number
+ *		       interpolation
+ */
+
+LenprtHF(s, p, t)
+	unsigned char *s;		/* header/footer string */
+	int p;				/* page number */
+	int t;				/* type: 0 = get interpolated length
+					 *	 1 = print */
+{
+	unsigned char buf[10];		/* buffer for page number */
+	int len;			/* line length */
+	unsigned char *s1;		/* temporary string pointer */
+	
+	if (s == NULL)
+		return(0);
+	for (len = 0; *s && *s != '%'; s++) {
+		len++;
+		if (t)
+			Charput((int)*s);
+	}
+	if (*s) {
+		(void) sprintf((char *)buf, "%d", p);
+		for (s1 = buf; *s1; s1++) {
+			len++;
+			if (t)
+				Charput((int)*s1);
+		}
+		for (s++; *s; s++) {
+			len++;
+			if (t)
+				Charput((int)*s);
+		}
+	}
+	return(len);
+}
+
+
+/*
+ * Charput(s) - put a character to output, subject to diversion
+ */
+
+void
+Charput(c)
+	int c;			/* character to put */
+{
+	if (Divert == 0)
+		putchar((unsigned char)c);
+}
+
+
+/*
+ * Stringput(s) - put a string to output, subject to diversion
+ */
+
+void
+Stringput(s)
+	unsigned char *s;	/* string to put */
+{
+	if (Divert == 0)
+		fputs((char *)s, stdout);
+}
Index: /trunk/minix/commands/cawf/pass2.c
===================================================================
--- /trunk/minix/commands/cawf/pass2.c	(revision 9)
+++ /trunk/minix/commands/cawf/pass2.c	(revision 9)
@@ -0,0 +1,842 @@
+/*
+ *	pass2.c - cawf(1) pass 2 function
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+#include "cawf.h"
+#include <ctype.h>
+
+/*
+ * Pass2(line) - process the nroff requests in a line and break
+ *		 text into words for pass 3
+ */
+
+void
+Pass2(line)
+	unsigned char *line;
+{
+	int brk;			/* request break status */
+	unsigned char buf[MAXLINE];	/* working buffer */
+	unsigned char c;		/* character buffer */
+	double d;			/* temporary double */
+	double exscale;			/* expression scaling factor */
+	double expr[MAXEXP];            /* expressions */
+	unsigned char exsign[MAXEXP];	/* expression signs */
+	int i, j;			/* temporary indexes */
+	int inword;			/* word processing status */
+	int nexpr;			/* number of expressions */
+	unsigned char nm[4], nm1[4];	/* names */
+	int nsp;			/* number of spaces */
+	unsigned char op;		/* expression term operator */
+	unsigned char opstack[MAXSP];	/* expression operation stack */
+	unsigned char period;		/* end of word status */
+	unsigned char *s1, *s2, *s3;	/* temporary string pointers */
+	double sexpr[MAXEXP];           /* signed expressions */
+	int sp;				/* expression stack pointer */
+	unsigned char ssign;		/* expression's starting sign */
+	int tabpos;			/* tab position */
+	double tscale;			/* term scaling factor */
+	double tval;			/* term value */
+	double val;			/* term value */
+	double valstack[MAXSP];		/* expression value stack */
+	unsigned char xbuf[MAXLINE];	/* expansion buffer */
+
+	if (line == NULL) {
+    /*
+     * End of macro expansion.
+     */
+		Pass3(DOBREAK, (unsigned char *)"need", NULL, 999);
+		return;
+	}
+    /*
+     * Adjust line number.
+     */
+	if (Lockil == 0)
+		P2il++;
+    /*
+     * Empty line - "^[ \t]*$" or "^\\\"".
+     */
+	if (regexec(Pat[6].pat, line)
+	||  strncmp((char *)line, "\\\"", 2) == 0) {
+		Pass3(DOBREAK, (unsigned char *)"space", NULL, 0);
+		return;
+	}
+    /*
+     * Line begins with white space.
+     */
+	if (*line == ' ' || *line == '\t') {
+		Pass3(DOBREAK, (unsigned char *)"flush", NULL, 0);
+		Pass3(0, (unsigned char *)"", NULL, 0);
+	}
+	if (*line != '.' && *line != '\'') {
+    /*
+     * Line contains text (not an nroff request).
+     */
+		if (Font[0] == 'R' && Backc == 0 && Aftnxt == NULL
+		&&  regexec(Pat[7].pat, line) == 0) {
+		    /*
+		     * The font is Roman, there is no "\\c" or "after next"
+		     * trap pending and and the line has no '\\', '\t', '-',
+		     * or "  "  (regular expression "\\|\t|-|  ").
+		     *
+		     * Output each word of the line as "<length> <word>".
+		     */
+			for (s1 = line;;) {
+				while (*s1 && *s1 == ' ')
+					s1++;
+				if (*s1 == '\0')
+					break;
+				for (s2 = s1, s3 = buf; *s2 && *s2 != ' ';)
+				    *s3++ = Trtbl[(int)*s2++];
+				*s3 = '\0';
+				Pass3((s2 - s1), buf, NULL, 0);
+				s1 = *s2 ? ++s2 : s2;
+			}
+		    /*
+		     * Line terminates with punctuation and optional
+		     * bracketing (regular expression "[.!?:][\])'\"*]*$").
+		     */
+			if (regexec(Pat[8].pat, line))
+				Pass3(NOBREAK, (unsigned char *)"gap", NULL, 2);
+			if (Centering > 0) {
+				Pass3(DOBREAK,(unsigned char *)"center", NULL,
+					0);
+				Centering--;
+			} else if (Fill == 0)
+				Pass3(DOBREAK, (unsigned char *)"flush", NULL,
+					0);
+			return;
+		}
+	    /*
+	     * Line must be scanned a character at a time.
+	     */
+		inword = nsp = tabpos = 0;
+		period = '\0';
+		for (s1 = line;; s1++) {
+		    /*
+		     * Space or TAB causes state transition.
+		     */
+			if (*s1 == '\0' || *s1 == ' ' || *s1 == '\t') {
+				if (inword) {
+					if (!Backc) {
+						Endword();
+						Pass3(Wordl, Word, NULL, 0);
+						if (Uhyph) {
+						  Pass3(NOBREAK,
+						    (unsigned char *)"nohyphen",
+						    NULL, 0);
+						}
+					}
+					inword = 0;
+					nsp = 0;
+				}
+				if (*s1 == '\0')
+					break;
+			} else {
+				if (inword == 0) {
+					if (Backc == 0) {
+						Wordl = Wordx = 0;
+						Uhyph = 0;
+					}
+					Backc = 0;
+					inword = 1;
+					if (nsp > 1) {
+						Pass3(NOBREAK,
+						    (unsigned char *)"gap",
+						    NULL, nsp);
+					}
+				}
+			}
+		    /*
+		     * Process a character.
+		     */
+			switch (*s1) {
+		    /*
+		     * Space
+		     */
+	     		case ' ':
+				nsp++;
+				period = '\0';
+				break;
+		    /*
+		     * TAB
+		     */
+	     		case '\t':
+				tabpos++;
+				if (tabpos <= Ntabs) {
+					Pass3(NOBREAK,
+					    (unsigned char *)"tabto", NULL,
+					    Tabs[tabpos-1]);
+				}
+				nsp = 0;
+				period = '\0';
+				break;
+		    /*
+		     * Hyphen if word is being assembled
+		     */
+			case '-':
+				if (Wordl <= 0)
+				    goto ordinary_char;
+				if ((i = Findhy(NULL, 0, 0)) < 0) {
+				    Error(WARN, LINE, " no hyphen for font ",
+					(char *)Font);
+				    return;
+				}
+				Endword();
+				Pass3(Wordl, Word, NULL, Hychar[i].len);
+				Pass3(NOBREAK, (unsigned char *)"userhyphen",
+				    Hychar[i].str, Hychar[i].len);
+				Wordl = Wordx = 0;
+				period = '\0';
+				Uhyph = 1;
+				break;
+		    /*
+		     * Backslash
+		     */
+			case '\\':
+				s1++;
+				switch(*s1) {
+			    /*
+			     * Comment - "\\\""
+			     */
+				case '"':
+					while (*(s1+1))
+						s1++;
+					break;
+			    /*
+			     * Change font - "\\fN"
+			     */
+				case 'f':
+					s1 = Asmcode(&s1, nm);
+					if (nm[0] == 'P') {
+					    Font[0] = Prevfont;
+					    break;
+					}
+					for (i = 0; Fcode[i].nm; i++) {
+					    if (Fcode[i].nm == nm[0])
+						break;
+					}
+					if (Fcode[i].nm == '\0'
+					||  nm[1] != '\0') {
+					    Error(WARN, LINE, " unknown font ",
+					    	(char *)nm);
+					    break;
+					}
+					if (Fcode[i].status != '1') {
+					    Error(WARN, LINE,
+						" font undefined ", (char *)nm);
+					    break;
+					} else {
+					    Prevfont = Font[0];
+					    Font[0] = nm[0];
+					}
+					break;
+			    /*
+			     * Positive horizontal motion - "\\h\\n(NN" or
+			     * "\\h\\nN"
+			     */
+				case 'h':
+					if (s1[1] != '\\' || s1[2] != 'n') {
+					    Error(WARN, LINE,
+						" no \\n after \\h", NULL);
+					    break;
+					}
+					s1 +=2;
+					s1 = Asmcode(&s1, nm);
+					if ((i = Findnum(nm, 0, 0)) < 0)
+						goto unknown_num;
+					if ((j = Numb[i].val) < 0) {
+					    Error(WARN, LINE, " \\h < 0 ",
+					    NULL);
+					    break;
+					}
+					if (j == 0)
+						break;
+					if ((strlen((char *)s1+1) + j + 1)
+					>=  MAXLINE)
+						goto line_too_long;
+					for (s2 = &xbuf[1]; j; j--)
+						*s2++ = ' ';
+					(void) strcpy((char *)s2, (char *)s1+1);
+					s1 = xbuf;
+					break;
+			    /*
+			     * Save current position in register if "\\k<reg>"
+			     */
+			        case 'k':
+					s1 = Asmcode(&s1, nm);
+					if ((i = Findnum(nm, 0, 0)) < 0)
+					    i = Findnum(nm, 0, 1);
+					Numb[i].val =
+						(int)((double)Outll * Scalen);
+					break;
+			    /*
+			     * Interpolate number - "\\n(NN" or "\\nN"
+			     */
+				case 'n':
+					s1 = Asmcode(&s1, nm);
+					if ((i = Findnum(nm, 0, 0)) < 0) {
+unknown_num:
+					    Error(WARN, LINE,
+					        " unknown number register ",
+						(char *)nm);
+					    break;
+					}
+					(void) sprintf((char *)buf, "%d",
+					    Numb[i].val);
+					if ((strlen((char *)buf)
+					   + strlen((char *)s1+1) + 1)
+					>=  MAXLINE) {
+line_too_long:
+					    Error(WARN, LINE, " line too long",
+					        NULL);
+					    break;
+					}
+					(void) sprintf((char *)buf, "%d%s",
+					    Numb[i].val, (char *)s1+1);
+					(void) strcpy((char *)&xbuf[1],
+						(char *)buf);
+				        s1 = xbuf;
+					break;
+			    /*
+			     * Change size - "\\s[+-][0-9]" - NOP
+			     */
+				case 's':
+					s1++;
+					if (*s1 == '+' || *s1 == '-')
+						s1++;
+					while (*s1 && isdigit(*s1))
+						s1++;
+					s1--;
+					break;
+			    /*
+			     * Continue - "\\c"
+			     */
+				case 'c':
+					Backc = 1;
+					break;
+			    /*
+			     * Interpolate string - "\\*(NN" or "\\*N"
+			     */
+				case '*':
+					s1 = Asmcode(&s1, nm);
+					s2 = Findstr(nm, NULL, 0);
+					if (*s2 != '\0') {
+					    if ((strlen((char *)s2)
+					       + strlen((char *)s1+1) + 1)
+					    >=  MAXLINE)
+						goto line_too_long;
+					    (void) sprintf((char *)buf, "%s%s",
+						(char *)s2, (char *)s1+1);
+					    (void) strcpy((char *)&xbuf[1],
+						(char *)buf);
+					    s1 = xbuf;
+					}
+					break;
+			    /*
+			     * Discretionary hyphen - "\\%"
+			     */
+				case '%':
+					if (Wordl <= 0)
+					    break;
+					if ((i = Findhy(NULL, 0, 0)) < 0) {
+					    Error(WARN, LINE,
+					        " no hyphen for font ",
+						(char *)Font);
+					    break;
+					}
+					Endword();
+					Pass3(Wordl, Word, NULL, Hychar[i].len);
+					Pass3(NOBREAK,
+					    (unsigned char *) "hyphen",
+					    Hychar[i].str, Hychar[i].len);
+					Wordl = Wordx = 0;
+					Uhyph = 1;
+					break;
+			    /*
+			     * None of the above - may be special character
+			     * name.
+			     */
+				default:
+					s2 = s1--;
+					s1 = Asmcode(&s1, nm);
+					if ((i = Findchar(nm, 0, NULL, 0)) < 0){
+					    s1 = s2;
+					    goto ordinary_char;
+					}
+					if (strcmp((char *)nm, "em") == 0
+					&& Wordx > 0) {
+				    /*
+				     * "\\(em" is a special case when a word
+				     * has been assembled, because of
+				     * hyphenation.
+				     */
+					    Endword();
+					    Pass3(Wordl, Word, NULL,
+					        Schar[i].len);
+					    Pass3(NOBREAK,
+						(unsigned char *)"userhyphen",
+					        Schar[i].str, Schar[i].len);
+				            Wordl = Wordx = 0;
+					    period = '\0';
+					    Uhyph = 1;
+			 		}
+				    /*
+				     * Interpolate a special character
+				     */
+					if (Str2word(Schar[i].str,
+					    strlen((char *)Schar[i].str)) != 0)
+						return;
+				        Wordl += Schar[i].len;
+					period = '\0';
+				}
+				break;
+		    /*
+		     * Ordinary character
+		     */
+			default:
+ordinary_char:
+				if (Str2word(s1, 1) != 0)
+					return;
+				Wordl++;
+				if (*s1 == '.' || *s1 == '!'
+				||  *s1 == '?' || *s1 == ':')
+				    period = '.';
+				else if (period == '.') {
+				    nm[0] = *s1;
+				    nm[1] = '\0';
+				    if (regexec(Pat[13].pat, nm) == 0)
+					 period = '\0';
+				}
+			}
+		}
+	    /*
+	     * End of line processing
+	     */
+     		if (!Backc) {
+			if (period == '.')
+				Pass3(NOBREAK, (unsigned char *)"gap", NULL, 2);
+			if (Centering > 0) {
+				Pass3(DOBREAK, (unsigned char *)"center", NULL,
+				0);
+				Centering--;
+			} else if (!Fill)
+				Pass3(DOBREAK, (unsigned char *)"flush", NULL,
+				0);
+		}
+		if (Aftnxt == NULL)
+			return;
+		/* else fall through to process an "after next trap */
+	}
+    /*
+     * Special -man macro handling.
+     */
+	if (Marg == MANMACROS) {
+	    /*
+	     * A text line - "^[^.]" - is only processed when there is an
+	     * "after next" directive.
+	     */
+		if (*line != '.' && *line != '\'') {
+			if (Aftnxt != NULL) {
+				if (regexec(Pat[9].pat, Aftnxt))  /* ",fP" */
+					Font[0] = Prevfont;
+				if (regexec(Pat[16].pat, Aftnxt))  /* ",fR" */
+					Font[0] = 'R';
+				if (regexec(Pat[10].pat, Aftnxt))  /* ",tP" */
+					Pass3(DOBREAK,
+						(unsigned char *)"toindent",
+						NULL, 0);
+				Free(&Aftnxt);
+			}
+			return;
+		}
+	    /*
+	     * Special footer handling - "^.lF"
+	     */
+		if (line[1] == 'l' && line[2] == 'F') {
+			s1 = Findstr((unsigned char *)"by", NULL, 0);
+			s2 = Findstr((unsigned char *)"nb", NULL, 0);
+			if (*s1 == '\0' || *s2 == '\0')
+				(void) sprintf((char *)buf, "%s%s",
+					(char *)s1, (char *)s2);
+			else
+				(void) sprintf((char *)buf, "%s; %s",
+					(char *)s1, (char *)s2);
+			Pass3(NOBREAK, (unsigned char *)"LF", buf, 0);
+			return;
+		}
+	}
+    /*
+     * Special -ms macro handling.
+     */
+	if (Marg == MSMACROS) {
+	    /*
+	     * A text line - "^[^.]" - is only processed when there is an
+	     * "after next" directive.
+	     */
+		if (*line != '.' && *line != '\'') {
+			if (Aftnxt != NULL) {
+				if (regexec(Pat[10].pat, Aftnxt))  /* ",tP" */
+					Pass3(DOBREAK,
+						(unsigned char *)"toindent",
+						NULL, 0);
+				Free(&Aftnxt);
+			}
+			return;
+		}
+	    /*
+	     * Numbered headings - "^[.']nH"
+	     */
+		if (line[1] == 'n' && line[2] == 'H') {
+			s1 = Field(2, line, 0);
+			if (s1 != NULL) {
+				i = atoi((char *)s1) - 1;	
+				if (i < 0) {
+					for (j = 0; j < MAXNHNR; j++) {
+						Nhnr[j] = 0;
+					}
+					i = 0;
+				} else if (i >= MAXNHNR) {
+				    (void) sprintf((char *)buf,
+					" over NH limit (%d)", MAXNHNR);
+				    Error(WARN, LINE, (char *)buf, NULL);
+				}
+			} else
+				i = 0;
+			Nhnr[i]++;
+			for (j = i + 1; j < MAXNHNR; j++) {
+				Nhnr[j] = 0;
+			}
+			s1 = buf;
+			for (j = 0; j <= i; j++) {
+				(void) sprintf((char *)s1, "%d.", Nhnr[j]);
+				s1 = buf + strlen((char *)buf);
+			}
+			(void) Findstr((unsigned char *)"Nh", buf, 1);
+			return;
+		}
+	}
+    /*
+     * Remaining lines should begin with a '.' or '\'' unless an "after next"
+     * trap has failed.
+     */
+	if (*line != '.' && *line != '\'') {
+		if (Aftnxt != NULL)
+			Error(WARN, LINE, " failed .it: ", (char *)Aftnxt);
+		else
+			Error(WARN, LINE, " unrecognized line ", NULL);
+		return;
+	}
+	brk = (*line == '.') ? DOBREAK : NOBREAK;
+    /*
+     * Evaluate expressions for "^[.'](ta|ll|ls|in|ti|po|ne|sp|pl|nr)"
+     * Then process the requests.
+     */
+	if (regexec(Pat[11].pat, &line[1])) {
+	    /*
+	     * Establish default scale factor.
+	     */
+		if ((line[1] == 'n' && line[2] == 'e')
+		||  (line[1] == 's' && line[2] == 'p')
+		||  (line[1] == 'p' && line[2] == 'l'))
+			exscale = Scalev;
+		else if (line[1] == 'n' && line[2] == 'r')
+			exscale = Scaleu;
+		else
+			exscale = Scalen;
+	    /*
+	     * Determine starting argument.
+	     */
+		if (line[1] == 'n' && line[2] == 'r')
+			s1 = Field(2, &line[3], 0);
+		else
+			s1 = Field(1, &line[3], 0);
+	    /*
+	     * Evaluate expressions.
+	     */
+		for (nexpr = 0; s1 != NULL &&*s1 != '\0'; ) {
+			while (*s1 == ' ' || *s1 == '\t')
+				s1++;
+			if (*s1 == '+' || *s1 == '-')
+				ssign = *s1++;
+			else
+				ssign = '\0';
+		    /*
+		     * Process terms.
+		     */
+			val = 0.0;
+			sp = -1;
+			c = '+';
+			s1--;
+			while (c == '+' || c == '*' || c == '%'
+			||  c == ')' || c == '-' || c == '/') {
+			    op = c;
+			    s1++;
+			    tscale = exscale;
+			    tval = 0.0;
+			/*
+			 * Pop stack on right parenthesis.
+			 */
+			    if (op == ')') {
+				tval = val;
+				if (sp >= 0) {
+				    val = valstack[sp];
+				    op = opstack[sp];
+				    sp--;
+				} else {
+				    Error(WARN, LINE,
+					" expression stack underflow", NULL);
+				    return;
+				}
+				tscale = Scaleu;
+			/*
+			 * Push stack on left parenthesis.
+			 */
+			    } else if (*s1 == '(') {
+				sp++;
+				if (sp >= MAXSP) {
+				    Error(WARN, LINE,
+				       " expression stack overflow", NULL);
+				    return;
+				}
+				valstack[sp] = val;
+				opstack[sp] = op;
+				val = 0.0;
+				c = '+';
+				continue;
+			    } else if (*s1 == '\\') {
+			      s1++;
+			      switch(*s1) {
+			/*
+			 * "\\"" begins a comment.
+			 */
+			      case '"':
+				while (*s1)
+					s1++;
+				break;
+			/*
+			 * Crude width calculation for "\\w"
+			 */
+			      case 'w':
+				s2 = ++s1;
+				if (*s1) {
+				    s1++;
+				    while (*s1 && *s1 != *s2)
+					s1++;
+				    tval = (double) (s1 - s2 - 1) * Scalen;
+				    if (*s1)
+					s1++;
+				}
+				break;
+			/*
+			 * Interpolate number register if "\\n".
+			 */
+			      case 'n':
+				s1 = Asmcode(&s1, nm);
+				if ((i = Findnum(nm, 0, 0)) >= 0)
+				    tval = Numb[i].val;
+			        s1++;
+			     }
+			/*
+			 * Assemble numeric value.
+			 */
+			    } else if (*s1 == '.' || isdigit(*s1)) {
+				for (i = 0; isdigit(*s1) || *s1 == '.'; s1++) {
+				    if (*s1 == '.') {
+					i = 10;
+					continue;
+				    }
+				    d = (double) (*s1 - '0');
+				    if (i) {
+					tval = tval + (d / (double) i);
+					i = i * 10;
+				    } else
+					tval = (tval * 10.0) + d;
+				}
+			    } else {
+			/*
+			 * It's not an expression.  Ignore extra scale.
+			 */
+				if ((i = Findscale((int)*s1, 0.0, 0)) < 0) {
+				    (void) sprintf((char *)buf,
+					" \"%s\" isn't an expression",
+					(char *)s1);
+				    Error(WARN, LINE, (char *)buf, NULL);
+				}
+				s1++;
+			    }
+			/*
+			 * Add term to expression value.
+			 */
+			    if ((i = Findscale((int)*s1, 0.0, 0)) >= 0) {
+				tval *= Scale[i].val;
+				s1++;
+			    } else
+				tval *= tscale;
+			    switch (op) {
+			    case '+':
+				val += tval;
+				break;
+			    case '-':
+				val -= tval;
+				break;
+			    case '*':
+				val *= tval;
+				break;
+			    case '/':
+			    case '%':
+				i = (int) val;
+				j = (int) tval;
+				if (j == 0) {
+				    Error(WARN, LINE,
+					(*s1 == '/') ? "div" : "mod",
+				        " by 0");
+				    return;
+				}
+				if (op == '/')
+					val = (double) (i / j);
+				else
+					val = (double) (i % j);
+				break;
+			    }
+			    c = *s1;
+			}
+		    /*
+		     * Save expression value and sign.
+		     */
+			if (nexpr >= MAXEXP) {
+				(void) sprintf((char *)buf,
+				    " at expression limit of %d", MAXEXP);
+				Error(WARN, LINE, (char *)buf, NULL);
+				return;
+			}
+			exsign[nexpr] = ssign;
+			expr[nexpr] = val;
+			if (ssign == '-')
+				sexpr[nexpr] = -1.0 * val;
+			else
+				sexpr[nexpr] = val;
+			nexpr++;
+			while (*s1 == ' ' || *s1 == '\t')
+				s1++;
+		}
+	    /*
+	     * Set parameters "(ll|ls|in|ti|po|pl)"
+	     */
+		if (regexec(Pat[12].pat, &line[1])) {
+			nm[0] = line[1];
+			nm[1] = line[2];
+			if ((i = Findparms(nm)) < 0) {
+				Error(WARN, LINE,
+				    " can't find parameter register ",
+				    (char *)nm);
+				return;
+			}
+			if (nexpr == 0 || exscale == 0.0)
+				j = Parms[i].prev;
+			else if (exsign[0] == '\0'
+			     ||  (nm[0] == 't' && nm[1] == 'i'))
+				 j = (int)(sexpr[0] / exscale);
+			else
+				j = Parms[i].val + (int)(sexpr[0] / exscale);
+			Parms[i].prev = Parms[i].val;
+			Parms[i].val = j;
+			nm[0] = (nexpr) ? exsign[0] : '\0';     /* for .ti */
+			nm[1] = '\0';
+			Pass3(brk, (unsigned char *)Parms[i].cmd, nm, j);
+			return;
+		}
+		if (line[1] == 'n') {
+			switch(line[2]) {
+	    /*
+	     * Need - "^[.']ne <expression>"
+	     */
+			case 'e':
+				if (nexpr && Scalev > 0.0)
+					i = (int) ((expr[0]/Scalev) + 0.99);
+				else
+					i = 0;
+				Pass3(DOBREAK, (unsigned char *)"need", NULL,
+					i);
+				return;
+	    /*
+	     * Number - "^[.']nr <name> <expression>"
+	     */
+			case 'r':
+				if ((s1 = Field(2, line, 0)) == NULL) {
+				    Error(WARN, LINE, " bad number register",
+				        NULL);
+				    return;
+				}
+				if ((i = Findnum(s1, 0, 0)) < 0)
+				    i = Findnum(s1, 0, 1);
+				if (nexpr < 1) {
+				    Numb[i].val = 0;
+				    return;
+				}
+				if (exsign[0] == '\0')
+				    Numb[i].val = (int) expr[0];
+				else
+				    Numb[i].val += (int) sexpr[0];
+				return;
+			}
+		}
+	    /*
+	     * Space - "^[.']sp <expression>"
+	     */
+		if (line[1] == 's' && line[2] == 'p') {
+			if (nexpr == 0)
+				i = 1;
+			else
+				i = (int)((expr[0] / Scalev) + 0.99);
+			while (i--)
+				Pass3(brk, (unsigned char *)"space", NULL, 0);
+			return;
+		}
+	    /*
+	     * Tab positions - "^[.']ta <pos1> <pos2> . . ."
+	     */
+     		if (line[1] == 't' && line[2] == 'a') {
+			tval = 0.0;
+			for (j = 0; j < nexpr; j++) {
+				if (exsign[j] == '\0')
+					tval = expr[j];
+				else
+					tval += sexpr[j];
+				Tabs[j] = (int) (tval / Scalen);
+			}
+			Ntabs = nexpr;
+			return;
+		}
+	}
+    /*
+     * Process all other nroff requests via Nreq().
+     */
+	(void) Nreq(line, brk);
+	return;
+}
Index: /trunk/minix/commands/cawf/pass3.c
===================================================================
--- /trunk/minix/commands/cawf/pass3.c	(revision 9)
+++ /trunk/minix/commands/cawf/pass3.c	(revision 9)
@@ -0,0 +1,614 @@
+/*
+ *	pass3.c - cawf(1) pass 3 function
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+#include "cawf.h"
+
+void
+Pass3(len, word, sarg, narg)
+	int len;			/* length (negative is special) */
+	unsigned char *word;		/* word */
+	unsigned char *sarg;		/* string argument */
+	int narg;			/* numeric argument */
+{
+	int addto;			/* spaces to add to all words */
+	int i, j, k;			/* temporary index */
+	unsigned char msg[MAXLINE];	/* message buffer */
+	int n;				/* temporary number */
+	unsigned char *s1;		/* temporary string pointer */
+	int sp = 0;			/* no-break spacing switch */
+	int sp_Outll;			/* sp-saved Outll */
+	char sp_Outln;			/* sp-saved Outln[0] */
+	int sp_Outlx;			/* sp-saved Outlx */
+	int sp_Padx;			/* sp-saved Padx */
+	int sp_Tind;			/* sp-saved Tind */
+	int wl;				/* real word length */
+	int xsp;			/* extra spaces to add */
+	int vsp;			/* vertical spacing status */
+
+	vsp = 0;
+	if (word != NULL)
+		wl = strlen((char *)word);
+    /*
+     * If not a special command, process a word.
+     */
+	if (len >= 0 && Outll < 0) {
+	/*
+	 * Enter first word.
+	 */
+		(void) strcpy((char *)Outln, (char *)word);
+		Outll = len;
+		Outlx = wl;
+		Padx = 0;
+	} else if (len >= 0
+	       && (Outll+Contlen+len+narg) <= (LL-Pgoff-Ind-Tind)) {
+	/*
+	 * The word fits, so enter it.
+	 */
+		if ((Contlen + len) > 0) {
+line_too_big:
+			if ((Outlx + Contlen + wl) >= MAXOLL) {
+				Error3(len, (char *)word, (char *)sarg, narg,
+					"output line too big");
+				return;
+			} else {
+				if (Contlen > 0 && Cont != NULL) {
+					if (Contlen == 1 && *Cont == ' ') {
+						Padchar[Padx++] = Outlx;
+						Outln[Outlx++] = ' ';
+					} else {
+					    (void) strcpy((char *)&Outln[Outlx],
+						(char *)Cont);
+					    Outlx += Contlen;
+					}
+				}
+				if (len > 0) {
+					(void) strcpy((char *)&Outln[Outlx],
+						(char *)word);
+					Outlx += wl;
+				}
+			}
+		}
+		Outll += Contlen + len;
+	} else if (len == NOBREAK || len == MESSAGE) {
+		/*
+		 * Do nothing (equivalent to break)
+		 */
+	} else if (len == DOBREAK && strcmp((char *)word, "need") == 0
+	       &&  (Nxtln + narg) < (Pglen + 1 - Botmarg)) {
+		/*
+		 * Do nothing, because there is room on the page.
+		 */
+	} else if (len == DOBREAK && strcmp((char *)word, "toindent") == 0
+	       &&  (Ind + Tind + Outll) < Ind) {
+	/*
+	 * Move to indent position with line - there is room.
+	 */
+		n = Ind - (Ind + Tind +Outll);
+		Outll += n;
+		if ((Outlx + n) >= MAXOLL)
+			goto line_too_big;
+		for (i = n; i; i--)
+			Outln[Outlx++] = ' ';
+		Padx = 0;
+		Free(&Cont);
+		Contlen = 0;
+	} else if (Outll >= 0
+	       || (len == DOBREAK && strcmp((char *)word, "need") == 0)) {
+	/*
+	 * A non-empty line or a "need" forces output.
+	 */
+		vsp = 0;
+
+print_line:
+		if (Nxtln == 1) {
+	    /*
+	     * We're at the top of the page, so issue the header.
+	     */
+			if (Thispg > 1)
+				Charput((int)'\f');
+			for (i = (Topmarg - 1)/2; i > 0; i--) {
+				Charput((int)'\n');
+				Nxtln++;
+			}
+		    /*
+		     * Print the page header, as required.
+		     */
+			if (Fph || Thispg > 1) {
+				i = LenprtHF(Hdc, Thispg, 0)
+				  + LenprtHF(Hdl, Thispg, 0)
+				  + LenprtHF(Hdr, Thispg, 0) + 2;
+				j = (LL - i - Pgoff) / 2 + 1;
+				n = LL - Pgoff - i - j + 2;
+				for (k = 0; k < Pgoff; k++)
+					Charput((int)' ');
+				if (Hdl)
+					LenprtHF(Hdl, Thispg, 1);
+				while (j-- > 0)
+					Charput((int)' ');
+				if (Hdc)
+					LenprtHF(Hdc, Thispg, 1);
+				while (n-- > 0)
+					Charput((int)' ');
+				if (Hdr)
+					LenprtHF(Hdr, Thispg, 1);
+				Charput((int)'\n');
+			} else
+				Charput((int)'\n');
+			Nxtln++;
+			while(Nxtln <= Topmarg) {
+				Charput((int)'\n');
+				Nxtln++;
+			}
+		}
+	    /*
+	     *  Add a trailing hyphen, if mecessary.
+	     */
+     		if (vsp == 0 && Eollen > 0 && Eol != NULL) {
+			i = strlen((char *)Eol);
+			if ((Outlx + i) >= MAXOLL)
+				goto line_too_big;
+			(void) strcpy((char *)&Outln[Outlx], (char *)Eol);
+			Outlx += i;
+			Outll += Eollen;
+		}
+	    /*
+	     * Trim trailing spaces from the output line.
+	     */
+     		while (Outlx > 0) {
+			if (Outln[Outlx - 1] != ' ')
+				break;
+			if (Padx > 0 && (Outlx - 1) == Padchar[Padx - 1])
+				Padx--;
+			Outlx--;
+			Outln[Outlx] = '\0';
+			Outll--;
+		}
+		if (Outlx == 0)
+			Charput((int)'\n');
+		else if (len == DOBREAK && strcmp((char *)word, "center") == 0)
+		    {
+		    /*
+		     * Center the output line.
+		     */
+			i = (LL - Pgoff - Outll) / 2;
+			if (i < 0)
+				i = 0;
+			for (j = (Pgoff + Ind + Tind + i); j; j--)
+				Charput((int)' ');
+			Stringput(Outln);
+			Charput((int)'\n');
+		} else if (Adj == LEFTADJ
+		       || (Adj == BOTHADJ && (len < 0 || Padx == 0))) {
+		    /*
+		     * No right margin adjustment - disabled, inappropriate
+		     * (line ended by break) or impossible.
+		     */
+			for (i = 0; i < (Pgoff + Ind + Tind); i++)
+				Charput((int)' ');
+			Stringput(Outln);
+			Charput((int)'\n');
+		} else if (Adj == BOTHADJ) {
+		    /*
+		     * Adjust right margin.
+		     */
+			for (i = 0; i < (Pgoff + Ind + Tind); i++)
+				Charput((int)' ');
+			i = LL - (Pgoff + Ind + Tind);
+			j = i - Outll;
+			addto = Padx ? (j / Padx) : 0;
+			xsp = j - (Padx * addto);
+			for (i = 0, s1 = Outln; i < Padx; i++) {
+				while (*s1 && (s1 - Outln) <= Padchar[i])
+					Charput((int)*s1++);
+				if (*s1 == '\0')
+					break;
+				j = addto;
+				if (Padfrom == PADLEFT) {
+					if (i < xsp)
+						j++;
+				} else if (i >= (Padx - xsp))
+					j++;
+				while (j-- > 0)
+					Charput((int)' ');
+			}
+			while (*s1)
+				Charput((int)*s1++);
+			Charput((int)'\n');
+			Padfrom = (Padfrom == PADLEFT) ? PADRIGHT : PADLEFT;
+		}
+	    /*
+	     * End of line housekeeping
+	     */
+		Nxtln++;
+		Outll = -1;
+		Outlx = 0;
+		Padx = 0;
+		Tind = 0;
+		Nospmode = 0;
+		if (vsp == 0 && len == DOBREAK
+		&&  strcmp((char *)word, "need") == 0) {
+		    /*
+		     * Break caused by "need" - satisfy it.
+		     */
+			while (Nxtln < (Pglen + 1 - Botmarg)) {
+				Charput((int)'\n');
+				Nxtln++;
+			}
+		}
+		if (Nxtln >= (Pglen + 1 - Botmarg)) {
+	    /*
+	     * Footer required
+	     */
+			for (i = (Botmarg - 1)/2; i > 0; i--) {
+				Charput((int)'\n');
+				Nxtln++;
+			}
+			i = LenprtHF(Ftl, Thispg, 0) + LenprtHF(Ftc, Thispg, 0)
+			  + LenprtHF(Ftr, Thispg, 0) + 2;
+			j = (LL - i - Pgoff) / 2 + 1;
+			n = LL - Pgoff - i - j + 2;
+			for (k = 0; k < Pgoff; k++)
+				Charput((int)' ');
+			if (Ftl)
+				LenprtHF(Ftl, Thispg, 1);
+			while (j-- > 0)
+				Charput((int)' ');
+			if (Ftc)
+				LenprtHF(Ftc, Thispg, 1);
+			while (n-- > 0)
+				Charput((int)' ');
+			if (Ftr)
+				LenprtHF(Ftr, Thispg, 1);
+			Charput((int)'\n');
+			Nxtln++;
+		/*
+		 * The last blank line on the page is suppressed to assist
+		 * printers that can't look ahead to the following FF.
+		 */
+			while (Nxtln < Pglen) {
+				Charput((int)'\n');
+				Nxtln++;
+			}
+			Nxtln = 1;
+			Thispg++;
+			Nospmode = 1;
+			Padfrom = PADRIGHT;
+		}
+	    /*
+	     * Initiate any extra vertical spacing.
+	     */
+		if (++vsp < Vspace)
+			goto print_line;
+	    /*
+	     * Save any input word that might have forced output.
+	     */
+		if (len >= 0) {
+			(void) strcpy((char *)Outln, (char *)word);
+			Outll = len;
+			Outlx = wl;
+			Padx = 0;
+		}
+	}
+    /*
+     * A break causes padding reversal.
+     */
+	if (len == DOBREAK)
+		Padfrom = PADRIGHT;
+	if (len >= 0 || strcmp((char *)word, "nohyphen") == 0) {
+    /*
+     * Reset continuation and hyphenation.
+     */
+		if (Contlen != 1 || Cont[0] != ' ') {
+			Free(&Cont);
+			Cont = Newstr((unsigned char *)" ");
+			Contlen = 1;
+		}
+		if (Eollen > 0) {
+			Free(&Eol);
+			Eollen = 0;
+		}
+		return;
+	}
+    /*
+     * Now post-process any special commands.
+     */
+	if (len == MESSAGE) {
+		Error3(len, (char *)word, (char *)sarg, narg, NULL);
+		return;
+	}
+
+	switch (*word) {
+
+	case 'b':				/* both */
+	    /*
+	     * Adjust on both margins.
+	     */
+		Adj = BOTHADJ;
+		return;
+
+	case 'c':				/* center */
+		return;
+
+	case 'e':				/* errsto */
+	    /*
+	     * "errsto" comes from awf.
+	     */
+		return;
+
+	case 'f':				/* flush and fph */
+		if (word[1] == 'l')
+			return;
+		else if (word[1] == 'p') {
+	    /*
+	     * First page header status
+	     */
+			Fph = narg;
+			return;
+		}
+		break;
+
+	case 'g':				/* gap */
+	    /*
+	     * Increase word gap.  (Space is not paddable.)
+	     */
+		if (Outll >= 0) {
+			if ((Outlx + narg - 1) >= MAXOLL)
+				goto line_too_big;
+			for (i = 0; i < (narg - 1); i++) {
+				Outln[Outlx++] = ' ';
+				Outll++;
+			}
+		}
+		return;
+
+	case 'h':				/* hyphen */
+	    /*
+	     * Set discretionary hyphen.
+	     */
+		Free(&Cont);
+		Contlen = 0;
+		Free(&Eol);
+		Eol = (sarg != NULL) ? Newstr(sarg) : NULL;
+		Eollen = narg;
+		return;
+
+	case 'i':				/* indent */
+	    /*
+	     * Set indentation.
+	     */
+		Ind = narg;
+		return;
+
+	case 'l':				/* left or linelen */
+		if (word[1] == 'e') {
+	    /*
+	     * Adjust on left margin.
+	     */
+			Adj = LEFTADJ;
+			return;
+		} else if (word[1] == 'i') {
+	    /*
+	     * Set line length.
+	     */
+			LL = narg;
+			return;
+		}
+		break;
+
+	case 'n':				/* need or nospace */
+		if (word[1] == 'e')
+			return;			/* need */
+		else if (word[1] == 'o') {
+	    /*
+	     * Set no space mode.
+	     */
+			Nospmode = 1;
+			return;
+		}
+		break;
+
+	case 'p':				/* pagelen or pageoffset */
+		if (strncmp((char *)&word[1], "age", 3) != 0)
+			break;
+		if (word[4] == 'l') {
+	    /*
+	     * Set page length.
+	     */
+			Pglen = narg;
+			return;
+		} else if (word[4] == 'o') {
+	    /*
+	     * Set page offset.
+	     */
+			Pgoff = narg;
+			return;
+		}
+		break;
+
+	case 's':				/* space */
+		if (sp) {
+
+		/*
+		 * Restore values after NOBREAK spacing ("^'sp").
+		 */
+			Outlx = sp_Outlx;
+			Outln[0] = sp_Outln;
+			Padx = sp_Padx;
+			Outll = sp_Outll;
+			Tind = sp_Tind;
+			return;
+		}
+		if (Nospmode == 0) {
+			if (len == NOBREAK) {
+		
+			/*
+			 * Set up for NOBREAK spacing.
+			 */
+				sp_Outlx = Outlx;
+				sp_Outln = Outln[0];
+				sp_Padx = Padx;
+				sp_Outll = Outll;
+				sp_Tind = Tind;
+				vsp = Vspace + 1;
+				sp = 1;
+			}
+		/*
+		 * Generate a blank line.
+		 */
+			Outlx = 0;
+			Outln[0] = '\0';
+			Padx = 0;
+			Outll = LL - 1;
+			if (sp)
+				goto print_line;
+		}
+		return;
+
+	case 't':				/* tabto, tempindent, or
+						 * toindent */
+		if (word[1] == 'a') {
+	    /*
+	     * Move to TAB stop.
+	     */
+			if (Outll < 0)
+				Outll = 0;
+			if ((n = narg - Outll) > 0) {
+				if ((Outlx + n) >= MAXOLL)
+					goto line_too_big;
+				Outll += n;
+				for (i = n; i > 0; i--)
+					Outln[Outlx++] = ' ';
+				Free(&Cont);
+				Contlen = 0;
+				Padx = 0;
+			}
+			return;
+		} else if (word[1] == 'e') {
+	    /*
+	     * Set temporary indentation.
+	     */
+			if (*sarg == '\0' && narg >= 0)
+				Tind = narg - Ind;
+			else
+				Tind = ((Ind + narg) >= 0) ? narg : -Ind;
+			return;
+		} else if (word[1] == 'o')
+			return;				/* toindent */
+		break;
+
+	case 'u':					/* userhyphen */
+	    /*
+	     * Set line length.
+	     */
+		Free(&Cont);
+		Free(&Eol);
+		Contlen = Eollen = narg;
+		Cont = (sarg == NULL) ? NULL : Newstr(sarg);
+		Eol = (sarg == NULL) ? NULL : Newstr(sarg);
+		return;
+
+	case 'v':					/* vspace */
+	    /*
+	     * Set vertical spacing.
+	     */
+		Vspace = (narg == 0) ? 1 : narg;
+		return;
+
+	case 'y':					/* yesspace */
+	    /*
+	     * Set space mode.
+	     */
+		Nospmode = 0;
+		return;
+	}				/* end of switch(*word) */
+    /*
+     * Locate header and footer defintions.
+     */
+	if (regexec(Pat[14].pat, word)) {
+		if (strcmp((char *)word, "LH") == 0) {
+		    /*
+		     * Left header
+		     */
+			Free(&Hdl);
+			if (sarg != NULL)
+				Hdl = Newstr(sarg);
+			return;
+		}
+		if (strcmp((char *)word, "CH") == 0) {
+		    /*
+		     * Center header
+		     */
+			Free(&Hdc);
+			if (sarg != NULL)
+				Hdc = Newstr(sarg);
+			return;
+		}
+		if (strcmp((char *)word, "RH") == 0) {
+		    /*
+		     * Right header
+		     */
+			Free(&Hdr);
+			if (sarg != NULL)
+				Hdr = Newstr(sarg);
+			return;
+		}
+		if (strcmp((char *)word, "LF") == 0) {
+		    /*
+		     * Left footer
+		     */
+			Free(&Ftl);
+			if (sarg != NULL)
+				Ftl = Newstr(sarg);
+			return;
+		}
+		if (strcmp((char *)word, "CF") == 0) {
+		    /*
+		     * Center footer
+		     */
+			Free(&Ftc);
+			if (sarg != NULL)
+				Ftc = Newstr(sarg);
+			return;
+		}
+		if (strcmp((char *)word, "RF") == 0) {
+		    /*
+		     * Right footer
+		     */
+			Free(&Ftr);
+			if (sarg != NULL)
+				Ftr = Newstr(sarg);
+			return;
+		}
+	}
+    /*
+     * Error on unknown arguments
+     */
+	Error3(len, (char *)word, (char *)sarg, narg, "unknown request");
+}
Index: /trunk/minix/commands/cawf/proto.h
===================================================================
--- /trunk/minix/commands/cawf/proto.h	(revision 9)
+++ /trunk/minix/commands/cawf/proto.h	(revision 9)
@@ -0,0 +1,117 @@
+/*
+ *	proto.h - function prototype definitions for cawf(1)
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+#include "ansi.h"
+
+#ifdef	UNIX
+# ifdef	USG
+#include <string.h>
+# else	/* not USG */
+#include <strings.h>
+# endif	/* USG */
+#else	/* not UNIX */
+#include <string.h>
+#endif	/* UNIX */
+
+/*
+ * The following conditional rat's nest intends to:
+ *
+ * for MS-DOS	#include <stdlib.h> and <malloc.h>.  <stdlib.h> exists in
+ *		MS-DOS so the STDLIB symbol should be defined and UNIX
+ *		shouldn't be.
+ *
+ * for Unix	#include <stdlib.h> if the STDLIB symbol is defined.  If
+ *		STDLIB isn't defined, define a prototype for getenv().
+ *		If the UNIX symbol is defined (and it should be) and if
+ *		the MALLOCH symbol is defined, #include <malloc.h>; else
+ *		define a prototype for malloc() if UNIX is defined and
+ *		MALLOCH isn't.  (The Unix <stdlib.h> usually defines the
+ *		malloc() prototype.)
+ *
+ * for ???	Define a prototype for getenv() and #include <malloc.h>
+ *		if neither STDLIB nor UNIX are defined.  (What system is
+ *		this?)
+ */
+
+#ifdef	STDLIB
+#include <stdlib.h>
+# ifndef	UNIX
+#include <malloc.h>
+# endif		/* UNIX */
+#else	/* not STDLIB */
+_PROTOTYPE(char *getenv,(char *name));
+# ifdef	UNIX
+#  ifdef	MALLOCH
+#include <malloc.h>
+#  else		/* not MALLOCH */
+_PROTOTYPE(char *malloc,(unsigned size));
+#  endif	/* MALLOCH */
+# else	/* not UNIX */
+#include <malloc.h>
+# endif	/* UNIX */
+#endif	/* STDLIB */
+
+_PROTOTYPE(unsigned char *Asmcode,(unsigned char **s, unsigned char *c));
+_PROTOTYPE(int Asmname,(unsigned char *s, unsigned char *c));
+_PROTOTYPE(void Charput,(int c));
+_PROTOTYPE(int Delmacro,(int mx));
+_PROTOTYPE(int Defdev,());
+_PROTOTYPE(void Delstr,(int sx));
+_PROTOTYPE(void Error,(int t, int l, char *s1, char *s2));
+_PROTOTYPE(void Error3,(int len, char *word, char *sarg, int narg, char *msg));
+_PROTOTYPE(void Expand,(unsigned char *line));
+_PROTOTYPE(void Delnum,(int nx));
+_PROTOTYPE(unsigned char *Field,(int n, unsigned char *p, int c));
+_PROTOTYPE(void Endword,());
+_PROTOTYPE(int Findchar,(unsigned char *nm, int l, unsigned char *s, int e));
+_PROTOTYPE(int Findhy,(unsigned char *s, int l, int e));
+_PROTOTYPE(int Findmacro,(unsigned char *p, int e));
+_PROTOTYPE(int Findnum,(unsigned char *n, int v, int e));
+_PROTOTYPE(int Findparms,(unsigned char *n));
+_PROTOTYPE(int Findscale,(int n, double v, int e));
+_PROTOTYPE(unsigned char *Findstr,(unsigned char *nm, unsigned char *s, int e));
+_PROTOTYPE(int getopt,(int argc, char **argv, char *opts));
+_PROTOTYPE(int LenprtHF,(unsigned char *s, int p, int t));
+_PROTOTYPE(int main,(int argc, char *argv[]));
+_PROTOTYPE(void Macro,(unsigned char *inp));
+_PROTOTYPE(void Nreq,(unsigned char *line, int brk));
+_PROTOTYPE(void Free,(unsigned char **p));
+_PROTOTYPE(unsigned char *Newstr,(unsigned char *s));
+_PROTOTYPE(void Pass2,(unsigned char *line));
+_PROTOTYPE(void Pass3,(int len, unsigned char *word, unsigned char *sarg, int narg));
+_PROTOTYPE(void regerror,(char *s));
+_PROTOTYPE(unsigned char *reg,(int paren, int *flagp));
+_PROTOTYPE(unsigned char *regatom,(int *flagp));
+_PROTOTYPE(unsigned char *regbranch,(int *flagp));
+_PROTOTYPE(regexp *regcomp,(char *exp));
+_PROTOTYPE(void regdump,(regexp *r));
+_PROTOTYPE(int regexec,(regexp *prog, unsigned char *string));
+_PROTOTYPE(void Stringput,(unsigned char *s));
+_PROTOTYPE(int Str2word,(unsigned char *s, int len));
Index: /trunk/minix/commands/cawf/regerror.c
===================================================================
--- /trunk/minix/commands/cawf/regerror.c	(revision 9)
+++ /trunk/minix/commands/cawf/regerror.c	(revision 9)
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include "regexp.h"
+#include "proto.h"
+
+void
+regerror(s)
+char *s;
+{
+#ifndef DOSPORT
+#ifdef ERRAVAIL
+	error("regexp: %s", s);
+#else
+	fprintf(stderr, "regexp(3): %s", s);
+	exit(1);
+#endif
+	/* NOTREACHED */
+#endif /* ifdef'd out for less's sake when reporting error inside less */
+}
Index: /trunk/minix/commands/cawf/regexp.c
===================================================================
--- /trunk/minix/commands/cawf/regexp.c	(revision 9)
+++ /trunk/minix/commands/cawf/regexp.c	(revision 9)
@@ -0,0 +1,1242 @@
+/*
+ * regcomp and regexec -- regsub and regerror are elsewhere
+ *
+ *	Copyright (c) 1986 by University of Toronto.
+ *	Written by Henry Spencer.  Not derived from licensed software.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to redistribute it freely,
+ *	subject to the following restrictions:
+ *
+ *	1. The author is not responsible for the consequences of use of
+ *		this software, no matter how awful, even if they arise
+ *		from defects in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *		by explicit claim or by omission.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *		be misrepresented as being the original software.
+ *
+ * Beware that some of this code is subtly aware of the way operator
+ * precedence is structured in regular expressions.  Serious changes in
+ * regular-expression syntax might require a total rethink.
+ */
+#include <stdio.h>
+#ifdef	UNIX
+#ifdef	USG
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#else
+#include <string.h>
+#endif
+#include "regexp.h"
+#include "regmagic.h"
+#include "proto.h"
+
+/*
+ * The "internal use only" fields in regexp.h are present to pass info from
+ * compile to execute that permits the execute phase to run lots faster on
+ * simple cases.  They are:
+ *
+ * regstart	char that must begin a match; '\0' if none obvious
+ * reganch	is the match anchored (at beginning-of-line only)?
+ * regmust	string (pointer into program) that match must include, or NULL
+ * regmlen	length of regmust string
+ *
+ * Regstart and reganch permit very fast decisions on suitable starting points
+ * for a match, cutting down the work a lot.  Regmust permits fast rejection
+ * of lines that cannot possibly match.  The regmust tests are costly enough
+ * that regcomp() supplies a regmust only if the r.e. contains something
+ * potentially expensive (at present, the only such thing detected is * or +
+ * at the start of the r.e., which can involve a lot of backup).  Regmlen is
+ * supplied because the test in regexec() needs it and regcomp() is computing
+ * it anyway.
+ */
+
+/*
+ * Structure for regexp "program".  This is essentially a linear encoding
+ * of a nondeterministic finite-state machine (aka syntax charts or
+ * "railroad normal form" in parsing technology).  Each node is an opcode
+ * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
+ * all nodes except BRANCH implement concatenation; a "next" pointer with
+ * a BRANCH on both ends of it is connecting two alternatives.  (Here we
+ * have one of the subtle syntax dependencies:  an individual BRANCH (as
+ * opposed to a collection of them) is never concatenated with anything
+ * because of operator precedence.)  The operand of some types of node is
+ * a literal string; for others, it is a node leading into a sub-FSM.  In
+ * particular, the operand of a BRANCH node is the first node of the branch.
+ * (NB this is *not* a tree structure:  the tail of the branch connects
+ * to the thing following the set of BRANCHes.)  The opcodes are:
+ */
+
+/* definition	number	opnd?	meaning */
+#define	END	0	/* no	End of program. */
+#define	BOL	1	/* no	Match "" at beginning of line. */
+#define	EOL	2	/* no	Match "" at end of line. */
+#define	ANY	3	/* no	Match any one character. */
+#define	ANYOF	4	/* str	Match any character in this string. */
+#define	ANYBUT	5	/* str	Match any character not in this string. */
+#define	BRANCH	6	/* node	Match this alternative, or the next... */
+#define	BACK	7	/* no	Match "", "next" ptr points backward. */
+#define	EXACTLY	8	/* str	Match this string. */
+#define	NOTHING	9	/* no	Match empty string. */
+#define	STAR	10	/* node	Match this (simple) thing 0 or more times. */
+#define	PLUS	11	/* node	Match this (simple) thing 1 or more times. */
+#define	OPEN	20	/* no	Mark this point in input as start of #n. */
+			/*	OPEN+1 is number 1, etc. */
+#define	CLOSE	30	/* no	Analogous to OPEN. */
+
+/*
+ * Opcode notes:
+ *
+ * BRANCH	The set of branches constituting a single choice are hooked
+ *		together with their "next" pointers, since precedence prevents
+ *		anything being concatenated to any individual branch.  The
+ *		"next" pointer of the last BRANCH in a choice points to the
+ *		thing following the whole choice.  This is also where the
+ *		final "next" pointer of each individual branch points; each
+ *		branch starts with the operand node of a BRANCH node.
+ *
+ * BACK		Normal "next" pointers all implicitly point forward; BACK
+ *		exists to make loop structures possible.
+ *
+ * STAR,PLUS	'?', and complex '*' and '+', are implemented as circular
+ *		BRANCH structures using BACK.  Simple cases (one character
+ *		per match) are implemented with STAR and PLUS for speed
+ *		and to minimize recursive plunges.
+ *
+ * OPEN,CLOSE	...are numbered at compile time.
+ */
+
+/*
+ * A node is one char of opcode followed by two chars of "next" pointer.
+ * "Next" pointers are stored as two 8-bit pieces, high order first.  The
+ * value is a positive offset from the opcode of the node containing it.
+ * An operand, if any, simply follows the node.  (Note that much of the
+ * code generation knows about this implicit relationship.)
+ *
+ * Using two bytes for the "next" pointer is vast overkill for most things,
+ * but allows patterns to get big without disasters.
+ */
+#define	OP(p)	(*(p))
+#define	NEXT(p)	(((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
+#define	OPERAND(p)	((p) + 3)
+
+/*
+ * See regmagic.h for one further detail of program structure.
+ */
+
+
+/*
+ * Utility definitions.
+ */
+#ifndef CHARBITS
+#define	UCHARAT(p)	((int)*(unsigned char *)(p))
+#else
+#define	UCHARAT(p)	((int)*(p)&CHARBITS)
+#endif
+
+#define	FAIL(m)	{ regerror(m); return(NULL); }
+#define	ISMULT(c)	((c) == '*' || (c) == '+' || (c) == '?')
+#define	META	"^$.[()|?+*\\"
+
+/*
+ * Flags to be passed up and down.
+ */
+#define	HASWIDTH	01	/* Known never to match null string. */
+#define	SIMPLE		02	/* Simple enough to be STAR/PLUS operand. */
+#define	SPSTART		04	/* Starts with * or +. */
+#define	WORST		0	/* Worst case. */
+#define STATIC 
+/*
+ * Global work variables for regcomp().
+ */
+
+STATIC char *regparse;		/* Input-scan pointer. */
+STATIC int regnpar;		/* () count. */
+STATIC unsigned char regdummy;
+STATIC unsigned char *regcode;	/* Code-emit pointer; &regdummy = don't. */
+STATIC long regsize;		/* Code size. */
+
+/*
+ * Forward declarations for regcomp()'s friends.
+ */
+_PROTOTYPE(STATIC unsigned char *reg, (int paren, int *flagp ));
+_PROTOTYPE(STATIC unsigned char *regbranch, (int *flagp ));
+_PROTOTYPE(STATIC unsigned char *regpiece, (int *flagp ));
+_PROTOTYPE(STATIC unsigned char *regatom, (int *flagp ));
+_PROTOTYPE(STATIC unsigned char *regnode, (int op ));
+_PROTOTYPE(STATIC void regc, (int b ));
+_PROTOTYPE(STATIC void reginsert, (int op, unsigned char *opnd ));
+_PROTOTYPE(STATIC void regtail, (unsigned char *p, unsigned char *val ));
+_PROTOTYPE(STATIC void regoptail, (unsigned char *p, unsigned char *val ));
+_PROTOTYPE(STATIC int regtry, (regexp *prog, unsigned char *string ));
+_PROTOTYPE(STATIC int regmatch, (unsigned char *prog ));
+_PROTOTYPE(STATIC int regrepeat, (unsigned char *p ));
+_PROTOTYPE(STATIC unsigned char *regnext, (unsigned char *p ));
+_PROTOTYPE(STATIC unsigned char *regprop, (unsigned char *op ));
+
+#ifdef STRCSPN
+_PROTOTYPE(STATIC int strcspn, (unsigned char *s1, unsigned char *s2 ));
+#endif
+
+/*
+ - regcomp - compile a regular expression into internal code
+ *
+ * We can't allocate space until we know how big the compiled form will be,
+ * but we can't compile it (and thus know how big it is) until we've got a
+ * place to put the code.  So we cheat:  we compile it twice, once with code
+ * generation turned off and size counting turned on, and once "for real".
+ * This also means that we don't allocate space until we are sure that the
+ * thing really will compile successfully, and we never have to move the
+ * code and thus invalidate pointers into it.  (Note that it has to be in
+ * one piece because free() must be able to free it all.)
+ *
+ * Beware that the optimization-preparation code in here knows about some
+ * of the structure of the compiled regexp.
+ */
+regexp *
+regcomp(exp)
+char *exp;
+{
+	register regexp *r;
+	register unsigned char *scan;
+	register unsigned char *longest;
+	register int len;
+	int flags;
+
+	if (exp == NULL)
+		FAIL("NULL argument");
+
+	/* First pass: determine size, legality. */
+	regparse = exp;
+	regnpar = 1;
+	regsize = 0L;
+	regcode = &regdummy;
+	regc(MAGIC);
+	if (reg(0, &flags) == NULL)
+		return(NULL);
+
+	/* Small enough for pointer-storage convention? */
+	if (regsize >= 32767L)		/* Probably could be 65535L. */
+		FAIL("regexp too big");
+
+	/* Allocate space. */
+	r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
+	if (r == NULL)
+		FAIL("out of space");
+
+	/* Second pass: emit code. */
+	regparse = exp;
+	regnpar = 1;
+	regcode = r->program;
+	regc(MAGIC);
+	if (reg(0, &flags) == NULL)
+		return(NULL);
+
+	/* Dig out information for optimizations. */
+	r->regstart = '\0';	/* Worst-case defaults. */
+	r->reganch = 0;
+	r->regmust = NULL;
+	r->regmlen = 0;
+	scan = r->program+1;			/* First BRANCH. */
+	if (OP(regnext(scan)) == END) {		/* Only one top-level choice. */
+		scan = OPERAND(scan);
+
+		/* Starting-point info. */
+		if (OP(scan) == EXACTLY)
+			r->regstart = *OPERAND(scan);
+		else if (OP(scan) == BOL)
+			r->reganch++;
+
+		/*
+		 * If there's something expensive in the r.e., find the
+		 * longest literal string that must appear and make it the
+		 * regmust.  Resolve ties in favor of later strings, since
+		 * the regstart check works with the beginning of the r.e.
+		 * and avoiding duplication strengthens checking.  Not a
+		 * strong reason, but sufficient in the absence of others.
+		 */
+		if (flags&SPSTART) {
+			longest = NULL;
+			len = 0;
+			for (; scan != NULL; scan = regnext(scan))
+				if (OP(scan) == EXACTLY
+				&& strlen((char *)OPERAND(scan)) >= len) {
+					longest = OPERAND(scan);
+					len = strlen((char *)OPERAND(scan));
+				}
+			r->regmust = longest;
+			r->regmlen = len;
+		}
+	}
+
+	return(r);
+}
+
+/*
+ - reg - regular expression, i.e. main body or parenthesized thing
+ *
+ * Caller must absorb opening parenthesis.
+ *
+ * Combining parenthesis handling with the base level of regular expression
+ * is a trifle forced, but the need to tie the tails of the branches to what
+ * follows makes it hard to avoid.
+ */
+STATIC unsigned char *
+reg(paren, flagp)
+int paren;			/* Parenthesized? */
+int *flagp;
+{
+	register unsigned char *ret;
+	register unsigned char *br;
+	register unsigned char *ender;
+	register int parno;
+	int flags;
+
+	*flagp = HASWIDTH;	/* Tentatively. */
+
+	/* Make an OPEN node, if parenthesized. */
+	if (paren) {
+		if (regnpar >= NSUBEXP)
+			FAIL("too many ()");
+		parno = regnpar;
+		regnpar++;
+		ret = regnode(OPEN+parno);
+	} else
+		ret = NULL;
+
+	/* Pick up the branches, linking them together. */
+	br = regbranch(&flags);
+	if (br == NULL)
+		return(NULL);
+	if (ret != NULL)
+		regtail(ret, br);	/* OPEN -> first. */
+	else
+		ret = br;
+	if (!(flags&HASWIDTH))
+		*flagp &= ~HASWIDTH;
+	*flagp |= flags&SPSTART;
+	while (*regparse == '|') {
+		regparse++;
+		br = regbranch(&flags);
+		if (br == NULL)
+			return(NULL);
+		regtail(ret, br);	/* BRANCH -> BRANCH. */
+		if (!(flags&HASWIDTH))
+			*flagp &= ~HASWIDTH;
+		*flagp |= flags&SPSTART;
+	}
+
+	/* Make a closing node, and hook it on the end. */
+	ender = regnode((paren) ? CLOSE+parno : END);	
+	regtail(ret, ender);
+
+	/* Hook the tails of the branches to the closing node. */
+	for (br = ret; br != NULL; br = regnext(br))
+		regoptail(br, ender);
+
+	/* Check for proper termination. */
+	if (paren && *regparse++ != ')') {
+		FAIL("unmatched ()");
+	} else if (!paren && *regparse != '\0') {
+		if (*regparse == ')') {
+			FAIL("unmatched ()");
+		} else
+			FAIL("junk on end");	/* "Can't happen". */
+		/* NOTREACHED */
+	}
+
+	return(ret);
+}
+
+/*
+ - regbranch - one alternative of an | operator
+ *
+ * Implements the concatenation operator.
+ */
+STATIC unsigned char *
+regbranch(flagp)
+int *flagp;
+{
+	register unsigned char *ret;
+	register unsigned char *chain;
+	register unsigned char *latest;
+	int flags;
+
+	*flagp = WORST;		/* Tentatively. */
+
+	ret = regnode(BRANCH);
+	chain = NULL;
+	while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
+		latest = regpiece(&flags);
+		if (latest == NULL)
+			return(NULL);
+		*flagp |= flags&HASWIDTH;
+		if (chain == NULL)	/* First piece. */
+			*flagp |= flags&SPSTART;
+		else
+			regtail(chain, latest);
+		chain = latest;
+	}
+	if (chain == NULL)	/* Loop ran zero times. */
+		(void) regnode(NOTHING);
+
+	return(ret);
+}
+
+/*
+ - regpiece - something followed by possible [*+?]
+ *
+ * Note that the branching code sequences used for ? and the general cases
+ * of * and + are somewhat optimized:  they use the same NOTHING node as
+ * both the endmarker for their branch list and the body of the last branch.
+ * It might seem that this node could be dispensed with entirely, but the
+ * endmarker role is not redundant.
+ */
+STATIC unsigned char *
+regpiece(flagp)
+int *flagp;
+{
+	register unsigned char *ret;
+	register unsigned char op;
+	register unsigned char *next;
+	int flags;
+
+	ret = regatom(&flags);
+	if (ret == NULL)
+		return(NULL);
+
+	op = *regparse;
+	if (!ISMULT(op)) {
+		*flagp = flags;
+		return(ret);
+	}
+
+	if (!(flags&HASWIDTH) && op != '?')
+		FAIL("*+ operand could be empty");
+	*flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
+
+	if (op == '*' && (flags&SIMPLE))
+		reginsert(STAR, ret);
+	else if (op == '*') {
+		/* Emit x* as (x&|), where & means "self". */
+		reginsert(BRANCH, ret);			/* Either x */
+		regoptail(ret, regnode(BACK));		/* and loop */
+		regoptail(ret, ret);			/* back */
+		regtail(ret, regnode(BRANCH));		/* or */
+		regtail(ret, regnode(NOTHING));		/* null. */
+	} else if (op == '+' && (flags&SIMPLE))
+		reginsert(PLUS, ret);
+	else if (op == '+') {
+		/* Emit x+ as x(&|), where & means "self". */
+		next = regnode(BRANCH);			/* Either */
+		regtail(ret, next);
+		regtail(regnode(BACK), ret);		/* loop back */
+		regtail(next, regnode(BRANCH));		/* or */
+		regtail(ret, regnode(NOTHING));		/* null. */
+	} else if (op == '?') {
+		/* Emit x? as (x|) */
+		reginsert(BRANCH, ret);			/* Either x */
+		regtail(ret, regnode(BRANCH));		/* or */
+		next = regnode(NOTHING);		/* null. */
+		regtail(ret, next);
+		regoptail(ret, next);
+	}
+	regparse++;
+	if (ISMULT(*regparse))
+		FAIL("nested *?+");
+
+	return(ret);
+}
+
+/*
+ - regatom - the lowest level
+ *
+ * Optimization:  gobbles an entire sequence of ordinary characters so that
+ * it can turn them into a single node, which is smaller to store and
+ * faster to run.  Backslashed characters are exceptions, each becoming a
+ * separate node; the code is simpler that way and it's not worth fixing.
+ */
+STATIC unsigned char *
+regatom(flagp)
+int *flagp;
+{
+	register unsigned char *ret;
+	int flags;
+
+	*flagp = WORST;		/* Tentatively. */
+
+	switch (*regparse++) {
+	case '^':
+		ret = regnode(BOL);
+		break;
+	case '$':
+		ret = regnode(EOL);
+		break;
+	case '.':
+		ret = regnode(ANY);
+		*flagp |= HASWIDTH|SIMPLE;
+		break;
+	case '[': {
+			register int class;
+			register int classend;
+
+			if (*regparse == '^') {	/* Complement of range. */
+				ret = regnode(ANYBUT);
+				regparse++;
+			} else
+				ret = regnode(ANYOF);
+			if (*regparse == ']' || *regparse == '-')
+				regc(*regparse++);
+			while (*regparse != '\0' && *regparse != ']') {
+				if (*regparse == '-') {
+					regparse++;
+					if (*regparse == ']' || *regparse == '\0')
+						regc('-');
+					else {
+						class = UCHARAT(regparse-2)+1;
+						classend = UCHARAT(regparse);
+						if (class > classend+1)
+							FAIL("invalid [] range");
+						for (; class <= classend; class++)
+							regc(class);
+						regparse++;
+					}
+				} else
+					regc(*regparse++);
+			}
+			regc('\0');
+			if (*regparse != ']')
+				FAIL("unmatched []");
+			regparse++;
+			*flagp |= HASWIDTH|SIMPLE;
+		}
+		break;
+	case '(':
+		ret = reg(1, &flags);
+		if (ret == NULL)
+			return(NULL);
+		*flagp |= flags&(HASWIDTH|SPSTART);
+		break;
+	case '\0':
+	case '|':
+	case ')':
+		FAIL("internal urp");	/* Supposed to be caught earlier. */
+		break;
+	case '?':
+	case '+':
+	case '*':
+		FAIL("?+* follows nothing");
+		break;
+	case '\\':
+		if (*regparse == '\0')
+			FAIL("trailing \\");
+		ret = regnode(EXACTLY);
+		regc(*regparse++);
+		regc('\0');
+		*flagp |= HASWIDTH|SIMPLE;
+		break;
+	default: {
+			register int len;
+			register unsigned char ender;
+
+			regparse--;
+#ifdef	STRCSPN
+			len = strcspn(regparse, (unsigned char *)META);
+#else
+			len = strcspn((char *)regparse, META);
+#endif
+			if (len <= 0)
+				FAIL("internal disaster");
+			ender = *(regparse+len);
+			if (len > 1 && ISMULT(ender))
+				len--;		/* Back off clear of ?+* operand. */
+			*flagp |= HASWIDTH;
+			if (len == 1)
+				*flagp |= SIMPLE;
+			ret = regnode(EXACTLY);
+			while (len > 0) {
+				regc(*regparse++);
+				len--;
+			}
+			regc('\0');
+		}
+		break;
+	}
+
+	return(ret);
+}
+
+/*
+ - regnode - emit a node
+ */
+STATIC unsigned char *			/* Location. */
+regnode(iop)
+int iop;
+{
+	register unsigned char *ret;
+	register unsigned char *ptr;
+	unsigned char op;
+
+	op = (unsigned char) iop;
+	ret = regcode;
+	if (ret == &regdummy) {
+		regsize += 3;
+		return(ret);
+	}
+
+	ptr = ret;
+	*ptr++ = op;
+	*ptr++ = '\0';		/* Null "next" pointer. */
+	*ptr++ = '\0';
+	regcode = ptr;
+
+	return(ret);
+}
+
+/*
+ - regc - emit (if appropriate) a byte of code
+ */
+STATIC void
+regc(ib)
+int ib;
+{
+	unsigned char b;
+
+	b = (unsigned char) ib;
+	if (regcode != &regdummy)
+		*regcode++ = b;
+	else
+		regsize++;
+}
+
+/*
+ - reginsert - insert an operator in front of already-emitted operand
+ *
+ * Means relocating the operand.
+ */
+STATIC void
+reginsert(iop, opnd)
+int iop;
+unsigned char *opnd;
+{
+	register unsigned char *src;
+	register unsigned char *dst;
+	register unsigned char *place;
+	unsigned char op;
+
+	op = (unsigned char) iop;
+	if (regcode == &regdummy) {
+		regsize += 3;
+		return;
+	}
+
+	src = regcode;
+	regcode += 3;
+	dst = regcode;
+	while (src > opnd)
+		*--dst = *--src;
+
+	place = opnd;		/* Op node, where operand used to be. */
+	*place++ = op;
+	*place++ = '\0';
+	*place++ = '\0';
+}
+
+/*
+ - regtail - set the next-pointer at the end of a node chain
+ */
+STATIC void
+regtail(p, val)
+unsigned char *p;
+unsigned char *val;
+{
+	register unsigned char *scan;
+	register unsigned char *temp;
+	register int offset;
+
+	if (p == &regdummy)
+		return;
+
+	/* Find last node. */
+	scan = p;
+	for (;;) {
+		temp = regnext(scan);
+		if (temp == NULL)
+			break;
+		scan = temp;
+	}
+
+	if (OP(scan) == BACK)
+		offset = scan - val;
+	else
+		offset = val - scan;
+	*(scan+1) = (offset>>8)&0377;
+	*(scan+2) = offset&0377;
+}
+
+/*
+ - regoptail - regtail on operand of first argument; nop if operandless
+ */
+STATIC void
+regoptail(p, val)
+unsigned char *p;
+unsigned char *val;
+{
+	/* "Operandless" and "op != BRANCH" are synonymous in practice. */
+	if (p == NULL || p == &regdummy || OP(p) != BRANCH)
+		return;
+	regtail(OPERAND(p), val);
+}
+
+/*
+ * regexec and friends
+ */
+
+/*
+ * Global work variables for regexec().
+ */
+STATIC unsigned char *reginput;		/* String-input pointer. */
+STATIC unsigned char *regbol;		/* Beginning of input, for ^ check. */
+STATIC unsigned char **regstartp;	/* Pointer to startp array. */
+STATIC unsigned char **regendp;		/* Ditto for endp. */
+
+#ifdef DEBUG
+int regnarrate = 0;
+void regdump();
+STATIC unsigned char *regprop();
+#endif
+
+/*
+ - regexec - match a regexp against a string
+ */
+int
+regexec(prog, string)
+register regexp *prog;
+register unsigned char *string;
+{
+	register unsigned char *s;
+#ifndef	STDLIB
+	extern char *strchr();
+#endif
+
+	/* Be paranoid... */
+	if (prog == NULL || string == NULL) {
+		regerror("NULL parameter");
+		return(0);
+	}
+
+	/* Check validity of program. */
+	if (UCHARAT(prog->program) != MAGIC) {
+		regerror("corrupted program");
+		return(0);
+	}
+
+	/* If there is a "must appear" string, look for it. */
+	if (prog->regmust != NULL) {
+		s = string;
+		while ((s = (unsigned char *)strchr((char *)s,prog->regmust[0]))
+		!= NULL) {
+			if (strncmp((char *)s, (char *)prog->regmust,
+			    prog->regmlen)
+			== 0)
+				break;	/* Found it. */
+			s++;
+		}
+		if (s == NULL)	/* Not present. */
+			return(0);
+	}
+
+	/* Mark beginning of line for ^ . */
+	regbol = string;
+
+	/* Simplest case:  anchored match need be tried only once. */
+	if (prog->reganch)
+		return(regtry(prog, string));
+
+	/* Messy cases:  unanchored match. */
+	s = string;
+	if (prog->regstart != '\0')
+		/* We know what char it must start with. */
+		while ((s = (unsigned char *)strchr((char *)s, prog->regstart))
+		!= NULL) {
+			if (regtry(prog, s))
+				return(1);
+			s++;
+		}
+	else
+		/* We don't -- general case. */
+		do {
+			if (regtry(prog, s))
+				return(1);
+		} while (*s++ != '\0');
+
+	/* Failure. */
+	return(0);
+}
+
+/*
+ - regtry - try match at specific point
+ */
+STATIC int			/* 0 failure, 1 success */
+regtry(prog, string)
+regexp *prog;
+unsigned char *string;
+{
+	register int i;
+	register unsigned char **sp;
+	register unsigned char **ep;
+
+	reginput = string;
+	regstartp = prog->startp;
+	regendp = prog->endp;
+
+	sp = prog->startp;
+	ep = prog->endp;
+	for (i = NSUBEXP; i > 0; i--) {
+		*sp++ = NULL;
+		*ep++ = NULL;
+	}
+	if (regmatch(prog->program + 1)) {
+		prog->startp[0] = string;
+		prog->endp[0] = reginput;
+		return(1);
+	} else
+		return(0);
+}
+
+/*
+ - regmatch - main matching routine
+ *
+ * Conceptually the strategy is simple:  check to see whether the current
+ * node matches, call self recursively to see whether the rest matches,
+ * and then act accordingly.  In practice we make some effort to avoid
+ * recursion, in particular by going through "ordinary" nodes (that don't
+ * need to know whether the rest of the match failed) by a loop instead of
+ * by recursion.
+ */
+STATIC int			/* 0 failure, 1 success */
+regmatch(prog)
+unsigned char *prog;
+{
+	register unsigned char *scan;	/* Current node. */
+	unsigned char *next;		/* Next node. */
+#ifndef	STDLIB
+	extern char *strchr();
+#endif
+
+	scan = prog;
+#ifdef DEBUG
+	if (scan != NULL && regnarrate)
+		fprintf(stderr, "%s(\n", regprop(scan));
+#endif
+	while (scan != NULL) {
+#ifdef DEBUG
+		if (regnarrate)
+			fprintf(stderr, "%s...\n", regprop(scan));
+#endif
+		next = regnext(scan);
+
+		switch (OP(scan)) {
+		case BOL:
+			if (reginput != regbol)
+				return(0);
+			break;
+		case EOL:
+			if (*reginput != '\0')
+				return(0);
+			break;
+		case ANY:
+			if (*reginput == '\0')
+				return(0);
+			reginput++;
+			break;
+		case EXACTLY: {
+				register int len;
+				register unsigned char *opnd;
+
+				opnd = OPERAND(scan);
+				/* Inline the first character, for speed. */
+				if (*opnd != *reginput)
+					return(0);
+				len = strlen((char *)opnd);
+				if (len > 1 && strncmp((char *)opnd,
+				   (char *)reginput, len)
+				!= 0)
+					return(0);
+				reginput += len;
+			}
+			break;
+		case ANYOF:
+			if (*reginput == '\0'
+			|| strchr((char *)OPERAND(scan), *reginput) == NULL)
+				return(0);
+			reginput++;
+			break;
+		case ANYBUT:
+			if (*reginput == '\0'
+			|| strchr((char *)OPERAND(scan), *reginput) != NULL)
+				return(0);
+			reginput++;
+			break;
+		case NOTHING:
+			break;
+		case BACK:
+			break;
+		case OPEN+1:
+		case OPEN+2:
+		case OPEN+3:
+		case OPEN+4:
+		case OPEN+5:
+		case OPEN+6:
+		case OPEN+7:
+		case OPEN+8:
+		case OPEN+9: {
+				register int no;
+				register unsigned char *save;
+
+				no = OP(scan) - OPEN;
+				save = reginput;
+
+				if (regmatch(next)) {
+					/*
+					 * Don't set startp if some later
+					 * invocation of the same parentheses
+					 * already has.
+					 */
+					if (regstartp[no] == NULL)
+						regstartp[no] = save;
+					return(1);
+				} else
+					return(0);
+			}
+			break;
+		case CLOSE+1:
+		case CLOSE+2:
+		case CLOSE+3:
+		case CLOSE+4:
+		case CLOSE+5:
+		case CLOSE+6:
+		case CLOSE+7:
+		case CLOSE+8:
+		case CLOSE+9: {
+				register int no;
+				register unsigned char *save;
+
+				no = OP(scan) - CLOSE;
+				save = reginput;
+
+				if (regmatch(next)) {
+					/*
+					 * Don't set endp if some later
+					 * invocation of the same parentheses
+					 * already has.
+					 */
+					if (regendp[no] == NULL)
+						regendp[no] = save;
+					return(1);
+				} else
+					return(0);
+			}
+			break;
+		case BRANCH: {
+				register unsigned char *save;
+
+				if (OP(next) != BRANCH)		/* No choice. */
+					next = OPERAND(scan);	/* Avoid recursion. */
+				else {
+					do {
+						save = reginput;
+						if (regmatch(OPERAND(scan)))
+							return(1);
+						reginput = save;
+						scan = regnext(scan);
+					} while (scan != NULL && OP(scan) == BRANCH);
+					return(0);
+					/* NOTREACHED */
+				}
+			}
+			break;
+		case STAR:
+		case PLUS: {
+				register unsigned char nextch;
+				register int no;
+				register unsigned char *save;
+				register int min;
+
+				/*
+				 * Lookahead to avoid useless match attempts
+				 * when we know what character comes next.
+				 */
+				nextch = '\0';
+				if (OP(next) == EXACTLY)
+					nextch = *OPERAND(next);
+				min = (OP(scan) == STAR) ? 0 : 1;
+				save = reginput;
+				no = regrepeat(OPERAND(scan));
+				while (no >= min) {
+					/* If it could work, try it. */
+					if (nextch == '\0' || *reginput == nextch)
+						if (regmatch(next))
+							return(1);
+					/* Couldn't or didn't -- back up. */
+					no--;
+					reginput = save + no;
+				}
+				return(0);
+			}
+			break;
+		case END:
+			return(1);	/* Success! */
+			break;
+		default:
+			regerror("memory corruption");
+			return(0);
+			break;
+		}
+
+		scan = next;
+	}
+
+	/*
+	 * We get here only if there's trouble -- normally "case END" is
+	 * the terminating point.
+	 */
+	regerror("corrupted pointers");
+	return(0);
+}
+
+/*
+ - regrepeat - repeatedly match something simple, report how many
+ */
+STATIC int
+regrepeat(p)
+unsigned char *p;
+{
+	register int count = 0;
+	register unsigned char *scan;
+	register unsigned char *opnd;
+
+	scan = reginput;
+	opnd = OPERAND(p);
+	switch (OP(p)) {
+	case ANY:
+		count = strlen((char *)scan);
+		scan += count;
+		break;
+	case EXACTLY:
+		while (*opnd == *scan) {
+			count++;
+			scan++;
+		}
+		break;
+	case ANYOF:
+		while (*scan != '\0' && strchr((char *)opnd, *scan) != NULL) {
+			count++;
+			scan++;
+		}
+		break;
+	case ANYBUT:
+		while (*scan != '\0' && strchr((char *)opnd, *scan) == NULL) {
+			count++;
+			scan++;
+		}
+		break;
+	default:		/* Oh dear.  Called inappropriately. */
+		regerror("internal foulup");
+		count = 0;	/* Best compromise. */
+		break;
+	}
+	reginput = scan;
+
+	return(count);
+}
+
+/*
+ - regnext - dig the "next" pointer out of a node
+ */
+STATIC unsigned char *
+regnext(p)
+register unsigned char *p;
+{
+	register int offset;
+
+	if (p == &regdummy)
+		return(NULL);
+
+	offset = NEXT(p);
+	if (offset == 0)
+		return(NULL);
+
+	if (OP(p) == BACK)
+		return(p-offset);
+	else
+		return(p+offset);
+}
+
+#ifdef DEBUG
+
+STATIC unsigned char *regprop();
+
+/*
+ - regdump - dump a regexp onto stdout in vaguely comprehensible form
+ */
+void
+regdump(r)
+regexp *r;
+{
+	register unsigned char *s;
+	register unsigned char op = EXACTLY;	/* Arbitrary non-END op. */
+	register unsigned char *next;
+	extern char *strchr();
+
+
+	s = r->program + 1;
+	while (op != END) {	/* While that wasn't END last time... */
+		op = OP(s);
+		printf("%2d%s", s-r->program, regprop(s));	/* Where, what. */
+		next = regnext(s);
+		if (next == NULL)		/* Next ptr. */
+			printf("(0)");
+		else 
+			printf("(%d)", (s-r->program)+(next-s));
+		s += 3;
+		if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
+			/* Literal string, where present. */
+			while (*s != '\0') {
+				putchar(*s);
+				s++;
+			}
+			s++;
+		}
+		putchar('\n');
+	}
+
+	/* Header fields of interest. */
+	if (r->regstart != '\0')
+		printf("start `%c' ", r->regstart);
+	if (r->reganch)
+		printf("anchored ");
+	if (r->regmust != NULL)
+		printf("must have \"%s\"", r->regmust);
+	printf("\n");
+}
+
+/*
+ - regprop - printable representation of opcode
+ */
+STATIC unsigned char *
+regprop(op)
+unsigned char *op;
+{
+	register unsigned char *p;
+	STATIC unsigned char buf[50];
+
+	(void) strcpy(buf, ":");
+
+	switch (OP(op)) {
+	case BOL:
+		p = "BOL";
+		break;
+	case EOL:
+		p = "EOL";
+		break;
+	case ANY:
+		p = "ANY";
+		break;
+	case ANYOF:
+		p = "ANYOF";
+		break;
+	case ANYBUT:
+		p = "ANYBUT";
+		break;
+	case BRANCH:
+		p = "BRANCH";
+		break;
+	case EXACTLY:
+		p = "EXACTLY";
+		break;
+	case NOTHING:
+		p = "NOTHING";
+		break;
+	case BACK:
+		p = "BACK";
+		break;
+	case END:
+		p = "END";
+		break;
+	case OPEN+1:
+	case OPEN+2:
+	case OPEN+3:
+	case OPEN+4:
+	case OPEN+5:
+	case OPEN+6:
+	case OPEN+7:
+	case OPEN+8:
+	case OPEN+9:
+		sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
+		p = NULL;
+		break;
+	case CLOSE+1:
+	case CLOSE+2:
+	case CLOSE+3:
+	case CLOSE+4:
+	case CLOSE+5:
+	case CLOSE+6:
+	case CLOSE+7:
+	case CLOSE+8:
+	case CLOSE+9:
+		sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
+		p = NULL;
+		break;
+	case STAR:
+		p = "STAR";
+		break;
+	case PLUS:
+		p = "PLUS";
+		break;
+	default:
+		regerror("corrupted opcode");
+		break;
+	}
+	if (p != NULL)
+		(void) strcat(buf, p);
+	return(buf);
+}
+#endif
+
+/*
+ * The following is provided for those people who do not have strcspn() in
+ * their C libraries.  They should get off their butts and do something
+ * about it; at least one public-domain implementation of those (highly
+ * useful) string routines has been published on Usenet.
+ */
+#ifdef STRCSPN
+/*
+ * strcspn - find length of initial segment of s1 consisting entirely
+ * of characters not from s2
+ */
+
+STATIC int
+strcspn(s1, s2)
+unsigned char *s1;
+unsigned char *s2;
+{
+	register unsigned char *scan1;
+	register unsigned char *scan2;
+	register int count;
+
+	count = 0;
+	for (scan1 = s1; *scan1 != '\0'; scan1++) {
+		for (scan2 = s2; *scan2 != '\0';)	/* ++ moved down. */
+			if (*scan1 == *scan2++)
+				return(count);
+		count++;
+	}
+	return(count);
+}
+#endif
Index: /trunk/minix/commands/cawf/regexp.h
===================================================================
--- /trunk/minix/commands/cawf/regexp.h	(revision 9)
+++ /trunk/minix/commands/cawf/regexp.h	(revision 9)
@@ -0,0 +1,17 @@
+/*
+ * Definitions etc. for regexp(3) routines.
+ *
+ * Caveat:  this is V8 regexp(3) [actually, a reimplementation thereof],
+ * not the System V one.
+ */
+#define NSUBEXP  10
+typedef struct regexp {
+	unsigned char *startp[NSUBEXP];
+	unsigned char *endp[NSUBEXP];
+	unsigned char regstart;		/* Internal use only. */
+	unsigned char reganch;		/* Internal use only. */
+	unsigned char *regmust;		/* Internal use only. */
+	unsigned char regmlen;		/* Internal use only. */
+	unsigned char program[1];	/* Unwarranted chumminess with
+					 * compiler. */
+} regexp;
Index: /trunk/minix/commands/cawf/regmagic.h
===================================================================
--- /trunk/minix/commands/cawf/regmagic.h	(revision 9)
+++ /trunk/minix/commands/cawf/regmagic.h	(revision 9)
@@ -0,0 +1,5 @@
+/*
+ * The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte.
+ */
+#define	MAGIC	0234
Index: /trunk/minix/commands/cawf/store.c
===================================================================
--- /trunk/minix/commands/cawf/store.c	(revision 9)
+++ /trunk/minix/commands/cawf/store.c	(revision 9)
@@ -0,0 +1,184 @@
+/*
+ *	store.c - cawf(1) storage areas
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+#include "cawf.h"
+
+struct rx Pat[] = {
+	{ "^[.'](i[ef]|el)",			 	NULL},	/* 0 */
+	{ "^[.']i[ef] !",				NULL},  /* 1 */
+	{ "^[.']i[ef] !?\\\\n\\(\\.\\$(>|>=|=|<|<=)[0-9] ",
+							NULL},	/* 2 */
+	{ "^[.']i[ef] !?'\\\\\\$[0-9]'[^']*' ",		NULL},	/* 3 */
+	{ "^[.']i[ef] !?[nt] ",				NULL},  /* 4 */
+	{ "\\\\\\$[0-9]",                               NULL},  /* 5 */
+	{ "^[ \t]*$",					NULL},  /* 6 */
+	{ "\\\\|\t|-|  ",				NULL},	/* 7 */
+	{ "[.!?:][]\\)'\\\"\\*]*$",                     NULL},  /* 8 */
+	{ ",fP",					NULL},	/* 9 */
+	{ ",tP",					NULL},	/* 10 */
+	{ "^(ta|ll|ls|in|ti|po|ne|sp|pl|nr)",           NULL},  /* 11 */
+	{ "^(ll|ls|in|ti|po|pl)",                       NULL},  /* 12 */
+	{ "[]\\)'\\\"\\*]",                             NULL},  /* 13 */
+	{ "^(LH|CH|RH|LF|CF|RF)",			NULL},	/* 14 */
+	{ "^[.']i[ef]",			 		NULL},	/* 15 */
+	{ ",fR",					NULL},	/* 16 */
+	{ NULL,                                         NULL}   /* END */
+};
+
+int Adj = BOTHADJ;			/* output line adjustment mode */
+unsigned char *Aftnxt = NULL;		/* action after next line */
+unsigned char *Args[] = { NULL, NULL,	/* 10 macro arguments */
+			  NULL, NULL,
+			  NULL, NULL,
+			  NULL, NULL,
+			  NULL, NULL
+};
+unsigned char *Argstack[10*MAXSP];	/* stack for Expand()'s "args[]" */
+int Backc = 0;				/* last word ended with '\\c' */
+int Botmarg = 5;			/* bottom margin */
+int Centering = 0;			/* centering count */
+int Condstack[MAXSP];                   /* stack for Expand()'s "cond" */
+unsigned char *Cont = NULL;		/* continue line append */
+int Contlen = 0;			/* continue line append length */
+int Curmx = -1;				/* current macro index */
+char *Device = NULL;			/* output device name */
+char *Devconf = NULL;			/* device configuration file path */
+char *Devfont = NULL;			/* output device font */
+int Divert = 0;                         /* diversion status */
+FILE *Efs = NULL;			/* error file stream */
+unsigned char *Eol = NULL;		/* end of line information */
+int Eollen = 0;				/* end of line length */
+int Err = 0;                            /* error flag */
+unsigned char *F = NULL;		/* field value */
+struct fcode Fcode[] = {		/* font codes */
+	{ 'B',  '\0'},			/* Bold */
+	{ 'I',  '\0'},			/* Italic */
+	{ 'R',  '\0'},			/* Roman */
+	{ 'C',  '\0'},			/* Courier */
+	{ '\0', '\0'}
+};
+int Fill = 0;				/* fill status */
+unsigned char Font[] = { '\0', '\0' };	/* current font */
+int Fontctl;				/* output font control */
+char Fontstat = 'R';			/* output font status */
+int Fph = 0;				/* first page header status */
+int Fsp = 0;				/* files stack pointer (for .so) */
+struct fontstr Fstr;			/* font control strings */
+unsigned char *Ftc = NULL;		/* center footer */
+unsigned char *Ftl = NULL;		/* left footer */
+unsigned char *Ftr = NULL;		/* right footer */
+unsigned char *Hdc = NULL;		/* center header */
+int Hdft = 0;				/* header/footer status */
+unsigned char *Hdl = NULL;		/* left header */
+unsigned char *Hdr = NULL;		/* right header */
+struct hytab Hychar[MAXHYCH];		/* hyphen characters */
+FILE *Ifs = NULL;			/* input file stream */
+FILE *Ifs_stk[MAXFSTK];                 /* Ifs stack */
+int Ind = 0;				/* indentation amount */
+unsigned char *Inname = NULL;		/* input file name */
+unsigned char *Inn_stk[MAXFSTK];	/* Inname stack */
+int LL = 78;				/* line length (default) */
+unsigned char Line[MAXLINE];		/* input line */
+int Lockil = 0;                      	/* pass 2 line number is locked
+                                         * (processing is inside macro) */
+int Marg = 0;				/* macro argument - man, ms, etc. */
+struct macro Macrotab[MAXMACRO];        /* macro table */
+unsigned char *Macrotxt[MAXMTXT];	/* macro text */
+int Mtx = 0;                            /* macro text index */
+int Mxstack[MAXSP];                     /* stack for Expand()'s "mx" */
+int Nfc;				/* number of font codes */
+int Nhnr[MAXNHNR];                      /* ".NH" numbers */
+int Nhy = 0;				/* number of Hychar[] entries */
+int Nleftstack[MAXSP];                  /* stack for Expand()'s "nleft" */
+int Nmac = 0;                           /* number of macros */
+int Nnr = 0;				/* number of Numb[] entries */
+int Nospmode = 1;                    	/* no space mode */
+int Nparms = 0;				/* number of Parms[] entries */
+int NR = 0;                             /* number of record ala awk */
+int NR_stk[MAXFSTK];                   	/* NR stack */
+int Nsch = 0;				/* number of Schar[] entries */
+int Nstr = 0;				/* number of entries in Str[] */
+int Ntabs = 0;				/* number of TAB positions */
+struct nbr Numb[MAXNR];			/* number registers */
+int Nxtln = 1;				/* next line number */
+int Outll = -1;				/* output line length */
+unsigned char Outln[MAXOLL*2];		/* output line */
+int Outlx = 0;				/* output line index */
+int P2il = 0; 	                        /* pass 2 input line number */
+unsigned char *P2name = NULL;		/* pass 2 input file name */
+int P3fill = 1;				/* pass 3 fill status */
+int Padchar[MAXOLL];			/* padding character locations */
+int Padfrom = PADLEFT;			/* which end to pad from */
+int Padx = 0;				/* Padchar[] index */
+struct parms Parms[] = {                /* parameter registers */
+	{ {'i', 'n'}, "indent", 0, 0      },
+	{ {'l', 'l'}, "linelen", 0, 0     },
+	{ {'l', 's'}, "vspace", 0, 0	  },
+	{ {'t', 'i'}, "tempindent", 0, 0  },
+	{ {'p', 'o'}, "pageoffset", 0, 0  },
+	{ {'p', 'l'}, "pagelen", 0, 0     },
+	{ {'\0', '\0'}, NULL, 0, 0        }
+};
+unsigned char Pass1ln[MAXLINE];		/* pass 1 output line */
+unsigned char Pass2ln[MAXLINE];		/* pass 2 output line */
+int Pglen = 66;				/* page length */
+int Pgoff = 0;				/* page offset */
+char *Pname = NULL;			/* program name */
+unsigned char Prevfont = '\0';		/* previous font */
+int Ptrstack[MAXSP];                    /* stack for Expand()'s "ptr" */
+struct scale Scale[] = {		/* scaling factors */
+	{ 'i',	(240.0)		 	},
+	{ 'c',	((240.0 * 50.0)/127.0)	},
+	{ 'P',	(240.0/6.0)		},
+	{ 'p',	(240.0/72.0)		},
+	{ 'u',  (1.0)                   },
+	{ 'm',  (1.0)                   },
+	{ 'n',  (1.0)                   },
+	{ 'v',  (1.0)                   },
+	{ '\0',	(0.0)			}
+};
+double Scalen = 0.0;			/* 'n' scaling factor */
+double Scaleu = 0.0;			/* 'u' scaling factor */
+double Scalev = 0.0;			/* 'v' scaling factor */
+struct schtab Schar[MAXSCH];		/* special characters */
+int Sp = -1;				/* stack pointer */
+struct str Str[MAXSTR];                 /* ".ds" strings */
+int Sx = -1;				/* string index */
+int Tabs[MAXEXP+1];			/* TAB positions */
+int Thispg = 1;				/* this page number */
+int Tind = 0; 				/* temporary indentation amount */
+int Topmarg = 5;			/* top margin */
+unsigned char *Trtbl = NULL;		/* .tr table */
+int Uhyph = 0;				/* hyphen usage state */
+int Vspace = 1;				/* vertical (inter-text-line) spacing */
+unsigned char Word[MAXLINE];		/* pass 2 word buffer */
+int Wordl = 0;                          /* effective length of Word[] */
+int Wordx = 0;                          /* Word[] index */
+int Dowarn = 1;				/* Enable warnings if true */
Index: /trunk/minix/commands/cawf/string.c
===================================================================
--- /trunk/minix/commands/cawf/string.c	(revision 9)
+++ /trunk/minix/commands/cawf/string.c	(revision 9)
@@ -0,0 +1,351 @@
+/*
+ *	string.c - string support functions for cawf(1)
+ */
+
+/*
+ *	Copyright (c) 1991 Purdue University Research Foundation,
+ *	West Lafayette, Indiana 47907.  All rights reserved.
+ *
+ *	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+ *	University Computing Center.  Not derived from licensed software;
+ *	derived from awf(1) by Henry Spencer of the University of Toronto.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to alter it and redistribute
+ *	it freely, subject to the following restrictions:
+ *
+ *	1. The author is not responsible for any consequences of use of
+ *	   this software, even if they arise from flaws in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *	   by explicit claim or by omission.  Credits must appear in the
+ *	   documentation.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *	   be misrepresented as being the original software.  Credits must
+ *	   appear in the documentation.
+ *
+ *	4. This notice may not be removed or altered.
+ */
+
+#include "cawf.h"
+#include <ctype.h>
+
+_PROTOTYPE(static void Setroman,());
+
+
+/*
+ * Asmname(s, c) - assemble name
+ */
+
+Asmname(s, c)
+	unsigned char *s;		/* pointer to name */
+	unsigned char *c;		/* code destination (c[3]) */
+{
+
+	c[1] = c[2] = '\0';
+	while (*s && *s == ' ')
+		s++;
+	if ((c[0] = *s) == '\0')
+		return(0);
+	return(((c[1] = s[1]) == '\0') ? 1 : 2);
+}
+
+
+/*
+ * Delstr(sx) - delete string
+ */
+
+void
+Delstr(sx)
+	int sx;				/* string index */
+{
+	char buf[MAXLINE];		/* message buffer */
+
+	if (sx >= Nstr) {
+		(void) sprintf(buf, " bad Delstr(%d) index", sx);
+		Error(FATAL, LINE, buf, NULL);
+	}
+	Free(&Str[sx].str);
+	while (sx < (Nstr - 1)) {
+		Str[sx] = Str[sx + 1];
+		sx++;
+	}
+	Nstr--;
+}
+
+
+/*
+ * Endword() - end a word
+ */
+
+void
+Endword()
+{
+	if (Fontstat != 'R')
+		Setroman();
+	Word[Wordx] = '\0';
+}
+
+
+/*
+ * Findchar(nm, l, s, e) - find special character definition and
+ *			   optionally enter it
+ */
+
+Findchar(nm, l, s, e)
+	unsigned char *nm;		/* character name */
+	int l;				/* effective length */
+	unsigned char *s;		/* value string */
+	int e;				/* 0 = find, don't enter
+					 * 1 = don't find, enter */
+{
+	int cmp, hi, low, mid;
+	unsigned char c[3];
+
+	c[0] = nm[0];
+	c[1] = (nm[1] == ' ' || nm[1] == '\t') ? '\0' : nm[1];
+	c[2] = '\0';
+	low = mid = 0;
+	hi = Nsch - 1;
+	while (low <= hi) {
+		mid = (low + hi) / 2;
+		if ((cmp = strncmp((char *)c, (char *)Schar[mid].nm, 2)) < 0)
+			hi = mid - 1;
+		else if (cmp > 0)
+			low = mid + 1;
+		else {
+			if ( ! e)
+				return(mid);
+			Free(&Schar[mid].str);
+			goto new_char;
+		}
+	}
+	if ( ! e)
+		return(-1);
+	if (Nsch >= MAXSCH)
+		Error(FATAL, LINE, " at character table limit", NULL);
+	if (Nsch) {
+		if (cmp > 0)
+			mid++;
+		for (hi = Nsch - 1; hi >= mid; hi--)
+			Schar[hi+1] = Schar[hi];
+	}
+	Nsch++;
+	Schar[mid].nm[0] = c[0];
+	Schar[mid].nm[1] = c[1];
+
+new_char:
+
+	Schar[mid].str = Newstr(s);
+	Schar[mid].len = l;
+	return(mid);
+}
+
+
+/*
+ * Findhy(s, l, e) - find and optionally enter hyphen
+ */
+
+Findhy(s, l, e)
+	unsigned char *s;		/* value string */
+	int l;				/* equivalent length */
+	int e;				/* 0 = find, don't enter
+					 * 1 = enter, don't find */
+{
+	int i;
+
+	for (i = 0; i < Nhy; i++) {
+		if (Font[0] == Hychar[i].font)
+			break;
+	}
+	if (i >= Nhy) {
+		if ( ! e)
+			return(-1);
+		if (Nhy >= MAXHYCH)
+			Error(FATAL, LINE, " at hyphen limit for font ",
+				(char *)Font);
+		Hychar[i].font = Font[0];
+		Nhy++;
+	} else {
+		if ( ! e)
+			return(i);
+		Error(WARN, LINE, " duplicate hyphen for font ", (char *)Font);
+		Free(&Hychar[i].str);
+	}
+	Hychar[i].str = Newstr(s);
+	Hychar[i].len = l;
+	return(i);
+}
+
+
+/*
+ * Findstr(nm, s, e) - find and  optionally enter string in Str[]
+ */
+
+unsigned char *
+Findstr(nm, s, e)
+	unsigned char *nm;		/* 2 character string name */
+	unsigned char *s;		/* string value */
+	int e;				/* 0 = find, don't enter
+					 * 1 = enter, don't find */
+{
+	unsigned char c[3];		/* character buffer */
+	int cmp, hi, low, mid;		/* binary search controls */
+	int i;				/* temporary indexes */
+	unsigned char *s1, *s2;		/* temporary string pointers */
+
+	c[0] = nm[0];
+	c[1] = (nm[1] == ' ' || nm[1] == '\t') ? '\0' : nm[1];
+	c[2] = '\0';
+	low = mid = 0;
+	hi = Nstr - 1;
+	Sx = -1;
+	while (low <= hi) {
+		mid = (low + hi) / 2;
+		if ((cmp = strncmp((char *)c, (char *)Str[mid].nm, 2)) < 0)
+			hi = mid - 1;
+		else if (cmp > 0)
+			low = mid + 1;
+		else {
+			Sx = mid;
+			if ( ! e)
+				return(Str[mid].str);
+			Free(&Str[mid].str);
+			goto new_string;
+		}
+	}
+	if ( ! e)
+		return((unsigned char *)"");
+	if (Nstr >= MAXSTR)
+		Error(FATAL, LINE, " out of space for string ", (char *)c);
+	if (Nstr) {
+		if (cmp > 0)
+			mid++;
+		for (hi = Nstr - 1; hi >= mid; hi--)
+			Str[hi+1] = Str[hi];
+	}
+	Nstr++;
+	Sx = mid;
+	Str[mid].nm[0] = c[0];
+	Str[mid].nm[1] = c[1];
+
+new_string:
+
+	if (s == NULL)
+		return (Str[mid].str = Newstr((unsigned char *)""));
+	i = (*s == '"') ? 1 : 0;
+	s1 = Str[mid].str = Newstr(s + i);
+	if (i) {
+		s2 = s1 + strlen((char *)s1);
+		if (s2 > s1 && *(s2-1) == '"')
+			*(s2-1) = '\0';
+	}
+	return(s1);
+}
+
+
+/*
+ * Setroman() - set Roman font
+ */
+
+static void
+Setroman()
+{
+	int i;
+
+	if ((Wordx + Fstr.rl) >= MAXLINE)
+		Error(WARN, LINE, " word too long", NULL);
+	else {
+		if (Fstr.r) {
+			for (i = 0; i < Fstr.rl; i++) {
+				Word[Wordx++] = Fstr.r[i];
+			}
+	    	}
+		Fontstat = 'R';
+	}
+}
+
+
+/*
+ * Str2word(s, len) - copy len characters from string to Word[]
+ */
+
+Str2word(s, len)
+	unsigned char *s;
+	int len;
+{
+	int i;
+
+	for (; len > 0; len--, s++) {
+		switch (Font[0]) {
+		case 'B':
+		case 'C':
+			if (Fontctl == 0) {
+				if ((Wordx + 5) >= MAXLINE) {
+word_too_long:
+					Error(WARN, LINE, " word too long",
+						NULL);
+					return(1);
+				}
+				Word[Wordx++] = Trtbl[(int)*s];
+				Word[Wordx++] = '\b';
+				Word[Wordx++] = Trtbl[(int)*s];
+				Word[Wordx++] = '\b';
+				Word[Wordx++] = Trtbl[(int)*s];
+				break;
+			}
+			if (Fontstat != Font[0]) {
+				if (Fontstat != 'R')
+					Setroman();
+				if ((Wordx + Fstr.bl) >= MAXLINE)
+					goto word_too_long;
+				if (Fstr.b) {
+					for (i = 0; i < Fstr.bl; i++) {
+						Word[Wordx++] = Fstr.b[i];
+					}
+				}
+				Fontstat = Font[0];
+			}
+			if ((Wordx + 1) >= MAXLINE)
+				goto word_too_long;
+			Word[Wordx++] = Trtbl[(int)*s];
+			break;
+		case 'I':
+			if (isalnum(*s)) {
+				if (Fontctl == 0) {
+					if ((Wordx + 3) >= MAXLINE)
+						goto word_too_long;
+					Word[Wordx++] = '_';
+					Word[Wordx++] = '\b';
+					Word[Wordx++] = Trtbl[(int)*s];
+					break;
+				}
+				if (Fontstat != 'I') {
+					if (Fontstat != 'R')
+						Setroman();
+					if ((Wordx + Fstr.itl) >= MAXLINE)
+						goto word_too_long;
+					if (Fstr.it) {
+					    for (i = 0; i < Fstr.itl; i++) {
+						Word[Wordx++] = Fstr.it[i];
+					    }
+					}
+					Fontstat = 'I';
+				}
+				if ((Wordx + 1) >= MAXLINE)
+					goto word_too_long;
+				Word[Wordx++] = Trtbl[(int)*s];
+				break;
+			}
+			/* else fall through */
+		default:
+			if (Fontstat != 'R')
+				Setroman();
+			if ((Wordx + 1) >= MAXLINE)
+				goto word_too_long;
+			Word[Wordx++] = Trtbl[(int)*s];
+		}
+	}
+	return(0);
+}
Index: /trunk/minix/commands/cron/Makefile
===================================================================
--- /trunk/minix/commands/cron/Makefile	(revision 9)
+++ /trunk/minix/commands/cron/Makefile	(revision 9)
@@ -0,0 +1,34 @@
+# Makefile for cron.
+
+CFLAGS=		-D_MINIX -D_POSIX_SOURCE
+CC = exec cc
+LDFLAGS=
+
+all:	cron crontab
+
+CRON_OBJ=	cron.o tab.o misc.o
+CRONTAB_OBJ=	crontab.o tab.o misc.o
+
+cron:	$(CRON_OBJ)
+	$(CC) $(LDFLAGS) -o $@ $(CRON_OBJ)
+	install -S 8kw $@
+
+crontab:	$(CRONTAB_OBJ)
+	$(CC) $(LDFLAGS) -o $@ $(CRONTAB_OBJ)
+	install -S 4kw $@
+
+install:	/usr/bin/cron /usr/bin/crontab
+
+/usr/bin/cron:	cron
+	install -cs $? $@
+
+/usr/bin/crontab:	crontab
+	install -cs -o root -m 4755 $? $@
+
+clean:
+	rm -f *.o cron crontab core a.out
+
+# Dependencies.
+cron.o crontab.o:	misc.h tab.h
+tab.o:			misc.h tab.h
+misc.o:			misc.h
Index: /trunk/minix/commands/cron/build
===================================================================
--- /trunk/minix/commands/cron/build	(revision 9)
+++ /trunk/minix/commands/cron/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/cron/cron.c
===================================================================
--- /trunk/minix/commands/cron/cron.c	(revision 9)
+++ /trunk/minix/commands/cron/cron.c	(revision 9)
@@ -0,0 +1,465 @@
+/*	cron 1.4 - clock daemon				Author: Kees J. Bot
+ *								7 Dec 1996
+ */
+
+#define _MINIX_SOURCE
+#define _MINIX 1
+
+#define nil ((void*)0)
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <limits.h>
+#include <dirent.h>
+#include <time.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include "misc.h"
+#include "tab.h"
+
+#if __minix && !__minix_vmd
+#define initgroups(name, gid)	(0)
+#endif
+
+static volatile int busy;	/* Set when something is afoot, don't sleep! */
+static volatile int need_reload;/* Set if table reload required. */
+static volatile int need_quit;	/* Set if cron must exit. */
+static volatile int debug;	/* Debug level. */
+
+static void run_job(cronjob_t *job)
+/* Execute a cron job.  Register its pid in the job structure.  If a job's
+ * crontab has an owner then its output is mailed to that owner, otherwise
+ * no special provisions are made, so the output will go where cron's output
+ * goes.  This keeps root's mailbox from filling up.
+ */
+{
+	pid_t pid;
+	int need_mailer;
+	int mailfd[2], errfd[2];
+	struct passwd *pw;
+	crontab_t *tab= job->tab;
+
+	need_mailer= (tab->user != nil);
+
+	if (job->atjob) {
+		struct stat st;
+
+		need_mailer= 1;
+		if (rename(tab->file, tab->data) < 0) {
+			if (errno == ENOENT) {
+				/* Normal error, job deleted. */
+				need_reload= 1;
+			} else {
+				/* Bad error, halt processing AT jobs. */
+				log(LOG_CRIT, "Can't rename %s: %s\n",
+					tab->file, strerror(errno));
+				tab_reschedule(job);
+			}
+			return;
+		}
+		/* Will need to determine the next AT job. */
+		need_reload= 1;
+
+		if (stat(tab->data, &st) < 0) {
+			log(LOG_ERR, "Can't stat %s: %s\n",
+						tab->data, strerror(errno));
+			tab_reschedule(job);
+			return;
+		}
+		if ((pw= getpwuid(st.st_uid)) == nil) {
+			log(LOG_ERR, "Unknown owner for uid %lu of AT job %s\n",
+				(unsigned long) st.st_uid, job->cmd);
+			tab_reschedule(job);
+			return;
+		}
+	} else {
+		pw= nil;
+		if (job->user != nil && (pw= getpwnam(job->user)) == nil) {
+			log(LOG_ERR, "%s: Unknown user\n", job->user);
+			tab_reschedule(job);
+			return;
+		}
+	}
+
+	if (need_mailer) {
+		errfd[0]= -1;
+		if (pipe(errfd) < 0 || pipe(mailfd) < 0) {
+			log(LOG_ERR, "pipe() call failed: %s\n",
+							strerror(errno));
+			if (errfd[0] != -1) {
+				close(errfd[0]);
+				close(errfd[1]);
+			}
+			tab_reschedule(job);
+			return;
+		}
+		(void) fcntl(errfd[1], F_SETFD,
+				fcntl(errfd[1], F_GETFD) | FD_CLOEXEC);
+
+		if ((pid= fork()) == -1) {
+			log(LOG_ERR, "fork() call failed: %s\n",
+							strerror(errno));
+			close(errfd[0]);
+			close(errfd[1]);
+			close(mailfd[0]);
+			close(mailfd[1]);
+			tab_reschedule(job);
+			return;
+		}
+
+		if (pid == 0) {
+			/* Child that is to be the mailer. */
+			char subject[70+20], *ps;
+
+			close(errfd[0]);
+			close(mailfd[1]);
+			if (mailfd[0] != 0) {
+				dup2(mailfd[0], 0);
+				close(mailfd[0]);
+			}
+
+			memset(subject, 0, sizeof(subject));
+			sprintf(subject,
+				"Output from your %s job: %.50s",
+				job->atjob ? "AT" : "cron",
+				job->cmd);
+			if (subject[70] != 0) {
+				strcpy(subject+70-3, "...");
+			}
+			for (ps= subject; *ps != 0; ps++) {
+				if (*ps == '\n') *ps= '%';
+			}
+
+			execl("/usr/bin/mail", "mail", "-s", subject,
+						pw->pw_name, (char *) nil);
+			write(errfd[1], &errno, sizeof(errno));
+			_exit(1);
+		}
+
+		close(mailfd[0]);
+		close(errfd[1]);
+		if (read(errfd[0], &errno, sizeof(errno)) > 0) {
+			log(LOG_ERR, "can't execute /usr/bin/mail: %s\n",
+							strerror(errno));
+			close(errfd[0]);
+			close(mailfd[1]);
+			tab_reschedule(job);
+			return;
+		}
+		close(errfd[0]);
+	}
+
+	if (pipe(errfd) < 0) {
+		log(LOG_ERR, "pipe() call failed: %s\n", strerror(errno));
+		if (need_mailer) close(mailfd[1]);
+		tab_reschedule(job);
+		return;
+	}
+	(void) fcntl(errfd[1], F_SETFD, fcntl(errfd[1], F_GETFD) | FD_CLOEXEC);
+
+	if ((pid= fork()) == -1) {
+		log(LOG_ERR, "fork() call failed: %s\n", strerror(errno));
+		close(errfd[0]);
+		close(errfd[1]);
+		if (need_mailer) close(mailfd[1]);
+		tab_reschedule(job);
+		return;
+	}
+
+	if (pid == 0) {
+		/* Child that is to be the cron job. */
+		close(errfd[0]);
+		if (need_mailer) {
+			if (mailfd[1] != 1) {
+				dup2(mailfd[1], 1);
+				close(mailfd[1]);
+			}
+			dup2(1, 2);
+		}
+
+		if (pw != nil) {
+			/* Change id to the owner of the job. */
+			initgroups(pw->pw_name, pw->pw_gid);
+			setgid(pw->pw_gid);
+			setuid(pw->pw_uid);
+			chdir(pw->pw_dir);
+			if (setenv("USER", pw->pw_name, 1) < 0) goto bad;
+			if (setenv("LOGNAME", pw->pw_name, 1) < 0) goto bad;
+			if (setenv("HOME", pw->pw_dir, 1) < 0) goto bad;
+			if (setenv("SHELL", pw->pw_shell[0] == 0 ? "/bin/sh"
+						: pw->pw_shell, 1) < 0) goto bad;
+		}
+
+		if (job->atjob) {
+			execl("/bin/sh", "sh", tab->data, (char *) nil);
+		} else {
+			execl("/bin/sh", "sh", "-c", job->cmd, (char *) nil);
+		}
+	    bad:
+		write(errfd[1], &errno, sizeof(errno));
+		_exit(1);
+	}
+
+	if (need_mailer) close(mailfd[1]);
+	close(errfd[1]);
+	if (read(errfd[0], &errno, sizeof(errno)) > 0) {
+		log(LOG_ERR, "can't execute /bin/sh: %s\n", strerror(errno));
+		close(errfd[0]);
+		tab_reschedule(job);
+		return;
+	}
+	close(errfd[0]);
+	job->pid= pid;
+	if (debug >= 1) fprintf(stderr, "executing >%s<, pid = %ld\n",
+						job->cmd, (long) job->pid);
+}
+
+static void load_crontabs(void)
+/* Load all the crontabs we like to run.  We didn't bother to make a list in
+ * an array or something, this is too system specific to make nice.
+ */
+{
+	DIR *spool;
+#if __minix_vmd
+	FILE *pkgs;
+#endif
+
+	tab_parse("/usr/lib/crontab", nil);
+	tab_parse("/usr/local/lib/crontab", nil);
+	tab_parse("/var/lib/crontab", nil);
+
+#if __minix_vmd
+	if ((pkgs= fopen("/usr/lib/packages", "r")) != nil) {
+		char name[NAME_MAX+1];
+		char *np;
+		int c;
+		char tab[sizeof("/var/opt//lib/crontab") + NAME_MAX];
+
+		while ((c= fgetc(pkgs)) != EOF) {
+			np= name;
+			while (c != EOF && c != '/' && c != '\n') {
+				if (np < name+NAME_MAX) *np++ = c;
+				c= fgetc(pkgs);
+			}
+			*np= 0;
+			while (c != EOF && c != '\n') c= fgetc(pkgs);
+
+			if (name[0] == 0) continue;	/* ? */
+
+			strcpy(tab, "/var/opt/");
+			strcat(tab, name);
+			strcat(tab, "/lib/crontab");
+			tab_parse(tab, nil);
+		}
+		if (ferror(pkgs)) {
+			log(LOG_CRIT, "/usr/lib/packages: %s\n",
+							strerror(errno));
+		}
+		fclose(pkgs);
+	} else {
+		if (errno != ENOENT) {
+			log(LOG_ERR, "/usr/lib/packages: %s\n",
+							strerror(errno));
+		}
+	}
+#endif /* Minix-vmd */
+
+	if ((spool= opendir("/usr/spool/crontabs")) != nil) {
+		struct dirent *entry;
+		char tab[sizeof("/usr/spool/crontabs/") + NAME_MAX];
+
+		while ((entry= readdir(spool)) != nil) {
+			if (entry->d_name[0] == '.') continue;
+
+			strcpy(tab, "/usr/spool/crontabs/");
+			strcat(tab, entry->d_name);
+			tab_parse(tab, entry->d_name);
+		}
+		closedir(spool);
+	}
+
+	/* Find the first to be executed AT job. */
+	tab_find_atjob("/usr/spool/at");
+
+	tab_purge();
+	if (debug >= 2) {
+		tab_print(stderr);
+		fprintf(stderr, "%lu memory chunks in use\n",
+			(unsigned long) alloc_count);
+	}
+}
+
+static void handler(int sig)
+{
+	switch (sig) {
+	case SIGHUP:
+		need_reload= 1;
+		break;
+	case SIGINT:
+	case SIGTERM:
+		need_quit= 1;
+		break;
+	case SIGUSR1:
+		debug++;
+		break;
+	case SIGUSR2:
+		debug= 0;
+		break;
+	}
+	alarm(1);	/* A signal may come just before a blocking call. */
+	busy= 1;
+}
+
+static void usage(void)
+{
+	fprintf(stderr, "Usage: %s [-d[#]]\n", prog_name);
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	int i;
+	struct sigaction sa, osa;
+	FILE *pf;
+	int r;
+
+	prog_name= strrchr(argv[0], '/');
+	if (prog_name == nil) prog_name= argv[0]; else prog_name++;
+
+	i= 1;
+	while (i < argc && argv[i][0] == '-') {
+		char *opt= argv[i++] + 1;
+
+		if (opt[0] == '-' && opt[1] == 0) break;	/* -- */
+
+		while (*opt != 0) switch (*opt++) {
+		case 'd':
+			if (*opt == 0) {
+				debug= 1;
+			} else {
+				debug= strtoul(opt, &opt, 10);
+				if (*opt != 0) usage();
+			}
+			break;
+		default:
+			usage();
+		}
+	}
+	if (i != argc) usage();
+
+	selectlog(SYSLOG);
+	openlog(prog_name, LOG_PID, LOG_DAEMON);
+	setlogmask(LOG_UPTO(LOG_INFO));
+
+	/* Save process id. */
+	if ((pf= fopen(PIDFILE, "w")) == NULL) {
+		fprintf(stderr, "%s: %s\n", PIDFILE, strerror(errno));
+		exit(1);
+	}
+	fprintf(pf, "%d\n", getpid());
+	if (ferror(pf) || fclose(pf) == EOF) {
+		fprintf(stderr, "%s: %s\n", PIDFILE, strerror(errno));
+		exit(1);
+	}
+
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags= 0;
+	sa.sa_handler= handler;
+
+	/* Hangup: Reload crontab files. */
+	sigaction(SIGHUP, &sa, nil);
+
+	/* User signal 1 & 2: Raise or reset debug level. */
+	sigaction(SIGUSR1, &sa, nil);
+	sigaction(SIGUSR2, &sa, nil);
+
+	/* Interrupt and Terminate: Cleanup and exit. */
+	if (sigaction(SIGINT, nil, &osa) == 0 && osa.sa_handler != SIG_IGN) {
+		sigaction(SIGINT, &sa, nil);
+	}
+	if (sigaction(SIGTERM, nil, &osa) == 0 && osa.sa_handler != SIG_IGN) {
+		sigaction(SIGTERM, &sa, nil);
+	}
+
+	/* Alarm: Wake up and run a job. */
+	sigaction(SIGALRM, &sa, nil);
+
+	/* Initialize current time and time next to do something. */
+	time(&now);
+	next= NEVER;
+
+	/* Table load required first time. */
+	need_reload= 1;
+
+	do {
+		if (need_reload) {
+			need_reload= 0;
+			load_crontabs();
+			busy= 1;
+		}
+
+		/* Run jobs whose time has come. */
+		if (next <= now) {
+			cronjob_t *job;
+
+			if ((job= tab_nextjob()) != nil) run_job(job);
+			busy= 1;
+		}
+
+		if (busy) {
+			/* Did a job finish? */
+			r= waitpid(-1, nil, WNOHANG);
+			busy= 0;
+		} else {
+			/* Sleep until the next job must be started. */
+			if (next == NEVER) {
+				alarm(0);
+			} else {
+#if __minix_vmd
+				struct timeval tvnext;
+
+				tvnext.tv_sec= next;
+				tvnext.tv_usec= 0;
+				sysutime(UTIME_SETALARM, &tvnext);
+#else
+				alarm((next - now) > INT_MAX
+						? INT_MAX : (next - now));
+#endif
+			}
+			if (debug >= 1) fprintf(stderr, "%s: sleep until %s",
+						prog_name, ctime(&next));
+
+			closelog();	/* Don't keep resources open. */
+
+			/* Wait for a job to exit or a timeout. */
+			r= waitpid(-1, nil, 0);
+			if (r == -1 && errno == ECHILD) pause();
+			alarm(0);
+			time(&now);
+		}
+
+		if (r > 0) {
+			/* A job has finished, reschedule it. */
+			if (debug >= 1) fprintf(stderr, "pid %d has exited\n",
+									r);
+			tab_reap_job((pid_t) r);
+			busy= 1;
+		}
+	} while (!need_quit);
+
+	/* Remove the pid file to signal that cron is gone. */
+	unlink(PIDFILE);
+
+	return 0;
+}
+
+/*
+ * $PchId: cron.c,v 1.4 2000/07/17 19:00:35 philip Exp $
+ */
Index: /trunk/minix/commands/cron/crontab.c
===================================================================
--- /trunk/minix/commands/cron/crontab.c	(revision 9)
+++ /trunk/minix/commands/cron/crontab.c	(revision 9)
@@ -0,0 +1,258 @@
+/*	crontab 1.2 - user crontab manipulation		Author: Kees J. Bot
+ *								12 Jan 1997
+ */
+#define nil ((void*)0)
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <sys/stat.h>
+#include "misc.h"
+#include "tab.h"
+
+#if __minix && !__minix_vmd
+#define seteuid(uid)	((uid),0)	/* Minix can't fiddle with uids. */
+#endif
+
+static int opentab(int uid, char *file, int how)
+/* Open a crontab file under the given uid.  How is 'r' or 'w'.  Return
+ * the result of open(2).
+ */
+{
+	uid_t safe_uid;
+	int flags, r, err;
+
+	switch (how) {
+	case 'r':	flags= O_RDONLY;			break;
+	case 'w':	flags= O_WRONLY | O_CREAT | O_TRUNC;	break;
+	default:	errno= EINVAL;				return -1;
+	}
+
+#if __minix && !__minix_vmd
+	/* Standard Minix has no saved uid, so use the lousy old access(). */
+	if (uid != 0) {
+		if (access(file, how == 'r' ? R_OK : W_OK) < 0) return -1;
+	}
+#endif
+
+	safe_uid= geteuid();
+	seteuid(uid);
+	r= open(file, flags, 0666);
+	err= errno;
+	seteuid(safe_uid);
+	errno= err;
+	return r;
+}
+
+static void copytab(int fd_in, char *file_in, int fd_out, char *file_out)
+/* Copy one open file to another.  Complain and exit on errors. */
+{
+	ssize_t r, w;
+	char buf[1024];
+
+	while ((r= read(fd_in, buf, sizeof(buf))) > 0) {
+		w= 0;
+		while (w < r) {
+			if ((r= write(fd_out, buf+w, r-w)) <= 0) {
+				fprintf(stderr,
+				"%s: Write error on %s: %s\n",
+					prog_name,
+					file_out,
+					r == 0 ? "End of file"
+							: strerror(errno));
+				exit(1);
+			}
+			w+= r;
+		}
+	}
+	if (r < 0) {
+		fprintf(stderr, "%s: Read error on %s: %s\n",
+			prog_name, file_in, strerror(errno));
+		exit(1);
+	}
+}
+
+static void usage(void)
+{
+	fprintf(stderr,
+		"Usage: %s -c [user] file  # Change crontab\n"
+		"       %s -l [user]       # List crontab\n"
+		"       %s -r [user]       # Remove crontab\n"
+		"       %s -p              # Tell cron to reload\n",
+		prog_name, prog_name, prog_name, prog_name);
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	int i;
+	int cflag, lflag, rflag, pflag;
+	uid_t uid;
+	char *user, *file;
+	struct passwd *pw;
+	static char SPOOLDIR[]= "/usr/spool/crontabs";
+	char tabfile[sizeof(SPOOLDIR) + NAME_MAX];
+
+	prog_name= strrchr(argv[0], '/');
+	if (prog_name == nil) prog_name= argv[0]; else prog_name++;
+
+	cflag= lflag= rflag= pflag= 0;
+	i= 1;
+	while (i < argc && argv[i][0] == '-') {
+		char *opt= argv[i++] + 1;
+
+		if (opt[0] == '-' && opt[1] == 0) break;	/* -- */
+
+		while (*opt != 0) switch (*opt++) {
+		case 'c':	cflag= 1;	break;
+		case 'l':	lflag= 1;	break;
+		case 'r':	rflag= 1;	break;
+		case 'p':	pflag= 1;	break;
+		default:	usage();
+		}
+	}
+	if (cflag + lflag + rflag + pflag != 1) usage();
+
+	user= file= nil;
+	if (!pflag && i < argc) user= argv[i++];
+	if (cflag) {
+		if (user == nil) usage();
+		if (i < argc) {
+			file= argv[i++];
+		} else {
+			file= user;
+			user= nil;
+		}
+	}
+	if (i != argc) usage();
+
+	if (geteuid() != 0) {
+		fprintf(stderr, "%s: No root privileges?\n", prog_name);
+	}
+	uid= getuid();
+	if (user == nil) {
+		if ((pw= getpwuid(uid)) == nil) {
+			fprintf(stderr,
+				"%s: Don't know who you (uid %lu) are!\n",
+				prog_name, (unsigned long) uid);
+			exit(1);
+		}
+	} else {
+		if ((pw= getpwnam(user)) == nil) {
+			fprintf(stderr,
+				"%s: Don't know who you (%s) are!\n",
+				prog_name, user);
+			exit(1);
+		}
+	}
+	if (uid != 0 && pw->pw_uid != uid) {
+		fprintf(stderr,
+		"%s: Only root can change the crontabs of others!\n",
+			prog_name);
+		exit(1);
+	}
+	user= pw->pw_name;
+	uid= pw->pw_uid;
+	seteuid(uid);
+	umask(0077);
+
+	selectlog(STDERR);
+	sprintf(tabfile, "%s/%s", SPOOLDIR, user);
+
+	if (lflag) {
+		int fd;
+
+		if ((fd= opentab(0, tabfile, 'r')) < 0) {
+			fprintf(stderr, "%s: Can't open %s: %s\n",
+				prog_name, tabfile, strerror(errno));
+			exit(1);
+		}
+		copytab(fd, tabfile, 1, "stdout");
+		close(fd);
+	}
+
+	if (rflag) {
+		seteuid(0);
+		if (unlink(tabfile) < 0) {
+			fprintf(stderr, "%s: Can't remove %s: %s\n",
+				prog_name, tabfile, strerror(errno));
+			exit(1);
+		}
+		seteuid(uid);
+		printf("Crontab of %s removed\n", user);
+		pflag= 1;
+	}
+
+	/* Initialize current Time */
+	time(&now);
+
+	if (cflag) {
+		int fd1, fd2;
+
+		if ((fd1= opentab(uid, file, 'r')) < 0) {
+			fprintf(stderr, "%s: Can't open %s: %s\n",
+				prog_name, file, strerror(errno));
+			exit(1);
+		}
+
+		/* Try to parse the new crontab file.  If the parsing
+		 * succeeds then 'crontabs' will be non-null.
+		 */
+		tab_parse(file, user);
+		tab_purge();
+		if (crontabs == nil) exit(1);
+
+		if ((fd2= opentab(0, tabfile, 'w')) < 0) {
+			fprintf(stderr, "%s: Can't open %s: %s\n",
+				prog_name, tabfile, strerror(errno));
+			exit(1);
+		}
+		copytab(fd1, file, fd2, tabfile);
+		close(fd1);
+		close(fd2);
+		printf("New crontab for %s installed\n", user);
+		pflag= 1;
+	}
+
+	if (pflag) {
+		/* Alert cron to the new situation. */
+		FILE *fp;
+
+		seteuid(0);
+		if ((fp= fopen(PIDFILE, "r")) != NULL) {
+			unsigned long pid;
+			int c;
+
+			pid= 0;
+			while ((c= fgetc(fp)) != EOF && c != '\n') {
+				if ((unsigned) (c - '0') >= 10) {
+					pid= 0; break;
+				}
+				pid= 10*pid + (c - '0');
+				if (pid >= 30000) { pid= 0; break; }
+			}
+			if (pid > 1 && kill((pid_t) pid, SIGHUP) == 0) {
+				pflag= 0;
+			}
+		}
+		seteuid(uid);
+		if (pflag) {
+			fprintf(stderr,
+			"%s: Alerting cron has failed; cron still running?\n",
+				prog_name);
+			exit(1);
+		}
+		printf("Cron signalled to reload tables\n");
+	}
+	return 0;
+}
+
+/*
+ * $PchId: crontab.c,v 1.4 2000/07/17 18:54:50 philip Exp $
+ */
Index: /trunk/minix/commands/cron/misc.c
===================================================================
--- /trunk/minix/commands/cron/misc.c	(revision 9)
+++ /trunk/minix/commands/cron/misc.c	(revision 9)
@@ -0,0 +1,68 @@
+/*	misc.c - Miscellaneous stuff for cron		Author: Kees J. Bot
+ *								12 Jan 1997
+ */
+#define nil ((void*)0)
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+#include "misc.h"
+
+char *prog_name;		/* Name of this program. */
+time_t now;			/* Cron's idea of the current time. */
+time_t next;			/* Time to run the next job. */
+
+size_t alloc_count;		/* # Of chunks of memory allocated. */
+
+void *allocate(size_t len)
+/* Checked malloc().  Better not feed it length 0. */
+{
+	void *mem;
+
+	if ((mem= malloc(len)) == nil) {
+		log(LOG_ALERT, "Out of memory, exiting\n");
+		exit(1);
+	}
+	alloc_count++;
+	return mem;
+}
+
+void deallocate(void *mem)
+{
+	if (mem != nil) {
+		free(mem);
+		alloc_count--;
+	}
+}
+
+static enum logto logto= SYSLOG;
+
+void selectlog(enum logto where)
+/* Select where logging output should go, syslog or stdout. */
+{
+	logto= where;
+}
+
+void log(int level, const char *fmt, ...)
+/* Like syslog(), but may go to stderr. */
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+
+#if __minix_vmd || !__minix
+	if (logto == SYSLOG) {
+		vsyslog(level, fmt, ap);
+	} else
+#endif
+	{
+		fprintf(stderr, "%s: ", prog_name);
+		vfprintf(stderr, fmt, ap);
+	}
+	va_end(ap);
+}
+
+/*
+ * $PchId: misc.c,v 1.3 2000/07/17 19:01:57 philip Exp $
+ */
Index: /trunk/minix/commands/cron/misc.h
===================================================================
--- /trunk/minix/commands/cron/misc.h	(revision 9)
+++ /trunk/minix/commands/cron/misc.h	(revision 9)
@@ -0,0 +1,42 @@
+/*	misc.h - miscellaneous stuff			Author: Kees J. Bot
+ *								7 Dec 1996
+ */
+#ifndef MISC__H
+#define MISC__H
+
+#include <time.h>
+
+/* The name of the program. */
+extern char *prog_name;
+
+/* Where cron stores it pid. */
+#define PIDFILE	"/usr/run/cron.pid"
+
+/* Cron's idea of the current time, and the time next to run something. */
+extern time_t now;
+extern time_t next;
+
+/* Memory allocation. */
+void *allocate(size_t len);
+void deallocate(void *mem);
+extern size_t alloc_count;
+
+/* Logging, by syslog or to stderr. */
+#if __minix_vmd || !__minix
+#include <sys/syslog.h>
+#else
+enum log_dummy { LOG_ERR, LOG_CRIT, LOG_ALERT };
+#define openlog(ident, opt, facility)	((void) 0)
+#define closelog()			((void) 0)
+#define setlogmask(mask)		(0)
+#endif
+
+enum logto { SYSLOG, STDERR };
+void selectlog(enum logto where);
+void log(int level, const char *fmt, ...);
+
+#endif /* MISC__H */
+
+/*
+ * $PchId: misc.h,v 1.3 2000/07/17 18:56:02 philip Exp $
+ */
Index: /trunk/minix/commands/cron/tab.c
===================================================================
--- /trunk/minix/commands/cron/tab.c	(revision 9)
+++ /trunk/minix/commands/cron/tab.c	(revision 9)
@@ -0,0 +1,816 @@
+/*	tab.c - process crontabs and create in-core crontab data
+ *							Author: Kees J. Bot
+ *								7 Dec 1996
+ * Changes:
+ * 17 Jul 2000 by Philip Homburg
+ *	- Tab_reschedule() rewritten (and fixed).
+ */
+#define nil ((void*)0)
+#include <sys/types.h>
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <time.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include "misc.h"
+#include "tab.h"
+
+static int nextbit(bitmap_t map, int bit)
+/* Return the next bit set in 'map' from 'bit' onwards, cyclic. */
+{
+	for (;;) {
+		bit= (bit+1) & 63;
+		if (bit_isset(map, bit)) break;
+	}
+	return bit;
+}
+
+void tab_reschedule(cronjob_t *job)
+/* Reschedule one job.  Compute the next time to run the job in job->rtime.
+ */
+{
+	struct tm prevtm, nexttm, tmptm;
+	time_t nodst_rtime, dst_rtime;
+
+	/* AT jobs are only run once. */
+	if (job->atjob) { job->rtime= NEVER; return; }
+
+	/* Was the job scheduled late last time? */
+	if (job->late) job->rtime= now;
+
+	prevtm= *localtime(&job->rtime);
+	prevtm.tm_sec= 0;
+
+	nexttm= prevtm;
+	nexttm.tm_min++;	/* Minimal increment */
+
+	for (;;)
+	{
+		if (nexttm.tm_min > 59)
+		{
+			nexttm.tm_min= 0;
+			nexttm.tm_hour++;
+		}
+		if (nexttm.tm_hour > 23)
+		{
+			nexttm.tm_min= 0;
+			nexttm.tm_hour= 0;
+			nexttm.tm_mday++;
+		}
+		if (nexttm.tm_mday > 31)
+		{
+			nexttm.tm_hour= nexttm.tm_min= 0;
+			nexttm.tm_mday= 1;
+			nexttm.tm_mon++;
+		}
+		if (nexttm.tm_mon >= 12)
+		{
+			nexttm.tm_hour= nexttm.tm_min= 0;
+			nexttm.tm_mday= 1;
+			nexttm.tm_mon= 0;
+			nexttm.tm_year++;
+		}
+
+		/* Verify tm_year. A crontab entry cannot restrict tm_year
+		 * directly. However, certain dates (such as Feb, 29th) do
+		 * not occur every year. We limit the difference between
+		 * nexttm.tm_year and prevtm.tm_year to detect impossible dates
+		 * (e.g, Feb, 31st). In theory every date occurs within a
+		 * period of 4 years. However, some years at the end of a 
+		 * century are not leap years (e.g, the year 2100). An extra
+		 * factor of 2 should be enough.
+		 */
+		if (nexttm.tm_year-prevtm.tm_year > 2*4)
+		{
+			job->rtime= NEVER;
+			return;			/* Impossible combination */
+		}
+
+		if (!job->do_wday)
+		{
+			/* Verify the mon and mday fields. If do_wday and
+			 * do_mday are both true we have to merge both
+			 * schedules. This is done after the call to mktime.
+			 */
+			if (!bit_isset(job->mon, nexttm.tm_mon))
+			{
+				/* Clear other fields */
+				nexttm.tm_mday= 1;
+				nexttm.tm_hour= nexttm.tm_min= 0;
+
+				nexttm.tm_mon++;
+				continue;
+			}
+
+			/* Verify mday */
+			if (!bit_isset(job->mday, nexttm.tm_mday))
+			{
+				/* Clear other fields */
+				nexttm.tm_hour= nexttm.tm_min= 0;
+
+				nexttm.tm_mday++;
+				continue;
+			}
+		}
+
+		/* Verify hour */
+		if (!bit_isset(job->hour, nexttm.tm_hour))
+		{
+			/* Clear tm_min field */
+			nexttm.tm_min= 0;
+
+			nexttm.tm_hour++;
+			continue;
+		}
+
+		/* Verify min */
+		if (!bit_isset(job->min, nexttm.tm_min))
+		{
+			nexttm.tm_min++;
+			continue;
+		}
+
+		/* Verify that we don't have any problem with DST. Try
+		 * tm_isdst=0 first. */
+		tmptm= nexttm;
+		tmptm.tm_isdst= 0;
+#if 0
+		fprintf(stderr, 
+	"tab_reschedule: trying %04d-%02d-%02d %02d:%02d:%02d isdst=0\n",
+				1900+nexttm.tm_year, nexttm.tm_mon+1,
+				nexttm.tm_mday, nexttm.tm_hour,
+				nexttm.tm_min, nexttm.tm_sec);
+#endif
+		nodst_rtime= job->rtime= mktime(&tmptm);
+		if (job->rtime == -1) {
+			/* This should not happen. */
+			log(LOG_ERR,
+			"mktime failed for %04d-%02d-%02d %02d:%02d:%02d",
+				1900+nexttm.tm_year, nexttm.tm_mon+1,
+				nexttm.tm_mday, nexttm.tm_hour,
+				nexttm.tm_min, nexttm.tm_sec);
+			job->rtime= NEVER;
+			return;	
+		}
+		tmptm= *localtime(&job->rtime);
+		if (tmptm.tm_hour != nexttm.tm_hour ||
+			tmptm.tm_min != nexttm.tm_min)
+		{
+			assert(tmptm.tm_isdst);
+			tmptm= nexttm;
+			tmptm.tm_isdst= 1;
+#if 0
+			fprintf(stderr, 
+	"tab_reschedule: trying %04d-%02d-%02d %02d:%02d:%02d isdst=1\n",
+				1900+nexttm.tm_year, nexttm.tm_mon+1,
+				nexttm.tm_mday, nexttm.tm_hour,
+				nexttm.tm_min, nexttm.tm_sec);
+#endif
+			dst_rtime= job->rtime= mktime(&tmptm);
+			if (job->rtime == -1) {
+				/* This should not happen. */
+				log(LOG_ERR,
+			"mktime failed for %04d-%02d-%02d %02d:%02d:%02d\n",
+					1900+nexttm.tm_year, nexttm.tm_mon+1,
+					nexttm.tm_mday, nexttm.tm_hour,
+					nexttm.tm_min, nexttm.tm_sec);
+				job->rtime= NEVER;
+				return;	
+			}
+			tmptm= *localtime(&job->rtime);
+			if (tmptm.tm_hour != nexttm.tm_hour ||
+				tmptm.tm_min != nexttm.tm_min)
+			{
+				assert(!tmptm.tm_isdst);
+				/* We have a problem. This time neither
+				 * exists with DST nor without DST.
+				 * Use the latest time, which should be
+				 * nodst_rtime.
+				 */
+				assert(nodst_rtime > dst_rtime);
+				job->rtime= nodst_rtime;
+#if 0
+				fprintf(stderr,
+			"During DST trans. %04d-%02d-%02d %02d:%02d:%02d\n",
+					1900+nexttm.tm_year, nexttm.tm_mon+1,
+					nexttm.tm_mday, nexttm.tm_hour,
+					nexttm.tm_min, nexttm.tm_sec);
+#endif
+			}
+		}
+
+		/* Verify this the combination (tm_year, tm_mon, tm_mday). */
+		if (tmptm.tm_mday != nexttm.tm_mday ||
+			tmptm.tm_mon != nexttm.tm_mon ||
+			tmptm.tm_year != nexttm.tm_year)
+		{
+			/* Wrong day */
+#if 0
+			fprintf(stderr, "Wrong day\n");
+#endif
+			nexttm.tm_hour= nexttm.tm_min= 0;
+			nexttm.tm_mday++;
+			continue;
+		}
+
+		/* Check tm_wday */
+		if (job->do_wday && bit_isset(job->wday, tmptm.tm_wday))
+		{
+			/* OK, wday matched */
+			break;
+		}
+
+		/* Check tm_mday */
+		if (job->do_mday && bit_isset(job->mon, tmptm.tm_mon) &&
+			bit_isset(job->mday, tmptm.tm_mday))
+		{
+			/* OK, mon and mday matched */
+			break;
+		}
+
+		if (!job->do_wday && !job->do_mday)
+		{
+			/* No need to match wday and mday */
+			break;
+		}
+
+		/* Wrong day */
+#if 0
+		fprintf(stderr, "Wrong mon+mday or wday\n");
+#endif
+		nexttm.tm_hour= nexttm.tm_min= 0;
+		nexttm.tm_mday++;
+	}
+#if 0
+	fprintf(stderr, "Using %04d-%02d-%02d %02d:%02d:%02d \n",
+		1900+nexttm.tm_year, nexttm.tm_mon+1, nexttm.tm_mday,
+		nexttm.tm_hour, nexttm.tm_min, nexttm.tm_sec);
+	tmptm= *localtime(&job->rtime);
+	fprintf(stderr, "Act. %04d-%02d-%02d %02d:%02d:%02d isdst=%d\n",
+		1900+tmptm.tm_year, tmptm.tm_mon+1, tmptm.tm_mday,
+		tmptm.tm_hour, tmptm.tm_min, tmptm.tm_sec,
+		tmptm.tm_isdst);
+#endif
+
+
+	/* Is job issuing lagging behind with the progress of time? */
+	job->late= (job->rtime < now);
+
+  	/* The result is in job->rtime. */
+  	if (job->rtime < next) next= job->rtime;
+}
+
+#define isdigit(c)	((unsigned) ((c) - '0') < 10)
+
+static char *get_token(char **ptr)
+/* Return a pointer to the next token in a string.  Move *ptr to the end of
+ * the token, and return a pointer to the start.  If *ptr == start of token
+ * then we're stuck against a newline or end of string.
+ */
+{
+	char *start, *p;
+
+	p= *ptr;
+	while (*p == ' ' || *p == '\t') p++;
+
+	start= p;
+	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != 0) p++;
+	*ptr= p;
+	return start;
+}
+
+static int range_parse(char *file, char *data, bitmap_t map,
+	int min, int max, int *wildcard)
+/* Parse a comma separated series of 'n', 'n-m' or 'n:m' numbers.  'n'
+ * includes number 'n' in the bit map, 'n-m' includes all numbers between
+ * 'n' and 'm' inclusive, and 'n:m' includes 'n+k*m' for any k if in range.
+ * Numbers must fall between 'min' and 'max'.  A '*' means all numbers.  A
+ * '?' is allowed as a synonym for the current minute, which only makes sense
+ * in the minute field, i.e. max must be 59.  Return true iff parsed ok.
+ */
+{
+	char *p;
+	int end;
+	int n, m;
+
+	/* Clear all bits. */
+	for (n= 0; n < 8; n++) map[n]= 0;
+
+	p= data;
+	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != 0) p++;
+	end= *p;
+	*p= 0;
+	p= data;
+
+	if (*p == 0) {
+		log(LOG_ERR, "%s: not enough time fields\n", file);
+		return 0;
+	}
+
+	/* Is it a '*'? */
+	if (p[0] == '*' && p[1] == 0) {
+		for (n= min; n <= max; n++) bit_set(map, n);
+		p[1]= end;
+		*wildcard= 1;
+		return 1;
+	}
+	*wildcard= 0;
+
+	/* Parse a comma separated series of numbers or ranges. */
+	for (;;) {
+		if (*p == '?' && max == 59 && p[1] != '-') {
+			n= localtime(&now)->tm_min;
+			p++;
+		} else {
+			if (!isdigit(*p)) goto syntax;
+			n= 0;
+			do {
+				n= 10 * n + (*p++ - '0');
+				if (n > max) goto range;
+			} while (isdigit(*p));
+		}
+		if (n < min) goto range;
+
+		if (*p == '-') {	/* A range of the form 'n-m'? */
+			p++;
+			if (!isdigit(*p)) goto syntax;
+			m= 0;
+			do {
+				m= 10 * m + (*p++ - '0');
+				if (m > max) goto range;
+			} while (isdigit(*p));
+			if (m < n) goto range;
+			do {
+				bit_set(map, n);
+			} while (++n <= m);
+		} else
+		if (*p == ':') {	/* A repeat of the form 'n:m'? */
+			p++;
+			if (!isdigit(*p)) goto syntax;
+			m= 0;
+			do {
+				m= 10 * m + (*p++ - '0');
+				if (m > (max-min+1)) goto range;
+			} while (isdigit(*p));
+			if (m == 0) goto range;
+			while (n >= min) n-= m;
+			while ((n+= m) <= max) bit_set(map, n);
+		} else {
+					/* Simply a number */
+			bit_set(map, n);
+		}
+		if (*p == 0) break;
+		if (*p++ != ',') goto syntax;
+	}
+	*p= end;
+	return 1;
+  syntax:
+	log(LOG_ERR, "%s: field '%s': bad syntax for a %d-%d time field\n",
+		file, data, min, max);
+	return 0;
+  range:
+	log(LOG_ERR, "%s: field '%s': values out of the %d-%d allowed range\n",
+		file, data, min, max);
+	return 0;
+}
+
+void tab_parse(char *file, char *user)
+/* Parse a crontab file and add its data to the tables.  Handle errors by
+ * yourself.  Table is owned by 'user' if non-null.
+ */
+{
+	crontab_t **atab, *tab;
+	cronjob_t **ajob, *job;
+	int fd;
+	struct stat st;
+	char *p, *q;
+	size_t n;
+	ssize_t r;
+	int ok, wc;
+
+	for (atab= &crontabs; (tab= *atab) != nil; atab= &tab->next) {
+		if (strcmp(file, tab->file) == 0) break;
+	}
+
+	/* Try to open the file. */
+	if ((fd= open(file, O_RDONLY)) < 0 || fstat(fd, &st) < 0) {
+		if (errno != ENOENT) {
+			log(LOG_ERR, "%s: %s\n", file, strerror(errno));
+		}
+		if (fd != -1) close(fd);
+		return;
+	}
+
+	/* Forget it if the file is awfully big. */
+	if (st.st_size > TAB_MAX) {
+		log(LOG_ERR, "%s: %lu bytes is bigger than my %lu limit\n",
+			file,
+			(unsigned long) st.st_size,
+			(unsigned long) TAB_MAX);
+		return;
+	}
+
+	/* If the file is the same as before then don't bother. */
+	if (tab != nil && st.st_mtime == tab->mtime) {
+		close(fd);
+		tab->current= 1;
+		return;
+	}
+
+	/* Create a new table structure. */
+	tab= allocate(sizeof(*tab));
+	tab->file= allocate((strlen(file) + 1) * sizeof(tab->file[0]));
+	strcpy(tab->file, file);
+	tab->user= nil;
+	if (user != nil) {
+		tab->user= allocate((strlen(user) + 1) * sizeof(tab->user[0]));
+		strcpy(tab->user, user);
+	}
+	tab->data= allocate((st.st_size + 1) * sizeof(tab->data[0]));
+	tab->jobs= nil;
+	tab->mtime= st.st_mtime;
+	tab->current= 0;
+	tab->next= *atab;
+	*atab= tab;
+
+	/* Pull a new table in core. */
+	n= 0;
+	while (n < st.st_size) {
+		if ((r = read(fd, tab->data + n, st.st_size - n)) < 0) {
+			log(LOG_CRIT, "%s: %s", file, strerror(errno));
+			close(fd);
+			return;
+		}
+		if (r == 0) break;
+		n+= r;
+	}
+	close(fd);
+	tab->data[n]= 0;
+	if (strlen(tab->data) < n) {
+		log(LOG_ERR, "%s contains a null character\n", file);
+		return;
+	}
+
+	/* Parse the file. */
+	ajob= &tab->jobs;
+	p= tab->data;
+	ok= 1;
+	while (ok && *p != 0) {
+		q= get_token(&p);
+		if (*q == '#' || q == p) {
+			/* Comment or empty. */
+			while (*p != 0 && *p++ != '\n') {}
+			continue;
+		}
+
+		/* One new job coming up. */
+		*ajob= job= allocate(sizeof(*job));
+		*(ajob= &job->next)= nil;
+		job->tab= tab;
+
+		if (!range_parse(file, q, job->min, 0, 59, &wc)) {
+			ok= 0;
+			break;
+		}
+
+		q= get_token(&p);
+		if (!range_parse(file, q, job->hour, 0, 23, &wc)) {
+			ok= 0;
+			break;
+		}
+
+		q= get_token(&p);
+		if (!range_parse(file, q, job->mday, 1, 31, &wc)) {
+			ok= 0;
+			break;
+		}
+		job->do_mday= !wc;
+
+		q= get_token(&p);
+		if (!range_parse(file, q, job->mon, 1, 12, &wc)) {
+			ok= 0;
+			break;
+		}
+		job->do_mday |= !wc;
+
+		q= get_token(&p);
+		if (!range_parse(file, q, job->wday, 0, 7, &wc)) {
+			ok= 0;
+			break;
+		}
+		job->do_wday= !wc;
+
+		/* 7 is Sunday, but 0 is a common mistake because it is in the
+		 * tm_wday range.  We allow and even prefer it internally.
+		 */
+		if (bit_isset(job->wday, 7)) {
+			bit_clr(job->wday, 7);
+			bit_set(job->wday, 0);
+		}
+
+		/* The month range is 1-12, but tm_mon likes 0-11. */
+		job->mon[0] >>= 1;
+		if (bit_isset(job->mon, 8)) bit_set(job->mon, 7);
+		job->mon[1] >>= 1;
+
+		/* Scan for options. */
+		job->user= nil;
+		while (q= get_token(&p), *q == '-') {
+			q++;
+			if (q[0] == '-' && q+1 == p) {
+				/* -- */
+				q= get_token(&p);
+				break;
+			}
+			while (q < p) switch (*q++) {
+			case 'u':
+				if (q == p) q= get_token(&p);
+				if (q == p) goto usage;
+				memmove(q-1, q, p-q);	/* gross... */
+				p[-1]= 0;
+				job->user= q-1;
+				q= p;
+				break;
+			default:
+			usage:
+				log(LOG_ERR,
+			"%s: bad option -%c, good options are: -u username\n",
+					file, q[-1]);
+				ok= 0;
+				goto endtab;
+			}
+		}
+
+		/* A crontab owned by a user can only do things as that user. */
+		if (tab->user != nil) job->user= tab->user;
+
+		/* Inspect the first character of the command. */
+		job->cmd= q;
+		if (q == p || *q == '#') {
+			/* Rest of the line is empty, i.e. the commands are on
+			 * the following lines indented by one tab.
+			 */
+			while (*p != 0 && *p++ != '\n') {}
+			if (*p++ != '\t') {
+				log(LOG_ERR, "%s: contains an empty command\n",
+					file);
+				ok= 0;
+				goto endtab;
+			}
+			while (*p != 0) {
+				if ((*q = *p++) == '\n') {
+					if (*p != '\t') break;
+					p++;
+				}
+				q++;
+			}
+		} else {
+			/* The command is on this line.  Alas we must now be
+			 * backwards compatible and change %'s to newlines.
+			 */
+			p= q;
+			while (*p != 0) {
+				if ((*q = *p++) == '\n') break;
+				if (*q == '%') *q= '\n';
+				q++;
+			}
+		}
+		*q= 0;
+		job->rtime= now;
+		job->late= 0;		/* It is on time. */
+		job->atjob= 0;		/* True cron job. */
+		job->pid= IDLE_PID;	/* Not running yet. */
+		tab_reschedule(job);	/* Compute next time to run. */
+	}
+  endtab:
+
+	if (ok) tab->current= 1;
+}
+
+void tab_find_atjob(char *atdir)
+/* Find the first to be executed AT job and kludge up an crontab job for it.
+ * We set tab->file to "atdir/jobname", tab->data to "atdir/past/jobname",
+ * and job->cmd to "jobname".
+ */
+{
+	DIR *spool;
+	struct dirent *entry;
+	time_t t0, t1;
+	struct tm tmnow, tmt1;
+	static char template[] = "96.365.1546.00";
+	char firstjob[sizeof(template)];
+	int i;
+	crontab_t *tab;
+	cronjob_t *job;
+
+	if ((spool= opendir(atdir)) == nil) return;
+
+	tmnow= *localtime(&now);
+	t0= NEVER;
+
+	while ((entry= readdir(spool)) != nil) {
+		/* Check if the name fits the template. */
+		for (i= 0; template[i] != 0; i++) {
+			if (template[i] == '.') {
+				if (entry->d_name[i] != '.') break;
+			} else {
+				if (!isdigit(entry->d_name[i])) break;
+			}
+		}
+		if (template[i] != 0 || entry->d_name[i] != 0) continue;
+
+		/* Convert the name to a time.  Careful with the century. */
+		memset(&tmt1, 0, sizeof(tmt1));
+		tmt1.tm_year= atoi(entry->d_name+0);
+		while (tmt1.tm_year < tmnow.tm_year-10) tmt1.tm_year+= 100;
+		tmt1.tm_mday= 1+atoi(entry->d_name+3);
+		tmt1.tm_min= atoi(entry->d_name+7);
+		tmt1.tm_hour= tmt1.tm_min / 100;
+		tmt1.tm_min%= 100;
+		tmt1.tm_isdst= -1;
+		if ((t1= mktime(&tmt1)) == -1) {
+			/* Illegal time?  Try in winter time. */
+			tmt1.tm_isdst= 0;
+			if ((t1= mktime(&tmt1)) == -1) continue;
+		}
+		if (t1 < t0) {
+			t0= t1;
+			strcpy(firstjob, entry->d_name);
+		}
+	}
+	closedir(spool);
+
+	if (t0 == NEVER) return;	/* AT job spool is empty. */
+
+	/* Create new table and job structures. */
+	tab= allocate(sizeof(*tab));
+	tab->file= allocate((strlen(atdir) + 1 + sizeof(template))
+						* sizeof(tab->file[0]));
+	strcpy(tab->file, atdir);
+	strcat(tab->file, "/");
+	strcat(tab->file, firstjob);
+	tab->data= allocate((strlen(atdir) + 6 + sizeof(template))
+						* sizeof(tab->data[0]));
+	strcpy(tab->data, atdir);
+	strcat(tab->data, "/past/");
+	strcat(tab->data, firstjob);
+	tab->user= nil;
+	tab->mtime= 0;
+	tab->current= 1;
+	tab->next= crontabs;
+	crontabs= tab;
+
+	tab->jobs= job= allocate(sizeof(*job));
+	job->next= nil;
+	job->tab= tab;
+	job->user= nil;
+	job->cmd= tab->data + strlen(atdir) + 6;
+	job->rtime= t0;
+	job->late= 0;
+	job->atjob= 1;		/* One AT job disguised as a cron job. */
+	job->pid= IDLE_PID;
+
+	if (job->rtime < next) next= job->rtime;
+}
+
+void tab_purge(void)
+/* Remove table data that is no longer current.  E.g. a crontab got removed.
+ */
+{
+	crontab_t **atab, *tab;
+	cronjob_t *job;
+
+	atab= &crontabs;
+	while ((tab= *atab) != nil) {
+		if (tab->current) {
+			/* Table is fine. */
+			tab->current= 0;
+			atab= &tab->next;
+		} else {
+			/* Table is not, or no longer valid; delete. */
+			*atab= tab->next;
+			while ((job= tab->jobs) != nil) {
+				tab->jobs= job->next;
+				deallocate(job);
+			}
+			deallocate(tab->data);
+			deallocate(tab->file);
+			deallocate(tab->user);
+			deallocate(tab);
+		}
+	}
+}
+
+static cronjob_t *reap_or_find(pid_t pid)
+/* Find a finished job or search for the next one to run. */
+{
+	crontab_t *tab;
+	cronjob_t *job;
+	cronjob_t *nextjob;
+
+	nextjob= nil;
+	next= NEVER;
+	for (tab= crontabs; tab != nil; tab= tab->next) {
+		for (job= tab->jobs; job != nil; job= job->next) {
+			if (job->pid == pid) {
+				job->pid= IDLE_PID;
+				tab_reschedule(job);
+			}
+			if (job->pid != IDLE_PID) continue;
+			if (job->rtime < next) next= job->rtime;
+			if (job->rtime <= now) nextjob= job;
+		}
+	}
+	return nextjob;
+}
+
+void tab_reap_job(pid_t pid)
+/* A job has finished.  Try to find it among the crontab data and reschedule
+ * it.  Recompute time next to run a job.
+ */
+{
+	(void) reap_or_find(pid);
+}
+
+cronjob_t *tab_nextjob(void)
+/* Find a job that should be run now.  If none are found return null.
+ * Update 'next'.
+ */
+{
+	return reap_or_find(NO_PID);
+}
+
+static void pr_map(FILE *fp, bitmap_t map)
+{
+	int last_bit= -1, bit;
+	char *sep;
+
+	sep= "";
+	for (bit= 0; bit < 64; bit++) {
+		if (bit_isset(map, bit)) {
+			if (last_bit == -1) last_bit= bit;
+		} else {
+			if (last_bit != -1) {
+				fprintf(fp, "%s%d", sep, last_bit);
+				if (last_bit != bit-1) {
+					fprintf(fp, "-%d", bit-1);
+				}
+				last_bit= -1;
+				sep= ",";
+			}
+		}
+	}
+}
+
+void tab_print(FILE *fp)
+/* Print out a stored crontab file for debugging purposes. */
+{
+	crontab_t *tab;
+	cronjob_t *job;
+	char *p;
+	struct tm tm;
+
+	for (tab= crontabs; tab != nil; tab= tab->next) {
+		fprintf(fp, "tab->file = \"%s\"\n", tab->file);
+		fprintf(fp, "tab->user = \"%s\"\n",
+				tab->user == nil ? "(root)" : tab->user);
+		fprintf(fp, "tab->mtime = %s", ctime(&tab->mtime));
+
+		for (job= tab->jobs; job != nil; job= job->next) {
+			if (job->atjob) {
+				fprintf(fp, "AT job");
+			} else {
+				pr_map(fp, job->min); fputc(' ', fp);
+				pr_map(fp, job->hour); fputc(' ', fp);
+				pr_map(fp, job->mday); fputc(' ', fp);
+				pr_map(fp, job->mon); fputc(' ', fp);
+				pr_map(fp, job->wday);
+			}
+			if (job->user != nil && job->user != tab->user) {
+				fprintf(fp, " -u %s", job->user);
+			}
+			fprintf(fp, "\n\t");
+			for (p= job->cmd; *p != 0; p++) {
+				fputc(*p, fp);
+				if (*p == '\n') fputc('\t', fp);
+			}
+			fputc('\n', fp);
+			tm= *localtime(&job->rtime);
+			fprintf(fp, "    rtime = %.24s%s\n", asctime(&tm),
+				tm.tm_isdst ? " (DST)" : "");
+			if (job->pid != IDLE_PID) {
+				fprintf(fp, "    pid = %ld\n", (long) job->pid);
+			}
+		}
+	}
+}
+
+/*
+ * $PchId: tab.c,v 1.5 2000/07/25 22:07:51 philip Exp $
+ */
Index: /trunk/minix/commands/cron/tab.h
===================================================================
--- /trunk/minix/commands/cron/tab.h	(revision 9)
+++ /trunk/minix/commands/cron/tab.h	(revision 9)
@@ -0,0 +1,72 @@
+/*	tab.h - in-core crontab data			Author: Kees J. Bot
+ *								7 Dec 1996
+ */
+#ifndef TAB__H
+#define TAB__H
+
+#include <sys/types.h>
+#include <limits.h>
+
+struct crontab;
+
+typedef unsigned char bitmap_t[8];
+
+typedef struct cronjob {	/* One entry in a crontab file */
+	struct cronjob	*next;
+	struct crontab	*tab;		/* Associated table file. */
+	bitmap_t	min;		/* Minute (0-59) */
+	bitmap_t	hour;		/* Hour (0-23) */
+	bitmap_t	mday;		/* Day of the month (1-31) */
+	bitmap_t	mon;		/* Month (1-12) */
+	bitmap_t	wday;		/* Weekday (0-7 with 0 = 7 = Sunday) */
+	char		*user;		/* User to run it as (nil = root) */
+	char		*cmd;		/* Command to run */
+	time_t		rtime;		/* When next to run */
+	char		do_mday;	/* True iff mon or mday is not '*' */
+	char		do_wday;	/* True iff wday is not '*' */
+	char		late;		/* True iff the job is late */
+	char		atjob;		/* True iff it is an AT job */
+	pid_t		pid;		/* Process-id of job if nonzero */
+} cronjob_t;
+
+typedef struct crontab {
+	struct crontab	*next;
+	char		*file;		/* Crontab name */
+	char		*user;		/* Owner if non-null */
+	time_t		mtime;		/* Last modified time */
+	cronjob_t	*jobs;		/* List of jobs in the file */
+	char		*data;		/* File data */
+	int		current;	/* True if current, i.e. file exists */
+} crontab_t;
+
+crontab_t *crontabs;		/* All crontabs. */
+
+/* A time as far in the future as possible. */
+#define NEVER		((time_t) ((time_t) -1 < 0 ? LONG_MAX : ULONG_MAX))
+
+/* Don't trust crontabs bigger than this: */
+#define TAB_MAX		((sizeof(int) == 2 ? 8 : 128) * 1024)
+
+/* Pid if no process running, or a pid value you'll never see. */
+#define IDLE_PID	((pid_t) 0)
+#define NO_PID		((pid_t) -1)
+
+/* Bitmap operations. */
+#define bit_set(map, n)		((void) ((map)[(n) >> 3] |= (1 << ((n) & 7))))
+#define bit_clr(map, n)		((void) ((map)[(n) >> 3] &= ~(1 << ((n) & 7))))
+#define bit_isset(map, n)	(!!((map)[(n) >> 3] & (1 << ((n) & 7))))
+
+/* Functions. */
+void tab_parse(char *file, char *user);
+void tab_find_atjob(char *atdir);
+void tab_purge(void);
+void tab_reap_job(pid_t pid);
+void tab_reschedule(cronjob_t *job);
+cronjob_t *tab_nextjob(void);
+void tab_print(FILE *fp);
+
+#endif /* TAB__H */
+
+/*
+ * $PchId: tab.h,v 1.3 2000/07/17 07:57:27 philip Exp $
+ */
Index: /trunk/minix/commands/de/Makefile
===================================================================
--- /trunk/minix/commands/de/Makefile	(revision 9)
+++ /trunk/minix/commands/de/Makefile	(revision 9)
@@ -0,0 +1,22 @@
+# Makefile for de
+
+CC	= exec cc
+CFLAGS	= -O -D_MINIX -D_POSIX_SOURCE -D_POSIX_1_SOURCE=2
+
+all:	de
+
+OBJS	= de.o de_stdin.o de_stdout.o de_diskio.o de_recover.o
+
+de:	$(OBJS)
+	$(CC) -i $(OBJS) -o de
+	install -S 4kw de
+
+install:	/usr/bin/de
+
+/usr/bin/de:	de
+	install -cs -o bin de $@
+
+$(OBJS): de.h
+
+clean:
+	rm -f *.bak *.o de
Index: /trunk/minix/commands/de/README
===================================================================
--- /trunk/minix/commands/de/README	(revision 9)
+++ /trunk/minix/commands/de/README	(revision 9)
@@ -0,0 +1,156 @@
+		de - A Minix Disk Editor
+
+	      Terrence W. Holm, Jan. 1989
+
+
+INTRODUCTION
+
+    The de(1) disk editor allows a system administrator to
+    look at and modify a Minix file system device. Commands
+    allow movement throughout a file system device, displaying
+    information in a couple of formats, writing blocks from
+    the device onto another file, and rewriting words on the
+    disk.
+
+    A few changes to the Minix file system aid recovering files.
+    I-node numbers are retained in directory entries now (they
+    get moved to the end). And all the i-node information is not
+    zeroed-out when a file is unlinked. So, after a file is
+    accidently rm(1)'ed, you can find the old i-node, and then
+    manually (or automatically) go to each of the freed blocks
+    and write them to a new file.
+
+
+USES FOR THE DISK EDITOR
+
+    1)	EDUCATION. Students can look at a file system in
+        a painless manner. For example you don't have to
+	use od(1) to look at the zone numbers in i-nodes.
+
+	A simple assignment is to change the size of an un-mounted
+	floppy disk file system from 360 to 300 blocks. (A more
+	difficult assignment is to explain why this works, even
+	though fsck(1) and df(1) do not report the correct number
+	of free blocks. :-)
+
+    2)  ADMINISTRATION. You can visually check inconsistencies
+	reported by fsck(1) before letting fsck(1) fix them.
+	You can change any word on the disk, this greatly simplifies
+	editing file system information. For example, changing the
+	size of a block special device is actually fun, no more
+	"blind" writing to your partitions.
+
+	Bit maps can be displayed with 2048 "bits" per screen,
+	(on the IBM/PC console), see how your zones are allocated!
+
+    3)  RECOVERING LOST FILES. You can search a disk for an ASCII
+	string, once found, the block can be written out to a file.
+
+	A one line change to fs/path.c allows users to get the i-node
+	number for a file after it has been removed from a directory.
+
+	Another couple lines changed in the file system keep the
+	i-node information available until the i-node is reused
+	(normally this information is zeroed out when an i-node is
+	released.) This allows a de(1) user to go to a released
+	i-node, get all the block numbers, go to these blocks and
+	write them back to a new file.
+
+	The whole recovery process is automated by running "de -r file".
+	So, IF a file is unlink(2)'ed (eg. "rm file"), AND IF no one
+	allocates a new i-node or block in the mean-time, THEN you
+	can recover the file.
+
+
+RECOVERY SECURITY
+
+    Normally Minix hard disk partitions are r/w only by the super-user,
+    and floppy disks are r/w by anyone. This means that only "root"
+    can look at hard disk partitions, but others can use de(1) to play
+    with their floppy disks.
+
+    When recovering files ("de -r file"), a user requires access to
+    the major file system partitions. This can be done by:
+
+	(a) Give everyone access to the hard disks. DON'T DO THIS, it
+	    defeats all the file system protection we already have.
+
+	(b) Make de(1) set-uid "root". This is the way to go, IF you
+	    are running a Minix system that has NO ACCESS from the
+	    outside. This allows anyone to execute "de -r file", but only
+	    root to use "de /dev/hd3". De(1) does some checking when
+	    retrieving lost blocks, eg. making sure they really are
+	    free blocks and making sure the user owned the i-node.
+	    BUT, file system information has been lost when the file
+	    was unlink(2)'ed, so de(1) can not be 100% sure that a
+	    recovered block really belonged to the user. THIS IS A
+	    SECURITY HOLE. [Since the only access to my machine is from
+	    observable terminals and their associated humans, I run
+	    de(1) as set-uid root.]
+
+	(c) Keep the disks rw-------, and don't set-uid de(1). This
+	    means that only the super-user can recover lost files.
+	    So, if you accidently "rm", you must tell the system
+	    administrator to "su" and recover your file, (be sure to
+	    inform the other users to stop whatever they are doing
+	    until the file is restored).
+
+
+INSTALLATION
+
+	- Install de.1 in /usr/man/cat1.
+
+	- Install the files: Makefile, README, de.h, de.c, de_stdin.c,
+	  de_stdout.c, de_diskio.c and de_recover.c in commands/de.
+	  Add -F and -T. to the Makefile, if necessary.
+
+	- "make" de(1). If a header file is not found, don't worry:
+	  You probably have it somewhere, just link it to what de(1)
+	  is looking for. This program also requires the subroutine
+	  tolower(3), see EFTH MINIX report #50, if you don't have it.
+
+	- Do you really want set-uid root on de?
+
+	- Patch the files fs/path.c, fs/link.c and fs/open.c. If
+	  you don't patch the file system then the recover option
+	  "-r" and associated commands ('x' and 'X') will not work,
+	  but de(1) is still functional and useful.
+
+	- "make" a new fs, using -DRECOVER. Rebuild a boot diskette.
+
+
+USING DE(1) FOR THE FIRST TIME
+
+    De(1) starts up in "word" mode at block 0 of the specified
+    device. Hit the PGDN (or space bar) a few times, observing
+    all the information on the screen. Each PGUP/PGDN moves to
+    the next 1024 byte block, (de(1) only knows about 1 block per
+    zone file systems). Note that "word" mode only displays 32
+    bytes at a time, so you are only observing the first 32 bytes
+    in the first few blocks when you skip using PGDN.
+
+    Now go back to block 3, (zone bit map), using "g 3 ENTER".
+    Change to "map" mode "v m", and then use the down arrow key
+    to check each 2 Megs in the zone bit map.
+
+    Now change to "block" mode using "v b". And go to some data
+    block, eg. "g 1000 ENTER". Use PGUP/PGDN to see what data
+    is in each nearby block.
+
+    Remember 'h' gives you a help page.
+
+    Try some more commands, for example: 'END', 'I', '/'.
+    (Note: searching through a whole disk under Minix takes a
+    long time: 30-60 seconds per megabyte, depending on your
+    machine, drive and controller, [Minix is embarrassingly slow].)
+
+    Don't worry about looking at a mounted device, you must specify
+    the "-w" option before the 's' command is operational, and
+    this command is the only one which will try to modify the
+    contents of the device.
+
+
+MINIX-ST
+
+    Please contact me if you are interesting in attempting a port
+    to MINIX-ST.
Index: /trunk/minix/commands/de/build
===================================================================
--- /trunk/minix/commands/de/build	(revision 9)
+++ /trunk/minix/commands/de/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/de/de.c
===================================================================
--- /trunk/minix/commands/de/de.c	(revision 9)
+++ /trunk/minix/commands/de/de.c	(revision 9)
@@ -0,0 +1,1335 @@
+/****************************************************************/
+/*								*/
+/*	de.c							*/
+/*								*/
+/*		Main loop of the "Disk editor".			*/
+/*								*/
+/****************************************************************/
+/*  origination         1989-Jan-15        Terrence W. Holm	*/
+/****************************************************************/
+
+
+#include <minix/config.h>
+#include <sys/types.h>
+#include <sys/dir.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <errno.h>
+#undef ERROR			/* arrgghh, errno.h has this pollution */
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <minix/const.h>
+#include <minix/type.h>
+#include "../../servers/fs/const.h"
+#include "../../servers/fs/type.h"
+#include "../../servers/fs/inode.h"
+
+#include "de.h"
+
+static char copyright[] = "de  (c) Terrence W. Holm 1989";
+
+
+_PROTOTYPE(void Push , (de_state *s ));
+_PROTOTYPE(int Get_Base , (int *base ));
+_PROTOTYPE(int Get_Filename , (de_state *s ));
+_PROTOTYPE(int Get_Count , (char *units , unsigned long *result ));
+_PROTOTYPE(void Exec_Shell , (void));
+_PROTOTYPE(void Sigint , (int));
+
+
+
+/****************************************************************/
+/*								*/
+/*	main()							*/
+/*								*/
+/*		Initialize. Handle the "-r" recovery option if	*/
+/*		specified, else enter the main processing loop.	*/
+/*								*/
+/****************************************************************/
+
+
+void main( argc, argv )
+  int   argc;
+  char *argv[];
+
+  {
+  static de_state s;		/* it is safer not to put it on the stack
+				 * and some things probably now rely on zero
+				 * initialization
+				 */  
+  char *command_name = argv[0];
+  int   recover = 0;
+
+
+  s.device_mode = O_RDONLY;
+
+
+  /*  Parse arguments  */
+
+  if ( argc == 3  &&  strcmp( argv[1], "-r" ) == 0 )
+    {
+    recover = 1;
+    --argc;
+    ++argv;
+    }
+  else if ( argc == 3  &&  strcmp( argv[1], "-w" ) == 0 )
+    {
+    s.device_mode = O_RDWR;
+    --argc;
+    ++argv;
+    }
+
+  if ( argc != 2  ||  *argv[1] == '-' )
+    {
+    fprintf( stderr, "Usage: %s [-w] /dev/device\n", command_name );
+    fprintf( stderr, "       %s -r lost_file_name\n", command_name );
+    exit( 1 );
+    }
+
+
+  /*  Set the effective id to the real id. This eliminates	*/
+  /*  any increase in privilege done by a set-uid bit on the	*/
+  /*  executable file. We want to be "root" for recovering 	*/
+  /*  files, because we must be able to read the device.	*/
+  /*  However, in normal usage, de(1) should not let just 	*/
+  /*  anyone look at a file system, thus we drop the privilege.	*/
+  /*								*/
+  /*  NOTE: There is a security hole when using "-r" with a	*/
+  /*  set-uid de(1). Do not use set-uid root if there is any	*/
+  /*  way to externally access your Minix system.		*/
+
+  if ( ! recover )
+    {
+    setuid( getuid() );
+    setgid( getgid() );
+    }
+
+
+  /*  Set terminal characteristics, and ^C interrupt handler  */
+
+  Save_Term();
+
+  if ( signal( SIGINT, SIG_IGN ) != SIG_IGN )
+    {
+    signal( SIGINT,  Sigint );
+    signal( SIGQUIT, Sigint );
+    }
+
+  Set_Term();
+
+  if ( ! Init_Termcap() )
+    Error( "Requires a termcap entry" );
+
+
+
+  /*  Get the device file name. If recovering, also open an output file.  */
+
+  if ( recover )
+    {
+    char *dir_name;
+    char *file_name;
+    struct stat device_stat;
+    struct stat tmp_stat;
+
+    /*  Split the path name into a directory and a file name.  */
+
+    if ( strlen(argv[1]) > MAX_STRING )
+      Error( "Path name too long" );
+
+    if ( ! Path_Dir_File( argv[1], &dir_name, &file_name ) )
+      Error( "Recover aborted" );
+
+    /*  Find the device holding the directory.  */
+
+    if ( (s.device_name = File_Device( dir_name )) == NULL )
+      Error( "Recover aborted" );
+
+
+    /*  The output file will be in /tmp with the same file name.  */
+
+    strcpy( s.file_name, TMP );
+    strcat( s.file_name, "/" );
+    strcat( s.file_name, file_name );
+
+
+    /*  Make sure /tmp is not on the same device as the file we	   */
+    /*  are trying to recover (we don't want to use up the free	   */
+    /*  i-node and blocks before we get a chance to recover them). */
+
+    if ( stat( s.device_name, &device_stat ) == -1 )
+      Error( "Can not stat(2) device %s", s.device_name );
+
+    if ( stat( TMP, &tmp_stat ) == -1 )
+      Error( "Can not stat(2) directory %s", TMP );
+
+    if ( device_stat.st_rdev == tmp_stat.st_dev )
+      Error( "Will not recover files on the same device as %s", TMP );
+
+    if ( access( s.file_name, F_OK ) == 0 )
+      Error( "Will not overwrite file %s", s.file_name );
+
+
+    /*  Open the output file.  */
+
+    if ( (s.file_f = fopen( s.file_name, "w" )) == NULL )
+      Error( "Can not open file %s", s.file_name );
+
+    /*  Don't let anyone else look at the recovered file  */
+
+    chmod( s.file_name, 0700 );
+
+    /*  If running as root then change the owner of the  */
+    /*  restored file. If not running as root then the   */
+    /*  chown(2) will fail.				 */
+
+    chown( s.file_name, getuid(), getgid() );
+    }
+  else
+    {
+    s.device_name = argv[1];
+    s.file_name[ 0 ] = '\0';
+    }
+
+
+  /*  Open the device file.  */
+
+  {
+  struct stat device_stat;
+  off_t size;
+
+  if ( stat( s.device_name, &device_stat ) == -1 )
+    Error( "Can not find file %s", s.device_name );
+
+  if ( (device_stat.st_mode & S_IFMT) != S_IFBLK  &&
+       (device_stat.st_mode & S_IFMT) != S_IFREG )
+    Error( "Can only edit block special or regular files" );
+
+
+  if ( (s.device_d = open( s.device_name, s.device_mode )) == -1 )
+    Error( "Can not open %s", s.device_name );
+
+  if ( (size = lseek( s.device_d, 0L, SEEK_END )) == -1 )
+    Error( "Error seeking %s", s.device_name );
+
+  if ( size % K != 0 )
+    {
+    Warning( "Device size is not a multiple of 1024" );
+    Warning( "The (partial) last block will not be accessible" );
+    }
+  }
+
+
+  /*  Initialize the rest of the state record  */
+
+  s.mode = WORD;
+  s.output_base = 10;
+  s.search_string[ 0 ] = '\0';
+
+  {
+  int i;
+
+  for ( i = 0;  i < MAX_PREV;  ++i )
+    {
+    s.prev_addr[ i ] = 0L;
+    s.prev_mode[ i ] = WORD;
+    }
+  }
+
+
+  sync();
+
+  Read_Super_Block( &s );
+
+  Read_Bit_Maps( &s );
+
+  s.address = 0L;
+
+
+
+  /*  Recover mode basically performs an 'x' and an 'X'  */
+
+  if ( recover )
+    {
+    ino_t inode = Find_Deleted_Entry( &s, argv[1] );
+    off_t size;
+
+    if ( inode == 0 )
+      {
+      unlink( s.file_name );
+      Error( "Recover aborted" );
+      }
+
+    s.address = ( (long) s.first_data - s.inode_blocks ) * K
+		      + (long) (inode - 1) * s.inode_size;
+
+    Read_Block( &s, s.buffer );
+
+
+    /*  Have found the lost i-node, now extract the blocks.  */
+
+    if ( (size = Recover_Blocks( &s )) == -1L )
+      {
+      unlink( s.file_name );
+      Error( "Recover aborted" );
+      }
+
+    Reset_Term();
+
+    printf( "Recovered %ld bytes, written to file %s\n", size, s.file_name );
+
+    exit( 0 );
+    }
+
+
+  /*  Enter the main loop, first time redraw the screen  */
+  {
+  int rc = REDRAW;
+
+
+  do
+    {
+    if ( rc == REDRAW )
+      {
+      Read_Block( &s, s.buffer );
+      Draw_Screen( &s );
+      s.last_addr = s.address;
+      Draw_Pointers( &s );
+      }
+
+    else if ( rc == REDRAW_POINTERS )
+      {
+      s.offset = (unsigned) (s.address & ~ K_MASK);
+      Draw_Pointers( &s );
+      }
+
+    else if ( rc == ERROR )
+      {
+      Erase_Prompt();
+      putchar( BELL );
+      }
+    } while ( (rc = Process( &s, Arrow_Esc(Get_Char()) )) != EOF );
+  }
+
+
+  /*  If there is an open output file that was never written to  */
+  /*  then remove its directory entry. This occurs when no 'w' 	 */
+  /*  or 'W' command occurred between a 'c' command and exiting	 */
+  /*  the program.						 */
+
+  if ( s.file_name[0] != '\0'  &&  ! s.file_written )
+    unlink( s.file_name );
+
+
+  Reset_Term();	   /*  Restore terminal characteristics  */
+
+  exit( 0 );
+  }
+
+
+
+/****************************************************************/
+/*								*/
+/*	Get_Base( base )					*/
+/*								*/
+/*		Get a new base value.				*/
+/*		Returns REDRAW or ERROR.			*/
+/*								*/
+/****************************************************************/
+
+
+
+int Get_Base( base )
+  int *base;
+  {
+	switch ( Get_Char() )
+	  {
+	  case 'h' :	*base = 16;
+			break;
+
+	  case 'd' :	*base = 10;
+			break;
+
+	  case 'o' :	*base = 8;
+			break;
+
+	  case 'b' :	*base = 2;
+			break;
+
+	  default  :	return( ERROR );
+	  }
+
+		return( REDRAW );
+  }
+
+
+
+/****************************************************************/
+/*								*/
+/*	Process( state, input_char )				*/
+/*								*/
+/*		Determine the function requested by the 	*/
+/*		input character. Returns OK, REDRAW,		*/
+/*		REDRAW_POINTERS,  ERROR or EOF.			*/
+/*								*/
+/****************************************************************/
+
+
+int Process( s, c )
+  de_state  *s;
+  int  c;
+
+  {
+  switch ( c )
+    {
+    case 'b' :				/*  Back up one block	*/
+    case ESC_PGUP :
+
+		if ( s->address == 0 )
+		  return( ERROR );
+
+		s->address = (s->address - K) & K_MASK;
+
+		return( REDRAW );
+
+
+    case 'B' :				/*  Back up to home	*/
+    case ESC_HOME :
+
+		if ( s->address == 0 )
+		  return( OK );
+
+		Push( s );
+
+		s->address = 0L;
+
+		return( REDRAW );
+
+
+    case 'c' :				/*  Change file name	*/
+
+		{
+		int rc = Get_Filename( s );
+
+		return( rc == OK ? REDRAW : rc );
+		}
+
+
+    case 'd' :				/*  Down		*/
+    case ESC_DOWN :
+
+		{
+		s->last_addr = s->address;
+
+		switch ( s->mode )
+		  {
+		  case WORD :	s->address += 2;
+
+				if ( (s->address & PAGE_MASK) == 0 )
+				  return( REDRAW );
+
+				return( REDRAW_POINTERS );
+
+		  case BLOCK :	s->address += 64;
+
+				if ( (s->last_addr & K_MASK) !=
+				     (s->address   & K_MASK) )
+				  return( REDRAW );
+
+				return( REDRAW_POINTERS );
+
+		  case MAP :	s->address += 256;
+
+				return( REDRAW );
+
+		  default :	Error( "Internal fault (mode)" );
+		  }
+		}
+
+
+    case 'f' :				/*  Forward one block	*/
+    case ' ' :
+    case ESC_PGDN :
+
+		if ( s->block == s->device_size - 1 )
+		  return( ERROR );
+
+		s->address = (s->address + K) & K_MASK;
+
+		return( REDRAW );
+
+
+    case 'F' :				/*  Forward to end	*/
+    case ESC_END :
+
+		{
+		off_t  last_block = ( (long) s->device_size - 1 ) * K;
+
+		if ( s->address == last_block )
+		  return( OK );
+
+		Push( s );
+
+		s->address = last_block;
+
+		return( REDRAW );
+		}
+
+
+    case 'g' :				/*  Goto block		*/
+
+		{
+		unsigned long block;
+
+		if ( Get_Count( "Block?", &block ) )
+		  {
+		  if ( block >= s->zones )
+		    {
+		    Warning( "Block number too large" );
+		    return( REDRAW );
+		    }
+
+		  Push( s );
+
+		  s->address = (off_t) block * K;
+
+		  return( REDRAW );
+		  }
+		else
+		  return( ERROR );
+		}
+
+
+    case 'G' :				/*  Goto block indirect	*/
+
+		{
+		unsigned block = *( (word_t *) &s->buffer[ s->offset ] );
+
+		if ( s->mode != WORD )
+		  {
+		  Warning( "Must be in visual mode \"word\"" );
+		  return( REDRAW );
+		  }
+
+		if ( block >= s->zones )
+		  {
+		  Warning( "Block number too large" );
+		  return( REDRAW );
+		  }
+
+		Push( s );
+
+		s->mode = BLOCK;
+		s->address = (long) block * K;
+
+		return( REDRAW );
+		}
+
+
+    case 'h' :				/*  Help		*/
+    case '?' :
+
+		Draw_Help_Screen( s );
+
+		Wait_For_Key();
+
+		return( REDRAW );
+
+
+    case 'i' :				/*  Goto i-node		*/
+
+		{
+		unsigned long inode;
+
+		if ( Get_Count( "I-node?", &inode ) )
+		  {
+		  if ( inode < 1  || inode > s->inodes )
+		    {
+		    Warning( "Illegal i-node number" );
+		    return( REDRAW );
+		    }
+
+		  Push( s );
+
+		  s->mode = WORD;
+		  s->address = (off_t) (s->first_data - s->inode_blocks) * K
+				  + (off_t) (inode - 1) * s->inode_size;
+
+		  return( REDRAW );
+		  }
+		else
+		  return( ERROR );
+		}
+
+
+    case 'I' :				/*  Filename to i-node	*/
+
+		{
+		ino_t inode;
+		char *filename;
+
+		Draw_Prompt( "File name?" );
+
+		filename = Get_Line();
+
+		if ( filename == NULL  ||  filename[0] == '\0' )
+		  return( ERROR );
+
+		inode = Find_Inode( s, filename );
+
+		if ( inode )
+		  {
+		  Push( s );
+
+		  s->mode = WORD;
+		  s->address = ( (long) s->first_data - s->inode_blocks ) * K
+				  + (long) (inode - 1) * s->inode_size;
+		  }
+
+		return( REDRAW );
+		}
+
+
+    case 'l' :				/*  Left		*/
+    case ESC_LEFT :
+
+		{
+		s->last_addr = s->address;
+
+		switch ( s->mode )
+		  {
+		  case WORD :	s->address = s->address - 32;
+
+				return( REDRAW );
+
+		  case BLOCK :	s->address -= 1;
+
+				if ( (s->last_addr & K_MASK) !=
+				     (s->address   & K_MASK) )
+				  return( REDRAW );
+
+				return( REDRAW_POINTERS );
+
+		  case MAP :	s->address -= 4;
+
+				if ( (s->last_addr & ~ MAP_MASK) !=
+				     (s->address   & ~ MAP_MASK) )
+				  return( REDRAW );
+
+				return( REDRAW_POINTERS );
+
+		  default :	Error( "Internal fault (mode)" );
+		  }
+		}
+
+
+    case 'm' :				/*  Invoke a Minix shell */
+
+		Reset_Term();
+
+		Exec_Shell();
+
+		Set_Term();
+
+		return( REDRAW );
+
+
+    case 'n' :				/*  Search for next	*/
+
+		{
+		off_t addr;
+
+		if ( s->search_string[0] == '\0' )
+		  {
+		  Warning( "No search string defined" );
+		  return( REDRAW );
+		  }
+
+		Draw_Prompt( "Searching..." );
+
+		if ( (addr = Search( s, s->search_string )) == -1L )
+		  {
+		  Warning( "Search string not found" );
+
+		  Wait_For_Key();
+
+		  return( REDRAW );
+		  }
+
+		Push( s );
+		s->address = addr;
+
+		return( REDRAW );
+		}
+
+
+    case 'o' :				/*  Set output base	*/
+
+		Draw_Prompt( "Output base?" );
+
+		return( Get_Base( &s->output_base ) );
+
+
+    case 'p' :				/*  Previous address	*/
+
+		{
+		int  i;
+
+		s->address = s->prev_addr[ 0 ];
+		s->mode    = s->prev_mode[ 0 ];
+
+  		for ( i = 0;  i < MAX_PREV - 1;  ++i )
+		  {
+    		  s->prev_addr[ i ] = s->prev_addr[ i + 1 ];
+		  s->prev_mode[ i ] = s->prev_mode[ i + 1 ];
+		  }
+
+		return( REDRAW );
+		}
+
+
+    case 'q' :				/*  Quit		 */
+    case EOF :
+    case CTRL_D :
+
+		return( EOF );
+
+
+    case 'r' :				/*  Right		*/
+    case ESC_RIGHT :
+
+		{
+		s->last_addr = s->address;
+
+		switch ( s->mode )
+		  {
+		  case WORD :	s->address += 32;
+
+				return( REDRAW );
+
+		  case BLOCK :	s->address += 1;
+
+				if ( (s->last_addr & K_MASK) !=
+				     (s->address   & K_MASK) )
+				  return( REDRAW );
+
+				return( REDRAW_POINTERS );
+
+		  case MAP :	s->address += 4;
+
+				if ( (s->last_addr & ~ MAP_MASK) !=
+				     (s->address   & ~ MAP_MASK) )
+				  return( REDRAW );
+
+				return( REDRAW_POINTERS );
+
+		  default :	Error( "Internal fault (mode)" );
+		  }
+		}
+
+    case 's' :				/*  Store word		*/
+
+		{
+		unsigned long word;
+
+		if ( s->mode != WORD )
+		  {
+		  Warning( "Must be in visual mode \"word\"" );
+		  return( REDRAW );
+		  }
+
+		if ( s->device_mode == O_RDONLY )
+		  {
+		  Warning( "Use -w option to open device for writing" );
+		  return( REDRAW );
+		  }
+
+		if ( Get_Count( "Store word?", &word ) )
+		  {
+		  if ( word != (word_t) word )
+		    {
+		      Warning( "Word is more than 16 bits" );
+		      return( REDRAW );
+		    }
+		  Write_Word( s, (word_t) word );
+
+		  return( REDRAW );
+		  }
+		else
+		  return( ERROR );
+		}
+
+
+    case 'u' :				/*  Up			*/
+    case ESC_UP :
+
+		{
+		s->last_addr = s->address;
+
+		switch ( s->mode )
+		  {
+		  case WORD :	s->address -= 2;
+
+				if ( (s->last_addr & PAGE_MASK) == 0 )
+				  return( REDRAW );
+
+				return( REDRAW_POINTERS );
+
+		  case BLOCK :	s->address -= 64;
+
+				if ( (s->last_addr & K_MASK) !=
+				     (s->address   & K_MASK) )
+				  return( REDRAW );
+
+				return( REDRAW_POINTERS );
+
+		  case MAP :	s->address -= 256;
+
+				return( REDRAW );
+
+		  default :	Error( "Internal fault (mode)" );
+		  }
+		}
+
+
+    case 'v' :				/*  Visual mode		*/
+
+		Draw_Prompt( "Visual mode?" );
+
+		switch ( Get_Char() )
+		  {
+		  case 'w' :	s->mode = WORD;
+				break;
+
+		  case 'b' :	s->mode = BLOCK;
+				break;
+
+		  case 'm' :	{
+				/* Assume user knows if map mode is possible
+				char *tty = ttyname( 0 );
+
+				if ( tty == NULL  ||
+				    strcmp( tty, "/dev/tty0" ) != 0 )
+				  Warning( "Must be at console" );
+				else
+				*/
+				  s->mode = MAP;
+
+				break;
+				}
+
+		  default  :	return( ERROR );
+		  }
+
+		return( REDRAW );
+
+
+    case 'w' :				/*  Write ASCII block	*/
+
+		if ( s->file_name[0] == '\0' )
+		  {
+		  int  rc = Get_Filename( s );
+
+		  if ( rc != OK )
+		    return( rc );
+		  }
+
+		/*  We have a successfully opened file  */
+
+		/*  Eliminate non-ASCII characters	*/
+		{
+		int i;
+		char buf[ K ];
+		char *from = s->buffer;
+		char *to = buf;
+
+		for ( i = 0;  i < K;  ++i, ++from )
+		  {
+		  *to = *from & 0x7f;
+
+		  if ( *to != '\0'  &&  *to != '\177' )
+		    ++to;
+		  }
+
+		if ( fwrite( buf, 1, (int)(to - buf), s->file_f ) != to - buf )
+		  Warning( "Problem writing out buffer" );
+
+		s->file_written = 1;
+
+		return( REDRAW );
+		}
+
+
+    case 'W' :				/*  Write block exactly	*/
+
+		if ( s->file_name[0] == '\0' )
+		  {
+		  int  rc = Get_Filename( s );
+
+		  if ( rc != OK )
+		    return( rc );
+		  }
+
+		/*  We have a successfully opened file  */
+
+		if ( fwrite( s->buffer, 1, K, s->file_f ) != K )
+		  Warning( "Problem writing out buffer" );
+
+		s->file_written = 1;
+
+		return( REDRAW );
+
+
+    case 'x' :				/*  eXtract lost entry	*/
+
+		{
+		ino_t inode;
+		char *filename;
+
+		Draw_Prompt( "Lost file name?" );
+
+		filename = Get_Line();
+
+		if ( filename == NULL  ||  filename[0] == '\0' )
+		  return( ERROR );
+
+		inode = Find_Deleted_Entry( s, filename );
+
+		if ( inode )
+		  {
+		  Push( s );
+
+		  s->mode = WORD;
+		  s->address = ( (long) s->first_data - s->inode_blocks ) * K
+				  + (long) (inode - 1) * s->inode_size;
+		  }
+
+		return( REDRAW );
+		}
+
+
+    case 'X' :				/*  eXtract lost blocks	*/
+
+		{
+		int  rc;
+
+		if ( s->mode != WORD )
+		  {
+		  Warning( "Must be in visual mode \"word\"" );
+		  return( REDRAW );
+		  }
+
+
+		/*  Force a new output file name.  */
+
+		if ( (rc = Get_Filename( s )) != OK )
+		  return( rc );
+
+
+		Draw_Strings( s );
+
+		Erase_Prompt();
+		Draw_Prompt( "Recovering..." );
+
+		if ( Recover_Blocks( s ) == -1L )
+		  unlink( s->file_name );
+
+		/*  Force closure of output file.  */
+
+		fclose( s->file_f );
+		s->file_name[ 0 ] = '\0';
+
+		return( REDRAW );
+		}
+
+
+    case '/' :				/*  Search		*/
+    case ESC_PLUS :
+
+		{
+		off_t addr;
+		char *string;
+
+		Draw_Prompt( "Search string?" );
+
+		string = Get_Line();
+
+		if ( string == NULL )
+		  return( ERROR );
+
+		if ( string[0] != '\0' )
+		  {
+		  strcpy( s->search_string, string );
+		  Draw_Strings( s );
+		  }
+
+		else if ( s->search_string[0] == '\0' )
+		  {
+		  Warning( "No search string defined" );
+		  return( REDRAW );
+		  }
+
+		Erase_Prompt();
+		Draw_Prompt( "Searching..." );
+
+		if ( (addr = Search( s, s->search_string )) == -1L )
+		  {
+		  Warning( "Search string not found" );
+
+		  Wait_For_Key();
+
+		  return( REDRAW );
+		  }
+
+		Push( s );
+
+		s->mode = BLOCK;
+		s->address = addr;
+
+		return( REDRAW );
+		}
+
+
+    default:
+		return( ERROR );
+    }
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Push( state )						*/
+/*								*/
+/*		Push current address and mode, used by the	*/
+/*		commands B, F, g, G, i, I, n, x and /.  This	*/
+/*		information is popped by the 'p' command.	*/
+/*								*/
+/****************************************************************/
+
+
+void Push( s )
+  de_state *s;
+
+  {
+  int  i;
+
+  for ( i = MAX_PREV - 1;  i > 0;  --i )
+    {
+    s->prev_addr[ i ] = s->prev_addr[ i - 1 ];
+    s->prev_mode[ i ] = s->prev_mode[ i - 1 ];
+    }
+
+  s->prev_addr[ 0 ] = s->address;
+  s->prev_mode[ 0 ] = s->mode;
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Get_Filename( state )					*/
+/*								*/
+/*		Read and check a filename.			*/
+/*								*/
+/****************************************************************/
+
+
+int Get_Filename( s )
+  de_state *s;
+
+  {
+  char *filename;
+  char *name;
+  FILE *f;
+
+  Draw_Prompt( "File name?" );
+
+  filename = Get_Line();
+
+  if ( filename == NULL  ||  filename[0] == '\0' )
+    return( ERROR );
+
+
+  for ( name = filename;  *name != '\0';  ++name )
+    if ( ! isgraph( *name ) )
+      {
+      Warning( "File name contains non-graphic characters" );
+      return( REDRAW );
+      }
+
+
+  if ( access( filename, F_OK ) == 0 )
+    {
+    Warning( "Will not overwrite file %s", filename );
+    return( REDRAW );
+    }
+
+  if ( (f = fopen( filename, "w" )) == NULL )
+    {
+    Warning( "Can not open file %s", filename );
+    return( REDRAW );
+    }
+
+  /*  If there is already an open output file then  */
+  /*  close it. If it was never written to then	    */
+  /*  remove its directory entry.		    */
+
+  if ( s->file_name[0] != '\0' )
+    {
+    if ( ! s->file_written )
+      unlink( s->file_name );
+
+    fclose( s->file_f );
+    }
+
+  strcpy( s->file_name, filename );
+  s->file_f = f;
+  s->file_written = 0;
+
+  return( OK );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Get_Count()						*/
+/*								*/
+/*		Read and check a number. Returns non-zero	*/
+/*		if successful.					*/
+/*								*/
+/****************************************************************/
+
+
+int Get_Count( units, result )
+  char *units;
+  unsigned long *result;
+
+  {
+  char *number;
+
+  Draw_Prompt( units );
+
+  number = Get_Line();
+
+  if ( number == NULL  ||  number[0] == '\0' )
+    return( 0 );
+
+  errno = 0;
+  *result = strtoul( number, (char **) NULL, 0 );
+  return( errno == 0 );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	In_Use( bit, map )					*/
+/*								*/
+/*		Is the bit set in the map?			*/
+/*								*/
+/****************************************************************/
+
+
+int In_Use( bit, map )
+  bit_t bit;
+  bitchunk_t *map;
+
+  {
+  return( map[ (int) (bit / (CHAR_BIT * sizeof (bitchunk_t))) ] &
+	  (1 << ((unsigned) bit % (CHAR_BIT * sizeof (bitchunk_t)))) );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Find_Inode( state, filename )				*/
+/*								*/
+/*		Find the i-node for the given file name.	*/
+/*								*/
+/****************************************************************/
+
+
+ino_t Find_Inode( s, filename )
+  de_state *s;
+  char *filename;
+
+  {
+  struct stat device_stat;
+  struct stat file_stat;
+  ino_t inode;
+
+
+  if ( fstat( s->device_d, &device_stat ) == -1 )
+    Error( "Can not fstat(2) file system device" );
+
+#ifdef S_IFLNK
+  if ( lstat( filename, &file_stat ) == -1 )
+#else
+  if ( stat( filename, &file_stat ) == -1 )
+#endif
+    {
+    Warning( "Can not find file %s", filename );
+    return( 0 );
+    }
+
+  if ( device_stat.st_rdev != file_stat.st_dev )
+    {
+    Warning( "File is not on device %s", s->device_name );
+    return( 0 );
+    }
+
+
+  inode = file_stat.st_ino;
+
+  if ( inode < 1  || inode > s->inodes )
+    {
+    Warning( "Illegal i-node number" );
+    return( 0 );
+    }
+
+  return( inode );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Exec_Shell()						*/
+/*								*/
+/*		Fork off a sub-process to exec() the shell.	*/
+/*								*/
+/****************************************************************/
+
+
+void Exec_Shell()
+
+  {
+  int pid = fork();
+
+  if ( pid == -1 )
+    return;
+
+
+  if ( pid == 0 )
+    {
+    /*  The child process  */
+
+    extern char **environ;
+    char *shell  =  getenv( "SHELL" );
+
+    if ( shell == NULL )
+      shell = "/bin/sh";
+
+    execle( shell, shell, (char *) 0, environ );
+
+    perror( shell );
+    exit( 127 );
+    }
+
+
+  /*  The parent process: ignore signals, wait for sub-process	*/
+
+  signal( SIGINT,  SIG_IGN );
+  signal( SIGQUIT, SIG_IGN );
+
+  {
+  int  status;
+  int  w;
+
+  while ( (w=wait(&status)) != pid  &&  w != -1 );
+  }
+
+  signal( SIGINT,  Sigint );
+  signal( SIGQUIT, Sigint );
+
+  return;
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Sigint()						*/
+/*								*/
+/*		Terminate the program on an interrupt (^C)	*/
+/*		or quit (^\) signal.				*/
+/*								*/
+/****************************************************************/
+
+
+void Sigint(n)
+int n;
+  {
+  Reset_Term();		/*  Restore terminal characteristics	*/
+
+  putchar( '\n' );
+
+  exit( 1 );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Error( text, ... )					*/
+/*								*/
+/*		Print an error message on stderr.		*/
+/*								*/
+/****************************************************************/
+
+
+#if __STDC__
+void Error( const char *text, ... )
+#else
+void Error( text )
+  char *text;
+#endif  
+
+  {
+  va_list argp;
+
+  Reset_Term();
+
+  fprintf( stderr, "\nde: " );
+  va_start( argp, text );
+  vfprintf( stderr, text, argp );
+  va_end( argp );
+  if ( errno != 0 )
+    fprintf( stderr, ": %s", strerror( errno ) );
+  fprintf( stderr, "\n" );
+
+  exit( 1 );
+  }
Index: /trunk/minix/commands/de/de.h
===================================================================
--- /trunk/minix/commands/de/de.h	(revision 9)
+++ /trunk/minix/commands/de/de.h	(revision 9)
@@ -0,0 +1,363 @@
+/****************************************************************/
+/*								*/
+/*	de.h							*/
+/*								*/
+/*		Definitions for the "Disk editor".		*/
+/*								*/
+/****************************************************************/
+/*  origination         1989-Jan-15        Terrence W. Holm	*/
+/****************************************************************/
+
+
+/****************************************************************/
+/*								*/
+/*	de(1)							*/
+/*								*/
+/*  This is the MINIX disk editor. It allows the user to	*/
+/*  observe and modify a file system. It can also be used	*/
+/*  to recover unlink(2)'ed files				*/
+/*								*/
+/*  See the de(1) man page.					*/
+/*								*/
+/****************************************************************/
+
+
+/****************************************************************/
+/*								*/
+/*	de		   Copyright  Terrence W. Holm  1989	*/
+/*								*/
+/* This program was written for users of the Minix operating	*/
+/* system, and in the spirit of other public domain software	*/
+/* written for said system, this source code is made available	*/
+/* at no cost to everyone. I assume no responsibility for	*/
+/* damage to file systems caused by this program.		*/
+/*								*/
+/* This program (one .h, five .c's and a "man" page) may be	*/
+/* copied and/or modified subject to (1) no charge must be	*/
+/* made for distribution, other than for the medium, (2) all	*/
+/* modified sources must be clearly marked as such, (3) all	*/
+/* sources must carry this copyright.				*/
+/*								*/
+/****************************************************************/
+
+
+/****************************************************************/
+/*								*/
+/*	files							*/
+/*								*/
+/*	    de.h		Definitions			*/
+/*	    de.c		The main loop			*/
+/*	    de_stdin.c		Character input routines	*/
+/*	    de_stdout.c		Output routines			*/
+/*	    de_diskio.c		File system read/write		*/
+/*	    de_recover.c	File restoration routines	*/
+/*								*/
+/*	    de.1		"Man" page			*/
+/*	    Makefile		For "make"			*/
+/*	    README		Installation help		*/
+/*								*/
+/*								*/
+/*	fs/path.c was modified to support the 'x' command.	*/
+/*	fs/link.c and fs/open.c were changed for 'X'.		*/
+/*								*/
+/****************************************************************/
+#undef printf
+#include <stdio.h>
+#include <dirent.h>
+
+/*  General constants  */
+
+#define   MAX_STRING	60		/*  For all input lines	*/
+#define   MAX_PREV	8		/*  For 'p' command	*/
+#define   SEARCH_BUFFER (4*K)		/*  For '/' and 'n'	*/
+
+
+/*  Files  */
+
+#define   TMP      "/tmp"		/*  For "-r" output	*/
+#define   DEV	   "/dev"		/*  Where devices are	*/
+
+
+/*  a.out header constants  (see a.out.h, if you have it)  */
+
+#if (CHIP == INTEL)
+#define   A_OUT    0x0301
+#define   SPLIT    0x0420
+#endif
+
+#if (CHIP == M68000)
+#define   A_OUT    0x0301
+#define   SPLIT	   0x0B20
+#endif
+
+#if (CHIP == SPARC)
+#define   A_OUT    0x0301
+#define   SPLIT    0x0B20
+#endif
+
+/*  Each buffer is 1k.  In WORD mode 16 words (32 bytes) can be	*/
+/*  displayed at once. In BLOCK mode 1K bytes can be displayed.	*/
+/*  In MAP mode 2048 bits (256 bytes) are displayed.		*/
+
+#define   K		1024		/*  STD_BLK		*/
+#define   K_MASK	(~(K-1))	/*  Round to K boundary	*/
+#define   K_SHIFT	10		/*  Ie. 1<<10 = K	*/
+#define   PAGE_MASK	0x1f		/*  Word mode: 32 bytes	*/
+#define   PAGE_SHIFT    5		/*  Ie. 1<<5 = 32	*/
+#define   MAP_BITS_PER_BLOCK (8 * K)    /*  1k block, 8192 bits */
+#define   MAP_MASK	0xff		/*  256 bytes/screen	*/
+
+
+
+/*  Terminal i/o codes  */
+
+#define   CTRL_D	'\004'		/*  ASCII ^D		*/
+#define   BELL		'\007'		/*  ASCII bell code     */
+#define   BS		'\010'		/*  ASCII back space	*/
+#define   CTRL_U	'\025'		/*  ASCII ^U		*/
+#define	  ESCAPE  	'\033'		/*  ASCII escape code	*/
+#define   DEL           '\177'		/*  ASCII delete code   */
+
+
+/*  Input escape codes generated by the	Minix console.	*/
+/*  Format: ESC [ X. 					*/
+
+#define   ESC_HOME	('H' + 0x80)
+#define   ESC_UP	('A' + 0x80)
+#define   ESC_PGUP	('V' + 0x80)
+#define   ESC_LEFT	('D' + 0x80)
+#define   ESC_5		('G' + 0x80)
+#define   ESC_RIGHT	('C' + 0x80)
+#define   ESC_END	('Y' + 0x80)
+#define   ESC_DOWN	('B' + 0x80)
+#define   ESC_PGDN	('U' + 0x80)
+#define   ESC_PLUS	('T' + 0x80)
+#define   ESC_MINUS	('S' + 0x80)
+
+
+/*  Graphic box codes - only applicable for console display  */
+/*  in visual mode "map".				     */
+
+#if (CHIP == INTEL)
+#define   BOX_CLR	' '		/*  Empty box		*/
+#define   BOX_ALL	'\333'		/*  Filled box		*/
+#define   BOX_TOP	'\337'		/*  Filled upper half	*/
+#define   BOX_BOT	'\334'		/*  Filled lower half   */
+#endif
+
+#if (CHIP == M68000)
+/*  Please change these.  */
+#define   BOX_CLR	' '		/*  Empty box		*/
+#define   BOX_ALL	'='		/*  Filled box		*/
+#define   BOX_TOP	'-'		/*  Filled upper half	*/
+#define   BOX_BOT	'_'		/*  Filled lower half   */
+#endif
+
+#if (CHIP == SPARC)
+/*  Please change these.  */
+#define   BOX_CLR	' '		/*  Empty box		*/
+#define   BOX_ALL	'='		/*  Filled box		*/
+#define   BOX_TOP	'-'		/*  Filled upper half	*/
+#define   BOX_BOT	'_'		/*  Filled lower half   */
+#endif
+
+/*  Move positions for the output display.  */
+
+#define   STATUS_COLUMN	 2
+#define   STATUS_LINE    0
+#define   BLOCK_COLUMN	 4
+#define   BLOCK_LINE	 4
+#define   INFO_COLUMN	 30
+#define   INFO_LINE	 BLOCK_LINE
+#define   PROMPT_COLUMN	 0
+#define   PROMPT_LINE	 23
+#define   WARNING_COLUMN 5
+#define   WARNING_LINE   10
+
+
+
+/*  Values returned by Process() and Get_Filename()  */
+
+#define   OK		  0		/*  No update required	*/
+#define   REDRAW	  1		/*  Redraw whole screen	*/
+#define   REDRAW_POINTERS 2		/*  Redraw just ptrs	*/
+#define   ERROR		  3		/*  Beep		*/
+
+
+/*  Visual modes  */
+
+#define   WORD	   1
+#define   BLOCK    2
+#define   MAP	   3
+
+typedef  unsigned short word_t;		/*  For most user i/o	*/
+#if _WORD_SIZE == 2
+typedef  unsigned int Word_t;		/*  What it should always be */
+#else
+typedef  int Word_t;			/*  Unsigned promotion under ANSI C */
+#endif
+
+#ifndef I_MAP_SLOTS
+/* Max number of inode and zone map blocks we can handle. */
+#define I_MAP_SLOTS	8
+#define Z_MAP_SLOTS	(sizeof(char *) == 2 ? 16 : 128)
+#endif
+
+typedef  struct  de_state		/*  State of disk ed.	*/
+  {
+  /*  Information from super block  */
+  /*  The types here are mostly promoted types for simplicity	*/
+  /*  and efficiency.						*/
+
+  unsigned inodes;			/*  Number of i-nodes	*/
+  zone_t zones;				/*  Total # of blocks	*/
+  unsigned inode_maps;			/*  I-node map blocks	*/
+  unsigned zone_maps;			/*  Zone map blocks	*/
+  unsigned inode_blocks;		/*  I-node blocks	*/
+  unsigned first_data;			/*  Total non-data blks	*/
+  int magic;				/*  Magic number	*/
+
+  /* Numbers derived from the magic number */  
+  
+  unsigned char is_fs;			/*  Nonzero for good fs	*/
+  unsigned char v1;			/*  Nonzero for V1 fs	*/
+  unsigned inode_size;			/*  Size of disk inode	*/
+  unsigned nr_indirects;		/*  # indirect blocks	*/
+  unsigned zone_num_size;		/*  Size of disk z num	*/
+  int block_size;			/*  FS block size       */
+
+  /* Other derived numbers */  
+  
+  bit_t inodes_in_map;			/*  Bits in i-node map	*/
+  bit_t zones_in_map;			/*  Bits in zone map	*/
+  int ndzones;				/*  # direct zones in an inode */
+
+  /*  Information from map blocks  */
+
+  bitchunk_t inode_map[ I_MAP_SLOTS * K / sizeof (bitchunk_t) ];
+  bitchunk_t zone_map[ Z_MAP_SLOTS * K / sizeof (bitchunk_t) ];
+
+  /*  Information for current block  */
+
+  off_t address;			/*  Current address	*/
+  off_t last_addr;			/*  For erasing ptrs	*/
+  zone_t block;				/*  Current block (1K)	*/
+  unsigned offset;			/*  Offset within block	*/
+
+  char buffer[ _MAX_BLOCK_SIZE ];
+
+  /*  Display state  */
+
+  int  mode;				/*  WORD, BLOCK or MAP	*/
+  int  output_base;			/*  2, 8, 10, or 16	*/
+
+  /*  Search information  */
+
+  char search_string[ MAX_STRING + 1 ];	/*  For '/' and 'n'	*/
+  off_t prev_addr[ MAX_PREV ];		/*  For 'p' command	*/
+  int   prev_mode[ MAX_PREV ];
+
+  /*  File information  */
+
+  char *device_name;			/*  From command line	*/
+  int   device_d;
+  int   device_mode;			/*  O_RDONLY or O_RDWR	*/
+  zone_t device_size;			/*  Number of blocks	*/
+
+  char  file_name[ MAX_STRING + 1 ];	/*  For 'w' and 'W'	*/
+  FILE *file_f;
+  int   file_written;			/*  Flag if written to	*/
+
+  }  de_state;
+
+
+
+/*  Forward references for external routines  */
+
+/*  de.c  */
+
+_PROTOTYPE(void main , (int argc , char *argv []));
+_PROTOTYPE(int Process , (de_state *s , int c ));
+
+#if __STDC__
+void  Error( const char *text, ... );
+#else
+void  Error();
+#endif
+
+_PROTOTYPE(int In_Use , (bit_t bit , bitchunk_t *map ));
+_PROTOTYPE(ino_t Find_Inode , (de_state *s , char *filename ));
+
+
+/*  de_stdin.c  */
+
+_PROTOTYPE(void Save_Term , (void));
+_PROTOTYPE(void Set_Term , (void));
+_PROTOTYPE(void Reset_Term , (void));
+_PROTOTYPE(int Get_Char , (void));
+_PROTOTYPE(char *Get_Line , (void));
+_PROTOTYPE(int Arrow_Esc , (int c ));
+
+/*  de_stdout.c  */
+
+_PROTOTYPE(int Init_Termcap , (void));
+_PROTOTYPE(void Draw_Help_Screen , (de_state *s ));
+_PROTOTYPE(void Wait_For_Key , (void));
+_PROTOTYPE(void Draw_Prompt , (char *string ));
+_PROTOTYPE(void Erase_Prompt , (void));
+
+_PROTOTYPE(void Draw_Screen , (de_state *s ));
+_PROTOTYPE(void Draw_Strings , (de_state *s ));
+_PROTOTYPE(void Draw_Pointers , (de_state *s ));
+_PROTOTYPE(void Print_Ascii , (int c ));
+
+_PROTOTYPE(void Goto , (int column , int line ));
+_PROTOTYPE(void Block_Type , (de_state *s ));
+_PROTOTYPE(void Draw_Words , (de_state *s ));
+_PROTOTYPE(void Draw_Info , (de_state *s ));
+_PROTOTYPE(void Draw_Block , (char *block ));
+_PROTOTYPE(void Draw_Map , (char *block , int max_bits ));
+_PROTOTYPE(void Draw_Offset , (de_state *s ));
+_PROTOTYPE(void Word_Pointers , (off_t old_addr , off_t new_addr ));
+_PROTOTYPE(void Block_Pointers , (off_t old_addr , off_t new_addr ));
+_PROTOTYPE(void Map_Pointers , (off_t old_addr , off_t new_addr ));
+_PROTOTYPE(void Print_Number , (Word_t number , int output_base ));
+_PROTOTYPE(void Draw_Zone_Numbers , (de_state *s , struct inode *inode ,
+						int zindex , int zrow ));
+
+#if __STDC__
+void  Warning( const char *text, ... );
+#else
+void  Warning();
+#endif
+
+
+/*  de_diskio.c  */
+
+_PROTOTYPE(void Read_Disk , (de_state *s , off_t block_addr , char *buffer ));
+_PROTOTYPE(void Read_Block , (de_state *s , char *buffer ));
+_PROTOTYPE(void Read_Super_Block , (de_state *s ));
+_PROTOTYPE(void Read_Bit_Maps , (de_state *s ));
+_PROTOTYPE(off_t Search , (de_state *s , char *string ));
+_PROTOTYPE(void Write_Word , (de_state *s , Word_t word ));
+
+
+/*  de_recover.c  */
+
+_PROTOTYPE(int Path_Dir_File , (char *path_name , char **dir_name ,
+							char **file_name ));
+_PROTOTYPE(char *File_Device , (char *file_name ));
+_PROTOTYPE(ino_t Find_Deleted_Entry , (de_state *s , char *path_name ));
+_PROTOTYPE(off_t Recover_Blocks , (de_state *s ));
+
+
+#undef    printf			/*  Because fs/const.h	*/
+					/*  defines it.		*/
+
+
+/*  Static functions are all pre-declared FORWARD but none are	*/
+/*  declared static yet - this can wait until all functions are	*/
+/*  declared with prototypes.					*/
+
+#undef FORWARD
+#define FORWARD /* static */
Index: /trunk/minix/commands/de/de_diskio.c
===================================================================
--- /trunk/minix/commands/de/de_diskio.c	(revision 9)
+++ /trunk/minix/commands/de/de_diskio.c	(revision 9)
@@ -0,0 +1,352 @@
+/****************************************************************/
+/*								*/
+/*	de_diskio.c						*/
+/*								*/
+/*		Reading and writing to a file system device.	*/
+/*								*/
+/****************************************************************/
+/*  origination         1989-Jan-15        Terrence W. Holm	*/
+/****************************************************************/
+
+
+#include <minix/config.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <dirent.h>
+
+#include <minix/const.h>
+#include <minix/type.h>
+#include "../../servers/fs/const.h"
+#include "../../servers/fs/type.h"
+#include "../../servers/fs/super.h"
+#include "../../servers/fs/inode.h"
+#include <minix/fslib.h>
+
+#include "de.h"
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Read_Disk( state, block_addr, buffer )			*/
+/*								*/
+/*		Reads a 1k block at "block_addr" into "buffer".	*/
+/*								*/
+/****************************************************************/
+
+
+void Read_Disk( s, block_addr, buffer )
+  de_state *s;
+  off_t  block_addr;
+  char  *buffer;
+
+  {
+  if ( lseek( s->device_d, block_addr, SEEK_SET ) == -1 )
+    Error( "Error seeking %s", s->device_name );
+
+  if ( read( s->device_d, buffer, s->block_size ) != s->block_size )
+    Error( "Error reading %s", s->device_name );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Read_Block( state, buffer )				*/
+/*								*/
+/*		Reads a 1k block from "state->address" into	*/
+/*		"buffer". Checks "address", and updates		*/
+/*		"block" and "offset".				*/
+/*								*/
+/****************************************************************/
+
+
+void Read_Block( s, buffer )
+  de_state *s;
+  char *buffer;
+
+  {
+  off_t end_addr;
+  off_t block_addr;
+  end_addr = (long) s->device_size * s->block_size - 1;
+
+  if ( s->address < 0 )
+    s->address = 0L;
+
+  if ( s->address > end_addr )
+    s->address = end_addr;
+
+  /*  The address must be rounded off for  */
+  /*  certain visual display modes.        */
+
+  if ( s->mode == WORD )
+    s->address &= ~1L;
+  else if ( s->mode == MAP )
+    s->address &= ~3L;
+
+
+  block_addr = s->address & K_MASK;
+
+  s->block  = (zone_t) (block_addr >> K_SHIFT);
+  s->offset = (unsigned) (s->address - block_addr);
+
+  Read_Disk( s, block_addr, buffer );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Read_Super_Block( state )				*/
+/*								*/
+/*		Read and check the super block.			*/
+/*								*/
+/****************************************************************/
+
+
+void Read_Super_Block( s )
+  de_state *s;
+
+  {
+  struct super_block *super = (struct super_block *) s->buffer;
+  unsigned inodes_per_block;
+  off_t size;
+
+  s->block_size = K;
+  Read_Disk( s, (long) SUPER_BLOCK_BYTES, s->buffer );
+
+  s->magic = super->s_magic;
+  if ( s->magic == SUPER_MAGIC )
+    {
+    s->is_fs = TRUE;
+    s->v1 = TRUE;
+    s->inode_size = V1_INODE_SIZE;
+    inodes_per_block = V1_INODES_PER_BLOCK;
+    s->nr_indirects = V1_INDIRECTS;
+    s->zone_num_size = V1_ZONE_NUM_SIZE;
+    s->zones = super->s_nzones;
+    s->ndzones = V1_NR_DZONES;
+    s->block_size = _STATIC_BLOCK_SIZE;
+    }
+  else if ( s->magic == SUPER_V2 || s->magic == SUPER_V3)
+    {
+    if(s->magic == SUPER_V3)
+    	s->block_size = super->s_block_size;
+    else
+    	s->block_size = _STATIC_BLOCK_SIZE;
+    s->is_fs = TRUE;
+    s->v1 = FALSE;
+    s->inode_size = V2_INODE_SIZE;
+    inodes_per_block = V2_INODES_PER_BLOCK(s->block_size);
+    s->nr_indirects = V2_INDIRECTS(s->block_size);
+    s->zone_num_size = V2_ZONE_NUM_SIZE;
+    s->zones = super->s_zones;
+    s->ndzones = V2_NR_DZONES;
+    }
+  else  
+    {
+    if ( super->s_magic == SUPER_REV )
+      Warning( "V1-bytes-swapped file system (?)" );
+    else if ( super->s_magic == SUPER_V2_REV )
+      Warning( "V2-bytes-swapped file system (?)" );
+    else  
+      Warning( "Not a Minix file system" );
+    Warning( "The file system features will not be available" );  
+    s->zones = 100000L;
+    return;
+    }
+
+  s->inodes = super->s_ninodes;
+  s->inode_maps = bitmapsize( (bit_t) s->inodes + 1 , s->block_size);
+  if ( s->inode_maps != super->s_imap_blocks )
+    {
+    if ( s->inode_maps > super->s_imap_blocks )
+      Error( "Corrupted inode map count or inode count in super block" );
+    else  
+      Warning( "Count of inode map blocks in super block suspiciously high" );
+    s->inode_maps = super->s_imap_blocks;
+    }
+
+  s->zone_maps = bitmapsize( (bit_t) s->zones , s->block_size);
+  if ( s->zone_maps != super->s_zmap_blocks )
+    {
+    if ( s->zone_maps > super->s_zmap_blocks )
+      Error( "Corrupted zone map count or zone count in super block" );
+    else
+      Warning( "Count of zone map blocks in super block suspiciously high" );
+    s->zone_maps = super->s_zmap_blocks;
+    }
+
+  s->inode_blocks = (s->inodes + inodes_per_block - 1) / inodes_per_block;
+  s->first_data   = 2 + s->inode_maps + s->zone_maps + s->inode_blocks;
+  if ( s->first_data != super->s_firstdatazone )
+  {
+    if ( s->first_data > super->s_firstdatazone )
+      Error( "Corrupted first data zone offset or inode count in super block" );
+    else
+      Warning( "First data zone in super block suspiciously high" );
+    s->first_data = super->s_firstdatazone;
+  }  
+
+  s->inodes_in_map = s->inodes + 1;
+  s->zones_in_map  = s->zones + 1 - s->first_data;
+
+  /*
+  if ( s->zones != s->device_size )
+    Warning( "Zone count does not equal device size" );
+  */
+
+  s->device_size = s->zones;
+
+  if ( super->s_log_zone_size != 0 )
+    Error( "Can not handle multiple blocks per zone" );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Read_Bit_Maps( state )					*/
+/*								*/
+/*		Read in the i-node and zone bit maps from the	*/
+/*		specified file system device.			*/
+/*								*/
+/****************************************************************/
+
+
+void Read_Bit_Maps( s )
+  de_state *s;
+
+  {
+  int i;
+
+  if ( s->inode_maps > I_MAP_SLOTS  ||  s->zone_maps > Z_MAP_SLOTS )
+    {
+    Warning( "Super block specifies too many bit map blocks" );
+    return;
+    }
+
+  for ( i = 0;  i < s->inode_maps;  ++i )
+    {
+    Read_Disk( s, (long) (2 + i) * K,
+	       (char *) &s->inode_map[ i * K / sizeof (bitchunk_t ) ] );
+    }
+
+  for ( i = 0;  i < s->zone_maps;  ++i )
+    {
+    Read_Disk( s, (long) (2 + s->inode_maps + i) * K,
+	       (char *) &s->zone_map[ i * K / sizeof (bitchunk_t ) ] );
+    }
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Search( state, string )					*/
+/*								*/
+/*		Search from the current address for the ASCII	*/
+/*		"string" on the device.				*/
+/*								*/
+/****************************************************************/
+
+
+off_t Search( s, string )
+  de_state *s;
+  char *string;
+
+  {
+  off_t address   = s->address + 1;
+  off_t last_addr = address;
+  char  buffer[ SEARCH_BUFFER ];
+  int   offset;
+  int   tail_length = strlen( string ) - 1;
+  int   count = SEARCH_BUFFER;
+  int   last_offset;
+
+
+  for (  ;  count == SEARCH_BUFFER;  address += SEARCH_BUFFER - tail_length )
+    {
+    if ( lseek( s->device_d, address, SEEK_SET ) == -1 )
+      Error( "Error seeking %s", s->device_name );
+
+    if ( (count = read( s->device_d, buffer, SEARCH_BUFFER)) == -1 )
+      Error( "Error reading %s", s->device_name );
+
+
+    if ( address - last_addr >= 500L * K )
+      {
+      putchar( '.' );
+      fflush( stdout );
+
+      last_addr += 500L * K;
+      }
+
+
+    last_offset = count - tail_length;
+
+    for ( offset = 0;  offset < last_offset;  ++offset )
+      {
+      register char c = buffer[ offset ];
+
+      if ( c == *string )
+	{
+	char *tail_buffer = &buffer[ offset + 1 ];
+	char *tail_string = string + 1;
+
+	do
+	  {
+	  if ( *tail_string == '\0' )
+	    return( address + offset );
+	  }
+          while ( *tail_buffer++ == *tail_string++ );
+        }
+      }  /*  end for ( offset )  */
+    }  /*  end for ( address )  */
+
+  return( -1L );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Write_Word( state, word )				*/
+/*								*/
+/*		Write a word at address.			*/
+/*								*/
+/****************************************************************/
+
+
+void Write_Word( s, word )
+  de_state *s;
+  word_t word;
+
+  {
+  if ( s->address & 01 )
+    Error( "Internal fault (unaligned address)" );
+
+  if ( lseek( s->device_d, s->address, SEEK_SET ) == -1 )
+    Error( "Error seeking %s", s->device_name );
+
+  if ( write( s->device_d, (char *) &word, sizeof word ) != sizeof word )
+    Error( "Error writing %s", s->device_name );
+  }
Index: /trunk/minix/commands/de/de_recover.c
===================================================================
--- /trunk/minix/commands/de/de_recover.c	(revision 9)
+++ /trunk/minix/commands/de/de_recover.c	(revision 9)
@@ -0,0 +1,612 @@
+/****************************************************************/
+/*								*/
+/*	de_recover.c						*/
+/*								*/
+/*		File restoration routines.			*/
+/*								*/
+/****************************************************************/
+/*  origination         1989-Jan-21        Terrence W. Holm	*/
+/*  handle "holes"	1989-Jan-28	   Terrence W. Holm	*/
+/****************************************************************/
+
+
+#include <minix/config.h>
+#include <sys/types.h>
+#include <sys/dir.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pwd.h>
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#include <minix/const.h>
+#include <minix/type.h>
+#include "../../servers/fs/const.h"
+#include "../../servers/fs/type.h"
+#include "../../servers/fs/inode.h"
+#include <minix/fslib.h>
+
+#include "de.h"
+
+_PROTOTYPE(int Indirect, (de_state *s, zone_t block, off_t *size, int dblind));
+_PROTOTYPE(int Data_Block, (de_state *s, zone_t block, off_t *file_size ));
+_PROTOTYPE(int Free_Block, (de_state *s, zone_t block ));
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Path_Dir_File( path_name, dir_name, file_name )		*/
+/*								*/
+/*		Split "path_name" into a directory name and	*/
+/*		a file name.					*/
+/*								*/
+/*		Zero is returned on error conditions.		*/
+/*								*/
+/****************************************************************/
+
+
+int Path_Dir_File( path_name, dir_name, file_name )
+  char  *path_name;
+  char **dir_name;
+  char **file_name;
+
+  {
+  char *p;
+  static char directory[ MAX_STRING + 1 ];
+  static char filename[ MAX_STRING + 1 ];
+
+
+  if ( (p = strrchr( path_name, '/' )) == NULL )
+    {
+    strcpy( directory, "." );
+    strcpy( filename, path_name );
+    }
+  else
+    {
+    *directory = '\0';
+    strncat( directory, path_name, p - path_name );
+    strcpy( filename, p + 1 );
+    }
+
+  if ( *directory == '\0' )
+    strcpy( directory, "/" );
+
+  if ( *filename == '\0' )
+    {
+    Warning( "A file name must follow the directory name" );
+    return( 0 );
+    }
+
+  *dir_name  = directory;
+  *file_name = filename;
+
+  return( 1 );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	File_Device( file_name )				*/
+/*								*/
+/*		Return the name of the file system device	*/
+/*		containing the file "file_name".		*/
+/*								*/
+/*		This is used if the "-r" option was specified.	*/
+/*		In this case we have only been given a file	*/
+/*		name, and must determine which file system	*/
+/*		device to open.					*/
+/*								*/
+/*		NULL is returned on error conditions.		*/
+/*								*/
+/****************************************************************/
+
+
+
+char *File_Device( file_name )
+  char *file_name;
+
+  {
+  struct stat file_stat;
+  struct stat device_stat;
+  int dev_d;
+  struct direct entry;
+  static char device_name[ NAME_MAX + 1 ];
+
+
+  if ( access( file_name, R_OK ) != 0 )
+    {
+    Warning( "Can not find %s", file_name );
+    return( NULL );
+    }
+
+
+  if ( stat( file_name, &file_stat ) == -1 )
+    {
+    Warning( "Can not stat(2) %s", file_name );
+    return( NULL );
+    }
+
+
+  /*  Open /dev for reading  */
+
+  if ( (dev_d = open( DEV, O_RDONLY )) == -1 )
+    {
+    Warning( "Can not read %s", DEV );
+    return( NULL );
+    }
+
+
+  while ( read( dev_d, (char *) &entry, sizeof(struct direct) )
+				     == sizeof(struct direct) )
+    {
+    if ( entry.d_ino == 0 )
+      continue;
+
+    strcpy( device_name, DEV );
+    strcat( device_name, "/" );
+    strncat( device_name, entry.d_name, NAME_MAX );
+
+    if ( stat( device_name, &device_stat ) == -1 )
+      continue;
+
+    if ( (device_stat.st_mode & S_IFMT) != S_IFBLK )
+      continue;
+
+    if ( file_stat.st_dev == device_stat.st_rdev )
+      {
+      close( dev_d );
+      return( device_name );
+      }
+    }
+
+  close( dev_d );
+
+  Warning( "The device containing file %s is not in %s", file_name, DEV );
+
+  return( NULL );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Find_Deleted_Entry( state, path_name )			*/
+/*								*/
+/*		Split "path_name" into a directory name and	*/
+/*		a file name. Then search the directory for	*/
+/*		an entry that would match the deleted file	*/
+/*		name. (Deleted entries have a zero i-node	*/
+/*		number, but the original i-node number is 	*/
+/*		placed at the end of the file name.)		*/
+/*								*/
+/*		If successful an i-node number is returned,	*/
+/*		else zero is returned.				*/
+/*								*/
+/****************************************************************/
+
+
+ino_t Find_Deleted_Entry( s, path_name )
+  de_state *s;
+  char *path_name;
+
+  {
+  char *dir_name;
+  char *file_name;
+
+
+  /*  Check if the file exists  */
+
+  if ( access( path_name, F_OK ) == 0 )
+    {
+    Warning( "File has not been deleted" );
+    return( 0 );
+    }
+
+
+  /*  Split the path name into a directory and a file name  */
+
+  if ( ! Path_Dir_File( path_name, &dir_name, &file_name ) )
+    return( 0 );
+
+
+  /*  Check to make sure the user has read permission on  */
+  /*  the directory.					  */
+
+  if ( access( dir_name, R_OK ) != 0 )
+    {
+    Warning( "Can not find %s", dir_name );
+    return( 0 );
+    }
+
+
+  /*  Make sure "dir_name" is really a directory. */
+  {
+  struct stat dir_stat;
+
+  if ( stat( dir_name, &dir_stat ) == -1   ||
+		 (dir_stat.st_mode & S_IFMT) != S_IFDIR )
+    {
+    Warning( "Can not find directory %s", dir_name );
+    return( 0 );
+    }
+  }
+
+
+  /*  Make sure the directory is on the current  */
+  /*  file system device.                        */
+
+  if ( Find_Inode( s, dir_name ) == 0 )
+    return( 0 );
+
+
+  /*  Open the directory and search for the lost file name.  */
+  {
+  int   dir_d;
+  int   count;
+  struct direct entry;
+
+  if ( (dir_d = open( dir_name, O_RDONLY )) == -1 )
+    {
+    Warning( "Can not read directory %s", dir_name );
+    return( 0 );
+    }
+
+  while ( (count = read( dir_d, (char *) &entry, sizeof(struct direct) ))
+					      == sizeof(struct direct) )
+    {
+    if ( entry.d_ino == 0  &&
+	strncmp( file_name, entry.d_name, NAME_MAX - sizeof(ino_t) ) == 0 )
+      {
+      ino_t inode = *( (ino_t *) &entry.d_name[ NAME_MAX - sizeof(ino_t) ] );
+
+      close( dir_d );
+
+      if ( inode < 1  || inode > s->inodes )
+    	{
+    	Warning( "Illegal i-node number" );
+    	return( 0 );
+    	}
+
+      return( inode );
+      }
+    }
+
+  close( dir_d );
+
+  if ( count == 0 )
+    Warning( "Can not find a deleted entry for %s", file_name );
+  else
+    Warning( "Problem reading directory %s", dir_name );
+
+  return( 0 );
+  }
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Recover_Blocks( state )					*/
+/*								*/
+/*		Try to recover all the blocks for the i-node	*/
+/*		currently pointed to by "s->address". The	*/
+/*		i-node and all of the blocks must be marked	*/
+/*		as FREE in the bit maps. The owner of the	*/
+/*		i-node must match the current real user name.	*/
+/*								*/
+/*		"Holes" in the original file are maintained.	*/
+/*		This allows moving sparse files from one device	*/
+/*		to another.					*/
+/*								*/
+/*		On any error -1L is returned, otherwise the	*/
+/*		size of the recovered file is returned.		*/
+/*								*/
+/*								*/
+/*		NOTE: Once a user has read access to a device,	*/
+/*		there is a security hole, as we lose the	*/
+/*		normal file system protection. For convenience,	*/
+/*		de(1) is sometimes set-uid root, this allows	*/
+/*		anyone to use the "-r" option. When recovering,	*/
+/*		Recover_Blocks() can only superficially check	*/
+/*		the validity of a request.			*/
+/*								*/
+/****************************************************************/
+
+
+off_t Recover_Blocks( s )
+  de_state *s;
+
+  {
+  struct inode core_inode;
+  d1_inode *dip1;
+  d2_inode *dip2;
+  struct inode *inode = &core_inode;
+  bit_t node = (s->address - (s->first_data - s->inode_blocks) * K) /
+		s->inode_size + 1;
+
+  dip1 = (d1_inode *) &s->buffer[ s->offset & ~ PAGE_MASK ];
+  dip2 = (d2_inode *) &s->buffer[ s->offset & ~ PAGE_MASK
+					    & ~ (V2_INODE_SIZE-1) ];
+  conv_inode( inode, dip1, dip2, READING, s->magic );
+
+  if ( s->block < s->first_data - s->inode_blocks  ||
+	    s->block >= s->first_data )
+    {
+    Warning( "Not in an inode block" );
+    return( -1L );
+    }
+
+
+  /*  Is this a valid, but free i-node?  */
+
+  if ( node > s->inodes )
+    {
+    Warning( "Not an inode" );
+    return( -1L );
+    }
+
+  if ( In_Use(node, s->inode_map) )
+    {
+    Warning( "I-node is in use" );
+    return( -1L );
+    }
+
+
+  /*  Only recover files that belonged to the real user.  */
+
+  {
+  uid_t real_uid = getuid();
+  struct passwd *user = getpwuid( real_uid );
+
+  if ( real_uid != SU_UID  &&  real_uid != inode->i_uid )
+    {
+    Warning( "I-node did not belong to user %s", user ? user->pw_name : "" );
+    return( -1L );
+    }
+  }
+
+
+  /*  Recover all the blocks of the file.  */
+
+  {
+  off_t file_size = inode->i_size;
+  int i;
+
+
+  /*  Up to s->ndzones pointers are stored in the i-node.  */
+
+  for ( i = 0;  i < s->ndzones;  ++i )
+    {
+    if ( file_size == 0 )
+	return( inode->i_size );
+
+    if ( ! Data_Block( s, inode->i_zone[ i ], &file_size ) )
+      return( -1L );
+    }
+
+  if ( file_size == 0 )
+    return( inode->i_size );
+
+
+  /*  An indirect block can contain up to inode->i_indirects more blk ptrs.  */
+
+  if ( ! Indirect( s, inode->i_zone[ s->ndzones ], &file_size, 0 ) )
+    return( -1L );
+
+  if ( file_size == 0 )
+    return( inode->i_size );
+
+
+  /*  A double indirect block can contain up to inode->i_indirects blk ptrs. */
+
+  if ( ! Indirect( s, inode->i_zone[ s->ndzones+1 ], &file_size, 1 ) )
+    return( -1L );
+
+  if ( file_size == 0 )
+    return( inode->i_size );
+
+  Error( "Internal fault (file_size != 0)" );
+  }
+
+  /* NOTREACHED */
+  return( -1L );
+  }
+
+
+
+
+
+
+/*  Indirect( state, block, &file_size, double )
+ *
+ *  Recover all the blocks pointed to by the indirect block
+ *  "block",  up to "file_size" bytes. If "double" is true,
+ *  then "block" is a double-indirect block pointing to
+ *  V*_INDIRECTS indirect blocks.
+ *
+ *  If a "hole" is encountered, then just seek ahead in the
+ *  output file.
+ */
+
+
+int Indirect( s, block, file_size, dblind )
+  de_state *s;
+  zone_t   block;
+  off_t    *file_size;
+  int       dblind;
+
+  {
+  union
+    {
+    zone1_t ind1[ V1_INDIRECTS ];
+    zone_t  ind2[ V2_INDIRECTS(_MAX_BLOCK_SIZE) ];
+    } indirect;
+  int  i;
+  zone_t zone;
+
+  /*  Check for a "hole".  */
+
+  if ( block == NO_ZONE )
+    {
+    off_t skip = (off_t) s->nr_indirects * K;
+
+    if ( *file_size < skip  ||  dblind )
+      {
+      Warning( "File has a hole at the end" );
+      return( 0 );
+      }
+
+    if ( fseek( s->file_f, skip, SEEK_CUR ) == -1 )
+      {
+      Warning( "Problem seeking %s", s->file_name );
+      return( 0 );
+      }
+
+    *file_size -= skip;
+    return( 1 );
+    }
+
+
+  /*  Not a "hole". Recover indirect block, if not in use.  */
+
+  if ( ! Free_Block( s, block ) )
+    return( 0 );
+
+
+  Read_Disk( s, (long) block << K_SHIFT, (char *) &indirect );
+
+  for ( i = 0;  i < s->nr_indirects;  ++i )
+    {
+    if ( *file_size == 0 )
+	return( 1 );
+
+    zone = (s->v1 ? indirect.ind1[ i ] : indirect.ind2[ i ]);
+    if ( dblind )
+      {
+      if ( ! Indirect( s, zone, file_size, 0 ) )
+	return( 0 );
+      }
+    else
+      {
+      if ( ! Data_Block( s, zone, file_size ) )
+        return( 0 );
+      }
+    }
+
+  return( 1 );
+  }
+
+
+
+
+
+
+/*  Data_Block( state, block, &file_size )
+ *
+ *  If "block" is free then write  Min(file_size, k)
+ *  bytes from it onto the current output file.
+ *
+ *  If "block" is zero, this means that a 1k "hole"
+ *  is in the file. The recovered file maintains
+ *  the reduced size by not allocating the block.
+ *
+ *  The file size is decremented accordingly.
+ */
+
+
+int Data_Block( s, block, file_size )
+  de_state *s;
+  zone_t   block;
+  off_t    *file_size;
+
+  {
+  char buffer[ K ];
+  off_t block_size = *file_size > K ? K : *file_size;
+
+
+  /*  Check for a "hole".  */
+
+  if ( block == NO_ZONE )
+    {
+    if ( block_size < K )
+      {
+      Warning( "File has a hole at the end" );
+      return( 0 );
+      }
+
+    if ( fseek( s->file_f, block_size, SEEK_CUR ) == -1 )
+      {
+      Warning( "Problem seeking %s", s->file_name );
+      return( 0 );
+      }
+
+    *file_size -= block_size;
+    return( 1 );
+    }
+
+
+  /*  Block is not a "hole". Copy it to output file, if not in use.  */
+
+  if ( ! Free_Block( s, block ) )
+    return( 0 );
+
+  Read_Disk( s, (long) block << K_SHIFT, buffer );
+
+
+  if ( fwrite( buffer, 1, (size_t) block_size, s->file_f )
+       != (size_t) block_size )
+    {
+    Warning( "Problem writing %s", s->file_name );
+    return( 0 );
+    }
+
+  *file_size -= block_size;
+  return( 1 );
+  }
+
+
+
+
+
+
+/*  Free_Block( state, block )
+ *
+ *  Make sure "block" is a valid data block number, and it
+ *  has not been allocated to another file.
+ */
+
+
+int Free_Block( s, block )
+  de_state *s;
+  zone_t  block;
+
+  {
+  if ( block < s->first_data  ||  block >= s->zones )
+    {
+    Warning( "Illegal block number" );
+    return( 0 );
+    }
+
+  if ( In_Use( (bit_t) (block - (s->first_data - 1)), s->zone_map ) )
+    {
+    Warning( "Encountered an \"in use\" data block" );
+    return( 0 );
+    }
+
+  return( 1 );
+  }
+
Index: /trunk/minix/commands/de/de_stdin.c
===================================================================
--- /trunk/minix/commands/de/de_stdin.c	(revision 9)
+++ /trunk/minix/commands/de/de_stdin.c	(revision 9)
@@ -0,0 +1,298 @@
+/****************************************************************/
+/*								*/
+/*	de_stdin.c						*/
+/*								*/
+/*		Processing input from the "de" user.		*/
+/*								*/
+/****************************************************************/
+/*  origination         1989-Jan-15        Terrence W. Holm	*/
+/****************************************************************/
+
+
+#include <sys/types.h>
+#include <termios.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include <minix/config.h>
+#include <minix/const.h>
+#include "../../servers/fs/const.h"
+#include "../../servers/fs/inode.h"
+
+#include "de.h"
+
+FORWARD _PROTOTYPE(int Timed_Get_Char , (int time ));
+FORWARD _PROTOTYPE(void Timed_Out , (int sig));
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Save_Term()						*/
+/*								*/
+/*		Save the current terminal characteristics.	*/
+/*								*/
+/*								*/
+/*	Set_Term()						*/
+/*								*/
+/*		Set up the terminal characteristics.		*/
+/*								*/
+/*								*/
+/*	Reset_Term()						*/
+/*								*/
+/*		Restore the terminal characteristics.		*/
+/*								*/
+/****************************************************************/
+
+
+static struct termios saved_term;
+
+
+void Save_Term()
+
+  {
+  tcgetattr( 0, &saved_term );
+  }
+
+
+
+
+void Set_Term()
+
+  {
+  struct termios term;
+
+  term = saved_term;
+
+
+  /*  No tab expansion, no echo, don't map ^M to ^J, cbreak mode  */
+
+  term.c_iflag &= ~ICRNL;
+  term.c_oflag &= ~OPOST;
+  term.c_lflag &= ~ICANON & ~ECHO;
+
+
+  /*  Change the interrupt character to ^C  */
+
+  term.c_cc[VINTR] = '\003';
+
+  tcsetattr( 0, TCSANOW, &term );
+  }
+
+
+
+
+void Reset_Term()
+
+  {
+  tcsetattr( 0, TCSANOW, &saved_term );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Get_Char()						*/
+/*								*/
+/*		Return the next input character. Escape		*/
+/*		sequences are mapped to special codes.		*/
+/*								*/
+/****************************************************************/
+
+
+int Get_Char()
+  {
+  int c;
+  static int unget_char = EOF;
+
+
+  /*  Flush the output to the screen before waiting  */
+  /*  for input from the user.			     */
+
+  fflush( stdout );
+
+  if ( unget_char == EOF )
+    {
+    while ( (c = Timed_Get_Char( 60 * 60 )) < EOF )
+      printf( "%c", BELL );
+    }
+  else
+    {
+    c = unget_char;
+    unget_char = EOF;
+    }
+
+  if ( c == EOF )
+    return( EOF );
+
+  if ( c != ESCAPE )
+    return( c );
+
+  if ( (c = Timed_Get_Char( 1 )) <= EOF )
+    return( ESCAPE );
+
+  if ( c != '[' )
+    {
+    unget_char = c;
+    return( ESCAPE );
+    }
+
+  if ( (c = Timed_Get_Char( 1 )) <= EOF )
+    {
+    unget_char = '[';
+    return( ESCAPE );
+    }
+
+  return( c | 0x80 );   /* Flag ESC [ x  */
+  }
+
+
+
+
+
+
+int Timed_Get_Char( time )
+  int time;
+
+  {
+  char c;
+  int  count;
+
+  signal( SIGALRM, Timed_Out );
+
+  alarm( time );
+  count = read( 0, &c, 1 );
+  alarm( 0 );
+
+  if ( count <= 0 )
+    return( EOF + count );
+
+  return( c & 0x7f );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Get_Line()						*/
+/*								*/
+/*		Read a line from the user. Returns a pointer	*/
+/*		to a local buffer, or NULL if DEL or a non-	*/
+/*		ASCII character was typed. Processes ^H and	*/
+/*		^U. ^M terminates the input.			*/
+/*								*/
+/****************************************************************/
+
+
+char *Get_Line()
+
+  {
+  int c;
+  int i;
+  static char line[ MAX_STRING + 1 ];
+
+  for ( i = 0;  i <= MAX_STRING;  ++i )
+    {
+    c = Get_Char();
+
+    if ( c == EOF  ||  c == DEL  ||  (c & 0x80) )
+	return( NULL );
+
+    if ( c == BS )
+	{
+	if ( --i >= 0 )
+	  {
+	  printf( "\b \b" );
+	  --i;
+	  }
+	}
+
+    else if ( c == CTRL_U )
+	{
+	for ( --i;  i >= 0;  --i )
+	  printf( "\b \b" );
+	}
+
+    else if ( c == '\r' )
+	{
+	line[ i ] = '\0';
+	return( line );
+	}
+
+    else if ( i < MAX_STRING )
+	{
+	line[ i ] = c;
+	Print_Ascii( c );
+	}
+
+    else  /*  Line buffer is full, don't add any more to it.  */
+	{
+	putchar( BELL );
+	--i;
+	}
+    }
+
+  Error( "Internal fault (line buffer overflow)" );
+
+  /* NOTREACHED */
+  return( NULL );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Arrow_Esc( char )					*/
+/*								*/
+/*		If the keyboard does not generate Ansi escape	*/
+/*		codes for the arrow keys, but does generate	*/
+/*		single byte control codes, then map these	*/
+/*		codes to the special characters we are using	*/
+/*		to denote the Ansi escape codes.		*/
+/*								*/
+/****************************************************************/
+
+
+extern  char   Kup;		/* (ku) - Up arrow key		*/
+extern  char   Kdown;		/* (kd) - Down arrow key	*/
+extern  char   Kleft;		/* (kl) - Left arrow key	*/
+extern  char   Kright;		/* (kr) - Right arrow key	*/
+
+
+int Arrow_Esc( c )
+  int c;
+
+  {
+  if ( c == Kup )
+    return( ESC_UP );
+
+  if ( c == Kdown )
+    return( ESC_DOWN );
+
+  if ( c == Kleft )
+    return( ESC_LEFT );
+
+  if ( c == Kright )
+    return( ESC_RIGHT );
+
+  return( c );
+  }
+
+void Timed_Out(sig)
+int sig;
+  {}
+
+/*
+ * $PchHeader: /mount/hd2/minix/sys/cmd/de/RCS/de_stdin.c,v 1.3 1995/02/10 08:01:30 philip Exp $
+ */
Index: /trunk/minix/commands/de/de_stdout.c
===================================================================
--- /trunk/minix/commands/de/de_stdout.c	(revision 9)
+++ /trunk/minix/commands/de/de_stdout.c	(revision 9)
@@ -0,0 +1,1173 @@
+/****************************************************************/
+/*								*/
+/*	de_stdout.c						*/
+/*								*/
+/*		Displaying information from the "Disk editor".	*/
+/*								*/
+/****************************************************************/
+/*  origination         1989-Jan-15        Terrence W. Holm	*/
+/****************************************************************/
+
+
+#include <minix/config.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termcap.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <minix/const.h>
+#include <minix/type.h>
+#include "../../servers/fs/const.h"
+#include "../../servers/fs/type.h"
+#include "../../servers/fs/inode.h"
+#include <minix/fslib.h>
+
+#include "de.h"
+
+#ifndef major
+#define major(x) ( (x>>8) & 0377)
+#define minor(x) (x & 0377)
+#endif
+
+/****************************************************************/
+/*   		Code for handling termcap			*/
+/****************************************************************/
+
+
+#define  TC_BUFFER  1024	/* Size of termcap(3) buffer	*/
+#define  TC_STRINGS  200	/* Enough room for cm,cl,so,se	*/
+
+
+static  char  *Tmove;		/* (cm) - Format for tgoto	*/
+static  char  *Tclr_all;	/* (cl) - Clear screen  	*/
+static  char  *Treverse;	/* (so) - Start reverse mode 	*/
+static  char  *Tnormal;		/* (se) - End reverse mode	*/
+
+char   Kup    = 0;		/* (ku) - Up arrow key		*/
+char   Kdown  = 0;		/* (kd) - Down arrow key	*/
+char   Kleft  = 0;		/* (kl) - Left arrow key	*/
+char   Kright = 0;		/* (kr) - Right arrow key	*/
+
+_PROTOTYPE(void Goto , (int column , int line ));
+_PROTOTYPE(void Block_Type , (de_state *s ));
+_PROTOTYPE(void Draw_Words , (de_state *s ));
+_PROTOTYPE(void Draw_Info , (de_state *s ));
+_PROTOTYPE(void Draw_Block , (char *block ));
+_PROTOTYPE(void Draw_Map , (char *block , int max_bits ));
+_PROTOTYPE(void Draw_Offset , (de_state *s ));
+_PROTOTYPE(void Word_Pointers , (off_t old_addr , off_t new_addr ));
+_PROTOTYPE(void Block_Pointers , (off_t old_addr , off_t new_addr ));
+_PROTOTYPE(void Map_Pointers , (off_t old_addr , off_t new_addr ));
+_PROTOTYPE(void Print_Number , (Word_t number , int output_base ));
+_PROTOTYPE(void Draw_Zone_Numbers , (de_state *s , struct inode *inode ,
+						int zindex , int zrow ));
+
+
+
+/****************************************************************/
+/*								*/
+/*	Init_Termcap()						*/
+/*								*/
+/*		Initializes the external variables for the	*/
+/*		current terminal.				*/
+/*								*/
+/****************************************************************/
+
+
+int Init_Termcap()
+
+  {
+  char  *term;
+  char   buffer[ TC_BUFFER ];
+  static char strings[ TC_STRINGS ];
+  char  *s = &strings[0];
+  char  *Kcode;
+
+
+  term = getenv( "TERM" );
+
+  if ( term == NULL )
+    return( 0 );
+
+  if ( tgetent( buffer, term ) != 1 )
+    return( 0 );
+
+
+  if ( (Tmove = tgetstr( "cm", &s )) == NULL )
+    return( 0 );
+
+  if ( (Tclr_all = tgetstr( "cl", &s )) == NULL )
+    return( 0 );
+
+  if ( (Treverse = tgetstr( "so", &s )) == NULL )
+    {
+    Treverse = Tnormal = s;
+    *s = '\0';
+    ++s;
+    }
+  else if ( (Tnormal = tgetstr( "se", &s )) == NULL )
+    return( 0 );
+
+
+  /*  See if there are single character arrow key codes  */
+
+  if ( (Kcode = tgetstr( "ku", &s )) != NULL  &&  strlen( Kcode ) == 1 )
+    Kup = Kcode[0];
+
+  if ( (Kcode = tgetstr( "kd", &s )) != NULL  &&  strlen( Kcode ) == 1 )
+    Kdown = Kcode[0];
+
+  if ( (Kcode = tgetstr( "kl", &s )) != NULL  &&  strlen( Kcode ) == 1 )
+    Kleft = Kcode[0];
+
+  if ( (Kcode = tgetstr( "kr", &s )) != NULL  &&  strlen( Kcode ) == 1 )
+    Kright = Kcode[0];
+
+
+  return( 1 );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Goto( column, line )					*/
+/*								*/
+/*		Use the termcap string to move the cursor.	*/
+/*								*/
+/****************************************************************/
+
+
+void Goto( column, line )
+  int  column;
+  int  line;
+
+  {
+  fputs( tgoto( Tmove, column, line ), stdout );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*   		       Output routines				*/
+/****************************************************************/
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Draw_Help_Screen()					*/
+/*								*/
+/****************************************************************/
+
+
+void Draw_Help_Screen( s )
+  de_state *s;
+
+  {
+  int down;
+  int right;
+
+  switch ( s->mode )
+    {
+    case WORD  :   down = 2;    right = 32;  break;
+    case BLOCK :   down = 64;   right = 1;   break;
+    case MAP   :   down = 256;  right = 4;   break;
+    }
+
+  printf( "%s                             ", Tclr_all );
+  printf( "%sDE  COMMANDS%s\r\n\n\n", Treverse, Tnormal );
+
+
+  printf( "   PGUP   b   Back one block              h   Help\r\n" );
+  printf( "   PGDN   f   Forward one block           q   Quit\r\n" );
+  printf( "   HOME   B   Goto first block            m   Minix shell\r\n" );
+  printf( "   END    F   Goto last block\r\n" );
+  printf( "                                          v   Visual mode (w b m)\r\n" );
+  printf( "          g   Goto specified block        o   Output base (h d o b)\r\n" );
+  printf( "          G   Goto block indirectly\r\n" );
+  printf( "          i   Goto i-node                 c   Change file name\r\n" );
+  printf( "          I   Filename to i-node          w   Write ASCII block\r\n" );
+  printf( "                                          W   Write block exactly\r\n" );
+  printf( "          /   Search\r\n" );
+  printf( "          n   Next occurrence             x   Extract lost entry\r\n" );
+  printf( "          p   Previous address            X   Extract lost blocks\r\n" );
+  printf( "                                          s   Store word\r\n" );
+  printf( "   UP     u   Move back %d bytes\r\n", down );
+  printf( "   DOWN   d   Move forward %d bytes\r\n", down );
+  printf( "   LEFT   l   Move back %d byte%s\r\n", right,
+					right == 1 ? "" : "s" );
+  printf( "   RIGHT  r   Move forward %d byte%s\r\n\n\n", right,
+					right == 1 ? "" : "s" );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Wait_For_Key()						*/
+/*								*/
+/*		The user must press a key to continue.		*/
+/*								*/
+/****************************************************************/
+
+
+void Wait_For_Key()
+
+  {
+  Draw_Prompt( "Press a key to continue..." );
+
+  Get_Char();
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Draw_Prompt( string )					*/
+/*								*/
+/*		Write a message in the "prompt" area.		*/
+/*								*/
+/****************************************************************/
+
+
+void Draw_Prompt( string )
+  char  *string;
+
+  {
+  Goto( PROMPT_COLUMN, PROMPT_LINE );
+
+  printf( "%s%s%s ", Treverse, string, Tnormal );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Erase_Prompt()						*/
+/*								*/
+/*		Erase the message in the "prompt" area.		*/
+/*								*/
+/****************************************************************/
+
+
+void Erase_Prompt()
+
+  {
+  Goto( PROMPT_COLUMN, PROMPT_LINE );
+
+  printf( "%77c", ' ' );
+
+  Goto( PROMPT_COLUMN, PROMPT_LINE );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Draw_Screen( state )					*/
+/*								*/
+/*		Redraw everything, except pointers.		*/
+/*								*/
+/****************************************************************/
+
+
+void Draw_Screen( s )
+  de_state *s;
+
+  {
+  fputs( Tclr_all, stdout );
+
+  Draw_Strings( s );
+  Block_Type( s );
+
+  switch ( s->mode )
+    {
+    case WORD :   Draw_Words( s );
+		  Draw_Info( s );
+		  break;
+
+    case BLOCK :  Draw_Block( s->buffer );
+		  break;
+
+    case MAP :	  {
+		  int max_bits = 2 * K;
+
+		  /*  Don't display the bits after the end  */
+		  /*  of the i-node or zone bit maps.	    */
+
+		  if ( s->block == 2 + s->inode_maps - 1 )
+		    max_bits = (int)
+			       (s->inodes_in_map
+				- CHAR_BIT * K * (ino_t) (s->inode_maps - 1)
+				- CHAR_BIT * (ino_t) (s->offset & ~ MAP_MASK));
+
+		  else if ( s->block == 2 + s->inode_maps + s->zone_maps - 1 )
+		    max_bits = (int)
+			       (s->zones_in_map
+			        - CHAR_BIT * K * (zone_t) (s->zone_maps - 1)
+				- CHAR_BIT * (zone_t) (s->offset & ~ MAP_MASK));
+
+		  if ( max_bits < 0 )
+		      max_bits = 0;
+
+		  Draw_Map( &s->buffer[ s->offset & ~ MAP_MASK ], max_bits );
+		  break;
+		  }
+    }
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Draw_Strings( state )					*/
+/*								*/
+/*		The first status line contains the device name,	*/
+/*		the current write file name (if one is open)	*/
+/*		and the current search string (if one has	*/
+/*		been defined).					*/
+/*								*/
+/*		Long strings are truncated.			*/
+/*								*/
+/****************************************************************/
+
+
+void Draw_Strings( s )
+  de_state *s;
+
+  {
+  int len;
+  int i;
+
+  Goto( STATUS_COLUMN, STATUS_LINE );
+
+  printf( "Device %s= %-14.14s  ",
+	     s->device_mode == O_RDONLY ? "" : "(w) ", s->device_name );
+
+  switch ( s->magic )
+    {
+    case SUPER_MAGIC :	printf( "V1 file system  ");
+			break;
+    case SUPER_REV :	printf( "V1-bytes-swapped file system (?)  ");
+			break;
+    case SUPER_V2 :	printf( "V2 file system  ");
+			break;
+    case SUPER_V2_REV :	printf( "V2-bytes-swapped file system (?)  ");
+			break;
+    case SUPER_V3 :	printf( "V3 file system  ");
+			break;
+    default :		printf( "not a Minix file system  ");
+			break;
+    }
+
+  len = strlen( s->file_name );
+
+  if ( len == 0 )
+    printf( "%29s", " " );
+  else if ( len <= 20 )
+    printf( "File = %-20s  ", s->file_name );
+  else
+    printf( "File = ...%17.17s  ", s->file_name + len - 17 );
+
+
+  len = strlen( s->search_string );
+
+  if ( len == 0 )
+    printf( "%20s", " " );
+  else
+    {
+    printf( "Search = " );
+
+    if ( len <= 11 )
+      {
+      for ( i = 0;  i < len;  ++i )
+        Print_Ascii( s->search_string[ i ] );
+
+      for ( ;  i < 11;  ++i )
+	putchar( ' ' );
+      }
+    else
+      {
+      for ( i = 0;  i < 8;  ++i )
+        Print_Ascii( s->search_string[ i ] );
+
+      printf( "..." );
+      }
+    }
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Block_Type( state )					*/
+/*								*/
+/*		Display the current block type.			*/
+/*								*/
+/****************************************************************/
+
+
+void Block_Type( s )
+  de_state *s;
+
+  {
+  Goto( STATUS_COLUMN, STATUS_LINE + 1 );
+
+  printf( "Block  = %5u of %-5u  ", s->block, s->zones );
+
+  if ( !s->is_fs )
+    return;
+
+  if ( s->block == BOOT_BLOCK )
+    printf( "Boot block" );
+
+  else if ( s->block == 1 )
+    printf( "Super block" );
+
+  else if ( s->block < 2 + s->inode_maps )
+    printf( "I-node bit map" );
+
+  else if ( s->block < 2 + s->inode_maps + s->zone_maps )
+    printf( "Zone bit map" );
+
+  else if ( s->block < s->first_data )
+    printf( "I-nodes" );
+
+  else
+    printf( "Data block  (%sin use)",
+	In_Use( (bit_t) (s->block - (s->first_data - 1)), s->zone_map )
+	? "" : "not " );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Draw_Words( state )					*/
+/*								*/
+/*		Draw a page in word format.			*/
+/*								*/
+/****************************************************************/
+
+
+void Draw_Words( s )
+  de_state *s;
+
+  {
+  int line;
+  int addr = s->offset & ~ PAGE_MASK;
+
+
+  for ( line = 0;  line < 16;  ++line, addr += 2 )
+    {
+    Goto( BLOCK_COLUMN, BLOCK_LINE + line );
+
+    printf( "%5d  ", addr );
+
+    Print_Number( *( (word_t *) &s->buffer[ addr ] ), s->output_base );
+    }
+
+  Goto( BLOCK_COLUMN + 64, BLOCK_LINE  );
+  printf( "(base %d)", s->output_base );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Draw_Info( state )					*/
+/*								*/
+/*		Add information to a page drawn in word format.	*/
+/*		The routine recognizes the super block, inodes,	*/
+/*		executables and "ar" archives. If the current	*/
+/*		page is not one of these, then ASCII characters	*/
+/*		are printed from the data words.		*/
+/*								*/
+/****************************************************************/
+
+
+char *super_block_info[] =  {	"number of inodes",
+				"V1 number of zones",
+				"inode bit map blocks",
+				"zone bit map blocks",
+				"first data zone",
+				"blocks per zone shift & flags",
+				"maximum file size",
+				"",
+				"magic number",
+				"fsck magic number",
+				"V2 number of zones"  };
+
+
+void Draw_Info( s )
+  de_state *s;
+
+  {
+  int i;
+  int page = s->offset >> PAGE_SHIFT;
+  dev_t dev;
+
+
+  if ( s->is_fs  &&  s->block == 1  &&  page == 0 )
+      for ( i = 0;  i < 11;  ++i )
+ 	{
+	Goto( INFO_COLUMN, INFO_LINE + i );
+	printf( "%s", super_block_info[ i ] );
+	}
+
+  else if ( s->is_fs  &&  s->block >= s->first_data - s->inode_blocks  &&
+	    s->block < s->first_data )
+      {
+      struct inode core_inode;
+      d1_inode *dip1;
+      d2_inode *dip2;
+      struct inode *inode = &core_inode;
+      int special = 0;
+      int m;
+      struct passwd *user;
+      struct group *grp;
+
+      dip1 = (d1_inode *) &s->buffer[ s->offset & ~ PAGE_MASK ];
+      dip2 = (d2_inode *) &s->buffer[ s->offset & ~ PAGE_MASK
+						& ~ (V2_INODE_SIZE-1) ];
+      conv_inode( inode, dip1, dip2, READING, s->magic );
+
+      user = getpwuid( inode->i_uid );
+      grp  = getgrgid( inode->i_gid );
+
+      if ( s->magic != SUPER_MAGIC  &&  page & 1 )
+	{
+	Draw_Zone_Numbers( s, inode, 2, 0 );
+	return;
+	}
+
+      Goto( INFO_COLUMN, INFO_LINE  );
+
+      switch( inode->i_mode & S_IFMT )
+    	{
+    	case S_IFDIR :  printf( "directory  " );
+		    	break;
+
+    	case S_IFCHR :  printf( "character  " );
+		    	special = 1;
+		    	break;
+
+    	case S_IFBLK :  printf( "block  " );
+		   	special = 1;
+		    	break;
+
+    	case S_IFREG :  printf( "regular  " );
+		    	break;
+#ifdef S_IFIFO
+    	case S_IFIFO :  printf( "fifo  " );
+		    	break;
+#endif
+#ifdef S_IFLNK
+    	case S_IFLNK :  printf( "symlink  " );
+		    	break;
+#endif
+#ifdef S_IFSOCK
+    	case S_IFSOCK:  printf( "socket  " );
+		    	break;
+#endif
+    	default      :  printf( "unknown  " );
+    	}
+
+	for ( m = 11;  m >= 0;  --m )
+	  putchar( (inode->i_mode & (1<<m)) ? "xwrxwrxwrtgu"[m] : '-' );
+
+	if ( s->magic == SUPER_MAGIC )
+	  {
+	  /* V1 file system */
+	  Goto( INFO_COLUMN, INFO_LINE + 1 );
+	  printf( "user %s", user ? user->pw_name : "" );
+
+	  Goto( INFO_COLUMN, INFO_LINE + 2 );
+	  printf( "file size %lu", inode->i_size );
+
+	  Goto( INFO_COLUMN, INFO_LINE + 4 );
+	  printf( "m_time %s", ctime( &inode->i_mtime ) );
+
+	  Goto( INFO_COLUMN, INFO_LINE + 6 );
+	  printf( "links %d, group %s",
+		  inode->i_nlinks, grp ? grp->gr_name : "" );
+
+	  Draw_Zone_Numbers( s, inode, 0, 7 );
+	  }
+	else
+	  {
+	  /* V2 file system, even page. */
+	  Goto( INFO_COLUMN, INFO_LINE + 1 );
+	  printf( "links %d ", inode->i_nlinks);
+
+	  Goto( INFO_COLUMN, INFO_LINE + 2 );
+	  printf( "user %s", user ? user->pw_name : "" );
+
+	  Goto( INFO_COLUMN, INFO_LINE + 3 );
+	  printf( "group %s", grp ? grp->gr_name : "" );
+
+	  Goto( INFO_COLUMN, INFO_LINE + 4 );
+	  printf( "file size %lu", inode->i_size );
+
+	  Goto( INFO_COLUMN, INFO_LINE + 6 );
+	  printf( "a_time %s", ctime( &inode->i_atime ) );
+
+	  Goto( INFO_COLUMN, INFO_LINE + 8 );
+	  printf( "m_time %s", ctime( &inode->i_mtime ) );
+
+	  Goto( INFO_COLUMN, INFO_LINE + 10 );
+	  printf( "c_time %s", ctime( &inode->i_ctime ) );
+
+	  Draw_Zone_Numbers( s, inode, 0, 12 );
+	}
+
+      if ( special )
+	{
+	Goto( INFO_COLUMN, INFO_LINE + 7 );
+	dev = (dev_t) inode->i_zone[0];
+	printf( "major %d, minor %d", major(dev), minor(dev) );
+	}
+      }
+
+  else  /*  Print ASCII characters for each byte in page  */
+      {
+      char *p = &s->buffer[ s->offset & ~ PAGE_MASK ];
+
+      for ( i = 0;  i < 16;  ++i )
+        {
+        Goto( INFO_COLUMN, INFO_LINE + i );
+        Print_Ascii( *p++ );
+        Print_Ascii( *p++ );
+        }
+
+      if ( s->block >= s->first_data  &&  page == 0 )
+	{
+	unsigned magic  = ((s->buffer[1] & 0xff) << 8) | (s->buffer[0] & 0xff);
+	unsigned second = ((s->buffer[3] & 0xff) << 8) | (s->buffer[2] & 0xff);
+
+	/*  Is this block the start of an executable file?  */
+
+	if ( magic == (unsigned) A_OUT )
+	  {
+          Goto( INFO_COLUMN, INFO_LINE );
+	  printf( "executable" );
+
+          Goto( INFO_COLUMN, INFO_LINE + 1 );
+
+	  if ( second == (unsigned) SPLIT )
+	    printf( "separate I & D" );
+	  else
+	    printf( "combined I & D" );
+	  }
+	}
+      }
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Draw_Block( block )					*/
+/*								*/
+/*		Redraw a 1k block in character format.		*/
+/*								*/
+/****************************************************************/
+
+
+void Draw_Block( block )
+  char *block;
+
+  {
+  int line;
+  int column;
+  int reverse = 0;
+  int msb_flag = 0;
+
+
+  for ( line = 0;  line < 16;  ++line )
+    {
+    Goto( BLOCK_COLUMN, BLOCK_LINE + line );
+
+    for ( column = 0;  column < 64;  ++column )
+      {
+      char c = *block++;
+
+      if ( c & 0x80 )
+	{
+	msb_flag = 1;
+	c &= 0x7f;
+	}
+
+      if ( c >= ' '  &&  c < DEL )
+	{
+	if ( reverse )
+	  { fputs( Tnormal, stdout ); reverse = 0; }
+
+        putchar( c );
+	}
+      else
+	{
+	if ( ! reverse )
+	  { fputs( Treverse, stdout ); reverse = 1; }
+
+	putchar( c == DEL ? '?' : '@' + c );
+	}
+      }  /*  end for ( column )  */
+    }  /*  end for ( line )  */
+
+  if ( reverse )
+    { fputs( Tnormal, stdout ); reverse = 0; }
+
+  if ( msb_flag )
+    {
+    Goto( BLOCK_COLUMN + 68, BLOCK_LINE + 6 );
+    fputs( "(MSB)", stdout );
+    }
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Draw_Map( block, max_bits )				*/
+/*								*/
+/*		Redraw a block in a bit map format.		*/
+/*		Display min( max_bits, 2048 ) bits.		*/
+/*								*/
+/*		The 256 bytes in "block" are displayed from	*/
+/*		top to bottom and left to right. Bit 0 of	*/
+/*		a byte is towards the top of the screen.	*/
+/*								*/
+/*		Special graphic codes are used to generate	*/
+/*		two "bits" per character position. So a 16	*/
+/*		line by 64 column display is 32 "bits" by	*/
+/*		64 "bits". Or 4 bytes by 64 bytes.		*/
+/*								*/
+/****************************************************************/
+
+
+void Draw_Map( block, max_bits )
+  char *block;
+  int   max_bits;
+
+  {
+  int line;
+  int column;
+  int bit_count = 0;
+
+  for ( line = 0;  line < 16;  ++line )
+    {
+    char *p = &block[ (line & 0xC) >> 2 ];
+    int shift = (line & 0x3) << 1;
+
+    Goto( BLOCK_COLUMN, BLOCK_LINE + line );
+
+    for ( column = 0;  column < 64;  ++column, p += 4 )
+      {
+      char c = (*p >> shift) & 0x3;
+      int current_bit = ((p - block) << 3) + shift;
+
+      /*  Don't display bits past "max_bits"  */
+
+      if ( current_bit >= max_bits )
+	break;
+
+      /*  If "max_bits" occurs in between the two bits  */
+      /*  I am trying to display as one character, then	*/
+      /*  zero off the high-order bit.			*/
+
+      if ( current_bit + 1 == max_bits )
+	c &= 1;
+
+      switch ( c )
+	{
+	case 0 :  putchar( BOX_CLR );
+		  break;
+
+	case 1 :  putchar( BOX_TOP );
+		  ++bit_count;
+		  break;
+
+	case 2 :  putchar( BOX_BOT );
+		  ++bit_count;
+		  break;
+
+	case 3 :  putchar( BOX_ALL );
+		  bit_count += 2;
+		  break;
+	}
+      }  /*  end for ( column )  */
+    }  /*  end for ( line )  */
+
+
+  Goto( BLOCK_COLUMN + 68, BLOCK_LINE + 6 );
+  printf( "(%d)", bit_count );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Draw_Pointers( state )					*/
+/*								*/
+/*		Redraw the pointers and the offset field.	*/
+/*		The rest of the screen stays intact.		*/
+/*								*/
+/****************************************************************/
+
+
+void Draw_Pointers( s )
+  de_state *s;
+
+  {
+  Draw_Offset( s );
+
+  switch ( s->mode )
+    {
+    case WORD :   Word_Pointers( s->last_addr, s->address );
+		  break;
+
+    case BLOCK :  Block_Pointers( s->last_addr, s->address );
+		  break;
+
+    case MAP :	  Map_Pointers( s->last_addr, s->address );
+		  break;
+    }
+
+  Goto( PROMPT_COLUMN, PROMPT_LINE );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Draw_Offset( state )					*/
+/*								*/
+/*		Display the offset in the current buffer	*/
+/*		and the relative position if within a map	*/
+/*		or i-node block.				*/
+/*								*/
+/****************************************************************/
+
+
+void Draw_Offset( s )
+  de_state *s;
+
+  {
+  Goto( STATUS_COLUMN, STATUS_LINE + 2 );
+
+  printf( "Offset = %5d           ", s->offset );
+
+
+  if ( s->block < 2 )
+    return;
+
+  if ( s->block < 2 + s->inode_maps )
+    {
+    long bit = (s->address - 2 * K) * 8;
+
+    if ( bit < s->inodes_in_map )
+	printf( "I-node %ld of %d     ", bit, s->inodes );
+    else
+	printf( "(padding)                " );
+    }
+
+  else if ( s->block < 2 + s->inode_maps + s->zone_maps )
+    {
+    long bit = (s->address - (2 + s->inode_maps) * K) * 8;
+
+    if ( bit < s->zones_in_map )
+	printf( "Block %ld of %u     ", bit + s->first_data - 1, s->zones );
+    else
+	printf( "(padding)                " );
+    }
+
+  else if ( s->block < s->first_data )
+    {
+    bit_t node = (s->address - (2 + s->inode_maps + s->zone_maps) * K) /
+		s->inode_size + 1;
+
+    if ( node <= s->inodes )
+	printf( "I-node %lu of %lu  (%sin use)       ",
+		(unsigned long) node, (unsigned long) s->inodes,
+		In_Use( node, s->inode_map ) ? "" : "not " );
+    else
+	printf( "(padding)                             " );
+    }
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Word_Pointers( old_addr, new_addr )			*/
+/*								*/
+/*	Block_Pointers( old_addr, new_addr )			*/
+/*								*/
+/*	Map_Pointers( old_addr, new_addr )			*/
+/*								*/
+/*		Redraw the index pointers for a each type	*/
+/*		of display. The pointer at "old_addr" is	*/
+/*		erased and a new pointer is positioned		*/
+/*		for "new_addr". This makes the screen		*/
+/*		update faster and more pleasant for the user.	*/
+/*								*/
+/****************************************************************/
+
+
+void Word_Pointers( old_addr, new_addr )
+  off_t old_addr;
+  off_t new_addr;
+
+  {
+  int from = ( (int) old_addr & PAGE_MASK ) >> 1;
+  int to   = ( (int) new_addr & PAGE_MASK ) >> 1;
+
+  Goto( BLOCK_COLUMN - 2, BLOCK_LINE + from );
+  putchar( ' ' );
+
+  Goto( BLOCK_COLUMN - 2, BLOCK_LINE + to );
+  putchar( '>' );
+  }
+
+
+
+
+void Block_Pointers( old_addr, new_addr )
+  off_t old_addr;
+  off_t new_addr;
+
+  {
+  int from = (int) old_addr & ~K_MASK;
+  int to   = (int) new_addr & ~K_MASK;
+
+  Goto( BLOCK_COLUMN - 2, BLOCK_LINE + from / 64 );
+  putchar( ' ' );
+
+  Goto( BLOCK_COLUMN - 2, BLOCK_LINE + to / 64 );
+  putchar( '>' );
+
+  Goto( BLOCK_COLUMN + from % 64, BLOCK_LINE + 17 );
+  putchar( ' ' );
+
+  Goto( BLOCK_COLUMN + to % 64, BLOCK_LINE + 17 );
+  putchar( '^' );
+  }
+
+
+
+
+void Map_Pointers( old_addr, new_addr )
+  off_t old_addr;
+  off_t new_addr;
+
+  {
+  int from = ( (int) old_addr & MAP_MASK ) >> 2;
+  int to   = ( (int) new_addr & MAP_MASK ) >> 2;
+
+  Goto( BLOCK_COLUMN + from, BLOCK_LINE + 17 );
+  putchar( ' ' );
+
+  Goto( BLOCK_COLUMN + to, BLOCK_LINE + 17 );
+  putchar( '^' );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Print_Number( number, output_base )			*/
+/*								*/
+/*		Output "number" in the output base.		*/
+/*								*/
+/****************************************************************/
+
+
+void Print_Number( number, output_base )
+  word_t number;
+  int output_base;
+
+  {
+  switch ( output_base )
+    {
+    case 16 :	printf( "%5x", number );
+		break;
+
+    case 10 :	printf( "%7u", number );
+		break;
+
+    case 8 :	printf( "%7o", number );
+		break;
+
+    case 2 :	{
+      		unsigned int mask;
+      		char pad = ' ';
+
+      		for ( mask = 0x8000;  mask > 1;  mask >>= 1 )
+		  putchar( (mask & number) ? (pad = '0', '1') : pad );
+
+      		putchar( (0x01 & number) ? '1' : '0' );
+
+		break;
+      		}
+
+    default :	Error( "Internal fault (output_base)" );
+    }
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Print_Ascii( char )					*/
+/*								*/
+/*		Display a character in reverse mode if it	*/
+/*		is not a normal printable ASCII character.	*/
+/*								*/
+/****************************************************************/
+
+
+void Print_Ascii( c )
+  char c;
+
+  {
+  c &= 0x7f;
+
+  if ( c < ' ' )
+    printf( "%s%c%s", Treverse, '@' + c, Tnormal );
+  else if ( c == DEL )
+    printf( "%s?%s", Treverse, Tnormal );
+  else
+    putchar( c );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*	Warning( text, arg1, arg2 )				*/
+/*								*/
+/*		Display a message for 2 seconds.		*/
+/*								*/
+/****************************************************************/
+
+
+#if __STDC__
+void Warning( const char *text, ... )
+#else
+void Warning( text )
+  char *text;
+#endif  
+
+  {
+  va_list argp;
+  
+  printf( "%c%s", BELL, Tclr_all );
+
+  Goto( WARNING_COLUMN, WARNING_LINE );
+
+  printf( "%s Warning: ", Treverse );
+  va_start( argp, text );
+  vprintf( text, argp );
+  va_end( argp );
+  printf( " %s", Tnormal );
+
+  fflush(stdout);		/* why does everyone forget this? */
+
+  sleep( 2 );
+  }
+
+
+void Draw_Zone_Numbers( s, inode, zindex, zrow )
+  de_state *s;
+  struct inode *inode;
+  int zindex;
+  int zrow;
+
+  {
+  static char *plurals[] = { "", "double ", "triple " };
+  zone_t zone;
+
+  for ( ; zrow < 16;
+	++zindex, zrow += s->zone_num_size / sizeof (word_t) )
+    {
+    Goto( INFO_COLUMN, INFO_LINE + zrow );
+    if ( zindex < s->ndzones )
+      printf( "zone %d", zindex );
+    else
+      printf( "%sindirect", plurals[ zindex - s->ndzones ] );
+    if ( s->magic != SUPER_MAGIC )
+      {
+      zone = inode->i_zone[ zindex ];
+      if ( zone != (word_t) zone )
+	{
+	Goto( INFO_COLUMN + 16, INFO_LINE + zrow );
+	printf("%ld", (long) zone );
+	}
+      }
+    }
+  }
Index: /trunk/minix/commands/dhcpd/Makefile
===================================================================
--- /trunk/minix/commands/dhcpd/Makefile	(revision 9)
+++ /trunk/minix/commands/dhcpd/Makefile	(revision 9)
@@ -0,0 +1,25 @@
+# Makefile for dhcpd.
+
+CFLAGS	= $(OPT) -D_MINIX
+LDFLAGS	=
+CC = exec cc
+
+all:	dhcpd
+
+OBJ=	dhcpd.o tags.o devices.o ether.o
+
+dhcpd:	$(OBJ)
+	$(CC) $(LDFLAGS) -o $@ $(OBJ)
+	install -S 12kw $@
+
+install:	/usr/bin/dhcpd
+
+/usr/bin/dhcpd:	dhcpd
+	install -c $? $@
+
+clean:
+	rm -f *.o dhcpd core a.out
+
+# Dependencies.
+$(OBJ):			dhcpd.h
+dhcpd.o ether.o:	arp.h
Index: /trunk/minix/commands/dhcpd/arp.h
===================================================================
--- /trunk/minix/commands/dhcpd/arp.h	(revision 9)
+++ /trunk/minix/commands/dhcpd/arp.h	(revision 9)
@@ -0,0 +1,26 @@
+/*	arp.h - Address Resolution Protocol packet format.
+ *							Author: Kees J. Bot
+ *								16 Dec 2000
+ */
+#ifndef ARP_H
+#define ARP_H
+
+typedef struct arp46 {
+	ether_addr_t	dstaddr;
+	ether_addr_t	srcaddr;
+	ether_type_t	ethtype;	/* ARP_PROTO. */
+	u16_t		hdr, pro;	/* ARP_ETHERNET & ETH_IP_PROTO. */
+	u8_t		hln, pln;	/* 6 & 4. */
+	u16_t		op;		/* ARP_REQUEST or ARP_REPLY. */
+	ether_addr_t	sha;		/* Source hardware address. */
+	u8_t		spa[4];		/* Source protocol address. */
+	ether_addr_t	tha;		/* Likewise for the target. */
+	u8_t		tpa[4];
+	char		padding[60 - (4*6 + 2*4 + 4*2 + 2*1)];
+} arp46_t;
+
+#define ARP_ETHERNET	1	/* ARP on Ethernet. */
+#define ARP_REQUEST	1	/* A request for an IP address. */
+#define ARP_REPLY	2	/* A reply to a request. */
+
+#endif /* ARP_H */
Index: /trunk/minix/commands/dhcpd/build
===================================================================
--- /trunk/minix/commands/dhcpd/build	(revision 9)
+++ /trunk/minix/commands/dhcpd/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/dhcpd/devices.c
===================================================================
--- /trunk/minix/commands/dhcpd/devices.c	(revision 9)
+++ /trunk/minix/commands/dhcpd/devices.c	(revision 9)
@@ -0,0 +1,280 @@
+/*	devices.c - Handle network devices.
+ *							Author: Kees J. Bot
+ *								11 Jun 1999
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <sys/asynchio.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_hdr.h>
+#include <net/gen/eth_io.h>
+#include <net/gen/ip_hdr.h>
+#include <net/gen/ip_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/udp_io.h>
+#include <net/gen/dhcp.h>
+#include "dhcpd.h"
+
+void get_buf(buf_t **bp)
+{
+    /* Allocate and return a buffer pointer iff *bp == nil. */
+    if (*bp != nil) {
+	/* Already has one. */
+    } else {
+	/* Get one from the heap. */
+	buf_t *new= allocate(sizeof(*new));
+	new->dhcp= (dhcp_t *) (new->buf + sizeof(eth_hdr_t)
+				+ sizeof(ip_hdr_t) + sizeof(udp_hdr_t));
+	new->udpio= ((udp_io_hdr_t *) new->dhcp) - 1;
+	new->udp= ((udp_hdr_t *) new->dhcp) - 1;
+	new->ip= ((ip_hdr_t *) new->udp) - 1;
+	new->eth= ((eth_hdr_t *) new->ip) - 1;
+	*bp= new;
+    }
+}
+
+void put_buf(buf_t **bp)
+{
+    /* Return a buffer to the heap. */
+    if (*bp != nil) {
+	free(*bp);
+	*bp= nil;
+    }
+}
+
+void give_buf(buf_t **dbp, buf_t **sbp)
+{
+    /* Hand over a buffer to another variable. */
+    put_buf(dbp);
+    *dbp= *sbp;
+    *sbp= nil;
+}
+
+#if __minix_vmd
+#define N_FDS		16	/* Minix-vmd can go async on many fds. */
+#else
+#define N_FDS		 1	/* Minix doesn't have async I/O. */
+#endif
+
+static fd_t fds[N_FDS];			/* List of open descriptors. */
+static struct network *fdwaitq;		/* Queue of nets waiting for fds. */
+
+network_t *newnetwork(void)
+{
+    /* Create and initialize a network structure. */
+    network_t *new;
+
+    new= allocate(sizeof(*new));
+    memset(new, 0, sizeof(*new));
+    new->hostname= nil;
+    new->solicit= NEVER;
+    new->sol_ct= -1;
+    return new;
+}
+
+void closefd(fd_t *fdp)
+{
+    /* Close a descriptor. */
+    if (fdp->fdtype != FT_CLOSED) {
+	asyn_close(&asyn, fdp->fd);
+	close(fdp->fd);
+	fdp->fdtype= FT_CLOSED;
+	fdp->since= 0;
+	put_buf(&fdp->bp);
+	if (debug >= 3) printf("%s: Closed\n", fdp->device);
+    }
+}
+
+int opendev(network_t *np, fdtype_t fdtype, int compete)
+{
+    /* Make sure that a network has the proper device open and configured.
+     * Return true if this is made so, or false if the device doesn't exist.
+     * If compete is true then the caller competes for old descriptors.
+     * The errno value is EAGAIN if we're out of descriptors.
+     */
+    fd_t *fdp, *fdold;
+    time_t oldest;
+    nwio_ethstat_t ethstat;
+    nwio_ethopt_t ethopt;
+    nwio_ipopt_t ipopt;
+    nwio_udpopt_t udpopt;
+    network_t **pqp;
+    static char devbytype[][4] = { "", "eth", "ip", "udp", "udp" };
+
+    /* Don't attempt to open higher level devices if not bound. */
+    if (!(np->flags & NF_BOUND) && fdtype > FT_ETHERNET) {
+	errno= EAGAIN;
+	return 0;
+    }
+
+    /* Check if already open / Find the oldest descriptor. */
+    fdold= nil;
+    oldest= NEVER;
+    for (fdp= fds; fdp < arraylimit(fds); fdp++) {
+	if (fdp->n == np->n && fdp->fdtype == fdtype) {
+	    /* Already open. */
+	    np->fdp= fdp;
+	    return 1;
+	}
+	if (fdp->since <= oldest) { fdold= fdp; oldest= fdp->since; }
+    }
+
+    /* None free?  Then wait for one to get old if so desired. */
+    if (fdold->fdtype != FT_CLOSED && !compete) {
+	errno= EAGAIN;
+	return 0;
+    }
+
+    if (!(np->flags & NF_WAIT)) {
+	for (pqp= &fdwaitq; *pqp != nil; pqp= &(*pqp)->wait) {}
+	*pqp= np;
+	np->wait= nil;
+	np->flags |= NF_WAIT;
+    }
+
+    /* We allow a net to keep a descriptor for half of the fast period. */
+    oldest += DELTA_FAST/2;
+
+    if (fdwaitq != np || (fdold->fdtype != FT_CLOSED && oldest > now)) {
+	/* This net is not the first in the queue, or the oldest isn't
+	 * old enough.  Forget it for now.
+	 */
+	if (oldest < event) event= oldest;
+	errno= EAGAIN;
+	return 0;
+    }
+
+    /* The oldest is mine. */
+    np->flags &= ~NF_WAIT;
+    fdwaitq= np->wait;
+    closefd(fdold);
+
+    /* Open the proper device in the proper mode. */
+    fdp= fdold;
+    fdp->n= np->n;
+    sprintf(fdp->device, "/dev/%s%d", devbytype[fdtype], np->n);
+    np->fdp= fdp;
+
+    if ((fdp->fd= open(fdp->device, O_RDWR)) < 0) {
+	if (errno == ENOENT || errno == ENODEV || errno == ENXIO) return 0;
+	fatal(fdp->device);
+    }
+
+    switch (fdtype) {
+    case FT_ETHERNET:
+	fcntl(np->fdp->fd, F_SETFL, fcntl(np->fdp->fd, F_GETFL) | O_NONBLOCK);
+	if (ioctl(np->fdp->fd, NWIOGETHSTAT, &ethstat) < 0) {
+	    /* Not an Ethernet. */
+	    close(fdp->fd);
+	    return 0;
+	}
+	np->eth= ethstat.nwes_addr;
+	ethopt.nweo_flags= NWEO_COPY | NWEO_EN_LOC | NWEO_EN_BROAD
+			| NWEO_REMANY | NWEO_TYPEANY | NWEO_RWDATALL;
+
+	if (ioctl(fdp->fd, NWIOSETHOPT, &ethopt) < 0) {
+	    fprintf(stderr, "%s: %s: Unable to set eth options: %s\n",
+		program, fdp->device, strerror(errno));
+	    exit(1);
+	}
+	break;
+
+    case FT_ICMP:
+	ipopt.nwio_flags= NWIO_COPY | NWIO_EN_LOC | NWIO_EN_BROAD
+			| NWIO_REMANY | NWIO_PROTOSPEC
+			| NWIO_HDR_O_SPEC | NWIO_RWDATALL;
+	ipopt.nwio_tos= 0;
+	ipopt.nwio_ttl= 1;
+	ipopt.nwio_df= 0;
+	ipopt.nwio_hdropt.iho_opt_siz= 0;
+	ipopt.nwio_proto= IPPROTO_ICMP;
+
+	if (ioctl(fdp->fd, NWIOSIPOPT, &ipopt) < 0) {
+	    fprintf(stderr, "%s: %s: Unable to set IP options: %s\n",
+		program, fdp->device, strerror(errno));
+	    exit(1);
+	}
+	break;
+
+    case FT_BOOTPC:
+	udpopt.nwuo_flags= NWUO_COPY | NWUO_EN_LOC | NWUO_EN_BROAD
+			| NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL
+			| NWUO_DI_IPOPT | NWUO_LP_SET;
+	udpopt.nwuo_locport= port_client;
+	goto udp;
+
+    case FT_BOOTPS:
+	udpopt.nwuo_flags= NWUO_EXCL | NWUO_EN_LOC | NWUO_EN_BROAD
+			| NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL
+			| NWUO_DI_IPOPT | NWUO_LP_SET;
+	udpopt.nwuo_locport= port_server;
+    udp:
+	if (ioctl(fdp->fd, NWIOSUDPOPT, &udpopt) == -1) {
+	    fprintf(stderr, "%s: %s: Unable to set UDP options: %s\n",
+		program, fdp->device, strerror(errno));
+	    exit(1);
+	}
+	break;
+
+    default:;
+    }
+
+    fdp->fdtype= fdtype;
+    fdp->since= now;
+    if (debug >= 3) printf("%s: Opened\n", fdp->device);
+    return 1;
+}
+
+void closedev(network_t *np, fdtype_t fdtype)
+{
+    /* We no longer need a given type of device to be open. */
+    fd_t *fdp;
+
+    for (fdp= fds; fdp < arraylimit(fds); fdp++) {
+	if (fdp->n == np->n && (fdp->fdtype == fdtype || fdtype == FT_ALL)) {
+	    closefd(fdp);
+	}
+    }
+}
+
+char *ipdev(int n)
+{
+    /* IP device for network #n. */
+    static char device[sizeof("/dev/ipNNN")];
+
+    sprintf(device, "/dev/ip%d", n);
+    return device;
+}
+
+void set_ipconf(char *device, ipaddr_t ip, ipaddr_t mask, unsigned mtu)
+{
+    /* Set IP address and netmask of an IP device. */
+    int fd;
+    nwio_ipconf_t ipconf;
+
+    if (test > 0) return;
+
+    if ((fd= open(device, O_RDWR)) < 0) fatal(device);
+    ipconf.nwic_flags= NWIC_IPADDR_SET | NWIC_NETMASK_SET;
+    ipconf.nwic_ipaddr= ip;
+    ipconf.nwic_netmask= mask;
+#ifdef NWIC_MTU_SET
+    if (mtu != 0) {
+	ipconf.nwic_flags |= NWIC_MTU_SET;
+	ipconf.nwic_mtu= mtu;
+    }
+#endif
+    if (ioctl(fd, NWIOSIPCONF, &ipconf) < 0) fatal(device);
+    close(fd);
+}
Index: /trunk/minix/commands/dhcpd/dhcpd.c
===================================================================
--- /trunk/minix/commands/dhcpd/dhcpd.c	(revision 9)
+++ /trunk/minix/commands/dhcpd/dhcpd.c	(revision 9)
@@ -0,0 +1,1406 @@
+/*	dhcpd 1.15 - Dynamic Host Configuration Protocol daemon.
+ *							Author: Kees J. Bot
+ *								11 Jun 1999
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#include <limits.h>
+#include <configfile.h>
+#include <sys/ioctl.h>
+#include <sys/asynchio.h>
+#include <net/hton.h>
+#include <net/gen/socket.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/ether.h>
+#include <net/gen/if_ether.h>
+#include <net/gen/eth_hdr.h>
+#include <net/gen/ip_hdr.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/udp_io.h>
+#include <net/gen/dhcp.h>
+#include "arp.h"
+#define EXTERN
+#include "dhcpd.h"
+
+char *configfile= PATH_DHCPCONF;
+char *poolfile= PATH_DHCPPOOL;
+static char *cachefile= PATH_DHCPCACHE;
+static int qflag;		/* True if printing cached DHCP data. */
+static int aflag, rflag;	/* True if adding or deleting pool addresses. */
+
+#define BCAST_IP	HTONL(0xFFFFFFFFUL)
+
+/* We try to play with up to this many networks. */
+#define N_NETS		32
+static unsigned n_nets;		/* Actual number of networks. */
+
+void report(const char *label)
+{
+    static FILE *logfp;
+    if(!logfp)
+	logfp = fopen("/usr/log/dhcp.log", "w");
+    if(logfp)
+    	fprintf(logfp, "%s: %s: %s\n", program, label, strerror(errno));
+}
+
+void fatal(const char *label)
+{
+    report(label);
+    exit(1);
+}
+
+void *allocate(size_t size)
+{
+    void *mem;
+
+    if ((mem= malloc(size)) == nil) fatal("Can't allocate memory");
+    return mem;
+}
+
+/* Choose a DHCP xid based on the start time and network number.  Not really
+ * random, but we don't have anything more random than the clock anyway.
+ */
+#define XID(np)		htonl(((u32_t) (np)->start << 8) | (np)->n)
+
+static network_t *network[N_NETS];
+
+int ifname2if(const char *name)
+{
+    /* Translate an interface name to a number, -1 if bad. */
+    char *end;
+    unsigned long n;
+
+    if (*name++ != 'i' || *name++ != 'p') return -1;
+    n= strtoul(name, &end, 10);
+    if (end == name || *end != 0) return -1;
+    if (n >= N_NETS) return -1;
+    return n;
+}
+
+network_t *if2net(int n)
+{
+    /* Translate an interface number to a network struct. */
+    int i;
+
+    for (i= 0; i < n_nets; i++) {
+	if (network[i]->n == n) return network[i];
+    }
+    return nil;
+}
+
+static ipaddr_t defaultmask(ipaddr_t ip)
+{
+    /* Compute netmask by the oldfashioned Class rules. */
+    if (B(&ip)[0] < 0x80) return HTONL(0xFF000000UL);	/* Class A. */
+    if (B(&ip)[0] < 0xC0) return HTONL(0xFFFF0000UL);	/* Class B. */
+    if (B(&ip)[0] < 0xE0) return HTONL(0xFFFFFF00UL);	/* Class C. */
+    return HTONL(0xFFFFFFFFUL);  /* Multicast?  Shouldn't happen... */
+}
+
+#define POOL_MAGIC	HTONL(0x81F85D00UL)
+
+typedef struct pool {		/* Dynamic pool entry. */
+	u32_t		magic;		/* Pool file magic number. */
+	ipaddr_t	ip;		/* IP address. */
+	u32_t		expire;		/* When does/did the lease expire? */
+	u8_t		len;		/* Client ID length. */
+	u8_t		unused[19];	/* Space for extensions. */
+	u8_t		clid[CLID_MAX];	/* Client ID of current/last user. */
+} pool_t;
+
+static int openpool(int mode)
+{
+    /* Open the dynamic pool and lock it, return fd on success or -1. */
+    int fd;
+    struct flock lck;
+
+    if ((fd= open(poolfile, mode, 0644)) < 0) {
+	if (errno != ENOENT) fatal(poolfile);
+	return -1;
+    }
+    if (mode != O_RDONLY) {
+	lck.l_type= F_WRLCK;
+	lck.l_whence= SEEK_SET;
+	lck.l_start= 0;
+	lck.l_len= 0;
+	if (fcntl(fd, F_SETLKW, &lck) < 0) fatal(poolfile);
+    }
+    return fd;
+}
+
+static int readpool(int fd, pool_t *entry)
+{
+    /* Read one pool table entry, return true unless EOF. */
+    ssize_t r;
+
+    if ((r= read(fd, entry, sizeof(*entry))) < 0) fatal(poolfile);
+    if (r == 0) return 0;
+
+    if (r != sizeof(*entry) || entry->magic != POOL_MAGIC) {
+	fprintf(stderr, "%s: %s: Pool table is corrupt\n",
+	    program, poolfile);
+	close(fd);
+	return 0;
+    }
+    return 1;
+}
+
+#if !__minix_vmd	/* No fsync() for Minix. */
+#define fsync(fd)	sync()
+#endif
+
+static void writepool(int fd, pool_t *entry)
+{
+    /* (Over)write a pool table entry. */
+    if (write(fd, entry, sizeof(*entry)) < 0
+	|| (entry->expire > now && fsync(fd) < 0)
+    ) {
+	fatal(poolfile);
+    }
+}
+
+static ipaddr_t findpool(u8_t *client, size_t len, ipaddr_t ifip)
+{
+    /* Look for a client ID in the dynamic address pool within the same network
+     * as 'ifip'.  Select an unused one for a new client if necessary.  Return
+     * 0 if nothing is available, otherwise the IP address we can offer.
+     */
+    int fd, found;
+    pool_t entry, oldest;
+    dhcp_t dhcp;
+    u8_t *pmask;
+    ipaddr_t mask;
+
+    /* Any information available on the network the client is at? */
+    if (!makedhcp(&dhcp, nil, 0, nil, 0, ifip, ifip, nil)) return 0;
+
+    if ((fd= openpool(O_RDWR)) < 0) return 0;
+
+    (void) gettag(&dhcp, DHCP_TAG_NETMASK, &pmask, nil);
+    memcpy(&mask, pmask, sizeof(mask));
+
+    oldest.expire= NEVER;
+    while ((found= readpool(fd, &entry))) {
+	/* Deleted entry? */
+	if (entry.ip == 0) continue;
+
+	/* Correct network? */
+	if (((entry.ip ^ ifip) & mask) != 0) continue;
+
+	/* Client present? */
+	if (entry.len == len && memcmp(entry.clid, client, len) == 0) break;
+
+	/* Oldest candidate for a new lease? */
+	entry.expire= ntohl(entry.expire);
+	if (entry.expire < oldest.expire) oldest= entry;
+    }
+    close(fd);
+
+    if (found) return entry.ip;
+    if (oldest.expire <= now) return oldest.ip;
+    return 0;
+}
+
+static int commitpool(ipaddr_t ip, u8_t *client, size_t len, time_t expire)
+{
+    /* Commit a new binding to stable storage, return true on success. */
+    int fd;
+    pool_t entry;
+
+    if ((fd= openpool(O_RDWR)) < 0) return 0;
+
+    do {
+	if (!readpool(fd, &entry)) {
+	    close(fd);
+	    return 0;
+	}
+    } while (entry.ip != ip);
+
+    entry.expire= htonl(expire);
+    entry.len= len;
+    memcpy(entry.clid, client, len);
+    if (lseek(fd, -(off_t)sizeof(entry), SEEK_CUR) == -1) fatal(poolfile);
+    writepool(fd, &entry);
+    close(fd);
+    return 1;
+}
+
+static void updatepool(int add, const char *name)
+{
+    /* Add a new IP address to the dynamic pool. */
+    ipaddr_t ip;
+    int fd, i;
+    pool_t entry;
+    struct hostent *he;
+    off_t off, off0;
+
+    if ((he= gethostbyname(name)) == nil || he->h_addrtype != AF_INET) {
+	fprintf(stderr, "%s: %s: Unknown host\n", program, name);
+	exit(1);
+    }
+    for (i= 0; he->h_addr_list[i] != nil; i++) {}
+    if (i != 1) {
+	fprintf(stderr, "%s: %s has %d addresses\n", program, name, i);
+	exit(1);
+    }
+    memcpy(&ip, he->h_addr_list[0], sizeof(ip));
+
+    if ((fd= openpool(O_RDWR|O_CREAT)) < 0) fatal(poolfile);
+
+    off= 0;
+    off0= -1;
+    while (readpool(fd, &entry)) {
+	if (add) {
+	    if (entry.ip == ip) {
+		fprintf(stderr, "%s: %s: %s is already present\n",
+		    program, poolfile, name);
+		exit(1);
+	    }
+	    if (entry.ip == 0 && off0 == -1) off0= off;
+	} else {
+	    if (entry.ip == ip) {
+		memset(&entry, 0, sizeof(entry));
+		entry.magic= POOL_MAGIC;
+		entry.ip= 0;
+		if (lseek(fd, off, SEEK_SET) == -1) fatal(poolfile);
+		writepool(fd, &entry);
+	    }
+	}
+	off+= sizeof(entry);
+    }
+
+    if (add) {
+	if (off0 != -1 && lseek(fd, off0, SEEK_SET) == -1) fatal(poolfile);
+	memset(&entry, 0, sizeof(entry));
+	entry.magic= POOL_MAGIC;
+	entry.ip= ip;
+	writepool(fd, &entry);
+    }
+    close(fd);
+}
+
+static void cachedhcp(int n, dhcp_t *dp)
+{
+    /* Store a DHCP packet in a cache where those who care can find it. */
+    static int inited;
+    FILE *fp;
+    int fd;
+    int mode;
+
+    if (test > 0) return;
+
+    if (!inited) {
+	/* First time, clear store and also save my pid. */
+	if ((fp= fopen(PATH_DHCPPID, "w")) != nil) {
+	    if (fprintf(fp, "%d\n", getpid()) == EOF || fclose(fp) == EOF) {
+		fatal(PATH_DHCPPID);
+	    }
+	}
+	inited= 1;
+	mode= O_WRONLY | O_CREAT | O_TRUNC;
+    } else {
+	mode= O_WRONLY;
+    }
+
+    dp->xid= htonl(now);	/* To tell how old this data is. */
+
+    if ((fd= open(cachefile, mode, 0666)) < 0
+	|| lseek(fd, (off_t) n * sizeof(*dp), SEEK_SET) == -1
+	|| write(fd, dp, sizeof(*dp)) < 0
+	|| close(fd) < 0
+    ) {
+	if (errno != ENOENT) fatal(cachefile);
+    }
+}
+
+static void printdata(void)
+{
+    /* Show the contents of the cache and the dynamic pool. */
+    int fd;
+    dhcp_t d;
+    ssize_t r;
+    int i;
+    pool_t entry;
+    unsigned long expire;
+    char delta[3*sizeof(u32_t)];
+
+    initdhcpconf();
+
+    if ((fd= open(cachefile, O_RDONLY)) < 0) fatal(cachefile);
+    i= 0;
+    while ((r= read(fd, &d, sizeof(d))) == sizeof(d)) {
+	if (d.yiaddr != 0) {
+	    printf("DHCP data for network %d:\n", i);
+	    printdhcp(&d);
+	}
+	i++;
+    }
+    if (r < 0) fatal(cachefile);
+    close(fd);
+
+    if ((fd= openpool(O_RDONLY)) >= 0) {
+	printf("Dynamic address pool since %ld:\n", (long) now);
+	while (readpool(fd, &entry)) {
+	    if (entry.ip == 0) continue;
+	    expire= ntohl(entry.expire);
+	    if (expire == 0) {
+		strcpy(delta, "unused");
+	    } else
+	    if (expire == 0xFFFFFFFFUL) {
+		strcpy(delta, "infinite");
+	    } else
+	    if (expire < now) {
+		sprintf(delta, "-%lu", now - expire);
+	    } else {
+		sprintf(delta, "+%lu", expire - now);
+	    }
+	    printf("\t%-15s %8s  ", inet_ntoa(entry.ip), delta);
+	    for (i= 0; i < entry.len; i++) {
+		printf("%02X", entry.clid[i]);
+	    }
+	    fputc('\n', stdout);
+	}
+	close(fd);
+    }
+}
+
+static udpport_t portbyname(const char *name)
+{
+    struct servent *se;
+
+    if ((se= getservbyname(name, "udp")) == nil) {
+	fprintf(stderr, "%s: Unknown port \"%s\"\n", program, name);
+	exit(1);
+    }
+    return se->s_port;
+}
+
+static int send(network_t *np, void *data, size_t len)
+{
+    /* Send out a packet using a filedescriptor that is probably in async mode,
+     * so first dup() a sync version, then write.  Return true on success.
+     */
+    int fd;
+    ssize_t r;
+
+    if ((fd= dup(np->fdp->fd)) < 0) fatal("Can't dup()");
+    if ((r= write(fd, data, len)) < 0) {
+	report(np->fdp->device);
+	sleep(10);
+    }
+    close(fd);
+    return r >= 0;
+}
+
+static size_t servdhcp(network_t *np, buf_t *bp, size_t dlen)
+{
+    buf_t *abp= nil;
+    ipaddr_t cip, ifip;
+    u8_t defclid[1+sizeof(bp->dhcp->chaddr)];
+    u8_t *pdata, *client, *class, *server, *reqip, *lease;
+    u32_t expire;
+    size_t len, cilen, calen;
+    int type, dyn;
+    u8_t atype;
+    static char NAKMESS[] = "IP address requested isn't yours";
+
+    if (test > 0) return 0;
+
+    /* The IP address of the interface close to the client. */
+    ifip= bp->dhcp->giaddr != 0 ? bp->dhcp->giaddr : np->ip;
+
+    /* All kinds of DHCP tags. */
+    if (gettag(bp->dhcp, DHCP_TAG_TYPE, &pdata, nil)) {
+	type= *pdata;
+    } else {
+	type= -1;		/* BOOTP? */
+    }
+
+    if (!gettag(bp->dhcp, DHCP_TAG_CLIENTID, &client, &cilen)) {
+	defclid[0]= bp->dhcp->htype;
+	memcpy(defclid+1, bp->dhcp->chaddr, bp->dhcp->hlen);
+	client= defclid;
+	cilen= 1+bp->dhcp->hlen;
+    }
+
+    if (!gettag(bp->dhcp, DHCP_TAG_CLASSID, &class, &calen)) {
+	calen= 0;
+    }
+
+    if (!gettag(bp->dhcp, DHCP_TAG_SERVERID, &server, nil)) {
+	server= B(&np->ip);
+    }
+
+    if (!gettag(bp->dhcp, DHCP_TAG_REQIP, &reqip, nil)) {
+	reqip= nil;
+    }
+
+    /* I'm a server?  Then see if I know this client. */
+    if ((np->flags & NF_SERVING)
+	&& bp->dhcp->op == DHCP_BOOTREQUEST
+	&& between(1, bp->dhcp->hlen, sizeof(bp->dhcp->chaddr))
+	&& (server == nil || memcmp(server, &np->ip, sizeof(np->ip)) == 0)
+    ) {
+	get_buf(&abp);
+
+	/* Is the client in my tables? */
+	(void) makedhcp(abp->dhcp, class, calen, client, cilen, 0, ifip, nil);
+	cip= abp->dhcp->yiaddr;
+
+	dyn= 0;
+	/* If not, do we have a dynamic address? */
+	if (cip == 0 && (cip= findpool(client, cilen, ifip)) != 0) dyn= 1;
+
+	if (type == DHCP_INFORM) {
+	    /* The client already has an address, it just wants information.
+	     * We only answer if we could answer a normal request (cip != 0),
+	     * unless configured to answer anyone.
+	     */
+	    if (cip != 0 || (np->flags & NF_INFORM)) cip= bp->dhcp->ciaddr;
+	}
+
+	if (cip == 0 || !makedhcp(abp->dhcp, class, calen,
+					client, cilen, cip, ifip, nil)) {
+	    put_buf(&abp);
+	}
+
+	if (abp != nil) {
+	    if (gettag(abp->dhcp, DHCP_TAG_LEASE, &lease, nil)) {
+		memcpy(&expire, lease, sizeof(expire));
+		expire= now + ntohl(expire);
+		if (expire < now) expire= 0xFFFFFFFFUL;
+	    } else {
+		if (dyn) {
+		    /* A dynamic address must have a lease. */
+		    fprintf(stderr, "%s: No lease set for address %s\n",
+			program, inet_ntoa(cip));
+		    exit(1);
+		}
+		lease= nil;
+		expire= 0xFFFFFFFFUL;
+	    }
+
+	    /* What does our client want, and what do we say? */
+	    switch (type) {
+	    case DHCP_DISCOVER:
+		atype= DHCP_OFFER;
+
+		/* Assign this address for a short moment. */
+		if (dyn && !commitpool(cip, client, cilen, now + DELTA_FAST)) {
+		    put_buf(&abp);
+		}
+		break;
+
+	    case -1:/* BOOTP */
+	    case DHCP_REQUEST:
+	    case DHCP_INFORM:
+		atype= DHCP_ACK;
+		/* The address wanted must be the address we offer. */
+		if ((reqip != nil && memcmp(reqip, &cip, sizeof(cip)) != 0)
+		    || (bp->dhcp->ciaddr != 0 && bp->dhcp->ciaddr != cip)
+		) {
+		    atype= DHCP_NAK;
+		} else
+		if (dyn && type == DHCP_REQUEST) {
+		    /* Assign this address for the duration of the lease. */
+		    if (!commitpool(cip, client, cilen, expire)) put_buf(&abp);
+		}
+		break;
+
+	    case DHCP_DECLINE:
+		/* Our client doesn't want the offered address! */
+		if (dyn
+		    && reqip != nil
+		    && memcmp(reqip, &cip, sizeof(cip)) == 0
+		) {
+		    int i;
+
+		    fprintf(stderr, "%s: ", program);
+		    for (i= 0; i < cilen; i++) {
+			fprintf(stderr, "%02X", client[i]);
+		    }
+		    fprintf(stderr, " declines %s", inet_ntoa(cip));
+		    if (gettag(bp->dhcp, DHCP_TAG_MESSAGE, &pdata, &len)) {
+			fprintf(stderr, " saying: \"%.*s\"", (int)len, pdata);
+		    }
+		    fputc('\n', stderr);
+
+		    /* Disable address for the duration of the lease. */
+		    (void) commitpool(cip, nil, 0, expire);
+		}
+		put_buf(&abp);
+		break;
+
+	    case DHCP_RELEASE:
+		/* Our client is nice enough to return its address. */
+		if (dyn) (void) commitpool(cip, client, cilen, now);
+		put_buf(&abp);
+		break;
+
+	    default:	/* Anything else is ignored. */
+		put_buf(&abp);
+	    }
+	}
+
+	if (abp != nil) {
+	    /* Finish the return packet. */
+	    abp->dhcp->htype= bp->dhcp->htype;
+	    abp->dhcp->hlen= bp->dhcp->hlen;
+	    abp->dhcp->hops= 0;
+	    abp->dhcp->xid= bp->dhcp->xid;
+	    abp->dhcp->secs= 0;
+	    abp->dhcp->flags= bp->dhcp->flags;
+	    abp->dhcp->ciaddr= 0;
+	    abp->dhcp->yiaddr= atype == DHCP_NAK ? 0 : cip;
+	    if (atype == DHCP_NAK) abp->dhcp->siaddr= 0;
+	    abp->dhcp->giaddr= bp->dhcp->giaddr;
+	    memcpy(abp->dhcp->chaddr,bp->dhcp->chaddr,sizeof(bp->dhcp->chaddr));
+
+	    settag(abp->dhcp, DHCP_TAG_SERVERID, &np->ip, sizeof(np->ip));
+
+	    if (lease == nil) {
+		/* No lease specified?  Then give an infinite lease. */
+		settag(abp->dhcp, DHCP_TAG_LEASE, &expire, sizeof(expire));
+	    }
+
+	    if (type == DHCP_INFORM) {
+		/* Oops, this one has a fixed address, so no lease business. */
+		abp->dhcp->yiaddr= 0;
+		settag(abp->dhcp, DHCP_TAG_LEASE, nil, 0);
+		settag(abp->dhcp, DHCP_TAG_RENEWAL, nil, 0);
+		settag(abp->dhcp, DHCP_TAG_REBINDING, nil, 0);
+	    }
+
+	    if (atype == DHCP_NAK) {
+		/* A NAK doesn't need much. */
+		memset(abp->dhcp->sname, 0, sizeof(abp->dhcp->sname));
+		memset(abp->dhcp->file, 0, sizeof(abp->dhcp->file));
+		memset(abp->dhcp->options, 255, sizeof(abp->dhcp->options));
+		settag(abp->dhcp, DHCP_TAG_MESSAGE, NAKMESS, sizeof(NAKMESS));
+	    }
+
+	    settag(abp->dhcp, DHCP_TAG_TYPE, &atype, sizeof(atype));
+
+	    /* Figure out where to send this to. */
+	    abp->udpio->uih_src_addr= np->ip;
+	    abp->udpio->uih_src_port= port_server;
+	    if (bp->dhcp->giaddr != 0) {
+		abp->udpio->uih_dst_addr= bp->dhcp->giaddr;
+		abp->udpio->uih_dst_port= port_server;
+	    } else
+	    if (bp->dhcp->flags & DHCP_FLAGS_BCAST) {
+		abp->udpio->uih_dst_addr= BCAST_IP;
+		abp->udpio->uih_dst_port= port_client;
+	    } else
+	    if (bp->udpio->uih_src_addr != 0
+		&& bp->udpio->uih_dst_addr == np->ip
+	    ) {
+		abp->udpio->uih_dst_addr= bp->udpio->uih_src_addr;
+		abp->udpio->uih_dst_port= port_client;
+	    } else {
+		abp->udpio->uih_dst_addr= BCAST_IP;
+		abp->udpio->uih_dst_port= port_client;
+	    }
+	    abp->udpio->uih_ip_opt_len= 0;
+	    abp->udpio->uih_data_len= sizeof(dhcp_t);
+
+	    /* Copy the packet to the input buffer, and return the new size. */
+	    memcpy(bp->buf, abp->buf, sizeof(bp->buf));
+	    put_buf(&abp);
+	    return sizeof(udp_io_hdr_t) + sizeof(dhcp_t);
+	}
+    }
+
+    /* I'm a relay?  If it is a not already a relayed request then relay. */
+    if ((np->flags & NF_RELAYING)
+	&& bp->dhcp->op == DHCP_BOOTREQUEST
+	&& bp->dhcp->giaddr == 0
+    ) {
+	bp->dhcp->giaddr= np->ip;
+	bp->udpio->uih_src_addr= np->ip;
+	bp->udpio->uih_src_port= port_server;
+	bp->udpio->uih_dst_addr= np->server;
+	bp->udpio->uih_dst_port= port_server;
+	return dlen;
+    }
+
+    /* I'm a relay?  If the server sends a reply to me then relay back. */
+    if ((np->flags & NF_RELAYING)
+	&& bp->dhcp->op == DHCP_BOOTREPLY
+	&& bp->dhcp->giaddr == np->ip
+    ) {
+	bp->dhcp->giaddr= 0;
+	bp->udpio->uih_src_addr= np->ip;
+	bp->udpio->uih_src_port= port_server;
+	bp->udpio->uih_dst_addr= BCAST_IP;
+	bp->udpio->uih_dst_port= port_client;
+	return dlen;
+    }
+
+    /* Don't know what to do otherwise, so doing nothing seems wise. */
+    return 0;
+}
+
+static void onsig(int sig)
+{
+    switch (sig) {
+    case SIGUSR1:	debug++;	break;
+    case SIGUSR2:	debug= 0;	break;
+    }
+}
+
+static void usage(void)
+{
+    fprintf(stderr,
+"Usage: %s [-qar] [-t[L]] [-d[L]] [-f config] [-c cache] [-p pool] [host ...]\n",
+	program);
+    exit(1);
+}
+
+int main(int argc, char **argv)
+{
+    int i;
+    network_t *np;
+    struct sigaction sa;
+    ssize_t r= -1;
+    buf_t *bp= nil;
+    static struct timeval eventtv;
+
+    program= argv[0];
+    start= now= time(nil);
+
+    debug= 0;
+    i= 1;
+    while (i < argc && argv[i][0] == '-') {
+	char *opt= argv[i++]+1;
+
+	if (opt[0] == '-' && opt[1] == 0) break;	/* -- */
+
+	while (*opt != 0) switch (*opt++) {
+	case 'f':
+	    if (*opt == 0) {
+		if (i == argc) usage();
+		opt= argv[i++];
+	    }
+	    configfile= opt;
+	    opt= "";
+	    break;
+	case 'c':
+	    if (*opt == 0) {
+		if (i == argc) usage();
+		opt= argv[i++];
+	    }
+	    cachefile= opt;
+	    opt= "";
+	    break;
+	case 'p':
+	    if (*opt == 0) {
+		if (i == argc) usage();
+		opt= argv[i++];
+	    }
+	    poolfile= opt;
+	    opt= "";
+	    break;
+	case 't':
+	    test= 1;
+	    if (between('0', *opt, '9')) test= strtoul(opt, &opt, 10);
+	    break;
+	case 'd':
+	    debug= 1;
+	    if (between('0', *opt, '9')) debug= strtoul(opt, &opt, 10);
+	    break;
+	case 'q':
+	    qflag= 1;
+	    break;
+	case 'a':
+	    aflag= 1;
+	    break;
+	case 'r':
+	    rflag= 1;
+	    break;
+	default:
+	    usage();
+	}
+    }
+    if (aflag + rflag + qflag > 1) usage();
+
+    if (aflag || rflag) {
+	/* Add or remove addresses from the dynamic pool. */
+	while (i < argc) updatepool(aflag, argv[i++]);
+	exit(0);
+    }
+
+    if (i != argc) usage();
+
+    if (qflag) {
+	/* Only show the contents of the cache and dynamic pool to the user. */
+	printdata();
+	exit(0);
+    }
+
+    /* BOOTP ports. */
+    port_server= portbyname("bootps");
+    port_client= portbyname("bootpc");
+
+    sa.sa_handler= onsig;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags= 0;
+    sigaction(SIGUSR1, &sa, nil);
+    sigaction(SIGUSR2, &sa, nil);
+
+    /* Initial configuration. */
+    for (i= 0; i < N_NETS; i++) {
+	int fd;
+	ipaddr_t ip, mask;
+
+	/* Is there something there? */
+	if ((fd= open(ipdev(i), O_RDWR|O_NONBLOCK)) < 0) {
+	    if (errno != ENOENT && errno != ENODEV && errno != ENXIO) {
+		fatal(ipdev(i));
+	    }
+	    continue;
+	}
+	close(fd);
+
+	network[n_nets++]= np= newnetwork();
+	np->n= i;
+
+	/* Ethernet? */
+	if (opendev(np, FT_ETHERNET, 1)) {
+	    np->type= B(&np->eth)[0] != 'Z' ? NT_ETHERNET : NT_SINK;
+	    if (debug >= 1) {
+		printf("%s: Ethernet address is %s%s\n",
+		    np->fdp->device, ether_ntoa(&np->eth),
+		    np->type == NT_SINK ? " (sink)" : "");
+	    }
+	    closedev(np, FT_ETHERNET);
+	}
+
+	/* Only true Ethernets worry about DHCP. */
+	if (np->type != NT_ETHERNET) np->renew= np->rebind= np->lease= NEVER;
+    }
+
+    /* Try to find my interfaces in the DHCP table. */
+    for (i= 0; i < n_nets; i++) {
+	ipaddr_t cip;
+	u8_t clid[1+DHCP_HLEN_ETH];
+	size_t cilen;
+
+	np= network[i];
+	if (np->flags & NF_BOUND) continue;
+
+	if (np->type == NT_IP) {
+	    cilen= 0;
+	} else {
+	    ether2clid(clid, &np->eth);
+	    cilen= 1+DHCP_HLEN_ETH;
+	}
+
+	/* Try to find an Ethernet address, or the IP address of an already
+	 * configured network.  If we have data we get an IP address back.
+	 */
+	get_buf(&bp);
+	(void) makedhcp(bp->dhcp, (u8_t *) "Minix", 5,
+					clid, cilen, np->ip, 0, np);
+	cip= bp->dhcp->yiaddr;
+
+	/* Gather information on the interface. */
+	if (cip != 0
+	    && makedhcp(bp->dhcp, (u8_t *) "Minix", 5,
+					clid, cilen, cip, cip, np)
+	    && test < 2
+	) {
+	    u8_t *pdata;
+	    u16_t mtu;
+
+	    cachedhcp(np->n, bp->dhcp);
+	    np->ip= cip;
+	    (void) gettag(bp->dhcp, DHCP_TAG_NETMASK, &pdata, nil);
+	    memcpy(&np->mask, pdata, sizeof(np->mask));
+	    if (gettag(bp->dhcp, DHCP_TAG_GATEWAY, &pdata, nil)) {
+		memcpy(&np->gateway, pdata, sizeof(np->gateway));
+	    } else {
+		np->gateway= 0;
+	    }
+	    if (gettag(bp->dhcp, DHCP_TAG_IPMTU, &pdata, nil)) {
+		memcpy(&mtu, pdata, sizeof(mtu));
+		mtu= ntohs(mtu);
+	    } else {
+		mtu= 0;
+	    }
+	    set_ipconf(ipdev(np->n), np->ip, np->mask, mtu);
+	    if (debug >= 1) {
+		printf("%s: IP address is %s\n",
+		    ipdev(np->n), cidr_ntoa(np->ip, np->mask));
+	    }
+	    np->flags |= NF_BOUND;
+	    np->renew= np->rebind= np->lease= NEVER;
+	    np->sol_ct= N_SOLICITS;
+	    np->solicit= 0;
+
+	    /* Other (previous) interfaces may have been defined. */
+	    i= 0;
+	}
+	put_buf(&bp);
+    }
+
+    for (;;) {
+	now= time(nil);
+	event= NEVER;
+
+	/* Is it time to request/renew a lease? */
+	for (i= 0; i < n_nets; i++) {
+	    np= network[i];
+
+	    if (np->renew <= now) {
+		u8_t type;
+		static u8_t taglist[] = {
+		    DHCP_TAG_NETMASK, DHCP_TAG_GATEWAY, DHCP_TAG_DNS,
+		    	DHCP_TAG_HOSTNAME
+		};
+		u8_t ethclid[1+DHCP_HLEN_ETH];
+
+		/* We may have lost our binding or even our lease. */
+		if (np->rebind <= now) np->server= BCAST_IP;
+
+		if (np->lease <= now) {
+		    if (np->flags & NF_BOUND) closedev(np, FT_ALL);
+
+		    if ((np->flags & (NF_BOUND | NF_POSSESSIVE)) == NF_BOUND) {
+			set_ipconf(ipdev(np->n), np->ip= 0, np->mask= 0, 0);
+			if (debug >= 1) {
+			    printf("%s: Interface disabled (lease expired)\n",
+				ipdev(np->n));
+			}
+		    }
+		    np->flags &= ~NF_BOUND;
+		}
+
+		/* See if we can open the network we need to send on. */
+		if (!(np->flags & NF_BOUND)) {
+		    if (!opendev(np, FT_ETHERNET, 1)) continue;
+		} else {
+		    if (!opendev(np, FT_BOOTPC, 1)) continue;
+		}
+
+		if (!(np->flags & NF_NEGOTIATING)) {
+		    /* We need to start querying a DHCP server. */
+		    np->start= now;
+		    np->delta= DELTA_FIRST;
+		    np->flags |= NF_NEGOTIATING;
+		}
+
+		/* Fill in a DHCP query packet. */
+		get_buf(&bp);
+		dhcp_init(bp->dhcp);
+		bp->dhcp->op= DHCP_BOOTREQUEST;
+		bp->dhcp->htype= DHCP_HTYPE_ETH;
+		bp->dhcp->hlen= DHCP_HLEN_ETH;
+		bp->dhcp->xid= XID(np);
+		bp->dhcp->secs= htons(now - np->start > 0xFFFF
+					? 0xFFFF : now - np->start);
+		memcpy(bp->dhcp->chaddr, &np->eth, sizeof(np->eth));
+
+		if (np->lease <= now) {
+		    /* First time, or my old server is unresponsive. */
+		    type= DHCP_DISCOVER;
+		} else {
+		    /* Request an offered address or renew an address. */
+		    type= DHCP_REQUEST;
+		    if (np->flags & NF_BOUND) {
+			/* A renewal, I claim my current address. */
+			bp->dhcp->ciaddr= np->ip;
+		    } else {
+			/* Nicely ask for the address just offered. */
+			settag(bp->dhcp, DHCP_TAG_REQIP, &np->ip,
+							sizeof(np->ip));
+			settag(bp->dhcp, DHCP_TAG_SERVERID, &np->server,
+							sizeof(np->server));
+		    }
+		}
+		settag(bp->dhcp, DHCP_TAG_TYPE, &type, 1);
+
+		/* My client ID.  Simply use the default. */
+		ether2clid(ethclid, &np->eth);
+		settag(bp->dhcp, DHCP_TAG_CLIENTID, ethclid, sizeof(ethclid));
+
+		/* The Class ID may serve to recognize Minix hosts. */
+		settag(bp->dhcp, DHCP_TAG_CLASSID, "Minix", 5);
+
+		/* The few tags that Minix can make good use of. */
+		settag(bp->dhcp, DHCP_TAG_REQPAR, taglist, sizeof(taglist));
+
+		/* Some weird sites use a hostname, not a client ID. */
+		if (np->hostname != nil) {
+		    settag(bp->dhcp, DHCP_TAG_HOSTNAME,
+					np->hostname, strlen(np->hostname));
+		}
+
+		bp->udpio->uih_src_addr= np->ip;
+		bp->udpio->uih_dst_addr= np->server;
+		bp->udpio->uih_src_port= port_client;
+		bp->udpio->uih_dst_port= port_server;
+		bp->udpio->uih_ip_opt_len= 0;
+		bp->udpio->uih_data_len= sizeof(dhcp_t);
+
+		if (!(np->flags & NF_BOUND)) {
+		    /* Rebind over Ethernet. */
+		    udp2ether(bp, np);
+		    if (send(np, bp->eth, sizeof(eth_hdr_t) + sizeof(ip_hdr_t)
+					+ sizeof(udp_hdr_t) + sizeof(dhcp_t))) {
+			if (debug >= 1) {
+			    printf("%s: Broadcast DHCP %s\n",
+				np->fdp->device, dhcptypename(type));
+			    if (debug >= 2) printdhcp(bp->dhcp);
+			}
+		    }
+		} else {
+		    /* Renew over UDP. */
+		    if (send(np, bp->udpio, sizeof(udp_io_hdr_t)
+							+ sizeof(dhcp_t))) {
+			if (debug >= 1) {
+			    printf("%s: Sent DHCP %s to %s\n",
+				np->fdp->device,
+				dhcptypename(type),
+				inet_ntoa(np->server));
+			    if (debug >= 2) printdhcp(bp->dhcp);
+			}
+		    }
+		}
+		put_buf(&bp);
+
+		/* When to continue querying a DHCP server? */
+		if (np->flags & NF_BOUND) {
+		    /* Still bound, keep halving time till next event. */
+		    time_t e, d;
+
+		    e= now < np->rebind ? np->rebind : np->lease;
+		    d= (e - now) / 2;
+		    if (d < DELTA_SLOW) d= DELTA_SLOW;
+		    np->renew= now + d;
+		    if (np->renew > e) np->renew= e;
+		} else {
+		    /* Not bound, be desparate. */
+		    np->renew= now + np->delta;
+		    if ((np->delta *= 2) > DELTA_FAST) np->delta= DELTA_FAST;
+		}
+	    }
+	    if (np->renew < event) event= np->renew;
+	}
+
+	/* Read DHCP responses. */
+	for (i= 0; i < n_nets; i++) {
+	    np= network[i];
+	    if (!(np->flags & NF_NEGOTIATING)) continue;
+
+	    if (!(np->flags & NF_BOUND)) {
+		if (!opendev(np, FT_ETHERNET, 0)) continue;
+		get_buf(&np->fdp->bp);
+		r= asyn_read(&asyn, np->fdp->fd, np->fdp->bp->eth,
+							BUF_ETH_SIZE);
+	    } else {
+		if (!opendev(np, FT_BOOTPC, 0)) continue;
+		get_buf(&np->fdp->bp);
+		r= asyn_read(&asyn, np->fdp->fd, np->fdp->bp->udpio,
+							BUF_UDP_SIZE);
+	    }
+	    if (r != -1) break;
+	    if (errno != ASYN_INPROGRESS && errno != EPACKSIZE) {
+		report(np->fdp->device);
+		sleep(10);
+	    }
+	}
+
+	/* Is there a response? */
+	if (i < n_nets) {
+	    give_buf(&bp, &np->fdp->bp);
+	    if (((!(np->flags & NF_BOUND)
+		    && r >= (sizeof(eth_hdr_t) + sizeof(ip_hdr_t)
+				+ sizeof(udp_hdr_t) + offsetof(dhcp_t, options))
+		    && ether2udp(bp)
+		    && bp->udpio->uih_dst_port == port_client)
+		  ||
+		  ((np->flags & NF_BOUND)
+		    && r >= sizeof(udp_io_hdr_t) + offsetof(dhcp_t, options)))
+		&& bp->dhcp->op == DHCP_BOOTREPLY
+		&& bp->dhcp->htype == DHCP_HTYPE_ETH
+		&& bp->dhcp->hlen == DHCP_HLEN_ETH
+		&& bp->dhcp->xid == XID(np)
+		&& memcmp(bp->dhcp->chaddr, &np->eth, sizeof(np->eth)) == 0
+	    ) {
+		/* Pfew!  We got a DHCP reply! */
+		u8_t *pdata;
+		size_t len;
+		int type;
+		ipaddr_t mask, gateway, relay, server;
+		u16_t mtu;
+		u32_t lease, renew, rebind, t;
+
+		relay= bp->udpio->uih_src_addr;
+		if (gettag(bp->dhcp, DHCP_TAG_SERVERID, &pdata, nil)) {
+		    memcpy(&server, pdata, sizeof(server));
+		} else {
+		    server= relay;
+		}
+
+		if (gettag(bp->dhcp, DHCP_TAG_TYPE, &pdata, nil)) {
+		    type= pdata[0];
+		} else {
+		    type= DHCP_ACK;	/* BOOTP? */
+		}
+
+		if (debug >= 1) {
+		    printf("%s: Got a DHCP %s from %s",
+			np->fdp->device, dhcptypename(type), inet_ntoa(server));
+		    printf(relay != server ? " through %s\n" : "\n",
+			inet_ntoa(relay));
+		    if (debug >= 2) printdhcp(bp->dhcp);
+		}
+
+		if (gettag(bp->dhcp, DHCP_TAG_NETMASK, &pdata, nil)) {
+		    memcpy(&mask, pdata, sizeof(mask));
+		} else {
+		    mask= defaultmask(bp->dhcp->ciaddr);
+		}
+
+		if (gettag(bp->dhcp, DHCP_TAG_IPMTU, &pdata, nil)) {
+		    memcpy(&mtu, pdata, sizeof(mtu));
+		    mtu= ntohs(mtu);
+		} else {
+		    mtu= 0;
+		}
+
+		if (gettag(bp->dhcp, DHCP_TAG_GATEWAY, &pdata, nil)) {
+		    memcpy(&gateway, pdata, sizeof(gateway));
+		} else {
+		    gateway= 0;
+		}
+
+		lease= NEVER;
+		if (gettag(bp->dhcp, DHCP_TAG_LEASE, &pdata, nil)) {
+		    memcpy(&lease, pdata, sizeof(lease));
+		    lease= ntohl(lease);
+		}
+
+		rebind= lease - lease / 8;
+		if (gettag(bp->dhcp, DHCP_TAG_REBINDING, &pdata, nil)) {
+		    memcpy(&t, pdata, sizeof(t));
+		    t= ntohl(t);
+		    if (t < rebind) rebind= t;
+		}
+
+		renew= lease / 2;
+		if (gettag(bp->dhcp, DHCP_TAG_RENEWAL, &pdata, nil)) {
+		    memcpy(&t, pdata, sizeof(t));
+		    t= ntohl(t);
+		    if (t < renew) renew= t;
+		}
+
+		if (type == DHCP_OFFER && np->rebind <= np->renew) {
+		    /* It's an offer for an address and we haven't taken one
+		     * yet.  It's all the same to us, so take this one.
+		     */
+		    np->ip= bp->dhcp->yiaddr;
+		    np->mask= mask;
+		    np->server= server;
+		    np->gateway= gateway;
+		    np->delta= DELTA_FIRST;
+		    np->renew= now;
+		    np->rebind= np->lease= now + DELTA_FAST;
+
+		    /* Send out an ARP request to see if the offered address
+		     * is in use already.
+		     */
+		    make_arp(bp, np);
+		    if (send(np, bp->eth, sizeof(arp46_t))) {
+			if (debug >= 2) {
+			    printf("Sent ARP for %s\n", inet_ntoa(np->ip));
+			}
+		    }
+		    np->flags &= ~NF_CONFLICT;
+		}
+
+		if (type == DHCP_ACK && !(np->flags & NF_CONFLICT)) {
+		    /* An acknowledgment.  The address is all mine. */
+		    cachedhcp(np->n, bp->dhcp);
+		    np->ip= bp->dhcp->yiaddr;
+		    np->mask= mask;
+		    np->server= server;
+		    set_ipconf(ipdev(np->n), np->ip, np->mask, mtu);
+		    if (debug >= 1) {
+			printf("%s: Address set to %s\n",
+			    ipdev(np->n), cidr_ntoa(np->ip, np->mask));
+		    }
+		    if (lease >= NEVER - now) {
+			/* The lease is infinite! */
+			np->renew= np->rebind= np->lease= NEVER;
+		    } else {
+			np->lease= now + lease;
+			np->renew= now + renew;
+			np->rebind= now + rebind;
+		    }
+		    if (test >= 3) {
+			np->renew= now + 60;
+			np->rebind= test >= 4 ? np->renew : np->renew + 60;
+			np->lease= test >= 5 ? np->rebind : np->rebind + 60;
+		    }
+		    if (!(np->flags & NF_IRDP)) {
+			np->sol_ct= (np->flags & NF_BOUND) ? 1 : N_SOLICITS;
+			np->solicit= 0;
+		    }
+		    np->flags &= ~NF_NEGOTIATING;
+		    np->flags |= NF_BOUND;
+		    closedev(np, FT_ETHERNET);
+		    closedev(np, FT_BOOTPC);
+		}
+
+		if (type == DHCP_ACK && (np->flags & NF_CONFLICT)) {
+		    /* Alas there is a conflict.  Decline to use the address. */
+		    u8_t ethclid[1+DHCP_HLEN_ETH];
+		    static char USED[]= "Address in use by 00:00:00:00:00:00";
+
+		    type= DHCP_DECLINE;
+		    dhcp_init(bp->dhcp);
+		    bp->dhcp->op= DHCP_BOOTREQUEST;
+		    bp->dhcp->htype= DHCP_HTYPE_ETH;
+		    bp->dhcp->hlen= DHCP_HLEN_ETH;
+		    bp->dhcp->xid= XID(np);
+		    bp->dhcp->secs= 0;
+		    memcpy(bp->dhcp->chaddr, &np->eth, sizeof(np->eth));
+		    settag(bp->dhcp, DHCP_TAG_REQIP, &np->ip, sizeof(np->ip));
+		    settag(bp->dhcp, DHCP_TAG_TYPE, &type, 1);
+		    ether2clid(ethclid, &np->eth);
+		    settag(bp->dhcp, DHCP_TAG_CLIENTID,ethclid,sizeof(ethclid));
+		    strcpy(USED+18, ether_ntoa(&np->conflict));
+		    settag(bp->dhcp, DHCP_TAG_MESSAGE, USED, strlen(USED));
+
+		    bp->udpio->uih_src_port= port_client;
+		    bp->udpio->uih_dst_port= port_server;
+		    bp->udpio->uih_ip_opt_len= 0;
+		    bp->udpio->uih_data_len= sizeof(dhcp_t);
+		    udp2ether(bp, np);
+
+		    if (send(np, bp->eth, sizeof(eth_hdr_t) + sizeof(ip_hdr_t)
+					+ sizeof(udp_hdr_t) + sizeof(dhcp_t))) {
+			if (debug >= 1) {
+			    printf("%s: Broadcast DHCP %s\n",
+				np->fdp->device, dhcptypename(type));
+			    if (debug >= 2) printdhcp(bp->dhcp);
+			}
+		    }
+		    
+		    np->renew= np->rebind= np->lease= now + DELTA_FAST;
+		    np->delta= DELTA_FIRST;
+		}
+
+		if (type == DHCP_NAK) {
+		    /* Oops, a DHCP server doesn't like me, start over! */
+		    np->renew= np->rebind= np->lease= now + DELTA_FAST;
+		    np->delta= DELTA_FIRST;
+
+		    fprintf(stderr, "%s: Got a NAK from %s",
+			program, inet_ntoa(server));
+		    if (relay != server) {
+			fprintf(stderr, " through %s", inet_ntoa(relay));
+		    }
+		    if (gettag(bp->dhcp, DHCP_TAG_MESSAGE, &pdata, &len)) {
+			fprintf(stderr, " saying: \"%.*s\"", (int)len, pdata);
+		    }
+		    fputc('\n', stderr);
+		}
+	    } else
+	    if (!(np->flags & NF_BOUND)
+		&& np->rebind > now
+		&& r >= sizeof(arp46_t)
+		&& is_arp_me(bp, np)
+	    ) {
+		/* Oh no, someone else is using the address offered to me! */
+		np->flags |= NF_CONFLICT;
+
+		fprintf(stderr, "%s: %s: %s offered by ",
+			program,
+			np->fdp->device,
+			inet_ntoa(np->ip));
+		fprintf(stderr, "%s is already in use by %s\n",
+			inet_ntoa(np->server),
+			ether_ntoa(&np->conflict));
+	    }
+	    put_buf(&bp);
+	    if (np->renew < event) event= np->renew;
+	}
+
+	/* Perform router solicitations. */
+	for (i= 0; i < n_nets; i++) {
+	    np= network[i];
+	    if (!(np->flags & NF_BOUND)) continue;
+
+	    if (np->solicit <= now) {
+		if (!opendev(np, FT_ICMP, 1)) continue;
+		np->solicit= NEVER;
+
+		get_buf(&bp);
+		if (np->gateway != 0) {
+		    /* No IRDP response seen yet, advertise the router given
+		     * by DHCP to my own interface.
+		     */
+		    icmp_advert(bp, np);
+		    if (send(np, bp->ip, sizeof(ip_hdr_t) + 16)) {
+			if (debug >= 2) {
+			    printf("%s: Sent advert for %s to self\n",
+				np->fdp->device, inet_ntoa(np->gateway));
+			}
+		    }
+		    np->solicit= now + DELTA_ADV/2;
+		}
+
+		if (np->sol_ct >= 0 && --np->sol_ct >= 0) {
+		    /* Send a router solicitation. */
+		    icmp_solicit(bp);
+		    if (send(np, bp->ip, sizeof(*bp->ip) + 8)) {
+			if (debug >= 2) {
+			    printf("%s: Broadcast router solicitation\n",
+				np->fdp->device);
+			}
+		    }
+		    np->solicit= now + DELTA_SOL;
+		} else {
+		    /* No response, or not soliciting right now. */
+		    closedev(np, FT_ICMP);
+		}
+
+		put_buf(&bp);
+	    }
+	    if (np->solicit < event) event= np->solicit;
+	}
+
+	/* Read router adverts. */
+	for (i= 0; i < n_nets; i++) {
+	    np= network[i];
+	    if (!(np->flags & NF_BOUND)) continue;
+	    if (np->sol_ct < 0) continue;
+
+	    if (!opendev(np, FT_ICMP, 0)) continue;
+	    get_buf(&np->fdp->bp);
+	    r= asyn_read(&asyn, np->fdp->fd, np->fdp->bp->ip, BUF_IP_SIZE);
+	    if (r != -1) break;
+	    if (errno != ASYN_INPROGRESS && errno != EPACKSIZE) {
+		report(np->fdp->device);
+		sleep(10);
+	    }
+	}
+
+	/* Is there an advert? */
+	if (i < n_nets && r >= sizeof(ip_hdr_t) + 8) {
+	    ipaddr_t router;
+
+	    give_buf(&bp, &np->fdp->bp);
+	    if ((router= icmp_is_advert(bp)) != 0) {
+		if (debug >= 2) {
+		    printf("%s: Router advert received from %s\n",
+			np->fdp->device, inet_ntoa(router));
+		}
+		np->solicit= NEVER;
+		np->sol_ct= -1;
+		np->flags |= NF_IRDP;
+		closedev(np, FT_ICMP);
+	    }
+	    put_buf(&bp);
+	}
+
+	/* We start serving if all the interfaces so marked are configured. */
+	for (i= 0; i < n_nets; i++) {
+	    np= network[i];
+	    if ((np->flags & NF_RELAYING) && (np->flags & NF_BOUND)) {
+		if (((np->ip ^ np->server) & np->mask) == 0) {
+		    /* Don't relay to a server that is on this same net. */
+		    np->flags &= ~NF_RELAYING;
+		}
+	    }
+	    if (!(np->flags & (NF_SERVING|NF_RELAYING))) continue;
+	    if (!(np->flags & NF_BOUND)) { serving= 0; break; }
+	    serving= 1;
+	}
+
+	/* Read DHCP requests. */
+	for (i= 0; i < n_nets; i++) {
+	    np= network[i];
+	    if (!(np->flags & NF_BOUND)) continue;
+	    if (!(np->flags & (NF_SERVING|NF_RELAYING)) || !serving) continue;
+
+	    if (!opendev(np, FT_BOOTPS, 0)) continue;
+	    get_buf(&np->fdp->bp);
+	    r= asyn_read(&asyn, np->fdp->fd, np->fdp->bp->udpio, BUF_UDP_SIZE);
+
+	    if (r != -1) break;
+	    if (errno != ASYN_INPROGRESS && errno != EPACKSIZE) {
+		report(np->fdp->device);
+		sleep(10);
+	    }
+	}
+
+	/* Is there a request? */
+	if (i < n_nets
+	    && r >= sizeof(udp_io_hdr_t) + offsetof(dhcp_t, options)
+	) {
+	    give_buf(&bp, &np->fdp->bp);
+
+	    if (debug >= 1) {
+		printf("%s: Got DHCP packet from %s to ",
+		    np->fdp->device, inet_ntoa(bp->udpio->uih_src_addr));
+		printf("%s\n", inet_ntoa(bp->udpio->uih_dst_addr));
+		if (debug >= 2) printdhcp(bp->dhcp);
+	    }
+
+	    /* Can we do something with this DHCP packet? */
+	    if ((r= servdhcp(np, bp, r)) > 0) {
+		/* Yes, we have something to send somewhere. */
+		if (send(np, bp->udpio, r)) {
+		    if (debug >= 1) {
+			printf("%s: Sent DHCP packet to %s\n",
+			    np->fdp->device,
+			    inet_ntoa(bp->udpio->uih_dst_addr));
+			if (debug >= 2) printdhcp(bp->dhcp);
+		    }
+		}
+	    }
+	    put_buf(&bp);
+	}
+
+	if (debug >= 1) {
+	    static char *lastbrk;
+	    extern char _end;
+
+	    if (sbrk(0) != lastbrk) {
+		lastbrk= sbrk(0);
+		printf("Memory use = %lu\n",
+		    (unsigned long) (lastbrk - &_end));
+	    }
+	    fflush(stdout);
+	}
+
+	/* Bail out if not a server, and there is nothing else to do ever. */
+	if (!serving && event == NEVER) break;
+
+	/* Wait for something to do. */
+	eventtv.tv_sec= event;
+	if (asyn_wait(&asyn, 0, event == NEVER ? nil : &eventtv) < 0) {
+	    if (errno != EINTR) {
+		report("asyn_wait()");
+		sleep(10);
+	    }
+	}
+    }
+    if (debug >= 1) printf("Nothing more to do! Bailing out...\n");
+    return 0;
+}
Index: /trunk/minix/commands/dhcpd/dhcpd.h
===================================================================
--- /trunk/minix/commands/dhcpd/dhcpd.h	(revision 9)
+++ /trunk/minix/commands/dhcpd/dhcpd.h	(revision 9)
@@ -0,0 +1,159 @@
+/*	dhcpd.h - Dynamic Host Configuration Protocol daemon.
+ *							Author: Kees J. Bot
+ *								16 Dec 2000
+ */
+
+#define nil ((void*)0)
+
+#include <minix/paths.h>
+
+/* Paths to files. */
+#define PATH_DHCPCONF	_PATH_DHCPCONF
+#define PATH_DHCPPID	_PATH_DHCPPID
+#define PATH_DHCPCACHE	_PATH_DHCPCACHE
+#define PATH_DHCPPOOL	_PATH_DHCPPOOL
+
+#define CLID_MAX	32	/* Maximum client ID length. */
+
+#ifndef EXTERN
+#define EXTERN	extern
+#endif
+
+EXTERN char *program;		/* This program's name. */
+extern char *configfile;	/* Configuration file. */
+extern char *poolfile;		/* Dynamic address pool. */
+EXTERN int serving;		/* True if being a DHCP server. */
+EXTERN unsigned test;		/* Test level. */
+EXTERN unsigned debug;		/* Debug level. */
+EXTERN asynchio_t asyn;		/* Bookkeeping for all async I/O. */
+
+/* BOOTP UDP ports:  (That they are different is quite stupid.) */
+EXTERN u16_t port_server;	/* Port server listens on. */
+EXTERN u16_t port_client;	/* Port client listens on. */
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+#define between(a,c,z)	(sizeof(c) <= sizeof(unsigned) ? \
+	(unsigned) (c) - (a) <= (unsigned) (z) - (a) : \
+	(unsigned long) (c) - (a) <= (unsigned long) (z) - (a))
+
+/* To treat objects as octet arrays: */
+#define B(a)		((u8_t *) (a))
+
+/* Times. */
+EXTERN time_t start, now;		/* Start and current time. */
+EXTERN time_t event;			/* Time of the next timed event. */
+
+/* Special times and periods: */
+#define NEVER	(sizeof(time_t) <= sizeof(int) ? INT_MAX : LONG_MAX)
+#define DELTA_FIRST		   4	/* Between first and second query. */
+#define DELTA_FAST		  64	/* Unbound queries this often. */
+#define DELTA_SLOW		 512	/* Bound queries are more relaxed. */
+#define N_SOLICITS		   3	/* Number of solicitations. */
+#define DELTA_SOL		   3	/* Time between solicitations. */
+#define DELTA_ADV		2048	/* Router adverts to self lifetime. */
+
+/* Buffers for packets. */
+typedef struct buf {
+	eth_hdr_t	*eth;		/* Ethernet header in payload. */
+	ip_hdr_t	*ip;		/* IP header in payload. */
+	udp_hdr_t	*udp;		/* UDP header in payload. */
+	udp_io_hdr_t	*udpio;		/* UDP I/O header in payload. */
+	dhcp_t		*dhcp;		/* DHCP data in payload. */
+	u8_t		pad[2];		/* buf[] must start at 2 mod 4. */
+					/* Payload: */
+	u8_t		buf[ETH_MAX_PACK_SIZE];
+} buf_t;
+
+#define BUF_ETH_SIZE	(ETH_MAX_PACK_SIZE)
+#define BUF_IP_SIZE	(BUF_ETH_SIZE - sizeof(eth_hdr_t))
+#define BUF_UDP_SIZE	(BUF_IP_SIZE - sizeof(ip_hdr_t) - sizeof(udp_hdr_t) \
+				+ sizeof(udp_io_hdr_t))
+
+/* Type of network device open: Ethernet, ICMP, BOOTP client, BOOTP server. */
+typedef enum { FT_CLOSED, FT_ETHERNET, FT_ICMP, FT_BOOTPC, FT_BOOTPS } fdtype_t;
+
+#define FT_ALL	FT_CLOSED	/* To close all open descriptors at once. */
+
+typedef struct fd {		/* An open descriptor. */
+	i8_t		fd;		/* Open descriptor. */
+	u8_t		fdtype;		/* Type of network open. */
+	char		device[sizeof("/dev/eth###")];	/* Device name. */
+	u8_t		n;		/* Network that owns it. */
+	buf_t		*bp;		/* Associated packet buffer. */
+	time_t		since;		/* Open since when? */
+} fd_t;
+
+/* Network state: Any IP device, Ethernet in sink mode, True Ethernet. */
+typedef enum { NT_IP, NT_SINK, NT_ETHERNET } nettype_t;
+
+typedef struct network {	/* Information on a network. */
+	u8_t		n;		/* Network number. */
+	ether_addr_t	eth;		/* Ethernet address of this net. */
+	u8_t		type;		/* What kind of net is this? */
+	i8_t		sol_ct;		/* Router solicitation count. */
+	ether_addr_t	conflict;	/* Address conflict with this one. */
+	unsigned	flags;		/* Various flags. */
+	fd_t		*fdp;		/* Current open device. */
+	struct network	*wait;		/* Wait for a resource list. */
+	ipaddr_t	ip;		/* IP address of this net. */
+	ipaddr_t	mask;		/* Associated netmask. */
+	ipaddr_t	gateway;	/* My router. */
+	ipaddr_t	server;		/* My DHCP server. */
+	const char	*hostname;	/* Optional hostname to query for. */
+	time_t		start;		/* Query or lease start time. */
+	time_t		delta;		/* Query again after delta seconds. */
+	time_t		renew;		/* Next query or go into renewal. */
+	time_t		rebind;		/* When to go into rebind. */
+	time_t		lease;		/* When our lease expires. */
+	time_t		solicit;	/* Time to do a router solicitation. */
+} network_t;
+
+/* Flags. */
+#define NF_NEGOTIATING	0x001		/* Negotiating with a DHCP server. */
+#define NF_BOUND	0x002		/* Address configured through DHCP. */
+#define NF_SERVING	0x004		/* I'm a server on this network. */
+#define NF_RELAYING	0x008		/* I'm relaying for this network. */
+#define NF_WAIT		0x010		/* Wait for a resource to free up. */
+#define NF_IRDP		0x020		/* IRDP is used on this net. */
+#define NF_CONFLICT	0x040		/* There is an address conflict. */
+#define NF_POSSESSIVE	0x080		/* Keep address if lease expires. */
+#define NF_INFORM	0x100		/* It's ok to answer DHCPINFORM. */
+
+/* Functions defined in dhcpd.c. */
+void report(const char *label);
+void fatal(const char *label);
+void *allocate(size_t size);
+int ifname2if(const char *name);
+network_t *if2net(int n);
+
+/* Devices.c */
+void get_buf(buf_t **bp);
+void put_buf(buf_t **bp);
+void give_buf(buf_t **dbp, buf_t **sbp);
+network_t *newnetwork(void);
+void closefd(fd_t *fdp);
+int opendev(network_t *np, fdtype_t fdtype, int compete);
+void closedev(network_t *np, fdtype_t fdtype);
+char *ipdev(int n);
+void set_ipconf(char *device, ipaddr_t ip, ipaddr_t mask, unsigned mtu);
+
+/* Ether.c */
+void udp2ether(buf_t *bp, network_t *np);
+int ether2udp(buf_t *bp);
+void make_arp(buf_t *bp, network_t *np);
+int is_arp_me(buf_t *bp, network_t *np);
+void icmp_solicit(buf_t *bp);
+void icmp_advert(buf_t *bp, network_t *np);
+ipaddr_t icmp_is_advert(buf_t *bp);
+
+/* Tags.c */
+#define gettag(dp, st, pd, pl)	dhcp_gettag((dp), (st), (pd), (pl))
+void settag(dhcp_t *dp, int tag, void *data, size_t len);
+char *cidr_ntoa(ipaddr_t addr, ipaddr_t mask);
+void ether2clid(u8_t *clid, ether_addr_t *eth);
+void initdhcpconf(void);
+int makedhcp(dhcp_t *dp, u8_t *class, size_t calen, u8_t *client, size_t cilen,
+				ipaddr_t ip, ipaddr_t ifip, network_t *np);
+char *dhcptypename(int type);
+void printdhcp(dhcp_t *dp);
Index: /trunk/minix/commands/dhcpd/ether.c
===================================================================
--- /trunk/minix/commands/dhcpd/ether.c	(revision 9)
+++ /trunk/minix/commands/dhcpd/ether.c	(revision 9)
@@ -0,0 +1,203 @@
+/*	ether.c - Raw Ethernet stuff
+ *							Author: Kees J. Bot
+ *								16 Dec 2000
+ */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/asynchio.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_hdr.h>
+#include <net/gen/ip_hdr.h>
+#include <net/gen/icmp.h>
+#include <net/gen/icmp_hdr.h>
+#include <net/gen/oneCsum.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/dhcp.h>
+#include "arp.h"
+#include "dhcpd.h"
+
+static ether_addr_t BCAST_ETH =	{{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }};
+#define BCAST_IP	HTONL(0xFFFFFFFFUL)
+#define LOCALHOST	HTONL(0x7F000001UL)
+
+static u16_t udp_cksum(ipaddr_t src, ipaddr_t dst, udp_hdr_t *udp)
+{
+    /* Compute the checksum of an UDP packet plus data. */
+    struct udp_pseudo {
+	ipaddr_t	src, dst;
+	u8_t		zero, proto;
+	u16_t		length;
+    } pseudo;
+    size_t len;
+
+    /* Fill in the UDP pseudo header that must be prefixed to the UDP
+     * packet to compute the checksum of the whole thing.
+     */
+    pseudo.src= src;
+    pseudo.dst= dst;
+    pseudo.zero= 0;
+    pseudo.proto= IPPROTO_UDP;
+    pseudo.length= udp->uh_length;
+
+    len= ntohs(udp->uh_length);
+    if (len & 1) {
+	/* Length is odd?  Pad with a zero. */
+	B(udp)[len++]= 0;
+    }
+    return oneC_sum(oneC_sum(0, &pseudo, sizeof(pseudo)), udp, len);
+}
+
+void udp2ether(buf_t *bp, network_t *np)
+{
+    /* Transform a packet in UDP format to raw Ethernet.  Ignore the UDP
+     * addresses, always broadcast from 0.0.0.0.
+     */
+    udp_io_hdr_t udpio;
+
+    /* Save the UDP I/O header. */
+    udpio= *bp->udpio;
+
+    /* Fill in the Ethernet, IP and UDP headers. */
+    bp->eth->eh_dst= BCAST_ETH;
+    bp->eth->eh_src= np->eth;
+    bp->eth->eh_proto= HTONS(ETH_IP_PROTO);
+    bp->ip->ih_vers_ihl= 0x45;
+    bp->ip->ih_tos= 0;
+    bp->ip->ih_length= htons(sizeof(ip_hdr_t)
+			+ sizeof(udp_hdr_t) + udpio.uih_data_len);
+    bp->ip->ih_id= 0;
+    bp->ip->ih_flags_fragoff= NTOHS(0x4000);
+    bp->ip->ih_ttl= IP_MAX_TTL;
+    bp->ip->ih_proto= IPPROTO_UDP;
+    bp->ip->ih_hdr_chk= 0;
+    bp->ip->ih_src= 0;
+    bp->ip->ih_dst= BCAST_IP;
+    bp->ip->ih_hdr_chk= ~oneC_sum(0, bp->ip, sizeof(*bp->ip));
+    bp->udp->uh_src_port= udpio.uih_src_port;
+    bp->udp->uh_dst_port= udpio.uih_dst_port;
+    bp->udp->uh_length= htons(sizeof(udp_hdr_t) + udpio.uih_data_len);
+    bp->udp->uh_chksum= 0;
+    bp->udp->uh_chksum= ~udp_cksum(bp->ip->ih_src, bp->ip->ih_dst, bp->udp);
+}
+
+int ether2udp(buf_t *bp)
+{
+    /* Transform an UDP packet read from raw Ethernet to normal UDP.
+     * Return true iff the packet is indeed UDP and has no errors.
+     */
+    udp_io_hdr_t udpio;
+
+    if (bp->eth->eh_proto != HTONS(ETH_IP_PROTO)
+	|| bp->ip->ih_vers_ihl != 0x45
+	|| bp->ip->ih_proto != IPPROTO_UDP
+	|| oneC_sum(0, bp->ip, 20) != (u16_t) ~0
+	|| udp_cksum(bp->ip->ih_src, bp->ip->ih_dst, bp->udp) != (u16_t) ~0
+    ) {
+	/* Not UDP/IP or checksums bad. */
+	return 0;
+    }
+    udpio.uih_src_addr= bp->ip->ih_src;
+    udpio.uih_dst_addr= bp->ip->ih_dst;
+    udpio.uih_src_port= bp->udp->uh_src_port;
+    udpio.uih_dst_port= bp->udp->uh_dst_port;
+    udpio.uih_ip_opt_len= 0;
+    udpio.uih_data_len= ntohs(bp->udp->uh_length) - sizeof(udp_hdr_t);
+    *bp->udpio= udpio;
+    return 1;
+}
+
+void make_arp(buf_t *bp, network_t *np)
+{
+    /* Create an ARP packet to query for my IP address. */
+    arp46_t *arp= (arp46_t *) bp->eth;
+
+    memset(arp, 0, sizeof(*arp));
+    arp->dstaddr= BCAST_ETH;
+    arp->srcaddr= np->eth;
+    arp->ethtype= HTONS(ETH_ARP_PROTO);
+    arp->hdr= HTONS(ARP_ETHERNET);
+    arp->pro= HTONS(ETH_IP_PROTO);
+    arp->hln= 6;
+    arp->pln= 4;
+    arp->op= HTONS(ARP_REQUEST);
+    arp->sha= np->eth;
+    memcpy(arp->spa, &np->ip, sizeof(np->ip));
+    memcpy(arp->tpa, &np->ip, sizeof(np->ip));
+}
+
+int is_arp_me(buf_t *bp, network_t *np)
+{
+    /* True iff an ARP packet is a reply from someone else with an address I
+     * thought was mine.  (That's like, bad.)
+     */
+    arp46_t *arp= (arp46_t *) bp->eth;
+
+    if (arp->ethtype == HTONS(ETH_ARP_PROTO)
+	&& arp->hdr == HTONS(ARP_ETHERNET)
+	&& arp->pro == HTONS(ETH_IP_PROTO)
+	&& arp->op == HTONS(ARP_REPLY)
+	&& memcmp(&arp->spa, &np->ip, sizeof(np->ip)) == 0
+	&& memcmp(&arp->sha, &np->eth, sizeof(np->eth)) != 0
+    ) {
+	np->conflict= arp->sha;
+	return 1;
+    }
+    return 0;
+}
+
+void icmp_solicit(buf_t *bp)
+{
+    /* Fill in a router solicitation ICMP packet. */
+    icmp_hdr_t *icmp= (icmp_hdr_t *) (bp->ip + 1);
+
+    bp->ip->ih_vers_ihl= 0x45;
+    bp->ip->ih_dst= BCAST_IP;
+
+    icmp->ih_type= ICMP_TYPE_ROUTE_SOL;
+    icmp->ih_code= 0;
+    icmp->ih_hun.ihh_unused= 0;
+    icmp->ih_chksum= 0;
+    icmp->ih_chksum= ~oneC_sum(0, icmp, 8);
+}
+
+void icmp_advert(buf_t *bp, network_t *np)
+{
+    /* Fill in a router advert to be sent to my own interface. */
+    icmp_hdr_t *icmp= (icmp_hdr_t *) (bp->ip + 1);
+
+    bp->ip->ih_vers_ihl= 0x45;
+    bp->ip->ih_dst= LOCALHOST;
+
+    icmp->ih_type= ICMP_TYPE_ROUTER_ADVER;
+    icmp->ih_code= 0;
+    icmp->ih_hun.ihh_ram.iram_na= 1;
+    icmp->ih_hun.ihh_ram.iram_aes= 2;
+    icmp->ih_hun.ihh_ram.iram_lt= htons(DELTA_ADV);
+    ((u32_t *) icmp->ih_dun.uhd_data)[0] = np->gateway;
+    ((u32_t *) icmp->ih_dun.uhd_data)[1] = HTONL((u32_t) -9999);
+    icmp->ih_chksum= 0;
+    icmp->ih_chksum= ~oneC_sum(0, icmp, 16);
+}
+
+ipaddr_t icmp_is_advert(buf_t *bp)
+{
+    /* Check if an IP packet is a router advertisement, and if it's genuine,
+     * i.e. the sender is mentioned in the packet.
+     */
+    icmp_hdr_t *icmp= (icmp_hdr_t *) (bp->ip + 1);
+    int i;
+
+    if (icmp->ih_type == ICMP_TYPE_ROUTER_ADVER) {
+	for (i= 0; i < icmp->ih_hun.ihh_ram.iram_na; i++) {
+	    if (((u32_t *) icmp->ih_dun.uhd_data)[2*i] == bp->ip->ih_src) {
+		/* It's a router! */
+		return bp->ip->ih_src;
+	    }
+	}
+    }
+    return 0;
+}
Index: /trunk/minix/commands/dhcpd/tags.c
===================================================================
--- /trunk/minix/commands/dhcpd/tags.c	(revision 9)
+++ /trunk/minix/commands/dhcpd/tags.c	(revision 9)
@@ -0,0 +1,924 @@
+/*	tags.c - Obtain DHCP tags from the config file
+ *							Author: Kees J. Bot
+ *								16 Dec 2000
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#include <limits.h>
+#include <configfile.h>
+#include <sys/ioctl.h>
+#include <sys/asynchio.h>
+#include <net/hton.h>
+#include <net/gen/socket.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/ether.h>
+#include <net/gen/if_ether.h>
+#include <net/gen/eth_hdr.h>
+#include <net/gen/ip_hdr.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/dhcp.h>
+#include "dhcpd.h"
+
+#define doff(field)		offsetof(dhcp_t, field)
+
+void settag(dhcp_t *dp, int tag, void *data, size_t len)
+{
+    if (!dhcp_settag(dp, tag, data, len)) {
+	/* Oops, it didn't fit?  Is this really Minix??? */
+	fprintf(stderr,
+	    "%s: DHCP packet too big, please trim the configuration\n",
+	    program);
+	exit(1);
+    }
+}
+
+static int name2ip(ipaddr_t *pip, const char *name, ipaddr_t ifip)
+{
+    /* Translate a name to an IP address, preferably from the hosts file,
+     * but also from the DNS if being a server.  Prefer the address closest
+     * to the interface with IP address 'ifip' if there are choices..
+     */
+    extern struct hostent *_gethostent(void);	/* File reading versions. */
+    extern void _endhostent(void);
+    struct hostent *he;
+    size_t len= strlen(name);
+    u32_t d, distance= -1;
+    ipaddr_t ip;
+    int i;
+    char *hn;
+
+    /* Already an IP address? */
+    if (inet_aton(name, pip)) return 1;
+
+    /* In the hosts file? */
+    while ((he= _gethostent()) != nil) {
+	hn= he->h_name;
+	i= -1;
+	do {
+	    if (strncasecmp(name, hn, len) == 0
+		&& (hn[len] == 0 || hn[len] == '.')
+	    ) {
+		memcpy(&ip, he->h_addr, sizeof(ip));
+		d= ntohl(ip) ^ ntohl(ifip);
+		if (d < distance) {
+		    *pip= ip;
+		    distance= d;
+		}
+		break;
+	    }
+	} while ((hn= he->h_aliases[++i]) != nil);
+    }
+    _endhostent();
+    if (distance < -1) return 1;
+
+    /* Nothing?  Try the real DNS if being a server. */
+    if (serving) {
+	if ((he= gethostbyname(name)) != nil && he->h_addrtype == AF_INET) {
+	    /* Select the address closest to 'ifip'. */
+	    for (i= 0; he->h_addr_list[i] != nil; i++) {
+		memcpy(&ip, he->h_addr_list[i], sizeof(ip));
+		d= ntohl(ip) ^ ntohl(ifip);
+		if (d < distance) {
+		    *pip= ip;
+		    distance= d;
+		}
+	    }
+	    return 1;
+	}
+    }
+    return 0;
+}
+
+static char *ip2name(ipaddr_t ip)
+{
+    /* Translate an IP address to a name, etc, etc. */
+    extern struct hostent *_gethostent(void);	/* File reading versions. */
+    extern void _endhostent(void);
+    struct hostent *he;
+
+    /* In the hosts file? */
+    while ((he= _gethostent()) != nil) {
+	if (memcmp(he->h_addr, &ip, sizeof(ip)) == 0) break;
+    }
+    _endhostent();
+
+    /* Nothing?  Try the real DNS if being a server. */
+    if (he == nil && serving) {
+	he= gethostbyaddr((char *) &ip, sizeof(ip), AF_INET);
+    }
+    return he != nil ? he->h_name : nil;
+}
+
+static int cidr_aton(const char *cidr, ipaddr_t *addr, ipaddr_t *mask)
+{
+    char *slash, *check;
+    ipaddr_t a;
+    int ok;
+    unsigned long len;
+
+    if ((slash= strchr(cidr, '/')) == nil) return 0;
+
+    *slash++= 0;
+    ok= inet_aton(cidr, &a);
+
+    len= strtoul(slash, &check, 10);
+    if (check == slash || *check != 0 || len > 32) ok= 0;
+
+    *--slash= '/';
+    if (!ok) return 0;
+    *addr= a;
+    *mask= htonl(len == 0 ? 0 : (0xFFFFFFFFUL << (32-len)) & 0xFFFFFFFFUL);
+    return 1;
+}
+
+char *cidr_ntoa(ipaddr_t addr, ipaddr_t mask)
+{
+    ipaddr_t testmask= 0xFFFFFFFFUL;
+    int n;
+    static char result[sizeof("255.255.255.255/255.255.255.255")];
+
+    for (n= 32; n >= 0; n--) {
+	if (mask == htonl(testmask)) break;
+	testmask= (testmask << 1) & 0xFFFFFFFFUL;
+    }
+
+    sprintf(result, "%s/%-2d", inet_ntoa(addr), n);
+    if (n == -1) strcpy(strchr(result, '/')+1, inet_ntoa(mask));
+    return result;
+}
+
+static size_t ascii2octet(u8_t *b, size_t size, const char *a)
+{
+    /* Convert a series of hex digit pairs to an octet (binary) array at
+     * 'b' with length 'size'.  Return the number of octets in 'a' or
+     * -1 on error.
+     */
+    size_t len;
+    int n, c;
+
+    len= 0;
+    n= 0;
+    while ((c= *a++) != 0) {
+	if (between('0', c, '9')) c= (c - '0') + 0x0;
+	else
+	if (between('a', c, 'f')) c= (c - 'a') + 0xa;
+	else
+	if (between('A', c, 'F')) c= (c - 'A') + 0xA;
+	else {
+	    return -1;
+	}
+
+	if (n == 0) {
+	    if (len < size) b[len] = c << 4;
+	} else {
+	    if (len < size) b[len] |= c;
+	    len++;
+	}
+	n ^= 1;
+    }
+    return n == 0 ? len : -1;
+}
+
+void ether2clid(u8_t *clid, ether_addr_t *eth)
+{
+    /* Convert an Ethernet address to the default client ID form. */
+    clid[0]= DHCP_HTYPE_ETH;
+    memcpy(clid+1, eth, DHCP_HLEN_ETH);
+}
+
+static size_t ascii2clid(u8_t *clid, const char *a)
+{
+    /* Convert an ethernet address, or a series of hex digits to a client ID.
+     * Return its length if ok, otherwise -1.
+     */
+    size_t len;
+    ether_addr_t *eth;
+
+    if ((eth= ether_aton(a)) != nil) {
+	ether2clid(clid, eth);
+	len= 1+DHCP_HLEN_ETH;
+    } else {
+	len= ascii2octet(clid, CLID_MAX, a);
+    }
+    return len;
+}
+
+static config_t *dhcpconf;		/* In-core DHCP configuration. */
+
+/* DHCP tag types. */
+typedef enum { TT_ASCII, TT_BOOLEAN, TT_IP, TT_NUMBER, TT_OCTET } tagtype_t;
+
+/* DHCP/BOOTP tag definitions. */
+typedef struct tagdef {
+	u8_t		tag;		/* Tag number. */
+	u8_t		type;		/* Type and flags. */
+	u8_t		gran;		/* Granularity. */
+	u8_t		max;		/* Maximum number of arguments. */
+	const char	*name;		/* Defined name. */
+} tagdef_t;
+
+#define TF_TYPE		0x07		/* To mask out the type. */
+#define TF_STATIC	0x08		/* "Static", i.e. a struct field. */
+#define TF_RO		0x10		/* Read-only, user can't set. */
+
+/* List of static DHCP fields.  The tag field is misused here as an offset
+ * into the DHCP structure.
+ */
+static tagdef_t statictag[] = {
+    { doff(op),     TT_NUMBER|TF_STATIC|TF_RO,	1,   1,	"op"		},
+    { doff(htype),  TT_NUMBER|TF_STATIC|TF_RO,	1,   1,	"htype"		},
+    { doff(hlen),   TT_NUMBER|TF_STATIC|TF_RO,	1,   1,	"hlen"		},
+    { doff(hops),   TT_NUMBER|TF_STATIC|TF_RO,	1,   1,	"hops"		},
+    { doff(xid),    TT_NUMBER|TF_STATIC|TF_RO,	4,   1,	"xid"		},
+    { doff(secs),   TT_NUMBER|TF_STATIC|TF_RO,	2,   1,	"secs"		},
+    { doff(flags),  TT_NUMBER|TF_STATIC|TF_RO,	2,   1,	"flags"		},
+    { doff(ciaddr), TT_IP|TF_STATIC|TF_RO,	1,   1,	"ciaddr"	},
+    { doff(yiaddr), TT_IP|TF_STATIC|TF_RO,	1,   1,	"yiaddr"	},
+    { doff(siaddr), TT_IP|TF_STATIC,		1,   1,	"siaddr"	},
+    { doff(giaddr), TT_IP|TF_STATIC|TF_RO,	1,   1,	"giaddr"	},
+    { doff(chaddr), TT_OCTET|TF_STATIC|TF_RO,	1,  16,	"chaddr"	},
+    { doff(sname),  TT_ASCII|TF_STATIC,		1,  64,	"sname"		},
+    { doff(file),   TT_ASCII|TF_STATIC,		1, 128,	"file"		},
+};
+#define N_STATIC	arraysize(statictag)
+
+static tagdef_t alltagdef[N_STATIC + 254];	/* List of tag definitions. */
+#define tagdef	(alltagdef+N_STATIC-1)		/* Just the optional ones. */
+
+#define tagdefined(tp)		((tp)->name != nil)
+
+static void inittagdef(void)
+{
+    /* Initialize the tag definitions from the "tag" commands in the config
+     * file.
+     */
+    int t;
+    tagdef_t *tp;
+    static tagdef_t predef[] = {
+	{ DHCP_TAG_NETMASK,	TT_IP,	   1,	  1,	"netmask"	},
+	{ DHCP_TAG_GATEWAY,	TT_IP,	   1,	255,	"gateway"	},
+	{ DHCP_TAG_DNS,		TT_IP,	   1,	255,	"DNSserver"	},
+    };
+    static char *typenames[] = { "ascii", "boolean", "ip", "number", "octet" };
+    config_t *cfg;
+    static u8_t rotags[] = {
+	DHCP_TAG_REQIP, DHCP_TAG_OVERLOAD, DHCP_TAG_TYPE, DHCP_TAG_SERVERID,
+	DHCP_TAG_REQPAR, DHCP_TAG_MESSAGE, DHCP_TAG_MAXDHCP
+    };
+
+    for (t= 1; t <= 254; t++) {
+	tp= &tagdef[t];
+	tp->tag= t;
+	tp->type= TT_OCTET;
+	tp->name= nil;
+    }
+
+    /* Set the static and "all Minix needs" tags. */
+    memcpy(alltagdef, statictag, sizeof(statictag));
+    for (tp= predef; tp < arraylimit(predef); tp++) tagdef[tp->tag] = *tp;
+
+    /* Search for tag definitions in the config file. */
+    for (cfg= dhcpconf; cfg != nil; cfg= cfg->next) {
+	config_t *cmd= cfg->list;
+
+	if (strcasecmp(cmd->word, "tag") == 0) {
+	    if (config_length(cmd) == 6
+		&& (cmd->next->flags & CFG_DULONG)
+		&& config_isatom(cmd->next->next)
+		&& config_isatom(cmd->next->next->next)
+		&& (cmd->next->next->next->next->flags & CFG_DULONG)
+		&& (cmd->next->next->next->next->next->flags & CFG_DULONG)
+	    ) {
+		unsigned long tag, gran, max;
+		const char *name, *typename;
+		unsigned type;
+
+		tag= strtoul(cmd->next->word, nil, 10);
+		name= cmd->next->next->word;
+		typename= cmd->next->next->next->word;
+		gran= strtoul(cmd->next->next->next->next->word, nil, 10);
+		max= strtoul(cmd->next->next->next->next->next->word, nil, 10);
+
+		for (type= 0; type < arraysize(typenames); type++) {
+		    if (strcasecmp(typename, typenames[type]) == 0) break;
+		}
+
+		if (!(1 <= tag && tag <= 254)
+		    || !(type < arraysize(typenames))
+		    || !((type == TT_NUMBER
+			    && (gran == 1 || gran == 2 || gran == 4))
+			|| (type != TT_NUMBER && 1 <= gran && gran <= 16))
+		    || !(max <= 255)
+		) {
+		    fprintf(stderr,
+			"\"%s\", line %u: Tag definition is incorrect\n",
+			cmd->file, cmd->line);
+		    exit(1);
+		}
+
+		tp= &tagdef[(int)tag];
+		tp->type= type;
+		tp->name= name;
+		tp->gran= gran;
+		tp->max= max;
+	    } else {
+		fprintf(stderr,
+	    "\"%s\", line %u: Usage: tag number name type granularity max\n",
+		    cmd->file, cmd->line);
+		exit(1);
+	    }
+	}
+    }
+
+    /* Many DHCP tags are not for the user to play with. */
+    for (t= 0; t < arraysize(rotags); t++) tagdef[rotags[t]].type |= TF_RO;
+}
+
+static tagdef_t *tagdefbyname(const char *name)
+{
+    /* Find a tag definition by the name of the tag.  Return null if not
+     * defined.
+     */
+    tagdef_t *tp;
+
+    for (tp= alltagdef; tp < arraylimit(alltagdef); tp++) {
+	if (tagdefined(tp) && strcasecmp(tp->name, name) == 0) return tp;
+    }
+    return nil;
+}
+
+void initdhcpconf(void)
+{
+    /* Read/refresh configuration from the DHCP configuration file. */
+    dhcpconf= config_read(configfile, 0, dhcpconf);
+    if (config_renewed(dhcpconf)) inittagdef();
+}
+
+static void configtag(dhcp_t *dp, config_t *cmd, ipaddr_t ifip)
+{
+    /* Add a tag to a DHCP packet from the config file. */
+    tagdef_t *tp;
+    u8_t data[260], *d;
+    size_t i;
+    int delete= 0;
+
+    if (strcasecmp(cmd->word, "no") == 0) {
+	if (config_length(cmd) != 2 || !config_isatom(cmd->next)) {
+	    fprintf(stderr, "\"%s\", line %u: Usage: no tag-name\n",
+		cmd->file, cmd->line);
+	    exit(1);
+	}
+	cmd= cmd->next;
+	delete= 1;
+    }
+
+    if ((tp= tagdefbyname(cmd->word)) == nil) {
+	fprintf(stderr, "\"%s\", line %u: Unknown tag '%s'\n",
+	    cmd->file, cmd->line, cmd->word);
+	exit(1);
+    }
+
+    if (tp->type & TF_RO) {
+	fprintf(stderr, "\"%s\", line %u: Tag '%s' can't be configured\n",
+	    cmd->file, cmd->line, cmd->word);
+	exit(1);
+    }
+
+    i= 0;
+    d= data;
+    if (!delete) {
+	config_t *arg= cmd->next;
+	do {
+	    switch (tp->type & TF_TYPE) {
+	    case TT_ASCII: {
+		if (arg == nil || !config_isatom(arg) || arg->next != nil) {
+		    fprintf(stderr, "\"%s\", line %u: Usage: %s string\n",
+			cmd->file, cmd->line, cmd->word);
+		    exit(1);
+		}
+		strncpy((char *) data, arg->word, sizeof(data));
+		d += i = strnlen((char *) data, sizeof(data));
+		break;}
+	    case TT_BOOLEAN: {
+		if (arg == nil || !config_isatom(arg)
+		    || !(strcasecmp(arg->word, "false") == 0
+			    || strcasecmp(arg->word, "true") == 0)
+		) {
+		    fprintf(stderr,
+			"\"%s\", line %u: Usage: %s false|true ...\n",
+			cmd->file, cmd->line, cmd->word);
+		    exit(1);
+		}
+		if (d < arraylimit(data)) {
+		    *d++ = (arg->word[0] != 'f' && arg->word[0] != 'F');
+		}
+		i++;
+		break;}
+	    case TT_IP: {
+		ipaddr_t ip;
+		unsigned long len;
+		char *end;
+
+		if (arg == nil || !config_isatom(arg)) {
+		    fprintf(stderr, "\"%s\", line %u: Usage: %s host ...\n",
+			cmd->file, cmd->line, cmd->word);
+		    exit(1);
+		}
+		if (arg->word[0] == '/'
+			&& between(1, len= strtoul(arg->word+1, &end, 10), 31)
+			&& *end == 0
+		) {
+		    ip= htonl((0xFFFFFFFFUL << (32-len)) & 0xFFFFFFFFUL);
+		} else
+		if (!name2ip(&ip, arg->word, ifip)) {
+		    fprintf(stderr,
+		    "\"%s\", line %u: Can't translate %s to an IP address\n",
+			arg->file, arg->line, arg->word);
+		    exit(1);
+		}
+		if (d <= arraylimit(data) - sizeof(ip)) {
+		    memcpy(d, &ip, sizeof(ip));
+		    d += sizeof(ip);
+		}
+		i++;
+		break;}
+	    case TT_NUMBER: {
+		unsigned long n;
+		int g;
+
+		if (arg == nil || !(arg->flags & CFG_CLONG)) {
+		    fprintf(stderr, "\"%s\", line %u: Usage: %s number ...\n",
+			cmd->file, cmd->line, cmd->word);
+		    exit(1);
+		}
+		n= strtoul(arg->word, nil, 0);
+		g= tp->gran;
+		do {
+		    if (d <= arraylimit(data)) *d++ = (n >> (--g * 8)) & 0xFF;
+		} while (g != 0);
+		i++;
+		break;}
+	    case TT_OCTET: {
+		if (arg == nil || !config_isatom(arg) || arg->next != nil) {
+		    fprintf(stderr, "\"%s\", line %u: Usage: %s hexdigits\n",
+			cmd->file, cmd->line, cmd->word);
+		    exit(1);
+		}
+		i= ascii2octet(data, sizeof(data), arg->word);
+		if (i == -1) {
+		    fprintf(stderr,
+			"\"%s\", line %u: %s: Bad hexdigit string\n",
+			arg->file, arg->line, arg->word);
+		    exit(1);
+		}
+		d= data + i;
+		break;}
+	    }
+	} while ((arg= arg->next) != nil);
+
+	if (d > data + 255) {
+	    fprintf(stderr, "\"%s\", line %u: Tag value is way too big\n",
+		cmd->file, cmd->line);
+	    exit(1);
+	}
+	if ((tp->type & TF_TYPE) != TT_NUMBER && (i % tp->gran) != 0) {
+	    fprintf(stderr,
+		"\"%s\", line %u: Expected a multiple of %d initializers\n",
+		cmd->file, cmd->line, tp->gran);
+	    exit(1);
+	}
+	if (tp->max != 0 && i > tp->max) {
+	    fprintf(stderr,
+		"\"%s\", line %u: Got %d initializers, can have only %d\n",
+		cmd->file, cmd->line, (int) i, tp->max);
+	    exit(1);
+	}
+    }
+    if (tp->type & TF_STATIC) {
+	size_t len= tp->gran * tp->max;
+	if ((tp->type & TF_TYPE) == TT_IP) len *= sizeof(ipaddr_t);
+	memset(B(dp) + tp->tag, 0, len);
+	memcpy(B(dp) + tp->tag, data, (d - data));
+    } else {
+	settag(dp, tp->tag, data, (d - data));
+    }
+}
+
+int makedhcp(dhcp_t *dp, u8_t *class, size_t calen, u8_t *client, size_t cilen,
+				ipaddr_t ip, ipaddr_t ifip, network_t *np)
+{
+    /* Fill in a DHCP packet at 'dp' for the host identified by the
+     * (class, client, ip) combination.  Makedhcp is normally called twice,
+     * once to find the IP address (so ip == 0) and once again to find all
+     * data that goes with that IP address (ip != 0).  On the first call the
+     * return value of this function should be ignored and only 'yiaddr'
+     * checked and used as 'ip' on the next pass.  True is returned iff there
+     * is information for the client on the network at interface address
+     * 'ifip', by checking if the 'ip' and 'ifip' are on the same network.
+     * If np is nonnull then we are working for one of our own interfaces, so
+     * options can be set and adjourning interfaces can be programmed.
+     */
+    config_t *todo[16];
+    size_t ntodo= 0;
+    ipaddr_t hip, mask;
+    u8_t *pmask;
+    char *hostname;
+    u32_t distance= -1;
+
+    initdhcpconf();
+
+    /* Start creating a packet. */
+    dhcp_init(dp);
+    dp->op= DHCP_BOOTREPLY;
+
+    /* The initial TODO list is the whole DHCP config. */
+    todo[ntodo++]= dhcpconf;
+
+    while (ntodo > 0) {
+	config_t *cmd, *follow;
+
+	if (todo[ntodo-1] == nil) { ntodo--; continue; }
+	cmd= todo[ntodo-1]->list;
+	todo[ntodo-1]= todo[ntodo-1]->next;
+
+	follow= nil;	/* Macro or list to follow next? */
+
+	if (strcasecmp(cmd->word, "client") == 0) {
+	    u8_t cfgid[CLID_MAX];
+	    size_t cfglen;
+	    char *name;
+	    int ifno;
+	    u32_t d;
+
+	    if (between(3, config_length(cmd), 5)
+		&& config_isatom(cmd->next)
+		&& (cfglen= ascii2clid(cfgid, cmd->next->word)) != -1
+		&& config_isatom(cmd->next->next)
+		&& (((ifno= ifname2if(cmd->next->next->word)) == -1
+			&& config_length(cmd) <= 4)
+		    || ((ifno= ifname2if(cmd->next->next->word)) != -1
+			&& config_length(cmd) >= 4
+			&& config_isatom(cmd->next->next->next)))
+	    ) {
+		if (cilen == cfglen && memcmp(client, cfgid, cilen) == 0
+		    && (ifno == -1 || np == nil || ifno == np->n)
+		) {
+		    config_t *atname= cmd->next->next;
+		    if (ifno != -1) atname= atname->next;
+		    name= atname->word;
+
+		    if (name2ip(&hip, name, ifip) && (ip == 0 || ip == hip)) {
+			d= ntohl(hip) ^ ntohl(ifip);
+			if (d < distance) {
+			    dp->yiaddr= hip;
+			    follow= atname->next;
+			    distance= d;
+			}
+		    }
+		}
+	    } else {
+		fprintf(stderr,
+	    "\"%s\", line %u: Usage: client ID [ip#] host [macro|{params}]\n",
+		    cmd->file, cmd->line);
+		exit(1);
+	    }
+	} else
+	if (strcasecmp(cmd->word, "class") == 0) {
+	    config_t *clist;
+	    int match;
+
+	    match= 0;
+	    for (clist= cmd->next; clist != nil
+				&& clist->next != nil
+				&& config_isatom(clist); clist= clist->next) {
+		if (calen > 0
+		    && strncmp(clist->word, (char *) class, calen) == 0
+		) {
+		    match= 1;
+		}
+	    }
+	    if (clist == cmd->next || clist->next != nil) {
+		fprintf(stderr,
+		"\"%s\", line %u: Usage: class class-name ... macro|{params}\n",
+		    cmd->file, cmd->line);
+	    }
+	    if (match) follow= clist;
+	} else
+	if (strcasecmp(cmd->word, "host") == 0) {
+	    if (config_length(cmd) == 3
+		&& config_isatom(cmd->next)
+	    ) {
+		if (ip != 0) {
+		    if (cidr_aton(cmd->next->word, &hip, &mask)) {
+			if (((hip ^ ip) & mask) == 0) {
+			    if (!gettag(dp, DHCP_TAG_NETMASK, nil, nil)) {
+				settag(dp, DHCP_TAG_NETMASK,
+						&mask, sizeof(mask));
+			    }
+			    dp->yiaddr= ip;
+			    follow= cmd->next->next;
+			}
+		    } else
+		    if (name2ip(&hip, cmd->next->word, ifip)) {
+			if (hip == ip) {
+			    dp->yiaddr= ip;
+			    follow= cmd->next->next;
+			}
+		    }
+		}
+	    } else {
+		fprintf(stderr,
+		"\"%s\", line %u: Usage: host host-spec macro|{params}\n",
+		    cmd->file, cmd->line);
+		exit(1);
+	    }
+	} else
+	if (strcasecmp(cmd->word, "interface") == 0) {
+	    if (between(3, config_length(cmd), 4)
+		&& config_isatom(cmd->next)
+		&& config_isatom(cmd->next->next)
+	    ) {
+		network_t *ifnp;
+
+		if (np != nil) {
+		    if ((ifnp= if2net(ifname2if(cmd->next->word))) == nil) {
+			fprintf(stderr,
+			    "\"%s\", line %u: Can't find interface %s\n",
+			    cmd->next->file, cmd->next->line, cmd->next->word);
+			exit(1);
+		    }
+		    if (!name2ip(&hip, cmd->next->next->word, 0)) {
+			fprintf(stderr,
+			    "\"%s\", line %u: Can't find IP address of %s\n",
+			    cmd->next->next->file, cmd->next->next->line,
+			    cmd->next->next->word);
+			exit(1);
+		    }
+		    ifnp->ip= hip;
+		    if (ifnp == np) {
+			dp->yiaddr= hip;
+			follow= cmd->next->next->next;
+		    }
+		}
+	    } else {
+		fprintf(stderr,
+		"\"%s\", line %u: Usage: interface ip# host%s\n",
+		    cmd->file, cmd->line, ntodo==1 ? " [macro|{params}]" : "");
+		exit(1);
+	    }
+	} else
+	if (strcasecmp(cmd->word, "macro") == 0) {
+	    if (config_length(cmd) == 2 && config_isatom(cmd->next)) {
+		follow= cmd->next;
+	    } else
+	    if (ntodo > 1) {
+		fprintf(stderr, "\"%s\", line %u: Usage: macro macro-name\n",
+		    cmd->file, cmd->line);
+		exit(1);
+	    }
+	} else
+	if (strcasecmp(cmd->word, "tag") == 0) {
+	    if (ntodo > 1) {
+		fprintf(stderr,
+		    "\"%s\", line %u: A %s can't be defined here\n",
+		    cmd->file, cmd->line, cmd->word);
+		exit(1);
+	    }
+	} else
+	if (strcasecmp(cmd->word, "option") == 0) {
+	    int ifno;
+	    network_t *ifnp;
+	    config_t *opt;
+
+	    if ((opt= cmd->next) != nil
+		&& config_isatom(opt)
+		&& (ifno= ifname2if(opt->word)) != -1
+	    ) {
+		if ((ifnp= if2net(ifno)) == nil) {
+		    fprintf(stderr,
+			"\"%s\", line %u: Interface %s is not enabled\n",
+			opt->file, opt->line, opt->word);
+		    exit(1);
+		}
+		opt= opt->next;
+	    } else {
+		ifnp= np;
+	    }
+
+	    if (between(1, config_length(opt), 2)
+		&& config_isatom(opt)
+		&& strcasecmp(opt->word, "server") == 0
+		&& (opt->next == nil
+		    || strcasecmp(opt->next->word, "inform") == 0)
+	    ) {
+		if (np != nil) {
+		    ifnp->flags |= NF_SERVING;
+		    if (opt->next != nil) ifnp->flags |= NF_INFORM;
+		}
+	    } else
+	    if (config_length(opt) == 2
+		&& config_isatom(opt)
+		&& strcasecmp(opt->word, "relay") == 0
+		&& config_isatom(opt->next)
+	    ) {
+		if (np != nil) {
+		    if (!name2ip(&hip, opt->next->word, ifip)) {
+			fprintf(stderr,
+			    "\"%s\", line %u: Can't find IP address of %s\n",
+			    opt->next->file, opt->next->line,
+			    opt->next->word);
+			exit(1);
+		    }
+		    ifnp->flags |= NF_RELAYING;
+		    ifnp->server= hip;
+		}
+	    } else
+	    if (config_length(opt) == 1
+		&& config_isatom(opt)
+		&& strcasecmp(opt->word, "possessive") == 0
+	    ) {
+		if (np != nil) ifnp->flags |= NF_POSSESSIVE;
+	    } else
+	    if (config_length(opt) == 2
+		&& config_isatom(opt)
+		&& strcasecmp(opt->word, "hostname") == 0
+		&& config_isatom(opt->next)
+	    ) {
+		if (np != nil) np->hostname= opt->next->word;
+	    } else {
+		fprintf(stderr, "\"%s\", line %u: Unknown option\n",
+		    cmd->file, cmd->line);
+		exit(1);
+	    }
+	} else {
+	    /* Must be an actual data carrying tag. */
+	    configtag(dp, cmd, ifip);
+	}
+
+	if (follow != nil) {
+	    /* A client/class/host entry selects a macro or list that must
+	     * be followed next.
+	     */
+	    config_t *macro;
+
+	    if (config_isatom(follow)) {	/* Macro name */
+		config_t *cfg;
+
+		for (cfg= dhcpconf; cfg != nil; cfg= cfg->next) {
+		    macro= cfg->list;
+
+		    if (strcasecmp(macro->word, "macro") == 0) {
+			if (config_length(macro) == 3
+			    && config_isatom(macro->next)
+			    && config_issub(macro->next->next)
+			) {
+			    if (strcasecmp(macro->next->word, follow->word) == 0
+			    ) {
+				break;
+			    }
+			} else {
+			    fprintf(stderr,
+			"\"%s\", line %u: Usage: macro macro-name {params}\n",
+				macro->file, macro->line);
+			}
+		    }
+		}
+		follow= cfg == nil ? nil : macro->next->next->list;
+	    } else {
+		/* Simply a list of more tags and stuff. */
+		follow= follow->list;
+	    }
+
+	    if (ntodo == arraysize(todo)) {
+		fprintf(stderr, "\"%s\", line %u: Nesting is too deep\n",
+		    follow->file, follow->line);
+		exit(1);
+	    }
+	    todo[ntodo++]= follow;
+	}
+    }
+
+    /* Check if the IP and netmask are OK for the interface. */
+    if (!gettag(dp, DHCP_TAG_NETMASK, &pmask, nil)) return 0;
+    memcpy(&mask, pmask, sizeof(mask));
+    if (((ip ^ ifip) & mask) != 0) return 0;
+
+    /* Fill in the hostname and/or domain. */
+    if ((hostname= ip2name(ip)) != nil) {
+	char *domain;
+
+	if ((domain= strchr(hostname, '.')) != nil) *domain++ = 0;
+
+	if (!gettag(dp, DHCP_TAG_HOSTNAME, nil, nil)) {
+	    settag(dp, DHCP_TAG_HOSTNAME, hostname, strlen(hostname));
+	}
+
+	if (domain != nil && !gettag(dp, DHCP_TAG_DOMAIN, nil, nil)) {
+	    settag(dp, DHCP_TAG_DOMAIN, domain, strlen(domain));
+	}
+    }
+
+    return 1;
+}
+
+static char *dhcpopname(int op)
+{
+    static char *onames[] = { "??\?", "REQUEST", "REPLY" };
+    return onames[op < arraysize(onames) ? op : 0];
+}
+
+char *dhcptypename(int type)
+{
+    static char *tnames[] = {
+	"??\?", "DISCOVER", "OFFER", "REQUEST", "DECLINE",
+	"ACK", "NAK", "RELEASE", "INFORM"
+    };
+    return tnames[type < arraysize(tnames) ? type : 0];
+}
+
+void printdhcp(dhcp_t *dp)
+{
+    /* Print the contents of a DHCP packet, usually for debug purposes. */
+    tagdef_t *tp;
+    u8_t *data, *ovld;
+    size_t i, len;
+
+    for (tp= alltagdef; tp < arraylimit(alltagdef); tp++) {
+	if (tp->type & TF_STATIC) {
+	    data= B(dp) + tp->tag;
+	    len= tp->gran * tp->max;
+	    if ((tp->type & TF_TYPE) == TT_IP) len *= sizeof(ipaddr_t);
+	    if (tp->tag == doff(chaddr)) len= dp->hlen;
+
+	    /* Don't show uninteresting stuff. */
+	    if (tp->tag == doff(htype) && dp->htype == DHCP_HTYPE_ETH) continue;
+
+	    if (tp->tag == doff(hlen) && dp->hlen == DHCP_HLEN_ETH) continue;
+
+	    if ((tp->tag == doff(file) || tp->tag == doff(sname))
+		&& gettag(dp, DHCP_TAG_OVERLOAD, &ovld, nil)
+		&& (ovld[0] & (tp->tag == doff(file) ? 1 : 2))
+	    ) {
+		continue;
+	    }
+	    for (i= 0; i < len && data[i] == 0; i++) {}
+	    if (i == len) continue;
+	} else {
+	    if (!gettag(dp, tp->tag, &data, &len)) continue;
+	}
+
+	if (tagdefined(tp)) {
+	    printf("\t%s =", tp->name);
+	} else {
+	    printf("\tT%d =", tp->tag);
+	}
+
+	i= 0;
+	while (i < len) {
+	    switch (tp->type & TF_TYPE) {
+	    case TT_ASCII: {
+		printf(" \"%.*s\"", (int) len, data);
+		i= len;
+		break;}
+	    case TT_BOOLEAN: {
+		printf(data[i++] == 0 ? " false" : " true");
+		break;}
+	    case TT_IP: {
+		ipaddr_t ip;
+		memcpy(&ip, data+i, sizeof(ip));
+		printf(" %s", inet_ntoa(ip));
+		i += sizeof(ip);
+		break;}
+	    case TT_NUMBER: {
+		u32_t n= 0;
+		int g= tp->gran;
+
+		do n= (n << 8) | data[i++]; while (--g != 0);
+		printf(" %lu", (unsigned long) n);
+		if ((tp->type & TF_STATIC) && tp->tag == doff(op)) {
+		    printf(" (%s)", dhcpopname(n));
+		}
+		if (!(tp->type & TF_STATIC) && tp->tag == DHCP_TAG_TYPE) {
+		    printf(" (%s)", dhcptypename(n));
+		}
+		break;}
+	    case TT_OCTET: {
+		if (i == 0) fputc(' ', stdout);
+		printf("%02X", data[i++]);
+		break;}
+	    }
+	}
+	fputc('\n', stdout);
+    }
+}
Index: /trunk/minix/commands/dis88/Makefile
===================================================================
--- /trunk/minix/commands/dis88/Makefile	(revision 9)
+++ /trunk/minix/commands/dis88/Makefile	(revision 9)
@@ -0,0 +1,50 @@
+# Makefile for dis
+
+# @(#) Makefile, Ver. 2.1 created 00:00:00 87/09/01
+# Makefile for 8088 symbolic disassembler
+
+# Copyright (C) 1987 G. M. Harding, all rights reserved.
+# Permission to copy and redistribute is hereby granted,
+# provided full source code, with all copyright notices,
+# accompanies any redistribution.
+
+# This Makefile  automates the process of compiling and linking
+# a symbolic  object-file  disassembler  program  for the Intel
+# 8088 CPU. Relatively machine-independent code is contained in
+# the file dismain.c; lookup tables and handler routines, which
+# are by their nature  machine-specific,  are  contained in two
+# files named distabs.c and dishand.c,  respectively.  (A third
+# machine-specific file, disfp.c, contains handler routines for
+# floating-point  coprocessor opcodes.)  A header file,  dis.h,
+# attempts to mediate between the machine-specific and machine-
+# independent portions of the code. An attempt has been made to
+# isolate machine  dependencies and to deal with them in fairly
+# straightforward ways. Thus, it should be possible to target a
+# different CPU by rewriting the handler  routines and changing
+# the initialization  data in the lookup tables.  It should not
+# be necessary to alter the formats of the tables.
+
+CFLAGS =-O -wo
+OBJ = disrel.o dismain.o distabs.o dishand.o disfp.o
+CC=exec cc
+
+all:	dis88
+
+dis88:	$(OBJ)
+	cc -i -o dis88 $(OBJ)
+	install -S 5kw dis88
+
+install:	/usr/bin/dis88
+
+/usr/bin/dis88:	dis88
+	install -cs -o bin dis88 $@
+
+disrel.o:	disrel.c
+dismain.o:	dismain.c dis.h
+distabs.o:	distabs.c dis.h
+dishand.o:	dishand.c dis.h
+disfp.o:	disfp.c dis.h
+
+
+clean:	
+	rm -f *.bak *.o core dis88
Index: /trunk/minix/commands/dis88/README
===================================================================
--- /trunk/minix/commands/dis88/README	(revision 9)
+++ /trunk/minix/commands/dis88/README	(revision 9)
@@ -0,0 +1,239 @@
+                                     dis88
+                                  Beta Release
+                                    87/09/01
+                                      ---
+                                 G. M. HARDING
+                                    POB 4142
+                           Santa Clara CA  95054-0142
+
+
+             "Dis88" is a symbolic disassembler for the Intel 8088 CPU,
+        designed to run under the PC/IX  operating  system on an IBM XT
+        or fully-compatible clone.  Its output is in the format of, and
+        is completely compatible with, the PC/IX assembler,  "as".  The
+        program is copyrighted by its author, but may be copied and re-
+        distributed freely provided that complete source code, with all
+        copyright notices, accompanies any distribution. This provision
+        also applies to any  modifications you may make.  You are urged
+        to comment such changes,  giving,  as a miminum,  your name and
+        complete address.
+
+             This release of the program is a beta release, which means
+        that it has been  extensively,  but not  exhaustively,  tested.
+        User comments, recommendations, and bug fixes are welcome.  The
+        principal features of the current release are:
+
+             (a)  The ability to  disassemble  any file in PC/IX object
+        format, making full use of symbol and relocation information if
+        it is present,  regardless of whether the file is executable or
+        linkable,  and regardless of whether it has continuous or split
+        I/D space;
+
+             (b)  Automatic generation of synthetic labels when no sym-
+        bol table is available; and
+
+             (c)  Optional  output of address and object-code  informa-
+        tion as assembler comment text.
+
+             Limitations of the current release are:
+
+             (a)  Numeric co-processor  (i.e., 8087)  mnemonics are not
+        supported.  Instructions  for the co-processor are disassembled
+        as CPU escape  sequences,  or as  interrupts,  depending on how
+        they were assembled in the first place. This limitation will be
+        addressed in a future release.
+
+             (b)  Symbolic  references  within the object  file's  data
+        segment are not supported. Thus, for example, if a data segment
+        location is initialized to point to a text segment address,  no
+        reference to a text segment symbol will be detected. This limi-
+        tation is likely to remain in future  releases,  because object
+        code does not, in most cases, contain sufficient information to
+        allow meaningful interpretation of pure data.  (Note,  however,
+        that  symbolic  references  to the data segment from within the
+        text segment are always supported.)
+
+             As a final caveat,  be aware that the PC/IX assembler does
+        not recognize the  "esc"  mnemonic,  even though it refers to a
+        completely  valid CPU operation  which is documented in all the
+        Intel literature. Thus, the corresponding opcodes (0xd8 through
+        0xdf) are disassembled as .byte directives. For reference, how-
+        ever,  the syntactically-correct "esc" instruction is output as
+        a comment.
+
+             To build the disassembler program, transfer all the source
+        files,  together with the Makefile,  to a suitable  (preferably
+        empty) PC/IX directory. Then, simply type "make".
+
+             To use dis88,  place it in a  directory  which  appears in
+        your $PATH list.  It may then be invoked by name from  whatever
+        directory you happen to be in.  As a minimum,  the program must
+        be invoked with one command-line argument:  the name of the ob-
+        ject file to be disassembled.  (Dis88 will complain if the file
+        specified is not an object file.)  Optionally,  you may specify
+        an output file; stdout is the default.  One command-line switch
+        is available:  "-o",  which makes the program display addresses
+        and object code along with its mnemonic disassembly.
+
+             The "-o" option is useful primarily for verifying the cor-
+        rectness of the program's output. In particular, it may be used
+        to check the accuracy of local  relative  jump  opcodes.  These
+        jumps often  target  local  labels,  which are lost at assembly
+        time;  thus,  the disassembly may contain cryptic  instructions
+        like "jnz .+39".  As a user convenience,  all relative jump and
+        call  opcodes are output with a comment  which  identifies  the
+        physical target address.
+
+             By convention, the release level of the program as a whole
+        is the SID of the file disrel.c, and this SID string appears in
+        each disassembly.  Release 2.1 of the program is the first beta
+        release to be distributed on Usenet.
+
+
+.TH dis88 1 LOCAL
+.SH "NAME"
+dis88 \- 8088 symbolic disassembler
+.SH "SYNOPSIS"
+\fBdis88\fP [ -o ] ifile [ ofile ]
+.SH "DESCRIPTION"
+Dis88 reads ifile, which must be in PC/IX a.out format.
+It interprets the binary opcodes and data locations, and
+writes corresponding assembler source code to stdout, or
+to ofile if specified.  The program's output is in the
+format of, and fully compatible with, the PC/IX assembler,
+as(1).  If a symbol table is present in ifile, labels and
+references will be symbolic in the output.  If the input
+file lacks a symbol table, the fact will be noted, and the
+disassembly will proceed, with the disassembler generating
+synthetic labels as needed.  If the input file has split
+I/D space, or if it is executable, the disassembler will
+make all necessary adjustments in address-reference calculations.
+.PP
+If the "-o" option appears, object code will be included
+in comments during disassembly of the text segment.  This
+feature is used primarily for debugging the disassembler
+itself, but may provide information of passing interest
+to users.
+.PP
+The program always outputs the current machine address
+before disassembling an opcode.  If a symbol table is
+present, this address is output as an assembler comment;
+otherwise, it is incorporated into the synthetic label
+which is generated internally.  Since relative jumps,
+especially short ones, may target unlabelled locations,
+the program always outputs the physical target address
+as a comment, to assist the user in following the code.
+.PP
+The text segment of an object file is always padded to
+an even machine address.  In addition, if the file has
+split I/D space, the text segment will be padded to a
+paragraph boundary (i.e., an address divisible by 16).
+As a result of this padding, the disassembler may produce
+a few spurious, but harmless, instructions at the
+end of the text segment.
+.PP
+Disassembly of the data segment is a difficult matter.
+The information to which initialized data refers cannot
+be inferred from context, except in the special case
+of an external data or address reference, which will be
+reflected in the relocation table.  Internal data and
+address references will already be resolved in the object file,
+and cannot be recreated.  Therefore, the data
+segment is disassembled as a byte stream, with long
+stretches of null data represented by an appropriate
+".zerow" pseudo-op.  This limitation notwithstanding,
+labels (as opposed to symbolic references) are always
+output at appropriate points within the data segment.
+.PP
+If disassembly of the data segment is difficult, disassembly of the
+bss segment is quite easy, because uninitialized data is all
+zero by definition.  No data
+is output in the bss segment, but symbolic labels are
+output as appropriate.
+.PP
+For each opcode which takes an operand, a particular
+symbol type (text, data, or bss) is appropriate.  This
+tidy correspondence is complicated somewhat, however,
+by the existence of assembler symbolic constants and
+segment override opcodes.  Therefore, the disassembler's
+symbol lookup routine attempts to apply a certain amount
+of intelligence when it is asked to find a symbol.  If
+it cannot match on a symbol of the preferred type, it
+may return a symbol of some other type, depending on
+preassigned (and somewhat arbitrary) rankings within
+each type.  Finally, if all else fails, it returns a
+string containing the address sought as a hex constant;
+this behavior allows calling routines to use the output
+of the lookup function regardless of the success of its
+search.
+.PP
+It is worth noting, at this point, that the symbol lookup
+routine operates linearly, and has not been optimized in
+any way.  Execution time is thus likely to increase
+geometrically with input file size.  The disassembler is
+internally limited to 1500 symbol table entries and 1500
+relocation table entries; while these limits are generous
+(/unix, itself, has fewer than 800 symbols), they are not
+guaranteed to be adequate in all cases.  If the symbol
+table or the relocation table overflows, the disassembly
+aborts.
+.PP
+Finally, users should be aware of a bug in the assembler,
+which causes it not to parse the "esc" mnemonic, even
+though "esc" is a completely legitimate opcode which is
+documented in all the Intel literature.  To accommodate
+this deficiency, the disassembler translates opcodes of
+the "esc" family to .byte directives, but notes the
+correct mnemonic in a comment for reference.
+.PP
+In all cases, it should be possible to submit the output
+of the disassembler program to the assembler, and assemble
+it without error.  In most cases, the resulting object
+code will be identical to the original; in any event, it
+will be functionally equivalent.
+.SH "SEE ALSO"
+adb(1), as(1), cc(1), ld(1).
+.br
+"Assembler Reference Manual" in the PC/IX Programmer's
+Guide.
+.SH "DIAGNOSTICS"
+"can't access input file" if the input file cannot be
+found, opened, or read.
+.sp
+"can't open output file" if the output file cannot be
+created.
+.sp
+"warning: host/cpu clash" if the program is run on a
+machine with a different CPU.
+.sp
+"input file not in object format" if the magic number
+does not correspond to that of a PC/IX object file.
+.sp
+"not an 8086/8088 object file" if the CPU ID of the
+file header is incorrect.
+.sp
+"reloc table overflow" if there are more than 1500
+entries in the relocation table.
+.sp
+"symbol table overflow" if there are more than 1500
+entries in the symbol table.
+.sp
+"lseek error" if the input file is corrupted (should
+never happen).
+.sp
+"warning: no symbols" if the symbol table is missing.
+.sp
+"can't reopen input file" if the input file is removed
+or altered during program execution (should never happen).
+.SH "BUGS"
+Numeric co-processor (i.e., 8087) mnemonics are not currently supported.
+Instructions for the co-processor are
+disassembled as CPU escape sequences, or as interrupts,
+depending on how they were assembled in the first place.
+.sp
+Despite the program's best efforts, a symbol retrieved
+from the symbol table may sometimes be different from
+the symbol used in the original assembly.
+.sp
+The disassembler's internal tables are of fixed size,
+and the program aborts if they overflow.
Index: /trunk/minix/commands/dis88/build
===================================================================
--- /trunk/minix/commands/dis88/build	(revision 9)
+++ /trunk/minix/commands/dis88/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/dis88/dis.h
===================================================================
--- /trunk/minix/commands/dis88/dis.h	(revision 9)
+++ /trunk/minix/commands/dis88/dis.h	(revision 9)
@@ -0,0 +1,167 @@
+ /*
+ ** @(#) dis.h, Ver. 2.1 created 00:00:00 87/09/01
+ */
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  *  Copyright (C) 1987 G. M. Harding, all rights reserved  *
+  *                                                         *
+  * Permission to copy and  redistribute is hereby granted, *
+  * provided full source code,  with all copyright notices, *
+  * accompanies any redistribution.                         *
+  *                                                         *
+  * This file contains declarations and definitions used by *
+  * the 8088 disassembler program. The program was designed *
+  * for execution on a machine of its own type (i.e., it is *
+  * not designed as a cross-disassembler);  consequently, A *
+  * SIXTEEN-BIT INTEGER SIZE HAS BEEN ASSUMED. This assump- *
+  * tion is not particularly important,  however, except in *
+  * the machine-specific  portions of the code  (i.e.,  the *
+  * handler  routines and the optab[] array).  It should be *
+  * possible to override this assumption,  for execution on *
+  * 32-bit machines,  by use of a  pre-processor  directive *
+  * (see below); however, this has not been tested.         *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <sys/types.h>
+#include <a.out.h>      /* Object file format definitions   */
+#include <fcntl.h>      /* System file-control definitions  */
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>      /* System standard I/O definitions  */
+
+#define MAXSYM 1500     /* Maximum entries in symbol table  */
+
+extern struct nlist     /* Array to hold the symbol table   */
+   symtab[MAXSYM];
+
+extern struct reloc     /* Array to hold relocation table   */
+   relo[MAXSYM];
+
+extern int symptr;      /* Index into the symtab[] array    */
+extern int relptr;      /* Index into the relo[] array      */
+
+struct opcode           /* Format for opcode data records   */
+{
+   char *text;          /* Pointer to mnemonic text   */
+   void (*func)();      /* Pointer to handler routine */
+   unsigned min;        /* Minimum # of object bytes  */
+   unsigned max;        /* Maximum # of object bytes  */
+};
+
+extern struct opcode    /* Array to hold the opcode table   */
+  optab[256];
+
+extern char *REGS[];    /* Table of register names          */
+extern char *REGS0[];   /* Mode 0 register name table       */
+extern char *REGS1[];   /* Mode 1 register name table       */
+
+#define AL REGS[0]      /* CPU register manifests           */
+#define CL REGS[1]
+#define DL REGS[2]
+#define BL REGS[3]
+#define AH REGS[4]
+#define CH REGS[5]
+#define DH REGS[6]
+#define BH REGS[7]
+#define AX REGS[8]
+#define CX REGS[9]
+#define DX REGS[10]
+#define BX REGS[11]
+#define SP REGS[12]
+#define BP REGS[13]
+#define SI REGS[14]
+#define DI REGS[15]
+#define ES REGS[16]
+#define CS REGS[17]
+#define SS REGS[18]
+#define DS REGS[19]
+#define BX_SI REGS0[0]
+#define BX_DI REGS0[1]
+#define BP_SI REGS0[2]
+#define BP_DI REGS0[3]
+
+extern int symrank[6][6];     /* Symbol type/rank matrix    */
+extern unsigned long PC;      /* Current program counter    */
+extern int segflg;      /* Flag: segment override in effect */
+extern int objflg;      /* Flag: output object as a comment */
+
+#define OBJMAX 8        /* Size of the object code buffer   */
+
+extern unsigned char    /* Internal buffer for object code  */
+   objbuf[OBJMAX];
+
+extern int objptr;      /* Index into the objbuf[] array    */
+
+extern char ADD[],      /* Opcode family mnemonic strings   */
+            OR[],
+            ADC[],
+            SBB[],
+            AND[],
+            SUB[],
+            XOR[],
+            CMP[],
+            NOT[],
+            NEG[],
+            MUL[],
+            DIV[],
+            MOV[],
+            ESC[],
+            TEST[],
+            AMBIG[];
+
+extern char *OPFAM[];   /* Indexed mnemonic family table    */
+extern struct exec HDR; /* Holds the object file's header   */
+
+#define LOOK_ABS 0      /* Arguments to lookup() function   */
+#define LOOK_REL 1
+#define LOOK_LNG 2
+
+#define TR_STD 0        /* Arguments to mtrans() function   */
+#define TR_SEG 8
+
+                        /* Macro for byte input primitive   */
+#define FETCH(p)  ++PC; p = getchar() & 0xff; objbuf[objptr++] = p
+
+
+/* disfp.c */
+_PROTOTYPE(void eshand, (int j ));
+_PROTOTYPE(void fphand, (int j ));
+_PROTOTYPE(void inhand, (int j ));
+
+/* dishand.c */
+_PROTOTYPE(void objini, (int j ));
+_PROTOTYPE(void objout, (void));
+_PROTOTYPE(void badseq, (int j, int k ));
+_PROTOTYPE(void dfhand, (int j ));
+_PROTOTYPE(void sbhand, (int j ));
+_PROTOTYPE(void aohand, (int j ));
+_PROTOTYPE(void sjhand, (int j ));
+_PROTOTYPE(void imhand, (int j ));
+_PROTOTYPE(void mvhand, (int j ));
+_PROTOTYPE(void mshand, (int j ));
+_PROTOTYPE(void pohand, (int j ));
+_PROTOTYPE(void cihand, (int j ));
+_PROTOTYPE(void mihand, (int j ));
+_PROTOTYPE(void mqhand, (int j ));
+_PROTOTYPE(void tqhand, (int j ));
+_PROTOTYPE(void rehand, (int j ));
+_PROTOTYPE(void mmhand, (int j ));
+_PROTOTYPE(void srhand, (int j ));
+_PROTOTYPE(void aahand, (int j ));
+_PROTOTYPE(void iohand, (int j ));
+_PROTOTYPE(void ljhand, (int j ));
+_PROTOTYPE(void mahand, (int j ));
+_PROTOTYPE(void mjhand, (int j ));
+
+/* dismain.c */
+_PROTOTYPE(void main, (int argc, char **argv ));
+
+/* distabs.c */
+_PROTOTYPE(char *getnam, (int k ));
+_PROTOTYPE(int lookext, (long off, long loc, char *buf ));
+_PROTOTYPE(char *lookup, (long addr, int type, int kind, long ext ));
+_PROTOTYPE(char *mtrans, (int c, int m, int type ));
+_PROTOTYPE(void mtrunc, (char *a ));
Index: /trunk/minix/commands/dis88/disfp.c
===================================================================
--- /trunk/minix/commands/dis88/disfp.c	(revision 9)
+++ /trunk/minix/commands/dis88/disfp.c	(revision 9)
@@ -0,0 +1,161 @@
+static char *sccsid =
+   "@(#) disfp.c, Ver. 2.1 created 00:00:00 87/09/01";
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  *  Copyright (C) 1987 G. M. Harding, all rights reserved  *
+  *                                                         *
+  * Permission to copy and  redistribute is hereby granted, *
+  * provided full source code,  with all copyright notices, *
+  * accompanies any redistribution.                         *
+  *                                                         *
+  * This file contains handler routines for the numeric op- *
+  * codes of the 8087 co-processor,  as well as a few other *
+  * opcodes which are related to 8087 emulation.            *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "dis.h"              /* Disassembler declarations  */
+
+#define FPINT0 0xd8           /* Floating-point interrupts  */
+#define FPINT1 0xd9
+#define FPINT2 0xda
+#define FPINT3 0xdb
+#define FPINT4 0xdc
+#define FPINT5 0xdd
+#define FPINT6 0xde
+#define FPINT7 0xdf
+
+                              /* Test for floating opcodes  */
+#define ISFLOP(x) \
+   (((x) >= FPINT0) && ((x) <= FPINT7))
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the  handler for the escape  family of opcodes. *
+  * These opcodes place the contents of a specified  memory *
+  * location on the system bus,  for access by a peripheral *
+  * or by a co-processor such as the 8087. (The 8087 NDP is *
+  * accessed  only  via bus  escapes.)  Due to a bug in the *
+  * PC/IX assembler,  the "esc" mnemonic is not recognized; *
+  * consequently,  escape opcodes are disassembled as .byte *
+  * directives,  with the appropriate  mnemonic and operand *
+  * included as a comment.  FOR NOW, those escape sequences *
+  * corresponding  to 8087  opcodes  are  treated as simple *
+  * escapes.                                                *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+eshand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF eshand()  * * * * * * * * * */
+
+   register char *a;
+   register int k;
+
+   objini(j);
+
+   FETCH(k);
+
+   a = mtrans((j & 0xfd),(k & 0xc7),TR_STD);
+
+   mtrunc(a);
+
+   printf("\t.byte\t0x%02.2x\t\t| esc\t%s\n",j,a);
+
+   for (k = 1; k < objptr; ++k)
+      printf("\t.byte\t0x%02.2x\n",objbuf[k]);
+
+}/* * * * * * * * * * * END OF eshand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the handler routine for floating-point opcodes. *
+  * Since PC/IX must  accommodate  systems with and without *
+  * 8087 co-processors, it allows floating-point operations *
+  * to be  initiated  in either of two ways:  by a software *
+  * interrput whose type is in the range 0xd8 through 0xdf, *
+  * or by a CPU escape sequence, which is invoked by an op- *
+  * code in the same range.  In either case, the subsequent *
+  * byte determines the actual numeric operation to be per- *
+  * formed.  However,  depending  on the  method of access, *
+  * either  one or two code bytes will  precede  that byte, *
+  * and the fphand()  routine has no way of knowing whether *
+  * it was invoked by  interrupt or by an escape  sequence. *
+  * Therefore, unlike all of the other handler routines ex- *
+  * cept dfhand(),  fphand() does not initialize the object *
+  * buffer, leaving that chore to the caller.               *
+  *                                                         *
+  * FOR NOW,  fphand()  does not disassemble floating-point *
+  * opcodes to floating  mnemonics,  but simply outputs the *
+  * object code as .byte directives.                        *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+fphand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF fphand()  * * * * * * * * * */
+
+   register int k;
+
+   segflg = 0;
+
+   FETCH(k);
+
+   printf("\t.byte\t0x%02.2x\t\t| 8087 code sequence\n",
+    objbuf[0]);
+
+   for (k = 1; k < objptr; ++k)
+      printf("\t.byte\t0x%02.2x\n",objbuf[k]);
+
+/* objout();                                       FOR NOW  */
+
+}/* * * * * * * * * * * END OF fphand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the  handler for  variable  software  interrupt *
+  * opcodes.  It is included in this file because PC/IX im- *
+  * plements its software floating-point emulation by means *
+  * of interrupts.  Any interrupt in the range 0xd8 through *
+  * 0xdf is an  NDP-emulation  interrupt,  and is specially *
+  * handled by the assembler.                               *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+inhand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF inhand()  * * * * * * * * * */
+
+   register int k;
+
+   objini(j);
+
+   FETCH(k);
+
+   if (ISFLOP(k))
+      {
+      fphand(k);
+      return;
+      }
+
+   printf("%s\t%d\n",optab[j].text,k);
+
+   objout();
+
+}/* * * * * * * * * * * END OF inhand() * * * * * * * * * * */
+
+
+
Index: /trunk/minix/commands/dis88/dishand.c
===================================================================
--- /trunk/minix/commands/dis88/dishand.c	(revision 9)
+++ /trunk/minix/commands/dis88/dishand.c	(revision 9)
@@ -0,0 +1,1071 @@
+static char *sccsid =
+   "@(#) dishand.c, Ver. 2.1 created 00:00:00 87/09/01";
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  *  Copyright (C) 1987 G. M. Harding, all rights reserved  *
+  *                                                         *
+  * Permission to copy and  redistribute is hereby granted, *
+  * provided full source code,  with all copyright notices, *
+  * accompanies any redistribution.                         *
+  *                                                         *
+  * This file contains the source code for most of the spe- *
+  * cialized handler routines of the disassembler  program. *
+  * (The file disfp.c contains handler routines specific to *
+  * the 8087 numeric  co-processor.)  Each handler  routine *
+  * interprets the opcode byte  (and subsequent data bytes, *
+  * if any)  of a particular family of opcodes,  and is re- *
+  * sponsible for generating appropriate output. All of the *
+  * code in this file is highly MACHINE-SPECIFIC, and would *
+  * have to be rewritten for a different  CPU.  The handler *
+  * routines are accessed  only via pointers in the optab[] *
+  * array, however, so machine dependencies are confined to *
+  * this file, its sister file "disfp.c", and the data file *
+  * "distabs.c".                                            *
+  *                                                         *
+  * All of the code in this file is based on the assumption *
+  * of sixteen-bit integers.                                *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "dis.h"              /* Disassembler declarations  */
+
+int segflg;                   /* Segment-override flag      */
+
+unsigned char objbuf[OBJMAX]; /* Buffer for object code     */
+
+int objptr;                   /* Index into objbuf[]        */
+
+unsigned long PC;             /* Current program counter    */
+
+
+ /* * * * * *  MISCELLANEOUS SUPPORTING ROUTINES  * * * * * */
+
+
+void
+objini(j)                     /* Object code init routine   */
+
+   register int j;
+
+{
+   if ((segflg == 1) || (segflg == 2))
+      segflg *= 3;
+   else
+      segflg = 0;
+   objptr = 0;
+   objbuf[objptr++] = (unsigned char)(j);
+}
+
+
+void
+objout()                      /* Object-code output routine */
+
+{
+    register int k;
+
+   if ( ! objflg )
+      return;
+   else
+      {
+      printf("\t|");
+      if (symptr >= 0)
+         printf(" %05.5lx:",(PC + 1L - (long)(objptr)));
+      for (k = 0; k < objptr; ++k)
+         printf(" %02.2x",objbuf[k]);
+      putchar('\n');
+      }
+}
+
+
+void
+badseq(j,k)                   /* Invalid-sequence routine   */
+
+   register int j, k;
+
+{
+   printf("\t.byte\t0x%02.2x\t\t| invalid code sequence\n",j);
+   printf("\t.byte\t0x%02.2x\n",k);
+}
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This  routine  is the first of several  opcode-specific *
+  * handlers,  each of which is  dedicated  to a particular *
+  * opcode family.  A pointer to a handler  routine is con- *
+  * tained in the second field of each optab[]  entry.  The *
+  * dfhand()  routine is the default handler,  invoked when *
+  * no other handler is appropriate (generally, when an in- *
+  * valid opcode is encountered).                           *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+dfhand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF dfhand()  * * * * * * * * * */
+
+   segflg = 0;
+
+   printf("\t.byte\t0x%02.2x",j);
+
+   if (optab[j].min || optab[j].max)
+      putchar('\n');
+   else
+      printf("\t\t| unimplemented opcode\n");
+
+}/* * * * * * * * * * * END OF dfhand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the  single-byte  handler,  invoked  whenever a *
+  * one-byte opcode is encountered.                         *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+sbhand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF sbhand()  * * * * * * * * * */
+
+   objini(j);
+
+   if (j == 0x2e)                               /* seg cs   */
+      segflg = 1;
+
+   if ((j == 0x26)                              /* seg es   */
+    || (j == 0x36)                              /* seg ss   */
+    || (j == 0x3e))                             /* seg ds   */
+      segflg = 2;
+
+   printf("%s\n",optab[j].text);
+
+   objout();
+
+}/* * * * * * * * * * * END OF sbhand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the handler for most of the processor's regular *
+  * arithmetic operations.                                  *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+aohand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF aohand()  * * * * * * * * * */
+
+   register int k;
+   int m, n;
+   char b[64];
+
+   objini(j);
+
+   switch (j & 7)
+      {
+      case 0 :
+      case 1 :
+      case 2 :
+      case 3 :
+         printf("%s\t",optab[j].text);
+         FETCH(k);
+         printf("%s\n",mtrans(j,k,TR_STD));
+         break;
+      case 4 :
+         FETCH(k);
+         printf("%s\tal,*0x%02.2x\n",optab[j].text,k);
+         break;
+      case 5 :
+         FETCH(m);
+         FETCH(n);
+         k = (n << 8) | m;
+         if (lookext((long)(k),(PC - 1),b))
+            printf("%s\tax,#%s\n",optab[j].text,b);
+         else
+            printf("%s\tax,#0x%04.4x\n",optab[j].text,k);
+         break;
+      default :
+         dfhand(j);
+         break;
+      }
+
+   objout();
+
+}/* * * * * * * * * * * END OF aohand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the  handler for opcodes  which  perform  short *
+  * (eight-bit) relative jumps.                             *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+sjhand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF sjhand()  * * * * * * * * * */
+
+   register int k;
+   int m;
+
+   objini(j);
+
+   FETCH(m);
+
+   if (m & 0x80)
+      k = 0xff00;
+   else
+      k = 0;
+
+   k |= m;
+
+   printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text,
+    lookup((PC + k + 1L),N_TEXT,LOOK_REL,-1L),
+    (PC + k + 1L));
+
+   objout();
+
+}/* * * * * * * * * * * END OF sjhand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the  handler for a  loosely-knit  family of op- *
+  * codes which perform  arithmetic and logical operations, *
+  * and which take immediate  data.  The routine's logic is *
+  * rather complex,  so,  in an effort to avoid  additional *
+  * complexity,  the search for external  references in the *
+  * relocation table has been dispensed with. Eager hackers *
+  * can try their hand at coding such a search.             *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+imhand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF imhand()  * * * * * * * * * */
+
+   unsigned long pc;
+   register int k;
+   int offset, oflag, immed, iflag, mod, opi, w, rm;
+   int m, n;
+   static char a[100], b[30];
+
+   objini(j);
+
+   FETCH(k);
+
+   pc = PC + 1;
+
+   offset = 0;
+   mod = (k & 0xc0) >> 6;
+   opi = (k & 0x38) >> 3;
+   w = j & 1;
+   rm = k & 7;
+
+   if ((j & 2)
+    && ((opi == 1)
+     || (opi == 4)
+     || (opi == 6)))
+      {
+      badseq(j,k);
+      return;
+      }
+
+   strcpy(a,OPFAM[opi]);
+
+   if ( ! w )
+      strcat(a,"b");
+
+   if ((oflag = mod) > 2)
+      oflag = 0;
+
+   if ((mod == 0) && (rm == 6))
+      {
+      FETCH(m);
+      FETCH(n);
+      offset = (n << 8) | m;
+      }
+   else if (oflag)
+      if (oflag == 2)
+         {
+         FETCH(m);
+         FETCH(n);
+         offset = (n << 8) | m;
+         }
+      else
+         {
+         FETCH(m);
+         if (m & 0x80)
+            n = 0xff00;
+         else
+            n = 0;
+         offset = n | m;
+         }
+
+   switch (j & 3)
+      {
+      case 0 :
+      case 2 :
+         FETCH(immed);
+         iflag = 0;
+         break;
+      case 1 :
+         FETCH(m);
+         FETCH(n);
+         immed = (n << 8) | m;
+         iflag = 1;
+         break;
+      case 3 :
+         FETCH(immed);
+         if (immed & 0x80)
+            immed &= 0xff00;
+         iflag = 0;
+         break;
+      }
+
+   strcat(a,"\t");
+
+   switch (mod)
+      {
+      case 0 :
+         if (rm == 6)
+            strcat(a,
+             lookup((long)(offset),N_DATA,LOOK_ABS,pc));
+         else
+            {
+            sprintf(b,"(%s)",REGS0[rm]);
+            strcat(a,b);
+            }
+         break;
+      case 1 :
+      case 2 :
+         if (mod == 1)
+            strcat(a,"*");
+         else
+            strcat(a,"#");
+         sprintf(b,"%d(",offset);
+         strcat(a,b);
+         strcat(a,REGS1[rm]);
+         strcat(a,")");
+         break;
+      case 3 :
+         strcat(a,REGS[(w << 3) | rm]);
+         break;
+      }
+
+   strcat(a,",");
+   if (iflag)
+      strcat(a,"#");
+   else
+      strcat(a,"*");
+   sprintf(b,"%d",immed);
+   strcat(a,b);
+
+   printf("%s\n",a);
+
+   objout();
+
+}/* * * * * * * * * * * END OF imhand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the  handler  for  various  "mov"-type  opcodes *
+  * which use the mod,  reg,  and r/m  fields of the second *
+  * code byte in a standard, straightforward way.           *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+mvhand(j)
+
+   int j;                     /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF mvhand()  * * * * * * * * * */
+
+   register int k, m = j;
+
+   objini(j);
+
+   FETCH(k);
+
+   if ((m == 0x84) || (m == 0x85)      /* Kind of kludgey   */
+    || (m == 0xc4) || (m == 0xc5)
+    || (m == 0x8d))
+      if (m & 0x40)
+         m |= 0x03;
+      else
+         m |= 0x02;
+
+   printf("%s\t%s\n",optab[j].text,mtrans(m,k,TR_STD));
+
+   objout();
+
+}/* * * * * * * * * * * END OF mvhand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the handler for segment-register "mov" opcodes. *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+mshand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF mshand()  * * * * * * * * * */
+
+   register int k;
+
+   objini(j);
+
+   FETCH(k);
+
+   if (k & 0x20)
+      {
+      badseq(j,k);
+      return;
+      }
+
+   printf("%s\t%s\n",optab[j].text,mtrans(j,k,TR_SEG));
+
+   objout();
+
+}/* * * * * * * * * * * END OF mshand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the  handler for pops,  other than  single-byte *
+  * pops.  (The 8088 allows  popping into any register,  or *
+  * directly into memory,  accessed  either  immediately or *
+  * through a register and an index.)                       *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+pohand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF pohand()  * * * * * * * * * */
+
+   char *a;
+   register int k;
+
+   objini(j);
+
+   FETCH(k);
+
+   if (k & 0x38)
+      {
+      badseq(j,k);
+      return;
+      }
+
+   printf("%s\t",optab[j].text);
+
+   a = mtrans((j & 0xfd),k,TR_STD);
+
+   mtrunc(a);
+
+   printf("%s\n",a);
+
+   objout();
+
+}/* * * * * * * * * * * END OF pohand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the handler routine for intersegment  calls and *
+  * jumps.  Its output is never symbolic,  because the host *
+  * linker  does not allow  symbolic  intersegment  address *
+  * references except by means of symbolic  constants,  and *
+  * any such  constants in the symbol  table,  even if they *
+  * are of the  appropriate  value,  may be misleading.  In *
+  * compiled code,  intersegment  references  should not be *
+  * encountered,  and even in assembled  code,  they should *
+  * occur infrequently. If and when they do occur, however, *
+  * they will be disassembled in absolute form.             *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+cihand(j)
+
+   int j;                     /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF cihand()  * * * * * * * * * */
+
+   register int m, n;
+
+   objini(j);
+
+   printf("%s\t",optab[j].text);
+
+   FETCH(m);
+   FETCH(n);
+
+   printf("#0x%04.4x,",((n << 8) | m));
+
+   FETCH(m);
+   FETCH(n);
+
+   printf("#0x%04.4x\n",((n << 8) | m));
+
+   objout();
+
+}/* * * * * * * * * * * END OF cihand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the handler for  "mov"  opcodes with  immediate *
+  * data.                                                   *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+mihand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF mihand()  * * * * * * * * * */
+
+   register int k;
+   int m, n;
+   char b[64];
+
+   objini(j);
+
+   printf("%s",optab[j].text);
+
+   if (j & 8)
+      {
+      FETCH(m);
+      FETCH(n);
+      k = ((n << 8) | m);
+      if (lookext((long)(k),(PC - 1),b))
+         printf("#%s\n",b);
+      else
+         printf("#%d\n",k);
+      }
+   else
+      {
+      FETCH(m);
+      printf("*%d\n",m);
+      }
+
+   objout();
+
+}/* * * * * * * * * * * END OF mihand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the handler for a family of quick-move opcodes. *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+mqhand(j)
+
+   int j;                     /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF mqhand()  * * * * * * * * * */
+
+   unsigned long pc;
+   register int m, n;
+
+   objini(j);
+
+   pc = PC + 1;
+
+   FETCH(m);
+   FETCH(n);
+
+   m = (n << 8) | m;
+
+   printf("%s\t",optab[j].text);
+
+   if (j & 2)
+      printf("%s,%s\n",
+       lookup((long)(m),N_DATA,LOOK_ABS,pc),
+       REGS[(j & 1) << 3]);
+   else
+      printf("%s,%s\n",
+       REGS[(j & 1) << 3],
+       lookup((long)(m),N_DATA,LOOK_ABS,pc));
+
+   objout();
+
+}/* * * * * * * * * * * END OF mqhand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the handler for a family of quick-test opcodes. *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+tqhand(j)
+
+   int j;                     /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF tqhand()  * * * * * * * * * */
+
+   register int m, n;
+   int k;
+   char b[64];
+
+   objini(j);
+
+   printf("%s\t%s,",optab[j].text,REGS[(j & 1) << 3]);
+
+   FETCH(m);
+
+   if (j & 1)
+      {
+      FETCH(n);
+      k = ((n << 8) | m);
+      if (lookext((long)(k),(PC - 1),b))
+         printf("#%s\n",b);
+      else
+         printf("#%d\n",k);
+      }
+   else
+      {
+      if (m & 80)
+         m |= 0xff00;
+      printf("*%d\n",m);
+      }
+
+   objout();
+
+}/* * * * * * * * * * * END OF tqhand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the handler for multiple-byte "return" opcodes. *
+  * The 8088 allows returns to take an optional  16-bit ar- *
+  * gument,  which  reflects  the  amount to be added to SP *
+  * after  the pop of the  return  address.  The idea is to *
+  * facilitate  the use of local  parameters  on the stack. *
+  * After some  rumination,  it was decided to  disassemble *
+  * any such arguments as absolute quantities,  rather than *
+  * rummaging  through the symbol table for possible corre- *
+  * sponding constants.                                     *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+rehand(j)
+
+   int j;                     /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF rehand()  * * * * * * * * * */
+
+   register int m, n;
+
+   objini(j);
+
+   FETCH(m);
+   FETCH(n);
+
+   m = (n << 8) | m;
+
+   printf("%s\t#0x%04.4x\n",optab[j].text,m);
+
+   objout();
+
+}/* * * * * * * * * * * END OF rehand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the handler for "mov"  opcodes involving memory *
+  * and immediate data.                                     *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+mmhand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF mmhand()  * * * * * * * * * */
+
+   char *a;
+   register int k;
+   char b[64];
+
+   objini(j);
+
+   FETCH(k);
+
+   if (k & 0x38)
+      {
+      badseq(j,k);
+      return;
+      }
+
+   printf("%s",optab[j].text);
+
+   if ( ! (j & 1) )
+      putchar('b');
+
+   a = mtrans((j & 0xfd),(k & 0xc7),TR_STD);
+
+   mtrunc(a);
+
+   printf("\t%s,",a);
+
+   if (j & 1)
+      {
+      FETCH(j);
+      FETCH(k);
+      k = (k << 8) | j;
+      if (lookext((long)(k),(PC - 1),b))
+         printf("#%s\n",b);
+      else
+         printf("#%d\n",k);
+      }
+   else
+      {
+      FETCH(k);
+      printf("*%d\n",k);
+      }
+
+   objout();
+
+}/* * * * * * * * * * * END OF mmhand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the  handler  for the 8088  family of shift and *
+  * rotate instructions.                                    *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+srhand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF srhand()  * * * * * * * * * */
+
+   char *a;
+   register int k;
+
+   objini(j);
+
+   FETCH(k);
+
+   if ((k & 0x38) == 0x30)
+      {
+      badseq(j,k);
+      return;
+      }
+
+   printf("%s",OPFAM[((k & 0x38) >> 3) + 16]);
+
+   if ( ! (j & 1) )
+      putchar('b');
+
+   a = mtrans((j & 0xfd),(k & 0xc7),TR_STD);
+
+   mtrunc(a);
+
+   printf("\t%s",a);
+
+   if (j & 2)
+      printf(",cl\n");
+   else
+      printf(",*1\n");
+
+   objout();
+
+}/* * * * * * * * * * * END OF srhand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the handler for the ASCII-adjust opcodes.       *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+aahand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF aahand()  * * * * * * * * * */
+
+   register int k;
+
+   objini(j);
+
+   FETCH(k);
+
+   if (k != 0x0a)
+      {
+      badseq(j,k);
+      return;
+      }
+
+   printf("%s\n",optab[j].text);
+
+   objout();
+
+}/* * * * * * * * * * * END OF aahand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the handler for port I/O opcodes  which specify *
+  * the port address as an immediate operand.               *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+iohand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF iohand()  * * * * * * * * * */
+
+   register int k;
+
+   objini(j);
+
+   FETCH(k);
+
+   printf("%s\t0x%02.2x\n",optab[j].text,k);
+
+   objout();
+
+}/* * * * * * * * * * * END OF iohand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the  handler  for opcodes  which  perform  long *
+  * (sixteen-bit) relative jumps and calls.                 *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+ljhand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF ljhand()  * * * * * * * * * */
+
+   register int k;
+   int m, n;
+
+   objini(j);
+
+   FETCH(m);
+   FETCH(n);
+
+   k = (n << 8) | m;
+
+   printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text,
+    lookup((PC + k + 1L),N_TEXT,LOOK_LNG,(PC - 1L)),
+    (PC + k + 1L));
+
+   objout();
+
+}/* * * * * * * * * * * END OF ljhand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the handler for a pair of oddball opcodes (0xf6 *
+  * and 0xf7) which perform miscellaneous arithmetic opera- *
+  * tions not dealt with elsewhere.                         *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+mahand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF mahand()  * * * * * * * * * */
+
+   char *a;
+   register int k;
+   char b[64];
+
+   objini(j);
+
+   FETCH(k);
+
+   a = mtrans((j & 0xfd),(k & 0xc7),TR_STD);
+
+   mtrunc(a);
+
+   switch (((k = objbuf[1]) & 0x38) >> 3)
+      {
+      case 0 :
+         printf("\ttest");
+         break;
+      case 1 :
+         badseq(j,k);
+         return;
+      case 2 :
+         printf("\tnot");
+         break;
+      case 3 :
+         printf("\tneg");
+         break;
+      case 4 :
+         printf("\tmul");
+         break;
+      case 5 :
+         printf("\timul");
+         break;
+      case 6 :
+         printf("\tdiv");
+         break;
+      case 7 :
+         printf("\tidiv");
+         break;
+      }
+
+   if ( ! (j & 1) )
+      putchar('b');
+
+   printf("\t%s",a);
+
+   if (k & 0x38)
+      putchar('\n');
+   else
+      if (j & 1)
+         {
+         FETCH(j);
+         FETCH(k);
+         k = (k << 8) | j;
+         if (lookext((long)(k),(PC - 1),b))
+            printf(",#%s\n",b);
+         else
+            printf(",#%d\n",k);
+         }
+      else
+         {
+         FETCH(k);
+         printf(",*%d\n",k);
+         }
+
+   objout();
+
+}/* * * * * * * * * * * END OF mahand() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the handler for miscellaneous jump, call, push, *
+  * and increment/decrement opcodes  (0xfe and 0xff)  which *
+  * are not dealt with elsewhere.                           *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+mjhand(j)
+
+   register int j;            /* Pointer to optab[] entry   */
+
+{/* * * * * * * * * *  START OF mjhand()  * * * * * * * * * */
+
+   char *a;
+   register int k;
+
+   objini(j);
+
+   FETCH(k);
+
+   a = mtrans((j & 0xfd),(k & 0xc7),TR_STD);
+
+   mtrunc(a);
+
+   switch (((k = objbuf[1]) & 0x38) >> 3)
+      {
+      case 0 :
+         printf("\tinc");
+         if ( ! (j & 1) )
+            putchar('b');
+         putchar('\t');
+         break;
+      case 1 :
+         printf("\tdec");
+         if ( ! (j & 1) )
+            putchar('b');
+         putchar('\t');
+         break;
+      case 2 :
+         if (j & 1)
+            printf("\tcall\t@");
+         else
+            goto BAD;
+         break;
+      case 3 :
+         if (j & 1)
+            printf("\tcalli\t@");
+         else
+            goto BAD;
+         break;
+      case 4 :
+         if (j & 1)
+            printf("\tjmp\t@");
+         else
+            goto BAD;
+         break;
+      case 5 :
+         if (j & 1)
+            printf("\tjmpi\t@");
+         else
+            goto BAD;
+         break;
+      case 6 :
+         if (j & 1)
+            printf("\tpush\t");
+         else
+            goto BAD;
+         break;
+      case 7 :
+ BAD :
+         badseq(j,k);
+         return;
+      }
+
+   printf("%s\n",a);
+
+   objout();
+
+}/* * * * * * * * * * * END OF mjhand() * * * * * * * * * * */
+
+
+
Index: /trunk/minix/commands/dis88/dismain.c
===================================================================
--- /trunk/minix/commands/dis88/dismain.c	(revision 9)
+++ /trunk/minix/commands/dis88/dismain.c	(revision 9)
@@ -0,0 +1,631 @@
+static char *sccsid =  "@(#) dismain.c, Ver. 2.1 created 00:00:00 87/09/01";
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  *  Copyright (C) 1987 G. M. Harding, all rights reserved  *
+  *                                                         *
+  * Permission to copy and  redistribute is hereby granted, *
+  * provided full source code,  with all copyright notices, *
+  * accompanies any redistribution.                         *
+  *                                                         *
+  * This file  contains  the source  code for the  machine- *
+  * independent  portions of a disassembler  program to run *
+  * in a Unix (System III) environment.  It expects, as its *
+  * input, a file in standard a.out format, optionally con- *
+  * taining symbol table information.  If a symbol table is *
+  * present, it will be used in the disassembly; otherwise, *
+  * all address references will be literal (absolute).      *
+  *                                                         *
+  * The disassembler  program was originally written for an *
+  * Intel 8088 CPU.  However, all details of the actual CPU *
+  * architecture are hidden in three machine-specific files *
+  * named  distabs.c,  dishand.c,  and disfp.c  (the latter *
+  * file is specific to the 8087 numeric co-processor). The *
+  * code in this file is generic,  and should require mini- *
+  * mal revision if a different CPU is to be targeted. If a *
+  * different version of Unix is to be targeted, changes to *
+  * this file may be necessary, and if a completely differ- *
+  * ent OS is to be targeted, all bets are off.             *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "dis.h"              /* Disassembler declarations  */
+
+extern char *release;         /* Contains release string    */
+static char *IFILE = NULL;    /* Points to input file name  */
+static char *OFILE = NULL;    /* Points to output file name */
+static char *PRG;             /* Name of invoking program   */
+static unsigned long zcount;  /* Consecutive "0" byte count */
+int objflg = 0;               /* Flag: output object bytes  */
+
+#define unix 1
+#define i8086 1
+#define ibmpc 1
+
+#if unix && i8086 && ibmpc    /* Set the CPU identifier     */
+static int cpuid = 1;
+#else
+static int cpuid = 0;
+#endif
+
+_PROTOTYPE(static void usage, (char *s ));
+_PROTOTYPE(static void fatal, (char *s, char *t ));
+_PROTOTYPE(static void zdump, (unsigned long beg ));
+_PROTOTYPE(static void prolog, (void));
+_PROTOTYPE(static void distext, (void));
+_PROTOTYPE(static void disdata, (void));
+_PROTOTYPE(static void disbss, (void));
+
+_PROTOTYPE(static char *invoker, (char *s));
+_PROTOTYPE(static int objdump, (char *c));
+_PROTOTYPE(static char *getlab, (int type));
+_PROTOTYPE(static void prolog, (void));
+
+ /* * * * * * * MISCELLANEOUS UTILITY FUNCTIONS * * * * * * */
+
+static void
+usage(s)
+   register char *s;
+{
+   fprintf(stderr,"Usage: %s [-o] ifile [ofile]\n",s);
+   exit(-1);
+}
+
+static void
+fatal(s,t)
+   register char *s, *t;
+{
+   fprintf(stderr,"\07%s: %s\n",s,t);
+   exit(-1);
+}
+
+static void
+zdump(beg)
+   unsigned long beg;
+{
+   beg = PC - beg;
+   if (beg > 1L)
+      printf("\t.zerow\t%ld\n",(beg >> 1));
+   if (beg & 1L)
+      printf("\t.byte\t0\n");
+}
+
+static char *
+invoker(s)
+   register char *s;
+{
+   register int k;
+
+   k = strlen(s);
+
+   while (k--)
+      if (s[k] == '/')
+         {
+         s += k;
+         ++s;
+         break;
+         }
+
+   return (s);
+}
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This rather tricky routine supports the disdata() func- *
+  * tion.  Its job is to output the code for a sequence  of *
+  * data bytes whenever the object buffer is full,  or when *
+  * a symbolic label is to be output. However, it must also *
+  * keep track of  consecutive  zero words so that  lengthy *
+  * stretches of null data can be  compressed by the use of *
+  * an  appropriate  assembler  pseudo-op.  It does this by *
+  * setting and testing a file-wide  flag which counts suc- *
+  * cessive full buffers of null data. The function returns *
+  * a logical  TRUE value if it outputs  anything,  logical *
+  * FALSE otherwise.  (This enables disdata()  to determine *
+  * whether to output a new  synthetic  label when there is *
+  * no symbol table.)                                       *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+static int
+objdump(c)
+
+   register char *c;
+
+{/* * * * * * * * * * START OF  objdump() * * * * * * * * * */
+
+   register int k;
+   int retval = 0;
+
+   if (objptr == OBJMAX)
+      {
+      for (k = 0; k < OBJMAX; ++k)
+         if (objbuf[k])
+            break;
+      if (k == OBJMAX)
+         {
+         zcount += k;
+         objptr = 0;
+         if (c == NULL)
+            return (retval);
+         }
+      }
+
+   if (zcount)
+      {
+      printf("\t.zerow\t%ld\n",(zcount >> 1));
+      ++retval;
+      zcount = 0L;
+      }
+
+   if (objptr)
+      {
+      printf("\t.byte\t");
+      ++retval;
+      }
+   else
+      return (retval);
+
+   for (k = 0; k < objptr; ++k)
+      {
+      printf("0x%02.2x",objbuf[k]);
+      if (k < (objptr - 1))
+         putchar(',');
+      else
+         putchar('\n');
+      }
+
+   objptr = 0;
+
+   return (retval);
+
+}/* * * * * * * * * *  END OF  objdump()  * * * * * * * * * */
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This  routine,  called  at the  beginning  of the input *
+  * cycle for each object byte,  and before any interpreta- *
+  * tion is  attempted,  searches  the symbol table for any *
+  * symbolic  name with a value  corresponding  to the cur- *
+  * rent PC and a type  corresponding  to the segment  type *
+  * (i.e.,  text, data, or bss) specified by the function's *
+  * argument. If any such name is found, a pointer to it is *
+  * returned; otherwise, a NULL pointer is returned.        *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+static char *
+getlab(type)
+register int type;
+{/* * * * * * * * * *  START OF getlab()  * * * * * * * * * */
+
+   register int k;
+   static char b[32], c[10];
+
+   if (symptr < 0)
+      if ((type == N_TEXT)
+       || ((type == N_DATA) && ( ! objptr ) && ( ! zcount )))
+         {
+         if (type == N_TEXT)
+            sprintf(b,"T%05.5lx:",PC);
+         else
+            sprintf(b,"D%05.5lx:",PC);
+         return (b);
+         }
+      else
+         return (NULL);
+
+   for (k = 0; k <= symptr; ++k)
+      if ((symtab[k].n_value == PC)
+       && ((symtab[k].n_sclass & N_SECT) == type))
+         {
+         sprintf(b,"%s:\n",getnam(k));
+         if (objflg && (type != N_TEXT))
+            sprintf(c,"| %05.5lx\n",PC);
+         strcat(b,c);
+         return (b);
+         }
+
+   return (NULL);
+
+}/* * * * * * * * * * * END OF getlab() * * * * * * * * * * */
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This routine  performs a preliminary scan of the symbol *
+  * table,  before disassembly begins, and outputs declara- *
+  * tions of globals and constants.                         *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+static void
+prolog()
+
+{/* * * * * * * * * *  START OF prolog()  * * * * * * * * * */
+
+   register int j, flag;
+
+   if (symptr < 0)
+      return;
+
+   for (j = flag = 0; j <= symptr; ++j)
+      if ((symtab[j].n_sclass & N_CLASS) == C_EXT)
+         if (((symtab[j].n_sclass & N_SECT) > N_UNDF)
+          && ((symtab[j].n_sclass & N_SECT) < N_COMM))
+            {
+            char *c = getnam(j);
+            printf("\t.globl\t%s",c);
+            if (++flag == 1)
+               {
+               putchar('\t');
+               if (strlen(c) < 8)
+                  putchar('\t');
+               printf("| Internal global\n");
+               }
+            else
+               putchar('\n');
+            }
+         else
+            if (symtab[j].n_value)
+               {
+               char *c = getnam(j);
+               printf("\t.comm\t%s,0x%08.8lx",c,
+                symtab[j].n_value);
+               if (++flag == 1)
+                  printf("\t| Internal global\n");
+               else
+                  putchar('\n');
+               }
+
+   if (flag)
+      putchar('\n');
+
+   for (j = flag = 0; j <= relptr; ++j)
+      if (relo[j].r_symndx < S_BSS)
+         {
+         char *c = getnam(relo[j].r_symndx);
+         ++flag;
+         printf("\t.globl\t%s",c);
+         putchar('\t');
+         if (strlen(c) < 8)
+            putchar('\t');
+         printf("| Undef: %05.5lx\n",relo[j].r_vaddr);
+         }
+
+   if (flag)
+      putchar('\n');
+
+   for (j = flag = 0; j <= symptr; ++j)
+      if ((symtab[j].n_sclass & N_SECT) == N_ABS)
+         {
+         char *c = getnam(j);
+         printf("%s=0x%08.8lx",c,symtab[j].n_value);
+         if (++flag == 1)
+            {
+            printf("\t\t");
+            if (strlen(c) < 5)
+               putchar('\t');
+            printf("| Literal\n");
+            }
+         else
+            putchar('\n');
+         }
+
+   if (flag)
+      putchar('\n');
+
+}/* * * * * * * * * * * END OF prolog() * * * * * * * * * * */
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This function is  responsible  for  disassembly  of the *
+  * object file's text segment.                             *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+static void
+distext()
+
+{/* * * * * * * * * * START OF  distext() * * * * * * * * * */
+
+   char *c;
+   register int j;
+   register void (*f)();
+
+   for (j = 0; j < (int)(HDR.a_hdrlen); ++j)
+      getchar();
+
+   printf("| %s, %s\n\n",PRG,release);
+
+   printf("| @(");
+
+   printf("#)\tDisassembly of %s",IFILE);
+
+   if (symptr < 0)
+      printf(" (no symbols)\n\n");
+   else
+      printf("\n\n");
+
+   if (HDR.a_flags & A_EXEC)
+      printf("| File is executable\n\n");
+
+   if (HDR.a_flags & A_SEP)
+      {
+      printf("| File has split I/D space, and may have\n");
+      printf("| extraneous instructions in text segment\n\n");
+      }
+
+   prolog();
+
+   printf("\t.text\t\t\t| loc = %05.5lx, size = %05.5lx\n\n",
+    PC,HDR.a_text);
+
+   segflg = 0;
+
+   for (PC = 0L; PC < HDR.a_text; ++PC)
+      {
+      j = getchar() & 0xff;
+      if ((j == 0) && ((PC + 1L) == HDR.a_text))
+         {
+         ++PC;
+         break;
+         }
+      if ((c = getlab(N_TEXT)) != NULL)
+         printf("%s",c);
+      f = optab[j].func;
+      (*f)(j);
+      }
+
+}/* * * * * * * * * *  END OF  distext()  * * * * * * * * * */
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This  function  handles the object file's data segment. *
+  * There is no good way to disassemble a data segment, be- *
+  * cause it is  impossible  to tell,  from the object code *
+  * alone,  what each data byte refers to.  If it refers to *
+  * an external symbol,  the reference can be resolved from *
+  * the relocation table, if there is one.  However,  if it *
+  * refers to a static symbol,  it cannot be  distinguished *
+  * from numeric, character, or other pointer data. In some *
+  * cases,  one might make a semi-educated  guess as to the *
+  * nature of the data,  but such  guesses  are  inherently *
+  * haphazard,  and they are  bound to be wrong a good por- *
+  * tion of the time.  Consequently,  the data  segment  is *
+  * disassembled  as a byte  stream,  which will satisfy no *
+  * one but which, at least, will never mislead anyone.     *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+static void
+disdata()
+
+{/* * * * * * * * * * START OF  disdata() * * * * * * * * * */
+
+   register char *c;
+   register int j;
+   unsigned long end;
+
+   putchar('\n');
+
+   if (HDR.a_flags & A_SEP)
+      {
+      PC = 0L;
+      end = HDR.a_data;
+      }
+   else
+      end = HDR.a_text + HDR.a_data;
+
+   printf("\t.data\t\t\t| loc = %05.5lx, size = %05.5lx\n\n",
+    PC,HDR.a_data);
+
+   segflg = 0;
+
+   for (objptr = 0, zcount = 0L; PC < end; ++PC)
+      {
+      if ((c = getlab(N_DATA)) != NULL)
+         {
+         objdump(c);
+         printf("%s",c);
+         }
+      if (objptr >= OBJMAX)
+         if (objdump(NULL) && (symptr < 0))
+            printf("D%05.5lx:",PC);
+      j = getchar() & 0xff;
+      objbuf[objptr++] = j;
+      }
+
+   objdump("");
+
+}/* * * * * * * * * *  END OF  disdata()  * * * * * * * * * */
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This  function  handles the object  file's bss segment. *
+  * Disassembly of the bss segment is easy,  because every- *
+  * thing in it is zero by definition.                      *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+static void disbss()
+
+{/* * * * * * * * * *  START OF disbss()  * * * * * * * * * */
+
+   register int j;
+   register char *c;
+   unsigned long beg, end;
+
+   putchar('\n');
+
+   if (HDR.a_flags & A_SEP)
+      end = HDR.a_data + HDR.a_bss;
+   else
+      end = HDR.a_text + HDR.a_data + HDR.a_bss;
+
+   printf("\t.bss\t\t\t| loc = %05.5lx, size = %05.5lx\n\n",
+    PC,HDR.a_bss);
+
+   segflg = 0;
+
+   for (beg = PC; PC < end; ++PC)
+      if ((c = getlab(N_BSS)) != NULL)
+         {
+         if (PC > beg)
+            {
+            zdump(beg);
+            beg = PC;
+            }
+         printf("%s",c);
+         }
+
+   if (PC > beg)
+      zdump(beg);
+
+}/* * * * * * * * * * * END OF disbss() * * * * * * * * * * */
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This is the program  entry  point.  The command line is *
+  * searched for an input file name, which must be present. *
+  * An optional output file name is also permitted; if none *
+  * is found, standard output is the default.  One command- *
+  * line option is available:  "-o",  which causes the pro- *
+  * gram to include  object code in comments along with its *
+  * mnemonic output.                                        *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+main(argc,argv)
+
+   int argc;                  /* Command-line args from OS  */
+   register char **argv;
+
+{/* * * * * * * * * * * START OF main() * * * * * * * * * * */
+
+   char a[1024];
+   register int fd;
+   long taboff, tabnum;
+   long reloff, relnum;
+
+   PRG = invoker(*argv);
+
+   while (*++argv != NULL)    /* Process command-line args  */
+      if (**argv == '-')
+         switch (*++*argv)
+            {
+            case 'o' :
+               if (*++*argv)
+                  usage(PRG);
+               else
+                  ++objflg;
+               break;
+            default :
+               usage(PRG);
+            }
+      else
+         if (IFILE == NULL)
+            IFILE = *argv;
+         else if (OFILE == NULL)
+            OFILE = *argv;
+         else
+            usage(PRG);
+
+   if (IFILE == NULL)
+      usage(PRG);
+   else
+      if ((fd = open(IFILE,0)) < 0)
+         {
+         sprintf(a,"can't access input file %s",IFILE);
+         fatal(PRG,a);
+         }
+
+   if (OFILE != NULL)
+      if (freopen(OFILE,"w",stdout) == NULL)
+         {
+         sprintf(a,"can't open output file %s",OFILE);
+         fatal(PRG,a);
+         }
+
+   if ( ! cpuid )
+      fprintf(stderr,"\07%s: warning: host/cpu clash\n",PRG);
+
+   read(fd, (char *) &HDR,sizeof(struct exec));
+
+   if (BADMAG(HDR))
+      {
+      sprintf(a,"input file %s not in object format",IFILE);
+      fatal(PRG,a);
+      }
+
+   if (HDR.a_cpu != A_I8086)
+      {
+      sprintf(a,"%s is not an 8086/8088 object file",IFILE);
+      fatal(PRG,a);
+      }
+
+   if (HDR.a_hdrlen <= A_MINHDR)
+      HDR.a_trsize = HDR.a_drsize = 0L;
+      HDR.a_tbase = HDR.a_dbase = 0L;
+/*   AST emergency patch
+      HDR.a_lnums = HDR.a_toffs = 0L;
+*/
+
+   reloff = HDR.a_text        /* Compute reloc data offset  */
+          + HDR.a_data
+          + (long)(HDR.a_hdrlen);
+
+   relnum =
+      (HDR.a_trsize + HDR.a_drsize) / sizeof(struct reloc);
+
+   taboff = reloff            /* Compute name table offset  */
+          + HDR.a_trsize
+          + HDR.a_drsize;
+
+   tabnum = HDR.a_syms / sizeof(struct nlist);
+
+   if (relnum > MAXSYM)
+      fatal(PRG,"reloc table overflow");
+
+   if (tabnum > MAXSYM)
+      fatal(PRG,"symbol table overflow");
+
+   if (relnum)                            /* Get reloc data */
+      if (lseek(fd,reloff,0) != reloff)
+         fatal(PRG,"lseek error");
+      else
+         {
+         for (relptr = 0; relptr < relnum; ++relptr)
+            read(fd, (char *) &relo[relptr],sizeof(struct reloc));
+         relptr--;
+         }
+
+   if (tabnum)                            /* Read in symtab */
+      if (lseek(fd,taboff,0) != taboff)
+         fatal(PRG,"lseek error");
+      else
+         {
+         for (symptr = 0; symptr < tabnum; ++symptr)
+            read(fd, (char *) &symtab[symptr],sizeof(struct nlist));
+         symptr--;
+         }
+   else
+      fprintf(stderr,"\07%s: warning: no symbols\n",PRG);
+
+   close(fd);
+
+   if (freopen(IFILE,"r",stdin) == NULL)
+      {
+      sprintf(a,"can't reopen input file %s",IFILE);
+      fatal(PRG,a);
+      }
+
+   distext();
+
+   disdata();
+
+   disbss();
+
+   exit(0);
+
+}/* * * * * * * * * * *  END OF main()  * * * * * * * * * * */
Index: /trunk/minix/commands/dis88/disrel.c
===================================================================
--- /trunk/minix/commands/dis88/disrel.c	(revision 9)
+++ /trunk/minix/commands/dis88/disrel.c	(revision 9)
@@ -0,0 +1,30 @@
+static char *copyright =
+   "@(#) Copyright (C) 1987 G. M. Harding, all rights reserved";
+
+static char *sccsid =
+   "@(#) disrel.c, Ver. 2.1 created 00:00:00 87/09/01";
+
+char *release =
+   "release 2.1 (MINIX)";
+
+ /*
+ **
+ ** This file documents the major revisions to the 8088 sym-
+ ** bolic disassembler. It also contains the release string
+ ** which is output at the head of each disassembly, and the
+ ** copyright string which must be incorporated in any code
+ ** distribution.
+ **
+ ** Permission to copy and redistribute is hereby granted,
+ ** provided full source code, with all copyright notices,
+ ** accompanies any redistribution.
+ **
+ ** REVISION HISTORY:
+ **
+ ** SEP 87:
+ **    After internal shakeout, released on Usenet.
+ **
+ ** JUN 88:
+ **    Ported to MINIX
+ */
+
Index: /trunk/minix/commands/dis88/distabs.c
===================================================================
--- /trunk/minix/commands/dis88/distabs.c	(revision 9)
+++ /trunk/minix/commands/dis88/distabs.c	(revision 9)
@@ -0,0 +1,715 @@
+static char *sccsid =
+   "@(#) distabs.c, Ver. 2.1 created 00:00:00 87/09/01";
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  *  Copyright (C) 1987 G. M. Harding, all rights reserved  *
+  *                                                         *
+  * Permission to copy and  redistribute is hereby granted, *
+  * provided full source code,  with all copyright notices, *
+  * accompanies any redistribution.                         *
+  *                                                         *
+  * This file  contains  the  lookup  tables and other data *
+  * structures for the Intel 8088 symbolic disassembler. It *
+  * also contains a few global  routines  which  facilitate *
+  * access to the tables,  for use primarily by the handler *
+  * functions.                                              *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "dis.h"              /* Disassembler declarations  */
+
+struct exec HDR;              /* Used to hold header info   */
+
+struct nlist symtab[MAXSYM];  /* Array of symbol table info */
+
+struct reloc relo[MAXSYM];    /* Array of relocation info   */
+
+int symptr = -1,              /* Index into symtab[]        */
+    relptr = -1;              /* Index into relo[]          */
+
+char *REGS[] =                /* Table of register names    */
+   {
+   "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
+   "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
+   "es", "cs", "ss", "ds"
+   };
+
+char *REGS0[] =               /* Mode 0 register name table */
+   {
+   "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "", "bx"
+   };
+
+char *REGS1[] =               /* Mode 1 register name table */
+   {
+   "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "bp", "bx"
+   };
+
+int symrank[6][6] =           /* Symbol type/rank matrix    */
+   {
+              /* UND  ABS  TXT  DAT  BSS  COM */
+   /* UND */      5,   4,   1,   2,   3,   0,
+   /* ABS */      1,   5,   4,   3,   2,   0,
+   /* TXT */      4,   1,   5,   3,   2,   0,
+   /* DAT */      3,   1,   2,   5,   4,   0,
+   /* BSS */      3,   1,   2,   4,   5,   0,
+   /* COM */      2,   0,   1,   3,   4,   5
+   };
+
+
+ /* * * * * * * * * * * * OPCODE DATA * * * * * * * * * * * */
+
+char ADD[]   = "\tadd",             /* Mnemonics by family  */
+     OR[]    = "\tor",
+     ADC[]   = "\tadc",
+     SBB[]   = "\tsbb",
+     AND[]   = "\tand",
+     SUB[]   = "\tsub",
+     XOR[]   = "\txor",
+     CMP[]   = "\tcmp",
+     NOT[]   = "\tnot",
+     NEG[]   = "\tneg",
+     MUL[]   = "\tmul",
+     DIV[]   = "\tdiv",
+     MOV[]   = "\tmov",
+     ESC[]   = "\tesc",
+     TEST[]  = "\ttest",
+     AMBIG[] = "",
+     ROL[]   = "\trol",
+     ROR[]   = "\tror",
+     RCL[]   = "\trcl",
+     RCR[]   = "\trcr",
+     SAL[]   = "\tsal",
+     SHR[]   = "\tshr",
+     SHL[]   = "\tshl",
+     SAR[]   = "\tsar";
+
+char *OPFAM[] =                     /* Family lookup table  */
+   {
+   ADD, OR, ADC, SBB, AND, SUB, XOR, CMP,
+   NOT, NEG, MUL, DIV, MOV, ESC, TEST, AMBIG,
+   ROL, ROR, RCL, RCR, SAL, SHR, SHL, SAR
+   };
+
+struct opcode optab[] =             /* Table of opcode data */
+   {
+   ADD,              aohand,  2,    4,             /* 0x00  */
+   ADD,              aohand,  2,    4,             /* 0x01  */
+   ADD,              aohand,  2,    4,             /* 0x02  */
+   ADD,              aohand,  2,    4,             /* 0x03  */
+   ADD,              aohand,  2,    2,             /* 0x04  */
+   ADD,              aohand,  3,    3,             /* 0x05  */
+   "\tpush\tes",     sbhand,  1,    1,             /* 0x06  */
+   "\tpop\tes",      sbhand,  1,    1,             /* 0x07  */
+   OR,               aohand,  2,    4,             /* 0x08  */
+   OR,               aohand,  2,    4,             /* 0x09  */
+   OR,               aohand,  2,    4,             /* 0x0a  */
+   OR,               aohand,  2,    4,             /* 0x0b  */
+   OR,               aohand,  2,    2,             /* 0x0c  */
+   OR,               aohand,  3,    3,             /* 0x0d  */
+   "\tpush\tcs",     sbhand,  1,    1,             /* 0x0e  */
+   NULL,             dfhand,  0,    0,             /* 0x0f  */
+   ADC,              aohand,  2,    4,             /* 0x10  */
+   ADC,              aohand,  2,    4,             /* 0x11  */
+   ADC,              aohand,  2,    4,             /* 0x12  */
+   ADC,              aohand,  2,    4,             /* 0x13  */
+   ADC,              aohand,  2,    2,             /* 0x14  */
+   ADC,              aohand,  3,    3,             /* 0x15  */
+   "\tpush\tss",     sbhand,  1,    1,             /* 0x16  */
+   "\tpop\tss",      sbhand,  1,    1,             /* 0x17  */
+   SBB,              aohand,  2,    4,             /* 0x18  */
+   SBB,              aohand,  2,    4,             /* 0x19  */
+   SBB,              aohand,  2,    4,             /* 0x1a  */
+   SBB,              aohand,  2,    4,             /* 0x1b  */
+   SBB,              aohand,  2,    2,             /* 0x1c  */
+   SBB,              aohand,  3,    3,             /* 0x1d  */
+   "\tpush\tds",     sbhand,  1,    1,             /* 0x1e  */
+   "\tpop\tds",      sbhand,  1,    1,             /* 0x1f  */
+   AND,              aohand,  2,    4,             /* 0x20  */
+   AND,              aohand,  2,    4,             /* 0x21  */
+   AND,              aohand,  2,    4,             /* 0x22  */
+   AND,              aohand,  2,    4,             /* 0x23  */
+   AND,              aohand,  2,    2,             /* 0x24  */
+   AND,              aohand,  3,    3,             /* 0x25  */
+   "\tseg\tes",      sbhand,  1,    1,             /* 0x26  */
+   "\tdaa",          sbhand,  1,    1,             /* 0x27  */
+   SUB,              aohand,  2,    4,             /* 0x28  */
+   SUB,              aohand,  2,    4,             /* 0x29  */
+   SUB,              aohand,  2,    4,             /* 0x2a  */
+   SUB,              aohand,  2,    4,             /* 0x2b  */
+   SUB,              aohand,  2,    2,             /* 0x2c  */
+   SUB,              aohand,  3,    3,             /* 0x2d  */
+   "\tseg\tcs",      sbhand,  1,    1,             /* 0x2e  */
+   "\tdas",          sbhand,  1,    1,             /* 0x2f  */
+   XOR,              aohand,  2,    4,             /* 0x30  */
+   XOR,              aohand,  2,    4,             /* 0x31  */
+   XOR,              aohand,  2,    4,             /* 0x32  */
+   XOR,              aohand,  2,    4,             /* 0x33  */
+   XOR,              aohand,  2,    2,             /* 0x34  */
+   XOR,              aohand,  3,    3,             /* 0x35  */
+   "\tseg\tss",      sbhand,  1,    1,             /* 0x36  */
+   "\taaa",          sbhand,  1,    1,             /* 0x37  */
+   CMP,              aohand,  2,    4,             /* 0x38  */
+   CMP,              aohand,  2,    4,             /* 0x39  */
+   CMP,              aohand,  2,    4,             /* 0x3a  */
+   CMP,              aohand,  2,    4,             /* 0x3b  */
+   CMP,              aohand,  2,    2,             /* 0x3c  */
+   CMP,              aohand,  3,    3,             /* 0x3d  */
+   "\tseg\tds",      sbhand,  1,    1,             /* 0x3e  */
+   "\taas",          sbhand,  1,    1,             /* 0x3f  */
+   "\tinc\tax",      sbhand,  1,    1,             /* 0x40  */
+   "\tinc\tcx",      sbhand,  1,    1,             /* 0x41  */
+   "\tinc\tdx",      sbhand,  1,    1,             /* 0x42  */
+   "\tinc\tbx",      sbhand,  1,    1,             /* 0x43  */
+   "\tinc\tsp",      sbhand,  1,    1,             /* 0x44  */
+   "\tinc\tbp",      sbhand,  1,    1,             /* 0x45  */
+   "\tinc\tsi",      sbhand,  1,    1,             /* 0x46  */
+   "\tinc\tdi",      sbhand,  1,    1,             /* 0x47  */
+   "\tdec\tax",      sbhand,  1,    1,             /* 0x48  */
+   "\tdec\tcx",      sbhand,  1,    1,             /* 0x49  */
+   "\tdec\tdx",      sbhand,  1,    1,             /* 0x4a  */
+   "\tdec\tbx",      sbhand,  1,    1,             /* 0x4b  */
+   "\tdec\tsp",      sbhand,  1,    1,             /* 0x4c  */
+   "\tdec\tbp",      sbhand,  1,    1,             /* 0x4d  */
+   "\tdec\tsi",      sbhand,  1,    1,             /* 0x4e  */
+   "\tdec\tdi",      sbhand,  1,    1,             /* 0x4f  */
+   "\tpush\tax",     sbhand,  1,    1,             /* 0x50  */
+   "\tpush\tcx",     sbhand,  1,    1,             /* 0x51  */
+   "\tpush\tdx",     sbhand,  1,    1,             /* 0x52  */
+   "\tpush\tbx",     sbhand,  1,    1,             /* 0x53  */
+   "\tpush\tsp",     sbhand,  1,    1,             /* 0x54  */
+   "\tpush\tbp",     sbhand,  1,    1,             /* 0x55  */
+   "\tpush\tsi",     sbhand,  1,    1,             /* 0x56  */
+   "\tpush\tdi",     sbhand,  1,    1,             /* 0x57  */
+   "\tpop\tax",      sbhand,  1,    1,             /* 0x58  */
+   "\tpop\tcx",      sbhand,  1,    1,             /* 0x59  */
+   "\tpop\tdx",      sbhand,  1,    1,             /* 0x5a  */
+   "\tpop\tbx",      sbhand,  1,    1,             /* 0x5b  */
+   "\tpop\tsp",      sbhand,  1,    1,             /* 0x5c  */
+   "\tpop\tbp",      sbhand,  1,    1,             /* 0x5d  */
+   "\tpop\tsi",      sbhand,  1,    1,             /* 0x5e  */
+   "\tpop\tdi",      sbhand,  1,    1,             /* 0x5f  */
+   NULL,             dfhand,  0,    0,             /* 0x60  */
+   NULL,             dfhand,  0,    0,             /* 0x61  */
+   NULL,             dfhand,  0,    0,             /* 0x62  */
+   NULL,             dfhand,  0,    0,             /* 0x63  */
+   NULL,             dfhand,  0,    0,             /* 0x64  */
+   NULL,             dfhand,  0,    0,             /* 0x65  */
+   NULL,             dfhand,  0,    0,             /* 0x66  */
+   NULL,             dfhand,  0,    0,             /* 0x67  */
+   NULL,             dfhand,  0,    0,             /* 0x68  */
+   NULL,             dfhand,  0,    0,             /* 0x69  */
+   NULL,             dfhand,  0,    0,             /* 0x6a  */
+   NULL,             dfhand,  0,    0,             /* 0x6b  */
+   NULL,             dfhand,  0,    0,             /* 0x6c  */
+   NULL,             dfhand,  0,    0,             /* 0x6d  */
+   NULL,             dfhand,  0,    0,             /* 0x6e  */
+   NULL,             dfhand,  0,    0,             /* 0x6f  */
+   "\tjo",           sjhand,  2,    2,             /* 0x70  */
+   "\tjno",          sjhand,  2,    2,             /* 0x71  */
+   "\tjc",           sjhand,  2,    2,             /* 0x72  */
+   "\tjnc",          sjhand,  2,    2,             /* 0x73  */
+   "\tjz",           sjhand,  2,    2,             /* 0x74  */
+   "\tjnz",          sjhand,  2,    2,             /* 0x75  */
+   "\tjna",          sjhand,  2,    2,             /* 0x76  */
+   "\tja",           sjhand,  2,    2,             /* 0x77  */
+   "\tjs",           sjhand,  2,    2,             /* 0x78  */
+   "\tjns",          sjhand,  2,    2,             /* 0x79  */
+   "\tjp",           sjhand,  2,    2,             /* 0x7a  */
+   "\tjnp",          sjhand,  2,    2,             /* 0x7b  */
+   "\tjl",           sjhand,  2,    2,             /* 0x7c  */
+   "\tjnl",          sjhand,  2,    2,             /* 0x7d  */
+   "\tjng",          sjhand,  2,    2,             /* 0x7e  */
+   "\tjg",           sjhand,  2,    2,             /* 0x7f  */
+   AMBIG,            imhand,  3,    5,             /* 0x80  */
+   AMBIG,            imhand,  4,    6,             /* 0x81  */
+   AMBIG,            imhand,  3,    5,             /* 0x82  */
+   AMBIG,            imhand,  3,    5,             /* 0x83  */
+   TEST,             mvhand,  2,    4,             /* 0x84  */
+   TEST,             mvhand,  2,    4,             /* 0x85  */
+   "\txchg",         mvhand,  2,    4,             /* 0x86  */
+   "\txchg",         mvhand,  2,    4,             /* 0x87  */
+   MOV,              mvhand,  2,    4,             /* 0x88  */
+   MOV,              mvhand,  2,    4,             /* 0x89  */
+   MOV,              mvhand,  2,    4,             /* 0x8a  */
+   MOV,              mvhand,  2,    4,             /* 0x8b  */
+   MOV,              mshand,  2,    4,             /* 0x8c  */
+   "\tlea",          mvhand,  2,    4,             /* 0x8d  */
+   MOV,              mshand,  2,    4,             /* 0x8e  */
+   "\tpop",          pohand,  2,    4,             /* 0x8f  */
+   "\tnop",          sbhand,  1,    1,             /* 0x90  */
+   "\txchg\tax,cx",  sbhand,  1,    1,             /* 0x91  */
+   "\txchg\tax,dx",  sbhand,  1,    1,             /* 0x92  */
+   "\txchg\tax,bx",  sbhand,  1,    1,             /* 0x93  */
+   "\txchg\tax,sp",  sbhand,  1,    1,             /* 0x94  */
+   "\txchg\tax,bp",  sbhand,  1,    1,             /* 0x95  */
+   "\txchg\tax,si",  sbhand,  1,    1,             /* 0x96  */
+   "\txchg\tax,di",  sbhand,  1,    1,             /* 0x97  */
+   "\tcbw",          sbhand,  1,    1,             /* 0x98  */
+   "\tcwd",          sbhand,  1,    1,             /* 0x99  */
+   "\tcalli",        cihand,  5,    5,             /* 0x9a  */
+   "\twait",         sbhand,  1,    1,             /* 0x9b  */
+   "\tpushf",        sbhand,  1,    1,             /* 0x9c  */
+   "\tpopf",         sbhand,  1,    1,             /* 0x9d  */
+   "\tsahf",         sbhand,  1,    1,             /* 0x9e  */
+   "\tlahf",         sbhand,  1,    1,             /* 0x9f  */
+   MOV,              mqhand,  3,    3,             /* 0xa0  */
+   MOV,              mqhand,  3,    3,             /* 0xa1  */
+   MOV,              mqhand,  3,    3,             /* 0xa2  */
+   MOV,              mqhand,  3,    3,             /* 0xa3  */
+   "\tmovb",         sbhand,  1,    1,             /* 0xa4  */
+   "\tmovw",         sbhand,  1,    1,             /* 0xa5  */
+   "\tcmpb",         sbhand,  1,    1,             /* 0xa6  */
+   "\tcmpw",         sbhand,  1,    1,             /* 0xa7  */
+   TEST,             tqhand,  2,    2,             /* 0xa8  */
+   TEST,             tqhand,  3,    3,             /* 0xa9  */
+   "\tstob",         sbhand,  1,    1,             /* 0xaa  */
+   "\tstow",         sbhand,  1,    1,             /* 0xab  */
+   "\tlodb",         sbhand,  1,    1,             /* 0xac  */
+   "\tlodw",         sbhand,  1,    1,             /* 0xad  */
+   "\tscab",         sbhand,  1,    1,             /* 0xae  */
+   "\tscaw",         sbhand,  1,    1,             /* 0xaf  */
+   "\tmov\tal,",     mihand,  2,    2,             /* 0xb0  */
+   "\tmov\tcl,",     mihand,  2,    2,             /* 0xb1  */
+   "\tmov\tdl,",     mihand,  2,    2,             /* 0xb2  */
+   "\tmov\tbl,",     mihand,  2,    2,             /* 0xb3  */
+   "\tmov\tah,",     mihand,  2,    2,             /* 0xb4  */
+   "\tmov\tch,",     mihand,  2,    2,             /* 0xb5  */
+   "\tmov\tdh,",     mihand,  2,    2,             /* 0xb6  */
+   "\tmov\tbh,",     mihand,  2,    2,             /* 0xb7  */
+   "\tmov\tax,",     mihand,  3,    3,             /* 0xb8  */
+   "\tmov\tcx,",     mihand,  3,    3,             /* 0xb9  */
+   "\tmov\tdx,",     mihand,  3,    3,             /* 0xba  */
+   "\tmov\tbx,",     mihand,  3,    3,             /* 0xbb  */
+   "\tmov\tsp,",     mihand,  3,    3,             /* 0xbc  */
+   "\tmov\tbp,",     mihand,  3,    3,             /* 0xbd  */
+   "\tmov\tsi,",     mihand,  3,    3,             /* 0xbe  */
+   "\tmov\tdi,",     mihand,  3,    3,             /* 0xbf  */
+   NULL,             dfhand,  0,    0,             /* 0xc0  */
+   NULL,             dfhand,  0,    0,             /* 0xc1  */
+   "\tret",          rehand,  3,    3,             /* 0xc2  */
+   "\tret",          sbhand,  1,    1,             /* 0xc3  */
+   "\tles",          mvhand,  2,    4,             /* 0xc4  */
+   "\tlds",          mvhand,  2,    4,             /* 0xc5  */
+   MOV,              mmhand,  3,    5,             /* 0xc6  */
+   MOV,              mmhand,  4,    6,             /* 0xc7  */
+   NULL,             dfhand,  0,    0,             /* 0xc8  */
+   NULL,             dfhand,  0,    0,             /* 0xc9  */
+   "\treti",         rehand,  3,    3,             /* 0xca  */
+   "\treti",         sbhand,  1,    1,             /* 0xcb  */
+   "\tint",          sbhand,  1,    1,             /* 0xcc  */
+   "\tint",          inhand,  2,    2,             /* 0xcd  */
+   "\tinto",         sbhand,  1,    1,             /* 0xce  */
+   "\tiret",         sbhand,  1,    1,             /* 0xcf  */
+   AMBIG,            srhand,  2,    4,             /* 0xd0  */
+   AMBIG,            srhand,  2,    4,             /* 0xd1  */
+   AMBIG,            srhand,  2,    4,             /* 0xd2  */
+   AMBIG,            srhand,  2,    4,             /* 0xd3  */
+   "\taam",          aahand,  2,    2,             /* 0xd4  */
+   "\taad",          aahand,  2,    2,             /* 0xd5  */
+   NULL,             dfhand,  0,    0,             /* 0xd6  */
+   "\txlat",         sbhand,  1,    1,             /* 0xd7  */
+   ESC,              eshand,  2,    2,             /* 0xd8  */
+   ESC,              eshand,  2,    2,             /* 0xd9  */
+   ESC,              eshand,  2,    2,             /* 0xda  */
+   ESC,              eshand,  2,    2,             /* 0xdb  */
+   ESC,              eshand,  2,    2,             /* 0xdc  */
+   ESC,              eshand,  2,    2,             /* 0xdd  */
+   ESC,              eshand,  2,    2,             /* 0xde  */
+   ESC,              eshand,  2,    2,             /* 0xdf  */
+   "\tloopne",       sjhand,  2,    2,             /* 0xe0  */
+   "\tloope",        sjhand,  2,    2,             /* 0xe1  */
+   "\tloop",         sjhand,  2,    2,             /* 0xe2  */
+   "\tjcxz",         sjhand,  2,    2,             /* 0xe3  */
+   "\tin",           iohand,  2,    2,             /* 0xe4  */
+   "\tinw",          iohand,  2,    2,             /* 0xe5  */
+   "\tout",          iohand,  2,    2,             /* 0xe6  */
+   "\toutw",         iohand,  2,    2,             /* 0xe7  */
+   "\tcall",         ljhand,  3,    3,             /* 0xe8  */
+   "\tjmp",          ljhand,  3,    3,             /* 0xe9  */
+   "\tjmpi",         cihand,  5,    5,             /* 0xea  */
+   "\tj",            sjhand,  2,    2,             /* 0xeb  */
+   "\tin",           sbhand,  1,    1,             /* 0xec  */
+   "\tinw",          sbhand,  1,    1,             /* 0xed  */
+   "\tout",          sbhand,  1,    1,             /* 0xee  */
+   "\toutw",         sbhand,  1,    1,             /* 0xef  */
+   "\tlock",         sbhand,  1,    1,             /* 0xf0  */
+   NULL,             dfhand,  0,    0,             /* 0xf1  */
+   "\trepnz",        sbhand,  1,    1,             /* 0xf2  */
+   "\trepz",         sbhand,  1,    1,             /* 0xf3  */
+   "\thlt",          sbhand,  1,    1,             /* 0xf4  */
+   "\tcmc",          sbhand,  1,    1,             /* 0xf5  */
+   AMBIG,            mahand,  2,    5,             /* 0xf6  */
+   AMBIG,            mahand,  2,    6,             /* 0xf7  */
+   "\tclc",          sbhand,  1,    1,             /* 0xf8  */
+   "\tstc",          sbhand,  1,    1,             /* 0xf9  */
+   "\tcli",          sbhand,  1,    1,             /* 0xfa  */
+   "\tsti",          sbhand,  1,    1,             /* 0xfb  */
+   "\tcld",          sbhand,  1,    1,             /* 0xfc  */
+   "\tstd",          sbhand,  1,    1,             /* 0xfd  */
+   AMBIG,            mjhand,  2,    4,             /* 0xfe  */
+   AMBIG,            mjhand,  2,    4              /* 0xff  */
+   };
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This simple routine  returns the name field of a symbol *
+  * table entry as a printable string.                      *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+char *
+getnam(k)
+
+   register int k;
+
+{/* * * * * * * * * *  START OF getnam()  * * * * * * * * * */
+
+   register int j;
+   static char a[9];
+
+   for (j = 0; j < 8; ++j)
+      if ( ! symtab[k].n_name[j] )
+         break;
+      else
+         a[j] = symtab[k].n_name[j];
+
+   a[j] = '\0';
+
+   return (a);
+
+}/* * * * * * * * * * * END OF getnam() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This function is  responsible  for mucking  through the *
+  * relocation  table in  search of  externally  referenced *
+  * symbols to be output as  operands.  It accepts two long *
+  * arguments: the code-segment location at which an extern *
+  * reference  is  expected,  and the offset value which is *
+  * embedded  in the  object  code and used at link time to *
+  * bias the external value.  In the most typical case, the *
+  * function will be called by lookup(), which always makes *
+  * a check for external names before  searching the symbol *
+  * table proper.  However,  it may also be called directly *
+  * by any function  (such as the  move-immediate  handler) *
+  * which wants to make an independent check for externals. *
+  * The caller is expected to supply, as the third argument *
+  * to the function,  a pointer to a character buffer large *
+  * enough to hold any possible  output  string.  Lookext() *
+  * will fill this  buffer and return a logical  TRUE if it *
+  * finds an extern reference;  otherwise, it will return a *
+  * logical FALSE, leaving the buffer undisturbed.          *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+int
+lookext(off,loc,buf)
+
+   long off, loc;
+   char *buf;
+
+{/* * * * * * * * * * START OF  lookext() * * * * * * * * * */
+
+   register int k;
+   char c[16];
+
+   if ((loc != -1L) && (relptr >= 0))
+      for (k = 0; k <= relptr; ++k)
+         if ((relo[k].r_vaddr == loc)
+          && (relo[k].r_symndx < S_BSS))
+            {
+            strcpy(buf,getnam(relo[k].r_symndx));
+            if (off)
+               {
+               if (off < 0)
+                  sprintf(c,"%ld",off);
+               else
+                  sprintf(c,"+%ld",off);
+               strcat(buf,c);
+               }
+            return (1);
+            }
+
+   return (0);
+
+}/* * * * * * * * * *  END OF  lookext()  * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This  function  finds an entry in the  symbol  table by *
+  * value.  Its input is a (long) machine address,  and its *
+  * output is a pointer to a string  containing  the corre- *
+  * sponding symbolic name. The function first searches the *
+  * relocation table for a possible external reference;  if *
+  * none is found,  a linear  search of the symbol table is *
+  * undertaken. If no matching symbol has been found at the *
+  * end of these searches,  the function  returns a pointer *
+  * to a string  containing the ASCII equivalent of the ad- *
+  * dress which was to be located,  so that,  regardless of *
+  * the success of the search,  the function's return value *
+  * is suitable for use as a memory-reference operand.  The *
+  * caller specifies the type of symbol to be found  (text, *
+  * data, bss, undefined,  absolute, or common) by means of *
+  * the function's  second  parameter.  The third parameter *
+  * specifies  the  format to be used in the event of a nu- *
+  * meric output:  zero for absolute format,  one for short *
+  * relative  format,  two for long  relative  format.  The *
+  * fourth  parameter is the address  which would appear in *
+  * the relocation table for the reference in question,  or *
+  * -1 if the relocation  table is not to be searched.  The *
+  * function attempts to apply a certain amount of intelli- *
+  * gence in its  selection  of symbols,  so it is possible *
+  * that,  in the absence of a type match,  a symbol of the *
+  * correct value but different type will be returned.      *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+char *
+lookup(addr,type,kind,ext)
+
+   long addr;              /* Machine address to be located */
+
+   int type,               /* Type of symbol to be matched  */
+       kind;               /* Addressing output mode to use */
+
+   long ext;               /* Value for extern ref, if any  */
+
+{/* * * * * * * * * *  START OF lookup()  * * * * * * * * * */
+
+   register int j, k;
+   static char b[64];
+
+   struct
+      {
+      int   i;
+      int   t;
+      }
+   best;
+
+   if (lookext(addr,ext,b))
+      return (b);
+
+   if (segflg)
+      if (segflg & 1)
+         type = N_TEXT;
+      else
+         type = N_DATA;
+
+   for (k = 0, best.i = -1; k <= symptr; ++k)
+      if (symtab[k].n_value == addr)
+         if ((j = symtab[k].n_sclass & N_SECT) == type)
+            {
+            best.t = j;
+            best.i = k;
+            break;
+            }
+         else if (segflg || (HDR.a_flags & A_SEP))
+            continue;
+         else if (best.i < 0)
+            best.t = j, best.i = k;
+         else if (symrank[type][j] > symrank[type][best.t])
+            best.t = j, best.i = k;
+
+   if (best.i >= 0)
+      return (getnam(best.i));
+
+   if (kind == LOOK_ABS)
+      sprintf(b,"0x%05.5x",addr);
+   else
+      {
+      long x = addr - (PC - kind);
+      if (x < 0)
+         sprintf(b,".%ld",x);
+      else
+         sprintf(b,".+%ld",x);
+      }
+
+   return (b);
+
+}/* * * * * * * * * * * END OF lookup() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This function  translates an 8088  addressing mode byte *
+  * to an equivalent assembler string,  returning a pointer *
+  * thereto.  If necessary,  it performs  successive inputs *
+  * of bytes from the object file in order to obtain offset *
+  * data,  adjusting PC  accordingly.  (The addressing mode *
+  * byte  appears in several  8088  opcodes;  it is used to *
+  * specify source and destination operand locations.)  The *
+  * third  argument to the function is zero if the standard *
+  * registers are to be used,  or eight if the segment reg- *
+  * isters are to be used; these constants are defined sym- *
+  * bolically in dis.h.  NOTE:  The mtrans()  function must *
+  * NEVER be called except  immediately  after fetching the *
+  * mode byte.  If any additional  object bytes are fetched *
+  * after  the fetch of the mode  byte,  mtrans()  will not *
+  * produce correct output!                                 *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+char *
+mtrans(c,m,type)
+
+   register int c;            /* Primary instruction byte   */
+   register int m;            /* Addressing mode byte       */
+
+   int type;                  /* Type code: standard or seg */
+
+{/* * * * * * * * * *  START OF mtrans()  * * * * * * * * * */
+
+   unsigned long pc;
+   int offset, oflag, dir, w, mod, reg, rm;
+   static char a[100];
+   static char b[30];
+
+   offset = 0;
+   dir = c & 2;
+   w = c & 1;
+   mod = (m & 0xc0) >> 6;
+   reg = (m & 0x38) >> 3;
+   rm = m & 7;
+   pc = PC + 1;
+
+   if (type)
+      w = 1;
+
+   if ((oflag = mod) > 2)
+      oflag = 0;
+
+   if (oflag)
+      {
+      int j, k;
+      if (oflag == 2)
+         {
+         FETCH(j);
+         FETCH(k);
+         offset = (k << 8) | j;
+         }
+      else
+         {
+         FETCH(j);
+         if (j & 0x80)
+            k = 0xff00;
+         else
+            k = 0;
+         offset = k | j;
+         }
+      }
+
+   if (dir)
+      {
+      strcpy(a,REGS[type + ((w << 3) | reg)]);
+      strcat(a,",");
+      switch (mod)
+         {
+         case 0 :
+            if (rm == 6)
+               {
+               int j, k;
+               FETCH(j);
+               FETCH(k);
+               offset = (k << 8) | j;
+               strcat(a,
+                lookup((long)(offset),N_DATA,LOOK_ABS,pc));
+               }
+            else
+               {
+               sprintf(b,"(%s)",REGS0[rm]);
+               strcat(a,b);
+               }
+            break;
+         case 1 :
+         case 2 :
+            if (mod == 1)
+               strcat(a,"*");
+            else
+               strcat(a,"#");
+            sprintf(b,"%d(",offset);
+            strcat(a,b);
+            strcat(a,REGS1[rm]);
+            strcat(a,")");
+            break;
+         case 3 :
+            strcat(a,REGS[(w << 3) | rm]);
+            break;
+         }
+      }
+   else
+      {
+      switch (mod)
+         {
+         case 0 :
+            if (rm == 6)
+               {
+               int j, k;
+               FETCH(j);
+               FETCH(k);
+               offset = (k << 8) | j;
+               strcpy(a,
+                lookup((long)(offset),N_DATA,LOOK_ABS,pc));
+               }
+            else
+               {
+               sprintf(b,"(%s)",REGS0[rm]);
+               strcpy(a,b);
+               }
+            break;
+         case 1 :
+         case 2 :
+            if (mod == 1)
+               strcpy(a,"*");
+            else
+               strcpy(a,"#");
+            sprintf(b,"%d(",offset);
+            strcat(a,b);
+            strcat(a,REGS1[rm]);
+            strcat(a,")");
+            break;
+         case 3 :
+            strcpy(a,REGS[(w << 3) | rm]);
+            break;
+         }
+      strcat(a,",");
+      strcat(a,REGS[type + ((w << 3) | reg)]);
+      }
+
+   return (a);
+
+}/* * * * * * * * * * * END OF mtrans() * * * * * * * * * * */
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  *                                                         *
+  * This simple routine  truncates a string returned by the *
+  * mtrans() function, removing its source operand. This is *
+  * useful in handlers which ignore the "reg"  field of the *
+  * mode byte.                                              *
+  *                                                         *
+  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+mtrunc(a)
+
+   register char *a;          /* Ptr. to string to truncate */
+
+{/* * * * * * * * * *  START OF mtrunc()  * * * * * * * * * */
+
+   register int k;
+
+   for (k = strlen(a) - 1; k >= 0; --k)
+      if (a[k] == ',')
+         {
+         a[k] = '\0';
+         break;
+         }
+
+}/* * * * * * * * * * * END OF mtrunc() * * * * * * * * * * */
+
+
+
Index: /trunk/minix/commands/elle/Makefile
===================================================================
--- /trunk/minix/commands/elle/Makefile	(revision 9)
+++ /trunk/minix/commands/elle/Makefile	(revision 9)
@@ -0,0 +1,57 @@
+# Makefile for elle
+
+CC = exec cc
+CFLAGS = -O -DIGN_JOB_CONTROL -D_POSIX_SOURCE -wa
+LDFLAGS= -i
+
+all:	elle ellec
+
+OBJ = eemain.o eecmds.o eesite.o eevini.o eedisp.o eeterm.o eeerr.o  \
+      eeques.o eebuff.o eefile.o eefed.o eeedit.o eebit.o eef1.o \
+      eef2.o eefd.o eehelp.o eekmac.o eef3.o eesrch.o eequer.o \
+      eefill.o eediag.o sbstr.o sbm.o sberr.o sbbcpy.o
+
+# It probably isn't necessary to make all this stuff all the time, but it
+# is fairly easy and makes the whole process simpler.  If this is not done,
+# the dependencies are very complicated because some of the .c and .h files
+# are made dynamically.
+elle:	ellec $(OBJ) $(FUN_OFILES) elle.h eesite.h
+#	$(CC) $(CFLAGS) -c defprf.c	# depends on the new *.h files
+	$(CC) $(LDFLAGS) -o $@ $(OBJ)
+	install -S 64k $@
+
+defprf.c:	deffun.e
+	cat deffun.e defprf.e | ellec -Pconf  > defprf.c
+
+eefdef.h:	deffun.e
+	cat deffun.e defprf.e | ellec -Fconf  > eefdef.h
+
+eefidx.h:	deffun.e
+	cat deffun.e defprf.e | ellec -FXconf > eefidx.h
+
+# Don't flush these files if interrupted, dammit!
+.PRECIOUS: ellec deffun.e defprf.e
+
+# The following files must be recompiled if eefidx.h is changed
+eecmds.o eebuff.o eeerr.o eehelp.o eejust.o eemain.o eeques.o eef1.o: eefidx.h
+
+# ELLE profile compiler.  
+#	Although eefdef.h and defprf.c are included by ELLEC, they
+#	are not listed as dependencies in order to avoid loops (see
+#	their target entries).  That is OK because their information is not
+#	used when generating the makecf files; it only furnishes default
+#	values needed when an ELLE user compiles a user profile.
+ellec: ellec.c
+	$(CC) $(LDFLAGS) $(CFLAGS) -o $@ ellec.c
+	install -S 8kw $@
+
+install:	/usr/bin/elle /usr/bin/ellec
+
+/usr/bin/elle:	elle
+	install -cs -o bin elle $@
+
+/usr/bin/ellec:	ellec
+	install -cs -o bin ellec $@
+
+clean:	
+	rm -f *.o *.bak core elle ellec
Index: /trunk/minix/commands/elle/build
===================================================================
--- /trunk/minix/commands/elle/build	(revision 9)
+++ /trunk/minix/commands/elle/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/elle/deffun.e
===================================================================
--- /trunk/minix/commands/elle/deffun.e	(revision 9)
+++ /trunk/minix/commands/elle/deffun.e	(revision 9)
@@ -0,0 +1,201 @@
+;;;
+;;; ELLE Master Function Definition file - "deffun.e"
+;;;
+;;;	This file serves as input to the ellec program.  It defines
+;;; all ELLE functions which may serve as keyboard-bound user commands.
+;;;
+;;; Format: (efun <Index> <Name> <Routine> <Module>)
+;;;		Index - an unique index # (used only within ELLE)
+;;;		Name - an unique string identifying this function to the user.
+;;;		Routine - the C routine implementing the function within ELLE.
+;;;		Module - the name of the C source file that the routine is in.
+;;;
+;;; The following definitions are roughly organized by object.
+;;; All functions that emulate EMACS functions are given names identical
+;;; to the EMACS function names.  For historical reasons these names
+;;; are not as consistent as they could be (sigh).
+;;; Those which have no exact counterpart in EMACS are identified by comments.
+
+(undefall)	; Ensure all predefined stuff is cleared out.
+
+; Simple Insertion
+(efun   1 "Insert Self"		f_insself	eef1)
+(efun   2 "Quoted Insert"	f_quotins	eef1)
+(efun   3 "CRLF"		f_crlf		eef1)
+
+; Characters
+(efun   4 "Forward Character"	f_fchar		eef1)
+(efun   5 "Backward Character"	f_bchar		eef1)
+(efun   6 "Delete Character"	f_dchar		eef1)
+(efun   7 "Backward Delete Character" f_bdchar	eef1)
+(efun   8 "Delete Horizontal Space" f_delspc	eef1)
+(efun   9 "Transpose Characters" f_tchars	eef1)
+
+; Words
+(efun  10 "Forward Word"	f_fword		eef1)
+(efun  11 "Backward Word"	f_bword		eef1)
+(efun  12 "Kill Word"		f_kword		eef1)
+(efun  13 "Backward Kill Word"	f_bkword	eef1)
+(efun  14 "Transpose Words"	f_twords	eef1)
+(efun  15 "Uppercase Word"	f_ucword	eef1)
+(efun  16 "Lowercase Word"	f_lcword	eef1)
+(efun  17 "Uppercase Initial"	f_uciword	eef1)
+     ; 18-19 reserved
+
+; Lines
+(efun  20 "Beginning of Line"	f_begline	eef2)
+(efun  21 "End of Line"		f_endline	eef2)
+(efun  22 "Next Line"		f_nxtline	eef2)
+(efun  23 "Previous Line"	f_prvline	eef2)
+(efun  24 "Down Real Line"	f_dnrline	eef2)
+(efun  25 "Up Real Line"	f_uprline	eef2)
+(efun  26 "Open Line"		f_oline		eef2)
+(efun  27 "Delete Blank Lines"	f_delblines	eef2)
+(efun  28 "Kill Line"		f_kline		eef2)
+(efun  29 "Backward Kill Line"	f_bkline	eef2)	; not EMACS
+(efun  30 "Goto Line"		f_goline	eef2)	; not EMACS
+     ; 31-34 reserved
+
+; Regions
+(efun  35 "Set/Pop Mark"	f_setmark	eef2)
+(efun  36 "Exchange Point and Mark" f_exchmark	eef2)
+(efun  37 "Kill Region"		f_kregion	eef2)
+(efun  38 "Copy Region"		f_copreg	eef2)
+(efun  39 "Uppercase Region"	f_ucreg		eef2)
+(efun  40 "Lowercase Region"	f_lcreg		eef2)
+(efun  41 "Fill Region"		f_fillreg	eef2)
+     ; 42-44 reserved
+
+; Paragraphs
+(efun  45 "Forward Paragraph"	f_fpara		eef2)
+(efun  46 "Backward Paragraph"	f_bpara		eef2)
+(efun  47 "Mark Paragraph"	f_mrkpara	eef2)
+(efun  48 "Fill Paragraph"	f_fillpara	eef2)
+     ; 49 reserved
+
+; Buffers
+(efun  50 "Select Buffer"	f_selbuffer	eebuff)
+(efun  51 "Select Existing Buffer" f_selxbuffer	eebuff)	; not EMACS
+(efun  52 "Kill Buffer"		f_kbuffer	eebuff)
+(efun  53 "List Buffers"	f_listbufs	eebuff)
+(efun  54 "Buffer Not Modified"	f_bufnotmod	eebuff)
+(efun  55 "EOL CRLF Mode"	f_eolmode	eebuff)	; ELLE
+(efun  56 "Goto Beginning"	f_gobeg		eebuff)
+(efun  57 "Goto End"		f_goend		eebuff)
+(efun  58 "What Page"		f_whatpage	eebuff)
+     ; 59 reserved
+
+; Files
+(efun  60 "Find File"		f_ffile		eefile)
+(efun  61 "Read File"		f_rfile		eefile)
+(efun  62 "Visit File"		f_vfile		eefile)
+(efun  63 "Insert File"		f_ifile		eefile)
+(efun  64 "Save File"		f_sfile		eefile)
+(efun  65 "Save All Files"	f_savefiles	eebuff)
+(efun  66 "Write File"		f_wfile		eefile)
+(efun  67 "Write Region"	f_wreg		eefile)
+(efun  68 "Write Last Kill"	f_wlastkill	eefile)	; not EMACS
+     ; 69 reserved
+
+; Windows
+(efun  70 "Two Windows"		f_2winds	eebuff)
+(efun  71 "One Window"		f_1wind		eebuff)
+(efun  72 "Other Window"	f_othwind	eebuff)
+(efun  73 "Grow Window"		f_growind	eebuff)
+(efun  74 "Shrink Window"	f_shrinkwind	eebuff)	; not EMACS	
+(efun  75 "Delete Window"	f_delwind	eebuff)	; not EMACS
+(efun  76 "Standout Window"	f_sowind	eebuff)	; ELLE
+(efun  77 "Two Mode Windows"	f_2modewinds	eebuff)	; ELLE
+
+; Window Positioning
+(efun  78 "New Window"		f_newwin	eefd)
+(efun  79 "Next Screen"		f_nscreen	eefd)
+(efun  80 "Previous Screen"	f_pscreen	eefd)
+(efun  81 "Other New Screen"	f_othnscreen	eefd)	; not EMACS
+(efun  82 "Line to Window Border" f_lwindbord	eefd)	; not EMACS
+(efun  83 "Scroll Window Up"	f_scupwind	eefd)	; not EMACS
+(efun  84 "Scroll Window Down"	f_scdnwind	eefd)	; not EMACS
+(efun  85 "Move to Window Top"	f_mvwtop	eefd)	; not EMACS
+(efun  86 "Move to Window Bottom" f_mvwbot	eefd)	; not EMACS
+     ; 87-89 reserved
+
+; Command Input
+(efun  90 "Set Profile"		f_setprof	eecmds)	; ELLE
+(efun  91 "Prefix Meta"		f_pfxmeta	eecmds)
+(efun  92 "Prefix Extend"	f_pfxext	eecmds)
+(efun  93 "Universal Arg"	f_uarg		eecmds)
+(efun  94 "Negative Argument"	f_negarg	eecmds)
+(efun  95 "Argument Digit"	f_argdig	eecmds)
+(efun  96 "VT100 Button Hack"	f_vtbuttons	eecmds)	; not EMACS
+
+; Help
+(efun  97 "Describe"		f_describe	eehelp)
+     ; 98-99 reserved
+
+; Keyboard Macros
+(efun 100 "Start Kbd Macro"	f_skmac		eekmac)
+(efun 101 "End Kbd Macro"	f_ekmac		eekmac)
+(efun 102 "Execute Kbd Macro"	f_xkmac		eekmac)
+(efun 103 "View Kbd Macro"	f_vkmac		eekmac)
+    ; 104 reserved
+
+; Killing
+(efun 105 "Un-kill"		f_unkill	eef3)
+(efun 106 "Un-kill Pop"		f_unkpop	eef3)
+(efun 107 "Append Next Kill"	f_appnkill	eef3)
+    ; 108-109 reserved
+
+; Searching
+(efun 110 "String Search"	f_srch		eesrch)
+(efun 111 "Reverse String Search" f_rsrch	eesrch)
+(efun 112 "Incremental Search"	f_isrch		eesrch)
+(efun 113 "Reverse Search"	f_risrch	eesrch)
+
+; Query Replace & friends
+(efun 114 "Replace String"	f_repstr	eequer)
+(efun 115 "Query Replace"	f_querep	eequer)
+(efun 116 "Replace in Line"	f_repline	eequer)	; not EMACS
+
+; Fill Mode
+(efun 117 "Set Fill Column"	f_sfcol		eefill)
+(efun 118 "Set Fill Prefix"	f_sfpref	eefill)
+(efun 119 "Auto Fill Mode"	f_fillmode	eefill)
+(efun 120 "Text Mode"		f_textmode	eefill)	; IMAGEN
+
+; Indentation
+(efun 121 "Indent According to Mode" f_indatm	eef3)
+(efun 122 "Indent New Line"	f_indnl		eef3)
+(efun 123 "Back to Indentation"	f_backind	eef3)
+(efun 124 "Indent for Comment"	f_indcomm	eef3)
+(efun 125 "Indent Relative"	f_indrel	eef3)
+	; 126-128 reserved
+
+; Miscellaneous
+(efun 129 "Match Bracket"	f_matchbrack	eef3)	; not EMACS 
+
+; Process Control
+(efun 130 "Push to Inferior"	f_pshinf	eemain)
+(efun 131 "Return to Superior"	f_retsup	eemain)
+(efun 132 "Write File Exit"	f_wfexit	eemain)	; not EMACS
+    ; 133-139 reserved
+
+; ELLE Debugging
+(efun 140 "Hit Breakpoint"	f_bkpt		eeerr)	; ELLE
+(efun 141 "Debug Mode"		f_debug		eediag)	; ELLE
+    ; 142-149 reserved
+;---------------------------------------------------------------
+
+; IMAGEN configuration only
+(efun 150 "Execute Unix Command" f_xucmd	eemake)	; IMAGEN
+(efun 151 "Execute Make"	f_make		eemake)	; IMAGEN
+(efun 152 "Find Next Error"	f_nxterr	eemake)	; IMAGEN
+
+; ICONOGRAPHICS-specific
+(efun 153 "ICO Extend Command"	f_icoxcmd	eefico)	; ICONOGRAPHICS
+(efun 154 "ICO Typeset Funs"	f_icotypfns	eefico)	; ICONOGRAPHICS
+(efun 155 "ICO Spec Input Funs" f_icospifns	eefico) ; ICONOGRAPHICS
+
+; SUN Mouse functions
+(efun 156 "Stuff Selection"	f_stuffsel	eesun)	; SUN
+(efun 157 "Select Region"	f_selregion	eesun)	; SUN
+
Index: /trunk/minix/commands/elle/defprf.c
===================================================================
--- /trunk/minix/commands/elle/defprf.c	(revision 9)
+++ /trunk/minix/commands/elle/defprf.c	(revision 9)
@@ -0,0 +1,231 @@
+/* This file defines the initial data for ELLE's default user profile.
+** It is automatically generated by ELLEC, and should not be edited.
+*/
+char charmap[] = {
+	35,	/* (  0)  ^@  Set/Pop Mark */
+	20,	/* (  1)  ^A  Beginning of Line */
+	 5,	/* (  2)  ^B  Backward Character */
+	 0,	/* (  3)  ^C  unknown function */
+	 6,	/* (  4)  ^D  Delete Character */
+	21,	/* (  5)  ^E  End of Line */
+	 4,	/* (  6)  ^F  Forward Character */
+	 0,	/* (  7)  ^G  unknown function */
+	 5,	/* ( 10)  ^H  Backward Character */
+	121,	/* ( 11)  ^I  Indent According to Mode */
+	122,	/* ( 12)  ^J  Indent New Line */
+	28,	/* ( 13)  ^K  Kill Line */
+	78,	/* ( 14)  ^L  New Window */
+	 3,	/* ( 15)  ^M  CRLF */
+	24,	/* ( 16)  ^N  Down Real Line */
+	26,	/* ( 17)  ^O  Open Line */
+	25,	/* ( 20)  ^P  Up Real Line */
+	 2,	/* ( 21)  ^Q  Quoted Insert */
+	113,	/* ( 22)  ^R  Reverse Search */
+	112,	/* ( 23)  ^S  Incremental Search */
+	 9,	/* ( 24)  ^T  Transpose Characters */
+	93,	/* ( 25)  ^U  Universal Arg */
+	79,	/* ( 26)  ^V  Next Screen */
+	37,	/* ( 27)  ^W  Kill Region */
+	92,	/* ( 30)  ^X  Prefix Extend */
+	105,	/* ( 31)  ^Y  Un-kill */
+	 0,	/* ( 32)  ^Z  unknown function */
+	91,	/* ( 33)  ^[  Prefix Meta */
+	141,	/* ( 34)  ^\  Debug Mode */
+	 0,	/* ( 35)  ^]  unknown function */
+	140,	/* ( 36)  ^^  Hit Breakpoint */
+	97,	/* ( 37)  ^_  Describe */
+	 1,	/* ( 40)      Insert Self */
+	 1,	/* ( 41)   !  Insert Self */
+	 1,	/* ( 42)   "  Insert Self */
+	 1,	/* ( 43)   #  Insert Self */
+	 1,	/* ( 44)   $  Insert Self */
+	 1,	/* ( 45)   %  Insert Self */
+	 1,	/* ( 46)   &  Insert Self */
+	 1,	/* ( 47)   '  Insert Self */
+	 1,	/* ( 50)   (  Insert Self */
+	 1,	/* ( 51)   )  Insert Self */
+	 1,	/* ( 52)   *  Insert Self */
+	 1,	/* ( 53)   +  Insert Self */
+	 1,	/* ( 54)   ,  Insert Self */
+	 1,	/* ( 55)   -  Insert Self */
+	 1,	/* ( 56)   .  Insert Self */
+	 1,	/* ( 57)   /  Insert Self */
+	 1,	/* ( 60)   0  Insert Self */
+	 1,	/* ( 61)   1  Insert Self */
+	 1,	/* ( 62)   2  Insert Self */
+	 1,	/* ( 63)   3  Insert Self */
+	 1,	/* ( 64)   4  Insert Self */
+	 1,	/* ( 65)   5  Insert Self */
+	 1,	/* ( 66)   6  Insert Self */
+	 1,	/* ( 67)   7  Insert Self */
+	 1,	/* ( 70)   8  Insert Self */
+	 1,	/* ( 71)   9  Insert Self */
+	 1,	/* ( 72)   :  Insert Self */
+	 1,	/* ( 73)   ;  Insert Self */
+	 1,	/* ( 74)   <  Insert Self */
+	 1,	/* ( 75)   =  Insert Self */
+	 1,	/* ( 76)   >  Insert Self */
+	 1,	/* ( 77)   ?  Insert Self */
+	 1,	/* (100)   @  Insert Self */
+	 1,	/* (101)   A  Insert Self */
+	 1,	/* (102)   B  Insert Self */
+	 1,	/* (103)   C  Insert Self */
+	 1,	/* (104)   D  Insert Self */
+	 1,	/* (105)   E  Insert Self */
+	 1,	/* (106)   F  Insert Self */
+	 1,	/* (107)   G  Insert Self */
+	 1,	/* (110)   H  Insert Self */
+	 1,	/* (111)   I  Insert Self */
+	 1,	/* (112)   J  Insert Self */
+	 1,	/* (113)   K  Insert Self */
+	 1,	/* (114)   L  Insert Self */
+	 1,	/* (115)   M  Insert Self */
+	 1,	/* (116)   N  Insert Self */
+	 1,	/* (117)   O  Insert Self */
+	 1,	/* (120)   P  Insert Self */
+	 1,	/* (121)   Q  Insert Self */
+	 1,	/* (122)   R  Insert Self */
+	 1,	/* (123)   S  Insert Self */
+	 1,	/* (124)   T  Insert Self */
+	 1,	/* (125)   U  Insert Self */
+	 1,	/* (126)   V  Insert Self */
+	 1,	/* (127)   W  Insert Self */
+	 1,	/* (130)   X  Insert Self */
+	 1,	/* (131)   Y  Insert Self */
+	 1,	/* (132)   Z  Insert Self */
+	 1,	/* (133)   [  Insert Self */
+	 1,	/* (134)   \  Insert Self */
+	 1,	/* (135)   ]  Insert Self */
+	 1,	/* (136)   ^  Insert Self */
+	 1,	/* (137)   _  Insert Self */
+	 1,	/* (140)   `  Insert Self */
+	 1,	/* (141)   a  Insert Self */
+	 1,	/* (142)   b  Insert Self */
+	 1,	/* (143)   c  Insert Self */
+	 1,	/* (144)   d  Insert Self */
+	 1,	/* (145)   e  Insert Self */
+	 1,	/* (146)   f  Insert Self */
+	 1,	/* (147)   g  Insert Self */
+	 1,	/* (150)   h  Insert Self */
+	 1,	/* (151)   i  Insert Self */
+	 1,	/* (152)   j  Insert Self */
+	 1,	/* (153)   k  Insert Self */
+	 1,	/* (154)   l  Insert Self */
+	 1,	/* (155)   m  Insert Self */
+	 1,	/* (156)   n  Insert Self */
+	 1,	/* (157)   o  Insert Self */
+	 1,	/* (160)   p  Insert Self */
+	 1,	/* (161)   q  Insert Self */
+	 1,	/* (162)   r  Insert Self */
+	 1,	/* (163)   s  Insert Self */
+	 1,	/* (164)   t  Insert Self */
+	 1,	/* (165)   u  Insert Self */
+	 1,	/* (166)   v  Insert Self */
+	 1,	/* (167)   w  Insert Self */
+	 1,	/* (170)   x  Insert Self */
+	 1,	/* (171)   y  Insert Self */
+	 1,	/* (172)   z  Insert Self */
+	 1,	/* (173)   {  Insert Self */
+	 1,	/* (174)   |  Insert Self */
+	 1,	/* (175)   }  Insert Self */
+	 1,	/* (176)   ~  Insert Self */
+	 7,	/* (177) DEL  Backward Delete Character */
+};
+ char metamap[] = {
+	02  , 86,	/* M-^B  Move to Window Bottom */
+	014 , 30,	/* M-^L  Goto Line */
+	016 , 84,	/* M-^N  Scroll Window Down */
+	020 , 83,	/* M-^P  Scroll Window Up */
+	022 ,111,	/* M-^R  Reverse String Search */
+	023 ,110,	/* M-^S  String Search */
+	024 , 85,	/* M-^T  Move to Window Top */
+	027 ,107,	/* M-^W  Append Next Kill */
+	030 , 51,	/* M-^X  Select Existing Buffer */
+	036 , 74,	/* M-^^  Shrink Window */
+	045 ,115,	/*  M-%  Query Replace */
+	055 , 94,	/*  M--  Negative Argument */
+	060 , 95,	/*  M-0  Argument Digit */
+	061 , 95,	/*  M-1  Argument Digit */
+	062 , 95,	/*  M-2  Argument Digit */
+	063 , 95,	/*  M-3  Argument Digit */
+	064 , 95,	/*  M-4  Argument Digit */
+	065 , 95,	/*  M-5  Argument Digit */
+	066 , 95,	/*  M-6  Argument Digit */
+	067 , 95,	/*  M-7  Argument Digit */
+	070 , 95,	/*  M-8  Argument Digit */
+	071 , 95,	/*  M-9  Argument Digit */
+	073 ,124,	/*  M-;  Indent for Comment */
+	074 , 56,	/*  M-<  Goto Beginning */
+	076 , 57,	/*  M->  Goto End */
+	0133, 46,	/*  M-[  Backward Paragraph */
+	0134,  8,	/*  M-\  Delete Horizontal Space */
+	0135, 45,	/*  M-]  Forward Paragraph */
+	0102, 11,	/*  M-B  Backward Word */
+	0103, 17,	/*  M-C  Uppercase Initial */
+	0104, 12,	/*  M-D  Kill Word */
+	0106, 10,	/*  M-F  Forward Word */
+	0107, 41,	/*  M-G  Fill Region */
+	0110, 47,	/*  M-H  Mark Paragraph */
+	0111,125,	/*  M-I  Indent Relative */
+	0114, 16,	/*  M-L  Lowercase Word */
+	0115,123,	/*  M-M  Back to Indentation */
+	0116, 22,	/*  M-N  Next Line */
+	0117, 96,	/*  M-O  VT100 Button Hack */
+	0120, 23,	/*  M-P  Previous Line */
+	0121, 48,	/*  M-Q  Fill Paragraph */
+	0124, 14,	/*  M-T  Transpose Words */
+	0125, 15,	/*  M-U  Uppercase Word */
+	0126, 80,	/*  M-V  Previous Screen */
+	0127, 38,	/*  M-W  Copy Region */
+	0131,106,	/*  M-Y  Un-kill Pop */
+	0176, 54,	/*  M-~  Buffer Not Modified */
+	0177, 13,	/* M-DEL  Backward Kill Word */
+};
+ char extmap[] = {
+	02  , 53,	/* X-^B  List Buffers */
+	03  ,132,	/* X-^C  Write File Exit */
+	05  , 67,	/* X-^E  Write Region */
+	06  , 60,	/* X-^F  Find File */
+	013 , 68,	/* X-^K  Write Last Kill */
+	014 , 40,	/* X-^L  Lowercase Region */
+	015 , 55,	/* X-^M  EOL CRLF Mode */
+	017 , 27,	/* X-^O  Delete Blank Lines */
+	020 , 90,	/* X-^P  Set Profile */
+	022 , 61,	/* X-^R  Read File */
+	023 , 64,	/* X-^S  Save File */
+	025 , 39,	/* X-^U  Uppercase Region */
+	026 , 62,	/* X-^V  Visit File */
+	027 , 66,	/* X-^W  Write File */
+	030 , 36,	/* X-^X  Exchange Point and Mark */
+	032 ,131,	/* X-^Z  Return to Superior */
+	041 ,130,	/*  X-!  Push to Inferior */
+	044 ,116,	/*  X-$  Replace in Line */
+	045 ,114,	/*  X-%  Replace String */
+	050 ,100,	/*  X-(  Start Kbd Macro */
+	051 ,101,	/*  X-)  End Kbd Macro */
+	052 ,103,	/*  X-*  View Kbd Macro */
+	056 ,118,	/*  X-.  Set Fill Prefix */
+	060 , 75,	/*  X-0  Delete Window */
+	061 , 71,	/*  X-1  One Window */
+	062 , 70,	/*  X-2  Two Windows */
+	070 , 76,	/*  X-8  Standout Window */
+	071 , 77,	/*  X-9  Two Mode Windows */
+	075 , 58,	/*  X-=  What Page */
+	0136, 73,	/*  X-^  Grow Window */
+	0102, 50,	/*  X-B  Select Buffer */
+	0105,102,	/*  X-E  Execute Kbd Macro */
+	0106,117,	/*  X-F  Set Fill Column */
+	0111, 63,	/*  X-I  Insert File */
+	0113, 52,	/*  X-K  Kill Buffer */
+	0117, 72,	/*  X-O  Other Window */
+	0123, 65,	/*  X-S  Save All Files */
+	0124,119,	/*  X-T  Auto Fill Mode */
+	0177, 29,	/* X-DEL  Backward Kill Line */
+};
+struct profile def_prof = {
+  1, /* Ver */
+  sizeof(charmap),   charmap,
+  sizeof(metamap)/2, metamap,
+  sizeof(extmap)/2,  extmap, 
+  0, 0
+};
Index: /trunk/minix/commands/elle/defprf.e
===================================================================
--- /trunk/minix/commands/elle/defprf.e	(revision 9)
+++ /trunk/minix/commands/elle/defprf.e	(revision 9)
@@ -0,0 +1,259 @@
+;;;
+;;; ELLE Default Command Profile - "defprf.e"
+;;;
+;;;	This file is input to the ellec program.  It defines the default
+;;; command key bindings that ELLE uses, in the absence of an individual
+;;; user profile.
+;;;	These defaults attempt to emulate the default EMACS command key
+;;; bindings.  Differences, where known, are commented.
+;;;
+;;;	"ELLE" means the function is unique to ELLE.
+;;;	E/G: (cmd altnam) "thisname";
+;;;		"E:" refers to TOPS-20 EMACS, "G:" refers to Gnu Emacs.
+;;;		(cmd) This function exists but is bound to "cmd" instead.
+;;;		    (*) function exists but is not bound to any specific key.
+;;;		    ()  function does not exist.
+;;;		    (=) function exists, with same binding (normally omitted)
+;;;		altnam  Name by which this function is known.
+;;;		"thisname" - name of function bound to this command.
+;;;		    -    means the command is unbound (undefined).
+
+(keyallunbind)		; Flush any predefined bindings
+
+(keybind ^@ "Set/Pop Mark")
+(keybind ^A "Beginning of Line")
+(keybind ^B "Backward Character")
+; ^C not bound.  			; E: ()- G: mode-specific-command-prefix
+(keybind ^D "Delete Character")
+(keybind ^E "End of Line")
+(keybind ^F "Forward Character")
+(keybind ^H "Backward Character")	; G: (^B) help-command
+(keybind ^I "Indent According to Mode")
+(keybind ^J "Indent New Line")
+(keybind ^K "Kill Line")
+(keybind ^L "New Window")
+(keybind ^M "CRLF")
+(keybind ^N "Down Real Line")
+(keybind ^O "Open Line")
+(keybind ^P "Up Real Line")
+(keybind ^Q "Quoted Insert")
+(keybind ^R "Reverse Search")
+(keybind ^S "Incremental Search")
+(keybind ^T "Transpose Characters")
+(keybind ^U "Universal Arg")
+(keybind ^V "Next Screen")
+(keybind ^W "Kill Region")
+(keybind ^X "Prefix Extend")
+(keybind ^Y "Un-kill")
+; ^Z not bound			; E: Prefix Control-Meta;  G: suspend-emacs
+(keybind ^[ "Prefix Meta")
+(keybind "^\" "Debug Mode")	; ELLE. E: () Prefix Meta;  G: () -
+; ^] not bound.			; E+G: Abort Recursive Edit
+(keybind ^^ "Hit Breakpoint")	; ELLE. E: () Prefix Control;  G: () -
+(keybind ^_ "Describe")		; E: (M-?) Help;  G: (^H-k) undo
+(keybind " " "Insert Self")
+(keybind ! "Insert Self")
+(keybind """" "Insert Self")
+(keybind # "Insert Self")
+(keybind $ "Insert Self")
+(keybind % "Insert Self")
+(keybind & "Insert Self")
+(keybind ' "Insert Self")
+(keybind "(" "Insert Self")
+(keybind ")" "Insert Self")
+(keybind * "Insert Self")
+(keybind + "Insert Self")
+(keybind , "Insert Self")
+(keybind - "Insert Self")
+(keybind . "Insert Self")
+(keybind / "Insert Self")
+(keybind 0 "Insert Self")
+(keybind 1 "Insert Self")
+(keybind 2 "Insert Self")
+(keybind 3 "Insert Self")
+(keybind 4 "Insert Self")
+(keybind 5 "Insert Self")
+(keybind 6 "Insert Self")
+(keybind 7 "Insert Self")
+(keybind 8 "Insert Self")
+(keybind 9 "Insert Self")
+(keybind : "Insert Self")
+(keybind ";" "Insert Self")
+(keybind < "Insert Self")
+(keybind = "Insert Self")
+(keybind > "Insert Self")
+(keybind ? "Insert Self")
+(keybind @ "Insert Self")
+(keybind A "Insert Self")
+(keybind B "Insert Self")
+(keybind C "Insert Self")
+(keybind D "Insert Self")
+(keybind E "Insert Self")
+(keybind F "Insert Self")
+(keybind G "Insert Self")
+(keybind H "Insert Self")
+(keybind I "Insert Self")
+(keybind J "Insert Self")
+(keybind K "Insert Self")
+(keybind L "Insert Self")
+(keybind M "Insert Self")
+(keybind N "Insert Self")
+(keybind O "Insert Self")
+(keybind P "Insert Self")
+(keybind Q "Insert Self")
+(keybind R "Insert Self")
+(keybind S "Insert Self")
+(keybind T "Insert Self")
+(keybind U "Insert Self")
+(keybind V "Insert Self")
+(keybind W "Insert Self")
+(keybind X "Insert Self")
+(keybind Y "Insert Self")
+(keybind Z "Insert Self")
+(keybind [ "Insert Self")
+(keybind "\" "Insert Self")
+(keybind ] "Insert Self")
+(keybind ^ "Insert Self")
+(keybind _ "Insert Self")
+(keybind ` "Insert Self")
+(keybind a "Insert Self")
+(keybind b "Insert Self")
+(keybind c "Insert Self")
+(keybind d "Insert Self")
+(keybind e "Insert Self")
+(keybind f "Insert Self")
+(keybind g "Insert Self")
+(keybind h "Insert Self")
+(keybind i "Insert Self")
+(keybind j "Insert Self")
+(keybind k "Insert Self")
+(keybind l "Insert Self")
+(keybind m "Insert Self")
+(keybind n "Insert Self")
+(keybind o "Insert Self")
+(keybind p "Insert Self")
+(keybind q "Insert Self")
+(keybind r "Insert Self")
+(keybind s "Insert Self")
+(keybind t "Insert Self")
+(keybind u "Insert Self")
+(keybind v "Insert Self")
+(keybind w "Insert Self")
+(keybind x "Insert Self")
+(keybind y "Insert Self")
+(keybind z "Insert Self")
+(keybind { "Insert Self")
+(keybind | "Insert Self")
+(keybind } "Insert Self")
+(keybind ~ "Insert Self")
+(keybind DEL "Backward Delete Character")
+
+; Meta chars
+
+(keybind M-^B "Move to Window Bottom")	; ELLE (ima). E+G:()-
+(keybind M-^L "Goto Line")		; E:();  G:(* goto-line) -
+(keybind M-^N "Scroll Window Down")	; ELLE (ima). E+G:()- forward-list
+(keybind M-^P "Scroll Window Up")	; ELLE (ima). E+G:()- backward-list
+(keybind M-^R "Reverse String Search")	; E:(*); G:(* search-backward) -
+(keybind M-^S "String Search")		; E:(*); G:(* search-forward) isearch-forward-regexp
+(keybind M-^T "Move to Window Top")	; ELLE (ima). E+G:()-
+(keybind M-^W "Append Next Kill")
+(keybind M-^X "Select Existing Buffer")	; ELLE (ima). E+G:()-
+(keybind M-^^ "Shrink Window")		; ELLE (ima). E+G:()-
+(keybind M-% "Query Replace")
+(keybind M-- "Negative Argument")
+(keybind M-0 "Argument Digit")
+(keybind M-1 "Argument Digit")
+(keybind M-2 "Argument Digit")
+(keybind M-3 "Argument Digit")
+(keybind M-4 "Argument Digit")
+(keybind M-5 "Argument Digit")
+(keybind M-6 "Argument Digit")
+(keybind M-7 "Argument Digit")
+(keybind M-8 "Argument Digit")
+(keybind M-9 "Argument Digit")
+(keybind "M-;" "Indent for Comment")
+(keybind M-< "Goto Beginning")
+(keybind M-> "Goto End")
+(keybind M-[ "Backward Paragraph")
+(keybind "M-\" "Delete Horizontal Space")
+(keybind M-] "Forward Paragraph")
+(keybind M-B "Backward Word")
+(keybind M-C "Uppercase Initial")
+(keybind M-D "Kill Word")
+(keybind M-F "Forward Word")
+(keybind M-G "Fill Region")
+(keybind M-H "Mark Paragraph")
+(keybind M-I "Indent Relative")		; E+G: (*) Tab to Tab Stop
+(keybind M-L "Lowercase Word")
+(keybind M-M "Back to Indentation")
+(keybind M-N  "Next Line")		; E:(*); G:(* forward-line) -
+(keybind M-O "VT100 button hack")	; ELLE. E+G: () -
+(keybind M-P  "Previous Line")		; E:(*); G:() -
+(keybind M-Q "Fill Paragraph")
+(keybind M-T "Transpose Words")
+(keybind M-U "Uppercase Word")
+(keybind M-V "Previous Screen")
+(keybind M-W "Copy Region")
+(keybind M-Y "Un-kill Pop")
+(keybind M-~ "Buffer Not Modified")
+(keybind M-DEL "Backward Kill Word")
+
+; Extended commands
+
+(keybind X-^B "List Buffers")
+(keybind X-^C "Write File Exit")	; ELLE (ima). E:()-; G: (= save-buffers-kill-emacs)
+(keybind X-^E "Write Region")		; E:(*)-;    G:(*) eval-last-sexp
+(keybind X-^F "Find File")
+(keybind X-^K "Write Last Kill")	; ELLE (mnx). E+G:()-
+(keybind X-^L "Lowercase Region")
+(keybind X-^M "EOL CRLF Mode")		; ELLE.  E+G: ()-
+(keybind X-^O "Delete Blank Lines")
+(keybind X-^P "Set Profile")		; ELLE.  E+G: () Mark Page
+(keybind X-^R "Read File")
+(keybind X-^S "Save File")
+(keybind X-^U "Uppercase Region")
+(keybind X-^V "Visit File")
+(keybind X-^W "Write File")
+(keybind X-^X "Exchange Point and Mark")
+(keybind X-^Z "Return to Superior")	; G:() suspend-emacs
+(keybind X-! "Push to Inferior")	; ELLE.  E:(*)-; G:()-
+(keybind X-$  "Replace in Line")	; ELLE (mnx). E+G:()-
+(keybind X-% "Replace String")		; E+G: (*) -
+(keybind "X-(" "Start Kbd Macro")
+(keybind "X-)" "End Kbd Macro")
+(keybind X-* "View Kbd Macro")		; E: (*)-; G: ()-
+(keybind X-. "Set Fill Prefix")
+(keybind X-0 "Delete Window")		; E: ()-
+(keybind X-1 "One Window")
+(keybind X-2 "Two Windows")
+(keybind X-8 "Standout Window")		; ELLE.  E+G:()-
+(keybind X-9 "Two Mode Windows")	; ELLE.  E+G:()-
+(keybind X-= "What Page")		; E+G: (*) What Cursor Position
+(keybind X-^ "Grow Window")
+(keybind X-B "Select Buffer")
+(keybind X-E "Execute Kbd Macro")
+(keybind X-F "Set Fill Column")
+(keybind X-I "Insert File")		; E: (*) Info
+(keybind X-K "Kill Buffer")
+(keybind X-O "Other Window")
+(keybind X-S "Save All Files")		; E:(*)-; G:(= save-some-buffers)
+(keybind X-T "Auto Fill Mode")		; E:(*) Transpose Regions;  G:(*)-
+(keybind X-DEL "Backward Kill Line")	; ELLE(ico)  E+G:() Backward Kill Sentence
+
+
+; IMAGEN-specific functions, not bound.
+;(keybind ""  "Text Mode")		; IMAGEN E:(*);	G:(*)
+;(keybind ""  "Execute Unix Command")	; IMAGEN E:();	G:(M-! shell-command)
+;(keybind ""  "Execute Make")		; IMAGEN E:(* Compile); G:(* compile)
+;(keybind ""  "Find Next Error")	; IMAGEN E:();	G:(X-` next-error)
+
+; SUN Mouse functions, for menuitem selection.
+;(menuitem "Stuff Selection")	; SUN
+;(menuitem "Select Region")	; SUN
+
+; Forget completely about these.
+;(keybind ""  "ICO Extend Command")	; ICONOGRAPHICS
+;(keybind ""  "ICO Typeset Funs")	; ICONOGRAPHICS
+;(keybind ""  "ICO Spec Input Funs")	; ICONOGRAPHICS
+
Index: /trunk/minix/commands/elle/eebit.c
===================================================================
--- /trunk/minix/commands/elle/eebit.c	(revision 9)
+++ /trunk/minix/commands/elle/eebit.c	(revision 9)
@@ -0,0 +1,47 @@
+/* ELLE - Copyright 1985, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*
+ * EEBIT	Bit Array functions
+ */
+#include "sb.h"
+
+/* Char-bit array functions.   All assume that there are at least 8 bits
+ * in a byte, and that the number of bytes per word is a power of 2.
+ */
+/* CHBBITS represents log 2 of the # of bits stored per chbit-array word.
+ *	WDBITS already has log2 of the # of bytes per word, and we are
+ *	assuming each byte has at least 8 bits, so log2(8) = 3.
+ */
+#define CHBSIZE (WDSIZE*8)	/* # bits per word */
+#define CHBBITS (WDBITS+3)	/* log2(CHBSIZE) */
+#define CHBMASK (CHBSIZE-1)
+#define CHBARYSIZ (128/CHBSIZE)	/* # words per ASCII array */
+
+/* CHBALLOC(size) - Allocates a char-bit array */
+int *
+chballoc(size)
+int size;
+{	return((int *)calloc((size + CHBSIZE-1)/CHBSIZE, (sizeof(int))));
+}
+
+/* CHBIT(array, char) - Tests bit in char-bit array
+ */
+chbit(array,c)
+register int *array, c;
+{	return(array[c >> CHBBITS] & (1 << (c & CHBMASK)));
+}
+/* CHBIS (array, char) - Sets bit in char-bit array
+ */
+chbis(array,c)
+register int *array, c;
+{	array[c >> CHBBITS] |= (1 << (c & CHBMASK));
+}
+/* CHBIC (array, char) - Clears bit in char-bit array
+ */
+chbic(array,c)
+register int *array, c;
+{	array[c >> CHBBITS] &= ~(1 << (c & CHBMASK));
+}
Index: /trunk/minix/commands/elle/eebuff.c
===================================================================
--- /trunk/minix/commands/elle/eebuff.c	(revision 9)
+++ /trunk/minix/commands/elle/eebuff.c	(revision 9)
@@ -0,0 +1,1081 @@
+/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+
+/* EEBUFF	Buffer and Window functions.
+ *	Each buffer is an independent SB-string described by a
+ *	buffer structure.  All buffer structures are allocated dynamically
+ *	and chained together starting from buf_head.
+ */
+
+#include "elle.h"
+
+#if FX_FILLMODE
+extern int fill_mode;
+#endif
+#if FX_SKMAC
+extern int kdef_mode;
+#endif
+
+struct buffer *make_buf(), *find_buf(), *sel_mbuf(), *sel_nbuf();
+struct window *make_win();
+
+/* EFUN: "Select Buffer" */
+/*	Select old buffer or create a new one.  Defaults to previously
+ *	used buffer.
+ */
+f_selbuffer()
+{	register char *ans;
+	register struct buffer *b;
+
+	if((b = last_buf) == cur_buf)	/* If default same as current, */
+		if(!(b = sel_mbuf(b)))	/* try to pick a more useful one. */
+			b = sel_nbuf(cur_buf);
+
+	ans = ask("Select buffer (%s): ",b->b_name);
+	if (ans == 0)		       /* he aborted */
+		return;
+	if (*ans != '\0')		/* Null string => use last buff */
+	  {	b = find_buf (ans);	/* Else find/create one */
+		if (b == 0)
+			b = make_buf (ans);
+	  }
+	sel_buf(b);
+	chkfree(ans);
+}
+
+#if FX_SELXBUFFER
+/* EFUN: "Select Existing Buffer" (not EMACS) - from IMAGEN config */
+
+static int findstr();
+
+f_selxbuffer()
+{	register char *ans;
+	register struct buffer *b;
+
+	b = last_buf;			/* This is default */
+	ans = ask("Select existing buffer (%s): ", b->b_name);
+	if (ans == 0)			/* Aborted */
+		return;
+	if (*ans != 0)
+	  {	for (b = buf_head; b != 0; b = b->b_next)
+			if (findstr(ans, b->b_name))
+				break;
+		if (b == 0)
+			ding("That isn't a substring of any buffer name!");
+	  }
+	chkfree(ans);
+	if (b != 0)
+	  {	saytoo(" => ");
+		sayntoo(b->b_name);
+		sel_buf(b);
+	  }
+}
+
+static int
+findstr(str, instr)			/* Find "str" in string "instr" */
+register char *str, *instr;
+{	register char *sp, *isp;
+
+	while (*instr)
+	  {	sp = str;
+		isp = instr;
+		while (*sp)
+			if (*sp++ != *isp++)
+				goto next;
+		return(1);
+next:		++instr;
+	  }
+	return(0);
+}
+#endif /*FX_SELXBUFFER*/
+
+
+/* EFUN: "Kill Buffer"	*/
+/*	Kill specified buffer - defaults to current buffer.
+ * This code assumes a killed buffer will never be on a window list unless it
+ * is pointed to by cur_buf or oth_win->w_buf!!!!
+ */
+f_kbuffer()
+{	register struct buffer *b, *ob;
+	register char *ans;
+
+	if((ans = ask("Kill buffer: ")) == 0)
+		return;
+	if(*ans == 0) b = cur_buf;
+	else if(*ans == SP) b = 0;
+	else b = find_buf(ans);
+
+	chkfree(ans);
+	if(!b)
+	  {	ding("No such buffer");
+		return;
+	  }
+#if IMAGEN
+	if (b->b_flags & B_PERMANENT)
+	  {	ding("Permanent buffer--cannot kill!");
+		return;
+	  }
+	if (b->b_flags & B_MODIFIED)
+	  {	if ((ans == ask("Buffer is modified; are you sure? ")) == 0)
+			return;
+		if(upcase(*ans) != 'Y')
+		  {	chkfree(ans);
+			return;
+		  }
+		chkfree(ans);
+	  }
+#endif /*IMAGEN*/
+	if(b == cur_buf || (oth_win && (oth_win->w_buf == b)))
+	  {	ob = last_buf;
+		do
+		  {
+			/* If default same as doomed buffer, try to pick
+			 * a more useful alternative. */
+			if((b == ob) && !(ob = sel_mbuf(b)))
+				ob = sel_nbuf(b);
+
+			ans = ask("Killing in-use buffer; select which other buffer (%s): ",
+					ob->b_name);
+			if(ans == 0) return;
+			if(*ans)
+			  {	if(*ans == SP) ob = 0;
+				else ob = find_buf(ans);
+			  }
+			chkfree(ans);
+			if(!ob)
+			  {	ding("No such buffer");
+				return;
+			  }
+		  } while (b == ob);
+
+		/* B is buffer to kill, OB is buffer to replace it with */
+		if(oth_win && (oth_win->w_buf == b))
+		  {	f_othwind();	/* Select other one */
+			chg_buf(ob);	/* Change to new buffer */
+			f_othwind();
+		  }
+		if(cur_buf == b)
+			chg_buf(ob);
+	  }
+
+	kill_buf(b);			/* Die!!!! */
+	if(last_buf == b)
+		last_buf = cur_buf;
+}
+
+/* EFUN: "List Buffers" */
+/*	Display a list of all user buffers.  Internal buffers, whose names
+ *	start with a space, are not shown.
+ */
+f_listbufs()
+{
+	register struct buffer *b;
+	register char *cp;
+	register int i;
+	struct buffer *tbuf, *savbuf;
+	char temp[20];
+
+	/* First must set up special buffer... */
+	savbuf = cur_buf;
+	chg_buf(tbuf = make_buf(" **SHOW**"));
+	e_sputz("Buffers in this ELLE:\n\n");
+	for(b = buf_head; b; b = b->b_next)
+	  {	cp = b->b_name;
+		if(*cp == SP) continue;	/* Ignore internal buffs */
+		e_sputz((b->b_flags&B_MODIFIED) ? "* " : "  ");
+		e_sputz(cp);			/* Insert buffer name */
+		dottoa(temp,ex_blen(b));	/* Get buff-length string */
+		if((i = ((FNAMELEN > 14) ? 30 : 20)
+			 - strlen(cp) - strlen(temp)) > 0)
+			e_insn(SP, i);
+		e_sputz(" (");
+		e_sputz(temp);
+		e_sputz(") ");
+		if(cp = b->b_fn)
+			e_sputz(cp);
+#if IMAGEN
+		if (b->b_flags & B_CMODE)
+			e_sputz(" (C)");
+		else if (b->b_flags & B_TEXTMODE)
+			e_sputz(" (Text)");
+		else
+			e_sputz(" (Fundamental)");
+#endif /*IMAGEN*/
+		e_putc(LF);
+	  }
+	mk_showin(tbuf);	/* Show this buffer in temp window */
+	chg_buf(savbuf);	/* Return to real current buffer */
+	kill_buf(tbuf);
+}
+
+
+/* EFUN: "Buffer Not Modified" */
+/*	Mark the current buffer as not modified.
+ */
+f_bufnotmod()
+{
+	cur_buf -> b_flags &= ~B_MODIFIED;
+	redp(RD_MODE);
+}
+
+#if FX_EOLMODE
+/* EFUN: "EOL CRLF Mode" (not EMACS) */
+/*	Toggle the EOL mode of the current buffer.
+**		LF EOL Mode means LF alone is an EOL.
+**		CRLF EOL Mode means CRLF together is an EOL.
+*/
+f_eolmode()
+{
+	cur_buf->b_flags ^= B_EOLCRLF;		/* Flip this bit */
+	say((cur_buf->b_flags & B_EOLCRLF)
+		? "EOL Mode is CRLF"		/* If now on */
+		: "EOL Mode is LF");		/* If now off */
+
+	redp(RD_WINRES);			/* Redo window for this buf */
+}
+#endif /*FX_EOLMODE*/
+
+
+#if FX_GOBEG
+/* EFUN: "Goto Beginning" */
+f_gobeg()
+{	e_gobob();
+	ed_setcur();
+}
+#endif /*FX_GOBEG*/
+
+#if FX_GOEND
+/* EFUN: "Goto End" */
+f_goend()
+{	e_goeob();
+	ed_setcur();
+}
+#endif /*FX_GOEND*/
+
+#if FX_WHATPAGE
+/* EFUN: "What Page" */
+/*	Extra info added as per earlier ICONOGRAPHICS "What Buffer Position"
+** Reports on current position as follows:
+**	Dot=<n>, Page <n>  Line <n> (line <n> of <m>)
+*/
+f_whatpage()
+{
+	register chroff cnt;
+	register int c;
+	register int page, line;
+	int lineatp;
+	char tempstr[12], *dottoa ();
+
+        saynow("Dot=");
+        dottoa(tempstr, cur_dot);
+        sayntoo(tempstr);
+
+	e_gobob();
+	page = line = lineatp = 1;
+	for (cnt = cur_dot; --cnt >= 0;)
+		if ((c = e_getc()) == LF)
+			++line;
+		else if (c == FF)
+		  {	++page;
+			lineatp = line;
+		  }
+
+        saytoo(", Page ");
+        dottoa(tempstr, (chroff)page);
+        saytoo(tempstr);
+	saytoo("  Line ");
+        dottoa(tempstr, (chroff)(1 + line - lineatp));
+        saytoo(tempstr);
+	saytoo("  Col ");
+        dottoa(tempstr, (chroff)indtion(cur_dot));
+        saytoo(tempstr);
+	saytoo("  [line ");
+	dottoa(tempstr, (chroff)line);
+	saytoo(tempstr);
+	sayntoo(" of ");		/* Force out while scan rest */
+
+        for(e_gocur(); e_gonl() ; ++line) ;	/* Count lines until EOF */
+	c = e_rgetc();			/* Remember what last char is */
+        dottoa(tempstr, (chroff)line);
+        saytoo(tempstr);
+        if (c != LF)		/* Check last char */
+            saytoo(" (no EOL at EOF!)");
+        sayntoo("]");
+	e_gocur();			/* Back to original position */
+}
+#endif /*FX_WHATPAGE*/
+
+
+init_buf ()			       /* init buffer stuff */
+{
+	buf_head = 0;
+	lines_buf = cur_buf = make_buf(" **LINES**");	/* For sep_win */
+	e_insn('-',scr_wid-2);			/* Fill with dashes */
+	last_buf = cur_buf = make_buf ("Main");	/* Make Main buffer */
+	init_win();				/* Now can init windows */
+}
+
+struct buffer *
+make_buf(bname)	       /* create buffer "bname" if it doesn't exist */
+char *bname;
+{	register struct buffer *b;
+	register char *name;
+
+	b = find_buf(name = bname);
+	if (b)				/* if it exists already */
+		return(b);
+	b = (struct buffer *) memalloc(sizeof (struct buffer));
+	b -> b_next = buf_head;	       /* link it in */
+	buf_head = b;
+	b->b_name = strdup(name);	/* Allocate copy of name string */
+	b->b_dot = 0;		/* Set dot to beg */
+	sb_open(b,(SBSTR *)0);		/* Open buffer with null initial sbstring */
+	b->b_fn = 0;
+	b->b_flags = 0;
+	b->b_mode = cur_mode;	/* Inherit current mode */
+	return(b);
+}
+
+
+struct buffer *
+find_buf(name)	       /* returns pointer to buffer of that name or 0 */
+char *name;
+{	register struct buffer *b = buf_head;
+
+	while (b && strcmp(b->b_name, name))
+		b = b -> b_next;
+	return(b);
+}
+
+sel_buf(b)				/* select buffer, saving last */
+struct buffer *b;
+{
+	if(b != cur_buf) last_buf = cur_buf;
+	chg_buf(b);
+}
+
+chg_buf (newbuf)		       /* change current buffer to newbuf */
+struct buffer *newbuf;
+{	register struct buffer *obuf, *nbuf;
+
+	if ((nbuf = newbuf) == (obuf = cur_buf))
+		return;			/* Do nothing if same buffers */
+	obuf->b_dot = cur_dot;
+	cur_buf = nbuf;
+	cur_mode = nbuf->b_mode;
+	e_gosetcur(nbuf->b_dot);	/* Set cur_dot and go there */
+	cur_win->w_buf = nbuf;
+	cur_win->w_dot = cur_dot;
+#if IMAGEN
+	cur_win->w_redp = RD_WINRES|RD_REDO;
+#else
+	cur_win->w_redp = RD_WINRES;	/* Reset flags - do complete update */
+#endif /*-IMAGEN*/
+	unlk_buf(obuf);			/* Unlock previous buffer if can */
+	mark_p = 0;			/* this is lazy */
+	redp(RD_MODE|RD_WINRES);
+}
+
+/* See if specified buffer belongs to any active window, and
+ * if not then get it into an idle, unlocked state; this helps the
+ * edit package compact and swap stuff out while it's not being used.
+ * Assumes proper state of dot has been stored into b_dot.
+ */
+unlk_buf(bufp)
+struct buffer *bufp;
+{	register struct buffer *b;
+	register struct window *w;
+
+	b = bufp;
+	for(w = win_head; w; w = w->w_next)
+		if(b == w->w_buf)
+			return;		/* Buffer is actively being shown */
+	sb_rewind((SBBUF *)b);		/* Return to idle state */
+}
+
+/* SEL_NBUF(buf) - Select next user buffer.  Ignores internal buffers.
+ *	Arg of 0 starts at beg of buffer list.  Always returns
+ *	a buffer pointer - returns argument (which may be 0)
+ *	if found no other user buffers.
+ *
+ * SEL_MBUF(buf) - Select next modified buffer.
+ *	Returns buffer ptr to "next" modified buffer, if any.
+ *	Arg of 0 starts at beg of buffer list and scans all of them.
+ *	Returns 0 if no other modified buffers exist (unlike SEL_NBUF!)
+ *	Ignores internal buffers, whose names start with a space.
+ */
+/* struct buffer *buf_mptr; */
+#if 0
+struct buffer *
+sel_mbuf(buf)
+struct buffer *buf;
+{	register struct buffer *b;
+	register int sweep;
+
+	sweep = 0;			/* Make 2 sweeps only */
+	if(b = buf) b = b->b_next;
+	do {
+		if(b == 0)		/* Initialize if needed */
+			b = buf_head;
+		for(; b; b = b->b_next)
+			if((b->b_flags & B_MODIFIED) && (*b->b_name != SP))
+				return((b == buf) ? 0 : b);
+	  } while(sweep++ != 0);
+	return(0);
+}
+#endif /*COMMENT*/
+
+struct buffer *
+sel_mbuf(buf)
+register struct buffer *buf;
+{	register struct buffer *b, *b2;
+	b = b2 = sel_nbuf(buf);
+	do {	if(b == buf) break;
+		if(b->b_flags & B_MODIFIED)
+			return(b);
+	  } while((b = sel_nbuf(b)) != b2);
+
+	return(0);
+}
+
+struct buffer *
+sel_nbuf(buf)
+register struct buffer *buf;
+{	register struct buffer *b;
+
+	b = buf;
+	do {
+		if(!b || !(b = b->b_next))
+			b = buf_head;
+		if(*b->b_name != SP)
+			break;
+	  } while (b != buf);
+	return(b);
+}
+
+
+kill_buf(buf)
+struct buffer *buf;
+{	register struct buffer *b, *b1, *bt;
+
+	b = buf;
+	b1 = 0;
+	for(bt = buf_head; bt && bt != b; bt = bt -> b_next)
+		b1 = bt;
+	if(bt == 0)
+	  {	ring_bell();
+		errbarf("No such buffer");	/* Internal error */
+		return;
+	  }
+	if (b1 == 0)
+		buf_head = b->b_next;
+	else
+		b1->b_next = b->b_next;
+	sbs_del(sb_close((SBBUF *)b));	/* Close buffer & delete sbstring */
+	sb_fdcls(-1);			/* Make sweep for unused FD's */
+	if(b->b_fn)
+		chkfree(b->b_fn);	/* Flush filename if one */
+	chkfree(b->b_name);		/* Flush name */
+	chkfree((char *)b);		/* Flush buffer */
+}
+
+
+/* ZAP_BUFFER - Delete all of the buffer, but if it's been modified,
+ *	ask first.  Returns 0 if user aborts.
+ */
+zap_buffer()
+{
+#if IMAGEN
+	extern struct buffer *exec_buf;	/* in e_make.c */
+
+	if(cur_buf != exec_buf && cur_buf -> b_flags & B_MODIFIED)
+#else
+	if(cur_buf -> b_flags & B_MODIFIED)
+#endif /*-IMAGEN*/
+		if(ask_kbuf(cur_buf) <= 0)
+			return(0);		/* Aborted */
+	ed_reset();		/* This takes care of redisplay too */
+	mark_p = 0;
+#if IMAGEN
+	cur_buf->b_flags &= ~B_BACKEDUP; /* Clear backed-up flag */
+#endif
+	return(1);
+}
+
+
+
+
+/* ASK_KBUF - Ask user "are you sure?" before killing a buffer.
+ *	Returns +1 if user says "yes" - OK to kill.
+ *		 0 if user aborts (^G)
+ *		-1 if user says "no".
+ */
+ask_kbuf(buf)
+struct buffer *buf;
+{	register struct buffer *b;
+	register char *s;
+	register int ans;
+
+	b = buf;
+	s = ask("Buffer %s contains changes - forget them? ", b->b_name);
+	if(s == 0) return(0);
+	ans = (upcase(*s) == 'Y') ? 1 : -1;
+	chkfree(s);
+	return(ans);
+}
+
+
+/* Window stuff */
+
+/* Like EMACS, ELLE only provides at most two user windows.
+ * The current user window is pointed to by user_win;
+ * the "other" one is oth_win.  If oth_win == 0, there is only one user
+ * window.
+ */
+
+#if FX_2MODEWINDS
+int sepmode_p = 0;	/* Set true if separator window is a 2nd mode win */
+#endif
+
+/* EFUN: "Two Windows" */
+/*	Divide the current window in half, put the current buffer in the
+ *	other window, and go to the new window.
+ */
+f_2winds()
+{	register int h, t;
+	register struct window *w;
+
+	if (oth_win)
+	  {
+#if !(IMAGEN)
+		ding("Already 2 windows");
+#endif /*-IMAGEN*/
+		return;
+	  }
+	w = cur_win;
+	d_fixcur();			/* Stabilize current window */
+	h = (w->w_ht) / 2;
+	t = w->w_pos + h;		/* Pos of dividing window */
+	sep_win = make_win(t, 1, lines_buf);
+					/* assume using dashes to separate */
+	oth_win = make_win(t + 1, w->w_ht - (h + 1), cur_buf);
+					/* Other window has balance */
+#if FX_SOWIND
+	oth_win->w_flags |= cur_win->w_flags&W_STANDOUT;
+	sep_win->w_flags |= mode_win->w_flags&W_STANDOUT;
+#endif
+#if FX_2MODEWINDS
+	chk2modws();			/* Update 2-mode-wind status */
+#endif
+	w->w_ht = h;			/* Decrease current window to half */
+
+	/* Minimize redisplay by moving each window's dot into
+	 * a currently displayed area */
+	if(cur_dot < (oth_win->w_topldot = scr[t+1]->sl_boff))
+		oth_win->w_dot = oth_win->w_topldot;	/* Adj bottom win */
+	else					/* Adjust top window */
+	  {	oth_win->w_dot = cur_dot;	/* Bottom keeps dot */
+		cur_dot = scr[t-1]->sl_boff;	/* but top needs new one. */
+	  }
+	f_othwind();			/* switch to other window */
+	redp(RD_WINDS);			/* Update all windows */
+}
+
+
+/* EFUN: "One Window" */
+/*	Revert to using only one window; use the current buffer (unlike
+ *	EMACS which always selects the top window's buffer)
+ *	Ensures that current window's vars are correctly set for
+ *	new dimensions (w_pos, w_ht, plus w_topldot to minimize redisplay),
+ *	then kills unneeded windows.
+ */
+f_1wind()
+{	register struct window *w;
+
+	if (oth_win == 0)
+	  {
+#if (!IMAGEN)
+		ding("Only 1 window");
+#endif /*-IMAGEN*/
+		return;
+	  }
+	w = cur_win;
+	if(w->w_pos)		/* If not top window */
+	  {	d_fixcur();		/* Ensure screen-line data correct */
+		e_go(w->w_topldot);	/* Beginning from top of window, */
+		d_fgoloff(-w->w_pos);	/* Move back enough lines */
+		w->w_topldot = e_dot();	/* To set new start of window */
+		e_gocur();		/* Then move back to orig place */
+		w->w_pos = 0;
+	  }
+	w->w_ht += oth_win -> w_ht + 1;
+	kill_win (oth_win);
+	kill_win (sep_win);
+	oth_win = sep_win = 0;
+#if FX_2MODEWINDS
+	chk2modws();	/* Update notion of whether have 2 mode winds */
+#endif
+	redp(RD_FIXWIN|RD_WINDS|RD_MODE); /* New topldot for this window,
+					 * and check all remaining windows */
+}
+
+/* EFUN: "Other Window" */
+/*	Move to the "other" user window.
+ */
+f_othwind ()
+{	if (oth_win == 0)
+	  {
+#if !(IMAGEN)
+		ding("Only 1 window");
+#endif /*-IMAGEN*/
+		return;
+	  }
+	chg_win(oth_win);
+	oth_win = user_win;
+	user_win = cur_win;
+	redp(RD_MODE);
+}
+
+/* EFUN: "Grow Window" */
+/*	Grow the current window - while in two window mode,
+ *	increase the size of the current window by the arg
+ *	and decrease the other accordingly
+ */
+f_growind()
+{	register struct window *cw, *ow;
+	register int e;
+
+	if ((ow = oth_win) == 0)
+	  {
+#if !(IMAGEN)
+		ding("Only 1 window");
+#endif /*-IMAGEN*/
+		return;
+	  }
+	e = exp;
+	if((cw = cur_win)->w_pos != 0)	/* If current window is on bottom */
+	  {	cw = ow;		/* Then fake code to think it's top */
+		ow = cur_win;
+		e = -e;
+	  }
+	if(  cw->w_ht + e < 1
+	  || ow->w_ht + e < 1)
+	  {	ding("Too much");
+		return;
+	  }
+	cw -> w_ht += e;
+	ow -> w_pos += e;
+	ow -> w_ht -= e;
+	sep_win -> w_pos += e;
+	redp(RD_WINDS | RD_MODE);		/* Update all windows */
+}
+
+#if FX_SHRINKWIND
+/* EFUN: "Shrink Window" (not EMACS) - from IMAGEN config */
+f_shrinkwind()
+{
+	if (! oth_win)
+		return;
+	f_othwind();
+	f_growind();
+	f_othwind();
+}
+#endif /*FX_SHRINKWIND*/
+
+#if FX_DELWIND
+/* EFUN: "Delete Window" (not EMACS) - from IMAGEN config */
+f_delwind()
+{
+	if(!oth_win)
+		return;
+	f_othwind();
+	f_1wind();
+}
+#endif /*FX_DELWIND*/
+
+#if FX_SOWIND
+/* EFUN: "Standout Window" (not EMACS) */
+/*	Toggles the display standout mode for the current window.
+**	With argument of 4, toggles the standout mode for the non-buffer
+**	parts of the screen, such as the ELLE mode line.
+** (This corresponds to FS INVMOD$ in EMACS)
+**	With argument of 0, turns standout mode off for all windows.
+*/
+/* It suffices to set the window flag bit and force a RD_WINRES for that
+ * window; the redisplay code will do the rest.
+*/
+static void tgso_wind();
+
+f_sowind()
+{
+	register struct window *w;
+	switch(exp)
+	  {	default:		/* Toggle current window */
+			tgso_wind(cur_win);
+			break;
+		case 4:			/* Toggle mode & separator windows */
+			tgso_wind(mode_win);
+			tgso_wind(sep_win);	/* This may not exist */
+			break;
+		case 0:			/* Turn off standout for all winds */
+			for(w = win_head; w; w = w->w_next)
+				if(w->w_flags&W_STANDOUT)
+					tgso_wind(w);
+	  }
+#if FX_2MODEWINDS
+	chk2modws();	/* Update notion of whether have 2 mode winds */
+#endif
+}
+
+static void
+tgso_wind(w)		/* Toggle standout mode for given window */
+register struct window *w;
+{
+	if (w == 0) return;		/* For case of no sep_win */
+	if (w->w_flags & W_STANDOUT)
+		w->w_flags &= ~W_STANDOUT;
+	else w->w_flags |= W_STANDOUT;
+	w->w_redp |= RD_WINRES;		/* Re-do this particular window */
+	redp(RD_CHKALL);		/* Check all windows for changes */
+}
+#endif /*FX_SOWIND*/
+
+
+#if FX_2MODEWINDS
+/* EFUN: "Two Mode Windows" (not EMACS) */
+/*	With arg, sets ev_2modws to that value (0, 1, or 2).
+**	No arg, toggles current setting between 0 and 2.
+*/
+
+f_2modewinds()
+{
+	ev_2modws = exp_p ? exp : (ev_2modws ? 0 : 2);
+	chk2modws();
+}
+
+/* CHK2MODWS - Called after anything changes which might affect
+**	whether 2 mode windows are in effect or not.  Fixes up
+**	sep_win to either be or not be a mode window.
+*/
+chk2modws()
+{	register struct window *w;
+	static struct buffer *sep_buf = 0;
+
+	if(!(w = sep_win))
+	  {	sepmode_p = 0;		/* Don't have 2 windows at all */
+		return;
+	  }
+	sepmode_p = (ev_2modws == 1)
+			? (mode_win->w_flags&W_STANDOUT)
+			: ev_2modws;
+
+	if(sepmode_p)		/* Turn 2-mode-winds on? */
+	  {
+		if(!sep_buf)
+			sep_buf = make_buf(" **SEPMODE**");
+		w->w_buf = sep_buf;
+		w->w_flags |= W_MODE;
+	  }
+	else			/* Turn 2-mode-winds off */
+	  {	w->w_buf = lines_buf;
+		w->w_flags &= ~W_MODE;
+		redp(RD_CHKALL);	/* No longer a mode win, so must */
+					/* check all to ensure it's updated */
+	  }
+	w->w_redp |= RD_WINRES;
+	redp(RD_MODE);
+}
+#endif /*FX_2MODEWINDS*/
+
+
+init_win ()
+{
+	win_head = 0;
+	oth_win = 0;
+	user_win = make_win(0, scr_ht - (ECHOLINES+1), cur_buf); /* Main */
+	mode_win = make_win(scr_ht - (ECHOLINES+1), 1, make_buf(" **MODE**"));
+	ask_win  = make_win(scr_ht - ECHOLINES,     1, make_buf(" **ASK**"));
+#if FX_SOWIND
+	if(ev_modwso)
+		mode_win->w_flags |= W_STANDOUT;
+#endif
+
+	cur_win = user_win;
+}
+
+chg_win(newwin)		       /* change current window to newwin */
+struct window *newwin;
+{
+	cur_win->w_dot = cur_dot;	/* Save window's current dot */
+	cur_win->w_redp |= rd_type&RDS_WINFLGS;	/* and its redisplay flags */
+	cur_win = newwin;		/* OK, switch to new current window */
+	cur_buf = newwin->w_buf;	/* Set new buffer from win */
+	e_gosetcur(newwin->w_dot);	/* Set new cur_dot from win too */
+			/* Note done this way to canonicalize the location
+			** (may be past new EOB) and ensure SB buffer
+			** internals agree with cur_dot.
+			*/
+	rd_type &= ~RDS_WINFLGS;	/* Remove old per-window flags */
+	redp(RD_WINRES|RD_MODE);	/* Maybe caller shd handle? */
+			/* Note WINRES must be set in case we are pointing
+			 * to a buffer that was modified while we were in
+			 * the other window!
+			 */
+}
+
+
+struct window *
+make_win (pos, ht, buf)
+int pos, ht;
+struct buffer *buf;
+{	register struct window *w;
+	register struct buffer *b;
+
+	b = buf;
+	w = (struct window *) memalloc(sizeof (struct window));
+	w->w_flags = 0;
+	w->w_pos = pos;
+	w->w_ht = ht;
+	w->w_buf = b;
+	w->w_dot = b->b_dot;	/* Set dot from buffer value */
+	w->w_topldot = 0;	/* Set top of window to beg of buffer */
+	w->w_pct = 200;		/* Assume "ALL" */
+	w->w_bmod = 0;
+	w->w_emod = 0;
+	w->w_oldz = 0;
+	w->w_redp = RD_WINRES;	/* Window will need complete update */
+	w->w_next = win_head;	/* Done, now link it in */
+	win_head = w;
+	return (w);
+}
+
+kill_win (win)
+struct window *win;
+{	register struct window *w, *w1, *kw;
+
+	kw = win;
+	w1 = 0;
+	for (w = win_head; w && w != kw; w = w -> w_next)
+		w1 = w;
+	if (w == 0)
+	  {	ring_bell();
+		errbarf("No such window");	/* Internal error */
+		return;
+	  }
+	if (w1 == 0)
+		win_head = w -> w_next;
+	else
+		w1 -> w_next = w -> w_next;
+	kw->w_buf->b_dot = (kw == cur_win) ? cur_dot : kw->w_dot;
+	chkfree (kw);
+#if IMAGEN		/* Not needed? */
+	redp (RD_WINRES|RD_WINDS|RD_REDO);
+#endif /*IMAGEN*/
+}
+
+
+/*
+ * "Show-window" routines, used to set up, step through, and close a
+ * temporary "show" window.
+ * MK_SHOWIN(bufp)
+ * UP_SHOWIN()
+ * KL_SHOWIN()
+ */
+
+/* MK_SHOWIN(bufp) - Temporarily display a buffer
+ */
+mk_showin(b)
+struct buffer *b;
+{	register struct window *w;
+	register int i;
+	int moreflg, intflg;		/* Interrupt flag */
+	struct window *savwin;
+
+	/* First must set up special window... */
+	savwin = cur_win;
+	chg_win(w = make_win(0, scr_ht-(ECHOLINES+3), b));
+ redo:
+	d_fixcur();		/* Fix up screen image of current window */
+
+	/* Find how many lines actually used, and reduce size to that */
+	i = w->w_ht;
+	while(--i >= 0)
+	  {
+		if(scr[i]->sl_boff != w->w_oldz) break;
+	  }
+	if(++i <= 0)
+		goto skipit;	/* Punt the whole thing */
+	if(!(moreflg = (i >= w->w_ht)))
+		w->w_ht = i;	/* Reduce size of window */
+
+	intflg = upd_wind(w);	/* Update the window! */
+	if(!intflg)		/* Unless input waiting, add prompt. */
+	  {
+		yellat( moreflg ?
+	"--MORE-- (type Space for more, or type any command to flush)" :
+	"------------------------------------------------ (Hit space to continue)--",
+			w->w_ht);
+		
+	  }
+	tbufls();		/* Ensure all output forced out */
+	i = cmd_read();		/* then wait for user to input a char */
+	if(i == SP)
+	  {	if(moreflg)
+		  {	yellat("", w->w_ht);
+			d_screen(1);
+			w->w_redp |= RD_WINRES;
+			goto redo;
+		  }
+	  }
+#if !(IMAGEN)		/* IMAGEN - always ignore what was typed */
+	else unrchf = i;
+#endif /*-IMAGEN*/
+skipit:	chg_win(savwin);
+	kill_win(w);
+	redp(RD_WINDS);		/* Update all remaining windows */
+}
+
+
+/* Mode Line generation */
+
+struct window *
+make_mode(bw)
+register struct window *bw;	/* Base window we are reporting status of */
+{
+	register struct buffer *b;	/* Buffer of this window */
+	struct window *mw, *savew;	/* Save current window */
+	struct buffer *saveb;	/* and current buffer (in case different) */
+	char temp[20];
+
+	saveb = cur_buf;	/* Save values prior to context switch */
+	savew = cur_win;
+	b = bw->w_buf;		/* Get buffer for that window */
+
+#if FX_2MODEWINDS
+	if((mw = sep_win) && (mw->w_flags&W_MODE) &&
+	    (bw->w_pos == 0))		/* Base window is top window? */
+	  {				/* Use sep_win as mode wind */
+	  }
+	else
+#endif
+		mw = mode_win;		/* Default is normal mode window */
+	chg_win(mw);			/* Go to mode line window */
+	e_gobob();			/* go to beginning */
+	e_reset();			/* Flush buffer */
+#if IMAGEN
+	e_sputz(" ");
+	e_sputz(b->b_name);
+	if (b -> b_flags & B_MODIFIED)
+		e_sputz("*");
+	e_sputz(" (");
+	if (b->b_flags & B_QUERYREP)
+		e_sputz("[Query Replace] ");
+	if (b->b_flags & B_CMODE)
+		e_sputz("C");
+	else if (b->b_flags & B_TEXTMODE)
+		e_sputz("Text");
+	else
+		e_sputz("Fundamental");
+	e_sputz(")  ");
+	if (b->b_fn)
+		e_sputz(b->b_fn);
+	e_sputz("      ");
+#else
+	e_sputz(ev_verstr);		/* Editor name/version */
+	e_sputz(" (");
+	e_sputz(cur_mode->mjm_name);	/* insert major mode name */
+#if FX_FILLMODE
+	if(fill_mode) e_sputz(" Fill");
+#endif /*FX_FILLMODE*/
+#if FX_SKMAC
+	if(kdef_mode) e_sputz(" MacroDef");
+#endif /*FX_SKMAC*/
+	e_sputz(") ");
+	e_sputz(b->b_name);		/* buffer name */
+	e_sputz(": ");
+	if (b->b_fn)
+		e_sputz(b->b_fn);       /* file name */
+	if (b->b_flags & B_MODIFIED)
+		e_sputz(" *");
+	else	e_sputz("  ");
+#endif /*-IMAGEN*/
+	if(bw->w_pct < 200)		/* Not ALL? */
+	  {	e_sputz(" --");
+		switch(bw->w_pct)
+		  {	case -1:
+				e_sputz("TOP");
+				break;
+			case 150:
+				e_sputz("BOT");
+				break;
+			default:
+				dottoa(&temp[0],(chroff)bw->w_pct);
+				e_sputz(&temp[0]);
+				e_putc('%');
+		  }
+		e_sputz("--");
+	  }
+#if FX_SOWIND
+	if(mw->w_flags&W_STANDOUT)
+		e_insn(SP, (int)(scr_wd0 - e_blen()));	/* Stuff out with spaces */
+#endif
+
+	redp(RD_WINRES);
+	chg_win(savew);		/* Restore context */
+	chg_buf(saveb);
+	return(mw);		/* Return mode window */
+}
+
+
+buf_mod()
+{	register struct buffer *b;
+
+	b = cur_buf;
+	if((b->b_flags & B_MODIFIED) == 0)
+	  {	b->b_flags |= B_MODIFIED;
+		redp(RD_MODE);
+	  }
+}
+
+/* BUF_TMOD - called when text modified in buffer, to set all
+ *	the appropriate indicators so that redisplay works right.
+ *	Changed text is everything from CUR_DOT to the given offset
+ *	from same.  If stuff was deleted, offset should be 0.
+ * BUF_TMAT - similar but argument is location of other end of range,
+ *	when caller knows that and wants life easy.
+ */
+
+buf_tmat(dot)
+chroff dot;
+{	buf_tmod(dot - cur_dot);	/* Convert to offset */
+}
+buf_tmod(offset)
+chroff offset;
+{	register struct window *w;
+	chroff a, b, tmp;
+
+	w = cur_win;
+	a = cur_dot;
+	b = a + offset;
+	if(a > b)	/* Get into right order */
+	  {	tmp = a;
+		a = b;
+		b = tmp;
+	  }
+	b = e_blen() - b;	/* Make upper bound relative to EOB */
+	if(w->w_bmod < 0)	/* Have range vars been set yet? */
+	  {	w->w_bmod = a;	/* Nope, so can just set 'em now. */
+		w->w_emod = b;
+	  }
+	else
+	  {	if(a < w->w_bmod)
+			w->w_bmod = a;
+		if(b < w->w_emod)
+			w->w_emod = b;
+	  }
+	buf_mod();		/* Maybe later just insert here? */
+	redp(RD_TMOD);
+}
Index: /trunk/minix/commands/elle/eecmds.c
===================================================================
--- /trunk/minix/commands/elle/eecmds.c	(revision 9)
+++ /trunk/minix/commands/elle/eecmds.c	(revision 9)
@@ -0,0 +1,323 @@
+/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+
+/* EECMDS	Command table lookup and profile code
+ */
+
+#include "elle.h"
+
+/* Function table, see the included file for explanation. */
+
+	/* First must pre-declare function addrs */
+#define EFUN(rtn,rtnstr,name) int rtn();
+#define EFUNHOLE
+#include "eefdef.h"
+
+	/* Now re-insert to define function table */
+int (*funtab[])() =
+{
+#undef EFUN		/* Avoid redefinition error message */
+#undef EFUNHOLE
+#define EFUN(rtn,rtnstr,name) rtn,
+#define EFUNHOLE 0,
+#include "eefdef.h"
+};
+int funmax = sizeof(funtab)/sizeof(funtab[0]);	/* 1st illegal function # */
+
+/* Insert default command char map tables and profile structure */
+
+#include "defprf.c"
+
+
+/* EFUN: "Prefix Meta" */
+/*	Meta-prefix command.
+ *	For now, very simple.  Perhaps later try to hair up with
+ *	time-out "M-" prompt?
+ */
+f_pfxmeta()
+{	return(cmd_xct(cmd_read()|CB_META));
+}
+
+/* EFUN: "Prefix Extend" */
+/*	Extended-prefix command.
+ *	Likewise trivial; perhaps later hair up with timeout "^X-" prompt?
+ */
+f_pfxext()
+{	return(cmd_xct(cmd_read()|CB_EXT));
+}
+
+/* EFUN: "Universal Arg" */
+/*	This routine is also called by "Argument Digit" with a special arg
+ * of -1 in order to share code.  Since that invocation always sets unrchf,
+ * it should always complete at least one digit read loop.
+ * Note that exp and exp_p are set to 1 and 0 at the top-level command
+ * loop.
+ */
+f_uarg(ch)
+int ch;
+{	register int c, oc, i;
+
+	/* Set distinguishing exp_p value depending on whether invoked
+	 * by CTRL-U or another function (Argument Digit, Negative Argument)
+	 */
+	exp_p = (ch < 0) ? 1 : 4;
+	i = 0;			/* Read numerical arg if any follows */
+	for(;;)
+	  {	oc = cmd_read();	/* Get next input char */
+		c = oc & 0177;
+		if(c == '-' && !i)
+		  {	exp_p = -1;
+			exp = 1;	/* Set in case no digits follow */
+		  }
+		else if('0' <= c && c <= '9')	/* If it's a digit too, */
+		  {	i = (i * 10) + c - '0';	/* add digit in. */
+			if(exp_p >= 0) exp_p = 1;
+			exp = i;
+		  }
+		else break;
+	  }
+	exp *= exp_p;		/* Multiply arg appropriately */
+	unrchf = oc;		/* Not a digit, re-read it next. */
+
+	this_cmd = ARGCMD;
+}
+
+/* EFUN: "Negative Argument" */
+f_negarg(ch)
+int ch;
+{	f_uarg(-1);		/* Invoke code from Universal Arg */
+	exp = -exp;
+}
+
+/* EFUN: "Argument Digit" */
+f_argdig(ch)
+int ch;
+{	unrchf = ch;		/* Re-read the digit */
+	f_uarg(-1);		/* Invoke code from Universal Arg */
+}
+
+/* EFUN: "Set Profile" */
+/*	Asks for a profile file and sets profile from it.
+ */
+f_setprof()
+{	int set_profile();
+	hack_file("Set Profile: ", set_profile);
+}
+
+#if FX_VTBUTTONS
+/* EFUN: "VT100 Button Hack" */
+/*	This must be bound to Meta-O if anything, because the VT100 sends
+ *	an ESC O prefix when the function buttons are used.
+ */
+f_vtbuttons ()			/* vt100 function buttons */
+{
+	switch(cmd_read())
+	  {	case ('A'): 
+			return (f_uprline ());
+		case ('B'): 
+			return (f_dnrline ());
+		case ('C'): 
+			return (f_fword ());
+		case ('D'): 
+			return (f_bword ());
+		case ('Q'): 		/* PF1 */
+			return (f_kregion());
+		default: 
+			ring_bell ();
+		break;
+	  }
+}
+#endif /*FX_VTBUTTONS*/
+
+
+/* CMD_WAIT() - Return TRUE if any command input waiting.
+*/
+cmd_wait()
+{	return(unrchf >= 0
+#if FX_SKMAC
+		|| km_inwait()		/* Check for kbdmac input waiting */
+#endif /*FX_SKMAC*/
+		|| tinwait());
+}
+
+/* CMD_READ() - Read a command (single char) from user, and return it.
+*/
+cmd_read()
+{	register int c;
+
+	if((c = unrchf) >= 0)	/* Re-reading last char? */
+	  {	unrchf = -1;
+		return(c);
+	  }
+#if FX_SKMAC			/* Hacking keyboard macros? */
+	return(km_getc());	/* Yes.  This calls tgetc if no kbd macro */
+#else
+	return(tgetc());
+#endif /*-FX_SKMAC*/
+}
+
+/* CMD_XCT(ch) - Command Execution dispatch routine.
+**	Takes char and executes the function (efun) bound to that command key.
+*/
+cmd_xct(ch)
+int ch;
+{	register int (*funct) ();
+	register int c;
+	int (*(cmd_fun())) ();
+
+	if(funct = cmd_fun(c = ch))		/* Get function to run */
+		return((*funct) (c&0177));	/* Invoke with char arg */
+	ring_bell();		/* Undefined command char, error. */
+}
+
+/* CMD_FUN(ch) - Return function for char, 0 if none
+*/
+int (*cmd_fun(c))()
+int c;
+{
+	return(funtab[cmd_idx(c)]);
+}
+
+/* CMD_IDX(ch) - Given command char, return function index for it
+*/
+cmd_idx(c)
+register int c;
+{	register char *cp;
+	register int i;
+
+	if(c&CB_EXT)
+	  {	cp = def_prof.extvec;
+		i = def_prof.extvcnt;
+		goto inlup;
+	  }
+	if(c&CB_META)
+	  {	cp = def_prof.metavec;
+		i = def_prof.metavcnt;
+	inlup:	c = upcase(c);
+		do {	if(*cp++ != c) cp++;
+			else
+			  {	i = *cp&0377;
+				break;
+			  }
+		  } while(--i);		/* If counts out, will return 0! */
+	  }
+	else i = def_prof.chrvec[c&0177]&0377;
+	if(i >= funmax)
+		return(0);
+	return(i);
+}
+
+
+/* Profile hacking */
+
+#if TOPS20
+#include <sys/file.h>		/* for O_BINARY */
+#endif
+
+set_profile(filename)
+char *filename;
+{	char pfile[200];
+	char psfile[200];
+	register int pfd, len;
+	chroff sbx_fdlen();
+	register char *profptr;
+	struct stored_profile st_prof;
+
+	if(filename) strcpy(pfile,filename);
+	else		/* Check for user's profile */
+	  {
+		strcat(strcat(strcpy(pfile,homedir),"/"),ev_profile);
+	  }
+	if((pfd = open(pfile,
+#if TOPS20
+				O_BINARY
+#else
+				0
+#endif
+					)) < 0)
+	  {	if(filename)
+		  {	ding("Cannot open file");
+		  }
+		return;
+	  }
+	if((len = (int)sbx_fdlen(pfd)) < sizeof(struct stored_profile))
+		goto badfil;
+	profptr = memalloc((SBMO)len);
+	if(read(pfd,profptr,len) != len)
+		goto badfmt;
+
+	/* Have read profile into memory, now set up ptrs etc */
+	bcopy((SBMA)profptr,(SBMA)&st_prof,sizeof(struct stored_profile));
+	def_prof.version = prof_upack(st_prof.version);
+	if(def_prof.version != 1)
+		goto badfmt;
+	def_prof.chrvcnt = prof_upack(st_prof.chrvcnt);
+	def_prof.chrvec  = profptr + prof_upack(st_prof.chrvec);
+	def_prof.metavcnt = prof_upack(st_prof.metavcnt);
+	def_prof.metavec = profptr + prof_upack(st_prof.metavec);
+	def_prof.extvcnt = prof_upack(st_prof.extvcnt);
+	def_prof.extvec  = profptr + prof_upack(st_prof.extvec);
+#if SUN
+	def_prof.menuvcnt = prof_upack(st_prof.menuvcnt);
+	def_prof.menuvec = profptr + prof_upack(st_prof.menuvec);
+#endif /*SUN*/
+	goto done;
+
+badfmt:	chkfree(profptr);
+badfil:	ding("Bad profile format");
+done:	close(pfd);
+}
+
+
+#if SUN
+/* SUN Menu profile hacking.
+ *	This is here, instead of e_sun.c, because
+ * the profile format is still evolving and for the time being I want to
+ * keep all profile-hacking code in one place. --KLH
+ */
+#include "suntool/tool_hs.h"
+#include "suntool/menu.h"
+
+#define MENUMAX	16
+
+/* Defined in eesun.c */
+extern struct menu *menuptr;
+extern struct menu menu;
+
+char *funamtab[] = {
+#undef EFUN
+#undef EFUNHOLE
+#define EFUN(rtn,rtnstr,name) name,
+#define EFUNHOLE 0,
+#include "eefdef.h"
+};
+
+init_menu() /* initialize the menu for elle from user profile */
+{
+	register struct menuitem *mi;
+	register int n, i, fni;
+
+	if((n = def_prof.menuvcnt) <= 0)
+		return;
+	if(n > MENUMAX) n = MENUMAX;
+	mi = menu.m_items = (struct menuitem *) calloc(n, sizeof *mi);
+
+	menu.m_itemcount = 0;
+	for(i = 0; i < n; i++)
+	  {	fni = def_prof.menuvec[i]&0377;
+		if(fni >= funmax) continue;
+		if(funtab[fni] && funamtab[fni])
+		  {	mi->mi_data = (caddr_t) funtab[fni];
+			mi->mi_imagedata = (caddr_t) strdup(funamtab[fni]);
+			mi->mi_imagetype = MENU_IMAGESTRING;
+			mi++;
+			menu.m_itemcount++;
+		  }
+	  }
+	if(menu.m_itemcount)
+		menuptr = &menu;
+}
+#endif /*SUN*/
Index: /trunk/minix/commands/elle/eediag.c
===================================================================
--- /trunk/minix/commands/elle/eediag.c	(revision 9)
+++ /trunk/minix/commands/elle/eediag.c	(revision 9)
@@ -0,0 +1,356 @@
+/* ELLE - Copyright 1982, 1985, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*	EEDIAG - Error diagnostics and testing routines
+ */
+
+#include "elle.h"
+
+#if FX_DEBUG
+
+/* EFUN: "Debug Mode" */
+/*	With no arg, toggles self-checking on and off.
+ *	With arg of 4 (^U), enters special debug/diagnostics mode.
+ */
+
+f_debug(ch)
+int ch;
+{	extern int (*vfy_vec)();	/* In E_MAIN.C */
+	char *vfy_data();
+
+	if(ch < 0)		/* Internal call? */
+	  {	dbg_diag();
+		return;
+	  }
+	if(exp == 4)
+	  {	askerr();
+		return;
+	  }
+	if(vfy_vec) vfy_vec = 0;		/* Toggle current value */
+	else vfy_vec = (int (*)())vfy_data;
+	say(vfy_vec ? "Self-checking on" : "Self-checking off");
+}
+
+
+char *
+vfy_data(flag)		/* Flag = 0 for quiet check */
+int flag;
+{
+	register char *res, *mess;
+	char *sbe_mvfy(), *sbe_sbvfy(), *sbe_svfy();
+
+	if(res = sbe_mvfy(0)) mess = "Mem mgt";
+	else if(res = sbe_sbvfy(cur_buf,0)) mess = "SBBUF";
+	else if(res = sbe_svfy(0)) mess = "SD list";
+	else return(0);		/* Success */
+
+	if(flag)
+	  {	int ostate = clean_exit();
+		printf("\n%s error: %s !!!\n",mess,res);
+		askerr();
+		if(ostate > 0) set_tty();
+	  }
+	return(res);	/* Error seen */
+}
+
+
+extern char *asklin();
+extern int sbx_nfl,sbm_nfl;
+
+char diaghelp[] = "\
+Q - Quit diag mode\n\
+! - Goto subshell\n\
+V - Verify Mem & SD lists\n\
+MF - Mem Freelist\n\
+M  - Mem list\n\
+B  - Current buffer SB\n\
+DF - SD Freelist\n\
+D  - SDs in use\n\
+DL - SD Logical lists\n\
+DP - SD Physical lists\n\
+C n - Compact; 0-7=sbx_comp(n), 8=SM freelist, 9=SD freelist.\n\
+W  - Window printout\n\
+X n - Xercise randomly (GC every n)\n\
+Z n - like X but with notes\n";
+
+dbg_diag()
+{	register char *cp;
+	register int c;
+	char linbuf[100];
+	char *sbe_mfl();
+	char *sbe_sfl();
+	char *sbe_sbs();
+	char *sbe_sdlist();
+
+    for(;;)
+    {	printf("D>");
+	asklin(cp = linbuf);			/* Read a line of input */
+	switch(upcase(*cp++))
+	  {
+	case '?':
+		writez(1,diaghelp);	/* Too long for printf */
+		continue;
+	case '!':
+		f_pshinf();		/* Invoke inferior subshell */
+		clean_exit();		/* Restore normal modes */
+		continue;
+	case 'Q':		/* Quit */
+		return;
+
+	case 'B':		/* Print current SBBUF */
+		sbe_sbs(cur_buf,1);
+		continue;
+
+	case 'C':		/* C n - Compact */
+		c = atoi(&linbuf[1]);
+		if(c == 8)
+			sbm_ngc();	/* GC the SM nodes */
+#if 0 /* This doesn't work, dangerous to invoke. */
+		else if(c == 9)
+			sbm_xngc(&sbx_nfl,sizeof(struct sdblk),
+				SM_DNODS);
+#endif
+		else
+			sbx_comp(512,c);
+		continue;
+
+	case 'D':		/* Print all SD blocks in mem order */
+		switch(upcase(*cp))
+		  {
+		case 0:		/* D - all SDs in mem order */
+			sbe_sds();
+			continue;
+		case 'F':	/* DF - SD freelist */
+			sbe_sfl(1);
+			continue;
+		case 'L':	/* DL - SD logical list */
+			sbe_sdlist(1,0);
+			continue;
+		case 'P':	/* DP - SD physical list */
+			sbe_sdlist(1,1);
+			continue;
+		  }
+		break;		/* failure */
+
+	case 'M':	
+		switch(upcase(*cp))
+		  {
+		case 0:		/* M - all mem alloc info */
+			sbe_mem();
+			continue;
+		case 'F':	/* MF - mem freelist */
+			sbe_mfl(1);
+			continue;
+		  }
+		break;		/* failure */
+
+	case 'V':		/* Verify */
+		if(cp = vfy_data(0))
+			printf("  Failed: %s\n",cp);
+		else printf("  OK\n");
+		continue;
+	case 'W':		/* Print out current window */
+		db_prwind(cur_win);
+		continue;
+	case 'X':		/* Xercise */
+		c = atoi(&linbuf[1]);
+		vfy_exer(0, c ? c : 100);
+		continue;
+	case 'Z':		/* Zercise */
+		c = atoi(&linbuf[1]);
+		vfy_exer(1, c ? c : 100);
+		continue;
+
+	  }	/* End of switch */
+
+	printf("?? Type ? for help\n");
+    }	/* Loop forever */
+}
+
+
+
+/* VFY_EXER - a "random" editor exerciser.  It creates a buffer,
+ *	fills it with some patterned stuff, and then edits it
+ *	pseudo-randomly in ways which retain the basic pattern.
+ *	Frequent GC's and self-checks are done, and execution
+ *	halted either when an error is seen or when typein is detected.
+ */
+char *xer_strs [] = {
+	"throne", "too", "sky", "fore", "fingers", "sex", "stone",
+	"010", "nazgul", "base"
+};
+
+
+vfy_exer(pf, gcfrq)
+int pf;			/* Nonzero to print notes as we go */
+int gcfrq;		/* Frequency of GC invocation (# passes per GC) */
+{	register int i, k, c;
+	long npass;
+	char *res, linbuf[100];
+	chroff lbeg, lend;
+	struct buffer *bfp, *make_buf();
+
+	/* Clean out kill buffer first */
+	for(i = 0; i < KILL_LEN; ++i)
+		kill_push((SBSTR *)0);
+
+	bfp = make_buf("**EXORCISE**");
+	chg_buf(bfp);
+	i = 2000;
+	e_gobol();
+	do {
+		ed_sins("Line ");
+		ed_sins(xer_strs[i%10]);
+		e_putc(LF);
+	  } while(--i);
+	if(pf) printf("Bufflen: %ld\n", e_blen());
+
+	/* Buffer now has stuff in it, start hacking. */
+	npass = 0;
+	srand(1);	/* Start random seed */
+	for(;;)
+	  {	if(tinwait() && (*asklin(linbuf)))
+		  {	printf("Typein stop.\n");
+			break;
+		  }
+		++npass;
+		printf(" Pass %ld",npass);
+		if(npass%gcfrq == 0)		/* Time to do a GC? */
+		  {
+			i = rand();		/* Level between 0-4 */
+			i = (i < 0 ? -i : i) % 5;
+			printf(" - GC lev %d\n", i);
+			sbx_comp(512,i);
+			goto xerchk;
+		  }
+
+		k = (i = rand())%1024;
+		if (i&020000) k = -k;
+		e_igoff(k);		/* Move randomly */
+		e_gobol();		/* Get stuff to flush */
+		lbeg = e_dot();
+		k = (i = rand())%64;
+		if(i&010000) k = -k;
+		e_igoff(k);
+		lend = e_nldot();
+		if(pf) printf(" Kill %ld/ %d;", lbeg, k);
+		ed_kill(lbeg, lend);
+		if(res = vfy_data(0))
+		  {	printf("XERR after kill: %s\n",res);
+			break;
+		  }
+		k = (i = rand())%2048;
+		if(i&04000) k = -k;
+		e_igoff(k);
+		e_gobol();
+		e_setcur();
+		if(pf) printf(" Yank %ld;", e_dot());
+		f_unkill();		/* Yank back */
+		if(res = vfy_data(0))
+		  {	printf("XERR after yank: %s\n",res);
+			break;
+		  }
+		last_cmd = YANKCMD;
+		for(i = rand()%4; i >= 0; --i)
+		  {	if(pf) printf(" Pop;");
+			f_unkpop();	/* Do meta-Y */
+			if(res = vfy_data(0))
+			  {	printf("XERR after pop: %s\n",res);
+				goto out;
+			  }
+		  }
+		if(rand()&07)	/* Slowly add stuff */
+		  {	if(pf) printf(" Add");
+			ed_sins("Line ");
+			ed_sins(xer_strs[rand()%10]);
+			e_putc(LF);
+			if(res = vfy_data(0))
+			  {	printf("XERR after ins: %s\n",res);
+				break;
+			  }
+		  }
+		printf("\n");
+
+		/* Okay, done with this pass edits, run through the
+		 * file to ensure pattern is still there
+		 */
+	xerchk:	e_gobob();
+		while((c = e_getc()) != EOF)
+			if(c == LF && (c = e_getc()) != EOF)
+			  {	if(         c != 'L'
+				  || e_getc() != 'i'
+				  || e_getc() != 'n'
+				  || e_getc() != 'e'
+				  || e_getc() != ' ')
+				  {	printf("XERR in pattern!\n");
+					goto out;
+				  }
+			  }
+	  }
+	/* User typein or error, stop. */
+out:	e_setcur();
+	redp(RD_SCREEN);
+	printf("Loop count = %ld\n",npass);
+}
+
+
+/* DB_PRWIND(win) - Print out stuff about given window
+ */
+db_prwind(w)
+register struct window *w;
+{	register struct scr_line *s;
+	register int i;
+	char tstr[MAXLINE+MAXCHAR];
+	char *db_scflgs();
+
+	printf("cur_dot/ %ld  cur_buf/ %o cur_win/ %o\n",
+		cur_dot, cur_buf, cur_win);
+
+	printf("Window %o:\n", w);
+	printf("  next/ %o\n", w->w_next);
+	printf("  buf / %o\n", w->w_buf);
+	printf("  redp/ %o\n", w->w_redp);
+
+	printf("  topldot/ %ld\n", w->w_topldot);
+	printf("  dot / %ld\n", w->w_dot);
+	printf("  bmod/ %ld\n", w->w_bmod);
+	printf("  emod/ %ld\n", w->w_emod);
+	printf("  oldz/ %ld\n", w->w_oldz);
+
+	printf("  pos / %d\n", w->w_pos);
+	printf("  ht  / %d\n", w->w_ht);
+	printf("\
+#  Flags   Boff Len ! Cols Line\n");
+	for(i = w->w_pos; i < w->w_pos + w->w_ht; ++i)
+	  {	s = scr[i];
+		printf("%2d %-5.5s %6ld %3d %1d %4d ",
+			i, db_scflgs(s->sl_flg), s->sl_boff, s->sl_len,
+			s->sl_cont, s->sl_col);
+		strncpy(tstr, s->sl_line, MAXLINE);
+		tstr[s->sl_col] = 0;
+		printf("%-40.40s\n", tstr);
+		if(s->sl_flg&SL_MOD)
+		  {	printf("%26d ", s->sl_ncol);
+			strncpy(tstr, s->sl_nlin, MAXLINE);
+			tstr[s->sl_ncol] = 0;
+			printf("%-40.40s\n", tstr);
+		  }
+	  }
+}
+
+char *
+db_scflgs(flags)
+int flags;
+{	static char retstr[10];
+	register char *cp;
+	
+	cp = retstr;
+	if(flags&SL_MOD) *cp++ = 'M';
+	if(flags&SL_EOL) *cp++ = 'E';
+	*cp = 0;
+	return(retstr);
+}
+
+#endif /*FX_DEBUG*/
Index: /trunk/minix/commands/elle/eedisp.c
===================================================================
--- /trunk/minix/commands/elle/eedisp.c	(revision 9)
+++ /trunk/minix/commands/elle/eedisp.c	(revision 9)
@@ -0,0 +1,1727 @@
+/* ELLE - Copyright 1982, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/* EEDISP	Redisplay and screen image routines
+ */
+
+#if 0
+
+Note that there are several different types of "efficiency" criteria
+involved with respect to display updating:
+	(1) Terminal speed: minimize # characters output.
+	(2) Program speed: minimize CPU time used.
+	(3) Program size: minimize code and memory usage.
+	(4) Program modularity: minimize "hooks" between edit/display rtns.
+The current algorithms necessarily represent a compromise among all of
+these objectives.
+
+	The cursor is always located at CUR_DOT in the buffer CUR_BUF
+of the current window CUR_WIN.  This may not be true during function
+execution, but is always true at the top-level loop of command
+execution and redisplay.  In order to minimize update overhead, there
+are various flags or variables that the edit functions can use to
+communicate with "redisplay" and tell it how extensive the updates
+really need to be.
+
+	The entire known screen is always represented by a linked list
+of "windows"; updating the entire screen consists of separately
+updating every window on the list.  Windows can only be defined
+horizontally (as a range of lines), and must not overlap.  Each window
+has a buffer associated with it; the redisplay routines are responsible
+for displaying the contents of this buffer.
+
+	The lowest level data structure for the screen consists of an
+array of SCR_LINE structures, one for each possible physical screen
+line.  Each line structure has some flags, and pointers to three different
+representations of what should be on the line:
+	(1) SL_BOFF, SL_LEN - Defines the range of the buffer data which
+		this screen line should represent.
+		If the flag SL_EOL is set, this range ends with (and includes)
+		an EOL character.
+	(2) SL_LINE, SL_COL - Always keeps a copy of the current physical
+		screen line image.  Each byte is a character which occupies
+		only one column position on the screen.
+		If the flag SL_CSO is set, the line is in standout mode.
+	(3) SL_NLIN, SL_NCOL - The desired "new" screen line image.
+		This is only valid if the SL_MOD flag is set for the line,
+		indicating that these variables are set and point to the
+		new image of what the screen line should be.
+		If the flag SL_NSO is set, the new line should be in standout
+		mode.
+
+	Lastly there is a variable SL_CONT, which is needed for
+continuation of too-long logical lines over several physical lines.  If
+SL_CONT is:
+	0 = logical line fits entirely on the screen.
+		Either SL_EOL is set, or this line is ended by EOF
+		(end of the buffer).
+	1 = logical line is too long, but the last buffer char fits
+		entirely on this physical line.  SL_EOL is never set.
+	>1 = logical line is too long, and the last buffer char
+		"overruns" the end of the physical image; that is, part of
+		its representation is at the end of this line, but the
+		rest of it is at the start of the next line.  This can
+		only happen with "big" characters like TAB, ^A, ~^A, etc.
+		that need more than one column of representation.
+		There are SL_CONT-1 chars of overrun stored at the
+		end of SL_LINE (SL_NLIN if SL_MOD is set).
+		SL_EOL is never set.
+
+Note that if a line contains any overrun, and the next line is also
+part of the same window, the next line''s screen image will start with
+the SL_CONT-1 chars of overrun, rather than with the representation of
+that line''s first buffer char.
+
+	The "EOL" character on Unix systems is normally the new-line
+character '\n' (ASCII LF).  However, on other systems EOL may be
+indicated by a two-character CR-LF sequence, with either CR or LF alone
+considered to be "stray".  For this reason, the buffer flag B_EOLCRLF
+exists to control handling and display of EOLs.  If the flag is off,
+the EOL mode is LF, and there are no problems of splitting up characters.
+If the flag is on, however, the EOL mode is CRLF and the following rules
+hold:
+	EOL is the sequence CR-LF only.
+	LF without preceding CR is a "stray" LF, displayed as ^J.
+	CR without following LF is a "stray" CR, displayed as ^M.
+	Stray LFs and CRs do not terminate a logical line.
+	"End of Line" as a position is the dot just before the CR of a CR-LF.
+	"Beg of Line" as a position is the dot just after the LF of a CR-LF.
+	If the current dot is between a CR and LF, it is positioned at
+		the beginning of the physical screen line.
+
+
+SL_LINE and SL_COL are always accurate at every stage of processing.
+The other variables are accurate only after fix_wind has been called
+to "fix up" the line structures within a window.  If either
+RD_WINRES or RD_TMOD is set, none of these "other variables" should
+be depended on.  Any functions which are screen-relative (d_ type)
+must be sure that fix_wind is called if necessary, and must give
+preference to the "new" representation in SL_NLINE and SL_NCOL if
+SL_MOD is set.
+
+The flag RD_UPDWIN will be set by fix_wind if any lines have been
+modified.  Because fix_wind does not perform any actual display update,
+it is possible for functions to continue operating on the buffer and
+screen image without requiring that changes be displayed until there is
+nothing else left to do.  The routine upd_wind performs the actual
+terminal I/O necessary to update all the screen lines which have SL_MOD
+set.  Although the process of updating each line is currently
+non-interruptible, it is possible for upd_wind to interrupt itself
+between line updates if it detects that user input has happened, and it will
+return with the window only partially updated.  The screen image state
+will be completely consistent, however, and the RD_UPDWIN flag will
+remain set.
+
+Communication between the editing functions and the redisplay routines
+is limited as much as possible to the flags in the global RD_TYPE.
+Each window has its own copy of these flags in W_REDP, so that if
+windows are changed, the update hints for that window will be
+preserved.  The flags that can be set are listed below.  Those marked
+with "*" are global in nature; all others apply only within a single
+window (normally the current window).
+
+* RD_SCREEN - Total refresh.  Clears entire screen and redisplays all
+	windows.
+* RD_MODE - Mode line has changed, update it.
+* RD_CHKALL - Check ALL windows for any redisplay flags, and perform
+	any updates necessary.  Otherwise only the current (or specified)
+	window flags are checked.
+* RD_WINDS - Updates all windows.  Like RD_WINRES applied to all windows.
+  RD_WINRES - Update window (assume completely changed).
+  RD_TMOD - Text changed in this window.  The range of changes is
+	specified by W_BMOD and W_EMOD in combination with W_OLDZ.
+	Redisplay checking will limit itself to this range.
+	These vars are set by buf_tmod in the main command loop, and
+	reset by fix_wind when the window is fixed up.
+  RD_MOVE - Cursor has moved within current window; may have moved outside
+	the window.  W_DOT or CUR_DOT specifies where it should be.
+  RD_ILIN - Hint: Line insert done.  Currently no function sets this.
+  RD_DLIN - Hint: Line delete done.  Currently no function sets this.
+
+Internal flags:
+  RD_UPDWIN - Window needs updating. Used by fix_wind and upd_wind only.
+	Set when window has been "fixed up" and at least one screen
+	line was modified.
+  RD_FIXWIN - Supposed to mean window needs fixing (via call to fix_wind).
+	Not really used.
+
+Not implemented, may never be, but comments retained:
+  RD_WINCLR - Clear window (not entire screen)
+  RD_NEWWIN - Window has moved.  (not needed? Random stuff here)
+	a. to follow cursor; redisplay selects a new TOPLDOT.
+	b. randomly; new TOPLDOT furnished, use unless cursor out (then a).
+	c. find new TOPLDOT as directed (move up/down N screen lines)
+	For now, assume that (c) doesn''t apply (ie C-V uses (b) and sets
+	TOPLDOT itself).  So fix_wind selects new one only if cursor
+	won''t fit.  topldot takes precedence over sl_boff.
+
+#endif /*COMMENT*/
+
+
+/* Declarations and stuff */
+
+#include "elle.h"
+
+static int sctr();
+
+
+int trm_mode;	/* 0 = TTY in normal, non-edit mode.
+		 * 1 = TTY in edit mode.
+		 * -1 = TTY detached (hung up).
+		 * This flag is only used by the 3 routines below,
+		 * plus hup_exit.
+		 */
+
+/* REDP_INIT() - Called once-only at startup to initialize redisplay
+ *	and terminal
+ */
+redp_init ()
+{
+	trm_mode = 0;		/* Ensure flag says not in edit mode */
+	ts_init();		/* Get sys term info, set up stuff */
+	if (trm_ospeed == 0)	/* Default speed to 9600 if unknown */
+		trm_ospeed = 13;
+	t_init();		/* Identify term type, set term-dep stuff */
+	set_scr();		/* Set up software screen image */
+	set_tty();		/* Enter editing mode! */
+	redp(RD_SCREEN|RD_MODE); /* Force full re-display, new mode line */
+}
+
+/* SET_TTY() - Set up terminal modes for editing */
+
+set_tty()
+{	if(trm_mode) return;	/* Ignore if detached or in edit mode */
+	trm_mode++;
+	ts_enter();		/* Set up system's ideas about terminal */
+	t_enter();		/* Set terminal up for editing */
+}
+
+/* CLEAN_EXIT() - Restore original terminal modes.
+ *	Returns previous state.
+ */
+clean_exit ()
+{	register int prevstate = trm_mode;
+
+	if(prevstate > 0)	/* Ignore unless in editing mode */
+	  {	trm_mode = 0;
+		t_curpos(scr_ht-1, 0);	/* Go to screen bottom */
+		t_exit();		/* Clean up the terminal */
+		tbufls();		/* Force out all buffered output */
+		ts_exit();		/* Restore system's old term state */
+#if ! IMAGEN
+		writez(1,"\n");		/* Get fresh line using OS output */
+#endif /*-IMAGEN*/
+	  }
+	return prevstate;
+}
+
+/* SET_SCR() - Allocate screen image, set up screenline pointer table */
+
+set_scr()
+{	register struct scr_line **scrp, *stp;
+	register scrsiz;
+	char *sbuf;
+
+	scr_wd0 = scr_wid - 1;
+	scrsiz = scr_ht*(scr_wid+MAXCHAR);
+	if(  scr_ht  > MAXHT || scr_wid > MAXLINE)
+	  {	clean_exit();
+		printf("ELLE: %dx%d screen too big\n",scr_ht,scr_wid);
+		exit(1);
+	  }
+	if((stp = (struct scr_line *) calloc(scr_ht*sizeof(struct scr_line)
+							 + scrsiz*2,1)) == 0)
+	  {	clean_exit();
+		printf("ELLE: not enough memory\n");
+		exit(1);
+	  }
+	sbuf = (char *)stp + scr_ht*sizeof(struct scr_line);
+	for(scrp = &scr[0]; scrp < &scr[scr_ht]; sbuf += scr_wid+MAXCHAR)
+	  {	stp->sl_line = sbuf;
+		stp->sl_nlin = sbuf + scrsiz;
+		*scrp++ = stp++;
+	  }
+}
+
+
+/* REDISPLAY()
+ *	Main function of redisplay routines.  Called every time ELLE
+ * forces update of the terminal screen.  "rd_type" contains hints
+ * as to what has changed or needs updating, to avoid wasting time
+ * on things which don't need attention.
+ */
+redisplay ()
+{	register struct window *w;
+	register i;
+	struct window *make_mode();
+
+	w = cur_win;
+	w->w_redp |= rd_type&RDS_WINFLGS;	/* Set cur_win's flags */
+	rd_type &= ~RDS_WINFLGS;		/* Leave only globals */
+
+	if (rd_type & RD_SCREEN)		/* Clear and refresh? */
+	  {
+		t_clear ();			/* Clear the screen */
+		for(i = scr_ht; --i >= 0;)	/* Clear screen image */
+			scr[i]->sl_col = 0;
+		if(w != ask_win)		/* If not in ask-window */
+		  {	chg_win(ask_win);
+			e_reset();		/* Then flush its contents */
+			chg_win(w);
+		  }
+		redp(RD_WINDS);		/* Update all windows */
+		rd_type &= ~RD_SCREEN;	/* If redisplay is interrupted, */
+					/* don't do it all over again */
+	  }
+	if (rd_type & RD_WINDS)		/* Update all windows? */
+	  {	redp(RD_CHKALL);
+		for (w = win_head; w; w = w -> w_next)	/* For each win */
+			w->w_redp |= RD_WINRES;
+		rd_type &= ~RD_WINDS;
+	  }
+	if (rd_type & RD_CHKALL)	/* Check all windows for changes? */
+	  {	for (w = win_head; w; w = w->w_next)	/* For each win */
+		    if(!(w->w_flags&W_MODE))		/* skip mode wins */
+			if(w->w_redp && upd_wind(w))
+				return;		/* May be interrupted */
+
+	  }
+
+	/* See if ask-window needs updating (to avoid RD_CHKALL in SAY) */
+	if((w = ask_win)->w_redp && upd_wind(w))
+		return;				/* May be interrupted */
+
+	/* Check current window for changes */
+	if((w = cur_win)->w_redp && upd_wind(w))
+		return;				/* May be interrupted */
+
+	/* Now update mode line(s) if necessary */
+	if(rd_type&RD_MODE)
+	  {
+		fupd_wind(w = make_mode(user_win));
+#if FX_2MODEWINDS
+		if (sep_win			/* If 2 windows */
+		  && (sep_win->w_flags&W_MODE)	/* and 2 mode windows */
+		  && (sep_win->w_redp || mode_win->w_redp))	/* Check */
+			fupd_wind(make_mode(oth_win));	/* Must update both */
+#endif
+	  }
+
+	/* Finally, leave cursor in right place. */
+	if(upd_curs(cur_dot)==0)		/* If something screwed up, */
+		errbarf("Cursor out of window");	/* Complain, */
+						/* and leave cursor at bot */
+	rd_type = 0;
+	tbufls();		/* Force out all terminal output */
+}
+
+fupd_wind(w)		/* Force window update */
+register struct window *w;
+{
+	w->w_redp |= RD_WINRES;
+	if(fix_wind(w))
+		upd_wind(w);
+}
+
+
+/*
+ * UPD_CURS
+ *	Move screen cursor to position of specified dot within current window.
+ *	Returns 0 if dot was not within window (and cursor was not moved),
+ *	otherwise returns 1 for success.
+ */
+upd_curs(adot)
+chroff adot;
+{	register struct scr_line *s;
+	register int y, x;
+	chroff savdot;
+
+	if((y = d_line(adot)) < 0)
+		return(0);	/* Fail, not within window */
+	s = scr[y];		/* Now have line that dot is on */
+
+	/* Get proper offset for any continuation chars from prev line */
+	if(y > cur_win->w_pos)
+	  {	if((x = scr[y-1]->sl_cont) > 0)
+			x--;
+	  }
+	else x = 0;
+
+	savdot = e_dot();
+	e_go(s->sl_boff);
+	if((x = d_ncols((int)(adot - s->sl_boff),x)) < 0)
+	  {	/* If lost, assume it's because we are just after a char
+		** which has its representation continued onto next line.
+		** Move cursor to end of that continuation.
+		** d_line should have ensured that this is safe, but
+		** we double-check just to make sure.
+		*/
+		if((x = s->sl_cont) > 0)	/* Set X to end of cont */
+			--x;
+						/* and on next line down */
+		if(++y >= (cur_win->w_pos + cur_win->w_ht))
+		  {	e_go(savdot);		/* Failed, below window */
+			return(0);
+		  }
+	  }
+	e_go(savdot);
+	t_move(y, x);		/* Move cursor cleverly */
+	return(1);		/* Return success! */
+}
+
+/* Return line # for given dot, -1 if out of current window */
+d_line(cdot)
+chroff cdot;
+{	register struct scr_line *s;
+	register struct window *w;
+	register int i;
+	chroff savdot;
+	int bot;
+
+	w = cur_win;
+	i = w->w_pos;
+	bot = i + w->w_ht;
+	for(; i < bot; i++)
+	  {	s = scr[i];
+		if(cdot <= s->sl_boff)
+			goto gotl;
+	  }
+	/* End of window, repeat test specially for last line */
+	savdot = s->sl_boff + (chroff)s->sl_len;
+	if(cdot > savdot)	/* If past last char of last line */
+		return(-1);	/* then clearly outside */
+	--i;			/* Make i match s (bottom line) */
+	if(savdot != cdot)	/* If not exactly at end */
+		return(i);	/* Then we're inside for sure */
+	goto linbet;
+
+gotl:	if(s->sl_boff != cdot)	/* Are we on line boundary? */
+	  {	if(i <= w->w_pos)	/* No, off top of window? */
+			return(-1);	/* Above top, out for sure */
+		return(--i);
+	  }
+
+	/* Here, dot is exactly on line boundary, have to decide which
+	 * line it really belongs to.
+	 * Get S = pointer to line which cursor is at the end of.
+	 */
+	if(i <= w->w_pos)	/* Quick chk of trivial case, empty buffer */
+		return(i);
+	s = scr[--i];
+linbet:
+	if((s->sl_flg&SL_EOL)	/* If line has LF */
+	  || (s->sl_cont > 1))	/* or a continued char */
+		if(++i >= bot)		/* Then cursor is on next line */
+			return(-1);
+	return(i);
+}
+
+
+/* D_NCOLS - auxiliary for UPD_CURS.  (also called by indtion() in EEFD)
+**	 We are positioned at a place in the current buffer corresponding to
+** the beginning of the screen line, and given:
+**	lcnt - # of chars in buffer to move forward over
+**	ccol - current column position
+** Returns the new column position.  There are some special cases:
+**	Hits EOF: returns normally (new column position)
+**	Hits EOL: returns -1
+**	Position is past end of screen: returns -1
+** The buffer position has changed, but this is irrelevant as upd_curs
+** restores it just after the call.
+*/
+d_ncols(lcnt, ccol)
+int lcnt;
+int ccol;
+{	register int col, i;
+	register SBBUF *sb;
+	int c;
+	char tmp[MAXCHAR*2];	/* MAXCHAR is enough, but *2 just in case */
+
+	col = ccol;
+	sb = (SBBUF *) cur_buf;
+	if((i = lcnt) > 0)
+		do {	if((c = sb_getc(sb)) == EOF)
+				break;
+			/* Check to see if we've run into an EOL */
+#if FX_EOLMODE
+			if(c == CR)
+			  {	if(eolcrlf(sb))
+				  {	if((c = sb_getc(sb)) == LF) /* EOL? */
+					/* Real EOL.  Fail unless point
+					** is between CR and LF, in which case
+					** we return 0 (left margin).
+					*/
+					    return (i==1 ? 0 : -1);
+					/* Stray CR, back up & fall thru */
+					if(c != EOF)
+						sb_backc(sb);
+					c = CR;
+				  }
+			  } else if (c == LF)
+			  {	if(!eolcrlf(sb))	/* Real EOL? */
+					return -1;	/* Yes, fail */
+				/* If EOL mode is CRLF then hitting a LF
+				** can only happen for stray LFs (the
+				** previous check for CR takes care of
+				** CRLFs, and we never start scanning
+				** from the middle of a CRLF.
+				** Drop thru to show stray LF.
+				*/
+			  }
+#else
+			if(c == LF)
+				return(-1);
+#endif /*-FX_EOLMODE*/
+			col += sctr(c, tmp, col);
+		  } while(--i);
+	if(col > scr_wd0)
+		return(-1);
+	return(col);
+}
+
+/* D_LUPD - called from command level to completely redisplay a
+ *	specific line on the screen.
+ */
+d_lupd(w, idx)
+struct window *w;		/* Window this line belongs to, if known */
+int idx;
+{	t_curpos(idx, 0);
+	t_docleol();		/* Zap physical screen line */
+	scr[idx]->sl_col = 0;	/* Reflect it on phys screen image */
+	if(w)			/* Mark window for updating */
+		w->w_redp |= RD_WINRES;
+	else redp(RD_WINDS);	/* No window given, assume global */
+	redp(RD_MOVE);		/* Cursor has moved */
+}
+
+/* Clear a window completely the "quickest possible way" */
+clear_wind(w)
+register struct window *w;
+{
+	register int i = w->w_pos;	/* Top line of window */
+	register int bot = i + w->w_ht;	/* Bottom line (plus 1) of window */
+
+	for ( ; i < bot; ++i)
+		d_lupd(w, i);		/* Zap that line */
+}
+
+
+/* FIX_WIND - Sets up window screen image.  Does not generate any
+ *	terminal output, but completely specifies what the new screen
+ *	image should look like.
+ *	Only the following 4 flags (lumped together in RDS_DOFIX)
+ *	provoke fix_wind to do something:
+ *		RD_MOVE - cursor has moved, must make sure still within
+ *			window, and select new one if not.
+ *		RD_TMOD - Text has been changed somewhere.
+ *		RD_FIXWIN - Something requested that fix_wind fix things.
+ *			Normally this is set when a new w_topldot is set.
+ *		RD_WINRES - Window needs to be completely regenerated.
+ * Results:
+ *	Verifies that the current dot for the window (w_dot) exists.
+ * If it is past the end of buffer, it is reset to EOB, and if this is
+ * the current window, also updates cur_dot.  Otherwise, w_dot is never
+ * adjusted; it is fix_wind's responsibility to make sure that the window
+ * displays w_dot.
+ *	Verifies that current w_topldot setting will result in cursor
+ * (specified by w_dot) appearing within window.  If not, resets w_topldot
+ * to an appropriate value (1/3 of way down from top, unless
+ * moving up in which case 1/3 of way up from bottom).
+ *	Makes sure that sl_boff, sl_len, sl_flg, and sl_cont
+ * are set properly for all lines in window.  SL_MOD is set
+ * for any lines requiring screen updates; these lines
+ * also have sl_nlin and sl_ncol properly set.
+ *	Note that sl_line and sl_col are NOT updated or changed, because
+ * the physical screen has not been altered!
+ *
+ *	Returns 0 if no physical screen updates are needed (other than
+ *		cursor moving and mode line updating).
+ *	Returns 1 if screen updates are needed; RD_UPDWIN is set in w_redp,
+ *		indicating that UPD_WIND should be called.
+ */
+
+fix_wind (win)
+struct window *win;
+{
+	register struct window *w;
+	register int i;
+	register struct scr_line *s;
+	chroff cdot, bdelta, updot, sdot, newz;
+	chroff savdot;
+	struct buffer *savbuf;
+	int bot, nlmod, savi, contf, ocontf, randomflg;
+	int newpct;
+
+	if(!(w = win))
+		return(0);
+	if(!(w->w_redp&RDS_DOFIX))	/* Anything we need to do? */
+		return(0);		/* Nope, just ignore */
+
+	/* Find current dot for this window, and set up other stuff */
+	cdot = (w == cur_win) ? cur_dot : w->w_dot;
+	bot = w->w_pos + w->w_ht;
+	savbuf = cur_buf;
+	cur_buf = w->w_buf;
+	savdot = e_dot();
+	nlmod = 0;			/* No screen image changes so far */
+
+	/* Dot (ie cursor) is before current top?  If so, must move
+	 * backwards to find a new topldot.  Note also that buffer may have
+	 * changed so that either cdot or topldot points past EOF.
+	 */
+	if(w->w_topldot > cdot)
+	  {	/* Yes, must search backwards scrht/3 screen lines */
+		/* from cdot in order to find topldot. */
+		/* Don't bother updating scr stuff beforehand since we'll
+		 * have to revise everything anyway and can do it on the fly.
+		 */
+		i = (ev_mvpct * w->w_ht) / 100;
+		goto skipdn;
+
+	finddn:	i = ((100 - ev_mvpct) * w->w_ht) / 100;
+	skipdn:	if(i <= 0) i = 1;	/* Ensure # is reasonable */
+		else if(i >= w->w_ht) i = w->w_ht-1;
+		e_go(cdot);		/* Start here (may normalize to EOF)*/
+		d_backup(i ? i : 1);	/* Try to back up cleverly */
+		w->w_topldot = e_dot();
+		randomflg = 0;		/* We have some idea where we are */
+	fixall:		/* Entry point for later recheck, with randomflg==1 */
+		newz = e_blen();
+		if(newz < cdot)		/* Part of buf may have gone away */
+		  {			/* So normalize dot to EOF */
+			w->w_dot = cdot = newz;
+			if(w == cur_win)	/* Special check for fixing */
+				cur_dot = newz;	/* up cur_dot too! */
+			goto finddn;	/* and get a new top-of-window loc */
+		  }
+	retry:	i = w->w_pos;
+		contf = 0;
+		s = 0;
+		for(; i < bot; i++)
+		  {	nlmod++;
+			fix_line(scr[i], s);	/* s = 0 the first time */
+			s = scr[i];
+#if FX_SOWIND
+			if(w->w_flags & W_STANDOUT)
+				s->sl_flg |= SL_NSO;
+			else s->sl_flg &= ~SL_NSO;
+#endif
+		  }
+		if(inwinp(w,cdot))	/* Ensure in window */
+			goto mdone;
+		if(randomflg)		/* If jumped randomly, */
+		  {	i = (ev_nwpct * w->w_ht) / 100;
+			goto skipdn;	/* Try to select new window */
+		  }
+
+		/* We tried to back up and went too far. */
+		if(cdot < w->w_topldot)	/* Verify place is ahead */
+		  {	errbarf("fix_wind failed");	/* Didn't back up?? */
+			goto finddn;
+		  }
+		/* Move down one line and try again */
+		if(w->w_ht > 1)
+			w->w_topldot = scr[w->w_pos+1]->sl_boff;
+		else
+		  {	s = scr[w->w_pos];
+			w->w_topldot = s->sl_boff + s->sl_len;
+		  }
+		e_go(w->w_topldot);
+		goto retry;
+	  }
+
+	/* At some future point, could separate out processing for
+	 * RD_WINRES and RD_FIXWIN.  Latter flag implies only w_topldot
+	 * has changed (new window selected).  Former implies whole
+	 * buffer has been munged, and everything is completely redone.
+	 */
+	if(w->w_redp&(RD_WINRES|RD_FIXWIN))	/* If re-figuring whole window */
+	  {	e_go(w->w_topldot);	/* Start here, and */
+		randomflg = 1;		/* set up flag saying random jump */
+		goto fixall;		/* and go crunch all lines. */
+	  }
+	if((w->w_redp&RD_TMOD)==0)	/* If claims no text mods, */
+	  {	if(inwinp(w,cdot)==0)	/* Just verify cursor loc. */
+			goto finddn;	/* Sigh.... */
+		newz = w->w_oldz;	/* Win, set up for exit. */
+		goto done;
+	  }
+	/* Here only when RD_TMOD is set, indicating changes are
+	 * between range variables.
+	 */
+	/* Find upper bound of any mods.  This is a little gross in the
+	 * speed dept and some faster way should perhaps be devised.
+	 * In particular the main loop should incrementally keep track of
+	 * buffer size, and should set a flag RD_TEXT if anything has
+	 * actually been changed.  Edit routines should have lots of
+	 * flags available to tell main loop more precisely what they did,
+	 * so main loop can take care of updating b/emod and stuff.
+	 */
+	if((newz = e_blen()) == 0)
+		goto finddn;		/* Ensure blank window is cleared */
+	bdelta = newz - w->w_oldz;
+	if((updot = newz) > w->w_emod)
+		updot -= w->w_emod;
+	if(bdelta == 0 && (updot == w->w_bmod))
+		goto inwinq;
+
+	/* Could also check for updot < w_topldot (changes above win)
+	 * or sl_boff+sl_len < w_bmod  (changes below win) but those
+	 * cases are probably pretty rare.
+	 */
+	/* First find line where changes start */
+	for(i = w->w_pos; i < bot; i++)
+	  {	s = scr[i];
+		if(w->w_bmod <= s->sl_boff)	/* Changes prior to this? */
+			break;
+	  }
+	if(i >= bot)			/* Test last line specially */
+	  {	if(w->w_bmod > (s->sl_boff + (chroff)s->sl_len))
+			goto inwinq;	/* Outside window */
+					/* Last line changed, hack it */
+	  }
+	if(i > w->w_pos			/* If we have a prev line */
+	  && (s->sl_len == 0		/* and we're at EOF, */
+	    || w->w_bmod != s->sl_boff	/* or not at start of line */
+	    || scr[i-1]->sl_cont))	/* or prev line is continuation */
+		s = scr[--i];		/* then it's prev line we want */
+
+	/* I has index for screen line changes begin on; S has ptr.
+	 * This piece of code handles case where buffer has been modified
+	 * starting at BMOD, and BDELTA chars have been inserted/deleted;
+	 * range of changes ends at UPDOT.
+	 */
+	savi = i;
+	while(++i < bot)
+		scr[i]->sl_boff += bdelta;
+	i = savi;
+
+	/* Now start with 1st changed line and start figuring new line
+	 * lengths.  Stop when hit end, or past updot and boff is correct
+	 * for start of line.
+	 */
+	/* can improve this by jumping out when past emod, and testing for
+	 * an EOL - then know stuff has to match someplace, so look for that.
+	 * could then simply update lengths or something?
+	 */
+	if(i > w->w_pos)	/* Find # cols already there from prev line*/
+		contf = scr[i-1]->sl_cont;
+	else contf = 0;
+	ocontf = 1;			/* Fake it so always update 1st line*/
+	e_go(sdot = s->sl_boff);
+	for(; i < bot; i++)
+	  {	s = scr[i];
+		if(updot <= sdot	/* If past changed stuff */
+		  && sdot == s->sl_boff	/* and locs are lined up */
+		  && contf == 0		/* and previous line clean */
+		  && ocontf == 0)	/* (both old and new images) */
+			break;		/* Then done. */
+		nlmod++;
+		ocontf = s->sl_cont;	/* Save old-image contf value */
+		fix_line(s, (i > w->w_pos) ? scr[i-1] : 0);
+#if FX_SOWIND
+		if(w->w_flags & W_STANDOUT)
+			s->sl_flg |= SL_NSO;
+		else s->sl_flg &= ~SL_NSO;
+#endif
+		sdot = e_dot();
+		contf = s->sl_cont;	/* Get new-image contf value */
+	  }
+	if(inwinp(w,cdot))	/* OK, screen fixed, see if cursor inside */
+		goto mdone;
+	goto finddn;
+
+	/* Test if still in window and dispatch appropriately */
+inwinq:	if(inwinp(w,cdot))
+		goto done;
+	else goto finddn;
+
+	/* Come here when done, after mods made to window.
+	 * Calculate new %-of-buffer position for window's view, and
+	 * see if it's changed from current %.
+	 */
+mdone:	if(w != cur_win) goto done;	/* If not current window, ignore */
+	s = scr[bot-1];
+	if((s->sl_boff + (chroff)s->sl_len) >= newz)
+		if(w->w_topldot) newpct = 150;	/* BOT */
+		else newpct = 200;		/* ALL */
+	else if(w->w_topldot == 0)
+		newpct = -1;			/* TOP */
+	else		/* NOTE: This won't work if topldot is huge */
+		newpct = (w->w_topldot*100)/newz;	/* nn% */
+	if(newpct != w->w_pct)		/* OK, now compare with old % */
+	  {	w->w_pct = newpct;	/* Different, must set and */
+		redp(RD_MODE);		/* invoke redisplay of mode line! */
+	  }
+
+done:	w->w_bmod = -1;		/* To indicate vars not set */
+	w->w_oldz = newz;
+	w->w_redp &= ~RDS_DOFIX;	/* Clear flags that invoked us */
+	if(nlmod)
+		w->w_redp |= RD_UPDWIN;	/* Say stuff to be updated */
+	e_go(savdot);
+	cur_buf = savbuf;
+	return(nlmod);
+}
+
+/* INWINP - Returns true if given dot is inside given window.
+ */
+inwinp(win,cdot)
+struct window *win;
+chroff cdot;
+{	register struct scr_line *s;
+	register struct window *w;
+	chroff sdot;
+
+	w = win;
+	if(cdot < w->w_topldot)
+		return(0);
+	s = scr[(w->w_pos + w->w_ht) - 1];
+	sdot = s->sl_boff + (chroff)s->sl_len;
+	if(cdot < sdot)
+		return(1);		/* Yup, inside window. */
+	if(cdot > sdot)
+		return(0);
+
+	/* Dot is exactly at end of window, must check further. */
+	if(s->sl_len		/* If line exists, */
+	 && ((s->sl_flg&SL_EOL)	/* and ends in LF, */
+	    || s->sl_cont > 1))	/* or sl_cont > 1, lose. */
+		return(0);
+	return(1);		/* Else inside, win. */
+}
+
+
+/*
+ * UPD_WIND
+ *	If argument 0, assumes cur_win and DOESN'T interrupt if input
+ *	detected.
+ */
+
+upd_wind(win)
+struct window *win;
+{	register int i, n;
+	register struct scr_line *s;
+	struct window *w;
+	int top, bot, dspf, num, isave, noicost, nodcost, iline, dline;
+#if FX_SOWIND
+	int oldso;
+#endif
+#if IMAGEN
+	int origdspf;
+	char redpmsg[128];
+#endif /*IMAGEN*/
+
+	if((w=win)==0)
+		w = cur_win;
+	dspf = w->w_redp;		/* Get update flags for window */
+#if IMAGEN
+	origdspf = dspf;
+#endif /*IMAGEN*/
+	if(w == cur_win)		/* If updating current window, */
+		dspf |= rd_type;	/* merge in global flags */
+	if((dspf &= RDS_WINFLGS) == 0)	/* Well, it might happen sometimes */
+		goto zdone;
+	w->w_redp = dspf;
+	if(dspf&(RD_WINRES|RD_TMOD|RD_MOVE|RD_FIXWIN))
+	  {	fix_wind(w);		/* May set some flags, so */
+		dspf = w->w_redp;	/* get them back... */
+	  }
+	if((dspf&RD_UPDWIN)==0)		/* Must ask for update! */
+		goto zdone;
+#if IMAGEN
+	if (dbg_redp)
+	  {	sprintf(redpmsg,
+			"buffer: %14s, rd_type: %06o, w_redp: %06o, dspf: %06o",
+			w->w_buf->b_name, rd_type, origdspf, dspf);
+		barf2(redpmsg);
+	  }
+#endif /*IMAGEN*/
+
+	/* Assume screen structure set up by FIX_WIND, just go
+	 * effect change for every line modified.
+	 */
+#if FX_SOWIND
+	oldso = t_dostandout((w->w_flags&W_STANDOUT)? 1:0);
+#endif
+	top = w->w_pos;
+	bot = top + w->w_ht;
+	for(i = top; i < bot; ++i)
+	  if((s = scr[i])->sl_flg&SL_MOD)
+	  {	if(win && tinwait())	/* If OK, stop if any chars typed */
+		  {	tbufls();
+			w->w_redp = dspf;
+#if FX_SOWIND
+			t_dostandout(oldso);
+#endif
+			return(1);	/* Return immediately, say int'd */
+		  }
+		if(slineq(s,s))		/* Compare old with new */
+			goto ldone;	/* Lines equal, no update needed */
+	
+#if IMAGEN
+		/* If hint says redo entirely */
+		if (dspf & RD_REDO)
+		  {	s->sl_flg |= SL_REDO;	 /* Do "fast update" */
+			goto nodel;		/* Just go update line */
+		  }
+#endif /*IMAGEN*/
+		if((trm_flags&TF_IDLIN)==0)
+			goto nodel;		/* Just go update line */
+
+
+		/* Check for I/D line.  If no hints exist, check for both
+		 * insert and delete.
+		 */
+		if((dspf&(RD_ILIN|RD_DLIN))==0)
+			dspf |= RD_ILIN|RD_DLIN;
+		noicost = 0;
+		nodcost = 0;
+
+		/* Check for insert line.  See if the current old screen
+		 * line is duplicated among any of the new lines which
+		 * follow it.  If a match is found, keep looking and add
+		 * up the number of characters in the matching lines.
+		 */
+		if(dspf&RD_ILIN)
+		  {
+			/* See if this old screen line is needed elsewhere */
+			if(s->sl_col == 0)	/* Ignore if blank */
+				goto noins;
+			
+			for(n = i+1; n < bot; n++)
+			  {	if((scr[n]->sl_flg&SL_MOD)==0)
+					break;
+				if(slineq(s, scr[n]))	/* Old, new */
+				  {	if(!noicost) iline = n;	/* 1st time */
+					noicost += s->sl_col;
+					s++;
+				  }
+				else if(noicost) break;
+			  }
+			if(!noicost)		/* If no match, forget it */
+				goto noins;	/* S will not have changed. */
+			s = scr[i];		/* Restore S */
+			n = iline;		/* Have matches, get index
+						 * of first matching line */
+
+			/* Heuristic to decide whether to perform
+			 * insert-line operation.  Kind of stupid, but
+			 * good enough for now.
+			 */
+			num = (n-i)*(tvc_ldn+tvc_lin) + (tvc_li + tvc_ld);
+			if((n-i) >= (scr_ht-(ECHOLINES+3))
+						/* Don't move lines all the
+						 * way down full screen! */
+			  || num >= noicost)	/* Compare cost with estimated
+						 * cost of not doing insert.*/
+				goto noins;
+
+			/* Insert lines! */
+			dspf &= ~RD_ILIN;
+			inslin(i, n - i, w);
+			for(; i < n; i++)	/* Update intervening lines */
+				upd_line (i);
+			goto ldone;
+		  }
+noins:
+
+		/* Check for delete line.  See if the new screen line
+		 * is duplicated among any of the old lines already on
+		 * the screen.  If a match is found, keep looking and add
+		 * up the number of characters in the matching lines.
+		 */
+		if(dspf&RD_DLIN)
+		  {
+			/* See if the new line already exists elsewhere */
+			if(s->sl_ncol == 0)	/* Ignore blank lines */
+				goto nodel;
+			for (n = i + 1; n < bot; n++)
+			  {	if((scr[n]->sl_flg&SL_MOD)==0)
+					break;
+				if(slineq(scr[n],s))	/* Old, new */
+				  {	if(!nodcost) dline = n;	/* 1st time */
+ 					nodcost += s->sl_ncol;
+					s++;
+				  }
+				else if(nodcost) break;
+			  }
+			if(!nodcost)		/* If no match, forget it */
+				goto nodel;	/* S will not have changed. */
+			s = scr[i];		/* Restore S */
+			n = dline;		/* Index of 1st match */
+
+			/* Heuristic to decide whether to perform
+			 * delete-line operation.  Same hack as for
+			 * insert-line.
+			 */
+			num = (n-i)*(tvc_ldn+tvc_lin) + (tvc_li + tvc_ld);
+			if((n-i) >= (scr_ht-(ECHOLINES+3))
+			  || num >= nodcost)
+				goto nodel;
+
+			/* Delete lines! */
+			dspf &= ~RD_DLIN;
+			dellin(i, n - i, w);
+			goto ldone;
+		  }
+nodel:
+		/* All failed, so just update line */
+		upd_line(i);
+ldone:		s->sl_flg &= ~SL_MOD;	/* Clear mod flag */
+	  }
+done:
+#if FX_SOWIND
+	t_dostandout(oldso);	/* Back to previous mode */
+#endif
+zdone:	w->w_redp = 0;
+	return(0);		/* Say completed */
+}
+
+
+
+/*
+ * SLINEQ - Compare old, new screen image lines.  If new line doesn't
+ *	have the modified flag set, use its old image.
+ *	If the standout mode differs, always fails.
+ */
+
+slineq(olds, news)
+struct scr_line *olds;
+struct scr_line *news;
+{	register char *cpo, *cpn;
+	register int cnt;
+
+	cpo = (char *)news;
+	if(((struct scr_line *)cpo)->sl_flg&SL_MOD)
+	  {	cnt = ((struct scr_line *)cpo)->sl_ncol;
+		cpn = ((struct scr_line *)cpo)->sl_nlin;
+#if FX_SOWIND		/* Mode of old must match mode of new */
+		if(((olds->sl_flg & SL_CSO)==0) !=
+			((((struct scr_line *)cpo)->sl_flg & SL_NSO)==0))
+			return 0;
+#endif
+	  }
+	else
+	  {	cnt = ((struct scr_line *)cpo)->sl_col;
+		cpn = ((struct scr_line *)cpo)->sl_line;
+#if FX_SOWIND		/* Modes of current lines must match */
+		if((olds->sl_flg & SL_CSO) !=
+			(((struct scr_line *)cpo)->sl_flg & SL_CSO))
+			return 0;
+#endif
+	  }
+
+	/* Crufty match stuff */
+	if(cnt != olds->sl_col)
+		return(0);
+	if(cnt)
+	  {	cpo = olds->sl_line;
+		do { if(*cpo++ != *cpn++)
+			return(0);
+		  } while(--cnt);
+	  }
+	return(1);
+}
+
+
+/* UPD_LINE(lineno) - Effects the update of a physical screen line,
+ *	assuming that the screen line structure for that line has been
+ *	properly set up by fix_wind.  It cannot be interrupted by typein.
+ *	Does a lot of work to check out optimization for char I/D.
+ *	Someday it could also check out the possibility of doing a CLEOL at
+ *	some point to reduce the number of spaces that need to be output.
+ */
+
+upd_line(y)
+int y;
+{	register i;
+	register char *sci, *cp;
+	struct scr_line *s;
+
+	int xpos;			/* actual screen position */
+	int c, c2, p2, cmpcost, delcost;
+	int savc, ocol, ncol;
+	char *savcp, *savsci;
+#if FX_SOWIND
+	int oldso, newso;
+	int writall = 0;
+#endif
+
+	s = scr[y];
+	savsci = sci = s->sl_line;	/* What is currently on the screen */
+#if IMAGEN
+	if (s->sl_flg & SL_REDO)
+	  {	/* Check for line-redo flag */
+		s->sl_flg &= ~SL_REDO;	/* Clear it: we are handling it */
+		writall = 1;	/* Re-do this line completely */
+		t_move(y, 0);
+		t_docleol();
+		s->sl_col = 0;
+	  }
+#endif /*IMAGEN*/
+
+#if FX_SOWIND
+	/* See whether modes of the lines are the same or not. */
+	newso = (s->sl_flg & SL_NSO)!=0;	/* Get new mode (true if SO)*/
+	if(((s->sl_flg & SL_CSO)!=0) !=	newso)
+	  {	t_move(y, 0);		/* Not same, must zap existing line */
+		t_docleol();
+		s->sl_col = 0;
+		writall = newso;	/* Output all if SO is new mode */
+	  }
+	oldso = t_dostandout(newso);	/* Get in right mode */
+#endif
+
+	ocol = s->sl_col;
+	savcp = cp = s->sl_nlin;
+	ncol = s->sl_ncol;
+
+	/* Find leading equalness */
+	i = ocol;
+	if(i > ncol) i = ncol;		/* Use minimum count */
+	if(i)
+	  {	do { if(*cp++ != *sci++)
+			  {	--cp;
+				break;
+			  }
+		  } while(--i);
+		i = cp - savcp;
+		sci = savsci;		/* Restore ptr to beg of cur line */
+	  }
+
+	/* From here on, "i" is now the x-coordinate (column addr)
+	 * of the first position that doesn't match.  "cp" points to
+	 * the first nonmatching char in the new line image.
+	 */
+#if COHERENT		/* Has direct video interface capability */
+	if(trm_flags&TF_DIRVID)
+	  {	if(ncol < ocol)
+		  {	/* Flesh out new line to completely replace old */
+			fillsp(&s->sl_nlin[ncol], ocol-ncol);
+			ncol = ocol;
+		  }
+		/* Spit out changed stuff.  t_direct will handle the
+		 * case where i == ncol (ie no changes needed).
+		 */
+		t_direct(y,i,cp,ncol-i);
+		goto done;
+	  }
+#endif /*COHERENT*/
+
+	if(i == ncol)			/* Matched up to end of new line? */
+		goto idone;		/* Yes, can skip big loop! */
+
+#if FX_SOWIND
+	if(writall)			/* If simply writing everything...*/
+	  {	t_move(y, 0);
+		tputn(cp, ncol);	/* Output them all */
+		curs_col = ncol;	/* Update cursor position */
+		goto idone;		/* then wrap up! */
+	  }
+#endif
+
+	/* Now must fill out remainder of old line with blanks. */
+	if(ocol < scr_wid)
+	  {
+#if FX_SOWIND
+		if(newso) fillset(&sci[ocol], scr_wid-ocol, 0);
+		else
+#endif
+		fillsp(&sci[ocol],scr_wid-ocol);	/* Fill out */
+	  }
+
+	/******  Main update loop. ******/
+	for (; i < ncol; i++)
+	  {	c = *cp++;		/* Note *CP will point to next */
+		if(c == sci[i])
+			continue;
+		if(i >= ocol)		/* Past EOL of old line? */
+		  {
+putin:			sci[i] = c;
+			if(y != curs_lin || i != curs_col)
+				t_move(y, i);
+			tput(c);
+			curs_col++;
+			continue;
+		  }
+
+		if((trm_flags&TF_IDCHR)==0)	/* Replace */
+			goto putin;
+
+		/* Do checking to see whether char I/D operations should
+		 * be invoked.  This code is quite CPU intensive and
+		 * can cause noticeable pauses if run on a slow CPU with
+		 * a fast (9600) terminal line.  The optimization tradeoff
+		 * seems worthwhile most of the time, however.
+		 */
+		cmpcost = 0;		/* Default is don't compare */
+		if(ncol == ocol)	/* If line lengths same, must chk */
+		  {
+/*			if(ncol >= scr_wid) */	/* If line overrun, compare */
+				cmpcost++;
+		  }
+#if 0
+If ncol == ocol, have problem with tabs:
+	If don''t use I/D char, but tabs exist, lots of wasteful update.
+	If DO use I/D char, and no tabs exist, potential for mistakenly
+		using I/D when didn''t have to.  Not too bad, though?
+	If DO use I/D char, then mild screw when inserting/deleting
+		just before a tab, since could have just overwritten,
+		but I/D insists on jerking things around.
+	Insert test:
+		If old char was space, replace? Problem: will cause cursor
+		jump if really should have shifted a long run of spaces.
+		But that is probably okay.
+	Delete test:
+		If new char is space, replace? again, will cause cursor jump
+		with long run of spaces.
+#endif /*COMMENT*/
+
+		if(ncol < ocol || cmpcost)	/* Try delete-char */
+		  {
+			/* Search old for match of c and nextc */
+dodel:			savc = c;
+			if(i >= ncol-1)
+				goto putin;
+			c2 = *cp;
+			if(c == SP && ncol == ocol)
+				goto tryins;
+			p2 = i;
+			for(;;)
+			  {	if(c == sci[i] && c2 == sci[i+1])
+					break;
+				if(++i < ocol)
+					continue;
+				i = p2;
+				if(cmpcost) {cmpcost = 0; goto tryins;}
+				goto putin;
+			  }
+			/* Find # chars that match (i.e. will be saved) */
+			for(c=1; (i+c < ncol) && (sci[i+c] == cp[c-1]); c++);
+			delcost = tvc_cd + tvc_cdn*(i - p2);
+			if(delcost >= c)
+			  {	c = savc;
+				i = p2;
+				if(cmpcost) { cmpcost = 0; goto tryins;}
+				goto putin;	/* Punt */
+			  }
+			if(cmpcost)
+			  {	c = savc; i = p2;
+				goto tryins;
+			  }
+			t_move(y, p2);
+			c = i - p2;	/* Find # chars to flush */
+			strncpy(&sci[p2],&sci[i], ocol-i);
+			ocol -= c;
+			fillsp(&sci[ocol], c);
+			i = p2;			/* Restore i */
+			t_delchr(c);		/* Flush this many cols */
+			continue;
+		  }
+
+		/* Try ins-char */
+		/* Search new for match of i and i+1 */
+		/* Note this cannot be used while in standout mode, since
+		** the new spaces created will probably be in the wrong mode.
+		*/
+tryins:
+#if FX_SOWIND
+		if(newso) goto putin;
+#endif
+		if(i+1 >= ocol)
+			goto putin;
+
+		savc = c;
+		savcp = cp;
+		c2 = sci[i+1];
+		if(sci[i] == SP && ncol == ocol)
+			goto putin;
+		xpos = i;		/* save current col */
+		i++;
+		for(;;)
+		  {	if(i >= ncol) goto puntx;
+			c = *cp++;
+inlp2:			if(c != sci[xpos])
+			  {	if(i > scr_wid) goto puntx;
+				i++;
+				continue;
+			  }
+			if(i >= ncol) goto puntx;
+			c = *cp++;
+			if(c != c2)
+			  {	i++;		/* Allow for previous c */
+				goto inlp2;	/* which is always 1 */
+			  }
+			break;
+		  }
+		if(i >= scr_wid) goto puntx;
+
+		/* Find how many chars match (i.e. will be saved) */
+		for(c = 2; xpos+c < ncol && sci[xpos+c] == *cp++; c++);
+		if((p2 = tvc_ci + tvc_cin*(i - xpos)) >= c)
+			goto puntx;	/* Not worth it... */
+		if(cmpcost && p2 >= delcost)
+			goto puntx;	/* Do delchr instead */
+
+		/* We've decided to insert some chars! */
+		i -= xpos;		/* Get # char positions to insert */
+		cp = savcp;		/* Get ptr to newline string */
+		--cp;			/* Point at 1st char to insert */
+					/* Make room in scr array */
+		inspc(&sci[xpos],
+			&sci[(ocol+i >= scr_wid) ? scr_wid-i : ocol], i);
+		ocol += i;		/* Update size of old line */
+		strncpy(&sci[xpos], cp, i);	/* Copy all inserted chars */
+
+		t_move(y, xpos);	/* Now ensure in right place */
+		t_inschr(i, cp);	/* and insert string onto screen! */
+
+		cp += i;		/* Update source ptr */
+		cp++;			/* Point to next char */
+		i += xpos;
+		continue;		/* Now continue loop! */
+
+	puntx:	i = xpos;
+		c = savc;
+		cp = savcp;
+		if(cmpcost) { cmpcost = 0; goto dodel;}
+		goto putin;
+	  }
+
+	/* All done putting up new stuff.  Now see if any remaining old
+	** stuff needs to be cleared from end of line.
+	*/
+idone:	if(i < ocol)		/* if still have text to right, */
+	  {	t_move(y,i);	/* move there */
+		t_docleol();	/* and clear old stuff. */
+	  }
+
+done:	s->sl_line = s->sl_nlin;	/* Replace old image by new */
+	s->sl_col = s->sl_ncol;
+	s->sl_nlin = sci;
+	s->sl_flg &= ~SL_MOD;
+#if FX_SOWIND			/* Copy standout mode to current */
+	if(newso) s->sl_flg |= SL_CSO;
+	else s->sl_flg &= ~SL_CSO;
+#endif
+}
+
+#if FX_SOWIND
+fillset(str,cnt,c)
+char *str;
+int cnt;
+int c;
+{	register int n;
+	register char *cp;
+	if((n = cnt) <= 0) return;
+	cp = str;
+	do{ *cp++ = c;
+	  } while(--n);
+}
+#endif
+
+fillsp(str,cnt)
+char *str;
+int cnt;
+{	register int n;
+	register char *cp;
+	if((n = cnt) <= 0) return;
+	cp = str;
+	do{ *cp++ = SP;
+	  } while(--n);
+}
+inspc(cp0, cpl, cnt)
+char *cp0, *cpl;
+int cnt;
+{	register char *cp, *cp2;
+	register n;
+	if((n = cnt) <= 0) return;
+	cp = cpl;		/* ptr to last+1 char in string */
+	cp2 = cp+n;		/* ptr to loc+1 to move to */
+	n = cp - cp0;		/* # chars to move */
+	do *--cp2 = *--cp;
+	while(--n);
+	n = cnt;		/* Now fill gap with spaces */
+	do *cp++ = SP;
+	while(--n);
+}
+
+
+/* FIX_LINE - Fixes up new screen image for a single line.  Does not
+ *	do any actual terminal I/O, and does not change the old screen
+ *	image.  Assumes that previous line (if any is furnished) has
+ *	already been properly set up.
+ */
+
+int sctreol = 0;	/* Ugly crock for talking to sctrin() */
+			/* 0 = no EOL seen, 1 = EOL seen, -1 = EOF seen */
+fix_line(slp, olds)
+struct scr_line *slp;
+struct scr_line *olds;
+{	register struct scr_line *s;
+	register int col, scrw;
+	char *cp;
+	int ch;
+
+	col = 0;
+	scrw = scr_wid;
+	cp = slp->sl_nlin;
+	if((s = olds) && (col = s->sl_cont))
+	  {	if(--col)
+			strncpy(cp, (s->sl_flg&SL_MOD) ?
+					&s->sl_nlin[scrw]
+					 : &s->sl_line[scrw], col);
+		cp += col;
+	  }
+	scrw--;			/* Note now using scr_wd0 !! */
+	s = slp;
+	s->sl_boff = e_dot();
+	col = sctrin(cp, scrw, col);
+	if (col < scrw || sctreol)	/* Does line need continuation mark? */
+		s->sl_cont = 0;		/* No, say no cont chars */
+	else {
+		/* Yes, find # cols of overflow.  If not 0, must be > 0 */
+		/* and char is a biggie.  Make room for continuation chars */
+		if(col -= scrw)
+			inspc(&s->sl_nlin[scrw],&s->sl_nlin[scrw+col], 1);
+		s->sl_cont = col+1;		/* # cont chars, plus 1 */
+		s->sl_nlin[scrw] = CI_CLINE;	/* Display "contin" mark */
+		col = scrw+1;
+	  }
+
+	s->sl_ncol = col;
+	s->sl_len = e_dot() - s->sl_boff;
+	s->sl_flg |= (SL_MOD|SL_EOL);	/* Say new, and assume line has EOL */
+	if(sctreol <= 0)		/* unless it doesn't really */
+		s->sl_flg &= ~SL_EOL;	/* in which case turn off flag */
+	return;
+}
+
+/* SCTRIN - auxiliary for FIX_LINE.
+ *	lim - # cols chars are allowed to use
+ *	ccol - current column (0 = bol)
+ * Returns when see EOL or EOF, or
+ *	when all columns have been filled up.  Retval-ccol = # overflow.
+ *	Note that any overflow is indivisible (i.e. a char with a
+ *	multi-col representation is responsible for the overflow).
+ *	So, overflow = 0 means next char would be in 1st non-ex column
+ *	and overflow > 0 means last char read has extra columns, but
+ *	it did start within bounds.
+ */
+sctrin(to, lim, ccol)
+char *to;
+int lim;
+int ccol;
+{	register SBBUF *sb;
+	register col, cnt;
+
+	sb = (SBBUF *) cur_buf;
+	col = ccol;
+	sctreol = 0;		/* No EOL or EOF seen */
+	do
+	  {	cnt = sb_getc(sb);
+		if(cnt == EOF)
+		  {	--sctreol;	/* Say EOF seen! */
+			return(col);
+		  }
+#if FX_EOLMODE
+		if(cnt == CR)		/* Possible EOL? */
+		  {	if(eolcrlf(sb))
+			  {	if((cnt = sb_getc(sb)) == LF)	/* Real EOL? */
+				  {	sctreol++;
+					return col;	/* Yes, return */
+				  }
+				/* Stray CR, back up & fall thru */
+				if(cnt != EOF)
+					sb_backc(sb);
+				cnt = CR;	/* Show stray CR */
+			  }
+		  } else if (cnt == LF)
+		  {	if(!eolcrlf(sb))	/* Real EOL? */
+			  {	sctreol++;
+				return col;	/* Yes, return */
+			  }
+			/* If EOL mode is CRLF then hitting a LF
+			** can only happen for stray LFs (the
+			** previous check for CR takes care of
+			** CRLFs, and we never start scanning
+			** from the middle of a CRLF.
+			** Drop thru to show stray LF.
+			*/
+		  }
+#else
+		if(cnt == LF)
+		  {	sctreol++;	/* Say EOL seen */
+			return col;
+		  }
+#endif /*_FX_EOLMODE*/
+		cnt = sctr(cnt, to, col);
+		to += cnt;
+		col += cnt;
+	  } while(col < lim);
+
+	/* If we're stopping because last char put us precisely at the
+	** end of the line, make a further check to see whether an EOL
+	** is next.  If so, we can include that in the line since it
+	** doesn't need any more columns for representation!
+	*/
+	if (col == lim)		/* If stopping exactly at edge of screen */
+	    switch (sb_getc(sb))	/* Check out next char */
+	      {	case EOF:
+			--sctreol;		/* Yes, note EOF seen */
+			break;			/* and can return immed */
+#if FX_EOLMODE
+		case CR:		/* Possible EOL? */
+			if(eolcrlf(sb))
+			  {	if((cnt = sb_getc(sb)) == LF)	/* Real EOL? */
+				  {	sctreol++;	/* Yes, set flag */
+					break;		/* and return */
+				  }
+				/* Stray CR, back up & fall thru */
+				if(cnt != EOF)		/* Back up char that */
+					sb_backc(sb);	/* came after the CR */
+				sb_rgetc(sb);		/* Then back over CR */
+				break;
+			  }
+			sb_backc(sb);
+			break;
+		case LF:
+			if(!eolcrlf(sb))	/* Real EOL? */
+			  {	sctreol++;	/* Yes, set flag */
+				break;		/* and return */
+			  }
+			/* If EOL mode is CRLF then hitting a LF
+			** can only happen for stray LFs (the
+			** previous check for CR takes care of
+			** CRLFs, and we never start scanning
+			** from the middle of a CRLF.
+			** Drop thru into default to back up over LF.
+			*/
+#else
+		case LF:
+			sctreol++;	/* Say EOL seen */
+			break;		/* and return */
+#endif /*-FX_EOLMODE*/
+		default:
+			sb_backc(sb);		/* Back up over random char */
+			break;
+	    }
+	return(col);
+}
+
+
+/* SCTR - Screen Char TRanslation routine.
+**	This routine is completely responsible for the way a buffer char is
+** displayed on the screen.  Given a char and the current column position,
+** it stores the representation using the given pointer and returns
+** the number of chars (columns) used by the representation.
+**	Normal printing chars (plus space) are simply themselves.
+**	TAB is a variable number of spaces depending on the column pos.
+**		(we use standard tabstops of 8)
+**	All control chars are uparrow followed by a printing char.
+**		e.g. ctrl-A = ^A
+**		This includes ESC which is ^[.
+**		DEL is shown as ^?.
+**	Chars with the 8th bit set have the prefix CI_META (currently ~) and
+**		the rest of the representation is as above (except for TAB).
+**	Chars with the 9th bit set have the prefix CI_TOP (currently |) and
+**		the rest of the representation is as above (except for TAB).
+**		This only exists for systems with 9-bit chars such as TOPS-20.
+*/
+
+static int
+sctr(ch, to, ccol)
+int ch;			/* Buffer char to translate */
+char *to;		/* Place to deposit translation in */
+int ccol;		/* Current column position */
+{	register char *cp;
+	register c, n;
+
+	c = ch;
+	if(037 < c && c < 0177)	/* Most common case */
+	  {	*to = c;
+		return(1);
+	  }
+	cp = to;
+	if(c == TAB)			/* Next most common case */
+	  {	n = 010 - (ccol&07);	/* Tab stops are every 8 cols */
+		ccol = n;		/* Save value */
+		do *cp++ = SP;
+		while (--n);
+		return(ccol);
+	  }
+	ccol = 1;			/* Re-use var */
+#if TOPS20
+	if(c&0400)			/* 9th bit set? */
+	  {	*cp++ = CI_TOP;
+		ccol++;
+	  }
+#endif /*TOPS20*/
+	if(c&0200)
+	  {	*cp++ = CI_META;
+		ccol++;
+	  }
+	if((c &= 0177) <= 037 || c == 0177)
+	  {	*cp++ = CI_CNTRL;
+		c ^= 0100;		/* Transform cntrl char */
+		ccol++;
+	  }
+	*cp = c;
+	return(ccol);
+}
+
+
+/* INSLIN(line, N, wind) - Insert lines
+ * DELLIN(line, N, wind) - Delete lines
+ *	Both routines insert/delete N lines at "line" in window "wind"
+ *	and update the screen image accordingly.
+ */
+
+inslin (line, n, win)
+int   line;			       /* line number to insert BEFORE */
+int   n;			       /* number of lines to insert */
+struct window *win;		       /* window we are in */
+{	register int  i;
+	register int bot;
+	register char **savp;
+	char *savscr[MAXHT];
+
+	bot = win -> w_ht + win -> w_pos;
+	t_curpos (line, 0);
+	t_inslin (n, bot);		/* do the insertion on the screen */
+	savp = &savscr[0];
+	for (i = 1; i <= n; i++)	/* free lines that fall off-screen */
+		*savp++ = scr[bot - i]->sl_line;
+
+	for (i = bot - 1; i >= line + n; i--)		/* move down lines */
+	  {	scr[i]->sl_line = scr[i - n]->sl_line;	/* below the insertion */
+		scr[i]->sl_col = scr[i - n]->sl_col;
+	  }
+	savp = &savscr[0];
+	for (i = line + n - 1; i >= line; i--)
+				       /* blank lines where inserted */
+	  {	scr[i]->sl_line = *savp++;
+		scr[i]->sl_col = 0;
+	  }
+	for(i = line; i < bot; ++i)
+		scr[i]->sl_flg |= SL_MOD;
+}
+
+dellin (line, n, win)
+int   line;			       /* first line to be deleted */
+int   n;			       /* number of lines to be deleted */
+struct window *win;		       /* window we are in */
+{	register int  i;
+	register int bot;
+	register char **savp;
+	char *savscr[MAXHT];
+
+	bot = win -> w_ht + win -> w_pos;
+
+	t_curpos (line, 0);
+	t_dellin (n, bot);	       /* do the deletion on the screen */
+	savp = &savscr[0];
+	for (i = line; i < line + n; i++)    /* free the deleted lines */
+		*savp++ = scr[i]->sl_line;
+	for (i = line; i < bot - n; i++)	/* move lines up to fill */
+	  {	scr[i]->sl_line = scr[i + n]->sl_line;	/* deleted spaces */
+		scr[i]->sl_col = scr[i + n]->sl_col;
+	  }
+
+	savp = &savscr[0];
+	for (i = bot - n; i < bot; i++)      /* blank lines at bottom */
+	  {	scr[i]->sl_line = *savp++;
+		scr[i]->sl_col = 0;
+	  }
+	for(i = line; i < bot; ++i)
+		scr[i]->sl_flg |= SL_MOD;
+}
+
+
+/* T_ Terminal functions - these are similar to the terminal-dependent
+ *	routines in EETERM (which they call) but rely on some knowledge of
+ *	the screen image in order to do their job cleverly.
+ */
+
+#if FX_SOWIND
+
+/* T_DOSTANDOUT(on) - Turn standout mode on or off, cleverly.
+**	Returns previous state.
+*/
+static int curso = 0;		/* Current state (initially off) */
+int
+t_dostandout(on)
+int on;
+{
+	int oldso;
+
+	if ((oldso = curso) != on)	/* If desired state doesn't match, */
+	  {	t_standout(on);		/* invoke new state. */
+		curso = on;
+	  }
+	return oldso;
+}
+#endif
+
+
+t_move(y,x)
+register int y,x;
+{	register int d;
+
+	if(y != curs_lin)		/* No vertical smarts yet */
+	  {	t_curpos(y, x);
+		return;
+	  }
+	if((d = (x - curs_col)) >= 0)	/* Find diff in column position */
+	  {	if(d == 0) return;	/* If none, nothing to do! */
+
+		/* Moving right.  If distance is less than abs-move cost,
+		 * do clever right-move by copying screen image */
+		if(d < tvc_pos)
+#if FX_SOWIND	/* Ensure not in standout mode */
+			if((scr[y]->sl_flg&(SL_CSO|SL_NSO))==0)
+#endif
+		  {
+			tputn(&scr[y]->sl_line[curs_col], d);
+			curs_col = x;
+			return;
+		  }
+	  }
+	/* Moving to left, try to do clever left-move by backspacing
+	 * instead of using abs move.
+	 */
+	else if((d = -d)*tvc_bs < tvc_pos)
+	  {	do { t_backspace();
+		  } while(--d);
+		return;
+	  }
+	/* No luck with cleverness, just move. */
+	t_curpos(y, x);
+}
+
+t_docleol()
+{	register struct scr_line *s;
+	register int cnt, ocol;
+
+	if(trm_flags&TF_CLEOL) t_cleol();	/* Winning */
+	else		/* Losing */
+	  {	s = scr[curs_lin];
+		if((cnt = s->sl_col - curs_col) > 0)
+		  {
+#if FX_SOWIND
+			int oldso = t_dostandout(0);
+#endif
+			ocol = curs_col;
+			do { tput(SP); curs_col++;
+			  } while(--cnt);
+#if FX_SOWIND
+			t_dostandout(oldso);
+#endif
+			t_move(curs_lin, ocol);
+		  }
+	  }
+}
+
Index: /trunk/minix/commands/elle/eeedit.c
===================================================================
--- /trunk/minix/commands/elle/eeedit.c	(revision 9)
+++ /trunk/minix/commands/elle/eeedit.c	(revision 9)
@@ -0,0 +1,723 @@
+/* ELLE - Copyright 1982, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*	EEEDIT - E-type routines */
+
+#include "elle.h"
+
+/* E_	- Operate on cur_buf.  Do not change value of cur_dot unless
+ *		unavoidable side effect (also e_setcur).
+ * EX_	- Like E_ but take SB ptr value.  Never touch cur_dot.
+ * ED_	- Like E_, operate on cur_buf, update cur_dot and display stuff.
+ * D_	- Perform necessary display update for given operations.
+ *
+ * Note that "dot" refers to the current read/write pointer for a sbbuffer.
+ * The name comes from EMACS/TECO where "." represents this value.
+ */
+
+#define CURSBB (SBBUF *)cur_buf		/* Shorthand for current SB buffer */
+
+e_reset()	/* Reset current buffer */
+{	ex_reset(CURSBB);
+	cur_dot = 0;
+}
+
+/* Basic functions - apply SB routines to current buffer.
+ * There is some optimization here which knows that certain SB functions
+ * are macros.
+ */
+e_rgetc()	/* Read/move 1 char backward */
+{	return(sb_rgetc((CURSBB)));
+}
+e_rdelc()	/* Delete 1 char backward */
+{	return(sb_rdelc((CURSBB)));
+}
+e_delc()	/* Delete 1 char forward */
+{	return(sb_deln(CURSBB,(chroff)1));
+}
+e_getc()	/* Read/move 1 char forward */
+{	register SBBUF *sb;
+	sb = CURSBB;		/* Macro: use reg */
+	return(sb_getc(sb));
+}
+e_backc()	/* Move 1 char backward */
+{	register SBBUF *sb;
+	sb = CURSBB;		/* Macro: use reg */
+	sb_backc(sb);			/* No value returned */
+}
+e_putc(c)	/* Insert/write 1 char forward */
+char c;
+{	register SBBUF *sb;
+	sb = CURSBB;		/* Macro: use reg */
+	return(sb_putc(sb, c));
+}
+e_peekc()	/* Read 1 char forward (no move) */
+{	register SBBUF *sb;
+	sb = CURSBB;		/* Macro: use reg */
+	return(sb_peekc(sb));
+}
+e_ovwc(ch)	/* Overwrite 1 char forward */
+char ch;
+{
+	sb_setovw(CURSBB);	/* Turn on overwrite mode */
+	e_putc(ch);
+	sb_clrovw(CURSBB);	/* Turn off overwrite mode */
+}
+
+SBSTR *
+e_copyn(off)	/* Copy N chars forward/backward, return SD to sbstring */
+chroff off;
+{	return(sb_cpyn(CURSBB,off));
+}
+e_deln(off)	/* Delete N chars forward/backward */
+chroff off;
+{	return(sb_deln(CURSBB, off));
+}
+
+/* E_SETCUR() - set cur_dot to current position (dot).  This is the only
+ *	E_ routine that mungs cur_dot except for e_reset.
+ */
+e_setcur()
+{	cur_dot = e_dot();
+}
+e_gosetcur(dot)		/* Go to specified dot and set cur_dot as well */
+chroff dot;
+{	sb_seek(CURSBB,dot,0);
+	e_setcur();	/* Not cur_dot = dot since want canonicalization */
+}
+
+/* E_GO(dot) - Move to specified location. */
+/* These "GO" routines all move to the location specified, returning
+ *	0 if successful and -1 on error.  "cur_dot" is never changed,
+ *	with the exception of e_gosetcur.
+ * Note that other "GO" routines (eg E_GONL) will return 1 if successful
+ *	and 0 if stopped by EOF.
+ */
+
+e_gocur() { return(e_go(cur_dot)); }		/* Move to cur_dot */
+e_gobob() { return(e_go((chroff) 0)); }		/* Move to Beg Of Buffer */
+e_goeob() { return(sb_seek(CURSBB,(chroff)0,2)); } /* Move to End Of Buffer */
+e_go(dot)	/* Move to specified location. */
+chroff dot;
+{	return(sb_seek(CURSBB,dot,0));
+}
+e_igoff(ioff)	/* Move (int) N chars forward/backward */
+int ioff;
+{	return(sb_seek(CURSBB,(chroff)ioff,1));
+}
+
+e_goff(off)	/* Move (full) N chars forward/backward */
+chroff off;
+{	return(sb_seek(CURSBB,off,1));
+}
+
+int ex_gonl(), ex_gopl(), ex_gobol(), ex_goeol();
+
+e_gobol() { return(ex_gobol(CURSBB)); }	/* Move to beg of this line */
+e_goeol() { return(ex_goeol(CURSBB)); }	/* Move to end of this line */
+e_gonl()  { return(ex_gonl(CURSBB)); }	/* Move to beg of next line */
+e_gopl()  { return(ex_gopl(CURSBB)); }	/* Move to beg of prev line */
+
+
+/* E_DOT() - Return current value of dot. */
+chroff e_dot()   { return(sb_tell(CURSBB)); }		/* Current pos */
+chroff e_nldot() { return(e_alldot(CURSBB,ex_gonl)); }	/* Beg of next line */
+chroff e_pldot() { return(e_alldot(CURSBB,ex_gopl)); }	/* Beg of prev line */
+chroff e_boldot(){ return(e_alldot(CURSBB,ex_gobol));}	/* Beg of this line */
+chroff e_eoldot(){ return(e_alldot(CURSBB,ex_goeol));}	/* End of this line */
+
+chroff
+e_alldot(sbp,rtn)	/* Auxiliary for above stuff */
+SBBUF *sbp;
+int (*rtn)();
+{	return(ex_alldot(sbp,rtn,e_dot()));
+}
+
+/* E_BLEN - Return length of current buffer */
+chroff
+e_blen() { return(ex_blen(CURSBB)); }
+
+
+/* EX_ routines - similar to E_ but take a buffer/sbbuf argument
+ *	instead of assuming current buffer.
+ */
+
+/* EX_RESET - Reset a given buffer */
+ex_reset(b)
+struct buffer *b;
+{	sbs_del(sb_close((SBBUF *)b));
+	sb_open((SBBUF *)b,(SBSTR *)0);
+}
+
+ex_go(sbp,loc)		/* Move to given dot in specified sbbuf */
+chroff loc;
+SBBUF *sbp;
+{	return(sb_seek(sbp,loc,0));
+}
+
+chroff
+ex_dot(sbp)	/* Return current position in specified sbbuf */
+SBBUF *sbp;
+{
+	return(sb_tell(sbp));
+}
+
+
+chroff
+ex_boldot(sbp,dot)	/* Return dot for BOL of specified sbbuf */
+SBBUF *sbp;
+chroff dot;
+{	return(ex_alldot(sbp,ex_gobol,dot));
+}
+
+chroff
+ex_alldot(sbp,rtn,dot)	/* Auxiliary for some e_ stuff */
+SBBUF *sbp;
+int (*rtn)();
+chroff dot;
+{	register SBBUF *sb;
+	chroff savloc, retloc;
+
+	savloc = sb_tell(sb = sbp);
+	sb_seek(sb,dot,0);
+	(*rtn)(sb);
+	retloc = sb_tell(sb);
+	sb_seek(sb,savloc,0);
+	return(retloc);
+}
+
+/* GO (forward) to Next Line of specified sbbuf - returns 0 if stopped at EOF
+ * before an EOL is seen. */
+ex_gonl(sbp)
+SBBUF *sbp;
+{	register SBBUF *sb;
+	register int c;
+	sb = sbp;
+#if FX_EOLMODE
+	if(eolcrlf(sb))
+		while((c = sb_getc(sb)) != EOF)
+		  {	if(c == LF)		/* Possible EOL? */
+			  {	sb_backc(sb);	/* See if prev char was CR */
+				if((c = sb_rgetc(sb)) != EOF)
+					sb_getc(sb);
+				sb_getc(sb);	/* Must restore position */
+				if(c == CR)	/* Now test for CR */
+					return(1);	/* Won, CR-LF! */
+			  }
+		  }
+	else
+#endif
+	while((c = sb_getc(sb)) != EOF)
+		if(c == LF)
+			return(1);
+	return(0);
+}
+
+/* GO (forward) to End Of Line of specified sbbuf - returns 0 if stopped at
+ * EOF before an EOL is seen. */
+ex_goeol(sbp)
+SBBUF *sbp;
+{	register SBBUF *sb;
+	register int c;
+	sb = sbp;
+#if FX_EOLMODE
+	if(eolcrlf(sb))
+		while((c = sb_getc(sb)) != EOF)
+		  {	if(c == LF)		/* Possible EOL? */
+			  {	sb_backc(sb);	/* See if prev char was CR */
+				if((c = sb_rgetc(sb)) == CR)
+					return(1);	/* Won, CR-LF! */
+				if(c != EOF)	/* No, must restore position */
+					sb_getc(sb);	/* Skip over */
+				sb_getc(sb);		/* Skip over LF */
+			  }
+		  }
+	else
+#endif
+	while((c = sb_getc(sb)) != EOF)
+		if(c == LF)
+		  {	sb_backc(sb);
+			return(1);
+		  }
+	return(0);
+}
+
+/* GO (backward) to Beg Of Line of specified sbbuf - returns 0 if stopped
+ * at EOF
+ */
+ex_gobol(sbp)
+SBBUF *sbp;
+{	register SBBUF *sb;
+	register int c;
+	sb = sbp;
+#if FX_EOLMODE
+	if(eolcrlf(sb))
+		while((c = sb_rgetc(sb)) != EOF)
+		  {	if(c == LF)		/* Possible EOL? */
+			  {	if((c = sb_rgetc(sb)) == CR)
+				  {	sb_getc(sb);	/* Won, CR-LF! */
+					sb_getc(sb);	/* Move back */
+					return(1);
+				  }
+				if(c != EOF)	/* No, must restore position */
+					sb_getc(sb);	/* Undo the rgetc */
+			  }
+		  }
+	else
+#endif
+	while((c = sb_rgetc(sb)) != EOF)
+		if(c == LF)
+		  {	sb_getc(sb);
+			return(1);
+		  }
+	return(0);
+}
+
+/* GO (backward) to Previous Line of specified sbbuf - returns 0 if stopped
+ * at EOF before an EOL is seen (i.e. if already on 1st line of buffer)
+ */
+ex_gopl(sbp)
+SBBUF *sbp;
+{	register SBBUF *sb;
+	register int c;
+	sb = sbp;
+#if FX_EOLMODE
+	if(eolcrlf(sb))
+		while((c = sb_rgetc(sb)) != EOF)
+		  {	if(c == LF)		/* Possible EOL? */
+			  {	if((c = sb_rgetc(sb)) == CR)
+				  {	ex_gobol(sb);
+					return(1);		/* Won! */
+				  }
+				if(c != EOF)	/* No, must restore position */
+					sb_getc(sb);	/* Undo the rgetc */
+			  }
+		  }
+	else
+#endif
+	while((c = sb_rgetc(sb)) != EOF)
+		if(c == LF)
+		  {	ex_gobol(sb);
+			return(1);	/* Won! */
+		  }
+	return(0);
+}
+
+
+chroff
+ex_blen(sbp)		/* Return length of specified sbbuf */
+SBBUF *sbp;
+{
+	return(sb_tell(sbp)+sb_ztell(sbp));
+}
+
+
+/* Miscellaneous stuff */
+
+/* E_GOFWSP() - Forward over whitespace */
+e_gofwsp()
+{	register int c;
+	while((c = e_getc()) == SP || c == TAB);
+	if(c != EOF) e_backc();
+}
+
+/* E_GOBWSP() - Backward over whitespace */
+e_gobwsp()
+{	register int c;
+	while((c = e_rgetc()) == SP || c == TAB);
+	if(c != EOF) e_getc();
+}
+
+
+/* E_GOLINE(n) - Goes N lines forward (or backward).
+**	If N == 0, goes to beginning of current line.
+**	Returns 0 if hit EOF.
+*/
+e_goline(i)
+register int i;
+{
+	if(i > 0)
+	  {	do { if(!e_gonl()) return(0); }
+		while(--i);
+	  }
+	else if(i < 0)
+	  {	i = -i;
+		do { if(!e_gopl()) return(0); }
+		while(--i);
+	  }
+	else e_gobol();		/* arg of 0 */
+	return 1;
+}
+
+/* E_LBLANKP() - Returns true if all characters in rest of line are blank.
+ *	Moves to beginning of next line as side effect, unless fails.
+ */
+e_lblankp()
+{	register int c;
+	for(;;) switch(e_getc())
+	  {
+		case SP:
+		case TAB:
+			continue;
+		case LF:	/* Normally drop thru to return 1 as for EOF */
+#if FX_EOLMODE
+			if(eolcrlf(cur_buf))
+			  {	e_rgetc();
+				if((c = e_rgetc()) != EOF) /* Get prev char */
+					e_getc();
+				e_getc();
+				if(c != CR)		/* Now examine */
+					continue;	/* Not CR-LF, go on */
+			  }	/* Else drop thru to return win */
+#endif
+		case EOF:
+			return(1);
+		default:
+			return(0);
+	  }
+	/* Never drops out */
+}
+
+
+
+e_insn(ch, cnt)
+int ch;
+int cnt;
+{	register int i;
+	if((i = cnt) > 0)
+		do { e_putc(ch);
+		  } while(--i);
+}
+
+e_sputz(acp)
+char *acp;
+{	register SBBUF *sb;
+	register char *cp;
+	register int c;
+	if(cp = acp)
+	  {	sb = CURSBB;
+		while(c = *cp++)
+			sb_putc(sb,c);
+	  }
+}
+
+/* BOLEQ - Returns TRUE if 2 dots are on the same line
+ *	(i.e. have the same Beg-Of-Line)
+ */
+boleq(dot1,dot2)
+chroff dot1,dot2;
+{	return( (ex_boldot(CURSBB,dot1) == ex_boldot(CURSBB,dot2)));
+}
+
+
+char *
+dottoa(str,val)
+char *str;
+chroff val;
+{	register char *s;
+
+	s = str;
+	if(val < 0)
+	  {	*s++ = '-';
+		val = -val;
+	  }
+	if(val >= 10)
+		s = dottoa(s, val/10);
+	*s++ = '0' + (int)(val%10);
+	*s = 0;
+	return(s);
+}
+
+
+
+/* Paragraph utilities */
+
+#if FX_FPARA || FX_BPARA || FX_MRKPARA || FX_FILLPARA
+
+#if FX_SFPREF
+extern char *fill_prefix;	/* Defined in eefill.c for now */
+extern int fill_plen;		/* Ditto */
+#endif /*FX_SFPREF*/
+
+#if ICONOGRAPHICS
+int para_mode = PARABLOCK;	/* eexcmd.c only other file that refs this */
+#endif /*ICONOGRAPHICS*/
+
+
+/* Go to beginning of paragraph */
+e_gobpa()
+{	register int c;
+	chroff savdot;
+
+	savdot = e_dot();
+	e_bwsp();
+	while((c = e_rgetc()) != EOF)
+		if(c == LF)		/* Went past line? */
+		  {	e_getc();		/* Back up and check */
+#if FX_SFPREF
+			if(fill_plen)
+				if(tstfillp(fill_plen))
+				  {	e_igoff(-(fill_plen+1));
+					continue;
+				  }
+				else break;
+#endif /*FX_SFPREF*/
+#if ICONOGRAPHICS
+                        c = e_peekc ();
+
+                        if (para_mode == PARABLOCK)
+                            if (c == LF)
+                                break;
+
+                        if (para_mode == PARALINE)
+                            if (c_wsp (c))
+                                break;
+#else
+			if(c_pwsp(e_peekc()))	/* Check 1st chr for wsp */
+				break;		/* If wsp, done */
+#endif /*ICONOGRAPHICS*/
+			e_rgetc();		/* Nope, continue */
+		  }
+	if((c = e_peekc()) == '.' || c == '-')
+	  {	e_gonl();
+		if(e_dot() >= savdot)
+			e_gopl();
+	  }
+}
+
+/* Go to end of paragraph */
+e_goepa()
+{	register int c;
+
+	e_gobol();			/* First go to beg of cur line */
+	e_fwsp();
+	while((c = e_getc()) != EOF)
+        	if (c == LF)
+		  {
+#if FX_SFPREF
+		if(fill_plen)		/* If Fill Prefix is defined */
+			if(tstfillp(fill_plen))	/* then must start with it */
+				continue;
+			else break;		/* or else we're done */
+#endif /*FX_SFPREF*/
+#if ICONOGRAPHICS
+                if (para_mode == PARABLOCK)
+                    if (e_peekc () == LF)
+                        break;
+
+                if (para_mode == PARALINE)
+                    if (c_wsp (e_peekc ()))
+                        break;
+#else
+                if(c_pwsp(e_peekc()))
+                        break;
+#endif /*-ICONOGRAPHICS*/
+		  }
+}
+
+exp_do(rpos, rneg)
+int (*rpos)(), (*rneg)();
+{	register int e;
+	register int (*rtn)();
+
+	if((e = exp) == 0)
+		return;
+	rtn = rpos;
+	if(e < 0)
+	  {	rtn = rneg;
+		e = -e;
+	  }
+	do { (*rtn)();
+	  } while(--e);
+}
+
+
+e_fwsp()
+{	register int c;
+	while(c_wsp(c = e_getc()));
+	if(c != EOF) e_backc();
+}
+e_bwsp()
+{	register int c;
+	while(c_wsp(c = e_rgetc()));
+	if(c != EOF) e_getc();
+}
+
+
+c_wsp(ch)
+int ch;
+{	register int c;
+	c = ch;
+	if(c == SP || c == TAB || c == LF || c == FF)
+		return(1);
+	return(0);
+}
+c_pwsp(ch)
+int ch;
+{	register int c;
+	c = ch;
+	if(c == '.' || c == '-')
+		return(1);
+	return(c_wsp(c));
+}
+
+#endif /* FX_FPARA || FX_BPARA || FX_MRKPARA || FX_FILLPARA */
+
+
+/* Word function auxiliaries */
+
+/* Returns true if this character is a delimiter. */
+delimp(c)
+int  c;
+{	static int  delim_tab[] =
+	  {
+	    0177777, 0177777,		/* All controls */
+	    0177777, 0176000,		/* All punct but 0-9 */
+	    0000001, 0074000,		/* All punct but A-Z and _ */
+	    0000001, 0174000		/* All punct but a-z */
+	  };
+	return (delim_tab[c >> 4] & (1 << (c & 017)));
+}
+
+e_wding(adot,n)
+register chroff *adot;
+int n;
+{	chroff savdot;
+	savdot = e_dot();
+	e_gowd(n);
+	*adot = e_dot();
+	e_go(savdot);
+	if(*adot == savdot)
+	  {	ring_bell();
+		return(0);
+	  }
+	return(1);
+}
+chroff
+e_wdot(dot,n)
+chroff dot;
+int n;
+{	chroff savdot, retdot;
+	savdot = e_dot();
+	e_go(dot);
+	e_gowd(n);
+	retdot = e_dot();
+	e_go(savdot);
+	return(retdot);
+}
+e_gowd(n)
+int n;
+{	register int (*gch)(), c, cnt;
+	int e_getc(), e_rgetc();
+	chroff ret_dot;
+
+	if((cnt = n) == 0)
+		return;
+	if(cnt > 0)
+		gch = e_getc;		/* Forward routine */
+	else
+	  {	gch = e_rgetc;		/* Backward routine */
+		cnt = -cnt;
+	  }
+	do
+	  {	ret_dot = e_dot();	/* Remember dot for last word found */
+		while((c = (*gch)()) != EOF && delimp(c));
+		if(c == EOF)
+		  {	e_go(ret_dot);		/* Use last word found */
+			break;
+		  }
+		while((c = (*gch)()) != EOF && !delimp(c));
+		if(c == EOF)
+			break;
+		if(n < 0) e_getc(); else e_backc();
+	  } while(--cnt);
+}
+
+
+/* Searching */
+
+e_search(mstr,mlen,backwards)
+char *mstr;
+int mlen;
+int backwards;
+{	register SBBUF *sb;
+	register char *cp;
+	register int c;
+	char *savcp;
+	int cnt, scnt;
+#if IMAGEN
+	register int c1;
+	register int caseless = (cur_buf->b_flags & B_TEXTMODE);
+#endif /*IMAGEN*/
+
+	sb = (SBBUF *) cur_buf;
+	if (!backwards)
+	  {		/* Search forwards */
+	sfwd:	cp = mstr;
+		while((c = sb_getc(sb)) != EOF)
+		  {
+#if IMAGEN
+			if((!caseless && c != *cp) || 
+			    (caseless && upcase(c) != upcase(*cp))) continue;
+#else
+			if(c != *cp) continue;
+#endif /*-IMAGEN*/
+			cp++;
+			cnt = mlen;
+			while(--cnt > 0)
+			  {
+#if IMAGEN
+				c1 = *cp++;
+				c = e_getc();
+				if ((!caseless && c1 != c) ||
+				     (caseless && upcase(c1) != upcase(c)))
+#else
+				if(*cp++ != (c = e_getc()))
+#endif /*-IMAGEN*/
+				  {	if(c == EOF) return(0);
+					sb_seek(sb,(chroff)(cnt-mlen),1);
+					goto sfwd;
+				  }
+			  }
+			return(1);
+		  }
+	  }
+	else
+	  {		/* Search backwards */
+		scnt = mlen - 1;
+		savcp = mstr + scnt;		/* Point to end of string */
+
+	sbck:	cp = savcp;
+		while((c = sb_rgetc(sb)) != EOF)
+		  {
+#if IMAGEN
+			if((!caseless && c != *cp) || 
+			    (caseless && upcase(c) != upcase(*cp))) continue;
+#else
+			if(c != *cp) continue;
+#endif /*-IMAGEN*/
+			cp--;
+			if((cnt = scnt) == 0) return(1);
+			do
+			  {
+#if IMAGEN
+				c1 = *cp--;
+				c = e_rgetc();
+				if ((!caseless && c1 != c) ||
+				     (caseless && upcase(c1) != upcase(c)))
+#else
+				if(*cp-- != (c = e_rgetc()))
+#endif /*-IMAGEN*/
+				  {	if(c == EOF) return(0);
+					sb_seek(sb,(chroff)(mlen-cnt),1);
+					goto sbck;
+				  }
+			  }
+			while(--cnt);
+			return(1);
+		  }
+	  }
+	return(0);		/* Failed */
+}
Index: /trunk/minix/commands/elle/eeerr.c
===================================================================
--- /trunk/minix/commands/elle/eeerr.c	(revision 9)
+++ /trunk/minix/commands/elle/eeerr.c	(revision 9)
@@ -0,0 +1,186 @@
+/* ELLE - Copyright 1982, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*	EEERR - Error handling & testing routines
+ */
+
+#include "elle.h"
+
+#if V6
+#include "eesigs.h"
+#else
+#include <signal.h>
+#endif
+
+/* EFUN: "Hit Breakpoint" */
+f_bkpt()
+{	clean_exit();
+	bpt();
+        set_tty();
+}
+bpt() {}		/* Put a DDT/ADB breakpoint here */
+
+
+#if !(STRERROR)		/* If strerror() not supported, we provide it. */
+extern int sys_nerr;		/* Max index into sys_errlist */
+extern char *sys_errlist[];
+
+char *
+strerror(num)
+int num;
+{
+	static char badbuf[30];
+	if (num > 0 && num <= sys_nerr)
+		return (sys_errlist[num]);
+	sprintf(badbuf, "unknown error %d", num);
+	return badbuf;
+}
+#endif /* -STRERROR */
+
+
+
+errsbm(type,adr,str,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)
+register int type;	/* Type, flags */
+int (*adr)();		/* Addr called from */
+char *str;		/* Printf string */
+{	register struct buffer *b;
+	int oldttystate;
+
+	oldttystate = clean_exit();	/* Ensure not in editing mode */
+	if(type == SBFERR)	/* File overwrite error?  A0 is FD */
+	  {	printf("WARNING - FILE CORRUPTED!\nBuffers affected:\n");
+		for(b = buf_head; b; b = b->b_next)
+		  {	if(sb_fdinp((SBBUF *)b, a0))
+				printf((b->b_fn ? "  %s: %s\n" : "  %s\n"),
+					b->b_name, b->b_fn);
+		  }
+		if (oldttystate > 0) set_tty();
+		return(1);	/* Try to continue normally */
+	  }
+	printf("%sERR: %o ", (type ? "SBX" : "SBM"), adr);
+	printf(str,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12);
+	askerr();
+}
+
+/*
+ *  Bite_bag -- Try to save our rear ends after a catastrophe.
+ *	This routine is mainly called from "interrupt"
+ *	level when a memory fault or bus error occurs.
+ *	We try to save the buffer to the file "ELLE.crash"
+ *	in the current working directory.  If it loses, well
+ *	then you have really lost.  Note: this routine does
+ *	not reset the appropriate signal handler, so it is
+ *	never re-entered.  If a fault repeats once in this
+ *	code, then the world dies.
+ */
+
+bite_bag(fault)				/* We come here on any memory error */
+int fault;
+{
+	int ostate;
+	/* Some systems, such as BSD4.x and SUN, do not reset caught signals
+	 * to SIG_DFL.
+	 * This is a win, but isn't what vanilla UNIX code expects.
+	 * Since it doesn't hurt to do it explicitly, we always turn it off
+	 * explicitly...
+	 */
+	signal(fault, SIG_DFL);		/* Reinstate default handling */
+
+	ostate = clean_exit();		/* Fix up the terminal modes first! */
+	printf("ELLE stopped by fatal interrupt (%d)!\n\
+Type S or W to try saving your work.\n",fault);
+	askerr();
+	if(ostate > 0) set_tty();
+	signal(fault, bite_bag);	/* If continued, re-enable signal */
+}
+
+/* HUP_EXIT - Called by a SIGHUP hangup signal.
+ *	Tries to save all modified buffers before exiting.
+ *	Note that the TTY is not touched at all, although the terminal mode
+ *	flag is set just in case further error handling routines are invoked.
+ */
+hup_exit()
+{	extern int trm_mode;		/* See e_disp.c */
+
+	trm_mode = -1;			/* Say TTY is now detached */
+	saveworld((struct buffer *)0, 0);	/* Save world, w/o feedback */
+	exit(1);
+}
+
+
+errint()		/* Routine provided for ADB jumps */
+{	askerr();
+}
+char askh1[] = "\
+A - Abort process\n\
+B - Breakpoint (must have \"bpt:b\" set in ADB)\n\
+C - Continue\n\
+D - Diagnostic command mode\n";
+char askh2[] = "\
+S - Try to save current buffer\n\
+W - Try to save world (all modified buffers)\n";
+
+int bsaving = 0;	/* Set while in middle of saving buffer(s) */
+
+askerr()
+{	register struct buffer *b;
+	char linbuf[100];
+	char *asklin();
+	extern int (*funtab[])();	/* In E_CMDS.C */
+	int ostate;
+
+	ostate = clean_exit();		/* Clean up TTY if not already done */
+reask:
+	printf("(A,B,C,D,S,W,?)");
+	switch(upcase(*asklin(linbuf)))
+	  {
+		case '?':
+			writez(1,askh1);	/* Too long for &$@! printf */
+			writez(1,askh2);	/* Too long for &$@! V6 C */
+			break;			/*    optimizer (/lib/c2) */
+		case 'A':
+			abort();
+			break;
+		case 'B':
+			bpt();
+			break;
+		case 'Q':
+		case 'C':
+			goto done;
+		case 'D':
+			if(funtab[FN_DEBUG])
+				(*funtab[FN_DEBUG])(-1);
+			else printf("Sorry, no diagnostics\n");
+			break;
+		case 'S':	/* Try to save current buffer only */
+			b = cur_buf;
+			goto savb;
+		case 'W':	/* Try to save all modified buffers */
+			b = 0;
+		savb:	if(bsaving++)
+			  {	printf("Already saving -- continued");
+				goto done;
+			  }
+			saveworld(b, 1);	/* Save, with feedback */
+			bsaving = 0;
+			break;
+	  }
+	goto reask;
+done:
+	if(ostate > 0)
+		set_tty();
+}
+
+char *
+asklin(acp)
+char *acp;
+{	register char *cp;
+	register int c;
+	cp = acp;
+	while((c = tgetc()) != LF)
+		*cp++ = c;
+	*cp++ = 0;
+	return(acp);
+}
Index: /trunk/minix/commands/elle/eef1.c
===================================================================
--- /trunk/minix/commands/elle/eef1.c	(revision 9)
+++ /trunk/minix/commands/elle/eef1.c	(revision 9)
@@ -0,0 +1,284 @@
+/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*
+ * EEF1	Various functions
+ *		Char move/ins/del
+ *		Case change
+ *		Char/word transpose
+ */
+
+#include "elle.h"
+
+/* EFUN: "Insert Self" */
+f_insself (c)
+int c;
+{
+#if IMAGEN
+	fim_insself(c);
+#else
+#if FX_FILLMODE
+	extern int fill_mode;
+
+	if(fill_mode) fx_insfill(c);
+	else
+#endif /*FX_FILLMODE*/
+	ed_insn(c, exp);	/* Normal stuff */
+#endif /*-IMAGEN*/
+}
+
+/* EFUN: "Quoted Insert"
+**	Inserts next char directly, <exp> number of times.
+** Does not check anything about the char and does not do anything
+** depending on the mode.  In particular, CR is not turned into EOL.
+*/
+f_quotins()
+{
+	ed_insn(cmd_read(), exp);	/* Insert next char directly */
+}
+
+#if FX_CRLF
+/* EFUN: "CRLF" */
+f_crlf()
+{
+#if IMAGEN
+	fim_crlf();
+#else
+	register int i;
+
+	if(e_goeol() == cur_dot		/* If at end of current line */
+	  && exp == 1			/* and inserting only 1 new line */
+	  && e_lblankp() && e_lblankp())	/* and next 2 lines blank */
+	  {	e_gocur();		/* Then just re-use next line. */
+		e_gonl();		/* Go to its start */
+		e_setcur();		/* and establish cur_dot there. */
+		ed_delete(e_dot(), e_eoldot());	/* Ensure any blanks flushed */
+	  }
+	else
+	  {	e_gocur();		/* Otherwise back to original place */
+		if((i = exp) > 0)	/* and simply insert newlines */
+			do ed_crins();
+			while(--i);
+	  }
+#endif /*-IMAGEN*/
+}
+#endif /*FX_CRLF*/
+
+
+/* EFUN: "Forward Character" */
+f_fchar()
+{	ed_igoff(exp);
+}
+
+/* EFUN: "Backward Character" */
+f_bchar()
+{	ed_igoff(-exp);
+}
+
+/* EFUN: "Delete Character" */
+f_dchar ()
+{
+#if IMAGEN
+	fim_dchar();
+#else
+	ef_deln(exp);
+#endif /*-IMAGEN*/
+}
+
+/* EFUN: "Backward Delete Character" */
+f_bdchar ()
+{
+#if IMAGEN
+	fim_bdchar();
+#else
+	ef_deln(-exp);
+#endif /*-IMAGEN*/
+}
+
+/* Delete forward or backward N characters.
+ * If arg, kills instead of deleting.
+ */
+ef_deln(x)
+int x;
+{
+	e_igoff(x);
+	if(exp_p) ed_kill(cur_dot, e_dot());
+	else ed_delete(cur_dot, e_dot());
+}
+
+
+#if FX_DELSPC
+/* EFUN: "Delete Horizontal Space" */
+/*	Delete spaces/tabs around point.
+ */
+f_delspc()
+{	chroff dot1;
+
+	e_gobwsp();			/* Move backward over whitespace */
+	dot1 = e_dot();			/* Save point */
+	e_gofwsp();			/* Move forward over whitespace */
+	ed_delete(dot1,e_dot());	/* Delete twixt start and here */
+}
+#endif /*FX_DELSPC*/
+
+
+#if FX_TCHARS
+/* EFUN: "Transpose Characters"
+ *	Transpose chars before and after cursor.  Doesn't hack args yet.
+ * EMACS: With positive arg, exchs chars before & after cursor, moves right,
+ *	and repeats the specified # of times, dragging the char to the
+ *	left of the cursor right.
+ *	With negative arg, transposes 2 chars to left of cursor, moves
+ *	between them, and repeats the specified # of times, exactly undoing
+ *	the positive arg form.  With zero arg, transposes chars at point
+ *	and mark.
+ *	HOWEVER: at the end of a line, with no arg, the preceding 2 chars
+ *	are transposed.
+ */
+f_tchars()
+{	register int c, c2;
+#if IMAGEN
+	c = e_rgetc();			/* Gosmacs style: twiddle prev 2 */
+	if (c == EOF)
+		return(e_gocur());	/* Do nothing at beginning of bfr */
+#else
+
+	if((c = e_getc()) == EOF	/* If at EOF */
+	  || e_rgetc() == LF)		/* or at end of line, */
+		c = e_rgetc();		/* use preceding 2 chars */
+#endif /*-IMAGEN*/
+
+	if((c2 = e_rgetc()) == EOF)	/* At beginning of buffer? */
+		return(e_gocur());	/* Yes, do nothing */
+	e_ovwc(c);
+	e_ovwc(c2);
+	e_setcur();
+	buf_tmod((chroff)-2);		/* Munged these 2 chars */
+}
+#endif /*FX_TCHARS*/
+
+
+#if FX_FWORD
+/* EFUN: "Forward Word" */
+f_fword()
+{	chroff retdot;
+	if(e_wding(&retdot, exp))
+		ed_go(retdot);
+}
+#endif
+
+#if FX_BWORD
+/* EFUN: "Backward Word" */
+f_bword()
+{	exp = -exp;
+	f_fword();
+}
+#endif
+
+#if FX_KWORD
+/* EFUN: "Kill Word" */
+f_kword()
+{	chroff retdot;
+
+	if(e_wding(&retdot,exp))
+	  {	ed_kill(cur_dot,retdot);
+		this_cmd = KILLCMD;
+	  }
+}
+#endif
+
+#if FX_BKWORD
+/* EFUN: "Backward Kill Word" */
+f_bkword()
+{	exp = -exp;
+	f_kword();
+}
+#endif
+
+
+#if FX_TWORDS
+/* EFUN: "Transpose Words" */
+/*	Transpose word.  Urk!
+ */
+f_twords()
+{	register SBSTR *sd1, *sd2;
+	register SBBUF *sb;
+	chroff begwd1, endwd1, begwd2, endwd2;
+
+	endwd2 = e_wdot(cur_dot, 1);	/* Go to end of 2nd word */
+	begwd2 = e_wdot(endwd2, -1);	/* Go to beg of 2nd word */
+	if(begwd2 >= endwd2)		/* If no 2nd word, punt. */
+		return;
+	begwd1 = e_wdot(begwd2, -1);	/* Go to beg of 1st word */
+	endwd1 = e_wdot(begwd1, 1);	/* Go to end of 1st word */
+	if(begwd1 >= endwd1)		/* If no 1st word, punt. */
+		return;
+	if(endwd1 > begwd2)		/* Avoid possible overlap */
+		return;
+
+	e_go(begwd2);
+	sb = (SBBUF *)cur_buf;
+	sd2 = sb_killn(sb, endwd2 - begwd2);	/* Excise wd 2 first */
+	e_go(begwd1);
+	sd1 = sb_killn(sb, endwd1 - begwd1);	/* Excise wd 1 */
+	sb_sins(sb, sd2);			/* Replace with wd 2 */
+	e_goff(begwd2 - endwd1);		/* Move past between stuff */
+	sb_sins(sb, sd1);			/* Insert wd 1 */
+	e_setcur();
+	buf_tmat(begwd1);			/* Modified this range */
+}
+#endif /*FX_TWORDS*/
+
+
+/* Case hacking functions and support */
+
+#if FX_UCWORD
+/* EFUN: "Uppercase Word" */
+f_ucword()
+{	case_word(0);
+}
+#endif /*FX_UCWORD*/
+
+#if FX_LCWORD
+/* EFUN: "Lowercase Word" */
+f_lcword()
+{	case_word(1);
+}
+#endif /*FX_LCWORD*/
+
+#if FX_UCIWORD
+/* EFUN: "Uppercase Initial" */
+f_uciword()
+{	case_word(2);
+}
+#endif /*FX_UCIWORD*/
+
+#if FX_UCWORD||FX_LCWORD||FX_UCIWORD
+case_word (downp)
+{	chroff retdot;
+#if IMAGEN
+	chroff startdot;
+
+	/* Normalize our position to beginning of "current" word,
+	 * where "current" is defined to be the current word we are in,
+	 * or else the previous word if we are not in any word.
+	 * All this silly nonsense just to perpetuate Gosmacs's
+	 * wrong behaviour!
+	 */
+	startdot = cur_dot;	/* Save current position */
+	e_getc();	/* If at beg of word, ensure we get inside it */
+	e_gowd(-1);	/* Go to start of this or prev word */
+	e_setcur();	/* Set cur_dot */
+#endif /*IMAGEN*/
+
+	if(e_wding(&retdot, exp))
+	  {	ed_case(cur_dot,retdot,downp);
+		e_gosetcur(retdot);
+	  }
+#if IMAGEN
+	e_gosetcur(startdot);
+#endif /*IMAGEN*/
+}
+#endif /* any case_word caller */
Index: /trunk/minix/commands/elle/eef2.c
===================================================================
--- /trunk/minix/commands/elle/eef2.c	(revision 9)
+++ /trunk/minix/commands/elle/eef2.c	(revision 9)
@@ -0,0 +1,314 @@
+/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*
+ * EEF2		Various functions
+ */
+
+#include "elle.h"
+
+/* Line Handling functions */
+
+/* EFUN: "Beginning of Line" */
+f_begline()
+{	e_gobol();
+	ed_setcur();
+}
+
+/* EFUN: "End of Line" */
+f_endline()
+{	e_goeol();
+	ed_setcur();
+}
+
+/* EFUN: "Next Line" */
+/*	Goes to beginning of next line */
+f_nxtline()
+{	return(down_bline(exp));
+}
+
+/* EFUN: "Previous Line" */
+/*	Goes to beginning of previous line */
+f_prvline()
+{	return(down_bline(-exp));
+}
+
+/* EFUN: "Down Real Line" */
+f_dnrline ()
+{	down_line(exp);
+}
+
+/* EFUN: "Up Real Line" */
+f_uprline ()
+{	down_line(-exp);
+}
+
+#if FX_OLINE
+/* EFUN: "Open Line" */
+f_oline()
+{	register int i;
+	chroff savdot;
+
+	savdot = cur_dot;
+	if((i = exp) > 0)
+		do { ed_crins(); }
+		while(--i);
+	e_gosetcur(savdot);
+}
+#endif /*FX_OLINE*/
+
+#if FX_DELBLINES
+/* EFUN: "Delete Blank Lines" */
+/*	Delete blank lines around point.
+ */
+f_delblines()
+{	register int c;
+	chroff dot1, dot2, oldcur;
+
+	oldcur = cur_dot;
+	do { e_gobwsp(); }
+	while ((c = e_rgetc()) == LF);
+	if (c != EOF)
+		e_gonl();
+	dot1 = e_dot();
+	if(dot1 > oldcur) return;
+	do { e_gofwsp(); }
+	while ((c = e_getc()) == LF);
+	if(c != EOF)
+		e_gobol();
+	dot2 = e_dot();
+	if(dot2 < oldcur) return;
+	ed_delete(dot1,dot2);
+}
+#endif /*FX_DELBLINES*/
+
+#if FX_KLINE
+/* EFUN: "Kill Line" */
+f_kline()
+{
+	if(exp_p)
+		e_goline(exp);		/* Move that many lines */
+					/* (if 0, goes to BOL) */
+	else				/* No arg, handle specially */
+	  {	if(e_lblankp())		/* Is rest of line blank? */
+			;		/* Yes, now at next line! */
+		else e_goeol();		/* No, go to EOL rather than NL */
+	  }
+	ed_kill(cur_dot,e_dot());
+	e_setcur();
+	this_cmd = KILLCMD;
+}
+#endif /*FX_KLINE*/
+
+#if FX_BKLINE
+/* EFUN: "Backward Kill Line" (not EMACS) */
+/*	Originally an Iconographics function.
+*/
+f_bkline()
+{
+	if(exp_p) exp = -exp;		/* If arg, invert it */
+	else
+	  {	exp = 0;		/* No arg, furnish 0 */
+		exp_p = 1;
+	  }
+	f_kline();			/* Invoke "Kill Line" */
+}
+#endif /*FX_BKLINE*/
+
+#if FX_GOLINE
+/* EFUN: "Goto Line" (not EMACS) (GNU goto-line) */
+f_goline()
+{
+        e_gobob();
+        down_bline(exp-1);    /* already at line 1 */
+}
+#endif /*FX_GOLINE*/
+
+
+down_bline(arg)
+int arg;
+{	
+	if(arg)
+		e_goline(arg);
+	ed_setcur();
+}
+
+#if FX_DNRLINE || FX_UPRLINE
+down_line (x)
+int x;
+{	register int i, res;
+
+	res = x ? e_goline(x) : 1;	/* Move that many lines */
+	goal = 0;
+	if(res == 0)			/* Hit buffer limits (EOF)? */
+	  {	if(x > 0)		/* Moving downwards? */
+		  {
+#if !(IMAGEN)		/* If IMAGEN, do not extend!! */
+			if(x == 1) ed_crins();	/* Yeah, maybe extend */
+			else
+#endif
+				goal = indtion(cur_dot);
+			goto done;
+		  }
+	  }
+
+	if(last_cmd == LINECMD		/* If previous cmd also a line move */
+	  && pgoal != -1)		/* and we have a previous goal col */
+		goal = pgoal;		/* then make it the current goal */
+	else goal = indtion(cur_dot);	/* Else invent goal from current pos */
+
+	i = inindex(e_dot(), goal);	/* See # chars needed to reach goal */
+	if(i == -1)			/* If off edge of line, */
+		e_goeol();		/* just move to end of this line */
+	else e_igoff(i);		/* else move to goal. */
+
+done:	pgoal = goal;
+	this_cmd = LINECMD;
+	ed_setcur();
+}
+#endif /*FX_DNRLINE || FX_UPRLINE*/
+
+
+
+
+/* Region Handling functions */
+
+/* EFUN: "Set/Pop Mark" */
+f_setmark()
+{
+	mark_dot = e_dot();
+	mark_p = 1;
+	if(ev_markshow)			/* If have one, show indicator */
+		saytoo(ev_markshow);	/* that mark was set. */
+}
+
+/* EFUN: "Exchange Point and Mark" */
+f_exchmark()
+{	chroff tmpdot;
+
+	if(chkmark())
+	  {	tmpdot = mark_dot;
+		mark_dot = cur_dot;
+		ed_go(tmpdot);		/* Set cur_dot and go there */
+	  }
+}
+
+/* EFUN: "Kill Region" */
+f_kregion()
+{
+	if(chkmark())
+	  {	ed_kill(cur_dot,mark_dot); /* Will adj cur_dot, mark_dot */
+		e_gocur();
+		this_cmd = KILLCMD;
+	  }
+}
+
+/* EFUN: "Copy Region" */
+f_copreg()
+{
+	if(chkmark())
+	  {	e_gocur();
+		kill_push(e_copyn(mark_dot - cur_dot));
+		e_gocur();
+	  }
+}
+
+
+/* EFUN: "Uppercase Region" */
+f_ucreg()
+{	ef_creg(0);
+}
+
+/* EFUN: "Lowercase Region" */
+f_lcreg()
+{	ef_creg(1);
+}
+
+ef_creg(downp)
+int downp;
+{
+	if(chkmark())
+		ed_case(cur_dot,mark_dot,downp);
+}
+
+#if FX_FILLREG
+/* EFUN: "Fill Region" */
+f_fillreg()
+{	if(chkmark())
+		ed_fill(mark_dot,cur_dot,0);
+}
+#endif /*FX_FILLREG*/
+
+/* CHKMARK() - minor utility for region-hacking functions.
+ *	Returns TRUE if mark exists.
+ *	Otherwise complains to user and returns 0.
+ */
+chkmark()
+{	if(mark_p == 0)
+		ding("No mark!");
+	return(mark_p);
+}
+
+
+/* Paragraph functions */
+
+#if FX_FPARA
+/* EFUN: "Forward Paragraph" */
+f_fpara()
+{	int e_gobpa(), e_goepa();
+
+	exp_do(e_goepa, e_gobpa);
+	ed_setcur();
+}
+#endif /*FX_FPARA*/
+
+#if FX_BPARA
+/* EFUN: "Backward Paragraph" */
+/*	Go to beginning of paragraph.
+ *	Skip all whitespace until text seen, then stop at beginning of
+ *	1st line starting with whitespace.
+ */
+f_bpara()
+{	int e_gobpa(), e_goepa();
+
+	exp_do(e_gobpa, e_goepa);
+	ed_setcur();
+}
+#endif /*FX_BPARA*/
+
+#if FX_MRKPARA
+/* EFUN: "Mark Paragraph" */
+f_mrkpara()
+{
+	f_fpara();		/* Go to end of paragraph */
+	f_setmark();		/* Put mark there */
+	f_bpara();		/* Then back to start of paragraph */
+}
+#endif /*FX_MRKPARA*/
+
+#if FX_FILLPARA
+/* EFUN: "Fill Paragraph" */
+f_fillpara()
+{
+	chroff savloc, endloc;
+
+	savloc = cur_dot;
+#if ICONOGRAPHICS
+        e_getc();			/* DON'T go to next para if at end */
+        e_gobpa();			/* of this one!! */
+#endif /*ICONOGRAPHICS*/
+	e_goepa();			/* Go to end of parag */
+	if(e_rgetc() != LF)		/* If last char EOL, back over it. */
+		e_getc();
+	endloc = e_dot();		/* Remember where end is */
+	e_gobpa();			/* Go to beg of parag */
+#if ICONOGRAPHICS
+        kill_push(e_copyn(endloc - e_dot ()));
+                                        /* put old version on kill ring */
+#endif /*ICONOGRAPHICS*/
+	e_fwsp();			/* Move over initial whitespace */
+	ed_fill(e_dot(), endloc, 0);	/* Fill this region, return to dot */
+}
+#endif /*FX_FILLPARA*/
Index: /trunk/minix/commands/elle/eef3.c
===================================================================
--- /trunk/minix/commands/elle/eef3.c	(revision 9)
+++ /trunk/minix/commands/elle/eef3.c	(revision 9)
@@ -0,0 +1,284 @@
+/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*
+ * EEF3		Various Functions (Yanking, Indentation, miscellaneous)
+ */
+
+#include "elle.h"
+
+#if FX_APPNKILL
+/* EFUN: "Append Next Kill" */
+f_appnkill()
+{	this_cmd = KILLCMD;	/* Fake out next call to ed_kill */
+}
+#endif /*FX_APPNKILL*/
+
+#if FX_UNKILL
+/* EFUN: "Un-kill" */
+f_unkill()
+{	register SBSTR *sd;
+
+	if((sd = kill_ring[kill_ptr]) == 0)
+	  {	ring_bell();
+		return;
+	  }
+	mark_dot = cur_dot;		/* Set mark at old location */
+	mark_p = 1;			/* Mark's been set */
+	sb_sins((SBBUF *)cur_buf,sbs_cpy(sd));	/* Insert copy of stuff */
+	cur_dot = e_dot();		/* We're now after the new stuff */
+	buf_tmat(mark_dot);		/* Say modified from here to cur_dot*/
+	this_cmd = YANKCMD;
+}
+#endif /*FX_UNKILL*/
+
+#if FX_UNKPOP
+/* EFUN: "Un-kill Pop" */
+f_unkpop()
+{	register SBSTR *sd;
+	register int i;
+
+	if (last_cmd != YANKCMD)
+	  {	ring_bell ();
+		return;
+	  }
+	ed_delete(cur_dot,mark_dot);
+	if(cur_dot > mark_dot)
+		cur_dot = mark_dot;
+	i = KILL_LEN;
+	do {
+		if(--kill_ptr < 0)
+			kill_ptr = KILL_LEN-1;
+		if(sd = kill_ring[kill_ptr])
+			break;
+	  } while(--i);
+
+	/* kill_ptr now pointing to right place; effect the yank. */
+	e_gocur();		/* Make sure point at right place too! */
+	return(f_unkill());
+}
+#endif /*FX_UNKPOP*/
+
+
+/* Indentation routines - still not polished */
+
+#if FX_INDATM
+/* EFUN: "Indent According to Mode" */
+/*	In Fundamental mode, just inserts a tab.
+*/
+f_indatm()
+{	f_insself(TAB);		/* This takes care of mode checking */
+}
+#endif /*FX_INDATM*/
+
+#if FX_INDNL
+/* EFUN: "Indent New Line" */
+f_indnl()			/* execute CR followed by tab */
+{
+#if IMAGEN
+	/* Not dispatch-based, but rather hard-wired to do Gosmacs thing */
+	ed_crins();
+	f_indund();
+#else
+	cmd_xct(CR);
+	cmd_xct(TAB);
+#endif /*-IMAGEN*/
+}
+#endif /*FX_INDNL*/
+
+
+#if FX_BACKIND
+/* EFUN: "Back to Indentation"
+**	Moves to end of current line's indentation.
+*/
+f_backind()
+{	e_gobol();	/* First move to beg of line */
+	e_gofwsp();	/* Then forward over whitespace */
+	ed_setcur();
+}
+#endif /*FX_BACKIND*/
+
+
+#if FX_INDCOMM
+
+static char *comm_beg = "/* ";
+static char *comm_end = " */";
+
+/* EFUN: "Indent for Comment" */
+f_indcomm()
+{
+	f_endline();
+	if(indtion(cur_dot) < ev_ccolumn)
+		ed_indto(ev_ccolumn);
+	else ed_sins("  ");
+	ed_sins (comm_beg);
+	ed_sins (comm_end);
+	e_igoff(-strlen (comm_end));       /* back over end string */
+	e_setcur();
+}
+#endif /*FX_INDCOMM*/
+
+#if FX_INDREL
+/* EFUN: "Indent Relative" */
+/* This used to mistakenly be called Indent Under.
+**	Still not fully implemented.
+**	If at beginning of line, looks back at previous indented line,
+** and indents this line that much.  If there is no preceding indented
+** line or not at beginning of line, insert a tab.
+*/
+f_indrel()
+{	register int c;
+	register  n;
+#if IMAGEN
+	chroff savdot;
+#endif /*IMAGEN*/
+#if ICONOGRAPHICS
+        chroff savdot;
+        int curind, newind, morebuf;
+#endif /*ICONOGRAPHICS*/
+
+	if((c = e_rgetc()) == EOF)
+#if IMAGEN
+		return(f_insself(TAB));	/* Do mode-based tabbing */
+#else
+		return(ed_insert(TAB));
+#endif /*-IMAGEN*/
+
+	if(c == LF)
+	  {	e_gobol();
+		e_gofwsp();
+		n = d_curind();
+		e_gonl();		/* Return to orig pos */
+		if(n)
+		  {	ed_indto(n);
+#if IMAGEN
+			savdot = e_dot();
+			e_gofwsp();
+			ed_delete(savdot, e_dot());
+#endif /*IMAGEN*/
+			return;
+		  }
+	  }
+#if ICONOGRAPHICS
+        else
+          {     e_igoff (1);
+                curind = indtion (savdot = e_dot ());
+                                /* get current dot and indentation */
+                while (1)       /* find a prev line that extends rightward */
+                   {    morebuf = e_gopl ();
+                        e_goeol ();
+                        if ((newind = d_curind()) > curind) break;
+                        if (morebuf == 0)  /* hit beginning of buffer */
+                        {       e_go (savdot);
+                                f_delspc();
+                                return (1);
+                        }
+                   }
+
+                e_gobol ();
+                e_igoff (inindex (e_dot (), curind));
+                if (d_curind() > curind)
+                        e_rgetc ();              /* pushed ahead by tab */
+
+                while (c_wsp (e_getc ()) == 0) ;
+                e_backc ();
+                e_fwsp ();
+                newind = d_curind();
+                e_go (savdot);
+                f_delspc();
+                ed_indto (newind);
+           }
+#else
+        else e_getc();
+#if IMAGEN
+	f_insself(TAB);			/* Do mode-based tabbing */
+#else
+	ed_insert(TAB);
+#endif /*-IMAGEN*/
+#endif /*-ICONOGRAPHICS*/
+}
+#endif /*FX_INDREL*/
+
+
+
+/* Paren matching stuff.  Note that this stuff will be very painful unless
+** tinwait() works properly.
+*/
+#if 0
+/* EFUN: "Self-Insert and Match" (intended to be bound to brackets) */
+/* (KLH: Evidently this was never finished)
+*/
+insertmatch(c)
+register int c;
+{
+	
+}
+#endif
+
+/* Should change this to Matching Paren */
+#if FX_MATCHBRACK
+/* EFUN: "Match Bracket" (not EMACS) - from IMAGEN config
+ * Show the matching bracket for the character right before dot
+ */
+f_matchbrack()
+{
+	chroff savdot;
+	register int i, mc, secs;
+
+	if (exp_p)
+		secs = exp;
+	else
+		secs = 1;
+	savdot = cur_dot;		/* Save our location */
+	mc = e_rgetc();			/* Pick up character before dot */
+	if (mc != ')' && mc != ']' && mc != '}')
+	  {	e_getc();		/* Nothing, try at dot instead */
+		e_getc();
+		mc = e_rgetc();
+		if (mc != ')' && mc != ']' && mc != '}')
+		  {	ding("What bracket?");
+			e_go(savdot);
+			return;
+		  }
+	  }
+	if (! matchonelevel(mc))
+		ring_bell();
+	else
+	  {	ed_setcur();
+	        if (d_line(cur_dot) < 0)
+			secs = 10;	/* Wait longer if off-screen */
+		redisplay();		/* Wish it were simple upd_wind() */
+	        for (i = 1; i <= secs; ++i)
+		  {	if (tinwait())
+				break;
+			sleep(1);
+	          }
+	  }
+	e_gosetcur(savdot);		/* Back to origin */
+	redp(RD_MOVE);			/* Cursor has moved */
+}
+
+
+/* Try to match 'mc', return true iff found it */
+matchonelevel(mc)
+register int mc;
+{
+	register int c;
+
+	while ((c = e_rgetc()) != EOF)
+	  {	if (c == /*[*/ ']' || c == /*(*/ ')' || c == /*{*/ '}')
+		  {	if (! matchonelevel(c))
+				break;
+		  }
+		else if (c == '(' /*)*/)
+			return(mc == /*(*/ ')');
+		else if (c == '[' /*]*/)
+			return(mc == /*[*/ ']');
+		else if (c == '{' /*}*/)
+			return(mc == /*{*/ '}');
+	  }
+	return(0);
+}
+#endif /*FX_MATCHBRACK*/
Index: /trunk/minix/commands/elle/eefd.c
===================================================================
--- /trunk/minix/commands/elle/eefd.c	(revision 9)
+++ /trunk/minix/commands/elle/eefd.c	(revision 9)
@@ -0,0 +1,439 @@
+/* ELLE - Copyright 1982, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+
+/* EEFD		Display control functions
+ */
+
+#include "elle.h"
+
+
+#if FX_NEWWIN
+/* EFUN: "New Window" */
+/* 	Clear current window and set as requested.
+ *		^L - clear current window and redisplay it (default top)
+ *		<arg>^L - select new window so that current line is
+ *			the <arg>'th from top of window (0 = top line)
+ *		^U^L - clear current line and redisplay.
+ */
+f_newwin()
+{	register int i, n;
+	register struct window *w;
+
+	d_fixcur();		/* Ensure screen vars correct */
+	w = cur_win;
+	if (exp_p)
+	  {	if((n = exp) == 4 && exp_p == 4		/* CTRL-U? */
+		  && (i = d_line(cur_dot)) >= 0)	/* On valid line? */
+		  {	d_lupd(w, i);			/* Update it */
+			return;
+		  }
+	  }
+	else			/* No argument given */
+	  {	redp(RD_SCREEN);	/* Clear whole screen (later just window? */
+#if IMAGEN
+		return;
+#else
+		n = (ev_nwpct*w->w_ht)/100;	/* Set new window using % */
+#endif /*-IMAGEN*/
+	  }
+	if (n < 0) n = 0;		/* Ensure # is reasonable */
+	else if (n >= w->w_ht)
+		n = w->w_ht - 1;
+	d_fgoloff(-n);			/* Go up given # of lines */
+	w->w_topldot = e_dot();		/* Set new top-line dot */
+	e_gocur();			/* Move back to cur_dot */
+	redp(RD_FIXWIN);		/* Say to re-hack window */
+}
+#endif /*FX_NEWWIN*/
+
+#if FX_NSCREEN
+/* EFUN: "Next Screen" */
+f_nscreen()
+{	d_screen( exp);
+}
+#endif /*FX_NSCREEN*/
+
+#if FX_PSCREEN
+/* EFUN: "Previous Screen" */
+f_pscreen()
+{	d_screen(-exp);
+}
+#endif /*FX_PSCREEN*/
+
+#if FX_OTHNSCREEN
+/* EFUN: "Other New Screen" (not EMACS) - from IMAGEN config */
+f_othnscreen()
+{
+	if (! oth_win)
+		return;
+	f_othwind();
+	if (exp_p)			/* With arg, back up */
+		d_screen(-1);
+	else
+		d_screen(1);
+	f_othwind();
+	redp(RD_WINDS);			/* Look at all windows */
+}
+#endif /*FX_OTHNSCREEN*/
+
+
+#if FX_LWINDBORD
+/* EFUN: "Line to Window Border" (not EMACS) - from IMAGEN config */
+f_lwindbord()
+{
+	if (exp_p)
+		/* With arg, means "to bottom" */
+		exp = cur_win->w_ht - 1;
+	else
+		/* Else, to top */
+		exp = 0;
+
+	/* Just a "front end" for ^L */
+	exp_p = 1;
+	f_newwin();
+}
+#endif /*FX_LWINDBORD*/
+
+#if FX_SCUPWIND
+/* EFUN: "Scroll Window Up" (not EMACS) - from IMAGEN config */
+f_scupwind()
+{
+	scroll_win(exp);
+}
+#endif /*FX_SCUPWIND*/
+
+#if FX_SCDNWIND
+/* EFUN: "Scroll Window Down" (not EMACS) - from IMAGEN config */
+f_scdnwind()
+{
+	scroll_win(-exp);
+}
+#endif /*FX_SCDNWIND*/
+
+
+#if FX_MVWTOP
+/* EFUN: "Move to Window Top" (not EMACS) - from IMAGEN config */
+f_mvwtop()
+{
+	extern moveborder();
+	moveborder(1);
+}
+#endif /*FX_MVWTOP*/
+
+#if FX_MVWBOT
+/* EFUN: "Move to Window Bottom" (not EMACS) - from IMAGEN config */
+f_mvwbot()
+{
+	extern moveborder();
+	moveborder(0);
+}
+#endif /*FX_MVWBOT*/
+
+
+
+
+#if FX_NSCREEN || FX_PSCREEN || FX_OTHNSCREEN
+/* Move to new loc by N screenfuls.
+ * If moving downward, keep bottom 2 lines of current screen on top of next.
+ * If moving up, keep top 2 lines of current screen on bottom of next.
+ */
+d_screen(rep)
+int rep;
+{
+	register int i;
+	register struct window *w;
+	chroff newdot;
+
+	w = cur_win;
+	if((i = w->w_ht - 2) <= 0)	/* Just-in-case check */
+		i = 1;
+	if((i *= rep) == 0)
+		return;
+	d_fixcur();			/* Ensure window fixed up */
+	e_go(w->w_topldot);		/* Start at top of screen */
+	d_fgoloff(i);
+
+	/* Find where we are now, and make that the new top of window. */
+	if((newdot = e_dot()) != e_blen())	/* If not at EOF, */
+		w->w_topldot = newdot;	/* set new top of window! */
+	else w->w_topldot = 0;		/* Else let fix_wind select top. */
+
+	e_setcur();			/* Ensure cur_dot set to real loc */
+#if IMAGEN
+	redp(RD_WINRES|RD_REDO);	/* HINT: just repaint screen */
+#else
+	redp(RD_FIXWIN|RD_MOVE);
+#endif /*-IMAGEN*/
+}
+#endif /*FX_NSCREEN || FX_PSCREEN || FX_OTHNSCREEN*/
+
+
+#if FX_SCUPWIND || FX_SCDNWIND	/* If want scroll-window function */
+scroll_win(n)
+register int n;
+{	register struct window *w = cur_win;
+	chroff savdot;
+
+	if (n == 0) return;
+	d_fixcur();		/* Ensure screen vars for win all set up */
+	e_go(w->w_topldot);	/* Go to top of current window */
+	d_fgoloff(n);		/* Move given # of display lines */
+	w->w_topldot = e_dot();	/* Set new top of window */
+	redp(RD_FIXWIN);	/* Say new window needs fixing up */
+
+	/* Now adjust position of current dot so it is still within window */
+	if (n > 0)
+	  {	/* Moving screen text "up" (win down) */
+		if (cur_dot < w->w_topldot)	/* See if scrolled off top */
+			e_setcur();		/* yes, make dot be win top */
+	  }
+	else {	/* Moving screen text "down" (win up) */
+		savdot = cur_dot;	/* Save since must temporarily */
+		e_setcur();		/* set current dot within window, */
+		d_fixcur();		/* so screen can be fixed up. */
+		if (inwinp(w, savdot))	/* Now see if old dot in new win */
+			cur_dot = savdot;	/* Yes, just restore it! */
+		else			/* No, make it beg of bottom line. */
+			cur_dot = scr[w->w_pos + w->w_ht - 1]->sl_boff;
+	  }
+	e_gocur();		/* Make current pos be cur_dot */
+}
+#endif /* FX_SC%%WIND */
+
+#if FX_MVWTOP || FX_MVWBOT	/* Guts for above two functions */
+static
+moveborder(top)
+int top;
+{
+	d_fixcur();		/* Ensure current win screen image fixed up */
+	e_gosetcur(top ? cur_win->w_topldot
+			: scr[cur_win->w_pos + cur_win->w_ht - 1]->sl_boff);
+
+	redp(RD_MOVE);		/* Should only be cursor adjustment */
+}
+#endif /*FX_MVW%%%*/
+
+
+/* Given a line and a position in that line, return the xpos.
+ * NOTE CAREFULLY that when line extends over several screen lines,
+ * the value returned is the screen X position even though it
+ * may be some lines down from the start of the logical line!
+ * Also note this won't work very well if tabs exist on the extra
+ * lines.  This rtn should not be used for cursor positioning.
+ * Also note: d_ncols() will never return -1 meaning EOL because the
+ * setup guarantees there is no EOL within the range checked.
+ */
+d_curind()	/* Find current indentation */
+{	indtion(e_dot());
+}
+indtion(lin)
+chroff lin;
+{	register int i, col;
+	chroff savdot;
+	chroff nchars;
+
+	savdot = e_dot();		/* Save current position */
+	e_go(lin);			/* Go to line caller wants */
+	e_gobol();			/* Go to its beginning */
+	col = 0;			/* Start at left margin */
+	if((nchars = lin - e_dot()) > 0)
+	    do {
+		if(nchars < (i = scr_wd0))
+			i = nchars;
+		if((col = d_ncols(i, col)) < 0)	/* Hit edge of screen? */
+			col = 0;		/* Reset to left margin */
+	    } while((nchars -= i) > 0);
+	e_go(savdot);			/* Restore current position */
+	return(col);
+}
+
+/* ININDEX - How many positions in lin must we go to get to xpos?
+ * Returns -1 if can't be done.  Assumes "lin" is at beginning of a line!
+ */
+
+inindex (lin, xpos)
+chroff lin;
+int   xpos;
+{	register int col, x;
+	chroff savdot;
+	char tmp[MAXLINE+MAXCHAR];
+	extern int sctreol;		/* From EEDISP */
+
+	if((x = xpos) <= 0) return(0);
+	if(x >= MAXLINE) return(-1);	/* ?!? */
+	col = 0;
+	savdot = e_dot();
+	e_go(lin);			/* Assumes this is start of line */
+	col = sctrin(tmp, x, 0);	/* Translate from sb_getc input */
+	if((col - x) >= 0)		/* Exact count-out or past it? */
+	  {	x = e_dot() - lin;	/* Yup, win. */
+		if (sctreol > 0)	/* Did we hit (and include) EOL? */
+#if FX_EOLMODE			/* If so, back up over the EOL. */
+			x -= eolcrlf(cur_buf) ? 2 : 1;
+#else
+			--x;
+#endif
+	  }
+	else x = -1;			/* Nope, EOL or EOF hit too soon. */
+	e_go(savdot);
+	return(x);
+}
+
+
+/*
+ * D_ ROUTINES - display-relative functions.  Similar to E_, but
+ *	a "line" is defined as one line of the screen rather than
+ *	as a logical text line.  Also, for efficiency reasons
+ *	arguments are given saying how many lines to hack.
+ */
+
+d_gopl() { return(d_goloff(-1)); }
+d_gonl() { return(d_goloff( 1)); }
+
+/* D_GOLOFF(i) - Go to beginning of a display line
+ * D_FGOLOFF(i) - ditto, but assumes screen image of window already fixed up.
+ *	i - # of lines offset.  Negative moves up, positive down.
+ *		Zero arg goes to beginning of current display line.
+ *	Side effects: screen image of window is fixed up at
+ *	start of routine, but is NOT updated by the move to new location.
+ */
+d_goloff(cnt)
+int cnt;
+{	d_fixcur();
+	d_fgoloff(cnt);		/* Now can invoke fixed-up fast version */
+}
+d_fgoloff(cnt)
+register int cnt;
+{	register int y;
+	struct scr_line l;
+	char line[MAXLINE+MAXCHAR];
+	int top, bot;
+
+	/* Find current position in window, since can save time
+	 * by using stuff already in fixed-up screen image.
+	 */
+	if((y = d_line(e_dot())) < 0)		/* Get current Y position */
+	  {
+		errbarf("Dot out of window");
+		y = 0;
+	  }
+	top = cur_win->w_pos;		/* 1st line of window */
+	bot = top + cur_win->w_ht;	/* 1st line not in window */
+	l.sl_boff = scr[y]->sl_boff;
+	l.sl_nlin = &line[0];
+	l.sl_cont = 0;
+
+	if(cnt > 0) goto down;
+	
+	/* Go upwards.  This is hairy because we want to be clever about
+	 * huge logical lines -- avoid going all the way back to BOL.
+	 */
+	if((y+cnt) >= top)	/* Fits? */
+		goto onscr;	/* Hurray, hack it! */
+	cnt += y - top;		/* Sigh, find # lines to skip */
+	y = top;
+	l.sl_boff = scr[y]->sl_boff;
+	e_go(l.sl_boff);
+
+	/* Okay, here's the hairy part.  Must go backwards from top
+	 * line; if no EOL within scr_wid*cnt chars, then simply assume one is
+	 * seen.
+	 */
+	cnt = -cnt;
+	d_backup(cnt);
+	return;		/* Really should re-adjust stuff, but... */
+
+	/* Go downwards.  Not too bad... */
+down:
+	if((y+cnt) <= bot)	/* Fits? */
+		goto onscr;	/* Hurray, hack it! */
+	cnt -= bot - y;		/* Sigh, find # lines can skip */
+	y = bot - 1;
+	l.sl_boff = scr[y]->sl_boff + scr[y]->sl_len;
+	if(y > top
+	  && (l.sl_cont = scr[y-1]->sl_cont))
+		l.sl_line = scr[y-1]->sl_line;
+	e_go(l.sl_boff);
+
+	do {
+		fix_line(&l,&l);
+	  } while(--cnt > 0 && l.sl_len);
+	return;
+
+onscr:	if((y += cnt) >= bot)
+	  {	--y;
+		e_go(scr[y]->sl_boff + scr[y]->sl_len);
+	  }
+	else e_go(scr[y]->sl_boff);
+}
+
+/* D_FIXCUR() - Ensure current window is fixed up, with
+ *	current location (not necessarily cur_dot)!
+ * Ensure cur_dot reflects real loc so that fix_wind will work,
+ * and always call fix_wind to ensure that screen image vars
+ * are set properly.  Note any active redisplay flags must be carried
+ * on into window redisplay flags, so fix_wind will notice them.
+ */
+d_fixcur()
+{	register struct window *w;
+	chroff savedot;
+
+	w = cur_win;
+	savedot = cur_dot;
+	e_setcur();
+	w->w_redp |= rd_type&RDS_WINFLGS;
+	fix_wind(w);		/* Always ensure window is set up! */
+	redp(w->w_redp);	/* Add back new flags */
+	rd_type &= ~RDS_DOFIX;	/* and flush fix-invoking ones */
+	cur_dot = savedot;	/* Restore cur_dot, no longer hacked. */
+}
+
+
+d_backup(nlin)		/* Try to back up by nlin screen lines */
+int nlin;
+{	register int cnt, n, c;
+	int eolstop;
+
+	if((cnt = nlin+1) <= 0) return;
+	c = 0;
+	do
+	  {	n = scr_wid;
+		eolstop = 0;		/* Not yet stopped at EOL */
+		do {	if((c = e_rgetc()) == EOF)
+				return;
+			if(c == LF)
+			  {
+#if FX_EOLMODE
+				if(eolcrlf(cur_buf))
+				  {	if((c = e_rgetc()) == CR)
+					  {	eolstop++;
+						break;
+					  }
+					if(c != EOF)
+						e_getc();
+				  }
+				else
+#endif
+				  {	eolstop++;
+					break;
+				  }
+			  }
+		  } while(--n);
+	  } while(--cnt);
+	if(eolstop)
+	  {
+#if FX_EOLMODE
+		if(eolcrlf(cur_buf)) e_getc();	/* Skip back over CR */
+#endif
+		e_getc();		/* Skip back over LF */
+	  }
+
+	/* At this point, dot is guaranteed to be less than goal,
+	 * which is the important thing for fix_wind, which can handle
+	 * things okay if dot is off bottom of window.
+	 */
+	return(1);		/* Say always test result */
+}
Index: /trunk/minix/commands/elle/eefdef.h
===================================================================
--- /trunk/minix/commands/elle/eefdef.h	(revision 9)
+++ /trunk/minix/commands/elle/eefdef.h	(revision 9)
@@ -0,0 +1,159 @@
+/* .H Function Definition file, generated by ELLEC */
+/*   0 */ EFUNHOLE /* Always undefined */
+/*   1 */ EFUN( f_insself   , "f_insself"   , "Insert Self")
+/*   2 */ EFUN( f_quotins   , "f_quotins"   , "Quoted Insert")
+/*   3 */ EFUN( f_crlf      , "f_crlf"      , "CRLF")
+/*   4 */ EFUN( f_fchar     , "f_fchar"     , "Forward Character")
+/*   5 */ EFUN( f_bchar     , "f_bchar"     , "Backward Character")
+/*   6 */ EFUN( f_dchar     , "f_dchar"     , "Delete Character")
+/*   7 */ EFUN( f_bdchar    , "f_bdchar"    , "Backward Delete Character")
+/*   8 */ EFUN( f_delspc    , "f_delspc"    , "Delete Horizontal Space")
+/*   9 */ EFUN( f_tchars    , "f_tchars"    , "Transpose Characters")
+/*  10 */ EFUN( f_fword     , "f_fword"     , "Forward Word")
+/*  11 */ EFUN( f_bword     , "f_bword"     , "Backward Word")
+/*  12 */ EFUN( f_kword     , "f_kword"     , "Kill Word")
+/*  13 */ EFUN( f_bkword    , "f_bkword"    , "Backward Kill Word")
+/*  14 */ EFUN( f_twords    , "f_twords"    , "Transpose Words")
+/*  15 */ EFUN( f_ucword    , "f_ucword"    , "Uppercase Word")
+/*  16 */ EFUN( f_lcword    , "f_lcword"    , "Lowercase Word")
+/*  17 */ EFUN( f_uciword   , "f_uciword"   , "Uppercase Initial")
+/*  18 */ EFUNHOLE
+/*  19 */ EFUNHOLE
+/*  20 */ EFUN( f_begline   , "f_begline"   , "Beginning of Line")
+/*  21 */ EFUN( f_endline   , "f_endline"   , "End of Line")
+/*  22 */ EFUN( f_nxtline   , "f_nxtline"   , "Next Line")
+/*  23 */ EFUN( f_prvline   , "f_prvline"   , "Previous Line")
+/*  24 */ EFUN( f_dnrline   , "f_dnrline"   , "Down Real Line")
+/*  25 */ EFUN( f_uprline   , "f_uprline"   , "Up Real Line")
+/*  26 */ EFUN( f_oline     , "f_oline"     , "Open Line")
+/*  27 */ EFUN( f_delblines , "f_delblines" , "Delete Blank Lines")
+/*  28 */ EFUN( f_kline     , "f_kline"     , "Kill Line")
+/*  29 */ EFUN( f_bkline    , "f_bkline"    , "Backward Kill Line")
+/*  30 */ EFUN( f_goline    , "f_goline"    , "Goto Line")
+/*  31 */ EFUNHOLE
+/*  32 */ EFUNHOLE
+/*  33 */ EFUNHOLE
+/*  34 */ EFUNHOLE
+/*  35 */ EFUN( f_setmark   , "f_setmark"   , "Set/Pop Mark")
+/*  36 */ EFUN( f_exchmark  , "f_exchmark"  , "Exchange Point and Mark")
+/*  37 */ EFUN( f_kregion   , "f_kregion"   , "Kill Region")
+/*  38 */ EFUN( f_copreg    , "f_copreg"    , "Copy Region")
+/*  39 */ EFUN( f_ucreg     , "f_ucreg"     , "Uppercase Region")
+/*  40 */ EFUN( f_lcreg     , "f_lcreg"     , "Lowercase Region")
+/*  41 */ EFUN( f_fillreg   , "f_fillreg"   , "Fill Region")
+/*  42 */ EFUNHOLE
+/*  43 */ EFUNHOLE
+/*  44 */ EFUNHOLE
+/*  45 */ EFUN( f_fpara     , "f_fpara"     , "Forward Paragraph")
+/*  46 */ EFUN( f_bpara     , "f_bpara"     , "Backward Paragraph")
+/*  47 */ EFUN( f_mrkpara   , "f_mrkpara"   , "Mark Paragraph")
+/*  48 */ EFUN( f_fillpara  , "f_fillpara"  , "Fill Paragraph")
+/*  49 */ EFUNHOLE
+/*  50 */ EFUN( f_selbuffer , "f_selbuffer" , "Select Buffer")
+/*  51 */ EFUN( f_selxbuffer, "f_selxbuffer", "Select Existing Buffer")
+/*  52 */ EFUN( f_kbuffer   , "f_kbuffer"   , "Kill Buffer")
+/*  53 */ EFUN( f_listbufs  , "f_listbufs"  , "List Buffers")
+/*  54 */ EFUN( f_bufnotmod , "f_bufnotmod" , "Buffer Not Modified")
+/*  55 */ EFUN( f_eolmode   , "f_eolmode"   , "EOL CRLF Mode")
+/*  56 */ EFUN( f_gobeg     , "f_gobeg"     , "Goto Beginning")
+/*  57 */ EFUN( f_goend     , "f_goend"     , "Goto End")
+/*  58 */ EFUN( f_whatpage  , "f_whatpage"  , "What Page")
+/*  59 */ EFUNHOLE
+/*  60 */ EFUN( f_ffile     , "f_ffile"     , "Find File")
+/*  61 */ EFUN( f_rfile     , "f_rfile"     , "Read File")
+/*  62 */ EFUN( f_vfile     , "f_vfile"     , "Visit File")
+/*  63 */ EFUN( f_ifile     , "f_ifile"     , "Insert File")
+/*  64 */ EFUN( f_sfile     , "f_sfile"     , "Save File")
+/*  65 */ EFUN( f_savefiles , "f_savefiles" , "Save All Files")
+/*  66 */ EFUN( f_wfile     , "f_wfile"     , "Write File")
+/*  67 */ EFUN( f_wreg      , "f_wreg"      , "Write Region")
+/*  68 */ EFUN( f_wlastkill , "f_wlastkill" , "Write Last Kill")
+/*  69 */ EFUNHOLE
+/*  70 */ EFUN( f_2winds    , "f_2winds"    , "Two Windows")
+/*  71 */ EFUN( f_1wind     , "f_1wind"     , "One Window")
+/*  72 */ EFUN( f_othwind   , "f_othwind"   , "Other Window")
+/*  73 */ EFUN( f_growind   , "f_growind"   , "Grow Window")
+/*  74 */ EFUN( f_shrinkwind, "f_shrinkwind", "Shrink Window")
+/*  75 */ EFUN( f_delwind   , "f_delwind"   , "Delete Window")
+/*  76 */ EFUN( f_sowind    , "f_sowind"    , "Standout Window")
+/*  77 */ EFUN( f_2modewinds, "f_2modewinds", "Two Mode Windows")
+/*  78 */ EFUN( f_newwin    , "f_newwin"    , "New Window")
+/*  79 */ EFUN( f_nscreen   , "f_nscreen"   , "Next Screen")
+/*  80 */ EFUN( f_pscreen   , "f_pscreen"   , "Previous Screen")
+/*  81 */ EFUNHOLE
+/*  82 */ EFUNHOLE
+/*  83 */ EFUN( f_scupwind  , "f_scupwind"  , "Scroll Window Up")
+/*  84 */ EFUN( f_scdnwind  , "f_scdnwind"  , "Scroll Window Down")
+/*  85 */ EFUN( f_mvwtop    , "f_mvwtop"    , "Move to Window Top")
+/*  86 */ EFUN( f_mvwbot    , "f_mvwbot"    , "Move to Window Bottom")
+/*  87 */ EFUNHOLE
+/*  88 */ EFUNHOLE
+/*  89 */ EFUNHOLE
+/*  90 */ EFUN( f_setprof   , "f_setprof"   , "Set Profile")
+/*  91 */ EFUN( f_pfxmeta   , "f_pfxmeta"   , "Prefix Meta")
+/*  92 */ EFUN( f_pfxext    , "f_pfxext"    , "Prefix Extend")
+/*  93 */ EFUN( f_uarg      , "f_uarg"      , "Universal Arg")
+/*  94 */ EFUN( f_negarg    , "f_negarg"    , "Negative Argument")
+/*  95 */ EFUN( f_argdig    , "f_argdig"    , "Argument Digit")
+/*  96 */ EFUN( f_vtbuttons , "f_vtbuttons" , "VT100 Button Hack")
+/*  97 */ EFUN( f_describe  , "f_describe"  , "Describe")
+/*  98 */ EFUNHOLE
+/*  99 */ EFUNHOLE
+/* 100 */ EFUN( f_skmac     , "f_skmac"     , "Start Kbd Macro")
+/* 101 */ EFUN( f_ekmac     , "f_ekmac"     , "End Kbd Macro")
+/* 102 */ EFUN( f_xkmac     , "f_xkmac"     , "Execute Kbd Macro")
+/* 103 */ EFUN( f_vkmac     , "f_vkmac"     , "View Kbd Macro")
+/* 104 */ EFUNHOLE
+/* 105 */ EFUN( f_unkill    , "f_unkill"    , "Un-kill")
+/* 106 */ EFUN( f_unkpop    , "f_unkpop"    , "Un-kill Pop")
+/* 107 */ EFUN( f_appnkill  , "f_appnkill"  , "Append Next Kill")
+/* 108 */ EFUNHOLE
+/* 109 */ EFUNHOLE
+/* 110 */ EFUN( f_srch      , "f_srch"      , "String Search")
+/* 111 */ EFUN( f_rsrch     , "f_rsrch"     , "Reverse String Search")
+/* 112 */ EFUN( f_isrch     , "f_isrch"     , "Incremental Search")
+/* 113 */ EFUN( f_risrch    , "f_risrch"    , "Reverse Search")
+/* 114 */ EFUN( f_repstr    , "f_repstr"    , "Replace String")
+/* 115 */ EFUN( f_querep    , "f_querep"    , "Query Replace")
+/* 116 */ EFUN( f_repline   , "f_repline"   , "Replace in Line")
+/* 117 */ EFUN( f_sfcol     , "f_sfcol"     , "Set Fill Column")
+/* 118 */ EFUN( f_sfpref    , "f_sfpref"    , "Set Fill Prefix")
+/* 119 */ EFUN( f_fillmode  , "f_fillmode"  , "Auto Fill Mode")
+/* 120 */ EFUNHOLE
+/* 121 */ EFUN( f_indatm    , "f_indatm"    , "Indent According to Mode")
+/* 122 */ EFUN( f_indnl     , "f_indnl"     , "Indent New Line")
+/* 123 */ EFUN( f_backind   , "f_backind"   , "Back to Indentation")
+/* 124 */ EFUN( f_indcomm   , "f_indcomm"   , "Indent for Comment")
+/* 125 */ EFUN( f_indrel    , "f_indrel"    , "Indent Relative")
+/* 126 */ EFUNHOLE
+/* 127 */ EFUNHOLE
+/* 128 */ EFUNHOLE
+/* 129 */ EFUNHOLE
+/* 130 */ EFUN( f_pshinf    , "f_pshinf"    , "Push to Inferior")
+/* 131 */ EFUN( f_retsup    , "f_retsup"    , "Return to Superior")
+/* 132 */ EFUN( f_wfexit    , "f_wfexit"    , "Write File Exit")
+/* 133 */ EFUNHOLE
+/* 134 */ EFUNHOLE
+/* 135 */ EFUNHOLE
+/* 136 */ EFUNHOLE
+/* 137 */ EFUNHOLE
+/* 138 */ EFUNHOLE
+/* 139 */ EFUNHOLE
+/* 140 */ EFUN( f_bkpt      , "f_bkpt"      , "Hit Breakpoint")
+/* 141 */ EFUN( f_debug     , "f_debug"     , "Debug Mode")
+/* 142 */ EFUNHOLE
+/* 143 */ EFUNHOLE
+/* 144 */ EFUNHOLE
+/* 145 */ EFUNHOLE
+/* 146 */ EFUNHOLE
+/* 147 */ EFUNHOLE
+/* 148 */ EFUNHOLE
+/* 149 */ EFUNHOLE
+/* 150 */ EFUNHOLE
+/* 151 */ EFUNHOLE
+/* 152 */ EFUNHOLE
+/* 153 */ EFUNHOLE
+/* 154 */ EFUNHOLE
+/* 155 */ EFUNHOLE
+/* 156 */ EFUNHOLE
+/* 157 */ EFUNHOLE
Index: /trunk/minix/commands/elle/eefed.c
===================================================================
--- /trunk/minix/commands/elle/eefed.c	(revision 9)
+++ /trunk/minix/commands/elle/eefed.c	(revision 9)
@@ -0,0 +1,285 @@
+/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*	EEFED - ED-type functions
+ */
+#include "elle.h"
+
+/*
+ * ED_INSERT -- Insert character given as argument.
+ */
+
+ed_insert(c)
+int c;
+{	register SBBUF *sb;
+
+	sb = (SBBUF *) cur_buf;		/* For a little speed */
+	sb_putc(sb,c);		/* Insert the char */
+	cur_dot++;		/* Advance dot */
+	buf_tmod((chroff)-1);	/* Mark buffer modified, for redisplay etc. */
+				/* Perhaps later use specialized routine? */
+}
+
+ed_insn(ch, cnt)
+int ch, cnt;
+{	register int i;
+	if((i = cnt) > 0)
+		do { ed_insert(ch);
+		  } while(--i);
+}
+
+ed_crins()
+{
+#if FX_EOLMODE
+	if (eolcrlf(cur_buf))	/* If EOL is made of CR-LF */
+		ed_insert(CR);	/* then first insert CR, then drop down to */
+#endif
+	ed_insert(LF);		/* Insert LF */
+}
+
+
+ed_sins (s)			       /* insert this string */
+register char *s;
+{	register c;
+	while (c = *s++)
+		ed_insert (c);
+}
+
+ed_nsins (s, i)		/* Insert string of N chars */
+register char *s;
+register int i;
+{	if(i > 0)
+		do { ed_insert(*s++); } while(--i);
+}
+
+/* ED_INDTO(col) - Indent to specified column.
+**	Finds current cursor position, and inserts tabs and spaces
+** so cursor ends up at column goal.  Does nothing if already at or past
+** specified column.
+*/
+
+ed_indto(goal)
+register int goal;
+{	register int ng;
+
+	ng = goal & ~07;		/* Get distance to tab stop */
+	ed_insn(TAB, ((ng - (d_curind() & ~07)) >> 3));
+	ed_insn(SP, goal-ng);
+}
+
+
+/* Oddball routine - Set cur_dot to actual I/O location and
+ * tell display that cursor probably moved.  This is not really a
+ * function of itself; it provides support for real functions.
+ */
+ed_setcur()
+{	e_setcur();	/* Set cur_dot */
+	redp(RD_MOVE);	/* Alert redisplay to check cursor loc */
+}
+
+/* Go to given dot */
+ed_go (dot)
+chroff dot;
+{	e_go(dot);
+	ed_setcur();
+}
+
+/* Go to given offset from current location */
+ed_goff(off)
+chroff off;
+{	e_goff(off);
+	ed_setcur();
+}
+
+/* Go to given INTEGER offset from current location */
+ed_igoff(ioff)
+int ioff;
+{	e_igoff(ioff);
+	ed_setcur();
+}
+
+/* Reset (delete all of) Buffer
+ * Should buffer be marked modified or not? Currently isn't.
+ */
+ed_reset()
+{	if(e_blen() == 0)
+		return;		/* Already empty */
+	e_reset();
+	cur_dot = 0;
+	cur_win->w_topldot = 0;	/* Is this necessary? */
+#if IMAGEN
+	redp(RD_WINRES|RD_REDO);
+#else
+	redp(RD_WINRES);	/* This window needs complete update */
+#endif /*-IMAGEN*/
+
+/*	buf_mod(); */		/* Mark modified ?? */
+/*	mark_p = 0; */		/* Say no mark set ?? */
+}
+
+ed_deln(off)
+chroff off;
+{	chroff dot;
+	dot = e_dot();
+	e_goff(off);	
+	ed_delete(e_dot(), dot);
+}
+
+/* ED_DELETE(dot1,dot2) -  Delete all characters between the two
+ *	positions indicated by dot1 and dot2.  Their order does not
+ *	matter; cur_dot and mark_dot are updated as necessary.
+ */
+ed_delete(dot1,dot2)
+chroff dot1,dot2;
+{	chroff tmpdot, savdot;
+
+	if(dot1 > dot2)
+	  {	tmpdot = dot1;
+		dot1 = dot2;
+		dot2 = tmpdot;
+	  }
+	e_go(dot1);
+	tmpdot = dot2-dot1;
+	sb_deln((SBBUF *)cur_buf,tmpdot);
+
+	savdot = cur_dot;		/* Save cur_dot value */
+	cur_dot = dot1;			/* so can set up for */
+	buf_tmod((chroff)0);		/* call to update disp-change vars */
+	cur_dot = savdot;
+
+	if(cur_dot >= dot2)
+		cur_dot -= tmpdot;
+	else if(cur_dot > dot1)
+		cur_dot = dot1;
+	if(mark_dot >= dot2)
+		mark_dot -= tmpdot;
+	else if(mark_dot > dot1)
+		mark_dot = dot1;
+	e_gocur();
+}
+
+/* ED_KILL(dot1,dot2) - Kill (save and delete) text between two places in
+ *	the buffer.
+ * We assume we are deleting from dot1 to dot2, thus if dot1 > dot2
+ * then backwards deletion is implied, and the saved text is prefixed
+ * (instead of appended) to any previously killed text.
+ */
+ed_kill(dot1,dot2)
+chroff dot1,dot2;
+{	register SBSTR *sd, *sdo;
+	SBSTR *e_copyn();
+
+	e_go(dot1);
+	sd = e_copyn(dot2-dot1);
+	if(sd == 0) return;
+	if(last_cmd == KILLCMD && (sdo = kill_ring[kill_ptr]))
+	  {	if(dot1 > dot2)	/* Prefix new killed stuff onto old stuff */
+		  {	sbs_app(sd,sdo);
+			kill_ring[kill_ptr] = sd;
+		  }
+		else		/* Append new stuff to old stuff */
+			sbs_app(sdo,sd);
+	  }
+	else kill_push(sd);
+	ed_delete(dot1,dot2);
+}
+
+kill_push(sdp)
+SBSTR *sdp;
+{	register SBSTR *sd;
+
+	if(++kill_ptr >= KILL_LEN) kill_ptr = 0;
+	if(sd = kill_ring[kill_ptr])
+		sbs_del(sd);
+	kill_ring[kill_ptr] = sdp;
+}
+
+
+
+#define isupper(c) (('A' <= c) && (c <= 'Z'))
+#define islower(c) (('a' <= c) && (c <= 'z'))
+#define toupper(c) (c + ('A' - 'a'))
+#define tolower(c) (c + ('a' - 'A'))
+
+#if FX_UCWORD||FX_LCWORD||FX_UCIWORD||FX_UCREG||FX_LCREG
+
+/* ED_CASE(dot1,dot2,downp) - Change the case within a region.
+ *	downp = 0 for uppercase, 1 for lowercase, 2 for capitalize.
+ */
+ed_case(dot1, dot2, downp)
+chroff dot1, dot2;
+int downp;
+{	chroff dcnt;
+	register int c, a, z;
+	int modflg;
+
+	modflg = 0;
+	if((dcnt = dot2 - dot1) < 0)
+	  {	dcnt = dot1;
+		dot1 = dot2;
+		dot2 = dcnt;
+		dcnt -= dot1;
+	  }
+	e_go(dot1);
+
+	if(downp==2)
+	  {	a = 0;	/* 0 looking for wd, 1 in word */
+		while(--dcnt >= 0)
+		  {	if(delimp(c = e_getc()))	/* Char in wd? */
+			  {	a = 0;			/* No */
+				continue;
+			  }
+			 if(a)		/* If already inside word */
+			  {	if(isupper(c))
+					c = tolower(c);
+				else continue;
+			  }
+			else	/* If encountered start of word */
+			  {	a = 1;
+				if(islower(c))
+					c = toupper(c);
+				else continue;
+			  }
+			e_backc();
+			e_ovwc(c);
+			modflg++;
+		  }
+		goto casdon;
+	  }
+	if(downp==0)
+	  {	a = 'a';		/* Convert to lower case */
+		z = 'z';
+		downp = -040;
+	  }
+	else
+	  {	a = 'A';		/* Convert to upper case */
+		z = 'Z';
+		downp = 040;
+	  }
+	while(--dcnt >= 0)
+	  {	if(a <= (c = e_getc()) && c <= z)
+		  {	e_backc();
+			e_ovwc(c+downp);
+			modflg++;
+		  }
+	  }
+
+casdon:	dot2 = cur_dot;			/* Save dot */
+	e_setcur();			/* Set up for modification range chk*/
+	if(modflg)
+		buf_tmat(dot1);		/* Stuff munged from there to here */
+	ed_go(dot2);
+}
+#endif /* any ed_case caller */
+
+
+/* UPCASE(c) - Return upper-case version of character */
+upcase(ch)
+int ch;
+{	register int c;
+	c = ch&0177;
+	return(islower(c) ? toupper(c) : c);
+}
+
Index: /trunk/minix/commands/elle/eefidx.h
===================================================================
--- /trunk/minix/commands/elle/eefidx.h	(revision 9)
+++ /trunk/minix/commands/elle/eefidx.h	(revision 9)
@@ -0,0 +1,241 @@
+/* .H Function Index Definition file, generated by ELLEC */
+/* FN_ defines Function Numbers (indices) for all known functions */
+/* FX_ defines Function eXistence in this ELLE configuration */
+#define FN_INSSELF          1 /* Insert Self */
+#define FX_INSSELF          1
+#define FN_QUOTINS          2 /* Quoted Insert */
+#define FX_QUOTINS          2
+#define FN_CRLF             3 /* CRLF */
+#define FX_CRLF             3
+#define FN_FCHAR            4 /* Forward Character */
+#define FX_FCHAR            4
+#define FN_BCHAR            5 /* Backward Character */
+#define FX_BCHAR            5
+#define FN_DCHAR            6 /* Delete Character */
+#define FX_DCHAR            6
+#define FN_BDCHAR           7 /* Backward Delete Character */
+#define FX_BDCHAR           7
+#define FN_DELSPC           8 /* Delete Horizontal Space */
+#define FX_DELSPC           8
+#define FN_TCHARS           9 /* Transpose Characters */
+#define FX_TCHARS           9
+#define FN_FWORD           10 /* Forward Word */
+#define FX_FWORD           10
+#define FN_BWORD           11 /* Backward Word */
+#define FX_BWORD           11
+#define FN_KWORD           12 /* Kill Word */
+#define FX_KWORD           12
+#define FN_BKWORD          13 /* Backward Kill Word */
+#define FX_BKWORD          13
+#define FN_TWORDS          14 /* Transpose Words */
+#define FX_TWORDS          14
+#define FN_UCWORD          15 /* Uppercase Word */
+#define FX_UCWORD          15
+#define FN_LCWORD          16 /* Lowercase Word */
+#define FX_LCWORD          16
+#define FN_UCIWORD         17 /* Uppercase Initial */
+#define FX_UCIWORD         17
+#define FN_BEGLINE         20 /* Beginning of Line */
+#define FX_BEGLINE         20
+#define FN_ENDLINE         21 /* End of Line */
+#define FX_ENDLINE         21
+#define FN_NXTLINE         22 /* Next Line */
+#define FX_NXTLINE         22
+#define FN_PRVLINE         23 /* Previous Line */
+#define FX_PRVLINE         23
+#define FN_DNRLINE         24 /* Down Real Line */
+#define FX_DNRLINE         24
+#define FN_UPRLINE         25 /* Up Real Line */
+#define FX_UPRLINE         25
+#define FN_OLINE           26 /* Open Line */
+#define FX_OLINE           26
+#define FN_DELBLINES       27 /* Delete Blank Lines */
+#define FX_DELBLINES       27
+#define FN_KLINE           28 /* Kill Line */
+#define FX_KLINE           28
+#define FN_BKLINE          29 /* Backward Kill Line */
+#define FX_BKLINE          29
+#define FN_GOLINE          30 /* Goto Line */
+#define FX_GOLINE          30
+#define FN_SETMARK         35 /* Set/Pop Mark */
+#define FX_SETMARK         35
+#define FN_EXCHMARK        36 /* Exchange Point and Mark */
+#define FX_EXCHMARK        36
+#define FN_KREGION         37 /* Kill Region */
+#define FX_KREGION         37
+#define FN_COPREG          38 /* Copy Region */
+#define FX_COPREG          38
+#define FN_UCREG           39 /* Uppercase Region */
+#define FX_UCREG           39
+#define FN_LCREG           40 /* Lowercase Region */
+#define FX_LCREG           40
+#define FN_FILLREG         41 /* Fill Region */
+#define FX_FILLREG         41
+#define FN_FPARA           45 /* Forward Paragraph */
+#define FX_FPARA           45
+#define FN_BPARA           46 /* Backward Paragraph */
+#define FX_BPARA           46
+#define FN_MRKPARA         47 /* Mark Paragraph */
+#define FX_MRKPARA         47
+#define FN_FILLPARA        48 /* Fill Paragraph */
+#define FX_FILLPARA        48
+#define FN_SELBUFFER       50 /* Select Buffer */
+#define FX_SELBUFFER       50
+#define FN_SELXBUFFER      51 /* Select Existing Buffer */
+#define FX_SELXBUFFER      51
+#define FN_KBUFFER         52 /* Kill Buffer */
+#define FX_KBUFFER         52
+#define FN_LISTBUFS        53 /* List Buffers */
+#define FX_LISTBUFS        53
+#define FN_BUFNOTMOD       54 /* Buffer Not Modified */
+#define FX_BUFNOTMOD       54
+#define FN_EOLMODE         55 /* EOL CRLF Mode */
+#define FX_EOLMODE         55
+#define FN_GOBEG           56 /* Goto Beginning */
+#define FX_GOBEG           56
+#define FN_GOEND           57 /* Goto End */
+#define FX_GOEND           57
+#define FN_WHATPAGE        58 /* What Page */
+#define FX_WHATPAGE        58
+#define FN_FFILE           60 /* Find File */
+#define FX_FFILE           60
+#define FN_RFILE           61 /* Read File */
+#define FX_RFILE           61
+#define FN_VFILE           62 /* Visit File */
+#define FX_VFILE           62
+#define FN_IFILE           63 /* Insert File */
+#define FX_IFILE           63
+#define FN_SFILE           64 /* Save File */
+#define FX_SFILE           64
+#define FN_SAVEFILES       65 /* Save All Files */
+#define FX_SAVEFILES       65
+#define FN_WFILE           66 /* Write File */
+#define FX_WFILE           66
+#define FN_WREG            67 /* Write Region */
+#define FX_WREG            67
+#define FN_WLASTKILL       68 /* Write Last Kill */
+#define FX_WLASTKILL       68
+#define FN_2WINDS          70 /* Two Windows */
+#define FX_2WINDS          70
+#define FN_1WIND           71 /* One Window */
+#define FX_1WIND           71
+#define FN_OTHWIND         72 /* Other Window */
+#define FX_OTHWIND         72
+#define FN_GROWIND         73 /* Grow Window */
+#define FX_GROWIND         73
+#define FN_SHRINKWIND      74 /* Shrink Window */
+#define FX_SHRINKWIND      74
+#define FN_DELWIND         75 /* Delete Window */
+#define FX_DELWIND         75
+#define FN_SOWIND          76 /* Standout Window */
+#define FX_SOWIND          76
+#define FN_2MODEWINDS      77 /* Two Mode Windows */
+#define FX_2MODEWINDS      77
+#define FN_NEWWIN          78 /* New Window */
+#define FX_NEWWIN          78
+#define FN_NSCREEN         79 /* Next Screen */
+#define FX_NSCREEN         79
+#define FN_PSCREEN         80 /* Previous Screen */
+#define FX_PSCREEN         80
+#define FN_OTHNSCREEN      81 /* Other New Screen */
+#define FX_OTHNSCREEN       0
+#define FN_LWINDBORD       82 /* Line to Window Border */
+#define FX_LWINDBORD        0
+#define FN_SCUPWIND        83 /* Scroll Window Up */
+#define FX_SCUPWIND        83
+#define FN_SCDNWIND        84 /* Scroll Window Down */
+#define FX_SCDNWIND        84
+#define FN_MVWTOP          85 /* Move to Window Top */
+#define FX_MVWTOP          85
+#define FN_MVWBOT          86 /* Move to Window Bottom */
+#define FX_MVWBOT          86
+#define FN_SETPROF         90 /* Set Profile */
+#define FX_SETPROF         90
+#define FN_PFXMETA         91 /* Prefix Meta */
+#define FX_PFXMETA         91
+#define FN_PFXEXT          92 /* Prefix Extend */
+#define FX_PFXEXT          92
+#define FN_UARG            93 /* Universal Arg */
+#define FX_UARG            93
+#define FN_NEGARG          94 /* Negative Argument */
+#define FX_NEGARG          94
+#define FN_ARGDIG          95 /* Argument Digit */
+#define FX_ARGDIG          95
+#define FN_VTBUTTONS       96 /* VT100 Button Hack */
+#define FX_VTBUTTONS       96
+#define FN_DESCRIBE        97 /* Describe */
+#define FX_DESCRIBE        97
+#define FN_SKMAC          100 /* Start Kbd Macro */
+#define FX_SKMAC          100
+#define FN_EKMAC          101 /* End Kbd Macro */
+#define FX_EKMAC          101
+#define FN_XKMAC          102 /* Execute Kbd Macro */
+#define FX_XKMAC          102
+#define FN_VKMAC          103 /* View Kbd Macro */
+#define FX_VKMAC          103
+#define FN_UNKILL         105 /* Un-kill */
+#define FX_UNKILL         105
+#define FN_UNKPOP         106 /* Un-kill Pop */
+#define FX_UNKPOP         106
+#define FN_APPNKILL       107 /* Append Next Kill */
+#define FX_APPNKILL       107
+#define FN_SRCH           110 /* String Search */
+#define FX_SRCH           110
+#define FN_RSRCH          111 /* Reverse String Search */
+#define FX_RSRCH          111
+#define FN_ISRCH          112 /* Incremental Search */
+#define FX_ISRCH          112
+#define FN_RISRCH         113 /* Reverse Search */
+#define FX_RISRCH         113
+#define FN_REPSTR         114 /* Replace String */
+#define FX_REPSTR         114
+#define FN_QUEREP         115 /* Query Replace */
+#define FX_QUEREP         115
+#define FN_REPLINE        116 /* Replace in Line */
+#define FX_REPLINE        116
+#define FN_SFCOL          117 /* Set Fill Column */
+#define FX_SFCOL          117
+#define FN_SFPREF         118 /* Set Fill Prefix */
+#define FX_SFPREF         118
+#define FN_FILLMODE       119 /* Auto Fill Mode */
+#define FX_FILLMODE       119
+#define FN_TEXTMODE       120 /* Text Mode */
+#define FX_TEXTMODE         0
+#define FN_INDATM         121 /* Indent According to Mode */
+#define FX_INDATM         121
+#define FN_INDNL          122 /* Indent New Line */
+#define FX_INDNL          122
+#define FN_BACKIND        123 /* Back to Indentation */
+#define FX_BACKIND        123
+#define FN_INDCOMM        124 /* Indent for Comment */
+#define FX_INDCOMM        124
+#define FN_INDREL         125 /* Indent Relative */
+#define FX_INDREL         125
+#define FN_MATCHBRACK     129 /* Match Bracket */
+#define FX_MATCHBRACK       0
+#define FN_PSHINF         130 /* Push to Inferior */
+#define FX_PSHINF         130
+#define FN_RETSUP         131 /* Return to Superior */
+#define FX_RETSUP         131
+#define FN_WFEXIT         132 /* Write File Exit */
+#define FX_WFEXIT         132
+#define FN_BKPT           140 /* Hit Breakpoint */
+#define FX_BKPT           140
+#define FN_DEBUG          141 /* Debug Mode */
+#define FX_DEBUG          141
+#define FN_XUCMD          150 /* Execute Unix Command */
+#define FX_XUCMD            0
+#define FN_MAKE           151 /* Execute Make */
+#define FX_MAKE             0
+#define FN_NXTERR         152 /* Find Next Error */
+#define FX_NXTERR           0
+#define FN_ICOXCMD        153 /* ICO Extend Command */
+#define FX_ICOXCMD          0
+#define FN_ICOTYPFNS      154 /* ICO Typeset Funs */
+#define FX_ICOTYPFNS        0
+#define FN_ICOSPIFNS      155 /* ICO Spec Input Funs */
+#define FX_ICOSPIFNS        0
+#define FN_STUFFSEL       156 /* Stuff Selection */
+#define FX_STUFFSEL         0
+#define FN_SELREGION      157 /* Select Region */
+#define FX_SELREGION        0
Index: /trunk/minix/commands/elle/eefile.c
===================================================================
--- /trunk/minix/commands/elle/eefile.c	(revision 9)
+++ /trunk/minix/commands/elle/eefile.c	(revision 9)
@@ -0,0 +1,834 @@
+/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+	 *	products without permission of the author.
+ */
+/*
+ * EEFILE	File reading/writing functions
+ */
+
+#include "elle.h"
+#include <stdio.h>	/* Use "standard" I/O package for writing */
+#ifndef BUFSIZ
+#define BUFSIZ BUFSIZE	/* Some places use wrong name in stdio.h */
+#endif /*-BUFSIZ*/
+#if V6
+	struct stat {
+		int st_dev;
+		int st_ino;
+		char *st_mode;
+		char st_nlink;
+		char st_uid;
+		char st_gid;
+		char st_size0;
+		char st_size;
+		int st_addr[8];
+		long st_atime;
+		long st_mtime;
+	};
+#define ENOENT (2)	/* Syscall error - no such file or dir */
+#else
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif /*-V6*/
+
+#if TOPS20
+#include <sys/file.h>		/* Get open mode bits */
+#endif
+
+extern char *strerror();		/* Return error string for errno */
+extern struct buffer *make_buf(), *find_buf();
+
+char *fncons(), *last_fname();
+
+int hoardfd = -1;	/* Retain a FD here to ensure we can always write */
+
+/* Flags for iwritfile() */
+#define WF_SMASK 07	/* Source Mask */
+#define WF_SBUFF  0	/*   source: Buffer */
+#define WF_SREG   1	/*   source: Region */
+#define WF_SKILL 2	/*   source: Last Kill */
+#define WF_ASK 010	/* Ask for filename to write to */
+static int iwritfile();
+
+
+/* EFUN: "Find File" */
+/*	Ask user for a filename and do a find_file for it.
+ *	If buffer exists for that filename, select that buffer.
+ *	Else create a buffer for it, and read in the file if it exists.
+ */
+f_ffile()
+{	int find_file();
+#if IMAGEN
+	hack_file("Visit file: ", find_file);
+#else
+	hack_file("Find file: ", find_file);
+#endif /*-IMAGEN*/
+}
+
+/* EFUN: "Read File" */
+/*	User read_file function, asks user for a filename and reads it
+ */
+f_rfile() { u_r_file("Read file: "); }
+
+/* EFUN: "Visit File" */
+/*	Same as Read File, with different prompt.
+ */
+f_vfile() { u_r_file("Visit file: "); }
+
+
+u_r_file(prompt)
+char *prompt;
+{	register char *f_name;
+	register struct buffer *b;
+
+	if((f_name = ask (prompt))==0)	/* prompt user for filename */
+		return;				/* user punted... */
+	b = cur_buf;
+	if(*f_name == '\0')
+	  {	if (b -> b_fn == 0)
+			ding("No default file name.");
+		else read_file(b -> b_fn);
+	  }
+	else read_file(f_name);
+	chkfree(f_name);
+}
+
+/* EFUN: "Insert File" */
+/*	Asks for a filename and inserts the file at current location.
+ *	Point is left at beginning, and the mark at the end.
+ */
+f_ifile()
+{	int ins_file();
+	hack_file("Insert file: ", ins_file);
+}
+
+
+/* EFUN: "Save File" */
+/*	Save current buffer to its default file name
+ */
+f_sfile()
+{	if(cur_buf->b_flags&B_MODIFIED)
+		return(iwritfile(WF_SBUFF));	/* Write buffer, don't ask */
+	else
+	  {	saynow("(No changes need to be written)");
+		return(1);
+	  }
+}
+
+#if FX_SAVEFILES || FX_WFEXIT
+/* EFUN: "Save All Files" */
+/*  F_SAVEFILES - Offer to save all modified files.
+ *	With argument, doesn't ask.
+ *	Returns 0 if user aborts or if an error happened.
+ */
+f_savefiles()
+{	register struct buffer *b, *savb;
+	register int res = 1;
+	char *ans;
+
+	savb = cur_buf;
+	for (b = buf_head; res && b; b = b->b_next)
+		if ((b->b_flags & B_MODIFIED) && b->b_fn)
+		  {	if(exp_p)		/* If arg, */
+			  {	chg_buf(b);	/* just save, don't ask */
+				res = f_sfile();
+				continue;	/* Check next buffer */
+			  }
+			/* Ask user whether to save */
+			ans = ask("Buffer %s contains changes - write out? ",
+					b->b_name);
+			if(ans == 0)
+			  {	res = 0;	/* User aborted */
+				break;
+			  }
+			if (upcase(*ans) == 'Y')
+			  {	chg_buf(b);
+				res = f_sfile();	/* Save File */
+			  }
+			chkfree(ans);
+		  }
+	chg_buf(savb);
+	return(res);
+}
+#endif /*FX_SAVEFILES||FX_WFEXIT*/
+
+
+/* EFUN: "Write File" */
+/*	Write out the buffer to an output file.
+ */
+f_wfile()
+{	return iwritfile(WF_ASK|WF_SBUFF);
+}
+
+/* EFUN: "Write Region" */
+/*	Write region out to a file
+ */
+f_wreg()
+{	return iwritfile(WF_ASK|WF_SREG);	/* Ask, write region */
+}
+
+#if FX_WLASTKILL
+/* EFUN: "Write Last Kill" (not EMACS) */
+/*	Write current kill buffer out to a file.
+**	This is mainly for MINIX.
+*/
+extern int kill_ptr;		/* From EEF3 */
+extern SBSTR *kill_ring[];
+
+f_wlastkill()
+{	return iwritfile(WF_ASK|WF_SKILL);
+}
+#endif
+
+
+
+/* HACK_FILE - intermediate subroutine
+ */
+hack_file(prompt, rtn)
+char *prompt;
+int (*rtn)();
+{	register char *f_name;
+
+	if((f_name = ask(prompt)) == 0)
+		return;
+	if (*f_name != '\0')			/* Check for null answer */
+		(*rtn)(f_name);
+	chkfree(f_name);
+}
+
+/* FIND_FILE(f_name)
+ *	If there is a buffer whose fn == f_name, select that buffer.
+ *	Else create one with name of the last section of f_name and
+ *	read the file into that buffer.
+ */
+find_file(f_name)
+register char *f_name;
+{	register struct buffer *b;
+	register char *ans;
+	char *lastn;
+	int fd;
+
+#if IMAGEN
+	char real_name[128];		/* File name w/ expanded ~ and $ */
+	expand_file(real_name, f_name);
+	f_name = real_name;
+#endif /*IMAGEN*/
+
+	for (b = buf_head; b; b = b -> b_next)
+		if(b->b_fn && (strcmp (b -> b_fn, f_name) == 0))
+			break;
+	if (b)				/* if we found one */
+	  {	sel_buf(b);		/* go there */
+		return;			/* and we are done */
+	  }
+	if((fd = open(f_name,0)) < 0)	/* See if file exists */
+	  {	if(errno != ENOENT)	/* No, check reason */
+		  {	ferr_ropn();	/* Strange error, complain */
+			return;		/* and do nothing else. */
+		  }
+	  }
+	else close(fd);			/* Found!  Close FD, since the */
+					/* read_file rtn will re-open. */
+
+	lastn = last_fname(f_name);	/* Find buffer name */
+	b = find_buf(lastn);		/* Is there a buffer of that name? */
+	if (b && (ex_blen(b) || b->b_fn))
+	  {	ans = ask("Buffer %s contains %s, which buffer shall I use? ",
+    			b -> b_name, b->b_fn ? b->b_fn : "something");
+		if(ans == 0) return;		/* Aborted */
+		if (*ans != '\0')		/* if null answer, use b */
+			b = make_buf(ans);	/* else use ans */
+		chkfree(ans);
+	  }
+	else
+		b = make_buf(lastn);
+	sel_buf(b);
+	if(fd < 0)		/* If file doesn't exist, */
+	  {	set_fn(f_name);	/* just say "new" and set filename */
+		return;		/* and return right away. */
+	  }
+	if (read_file(f_name)==0)	/* File exists, read it in! */
+	  {	if(b->b_fn)		/* Failed... if filename, */
+		  {	chkfree(b->b_fn);	/* flush the filename. */
+			b->b_fn = 0;
+		  }
+	  }
+}
+
+/* READ_FILE(f_name)
+ *	Reads file into current buffer, flushing any
+ *	previous contents (if buffer modified, will ask about saving)
+ *	Returns 0 if failed.
+ */
+read_file(f_name)
+char *f_name;
+{
+#if IMAGEN
+	struct stat s;
+	char real_name[128];		/* File name w/ expanded ~ and $ */
+#endif /*IMAGEN*/
+
+	if(!zap_buffer())	/* Flush the whole buffer */
+		return;		/* Unless user aborts */
+#if IMAGEN
+	expand_file(real_name, f_name);
+	f_name = real_name;		/* Hack, hack! */
+#endif /*IMAGEN*/
+	set_fn(f_name);
+	if (ins_file(f_name)==0)
+		return 0;
+	f_bufnotmod();		/* Say not modified now */
+#if IMAGEN
+	stat(f_name, &s);		/* Get file stat */
+	cur_buf->b_mtime = s.st_mtime;	/*  and pick out last-modified time */
+#endif /*IMAGEN*/
+	return 1;
+}
+
+/* INS_FILE(f_name)
+ *	Inserts file named f_name into current buffer at current point
+ *	Point is not moved; mark is set to end of inserted stuff.
+ *	Returns 0 if failed, 1 if won.
+ */
+ins_file (f_name)
+char *f_name;
+{	register int ifd;
+	register SBSTR *sd;
+	chroff insdot;			/* To check for range of mods */
+
+#if IMAGEN
+	char real_name[128];		/* File name w/ expanded ~ and $ */
+	expand_file(real_name, f_name);
+	f_name = real_name;
+#endif /*IMAGEN*/
+#if !(TOPS20)
+	if((ifd = open(f_name,0)) < 0)
+#else
+	if((ifd = open(f_name,O_RDONLY|O_UNCONVERTED)) < 0)
+#endif /*TOPS20*/
+	  {	ferr_ropn();		/* Can't open, complain */
+		return 0;		/* no redisplay */
+	  }
+	errno = 0;
+	if((sd = sb_fduse(ifd)) == 0)
+	  {	if (ifd >= SB_NFILES)
+			dingtoo(" Cannot read - too many internal files");
+		else if (errno)
+			ferr_ropn();
+		else errbarf("SB rtn cannot read file?");
+		close(ifd);
+		return 0;
+	  }
+	sb_sins(cur_buf,sd);
+	insdot = e_dot();
+	f_setmark();			/* Set mark at current ptr */
+	if(cur_dot != insdot)		/* If pointer was advanced, */
+		buf_tmat(insdot);	/* then stuff was inserted */
+	e_gocur();
+	return 1;
+}
+
+ferr_ropn() { ferr(" Cannot read"); }
+ferr_wopn() { ferr(" Cannot write"); }
+ferr(str)
+char *str;
+{	saytoo(str);
+	saytoo(" - ");
+	dingtoo(strerror(errno));
+}
+
+
+
+/* IWRITFILE - auxiliary for writing files.
+**	Returns 1 if write successful, 0 if not.
+*/
+static int
+iwritfile(flags)
+int flags;
+{	register struct buffer *b;
+	register char *o_name;		/* output file name */
+	int styp = flags & WF_SMASK;	/* Source type, one of WF_Sxxx */
+	char *prompt;
+#ifdef STDWRITE
+	register FILE *o_file;		/* output file pointer */
+	char obuf[BUFSIZ];
+	chroff dotcnt;
+#endif /*STDWRITE*/
+	int ofd;			/* output file FD */
+	SBSTR *sd;
+	char fname[FNAMSIZ];		/* To avoid chkfree hassle */
+	char newname[FNAMSIZ];		/* for robustness */
+	char oldname[FNAMSIZ];		/* ditto */
+	int res;
+	struct stat statb;
+	int statres;
+#if IMAGEN
+	struct stat s;
+	char real_name[128];		/* File name w/ expanded ~ and $ */
+#endif /*IMAGEN*/
+	res = 1;			/* Let's keep track of success */
+
+	/* Check for existence of source, and set prompt string */
+	switch(styp)
+	  {
+		case WF_SBUFF:
+			prompt = "Write File: ";
+			break;
+		case WF_SREG:
+			if(!mark_p)
+			  {	dingtoo(" No Mark!");
+				return(0);
+			  }
+			prompt = "Write Region: ";
+			break;
+#if FX_WLASTKILL
+		case WF_SKILL:
+			if(!kill_ring[kill_ptr])
+			  {	dingtoo("No killed stuff");
+				return(0);
+			  }
+			prompt = "Write Last Kill: ";
+			break;
+#endif
+		default:			/* Internal error */
+			errbarf("bad iwritfile arg");
+			return 0;
+	  }
+
+	if (flags&WF_ASK)
+	  {	if((o_name = ask(prompt))==0)
+			return(0);		/* User punted. */
+		strcpy(&fname[0], o_name);	/* Copy filename onto stack */
+		chkfree(o_name);
+	  }
+	o_name = &fname[0];
+	b = cur_buf;
+	if (!(flags&WF_ASK) || (*o_name == '\0'))
+	  {	if (b->b_fn == 0)
+		  {	ding("No default file name.");
+			return(0);
+		  }
+		strcpy(o_name, b->b_fn);
+	  }
+
+#if IMAGEN
+	expand_file(real_name, o_name);
+	o_name = real_name;		/* Hack, hack */
+#endif /*IMAGEN*/
+
+	statres = stat(o_name,&statb);	/* Get old file's info (if any) */
+
+#if IMAGEN
+	/* Now, make sure someone hasn't written the file behind our backs */
+	if ((styp==WF_SBUFF) && !(flags&WF_ASK)
+	  && b->b_fn && stat(b->b_fn, &s) >= 0)
+		if (s.st_mtime != b->b_mtime)
+		  {	char *ans;
+			ans = ask("Since you last read \"%s\", someone has changed it.\nDo you want to write it anyway (NOT RECOMMENDED!)? ",
+				   b->b_fn);
+			if (ans == 0 || upcase(*ans) != 'Y')
+			  {
+				ding("I suggest you either read it again, or\nwrite it to a temporary file, and merge the two versions manually.");
+				if (ans) chkfree(ans);
+				return(0);
+			  }
+			if (ans) chkfree(ans);
+		  }
+#endif /*IMAGEN*/
+
+  /* Try to get around major UNIX screw of smashing files.
+   * This still isn't perfect (screws up with long filenames) but...
+   * 1. Write out to <newname>
+   * 2. Rename <name> to <oldname> (may have to delete existing <oldname>)
+   * 3. Rename <newname> to <name>.
+   */
+	fncons(oldname,ev_fno1,o_name,ev_fno2);	/* Set up "old" filename */
+	fncons(newname,ev_fnn1,o_name,ev_fnn2);	/* Set up "new" filename */
+	unlink(newname);			/* Ensure we don't clobber */
+	unhoard();				/* Now give up saved FD */
+#if !(V6)	/* Standard V6 doesn't have access call */
+	if(statres >= 0)			/* If file exists, */
+	  {	if(access(o_name, 2) != 0)	/* check for write access */
+		  {	ferr_wopn();
+			res = 0;	/* Failure */
+			goto wdone;
+		  }
+	  }
+#endif /*-V6*/
+#ifdef STDWRITE
+	if(flags&WF_ASK)
+	  {	if((o_file = fopen(newname, "w")) ==0)	/* Create new output file */
+		  {	ferr_wopn();
+			res = 0;		/* Failure */
+			goto wdone;
+		  }
+		setbuf(o_file,obuf);	/* Ensure always have buffer */
+	  }
+	else	/* New stuff */
+#endif /*STDWRITE*/
+	  {
+#if !(TOPS20)
+		if((ofd = creat(newname,ev_filmod)) < 0)
+#else
+		if((ofd = open(newname,O_WRONLY|O_UNCONVERTED)) < 0)
+#endif /*TOPS20*/
+		  {	ferr_wopn();
+			res = 0;		/* Failure */
+			goto wdone;
+		  }
+	  }
+	if (styp==WF_SBUFF)
+		set_fn(o_name);		/* Won, so set default fn for buff */
+#if IMAGEN
+	saynow("Writing ");
+	switch(styp)
+	  {	case WF_SBUFF:	saytoo(b->b_fn); break;
+		case WF_SREG:	saytoo("region"); break;
+#if FX_WLASTKILL
+		case WF_SKILL:	saytoo("last kill"); break;
+#endif
+	  }
+	sayntoo("...");
+#else
+	saynow("Writing...");
+#endif /*-IMAGEN*/
+
+#if !(TOPS20)			/* T20 does all this already */
+	if(statres >= 0)		/* Get old file's modes */
+	  {				/* Try to duplicate them */
+		/* Do chmod first since after changing owner we may not
+		** have permission to change mode, at least on V6.
+		*/
+		chmod(newname,statb.st_mode & 07777);
+#if V6
+		chown(newname, (statb.st_gid<<8)|(statb.st_uid&0377));
+#else
+		chown(newname,statb.st_uid,statb.st_gid);
+#endif /*-V6*/
+	  }
+#if V6
+	/* If no old file existed, and we are a V6 system, try to set
+	 * the modes explicitly.  On V7 we're OK because the user can
+	 * diddle "umask" to get whatever is desired.
+	 * On TOPS-20 of course everything is all peachy.
+	 */
+	else chmod(newname, ev_filmod);
+#endif /*V6*/
+#endif /*TOPS20*/
+
+
+#ifdef STDWRITE
+	if(flags&WF_ASK)
+	  {	switch(styp)
+		  {
+			case WF_SBUFF:
+				dotcnt = e_blen();
+				e_gobob();
+				break;
+			case WF_SREG:
+				if((dotcnt = mark_dot - cur_dot) < 0)
+				  {	e_goff(dotcnt);
+					dotcnt = -dotcnt;
+				  }
+				else e_gocur();
+				break;
+			/* WF_SKILL not implemented here */
+		  }
+		while(--dotcnt >= 0)
+			putc(sb_getc(((SBBUF *)b)), o_file);
+		e_gocur();
+		fflush(o_file);			/* Force everything out */
+		res = ferror(o_file);		/* Save result of stuff */
+		fclose(o_file);			/* Now flush FD */
+	  }
+	else	/* New stuff */
+#endif /*STDWRITE*/
+	  {
+		switch(styp)
+		  {
+			case WF_SBUFF:
+				res = sb_fsave((SBBUF *)b, ofd);
+				break;
+			case WF_SREG:
+				e_gocur();
+				sd = e_copyn((chroff)(mark_dot - cur_dot));
+				res = sbx_aout(sd, 2, ofd);
+				sbs_del(sd);
+				break;
+#if FX_WLASTKILL
+			case WF_SKILL:
+				res = sbx_aout(kill_ring[kill_ptr], 2, ofd);
+				break;
+#endif
+		  }
+		close(ofd);
+	  }
+	if(errno = res)
+	  {	ferr(" Output error");
+		res = 0;		/* Failure */
+		goto wdone;
+	  }
+	else
+		res = 1;		/* Success so far */
+	if(styp == WF_SBUFF)
+		f_bufnotmod();		/* Reset "buffer modified" flag */
+
+	/* Here we effect the screw-prevention steps explained earlier. */
+	/* TOPS-20, with generation numbers, need not worry about this. */
+#if TOPS20
+	saynow("Written");
+
+#else /*-TOPS20*/
+#if IMAGEN	/* KLH -- This conditional bracketting is prone to lossage */
+	/* Only create the .BAK file once per editing session!! */
+	if ((styp==WF_SBUFF) || !(b->b_flags & B_BACKEDUP))
+	  {	if (styp==WF_SBUFF)
+			b->b_flags |= B_BACKEDUP;
+#endif /*IMAGEN*/
+	unlink(oldname);	/* remove any existing "old" file */
+	if(link(o_name,oldname) == 0)	/* Rename current to "old" */
+	 	unlink(o_name);
+		/* Here is the critical point... if we stop here, there is no
+		 * longer any file with the appropriate filename!!!
+		 */
+#if IMAGEN
+	  }
+	else
+		unlink(o_name);
+#endif /*IMAGEN*/
+	if(link(newname,o_name) == 0)	/* Rename "new" to current */
+	  {	unlink(newname);
+#if IMAGEN
+		sayntoo("OK");
+#else
+		saynow("Written");
+#endif /*-IMAGEN*/
+	  }
+	else
+	  {	dingtoo("rename error!");
+		res = 0;
+	  }
+#endif /*-TOPS20*/
+
+#if IMAGEN
+	/* Update the last-modified time for the file in this buffer */
+	if ((styp == WF_SBUFF) && b->b_fn)
+	  {	stat(b->b_fn, &s);
+		b->b_mtime = s.st_mtime;
+	  }
+#endif /*IMAGEN*/
+
+wdone:
+	hoard();			/* Get back a retained FD */
+	return(res);
+}
+
+
+/* FNCONS(dest,pre,f_name,post)
+ *	Specialized routine to cons up a filename string into "dest",
+ *	given prefix and postfix strings to be added onto last component of
+ *	filename.
+ */
+char *
+fncons(dest, pre, f_name, post)
+char *dest,*pre,*f_name,*post;
+{	register char *cp, *cp2;
+	char *last_fname();
+
+	cp = dest;
+	*cp = 0;			/* Make dest string null initially */
+	cp2 = last_fname(f_name);	/* Get pointer to beg of last name */
+	strncat(cp,f_name,cp2-f_name);	/* Copy first part of filename */
+	if(pre)	strcat(cp, pre);	/* If prefix exists, add it on */
+	cp = last_fname(cp);		/* Recheck in case levels added */
+	strcat(cp, cp2);		/* Now add last name */
+	if(cp2 = post)			/* If there's a postfix, must check */
+	  {	cp[FNAMELEN-strlen(cp2)] = 0;	/* and cut dest so postfix */
+		strcat(cp, cp2);		/* will fit on end. */
+	  }
+	return(dest);
+}
+
+/* LAST_FNAME(string)
+ *	Get the last component of a file name.  Returns pointer to
+ *	start of component; does NOT copy string!
+ */
+char *
+last_fname(f_name)
+char *f_name;
+{	register char *cp, *p;
+	register int c;
+
+	p = f_name;		/* pointer to last slash */
+	cp = p;
+	while(c = *cp++)
+		if(c == '/')
+			p = cp;		/* point to after the slash */
+	return(p);
+}
+
+/* SET_FN(string)
+ *	Set the default filename for current buffer to "string".
+ */
+set_fn (string)
+char *string;
+{	register struct buffer *b;
+	register char *str;
+#if IMAGEN
+	register char *cp;
+	register int len;
+#endif /*IMAGEN*/
+	char *strdup();
+
+	b = cur_buf;
+	str = strdup(string);		/* Copy now in case copying self */
+	if(b->b_fn)
+		chkfree(b->b_fn);
+	b -> b_fn = str;
+#if IMAGEN
+	/* Do mode determination based on file name (HACK HACK) */
+	len = strlen(str);
+	b->b_flags &= ~(B_CMODE|B_TEXTMODE);
+	if (len > 4)
+	  {	if (strcmp(&str[len - 5], "draft") == 0)
+			b->b_flags |= B_TEXTMODE;
+		else
+		  {	cp = &str[len - 4];
+			if (strcmp(cp, ".txt") == 0 ||
+			    strcmp(cp, ".mss") == 0)
+				b->b_flags |= B_TEXTMODE;
+		  }
+	  }
+	if (len > 2)
+	  {	cp = &str[len - 2];
+		if (strcmp(cp, ".h") == 0 || strcmp(cp, ".c") == 0)
+			b->b_flags |= B_CMODE;
+	  }
+#endif /*IMAGEN*/
+	redp(RD_MODE);
+}
+
+
+/* SAVEWORLD - Attempt to save all changes user has made.
+ *	Currently this amounts to writing out all modified buffers
+ *	to the files $HOME/+buffername.  If a buffer is given as argument,
+ *	only that buffer is saved.
+ *	This is only called from the error handling routines with
+ *	the TTY either gone or in normal (non-edit) mode.  The "grunt"
+ *	flag says whether to output feedback during the saving process.
+ */
+saveworld(bp, grunt)
+struct buffer *bp;
+int grunt;
+{	register struct buffer *b;
+	register int wfd;
+	char sfname[FNAMSIZ];
+	struct buffer *sel_mbuf();
+
+	unhoard();		/* Ensure a FD is free for writing */
+	if(b = bp) goto once;
+	while(!bp && (b = sel_mbuf(b)))
+	  {
+	once:	strcat(strcat(strcpy(sfname,homedir),"/+"),b->b_name);
+		if(grunt) printf("Saving %s...",sfname);
+#if !(TOPS20)
+		if((wfd = creat(sfname, ev_filmod)) < 0)
+#else
+		if((wfd = open(sfname,O_WRONLY|O_UNCONVERTED)) < 0)
+#endif /*TOPS20*/
+		  {	if(grunt)
+				printf(" error - %s\n", strerror(errno));
+		  }
+		else
+		  {	sb_fsave((SBBUF *)b, wfd);
+			close(wfd);
+			if(grunt) printf("\n");
+		  }
+		b->b_flags &= ~B_MODIFIED;
+	  }
+	hoard();
+}
+
+/* HOARD, UNHOARD - Routines to save a FD for writing, to make sure
+ *	that we can always write out a buffer no matter how many
+ *	file descriptors we are currently using.
+ */
+hoard()			/* Stash away a FD */
+{	if(hoardfd <= 0)
+#if !(TOPS20)
+		hoardfd = open("nul:", 1);
+#else
+		hoardfd = open("/dev/null", 1);
+#endif
+}
+unhoard()		/* Give up our stashed FD so it can be re-used */
+{	close(hoardfd);
+	hoardfd = -1;
+}
+
+
+#if IMAGEN
+#include <pwd.h>
+#include <ctype.h>
+
+/*
+ * expand_file: expand any ~user-name/ or $env-var/ prefixes in sfn,
+ * producing the full name in dfn
+ */
+expand_file(dfn, sfn)
+register char *dfn, *sfn;
+{
+	register char *sp, *tp;
+	register int c;
+	register struct passwd *pw;
+	char ts[128];
+
+	/* HORRIBLE, GROSS, DISGUSTING HACK: if the destination and
+	 * source strings are identical (same pointer), then do not
+	 * do any expansion--this happens to work with the current
+	 * structure very well, since multiple expansions may happen.
+	 */
+	if (dfn == sfn)
+		return;
+
+	ts[0] = 0;
+
+	/* If have a leading $, then expand environment variable */
+	if (*sfn == '$')
+	  {	++sfn;
+		tp = ts;
+		while (*tp++ = *sfn)
+			if (!isalnum(*sfn))
+				break;
+			else
+				++sfn;
+		*--tp = 0;		/* Just in case */
+		strcpy(ts, getenv(ts));	/* MARGINAL!! */
+	  }
+	/* If have leading ~, then expand login name (null means $HOME) */
+	else if (*sfn == '~')
+	  {	++sfn;
+		if (*sfn == '/' || *sfn == 0)
+			strcpy(ts, getenv("HOME"));
+		else
+		  {	tp = ts;
+			while (*sfn && *sfn != '/')
+				*tp++ = *sfn++;
+			*tp = 0;
+			pw = (struct passwd *)getpwnam(ts);
+			if (! pw)
+				strcpy(ts, "???");
+			else
+				strcpy(ts, pw->pw_dir);
+		  }
+	  }
+
+	/* Now, ts is either empty or contains the expansion;
+	 * sfn has been updated correctly.
+	 */
+	strcpy(dfn, ts);
+	strcat(dfn, sfn);
+}
+#endif /*IMAGEN*/
Index: /trunk/minix/commands/elle/eefill.c
===================================================================
--- /trunk/minix/commands/elle/eefill.c	(revision 9)
+++ /trunk/minix/commands/elle/eefill.c	(revision 9)
@@ -0,0 +1,648 @@
+/* ELLE - Copyright 1982, 1985, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*
+ * EEFILL	Fill Mode functions
+ */
+
+#include "elle.h"
+
+extern int ev_fcolumn;	/* Fill Column variable (defined in EEVINI) */
+#if FX_SFPREF
+char *fill_prefix;	/* Fill Prefix variable */
+int fill_plen;		/* Length of Fill Prefix (0 = no prefix) */
+#endif /*FX_SFPREF*/
+
+#if FX_FILLMODE
+int fill_mode = 0;	/* TRUE when Auto Fill Mode is on */
+int *fill_trig;		/* Pointer to fill-trigger chbit array */
+static char *fill_initrig = " \t.,;:)!";
+#endif /*FX_FILLMODE*/
+
+/* Following stuff for testing routines on */
+/*
+
+          1         2         3         4         5	    6         7
+0123456789012345678901234567890123456789012345678901234567890123456789012345
+
+Okay...  more stuff to hack.  Okay.  a b c d e f g h i j k l m
+n o p q r s t u v w x y z dfsd stuff to hack 01234 Okay testing
+more stuff to hack.  Okay...  more stuff to hack more stuff to
+hack.  Okay...  more stuff to line long stuff to hack.  Okay...
+even more gap and.  period.  okay, end of stuff.
+	This is another fence.
+*/
+
+
+
+#if FX_SFCOL
+/* EFUN: "Set Fill Column" */
+f_sfcol()
+{	register int linel;
+	char temp[20];
+
+	linel = exp_p ? exp : d_curind();
+	if(linel < 0) linel = 0;
+	say("Fill column = ");
+	dottoa(temp,(chroff)linel);
+	saytoo(temp);
+	ev_fcolumn = linel;
+}
+#endif /*FX_SFCOL*/
+
+
+#if FX_SFPREF
+/* EFUN: "Set Fill Prefix" */
+f_sfpref()
+{	register int i;
+	register char *cp;
+
+	if((i = cur_dot - e_boldot()) > MAXLINE)
+	  {	ding("Absurd Fill Prefix");
+		return;
+	  }
+	if(fill_prefix)
+	  {	chkfree(fill_prefix);
+		fill_plen = 0;
+	  }
+	if(i <= 0)
+	  {	fill_prefix = 0;
+		cp = "";
+	  }
+	else
+	  {	fill_prefix = cp = memalloc((SBMO)(i+1));
+		fill_plen = i;
+		e_gobol();
+		do { *cp++ = e_getc(); }
+		while(--i);
+		*cp = 0;
+		cp = fill_prefix;
+	  }
+	say("Fill Prefix = \"");
+	saytoo(cp);
+	saytoo("\"");
+}
+
+
+/* TSTFILLP(lim) - Check for existence of Fill Prefix at current dot.  If
+ *	not there, returns 0 without changing dot.  If there, returns
+ *	1 and leaves dot immediately after the Fill Prefix.
+ *	Lim = # of chars allowed to scan from buffer.
+ */
+tstfillp(lim)
+int lim;
+{	register int i, c;
+	register char *cp;
+	chroff savdot;
+
+	if(!(i = fill_plen) || (i > lim))
+		return(0);
+	savdot = e_dot();
+	cp = fill_prefix;
+	do {	if(*cp++ != e_getc())
+		  {	e_go(savdot);
+			return(0);
+		  }
+	  } while(--i);
+	return(1);
+}
+#endif /*FX_SFPREF*/
+
+
+#if FX_FILLREG || FX_FILLPARA
+
+/* ED_FILL(start, end, flag) - Fill a region.
+ *	Flag	0 for full filling; extra whitespace is flushed.  First
+ *			word is always retained.
+ *		1 for skimpy filling such as Auto-Fill likes.
+ *			Extra whitespace is NOT flushed, except at
+ *			beginning of a newly created line.
+ *			This is not yet implemented however.
+ * Note: updates cur_dot to compensate for changes in buffer, and returns
+ *	there when done!
+ * Note: Checks for Fill Prefix when it exists.
+ */
+ed_fill(begloc, endloc, flag)
+chroff begloc, endloc;
+int flag;
+{	register int c;
+	register int len, lastc;
+	chroff savloc;
+	int lastbrk;
+	int parlen;
+
+	parlen = endloc - begloc;
+	if(parlen < 0)
+	  {	begloc = endloc;
+		parlen = -parlen;
+	  }
+	e_go(begloc);
+	len = d_curind();		/* Set up current col */
+
+#if FX_SFPREF
+	/* If at beg of line, check for fill prefix and skip over it */
+	if((len == 0) && tstfillp(parlen))
+	  {	parlen -= fill_plen;
+		len = d_curind();
+	  }
+#endif /*FX_SFPREF*/
+	lastbrk = 0;			/* Put next word on no matter what. */
+	c = 0;
+	for(;;)
+	  {
+#if ICONOGRAPHICS
+             if (c != ')' && c != '"')  /* allow for two sp after .) or ." */
+#endif /*ICONOGRAPHICS*/
+		lastc = c;
+		if(--parlen < 0) break;
+		c = e_getc();
+		if(c == EOF)
+			break;
+#if FX_SFPREF
+		/* If at beg of line, check for fill prefix and flush it */
+		if((c == LF) && tstfillp(parlen))
+		  {	e_igoff(-(fill_plen+1));
+			e_ovwc(c = SP);
+			e_deln((chroff)fill_plen);
+			parlen -= fill_plen;
+			if(cur_dot >= e_dot())
+				cur_dot -= fill_plen;
+		  }
+#endif /*FX_SFPREF*/
+		if(c == TAB || c == LF)		/* Replace tabs+eols by sps */
+		  {	e_backc();		/* Back up 1 */
+			e_ovwc(c = SP);
+		  }
+		if(c == SP)
+		  {	if(lastc == SP)
+			  {	e_rdelc();
+				if(cur_dot > e_dot()) --cur_dot;
+				continue;
+			  }
+			lastbrk = len;
+			if(lastc == '.' || lastc == '!' || lastc == '?'
+#if ICONOGRAPHICS
+                                                        || lastc == ':'
+#endif /*ICONOGRAPHICS*/
+									)
+			  {	if(--parlen < 0) goto done;
+				if((c = e_getc()) == EOF)
+					goto done;
+				len++;
+				if(c != SP)
+				  {	e_backc();
+					e_putc(c = SP);
+					if(cur_dot >= e_dot()) ++cur_dot;
+				  }
+			  }
+		  }
+#if ICONOGRAPHICS
+		if (c == BS)                    /* adjust for backspaces */
+			if ((len -= 2) < 0) len = 0;
+#endif /*ICONOGRAPHICS*/
+		/* Normal char */
+		if(++len > ev_fcolumn && lastbrk)	/* If went too far */
+		  {	c = lastbrk - len;	/* Must put EOL at last SP */
+			e_igoff(c);
+			parlen -= c;	/* C is negative, actually adding */
+			parlen--;
+			e_ovwc(LF);
+			lastbrk = 0;
+			len = 0;
+			c = SP;		/* Pretend this char was space */
+#if FX_SFPREF
+			if(fill_plen)
+			  {	if(cur_dot >= e_dot())
+					cur_dot += fill_plen;
+				/* Better hope no nulls in prefix! */
+				e_sputz(fill_prefix);
+				len = d_curind();
+			  }
+#endif /*FX_SFPREF*/
+		  }
+	  }
+done:	savloc = cur_dot;
+	e_setcur();	/* Reached paragraph end, set cur_dot temporarily */
+	buf_tmod(begloc-cur_dot);	/* So that proper range is marked */
+	e_gosetcur(savloc);		/* Then restore original cur_dot */
+}
+#endif /*FX_FILLREG || FX_FILLPARA*/
+
+
+#if FX_FILLMODE
+
+/* EFUN: "Auto Fill Mode" */
+/*	Toggles Auto Fill Mode (a minor mode). */
+f_fillmode()
+{	register char *cp;
+	int *chballoc();
+
+	fill_mode = fill_mode ? 0 : 1;
+	if(!fill_trig)
+	  {	fill_trig = chballoc(128);
+		for(cp = fill_initrig; *cp; ++cp)
+			chbis(fill_trig, *cp);
+	  }
+	redp(RD_MODE);
+}
+
+/* Called by F_INSSELF to handle char insertion in Auto Fill mode */
+fx_insfill(c)
+int c;
+{
+	ed_insn(c,exp);
+	if(chbit(fill_trig, c))
+	  {	fill_cur_line();
+
+	  }
+}
+
+
+fill_cur_line()
+{
+	register int foundit, i;
+	chroff lastbrkdot, boldot, eoldot;
+
+	boldot = e_boldot();
+
+	/* First back up to find place to make first break. */
+	e_bwsp();
+	lastbrkdot = e_dot();
+	foundit = 0;
+	for(foundit = 0; foundit >= 0;)
+	  {	if((i = d_curind()) <= ev_fcolumn)
+		  {	if(foundit)
+				foundit = -1;
+			else break;
+		  }
+		else ++foundit;
+		while (!c_wsp (e_rgetc ())) ;
+		e_bwsp();
+		lastbrkdot = e_dot();
+		if(lastbrkdot <= boldot)
+		  {	lastbrkdot = boldot;
+			break;
+		  }
+	  }
+
+	if(foundit)
+		ed_fill(lastbrkdot, e_eoldot(), 1);
+}
+#endif /*FX_FILLMODE*/
+
+
+#if IMAGEN
+
+#if FX_TEXTMODE
+/* EFUN: "Text Mode Toggle" (not EMACS) */
+f_textmode()
+{
+	cur_buf->b_flags ^= B_TEXTMODE;
+	redp(RD_MODE);
+}
+#endif /*FX_TEXTMODE*/
+
+int curr_indent = -1;		/* Current indent (for text mode autowrap) */
+				/*  (misnomered: actually current column) */
+chroff best_break;		/* Best break point so far */
+
+
+/* Fill-mode version of "Insert Self" */
+
+fim_insself(c)
+int c;
+{
+	register int ind, flags = cur_buf->b_flags;
+
+	/* In Text mode, auto-wrap happens at spaces after fill column */
+	if (c == SP && flags & B_TEXTMODE && exp == 1 && magic_wrap(c))
+		return;
+
+	/* In C-mode, tab stops are every 4 columns */
+	else if (c == TAB && flags & B_CMODE &&
+			(ind = magic_backto_bol()) >= 0)
+		ed_indto((ind + 4) & ~3);
+	else
+	  {	ed_insn(c, exp);
+
+		/* Keep track of indent, once we have a grip on it */
+		if (last_cmd == INSCMD && curr_indent != -1)
+		  {	this_cmd = INSCMD;  /* Keep the ball rolling */
+			if (c == TAB)
+				curr_indent = ((curr_indent + 8) & ~7)
+						 + 8 * (exp - 1);
+			else if (c == '\n')
+				curr_indent = 0;
+			else if (c < SP || c > 0176)
+				curr_indent += (2 * exp);
+			else
+				curr_indent += exp;
+		  }
+	  }
+}
+
+/* Fill-mode version of "Delete Character" */
+
+fim_dchar()
+{	/* In C mode, deleting at BOL should do fake TAB preservation */
+	if (cur_buf->b_flags & B_CMODE)
+	  {	chroff savdot;
+		register int c, indent;
+
+		if (e_rgetc() != LF)
+		  {	/* Only hack this at BOL */
+			e_getc();
+			goto normal;
+	    	  }
+		e_getc();
+		savdot = e_dot();
+		indent = 0;
+		while ((c = e_getc()) == SP || c == TAB)
+			if (c == SP)
+				++indent;
+		else
+			indent = (indent + 8) & ~7;
+		e_rgetc();
+		if (indent >= 4)
+		  {	ed_delete(savdot, e_dot());
+			ed_indto((indent - 4) & ~3);
+			f_begline();		/* HACK!!!! */
+		  }
+		else
+		  {	e_go(savdot);
+			ef_deln(exp);
+		  }
+	  }
+	else
+ normal:	return (ef_deln(exp));
+}
+
+/* Fill-mode version of "Backward Delete Character" */
+
+fim_bdchar()
+{	register int ind;
+
+	/* If in C mode, and deleting into white space at BOL, hack tabs */
+	if (exp == 1 && cur_buf->b_flags & B_CMODE &&
+			(ind = magic_backto_bol()) > 0)
+		ed_indto(ind < 4 ? ind - 1 : ((ind - 4) & ~3));
+	else
+		return (ef_deln (-exp));
+}
+
+/* Fill-mode version of "CRLF" */
+fim_crlf()
+{	register int i;
+
+	if(e_getc() == LF
+	  && exp == 1
+	  && e_lblankp() && e_lblankp())
+	  {	e_gocur();
+		e_gonl();
+		e_setcur();
+		ed_delete(e_dot(), e_eoldot());
+	  }
+	else
+	  {	e_gocur();
+#if IMAGEN
+		if (cur_buf->b_flags & B_TEXTMODE && exp == 1 &&
+		    magic_wrap('\n'))
+			return;
+		else
+#endif /*IMAGEN*/
+		if((i = exp) > 0)
+			do ed_crins();
+			while(--i);
+	  }
+}
+
+
+/* Do all magic for auto-wrap in Text mode:
+ * return as did wrap (i.e., everything is taken care of)
+ */
+magic_wrap(tc)
+int tc;				/* "trigger char" */
+{
+	register int c, indent, i, nc;
+	chroff savdot, modstart, breakdot;
+    
+	savdot = e_dot();
+	nc = 0;
+	if (last_cmd == INSCMD && curr_indent != -1)
+	  {	indent = curr_indent;		/* Already know our indent */
+		breakdot = best_break;
+	  }
+	else
+	  {
+#ifdef INDENTDEBUG
+		barf2("Full indent calculation");
+#endif
+		for (nc = 0; (c = e_rgetc()) != EOF && c != '\n'; ++nc)
+		    ;				/* nc: # chars to look at */
+		if (c == '\n')			/* Go back over NL */
+			e_getc();
+		indent = 0;
+    
+		/* Search for last line break point, leaving it in breakdot */
+		breakdot = (chroff)0;
+		while (--nc >= 0)
+		  {	c = e_getc();
+			if (c == TAB)
+				indent = (indent + 8) & ~7;
+			else if (c < SP || c > 0176)
+				indent += 2;
+			else
+				++indent;
+			if ((c == SP || c == TAB) &&
+			  (breakdot == (chroff)0 || (indent <= ev_fcolumn)))
+				breakdot = e_dot();
+		  }
+	  }
+
+    /* If there is nothing to do, get out */
+	if (indent <= ev_fcolumn)
+	  {	e_go(savdot);
+		if (tc == SP)
+		  {	curr_indent = indent;
+			best_break = (chroff)(savdot + 1); /* Remember here, also */
+			this_cmd = INSCMD;		/* We do know current indent */
+		  }
+		else if (tc == '\n')
+		  {	curr_indent = 0;
+			best_break = (chroff)0;
+			this_cmd = INSCMD;
+		  }
+		else
+			errbarf("bad trigger");
+		return(0);
+	  }
+
+	if (breakdot == (chroff)0)
+	  {
+	/* No breakpoint found or none needed, just break line at end
+	 */
+		e_go(savdot);
+		modstart = savdot;
+		e_putc('\n');
+	  }
+	else
+	  {
+	/* Get to breakpoint and replace with newline
+	 */
+		e_go(breakdot);
+		e_rdelc();
+		modstart = e_dot();		/* Remember where changes start */
+		e_putc('\n');			/* Insert line break */
+		e_go(savdot);			/* Get back to trigger point */
+	  }
+	if (e_rgetc() != '\n')
+	  {		/* If not at line start, */
+		e_getc();
+		e_putc(tc);			/*  insert trigger character */
+
+	/* Once again, compute new indent by backing up to BOL */
+		for (nc = 0; (c = e_rgetc()) != EOF && c != '\n'; ++nc)
+			;
+		if (c == '\n')			/* Go back over NL */
+			e_getc();
+		indent = 0;
+		breakdot = (chroff)0;
+		while (--nc >= 0)
+		  {		/* Get back to current dot */
+			c = e_getc();
+			if (c == TAB)
+				indent = (indent + 8) & ~7;
+			else if (c < SP || c > 0176)
+				indent += 2;
+			else
+				++indent;
+			if ((c == SP || c == TAB) &&
+			  (breakdot == (chroff)0 || (indent <= ev_fcolumn)))
+				breakdot = e_dot();
+		  }
+		if (breakdot == (chroff)0)	/* If no good break found, use dot */
+			breakdot = e_dot();
+		curr_indent = indent;		/* Now we know where we are */
+		if (tc == '\n')			/* If trigger was NL */
+			best_break = (chroff)0;	/*  indent is 0, and no best break */
+		else
+			best_break = breakdot;	/* This is best break so far */
+	  }
+	else
+	  {	e_getc();
+		curr_indent = 0;		/* At line start, no indent */
+		best_break = (chroff)0;		/* Do not have a best break so far */
+	  }
+	ed_setcur();
+	buf_tmat(modstart);			/* Alert to potential changes */
+	this_cmd = INSCMD;			/* Say we know where we are */
+	return(1);
+}
+
+/* Do lots of magic things for C-mode indent:
+ * erase back to BOL iff we are looking back at white space only,
+ * returning the indent level of the original dot
+ * (< 0 means no erasure done)
+ */
+/*#define MYDEBUG /* */
+#ifdef MYDEBUG
+reveal(msg, v1, v2, v3)
+char *msg;
+{
+	char ahint[128];
+	sprintf(ahint, msg, v1, v2, v3);
+	barf2(ahint);
+}
+#endif
+
+magic_backto_bol()
+{
+	chroff savdot;
+	register int c, indent, nc, i;
+
+	savdot = e_dot();
+        nc = 0;
+	while ((c = e_rgetc()) != EOF && c != LF)
+	  {	++nc;			/* Count # chars */
+		if (c != SP && c != TAB)
+		  {	e_go(savdot);
+#ifdef MYDEBUG
+			reveal("fail: nc: %d", nc);
+#endif
+			return -1;
+        	  }
+    	  }
+	if (c == LF)			/* Go back over the LF */
+		e_getc();
+    	indent = 0;			/* (zero-based indent) */
+    	savdot = e_dot();		/* BOL is now origin for delete */
+    	for (i = 1; i <= nc; ++i)
+    		if ((c = e_getc()) == SP)
+			++indent;
+		else 			/* (tab) */
+			indent = (indent + 8) & ~7;
+    	if (nc > 0)			/* Don't bother deleting nothing */
+		ed_delete(savdot, e_dot());
+#ifdef MYDEBUG
+	reveal("indent: %d, nc: %d, foo: %d", indent, nc, 234);
+#endif
+	return(indent);
+}
+#endif /*IMAGEN*/
+
+
+#if ICONOGRAPHICS
+/* Iconographics hack for Auto-Fill mode.  Too big and clumsy, but
+ * retained for posterity in case it has some obscure feature.
+ */
+
+fill_current_line ()
+{
+        chroff startpos, endpos, savepos, limitpos;
+        int i, foundit;
+        SBSTR *savep;
+
+        foundit = 0;
+        while (d_curind() > ev_fcolumn)
+           {
+            foundit = 1;
+            startpos = e_dot ();
+            e_bwsp ();
+            while (d_curind() > ev_fcolumn) /* back up to ends of wds*/
+               {                                /* until <= fill column */
+                while (!c_wsp (e_rgetc ())) ;
+                e_bwsp ();
+               }
+            if (e_dot () == e_boldot ())
+               { /*	ding ("Word does not fit in fill column"); */
+	                return(0);
+               }
+            savep = e_copyn (startpos - e_dot ());
+            e_setcur ();                /* ed_delete does gocur */
+            ed_delete (savepos = e_dot (), startpos);
+
+		f_crlf();		/* Now insert newline */
+		e_sputz(fill_prefix);	/* With fill prefix */
+            startpos += e_dot () - savepos;
+            if (d_curind() > ev_fcolumn)
+               {	ed_delete (savepos, e_dot ());
+	                sb_sins (cur_buf, savep);
+	                e_setcur ();
+        	        ding ("Fill prefix > fill column???");
+                	return(0);
+               }
+            savepos = e_dot ();         /* gun inherited initial whitespace */
+            sb_sins (cur_buf, savep);
+            e_go (savepos);
+            e_fwsp ();
+            if ((limitpos = e_dot ()) > startpos) limitpos = startpos;
+                                        /* in case rest of line was white */
+            ed_delete (savepos, limitpos);
+            e_gosetcur (startpos + savepos - limitpos);
+           }
+
+        return foundit;
+  }
+#endif /*ICONOGRAPHICS*/
Index: /trunk/minix/commands/elle/eehelp.c
===================================================================
--- /trunk/minix/commands/elle/eehelp.c	(revision 9)
+++ /trunk/minix/commands/elle/eehelp.c	(revision 9)
@@ -0,0 +1,81 @@
+/* ELLE - Copyright 1982, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*	EEHELP - Help function
+ */
+
+#include "elle.h"		       /* include structure definitions */
+
+
+#if FX_DESCRIBE
+/* EFUN: "Describe" */
+/*	DESCRIBE - Help-command hack.
+**	Crude approximation of EMACS function.
+*/
+static struct buffer *help_buf;
+
+f_describe()
+{	register char *cp;
+	register int i, c;
+	char str[10];
+	struct buffer *savbuf, *b, *make_buf();
+	chroff bdot;
+
+	saynow("Help for command: ");
+	i = cmd_idx(c = cmd_read());		/* Get function idx for cmd */
+	if(c&CB_META) sayntoo("M-");
+	if(i == FN_PFXMETA)
+	  {	sayntoo("M-");
+		i = cmd_idx(c = (cmd_read() | CB_META));
+	  }
+	else if(i == FN_PFXEXT)
+	  {	sayntoo("^X-");
+		i = cmd_idx(c = (cmd_read() | CB_EXT));
+	  }
+	str[0] = c&0177;
+	str[1] = 0;
+	sayntoo(str);
+
+	/* Now read in the help file, if necessary */
+	savbuf = cur_buf;
+	if(help_buf)
+		chg_buf(help_buf);
+	else
+	  {
+		saynow("Loading ");
+		sayntoo(ev_helpfile);
+		sayntoo("...");
+		chg_buf(help_buf = make_buf(" **HELP**"));
+		if(read_file(ev_helpfile) == 0)
+		  {	chg_buf(savbuf);
+			kill_buf(help_buf);
+			help_buf = 0;
+			return;
+		  }
+	  }
+
+
+	/* Find function index in current buffer */
+	cp = str;
+	*cp++ = '<';
+	*cp++ = 'F';
+	cp = dottoa(cp, (chroff)i);
+	*cp++ = '>';
+	e_gobob();
+	if(e_search(str, cp-str, 0) == 0)
+		sayntoo(" No help found");
+	else
+	  {
+		bdot = e_dot();
+		while(!e_lblankp()) e_gonl();	/* Move past 1st blank line */
+		b = make_buf(" *SHOW*");
+		sb_sins((SBBUF *)b, e_copyn(bdot - e_dot()));
+		mk_showin(b);			/* Show the stuff */
+		kill_buf(b);
+		sayclr();
+	  }
+	chg_buf(savbuf);
+}
+#endif /*FX_DESCRIBE*/
Index: /trunk/minix/commands/elle/eekmac.c
===================================================================
--- /trunk/minix/commands/elle/eekmac.c	(revision 9)
+++ /trunk/minix/commands/elle/eekmac.c	(revision 9)
@@ -0,0 +1,181 @@
+/* ELLE - Copyright 1982, 1985, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*	EEKMAC - Keyboard Macro routines
+ *		Modelled after the "e_macro.c" for ICONOGRAPHICS
+ *		by C. D. Tavares, 9/11/82
+ */
+
+#include "elle.h"
+
+#if FX_SKMAC		/* Entire file is under this conditional! */
+
+int kdef_mode;		/* Set when collecting (a "minor mode") */
+static int km_flag = 0;	/* 1 = executing, -1 collecting, 0 neither */
+static int km_exp;	/* Arg to "Execute Kbd Macro" - # times more to xct */
+static struct buffer *km_buf;
+
+/* EFUN: "Start Kbd Macro" */
+
+f_skmac()
+{	register struct buffer *b;
+	struct buffer *make_buf();
+
+	if(km_flag)
+	  {	ding("Kbd macro active, ignoring \"Start Kbd Macro\"");
+		return;
+	  }
+	if((b = km_buf) == 0)
+		b = km_buf = make_buf(" *KBDMAC*");
+	ex_reset(b);
+	km_flag = -1;		/* Say starting macro collection */
+	kdef_mode = 1;
+	redp(RD_MODE);
+}
+
+/* EFUN: "End Kbd Macro" */
+
+f_ekmac()
+{
+	if(km_flag > 0 && (--km_exp >= 0))
+	  {	ex_go((SBBUF *)km_buf, (chroff)0);
+	  }
+	else if(km_flag)
+	  {	km_flag = 0;
+		kdef_mode = 0;	/* Flush minor mode */
+		redp(RD_MODE);
+	  }
+}
+
+/* EFUN: "Execute Kbd Macro" */
+
+f_xkmac()
+{
+	if(km_flag)
+		ding("Already in kbd macro!");
+	else if(km_buf == 0)
+		ding("No kbd macro defined");
+	else if((km_exp = exp-1) >= 0)
+	  {
+		ex_go((SBBUF *)km_buf, (chroff) 0);
+		km_flag = 1;		/* Start macro execution */
+	  }
+}
+
+/* EFUN: "View Kbd Macro" */
+
+f_vkmac()
+{	register struct buffer *b, *savbuf;
+	chroff prmplen;
+
+	if(!(b = km_buf))
+	  {	ding("No kbd macro defined");
+		return;
+	  }
+	savbuf = cur_buf;
+	chg_buf(b);
+	e_gobob();
+	e_sputz("Current Kbd macro:\n\n");
+	prmplen = e_dot();
+	mk_showin(b);		/* Show the macro buffer temporarily */
+	e_gobob();
+        chg_buf(savbuf);
+	sb_deln((SBBUF *)b, prmplen);	/* Flush the prompt */
+}
+
+
+/* KM_GETC - return next command char from kbd macro being executed.
+**	This is < 0 if not executing kbd macro.  Also responsible for
+**	gathering input for kbd macro.
+*/
+km_getc()
+{	register int c;
+
+	while (km_flag > 0)		/* Executing macro? */
+	  {	c = sb_getc(((SBBUF *)km_buf));	/* Yes, get char */
+		if(c != EOF)
+			return(c);		/* and return as cmd */
+
+		if(--km_exp >= 0)		/* Macro done.  Repeat? */
+			ex_go((SBBUF *)km_buf, (chroff)0);	/* Yes */
+		else km_flag = 0;		/* No, stop execution */
+	  }
+	c = tgetc();			/* Get char from user (TTY) */
+	if(km_flag < 0)			/* Save it if collecting macro */
+	  {	sb_putc(((SBBUF *)km_buf), c);
+	  }
+	return(c);
+}
+
+/* KM_INWAIT() - Return TRUE if any keyboard-macro input waiting.
+ */
+km_inwait()
+{	register int c;
+	if(km_flag > 0)
+		if((c = sb_getc(((SBBUF *)km_buf))) != EOF || (km_exp > 0))
+		  {	sb_backc(((SBBUF *)km_buf));
+			return(1);
+		  }
+	return(0);
+}
+
+km_abort ()
+{
+	if(km_flag > 0)		/* Executing? */
+		km_flag = 0;	/* Stop */
+	else if(km_flag < 0)	/* Collecting? */
+		f_ekmac();	/* Close it out */
+}
+
+#endif /*FX_SKMAC*/
+
+
+#if 0	/* Old unused stuff */
+static char mode_buf [60];
+
+add_mode (mode)
+  char *mode;
+  {
+        register char *cur, *c, *m;
+
+        if (cur_mode != mode_buf)
+           {
+            strcpy (mode_buf, cur_mode);
+            cur_mode = mode_buf;
+           }
+
+        if (cur_mode [0]) strcat (cur_mode, ", ");
+        strcat (cur_mode, mode);
+        make_mode ();
+  }
+
+remove_mode (mode)
+  char *mode;
+  {
+        register char *cur, *c, *m;
+
+        if (*cur_mode == 0) return;
+
+        if (cur_mode != mode_buf)
+           {
+            strcpy (mode_buf, cur_mode);
+            cur_mode = mode_buf;
+           }
+
+        for (cur = cur_mode ; *cur ; cur++)
+            if (*cur == *mode)          /* 1st char matches */
+               {
+                for (c = cur, m = mode ; *m && (*m == *c) ; m++, c++) ;
+                if (!(*m))              /* ok, mode matched */
+                   {                    /* kill leading ", " */
+                    if (*(cur - 1) == ' ') --cur;
+                    if (*(cur - 1) == ',') --cur;
+                    for ( ; *cur = *c ; cur++, c++) ;   /* recopy to end */
+                    make_mode ();
+                    return;
+                   }
+               }
+  }
+#endif /*COMMENT*/
Index: /trunk/minix/commands/elle/eemain.c
===================================================================
--- /trunk/minix/commands/elle/eemain.c	(revision 9)
+++ /trunk/minix/commands/elle/eemain.c	(revision 9)
@@ -0,0 +1,516 @@
+/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*
+ * EEMAIN	ELLE Main Command Loop
+ */
+
+#include "elle.h"
+
+#include <stdio.h>
+#if !(V6)
+#include <signal.h>
+#else
+#include "eesigs.h"		/* Use this on V6 system */
+#endif /*V6*/
+
+char *argfile[MAXARGFILES];	/* Filename args at startup */
+
+extern int (*sbm_debug)();
+extern int (*sbv_debug)();
+int (*vfy_vec)();	/* If non-zero, routine to verify data
+			 * after each main-loop command */
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+	register int c;		/* Current command character */
+	register int i;
+	static int waitct;
+	extern int errsbm();
+#if SUN
+	extern int sun_rdevf;	/* from EESUN */
+#endif
+#ifdef STKMEM
+	char stackm[STKMEM];		/* Allocate some unused stack space */
+#endif /*STKMEM*/
+
+	sbv_debug = errsbm;		/* Load with addrs of routine to */
+	sbm_debug = errsbm;		/* process SB and SBM errors. */
+
+#ifdef STKMEM
+	sbm_init(&stackm[0],(SBMO)STKMEM);	/* Initialize mem alloc rtns */
+#endif /*STKMEM*/
+#if SUN
+	sun_main(&argc, argv);		/* On SUN, invoke window startup */
+#endif /*SUN*/
+
+	setbuf(stdout, (char *)NULL);	/* Remove all stdio buffering */
+	setbuf(stderr, (char *)NULL);	/* in case of error reports. */
+
+	waitct = 0;			/* debugging */
+	doargs(argc,argv);		/* Set up args */
+	initialize ();			/* Initialize the editor */
+
+	if (argfile[0])			/* shell line arg */
+		find_file(argfile[0]);
+#if MAXARGFILES > 1
+	if(argfile[1])
+	  {	f_2winds();		/* Make 2 windows, go to 2nd */
+		i = 1;
+#if MAXARGFILES > 2
+		for (; i < MAXARGFILES; ++i)
+#endif /* > 2 files */
+			find_file(argfile[i]);	/* Get further file(s) */
+		f_othwind();		/* Move back to 1st window */
+	  }
+#endif /* > 1 file */
+
+	redp(RD_SCREEN|RD_MODE);	/* Clear and show mode line */
+	setexit(0);			/* catch for ints, ^G throws */
+
+/* -----------------------------------------------------------
+**			ELLE MAIN LOOP
+**
+*/
+	for (;;)
+	  {
+		/* First set up default arg unless last cmd specified it */
+		if(this_cmd != ARGCMD)
+		  {	exp = 1;		/* Default arg is 1 */
+			exp_p = 0;		/* Say no explicit arg */
+			last_cmd = this_cmd;
+		  }
+		this_cmd = 0;
+
+		askclr();		/* If stuff asked, say to clear it */
+		if(cmd_wait())
+			waitct++;
+		else if(rd_type != 0)
+			redisplay();	/* Redisplay if needed and no input */
+#if SUN
+		sun_rdevf = 1;		/* Allow mouse events on this input */
+#endif
+		c = cmd_read();		/* Read an editor command */
+		sayclr();		/* Ask to clear echo area cleverly */
+
+#if SUN
+		if(c != -1)		/* SUN may not have real input */
+#endif					/*    if mouse event happened. */
+			cmd_xct(c);	/* Execute the command char! */
+
+		if(vfy_vec)		/* If debugging, */
+			(*vfy_vec)(1);	/* verify data structs right away */
+	  }
+}
+
+
+char *prof_file;	/* Can specify user profile filename */
+
+doargs(argc,argv)
+int argc;
+char **argv;
+{	register int cnt, c;
+	register char **av;
+	extern int tibfmsk;
+	int argfiles = 0;
+	int argsignored = 0;
+
+	av = argv;
+	cnt = argc;
+
+#if V6	/* V6 doesn't have environment thus no TERM var */
+	/* Hack to force terminal type; analyze pgm name to get
+	 * possible ".type" suffix.
+	 */
+	if(cnt && (c = strlen(*av)))
+	  while(--c >= 0)
+	  {	switch(av[0][c])
+		  {	case '.':
+				tv_stype = &av[0][c+1];
+			case '/':
+				break;
+			default: continue;
+		  }
+		break;
+	  }
+#endif /*V6*/
+
+	while(--cnt > 0)
+	  {	++av;
+		if(*av[0] != '-')	/* If not switch, */
+		  {			/* assume it's an input filename */
+			if (argfiles < MAXARGFILES)
+				argfile[argfiles++] = *av;
+			else
+				++argsignored;
+			continue;
+		  }
+		c = upcase(av[0][1]);
+		switch(c)		/* Switches without args */
+		  {	case 'I':	/* Allow debug ints */
+				dbg_isw = 1;
+				continue;
+			case '8':		/* Ask for 8-bit input */
+				tibfmsk = 0377;
+				continue;
+			case '7':		/* Ask for 7-bit input */
+				tibfmsk = 0177;
+				continue;
+#if IMAGEN
+			case 'R':	/* Debug redisplay stuff */
+				dbg_redp = 1;
+				continue;
+#endif /*IMAGEN*/
+		  }
+		if(--cnt <= 0)
+			goto stop;
+		++av;
+		switch(c)		/* Switches with args */
+		  {	case 'T':	/* Terminal type */
+				tv_stype = *av;
+				break;	
+			case 'P':
+				prof_file = *av;
+			default:
+				goto stop;
+		  }
+		continue;
+	stop:	printf("ELLE: bad switch: %s\n",*av);
+		exit(1);
+	  }
+	if (argsignored > 0)
+	  {	printf("ELLE: more than %d file args, %d ignored.\n",
+			MAXARGFILES, argsignored);
+		sleep(2);	/* Complain but continue after pause */
+	  }
+}
+
+
+int f_throw();		/* throw function */
+int bite_bag();		/* Error handling routine */
+int hup_exit();		/* Hangup handling routine */
+
+struct majmode ifunmode = { "Fundamental" };
+
+initialize ()				/* Initialization */
+{
+#if SUN
+	extern int sun_winfd;
+#endif
+	cur_mode = fun_mode = &ifunmode;	/* Set current major mode */
+	unrchf = pgoal = -1;
+	if(!homedir)
+	  {
+#if V6
+		extern char *logdir();
+		homedir = logdir();
+#else /* V7 */
+		homedir = getenv("HOME");
+#endif /*-V6*/
+	  }
+
+	sbx_tset((chroff)0,0);		/* Create swapout file */
+					/* (Temporary hack, fix up later) */
+	hoard();			/* Hoard a FD for write purposes */
+
+	redp_init();			/* Set up the display routines */
+	init_buf();			/* Set up initial buffers */
+	set_profile(prof_file);		/* Set up user profile */
+
+#if SUN
+	if(sun_winfd) sun_init();
+#endif /*SUN*/
+
+	/* Set up signal handlers */
+#if 0					/* not really used */
+	signal (SIGQUIT, f_throw);	/* Quit - on ^G */
+#endif
+#if !(MINIX)
+	signal (SIGSYS, bite_bag);	/* Bad arg to Sys call */
+#endif
+	signal (SIGSEGV, bite_bag);	/* Segmentation Violation */
+#if !(COHERENT)
+	signal (SIGILL, bite_bag);	/* Illegal Instruction interrupt */
+	signal (SIGBUS, bite_bag);	/* Bus Error interrupt */
+#endif /*-COHERENT*/
+#if !(TOPS20)				/* T20 just detaches job */
+	signal (SIGHUP, hup_exit);	/* Terminal Hangup interrupt */
+#endif /*-TOPS20*/
+}
+
+
+/* NOTE: This routine is not actually used, because ELLE does not
+ * allow interrupts to do anything.
+ */
+/* EFUN: "Error Throw" */
+f_throw ()			       /* abort whatever is going on */
+{
+	ring_bell ();
+	curs_lin = -1000;		/* make t_curpos do something */
+	redp(RD_MOVE);		/* crock: cursor seems to move, so fix it */
+	signal(SIGQUIT, f_throw);	/* rearm signal */
+/*	unwind_stack(main); */
+	reset(1);			/* throw to main loop */
+}
+
+/* RING_BELL - General-purpose feeper when something goes wrong with
+ *	a function.
+ */
+ring_bell()
+{	t_bell();		/* Tell user something's wrong */
+
+#if FX_SKMAC
+        f_ekmac();		/* Stop collecting keyboard macro if any */
+#endif /*FX_SKMAC*/
+}
+
+
+/* EFUN: "Return to Superior"
+ *	Behavior here is somewhat system-dependent.  If it is possible to
+ * suspend the process and continue later, we do not ask about modified
+ * buffers.  Otherwise, we do.  Questioning can always be forced by using
+ * the prefix ^U.
+ *	Note that here we try to be very careful about not letting the user
+ * exit while buffers are still modified, since UNIX flushes the process
+ * if we exit.  Also, the code here conspires with sel_mbuf to rotate
+ * through all modified buffers, complaining about a different one each time,
+ * so that the user need not even know how to select a buffer!
+ */
+f_retsup()
+{	register char *reply;
+	register int c;
+	register struct buffer *b, *b2;
+	extern struct buffer *sel_mbuf();
+	extern int tsf_pause;
+
+	/* If we have capability of pausing and later continuing, do that,
+	 * except if CTRL-U forces us into question/save/quit behavior.
+	 */
+	if(tsf_pause && (exp_p != 4))
+	  {	clean_exit();		/* Return TTY to normal mode */
+		ts_pause();		/* Pause this inferior */
+		set_tty();		/* Continued, return to edit mode */
+		redp(RD_SCREEN);
+		return;
+	  }
+
+	/* Sigh, do more typical "Are you sure" questioning prior to
+	 * killing the editor permanently.
+	 */
+	b = cur_buf;
+	if((b = sel_mbuf(b)) || (b = sel_mbuf((struct buffer *)0)) )
+	  {	if(b2 = sel_mbuf(b))
+			reply = ask(
+		"Quit: buffers %s, %s,... still have changes - forget them? ",
+				b->b_name, b2->b_name);
+		else
+			reply = ask(
+		"Quit: buffer %s still has changes - forget them? ",
+				b->b_name);
+		
+	  }
+	else
+	  {
+#if IMAGEN	/* Do not ask further if nothing modified */
+		barf("Bye");
+		clean_exit();
+		exit(0);
+#else
+		reply = ask("Quit? ");
+#endif /*-IMAGEN*/
+	  }
+
+	if (reply == 0)
+		return;			/* Aborted, just return */
+
+	c = upcase(*reply);		/* Get 1st char of reply */
+	chkfree(reply);
+
+	switch(c)
+	  {	case 'Y':
+#if IMAGEN
+			barf("Bye");
+#endif /*IMAGEN*/
+			clean_exit();
+			exit(0);
+#if 0
+		case 'S':		/* Suspend command for debugging */
+			bkpt();
+			return;
+#endif /*COMMENT*/
+		default:		/* Complain */
+			ring_bell();
+		case 'N':
+			if(b)	/* B set if we have any modified buffers */
+			  {	sel_buf(b);
+				if(b->b_fn)
+					saynow("Use ^X ^S to save buffer");
+				else	saynow("Use ^X ^W to write out buffer");
+			  }
+	  }
+}
+
+
+
+#if FX_WFEXIT
+/* EFUN: "Write File Exit" (not EMACS) - from IMAGEN config */
+f_wfexit()
+{
+	exp_p = 1;		/* Ensure f_savefiles asks no questions */
+	if (! f_savefiles())	/* Save all modified buffers, but */
+		return;		/*  stay here if any save fails */
+	saynow("Bye");
+	clean_exit();
+	exit(0);
+}
+#endif /*FX_WFEXIT*/
+
+
+/* Subprocess-handling stuff; put here for time being. */
+
+/* EFUN: "Push to Inferior" */
+#if TOPS20
+#include <frkxec.h>	/* Support for KCC forkexec() call */
+#endif
+f_pshinf()
+{
+	register int res;
+	register int (*sav2)(), (*sav3)();
+	int pid, status;
+	char *shellname;
+#if IMAGEN
+	char fullshell[64];
+#endif /*IMAGEN*/
+
+	sav2 = signal(SIGINT, SIG_IGN);		/* Ignore TTY interrupts */
+	sav3 = signal(SIGQUIT, SIG_IGN);	/* Ditto TTY "quit"s */
+	clean_exit();				/* Restore normal TTY modes */
+
+#if TOPS20
+    {
+	struct frkxec fx;
+	fx.fx_flags = FX_WAIT | FX_T20_PGMNAME;
+	fx.fx_name = "SYS:EXEC.EXE";
+	fx.fx_argv = fx.fx_envp = NULL;
+	if (forkexec(&fx) < 0)
+		writerr("Cannot run EXEC");
+    }
+#else /*-TOPS20*/
+	switch(pid = fork())
+	  {	case -1:
+			writerr("Cannot fork");
+			break;
+		case 0:		/* We're the child */
+			for(res = 3; res < 20;)	/* Don't let inf hack fd's */
+				close(res++);
+#if V6
+			execl("/bin/sh","-sh",0);
+#else
+			signal(SIGINT, SIG_DFL);	/* V7 shell wants this?? */
+			signal(SIGQUIT, SIG_DFL);	/*	*/
+#if IMAGEN
+			if((shellname = getenv("SHELL")) == 0)
+				shellname = "sh";
+			strcpy(fullshell, "/bin/");
+			strcat(fullshell, shellname);
+			shellname = fullshell;
+#else
+			if((shellname = getenv("SHELL")) == 0)
+				shellname = "/bin/sh";
+#endif /*-IMAGEN*/
+
+			if((shellname = getenv("SHELL")) == 0)
+				shellname = "/bin/sh";
+			execl(shellname, shellname, 0);
+#endif /*-V6*/
+			writerr("No shell!");
+			exit(1);
+			break;
+		default:
+			while((res = wait(&status)) != pid && res != -1);
+			break;
+	  }
+#endif /*-TOPS20*/
+
+	signal(SIGINT, sav2);		/* Restore signal settings */
+	signal(SIGQUIT, sav3);
+	set_tty();			/* Restore editor TTY modes */
+	redp(RD_SCREEN|RD_MODE);	/* Done, redisplay */
+}
+
+
+/* Miscellaneous utility routines - memory alloc/free and string hacking.
+ * If this page becomes overly large, it can be split off into a separate
+ * file called E_MISC.
+ */
+char *
+strdup(s)
+char *s;	/* Note that STRCPY's return val must be its 1st arg */
+{	char *strcpy();
+	return(strcpy(memalloc((SBMO)(strlen(s)+1)), s));
+}
+
+char *
+memalloc(size)
+SBMO size;
+{	register SBMA ptr;
+	extern SBMA sbx_malloc();
+
+	if ((ptr = (SBMA)sbx_malloc(size)) != 0)
+		return((char *)ptr);
+	barf("ELLE: No memory left");
+	askerr();
+	return(0);		/* If we dare to continue... */
+}
+
+chkfree (ptr)
+SBMA ptr;
+{
+	if(!free(ptr))
+	  {	errbarf("Something overwrote an allocated block!");
+		askerr();
+	  }
+}
+
+
+/* USTRCMP - Uppercase String Compare.
+ *	Returns 0 if mismatch,
+ *		1 if full match,
+ *		-1 if str1 runs out first (partial match)
+ */
+ustrcmp(str1,str2)
+char *str1, *str2;
+{	register char *s1, *s2;
+	register int c;
+	s1 = str1; s2 = str2;
+	while(c = *s1++)
+	  {	if(c != *s2 && upcase(c) != upcase(*s2))
+			return(0);
+		s2++;
+	  }
+	return(c == *s2 ? 1 : -1);
+}
+
+
+/* WRITERR(str) - Output string to standard error output.
+**	This is a separate routine to save a little space on calls.
+*/
+writerr(str)
+char *str;
+{	return(writez(2, str));
+}
+
+/* WRITEZ(fd, str) - Miscellaneous general-purpose string output.
+ */
+writez(fd,acp)
+int fd;
+char *acp;
+{	register char *cp;
+	cp = acp;
+	while(*cp++);
+	write(fd,acp,cp-acp-1);
+}
Index: /trunk/minix/commands/elle/eemake.c
===================================================================
--- /trunk/minix/commands/elle/eemake.c	(revision 9)
+++ /trunk/minix/commands/elle/eemake.c	(revision 9)
@@ -0,0 +1,310 @@
+/* ELLE - Copyright 1982, 1985, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/* EEMAKE - IMAGEN configuration functions for interfacing to "make".
+ *	Written by (I think) Chris Ryland at IMAGEN, who also
+ * wrote other functions scattered through ELLE.  These are either
+ * conditionalized or are commented as being derived from the IMAGEN
+ * configuration.
+ *
+ * KLH: An attempt has been made to keep these routines updated as ELLE
+ * changed, but their workings cannot be guaranteed.
+ */
+
+
+/*
+ * eemake: "make" (and other program) support
+ *
+ * Next-error depends on programs writing error messages of the form:
+ *  "file", line n: message
+ * which is a de facto standard, at least in some worlds.
+ */
+
+#include "elle.h"
+
+#if !(IMAGEN)		/* Only with IMAGEN config for now */
+f_xucmd() {}
+f_make() {}
+f_nxterr() {}
+#else
+
+#include <stdio.h>
+
+struct buffer *exec_buf;	/* Ptr to "Execution" buffer */
+				/* Only external ref is from e_buff.c */
+
+#define MSGLENGTH (scr_wid - 11)	/* Max length of message */
+int fresh_make = 1;			/* Fresh Execution buffer contents */
+chroff last_error_BOL;			/* Dot for last-error's BOL */
+
+/* EFUN: "Execute Unix Command" */
+f_xucmd()
+{
+	make_or_unix_cmd(0);
+}
+
+/* EFUN: "Execute Make" */
+f_make()
+{
+	make_or_unix_cmd(1);
+}
+
+/* EFUN: "Find Next Error" */
+f_nxterr()
+{
+	register struct sbstr *sb;
+	register char *cp;
+	register int c;
+	char file[64], line[32];
+#ifdef ONEWINDOW
+	char msg[512];
+#endif
+	chroff linedot;
+	int lineno;
+	register int len;
+
+	sel_execbuf();
+	if (! fresh_make)
+	  {	e_go(last_error_BOL);
+		e_gonl();
+	  }
+	else
+	  {	fresh_make = 0;
+		e_gobob();
+		last_error_BOL = e_dot();
+	  }
+
+	/* Looking for `"file", line n: msg' */
+	if (! e_search("\", line ", 8, 0))
+		goto failed;
+	linedot = e_dot();
+	e_gobol();			/* Found something, get to BOL */
+	if (e_getc() != '"')
+		goto failed;		/* Insist on beginning "file" */
+	cp = file;			/* Pick up filename */
+	while ((c = e_getc()) != '"')
+		*cp++ = c;
+	*cp = 0;
+	e_go(linedot);			/* Back to after "line " */
+	cp = line;
+	while ((c = e_getc()) >= '0' && c <= '9')
+		*cp++ = c;
+	*cp = 0;
+	lineno = atoi(line);		/* Pick up line number */
+#ifdef ONEWINDOW
+	cp = msg;			/* Now get rest of line to msg */
+	len = 0;			/* But keep length <= MSGLENGTH */
+	e_getc();			/* Go past purported space */
+	while ((c = e_getc()) != LF && c != EOF && len <= MSGLENGTH)
+	  {	if (c == '\t')
+			len = (len + 8) & ~07;
+		else if (c < ' ' || c > 0176)
+			len += 2;
+		else
+			++len;
+		*cp++ = c;
+	  }
+	*cp = 0;
+	if (len > MSGLENGTH)
+		strcat(msg, "...");
+#ifdef DEBUG
+	say("file ");
+	saytoo(file);
+	saytoo(", line ");
+	saytoo(line);
+	saytoo(", msg: ");
+	sayntoo(msg);
+#else
+	say(line);
+	saytoo(": ");
+	sayntoo(msg);
+#endif /*DEBUG*/
+#else /* -ONEWINDOW */
+	f_begline();			/* Get to start of line */
+	last_error_BOL = e_dot();	/* Remember this position */
+	exp_p = 1;			/* Make this the new top line */
+	exp = 0;
+	f_newwin();
+	upd_wind(0);
+#endif /*ONEWINDOW*/
+
+	/* Now, visit the given file and line */
+#ifdef ONEWINDOW	
+#else
+	f_othwind();			/* To other window */
+#endif
+	find_file(file);
+	f_gobeg();
+	down_line(lineno - 1);
+#ifdef READJUST				/* NAW */
+	exp_p = 1;
+	exp = cur_win->w_ht / 4;	/* Adjust how we look at "error" */
+	f_newwin();
+#endif /*READJUST*/
+	return;
+
+failed:	ding("No more errors!");
+	fresh_make = 1;			/* Fake-out: pretend starting over */
+	return;
+}
+
+
+
+/* Do the "cmd" and put its output in the Execution buffer */
+do_exec(cmd, nicely)
+char *cmd;
+int nicely;
+{
+	register int n;
+	int status, res, pid, fd[2];
+	char nicecmd[256];
+	char pipebuff[512];
+	struct buffer *b;
+
+	b = cur_buf;
+	sel_execbuf();			/* Get our execution buffer up */
+	ed_reset();			/* Clear it out */
+	fresh_make = 1;
+	upd_wind(0);
+	if (nicely)
+		sayntoo(" ...starting up...");
+	else
+		sayntoo(" ...starting up (nasty person)...");
+	pipe(fd);
+	switch (pid = fork())
+	  {
+	case -1:
+		/* Fork failed, in parent */
+		ding("Cannot fork!?!");
+		break;
+
+	case 0: /* In child */
+		for (n = 0; n < 20; ++n)
+			if (n != fd[0] && n != fd[1])
+				close(n);
+		open("/dev/null", 0);	/* Give ourselves empty stdin */
+		dup(fd[1]);
+		dup(fd[1]);		/* stdout, stderr out to pipe */
+		close(fd[1]);		/* Close the pipe itself */
+		close(fd[0]);
+		if (nicely)
+		  {	strcpy(nicecmd, "nice -4 ");
+			strcat(nicecmd, cmd);
+			execl("/bin/sh", "sh", "-c", nicecmd, 0);
+		  }
+		else
+			execl("/bin/sh", "sh", "-c", cmd, 0);
+		write(1, "Cannot execute!", 15);
+		_exit(-1);
+		break;
+
+	default:
+		/* Parent */
+		close(fd[1]);		/* Close the output direction */
+		while ((n = read(fd[0], pipebuff, sizeof(pipebuff))) > 0)
+		  {	ed_nsins(pipebuff, n);
+			upd_wind(0);
+			saynow("Chugging along...");
+		  }
+		close(fd[0]);
+		while ((res = wait(&status)) != pid && res != -1)
+			;		/* Wait for this fork to die */
+		f_bufnotmod();		/* Buffer is fresh */
+		saynow("Done!");
+		break;
+	  }
+	f_othwind();			/* Back to other window */
+	chg_buf(b);			/* Back to original buffer */
+}
+
+char last_make_cmd[256];		/* Last Unix/make command */
+int have_last_make_cmd = 0;
+
+make_or_unix_cmd(domake)
+int domake;
+{
+#if APOLLO
+	register int nicely = exp == 16;	/* modification for apollo */
+#else
+	register int nicely = exp != 16;
+#endif /*-APOLLO*/
+	register char *reply, *cmd = 0;
+
+	if (domake)			/* If "make"-style, */
+	  {	int savp = exp_p;
+		exp_p = 1;
+		f_savefiles();		/*  write modified files quietly */
+		exp_p = savp;
+	  }
+	if (exp_p || ! domake)
+	  {		/* Arg given make, or Unix command */
+		reply = ask((! domake) ? "Unix command: " : "Command: ");
+		if (! reply)
+			return;
+		if (*reply == 0)
+		  {	if (have_last_make_cmd)
+				cmd = &last_make_cmd[0];
+			else
+			  {	chkfree(reply);
+				ding("No previous command!");
+				return;
+			  }
+		  }
+		else
+			cmd = reply;
+		if (cmd != &last_make_cmd[0])	/* Update last command */
+			strcpy(last_make_cmd, cmd);
+		have_last_make_cmd = 1;
+		say("Command: ");
+		sayntoo(cmd);
+		do_exec(cmd, nicely);
+		chkfree(reply);
+	  }
+	else if (have_last_make_cmd)
+	  {	say("Command: ");
+		sayntoo(last_make_cmd);
+		do_exec(last_make_cmd, nicely);
+	  }
+	else
+	  {	saynow("Command: make");
+		do_exec("make", nicely);
+	  }
+}
+
+
+sel_execbuf()
+{	if(!exec_buf)
+	  {	/* Make execution buffer; don't let anyone kill it */
+		exec_buf = make_buf("Execution");
+		exec_buf->b_flags |= B_PERMANENT;
+	  }
+	popto_buf(exec_buf);
+}
+
+/* Utility: pop the given buffer to a window, getting into 2-window mode */
+popto_buf(b)
+register struct buffer *b;
+{
+	/* See if we already have this buffer in a visible window */
+	if (b == cur_win->w_buf)
+	  {	if (oth_win == 0)
+		  {	f_2winds();
+			f_othwind();		/* Get back to our window */
+		  }
+	  }
+	else if (oth_win != 0 && b == oth_win->w_buf)
+		f_othwind();
+	else if (oth_win == 0)
+	  {		/* One window mode */
+		f_2winds();			/* Get two, get into second */
+		sel_buf(b);			/* Select our new buffer */
+	  }
+	else
+	  {	f_othwind();			/* Get to other window */
+		sel_buf(b);			/*  and select our buffer */
+	  }
+}
+
+#endif /*IMAGEN*/
Index: /trunk/minix/commands/elle/eeprof.h
===================================================================
--- /trunk/minix/commands/elle/eeprof.h	(revision 9)
+++ /trunk/minix/commands/elle/eeprof.h	(revision 9)
@@ -0,0 +1,20 @@
+#define PROF_VER (1)
+
+struct profile {
+int version;
+int chrvcnt;  char *chrvec; 
+int metavcnt; char *metavec;
+int extvcnt;  char *extvec; 
+int menuvcnt; char *menuvec;
+};
+
+struct stored_profile {
+unsigned char version[2];
+unsigned char chrvcnt[2], chrvec[2]; 
+unsigned char metavcnt[2], metavec[2];
+unsigned char extvcnt[2], extvec[2]; 
+unsigned char menuvcnt[2], menuvec[2];
+};
+
+#define prof_pack(p, n)		((p)[0] = (n) & 0xFF, (p)[1] = (n) >> 8)
+#define prof_upack(p)		((p)[0] | ((p)[1] << 8))
Index: /trunk/minix/commands/elle/eeproto.h
===================================================================
--- /trunk/minix/commands/elle/eeproto.h	(revision 9)
+++ /trunk/minix/commands/elle/eeproto.h	(revision 9)
@@ -0,0 +1,435 @@
+#ifndef _ANSI
+#include <ansi.h>
+#endif
+
+/* eebit.c */
+_PROTOTYPE( int *chballoc, (int size) );
+_PROTOTYPE( int chbit, (int *array, int c) );
+_PROTOTYPE( int chbis, (int *array, int c) );
+_PROTOTYPE( int chbic, (int *array, int c) );
+
+/* eebuff.c */
+_PROTOTYPE( int f_selbuffer, (void) );
+_PROTOTYPE( int f_selxbuffer, (void) );
+_PROTOTYPE( int f_kbuffer, (void) );
+_PROTOTYPE( int f_listbufs, (void) );
+_PROTOTYPE( int f_bufnotmod, (void) );
+_PROTOTYPE( int f_eolmode, (void) );
+_PROTOTYPE( int f_gobeg, (void) );
+_PROTOTYPE( int f_goend, (void) );
+_PROTOTYPE( int f_whatpage, (void) );
+_PROTOTYPE( int init_buf, (void) );
+_PROTOTYPE( struct buffer *make_buf, (char *bname) );
+_PROTOTYPE( struct buffer *find_buf, (char *name) );
+_PROTOTYPE( int sel_buf, (struct buffer *b) );
+_PROTOTYPE( int chg_buf, (struct buffer *newbuf) );
+_PROTOTYPE( int unlk_buf, (struct buffer *bufp) );
+_PROTOTYPE( struct buffer *sel_mbuf, (struct buffer *buf) );
+_PROTOTYPE( struct buffer *sel_mbuf, (struct buffer *buf) );
+_PROTOTYPE( struct buffer *sel_nbuf, (struct buffer *buf) );
+_PROTOTYPE( int kill_buf, (struct buffer *buf) );
+_PROTOTYPE( int zap_buffer, (void) );
+_PROTOTYPE( int ask_kbuf, (struct buffer *buf) );
+_PROTOTYPE( int f_2winds, (void) );
+_PROTOTYPE( int f_1wind, (void) );
+_PROTOTYPE( int f_othwind, (void) );
+_PROTOTYPE( int f_growind, (void) );
+_PROTOTYPE( int f_shrinkwind, (void) );
+_PROTOTYPE( int f_delwind, (void) );
+_PROTOTYPE( int f_sowind, (void) );
+_PROTOTYPE( int f_2modewinds, (void) );
+_PROTOTYPE( int chk2modws, (void) );
+_PROTOTYPE( int init_win, (void) );
+_PROTOTYPE( int chg_win, (struct window *newwin) );
+_PROTOTYPE( struct window *make_win, (int pos, int ht, struct buffer *buf) );
+_PROTOTYPE( int kill_win, (struct window *win) );
+_PROTOTYPE( int mk_showin, (struct buffer *b) );
+_PROTOTYPE( struct window *make_mode, (struct window *bw) );
+_PROTOTYPE( int buf_mod, (void) );
+_PROTOTYPE( int buf_tmat, (chroff dot) );
+_PROTOTYPE( int buf_tmod, (chroff offset) );
+
+/* eecmds.c */
+_PROTOTYPE( int f_pfxmeta, (void) );
+_PROTOTYPE( int f_pfxext, (void) );
+_PROTOTYPE( int f_uarg, (int ch) );
+_PROTOTYPE( int f_negarg, (int ch) );
+_PROTOTYPE( int f_argdig, (int ch) );
+_PROTOTYPE( int f_setprof, (void) );
+_PROTOTYPE( int f_vtbuttons, (void) );
+_PROTOTYPE( int cmd_wait, (void) );
+_PROTOTYPE( int cmd_read, (void) );
+_PROTOTYPE( int cmd_xct, (int ch) );
+_PROTOTYPE( int cmd_idx, (int c) );
+_PROTOTYPE( int set_profile, (char *filename) );
+_PROTOTYPE( int init_menu, (void) );
+
+/* eediag.c */
+_PROTOTYPE( int f_debug, (int ch) );
+_PROTOTYPE( char *vfy_data, (int flag) );
+_PROTOTYPE( int dbg_diag, (void) );
+_PROTOTYPE( int vfy_exer, (int pf, int gcfrq) );
+_PROTOTYPE( int db_prwind, (struct window *w) );
+_PROTOTYPE( char *db_scflgs, (int flags) );
+
+/* eedisp.c */
+_PROTOTYPE( int set_tty, (void) );
+_PROTOTYPE( int clean_exit, (void) );
+_PROTOTYPE( int set_scr, (void) );
+_PROTOTYPE( int redisplay, (void) );
+_PROTOTYPE( int fupd_wind, (struct window *w) );
+_PROTOTYPE( int upd_curs, (chroff adot) );
+_PROTOTYPE( int d_line, (chroff cdot) );
+_PROTOTYPE( int d_ncols, (int lcnt, int ccol) );
+_PROTOTYPE( int d_lupd, (struct window *w, int idx) );
+_PROTOTYPE( int clear_wind, (struct window *w) );
+_PROTOTYPE( int fix_wind, (struct window *win) );
+_PROTOTYPE( int inwinp, (struct window *win, chroff cdot) );
+_PROTOTYPE( int upd_wind, (struct window *win) );
+_PROTOTYPE( int slineq, (struct scr_line *olds, struct scr_line *news) );
+_PROTOTYPE( int upd_line, (int y) );
+_PROTOTYPE( int fillset, (char *str, int cnt, int c) );
+_PROTOTYPE( int fillsp, (char *str, int cnt) );
+_PROTOTYPE( int inspc, (char *cp0, char *cpl, int cnt) );
+_PROTOTYPE( int fix_line, (struct scr_line *slp, struct scr_line *olds) );
+_PROTOTYPE( int sctrin, (char *to, int lim, int ccol) );
+_PROTOTYPE( int inslin, (int line, int n, struct window *win) );
+_PROTOTYPE( int dellin, (int line, int n, struct window *win) );
+_PROTOTYPE( int t_dostandout, (int on) );
+_PROTOTYPE( int t_move, (int y, int x) );
+_PROTOTYPE( int t_docleol, (void) );
+
+/* eeedit.c */
+_PROTOTYPE( int e_reset, (void) );
+_PROTOTYPE( int e_rgetc, (void) );
+_PROTOTYPE( int e_rdelc, (void) );
+_PROTOTYPE( int e_delc, (void) );
+_PROTOTYPE( int e_getc, (void) );
+_PROTOTYPE( int e_backc, (void) );
+_PROTOTYPE( int e_putc, (int c) );
+_PROTOTYPE( int e_peekc, (void) );
+_PROTOTYPE( int e_ovwc, (int ch) );
+_PROTOTYPE( SBSTR *e_copyn, (chroff off) );
+_PROTOTYPE( int e_deln, (chroff off) );
+_PROTOTYPE( int e_setcur, (void) );
+_PROTOTYPE( int e_gosetcur, (chroff dot) );
+_PROTOTYPE( int e_gocur, (void) );
+_PROTOTYPE( int e_gobob, (void) );
+_PROTOTYPE( int e_goeob, (void) );
+_PROTOTYPE( int e_go, (chroff dot) );
+_PROTOTYPE( int e_igoff, (int ioff) );
+_PROTOTYPE( int e_goff, (chroff off) );
+_PROTOTYPE( int e_gobol, (void) );
+_PROTOTYPE( int e_goeol, (void) );
+_PROTOTYPE( int e_gonl, (void) );
+_PROTOTYPE( int e_gopl, (void) );
+_PROTOTYPE( chroff e_dot, (void) );
+_PROTOTYPE( chroff e_nldot, (void) );
+_PROTOTYPE( chroff e_pldot, (void) );
+_PROTOTYPE( chroff e_boldot, (void) );
+_PROTOTYPE( chroff e_eoldot, (void) );
+_PROTOTYPE( chroff e_alldot, (SBBUF *sbp, int (*rtn )()) );
+_PROTOTYPE( chroff e_blen, (void) );
+_PROTOTYPE( int ex_reset, (struct buffer *b) );
+_PROTOTYPE( int ex_go, (SBBUF *sbp, chroff loc) );
+_PROTOTYPE( chroff ex_dot, (SBBUF *sbp) );
+_PROTOTYPE( chroff ex_boldot, (SBBUF *sbp, chroff dot) );
+_PROTOTYPE( chroff ex_alldot, (SBBUF *sbp, int (*rtn )(), chroff dot) );
+_PROTOTYPE( int ex_gonl, (SBBUF *sbp) );
+_PROTOTYPE( int ex_goeol, (SBBUF *sbp) );
+_PROTOTYPE( int ex_gobol, (SBBUF *sbp) );
+_PROTOTYPE( int ex_gopl, (SBBUF *sbp) );
+_PROTOTYPE( chroff ex_blen, (SBBUF *sbp) );
+_PROTOTYPE( int e_gofwsp, (void) );
+_PROTOTYPE( int e_gobwsp, (void) );
+_PROTOTYPE( int e_goline, (int i) );
+_PROTOTYPE( int e_lblankp, (void) );
+_PROTOTYPE( int e_insn, (int ch, int cnt) );
+_PROTOTYPE( int e_sputz, (char *acp) );
+_PROTOTYPE( int boleq, (chroff dot1, chroff dot2) );
+_PROTOTYPE( char *dottoa, (char *str, chroff val) );
+_PROTOTYPE( int e_gobpa, (void) );
+_PROTOTYPE( int e_goepa, (void) );
+_PROTOTYPE( int exp_do, (int (*rpos )(), int (*rneg )()) );
+_PROTOTYPE( int e_fwsp, (void) );
+_PROTOTYPE( int e_bwsp, (void) );
+_PROTOTYPE( int c_wsp, (int ch) );
+_PROTOTYPE( int c_pwsp, (int ch) );
+_PROTOTYPE( int delimp, (int c) );
+_PROTOTYPE( int e_wding, (chroff *adot, int n) );
+_PROTOTYPE( chroff e_wdot, (chroff dot, int n) );
+_PROTOTYPE( int e_gowd, (int n) );
+_PROTOTYPE( int e_search, (char *mstr, int mlen, int backwards) );
+
+/* eeerr.c */
+_PROTOTYPE( int f_bkpt, (void) );
+_PROTOTYPE( int bpt, (void) );
+_PROTOTYPE( char *strerror, (int num) );
+_PROTOTYPE( int errsbm, (int type, int (*adr )(), char *str, int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12) );
+_PROTOTYPE( int bite_bag, (int fault) );
+_PROTOTYPE( int hup_exit, (void) );
+_PROTOTYPE( int errint, (void) );
+_PROTOTYPE( int askerr, (void) );
+_PROTOTYPE( char *asklin, (char *acp) );
+
+/* eef1.c */
+_PROTOTYPE( int f_insself, (int c) );
+_PROTOTYPE( int f_quotins, (void) );
+_PROTOTYPE( int f_crlf, (void) );
+_PROTOTYPE( int f_fchar, (void) );
+_PROTOTYPE( int f_bchar, (void) );
+_PROTOTYPE( int f_dchar, (void) );
+_PROTOTYPE( int f_bdchar, (void) );
+_PROTOTYPE( int ef_deln, (int x) );
+_PROTOTYPE( int f_delspc, (void) );
+_PROTOTYPE( int f_tchars, (void) );
+_PROTOTYPE( int f_fword, (void) );
+_PROTOTYPE( int f_bword, (void) );
+_PROTOTYPE( int f_kword, (void) );
+_PROTOTYPE( int f_bkword, (void) );
+_PROTOTYPE( int f_twords, (void) );
+_PROTOTYPE( int f_ucword, (void) );
+_PROTOTYPE( int f_lcword, (void) );
+_PROTOTYPE( int f_uciword, (void) );
+_PROTOTYPE( int case_word, (int downp) );
+
+/* eef2.c */
+_PROTOTYPE( int f_begline, (void) );
+_PROTOTYPE( int f_endline, (void) );
+_PROTOTYPE( int f_nxtline, (void) );
+_PROTOTYPE( int f_prvline, (void) );
+_PROTOTYPE( int f_dnrline, (void) );
+_PROTOTYPE( int f_uprline, (void) );
+_PROTOTYPE( int f_oline, (void) );
+_PROTOTYPE( int f_delblines, (void) );
+_PROTOTYPE( int f_kline, (void) );
+_PROTOTYPE( int f_bkline, (void) );
+_PROTOTYPE( int f_goline, (void) );
+_PROTOTYPE( int down_bline, (int arg) );
+_PROTOTYPE( int down_line, (int x) );
+_PROTOTYPE( int f_setmark, (void) );
+_PROTOTYPE( int f_exchmark, (void) );
+_PROTOTYPE( int f_kregion, (void) );
+_PROTOTYPE( int f_copreg, (void) );
+_PROTOTYPE( int f_ucreg, (void) );
+_PROTOTYPE( int f_lcreg, (void) );
+_PROTOTYPE( int ef_creg, (int downp) );
+_PROTOTYPE( int f_fillreg, (void) );
+_PROTOTYPE( int chkmark, (void) );
+_PROTOTYPE( int f_fpara, (void) );
+_PROTOTYPE( int f_bpara, (void) );
+_PROTOTYPE( int f_mrkpara, (void) );
+_PROTOTYPE( int f_fillpara, (void) );
+
+/* eef3.c */
+_PROTOTYPE( int f_appnkill, (void) );
+_PROTOTYPE( int f_unkill, (void) );
+_PROTOTYPE( int f_unkpop, (void) );
+_PROTOTYPE( int f_indatm, (void) );
+_PROTOTYPE( int f_indnl, (void) );
+_PROTOTYPE( int f_backind, (void) );
+_PROTOTYPE( int f_indcomm, (void) );
+_PROTOTYPE( int f_indrel, (void) );
+_PROTOTYPE( int insertmatch, (int c) );
+_PROTOTYPE( int f_matchbrack, (void) );
+_PROTOTYPE( int matchonelevel, (int mc) );
+
+/* eefd.c */
+_PROTOTYPE( int f_newwin, (void) );
+_PROTOTYPE( int f_nscreen, (void) );
+_PROTOTYPE( int f_pscreen, (void) );
+_PROTOTYPE( int f_othnscreen, (void) );
+_PROTOTYPE( int f_lwindbord, (void) );
+_PROTOTYPE( int f_scupwind, (void) );
+_PROTOTYPE( int f_scdnwind, (void) );
+_PROTOTYPE( int f_mvwtop, (void) );
+_PROTOTYPE( int f_mvwbot, (void) );
+_PROTOTYPE( int d_screen, (int rep) );
+_PROTOTYPE( int scroll_win, (int n) );
+_PROTOTYPE( int d_curind, (void) );
+_PROTOTYPE( int indtion, (chroff lin) );
+_PROTOTYPE( int inindex, (chroff lin, int xpos) );
+_PROTOTYPE( int d_gopl, (void) );
+_PROTOTYPE( int d_gonl, (void) );
+_PROTOTYPE( int d_goloff, (int cnt) );
+_PROTOTYPE( int d_fgoloff, (int cnt) );
+_PROTOTYPE( int d_fixcur, (void) );
+_PROTOTYPE( int d_backup, (int nlin) );
+
+/* eefed.c */
+_PROTOTYPE( int ed_insert, (int c) );
+_PROTOTYPE( int ed_insn, (int ch, int cnt) );
+_PROTOTYPE( int ed_crins, (void) );
+_PROTOTYPE( int ed_sins, (char *s) );
+_PROTOTYPE( int ed_nsins, (char *s, int i) );
+_PROTOTYPE( int ed_indto, (int goal) );
+_PROTOTYPE( int ed_setcur, (void) );
+_PROTOTYPE( int ed_go, (chroff dot) );
+_PROTOTYPE( int ed_goff, (chroff off) );
+_PROTOTYPE( int ed_igoff, (int ioff) );
+_PROTOTYPE( int ed_reset, (void) );
+_PROTOTYPE( int ed_deln, (chroff off) );
+_PROTOTYPE( int ed_delete, (chroff dot1, chroff dot2) );
+_PROTOTYPE( int ed_kill, (chroff dot1, chroff dot2) );
+_PROTOTYPE( int kill_push, (SBSTR *sdp) );
+_PROTOTYPE( int ed_case, (chroff dot1, chroff dot2, int downp) );
+_PROTOTYPE( int upcase, (int ch) );
+
+/* eefile.c */
+_PROTOTYPE( int f_ffile, (void) );
+_PROTOTYPE( int f_rfile, (void) );
+_PROTOTYPE( int f_vfile, (void) );
+_PROTOTYPE( int u_r_file, (char *prompt) );
+_PROTOTYPE( int f_ifile, (void) );
+_PROTOTYPE( int f_sfile, (void) );
+_PROTOTYPE( int f_savefiles, (void) );
+_PROTOTYPE( int f_wfile, (void) );
+_PROTOTYPE( int f_wreg, (void) );
+_PROTOTYPE( int f_wlastkill, (void) );
+_PROTOTYPE( int hack_file, (char *prompt, int (*rtn )()) );
+_PROTOTYPE( int find_file, (char *f_name) );
+_PROTOTYPE( int read_file, (char *f_name) );
+_PROTOTYPE( int ins_file, (char *f_name) );
+_PROTOTYPE( int ferr_ropn, (void) );
+_PROTOTYPE( int ferr_wopn, (void) );
+_PROTOTYPE( int ferr, (char *str) );
+_PROTOTYPE( char *fncons, (char *dest, char *pre, char *f_name, char *post) );
+_PROTOTYPE( char *last_fname, (char *f_name) );
+_PROTOTYPE( int set_fn, (char *string) );
+_PROTOTYPE( int saveworld, (struct buffer *bp, int grunt) );
+_PROTOTYPE( int hoard, (void) );
+_PROTOTYPE( int unhoard, (void) );
+_PROTOTYPE( int expand_file, (char *dfn, char *sfn) );
+
+/* eefill.c */
+_PROTOTYPE( int f_sfcol, (void) );
+_PROTOTYPE( int f_sfpref, (void) );
+_PROTOTYPE( int tstfillp, (int lim) );
+_PROTOTYPE( int ed_fill, (chroff begloc, chroff endloc, int flag) );
+_PROTOTYPE( int f_fillmode, (void) );
+_PROTOTYPE( int fx_insfill, (int c) );
+_PROTOTYPE( int fill_cur_line, (void) );
+_PROTOTYPE( int f_textmode, (void) );
+_PROTOTYPE( int fim_insself, (int c) );
+_PROTOTYPE( int fim_dchar, (void) );
+_PROTOTYPE( int fim_bdchar, (void) );
+_PROTOTYPE( int fim_crlf, (void) );
+_PROTOTYPE( int magic_wrap, (int tc) );
+_PROTOTYPE( int reveal, (char *msg, int v1, int v2, int v3) );
+_PROTOTYPE( int magic_backto_bol, (void) );
+_PROTOTYPE( int fill_current_line, (void) );
+
+/* eehelp.c */
+_PROTOTYPE( int f_describe, (void) );
+
+/* eekmac.c */
+_PROTOTYPE( int f_skmac, (void) );
+_PROTOTYPE( int f_ekmac, (void) );
+_PROTOTYPE( int f_xkmac, (void) );
+_PROTOTYPE( int f_vkmac, (void) );
+_PROTOTYPE( int km_getc, (void) );
+_PROTOTYPE( int km_inwait, (void) );
+_PROTOTYPE( int km_abort, (void) );
+_PROTOTYPE( int add_mode, (char *mode) );
+_PROTOTYPE( int remove_mode, (char *mode) );
+
+/* eemain.c */
+_PROTOTYPE( int doargs, (int argc, char **argv) );
+_PROTOTYPE( int initialize, (void) );
+_PROTOTYPE( int f_throw, (void) );
+_PROTOTYPE( int ring_bell, (void) );
+_PROTOTYPE( int f_retsup, (void) );
+_PROTOTYPE( int f_wfexit, (void) );
+_PROTOTYPE( int f_pshinf, (void) );
+_PROTOTYPE( char *strdup, (char *s) );
+_PROTOTYPE( char *memalloc, (SBMO size) );
+_PROTOTYPE( int chkfree, (SBMA ptr) );
+_PROTOTYPE( int ustrcmp, (char *str1, char *str2) );
+_PROTOTYPE( int writerr, (char *str) );
+_PROTOTYPE( int writez, (int fd, char *acp) );
+
+/* eemake.c */
+_PROTOTYPE( int f_xucmd, (void) );
+_PROTOTYPE( int f_make, (void) );
+_PROTOTYPE( int f_nxterr, (void) );
+_PROTOTYPE( int f_xucmd, (void) );
+_PROTOTYPE( int f_make, (void) );
+_PROTOTYPE( int f_nxterr, (void) );
+_PROTOTYPE( int do_exec, (char *cmd, int nicely) );
+_PROTOTYPE( int make_or_unix_cmd, (int domake) );
+_PROTOTYPE( int sel_execbuf, (void) );
+_PROTOTYPE( int popto_buf, (struct buffer *b) );
+
+/* eequer.c */
+_PROTOTYPE( int f_querep, (void) );
+_PROTOTYPE( int f_repstr, (void) );
+_PROTOTYPE( int f_repline, (void) );
+_PROTOTYPE( int ed_dorep, (int type, struct majmode *mode) );
+
+/* eeques.c */
+#if 0
+_PROTOTYPE( char *ask, (char *string, char *arg1, char *arg2, char *arg3) );
+#else
+char *ask();
+#endif
+_PROTOTYPE( int askclr, (void) );
+_PROTOTYPE( int say, (char *str) );
+_PROTOTYPE( int saynow, (char *str) );
+_PROTOTYPE( int saytoo, (char *str) );
+_PROTOTYPE( int sayntoo, (char *str) );
+_PROTOTYPE( int ding, (char *str) );
+_PROTOTYPE( int dingtoo, (char *str) );
+_PROTOTYPE( int saylntoo, (char *str, int n) );
+_PROTOTYPE( int sayclr, (void) );
+#if 0
+_PROTOTYPE( int sayall, (char *str, int flags, int len) );
+#else
+int sayall();
+#endif
+_PROTOTYPE( int yellat, (char *str, int line) );
+_PROTOTYPE( int yelltoo, (char *str) );
+_PROTOTYPE( int errbarf, (char *str) );
+_PROTOTYPE( int barf, (char *str) );
+_PROTOTYPE( int barf2, (char *str) );
+
+/* eesite.c */
+_PROTOTYPE( int ts_inp, (void) );
+_PROTOTYPE( int ts_init, (void) );
+_PROTOTYPE( int ts_enter, (void) );
+_PROTOTYPE( int ts_exit, (void) );
+_PROTOTYPE( int tpoke, (int cmd, int bn, int val) );
+_PROTOTYPE( int ts_pause, (void) );
+
+/* eesrch.c */
+_PROTOTYPE( int f_srch, (void) );
+_PROTOTYPE( int f_rsrch, (void) );
+_PROTOTYPE( int lin_search, (int backwards) );
+_PROTOTYPE( int srchint, (void) );
+_PROTOTYPE( char *srch_ask, (char *prompt) );
+_PROTOTYPE( int f_risrch, (void) );
+_PROTOTYPE( int i_search, (int back) );
+
+/* eeterm.c */
+_PROTOTYPE( int t_init, (void) );
+_PROTOTYPE( int t_fatal, (char *str) );
+_PROTOTYPE( int t_enter, (void) );
+_PROTOTYPE( int t_exit, (void) );
+_PROTOTYPE( int t_clear, (void) );
+_PROTOTYPE( int t_curpos, (int lin, int col) );
+_PROTOTYPE( int t_backspace, (void) );
+_PROTOTYPE( int t_bell, (void) );
+_PROTOTYPE( int t_cleol, (void) );
+_PROTOTYPE( int t_inslin, (int n, int bot) );
+_PROTOTYPE( int t_dellin, (int n, int bot) );
+_PROTOTYPE( int t_inschr, (int n, char *str) );
+_PROTOTYPE( int t_delchr, (int n) );
+_PROTOTYPE( int t_standout, (int on) );
+_PROTOTYPE( int t_direct, (int lin, int col, char *str, int len) );
+_PROTOTYPE( int tput, (int ch) );
+_PROTOTYPE( int tputz, (char *str) );
+_PROTOTYPE( int tputn, (char *str, int cnt) );
+_PROTOTYPE( int tbufls, (void) );
+_PROTOTYPE( int tgetc, (void) );
+_PROTOTYPE( int tinwait, (void) );
+
+/* eevini.c */
Index: /trunk/minix/commands/elle/eequer.c
===================================================================
--- /trunk/minix/commands/elle/eequer.c	(revision 9)
+++ /trunk/minix/commands/elle/eequer.c	(revision 9)
@@ -0,0 +1,189 @@
+/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*
+ * EEQUER	Query-Replace and Replace-String functions
+ */
+
+#include "elle.h"		       /* include structure definitions */
+
+/* EFUN: "Query Replace" */
+/*	Crude approximation of EMACS function.
+ */
+f_querep()
+{	static struct majmode iqrpmode = { "Query Replace" };
+	ed_dorep(0, &iqrpmode);
+}
+
+/* EFUN: "Replace String" */
+/*	Similar to Query Replace and uses same code.
+ */
+f_repstr()
+{	static struct majmode irepmode = { "Replace String" };
+	ed_dorep(1, &irepmode);
+}
+
+#if FX_REPLINE
+/* EFUN: "Replace in Line" (not EMACS) */
+/*	Acts like Replace String but only operates on current line.
+**	Currently a big crock.
+**	Feature of crockishness is that Unkill Pop (M-Y) will restore old
+**	line.
+*/
+f_repline()
+{
+	extern struct buffer *make_buf();
+	struct buffer *b, *oldb = cur_buf;
+	static struct majmode rlmode = { "Replace in Line" };
+
+	if(!(b = make_buf(" **LINE**")))
+	  {	ring_bell();
+		return;
+	  }
+	f_kline();		/* Kill line(s) from original buffer */
+	chg_buf(b);		/* Switch to temp buffer */
+	f_unkill();		/* Get killed stuff into temp buffer */
+	e_gosetcur((chroff)0);	/* Starting at beginning, */
+	ed_dorep(1, &rlmode);		/* Execute Replace String on it. */
+	ed_kill((chroff)0, e_blen());	/* Now kill everything in it, */
+	chg_buf(oldb);		/* switch back to original buffer, */
+	f_unkill();		/* and restore new stuff! */
+	kill_buf(b);		/* Now flush temporary buffer. */
+}
+#endif
+
+
+/* Note that the major mode is set without changing the buffer's major
+ * mode.  When the function is done, the current major mode is reset
+ * from the buffer mode.
+ */
+ed_dorep(type, mode)		/* 0 = Query Replace, 1 = Replace String */
+int type;
+struct majmode *mode;
+{	register int c;
+	register int olen, allflg;
+	char *srch_ask();
+	char *opromp, *npromp;
+	char *nstr, *ostr;	/* Note ostr is == to srch_str */
+	int nlen;
+	chroff last_loc;
+#if IMAGEN
+	int nrepled = 0;
+	char replmsg[64];
+#endif /*IMAGEN*/
+
+	/* Set mode, then get search string and replace string */
+#if IMAGEN
+	cur_win->w_buf->b_flags |= B_QUERYREP;
+#else
+	cur_mode = mode;	/* Set major mode pointer */
+#endif /*-IMAGEN*/
+
+	redp(RD_MODE);
+	nstr = 0;
+#if IMAGEN
+	opromp = "Old string: ";
+	npromp = "New string: ";
+#else
+	opromp = "Replace string: ";
+	npromp = "with string: ";
+#endif /*-IMAGEN*/
+	if((ostr = srch_ask(opromp)) == 0)
+		goto done;
+	olen = srch_len;	/* srch_ask sets this! */
+	if((nstr = ask("%s%s %s", opromp, ostr, npromp)) == 0)
+		goto done;
+	nlen = ask_len;
+
+	/* Now enter search and subcommand loop */
+	allflg = type;		/* Unless 0 for Query Rep, replace all */ 
+	for(;;)
+	  {	last_loc = cur_dot;
+		if(e_search(ostr,olen,0) == 0)
+			break;
+		ed_setcur();			/* Cursor moved */
+	redisp:
+		if(!allflg) redisplay();	/* Update screen */
+	getcmd:
+		if(!allflg) c = cmd_read();
+		else c = SP;
+		switch(c)
+		  {
+#if IMAGEN
+			case 'n':
+#endif /*IMAGEN*/
+			case DEL:	/* Don't replace, go on */
+				continue;
+#if IMAGEN
+			case ',':
+#endif /*IMAGEN*/
+			case '.':	/* Replace and exit */
+			case SP:	/* Replace, go on */
+				ed_delete(cur_dot,(chroff)(cur_dot-olen));
+				ed_nsins(nstr,nlen);
+#if IMAGEN
+				++nrepled;
+#endif /*IMAGEN*/
+				if(c == '.') goto done;
+				continue;
+#if IMAGEN
+			default:
+#endif /*IMAGEN*/
+			case '?':	/* Show options */
+#if IMAGEN
+				saynow("\
+' '=>change, 'n'=>don't, '.'=>change, quit, '!'=>change rest, '^'=>back up");
+#else
+				saynow("\
+SP=Replace, DEL=Don't, ESC=Stop, !=Replace all, ^=Back up, .=Replace & Stop");
+#endif /*-IMAGEN*/
+				goto getcmd;
+			case '^':	/* Return to last place found */
+				ed_go(last_loc);
+				goto redisp;
+
+			case CTRL('G'):
+			case ESC:	/* Exit where we are */
+				goto done;
+
+			case CTRL('L'):	/* Redisplay */
+				redp(RD_SCREEN);
+				goto redisp;
+
+			case '!':	/* Replace all the rest */
+				allflg++;
+				goto getcmd;
+
+#if !(IMAGEN)
+			case ',':	/* Replace and show */
+			case CTRL('R'):	/* Enter edit mode recursively */
+			case CTRL('W'):	/* Delete once and ^R */
+				saynow("not implemented");
+				goto getcmd;
+			default:	/* Exit and re-read char */
+				unrchf = c;
+				goto done;
+#endif /*-IMAGEN*/
+		  }
+	  }
+done:
+#if IMAGEN
+	cur_win->w_buf->b_flags &= ~B_QUERYREP;
+#else
+	cur_mode = cur_buf->b_mode;
+#endif /*-IMAGEN*/
+
+	redp(RD_MODE);
+	if(nstr) 	/* Free nstr (but not ostr, it's == srch_str!) */
+		chkfree(nstr);
+#if IMAGEN
+	if (nrepled <= 0)
+		saynow("No replacements done");
+	else
+	  {	sprintf(replmsg, "Replaced %d occurences", nrepled);
+		saynow(replmsg);
+	  }
+#endif /*IMAGEN*/
+}
Index: /trunk/minix/commands/elle/eeques.c
===================================================================
--- /trunk/minix/commands/elle/eeques.c	(revision 9)
+++ /trunk/minix/commands/elle/eeques.c	(revision 9)
@@ -0,0 +1,328 @@
+/* ELLE - Copyright 1982, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*	EEQUES - Handle queries and status displays
+ */
+#include "elle.h"
+
+/*
+ * Ask -- ask the user for some input on the lowest line of the screen
+ * 
+ * The arg is a string in printf form, followed by up to three args
+ * for the printf string
+ *
+ *        The string is read into a sort of mini buffer, only the
+ *        last line of which is visible on the screen. All editing
+ *        features are available to the user to edit the input string.
+ *        When the delim character is typed, input is terminated and
+ *        The input string is passed back to the caller.
+ *	  The delim is either an escape or a cr.
+ *        IT IS UP TO THE CALLER TO FREE THIS MEMORY.
+ *
+ * Note that the actual length of the returned string can be found
+ * in the global variable ask_len.  This is a crock but allows
+ * callers to hack nulls in arg strings if they want to.
+ */
+
+int chg_win();
+struct window *make_mode();
+
+static int ask_lin;	/* Saved cursor location when ask is done */
+static int ask_blen;	/* Non-zero if buffer contains something */
+static int ask_cnt;	/* Incremented by ask(), cleared by askclr() */
+
+/* Table of allowed functions during ASK */
+static char askftab[] = {
+	FN_PFXMETA, FN_INSSELF, FN_BEGLINE, FN_ENDLINE, FN_BCHAR, FN_FCHAR,
+	FN_DCHAR, FN_BDCHAR, FN_TCHARS, FN_QUOTINS, FN_UARG, FN_BKPT,
+	FN_DEBUG,
+	FN_GOBEG, FN_GOEND, FN_FWORD, FN_BWORD, FN_KWORD, FN_BKWORD,
+	FN_UCWORD, FN_LCWORD, FN_UCIWORD, FN_ARGDIG, FN_NEWWIN, FN_KLINE,
+	FN_UNKILL, FN_BKLINE,
+	0
+};
+
+char *
+ask (string, arg1, arg2, arg3)
+char *string, *arg1, *arg2, *arg3;
+
+{	register int i, c;
+	register char *s;
+	struct window *oldwin;
+	char *newline;		/* where output line goes */
+	char cbuf[200];			/* For prompt string creation */
+	int p_length;			/* length of prompt */
+	chroff anslen;			/* Length of answer */
+	int funnum;			/* Crock stuff */
+#if FX_FILLMODE
+	extern int fill_mode;
+	int ofillmode = fill_mode;	/* Gotta turn this one off */
+	fill_mode = 0;
+#endif /*FX_FILLMODE*/
+
+	oldwin = cur_win;
+	chg_win (ask_win);
+	ed_reset();			/* Flush contents & request redisp */
+	ask_lin = cur_win->w_pos;	/* Set here in case never redisp */
+	ask_cnt++;			/* Bump # of times called */
+
+  	/* copy 'string' into line */
+	cbuf[0] = 0;
+asklp:	sprintf (&cbuf[strlen(cbuf)], string, arg1, arg2, arg3);
+	p_length = strlen(cbuf);	/* Find how long it is */
+
+  	/* now let the user type in */
+	for(;;)
+	  {
+		if ((rd_type & (RDS_WINFLGS|RD_MODE)) && tinwait () == 0)
+		  {
+			e_gobob();	/* Gross crock: insert prompt */
+			e_sputz(cbuf);		/* Ugh, bletch */
+			cur_dot += p_length;	/* Temporarily update loc */
+			redp(RD_WINRES);	/* Do complete re-crunch */
+			upd_wind((struct window *)0);		/* Don't interrupt */
+			/* Ensure mode line is spiffy too.  This should
+			** only have to be invoked the first time ask_win
+			** redisplay is done, and never thereafter.
+			*/
+			if(rd_type&RD_MODE)	/* If mode also needs it, */
+				fupd_wind(make_mode(user_win));	/* do it */
+
+			upd_curs(cur_dot);
+			rd_type &= ~(RDS_WINFLGS|RD_MODE);
+			ask_lin = curs_lin;	/* Remember line cursor on */
+			tbufls();
+
+			e_gobob();	/* More crock: Remove prompt */
+			sb_deln((SBBUF *)cur_buf,(chroff)p_length);	/* Ugh etc. */
+			cur_dot -= p_length;		/* Restore loc */
+			e_gocur();
+		  }
+		exp = 1;
+		exp_p = 0;
+	cont:	this_cmd = 0;
+		c = cmd_read();
+
+		if (
+#if !(ICONOGRAPHICS)
+			c == ESC ||
+#endif /*-ICONOGRAPHICS*/
+				 c == LF || c == CR)
+			break;
+		if (c == BELL)       /* ^G means punt.. */
+		  {	chg_win(oldwin);
+			ask_blen = 1;	/* Assume buffer has something */
+			ding((char *)0);	/* Clear echo window */
+			ask_cnt = 0;	/* Nothing for askclr to do */
+#if FX_SKMAC
+			km_abort();
+#endif /*FX_SKMAC*/
+#if FX_FILLMODE
+			fill_mode = ofillmode;
+#endif /*FX_FILLMODE*/
+			return(0);	/* Return 0 to indicate we quit */
+		  }
+		/* This censoring section is a real crock! */
+		funnum = cmd_idx(c);		/* Map key to command */
+		while(funnum == FN_PFXMETA)	/* Allow META prefix */
+			funnum = cmd_idx(c = CB_META|cmd_read());
+		for(s = askftab; (i = *s&0377); ++s)
+			if(funnum == i) break;
+		switch(i)
+		  {	default:	/* Permissible function */
+				cmd_xct(c);
+				break;
+			case FN_NEWWIN:	/* Wants redisplay, do specially */
+				clear_wind(ask_win);
+				break;
+			case 0:		/* Illegal function */
+				ring_bell();
+#if FX_SKMAC
+				km_abort();
+#endif /*FX_SKMAC*/
+				continue;
+		  }
+		if(this_cmd == ARGCMD)
+			goto cont;
+	  }
+
+	if((anslen = e_blen()) > 255)		/* Ridiculously long? */
+	  {	strcpy(cbuf,"Huh? Try again - ");
+#if FX_SKMAC
+			km_abort();
+#endif /*FX_SKMAC*/
+		goto asklp;
+	  }
+	i = anslen;
+	e_gobob();		/* Go to start of buffer */
+	e_sputz(cbuf);		/* Re-insert prompt so buffer == screen */
+	ask_blen = i + 1;	/* Say buffer has something in it */
+
+	s = memalloc((SBMO)(i + 1));	/* Allocate fixed loc for answer */
+	newline = s;		/* Return ptr to allocated string */
+	ask_len = i;		/* And return (via global) length of string */
+	if(i) do { *s++ = e_getc(); }
+		while(--i);
+	*s = '\0';		       /* make sure string terminated */
+	chg_win(oldwin);
+#if FX_FILLMODE
+	fill_mode = ofillmode;
+#endif /*FX_FILLMODE*/
+	return (newline);	       /* return pointer to data */
+}
+
+/* ASKCLR - Clears the echo area (but not immediately) if the last thing
+**	done to it was an ask() call.  Note that invoking a SAY routine
+**	specifically causes this to be a no-op; SAYCLR must be done instead.
+*/
+askclr()
+{
+	if(ask_cnt) sayclr();	/* Zap if need be */
+}
+
+
+/* SAY - put up some text on bottom line.
+ *	Does this intelligently; text stays up until next SAY or
+ *	screen refresh.
+ * SAYNOW - like SAY but forces display right away
+ * SAYTOO - adds to existing stuff
+ * SAYNTOO - ditto but forces output right away.
+ * DING - Ring_bell then SAYNOW 
+ * DINGTOO - is to DING as SAYNTOO is to SAYNOW.
+ * SAYCLR - Clears echo area (but not immediately)
+ */
+#define SAY_NOW 01	/* Force display immediately */
+#define SAY_TOO 02	/* Add to existing stuff */
+#define SAY_BEL 04	/* Ding bell prior to text */
+#define SAY_LEN 010	/* String length specified by 3rd arg */
+
+say(str)	char *str; {	sayall(str, 0); }
+saynow(str)	char *str; {	sayall(str, SAY_NOW); }
+saytoo(str)	char *str; {	sayall(str, SAY_TOO); }
+sayntoo(str)	char *str; {	sayall(str, SAY_NOW|SAY_TOO); }
+ding(str)	char *str; {	sayall(str, SAY_NOW|SAY_BEL); }
+dingtoo(str)	char *str; {	sayall(str, SAY_NOW|SAY_TOO|SAY_BEL); }
+saylntoo(str,n)	char *str; {	sayall(str, SAY_NOW|SAY_TOO|SAY_LEN, n); }
+sayclr()		   {	sayall((char *)0, 0); }
+
+sayall(str,flags,len)
+char *str;
+int flags, len;
+{	register struct window *w;
+	register f;
+
+	f = flags;
+	w = cur_win;
+
+	ask_cnt = 0;			/* Always reset this */
+	if(str == 0 && ask_blen == 0)	/* If clearing, and buff empty */
+		return;			/* nothing to do. */
+	chg_win(ask_win);
+	if(f&SAY_TOO)
+		e_goeob();	/* Add to end of existing stuff */
+	else e_reset();		/* Flush previous stuff if any */
+	if(str)
+	  {	if(f&SAY_LEN)		/* Insert string to post up */
+			ed_nsins(str,len);
+		else e_sputz(str);
+	  }
+	ask_blen = e_dot();	/* Remember whether buffer has something */
+
+	e_setcur();		/* and remember to set dot */
+	if(f&SAY_NOW)
+	  {	if(f&SAY_BEL)
+			ring_bell();
+		redp(RD_WINRES);
+		upd_wind((struct window *)0);
+		tbufls();
+	  }
+	else redp(RD_WINRES);	/* Set for this window */
+	chg_win(w);		/* Back to previous window */
+
+	/* redisplay() does a special check for ask_win->w_redp, so we
+	** don't need to set a global flag like RD_CHKALL.
+	*/
+}
+
+
+/* YELLAT -- post string on specified line of screen, immediately.
+ *	Differs from SAYNOW and SAYNTOO in that NO buffer
+ *	manipulation is done; screen image is hacked directly.
+ */
+
+yellat(str, line)
+char *str;
+register int line;
+{	register struct scr_line *s;
+
+	s = scr[line];
+	strncpy(s->sl_nlin, str, scr_wd0);
+	s->sl_ncol = strlen(str);
+#if IMAGEN
+	s->sl_flg |= SL_REDO;
+#endif
+	upd_line(line);
+	tbufls();
+}
+
+/* YELLTOO -- Append string to previous echo line of screen, immediately.
+**	Uses the ask_lin variable which is set by ask().
+**	Currently this function is only needed for srchint() in EESRCH.
+*/
+yelltoo(str)
+char *str;
+{	register int i;
+	register struct scr_line *s;
+	char nstr[MAXLINE];
+
+	s = scr[ask_lin];
+	i = s->sl_col;
+	nstr[0] = 0;
+	strncat(strncat(nstr, s->sl_line, i),	/* Make new string */
+			str, MAXLINE - i);
+	yellat(nstr, ask_lin);			/* Post it */
+}
+
+
+/* BARF - output a message on the bottom line of the screen,
+**	bypassing everything (window, buffer, screen image).
+**	Does NOT know about SAY's stuff and does not update it!
+**	Use only in dire straits...
+** ERRBARF - same but uses a standard error-message prefix.
+*/
+
+errbarf(str)
+char *str;
+{
+	barf("\007ELLE Internal Error: ");
+	tputz(str);
+	tbufls();
+}
+
+barf(str)
+char *str;
+{
+	ask_cnt = 0;			/* Ensure askclr() disabled */
+	t_curpos(scr_ht - ECHOLINES, 0);       /* goto echo area */
+	t_cleol();
+	tputz(str);
+	tbufls();
+	curs_col = -1000;	/* Say we dunno where cursor is now */
+}
+
+#if IMAGEN
+/* Same, but do it far from harm's way */
+barf2(str)
+char *str;
+{
+	t_curpos (scr_ht - 1, scr_wid - strlen(str) - 8);
+	t_cleol ();
+	tputz(str);
+	tputz(" --M--");
+	tbufls();
+	tgetc();			/* Read any char & discard */
+	curs_col = -1000;	/* Say we dunno where cursor is now */
+}
+#endif /*IMAGEN*/
Index: /trunk/minix/commands/elle/eesigs.h
===================================================================
--- /trunk/minix/commands/elle/eesigs.h	(revision 9)
+++ /trunk/minix/commands/elle/eesigs.h	(revision 9)
@@ -0,0 +1,32 @@
+/* ELLE - Copyright 1984, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/* EESIGS.H
+ *	This file is only provided for inclusion only by V6 systems, where
+ * the standard /usr/include/signal.h file may not exist and thus we
+ * need to do our own definitions.
+ */
+
+/* Signals marked with "*" cause a core image dump
+ * if not caught or ignored. */
+
+#define	SIGHUP	1	/*   Hangup (eg dialup carrier lost) */
+#define	SIGINT	2	/*   Interrupt (user TTY interrupt) */
+#define	SIGQUIT	3	/* * Quit (user TTY interrupt) */
+#define	SIGILL	4	/* * Illegal Instruction (not reset when caught) */
+#define	SIGTRAP	5	/* * Trace Trap (not reset when caught) */
+#define	SIGIOT	6	/* * IOT instruction */
+#define	SIGEMT	7	/* * EMT instruction */
+#define	SIGFPE	8	/* * Floating Point Exception */
+#define	SIGKILL	9	/*   Kill (cannot be caught or ignored) */
+#define	SIGBUS	10	/* * Bus Error */
+#define	SIGSEGV	11	/* * Segmentation Violation */
+#define	SIGSYS	12	/* * Bad argument to system call */
+#define	SIGPIPE	13	/*   Write on a pipe with no one to read it */
+#define	SIGALRM	14	/*   Alarm Clock */
+#define	SIGTERM	15	/*   Software termination signal (from "kill" pgm) */
+
+#define	SIG_DFL	(int (*)())0	/* Arg to "signal" to resume default action */
+#define	SIG_IGN	(int (*)())1	/* Arg to "signal" to ignore this sig */
Index: /trunk/minix/commands/elle/eesite.c
===================================================================
--- /trunk/minix/commands/elle/eesite.c	(revision 9)
+++ /trunk/minix/commands/elle/eesite.c	(revision 9)
@@ -0,0 +1,364 @@
+/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/* EESITE	Site dependent frobs
+ *	Primarily TS_ routines for TTY control.  Most site-dependent
+ *	routine is TS_INP for detection of TTY input.
+ */
+
+#include "elle.h"
+
+#if !(V6)
+#include <signal.h>	/* For SIGTSTP in ts_pause */
+#else
+#include "eesigs.h"
+#endif
+
+int tsf_pause = 0;	/* Set if ts_pause works.  Ref'd by equit in e_main */
+
+#if !(SYSV || BBN)	/* SYSV and BBN have weird tty calls */
+
+#if MINIX
+#include <termios.h>
+struct termios origterm, newterm;
+#else
+#if V6
+	/* Normal V6 declarations, must provide explicitly */
+struct sgttyb {
+	char sg_ispeed;
+	char sg_ospeed;
+	char sg_erase;
+	char sg_kill;
+	int sg_flags;
+};
+#define ECHO (010)
+#define CRMOD (020)
+#define RAW (040)
+#else
+	/* Normal V7 UNIX declarations, can use include file */
+#include <sgtty.h>
+#endif
+
+struct sgttyb nstate;	/* Both V6 and V7 */
+struct sgttyb ostate;	/* Both V6 and V7 */
+#endif /*!(SYSV || BBN)*/
+#endif /*!MINIX*/
+
+
+#if BBN		/* BBN system frobs */
+#include "/sys/sys/h/modtty.h"
+struct modes  nstate;
+struct modes  ostate;
+#endif /*BBN*/
+
+#if DNTTY		/* DN TTY frobs */
+#include <tty.h>
+char partab[2];		/* to satisfy obscene ref in tty.h */
+#endif /*DNTTY*/
+
+
+#if (UCB || TOPS20)		/* UCB, TOPS20 additional frobs */
+#include <sys/ioctl.h>		/* For ts_inp() and tldisc */
+#if IMAGEN
+struct tchars otchars, ntchars;	/* Original and new tchars */
+#endif /*IMAGEN*/
+#endif /*(UCB || TOPS20)*/
+
+#if SYSV		/* System V (and PC/IX) crocks */
+#include <termio.h>
+#include <sys/ioctl.h>
+
+struct termio	/* terminal i/o status flags */
+	origterm,	/* status of terminal at start of ELLE */
+	newterm;	/* status of terminal when using ELLE */
+#endif /*SYSV*/
+
+/* TS_INP
+ *	Ask system if terminal input is available (on file descriptor 0).
+ *	Returns non-zero if so, else returns zero.
+ *	Very important that this call NOT hang or block in any way,
+ *	because it is used to detect type-ahead by the user;
+ *	return should be immediate whether or not input is waiting.
+ */
+ts_inp()
+{
+#if BBN				/* Idiosyncratic */
+	int   cap_buf[2];
+	capac (0, &cap_buf[0], 4);
+	return (cap_buf[0]);
+#endif /*BBN*/
+
+#if (DNTTY || ONYX)		/* Have "empty()" syscall */
+	return(empty(0) ? 0 : 1);
+#endif /*DNTTY || ONYX*/
+#if (UCB || TOPS20)		/* Have FIONREAD ioctl */
+	long retval;
+	if(ioctl(0,FIONREAD,&retval))	/* If this call fails, */
+		return(0);		/* assume no input waiting */
+	return((retval ? 1 : 0));
+#endif /*UCB || TOPS20*/
+#if COHERENT
+	int retval;
+	ioctl(0, TIOCQUERY, &retval);
+	return((retval ? 1 : 0));
+#endif /*COHERENT*/
+#if VENIX86
+	struct sgttyb iocbuf;
+	ioctl(0, TIOCQCNT, &iocbuf);
+	return(iocbuf.sg_ispeed != 0 );
+#endif /*VENIX86*/
+
+#if !(BBN||COHERENT||DNTTY||ONYX||TOPS20||UCB||VENIX86)
+	return(0);		/* Default - never any type-ahead, sigh */
+#endif
+}
+
+
+/* TS_INIT()
+ *	Get terminal information from system, initialize things for
+ *	ts_enter and ts_exit.  This is called before t_init.
+ *	Must set "trm_ospeed".
+ */
+ts_init()
+{
+#if DNTTY
+	signal(16,1);		/* DN peculiar - turn off ctl-A */
+#endif /*DNTTY*/
+
+#if !(MINIX || SYSV || BBN)		/* Normal UNIX stuff */
+	ioctl(1, TIOCGETP, &ostate);	/* Remember old state */
+	nstate = ostate;		/* Set up edit-mode state vars */
+	nstate.sg_flags |= RAW;			/* We'll want raw mode */
+	nstate.sg_flags &= ~(ECHO|CRMOD);	/* with no echoing */
+	trm_ospeed = ostate.sg_ospeed;
+
+#if (IMAGEN && UCB)
+	/* Get around 4.1+ remote/local flow control bug (from Gosmacs) */
+	ioctl(0, TIOCGETC, &otchars);  /* Save original tchars */
+	ntchars = otchars;
+	ntchars.t_startc = -1;		/* Kill start/stop */
+	ntchars.t_stopc  = -1;
+	ioctl(0, TIOCSETC, &ntchars);
+#endif /*IMAGEN && UCB*/
+#endif /*!(SYSV || BBN)*/
+
+#if BBN
+	modtty(1, M_GET | M_MODES, &ostate, sizeof(ostate));	/* Save old */
+	modtty(1, M_GET | M_MODES, &nstate, sizeof(nstate));	/* Setup new */
+	nstate.t_erase = nstate.t_kill = nstate.t_intr = nstate.t_esc =
+		nstate.t_eof = nstate.t_replay = 0377;
+	nstate.t_quit = BELL;			/* ^G */
+	nstate.t_breaks = TB_ALL;		/* break on all */
+	nstate.t_iflags &= ~TI_ECHO & ~TI_NOSPCL & ~TI_CRMOD;
+				/* no echos, specials on, no CR -> LF*/
+	nstate.t_iflags |= TI_CLR_MSB;			/* ignore parity */
+	nstate.t_oflags &= ~TO_CRMOD & ~TO_AUTONL;	/* no CR -> NL */
+	if (trm_flags & NOXONOFF)
+		nstate.t_oflags &= ~TO_XONXOFF;
+	else
+		nstate.t_oflags |= TO_XONXOFF;   
+
+	nstate.t_oflags |= TO_CLR_MSB;		/* no special high bits */
+	nstate.t_pagelen = 0;			/* no paging of output */
+	trm_ospeed = ostate.t_ospeed;
+#endif /*BBN*/
+
+#if MINIX
+	tcgetattr(0, &origterm);	/* How things are now */
+	newterm = origterm;		/* Save them for restore on exit */
+
+	/* input flags */
+	newterm.c_iflag |= IGNBRK;	/* Ignore break conditions.*/
+	newterm.c_iflag &= ~INLCR;	/* Don't map NL to CR on input */
+	newterm.c_iflag &= ~ICRNL;      /* Don't map CR to NL on input */
+	newterm.c_iflag &= ~BRKINT;	/* Do not signal on break.*/
+	newterm.c_iflag &= ~IXON;	/* Disable start/stop output control.*/
+	newterm.c_iflag &= ~IXOFF;	/* Disable start/stop input control.*/
+
+	/* output flags */
+	newterm.c_oflag &= ~OPOST;	/* Disable output processing */
+
+	/* line discipline */
+	newterm.c_lflag &= ~ISIG;	/* Disable signals.*/
+	newterm.c_lflag &= ~ICANON;	/* Want to disable canonical I/O */
+	newterm.c_lflag &= ~ECHO;	/* Disable echo.*/
+	newterm.c_lflag &= ~ECHONL;	/* Disable separate NL echo.*/
+	newterm.c_lflag &= ~IEXTEN;	/* Disable input extensions.*/
+
+	newterm.c_cc[VMIN] = 1;		/* Min. chars. on input (immed) */
+	newterm.c_cc[VTIME] = 0;        /* Min. time delay on input (immed) */
+
+	/* Make it stick */
+	tcsetattr(0, TCSANOW, &newterm);
+#endif /*MINIX*/
+
+#if SYSV
+	ioctl(0, TCGETA, &origterm);	/* How things are now */
+	newterm = origterm;		/* Save them for restore on exit */
+
+	/* input flags */
+	newterm.c_iflag |= IGNBRK;	/* Ignore break conditions.*/
+	newterm.c_iflag &= ~INLCR;	/* Don't map NL to CR on input */
+	newterm.c_iflag &= ~ICRNL;      /* Don't map CR to NL on input */
+	newterm.c_iflag &= ~BRKINT;	/* Do not signal on break.*/
+	newterm.c_iflag &= ~IXON;	/* Disable start/stop output control.*/
+	newterm.c_iflag &= ~IXOFF;	/* Disable start/stop input control.*/
+
+	/* line discipline */
+	newterm.c_lflag &= ~ISIG;	/* Disable signals.*/
+	newterm.c_lflag &= ~ICANON;	/* Want to disable canonical I/O */
+	newterm.c_lflag &= ~ECHO;	/* Disable echo.*/
+
+	newterm.c_cc[4] = 1;		/* Min. chars. on input (immed) */
+	newterm.c_cc[5] = 1;	        /* Min. time delay on input (immed) */
+
+	/* Make it stick */
+	ioctl(0, TCSETA, &newterm);
+#endif /*SYSV*/
+
+#if (UCB || TOPS20)
+	{	int tldisc;
+		ioctl(0, TIOCGETD, &tldisc);	/* Find line discipline */
+
+/* The flag IGN_JOB_CONTROL has been introduced to allow job control haters
+ * to simply ignore the whole thing.  When ELLE is compiled with
+ * -DIGN_JOB_CONTROL, it will exit properly when the Return to Superior
+ * command is executed.
+*/
+#if SIGTSTP
+#ifndef IGN_JOB_CONTROL
+		if(tldisc == NTTYDISC) tsf_pause = 1;
+#endif
+#endif /*SIGTSTP*/
+
+	}
+#endif /*UCB || TOPS20*/
+}
+
+/* TS_ENTER()
+ *	Tell system to enter right terminal mode for editing.
+ *	This is called before t_enter.
+ */
+ts_enter()
+{
+#if !(MINIX || SYSV || BBN)
+	ioctl(1, TIOCSETP, &nstate);
+#if IMAGEN && UCB
+	ioctl(0, TIOCSETC, &ntchars);	/* Restore new tchars */
+#endif /*IMAGEN && UCB*/
+#endif /*!(SYSV||BBN)*/
+
+#if BBN
+	modtty (1, M_SET | M_MODES, &nstate, sizeof (nstate));
+#endif /*BBN*/
+
+#if MINIX
+	/* Make it behave as previously defined in ts_init */
+	tcsetattr(0, TCSANOW, &newterm);
+#endif /*SYSV*/
+
+#if SYSV
+	/* Make it behave as previously defined in ts_init */
+	ioctl(0, TCSETA, &newterm);
+#endif /*SYSV*/
+
+#if DNTTY	/* DN hackery!  Enable 8-bit input so as to read meta bit. */
+	if(dbg_isw)
+	  {	tpoke(TH_CSET,T_2FLGS2,EEI);	/* Enable ints */
+		tpoke(TH_CSETB,T_QUIT, 0377);	/* Turn off QUIT intrpt */
+	  }
+	else if(trm_flags & TF_METAKEY)
+		tpoke(TH_CSET,T_2FLGS2,T2_LITIN); /* Turn on 8-bit input! */
+#endif /*DNTTY*/
+}
+
+/* TS_EXIT
+ *	Tell system to restore old terminal mode (we are leaving edit mode).
+ *	This is called after t_exit.
+ */
+ts_exit()
+{
+#if DNTTY
+	if(dbg_isw)
+		tpoke(TH_CCLR,T_2FLGS2,EEI);	/* Turn off EEI bit */
+	else if(trm_flags & TF_METAKEY)
+		tpoke(TH_CCLR,T_2FLGS2,T2_LITIN); /* Turn off 8-bit input */
+#endif /*DNTTY*/
+
+#if !(MINIX || SYSV || BBN)
+	ioctl(1, TIOCSETP, &ostate);	/* SYSV and BBN don't use stty */
+#if IMAGEN && UCB
+	ioctl(0, TIOCSETC, &otchars);	/* Restore original tchars */
+#endif /*IMAGEN && UCB*/
+#endif /*!(SYSV || BBN)*/
+
+#if BBN
+	modtty (1, M_SET | M_MODES, &ostate, sizeof (ostate));
+#endif /*BBN*/
+
+#if MINIX
+	tcsetattr(0, TCSANOW, &origterm);
+#endif /*MINIX*/
+
+#if SYSV
+	ioctl(0, TCSETA, &origterm);
+#endif /*SYSV*/
+}
+
+#if DNTTY
+int thkcmd[] { 0, 0, -1 };
+tpoke(cmd,bn,val)
+int cmd, bn, val;
+{
+	thkcmd[0] = cmd|bn;
+	thkcmd[1] = val;
+	if(ttyhak(0,&thkcmd) < 0)
+		return(-1);
+	else return(thkcmd[1]);
+}
+#endif /*DNTTY*/
+
+
+/* TS_PAUSE - Stop process and return control of TTY to superior.
+ *	There is also a flag variable, TSF_PAUSE, which indicates
+ *	whether or not this routine will actually do anything.
+ */
+#if TOPS20
+#include <jsys.h>
+#endif
+
+ts_pause()
+{
+#if TOPS20
+	int acs[5];
+	jsys(HALTF, acs);
+#endif
+
+#if UCB
+#if SIGTSTP
+	signal(SIGTSTP, SIG_DFL);
+#if BSD4_2
+#define	mask(s)	(1 << ((s)-1))
+	sigsetmask(sigblock(0) &~ mask(SIGTSTP));
+#endif /*BSD4_2*/
+	kill(0, SIGTSTP);
+#if BSD4_2
+	sigblock(mask(SIGTSTP));
+#endif /*BSD4_2*/
+#endif /*SIGTSTP*/
+#endif /*UCB*/
+}
+
+ts_winsize()
+{
+#ifdef TIOCGWINSZ
+	struct winsize winsize;
+
+	if (ioctl(1, TIOCGWINSZ, &winsize) == 0) {
+		if (winsize.ws_row != 0) scr_ht = winsize.ws_row;
+		if (winsize.ws_col != 0) scr_wid = winsize.ws_col;
+	}
+#endif
+}
Index: /trunk/minix/commands/elle/eesite.h
===================================================================
--- /trunk/minix/commands/elle/eesite.h	(revision 9)
+++ /trunk/minix/commands/elle/eesite.h	(revision 9)
@@ -0,0 +1,186 @@
+/* ELLE - Copyright 1984, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*
+ * EESITE.H	Site-dependent switches & definitions
+ */
+
+/* CONDITIONAL COMPILATION SWITCHES */
+
+#define V6	0	/* Running on V6 system (else V7 assumed) */
+
+#define APOLLO 0	/* Running on an Apollo system */
+#define BBN	0	/* Running on BBN system (tty stuff) */
+#define BSD4_2	0	/* Running on 4.2BSD system */
+#define COHERENT 0	/* Running on Coherent IBM-PC system */
+#define DNTTY	0	/* Running on SRI V6 Deafnet system (tty stuff) */
+#define HPUX	0	/* Running on Hewlett-Packard System V + */
+#define MINIX	1	/* Running on MINIX (IBM-PC) system */
+#define ONYX	0	/* Running on ONYX Z8000 system */
+#define PCIX	0	/* Running on PC/IX (IBM-PC) system */
+#define SUN	0	/* Running on SUN workstation system */
+#define SYSV	0	/* Running on Unix System V (or perhaps Sys III) */
+#define TOPS20	0	/* Running on TOPS-20 KCC C implementation */
+#define UCB	0	/* Running on 2.8, 2.9, or 4.x BSD sys (tty stuff) */
+#define VENIX86 0	/* Running on Venix86 (IBM-PC) system */
+
+#define ICONOGRAPHICS 0 /* Using Iconographics configuration version */
+#define IMAGEN 0	/* Using Imagen configuration version */
+
+/* Resolve system dependencies */
+#if SUN
+#undef BSD4_2
+#define BSD4_2 1	/* SUN uses 4.2BSD */
+#endif
+
+#if BSD4_2
+#undef UCB
+#define UCB	1	/* 4.2 is special case of general UCB stuff */
+#endif /*BSD4_2*/
+
+#if (PCIX || HPUX)
+#undef SYSV
+#define SYSV	1	/* PC/IX & HP-UX are based on System III & V (resp) */
+#endif
+
+
+/* Set system or site dependent stuff here */
+
+#if V6
+#define void int	/* May need this for other systems too */
+#endif
+
+/* Changes to parameters (elle.h) or variable defaults (e_vinit.c) */
+
+#if COHERENT
+#define EVFNO2  0	/* "Old" filename postfix - use no old file! */
+#define EVFNN2 "+"	/* "New" filename postfix */
+#define TX_COHIBM 1	/* Ensure Coherent IBM-PC console support included */
+#endif /*COHERENT*/
+
+#if DNTTY
+#define EVLLEN 60	/* Short line length for TDDs */
+#endif /*DNTTY*/
+
+#if HPUX
+#define EVFNO2 "~"	/* Same as CCA Emacs.  Sorts last in listing. */
+#endif /*HPUX*/
+
+#if MINIX
+#define EVFNO2 ".bak"	/* "Old" filename postfix */
+#define EVMARKSHOW "Mark set"
+#define EVCCOL (33)	/* Use this as Comment Column */
+#define EVMVPCT 1	/* 1% - Try to use minimal window repositioning */
+#define EVMODWSO 1	/* Use mode window standout if can */
+#define STRERROR 1	/* Say that implementation provides strerror() */
+
+#include <sys/types.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#endif /*MINIX*/
+
+#if ONYX
+#define STKMEM (4*512)		/* ONYX Z8000 seems to have less room avail */
+#endif /*ONYX*/
+
+#if BSD4_2
+#define FNAMELEN 255	/* Max size of last filename component */
+#define FNAMSIZ 400	/* Max size of complete filename */
+#endif /*BSD4_2*/
+
+#if TOPS20
+#define EVHELPFILE "elle:help.dat"	/* T20 ELLE help file */
+#define EVPROFBINFILE "ellep.b1"	/* T20 binary profile file */
+#define EVPROFTEXTFILE "ellep.e"	/* T20 ASCII profile file */
+#define EVFNO2 0	/* No old filename postfix (T20 has generations) */
+#define EVFNN2 0	/* No new filename postfix (T20 has generations) */
+#define FNAMELEN (40*3)	/* Max size of non-directory filename component */
+#define FNAMSIZ (40*5)	/* Max size of complete filename */
+#define STRERROR 1	/* Say that implementation provides strerror() */
+#endif /*TOPS20*/
+
+#if VENIX86
+#define TIBFSIZ 1	/* Venix86 block reads in raw mode */
+#endif /*VENIX86*/
+
+/* Configuration settings */
+
+#if ICONOGRAPHICS
+#define EVFNO2 "@"	/* "Old" filename postfix */
+#define EVMARKSHOW "Set."
+#define PARABLOCK 1	/* Values meaningful only for ICONOGRAPHICS */
+#define PARALINE  2
+#define TXC_VISBEL 1	/* Use visible bell if possible */
+#endif /*ICONOGRAPHICS*/
+
+#if IMAGEN
+#define EVFNO2 ".BAK"	/* "Old" filename postfix */
+#define EVMARKSHOW "Mark set"
+#define TOBFSIZ (10*80)	/* Size of TTY output buffer */
+#define ECHOLINES 2	/* Use 2 echo-area lines, not 1 */
+#define MAXARGFILES 10	/* Several startup filename args */
+#endif /*IMAGEN*/
+
+
+/* Now set any defaults for things not already defined */
+
+/* TERMINAL SUPPORT SWITCHES */
+/* 	Only those terminals which have a switch defined here	*/
+/*	will be included in ELLE's "hardwired" support.		*/
+/*	Switch name:	Compiles support for:			*/
+#ifndef TX_TERMCAP
+#define TX_TERMCAP 1	/*    *	- most TERMCAP-defined terminals */
+#endif
+#ifndef TX_H19
+#define TX_H19	1	/* "H19"	- Heath/Zenith-19 */
+#endif
+#ifndef TX_DM2500
+#define TX_DM2500 1	/* "DM2500","DM3025" - Datamedia 2500 */
+#endif
+#ifndef TX_COHIBM
+#define TX_COHIBM 0	/* "COHIBM"	- Coherent IBM-PC console */
+#endif
+#ifndef TX_TVI925
+#define TX_TVI925 0	/* "TVI925"	- TeleVideo 925 */
+#endif
+#ifndef TX_OM8025
+#define TX_OM8025 0	/* "OM8025"	- Omron 8025AG */
+#endif
+
+#ifndef TXC_VISBEL	/* Non-zero if want to use visible bell */
+#define TXC_VISBEL 0
+#endif
+
+/* Default terminal type string, used if ELLE cannot get type either
+** from $TERM or from startup args.
+*/
+#ifndef TXS_DEFAULT
+#define TXS_DEFAULT "H19"	/* Default terminal type string */
+#endif
+
+/* Combination parameter/switch definitions */
+
+/* STKMEM - System-dependent stack allocation crock, defines amount of
+ *	stack memory to grab for general-purpose use.  This is mainly
+ *	useful for PDP-11s or machines with similarly brain-damaged
+ *	address space hardware.  A PDP-11 memory segment is 8K bytes,
+ *	or 16 512-byte blocks, and the stack segment quarantines all of
+ *	this space even though the actual stack may only use a miniscule
+ *	portion of it.
+ */
+
+/* Use this if compiling for a PDP11 system, otherwise leave undefined.. */
+#if (V6 || 0)
+#define STKMEM (8*512)		/* Use half a PDP11 segment */
+#endif
+
+/* These defaults are in eesite.h so ELLEC can get at them too. */
+#ifndef EVPROFBINFILE	/* Location of binary user profile, relative to HOME */
+#define EVPROFBINFILE ".ellepro.b1"
+#endif
+#ifndef EVPROFTEXTFILE	/* Location of ASCII user profile (used by ELLEC) */
+#define EVPROFTEXTFILE ".ellepro.e"
+#endif
Index: /trunk/minix/commands/elle/eesrch.c
===================================================================
--- /trunk/minix/commands/elle/eesrch.c	(revision 9)
+++ /trunk/minix/commands/elle/eesrch.c	(revision 9)
@@ -0,0 +1,277 @@
+/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*
+ * EESRCH	Searching functions
+ */
+
+#include "elle.h"
+#if !(V6)
+#include <signal.h>
+#else
+#include "eesigs.h"		/* Use this on V6 system */
+#endif /*V6*/
+
+/*
+ *   Buffer String Search routines
+ *
+ *      If no search string is provided, a string that was previously
+ *      used in the last search is once again used.
+ */
+
+/* EFUN: "String Search" */
+f_srch()
+{	return (lin_search (0));
+}
+
+/* EFUN: "Reverse String Search" */
+f_rsrch()
+{	return (lin_search (1));
+}
+
+/* LIN_SEARCH - Main routine for non-incremental String Search.  Asks for
+ *	a search string and looks for it.
+ */ 
+lin_search (backwards)
+int  backwards;
+{	register char *mem;	/* item to be searched for */
+	register int res;
+	int srchint(), (*sav_srchalarm)();
+	char *srch_ask();
+	chroff savdot;
+
+	savdot = cur_dot;		/* Save original loc */
+
+#if ICONOGRAPHICS
+        if((mem = srch_ask(backwards ? "Reverse Search%s%s%s"
+                                     : "Search%s%s%s"))==0)
+                return;
+#else
+        if((mem = srch_ask(backwards ? "Reverse Search: " : "Search: "))==0)
+                return;
+#endif /*-ICONOGRAPHICS*/
+	sav_srchalarm = signal(SIGALRM,/*&*/srchint);	/* Handle timeout */
+	alarm(1);					/* One sec from now */
+
+	res = e_search(mem,srch_len,backwards);	/* Search for str! */
+
+	alarm(0);				/* Turn off alarm */
+	signal(SIGALRM,sav_srchalarm);		/* Restore old handler */
+
+	if(res)				/* Search won? */
+	  {	ed_setcur();
+		return;
+	  }
+
+	/* Search failed */
+	e_gosetcur(savdot);
+	ding("Search Failed");
+}
+
+srchint()
+{	yelltoo(" ...");
+}
+
+char *
+srch_ask(prompt)
+char *prompt;
+{	register char *ans, *old;
+
+#if ICONOGRAPHICS
+        if (srch_str)
+           ans = ask(prompt, " (", srch_str, "): ");
+        else ans = ask (prompt, ": ", "", "");
+        if (ans == 0) return (0);
+#else
+        if((ans = ask(prompt)) == 0)
+                return(0);              /* user punted ... */
+#endif /*-ICONOGRAPHICS*/
+	old = srch_str;
+	if (*ans == '\0')
+	  {	chkfree(ans);
+		if ((ans = old) == 0)		/* no string specified */
+		  {	dingtoo("Nothing to search for");
+			return(0);
+		  }
+#if !(ICONOGRAPHICS)
+		saylntoo(old, srch_len);	/* Show what old string is */
+#endif /*-ICONOGRAPHICS*/
+	  }
+	else
+	  {	if (old)
+			chkfree(old);	/* free up old srch string */
+		srch_str = ans;
+		srch_len = ask_len;
+	  }
+	return(ans);
+}
+
+
+#if 0
+	Incremental Search stuff.
+Description of EMACS behavior:
+	^Q quotes next char.
+	DEL cancels last char.  If this cancelled a match, point is moved
+		to previous match.
+	If not all of input can be found, it is not discarded.  Can rub out,
+		discard unmatched stuff with ^G, exit, etc.
+	^S repeats search forward; ^R repeats backward.
+		If empty string, either
+			changes direction (if not same)
+			or brings back previous string
+	ESC exits.  If empty string, changes to non-incremental string search.
+	^G of a winning search aborts, exits, and moves point back to origin.
+	^G of a failing search discards the input that wasn''t found.
+	Other C- or M- chars exit and are executed.
+ELLE also interprets ^H (BS) as DEL, because some keyboards make it hard to
+	type DEL and there is no way the user can
+	re-bind the incremental-search commands.
+#endif /*COMMENT*/
+
+#if FX_ISRCH
+/* EFUN: "Incremental Search" */
+f_isrch() { i_search(0); }
+#endif /*FX_ISRCH*/
+
+#if FX_RISRCH
+/* EFUN: "Reverse Search" */
+f_risrch() { i_search(1); }
+#endif /*FX_RISRCH*/
+
+#if FX_ISRCH || FX_RISRCH
+
+i_search(back)
+int back;		/* Current mode: 0 if forward, 1 if backward */
+{	register int c;
+	register int inpcnt;	/* # chars in current input srch str */
+	int inpgood;		/* Length of last winning string */
+	char inpstr[ISRCHLIM];	/* Holds current input search string */
+	chroff inpdot[ISRCHLIM];	/* Holds winning addrs for each */
+	struct window *savwin;
+	int winning;	/* 1 = currently winning, 0 = currently failing */
+	int pref, shown;
+	int f_insself(), (*(cmd_fun()))();
+
+	winning = 1;
+	inpcnt = 0;
+	inpgood = 0;
+	inpdot[0] = cur_dot;
+	savwin = cur_win;
+
+	/* Set up prompt and read all TTY input thus far */
+	shown = 0;
+ sloop:	c = cmd_wait();		/* See if any command input waiting */
+	if(shown || !c)
+	  {	e_setcur();	/* Assume we moved around, so set cur_dot */
+		chg_win(ask_win);
+		ed_reset();	/* Flush contents & invoke redisplay */
+		ed_sins(back ? "R-search: " : "I-search: ");
+		ed_nsins(inpstr, inpcnt);
+		if(!winning) ed_sins("\t(FAILING)");
+		upd_wind((struct window *)0);	/* Force ask_win update */
+		if(c)
+		  {	upd_curs(cur_dot);
+			tbufls();
+		  }
+		chg_win(savwin);
+		shown = 1;	/* Say search prompt has been shown */
+	  }
+	if(!c)			/* If no user input waiting, show buffer */
+	  {	redp(RD_MOVE);		/* Cursor moved in window */
+		redisplay();
+	  }
+	c = cmd_read();		/* Get input char */
+	switch(c)
+	  {	case DEL:		/* Cancel last char */
+		case BS:		/* Hard to type DEL on some kbds */
+			if(inpcnt <= 0) goto sloop;
+			if(--inpcnt > inpgood) goto sloop;
+			winning = 1;
+			if(inpcnt == inpgood) goto sloop;
+			inpgood--;
+			ed_go(inpdot[inpcnt]);
+			goto sloop;
+
+		case CTRL('Q'):
+			c = cmd_read();	/* Quote next char */
+			break;
+		case CTRL('S'):
+			pref = 0;
+			goto ctlsr;
+		case CTRL('R'):
+			pref = 1;
+			goto ctlsr;
+
+		case CTRL('G'):
+			if(winning)
+			  {	ed_go(inpdot[0]);
+				goto sdone;
+			  }
+			inpcnt = inpgood;
+			winning = 1;
+			goto sloop;
+		case ESC:
+		case CR:
+			if(inpcnt)
+				goto sdone;
+			lin_search(back);
+			return;
+		default:
+			if(f_insself != cmd_fun(c))
+			  {	unrchf = c;
+				goto sdone;
+			  }
+		case TAB:	/* Strange self-inserting char */
+			break;
+	  }
+	if(inpcnt >= ISRCHLIM-1)
+	  {	ding("I-search str too long");
+		sleep(1);
+		goto sdone;
+	  }
+	inpstr[inpcnt++] = c;
+	if(!winning) goto sloop;
+
+	/* Now search for string.  (Arm alarm interrupt?) */
+	/* cur_dot has current location cursor is at; we want to back off
+	 * from this so a repeated search will find the same location if
+	 * appropriate. */
+	e_igoff(back ? inpcnt : -(inpcnt-1));
+dosrch:
+	winning = e_search(inpstr,inpcnt,back);
+	if (winning)
+	  {	inpgood = inpcnt;	/* Remember last win length */
+		inpdot[inpcnt] = e_dot();	/* and location */
+	  }
+	else e_gocur();			/* Back to start position */
+	goto sloop;
+
+ ctlsr:	if (pref != back)
+	  {	back = pref;
+		if(inpcnt <= 0) goto sloop;
+	  }
+	if(inpcnt <= 0)
+	  {	if(!srch_str || (inpcnt = srch_len) <= 0)
+			goto sloop;
+		bcopy((SBMA)srch_str, (SBMA)inpstr, srch_len);
+		inpcnt = srch_len;
+		unrchf = c;		/* Repeat cmd after display */
+		shown = 1;		/* Force search-string display */
+		goto sloop;
+	  }
+	goto dosrch;
+
+  sdone:
+	if(srch_str) chkfree(srch_str);
+	srch_str = memalloc((SBMO)(inpcnt+1));
+	bcopy((SBMA)inpstr,(SBMA)srch_str,inpcnt);	/* Copy into srch_str */
+	srch_len = inpcnt;
+	e_setcur();
+	chg_win(ask_win);
+	ed_reset();
+	chg_win(savwin);
+	redp(RD_CHKALL);
+}
+#endif /*FX_ISRCH || FX_RISRCH*/
Index: /trunk/minix/commands/elle/eeterm.c
===================================================================
--- /trunk/minix/commands/elle/eeterm.c	(revision 9)
+++ /trunk/minix/commands/elle/eeterm.c	(revision 9)
@@ -0,0 +1,1300 @@
+/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*
+ *  EETERM	ELLE Terminal Driver.
+ *	Directly supports DM2500, H-19, Omron 8025AG, Coherent/IBM-PC, TVI925.
+ *	Others also supported if using TX_TERMCAP.
+ */
+
+#include "elle.h"
+
+/* Define terminal indices (there may be holes but C preprocessor is too
+ * stupid to let us close them).  Should be one TN_ definition for every
+ * hardwired terminal type, even though whether or not it is actually
+ * compiled depends on which TX_ switches are defined.
+ */
+#define TN_TERMCAP 0
+#define TN_DM2500 1
+#define TN_H19	  2
+#define TN_OM8025 3
+#define TN_COHIBM 4	/* Coherent IBM-PC console */
+#define TN_TVI925 5
+
+#if TX_COHIBM && !(TX_H19)	/* Ensure H19 defined if COHIBM is. */
+#define TX_H19 1
+#endif
+
+#ifndef TXS_DEFAULT		/* If no default is explicitly specified */
+#define TXS_DEFAULT "H19"	/* Then settle for H-19 */
+#endif /*TXS_DEFAULT*/
+
+
+
+
+extern char *tv_stype;	/* If set, specifies terminal type */
+extern int tibfmsk;	/* Crock to mask off parity (meta) bit */
+static int tv_padc;	/* Pad character to use */
+static int tv_cspeed;	/* # msec per char (set from trm_ospeed) */
+static int tv_type;	/* Index of selected terminal type */
+
+/* Internal functions */
+static void tpadn(), tpad();
+
+/* Character speed table, indexed by system output speed value (0-017).
+ * Value in table is 100 * <# msec used per character>.
+ */
+static int cspdtab[] =
+{	/* Val    Idx Baud CPS  Time/char in msec */
+	0,	/*  0 Hangup -	----		*/
+	13333,	/*  1   50 7.5 133.33  (Baudot)	*/
+	10000,	/*  2   75  10 100.0   (Baudot)	*/
+	10000,	/*  3  110  10 100.0		*/
+	 8200,	/*  4 134.5 12.2 82.0 (IBM2741)	*/
+	 6666,	/*  5  150  15 	66.6666 	*/
+	 5000,	/*  6  200  20	50.0		*/
+	 3333,	/*  7  300  30	33.3333 	*/
+	 1666,	/*  8  600  60  16.6666 	*/
+	  833,	/*  9 1200 120   8.3333 	*/
+	  555,	/* 10 1800 180   5.5555 	*/
+	  416,	/* 11 2400 240   4.1666 	*/
+	  208,	/* 12 4800 480   2.0833		*/
+	  104,	/* 13 9600 960   1.04166	*/
+	0,	/* 14 Ext A  ?	 ?		*/
+	0	/* 15 Ext B  ?	 ?		*/
+};
+
+#if TX_TERMCAP
+/* Declarations for TERMCAP stuff.  Only EETERM knows about them. */
+
+/* Termcap routines */
+extern int tgetent(), tgetnum(), tgetflag(), tputs();
+extern char *tgetstr(), *tgoto();
+static int getcap();		/* Internal routines */
+static void putpad(), putnpad(), putpar();
+
+/* Gross disgusting externals that must be defined for TERMCAP rtns */
+char	PC;		/* Pad char */
+char	*BC;		/* Backspace to use, if not ^H */
+char	*UP;		/* Cursor up */
+short	ospeed;		/* Terminal output speed */
+
+/* Termcap numerical values/flags */
+static int
+	tc_am,		/* TRUE if has auto-wrap */
+	tc_km;		/* TRUE if meta key exists */
+
+/* Termcap capability strings we want to know about */
+
+struct tcap { char tcicod1, tcicod2, *tccap; };
+static struct tcap tcap[] = {
+#define TC_al	tcap[0].tccap	/* Add (insert) line */
+	{'a','l', 0},
+#define TC_AL	tcap[1].tccap	/* Add N lines */
+	{'A','L', 0},
+#define TC_bc	tcap[2].tccap	/* Backspace Char (for BC) */
+	{'b','c', 0},
+#define TC_ce	tcap[3].tccap	/* Erase to end of line (CLEOL) */
+	{'c','e', 0},
+#define TC_cl	tcap[4].tccap	/* Clear screen */
+	{'c','l', 0},
+#define TC_cm	tcap[5].tccap	/* Cursor motion */
+	{'c','m', 0},
+#define TC_dc	tcap[6].tccap	/* Delete char */
+	{'d','c', 0},
+#define TC_DC	tcap[7].tccap	/* Delete N chars */
+	{'D','C', 0},
+#define TC_dl	tcap[8].tccap	/* Delete line */
+	{'d','l', 0},
+#define TC_DL	tcap[9].tccap	/* Delete N lines */
+	{'D','L', 0},
+#define TC_dm	tcap[10].tccap	/* Delete mode on */
+	{'d','m', 0},
+#define TC_ed	tcap[11].tccap	/* Delete mode off */
+	{'e','d', 0},
+#define TC_ei	tcap[12].tccap	/* Insert mode off */
+	{'e','i', 0},
+#define TC_ia	tcap[13].tccap	/* Add line while in insert mode (see note) */
+	{'i','a', 0},
+#define TC_ic	tcap[14].tccap	/* Insert blank char */
+	{'i','c', 0},
+#define TC_IC	tcap[15].tccap	/* Insert N blank chars */
+	{'I','C', 0},
+#define TC_id	tcap[16].tccap	/* Delete line while in del mode (see note) */
+	{'i','d', 0},
+#define TC_im	tcap[17].tccap	/* Insert mode on */
+	{'i','m', 0},
+#define TC_ip	tcap[18].tccap	/* Padding to send after char insertion */
+	{'i','p', 0},
+#define TC_mm	tcap[19].tccap	/* String to set (turn on) meta-key mode */
+	{'m','m', 0},
+#define TC_mo	tcap[20].tccap	/* String to reset (turn off) meta-key mode */
+	{'m','o', 0},
+#define TC_pc	tcap[21].tccap	/* Pad Char (for PC) */
+	{'p','c', 0},
+#define TC_se	tcap[22].tccap	/* End standout mode */
+	{'s','e', 0},
+#define TC_so	tcap[23].tccap	/* Enter standout mode */
+	{'s','o', 0},
+#define TC_te	tcap[24].tccap	/* String to end programs that use termcap */
+	{'t','e', 0},
+#define TC_ti	tcap[25].tccap	/* String to beg programs that use termcap */
+	{'t','i', 0},
+#define TC_up	tcap[26].tccap	/* Move cursor up (for UP) */
+	{'u','p', 0},
+#define TC_vb	tcap[27].tccap	/* Visible bell */
+	{'v','b', 0},
+};
+#define NTCAPS ((sizeof(tcap))/(sizeof(struct tcap)))	/* # entries */
+
+/*
+ * There are many other things that must be taken into account.
+ * The termcap code here will probably not work for many termcap entries,
+ * but the only sure way to find out which ones they are is to try them.
+ */
+/* Note that the "ia" and "id" strings are not defined by the TERMCAP doc;
+ * their usage here is derived from examining other TERMCAP-using programs.
+ * Sigh!!!!
+ */
+#endif /*TX_TERMCAP*/
+
+
+/* T_INIT is called once only at program startup, to identify the
+ *	terminal type and set up any one-time things.
+ * T_FATAL is only called if some routine detects an error related to the
+ *	terminal specification, before any initialization is done.
+ *	It prints a short error message and exits the program.
+ * T_ENTER is called after TS_ENTER to set the terminal parameters for
+ *	editing (as opposed to normal typeout).  It may be called
+ *	several times.
+ * T_EXIT is called before TS_EXIT to restore normal typeout modes.
+ *	It is called on exit from the program, and perhaps other times.
+ */
+t_init()
+{
+	char *getenv();
+
+	/* Set some default parameters */
+	scr_ht = 24;
+	scr_wid = 79;
+	trm_flags = 0;
+	tvc_cin = 1;		/* Assume 1 char per char I/D pos */
+	tvc_cdn = 1;
+	tvc_pos = 4;		/* Default abs-move cost is 4 chars */
+	tvc_bs = 1;		/* Default backspace cost is 1 char */
+	tv_cspeed = cspdtab[trm_ospeed];	/* Find # msec per char */
+
+	/* First must determine terminal type, and check for terminals
+	 * that are hardwired into ELLE. */
+	if(!tv_stype		/* String set in command line args? */
+#if !(V6)
+	 && !(tv_stype = getenv("TERM"))	/* or given by TERM var? */
+#endif /*-V6*/
+		) tv_stype = TXS_DEFAULT;	/* No, try using default */
+	if(0) ;			/* Sigh, stupid construct */
+#if TX_H19
+	else if(ustrcmp(tv_stype,"H19")) tv_type = TN_H19;
+#endif /*TX_H19*/
+#if TX_OM8025
+	else if(ustrcmp(tv_stype,"OM8025")) tv_type = TN_OM8025;
+#endif /*TX_OM8025*/
+#if TX_DM2500
+	else if(ustrcmp(tv_stype,"DM2500")) tv_type = TN_DM2500;
+	else if(ustrcmp(tv_stype,"DM3025")) tv_type = TN_DM2500;
+#endif /*TX_DM2500*/
+#if TX_COHIBM
+	else if(ustrcmp(tv_stype,"COHIBM")) tv_type = TN_COHIBM;
+#endif /*TX_COHIBM*/
+#if TX_TVI925
+	else if(ustrcmp(tv_stype,"TVI925")) tv_type = TN_TVI925;
+#endif /*TX_TVI925*/
+#if TX_TERMCAP	/* This should be last thing */
+	else if(getcap(tv_stype)) tv_type = TN_TERMCAP;
+#endif /*TX_TERMCAP*/
+	else t_fatal("type unknown");	/* Ugh, barf and exit */
+
+	/* Terminal selected, now initialize parameters for it. */
+	switch(tv_type)
+	  {
+#if TX_DM2500
+		case TN_DM2500:
+			tv_padc = 0177;		/* Use rubout for pad */
+			tvc_pos = 3;		/* Only 3 chars for abs mov */
+			tvc_ci = 2;
+		/*	tvc_cin = 1; */		/* Default is OK */
+			tvc_cd = 2;
+		/*	tvc_cdn = 1; */		/* Default is OK */
+			tvc_ld = 2;
+			tvc_ldn = 1;
+			tvc_li = 2;
+			tvc_lin = 1;
+			if(trm_ospeed == 13)	/* If 9600, */
+			  {	tvc_cin = 5;		/* Sigh, high cost */
+				tvc_cdn = 2;
+				tvc_lin = 18;
+				tvc_ldn = 2;
+			  }
+			trm_flags |= TF_IDLIN|TF_IDCHR|TF_CLEOL|TF_METAKEY;
+			break;
+#endif /*TX_DM2500*/
+#if TX_H19
+		case TN_H19:			
+			trm_flags |= TF_IDLIN|TF_IDCHR|TF_CLEOL;
+			tvc_ci = 8;
+		/*	tvc_cin = 1; */	/* default is ok */
+			tvc_cd = 0;
+			tvc_cdn = 2;
+		/*	tvc_ld = 0; */	/* Default is OK */
+			tvc_ldn = 1 << (trm_ospeed - 7);
+		/*	tvc_li = 0; */	/* Default is OK */
+			tvc_lin = tvc_ldn;
+			break;
+#endif /*TX_H19*/
+#if TX_COHIBM
+		case TN_COHIBM:
+			trm_flags |= TF_IDLIN|TF_IDCHR|TF_CLEOL|TF_METAKEY|TF_DIRVID;
+			/* Always use lowest possible costs */
+		/*	tvc_ci = 0; */	/* Default */
+			tvc_cin = 2;
+		/*	tvc_cd = 0; */	/* Default */
+			tvc_cdn = 2;
+		/*	tvc_ld = 0; */	/* Default */
+			tvc_ldn = 2;
+		/*	tvc_li = 0; */	/* Default */
+			tvc_lin = 2;
+			break;
+#endif /*TX_COHIBM*/
+#if TX_OM8025
+		case TN_OM8025:
+			trm_flags |= TF_IDLIN|TF_IDCHR|TF_CLEOL;
+			tvc_pos = 6;
+		/*	tvc_ci = tvc_cd = 0; */	/* Default */
+			tvc_cin = 4;
+			tvc_cdn = 2;
+		/*	tvc_ld = tvc_li = 0; */	/* Default */
+			tvc_ldn = 10;		/* Crude approx */
+			tvc_lin = 10;
+			if(trm_ospeed > 7)	/* If faster than 300 baud */
+				trm_flags &= ~TF_IDLIN;	/* Turn off LID */
+			break;
+#endif /*TX_OM8025*/
+#if TX_TVI925
+		case TN_TVI925:
+			trm_flags |= TF_IDLIN|TF_IDCHR|TF_CLEOL;
+			tvc_ci = tvc_cd = tvc_cin = tvc_cdn
+				= tvc_ldn = tvc_lin = 2;
+			break;
+#endif /*TX_TVI925*/
+	  }
+	if(tibfmsk < 0)		/* If mask is still default -1, set it. */
+		tibfmsk = ((trm_flags&TF_METAKEY) ? 0377 : 0177);
+}
+
+/* T_FATAL(str) - prints error message and exits.
+*/
+t_fatal(str)
+char *str;
+{	writerr("ELLE: \"");
+	writerr(tv_stype);
+	writerr("\" terminal ");
+	writerr(str);
+	writerr("\n");
+	exit(1);		/* Terminate with prejudice */
+}
+
+
+/* T_ENTER is called after TS_ENTER to set the terminal parameters for
+ *	editing (as opposed to normal typeout).
+ *	Standout mode must initially be off.
+ */
+
+t_enter()
+{	switch(tv_type)
+	  {
+#if TX_TERMCAP
+		case TN_TERMCAP:
+                        putpad(TC_ti);
+			if(tc_km) putpad(TC_mm);	/* Use meta if poss */
+#if FX_SOWIND
+			t_standout(0);		/* Ensure standout mode off */
+#endif
+			break;
+#endif /*TX_TERMCAP*/
+#if TX_DM2500
+		case TN_DM2500:
+			tput(030);	/* Just in case, flush stray modes */
+			break;
+#endif /*TX_DM2500*/
+#if TX_COHIBM
+		case TN_COHIBM:		/* Note TN_H19 will exist too */
+#endif /*TX_COHIBM*/
+#if TX_H19
+		case TN_H19:
+			/* Enter ZDS (Heath) mode, then
+			 * Exit graphics mode (G) Exit ins-char mode (O)
+			 * exit rev video mode (q) exit hold-screen mode (\)
+			 * set cursor on (y5)
+			 */
+			tputz("\033[?2h\033G\033O\033q\033\\\033y5");
+			/* Set Discard-at-EOL (w)
+			 * Set no auto-CR (y9)
+			 * Enable 25th line (x1)
+			 */
+			tputz("\033w\033y9\033x1");
+			break;
+#endif /*TX_H19*/
+	  }
+}
+
+
+/* T_EXIT - Leave editing modes.  This function should restore
+**	the terminal's modes to what they were before ELLE was started.
+**	Standout mode is turned off.
+*/
+
+t_exit()
+{
+	switch(tv_type)
+	  {
+#if TX_TERMCAP
+		case TN_TERMCAP:
+			if(tc_km) putpad(TC_mo);	/* Turn off meta */
+			putpad(TC_te);
+			break;
+#endif /*TX_TERMCAP*/
+#if TX_DM2500
+		case TN_DM2500:
+			tput(035);	/* Turn on roll mode */
+			break;
+#endif /*TX_DM2500*/
+#if TX_COHIBM
+		case TN_COHIBM:		/* If this exists, TN_H19 will too */
+#endif /*TX_COHIBM*/
+#if TX_H19
+		case TN_H19:
+			tputz("\033v");		/* Turn EOL-wrap back on */
+#if DNTTY
+			tputz("\033<");		/* Return to ANSI mode */
+#endif /*DNTTY*/
+			break;
+#endif /*TX_H19*/
+	  }
+}
+
+
+/* T_CLEAR() - Clears the screen and homes the cursor.
+ *	Always valid - ELLE refuses to support terminals without this.
+ */
+
+t_clear ()
+{	switch(tv_type)
+	  {
+#if TX_TERMCAP
+		case TN_TERMCAP:
+			putnpad(TC_cl,scr_ht);
+			break;
+#endif /*TX_TERMCAP*/
+#if TX_DM2500
+		case TN_DM2500:
+			tputz("\036\036");	/* Double Master Clear */
+			break;
+#endif /*TX_DM2500*/
+#if TX_COHIBM
+		case TN_COHIBM:		/* Note TN_H19 will exist too */
+#endif /*TX_COHIBM*/
+#if TX_H19
+		case TN_H19:
+			tputz("\033E");
+		/*	tputn(zpadstr,9);	*/
+			break;
+#endif /*TX_H19*/
+#if TX_OM8025
+		case TN_OM8025:
+			tputz("\033H\033J");	/* Home then CLEOS */
+			tpad(1000);		/* One second!!!! */
+			break;
+#endif /*TX_OM8025*/
+#if TX_TVI925
+		case TN_TVI925:
+			tput(032);	/* ^Z */
+			break;
+#endif /*TX_TVI925*/
+	  }
+	curs_lin = curs_col = 0;
+}
+
+
+/* T_CURPOS(y, x) - Absolute move.  Place cursor in given position
+ *	regardless of where it currently is.
+ *	Updates curs_lin, curs_col.
+ *	Always valid -- ELLE refuses to support terminals without this.
+ */
+
+t_curpos (lin, col)
+register int lin, col;
+{
+	if(col > scr_wid)		/* Easiest to catch here */
+		col = scr_wid;
+
+	/* Do absolute positioning */
+	switch(tv_type)
+	  {
+#if TX_TERMCAP
+		case TN_TERMCAP:
+			putpad(tgoto(TC_cm, col, lin));
+			break;
+#endif /*TX_TERMCAP*/
+#if TX_DM2500
+		case TN_DM2500:
+			tput(014);
+			tput(col^0140);
+			tput(lin^0140);
+			break;
+#endif /*TX_DM2500*/
+#if TX_COHIBM
+		case TN_COHIBM:		/* If this exists, TN_H19 will too */
+#endif /*TX_COHIBM*/
+#if TX_H19
+		case TN_H19:
+			tputz("\033Y");
+			tput(lin+040);
+			tput(col+040);
+			break;
+#endif /*TX_H19*/
+#if TX_OM8025
+		case TN_OM8025:
+			tputz("\033\175");
+			tput(0100+((lin+1)>>4));
+			tput(0100+((lin+1)&017));
+			tput(0100+((col+1)>>4));
+			tput(0100+((col+1)&017));
+			break;
+#endif /*TX_OM8025*/
+#if TX_TVI925
+		case TN_TVI925:
+			tputz("\033=");
+			tput(lin+040);
+			tput(col+040);
+			break;
+#endif /*TX_TVI925*/
+	  }
+	curs_lin = lin;
+	curs_col = col;
+}
+
+/* T_BACKSPACE() - Back up 1 character position.
+ *	Updates curs_col.
+ *	Only valid if tvc_bs has a "reasonable" value ( < 1000)
+ */
+
+t_backspace()
+{
+#if TX_TERMCAP
+	if(BC) tputz(BC);	/* Use alternate BS */
+	else
+#endif
+	tput('\010');		/* Send BS */
+	--curs_col;
+}
+
+/* T_BELL() - Ring terminal's bell (or flash something, or whatever).
+ *	Forces out all output thus far, to ensure immediate attention.
+ *	This used to be an unbuffered feep, but was changed to use normal
+ *	output path in order to avoid messing up terminal escape sequences.
+ */
+t_bell()
+{
+#if TXC_VISBEL && TX_TERMCAP
+	if(TC_vb)
+	        tputz(TC_vb);		/* Do visible bell if possible */
+	else
+#endif
+        tput(BELL);
+        tbufls();       /* Force it out */
+}
+
+
+/* T_CLEOL() - Clear to End Of Line.
+ *	Only valid if trm_flags has TF_CLEOL set.
+ */
+
+t_cleol ()
+{
+	switch(tv_type)
+	  {
+#if TX_TERMCAP
+		case TN_TERMCAP:
+			putpad(TC_ce);
+			break;
+#endif /*TX_TERMCAP*/
+#if TX_DM2500
+		case TN_DM2500:
+			tput(027);
+			break;
+#endif /*TX_DM2500*/
+#if TX_COHIBM
+		case TN_COHIBM:		/* If this exists, TN_H19 will too */
+#endif /*TX_COHIBM*/
+#if TX_H19
+		case TN_H19:
+			tputz("\033K");
+			break;
+#endif /*TX_H19*/
+#if TX_OM8025
+		case TN_OM8025:
+			tputz("\033K");
+			tpad(41);	/* 1/25 sec padding */
+			break;
+#endif /*TX_OM8025*/
+#if TX_TVI925
+		case TN_TVI925:
+			tputz("\033T");
+			break;
+#endif /*TX_TVI925*/
+	  }
+}
+
+
+/* T_INSLIN(n, bot) - Insert lines in window.
+ *	n   - # blank lines to insert.
+ *	bot - # of last line of current window
+ *
+ *		The current line is moved down and N blank lines inserted.
+ *	Lines which are moved past bot are lost.
+ *	May leave cursor in random place.
+ *	Only valid if trm_flags has TF_IDLIN set.
+ */
+
+t_inslin (n, bot)
+int   n;			/* number of lines */
+int   bot;			/* line number of last line in window */
+{	register  i, j;
+	int savc,savl;
+
+	if((i = n) <= 0) return;
+	if(bot < (scr_ht-1))
+	  {	savc = curs_col;
+		savl = curs_lin;
+		t_curpos(bot-i, 0);
+		t_dellin(i, scr_ht);
+		t_curpos(savl, savc);
+	  }
+	switch(tv_type)
+	  {
+#if TX_TERMCAP
+		case TN_TERMCAP:
+			if(TC_AL)
+				putpar(TC_AL, i, i);
+			else if(TC_ia)
+			  {	putpad(TC_im);
+				do { putpad(TC_ia);
+				  } while(--i);
+				putpad(TC_ei);
+			  }
+			else
+				do { putnpad(TC_al, scr_ht - curs_lin);
+				  } while(--i);
+			break;
+#endif /*TX_TERMCAP*/
+#if TX_DM2500
+		case TN_DM2500:
+			tput(020);		/* Enter I/D mode */
+			do {	tput(012);		/* Insert line */
+			  	switch(trm_ospeed)
+				  {	case 13: j = 17; break;	/* 9600 */
+					case 12: j = 8; break;	/* 4800 */
+					case 11: j = 4; break;	/* 2400 */
+					case 9:  j = 2; break;	/* 1200 */
+					default: j = 0; break;
+				  }
+				tpadn(j);
+			  } while(--i);
+			tput(030);			/* Exit I/D mode */
+			break;
+#endif /*TX_DM2500*/
+#if TX_H19
+	/* NOTE: H19 supposedly requires 19 ms for each line during line I/D
+	 * operations.
+	 * In actual practice, at 9600 baud 25 pads are necessary (24 wont work!)
+	 * for both I and D.  Plus esc-E needs 9 pads.
+	 */
+		case TN_H19:
+			do {	tputz("\033L");
+				switch(trm_ospeed)
+				  {	case 13: j = 25; break;
+					case 9:	j = 4; break;
+					case 7: j = 1; break;
+					default: j = 0; break;
+				  }
+				tpadn(j);
+			  } while(--i);
+			break;
+#endif /*TX_H19*/
+#if TX_COHIBM
+		case TN_COHIBM:
+			do {	tputz("\033L");  /* no padding required */
+		  	  } while(--i);
+			break;
+#endif /*TX_COHIBM*/
+#if TX_OM8025
+		case TN_OM8025:
+			do {	tputz("\033L");
+				tpad(100*(scr_ht - curs_lin));	/* .1 per moved line*/
+			  } while(--i);
+			break;
+#endif /*TX_OM8025*/
+#if TX_TVI925
+		case TN_TVI925:
+			do tputz("\033E");
+			while(--i);
+			break;
+#endif /*TX_TVI925*/
+	  }
+}
+
+
+/* T_DELLIN(n, bot) - Delete lines from window.
+ *	n   - # lines to delete.
+ *	bot - # of last line of current window.
+ *		The current line, and N-1 following lines, are deleted.
+ *	Blank lines are inserted past bot.
+ *	Cursor should be left at original position.
+ *	Only valid if trm_flags has TF_IDLIN set.
+ */
+t_dellin (n, bot)
+int   n;			/* number of lines */
+int   bot;			/* line number of last line in window */
+{	register  i, j;
+	int savl, savc;
+
+	if((i = n) <= 0) return;
+	switch(tv_type)
+	  {
+#if TX_TERMCAP
+		case TN_TERMCAP:
+			if(TC_DL)
+				putpar(TC_DL, i, i);
+			else if(TC_id)
+			  {	putpad(TC_dm);
+				do putpad(TC_id);
+				while(--i);
+				putpad(TC_ed);
+			  }
+			else
+				do { putnpad(TC_dl,scr_ht - curs_lin);
+				  } while(--i);
+
+			break;
+#endif /*TX_TERMCAP*/
+#if TX_DM2500
+		case TN_DM2500:
+			tput(020);
+			do {	tput(032);
+			  	if(trm_ospeed >= 13)	/* 9600 */
+					tput(0177);
+			  } while(--i);
+			tput(030);
+			break;
+#endif /*TX_DM2500*/
+#if TX_H19
+		case TN_H19:
+			do {	tputz("\033M");
+				switch(trm_ospeed){
+					case 13: j = 25; break;
+					case 9:	j = 4; break;
+					case 7: j = 1; break;
+					default: j = 0; break;
+					}
+				tpadn(j);
+			  } while(--i);
+			break;
+#endif /*TX_H19*/
+#if TX_COHIBM
+		case TN_COHIBM:
+			do {	tputz("\033M");	  /* no padding required */
+			  } while(--i);
+			break;
+#endif /*TX_COHIBM*/
+#if TX_OM8025
+		case TN_OM8025:
+			do {	tputz("\033M");
+				tpad(100*(scr_ht - curs_lin));
+			  } while(--i);
+			break;
+#endif /*TX_OM8025*/
+#if TX_TVI925
+		case TN_TVI925:
+			do {	tputz("\033R");
+			  } while(--i);
+			break;
+#endif /*TX_TVI925*/
+	  }
+	if(bot < (scr_ht-1))
+	  {	savl = curs_lin;
+		savc = curs_col;
+		t_curpos(bot-n,0);
+		t_inslin(n,scr_ht);
+		t_curpos(savl,savc);
+	  }
+}
+
+
+/* T_INSCHR(n, str) - Insert n chars in current line
+ *	n   - # characters to insert
+ *	str - Pointer to char string.  If 0, insert spaces.
+ *
+ *	Insert N characters from string str at current position.
+ *	The cursor may move but curs_col must be updated.
+ *	Only valid if trm_flags has TF_IDCHR set.
+ */
+t_inschr(n, str)
+int n;
+char *str;
+{	register int i;
+	register char *cp;
+
+	if((i = n) <= 0) return;
+	cp = str;
+	switch(tv_type)
+	  {
+#if TX_TERMCAP
+		case TN_TERMCAP:
+			putpad(TC_im);		/* Go into insert mode */
+			if(TC_IC)
+			  {	putpar(TC_IC, i, 1);
+				if(cp) tputn(cp, i);
+				else do tput(SP); while(--i);
+			  }
+			else do {
+				if(TC_ic) putpad(TC_ic);
+				if(cp) tput(*cp++);
+				else tput(SP);
+				if(TC_ip) putpad(TC_ip);
+			  } while(--i);
+			putpad(TC_ei);		/* Exit insert mode */
+			curs_col += n;
+			break;
+#endif /*TX_TERMCAP*/
+#if TX_COHIBM
+		case TN_COHIBM:		/* If this exists, TN_H19 will too */
+#endif /*TX_COHIBM*/
+#if TX_H19
+		case TN_H19:
+			tputz("\033@");		/* Enter ins char mode */
+			do {	if(cp) tput(*cp++);
+				else tput(SP);
+			  } while(--i);
+			tputz("\033O");		/* Exit ins char mode */
+			curs_col += n;
+			break;
+#endif /*TX_H19*/
+#if TX_DM2500
+		case TN_DM2500:
+			tput(020);		/* Enter I/D mode */
+			if(trm_ospeed == 13)	/* 9600 baud lossage */
+			  {	do {
+					tputz(" \177");	/* SP and DEL */
+				  } while(--i);
+				tput(030);
+				i = n;
+				if(i < 3)	/* If close enough, */
+					tputn("\010\010", i);	/* use BSes */
+				else t_curpos(curs_lin, curs_col);
+			  }
+			else			/* Not 9600, can win */
+			  {	do { tput(034);
+				  } while(--i);
+				tput(030);
+				if(cp == 0) return;
+				i = n;
+			  }
+
+			do {	if(cp) tput(*cp++);
+				else tput(SP);
+			  } while(--i);
+			curs_col += n;
+			break;
+#endif /*TX_DM2500*/
+#if TX_OM8025
+		case TN_OM8025:
+			do {
+				tputz("\033@");
+				if(cp) tput(*cp++);
+				else tput(SP);
+			  } while(--i);
+			curs_col += n;
+			break;
+#endif /*TX_OM8025*/
+#if TX_TVI925
+		case TN_TVI925:
+			do {	tputz("\033Q");
+			  } while(--i);
+			if(cp)
+			  {	tputn(cp, n);
+				curs_col += n;
+			  }
+			break;
+#endif /*TX_TVI925*/
+	  }
+}
+
+
+/* T_DELCHR(n) - Delete N chars in current line.
+ *	Deletes the N characters to the right of the cursor.  Remaining
+ *	chars are shifted left.  The cursor should not move.
+ *	Only valid if trm_flags has TF_IDCHR set.
+ */
+t_delchr(n)		/* Delete N chars at current loc */
+int n;
+{	register int i;
+
+	if((i = n) <= 0) return;
+	switch(tv_type)
+	  {
+#if TX_TERMCAP
+		case TN_TERMCAP:
+			putpad(TC_dm);	/* Enter delete mode */
+			if(TC_DC)
+				putpar(TC_DC, i, 1);
+			else do {	/* Delete char while in del mode */
+				putpad(TC_dc);
+			} while(--i);
+			putpad(TC_ed);	/* Exit delete mode */
+			break;
+#endif /*TX_TERMCAP*/
+#if TX_COHIBM
+		case TN_COHIBM:		/* If this exists, TN_H19 will too */
+#endif /*TX_COHIBM*/
+#if TX_H19
+		case TN_H19:
+			do tputz("\033N");
+			while(--i);
+			break;
+#endif /*TX_H19*/
+#if TX_DM2500
+		case TN_DM2500:
+			tput(020);		/* Enter I/D mode */
+			do if(trm_ospeed == 13)	/* 9600? */
+				tputz("\010\177");	/* BS and DEL */
+			  else tput(010);
+			while(--i);
+			tput(030);		/* Exit I/D mode */
+			break;
+#endif /*TX_DM2500*/
+#if TX_OM8025
+		case TN_OM8025:
+			do tputz("\033P");
+			while (--i);
+			break;
+#endif /*TX_OM8025*/
+#if TX_TVI925
+		case TN_TVI925:
+			do {	tputz("\033W");
+			  } while(--i);
+#endif /*TX_TVI925*/
+	  }
+}
+
+
+#if FX_SOWIND
+
+/* T_STANDOUT(n) - Enter or leave standout mode.
+ *	n   - 0 to return to normal display mode,
+ *	      1 to enter standout display mode.
+ *		This is usually reverse video but may be something else.
+ *
+ *	Only valid if trm_flags has TF_SO set.
+ */
+
+t_standout(on)
+int on;
+{
+	switch(tv_type)
+	  {
+#if TX_TERMCAP
+		case TN_TERMCAP:
+			putpad(on ? TC_so : TC_se);
+			break;
+#endif /*TX_TERMCAP*/
+
+#if TX_COHIBM
+		case TN_COHIBM:		/* Note TN_H19 will exist too */
+#endif /*TX_COHIBM*/
+#if TX_H19
+		case TN_H19:
+			tputz(on ? "\033p" : "\033q");
+			break;
+#endif /*TX_H19*/
+	  }
+}
+#endif /*FX_SOWIND*/
+
+
+
+/* TPADN(n) - Output N pad chars.
+ */
+static void
+tpadn(n)
+int n;
+{	register int i, pad;
+	if((i = n) > 0)
+	  {	pad = tv_padc;
+		do { tput(pad);
+		  } while(--i);
+	  }
+}
+
+/* TPAD(msec) - Output padding for given # of milliseconds.
+ */
+static void
+tpad(n)
+int n;
+{	register int i, i2;
+
+	i = n;
+	while(i > 0)
+	  {	if((i2 = 320) < i)	/* So can use integers */
+			i2 = i;
+		i -= i2;
+		i2 *= 100;
+		while((i2 -= tv_cspeed) > 0)
+			tput(tv_padc);
+	  }
+}
+#if TX_TERMCAP
+/*
+ * Print the string str, interpreting padding.
+ */
+int tput();	/* Our output function */
+static void
+putpad(str)
+char *str;
+{	if(str) tputs(str, 1, tput);	/* Invoke TERMCAP function */
+}
+static void
+putnpad(str,n)
+char *str;
+int n;
+{	if(str) tputs(str, n, tput);
+}
+static void
+putpar(str, par, n)		/* Wish we had tparm() */
+char *str;
+int par,n;
+{	putnpad(tgoto(str, 0, par), n);
+}
+#endif /*TX_TERMCAP*/
+
+
+/*
+ * Read in the stuff from termcap upon startup.
+ */
+
+#if TX_TERMCAP
+static int tstrlen(), tstrlp();
+
+#ifndef TCAPSLEN
+#define TCAPSLEN 1024	/* Default size of buffer for TERMCAP strings */
+#endif /*-TCAPSLEN*/
+
+static int
+getcap(stype)
+char *stype;
+{	register char *t;
+	register int i;
+	int buflen;
+	char *tcbuf, *tcbptr;		/* Pointers into termcap buffer */
+	char tmpstr[4];
+	char tmpbuf[TCAPSLEN];		/* Allocate from stack */
+	char *malloc();
+	char *realloc();
+
+	/* First see if can find the terminal type. */
+	if((tgetent(tmpbuf, stype)) != 1)
+		return(0);
+
+	/* Found it!  Set up a string buffer to save the caps. */
+	if(!(tcbuf = malloc(TCAPSLEN)))	/* Get permanent buffer */
+		t_fatal(" - cannot allocate termcap buffer");
+	tcbptr = tcbuf;
+
+	/* Now gobble all the string caps that ELLE wants to know about. */
+	tmpstr[3] = '\0';
+	i = NTCAPS;
+	do {
+		tmpstr[0] = tcap[i].tcicod1;	/* Make str of the code */
+		tmpstr[1] = tcap[i].tcicod2;
+		tcap[i].tccap = tgetstr(tmpstr, &tcbptr);	/* Get cap */
+	} while(--i);
+	buflen = tcbptr - tcbuf;	/* String buffer done, finalize */
+	if(buflen >= TCAPSLEN)
+		t_fatal("description too big!");
+	realloc(tcbuf, buflen);		/* Free up unused part of buffer */
+					/* (this better not move it!!!) */
+
+	/* Now get the number/flag stuff that ELLE needs. */
+	tc_am = tgetflag("am");		/* auto wrap */
+	if (tgetflag("xn")) tc_am = 0;	/* auto wrap at 81st char, nice! */
+	tc_km = (tgetflag("km")		/* TTY has meta key */
+		|| tgetflag("MT"));	/* Alternate version of "km"?? */
+	scr_ht = tgetnum("li");		/* Set screen height (# lines) */
+	scr_wid = tgetnum("co");	/* Set screen width (# cols) */
+	ts_winsize();
+
+	/* Now initialize the stupid external vars that TERMCAP rtns want. */
+	if(TC_pc) PC = *TC_pc;	/* Pad char */
+	BC = TC_bc;		/* Backspace str (if no BS) */
+	UP = TC_up;		/* Cursor up */
+	ospeed = trm_ospeed;	/* Put output speed here */
+
+
+	/* Basic data extracted, now mull over it and set the remaining
+	 * ELLE variables
+	 */
+#if FX_SOWIND
+	if(tgetnum("sg") <= 0)		/* If no magic cookie problems */
+	  {	if (TC_so && TC_se)	/* And have standout caps, */
+			trm_flags |= TF_SO;	/* Say has standout cap */
+	  }
+#endif
+
+	if (!(TC_cm && TC_cl))
+		t_fatal("lacks cursor addressing or clear screen.");
+	tvc_pos = tstrlen(TC_cm);		/* Find cost of abs move */
+	if(BC)					/* Find cost of backspace */
+		tvc_bs = tstrlen(BC);
+
+	/* Find costs for doing I/D char operations */
+	if ((TC_im||TC_ic) && (TC_dm||TC_dc))
+	  {	trm_flags |= TF_IDCHR;
+		tvc_ci  = tstrlen(TC_im)+tstrlen(TC_ei);
+		tvc_cin = tstrlen(TC_ic)+1+tstrlen(TC_ip);
+		if(TC_IC)			/* If have multi-IC, use it */
+		  {	tvc_ci += tstrlp(TC_IC, 1);
+			tvc_cin = 1;
+		  }
+		tvc_cd  = tstrlen(TC_dm)+tstrlen(TC_ed);
+		tvc_cdn = tstrlen(TC_dc);
+		if(TC_DC)			/* If have multi-DC, use it */
+		  {	tvc_cd += tstrlp(TC_DC, 1);
+			tvc_cdn = 0;
+		  }
+	  }
+
+	/* Find costs for doing I/D line operations */
+	if ((TC_ia || TC_al) && (TC_id || TC_dl))
+	  {	trm_flags |= TF_IDLIN;
+		tvc_li = 0;			/* Usual case */
+		tvc_lin = tstrlen(TC_al);
+		if(TC_AL)			/* If have multi-IL, use it */
+		  {	tvc_li  = tstrlp(TC_AL, 1);
+			tvc_lin = tstrlp(TC_AL, 2) - tvc_lin;
+		  }
+		else if(TC_ia)
+		  {	tvc_li  = tstrlen(TC_im)+tstrlen(TC_ei);
+			tvc_lin = tstrlen(TC_ia);
+		  }
+
+		tvc_ld = 0;			/* Usual case */
+		tvc_ldn = tstrlen(TC_dl);
+		if(TC_DL)			/* If have multi-DL, use it */
+		  {	tvc_ld  = tstrlp(TC_DL, 1);
+			tvc_ldn = tstrlp(TC_DL, 2) - tvc_ld;
+		  }
+		else if(TC_id)
+		  {	tvc_ld = tstrlen(TC_dm)+tstrlen(TC_ed);
+			tvc_ldn = tstrlen(TC_id);
+		  }
+	  }
+
+	if (tc_am)
+	  {	scr_wid--;		/* For now, avoid invoking wrap. */
+#if 0
+		trm_flags |= AUTOWRAP;	/* */
+#endif
+	  }
+	if (TC_ce) trm_flags |= TF_CLEOL;		/* Term has CLEOL? */
+	if (tc_km) trm_flags |= TF_METAKEY;	/* Term has meta key? */
+
+	return(1);
+}
+
+/* Pair of routines which conspire in order to find # chars actually output
+ * by a particular termcap string.
+ */
+static int _tslen;		/* Stored count */
+static void _tslinc(ch) { _tslen++; }
+static int
+tstrlen(str)
+char *str;
+{	_tslen = 0;
+	if(str && str[0])
+		tputs(str, 1, _tslinc);	/* Mult padding by just 1 */
+	return(_tslen);
+}
+
+static int
+tstrlp(str, par)		/* Same but with parameter */
+char *str;
+int par;
+{
+#if 0
+	if(str)
+	  {	char *cp = tgoto(str, 0, par);
+		int i = strlen(cp);
+		while(--i >= 0)
+			printf(" %o", *cp++);
+		printf("\n");
+	  }
+#endif
+	return !str ? 0 : tstrlen(tgoto(str, 0, par));
+}
+#endif /*TX_TERMCAP*/
+
+
+/* Direct-Video terminal output routine
+ *	Currently only COHERENT has this capability.
+ */
+
+#if COHERENT
+#include <sgtty.h>
+
+struct vidctl {
+	int	v_position;		/* Position in video memory */
+	int	v_count;		/* Number of characters to transfer */
+	char	*v_buffer;		/* Character buffer to read/write */
+};
+/*
+ * Attribute masks for TIOVPUTB - attributes occupy odd addresses
+ * in video memory.
+ */
+#define	VNORM	0x07			/* Ordinary Video */
+#define	VINTE	0x08			/* Intense video */
+#define	VBLIN	0x80			/* Blinking video */
+#define	VREVE	0x70			/* Reverse video */
+#define	VUNDE	0x01			/* Underline video (mono board) */
+
+/* T_DIRECT(line, col, string, len) - Do direct-video output of string.
+ *	Puts the string ("len" chars in length) on the screen starting at
+ *	the X,Y character position given by col, line.
+ *	This routine is only called if terminal has the "TF_DIRVID" flag set.
+ */
+t_direct(lin, col, str, len)
+int lin, col;
+register char *str;
+register int len;
+{	register char *cp;
+	char vbuf[MAXLINE*2];
+	struct vidctl v;
+
+	if(len <= 0) return;
+	tbufls();		/* Ensure normal output is forced out */
+	v.v_position = (lin*80 + col)*2;
+	v.v_count = len*2;
+	v.v_buffer = cp = vbuf;
+	do {
+		*cp++ = *str++;
+		*cp++ = VNORM;
+	  } while(--len);
+	ioctl(1, TIOVPUTB, &v);
+}
+#endif /*COHERENT*/
+
+
+/*
+ * Terminal Output buffering routines
+ */
+
+static char tbuf[TOBFSIZ];	/* Output buffer */
+static int tbufcnt = 0;		/* # chars of room left in buffer */
+static char *tbufp = 0;		/* Pointer to deposit in buffer */
+
+tput(ch)
+int ch;
+{	if(--tbufcnt < 0)
+		tbufls();
+	*tbufp++ = ch;
+}
+
+tputz(str)
+char *str;
+{	register int c;
+	register char *cp, *tp;
+	cp = str;
+	tp = tbufp;
+	while(c = *cp++)
+	  {	if(--tbufcnt < 0)
+		  {	tbufp = tp;
+			tbufls();
+			tp = tbufp;
+		  }
+		*tp++ = c;
+	  }
+	tbufp = tp;
+}
+
+tputn(str,cnt)
+char *str;
+int cnt;
+{	register int c;
+	register char *cp, *tp;
+	cp = str;
+	tp = tbufp;
+	if((c = cnt) > 0)
+	do {
+		if(--tbufcnt < 0)
+		  {
+			tbufp = tp;
+			tbufls();
+			tp = tbufp;
+		  }
+		*tp++ = *cp++;
+	  } while(--c);
+	tbufp = tp;
+}
+
+tbufls()
+{	register int cnt;
+
+	if(tbufp
+	  && (cnt = tbufp - tbuf) > 0)		/* # chars written */
+		write(1, tbuf, cnt);		/* Out they go */
+	tbufp = tbuf;
+	tbufcnt = TOBFSIZ-1;	/* Allow for usual expected decrement */
+}
+
+
+/*
+ * Terminal Input buffering routines
+ */
+
+int tibfmsk = -1;		/* Mask AND'ed with input chars (external) */
+static char tibuf[TIBFSIZ];	/* TTY input buffer */
+static char *tibfp;		/* Pointer to read from buffer */
+static int tibfcnt = 0;		/* # chars left to be read from buffer */
+
+tgetc()
+{
+#if SUN
+	register int c;
+	extern int sun_winfd, sun_rdevf;
+
+	if(sun_winfd)
+	  {	if(!sun_rdevf)
+			return(sun_input(1)&tibfmsk);
+		sun_rdevf = 0;		/* Check mouse too, but only once! */
+		c = sun_input(0);
+		if(c != -1) c &= tibfmsk;
+		return(c);
+	  }
+#endif /*SUN*/
+	while(--tibfcnt < 0)
+		tibfcnt = read(0,(tibfp = tibuf),TIBFSIZ);
+	return((*tibfp++)&tibfmsk);
+}
+
+tinwait()
+{	return(tibfcnt > 0 || ts_inp());
+}
Index: /trunk/minix/commands/elle/eevini.c
===================================================================
--- /trunk/minix/commands/elle/eevini.c	(revision 9)
+++ /trunk/minix/commands/elle/eevini.c	(revision 9)
@@ -0,0 +1,100 @@
+/* ELLE - Copyright 1982, 1987 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/* EEVINI - ELLE initialized variables and array storage.
+ *	Initial values are defined here, but the vars must be
+ * declared in ELLE.H as well so that references from all modules will
+ * compile correctly.
+ *	Arrays are also allocated here, so size re-definitions only require
+ * re-compiling this single small module.
+ */
+
+#define EXT		/* Allocate storage for non-initialized vars */
+#include "elle.h"
+
+#ifndef EVFILMOD
+#if V6
+#define EVFILMOD (0600)	/* (int) Default file creation mode on V6 */
+#else
+#define EVFILMOD (0666)	/* (int) Default file creation mode on V7, note */
+#endif /*-V6*/		/*       paranoids can use V7 "umask" in shell. */
+#endif
+#ifndef EVFNO1
+#define EVFNO1 0	/* (char *) "Old" filename prefix */
+#endif
+#ifndef EVFNN1
+#define EVFNN1 0	/* (char *) "New" filename prefix */
+#endif
+#ifndef EVFNO2
+#define EVFNO2 "O"	/* (char *) "Old" filename postfix */
+#endif
+#ifndef EVFNN2
+#define EVFNN2 "N"	/* (char *) "New" filename postfix */
+#endif
+#ifndef EVFCOL
+#define EVFCOL (71)	/* (int) Initial value for Fill Column */
+#endif
+#ifndef EVCCOL
+#define EVCCOL (40)	/* (int) Initial value for Comment Column */
+#endif
+#ifndef EVNWPCT
+#define EVNWPCT 50	/* (int) 50% For random New Window, center cursor. */
+#endif
+#ifndef EVMVPCT
+#define EVMVPCT 67	/* (int) 67% When move off edge, show 67% new stuff */
+#endif
+#ifndef EVMODWSO
+#define EVMODWSO 0	/* (bool) Initial mode window standout mode */
+#endif
+#ifndef EV2MODEWS
+#define EV2MODEWS 1	/* 2-mode-window flag. 0=Never, 1=if SO, 2=always */
+#endif
+#ifndef EVMARKSHOW
+#define EVMARKSHOW 0	/* (char *) String shown for Set Mark */
+#endif
+#ifndef EVHELPFILE	/* (char *) Location of ELLE help file. */
+#define EVHELPFILE "/usr/src/elle/help.dat"
+#endif
+
+char *ev_verstr = "ELLE 4.1b";	/* String: Editor name and version # */
+int ev_filmod = EVFILMOD;	/* Default file creation mode */
+char *ev_fno1 = EVFNO1;		/* "Old" filename prefix */
+char *ev_fnn1 = EVFNN1;		/* "New" filename prefix */
+char *ev_fno2 = EVFNO2;		/* "Old" filename postfix */
+char *ev_fnn2 = EVFNN2;		/* "New" filename postfix */
+
+int ev_fcolumn = EVFCOL;	/* Initial value for Fill Column */
+#if FX_INDCOMM
+int ev_ccolumn = EVCCOL;	/* Initial value for Comment Column */
+#endif
+
+/* New window selection parameters.
+**	Both are expressed as an integer % of window lines (where the whole
+**	window is 100), and apply when a new window is selected.
+** ev_nwpct - when "New Window" is called, % of lines between top and cursor.
+**	Also applies when screen has changed randomly.
+** ev_mvpct - when cursor moves out of window, this is the % of lines
+**	between top and cursor (if moved off top) or between bottom and
+**	cursor (if moved off bottom).
+*/
+int ev_nwpct = EVNWPCT;		/* New Window cursor loc preference (%) */
+int ev_mvpct = EVMVPCT;		/* Moved cursor loc preference (%) */
+
+#if FX_SOWIND
+int ev_modwso = EVMODWSO;	/* Initial mode window standout flag */
+#endif
+#if FX_2MODEWINDS
+int ev_2modws = EV2MODEWS;	/* Initial 2-mode-wind flag */
+#endif
+char *ev_markshow = EVMARKSHOW;	/* String to display when Set Mark done */
+
+char *ev_helpfile = EVHELPFILE;	/* Location of ELLE help file */
+char *ev_profile = EVPROFBINFILE; /* Location of ELLE binary user profile */
+				/* Note ELLE doesn't use EVPROFTEXTFILE. */
+
+/* Array allocations */
+
+struct scr_line *scr[MAXHT];		/* Array of screen line structures */
+SBSTR *kill_ring[KILL_LEN];		/* Kill ring table */
Index: /trunk/minix/commands/elle/elle.h
===================================================================
--- /trunk/minix/commands/elle/elle.h	(revision 9)
+++ /trunk/minix/commands/elle/elle.h	(revision 9)
@@ -0,0 +1,364 @@
+/* ELLE - Copyright 1982, 1984 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/*
+ * ELLE.H	Global ELLE definitions
+ */
+
+#ifndef EXT
+#define EXT extern	/* Default assumes these are referencing decls */
+#endif
+
+/* Make identifiers unique in 1st 6 chars as per ANSI rule for externals */
+#define tvc_cin tvccin
+#define tvc_cdn tvccdn
+#define tvc_lin tvclin
+#define tvc_ldn tvcldn
+#define ev_fno1 evfno1
+#define ev_fno2 evfno2
+#define ev_fnn1 evfnn1
+#define ev_fnn2 evfnn2
+
+#define ask_sall	asksal	/* eebuff.c */
+#define ask_save	asksav
+#define buf_tmod	buftmo
+#define buf_tmat	buftma
+#define e_gobob		egobob	/* eeedit.c */
+#define e_gobol		egobol
+#define e_goeob		egoeob
+#define e_goeol		egoeol
+#define fill_prefix	filpfx	/* eefill.c */
+#define fill_plen	filpln
+#define fill_cur_line	filcln
+#define kill_ptr	kilptr		/* eef3.c */
+#define kill_push	kilpsh
+#define ed_insert	edinst	/* eefed.c */
+#define ed_insn		edinsn
+#define ed_deln		eddeln
+#define ed_delete	eddele
+#define f_fillreg	ffilrg	/* eejust.c */
+#define f_fillpara	ffilpa
+
+#include "eesite.h"	/* Insert site-dependent flags and parameters */
+#include "sb.h"		/* Insert SB package definitions */
+#include "eeprof.h"	/* Insert user profile definition.  This is a
+			 *	separate file so ELLEC can use it too. */
+#include "eefidx.h"	/* Insert desired function defs */
+
+/* ELLE Compile-time parameter defaults */
+
+#ifndef KILL_LEN
+#define KILL_LEN 8	/* Size of kill ring */
+#endif
+#ifndef MAXHT
+#define MAXHT 72	/* Height (# lines) of largest screen we'll suport */
+#endif
+#ifndef MAXLINE
+#define MAXLINE 132	/* Width  (# chars) of largest screen we'll support */
+#endif
+#ifndef FNAMELEN
+#define FNAMELEN 14	/* Sys-dep: Max size of last filename component */
+#endif			/*	Check FNAMSIZ if you change this. */
+#ifndef FNAMSIZ
+#define FNAMSIZ 100	/* Sys-dep: Max size of complete filename */
+#endif			/*	This must be at least as large as FNAMELEN! */
+#ifndef ISRCHLIM
+#define ISRCHLIM 50	/* Max # of chars to allow I-search on */
+#endif
+#ifndef TOBFSIZ
+#define TOBFSIZ 80	/* Size of TTY output buffer */
+#endif
+#ifndef TIBFSIZ
+#define TIBFSIZ 50	/* Size of TTY input buffer */
+#endif
+#ifndef ECHOLINES
+#define ECHOLINES 1	/* # of lines for echo area (below mode line) */
+#endif
+#ifndef MAXARGFILES
+#define MAXARGFILES 2	/* # of filename args OK at startup */
+#endif
+
+/* ELLE initialized variables.
+ *	Initial values are defined in EEVINI.C, but the vars must be
+ * declared here as well so that references from all modules will
+ * compile correctly.
+ */
+
+extern char *ev_verstr;		/* String: Editor name and version # */
+extern int ev_filmod;		/* Default file creation mode */
+extern char *ev_fno1,*ev_fno2;	/* Pre, postfix for "old" filenames */
+extern char *ev_fnn1,*ev_fnn2;	/* Pre, postfix for "new" filenames */
+extern int ev_fcolumn;		/* Fill Column variable */
+#if FX_INDCOMM
+extern int ev_ccolumn;		/* Comment Column variable */
+#endif
+extern int ev_nwpct, ev_mvpct;	/* New window selection percentages */
+#if FX_SOWIND
+extern int ev_modwso;		/* Initial mode window standout flag */
+#endif
+#if FX_2MODEWINDS
+extern int ev_2modws;		/* Initial setting of 2-mode-window flag */
+#endif
+extern char *ev_markshow;	/* String to show when Set Mark done */
+extern char *ev_helpfile;	/* Location of ELLE help file */
+extern char *ev_profile;	/* Filename of ELLE binary user profile */
+extern struct profile def_prof;	/* ELLE default user profile */
+
+/* Global variables */
+
+EXT chroff cur_dot;		/* Current dot */
+EXT chroff mark_dot;		/* Dot for mark */
+EXT int mark_p;			/* flag indicating whether mark exists */
+EXT int this_cmd, last_cmd;	/* Command type */
+EXT int unrchf;			/* Stuffed character back for readcommand */
+EXT int exp;			/* Numeric argument for commands */
+EXT int exp_p;			/* Flag meaning an arg was given */
+EXT int pgoal;			/* Permanent goal column */
+EXT int goal;
+EXT char *srch_str;		/* Last search string specified (0 = none) */
+EXT int srch_len;		/* Length of srch_str string */
+EXT int ask_len;		/* Length of last string returned by "ask" */
+EXT char *homedir;		/* User's home directory */
+EXT int kill_ptr;		/* Index into kill ring */
+extern SBSTR *kill_ring[];	/* Kill ring table (allocated in eevini) */
+
+/* Editor Command types */
+
+#define KILLCMD 1		/* Kill command, for kill merging */
+#define ARGCMD  2		/* Argument-setter, for main loop */
+#define YANKCMD 3		/* Yank command, for yankpop */
+#define LINECMD 4		/* Next or previous line goal hacking */
+#if IMAGEN
+#define INSCMD  5		/* Simple char-insert command, for autowrap */
+#endif /*IMAGEN*/
+
+/* Misc char definitions */
+#define CTRL(ch) (037&ch)
+#define BELL	('\007')	/* Will become \a in ANSI */
+#define BS	('\b')
+#define TAB	('\t')
+#define LF	('\n')
+#define FF	('\f')
+#define CR	('\r')
+#define ESC	('\033')
+#define SP	(' ')
+#define DEL	('\177')
+
+#define CB_META (0200)		/* Meta bit in command char */
+#define CB_EXT  (0400)		/* Extend bit in command char */
+#define METIZER ESC
+#define EXTIZER CTRL('X')
+
+/* Terminal parameters - set at runtime startup */
+
+EXT char *tv_stype;	/* Terminal type string specified by user/system */
+EXT int scr_ht;		/* # lines of main screen area */
+EXT int scr_wid;	/* # columns of screen */
+EXT int scr_wd0;	/* scr_wid - 1 (for 0-origin stuff) */
+EXT int trm_ospeed;	/* Output speed index */
+EXT int tvc_pos;	/* Cost for absolute move (# of output chars) */
+EXT int tvc_bs;		/* Cost for backspace */
+EXT int tvc_ci, tvc_cin;	/* Char ins cost per call, cost per column */
+EXT int tvc_cd, tvc_cdn;	/* Char del   "   "   "     "    "   "     */
+EXT int tvc_li, tvc_lin;	/* Line ins cost per call, cost per line */
+EXT int tvc_ld, tvc_ldn;	/* Line del   "   "   "     "    "   "   */
+
+EXT int trm_flags;	/* Terminal capabilities - bit flags */
+			/* Maybe change to word vars someday (faster) */
+#define TF_IDLIN	01	/* Has I/D line */
+#define TF_IDCHR	02	/* Has I/D char */
+#define TF_SO		04	/* Has usable standout mode */
+#define TF_CLEOL	010	/* Has clear-to-eol */
+#define TF_METAKEY	020	/* Has meta key */
+#define TF_DIRVID	040	/* Has direct-video type interface */
+
+
+/* Redisplay definitions */
+
+EXT int curs_lin;	/* Line # of current cursor (0 origin) */
+EXT int curs_col;	/* Column # of current cursor (0 origin) */
+
+EXT int rd_type;	/* Global var: holds redisplay "hints" */
+#define redp(n) rd_type |= (n)
+
+#define RD_SCREEN 01	/* Clear everything and redisplay */
+#define RD_WINDS 02	/* Check all windows for changes (b/emod) */
+#define RD_MODE 04	/* Mode line has changed, update it. */
+#define RD_WINRES 0400	/* Assume all of window was changed (clear b/emod) */
+#define RD_MOVE	010	/* Cursor has moved */
+#define RD_UPDWIN 020	/* Window fixed, must update modified screen lines */
+/*#define RD_ICHR 0	*//* Hint: Char insert done */
+/*#define RD_DCHR 0	*//* Hint: Char del done */
+#define RD_ILIN 0100	/* Hint: Line insert done */
+#define RD_DLIN 0200	/* Hint: Line del done */
+
+/* #define RD_MOVWIN 02000	*//* Window should be re-positioned */
+#define RD_FIXWIN 02000		/* Window needs fixing (call fix_wind) */
+#define RD_TMOD   04000		/* Text changed in this window, check it. */
+#define RD_WINCLR 010000	/* Clear window with CLEOLs (not yet) */
+#define RD_CHKALL 020000	/* Check all windows for redisplay flags */
+#if IMAGEN
+#define RD_REDO   040000	/* Just re-do the entire window, don't think */
+#endif /*IMAGEN*/
+
+	/* Flags with global effects, only seen in rd_type */
+#define RDS_GLOBALS (RD_SCREEN|RD_MODE|RD_WINDS|RD_CHKALL)
+	/* Flags which are allowed per-window (in w_redp) */
+#define RDS_WINFLGS (~RDS_GLOBALS)
+	/* Flags which force FIX_WIND() to do something */
+#define RDS_DOFIX (RD_WINRES|RD_TMOD|RD_FIXWIN|RD_MOVE)
+
+#define CI_CLINE '!'		/* Char indicator for continued line */
+#define CI_CNTRL '^'		/* Char indicator for control chars */
+#define CI_META  '~'		/* Char indicator for meta-bit (8th) set */
+#define CI_TOP   '|'		/* Char indicator for top-bit (9th) set */
+#define MAXCHAR (8+3)		/* Longest char representation (TAB) + slop */
+
+/* Definitions for screen structures */
+
+struct scr_line {
+	chroff sl_boff;		/* Ptr to start of line's text in buffer */
+	int sl_len;		/* # buffer chars in line (incl NL) */
+	char *sl_line;		/* Ptr to screen image of line */
+	int sl_col;		/* # chars in image == # columns used */
+	char sl_flg;		/* Flags - set if this line modified */
+	char sl_cont;		/* If line being continued on next, this */
+				/* contains 1 plus # extra chars (if any) */
+				/* stored at end of this line which shd be */
+				/* put at beg of next line. */
+	char *sl_nlin;	/* New screen image line if modified flag set */
+	int sl_ncol;
+};
+	/* sl_flg definitions */
+#define SL_MOD 01		/* New line exists, must update to it */
+#define SL_EOL 02		/* Buffer line ends with EOL */
+#define SL_CSO 04		/* Current screen line is in standout mode */
+#define SL_NSO 010		/* New screen line is in standout mode */
+#if IMAGEN
+#define SL_REDO 0100		/* Line should be redone completely */
+#endif /*IMAGEN*/
+
+extern struct scr_line *scr[];	/* Screen line ptrs (allocated in e_vinit) */
+
+
+/* Buffer stuff */
+
+struct buffer 
+{	SBBUF b_sb;			/* MUST be 1st thing! */
+	struct buffer *b_next;		/* ptr to next in chain */
+	char *b_name;			/* text name */
+	char *b_fn;			/* filename */
+	chroff b_dot;			/* point (dot) */
+	int b_flags;			/* misc. bits */
+	struct majmode *b_mode;		/* Mode of buffer */
+#if IMAGEN
+	long b_mtime;			/* Last file modification time */
+#endif /*IMAGEN*/
+};
+	/* b_flags definitions */
+#define B_MODIFIED	01		/* Buffer is modified */
+#define B_EOLCRLF	0200		/* On = CRLF mode, off = LF mode */
+#if IMAGEN
+#define B_PERMANENT 002			/* buffer cannot be killed */
+#define B_CMODE	    004			/* "C" mode (HACK HACK) */
+#define B_BACKEDUP  010			/* Buffer has been backed up once */
+#define B_TEXTMODE  020			/* Text mode (auto-wrap, basically) */
+#define B_QUERYREP  040			/* Query-replace mode (qualifier) */
+#endif /*IMAGEN*/
+
+/* Handy macro to check EOL mode */
+#define eolcrlf(buf) (((struct buffer *)buf)->b_flags&B_EOLCRLF)
+
+/* Buffer pointers */
+
+EXT struct buffer
+		 *buf_head,		/* head of list of all buffers */
+		 *cur_buf,		/* buffer we are editing now */
+		 *last_buf,		/* buffer we were editing before */
+		 *lines_buf;		/* buffer for sep_win */
+
+/* Window stuff */
+
+struct window
+{	struct window *w_next;		/* ptr to next in chain */
+	int w_flags;			/* Window flags */
+	int w_pos;			/* index of top line */
+	int w_ht;			/* number of lines */
+	struct buffer *w_buf;		/* buffer in this window */
+	int w_pct;			/* % of buffer window is at */
+	int w_redp;			/* Redisplay hints */
+	chroff w_topldot;		/* line currently at top of window */
+	chroff w_dot;			/* Saved dot while not cur_win */
+	chroff w_bmod;			/* Lower bound of modified text */
+	chroff w_emod;			/* Upper bound of modified text */
+					/* (offset from end of buffer!) */
+	chroff w_oldz;			/* Buffer len as of last update */
+};
+
+/* Window flags */
+#define W_STANDOUT	01	/* Use terminal's standout mode for window */
+#define W_MODE		02	/* This is a mode window */
+
+/* Window pointers */
+
+EXT struct window
+		*win_head,		/* head of list of all windows */
+		*cur_win,		/* window we are now in */
+		*user_win,		/* current user window */
+		*oth_win,		/* "other" user window */
+		*mode_win,		/* window for mode line */
+		*ask_win,		/* window for ask (echo) area */
+		*sep_win;		/* window for separation dashes */
+
+/* Major Mode stuff.  Each buffer has its own major mode.
+ * Only one major mode may be in effect at any time.
+ */
+struct majmode {
+	char *mjm_name;		/* Simple for now */
+};
+EXT struct majmode *fun_mode;	/* Fundamental mode - the default */
+EXT struct majmode *cur_mode;	/* Current major mode */
+
+/* Minor modes are currently implemented by means of flag variables
+ * which have global effects (regardless of buffer or major mode).
+ * Each variable has the name "x_mode" where x is the name of the minor
+ * mode.  These are declared in the modules containing their support code.
+ * In the future this may be generalized along the lines of major modes.
+ */
+
+
+/* Miscellaneous debug stuff */
+
+EXT int dbgval;		/* Set nonzero to do verify stuff */
+EXT int dbg_isw;	/* Set to enable interrupts if possible */
+#if IMAGEN
+EXT int dbg_redp;	/* Set to debug redisplay algorithms */
+#endif /*IMAGEN*/
+extern int errno;
+
+/* V7 routines for setexit/reset emulation */
+
+#if !(V6)
+#include <setjmp.h>
+EXT jmp_buf env_main;
+#define setexit(a)	setjmp(env_main)
+#define reset(a)	longjmp(env_main,a)
+#endif /*-V6*/
+
+/* Declare functions returning CHROFF values (offsets into a buffer) */
+
+extern chroff e_dot(),e_nldot(),e_pldot(),e_boldot(),e_eoldot(),
+	e_alldot(),ex_boldot(),ex_alldot(),
+	ex_blen(),e_blen(),ex_dot(),e_wdot();
+
+extern SBSTR *e_copyn();
+
+/* Some other commonly needed declarations */
+
+extern char *memalloc(), *ask(), *dottoa(), *strdup();
+#if !(V6)
+extern char *getenv();
+#endif /*-V6*/
+#include "eeproto.h"	/* function prototypes */
Index: /trunk/minix/commands/elle/ellec.c
===================================================================
--- /trunk/minix/commands/elle/ellec.c	(revision 9)
+++ /trunk/minix/commands/elle/ellec.c	(revision 9)
@@ -0,0 +1,1425 @@
+/* ELLEC - Copyright 1983 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.
+ */
+/* ELLEC - ELLE Compiler
+ *    Invoked with no arguments, acts as general ELLE compiler filter;
+ *	reads ASCII profile input, and outputs a binary profile.
+ *    Otherwise:
+ *	-Profile	Compiles user's profile.
+ *		HOME/.ellepro.e -> HOME/.ellepro.bN (N = fmt version #)
+ *		NOTE: on V6, "HOME/" is left out.
+ *	-Pconf		Outputs defprf.c for ELLE (accepts std in) (old -E)
+ *	-Fconf		Outputs eefdef.h for ELLE (accepts std in)
+ *	-FXconf		Outputs eefidx.h for ELLE (accepts std in)
+ *	-CMconf		Outputs config makefile for ELLE ( " )
+ *	-CSconf	arg	Outputs config file using "arg" - for V6 config.v6 file.
+ *	-Pdump		Outputs defprf.e user profile (old -P)
+ *	-Fdump		Outputs deffun.e
+ */
+
+#if 0
+The ASCII profile file associates command chars with functions.
+It is simply a series of lisp-like expressions of the form
+	(keybind <char spec> <fun spec>)
+		
+	e.g. (keybind "C-Y" "Yank Pop")
+
+Command char specification:
+	Allowed prefixes:
+		<ch>	The char itself
+		C-	Controlify (zap bits 140)
+		^<ch>	Ditto
+		M-	Meta (add bit 200) - case ignored
+		X-	Extended (add bit) - case ignored
+	To quote a char or char spec, use quoted-string syntax.
+
+Function name specification:
+	Function names are specified by quoted strings containing the entire
+	long-form ASCII function name.  Matching is done case-independently.
+
+#endif /*COMMENT*/
+
+
+
+#include "eesite.h"		/* Site specific stuff if any */
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+#include "eeprof.h"		/* Profile structure definition */
+
+
+#define EFUNMAX 400	/* Maximum # (+1) of functions that can be defined */
+#define KBTSIZ (128*2)	/* Initial size of key binding tables */
+
+
+/* EFUN Function definition table.
+**	Functions that were copied from the pre-defined table will
+** have a value of NULL in ef_mod.
+*/
+struct fun {
+	int ef_idx;	/* Function index (same as index of entry) */
+	char *ef_name;	/* Function name */
+	char *ef_adr;	/* C routine name in ELLE */
+	char *ef_mod;	/* Source module that C routine lives in */
+};
+struct fun efuntab[EFUNMAX];
+int efxmax = 0;		/* Largest function idx used */
+
+int format_ver = PROF_VER;	/* Current version # of binary profile fmt */
+
+/* Keybind mapping tables.  There are four separate tables:
+**	Simple character.  Always 128 single-byte items, indexed by the simple
+**		command char.  Each item is the corresponding function index.
+**	Meta char.  Variable number of 2-byte items; first is a command char
+**		and second is its function index.
+**	Extended char.  Same format as Meta char.
+**	Menu item (SUN only).  Variable number of single-byte items, each
+**		a function index.
+**
+*/
+char *chrptr;		/* Pointer to simple-char table */
+int chrsiz = 128;	/* Current size of table */
+int chrcnt = 0;		/* # bytes actually used */
+
+char *mtaptr;		/* Pointer to meta-char table */
+int mtasiz = KBTSIZ;	/* Current size (twice the # of items) */
+int mtacnt = 0;		/* # bytes actually used */
+
+char *extptr;		/* Pointer to ext-char table */
+int extsiz = KBTSIZ;	/* Current size (twice the # of items) */
+int extcnt = 0;		/* # bytes actually used */
+
+char *mnuptr;		/* Pointer to menu-item table (SUN only) */
+int mnusiz = KBTSIZ;	/* Current size */
+int mnucnt = 0;		/* # bytes actually used */
+
+
+#define CB_EXT 0400		/* "X-" prefix on command char */
+#define CB_META 0200		/* "M-" prefix on command char */
+
+
+/* Set up the pre-defined data areas.  This includes the
+** predefined function table plus the default profile (keyboard mappings).
+** Note this only contains entries for ef_name and ef_adr.
+*/
+
+struct fun pdfuntab[] = {	/* Pre-Defined Function table */
+#define EFUN(rtn,rtnstr,name) 0, name, rtnstr, 0,
+#define EFUNHOLE 0, 0, 0, 0,
+#include "eefdef.h"
+};
+int npdfuns = sizeof(pdfuntab)/sizeof(struct fun);	/* # of entries */
+
+#include "defprf.c"	/* Insert default profile mapping */
+			/* This defines charmap, metamap, and extmap. */
+
+
+/* Stuff for feeble-minded list processor */
+#define NIL ((struct lnode *)0)
+#define LTRUE (&ltruenode)
+
+#define LT_VAL 0
+#define LT_STR 1
+#define LT_LIST 2
+#define LT_ATOM 3	/* Should use this later instead of LT_STR */
+
+struct lnode {
+	struct lnode *lnxt;
+	int ltyp;
+	union {
+		int lvi;
+		char *lvs;
+		struct lnode *lvl;
+	} lval;
+};
+
+struct lnode ltruenode;		/* Constant TRUE */
+
+_PROTOTYPE(int main , (int argc , char **argv ));
+_PROTOTYPE(int doargs , (int argc , char **argv ));
+_PROTOTYPE(char **findkey , (char *cp , char ***aretp , char **tabp , int tabsiz , int elsize ));
+_PROTOTYPE(int nstrcmp , (char *s1 , char *s2 ));
+_PROTOTYPE(int ustrcmp , (char *s1 , char *s2 ));
+_PROTOTYPE(int strueq , (char *s1 , char *s2 ));
+_PROTOTYPE(int do_opcod , (void));
+_PROTOTYPE(int do_opasc , (void));
+_PROTOTYPE(int outkbind , (int c , int fx ));
+_PROTOTYPE(int do_obprof , (void));
+_PROTOTYPE(int mupcase , (int ch ));
+_PROTOTYPE(int upcase , (int ch ));
+_PROTOTYPE(char *qstr , (char *str ));
+_PROTOTYPE(char *charep , (int c ));
+_PROTOTYPE(int do_ocnf , (char *str ));
+_PROTOTYPE(int do_ofcod , (void));
+_PROTOTYPE(int do_ofasc , (void));
+_PROTOTYPE(int do_ofxcod , (void));
+_PROTOTYPE(int compile_stdin , (void));
+_PROTOTYPE(int lrch , (void));
+_PROTOTYPE(struct lnode *lread , (void));
+_PROTOTYPE(int wspfls , (void));
+_PROTOTYPE(struct lnode *lrstr , (int flg ));
+_PROTOTYPE(int islword , (int c ));
+_PROTOTYPE(struct lnode *eval , (struct lnode *lp ));
+_PROTOTYPE(struct lnode *undefall , (struct lnode *lp ));
+_PROTOTYPE(struct lnode *efun , (struct lnode *lp ));
+_PROTOTYPE(struct lnode *keybind , (struct lnode *lp ));
+_PROTOTYPE(struct lnode *keyallun , (void));
+_PROTOTYPE(struct lnode *menuitem , (struct lnode *lp ));
+_PROTOTYPE(int repchar , (char *str ));
+_PROTOTYPE(struct lnode *getln , (void));
+_PROTOTYPE(int numcvt , (char *str , int *anum ));
+_PROTOTYPE(int listcnt , (struct lnode *lp ));
+_PROTOTYPE(char *funname , (int i ));
+_PROTOTYPE(int findfun , (char *name ));
+_PROTOTYPE(int funcnt , (int *arr ));
+_PROTOTYPE(int scpy , (char *from , char *to , int cnt ));
+_PROTOTYPE(char *stripsp , (char *cp ));
+
+int warn();
+int lerr();
+int fatal();
+
+
+
+/* ELLEC argument stuff */
+char *argfile;
+char *outfile;
+int swfilter;	/* If no args */
+int swprof;	/* -P */
+int swelle;	/* -E */
+
+int uproflg;	/* Do compilation of user's profile */
+int swpcnf;	/* Output defprf.c (C initialization of profile) */
+int swfcnf;	/* Output eefdef.h */
+int swfxcnf;	/* Output eefidx.h */
+int swcmcnf;	/* Output config makefile (makecf.fun) */
+char *swcscnf;	/* Output config specially (for V6) */
+int swallc;	/* Do all of config stuff */
+int swfdmp;	/* Output deffun.e */
+int nfiles;	/* # file specs seen */
+
+main(argc,argv)
+int argc;
+char **argv;
+{	register int i;
+	register char *cp;
+	char temp[300];
+
+	/* Initialize LTRUE
+	** (cannot portably initialize a union at compile time)
+	*/
+	ltruenode.ltyp = LT_VAL;	/* Set type (other fields zero) */
+
+	/* Process switches */
+	if(argc <= 1) swfilter++;	/* If no args, assume filter */
+	else doargs(argc,argv);
+
+	/* Initialize function definitions and key bindings from predefs */
+	chrptr = malloc(chrsiz);
+	mtaptr = malloc(mtasiz);
+	extptr = malloc(extsiz);
+	mnuptr = malloc(mnusiz);
+	if (!chrptr || !mtaptr || !extptr || !mnuptr)
+		fatal("cannot init, no memory");
+
+	scpy(charmap, chrptr, (chrcnt = sizeof(charmap)));
+	scpy(metamap, mtaptr, (mtacnt = sizeof(metamap)));
+	scpy( extmap, extptr, (extcnt = sizeof(extmap)));
+	if(def_prof.menuvec)
+		scpy(def_prof.menuvec, mnuptr, (mnucnt = def_prof.menuvcnt));
+
+	for(i = 0; i < npdfuns; ++i)		/* Initialize function defs */
+		if(pdfuntab[i].ef_name)
+		  {	efuntab[i].ef_idx = i;
+			efuntab[i].ef_name = pdfuntab[i].ef_name;
+			efuntab[i].ef_adr = stripsp(pdfuntab[i].ef_adr);
+			if(efxmax < i) efxmax = i;
+		  }
+
+
+	/* Routines expect input from stdin and output their results
+	 * to stdout.
+	 */
+	if(argfile)
+		if(freopen(argfile,"r",stdin) == NULL)
+			fatal("cannot open input file \"%s\"",argfile);
+	if(outfile)
+		if(freopen(outfile,"w",stdout) == NULL)
+			fatal("cannot open output file \"%s\"",outfile);
+
+
+	/* Check for general compilation */
+	if(swfilter)
+	  {	/* Not really implemented yet */
+		fatal("bad usage, see doc");
+	  }
+
+	/* Do profile hacking of some kind */
+	if(swprof || swelle)
+	  {	if (compile_stdin())	/* Compile input profile */
+		  {	if(swprof)
+				do_opasc();	/* Output ASCII profile (.e) */
+			else if(swelle)
+				do_opcod();	/* Output bin profile (.b1) */
+		  }
+		exit(0);
+	  }
+
+	/* Check for variousness */
+	if(swpcnf)
+	  {	if(compile_stdin())		/* Compile input */
+			do_opcod();	/* Output the C initialization code */
+		exit(0);
+	  }
+	if(swfxcnf)
+	  {	if(compile_stdin())		/* Compile input */
+			do_ofxcod();	/* Output the eefidx.h code */
+		exit(0);
+	  }
+	if(swfcnf)
+	  {	if(compile_stdin())		/* Compile input */
+			do_ofcod();	/* Output the eefdef.h code */
+		exit(0);
+	  }
+	if(swcmcnf || swcscnf)
+	  {	if(compile_stdin())		/* Compile input */
+			do_ocnf(swcscnf);	/* Output the makecf.fun code */
+		exit(0);
+	  }
+	if(swfdmp)
+	  {	if(compile_stdin())		/* Compile input */
+			do_ofasc();	/* Output the deffun.e code */
+		exit(0);
+	  }
+
+
+	/* Hack user's profile */
+	if(!uproflg) exit(0);
+	if(!argfile)
+	  {
+		temp[0] = 0;
+#if !V6
+		if (cp = getenv("HOME"))
+			strcat(temp, cp);
+#if !TOPS20
+		strcat(temp,"/");
+#endif /*-TOPS20*/
+#endif /*-V6*/
+		strcat(temp, EVPROFTEXTFILE);
+		if(freopen(temp,"r",stdin) == NULL)
+			fatal("cannot open profile \"%s\"",temp);
+	  }
+	if(!outfile)
+	  {
+		temp[0] = 0;
+#if !V6
+		if (cp = getenv("HOME"))
+			strcat(temp, cp);
+#if !TOPS20
+		strcat(temp,"/");
+#endif /*-TOPS20*/
+#endif /*-V6*/
+		strcat(temp, EVPROFBINFILE);
+		if(freopen(temp,"wb",stdout) == NULL	/* Try binary 1st */
+		  && freopen(temp,"w",stdout) == NULL)
+			fatal("cannot open output profile \"%s\"",temp);
+
+	  }
+	/* Hack user's profile */
+	if(compile_stdin())		/* Compile input profile */
+		do_obprof();	/* Output the binary */
+
+}
+
+
+#define SW_FLG 0
+#define SW_VAR 1
+#define SW_STR 2
+struct swarg {
+	char *sw_name;
+	long sw_type;
+	int *sw_avar;
+	char **sw_astr;
+} swtab[] = {
+	"P",		SW_FLG, &swprof,	0,	/* Old stuff */
+	"E",		SW_FLG,	&swelle,	0,
+	"Profile",	SW_FLG, &uproflg,	0,
+	"Pconf",	SW_FLG, &swpcnf,	0,
+	"Fconf",	SW_FLG, &swfcnf,	0,
+	"FXconf",	SW_FLG, &swfxcnf,	0,
+	"CMconf",	SW_FLG, &swcmcnf,	0,
+	"CSconf",	SW_STR, 0,		&swcscnf,
+	"Allconf",	SW_FLG, &swallc,	0,
+	"Pdump",	SW_FLG,	&swprof,	0,
+	"Fdump",	SW_FLG, &swfdmp,	0
+};
+
+doargs(argc,argv)
+int argc;
+char **argv;
+{	register int cnt, c;
+	register char **av;
+	register int i;
+	register struct swarg *swp;
+	struct swarg *swp2;
+	int swerrs = 0;
+
+	av = argv;
+	cnt = argc;
+	nfiles = 0;
+
+	while(--cnt > 0)
+	  {	++av;
+		if(*av[0] != '-')	/* If not switch, */
+		  {			/* assume it's an input filename */
+			nfiles++;
+			continue;
+		  }
+		av[0]++;
+
+		/* Try to look up switch in table */
+		swp = (struct swarg *)findkey(av[0], &swp2, swtab,
+			(sizeof(swtab))/(sizeof(struct swarg)),
+			(sizeof(struct swarg))/(sizeof(char *)));
+		if(swp2)
+		  {	fprintf(stderr,"ellec: ambiguous switch: -%s = %s or %s\n",
+				av[0], swp->sw_name, swp2->sw_name);
+			goto swdone;
+		  }
+		if(swp)	switch(swp->sw_type)
+		  {	case SW_FLG:
+				*(swp->sw_avar) = 1;
+				goto swdone;
+			case SW_VAR:
+				*(swp->sw_avar) = 1;
+				if(cnt <= 1) goto swdone;
+				if(isdigit(*av[1]))
+				  {	*(swp->sw_avar) = atoi(av[1]);
+					--cnt;
+					goto swargdone;
+				  }
+				goto swdone;
+				
+			case SW_STR:
+				if(cnt <= 1) goto swdone;
+				*(swp->sw_astr) = av[1];
+				goto swargdone;
+
+			default:
+				fprintf(stderr,"ellec: bad switch type: %s\n",
+					av[0]);
+				swerrs++;
+		  }
+
+	stop:	fprintf(stderr,"ellec: bad switch: %s\n",*av);
+		swerrs++;
+		goto swdone;
+	swargdone:
+		av[0] = 0;
+		av++;
+	swdone:	av[0] = 0;
+	  }
+	if(swerrs) exit(1);		/* Stop if any problems */
+}
+
+char **
+findkey(cp, aretp, tabp, tabsiz, elsize)
+register char *cp;
+char ***aretp;
+register char **tabp;
+int tabsiz, elsize;
+{	register char **mp1, **mp2;
+	register int i, res;
+	
+	*aretp = mp1 = mp2 = 0;
+	for(i = 0; i < tabsiz; ++i, tabp += elsize)
+	  { if(res = ustrcmp(cp,*tabp))
+		  {	if(res > 0) return(tabp);
+			if(!mp1) mp1 = tabp;
+			else mp2 = tabp;
+		  }
+	  }
+	if(mp2)
+		*aretp = mp2;		/* Ambiguous */
+	return(mp1);
+}
+
+/* NSTRCMP - New string compare.
+ *	Returns:
+ *		2 if str2 > str1 (mismatch)
+ *		1 if str2 counted out (str1 > str2)
+ *		0 if full match
+ *		-1 if str1 counted out (str1 < str2)
+ *		-2 if str1 < str2 (mismatch)
+ */
+
+nstrcmp(s1,s2)
+register char *s1, *s2;
+{	register int c, d;
+
+	while(c = *s1++)
+	  {	if(c != *s2)
+		  {	if((d = upcase(c) - upcase(*s2)) != 0)
+				return(*s2==0 ? 1 : (d > 0 ? 2 : -2));
+		  }
+		++s2;
+	  }
+	return(*s2 ? -1 : 0);
+}
+
+/* USTRCMP - uppercase string compare.
+ *	Returns 0 if mismatch,
+ *		1 if full match,
+ *		-1 if str1 runs out first (partial match)
+ */
+ustrcmp(s1,s2)
+register char *s1, *s2;
+{	register int c;
+
+	if ( ! s1 || ! s2 ) return ( 0 );	/* Check for null ptr */
+	while(c = *s1++)
+	  { if(c != *s2)
+		  {	if(((c ^ *s2) != 040)
+			 || (upcase(c) != upcase(*s2)))
+				return(0);
+		  }
+		s2++;
+	  }
+	return(c == *s2 ? 1 : -1);
+}
+
+strueq(s1,s2)
+char *s1;
+char *s2;
+{	return (ustrcmp(s1, s2) > 0 ? 1 : 0);
+}
+
+
+/* Output C initialization code for default profile (defprf.c) */
+
+do_opcod()
+{	register int i, c, f;
+
+	printf("\
+/* This file defines the initial data for ELLE's default user profile.\n\
+** It is automatically generated by ELLEC, and should not be edited.\n\
+*/\n\
+char charmap[] = {\n");
+	for(i=0; i < chrcnt; i++)
+	  {	printf("\t%2d,",(f = chrptr[i]&0377));
+		printf("\t/* (%3o) %3s",i,charep(i));
+		printf("  %s",funname(f));
+		printf(" */\n");
+	  }
+
+	printf("};\n char metamap[] = {\n");
+	for(i = 0; i < mtacnt; i += 2)
+	  {	printf("\t0%-3o,%3d,",(c = mtaptr[i]&0377),(f = mtaptr[i+1]&0377));
+		printf("\t/* %4s",charep(c|CB_META));
+		printf("  %s",funname(f));
+		printf(" */\n");
+	  }
+
+	printf("};\n char extmap[] = {\n");
+	for(i = 0; i < extcnt; i += 2)
+	  {	printf("\t0%-3o,%3d,",(c = extptr[i]&0377),(f = extptr[i+1]&0377));
+		printf("\t/* %4s",charep(c|CB_EXT));
+		printf("  %s",funname(f));
+		printf(" */\n");
+	  }
+	printf("};\n");
+	printf("struct profile def_prof = {\n");
+	printf("  %d, /* Ver */\n", format_ver);
+	printf("  sizeof(charmap),   charmap,\n");
+	printf("  sizeof(metamap)/2, metamap,\n");
+	printf("  sizeof(extmap)/2,  extmap, \n");
+	printf("  0, 0\n");
+	printf("};\n");
+
+}
+
+
+/* Output ASCII version of default profile */
+
+int oerrs;
+
+do_opasc()
+{	register int i, c, f;
+
+	oerrs = 0;
+	printf("; ELLE default ASCII profile\n\n");
+	printf("(keyallunbind)  ; To flush all existing bindings\n\n");
+	for(i=0; i < chrcnt; i++)
+		outkbind(i, chrptr[i]&0377);
+
+	printf("\n; Meta chars\n\n");
+	for(i = 0; i < mtacnt; i += 2)
+		outkbind(CB_META | (mtaptr[i]&0377), mtaptr[i+1]&0377);
+
+	printf("\n ; Extended commands\n\n");
+	for(i = 0; i < extcnt; i += 2)
+		outkbind(CB_EXT | (extptr[i]&0377), extptr[i+1]&0377);
+
+	printf("\n");
+	if(oerrs)
+		fatal("%d errors encountered, check output file.", oerrs);
+}
+
+outkbind(c, fx)
+{
+	if(fx == 0)		/* Allow key to be mapped to nothing. */
+		return;
+	if(fx <= 0 || fx > efxmax)
+		printf(";INTERNAL ERROR: Bad function index %d for key %s\n",
+			fx, charep(c));
+	else if(efuntab[fx].ef_name == NULL)
+		printf(";INTERNAL ERROR: No name for function %d while mapping key %s\n",
+			fx, charep(c));
+	else {
+	  	printf("(keybind %s \"%s\")\n",
+			qstr(charep(c)),efuntab[fx].ef_name);
+		return;
+	  }
+	oerrs++;
+}
+
+
+/* Output binary user profile */
+
+do_obprof()
+{	register unsigned int rp;	/* Relative "pointer" */
+	struct stored_profile st_prof;
+
+	rp = sizeof(st_prof);		/* Initialize */
+
+	/* Fixed by Kochin Chang, July 1995 */
+	/* format version should be the first field in compiled profile */
+	prof_pack(st_prof.version, format_ver);
+
+	prof_pack(st_prof.chrvec, rp);
+	prof_pack(st_prof.chrvcnt, chrcnt);
+	rp += chrcnt;
+
+	prof_pack(st_prof.metavec, rp);
+	prof_pack(st_prof.metavcnt, mtacnt/2);
+	rp += mtacnt;
+
+	prof_pack(st_prof.extvec, rp);
+	prof_pack(st_prof.extvcnt, extcnt/2);
+	rp += extcnt;
+
+	prof_pack(st_prof.menuvec, rp);
+	prof_pack(st_prof.menuvcnt, mnucnt);
+	rp += mnucnt;
+
+	fwrite((char *)&st_prof,sizeof(st_prof),1,stdout);
+	fwrite(chrptr,sizeof(char),chrcnt,stdout);
+	if(mtacnt)  fwrite(mtaptr, sizeof(*mtaptr), mtacnt, stdout);
+	if(extcnt)  fwrite(extptr, sizeof(*extptr), extcnt, stdout);
+	if(mnucnt) fwrite(mnuptr,sizeof(*mnuptr),mnucnt,stdout);
+}
+
+/* Return upper-case version of character */
+mupcase(ch)
+register int ch;
+{	return((ch&(~0177)) | upcase(ch));
+}
+upcase (ch)
+{	register int c;
+	c = ch&0177;
+	return((('a' <= c) && (c <= 'z')) ? (c - ('a'-'A')) : c);
+}
+
+char *
+qstr(str)
+register char *str;
+{	register int c;
+	static char qstrbuf[100];
+	register char *cp;
+	cp = str;
+	while((c = *cp++) && islword(c));
+	if(c == 0) return(str);	/* No quoting needed */
+
+	cp = qstrbuf;
+	*cp++ = '"';
+	while(*cp++ = c = *str++)
+		if(c == '"') *cp++ = c;	/* Double the quotes */
+	cp[-1] = '"';
+	*cp = 0;
+	return(qstrbuf);
+}
+
+char *
+charep(c)
+register int c;
+{	static char chrbuf[10];
+	register char *cp;
+	cp = chrbuf;
+	if(c&CB_EXT)
+	  {	*cp++ = 'X';
+		*cp++ = '-';
+		c &= ~CB_EXT;
+	  }
+	if(c&CB_META)
+	  {	*cp++ = 'M';
+		*cp++ = '-';
+		c &= ~CB_META;
+	  }
+	if(c <= 037)
+	  {	*cp++ = '^';
+		c += 0100;
+	  }
+	if(c == 0177)
+	  {	*cp++ = 'D';
+		*cp++ = 'E';
+		*cp++ = 'L';
+	  }
+	else *cp++ = c;
+	*cp = 0;
+	return(chrbuf);
+}
+
+
+/* Output config Makefile (makecf.fun)
+ *	If argument is 0 (NULL), does Makefile type output.
+ *	Otherwise uses string for special-purpose output.
+ */
+do_ocnf(str)
+char *str;
+{	register struct fun *fnp;
+	register int i, mi;
+	register char *cp;
+	int fmtab[EFUNMAX];
+	int nfmods;
+	char *modtab[EFUNMAX];
+	char *unknown = "unknown-module";
+
+	if(str == NULL)			/* If not V6 version */
+	  {	printf("# Function module definition file, generated by ELLEC\n");
+		printf("FUN_OFILES = ");
+	  }
+
+	nfmods = 0;
+
+	funcnt(fmtab);		/* Count function occs */
+
+	for(i = 1; i <= efxmax; ++i)
+	  {	if(fmtab[i] == 0) continue;
+		fnp = &efuntab[i];
+
+		if(fnp->ef_name == 0)
+			fatal("internal error - no name for function %d", i);
+		
+		/* Got a function, store its module name if not a dup */
+		if ((cp = fnp->ef_mod) == NULL)	/* Substitute if undef */
+			cp = unknown;	
+		for(mi=0; mi < nfmods; ++mi)
+			if(ustrcmp(cp, modtab[mi]) > 0)
+				break;
+		if(mi < nfmods) continue;
+		modtab[nfmods++] = cp;
+	  }
+
+	/* Now have table of all modules used.  Crunch them into output. */
+	for(mi=0; mi < nfmods; ++mi)
+	    if (modtab[mi] != unknown)
+	      {	if(str != NULL)		/* V6 version? */
+			printf("%s %s\n", str, modtab[mi]);
+		else printf("\\\n\t%s.o", modtab[mi]);
+	      }
+	printf("\n");
+}
+
+
+/* Output eefdef.h */
+
+do_ofcod()
+{	register struct fun *fnp;
+	register int i;
+	char temp[40];
+	int fmtab[EFUNMAX];
+
+	printf("/* .H Function Definition file, generated by ELLEC */\n");
+	printf("/*   0 */ EFUNHOLE /* Always undefined */\n");
+
+	funcnt(fmtab);		/* Count function occs */
+
+	for(i = 1; i <= efxmax ; ++i)
+	  {
+		fnp = &efuntab[i];
+		printf("/* %3d */ ", i);
+		if(fmtab[i] == 0 || fnp->ef_name == 0)
+			printf("EFUNHOLE\n");
+		else
+		  {	sprintf(temp, "\"%s\"", fnp->ef_adr);
+			printf("EFUN( %-12s, %-14s, \"%s\")\n", fnp->ef_adr,
+				temp, fnp->ef_name);
+		  }
+	  }
+
+}
+
+
+/* Output ascii version of function def file
+*/
+do_ofasc()
+{	register struct fun *fnp;
+	register int i;
+	register char *fa, *fm;
+
+	printf("; Master Function Definition file\n");
+
+	for(i = 1; i <= efxmax ; ++i)
+	  {
+		fnp = &efuntab[i];
+		if(fnp->ef_idx == 0)	/* No definition for this index? */
+			continue;
+		if(fnp->ef_name == 0)
+		  {	warn("internal error - no name for function %d", i);
+			continue;
+		  }
+
+		if ((fa = fnp->ef_adr) == NULL)
+			fa = "unknown-addr";
+		if ((fm = fnp->ef_mod) == NULL)
+			fm = "unknown-module";
+		printf("(efun %d \"%s\" %s %s)\n",
+			fnp->ef_idx, fnp->ef_name, fa, fm);
+	  }
+}
+
+
+/* Output eefidx.h */
+
+do_ofxcod()
+{	register struct fun *fnp;
+	register int i;
+	register char *cp, *cp2;
+	int fmtab[EFUNMAX];
+	char tmpstr[100];
+
+	printf("\
+/* .H Function Index Definition file, generated by ELLEC */\n");
+	printf("\
+/* FN_ defines Function Numbers (indices) for all known functions */\n");
+	printf("\
+/* FX_ defines Function eXistence in this ELLE configuration */\n");
+
+	funcnt(fmtab);		/* Count function occs */
+
+	for(i = 1; i <= efxmax ; ++i)
+	  {
+		fnp = &efuntab[i];
+		if(fnp->ef_idx == 0)	/* No definition for this index? */
+			continue;
+		if(fnp->ef_adr == 0 || fnp->ef_name == 0)
+		  {	warn("internal error - no addr/name for function %d", i);
+			continue;
+		  }
+
+		cp2 = fnp->ef_adr;
+		cp = tmpstr;
+		while(*cp++ = upcase(*cp2++));
+		cp = tmpstr;
+		if((*cp++ != 'F') || (*cp++ != '_'))
+			cp = tmpstr;
+
+		/* Always define FN_ as index */
+		printf("#define FN_%-14s %3d /* %s */\n",
+				cp, i, fnp->ef_name);
+		/* Define FX_ as 0 if unused, else same as FN_ */
+		printf("#define FX_%-14s %3d\n", cp,
+			(fmtab[i] == 0) ? 0 : i);	/* 0 if unused */
+	  }
+
+}
+
+
+/* Compile input! */
+
+compile_stdin()
+{	register struct lnode *lp;
+
+	while((lp = lread()) != NIL)
+		eval(lp);
+
+	return(1);
+}
+
+
+#define MAXLINE 300
+int llstch = -1;
+int leofflg;
+#define unlrch(c) llstch = c
+
+int lineno = 0;
+char linebuf[MAXLINE];
+char *linecp = linebuf;
+
+lrch()
+{	register int c;
+	if((c = llstch) >= 0)
+	  {	if(c == 0 && leofflg)
+			return(EOF);
+		llstch = -1;
+		return(c);
+	  }
+	if((c = getc(stdin)) == EOF)
+	  {	leofflg = 1;
+		llstch = 0;
+		*linecp = 0;
+		linecp = linebuf;
+		return(c);
+	  }
+	if(c == '\n')
+	  {	lineno++;
+		linecp = linebuf;
+	  }
+	else *linecp++ = c;
+	return(c);
+}
+
+struct lnode *
+lread()
+{	register int c;
+	register struct lnode *lp, *lp2;
+	struct lnode *head;
+
+	wspfls();
+	if((c = lrch())== EOF)
+		return(NIL);
+	if(c == ')')	/* End of a list? */
+		return(NIL);
+	if(c == '(')	/* Start of a list? */
+	  {	head = lp = getln();
+		lp->ltyp = LT_LIST;
+		if((head->lval.lvl = lp = lread()) == NIL)
+			return(head);	/* Return empty list */
+		while(lp2 = lread())
+		  {	lp->lnxt = lp2;
+			lp = lp2;
+		  }
+		return(head);
+	  }
+
+	/* Atom of some kind */
+	if(c=='"')
+	  {	return(lrstr(1));
+	  }
+	unlrch(c);
+	return(lrstr(0));
+}
+
+wspfls()
+{	register int c;
+	for(;;)
+	  {	c = lrch();
+		if(isspace(c)) continue;
+		if(c == ';')
+			while((c = lrch()) != '\n')
+				if(c == EOF) return;		
+		break;
+	  }		
+	if(c != EOF) unlrch(c);
+}
+
+#define LSMAX 300	/* Max # chars in atom string */
+struct lnode *
+lrstr(flg)
+{	char cbuf[LSMAX];
+	register char *cp;
+	register int c, i;
+	struct lnode *lp;
+
+	cp = cbuf;
+	i = 0;
+
+	while((c = lrch()) != EOF)
+	  if (flg) switch(c)
+	  {	case '"':
+			if((c = lrch()) == EOF)
+				return(NIL);
+			if(c != '"')
+			  {	unlrch(c);
+				goto out;
+			  }
+		default:
+		ok:
+			if(++i > LSMAX)
+				break;
+			*cp++ = c;
+			continue;
+	  }
+	else
+	  {	if(islword(c)) goto ok;
+		unlrch(c);
+		break;
+	  }
+  out:
+	lp = getln();
+	lp->ltyp = LT_STR;
+	lp->lval.lvs = malloc(i+1);
+	*cp = 0;
+	strcpy(lp->lval.lvs, cbuf);
+	return(lp);
+}
+islword(c)
+{	return((040 < c && c < 0177
+		&& c != '(' && c !=')' && c != ';'
+		&& c != '"' && c != '\\') ? 1 : 0);
+}
+
+
+
+struct lnode *keybind(), *keyallun(), *menuitem(), *efun(),
+	*undefall();
+
+struct lfun {
+	char *lfname;			/* Name of list function */
+	struct lnode * (*lfrtn)();	/* Function address */
+} lfntab[] = {
+	"keybind",	keybind,
+	"efun",		efun,
+	"menuitem",	menuitem,
+	"keyallunbind",	keyallun,
+/*	"keyunbind",	keyunbind,	*/	/* Not yet */
+	"undefall",	undefall,
+/*	"undef",	undef,		*/	/* Not yet */
+	0, 0
+};
+
+struct lnode *
+eval(lp)
+register struct lnode *lp;
+{	register struct lnode *flp;
+	register struct lfun *lfent;
+
+	if(lp->ltyp != LT_LIST)
+		return(lp);
+	if((flp = lp->lval.lvl) == NIL)
+		return(NIL);
+	if(flp->ltyp != LT_STR)
+		return(NIL);
+
+	/* Look up list function and invoke it */
+	for(lfent = lfntab; lfent->lfname; lfent++)
+		if(strueq(flp->lval.lvs, lfent->lfname))
+			return((*(lfent->lfrtn))(flp->lnxt));
+
+	lerr("unknown op: (%s)", flp->lval.lvs);
+	return(NIL);
+}
+
+
+
+/* UNDEFALL - (undefall)
+**	Undefines all functions.  Typically used to clear out
+** predefined functions prior to compiling a set of new efuns.
+*/
+struct lnode *
+undefall(lp)
+register struct lnode *lp;
+{
+	register int i;
+	efxmax = 0;		/* Say nothing in function def table! */
+	for(i = 0; i < EFUNMAX; ++i)
+	  {	efuntab[i].ef_idx = 0;
+		efuntab[i].ef_name = 0;
+		efuntab[i].ef_adr = 0;
+		efuntab[i].ef_mod = 0;
+	  }
+	return(LTRUE);
+}
+
+
+/* EFUN - (efun <index> <functionname> <address> <module>)
+**	Checks out the args and if no problems, stores the function
+** definition in efuntab.
+*/
+struct lnode *
+efun(lp)
+register struct lnode *lp;
+{	struct lnode *nlp;
+	register int c, i;
+	register struct fun *fnp;
+	char *fname, *faddr, *fmod;
+	int fni, num;
+
+	if(listcnt(lp) < 4)
+	  {	lerr("efun - not enough args");
+		return(NIL);
+	  }
+
+	/* First thing should be function index */
+	switch(lp->ltyp)
+	  {	case LT_VAL:
+			fni = lp->lval.lvi;
+			break;
+		case LT_STR:
+			if(numcvt(lp->lval.lvs, &num))
+			  {	fni = num;
+				break;
+			  }
+		default:
+			lerr("efun - non-value function index");
+			return(NIL);
+	  }
+
+	/* Next thing should be function name */
+	lp = lp->lnxt;
+	if(lp->ltyp != LT_STR)	/* Function name not a string */
+	  {	lerr("efun - non-string function name");
+		return(NIL);
+	  }
+	fname = lp->lval.lvs;
+
+	/* Next thing should be function addr */
+	lp = lp->lnxt;
+	if(lp->ltyp != LT_STR)	/* Function addr not a string */
+	  {	lerr("efun - non-string function addr");
+		return(NIL);
+	  }
+	faddr = lp->lval.lvs;
+
+	/* Next thing should be function module */
+	lp = lp->lnxt;
+	if(lp->ltyp != LT_STR)	/* Function module not a string */
+	  {	lerr("efun - non-string function module");
+		return(NIL);
+	  }
+	fmod = lp->lval.lvs;
+
+	/* Now see if already exists or anything */
+	if(fni <= 0 || fni > EFUNMAX)
+	  {	lerr("efun - bad function index %d", fni);
+		return(NIL);
+	  }
+	fnp = &efuntab[fni];
+	if(fnp->ef_idx != 0)
+	  {
+		if (fnp->ef_idx == fni
+		 && strueq(fnp->ef_name, fname)
+		 && strueq(fnp->ef_adr, faddr)
+		 && (fnp->ef_mod == NULL || strueq(fnp->ef_mod, fmod)))
+			goto win;		/* Benign redefinition */
+
+lerr("efun - redefining function (%d \"%s\" %s %s)",
+		fnp->ef_idx, fnp->ef_name, fnp->ef_adr,
+		(fnp->ef_mod ? fnp->ef_mod : "unknown-module"));
+	  }
+	for(i = 0; i < EFUNMAX; ++i)
+	  {	if(efuntab[i].ef_idx == 0) continue;
+		if(ustrcmp(efuntab[i].ef_adr,faddr) > 0
+		  || ustrcmp(efuntab[i].ef_name, fname) > 0)
+		  {	if(i == fni) continue;
+			lerr("efun - name or address dup!  \"%s\"", fname);
+			return(NIL);
+		  }
+	  }
+
+	/* No problems, store the function def in efuntab! */
+win:	fnp->ef_idx = fni;
+	fnp->ef_mod = fmod;
+	fnp->ef_adr = faddr;
+	fnp->ef_name = fname;
+
+	if(efxmax < fni) efxmax = fni;
+	return(LTRUE);
+}
+
+
+
+/* KEYBIND - (keybind <charspec> <functionname>) */
+
+struct lnode *
+keybind(lp)
+register struct lnode *lp;
+{	struct lnode *nlp;
+	register int c, i;
+	int fni;
+
+	if(lp == NIL || (nlp = lp->lnxt)== NIL)
+		return(NIL);
+	switch(lp->ltyp)
+	  {	case LT_VAL:
+			c = lp->lval.lvi;
+			break;
+		case LT_LIST:
+			return(NIL);
+		case LT_STR:
+			c = repchar(lp->lval.lvs);
+			break;
+	  }
+	if(c == -1)
+		return(NIL);	/* No such command char name */
+
+	lp = nlp;
+	if(lp->ltyp != LT_STR)	/* Function name not a string */
+	  {	lerr("(keybind) non-string function name");
+		return(NIL);
+	  }
+	fni = findfun(lp->lval.lvs);
+	if(fni == 0)		/* No such function name */
+	  {	lerr("(keybind) no such function - \"%s\"", lp->lval.lvs);
+		return(NIL);
+	  }
+	if(c & CB_EXT)
+	  {	c &= ~CB_EXT;
+
+		/* Check for redefinition */
+		for(i = 0; i < extcnt; i += 2)
+			if(c == (extptr[i]&0377))	/* Already there? */
+			  {	if((extptr[i+1]&0377) != fni)	/* Yes, check fn */
+				    lerr("(keybind) redefining X-%s as %d=\"%s\"",
+					charep(c), fni, lp->lval.lvs);
+				break;
+			  }
+		if(i >= extcnt)		/* Didn't find? */
+		  {	if(extcnt >= extsiz)
+			  {	lerr("(keybind) too many X- commands");
+				return(NIL);	/* Too many EXT cmds */
+			  }
+			i = extcnt;	/* Increase size of table */
+			extcnt += 2;
+		  }
+		/* Now store new binding */
+		extptr[i] = c;
+		extptr[i+1] = fni;
+	  }
+	else if(c&CB_META)
+	  {	c &= ~CB_META;
+
+		/* Check for redefinition */
+		for(i = 0; i < mtacnt; i += 2)
+			if(c == (mtaptr[i]&0377))	/* Already there? */
+			  {	if((mtaptr[i+1]&0377) != fni)	/* Yes, check fn */
+				    lerr("(keybind) redefining M-%s as %d=\"%s\"",
+					charep(c), fni, lp->lval.lvs);
+				break;
+			  }
+		if(i >= mtacnt)		/* Didn't find? */
+		  {	if(mtacnt >= mtasiz)
+			  {	lerr("(keybind) too many M- commands");
+				return(NIL);	/* Too many META cmds */
+			  }
+			i = mtacnt;	/* Increase size of table */
+			mtacnt += 2;
+		  }
+		/* Now store new binding */
+		mtaptr[i] = c;
+		mtaptr[i+1] = fni;
+	  }
+	else {
+		i = c & 0177;
+		if (chrptr[i] && (chrptr[i]&0377) != fni)
+		    lerr("(keybind) redefining %s as %d=\"%s\"",
+			charep(c), fni, lp->lval.lvs);
+		chrptr[i] = fni;
+	  }
+	return(LTRUE);
+}
+
+/* KEYALLUNBIND - (keyallunbind) */
+struct lnode *
+keyallun()
+{	register int i;
+	register char *cp;
+
+/*	fprintf(stderr, "ellec: clearing all key definitions\n"); */
+	for(i = 0, cp = chrptr; i < chrcnt; i++)
+		*cp++ = 0;
+	mtacnt = extcnt = mnucnt = 0;
+	return(LTRUE);
+}
+
+
+/* MENUITEM - (menuitem <functionname>) */
+
+struct lnode *
+menuitem(lp)
+register struct lnode *lp;
+{	register int i, fni;
+
+	if(lp == NIL)
+		return(NIL);
+	switch(lp->ltyp)
+	  {	case LT_VAL:
+			fni = lp->lval.lvi;
+			break;
+		case LT_LIST:
+			return(NIL);
+		case LT_STR:
+			fni = findfun(lp->lval.lvs);
+			break;
+	  }
+	if(fni == 0) return(NIL);	/* Bad val or no such function name */
+	for(i = 0; i < mnusiz; i++)
+		if(fni == (mnuptr[i]&0377) || mnuptr[i] == 0)
+		  {	mnuptr[i] = fni;
+			mnucnt++;
+			return(LTRUE);
+		  }
+	return(NIL);		/* Too many menu items */
+}
+
+
+repchar(str)
+register char *str;
+{	register int c;
+	register int i, l;
+
+	if (str == 0) return (-1);
+	i = 0;
+	l = strlen(str);
+	c = (*str++)&0377;
+	if(l == 0) return(-1);
+	if(l == 1) return(c);	/* One-char representation */
+	if(c == '^')
+		if(l == 2) return((~0140) & mupcase(*str));
+		else return(-1);
+	c = mupcase(c);
+	if (*str == '-')
+	  {	if(*++str == 0) return(-1);
+		switch(c)
+		  {	case 'X': return(CB_EXT | mupcase(repchar(str)));
+			case 'M': return(CB_META | mupcase(repchar(str)));
+			case 'C': return((~0140) & repchar(str));
+		  }
+	  }
+	if(c == 'S' && upcase(*str) == 'P' && l == 2)
+		return(' ');
+	if(c == 'D' && upcase(*str++) == 'E' && upcase(*str++) == 'L'
+		&& *str == 0)
+		return(0177);
+	return(-1);		
+}
+
+struct lnode *
+getln()
+{	return((struct lnode *)calloc(1,sizeof(struct lnode)));
+}
+
+numcvt(str, anum)
+char *str;
+int *anum;
+{	register char *cp;
+	register int i, c, sign;
+	if((cp = str) == 0)
+		return 0;
+	i = sign = 0;
+	if(*cp == '-')
+		cp++, sign++;
+	while(c = *cp++)
+		if(!isdigit(c)) return(0);
+		else i = 10*i + (c - '0');
+	*anum = sign ? -i : i;
+	return(1);
+}
+
+
+
+listcnt(lp)
+register struct lnode *lp;
+{	register int i;
+	i = 0;
+	while(lp)
+		++i, lp = lp->lnxt;
+	return(i);
+}
+
+
+/* FUNNAME - Given function index, return function name.
+**	Always wins; returns "unknown" for bad indices.
+*/
+char *
+funname(i)
+register int i;
+{
+	register char *cp = NULL;
+	if(0 < i && i <= efxmax && (cp = efuntab[i].ef_name))
+		return cp;
+	return("unknown function");
+}
+
+findfun(name)
+register char *name;
+{	register int i;
+	if((i = efxmax) > 0)
+	  {	do { if(strueq(name, efuntab[i].ef_name))
+			return(i);
+		  } while(--i);
+		return(0);
+	  }
+	return(0);
+}
+
+
+/* FUNCNT - Scan all key bindings, counting each occurrence of every
+**	function index.
+**	This is used to determine which functions are actually used.
+*/
+funcnt(arr)
+register int *arr;		/* Pointer to array of EFUNMAX ints */
+{
+	register int i;
+
+	for(i = 0; i < EFUNMAX; ++i)	/* Clear the array */
+		arr[i] = 0;
+	
+	for(i = 0; i < chrcnt; ++i)	/* Scan bindings */
+		arr[chrptr[i]&0377]++;
+	for(i = 0; i < mtacnt; i += 2)
+		arr[mtaptr[i+1]&0377]++;
+	for(i = 0; i < extcnt; i += 2)
+		arr[extptr[i+1]&0377]++;
+}
+
+scpy(from,to,cnt)
+register char *from,*to;
+register int cnt;
+{	if(cnt > 0)
+		do { *to++ = *from++; }
+		while(--cnt);
+}
+
+/* STRIPSP - strip spaces from string.  Returns ptr to start. */
+char *
+stripsp(cp)
+register char *cp;
+{
+	register char *ep, *lastp;
+	while(*cp == ' ') ++cp;
+	if (*cp)
+	  {	ep = cp + strlen(cp);	/* Point to null ending the str */
+		while (*--ep == ' ');
+		*++ep = 0;		/* Tie it off */
+	  }
+	return cp;
+}
+
+
+warn(str,a,b,c,d,e,f,g,h,i)
+char *str;
+{
+	fprintf(stderr, "ellec: ");
+	fprintf(stderr, str, a,b,c,d,e,f,g,h,i);
+	fprintf(stderr, "\n");
+}
+
+lerr(str,a,b,c,d,e,f,g,h,i)
+char *str;
+{
+	warn(str, a,b,c,d,e,f,g,h,i);
+	*linecp = 0;			/* Tie off current line buffer */
+	fprintf(stderr, "    Line %d: %s\n", lineno, linebuf);
+}
+
+fatal(str,a,b,c,d,e,f,g,h,i)
+char *str;
+{
+	warn(str, a,b,c,d,e,f,g,h,i);
+	exit(1);
+}
+
Index: /trunk/minix/commands/elle/sb.h
===================================================================
--- /trunk/minix/commands/elle/sb.h	(revision 9)
+++ /trunk/minix/commands/elle/sb.h	(revision 9)
@@ -0,0 +1,284 @@
+/* SB - Copyright 1982 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.  In all cases
+ *	the source code and any modifications thereto must remain
+ *	available to any user.
+ *
+ *	This is part of the SB library package.
+ *	Any software using the SB library must likewise be made
+ *	quasi-public, with freely available sources.
+ */
+
+#ifdef COMMENT
+
+The initials "SB" stand for "String Block" or "String Buffer".
+
+SBBUFFER - A SB buffer containing a sbstring opened for editing.
+SBFILE   - A structure holding file-specific information for all
+		SDBLKs pointing to that file.
+SBSTRING - A SB string; conceptually a single string, but actually
+		a linked list of SDBLKs.  Unless opened by a SBBUFFER,
+		only a few operations are allowed on SBSTRINGs (creating,
+		copying, deleting).
+SDBLK    - One of the linked nodes constituting a sbstring.  Each SDBLK
+		node points to a continuous string either in memory or
+		on disk, or both.
+SBLK	 - Another name for SDBLK.
+SMBLK	 - An allocated chunk of memory.  Also refers to the node structure
+		maintained by the SBM memory management routines, which
+		points to the actual chunk of memory.
+SBM	 - Name of the memory management package.  SBM routines are used
+		to allocate memory in general, and are not just for
+		use by SB routines.
+
+************ MACHINE DEPENDENT DEFINITIONS **********
+
+	The following compile time definitions represent machine
+dependent parameters which are intended mainly for use only by SBM and
+SBSTR routines.  Other programs should use them with caution.  Note
+that a great deal of code assumes that type "int" corresponds to a basic
+machine word (as per C Reference Manual).
+
+	The current definitions will only work for machines which have
+1, 2, 4, or 8 "char" bytes in a machine word.  Any other size will
+require some changes to the definitions and possibly to some places
+using them.
+
+WORD   - integer-type definition corresponding to machine word.
+WDSIZE - # addressable char bytes in a machine word.		(1, 2, 4, 8)
+WDBITS - # low order bits in an address, ie log2(WDSIZE).	(0, 1, 2, 3)
+WDMASK - Mask for low order bits of address			(0, 1, 3, 7)
+CHAR_MASK - If defined, machine does sign-extension on chars, and
+	they must be masked with this value.
+
+	Note that the macro for WDBITS has no mathematical significance
+other than being an expression which happens to evaluate into the right
+constant for the 4 allowed values of WDSIZE, and in fact it is this
+crock which restricts WDSIZE!  If C had a base 2 logarithm expression
+then any power of 2 could be used.
+
+Values for machines
+				WORD	WDSIZE	WDBITS	WDMASK
+	PDP11, Z8000, I8086	int	2	1	01
+	VAX11, M68000, PDP10	int	4	2	03
+
+#endif /* COMMENT */
+
+
+/* First try to define a few things in a semi-portable way
+*/
+#include "eesite.h"
+#ifdef __STDC__		/* Implementation supports ANSI stuff? */
+#include <limits.h>		/* Get sizes for char stuff */
+#define _SBMUCHAR 1		/* Can use "unsigned char" */
+#define _SBMCHARSIGN (CHAR_MIN < 0)	/* True if "char" is sign-extended */
+#define CHAR_MASK (UCHAR_MAX)
+
+#else	/* not ANSI */
+#ifndef _SBMUCHAR		/* Default assumes no "unsigned char" */
+#define _SBMUCHAR 0
+#endif
+#ifndef _SBMCHARSIGN		/* Default assumes "char" is sign-extended */
+#define _SBMCHARSIGN 1
+#endif
+#ifndef CHAR_MASK		/* Default assumes "char" is 8 bits */
+#define CHAR_MASK 0377
+#endif
+#endif	/* not ANSI */
+
+/* Define "sb_uchartoint" as a macro which ensures that an unsigned
+** character value is converted properly to an int value.
+*/
+#if (_SBMUCHAR || (_SBMCHARSIGN==0))
+#define sb_uchartoint(a) (a)		/* No fear of sign extension */
+#else
+#define sb_uchartoint(a) ((a)&CHAR_MASK)	/* Bah, sign extension */
+#endif
+
+
+/* Defs for machines with a base-2 WDSIZE.  Yes, the (int) is indeed necessary
+ * (to allow implicit conversion to long where needed - the PDP11 compiler
+ * is known to lose without it, because sizeof is cast as "unsigned int"
+ * which loses big in long masks!)
+ */
+#define WORD int
+#define WDSIZE ((int)(sizeof(WORD)))
+#define WDMASK (WDSIZE-1)
+#define WDBITS ((WDSIZE>>2)+(1&WDMASK))
+
+#define rnddiv(a) ((a)>>WDBITS)		/* # words, rounded down */
+#define rndrem(a) ((a)&WDMASK)		/* # bytes remaining past wd bndary */
+#define rnddwn(a) ((a)&~WDMASK)		/* Round down to word boundary */
+#define rndup(a)  rnddwn((a)+WDSIZE-1)	/* Round up to word boundary */
+
+#ifdef COMMENT	/* The following are for machines without a base-2 WDSIZE */
+#define rnddiv(a) ((a)/WDSIZE)
+#define rndrem(a) ((a)%WDSIZE)
+#define rnddwn(a) ((a)-rndrem(a))
+#define rndup(a)  rnddwn((a)+WDSIZE-1)
+#undef WDMASK			/* These become meaningless and anything */
+#undef WDBITS			/* which uses them should be changed! */
+#endif /* COMMENT */
+
+/* The following 3 definitions are somewhat machine-dependent,
+ * but are specifically intended for general use and work for all
+ * currently known C implementations.
+ *	SBMO must be an integer-type object large enough to hold
+ *	the largest difference in SBMA pointers, and must not be
+ *	used in signed comparisons.
+ */
+
+typedef long chroff;		/* CHROFF - Char offset in disk/sbstr */
+typedef unsigned int SBMO;	/* SBMO - Char offset in memory */
+typedef
+#if _SBMUCHAR
+	unsigned
+#endif
+		char *SBMA;	/* SBMA - Pointer to char loc in memory */
+
+
+
+/* The following definitions tend to be system-dependent.  Only the
+ * SBM and SBSTR routines use them.
+ */
+#define SB_NFILES 32		/* # of open files we can hack.  Actually
+				 * this is max FD value plus 1. */
+#define SB_BUFSIZ 512		/* Optimal buffer size (system block size) */
+#define SB_SLOP (16*WDSIZE)	/* # slop chars to tolerate for allocations */
+
+#define SMNODES (20)		/* # SM or SD nodes to create when needed */
+#define SMCHUNKSIZ (16*512)	/* # bytes of mem to create (via sbrk) " " */
+#define MAXSBMO ((SBMO)-1)	/* Used in SBM only */
+		/* MAXSBMO should be the largest possible SBMO value. */
+
+
+#define EOF (-1)
+#define SBFILE struct sbfile
+#define SBBUF struct sbbuffer
+#define SBSTR struct sdblk	/* Start of a sbstring */
+
+struct sbfile {
+	int sfflags;		/* Various flags */
+	int sffd;		/* FD for file (-1 if none) */
+	struct sdblk *sfptr1;	/* Ptr to 1st node in phys list */
+	chroff sflen;		/* Original length of file FD is for */
+};
+
+	/* Definition of SBBUF string/buffer */
+struct sbbuffer {
+	SBMA sbiop;		/* I/O pointer into in-core text */
+	int sbrleft;		/* # chars left for reading */
+	int sbwleft;		/* # chars left for writing */
+	int sbflags;		/* Various flags */
+	chroff sbdot;		/* Logical pos for start of current sdblk */
+	chroff sboff;		/* Offset into current sdblk (if no smblk)*/
+	struct sdblk *sbcur;	/* Pointer to current SD block of string */
+};
+	/* Flags for "sbflags" */
+#define SB_OVW	01	/* Over-write mode */
+#define SB_WRIT 02	/* Written; smuse needs to be updated from sbiop */
+
+	/* NOTE: An unused sbbuf structure should be completely zeroed.
+	 *	This will cause routines to handle it properly
+	 *	if they are accidentally pointed at it.
+	 */
+
+	/* Definition of SDBLK */
+struct sdblk {
+	struct sdblk *slforw;	/* Logical sequence forward link */
+	struct sdblk *slback;	/* Logical sequence backward link */
+	int sdflags;
+	struct sdblk *sdforw;	/* Physical sequence (disk) */
+	struct sdblk *sdback;	/* ditto - backptr for easy flushing */
+	struct smblk *sdmem;	/* Mem pointer, 0 if no in-core version */
+	SBFILE *sdfile;		/* File pointer, 0 if no disk version */
+	chroff sdlen;		/* # chars in disk text */
+	chroff sdaddr;		/* Disk address of text */
+};
+	/* Flags for "sdflags" */
+#define SD_LOCK 0100000		/* Locked because opened by a SBBUF */
+#define SD_LCK2	0040000		/* Locked for other reasons */
+#define SD_MOD	0020000		/* Modified, mem blk is real stuff */
+#define SD_NID	   0323		/* Node ID marks active (not on freelist) */
+#define SD_LOCKS (SD_LOCK|SD_LCK2)
+
+/* Note sdback is ONLY needed for fixing up phys list when a sdblk is
+ * deleted (so as to find previous blk in phys list).  Perhaps it shd
+ * be flushed (ie only use SDFORW)?  How to do deletions - use circular
+ * list?  Sigh.
+ */
+
+	/* Definition of SMBLK (used by SBM routines) */
+struct smblk {
+	struct smblk *smforw;	/* Links to other mem blks, in phys order */
+	struct smblk *smback;
+	int smflags;		/* Type, in-use flags */
+	SBMA smaddr;		/* Mem address of text */
+	SBMO smlen;		/* # bytes in mem block */
+	SBMO smuse;		/* # bytes "used" in block */
+};
+	/* Flags for "smflags" */
+#define SM_USE	0100000		/* Block is in use (mem free if off) */
+#define SM_NXM	 040000		/* Block mem is non-existent */
+#define SM_EXT	 020000		/* Block mem owned by external (non-SBM) rtn*/
+#define SM_MNODS 010000		/* Block holds SMBLK nodes */
+#define SM_DNODS  04000		/* Block holds SDBLK nodes */
+#define SM_NID	   0315		/* Node in-use identifier (low byte) */
+
+/* Error handler type values */
+#define SBMERR 0	/* Error in SBM package */
+#define SBXERR 1	/* Error in SBSTR package */
+#define SBFERR 2	/* "Error" - SBSTR package found a file overwritten.
+			 *	Non-zero return will continue normally. */
+
+
+/* Redefine certain external symbols to be unique in the first 6 chars
+** to conform with ANSI requirements.
+*/
+#define sbm_nfre sbmnfre	/* SBM stuff */
+#define sbm_nfor sbmnfor
+#define sbm_nmov sbmnmov
+#define sbm_ngc  sbmngc
+#define sbx_ndget sbxndg	/* SBSTR stuff */
+#define sbx_ndel  sbxnde
+#define sbx_ndfre sbxndf
+#define sbx_sdcpy sbxsdc
+#define sbx_sdgc  sbxsdg
+#define sbe_sdlist sbesls	/* SBERR stuff */
+#define sbe_sdtab  sbestb
+#define sbe_sds    sbesds
+#define sbe_sbvfy  sbesbv
+#define sbe_sbs    sbesbs
+
+/* Forward declarations */
+extern SBMA sbm_lowaddr;	/* For roundoff purposes */
+
+extern SBFILE sbv_tf;		/* SBFILE for temp swapout file */
+extern int (*sbv_debug)();	/* Error handler address */
+extern off_t lseek();		/* For sbstr code mostly */
+extern char *mktemp();
+extern char *malloc();
+extern char *calloc();
+extern SBBUF *sb_open();
+extern SBSTR *sb_close(), *sb_fduse(), *sbs_cpy(), *sbs_app(), *sb_cpyn(),
+	*sb_killn();
+extern struct sdblk *sbx_ready();
+extern chroff sb_tell(), sb_ztell(), sbs_len();
+
+
+/* Definition of SB_GETC, SB_PUTC, SB_BACKC macros */
+
+#define sb_putc(s,c) (--((s)->sbwleft) >= 0 ? \
+				(*(s)->sbiop++ = c) : sb_sputc(s,c))
+#define sb_getc(s)   (--((s)->sbrleft) >= 0 ? \
+				sb_uchartoint(*(s)->sbiop++) : sb_sgetc(s))
+#define sb_peekc(s)  ((s)->sbrleft > 0 ? \
+				sb_uchartoint(*(s)->sbiop)   : sb_speekc(s))
+
+/* WARNING - sb_backc must ONLY be used if last operation was a
+ * successful sb_getc!!  For slow but sure invocation use sb_rgetc.
+ */
+#define sb_backc(s) (++(s->sbrleft), --(s->sbiop))
+
+#include "sbproto.h"	/* function prototypes */
Index: /trunk/minix/commands/elle/sbbcpy.c
===================================================================
--- /trunk/minix/commands/elle/sbbcpy.c	(revision 9)
+++ /trunk/minix/commands/elle/sbbcpy.c	(revision 9)
@@ -0,0 +1,54 @@
+
+#include "sb.h"
+
+/* BCOPY(from,to,cnt) - Copy string of bytes.
+ *	Normally this routine is an assembly-language library routine,
+ *	but not all systems have it.  Hence this C-language version
+ *	which tries to be fairly machine-independent.
+ *	Attempts to be clever about using word moves instead of byte moves.
+ *	Does not hack overlapping backward moves.
+ */
+bcopy(from, to, cnt)	/* Copy count bytes from -> to */
+register SBMA from;
+register SBMA to;
+register unsigned cnt;
+{
+	if(!cnt)
+		return;
+	while(rndrem((int)from))	/* Get source aligned */
+	  {     *to++ = *from++;
+		if(--cnt == 0) return;
+	  }
+	if(rndrem((int)to) == 0)	/* Do word move if dest now aligned */
+	  {	register unsigned tmp;
+		tmp = cnt;
+		if((cnt = rnddiv(cnt)) > 4)
+		  {	sbm_wcpy((int *)from, (int *)to, cnt);
+			if((cnt = rndrem(tmp)) == 0)
+				return;	/* No leftover bytes, all done */
+			tmp -= cnt;	/* Ugh, must update pointers */
+			from += tmp;
+			to += tmp;
+		  }
+		else cnt = tmp;		/* Not worth call overhead */
+	  }                             
+	do { *to++ = *from++; }		/* Finish up with byte loop */
+	while(--cnt);
+}
+
+/* SBM_WCPY - word-move auxiliary routine.
+ *	This is a separate routine so that machines with only a few
+ *	registers have a chance to use them for the word copy loop.
+ *	This cannot be made part of BCOPY without doing some
+ *	unnecessary pointer conversions and using extra variables
+ *	(since most compilers will not accept type casts on lvalues,
+ *	which are needed to treat (char *) as (int *)).
+ */
+sbm_wcpy(from, to, cnt)
+register int *from, *to;
+register unsigned cnt;
+{
+	if(cnt)
+		do { *to++ = *from++; }
+		while(--cnt);
+}
Index: /trunk/minix/commands/elle/sberr.c
===================================================================
--- /trunk/minix/commands/elle/sberr.c	(revision 9)
+++ /trunk/minix/commands/elle/sberr.c	(revision 9)
@@ -0,0 +1,686 @@
+/* SB - Copyright 1982 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.  In all cases
+ *	the source code and any modifications thereto must remain
+ *	available to any user.
+ *
+ *	This is part of the SB library package.
+ *	Any software using the SB library must likewise be made
+ *	quasi-public, with freely available sources.
+ */
+
+#define PRINT		/* Include printout stuff */
+
+#include "sb.h"
+#include <stdio.h>
+
+extern struct smblk *sbm_nfl;
+extern struct smblk *sbm_list;
+extern struct sdblk *sbx_nfl;
+
+#ifdef PRINT
+#define PRF(stmt) {if(p) stmt;}
+#define PRFBUG(str,stmt) {if(p) stmt;else return(str);}
+#define PRFBAD(str,stmt) {if(p) stmt; return(str);}
+#else
+#define PRF(stmt) ;
+#define PRFBUG(str,stmt) return(str);
+#define PRFBAD(str,stmt) return(str);
+#endif
+
+#ifndef NPTRS
+#define NPTRS (1000)		/* Catch loops of period less than this. */
+#endif
+
+int sbe_dec = 0;		/* Set nonzero to use decimal printout */
+
+struct ptab {
+	int pt_pflag;		/* Printflag value */
+	char *pt_err;		/* Error string return */
+	int pt_xerr;		/* Error index return */
+	int pt_hidx;		/* Highest freelist entry */
+	int pt_nsto;		/* # entries stored in table */
+	int pt_cnt;		/* # of entry store attempts */
+	struct smblk *pt_tab[NPTRS];
+};
+
+_PROTOTYPE( char *sbe_sdtab, (struct ptab *pt, int p, int phys) );
+_PROTOTYPE( char *sbe_schk, (struct sdblk *sd, struct ptab *pt) );
+_PROTOTYPE( int sbe_tbent, (struct ptab *pt, struct smblk *sm) );
+
+#define PTF_PRF	01	/* Do printout stuff */
+#define PTF_OVFERR 02	/* Complain if table overflows */
+#define PTF_SDPHYS 04	/* Follow SD phys links (else logical links) */
+
+struct flgt {
+	int flg_bit;
+	int flg_chr;
+};
+
+_PROTOTYPE( char *sbe_fstr, (int flags, struct flgt *fp) );
+
+char *sbe_mvfy(), *sbe_mfl(), *sbe_mlst();		/* SBM */
+char *sbe_sbvfy(), *sbe_sbs();				/* SBBUF */
+char *sbe_svfy(), *sbe_sdlist(), *sbe_sdtab(), *sbe_schk();	/* SD */
+char *sbe_fstr();				/* Misc utility */
+
+
+
+/* SBE_MEM() - Print out memory usage list
+*/
+sbe_mem()
+{
+	printf("\nMemory Usage:\n");
+	printf("\tsbm_nfl : %6o\n",sbm_nfl);
+	printf("\tsbm_list: %6o\n",sbm_list);
+	printf("\tsmblk nodes are %o bytes long.\n",sizeof (struct smblk));
+
+	sbe_mlst(1);		/* Scan mem list, printing stuff. */
+}
+
+/* SBE_MVFY() - Verify memory allocation structures
+ *	Returns error message (0 if no errors found).
+ */
+char *
+sbe_mvfy()
+{	register char *res;
+
+	if((res = sbe_mfl(0))
+	  || (res = sbe_mlst(0)))
+		return(res);
+	return(0);
+}
+
+
+/* SBM Debugging Routines */
+
+struct flgt smflgtab[] = {
+	SM_USE,	'U',
+	SM_NXM, 'N',
+	SM_EXT, 'E',
+	SM_MNODS,'M',
+	SM_DNODS,'D',
+	0,0
+};
+
+static char smfhelp[] = "U-Used, N-NXM, E-External, M-SMnodes, D-SDnodes";
+static char smhdline[] = "\
+      SM: back   smaddr   smlen  smuse  smflags";
+
+/* SBE_MFL(printflag) - Verify/Print memory freelist
+ *	Returns error message (0 if no errors found).
+ */
+char *
+sbe_mfl(p)
+int p;
+{	register struct smblk *sm;
+	register int i;
+	struct ptab smtab;		/* For loop detection */
+
+	PRF(printf("Tracing SM node freelist --\n"))
+	PRF(printf("    Maximum loop detection size is %d.", NPTRS))
+	if((sm = sbm_nfl) == 0)
+	  {	PRF(printf("\n\tNo list.\n"))
+		return(0);			/* Null freelist is ok */
+	  }
+	smtab.pt_pflag = p ? PTF_PRF : 0;
+	smtab.pt_nsto = smtab.pt_cnt = 0;
+	i = 0;				/* Print 8 addrs/line */
+	for(; sm; sm = sm->smforw)
+	  {
+		PRF(printf("%s%7o->", (i==0 ? "\n    " : ""), sm))
+		if(++i >= 8) i = 0;
+		if(sbe_tbent(&smtab, sm) < 0)	/* If hit loop, stop */
+			PRFBAD("SM freelist loop",
+			  printf("\nLOOP - %o seen as node %d!!\n",
+				sm, smtab.pt_xerr))
+		if(sm->smflags)
+		  {	PRF((i = 0, printf("\nFreelist node has flags:\n")))
+			PRFBUG("Free SM flagged", sbe_smp(sm, 0))
+		  }
+	  }
+	PRF(printf("\nEnd - %d nodes on SM freelist.\n", smtab.pt_cnt))
+	return(0);
+}
+
+/* SBE_MLST(printflag) - Verify/Print allocated memory list.
+ *	Returns error message (0 if no errors found).
+ */
+char *
+sbe_mlst(p)
+int p;
+{	register struct smblk *sm, *smf, *smb;
+	char *nextaddr;
+	int i;
+	struct ptab smtab;		/* For loop detection */
+
+	PRF(printf("Tracing mem list -- \n"))
+	if((sm = sbm_list) == 0)
+	  {	PRF(printf("\tNo list?!\n"))
+		if(sbm_nfl)		/* Ensure rest are 0 too */
+			return("No mem list?!!");
+		return(0);
+	  }
+
+	smtab.pt_pflag = p;
+	smtab.pt_cnt = smtab.pt_nsto = 0;
+	smb = 0;
+	PRF(printf("   Flags: %s\n%s\n", smfhelp, smhdline))
+	for(; sm; sm = smf)
+	  {	PRF(printf("  %6o: ",sm))
+		if(sbe_tbent(&smtab, sm) < 0)
+			PRFBAD("Loop in mem list!!",
+			  printf("LOOP - seen as node %d!!\n", smtab.pt_xerr))
+
+		if(sm->smback == smb)
+			PRF(printf("^ "))	/* Back ptr OK */
+
+		else PRFBUG("Bad back ptr!",
+			printf("%6o BAD Backptr!!\n\t    ",sm->smback))
+
+		if((sm->smflags&0377)!= SM_NID)
+			PRFBUG("SM: bad node ID",
+				printf("BAD - no node ID!\n\t    "))
+		PRF(printf((sm->smflags&SM_USE) ? "     " : "FREE "))
+		if(sm->smlen == 0)
+			PRFBUG("SM: len 0",
+				printf("Zero-length area!"))
+		if((sm->smflags&SM_USE)==0
+		  && rndrem(sm->smaddr - sbm_lowaddr))
+			PRFBUG("Bad free-mem block",
+				printf("Bad free-mem block"))
+		PRF(sbe_smp(sm, 1))		/* Print out rest of info */
+
+		if(nextaddr != sm->smaddr
+		  && smtab.pt_cnt != 1)		/* 1st time needs init */
+		  {	PRFBUG("Alignment error!",
+				printf("\t  BAD!! %6o expected; ",nextaddr))
+#if !(MINIX)
+			PRF((i = sm->smaddr - nextaddr) > 0
+				? printf("%d skipped.\n",i)
+				: printf("%d overlapped.\n",-i))
+#endif
+		  }
+		nextaddr = sm->smaddr + sm->smlen;
+		smf = sm->smforw;
+		smb = sm;			/* Save ptr to back */
+	  }
+	PRF(printf("End = %6o\n",nextaddr))
+	return(0);
+}
+
+#ifdef PRINT
+sbe_smp(sm,type)
+register struct smblk *sm;
+int type;
+{
+	if(type==0)
+		printf("  %6o:  %s  ", sm,
+			((sm->smflags&SM_USE) ? "    " : "FREE"));
+	printf("%6o: ", sm->smaddr);
+	printf((sbe_dec ? "%5d. %5d." : "%6o %6o"), sm->smlen, sm->smuse);
+	printf("  %7o = %s\n", sm->smflags, sbe_fstr(sm->smflags, smflgtab));
+}
+#endif /*PRINT*/
+
+
+/* SD (SBSTR) debugging routines */
+
+struct flgt sdflgtab[] = {
+	SD_LOCK, 'L',
+	SD_LCK2, 'T',
+	SD_MOD,	 '*',
+	0,0
+};
+
+static char sdfhelp[] = "\
+<f> flags: *-MOD (disk outofdate), L-LOCK, T-LCK2 (temp)";
+static char sdhdline[] = "\
+<f>      SD: slforw slback sdflgs sdforw sdback  sdmem sdfile  sdaddr sdlen";
+
+
+/* SBE_SFL(printflag) - Verify/Print SD freelist
+ *	Returns error message (0 if no errors found).
+ */
+char *
+sbe_sfl(p)
+int p;
+{	register struct sdblk *sd;
+	register int i;
+	struct ptab sdtab;		/* For loop detection */
+
+	PRF(printf("Tracing SDBLK node freelist --\n"))
+	PRF(printf("    Maximum loop detection size is %d.", NPTRS))
+	if((sd = sbx_nfl) == 0)
+	  {	PRF(printf("\n\tNo list.\n"))
+		return(0);			/* Null freelist is ok */
+	  }
+	sdtab.pt_pflag = p ? PTF_PRF : 0;
+	sdtab.pt_nsto = sdtab.pt_cnt = 0;
+	i = 0;				/* Print 8 addrs/line */
+	for(; sd; sd = sd->slforw)
+	  {
+		PRF(printf("%s%7o->", (i==0 ? "\n    " : ""), sd))
+		if(++i >= 8) i = 0;
+		if(sbe_tbent(&sdtab, sd) < 0)	/* If hit loop, stop */
+			PRFBAD("SD freelist loop",
+			  printf("\nLOOP - %o seen as node %d!!",
+				sd, sdtab.pt_xerr))
+		if(sd->sdflags)
+		  {	PRF((i = 0, printf("\nFreelist node has flags:\n")))
+			PRFBUG("Free SD flagged", sbe_psd(sd))
+		  }
+	  }
+	PRF(printf("\nEnd - %d nodes on SD freelist.\n", sdtab.pt_cnt))
+	return(0);
+}
+
+
+
+/* SBE_SDS() - Print out all sdblk data stuff
+ */
+sbe_sds()
+{	int sbe_psd();
+
+	printf("Printout of all in-use SDBLKs:\n");
+	printf("  %s\n", sdfhelp);
+	printf("%s\n", sdhdline);
+	sbm_nfor(SM_DNODS,sizeof(struct sdblk),sbe_psd,0);
+	printf("\n");
+}
+
+/* SBE_PSD - Auxiliary for invocation by SBE_SDS above. */
+sbe_psd(sd)
+register struct sdblk *sd;
+{	register int flags;
+
+	flags = sd->sdflags;
+	printf("%c%c%c",
+		((flags&SD_MOD)  ? '*' : ' '),
+		((flags&SD_LOCK) ? 'L' : ' '),
+		((flags&SD_LCK2) ? 'T' : ' '));
+
+	printf(" %7o: %6o %6o %6o %6o %6o %6o %6o %7lo %5ld.\n", sd,
+		sd->slforw, sd->slback, sd->sdflags,
+		sd->sdforw, sd->sdback, sd->sdmem,
+		sd->sdfile, sd->sdaddr, sd->sdlen);
+	return(0);
+}
+
+/* SBE_SVFY() - Verify all SD blocks
+ *	Returns error message (0 if no errors found).
+ */
+char *
+sbe_svfy()
+{	register char *res;
+	return((res = sbe_sdlist(0,0)) ? res : sbe_sdlist(0,1));
+}
+
+/* SBE_SDLIST(printflag, physflag) - Verify/Print all SD blocks.
+ *	Show logical lists if physflag 0
+ *	Show physical lists otherwise
+ *	Returns error message (0 if no errors found).
+ */
+char *
+sbe_sdlist(p,phys)
+int p, phys;
+{	register char *res;
+	struct ptab sdtab;	/* The SDLIST table to use */
+
+	/* First put freelist in table, then scan for all
+	 * SD nodes.  Each active node (not in table) gets
+	 * its entire list traced forward/backward and added to table.
+	 */
+	if(res = sbe_sdtab(&sdtab, p, phys))	/* Set up freelist table */
+		return(res);
+
+	/* Freelist entered in table, now scan all SD's */
+	res = (char *)sbm_nfor(SM_DNODS,sizeof(struct sdblk),
+			sbe_schk, &sdtab);
+
+	PRF(printf("\n"))
+	return(res);
+}
+
+/* SBE_SDTAB(tableptr, printflag, physflag) - Auxiliary for SBE_SDLIST.
+ *	Stuffs all freelist SDBLK addresses in table for dup detection.
+ *	Returns error message (0 if no errors found).
+ */
+char *
+sbe_sdtab(pt, p, phys)
+register struct ptab *pt;
+int p, phys;
+{	register struct sdblk *sd;
+	register int res;
+
+	pt->pt_pflag = (p ? PTF_PRF : 0) | (phys ? PTF_SDPHYS : 0)
+			| PTF_OVFERR;
+	pt->pt_cnt = pt->pt_nsto = 0;	/* Initialize */
+
+	/* Stick freelist in table */
+	for(sd = sbx_nfl; sd; sd = sd->slforw)
+	  {	if(sbe_tbent(pt, sd) < 0)
+		  {	if(pt->pt_xerr < 0)
+				PRFBAD("SD freelist too long",
+					printf("SD freelist too long (%d)\n",
+						NPTRS))
+			PRFBAD("SD freelist loop",
+			  printf("SD freelist loop at %o\n", pt->pt_xerr))
+		  }
+
+		if(sd->sdflags)
+		  {
+			PRF(printf("Bad free SD, non-zero flag:\n"))
+			PRFBUG("Free SD flagged", sbe_psd(sd))
+		  }
+	  }
+	pt->pt_hidx = pt->pt_nsto;	/* Set idx of 1st non-FL entry */
+	return(0);
+}
+
+
+/* SBE_SCHK(SDptr, tableptr) - Auxiliary for SBE_SDLIST.
+ *	If SD not already in table, verifies or prints
+ *	the complete physical or logical list it's on, and enters all
+ *	of its SDs into table (to prevent doing it again).
+ *	Returns 0 if no errors, else error string.
+** There is a problem when the table overflows.  The tbent routine
+** wants to add it (wrapping around at bottom) in that case, because
+** that still helps detect loops.  But this routine wants to reset
+** the table back (after scanning to head of list) and once it starts
+** scanning forward again it will fail, because some of the SDs are
+** still in the table due to the wraparound!  Thus PTF_OVFERR is always
+** set, in order to at least give the right error message.
+*/
+char *
+sbe_schk(sd, pt)
+register struct sdblk *sd;
+struct ptab *pt;
+{	register struct sdblk *sdx;
+	register struct smblk *sm;
+	struct sbfile *savfile;
+	chroff lastaddr;
+	int p, res, savidx, phys;
+
+	phys = pt->pt_pflag&PTF_SDPHYS;	/* Set up physflag */
+	if(phys && (sd->sdfile == 0))	/* Ignore non-phys stuff if phys */
+		return(0);
+	p = pt->pt_pflag&PTF_PRF;	/* Set up printflag */
+	savidx = pt->pt_nsto;		/* Remember initial extent of table */
+
+	if(sbe_tbent(pt, sd) < 0)
+	  {	if(pt->pt_xerr >= 0)	/* OK if already in table */
+			return(0);
+		PRFBAD("Too many SDs",
+			printf("Too many SDs for table (%d)\n",	NPTRS))
+	  }
+
+	/* Now search backward for start of list */
+	while(sdx = (phys ? sd->sdback : sd->slback))
+		if(sbe_tbent(pt,sdx) >= 0)
+			sd = sdx;
+		else break;
+	if(sdx)
+	  {	if(pt->pt_xerr < 0)	/* Table error? */
+			PRFBAD("Too many SDs",
+				printf("Too many SDs for table (%d)\n",NPTRS))
+		PRF(printf("Backlist loop!! Dup'd node:%s\n",
+				(pt->pt_xerr < pt->pt_hidx) ?
+					"(on freelist!)" : "" ))
+		PRFBUG((phys ? "Phys SD loop" : "SD loop"), sbe_psd(sdx))
+	  }
+	/* Reset table to flush nodes backed over */
+	pt->pt_cnt = pt->pt_nsto = savidx;
+
+	/* SD now points to start of list.  Begin stepping thru list... */
+	PRF(printf("---- %sList started: ", (phys ? "Phys " : "")))
+	if(phys)
+	  {	savfile = sd->sdfile;
+		PRF(printf(" SF: %o, fd= %d, ln= %ld\n",
+			savfile,savfile->sffd,savfile->sflen))
+		if(savfile->sfptr1 != sd)
+			PRFBUG("SFPTR1 bad",
+			  printf("  BAD!! Sfptr1 %o doesn't match SD %o!!\n",
+				savfile->sfptr1, sd))
+		lastaddr = 0;
+	  }
+	else PRF(printf("\n"))
+
+	PRF(printf("%s\n", sdhdline))
+	for(sdx = 0; sd; (sdx = sd, sd = (phys ? sd->sdforw : sd->slforw)))
+	  {
+		PRF(sbe_psd(sd))	/* Print it out */
+		if(sdx != (phys ? sd->sdback : sd->slback))
+		  {	if(phys)
+			  PRFBUG("PSD bad sdback",printf("\tBad phys backptr\n"))
+			else
+			  PRFBUG("SD bad slback",printf("\tBad backptr\n"))
+		  }
+
+		if((sd->sdflags&0377) != SD_NID)
+			PRFBUG("Bad SD node ID", printf("\tBad node ID!\n"))
+
+
+		if(sd->sdfile && (sd->sdlen < 0 || sd->sdaddr < 0))
+			PRFBUG("SD: neg len/addr",
+				printf("\tNeg disk len/addr\n"))
+		if(phys) goto dophys;
+
+		/* Do special stuff for logical list */
+		if(sm = sd->sdmem)
+		  {	if((sm->smflags&0377) != SM_NID)
+				PRFBUG("SD: bad SM",
+					printf("\nBad SMBLK ptr\n"))
+			if((sd->sdflags&SD_MOD)==0
+			  && sd->sdlen != sm->smuse)
+				PRFBUG("SD != SM",
+					printf("\tBad SMBLK? Len conflict\n"))
+			if(sm->smlen < sm->smuse)
+				PRFBUG("SD: SM len < use",
+					printf("\tBad SMBLK, len < use\n"))
+		  }
+		goto doboth;	/* Skip phys stuff */
+
+		/* Do special stuff for phys list */
+	dophys:	if(sd->sdfile != savfile)
+			PRFBUG("SD: bad sdfile",
+				printf("\tBad sdfile ptr! Shd be %o\n",
+					savfile))
+		if(sd->sdaddr < lastaddr)
+			PRFBUG("SD addr out of order",
+				printf("\tBad disk addr, not in order!\n"))
+		lastaddr = sd->sdaddr;
+		/* Done with special phys stuff */
+
+	doboth:	if(sbe_tbent(pt, sd) < 0)
+		  {	if(pt->pt_xerr < 0)
+				PRFBAD("Too many SDs",
+					printf("Too many SDs for table (%d)\n",NPTRS))
+
+			PRFBUG("SD loop",
+				printf("\tLOOP!! This SD already seen%s.\n",
+					(pt->pt_xerr < pt->pt_hidx) ?
+					" (on freelist!)" : "" ))
+			break;
+		  }
+	  }
+	PRF(printf("-----------\n"))
+	return(0);
+}
+
+
+/* SBE_DSK(SFptr) - Print out disk usage list for specific file
+ */
+
+sbe_dsk(sfp)
+SBFILE *sfp;
+{
+	printf("SBFILE printout not coded: %o\n",sfp);
+}
+
+
+/* SBBUF structure debugging routines */
+
+struct flgt sbflgtab[] = {
+	SB_OVW, 'O',
+	SB_WRIT,'W',
+	0,0
+};
+static char sbfhelp[] = "O-Overwrite, W-Write";
+
+/* SBE_SBVFY(SBptr) - Verify a SB-string.
+ *	Returns error message (0 if no errors found).
+ */
+char *
+sbe_sbvfy(sbp)
+SBBUF *sbp;
+{	return(sbe_sbs(sbp,0));
+}
+
+/* SBE_SBS(SBptr, printflag) - Verify/Print SBSTR data stuff
+ *	Returns error message (0 if no errors found).
+ */
+char *
+sbe_sbs(sbp,p)
+SBBUF *sbp;
+int p;
+{	register SBBUF *sb;
+	register struct smblk *sm;
+	register struct sdblk *sd;
+
+	sb = sbp;
+	PRF(printf("SBSTR %o: ",sb))
+	if(sb == 0)
+		PRFBUG(0,printf("Zero pointer???\n"))
+
+	/* First print out cryptic summary in case pointers bomb
+	 * out farther on. */
+	PRF(printf(" (io,cur,r,w,f,.,+ = %o,%o,%d,%d,%o,%lo,%lo)\n",
+		sb->sbiop, sb->sbcur, sb->sbrleft, sb->sbwleft,
+		sb->sbflags, sb->sbdot, sb->sboff))
+
+	PRF(printf("  sbflags %5o = %s (%s)\n",
+			sb->sbflags, sbe_fstr(sb->sbflags,sbflgtab),
+			sbfhelp))
+
+	if(sd = sb->sbcur)	/* Okay, now try getting pointers */
+		sm = sd->sdmem;
+	else sm = 0;
+
+	PRF(printf("  sbcur %6o",sd))
+	if(sd)
+	  {
+		PRF(printf("\n   %s\n   ", sdhdline))
+		PRF(sbe_psd(sd))
+
+		if((sd->sdflags&0377) != SD_NID)
+			PRFBUG("SBCUR not SD?",printf("   BAD SDBLK ID!! \n"))
+		if(sm)
+		  {
+			PRF(printf("   %s\n   ", smhdline))
+			PRF(sbe_smp(sm,0))
+			if((sm->smflags&0377) != SM_NID)
+				PRFBUG("SBCUR has bad SM",
+					printf("   BAD SMBLK ID!!\n"))
+		  }
+	  }
+
+
+	PRF(printf("  sbiop  %6o",sb->sbiop))
+	if(sb->sbiop)
+	  {	if(!sm || sb->sbiop < sm->smaddr
+		  || sb->sbiop > (sm->smaddr + sm->smlen))
+			PRFBUG("Bad SBIOP", printf("  BAD"))
+	  }
+	else if(sb->sbrleft > 0 || sb->sbwleft > 0)
+		PRFBUG("Bad SBIOP/cnts", printf("  BAD"))
+	PRF(printf("\n"))
+
+	PRF(printf("  sbrleft %5o = %5d.",sb->sbrleft, sb->sbrleft))
+	if(sb->sbrleft
+	  && (	!sm
+	    ||	sb->sbwleft
+	    ||	(sb->sbflags&SB_WRIT)
+	    ||	(sb->sbrleft != (sm->smuse - (sb->sbiop - sm->smaddr)))
+	    ))
+		PRFBUG("Bad sbrleft", printf("  BAD"))
+	PRF(printf("\n"))
+
+	PRF(printf("  sbwleft %5o = %5d.", sb->sbwleft, sb->sbwleft))
+	if(sb->sbwleft
+	  && (	!sm
+	    ||	(sb->sbflags&SB_WRIT) == 0
+	    ||	(sb->sbwleft > (sm->smlen - (sb->sbiop - sm->smaddr)))
+	    ))
+		PRFBUG("Bad sbwleft", printf("  BAD"))
+	PRF(printf("\n"))
+
+	PRF(printf("  sbdot %7lo = %7ld.", sb->sbdot, sb->sbdot))
+	if(sb->sbdot < 0)
+		PRFBUG("Bad sbdot", printf("  BAD"))
+
+	PRF(printf("\n  sboff %7lo = %7ld.\n", sb->sboff, sb->sboff))
+	PRF(printf("  I/O ptr loc: %ld.\n\n", sb_tell(sb)))
+
+	return(0);
+}
+
+
+/* SBE_TBENT() - Auxiliary to add and check entries to a pointer table.
+ *	Note we assume here that smblk ptrs are used, although sdblks
+ *	can also be hacked.  This wins as long as the two kinds of ptrs
+ *	are basically identical (saves horrible casting problems).
+ *	Returns index # if successful (between 0 and NPTRS-1 inclusive).
+ *	Otherwise an error (-1), with relevant info in pt_xerr:
+ *		-1 if out of room and flag set making it an error
+ *		0-n if entry already existed.
+ */
+sbe_tbent(pt, sm)
+register struct ptab *pt;
+struct smblk *sm;
+{	register struct smblk **smt;
+	register int i;
+	int p;
+
+	p = pt->pt_pflag&PTF_PRF;	/* Set up print flag */
+	smt = &(pt->pt_tab[0]);
+	if(i = pt->pt_nsto)
+	  {	do {
+			if(sm == *smt++)
+			  {	pt->pt_xerr = pt->pt_nsto - i;
+				return(-1);
+			  }
+		  } while(--i);
+		--smt;
+	  }
+
+	i = pt->pt_cnt++;
+	if(++(pt->pt_nsto) > NPTRS)
+	  {	if(pt->pt_pflag&PTF_OVFERR)
+		  {	pt->pt_err = "Ptrtab overflow";
+			pt->pt_xerr = -1;
+			return(-1);
+		  }
+		pt->pt_nsto = NPTRS;
+		i %= NPTRS;
+	  }
+	pt->pt_tab[i] = sm;
+	return(i);
+}
+
+/* SBE_FSTR(flags, flagtab) - Auxiliary to convert flag word to a string
+ *	and return pointer to it.  Handy for printfs.
+ */
+char *
+sbe_fstr(flags, fp)
+register int flags;
+register struct flgt *fp;
+{	static char retstr[17];	/* Max of 16 flags */
+	register char *cp;
+	cp = retstr;
+	for(; fp->flg_bit; ++fp)
+		*cp++ = (fp->flg_bit&flags) ? fp->flg_chr : ' ';
+	*cp = 0;
+	return(retstr);
+}
Index: /trunk/minix/commands/elle/sbm.c
===================================================================
--- /trunk/minix/commands/elle/sbm.c	(revision 9)
+++ /trunk/minix/commands/elle/sbm.c	(revision 9)
@@ -0,0 +1,923 @@
+/* SB - Copyright 1982 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.  In all cases
+ *	the source code and any modifications thereto must remain
+ *	available to any user.
+ *
+ *	This is part of the SB library package.
+ *	Any software using the SB library must likewise be made
+ *	quasi-public, with freely available sources.
+ */
+
+#if 0
+	This file contains the low-level memory allocation
+subroutines which are used by the SBLK routines.  The code here
+is quite machine-dependent, and the definitions in "sb.h" should be
+carefully checked to verify that they are correct for the target
+machine.
+
+	The ultimate low-level routine is "sbrk()" which must be
+provided by the system''s C library.  SBM expects that successive calls
+to sbrk() will return contiguous areas of memory with progressively
+higher addresses.  Also, the very first call to sbrk() is assumed to
+return a word-aligned address.
+#endif /*COMMENT*/
+
+#include "sb.h"
+
+#define FUDGE (sizeof(struct smblk))	/* Allow this much fudge in
+				allocation, to prevent undue fragmentation */
+
+char *(*sbm_debug)();           /* Debug switch - user-furnished routine */
+
+struct smblk *sbm_nfl;          /* Pointer to node freelist */
+struct smblk *sbm_nxtra;	/* Reserved extra free node */
+struct smblk *sbm_list;         /* Pointer to smblk memory alloc list.
+				 * ALL smblks are strung onto this list
+				 * except for the freelist!
+				 */
+SBMA sbm_lowaddr;		/* Lowest word-aligned address we know about.*/
+
+/* If compiling with debug switch set, use special routine in place of
+ * sbrk so we can pretend we have a very limited area of free memory.
+ */
+#ifdef DBG_SIZE
+#define SBM_SBRK sbm_brk
+char *sbm_brk();
+#else
+#define SBM_SBRK sbrk
+#endif /*DBG_SIZE*/
+
+/* Forward routine declarations */
+char *sbrk();
+struct smblk *sbm_nmak(), *sbm_nget(), *sbm_mget(), *sbm_split();
+struct smblk *sbm_lmak(), *sbm_err();
+
+
+/* SBM_INIT - Initialize storage management.
+ *	If args are zero, normal initialization is done.  Otherwise,
+ *	args are understood to be pointers to an area of memory allocated
+ *	on the stack (eg by an "int mem[2000]" declaration in MAIN) and
+ *	initialization will include this area in addition to the
+ *	unused space between "_end" and the start of the stack segment.
+ *	This is mostly of use for PDP11s which would otherwise waste a lot
+ *	of address space.
+ *	Maybe should have a SBM_RESET() function?
+ */
+
+struct smblk *
+sbm_init(xaddr,xlen)
+SBMA xaddr;		/* Address of allocated stack area if any */
+SBMO xlen;		/* Size of this area */
+{       register struct smblk *sm, *sml;
+	register char *cp;
+
+	/* Get initial chunk of memory from standard system rtn */
+	if((cp = SBM_SBRK(SMNODES*sizeof(struct smblk))) == 0
+	  || (int) cp == -1)
+		return(sbm_err(0,"Can't sbrk"));
+	sm = (struct smblk *)cp;		/* Better be word-aligned! */
+	sbm_lmak(sm,(SBMO)sizeof(struct smblk),SMNODES);      /* Make list */
+	sbm_nfl = sm;				/* Point freelist at it */
+	sbm_lowaddr = (SBMA)sm;			/* Remember lowest addr seen */
+
+	/* Set up 1st node pointing to all memory from here on up.
+	 * We don't know exactly how much will be available at this point,
+	 * so we just pretend we have the maximum possible.
+	 */
+	sbm_list = sml = sbm_nget();
+	sml->smforw = sml->smback = 0;
+	sml->smflags = SM_USE|SM_NID;		/* Initial flags */
+	sml->smaddr = (SBMA) sml;
+	sml->smlen = MAXSBMO;			/* Pretend we have lots */
+	sml->smuse = (SMNODES * sizeof(struct smblk));
+
+	/* Now split off everything above initial allocation as NXM. */
+	sm = sbm_split(sml, sm->smuse);
+	sml->smflags |= SM_MNODS;	/* Mark 1st node as having SM nodes */
+	sm->smflags  |= SM_NXM;		/* Mark 2nd node as NXM */
+
+	/* Now possibly set up extra nodes, if stack mem is being allocated
+	 * (From our viewpoint it looks as if a chunk in the middle of
+	 * the initial NXM section has been declared usable)
+	 */
+	if(xlen)
+	  {     /* Allow for "extra" static stack memory */
+		/* Will lose if xaddr <= 1st NXM! */
+		sml = sbm_split(sm, (SBMO)(xaddr - sm->smaddr));
+		sbm_split(sml, xlen);		/* Split off following NXM */
+		sml->smflags &= ~(SM_USE|SM_NXM); /* This node is free mem! */
+	  }
+
+	/* Now set up a small additional node which points to the NXM
+	 * that we cannot get from SBRK.  At this stage, this is just
+	 * a place-holder, to reserve the node so we don't have to
+	 * worry about running out of nodes at the same time sbrk stops
+	 * returning memory.
+	 * SM points to the NXM that we expect SBRK to dig into.
+	 */
+	sbm_split(sm, sm->smlen - WDSIZE); /* Chop off teensy bit */
+	sm->smflags &= ~SM_USE;		/* Now mark NXM "free"!! */
+
+	/* Finally, reserve an "extra" SM node for use by sbm_nget
+	 * when it is allocating more freelist node chunks.
+	 */
+	sbm_nxtra = sbm_nget();
+
+	return(sbm_list);
+}
+
+
+/* SBM_NGET() - Get a free SM node.
+ *	Note the hair to provide a spare SM node when
+ *	we are allocating memory for more SM nodes.  This is necessary
+ *	because sbm_mget and sbm_nget call each other recursively and
+ *	sbm_mget cannot create any new memory without a SM node to point
+ *	at the allocated chunk.
+ */
+struct smblk *
+sbm_nget()
+{       register struct smblk *sm, *sml;
+
+	if(!(sm = sbm_nfl))		/* Get a node from freelist */
+	  {	/* Freelist is empty, try to allocate more nodes. */
+
+		/* Put our "spare" smblk on freelist temporarily so that
+		 * sbm_mget has a chance of winning.
+		 * Infinite recursion is avoided by a test
+		 * in sbm_mget which checks sbm_nfl and sbm_nxtra.
+		 */
+		if(!(sm = sbm_nxtra))
+			return(sbm_err(0,"Zero sbm_nxtra!"));
+		sm->smforw = 0;
+		sbm_nfl = sm;
+		sbm_nxtra = 0;
+
+		/* Try to allocate another chunk of SM nodes. */
+		sml = sbm_nmak(sizeof(struct smblk),SM_MNODS);
+
+		/* Put the new free nodes (if any) on freelist.
+		 * Done this way because freelist may have had one or two
+		 * nodes added to it by sbm_mget, so can't just stick
+		 * a new pointer in sbm_nfl.
+		 */
+		while(sm = sml)
+		  {	sml = sm->smforw;
+			sbm_nfre(sm);
+		  }
+
+		/* Now reserve an extra node again.
+		 * It is an error if there is nothing on freelist here,
+		 * because even if sbm_mget failed the "extra node" should
+		 * still be on freelist.  The check for a zero sbm_nxtra
+		 * above will catch such an error.
+		 */
+		sbm_nxtra = sbm_nget();
+
+		/* Now see if anything to return */
+		if(!(sm = sbm_nfl))		/* If freelist empty again, */
+			return(0);		/* give up. */
+	  }
+	sbm_nfl = sm->smforw;   /* If win, take it off freelist */
+	return(sm);		/* Return ptr or 0 if none */
+}
+
+/* SBM_NFRE(sm) - Return a SM node to the SM freelist.
+ */
+sbm_nfre(smp)
+struct smblk *smp;
+{       register struct smblk *sm;
+	(sm = smp)->smflags = 0;
+	sm->smforw = sbm_nfl;
+	sbm_nfl = sm;
+}
+
+/* SBM_NMAK(elsize, flag) - Make (allocate & build) a typeless node freelist.
+ */
+struct smblk *
+sbm_nmak(elsize, flag)
+SBMO elsize;
+unsigned flag;
+{       register struct smblk *sm, *smp;
+	register int cnt;
+
+	if((sm = sbm_mget(SMNODES*elsize,SMNODES*elsize)) == 0)
+		return(0);
+
+	sm->smflags |= flag;            /* Indicate type of nodes */
+	cnt = sm->smlen/elsize;		/* Find # nodes that will fit */
+	sm->smuse = cnt * elsize;	/* Actual size used */
+	smp = (struct smblk *)(sm->smaddr);	/* Ptr to 1st loc of mem */
+	sbm_lmak(smp, (SBMO)elsize, cnt);	/* Build freelist */
+	return(smp);            /* Return 1st free node. Caller is */
+				/* responsible for setting freelist ptr. */
+}
+
+/* SBM_LMAK - Build freelist of typeless nodes.
+ *	Note this does not allocate memory, it just converts an already
+ *	allocated memory area.
+ */
+struct smblk *
+sbm_lmak(addr, elsize, num)
+SBMA addr;
+SBMO elsize;
+int num;
+{	register struct smblk *sm, *smp;
+	register int cnt;
+
+	smp = (struct smblk *) addr;
+	if((cnt = num) <= 0)
+		return(0);
+	do {	sm = smp;       /* Save ptr */
+		sm->smforw = (smp = (struct smblk *) ((SBMA)smp + elsize));
+		sm->smflags = 0;
+	  } while(--cnt);
+	sm->smforw = 0;         /* Last node points to nothing */
+	return(sm);		/* Return ptr to last node */
+}
+
+/* SBM_NMOV(sm1, sm2, begp, elsize) - Move a typeless node.
+ *	Copy sm1 to sm2, adjust ptrs, leave sm1 free.
+ */
+sbm_nmov(smp1,smp2,begp,elsize)
+struct smblk *smp1, *smp2, **begp;
+int elsize;
+{       register struct smblk *sm;
+
+	bcopy((SBMA)smp1,(SBMA)(sm = smp2), elsize);     /* Copy the stuff */
+	if(sm->smforw) sm->smforw->smback = sm; /* Fix up links */
+	if(sm->smback) sm->smback->smforw = sm;
+	else *begp = sm;
+}
+
+
+/* SBM_MGET(min,max) - Get a SMBLK with specified amount of memory.
+ *      Returns 0 if none available.
+ *      Memory is guaranteed to start on word boundary, but may not
+ *              end on one.  Note that sbm_mfree is responsible for
+ *              ensuring that free mem starts word-aligned.
+ *	A subtle but major concern of this code is the number of freelist
+ * nodes gobbled by a single call.  If the freelist happens to not have
+ * enough nodes, then a recursive call to sbm_mget is made (via sbm_nget)
+ * in order to allocate a new batch of freelist nodes!  sbm_nget will
+ * always provide a single "spare" node during such an allocation, but
+ * there is only one and it is essential that sbm_mget gobble only ONE
+ * (if any) during such a call, which is indicated by sbm_nxtra==0.
+ *	The maximum # of freelist nodes that sbm_mget can gobble is
+ * 2, when (1) NXM memory is obtained, and a SM is needed to point at
+ * the new free mem, plus (2) the resulting SM is too big, and has to
+ * be split up, which requires another SM for the remainder.
+ *	The "used-NXM" smblk is set up at init time precisely in order to
+ * avoid the necessity of creating it here when sbrk stops winning, since
+ * that would require yet another freelist node and make it possible for
+ * sbm_mget to gobble 3 during one call -- too many.
+ *	Further note: the sbm_nfl checks are necessary in order
+ * to ensure that a SM node is available for use by sbm_split.  Otherwise
+ * the calls to sbm_split might create a new SM freelist by gobbling the
+ * very memory which we are hoping to return!
+ */
+SBMO sbm_chksiz = SMCHUNKSIZ;	/* Current chunk size to feed sbrk */
+
+struct smblk *
+sbm_mget(cmin,cmax)
+SBMO cmin,cmax;
+{       register struct smblk *sm, *sml;
+	register SBMO csiz;
+	register SBMA addr, xaddr;
+
+	if((sm = sbm_list) == 0         /* If never done, */
+	  && (sm = sbm_init((SBMA)0,(SBMO)0)) == 0)	/* initialize mem alloc stuff. */
+		return(0);		/* Can't init??? */
+
+	/* Round up sizes to word boundary */
+	if(rndrem(cmin)) cmin = rndup(cmin);
+	if(rndrem(cmax)) cmax = rndup(cmax);
+
+	/* Search for a free block having enough memory.
+	 * If run into a free-NXM block, always "win", since there may be
+	 * a combination of preceding free-mem and new mem which will satisfy
+	 * the request.  If it turns out this didn't work, we'll just fail
+	 * a little farther on.
+	 */
+retry:	csiz = cmin;			/* Set size that will satisfy us */
+	do {
+		if(  ((sm->smflags&SM_USE) == 0)
+		  && ((sm->smlen >= csiz) || (sm->smflags&SM_NXM)) )
+			break;
+	  } while(sm = sm->smforw);
+	if(sm == 0)
+		return(0);	/* Found none that minimum would fit */
+
+	if(sm->smflags&SM_NXM)
+	  {	/* Found free area, but it's marked NXM and the system
+		 * must be persuaded (via sbrk) to let us use that portion
+		 * of our address space.  Grab a good-sized chunk.
+		 */
+		if(sbm_nfl == 0)	/* Verify a spare SM node is avail */
+			goto getnod;	/* Nope, must get one. */
+
+		/* Decide amount of mem to ask system for, via sbrk.
+		 * The fine point here is the check of sbm_nxtra to make sure
+		 * that, when building more freelist nodes, we don't have
+		 * to use more than one SM node in the process.  If we
+		 * asked for too much mem, we'd have to use a SM node
+		 * to hold the excess after splitting.
+		 */
+		csiz = cmax;
+		if(sbm_nxtra		/* If normal then try for big chunk */
+		  && csiz < sbm_chksiz) csiz = sbm_chksiz;	/* Max */
+		if (csiz > sm->smlen)  csiz = sm->smlen;	/* Min */
+
+		/* Get the NXM mem */
+		if((addr = (SBMA)SBM_SBRK(csiz)) != sm->smaddr)
+		  {     /* Unexpected value returned from SBRK! */
+
+			if((int)addr != 0 && (int)addr != -1)
+			  {	return(sbm_err(0,"SBRK %o != %o", addr,
+						sm->smaddr));
+#if 0
+			/* If value indicates couldn't get the stuff, then
+			 * we have probably hit our limit and the rest of
+			 * NXM should be declared "used" to prevent further
+			 * hopeless sbrk calls.  We split off the portion
+			 * of NXM that is known for sure to be unavailable,
+			 * and mark it "used".  If a "used NXM" area already
+			 * exists following this one, the two are merged.
+			 * The chunk size is then reduced by half, so
+			 * only log2(SMCHUNKSIZ) attempts will be made, and
+			 * we try again.
+			 */
+				/* If returned some mem which starts outside
+				 * the NXM then something is screwed up. */
+				if(addr < sm->smaddr
+				  || (addr >= sm->smaddr+sm->smlen))
+					return(sbm_err(0,"SBRK %o != %o",
+						addr, sm->smaddr));
+				/* Got some mem, falls within NXM.
+				 * Presumably someone else has called sbrk
+				 * since last time, so we need to fence off
+				 * the intervening area. */
+				sm = sbm_split((sml=sm),(addr - sm->smaddr));
+				sml->smflags |= SM_USE|SM_EXT;
+				return(sbm_mget(cmin,cmax));
+#endif /*COMMENT*/
+			  }
+
+			/* Handle case of SBRK claiming no more memory.
+			 * Gobble as much as we can, and then turn this NXM
+			 * block into a free-mem block, and leave the
+			 * remainder in the used-NXM block (which should
+			 * immediately follow this free-NXM block!)
+			 */
+			if(!(sml = sm->smforw)	/* Ensure have used-NXM blk */
+			  || (sml->smflags&(SM_USE|SM_NXM))
+					!= (SM_USE|SM_NXM))
+				return(sbm_err(0,"No uNXM node!"));
+			xaddr = sm->smaddr;	/* Use this for checking */
+			sm->smuse = 0;		/* Use this for sum */
+			for(csiz = sm->smlen; csiz > 0;)
+			  {	addr = SBM_SBRK(csiz);
+				if((int)addr == 0 || (int)addr == -1)
+				  {	csiz >>= 1;
+					continue;
+				  }
+				if(addr != xaddr)
+					return(sbm_err(0,"SBRK %o != %o", addr,
+						xaddr));
+				sm->smuse += csiz;
+				xaddr += csiz;
+			  }
+
+			/* Have gobbled as much from SBRK as we could.
+			 * Turn the free-NXM block into a free-mem block,
+			 * unless we got nothing, in which case just merge
+			 * it into the used-NXM block and continue
+			 * searching from this point.
+			 */
+			if(!(csiz = sm->smuse))	/* Get total added */
+			  {	sm->smflags = sml->smflags;	/* Ugh. */
+				sbm_mmrg(sm);
+				goto retry;		/* Keep looking */
+			  }
+			else
+			  {	sml->smaddr = sm->smaddr + csiz;
+				sml->smlen += sm->smlen - csiz;
+				sm->smlen = csiz;
+				sm->smflags &= ~SM_NXM;	/* No longer NXM */
+			  }
+		  }
+
+		/* Here when we've acquired CSIZ more memory from sbrk.
+		 * If preceding mem area is not in use, merge new mem
+		 * into it.
+		 */
+		if((sml = sm->smback) && 
+		  (sml->smflags&(SM_USE|SM_NXM))==0)    /* Previous free? */
+		  {     sml->smlen += csiz;		/* Yes, simple! */
+			sm->smaddr += csiz;		/* Fix up */
+			if((sm->smlen -= csiz) == 0)	/* If no NXM left,*/
+				sbm_mmrg(sml);	/* Merge NXM node w/prev */
+			sm = sml;		/* Prev is now winning node */
+		  }
+		else
+		  {	/* Prev node isn't a free area.  Split up the NXM
+			 * node to account for acquired mem, unless we
+			 * gobbled all the mem available.
+			 */
+			if(sm->smlen > csiz	/* Split unless all used */
+			  && !sbm_split(sm,csiz)) /* Call shd always win */
+				return(sbm_err(0,"getsplit err: %o",sm));
+			sm->smflags &= ~SM_NXM;	/* Node is now real mem */
+		  }
+
+		/* Now make a final check that we have enough memory.
+		 * This can fail because SBRK may not have been able
+		 * to gobble enough memory, either because (1) not
+		 * as much NXM was available as we thought,
+		 * or (2) we noticed the free-NXM area and immediately
+		 * gambled on trying it without checking any lengths.
+		 * In any case, we try again starting from the current SM
+		 * because there may be more free mem higher up (eg on
+		 * stack).
+		 */
+		if(sm->smlen < cmin)
+			goto retry;
+	  }
+
+	/* Check to see if node has too much mem.  This is especially true
+	 * for memory just acquired via sbrk, which gobbles a huge chunk each
+	 * time.  If there's too much, we split up the area.
+	 */
+	if(sm->smlen > cmax+FUDGE)	/* Got too much?  (Allow some fudge)*/
+		/* Yes, split up so don't gobble too much. */
+		if(sbm_nfl)                     /* If success guaranteed, */
+			sbm_split(sm,cmax);     /* split it, all's well. */
+		else goto getnod;
+
+	sm->smuse = 0;
+	sm->smflags |= SM_USE;  /* Finally seize it by marking "in-use". */
+	return(sm);
+
+	/* Come here when we will need to get another SM node but the
+	 * SM freelist is empty.  We have to forget about using the area
+	 * we just found, because sbm_nget may gobble it for the
+	 * freelist.  So, we first force a refill of the freelist, and then
+	 * invoke ourselves again on what's left.
+	 */
+getnod:
+	if(sml = sbm_nget())		/* Try to build freelist */
+	  {	sbm_nfre(sml);		/* Won, give node back, */
+		sm = sbm_list;		/* and retry, starting over! */
+		goto retry;	
+	  }
+	/* Failed.  Not enough memory for both this request
+	 * and one more block of SM nodes.  Since such a SM_MNODS
+	 * block isn't very big, we are so close to the limits that it
+	 * isn't worth trying to do something fancy here to satisfy the
+	 * original request.  So we just fail.
+	 */
+	return(0);
+}
+
+#ifdef DBG_SIZE
+/* Code for debugging stuff by imposing an artificial limitation on size
+ * of available memory.
+ */
+SBMO sbm_dlim = MAXSBMO;	/* Amount of mem to allow (default is max) */
+
+char *
+sbm_brk(size)
+unsigned size;
+{	register char *addr;
+
+	if(size > sbm_dlim) return(0);
+	addr = sbrk(size);
+	if((int)addr == 0 || (int)addr == -1)
+		return(0);
+	sbm_dlim -= size;
+	return(addr);
+}
+#endif /*DBG_SIZE*/
+
+
+/* SBM_MFREE(sm) - Free up an allocated memory area.
+ */
+sbm_mfree(sm)
+register struct smblk *sm;
+{       register struct smblk *smx;
+	register SBMO crem;
+
+	sm->smflags &= ~SM_USE;			/* Say mem is free */
+	if((smx = sm->smback)                   /* Check preceding mem */
+	  && (smx->smflags&(SM_USE|SM_NXM))==0) /*   If it's free, */
+		sbm_mmrg(sm = smx);		/*   then merge 'em. */
+	if((smx = sm->smforw)			/* Check following mem */
+	  && (smx->smflags&(SM_USE|SM_NXM))==0) /*   Again, if free,  */
+		sbm_mmrg(sm);                   /*   merge them.   */
+
+	if(sm->smlen == 0)              /* Just in case, chk for null blk */
+	  {     if(smx = sm->smback)            /* If pred exists, */
+			sbm_mmrg(smx);          /* merge quietly. */
+		else {
+			sbm_list = sm->smforw;  /* 1st node on list, so */
+			sbm_nfre(sm);           /* simply flush it. */
+		  }
+		return;
+	  }
+
+	/* This code is slightly over-general for some machines.
+	 * The pointer subtraction is done in order to get a valid integer
+	 * offset value regardless of the internal representation of a pointer.
+	 * We cannot reliably force alignment via casts; some C implementations
+	 * treat that as a no-op.
+	 */
+	if(crem = rndrem(sm->smaddr - sbm_lowaddr))	/* On word bndry? */
+	  {     /* No -- must adjust.  All free mem blks MUST, by fiat,
+		 * start on word boundary.  Here we fix things by
+		 * making the leftover bytes belong to the previous blk,
+		 * no matter what it is used for.  Prev blk is guaranteed to
+		 * (1) Exist (this cannot be 1st blk since 1st is known to
+		 * start on wd boundary) and to be (2) Non-free (else it would
+		 * have been merged).
+		 */
+		if((smx = sm->smback) == 0)     /* Get ptr to prev blk */
+		  {	sbm_err(0,"Align err");	/* Catch screws */
+			return;
+		  }
+		crem = WDSIZE - crem;	/* Find # bytes to flush */
+		if(crem >= sm->smlen)	/* Make sure node has that many */
+		  {	sbm_mmrg(smx);  /* Flush node to avoid zero length */
+			return;
+		  }
+		smx->smlen += crem;	/* Make stray bytes part of prev */
+		sm->smaddr += crem;	/* And flush from current. */
+		sm->smlen -= crem;
+	  }
+}
+
+
+/* SBM_EXP - Expand (or shrink) size of an allocated memory chunk.
+ *	"nsize" is desired new size; may be larger or smaller than current
+ *	size.
+ */
+struct smblk *
+sbm_exp(sm,size)
+register struct smblk *sm;
+register SBMO size;
+{       register struct smblk *smf;
+	register SBMO mexp, pred, succ;
+
+	if(sm->smlen >= size)		/* Do we want truncation? */
+		goto realo2;		/* Yup, go split block */
+
+	/* Block is expanding. */
+	mexp = size - sm->smlen;		/* Get # bytes to expand by */
+	pred = succ = 0;
+	if((smf = sm->smforw)           	/* See if free mem follows */
+	 && (smf->smflags&(SM_USE|SM_NXM)) == 0)
+		if((succ = smf->smlen) >= mexp)
+			goto realo1;		/* Quick stuff if succ OK */
+
+	if((smf = sm->smback)			/* See if free mem precedes */
+	 && (smf->smflags&(SM_USE|SM_NXM)) == 0)
+		pred = smf->smlen;
+
+	/* If not enough free space combined on both sides of this chunk,
+	 * we have to look for a completely new block.
+	 */
+	if(pred+succ < mexp)
+	  {	if((smf = sbm_mget(size,size)) == 0)
+			return(0);              /* Couldn't find one */
+		else pred = 0;			/* Won, indicate new block */
+	  }
+
+	/* OK, must copy either into new block or down into predecessor
+	 * (overlap is OK as long as bcopy moves 1st byte first)
+	 */
+	bcopy(sm->smaddr, smf->smaddr, sm->smlen);
+	smf->smflags = sm->smflags;     /* Copy extra attribs */
+	smf->smuse = sm->smuse;
+	if(!pred)			/* If invoked sbm_mget */
+	  {	sbm_mfree(sm);		/* then must free up old area */
+		return(smf);		/* and can return immediately. */
+	  }
+	sbm_mmrg(smf);			/* Merge current into pred blk */
+	sm = smf;			/* Now pred is current blk. */
+
+	if(succ)
+realo1:		sbm_mmrg(sm);		/* Merge succ into current blk */
+realo2: if(sm->smlen > size		/* If now have too much, */
+	  && sbm_split(sm, size))       /* split up and possibly */
+		sbm_mfree(sm->smforw);  /* free up unused space. */
+	return(sm);
+
+	/* Note that sbm_split can fail if it can't get a free node,
+	 * which is only possible if we are reducing the size of an area.
+	 * If it fails, we just return anyway without truncating the area.
+	 */
+}
+
+
+/* SBM_MMRG(sm) - Merge a memory area with the area following it.
+ *	The node (and memory area) following the SM pointed to are
+ *	merged in and the successor node freed up.  The flags
+ *	and smuse of the current SM (which is not moved or anything)
+ *	remain the same.
+ */
+sbm_mmrg(smp)
+struct smblk *smp;
+{       register struct smblk *sm, *sm2;
+
+	sm = smp;
+	sm->smlen += (sm2 = sm->smforw)->smlen;	/* Add succ's len */
+	if(sm->smforw = sm2->smforw)            /* and fix linkages */
+		sm->smforw->smback = sm;
+	sbm_nfre(sm2);                          /* now can flush succ node */
+}
+
+/* SBM_SPLIT - Split up an area (gets a new smblk to point to split-off
+ *	portion.)
+ * Note returned value is ptr to 2nd smblk, since this is a new one.
+ * Ptr to 1st remains valid since original smblk stays where it is.
+ * NOTE: Beware of splitting up free mem (SM_USE == 0) since sbm_nget may
+ * steal it out from under unless precautions are taken!  See comments
+ * at sbm_mget related to this.
+ */
+struct smblk *
+sbm_split(smp,coff)
+struct smblk *smp;
+SBMO coff;
+{       register struct smblk *sm, *smx;
+	register SBMO csiz;
+
+	if((sm = smp)->smlen <= (csiz = coff))
+		return(0);
+	if((smx = sbm_nget()) == 0)
+		return(0);
+	smx->smlen = sm->smlen - csiz;          /* Set 2nd size */
+	smx->smaddr = sm->smaddr + csiz;        /* Set 2nd addr */
+	sm->smlen = csiz;			/* Take from 1st size */
+	smx->smflags = sm->smflags;             /* Copy flags */
+	if(smx->smforw = sm->smforw)            /* Splice 2nd after 1 */
+		smx->smforw->smback = smx;
+	smx->smback = sm;
+	sm->smforw = smx;                       /* Put 2nd into chain */
+	return(smx);                            /* Return ptr to 2nd smblk */
+}
+
+#if 0	/* Replaced by "bcopy" for system-dep efficiency */
+/* SBM_SCPY - Copy string of bytes.  Somewhat machine-dependent;
+ *	Tries to be clever about using word moves instead of byte moves.
+ */
+sbm_scpy(from, to, count)       /* Copy count bytes from -> to */
+char *from, *to;
+unsigned count;
+{       register char *s1, *s2;
+	register unsigned cnt;
+	int tmp;
+
+	if((cnt = count) == 0)
+		return;
+	s1 = from;
+	s2 = to;
+	while(rndrem((int)s1))		/* Get 1st ptr aligned */
+	  {     *s2++ = *s1++;
+		if(--cnt == 0) return;
+	  }
+	if(rndrem((int)s2) == 0)	/* Do wd move if ptr 2 now aligned */
+	  {
+#ifdef DUMBPCC /* Code for dumber (Portable C type) compiler */
+		register WORD *ap, *bp;
+		tmp = cnt;
+		ap = (WORD *) s1;
+		bp = (WORD *) s2;
+		if(cnt = rnddiv(cnt))
+			do { *bp++ = *ap++; }
+			while(--cnt);
+		if ((cnt = rndrem(tmp)) ==0)
+			return;
+		s1 = (char *) ap;
+		s2 = (char *) bp;
+#else
+	/* Tight loop for efficient copying on 11s */
+		tmp = cnt;
+		if(cnt = rnddiv(cnt))
+			do { *((WORD *)s2)++ = *((WORD *)s1)++; }
+			while(--cnt);
+		if((cnt = rndrem(tmp)) == 0)
+			return;
+#endif /*-DUMBPCC*/
+	  }                             
+	do { *s2++ = *s1++; }	/* Finish up with byte loop */
+	while(--cnt);
+}
+#endif /*COMMENT*/
+
+struct smblk *		/* If it returns at all, this is most common type */
+sbm_err(val,str,a0,a1,a2,a3)
+char *str;
+struct smblk *val;
+{	int *sptr;
+
+	sptr = (int *) &sptr;	/* Point to self on stack */
+	sptr += 5;		/* Point to return addr */
+	if((int)sbm_debug==1)
+		abort();
+	if(sbm_debug)
+		(*sbm_debug)(0,*sptr,str,a0,a1,a2,a3);
+	return(val);
+}
+
+
+/* These routines correspond to the V7 LIBC routines as described
+ * in the V7 UPM (3).  They should provide satisfactory emulation
+ * if the documentation is correct.  Replacement is necessary since
+ * the SBM routines are jealous and cannot tolerate competition for
+ * calls of SBRK; i.e. the memory being managed must be contiguous.
+ */
+
+/* Guaranteed to return word-aligned pointer to area of AT LEAST
+ * requested size.  Area size is rounded up to word boundary.
+ */
+
+char *
+malloc(size)
+unsigned size;
+{       register struct smblk *sm, **sma;
+	register SBMO siz;
+
+	siz = rndup(size + sizeof (struct smblk *));   /* Make room for ptr */
+	if((sm = sbm_mget(siz,siz)) == 0)
+		return(0);
+	*(sma = (struct smblk **)sm->smaddr) = sm; /* Store ptr in addr-1 */
+	return((char *)++sma);
+}
+
+char *
+alloc(size)     /* For V6 programs - note different failure value! */
+unsigned size;
+{       register char *addr;
+	return((addr = malloc(size)) ? addr : (char *) -1);
+}
+
+free(ptr)
+char *ptr;
+{       register struct smblk *sm, **smp;
+
+	smp = &((struct smblk **)ptr)[-1];	/* Point to addr-1 */
+	sm = *smp;				/* Pluck SM ptr therefrom */
+	if(((sm->smflags&0377) != SM_NID) || sm->smaddr != (SBMA)smp)
+		return((int)sbm_err(0,"free: bad arg %o", ptr));
+	sbm_mfree(sm);
+	return(1);
+}
+
+char *
+realloc(ptr,size)
+char *ptr;
+unsigned size;
+{       register struct smblk *sm, **smp;
+
+	smp = &((struct smblk **)ptr)[-1];	/* Point to addr-1 */
+	sm = *smp;				/* Pluck SM ptr therefrom */
+	if(((sm->smflags&0377) != SM_NID) || (sm->smaddr != (SBMA)smp))
+		return((char *)sbm_err(0,"realloc: bad arg %o",ptr));
+	if((sm = sbm_exp(sm, rndup(size+(sizeof(struct smblk *))))) == 0)
+		return(0);
+	*(smp = (struct smblk **)sm->smaddr) = sm;      /* Save smblk ptr */
+	return((char *)++smp);
+}
+
+char *
+calloc(nelem,elsize)
+unsigned nelem, elsize;
+{       register SBMO cmin;
+	register WORD *ip;                     /* Clear in units of words */
+	register char *addr;
+
+	if((cmin = nelem*elsize) == 0           /* Find # bytes to get */
+	  || (addr = malloc(cmin)) == 0)        /* Get it */
+		return(0);
+	ip = (WORD *) addr;			/* Set up ptr to area */
+	cmin = rnddiv(cmin+WDSIZE-1);		/* Find # words to clear */
+	do { *ip++ = 0; } while (--cmin);       /* Zap the area */
+	return(addr);
+}
+
+
+/* SBM_NGC() - Specific routine for GC'ing SMBLK nodes.
+ *
+ * SBM_XNGC(begp, elsize, type) - Compact nodes of specified type.
+ *      Scans allocated mem from low to high to find chunks with nodes of
+ *	the specified type.
+ *      Flushes current freelist and rebuilds it as scan progresses,
+ *      such that 1st thing on list is lowest-addr node.  When a node is
+ *      seen that can be moved, new node is acquired from freelist if
+ *      it exists, otherwise no move is made.  If a chunk has been scanned
+ *      and no active nodes remain, it is flushed and freelist updated.
+ *      NOTE: This has not yet been verified to work with nodes of any
+ *		type other than SMBLK.
+ */
+
+sbm_ngc()
+{	register struct smblk *sm;
+	if(!(sm = sbm_nxtra))
+		return((int)sbm_err(0,"Zero sbm_nxtra"));
+	sm->smflags |= SM_USE;		/* Ensure this one isn't GC'd */
+	sbm_xngc(&sbm_nfl, sizeof(struct smblk), SM_MNODS);
+	sm->smflags = 0;		/* Flush temporary crock */
+}
+sbm_xngc(begp, elsize, flag)
+struct smblk **begp;
+unsigned elsize, flag;
+{       register struct smblk *sm, *chk, *smf;
+	struct smblk *ftail, *savtail;
+	int cnt, inuse;
+
+	*begp = ftail = 0;		/* Flush node freelist */
+	for(chk = sbm_list; chk; chk = chk->smforw)
+	  if(chk->smflags&flag)
+	    {   sm = (struct smblk *) chk->smaddr;
+		cnt = (chk->smuse)/elsize;
+		savtail = ftail;
+		inuse = 0;
+		smf = *begp;
+					 /* Set up ptr to 1st freelist node */
+		while(--cnt >= 0)
+		  {     /* Here decide if movable */
+			if(sm->smflags && smf   /* Live and have copy place */
+			  && (
+				(sm->smflags&SM_USE) == 0       /* Free mem? */
+			    ||  (sm->smflags&(SM_MNODS|SM_DNODS))
+			     )
+			  && sm->smback)        /* has backptr (see ncpy) */
+			  {                             /* Move the node */
+				*begp = smf->smforw;	/* Get free node */
+				if(smf == ftail)
+					ftail = 0;
+				if(smf == savtail)
+					savtail = 0;
+				/* Move node.  Already checked for back ptr
+				 * of 0 since no obvious way to tell where
+				 * the ptr to list is kept.  Sigh.
+				 */
+				sbm_nmov(sm,smf,(struct smblk **)0,elsize);
+				/* Get ptr to new freelist node.  Note
+				 * check to ensure that it is not in this
+				 * same chunk (if it is, no point in moving
+				 * any nodes!)
+				 */
+				if((smf = *begp) >= chk)
+					smf = 0;        /* Zero if same chk */
+				sm->smflags = 0;        /* Make node free */
+			  }
+			/* At this point, not movable */
+			if(sm->smflags == 0)            /* Free node? */
+			  {     if(ftail)               /* Add to freelist */
+					ftail->smforw = sm;
+				ftail = sm;
+				if(*begp == 0)
+					*begp = sm;
+				sm->smforw = 0;
+			  }
+			else inuse++;
+			sm = (struct smblk *)((SBMA)sm + elsize);
+		  }
+		if(inuse == 0                           /* All free? */
+		  && (sm = chk->smback))		/* & not 1st? */
+		  {     if(savtail)                     /* Edit freelist */
+				(ftail = savtail)->smforw = 0;
+			else *begp = ftail = 0;
+			sbm_mfree(chk);
+			chk = sm;
+		  }
+	    }
+}
+
+/*
+ *      Note that proc must return a zero value, or loop aborts and
+ *      returns that selfsame value.
+ */
+sbm_nfor(flag,nodsiz,proc,arg)
+int flag;
+int (*proc)();
+int nodsiz;
+struct sbfile *arg;
+{       register struct smblk *sm, *np;
+	register int cnt;
+	int res;
+
+	for(sm = sbm_list; sm; sm = sm->smforw)
+	  if(sm->smflags&flag)
+	    {   np = (struct smblk *) sm->smaddr;
+		cnt = sm->smuse/nodsiz;
+		do {
+			if(np->smflags)
+				if(res = (*proc)(np,arg))
+					return(res);
+			np = (struct smblk *)((SBMA)np + nodsiz);
+		  } while(--cnt);
+	    }
+	return(0);
+}
Index: /trunk/minix/commands/elle/sbproto.h
===================================================================
--- /trunk/minix/commands/elle/sbproto.h	(revision 9)
+++ /trunk/minix/commands/elle/sbproto.h	(revision 9)
@@ -0,0 +1,120 @@
+#ifndef _ANSI
+#include <ansi.h>
+#endif
+
+/* sbbcpy.c */
+_PROTOTYPE( int bcopy, (SBMA from, SBMA to, unsigned cnt) );
+_PROTOTYPE( int sbm_wcpy, (int *from, int *to, unsigned cnt) );
+
+/* sberr.c */
+_PROTOTYPE( int sbe_mem, (void) );
+_PROTOTYPE( char *sbe_mvfy, (void) );
+_PROTOTYPE( char *sbe_mfl, (int p) );
+_PROTOTYPE( char *sbe_mlst, (int p) );
+_PROTOTYPE( int sbe_smp, (struct smblk *sm, int type) );
+_PROTOTYPE( char *sbe_sfl, (int p) );
+_PROTOTYPE( int sbe_sds, (void) );
+_PROTOTYPE( int sbe_psd, (struct sdblk *sd) );
+_PROTOTYPE( char *sbe_svfy, (void) );
+_PROTOTYPE( char *sbe_sdlist, (int p, int phys) );
+_PROTOTYPE( int sbe_dsk, (SBFILE *sfp) );
+_PROTOTYPE( char *sbe_sbvfy, (SBBUF *sbp) );
+_PROTOTYPE( char *sbe_sbs, (SBBUF *sbp, int p) );
+
+/* sbm.c */
+_PROTOTYPE( struct smblk *sbm_init, (SBMA xaddr, SBMO xlen) );
+_PROTOTYPE( struct smblk *sbm_nget, (void) );
+_PROTOTYPE( int sbm_nfre, (struct smblk *smp) );
+_PROTOTYPE( struct smblk *sbm_nmak, (SBMO elsize, unsigned flag) );
+_PROTOTYPE( struct smblk *sbm_lmak, (SBMA addr, SBMO elsize, int num) );
+_PROTOTYPE( int sbm_nmov, (struct smblk *smp1, struct smblk *smp2, struct smblk **begp, int elsize) );
+_PROTOTYPE( struct smblk *sbm_mget, (SBMO cmin, SBMO cmax) );
+_PROTOTYPE( char *sbm_brk, (unsigned size) );
+_PROTOTYPE( int sbm_mfree, (struct smblk *sm) );
+_PROTOTYPE( struct smblk *sbm_exp, (struct smblk *sm, SBMO size) );
+_PROTOTYPE( int sbm_mmrg, (struct smblk *smp) );
+_PROTOTYPE( struct smblk *sbm_split, (struct smblk *smp, SBMO coff) );
+_PROTOTYPE( int sbm_scpy, (char *from, char *to, unsigned count) );
+#if 0
+_PROTOTYPE( struct smblk *sbm_err, (struct smblk *val, char *str, int a0, int a1, int a2, int a3) );
+#else
+struct smblk *sbm_err();
+#endif
+_PROTOTYPE( char *malloc, (unsigned size) );
+_PROTOTYPE( char *alloc, (unsigned size) );
+_PROTOTYPE( int free, (char *ptr) );
+_PROTOTYPE( char *realloc, (char *ptr, unsigned size) );
+_PROTOTYPE( char *calloc, (unsigned nelem, unsigned elsize) );
+_PROTOTYPE( int sbm_ngc, (void) );
+_PROTOTYPE( int sbm_xngc, (struct smblk **begp, unsigned elsize, unsigned flag) );
+_PROTOTYPE( int sbm_nfor, (int flag, int nodsiz, int (*proc )(), struct sbfile *arg) );
+
+/* sbstr.c */
+_PROTOTYPE( SBSTR *sb_close, (SBBUF *sbp) );
+_PROTOTYPE( int sb_setovw, (SBBUF *sbp) );
+_PROTOTYPE( int sb_clrovw, (SBBUF *sbp) );
+_PROTOTYPE( chroff sbx_fdlen, (int fd) );
+_PROTOTYPE( SBSTR *sb_fduse, (int ifd) );
+_PROTOTYPE( int sb_fdcls, (int ifd) );
+_PROTOTYPE( int sbx_fcls, (struct sbfile *sfp) );
+_PROTOTYPE( int sb_fdinp, (SBBUF *sb, int fd) );
+_PROTOTYPE( int sb_fsave, (SBBUF *sb, int fd) );
+_PROTOTYPE( int sb_sgetc, (SBBUF *sb) );
+_PROTOTYPE( int sb_sputc, (SBBUF *sb, int ch) );
+_PROTOTYPE( int sb_speekc, (SBBUF *sb) );
+_PROTOTYPE( int sb_rgetc, (SBBUF *sb) );
+_PROTOTYPE( int sb_rdelc, (SBBUF *sbp) );
+_PROTOTYPE( int sb_deln, (SBBUF *sbp, chroff num) );
+_PROTOTYPE( struct sdblk *sb_killn, (SBBUF *sbp, chroff num) );
+_PROTOTYPE( SBSTR *sb_cpyn, (SBBUF *sbp, chroff num) );
+_PROTOTYPE( int sb_sins, (SBBUF *sbp, struct sdblk *sdp) );
+_PROTOTYPE( SBSTR *sbs_cpy, (SBSTR *sdp) );
+_PROTOTYPE( int sbs_del, (SBSTR *sdp) );
+_PROTOTYPE( SBSTR *sbs_app, (struct sdblk *sdp, struct sdblk *sdp2) );
+_PROTOTYPE( chroff sbs_len, (SBSTR *sdp) );
+_PROTOTYPE( int sb_seek, (SBBUF *sbp, chroff coff, int flg) );
+_PROTOTYPE( int sb_rewind, (SBBUF *sbp) );
+_PROTOTYPE( chroff sb_tell, (SBBUF *sbp) );
+_PROTOTYPE( chroff sb_ztell, (SBBUF *sbp) );
+#if 0
+_PROTOTYPE( struct sdblk *sbx_ready, (SBBUF *sbp, int type, SBMO cmin, SBMO cmax) );
+#else
+struct sdblk *sbx_ready();
+#endif
+_PROTOTYPE( struct sdblk *sbx_next, (SBBUF *sbp) );
+_PROTOTYPE( struct sdblk *sbx_norm, (SBBUF *sbp, int mode) );
+_PROTOTYPE( struct sdblk *sbx_beg, (struct sdblk *sdp) );
+_PROTOTYPE( int sbx_smdisc, (SBBUF *sbp) );
+_PROTOTYPE( int sbx_sbrdy, (SBBUF *sbp) );
+_PROTOTYPE( struct sdblk *sbx_scpy, (struct sdblk *sdp, struct sdblk *sdlast) );
+_PROTOTYPE( struct sdblk *sbx_sdcpy, (struct sdblk *sdp) );
+_PROTOTYPE( struct sdblk *sbx_xcis, (SBBUF *sbp, chroff num, struct sdblk **asd2, chroff *adot) );
+_PROTOTYPE( struct sdblk *sbx_split, (struct sdblk *sdp, chroff coff) );
+_PROTOTYPE( struct smblk *sbx_msplit, (struct smblk *smp, SBMO size) );
+_PROTOTYPE( struct sdblk *sbx_ndel, (struct sdblk *sdp) );
+_PROTOTYPE( int sbx_npdel, (struct sdblk *sdp) );
+_PROTOTYPE( struct sdblk *sbx_ndget, (void) );
+_PROTOTYPE( int sbx_ndfre, (struct sdblk *sdp) );
+_PROTOTYPE( SBMA sbx_malloc, (unsigned size) );
+_PROTOTYPE( struct smblk *sbx_mget, (SBMO cmin, SBMO cmax) );
+_PROTOTYPE( int sbx_comp, (int cmin, int lev) );
+_PROTOTYPE( int sbx_sdgc, (struct sdblk *sdp, int lev) );
+#if 0
+_PROTOTYPE( int sbx_aout, (struct sdblk *sdp, int flag, int fd) );
+#else
+int sbx_aout();
+#endif
+_PROTOTYPE( chroff sbx_qlen, (struct sdblk *sdp) );
+_PROTOTYPE( int sbx_tset, (chroff loff, int align) );
+_PROTOTYPE( struct sdblk *sbx_ffnd, (SBFILE *sfp, chroff size, chroff *aloc) );
+_PROTOTYPE( int sbx_rdf, (int fd, char *addr, int cnt, int skflg, chroff loc) );
+_PROTOTYPE( int sbx_rugpull, (int fd) );
+_PROTOTYPE( int sbx_unpur, (struct sdblk *sd, struct sbfile *sf) );
+#if 0
+_PROTOTYPE( int sbx_err, (int val, char *str, int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12) );
+#else
+int sbx_err();
+#endif
+
+/* sbvall.c */
+_PROTOTYPE( char *valloc, (unsigned size) );
Index: /trunk/minix/commands/elle/sbstr.c
===================================================================
--- /trunk/minix/commands/elle/sbstr.c	(revision 9)
+++ /trunk/minix/commands/elle/sbstr.c	(revision 9)
@@ -0,0 +1,2213 @@
+/* SB - Copyright 1982 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.  In all cases
+ *	the source code and any modifications thereto must remain
+ *	available to any user.
+ *
+ *	This is part of the SB library package.
+ *	Any software using the SB library must likewise be made
+ *	quasi-public, with freely available sources.
+ */
+
+#if 0
+Todo stuff:
+	New definitions:
+		sbbuffer - old sbstr.  Abbrev & struct "sbbuff".  Macro SBBUFF
+			(or SBBUF?)
+		sbstring - list of sds.  Abbrev sbstr.  Macro SBSTR.
+			Should *sbstr == *sdblk?  Yeah.
+		sbfile - as before.  Macro SBFILE. (or SBFIL?)
+
+	Try to get zero-length sdblks flushed on the fly,
+		rather than waiting for moby GC.  Also, need to set
+		up compaction of SD freelist, as well as SM freelist.
+		Make SM freelist compact self-invoked by SBM_MGET?
+	Any need for phys disk ptrs other than for tempfile?
+		Can do sbm_forn through SDblks to find active sdfiles
+		so list isn''t needed for that.
+	Can sdback be flushed?  (not needed for keeping list sorted,
+		or for searching it -- only used when linking
+		blocks in or out of list.)  Perhaps use circular list?
+		If list only used for tmpfile, then to link in/out could
+		always start from sfptr1 of tmpfile? Sure, but slow?
+		Last SD on phys list could belong to no logical list,
+		and denote free space on tmpfile?
+
+	--------------------------
+
+	An "open" SBBUFFER will allow one to read, write, insert into,
+and delete from a sbstring (a logical character string).  "Dot" refers
+to the current logical character position, which is where all
+operations must happen; sb_fseek must be used to change this location.
+There are several states that the I/O can be in:
+!SBCUR		----CLOSED----
+		All other elements, including SBIOP, should also be 0.
+		Dot is 0.
+SBCUR && !SBIOP	----OPEN/IDLE----
+		SBCUR points to a SD block (its SDMEM may or may not exist)
+		SBIOP==0 (otherwise it would be open/ready)
+		Dot is SBDOT + SBOFF.
+		R/Wleft must be 0.
+SBCUR && SBIOP	----OPEN/READY----
+		SBCUR points to a SDBLK (SDMEM must exist!)
+		SBIOP exists.
+		Dot is SBDOT + offset into SMBLK.  SBOFF is ignored!
+		SB_WRIT flag is set if "smuse" must be updated.
+		The R/Wleft counts are set up:
+		1. Rleft 0, Wleft 0 -- Since SBIOP is set, must assume
+			counts are too.
+			So this means at end of text, no room left.
+			Otherwise would imply that setup needs doing.
+		2. Rleft N, Wleft 0 -- At beg or middle of text
+		3. Rleft 0, Wleft N -- At end of text
+		4. Rleft N, Wleft N -- Shouldn''t ever happen
+
+		Note that Rleft is always correct.  Wleft is sometimes
+		set 0 in order to force a call to determine real state.
+
+Note that SBIOP alone is a sufficient test for being OPEN/READY.
+
+The important thing about updating the smblk is to ensure that the "smuse"
+field is correct.  This can only be changed by writing or deleting.  We assume
+that deletions always update immediately, thus to determine if an update
+is necessary, see if SB_WRIT is set.  If so, update smuse before doing
+anything but more writing!!!!
+
+The SDBLK must be marked "modified" whenever a write operation is
+done.  We try to do this only the first time, by keeping Wleft zero
+until after the first write.  This is also when SB_WRIT gets set.
+However, if in overwrite mode, Wleft must be kept zero in order to
+force the proper actions; SB_WRIT is also not turned on since smuse
+will not change.  Note that at EOF, overwrite becomes the same thing
+as insert and is treated identically...
+
+	If a SBLK has an in-core copy but no disk copy, it can be
+freely modified.  Otherwise, modifications should preferably split
+the block so as to retain "pure" blocks as long as possible.  "Pure" blocks
+can always have their in-core versions flushed immediately (unless for
+compaction purposes they''ll need to be written out in the same GC pass).
+Alternatively, mods can simply mark the disk copy "free" and go
+ahead as if no such copy existed.
+	No additions or changes to a pure block are allowed, but
+deletions from the end or beginning are always allowed.  All other
+changes must split or insert new blocks to accomplish the changes.
+
+Locking:
+	SDBLKs are subject to unpredictable relocation, compaction,
+and garbage collecting.  There are three ways in which a SDBLK can
+remain fixed:
+
+	1. The SDBLK has the SD_LOCK flag set.  This flag is used whenever
+		a SBBUF''s SBCUR is pointing to this SDBLK.
+	2. The SDBLK has the SD_LCK2 flag set.  This flag is used only
+		during execution of various internal routines and should
+		not be seen anywhere during execution of user code.
+	3. The SDBLK has no back-pointer (is first block in a sbstring).
+		Such SDBLKs cannot be relocated (since it is not known
+		what may be pointing to them) but unlike the other 2 cases
+		they are still subject to compaction with succeeding SDBLKs.
+
+The SDBLK must be locked with SD_LOCK for as long as it is being
+pointed to by SBCUR.  The sole exception is when a SBBUF in the
+OPEN/IDLE state is pointing to the first SDBLK of a sbstring; this
+sdblk is guaranteed not to be moved, since sdblks without a
+back-pointer are never moved.  SD_LOCK is asserted as soon as the state
+changes to OPEN/READY, of course.  The internal routines take pains to
+always move SD_LOCK as appropriate.  Note that only one SD in a
+sbstring can ever have SD_LOCK turned on.  SD_LCK2 is an auxiliary flag
+which may appear in more than one SDBLK, for use by low-level routines
+for various temporary reasons; either will prevent the SDBLK from being
+modified in any way by the storage compactor.
+
+SEEKs are a problem because it''s unclear at seek time what will happen
+next, so the excision of the smblk can''t be optimized.  If the seek
+happens to land in a sdblk with an existing smblk, there''s no problem;
+but if it''s a sdblk alone, how to decide which part of it to read in???
+If next action is:
+	write - split up sdblk and create new one.  Read nothing in.
+	read - read in 512 bytes starting at disk blk boundary if possible
+		else read in 128 bytes starting with selected char
+		(include beg of sdblk if less than 64 chars away)
+	overwrite - as for read.
+	backread - like read but position at end of sdblk.
+	delete - split up sdblk, read nothing in.
+
+We solve this through the OPEN/IDLE state, where SBIOP == 0 means SBOFF
+points to logical offset from start of current sdblk, so that the seek
+need not take any action.  Only when a specific operation is requested
+will the transition to OPEN/READY take place, at which time we''ll know
+what the optimal excision strategy is.  The routine SBX_READY performs
+this function.
+
+The physical links (SDFORW and SDBACK) are only valid when SDFILE is
+set (likewise for SDLEN and SDADDR).  In other words, mungs to a sdblk
+must check SDFILE to see whether or not the phys links should be
+altered.  Normally they aren''t except during sdblk creation, deletion,
+or swapout, no matter how much the sdblk gets shuffled around
+logically.  The disk physical list is kept sorted in order of starting
+addresses.  The text blocks indicated can overlap.  When a GC is
+necessary, the code must figure out how much space is actually free.
+
+-------------- Old woolgathering, ignore rest of this page ---------------
+
+Question: should 512-byte buffers be maintained, one for each SBFILE?
+Or should the in-core text be hacked up to serve for buffering?
+Question is where to point the READ/WRITE system calls.  Currently,
+they are pointed directly at the in-core text, and there are no
+auxiliary buffers.
+
+If use auxiliary buffers:
+	How to handle flushing, when changing location etc?
+	Could be clever about reading from large disk block, only
+	get part of it into buffer instead of splitting up in order to
+	read a "whole" block.
+	Problem: sbstrings can include pieces of several different files.
+		Hard to maintain just one buffer per FD without hacking
+		done on one sbstring screwing that on another.
+If don''t use buffers:
+	Need to have a "chars-left" field in mem blocks, so know how
+	much more can be added.  Will need heuristics for how much
+	extra space to allocate.
+#endif /*COMMENT*/
+
+
+/* Includes, initial definitions */
+
+#include <stdio.h>
+#include "sb.h"
+
+#ifndef V6
+#define V6 0
+#endif
+
+#if V6
+#include <stat.h>
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#if MINIX
+#include <fcntl.h>	/* For open() flags */
+#else
+#include <sys/file.h>	/* For open() flags */
+#endif /* MINIX */
+#endif /*-V6*/
+
+extern int errno;
+extern char *strerror();	/* From ANSI <string.h> */
+
+/* Allocation decls */
+SBFILE sbv_tf;		/* SBFILE for temp swapout file */
+int (*sbv_debug)();	/* Error handler address */
+
+
+/* SBX_READY argument flags (internal to SBSTR routines only)
+ * The following values should all be unique; the exact value
+ * doesn't matter as long as the right SKM flags are given.
+ */
+#define SK_READF 0			/* 0-skip fwd,  align BOB */
+#define SK_READB (0|SKM_0BACK|SKM_EOB)	/* 0-skip bkwd, align EOB */
+#define SK_WRITEF (0|SKM_EOB)		/* 0-skip fwd,  align EOB */
+#define SK_DELF (4|SKM_0BACK)		/* 0-skip bkwd, align BOB */
+#define SK_DELB (4|SKM_EOB)		/* 0-skip fwd,  align EOB */
+#define SKM_0BACK 01	/* Zero-skip direction: 0 = fwd, set = backwd
+			 * Don't ever change this value! See SBX_NORM. */
+#define SKM_EOB	  02	/* Alignment: 0 = Beg-Of-Buf, set = End-Of-Buf */
+
+/* Note on routine names:
+ *	"SB_" 	User callable, deals with sbbufs (usually).
+ *	"SBS_"	User callable, deals with sbstrings only.
+ *	"SBX_"	Internal routine, not meant for external use.
+ *	"SBM_"	Routine handling mem alloc, usually user callable.
+ */
+
+
+/* SBBUF Opening, Closing, Mode setting */
+
+/* SB_OPEN(sb,sd) - Sets up SBBUF given pointer to first SD of a sbstring.
+ * 	If SD == 0 then creates null sbstring.
+ *	Any previous contents of SBBUF are totally ignored!!!  If you
+ *		want to save the stuff, use SB_UNSET.
+ *	Sets I/O ptr to start of sbstring.
+ *	Returns 0 if error, else the given SB.
+ */
+SBBUF *
+sb_open(sbp,sdp)
+SBBUF *sbp;
+SBSTR *sdp;
+{	register struct sdblk *sd;
+	register int cnt;
+	register WORD *clrp;
+
+	if(!sbp) return((SBBUF *)0);
+	if((sd = sdp) == 0)
+	  {	sd = sbx_ndget();	/* Get a fresh node */
+		clrp = (WORD *) sd;	/* Clear it all */
+		cnt = rnddiv(sizeof(struct sdblk));
+		do { *clrp++ = 0; } while(--cnt);
+		sd->sdflags = SD_NID;	/* Except flags of course */
+	  }
+	else if(sd->slback)		/* Must be first thing in sbstring */
+		return((SBBUF *)0);		/* Perhaps could normalize tho */
+
+	clrp = (WORD *) sbp;		/* Clear sbbuffer stuff */
+	cnt = rnddiv(sizeof(SBBUF));
+	do { *clrp++ = 0; } while(--cnt);
+
+	sbp->sbcur = sd;
+	/* Note that SD_LOCK need not be set, because first SDBLK has no
+	 * backptr.  This is desirable to allow storage compactor maximum
+	 * freedom in merging sdblks.
+	 */
+	/*	sd->sdflags |= SD_LOCK; */	/* Lock this one */
+	return(sbp);
+}
+
+
+/* SB_CLOSE(sb)	- Close a SBBUF.
+ *	Returns pointer to start of sbstring (first SD).
+ *	Returns 0 if error.
+ */
+SBSTR *
+sb_close(sbp)
+SBBUF *sbp;
+{	register SBBUF *sb;
+	register struct sdblk *sd;
+
+	if((sb = sbp) == 0)	/* Verify pointer */
+		return((SBSTR *)0);
+	sb_rewind(sb);		/* Do most of the work, including unlock */
+	sd = sb->sbcur;		/* Save ptr to sbstring */
+	sb->sbcur = 0;		/* Now reset the sbbuffer structure */
+	sb->sbflags = 0;
+	return(sd);
+}
+
+
+/* SB_SETOVW(sbp) - Set SBBUF Over-write mode for PUTC's.
+ * SB_CLROVW(sbp) - Clear ditto.
+ */
+sb_setovw(sbp)
+SBBUF *sbp;
+{	register SBBUF *sb;
+	if(sb=sbp)
+	  {	sb->sbflags |= SB_OVW;
+		sb->sbwleft = 0;
+	  }
+}
+
+sb_clrovw(sbp)
+SBBUF *sbp;
+{	register SBBUF *sb;
+	if(sb=sbp) sb->sbflags &= ~SB_OVW;
+}
+
+
+/* SBSTRING file system operations (see also sb_fsave) */
+
+/* SB_FDUSE(fd) - Make a sbstring for given file.
+ * 	FD is an open file descriptor.
+ *	Returns pointer to a SBSTR containing the given file, or 0 if error.
+ *	The FD must not be closed until a SB_FDCLS is done to
+ *	purge memory of any blocks pointing at the file.
+ * ** Maybe allocate sbfile structs with sbx_ndget, i.e. overlay on
+ * ** top of sdblk node??  Wd this screw verify, GC, etc? Maybe not if
+ * ** SD_LCK2 set...
+ */
+
+struct sbfile *sbv_ftab[SB_NFILES];
+
+chroff
+sbx_fdlen(fd)
+int fd;
+{
+#if !V6
+	struct stat statb;
+#else
+	struct statb statb;
+	chroff len;
+	struct {int hiwd ; int lowd;} foo;
+#endif /*V6*/
+
+	if(fstat(fd,&statb) < 0) return((chroff)-1);
+#if V6
+	len = statb.i_size1;
+	len.hiwd = statb.i_size0 & 0377;
+	return(len);
+#else
+	return((chroff)statb.st_size);
+#endif /*-V6*/
+}
+
+SBSTR *
+sb_fduse(ifd)
+int ifd;
+{	register struct sdblk *sd;
+	register struct sbfile *sf;
+	register int fd;
+	chroff len;
+
+	if((fd = ifd) < 0 || SB_NFILES <= fd	/* Check for absurd FD */
+	  || sbv_ftab[fd])			/* and slot already in use */
+		return((SBSTR *)0);
+	if((len = sbx_fdlen(fd)) < 0) return((SBSTR *)0);
+	sbv_ftab[fd]= sf = (struct sbfile *)sbx_malloc(sizeof(struct sbfile));
+	sf->sffd = fd;
+	sf->sfptr1 = sd = sbx_ndget();
+	sf->sflen = len;
+	sd->slforw = 0;
+	sd->slback = 0;
+	sd->sdforw = 0;
+	sd->sdback = 0;
+	sd->sdmem = 0;
+	sd->sdfile = sf;
+	sd->sdlen = len;
+	sd->sdaddr = 0;
+	return(sd);
+}
+
+/* SB_FDCLS(fd) - Close a file descriptor being used by sbstrings.
+ *	If arg is -1, closes all FD's that are unused (a "sweep").
+ *	For specific arg, returns 0 if couldn't close FD because still in use.
+ *	Perhaps later version of routine could have option to copy
+ *	still-used SD's to tempfile, and force the FD closed?
+ */
+sb_fdcls(ifd)
+int ifd;
+{	register int fd;
+
+	if((fd = ifd) >= 0)
+	  {	if(fd >= SB_NFILES) return(0);	/* Error of sorts */
+		return(sbx_fcls(sbv_ftab[fd]));
+	  }
+	fd = SB_NFILES-1;
+	do {
+		sbx_fcls(sbv_ftab[fd]);
+	  } while(--fd);	/* Doesn't try FD 0 ! */
+	return(1);
+}
+
+sbx_fcls(sfp)
+struct sbfile *sfp;
+{	register struct sbfile *sf;
+	register int fd;
+
+	if((sf = sfp)==0		/* Ignore null args */
+	  || sf == &sbv_tf)		/* and never close our tempfile! */
+		return(0);
+	fd = sf->sffd;			/* Find sys file descriptor */
+	if(sbv_ftab[fd] != sf)		/* Ensure consistency */
+		return(sbx_err(0,"SF table inconsistency"));
+	if(sf->sfptr1)			/* Any phys list still exists? */
+		return(0);		/* Yes, still in use, can't close */
+	close(fd);			/* Maybe do this when list gone? */
+	sbv_ftab[fd] = 0;		/* Remove from table */
+	free(sf);			/* Remove sbfile struct from mem */
+}
+
+/* SB_FDINP(sb,fd) - Returns TRUE if specified fd is still in use
+ *	by specified sbbuffer.
+ */
+sb_fdinp(sb, fd)
+register SBBUF *sb;
+int fd;
+{	register struct sdblk *sd;
+	register struct sbfile *sf;
+
+	if((sf = sbv_ftab[fd]) == 0
+	  || (sd = sb->sbcur) == 0)
+		return(0);
+	sd = sbx_beg(sd);		/* Move to beginning of sbstring */
+	for(; sd; sd = sd->slforw)	/* Scan thru all blocks in string */
+		if(sd->sdfile == sf)	/* If any of them match, */
+			return(1);	/* Return tally-ho */
+	return(0); 
+}
+
+/* SB_FSAVE(sb,fd) - Write entire SBBUF out to specified FD.
+ *	Returns 0 if successful, else system call error number.
+ */
+sb_fsave(sb,fd)		/* Write all of given sbbuf to given fd */
+register SBBUF *sb;
+int fd;
+{
+	sbx_smdisc(sb);
+	return(sbx_aout(sbx_beg(sb->sbcur), 2, fd));
+}
+
+
+/* SBBUF Character Operations */
+
+/* SB_GETC(sb) - Get next char from sbstring.
+ *	Returns char at current location and advances I/O ptr.
+ *	Returns EOF on error or end-of-string.
+ */
+int
+sb_sgetc(sb)
+register SBBUF *sb;
+{
+	if(--(sb->sbrleft) >= 0)
+		return sb_uchartoint(*sb->sbiop++);
+
+	/* Must do hard stuff -- check ptrs, get next blk */
+	sb->sbrleft = 0;			/* Reset cnt to zero */
+	if(sb->sbcur == 0			/* Make sure sbbuffer there */
+	  || (int)sbx_ready(sb,SK_READF,0,SB_BUFSIZ) <= 0)  /* Normalize & gobble */
+		return(EOF);
+	return(sb_sgetc(sb));			/* Try again */
+}	/* Loop wd be faster, but PDL OV will catch infinite-loop bugs */
+
+
+/* SB_PUTC(sb,ch) - Put char into sbstring.
+ *	Inserts char at current location.
+ *	Returns EOF on error, else the char value.
+ */
+int
+sb_sputc(sb,ch)
+register SBBUF *sb;
+int ch;
+{
+	register struct sdblk *sd;
+
+	if(--(sb->sbwleft) >= 0) return(*sb->sbiop++ = ch);
+
+	sb->sbwleft = 0;		/* Reset cnt to avoid overflow */
+	if((sd = sb->sbcur) == 0)	/* Verify string is there */
+		return(EOF);		/* Could perhaps create it?? */
+	if(sb->sbflags&SB_OVW)		/* If overwriting, handle std case */
+	  {	if(sb->sbiop &&
+		  --sb->sbrleft >= 0)		/* Use this for real count */
+		  {	sd->sdflags |= SD_MOD;	/* Win, munging... */
+			return(*sb->sbiop++ = ch);
+		  }
+		/* Overwriting and hit end of this block. */
+		if((int)sbx_ready(sb,SK_READF,0,SB_BUFSIZ) > 0) /* Re-normalize */
+			return(sb_sputc(sb,ch));
+
+		/*  No blks left, fall through to insert stuff at end */
+	  }
+
+	/* Do canonical setup with heavy artillery */
+	if((int)sbx_ready(sb,SK_WRITEF,SB_SLOP,SB_BUFSIZ) <= 0)	/* Get room */
+		return(EOF);		/* Should never happen, but... */
+	sb->sbflags |= SB_WRIT;
+	sb->sbcur->sdflags |= SD_MOD;
+	return(sb_sputc(sb,ch));	/* Try again */
+}	/* Loop wd be faster, but PDL OV will catch infinite-loop bugs */
+
+
+/* SB_PEEKC(sb) - Peek at next char from sbstring.
+ *	Returns char that sb_getc would next return, but without
+ *	changing I/O ptr.
+ *	Returns EOF on error or end-of-string.
+ */
+int
+sb_speekc(sb)
+register SBBUF *sb;
+{
+	if (sb->sbrleft <= 0)			/* See if OK to read */
+	  {	if (sb_sgetc(sb) == EOF)	/* No, try hard to get next */
+			return EOF;		/* Failed, return EOF */
+		sb_backc(sb);			/* Won, back up */
+	  }
+	return sb_uchartoint(*sb->sbiop);
+}
+
+/* SB_RGETC(sb) - Get previous char from sbstring.
+ *	Returns char prior to current location and backs up I/O ptr.
+ *	Returns EOF on error or beginning-of-string.
+ */
+int
+sb_rgetc(sb)
+register SBBUF *sb;
+{
+	register struct smblk *sm;
+	register struct sdblk *sd;
+
+	if((sd=sb->sbcur) && (sm = sd->sdmem)
+	  && sb->sbiop > sm->smaddr)
+	  {	if(sb->sbflags&SB_WRIT)
+		  {	sm->smuse = sb->sbiop - sm->smaddr;
+			sb->sbwleft = 0;
+			sb->sbflags &= ~SB_WRIT;
+		  }
+		sb->sbrleft++;
+		return sb_uchartoint(*--sb->sbiop);	/* Return char */ 
+	  }
+	if((int)sbx_ready(sb,SK_READB,SB_BUFSIZ,0) <= 0)
+		return(EOF);
+	return(sb_rgetc(sb));
+}
+
+/* SB_RDELC(sb) - Delete backwards one char.
+ *	Returns nothing.
+ */
+sb_rdelc(sbp)
+SBBUF *sbp;
+{	register SBBUF *sb;
+	register struct sdblk *sd;
+
+	if(((sb=sbp)->sbflags&SB_WRIT)	/* Handle simple case fast */
+	  && sb->sbiop > (sd = sb->sbcur)->sdmem->smaddr)
+		  {	sb->sbwleft++;
+			sb->sbiop--;
+			sd->sdflags |= SD_MOD;
+			return;
+		  }
+	else sb_deln(sb,(chroff) -1);	/* Else punt... */
+}
+
+/* SB_DELC(sb) - Delete one char forward? */
+/* SB_INSC(sb,ch) - Insert char?  (instead of or in addition to PUTC) */
+
+
+
+/* SBBUF string or N-char operations */
+
+/* SB_DELN(sb,chroff) - delete N chars.  Negative N means backwards.
+ *	Differs from sb_killn in that it flushes the text forever,
+ *	and doesn't return anything.
+ */
+
+sb_deln(sbp, num)
+SBBUF *sbp;
+chroff num;
+{
+	register struct sdblk *sd;
+
+	if(sd = sb_killn(sbp,num))
+		sbs_del(sd);	/* Punt */
+}
+
+/* SB_KILLN(sb,chroff) - delete N chars, saving.  Negative N means backwards.
+ *	Returns SD pointer to beginning of saved sbstring.
+ */
+struct sdblk *
+sb_killn(sbp, num)
+SBBUF *sbp;
+chroff num;
+{	register SBBUF *sb;
+	register struct sdblk *sd, *sd2;
+	struct sdblk *sdr, *sdx;
+	chroff savdot;
+
+	if((sd = sbx_xcis((sb=sbp),num,&sdr,&savdot)) == 0)
+		return((struct sdblk *)0);
+
+	sb->sbcur->sdflags &= ~SD_LOCK;	/* Now can flush sbcur lock */
+
+	/* SD and SD2 now delimit bounds of stuff to excise.
+	 * First do direction dependent fixups
+	 */
+	if(num >= 0)			/* If deleting forward, */
+		sb->sbdot = savdot;	/* must reset dot to initial loc */
+
+	/* SD and SD2 now in first/last order.  Complete SBCUR fixup. */
+	sd2 = sdr;			/* sdr has ptr to end of stuff */
+	if(sd2 = sd2->slforw)		/* More stuff after killed list? */
+	  {	sb->sbcur = sd2;	/* Yes, point at it */
+		sb->sboff = 0;		/* Dot already set right */
+	  }
+	else if(sdx = sd->slback)	/* See if any prior to killed list */
+	  {	sb->sbcur = sdx;		/* Yes, point at it */
+		sb->sboff = (sdx->sdmem ?	/* Get len of prev blk */
+			sdx->sdmem->smuse : sdx->sdlen);
+		sb->sbdot -= sb->sboff;
+	  }
+	else sb_open(sb,(SBSTR *)0);	/* No stuff left!  Create null sbstring */
+
+	/* Fix up logical links.  Note SD2 points to succ of killed stuff */
+	if(sd->slback)			/* If previous exists */
+	  {	if(sd->slback->slforw = sd2)	/* Point it to succ, and */
+			sd2->slback = sd->slback; /* thence to self */
+		sd->slback = 0;			/* Now init killed list */
+	  }
+	else if(sd2) sd2->slback = 0;		/* No prev, clean rest */
+	(sd2 = sdr)->slforw = 0;		/* Finish killed list */
+
+	sb->sbcur->sdflags |= SD_LOCK;	/* Ensure current SD now locked */
+	sd->sdflags &= ~SD_LCK2;	/* And unlock killed list */
+	sd2->sdflags &= ~SD_LCK2;
+	return(sd);
+}
+
+/* SB_CPYN(sbp,num) - Copy num characters, returns SD to sbstring.
+ *	Like SB_KILLN but doesn't take chars out of original sbstring.
+ */
+SBSTR *
+sb_cpyn(sbp,num)
+SBBUF *sbp;
+chroff num;
+{	register SBBUF *sb;
+	register struct sdblk *sd, *sd2;
+	struct sdblk *sdr;
+	chroff savloc;
+
+	sb = sbp;
+	if((sd = sbx_xcis(sb,num,&sdr,&savloc)) == 0)
+		return((SBSTR *)0);
+	sd2 = sbx_scpy(sd,sdr);
+	sb_seek(sb,-num,1);		/* Return to original loc */
+	return(sd2);		/* Return val is ptr to head of copy.
+				 * It needn't be locked, because GC will
+				 * never move list heads!
+				 */
+}
+
+/* SB_SINS(sb,sd) - Insert sbstring at current location
+ *
+ */
+sb_sins(sbp,sdp)
+SBBUF *sbp;
+struct sdblk *sdp;
+{	register SBBUF *sb;
+	register struct sdblk *sd, *sdx;
+	chroff inslen;
+
+	if((sb = sbp)==0
+	  || (sd = sdp) == 0)
+		return(0);
+	if(sd->slback)		/* Perhaps normalize to beg? */
+		return(0);
+	if((sdx = (struct sdblk *)sbx_ready(sb,SK_DELB)) == 0)	/* Get cur pos ready */
+		return(0);
+	inslen = sbs_len(sd);		/* Save length of inserted stuff */
+
+	sd->slback = sdx;		/* Fix up links */
+	if(sdx->slforw)
+	  {	while(sd->slforw)	/* Hunt for end of inserted sbstring */
+			sd = sd->slforw;
+		sd->slforw = sdx->slforw;
+		sd->slforw->slback = sd;
+	  }
+	sdx->slforw = sdp;
+	sb->sboff += inslen;		/* Set IO ptr to end of new stuff */
+	return(1);
+}
+
+
+/* SBSTRING routines - operate on "bare" sbstrings. */
+
+/* SBS_CPY(sd) - Copies given sbstring, returns ptr to new sbstring.
+ */
+SBSTR *
+sbs_cpy(sdp)
+SBSTR *sdp;
+{	return(sbx_scpy(sdp,(struct sdblk *)0));
+}
+
+/* SBS_DEL(sd) - Flush a sbstring.
+ */
+sbs_del(sdp)
+SBSTR *sdp;
+{	register struct sdblk *sd;
+
+	if(sd = sdp)
+		while(sd = sbx_ndel(sd));
+}
+
+
+/* SBS_APP(sd1,sd2) - Appends sbstring sd2 at end of sbstring sd1.
+ *	Returns sd1 (pointer to new sbstring).
+ */
+
+SBSTR *
+sbs_app(sdp,sdp2)
+struct sdblk *sdp,*sdp2;
+{	register struct sdblk *sd, *sdx;
+
+	if(sd = sdp)
+	  {	while(sdx = sd->slforw)
+			sd = sdx;
+		if(sd->slforw = sdx = sdp2)
+			sdx->slback = sd;
+	  }
+	return(sdp);
+}
+
+/* SBS_LEN(sd) - Find length of sbstring.
+ */
+chroff
+sbs_len(sdp)
+SBSTR *sdp;
+{	register struct sdblk *sd;
+	register struct smblk *sm;
+	chroff len;
+
+	if((sd = sdp)==0) return((chroff)0);
+	len = 0;
+	for(; sd ; sd = sd->slforw)
+	  {	if(sm = sd->sdmem)
+			len += (chroff)sm->smuse;
+		else len += sd->sdlen;
+	  }
+	return(len);
+}
+
+
+/* SBBUF I/O pointer ("dot") routines */
+
+/* SB_SEEK(sb,chroff,flag) - Like FSEEK.  Changes I/O ptr value as
+ *	indicated by "flag":
+ * 		0 - offset from beg
+ *		1 - offset from current pos
+ *		2 - offset from EOF
+ *	Returns -1 on errors.
+ *	Seeking beyond beginning or end of sbbuf will leave pointer
+ *	at the beginning or end respectively.
+ *	Returns 0 unless error (then returns -1).
+ */
+sb_seek(sbp, coff, flg)
+SBBUF *sbp;
+chroff coff;
+int flg;
+{	register SBBUF *sb;
+	register struct smblk *sm;
+	register struct sdblk *sd;
+	SBMO moff;
+
+	sb = sbp;
+	if((sd = sb->sbcur) == 0) return(-1);
+	if(sb->sbiop == 0)
+	  {	switch(flg)
+		  {	case 0:	if(coff == 0)	/* Optimize common case */
+					return(sb_rewind(sb));
+				sb->sboff = coff - sb->sbdot;	/* Abs */
+				break;
+			case 1:	sb->sboff += coff;		/* Rel */
+				break;
+			case 2:	sb->sboff += sb_ztell(sb) + coff;
+				break;
+			default: return(-1);
+		  }
+		sbx_norm(sb,0);
+		return(0);
+	  }
+	if((sm = sd->sdmem) == 0)
+		return(sbx_err(-1,"SDMEM 0"));
+	moff = sb->sbiop - sm->smaddr;	/* Get cur smblk offset */
+	if(sb->sbflags&SB_WRIT)		/* Update since moving out */
+	  {	sm->smuse = moff;
+		sb->sbflags &= ~SB_WRIT;
+	  }
+	sb->sbwleft = 0;		/* Always gets zapped */
+	switch(flg)
+	  {	case 0:		/* Offset from beginning */
+			coff -= sb->sbdot + (chroff)moff; /* Make rel */
+
+		case 1:		/* Offset from current loc */
+			break;
+
+		case 2:		/* Offset from end */
+			coff += sb_ztell(sb);
+			break;
+		default: return(-1);
+	  }
+
+	/* COFF now has relative offset from current location */
+	if (-(chroff)moff <= coff && coff <= sb->sbrleft)
+	  {				/* Win! Handle repos-within-smblk */
+		sb->sbiop += coff;
+		sb->sbrleft -= coff;	/* Set r; wleft already 0 */
+		return(0);
+	  }
+
+	/* Come here when moving to a different sdblk. */
+	sb->sbrleft = 0;
+	sb->sbiop = 0;
+	sb->sboff = coff + (chroff)moff;
+	sbx_norm(sb,0);
+	return(0);
+}
+
+/* SB_REWIND(sb) - Go to beginning of sbbuffer.
+ *	Much faster than using sb_seek.  Note that this leaves the sbbuffer
+ *	in an open/idle state which is maximally easy to compact.
+ */
+sb_rewind(sbp)
+SBBUF *sbp;
+{	register SBBUF *sb;
+	register struct sdblk *sd;
+
+	if((sb = sbp)==0) return;
+	sbx_smdisc(sb);			/* Ensure I/O disconnected */
+	(sd = sb->sbcur)->sdflags &= ~SD_LOCK;	/* Unlock current blk */
+	sd = sbx_beg(sd);		/* Move to beg of sbstring */
+	/* Need not lock - see sb_open comments, also sb_close */
+	/*	sd->sdflags |= SD_LOCK; */	/* Lock onto this one */
+	sb->sbcur = sd;
+	sb->sbdot = 0;
+	sb->sboff = 0;
+}
+
+/* SB_TELL(sb) - Get I/O ptr value for SBBUF.
+ *	Returns -1 on errors.
+ */
+
+chroff
+sb_tell(sbp)
+SBBUF *sbp;
+{	register SBBUF *sb;
+	register struct smblk *sm;
+	register struct sdblk *sd;
+
+	if((sd = (sb=sbp)->sbcur) == 0)
+		return((chroff)-1);
+	if(sb->sbiop == 0)
+		return(sb->sbdot + sb->sboff);
+	if((sm = sd->sdmem) == 0)
+		return(sbx_err(0,"SDMEM 0"));
+	return(sb->sbdot + (unsigned)(sb->sbiop - sm->smaddr));
+}
+
+/* SB_ZTELL(sb) - Get I/O ptr relative to "Z" (EOF).
+ *	Returns # chars from current location to EOF; 0 if any errors.
+ */
+chroff
+sb_ztell(sbp)
+SBBUF *sbp;
+{	register SBBUF *sb;
+	register struct smblk *sm;
+	register struct sdblk *sd;
+
+	if((sd = (sb=sbp)->sbcur) == 0)
+		return((chroff)0);
+	if(sb->sbiop && (sm = sd->sdmem))
+	  {	if(sb->sbflags&SB_WRIT)		/* If actively writing, */
+			return(sbs_len(sd->slforw));	/* ignore this blk. */
+			/* Note that previous code makes it unnecessary
+			 * to invoke sbx_smdisc.  (otherwise wrong
+			 * smuse would confuse sbs_len).
+			 */
+		return(sbs_len(sd) - (sb->sbiop - sm->smaddr));
+	  }
+	else
+		return(sbs_len(sd) - sb->sboff);
+}
+
+
+/* Code past this point should insofar as possible be INTERNAL. */
+
+/* SBX_READY(sb,type,cmin,cmax) - Set up SBBUF for reading or writing.
+ *
+ * If no current smblk:
+ *	reading - set up for reading
+ *	writing - set up for splitting?
+ * If current smblk:
+ *	reading - if can read, OK.  Else position at beg of next sdblk
+ *	writing - if can write, OK.  Else position at end of prev sdblk,
+ *		or set up for splitting?
+ * Types:
+ *	0 - Read forward (BOB)
+ *	1 - Read backward (EOB)
+ *	3 - Write (insert forward) (EOB)
+ *	4 - Delete forward (return SD, force BOB-aligned)
+ *	5 - Delete backward (return SD, force EOB-aligned)
+ * Connected SD is always locked.
+ * Returns 0 if error, -1 if EOF-type error, 1 for success.
+ *
+ * For types 0,1:
+ *	CMIN,CMAX represent max # chars to read in to left and right of
+ *		I/O ptr (prev and post).  Actual amount read in may be
+ *		much less, but will never be zero.
+ *	Successful return guarantees that SBIOP etc. are ready.
+ * For type 3:
+ *	If new block is allocated, CMIN and CMAX represent min, max sizes
+ *		of the block.
+ *	Successful return guarantees that SBIOP etc. are ready, but
+ *	NOTE that SB_WRIT and SD_MOD are not set!  If not going to use
+ *	for writing, be sure to clear sbwleft on return!
+ * For types 4,5:
+ *	CMIN, CMAX are ignored.
+ *	SBIOP is always cleared.  SBOFF is guaranteed to be 0 for
+ *	type 4, SMUSE for type 5.
+ *	Return value is a SD ptr; 0 indicates error.  -1 isn't used.
+ */
+
+struct sdblk *
+sbx_ready(sbp,type,cmin,cmax)
+SBBUF *sbp;
+int type;
+SBMO cmin,cmax;
+{	register SBBUF *sb;
+	register struct sdblk *sd;
+	register struct smblk *sm;
+	int cnt, slop, rem;
+	SBMO moff;
+
+	if((sd = (sb=sbp)->sbcur) == 0)
+		return(0);
+	if(sb->sbiop)		/* Canonicalize for given operation */
+	  {	if((sm = sd->sdmem)==0)
+			return(0);
+		moff = sb->sbiop - sm->smaddr;	/* Current block offset */
+	  switch(type)
+	  {
+	case SK_READF:		/* Read Forward */
+		if(sb->sbrleft > 0)	/* Already set up? */
+			return(1);	/* Yup, fast return */
+		sbx_smdisc(sb);		/* None left, disc to get next */
+		if((sd = sbx_next(sb)) == 0)	/* Try to get next blk */
+			return(-1);	/* At EOF */
+		break;
+
+	case SK_READB:		/* Read Backward */
+		if(moff)		/* Stuff there to read? */
+		  {	if(sb->sbflags&SB_WRIT)	/* Yup, turn writes off */
+			  {	sm->smuse = moff;
+				sb->sbflags &= ~SB_WRIT;
+			  }
+			sb->sbwleft = 0;
+			return(1);
+		  }
+		sbx_smdisc(sb);
+		break;
+
+	case SK_WRITEF:		/* Writing */
+		if(sb->sbrleft <= 0)
+			sb->sbwleft = sm->smlen - moff;
+		if(sb->sbwleft > 0)
+			return(1);	/* OK to write now */
+					/* NOTE: flags not set!!! */
+		sbx_smdisc(sb);
+		break;
+
+	case SK_DELF:		/* Delete forward - force BOB */
+		if(sb->sbrleft <= 0)		/* At end of blk? */
+		  {	sbx_smdisc(sb);		/* Win, unhook */
+			return(sbx_next(sb));   /* Return next or 0 if EOF */
+		  }
+		sbx_smdisc(sb);			/* Not at end, but see if */
+		if(moff == 0)			/* at beg of blk? */
+			return(sd);	/* Fast win! */
+		break;
+
+	case SK_DELB:		/* Delete backward - force EOB */
+		if(sb->sbrleft <= 0)		/* Win if already EOB */
+		  {	sbx_smdisc(sb);
+			return(sd);
+		  }
+		sbx_smdisc(sb);
+		break;
+
+	default:
+		return(0);
+	  }
+	  }
+
+	/* Schnarf in the text, or whatever.
+	 * SD points to current sdblk (must be SD_LOCKed)
+	 * SBDOT must have correct value for this SD
+	 * SBOFF has offset from there to put I/O ptr at.
+	 *
+	 * After normalization, SBOFF is guaranteed to point within
+	 * the SD.  Other guarantees apply to boundary cases, depending
+	 * on the mode (type) bits.
+	 */
+	sd = sbx_norm(sb,type);	/* Normalize I/O pos appropriately */
+	sm = sd->sdmem;
+	switch(type)
+	  {
+	case SK_READB:		/* Read Backward */
+		if(sb->sboff == 0)	/* Due to normalize, if 0 seen */
+			return(-1);	/* then we know it's BOF */
+		if(sm) goto sekr2;
+		else goto sekr1;
+
+	case SK_READF:		/* Read Forward */
+		if(sm) goto sekr2;
+		if(sb->sboff == sd->sdlen)	/* Normalize means if EOB */
+			return(-1);		/* then at EOF. */
+	sekr1:	slop = SB_SLOP;
+	sekr3:	if(sb->sboff > cmin+slop)	/* Too much leading text? */
+		  {				/* Split off leading txt */
+			sbx_split(sd,(chroff)(sb->sboff - cmin));
+			sd = sbx_next(sb);	/* Point to next sdblk */
+			sb->sboff = cmin;	/* Set correct offset */
+						/* (sbx_next assumes 0) */
+		  }
+		if(sd->sdlen > sb->sboff+cmax+slop) /* Too much trailing txt? */
+			sbx_split(sd,(chroff)(sb->sboff+cmax));
+
+		/* ----- Try to get mem blk to read stuff into ----- */
+		/* Note alignment hack for extra efficiency.  This ensures
+		 * that all reads from disk to memory are made with the same
+		 * source and destination word alignment, so the system kernel
+		 * only needs byte-moves for the first or last bytes; all
+		 * others can be word-moves.
+		 * This works because sbx_mget always returns word-aligned
+		 * storage, and we use sbx_msplit to trim off the right number
+		 * of bytes from the start.
+		 */
+		cnt = sd->sdlen;		/* Get # bytes we'd like */
+		if(rem = rndrem(sd->sdaddr))	/* If disk not word-aligned */
+			cnt += rem;		/* allow extra for aligning.*/
+		if(sm == 0)			/* Always true 1st time */
+		  {	sm = sbx_mget(SB_SLOP,cnt); /* Get room (may GC!)*/
+			if(sm->smlen < cnt)	/* Got what we wanted? */
+			  {	slop = 0;	/* NO!!	 Impose stricter */
+				cmin = 0;	/* limits.  Allow for new */
+				cmax = sm->smlen - (WDSIZE-1); /* rem. */
+				if(type == SK_READB)
+				  {	cmin = cmax; cmax = 0; }
+				goto sekr3;	/* Go try again, sigh. */
+			  }
+		  }
+		else if(sm->smlen < cnt)	/* 2nd time shd always win */
+		  {	sbx_err(0,"Readin blksiz err");	/* Internal error, */
+			if((cmax /= 2) > 0) goto sekr3;	/* w/crude recovery */
+			return(0);
+		  }
+		if(rem)		/* If disk not word-aligned, hack stuff */
+		  {	sm = sbx_msplit(sm, (SBMO)rem);	/* Trim off from beg*/
+			sbm_mfree(sm->smback);		/* Free the excess */
+		  }
+		sd->sdmem = sm;
+		sm->smuse = sd->sdlen;
+
+		if(sd->sdfile == 0)
+			return(sbx_err(0,"No file"));	/* Gasp? */
+		if(!sbx_rdf(sd->sdfile->sffd, sm->smaddr, sm->smuse,
+				1, sd->sdaddr))
+			return(sbx_err(0,"Readin SD: %o", sd));
+		/* ------- */
+
+	sekr2:	sbx_sbrdy(sb);		/* Make it current, pt to beg */
+		sb->sbwleft = 0;	/* Ensure not set (esp if READB) */
+		break;
+
+	case SK_WRITEF:		/* Write-type seek */
+		if(sm == 0)
+		  {	/* Block is on disk, so always split (avoid readin) */
+			if(sd->sdlen)			/* May be empty */
+			  {	sbx_split(sd, sb->sboff); /* Split at IO ptr */
+				sd = sbx_next(sb);	/* Move to 2nd part */
+				if(sd->sdlen)		/* If stuff there, */
+							/* split it again. */
+					sbx_split(sd, (chroff) 0);
+			  }
+			goto sekwget;
+		  }
+
+		/* Block in memory */
+		moff = sm->smuse;
+		if(sb->sboff == moff)		/* At end of the block? */
+		  {	if(sm->smlen > moff)	/* Yes, have room? */
+				goto sekw;	/* Win, go setup and ret */
+			if(sm->smforw			/* If next mem blk */
+			  && (sm->smforw->smflags	/* Can have bytes */
+				& (SM_USE|SM_NXM))==0	/* stolen from it */
+			  && (sd->sdflags&SD_MOD)	/* and we ain't pure*/
+			  && sm->smlen < cmax)		/* and not too big */
+			  {	/* Then steal some core!!  Note that without
+				 * the size test, a stream of putc's could
+				 * create a monster block gobbling all mem.
+				 */
+				cmin = cmax - sm->smlen;
+				if(cmin&01) cmin++;	/* Ensure wd-align */
+				if(sm->smforw->smlen <= cmin)
+				  {	sbm_mmrg(sm);
+					goto sekw;
+				  }
+				sm->smforw->smlen -= cmin;
+				sm->smforw->smaddr += cmin;
+				sm->smlen += cmin;
+				goto sekw;
+			  }
+			/* Last try... check next logical blk for room */
+			if(sd->slforw && (sm = sd->slforw->sdmem)
+			  && sm->smuse == 0
+			  && sm->smlen)
+			  {	sd = sbx_next(sb);	/* Yup, go there */
+				goto sekw;
+			  }
+		  }
+
+		/* Middle of block, split up to insert */
+		sbx_split(sd, sb->sboff);	/* Split at IO ptr */
+		if(sd->sdmem)			/* Unless blk now empty, */
+		  {	sd = sbx_next(sb);	/* move to next. */
+			if(sd->sdmem)		/* If not empty either */
+			  sbx_split(sd, (chroff) 0);	/* Split again */
+		  }
+
+		/* Have empty SD block, get some mem for it */
+  sekwget:	sd->sdmem = sm = sbx_mget(cmin,cmax);
+		sm->smuse = 0;
+   sekw:	sbx_sbrdy(sb);		/* Sets up sbwleft... */
+		return(1);
+
+	case SK_DELF:		/* Delete forward */
+		if(sb->sboff == 0)	/* At block beg already? */
+			return(sd);	/* Win, return it */
+		sbx_split(sd, sb->sboff);	/* No, split up and */
+		return(sbx_next(sb));	/* return ptr to 2nd part */
+
+	case SK_DELB:		/* Delete backward (force EOB align) */
+		if(sb->sboff !=		/* If not at EOB already, */
+		  (sm ? (chroff)(sm->smuse) : sd->sdlen))
+			sbx_split(sd, sb->sboff);	/* Then split */
+		return(sd);	/* And return ptr to 1st part */
+		break;
+
+	default:
+		return(0);
+	  }	/* End of switch */
+	return(1);
+}
+
+struct sdblk *
+sbx_next (sbp)
+SBBUF *sbp;
+{	register SBBUF *sb;
+	register struct sdblk *sd, *sdf;
+	if((sdf = (sd = (sb=sbp)->sbcur)->slforw) == 0)
+		return((struct sdblk *)0);
+	sb->sbdot += (sd->sdmem ? (chroff)sd->sdmem->smuse : sd->sdlen);
+	sb->sboff = 0;
+	sd->sdflags &= ~SD_LOCK;	/* Unlock current */
+	sdf->sdflags |= SD_LOCK;	/* Lock next */
+	sb->sbcur = sdf;
+	return(sdf);
+}
+
+
+/* SBX_NORM(sb,mode) - Normalizes I/O position as desired.
+ *	The SBBUF must have I/O disconnected (SBIOP==0).
+ *	Adjusts SBCUR, SBDOT, and SBOFF so that SBOFF is guaranteed
+ *	to point to a location in the current SD block.
+ *	The mode flags determine action when there is more than
+ *	one possible SD that could be pointed to, as is the case
+ *	when the I/O pos falls on a block boundary (possibly with
+ *	adjacent zero-length blocks as well).
+ *	SKM_0BACK - Zero-skip direction.
+ *		  0 = Skip forward over zero-length blocks.
+ *		set = Skip backward over zero-length blocks.
+ *	SKM_EOB	  - Block-end selection (applies after skipping done).
+ *		  0 = Point to BOB (Beginning Of Block).
+ *		set = Point to EOB (End Of Block).
+ * Returns the new current SD as a convenience.
+ * Notes:
+ *	The SKM_0BACK flag value is a special hack to search in
+ *		the right direction when SBOFF is initially 0.
+ *	None of the mode flags have any effect if the I/O pos falls
+ *		within a block.
+ *	Perhaps this routine should flush the zero-length blks it
+ *		finds, if they're not locked??
+ */
+struct sdblk *
+sbx_norm(sbp,mode)
+SBBUF *sbp;
+int mode;
+{	register struct sdblk *sd;
+	register struct smblk *sm;
+	register SBBUF *sb;
+	chroff len;
+
+	if((sd = (sb=sbp)->sbcur) == 0)
+	  {	sb->sbdot = 0;
+		sb->sboff = 0;
+		return(sd);
+	  }
+	sd->sdflags &= ~SD_LOCK;	/* Unlock current blk */
+
+	if(sb->sboff >= (mode&01))	/* Hack hack to get right skip */
+	  for(;;)			/* Scan forwards */
+	  {	if(sm = sd->sdmem)		/* Get length of this blk */
+			len = sm->smuse;
+		else len = sd->sdlen;
+		if(sb->sboff <= len)
+		  if(sb->sboff < len	/* If == and fwd 0-skip, continue */
+		  || (mode&SKM_0BACK))
+		    {	if((mode&SKM_EOB)	/* Done, adjust to EOB? */
+			  && sb->sboff == 0	/* Yes, are we at BOB? */
+			  && sd->slback)	/* and can do it? */
+			  {	sd = sd->slback;	/* Move to EOB */
+				sb->sboff = (sm = sd->sdmem) 
+					? (chroff)(sm->smuse) : sd->sdlen;
+				sb->sbdot -= sb->sboff;
+			  }
+			break;
+		    }
+		if(sd->slforw == 0)	/* At EOF? */
+		  {	sb->sboff = len;
+			break;
+		  }
+		sd = sd->slforw;
+		sb->sboff -= len;
+		sb->sbdot += len;
+	  }
+	else				/* Scan backwards */
+	 for(;;)
+	  {	if(sd->slback == 0)	/* At BOF? */
+		  {	sb->sboff = 0;
+			sb->sbdot = 0;	/* Should already be 0, but... */
+			break;
+		  }
+		sd = sd->slback;
+		if(sm = sd->sdmem)		/* Get length of this blk */
+			len = sm->smuse;
+		else len = sd->sdlen;
+		sb->sbdot -= len;
+		if((sb->sboff += len) >= 0)
+		  if(sb->sboff > 0	/* If == 0 and bkwd 0-skip, continue */
+		    || !(mode&SKM_0BACK))
+		    {	if((mode&SKM_EOB) == 0	/* Done, adjust to BOB? */
+			  && sb->sboff == len	/* Yes, are we at EOB? */
+			  && sd->slforw)	/* and can do it? */
+			  {	sd = sd->slforw;	/* Move to BOB */
+				sb->sboff = 0;
+				sb->sbdot += len;
+			  }
+			break;
+		    }
+	  }
+	sb->sbcur = sd;
+	sd->sdflags |= SD_LOCK;
+	return(sd);
+}
+
+
+
+struct sdblk *
+sbx_beg(sdp)
+struct sdblk *sdp;
+{	register struct sdblk *sd, *sdx;
+	if(sd = sdp)
+		while(sdx = sd->slback)
+			sd = sdx;
+	return(sd);
+}
+
+
+sbx_smdisc(sbp)
+SBBUF *sbp;
+{	register SBBUF *sb;
+	register struct smblk *sm;
+	register struct sdblk *sd;
+
+	sb = sbp;
+	if((sd = sb->sbcur) == 0
+	  || (sm = sd->sdmem) == 0)
+		return;
+	if(sb->sbflags&SB_WRIT)
+	  {	sm->smuse = sb->sbiop - sm->smaddr;
+		sb->sbflags &= ~SB_WRIT;
+	  }
+	sb->sboff = sb->sbiop - sm->smaddr;
+	sb->sbiop = 0;
+	sb->sbrleft = sb->sbwleft = 0;
+}
+
+sbx_sbrdy(sbp)		/* Sets up SBIOP, SBRLEFT, SBWLEFT */
+SBBUF *sbp;
+{	register SBBUF *sb;
+	register struct sdblk *sd;
+	register struct smblk *sm;
+
+	if((sd = (sb=sbp)->sbcur) == 0
+	  || (sm = sd->sdmem) == 0)
+		return;
+	sd->sdflags |= SD_LOCK;
+	sb->sbiop = sm->smaddr + sb->sboff;
+	if(sb->sbrleft = sm->smuse - sb->sboff)
+		sb->sbwleft = 0;
+	else sb->sbwleft = sm->smlen - sm->smuse;
+}
+
+
+
+/* SBX_SCPY(sd,sdl) - Copies given sbstring, returns ptr to new sbstring.
+ *	Only goes as far as sdl (last copied blk); 0 for entire sbstring.
+ */
+struct sdblk *
+sbx_scpy(sdp,sdlast)
+struct sdblk *sdp, *sdlast;
+{	register struct sdblk *sd, *sd2, *sdn;
+	struct sdblk *sdr;
+
+	if((sd = sdp) == 0) return((struct sdblk *)0);
+	sdn = 0;
+	do {
+		sd->sdflags |= SD_LCK2;
+		sd2 = sbx_sdcpy(sd);
+		if(sd2->slback = sdn)
+		  {	sdn->slforw = sd2;
+			sdn->sdflags &= ~SD_LOCKS;
+		  }
+		else sdr = sd2;		/* Save 1st */
+		sdn = sd2;
+		sd->sdflags &= ~SD_LCK2;
+	  } while(sd != sdlast && (sd = sd->slforw));
+	sd2->slforw = 0;
+	sd2->sdflags &= ~SD_LOCKS;
+	return(sdr);
+}
+
+
+/* SBX_SDCPY(sd) - Copies given sdblk, returns ptr to new blk.
+ *	Does not set locks, assumes caller does this (which it MUST,
+ *	to avoid compaction lossage!)
+ */
+
+struct sdblk *
+sbx_sdcpy(sdp)
+struct sdblk *sdp;
+{	register struct sdblk *sd, *sd2;
+	register struct smblk *sm, *sm2;
+
+	if((sd = sdp) == 0) return((struct sdblk *)0);
+	sd2 = sbx_ndget();		/* Get a free sdblk */
+	bcopy((SBMA)sd, (SBMA)sd2, sizeof(struct sdblk));	/* Copy sdblk data */
+	sd2->slforw = 0;		/* Don't let it think it's on a list */
+	sd2->slback = 0;
+	if(sd2->sdfile)			/* If has disk copy, */
+	  {	sd->sdforw = sd2;	/* Fix phys list ptrs */
+		sd2->sdback = sd;
+		if(sd2->sdforw)
+			sd2->sdforw->sdback = sd2;
+	  }
+	if(sm = sd2->sdmem)		/* If has in-core copy, try to */
+	  {	if(sm2 = sbm_mget(sm->smuse,sm->smuse))	/* get mem for it */
+		  {	bcopy(sm->smaddr,sm2->smaddr,sm->smuse);
+			sm2->smuse = sm->smuse;
+			sd2->sdmem = sm2;	/* Point new sd to copy */
+		  }
+		else				/* Can't get mem... */
+		  {	if(sd2->sdflags&SD_MOD)
+				sbx_aout(sd2,1);	/* Swap out the blk */
+			sd2->sdmem = 0;		/* Don't have incore copy */
+		  }
+	  }
+	return(sd2);
+}
+
+
+/* SBX_XCIS(sbp,coff,&sdp2,adot) - Internal routine to excise a sbstring,
+ *	defined as everything between current location and given offset.
+ *	SD to first sdblk is returned (0 if error)
+ *	SD2 (address passed as 3rd arg) is set to last sdblk.
+ *	Both are locked with LCK2 to ensure that pointers are valid.
+ *	The current location at time of call is also returned via adot.
+ */
+struct sdblk *
+sbx_xcis(sbp,num,asd2,adot)
+SBBUF *sbp;
+chroff num, *adot;
+struct sdblk **asd2;
+{	register SBBUF *sb;
+	register struct sdblk *sd, *sd2;
+	int dirb;
+
+	if((sb = sbp) == 0) return((struct sdblk *)0);
+	dirb = 0;		/* Delete forward */
+	if(num == 0) return((struct sdblk *)0);	/* Delete nothing */
+	if(num < 0) dirb++;	/* Delete backward */
+
+	if((sd = (struct sdblk *)
+			sbx_ready(sb, (dirb ? SK_DELB : SK_DELF))) == 0)
+		return((struct sdblk *)0);		/* Maybe nothing there */
+	sd->sdflags |= SD_LCK2;		/* Lock up returned SD */
+	*adot = sb->sbdot;		/* Save current location */
+	sb->sboff += num;		/* Move to other end of range */
+
+	if((sd2 = (struct sdblk *)
+			sbx_ready(sb,(dirb ? SK_DELF : SK_DELB))) == 0)
+	  {	sd->sdflags &= ~SD_LCK2;	/* This shd never happen if */
+		return(				/* we got this far, but...  */
+		  (struct sdblk *)sbx_err(0,"KILLN SD2 failed"));
+	  }
+	sd2->sdflags |= SD_LCK2;	/* Lock up other end of stuff */
+
+	/* SD and SD2 now delimit bounds of stuff to excise.
+	 * Now do direction dependent fixups
+	 */
+	if(dirb)
+	  {	/* Backward, current sbdot is ok but must get SD/SD2
+		 * into first/last order.  Also, due to nature of block
+		 * splitups, a backward delete within single block will leave
+		 * SD actually pointing at predecessor block.
+		 */
+		if(sd->slforw == sd2)	/* If SD became pred, fix things. */
+		  {	sd->sdflags &= ~SD_LCK2;	/* Oops, unlock! */
+			sd = sd2;
+		  }
+		else	/* Just need to swap SD, SD2 ptrs. */
+		  {	/* Goddamit why doesn't C have an */
+			/* exchange operator??? */
+			*asd2 = sd;
+			return(sd2);
+		  }
+	  }
+	*asd2 = sd2;
+	return(sd);
+}
+
+
+/* SBX_SPLIT(sd,chroff) - Splits block SD at point CHROFF (offset from
+ *	start of block).  SD remains valid; it is left locked.
+ *	The smblk is split too, if one exists, and SMUSE adjusted.
+ *	If offset 0, or equal to block length, the 1st or 2nd SD respectively
+ *	will not have a smblk and its sdlen will be 0.
+ *	(Note that if a smblk exists, a zero sdlen doesn't indicate much)
+ */
+struct sdblk *
+sbx_split(sdp, coff)
+struct sdblk *sdp;
+chroff coff;
+{	register struct sdblk *sd, *sdf, *sdx;
+
+	if((sd=sdp) == 0)
+		return((struct sdblk *)0);
+	sd->sdflags |= SD_LOCK;
+	if(sd->sdflags&SD_MOD)		/* If block has been munged, */
+		sbx_npdel(sd);		/* Flush from phys list now. */
+	sdf = sbx_ndget();		/* Get a sdblk node */
+	bcopy((SBMA)sd, (SBMA)sdf, (sizeof (struct sdblk)));	/* Copy node */
+	/* Note that the flags are copied, so both sdblks are locked and
+	 * safe from possible GC compaction during call to sbx_msplit...
+	 */
+	if(coff == 0)			/* If offset was 0, */
+	  {				/* then 1st SD becomes null */
+		if(sdf->sdfile)		/* Fix up phys links here */
+		  {	if(sdx = sdf->sdback)
+				sdx->sdforw = sdf;
+			else sdf->sdfile->sfptr1 = sdf;
+			if(sdx = sdf->sdforw)
+				sdx->sdback = sdf;
+		  }
+		sdx = sd;
+		goto nulsdx;
+	  }
+	else if(sd->sdmem)
+		if(coff >= sd->sdmem->smuse)
+			goto nulsdf;
+		else sdf->sdmem = sbx_msplit(sd->sdmem, (SBMO)coff);
+	else if(coff >= sd->sdlen)
+nulsdf:	  {	sdx = sdf;
+nulsdx:		sdx->sdforw = 0;
+		sdx->sdback = 0;
+		sdx->sdmem = 0;
+		sdx->sdfile = 0;
+		sdx->sdlen = 0;
+		sdx->sdaddr = 0;
+		goto nulskp;
+	  }
+	if(sd->sdfile)
+	  {	sdf->sdlen -= coff;		/* Set size of remainder */
+		sdf->sdaddr += coff;		/* and address */
+		sd->sdlen = coff;		/* Set size of 1st part */
+
+	/* Link 2nd block into proper place in physical sequence.
+	 * 1st block is already in right place.	 Search forward until
+	 * find a block with same or higher disk address, and insert
+	 * in front of it.  If sdlen is zero, just flush the links,
+	 * which is OK since the 1st block is what's pointed to anyway.
+	 */
+		if(sdf->sdlen > 0)
+		  {	while((sdx = sd->sdforw) /* Find place to insert */
+			  && sdf->sdaddr > sdx->sdaddr)
+				sd = sdx;
+			sdf->sdback = sd;	/* Link following sd. */
+			if(sdf->sdforw = sd->sdforw)
+				sdf->sdforw->sdback = sdf;
+			sd->sdforw = sdf;
+			sd = sdp;		/* Restore pointer */
+		  }
+		else
+		  {	sdf->sdforw = 0;
+			sdf->sdback = 0;
+			sdf->sdfile = 0;	/* Say no disk */
+		  }
+	  }
+
+nulskp:	sdf->slback = sd;		/* Link in logical sequence */
+	if(sd->slforw)
+		sd->slforw->slback = sdf;
+	sd->slforw = sdf;
+
+	sdf->sdflags &= ~SD_LOCKS;	/* Unlock 2nd but not 1st */
+	return(sd);			/* Note sd, not sdf */
+}
+
+/* SBX_MSPLIT - Like sbm_split but never fails, and sets
+ *	SMUSE values appropriately
+ */
+struct smblk *
+sbx_msplit(smp, size)
+struct smblk *smp;
+SBMO size;
+{	register struct smblk *sm, *smx;
+	register int lev;
+
+	lev = 0;
+	while((smx = sbm_split((sm = smp), size)) == 0)
+		sbx_comp(SB_BUFSIZ,lev++); /* Need to get some smblk nodes */
+	if(sm->smlen >= sm->smuse)	/* Split across used portion? */
+		smx->smuse = 0;		/* Nope, new blk is all free */
+	else
+	  {	smx->smuse = sm->smuse - sm->smlen;
+		sm->smuse = sm->smlen;
+	  }
+	return(smx);
+}
+
+
+/* SBX_NDEL - flush a SD and associated SM.  Fixes up logical
+ * and physical links properly.  Returns ptr to next logical SD.
+ * NOTE: if sd->slback does not exist, the returned SD is your
+ * only hold on the list, since the SD gets flushed anyway!
+ */
+struct sdblk *
+sbx_ndel(sdp)
+struct sdblk *sdp;
+{	register struct sdblk *sd, *sdx;
+	register struct smblk *sm;
+
+	sd = sdp;
+	if(sm = sd->sdmem)		/* If smblk exists, */
+	  {	sbm_mfree(sm);		/* flush it. */
+		sd->sdmem = 0;
+	  }
+	if(sdx = sd->slback)
+		sdx->slforw = sd->slforw;
+	if(sd->slforw)
+		sd->slforw->slback = sdx;	/* May be zero */
+
+	/* Logical links done, now hack phys links */
+	if(sd->sdfile)			/* Have phys links? */
+		sbx_npdel(sd);		/* Yes, flush from phys list */
+
+	sdx = sd->slforw;
+	sbx_ndfre(sd);
+	return(sdx);
+}
+
+sbx_npdel(sdp)
+struct sdblk *sdp;
+{	register struct sdblk *sd, *sdx;
+	register struct sbfile *sf;
+
+	if((sf = (sd=sdp)->sdfile) == 0)
+		return;
+	if(sdx = sd->sdback)	/* Start of disk file? */
+		sdx->sdforw = sd->sdforw;
+	else
+		sf->sfptr1 = sd->sdforw;
+	if(sdx = sd->sdforw)
+		sdx->sdback = sd->sdback;
+	sd->sdfile = 0;
+	sd->sdlen = 0;
+}
+
+
+
+struct sdblk *sbx_nfl;	/* Pointer to sdblk node freelist */
+
+struct sdblk *
+sbx_ndget()		/* Like sbm_nget but never fails! */
+{	register struct sdblk *sd;
+	register int lev;
+
+	lev = 0;
+	while((sd = sbx_nfl) == 0		/* Get a node */
+						/* If fail, make more */
+		&& (sd = sbm_nmak((sizeof (struct sdblk)),SM_DNODS)) == 0)
+						/* If still fail, try GC */
+			sbx_comp(sizeof(struct sdblk)*SM_DNODS,lev++);
+
+	sbx_nfl = sd->slforw;		/* Take it off freelist */
+	sd->sdflags = SD_NID;
+	return(sd);			/* Return ptr to it */
+}
+
+sbx_ndfre(sdp)
+struct sdblk *sdp;
+{	register struct sdblk *sd;
+	(sd = sdp)->sdflags = 0;
+	sd->slforw = sbx_nfl;
+	sbx_nfl = sd;
+}
+
+SBMA
+sbx_malloc(size)
+unsigned size;
+{
+	register int lev;
+	register SBMA res;
+
+	lev = 0;
+	while((res = (SBMA)malloc(size)) == 0)
+		sbx_comp(size,lev++);
+	return(res);
+}
+
+struct smblk *
+sbx_mget(cmin,cmax)     /* like sbm_mget but never fails! */
+SBMO cmin, cmax;
+{	register struct smblk *sm;
+	register int lev, csiz;
+
+	lev = 0;
+	csiz = cmax;
+	for(;;)
+	  {	if(sm = sbm_mget(csiz,cmax))
+			return(sm);		/* Won right off... */
+		sbx_comp(csiz,lev++);		/* Barf, invoke GC */
+		if(sm = sbm_mget(csiz,cmax))	/* Then try again */
+			return(sm);
+		if((csiz >>= 1) < cmin)		/* If still short, reduce */
+			csiz = cmin;		/* request down to min */
+	  }
+}
+
+
+chroff sbv_taddr;	/* Disk addr of place to write into (set by TSET) */
+struct sdblk *sbv_tsd;	/* SD that disk addr comes after (set by TSET) */
+
+#define sbx_qlk(sd)  (sd->sdflags&SD_LOCKS)
+
+#if 0
+	This is the compaction routine, which is the key to the
+entire scheme.	Paging text to and from disk is trivial, but the
+ability to merge blocks is the important thing since it allows
+flushing the pointer information as well as the actual text!  This
+eliminates fragmentation as a fatal problem.
+	There are a variety of ways that storage can be reclaimed:
+
+- "pure" in-core blocks can be flushed instantly.
+- "impure" incore blocks can be written to tempfile storage and flushed.
+- The SM node freelist can be compacted so as to flush memory which is
+	used for nothing but holding free nodes.
+- The SD node freelist can be compacted, ditto.
+- SBBUFs can be compacted, by:
+	- Merging logically & physically adjacent on-disk pieces
+	- merging logically & physically adjacent in-core pieces
+	- merging logically adjacent in-core pieces
+	- merging logically adjacent disk pieces, by reading in
+		and then writing out to tempfile storage.
+		Worst case would reduce whole sbstr to single tempfile block.
+
+Problems:
+	What is "optimal" algorithm for typical usage?
+	Must go over all code to make sure right things get locked
+		and unlocked to avoid having rug pulled out from under.
+	Could have optional "registration table" for sbstruc; if exist
+		in table, can check during GC.	If find one, can first
+		do sbx_smdisc and then repoint sbcur to 1st block,
+		with sbdot of 0 and sboff of sb_tell().	 This allows
+		reducing whole thing to one block even tho "locked".
+		Never touch stuff locked with SD_LCK2, though.
+		Also may need way to protect the sbstr SD actually being
+		pointed to by current sbx routine processing.
+	Could have count of # nodes free for SM and SD; don''t GC 
+		unless # is some number greater than size of a node block!
+	Have different levels of compaction; pass level # down thru calls
+		so as to invoke progressively sterner compaction measures.
+		Can invoke sbx_comp with any particular level!
+	Must have list somewhere of SBBUFs?  or maybe OK to scan core
+		for SM_DNODS, then scan sdblks?
+	Screw: could happen that stuff gets flushed (cuz pure) or even
+		written out to tempfile, and then we have to read it back
+		in so as to compact more stuff into tempfile... how to avoid?
+		If pure stuff small and next to impure stuff, merge?
+	Some calls just want to get another free node and don''t need
+		new core.  How to indicate this?  How to decide between
+		freeing up used nodes, and creating new node freelist?
+#endif /*COMMENT*/
+/* Compact stuff.
+ * General algorithm for getting storage is:
+ *	1) allocate from freelist if enough there
+ *	2) find unlocked pure smblk to free up
+ *	3) find unlocked impure smblks, write out.
+ *	4) Compact stuff by reducing # of sdblks.  This is key to scheme!
+ *		Otherwise fragmentation will kill program.
+ * Maybe put age cnt in each sbstr?  Bump global and set cntr each time
+ * sbstr gets major hacking (not just getc/putc).
+ */
+extern struct smblk *sbm_list;
+sbx_comp(cmin,lev)
+int cmin, lev;
+{	int sbx_sdgc();
+
+	if(lev > 100)		/* If program has no way to handle this, */
+		abort();	/* then simply blow up. */
+	if(lev > 10)		/* Too many iterations? Try to warn. */
+		return(sbx_err(0,"GC loop, cannot free block of size %d",
+				cmin));
+
+	/* Step thru core hunting for SD node blocks */
+	sbm_nfor(SM_DNODS,sizeof(struct sdblk),sbx_sdgc,lev);
+}
+
+/* Do GC stuff on a sdblk.  Guaranteed to exist, but may be locked */
+sbx_sdgc(sdp,lev)
+struct sdblk *sdp;
+int lev;
+{	register struct sdblk *sd, *sdf;
+	register struct smblk *sm;
+	struct smblk *smf, *sbm_exp ();
+	SBMO more;
+
+	sd = sdp;
+	if(sbx_qlk(sd)) return(0);
+	sm = sd->sdmem;
+	sdf = sd->slforw;
+	if (lev < 4) goto lev3;
+
+	/* Level 4 - write out everything possible */
+	/* Back up to start of sbstr */
+	while((sdf = sd->slback) && !sbx_qlk(sdf))
+		sd = sdf;
+	if((sdf = sd->slforw) == 0	/* If only 1 blk, ensure on disk */
+	  || sbx_qlk(sdf))
+	  {	if(sm = sd->sdmem)
+		  {	if(sd->sdflags&SD_MOD)		/* If impure, */
+				sbx_aout(sd, 1);	/* swap out the SD */
+			sbm_mfree(sm);
+			sd->sdmem = 0;
+		  }
+		return(0);
+	  }
+	/* At least two blocks in string.  Set up for flushout. */
+	sbx_aout(sd, 0);	/* Swapout as much of sbstring as possible */
+	return(0);
+
+lev3:			/* Level 3 - write out more */
+lev2:			/* Level 2 - write out all impure & small pure */
+lev1:	if(lev >= 1)	/* Level 1 - merge small impure & small pure */
+	  {	if(!sm || !sdf) return(0);
+		while(((smf = sdf->sdmem) && !(sdf->sdflags&SD_LOCKS)
+		  && (more = smf->smuse + sm->smuse) < SB_BUFSIZ) )
+		  {	if(sm->smforw != smf
+			  && more > sm->smlen)		/* If need more rm */
+			  {	sm = sbm_exp(sm,more);	/* Get it */
+				if(!sm) return(0);	/* If none, stop */
+				sd->sdmem = sm;
+			  }
+			bcopy(smf->smaddr,
+			     sm->smaddr + sm->smuse, smf->smuse);
+			sm->smuse = more;
+			if(sm->smforw == smf)
+			  {	sdf->sdmem = 0;
+				sbm_mmrg(sm);	/* Merge */
+				if(sm->smlen > more+SB_SLOP)
+					sbm_mfree(sbm_split(sm, more));
+					/* Guaranteed to win since mmrg
+					 * just freed a mem node */
+			  }
+			sd->sdflags |= SD_MOD;
+			if(sdf = sbx_ndel(sdf))
+				continue;
+			return(0);
+		  }
+	  }
+
+	if(lev <= 0)	/* Level 0 - free up large pure blocks */
+			/* Also merge blocks which are adjacent on disk */
+	  {	if(sm)
+		  {	if(sm->smuse == 0)
+				sd->sdlen = 0;
+			else if((sd->sdflags&SD_MOD) == 0
+			    && sm->smuse > 64)
+			  {	sbm_mfree(sm);
+				sd->sdmem = 0;
+				goto lev0adj;
+			  }
+			else goto lev0adj;
+		  }
+
+		if(sd->sdlen == 0	/* Free zero blocks */
+		  && sd->slback)	/* Make sure don't lose list */
+		  {	sbx_ndel(sd);
+			if((sd = sdf) == 0)
+				return(0);
+			sdf = sd->slforw;
+		  }
+	lev0adj:	/* Merge blocks if adjacent on disk */
+			/* This is common after reading thru large chunks
+			* of a file but not modifying it much.
+			*/
+		if((sd->sdflags&SD_MOD) == 0	/* Pure */
+		  && sdf && (sdf->sdflags&(SD_LOCKS|SD_MOD)) == 0
+		  && sd->sdfile && (sd->sdfile == sdf->sdfile)
+		  && (sd->sdaddr + sd->sdlen) == sdf->sdaddr )
+		  {	sd->sdlen += sdf->sdlen;
+			sbx_ndel(sdf);		/* Flush 2nd */
+			if(sm = sd->sdmem)
+			  {	sbm_mfree(sm);
+				sd->sdmem = 0;
+			  }
+		  }
+		return(0);
+	  }
+	return(0);
+}
+
+
+/* SBX_AOUT - output ALL of a hackable sbstring starting at given sdblk.
+ *	Note that code is careful to do things so that an abort at any
+ *	time (e.g. write error) will still leave sbstring in valid state.
+ * Flag value:
+ *	0 - Writes out as many unlocked sdblks as possible, and merges
+ *		so that resulting sdblk (same one pointed to by arg)
+ *		incorporates all stuff written out.
+ *	1 - Writes out single sdblk indicated, whether unlocked or not.
+ *		Doesn't free mem or merge anything; does update physlist
+ *		and flags.
+ *	2 - Writes out all sdblks to specified FD/offset, no mods at all,
+ *		not even to physlist or flags.	Good for saving files
+ *		when something seems wrong.  (How to pass fd/off args?)
+ *		(offset arg not implemented, no need yet; 0 assumed)
+ * Returns 0 if successful, else UNIX system call error number.
+ */
+
+sbx_aout(sdp,flag,fd)
+struct sdblk *sdp;
+int flag, fd;
+{	register struct sdblk *sd;
+	register struct smblk *sm;
+	register int cnt;
+	int ifd, ofd, skflg, rem;
+	chroff inlen;
+	extern SBMA sbm_lowaddr;	/* Need this from SBM for rndrem */
+	char buf[SB_BUFSIZ+16];	/* Get buffer space from stack! */
+				/* Allow extra for word-align reads. */
+				/* This should be +WDSIZE, but some */
+				/* C compilers (eg XENIX) can't handle */
+				/* "sizeof" arith in allocation stmts! */
+
+	/* This flag and the two ptrs below are needed because UNIX
+	 * maintains only one I/O ptr per open file, and we can sometimes
+	 * be reading from/writing to the swapout file at same time.
+	 * Using DUP() to get a new FD (to avoid seeking back and forth)
+	 * won't help since both FD's will use the same I/O ptr!!!
+	 * Lastly, can't depend on returned value of LSEEK to push/pop
+	 * ptr, since V6 systems don't implement tell() or lseek() directly.
+	 * So we have to do it by hand...
+	 */
+	int botchflg;
+	chroff outptr, inptr;
+
+	if((sd = sdp)==0) return;
+	ofd = sbv_tf.sffd;		/* Default output FD */
+	if(flag==0)
+	  {	sbx_tset(sbx_qlen(sd),0);/* Find place for whole string */
+		outptr = sbv_taddr;	/* We'll have to update wrt ptr */
+	  }
+	else if (flag==1)	/* Single SD block, so it's reasonable to 
+				 * try aligning the output with the input. */
+	  {	if(sm = sd->sdmem)
+		  {	cnt = rndrem(sm->smaddr - sbm_lowaddr);
+			sbx_tset((chroff)(sm->smuse),cnt);
+		  }
+		else
+		  {	cnt = rndrem(sd->sdaddr);
+			sbx_tset(sd->sdlen, cnt);
+		  }
+		outptr = sbv_taddr;	/* We'll have to update wrt ptr */
+	  }
+	else		/* Outputting a whole sbstring to a file */
+	  {	ofd = fd;
+		outptr = 0;
+	  }
+
+	for(; sd;)
+	  {	if(flag==0 && sbx_qlk(sd))
+			break;		/* Stop when hit locked sdblk */
+		if(sm = sd->sdmem)
+		  {	if(cnt = sm->smuse)
+				if(write(ofd, sm->smaddr, cnt) != cnt)
+					return(sbx_err(errno,"Swapout wrt err"));
+			outptr += cnt;
+			if(flag==0)
+			  {	sd->sdmem = 0;	/* Flush the mem used */
+				sbm_mfree(sm);
+			  }
+			inlen = cnt;
+		  }
+		else if(inlen = sd->sdlen)
+		  {	if(sd->sdfile == 0)
+				return(sbx_err(errno,"Sdfile 0, SD %o",sd));
+			/* Foo on UNIX */
+			botchflg = ((ifd = sd->sdfile->sffd) == ofd) ? 1 : 0;
+			skflg = 1;		/* Always seek first time */
+			inptr = sd->sdaddr;
+			/* Efficiency hack - set up for first read so that
+			 * transfer is word-aligned and terminates at end
+			 * of a disk block.
+			 */
+			rem = rndrem(inptr);		/* Get alignment */
+			cnt = SB_BUFSIZ - (int)(inptr%SB_BUFSIZ);
+			while(inlen > 0)
+			  {
+				if(inlen < cnt) cnt = inlen;
+				if(!sbx_rdf(ifd, buf+rem, cnt, skflg, inptr))
+					return(sbx_err(errno,"Swapout err, SD %o",sd));
+				/* Further seeks depend on botch setting */
+				if(skflg = botchflg)
+				  {	if(lseek(ofd,outptr,0) < 0)
+						return(sbx_err(errno,
+							"Swapout sk err"));
+					inptr += cnt;
+				  }
+				if(write(ofd, buf+rem, cnt) != cnt)
+					return(sbx_err(errno,
+						"Swapout wrt err"));
+				outptr += cnt;
+				inlen -= cnt;
+				cnt = SB_BUFSIZ; /* Now can use full blocks */
+				rem = 0;	/* Aligned nicely, too! */
+			  }
+			inlen = sd->sdlen;
+		  }
+
+		/* Text written out, now merge block in */
+		if(flag == 2)			/* No merge if saving file */
+			goto donxt;
+		if(sd != sdp)			/* First block? */
+		  {	sdp->sdlen += inlen;	/* No, simple merge */
+			sd = sbx_ndel(sd);	/* Flush, get next */
+			continue;
+		  }
+
+		/* Handle 1st block specially */
+		if(sd->sdfile		/* Unlink from phys list */
+		  && sd != sbv_tsd)	/* Don't unlink if self */
+			sbx_npdel(sd);
+		sd->sdlen = inlen;
+		sd->sdfile = &sbv_tf;
+		sd->sdaddr = sbv_taddr;	/* Set from sbx_tset val */
+		sd->sdflags &= ~SD_MOD;	/* On disk, no longer modified */
+
+		/* Now insert into phys list at specified place */
+		if(sd == sbv_tsd)	/* If already same place */
+			goto next;	/* Skip linkin. */
+		if(sd->sdback = sbv_tsd)
+		  {	sd->sdforw = sbv_tsd->sdforw;
+			sd->sdback->sdforw = sd;
+		  }
+		else
+		  {	sd->sdforw = sbv_tf.sfptr1;
+			sbv_tf.sfptr1 = sd;
+		  }
+		if(sd->sdforw)
+			sd->sdforw->sdback = sd;
+
+	next:	if(flag==1)		/* If only doing 1 sdblk, */
+			break;		/* stop here. */
+	donxt:	sd = sd->slforw;	/* Done with 1st, get next */
+	  }
+	return(0);			/* Win return, no errors */
+}
+
+/* Returns hackable length of a sbstring (ends at EOF or locked block) */
+chroff
+sbx_qlen(sdp)
+struct sdblk *sdp;
+{	register struct sdblk *sd;
+	register struct smblk *sm;
+	chroff len;
+
+	len = 0;
+	for(sd = sdp; sd && !sbx_qlk(sd); sd = sd->slforw)
+		if(sm = sd->sdmem)
+			len += (chroff)sm->smuse;
+		else len += sd->sdlen;
+	return(len);
+}
+
+
+
+/* SBX_TSET - finds a place on temp swapout file big enough to hold
+ *	given # of chars.  Sets SBV_TADDR to that location, as well
+ *	as seeking to it so the next write call will output there.
+ *	This location is guaranteed to have the requested
+ *	byte alignment (0 = word-aligned).
+ */
+sbx_tset(loff, align)
+chroff loff;
+int align;
+{	register int fd;
+
+	if(sbv_tf.sffd <= 0)
+	  {		/* Must open the temp file! */
+/* Temporary file mechanism is system-dependent.  Eventually this
+** will probably require inclusion of a true c-env header file; for the
+** time being, we can cheat a little by checking O_T20_WILD, which will
+** be defined by <sys/file.h> on TOPS-20.  Otherwise, we assume we are
+** on a real Unix.
+*/
+#ifdef O_T20_WILD
+		extern char *tmpnam();	/* Use ANSI function */
+		fd = open(tmpnam((char *)NULL),
+				O_RDWR | O_CREAT | O_TRUNC | O_BINARY);
+		if(fd < 0)
+			return(sbx_err(0,"Swapout creat err"));		
+#else /* Real Unix */
+		static char fcp[] = "/tmp/sbd.XXXXXX";
+		if((fd = creat(mktemp(fcp),0600)) < 0)
+			return(sbx_err(0,"Swapout creat err"));
+		/* Must re-open so that we can both read and write to it */
+		close(fd);
+		if((fd = open(fcp,2)) < 0)
+			return(sbx_err(0,"Swapout open err"));
+		unlink(fcp);	/* Set so it vanishes when we do */
+#endif
+
+		sbv_tf.sffd = fd;	/* Initialize the sbfile struct */
+		sbv_tf.sfptr1 = 0;
+		sbv_ftab[fd] = &sbv_tf;	/* Record in table of all sbfiles */
+		sbv_taddr = 0;		/* "Return" this value */
+		return;		/* Ignore alignment for now */
+	  }
+	sbv_tsd = sbx_ffnd(&sbv_tf, loff+align, &sbv_taddr);
+	sbv_taddr += align;
+	if(lseek(sbv_tf.sffd, sbv_taddr, 0) < 0)
+		return(sbx_err(0,"Swapout seek err: (%d,%ld,0) %d %s",
+			sbv_tf.sffd, sbv_taddr, errno, strerror(errno)));
+
+}
+
+/* SBX_FFND - searches disk list of given file for free space of
+ *	at least size chars.  Note that list must be sorted by ascending
+ *	disk addrs in order for this to work!  If sdaddrs are only
+ *	changed in SBX_SPLIT this will be true.
+ *	Sets "aloc" to disk address for writing (this is guaranteed to
+ *	be word-aligned, for efficiency), and returns SD ptr to
+ *	block which this addr should follow in the physical list.  If ptr
+ *	is 0, it means addr should be 1st thing in list.
+ */
+struct sdblk *
+sbx_ffnd(sfp, size, aloc)
+SBFILE *sfp;
+chroff size, *aloc;
+{	register struct sdblk *sd, *sds, *sdl;
+	chroff cur;
+
+	cur = 0;
+	sds = 0;
+	sd = sfp->sfptr1;
+redo:	for(; sd ; sd = (sds=sd)->sdforw)
+	  {	if(cur < sd->sdaddr)		/* Gap seen? */
+		  {	if(size <= (sd->sdaddr - cur))	/* Yes, big enuf? */
+				break;			/* Yup! */
+		  }					/* No, bump. */
+		else if(cur >=(sd->sdaddr + sd->sdlen))	/* No gap but chk */
+			continue;			/* No overlap, ok */
+		/* Bump to next possible gap. */
+		cur = sd->sdaddr + sd->sdlen;
+		cur = (long)rndup(cur);	/* Round up to word boundary! */
+	  }
+	*aloc = cur;		/* Return winning addr */
+
+	/* Perform verification check -- make sure this really is OK
+	 * and complain if not.	 If this never blows up, eventually can
+	 * take the check out.
+	 */
+	sdl = sd;
+	for(sd = sfp->sfptr1; sd; sd = sd->sdforw)
+	  {	if(cur < sd->sdaddr)
+		  {	if(size <= (sd->sdaddr - cur))
+				continue;
+		  }
+		else if(cur >= (sd->sdaddr + sd->sdlen))
+			continue;
+
+		sbx_err(0,"FFND blew it, but recovered. SD %o siz %ld",
+			sd, size);
+		sd = (sds = sdl)->sdforw;
+		goto redo;
+	  }
+
+
+	return(sds);		/* Return ptr to block this addr follows */
+}
+
+sbx_rdf(fd,addr,cnt,skflg,loc)
+register int fd;
+char *addr;
+int skflg;
+chroff loc;
+{	register int rres, eres;
+	long lres;
+	char *errtyp, *ftyp;
+	chroff curlen;
+
+	errno = 0;
+	if(skflg && (lres = lseek(fd, (long)loc, 0)) == -1)
+	  {	errtyp = "Sk err";
+		goto errhan;
+	  }
+	if((rres = read(fd, addr, cnt)) != cnt)
+	  {	lres = rres;
+		errtyp = "Rd err";
+		goto errhan;
+	  }
+	return(rres);
+errhan:				/* Handle read or seek error */
+	eres = errno;
+	if(fd == sbv_tf.sffd)	/* See if dealing with swapout file */
+	  {	ftyp = "(swap)";
+		curlen = 0;
+	  }
+	else {			/* No, normal buffer file. */
+		ftyp = "";
+		curlen = sbx_fdlen(fd);
+		if(sbv_ftab[fd] &&
+		  (curlen != sbv_ftab[fd]->sflen))	/* File changed? */
+			if(sbx_rugpull(fd))	/* Yes, handle special case */
+				return(cnt);	/* Allow "win" return */
+	  }
+	sbx_err(0,"%s %d:%s, %ld:(%d%s,%o,%d)=%ld (fl %ld)",
+			errtyp,	eres, strerror(eres),
+			loc, fd, ftyp, addr, cnt, lres,
+			curlen);
+	return(0);
+}
+
+/* SBX_RUGPULL(fd) - Special routine called when package detects that
+ *	the file indicated by the fd has changed since its original
+ *	opening.  This can happen when a file is over-written by some
+ *	other program (ED, for example).
+ *	This means that all sdblks which reference this fd
+ *	are probably bad.  Pass special error back up to the calling
+ *	program to give it a chance at doing something.
+ *	Extra credit: scan all sdblks and unpurify all which point to this
+ *	file, so as to protect everything we still remember about it.
+ *	Otherwise a GC could flush pure in-core portions.
+ */
+sbx_rugpull(fd)		/* FD already known to have entry in sbv_ftab */
+register int fd;
+{	int sbx_unpur();
+
+	/* First scan all sdblks to save what we still have. */
+	/* This does NOT remove the sdfile pointer, so we can still
+	 * find blocks that are affected. */
+	sbm_nfor(SM_DNODS, sizeof(struct sdblk), sbx_unpur, sbv_ftab[fd]);
+
+	if((int)sbv_debug == 1 || !sbv_debug)
+		return(0);			/* Nothing else we can do */
+	return((*sbv_debug)(2,(int *)0,"",fd));	/* Let caller handle it */
+}
+sbx_unpur(sd, sf)		/* Auxiliary routine for SBX_RUGPULL */
+register struct sdblk *sd;
+register struct sbfile *sf;
+{	if(sd->sdfile == sf	/* If sdblk belongs to affected file */
+	  && sd->sdmem)		/* and has in-core version of text, */
+		sd->sdflags |= SD_MOD;	/* then ensure core version is used */
+}
+
+sbx_err(val,str,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)
+char *str;
+{	int *sptr;
+
+	sptr = (int *) &sptr;	/* Point to self on stack */
+	sptr += 5;		/* Point to return addr */
+	if((int)sbv_debug == 1)
+	  {	abort();
+	  }
+	if(sbv_debug)
+		(*sbv_debug)(1,*sptr,str,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12);
+	return(val);
+}
Index: /trunk/minix/commands/elle/sbvall.c
===================================================================
--- /trunk/minix/commands/elle/sbvall.c	(revision 9)
+++ /trunk/minix/commands/elle/sbvall.c	(revision 9)
@@ -0,0 +1,42 @@
+/* VALLOC - Aligned memory allocator
+ *	Emulation of the 4.2BSD library routine of the same name.
+ *	Copyright 1985 by Ken Harrenstien, SRI International
+ *	This software is quasi-public; it may be used freely with
+ *	like software, but may NOT be sold or made part of licensed
+ *	products without permission of the author.  In all cases
+ *	the source code and any modifications thereto must remain
+ *	available to any user.
+ *
+ *	This is part of the SB library package.
+ *	Any software using the SB library must likewise be made
+ *	quasi-public, with freely available sources.
+ */
+
+#include "sb.h"
+
+char *
+valloc(size)
+unsigned size;
+{	register int pagmsk;
+	register SBMO i;
+	register struct smblk *sm, *smr;
+	struct smblk *sbm_mget(), *sbm_split();
+
+	pagmsk = getpagesize() - 1;	/* Get page size in bytes, less 1 */
+	if(!(sm = sbm_mget(size+pagmsk, size+pagmsk))) /* Get area big enuf */
+		return(0);
+	/* Now find # bytes prior to 1st page boundary.
+	 * This expression gives 0 if already at boundary, else #-1.
+	 */
+	i = pagmsk - ((int)(sm->smaddr) & pagmsk);
+	if(i)		/* If need to split off preceding stuff, */
+	  {	smr = sbm_split(sm, i+1);	/* do so (note i adjusted) */
+		sbm_mfree(sm);			/* Release preceding mem */
+		if(!(sm = smr)) return(0);	/* If couldn't split, fail */
+	  }
+	if(i = (sm->smlen - size))	/* See if any trailing stuff */
+	  {	smr = sbm_split(sm, size);	/* Yeah, split it off too */
+		if(smr) sbm_mfree(smr);	/* If couldn't split, excess OK. */
+	  }
+	return((char *)(sm->smaddr));
+}
Index: /trunk/minix/commands/elvis/.descr
===================================================================
--- /trunk/minix/commands/elvis/.descr	(revision 9)
+++ /trunk/minix/commands/elvis/.descr	(revision 9)
@@ -0,0 +1,1 @@
+Lightweight vi
Index: /trunk/minix/commands/elvis/Doc.sh
===================================================================
--- /trunk/minix/commands/elvis/Doc.sh	(revision 9)
+++ /trunk/minix/commands/elvis/Doc.sh	(revision 9)
@@ -0,0 +1,3314 @@
+echo x - cflags.ms
+sed '/^X/s///' > cflags.ms << '/'
+X.Go 9 "CFLAGS"
+X.PP
+X\*E uses many preprocessor symbols to control compilation.
+XSome of these control the sizes of buffers and such.
+XThe "-DNO_XXXX" options remove small sets of related features.
+X.PP
+XMost \*E users will probably want to keep all features available.
+XMinix-PC users, though, will have to sacrifice some sets because otherwise
+X\*E would be too bulky to compile.
+XThe "asld" phase of the compiler craps out.
+X.IP "-DM_SYSV, -Dbsd, -DTOS, -DCOHERENT, -Damiga"
+XThese flags tell the compiler that \*E is being compiled for
+XSystem-V UNIX, BSD UNIX, Atari TOS, Coherent, or AmigaDos, respectively.
+XFor other systems, the config.h file can generally figure it out automatically.
+X.IP -DRAINBOW
+XFor MS-DOS systems, this causes support for the DEC Rainbow to be compiled
+Xinto \*E.
+X.IP -DS5WINSIZE
+XSome versions of SysV UNIX don't support support the "winsize"
+Xstyle of screen-size testing,
+Xso elvis ignores window size changes by default.
+X.IP
+XHowever, many of the newer SysV systems defines "winsize" in the
+Xfile "/usr/include/sys/ptem.h".
+XIf your SysV system has "winsize" then you should add
+X-DS5SWINSIZE to the CFLAGS setting.
+X.IP -DTERMIOS
+XPOSIX is a SysV-derived specification which uses a terminal control
+Xpackage called "termios", instead of "termio".
+XSome other SysV systems may also use termios.
+XYou can make elvis uses termios instead of the more common termio
+Xby adding -DTERMIOS to CFLAGS.
+X(Note: This hasn't been tested very well.)
+X.IP -DNBUFS=\fInumber\fP
+X\*E keeps most of your text in a temporary file;
+Xonly a small amount is actually stored in RAM.
+XThis flag allows you to control how much of the file can be in RAM at any time.
+XThe default is 5 blocks, and the minimum is 3 blocks.
+X(See the -DBLKSIZE flag, below.)
+X.IP
+XMore RAM allows global changes to happen a little faster.
+X f you're just making many small changes in one section of a file, though,
+Xextra RAM won't help much.
+X.IP -DBLKSIZE=\fInumber\fP
+XThis controls the size of blocks that \*E uses internally.
+XThe value of BLKSIZE must be a power of two.
+XEvery time you double BLKSIZE, you quadruple the size of a text file that
+X\*E can handle, but you also cause the temporary file to grow faster.
+XFor MS-DOS, Coherent, and Minix-PC, the default value is 1024, which allows
+Xyou to edit files up to almost 512K bytes long.
+XFor all other systems, the default value is 2048, which allows you to edit
+Xfiles that are nearly 2 megabytes long.
+X.IP
+XThe BLKSIZE also determines the maximum line length, and a few other limits.
+XBLKSIZE should be either 256, 512, 1024, or 2048.
+XValues other than these can lead to strange behaviour.
+X.IP -DTMPDIR=\fIstring\fP
+XThis sets the default value of the "directory" option, which specifies where
+Xthe temporary files should reside.
+XThe value of TMPDIR must be a string, so be sure your value includes the
+Xquote characters on each end.
+X.IP "-DEXRC=\fIstr\fP, -DHMEXRC=\fIstr\fP, -DSYSEXRC=\fIstr\fP, -DEXINIT=\fIstr\fP"
+XThis lets you control the names of the initialization files.
+XTheir values must be strings, so be careful about quoting.
+X.IP
+XEXRC is the name of the initialization file in the current directory.
+XIts default value is ".exrc" on UNIX systems -- the same as the real vi.
+XSince that isn't a legal DOS filename, under DOS the default is "elvis.rc".
+XFor other systems, check the config.h file.
+X.IP
+XHMEXRC is the name of the initialization file in your home directory.
+XBy default, it is the same as EXRC.
+X\*E will automatically prepend the name of your home directory to HMEXRC
+Xat run time, so don't give a full path name.
+X.IP
+XSYSEXRC is the name of a system-wide initialization file.
+XIt has no default value;
+Xif you don't define a value for it, then
+Xthe code that supports SYSEXRC just isn't compiled.
+XThe value of SYSEXRC should be a full pathname, in quotes.
+X.IP
+XEXINIT is the name of an environment variable that can contain initialization
+Xcommands.
+XNormally, its value is "EXINIT".
+X.IP -DKEYWORDPRG=\fIstring\fP
+XThis flag determines the default value of the "keywordprg" option.
+XIts value must be a string, so be careful about quoting.
+XThe default value of this flag is "ref", which is a C reference program.
+X.IP "-DCC_COMMAND=\fIstring\fP -DMAKE_COMMAND=\fIstring\fP -DERRLIST=\fIstring\fP"
+XThese control the names of the C compiler, the "make" utility, and the
+Xerror output file, respectively.
+XThey are only used if -DNO_ERRLIST is not given.
+X.IP
+XThe default value of CC_COMMAND depends on the Operating System and compiler
+Xthat you use to compile elvis;
+Xfor UNIX, the default is "cc".
+XThe default values of MAKE_COMMAND and ERRLIST are "make" and "errlist",
+Xrespectively.
+X.IP -DMAXRCLEN=\fInumber\fP
+XThis determines how large a :@ macro command can be (measured in bytes).
+XThe default is 1000 bytes.
+XIf you increase this value significantly,
+Xthen you may need to allocate extra memory for the stack.
+XSee the "CHMEM" setting in the Makefile.
+X.IP -DSHELL=\fIstring\fP
+XThis is the default value of the "shell" option, and hence
+Xthe default shell used from within \*E.
+XThis only controls the default;
+Xthe value you give here may be overridden at run-time by setting
+Xan environment variable named SHELL (or COMSPEC for MS-DOS).
+XIts value must be a string constant, so be careful about quoting.
+X.IP -DTAGS=\fIstring\fP
+XThis sets the name of the "tags" file,
+Xwhich is used by the :tag command.
+XIts value must be a string constant, so be careful about quoting.
+X.IP "-DCS_IBMPC -DCS_LATIN1 -DCS_SPECIAL"
+XThe digraph table and flipcase option will normally start out empty.
+XHowever, if you add -DCS_IBMPC or -DCS_LATIN1 to your CFLAGS,
+Xthen they will start out filled with values that are appropriate for the
+XIBM PC character set or the ISO Latin-1 character set, respectively.
+X.IP
+XYou can also use -DCS_IBMPC and -DCS_SPECIAL together to get digraphs
+Xthat produce the PC's graphic characters.
+X.IP "-DDEBUG -DEBUG2"
+X-DDEBUG adds the ":debug" and ":validate" commands,
+Xand also adds many internal consistency checks.
+XIt increases the size of the ".text" segment by about 6K.
+X.IP
+X-DDEBUG2 causes a line to be appended to a file called "debug.out"
+Xeverytime any change is made to the edit buffer.
+X.IP -DCRUNCH
+XThis flag removes some non-critical code, so that \*E is smaller.
+XFor example, it removes a short-cut from the regexp package, so that
+Xtext searches are slower.
+XAlso, screen updates are not as efficient.
+XA couple of obscure features are disabled by this, too.
+X.IP -DNO_MKEXRC
+XThis removes the ":mkexrc" command,
+Xso you have to create any .exrc files manually.
+XThe size of the .text segment will be reduced by about 600 bytes.
+X.IP -DNO_CHARATTR
+XPermanently disables the charattr option.
+XThis reduces the size of your ".text" segment by about 850 bytes.
+X.IP -DNO_RECYCLE
+XNormally, \*E will recycle space (from the temporary file) which contains
+Xtotally obsolete text.
+XThis flag disables this recycling.
+XWithout recycling, the ".text" segment is about 1K smaller
+Xthan it would otherwise be,
+Xbut the tmp file grows much faster.
+XIf you have a lot of free space on your hard disk,
+Xbut \*E is too bulky to run with recycling,
+Xthen try it without recycling.
+X.IP
+XWhen using a version of \*E that has been compiled with -DNO_RECYCLE,
+Xyou should be careful to avoid making many small changes to a file
+Xbecause each individual change will cause the tmp file to grow by at least 1k.
+XHitting "x" thirty times counts as thirty changes,
+Xbut typing "30x" counts as one change.
+XAlso, you should occasionally do a ":w" followed by a ":e" to start with a
+Xfresh tmp file.
+X.IP
+XInterestingly, the real vi never recycles space from its temporary file.
+X.IP -DNO_SENTENCE
+XLeaves out the "(" and ")" visual mode commands.
+XAlso, the "[[", "]]", "{", and "}" commands will not recognize *roff macros.
+XThe sections and paragraphs options go away.
+XThis saves about 650 bytes in the ".text" segment.
+X.IP -DNO_CHARSEARCH
+XLeaves out the visual commands which locate a given character
+Xin the current line:
+X"f", "t", "F", "T", "," and ";".
+XThis saves about 900 bytes.
+X.IP -DNO_EXTENSIONS
+XLeaves out the "K" and "#" visual commands.
+XAlso, the arrow keys will no longer work in input mode.
+XRegular expressions will no longer recognize the \\{\\} operator.
+X(Other extensions are either inherent in the design of \*E,
+Xor are controlled by more specific flags,
+Xor are too tiny to be worth removing.)
+XThis saves about 250 bytes.
+X.IP -DNO_MAGIC
+XPermanently disables the "magic" option, so that most meta-characters
+Xin a regular expression are *NOT* recognized.
+XThis saves about 3k of space in the ".text" segment, because
+Xthe complex regular expression code can be replaced by much simpler code.
+X.IP -DNO_SHOWMODE
+XPermanently disables the "showmode" option, saving about 250 bytes.
+X.IP -DNO_CURSORSHAPE
+XNormally, \*E tries to adjust the shape of the cursor as a reminder
+Xof which mode you're in.
+XThe -DNO_CURSORSHAPE flag disables this, saving about 150 bytes.
+X.IP -DNO_DIGRAPH
+XTo allow entry of non-ASCII characters, \*E supports digraphs.
+XA digraph is a single (non-ASCII) character which is entered as a
+Xcombination of two other (ASCII) characters.
+XIf you don't need to input non-ASCII characters,
+Xor if your keyboard supports a better way of entering non-ASCII characters,
+Xthen you can disable the digraph code and save about 450 bytes.
+X.IP -DNO_ERRLIST
+X\*E adds a ":errlist" command, which is useful to programmers.
+XIf you don't need this feature, you can disable it via the -DNO_ERRLIST flag.
+XThis will reduce the .text segment by about 900 bytes, and the .bss segment
+Xby about 300 bytes.
+X.IP -DNO_ABBR
+XThe -DNO_ABBR flag disables the ":abbr" command,
+Xand reduces the size of \*E by about 250 bytes.
+X.IP -DNO_OPTCOLS
+XWhen \*E displays the current options settings via the ":set" command,
+Xthe options are normally sorted into columns.
+XThe -DNO_OPTCOLS flag causes the options to be sorted across the rows,
+Xwhich is much simpler for the computer.
+XThe -DNO_OPTCOLS flag will reduce the size of your .text segment by about
+X500 bytes.
+X.IP -DNO_MODELINES
+XThis removes all support for modelines.
+X.IP -DNO_TAG
+XThis disables tag lookup.
+XIt reduces the size of the .text segment by about 750 bytes.
+X.IP "-DNO_ALT_FKEY -DNO_CTRL_FKEY -DNO_SHIFT_FKEY -DNO_FKEY"
+XThese remove explicit support of function keys.
+X-DNO_ALT_FKEY removes support for the <alternate> versions function keys.
+X-DNO_CTRL_FKEY removes support for the <control> and <alternate> versions function keys.
+X-DNO_SHIFT_FKEY removes support for the <shift>, <control>, and <alternate> versions function keys.
+X-DNO_FKEY removes all support of function keys.
+X.IP
+X\*E's ":map" command normally allows you to use the special sequence "#<n>"
+Xto map function key <n>.
+XFor example, ":map #1 {!}fmt^M" will cause the <F1> key to reformat a paragraph.
+X\*E checks the :k1=: field in the termcap description of your terminal
+Xto figure out what code is sent by the <F1> key.
+XThis is handy because it allows you to create a .exrc file which maps function
+Xkeys the same way regardless of what type of terminal you use.
+X.IP
+XThat behaviour is standard; most implementations of the real vi supports it too.
+X\*E extends this to allow you to use "#1s" to refer to <shift>+<F1>,
+X"#1c" to refer to <control>+<F1>, and
+X"#1a" to refer to <alt>+<F1>.
+XThe termcap description for the terminal should have fields named
+X:s1=:c1=:a1=: respectively, to define the code sent by these key conbinations.
+X(You should also have :k2=:s2=:c2=:a2=: for the <F2> key, and so on.)
+X.IP
+XBut there may be problems.
+XThe terminfo database doesn't support :s1=:c1=:a1=:, so no terminfo terminal
+Xdescription could ever support shift/control/alt function keys;
+Xso you might as well add -DNO_SHIFT_FKEY to CFLAGS if you're using terminfo.
+X.IP
+XNote that, even if you have -DNO_FKEYS, you can still configure \*E to use
+Xyour function keys my mapping the literal character codes sent by the key.
+XYou just couldn't do it in a terminal-independent way.
+XTERM_925
+X.IP "-DTERM_AMIGA -DTERM_VT100 -DTERM_VT52 etc."
+XThe tinytcap.c file contains descriptions of several terminal types.
+XFor each system that uses tinytcap, a reasonable subset of the available
+Xdescriptions is actually compiled into \*E.
+XIf you wish to enlarge this subset, then you can add the appropriate -DTERM_XXX
+Xflag to your CFLAGS settings.
+X.IP
+XFor a list of the available terminal types, check the tinytcap.c file.
+X.IP -DINTERNAL_TAGS
+XNormally, \*E uses the "ref" program to perform tag lookup.
+XThis is more powerful than the real vi's tag lookup,
+Xbut it can be much slower.
+X.IP
+XIf you add -DINTERNAL_TAGS to your CFLAGS setting,
+Xthen \* will use its own internal tag lookup code, which is faster.
+X.IP -DPRSVDIR=\fIdirectory\fR
+XThis controls where preserved files will be placed.
+XAn appropriate default has been chosen for each Operating System,
+Xso you probably don't need to worry about it.
+X.IP -DFILEPERMS=\fInumber\fR
+XThis affects the attributes of files that are created by \*E;
+Xit is used as the second argument to the creat() function.
+XThe default is 0666 which (on UNIX systems at least) means that
+Xanybody can read or write the new file, but nobody can execute it.
+XOn UNIX systems, the creat() call modifies this via the umask setting.
+X.IP -DKEYBUFSIZE=\fInumber\fR
+XThis determines the size of the type-ahead buffer that elvis uses.
+XIt also limits the size of keymaps that it can handle.
+XThe default is 1000 characters, which should be plenty.
+/
+echo x - cutbufs.ms
+sed '/^X/s///' > cutbufs.ms << '/'
+X.Go 6 "CUT BUFFERS"
+X.PP
+XWhen \*E deletes text, it stores that text in a cut buffer.
+XThis happens in both visual mode and EX mode.
+XThere is no practical limit to how much text a cut buffer can hold.
+X.PP
+XThere are 36 cut buffers:
+X26 named buffers ("a through "z),
+X9 anonymous buffers ("1 through "9),
+Xand 1 extra cut buffer (".).
+X.PP
+XIn EX mode, the :move and :copy commands use a cut buffer to temporarily
+Xhold the text to be moved/copied.
+X.NH 2
+XPutting text into a Cut Buffer
+X.PP
+XIn visual mode, text is copied into a cut buffer when you use the
+Xd, y, c, C, s, or x commands.
+XThere are also a few others.
+X.PP
+XBy default, the text goes into the "1 buffer.
+XThe text that used to be in "1 gets shifted into "2,
+X"2 gets shifted into "3, and so on.
+XThe text that used to be in "9 is lost.
+XThis way, the last 9 things you deleted are still accessible.
+X.PP
+XYou can also put the text into a named buffer -- "a through "z.
+XTo do this, you should type the buffer's name
+X(two keystrokes: a double-quote and a lowercase letter)
+Xbefore the command that will cut the text.
+XWhen you do this, "1 through "9 are not affected by the cut.
+X.PP
+XYou can append text to one of the named buffers.
+XTo do this, type the buffer's name in uppercase
+X(a double-quote and an uppercase letter)
+Xbefore the d/y/c/C/s/x command.
+X.PP
+XThe ". buffer is special.
+XIt isn't affected by the d/y/c/C/s/x command.
+XInstead, it stores the text that you typed in
+Xthe last time you were in input mode.
+XIt is used to implement the . visual command,
+Xand ^A in input mode.
+X.PP
+XIn EX mode (also known as colon mode),
+Xthe :delete, :change, and :yank commands all copy text into a cut buffer.
+XLike the visual commands, these EX commands normally use the "1 buffer,
+Xbut you can use one of the named buffers by giving its name after the command.
+XFor example,
+X.sp 1
+X.ti +0.5i
+X:20,30y a
+X.sp
+X.LP
+Xwill copy lines 20 through 30 into cut buffer "a.
+X.PP
+XYou can't directly put text into the ". buffer, or the "2 through "9 buffers.
+X.NH 2
+XPasting from a Cut Buffer
+X.PP
+XThere are two styles of pasting:
+Xline-mode and character-mode.
+XIf a cut buffer contains whole lines (from a command like "dd")
+Xthen line-mode pasting is used;
+Xif it contains partial lines (from a command like "dw")
+Xthen character-mode pasting is used.
+XThe EX commands always cut whole lines.
+X.PP
+XCharacter-mode pasting causes the text to be inserted into the line that
+Xthe cursor is on.
+X.PP
+XLine-mode pasting inserts the text on a new line above or below the line
+Xthat the cursor is on.
+XIt doesn't affect the cursor's line at all.
+X.PP
+XIn visual mode, the p and P commands insert text from a cut buffer.
+XUppercase P will insert it before the cursor,
+Xand lowercase p will insert it after the cursor.
+XNormally, these commands will paste from the "1 buffer, but you can
+Xspecify any other buffer to paste from.
+XJust type its name (a double-quote and another character)
+Xbefore you type the P or p.
+X.PP
+XIn EX mode, the (pu)t command pastes text after a given line.
+XTo paste from a buffer other that "1,
+Xenter its name after the command.
+X.NH 2
+XMacros
+X.PP
+XThe contents of a named cut buffer can be executed as a series of
+Xex/vi commands.
+X.PP
+XTo put the instructions into the cut buffer, you must first insert
+Xthem into the file, and then delete them into a named cut buffer.
+X.PP
+XTo execute a cut buffer's contents as EX commands,
+Xyou should give the EX command "@" and the name of the buffer.
+XFor example, :@z will execute "z as a series of EX commands.
+X.PP
+XTo execute a cut buffer's contents as visual commands,
+Xyou should give the visual command "@" and the letter of the buffer's name.
+XThe visual "@" command is different from the EX "@" command.
+XThey interpret the cut buffer's contents differently.
+X.PP
+XThe visual @ command can be rather finicky.
+XEach character in the buffer is interpretted as a keystroke.
+XIf you load the instructions into the cut buffer via a "zdd command,
+Xthen the newline character at the end of the line will be executed just
+Xlike any other character, so the cursor would be moved down 1 line.
+XIf you don't want the cursor to move down 1 line at the end of each
+X@z command, then you should load the cut buffer by saying 0"zD instead.
+X.PP
+XAlthough cut buffers can hold any amount of text,
+X\*E can only \fIexecute\fR small buffers.
+XThe size limit is roughly 1000 characters, for either EX macros or VI macros.
+XIf a buffer is too large to execute, an error message is displayed.
+X.PP
+XYou can't nest :@ commands.
+XYou can't run :@ commands from your .exrc file,
+Xor any other :source file either.
+XSimilarly, you can't run a :source command from within an @ command.
+XHopefully, these restrictions will be lifted in a later version.
+X.NH 2
+XThe Effect of Switching Files
+X.PP
+XWhen \*E first starts up, all cut buffers are empty.
+XWhen you switch to a different file
+X(via the :n or :e commands perhaps)
+Xthe 9 anonymous cut buffers are emptied again,
+Xbut the other 27 buffers ("a through "z, and ".) retain their text.
+/
+echo x - differ.ms
+sed '/^X/s///' > differ.ms << '/'
+X.Go 7 "DIFFERENCES BETWEEN \*E & BSD VI/EX"
+X.PP
+X\*E is not 100% compatible with the real vi/ex.
+X\*E has many small extensions, some omissions, and a few features which
+Xare implemented in a slightly different manner.
+X.NH 2
+XExtensions
+X.IP "Save Configuration" 1i
+XThe :mkexrc command saves the current :set and :map configurations in
+Xthe ".exrc" file in your current directory.
+X.IP "Previous File" 1i
+XThe :N or :prev command moves backwards through the args list.
+X.IP "Center Current Row" 1i
+XIn visual command mode, the (lowercase) "zz" command will center the current
+Xline on the screen, like "z=".
+X.IP "Changing Repeat Count" 1i
+XThe default count value for . is the same as the previous command
+Xwhich . is meant to repeat.
+XHowever, you can supply a new count if you wish.
+XFor example, after "3dw", "." will delete 3 words,
+Xbut "5." will delete 5 words.
+X.IP "Previous Text" 1i
+XThe text which was most recently input
+X(via a "cw" command, or something similar)
+Xis saved in a cut buffer called ". (which
+Xis a pretty hard name to write in an English sentence).
+X.IP "Keyword Lookup" 1i
+XIn visual command mode, you can move the cursor onto a word and press
+Xshift-K to have \*E run a reference program to look that word up.
+XThis command alone is worth the price of admission!
+XSee the ctags and ref programs.
+X.IP "Increment/Decrement" 1i
+XIn visual command mode, you can move the cursor onto a number and
+Xthen hit ## or #+ to increment that number by 1.
+XTo increment it by a larger amount,
+Xtype in the increment value before hitting the initial #.
+XThe number can also be decremented or set by hitting #- or #=, respectively.
+X.IP "Input Mode" 1i
+XYou can backspace past the beginning of the line.
+X.IP "" 1i
+XThe arrow keys work in input mode.
+X.IP "" 1i
+XIf you type control-A, then the text that you input last time is inserted.
+XYou will remain in input mode, so you can backspace over part of it,
+Xor add more to it.
+X(This is sort of like control-@ on the real vi,
+Xexcept that control-A really works.)
+X.IP "" 1i
+XControl-P will insert the contents of the cut buffer.
+X.IP "" 1i
+XReal vi can only remember up to 128 characters of input,
+Xbut \*E can remember any amount.
+X.IP "" 1i
+XThe ^T and ^D keys can adjust the indent of a line no matter where
+Xthe cursor happens to be in that line.
+X.IP "" 1i
+XYou can save your file and exit \*E directly from input mode by hitting
+Xcontrol-Z twice.
+X.IP "" 1i
+X\*E supports digraphs as a way to enter non-ASCII characters.
+X.IP "Start in Input Mode" 1i
+XIf you ":set inputmode" in your .exrc file, then \*E will start up in
+Xinput mode instead of visual command mode.
+X.IP "Visible Fonts" 1i
+XWith ":set charattr", \*E can display "backslash-f" style character attributes on the
+Xscreen as you edit.
+XThe following example shows the recognized atributes:
+X.sp
+X.ti +0.5i
+Xnormal \\fBboldface\\fR \\fIitalics\\fR \\fUunderlined\\fR normal
+X.sp
+XNOTE: you must compile \*E without the -DNO_CHARATTR flag for
+Xthis to work.
+X.IP "File Syncing" 1i
+XAfter a crash, you can usually recover the altered form of the file
+Xfrom the temporary file that \*E uses -- unless the temporary file was
+Xcorrupted.
+X.IP "" 1i
+XUNIX systems use a delayed-write cache, which means that when \*E tries to
+Xwrite to the temporary file, the information might still be in RAM instead
+Xof on the disk.
+XA power failure at that time would cause the in-RAM information to be lost.
+XUNIX's sync() call will force all such information to disk.
+X.IP "" 1i
+XMS-DOS and Atari TOS don't write a file's length to disk until that file
+Xis closed.
+XConsequently, the temporary file would appear to be 0 bytes long if power
+Xfailed when we were editing.
+XTo avoid this problem, a sync() function has been written which will close
+Xthe temporary file and then immediately reopen it.
+X.IP "Cursor Shape" 1i
+X\*E changes the shape of the cursor to indicate which mode you're in,
+Xif your terminal's termcap entry includes the necessary capabilities.
+X.IP "Hide nroff Lines" 1i
+XTh ":set hideformat" option hides nroff format control lines.
+X(They are displayed on the screen as blank lines.)
+X.ne 7
+X.IP "Compiler Interface" 1i
+X\*E is clever enough to parse the error messages emitted by many compilers.
+XTo use this feature,
+Xyou should collect your compiler's error messages into a file called "errlist";
+X\*E will read this file,
+Xdetermine which source file caused the error messages,
+Xstart editing that file,
+Xmove the cursor to the line where the error was detected,
+Xand display the error message on the status line.
+XNifty!
+X.IP "Visible Text Selection" 1i
+XIn visual command mode, 'v' starts visibly selecting characters and
+X\&'V' starts visibly selecting whole lines.
+XThe character or line where the cursor is located becomes one
+Xendpoint of the selection.
+XYou can then use the standard cursor movement commands to move the cursor
+Xto the other endpoint, and then press one of the operator commands
+X(c/d/y/</>/!/=/\\).
+XThe operator will then immediately be applied to the selected text.
+X.IP "Pop-up Menu Operator" 1i
+XThe '\\' key is a new operator,
+Xsimilar in operation to the c/d/y/</>/! operators
+XIt conjures up a menu, from which you can select any of the other
+Xoperators plus a few other common commands.
+X.IP "Preset Filter Operator" 1i
+XThe '=' key is another new operator.
+XIt is similar to the '!' operator, except that while
+X\&'!' asks you to type in a filter command each time,
+X\&'=' assumes it should always run the command stored in the \fIequalprg\fR option.
+X.IP "Move to a Given Percentage" 1i
+XThe '%' movement key can now accept an optional count.
+XWithout a count, the '%' key still moves to a matching parenthesis
+Xlike it always did.
+XWith a count somewhere between 1 and 100, though, it moves the cursor to
+Xapproximately a given percentage of the way through the file.
+XFor example, typing "50%" will move the cursor to the middle of the file.
+X.IP "Regular Expressions"
+XIn regular expressions, several new forms of closure operators are supported:
+X\\{\fIn\fR}, \\{\fIn\fR,\fIm\fR}, \\+, and \\?.
+X.NH 2
+XOmissions
+X.PP
+XThe replace mode is a hack.
+XIt doesn't save the text that it overwrites.
+X.PP
+XLong lines are displayed differently -- where the real vi would
+Xwrap a long line onto several rows of the screen, \*E simply
+Xdisplays part of the line, and allows you to scroll the screen
+Xsideways to see the rest of it.
+X.PP
+XThe ":preserve" and ":recover" commands are missing.
+XSo is the -r flag.
+XI've never had a good reason to use ":preserve",
+Xand since ":recover" is used so rarely
+XI decided to implement it as a separate program.
+XThere's no need to load the recovery code into memory every
+Xtime you edit a file, I figured.
+X.PP
+XLISP support is missing.
+XHowever, the = key is still an operator that reformats lines of text.
+XBy default, it reformats lines by sending them through the \fIfmt\fP filter,
+Xbut you could write your own LISP beautifier and configure elvis to use it.
+XKey mappings could take care of most other differences.
+XAuto-indent is the only thing that is irrecoverably lost.
+X.PP
+XAutoindent mode acts a little different from the real vi, anyway.
+XIt doesn't handle ^^D or 0^D correctly.
+XOn the other hand, it \fIdoes\fP allow ^D and ^T to be used anywhere in the
+Xline, to adjust the indentation for the whole line.
+/
+echo x - environ.ms
+sed '/^X/s///' > environ.ms << '/'
+X.Go 11 "ENVIRONMENT VARIABLES"
+X.PP
+X\*E examines several environment variables when it starts up.
+XThe values of these variables are used internally for a variety
+Xof purposes.
+XYou don't need to define all of these;
+Xon most systems, \*E only requires TERM to be defined.
+XOn AmigaDOS, MS-DOS or TOS systems, even that is optional.
+X.SH
+XTERM, TERMCAP
+X.PP
+XTERM tells \*E the name of the termcap entry to use.
+XTERMCAP may contain either the entire termcap entry,
+Xor the full pathname of the termcap file to search through.
+X.PP
+XIf your version of \*E is using tinytcap instead of the full termcap library,
+Xthen the value of TERMCAP \fIcannot\fR contain any backslash escapes (\\E, \\r, etc.)
+Xor carat escapes (^[, ^M, etc.), because tinytcap doesn't understand them.
+XInstead, you should embed the actual control character into the string.
+X.SH
+XTMP, TEMP
+X.PP
+XThese only work for AmigaDOS, MS-DOS and Atari TOS.
+XEither of these variables may be used to set the "directory" option,
+Xwhich controls where temporary files are stored.
+XIf you define them both, then TMP is used, and TEMP is ignored.
+X.SH
+XLINES, COLUMNS
+X.PP
+XThe termcap entry for your terminal should specify the size of your screen.
+XIf you're using a windowing interface, then there is an ioctl() call which
+Xwill provide the size of the window; the ioctl() values will override the
+Xvalues in the termcap entry.
+XThe LINES and COLUMNS environment variables (if defined)
+Xwill override either of these sources.
+XThey, in turn, can be overridden by a ":set" command.
+X.PP
+XNormally, the LINES and COLUMNS variables shouldn't need to be defined.
+X.SH
+XEXINIT
+X.PP
+XThis variable's value may contain one or more colon-mode commands,
+Xwhich will be executed after all of the ".exrc" files
+Xbut before interactive editing begins.
+X.PP
+XTo put more than one command in EXINIT, you can separate the commands
+Xwith either a newline or a '|' character.
+X.SH
+XSHELL, COMSPEC
+X.PP
+XYou can use COMSPEC in MS-DOS, or SHELL in any other system,
+Xto specify which shell should be used for executing commands and
+Xexpanding wildcards.
+X.SH
+XHOME
+X.PP
+XThis variable should give the full pathname of your home directory.
+X\*E needs to know the name of your home directory so it can locate
+Xthe ".exrc" file there.
+X.SH
+XTAGPATH
+X.PP
+XThis variable is used by the "ref" program.
+XIt contains a list of directories that might contain a relevent "tags" file.
+XUnder AmigaDOS, MS-DOS or Atari TOS, the names of the directories should be separated by
+Xsemicolons (";").
+XUnder other operating systems, the names should be separated by colons (":").
+X.PP
+XIf you don't define TAGPATH, then "ref" will use a default list which includes
+Xthe current directory and a few other likely places.
+XSee the definition of DEFTAGPATH at the start of ref.c for an accurate list.
+/
+echo x - ex.ms
+sed '/^X/s///' > ex.ms << '/'
+X.Go 3 "COLON MODE COMMANDS"
+X.ID
+X.ps
+X.in 0.8i
+X.ta 2i 3.i
+X.\" NOTE: The following macro is used to output a single line of the
+X.\" command chart.  Its usage is:
+X.\"
+X.\"		.Cm <linespecs> <name> <arguments>...
+X.\"
+X.de Cm
+X.if "\\$1"0" \t\\$2\t\\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+X.if "\\$1"1" \s-2[line]\s+2\t\\$2\t\\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+X.if "\\$1"2" \s-2[line][,line]\s+2\t\\$2\t\\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+X..
+X.if t .ds Q ``
+X.if t .ds U ''
+X.if n .ds Q "
+X.if n .ds U "
+X\s+2LINES	COMMAND	ARGUMENTS\s-2
+X.Cm 0 ab[br] [short] [expanded form]
+X.Cm 1 a[ppend][!]
+X.Cm 0 ar[gs] [files]
+X.Cm 0 cc [files]
+X.Cm 0 cd[!] [directory]
+X.Cm 2 c[hange]
+X.Cm 0 chd[ir][!] [directory]
+X.Cm 2 co[py] line
+X.Cm 0 col[or] [when] [[\*Qlight\*U] color] [\*Qon\*U color]
+X.Cm 2 d[elete] [\*Ux]
+X.Cm 0 dig[raph][!] [XX [Y]]
+X.Cm 0 e[dit][!] [file]
+X.Cm 0 er[rlist][!] [errlist]
+X.Cm 0 f[ile] [file]
+X.Cm 2 g[lobal] /regexp/ command
+X.Cm 1 i[nsert]
+X.Cm 2 j[oin][!]
+X.Cm 2 l[ist]
+X.Cm 0 mak[e] [target]
+X.Cm 0 map[!] key mapped_to
+X.Cm 1 ma[rk]  \*Ux
+X.Cm 0 mk[exrc]
+X.Cm 2 m[ove] line
+X.Cm 0 n[ext][!] [files]
+X.Cm 0 N[ext][!]
+X.Cm 2 nu[mber]
+X.Cm 2 p[rint]
+X.Cm 1 pu[t] [\*Ux]
+X.Cm 0 q[uit][!]
+X.Cm 1 r[ead] file
+X.Cm 0 rew[ind][!]
+X.Cm 0 se[t] [options]
+X.Cm 0 so[urce] file
+X.Cm 2 s[ubstitute] /regexp/replacement/[p][g][c]
+X.Cm 0 ta[g][!] tagname
+X.Cm 0 una[bbr] [short]
+X.Cm 0 u[ndo]
+X.Cm 0 unm[ap][!] key
+X.Cm 0 ve[rsion]
+X.Cm 2 v[global] /regexp/ command
+X.Cm 0 vi[sual] [filename]
+X.Cm 0 wq 
+X.Cm 2 w[rite][!] [[>>]file]
+X.Cm 0 x[it][!]
+X.Cm 2 y[ank] [\*Ux]
+X.Cm 2 ! command
+X.Cm 2 < 
+X.Cm 2 = 
+X.Cm 2 > 
+X.Cm 2 & 
+X.Cm 0 @ "" \*Ux
+X.DE
+X.TA
+X.PP
+XTo use colon mode commands, you must switch from visual command
+Xmode to colon command mode.
+XThe visual mode commands to do this are ":" for a single colon command,
+Xor "Q" for many colon mode commands.
+X.NH 2
+XLine Specifiers
+X.PP
+XLine specifiers are always optional.
+XThe first line specifier of most commands usually defaults to the current line.
+XThe second line specifier usually defaults to be the same
+Xas the first line specifier.
+XExceptions are :write, :global, and :vglobal, which act on all lines of the
+Xfile by default, and :!, which acts on no lines by default.
+X.PP
+XLine specifiers consist of an absolute part and a relative part.
+XThe absolute part of a line specifier may be either an explicit line number,
+Xa mark, a dot to denote the current line, a dollar sign to denote the last
+Xline of the file, or a forward or backward search.
+X.PP
+XAn explicit line number is simply a decimal number, expressed as a
+Xstring of digits.
+X.PP
+XA mark is typed in as an apostrophe followed by a letter.
+XMarks must be set before they can be used.
+XYou can set a mark in visual command mode by typing "m" and a letter,
+Xor you can set it in colon command mode via the "mark" command.
+X.PP
+XA forward search is typed in as a regular expression surrounded by
+Xslash characters; searching begins at the default line.
+XA backward search is typed in as a regular expression surrounded by
+Xquestion marks; searching begins at the line before the default line.
+X.PP
+XIf you omit the absolute part, then the default line is used.
+X.PP
+XThe relative part of a line specifier is typed as a "+" or "-" character
+Xfollowed by a decimal number.
+XThe number is added to or subtracted from the absolute part
+Xof the line specifier to produce the final line number.
+X.PP
+XAs a special case, the % character may be used to specify all lines of the file.
+XIt is roughly equivelent to saying 1,$.
+XThis can be a handy shortcut.
+X.PP
+XSome examples:
+X.LD
+X.ps
+X.ta 0.5i 1.8i
+X	:p	print the current line
+X	:37p	print line 37
+X	:'gp	print the line which contains mark g
+X	:/foo/p	print the next line that contains "foo"
+X	:$p	print the last line of the file
+X	:20,30p	print lines 20 through 30
+X	:1,$p	print all lines of the file
+X	:%p	print all lines of the file
+X	:/foo/-2,+4p	print 5 lines around the next "foo"
+X.TA
+X.DE
+X.NH 2
+XText Entry Commands
+X.if n .ul 0
+X.ID
+X.ps
+X[line] append
+X[line][,line] change ["x]
+X[line] insert
+X.DE
+X.PP
+XThe \fBa\fRppend command inserts text after the specified line.
+X.PP
+XThe \fBi\fRnsert command inserts text before the specified line.
+X.PP
+XThe \fBc\fRhange command copies the range of lines into a cut buffer,
+Xdeletes them, and inserts new text where the old text used to be.
+X.PP
+XFor all of these commands, you indicate the end of the text you're
+Xinserting by hitting ^D or by entering a line which contains only a
+Xperiod.
+X.NH 2
+XCut & Paste Commands
+X.if n .ul 0
+X.ID
+X.ps
+X[line][,line] delete ["x]
+X[line][,line] yank ["x]
+X[line] put ["x]
+X[line][,line] copy line
+X[line][,line] to line
+X[line][,line] move line
+X.DE
+X.PP
+XThe \fBd\fRelete command copies the specified range of lines into a
+Xcut buffer, and then deletes them.
+X.PP
+XThe \fBy\fRank command copies the specified range of lines into a cut
+Xbuffer, but does *not* delete them.
+X.PP
+XThe \fBpu\fRt command inserts text from a cut buffer after the
+Xspecified line.
+X.PP
+XThe \fBco\fRpy and \fBt\fRo commands yank the specified range of lines and
+Xthen immediately paste them after some other line.
+X.PP
+XThe \fBm\fRove command deletes the specified range of lines and then
+Ximmediately pastes them after some other line.
+XIf the destination line comes after the deleted text,
+Xthen it will be adjusted automatically to account for the deleted lines.
+X.NH 2
+XDisplay Text Commands
+X.if n .ul 0
+X.ID
+X.ps
+X[line][,line] print
+X[line][,line] list
+X[line][,line] number
+X.DE
+X.PP
+XThe \fBp\fRrint command displays the specified range of lines.
+X.PP
+XThe \fBnu\fRmber command displays the lines, with line numbers.
+X.PP
+XThe \fBl\fRist command also displays them, but it is careful to make
+Xcontrol characters visible.
+X.NH 2
+XGlobal Operations Commands
+X.if n .ul 0
+X.ID
+X.ps
+X[line][,line] global /regexp/ command
+X[line][,line] vglobal /regexp/ command
+X.DE
+X.PP
+XThe \fBg\fRlobal command searches through the lines of the specified range
+X(or through the whole file if no range is specified)
+Xfor lines that contain a given regular expression.
+XIt then moves the cursor to each of these lines and
+Xruns some other command on them.
+X.PP
+XThe \fBv\fRglobal command is similar, but it searches for lines that \fIdon't\fR
+Xcontain the regular expression.
+X.NH 2
+XLine Editing Commands
+X.if n .ul 0
+X.ID
+X.ps
+X[line][,line] join[!]
+X[line][,line] ! program
+X[line][,line] <
+X[line][,line] >
+X[line][,line] substitute /regexp/replacement/[p][g][c]
+X[line][,line] &
+X.DE
+X.PP
+XThe \fBj\fRoin command catenates all lines in the specified range together
+Xto form one big line.
+XIf only a single line is specified, then the following line is catenated
+Xonto it.
+XThe normal ":join" inserts one or two spaces between the lines;
+Xthe ":join!" variation (with a '!') doesn't insert spaces.
+X.PP
+XThe \fB!\fR command runs an external filter program,
+Xand feeds the specified range of lines to it's stdin.
+XThe lines are then replaced by the output of the filter.
+XA typical example would be ":'a,'z!sort" to sort the lines 'a,'z.
+X.PP
+XThe \fB<\fR and \fB>\fR commands shift the specified range of lines left or right,
+Xnormally by the width of 1 tab character.
+XThe "shiftwidth" option determines the shifting amount.
+X.PP
+XThe \fBs\fRubstitute command finds the regular expression in each line,
+Xand replaces it with the replacement text.
+XThe "p" option causes the altered lines to be printed.
+XThe "g" option permits all instances of the regular expression
+Xto be found & replaced.
+X(Without "g", only the first occurrence in each line is replaced.)
+XThe "c" option asks for confirmation before each substitution.
+X.PP
+XThe \fB&\fR command repeats the previous substitution command.
+XActually, "&" is equivelent to "s//~/" with the same options as last time.
+XIt searches for the last regular expression that you specified for any purpose,
+Xand replaces it with the the same text
+Xthat was used in the previous substitution.
+X.NH 2
+XUndo Command
+X.if n .ul 0
+X.ID
+X.ps
+Xundo
+X.DE
+X.PP
+XThe \fBu\fRndo command restores the file to the state it was in before
+Xyour most recent command which changed text.
+X.NH 2
+XConfiguration & Status Commands
+X.if n .ul 0
+X.ID
+X.ps
+Xmap[!] [key mapped_to]
+Xunmap[!] key
+Xabbr [word expanded_form_of_word]
+Xunabbr word
+Xdigraph[!] [XX [Y]]
+Xset [options]
+Xmkexrc
+X[line] mark "x
+Xvisual
+Xversion
+X[line][,line] =
+Xfile [file]
+Xsource file
+X@ "x
+Xcolor [when] [["light"] color] ["on" color]
+X.DE
+X.PP
+XThe \fBma\fRp command allows you to configure \*E to recognize your function keys,
+Xand treat them as though they transmitted some other sequence of characters.
+XNormally this mapping is done only when in the visual command mode,
+Xbut with the [!] present it will map keys under input and replace modes as well.
+XWhen this command is given with no arguments,
+Xit prints a table showing all mappings currently in effect.
+XWhen called with two arguments, the first is the sequence that your
+Xfunction key really sends, and the second is the sequence that you want
+X\*E to treat it as having sent.
+XAs a special case, if the first argument is a number then \*E will map the
+Xcorresponding function key;
+Xfor example, ":map 7 dd" will cause the <F7> key to delete a line.
+X.PP
+XThe \fBunm\fRap command removes key definitions that were made via the map command.
+X.PP
+XThe \fBab\fRbr command is used to define/list a table of abbreviations.
+XThe table contains both the abbreviated form and the fully spelled-out form.
+XWhen you're in visual input mode, and you type in the abbreviated form,
+X\*E will replace the abbreviated form with the fully spelled-out form.
+XWhen this command is called without arguments, it lists the table;
+Xwith two or more arguments, the first argument is taken as the abbreviated
+Xform, and the rest of the command line is the fully-spelled out form.
+X.PP
+XThe \fBuna\fRbbr command deletes entries from the abbr table.
+X.PP
+XThe \fBdi\fRgraph command allows you to display the set of digraphs that \*E is
+Xusing, or add/remove a digraph.
+XTo list the set of digraphs, use the digraph command with no arguments.
+XTo add a digraph, you should give the digraph command two arguments.
+XThe first argument is the two ASCII characters that are to be combined;
+Xthe second is the non-ASCII character that they represent.
+XThe non-ASCII character's most significant bit is automatically set by the
+Xdigraph command, unless to append a ! to the command name.
+XRemoval of a digraph is similar to adding a digraph, except that you should
+Xleave off the second argument.
+X.PP
+XThe \fBse\fRt command allows you examine or set various options.
+XWith no arguments, it displays the values of options that have been changed.
+XWith the single argument "all" it displays the values of all options,
+Xregardless of whether they've been explicitly set or not.
+XOtherwise, the arguments are treated as options to be set.
+X.PP
+XThe \fBmk\fRexrc command saves the current configuration to a file
+Xcalled ".exrc" in the current directory.
+X.PP
+XThe mar\fBk\fR command defines a named mark to refer to a specific place
+Xin the file.
+XThis mark may be used later to specify lines for other commands.
+X.PP
+XThe \fBvi\fRsual command puts the editor into visual mode.
+XInstead of emulating ex, \*E will start emulating vi.
+X.PP
+XThe \fBve\fRrsion command tells you that what version of \*E this is.
+X.PP
+XThe \fB=\fR command tells you what line you specified, or,
+Xif you specified a range of lines, it will tell you both endpoints and
+Xthe number of lines included in the range.
+X.PP
+XThe \fBf\fRile command tells you the name of the file,
+Xwhether it has been modified,
+Xthe number of lines in the file,
+Xand the current line number.
+XYou can also use it to change the name of the current file.
+X.PP
+XThe \fBso\fRurce command reads a sequence of colon mode commands from a file,
+Xand interprets them.
+X.PP
+XThe \fB@\fR command executes the contents of a cut-buffer as EX commands.
+X.PP
+XThe \fBcol\fRor command only works under MS-DOS, or if you have an ANSI-compatible
+Xcolor terminal.
+XIt allows you to set the foreground and background colors
+Xfor different types of text:
+Xnormal, bold, italic, underlined, standout, pop-up menu, and visible selection.
+XBy default, it changes the "normal" colors;
+Xto change other colors, the first argument to the :color command should be
+Xthe first letter of the type of text you want.
+XThe syntax for the colors themselves is fairly intuitive.
+XFor example, ":color light cyan on blue" causes normal text to be displayed
+Xin light cyan on a blue background, and
+X":color b bright white" causes bold text to be displayed in bright white on
+Xa blue background.
+XThe background color always defaults to the current background color of
+Xnormal text.
+XYour first :color command \fImust\fP specify both the foreground and background
+Xfor normal text.
+X.NH 2
+XMultiple File Commands
+X.if n .ul 0
+X.ID
+X.ps
+Xargs [files]
+Xnext[!] [files]
+XNext[!]
+Xprevious[!]
+Xrewind[!]
+X.DE
+X.PP
+XWhen you invoke \*E from your shell's command line,
+Xany filenames that you give to \*E as arguments are stored in the args list.
+XThe \fBar\fRgs command will display this list, or define a new one.
+X.PP
+XThe \fBn\fRext command switches from the current file to the next one
+Xin the args list.
+XYou may specify a new args list here, too.
+X.PP
+XThe \fBN\fRext and \fBpre\fRvious commands
+X(they're really aliases for the same command)
+Xswitch from the current file to the preceding file in the args list.
+X.PP
+XThe \fBrew\fRind command switches from the current file to the first file
+Xin the args list.
+X.NH 2
+XSwitching Files
+X.if n .ul 0
+X.ID
+X.ps
+Xedit[!] [file]
+Xtag[!] tagname
+X.DE
+X.PP
+XThe \fBe\fRdit command allows to switch from the current file to some other file.
+XThis has nothing to do with the args list, by the way.
+X.PP
+XThe \fBta\fRg command looks up a given tagname in a file called "tags".
+XThis tells it which file the tag is in, and how to find it in that file.
+X\*E then switches to the tag's file and finds the tag.
+X.NH 2
+XWorking with a Compiler
+X.if n .ul 0
+X.ID
+X.ps
+Xcc [files]
+Xmake [target]
+Xerrlist[!] [errlist]
+X.DE
+X.PP
+XThe \fBcc\fR and \fBmak\fRe commands execute your compiler or "make" utility
+Xand redirect any error messages into a file called "errlist".
+XBy default, cc is run on the current file.
+X(You should write it before running cc.)
+XThe contents of the "errlist" file are then scanned for error messages.
+XIf an error message is found, then the cursor is moved to the line where
+Xthe error was detected,
+Xand the description of the error is displayed on the status line.
+X.PP
+XAfter you've fixed one error, the \fBer\fRrlist command will move
+Xthe cursor to the next error.
+XIn visual command mode,
+Xhitting `*' will do this, too.
+X.PP
+XYou can also create an "errlist" file from outside of \*E,
+Xand use "\*E -m" to start elvis and have the cursor moved to the
+Xfirst error.
+XNote that you don't need to supply a filename with "\*E -m" because
+Xthe error messages always say which source file an error is in.
+X.PP
+XNote:
+XWhen you use errlist repeatedly to fix several errors in a single file,
+Xit will attempt to adjust the reported line numbers to allow for lines
+Xthat you have inserted or deleted.
+XThese adjustments are made with the assumption that you will work though
+Xthe file from the beginning to the end.
+X.NH 2
+XExit Commands
+X.if n .ul 0
+X.ID
+X.ps
+Xquit[!]
+Xwq
+Xxit
+X.DE
+X.PP
+XThe \fBq\fRuit command exits from the editor without saving your file.
+X.PP
+XThe \fBwq\fR command writes your file out, then then exits.
+X.PP
+XThe \fBx\fRit command is similar to the \fBwq\fR command, except that
+X\fBx\fRit won't bother to write your file if you haven't modified it.
+X.NH 2
+XFile I/O Commands
+X.if n .ul 0
+X.ID
+X.ps
+X[line] read file
+X[line][,line] write[!] [[>>]file]
+X.DE
+X.PP
+XThe \fBr\fRead command gets text from another file and inserts it
+Xafter the specified line.
+XIt can also read the output of a program;
+Xsimply precede the program name by a '!' and use it in place of the file name.
+X.PP
+XThe \fBw\fRrite command writes the whole file, or just part of it,
+Xto some other file.
+XThe !, if present, will permit the lines to be written even if you've set
+Xthe readonly option.
+XIf you precede the filename by >> then the lines will be appended to the file.
+XYou can send the lines to the standard input of a program by replacing the
+Xfilename with a '!' followed by the command and its arguments.
+X.PP
+XNote: Be careful not to confuse ":w!filename" and ":w !command".
+XTo write to a program, you must have at least one blank before the '!'.
+X.NH 2
+XDirectory Commands
+X.if n .ul 0
+X.ID
+X.ps
+Xcd [directory]
+Xchdir [directory]
+Xshell
+X.DE
+X.PP
+XThe \fBcd\fR and \fBchd\fRir commands
+X(really two names for one command)
+Xswitch the current working directory.
+X.PP
+XThe \fBsh\fRell command starts an interactive shell.
+X.NH 2
+XDebugging Commands
+X.if n .ul 0
+X.ID
+X.ps
+X[line][,line] debug[!]
+Xvalidate[!]
+X.DE
+X.PP
+XThese commands are only available if you compile \*E with the -DDEBUG flag.
+X.PP
+XThe de\fBb\fRug command lists statistics for the blocks which contain
+Xthe specified range of lines.
+XIf the ! is present, then the contents of those blocks is displayed, too.
+X.PP
+XThe \fBva\fRlidate command checks certain variables for internal consistency.
+XNormally it doesn't output anything unless it detects a problem.
+XWith the !, though, it will always produce *some* output.
+/
+echo x - index.ms
+sed '/^X/s///' > index.ms << '/'
+X.XS 1
+XINTRODUCTION
+XWhat E\s-2LVIS\s+2 does,
+XCopyright,
+XHow to compile E\s-2LVIS\s+2,
+XOverview
+X.XA 2
+XVISUAL MODE COMMANDS
+XNormal interactive editing,
+XInput mode,
+XArrow keys,
+XDigraphs,
+XAbbreviations,
+XAuto-indentation
+X.XA 3
+XCOLON MODE COMMANDS
+XLine specifiers,
+XText entry,
+XCut & paste,
+XDisplay text,
+XGlobal operations,
+XLine editing,
+XUndo,
+XConfiguration & status,
+XMultiple files,
+XSwitching files,
+XWorking with a compiler,
+XExiting,
+XFile I/O,
+XDirectory & shell,
+XDebugging
+X.XA 4
+XREGULAR EXPRESSIONS
+XSyntax,
+XOptions,
+XSubstitutions,
+XExamples
+X.XA 5
+XOPTIONS
+XAutoindent,
+XAutoprint,
+Xetc.
+X.XA 6
+XCUT BUFFERS
+XPutting text into a cut buffer,
+XPasting from a cut buffer,
+XMacros,
+XThe effect of switching files
+X.XA 7
+XDIFFERENCES BETWEEN E\s-2LVIS\s+2 AND THE REAL VI/EX
+XExtensions,
+XOmissions
+X.XA 8
+XINTERNAL
+XFor programmers only,
+XThe temporary file,
+XImplementation of editing,
+XMarks and the cursor,
+XColon command interpretation,
+XScreen control,
+XPortability
+X.XA 9
+XCFLAGS
+X.XA 10
+XTERMCAP
+X.XA 11
+XENVIRONMENT VARIABLES
+X.XA 12
+XVERSIONS
+X.XA 13
+XQUESTIONS & ANSWERS
+X.XE
+X.PX
+X.sp 0.3i
+X.ce 1
+XUNIX-style "man" pages appear at the end of this manual.
+/
+echo x - internal.ms
+sed '/^X/s///' > internal.ms << '/'
+X.Go 8 "INTERNAL"
+X.PP
+XYou don't need to know the material in this section to use \*E.
+XYou only need it if you intend to modify \*E.
+X.PP
+XYou should also check out the CFLAGS, TERMCAP, ENVIRONMENT VARIABLES,
+XVERSIONS, and QUIESTIONS & ANSWERS sections of this manual.
+X.NH 2
+XThe temporary file
+X.PP
+XThe temporary file is divided into blocks of 1024 bytes each.
+XThe functions in "blk.c" maintain a cache of the five most recently used blocks,
+Xto minimize file I/O.
+X.PP
+XWhen \*E starts up, the file is copied into the temporary file
+Xby the function \fBtmpstart()\fR in "tmp.c".
+XSmall amounts of extra space are inserted into the temporary file to
+Xinsure that no text lines cross block boundaries.
+XThis speeds up processing and simplifies storage management.
+XThe extra space is filled with NUL characters.
+Xthe input file must not contain any NULs, to avoid confusion.
+XThis also limits lines to a length of 1023 characters or less.
+X.PP
+XThe data blocks aren't necessarily stored in sequence.
+XFor example, it is entirely possible that the data block containing
+Xthe first lines of text will be stored after the block containing the
+Xlast lines of text.
+X.PP
+XIn RAM, \*E maintains two lists: one that describes the "proper"
+Xorder of the disk blocks, and another that records the line number of
+Xthe last line in each block.
+XWhen \*E needs to fetch a given line of text, it uses these tables
+Xto locate the data block which contains that line.
+X.PP
+XBefore each change is made to the file, these lists are copied.
+XThe copies can be used to "undo" the change.
+XAlso, the first list
+X-- the one that lists the data blocks in their proper order --
+Xis written to the first data block of the temp file.
+XThis list can be used during file recovery.
+X.PP
+XWhen blocks are altered, they are rewritten to a \fIdifferent\fR block in the file,
+Xand the order list is updated accordingly.
+XThe original block is left intact, so that "undo" can be performed easily.
+X\*E will eventually reclaim the original block, when it is no longer needed.
+X.NH 2
+XImplementation of Editing
+X.PP
+XThere are three basic operations which affect text:
+X.ID
+X\(bu delete text	- delete(from, to)
+X\(bu add text	- add(at, text)
+X\(bu yank text	- cut(from, to)
+X.DE
+X.PP
+XTo yank text, all text between two text positions is copied into a cut buffer.
+XThe original text is not changed.
+XTo copy the text into a cut buffer,
+Xyou need only remember which physical blocks that contain the cut text,
+Xthe offset into the first block of the start of the cut,
+Xthe offset into the last block of the end of the cut,
+Xand what kind of cut it was.
+X(Cuts may be either character cuts or line cuts;
+Xthe kind of a cut affects the way it is later "put".)
+XYanking is implemented in the function \fBcut()\fR,
+Xand pasting is implemented in the function \fBpaste()\fR.
+XThese functions are defined in "cut.c".
+X.PP
+XTo delete text, you must modify the first and last blocks, and
+Xremove any reference to the intervening blocks in the header's list.
+XThe text to be deleted is specified by two marks.
+XThis is implemented in the function \fBdelete()\fR.
+X.PP
+XTo add text, you must specify
+Xthe text to insert (as a NUL-terminated string)
+Xand the place to insert it (as a mark).
+XThe block into which the text is to be inserted may need to be split into
+Xas many as four blocks, with new intervening blocks needed as well...
+Xor it could be as simple as modifying a single block.
+XThis is implemented in the function \fBadd()\fR.
+X.PP
+XThere is also a \fBchange()\fR function,
+Xwhich generally just calls delete() and add().
+XFor the special case where a single character is being replaced by another
+Xsingle character, though, change() will optimize things somewhat.
+XThe add(), delete(), and change() functions are all defined in "modify.c".
+X.PP
+XThe \fBinput()\fR function reads text from a user and inserts it into the file.
+XIt makes heavy use of the add(), delete(), and change() functions.
+XIt inserts characters one at a time, as they are typed.
+X.PP
+XWhen text is modified, an internal file-revision counter, called \fBchanges\fR,
+Xis incremented.
+XThis counter is used to detect when certain caches are out of date.
+X(The "changes" counter is also incremented when we switch to a different file,
+Xand also in one or two similar situations -- all related to invalidating caches.)
+X.NH 2
+XMarks and the Cursor
+X.PP
+XMarks are places within the text.
+XThey are represented internally as 32-bit values which are split
+Xinto two bitfields:
+Xa line number and a character index.
+XLine numbers start with 1, and character indexes start with 0.
+XLines can be up to 1023 characters long, so the character index is 10 bits
+Xwide and the line number fills the remaining 22 bits in the long int.
+X.PP
+XSince line numbers start with 1,
+Xit is impossible for a valid mark to have a value of 0L.
+X0L is therefore used to represent unset marks.
+X.PP
+XWhen you do the "delete text" change, any marks that were part of
+Xthe deleted text are unset, and any marks that were set to points
+Xafter it are adjusted.
+XMarks are adjusted similarly after new text is inserted.
+X.PP
+XThe cursor is represented as a mark.
+X.NH 2
+XColon Command Interpretation
+X.PP
+XColon commands are parsed, and the command name is looked up in an array
+Xof structures which also contain a pointer to the function that implements
+Xthe command, and a description of the arguments that the command can take.
+XIf the command is recognized and its arguments are legal,
+Xthen the function is called.
+X.PP
+XEach function performs its task; this may cause the cursor to be
+Xmoved to a different line, or whatever.
+X.NH 2
+XScreen Control
+X.PP
+XIn input mode or visual command mode,
+Xthe screen is redrawn by a function called \fBredraw()\fR.
+XThis function is called in the getkey() function before each keystroke is
+Xread in, if necessary.
+X.PP
+XRedraw() write to the screen via a package which looks like the "curses"
+Xlibrary, but isn't.
+XIt is actually much simpler.
+XMost curses operations are implemented as macros which copy characters
+Xinto a large I/O buffer, which is then written with a single large
+Xwrite() call as part of the refresh() operation.
+X.PP
+X(Note: Under MS-DOS, the pseudo-curses macros check to see whether you're
+Xusing the pcbios interface.  If you are, then the macros call functions
+Xin "pc.c" to implement screen updates.)
+X.PP
+XThe low-level functions which modify text (namely add(), delete(), and change())
+Xsupply redraw() with clues to help redraw() decide which parts of the
+Xscreen must be redrawn.
+XThe clues are given via a function called \fBredrawrange()\fR.
+X.PP
+XMost EX commands use the pseudo-curses package to perform their output,
+Xlike redraw().
+X.PP
+XThere is also a function called \fBmsg()\fR which uses the same syntax as printf().
+XIn EX mode, msg() writes message to the screen and automatically adds a
+Xnewline.
+XIn VI mode, msg() writes the message on the bottom line of the screen
+Xwith the "standout" character attribute turned on.
+X.NH 2
+XOptions
+X.PP
+XFor each option available through the ":set" command,
+X\*E contains a character array variable, named "o_\fIoption\fR".
+XFor example, the "lines" option uses a variable called "o_lines".
+X.PP
+XFor boolean options, the array has a dimension of 1.
+XThe first (and only) character of the array will be NUL if the
+Xvariable's value is FALSE, and some other value if it is TRUE.
+XTo check the value, just by dereference the array name,
+Xas in "if (*o_autoindent)".
+X.PP
+XFor number options, the array has a dimension of 3.
+XThe array is treated as three unsigned one-byte integers.
+XThe first byte is the current value of the option.
+XThe second and third bytes are the lower and upper bounds of that
+Xoption.
+X.PP
+XFor string options, the array usually has a dimension of about 60
+Xbut this may vary.
+XThe option's value is stored as a normal NUL-terminated string.
+X.PP
+XAll of the options are declared in "opts.c".
+XMost are initialized to their default values;
+Xthe \fBinitopts()\fR function is used to perform any environment-specific
+Xinitialization.
+X.NH 2
+XPortability
+X.PP
+XTo improve portability, \*E collects as many of the system-dependent
+Xdefinitions as possible into the "config.h" file.
+XThis file begins with some preprocessor instructions which attempt to
+Xdetermine which compiler and operating system you have.
+XAfter that, it conditionally defines some macros and constants for your system.
+X.PP
+XOne of the more significant macros is \fBttyread()\fR.
+XThis macro is used to read raw characters from the keyboard, possibly
+Xwith timeout.
+XFor UNIX systems, this basically reads bytes from stdin.
+XFor MSDOS, TOS, and OS9, ttyread() is a function defined in curses.c.
+XThere is also a \fBttywrite()\fR macro.
+X.PP
+XThe \fBtread()\fR and \fBtwrite()\fR macros are versions of read() and write() that are
+Xused for text files.
+XOn UNIX systems, these are equivelent to read() and write().
+XOn MS-DOS, these are also equivelent to read() and write(),
+Xsince DOS libraries are generally clever enough to convert newline characters
+Xautomatically.
+XFor Atari TOS, though, the MWC library is too stupid to do this,
+Xso we had to do the conversion explicitly.
+X.PP
+XOther macros may substitute index() for strchr(), or bcopy() for memcpy(),
+Xor map the "void" data type to "int", or whatever.
+X.PP
+XThe file "tinytcap.c" contains a set of functions that emulate the termcap
+Xlibrary for a small set of terminal types.
+XThe terminal-specific info is hard-coded into this file.
+XIt is only used for systems that don't support real termcap.
+XAnother alternative for screen control can be seen in
+Xthe "curses.h" and "pc.c" files.
+XHere, macros named VOIDBIOS and CHECKBIOS are used to indirectly call
+Xfunctions which perform low-level screen manipulation via BIOS calls.
+X.PP
+XThe stat() function must be able to come up with UNIX-style major/minor/inode
+Xnumbers that uniquely identify a file or directory.
+X.PP
+XPlease try to keep you changes localized,
+Xand wrap them in #if/#endif pairs,
+Xso that \*E can still be compiled on other systems.
+XAnd PLEASE let me know about it, so I can incorporate your changes into
+Xmy latest-and-greatest version of \*E.
+/
+echo x - intro.ms
+sed '/^X/s///' > intro.ms << '/'
+X.Go 1 "INTRODUCTION"
+X.PP
+X\*E is a clone of vi/ex, the standard UNIX editor.
+X\*E supports nearly all of the vi/ex commands,
+Xin both visual mode and colon mode.
+X.PP
+XLike vi/ex, \*E stores most of the text in a temporary file, instead of RAM.
+XThis allows it to edit files that are too large to fit
+Xin a single process' data space.
+XAlso, the edit buffer can survive a power failure or crash.
+X.PP
+X\*E runs under BSD UNIX, AT&T SysV UNIX, Minix, MS-DOS, Atari TOS,
+XCoherent, OS9/68000, VMS and AmigaDos.
+XThe next version is also expected to add MS-Windows, OS/2 and MacOS.
+XContact me before you start porting it to some other OS,
+Xbecause somebody else may have already done it for you.
+X.PP
+X\*E is freely redistributable, in either source form or executable form.
+XThere are no restrictions on how you may use it.
+X.NH 2
+XCompiling
+X.PP
+XSee the "Versions" section of this manual for instructions on how to compile
+X\*E.
+X.PP
+XIf you want to port \*E to another O.S. or compiler, then
+Xyou should start be reading the "Portability" part of the "Internal" section.
+X.NH 2
+XOverview of \*E
+X.PP
+XThe user interface of \*E/vi/ex is weird.
+XThere are two major command modes in \*E, and a few text input modes as well.
+XEach command mode has a command which allows you to switch to the other mode.
+X.PP
+XYou will probably use the \fIvisual command mode\fR
+Xmost of the time.
+XThis is the mode that \*E normally starts up in.
+X.PP
+XIn visual command mode, the entire screen is filled with lines of text
+Xfrom your file.
+XEach keystroke is interpretted as part of a visual command.
+XIf you start typing text, it will \fInot\fR be inserted,
+Xit will be treated as part of a command.
+XTo insert text, you must first give an "insert text" command.
+XThis will take some getting used to.
+X(An alternative exists.
+XLookup the "inputmode" option.)
+X.PP
+XThe \fIcolon mode\fR is quite different.
+X\*E displays a ":" character on the bottom line of the screen, as a prompt.
+XYou are then expected to type in a command line and hit the <Return> key.
+XThe set of commands recognized in the colon mode is different
+Xfrom visual mode's.
+/
+echo x - options.ms
+sed '/^X/s///' > options.ms << '/'
+X.Go 5 "OPTIONS"
+X.PP
+XOptions may be set or examined via the colon command "set".
+XThe values of options will affect the operation of later commands.
+X.PP
+XFor convenience, options have both a long descriptive name and a short name
+Xwhich is easy to type.
+XYou may use either name interchangably.
+XI like the short names, myself.
+X.PP
+XThere are three types of options: Boolean, string, and numeric.
+XBoolean options are made TRUE by giving the name of the option as an
+Xargument to the "set" command;
+Xthey are made FALSE by prefixing the name with "no".
+XFor example, "set autoindent" makes the autoindent option TRUE,
+Xand "set noautoindent" makes it FALSE.
+X\*E also allows boolean options to be toggled by prefixing the name with "neg".
+XSo, ":map g :set neglist^M" will cause the <g> key to alternately toggle the
+X"list" option on and off.
+X(The "neg" prefix is an extension; the real vi doesn't support it.)
+X.PP
+XTo change the value of a string or numeric option, pass the "set" command
+Xthe name of the option, followed by an "=" sign and the option's new value.
+XFor example, "set tabstop=8" will give the tabstop option a value of 8.
+XFor string options, you may enclose the new value in quotes.
+X.LD
+X.ta 1.9i 2.4i 3.8i
+X.ps +2
+X\fBNAMES	TYPE	DEFAULT	MEANING\fP
+X.ps
+Xautoindent, ai	Bool	noai	auto-indent during input
+Xautoprint, ap	Bool	ap	in EX, print the current line
+Xautotab, at	Bool	at	auto-indent allowed to use tabs?
+Xautowrite, aw	Bool	noaw	auto-write when switching files
+Xbeautify,  bf	Bool	nobf	strip control chars from file?
+Xcharattr, ca	Bool	noca	interpret \\fX sequences?
+Xcc, cc	Str	cc="cc -c"	name of the C compiler
+Xcolumns, co	Num	co=80	width of the screen
+Xdigraph, dig	Bool	nodig	recognize digraphs?
+Xdirectory, dir	Str	dir="/usr/tmp"	where tmp files are kept
+Xedcompatible, ed	Bool	noed	remember ":s//" options
+Xequalprg, ep	Bool	ep="fmt"	program to run for = operator
+Xerrorbells, eb	Bool	eb	ring bell on error
+Xexrc, exrc	Bool	noexrc	read "./.exrc" file?
+Xexrefresh, er	Bool	er	write lines indiviually in EX
+Xflash, vbell	Bool	flash	use visible alternative to bell
+Xflipcase, fc	Str	fc=""	non-ASCII chars flipped by ~
+Xhideformat, hf	Bool	hf	hide text formatter commands
+Xignorecase, ic	Bool	noic	upper/lowercase match in search
+Xinputmode, im	Bool	noim	start vi in insert mode?
+Xkeytime, kt	Num	kt=2	timeout for mapped key entry
+Xkeywordprg, kp	Str	kp="ref"	full pathname of shift-K prog
+Xlines, ln	Num	ln=25	number of lines on the screen
+Xlist, li	Bool	noli	display lines in "list" mode
+Xmagic, ma	Bool	ma	use regular expression in search
+Xmake, mk	Str	mk="make"	name of the "make" program
+Xmesg, ms	Bool	ms	allow messages from other users?
+Xmodelines, ml	Bool	noml	are modelines processed?
+Xmore, more	Bool	more	pause between messages?
+Xnovice, nov	Bool	nonovice	set options for ease of use
+Xparagraphs, para	Str	para="PPppIPLPQP"	names of "paragraph" nroff cmd
+Xprompt, pr	Bool	pr	show ':' prompt in \fIex\fR mode
+Xreadonly, ro	Bool	noro	prevent overwriting of orig file
+Xremap, rem	Bool	remap	allow key maps to call key maps
+Xreport, re	Num	re=5	report when 5 or more changes
+Xruler, ru	Bool	noru	display line/column numbers
+Xscroll, sc	Num	sc=12	scroll amount for ^U and ^D
+Xsections, sect	Str	sect="NHSHSSSEse"	names of "section" nroff cmd
+Xshell, sh	Str	sh="/bin/sh"	full pathname of the shell
+Xshowmatch, sm	Bool	nosm	show matching ()[]{}
+Xshowmode, smd	Bool	nosmd	say when we're in input mode
+Xshiftwidth, sw	Num	sw=8	shift amount for < and >
+Xsidescroll, ss	Num	ss=8	amount of sideways scrolling
+Xsync, sy	Bool	nosy	call sync() often
+Xtabstop, ts	Num	ts=8	width of tab characters
+Xtaglength, tl	Num	tl=0	significant chars in tag name
+Xterm, te	Str	te="$TERM"	name of the termcap entry
+Xterse, tr	Bool	notr	give shorter error messages
+Xtimeout, to	Bool	to	distinguish <esc> from <arrow>?
+Xwarn, wa	Bool	wa	warn for ! if file modified
+Xwindow, wi	Num	wi=24	lines to redraw after long move
+Xwrapmargin, wm	Num	wm=0	wrap long lines in input mode
+Xwrapscan, ws	Bool	ws	at EOF, searches wrap to line 1
+Xwriteany, wr	Bool	nowr	allow :w to clobber files
+X.DE
+X.TA
+X.ne 6
+X.IP "autoindent, ai"
+XDuring input mode, the autoindent option will cause each added line
+Xto begin with the same amount of leading whitespace as the line above it.
+XWithout autoindent, added lines are initially empty.
+X.IP "autoprint, ap"
+XThis option only affects EX mode.
+XIf the autoprint option on,
+Xand either the cursor has moved to a different line
+Xor the previous command modified the file,
+Xthen \*E will print the current line.
+X.IP "autotab, at"
+XThis option affects the behaviour of the autoindent mode.
+XIf autoindent is turned off, then autotab has no effect.
+X.IP
+XWhen autotab is turned on, elvis will use a mixture of spaces and tabs
+Xto create the proper amount of indentation.
+XThis is the default.
+X.IP
+XWhen autotab is turned off, elvis will only use spaces for auto-indent.
+X\*E will still insert a real tab character when you hit the <Tab> key, though;
+Xthe autotab option only affects \fIautomatic\fR indentation.
+X.IP "autowrite, aw"
+XWhen you're editing one file and decide to switch to another
+X\- via the :tag command, or :next command, perhaps \-
+Xif your current file has been modified,
+Xthen \*E will normally print an error message and refuse to switch.
+X.IP
+XHowever, if the autowrite option is on,
+Xthen \*E will write the modified version of the current file
+Xand successfully switch to the new file.
+X.IP "beautify, bf"
+XThis option causes all control characters to be deleted from the text file,
+Xat the time when you start editing it.
+XIf you're already editing a file when you turn on the beautify option,
+Xthen that file won't be affected.
+X.IP cc
+XThe :cc command runs the C compiler.
+XThis option should be set to the name of your compiler.
+X.IP "charattr, ca"
+XMany text formatting programs allow you to designate portions of
+Xyour text to be underlined, italicized, or boldface by embedding
+Xthe special strings \\fU, \\fI, and \\fB in your text.
+XThe special string \\fP marks the end of underlined or boldface text.
+X.IP
+X\*E normally treats those special strings just like any other text.
+X.IP
+XHowever, if the charattr option is on, then \*E will interpret
+Xthose special strings correctly,
+Xto display underlined or boldface text on the screen.
+X(This only works, of course, if your terminal can display
+Xunderlined and boldface, and if the TERMCAP entry says how to do it.)
+X.IP "columns, co"
+XThis option shows how wide your screen is.
+X.IP "digraph, dig"
+XThis option is used to enable/disable recognition of digraphs.
+XThe default value is nodigraph, which means that digraphs will not be
+Xrecognized.
+X.IP "directory, dir"
+X\*E stores text in temporary files.
+XThis option allows you to control which directory those temporary files will
+Xappear in.
+XThe default is /usr/tmp.
+X.IP
+XThis option can only be set in a .exrc file;
+Xafter that, \*E will have already started making temporary files
+Xin some other directory, so it would be too late.
+X.IP "edcompatible, ed"
+XThis option affects the behaviour of the ":s/regexp/text/options" command.
+XIt is normally off (:se noed) which causes all of the substitution options
+Xto be off unless explicitly given.
+X.IP
+XHowever, with edcompatible on (:se ed), the substitution command remembers
+Xwhich options you used last time.
+XThose same options will continue to be used until you change them.
+XIn edcompatible mode, when you explicitly give the name of a
+Xsubstitution option, you will toggle the state of that option.
+X.IP
+XThis all seems very strange to me, but its implementation was almost free
+Xwhen I added the ":&" command to repeat the previous substitution,
+Xso there it is.
+X.IP "equalprg, ep"
+XThis holds the name & arguments of the external filter program
+Xused the the visual = operator.
+XThe defualt value is "fmt",
+Xso the = operator will adjust line breaks in text.
+X.IP "errorbells, eb"
+X\*E normally rings a bell when you do something wrong.
+XThis option lets you disable the bell.
+X.IP exrc
+XThis option specifies whether a .exrc file in the current directory
+Xshould be executed.
+XBy default, this option is off (":set noexrc") which prevents elvis from
+Xexecuting .exrc in the current directory.
+XIf the .exrc file in your home directory turns this option on (":set exrc")
+Xthen the \*E will attempt to execute the .exrc file in the current directory.
+X.IP
+XThis option exist mainly for security reasons.
+XA mean-spirited person could do something like
+X.br
+X	echo >/tmp/.exrc '!rm -rf $HOME'
+X.br
+Xand then anybody who attempted to edit or view a file in the /tmp directory
+Xwould lose most of their files.
+XWith the exrc option turned off, this couldn't happen to you.
+X.IP "exrefresh, er"
+XThe EX mode of \*E writes many lines to the screen.
+XYou can make \*E either write each line to the screen separately,
+Xor save up many lines and write them all at once.
+X.IP
+XThe exrefresh option is normally on, so each line is written to the
+Xscreen separately.
+X.IP
+XYou may wish to turn the exrefresh option off (:se noer) if the
+X"write" system call is costly on your machine, or if you're using a
+Xwindowing environment.
+X(Windowing environments scroll text a lot faster when you write
+Xmany lines at once.)
+X.IP
+XThis option has no effect in visual command mode or input mode.
+X.IP "flash, vbell"
+XIf your termcap entry describes a visible alternative to ringing
+Xyour terminal's bell, then this option will say whether the visible
+Xversion gets used or not.
+XNormally it will be.
+X.IP
+XIf your termcap does NOT include a visible bell capability,
+Xthen the flash option will be off, and you can't turn it on.
+X.IP "flipcase, fc"
+XThe flipcase option allows you to control how the non-ASCII characters are
+Xaltered by the "~" command.
+X.IP
+XThe string is divided into pairs of characters.
+XWhen "~" is applied to a non-ASCII character,
+X\*E looks up the character in the flipcase string to see which pair it's in,
+Xand replaces it by the other character of the pair.
+X.IP "hideformat, hf"
+XMany text formatters require you to embed format commands in your text,
+Xon lines that start with a "." character.
+X\*E normally displays these lines like any other text,
+Xbut if the hideformat option is on,
+Xthen format lines are displayed as blank lines.
+X.IP "ignorecase, ic"
+XNormally, when \*E searches for text, it treats uppercase letters
+Xas being different for lowercase letters.
+X.IP
+XWhen the ignorecase option is on, uppercase and lowercase are treated as equal.
+X.IP "inputmode, im"
+XThis option allows you to have \*E start up in insert mode.
+XYou can still exit insert mode at any time by hitting the ESC key, as usual.
+XUsually, this option would be set in your ".exrc" file.
+X.IP "keytime, kt"
+XThe arrow keys of most terminals send a multi-character sequence.
+XIt takes a measurable amount of time for these sequences to be transmitted.
+XThe keytime option allows you to control the maximum amount of time
+Xto allow for an arrow key (or other mapped key) to be received in full.
+X.IP
+XOn most systems, the setting is the number of tenths of a second to allow
+Xbetween characters.
+XOn some other systems, the setting is in whole seconds.
+X.IP
+XTry to avoid setting keytime=1.
+XMost systems just count clock beats, so if you tried to read a character
+Xshortly before a clock beat, you could allow almost no time at all for
+Xreading the characters.
+XFor higher keytime settings, the difference is less critical.
+X.IP
+XIf your system's response time is poor, you might want to increase the keytime.
+XIn particular, I've found that when keystrokes must be sent through a network
+X(via X windows, rlogin, or telnet, for example) the keytime should be set to
+Xat least 1 second.
+X.IP
+XAs a special case,
+Xyou can set keytime to 0 to disable this time limit stuff altogether.
+XThe big problem here is:
+XIf your arrow keys' sequences start with an ESC,
+Xthen every time you hit your ESC key \*E will wait... and wait...
+Xto see if maybe that ESC was part of an arrow key's sequence.
+X.IP
+XNOTE: this option is a generalization of the timeout option of the real vi.
+X.IP "keywordprg, kp"
+X\*E has a special keyword lookup feature.
+XYou move the cursor onto a word, and hit shift-K,
+Xand \*E uses another program to look up the word
+Xand display information about it.
+X.IP
+XThis option says which program gets run.
+X.IP
+XThe default value of this option is "ref",
+Xwhich is a program that looks up the definition of a function in C.
+XIt looks up the function name in a file called "refs" which is created by ctags.
+X.IP
+XYou can subtitute other programs, such as an English dictionary program
+Xor the online manual.
+X\*E runs the program, using the keyword as its only argument.
+XThe program should write information to stdout.
+XThe program's exit status should be 0, unless you want \*E to print
+X"<<< failed >>>".
+X.IP "lines, ln"
+XThis option says how many lines you screen has.
+X.IP "list, li"
+XIn nolist mode (the default), \*E displays text in a "normal" manner
+X-- with tabs expanded to an appropriate number of spaces, etc.
+X.IP
+XHowever, sometimes it is useful to have tab characters displayed differently.
+XIn list mode, tabs are displayed as "^I",
+Xand a "$" is displayed at the end of each line.
+X.IP "magic, ma"
+XThe search mechanism in \*E can accept "regular expressions"
+X-- strings in which certain characters have special meaning.
+X.IP
+XThe magic option is normally on, which causes these characters to be treated
+Xspecially.
+X.IP
+XIf you turn the magic option off (:se noma),
+Xthen all characters except ^ and $ are treated literally.
+X^ and $ retain their special meanings regardless of the setting of magic.
+X.IP "make, mk"
+XThe :make command runs your "make" program.
+XThis option defines the name of your "make" program.
+X.IP mesg
+XWith the real vi, running under real UNIX,
+X":set nomesg" would prevent other users from sending you messages.
+X\*E ignores it, though.
+X.IP "modelines, ml"
+X\*E supports modelines.
+XModelines are lines near the beginning or end of your text file which
+Xcontain "ex:yowza:",
+Xwhere "yowza" is any EX command.
+XA typical "yowza" would be something like "set ts=5 ca kp=spell wm=15".
+XOther text may also appear on a modeline,
+Xso you can place the "ex:yowza:" in a comment:
+X.br
+X.ID
+X/* ex:set sw=4 ai: */
+X.DE
+X.IP
+XNormally these lines are ignored, for security reasons,
+Xbut if you have "set modelines" in your .exrc file
+Xthen "yowza" is executed.
+X.IP "novice, nov"
+XThe command ":set novice" is equivelent to ":set nomagic report=1 showmode".
+X.IP "paragraphs, pa"
+XThe { and } commands move the cursor forward or backward in increments
+Xof one paragraph.
+XParagraphs may be separated by blank lines, or by a "dot" command of
+Xa text formatter.
+XDifferent text formatters use different "dot" commands.
+XThis option allows you to configure \*E to work with your text formatter.
+X.IP
+XIt is assumed that your formatter uses commands that start with a
+X"." character at the front of a line,
+Xand then have a one- or two-character command name.
+X.IP
+XThe value of the paragraphs option is a string in which each pair
+Xof characters is one possible form of your text formatter's paragraph
+Xcommand.
+X.IP "more"
+XWhen \*E must display a sequence of messages at the bottom line of the screen
+Xin visual mode, it normally pauses after all but the last one, so you have
+Xtime to read them all.
+X.IP
+XIf you turn off the "more" option, then \*E will not pause.
+XThis means you can only read the last message, but it is usually the most
+Ximportant one anyway.
+X.IP "prompt, pr"
+XIf you ":set noprompt", then \*E will no longer emit a ':' when it
+Xexpects you to type in an \fIex\fR command.
+XThis is slightly useful if you're using an astonishingly slow UNIX machine,
+Xbut the rest of us can just ignore this one.
+X.IP "readonly, ro"
+XNormally, \*E will let you write back any file to which you have
+Xwrite permission.
+XIf you don't have write permission, then you can only write the changed
+Xversion of the file to a \fIdifferent\fP file.
+X.IP
+XIf you set the readonly option,
+Xthen \*E will pretend you don't have write permission to \fIany\fP file you edit.
+XIt is useful when you really only mean to use \*E to look at a file,
+Xnot to change it.
+XThis way you can't change it accidentally.
+X.IP
+XThis option is normally off, unless you use the "view" alias of \*E.
+X"View" is like "vi" except that the readonly option is on.
+X.IP "remap"
+XThe ":map" command allows you to convert one key sequence into another.
+XThe remap option allows you to specify what should happen if portions of
+Xthat other sequence are also in the map table.
+XIf remap is on, then those portions will also be mapped, just as if they
+Xhad been typed on the keyboard.
+XIf remap is off, then the matching portions will not be mapped.
+X.IP
+XFor example, if you enter the commands ":map A B" and ":map B C",
+Xthen when remap is on, A will be converted to C.
+XBut when remap is off, A will be converted only to B.
+X.IP "report, re"
+XCommands in \*E may affect many lines.
+XFor commands that affect a lot of lines, \*E will output a message saying
+Xwhat was done and how many lines were affected.
+XThis option allows you to define what "a lot of lines" means.
+XThe default is 5, so any command which affects 5 or more lines will cause
+Xa message to be shown.
+X.IP "ruler, ru"
+XThis option is normally off.
+XIf you turn it on, then \*E will constantly display the line/column numbers
+Xof the cursor, at the bottom of the screen.
+X.IP "scroll, sc"
+XThe ^U and ^D keys normally scroll backward or forward by half a screenful,
+Xbut this is adjustable.
+XThe value of this option says how many lines those keys should scroll by.
+XIf you invoke ^U or ^D with a count argument (for example, "33^D") then
+Xthis option's value is set to the count.
+X.IP "sections, se"
+XThe [[ and ]] commands move the cursor backward or forward in increments of
+X1 section.
+XSections may be delimited by a { character in column 1
+X(which is useful for C source code)
+Xor by means of a text formatter's "dot" commands.
+X.IP
+XThis option allows you to configure \*E to work with your text formatter's
+X"section" command, in exectly the same way that the paragraphs option makes
+Xit work with the formatter's "paragraphs" command.
+X.IP "shell, sh"
+XWhen \*E forks a shell
+X(perhaps for the :! or :shell commands)
+Xthis is the program that is uses as a shell.
+XThis is "/bin/sh" by default,
+Xunless you have set the SHELL (or COMSPEC, for MS-DOS) environment variable,
+Xit which case the default value is copied from the environment.
+X.IP "shiftwidth, sw"
+XThe < and > commands shift text left or right by some uniform number of columns.
+XThe shiftwidth option defines that "uniform number".
+XThe default is 8.
+X.IP "showmatch, sm"
+XWith showmatch set,
+Xin input mode every time you hit one of )}],
+X\*E will momentarily move the cursor to the matching ({[.
+X.IP "showmode, smd"
+XIn visual mode, it is easy to forget whether you're in the visual command mode
+Xor input/replace mode.
+XNormally, the showmode option is off, and you haven't a clue as to which mode
+Xyou're in.
+XIf you turn the showmode option on, though, a little message will appear in the
+Xlower right-hand corner of your screen, telling you which mode you're in.
+X.IP "sidescroll, ss"
+XFor long lines, \*E scrolls sideways.
+X(This is different from the real vi,
+Xwhich wraps a single long line onto several rows of the screen.)
+X.IP
+XTo minimize the number of scrolls needed,
+X\*E moves the screen sideways by several characters at a time.
+XThe value of this option says how many characters' widths to scroll at a time.
+X.IP
+XGenerally, the faster your screen can be redrawn,
+Xthe lower the value you will want in this option.
+X.IP "sync, sy"
+XIf the system crashes during an edit session, then most of your work
+Xcan be recovered from the temporary file that \*E uses to store
+Xchanges.
+XHowever, sometimes the OS will not copy changes to the
+Xhard disk immediately, so recovery might not be possible.
+XThe [no]sync option lets you control this.
+X.IP
+XIn nosync mode (which is the default, for UNIX), \*E lets the operating system
+Xcontrol when data is written to the disk.
+XThis is generally faster.
+X.IP
+XIn sync mode (which is the default for MS-DOS, AmigaDos, and Atari TOS),
+X\*E forces all changes out
+Xto disk every time you make a change.
+XThis is generally safer, but slower.
+XIt can also be a rather rude thing to do on a multi-user system.
+X.IP "tabstop, ts"
+XTab characters are normally 8 characters wide,
+Xbut you can change their widths by means of this option.
+X.IP "taglength, tl"
+XThis option allows you to specify how many characters of a tag's name
+Xmust match when performing tag lookup.
+XAs a special case, ":set taglength=0" means that all characters of a tag's
+Xname must match.
+X.IP
+XNote: some configurations of \*E don't support this option.
+X.IP "term, te"
+XThis read-only option shows the name of the termcap entry that
+X\*E is using for your terminal.
+X.IP "terse, tr"
+XThe real vi uses this option to select longer vs. shorter error messages.
+X\*E has only one set of error messages, though, so this option has no effect.
+X.IP "timeout, to"
+XThe command ":set notimeout" is equivelent to ":set keytime=0",
+Xand ":set timeout" is equivelent to ":set keytime=1".
+XThis affects the behaviour of the <Esc> key.
+XSee the discussion of the "keytime" option for more information.
+X.IP "warn, wa"
+XIf you have modified a file but not yet written it back to disk, then
+X\*E will normally print a warning before executing a ":!cmd" command.
+XHowever, in nowarn mode, this warning is not given.
+X.IP
+X\*E also normally prints a message after a successful search that
+Xwrapped at EOF.
+XThe [no]warn option can also disable this warning.
+X.IP "window, wi"
+XThis option controls how many lines are redrawn after a long move.
+X.IP
+XOn fast terminals, this is usually set to the number of rows that the
+Xterminal can display, minus one.
+XThis causes the entire screen to be filled with text around the cursor.
+X.IP
+XOn slow terminals, you may wish to reduce this value to about 7 or so.
+XThat way, if you're doing something like repeatedly hitting 'n' to search
+Xfor each occurrence of some string and trying to find a particular occurrence,
+Xthen you don't need to wait as long for \*E to redraw the screen after each
+Xsearch.
+X.IP "wrapmargin, wm"
+XNormally (with wrapmargin=0) \*E will let you type in extremely long
+Xlines, if you wish.
+X.IP
+XHowever, with warpmargin set to something other that 0 (wrapmargin=10
+Xis nice), \*E will automatically cause long lines to be "wrapped"
+Xon a word break for lines come too close to the right-hand margin.
+XFor example: On an 80-column screen, ":set wm=10" will cause lines to
+Xwrap when their length exceeds 70 columns.
+X.IP "wrapscan, ws"
+XNormally, when you search for something, \*E will find it no matter
+Xwhere it is in the file.
+X\*E starts at the cursor position, and searches forward.
+XIf \*E hits EOF without finding what you're looking for,
+Xthen it wraps around to continue searching from line 1.
+XIf you turn off the wrapscan option (:se nows),
+Xthen when \*E hits EOF during a search, it will stop and say so.
+X.IP "writeany, wr"
+XWith "writeany" turned off, elvis will prevent you from accidentally
+Xoverwriting a file.
+XFor example, if "foo" exists then ":w foo" will fail.
+XIf you turn on the "writeany" option, then ":w foo" will work.
+X.IP
+XRegardless of the setting of "writeany", though, ":w! foo" will work.
+XThe '!' forces the ":w" command to write the file unless the operating system
+Xwon't allow it.
+/
+echo x - question.ms
+sed '/^X/s///' > question.ms << '/'
+X.nr Qn 0 1
+X.de QQ
+X.sp
+X.IP \fB\\n+(Qn) 0.3i
+X..
+X.de AA
+X.IP \fR 0.75i
+X..
+X.Go 13 "QUESTIONS & ANSWERS"
+X.QQ
+XHow can I make elvis run faster under DOS?
+X.AA
+XThere are several things you can do.
+XThe first thing to do is get a good screen driver such as NANSI.SYS.
+XThis can speed up screen redrawing by as much as a factor of eight!
+XThe DOS-specific part of section 12 tells you how to do this.
+X.AA
+XYou might also consider reducing the size of the blocks that elvis uses.
+XYou'll need to recompile \*E to do this.
+XThe default BLKSIZE is 1024 byte for the DOS version of \*E, which means
+Xthat for each keystroke that you insert, elvis must shift an average of
+Xabout 500 bytes.
+XThat's a lot to ask from a little old 5MHz 8088.
+XA BLKSIZE of 512 bytes might be more appropriate.
+X.AA
+XIf you're \fIreally\fR desperate for more speed, you might want to make
+X\*E store its temporary files on a RAM disk.
+XHowever, this limits the size of the file you can edit, and it eliminates any
+Xchance you may have had to recover your work after a power failure
+Xor system crash, but it might be worth it; you decide.
+XTo do this, add ":set dir=R:\\" (or whatever your RAM disk's name is)
+Xto the \fIelvis.rc\fP file.
+X.AA
+XNext, consider turning off the "sync" option.
+XWhen the sync option is turned on, \*E will close the temporary file
+Xand reopen it after every change, in order to force DOS to update
+Xthe file's directory entry.
+XIf you put ":set nosync" into the \fIelvis.rc\fP file, then elvis will
+Xonly close the file when you start editing a different text file, or
+Xwhen you're exiting \*E.
+XConsequently, there is no chance that you'll be able to recover your
+Xchanges after a power failure... so if you're going to this, then you
+Xmight as well store the temp files on the RAM disk, too.
+X.QQ
+XWhere's the <Esc> key on a DEC keyboard?
+X.AA
+XI don't know.  Maybe the <F11> key?
+XYou could always use ":map!" to make some other key act like the <Esc> key.
+XIf all else fails, use <Control><[>.
+X.QQ
+XIs there a way to show which keys do what?
+X.AA
+XYes.  The command ":map" will show what each key does in command mode,
+Xand ":map!" (with an exclamation mark) shows what each key does in
+Xinput mode.
+X.AA
+XThe table is divided into three columns: the key's label, the characters
+Xthat it sends, and the characters that \*E pretends you typed.
+X.QQ
+XHow can I make \*E display long lines like the real vi?
+X.AA
+XYou can't yet.
+XThe next version of \*E shouldsupport this, though.
+X.QQ
+XI can't recover my text [under MS-DOS or Atari TOS].
+XAccording to the directory listing, the temporary file is 0 bytes long.
+XWhat went wrong?
+X.AA
+XMS-DOS and TOS only update a file's directory entry when the file is closed.
+XIf the system crashes while the file is still open, then the file's length
+Xis stored as 0 bytes.
+XThe ":set sync" option is supposed to prevent this;
+Xyou probably turned it off in the interest of speed, right?
+X.AA
+XUnder MS-DOS [I don't know about TOS], you should delete the empty
+Xtemporary file, and then run CHKDSK/F.
+XThis \fImight\fP find the data that belonged in the empty file,
+Xand place it in a new file with a name like "000001.CHK" -- something like that.
+XYou can then try to extract the text from that temporary file by giving the
+Xcommand "elvprsv -R 000001.chk >goodnews.txt".
+XIf you're lucky, then your text might be in GOODNEWS.TXT.
+X.QQ
+XWhat is the most current version of \*E?
+X.AA
+XEach version of \*E that is released to the public has a version number
+Xof the form "number point number".
+XAs I write this, the most current version of elvis is 1.5.
+X.AA
+XThe intermediate steps between one release and the next are labeled with
+Xthe \fInext\fP version number, with a letter appended.
+XFor example, after 1.4 was released, I started working on 1.5a.
+XI am currently working on 2.0a.
+XWhen \*E reaches a stable state, I'll call it 2.0 and release it.
+X.AA
+XSometimes a beta-test version of elvis will be available via anonymous FTP
+Xfrom m2xenix.psg.com, in the directory "pub/elvis/beta".
+X.QQ
+XI only got executables, but now I want the source code.
+XWhere can I get it?
+X.AA
+XIf you have access to the Internet, then you should be able to fetch it
+Xfrom one of the public archives such as \fBplains.nodak.edu\fP.
+XIt is accessible via anonymous FTP, or via an email server named
+X"archive-server@plains.nodak.edu".
+XElvis is located in the directory "/pub/Minix/all.contrib".
+X.AA
+XI will also offer it to the C Users' Group.
+XThey sell C source code for us$8 per diskette
+X(or slightly more outside  North  America).
+XTheir phone number is (913) 841-1631,
+Xand their address is:
+X.ID
+XThe C Users' Group
+XPO Box 3127
+XLawrence KS 66046-0127
+X.DE
+X.QQ
+XIs this shareware, or public domain, or what?
+X.AA
+XIt is not public domain; it is copyrighted by me, Steve Kirkendall.
+XHowever, this particular version is freely redistributable, in either
+Xsource form or executable form.
+X(I would prefer that you give copies away for free, complete with the
+Xfull source code... but I'm not going to force you.)
+X.AA
+XIt is not shareware; you aren't expected to send me anything.
+XYou can use it without guilt.
+X.AA
+XIt is not "copylefted."
+XI hold a copyright, but currently I have not added any of the usual restrictions
+Xthat you would find on copylefted software.
+XIf people start doing really obnoxious things to \*E, then I will start
+Xadding restrictions to subsequent versions, but earlier versions won't
+Xbe affected.
+X(So far, everybody has been pretty good about this so no restrictions
+Xhave been necessary.)
+X.QQ
+XCan I reuse parts of your source code?
+X.AA
+XYes.  Please be careful, though, to make sure that the code really is mine.
+XSome of the code was contributed by other people, and I don't have the
+Xauthority to give you permission to use it.
+XThe author's name can be found near the top of each source file.
+XIf it says "Steve Kirkendall" then you may use it;
+Xotherwise, you'd better contact the author first.
+X.AA
+XPlease don't remove my name from the source code.
+XIf you modify the source, please make a note of that fact in a comment
+Xnear the top of the source code.
+XAnd, finally, please mention my name in your documentation.
+X.QQ
+XCan \*E work with non-ASCII files?
+X.AA
+X\*E can't edit binary files because it can't handle the NUL character,
+Xand because of line-length limitations.
+XHowever, it is 8-bit clean so you should be able to edit any European
+Xextended ASCII file without any surprises.
+X.AA
+X\*E has also been modified to work with 16-bit character sets.
+XYongguang Zhang (ygz@cs.purdue.edu) has created a Chinese version of \*E
+Xthat uses 16-bit characters and runs under cxterm (Chinese X-term)
+Xon X-windows systems.
+XJunichiro Itoh (itojun@foretune.co.jp) has modified \*E to edit Japanese
+Xtext under MS-DOS.
+/
+echo x - regexp.ms
+sed '/^X/s///' > regexp.ms << '/'
+X.Go 4 "REGULAR EXPRESSIONS"
+X
+X.PP
+X\*E uses regular expressions for searching and substututions.
+XA regular expression is a text string in which some characters have
+Xspecial meanings.
+XThis is much more powerful than simple text matching.
+X.SH
+XSyntax
+X.PP
+X\*E' regexp package treats the following one- or two-character
+Xstrings (called meta-characters) in special ways:
+X.IP "\\\\\\\\(\fIsubexpression\fP\\\\\\\\)" 0.8i
+XThe \\( and \\) metacharacters are used to delimit subexpressions.
+XWhen the regular expression matches a particular chunk of text,
+X\*E will remember which portion of that chunk matched the \fIsubexpression\fP.
+XThe :s/regexp/newtext/ command makes use of this feature.
+X.IP "^" 0.8i
+XThe ^ metacharacter matches the beginning of a line.
+XIf, for example, you wanted to find "foo" at the beginning of a line,
+Xyou would use a regular expression such as /^foo/.
+XNote that ^ is only a metacharacter if it occurs
+Xat the beginning of a regular expression;
+Xanyplace else, it is treated as a normal character.
+X.IP "$" 0.8i
+XThe $ metacharacter matches the end of a line.
+XIt is only a metacharacter when it occurs at the end of a regular expression;
+Xelsewhere, it is treated as a normal character.
+XFor example, the regular expression /$$/ will search for a dollar sign at
+Xthe end of a line.
+X.IP "\\\\\\\\<" 0.8i
+XThe \\< metacharacter matches a zero-length string at the beginning of
+Xa word.
+XA word is considered to be a string of 1 or more letters and digits.
+XA word can begin at the beginning of a line
+Xor after 1 or more non-alphanumeric characters.
+X.IP "\\\\\\\\>" 0.8i
+XThe \\> metacharacter matches a zero-length string at the end of a word.
+XA word can end at the end of the line
+Xor before 1 or more non-alphanumeric characters.
+XFor example, /\\<end\\>/ would find any instance of the word "end",
+Xbut would ignore any instances of e-n-d inside another word
+Xsuch as "calendar".
+X.IP "\&." 0.8i
+XThe . metacharacter matches any single character.
+X.IP "[\fIcharacter-list\fP]" 0.8i
+XThis matches any single character from the \fIcharacter-list\fP.
+XInside the \fIcharacter-list\fP, you can denote a span of characters
+Xby writing only the first and last characters, with a hyphen between
+Xthem.
+XIf the \fIcharacter-list\fP is preceded by a ^ character, then the
+Xlist is inverted -- it will match character that \fIisn't\fP mentioned
+Xin the list.
+XFor example, /[a-zA-Z]/ matches any letter, and /[^ ]/ matches anything
+Xother than a blank.
+X.IP "\\\\\\\\{\fIn\fP\\\\\\\\}" 0.8i
+XThis is a closure operator,
+Xwhich means that it can only be placed after something that matches a
+Xsingle character.
+XIt controls the number of times that the single-character expression
+Xshould be repeated.
+X.IP "" 0.8i
+XThe \\{\fIn\fP\\} operator, in particular, means that the preceding
+Xexpression should be repeated exactly \fIn\fP times.
+XFor example, /^-\\{80\\}$/ matches a line of eighty hyphens, and
+X/\\<[a-zA-Z]\\{4\\}\\>/ matches any four-letter word.
+X.IP "\\\\\\\\{\fIn\fP,\fIm\fP\\\\\\\\}" 0.8i
+XThis is a closure operator which means that the preceding single-character
+Xexpression should be repeated between \fIn\fP and \fIm\fP times, inclusive.
+XIf the \fIm\fP is omitted (but the comma is present) then \fIm\fP is
+Xtaken to be inifinity.
+XFor example, /"[^"]\\{3,5\\}"/ matches any pair of quotes which contains
+Xthree, four, or five non-quote characters.
+X.IP "*" 0.8i
+XThe * metacharacter is a closure operator which means that the preceding
+Xsingle-character expression can be repeated zero or more times.
+XIt is equivelent to \\{0,\\}.
+XFor example, /.*/ matches a whole line.
+X.IP "\\\\\\\\+" 0.8i
+XThe \\+ metacharacter is a closure operator which means that the preceding
+Xsingle-character expression can be repeated one or more times.
+XIt is equivelent to \\{1,\\}.
+XFor example, /.\\+/ matches a whole line, but only if the line contains
+Xat least one character.
+XIt doesn't match empty lines.
+X.IP "\\\\\\\\?" 0.8i
+XThe \\? metacharacter is a closure operator which indicates that the
+Xpreceding single-character expression is optional -- that is, that it
+Xcan occur 0 or 1 times.
+XIt is equivelent to \\{0,1\\}.
+XFor example, /no[ -]\\?one/ matches "no one", "no-one", or "noone".
+X.PP
+XAnything else is treated as a normal character which must exactly match
+Xa character from the scanned text.
+XThe special strings may all be preceded by a backslash to
+Xforce them to be treated normally.
+X.SH
+XSubstitutions
+X.PP
+XThe :s command has at least two arguments: a regular expression,
+Xand a substitution string.
+XThe text that matched the regular expression is replaced by text
+Xwhich is derived from the substitution string.
+X.br
+X.ne 15 \" so we don't mess up the table
+X.PP
+XMost characters in the substitution string are copied into the
+Xtext literally but a few have special meaning:
+X.LD
+X.ta 0.75i 1.3i
+X	&	Insert a copy of the original text
+X	~	Insert a copy of the previous replacement text
+X	\\1	Insert a copy of that portion of the original text which
+X		matched the first set of \\( \\) parentheses
+X	\\2-\\9	Do the same for the second (etc.) pair of \\( \\)
+X	\\U	Convert all chars of any later & or \\# to uppercase
+X	\\L	Convert all chars of any later & or \\# to lowercase
+X	\\E	End the effect of \\U or \\L
+X	\\u	Convert the first char of the next & or \\# to uppercase
+X	\\l	Convert the first char of the next & or \\# to lowercase
+X.TA
+X.DE
+X.PP
+XThese may be preceded by a backslash to force them to be treated normally.
+XIf "nomagic" mode is in effect,
+Xthen & and ~ will be treated normally,
+Xand you must write them as \\& and \\~ for them to have special meaning.
+X.SH
+XOptions
+X.PP
+X\*E has two options which affect the way regular expressions are used.
+XThese options may be examined or set via the :set command.
+X.PP
+XThe first option is called "[no]magic".
+XThis is a boolean option, and it is "magic" (TRUE) by default.
+XWhile in magic mode, all of the meta-characters behave as described above.
+XIn nomagic mode, only ^ and $ retain their special meaning.
+X.PP
+XThe second option is called "[no]ignorecase".
+XThis is a boolean option, and it is "noignorecase" (FALSE) by default.
+XWhile in ignorecase mode, the searching mechanism will not distinguish between
+Xan uppercase letter and its lowercase form.
+XIn noignorecase mode, uppercase and lowercase are treated as being different.
+X.PP
+XAlso, the "[no]wrapscan" option affects searches.
+X.SH
+XExamples
+X.PP
+XThis example changes every occurence of "utilize" to "use":
+X.sp
+X.ti +1i
+X:%s/utilize/use/g
+X.PP
+XThis example deletes all whitespace that occurs at the end of a line anywhere
+Xin the file.
+X(The brackets contain a single space and a single tab.):
+X.sp
+X.ti +1i
+X:%s/[   ]\\+$//
+X.PP
+XThis example converts the current line to uppercase:
+X.sp
+X.ti +1i
+X:s/.*/\\U&/
+X.PP
+XThis example underlines each letter in the current line,
+Xby changing it into an "underscore backspace letter" sequence.
+X(The ^H is entered as "control-V backspace".):
+X.sp
+X.ti +1i
+X:s/[a-zA-Z]/_^H&/g
+X.PP
+XThis example locates the last colon in a line,
+Xand swaps the text before the colon with the text after the colon.
+XThe first \\( \\) pair is used to delimit the stuff before the colon,
+Xand the second pair delimit the stuff after.
+XIn the substitution text, \\1 and \\2 are given in reverse order
+Xto perform the swap:
+X.sp
+X.ti +1i
+X:s/\\(.*\\):\\(.*\\)/\\2:\\1/
+/
+echo x - termcap.ms
+sed '/^X/s///' > termcap.ms << '/'
+X.Go 10 "TERMCAP"
+X.PP
+X\*E uses fairly standard termcap fields for most things.
+XI invented the cursor shape names
+Xbut other than that there should be few surprises.
+X.SH
+XRequired numeric fields
+X.if n .ul 0
+X.ID
+X:co#:	number of columns on the screen (chars per line)
+X:li#:	number of lines on the screen
+X.DE
+X.SH
+XRequired string fields
+X.ID
+X.if n .ul 0
+X:ce=:	clear to end-of-line
+X:cl=:	home the cursor & clear the screen
+X:cm=:	move the cursor to a given row/column
+X:up=:	move the cursor up one line
+X.DE
+X.SH
+XBoolean fields
+X.if n .ul 0
+X.ID
+X:am:	auto margins - wrap when char is written in last column?
+X:xn:	brain-damaged auto margins - newline ignored after wrap
+X:pt:	physical tabs?
+X.DE
+X.SH
+XOptional string fields
+X.if n .ul 0
+X.ID
+X:al=:	insert a blank row on the screen
+X:dl=:	delete a row from the screen
+X:cd=:	clear to end of display
+X:ei=:	end insert mode
+X:ic=:	insert a blank character
+X:im=:	start insert mode
+X:dc=:	delete a character
+X:sr=:	scroll reverse (insert row at top of screen)
+X:vb=:	visible bell
+X:ti=:	terminal initialization string, to start full-screen mode
+X:te=:	terminal termination, to end full-screen mode
+X:ks=:	enables the cursor keypad
+X:ke=:	disables the cursor keypad
+X.DE
+X.SH
+XOptional strings received from the keyboard
+X.if n .ul 0
+X.ID
+X:kd=:	sequence sent by the <down arrow> key
+X:kl=:	sequence sent by the <left arrow> key
+X:kr=:	sequence sent by the <right arrow> key
+X:ku=:	sequence sent by the <up arrow> key
+X:kP=:	sequence sent by the <PgUp> key
+X:kN=:	sequence sent by the <PgDn> key
+X:kh=:	sequence sent by the <Home> key
+X:kH=:	sequence sent by the <End> key
+X:kI=:	sequence sent by the <Insert> key
+X.DE
+X.PP
+XOriginally, termcap didn't have any names for the <PgUp>, <PgDn>, <Home>,
+Xand <End> keys.
+XAlthough the capability names shown in the table above are the most common,
+Xthey are \fInot\fR universal.
+XSCO Xenix uses :PU=:PD=:HM=:EN=: for those keys.
+XAlso, if the four arrow keys happen to be part of a 3x3 keypad,
+Xthen the five non-arrow keys may be named :K1=: through :K5=:,
+Xso an IBM PC keyboard may be described using those names instead.
+X\*E can find any of these names.
+X.SH
+XOptional strings sent by function keys
+X.if n .ul 0
+X.ID
+X:k1=:...:k9=:k0=:	codes sent by <F1> through <F10> keys
+X:s1=:...:s9=:s0=:	codes sent by <Shift F1> ... <Shift F10>
+X:c1=:...:c9=:c0=:	codes sent by <Ctrl F1> ... <Ctrl F10>
+X:a1=:...:a9=:a0=:	codes sent by <Alt F1> ... <Alt F10>
+X.DE
+X.PP
+XNote that :k0=: is used to describe the <F10> key.
+XSome termcap documents recommend :ka=: or even :k;=: for describing
+Xthe <F10> key, but \*E doesn't support that.
+X.PP
+XAlso, the :s1=:..., :c1=:..., and :a1=:... codes are very non-standard.
+XThe terminfo library doesn't support them.
+X.SH
+XOptional fields that describe character attributes
+X.if n .ul 0
+X.ID
+X:so=:se=:	start/end standout mode (We don't care about :sg#:)
+X:us=:ue=:	start/end underlined mode
+X:md=:me=:	start/end boldface mode
+X:as=:ae=:	start/end alternate character set (italics)
+X:ug#:		visible gap left by :us=:ue=:md=:me=:as=:ae=:
+X.DE
+X.SH
+XOptional fields that affect the cursor's shape
+X.PP
+XThe :cQ=: string is used by \*E immediately before exiting to undo
+Xthe effects of the other cursor shape strings.
+XIf :cQ=: is not given, then all other cursor shape strings are ignored.
+X.ID
+X:cQ=:	normal cursor
+X:cX=:	cursor used for reading EX command
+X:cV=:	cursor used for reading VI commands
+X:cI=:	cursor used during VI input mode
+X:cR=:	cursor used during VI replace mode
+X.DE
+X.PP
+XIf the capabilities above aren't given, then \*E will try to use the
+Xfollowing values instead.
+X.ID
+X:ve=:	normal cursor, used as :cQ=:cX=:cI=:cR=:
+X:vs=:	gaudy cursor, used as :cV=:
+X.DE
+X.SH
+XAn example
+X.PP
+XHere's the termcap entry I use on my Minix-ST system.
+XSome of the fields in it have nothing to do with \*E.
+XSome can only work on my system;
+XI have modified my kernel's screen driver.
+X.sp
+X.LD
+X.ne 14
+Xmx|minix|minixst|ansi:\\
+X	:is=\\E[0~:co#80:li#25:bs:pt:\\
+X	:cm=\\E[%i%d;%dH:up=\\E[A:do=^J:nd=\\E[C:sr=\\EM:\\
+X	:cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:\\
+X	:al=\\E[L:dl=\\E[M:ic=\\E[@:dc=\\E[P:im=:ei=:\\
+X	:so=\\E[7m:se=\\E[m:us=\\E[4m:ue=\\E[m:\\
+X	:md=\\E[1m:me=\\E[m:as=\\E[1;3m:ae=\\E[m:\\
+X	:ku=\\E[A:kd=\\E[B:kr=\\E[C:kl=\\E[D:\\
+X	:k1=\\E[1~:k2=\\E[2~:k3=\\E[3~:k4=\\E[4~:k5=\\E[5~:\\
+X	:k6=\\E[6~:k7=\\E[17~:k8=\\E[18~:k9=\\E[19~:k0=\\E[20~:\\
+X	:kU=\\E[36~:kQ=\\E[32~:kH=\\E[28~:\\
+X	:GV=3:GH=D:G1=?:G2=Z:G3=@:G4=Y:GC=E:GL=4:GR=C:GU=A:GD=B:\\
+X	:cQ=\\E[k:cX=\\E[2;0k:cV=\\E[16;0k:cI=\\E[k:cR=\\E[16;20k:
+X.DE
+/
+echo x - title.ms
+sed '/^X/s///' > title.ms << '/'
+X.de tE
+X.ps 80
+X.ce 1
+X\*E
+X..
+X.de nE
+X.ce 7
+X#######                                
+X#        #       #    #     #     #### 
+X#        #       #    #     #    #     
+X#####    #       #    #     #     #### 
+X#        #       #    #     #         #
+X#        #        #  #      #    #    #
+X#######  ######    ##       #     #### 
+X..
+X.sp |2i
+X.if t .tE
+X.if n .nE
+X.ps 10
+X.sp 1
+X.ce 2
+X- a clone of vi/ex -
+Xversion \*V
+X.sp |7.5i
+X.IP Author: 0.9i
+XSteve Kirkendall
+X.br
+X14407 SW Teal Blvd., Apt C
+X.br
+XBeaverton, OR 97005
+X.IP E-Mail: 0.9i
+Xkirkenda@cs.pdx.edu
+X.IP Phone: 0.9i
+X(503) 643-6980
+/
+echo x - ver.ms
+sed '/^X/s///' > ver.ms << '/'
+X.ds V 1.5j-betatest
+X.if t .ds E E\s-2LVIS\s+2
+X.if n .ds E Elvis
+X.\"
+X.\" usage: .Go <section#> <title>
+X.de Go
+X.ds LH "\\$1-\\\\n%
+X.ds RH "\\$1-\\\\n%
+X.ds CH "\\$2
+X.NH S \\$1
+X\\$2
+X.\"if !\\n%=1 .bp 1
+X.if n .ul 0
+X..
+/
+echo x - versions.ms
+sed '/^X/s///' > versions.ms << '/'
+X.Go 12 "VERSIONS"
+X.PP
+X\*E currently works under BSD UNIX, AT&T System-V UNIX, SCO XENIX,
+XMinix, Coherent, MS-DOS, Atari TOS, OS9/68k, VAX/VMS, and AmigaDos.
+XThis section of the manual provides special information that applies to each
+Xparticular version of \*E.
+X.PP
+XFor all versions except MS-DOS,
+Xthe file "Makefile.mix" should be copied to "Makefile",
+Xand then edited to select the correct set of options for your system.
+XThere is more information about this embedded in the file itself.
+X.NH 2
+XBSD UNIX
+X.PP
+XTemporary files are stored in /tmp.
+X.PP
+XYou should modify /etc/rc so that
+Xthe temp files are preserved when the system is rebooted.
+XFind a line in /etc/rc which reads
+X.br
+X.ti +0.5i
+Xex4.3preserve /tmp
+X.PP
+Xor something like that, and append the following line after it:
+X.br
+X.ti +0.5i
+Xelvprsv /tmp/elv*
+X.PP
+XIf you do not have permission to modify /etc/rc, don't fret.
+XThe above modification is only needed to allow you to recover your changes
+Xafter a system crash.
+XYou can still run \*E without that modification,
+Xand you can still recover your changes when \*E crashes
+Xor when your dialup modem looses the carrier signal, or something like that.
+XOnly a system crash or power failure could hurt you.
+X.PP
+XBoth \*E and the real Vi
+Xread initialization commands from a file called ".exrc",
+Xbut the commands in that file might work on one but not the other.
+XFor example, "set keywordprg=man" will work for \*E,
+Xbut Vi will complain because it doesn't have a "keywordprg" option.
+XIf the warning messages annoy you, then you can edit the config.h file
+Xto change the name of the initialization file ".exrc" to something else,
+Xsuch as ".elvisrc".
+X.PP
+XIf you use X windows, you may wish to add "-DCS_LATIN1" to CFLAGS.
+XThis will cause the digraph table and the flipcase option to have default
+Xvalues that are appropriate for the LATIN-1 character set.
+XThat's the standard character set for X.
+X.PP
+XThe default keyboard macro time-out value is larger for BSD than it is for
+Xsome other systems, because I've had trouble running \*E via rlogin or Xterm.
+XI guess it takes a while for those keystokes to squirt through the net.
+X.NH 2
+XSystem-V UNIX
+X.PP
+XMost SysV UNIX systems use terminfo instead of termcap,
+Xbut  the  terminfo  library  doesn't seem to have a standard name.
+XAs shipped, Elvis' Makefile.mix  is  configured  with "LIBS=-lterm".
+XYou may need to change it to "LIBS=-ltermcap" or "LIBS=-lterminfo"
+Xor even "LIBS=-lcurses".
+X.PP
+XThe /etc/rc file should be modified as described for BSD systems, above.
+XThe only difference is that SysV systems tend to have directories for
+Xinitialization, instead of a single large /etc/rc file.
+XEditor recovery is usually done somewhere in the /etc/rc2.d directory.
+X.PP
+XThe potential trouble with ".exrc" described above for BSD UNIX applies
+Xto System-V UNIX as well.
+X.PP
+X\*E uses control-C as the interrupt key, not Delete.
+X.NH 2
+XSCO Xenix
+X.PP
+XFor Xenix-386, you can use the generic System-V settings.
+XYou may wish to add "-DCS_IBMPC" to CFLAGS, to have the digraph table and
+Xflipcase option start up in a mode that is appropriate for the console.
+X
+XThere is a separate group of settings for use with Xenix-286.
+XIt already has "-DCS_IBMPC" in CFLAGS.
+X.PP
+XBecause Xenix is so similar to System-V, everything I said earlier about
+XSystem-V applies to the Xenix version too, except that editor recovery
+Xprobably belongs in a directory called /etc/rc.d/8.
+X.NH 2
+XMinix
+X.PP
+XThere are separate settings in Makefile.mix for Minix-PC and Minix-68k.
+XThe differences between these two are that
+Xthe 68k version uses ".o" for the object file extension where
+Xthe PC version uses ".s", and
+Xthe PC version has some extra flags in CFLAGS to reduce the size of \*E.
+XThe PC version also uses tinytcap (instead of the full termcap) to make it smaller.
+X.PP
+XMinix-PC users should read the CFLAGS section of this manual very carefully.
+XYou have some choices to make...
+X.PP
+XThe temporary files are stored in /usr/tmp.
+XThe /usr/tmp directory must exist before you run \*E,
+Xand it must be readable/writable by everybody.
+XWe use /usr/tmp instead of /tmp because
+Xafter a system crash or power failure,
+Xyou can recover the altered version of a file from the temporary file
+Xin /usr/tmp.
+XIf it was stored in /tmp, though, then it would be lost because /tmp is
+Xnormally located on the RAM disk.
+X.PP
+X\*E uses control-C as the interrupt key, not Delete.
+X.NH 2
+XCoherent
+X.PP
+X\*E was ported to Coherent by Esa Ahola.
+X.PP
+X\*E is too large to run under Coherent unless you eliminate some
+Xfeatures via the CFLAGS setting.
+XThe recommended settings, in Makefile.mix, produce a working version
+Xof \*E which emulates Vi faithfully, but lacks most of the extensions.
+XYou should read the CFLAGS section of this manual carefully.
+X.PP
+XYou can probably reduce the size of \*E by using tinytcap.c instead of -lterm.
+XThis would allow you to keep most features of \*E,
+Xat the expense of terminal independence.
+X(Tinytcap.c has ANSI escape sequences hard-coded into it.)
+XTo use tinytcap, just add "tinytcap.o" to the "EXTRA=" line in the Makefile,
+Xand remove "-lterm" from the "LIBS=" line.
+X.PP
+XThe temporary files are stored in /tmp.
+XYou should modify your /etc/rc file as described for BSD earlier.
+X.NH 2
+XMS-DOS
+X.PP
+X\*E was ported to MS-DOS by Guntram Blohm and Martin Patzel.
+XWillett Kempton added support for the DEC Rainbow.
+X.PP
+XIdeally, \*E should be compiled with Microsoft C 5.10 and the standard
+XMicrosoft Make utility,
+Xvia the command "make elvis.mak".
+XThis will compile \*E and all related utilities.
+X.PP
+XWith Microsoft C 6.00, you may have trouble compiling regexp.c.
+XIf so, try compiling it without optimization.
+X.PP
+XThe "Makefile.mix" file contains a set of suggested settings for compiling
+Xelvis with Turbo-C or Borland C.
+X(If you have Turbo-C, but not the Make utility,
+Xthen you can \fIalmost\fR use the "\*E.prj" file to compile \*E,
+Xbut you must explicitly force Turbo-C to compile it with the "medium" memory model.
+XMost of the related programs [ctags, ref, virec, refont, and wildcard] are
+Xonly one file long, so you should have no trouble compiling them.)
+XThe "alias.c" file is meant to be compiled once into an executable named
+X"ex.exe".
+XYou should then copy "ex.exe" to "vi.exe" and "view.exe".
+X.PP
+X\*E stores its temporary files in C:\\tmp.
+XIf this is not satisfactory, then you should edit the CFLAGS line of
+Xyour Makefile to change TMPDIR to something else before compiling.
+XYou can also control the name of the temp directory via an environment
+Xvariable named TMP or TEMP.
+XThe directory must exist before you can run \*E.
+X.PP
+XThe TERM environment variable determines how elvis will write to the screen.
+XIt can be set to any one of the following values:
+X.LD
+X.ta 1.5i 2.5i
+X	pcbios	Use BIOS calls on an IBM-PC clone.
+X	rainbow	Use DEC Rainbow interface.
+X	ansi	Use ANSI.SYS driver.
+X	nansi	User faster NANSI.SYS driver.
+X.DE
+X.PP
+XIf the TERM variable isn't set, then elvis will automatically select either
+Xthe "rainbow" interface (when run on a Rainbow) or "pcbios" (on an IBM clone).
+X.PP
+XYou may prefer to use NANSI.SYS for speed;
+Xor you may NEED to use ANSI.SYS for a non-clone, such as a lap-top.
+XIf so, you should
+Xinstall one of these drivers by adding "driver = nansi.sys" (or whatever)
+Xto your CONFIG.SYS file,
+Xand then you should define TERM to be "nansi" (or whatever) by adding
+X"set TERM=nansi" to your AUTOEXEC.BAT file.
+XYou must then reboot for these changes to take effect.
+XAfter that, \*E will notice the "TERM" setting and use the driver.
+X.PP
+XSince ".exrc" is not a valid DOS filename,
+Xthe name of the initialization file has been changed to "elvis.rc".
+XElvis will look for an "elvis.rc" file first in your home directory,
+Xand then in the current directory.
+XNote that you must set an environment variable named "HOME" to the
+Xfull pathname of your home directory, for Elvis to check there;
+Xif "HOME" isn't set, then Elvis will only look in the current directory.
+XTo set "HOME", you would typically add the following line to your
+XAUTOEXEC.BAT file:
+X.br
+X.ti +0.5i
+Xset HOME c:\\
+X.PP
+XAn extra program, called "wildcard", is needed for MS-DOS.
+XIt expands wildcard characters in file names.
+XIf \*E flashes a "Bad command or filename" message when it starts,
+Xthen you've probably lost the WILDCARD.EXE program somehow.
+X.PP
+X\*E can run under Windows, but only in full-screen mode.
+XAlso, Windows uses an environment variable called TEMP which interferes with
+Xelvis' usage of TEMP;
+Xto work around this, you can simply set an environment variable named
+XTMP (with no 'E') to the name of elvis' temporary directory.
+XWhen TEMP and TMP are both set, \*E uses TMP and ignored TEMP.
+X.NH 2
+XAtari TOS
+X.PP
+X\*E was ported to Atari TOS by Guntram Blohm and Martin Patzel.
+XIt is very similar to the MS-DOS version.
+XIt has been tested with the Mark Williams C compiler and also GNU-C.
+X.PP
+XThe TERM environment variable is ignored;
+Xthe ST port always assumes that TERM=vt52.
+XThe SHELL (not COMSPEC!) variable should be set to
+Xthe name of a line-oriented shell.
+X.PP
+XA simple shell in included with \*E.
+XIts source is in "shell.c", and the name of the executable is "shell.ttp".
+XThe file "profile.sh" should contain a set of instructions to be executed
+Xwhen the shell first starts up.
+XAn example of this file is included, but you will almost certainly want to
+Xedit it right away to match your configuration.
+X(If you already have a command-line shell,
+Xthen you'll probably want to continue using it.
+XThe shell that comes with \*E is very limited.)
+X.PP
+XCurrently, character attributes cannot be displayed on the screen.
+X.PP
+X\*E runs under MiNT (a free multi-tasking extension to TOS)
+Xbut it can be a CPU hog because of the way that \*E reads from the
+Xkeyboard with timeout.
+XAlso, \*E doesn't use any of the special features of MiNT.
+XI have received a set of patches that optimize \*E for MiNT,
+Xbut they arrived too late to integrate into this release.
+X.NH 2
+XOS9/68k
+X.PP
+X\*E was ported to OS9/68k by Peter Reinig.
+X.PP
+XThe Makefile is currently configured to install \*E and the related
+Xprograms in /dd/usr/cmds
+XIf this this is unacceptable, then you should change the BIN setting
+Xto some other directory.
+XSimilarly, it expects the source code to reside in /dd/usr/src/elvis;
+Xthe ODIR setting is used to control this.
+X.PP
+XTemporary files are stored in the /dd/tmp directory.
+XYour /dd/startup file may need to be modified
+Xto prevent it from deleting \*E' temporary files;
+Xmake /dd/startup run the \fIelvprsv\fR program before it wipes out /dd/tmp.
+X.PP
+XThe program in alias.c is linked repeatedly to produce the
+X"vi", "view", and "input" aliases for \*E.
+XSadly, the "ex" alias is impossible to implement under OS9
+Xbecause the shell has a built-in command by that name.
+X.PP
+XFor some purposes,
+Xyou must give `make' the "-b" option.
+XSpecifically, you need this for "make -b clean" and "make -b install".
+X.NH 2
+XVAX/VMS
+X.PP
+XJohn Campbell ported \*E to VAX/VMS.
+X.PP
+XA heavily laden VAX can take half an hour to compile elvis.
+XThis is normal.
+XDon't panic.
+X.PP
+XWhile running, elvis will create temporary files in SYS$SCRATCH.
+XEnter SHOW LOGICAL SYS$SCRATCH to see what actual directory you are using.
+XMany sites have SYS$SCRATCH equivalenced to SYS$LOGIN.
+XThe elvis temporary files look like the following on VMS while elvis is running:
+X.br
+X.ti 0.75i
+XELV_1123A.1;1       ELV_1123A.2;1       SO070202.;1
+X.PP
+XAlso, filtering commands (like !!dir and !}fmt) should work on VMS.
+XThis assumes, however, that you can create temporary mailboxes and that
+Xyour mailbox quota (a sysgen parameter) is at least 256 bytes for a
+Xsingle write to the mailbox.
+XThis is the default sysgen parameter,
+Xso there should be few people who experience filter problems.
+X.PP
+XAdditionally, an attempt was made to support the standard terminals on VMS:
+X"vt52", "vt100", "vt200", "vt300", "vt101", "vt102".
+XNon-standard terminals could be supported by setting your terminal type to
+XUNKNOWN (by entering SET TERM/UNKNOWN)
+Xand defining the logical name ELVIS_TERM.
+XWhatever ELVIS_TERM translates to, however, will have to be included in
+Xtinytcap.c.
+XNote that the upper/lowercase distinctions are significant,
+Xand that DCL will upshift characters that are not quoted strings, so
+Xenter DEFINE ELVIS_TERM "hp2621a".
+XAs distributed, it would probably not be a good idea to have more than the
+Xstandard terminals in tinytcap.c (else it wouldn't be tiny, would it?).
+XChanges here, of course, would require a recompilation to take effect.
+X.PP
+XIf you have a version of the "termcap" library and database on your system,
+Xthen you may wish to replace tinytcap with the real termcap.
+X.NH 2
+XAmigaDOS
+X.PP
+XMike Rieser and Dale Rahn ported \*E to AmigaDOS.
+X.PP
+XThe port was done using Manx Aztec C version 5.2b.
+X\*E uses about as much space as it can and still be small code and data.
+X\*E should also compile under DICE, though there may be a little trouble with
+Xsigned versus unsigned chars.
+X.PP
+XThe port has been done so the same binary will run under both versions of AmigaDOS.
+XUnder AmigaDOS 2.04, \*E supports all the documented features.
+XIt also uses an external program ref to do tag lookup.
+XSo, the accompanying programs: ref and ctags are recommended.
+XUnder AmigaDOS 1.2/1.3 \*E works, buts lacks the more advanced features.
+X.PP
+XFor the port to AmigaDOS 2.04, we tried to use as many Native AmigaDOS
+Xcalls as we could.
+XThis should increase Elvis's chances at being compiled with other compilers.
+XDICE seems to have a different default char type.
+XYou may need to use the UCHAR() macro in tio.c.
+XTo test it, try the :map command; if it looks right, things are cool.
+X.PP
+XFor the port to AmigaDOS 1.3, we tried to make sure the program was at
+Xleast usable.
+XMany features are missing, most notably running commands in subshells.
+XAlso, what we could get working, we used Aztec functions to support them,
+Xso this part is little more compiler dependent.
+X.PP
+XAztec is compatible with the SAS libcall #pragma.
+XI personally prefer using the includes that come from Commodore over the ones
+Xsupplied with Aztec, but for people with a straight Aztec installation,
+XI went with the default names for the Aztec pragmas.
+X.PP
+XOne include you'll need is <sys/types.h>.
+XIts a common include when porting software just make yourself one.
+XIts a two line file that saves a lot of hassle especially in the elvis source.
+XSo, make a directory where your includes are located called `sys'
+Xand in a file below that type:
+X.br
+X.ti +0.8i
+X/* sys/types.h */
+X.br
+X.ti +0.8i
+X#include <exec/types.h>
+X.PP
+XWhen setting environment variables (either local or global) for
+Xvariables that specify a directory, make sure the variable ends in `:'
+Xor `/'.
+XThis saved from having to change much of the way elvis works.
+XThe default temporary directory (if TEMP and TMP aren't specified) is "T:".
+XThe default if HOME directory (if no HOME environment variable is set) is "S:".
+X.PP
+XTo avoid conlict with other uses, \*E uses elvis.rc instead of .exrc or
+Xwhere it looks for macros.
+X.NH 2
+XOther Systems
+X.PP
+XFor Sun workstations, use the BSD configuration.
+XEarlier versions of elvis didn't link correctly due to a quirk in Sun's
+Xversion of the "make" utility, but this version of elvis has a work-around
+Xfor that quirk so you should have no trouble at all.
+X.PP
+XFor Linux, use the SysV settings.
+XYou can probably just remove the "-lterm" from the "LIBS= -lterm" line,
+Xsince linux keeps the termcap functions in the standard C library.
+X.PP
+XFor other UNIXoid systems, I suggest you start with the Minix-68k settings
+Xand then grow from that.
+XMinix is a nice starting point because it is a clone of Version 7 UNIX,
+Xwhich was the last common ancestor of BSD UNIX and SysV UNIX.
+XAny Operating System which claims any UNIX compatibility what so ever
+Xwill therefore support V7/Minix code.
+XYou may need to fiddle with #include directives or something, though.
+XMinix-68k is a better starting point than Minix-PC because the PC compiler
+Xhas some severe quirks.
+/
+echo x - visual.ms
+sed '/^X/s///' > visual.ms << '/'
+X.Go 2 "VISUAL MODE COMMANDS"
+X.PP
+XMost visual mode commands are one keystroke long.
+XThe following table lists the operation performed by each keystroke,
+Xand also denotes any options or arguments that it accepts.
+XNotes at the end of the table describe the notation used in this table.
+X.PP
+XIn addition to the keys listed here, your keyboard's "arrow" keys
+Xwill be interpretted as the appropriate cursor movement commands.
+XThe same goes for <PgUp> and <PgDn>, if your keyboard has them.
+XThe <Insert> key will toggle between insert mode and replace mode.
+XThere is a colon mode command (":map", to be described later)
+Xwhich will allow you to define other keys, such as function keys.
+X.PP
+XA tip: visual command mode looks a lot like text input mode.
+XIf you forget which mode you're in, just hit the <Esc> key.
+XIf \*E beeps, then you're in visual command mode.
+XIf \*E does not beep, then you were in input mode,
+Xbut by hitting <Esc> you will have switched to visual command mode.
+XSo, one way or another, after <Esc> \*E will be ready for a command.
+X.LD
+X.ta 0.7i 1.3i
+X\s+2COMMAND	DESCRIPTION\s-2
+X	^A	Search for next occurence of word at cursor (MOVE)(EXT)
+X	^B	Move toward the top of the file by 1 screenful
+X	^C	--- (usually sends SIGINT, to interupt a command)
+Xcount	^D	Scroll down <count> lines (default 1/2 screen)
+Xcount	^E	Scroll up <count> lines
+X	^F	Move toward the bottom of the file by 1 screenful
+X	^G	Show file status, and the current line #
+Xcount	^H	Move left, like h (MOVE)
+X	^I	---
+Xcount	^J	Move down (MOVE)
+X	^K	---
+X	^L	Redraw the screen
+Xcount	^M	Move to the front of the next line (MOVE)
+Xcount	^N	Move down (MOVE)
+X	^O	---
+Xcount	^P	Move up (MOVE)
+X	^Q	--- (typically XON, which restarts screen updates)
+X	^R	Redraw the screen
+X	^S	--- (typically XOFF, which stops screen updates)
+X	^T	---
+Xcount	^U	Scroll up <count> lines (default 1/2 screen)
+X	^V	---
+X	^W	---
+Xcount	^X	Move to a physical column number on the screen (MOVE) (EXT)
+Xcount	^Y	Scroll down <count> lines
+X	^Z	--- (sometimes sends SIGSUSP, to suspend execution)
+X	ESC	---
+X	^\\	--- (usually sends SIGQUIT, which is ignored)
+X	^]	If the cursor is on a tag name, go to that tag
+X	^^	Switch to the previous file, like ":e #"
+X	^_	---
+Xcount	SPC	Move right,like l (MOVE)
+X	! \s-2mv\s+2	Run the selected lines thru an external filter program
+X	" \s-2key\s+2	Select which cut buffer to use next
+Xcount	# \s-2+\s+2	Increment a number (EDIT) (EXT)
+X	$	Move to the rear of the current line (MOVE)
+Xcount	%	Move to matching (){}[] or to a given % of file (MOVE) (EXT)
+Xcount	&	Repeat the previous ":s//" command here (EDIT)
+X	' \s-2key\s+2	Move to a marked line (MOVE)
+Xcount	(	Move backward <count> sentences (MOVE)
+Xcount	)	Move forward <count> sentences (MOVE)
+X	*	Go to the next error in the errlist (EXT)
+Xcount	+	Move to the front of the next line (MOVE)
+Xcount	,	Repeat the previous [fFtT] but in the other direction (MOVE)
+Xcount	-	Move to the front of the preceding line (MOVE)
+Xcount	.	Repeat the previous "edit" command
+X	/ \s-2text\s+2	Search forward for a given regular expression (MOVE)
+X	0	If not part of count, move to 1st char of this line (MOVE)
+X	1	Part of count
+X	2	Part of count
+X	3	Part of count
+X	4	Part of count
+X	5	Part of count
+X	6	Part of count
+X	7	Part of count
+X	8	Part of count
+X	9	Part of count
+X	: \s-2text\s+2	Run single EX cmd
+Xcount	;	Repeat the previous [fFtT] cmd (MOVE)
+X	< \s-2mv\s+2	Shift text left (EDIT)
+X	= \s-2mv\s+2	Reformat
+X	> \s-2mv\s+2	Shift text right (EDIT)
+X	? \s-2text\s+2	Search backward for a given regular expression (MOVE)
+X	@ \s-2key\s+2	Execute the contents of a cut-buffer as VI commands
+Xcount	A \s-2inp\s+2	Append at end of the line (EDIT)
+Xcount	B	Move back Word (MOVE)
+X	C \s-2inp\s+2	Change text from the cursor through the end of the line (EDIT)
+X	D	Delete text from the cursor through the end of the line (EDIT)
+Xcount	E	Move end of Word (MOVE)
+Xcount	F \s-2key\s+2	Move leftward to a given character (MOVE)
+Xcount	G	Move to line #<count> (default is the bottom line) (MOVE)
+Xcount	H	Move to home row (the line at the top of the screen)
+Xcount	I \s-2inp\s+2	Insert at the front of the line (after indents) (EDIT)
+Xcount	J	Join lines, to form one big line (EDIT)
+X	K	Look up keyword (EXT)
+Xcount	L	Move to last row (the line at the bottom of the screen)
+X	M	Move to middle row
+X	N	Repeat previous search, but in the opposite direction (MOVE)
+Xcount	O \s-2inp\s+2	Open up a new line above the current line (EDIT)
+X	P	Paste text before the cursor (EDIT)
+X	Q	Quit to EX mode
+X	R \s-2inp\s+2	Overtype (EDIT)
+Xcount	S \s-2inp\s+2	Change lines, like <count>cc
+Xcount	T \s-2key\s+2	Move leftward *almost* to a given character (MOVE)
+X	U	Undo all recent changes to the current line
+X	V	Start marking lines for c/d/y/</>/!/\\ (EXT)
+Xcount	W	Move forward <count> Words (MOVE)
+Xcount	X	Delete the character(s) to the left of the cursor (EDIT)
+Xcount	Y	Yank text line(s) (copy them into a cut buffer)
+X	Z Z	Save the file & exit
+X	[ [	Move back 1 section (MOVE)
+X	\\ \s-2mv\s+2	Pop-up menu for modifying text (EXT)
+X	] ]	Move forward 1 section (MOVE)
+X	^	Move to the front of the current line (after indent) (MOVE)
+Xcount	_	Move to the current line
+X	` \s-2key\s+2	Move to a marked character (MOVE)
+Xcount	a \s-2inp\s+2	Insert text after the cursor (EDIT)
+Xcount	b	Move back <count> words (MOVE)
+X	c \s-2mv\s+2	Change text (EDIT)
+X	d \s-2mv\s+2	Delete text (EDIT)
+Xcount	e	Move forward to the end of the current word (MOVE)
+Xcount	f \s-2key\s+2	Move rightward to a given character (MOVE)
+X	g	---
+Xcount	h	Move left (MOVE)
+Xcount	i \s-2inp\s+2	Insert text at the cursor (EDIT)
+Xcount	j	Move down (MOVE)
+Xcount	k	Move up (MOVE)
+Xcount	l	Move right (MOVE)
+X	m \s-2key\s+2	Mark a line or character
+X	n	Repeat the previous search (MOVE)
+Xcount	o \s-2inp\s+2	Open a new line below the current line (EDIT)
+X	p	Paste text after the cursor (EDIT)
+X	q	---
+Xcount	r \s-2key\s+2	Replace <count> chars by a given character (EDIT)
+Xcount	s \s-2inp\s+2	Replace <count> chars with text from the user (EDIT)
+Xcount	t \s-2key\s+2	Move rightward *almost* to a given character (MOVE)
+X	u	Undo the previous edit command
+X	v	Start marking characters for c/d/y/</>/!/\\ (EXT)
+Xcount	w	Move forward <count> words (MOVE)
+Xcount	x	Delete the character that the cursor's on (EDIT)
+X	y \s-2mv\s+2	Yank text (copy it into a cut buffer)
+X	z \s-2key\s+2	Scroll current line to the screen's +=top -=bottom .=middle
+Xcount	{	Move back <count> paragraphs (MOVE)
+Xcount	|	Move to column <count> (the leftmost column is 1)
+Xcount	}	Move forward <count> paragraphs (MOVE)
+Xcount	~	Switch a character between uppercase & lowercase (EDIT)
+X	DEL	--- (usually mapped to shift-X, so it deletes one character)
+X.DE
+X.IP count
+XMany commands may be preceded by a count.  This is a sequence of digits
+Xrepresenting a decimal number.  For most commands that use a count,
+Xthe command is repeated <count> times.  The count is always optional,
+Xand usually defaults to 1.
+X.IP key
+XSome commands require two keystrokes.  The first key always determines
+Xwhich command is to be executed.  The second key is used as a parameter
+Xto the command.
+X.IP mv
+XSome commands (! < > c d y \\ =) operate on text between the cursor and some
+Xother position.
+XThere are three ways that you can specifify that other position.
+X.IP
+XThe first way is to follow the command keystroke with a movement command.
+XFor example, "dw" deletes a single word.
+X"d3w" and "3dw" both delete three words.
+X.IP
+XThe second way is to type the command keystroke twice.
+XThis causes whole lines to be acted upon.
+XFor example, ">>" indents the current line.
+X"3>>" indents the current line and the following two lines.
+X.IP
+XThe last way is to move the cursor to one end of the text,
+Xtype 'v' or 'V' to start marking,
+Xmove the cursor to the other end,
+Xand then type the desired command key.
+X.IP inp
+XMany commands allow the user to interactively enter text.
+XSee the discussion of "input mode" in the following section.
+X.IP (EXT)
+XThese commands are extensions -- the real vi doesn't have them.
+X.IP (EDIT)
+XThese commands affect text, and may be repeated by the "." command.
+X.IP (MOVE)
+XThese commands move the cursor, and may be used to specify the extent
+Xof a member of the "mv" class of commands.
+X.NH 2
+XInput Mode
+X.PP
+XYou can't type text into your file directly from visual command mode.
+XInstead, you must first give a command which will put you into input mode.
+XThe commands to do this are A/C/I/O/R/S/a/i/o/s.
+X.PP
+XThe S/s/C/c commands temporarily place a $ at the end of the text that
+Xthey are going to change.
+X.PP
+XIn input mode, all keystrokes are inserted into the text at the
+Xcursor's position, except for the following:
+X.ID
+X^A	insert a copy of the last input text
+X^D	delete one indent character
+X^H	(backspace) erase the character before the cursor
+X^L	redraw the screen
+X^M	(carriage return) insert a newline (^J, linefeed)
+X^O	execute next key as a visual command (limited!)
+X^P	insert the contents of the cut buffer
+X^R	redraw the screen, like ^L
+X^T	insert an indent character
+X^U	backspace to the beginning of the line
+X^V	insert the following keystroke, even if special
+X^W	backspace to the beginning of the current word
+X^Z^Z	write the file & exit \*E
+X^[	(ESCape) exit from input mode, back to command mode
+X.DE
+X.PP
+XAlso, on some systems, ^S may stop output, ^Q may restart output,
+Xand ^C may interupt execution.
+X^@ (the NUL character) cannot be inserted.
+X.PP
+XThe R visual command puts you in overtype mode,
+Xwhich is a slightly different form of input mode.
+XIn overtype mode, each time you insert a character,
+Xone of the old characters is deleted from the file.
+X.NH 2
+XArrow keys in Input Mode
+X.PP
+XThe arrow keys can be used to move the cursor in input mode.
+X(This is an extension; the real Vi doesn't support arrow keys in input mode.)
+XThe <PgUp>, <PgDn>, <Home>, and <End> keys work in input mode, too.
+XThe <Delete> key deletes a single character in input mode.
+XThe <Insert> key toggles between input mode and replace mode.
+X.PP
+XThe best thing about allowing arrow keys to work in input mode is that
+Xas long as you're in input mode,
+X\*E seems to have a fairly ordinary user interface.
+XWith most other text editors, you are always in either insert mode or
+Xreplace mode, and you can use the arrow keys at any time to move the cursor.
+XNow, \*E can act like that, too.
+XIn fact, with the new "inputmode" option and the "control-Z control-Z" input
+Xcommand, you may never have to go into visual command mode for simple edit
+Xsessions.
+X.NH 2
+XDigraphs
+X.PP
+X\*E supports digraphs as a way to enter non-ASCII characters.
+XA digraph is a character which is composed of two other characters.
+XFor example, an apostrophe and the letter i could be defined as a digraph
+Xwhich is to be stored & displayed as an accented i.
+X.PP
+XThere is no single standard for extended ASCII character sets.
+X\*E can be compiled to fill the digraph with values appropriate for
+Xeither the IBM PC character set, or the LATIN-1 character set used by
+XX windows, or neither.
+X(See the discussions of -DCS_IBMPC and -DCS_LATIN1 in the CFLAGS section
+Xof this manual.)
+XYou can view or edit the digraph table via the ":digraph" colon command.
+X.PP
+XDigraphs will not be recognized until you've entered ":set digraph".
+X.PP
+XTo actually use a digraph
+Xtype the first character, then hit <Backspace>, and then type the
+Xsecond character.
+X\*E will then substitute the non-ASCII character in their place.
+X.NH 2
+XAbbreviations
+X.PP
+X\*E can expand abbreviations for you.
+XYou define an abbreviation with the :abbr command,
+Xand then whenever you type in the abbreviated form while in input mode,
+X\*E will immediately replace it with the long form.
+XCOBOL programmers should find this useful. :-)
+X.PP
+X\*E doesn't perform the substitution until you type a non-alphanumeric
+Xcharacter to mark the end of the word.
+XIf you type a control-V before that non-alphanumeric character, then
+X\*E will not perform the substitution.
+X.NH 2
+XAuto-Indent
+X.PP
+XWith the ":set autoindent" option turned on,
+X\*E will automatically insert leading whitespace at the beginning of each
+Xnew line that you type in.
+XThe leading whitespace is copied from the preceding line.
+X.PP
+XTo add more leading whitespace, type control-T.
+XTo remove some whitespace, type control-D.
+X.PP
+XIf you ":set noautotab", then the whitespace generated by control-T will
+Xalways consist of spaces -- never tabs.
+XSome people seem to prefer this.
+X.PP
+X\*E' autoindent mode isn't 100% compatible with vi's.
+XIn \*E, 0^D and ^^D don't work,
+X^U can wipeout all indentation, 
+Xand sometimes \*E will use a different amount of indentation than vi would.
+/
Index: /trunk/minix/commands/elvis/Knownbug.txt
===================================================================
--- /trunk/minix/commands/elvis/Knownbug.txt	(revision 9)
+++ /trunk/minix/commands/elvis/Knownbug.txt	(revision 9)
@@ -0,0 +1,68 @@
+The following options are missing:
+	[no]optimize	- affects screen redrawing method
+	[no]redraw	- simulate character insertion by redrawing line
+	[no]slowopen	- don't use character insertion
+	tags="tags"	- list of tags, used as TAGPATH
+
+I'd like to improve the versatility of the options whose value is a command:
+cc, make, kp, and ep.  I'd like to add some notation that allows you to say
+where to insert the current filename or current word.
+-------------------------------------------------------------------------------
+Currently, elvis is configured to look for | only in .exrc files.  It doesn't
+look for | in any interactively entered command lines, yet.
+-------------------------------------------------------------------------------
+The 'p', '#', and 'l' flags aren't supported.  Also, ex commands don't accept
+counts; e.g., ":c5" can't be used to change five lines. 
+-------------------------------------------------------------------------------
+The following have been reported, but have not been verified.  If you have
+experienced any of the following, and haven't reported it yet, then please
+report it now!  I need more information about these bugs.
+
+[Bugs that are not in this list should also be reported, of course.]
+
+- Under VMS on an 80-column screen, after scolling sideways to approximately
+  column 110, a ^L will not redraw the part of the line after the cursor.
+- On an Atari ST running under TOS: some ASCII keys seem to send '#' plus
+  another key.  (This is normal for non-ASCII keys like <F1> or <Help>, but
+  ASCII keys should always send a single ASCII character.)
+-------------------------------------------------------------------------------
+BIG JOBS:
+  Desirable extension: merge input mode and visual command mode.
+  Display long lines by wrapping, like the real vi (if ":set sidescroll=0")
+-------------------------------------------------------------------------------
+
+- In the ":w >>filename" command, elvis doesn't allow any whitespace between
+  the ">>" and "filename".
+
+- Elvis doesn't allow "backslash newline" inside a single EX command.
+
+- VMS intercepts the control-T character, which is normally used to increase
+  indentation.  The <Tab> key works, but it doesn't do quite the same thing.
+  (":map! ^I ^T" helps.)
+
+- Under VMS, file I/O is very slow.  Looking over the vmsio.c file, I get the
+  impression that it is rather over-done for elvis.  Its speed could
+  probably be inproved.
+
+- The errlist feature doesn't seem to work with the Borland compilers.  Perhaps
+  they write to stderr instead of stdout?  This will probably be easy to solve
+  once I modify the "cc" and "make" options, as described earlier.
+
+- The command ":0" should move the cursor to line 1.  Currently, it doesn't
+  move the cursor at all.
+
+- File preservation is still flakey.  On DOS/TOS/VMS systems, it is also more
+  complex that it should be.
+
+- The act of appending to a cut buffer (as in "Ayy) sets file modification
+  flag.  It shouldn't!
+
+- The .exrc file is limited to BLKSIZE bytes -- 2048 on most systems, but
+  1024 on Minicx-PC, Coherent, and MS-DOS.
+
+- I *still* haven't quite perfected the screen update code.  If you suspect
+  that the screen doesn't accurately reflect the contents of the edit buffer,
+  then you should try doing a control-L.
+
+  I'll be overhauling the screen update code soon to make it wrap long lines
+  like the real vi.  I expect to fix this bug then.
Index: /trunk/minix/commands/elvis/Makedoc
===================================================================
--- /trunk/minix/commands/elvis/Makedoc	(revision 9)
+++ /trunk/minix/commands/elvis/Makedoc	(revision 9)
@@ -0,0 +1,87 @@
+# This is the Makefile for Elvis' "doc" directory.  It makes use of a
+# troff-like formatter called mroff.  Since you probably don't have mroff,
+# you'll need to edit this Makefile before you can fully use it.  It can
+# also use nroff, though, so you should be able to get something out of it.
+#
+# make		Use nroff to create an ASCII version of the manual.
+# make foo.doc	Use nroff to create an ASCII version of foo.man or foo.ms
+# make manual	Use MROFF to print a typeset manual on a laser printer
+# make foo.1200	Use MROFF to print a typeset version of foo.man or foo.ms
+# make foo.100	Use MROFF to print a draft-quality version of foo.man or foo.ms
+# make foo.more	Use MROFF to preview foo.man or foo.more on your terminal
+#
+
+###############################################################################
+# Definitions...
+
+MAN=	ctags.man elvis.man elvprsv.man elvrec.man fmt.man ref.man
+MS=	title.ms index.ms intro.ms visual.ms ex.ms regexp.ms options.ms\
+	cutbufs.ms differ.ms internal.ms cflags.ms termcap.ms environ.ms\
+	versions.ms question.ms
+ASC=	title.doc index.doc intro.doc visual.doc ex.doc regexp.doc options.doc\
+	cutbufs.doc differ.doc internal.doc cflags.doc termcap.doc environ.doc\
+	versions.doc question.doc\
+	ctags.doc elvis.doc elvprsv.doc elvrec.doc fmt.doc ref.doc
+MANUAL=	title.1200 index.1200 intro.1200 visual.1200 ex.1200 regexp.1200 options.1200\
+	cutbufs.1200 differ.1200 internal.1200 cflags.1200 termcap.1200 environ.1200\
+	versions.1200\
+	ctags.1200 elvis.1200 elvprsv.1200 elvrec.1200 fmt.1200 ref.1200
+VER=	ver.ms
+TROFF=	mroff
+NROFF=	nroff
+
+###############################################################################
+# Rules...
+
+.SUFFIXES: .tmp .100 .1200 .more .doc .man .ms .vga .vgas
+
+.ms.tmp:
+	$(TROFF) -ms $(VER) $< >tmp
+
+.man.tmp:
+	$(TROFF) -man $< >tmp
+
+.ms.more:
+	$(TROFF) -ms $(VER) $< | draft | more
+
+.man.more:
+	$(TROFF) -man $< | draft | more
+
+.ms.1200:
+	$(TROFF) -ms $(VER) $< | hp2 1200 | lp -og $(PRINTER)
+
+.man.1200:
+	$(TROFF) -man $< | hp2 1200 | lp -og $(PRINTER)
+
+.ms.100:
+	$(TROFF) -ms $(VER) $< | hp2 100 | lp -og $(PRINTER)
+
+.man.100:
+	$(TROFF) -man $< | hp2 100 | lp -og $(PRINTER)
+
+.ms.doc:
+	$(NROFF) -ms $(VER) $< >$@
+
+.man.doc:
+	$(NROFF) -man $< >$@
+
+.ms.vga:
+	$(TROFF) -ms $(VER) $< >/tmp/foo
+	-vga /tmp/foo
+	rm /tmp/foo
+
+.ms.vgas:
+	$(TROFF) -ms $(VER) $< >/tmp/foo
+	-vgas /tmp/foo
+	rm /tmp/foo
+
+#############################################################################
+# Targets...
+
+asc: $(ASC)
+	cat $(ASC) >asc
+
+manual: $(MANUAL)
+
+clean:
+	rm -f *.doc *.sh
Index: /trunk/minix/commands/elvis/Makefile
===================================================================
--- /trunk/minix/commands/elvis/Makefile	(revision 9)
+++ /trunk/minix/commands/elvis/Makefile	(revision 9)
@@ -0,0 +1,92 @@
+# Makefile for elvis
+#
+# Several groups of Makefile settings are included below.  Choose *ONE* group
+# of settings for your particular system, and leave the others commented out.
+# The meanings of these settings are:
+#	EXTRA	version-specific object files used in elvis
+#	CC	the C compiler command, possibly with "memory model" flags
+#	CFLAGS	compiler flags used to select compile-time options
+#	PROGS	the list of all programs
+#	SORT	if the "tags" file must be sorted, then SORT=-DSORT
+
+CC = exec cc
+PROGS=	elvis ctags ref elvrec fmt elvprsv
+
+#---- These settings are recommended for Minix-PC ----
+EXTRA=	tinytcap.o tinyprnt.o
+CFLAGS=	-O -w -D_POSIX_SOURCE -D_MINIX -DCRUNCH \
+	-DNO_MKEXRC -DNO_CURSORSHAPE -DNO_CHARATTR -DNO_SHOWMODE \
+	-DNO_MODELINE -DNO_OPTCOLS -DNO_DIGRAPH -DNO_EXTENSIONS \
+	-DNO_ERRLIST -DNO_FKEY -DNO_VISIBLE -DNO_COLOR -DNO_POPUP
+LDFLAGS=-i
+
+#---- These settings are recommended for Minix-ST ----
+#EXTRA=
+#CFLAGS=
+
+###########################################################################
+###     The rest of this Makefile contains no user-serviceable parts    ###
+###########################################################################
+
+OBJ=blk.o cmd1.o cmd2.o ctype.o curses.o cut.o ex.o input.o \
+   main.o misc.o modify.o move1.o move2.o move3.o move4.o move5.o \
+   opts.o recycle.o redraw.o regexp.o regsub.o system.o tio.o tmp.o \
+   unix.o vars.o vcmd.o vi.o
+
+all:	$(PROGS)
+
+elvis:	$(OBJ)
+	$(CC) $(LDFLAGS) -o elvis $(OBJ)
+	install -S 18kw elvis
+
+ctags:	ctags.c
+	$(CC) $(CFLAGS) $(SORT) $(LDFLAGS) -o ctags ctags.c
+	install -S 4kw $@
+
+ref:	ref.c
+	$(CC) $(CFLAGS) $(LDFLAGS) -o ref ref.c
+	install -S 4kw $@
+
+elvrec:	elvrec.c
+	$(CC) $(CFLAGS) $(LDFLAGS) -o elvrec elvrec.c
+	install -S 4kw $@
+
+fmt:	fmt.c
+	$(CC) $(CFLAGS) $(LDFLAGS) -o fmt fmt.c
+	install -S 4kw $@
+
+elvprsv:	elvprsv.c
+	$(CC) $(CFLAGS) $(LDFLAGS) -o elvprsv elvprsv.c ctype.o
+	install -S 4kw $@
+
+install:	/usr/bin/elvis \
+		/bin/elvis \
+		/usr/bin/ctags /usr/bin/ref /usr/bin/fmt \
+		/usr/bin/elvrec /usr/bin/elvprsv
+
+/usr/bin/elvis:	elvis
+	install -cs -o bin elvis $@
+
+/bin/elvis:	elvis
+	install -cs -o bin elvis $@
+
+/usr/bin/ctags:	ctags
+	install -cs -o bin ctags $@
+
+/usr/bin/ref:	ref
+	install -cs -o bin ref $@
+
+/usr/bin/fmt:	fmt
+	install -cs -o bin fmt $@
+
+/usr/bin/elvrec:	elvrec
+	install -cs -o root -m 4755 elvrec $@
+
+/usr/bin/elvprsv:	elvprsv
+	install -cs -o root -m 4755 elvprsv $@
+
+# Dependencies
+$(OBJ):	vi.h curses.h config.h regexp.h ctype.h
+
+clean:	
+	rm -f *.o ctags ref elvrec fmt elvprsv elvis
Index: /trunk/minix/commands/elvis/Man.sh
===================================================================
--- /trunk/minix/commands/elvis/Man.sh	(revision 9)
+++ /trunk/minix/commands/elvis/Man.sh	(revision 9)
@@ -0,0 +1,414 @@
+echo x - ctags.man
+sed '/^X/s///' > ctags.man << '/'
+X.TH CTAGS 1
+X.SH NAME
+Xctags - Generates "tags" and (optionally) "refs" files
+X.SH SYNOPSIS
+X\fBctags\fP [\fB-stvra\fP] \fIfilesnames\fP...
+X.SH DESCRIPTION
+X\fIctags\fP generates the "tags" and "refs" files
+Xfrom a group of C source files.
+XThe "tags" file is used by Elvis' ":tag" command,
+Xcontrol-] command,
+Xand -t option.
+XThe "refs" file is sometimes used by the \fIref(1)\fP program.
+X.PP
+XEach C source file is scanned for #define statements and
+Xglobal function definitions.
+XThe name of the macro or function becomes the name of a tag.
+XFor each tag, a line is added to the "tags" file which contains:
+X.RS
+X.nf
+X       - the name of the tag
+X       - a tab character
+X       - the name of the file containing the tag
+X       - a tab character
+X       - a way to find the particular line within the file.
+X.RE
+X.fi
+X.PP
+XThe filenames list will typically be the names of all C source
+Xfiles in the current directory, like this:
+X.RS
+X.nf
+X$ ctags -stv *.[ch]
+X.RE
+X.fi
+X.SH OPTIONS
+X.IP \fB-t\fR
+XInclude typedefs.
+XA tag will be generated for each user-defined type.
+XAlso tags will be generated for struct and enum names.
+XTypes are considered to be global if they are defined in a header file,
+Xand static if they are defined in a C source file.
+X.IP \fB-v\fR
+XInclude variable declarations.
+XA tag will be generated for each variable, except for those that are declared
+Xinside the body of a function.
+X.IP \fB-s\fR
+XInclude static tags.
+X\fICtags\fR will normally put global tags in the "tags" file, and silently ignore
+Xthe static tags.
+XThis flag causes both global and static tags to be added.
+XThe name of a static tag is generated by prefixing the name of the declared
+Xitem with the name of the file where it is defined, with a colon in between.
+XFor example, "static foo(){}" in "bar.c" results in a tag named "bar.c:foo".
+X.IP \fB-r\fP
+XThis causes \fIctags\fP to generate both "tags" and "refs".
+XWithout \fB-r\fP, it would only generate "tags".
+X.IP \fB-a\fR
+XAppend to "tags", and maybe "refs".
+XNormally, \fIctags\fR overwrites these files each time it is invoked.
+XThis flag is useful when you have to many files in the current directory
+Xfor you to list them on a single command-line;
+Xit allows you to split the arguments among several invocations.
+X.SH FILES
+X.IP tags
+XA cross-reference that lists each tag name, the name of the source file that
+Xcontains it, and a way to locate a particular line in the source file.
+X.IP refs
+XThe "refs" file contains the definitions for each tag in the "tags" file,
+Xand very little else.
+XThis file can be useful, for example, when licensing restrictions prevent
+Xyou from making the source code to the standard C library readable by everybody,
+Xbut you still everybody to know what arguments the library functions need.
+X.SH BUGS
+X.PP
+X\fIctags\fR is sensitive to indenting and line breaks.
+XConsequently, it might not discover all of the tags in a file that
+Xis formatted in an unusual way.
+X.SH "SEE ALSO"
+Xelvis(1), refs(1)
+X.SH AUTHOR
+X.nf
+XSteve Kirkendall
+Xkirkenda@cs.pdx.edu
+X.fi
+/
+echo x - elvis.man
+sed '/^X/s///' > elvis.man << '/'
+X.TH ELVIS 1
+X.SH NAME
+Xelvis, ex, vi, view, input - The editor
+X.SH SYNOPSIS
+X\fBelvis\fP [\fIflags\fP] [\fB+\fP\fIcmd\fP] [\fIfiles\fP...]
+X.SH DESCRIPTION
+X\fIElvis\fP is a text editor which emulates \fIvi\fP/\fIex\fP.
+X.PP
+XOn systems which pass the program name as an argument, such as Unix and Minix,
+Xyou may also install \fIelvis\fP under the names "ex", "vi", "view", and "input".
+XThese extra names would normally be links to elvis;
+Xsee the "ln" shell command.
+X.PP
+XWhen \fIelvis\fP is invoked as "vi",
+Xit behaves exactly as though it was invoked as "elvis".
+XHowever, if you invoke \fIelvis\fP as "view",
+Xthen the readonly option is set as though you had given it the "-R" flag.
+XIf you invoke \fIelvis\fP as "ex",
+Xthen \fIelvis\fP will start up in the colon command mode
+Xinstead of the visual command mode,
+Xas though you had given it the "-e" flag.
+XIf you invoke \fIelvis\fP as "input" or "edit",
+Xthen \fIelvis\fP will start up in input mode,
+Xas though the "-i" flag was given.
+X.SH OPTIONS
+X.IP \fB-r\fP
+XTo the real vi, this flag means that a previous edit should be recovered.
+X\fIElvis\fP, though, has a separate program, called \fIelvrec(1)\fP, for recovering
+Xfiles.
+XWhen you invoke \fIelvis\fP with -r, \fIelvis\fP will tell you to run \fIelvrec\fP.
+X.IP \fB-R\fP
+XThis sets the "readonly" option,
+Xso you won't accidentally overwrite a file.
+X.IP "\fB-t\fP \fItag\fP"
+XThis causes \fIelvis\fP to start editing at the given tag.
+X.IP "\fB-m\fP [\fIfile\fP]"
+X\fIElvis\fP will search through \fIfile\fP for something that looks like
+Xan error message from a compiler.
+XIt will then begin editing the source file that caused the error,
+Xwith the cursor sitting on the line where the error was detected.
+XIf you don't explicitly name a \fIfile\fP, then "errlist" is assumed.
+X.IP \fB-e\fP
+X\fIElvis\fP will start up in colon command mode.
+X.IP \fB-v\fP
+X\fIElvis\fP will start up in visual command mode.
+X.IP \fB-i\fP
+X\fIElvis\fP will start up in input mode.
+X.IP "\fB-w\fR \fIwinsize\fR"
+XSets the "window" option's value to \fIwinsize\fR.
+X.IP "\fB+\fP\fIcommand\fP or \fB-c\fP \fIcommand\fP"
+XIf you use the +\fIcommand\fP parameter,
+Xthen after the first file is loaded
+X\fIcommand\fP is executed as an EX command.
+XA typical example would be "elvis +237 foo",
+Xwhich would cause \fIelvis\fP to start editing foo and
+Xthen move directly to line 237.
+XThe "-c \fIcommand\fP" variant was added for UNIX SysV compatibility.
+X.SH FILES
+X.IP /tmp/elv*
+XDuring editing,
+X\fIelvis\fP stores text in a temporary file.
+XFor UNIX, this file will usually be stored in the /tmp directory,
+Xand the first three characters will be "elv".
+XFor other systems, the temporary files may be stored someplace else;
+Xsee the version-specific section of the documentation.
+X.IP tags
+XThis is the database used by the \fI:tags\fP command and the \fB-t\fP option.
+XIt is usually created by the \fIctags(1)\fP program.
+X.IP ".exrc or elvis.rc"
+XOn UNIX-like systems, a file called ".exrc" in your home directory
+Xis executed as a series of \fIex\fR commands.
+XA file by the same name may be executed in the current directory, too.
+XOn non-UNIX systems, ".exrc" is usually an invalid file name;
+Xthere, the initialization file is called "elvis.rc" instead.
+X.SH "SEE ALSO"
+Xctags(1), ref(1), virec(1)
+X.PP
+X\fIElvis - A Clone of Vi/Ex\fP, the complete \fIelvis\fP documentation.
+X.SH BUGS
+XThere is no LISP support.
+XCertain other features are missing, too.
+X.PP
+XAuto-indent mode is not quite compatible with the real vi.
+XAmong other things, 0^D and ^^D don't do what you might expect.
+X.PP
+XLong lines are displayed differently.
+XThe real vi wraps long lines onto multiple rows of the screen,
+Xbut \fIelvis\fP scrolls sideways.
+X.SH AUTHOR
+X.nf
+XSteve Kirkendall
+Xkirkenda@cs.pdx.edu
+X.fi
+X.PP
+XMany other people have worked to port \fIelvis\fP to various operating systems.
+XTo see who deserves credit, run the \fI:version\fP command from within \fIelvis\fP,
+Xor look in the system-specific section of the complete documentation.
+/
+echo x - elvprsv.man
+sed '/^X/s///' > elvprsv.man << '/'
+X.TH ELVPRSV 1
+X.SH NAME
+Xelvprsv - Preserve the the modified version of a file after a crash.
+X.SH SYNOPSIS
+X.nf
+X\fB\fBelvprsv\fP ["-\fIwhy elvis died\fP"] /tmp/\fIfilename\fP...
+X\fB\fBelvprsv\fP -R /tmp/\fIfilename\fP...
+X.fi
+X.SH DESCRIPTION
+X.PP
+X\fIelvprsv\fP preserves your edited text after \fIelvis\fP dies.
+XThe text can be recovered later, via the \fIelvprsv\fP program.
+X.PP
+XFor UNIX-like systems,
+Xyou should never need to run this program from the command line.
+XIt is run automatically when \fIelvis\fP is about to die,
+Xand it should be run (via /etc/rc) when the computer is booted.
+XTHAT'S ALL!
+X.PP
+XFor non-UNIX systems such as MS-DOS, you can either use \fIelvprsv\fP
+Xthe same way as under UNIX systems (by running it from your AUTOEXEC.BAT file),
+Xor you can run it separately with the "-R" flag to recover the files
+Xin one step.
+X.PP
+XIf you're editing a file when \fIelvis\fP dies
+X(due to a bug, system crash, power failure, etc.)
+Xthen \fIelvprsv\fP will preserve the most recent version of your text.
+XThe preserved text is stored in a special directory; it does NOT overwrite
+Xyour text file automatically.
+X.PP
+X\fIelvprsv\fP will send mail to any user whose work it preserves,
+Xif your operating system normally supports mail.
+X.SH FILES
+X.IP /tmp/elv*
+XThe temporary file that \fIelvis\fP was using when it died.
+X.IP /usr/preserve/p*
+XThe text that is preserved by \fIelvprsv\fP.
+X.IP /usr/preserve/Index
+XA text file which lists the names of all preserved files, and the names
+Xof the /usr/preserve/p* files which contain their preserved text.
+X.SH BUGS
+X.PP
+XDue to the permissions on the /usr/preserve directory, on UNIX systems
+X\fIelvprsv\fP must be run as superuser.
+XThis is accomplished by making the \fIelvprsv\fP executable be owned by "root"
+Xand turning on its "set user id" bit.
+X.PP
+XIf you're editing a nameless buffer when \fIelvis\fP dies, then \fIelvprsv\fP will pretend
+Xthat the file was named "foo".
+X.SH AUTHOR
+X.nf
+XSteve Kirkendall
+Xkirkenda@cs.pdx.edu
+X.fi
+/
+echo x - elvrec.man
+sed '/^X/s///' > elvrec.man << '/'
+X.TH ELVREC 1
+X.SH NAME
+Xelvrec - Recover the modified version of a file after a crash
+X.SH SYNOPSIS
+X.nf
+X\fBelvrec\fP [\fIpreservedfile\fP [\fInewfile\fR]]
+X.fi
+X.SH DESCRIPTION
+X.PP
+XIf you're editing a file when \fIelvis\fP dies, the system crashes, or power fails,
+Xthe most recent version of your text will be preserved.
+XThe preserved text is stored in a special directory; it does NOT overwrite
+Xyour text file automatically.
+X.PP
+XThe \fIelvrec\fP program locates the preserved version of a given file,
+Xand writes it over the top of your text file -- or to a new file, if you prefer.
+XThe recovered file will have nearly all of your changes.
+X.PP
+XTo see a list of all recoverable files, run \fIelvrec\fP with no arguments.
+X.SH FILES
+X.IP /usr/preserve/p*
+XThe text that was preserved when \fIelvis\fP died.
+X.IP /usr/preserve/Index
+XA text file which lists the names of all preserved files, and the names
+Xof the /usr/preserve/p* files which contain their preserved text.
+X.SH BUGS
+X.PP
+X\fIelvrec\fP is very picky about filenames.
+XYou must tell it to recover the file using exactly the same pathname as
+Xwhen you were editing it.
+XThe simplest way to do this is to go into the same directory that you were
+Xediting, and invoke \fIelvrec\fP with the same filename as \fIelvis\fP.
+XIf that doesn't work, then try running \fIelvrec\fP with no arguments,
+Xto see exactly which pathname it is using for the desired file.
+X.PP
+XDue to the permissions on the /usr/preserve directory, on UNIX systems
+X\fIelvrec\fP must be run as superuser.
+XThis is accomplished by making the \fIelvrec\fP executable be owned by "root"
+Xand setting its "set user id" bit.
+X.PP
+XIf you're editing a nameless buffer when \fIelvis\fP dies, then \fIelvrec\fP
+Xwill pretend that the file was named "foo".
+X.SH AUTHOR
+X.nf
+XSteve Kirkendall
+Xkirkenda@cs.pdx.edu
+X.fi
+/
+echo x - fmt.man
+sed '/^X/s///' > fmt.man << '/'
+X.TH FMT 1
+X.SH NAME
+Xfmt - adjust line-length for paragraphs of text
+X.SH SYNOPSIS
+X\fBfmt\fP [\-\fIwidth\fP] [\fIfiles\fP]...
+X.SH DESCRIPTION
+X\fIfmt\fR is a simple text formatter.
+XIt inserts or deletes newlines, as necessary, to make all lines in a
+Xparagraph be approximately the same width.
+XIt preserves indentation and word spacing.
+X.PP
+XThe default line width is 72 characters.
+XYou can override this with the \-\fIwidth\fR flag.
+XIf you don't name any files on the command line,
+Xthen \fIfmt\fR will read from stdin.
+X.PP
+XIt is typically used from within \fIvi\fR to adjust the line breaks
+Xin a single paragraph.
+XTo do this, move the cursor to the top of the paragraph,
+Xtype "!}fmt", and
+Xhit <Return>.
+X.SH AUTHOR
+X.nf
+XSteve Kirkendall
+Xkirkenda@cs.pdx.edu
+X.fi
+/
+echo x - ref.man
+sed '/^X/s///' > ref.man << '/'
+X.TH REF 1
+X.SH NAME
+Xref - Display a C function header
+X.SH SYNOPSIS
+X\fBref\fR [-t] [-c \fIclass\fR]... [-f \fIfile\fR]... \fItag\fR
+X.SH DESCRIPTION
+X\fIref\fP quickly locates and displays the header of a function.
+XTo do this, \fIref\fR
+Xlooks in the "tags" file for the line that describes the function, and then 
+Xscans the source file for the function.
+XWhen it locates the function, it displays an introductory comment
+X(if there is one), the function's declaration, and the declarations of all
+Xarguments.
+X.SH "SEARCH METHOD"
+X.PP
+X\fIref\fR uses a fairly sophisticated tag look-up algorithm.
+XIf you supply a filename via \fB-f\fR \fIfile\fR, then elvis first scans
+Xthe tags file for a static tag from that file.
+XThis search is limited to the tags file in the current directory.
+X.PP
+XIf you supply a classname via \fB-c\fR \fIclass\fR, then elvis searches
+Xfor a tag from that class.
+XThis search is not limited to the current directory;
+XYou can supply a list of directories in the environment variable \fITAGPATH\fR,
+Xand \fIref\fR will search through the "tags" file in each directory until it finds
+Xa tag in the desired class.
+X.PP
+XIf that fails, \fIref\fR will then try to look up an ordinary global tag.
+XThis search checks all of the directories listed in \fITAGPATH\fR, too.
+X.PP
+XIf you've given the \fB-t\fR flag, then \fIref\fR will simply output the tag line that
+Xit found, and then exit.
+XWithout \fB-t\fR, though, \fIref\fR will search for the tag line.
+XIt will try to open the source file, which should be in the same directory
+Xas the tags file where the tag was discovered.
+XIf the source file doesn't exist, or is unreadable, then \fIref\fR will try to open
+Xa file called "\fIrefs\fR" in that directory.
+XEither way, \fIref\fR will try to locate the tag, and display whatever it finds.
+X.SH "INTERACTION WITH ELVIS"
+X.PP
+X\fIref\fP is used by \fIelvis\fR' shift-K command.
+XIf the cursor is located on a word such as "splat", in the file "foo.c",
+Xthen \fIelvis\fR will invoke \fIref\fR with the command "ref -f foo.c splat".
+X.PP
+XIf \fIelvis\fR has been compiled with the -DEXTERNAL_TAGS flag, then \fIelvis\fR will
+Xuse \fIref\fR \fB\fRto scan the tags files.
+XThis is slower than the built-in tag searching, but it allows \fIelvis\fR to access
+Xthe more sophisticated tag lookup provided by \fIref\fR.
+XOther than that, external tags should act exactly like internal tags.
+X.SH OPTIONS
+X.IP \fB-t\fR
+XOutput tag info, instead of the function header.
+X.IP "\fB-f\fR \fIfile\fR"
+XThe tag might be a static function in \fIfile\fR.
+XYou can use several -f flags to have \fIref\fR consider static tags from more than one file.
+X.IP "\fB-c\fR \fIclass\fR"
+XThe tag might be a member of class \fIclass\fR.
+XYou can use several -c flags to have \fIref\fR consider tags from more than one class.
+X.SH FILES
+X.IP \fBtags\fR
+XList of function names and their locations, generated by \fIctags\fR.
+X.IP \fBrefs\fR
+XFunction headers extracted from source files (optional).
+X.SH ENVIRONMENT
+X.IP \fBTAGPATH\fR
+XList of directories to be searched.
+XThe elements in the list are separated by either
+Xsemicolons (for MS-DOS, Atari TOS, and AmigaDos), or
+Xby colons (every other operating system).
+XFor each operating system, \fIref\fR has a built-in default which is probably
+Xadequate.
+X.SH NOTES
+X.PP
+XYou might want to generate a "tags" file the directory that contains the
+Xsource code for standard C library on your system.
+XIf licensing restrictions prevent you from making the library source readable
+Xby everybody, then you can have \fIctags\fR generate a "refs" file,
+Xand make "refs" readable by everybody.
+X.PP
+XIf your system doesn't come with the library source code, then perhaps you
+Xcan produce something workable from the \fIlint\fR libraries.
+X.SH "SEE ALSO"
+Xelvis(1), ctags(1)
+X.SH AUTHOR
+X.nf
+XSteve Kirkendall
+Xkirkenda@cs.pdx.edu
+X.fi
+/
Index: /trunk/minix/commands/elvis/Readme.txt
===================================================================
--- /trunk/minix/commands/elvis/Readme.txt	(revision 9)
+++ /trunk/minix/commands/elvis/Readme.txt	(revision 9)
@@ -0,0 +1,31 @@
+Elvis is a clone of vi/ex, the standard UNIX editor.  Elvis supports
+nearly all of the vi/ex commands, in both visual mode and colon mode.
+
+Elvis runs under BSD UNIX, AT&T SysV UNIX, SCO Xenix, Minix, MS-DOS
+(Turbo-C or MSC 5.1), Atari TOS, OS9/68000, Coherent, VMS, and AmigaDos.
+Ports to other operating systems are in progress; contact me before you
+start porting it to some other OS, because somebody else may have
+already done it for you.
+
+Elvis is freely redistributable, in either source form or executable
+form.  There are no restrictions on how you may use it.
+
+The file "elvisman.txt" contains the manual for elvis.  It is a plain
+ASCII file with nothing more exotic than a newline character.  It is
+formatted for 66-line, 80-column pages.  There may also be an archive of
+"*.ms" and "*.man" files, which contain the TROFF source text used to
+generate that manual.
+
+The file named "Makefile.mix" is used to compile elvis for all systems
+except VMS and possibly MS-DOS.  You should copy "Makefile.mix" to
+"Makefile", and then edit "Makefile" to select the appropriate group of
+settings for your system.
+
+
+Author: Steve Kirkendall
+	14407 SW Teal Blvd. #C
+	Beaverton, OR   97005
+
+E-mail:	kirkenda@cs.pdx.edu
+
+Phone:	(503) 643-6980
Index: /trunk/minix/commands/elvis/blk.c
===================================================================
--- /trunk/minix/commands/elvis/blk.c	(revision 9)
+++ /trunk/minix/commands/elvis/blk.c	(revision 9)
@@ -0,0 +1,469 @@
+/* blk.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains the functions that get/put blocks from the temp file.
+ * It also contains the "do" and "undo" functions.
+ */
+
+#include "config.h"
+#include "vi.h"
+
+#ifndef NBUFS
+# define NBUFS	5		/* must be at least 3 -- more is better */
+#endif
+
+
+/*------------------------------------------------------------------------*/
+
+BLK		hdr;		/* buffer for the header block */
+
+static int	b4cnt;		/* used to count context of beforedo/afterdo */
+static struct _blkbuf
+{
+	BLK		buf;		/* contents of a text block */
+	unsigned short	logical;	/* logical block number */
+	int		dirty;		/* must the buffer be rewritten? */
+}
+		blk[NBUFS],	/* buffers for text[?] blocks */
+		*toonew,	/* buffer which shouldn't be recycled yet */
+		*newtoo,	/* another buffer which should be recycled */
+		*recycle = blk;	/* next block to be recycled */
+
+
+
+
+
+/* This function wipes out all buffers */
+void blkinit()
+{
+	int	i;
+
+	for (i = 0; i < NBUFS; i++)
+	{
+		blk[i].logical = 0;
+		blk[i].dirty = FALSE;
+	}
+	for (i = 0; i < MAXBLKS; i++)
+	{
+		hdr.n[i] = 0;
+	}
+}
+
+/* This function allocates a buffer and fills it with a given block's text */
+BLK *blkget(logical)
+	int	logical;	/* logical block number to fetch */
+{
+	REG struct _blkbuf	*this;	/* used to step through blk[] */
+	REG int	i;
+
+	/* if logical is 0, just return the hdr buffer */
+	if (logical == 0)
+	{
+		return &hdr;
+	}
+
+	/* see if we have that block in mem already */
+	for (this = blk; this < &blk[NBUFS]; this++)
+	{
+		if (this->logical == logical)
+		{
+			newtoo = toonew;
+			toonew = this;
+			return &this->buf;
+		}
+	}
+
+	/* choose a block to be recycled */
+	do
+	{
+		this = recycle++;
+		if (recycle == &blk[NBUFS])
+		{
+			recycle = blk;
+		}
+	} while (this == toonew || this == newtoo);
+
+	/* if it contains a block, flush that block */
+	blkflush(this);
+
+	/* fill this buffer with the desired block */
+	this->logical = logical;
+	if (hdr.n[logical])
+	{
+		/* it has been used before - fill it from tmp file */
+		lseek(tmpfd, (long)hdr.n[logical] * (long)BLKSIZE, 0);
+		if (read(tmpfd, this->buf.c, (unsigned)BLKSIZE) != BLKSIZE)
+		{
+			msg("Error reading back from tmp file!");
+		}
+	}
+	else
+	{
+		/* it is new - zero it */
+		for (i = 0; i < BLKSIZE; i++)
+		{
+			this->buf.c[i] = 0;
+		}
+	}
+
+	/* This isn't really a change, but it does potentially invalidate
+	 * the kinds of shortcuts that the "changes" variable is supposed
+	 * to protect us from... so count it as a change.
+	 */
+	changes++;
+
+	/* mark it as being "not dirty" */
+	this->dirty = 0;
+
+	/* return it */
+	newtoo = toonew;
+	toonew = this;
+	return &this->buf;
+}
+
+
+
+/* This function writes a block out to the temporary file */
+void blkflush(this)
+	REG struct _blkbuf	*this;	/* the buffer to flush */
+{
+	long		seekpos;	/* seek position of the new block */
+	unsigned short	physical;	/* physical block number */
+
+	/* if its empty (an orphan blkadd() maybe?) then make it dirty */
+	if (this->logical && !*this->buf.c)
+	{
+		blkdirty(&this->buf);
+	}
+
+	/* if it's an empty buffer or a clean version is on disk, quit */
+	if (!this->logical || hdr.n[this->logical] && !this->dirty)
+	{
+		return;
+	}
+
+	/* find a free place in the file */
+#ifndef NO_RECYCLE
+	seekpos = allocate();
+	lseek(tmpfd, seekpos, 0);
+#else
+	seekpos = lseek(tmpfd, 0L, 2);
+#endif
+	physical = seekpos / BLKSIZE;
+
+	/* put the block there */
+	if (write(tmpfd, this->buf.c, (unsigned)BLKSIZE) != BLKSIZE)
+	{
+		msg("Trouble writing to tmp file");
+	}
+	this->dirty = FALSE;
+
+	/* update the header so it knows we put it there */
+	hdr.n[this->logical] = physical;
+}
+
+
+/* This function sets a block's "dirty" flag or deletes empty blocks */
+void blkdirty(bp)
+	BLK	*bp;	/* buffer returned by blkget() */
+{
+	REG int		i, j;
+	REG char	*scan;
+	REG int		k;
+
+	/* find the buffer */
+	for (i = 0; i < NBUFS && bp != &blk[i].buf; i++)
+	{
+	}
+#ifdef DEBUG
+	if (i >= NBUFS)
+	{
+		msg("blkdirty() called with unknown buffer at 0x%lx", bp);
+		return;
+	}
+	if (blk[i].logical == 0)
+	{
+		msg("blkdirty called with freed buffer");
+		return;
+	}
+#endif
+
+	/* if this block ends with line# INFINITY, then it must have been
+	 * allocated unnecessarily during tmpstart().  Forget it.
+	 */
+	if (lnum[blk[i].logical] == INFINITY)
+	{
+#ifdef DEBUG
+		if (blk[i].buf.c[0])
+		{
+			msg("bkldirty called with non-empty extra BLK");
+		}
+#endif
+		blk[i].logical = 0;
+		blk[i].dirty = FALSE;
+		return;
+	}
+
+	/* count lines in this block */
+	for (j = 0, scan = bp->c; *scan && scan < bp->c + BLKSIZE; scan++)
+	{
+		if (*scan == '\n')
+		{
+			j++;
+		}
+	}
+
+	/* adjust lnum, if necessary */
+	k = blk[i].logical;
+	j += (lnum[k - 1] - lnum[k]);
+	if (j != 0)
+	{
+		nlines += j;
+		while (k < MAXBLKS && lnum[k] != INFINITY)
+		{
+			lnum[k++] += j;
+		}
+	}
+
+	/* if it still has text, mark it as dirty */
+	if (*bp->c)
+	{
+		blk[i].dirty = TRUE;
+	}
+	else /* empty block, so delete it */
+	{
+		/* adjust the cache */
+		k = blk[i].logical;
+		for (j = 0; j < NBUFS; j++)
+		{
+			if (blk[j].logical >= k)
+			{
+				blk[j].logical--;
+			}
+		}
+
+		/* delete it from hdr.n[] and lnum[] */
+		blk[i].logical = 0;
+		blk[i].dirty = FALSE;
+		while (k < MAXBLKS - 1)
+		{
+			hdr.n[k] = hdr.n[k + 1];
+			lnum[k] = lnum[k + 1];
+			k++;
+		}
+		hdr.n[MAXBLKS - 1] = 0;
+		lnum[MAXBLKS - 1] = INFINITY;
+	}
+}
+
+
+/* insert a new block into hdr, and adjust the cache */
+BLK *blkadd(logical)
+	int	logical;	/* where to insert the new block */
+{
+	REG int	i;
+
+	/* adjust hdr and lnum[] */
+	for (i = MAXBLKS - 1; i > logical; i--)
+	{
+		hdr.n[i] = hdr.n[i - 1];
+		lnum[i] = lnum[i - 1];
+	}
+	hdr.n[logical] = 0;
+	lnum[logical] = lnum[logical - 1];
+
+	/* adjust the cache */
+	for (i = 0; i < NBUFS; i++)
+	{
+		if (blk[i].logical >= logical)
+		{
+			blk[i].logical++;
+		}
+	}
+
+	/* return the new block, via blkget() */
+	return blkget(logical);
+}
+
+
+/* This function forces all dirty blocks out to disk */
+void blksync()
+{
+	int	i;
+
+	for (i = 0; i < NBUFS; i++)
+	{
+		/* blk[i].dirty = TRUE; */
+		blkflush(&blk[i]);
+	}
+	if (*o_sync)
+	{
+		sync();
+	}
+}
+
+/*------------------------------------------------------------------------*/
+
+static MARK	undocurs;	/* where the cursor should go if undone */
+static long	oldnlines;
+static long	oldlnum[MAXBLKS];
+
+
+/* This function should be called before each command that changes the text.
+ * It defines the state that undo() will reset the file to.
+ */
+void beforedo(forundo)
+	int		forundo;	/* boolean: is this for an undo? */
+{
+	REG int		i;
+	REG long	l;
+
+	/* if this is a nested call to beforedo, quit! Use larger context */
+	if (b4cnt++ > 0)
+	{
+		return;
+	}
+
+	/* force all block buffers to disk */
+	blksync();
+
+#ifndef NO_RECYCLE
+	/* perform garbage collection on blocks from tmp file */
+	garbage();
+#endif
+
+	/* force the header out to disk */
+	lseek(tmpfd, 0L, 0);
+	if (write(tmpfd, hdr.c, (unsigned)BLKSIZE) != BLKSIZE)
+	{
+		msg("Trouble writing header to tmp file ");
+	}
+
+	/* copy or swap oldnlines <--> nlines, oldlnum <--> lnum */
+	if (forundo)
+	{
+		for (i = 0; i < MAXBLKS; i++)
+		{
+			l = lnum[i];
+			lnum[i] = oldlnum[i];
+			oldlnum[i] = l;
+		}
+		l = nlines;
+		nlines = oldnlines;
+		oldnlines = l;
+	}
+	else
+	{
+		for (i = 0; i < MAXBLKS; i++)
+		{
+			oldlnum[i] = lnum[i];
+		}
+		oldnlines = nlines;
+	}
+
+	/* save the cursor position */
+	undocurs = cursor;
+
+	/* upon return, the calling function continues and makes changes... */
+}
+
+/* This function marks the end of a (nested?) change to the file */
+void afterdo()
+{
+	if (--b4cnt)
+	{
+		/* after abortdo(), b4cnt may decribe nested beforedo/afterdo
+		 * pairs incorrectly.  If it is decremented to often, then
+		 * keep b4cnt sane but don't do anything else.
+		 */
+		if (b4cnt < 0)
+			b4cnt = 0;
+
+		return;
+	}
+
+	/* make sure the cursor wasn't left stranded in deleted text */
+	if (markline(cursor) > nlines)
+	{
+		cursor = MARK_LAST;
+	}
+	/* NOTE: it is still possible that markidx(cursor) is after the
+	 * end of a line, so the Vi mode will have to take care of that
+	 * itself */
+
+	/* if a significant change has been made to this file, then set the
+	 * MODIFIED flag.
+	 */
+	if (significant)
+	{
+		setflag(file, MODIFIED);
+		setflag(file, UNDOABLE);
+	}	
+}
+
+/* This function cuts short the current set of changes.  It is called after
+ * a SIGINT.
+ */
+void abortdo()
+{
+	/* finish the operation immediately. */
+	if (b4cnt > 0)
+	{
+		b4cnt = 1;
+		afterdo();
+	}
+
+	/* in visual mode, the screen is probably screwed up */
+	if (mode == MODE_COLON)
+	{
+		mode = MODE_VI;
+	}
+	if (mode == MODE_VI)
+	{
+		redraw(MARK_UNSET, FALSE);
+	}
+}
+
+/* This function discards all changes made since the last call to beforedo() */
+int undo()
+{
+	BLK		oldhdr;
+
+	/* if beforedo() has never been run, fail */
+	if (!tstflag(file, UNDOABLE))
+	{
+		msg("You haven't modified this file yet.");
+		return FALSE;
+	}
+
+	/* read the old header form the tmp file */
+	lseek(tmpfd, 0L, 0);
+	if (read(tmpfd, oldhdr.c, (unsigned)BLKSIZE) != BLKSIZE)
+	{
+		msg("Trouble rereading the old header from tmp file");
+	}
+
+	/* "do" the changed version, so we can undo the "undo" */
+	cursor = undocurs;
+	beforedo(TRUE);
+	afterdo();
+
+	/* wipe out the block buffers - we can't assume they're correct */
+	blkinit();
+
+	/* use the old header -- and therefore the old text blocks */
+	hdr = oldhdr;
+
+	/* This is a change */
+	significant = TRUE;
+	changes++;
+
+	return TRUE;
+}
Index: /trunk/minix/commands/elvis/build
===================================================================
--- /trunk/minix/commands/elvis/build	(revision 9)
+++ /trunk/minix/commands/elvis/build	(revision 9)
@@ -0,0 +1,2 @@
+#!/bin/sh
+make && make install
Index: /trunk/minix/commands/elvis/cmd1.c
===================================================================
--- /trunk/minix/commands/elvis/cmd1.c	(revision 9)
+++ /trunk/minix/commands/elvis/cmd1.c	(revision 9)
@@ -0,0 +1,1774 @@
+/* cmd1.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains some of the EX commands - mostly ones that deal with
+ * files, options, etc. -- anything except text.
+ */
+
+#include "config.h"
+#include "ctype.h"
+#include "vi.h"
+#include "regexp.h"
+
+#ifdef DEBUG
+/* print the selected lines with info on the blocks */
+/*ARGSUSED*/
+void cmd_debug(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	REG char	*scan;
+	REG long	l;
+	REG int		i;
+	int		len;
+
+	/* scan lnum[] to determine which block its in */
+	l = markline(frommark);
+	for (i = 1; l > lnum[i]; i++)
+	{
+	}
+
+	do
+	{
+		/* fetch text of the block containing that line */
+		scan = blkget(i)->c;
+
+		/* calculate its length */
+		if (scan[BLKSIZE - 1])
+		{
+			len = BLKSIZE;
+		}
+		else
+		{
+			len = strlen(scan);
+		}
+
+		/* print block stats */
+		msg("##### hdr[%d]=%d, lnum[%d-1]=%ld, lnum[%d]=%ld (%ld lines)",
+			i, hdr.n[i], i, lnum[i-1], i, lnum[i], lnum[i] - lnum[i - 1]);
+		msg("##### len=%d, buf=0x%lx, %sdirty",
+			len, scan, ((int *)scan)[MAXBLKS + 1] ? "" : "not ");
+		if (bang)
+		{
+			while (--len >= 0)
+			{
+				addch(*scan);
+				scan++;
+			}
+		}
+		exrefresh();
+
+		/* next block */
+		i++;
+	} while (i < MAXBLKS && lnum[i] && lnum[i - 1] < markline(tomark));
+}
+
+
+/* This function checks a lot of conditions to make sure they aren't screwy */
+/*ARGSUSED*/
+void cmd_validate(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	char	*scan;
+	int	i;
+	int	nlcnt;	/* used to count newlines */
+	int	len;	/* counts non-NUL characters */
+
+	/* check lnum[0] */
+	if (lnum[0] != 0L)
+	{
+		msg("lnum[0] = %ld", lnum[0]);
+	}
+
+	/* check each block */
+	for (i = 1; lnum[i] <= nlines; i++)
+	{
+		scan = blkget(i)->c;
+		if (scan[BLKSIZE - 1])
+		{
+			msg("block %d has no NUL at the end", i);
+		}
+		else
+		{
+			for (nlcnt = len = 0; *scan; scan++, len++)
+			{
+				if (*scan == '\n')
+				{
+					nlcnt++;
+				}
+			}
+			if (scan[-1] != '\n')
+			{
+				msg("block %d doesn't end with '\\n' (length %d)", i, len);
+			}
+			if (bang || nlcnt != lnum[i] - lnum[i - 1])
+			{
+				msg("block %d (line %ld?) has %d lines, but should have %ld",
+					i, lnum[i - 1] + 1L, nlcnt, lnum[i] - lnum[i - 1]);
+			}
+		}
+		exrefresh();
+	}
+
+	/* check lnum again */
+	if (lnum[i] != INFINITY)
+	{
+		msg("hdr.n[%d] = %d, but lnum[%d] = %ld",
+			i, hdr.n[i], i, lnum[i]);
+	}
+
+	msg("# = \"%s\", %% = \"%s\"", prevorig, origname);
+	msg("V_from=%ld.%d, cursor=%ld.%d", markline(V_from), markidx(V_from), markline(cursor), markidx(cursor));
+}
+#endif /* DEBUG */
+
+
+/*ARGSUSED*/
+void cmd_mark(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	/* validate the name of the mark */
+	if (*extra == '"')
+	{
+		extra++;
+	}
+	/* valid mark names are lowercase ascii characters */
+	if (!isascii(*extra) || !islower(*extra) || extra[1])
+	{
+		msg("Invalid mark name");
+		return;
+	}
+
+	mark[*extra - 'a'] = tomark;
+}
+
+/*ARGSUSED*/
+void cmd_write(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	int		fd;
+	int		append;	/* boolean: write in "append" mode? */
+	REG long	l;
+	REG char	*scan;
+	REG int		i;
+
+	/* if writing to a filter, then let filter() handle it */
+	if (*extra == '!')
+	{
+		filter(frommark, tomark, extra + 1, FALSE);
+		return;
+	}
+
+	/* if all lines are to be written, use tmpsave() */
+	if (frommark == MARK_FIRST && tomark == MARK_LAST && cmd == CMD_WRITE)
+	{
+		tmpsave(extra, bang);
+		return;
+	}
+
+	/* see if we're going to do this in append mode or not */
+	append = FALSE;
+	if (extra[0] == '>' && extra[1] == '>')
+	{
+		extra += 2;
+		append = TRUE;
+	}
+
+	/* either the file must not exist, or we must have a ! or be appending */
+	if (access(extra, 0) == 0 && !bang && !append)
+	{
+		msg("File already exists - Use :w! to overwrite");
+		return;
+	}
+
+	/* else do it line-by-line, like cmd_print() */
+	if (append)
+	{
+#ifdef O_APPEND
+		fd = open(extra, O_WRONLY|O_APPEND);
+#else
+		fd = open(extra, O_WRONLY);
+		if (fd >= 0)
+		{
+			lseek(fd, 0L, 2);
+		}
+#endif
+	}
+	else
+	{
+		fd = -1; /* so we know the file isn't open yet */
+	}
+
+	if (fd < 0)
+	{
+		fd = creat(extra, FILEPERMS);
+		if (fd < 0)
+		{
+			msg("Can't write to \"%s\"", extra);
+			return;
+		}
+	}
+	for (l = markline(frommark); l <= markline(tomark); l++)
+	{
+		/* get the next line */
+		scan = fetchline(l);
+		i = strlen(scan);
+		scan[i++] = '\n';
+
+		/* print the line */
+		if (twrite(fd, scan, i) < i)
+		{
+			msg("Write failed");
+			break;
+		}
+	}
+	rptlines = markline(tomark) - markline(frommark) + 1;
+	rptlabel = "written";
+	close(fd);
+}	
+
+
+/*ARGSUSED*/
+void cmd_shell(frommark, tomark, cmd, bang, extra)
+	MARK	frommark, tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	static char	prevextra[80];
+
+	/* special case: ":sh" means ":!sh" */
+	if (cmd == CMD_SHELL)
+	{
+		extra = o_shell;
+		frommark = tomark = 0L;
+	}
+
+	/* if extra is "!", substitute previous command */
+	if (*extra == '!')
+	{
+		if (!*prevextra)
+		{
+			msg("No previous shell command to substitute for '!'");
+			return;
+		}
+		extra = prevextra;
+	}
+	else if (cmd == CMD_BANG && strlen(extra) < sizeof(prevextra) - 1)
+	{
+		strcpy(prevextra, extra);
+	}
+
+	/* warn the user if the file hasn't been saved yet */
+	if (*o_warn && tstflag(file, MODIFIED))
+	{
+		if (mode == MODE_VI)
+		{
+			mode = MODE_COLON;
+		}
+		msg("Warning: \"%s\" has been modified but not yet saved", origname);
+	}
+
+	/* if no lines were specified, just run the command */
+	suspend_curses();
+	if (frommark == 0L)
+	{
+		system(extra);
+	}
+	else /* pipe lines from the file through the command */
+	{
+		filter(frommark, tomark, extra, TRUE);
+	}
+
+	/* resume curses quietly for MODE_EX, but noisily otherwise */
+	resume_curses(mode == MODE_EX);
+}
+
+
+/*ARGSUSED*/
+void cmd_global(frommark, tomark, cmd, bang, extra)
+	MARK	frommark, tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;	/* rest of the command line */
+{
+	char	*cmdptr;	/* the command from the command line */
+	char	cmdln[100];	/* copy of the command from the command line */
+	char	*line;		/* a line from the file */
+	long	l;		/* used as a counter to move through lines */
+	long	lqty;		/* quantity of lines to be scanned */
+	long	nchanged;	/* number of lines changed */
+	regexp	*re;		/* the compiled search expression */
+
+	/* can't nest global commands */
+	if (doingglobal)
+	{
+		msg("Can't nest global commands.");
+		rptlines = -1L;
+		return;
+	}
+
+	/* ":g! ..." is the same as ":v ..." */
+	if (bang)
+	{
+		cmd = CMD_VGLOBAL;
+	}
+
+	/* make sure we got a search pattern */
+	if (*extra != '/' && *extra != '?')
+	{
+		msg("Usage: %c /regular expression/ command", cmd == CMD_GLOBAL ? 'g' : 'v');
+		return;
+	}
+
+	/* parse & compile the search pattern */
+	cmdptr = parseptrn(extra);
+	if (!extra[1])
+	{
+		msg("Can't use empty regular expression with '%c' command", cmd == CMD_GLOBAL ? 'g' : 'v');
+		return;
+	}
+	re = regcomp(extra + 1);
+	if (!re)
+	{
+		/* regcomp found & described an error */
+		return;
+	}
+
+	/* for each line in the range */
+	doingglobal = TRUE;
+	ChangeText
+	{
+		/* NOTE: we have to go through the lines in a forward order,
+		 * otherwise "g/re/p" would look funny.  *BUT* for "g/re/d"
+		 * to work, simply adding 1 to the line# on each loop won't
+		 * work.  The solution: count lines relative to the end of
+		 * the file.  Think about it.
+		 */
+		for (l = nlines - markline(frommark),
+			lqty = markline(tomark) - markline(frommark) + 1L,
+			nchanged = 0L;
+		     lqty > 0 && nlines - l >= 0 && nchanged >= 0L;
+		     l--, lqty--)
+		{
+			/* fetch the line */
+			line = fetchline(nlines - l);
+
+			/* if it contains the search pattern... */
+			if ((!regexec(re, line, 1)) == (cmd != CMD_GLOBAL))
+			{
+				/* move the cursor to that line */
+				cursor = MARK_AT_LINE(nlines - l);
+
+				/* do the ex command (without mucking up
+				 * the original copy of the command line)
+				 */
+				strcpy(cmdln, cmdptr);
+				rptlines = 0L;
+				doexcmd(cmdln);
+				nchanged += rptlines;
+			}
+		}
+	}
+	doingglobal = FALSE;
+
+	/* free the regexp */
+	free(re);
+
+	/* Reporting...*/
+	rptlines = nchanged;
+}
+
+
+/*ARGSUSED*/
+void cmd_file(frommark, tomark, cmd, bang, extra)
+	MARK	frommark, tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+#ifndef CRUNCH
+	/* if we're given a new filename, use it as this file's name */
+	if (extra && *extra)
+	{
+		strcpy(origname, extra);
+		storename(origname);
+		setflag(file, NOTEDITED);
+	}
+#endif
+	if (cmd == CMD_FILE)
+	{
+#ifndef CRUNCH
+		msg("\"%s\" %s%s%s %ld lines,  line %ld [%ld%%]",
+#else
+		msg("\"%s\" %s%s %ld lines,  line %ld [%ld%%]",
+#endif
+			*origname ? origname : "[NO FILE]",
+			tstflag(file, MODIFIED) ? "[MODIFIED]" : "",
+#ifndef CRUNCH
+			tstflag(file, NOTEDITED) ?"[NOT EDITED]":"",
+#endif
+			tstflag(file, READONLY) ? "[READONLY]" : "",
+			nlines,
+			markline(frommark),
+			markline(frommark) * 100 / nlines);
+	}
+#ifndef CRUNCH
+	else if (markline(frommark) != markline(tomark))
+	{
+		msg("range \"%ld,%ld\" contains %ld lines",
+			markline(frommark),
+			markline(tomark),
+			markline(tomark) - markline(frommark) + 1L);
+	}
+#endif
+	else
+	{
+		msg("%ld", markline(frommark));
+	}
+}
+
+
+/*ARGSUSED*/
+void cmd_edit(frommark, tomark, cmd, bang, extra)
+	MARK	frommark, tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	long	line = 1L;	/* might be set to prevline */
+#ifndef CRUNCH
+	char	*init = (char *)0;
+#endif
+
+
+	/* if ":vi", then switch to visual mode, and if no file is named
+	 * then don't switch files.
+	 */
+	if (cmd == CMD_VISUAL)
+	{
+		mode = MODE_VI;
+		msg("");
+		if (!*extra)
+		{
+			return;
+		}
+	}
+
+	/* Editing previous file?  Then start at previous line */
+	if (!strcmp(extra, prevorig))
+	{
+		line = prevline;
+	}
+
+#ifndef CRUNCH
+	/* if we were given an explicit starting line, then start there */
+	if (*extra == '+')
+	{
+		for (init = ++extra; !isspace(*extra); extra++)
+		{
+		}
+		while (isspace(*extra))
+		{
+			*extra++ = '\0';
+		}
+		if (!*init)
+		{
+			init = "$";
+		}
+		if (!extra)
+		{
+			extra = origname;
+		}
+	}
+#endif /* not CRUNCH */
+
+	/* switch files */
+	if (tmpabort(bang))
+	{
+		tmpstart(extra);
+		if (line <= nlines && line >= 1L)
+		{
+			cursor = MARK_AT_LINE(line);
+		}
+#ifndef CRUNCH
+		if (init)
+		{
+			doexcmd(init);
+		}
+#endif
+	}
+	else
+	{
+		msg("Use edit! to abort changes, or w to save changes");
+
+		/* so we can say ":e!#" next time... */
+		strcpy(prevorig, extra);
+		prevline = 1L;
+	}
+}
+
+/* This code is also used for rewind -- GB */
+
+/*ARGSUSED*/
+void cmd_next(frommark, tomark, cmd, bang, extra)
+	MARK	frommark, tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	int	i, j;
+	char	*scan;
+
+	/* if extra stuff given, use ":args" to define a new args list */
+	if (cmd == CMD_NEXT && extra && *extra)
+	{
+		cmd_args(frommark, tomark, cmd, bang, extra);
+	}
+
+	/* move to the next arg */
+	if (cmd == CMD_NEXT)
+	{
+		i = argno + 1;
+	}
+	else if (cmd == CMD_PREVIOUS)
+	{
+		i = argno - 1;
+	}
+	else /* cmd == CMD_REWIND */
+	{
+		i = 0;
+	}	
+	if (i < 0 || i >= nargs)
+	{
+		msg("No %sfiles to edit", cmd == CMD_REWIND ? "" : "more ");
+		return;
+	}
+
+	/* find & isolate the name of the file to edit */
+	for (j = i, scan = args; j > 0; j--)
+	{
+		while(*scan++)
+		{
+		}
+	}
+
+	/* switch to the next file */
+	if (tmpabort(bang))
+	{
+		tmpstart(scan);
+		argno = i;
+	}
+	else
+	{
+		msg("Use :%s! to abort changes, or w to save changes",
+			cmd == CMD_NEXT ? "next" :
+			cmd == CMD_PREVIOUS ? "previous" :
+					"rewind");
+	}
+}
+
+/* also called from :wq -- always writes back in this case */
+
+/*ARGSUSED*/
+void cmd_xit(frommark, tomark, cmd, bang, extra)
+	MARK	frommark, tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	static long	whenwarned;	/* when the user was last warned of extra files */
+	int		oldflag;
+
+	/* if there are more files to edit, then warn user */
+	if (argno >= 0 && argno + 1 < nargs && whenwarned != changes && (!bang || cmd != CMD_QUIT))
+	{
+		msg("More files to edit -- Use \":n\" to go to next file");
+		whenwarned = changes;
+		return;
+	}
+
+	if (cmd == CMD_QUIT)
+	{
+		oldflag = *o_autowrite;
+		*o_autowrite = FALSE;
+		if (tmpabort(bang))
+		{
+			mode = MODE_QUIT;
+		}
+		else
+		{
+			msg("Use q! to abort changes, or wq to save changes");
+		}
+		*o_autowrite = oldflag;
+	}
+	else
+	{
+		/* else try to save this file */
+		oldflag = tstflag(file, MODIFIED);
+		if (cmd == CMD_WQUIT)
+			setflag(file, MODIFIED);
+		if (tmpend(bang))
+		{
+			mode = MODE_QUIT;
+		}
+		else
+		{
+			msg("Could not save file -- use quit! to abort changes, or w filename");
+		}
+		if (!oldflag)
+			clrflag(file, MODIFIED);
+	}
+}
+
+
+/*ARGSUSED*/
+void cmd_args(frommark, tomark, cmd, bang, extra)
+	MARK	frommark, tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	char	*scan;
+	int	col;
+	int	arg;
+	int	scrolled = FALSE;
+	int	width;
+
+	/* if no extra names given, or just current name, then report the args
+	 * we have now.
+	 */
+	if (!extra || !*extra)
+	{
+		/* empty args list? */
+		if (nargs == 1 && !*args)
+		{
+			return;
+		}
+
+		/* list the arguments */
+		for (scan = args, col = arg = 0;
+		     arg < nargs;
+		     scan += width + 1, col += width, arg++)
+		{
+			width = strlen(scan);
+			if (col + width >= COLS - 4)
+			{
+				addch('\n');
+				col = 0;
+				scrolled = TRUE;
+			}
+			else if (col > 0)
+			{
+				addch(' ');
+				col++;
+			}
+			if (arg == argno)
+			{
+				addch('[');
+				addstr(scan);
+				addch(']');
+				col += 2;
+			}
+			else
+			{
+				addstr(scan);
+			}
+		}
+
+		/* write a trailing newline */
+		if ((mode == MODE_EX || mode == MODE_COLON || scrolled) && col)
+		{
+			addch('\n');
+		}
+		exrefresh();	
+	}
+	else /* new args list given */
+	{
+		for (scan = args, nargs = 1; *extra; )
+		{
+			if (isspace(*extra))
+			{
+				*scan++ = '\0';
+				while (isspace(*extra))
+				{
+					extra++;
+				}
+				if (*extra)
+				{
+					nargs++;
+				}
+			}
+			else
+			{
+				*scan++ = *extra++;
+			}
+		}
+		*scan = '\0';
+
+		/* reset argno to before the first, so :next will go to first */
+		argno = -1;
+
+		if (nargs != 1)
+		{
+                        msg("%d files to edit", nargs);
+		}
+	}
+}
+
+
+/*ARGSUSED*/
+void cmd_cd(frommark, tomark, cmd, bang, extra)
+	MARK	frommark, tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	char	*getenv();
+
+#ifndef CRUNCH
+	/* if current file is modified, and no '!' was given, then error */
+	if (tstflag(file, MODIFIED) && !bang)
+	{
+		msg("File modified; use \"cd! %s\" to switch anyway", extra);
+	}
+#endif
+
+	/* default directory name is $HOME */
+	if (!*extra)
+	{
+		extra = getenv("HOME");
+		if (!extra)
+		{
+			msg("environment variable $HOME not set");
+			return;
+		}
+	}
+
+	/* go to the directory */
+	if (chdir(extra) < 0)
+	{
+		perror(extra);
+	}
+}
+
+
+/*ARGSUSED*/
+void cmd_map(frommark, tomark, cmd, bang, extra)
+	MARK	frommark, tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	char	*mapto;
+	char	*build, *scan;
+#ifndef NO_FKEY
+	static char *fnames[NFKEYS] =
+	{
+		"#10", "#1", "#2", "#3", "#4",
+		"#5", "#6", "#7", "#8", "#9",
+# ifndef NO_SHIFT_FKEY
+		"#10s", "#1s", "#2s", "#3s", "#4s",
+		"#5s", "#6s", "#7s", "#8s", "#9s",
+#  ifndef NO_CTRL_FKEY
+		"#10c", "#1c", "#2c", "#3c", "#4c",
+		"#5c", "#6c", "#7c", "#8c", "#9c",
+#   ifndef NO_ALT_FKEY
+		"#10a", "#1a", "#2a", "#3a", "#4a",
+		"#5a", "#6a", "#7a", "#8a", "#9a",
+#   endif
+#  endif
+# endif
+	};
+	int	key;
+#endif
+
+	/* "map" with no extra will dump the map table contents */
+	if (!*extra)
+	{
+#ifndef NO_ABBR
+		if (cmd == CMD_ABBR)
+		{
+			dumpkey(bang ? WHEN_EX|WHEN_VIINP|WHEN_VIREP : WHEN_VIINP|WHEN_VIREP, TRUE);
+		}
+		else
+#endif
+		{
+			dumpkey(bang ? WHEN_VIINP|WHEN_VIREP : WHEN_VICMD, FALSE);
+		}
+	}
+	else
+	{
+		/* "extra" is key to map, followed by what it maps to */
+
+		/* handle quoting inside the "raw" string */
+		for (build = mapto = extra;
+		     *mapto && (*mapto != ' ' && *mapto != '\t');
+		     *build++ = *mapto++)
+		{
+			if (*mapto == ctrl('V') && mapto[1])
+			{
+				mapto++;
+			}
+		}
+
+		/* skip whitespace, and mark the end of the "raw" string */
+		while ((*mapto == ' ' || *mapto == '\t'))
+		{
+			*mapto++ = '\0';
+		}
+		*build = '\0';
+
+		/* strip ^Vs from the "cooked" string */
+		for (scan = build = mapto; *scan; *build++ = *scan++)
+		{
+			if (*scan == ctrl('V') && scan[1])
+			{
+				scan++;
+			}
+		}
+		*build = '\0';
+
+#ifndef NO_FKEY
+		/* if the mapped string is '#' and a number, then assume
+		 * the user wanted that function key
+		 */
+		if (extra[0] == '#' && isdigit(extra[1]))
+		{
+			key = atoi(extra + 1) % 10;
+# ifndef NO_SHIFT_FKEY
+			build = extra + strlen(extra) - 1;
+			if (*build == 's')
+				key += 10;
+#  ifndef NO_CTRL_FKEY
+			else if (*build == 'c')
+				key += 20;
+#   ifndef NO_ALT_FKEY
+			else if (*build == 'a')
+				key += 30;
+#   endif
+#  endif
+# endif
+			if (FKEY[key])
+				mapkey(FKEY[key], mapto, bang ? WHEN_VIINP|WHEN_VIREP : WHEN_VICMD, fnames[key]);
+			else
+				msg("This terminal has no %s key", fnames[key]);
+		}
+		else
+#endif
+#ifndef NO_ABBR
+		if (cmd == CMD_ABBR || cmd == CMD_UNABBR)
+		{
+			mapkey(extra, mapto, bang ? WHEN_EX|WHEN_VIINP|WHEN_VIREP : WHEN_VIINP|WHEN_VIREP, "abbr");
+		}
+		else
+#endif
+		{
+			mapkey(extra, mapto, bang ? WHEN_VIINP|WHEN_VIREP : WHEN_VICMD, (char *)0);
+		}
+	}
+}
+
+
+/*ARGSUSED*/
+void cmd_set(frommark, tomark, cmd, bang, extra)
+	MARK	frommark, tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	if (!*extra)
+	{
+		dumpopts(FALSE);/* "FALSE" means "don't dump all" - only set */
+	}
+	else if (!strcmp(extra, "all"))
+	{
+		dumpopts(TRUE);	/* "TRUE" means "dump all" - even unset vars */
+	}
+	else
+	{
+		setopts(extra);
+
+		/* That option may have affected the appearence of text */
+		changes++;
+	}
+}
+
+/*ARGSUSED*/
+void cmd_tag(frommark, tomark, cmd, bang, extra)
+	MARK	frommark, tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	int	fd;	/* file descriptor used to read the file */
+	char	*scan;	/* used to scan through the tmpblk.c */
+#ifdef INTERNAL_TAGS
+	char	*cmp;	/* char of tag name we're comparing, or NULL */
+	char	*end;	/* marks the end of chars in tmpblk.c */
+#else
+	int	i;
+#endif
+#ifndef NO_MAGIC
+	char	wasmagic; /* preserves the original state of o_magic */
+#endif
+	static char prevtag[30];
+
+	/* if no tag is given, use the previous tag */
+	if (!extra || !*extra)
+	{
+		if (!*prevtag)
+		{
+			msg("No previous tag");
+			return;
+		}
+		extra = prevtag;
+	}
+	else
+	{
+		strncpy(prevtag, extra, sizeof prevtag);
+		prevtag[sizeof prevtag - 1] = '\0';
+	}
+
+#ifndef INTERNAL_TAGS
+	/* use "ref" to look up the tag info for this tag */
+	sprintf(tmpblk.c, "ref -t %s%s %s", (*origname ? "-f" : ""),origname, prevtag);
+	fd = rpipe(tmpblk.c, 0);
+	if (fd < 0)
+	{
+		msg("Can't run \"%s\"", tmpblk.c);
+		return;
+	}
+
+	/* try to read the tag info */
+	for (scan = tmpblk.c;
+	     (i = tread(fd, scan, scan - tmpblk.c + BLKSIZE)) > 0;
+	     scan += i)
+	{
+	}
+	*scan = '\0';
+
+	/* close the pipe.  abort if error */
+	if (rpclose(fd) != 0 || scan < tmpblk.c + 3)
+	{
+		msg("tag \"%s\" not found", extra);
+		return;
+	}
+
+#else /* use internal code to look up the tag */
+	/* open the tags file */
+	fd = open(TAGS, O_RDONLY);
+	if (fd < 0)
+	{
+		msg("No tags file");
+		return;
+	}
+
+	/* Hmmm... this would have been a lot easier with <stdio.h> */
+
+	/* find the line with our tag in it */
+	for(scan = end = tmpblk.c, cmp = extra; ; scan++)
+	{
+		/* read a block, if necessary */
+		if (scan >= end)
+		{
+			end = tmpblk.c + tread(fd, tmpblk.c, BLKSIZE);
+			scan = tmpblk.c;
+			if (scan >= end)
+			{
+				msg("tag \"%s\" not found", extra);
+				close(fd);
+				return;
+			}
+		}
+
+		/* if we're comparing, compare... */
+		if (cmp)
+		{
+			/* matched??? wow! */
+			if (!*cmp && *scan == '\t')
+			{
+				break;
+			}
+			if (*cmp++ != *scan)
+			{
+				/* failed! skip to newline */
+				cmp = (char *)0;
+			}
+		}
+
+		/* if we're skipping to newline, do it fast! */
+		if (!cmp)
+		{
+			while (scan < end && *scan != '\n')
+			{
+				scan++;
+			}
+			if (scan < end)
+			{
+				cmp = extra;
+			}
+		}
+	}
+
+	/* found it! get the rest of the line into memory */
+	for (cmp = tmpblk.c, scan++; scan < end && *scan != '\n'; )
+	{
+		*cmp++ = *scan++;
+	}
+	if (scan == end)
+	{
+		tread(fd, cmp, BLKSIZE - (int)(cmp - tmpblk.c));
+	}
+	else
+		*cmp = *scan;
+
+	/* we can close the tags file now */
+	close(fd);
+#endif /* INTERNAL_TAGS */
+
+	/* extract the filename from the line, and edit the file */
+	for (scan = tmpblk.c; *scan != '\t'; scan++)
+	{
+	}
+	*scan++ = '\0';
+	if (strcmp(origname, tmpblk.c) != 0)
+	{
+		if (!tmpabort(bang))
+		{
+			msg("Use :tag! to abort changes, or :w to save changes");
+			return;
+		}
+		tmpstart(tmpblk.c);
+	}
+
+	/* move to the desired line (or to line 1 if that fails) */
+#ifndef NO_MAGIC
+	wasmagic = *o_magic;
+	*o_magic = FALSE;
+#endif
+	cursor = MARK_FIRST;
+	linespec(scan, &cursor);
+	if (cursor == MARK_UNSET)
+	{
+		cursor = MARK_FIRST;
+		msg("Tag's address is out of date");
+	}
+#ifndef NO_MAGIC
+	*o_magic = wasmagic;
+#endif
+}
+
+
+
+
+
+/* describe this version of the program */
+/*ARGSUSED*/
+void cmd_version(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	msg("%s", VERSION);
+#ifdef CREDIT
+	msg("%s", CREDIT);
+#endif
+#ifdef CREDIT2
+	msg("%s", CREDIT2);
+#endif
+#ifdef COMPILED_BY
+	msg("Compiled by %s", COMPILED_BY);
+#endif
+#ifdef COPYING
+	msg("%s", COPYING);
+#endif
+}
+
+
+#ifndef NO_MKEXRC
+/* make a .exrc file which describes the current configuration */
+/*ARGSUSED*/
+void cmd_mkexrc(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	int	fd;
+
+	/* the default name for the .exrc file EXRC */
+	if (!*extra)
+	{
+		extra = EXRC;
+	}
+
+	/* create the .exrc file */
+	fd = creat(extra, FILEPERMS);
+	if (fd < 0)
+	{
+		msg("Couldn't create a new \"%s\" file", extra);
+		return;
+	}
+
+	/* save stuff */
+	saveopts(fd);
+	savemaps(fd, FALSE);
+#ifndef NO_ABBR
+	savemaps(fd, TRUE);
+#endif
+#ifndef NO_DIGRAPH
+	savedigs(fd);
+#endif
+#ifndef NO_COLOR
+	savecolor(fd);
+#endif
+
+	/* close the file */
+	close(fd);
+	msg("Configuration saved");
+}
+#endif
+
+#ifndef NO_DIGRAPH
+/*ARGSUSED*/
+void cmd_digraph(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	do_digraph(bang, extra);
+}
+#endif
+
+
+#ifndef NO_ERRLIST 
+static char	errfile[256];	/* the name of a file containing an error */
+static long	errline;	/* the line number for an error */
+static int	errfd = -2;	/* fd of the errlist file */
+
+/* This static function tries to parse an error message.
+ *
+ * For most compilers, the first word is taken to be the name of the erroneous
+ * file, and the first number after that is taken to be the line number where
+ * the error was detected.  The description of the error follows, possibly
+ * preceded by an "error ... :" or "warning ... :" label which is skipped.
+ *
+ * For Coherent, error messages look like "line#: filename: message".
+ *
+ * For non-error lines, or unparsable error lines, this function returns NULL.
+ * Normally, though, it alters errfile and errline, and returns a pointer to
+ * the description.
+ */
+static char *parse_errmsg(text)
+	REG char	*text;
+{
+	REG char	*cpy;
+	long		atol();
+# if COHERENT || TOS /* any Mark Williams compiler */
+	/* Get the line number.  If no line number, then ignore this line. */
+	errline = atol(text);
+	if (errline == 0L)
+		return (char *)0;
+
+	/* Skip to the start of the filename */
+	while (*text && *text++ != ':')
+	{
+	}
+	if (!*text++)
+		return (char *)0;
+
+	/* copy the filename to errfile */
+	for (cpy = errfile; *text && (*cpy++ = *text++) != ':'; )
+	{
+	}
+	if (!*text++)
+		return (char *)0;
+	cpy[-1] = '\0';
+
+	return text;
+# else /* not a Mark Williams compiler */
+	char		*errmsg;
+
+	/* the error message is the whole line, by default */
+	errmsg = text;
+
+	/* skip leading garbage */
+	while (*text && !isalnum(*text))
+	{
+		text++;
+	}
+
+	/* copy over the filename */
+	cpy = errfile;
+	while(isalnum(*text) || *text == '.')
+	{
+		*cpy++ = *text++;
+	}
+	*cpy = '\0';
+
+	/* ignore the name "Error" and filenames that contain a '/' */
+	if (*text == '/' || !*errfile || !strcmp(errfile + 1, "rror") || access(errfile, 0) < 0)
+	{
+		return (char *)0;
+	}
+
+	/* skip garbage between filename and line number */
+	while (*text && !isdigit(*text))
+	{
+		text++;
+	}
+
+	/* if the number is part of a larger word, then ignore this line */
+	if (*text && isalpha(text[-1]))
+	{
+		return (char *)0;
+	}
+
+	/* get the error line */
+	errline = 0L;
+	while (isdigit(*text))
+	{
+		errline *= 10;
+		errline += (*text - '0');
+		text++;
+	}
+
+	/* any line which lacks a filename or line number should be ignored */
+	if (!errfile[0] || !errline)
+	{
+		return (char *)0;
+	}
+
+	/* locate the beginning of the error description */
+	while (*text && !isspace(*text))
+	{
+		text++;
+	}
+	while (*text)
+	{
+#  ifndef CRUNCH
+		/* skip "error #:" and "warning #:" clauses */
+		if (!strncmp(text + 1, "rror ", 5)
+		 || !strncmp(text + 1, "arning ", 7)
+		 || !strncmp(text + 1, "atal error", 10))
+		{
+			do
+			{
+				text++;
+			} while (*text && *text != ':');
+			continue;
+		}
+#  endif
+
+		/* anything other than whitespace or a colon is important */
+		if (!isspace(*text) && *text != ':')
+		{
+			errmsg = text;
+			break;
+		}
+
+		/* else keep looking... */
+		text++;
+	}
+
+	return errmsg;
+# endif /* not COHERENT */
+}
+
+/*ARGSUSED*/
+void cmd_errlist(frommark, tomark, cmd, bang, extra)
+	MARK	frommark, tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	static long	endline;/* original number of lines in this file */
+	static long	offset;	/* offset of the next line in the errlist file */
+	int		i;
+	char		*errmsg;
+
+	/* if a new errlist file is named, open it */
+	if (extra && extra[0])
+	{
+		/* close the old one */
+		if (errfd >= 0)
+		{
+			close(errfd);
+		}
+
+		/* open the new one */
+		errfd = open(extra, O_RDONLY);
+		offset = 0L;
+		endline = nlines;
+	}
+	else if (errfd < 0)
+	{
+		/* open the default file */
+		errfd = open(ERRLIST, O_RDONLY);
+		offset = 0L;
+		endline = nlines;
+	}
+
+	/* do we have an errlist file now? */
+	if (errfd < 0)
+	{
+		msg("There is no errlist file");
+		beep();
+		return;
+	}
+
+	/* find the next error message in the file */
+	do
+	{
+		/* read the next line from the errlist */
+		lseek(errfd, offset, 0);
+		if (tread(errfd, tmpblk.c, (unsigned)BLKSIZE) <= 0)
+		{
+			msg("No more errors");
+			beep();
+			close(errfd);
+			errfd = -2;
+			return;
+		}
+		for (i = 0; tmpblk.c[i] != '\n'; i++)
+		{
+		}
+		tmpblk.c[i++] = 0;
+
+		/* look for an error message in the line */
+		errmsg = parse_errmsg(tmpblk.c);
+		if (!errmsg)
+		{
+			offset += i;
+		}
+
+	} while (!errmsg);
+
+	/* switch to the file containing the error, if this isn't it */
+	if (strcmp(origname, errfile))
+	{
+		if (!tmpabort(bang))
+		{
+			msg("Use :er! to abort changes, or :w to save changes");
+			beep();
+			return;
+		}
+		tmpstart(errfile);
+		endline = nlines;
+	}
+	else if (endline == 0L)
+	{
+		endline = nlines;
+	}
+
+	/* go to the line where the error was detected */
+	cursor = MARK_AT_LINE(errline + (nlines - endline));
+	if (cursor > MARK_LAST)
+	{
+		cursor = MARK_LAST;
+	}
+	if (mode == MODE_VI)
+	{
+		redraw(cursor, FALSE);
+	}
+
+	/* display the error message */
+#ifdef CRUNCH
+	msg("%.70s", errmsg);
+#else
+	if (nlines > endline)
+	{
+		msg("line %ld(+%ld): %.60s", errline, nlines - endline, errmsg);
+	}
+	else if (nlines < endline)
+	{
+		msg("line %ld(-%ld): %.60s", errline, endline - nlines, errmsg);
+	}
+	else
+	{
+		msg("line %ld: %.65s", errline, errmsg);
+	}
+#endif
+
+	/* remember where the NEXT error line will start */
+	offset += i;
+}
+
+
+/*ARGSUSED*/
+void cmd_make(frommark, tomark, cmd, bang, extra)
+	MARK	frommark, tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	BLK	buf;
+
+	/* if the file hasn't been saved, then complain unless ! */
+	if (tstflag(file, MODIFIED) && !bang)
+	{
+		msg("\"%s\" not saved yet", origname);
+		return;
+	}
+
+	/* build the command */
+	sprintf(buf.c, "%s %s %s%s", (cmd == CMD_CC ? o_cc : o_make), extra, REDIRECT, ERRLIST);
+	qaddstr(buf.c);
+	addch('\n');
+
+	/* close the old errlist file, if any */
+	if (errfd >= 0)
+	{
+		close(errfd);
+		errfd = -3;
+	}
+
+	/* run the command, with curses temporarily disabled */
+	suspend_curses();
+	system(buf.c);
+	resume_curses(mode == MODE_EX);
+	if (mode == MODE_COLON)
+		mode = MODE_VI;
+
+	/* run the "errlist" command */
+	cmd_errlist(MARK_UNSET, MARK_UNSET, cmd, bang, ERRLIST);
+}
+#endif
+
+
+
+#ifndef NO_COLOR
+
+/* figure out the number of text colors we use with this configuration */
+# ifndef NO_POPUP
+#  ifndef NO_VISIBLE
+#   define NCOLORS 7
+#  else
+#   define NCOLORS 6
+#  endif
+# else
+#  ifndef NO_VISIBLE
+#   define NCOLORS 6
+#  else
+#   define NCOLORS 5
+#  endif
+# endif
+
+/* the attribute bytes used in each of "when"s */
+static char bytes[NCOLORS];
+
+static struct
+{
+	char	*word;	/* a legal word */
+	int	type;	/* what type of word this is */
+	int	val;	/* some other value */
+}
+	words[] =
+{
+	{"normal",	1,	A_NORMAL},	/* all "when" names must come */
+	{"standout",	1,	A_STANDOUT},	/* at the top of the list.    */
+	{"bold",	1,	A_BOLD},	/* The first 3 must be normal,*/
+	{"underlined",	1,	A_UNDERLINE},	/* standout, and bold; the    */
+	{"italics",	1,	A_ALTCHARSET},	/* remaining names follow.    */
+#ifndef NO_POPUP
+	{"popup",	1,	A_POPUP},
+#endif
+#ifndef NO_VISIBLE
+	{"visible",	1,	A_VISIBLE},
+#endif
+
+	{"black",	3,	0x00},		/* The color names start right*/
+	{"blue",	3,	0x01},		/* after the "when" names.    */
+	{"green",	3,	0x02},
+	{"cyan",	3,	0x03},
+	{"red",		3,	0x04},
+	{"magenta",	3,	0x05},
+	{"brown",	3,	0x06},
+	{"white",	3,	0x07},
+	{"yellow",	3,	0x0E}, /* bright brown */
+	{"gray",	3,	0x08}, /* bright black?  of course! */
+	{"grey",	3,	0x08},
+
+	{"bright",	2,	0x08},
+	{"light",	2,	0x08},
+	{"blinking",	2,	0x80},
+	{"on",		0,	0},
+	{"n",		1,	A_NORMAL},
+	{"s",		1,	A_STANDOUT},
+	{"b",		1,	A_BOLD},
+	{"u",		1,	A_UNDERLINE},
+	{"i",		1,	A_ALTCHARSET},
+#ifndef NO_POPUP
+	{"p",		1,	A_POPUP},
+	{"menu",	1,	A_POPUP},
+#endif
+#ifndef NO_VISIBLE
+	{"v",		1,	A_VISIBLE},
+#endif
+	{(char *)0,	0,	0}
+};
+
+/*ARGSUSED*/
+void cmd_color(frommark, tomark, cmd, bang, extra)
+	MARK	frommark, tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	int	attrbyte;
+	int	cmode;
+	int	nowbg;	/* BOOLEAN: is the next color background? */
+
+	REG char *scan;
+	REG	i;
+
+
+#ifndef CRUNCH
+	/* if no args are given, then report the current colors */
+	if (!*extra)
+	{
+		/* if no colors are set, then say so */
+		if (!bytes[0])
+		{
+			msg("no colors have been set");
+			return;
+		}
+
+		/* report all five color combinations */
+		for (i = 0; i < NCOLORS; i++)
+		{
+			qaddstr("color ");
+			qaddstr(words[i].word);
+			qaddch(' ');
+			if (bytes[i] & 0x80)
+				qaddstr("blinking ");
+			switch (bytes[i] & 0xf)
+			{
+			  case 0x08:	qaddstr("gray");	break;
+			  case 0x0e:	qaddstr("yellow");	break;
+			  case 0x0f:	qaddstr("bright white");break;
+			  default:
+				if (bytes[i] & 0x08)
+					qaddstr("light ");
+				qaddstr(words[(bytes[i] & 0x07) + NCOLORS].word);
+			}
+			qaddstr(" on ");
+			qaddstr(words[((bytes[i] >> 4) & 0x07) + NCOLORS].word);
+			addch('\n');
+			exrefresh();
+		}
+		return;
+	}
+#endif
+
+	/* The default background color is the same as "normal" chars.
+	 * There is no default foreground color.
+	 */
+	cmode = A_NORMAL;
+	attrbyte = bytes[0] & 0x70;
+	nowbg = FALSE;
+
+	/* parse each word in the "extra" text */
+	for (scan = extra; *extra; extra = scan)
+	{
+		/* locate the end of the word */
+		while (*scan && *scan != ' ')
+		{
+			scan++;
+		}
+
+		/* skip whitespace at the end of the word */
+		while(*scan == ' ')
+		{
+			*scan++ = '\0';
+		}
+
+		/* lookup the word */
+		for (i = 0; words[i].word && strcmp(words[i].word, extra); i++)
+		{
+		}
+
+		/* if not a word, then complain */
+		if (!words[i].word)
+		{
+			msg("Invalid color name: %s", extra);
+			return;
+		}
+
+		/* process the word */
+		switch (words[i].type)
+		{
+		  case 1:
+			cmode = words[i].val;
+			break;
+
+		  case 2:
+			attrbyte |= words[i].val;
+			break;
+
+		  case 3:
+			if (nowbg)
+				attrbyte = ((attrbyte & ~0x70) | ((words[i].val & 0x07) << 4));
+			else
+				attrbyte |= words[i].val;
+			nowbg = TRUE;
+			break;
+		}
+	}
+
+	/* if nowbg isn't set now, then we were never given a foreground color */
+	if (!nowbg)
+	{
+		msg("usage: color [when] [\"bright\"] [\"blinking\"] foreground [background]");
+		return;
+	}
+
+	/* the first ":color" command MUST define the "normal" colors */
+	if (!bytes[0])
+		cmode = A_NORMAL;
+
+	/* we should now have a cmode and an attribute byte... */
+
+	/* set the color */
+	setcolor(cmode, attrbyte);
+
+	/* remember what we just did */
+	bytes[cmode] = attrbyte;
+
+	/* if the other colors haven't been set yet, then set them to defaults */
+	if (!bytes[1])
+	{
+		/* standout is the opposite of normal */
+		bytes[1] = ((attrbyte << 4) & 0x70 | (attrbyte >> 4) & 0x07);
+		setcolor(A_STANDOUT, bytes[1]);
+
+		/* if "normal" isn't bright, then bold defaults to normal+bright
+		 * else bold defaults to bright white.
+		 */
+		bytes[2] = attrbyte | ((attrbyte & 0x08) ? 0x0f : 0x08);
+		setcolor(A_BOLD, bytes[2]);
+
+		/* all others default to the "standout" colors, without blinking */
+		for (i = 3; i < NCOLORS; i++)
+		{
+			bytes[i] = (bytes[1] & 0x7f);
+			setcolor(words[i].val, bytes[i]);
+		}
+	}
+
+	/* force a redraw, so we see the new colors */
+	redraw(MARK_UNSET, FALSE);
+}
+
+
+
+void savecolor(fd)
+	int	fd;	/* file descriptor to write colors to */
+{
+	int	i;
+	char	buf[80];
+
+	/* if no colors are set, then return */
+	if (!bytes[0])
+	{
+		return;
+	}
+
+	/* save all five color combinations */
+	for (i = 0; i < NCOLORS; i++)
+	{
+		strcpy(buf, "color ");
+		strcat(buf, words[i].word);
+		strcat(buf, " ");
+		if (bytes[i] & 0x80)
+			strcat(buf, "blinking ");
+		switch (bytes[i] & 0xf)
+		{
+		  case 0x08:	strcat(buf, "gray");	break;
+		  case 0x0e:	strcat(buf, "yellow");	break;
+		  case 0x0f:	strcat(buf, "bright white");break;
+		  default:
+			if (bytes[i] & 0x08)
+				strcat(buf, "light ");
+			strcat(buf, words[(bytes[i] & 0x07) + NCOLORS].word);
+		}
+		strcat(buf, " on ");
+		strcat(buf, words[((bytes[i] >> 4) & 0x07) + NCOLORS].word);
+		strcat(buf, "\n");
+		twrite(fd, buf, (unsigned)strlen(buf));
+	}
+}
+#endif
+
+#ifdef SIGTSTP
+/* temporarily suspend elvis */
+/*ARGSUSED*/
+void cmd_suspend(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	void	(*func)();	/* stores the previous setting of SIGTSTP */
+
+#if ANY_UNIX
+	/* the Bourne shell can't handle ^Z */
+	if (!strcmp(o_shell, "/bin/sh"))
+	{
+		msg("The /bin/sh shell doesn't support ^Z");
+		return;
+	}
+#endif
+
+	move(LINES - 1, 0);
+	if (tstflag(file, MODIFIED))
+	{
+		addstr("Warning: \"");
+		addstr(origname);
+		addstr("\" modified but not yet saved");
+		clrtoeol();
+	}
+	refresh();
+	suspend_curses();
+	func = signal(SIGTSTP, SIG_DFL);
+	kill (0, SIGTSTP);
+
+	/* the process stops and resumes here */
+
+	signal(SIGTSTP, func);
+	resume_curses(TRUE);
+	if (mode == MODE_VI || mode == MODE_COLON)
+		redraw(MARK_UNSET, FALSE);
+	else
+		refresh ();
+}
+#endif
Index: /trunk/minix/commands/elvis/cmd2.c
===================================================================
--- /trunk/minix/commands/elvis/cmd2.c	(revision 9)
+++ /trunk/minix/commands/elvis/cmd2.c	(revision 9)
@@ -0,0 +1,942 @@
+/* cmd2.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains some of the commands - mostly ones that change text */
+
+#include "config.h"
+#include "ctype.h"
+#include "vi.h"
+#include "regexp.h"
+#if TOS
+# include <stat.h>
+#else
+# if OSK
+#  include "osk.h"
+# else
+#  if AMIGA
+#   include "amistat.h"
+#  else
+#   include <sys/stat.h>
+#  endif
+# endif
+#endif
+
+
+/*ARGSUSED*/
+void cmd_substitute(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;	/* rest of the command line */
+{
+	char	*line;	/* a line from the file */
+	regexp	*re;	/* the compiled search expression */
+	char	*subst;	/* the substitution string */
+	char	*opt;	/* substitution options */
+	long	l;	/* a line number */
+	char	*s, *d;	/* used during subtitutions */
+	char	*conf;	/* used during confirmation */
+	long	chline;	/* # of lines changed */
+	long	chsub;	/* # of substitutions made */
+	static	optp;	/* boolean option: print when done? */
+	static	optg;	/* boolean option: substitute globally in line? */
+	static	optc;	/* boolean option: confirm before subst? */
+#ifndef CRUNCH
+	long	oldnlines;
+#endif
+
+
+	/* for now, assume this will fail */
+	rptlines = -1L;
+
+	if (cmd == CMD_SUBAGAIN)
+	{
+#ifndef NO_MAGIC
+		if (*o_magic)
+			subst = "~";
+		else
+#endif
+		subst = "\\~";
+		re = regcomp("");
+
+		/* if visual "&", then turn off the "p" and "c" options */
+		if (bang)
+		{
+			optp = optc = FALSE;
+		}
+	}
+	else /* CMD_SUBSTITUTE */
+	{
+		/* make sure we got a search pattern */
+		if (*extra != '/' && *extra != '?')
+		{
+			msg("Usage: s/regular expression/new text/");
+			return;
+		}
+
+		/* parse & compile the search pattern */
+		subst = parseptrn(extra);
+		re = regcomp(extra + 1);
+	}
+
+	/* abort if RE error -- error message already given by regcomp() */
+	if (!re)
+	{
+		return;
+	}
+
+	if (cmd == CMD_SUBSTITUTE)
+	{
+		/* parse the substitution string & find the option string */
+		for (opt = subst; *opt && *opt != *extra; opt++)
+		{
+			if (*opt == '\\' && opt[1])
+			{
+				opt++;
+			}
+		}
+		if (*opt)
+		{
+			*opt++ = '\0';
+		}
+
+		/* analyse the option string */
+		if (!*o_edcompatible)
+		{
+			optp = optg = optc = FALSE;
+		}
+		while (*opt)
+		{
+			switch (*opt++)
+			{
+			  case 'p':	optp = !optp;	break;
+			  case 'g':	optg = !optg;	break;
+			  case 'c':	optc = !optc;	break;
+			  case ' ':
+			  case '\t':			break;
+			  default:
+				msg("Subst options are p, c, and g -- not %c", opt[-1]);
+				return;
+			}
+		}
+	}
+
+	/* if "c" or "p" flag was given, and we're in visual mode, then NEWLINE */
+	if ((optc || optp) && mode == MODE_VI)
+	{
+		addch('\n');
+		exrefresh();
+	}
+
+	ChangeText
+	{
+		/* reset the change counters */
+		chline = chsub = 0L;
+
+		/* for each selected line */
+		for (l = markline(frommark); l <= markline(tomark); l++)
+		{
+			/* fetch the line */
+			line = fetchline(l);
+
+			/* if it contains the search pattern... */
+			if (regexec(re, line, TRUE))
+			{
+				/* increment the line change counter */
+				chline++;
+
+				/* initialize the pointers */
+				s = line;
+				d = tmpblk.c;
+
+				/* do once or globally ... */
+				do
+				{
+#ifndef CRUNCH
+					/* confirm, if necessary */
+					if (optc)
+					{
+						for (conf = line; conf < re->startp[0]; conf++)
+							addch(*conf);
+						standout();
+						for ( ; conf < re->endp[0]; conf++)
+							addch(*conf);
+						standend();
+						for (; *conf; conf++)
+							addch(*conf);
+						addch('\n');
+						exrefresh();
+						if (getkey(0) != 'y')
+						{
+							/* copy accross the original chars */
+							while (s < re->endp[0])
+								*d++ = *s++;
+
+							/* skip to next match on this line, if any */
+							goto Continue;
+						}
+					}
+#endif /* not CRUNCH */
+
+					/* increment the substitution change counter */
+					chsub++;
+
+					/* copy stuff from before the match */
+					while (s < re->startp[0])
+					{
+						*d++ = *s++;
+					}
+
+					/* substitute for the matched part */
+					regsub(re, subst, d);
+					s = re->endp[0];
+					d += strlen(d);
+
+Continue:
+					/* if this regexp could conceivably match
+					 * a zero-length string, then require at
+					 * least 1 unmatched character between
+					 * matches.
+					 */
+					if (re->minlen == 0)
+					{
+						if (!*s)
+							break;
+						*d++ = *s++;
+					}
+
+				} while (optg && regexec(re, s, FALSE));
+
+				/* copy stuff from after the match */
+				while (*d++ = *s++)	/* yes, ASSIGNMENT! */
+				{
+				}
+
+#ifndef CRUNCH
+				/* NOTE: since the substitution text is allowed to have ^Ms which are
+				 * translated into newlines, it is possible that the number of lines
+				 * in the file will increase after each line has been substituted.
+				 * we need to adjust for this.
+				 */
+				oldnlines = nlines;
+#endif
+
+				/* replace the old version of the line with the new */
+				d[-1] = '\n';
+				d[0] = '\0';
+				change(MARK_AT_LINE(l), MARK_AT_LINE(l + 1), tmpblk.c);
+
+#ifndef CRUNCH
+				l += nlines - oldnlines;
+				tomark += MARK_AT_LINE(nlines - oldnlines);
+#endif
+
+				/* if supposed to print it, do so */
+				if (optp)
+				{
+					addstr(tmpblk.c);
+					exrefresh();
+				}
+
+				/* move the cursor to that line */
+				cursor = MARK_AT_LINE(l);
+			}
+		}
+	}
+
+	/* free the regexp */
+	free(re);
+
+	/* if done from within a ":g" command, then finish silently */
+	if (doingglobal)
+	{
+		rptlines = chline;
+		rptlabel = "changed";
+		return;
+	}
+
+	/* Reporting */
+	if (chsub == 0)
+	{
+		msg("Substitution failed");
+	}
+	else if (chline >= *o_report)
+	{
+		msg("%ld substitutions on %ld lines", chsub, chline);
+	}
+	rptlines = 0L;
+}
+
+
+
+
+/*ARGSUSED*/
+void cmd_delete(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	MARK	curs2;	/* an altered form of the cursor */
+
+	/* choose your cut buffer */
+	if (*extra == '"')
+	{
+		extra++;
+	}
+	if (*extra)
+	{
+		cutname(*extra);
+	}
+
+	/* make sure we're talking about whole lines here */
+	frommark = frommark & ~(BLKSIZE - 1);
+	tomark = (tomark & ~(BLKSIZE - 1)) + BLKSIZE;
+
+	/* yank the lines */
+	cut(frommark, tomark);
+
+	/* if CMD_DELETE then delete the lines */
+	if (cmd != CMD_YANK)
+	{
+		curs2 = cursor;
+		ChangeText
+		{
+			/* delete the lines */
+			delete(frommark, tomark);
+		}
+		if (curs2 > tomark)
+		{
+			cursor = curs2 - tomark + frommark;
+		}
+		else if (curs2 > frommark)
+		{
+			cursor = frommark;
+		}
+	}
+}
+
+
+/*ARGSUSED*/
+void cmd_append(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	long	l;	/* line counter */
+
+#ifndef CRUNCH
+	/* if '!' then toggle auto-indent */
+	if (bang)
+	{
+		*o_autoindent = !*o_autoindent;
+	}
+#endif
+
+	ChangeText
+	{
+		/* if we're doing a change, delete the old version */
+		if (cmd == CMD_CHANGE)
+		{
+			/* delete 'em */
+			cmd_delete(frommark, tomark, cmd, bang, extra);
+		}
+
+		/* new lines start at the frommark line, or after it */
+		l = markline(frommark);
+		if (cmd == CMD_APPEND)
+		{
+ 			l++;
+		}
+
+		/* get lines until no more lines, or "." line, and insert them */
+		while (vgets('\0', tmpblk.c, BLKSIZE) >= 0)
+		{
+			addch('\n');
+			if (!strcmp(tmpblk.c, "."))
+			{
+				break;
+			}
+
+			strcat(tmpblk.c, "\n");
+			add(MARK_AT_LINE(l), tmpblk.c);
+			l++;
+		}
+	}
+
+	/* on the odd chance that we're calling this from vi mode ... */
+	redraw(MARK_UNSET, FALSE);
+}
+
+
+/*ARGSUSED*/
+void cmd_put(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	/* choose your cut buffer */
+	if (*extra == '"')
+	{
+		extra++;
+	}
+	if (*extra)
+	{
+		cutname(*extra);
+	}
+
+	/* paste it */
+	ChangeText
+	{
+		cursor = paste(frommark, TRUE, FALSE);
+	}
+}
+
+
+/*ARGSUSED*/
+void cmd_join(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	long	l;
+	char	*scan;
+	int	len;	/* length of the new line */
+
+	/* if only one line is specified, assume the following one joins too */
+	if (markline(frommark) == nlines)
+	{
+		msg("Nothing to join with this line");
+		return;
+	}
+	if (markline(frommark) == markline(tomark))
+	{
+		tomark += BLKSIZE;
+	}
+
+	/* get the first line */
+	l = markline(frommark);
+	strcpy(tmpblk.c, fetchline(l));
+	len = strlen(tmpblk.c);
+
+	/* build the longer line */
+	while (++l <= markline(tomark))
+	{
+		/* get the next line */
+		scan = fetchline(l);
+
+		/* remove any leading whitespace */
+		while (*scan == '\t' || *scan == ' ')
+		{
+			scan++;
+		}
+
+		/* see if the line will fit */
+		if (strlen(scan) + len + 3 > BLKSIZE)
+		{
+			msg("Can't join -- the resulting line would be too long");
+			return;
+		}
+
+		/* catenate it, with a space (or two) in between */
+		if (!bang)
+		{
+			if (len >= 1)
+			{
+				if (tmpblk.c[len - 1] == '.'
+				 || tmpblk.c[len - 1] == '?'
+				 || tmpblk.c[len - 1] == '!')
+				{
+					 tmpblk.c[len++] = ' ';
+				}
+				tmpblk.c[len++] = ' ';
+			}
+		}
+		strcpy(tmpblk.c + len, scan);
+		len += strlen(scan);
+	}
+	tmpblk.c[len++] = '\n';
+	tmpblk.c[len] = '\0';
+
+	/* make the change */
+	ChangeText
+	{
+		frommark &= ~(BLKSIZE - 1);
+		tomark &= ~(BLKSIZE - 1);
+		tomark += BLKSIZE;
+		change(frommark, tomark, tmpblk.c);
+	}
+
+	/* Reporting... */
+	rptlines = markline(tomark) - markline(frommark) - 1L;
+	rptlabel = "joined";
+}
+
+
+
+/*ARGSUSED*/
+void cmd_shift(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	long	l;	/* line number counter */
+	int	oldidx;	/* number of chars previously used for indent */
+	int	newidx;	/* number of chars in the new indent string */
+	int	oldcol;	/* previous indent amount */
+	int	newcol;	/* new indent amount */
+	char	*text;	/* pointer to the old line's text */
+
+	ChangeText
+	{
+		/* for each line to shift... */
+		for (l = markline(frommark); l <= markline(tomark); l++)
+		{
+			/* get the line - ignore empty lines unless ! mode */
+			text = fetchline(l);
+			if (!*text && !bang)
+				continue;
+
+			/* calc oldidx and oldcol */
+			for (oldidx = 0, oldcol = 0;
+			     text[oldidx] == ' ' || text[oldidx] == '\t';
+			     oldidx++)
+			{
+				if (text[oldidx] == ' ')
+				{
+					oldcol += 1;
+				}
+				else
+				{
+					oldcol += *o_tabstop - (oldcol % *o_tabstop);
+				}
+			}
+
+			/* calc newcol */
+			if (cmd == CMD_SHIFTR)
+			{
+				newcol = oldcol + (*o_shiftwidth & 0xff);
+			}
+			else
+			{
+				newcol = oldcol - (*o_shiftwidth & 0xff);
+				if (newcol < 0)
+					newcol = 0;
+			}
+
+			/* if no change, then skip to next line */
+			if (oldcol == newcol)
+				continue;
+
+			/* build a new indent string */
+			newidx = 0;
+			if (*o_autotab)
+			{
+				while (newcol >= *o_tabstop)
+				{
+					tmpblk.c[newidx++] = '\t';
+					newcol -= *o_tabstop;
+				}
+			}
+			while (newcol > 0)
+			{
+				tmpblk.c[newidx++] = ' ';
+				newcol--;
+			}
+			tmpblk.c[newidx] = '\0';
+
+			/* change the old indent string into the new */
+			change(MARK_AT_LINE(l), MARK_AT_LINE(l) + oldidx, tmpblk.c);
+		}
+	}
+
+	/* Reporting... */
+	rptlines = markline(tomark) - markline(frommark) + 1L;
+	if (cmd == CMD_SHIFTR)
+	{
+		rptlabel = ">ed";
+	}
+	else
+	{
+		rptlabel = "<ed";
+	}
+}
+
+
+/*ARGSUSED*/
+void cmd_read(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	int	fd, rc;	/* used while reading from the file */
+	char	*scan;	/* used for finding NUL characters */
+	int	hadnul;	/* boolean: any NULs found? */
+	int	addnl;	/* boolean: forced to add newlines? */
+	int	len;	/* number of chars in current line */
+	long	lines;	/* number of lines in current block */
+	struct stat statb;
+
+	/* special case: if ":r !cmd" then let the filter() function do it */
+	if (extra[0] == '!')
+	{
+		filter(frommark, MARK_UNSET, extra + 1, TRUE);
+		return;
+	}
+
+	/* open the file */
+	fd = open(extra, O_RDONLY);
+	if (fd < 0)
+	{
+		msg("Can't open \"%s\"", extra);
+		return;
+	}
+
+#ifndef CRUNCH
+	if (stat(extra, &statb) < 0)
+	{
+		msg("Can't stat \"%s\"", extra);
+	}
+# if TOS
+	if (statb.st_mode & S_IJDIR)
+# else
+#  if OSK
+	if (statb.st_mode & S_IFDIR)
+#  else
+	if ((statb.st_mode & S_IFMT) != S_IFREG)
+#  endif
+# endif
+	{
+		msg("\"%s\" is not a regular file", extra);
+		return;
+	}
+#endif /* not CRUNCH */
+
+	/* get blocks from the file, and add them */
+	ChangeText
+	{
+		/* insertion starts at the line following frommark */
+		tomark = frommark = (frommark | (BLKSIZE - 1L)) + 1L;
+		len = 0;
+		hadnul = addnl = FALSE;
+
+		/* add an extra newline, so partial lines at the end of
+		 * the file don't trip us up
+		 */
+		add(tomark, "\n");
+
+		/* for each chunk of text... */
+		while ((rc = tread(fd, tmpblk.c, BLKSIZE - 1)) > 0)
+		{
+			/* count newlines, convert NULs, etc. ... */
+			for (lines = 0, scan = tmpblk.c; rc > 0; rc--, scan++)
+			{
+				/* break up long lines */
+				if (*scan != '\n' && len + 2 > BLKSIZE)
+				{
+					*scan = '\n';
+					addnl = TRUE;
+				}
+
+				/* protect against NUL chars in file */
+				if (!*scan)
+				{
+					*scan = 0x80;
+					hadnul = TRUE;
+				}
+
+				/* starting a new line? */
+				if (*scan == '\n')
+				{
+					/* reset length at newline */
+					len = 0;
+					lines++;
+				}
+				else
+				{
+					len++;
+				}
+			}
+
+			/* add the text */
+			*scan = '\0';
+			add(tomark, tmpblk.c);
+			tomark += MARK_AT_LINE(lines) + len - markidx(tomark);
+		}
+
+		/* if partial last line, then retain that first newline */
+		if (len > 0)
+		{
+			msg("Last line had no newline");
+			tomark += BLKSIZE; /* <- for the rptlines calc */
+		}
+		else /* delete that first newline */
+		{
+			delete(tomark, (tomark | (BLKSIZE - 1L)) + 1L);
+		}
+	}
+
+	/* close the file */
+	close(fd);
+
+	/* Reporting... */
+	rptlines = markline(tomark) - markline(frommark);
+	rptlabel = "read";
+	if (mode == MODE_EX)
+	{
+		cursor = (tomark & ~BLKSIZE) - BLKSIZE;
+	}
+	else
+	{
+		cursor = frommark;
+	}
+
+	if (addnl)
+		msg("Newlines were added to break up long lines");
+	if (hadnul)
+		msg("NULs were converted to 0x80");
+}
+
+
+
+/*ARGSUSED*/
+void cmd_undo(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	undo();
+}
+
+
+/* print the selected lines */
+/*ARGSUSED*/
+void cmd_print(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	REG char	*scan;
+	REG long	l;
+	REG int		col;
+
+	for (l = markline(frommark); l <= markline(tomark); l++)
+	{
+		/* display a line number, if CMD_NUMBER */
+		if (cmd == CMD_NUMBER)
+		{
+			sprintf(tmpblk.c, "%6ld  ", l);
+			qaddstr(tmpblk.c);
+			col = 8;
+		}
+		else
+		{
+			col = 0;
+		}
+
+		/* get the next line & display it */
+		for (scan = fetchline(l); *scan; scan++)
+		{
+			/* expand tabs to the proper width */
+			if (*scan == '\t' && cmd != CMD_LIST)
+			{
+				do
+				{
+					qaddch(' ');
+					col++;
+				} while (col % *o_tabstop != 0);
+			}
+			else if (*scan > 0 && *scan < ' ' || *scan == '\177')
+			{
+				qaddch('^');
+				qaddch(*scan ^ 0x40);
+				col += 2;
+			}
+			else if ((*scan & 0x80) && cmd == CMD_LIST)
+			{
+				sprintf(tmpblk.c, "\\%03o", UCHAR(*scan));
+				qaddstr(tmpblk.c);
+				col += 4;
+			}
+			else
+			{
+				qaddch(*scan);
+				col++;
+			}
+
+			/* wrap at the edge of the screen */
+			if (!has_AM && col >= COLS)
+			{
+				addch('\n');
+				col -= COLS;
+			}
+		}
+		if (cmd == CMD_LIST)
+		{
+			qaddch('$');
+		}
+		addch('\n');
+		exrefresh();
+	}
+}
+
+
+/* move or copy selected lines */
+/*ARGSUSED*/
+void cmd_move(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	MARK	destmark;
+
+	/* parse the destination linespec.  No defaults.  Line 0 is okay */
+	destmark = cursor;
+	if (!strcmp(extra, "0"))
+	{
+		destmark = 0L;
+	}
+	else if (linespec(extra, &destmark) == extra || !destmark)
+	{
+		msg("invalid destination address");
+		return;
+	}
+
+	/* flesh the marks out to encompass whole lines */
+	frommark &= ~(BLKSIZE - 1);
+	tomark = (tomark & ~(BLKSIZE - 1)) + BLKSIZE;
+	destmark = (destmark & ~(BLKSIZE - 1)) + BLKSIZE;
+
+	/* make sure the destination is valid */
+	if (cmd == CMD_MOVE && destmark >= frommark && destmark < tomark)
+	{
+		msg("invalid destination address");
+	}
+
+	/* Do it */
+	ChangeText
+	{
+		/* save the text to a cut buffer */
+		cutname('\0');
+		cut(frommark, tomark);
+
+		/* if we're not copying, delete the old text & adjust destmark */
+		if (cmd != CMD_COPY)
+		{
+			delete(frommark, tomark);
+			if (destmark >= frommark)
+			{
+				destmark -= (tomark - frommark);
+			}
+		}
+
+		/* add the new text */
+		paste(destmark, FALSE, FALSE);
+	}
+
+	/* move the cursor to the last line of the moved text */
+	cursor = destmark + (tomark - frommark) - BLKSIZE;
+	if (cursor < MARK_FIRST || cursor >= MARK_LAST + BLKSIZE)
+	{
+		cursor = MARK_LAST;
+	}
+
+	/* Reporting... */
+	rptlabel = ( (cmd == CMD_COPY) ? "copied" : "moved" );
+}
+
+
+
+/* execute EX commands from a file */
+/*ARGSUSED*/
+void cmd_source(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	/* must have a filename */
+	if (!*extra)
+	{
+		msg("\"source\" requires a filename");
+		return;
+	}
+
+	doexrc(extra);
+}
+
+
+#ifndef NO_AT
+/*ARGSUSED*/
+void cmd_at(frommark, tomark, cmd, bang, extra)
+	MARK	frommark;
+	MARK	tomark;
+	CMD	cmd;
+	int	bang;
+	char	*extra;
+{
+	static	nest = FALSE;
+	int	result;
+	char	buf[MAXRCLEN];
+
+	/* don't allow nested macros */
+	if (nest)
+	{
+		msg("@ macros can't be nested");
+		return;
+	}
+	nest = TRUE;
+
+	/* require a buffer name */
+	if (*extra == '"')
+		extra++;
+	if (!*extra || !isascii(*extra) ||!islower(*extra))
+	{
+		msg("@ requires a cut buffer name (a-z)");
+	}
+
+	/* get the contents of the buffer */
+	result = cb2str(*extra, buf, (unsigned)(sizeof buf));
+	if (result <= 0)
+	{
+		msg("buffer \"%c is empty", *extra);
+	}
+	else if (result >= sizeof buf)
+	{
+		msg("buffer \"%c is too large to execute", *extra);
+	}
+	else
+	{
+		/* execute the contents of the buffer as ex commands */
+		exstring(buf, result, '\\');
+	}
+
+	nest = FALSE;
+}
+#endif
Index: /trunk/minix/commands/elvis/config.h
===================================================================
--- /trunk/minix/commands/elvis/config.h	(revision 9)
+++ /trunk/minix/commands/elvis/config.h	(revision 9)
@@ -0,0 +1,525 @@
+/*
+ * vi configuration file
+ * We try to automatically configure to various compilers and operating
+ * systems. Extend the autoconf section as needed.
+ */
+
+#ifndef _CONFIG_H
+# define _CONFIG_H
+
+/*************************** autoconf section ************************/
+
+/* Commodore-Amiga */
+#ifdef	amiga
+# define AMIGA		1
+# define COMPILED_BY	"Manx Aztec C 5.2b"
+#endif
+
+/* standard unix V (?) */
+#ifdef	M_SYSV
+# define UNIXV		1
+#endif
+
+/* xelos system, University of Ulm */
+#ifdef	xelos
+# define UNIXV		1
+#endif
+
+/* BSD UNIX? */
+#ifdef bsd
+# define BSD		1
+#else
+# ifdef sun
+#  define BSD		1
+# endif
+#endif
+
+/* Microsoft C: sorry, Watcom does the same thing */
+#ifdef	M_I86
+# ifndef M_SYSV
+#  define MSDOS		1
+#  ifdef IBMC2
+#   define COMPILED_BY	"IBM C/2 1.00"
+#  else
+#   define MICROSOFT	1
+#   define COMPILED_BY	"Microsoft C 5.10"
+#  endif
+# endif
+#endif
+
+/* Borland's Turbo C */
+#ifdef	__TURBOC__
+# define MSDOS		1
+# define TURBOC		1
+# ifdef __BORLANDC__
+# define COMPILED_BY	"Borland C 2.00"
+# else
+# define COMPILED_BY	(__TURBOC__ >= 661 ? "Turbo C++ 1.00" : "Turbo C 2.00")
+# endif
+#endif
+
+/* Tos Mark-Williams */
+#ifdef	M68000
+# define TOS 1
+# define COMPILED_BY	"Mark Williams C"
+#endif
+
+/* Tos GNU-C */
+#if defined(__atarist__) && defined(__gem__)
+# define TOS 1
+# define COMPILED_BY	"GNU-C " __VERSION__
+#endif
+
+/* OS9/68000 */
+#ifdef	OSK
+# define COMPILED_BY	"Microware C V2.3 Edition 40"
+#endif
+
+/* DEC Rainbow, running MS-DOS (handled by earlier MS-DOS tests) */
+/* (would need -DRAINBOW in CFLAGS to compile a Rainbow-compatible .EXE) */
+
+#ifdef VMS
+# define COMPILED_BY    "VAX/VMS VAXC compiler"
+# undef VMS
+# define VMS 1
+#endif
+
+/*************************** end of autoconf section ************************/
+
+/* All undefined symbols are defined to zero here, to allow for older    */
+/* compilers which dont understand #if defined() or #if UNDEFINED_SYMBOL */
+
+/*************************** operating systems *****************************/
+ 
+#ifndef	BSD
+# define BSD	0		/* UNIX - Berkeley 4.x */
+#endif
+
+#ifndef	UNIXV
+# define UNIXV	0		/* UNIX - AT&T SYSV */
+#endif
+
+#ifndef	UNIX7
+# define UNIX7	0		/* UNIX - version 7 */
+#endif
+
+#ifndef	MSDOS
+# define MSDOS	0		/* PC		*/
+#endif
+
+#ifndef	TOS
+# define TOS	0		/* Atari ST	*/
+#endif
+
+#ifndef	AMIGA
+# define AMIGA	0		/* Commodore Amiga */
+#endif
+
+#ifndef OSK
+# define OSK	0		/* OS-9 / 68k */
+#endif
+
+#ifndef COHERENT
+# define COHERENT 0		/* Coherent */
+#endif
+
+#ifndef RAINBOW			/* DEC Rainbow support, under MS-DOS */
+# define RAINBOW 0
+#endif
+
+#ifndef VMS
+# define VMS 0                  /* VAX/VMS */
+#endif
+				/* Minix has no predefines */
+#if !BSD && !UNIXV && !UNIX7 && !MSDOS && !TOS && !AMIGA && !OSK && !COHERENT && !VMS
+# define MINIX	1
+#else
+# define MINIX	0
+#endif
+
+				/* generic combination of Unices */
+#if UNIXV || UNIX7 || BSD || MINIX || COHERENT
+# define ANY_UNIX 1
+#else
+# define ANY_UNIX 0
+#endif
+
+/*************************** compilers **************************************/
+ 
+#ifndef	AZTEC_C
+# define AZTEC_C	0
+#endif
+
+#ifndef	MICROSOFT
+# define MICROSOFT	0
+#endif
+
+#ifndef	TURBOC
+# define TURBOC		0
+#endif
+
+/******************************* Credit ************************************/
+
+#if MSDOS
+# define CREDIT "Ported to MS-DOS by Guntram Blohm & Martin Patzel"
+# if RAINBOW
+#  define CREDIT2 "Rainbow support added by Willett Kempton"
+# endif
+#endif
+
+#if AMIGA
+# define CREDIT "Ported to AmigaDOS 2.04 by Mike Rieser & Dale Rahn"
+#endif
+
+#if TOS
+# define CREDIT "Ported to Atari/TOS by Guntram Blohm & Martin Patzel"
+#endif
+
+#if OSK
+# define CREDIT	"Ported to Microware OS9/68k by Peter Reinig"
+#endif
+
+#if COHERENT
+# define CREDIT	"Ported to Coherent by Esa Ahola"
+#endif
+
+#if VMS
+# define CREDIT "Ported to VAX/VMS by John Campbell"
+#endif
+/*************************** functions depending on OS *********************/
+
+/* There are two terminal-related functions that we need: ttyread() and
+ * ttywrite().  The ttyread() function implements read-with-timeout and is
+ * a true function on all systems.  The ttywrite() function is almost always
+ * just a macro...
+ */
+#if !TOS && !AMIGA
+# define ttywrite(buf, len)	write(1, buf, (unsigned)(len))	/* raw write */
+#endif
+
+/* The strchr() function is an official standard now, so everybody has it
+ * except Unix version 7 (which is old) and BSD Unix (which is academic).
+ * Those guys use something called index() to do the same thing.
+ */
+#if BSD || UNIX7 || OSK
+# define strchr	index
+#endif
+extern char *strchr();
+
+/* BSD uses bcopy() instead of memcpy() */
+#if BSD
+# define memcpy(dest, src, siz)	bcopy(src, dest, siz)
+#endif
+
+/* BSD uses getwd() instead of getcwd().  The arguments are a little different,
+ * but we'll ignore that and hope for the best; adding arguments to the macro
+ * would mess up an "extern" declaration of the function.
+ */
+#if BSD || COHERENT
+# define getcwd	getwd
+#endif
+extern char *getcwd();
+
+/* text versa binary mode for read/write */
+#if !TOS
+#define	tread(fd,buf,n)		read(fd,buf,(unsigned)(n))
+#define twrite(fd,buf,n)	write(fd,buf,(unsigned)(n))
+#endif
+
+/**************************** Compiler quirks *********************************/
+
+/* the UNIX version 7 and (some) TOS compilers, don't allow "void" */
+#if UNIX7 || TOS
+# define void int
+#endif
+
+/* as far as I know, all compilers except version 7 support unsigned char */
+/* NEWFLASH: the Minix-ST compiler has subtle problems with unsigned char */
+#if UNIX7 || MINIX
+# define UCHAR(c)	((c) & 0xff)
+# define uchar		char
+#else
+# define UCHAR(c)	((unsigned char)(c))
+# define uchar		unsigned char
+#endif
+
+/* Some compilers prefer to have malloc declared as returning a (void *) */
+#if BSD || AMIGA
+extern void *malloc();
+#else
+extern char *malloc();
+#endif
+
+/* everybody but Amiga wants lseek declared here */
+#if !AMIGA
+extern long lseek();
+#endif
+
+/******************* Names of files and environment vars **********************/
+
+#if ANY_UNIX
+# ifndef TMPDIR
+#  if MINIX
+#   define TMPDIR	"/tmp"
+#  endif
+# endif
+# ifndef PRSVDIR
+#  define PRSVDIR	"/usr/preserve"	/* directory where preserved file live */
+# endif
+# ifndef PRSVINDEX
+#  define PRSVINDEX	"/usr/preserve/Index" /* index of files in PRSVDIR */
+# endif
+# ifndef EXRC
+#  define EXRC		".exrc"		/* init file in current directory */
+# endif
+# define SCRATCHOUT	"%s/soXXXXXX"	/* temp file used as input to filter */
+# ifndef SHELL
+#  define SHELL		"/bin/sh"	/* default shell */
+# endif
+# if COHERENT
+#  ifndef REDIRECT
+#   define REDIRECT	">"		/* Coherent CC writes errors to stdout */
+#  endif
+# endif
+#endif
+
+#if AMIGA		/* Specify AMIGA environment */
+# ifndef CC_COMMAND
+#  define CC_COMMAND	"cc"		/* generic C compiler */
+# endif
+# ifndef COLON
+#  define COLON		':'		/* Amiga files can also end in `:' */
+# endif
+# ifndef SYSEXRC
+#  define SYSEXRC	"S:" EXRC	/* name of ".exrc" file in system dir */
+# endif
+# ifndef MAXRCLEN
+#  define MAXRCLEN	2048		/* max size of a .exrc file */
+# endif
+# ifndef NBUFS
+#  define NBUFS		10		/* must be at least 3 -- more is better */
+# endif
+# ifndef NEEDSYNC
+#  define NEEDSYNC	TRUE		/* assume ":se sync" by default */
+# endif
+# ifndef PRSVDIR
+#  define PRSVDIR	"Elvis:"	/* directory where preserved file live */
+# endif
+# ifndef PRSVINDEX
+#  define PRSVINDEX	"Elvis:Index"	/* index of files in PRSVDIR */
+# endif
+# ifndef REDIRECT
+#  define REDIRECT	">"		/* Amiga writes errors to stdout */
+# endif
+# ifndef SCRATCHIN
+#  define SCRATCHIN	"%sSIXXXXXX"
+# endif
+# ifndef SCRATCHOUT
+#  define SCRATCHOUT	"%sSOXXXXXX"
+# endif
+# ifndef SHELL
+#  define SHELL		"newshell"	/* default shell */
+# endif
+# ifndef TERMTYPE
+#  define TERMTYPE	"amiga"		/* default termtype */
+# endif
+# ifndef TMPDIR				/* for AMIGA should end in `:' or `/' */
+#  define TMPDIR	"T:"		/* directory where temp files live */
+# endif
+# ifndef TMPNAME
+#  define TMPNAME	"%selv_%x.%x"	/* format of names for temp files */
+# endif
+#endif
+
+#if MSDOS || TOS
+/* do not change TMPNAME and SCRATCH*: they MUST begin with '%s\\'! */
+# ifndef TMPDIR
+#  define TMPDIR	"C:\\tmp"	/* directory where temp files live */
+# endif
+# ifndef PRSVDIR
+#  define PRSVDIR	"C:\\preserve"	/* directory where preserved file live */
+# endif
+# ifndef PRSVINDEX
+#  define PRSVINDEX	"C:\\preserve\\Index" /* index of files in PRSVDIR */
+# endif
+# define TMPNAME	"%s\\elv_%x.%x" /* temp file */
+# if MSDOS
+#  if MICROSOFT
+#   define CC_COMMAND	"cl -c"		/* C compiler */
+#  else
+#   if __BORLANDC__  /* Borland C */
+#    define CC_COMMAND	"bcc"		/* C compiler */
+#   else
+#   if TURBOC        /* Turbo C */
+#    define CC_COMMAND	"tcc"		/* C compiler */
+#   endif	/* TURBOC */
+#   endif	/* BORLANDC */
+#  endif		/* MICROSOFT */
+# endif		/* MSDOS */
+# define SCRATCHIN	"%s\\siXXXXXX"	/* DOS ONLY - output of filter program */
+# define SCRATCHOUT	"%s\\soXXXXXX"	/* temp file used as input to filter */
+# define SLASH		'\\'
+# ifndef SHELL
+#  if TOS
+#   define SHELL	"shell.ttp"	/* default shell */
+#  else
+#   define SHELL	"command.com"	/* default shell */
+#  endif
+# endif
+# define NEEDSYNC	TRUE		/* assume ":se sync" by default */
+# if TOS && __GNUC__			/* probably on other systems, too */
+#  define REDIRECT	"2>"		/* GNUC reports on 2, others on 1 */
+#  define CC_COMMAND	"gcc -c"
+# else
+#  define REDIRECT	">"		/* shell's redirection of stderr */
+# endif
+#endif
+
+#if VMS
+/* do not change TMPNAME, and SCRATCH*: they MUST begin with '%s\\'! */
+# ifndef TMPDIR
+#  define TMPDIR        "sys$scratch:"  /* directory where temp files live */
+# endif
+# define TMPNAME        "%selv_%x.%x;1" /* temp file */
+# define SCRATCHIN      "%ssiXXXXXX"    /* DOS ONLY - output of filter program */
+# define SCRATCHOUT     "%ssoXXXXXX"    /* temp file used as input to filter */
+# define SLASH          '\:'  /* Worry point... jdc */
+# ifndef SHELL
+#   define SHELL        ""      /* default shell */
+# endif
+# define REDIRECT       ">"             /* shell's redirection of stderr */
+# define tread(fd,buf,n)  vms_read(fd,buf,(unsigned)(n))
+# define close vms_close
+# define lseek vms_lseek
+# define unlink vms_delete
+# define delete __delete   /* local routine conflicts w/VMS rtl routine. */
+# define rpipe vms_rpipe
+# define rpclose vms_rpclose
+# define ttyread vms_ttyread
+/* There is no sync() on vms */
+# define sync()
+/* jdc -- seems VMS external symbols are case insensitive */
+# define m_fWord m_fw_ord
+# define m_bWord m_bw_ord
+# define m_eWord m_ew_ord
+# define m_Nsrch m_n_srch
+# define m_Fch   m_f_ch
+# define m_Tch   m_t_ch
+# define v_Xchar v_x_char
+/* jdc -- also, braindead vms curses always found by linker. */
+# define LINES elvis_LINES
+# define COLS  elvis_COLS
+# define curscr elvis_curscr
+# define stdscr elvis_stdscr
+# define initscr elvis_initscr
+# define endwin  elvis_endwin
+# define wrefresh elvis_wrefresh
+#endif
+
+#if OSK
+# ifndef TMPDIR
+#  define TMPDIR	"/dd/tmp"	   /* directory where temp files live */
+# endif
+# ifndef PRSVDIR
+#  define PRSVDIR	"/dd/usr/preserve" /* directory where preserved file live */
+# endif
+# ifndef PRSVINDEX
+#  define PRSVINDEX	"/dd/usr/preserve/Index" /* index of files in PRSVDIR */
+# endif
+# ifndef CC_COMMAND
+#  define CC_COMMAND	"cc -r"		   /* name of the compiler */
+# endif
+# ifndef EXRC
+#  define EXRC		".exrc"		   /* init file in current directory */
+# endif
+# define SCRATCHOUT	"%s/soXXXXXX"	   /* temp file used as input to filter */
+# ifndef SHELL
+#  define SHELL		"shell"		   /* default shell */
+# endif
+# define FILEPERMS	(S_IREAD|S_IWRITE) /* file permissions used for creat() */
+# define REDIRECT	">>-"		   /* shell's redirection of stderr */
+# define sync()				   /* OS9 doesn't need a sync() */
+#endif
+
+#ifndef	TAGS
+# define TAGS		"tags"		/* name of the tags file */
+#endif
+
+#ifndef TMPNAME
+# define TMPNAME	"%s/elv_%x.%x"	/* format of names for temp files */
+#endif
+
+#ifndef EXINIT
+# define EXINIT		"EXINIT"	/* name of EXINIT environment variable */
+#endif
+
+#ifndef	EXRC
+# define EXRC		"elvis.rc"	/* name of ".exrc" file in current dir */
+#endif
+
+#ifndef HMEXRC
+# define HMEXRC		EXRC		/* name of ".exrc" file in home dir */
+#endif
+
+#ifndef	KEYWORDPRG
+# define KEYWORDPRG	"ref"
+#endif
+
+#ifndef	SCRATCHOUT
+# define SCRATCHIN	"%s/SIXXXXXX"
+# define SCRATCHOUT	"%s/SOXXXXXX"
+#endif
+
+#ifndef ERRLIST
+# define ERRLIST	"errlist"
+#endif
+
+#ifndef	SLASH
+# define SLASH		'/'
+#endif
+
+#ifndef SHELL
+# define SHELL		"shell"
+#endif
+
+#ifndef REG
+# define REG		register
+#endif
+
+#ifndef NEEDSYNC
+# define NEEDSYNC	FALSE
+#endif
+
+#ifndef FILEPERMS
+# define FILEPERMS	0666
+#endif
+
+#ifndef PRESERVE
+# define PRESERVE	"elvprsv"	/* name of the "preserve" program */
+#endif
+
+#ifndef CC_COMMAND
+# define CC_COMMAND	"cc -c"
+#endif
+
+#ifndef MAKE_COMMAND
+# define MAKE_COMMAND	"make"
+#endif
+
+#ifndef REDIRECT
+# define REDIRECT	"2>"
+#endif
+
+#ifndef BLKSIZE
+# ifdef CRUNCH
+#  define BLKSIZE	1024
+# else
+#  define BLKSIZE	2048
+# endif
+#endif
+
+#ifndef KEYBUFSIZE
+# define KEYBUFSIZE	1000
+#endif
+
+#endif  /* ndef _CONFIG_H */
Index: /trunk/minix/commands/elvis/ctags.c
===================================================================
--- /trunk/minix/commands/elvis/ctags.c	(revision 9)
+++ /trunk/minix/commands/elvis/ctags.c	(revision 9)
@@ -0,0 +1,819 @@
+/* ctags.c */
+
+/* This is a reimplementation of the ctags(1) program.  It supports ANSI C,
+ * and has heaps o' flags.  It is meant to be distributed with elvis.
+ */
+
+#include <stdio.h>
+#include "config.h"
+#ifndef FALSE
+# define FALSE	0
+# define TRUE	1
+#endif
+#ifndef TAGS
+# define TAGS	"tags"
+#endif
+#ifndef REFS
+# define REFS	"refs"
+#endif
+#ifndef BLKSIZE
+# define BLKSIZE 1024
+#endif
+
+#include "ctype.c" /* yes, that really is the .c file, not the .h one. */
+
+/* -------------------------------------------------------------------------- */
+/* Some global variables */
+
+/* The following boolean variables are set according to command line flags */
+int	incl_static;	/* -s  include static tags */
+int	incl_types;	/* -t  include typedefs and structs */
+int	incl_vars;	/* -v  include variables */
+int	make_refs;	/* -r  generate a "refs" file */
+int	append_files;	/* -a  append to "tags" [and "refs"] files */
+
+/* The following are used for outputting to the "tags" and "refs" files */
+FILE	*tags;		/* used for writing to the "tags" file */
+FILE	*refs;		/* used for writing to the "refs" file */
+
+/* -------------------------------------------------------------------------- */
+/* These are used for reading a source file.  It keeps track of line numbers */
+char	*file_name;	/* name of the current file */
+FILE	*file_fp;	/* stream used for reading the file */
+long	file_lnum;	/* line number in the current file */
+long	file_seek;	/* fseek() offset to the start of current line */
+int	file_afternl;	/* boolean: was previous character a newline? */
+int	file_prevch;	/* a single character that was ungotten */
+int	file_header;	/* boolean: is the current file a header file? */
+
+/* This function opens a file, and resets the line counter.  If it fails, it
+ * it will display an error message and leave the file_fp set to NULL.
+ */
+void file_open(name)
+	char	*name;	/* name of file to be opened */
+{
+	/* if another file was already open, then close it */
+	if (file_fp)
+	{
+		fclose(file_fp);
+	}
+
+	/* try to open the file for reading.  The file must be opened in
+	 * "binary" mode because otherwise fseek() would misbehave under DOS.
+	 */
+#if MSDOS || TOS
+	file_fp = fopen(name, "rb");
+#else
+	file_fp = fopen(name, "r");
+#endif
+	if (!file_fp)
+	{
+		perror(name);
+	}
+
+	/* reset the name & line number */
+	file_name = name;
+	file_lnum = 0L;
+	file_seek = 0L;
+	file_afternl = TRUE;
+
+	/* determine whether this is a header file */
+	file_header = FALSE;
+	name += strlen(name) - 2;
+	if (name >= file_name && name[0] == '.' && (name[1] == 'h' || name[1] == 'H'))
+	{
+		file_header = TRUE;
+	}
+}
+
+/* This function reads a single character from the stream.  If the *previous*
+ * character was a newline, then it also increments file_lnum and sets
+ * file_offset.
+ */
+int file_getc()
+{
+	int	ch;
+
+	/* if there is an ungotten character, then return it.  Don't do any
+	 * other processing on it, though, because we already did that the
+	 * first time it was read.
+	 */
+	if (file_prevch)
+	{
+		ch = file_prevch;
+		file_prevch = 0;
+		return ch;
+	}
+
+	/* if previous character was a newline, then we're starting a line */
+	if (file_afternl)
+	{
+		file_afternl = FALSE;
+		file_seek = ftell(file_fp);
+		file_lnum++;
+	}
+
+	/* Get a character.  If no file is open, then return EOF */
+	ch = (file_fp ? getc(file_fp) : EOF);
+
+	/* if it is a newline, then remember that fact */
+	if (ch == '\n')
+	{
+		file_afternl = TRUE;
+	}
+
+	/* return the character */
+	return ch;
+}
+
+/* This function ungets a character from the current source file */
+void file_ungetc(ch)
+	int	ch;	/* character to be ungotten */
+{
+	file_prevch = ch;
+}
+
+/* This function copies the current line out some other fp.  It has no effect
+ * on the file_getc() function.  During copying, any '\' characters are doubled
+ * and a leading '^' or trailing '$' is also quoted.  The newline character is
+ * not copied.
+ *
+ * This is meant to be used when generating a tag line.
+ */
+void file_copyline(seek, fp)
+	long	seek;	/* where the lines starts in the source file */
+	FILE	*fp;	/* the output stream to copy it to */
+{
+	long	oldseek;/* where the file's pointer was before we messed it up */
+	char	ch;	/* a single character from the file */
+	char	next;	/* the next character from this file */
+
+	/* go to the start of the line */
+	oldseek = ftell(file_fp);
+	fseek(file_fp, seek, 0);
+
+	/* if first character is '^', then emit \^ */
+	ch = getc(file_fp);
+	if (ch == '^')
+	{
+		putc('\\', fp);
+		putc('^', fp);
+		ch = getc(file_fp);
+	}
+
+	/* write everything up to, but not including, the newline */
+	while (ch != '\n')
+	{
+		/* preread the next character from this file */
+		next = getc(file_fp);
+
+		/* if character is '\', or a terminal '$', then quote it */
+		if (ch == '\\' || (ch == '$' && next == '\n'))
+		{
+			putc('\\', fp);
+		}
+		putc(ch, fp);
+
+		/* next character... */
+		ch = next;
+	}
+
+	/* seek back to the old position */
+	fseek(file_fp, oldseek, 0);
+}
+
+/* -------------------------------------------------------------------------- */
+/* This section handles preprocessor directives.  It strips out all of the
+ * directives, and may emit a tag for #define directives.
+ */
+
+int	cpp_afternl;	/* boolean: look for '#' character? */
+int	cpp_prevch;	/* an ungotten character, if any */
+int	cpp_refsok;	/* boolean: can we echo characters out to "refs"? */
+
+/* This function opens the file & resets variables */
+void cpp_open(name)
+	char	*name;	/* name of source file to be opened */
+{
+	/* use the lower-level file_open function to open the file */
+	file_open(name);
+
+	/* reset variables */
+	cpp_afternl = TRUE;
+	cpp_refsok = TRUE;
+}
+
+/* This function copies a character from the source file to the "refs" file */
+void cpp_echo(ch)
+	int	ch; /* the character to copy */
+{
+	static	wasnl;
+
+	/* echo non-EOF chars, unless not making "ref", or echo turned off */
+	if (ch != EOF && make_refs && cpp_refsok && !file_header)
+	{
+		/* try to avoid blank lines */
+		if (ch == '\n')
+		{
+			if (wasnl)
+			{
+				return;
+			}
+			wasnl = TRUE;
+		}
+		else
+		{
+			wasnl = FALSE;
+		}
+
+		/* add the character */
+		putc(ch, refs);
+	}
+}
+
+/* This function returns the next character which isn't part of a directive */
+int cpp_getc()
+{
+	static
+	int	ch;	/* the next input character */
+	char	*scan;
+
+	/* if we have an ungotten character, then return it */
+	if (cpp_prevch)
+	{
+		ch = cpp_prevch;
+		cpp_prevch = 0;
+		return ch;
+	}
+
+	/* Get a character from the file.  Return it if not special '#' */
+	ch = file_getc();
+	if (ch == '\n')
+	{
+		cpp_afternl = TRUE;
+		cpp_echo(ch);
+		return ch;
+	}
+	else if (ch != '#' || !cpp_afternl)
+	{
+		/* normal character.  Any non-whitespace should turn off afternl */
+		if (ch != ' ' && ch != '\t')
+		{
+			cpp_afternl = FALSE;
+		}
+		cpp_echo(ch);
+		return ch;
+	}
+
+	/* Yikes!  We found a directive */
+
+	/* see whether this is a #define line */
+	scan = " define ";
+	while (*scan)
+	{
+		if (*scan == ' ')
+		{
+			/* space character matches any whitespace */
+			do
+			{
+				ch = file_getc();
+			} while (ch == ' ' || ch == '\t');
+			file_ungetc(ch);
+		}
+		else
+		{
+			/* other characters should match exactly */
+			ch = file_getc();
+			if (ch != *scan)
+			{
+				file_ungetc(ch);
+				break;
+			}
+		}
+		scan++;
+	}
+
+	/* is this a #define line?  and should we generate a tag for it? */
+	if (!*scan && (file_header || incl_static))
+	{
+		/* if not a header, then this will be a static tag */
+		if (!file_header)
+		{
+			fputs(file_name, tags);
+			putc(':', tags);
+		}
+
+		/* output the tag name */
+		for (ch = file_getc(); isalnum(ch) || ch == '_'; ch = file_getc())
+		{
+			putc(ch, tags);
+		}
+
+		/* output a tab, the filename, another tab, and the line number */
+		fprintf(tags, "\t%s\t%ld\n", file_name, file_lnum);
+	}
+
+	/* skip to the end of the directive -- a newline that isn't preceded
+	 * by a '\' character.
+	 */
+	while (ch != EOF && ch != '\n')
+	{
+		if (ch == '\\')
+		{
+			ch = file_getc();
+		}
+		ch = file_getc();
+	}
+
+	/* return the newline that we found at the end of the directive */
+	cpp_echo(ch);
+	return ch;
+}
+
+/* This puts a character back into the input queue for the source file */
+cpp_ungetc(ch)
+	int	ch;	/* a character to be ungotten */
+{
+	cpp_prevch = ch;
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* This is the lexical analyser.  It gets characters from the preprocessor,
+ * and gives tokens to the parser.  Some special codes are...
+ *   (deleted)  /*...* /	(comments)
+ *   (deleted)	//...\n	(comments)
+ *   (deleted)	(*	(parens used in complex declaration)
+ *   (deleted)	[...]	(array subscript, when ... contains no ])
+ *   (deleted)	struct	(intro to structure declaration)
+ *   BODY	{...}	('{' can occur anywhere, '}' only at BOW if ... has '{')
+ *   ARGS	(...{	(args of function, not extern or forward)
+ *   ARGS	(...);	(args of an extern/forward function declaration)
+ *   COMMA	,	(separate declarations that have same scope)
+ *   SEMICOLON	;	(separate declarations that have different scope)
+ *   SEMICOLON  =...;	(initializer)
+ *   TYPEDEF	typedef	(the "typedef" keyword)
+ *   STATIC	static	(the "static" keyword)
+ *   STATIC	private	(the "static" keyword)
+ *   STATIC	PRIVATE	(the "static" keyword)
+ *   NAME	[a-z]+	(really any valid name that isn't reserved word)
+ */
+
+/* #define EOF -1 */
+#define DELETED	  0
+#define BODY	  1
+#define ARGS	  2
+#define COMMA	  3
+#define SEMICOLON 4
+#define TYPEDEF   5
+#define STATIC	  6
+#define EXTERN	  7
+#define NAME	  8
+
+char	lex_name[BLKSIZE];	/* the name of a "NAME" token */
+long	lex_seek;		/* start of line that contains lex_name */
+
+lex_gettoken()
+{
+	int	ch;		/* a character from the preprocessor */
+	int	next;		/* the next character */
+	int	token;		/* the token that we'll return */
+	int	i;
+
+	/* loop until we get a token that isn't "DELETED" */
+	do
+	{
+		/* get the next character */
+		ch = cpp_getc();
+
+		/* process the character */
+		switch (ch)
+		{
+		  case ',':
+			token = COMMA;
+			break;
+
+		  case ';':
+			token = SEMICOLON;
+			break;
+
+		  case '/':
+			/* get the next character */
+			ch = cpp_getc();
+			switch (ch)
+			{
+			  case '*':	/* start of C comment */
+				ch = cpp_getc();
+				next = cpp_getc();
+				while (next != EOF && (ch != '*' || next != '/'))
+				{
+					ch = next;
+					next = cpp_getc();
+				}
+				break;
+
+			  case '/':	/* start of a C++ comment */
+				do
+				{
+					ch = cpp_getc();
+				} while (ch != '\n' && ch != EOF);
+				break;
+
+			  default:	/* some other slash */
+				cpp_ungetc(ch);
+			}
+			token = DELETED;
+			break;
+
+		  case '(':
+			ch = cpp_getc();
+			if (ch == '*')
+			{
+				token = DELETED;
+			}
+			else
+			{
+				next = cpp_getc();
+				while (ch != '{' && ch != EOF && (ch != ')' || next != ';'))/*}*/
+				{
+					ch = next;
+					next = cpp_getc();
+				}
+				if (ch == '{')/*}*/
+				{
+					cpp_ungetc(ch);
+				}
+				else if (next == ';')
+				{
+					cpp_ungetc(next);
+				}
+				token = ARGS;
+			}
+			break;
+
+		  case '{':/*}*/
+			/* don't send the next characters to "refs" */
+			cpp_refsok = FALSE;
+
+			/* skip ahead to closing '}', or to embedded '{' */
+			do
+			{
+				ch = cpp_getc();
+			} while (ch != '{' && ch != '}' && ch != EOF);
+
+			/* if has embedded '{', then skip to '}' in column 1 */
+			if (ch == '{') /*}*/
+			{
+				ch = cpp_getc();
+				next = cpp_getc();
+				while (ch != EOF && (ch != '\n' || next != '}'))/*{*/
+				{
+					ch = next;
+					next = cpp_getc();
+				}
+			}
+
+			/* resume "refs" processing */
+			cpp_refsok = TRUE;
+			cpp_echo('}');
+
+			token = BODY;
+			break;
+
+		  case '[':
+			/* skip to matching ']' */
+			do
+			{
+				ch = cpp_getc();
+			} while (ch != ']' && ch != EOF);
+			token = DELETED;
+			break;
+
+		  case '=':
+		  	/* skip to next ';' */
+			do
+			{
+				ch = cpp_getc();
+
+				/* leave array initializers out of "refs" */
+				if (ch == '{')
+				{
+					cpp_refsok = FALSE;
+				}
+			} while (ch != ';' && ch != EOF);
+
+			/* resume echoing to "refs" */
+			if (!cpp_refsok)
+			{
+				cpp_refsok = TRUE;
+				cpp_echo('}');
+				cpp_echo(';');
+			}
+			token = SEMICOLON;
+			break;
+
+		  case EOF:
+			token = EOF;
+			break;
+
+		  default:
+			/* is this the start of a name/keyword? */
+			if (isalpha(ch) || ch == '_')
+			{
+				/* collect the whole word */
+				lex_name[0] = ch;
+				for (i = 1, ch = cpp_getc();
+				     i < BLKSIZE - 1 && (isalnum(ch) || ch == '_');
+				     i++, ch = cpp_getc())
+				{
+					lex_name[i] = ch;
+				}
+				lex_name[i] = '\0';
+				cpp_ungetc(ch);
+
+				/* is it a reserved word? */
+				if (!strcmp(lex_name, "typedef"))
+				{
+					token = TYPEDEF;
+					lex_seek = -1L;
+				}
+				else if (!strcmp(lex_name, "static")
+				      || !strcmp(lex_name, "private")
+				      || !strcmp(lex_name, "PRIVATE"))
+				{
+					token = STATIC;
+					lex_seek = -1L;
+				}
+				else if (!strcmp(lex_name, "extern")
+				      || !strcmp(lex_name, "EXTERN")
+				      || !strcmp(lex_name, "FORWARD"))
+				{
+					token = EXTERN;
+					lex_seek = -1L;
+				}
+				else
+				{
+					token = NAME;
+					lex_seek = file_seek;
+				}
+			}
+			else /* not part of a name/keyword */
+			{
+				token = DELETED;
+			}
+
+		} /* end switch(ch) */
+
+	} while (token == DELETED);
+
+	return token;
+}
+
+/* -------------------------------------------------------------------------- */
+/* This is the parser.  It locates tag candidates, and then decides whether to
+ * generate a tag for them.
+ */
+
+/* This function generates a tag for the object in lex_name, whose tag line is
+ * located at a given seek offset.
+ */
+void maketag(scope, seek)
+	int	scope;	/* 0 if global, or STATIC if static */
+	long	seek;	/* the seek offset of the line */
+{
+	/* output the tagname and filename fields */
+	if (scope == EXTERN)
+	{
+		/* whoa!  we should *never* output a tag for "extern" decl */
+		return;
+	}
+	else if (scope == STATIC)
+	{
+		fprintf(tags, "%s:%s\t%s\t", file_name, lex_name, file_name);
+	}
+	else
+	{
+		fprintf(tags, "%s\t%s\t", lex_name, file_name);
+	}
+
+	/* output the target line */
+	putc('/', tags);
+	putc('^', tags);
+	file_copyline(seek, tags);
+	putc('$', tags);
+	putc('/', tags);
+	putc('\n', tags);
+}
+
+
+/* This function parses a source file, adding any tags that it finds */
+void ctags(name)
+	char	*name;	/* the name of a source file to be checked */
+{
+	int	prev;	/* the previous token from the source file */
+	int	token;	/* the current token from the source file */
+	int	scope;	/* normally 0, but could be a TYPEDEF or STATIC token */
+	int	gotname;/* boolean: does lex_name contain a tag candidate? */
+	long	tagseek;/* start of line that contains lex_name */
+
+	/* open the file */
+	cpp_open(name);
+
+	/* reset */
+	scope = 0;
+	gotname = FALSE;
+	token = SEMICOLON;
+
+	/* parse until the end of the file */
+	while (prev = token, (token = lex_gettoken()) != EOF)
+	{
+		/* scope keyword? */
+		if (token == TYPEDEF || token == STATIC || token == EXTERN)
+		{
+			scope = token;
+			gotname = FALSE;
+			continue;
+		}
+
+		/* name of a possible tag candidate? */
+		if (token == NAME)
+		{
+			tagseek = file_seek;
+			gotname = TRUE;
+			continue;
+		}
+
+		/* if NAME BODY, without ARGS, then NAME is a struct tag */
+		if (gotname && token == BODY && prev != ARGS)
+		{
+			gotname = FALSE;
+			
+			/* ignore if in typedef -- better name is coming soon */
+			if (scope == TYPEDEF)
+			{
+				continue;
+			}
+
+			/* generate a tag, if -t and maybe -s */
+			if (incl_types && (file_header || incl_static))
+			{
+				maketag(file_header ? 0 : STATIC, tagseek);
+			}
+		}
+
+		/* If NAME ARGS BODY, then NAME is a function */
+		if (gotname && prev == ARGS && token == BODY)
+		{
+			gotname = FALSE;
+			
+			/* generate a tag, maybe checking -s */
+			if (scope != STATIC || incl_static)
+			{
+				maketag(scope, tagseek);
+			}
+		}
+
+		/* If NAME SEMICOLON or NAME COMMA, then NAME is var/typedef */
+		if (gotname && (token == SEMICOLON || token == COMMA))
+		{
+			gotname = FALSE;
+
+			/* generate a tag, if -v/-t and maybe -s */
+			if (scope == TYPEDEF && incl_types && (file_header || incl_static)
+			 || scope == STATIC && incl_vars && incl_static
+			 || incl_vars)
+			{
+				/* a TYPEDEF outside of a header is STATIC */
+				if (scope == TYPEDEF && !file_header)
+				{
+					maketag(STATIC, tagseek);
+				}
+				else /* use whatever scope was declared */
+				{
+					maketag(scope, tagseek);
+				}
+			}
+		}
+
+		/* reset after a semicolon or ARGS BODY pair */
+		if (token == SEMICOLON || (prev == ARGS && token == BODY))
+		{
+			scope = 0;
+			gotname = FALSE;
+		}
+	}
+
+	/* The source file will be automatically closed */
+}
+
+/* -------------------------------------------------------------------------- */
+
+void usage()
+{
+	fprintf(stderr, "usage: ctags [flags] filenames...\n");
+	fprintf(stderr, "\t-s  include static functions\n");
+	fprintf(stderr, "\t-t  include typedefs\n");
+	fprintf(stderr, "\t-v  include variable declarations\n");
+	fprintf(stderr, "\t-r  generate a \"refs\" file, too\n");
+	fprintf(stderr, "\t-a  append to \"tags\", instead of overwriting\n");
+	exit(2);
+}
+
+
+
+#if AMIGA
+# include "amiwild.c"
+#endif
+
+#if VMS
+# include "vmswild.c"
+#endif
+
+main(argc, argv)
+	int	argc;
+	char	**argv;
+{
+	int	i, j;
+
+#if MSDOS || TOS
+	char	**wildexpand();
+	argv = wildexpand(&argc, argv);
+#endif
+
+	/* build the tables used by the ctype macros */
+	_ct_init("");
+
+	/* parse the option flags */
+	for (i = 1; i < argc && argv[i][0] == '-'; i++)
+	{
+		for (j = 1; argv[i][j]; j++)
+		{
+			switch (argv[i][j])
+			{
+			  case 's':	incl_static = TRUE;	break;
+			  case 't':	incl_types = TRUE;	break;
+			  case 'v':	incl_vars = TRUE;	break;
+			  case 'r':	make_refs = TRUE;	break;
+			  case 'a':	append_files = TRUE;	break;
+			  default:	usage();
+			}
+		}
+	}
+
+	/* There should always be at least one source file named in args */
+	if (i == argc)
+	{
+		usage();
+	}
+
+	/* open the "tags" and maybe "refs" files */
+	tags = fopen(TAGS, append_files ? "a" : "w");
+	if (!tags)
+	{
+		perror(TAGS);
+		exit(3);
+	}
+	if (make_refs)
+	{
+		refs = fopen(REFS, append_files ? "a" : "w");
+		if (!refs)
+		{
+			perror(REFS);
+			exit(4);
+		}
+	}
+
+	/* parse each source file */
+	for (; i < argc; i++)
+	{
+		ctags(argv[i]);
+	}
+
+	/* close "tags" and maybe "refs" */
+	fclose(tags);
+	if (make_refs)
+	{
+		fclose(refs);
+	}
+
+#ifdef SORT
+		/* This is a hack which will sort the tags list.   It should
+		 * on UNIX and OS-9.  You may have trouble with csh.   Note
+		 * that the tags list only has to be sorted if you intend to
+		 * use it with the real vi;  elvis permits unsorted tags.
+		 */
+# if OSK
+		system("qsort tags >-_tags; -nx; del tags; rename _tags tags");
+# else	
+		system("sort tags >_tags$$; mv _tags$$ tags");
+# endif
+#endif
+
+	exit(0);
+	/*NOTREACHED*/
+}
+
+#if MSDOS || TOS
+# define WILDCARD_NO_MAIN
+# include "wildcard.c"
+#endif
Index: /trunk/minix/commands/elvis/ctype.c
===================================================================
--- /trunk/minix/commands/elvis/ctype.c	(revision 9)
+++ /trunk/minix/commands/elvis/ctype.c	(revision 9)
@@ -0,0 +1,74 @@
+/* ctype.c */
+
+/* This file contains the tables and initialization function for elvis'
+ * version of <ctype.h>.  It should be portable.
+ */
+
+#include "config.h"
+#include "ctype.h"
+
+uchar	_ct_toupper[256];
+uchar	_ct_tolower[256];
+uchar	_ct_ctypes[256];
+
+/* This function initializes the tables used by the ctype macros.  It should
+ * be called at the start of the program.  It can be called again anytime you
+ * wish to change the non-standard "flipcase" list.  The "flipcase" list is
+ * a string of characters which are taken to be lowercase/uppercase pairs.
+ * If you don't want to use any special flipcase characters, then pass an
+ * empty string.
+ */
+void _ct_init(flipcase)
+	uchar	*flipcase;	/* list of non-standard lower/upper letter pairs */
+{
+	int	i;
+	uchar	*scan;
+
+	/* reset all of the tables */
+	for (i = 0; i < 256; i++)
+	{
+		_ct_toupper[i] = _ct_tolower[i] = i;
+		_ct_ctypes[i] = 0;
+	}
+
+	/* add the digits */
+	for (scan = (uchar *)"0123456789"; *scan; scan++)
+	{
+		_ct_ctypes[*scan] |= _CT_DIGIT | _CT_ALNUM;
+	}
+
+	/* add the whitespace */
+	for (scan = (uchar *)" \t\n\r\f"; *scan; scan++)
+	{
+		_ct_ctypes[*scan] |= _CT_SPACE;
+	}
+
+	/* add the standard ASCII letters */
+	for (scan = (uchar *)"aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"; *scan; scan += 2)
+	{
+		_ct_ctypes[scan[0]] |= _CT_LOWER | _CT_ALNUM;
+		_ct_ctypes[scan[1]] |= _CT_UPPER | _CT_ALNUM;
+		_ct_toupper[scan[0]] = scan[1];
+		_ct_tolower[scan[1]] = scan[0];
+	}
+
+	/* add the flipcase letters */
+	for (scan = flipcase; scan[0] && scan[1]; scan += 2)
+	{
+		_ct_ctypes[scan[0]] |= _CT_LOWER | _CT_ALNUM;
+		_ct_ctypes[scan[1]] |= _CT_UPPER | _CT_ALNUM;
+		_ct_toupper[scan[0]] = scan[1];
+		_ct_tolower[scan[1]] = scan[0];
+	}
+
+	/* include '_' in the isalnum() list */
+	_ct_ctypes[UCHAR('_')] |= _CT_ALNUM;
+
+	/* !!! find the control characters in an ASCII-dependent way */
+	for (i = 0; i < ' '; i++)
+	{
+		_ct_ctypes[i] |= _CT_CNTRL;
+	}
+	_ct_ctypes[127] |= _CT_CNTRL;
+	_ct_ctypes[255] |= _CT_CNTRL;
+}
Index: /trunk/minix/commands/elvis/ctype.h
===================================================================
--- /trunk/minix/commands/elvis/ctype.h	(revision 9)
+++ /trunk/minix/commands/elvis/ctype.h	(revision 9)
@@ -0,0 +1,40 @@
+/* ctype.h */
+
+/* This file contains macros definitions and extern declarations for a
+ * version of <ctype.h> which is aware of the o_flipcase letters used in
+ * elvis.
+ *
+ * This file uses the "uchar" data type and "UCHAR" conversion macro which
+ * are defined in "config.h".  Consequently, any file that includes this
+ * header must include config.h first.
+ */
+
+#ifndef _CT_UPPER
+
+#define _CT_UPPER	0x01
+#define _CT_LOWER	0x02
+#define _CT_SPACE	0x04
+#define _CT_DIGIT	0x08
+#define _CT_ALNUM	0x10
+#define _CT_CNTRL	0x20
+
+#define isalnum(c)	(_ct_ctypes[UCHAR(c)] & _CT_ALNUM)
+#define isalpha(c)	(_ct_ctypes[UCHAR(c)] & (_CT_LOWER|_CT_UPPER))
+#define isdigit(c)	(_ct_ctypes[UCHAR(c)] & _CT_DIGIT)
+#define islower(c)	(_ct_ctypes[UCHAR(c)] & _CT_LOWER)
+#define isspace(c)	(_ct_ctypes[UCHAR(c)] & _CT_SPACE)
+#define isupper(c)	(_ct_ctypes[UCHAR(c)] & _CT_UPPER)
+#define iscntrl(c)	(_ct_ctypes[UCHAR(c)] & _CT_CNTRL)
+#define ispunct(c)	(!_ct_ctypes[UCHAR(c)]) /* punct = "none of the above" */
+
+#define isascii(c)	(!((c) & 0x80))
+
+#define toupper(c)	_ct_toupper[UCHAR(c)]
+#define tolower(c)	_ct_tolower[UCHAR(c)]
+
+extern uchar	_ct_toupper[];
+extern uchar	_ct_tolower[];
+extern uchar	_ct_ctypes[];
+extern void	_ct_init(/* char *flipcase */);
+
+#endif /* ndef _CT_UPPER */
Index: /trunk/minix/commands/elvis/curses.c
===================================================================
--- /trunk/minix/commands/elvis/curses.c	(revision 9)
+++ /trunk/minix/commands/elvis/curses.c	(revision 9)
@@ -0,0 +1,930 @@
+/* curses.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains the functions & variables needed for a tiny subset of
+ * curses.  The principle advantage of this version of curses is its
+ * extreme speed.  Disadvantages are potentially larger code, few supported
+ * functions, limited compatibility with full curses, and only stdscr.
+ */
+
+#include "config.h"
+#include "vi.h"
+
+#if ANY_UNIX
+/* The termios/termio/sgtty #ifdefs were a mess, so I removed all but termios.
+ * (KJB)
+ */
+# include	<termios.h>
+# if MINIX
+#  include	<sys/ioctl.h>
+# endif
+#endif
+
+#if TOS
+# include	<osbind.h>
+#endif
+
+#if OSK
+# include	<sgstat.h>
+#endif
+
+#if VMS
+extern int VMS_read_raw;  /* Set in initscr() */
+#endif
+
+
+extern char	*getenv();
+static void	 starttcap();
+
+/* variables, publicly available & used in the macros */
+char	*termtype;	/* name of terminal entry */
+short	ospeed;		/* speed of the tty, eg B2400 */
+#if OSK
+char	PC_;	/* Pad char */
+char	*BC;	/* backspace character string */
+#else
+char	PC;		/* Pad char */
+#endif
+WINDOW	*stdscr;	/* pointer into kbuf[] */
+WINDOW	kbuf[KBSIZ];	/* a very large output buffer */
+int	LINES;		/* :li#: number of rows */
+int	COLS;		/* :co#: number of columns */
+int	AM;		/* :am:  boolean: auto margins? */
+int	PT;		/* :pt:  boolean: physical tabs? */
+char	*VB;		/* :vb=: visible bell */
+char	*UP;		/* :up=: move cursor up */
+char	*SO = "";	/* :so=: standout start */
+char	*SE = "";	/* :se=: standout end */
+char	*US = "";	/* :us=: underline start */
+char	*UE = "";	/* :ue=: underline end */
+char	*MD = "";	/* :md=: bold start */
+char	*ME = "";	/* :me=: bold end */
+char	*AS = "";	/* :as=: alternate (italic) start */
+char	*AE = "";	/* :ae=: alternate (italic) end */
+#ifndef NO_VISIBLE
+char	*MV;		/* :mv=: "visible" selection start */
+#endif
+char	*CM;		/* :cm=: cursor movement */
+char	*CE;		/* :ce=: clear to end of line */
+char	*CD;		/* :cd=: clear to end of screen */
+char	*AL;		/* :al=: add a line */
+char	*DL;		/* :dl=: delete a line */
+#if OSK
+char	*SR_;		/* :sr=: scroll reverse */
+#else
+char	*SR;		/* :sr=: scroll reverse */
+#endif
+char	*KS = "";	/* :ks=: init string for cursor */
+char	*KE = "";	/* :ke=: restore string for cursor */
+char	*KU;		/* :ku=: key sequence sent by up arrow */
+char	*KD;		/* :kd=: key sequence sent by down arrow */
+char	*KL;		/* :kl=: key sequence sent by left arrow */
+char	*KR;		/* :kr=: key sequence sent by right arrow */
+char	*HM;		/* :HM=: key sequence sent by the <Home> key */
+char	*EN;		/* :EN=: key sequence sent by the <End> key */
+char	*PU;		/* :PU=: key sequence sent by the <PgUp> key */
+char	*PD;		/* :PD=: key sequence sent by the <PgDn> key */
+char	*KI;		/* :kI=: key sequence sent by the <Insert> key */
+#ifndef NO_FKEY
+char	*FKEY[NFKEYS];	/* :k0=: ... :k9=: sequences sent by function keys */
+#endif
+char	*IM = "";	/* :im=: insert mode start */
+char	*IC = "";	/* :ic=: insert the following character */
+char	*EI = "";	/* :ei=: insert mode end */
+char	*DC;		/* :dc=: delete a character */
+char	*TI = "";	/* :ti=: terminal init */	/* GB */
+char	*TE = "";	/* :te=: terminal exit */	/* GB */
+#ifndef NO_CURSORSHAPE
+#if 1
+char	*CQ = (char *)0;/* :cQ=: normal cursor */
+char	*CX = (char *)1;/* :cX=: cursor used for EX command/entry */
+char	*CV = (char *)2;/* :cV=: cursor used for VI command mode */
+char	*CI = (char *)3;/* :cI=: cursor used for VI input mode */
+char	*CR = (char *)4;/* :cR=: cursor used for VI replace mode */
+#else
+char	*CQ = "";	/* :cQ=: normal cursor */
+char	*CX = "";	/* :cX=: cursor used for EX command/entry */
+char	*CV = "";	/* :cV=: cursor used for VI command mode */
+char	*CI = "";	/* :cI=: cursor used for VI input mode */
+char	*CR = "";	/* :cR=: cursor used for VI replace mode */
+#endif
+#endif
+char	*aend = "";	/* end an attribute -- either UE or ME */
+char	ERASEKEY;	/* backspace key taken from ioctl structure */
+#ifndef NO_COLOR
+char	normalcolor[16];
+char	SOcolor[16];
+char	SEcolor[16];
+char	UScolor[16];
+char	UEcolor[16];
+char	MDcolor[16];
+char	MEcolor[16];
+char	AScolor[16];
+char	AEcolor[16];
+# ifndef NO_POPUP
+char	POPUPcolor[16];
+# endif
+# ifndef NO_VISIBLE
+char	VISIBLEcolor[16];
+# endif
+#endif
+
+#if ANY_UNIX
+static struct termios	oldtermio;	/* original tty mode */
+static struct termios	newtermio;	/* cbreak/noecho tty mode */
+#endif
+
+#if OSK
+static struct sgbuf	oldsgttyb;	/* orginal tty mode */
+static struct sgbuf	newsgttyb;	/* noecho tty mode */
+#endif
+
+static char	*capbuf;	/* capability string buffer */
+
+
+/* Initialize the Curses package. */
+void initscr()
+{
+	/* make sure TERM variable is set */
+	termtype = getenv("TERM");
+
+#if VMS
+	/* VMS getenv() handles TERM as a environment setting.  Foreign 
+	 * terminal support can be implemented by setting the ELVIS_TERM
+	 * logical or symbol to match a tinytcap entry.
+	 */
+	if (!strcmp(termtype,"unknown"))
+		termtype = getenv("ELVIS_TERM");
+#endif
+#if MSDOS
+	/* For MS-DOS, if TERM is unset we can default to "pcbios", or
+	 * maybe "rainbow".
+	 */
+	if (!termtype)
+	{
+#ifdef RAINBOW
+		if (*(unsigned char far*)(0xffff000eL) == 6   /* Rainbow 100a */
+		 || *(unsigned char far*)(0xffff000eL) == 148)/* Rainbow 100b */
+		{
+			termtype = "rainbow";
+		}
+		else
+#endif
+			termtype = "pcbios";
+	}
+	if (!strcmp(termtype, "pcbios"))
+#else
+	if (!termtype)
+#endif
+	{
+#if ANY_UNIX
+		write(2, "Environment variable TERM must be set\n", (unsigned)38);
+		exit(1);
+#endif
+#if OSK
+		writeln(2, "Environment variable TERM must be set\n", (unsigned)38);
+		exit(1);
+#endif
+#if AMIGA
+		termtype = TERMTYPE;
+		starttcap(termtype);
+#endif
+#if MSDOS
+		starttcap("pcbios");
+#endif
+#if TOS
+		termtype = "vt52";
+		starttcap(termtype);
+#endif
+#if VMS
+		write(2, "UNKNOWN terminal: define ELVIS_TERM\n", (unsigned)36);
+		exit(1);
+#endif
+	}
+	else
+	{
+#if MSDOS
+		*o_pcbios = 0;
+#endif
+		/* start termcap stuff */
+		starttcap(termtype);
+	}
+
+	/* create stdscr and curscr */
+	stdscr = kbuf;
+
+	/* change the terminal mode to cbreak/noecho */
+#if ANY_UNIX
+	tcgetattr(2, &oldtermio);
+#endif
+
+#if OSK
+	_gs_opt(0, &oldsgttyb);
+#endif
+
+#if VMS
+	VMS_read_raw = 1;   /* cbreak/noecho */
+	vms_open_tty();
+#endif
+	resume_curses(TRUE);
+}
+
+/* Shut down the Curses package. */
+void endwin()
+{
+	/* change the terminal mode back the way it was */
+	suspend_curses();
+#if AMIGA
+	amiclosewin();
+#endif
+}
+
+
+static int curses_active = FALSE;
+
+/* Send any required termination strings.  Turn off "raw" mode. */
+void suspend_curses()
+{
+#ifndef NO_CURSORSHAPE
+	if (has_CQ)
+	{
+		do_CQ();
+	}
+#endif
+	if (has_TE)					/* GB */
+	{
+		do_TE();
+	}
+	if (has_KE)
+	{
+		do_KE();
+	}
+#ifndef NO_COLOR
+	quitcolor();
+#endif
+	refresh();
+
+	/* change the terminal mode back the way it was */
+#if ANY_UNIX
+	tcsetattr(2, TCSADRAIN, &oldtermio);
+#endif
+#if OSK
+	_ss_opt(0, &oldsgttyb);
+#endif
+#if AMIGA
+	ttyshutdown();
+#endif
+#if MSDOS
+	raw_set_stdio(FALSE);
+#endif
+
+#if VMS
+	VMS_read_raw = 0;
+#endif
+	curses_active = FALSE;
+}
+
+
+/* put the terminal in RAW mode.  If "quietly" is FALSE, then ask the user
+ * to hit a key, and wait for keystroke before returning.
+ */
+void resume_curses(quietly)
+	int	quietly;
+{
+	if (!curses_active)
+	{
+		/* change the terminal mode to cbreak/noecho */
+#if ANY_UNIX
+		ospeed = cfgetospeed(&oldtermio);
+		ERASEKEY = oldtermio.c_cc[VERASE];
+		newtermio = oldtermio;
+		newtermio.c_iflag &= (IXON|IXOFF|IXANY|ISTRIP|IGNBRK);
+		newtermio.c_oflag &= ~OPOST;
+		newtermio.c_lflag &= ISIG;
+		newtermio.c_cc[VINTR] = ctrl('C'); /* always use ^C for interrupts */
+		newtermio.c_cc[VMIN] = 1;
+		newtermio.c_cc[VTIME] = 0;
+		newtermio.c_cc[VSUSP] = 0;
+		tcsetattr(2, TCSADRAIN, &newtermio);
+#endif
+#if OSK
+		newsgttyb = oldsgttyb;
+		newsgttyb.sg_echo = 0;
+		newsgttyb.sg_eofch = 0;
+		newsgttyb.sg_kbach = 0;
+		newsgttyb.sg_kbich = ctrl('C');
+		_ss_opt(0, &newsgttyb);
+		ospeed = oldsgttyb.sg_baud;
+		ERASEKEY = oldsgttyb.sg_bspch;
+#endif
+#if AMIGA
+		/* turn on window resize and RAW */
+		ttysetup();
+#endif
+#if MSDOS
+		raw_set_stdio(TRUE);
+#endif
+
+#if VMS
+		VMS_read_raw = 1;
+		{ int c;
+			read(0,&c,0);   /* Flush the tty buffer. */
+		}
+		ERASEKEY = '\177';  /* Accept <DEL> as <^H> for VMS */
+#endif
+
+		if (has_TI)					/* GB */
+		{
+			do_TI();
+		}
+		if (has_KS)
+		{
+			do_KS();
+		}
+
+		curses_active = TRUE;
+	}
+
+	/* If we're supposed to quit quietly, then we're done */
+	if (quietly)
+	{
+		return;
+	}
+
+	signal(SIGINT, SIG_IGN);
+
+	move(LINES - 1, 0);
+	do_SO();
+#if VMS
+	qaddstr("\n[Press <RETURN> to continue]");
+#else
+	qaddstr("[Press <RETURN> to continue]");
+#endif
+	do_SE();
+	refresh();
+	ttyread(kbuf, 20, 0); /* in RAW mode, so <20 is very likely */
+	if (kbuf[0] == ':')
+	{
+		mode = MODE_COLON;
+		addch('\n');
+		refresh();
+	}
+	else
+	{
+		mode = MODE_VI;
+		redraw(MARK_UNSET, FALSE);
+	}	
+	exwrote = FALSE;
+
+#if TURBOC || __GNUC__ || _ANSI
+	signal(SIGINT, (void(*)()) trapint);
+#else
+	signal(SIGINT, trapint);
+#endif
+}
+
+/* This function fetches an optional string from termcap */
+static void mayhave(T, s)
+	char	**T;	/* where to store the returned pointer */
+	char	*s;	/* name of the capability */
+{
+	char	*val;
+
+	val = tgetstr(s, &capbuf);
+	if (val)
+	{
+		*T = val;
+	}
+}
+
+
+/* This function fetches a required string from termcap */
+static void musthave(T, s)
+	char	**T;	/* where to store the returned pointer */
+	char	*s;	/* name of the capability */
+{
+	mayhave(T, s);
+	if (!*T)
+	{
+		write(2, "This termcap entry lacks the :", (unsigned)30);
+		write(2, s, (unsigned)2);
+		write(2, "=: capability\n", (unsigned)14);
+#if OSK
+		write(2, "\l", 1);
+#endif
+		exit(1);
+	}
+}
+
+
+/* This function fetches a pair of strings from termcap.  If one of them is
+ * missing, then the other one is ignored.
+ */
+static void pair(T, U, sT, sU)
+	char	**T;	/* where to store the first pointer */
+	char	**U;	/* where to store the second pointer */
+	char	*sT;	/* name of the first capability */
+	char	*sU;	/* name of the second capability */
+{
+	mayhave(T, sT);
+	mayhave(U, sU);
+	if (!**T || !**U)
+	{
+		*T = *U = "";
+	}
+}
+
+
+
+/* Read everything from termcap */
+static void starttcap(term)
+	char	*term;
+{
+	static char	cbmem[800];
+
+	/* allocate memory for capbuf */
+	capbuf = cbmem;
+
+	/* get the termcap entry */
+	switch (tgetent(kbuf, term))
+	{
+	  case -1:
+		write(2, "Can't read /etc/termcap\n", (unsigned)24);
+#if OSK
+		write(2, "\l", 1);
+#endif
+		exit(2);
+
+	  case 0:
+		write(2, "Unrecognized TERM type\n", (unsigned)23);
+#if OSK
+		write(2, "\l", 1);
+#endif
+		exit(3);
+	}
+
+	/* get strings */
+	musthave(&UP, "up");
+	mayhave(&VB, "vb");
+	musthave(&CM, "cm");
+	pair(&SO, &SE, "so", "se");
+	mayhave(&TI, "ti");
+	mayhave(&TE, "te");
+	if (tgetnum("ug") <= 0)
+	{
+		pair(&US, &UE, "us", "ue");
+		pair(&MD, &ME, "md", "me");
+
+		/* get italics, or have it default to underline */
+		pair(&AS, &AE, "as", "ae");
+		if (!*AS)
+		{
+			AS = US;
+			AE = UE;
+		}
+	}
+#ifndef NO_VISIBLE
+	MV = SO; /* by default */
+	mayhave(&MV, "mv");
+#endif
+	mayhave(&AL, "al");
+	mayhave(&DL, "dl");
+	musthave(&CE, "ce");
+	mayhave(&CD, "cd");
+#if OSK
+	mayhave(&SR_, "sr");
+#else	
+	mayhave(&SR, "sr");
+#endif
+	pair(&IM, &EI, "im", "ei");
+	mayhave(&IC, "ic");
+	mayhave(&DC, "dc");
+
+	/* other termcap stuff */
+	AM = (tgetflag("am") && !tgetflag("xn"));
+	PT = tgetflag("pt");
+#if AMIGA
+	amiopenwin(termtype);	/* Must run this before ttysetup(); */
+	ttysetup();	/* Must run this before getsize(0); */
+#endif
+	getsize(0);
+
+	/* Key sequences */
+	pair(&KS, &KE, "ks", "ke");
+	mayhave(&KU, "ku");		/* up */
+	mayhave(&KD, "kd");		/* down */
+	mayhave(&KL, "kl");		/* left */
+	mayhave(&KR, "kr");		/* right */
+	mayhave(&PU, "kP");		/* PgUp */
+	mayhave(&PD, "kN");		/* PgDn */
+	mayhave(&HM, "kh");		/* Home */
+	mayhave(&EN, "kH");		/* End */
+	mayhave(&KI, "kI");		/* Insert */
+#ifndef CRUNCH
+	if (!PU) mayhave(&PU, "K2");	/* "3x3 pad" names for PgUp, etc. */
+	if (!PD) mayhave(&PD, "K5");
+	if (!HM) mayhave(&HM, "K1");
+	if (!EN) mayhave(&EN, "K4");
+
+	mayhave(&PU, "PU");		/* old XENIX names for PgUp, etc. */
+	mayhave(&PD, "PD");		/* (overrides others, if used.) */
+	mayhave(&HM, "HM");
+	mayhave(&EN, "EN");
+#endif
+#ifndef NO_FKEY
+	mayhave(&FKEY[0], "k0");		/* function key codes */
+	mayhave(&FKEY[1], "k1");
+	mayhave(&FKEY[2], "k2");
+	mayhave(&FKEY[3], "k3");
+	mayhave(&FKEY[4], "k4");
+	mayhave(&FKEY[5], "k5");
+	mayhave(&FKEY[6], "k6");
+	mayhave(&FKEY[7], "k7");
+	mayhave(&FKEY[8], "k8");
+	mayhave(&FKEY[9], "k9");
+# ifndef NO_SHIFT_FKEY
+	mayhave(&FKEY[10], "s0");		/* shift function key codes */
+	mayhave(&FKEY[11], "s1");
+	mayhave(&FKEY[12], "s2");
+	mayhave(&FKEY[13], "s3");
+	mayhave(&FKEY[14], "s4");
+	mayhave(&FKEY[15], "s5");
+	mayhave(&FKEY[16], "s6");
+	mayhave(&FKEY[17], "s7");
+	mayhave(&FKEY[18], "s8");
+	mayhave(&FKEY[19], "s9");
+#  ifndef NO_CTRL_FKEY
+	mayhave(&FKEY[20], "c0");		/* control function key codes */
+	mayhave(&FKEY[21], "c1");
+	mayhave(&FKEY[22], "c2");
+	mayhave(&FKEY[23], "c3");
+	mayhave(&FKEY[24], "c4");
+	mayhave(&FKEY[25], "c5");
+	mayhave(&FKEY[26], "c6");
+	mayhave(&FKEY[27], "c7");
+	mayhave(&FKEY[28], "c8");
+	mayhave(&FKEY[29], "c9");
+#   ifndef NO_ALT_FKEY
+	mayhave(&FKEY[30], "a0");		/* alt function key codes */
+	mayhave(&FKEY[31], "a1");
+	mayhave(&FKEY[32], "a2");
+	mayhave(&FKEY[33], "a3");
+	mayhave(&FKEY[34], "a4");
+	mayhave(&FKEY[35], "a5");
+	mayhave(&FKEY[36], "a6");
+	mayhave(&FKEY[37], "a7");
+	mayhave(&FKEY[38], "a8");
+	mayhave(&FKEY[39], "a9");
+#   endif
+#  endif
+# endif
+#endif
+
+#ifndef NO_CURSORSHAPE
+	/* cursor shapes */
+	CQ = tgetstr("cQ", &capbuf);
+	if (has_CQ)
+	{
+		CX = tgetstr("cX", &capbuf);
+		if (!CX) CX = CQ;
+		CV = tgetstr("cV", &capbuf);
+		if (!CV) CV = CQ;
+		CI = tgetstr("cI", &capbuf);
+		if (!CI) CI = CQ;
+		CR = tgetstr("cR", &capbuf);
+		if (!CR) CR = CQ;
+	}
+# ifndef CRUNCH
+	else
+	{
+		CQ = CV = "";
+		pair(&CQ, &CV, "ve", "vs");
+		CX = CI = CR = CQ;
+	}
+# endif /* !CRUNCH */
+#endif /* !NO_CURSORSHAPE */
+
+#ifndef NO_COLOR
+	strcpy(SOcolor, SO);
+	strcpy(SEcolor, SE);
+	strcpy(AScolor, AS);
+	strcpy(AEcolor, AE);
+	strcpy(MDcolor, MD);
+	strcpy(MEcolor, ME);
+	strcpy(UScolor, US);
+	strcpy(UEcolor, UE);
+# ifndef NO_POPUP
+	strcpy(POPUPcolor, SO);
+# endif
+# ifndef NO_VISIBLE
+	strcpy(VISIBLEcolor, MV);
+# endif
+#endif
+
+}
+
+
+/* This function gets the window size.  It uses the TIOCGWINSZ ioctl call if
+ * your system has it, or tgetnum("li") and tgetnum("co") if it doesn't.
+ * This function is called once during initialization, and thereafter it is
+ * called whenever the SIGWINCH signal is sent to this process.
+ */
+int getsize(signo)
+	int	signo;
+{
+	int	lines;
+	int	cols;
+#ifdef TIOCGWINSZ
+	struct winsize size;
+#endif
+
+#ifdef SIGWINCH
+	/* reset the signal vector */
+	signal(SIGWINCH, getsize);
+#endif
+
+	/* get the window size, one way or another. */
+	lines = cols = 0;
+#ifdef TIOCGWINSZ
+	if (ioctl(2, TIOCGWINSZ, &size) >= 0)
+	{
+		lines = size.ws_row;
+		cols = size.ws_col;
+	}
+#endif
+#if AMIGA
+	/* Amiga gets window size by asking the console.device */
+	if (!strcmp(TERMTYPE, termtype))
+	{
+	    auto long len;
+	    auto char buf[30];
+	    
+	    Write(Output(), "\2330 q", 4); /* Ask the console.device */
+	    len = Read(Input(), buf, 29);
+	    buf[len] = '\000';
+	    sscanf(&buf[5], "%d;%d", &lines, &cols);
+	}
+#endif
+	if ((lines == 0 || cols == 0) && signo == 0)
+	{
+		LINES = tgetnum("li");
+		COLS = tgetnum("co");
+	}
+#if MSDOS
+# ifdef RAINBOW
+	if (!strcmp(termtype, "rainbow"))
+	{
+		/* Determine whether Rainbow is in 80-column or 132-column mode */
+		cols = *(unsigned char far *)0xee000f57L;
+	}
+	else
+# endif
+	{
+		lines = v_rows();
+		cols = v_cols();
+	}
+#endif
+	if (lines >= 2)
+	{
+		LINES = lines;
+	}
+
+	if (cols >= 30)
+	{
+		COLS = cols;
+	}
+
+	/* Make sure we got values that we can live with */
+	if (LINES < 2 || COLS < 30)
+	{
+		write(2, "Screen too small\n", (unsigned)17);
+#if OSK
+		write(2, "\l", 1);
+#endif
+		endwin();
+		exit(2);
+	}
+
+#if AMIGA
+	if (*o_lines != LINES || *o_columns != COLS)
+	{
+		*o_lines = LINES;
+		*o_columns = COLS;
+	}
+#endif
+
+	return 0;
+}
+
+
+/* This is a function version of addch() -- it is used by tputs() */
+int faddch(ch)
+	int	ch;
+{
+	addch(ch);
+
+	return 0;
+}
+
+/* This function quickly adds a string to the output queue.  It does *NOT*
+ * convert \n into <CR><LF>.
+ */
+void qaddstr(str)
+	char	*str;
+{
+	REG char *s_, *d_;
+
+#if MSDOS
+	if (o_pcbios[0])
+	{
+		while (*str)
+			qaddch(*str++);
+		return;
+	}
+#endif
+	for (s_=(str), d_=stdscr; *d_++ = *s_++; )
+	{
+	}
+	stdscr = d_ - 1;
+}
+
+/* Output the ESC sequence needed to go into any video mode, if supported */
+void attrset(a)
+	int	a;
+{
+	do_aend();
+	if (a == A_BOLD)
+	{
+		do_MD();
+		aend = ME;
+	}
+	else if (a == A_UNDERLINE)
+	{
+		do_US();
+		aend = UE;
+	}
+	else if (a == A_ALTCHARSET)
+	{
+		do_AS();
+		aend = AE;
+	}
+	else
+	{
+		aend = "";
+	}
+}
+
+
+/* Insert a single character into the display */
+void insch(ch)
+	int	ch;
+{
+	if (has_IM)
+		do_IM();
+	do_IC();
+	qaddch(ch);
+	if (has_EI)
+		do_EI();
+}
+
+void wrefresh()
+{
+	if (stdscr != kbuf)
+	{
+		VOIDBIOS(;,ttywrite(kbuf, (unsigned)(stdscr - kbuf)));
+		stdscr = kbuf;
+	}
+}
+
+void wqrefresh()
+{
+	if (stdscr - kbuf > 2000)
+	{
+		VOIDBIOS(stdscr = kbuf,
+		{
+			ttywrite(kbuf, (unsigned)(stdscr - kbuf)); 
+			stdscr = kbuf;
+		});
+	}
+}
+
+#ifndef NO_COLOR
+/* This function is called during termination.  It resets color modes */
+int ansiquit()
+{
+	/* if ANSI color terminal, then reset the colors */
+	if (!strcmp(UP, "\033[A"))
+	{
+		tputs("\033[37;40m\033[m", 1, faddch);
+		clrtoeol();
+		return 1;
+	}
+	return 0;
+}
+
+/* This sets the color strings that work for ANSI terminals.  If the TERMCAP
+ * doesn't look like an ANSI terminal, then it returns FALSE.  If the colors
+ * aren't understood, it also returns FALSE.  If all goes well, it returns TRUE
+ */
+int ansicolor(cmode, attrbyte)
+	int	cmode;		/* mode to set, e.g. A_NORMAL */
+	int	attrbyte;	/* IBM PC attribute byte */
+{
+	char	temp[16];	/* hold the new mode string */
+
+	/* if not ANSI-ish, then fail */
+	if (strcmp(UP, "\033[A") && strcmp(UP, "\033OA"))
+	{
+		msg("Don't know how to set colors for this terminal");
+		return 0;
+	}
+
+	/* construct the color string */
+	sprintf(temp, "\033[m\033[3%c;4%c%s%sm",
+		"04261537"[attrbyte & 0x07],
+		"04261537"[(attrbyte >> 4) & 0x07],
+		(attrbyte & 0x08) ? ";1" : "",
+		(attrbyte & 0x80) ? ";5" : "");
+
+	/* stick it in the right place */
+	switch (cmode)
+	{
+	  case A_NORMAL:
+		if (!strcmp(MEcolor, normalcolor))
+			strcpy(MEcolor, temp);
+		if (!strcmp(UEcolor, normalcolor))
+			strcpy(UEcolor, temp);
+		if (!strcmp(AEcolor, normalcolor))
+			strcpy(AEcolor, temp);
+		if (!strcmp(SEcolor, normalcolor))
+			strcpy(SEcolor, temp);
+
+		strcpy(normalcolor, temp);
+		tputs(normalcolor, 1, faddch);
+		break;
+
+	  case A_BOLD:
+		strcpy(MDcolor, temp);
+		strcpy(MEcolor, normalcolor);
+		break;
+
+	  case A_UNDERLINE:
+		strcpy(UScolor, temp);
+		strcpy(UEcolor, normalcolor);
+		break;
+
+	  case A_ALTCHARSET:
+		strcpy(AScolor, temp);
+		strcpy(AEcolor, normalcolor);
+		break;
+
+	  case A_STANDOUT:
+		strcpy(SOcolor, temp);
+		strcpy(SEcolor, normalcolor);
+		break;
+
+#ifndef NO_POPUP
+	  case A_POPUP:
+		strcpy(POPUPcolor, temp);
+		break;
+#endif
+
+#ifndef NO_VISIBLE
+	  case A_VISIBLE:
+		strcpy(VISIBLEcolor, temp);
+		break;
+#endif
+	}
+
+	return 1;
+}
+
+
+/* This function outputs the ESC sequence needed to switch the screen back
+ * to "normal" mode.  On color terminals which haven't had their color set
+ * yet, this is one of the termcap strings; for color terminals that really
+ * have had colors defined, we just the "normal color" escape sequence.
+ */
+endcolor()
+{
+	if (aend == ME)
+		tputs(MEcolor, 1, faddch);
+	else if (aend == UE)
+		tputs(UEcolor, 1, faddch);
+	else if (aend == AE)
+		tputs(AEcolor, 1, faddch);
+	else if (aend == SE)
+		tputs(SEcolor, 1, faddch);
+	aend = "";
+	return 0;
+}
+
+
+#endif /* !NO_COLOR */
Index: /trunk/minix/commands/elvis/curses.h
===================================================================
--- /trunk/minix/commands/elvis/curses.h	(revision 9)
+++ /trunk/minix/commands/elvis/curses.h	(revision 9)
@@ -0,0 +1,319 @@
+/* curses.h */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This is the header file for a small, fast, fake curses package */
+
+/* termcap stuff */
+extern char	*tgoto();
+extern char	*tgetstr();
+extern void	tputs();
+
+#if MSDOS
+/* BIOS interface used instead of termcap for MS-DOS */
+extern int	vmode;
+extern void	v_up();
+extern void	v_cb();
+extern void	v_cs();
+extern void	v_ce();
+extern void	v_cl();
+extern void	v_cd();
+extern void	v_al();
+extern void	v_dl();
+extern void	v_sr();
+extern void	v_move();
+#endif
+
+/* faddch() is a function.  a pointer to it is passed to tputs() */
+extern int	faddch();
+
+/* data types */
+#define WINDOW	char
+
+/* CONSTANTS & SYMBOLS */
+#define TRUE		1
+#define FALSE		0
+#define A_NORMAL	0
+#define A_STANDOUT	1
+#define A_BOLD		2
+#define A_UNDERLINE	3
+#define A_ALTCHARSET	4
+#define A_POPUP		5
+#define A_VISIBLE	6
+#define KBSIZ		4096
+
+/* figure out how many function keys we need to allow. */
+#ifndef NO_FKEY
+# ifdef NO_SHIFT_FKEY
+#  define	NFKEYS	10
+# else
+#  ifdef NO_CTRL_FKEY
+#   define	NFKEYS	20
+#  else
+#   ifdef NO_ALT_FKEY
+#    define	NFKEYS	30
+#   else
+#    define	NFKEYS	40
+#   endif
+#  endif
+# endif
+extern char	*FKEY[NFKEYS];	/* :k0=:...:k9=: codes sent by function keys */
+#endif
+
+/* extern variables, defined in curses.c */
+extern char	*termtype;	/* name of terminal entry */
+extern short	ospeed;		/* tty speed, eg B2400 */
+#if OSK
+extern char PC_;	/* Pad char */
+extern char	*BC;	/* Backspace char string */
+#else
+extern char	PC;		/* Pad char */
+#endif
+extern WINDOW	*stdscr;	/* pointer into kbuf[] */
+extern WINDOW	kbuf[KBSIZ];	/* a very large output buffer */
+extern int	LINES;		/* :li#: number of rows */
+extern int	COLS;		/* :co#: number of columns */
+extern int	AM;		/* :am:  boolean: auto margins? */
+extern int	PT;		/* :pt:  boolean: physical tabs? */
+extern char	*VB;		/* :vb=: visible bell */
+extern char	*UP;		/* :up=: move cursor up */
+extern char	*SO;		/* :so=: standout start */
+extern char	*SE;		/* :se=: standout end */
+extern char	*US;		/* :us=: underline start */
+extern char	*UE;		/* :ue=: underline end */
+extern char	*MD;		/* :md=: bold start */
+extern char	*ME;		/* :me=: bold end */
+extern char	*AS;		/* :as=: alternate (italic) start */
+extern char	*AE;		/* :ae=: alternate (italic) end */
+#ifndef NO_VISIBLE
+extern char	*MV;		/* :mv=: "visible" selection start */
+#endif
+extern char	*CM;		/* :cm=: cursor movement */
+extern char	*CE;		/* :ce=: clear to end of line */
+extern char	*CD;		/* :cd=: clear to end of screen */
+extern char	*AL;		/* :al=: add a line */
+extern char	*DL;		/* :dl=: delete a line */
+#if OSK
+extern char	*SR_;		/* :sr=: scroll reverse */
+#else
+extern char	*SR;		/* :sr=: scroll reverse */
+#endif
+extern char	*KS;		/* :ks=: init string for cursor */
+extern char	*KE;		/* :ke=: restore string for cursor */
+extern char	*KU;		/* :ku=: sequence sent by up key */
+extern char	*KD;		/* :kd=: sequence sent by down key */
+extern char	*KL;		/* :kl=: sequence sent by left key */
+extern char	*KR;		/* :kr=: sequence sent by right key */
+extern char	*PU;		/* :PU=: key sequence sent by PgUp key */
+extern char	*PD;		/* :PD=: key sequence sent by PgDn key */
+extern char	*HM;		/* :HM=: key sequence sent by Home key */
+extern char	*EN;		/* :EN=: key sequence sent by End key */
+extern char	*KI;		/* :kI=: key sequence sent by Insert key */
+extern char	*IM;		/* :im=: insert mode start */
+extern char	*IC;		/* :ic=: insert following char */
+extern char	*EI;		/* :ei=: insert mode end */
+extern char	*DC;		/* :dc=: delete a character */
+extern char	*TI;		/* :ti=: terminal init */	/* GB */
+extern char	*TE;		/* :te=: terminal exit */	/* GB */
+#ifndef NO_CURSORSHAPE
+extern char	*CQ;		/* :cQ=: normal cursor */
+extern char	*CX;		/* :cX=: cursor used for EX command/entry */
+extern char	*CV;		/* :cV=: cursor used for VI command mode */
+extern char	*CI;		/* :cI=: cursor used for VI input mode */
+extern char	*CR;		/* :cR=: cursor used for VI replace mode */
+#endif
+extern char	*aend;		/* end an attribute -- either UE or ME */
+extern char	ERASEKEY;	/* taken from the ioctl structure */
+#ifndef NO_COLOR
+extern char	SOcolor[];
+extern char	SEcolor[];
+extern char	UScolor[];
+extern char	UEcolor[];
+extern char	MDcolor[];
+extern char	MEcolor[];
+extern char	AScolor[];
+extern char	AEcolor[];
+# ifndef NO_POPUP
+extern char	POPUPcolor[];
+# endif
+# ifndef NO_VISIBLE
+extern char	VISIBLEcolor[];
+# endif
+extern char	normalcolor[];
+#endif /* undef NO_COLOR */
+
+/* Msdos-versions may use bios; others always termcap.
+ * Will emit some 'code has no effect' warnings in unix.
+ */
+ 
+#if MSDOS
+extern char o_pcbios[1];		/* BAH! */
+#define	CHECKBIOS(x,y)	(*o_pcbios ? (x) : (y))
+#define VOIDBIOS(x,y)	{if (*o_pcbios) {x;} else {y;}}
+#else
+#define	CHECKBIOS(x,y)	(y)
+#define VOIDBIOS(x,y)	{y;}
+#endif
+
+#ifndef NO_COLOR
+# define setcolor(m,a)	CHECKBIOS(bioscolor(m,a), ansicolor(m,a))
+# define fixcolor()	VOIDBIOS(;, tputs(normalcolor, 1, faddch))
+# define quitcolor()	CHECKBIOS(biosquit(), ansiquit())
+# define do_SO()	VOIDBIOS((vmode=A_STANDOUT), tputs(SOcolor, 1, faddch))
+# define do_SE()	VOIDBIOS((vmode=A_NORMAL), tputs(SEcolor, 1, faddch))
+# define do_US()	VOIDBIOS((vmode=A_UNDERLINE), tputs(UScolor, 1, faddch))
+# define do_UE()	VOIDBIOS((vmode=A_NORMAL), tputs(UEcolor, 1, faddch))
+# define do_MD()	VOIDBIOS((vmode=A_BOLD), tputs(MDcolor, 1, faddch))
+# define do_ME()	VOIDBIOS((vmode=A_NORMAL), tputs(MEcolor, 1, faddch))
+# define do_AS()	VOIDBIOS((vmode=A_ALTCHARSET), tputs(AScolor, 1, faddch))
+# define do_AE()	VOIDBIOS((vmode=A_NORMAL), tputs(AEcolor, 1, faddch))
+# define do_POPUP()	VOIDBIOS((vmode=A_POPUP), tputs(POPUPcolor, 1, faddch))
+# define do_VISIBLE()	VOIDBIOS((vmode=A_VISIBLE), tputs(VISIBLEcolor, 1, faddch))
+#else
+# define do_SO()	VOIDBIOS((vmode=A_STANDOUT), tputs(SO, 1, faddch))
+# define do_SE()	VOIDBIOS((vmode=A_NORMAL), tputs(SE, 1, faddch))
+# define do_US()	VOIDBIOS((vmode=A_UNDERLINE), tputs(US, 1, faddch))
+# define do_UE()	VOIDBIOS((vmode=A_NORMAL), tputs(UE, 1, faddch))
+# define do_MD()	VOIDBIOS((vmode=A_BOLD), tputs(MD, 1, faddch))
+# define do_ME()	VOIDBIOS((vmode=A_NORMAL), tputs(ME, 1, faddch))
+# define do_AS()	VOIDBIOS((vmode=A_ALTCHARSET), tputs(AS, 1, faddch))
+# define do_AE()	VOIDBIOS((vmode=A_NORMAL), tputs(AE, 1, faddch))
+# define do_POPUP()	VOIDBIOS((vmode=A_POPUP), tputs(SO, 1, faddch))
+# define do_VISIBLE()	VOIDBIOS((vmode=A_VISIBLE), tputs(MV, 1, faddch))
+#endif
+
+#define	do_VB()		VOIDBIOS(;, tputs(VB, 1, faddch))
+#define	do_UP()		VOIDBIOS(v_up(), tputs(UP, 1, faddch))
+#undef	do_CM		/* move */
+#define	do_CE()		VOIDBIOS(v_ce(), tputs(CE, 1, faddch))
+#define	do_CD()		VOIDBIOS(v_cd(), tputs(CD, 1, faddch))
+#define	do_AL()		VOIDBIOS(v_al(), tputs(AL, LINES, faddch))
+#define	do_DL()		VOIDBIOS(v_dl(), tputs(DL, LINES, faddch))
+#if OSK
+#define	do_SR()		VOIDBIOS(v_sr(), tputs(SR_, 1, faddch))
+#else
+#define	do_SR()		VOIDBIOS(v_sr(), tputs(SR, 1, faddch))
+#endif
+#define do_KS()		VOIDBIOS(1, tputs(KS, 1, faddch))
+#define do_KE()		VOIDBIOS(1, tputs(KE, 1, faddch))
+#define	do_IM()		VOIDBIOS(;, tputs(IM, 1, faddch))
+#define	do_IC()		VOIDBIOS(;, tputs(IC, 1, faddch))
+#define	do_EI()		VOIDBIOS(;, tputs(EI, 1, faddch))
+#define	do_DC()		VOIDBIOS(;, tputs(DC, COLS, faddch))
+#define	do_TI()		VOIDBIOS(;, (void)ttywrite(TI, (unsigned)strlen(TI)))
+#define	do_TE()		VOIDBIOS(;, (void)ttywrite(TE, (unsigned)strlen(TE)))
+#ifndef NO_CURSORSHAPE
+# define do_CQ()	VOIDBIOS(v_cs(), tputs(CQ, 1, faddch))
+# define do_CX()	VOIDBIOS(v_cs(), tputs(CX, 1, faddch))
+# define do_CV()	VOIDBIOS(v_cs(), tputs(CV, 1, faddch))
+# define do_CI()	VOIDBIOS(v_cb(), tputs(CI, 1, faddch))
+# define do_CR()	VOIDBIOS(v_cb(), tputs(CR, 1, faddch))
+#endif
+#ifndef NO_COLOR
+# define do_aend()	VOIDBIOS((vmode=A_NORMAL), endcolor())
+#else
+# define do_aend()	VOIDBIOS((vmode=A_NORMAL), tputs(aend, 1, faddch))
+#endif
+
+#define	has_AM		CHECKBIOS(1, AM)
+#define	has_PT		CHECKBIOS(0, PT)
+#define	has_VB		CHECKBIOS((char *)0, VB)
+#define	has_UP		CHECKBIOS((char *)1, UP)
+#define	has_SO		CHECKBIOS((char)1, (*SO))
+#define	has_SE		CHECKBIOS((char)1, (*SE))
+#define	has_US		CHECKBIOS((char)1, (*US))
+#define	has_UE		CHECKBIOS((char)1, (*UE))
+#define	has_MD		CHECKBIOS((char)1, (*MD))
+#define	has_ME		CHECKBIOS((char)1, (*ME))
+#define	has_AS		CHECKBIOS((char)1, (*AS))
+#define	has_AE		CHECKBIOS((char)1, (*AE))
+#undef	has_CM		/* cursor move: don't need */
+#define	has_CB		CHECKBIOS(1, 0)
+#define	has_CS		CHECKBIOS(1, 0)
+#define	has_CE		CHECKBIOS((char *)1, CE)
+#define	has_CD		CHECKBIOS((char *)1, CD)
+#define	has_AL		CHECKBIOS((char *)1, AL)
+#define	has_DL		CHECKBIOS((char *)1, DL)
+#if OSK
+#define	has_SR		CHECKBIOS((char *)1, SR_)
+#else
+#define	has_SR		CHECKBIOS((char *)1, SR)
+#endif
+#define has_KS		CHECKBIOS((char)1, (*KS))
+#define has_KE		CHECKBIOS((char)1, (*KE))
+#define	has_KU		KU
+#define	has_KD		KD
+#define	has_KL		KL
+#define	has_KR		KR
+#define has_HM		HM
+#define has_EN		EN
+#define has_PU		PU
+#define has_PD		PD
+#define has_KI		KI
+#define	has_IM		CHECKBIOS((char)0, (*IM))
+#define	has_IC		CHECKBIOS((char)0, (*IC))
+#define	has_EI		CHECKBIOS((char)0, (*EI))
+#define	has_DC		CHECKBIOS((char *)0, DC)
+#define	has_TI		CHECKBIOS((char)0, (*TI))
+#define	has_TE		CHECKBIOS((char)0, (*TE))
+#ifndef NO_CURSORSHAPE
+#define has_CQ		CHECKBIOS((char *)1, CQ)
+#endif
+
+/* (pseudo)-Curses-functions */
+
+#ifdef lint
+# define _addCR		VOIDBIOS(;, (stdscr[-1] == '\n' ? qaddch('\r') : (stdscr[-1] = '\n')))
+#else
+# if OSK
+#  define _addCR	VOIDBIOS(;, (stdscr[-1] == '\n' ? qaddch('\l') : (stdscr[-1] = stdscr[-1])))
+# else
+#  define _addCR	VOIDBIOS(;, (stdscr[-1] == '\n' ? qaddch('\r') : 0))
+# endif
+#endif
+
+#ifdef AZTEC_C
+# define qaddch(ch)	CHECKBIOS(v_put(ch), (*stdscr = (ch), *stdscr++))
+#else
+#define qaddch(ch)	CHECKBIOS(v_put(ch), (*stdscr++ = (ch)))
+#endif
+
+#if OSK
+#define addch(ch)	if (qaddch(ch) == '\n') qaddch('\l'); else
+#else
+#define addch(ch)	if (qaddch(ch) == '\n') qaddch('\r'); else
+#endif
+
+extern void initscr();
+extern void endwin();
+extern void suspend_curses();
+extern void resume_curses();
+extern void attrset();
+extern void insch();
+extern void qaddstr();
+extern void wrefresh();
+extern void wqrefresh();
+#define addstr(str)	{qaddstr(str); _addCR;}
+#define move(y,x)	VOIDBIOS(v_move(x,y), tputs(tgoto(CM, x, y), 1, faddch))
+#define mvaddch(y,x,ch)	{move(y,x); addch(ch);}
+#define refresh()	VOIDBIOS(;, wrefresh())
+#define standout()	do_SO()
+#define standend()	do_SE()
+#define clrtoeol()	do_CE()
+#define clrtobot()	do_CD()
+#define insertln()	do_AL()
+#define deleteln()	do_DL()
+#define delch()		do_DC()
+#define scrollok(w,b)
+#define raw()
+#define echo()
+#define cbreak()
+#define noraw()
+#define noecho()
+#define nocbreak()
Index: /trunk/minix/commands/elvis/cut.c
===================================================================
--- /trunk/minix/commands/elvis/cut.c	(revision 9)
+++ /trunk/minix/commands/elvis/cut.c	(revision 9)
@@ -0,0 +1,700 @@
+/* cut.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains function which manipulate the cut buffers. */
+
+#include "config.h"
+#include "vi.h"
+#if TURBOC
+#include <process.h>		/* needed for getpid */
+#endif
+#if TOS
+#include <osbind.h>
+#define	rename(a,b)	Frename(0,a,b)
+#endif
+
+# define NANONS	9	/* number of anonymous buffers */
+
+static struct cutbuf
+{
+	short	*phys;	/* pointer to an array of #s of BLKs containing text */
+	int	nblks;	/* number of blocks in phys[] array */
+	int	start;	/* offset into first block of start of cut */
+	int	end;	/* offset into last block of end of cut */
+	int	tmpnum;	/* ID number of the temp file */
+	char	lnmode;	/* boolean: line-mode cut? (as opposed to char-mode) */
+}
+	named[27],	/* cut buffers "a through "z and ". */
+	anon[NANONS];	/* anonymous cut buffers */
+
+static char	cbname;	/* name chosen for next cut/paste operation */
+static char	dotcb;	/* cut buffer to use if "doingdot" is set */
+
+
+#ifndef NO_RECYCLE
+/* This function builds a list of all blocks needed in the current tmp file
+ * for the contents of cut buffers.
+ * !!! WARNING: if you have more than ~450000 bytes of text in all of the
+ * cut buffers, then this will fail disastrously, because buffer overflow
+ * is *not* allowed for.
+ */
+int cutneeds(need)
+	BLK		*need;	/* this is where we deposit the list */
+{
+	struct cutbuf	*cb;	/* used to count through cut buffers */
+	int		i;	/* used to count through blocks of a cut buffer */
+	int		n;	/* total number of blocks in list */
+
+	n = 0;
+
+	/* first the named buffers... */
+	for (cb = named; cb < &named[27]; cb++)
+	{
+		if (cb->tmpnum != tmpnum)
+			continue;
+
+		for (i = cb->nblks; i-- > 0; )
+		{
+			need->n[n++] = cb->phys[i];
+		}
+	}
+
+	/* then the anonymous buffers */
+	for (cb = anon; cb < &anon[NANONS]; cb++)
+	{
+		if (cb->tmpnum != tmpnum)
+			continue;
+
+		for (i = cb->nblks; i-- > 0; )
+		{
+			need->n[n++] = cb->phys[i];
+		}
+	}
+
+	/* return the length of the list */
+	return n;
+}
+#endif
+
+static void maybezap(num)
+	int	num;	/* the tmpnum of the temporary file to [maybe] delete */
+{
+	char	cutfname[80];
+	int	i;
+
+	/* if this is the current tmp file, then we'd better keep it! */
+	if (tmpfd >= 0 && num == tmpnum)
+	{
+		return;
+	}
+
+	/* see if anybody else needs this tmp file */
+	for (i = 27; --i >= 0; )
+	{
+		if (named[i].nblks > 0 && named[i].tmpnum == num)
+		{
+			break;
+		}
+	}
+	if (i < 0)
+	{
+		for (i = NANONS; --i >= 0 ; )
+		{
+			if (anon[i].nblks > 0 && anon[i].tmpnum == num)
+			{
+				break;
+			}
+		}
+	}
+
+	/* if nobody else needs it, then discard the tmp file */
+	if (i < 0)
+	{
+#if MSDOS || TOS
+		strcpy(cutfname, o_directory);
+		if ((i = strlen(cutfname)) && !strchr(":/\\", cutfname[i - 1]))
+			cutfname[i++] = SLASH;
+		sprintf(cutfname + i, TMPNAME + 3, getpid(), num);
+#else
+		sprintf(cutfname, TMPNAME, o_directory, getpid(), num);
+#endif
+		unlink(cutfname);
+	}
+}
+
+/* This function frees a cut buffer.  If it was the last cut buffer that
+ * refered to an old temp file, then it will delete the temp file. */
+static void cutfree(buf)
+	struct cutbuf	*buf;
+{
+	int	num;
+
+	/* return immediately if the buffer is already empty */
+	if (buf->nblks <= 0)
+	{
+		return;
+	}
+
+	/* else free up stuff */
+	num = buf->tmpnum;
+	buf->nblks = 0;
+#ifdef DEBUG
+	if (!buf->phys)
+		msg("cutfree() tried to free a NULL buf->phys pointer.");
+	else
+#endif
+	free((char *)buf->phys);
+
+	/* maybe delete the temp file */
+	maybezap(num);
+}
+
+/* This function is called when we are about to abort a tmp file.
+ *
+ * To minimize the number of extra files lying around, only named cut buffers
+ * are preserved in a file switch; the anonymous buffers just go away.
+ */
+void cutswitch()
+{
+	int	i;
+
+	/* mark the current temp file as being "obsolete", and close it.  */
+	storename((char *)0);
+	close(tmpfd);
+	tmpfd = -1;
+
+	/* discard all anonymous cut buffers */
+	for (i = 0; i < NANONS; i++)
+	{
+		cutfree(&anon[i]);
+	}
+
+	/* delete the temp file, if we don't really need it */
+	maybezap(tmpnum);
+}
+
+/* This function should be called just before termination of vi */
+void cutend()
+{
+	int	i;
+
+	/* free the anonymous buffers, if they aren't already free */
+	cutswitch();
+
+	/* free all named cut buffers, since they might be forcing an older
+	 * tmp file to be retained.
+	 */
+	for (i = 0; i < 27; i++)
+	{
+		cutfree(&named[i]);
+	}
+
+	/* delete the temp file */
+	maybezap(tmpnum);
+}
+
+
+/* This function is used to select the cut buffer to be used next */
+void cutname(name)
+	int	name;	/* a single character */
+{
+	cbname = name;
+}
+
+
+
+
+/* This function copies a selected segment of text to a cut buffer */
+void cut(from, to)
+	MARK	from;		/* start of text to cut */
+	MARK	to;		/* end of text to cut */
+{
+	int		first;	/* logical number of first block in cut */
+	int		last;	/* logical number of last block used in cut */
+	long		line;	/* a line number */
+	int		lnmode;	/* boolean: will this be a line-mode cut? */
+	MARK		delthru;/* end of text temporarily inserted for apnd */
+	REG struct cutbuf *cb;
+	REG long	l;
+	REG int		i;
+	REG char	*scan;
+	char		*blkc;
+
+	/* detect whether this must be a line-mode cut or char-mode cut */
+	if (markidx(from) == 0 && markidx(to) == 0)
+		lnmode = TRUE;
+	else
+		lnmode = FALSE;
+
+	/* by default, we don't "delthru" anything */
+	delthru = MARK_UNSET;
+
+	/* handle the "doingdot" quirks */
+	if (doingdot)
+	{
+		if (!cbname)
+		{
+			cbname = dotcb;
+		}
+	}
+	else if (cbname != '.')
+	{
+		dotcb = cbname;
+	}
+
+	/* decide which cut buffer to use */
+	if (!cbname)
+	{
+		/* free up the last anonymous cut buffer */
+		cutfree(&anon[NANONS - 1]);
+
+		/* shift the anonymous cut buffers */
+		for (i = NANONS - 1; i > 0; i--)
+		{
+			anon[i] = anon[i - 1];
+		}
+
+		/* use the first anonymous cut buffer */
+		cb = anon;
+		cb->nblks = 0;
+	}
+	else if (cbname >= 'a' && cbname <= 'z')
+	{
+		cb = &named[cbname - 'a'];
+		cutfree(cb);
+	}
+#ifndef CRUNCH
+	else if (cbname >= 'A' && cbname <= 'Z')
+	{
+		cb = &named[cbname - 'A'];
+		if (cb->nblks > 0)
+		{
+			/* resolve linemode/charmode differences */
+			if (!lnmode && cb->lnmode)
+			{
+				from &= ~(BLKSIZE - 1);
+				if (markidx(to) != 0 || to == from)
+				{
+					to = to + BLKSIZE - markidx(to);
+				}
+				lnmode = TRUE;
+			}
+
+			/* insert the old cut-buffer before the new text */
+			mark[28] = to;
+			delthru = paste(from, FALSE, TRUE);
+			if (delthru == MARK_UNSET)
+			{
+				return;
+			}
+			delthru++;
+			to = mark[28];
+		}
+		cutfree(cb);
+	}
+#endif /* not CRUNCH */
+	else if (cbname == '.')
+	{
+		cb = &named[26];
+		cutfree(cb);
+	}
+	else
+	{
+		msg("Invalid cut buffer name: \"%c", cbname);
+		dotcb = cbname = '\0';
+		return;
+	}
+	cbname = '\0';
+	cb->tmpnum = tmpnum;
+
+	/* detect whether we're doing a line mode cut */
+	cb->lnmode = lnmode;
+
+	/* ---------- */
+
+	/* Reporting... */	
+	if (markidx(from) == 0 && markidx(to) == 0)
+	{
+		rptlines = markline(to) - markline(from);
+		rptlabel = "yanked";
+	}
+
+	/* ---------- */
+
+	/* make sure each block has a physical disk address */
+	blksync();
+
+	/* find the first block in the cut */
+	line = markline(from);
+	for (first = 1; line > lnum[first]; first++)
+	{
+	}
+
+	/* fetch text of the block containing that line */
+	blkc = scan = blkget(first)->c;
+
+	/* find the mark in the block */
+	for (l = lnum[first - 1]; ++l < line; )
+	{
+		while (*scan++ != '\n')
+		{
+		}
+	}
+	scan += markidx(from);
+
+	/* remember the offset of the start */
+	cb->start = scan - blkc;
+
+	/* ---------- */
+
+	/* find the last block in the cut */
+	line = markline(to);
+	for (last = first; line > lnum[last]; last++)
+	{
+	}
+
+	/* fetch text of the block containing that line */
+	if (last != first)
+	{
+		blkc = scan = blkget(last)->c;
+	}
+	else
+	{
+		scan = blkc;
+	}
+
+	/* find the mark in the block */
+	for (l = lnum[last - 1]; ++l < line; )
+	{
+		while (*scan++ != '\n')
+		{
+		}
+	}
+	if (markline(to) <= nlines)
+	{
+		scan += markidx(to);
+	}
+
+	/* remember the offset of the end */
+	cb->end = scan - blkc;
+
+	/* ------- */
+
+	/* remember the physical block numbers of all included blocks */
+	cb->nblks = last - first;
+	if (cb->end > 0)
+	{
+		cb->nblks++;
+	}
+#ifdef lint
+	cb->phys = (short *)0;
+#else
+	cb->phys = (short *)malloc((unsigned)(cb->nblks * sizeof(short)));
+#endif
+	for (i = 0; i < cb->nblks; i++)
+	{
+		cb->phys[i] = hdr.n[first++];
+	}
+
+#ifndef CRUNCH
+	/* if we temporarily inserted text for appending, then delete that
+	 * text now -- before the user sees it.
+	 */
+	if (delthru)
+	{
+		line = rptlines;
+		delete(from, delthru);
+		rptlines = line;
+		rptlabel = "yanked";
+	}
+#endif /* not CRUNCH */
+}
+
+
+static void readcutblk(cb, blkno)
+	struct cutbuf	*cb;
+	int		blkno;
+{
+	char		cutfname[50];/* name of an old temp file */
+	int		fd;	/* either tmpfd or the result of open() */
+#if MSDOS || TOS
+	int		i;
+#endif
+
+	/* decide which fd to use */
+	if (cb->tmpnum == tmpnum)
+	{
+		fd = tmpfd;
+	}
+	else
+	{
+#if MSDOS || TOS
+		strcpy(cutfname, o_directory);
+		if ((i = strlen(cutfname)) && !strchr(":/\\", cutfname[i-1]))
+			cutfname[i++]=SLASH;
+		sprintf(cutfname+i, TMPNAME+3, getpid(), cb->tmpnum);
+#else
+		sprintf(cutfname, TMPNAME, o_directory, getpid(), cb->tmpnum);
+#endif
+		fd = open(cutfname, O_RDONLY);
+	}
+
+	/* get the block */
+	lseek(fd, (long)cb->phys[blkno] * (long)BLKSIZE, 0);
+	if (read(fd, tmpblk.c, (unsigned)BLKSIZE) != BLKSIZE)
+	{
+		msg("Error reading back from tmp file for pasting!");
+	}
+
+	/* close the fd, if it isn't tmpfd */
+	if (fd != tmpfd)
+	{
+		close(fd);
+	}
+}
+
+
+/* This function inserts text from a cut buffer, and returns the MARK where
+ * insertion ended.  Return MARK_UNSET on errors.
+ */
+MARK paste(at, after, retend)
+	MARK	at;	/* where to insert the text */
+	int	after;	/* boolean: insert after mark? (rather than before) */
+	int	retend;	/* boolean: return end of text? (rather than start) */
+{
+	REG struct cutbuf	*cb;
+	REG int			i;
+
+	/* handle the "doingdot" quirks */
+	if (doingdot)
+	{
+		if (!cbname)
+		{
+			if (dotcb >= '1' && dotcb < '1' + NANONS - 1)
+			{
+				dotcb++;
+			}
+			cbname = dotcb;
+		}
+	}
+	else if (cbname != '.')
+	{
+		dotcb = cbname;
+	}
+
+	/* decide which cut buffer to use */
+	if (cbname >= 'A' && cbname <= 'Z')
+	{
+		cb = &named[cbname - 'A'];
+	}
+	else if (cbname >= 'a' && cbname <= 'z')
+	{
+		cb = &named[cbname - 'a'];
+	}
+	else if (cbname >= '1' && cbname <= '9')
+	{
+		cb = &anon[cbname - '1'];
+	}
+	else if (cbname == '.')
+	{
+		cb = &named[26];
+	}
+	else if (!cbname)
+	{
+		cb = anon;
+	}
+	else
+	{
+		msg("Invalid cut buffer name: \"%c", cbname);
+		cbname = '\0';
+		return MARK_UNSET;
+	}
+
+	/* make sure it isn't empty */
+	if (cb->nblks == 0)
+	{
+		if (cbname)
+			msg("Cut buffer \"%c is empty", cbname);
+		else
+			msg("Cut buffer is empty");
+		cbname = '\0';
+		return MARK_UNSET;
+	}
+	cbname = '\0';
+
+	/* adjust the insertion MARK for "after" and line-mode cuts */
+	if (cb->lnmode)
+	{
+		at &= ~(BLKSIZE - 1);
+		if (after)
+		{
+			at += BLKSIZE;
+		}
+	}
+	else if (after)
+	{
+		/* careful! if markidx(at) == 0 we might be pasting into an
+		 * empty line -- so we can't blindly increment "at".
+		 */
+		if (markidx(at) == 0)
+		{
+			pfetch(markline(at));
+			if (plen != 0)
+			{
+				at++;
+			}
+		}
+		else
+		{
+			at++;
+		}
+	}
+
+	/* put a copy of the "at" mark in the mark[] array, so it stays in
+	 * sync with changes made via add().
+	 */
+	mark[27] = at;
+
+	/* simple one-block paste? */
+	if (cb->nblks == 1)
+	{
+		/* get the block */
+		readcutblk(cb, 0);
+
+		/* isolate the text we need within it */
+		if (cb->end)
+		{
+			tmpblk.c[cb->end] = '\0';
+		}
+
+		/* insert it */
+		ChangeText
+		{
+			add(at, &tmpblk.c[cb->start]);
+		}
+	}
+	else
+	{
+		/* multi-block paste */
+
+		ChangeText
+		{
+			i = cb->nblks - 1;
+
+			/* add text from the last block first */
+			if (cb->end > 0)
+			{
+				readcutblk(cb, i);
+				tmpblk.c[cb->end] = '\0';
+				add(at, tmpblk.c);
+				i--;
+			}
+
+			/* add intervening blocks */
+			while (i > 0)
+			{
+				readcutblk(cb, i);
+				add(at, tmpblk.c);
+				i--;
+			}
+
+			/* add text from the first cut block */
+			readcutblk(cb, 0);
+			add(at, &tmpblk.c[cb->start]);
+		}
+	}
+
+	/* Reporting... */
+	rptlines = markline(mark[27]) - markline(at);
+	rptlabel = "pasted";
+
+	/* return the mark at the beginning/end of inserted text */
+	if (retend)
+	{
+		return mark[27] - 1L;
+	}
+	return at;
+}
+
+
+
+
+#ifndef NO_AT
+
+/* This function copies characters from a cut buffer into a string.
+ * It returns the number of characters in the cut buffer.  If the cut
+ * buffer is too large to fit in the string (i.e. if cb2str() returns
+ * a number >= size) then the characters will not have been copied.
+ * It returns 0 if the cut buffer is empty, and -1 for invalid cut buffers.
+ */
+int cb2str(name, buf, size)
+	int	name;	/* the name of a cut-buffer to get: a-z only! */
+	char	*buf;	/* where to put the string */
+	unsigned size;	/* size of buf */
+{
+	REG struct cutbuf	*cb;
+	REG char		*src;
+	REG char		*dest;
+
+	/* decide which cut buffer to use */
+	if (name >= 'a' && name <= 'z')
+	{
+		cb = &named[name - 'a'];
+	}
+	else
+	{
+		return -1;
+	}
+
+	/* if the buffer is empty, return 0 */
+	if (cb->nblks == 0)
+	{
+		return 0;
+	}
+
+	/* !!! if not a single-block cut, then fail */
+	if (cb->nblks != 1)
+	{
+		return size;
+	}
+
+	/* if too big, return the size now, without doing anything */
+	if (cb->end - cb->start >= size)
+	{
+		return cb->end - cb->start;
+	}
+
+	/* get the block */
+	readcutblk(cb, 0);
+
+	/* isolate the string within that blk */
+	if (cb->start == 0)
+	{
+		tmpblk.c[cb->end] = '\0';
+	}
+	else
+	{
+		for (dest = tmpblk.c, src = dest + cb->start; src < tmpblk.c + cb->end; )
+		{
+			*dest++ = *src++;
+		}
+		*dest = '\0';
+	}
+
+	/* copy the string into the buffer */
+	if (buf != tmpblk.c)
+	{
+		strcpy(buf, tmpblk.c);
+	}
+
+	/* return the length */
+	return cb->end - cb->start;
+}
+#endif
Index: /trunk/minix/commands/elvis/elvprsv.c
===================================================================
--- /trunk/minix/commands/elvis/elvprsv.c	(revision 9)
+++ /trunk/minix/commands/elvis/elvprsv.c	(revision 9)
@@ -0,0 +1,287 @@
+/* elvprsv.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains the portable sources for the "elvprsv" program.
+ * "Elvprsv" is run by Elvis when Elvis is about to die.  It is also
+ * run when the computer boots up.  It is not intended to be run directly
+ * by the user, ever.
+ *
+ * Basically, this program does the following four things:
+ *    - It extracts the text from the temporary file, and places the text in
+ *	a file in the /usr/preserve directory.
+ *    - It adds a line to the /usr/preserve/Index file, describing the file
+ *	that it just preserved.
+ *    - It removes the temporary file.
+ *    -	It sends mail to the owner of the file, saying that the file was
+ *	preserved, and how it can be recovered.
+ *
+ * The /usr/preserve/Index file is a log file that contains one line for each
+ * file that has ever been preserved.  Each line of this file describes one
+ * preserved file.  The first word on the line is the name of the file that
+ * contains the preserved text.  The second word is the full pathname of the
+ * file that was being edited; for anonymous buffers, this is the directory
+ * name plus "/foo".
+ *
+ * If elvprsv's first argument (after the command name) starts with a hyphen,
+ * then the characters after the hyphen are used as a description of when
+ * the editor went away.  This is optional.
+ *
+ * The remaining arguments are all the names of temporary files that are
+ * to be preserved.  For example, on a UNIX system, the /etc/rc file might
+ * invoke it this way:
+ *
+ *	elvprsv "-the system went down" /tmp/elv_*.*
+ *
+ * This file contains only the portable parts of the preserve program.
+ * It must #include a system-specific file.  The system-specific file is
+ * expected to define the following functions:
+ *
+ *	char *ownername(char *filename)	- returns name of person who owns file
+ *
+ *	void mail(char *user, char *name, char *when)
+ *					- tell user that file was preserved
+ */
+
+#include <stdio.h>
+#include "config.h"
+#include "vi.h"
+
+#if AMIGA
+BLK tmpblk;
+#error AMIGA here DEBUG
+# include "amiwild.c"
+# include "amiprsv.c"
+#endif
+
+#if OSK
+# undef sprintf
+#endif
+
+#if ANY_UNIX || OSK
+# include "prsvunix.c"
+#endif
+
+#if MSDOS || TOS
+# include "prsvdos.c"
+# define WILDCARD_NO_MAIN
+# include "wildcard.c"
+#endif
+
+
+BLK	buf;
+BLK	hdr;
+BLK	name;
+int	rewrite_now;	/* boolean: should we send text directly to orig file? */
+
+
+
+/* This function preserves a single file, and announces its success/failure
+ * via an e-mail message.
+ */
+void preserve(tname, when)
+	char	*tname;		/* name of a temp file to be preserved */
+	char	*when;		/* description of when the editor died */
+{
+	int	infd;		/* fd used for reading from the temp file */
+	FILE	*outfp;		/* fp used for writing to the recovery file */
+	FILE	*index;		/* fp used for appending to index file */
+	char	outname[100];	/* the name of the recovery file */
+	char	*user;		/* name of the owner of the temp file */
+#if AMIGA
+	char	*prsvdir;
+#endif
+	int	i;
+
+	/* open the temp file */
+	infd = open(tname, O_RDONLY|O_BINARY);
+	if (infd < 0)
+	{
+		/* if we can't open the file, then we should assume that
+		 * the filename contains wildcard characters that weren't
+		 * expanded... and also assume that they weren't expanded
+		 * because there are no files that need to be preserved.
+		 * THEREFORE... we should silently ignore it.
+		 * (Or loudly ignore it if the user was using -R)
+		 */
+		if (rewrite_now)
+		{
+			perror(tname);
+		}
+		return;
+	}
+
+	/* read the header and name from the file */
+	if (read(infd, hdr.c, BLKSIZE) != BLKSIZE
+	 || read(infd, name.c, BLKSIZE) != BLKSIZE)
+	{
+		/* something wrong with the file - sorry */
+		fprintf(stderr, "%s: trucated header blocks\n", tname);
+		close(infd);
+		return;
+	}
+
+	/* If the filename block contains an empty string, then Elvis was
+	 * only keeping the temp file around because it contained some text
+	 * that was needed for a named cut buffer.  The user doesn't care
+	 * about that kind of temp file, so we should silently delete it.
+	 */
+	if (name.c[0] == '\0' && name.c[1] == '\177')
+	{
+		close(infd);
+		unlink(tname);
+		return;
+	}
+
+	if (rewrite_now)
+	{
+		/* we don't need to open the index file */
+		index = (FILE *)0;
+
+		/* make sure we can read every block! */
+		for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
+		{
+			lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
+			if (read(infd, buf.c, BLKSIZE) != BLKSIZE)
+			{
+				/* messed up header */
+				fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
+				close(infd);
+				return;
+			}
+		}
+
+		/* open the user's file for writing */
+		outfp = fopen(name.c, "w");
+		if (!outfp)
+		{
+			perror(name.c);
+			close(infd);
+			return;
+		}
+	}
+	else
+	{
+		/* open/create the index file */
+		index = fopen(PRSVINDEX, "a");
+		if (!index)
+		{
+			perror(PRSVINDEX);
+			exit(1);
+		}
+
+		/* create the recovery file in the PRESVDIR directory */
+#if AMIGA
+		prsvdir = &PRSVDIR[strlen(PRSVDIR) - 1];
+		if (*prsvdir == '/' || *prsvdir == ':')
+		{
+			sprintf(outname, "%sp%ld", PRSVDIR, ftell(index));
+		}
+		else
+#endif
+		sprintf(outname, "%s%cp%ld", PRSVDIR, SLASH, ftell(index));
+		outfp = fopen(outname, "w");
+		if (!outfp)
+		{
+			perror(outname);
+			close(infd);
+			fclose(index);
+			return;
+		}
+	}
+
+	/* write the text of the file out to the recovery file */
+	for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
+	{
+		lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
+		if (read(infd, buf.c, BLKSIZE) != BLKSIZE)
+		{
+			/* messed up header */
+			fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
+			fclose(outfp);
+			close(infd);
+			if (index)
+			{
+				fclose(index);
+			}
+			unlink(outname);
+			return;
+		}
+		fputs(buf.c, outfp);
+	}
+
+	/* add a line to the index file */
+	if (index)
+	{
+		fprintf(index, "%s %s\n", outname, name.c);
+	}
+
+	/* close everything */
+	close(infd);
+	fclose(outfp);
+	if (index)
+	{
+		fclose(index);
+	}
+
+	/* Are we doing this due to something more frightening than just
+	 * a ":preserve" command?
+	 */
+	if (*when)
+	{
+		/* send a mail message */
+		mail(ownername(tname), name.c, when);
+
+		/* remove the temp file -- the editor has died already */
+		unlink(tname);
+	}
+}
+
+main(argc, argv)
+	int	argc;
+	char	**argv;
+{
+	int	i;
+	char	*when = "the editor went away";
+
+#if MSDOS || TOS
+	/* expand any wildcards in the command line */
+	argv = wildexpand(&argc, argv);
+#endif
+
+	/* do we have a "when" argument? */
+	i = 1;
+	if (argc >= i + 1 && !strcmp(argv[i], "-R"))
+	{
+		rewrite_now = 1;
+		when = "";
+		i++;
+#if ANY_UNIX
+		setuid(geteuid());
+#endif
+	}
+#if OSK
+	else
+	{
+		setuid(0);
+	}
+#endif
+	if (argc >= i + 1 && argv[i][0] == '-')
+	{
+		when = argv[i] + 1;
+		i++;
+	}
+
+	/* preserve everything we're supposed to */
+	while (i < argc)
+	{
+		preserve(argv[i], when);
+		i++;
+	}
+}
Index: /trunk/minix/commands/elvis/elvrec.c
===================================================================
--- /trunk/minix/commands/elvis/elvrec.c	(revision 9)
+++ /trunk/minix/commands/elvis/elvrec.c	(revision 9)
@@ -0,0 +1,199 @@
+/* elvrec.c */
+
+/* This file contains the file recovery program */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+#include <stdio.h>
+#include "config.h"
+#include "vi.h"
+#include <sys/stat.h>
+
+void recover(basename, outname)
+	char	*basename;	/* the name of the file to recover */
+	char	*outname;	/* the name of the file to write to */
+{
+	char	pathname[500];	/* full pathname of the file to recover */
+	char	line[600];	/* a line from the /usr/preserve/Index file */
+	int	ch;		/* a character from the text being recovered */
+	FILE	*from;		/* the /usr/preserve file, or /usr/preserve/Index */
+	FILE	*to;		/* the user's text file */
+	char	*ptr;
+	struct stat st;
+#if OSK
+	int		uid;
+#endif
+
+	/* convert basename to a full pathname */
+	if (basename)
+	{
+#ifndef CRUNCH
+# if MSDOS || TOS
+		if (!basename[0] || basename[1] != ':')
+# else
+		if (basename[0] != SLASH)
+# endif
+		{
+			ptr = getcwd(pathname, sizeof pathname);
+			if (ptr != pathname)
+			{
+				strcpy(pathname, ptr);
+			}
+			ptr = pathname + strlen(pathname);
+			*ptr++ = SLASH;
+			strcpy(ptr, basename);
+		}
+		else
+#endif
+		{
+			strcpy(pathname, basename);
+		}
+	}
+
+#if OSK
+	uid = getuid();
+	if(setuid(0))
+		exit(_errmsg(errno, "Can't set uid\n"));
+#endif
+	/* scan the /usr/preserve/Index file, for the *oldest* unrecovered
+	 * version of this file.
+	 */
+	from = fopen(PRSVINDEX, "r");
+	while (from && fgets(line, sizeof line, from))
+	{
+		/* strip off the newline from the end of the string */
+		line[strlen(line) - 1] = '\0';
+
+		/* parse the line into a "preserve" name and a "text" name */
+		for (ptr = line; *ptr != ' '; ptr++)
+		{
+		}
+		*ptr++ = '\0';
+
+		/* If the "preserve" file is missing, then ignore this line
+		 * because it describes a file that has already been recovered.
+		 */
+		if (stat(line, &st) < 0)
+		{
+			continue;
+		}
+
+		/* are we looking for a specific file? */
+		if (basename)
+		{
+			/* quit if we found it */
+			if (!strcmp(ptr, pathname))
+			{
+				break;
+			}
+		}
+		else
+		{
+			/* list this file as "available for recovery" */
+			puts(ptr);
+		}
+	}
+
+	/* file not found? */
+	if (!basename || !from || feof(from))
+	{
+		if (from != NULL) fclose(from);
+		if (basename)
+		{
+			fprintf(stderr, "%s: no recovered file has that exact name\n", pathname);
+		}
+		return;
+	}
+	if (from != NULL) fclose(from);
+
+	/* copy the recovered text back into the user's file... */
+
+	/* open the /usr/preserve file for reading */
+	from = fopen(line, "r");
+	if (!from)
+	{
+		perror(line);
+		exit(2);
+	}
+
+#if ANY_UNIX
+	/* Be careful about user-id.  We want to be running under the user's
+	 * real id when we open/create the user's text file... but we want
+	 * to be superuser when we delete the /usr/preserve file.  For UNIX,
+	 * we accomplish this by deleting the /usr/preserve file *now*,
+	 * when it is open but before we've read it.  Then we revert to the
+	 * user's real id.
+	 */
+	unlink(line);
+	setuid(getuid());
+#endif
+#if OSK
+	setuid(uid);
+#endif
+
+	if (outname == NULL) return;
+
+	/* open the user's file for writing */
+	to = fopen(outname, "w");
+	if (!to)
+	{
+		perror(ptr);
+		exit(2);
+	}
+
+	/* copy the text */
+	while ((ch = getc(from)) != EOF)
+	{
+		putc(ch, to);
+	}
+
+#if !ANY_UNIX
+#if OSK
+	fclose(from);
+	setuid(0);
+#endif
+	/* delete the /usr/preserve file */
+	unlink(line);
+#if OSK
+	setuid(uid);
+#endif
+#endif
+}
+
+main(argc, argv)
+	int	argc;
+	char	**argv;
+{
+	/* check arguments */
+	if (argc > 3)
+	{
+		fprintf(stderr, "usage: %s [preserved_file [recovery_file]]\n", argv[0]);
+		exit(1);
+	}
+
+	/* recover the requested file, or list recoverable files */
+	if (argc == 3)
+	{
+		/* recover the file, but write it to a different filename */
+		recover (argv[1], argv[2]);
+	}
+	else if (argc == 2)
+	{
+		/* recover the file */
+		recover(argv[1], argv[1]);
+	}
+	else
+	{
+		/* list the recoverable files */
+		recover((char *)0, (char *)0);
+	}
+
+	/* success! */
+	exit(0);
+}
Index: /trunk/minix/commands/elvis/ex.c
===================================================================
--- /trunk/minix/commands/elvis/ex.c	(revision 9)
+++ /trunk/minix/commands/elvis/ex.c	(revision 9)
@@ -0,0 +1,722 @@
+/* ex.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains the code for reading ex commands. */
+
+#include "config.h"
+#include "ctype.h"
+#include "vi.h"
+
+/* This data type is used to describe the possible argument combinations */
+typedef short ARGT;
+#define FROM	1		/* allow a linespec */
+#define	TO	2		/* allow a second linespec */
+#define BANG	4		/* allow a ! after the command name */
+#define EXTRA	8		/* allow extra args after command name */
+#define XFILE	16		/* expand wildcards in extra part */
+#define NOSPC	32		/* no spaces allowed in the extra part */
+#define	DFLALL	64		/* default file range is 1,$ */
+#define DFLNONE	128		/* no default file range */
+#define NODFL	256		/* do not default to the current file name */
+#define EXRCOK	512		/* can be in a .exrc file */
+#define NL	1024		/* if mode!=MODE_EX, then write a newline first */
+#define PLUS	2048		/* allow a line number, as in ":e +32 foo" */
+#define ZERO	4096		/* allow 0 to be given as a line number */
+#define NOBAR	8192		/* treat following '|' chars as normal */
+#define FILES	(XFILE + EXTRA)	/* multiple extra files allowed */
+#define WORD1	(EXTRA + NOSPC)	/* one extra word allowed */
+#define FILE1	(FILES + NOSPC)	/* 1 file allowed, defaults to current file */
+#define NAMEDF	(FILE1 + NODFL)	/* 1 file allowed, defaults to "" */
+#define NAMEDFS	(FILES + NODFL)	/* multiple files allowed, default is "" */
+#define RANGE	(FROM + TO)	/* range of linespecs allowed */
+#define NONE	0		/* no args allowed at all */
+
+/* This array maps ex command names to command codes. The order in which
+ * command names are listed below is significant -- ambiguous abbreviations
+ * are always resolved to be the first possible match.  (e.g. "r" is taken
+ * to mean "read", not "rewind", because "read" comes before "rewind")
+ */
+static struct
+{
+	char	*name;	/* name of the command */
+	CMD	code;	/* enum code of the command */
+	void	(*fn)();/* function which executes the command */
+	ARGT	argt;	/* command line arguments permitted/needed/used */
+}
+	cmdnames[] =
+{   /*	cmd name	cmd code	function	arguments */
+	{"append",	CMD_APPEND,	cmd_append,	FROM+ZERO+BANG	},
+#ifdef DEBUG
+	{"bug",		CMD_DEBUG,	cmd_debug,	RANGE+BANG+EXTRA+NL},
+#endif
+	{"change",	CMD_CHANGE,	cmd_append,	RANGE+BANG	},
+	{"delete",	CMD_DELETE,	cmd_delete,	RANGE+WORD1	},
+	{"edit",	CMD_EDIT,	cmd_edit,	BANG+FILE1+PLUS	},
+	{"file",	CMD_FILE,	cmd_file,	NAMEDF		},
+	{"global",	CMD_GLOBAL,	cmd_global,	RANGE+BANG+EXTRA+DFLALL+NOBAR},
+	{"insert",	CMD_INSERT,	cmd_append,	FROM+BANG	},
+	{"join",	CMD_INSERT,	cmd_join,	RANGE+BANG	},
+	{"k",		CMD_MARK,	cmd_mark,	FROM+WORD1	},
+	{"list",	CMD_LIST,	cmd_print,	RANGE+NL	},
+	{"move",	CMD_MOVE,	cmd_move,	RANGE+EXTRA	},
+	{"next",	CMD_NEXT,	cmd_next,	BANG+NAMEDFS	},
+	{"Next",	CMD_PREVIOUS,	cmd_next,	BANG		},
+	{"print",	CMD_PRINT,	cmd_print,	RANGE+NL	},
+	{"quit",	CMD_QUIT,	cmd_xit,	BANG		},
+	{"read",	CMD_READ,	cmd_read,	FROM+ZERO+NAMEDF},
+	{"substitute",	CMD_SUBSTITUTE,	cmd_substitute,	RANGE+EXTRA	},
+	{"to",		CMD_COPY,	cmd_move,	RANGE+EXTRA	},
+	{"undo",	CMD_UNDO,	cmd_undo,	NONE		},
+	{"vglobal",	CMD_VGLOBAL,	cmd_global,	RANGE+EXTRA+DFLALL+NOBAR},
+	{"write",	CMD_WRITE,	cmd_write,	RANGE+BANG+FILE1+DFLALL},
+	{"xit",		CMD_XIT,	cmd_xit,	BANG+NL		},
+	{"yank",	CMD_YANK,	cmd_delete,	RANGE+WORD1	},
+
+	{"!",		CMD_BANG,	cmd_shell,	EXRCOK+RANGE+NAMEDFS+DFLNONE+NL+NOBAR},
+	{"#",		CMD_NUMBER,	cmd_print,	RANGE+NL	},
+	{"<",		CMD_SHIFTL,	cmd_shift,	RANGE		},
+	{">",		CMD_SHIFTR,	cmd_shift,	RANGE		},
+	{"=",		CMD_EQUAL,	cmd_file,	RANGE		},
+	{"&",		CMD_SUBAGAIN,	cmd_substitute,	RANGE		},
+#ifndef NO_AT
+	{"@",		CMD_AT,		cmd_at,		EXTRA		},
+#endif
+
+#ifndef NO_ABBR
+	{"abbreviate",	CMD_ABBR,	cmd_map,	EXRCOK+BANG+EXTRA},
+#endif
+	{"args",	CMD_ARGS,	cmd_args,	EXRCOK+NAMEDFS	},
+#ifndef NO_ERRLIST
+	{"cc",		CMD_CC,		cmd_make,	BANG+FILES	},
+#endif
+	{"cd",		CMD_CD,		cmd_cd,		EXRCOK+BANG+NAMEDF},
+	{"copy",	CMD_COPY,	cmd_move,	RANGE+EXTRA	},
+#ifndef NO_DIGRAPH
+	{"digraph",	CMD_DIGRAPH,	cmd_digraph,	EXRCOK+BANG+EXTRA},
+#endif
+#ifndef NO_ERRLIST
+	{"errlist",	CMD_ERRLIST,	cmd_errlist,	BANG+NAMEDF	},
+#endif
+	{"ex",		CMD_EDIT,	cmd_edit,	BANG+FILE1	},
+	{"mark",	CMD_MARK,	cmd_mark,	FROM+WORD1	},
+#ifndef NO_MKEXRC
+	{"mkexrc",	CMD_MKEXRC,	cmd_mkexrc,	NAMEDF		},
+#endif
+	{"number",	CMD_NUMBER,	cmd_print,	RANGE+NL	},
+	{"put",		CMD_PUT,	cmd_put,	FROM+ZERO+WORD1	},
+	{"set",		CMD_SET,	cmd_set,	EXRCOK+EXTRA	},
+	{"shell",	CMD_SHELL,	cmd_shell,	NL		},
+	{"source",	CMD_SOURCE,	cmd_source,	EXRCOK+NAMEDF	},
+#ifdef SIGTSTP
+	{"stop",	CMD_STOP,	cmd_suspend,	NONE		},
+#endif
+	{"tag",		CMD_TAG,	cmd_tag,	BANG+WORD1	},
+	{"version",	CMD_VERSION,	cmd_version,	EXRCOK+NONE	},
+	{"visual",	CMD_VISUAL,	cmd_edit,	BANG+NAMEDF	},
+	{"wq",		CMD_WQUIT,	cmd_xit,	NL		},
+
+#ifdef DEBUG
+	{"debug",	CMD_DEBUG,	cmd_debug,	RANGE+BANG+EXTRA+NL},
+	{"validate",	CMD_VALIDATE,	cmd_validate,	BANG+NL		},
+#endif
+	{"chdir",	CMD_CD,		cmd_cd,		EXRCOK+BANG+NAMEDF},
+#ifndef NO_COLOR
+	{"color",	CMD_COLOR,	cmd_color,	EXRCOK+EXTRA	},
+#endif
+#ifndef NO_ERRLIST
+	{"make",	CMD_MAKE,	cmd_make,	BANG+NAMEDFS	},
+#endif
+	{"map",		CMD_MAP,	cmd_map,	EXRCOK+BANG+EXTRA},
+	{"previous",	CMD_PREVIOUS,	cmd_next,	BANG		},
+	{"rewind",	CMD_REWIND,	cmd_next,	BANG		},
+#ifdef SIGTSTP
+	{"suspend",	CMD_SUSPEND,	cmd_suspend,	NONE		},
+#endif
+	{"unmap",	CMD_UNMAP,	cmd_map,	EXRCOK+BANG+EXTRA},
+#ifndef NO_ABBR
+	{"unabbreviate",CMD_UNABBR,	cmd_map,	EXRCOK+WORD1	},
+#endif
+
+	{(char *)0}
+};
+
+
+/* This function parses a search pattern - given a pointer to a / or ?,
+ * it replaces the ending / or ? with a \0, and returns a pointer to the
+ * stuff that came after the pattern.
+ */
+char	*parseptrn(ptrn)
+	REG char	*ptrn;
+{
+	REG char 	*scan;
+
+	for (scan = ptrn + 1;
+	     *scan && *scan != *ptrn;
+	     scan++)
+	{
+		/* allow backslashed versions of / and ? in the pattern */
+		if (*scan == '\\' && scan[1] != '\0')
+		{
+			scan++;
+		}
+	}
+	if (*scan)
+	{
+		*scan++ = '\0';
+	}
+
+	return scan;
+}
+
+
+/* This function parses a line specifier for ex commands */
+char *linespec(s, markptr)
+	REG char	*s;		/* start of the line specifier */
+	MARK		*markptr;	/* where to store the mark's value */
+{
+	long		num;
+	REG char	*t;
+
+	/* parse each ;-delimited clause of this linespec */
+	do
+	{
+		/* skip an initial ';', if any */
+		if (*s == ';')
+		{
+			s++;
+		}
+
+		/* skip leading spaces */
+		while (isspace(*s))
+		{
+			s++;
+		}
+
+		/* dot means current position */
+		if (*s == '.')
+		{
+			s++;
+			*markptr = cursor;
+		}
+		/* '$' means the last line */
+		else if (*s == '$')
+		{
+			s++;
+			*markptr = MARK_LAST;
+		}
+		/* digit means an absolute line number */
+		else if (isdigit(*s))
+		{
+			for (num = 0; isdigit(*s); s++)
+			{
+				num = num * 10 + *s - '0';
+			}
+			*markptr = MARK_AT_LINE(num);
+		}
+		/* appostrophe means go to a set mark */
+		else if (*s == '\'')
+		{
+			s++;
+			*markptr = m_tomark(cursor, 1L, (int)*s);
+			s++;
+		}
+		/* slash means do a search */
+		else if (*s == '/' || *s == '?')
+		{
+			/* put a '\0' at the end of the search pattern */
+			t = parseptrn(s);
+
+			/* search for the pattern */
+			*markptr &= ~(BLKSIZE - 1);
+			if (*s == '/')
+			{
+				pfetch(markline(*markptr));
+				if (plen > 0)
+					*markptr += plen - 1;
+				*markptr = m_fsrch(*markptr, s);
+			}
+			else
+			{
+				*markptr = m_bsrch(*markptr, s);
+			}
+
+			/* adjust command string pointer */
+			s = t;
+		}
+
+		/* if linespec was faulty, quit now */
+		if (!*markptr)
+		{
+			return s;
+		}
+
+		/* maybe add an offset */
+		t = s;
+		if (*t == '-' || *t == '+')
+		{
+			s++;
+			for (num = 0; isdigit(*s); s++)
+			{
+				num = num * 10 + *s - '0';
+			}
+			if (num == 0)
+			{
+				num = 1;
+			}
+			*markptr = m_updnto(*markptr, num, *t);
+		}
+	} while (*s == ';' || *s == '+' || *s == '-');
+
+	/* protect against invalid line numbers */
+	num = markline(*markptr);
+	if (num < 1L || num > nlines)
+	{
+		msg("Invalid line number -- must be from 1 to %ld", nlines);
+		*markptr = MARK_UNSET;
+	}
+
+	return s;
+}
+
+
+
+/* This function reads an ex command and executes it. */
+void ex()
+{
+	char		cmdbuf[150];
+	REG int		cmdlen;
+	static long	oldline;
+
+	significant = FALSE;
+	oldline = markline(cursor);
+
+	while (mode == MODE_EX)
+	{
+		/* read a line */
+#ifdef CRUNCH
+		cmdlen = vgets(':', cmdbuf, sizeof(cmdbuf));
+#else
+		cmdlen = vgets(*o_prompt ? ':' : '\0', cmdbuf, sizeof(cmdbuf));
+#endif
+		if (cmdlen < 0)
+		{
+			return;
+		}
+
+		/* if empty line, assume ".+1" */
+		if (cmdlen == 0)
+		{
+			strcpy(cmdbuf, ".+1");
+			qaddch('\r');
+			clrtoeol();
+		}
+		else
+		{
+			addch('\n');
+		}
+		refresh();
+
+		/* parse & execute the command */
+		doexcmd(cmdbuf);
+
+		/* handle autoprint */
+		if (significant || markline(cursor) != oldline)
+		{
+			significant = FALSE;
+			oldline = markline(cursor);
+			if (*o_autoprint && mode == MODE_EX)
+			{
+				cmd_print(cursor, cursor, CMD_PRINT, FALSE, "");
+			}
+		}
+	}
+}
+
+void doexcmd(cmdbuf)
+	char		*cmdbuf;	/* string containing an ex command */
+{
+	REG char	*scan;		/* used to scan thru cmdbuf */
+	MARK		frommark;	/* first linespec */
+	MARK		tomark;		/* second linespec */
+	REG int		cmdlen;		/* length of the command name given */
+	CMD		cmd;		/* what command is this? */
+	ARGT		argt;		/* argument types for this command */
+	short		forceit;	/* bang version of a command? */
+	REG int		cmdidx;		/* index of command */
+	REG char	*build;		/* used while copying filenames */
+	int		iswild;		/* boolean: filenames use wildcards? */
+	int		isdfl;		/* using default line ranges? */
+	int		didsub;		/* did we substitute file names for % or # */
+
+	/* ex commands can't be undone via the shift-U command */
+	U_line = 0L;
+
+	/* permit extra colons at the start of the line */
+	for (; *cmdbuf == ':'; cmdbuf++)
+	{
+	}
+
+	/* ignore command lines that start with a double-quote */
+	if (*cmdbuf == '"')
+	{
+		return;
+	}
+	scan = cmdbuf;
+
+	/* parse the line specifier */
+	if (nlines < 1)
+	{
+		/* no file, so don't allow addresses */
+	}
+	else if (*scan == '%')
+	{
+		/* '%' means all lines */
+		frommark = MARK_FIRST;
+		tomark = MARK_LAST;
+		scan++;
+	}
+	else if (*scan == '0')
+	{
+		frommark = tomark = MARK_UNSET;
+		scan++;
+	}
+	else
+	{
+		frommark = cursor;
+		scan = linespec(scan, &frommark);
+		tomark = frommark;
+		if (frommark && *scan == ',')
+		{
+			scan++;
+			scan = linespec(scan, &tomark);
+		}
+		if (!tomark)
+		{
+			/* faulty line spec -- fault already described */
+			return;
+		}
+		if (frommark > tomark)
+		{
+			msg("first address exceeds the second");
+			return;
+		}
+	}
+	isdfl = (scan == cmdbuf);
+
+	/* skip whitespace */
+	while (isspace(*scan))
+	{
+		scan++;
+	}
+
+	/* if no command, then just move the cursor to the mark */
+	if (!*scan)
+	{
+		if (tomark != MARK_UNSET)
+			cursor = tomark;
+		return;
+	}
+
+	/* figure out how long the command name is */
+	if (!isalpha(*scan))
+	{
+		cmdlen = 1;
+	}
+	else
+	{
+		for (cmdlen = 1;
+		     isalpha(scan[cmdlen]);
+		     cmdlen++)
+		{
+		}
+	}
+
+	/* lookup the command code */
+	for (cmdidx = 0;
+	     cmdnames[cmdidx].name && strncmp(scan, cmdnames[cmdidx].name, cmdlen);
+	     cmdidx++)
+	{
+	}
+	argt = cmdnames[cmdidx].argt;
+	cmd = cmdnames[cmdidx].code;
+	if (cmd == CMD_NULL)
+	{
+		msg("Unknown command \"%.*s\"", cmdlen, scan);
+		return;
+	}
+
+	/* !!! if the command doesn't have NOBAR set, then replace | with \0 */
+
+	/* if the command ended with a bang, set the forceit flag */
+	scan += cmdlen;
+	if ((argt & BANG) && *scan == '!')
+	{
+		scan++;
+		forceit = 1;
+	}
+	else
+	{
+		forceit = 0;
+	}
+
+	/* skip any more whitespace, to leave scan pointing to arguments */
+	while (isspace(*scan))
+	{
+		scan++;
+	}
+
+	/* a couple of special cases for filenames */
+	if (argt & XFILE)
+	{
+		/* if names were given, process them */
+		if (*scan)
+		{
+			for (build = tmpblk.c, iswild = didsub = FALSE; *scan; scan++)
+			{
+				switch (*scan)
+				{
+				  case '\\':
+					if (scan[1] == '\\' || scan[1] == '%' || scan[1] == '#')
+					{
+						*build++ = *++scan;
+					}
+					else
+					{
+						*build++ = '\\';
+					}
+					break;
+
+				  case '%':
+					if (!*origname)
+					{
+						msg("No filename to substitute for %%");
+						return;
+					}
+					strcpy(build, origname);
+					while (*build)
+					{
+						build++;
+					}
+					didsub = TRUE;
+					break;
+
+				  case '#':
+					if (!*prevorig)
+					{
+						msg("No filename to substitute for #");
+						return;
+					}
+					strcpy(build, prevorig);
+					while (*build)
+					{
+						build++;
+					}
+					didsub = TRUE;
+					break;
+
+				  case '*':
+				  case '?':
+#if !(MSDOS || TOS)
+				  case '[':
+				  case '`':
+				  case '{': /* } */
+				  case '$':
+				  case '~':
+#endif
+					*build++ = *scan;
+					iswild = TRUE;
+					break;
+
+				  default:
+					*build++ = *scan;
+				}
+			}
+			*build = '\0';
+
+			if (cmd == CMD_BANG
+			 || cmd == CMD_READ && tmpblk.c[0] == '!'
+			 || cmd == CMD_WRITE && tmpblk.c[0] == '!')
+			{
+				if (didsub)
+				{
+					if (mode != MODE_EX)
+					{
+						addch('\n');
+					}
+					addstr(tmpblk.c);
+					addch('\n');
+					exrefresh();
+				}
+			}
+			else
+			{
+				if (iswild && tmpblk.c[0] != '>')
+				{
+					scan = wildcard(tmpblk.c);
+				}
+			}
+		}
+		else /* no names given, maybe assume origname */
+		{
+			if (!(argt & NODFL))
+			{
+				strcpy(tmpblk.c, origname);
+			}
+			else
+			{
+				*tmpblk.c = '\0';
+			}
+		}
+
+		scan = tmpblk.c;
+	}
+
+	/* bad arguments? */
+	if (!(argt & EXRCOK) && nlines < 1L)
+	{
+		msg("Can't use the \"%s\" command in a %s file", cmdnames[cmdidx].name, EXRC);
+		return;
+	}
+	if (!(argt & (ZERO | EXRCOK)) && frommark == MARK_UNSET)
+	{
+		msg("Can't use address 0 with \"%s\" command.", cmdnames[cmdidx].name);
+		return;
+	}
+	if (!(argt & FROM) && frommark != cursor && nlines >= 1L)
+	{
+		msg("Can't use address with \"%s\" command.", cmdnames[cmdidx].name);
+		return;
+	}
+	if (!(argt & TO) && tomark != frommark && nlines >= 1L)
+	{
+		msg("Can't use a range with \"%s\" command.", cmdnames[cmdidx].name);
+		return;
+	}
+	if (!(argt & EXTRA) && *scan)
+	{
+		msg("Extra characters after \"%s\" command.", cmdnames[cmdidx].name);
+		return;
+	}
+	if ((argt & NOSPC) && !(cmd == CMD_READ && (forceit || *scan == '!')))
+	{
+		build = scan;
+#ifndef CRUNCH
+		if ((argt & PLUS) && *build == '+')
+		{
+			while (*build && !isspace(*build))
+			{
+				build++;
+			}
+			while (*build && isspace(*build))
+			{
+				build++;
+			}
+		}
+#endif /* not CRUNCH */
+		for (; *build; build++)
+		{
+			if (isspace(*build))
+			{
+				msg("Too many %s to \"%s\" command.",
+					(argt & XFILE) ? "filenames" : "arguments",
+					cmdnames[cmdidx].name);
+				return;
+			}
+		}
+	}
+
+	/* some commands have special default ranges */
+	if (isdfl && (argt & DFLALL))
+	{
+		frommark = MARK_FIRST;
+		tomark = MARK_LAST;
+	}
+	else if (isdfl && (argt & DFLNONE))
+	{
+		frommark = tomark = 0L;
+	}
+
+	/* write a newline if called from visual mode */
+	if ((argt & NL) && mode != MODE_EX && !exwrote)
+	{
+		addch('\n');
+		exrefresh();
+	}
+
+	/* act on the command */
+	(*cmdnames[cmdidx].fn)(frommark, tomark, cmd, forceit, scan);
+}
+
+
+/* This function executes EX commands from a file.  It returns 1 normally, or
+ * 0 if the file could not be opened for reading.
+ */
+int doexrc(filename)
+	char	*filename;	/* name of a ".exrc" file */
+{
+	int	fd;		/* file descriptor */
+	int	len;		/* length of the ".exrc" file */
+
+	/* !!! kludge: we use U_text as the buffer.  This has the side-effect
+	 * of interfering with the shift-U visual command.  Disable shift-U.
+	 */
+	U_line = 0L;
+
+	/* open the file, read it, and close */
+	fd = open(filename, O_RDONLY);
+	if (fd < 0)
+	{
+		return 0;
+	}
+	len = tread(fd, U_text, BLKSIZE);
+	close(fd);
+
+	/* execute the string */
+	exstring(U_text, len, ctrl('V'));
+
+	return 1;
+}
+
+/* This function executes EX commands from a string.  The commands may be
+ * separated by newlines or by | characters.  It also handles quoting.
+ * Each individual command is limited to 132 bytes, but the total string
+ * may be longer.
+ */
+void exstring(buf, len, qchar)
+	char	*buf;	/* the commands to execute */
+	int	len;	/* the length of the string */
+	int	qchar;	/* the quote character -- ^V for file, or \ for kbd */
+{
+	char	single[133];	/* a single command */
+	char	*src, *dest;
+	int	i;
+
+	/* find & do each command */
+	for (src = buf; src < &buf[len]; src++)
+	{
+		/* Copy a single command into single[].  Convert any quoted |
+		 * into a normal |, and stop at a newline or unquoted |.
+		 */
+		for (dest = single, i = 0;
+		     i < 132 && src < &buf[len] && *src != '\n' && *src != '|';
+		     src++, i++)
+		{
+			if (src[0] == qchar && src[1] == '|')
+			{
+				src++;
+			}
+			*dest++ = *src;
+		}
+		*dest = '\0';
+
+		/* do it */
+		doexcmd(single);
+	}
+}
Index: /trunk/minix/commands/elvis/fmt.c
===================================================================
--- /trunk/minix/commands/elvis/fmt.c	(revision 9)
+++ /trunk/minix/commands/elvis/fmt.c	(revision 9)
@@ -0,0 +1,266 @@
+/* fmt.c */
+
+/* usage: fmt [-width] [files]...
+ *
+ * Fmt rearrages text in order to make each line have roughly the
+ * same width.  Indentation and word spacing is preserved.
+ *
+ * The default width is 72 characters, but you can override that via -width.
+ * If no files are given on the command line, then it reads stdin.
+ */
+
+#include <stdio.h>
+
+#ifndef TRUE
+# define TRUE	1
+# define FALSE	0
+#endif
+
+
+
+int	width = 72;	/* the desired line width */
+int	isblank;	/* is the current output line blank? */
+int	indent;		/* width of the indentation */
+char	ind[512];	/* indentation text */
+char	word[1024];	/* word buffer */
+
+/* This function displays a usage message and quits */
+void usage()
+{
+	fprintf(stderr, "usage: fmt [-width] [files]...\n");
+	exit(2);
+}
+
+
+
+/* This function outputs a single word.  It takes care of spacing and the
+ * newlines within a paragraph.
+ */
+void putword()
+{
+	int		i;		/* index into word[], or whatever */
+	int		ww;		/* width of the word */
+	int		sw;		/* width of spacing after word */
+	static int	psw;		/* space width of previous word */
+	static int	tab;		/* the width of text already written */
+
+
+	/* separate the word and its spacing */
+	for (ww = 0; word[ww] && word[ww] != ' '; ww++)
+	{
+	}
+	sw = strlen(word) - ww;
+	word[ww] = '\0';
+
+	/* if no spacing (that is, the word was at the end of the line) then
+	 * assume 1 space unless the last char of the word was punctuation
+	 */
+	if (sw == 0)
+	{
+		sw = 1;
+		if (word[ww - 1] == '.' || word[ww - 1] == '?' || word[ww - 1] == '!')
+			sw = 2;
+	}
+
+	/* if this is the first word on the line... */
+	if (isblank)
+	{
+		/* output the indentation first */
+		fputs(ind, stdout);
+		tab = indent;
+	}
+	else /* text has already been written to this output line */
+	{
+		/* will the word fit on this line? */
+		if (psw + ww + tab <= width)
+		{
+			/* yes - so write the previous word's spacing */
+			for (i = 0; i < psw; i++)
+			{
+				putchar(' ');
+			}
+			tab += psw;
+		}
+		else
+		{
+			/* no, so write a newline and the indentation */
+			putchar('\n');
+			fputs(ind, stdout);
+			tab = indent;
+		}
+	}
+
+	/* write the word itself */
+	fputs(word, stdout);
+	tab += ww;
+
+	/* remember this word's spacing */
+	psw = sw;
+
+	/* this output line isn't blank anymore. */
+	isblank = FALSE;
+}
+
+
+
+/* This function reformats text. */
+void fmt(in)
+	FILE	*in;		/* the name of the input stream */
+{
+	int	ch;		/* character from input stream */
+	int	prevch;		/* the previous character in the loop */
+	int	i;		/* index into ind[] or word[] */
+	int	inword;		/* boolean: are we between indent & newline? */
+
+
+	/* for each character in the stream... */
+	for (indent = -1, isblank = TRUE, inword = FALSE, i = 0, prevch = '\n';
+	     (ch = getc(in)) != EOF;
+	     prevch = ch)
+	{
+		/* is this the end of a line? */
+		if (ch == '\n')
+		{
+			/* if end of last word in the input line */
+			if (inword)
+			{
+				/* if it really is a word */
+				if (i > 0)
+				{
+					/* output it */
+					word[i] = '\0';
+					putword();
+				}
+			}
+			else /* blank line in input */
+			{
+				/* finish the previous paragraph */
+				if (!isblank)
+				{
+					putchar('\n');
+					isblank = TRUE;
+				}
+
+				/* output a blank line */
+				putchar('\n');
+			}
+
+			/* continue with next input line... */
+			indent = -1;
+			i = 0;
+			inword = FALSE;
+			continue;
+		}
+
+		/* if we're expecting indentation now... */
+		if (indent < 0)
+		{
+			/* if this is part of the indentation... */
+			if (ch == ' ' || ch == '\t')
+			{
+				/* remember it */
+				ind[i++] = ch;
+			}
+			else /* end of indentation */
+			{
+				/* mark the end of the indentation string */
+				ind[i] = '\0';
+
+				/* calculate the width of the indentation */
+				for (i = indent = 0; ind[i]; i++)
+				{
+					if (ind[i] == '\t')
+						indent = (indent | 7) + 1;
+					else
+						indent++;
+				}
+
+				/* reset the word index */
+				i = 0;
+
+				/* reprocess that last character */
+				ungetc(ch, in);
+			}
+
+			/* continue in the for-loop */
+			continue;
+		}
+
+		/* if we get here, we're either in a word or in the space
+		 * after a word.
+		 */
+		inword = TRUE;
+
+		/* is this the start of a new word? */
+		if (ch != ' ' && prevch == ' ')
+		{
+			/* yes!  output the previous word */
+			word[i] = '\0';
+			putword();
+
+			/* reset `i' to the start of the word[] buffer */
+			i = 0;
+		}
+		word[i++] = ch;
+	}
+
+	/* if necessary, write a final newline */
+	if (!isblank)
+	{
+		putchar('\n');
+		isblank = TRUE;
+	}
+}
+
+
+
+
+
+int main(argc, argv)
+	int	argc;
+	char	**argv;
+{
+	FILE	*in;	/* an input stream */
+	int	error;	/* if non-zero, then an error occurred */
+	int	i;
+
+
+	/* handle the -width flag, if given */
+	if (argc > 1 && argv[1][0] == '-')
+	{
+		width = atoi(argv[1] + 1);
+		if (width <= 0)
+		{
+			usage();
+		}
+		argc--;
+		argv++;
+	}
+
+	/* if no filenames given, then process stdin */
+	if (argc == 1)
+	{
+		fmt(stdin);
+	}
+	else /* one or more filenames given */
+	{
+		for (error = 0, i = 1; i < argc; i++)
+		{
+			in = fopen(argv[i], "r");
+			if (!in)
+			{
+				perror(argv[i]);
+				error = 3;
+			}
+			else
+			{
+				fmt(in);
+				fclose(in);
+			}
+		}
+	}
+
+	/* exit, possibly indicating an error */
+	exit(error);
+	/*NOTREACHED*/
+}
Index: /trunk/minix/commands/elvis/input.c
===================================================================
--- /trunk/minix/commands/elvis/input.c	(revision 9)
+++ /trunk/minix/commands/elvis/input.c	(revision 9)
@@ -0,0 +1,852 @@
+/* input.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains the input() function, which implements vi's INPUT mode.
+ * It also contains the code that supports digraphs.
+ */
+
+#include "config.h"
+#include "ctype.h"
+#include "vi.h"
+
+
+#ifndef NO_DIGRAPH
+static struct _DIG
+{
+	struct _DIG	*next;
+	char		key1;
+	char		key2;
+	char		dig;
+	char		save;
+} *digs;
+
+char digraph(key1, key2)
+	char	key1;	/* the underlying character */
+	char	key2;	/* the second character */
+{
+	int		newkey;
+	REG struct _DIG	*dp;
+
+	/* if digraphs are disabled, then just return the new char */
+	if (!*o_digraph)
+	{
+		return key2;
+	}
+
+	/* remember the new key, so we can return it if this isn't a digraph */
+	newkey = key2;
+
+	/* sort key1 and key2, so that their original order won't matter */
+	if (key1 > key2)
+	{
+		key2 = key1;
+		key1 = newkey;
+	}
+
+	/* scan through the digraph chart */
+	for (dp = digs;
+	     dp && (dp->key1 != key1 || dp->key2 != key2);
+	     dp = dp->next)
+	{
+	}
+
+	/* if this combination isn't in there, just use the new key */
+	if (!dp)
+	{
+		return newkey;
+	}
+
+	/* else use the digraph key */
+	return dp->dig;
+}
+
+/* this function lists or defines digraphs */
+void do_digraph(bang, extra)
+	int	bang;
+	char	extra[];
+{
+	int		dig;
+	REG struct _DIG	*dp;
+	struct _DIG	*prev;
+	static int	user_defined = FALSE; /* boolean: are all later digraphs user-defined? */
+	char		listbuf[8];
+
+	/* if "extra" is NULL, then we've reached the end of the built-ins */
+	if (!extra)
+	{
+		user_defined = TRUE;
+		return;
+	}
+
+	/* if no args, then display the existing digraphs */
+	if (*extra < ' ')
+	{
+		listbuf[0] = listbuf[1] = listbuf[2] = listbuf[5] = ' ';
+		listbuf[7] = '\0';
+		for (dig = 0, dp = digs; dp; dp = dp->next)
+		{
+			if (dp->save || bang)
+			{
+				dig += 7;
+				if (dig >= COLS)
+				{
+					addch('\n');
+					exrefresh();
+					dig = 7;
+				}
+				listbuf[3] = dp->key1;
+				listbuf[4] = dp->key2;
+				listbuf[6] = dp->dig;
+				qaddstr(listbuf);
+			}
+		}
+		addch('\n');
+		exrefresh();
+		return;
+	}
+
+	/* make sure we have at least two characters */
+	if (!extra[1])
+	{
+		msg("Digraphs must be composed of two characters");
+		return;
+	}
+
+	/* sort key1 and key2, so that their original order won't matter */
+	if (extra[0] > extra[1])
+	{
+		dig = extra[0];
+		extra[0] = extra[1];
+		extra[1] = dig;
+	}
+
+	/* locate the new digraph character */
+	for (dig = 2; extra[dig] == ' ' || extra[dig] == '\t'; dig++)
+	{
+	}
+	dig = extra[dig];
+	if (!bang && dig)
+	{
+		dig |= 0x80;
+	}
+
+	/* search for the digraph */
+	for (prev = (struct _DIG *)0, dp = digs;
+	     dp && (dp->key1 != extra[0] || dp->key2 != extra[1]);
+	     prev = dp, dp = dp->next)
+	{
+	}
+
+	/* deleting the digraph? */
+	if (!dig)
+	{
+		if (!dp)
+		{
+#ifndef CRUNCH
+			msg("%c%c not a digraph", extra[0], extra[1]);
+#endif
+			return;
+		}
+		if (prev)
+			prev->next = dp->next;
+		else
+			digs = dp->next;
+		free(dp);
+		return;
+	}
+
+	/* if necessary, create a new digraph struct for the new digraph */
+	if (dig && !dp)
+	{
+		dp = (struct _DIG *)malloc(sizeof *dp);
+		if (!dp)
+		{
+			msg("Out of space in the digraph table");
+			return;
+		}
+		if (prev)
+			prev->next = dp;
+		else
+			digs = dp;
+		dp->next = (struct _DIG *)0;
+	}
+
+	/* assign it the new digraph value */
+	dp->key1 = extra[0];
+	dp->key2 = extra[1];
+	dp->dig = dig;
+	dp->save = user_defined;
+}
+
+# ifndef NO_MKEXRC
+void savedigs(fd)
+	int		fd;
+{
+	static char	buf[] = "digraph! XX Y\n";
+	REG struct _DIG	*dp;
+
+	for (dp = digs; dp; dp = dp->next)
+	{
+		if (dp->save)
+		{
+			buf[9] = dp->key1;
+			buf[10] = dp->key2;
+			buf[12] = dp->dig;
+			write(fd, buf, (unsigned)14);
+		}
+	}
+}
+# endif
+#endif
+
+
+/* This function allows the user to replace an existing (possibly zero-length)
+ * chunk of text with typed-in text.  It returns the MARK of the last character
+ * that the user typed in.
+ */
+MARK input(from, to, when, above)
+	MARK	from;	/* where to start inserting text */
+	MARK	to;	/* extent of text to delete */
+	int	when;	/* either WHEN_VIINP or WHEN_VIREP */
+	int	above;	/* boolean: take indentation from lower line? */
+{
+	char	key[2];	/* key char followed by '\0' char */
+	char	*build;	/* used in building a newline+indent string */
+	char	*scan;	/* used while looking at the indent chars of a line */
+	MARK	m;	/* some place in the text */
+#ifndef NO_EXTENSIONS
+	int	quit = FALSE;	/* boolean: are we exiting after this? */
+	int	inchg;	/* boolean: have we done a "beforedo()" yet? */
+#endif
+
+#ifdef DEBUG
+	/* if "from" and "to" are reversed, complain */
+	if (from > to)
+	{
+		msg("ERROR: input(%ld:%d, %ld:%d)",
+			markline(from), markidx(from),
+			markline(to), markidx(to));
+		return MARK_UNSET;
+	}
+#endif
+
+	key[1] = 0;
+
+	/* if we're replacing text with new text, save the old stuff */
+	/* (Alas, there is no easy way to save text for replace mode) */
+	if (from != to)
+	{
+		cut(from, to);
+	}
+
+	/* if doing a dot command, then reuse the previous text */
+	if (doingdot)
+	{
+		ChangeText
+		{
+			/* delete the text that's there now */
+			if (from != to)
+			{
+				delete(from, to);
+			}
+
+			/* insert the previous text */
+			cutname('.');
+			cursor = paste(from, FALSE, TRUE) + 1L;
+		}
+	}
+	else /* interactive version */
+	{
+		/* assume that whoever called this already did a beforedo() */
+#ifndef NO_EXTENSIONS
+		inchg = TRUE;
+#endif
+
+		/* if doing a change within the line... */
+		if (from != to && markline(from) == markline(to))
+		{
+			/* mark the end of the text with a "$" */
+			change(to - 1, to, "$");
+		}
+		else
+		{
+			/* delete the old text right off */
+			if (from != to)
+			{
+				delete(from, to);
+			}
+			to = from;
+		}
+
+		/* handle autoindent of the first line, maybe */
+		cursor = from;
+		m = (above ? (cursor + BLKSIZE) : (cursor - BLKSIZE));
+		if (*o_autoindent && markidx(m) == 0
+		 && markline(m) >= 1L && markline(m) <= nlines)
+		{
+			/* Only autoindent blank lines. */
+			pfetch(markline(cursor));
+			if (plen == 0)
+			{
+				/* Okay, we really want to autoindent */
+				pfetch(markline(m));
+				for (scan = ptext, build = tmpblk.c;
+				     *scan == ' ' || *scan == '\t';
+				     )
+				{
+					*build++ = *scan++;
+				}
+				if (build > tmpblk.c)
+				{
+					*build = '\0';
+					add(cursor, tmpblk.c);
+					cursor += (build - tmpblk.c);
+					if (cursor > to)
+						to = cursor;
+				}
+			}
+		}
+
+		/* repeatedly add characters from the user */
+		for (;;)
+		{
+			/* Get a character */
+			redraw(cursor, TRUE);
+#ifdef DEBUG2
+			msg("cursor=%ld.%d, to=%ld.%d",
+				markline(cursor), markidx(cursor),
+				markline(to), markidx(to));
+#endif
+#ifndef NO_ABBR
+			pfetch(markline(cursor));
+			build = ptext;
+			if (pline == markline(from))
+				build += markidx(from);
+			for (scan = ptext + markidx(cursor); --scan >= build && isalnum(*scan); )
+			{
+			}
+			scan++;
+			key[0] = getabkey(when, scan, (int)(ptext + markidx(cursor) - scan));
+#else
+			key[0] = getkey(when);
+#endif
+#ifndef NO_VISIBLE
+			if (key[0] != '\0' && V_from != MARK_UNSET)
+			{
+				msg("Can't modify text during a selection");
+				beep();
+				continue;
+			}
+#endif
+
+#ifndef NO_EXTENSIONS
+			if (key[0] == ctrl('O'))
+			{
+				if (inchg)
+				{
+					if (cursor < to)
+					{
+						delete(cursor, to);
+						redraw(cursor, TRUE);
+					}
+					afterdo();
+					inchg = FALSE;
+				}
+			}
+			else if (key[0] != ctrl('['))
+			{
+				if (!inchg)
+				{
+					beforedo(FALSE);
+					inchg = TRUE;
+				}
+			}
+#endif
+
+#ifndef CRUNCH
+			/* if wrapmargin is set & we're past the
+			 * warpmargin, then change the last whitespace
+			 * characters on line into a newline
+			 */
+			if (*o_wrapmargin != 0)
+			{
+				pfetch(markline(cursor));
+				if (idx2col(cursor, ptext, TRUE) > COLS - (*o_wrapmargin & 0xff))
+				{
+					build = tmpblk.c;
+					*build++ = '\n';
+					if (*o_autoindent)
+					{
+						/* figure out indent for next line */
+						for (scan = ptext; *scan == ' ' || *scan == '\t'; )
+						{
+							*build++ = *scan++;
+						}
+					}
+					*build = '\0';
+
+					scan = ptext + plen;
+					m = cursor & ~(BLKSIZE - 1);
+					while (ptext < scan)
+					{
+						scan--;
+						if (*scan != ' ' && *scan != '\t')
+							continue;
+
+						/*break up line, and we do autoindent if needed*/
+						change(m + (scan - ptext), m + (scan - ptext) + 1, tmpblk.c);
+						cursor = (cursor & ~(BLKSIZE - 1))
+							+ BLKSIZE
+							+ strlen(tmpblk.c) - 1
+							+ plen - (scan - ptext) - 1;
+
+						/*remove trailing spaces on previous line*/
+						pfetch(markline(m));
+						scan = ptext + plen;
+						while (ptext < scan)
+						{
+							scan--;
+							if (*scan != ' ' && *scan != '\t')
+								break;
+						}
+						delete(m + (scan-ptext) + 1, m + plen);
+
+						break;
+					}
+				}
+			}
+#endif /* !CRUNCH */
+
+			/* process it */
+			switch (*key)
+			{
+#ifndef NO_EXTENSIONS
+			  case ctrl('O'): /* special movement mapped keys */
+				*key = getkey(0);
+				switch (*key)
+				{
+				  case 'h':	m = m_left(cursor, 0L);		break;
+				  case 'j':
+				  case 'k':	m = m_updnto(cursor, 0L, *key);	break;
+				  case 'l':	m = cursor + 1;			break;
+				  case 'B':
+				  case 'b':	m = m_bword(cursor, 0L, *key);	break;
+				  case 'W':
+				  case 'w':	m = m_fword(cursor, 0L, *key, '\0');	break;
+				  case '^':	m = m_front(cursor, 0L);	break;
+				  case '$':	m = m_rear(cursor, 0L);		break;
+				  case ctrl('B'):
+				  case ctrl('F'):
+						m = m_scroll(cursor, 0L, *key); break;
+				  case 'x':
+#ifndef NO_VISIBLE
+						if (V_from)
+							beep();
+						else
+#endif
+						ChangeText
+						{
+							m = v_xchar(cursor, 0L, 'x');
+						}
+						break;
+				  case 'i':	m = to = from = cursor;
+						when = WHEN_VIINP + WHEN_VIREP - when;
+										break;
+				  case 'K':
+					pfetch(markline(cursor));
+					changes++; /* <- after this, we can alter ptext */
+					ptext[markidx(cursor)] = 0;
+					for (scan = ptext + markidx(cursor) - 1;
+					     scan >= ptext && isalnum(*scan);
+					     scan--)
+					{
+					}
+					scan++;
+					m = (*scan ? v_keyword(scan, cursor, 0L) : cursor);
+					break;
+
+# ifndef NO_VISIBLE
+				  case 'v':
+				  case 'V':
+					if (V_from)
+						V_from = MARK_UNSET;
+					else
+						V_from = cursor;
+					m = from = to = cursor;
+					V_linemd = (*key == 'V');
+					break;
+
+				  case 'd':
+				  case 'y':
+				  case '\\':
+					/* do nothing if unmarked */
+					if (!V_from)
+					{
+						msg("You must mark the text first");
+						beep();
+						break;
+					}
+
+					/* "from" must come before "to" */
+					if (V_from < cursor)
+					{
+						from = V_from;
+						to = cursor;
+					}
+					else
+					{
+						from = cursor;
+						to = V_from;
+					}
+
+					/* we don't need V_from anymore */
+					V_from = MARK_UNSET;
+
+					if (V_linemd)
+					{
+						/* adjust for line mode */
+						from &= ~(BLKSIZE - 1);
+						to |= (BLKSIZE - 1);
+					}
+					else
+					{
+						/* in character mode, we must
+						 * worry about deleting the newline
+						 * at the end of the last line
+						 */
+						pfetch(markline(to));
+						if (markidx(to) == plen)
+							to |= (BLKSIZE - 1);
+					}
+					to++;
+
+					switch (*key)
+					{
+					  case 'y':
+						cut(from, to);
+						break;
+
+					  case 'd':
+						ChangeText
+						{
+							cut(from, to);
+							delete(from, to);
+						}
+						cursor = from;
+						break;
+
+#ifndef NO_POPUP
+					  case '\\':
+						ChangeText
+						{
+							cursor = v_popup(from, to);
+						}
+						break;
+#endif
+					}
+					m = from = to = cursor;
+					break;
+
+				  case 'p':
+				  case 'P':
+					V_from = MARK_UNSET;
+					ChangeText
+					{
+						m = from = to = cursor = paste(cursor, (*key == 'p'), FALSE);
+					}
+					break;
+# endif /* !NO_VISIBLE */
+				  default:	m = MARK_UNSET;
+				}
+
+				/* adjust the moved cursor */
+				if (m != cursor)
+				{
+					m = adjmove(cursor, m, (*key == 'j' || *key == 'k' ? 0x20 : 0));
+					if (*key == '$' || (*key == 'l' && m <= cursor))
+					{
+						m++;
+					}
+				}
+
+				/* if the cursor is reasonable, use it */
+				if (m == MARK_UNSET)
+				{
+					beep();
+				}
+				else
+				{
+					from = to = cursor = m;
+				}
+				break;
+
+			  case ctrl('Z'):
+				if (getkey(0) == ctrl('Z'))
+				{
+					quit = TRUE;
+					goto BreakBreak;
+				}
+				break;
+#endif
+
+			  case ctrl('['):
+				/* if last line contains only whitespace, then remove whitespace */
+				if (*o_autoindent)
+				{
+					pfetch(markline(cursor));
+					for (scan = ptext; isspace(*scan); scan++)
+					{
+					}
+					if (scan > ptext && !*scan)
+					{
+						cursor &= ~(BLKSIZE - 1L);
+						if (to < cursor + plen)
+						{
+							to = cursor + plen;
+						}
+					}
+				}
+				goto BreakBreak;
+
+			  case ctrl('U'):
+				if (markline(cursor) == markline(from))
+				{
+					cursor = from;
+				}
+				else
+				{
+					cursor &= ~(BLKSIZE - 1);
+				}
+				break;
+
+			  case ctrl('D'):
+			  case ctrl('T'):
+				if (to > cursor)
+				{
+					delete(cursor, to);
+				}
+				mark[27] = cursor;
+				cmd_shift(cursor, cursor, *key == ctrl('D') ? CMD_SHIFTL : CMD_SHIFTR, TRUE, "");
+				if (mark[27])
+				{
+					cursor = mark[27];
+				}
+				else
+				{
+					cursor = m_front(cursor, 0L);
+				}
+				to = cursor;
+				break;
+
+			  case '\b':
+				if (cursor <= from)
+				{
+					beep();
+				}
+				else if (markidx(cursor) == 0)
+				{
+					cursor -= BLKSIZE;
+					pfetch(markline(cursor));
+					cursor += plen;
+				}
+				else
+				{
+					cursor--;
+				}
+				break;
+
+			  case ctrl('W'):
+				m = m_bword(cursor, 1L, 'b');
+				if (markline(m) == markline(cursor) && m >= from)
+				{
+					cursor = m;
+					if (from > cursor)
+					{
+						from = cursor;
+					}
+				}
+				else
+				{
+					beep();
+				}
+				break;
+
+			  case '\n':
+#if OSK
+			  case '\l':
+#else				  
+			  case '\r':
+#endif
+				build = tmpblk.c;
+				*build++ = '\n';
+				if (*o_autoindent)
+				{
+					/* figure out indent for next line */
+					pfetch(markline(cursor));
+					for (scan = ptext; *scan == ' ' || *scan == '\t'; )
+					{
+						*build++ = *scan++;
+					}
+
+					/* remove indent from this line, if blank */
+					if ((scan - ptext) >= markidx(cursor) && plen > 0)
+					{
+						to = cursor &= ~(BLKSIZE - 1);
+						delete(cursor, cursor + plen);
+					}
+				}
+				*build = 0;
+				if (cursor >= to && when != WHEN_VIREP)
+				{
+					add(cursor, tmpblk.c);
+				}
+				else
+				{
+					change(cursor, to, tmpblk.c);
+				}
+				redraw(cursor, TRUE);
+				to = cursor = (cursor & ~(BLKSIZE - 1))
+						+ BLKSIZE
+						+ (int)(build - tmpblk.c) - 1;
+				break;
+
+			  case ctrl('A'):
+			  case ctrl('P'):
+				if (cursor < to)
+				{
+					delete(cursor, to);
+				}
+				if (*key == ctrl('A'))
+				{
+					cutname('.');
+				}
+				to = cursor = paste(cursor, FALSE, TRUE) + 1L;
+				break;
+
+			  case ctrl('V'):
+				if (cursor >= to && when != WHEN_VIREP)
+				{
+					add(cursor, "^");
+				}
+				else
+				{
+					change(cursor, to, "^");
+					to = cursor + 1;
+				}
+				redraw(cursor, TRUE);
+				*key = getkey(0);
+				if (*key == '\n')
+				{
+					/* '\n' too hard to handle */
+#if OSK
+					*key = '\l';
+#else
+					*key = '\r';
+#endif
+				}
+				change(cursor, cursor + 1, key);
+				cursor++;
+				if (cursor > to)
+				{
+					to = cursor;
+				}
+				break;
+
+			  case ctrl('L'):
+			  case ctrl('R'):
+				redraw(MARK_UNSET, FALSE);
+				break;
+
+			  default:
+				if (cursor >= to && when != WHEN_VIREP)
+				{
+					add(cursor, key);
+					cursor++;
+					to = cursor;
+				}
+				else
+				{
+					pfetch(markline(cursor));
+					if (markidx(cursor) == plen)
+					{
+						add(cursor, key);
+					}
+					else
+					{
+#ifndef NO_DIGRAPH
+						*key = digraph(ptext[markidx(cursor)], *key);
+#endif
+						change(cursor, cursor + 1, key);
+					}
+					cursor++;
+				}
+#ifndef NO_SHOWMATCH
+				/* show matching "({[" if necessary */
+				if (*o_showmatch && strchr(")}]", *key))
+				{
+					redraw(cursor, TRUE);
+					m = m_match(cursor - 1, 0L);
+					if (markline(m) >= topline
+					 && markline(m) <= botline)
+					{
+						redraw(m, TRUE);
+						refresh();
+						sleep(1);
+					}
+				}
+#endif
+			} /* end switch(*key) */
+		} /* end for(;;) */
+BreakBreak:;
+		/* delete any excess characters */
+		if (cursor < to)
+		{
+#ifndef NO_EXTENSIONS
+			/* if we aren't in the middle of a change, start one! */
+			if (!inchg)
+			{
+				beforedo(FALSE);
+				inchg = TRUE;
+			}
+#endif
+			delete(cursor, to);
+		}
+
+	} /* end if doingdot else */
+
+	/* put the new text into a cut buffer for possible reuse */
+	if (!doingdot)
+	{
+		blksync();
+		cutname('.');
+		cut(from, cursor);
+	}
+
+	/* move to last char that we inputted, unless it was newline */
+	if (markidx(cursor) != 0)
+	{
+		cursor--;
+	}
+	redraw(cursor, FALSE);
+
+#ifndef NO_EXTENSIONS
+	if (quit)
+	{
+		/* if this is a nested "do", then cut it short */
+		abortdo();
+
+		/* exit, unless we can't write out the file */
+		cursor = v_xit(cursor, 0L, 'Z');
+	}
+#endif
+
+	rptlines = 0L;
+	return cursor;
+}
Index: /trunk/minix/commands/elvis/main.c
===================================================================
--- /trunk/minix/commands/elvis/main.c	(revision 9)
+++ /trunk/minix/commands/elvis/main.c	(revision 9)
@@ -0,0 +1,516 @@
+/* main.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains the main() function of vi */
+
+/* HACK! bcc needs to disable use of precompiled headers for this file,
+   or else command line args will not be passed to elvis */
+#if __BORLANDC__
+#include "borland.h"
+#endif
+
+#include "config.h"
+#include <setjmp.h>
+#include "vi.h"
+
+extern		trapint(); /* defined below */
+extern char	*getenv();
+jmp_buf		jmpenv;
+
+#ifndef NO_DIGRAPH
+static init_digraphs();
+#endif
+
+/*---------------------------------------------------------------------*/
+
+#if AMIGA
+# include "amiwild.c"
+main (argc, argv)
+#else
+# if VMS
+#  include "vmswild.c"
+main (argc, argv)
+# else
+void main(argc, argv)
+# endif
+#endif
+	int	argc;
+	char	*argv[];
+{
+	int	i;
+	char	*cmd = (char *)0;
+	char	*err = (char *)0;
+	char	*str;
+	char	*tag = (char *)0;
+
+	/* set mode to MODE_VI or MODE_EX depending on program name */
+	switch (argv[0][strlen(argv[0]) - 1])
+	{
+	  case 'x':			/* "ex" */
+		mode = MODE_EX;
+		break;
+
+	  case 'w':			/* "view" */
+		mode = MODE_VI;
+		*o_readonly = TRUE;
+		break;
+#ifndef NO_EXTENSIONS
+	  case 't':			/* "edit" or "input" */
+		mode = MODE_VI;
+		*o_inputmode = TRUE;
+		break;
+#endif
+	  default:			/* "vi" or "elvis" */
+		mode = MODE_VI;
+	}
+
+#ifndef DEBUG
+# ifdef	SIGQUIT
+	/* normally, we ignore SIGQUIT.  SIGINT is trapped later */
+	signal(SIGQUIT, SIG_IGN);
+# endif
+#endif
+
+	/* temporarily ignore SIGINT */
+	signal(SIGINT, SIG_IGN);
+
+	/* start curses */
+	initscr();
+	cbreak();
+	noecho();
+	scrollok(stdscr, TRUE);
+
+	/* arrange for deadly signals to be caught */
+# ifdef SIGHUP
+	signal(SIGHUP, (void(*)()) deathtrap);
+# endif
+# ifndef DEBUG
+#  ifdef SIGILL
+	signal(SIGILL, (void(*)()) deathtrap);
+#  endif
+#  ifdef SIGBUS
+	signal(SIGBUS, (void(*)()) deathtrap);
+#  endif
+#  ifdef SIGSEGV
+	signal(SIGSEGV, (void(*)()) deathtrap);
+#  endif
+#  ifdef SIGSYS
+	signal(SIGSYS, (void(*)()) deathtrap);
+#  endif
+# endif /* !DEBUG */
+# ifdef SIGPIPE
+	signal(SIGPIPE, (void(*)()) deathtrap);
+# endif
+# ifdef SIGTERM
+	signal(SIGTERM, (void(*)()) deathtrap);
+# endif
+# ifdef SIGUSR1
+	signal(SIGUSR1, (void(*)()) deathtrap);
+# endif
+# ifdef SIGUSR2
+	signal(SIGUSR2, (void(*)()) deathtrap);
+# endif
+
+	/* initialize the options - must be done after initscr(), so that
+	 * we can alter LINES and COLS if necessary.
+	 */
+	initopts();
+
+	/* map the arrow keys.  The KU,KD,KL,and KR variables correspond to
+	 * the :ku=: (etc.) termcap capabilities.  The variables are defined
+	 * as part of the curses package.
+	 */
+	if (has_KU) mapkey(has_KU, "k",    WHEN_VICMD|WHEN_INMV, "<Up>");
+	if (has_KD) mapkey(has_KD, "j",    WHEN_VICMD|WHEN_INMV, "<Down>");
+	if (has_KL) mapkey(has_KL, "h",    WHEN_VICMD|WHEN_INMV, "<Left>");
+	if (has_KR) mapkey(has_KR, "l",    WHEN_VICMD|WHEN_INMV, "<Right>");
+	if (has_HM) mapkey(has_HM, "^",    WHEN_VICMD|WHEN_INMV, "<Home>");
+	if (has_EN) mapkey(has_EN, "$",    WHEN_VICMD|WHEN_INMV, "<End>");
+	if (has_PU) mapkey(has_PU, "\002", WHEN_VICMD|WHEN_INMV, "<PageUp>");
+	if (has_PD) mapkey(has_PD, "\006", WHEN_VICMD|WHEN_INMV, "<PageDn>");
+	if (has_KI) mapkey(has_KI, "i",    WHEN_VICMD|WHEN_INMV, "<Insert>");
+#if MSDOS
+# if RAINBOW
+	if (!strcmp("rainbow", o_term))
+	{
+		mapkey("\033[1~",  "/",		WHEN_VICMD,		"<Find>");
+		mapkey("\033[3~",  "x",		WHEN_VICMD|WHEN_INMV,	"<Remove>");
+		mapkey("\033[4~",  "v",		WHEN_VICMD|WHEN_INMV,	"<Select>");
+		mapkey("\033[17~", ":sh\n",	WHEN_VICMD,		"<Intrpt>");
+		mapkey("\033[19~", ":q\n",	WHEN_VICMD,		"<Cancel>");
+		mapkey("\033[21~", "ZZ",	WHEN_VICMD,		"<Exit>");
+		mapkey("\033[26~", "V",		WHEN_VICMD|WHEN_INMV,	"<AddlOp>");
+		mapkey("\033[28~", "\\",	WHEN_VICMD|WHEN_INMV,	"<Help>");
+		mapkey("\033[29~", "K",		WHEN_VICMD|WHEN_INMV,	"<Do>");
+	}
+	else
+# endif /* RAINBOW */
+	{
+		mapkey("#S", "x", WHEN_VICMD|WHEN_INMV,	"<Delete>");
+		mapkey("#s", "B", WHEN_VICMD|WHEN_INMV,	"^<Left>");
+		mapkey("#t", "W", WHEN_VICMD|WHEN_INMV,	"^<Right>");
+	}
+#else /* not MSDOS */
+# if COHERENT
+	mapkey("\033[P", "x", WHEN_VICMD|WHEN_INMV, "<Del>");
+# else
+#if AMIGA
+	mapkey("\233?~", "\\",	WHEN_VICMD|WHEN_INMV,	"<Help>");
+#endif
+
+	if (ERASEKEY != '\177')
+	{
+		mapkey("\177", "x", WHEN_VICMD|WHEN_INMV, "<Del>");
+	}
+# endif
+#endif
+
+#ifndef NO_DIGRAPH
+	init_digraphs();
+#endif /* NO_DIGRAPH */
+
+	/* process any flags */
+	for (i = 1; i < argc && *argv[i] == '-'; i++)
+	{
+		switch (argv[i][1])
+		{
+		  case 'R':	/* readonly */
+			*o_readonly = TRUE;
+			break;
+
+		  case 'L':
+		  case 'r':	/* recover */
+			msg("Use the `elvrec` program to recover lost files");
+			endmsgs();
+			refresh();
+			endwin();
+			exit(0);
+			break;
+
+		  case 't':	/* tag */
+			if (argv[i][2])
+			{
+				tag = argv[i] + 2;
+			}
+			else
+			{
+				tag = argv[++i];
+			}
+			break;
+
+		  case 'v':	/* vi mode */
+			mode = MODE_VI;
+			break;
+
+		  case 'e':	/* ex mode */
+			mode = MODE_EX;
+			break;
+#ifndef NO_EXTENSIONS
+		  case 'i':	/* input mode */
+			*o_inputmode = TRUE;
+			break;
+#endif
+#ifndef NO_ERRLIST
+		  case 'm':	/* use "errlist" as the errlist */
+			if (argv[i][2])
+			{
+				err = argv[i] + 2;
+			}
+			else if (i + 1 < argc)
+			{
+				err = argv[++i];
+			}
+			else
+			{
+				err = "";
+			}
+			break;
+#endif
+#ifndef CRUNCH
+		 case 'c':	/* run the following command, later */
+			if (argv[i][2])
+			{
+				cmd = argv[i] + 2;
+			}
+			else
+			{
+				cmd = argv[++i];
+			}
+			break;
+
+		  case 'w':	/* set the window size */
+			if (argv[i][2])
+			{
+				*o_window = atoi(argv[i] + 2);
+				wset = TRUE;
+			}
+			else
+			{
+				*o_window = atoi(argv[++i]);
+				wset = TRUE;
+			}
+			break;
+#endif
+		  default:
+			msg("Ignoring unknown flag \"%s\"", argv[i]);
+		}
+	}
+
+	/* if we were given an initial ex command, save it... */
+	if (i < argc && *argv[i] == '+')
+	{
+		if (argv[i][1])
+		{
+			cmd = argv[i++] + 1;
+		}
+		else
+		{
+			cmd = "$"; /* "vi + file" means start at EOF */
+			i++;
+		}
+	}
+
+	/* the remaining args are file names. */
+	if (i < argc)
+	{
+		strcpy(args, argv[i]);
+		while (++i < argc && strlen(args) + 1 + strlen(argv[i]) < sizeof args)
+		{
+			strcat(args, " ");
+			strcat(args, argv[i]);
+		}
+#if MSDOS || TOS
+		/* expand wildcard characters, if necessary */
+		if (strchr(args, '*') || strchr(args, '?'))
+		{
+			strcpy(args, wildcard(args));
+		}
+#endif
+		strcpy(tmpblk.c, args);
+		cmd_args(MARK_UNSET, MARK_UNSET, CMD_ARGS, TRUE, tmpblk.c);
+	}
+	else
+	{
+		/* empty args list */
+		args[0] = '\0';
+		nargs = 1;
+		argno = -1;
+	}
+
+	/* perform the .exrc files and EXINIT environment variable */
+#ifdef SYSEXRC
+	doexrc(SYSEXRC);
+#endif
+#ifdef HMEXRC
+	str = getenv("HOME");
+	if (str && *str)
+	{
+		strcpy(tmpblk.c, str);
+		str = tmpblk.c + strlen(tmpblk.c);
+#if !VMS
+# if AMIGA	/* Don't SLASH a device. "Elvis:.exrc" */
+		if (str[-1] != COLON && str[-1] != SLASH)
+# else
+		if (str[-1] != SLASH)
+# endif
+		{
+			*str++ = SLASH;
+		}
+#endif
+		strcpy(str, HMEXRC);
+		doexrc(tmpblk.c);
+	}
+#endif
+#ifndef CRUNCH
+	if (*o_exrc)
+#endif
+	{
+		doexrc(EXRC);
+	}
+#ifdef EXINIT
+	str = getenv(EXINIT);
+	if (str)
+	{
+		exstring(str, strlen(str), ctrl('V'));
+	}
+#endif
+
+	/* search for a tag (or an error) now, if desired */
+	blkinit();
+	if (tag)
+	{
+		cmd_tag(MARK_FIRST, MARK_FIRST, CMD_TAG, 0, tag);
+	}
+#ifndef NO_ERRLIST
+	else if (err)
+	{
+		cmd_errlist(MARK_FIRST, MARK_FIRST, CMD_ERRLIST, 0, err);
+	}
+#endif
+
+	/* if no tag/err, or tag failed, then start with first arg */
+	if (tmpfd < 0)
+	{
+		/* start with first arg */
+		cmd_next(MARK_UNSET, MARK_UNSET, CMD_NEXT, FALSE, "");
+
+		/* pretend to do something, just to force a recoverable
+		 * version of the file out to disk
+		 */
+		ChangeText
+		{
+		}
+		clrflag(file, MODIFIED);
+	}
+
+	/* now we do the immediate ex command that we noticed before */
+	if (cmd)
+	{
+		doexcmd(cmd);
+	}
+
+	/* repeatedly call ex() or vi() (depending on the mode) until the
+	 * mode is set to MODE_QUIT
+	 */
+	while (mode != MODE_QUIT)
+	{
+		if (setjmp(jmpenv))
+		{
+			/* Maybe we just aborted a change? */
+			abortdo();
+		}
+		signal(SIGINT, (void(*)()) trapint);
+
+		switch (mode)
+		{
+		  case MODE_VI:
+			vi();
+			break;
+
+		  case MODE_EX:
+			ex();
+			break;
+#ifdef DEBUG
+		  default:
+			msg("mode = %d?", mode);
+			mode = MODE_QUIT;
+#endif
+		}
+	}
+
+	/* free up the cut buffers */
+	cutend();
+
+	/* end curses */
+#ifndef	NO_CURSORSHAPE
+	if (has_CQ)
+		do_CQ();
+#endif
+	endmsgs();
+	move(LINES - 1, 0);
+	clrtoeol();
+	refresh();
+	endwin();
+
+	exit(0);
+	/*NOTREACHED*/
+}
+
+
+/*ARGSUSED*/
+int trapint(signo)
+	int	signo;
+{
+	beep();
+	resume_curses(FALSE);
+	abortdo();
+#if OSK
+	sigmask(-1);
+#endif
+#if TURBOC || __GNUC__ || _ANSI
+	signal(signo, (void (*)())trapint);
+#else
+	signal(signo, trapint);
+#endif
+	doingglobal = FALSE;
+
+	longjmp(jmpenv, 1);
+
+	return 0;
+}
+
+
+
+#ifndef NO_DIGRAPH
+
+/* This stuff us used to build the default digraphs table. */
+static char	digtable[][4] =
+{
+# ifdef CS_IBMPC
+	"C,\200",	"u\"\1",	"e'\2",		"a^\3",
+	"a\"\4",	"a`\5",		"a@\6",		"c,\7",
+	"e^\10",	"e\"\211",	"e`\12",	"i\"\13",
+	"i^\14",	"i`\15",	"A\"\16",	"A@\17",
+	"E'\20",	"ae\21",	"AE\22",	"o^\23",
+	"o\"\24",	"o`\25",	"u^\26",	"u`\27",
+	"y\"\30",	"O\"\31",	"U\"\32",	"a'\240",
+	"i'!",		"o'\"",		"u'#",		"n~$",
+	"N~%",		"a-&",		"o-'",		"~?(",
+	"~!-",		"\"<.",		"\">/",
+#  ifdef CS_SPECIAL
+	"2/+",		"4/,",		"^+;",		"^q<",
+	"^c=",		"^r>",		"^t?",		"pp]",
+	"^^^",		"oo_",		"*a`",		"*ba",
+	"*pc",		"*Sd",		"*se",		"*uf",
+	"*tg",		"*Ph",		"*Ti",		"*Oj",
+	"*dk",		"*Hl",		"*hm",		"*En",
+	"*No",		"eqp",		"pmq",		"ger",
+	"les",		"*It",		"*iu",		"*/v",
+	"*=w",		"sq{",		"^n|",		"^2}",
+	"^3~",		"^_\377",
+#  endif /* CS_SPECIAL */
+# endif /* CS_IBMPC */
+# ifdef CS_LATIN1
+	"~!!",		"a-*",		"\">+",		"o-:",
+	"\"<>",		"~??",
+
+	"A`@",		"A'A",		"A^B",		"A~C",
+	"A\"D",		"A@E",		"AEF",		"C,G",
+	"E`H",		"E'I",		"E^J",		"E\"K",
+	"I`L",		"I'M",		"I^N",		"I\"O",
+	"-DP",		"N~Q",		"O`R",		"O'S",
+	"O^T",		"O~U",		"O\"V",		"O/X",
+	"U`Y",		"U'Z",		"U^[",		"U\"\\",
+	"Y'_",
+
+	"a``",		"a'a",		"a^b",		"a~c",
+	"a\"d",		"a@e",		"aef",		"c,g",
+	"e`h",		"e'i",		"e^j",		"e\"k",
+	"i`l",		"i'm",		"i^n",		"i\"o",
+	"-dp",		"n~q",		"o`r",		"o's",
+	"o^t",		"o~u",		"o\"v",		"o/x",
+	"u`y",		"u'z",		"u^{",		"u\"|",
+	"y'~",
+# endif /* CS_LATIN1 */
+	""
+};
+
+static init_digraphs()
+{
+	int	i;
+
+	for (i = 0; *digtable[i]; i++)
+	{
+		do_digraph(FALSE, digtable[i]);
+	}
+	do_digraph(FALSE, (char *)0);
+	return 0;
+}
+#endif /* NO_DIGRAPH */
Index: /trunk/minix/commands/elvis/misc.c
===================================================================
--- /trunk/minix/commands/elvis/misc.c	(revision 9)
+++ /trunk/minix/commands/elvis/misc.c	(revision 9)
@@ -0,0 +1,103 @@
+/* misc.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains functions which didn't seem happy anywhere else */
+
+#include "config.h"
+#include "vi.h"
+
+
+/* find a particular line & return a pointer to a copy of its text */
+char *fetchline(line)
+	long	line;	/* line number of the line to fetch */
+{
+	int		i;
+	REG char	*scan;	/* used to search for the line in a BLK */
+	long		l;	/* line number counter */
+	static BLK	buf;	/* holds ONLY the selected line (as string) */
+	REG char	*cpy;	/* used while copying the line */
+	static long	nextline;	/* }  These four variables are used */
+	static long	chglevel;	/*  } to implement a shortcut when  */
+	static char	*nextscan;	/*  } consecutive lines are fetched */
+	static long	nextlnum;	/* }                                */
+
+	/* can we do a shortcut? */
+	if (changes == chglevel && line == nextline)
+	{
+		scan = nextscan;
+	}
+	else
+	{
+		/* scan lnum[] to determine which block its in */
+		for (i = 1; line > lnum[i]; i++)
+		{
+		}
+		nextlnum = lnum[i];
+
+		/* fetch text of the block containing that line */
+		scan = blkget(i)->c;
+
+		/* find the line in the block */
+		for (l = lnum[i - 1]; ++l < line; )
+		{
+			while (*scan++ != '\n')
+			{
+			}
+		}
+	}
+
+	/* copy it into a block by itself, with no newline */
+	for (cpy = buf.c; *scan != '\n'; )
+	{
+		*cpy++ = *scan++;
+	}
+	*cpy = '\0';
+
+	/* maybe speed up the next call to fetchline() ? */
+	if (line < nextlnum)
+	{
+		nextline = line + 1;
+		chglevel = changes;
+		nextscan = scan + 1;
+	}
+	else
+	{
+		nextline = 0;
+	}
+
+	/* Calls to fetchline() interfere with calls to pfetch().  Make sure
+	 * that pfetch() resets itself on its next invocation.
+	 */
+	pchgs = 0L;
+
+	/* Return a pointer to the line's text */
+	return buf.c;
+}
+
+
+/* error message from the regexp code */
+void regerror(txt)
+	char	*txt;	/* an error message */
+{
+	msg("RE error: %s", txt);
+}
+
+/* This function is equivelent to the pfetch() macro */
+void	pfetch(l)
+	long	l;	/* line number of line to fetch */
+{
+	if(l != pline || changes != pchgs)
+	{
+		pline = (l);
+		ptext = fetchline(pline);
+		plen = strlen(ptext);
+		pchgs = changes;
+	}
+}
Index: /trunk/minix/commands/elvis/modify.c
===================================================================
--- /trunk/minix/commands/elvis/modify.c	(revision 9)
+++ /trunk/minix/commands/elvis/modify.c	(revision 9)
@@ -0,0 +1,474 @@
+/* modify.c */
+
+/* This file contains the low-level file modification functions:
+ *	delete(frommark, tomark)	- removes line or portions of lines
+ *	add(frommark, text)		- inserts new text
+ *	change(frommark, tomark, text)	- delete, then add
+ */
+
+#include "config.h"
+#include "vi.h"
+
+#ifdef DEBUG2
+# include <stdio.h>
+static FILE *dbg;
+
+/*VARARGS1*/
+debout(msg, arg1, arg2, arg3, arg4, arg5)
+	char	*msg, *arg1, *arg2, *arg3, *arg4, *arg5;
+{
+	if (!dbg)
+	{
+		dbg = fopen("debug.out", "w");
+		if (!dbg)
+			return;
+		setbuf(dbg, (FILE *)0);
+	}
+	fprintf(dbg, msg, arg1, arg2, arg3, arg4, arg5);
+}
+#endif /* DEBUG2 */
+
+/* delete a range of text from the file */
+void delete(frommark, tomark)
+	MARK		frommark;	/* first char to be deleted */
+	MARK		tomark;		/* AFTER last char to be deleted */
+{
+	int		i;		/* used to move thru logical blocks */
+	REG char	*scan;		/* used to scan thru text of the blk */
+	REG char	*cpy;		/* used when copying chars */
+	BLK		*blk;		/* a text block */
+	long		l;		/* a line number */
+	MARK		m;		/* a traveling version of frommark */
+
+#ifdef DEBUG2
+	debout("delete(%ld.%d, %ld.%d)\n", markline(frommark), markidx(frommark), markline(tomark), markidx(tomark));
+#endif
+
+	/* if not deleting anything, quit now */
+	if (frommark == tomark)
+	{
+		return;
+	}
+
+	/* This is a change */
+	changes++;
+	significant = TRUE;
+
+	/* supply clues to the redraw module */
+	redrawrange(markline(frommark), markline(tomark), markline(frommark));
+
+	/* adjust marks 'a through 'z and '' as needed */
+	l = markline(tomark);
+	for (i = 0; i < NMARKS; i++)
+	{
+		if (mark[i] < frommark)
+		{
+			continue;
+		}
+		else if (mark[i] < tomark)
+		{
+			mark[i] = MARK_UNSET;
+		}
+		else if (markline(mark[i]) == l)
+		{
+			if (markline(frommark) == l)
+			{
+				mark[i] -= markidx(tomark) - markidx(frommark);
+			}
+			else
+			{
+				mark[i] -= markidx(tomark);
+			}
+		}
+		else
+		{
+			mark[i] -= MARK_AT_LINE(l - markline(frommark));
+		}
+	}
+
+	/* Reporting... */
+	if (markidx(frommark) == 0 && markidx(tomark) == 0)
+	{
+		rptlines = markline(tomark) - markline(frommark);
+		rptlabel = "deleted";
+	}
+
+	/* find the block containing frommark */
+	l = markline(frommark);
+	for (i = 1; lnum[i] < l; i++)
+	{
+	}
+
+	/* process each affected block... */
+	for (m = frommark;
+	     m < tomark && lnum[i] < INFINITY;
+	     m = MARK_AT_LINE(lnum[i - 1] + 1))
+	{
+		/* fetch the block */
+		blk = blkget(i);
+
+		/* find the mark in the block */
+		scan = blk->c;
+		for (l = markline(m) - lnum[i - 1] - 1; l > 0; l--)
+		{
+			while (*scan++ != '\n')
+			{
+			}
+		}
+		scan += markidx(m);
+
+		/* figure out where the changes to this block end */
+		if (markline(tomark) > lnum[i])
+		{
+			cpy = blk->c + BLKSIZE;
+		}
+		else if (markline(tomark) == markline(m))
+		{
+			cpy = scan - markidx(m) + markidx(tomark);
+		}
+		else
+		{
+			cpy = scan;
+			for (l = markline(tomark) - markline(m);
+			     l > 0;
+			     l--)
+			{
+				while (*cpy++ != '\n')
+				{
+				}
+			}
+			cpy += markidx(tomark);
+		}
+
+		/* delete the stuff by moving chars within this block */
+		while (cpy < blk->c + BLKSIZE)
+		{
+			*scan++ = *cpy++;
+		}
+		while (scan < blk->c + BLKSIZE)
+		{
+			*scan++ = '\0';
+		}
+
+		/* adjust tomark to allow for lines deleted from this block */
+		tomark -= MARK_AT_LINE(lnum[i] + 1 - markline(m));
+
+		/* if this block isn't empty now, then advance i */
+		if (*blk->c)
+		{
+			i++;
+		}
+
+		/* the buffer has changed.  Update hdr and lnum. */
+		blkdirty(blk);
+	}
+
+	/* must have at least 1 line */
+	if (nlines == 0)
+	{
+		blk = blkadd(1);
+		blk->c[0] = '\n';
+		blkdirty(blk);
+		cursor = MARK_FIRST;
+	}
+}
+
+
+/* add some text at a specific place in the file */
+void add(atmark, newtext)
+	MARK		atmark;		/* where to insert the new text */
+	char		*newtext;	/* NUL-terminated string to insert */
+{
+	REG char	*scan;		/* used to move through string */
+	REG char	*build;		/* used while copying chars */
+	int		addlines;	/* number of lines we're adding */
+	int		lastpart;	/* size of last partial line */
+	BLK		*blk;		/* the block to be modified */
+	int		blkno;		/* the logical block# of (*blk) */
+	REG char	*newptr;	/* where new text starts in blk */
+	BLK		buf;		/* holds chars from orig blk */
+	BLK		linebuf;	/* holds part of line that didn't fit */
+	BLK		*following;	/* the BLK following the last BLK */
+	int		i;
+	long		l;
+
+#ifdef DEBUG2
+	debout("add(%ld.%d, \"%s\")\n", markline(atmark), markidx(atmark), newtext);
+#endif
+#ifdef lint
+	buf.c[0] = 0;
+#endif
+	/* if not adding anything, return now */
+	if (!*newtext)
+	{
+		return;
+	}
+
+	/* This is a change */
+	changes++;
+	significant = TRUE;
+
+	/* count the number of lines in the new text */
+	for (scan = newtext, lastpart = addlines = 0; *scan; )
+	{
+		if (*scan++ == '\n')
+		{
+			addlines++;
+			lastpart = 0;
+		}
+		else
+		{
+			lastpart++;
+		}
+	}
+
+	/* Reporting... */
+	if (lastpart == 0 && markidx(atmark) == 0)
+	{
+		rptlines = addlines;
+		rptlabel = "added";
+	}
+
+	/* extract the line# from atmark */
+	l = markline(atmark);
+
+	/* supply clues to the redraw module */
+	if ((markidx(atmark) == 0 && lastpart == 0) || addlines == 0)
+	{
+		redrawrange(l, l, l + addlines);
+	}
+	else
+	{
+		/* make sure the last line gets redrawn -- it was
+		 * split, so its appearance has changed
+		 */
+		redrawrange(l, l + 1L, l + addlines + 1L);
+	}
+
+	/* adjust marks 'a through 'z and '' as needed */
+	for (i = 0; i < NMARKS; i++)
+	{
+		if (mark[i] < atmark)
+		{
+			/* earlier line, or earlier in same line: no change */
+			continue;
+		}
+		else if (markline(mark[i]) > l)
+		{
+			/* later line: move down a whole number of lines */
+			mark[i] += MARK_AT_LINE(addlines);
+		}
+		else
+		{
+			/* later in same line */
+			if (addlines > 0)
+			{
+				/* multi-line add, which split this line:
+				 * move down, and possibly left or right,
+				 * depending on where the split was and how
+				 * much text was inserted after the last \n
+				 */
+				mark[i] += MARK_AT_LINE(addlines) + lastpart - markidx(atmark);
+			}
+			else
+			{
+				/* totally within this line: move right */
+				mark[i] += lastpart;
+			}
+		}
+	}
+
+	/* get the block to be modified */
+	for (blkno = 1; lnum[blkno] < l && lnum[blkno + 1] < INFINITY; blkno++)
+	{
+	}
+	blk = blkget(blkno);
+	buf = *blk;
+
+	/* figure out where the new text starts */
+	for (newptr = buf.c, l = markline(atmark) - lnum[blkno - 1] - 1;
+	     l > 0;
+	     l--)
+	{
+		while (*newptr++ != '\n')
+		{
+		}
+	}
+	newptr += markidx(atmark);
+
+	/* keep start of old block */
+	build = blk->c + (int)(newptr - buf.c);
+
+	/* fill this block (or blocks) from the newtext string */
+	while (*newtext)
+	{
+		while (*newtext && build < blk->c + BLKSIZE - 1)
+		{
+			*build++ = *newtext++;
+		}
+		if (*newtext)
+		{
+			/* save the excess */
+			for (scan = linebuf.c + BLKSIZE;
+			     build > blk->c && build[-1] != '\n';
+			     )
+			{
+				*--scan = *--build;
+			}
+
+			/* write the block */
+			while (build < blk->c + BLKSIZE)
+			{
+				*build++ = '\0';
+			}
+			blkdirty(blk);
+
+			/* add another block */
+			blkno++;
+			blk = blkadd(blkno);
+
+			/* copy in the excess from last time */
+			for (build = blk->c; scan < linebuf.c + BLKSIZE; )
+			{
+				*build++ = *scan++;
+			}
+		}
+	}
+
+	/* fill this block(s) from remainder of orig block */
+	while (newptr < buf.c + BLKSIZE && *newptr)
+	{
+		while (newptr < buf.c + BLKSIZE
+		    && *newptr
+		    && build < blk->c + BLKSIZE - 1)
+		{
+			*build++ = *newptr++;
+		}
+		if (newptr < buf.c + BLKSIZE && *newptr)
+		{
+			/* save the excess */
+			for (scan = linebuf.c + BLKSIZE;
+			     build > blk->c && build[-1] != '\n';
+			     )
+			{
+				*--scan = *--build;
+			}
+
+			/* write the block */
+			while (build < blk->c + BLKSIZE)
+			{
+				*build++ = '\0';
+			}
+			blkdirty(blk);
+
+			/* add another block */
+			blkno++;
+			blk = blkadd(blkno);
+
+			/* copy in the excess from last time */
+			for (build = blk->c; scan < linebuf.c + BLKSIZE; )
+			{
+				*build++ = *scan++;
+			}
+		}
+	}
+
+	/* see if we can combine our last block with the following block */
+	if (lnum[blkno] < nlines && lnum[blkno + 1] - lnum[blkno] < (BLKSIZE >> 6))
+	{
+		/* hey, we probably can!  Get the following block & see... */
+		following = blkget(blkno + 1);
+		if (strlen(following->c) + (build - blk->c) < BLKSIZE - 1)
+		{
+			/* we can!  Copy text from following to blk */
+			for (scan = following->c; *scan; )
+			{
+				*build++ = *scan++;
+			}
+			while (build < blk->c + BLKSIZE)
+			{
+				*build++ = '\0';
+			}
+			blkdirty(blk);
+
+			/* pretend the following was the last blk */
+			blk = following;
+			build = blk->c;
+		}
+	}
+
+	/* that last block is dirty by now */
+	while (build < blk->c + BLKSIZE)
+	{
+		*build++ = '\0';
+	}
+	blkdirty(blk);
+}
+
+
+/* change the text of a file */
+void change(frommark, tomark, newtext)
+	MARK	frommark, tomark;
+	char	*newtext;
+{
+	int	i;
+	long	l;
+	char	*text;
+	BLK	*blk;
+
+#ifdef DEBUG2
+	debout("change(%ld.%d, %ld.%d, \"%s\")\n", markline(frommark), markidx(frommark), markline(tomark), markidx(tomark), newtext);
+#endif
+
+	/* optimize for single-character replacement */
+	if (frommark + 1 == tomark && newtext[0] && !newtext[1] && newtext[0] != '\n')
+	{
+		/* find the block containing frommark */
+		l = markline(frommark);
+		for (i = 1; lnum[i] < l; i++)
+		{
+		}
+
+		/* get the block */
+		blk = blkget(i);
+
+		/* find the line within the block */
+		for (text = blk->c, i = l - lnum[i - 1] - 1; i > 0; text++)
+		{
+			if (*text == '\n')
+			{
+				i--;
+			}
+		}
+
+		/* replace the char */
+		text += markidx(frommark);
+		if (*text == newtext[0])
+		{
+			/* no change was needed - same char */
+			return;
+		}
+		else if (*text != '\n')
+		{
+			/* This is a change */
+			changes++;
+			significant = TRUE;
+			ChangeText
+			{
+				*text = newtext[0];
+				blkdirty(blk);
+			}
+			redrawrange(markline(frommark), markline(tomark), markline(frommark));
+			return;
+		}
+		/* else it is a complex change involving newline... */
+	}
+
+	/* couldn't optimize, so do delete & add */
+	ChangeText
+	{
+		delete(frommark, tomark);
+		add(frommark, newtext);
+		rptlabel = "changed";
+	}
+}
Index: /trunk/minix/commands/elvis/move1.c
===================================================================
--- /trunk/minix/commands/elvis/move1.c	(revision 9)
+++ /trunk/minix/commands/elvis/move1.c	(revision 9)
@@ -0,0 +1,585 @@
+/* move1.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains most movement functions */
+
+#include "config.h"
+#include "vi.h"
+#include "ctype.h"
+
+MARK	m_updnto(m, cnt, cmd)
+	MARK	m;	/* movement is relative to this mark */
+	long	cnt;	/* a numeric argument */
+	char	cmd;	/* the command character */
+{
+	DEFAULT(cmd == 'G' ? nlines : 1L);
+
+	/* move up or down 'cnt' lines */
+	switch (cmd)
+	{
+	  case ctrl('P'):
+	  case '-':
+	  case 'k':
+		m -= MARK_AT_LINE(cnt);
+		break;
+
+	  case 'G':
+		if (cnt < 1L || cnt > nlines)
+		{
+			msg("Only %ld lines", nlines);
+			return MARK_UNSET;
+		}
+		m = MARK_AT_LINE(cnt);
+		break;
+
+	  case '_':
+		cnt--;
+		/* fall through... */
+
+	  default:
+		m += MARK_AT_LINE(cnt);
+	}
+
+	/* if that left us screwed up, then fail */
+	if (m < MARK_FIRST || markline(m) > nlines)
+	{
+		return MARK_UNSET;
+	}
+
+	return m;
+}
+
+/*ARGSUSED*/
+MARK	m_right(m, cnt, key, prevkey)
+	MARK	m;	/* movement is relative to this mark */
+	long	cnt;	/* a numeric argument */
+	int	key;	/* movement keystroke */
+	int	prevkey;/* operator keystroke, or 0 if none */
+{
+	int		idx;	/* index of the new cursor position */
+
+	DEFAULT(1);
+
+	/* If used with an operator, then move 1 less character, since the 'l'
+	 * command includes the character that it moves onto.
+	 */
+	if (prevkey != '\0')
+	{
+		cnt--;
+	}
+
+	/* move to right, if that's OK */
+	pfetch(markline(m));
+	idx = markidx(m) + cnt;
+	if (idx < plen)
+	{
+		m += cnt;
+	}
+	else
+	{
+		return MARK_UNSET;
+	}
+
+	return m;
+}
+
+/*ARGSUSED*/
+MARK	m_left(m, cnt)
+	MARK	m;	/* movement is relative to this mark */
+	long	cnt;	/* a numeric argument */
+{
+	DEFAULT(1);
+
+	/* move to the left, if that's OK */
+	if (markidx(m) >= cnt)
+	{
+		m -= cnt;
+	}
+	else
+	{
+		return MARK_UNSET;
+	}
+
+	return m;
+}
+
+/*ARGSUSED*/
+MARK	m_tocol(m, cnt, cmd)
+	MARK	m;	/* movement is relative to this mark */
+	long	cnt;	/* a numeric argument */
+	int	cmd;	/* either ctrl('X') or '|' */
+{
+	char	*text;	/* text of the line */
+	int	col;	/* column number */
+	int	idx;	/* index into the line */
+
+
+	/* if doing ^X, then adjust for sideways scrolling */
+	if (cmd == ctrl('X'))
+	{
+		DEFAULT(*o_columns & 0xff);
+		cnt += leftcol;
+	}
+	else
+	{
+		DEFAULT(1);
+	}
+
+	/* internally, columns are numbered 0..COLS-1, not 1..COLS */
+	cnt--;
+
+	/* if 0, that's easy */
+	if (cnt == 0)
+	{
+		m &= ~(BLKSIZE - 1);
+		return m;
+	}
+
+	/* find that column within the line */
+	pfetch(markline(m));
+	text = ptext;
+	for (col = idx = 0; col < cnt && *text; text++, idx++)
+	{
+		if (*text == '\t' && !*o_list)
+		{
+			col += *o_tabstop;
+			col -= col % *o_tabstop;
+		}
+		else if (UCHAR(*text) < ' ' || *text == '\177')
+		{
+			col += 2;
+		}
+#ifndef NO_CHARATTR
+		else if (text[0] == '\\' && text[1] == 'f' && text[2] && *o_charattr)
+		{
+			text += 2; /* plus one more as part of for loop */
+		}
+#endif
+		else
+		{
+			col++;
+		}
+	}
+	if (!*text)
+	{
+		/* the desired column was past the end of the line, so
+		 * act like the user pressed "$" instead.
+		 */
+		return m | (BLKSIZE - 1);
+	}
+	else
+	{
+		m = (m & ~(BLKSIZE - 1)) + idx;
+	}
+	return m;
+}
+
+/*ARGSUSED*/
+MARK	m_front(m, cnt)
+	MARK	m;	/* movement is relative to this mark */
+	long	cnt;	/* a numeric argument (ignored) */
+{
+	char	*scan;
+
+	/* move to the first non-whitespace character */
+	pfetch(markline(m));
+	scan = ptext;
+	m &= ~(BLKSIZE - 1);
+	while (*scan == ' ' || *scan == '\t')
+	{
+		scan++;
+		m++;
+	}
+
+	return m;
+}
+
+/*ARGSUSED*/
+MARK	m_rear(m, cnt)
+	MARK	m;	/* movement is relative to this mark */
+	long	cnt;	/* a numeric argument (ignored) */
+{
+	/* Try to move *EXTREMELY* far to the right.  It is fervently hoped
+	 * that other code will convert this to a more reasonable MARK before
+	 * anything tries to actually use it.  (See adjmove() in vi.c)
+	 */
+	return m | (BLKSIZE - 1);
+}
+
+#ifndef NO_SENTENCE
+static int isperiod(ptr)
+	char	*ptr;	/* pointer to possible sentence-ender */
+{
+	/* if not '.', '?', or '!', then it isn't a sentence ender */
+	if (*ptr != '.' && *ptr != '?' && *ptr != '!')
+	{
+		return FALSE;
+	}
+
+	/* skip any intervening ')', ']', or '"' characters */
+	do
+	{
+		ptr++;
+	} while (*ptr == ')' || *ptr == ']' || *ptr == '"');
+
+	/* do we have two spaces or EOL? */
+	if (!*ptr || ptr[0] == ' ' && ptr[1] == ' ')
+	{
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/*ARGSUSED*/
+MARK	m_sentence(m, cnt, cmd)
+	MARK	m;	/* movement is relative to this mark */
+	long	cnt;	/* a numeric argument */
+	int	cmd;	/* either '(' or ')' */
+{
+	REG char	*text;
+	REG long	l;
+
+	DEFAULT(1);
+
+	/* If '(' command, then move back one word, so that if we hit '(' at
+	 * the start of a sentence we don't simply stop at the end of the
+	 * previous sentence and bounce back to the start of this one again.
+	 */
+	if (cmd == '(')
+	{
+		m = m_bword(m, 1L, 'b');
+		if (!m)
+		{
+			return m;
+		}
+	}
+
+	/* get the current line */
+	l = markline(m);
+	pfetch(l);
+	text = ptext + markidx(m);
+
+	/* for each requested sentence... */
+	while (cnt-- > 0)
+	{
+		/* search forward for one of [.?!] followed by spaces or EOL */
+		do
+		{
+			if (cmd == ')')
+			{
+				/* move forward, wrap at end of line */
+				if (!text[0])
+				{
+					if (l >= nlines)
+					{
+						return MARK_UNSET;
+					}
+					l++;
+					pfetch(l);
+					text = ptext;
+				}
+				else
+				{
+					text++;
+				}
+			}
+			else
+			{
+				/* move backward, wrap at beginning of line */
+				if (text == ptext)
+				{
+					do
+					{
+						if (l <= 1)
+						{
+							return MARK_FIRST;
+						}
+						l--;
+						pfetch(l);
+					} while (!*ptext);
+					text = ptext + plen - 1;
+				}
+				else
+				{
+					text--;
+				}
+			}
+		} while (!isperiod(text));
+	}
+
+	/* construct a mark for this location */
+	m = buildmark(text);
+
+	/* move forward to the first word of the next sentence */
+	m = m_fword(m, 1L, 'w', '\0');
+
+	return m;
+}
+#endif
+
+MARK	m_paragraph(m, cnt, cmd)
+	MARK	m;	/* movement is relative to this mark */
+	long	cnt;	/* a numeric argument */
+	int	cmd;	/* either '{' or '}' */
+{
+	char	*text;	/* text of the current line */
+	char	*pscn;	/* used to scan thru value of "paragraphs" option */
+	long	l, ol;	/* current line number, original line number */
+	int	dir;	/* -1 if we're moving up, or 1 if down */
+	char	col0;	/* character to expect in column 0 */
+#ifndef NO_SENTENCE
+# define SENTENCE(x)	(x)
+	char	*list;	/* either o_sections or o_paragraph */
+#else
+# define SENTENCE(x)
+#endif
+
+	DEFAULT(1);
+
+	/* set the direction, based on the command */
+	switch (cmd)
+	{
+	  case '{':
+		dir = -1;
+		col0 = '\0';
+		SENTENCE(list = o_paragraphs); 
+		break;
+
+	  case '}':
+		dir = 1;
+		col0 = '\0';
+		SENTENCE(list = o_paragraphs); 
+		break;
+
+	  case '[':
+		if (getkey(0) != '[')
+		{
+			return MARK_UNSET;
+		}
+		dir = -1;
+		col0 = '{';
+		SENTENCE(list = o_sections); 
+		break;
+
+	  case ']':
+		if (getkey(0) != ']')
+		{
+			return MARK_UNSET;
+		}
+		dir = 1;
+		col0 = '{';
+		SENTENCE(list = o_sections); 
+		break;
+	}
+	ol = l = markline(m);
+
+	/* for each paragraph that we want to travel through... */
+	while (l > 0 && l <= nlines && cnt-- > 0)
+	{
+		/* skip blank lines between paragraphs */
+		while (l > 0 && l <= nlines && col0 == *(text = fetchline(l)))
+		{
+			l += dir;
+		}
+
+		/* skip non-blank lines that aren't paragraph separators
+		 */
+		do
+		{
+#ifndef NO_SENTENCE
+			if (*text == '.' && l != ol)
+			{
+				for (pscn = list; pscn[0] && pscn[1]; pscn += 2)
+				{
+					if (pscn[0] == text[1] && pscn[1] == text[2])
+					{
+						pscn = (char *)0;
+						goto BreakBreak;
+					}
+				}
+			}
+#endif
+			l += dir;
+		} while (l > 0 && l <= nlines && col0 != *(text = fetchline(l)));
+BreakBreak:	;
+	}
+
+	if (l > nlines)
+	{
+		m = MARK_LAST;
+	}
+	else if (l <= 0)
+	{
+		m = MARK_FIRST;
+	}
+	else
+	{
+		m = MARK_AT_LINE(l);
+	}
+	return m;
+}
+
+
+/*ARGSUSED*/
+MARK	m_match(m, cnt)
+	MARK	m;	/* movement is relative to this mark */
+	long	cnt;	/* a numeric argument (normally 0) */
+{
+	long	l;
+	REG char	*text;
+	REG char	match;
+	REG char	nest;
+	REG int		count;
+
+#ifndef NO_EXTENSIONS
+	/* if we're given a number, then treat it as a percentage of the file */
+	if (cnt > 0)
+	{
+		/* make sure it is a reasonable number */
+		if (cnt > 100)
+		{
+			msg("can only be from 1%% to 100%%");
+			return MARK_UNSET;
+		}
+
+		/* return the appropriate line number */
+		l = (nlines - 1L) * cnt / 100L + 1L;
+		return MARK_AT_LINE(l);
+	}
+#endif /* undef NO_EXTENSIONS */
+
+	/* get the current line */
+	l = markline(m);
+	pfetch(l);
+	text = ptext + markidx(m);
+
+	/* search forward within line for one of "[](){}" */
+	for (match = '\0'; !match && *text; text++)
+	{
+		/* tricky way to recognize 'em in ASCII */
+		nest = *text;
+		if ((nest & 0xdf) == ']' || (nest & 0xdf) == '[')
+		{
+			match = nest ^ ('[' ^ ']');
+		}
+		else if ((nest & 0xfe) == '(')
+		{
+			match = nest ^ ('(' ^ ')');
+		}
+		else
+		{
+			match = 0;
+		}
+	}
+	if (!match)
+	{
+		return MARK_UNSET;
+	}
+	text--;
+
+	/* search forward or backward for match */
+	if (match == '(' || match == '[' || match == '{')
+	{
+		/* search backward */
+		for (count = 1; count > 0; )
+		{
+			/* wrap at beginning of line */
+			if (text == ptext)
+			{
+				do
+				{
+					if (l <= 1L)
+					{
+						return MARK_UNSET;
+					}
+					l--;
+					pfetch(l);
+				} while (!*ptext);
+				text = ptext + plen - 1;
+			}
+			else
+			{
+				text--;
+			}
+
+			/* check the char */
+			if (*text == match)
+				count--;
+			else if (*text == nest)
+				count++;
+		}
+	}
+	else
+	{
+		/* search forward */
+		for (count = 1; count > 0; )
+		{
+			/* wrap at end of line */
+			if (!*text)
+			{
+				if (l >= nlines)
+				{
+					return MARK_UNSET;
+				}
+				l++;
+				pfetch(l);
+				text = ptext;
+			}
+			else
+			{
+				text++;
+			}
+
+			/* check the char */
+			if (*text == match)
+				count--;
+			else if (*text == nest)
+				count++;
+		}
+	}
+
+	/* construct a mark for this place */
+	m = buildmark(text);
+	return m;
+}
+
+/*ARGSUSED*/
+MARK	m_tomark(m, cnt, key)
+	MARK	m;	/* movement is relative to this mark */
+	long	cnt;	/* (ignored) */
+	int	key;	/* keystroke - the mark to move to */
+{
+	/* mark '' is a special case */
+	if (key == '\'' || key == '`')
+	{
+		if (mark[26] == MARK_UNSET)
+		{
+			return MARK_FIRST;
+		}
+		else
+		{
+			return mark[26];
+		}
+	}
+
+	/* if not a valid mark number, don't move */
+	if (key < 'a' || key > 'z')
+	{
+		return MARK_UNSET;
+	}
+
+	/* return the selected mark -- may be MARK_UNSET */
+	if (!mark[key - 'a'])
+	{
+		msg("mark '%c is unset", key);
+	}
+	return mark[key - 'a'];
+}
+
Index: /trunk/minix/commands/elvis/move2.c
===================================================================
--- /trunk/minix/commands/elvis/move2.c	(revision 9)
+++ /trunk/minix/commands/elvis/move2.c	(revision 9)
@@ -0,0 +1,291 @@
+/* move2.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This function contains the movement functions that perform RE searching */
+
+#include "config.h"
+#include "vi.h"
+#include "regexp.h"
+
+extern long	atol();
+
+static regexp	*re;	/* compiled version of the pattern to search for */
+static		prevsf;	/* boolean: previous search direction was forward? */
+
+#ifndef NO_EXTENSIONS
+/*ARGSUSED*/
+MARK m_wsrch(word, m, cnt)
+	char	*word;	/* the word to search for */
+	MARK	m;	/* the starting point */
+	int	cnt;	/* ignored */
+{
+	char	buffer[30];
+
+	/* wrap \< and \> around the word */
+	strcpy(buffer, "/\\<");
+	strcat(buffer, word);
+	strcat(buffer, "\\>");
+
+	/* show the searched-for word on the bottom line */
+	move(LINES - 1, 0);
+	qaddstr(buffer);
+	clrtoeol();
+	refresh();
+
+	/* search for the word */
+	return m_fsrch(m, buffer);
+}
+#endif
+
+MARK	m_nsrch(m)
+	MARK	m;	/* where to start searching */
+{
+	if (prevsf)
+	{
+		m = m_fsrch(m, (char *)0);
+		prevsf = TRUE;
+	}
+	else
+	{
+		m = m_bsrch(m, (char *)0);
+		prevsf = FALSE;
+	}
+	return m;
+}
+
+MARK	m_Nsrch(m)
+	MARK	m;	/* where to start searching */
+{
+	if (prevsf)
+	{
+		m = m_bsrch(m, (char *)0);
+		prevsf = TRUE;
+	}
+	else
+	{
+		m = m_fsrch(m, (char *)0);
+		prevsf = FALSE;
+	}
+	return m;
+}
+
+MARK	m_fsrch(m, ptrn)
+	MARK	m;	/* where to start searching */
+	char	*ptrn;	/* pattern to search for */
+{
+	long	l;	/* line# of line to be searched */
+	char	*line;	/* text of line to be searched */
+	int	wrapped;/* boolean: has our search wrapped yet? */
+	int	pos;	/* where we are in the line */
+#ifndef CRUNCH
+	long	delta = INFINITY;/* line offset, for things like "/foo/+1" */
+#endif
+
+	/* remember: "previous search was forward" */
+	prevsf = TRUE;
+
+	if (ptrn && *ptrn)
+	{
+		/* locate the closing '/', if any */
+		line = parseptrn(ptrn);
+#ifndef CRUNCH
+		if (*line)
+		{
+			delta = atol(line);
+		}
+#endif
+		ptrn++;
+
+		/* free the previous pattern */
+		if (re) free(re);
+
+		/* compile the pattern */
+		re = regcomp(ptrn);
+		if (!re)
+		{
+			return MARK_UNSET;
+		}
+	}
+	else if (!re)
+	{
+		msg("No previous expression");
+		return MARK_UNSET;
+	}
+
+	/* search forward for the pattern */
+	pos = markidx(m) + 1;
+	pfetch(markline(m));
+	if (pos >= plen)
+	{
+		pos = 0;
+		m = (m | (BLKSIZE - 1)) + 1;
+	}
+	wrapped = FALSE;
+	for (l = markline(m); l != markline(m) + 1 || !wrapped; l++)
+	{
+		/* wrap search */
+		if (l > nlines)
+		{
+			/* if we wrapped once already, then the search failed */
+			if (wrapped)
+			{
+				break;
+			}
+
+			/* else maybe we should wrap now? */
+			if (*o_wrapscan)
+			{
+				l = 0;
+				wrapped = TRUE;
+				continue;
+			}
+			else
+			{
+				break;
+			}
+		}
+
+		/* get this line */
+		line = fetchline(l);
+
+		/* check this line */
+		if (regexec(re, &line[pos], (pos == 0)))
+		{
+			/* match! */
+			if (wrapped && *o_warn)
+				msg("(wrapped)");
+#ifndef CRUNCH
+			if (delta != INFINITY)
+			{
+				l += delta;
+				if (l < 1 || l > nlines)
+				{
+					msg("search offset too big");
+					return MARK_UNSET;
+				}
+				force_flags = LNMD|INCL;
+				return MARK_AT_LINE(l);
+			}
+#endif
+			return MARK_AT_LINE(l) + (int)(re->startp[0] - line);
+		}
+		pos = 0;
+	}
+
+	/* not found */
+	msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE");
+	return MARK_UNSET;
+}
+
+MARK	m_bsrch(m, ptrn)
+	MARK	m;	/* where to start searching */
+	char	*ptrn;	/* pattern to search for */
+{
+	long	l;	/* line# of line to be searched */
+	char	*line;	/* text of line to be searched */
+	int	wrapped;/* boolean: has our search wrapped yet? */
+	int	pos;	/* last acceptable idx for a match on this line */
+	int	last;	/* remembered idx of the last acceptable match on this line */
+	int	try;	/* an idx at which we strat searching for another match */
+#ifndef CRUNCH
+	long	delta = INFINITY;/* line offset, for things like "/foo/+1" */
+#endif
+
+	/* remember: "previous search was not forward" */
+	prevsf = FALSE;
+
+	if (ptrn && *ptrn)
+	{
+		/* locate the closing '?', if any */
+		line = parseptrn(ptrn);
+#ifndef CRUNCH
+		if (*line)
+		{
+			delta = atol(line);
+		}
+#endif
+		ptrn++;
+
+		/* free the previous pattern, if any */
+		if (re) free(re);
+
+		/* compile the pattern */
+		re = regcomp(ptrn);
+		if (!re)
+		{
+			return MARK_UNSET;
+		}
+	}
+	else if (!re)
+	{
+		msg("No previous expression");
+		return MARK_UNSET;
+	}
+
+	/* search backward for the pattern */
+	pos = markidx(m);
+	wrapped = FALSE;
+	for (l = markline(m); l != markline(m) - 1 || !wrapped; l--)
+	{
+		/* wrap search */
+		if (l < 1)
+		{
+			if (*o_wrapscan)
+			{
+				l = nlines + 1;
+				wrapped = TRUE;
+				continue;
+			}
+			else
+			{
+				break;
+			}
+		}
+
+		/* get this line */
+		line = fetchline(l);
+
+		/* check this line */
+		if (regexec(re, line, 1) && (int)(re->startp[0] - line) < pos)
+		{
+			/* match!  now find the last acceptable one in this line */
+			do
+			{
+				last = (int)(re->startp[0] - line);
+				try = (int)(re->endp[0] - line);
+			} while (try > 0
+				 && regexec(re, &line[try], FALSE)
+				 && (int)(re->startp[0] - line) < pos);
+
+			if (wrapped && *o_warn)
+				msg("(wrapped)");
+#ifndef CRUNCH
+			if (delta != INFINITY)
+			{
+				l += delta;
+				if (l < 1 || l > nlines)
+				{
+					msg("search offset too big");
+					return MARK_UNSET;
+				}
+				force_flags = LNMD|INCL;
+				return MARK_AT_LINE(l);
+			}
+#endif
+			return MARK_AT_LINE(l) + last;
+		}
+		pos = BLKSIZE;
+	}
+
+	/* not found */
+	msg(*o_wrapscan ? "Not found" : "Hit top without finding RE");
+	return MARK_UNSET;
+}
+
Index: /trunk/minix/commands/elvis/move3.c
===================================================================
--- /trunk/minix/commands/elvis/move3.c	(revision 9)
+++ /trunk/minix/commands/elvis/move3.c	(revision 9)
@@ -0,0 +1,163 @@
+/* move3.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains movement functions that perform character searches */
+
+#include "config.h"
+#include "vi.h"
+
+#ifndef NO_CHARSEARCH
+static MARK	(*prevfwdfn)();	/* function to search in same direction */
+static MARK	(*prevrevfn)();	/* function to search in opposite direction */
+static char	prev_key;	/* sought cvhar from previous [fFtT] */
+
+MARK	m__ch(m, cnt, cmd)
+	MARK	m;	/* current position */
+	long	cnt;
+	char	cmd;	/* command: either ',' or ';' */
+{
+	MARK	(*tmp)();
+
+	if (!prevfwdfn)
+	{
+		msg("No previous f, F, t, or T command");
+		return MARK_UNSET;
+	}
+
+	if (cmd == ',')
+	{
+		m =  (*prevrevfn)(m, cnt, prev_key);
+
+		/* Oops! we didn't want to change the prev*fn vars! */
+		tmp = prevfwdfn;
+		prevfwdfn = prevrevfn;
+		prevrevfn = tmp;
+
+		return m;
+	}
+	else
+	{
+		return (*prevfwdfn)(m, cnt, prev_key);
+	}
+}
+
+/* move forward within this line to next occurrence of key */
+MARK	m_fch(m, cnt, key)
+	MARK	m;	/* where to search from */
+	long	cnt;
+	char	key;	/* what to search for */
+{
+	REG char	*text;
+
+	DEFAULT(1);
+
+	prevfwdfn = m_fch;
+	prevrevfn = m_Fch;
+	prev_key = key;
+
+	pfetch(markline(m));
+	text = ptext + markidx(m);
+	while (cnt-- > 0)
+	{
+		do
+		{
+			m++;
+			text++;
+		} while (*text && *text != key);
+	}
+	if (!*text)
+	{
+		return MARK_UNSET;
+	}
+	return m;
+}
+
+/* move backward within this line to previous occurrence of key */
+MARK	m_Fch(m, cnt, key)
+	MARK	m;	/* where to search from */
+	long	cnt;
+	char	key;	/* what to search for */
+{
+	REG char	*text;
+
+	DEFAULT(1);
+
+	prevfwdfn = m_Fch;
+	prevrevfn = m_fch;
+	prev_key = key;
+
+	pfetch(markline(m));
+	text = ptext + markidx(m);
+	while (cnt-- > 0)
+	{
+		do
+		{
+			m--;
+			text--;
+		} while (text >= ptext && *text != key);
+	}
+	if (text < ptext)
+	{
+		return MARK_UNSET;
+	}
+	return m;
+}
+
+/* move forward within this line almost to next occurrence of key */
+MARK	m_tch(m, cnt, key)
+	MARK	m;	/* where to search from */
+	long	cnt;
+	char	key;	/* what to search for */
+{
+	/* skip the adjacent char */
+	pfetch(markline(m));
+	if (plen <= markidx(m))
+	{
+		return MARK_UNSET;
+	}
+	m++;
+
+	m = m_fch(m, cnt, key);
+	if (m == MARK_UNSET)
+	{
+		return MARK_UNSET;
+	}
+
+	prevfwdfn = m_tch;
+	prevrevfn = m_Tch;
+
+	return m - 1;
+}
+
+/* move backward within this line almost to previous occurrence of key */
+MARK	m_Tch(m, cnt, key)
+	MARK	m;	/* where to search from */
+	long	cnt;
+	char	key;	/* what to search for */
+{
+	/* skip the adjacent char */
+	if (markidx(m) == 0)
+	{
+		return MARK_UNSET;
+	}
+	m--;
+
+	m = m_Fch(m, cnt, key);
+	if (m == MARK_UNSET)
+	{
+		return MARK_UNSET;
+	}
+
+	prevfwdfn = m_Tch;
+	prevrevfn = m_tch;
+
+	return m + 1;
+}
+#endif
Index: /trunk/minix/commands/elvis/move4.c
===================================================================
--- /trunk/minix/commands/elvis/move4.c	(revision 9)
+++ /trunk/minix/commands/elvis/move4.c	(revision 9)
@@ -0,0 +1,211 @@
+/* move4.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains movement functions which are screen-relative */
+
+#include "config.h"
+#include "vi.h"
+
+/* This moves the cursor to a particular row on the screen */
+/*ARGSUSED*/
+MARK m_row(m, cnt, key)
+	MARK	m;	/* the cursor position */
+	long	cnt;	/* the row we'll move to */
+	int	key;	/* the keystroke of this move - H/L/M */
+{
+	DEFAULT(1);
+
+	/* calculate destination line based on key */
+	cnt--;
+	switch (key)
+	{
+	  case 'H':
+		cnt = topline + cnt;
+		break;
+
+	  case 'M':
+		cnt = topline + (LINES - 1) / 2;
+		break;
+
+	  case 'L':
+		cnt = botline - cnt;
+		break;
+	}
+
+	/* return the mark of the destination line */
+	return MARK_AT_LINE(cnt);
+}
+
+
+/* This function repositions the current line to show on a given row */
+MARK m_z(m, cnt, key)
+	MARK	m;	/* the cursor */
+	long	cnt;	/* the line number we're repositioning */
+	int	key;	/* key struck after the z */
+{
+	long	newtop;
+	int	i;
+
+	/* Which line are we talking about? */
+	if (cnt < 0 || cnt > nlines)
+	{
+		return MARK_UNSET;
+	}
+	if (cnt)
+	{
+		m = MARK_AT_LINE(cnt);
+		newtop = cnt;
+	}
+	else
+	{
+		newtop = markline(m);
+	}
+
+	/* allow a "window size" number to be entered */
+	for (i = 0; key >= '0' && key <= '9'; key = getkey(0))
+	{
+		i = i * 10 + key - '0';
+	}
+#ifndef CRUNCH
+	if (i > 0 && i <= LINES - 1)
+	{
+		*o_window = i;
+		wset = TRUE;
+	}
+#else
+	/* the number is ignored if -DCRUNCH */
+#endif
+
+	/* figure out which line will have to be at the top of the screen */
+	switch (key)
+	{
+	  case '\n':
+#if OSK
+	  case '\l':
+#else
+	  case '\r':
+#endif
+	  case '+':
+		break;
+
+	  case '.':
+	  case 'z':
+		newtop -= LINES / 2;
+		break;
+
+	  case '-':
+		newtop -= LINES - 1;
+		break;
+
+	  default:
+		return MARK_UNSET;
+	}
+
+	/* make the new topline take effect */
+	redraw(MARK_UNSET, FALSE);
+	if (newtop >= 1)
+	{
+		topline = newtop;
+	}
+	else
+	{
+		topline = 1L;
+	}
+	redrawrange(0L, INFINITY, INFINITY);
+
+	/* The cursor doesn't move */
+	return m;
+}
+
+
+/* This function scrolls the screen.  It does this by calling redraw() with
+ * an off-screen line as the argument.  It will move the cursor if necessary
+ * so that the cursor is on the new screen.
+ */
+/*ARGSUSED*/
+MARK m_scroll(m, cnt, key)
+	MARK	m;	/* the cursor position */
+	long	cnt;	/* for some keys: the number of lines to scroll */
+	int	key;	/* keystroke that causes this movement */
+{
+	MARK	tmp;	/* a temporary mark, used as arg to redraw() */
+
+	/* adjust cnt, and maybe *o_scroll, depending of key */
+	switch (key)
+	{
+	  case ctrl('F'):
+	  case ctrl('B'):
+		DEFAULT(1);
+		redrawrange(0L, INFINITY, INFINITY); /* force complete redraw */
+		cnt = cnt * (LINES - 1) - 2; /* keeps two old lines on screen */
+		break;
+
+	  case ctrl('E'):
+	  case ctrl('Y'):
+		DEFAULT(1);
+		break;
+
+	  case ctrl('U'):
+	  case ctrl('D'):
+		if (cnt == 0) /* default */
+		{
+			cnt = *o_scroll;
+		}
+		else
+		{
+			if (cnt > LINES - 1)
+			{
+				cnt = LINES - 1;
+			}
+			*o_scroll = cnt;
+		}
+		break;
+	}
+
+	/* scroll up or down, depending on key */
+	switch (key)
+	{
+	  case ctrl('B'):
+	  case ctrl('Y'):
+	  case ctrl('U'):
+		cnt = topline - cnt;
+		if (cnt < 1L)
+		{
+			cnt = 1L;
+			m = MARK_FIRST;
+		}
+		tmp = MARK_AT_LINE(cnt) + markidx(m);
+		redraw(tmp, FALSE);
+		if (markline(m) > botline)
+		{
+			m = MARK_AT_LINE(botline);
+		}
+		break;
+
+	  case ctrl('F'):
+	  case ctrl('E'):
+	  case ctrl('D'):
+		cnt = botline + cnt;
+		if (cnt > nlines)
+		{
+			cnt = nlines;
+			m = MARK_LAST;
+		}
+		tmp = MARK_AT_LINE(cnt) + markidx(m);
+		redraw(tmp, FALSE);
+		if (markline(m) < topline)
+		{
+			m = MARK_AT_LINE(topline);
+		}
+		break;
+	}
+
+	return m;
+}
Index: /trunk/minix/commands/elvis/move5.c
===================================================================
--- /trunk/minix/commands/elvis/move5.c	(revision 9)
+++ /trunk/minix/commands/elvis/move5.c	(revision 9)
@@ -0,0 +1,256 @@
+/* move5.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains the word-oriented movement functions */
+
+#include "config.h"
+#include "ctype.h"
+#include "vi.h"
+
+MARK	m_fword(m, cnt, cmd, prevkey)
+	MARK	m;	/* movement is relative to this mark */
+	long	cnt;	/* a numeric argument */
+	int	cmd;	/* either 'w' or 'W' */
+	int	prevkey;/* previous command... if 'c' then exclude whitespace */
+{
+	REG long	l;
+	REG char	*text;
+	REG int		i;
+
+	DEFAULT(1);
+
+	l = markline(m);
+	pfetch(l);
+	text = ptext + markidx(m);
+
+#ifndef CRUNCH
+	/* As a special case, "cw" or "cW" on whitespace without a count
+	 * treats the single whitespace character under the cursor as a word.
+	 */
+	if (cnt == 1L && prevkey == 'c' && isspace(*text))
+	{
+		return m + 1L;
+	}
+#endif
+
+	while (cnt-- > 0) /* yes, ASSIGNMENT! */
+	{
+		i = *text++;
+
+		if (cmd == 'W')
+		{
+			/* include any non-whitespace */
+			while (i && !isspace(i))
+			{
+				i = *text++;
+			}
+		}
+		else if (isalnum(i) || i == '_')
+		{
+			/* include an alphanumeric word */
+			while (i && isalnum(i))
+			{
+				i = *text++;
+			}
+		}
+		else
+		{
+			/* include contiguous punctuation */
+			while (i && !isalnum(i) && !isspace(i))
+			{
+				i = *text++;
+			}
+		}
+
+		/* if not part of "cw" or "cW" command... */
+		if (prevkey != 'c' || cnt > 0)
+		{
+			/* include trailing whitespace */
+			while (!i || isspace(i))
+			{
+				/* did we hit the end of this line? */
+				if (!i)
+				{
+					/* "dw" shouldn't delete newline after word */
+					if (prevkey && cnt == 0)
+					{
+						break;
+					}
+
+					/* move to next line, if there is one */
+					l++;
+					if (l > nlines)
+					{
+						return MARK_UNSET;
+					}
+					pfetch(l);
+					text = ptext;
+				}
+
+				i = *text++;
+			}
+		}
+		text--;
+	}
+
+	/* if argument to operator, then back off 1 char since "w" and "W"
+	 * include the last char in the affected text.
+	 */
+	if (prevkey)
+	{
+		text--;
+	}
+
+	/* construct a MARK for this place */
+	m = buildmark(text);
+	return m;
+}
+
+
+MARK	m_bword(m, cnt, cmd)
+	MARK	m;	/* movement is relative to this mark */
+	long	cnt;	/* a numeric argument */
+	int	cmd;	/* either 'b' or 'B' */
+{
+	REG long	l;
+	REG char	*text;
+
+	DEFAULT(1);
+
+	l = markline(m);
+	pfetch(l);
+	text = ptext + markidx(m);
+	while (cnt-- > 0) /* yes, ASSIGNMENT! */
+	{
+		text--;
+
+		/* include preceding whitespace */
+		while (text < ptext || isspace(*text))
+		{
+			/* did we hit the end of this line? */
+			if (text < ptext)
+			{
+				/* move to preceding line, if there is one */
+				l--;
+				if (l <= 0)
+				{
+					return MARK_UNSET;
+				}
+				pfetch(l);
+				text = ptext + plen - 1;
+			}
+			else
+			{
+				text--;
+			}
+		}
+
+		if (cmd == 'B')
+		{
+			/* include any non-whitespace */
+			while (text >= ptext && !isspace(*text))
+			{
+				text--;
+			}
+		}
+		else if (isalnum(*text) || *text == '_')
+		{
+			/* include an alphanumeric word */
+			while (text >= ptext && isalnum(*text))
+			{
+				text--;
+			}
+		}
+		else
+		{
+			/* include contiguous punctuation */
+			while (text >= ptext && !isalnum(*text) && !isspace(*text))
+			{
+				text--;
+			}
+		}
+		text++;
+	}
+
+	/* construct a MARK for this place */
+	m = buildmark(text);
+	return m;
+}
+
+MARK	m_eword(m, cnt, cmd)
+	MARK	m;	/* movement is relative to this mark */
+	long	cnt;	/* a numeric argument */
+	int	cmd;	/* either 'e' or 'E' */
+{
+	REG long	l;
+	REG char	*text;
+	REG int		i;
+
+	DEFAULT(1);
+
+	l = markline(m);
+	pfetch(l);
+	text = ptext + markidx(m);
+	while (cnt-- > 0) /* yes, ASSIGNMENT! */
+	{
+		if (*text)
+			text++;
+		i = *text++;
+
+		/* include preceding whitespace */
+		while (!i || isspace(i))
+		{
+			/* did we hit the end of this line? */
+			if (!i)
+			{
+				/* move to next line, if there is one */
+				l++;
+				if (l > nlines)
+				{
+					return MARK_UNSET;
+				}
+				pfetch(l);
+				text = ptext;
+			}
+
+			i = *text++;
+		}
+
+		if (cmd == 'E')
+		{
+			/* include any non-whitespace */
+			while (i && !isspace(i))
+			{
+				i = *text++;
+			}
+		}
+		else if (isalnum(i) || i == '_')
+		{
+			/* include an alphanumeric word */
+			while (i && isalnum(i))
+			{
+				i = *text++;
+			}
+		}
+		else
+		{
+			/* include contiguous punctuation */
+			while (i && !isalnum(i) && !isspace(i))
+			{
+				i = *text++;
+			}
+		}
+		text -= 2;
+	}
+
+	/* construct a MARK for this place */
+	m = buildmark(text);
+	return m;
+}
Index: /trunk/minix/commands/elvis/opts.c
===================================================================
--- /trunk/minix/commands/elvis/opts.c	(revision 9)
+++ /trunk/minix/commands/elvis/opts.c	(revision 9)
@@ -0,0 +1,797 @@
+/* opts.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains the code that manages the run-time options -- The 
+ * values that can be modified via the "set" command.
+ */
+
+#include "config.h"
+#include "vi.h"
+#include "ctype.h"
+#ifndef NULL
+#define NULL (char *)0
+#endif
+extern char	*getenv();
+
+/* maximum width to permit for strings, including ="" */
+#define MAXWIDTH 20
+
+/* These are the default values of all options */
+char	o_autoindent[1] =	{FALSE};
+char	o_autoprint[1] =	{TRUE};
+char	o_autotab[1] =		{TRUE};
+char	o_autowrite[1] = 	{FALSE};
+char	o_columns[3] =		{80, 32, 255};
+char	o_directory[30] =	TMPDIR;
+char	o_edcompatible[1] =	{FALSE};
+char	o_equalprg[80] =	{"fmt"};
+char	o_errorbells[1] =	{TRUE};
+char	o_exrefresh[1] =	{TRUE};
+char	o_ignorecase[1] =	{FALSE};
+char	o_keytime[3] =		{1, 0, 50};
+char	o_keywordprg[80] =	{KEYWORDPRG};
+char	o_lines[3] =		{25, 2, 96};
+char	o_list[1] =		{FALSE};
+char	o_number[1] =		{FALSE};
+char	o_readonly[1] =		{FALSE};
+char	o_remap[1] =		{TRUE};
+char	o_report[3] =		{5, 1, 127};
+char	o_scroll[3] =		{12, 1, 127};
+char	o_shell[60] =		SHELL;
+char	o_shiftwidth[3] =	{8, 1, 255};
+char	o_sidescroll[3] =	{8, 1, 40};
+char	o_sync[1] =		{NEEDSYNC};
+char	o_tabstop[3] =		{8, 1, 40};
+char	o_term[30] =		"?";
+char	o_flash[1] =		{TRUE};
+char	o_warn[1] =		{TRUE};
+char	o_wrapscan[1] =		{TRUE};
+
+#ifndef CRUNCH
+char	o_beautify[1] =		{FALSE};
+char	o_exrc[1] =		{FALSE};
+char	o_mesg[1] =		{TRUE};
+char	o_more[1] =		{TRUE};
+char	o_novice[1] =		{FALSE};
+char	o_prompt[1] =		{TRUE};
+char	o_taglength[3] =	{0, 0, 30};
+char	o_terse[1] =		{FALSE};
+char	o_window[3] =		{0, 1, 24};
+char	o_wrapmargin[3] =	{0, 0, 255};
+char	o_writeany[1] =		{FALSE};
+#endif
+
+#ifndef NO_ERRLIST
+char	o_cc[30] =		{CC_COMMAND};
+char	o_make[30] =		{MAKE_COMMAND};
+#endif
+
+#ifndef NO_CHARATTR
+char	o_charattr[1] =		{FALSE};
+#endif
+
+#ifndef NO_DIGRAPH
+char	o_digraph[1] =		{FALSE};
+char	o_flipcase[80]
+# ifdef CS_IBMPC
+	= {"\207\200\201\232\202\220\204\216\206\217\221\222\224\231\244\245"}
+# endif
+# ifdef CS_LATIN1
+	/* initialized by initopts() */
+# endif
+	;
+#endif
+
+#ifndef NO_SENTENCE
+char	o_hideformat[1] =	{FALSE};
+#endif
+
+#ifndef NO_EXTENSIONS
+char	o_inputmode[1] =	{FALSE};
+char	o_ruler[1] =		{FALSE};
+#endif
+
+#ifndef NO_MAGIC
+char	o_magic[1] =		{TRUE};
+#endif
+
+#ifndef NO_MODELINES
+char	o_modelines[1] =	{FALSE};
+#endif
+
+#ifndef NO_SENTENCE
+char	o_paragraphs[30] =	"PPppIPLPQP";
+char	o_sections[30] =	"NHSHSSSEse";
+#endif
+
+#if MSDOS
+char	o_pcbios[1] =		{TRUE};
+#endif
+
+#ifndef NO_SHOWMATCH
+char	o_showmatch[1] =	{FALSE};
+#endif
+
+#ifndef	NO_SHOWMODE
+char	o_smd[1] =		{FALSE};
+#endif
+
+
+/* The following describes the names & types of all options */
+#define BOOL	0
+#define	NUM	1
+#define	STR	2
+#define SET	0x01	/* this option has had its value altered */
+#define CANSET	0x02	/* this option can be set at any time */
+#define RCSET	0x06	/* this option can be set in a .exrc file only */
+#define NOSAVE	0x0a	/* this option should never be saved by mkexrc */
+#define WSET	0x20	/* is this the "window" size option? */
+#define MR	0x40	/* does this option affect the way text is displayed? */
+struct
+{
+	char	*name;	/* name of an option */
+	char	*nm;	/* short name of an option */
+	char	type;	/* type of an option */
+	char	flags;	/* boolean: has this option been set? */
+	char	*value;	/* value */
+}
+	opts[] =
+{
+	/* name			type	flags		value */
+	{ "autoindent",	"ai",	BOOL,	CANSET,		o_autoindent	},
+	{ "autoprint",	"ap",	BOOL,	CANSET,		o_autoprint	},
+	{ "autotab",	"at",	BOOL,	CANSET,		o_autotab	},
+	{ "autowrite",	"aw",	BOOL,	CANSET,		o_autowrite	},
+#ifndef CRUNCH
+	{ "beautify",	"bf",	BOOL,	CANSET,		o_beautify	},
+#endif
+#ifndef NO_ERRLIST
+	{ "cc",		"cc",	STR,	CANSET,		o_cc		},
+#endif
+#ifndef NO_CHARATTR
+	{ "charattr",	"ca",	BOOL,	CANSET|MR,	o_charattr	},
+#endif
+	{ "columns",	"co",	NUM,	SET|NOSAVE|MR,	o_columns	},
+#ifndef NO_DIGRAPH
+	{ "digraph",	"dig",	BOOL,	CANSET,		o_digraph	},
+#endif
+	{ "directory",	"dir",	STR,	RCSET,		o_directory	},
+	{ "edcompatible","ed",	BOOL,	CANSET,		o_edcompatible	},
+	{ "equalprg",	"ep",	STR,	CANSET,		o_equalprg	},
+	{ "errorbells",	"eb",	BOOL,	CANSET,		o_errorbells	},
+#ifndef CRUNCH
+	{ "exrc",	"exrc",	BOOL,	CANSET,		o_exrc		},
+#endif
+	{ "exrefresh",	"er",	BOOL,	CANSET,		o_exrefresh	},
+	{ "flash",	"vbell",BOOL,	CANSET,		o_flash		},
+#ifndef NO_DIGRAPH
+	{ "flipcase",	"fc",	STR,	CANSET,		o_flipcase	},
+#endif
+#ifndef NO_SENTENCE
+	{ "hideformat",	"hf",	BOOL,	CANSET|MR,	o_hideformat	},
+#endif
+	{ "ignorecase",	"ic",	BOOL,	CANSET,		o_ignorecase	},
+#ifndef NO_EXTENSIONS
+	{ "inputmode",	"im",	BOOL,	CANSET,		o_inputmode	},
+#endif
+	{ "keytime",	"kt",	NUM,	CANSET,		o_keytime	},
+	{ "keywordprg",	"kp",	STR,	CANSET,		o_keywordprg	},
+	{ "lines",	"ls",	NUM,	SET|NOSAVE|MR,	o_lines		},
+	{ "list",	"li",	BOOL,	CANSET|MR,	o_list		},
+#ifndef NO_MAGIC
+	{ "magic",	"ma",	BOOL,	CANSET,		o_magic		},
+#endif
+#ifndef NO_ERRLIST
+	{ "make",	"mk",	STR,	CANSET,		o_make		},
+#endif
+#ifndef CRUNCH
+	{ "mesg",	"me",	BOOL,	CANSET,		o_mesg		},
+#endif
+#ifndef NO_MODELINES
+	{ "modelines",	"ml",	BOOL,	CANSET,		o_modelines	},
+#endif
+#ifndef CRUNCH
+	{ "more",	"mo",	BOOL,	CANSET,		o_more		},
+	{ "novice",	"nov",	BOOL,	CANSET,		o_novice	},
+#endif
+	{ "number",	"nu",	BOOL,	CANSET|MR,	o_number	},
+#ifndef NO_SENTENCE
+	{ "paragraphs",	"para",	STR,	CANSET,		o_paragraphs	},
+#endif
+#if MSDOS
+	{ "pcbios",	"pc",	BOOL,	SET|NOSAVE,	o_pcbios	},
+#endif
+#ifndef CRUNCH
+	{ "prompt",	"pr",	BOOL,	CANSET,		o_prompt	},
+#endif
+	{ "readonly",	"ro",	BOOL,	CANSET,		o_readonly	},
+	{ "remap",	"remap",BOOL,	CANSET,		o_remap		},
+	{ "report",	"re",	NUM,	CANSET,		o_report	},
+#ifndef NO_EXTENSIONS
+	{ "ruler",	"ru",	BOOL,	CANSET,		o_ruler		},
+#endif
+	{ "scroll",	"sc",	NUM,	CANSET,		o_scroll	},
+#ifndef NO_SENTENCE
+	{ "sections",	"sect",	STR,	CANSET,		o_sections	},
+#endif
+	{ "shell",	"sh",	STR,	CANSET,		o_shell		},
+#ifndef NO_SHOWMATCH
+	{ "showmatch",	"sm",	BOOL,	CANSET,		o_showmatch	},
+#endif
+#ifndef	NO_SHOWMODE
+	{ "showmode",	"smd",	BOOL,	CANSET,		o_smd		},
+#endif
+	{ "shiftwidth",	"sw",	NUM,	CANSET,		o_shiftwidth	},
+	{ "sidescroll",	"ss",	NUM,	CANSET,		o_sidescroll	},
+	{ "sync",	"sy",	BOOL,	CANSET,		o_sync		},
+	{ "tabstop",	"ts",	NUM,	CANSET|MR,	o_tabstop	},
+#ifndef CRUNCH
+	{ "taglength",	"tl",	NUM,	CANSET,		o_taglength	},
+#endif
+	{ "term",	"te",	STR,	SET,		o_term		},
+#ifndef CRUNCH
+	{ "terse",	"tr",	BOOL,	CANSET,		o_terse		},
+	{ "timeout",	"to",	BOOL,	CANSET,		o_keytime	},
+#endif
+#ifndef CRUNCH
+	{ "window",	"wi",	NUM,	CANSET|MR|WSET,	o_window	},
+	{ "wrapmargin",	"wm",	NUM,	CANSET,		o_wrapmargin	},
+#endif
+	{ "wrapscan",	"ws",	BOOL,	CANSET,		o_wrapscan	},
+#ifndef CRUNCH
+	{ "writeany",	"wr",	BOOL,	CANSET,		o_writeany	},
+#endif
+	{ NULL, NULL, 0, CANSET, NULL }
+};
+
+
+/* This function initializes certain options from environment variables, etc. */
+void initopts()
+{
+	char	*val;
+	int	i;
+
+	/* set some stuff from environment variables */
+#if MSDOS
+	if (val = getenv("COMSPEC")) /* yes, ASSIGNMENT! */
+#else
+	if (val = getenv("SHELL")) /* yes, ASSIGNMENT! */
+#endif
+	{
+		strcpy(o_shell, val);
+	}
+
+	strcpy(o_term, termtype);
+#if MSDOS
+	if (strcmp(termtype, "pcbios"))
+	{
+		o_pcbios[0] = FALSE;
+	}
+	else
+	{
+		o_pcbios[0] = TRUE;
+	}
+#endif
+
+#if AMIGA || MSDOS || TOS
+	if ((val = getenv("TMP")) /* yes, ASSIGNMENT! */
+	||  (val = getenv("TEMP")))
+		strcpy(o_directory, val);
+#endif
+
+#ifndef CRUNCH
+	if ((val = getenv("LINES")) && atoi(val) > 4) /* yes, ASSIGNMENT! */
+	{
+		LINES = atoi(val);
+	}
+	if ((val = getenv("COLUMNS")) && atoi(val) > 30) /* yes, ASSIGNMENT! */
+	{
+		COLS = atoi(val);
+	}
+#endif
+	*o_lines = LINES;
+	*o_columns = COLS;
+	*o_scroll = LINES / 2 - 1;
+#ifndef CRUNCH
+	if (o_window[0] == 0)
+	{
+		o_window[0] = o_window[2] = *o_lines;
+	}
+#endif
+
+	/* disable the flash option if we don't know how to do a flash */
+	if (!has_VB)
+	{
+		for (i = 0; opts[i].value != o_flash; i++)
+		{
+		}
+		opts[i].flags &= ~CANSET;
+		*o_flash = FALSE;
+	}
+
+#ifndef NO_DIGRAPH
+# ifdef CS_LATIN1
+	for (i = 0, val = o_flipcase; i < 32; i++)
+	{
+		/* leave out the multiply/divide symbols */
+		if (i == 23)
+			continue;
+
+		/* add lower/uppercase pair */
+		*val++ = i + 0xe0;
+		*val++ = i + 0xc0;
+	}
+	*val = '\0';
+# endif /* CS_LATIN1 */
+
+	/* initialize the ctype package */
+	_ct_init(o_flipcase);
+#else
+	_ct_init("");
+#endif /* not NO_DIGRAPH */
+}
+
+/* This function lists the current values of all options */
+void dumpopts(all)
+	int	all;	/* boolean: dump all options, or just set ones? */
+{
+#ifndef NO_OPTCOLS
+	int	i, j, k;
+	char	nbuf[4];	/* used for converting numbers to ASCII */
+	int	widths[5];	/* width of each column, including gap */
+	int	ncols;		/* number of columns */
+	int	nrows;		/* number of options per column */
+	int	nset;		/* number of options to be output */
+	int	width;		/* width of a particular option */
+	int	todump[60];	/* indicies of options to be dumped */
+
+	/* step 1: count the number of set options */
+	for (nset = i = 0; opts[i].name; i++)
+	{
+		if (all || (opts[i].flags & SET))
+		{
+			todump[nset++] = i;
+		}
+	}
+
+	/* step two: try to use as many columns as possible */
+	for (ncols = (nset > 5 ? 5 : nset); ncols > 1; ncols--)
+	{
+		/* how many would go in this column? */
+		nrows = (nset + ncols - 1) / ncols;
+
+		/* figure out the width of each column */
+		for (i = 0; i < ncols; i++)
+		{
+			widths[i] = 0;
+			for (j = 0, k = nrows * i; j < nrows && k < nset; j++, k++)
+			{
+				/* figure out the width of a particular option */
+				switch (opts[todump[k]].type)
+				{
+				  case BOOL:
+					if (!*opts[todump[k]].value)
+						width = 2;
+					else
+						width = 0;
+					break;
+
+				  case STR:
+					width = 3 + strlen(opts[todump[k]].value);
+					if (width > MAXWIDTH)
+						width = MAXWIDTH;
+					break;
+
+				  case NUM:
+					width = 4;
+					break;
+				}
+				width += strlen(opts[todump[k]].name);
+
+				/* if this is the widest so far, widen col */
+				if (width > widths[i])
+				{
+					widths[i] = width;
+				}
+			}
+
+		}
+
+		/* if the total width is narrow enough, then use it */
+		for (width = -2, i = 0; i < ncols; i++)
+		{
+			width += widths[i] + 2;
+		}
+		if (width < COLS - 1)
+		{
+			break;
+		}
+	}
+
+	/* step 3: output the columns */
+	nrows = (nset + ncols - 1) / ncols;
+	for (i = 0; i < nrows; i++)
+	{
+		for (j = 0; j < ncols; j++)
+		{
+			/* if we hit the end of the options, quit */
+			k = i + j * nrows;
+			if (k >= nset)
+			{
+				break;
+			}
+
+			/* output this option's value */
+			width = 0;
+			switch (opts[todump[k]].type)
+			{
+			  case BOOL:
+				if (!*opts[todump[k]].value)
+				{
+					qaddch('n');
+					qaddch('o');
+					width = 2;
+				}
+				qaddstr(opts[todump[k]].name);
+				width += strlen(opts[todump[k]].name);
+				break;
+
+			  case NUM:
+				sprintf(nbuf, "%-3d", UCHAR(*opts[todump[k]].value));
+				qaddstr(opts[todump[k]].name);
+				qaddch('=');
+				qaddstr(nbuf);
+				width = 4 + strlen(opts[todump[k]].name);
+				break;
+
+			  case STR:
+				qaddstr(opts[todump[k]].name);
+				qaddch('=');
+				qaddch('"');
+				strcpy(tmpblk.c, opts[todump[k]].value);
+				width = 3 + strlen(tmpblk.c);
+				if (width > MAXWIDTH)
+				{
+					width = MAXWIDTH;
+					strcpy(tmpblk.c + MAXWIDTH - 6, "...");
+				}
+				qaddstr(tmpblk.c);
+				qaddch('"');
+				width += strlen(opts[todump[k]].name);
+				break;
+			}
+
+			/* pad the field to the correct size */
+			if (k + nrows <= nset)
+			{
+				while (width < widths[j] + 2)
+				{
+					qaddch(' ');
+					width++;
+				}
+			}
+		}
+		addch('\n');
+		exrefresh();
+	}
+#else
+	int	i;
+	int	col;
+	char	nbuf[4];
+
+	for (i = col = 0; opts[i].name; i++)
+	{
+		/* if not set and not all, ignore this option */
+		if (!all && !(opts[i].flags & SET))
+		{
+			continue;
+		}
+
+		/* align this option in one of the columns */
+		if (col > 52)
+		{
+			addch('\n');
+			col = 0;
+		}
+		else if (col > 26)
+		{
+			while (col < 52)
+			{
+				qaddch(' ');
+				col++;
+			}
+		}
+		else if (col > 0)
+		{
+			while (col < 26)
+			{
+				qaddch(' ');
+				col++;
+			}
+		}
+
+		switch (opts[i].type)
+		{
+		  case BOOL:
+			if (!*opts[i].value)
+			{
+				qaddch('n');
+				qaddch('o');
+				col += 2;
+			}
+			qaddstr(opts[i].name);
+			col += strlen(opts[i].name);
+			break;
+
+		  case NUM:
+			sprintf(nbuf, "%-3d", UCHAR(*opts[i].value));
+			qaddstr(opts[i].name);
+			qaddch('=');
+			qaddstr(nbuf);
+			col += 4 + strlen(opts[i].name);
+			break;
+
+		  case STR:
+			qaddstr(opts[i].name);
+			qaddch('=');
+			qaddch('"');
+			qaddstr(opts[i].value);
+			qaddch('"');
+			col += 3 + strlen(opts[i].name) + strlen(opts[i].value);
+			break;
+		}
+		exrefresh();
+	}
+	if (col > 0)
+	{
+		addch('\n');
+		exrefresh();
+	}
+#endif
+}
+
+#ifndef NO_MKEXRC
+/* This function saves the current configuration of options to a file */
+void saveopts(fd)
+	int	fd;	/* file descriptor to write to */
+{
+	int	i;
+	char	buf[256], *pos;
+
+	/* write each set options */
+	for (i = 0; opts[i].name; i++)
+	{
+		/* if unset or unsettable, ignore this option */
+		if ((opts[i].flags & (SET|CANSET|NOSAVE)) != (SET|CANSET))
+		{
+			continue;
+		}
+
+		strcpy(buf, "set ");
+		pos = &buf[4];
+		switch (opts[i].type)
+		{
+		  case BOOL:
+			if (!*opts[i].value)
+			{
+				*pos++='n';
+				*pos++='o';
+			}
+			strcpy(pos, opts[i].name);
+			strcat(pos, "\n");
+			break;
+
+		  case NUM:
+			sprintf(pos, "%s=%-3d\n", opts[i].name, *opts[i].value & 0xff);
+			break;
+
+		  case STR:
+			sprintf(pos, "%s=\"%s\"\n", opts[i].name, opts[i].value);
+			break;
+		}
+		twrite(fd, buf, (unsigned)strlen(buf));
+	}
+}
+#endif
+
+
+/* This function changes the values of one or more options. */
+void setopts(assignments)
+	char	*assignments;	/* a string containing option assignments */
+{
+	char	*name;		/* name of variable in assignments */
+	char	*value;		/* value of the variable */
+	char	*scan;		/* used for moving through strings */
+	char	*build;		/* used for copying chars from "scan" */
+	char	*prefix;	/* pointer to "neg" or "no" at front of a boolean */
+	int	quote;		/* boolean: inside '"' quotes? */
+	int	i, j;
+
+#ifndef CRUNCH
+	/* reset the upper limit of "window" option to lines-1 */
+	*o_window = *o_lines - 1;
+#endif
+
+	/* for each assignment... */
+	for (name = assignments; *name; )
+	{
+		/* skip whitespace */
+		if (*name == ' ' || *name == '\t')
+		{
+			name++;
+			continue;
+		}
+
+		/* after the name, find the value (if any) */
+		for (scan = name; isalnum(*scan); scan++)
+		{
+		}
+		if (*scan == '=')
+		{
+			*scan++ = '\0';
+			value = build = scan;
+			for (quote = FALSE; *scan && (quote || !isspace(*scan)); scan++)
+			{
+				if (*scan == '"')
+				{
+					quote = !quote;
+				}
+				else if (*scan == '\\' && scan[1])
+				{
+					*build++ = *++scan;
+				}
+				else
+				{
+					*build++ = *scan;
+				}
+			}
+			if (*scan)
+				scan++;
+			*build = '\0';
+		}
+		else /* no "=" so it is probably boolean... */
+		{
+			if (*scan)
+			{
+				*scan++ = '\0';
+			}
+			value = NULL;
+			prefix = name;
+#ifndef CRUNCH
+			if (!strcmp(name, "novice"))
+				/* don't check for a "no" prefix */;
+			else
+#endif
+			if (prefix[0] == 'n' && prefix[1] == 'o')
+				name += 2;
+			else if (prefix[0] == 'n' && prefix[1] == 'e' && prefix[2] == 'g')
+				name += 3;
+		}
+
+		/* find the variable */
+		for (i = 0;
+		     opts[i].name && strcmp(opts[i].name, name) && strcmp(opts[i].nm, name);
+		     i++)
+		{
+		}
+
+		/* change the variable */
+		if (!opts[i].name)
+		{
+			msg("invalid option name \"%s\"", name);
+		}
+		else if ((opts[i].flags & CANSET) != CANSET)
+		{
+			msg("option \"%s\" can't be altered", name);
+		}
+		else if ((opts[i].flags & RCSET) != CANSET && nlines >= 1L)
+		{
+			msg("option \"%s\" can only be set in a %s file", name, EXRC);
+		}
+		else if (value)
+		{
+			switch (opts[i].type)
+			{
+			  case BOOL:
+				msg("option \"[no]%s\" is boolean", name);
+				break;
+
+			  case NUM:
+				j = atoi(value);
+				if (j == 0 && *value != '0')
+				{
+					msg("option \"%s\" must have a numeric value", name);
+				}
+				else if (j < opts[i].value[1] || j > (opts[i].value[2] & 0xff))
+				{
+					msg("option \"%s\" must have a value between %d and %d",
+						name, opts[i].value[1], opts[i].value[2] & 0xff);
+				}
+				else
+				{
+					*opts[i].value = atoi(value);
+					opts[i].flags |= SET;
+				}
+				break;
+
+			  case STR:
+				strcpy(opts[i].value, value);
+				opts[i].flags |= SET;
+				break;
+			}
+			if (opts[i].flags & MR)
+			{
+				redraw(MARK_UNSET, FALSE);
+			}
+#ifndef CRUNCH
+			if (opts[i].flags & WSET)
+			{
+				wset = TRUE;
+			}
+#endif
+		}
+		else /* valid option, no value */
+		{
+			if (opts[i].type == BOOL)
+			{
+				if (prefix == name)
+					*opts[i].value = TRUE;
+				else if (prefix[1] == 'o')
+					*opts[i].value = FALSE;
+				else
+					*opts[i].value = !*opts[i].value;
+
+				opts[i].flags |= SET;
+				if (opts[i].flags & MR)
+				{
+					redraw(MARK_UNSET, FALSE);
+				}
+			}
+			else
+			{
+				msg("option \"%s\" must be given a value", name);
+			}
+		}
+
+		/* move on to the next option */
+		name = scan;
+	}
+
+	/* special processing ... */
+
+#ifndef CRUNCH
+	/* if "novice" is set, then ":set report=1 showmode nomagic" */
+	if (*o_novice)
+	{
+		*o_report = 1;
+# ifndef NO_SHOWMODE
+		*o_smd = TRUE;
+# endif
+# ifndef NO_MAGIC
+		*o_magic = FALSE;
+# endif
+	}
+#endif
+
+	/* if "readonly" then set the READONLY flag for this file */
+	if (*o_readonly)
+	{
+		setflag(file, READONLY);
+	}
+
+#ifndef NO_DIGRAPH
+	/* re-initialize the ctype package */
+	_ct_init(o_flipcase);
+#endif /* not NO_DIGRAPH */
+
+	/* copy o_lines and o_columns into LINES and COLS */
+	LINES = (*o_lines & 255);
+	COLS = (*o_columns & 255);
+}
Index: /trunk/minix/commands/elvis/prsvunix.c
===================================================================
--- /trunk/minix/commands/elvis/prsvunix.c	(revision 9)
+++ /trunk/minix/commands/elvis/prsvunix.c	(revision 9)
@@ -0,0 +1,106 @@
+/* prsvunix.c */
+
+/* This file contains the UNIX-specific parts of the "elvprsv" program. */
+
+#if OSK
+#define ELVPRSV
+#include "osk.c"
+#else
+#include <sys/stat.h>
+#include <pwd.h>
+#endif
+extern struct passwd *getpwuid();
+
+/* This variable is used to add extra error messages for mail sent to root */
+char *ps;
+
+/* This function returns the login name of the owner of a file */
+char *ownername(filename)
+	char	*filename;	/* name of a file */
+{
+	struct stat	st;
+	struct passwd	*pw;
+
+	/* stat the file, to get its uid */
+	if (stat(filename, &st) < 0)
+	{
+		ps = "stat() failed";
+		return "root";
+	}
+
+	/* get the /etc/passwd entry for that user */
+	pw = getpwuid(st.st_uid);
+	if (!pw)
+	{
+		ps = "uid not found in password file";
+		return "root";
+	}
+
+	/* return the user's name */
+	return pw->pw_name;
+}
+
+
+/* This function sends a mail message to a given user, saying that a file
+ * has been preserved.
+ */
+void mail(user, file, when)
+	char	*user;	/* name of user who should receive the mail */
+	char	*file;	/* name of original text file that was preserved */
+	char	*when;	/* description of why the file was preserved */
+{
+	char	cmd[80];/* buffer used for constructing a "mail" command */
+	FILE	*m, *popen();	/* stream used for giving text to the "mail" program */
+	char	*base;	/* basename of the file */
+
+	/* separate the directory name from the basename. */
+	for (base = file + strlen(file); --base > file && *base != SLASH; )
+	{
+	}
+	if (*base == SLASH)
+	{
+		*base++ = '\0';
+	}
+
+	/* for anonymous buffers, pretend the name was "foo" */
+	if (!strcmp(base, "*"))
+	{
+		base = "foo";
+	}
+
+	/* open a pipe to the "mail" program */
+#if OSK
+	sprintf(cmd, "mail \"-s=%s preserved!\" %s", base, user);
+#else /* ANY_UNIX */
+	sprintf(cmd, "mail %s >/dev/null 2>/dev/null", user);
+#endif
+	m = popen(cmd, "w");
+	if (!m)
+	{
+		/* Can't send mail!  Hope the user figures it out. */
+		return;
+	}
+
+	/* Tell the user that the file was preserved */
+	fprintf(m, "A version of your file \"%s%c%s\"\n", file, SLASH, base);
+	fprintf(m, "was preserved when %s.\n", when);
+	fprintf(m, "To recover this file, do the following:\n");
+	fprintf(m, "\n");
+#if OSK
+	fprintf(m, "     chd %s\n", file);
+#else /* ANY_UNIX */
+	fprintf(m, "     cd %s\n", file);
+#endif
+	fprintf(m, "     elvrec %s\n", base);
+	fprintf(m, "\n");
+	fprintf(m, "With fond wishes for a speedy recovery,\n");
+	fprintf(m, "                                    Elvis\n");
+	if (ps)
+	{
+		fprintf(m, "\nP.S. %s\n", ps);
+		ps = (char *)0;
+	}
+
+	/* close the stream */
+	pclose(m);
+}
Index: /trunk/minix/commands/elvis/recycle.c
===================================================================
--- /trunk/minix/commands/elvis/recycle.c	(revision 9)
+++ /trunk/minix/commands/elvis/recycle.c	(revision 9)
@@ -0,0 +1,183 @@
+/* recycle.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains the functions perform garbage collection and allocate
+ * reusable blocks.
+ */
+
+#include "config.h"
+#include "vi.h"
+
+#ifndef NO_RECYCLE
+/* this whole file would have be skipped if NO_RECYCLE is defined */
+
+
+#define BTST(bitno, byte)	((byte) & (1 << (bitno)))
+#define BSET(bitno, byte)	((byte) |= (1 << (bitno)))
+#define BCLR(bitno, byte)	((byte) &= ~(1 << (bitno)))
+
+#define TST(blkno)		((blkno) < MAXBIT ? BTST((blkno) & 7, bitmap[(blkno) >> 3]) : 1)
+#define SET(blkno)		if ((blkno) < MAXBIT) BSET((blkno) & 7, bitmap[(blkno) >> 3])
+#define CLR(blkno)		if ((blkno) < MAXBIT) BCLR((blkno) & 7, bitmap[(blkno) >> 3])
+
+/* bitmap of free blocks in first 4096k of tmp file */
+static unsigned char bitmap[512];
+#define MAXBIT	(sizeof bitmap << 3)
+
+/* this function locates all free blocks in the current tmp file */
+void garbage()
+{
+	int	i;
+	BLK	oldhdr;
+
+	/* start by assuming every block is free */
+	for (i = 0; i < sizeof bitmap; i++)
+	{
+		bitmap[i] = 255;
+	}
+
+	/* header blocks aren't free */
+#ifndef lint
+	CLR(0);
+	CLR(1);
+#endif
+
+	/* blocks needed for current hdr aren't free */
+	for (i = 1; i < MAXBLKS; i++)
+	{
+		CLR(hdr.n[i]);
+	}
+
+	/* blocks needed for undo version aren't free */
+	lseek(tmpfd, 0L, 0);
+	if (read(tmpfd, &oldhdr, (unsigned)sizeof oldhdr) != sizeof oldhdr)
+	{
+		msg("garbage() failed to read oldhdr??");
+		for (i = 0; i < sizeof bitmap; i++)
+		{
+			bitmap[i] = 0;
+		}
+		return;
+	}
+	for (i = 1; i < MAXBLKS; i++)
+	{
+		CLR(oldhdr.n[i]);
+	}
+
+	/* blocks needed for cut buffers aren't free */
+	for (i = cutneeds(&oldhdr) - 1; i >= 0; i--)
+	{
+		CLR(oldhdr.n[i]);
+	}
+}
+
+/* This function allocates the first available block in the tmp file */
+long allocate()
+{
+	int	i;
+	long	offset;
+
+	/* search for the first byte with a free bit set */
+	for (i = 0; i < sizeof bitmap && bitmap[i] == 0; i++)
+	{
+	}
+
+	/* if we hit the end of the bitmap, return the end of the file */
+	if (i == sizeof bitmap)
+	{
+		offset = lseek(tmpfd, 0L, 2);
+	}
+	else /* compute the offset for the free block */
+	{
+		for (i <<= 3; TST(i) == 0; i++)
+		{
+		}
+		offset = (long)i * (long)BLKSIZE;
+
+		/* mark the block as "allocated" */
+		CLR(i);
+	}
+
+	return offset;
+}
+
+#endif
+
+#ifdef DEBUG
+# include <stdio.h>
+# undef malloc
+# undef free
+# define MEMMAGIC 0x19f72cc0L
+# define MAXALLOC 800
+static char *allocated[MAXALLOC];
+static char *fromfile[MAXALLOC];
+static int  fromline[MAXALLOC]; 
+static int  sizes[MAXALLOC];
+
+char *dbmalloc(size, file, line)
+	int	size;
+	char	*file;
+	int	line;
+{
+	char	*ret;
+	int	i;
+
+	size = size + sizeof(long) - (size % sizeof(long));
+	ret = (char *)malloc(size + 2 * sizeof(long)) + sizeof(long);
+	for (i = 0; i < MAXALLOC && allocated[i]; i++)
+	{
+	}
+	if (i == MAXALLOC)
+	{
+		endwin();
+		fprintf(stderr, "\r\n%s(%d): Too many malloc calls!\n", file, line);
+		abort();
+	}
+	sizes[i] = size/sizeof(long);
+	allocated[i] = ret;
+	fromfile[i] = file;
+	fromline[i] = line;
+	((long *)ret)[-1] = MEMMAGIC;
+	((long *)ret)[sizes[i]] = MEMMAGIC;
+	return ret;
+}
+
+dbfree(ptr, file, line)
+	char	*ptr;
+	char	*file;
+	int	line;
+{
+	int	i;
+
+	for (i = 0; i < MAXALLOC && allocated[i] != ptr; i++)
+	{
+	}
+	if (i == MAXALLOC)
+	{
+		endwin();
+		fprintf(stderr, "\r\n%s(%d): attempt to free mem that wasn't allocated\n", file, line);
+		abort();
+	}
+	allocated[i] = (char *)0;
+	if (((long *)ptr)[-1] != MEMMAGIC)
+	{
+		endwin();
+		fprintf(stderr, "\r\n%s(%d): underflowed malloc space, allocated at %s(%d)\n", file, line, fromfile[i], fromline[i]);
+		abort();
+	}
+	if (((long *)ptr)[sizes[i]] != MEMMAGIC)
+	{
+		endwin();
+		fprintf(stderr, "\r\n%s(%d): overflowed malloc space, allocated at %s(%d)\n", file, line, fromfile[i], fromline[i]);
+		abort();
+	}
+	free(ptr - sizeof(long));
+}
+#endif
Index: /trunk/minix/commands/elvis/redraw.c
===================================================================
--- /trunk/minix/commands/elvis/redraw.c	(revision 9)
+++ /trunk/minix/commands/elvis/redraw.c	(revision 9)
@@ -0,0 +1,1295 @@
+/* redraw.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains functions that draw text on the screen.  The major entry
+ * points are:
+ *	redrawrange()	- called from modify.c to give hints about what parts
+ *			  of the screen need to be redrawn.
+ *	redraw()	- redraws the screen (or part of it) and positions
+ *			  the cursor where it belongs.
+ *	idx2col()	- converts a markidx() value to a logical column number.
+ */
+
+#include "config.h"
+#include "vi.h"
+
+/* This variable contains the line number that smartdrawtext() knows best */
+static long smartlno;
+
+/* This function remembers where changes were made, so that the screen can be
+ * redraw in a more efficient manner.
+ */
+static long	redrawafter;	/* line# of first line that must be redrawn */
+static long	preredraw;	/* line# of last line changed, before change */
+static long	postredraw;	/* line# of last line changed, after change */
+static int	mustredraw;	/* boolean: anything forcing a screen update? */
+void redrawrange(after, pre, post)
+	long	after;	/* lower bound of redrawafter */
+	long	pre;	/* upper bound of preredraw */
+	long	post;	/* upper bound of postredraw */
+{
+	if (after == redrawafter)
+	{
+		/* multiple insertions/deletions at the same place -- combine
+		 * them
+		 */
+		preredraw -= (post - pre);
+		if (postredraw < post)
+		{
+			preredraw += (post - postredraw);
+			postredraw = post;
+		}
+		if (redrawafter > preredraw)
+		{
+			redrawafter = preredraw;
+		}
+		if (redrawafter < 1L)
+		{
+			redrawafter = 0L;
+			preredraw = postredraw = INFINITY;
+		}
+	}
+	else if (postredraw > 0L)
+	{
+		/* multiple changes in different places -- redraw everything
+		 * after "after".
+		 */
+		postredraw = preredraw = INFINITY;
+		if (after < redrawafter)
+			redrawafter = after;
+	}
+	else
+	{
+		/* first change */
+		redrawafter = after;
+		preredraw = pre;
+		postredraw = post;
+	}
+	mustredraw = TRUE;
+}
+
+
+#ifndef NO_CHARATTR
+/* see if a given line uses character attribute strings */
+static int hasattr(lno, text)
+	long		lno;	/* the line# of the cursor */
+	REG char	*text;	/* the text of the line, from fetchline */
+{
+	static long	plno;	/* previous line number */
+	static long	chgs;	/* previous value of changes counter */
+	static int	panswer;/* previous answer */
+	char		*scan;
+
+	/* if charattr is off, then the answer is "no, it doesn't" */
+	if (!*o_charattr)
+	{
+		chgs = 0; /* <- forces us to check if charattr is later set */
+		return FALSE;
+	}
+
+	/* if we already know the answer, return it... */
+	if (lno == plno && chgs == changes)
+	{
+		return panswer;
+	}
+
+	/* get the line & look for "\fX" */
+	if (!text[0] || !text[1] || !text[2])
+	{
+		panswer = FALSE;
+	}
+	else
+	{
+		for (scan = text; scan[2] && !(scan[0] == '\\' && scan[1] == 'f'); scan++)
+		{
+		}
+		panswer = (scan[2] != '\0');
+	}
+
+	/* save the results */
+	plno = lno;
+	chgs = changes;
+
+	/* return the results */
+	return panswer;
+}
+#endif
+
+
+#ifndef NO_VISIBLE
+/* This function checks to make sure that the correct lines are shown in
+ * reverse-video.  This is used to handle the "v" and "V" commands.
+ */
+static long	vizlow, vizhigh;	/* the starting and ending lines */
+static int	vizleft, vizright;	/* starting & ending indicies */
+static int	vizchange;		/* boolean: must use stupid drawtext? */
+static void setviz(curs)
+	MARK		curs;
+{
+	long		newlow, newhigh;
+	long		extra = 0L;
+
+	/* for now, assume the worst... */
+	vizchange = TRUE;
+
+	/* set newlow & newhigh according to V_from and cursor */
+	if (!V_from)
+	{
+		/* no lines should have reverse-video */
+		if (vizlow)
+		{
+			redrawrange(vizlow, vizhigh + 1L, vizhigh + 1L);
+			vizlow = vizhigh = 0L;
+		}
+		else
+		{
+			vizchange = FALSE;
+		}
+		return;
+	}
+
+	/* figure out which lines *SHOULD* have hilites */
+	if (V_from < curs)
+	{
+		newlow = markline(V_from);
+		newhigh = markline(curs);
+		vizleft = markidx(V_from);
+		vizright = markidx(curs) + 1;
+	}
+	else
+	{
+		newlow = markline(curs);
+		newhigh = markline(V_from);
+		vizleft = markidx(curs);
+		vizright = markidx(V_from) + 1;
+	}
+
+	/* adjust for line-mode hiliting */
+	if (V_linemd)
+	{
+		vizleft = 0;
+		vizright = BLKSIZE - 1;
+	}
+	else
+	{
+		extra = 1L;
+	}
+
+	/* arrange for the necessary lines to be redrawn */
+	if (vizlow == 0L)
+	{
+		/* just starting to redraw */
+		redrawrange(newlow, newhigh, newhigh);
+	}
+	else
+	{
+		/* Were new lines added/removed at the front? */
+		if (newlow != vizlow)
+		{
+			if (newlow < vizlow)
+				redrawrange(newlow, vizlow + extra, vizlow + extra);
+			else
+				redrawrange(vizlow, newlow + extra, newlow + extra);
+		}
+
+		/* Were new lines added/removed at the back? */
+		if (newhigh != vizhigh)
+		{
+			if (newhigh < vizhigh)
+				redrawrange(newhigh + 1L - extra, vizhigh + 1L, vizhigh + 1L);
+			else
+				redrawrange(vizhigh + 1L - extra, newhigh, newhigh);
+		}
+	}
+
+	/* remember which lines will contain hilighted text now */
+	vizlow = newlow;
+	vizhigh = newhigh;
+}
+#endif /* !NO_VISIBLE */
+
+
+/* This function converts a MARK to a column number.  It doesn't automatically
+ * adjust for leftcol; that must be done by the calling function
+ */
+int idx2col(curs, text, inputting)
+	MARK		curs;	/* the line# & index# of the cursor */
+	REG char	*text;	/* the text of the line, from fetchline */
+	int		inputting;	/* boolean: called from input() ? */
+{
+	static MARK	pcursor;/* previous cursor, for possible shortcut */
+	static MARK	pcol;	/* column number for pcol */
+	static long	chgs;	/* previous value of changes counter */
+	REG int		col;	/* used to count column numbers */
+	REG int		idx;	/* used to count down the index */
+	REG int		i;
+
+	/* for now, assume we have to start counting at the left edge */
+	col = 0;
+	idx = markidx(curs);
+
+	/* if the file hasn't changed & line number is the same & it has no
+	 * embedded character attribute strings, can we do shortcuts?
+	 */
+	if (chgs == changes
+	 && !((curs ^ pcursor) & ~(BLKSIZE - 1))
+#ifndef NO_CHARATTR
+	 && !hasattr(markline(curs), text)
+#endif
+	)
+	{
+		/* no movement? */
+		if (curs == pcursor)
+		{
+			/* return the column of the char; for tabs, return its last column */
+			if (text[idx] == '\t' && !inputting && !*o_list)
+			{
+				return pcol + *o_tabstop - (pcol % *o_tabstop) - 1;
+			}
+			else
+			{
+				return pcol;
+			}
+		}
+
+		/* movement to right? */
+		if (curs > pcursor)
+		{
+			/* start counting from previous place */
+			col = pcol;
+			idx = markidx(curs) - markidx(pcursor);
+			text += markidx(pcursor);
+		}
+	}
+
+	/* count over to the char after the idx position */
+	while (idx > 0 && (i = *text)) /* yes, ASSIGNMENT! */
+	{
+		if (i == '\t' && !*o_list)
+		{
+			col += *o_tabstop;
+			col -= col % *o_tabstop;
+		}
+		else if (i >= '\0' && i < ' ' || i == '\177')
+		{
+			col += 2;
+		}
+#ifndef NO_CHARATTR
+		else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
+		{
+			text += 2; /* plus one more at bottom of loop */
+			idx -= 2;
+		}			
+#endif
+		else
+		{
+			col++;
+		}
+		text++;
+		idx--;
+	}
+
+	/* save stuff to speed next call */
+	pcursor = curs;
+	pcol = col;
+	chgs = changes;
+
+	/* return the column of the char; for tabs, return its last column */
+	if (*text == '\t' && !inputting && !*o_list)
+	{
+		return col + *o_tabstop - (col % *o_tabstop) - 1;
+	}
+	else
+	{
+		return col;
+	}
+}
+
+
+/* This function is similar to idx2col except that it takes care of sideways
+ * scrolling - for the given line, at least.
+ */
+int mark2phys(m, text, inputting)
+	MARK	m;		/* a mark to convert */
+	char	*text;		/* the line that m refers to */
+	int	inputting;	/* boolean: caled from input() ? */
+{
+	int	i;
+
+	i = idx2col(m, text, inputting);
+	while (i < leftcol)
+	{
+		leftcol -= *o_sidescroll;
+		mustredraw = TRUE;
+		redrawrange(1L, INFINITY, INFINITY);
+	}
+	while (i > rightcol)
+	{
+		leftcol += *o_sidescroll;
+		mustredraw = TRUE;
+		redrawrange(1L, INFINITY, INFINITY);
+	}
+	physrow = markline(m) - topline;
+	physcol = i - leftcol;
+	if (*o_number)
+		physcol += 8;
+
+	return physcol;
+}
+
+/* This function draws a single line of text on the screen.  The screen's
+ * cursor is assumed to be located at the leftmost column of the appropriate
+ * row.
+ */
+static void drawtext(text, lno, clr)
+	REG char	*text;	/* the text to draw */
+	long		lno;	/* the number of the line to draw */
+	int		clr;	/* boolean: do a clrtoeol? */
+{
+	REG int		col;	/* column number */
+	REG int		i;
+	REG int		tabstop;	/* *o_tabstop */
+	REG int		limitcol;	/* leftcol or leftcol + COLS */
+	int		abnormal;	/* boolean: charattr != A_NORMAL? */
+#ifndef NO_VISIBLE
+	int		rev;		/* boolean: standout mode, too? */
+	int		idx = 0;
+#endif
+	char		numstr[9];
+
+	/* show the line number, if necessary */
+	if (*o_number)
+	{
+		sprintf(numstr, "%6ld |", lno);
+		qaddstr(numstr);
+	}
+
+#ifndef NO_SENTENCE
+	/* if we're hiding format lines, and this is one of them, then hide it */
+	if (*o_hideformat && *text == '.')
+	{
+		clrtoeol();
+#if OSK
+		qaddch('\l');
+#else
+		qaddch('\n');
+#endif
+		return;
+	}
+#endif
+
+	/* move some things into registers... */
+	limitcol = leftcol;
+	tabstop = *o_tabstop;
+	abnormal = FALSE;
+
+#ifndef CRUNCH
+	if (clr)
+		clrtoeol();
+#endif
+
+	/* skip stuff that was scrolled off left edge */
+	for (col = 0;
+	     (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */
+	     text++)
+	{
+#ifndef NO_VISIBLE
+		idx++;
+#endif
+		if (i == '\t' && !*o_list)
+		{
+			col = col + tabstop - (col % tabstop);
+		}
+		else if (i >= 0 && i < ' ' || i == '\177')
+		{
+			col += 2;
+		}
+#ifndef NO_CHARATTR
+		else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
+		{
+			text += 2; /* plus one more as part of "for" loop */
+
+			/* since this attribute might carry over, we need it */
+			switch (*text)
+			{
+			  case 'R':
+			  case 'P':
+				attrset(A_NORMAL);
+				abnormal = FALSE;
+				break;
+
+			  case 'B':
+				attrset(A_BOLD);
+				abnormal = TRUE;
+				break;
+
+			  case 'U':
+				attrset(A_UNDERLINE);
+				abnormal = TRUE;
+				break;
+
+			  case 'I':
+				attrset(A_ALTCHARSET);
+				abnormal = TRUE;
+				break;
+			}
+		}
+#endif
+		else
+		{
+			col++;
+		}
+	}
+
+#ifndef NO_VISIBLE
+	/* Should we start hiliting at the first char of this line? */
+	if ((lno > vizlow && lno <= vizhigh
+	    || lno == vizlow && vizleft < idx)
+	   && !(lno == vizhigh && vizright < idx))
+	{
+		do_VISIBLE();
+		rev = TRUE;
+	}
+#endif
+
+	/* adjust for control char that was partially visible */
+	while (col > limitcol)
+	{
+		qaddch(' ');
+		limitcol++;
+	}
+
+	/* now for the visible characters */
+	limitcol = leftcol + COLS;
+	if (*o_number)
+		limitcol -= 8;
+	for (; (i = *text) && col < limitcol; text++)
+	{
+#ifndef NO_VISIBLE
+		/* maybe turn hilite on/off in the middle of the line */
+		if (lno == vizlow && vizleft == idx)
+		{
+			do_VISIBLE();
+			rev = TRUE;
+		}
+		if (lno == vizhigh && vizright == idx)
+		{
+			do_SE();
+			rev = FALSE;
+		}
+		idx++;
+
+		/* if hiliting, never emit physical tabs */
+		if (rev && i == '\t' && !*o_list)
+		{
+			i = col + tabstop - (col % tabstop);
+			do
+			{
+				qaddch(' ');
+				col++;
+			} while (col < i);
+		}
+		else
+#endif /* !NO_VISIBLE */
+		if (i == '\t' && !*o_list)
+		{
+			i = col + tabstop - (col % tabstop);
+			if (i < limitcol)
+			{
+#ifdef CRUNCH
+				if (!clr && has_PT && !((i - leftcol) & 7))
+#else
+				if (has_PT && !((i - leftcol) & 7))
+#endif
+				{
+					do
+					{
+						qaddch('\t');
+						col += 8; /* not exact! */
+					} while (col < i);
+					col = i; /* NOW it is exact */
+				}
+				else
+				{
+					do
+					{
+						qaddch(' ');
+						col++;
+					} while (col < i);
+				}
+			}
+			else /* tab ending after screen? next line! */
+			{
+				col = limitcol;
+				if (has_AM)
+				{
+					addch('\n');	/* GB */
+				}
+			}
+		}
+		else if (i >= 0 && i < ' ' || i == '\177')
+		{
+			col += 2;
+			qaddch('^');
+			if (col <= limitcol)
+			{
+				qaddch(i ^ '@');
+			}
+		}
+#ifndef NO_CHARATTR
+		else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
+		{
+			text += 2; /* plus one more as part of "for" loop */
+			switch (*text)
+			{
+			  case 'R':
+			  case 'P':
+				attrset(A_NORMAL);
+				abnormal = FALSE;
+				break;
+
+			  case 'B':
+				attrset(A_BOLD);
+				abnormal = TRUE;
+				break;
+
+			  case 'U':
+				attrset(A_UNDERLINE);
+				abnormal = TRUE;
+				break;
+
+			  case 'I':
+				attrset(A_ALTCHARSET);
+				abnormal = TRUE;
+				break;
+			}
+		}
+#endif
+		else
+		{
+			col++;
+			qaddch(i);
+		}
+	}
+
+	/* get ready for the next line */
+#ifndef NO_CHARATTR
+	if (abnormal)
+	{
+		attrset(A_NORMAL);
+	}
+#endif
+	if (*o_list && col < limitcol)
+	{
+		qaddch('$');
+		col++;
+	}
+
+#ifndef NO_VISIBLE
+	/* did we hilite this whole line?  If so, STOP! */
+	if (rev)
+	{
+		do_SE();
+	}
+#endif
+
+#ifdef CRUNCH
+	if (clr && col < limitcol)
+	{
+		clrtoeol();
+	}
+#endif
+	if (!has_AM || col < limitcol)
+	{
+		addch('\n');
+	}
+
+	wqrefresh();
+}
+
+
+#ifndef CRUNCH
+static void nudgecursor(same, scan, new, lno)
+	int	same;	/* number of chars to be skipped over */
+	char	*scan;	/* where the same chars end */
+	char	*new;	/* where the visible part of the line starts */
+	long	lno;	/* line number of this line */
+{
+	int	col;
+
+	if (same > 0)
+	{
+		if (same < 5)
+		{
+			/* move the cursor by overwriting */
+			while (same > 0)
+			{
+				qaddch(scan[-same]);
+				same--;
+			}
+		}
+		else
+		{
+			/* move the cursor by calling move() */
+			col = (int)(scan - new);
+			if (*o_number)
+				col += 8;
+			move((int)(lno - topline), col);
+		}
+	}
+}
+#endif /* not CRUNCH */
+
+/* This function draws a single line of text on the screen, possibly with
+ * some cursor optimization.  The cursor is repositioned before drawing
+ * begins, so its position before doesn't really matter.
+ */
+static void smartdrawtext(text, lno, showit)
+	REG char	*text;	/* the text to draw */
+	long		lno;	/* line number of the text */
+	int		showit;	/* boolean: output line? (else just remember it) */
+{
+#ifdef CRUNCH
+	move((int)(lno - topline), 0);
+	if (showit)
+	{
+		drawtext(text, lno, TRUE);
+	}
+#else /* not CRUNCH */
+	static char	old[256];	/* how the line looked last time */
+	char		new[256];	/* how it looks now */
+	char		*build;		/* used to put chars into new[] */
+	char		*scan;		/* used for moving thru new[] or old[] */
+	char		*end;		/* last non-blank changed char */
+	char		*shift;		/* used to insert/delete chars */
+	int		same;		/* length of a run of unchanged chars */
+	int		limitcol;
+	int		col;
+	int		i;
+	char		numstr[9];
+
+# ifndef NO_CHARATTR
+	/* if this line has attributes, do it the dumb way instead */
+	if (hasattr(lno, text))
+	{
+		move((int)(lno - topline), 0);
+		drawtext(text, lno, TRUE);
+		return;
+	}
+# endif
+# ifndef NO_SENTENCE
+	/* if this line is a format line, & we're hiding format lines, then
+	 * let the dumb drawtext() function handle it
+	 */
+	if (*o_hideformat && *text == '.')
+	{
+		move((int)(lno - topline), 0);
+		drawtext(text, lno, TRUE);
+		return;
+	}
+# endif
+# ifndef NO_VISIBLE
+	if (vizchange)
+	{
+		move((int)(lno - topline), 0);
+		drawtext(text, lno, TRUE);
+		smartlno = 0L;
+		return;
+	}
+# endif
+
+	/* skip stuff that was scrolled off left edge */
+	limitcol = leftcol;
+	for (col = 0;
+	     (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */
+	     text++)
+	{
+		if (i == '\t' && !*o_list)
+		{
+			col = col + *o_tabstop - (col % *o_tabstop);
+		}
+		else if (i >= 0 && i < ' ' || i == '\177')
+		{
+			col += 2;
+		}
+		else
+		{
+			col++;
+		}
+	}
+
+	/* adjust for control char that was partially visible */
+	build = new;
+	while (col > limitcol)
+	{
+		*build++ = ' ';
+		limitcol++;
+	}
+
+	/* now for the visible characters */
+	limitcol = leftcol + COLS;
+	if (*o_number)
+		limitcol -= 8;
+	for (; (i = *text) && col < limitcol; text++)
+	{
+		if (i == '\t' && !*o_list)
+		{
+			i = col + *o_tabstop - (col % *o_tabstop);
+			while (col < i && col < limitcol)
+			{
+				*build++ = ' ';
+				col++;
+			}
+		}
+		else if (i >= 0 && i < ' ' || i == '\177')
+		{
+			col += 2;
+			*build++ = '^';
+			if (col <= limitcol)
+			{
+				*build++ = (i ^ '@');
+			}
+		}
+		else
+		{
+			col++;
+			*build++ = i;
+		}
+	}
+	if (col < limitcol && *o_list)
+	{
+		*build++ = '$';
+		col++;
+	}
+	end = build;
+	while (col < limitcol)
+	{
+		*build++ = ' ';
+		col++;
+	}
+
+	/* if we're just supposed to remember this line, then remember it */
+	if (!showit)
+	{
+		smartlno = lno;
+		strncpy(old, new, COLS);
+		return;
+	}
+
+	/* locate the last non-blank character */
+	while (end > new && end[-1] == ' ')
+	{
+		end--;
+	}
+
+	/* can we optimize the displaying of this line? */
+	if (lno != smartlno)
+	{
+		/* nope, can't optimize - different line */
+		move((int)(lno - topline), 0);
+
+		/* show the line number, if necessary */
+		if (*o_number)
+		{
+			sprintf(numstr, "%6ld |", lno);
+			qaddstr(numstr);
+		}
+
+		/* show the new line */
+		for (scan = new, build = old; scan < end; )
+		{
+			qaddch(*scan);
+			*build++ = *scan++;
+		}
+		if (end < new + COLS - (*o_number ? 8 : 0))
+		{
+			clrtoeol();
+			while (build < old + COLS)
+			{
+				*build++ = ' ';
+			}
+		}
+		smartlno = lno;
+		return;
+	}
+
+	/* skip any initial unchanged characters */
+	for (scan = new, build = old; scan < end && *scan == *build; scan++, build++)
+	{
+	}
+	i = (scan - new);
+	if (*o_number)
+		i += 8;
+	move((int)(lno - topline), i);
+
+	/* The in-between characters must be changed */
+	same = 0;
+	while (scan < end)
+	{
+		/* is this character a match? */
+		if (scan[0] == build[0])
+		{
+			same++;
+		}
+		else /* do we want to insert? */
+		if (scan < end - 1 && scan[1] == build[0] && (has_IC || has_IM))
+		{
+			nudgecursor(same, scan, new, lno);
+			same = 0;
+
+			insch(*scan);
+			for (shift = old + COLS; --shift > build; )
+			{
+				shift[0] = shift[-1];
+			}
+			*build = *scan;
+		}
+		else /* do we want to delete? */
+		if (build < old + COLS - 1 && scan[0] == build[1] && has_DC)
+		{
+			nudgecursor(same, scan, new, lno);
+			same = 0;
+
+			delch();
+			same++;
+			for (shift = build; shift < old + COLS - 1; shift++)
+			{
+				shift[0] = shift[1];
+			}
+			if (*o_number)
+				shift -= 8;
+			*shift = ' ';
+		}
+		else /* we must overwrite */
+		{
+			nudgecursor(same, scan, new, lno);
+			same = 0;
+
+			addch(*scan);
+			*build = *scan;
+		}
+
+		build++;
+		scan++;
+	}
+
+	/* maybe clear to EOL */
+	end = old + COLS - (*o_number ? 8 : 0);
+	while (build < end && *build == ' ')
+	{
+		build++;
+	}
+	if (build < end)
+	{
+		nudgecursor(same, scan, new, lno);
+		same = 0;
+
+		clrtoeol();
+		while (build < old + COLS)
+		{
+			*build++ = ' ';
+		}
+	}
+#endif /* not CRUNCH */
+}
+
+
+/* This function is used in visual mode for drawing the screen (or just parts
+ * of the screen, if that's all thats needed).  It also takes care of
+ * scrolling.
+ */
+void redraw(curs, inputting)
+	MARK	curs;		/* where to leave the screen's cursor */
+	int	inputting;	/* boolean: being called from input() ? */
+{
+	char		*text;		/* a line of text to display */
+	static long	chgs;		/* previous changes level */
+	long		l;
+	int		i;
+#ifndef CRUNCH
+	static long	showtop;	/* top line in window */
+	static long	showbottom;	/* bottom line in window */
+#endif
+
+	/* if curs == MARK_UNSET, then we should reset internal vars */
+	if (curs == MARK_UNSET)
+	{
+		if (topline < 1 || topline > nlines)
+		{
+			topline = 1L;
+		}
+		else
+		{
+			move(LINES - 1, 0);
+			clrtoeol();
+		}
+		leftcol = 0;
+		mustredraw = TRUE;
+		redrawafter = INFINITY;
+		preredraw = 0L;
+		postredraw = 0L;
+		chgs = 0;
+		smartlno = 0L;
+#ifndef NO_VISIBLE
+		vizlow = vizhigh = 0L;
+		vizchange = FALSE;
+#endif
+#ifndef CRUNCH
+		showtop = 0;
+		showbottom = INFINITY;
+#endif
+		return;
+	}
+
+#ifndef NO_VISIBLE
+	/* adjustments to hilited area may force extra lines to be redrawn. */
+	setviz(curs);
+#endif
+
+	/* figure out which column the cursor will be in */
+	l = markline(curs);
+	text = fetchline(l);
+	mark2phys(curs, text, inputting);
+
+#ifndef NO_COLOR
+	fixcolor();
+#endif
+
+	/* adjust topline, if necessary, to get the cursor on the screen */
+	if (l >= topline && l <= botline)
+	{
+		/* it is on the screen already */
+
+		/* if the file was changed but !mustredraw, then redraw line */
+		if (!mustredraw && (chgs != changes
+#ifndef NO_VISIBLE
+			|| V_from
+#endif
+#ifndef CRUNCH
+			|| l < showtop || l > showbottom
+#endif
+							))
+		{
+			smartdrawtext(text, l, (chgs != changes));
+		}
+	}
+	else if (l < topline && l > topline - LINES && (has_SR || has_AL))
+	{
+		/* near top - scroll down */
+		if (!mustredraw)
+		{
+			move(0,0);
+			while (l < topline)
+			{
+				topline--;
+				if (has_SR)
+				{
+					do_SR();
+				}
+				else
+				{
+					insertln();
+				}
+				text = fetchline(topline);
+				drawtext(text, topline, FALSE);
+				do_UP();
+			}
+
+			/* blank out the last line */
+			move(LINES - 1, 0);
+			clrtoeol();
+		}
+		else
+		{
+			topline = l;
+			redrawrange(0L, INFINITY, INFINITY);
+		}
+	}
+	else if (l > topline && l < botline + LINES)
+	{
+		/* near bottom -- scroll up */
+		if (!mustredraw)
+		{
+			move(LINES - 1,0);
+			clrtoeol();
+			while (l > botline)
+			{
+				topline++; /* <-- also adjusts botline */
+				text = fetchline(botline);
+				drawtext(text, botline, FALSE);
+			}
+#ifndef CRUNCH
+			showbottom = l;
+#endif
+		}
+		else
+		{
+			topline = l - (LINES - 2);
+			redrawrange(0L, INFINITY, INFINITY);
+		}
+	}
+	else
+	{
+		/* distant line - center it & force a redraw */
+		topline = l - (LINES / 2) - 1;
+		if (topline < 1)
+		{
+			topline = 1;
+		}
+		redrawrange(0L, INFINITY, INFINITY);
+		changes++;
+	}
+
+#ifndef CRUNCH
+	/* make sure the current line is included in the "window" */
+	if (l < showtop)
+	{
+		redrawrange(l, showtop, showtop);
+		showtop = l;
+	}
+	if (l > showbottom)
+	{
+		redrawrange(showbottom, l, l);
+		showbottom = l;
+	}
+#endif
+
+
+	/* Now... do we really have to redraw? */
+	if (mustredraw)
+	{
+		/* If redrawfter (and friends) aren't set, assume we should
+		 * redraw everything.
+		 */
+		if (redrawafter == INFINITY)
+		{
+			redrawafter = 0L;
+			preredraw = postredraw = INFINITY;
+		}
+
+#ifndef CRUNCH
+		/* shrink the window, if possible */
+		if (showtop < topline)
+		{
+			showtop = topline;
+		}
+		if (showbottom > botline)
+		{
+			showbottom = botline;
+		}
+		if (postredraw == INFINITY)
+		{
+			/* these will be set to more reasonable values later */
+			showtop = INFINITY;
+			showbottom = 0L;
+		}
+#endif
+
+		/* adjust smartlno to correspond with inserted/deleted lines */
+		if (smartlno >= redrawafter)
+		{
+			if (smartlno < preredraw && postredraw != preredraw) /*!!!*/
+			{
+				smartlno = 0L;
+			}
+			else
+			{
+				smartlno += (postredraw - preredraw);
+			}
+		}
+
+		/* should we insert some lines into the screen? */
+		if (preredraw < postredraw && preredraw <= botline)
+		{
+			/* lines were inserted into the file */
+
+			/* decide where insertion should start */
+			if (preredraw < topline)
+			{
+				l = topline;
+			}
+			else
+			{
+				l = preredraw;
+			}
+
+			/* insert the lines... maybe */
+			if (l + postredraw - preredraw > botline || !has_AL || *o_number)
+			{
+				/* Whoa!  a whole screen full - just redraw */
+				preredraw = postredraw = INFINITY;
+			}
+			else
+			{
+				/* really insert 'em */
+				move((int)(l - topline), 0);
+				for (i = postredraw - preredraw; i > 0; i--)
+				{
+					insertln();
+				}
+
+				/* NOTE: the contents of those lines will be
+				 * drawn as part of the regular redraw loop.
+				 */
+
+				/* clear the last line */
+				move(LINES - 1, 0);
+				clrtoeol();
+			}
+		}
+
+		/* do we want to delete some lines from the screen? */
+		if (preredraw > postredraw && postredraw <= botline)
+		{
+			if (preredraw > botline || !has_DL || *o_number)
+			{
+				postredraw = preredraw = INFINITY;
+			}
+			else /* we'd best delete some lines from the screen */
+			{
+				/* clear the last line, so it doesn't look
+				 * ugly as it gets pulled up into the screen
+				 */
+				move(LINES - 1, 0);
+				clrtoeol();
+
+				/* delete the lines */
+				move((int)(postredraw - topline), 0);
+			 	for (l = postredraw;
+				     l < preredraw && l <= botline;
+				     l++)
+				{
+					deleteln();
+				}
+
+				/* draw the lines that are now newly visible
+				 * at the bottom of the screen
+				 */
+				i = LINES - 1 + (postredraw - preredraw);
+				move(i, 0);
+				for (l = topline + i; l <= botline; l++)
+				{
+					/* clear this line */
+					clrtoeol();
+
+					/* draw the line, or ~ for non-lines */
+					if (l <= nlines)
+					{
+						text = fetchline(l);
+						drawtext(text, l, FALSE);
+					}
+					else
+					{
+						addstr("~\n");
+					}
+				}
+			}
+		}
+
+		/* redraw the current line */
+		l = markline(curs);
+		pfetch(l);
+		smartdrawtext(ptext, l, TRUE);
+
+#ifndef CRUNCH
+		/* decide which lines must be in the "window" around the cursor */
+		l = markline(curs);
+		if ((*o_window & 0xff) + 1 == LINES)
+		{
+			showtop = 1;
+			showbottom = INFINITY;
+		}
+		else if (l < showtop || l > showbottom)
+		{
+			l -= (*o_window & 0xff) / 2;
+			if (l < topline)
+			{
+				l = topline;
+			}
+			if (l < showtop)
+			{
+				showtop = l;
+			}
+			l += (*o_window & 0xff) - 1;
+			if (l > botline)
+			{
+				showtop = showtop - l + botline;
+				l = botline;
+			}
+			if (l > showbottom)
+			{
+				showbottom = l;
+			}
+		}
+#endif
+
+		/* decide where we should start redrawing from */
+		if (redrawafter < topline)
+		{
+			l = topline;
+		}
+		else
+		{
+			l = redrawafter;
+		}
+		if (l <= botline && l < postredraw && (l != smartlno || botline != smartlno))
+		{
+			/* draw the other lines */
+			move((int)(l - topline), 0);
+			for (; l <= botline && l < postredraw; l++)
+			{
+				/* we already drew the current line, so skip it now */
+				if (l == smartlno)
+				{
+#if OSK
+					qaddch('\l');
+#else
+					qaddch('\n');
+#endif
+					continue;
+				}
+
+				/* draw the line, or ~ for non-lines */
+				if (l > nlines)
+				{
+					qaddch('~');
+					clrtoeol();
+					addch('\n');
+				}
+#ifndef CRUNCH
+				else if (l < showtop || l > showbottom)
+				{
+					qaddch('@');
+					clrtoeol();
+					addch('\n');
+				}
+#endif
+				else
+				{
+					text = fetchline(l);
+					drawtext(text, l, TRUE);
+				}
+			}
+		}
+
+		mustredraw = FALSE;
+	}
+
+	/* force total (non-partial) redraw next time if not set */
+	redrawafter = INFINITY;
+	preredraw = 0L;
+	postredraw = 0L;
+
+	/* move the cursor to where it belongs */
+	move((int)(markline(curs) - topline), physcol);
+	wqrefresh();
+
+	chgs = changes;
+}
Index: /trunk/minix/commands/elvis/ref.c
===================================================================
--- /trunk/minix/commands/elvis/ref.c	(revision 9)
+++ /trunk/minix/commands/elvis/ref.c	(revision 9)
@@ -0,0 +1,521 @@
+/* ref2.c */
+
+/* This is a totally rewritten version of ref.  This version looks for the
+ * desired function name in the "tags" file, and then reads the header out
+ * from the source file.  There is no longer any need for a "refs" file.
+ *
+ * Usage:	ref [-a] [-t] [-f file] [-c class] tag
+ * Options:	-t	   output tag info, not the description
+ *		-f file	   default filename for static functions
+ *		-c class   default class names for class functions
+ */
+
+#include <stdio.h>
+#include "config.h"
+extern char	*getenv();
+extern char	*fgets();
+
+
+/* This is the default path that is searched for tags */
+#if OSK
+# define DEFTAGPATH ".:/dd/defs:/dd/defs/sys:/dd/usr/src/lib:../lib:/dd/usr/lib"
+#else
+# if ANY_UNIX
+#  define DEFTAGPATH ".:/usr/include:/usr/include/sys:/usr/src/lib:../lib:/usr/local/lib"
+# else
+#  if MSDOS || TOS
+#   define DEFTAGPATH ".;C:\\include;C:\\include\\sys;C:\\lib;..\\lib"
+#   define SEP ';'
+#  else
+#   if AMIGA
+#    define DEFTAGPATH ".;Include:;Include:sys"
+#    define SEP ';'
+#   else /* any other OS */
+#    define DEFTAGPATH "."
+#   endif
+#  endif
+# endif
+#endif
+
+#ifndef SEP
+# define SEP ':'
+#endif
+
+
+/* These variables reflect the command-line options given by the user. */
+int	taginfo;	/* boolean: give only the tag info? (not header?) */
+char	*def_file;	/* default filename for static functions */
+char	*def_class;	/* default classname for class members */
+int	colons;		/* #colons in tag: 0=normal, 1=static, 2=member */
+
+/* This function checks for a tag in the "tags" file of given directory.
+ * If the tag is found, then it returns a pointer to a static buffer which
+ * contains the filename, a tab character, and a linespec for finding the
+ * the tag.  If the tag is not found in the "tags" file, or if the "tags"
+ * file cannot be opened or doesn't exist, then this function returns NULL.
+ */
+char *cktagdir(tag, dir)
+	char	*tag;	/* name of the tag to look for */
+	char	*dir;	/* name of the directory to check */
+{
+	char	buf[BLKSIZE];
+	static char found[BLKSIZE];
+	FILE	*tfile;
+	int	len;
+
+#if AMIGA
+	if (dir[strlen(dir) - 1] == COLON)
+	    sprintf(buf, "%s%s", dir, TAGS);   /* no slash after colon. */
+	else
+#endif
+	/* construct the name of the "tags" file in this directory */
+	sprintf(buf, "%s%c%s", dir, SLASH, TAGS);
+
+	/* Try to open the tags file.  Return NULL if can't open */
+#if AMIGA
+	if (buf[0] == '.' && buf[1] == SLASH)
+	    tfile = fopen(&buf[2], "r");
+	else
+#endif
+	tfile = fopen(buf, "r");
+	if (!tfile)
+	{
+		return (char *)0;
+	}
+
+	/* compute the length of the tagname once */
+	len = strlen(tag);
+
+	/* read lines until we get the one for this tag */
+	found[0] = '\0';
+	while (fgets(buf, sizeof buf, tfile))
+	{
+		/* is this the one we want? */
+		if (!strncmp(buf, tag, len) && buf[len] == '\t')
+		{
+			/* we've found a match -- remember it */
+			strcpy(found, buf);
+
+			/* if there is no default file, or this match is in
+			 * the default file, then we've definitely found the
+			 * one we want.  Break out of the loop now.
+			 */
+			if (!def_file || !strncmp(&buf[len + 1], def_file, strlen(def_file)))
+			{
+				break;
+			}
+		}
+	}
+
+	/* we're through reading */
+	fclose(tfile);
+
+	/* if there's anything in found[], use it */
+	if (found[0])
+	{
+		return &found[len + 1];
+	}
+
+	/* else we didn't find it */
+	return (char *)0;
+}
+
+/* This function reads a single textline from a binary file.  It returns
+ * the number of bytes read, or 0 at EOF.
+ */
+int getline(buf, limit, fp)
+	char	*buf;	/* buffer to read into */
+	int	limit;	/* maximum characters to read */
+	FILE	*fp;	/* binary stream to read from */
+{
+	int	bytes;	/* number of bytes read so far */
+	int	ch;	/* single character from file */
+
+	for (bytes = 0, ch = 0; ch != '\n' && --limit > 0 && (ch = getc(fp)) != EOF; bytes++)
+	{
+#if MSDOS || TOS
+		/* since this is a binary file, we'll need to manually strip CR's */
+		if (ch == '\r')
+		{
+			continue;
+		}
+#endif
+		*buf++ = ch;
+	}
+	*buf = '\0';
+
+	return bytes;
+}
+
+
+/* This function reads a source file, looking for a given tag.  If it finds
+ * the tag, then it displays it and returns TRUE.  Otherwise it returns FALSE.
+ * To display the tag, it attempts to output any introductory comment, the
+ * tag line itself, and any arguments.  Arguments are assumed to immediately
+ * follow the tag line, and start with whitespace.  Comments are assumed to
+ * start with lines that begin with "/*", "//", "(*", or "--", and end at the
+ * tag line or at a blank line.
+ */
+int lookup(dir, entry)
+	char	*dir;	/* name of the directory that contains the source */
+	char	*entry;	/* source filename, <Tab>, linespec */
+{
+	char	buf[BLKSIZE];	/* pathname of sourcefile */
+	long	lnum;		/* line number */
+	long	here;		/* seek position where current line began */
+	long	comment;	/* seek position of introductory comment, or -1L */
+	FILE	*sfile;		/* used for reading the source file */
+	int	len;		/* length of string */
+	char	*ptr;
+
+
+	/* construct the pathname of the source file */
+	strcpy(buf, dir);
+	ptr = buf + strlen(buf);
+#if AMIGA
+	if (ptr[-1] != COLON)
+#endif
+	*ptr++ = SLASH;
+	while (*entry != '\t')
+	{
+		*ptr++ = *entry++;
+	}
+	*ptr = '\0';
+	entry++;
+
+	/* searching for string or number? */
+	if (*entry >= '0' && *entry <= '9')
+	{
+		/* given a specific line number */
+		lnum = atol(entry);
+		entry = (char *)0;
+	}
+	else
+	{
+		/* given a string -- strip off "/^" and "$/\n" */
+		entry += 2;
+		len = strlen(entry) - 2;
+		if (entry[len - 1] == '$')
+		{
+			entry[len - 1] = '\n';
+		}
+		lnum = 0L;
+	}
+
+	/* Open the file.  Note that we open the file in binary mode even
+	 * though we know it is a text file, because ftell() and fseek()
+	 * don't work on text files.
+	 */
+#if MSDOS || TOS
+	sfile = fopen(buf, "rb");
+#else
+# if AMIGA
+	if (buf[0] == '.' && buf[1] == SLASH)
+	    sfile = fopen(&buf[2], "r");
+	else
+# endif
+	sfile = fopen(buf, "r");
+#endif
+	if (!sfile)
+	{
+		/* can't open the real source file.  Try "refs" instead */
+#if AMIGA
+		if (dir[strlen(dir) - 1] == COLON)
+			sprintf(buf, "%srefs", dir);
+		else
+#endif
+		sprintf(buf, "%s%crefs", dir, SLASH);
+#if MSDOS || TOS
+		sfile = fopen(buf, "rb");
+#else
+# if AMIGA
+		if (buf[0] == '.' && buf[1] == SLASH)
+		    sfile = fopen(&buf[2], "r");
+		else
+# endif
+		sfile = fopen(buf, "r");
+#endif
+		if (!sfile)
+		{
+			/* failed! */
+			return 0;
+		}
+	}
+
+	/* search the file */
+	for (comment = -1L; here = ftell(sfile), getline(buf, BLKSIZE, sfile) > 0; )
+	{
+		/* Is this the start/end of a comment? */
+		if (comment == -1L)
+		{
+			/* starting a comment? */
+			if (buf[0] == '/' && buf[1] == '*'
+			 || buf[0] == '/' && buf[1] == '/'
+			 || buf[0] == '(' && buf[1] == '*'
+			 || buf[0] == '-' && buf[1] == '-')
+			{
+				comment = here;
+			}
+		}
+		else
+		{
+			/* ending a comment? */
+			if (buf[0] == '\n' || buf[0] == '#')
+			{
+				comment = -1L;
+			}
+		}
+
+		/* is this the tag line? */
+		if (--lnum == 0L || (entry && !strncmp(buf, entry, len)))
+		{
+			/* if there were introductory comments, show them */
+			if (comment != -1L)
+			{
+				fseek(sfile, comment, 0);
+				while (comment != here)
+				{
+					getline(buf, BLKSIZE, sfile);
+					fputs(buf, stdout);
+					comment = ftell(sfile);
+				}
+
+				/* re-fetch the tag line */
+				fgets(buf, BLKSIZE, sfile);
+			}
+
+			/* show the tag line */
+			fputs(buf, stdout);
+
+			/* show any argument lines */
+			while (getline(buf, BLKSIZE, sfile) > 0
+			    && buf[0] != '#'
+			    && strchr(buf, '{') == (char *)0)
+			{
+				fputs(buf, stdout);
+			}
+
+			/* Done!  Close the file, and return TRUE */
+			fclose(sfile);
+			return 1;
+		}
+	}
+
+	/* not found -- return FALSE */
+	return 0;
+}
+
+/* This function searches through the entire search path for a given tag.
+ * If it finds the tag, then it displays the info and returns TRUE;
+ * otherwise it returns FALSE.
+ */
+int find(tag)
+	char	*tag;	/* the tag to look up */
+{
+	char	*tagpath;
+	char	dir[80];
+	char	*ptr;
+	int	len;
+
+	if (colons == 1)
+	{
+		/* looking for static function -- only look in current dir */
+		tagpath = ".";
+	}
+	else
+	{
+		/* get the tagpath from the environment.  Default to DEFTAGPATH */
+		tagpath = getenv("TAGPATH");
+		if (!tagpath)
+		{
+			tagpath = DEFTAGPATH;
+		}
+	}
+
+	/* for each entry in the path... */
+	while (*tagpath)
+	{
+		/* Copy the entry into the dir[] buffer */
+		for (ptr = dir; *tagpath && *tagpath != SEP; tagpath++)
+		{
+			*ptr++ = *tagpath;
+		}
+		if (*tagpath == SEP)
+		{
+			tagpath++;
+		}
+
+		/* if the entry ended with "/tags", then strip that off */
+		len = strlen(TAGS);
+		if (&dir[len] < ptr && ptr[-len - 1] == SLASH && !strncmp(&ptr[-len], TAGS, len))
+		{
+			ptr -= len + 1;
+		}
+
+		/* if the entry is now an empty string, then assume "." */
+		if (ptr == dir)
+		{
+			*ptr++ = '.';
+		}
+		*ptr = '\0';
+
+		/* look for the tag in this path.  If found, then display it
+		 * and exit.
+		 */
+		ptr = cktagdir(tag, dir);
+		if (ptr)
+		{
+			/* just supposed to display tag info? */
+			if (taginfo)
+			{
+				/* then do only that! */
+				if (strcmp(dir, "."))
+				{
+					printf("%s%c%s", dir, SLASH, ptr);
+				}
+				else
+				{
+					/* avoid leading "./" if possible */
+					fputs(ptr, stdout);
+				}
+				return 1;
+			}
+			else
+			{
+				/* else look up the declaration of the thing */
+				return lookup(dir, ptr);
+			}
+		}
+	}
+
+	/* if we get here, then the tag wasn't found anywhere */
+	return 0;
+}
+
+void usage()
+{
+	fputs("usage: ref [-a] [-t] [-c class] [-f file] tag\n", stderr);
+	fputs("   -a        function's args may be flush against left margin\n", stderr);
+	fputs("   -t        output tag info, instead of the function header\n", stderr);
+	fputs("   -f File   tag might be a static function in File\n", stderr);
+	fputs("   -c Class  tag might be a member of class Class\n", stderr);
+	exit(2);
+}
+
+
+int countcolons(str)
+	char	*str;
+{
+	while (*str != ':' && *str)
+	{
+		str++;
+	}
+	if (str[0] != ':')
+	{
+		return 0;
+	}
+	else if (str[1] != ':')
+	{
+		return 1;
+	}
+	return 2;
+}
+
+int main(argc, argv)
+	int	argc;
+	char	**argv;
+{
+	char	def_tag[100];	/* used to build tag name with default file/class */
+	int	i;
+
+	/* parse flags */
+	for (i = 1; i < argc && argv[i][0] == '-'; i++)
+	{
+		switch (argv[i][1])
+		{
+		  case 't':
+			taginfo = 1;
+			break;
+
+		  case 'f':
+			if (argv[i][2])
+			{
+				def_file = &argv[i][2];
+			}
+			else if (++i < argc)
+			{
+				def_file = argv[i];
+			}
+			else
+			{
+				usage();
+			}
+			break;
+
+		  case 'c':
+			if (argv[i][2])
+			{
+				def_class = &argv[i][2];
+			}
+			else if (++i < argc)
+			{
+				def_class = argv[i];
+			}
+			else
+			{
+				usage();
+			}
+			break;
+
+		  default:
+			usage();
+		}
+	}
+
+	/* if no tag was given, complain */
+	if (i + 1 != argc)
+	{
+		usage();
+	}
+
+	/* does the tag have an explicit class or file? */
+	colons = countcolons(argv[i]);
+
+	/* if not, then maybe try some defaults */
+	if (colons == 0)
+	{
+		/* try a static function in the file first */
+		if (def_file)
+		{
+			sprintf(def_tag, "%s:%s", def_file, argv[i]);
+			colons = 1;
+			if (find(def_tag))
+			{
+				exit(0);
+			}
+		}
+
+		/* try a member function for a class */
+		if (def_class)
+		{
+			sprintf(def_tag, "%s::%s", def_class, argv[i]);
+			colons = 2;
+			if (find(def_tag))
+			{
+				exit(0);
+			}
+		}
+
+		/* oh, well */
+		colons = 0;
+	}
+
+	/* find the tag */
+	if (find(argv[i]))
+	{
+		exit(0);
+	}
+
+	exit(1);
+	/*NOTREACHED*/
+}
Index: /trunk/minix/commands/elvis/regexp.c
===================================================================
--- /trunk/minix/commands/elvis/regexp.c	(revision 9)
+++ /trunk/minix/commands/elvis/regexp.c	(revision 9)
@@ -0,0 +1,934 @@
+/* regexp.c */
+
+/* This file contains the code that compiles regular expressions and executes
+ * them.  It supports the same syntax and features as vi's regular expression
+ * code.  Specifically, the meta characters are:
+ *	^	matches the beginning of a line
+ *	$	matches the end of a line
+ *	\<	matches the beginning of a word
+ *	\>	matches the end of a word
+ *	.	matches any single character
+ *	[]	matches any character in a character class
+ *	\(	delimits the start of a subexpression
+ *	\)	delimits the end of a subexpression
+ *	*	repeats the preceding 0 or more times
+ * NOTE: You cannot follow a \) with a *.
+ *
+ * The physical structure of a compiled RE is as follows:
+ *	- First, there is a one-byte value that says how many character classes
+ *	  are used in this regular expression
+ *	- Next, each character class is stored as a bitmap that is 256 bits
+ *	  (32 bytes) long.
+ *	- A mixture of literal characters and compiled meta characters follows.
+ *	  This begins with M_BEGIN(0) and ends with M_END(0).  All meta chars
+ *	  are stored as a \n followed by a one-byte code, so they take up two
+ *	  bytes apiece.  Literal characters take up one byte apiece.  \n can't
+ *	  be used as a literal character.
+ *
+ * If NO_MAGIC is defined, then a different set of functions is used instead.
+ * That right, this file contains TWO versions of the code.
+ */
+
+#include <setjmp.h>
+#include "config.h"
+#include "ctype.h"
+#include "vi.h"
+#include "regexp.h"
+
+
+
+static char	*previous;	/* the previous regexp, used when null regexp is given */
+
+
+#ifndef NO_MAGIC
+/* THE REAL REGEXP PACKAGE IS USED UNLESS "NO_MAGIC" IS DEFINED */
+
+/* These are used to classify or recognize meta-characters */
+#define META		'\0'
+#define BASE_META(m)	((m) - 256)
+#define INT_META(c)	((c) + 256)
+#define IS_META(m)	((m) >= 256)
+#define IS_CLASS(m)	((m) >= M_CLASS(0) && (m) <= M_CLASS(9))
+#define IS_START(m)	((m) >= M_START(0) && (m) <= M_START(9))
+#define IS_END(m)	((m) >= M_END(0) && (m) <= M_END(9))
+#define IS_CLOSURE(m)	((m) >= M_SPLAT && (m) <= M_RANGE)
+#define ADD_META(s,m)	(*(s)++ = META, *(s)++ = BASE_META(m))
+#define GET_META(s)	(*(s) == META ? INT_META(*++(s)) : *s)
+
+/* These are the internal codes used for each type of meta-character */
+#define M_BEGLINE	256		/* internal code for ^ */
+#define M_ENDLINE	257		/* internal code for $ */
+#define M_BEGWORD	258		/* internal code for \< */
+#define M_ENDWORD	259		/* internal code for \> */
+#define M_ANY		260		/* internal code for . */
+#define M_SPLAT		261		/* internal code for * */
+#define M_PLUS		262		/* internal code for \+ */
+#define M_QMARK		263		/* internal code for \? */
+#define M_RANGE		264		/* internal code for \{ */
+#define M_CLASS(n)	(265+(n))	/* internal code for [] */
+#define M_START(n)	(275+(n))	/* internal code for \( */
+#define M_END(n)	(285+(n))	/* internal code for \) */
+
+/* These are used during compilation */
+static int	class_cnt;	/* used to assign class IDs */
+static int	start_cnt;	/* used to assign start IDs */
+static int	end_stk[NSUBEXP];/* used to assign end IDs */
+static int	end_sp;
+static char	*retext;	/* points to the text being compiled */
+
+/* error-handling stuff */
+jmp_buf	errorhandler;
+#define FAIL(why)	regerror(why); longjmp(errorhandler, 1)
+
+
+
+
+
+/* This function builds a bitmap for a particular class */
+static char *makeclass(text, bmap)
+	REG char	*text;	/* start of the class */
+	REG char	*bmap;	/* the bitmap */
+{
+	REG int		i;
+	int		complement = 0;
+
+
+	/* zero the bitmap */
+	for (i = 0; bmap && i < 32; i++)
+	{
+		bmap[i] = 0;
+	}
+
+	/* see if we're going to complement this class */
+	if (*text == '^')
+	{
+		text++;
+		complement = 1;
+	}
+
+	/* add in the characters */
+	while (*text && *text != ']')
+	{
+		/* is this a span of characters? */
+		if (text[1] == '-' && text[2])
+		{
+			/* spans can't be backwards */
+			if (text[0] > text[2])
+			{
+				FAIL("Backwards span in []");
+			}
+
+			/* add each character in the span to the bitmap */
+			for (i = text[0]; bmap && i <= text[2]; i++)
+			{
+				bmap[i >> 3] |= (1 << (i & 7));
+			}
+
+			/* move past this span */
+			text += 3;
+		}
+		else
+		{
+			/* add this single character to the span */
+			i = *text++;
+			if (bmap)
+			{
+				bmap[i >> 3] |= (1 << (i & 7));
+			}
+		}
+	}
+
+	/* make sure the closing ] is missing */
+	if (*text++ != ']')
+	{
+		FAIL("] missing");
+	}
+
+	/* if we're supposed to complement this class, then do so */
+	if (complement && bmap)
+	{
+		for (i = 0; i < 32; i++)
+		{
+			bmap[i] = ~bmap[i];
+		}
+	}
+
+	return text;
+}
+
+
+
+
+/* This function gets the next character or meta character from a string.
+ * The pointer is incremented by 1, or by 2 for \-quoted characters.  For [],
+ * a bitmap is generated via makeclass() (if re is given), and the
+ * character-class text is skipped.
+ */
+static int gettoken(sptr, re)
+	char	**sptr;
+	regexp	*re;
+{
+	int	c;
+
+	c = **sptr;
+	++*sptr;
+	if (c == '\\')
+	{
+		c = **sptr;
+		++*sptr;
+		switch (c)
+		{
+		  case '<':
+			return M_BEGWORD;
+
+		  case '>':
+			return M_ENDWORD;
+
+		  case '(':
+			if (start_cnt >= NSUBEXP)
+			{
+				FAIL("Too many \\(s");
+			}
+			end_stk[end_sp++] = start_cnt;
+			return M_START(start_cnt++);
+
+		  case ')':
+			if (end_sp <= 0)
+			{
+				FAIL("Mismatched \\)");
+			}
+			return M_END(end_stk[--end_sp]);
+
+		  case '*':
+			return (*o_magic ? c : M_SPLAT);
+
+		  case '.':
+			return (*o_magic ? c : M_ANY);
+
+		  case '+':
+			return M_PLUS;
+
+		  case '?':
+			return M_QMARK;
+#ifndef CRUNCH
+		  case '{':
+			return M_RANGE;
+#endif
+		  default:
+			return c;
+		}
+	}
+	else if (*o_magic)
+	{
+		switch (c)
+		{
+		  case '^':
+			if (*sptr == retext + 1)
+			{
+				return M_BEGLINE;
+			}
+			return c;
+
+		  case '$':
+			if (!**sptr)
+			{
+				return M_ENDLINE;
+			}
+			return c;
+
+		  case '.':
+			return M_ANY;
+
+		  case '*':
+			return M_SPLAT;
+
+		  case '[':
+			/* make sure we don't have too many classes */
+			if (class_cnt >= 10)
+			{
+				FAIL("Too many []s");
+			}
+
+			/* process the character list for this class */
+			if (re)
+			{
+				/* generate the bitmap for this class */
+				*sptr = makeclass(*sptr, re->program + 1 + 32 * class_cnt);
+			}
+			else
+			{
+				/* skip to end of the class */
+				*sptr = makeclass(*sptr, (char *)0);
+			}
+			return M_CLASS(class_cnt++);
+
+		  default:
+			return c;
+		}
+	}
+	else	/* unquoted nomagic */
+	{
+		switch (c)
+		{
+		  case '^':
+			if (*sptr == retext + 1)
+			{
+				return M_BEGLINE;
+			}
+			return c;
+
+		  case '$':
+			if (!**sptr)
+			{
+				return M_ENDLINE;
+			}
+			return c;
+
+		  default:
+			return c;
+		}
+	}
+	/*NOTREACHED*/
+}
+
+
+
+
+/* This function calculates the number of bytes that will be needed for a
+ * compiled RE.  Its argument is the uncompiled version.  It is not clever
+ * about catching syntax errors; that is done in a later pass.
+ */
+static unsigned calcsize(text)
+	char		*text;
+{
+	unsigned	size;
+	int		token;
+
+	retext = text;
+	class_cnt = 0;
+	start_cnt = 1;
+	end_sp = 0;
+	size = 5;
+	while ((token = gettoken(&text, (regexp *)0)) != 0)
+	{
+		if (IS_CLASS(token))
+		{
+			size += 34;
+		}
+#ifndef CRUNCH
+		else if (token == M_RANGE)
+		{
+			size += 4;
+			while ((token = gettoken(&text, (regexp *)0)) != 0
+			    && token != '}')
+			{
+			}
+			if (!token)
+			{
+				return size;
+			}
+		}
+#endif
+		else if (IS_META(token))
+		{
+			size += 2;
+		}
+		else
+		{
+			size++;
+		}
+	}
+
+	return size;
+}
+
+
+
+/* This function compiles a regexp. */
+regexp *regcomp(exp)
+	char		*exp;
+{
+	int		needfirst;
+	unsigned	size;
+	int		token;
+	int		peek;
+	char		*build;
+	regexp		*re;
+#ifndef CRUNCH
+	int		from;
+	int		to;
+	int		digit;
+#endif
+
+
+	/* prepare for error handling */
+	re = (regexp *)0;
+	if (setjmp(errorhandler))
+	{
+		if (re)
+		{
+			free(re);
+		}
+		return (regexp *)0;
+	}
+
+	/* if an empty regexp string was given, use the previous one */
+	if (*exp == 0)
+	{
+		if (!previous)
+		{
+			FAIL("No previous RE");
+		}
+		exp = previous;
+	}
+	else /* non-empty regexp given, so remember it */
+	{
+		if (previous)
+			free(previous);
+		previous = (char *)malloc((unsigned)(strlen(exp) + 1));
+		if (previous)
+			strcpy(previous, exp);
+	}
+
+	/* allocate memory */
+	class_cnt = 0;
+	start_cnt = 1;
+	end_sp = 0;
+	retext = exp;
+	size = calcsize(exp) + sizeof(regexp) + 10; /* !!! 10 bytes for slop */
+#ifdef lint
+	re = ((regexp *)0) + size;
+#else
+	re = (regexp *)malloc((unsigned)size);
+#endif
+	if (!re)
+	{
+		FAIL("Not enough memory for this RE");
+	}
+
+	/* compile it */
+	build = &re->program[1 + 32 * class_cnt];
+	re->program[0] = class_cnt;
+	for (token = 0; token < NSUBEXP; token++)
+	{
+		re->startp[token] = re->endp[token] = (char *)0;
+	}
+	re->first = 0;
+	re->bol = 0;
+	re->minlen = 0;
+	needfirst = 1;
+	class_cnt = 0;
+	start_cnt = 1;
+	end_sp = 0;
+	retext = exp;
+	for (token = M_START(0), peek = gettoken(&exp, re);
+	     token;
+	     token = peek, peek = gettoken(&exp, re))
+	{
+		/* special processing for the closure operator */
+		if (IS_CLOSURE(peek))
+		{
+			/* detect misuse of closure operator */
+			if (IS_START(token))
+			{
+				FAIL("Closure operator follows nothing");
+			}
+			else if (IS_META(token) && token != M_ANY && !IS_CLASS(token))
+			{
+				FAIL("Closure operators can only follow a normal character or . or []");
+			}
+
+#ifndef CRUNCH
+			/* if \{ \} then read the range */
+			if (peek == M_RANGE)
+			{
+				from = 0;
+				for (digit = gettoken(&exp, re);
+				     !IS_META(digit) && isdigit(digit);
+				     digit = gettoken(&exp, re))
+				{
+					from = from * 10 + digit - '0';
+				}
+				if (digit == '}')
+				{
+					to = from;
+				}
+				else if (digit == ',')
+				{
+					to = 0;
+					for (digit = gettoken(&exp, re);
+					     !IS_META(digit) && isdigit(digit);
+					     digit = gettoken(&exp, re))
+					{
+						to = to * 10 + digit - '0';
+					}
+					if (to == 0)
+					{
+						to = 255;
+					}
+				}
+				if (digit != '}')
+				{
+					FAIL("Bad characters after \\{");
+				}
+				else if (to < from || to == 0 || from >= 255)
+				{
+					FAIL("Invalid range for \\{ \\}");
+				}
+				re->minlen += from;
+			}
+			else
+#endif
+			if (peek != M_SPLAT)
+			{
+				re->minlen++;
+			}
+
+			/* it is okay -- make it prefix instead of postfix */
+			ADD_META(build, peek);
+#ifndef CRUNCH
+			if (peek == M_RANGE)
+			{
+				*build++ = from;
+				*build++ = (to < 255 ? to : 255);
+			}
+#endif
+			
+
+			/* take care of "needfirst" - is this the first char? */
+			if (needfirst && peek == M_PLUS && !IS_META(token))
+			{
+				re->first = token;
+			}
+			needfirst = 0;
+
+			/* we used "peek" -- need to refill it */
+			peek = gettoken(&exp, re);
+			if (IS_CLOSURE(peek))
+			{
+				FAIL("* or \\+ or \\? doubled up");
+			}
+		}
+		else if (!IS_META(token))
+		{
+			/* normal char is NOT argument of closure */
+			if (needfirst)
+			{
+				re->first = token;
+				needfirst = 0;
+			}
+			re->minlen++;
+		}
+		else if (token == M_ANY || IS_CLASS(token))
+		{
+			/* . or [] is NOT argument of closure */
+			needfirst = 0;
+			re->minlen++;
+		}
+
+		/* the "token" character is not closure -- process it normally */
+		if (token == M_BEGLINE)
+		{
+			/* set the BOL flag instead of storing M_BEGLINE */
+			re->bol = 1;
+		}
+		else if (IS_META(token))
+		{
+			ADD_META(build, token);
+		}
+		else
+		{
+			*build++ = token;
+		}
+	}
+
+	/* end it with a \) which MUST MATCH the opening \( */
+	ADD_META(build, M_END(0));
+	if (end_sp > 0)
+	{
+		FAIL("Not enough \\)s");
+	}
+
+	return re;
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+
+
+/* This function checks for a match between a character and a token which is
+ * known to represent a single character.  It returns 0 if they match, or
+ * 1 if they don't.
+ */
+int match1(re, ch, token)
+	regexp		*re;
+	REG char	ch;
+	REG int		token;
+{
+	if (!ch)
+	{
+		/* the end of a line can't match any RE of width 1 */
+		return 1;
+	}
+	if (token == M_ANY)
+	{
+		return 0;
+	}
+	else if (IS_CLASS(token))
+	{
+		if (re->program[1 + 32 * (token - M_CLASS(0)) + (ch >> 3)] & (1 << (ch & 7)))
+			return 0;
+	}
+	else if (ch == token || *o_ignorecase && tolower(ch) == tolower(token))
+	{
+		return 0;
+	}
+	return 1;
+}
+
+
+
+/* This function checks characters up to and including the next closure, at
+ * which point it does a recursive call to check the rest of it.  This function
+ * returns 0 if everything matches, or 1 if something doesn't match.
+ */
+int match(re, str, prog, here)
+	regexp		*re;	/* the regular expression */
+	char		*str;	/* the string */
+	REG char	*prog;	/* a portion of re->program, an compiled RE */
+	REG char	*here;	/* a portion of str, the string to compare it to */
+{
+	REG int		token;	/* the roken pointed to by prog */
+	REG int		nmatched;/* counter, used during closure matching */ 
+	REG int		closure;/* the token denoting the type of closure */
+	int		from;	/* minimum number of matches in closure */
+	int		to;	/* maximum number of matches in closure */
+
+	for (token = GET_META(prog); !IS_CLOSURE(token); prog++, token = GET_META(prog))
+	{
+		switch (token)
+		{
+		/*case M_BEGLINE: can't happen; re->bol is used instead */
+		  case M_ENDLINE:
+			if (*here)
+				return 1;
+			break;
+
+		  case M_BEGWORD:
+			if (here != str &&
+			   (here[-1] == '_' || isalnum(here[-1])))
+				return 1;
+			break;
+
+		  case M_ENDWORD:
+			if (here[0] == '_' || isalnum(here[0]))
+				return 1;
+			break;
+
+		  case M_START(0):
+		  case M_START(1):
+		  case M_START(2):
+		  case M_START(3):
+		  case M_START(4):
+		  case M_START(5):
+		  case M_START(6):
+		  case M_START(7):
+		  case M_START(8):
+		  case M_START(9):
+			re->startp[token - M_START(0)] = (char *)here;
+			break;
+
+		  case M_END(0):
+		  case M_END(1):
+		  case M_END(2):
+		  case M_END(3):
+		  case M_END(4):
+		  case M_END(5):
+		  case M_END(6):
+		  case M_END(7):
+		  case M_END(8):
+		  case M_END(9):
+			re->endp[token - M_END(0)] = (char *)here;
+			if (token == M_END(0))
+			{
+				return 0;
+			}
+			break;
+
+		  default: /* literal, M_CLASS(n), or M_ANY */
+			if (match1(re, *here, token) != 0)
+				return 1;
+			here++;
+		}
+	}
+
+	/* C L O S U R E */
+
+	/* step 1: see what we have to match against, and move "prog" to point
+	 * to the remainder of the compiled RE.
+	 */
+	closure = token;
+	prog++;
+	switch (closure)
+	{
+	  case M_SPLAT:
+		from = 0;
+		to = strlen(str);	/* infinity */
+		break;
+
+	  case M_PLUS:
+		from = 1;
+		to = strlen(str);	/* infinity */
+		break;
+
+	  case M_QMARK:
+		from = 0;
+		to = 1;
+		break;
+
+#ifndef CRUNCH
+	  case M_RANGE:
+		from = UCHAR(*prog++);
+		to = UCHAR(*prog++);
+		if (to == 255)
+		{
+			to = strlen(str); /* infinity */
+		}
+		break;
+#endif
+	}
+	token = GET_META(prog);
+	prog++;
+
+	/* step 2: see how many times we can match that token against the string */
+	for (nmatched = 0;
+	     nmatched < to && *here && match1(re, *here, token) == 0;
+	     nmatched++, here++)
+	{
+	}
+
+	/* step 3: try to match the remainder, and back off if it doesn't */
+	while (nmatched >= from && match(re, str, prog, here) != 0)
+	{
+		nmatched--;
+		here--;
+	}
+
+	/* so how did it work out? */
+	if (nmatched >= from)
+		return 0;
+	return 1;
+}
+
+
+
+/* This function searches through a string for text that matches an RE. */
+int regexec(re, str, bol)
+	regexp	*re;	/* the compiled regexp to search for */
+	char	*str;	/* the string to search through */
+	int	bol;	/* boolean: does str start at the beginning of a line? */
+{
+	char	*prog;	/* the entry point of re->program */
+	int	len;	/* length of the string */
+	REG char	*here;
+
+	/* if must start at the beginning of a line, and this isn't, then fail */
+	if (re->bol && !bol)
+	{
+		return 0;
+	}
+
+	len = strlen(str);
+	prog = re->program + 1 + 32 * re->program[0];
+
+	/* search for the RE in the string */
+	if (re->bol)
+	{
+		/* must occur at BOL */
+		if ((re->first
+			&& match1(re, *(char *)str, re->first))/* wrong first letter? */
+		 || len < re->minlen			/* not long enough? */
+		 || match(re, (char *)str, prog, str))	/* doesn't match? */
+			return 0;			/* THEN FAIL! */
+	}
+#ifndef CRUNCH
+	else if (!*o_ignorecase)
+	{
+		/* can occur anywhere in the line, noignorecase */
+		for (here = (char *)str;
+		     (re->first && re->first != *here)
+			|| match(re, (char *)str, prog, here);
+		     here++, len--)
+		{
+			if (len < re->minlen)
+				return 0;
+		}
+	}
+#endif
+	else
+	{
+		/* can occur anywhere in the line, ignorecase */
+		for (here = (char *)str;
+		     (re->first && match1(re, *here, (int)re->first))
+			|| match(re, (char *)str, prog, here);
+		     here++, len--)
+		{
+			if (len < re->minlen)
+				return 0;
+		}
+	}
+
+	/* if we didn't fail, then we must have succeeded */
+	return 1;
+}
+
+/*============================================================================*/
+#else /* NO_MAGIC */
+
+regexp *regcomp(exp)
+	char	*exp;
+{
+	char	*src;
+	char	*dest;
+	regexp	*re;
+	int	i;
+
+	/* allocate a big enough regexp structure */
+#ifdef lint
+	re = (regexp *)0;
+#else
+	re = (regexp *)malloc((unsigned)(strlen(exp) + 1 + sizeof(struct regexp)));
+#endif
+	if (!re)
+	{
+		regerror("Could not malloc a regexp structure");
+		return (regexp *)0;
+	}
+
+	/* initialize all fields of the structure */
+	for (i = 0; i < NSUBEXP; i++)
+	{
+		re->startp[i] = re->endp[i] = (char *)0;
+	}
+	re->minlen = 0;
+	re->first = 0;
+	re->bol = 0;
+
+	/* copy the string into it, translating ^ and $ as needed */
+	for (src = exp, dest = re->program + 1; *src; src++)
+	{
+		switch (*src)
+		{
+		  case '^':
+			if (src == exp)
+			{
+				re->bol += 1;
+			}
+			else
+			{
+				*dest++ = '^';
+				re->minlen++;
+			}
+			break;
+
+		  case '$':
+			if (!src[1])
+			{
+				re->bol += 2;
+			}
+			else
+			{
+				*dest++ = '$';
+				re->minlen++;
+			}
+			break;
+
+		  case '\\':
+			if (src[1])
+			{
+				*dest++ = *++src;
+				re->minlen++;
+			}
+			else
+			{
+				regerror("extra \\ at end of regular expression");
+			}
+			break;
+
+		  default:
+			*dest++ = *src;
+			re->minlen++;
+		}
+	}
+	*dest = '\0';
+
+	return re;
+}
+
+
+/* This "helper" function checks for a match at a given location.  It returns
+ * 1 if it matches, 0 if it doesn't match here but might match later on in the
+ * string, or -1 if it could not possibly match
+ */
+static int reghelp(prog, string, bolflag)
+	struct regexp	*prog;
+	char		*string;
+	int		bolflag;
+{
+	char		*scan;
+	char		*str;
+
+	/* if ^, then require bolflag */
+	if ((prog->bol & 1) && !bolflag)
+	{
+		return -1;
+	}
+
+	/* if it matches, then it will start here */
+	prog->startp[0] = string;
+
+	/* compare, possibly ignoring case */
+	if (*o_ignorecase)
+	{
+		for (scan = &prog->program[1]; *scan; scan++, string++)
+			if (tolower(*scan) != tolower(*string))
+				return *string ? 0 : -1;
+	}
+	else
+	{
+		for (scan = &prog->program[1]; *scan; scan++, string++)
+			if (*scan != *string)
+				return *string ? 0 : -1;
+	}
+
+	/* if $, then require string to end here, too */
+	if ((prog->bol & 2) && *string)
+	{
+		return 0;
+	}
+
+	/* if we get to here, it matches */
+	prog->endp[0] = string;
+	return 1;
+}
+
+
+
+int regexec(prog, string, bolflag)
+	struct regexp	*prog;
+	char		*string;
+	int		bolflag;
+{
+	int		rc;
+
+	/* keep trying to match it */
+	for (rc = reghelp(prog, string, bolflag); rc == 0; rc = reghelp(prog, string, 0))
+	{
+		string++;
+	}
+
+	/* did we match? */
+	return rc == 1;
+}
+#endif
Index: /trunk/minix/commands/elvis/regexp.h
===================================================================
--- /trunk/minix/commands/elvis/regexp.h	(revision 9)
+++ /trunk/minix/commands/elvis/regexp.h	(revision 9)
@@ -0,0 +1,21 @@
+/*
+ * Definitions etc. for regexp(3) routines.
+ *
+ * Caveat:  this is V8 regexp(3) [actually, a reimplementation thereof],
+ * not the System V one.
+ */
+#define NSUBEXP  10
+
+typedef struct regexp {
+	char	*startp[NSUBEXP];
+	char	*endp[NSUBEXP];
+	int	minlen;		/* length of shortest possible match */
+	char	first;		/* first character, if known; else \0 */
+	char	bol;		/* boolean: must start at beginning of line? */
+	char	program[1];	/* Unwarranted chumminess with compiler. */
+} regexp;
+
+extern regexp *regcomp();
+extern int regexec();
+extern void regsub();
+extern void regerror();
Index: /trunk/minix/commands/elvis/regsub.c
===================================================================
--- /trunk/minix/commands/elvis/regsub.c	(revision 9)
+++ /trunk/minix/commands/elvis/regsub.c	(revision 9)
@@ -0,0 +1,243 @@
+/* regsub.c */
+
+/* This file contains the regsub() function, which performs substitutions
+ * after a regexp match has been found.
+ */
+
+#include "config.h"
+#include "ctype.h"
+#include "vi.h"
+#include "regexp.h"
+
+
+/* perform substitutions after a regexp match */
+void regsub(re, src, dst)
+	regexp		*re;	/* the regexp with pointers into matched text */
+	REG char	*src;	/* the replacement string */
+	REG char	*dst;	/* where to put the result of the subst */
+{
+	REG char	*cpy;	/* pointer to start of text to copy */
+	REG char	*end;	/* pointer to end of text to copy */
+	REG char	c;
+	char		*start;
+#ifndef CRUNCH
+	int		mod = 0;/* used to track \U, \L, \u, \l, and \E */
+	int		len;	/* used to calculate length of subst string */
+	static char	*prev;	/* a copy of the text from the previous subst */
+
+	/* replace \~ (or maybe ~) by previous substitution text */
+
+	/* step 1: calculate the length of the new substitution text */
+	for (len = strlen(src), c = '\0', cpy = src; *cpy; cpy++)
+	{
+# ifdef NO_MAGIC
+		if (c == '\\' && *cpy == '~')
+# else
+		if (c == (*o_magic ? '\0' : '\\') && *cpy == '~')
+# endif
+		{
+			if (!prev)
+			{
+				regerror("No prev text to substitute for ~");
+				return;
+			}
+			len += strlen(prev) - 1;
+# ifndef NO_MAGIC
+			if (!*o_magic)
+# endif
+				len -= 1; /* because we lose the \ too */
+		}
+
+		/* watch backslash quoting */
+		if (c != '\\' && *cpy == '\\')
+			c = '\\';
+		else
+			c = '\0';
+	}
+
+	/* allocate memory for the ~ed version of src */
+	start = cpy = (char *)malloc((unsigned)(len + 1));
+	if (!cpy)
+	{
+		regerror("Not enough memory for ~ expansion");
+		return;
+	}
+
+	/* copy src into start, replacing the ~s by the previous text */
+	while (*src)
+	{
+# ifndef NO_MAGIC
+		if (*o_magic && *src == '~')
+		{
+			strcpy(cpy, prev);
+			cpy += strlen(prev);
+			src++;
+		}
+		else if (!*o_magic && *src == '\\' && *(src + 1) == '~')
+# else /* NO_MAGIC */
+		if (*src == '\\' && *(src + 1) == '~')
+# endif /* NO_MAGIC */
+		{
+			strcpy(cpy, prev);
+			cpy += strlen(prev);
+			src += 2;
+		}
+		else
+		{
+			*cpy++ = *src++;
+		}
+	}
+	*cpy = '\0';
+#ifdef DEBUG
+	if ((int)(cpy - start) != len)
+	{
+		msg("Bug in regsub.c! Predicted length = %d, Actual length = %d", len, (int)(cpy - start));
+	}
+#endif
+
+	/* remember this as the "previous" for next time */
+	if (prev)
+		free(prev);
+	prev = src = start;
+
+#endif /* undef CRUNCH */
+
+	start = src;
+	while ((c = *src++) != '\0')
+	{
+#ifndef NO_MAGIC
+		/* recognize any meta characters */
+		if (c == '&' && *o_magic)
+		{
+			cpy = re->startp[0];
+			end = re->endp[0];
+		}
+		else
+#endif /* not NO_MAGIC */
+		if (c == '\\')
+		{
+			c = *src++;
+			switch (c)
+			{
+#ifndef NO_MAGIC
+			  case '0':
+			  case '1':
+			  case '2':
+			  case '3':
+			  case '4':
+			  case '5':
+			  case '6':
+			  case '7':
+			  case '8':
+			  case '9':
+				/* \0 thru \9 mean "copy subexpression" */
+				c -= '0';
+				cpy = re->startp[c];
+				end = re->endp[c];
+				break;
+# ifndef CRUNCH
+			  case 'U':
+			  case 'u':
+			  case 'L':
+			  case 'l':
+				/* \U and \L mean "convert to upper/lowercase" */
+				mod = c;
+				continue;
+
+			  case 'E':
+			  case 'e':
+				/* \E ends the \U or \L */
+				mod = 0;
+				continue;
+# endif /* not CRUNCH */
+			  case '&':
+				/* "\&" means "original text" */
+				if (*o_magic)
+				{
+					*dst++ = c;
+					continue;
+				}
+				cpy = re->startp[0];
+				end = re->endp[0];
+				break;
+
+#else /* NO_MAGIC */
+			  case '&':
+				/* "\&" means "original text" */
+				cpy = re->startp[0];
+				end = re->endp[0];
+				break;
+#endif /* NO_MAGIC */
+			  default:
+				/* ordinary char preceded by backslash */
+				*dst++ = c;
+				continue;
+			}
+		}
+#ifndef CRUNCH
+# if OSK
+		else if (c == '\l')
+# else
+		else if (c == '\r')
+# endif
+		{
+			/* transliterate ^M into newline */
+			*dst++ = '\n';
+			continue;
+		}
+#endif /* !CRUNCH */
+		else
+		{
+			/* ordinary character, so just copy it */
+			*dst++ = c;
+			continue;
+		}
+
+		/* Note: to reach this point in the code, we must have evaded
+		 * all "continue" statements.  To do that, we must have hit
+		 * a metacharacter that involves copying.
+		 */
+
+		/* if there is nothing to copy, loop */
+		if (!cpy)
+			continue;
+
+		/* copy over a portion of the original */
+		while (cpy < end)
+		{
+#ifndef NO_MAGIC
+# ifndef CRUNCH
+			switch (mod)
+			{
+			  case 'U':
+			  case 'u':
+				/* convert to uppercase */
+				*dst++ = toupper(*cpy++);
+				break;
+
+			  case 'L':
+			  case 'l':
+				/* convert to lowercase */
+				*dst++ = tolower(*cpy++);
+				break;
+
+			  default:
+				/* copy without any conversion */
+				*dst++ = *cpy++;
+			}
+
+			/* \u and \l end automatically after the first char */
+			if (mod && (mod == 'u' || mod == 'l'))
+			{
+				mod = 0;
+			}
+# else /* CRUNCH */
+			*dst++ = *cpy++;
+# endif /* CRUNCH */
+#else /* NO_MAGIC */
+			*dst++ = *cpy++;
+#endif /* NO_MAGIC */
+		}
+	}
+	*dst = '\0';
+}
Index: /trunk/minix/commands/elvis/system.c
===================================================================
--- /trunk/minix/commands/elvis/system.c	(revision 9)
+++ /trunk/minix/commands/elvis/system.c	(revision 9)
@@ -0,0 +1,423 @@
+/* system.c  -- UNIX version */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains a new version of the system() function and related stuff.
+ *
+ * Entry points are:
+ *	system(cmd)		- run a single shell command
+ *	wildcard(names)		- expand wildcard characters in filanames
+ *	filter(m,n,cmd,back)	- run text lines through a filter program
+ *
+ * This is probably the single least portable file in the program.  The code
+ * shown here should work correctly if it links at all; it will work on UNIX
+ * and any O.S./Compiler combination which adheres to UNIX forking conventions.
+ */
+
+#include "config.h"
+#include "vi.h"
+extern char	**environ;
+
+#if ANY_UNIX
+
+/* This is a new version of the system() function.  The only difference
+ * between this one and the library one is: this one uses the o_shell option.
+ */
+int system(cmd)
+	char	*cmd;	/* a command to run */
+{
+	int	pid;	/* process ID of child */
+	int	died;
+	int	status;	/* exit status of the command */
+
+
+	signal(SIGINT, SIG_IGN);
+	pid = fork();
+	switch (pid)
+	{
+	  case -1:						/* error */
+		msg("fork() failed");
+		status = -1;
+		break;
+
+	  case 0:						/* child */
+		/* for the child, close all files except stdin/out/err */
+		for (status = 3; status < 60 && (close(status), errno != EINVAL); status++)
+		{
+		}
+
+		signal(SIGINT, SIG_DFL);
+		if (cmd == o_shell)
+		{
+			execle(o_shell, o_shell, (char *)0, environ);
+		}
+		else
+		{
+			execle(o_shell, o_shell, "-c", cmd, (char *)0, environ);
+		}
+		msg("execle(\"%s\", ...) failed", o_shell);
+		exit(1); /* if we get here, the exec failed */
+
+	  default:						/* parent */
+		do
+		{
+			died = wait(&status);
+		} while (died >= 0 && died != pid);
+		if (died < 0)
+		{
+			status = -1;
+		}
+#if __GNUC__ || _ANSI
+		signal(SIGINT, (void (*)()) trapint);
+#else
+		signal(SIGINT, trapint);
+#endif
+	}
+
+	return status;
+}
+
+/* This private function opens a pipe from a filter.  It is similar to the
+ * system() function above, and to popen(cmd, "r").
+ */
+int rpipe(cmd, in)
+	char	*cmd;	/* the filter command to use */
+	int	in;	/* the fd to use for stdin */
+{
+	int	r0w1[2];/* the pipe fd's */
+
+	/* make the pipe */
+	if (pipe(r0w1) < 0)
+	{
+		return -1;	/* pipe failed */
+	}
+
+	/* The parent process (elvis) ignores signals while the filter runs.
+	 * The child (the filter program) will reset this, so that it can
+	 * catch the signal.
+	 */
+	signal(SIGINT, SIG_IGN);
+
+	switch (fork())
+	{
+	  case -1:						/* error */
+		return -1;
+
+	  case 0:						/* child */
+		/* close the "read" end of the pipe */
+		close(r0w1[0]);
+
+		/* redirect stdout to go to the "write" end of the pipe */
+		close(1);
+		dup(r0w1[1]);
+		close(2);
+		dup(r0w1[1]);
+		close(r0w1[1]);
+
+		/* redirect stdin */
+		if (in != 0)
+		{
+			close(0);
+			dup(in);
+			close(in);
+		}
+
+		/* the filter should accept SIGINT signals */
+		signal(SIGINT, SIG_DFL);
+
+		/* exec the shell to run the command */
+		execle(o_shell, o_shell, "-c", cmd, (char *)0, environ);
+		exit(1); /* if we get here, exec failed */
+
+	  default:						/* parent */
+		/* close the "write" end of the pipe */	
+		close(r0w1[1]);
+
+		return r0w1[0];
+	}
+}
+
+#endif /* non-DOS */
+
+#if OSK
+
+/* This private function opens a pipe from a filter.  It is similar to the
+ * system() function above, and to popen(cmd, "r").
+ */
+int rpipe(cmd, in)
+	char	*cmd;	/* the filter command to use */
+	int	in;	/* the fd to use for stdin */
+{
+	return osk_popen(cmd, "r", in, 0);
+}	
+#endif
+
+#if ANY_UNIX || OSK
+
+/* This function closes the pipe opened by rpipe(), and returns 0 for success */
+int rpclose(fd)
+	int	fd;
+{
+	int	status;
+
+	close(fd);
+	wait(&status);
+#if __GNUC__ || _ANSI
+	signal(SIGINT, (void (*)()) trapint);
+#else
+	signal(SIGINT, trapint);
+#endif
+	return status;
+}
+
+#endif /* non-DOS */
+
+/* This function expands wildcards in a filename or filenames.  It does this
+ * by running the "echo" command on the filenames via the shell; it is assumed
+ * that the shell will expand the names for you.  If for any reason it can't
+ * run echo, then it returns the names unmodified.
+ */
+
+#if MSDOS || TOS
+#define	PROG	"wildcard "
+#define	PROGLEN	9
+#include <string.h>
+#else
+#define	PROG	"echo "
+#define	PROGLEN	5
+#endif
+
+#if !AMIGA
+char *wildcard(names)
+	char	*names;
+{
+
+# if VMS
+/* 
+   We could use expand() [vmswild.c], but what's the point on VMS? 
+   Anyway, echo is the wrong thing to do, it takes too long to build
+   a subprocess on VMS and any "echo" program would have to be supplied
+   by elvis.  More importantly, many VMS utilities expand names 
+   themselves (the shell doesn't do any expansion) so the concept is
+   non-native.  jdc
+*/
+	return names;
+# else
+
+	int	i, j, fd;
+	REG char *s, *d;
+
+
+	/* build the echo command */
+	if (names != tmpblk.c)
+	{
+		/* the names aren't in tmpblk.c, so we can do it the easy way */
+		strcpy(tmpblk.c, PROG);
+		strcat(tmpblk.c, names);
+	}
+	else
+	{
+		/* the names are already in tmpblk.c, so shift them to make
+		 * room for the word "echo "
+		 */
+		for (s = names + strlen(names) + 1, d = s + PROGLEN; s > names; )
+		{
+			*--d = *--s;
+		}
+		strncpy(names, PROG, PROGLEN);
+	}
+
+	/* run the command & read the resulting names */
+	fd = rpipe(tmpblk.c, 0);
+	if (fd < 0) return names;
+	i = 0;
+	do
+	{
+		j = tread(fd, tmpblk.c + i, BLKSIZE - i);
+		i += j;
+	} while (j > 0);
+
+	/* successful? */
+	if (rpclose(fd) == 0 && j == 0 && i < BLKSIZE && i > 0)
+	{
+		tmpblk.c[i-1] = '\0'; /* "i-1" so we clip off the newline */
+		return tmpblk.c;
+	}
+	else
+	{
+		return names;
+	}
+# endif
+}
+#endif
+
+/* This function runs a range of lines through a filter program, and replaces
+ * the original text with the filtered version.  As a special case, if "to"
+ * is MARK_UNSET, then it runs the filter program with stdin coming from
+ * /dev/null, and inserts any output lines.
+ */
+int filter(from, to, cmd, back)
+	MARK	from, to;	/* the range of lines to filter */
+	char	*cmd;		/* the filter command */
+	int	back;		/* boolean: will we read lines back? */
+{
+	int	scratch;	/* fd of the scratch file */
+	int	fd;		/* fd of the pipe from the filter */
+	char	scrout[50];	/* name of the scratch out file */
+	MARK	new;		/* place where new text should go */
+	long	sent, rcvd;	/* number of lines sent/received */
+	int	i, j;
+
+	/* write the lines (if specified) to a temp file */
+	if (to)
+	{
+		/* we have lines */
+#if MSDOS || TOS
+		strcpy(scrout, o_directory);
+		if ((i=strlen(scrout)) && !strchr("\\/:", scrout[i-1]))
+			scrout[i++]=SLASH;
+		strcpy(scrout+i, SCRATCHOUT+3);
+#else
+		sprintf(scrout, SCRATCHOUT, o_directory);
+#endif
+		mktemp(scrout);
+		cmd_write(from, to, CMD_BANG, FALSE, scrout);
+		sent = markline(to) - markline(from) + 1L;
+
+		/* use those lines as stdin */
+		scratch = open(scrout, O_RDONLY);
+		if (scratch < 0)
+		{
+			unlink(scrout);
+			return -1;
+		}
+	}
+	else
+	{
+		scratch = 0;
+		sent = 0L;
+	}
+
+	/* start the filter program */
+#if VMS
+	/* 
+	   VMS doesn't know a thing about file descriptor 0.  The rpipe
+	   concept is non-portable.  Hence we need a file name argument.
+	*/
+	fd = rpipe(cmd, scratch, scrout);
+#else
+	fd = rpipe(cmd, scratch);
+#endif
+	if (fd < 0)
+	{
+		if (to)
+		{
+			close(scratch);
+			unlink(scrout);
+		}
+		return -1;
+	}
+
+	if (back)
+	{
+		ChangeText
+		{
+			/* adjust MARKs for whole lines, and set "new" */
+			from &= ~(BLKSIZE - 1);
+			if (to)
+			{
+				to &= ~(BLKSIZE - 1);
+				to += BLKSIZE;
+				new = to;
+			}
+			else
+			{
+				new = from + BLKSIZE;
+			}
+
+#if VMS
+/* Reading from a VMS mailbox (pipe) is record oriented... */
+# define tread vms_pread
+#endif
+
+			/* repeatedly read in new text and add it */
+			rcvd = 0L;
+			while ((i = tread(fd, tmpblk.c, BLKSIZE - 1)) > 0)
+			{
+				tmpblk.c[i] = '\0';
+				add(new, tmpblk.c);
+#if VMS
+				/* What!  An advantage to record oriented reads? */
+				new += (i - 1);
+				new = (new & ~(BLKSIZE - 1)) + BLKSIZE;
+				rcvd++;
+#else
+				for (i = 0; tmpblk.c[i]; i++)
+				{
+					if (tmpblk.c[i] == '\n')
+					{
+						new = (new & ~(BLKSIZE - 1)) + BLKSIZE;
+						rcvd++;
+					}
+					else
+					{
+						new++;
+					}
+				}
+#endif
+			}
+		}
+
+		/* delete old text, if any */
+		if (to)
+		{
+			cut(from, to);
+			delete(from, to);
+		}
+	}
+	else
+	{
+		/* read the command's output, and copy it to the screen */
+		while ((i = tread(fd, tmpblk.c, BLKSIZE - 1)) > 0)
+		{
+			for (j = 0; j < i; j++)
+			{
+				addch(tmpblk.c[j]);
+			}
+		}
+		rcvd = 0;
+	}
+
+	/* Reporting... */
+	if (sent >= *o_report || rcvd >= *o_report)
+	{
+		if (sent > 0L && rcvd > 0L)
+		{
+			msg("%ld lines out, %ld lines back", sent, rcvd);
+		}
+		else if (sent > 0)
+		{
+			msg("%ld lines written to filter", sent);
+		}
+		else
+		{
+			msg("%ld lines read from filter", rcvd);
+		}
+	}
+	rptlines = 0L;
+
+	/* cleanup */
+	rpclose(fd);
+	if (to)
+	{
+		close(scratch);
+		unlink(scrout);
+	}
+	return 0;
+}
Index: /trunk/minix/commands/elvis/tinyprnt.c
===================================================================
--- /trunk/minix/commands/elvis/tinyprnt.c	(revision 9)
+++ /trunk/minix/commands/elvis/tinyprnt.c	(revision 9)
@@ -0,0 +1,230 @@
+/* tinyprnt.c */
+
+#if OSK
+#define sprintf Sprintf
+#endif
+
+/* This is a limited version of sprintf().  It is useful for Minix-PC and
+ * Coherent-286 because those systems are both limited to 64k+64k and the
+ * standard sprintf() is just too damn big.
+ *
+ * It should also be useful for OS-9 because OS-9's sprintf() doesn't
+ * understand the true meaning of asterisks in a format string.  This one
+ * does.
+ */
+
+/* Place-holders in format strings look like "%<pad><clip><type>".
+ *
+ * The <pad> adds space to the front (or, if negative, to the back) of the
+ * output value, to pad it to a given width.  If <pad> is absent, then 0 is
+ * assumed.  If <pad> is an asterisk, then the next argument is assumed to
+ * be an (int) which used as the pad width.
+ *
+ * The <clip> string can be absent, in which case no clipping is done.
+ * However, if it is present, then it should be either a "." followed by
+ * a number, or a "." followed by an asterisk.  The asterisk means that the
+ * next argument is an (int) which should be used as the pad width.  Clipping
+ * only affects strings; for other data types it is ignored.
+ *
+ * The <type> is one of "s" for strings, "c" for characters (really ints that
+ * are assumed to be legal char values), "d" for ints, "ld" for long ints, or
+ * "%" to output a percent sign.
+ */
+
+/* NOTE: Variable argument lists are handled by direct stack-twiddling. Sorry! */
+
+static void cvtnum(buf, num, base)
+	char		*buf;	/* where to store the number */
+	unsigned long	num;	/* the number to convert */
+	int		base;	/* either 8, 10, or 16 */
+{
+	static char	digits[] = "0123456789abcdef";
+	unsigned long	tmp;
+
+	/* if the number is 0, then just stuff a "0" into the buffer */
+	if (num == 0L)
+	{
+		buf[0] = '0';
+		buf[1] = '\0';
+		return;
+	}
+
+	/* use tmp to figure out how many digits we'll need */
+	for (tmp = num; tmp > 0; tmp /= base)
+	{
+		buf++;
+	}
+
+	/* mark the spot that will be the end of the string */
+	*buf = '\0';
+
+	/* generate all digits, as needed */
+	for (tmp = num; tmp > 0; tmp /= base)
+	{
+		*--buf = digits[tmp % base];
+	}
+}
+
+int sprintf(buf, fmt, argref)
+	char	*buf;	/* where to deposit the formatted output */
+	char	*fmt;	/* the format string */
+	int	argref;	/* the first argument is located at &argref */
+{
+	char	*argptr;/* pointer to next argument on the stack */
+	int	pad;	/* value of the pad string */
+	int	clip;	/* value of the clip string */
+	long	num;	/* a binary number being converted to ASCII digits */
+	long	digit;	/* used during conversion */
+	char	*src, *dst;
+
+	/* make argptr point to the first argument after the format string */
+	argptr = (char *)&argref;
+
+	/* loop through the whole format string */
+	while (*fmt)
+	{
+		/* if not part of a place-holder, then copy it literally */
+		if (*fmt != '%')
+		{
+			*buf++ = *fmt++;
+			continue;
+		}
+
+		/* found a place-holder!  Get <pad> value */
+		fmt++;
+		if ('*' == *fmt)
+		{
+			pad = *((int *)argptr)++;
+			fmt++;
+		}
+		else if (*fmt == '-' || (*fmt >= '0' && *fmt <= '9'))
+		{
+			pad = atol(fmt);
+			do
+			{
+				fmt++;
+			} while (*fmt >= '0' && *fmt <= '9');
+		}
+		else
+		{
+			pad = 0;
+		}
+
+		/* get a <clip> value */
+		if (*fmt == '.')
+		{
+			fmt++;
+			if ('*' == *fmt)
+			{
+				clip = *((int *)argptr)++;
+				fmt++;
+			}
+			else if (*fmt >= '0' && *fmt <= '9')
+			{
+				clip = atol(fmt);
+				do
+				{
+					fmt++;
+				} while (*fmt >= '0' && *fmt <= '9');
+			}
+		}
+		else
+		{
+			clip = 0;
+		}
+
+		/* handle <type>, possibly noticing <clip> */
+		switch (*fmt++)
+		{
+		  case 'c':
+			buf[0] = *((int *)argptr)++;
+			buf[1] = '\0';
+			break;
+
+		  case 's':
+			src = *((char **)argptr)++;
+			if (!src)
+			{
+				src = "(null)";
+			}
+			if (clip)
+			{
+				strncpy(buf, src, clip);
+				buf[clip] = '\0';
+			}
+			else
+			{
+				strcpy(buf, src);
+			}
+			break;
+
+		  case 'l':
+			fmt++; /* to skip the "d" in "%ld" */
+			num = *((long *)argptr)++;
+			dst = buf;
+			if (num < 0)
+			{
+				*dst++ = '-';
+				num = -num;
+			}
+			cvtnum(dst, num, 10);
+			break;
+
+		  case 'x':
+			num = *((int *)argptr)++;
+			cvtnum(buf, num, 16);
+			break;
+
+		  case 'd':
+			num = *((int *)argptr)++;
+			dst = buf;
+			if (num < 0)
+			{
+				*dst++ = '-';
+				num = -num;
+			}
+			cvtnum(dst, num, 10);
+			break;
+
+		  default:
+			buf[0] = fmt[-1];
+			buf[1] = '\0';
+		}
+
+		/* now fix the padding, if the value is too short */
+		clip = strlen(buf);
+		if (pad < 0)
+		{
+			/* add spaces after the value */
+			pad = -pad - clip;
+			for (buf += clip; pad > 0; pad--)
+			{
+				*buf++ = ' ';
+			}
+			*buf = '\0';
+		}
+		else
+		{
+			/* add spaces before the value */
+			pad -= clip;
+			if (pad > 0)
+			{
+				src = buf + clip;
+				dst = src + pad;
+				*dst = '\0';
+				while (src > buf)
+				{
+					*--dst = *--src;
+				}
+				while (dst > buf)
+				{
+					*--dst = ' ';
+				}
+			}
+			buf += strlen(buf);
+		}
+	}
+
+	/* mark the end of the output string */
+	*buf = '\0';
+}
Index: /trunk/minix/commands/elvis/tinytcap.c
===================================================================
--- /trunk/minix/commands/elvis/tinytcap.c	(revision 9)
+++ /trunk/minix/commands/elvis/tinytcap.c	(revision 9)
@@ -0,0 +1,388 @@
+/* tinytcap.c */
+
+/* This file contains functions which simulate the termcap functions.
+ *
+ * It doesn't access a "termcap" file.  Instead, it uses an initialized array
+ * of strings to store the entries.  Any string that doesn't start with a ':'
+ * is taken to be the name of a type of terminal.  Any string that does start
+ * with a ':' is interpretted as the list of fields describing all of the
+ * terminal types that precede it.
+ *
+ * Note: since these are C strings, you can't use special sequences like
+ * ^M or \E in the fields; your C compiler won't understand them.  Also,
+ * at run time there is no way to tell the difference between ':' and '\072'
+ * so I sure hope your terminal definition doesn't require a ':' character.
+ *
+ * getenv(TERM) on VMS checks the SET TERM device setting.  To implement
+ * non-standard terminals set the logical ELVIS_TERM in VMS. (jdc)
+ *
+ * Other possible terminal types are...
+ * 	TERM_WYSE925	- "wyse925", a Wyse 50 terminal emulating Televideo 925
+ * ... or you could set $TERMCAP to the terminal's description string, which
+ * $TERM set up to match it.
+ *
+ * Note that you can include several terminal types at the same time.  Elvis
+ * chooses which entry to use at runtime, based primarily on the value of $TERM.
+ */
+
+
+#include "config.h"
+extern char *getenv();
+
+/* decide which terminal descriptions should *always* be included. */
+#if MSDOS
+# define	TERM_NANSI
+# define	TERM_DOSANSI
+# if RAINBOW
+#  define	TERM_RAINBOW
+# endif
+#endif
+
+#if VMS
+# define	TERM_VT100
+# define	TERM_VT100W
+# define	TERM_VT52
+#endif
+
+#if AMIGA
+# define	TERM_AMIGA	/* Internal Amiga termcap entry */
+/* # define	TERM_VT52	/* The rest of these are here for those */
+# define	TERM_VT100	/* people who want to use elvis over an */
+/* # define	TERM_NANSI	/* AUX: port (serial.device). */
+/* # define	TERM_DOSANSI	/* Take out all but AMIGA to save memory. */
+/* # define	TERM_MINIX	/* Vanilla ANSI? */
+/* # define	TERM_925	/* Hang a terminal off your Amiga */
+#endif
+
+#if MINIX || UNIXV
+# define	TERM_MINIX
+#endif
+
+#if COHERENT
+# define	TERM_COHERENT
+#endif
+
+#if TOS
+# define	TERM_ATARI
+#endif
+
+static char *termcap[] =
+{
+#ifdef TERM_AMIGA
+"AA",
+"amiga",
+"Amiga ANSI",
+/* Amiga termcap modified from version 1.3 by Kent Polk */
+":co#80:li#24:am:bs:bw:xn:\
+:AL=\233%dL:DC=\233%dP:DL=\233%dM:DO=\233%dB:\
+:LE=\233%dD:RI=\233%dC:SF=\233%dS:SR=\233%dT:UP=\233%dA:IC=\233%d@:\
+:ae=\2330m:al=\233L:as=\2333m:bl=\007:bt=\233Z:cd=\233J:\
+:ce=\233K:cl=\013:cm=\233%i%d;%dH:dc=\233P:dl=\233M:do=\233B:\
+:kb=^H:ho=\233H:ic=\233@:is=\23320l:\
+:mb=\2337;2m:md=\2331m:me=\2330m:mh=\2332m:mk=\2338m:mr=\2337m:nd=\233C:\
+:rs=\033c:se=\2330m:sf=\233S:so=\2337m:sb=\233T:sr=\233T:ue=\23323m:\
+:up=\233A:us=\2334m:vb=\007:ve=\233\040p:vi=\2330\040p:\
+:k1=\2330~:k2=\2331~:k3=\2332~:k4=\2333~:k5=\2334~:\
+:k6=\2335~:k7=\2336~:k8=\2337~:k9=\2338~:k0=\2339~:\
+:s1=\23310~:s2=\23311~:s3=\23312~:s4=\23313~:s5=\23314~:\
+:s6=\23315~:s7=\23316~:s8=\23317~:s9=\23318~:s0=\23319~:\
+:kd=\233B:kl=\233D:kn#10:kr=\233C:ku=\233A:le=\233D:\
+:kP=\233T:kN=\233S:kh=\233\040A:kH=\233\040@:",
+#endif
+
+#ifdef TERM_NANSI
+"fansi",
+"nnansi",
+"nansi",
+"pcbios",
+":al=\033[L:dl=\033[M:am:bs:ce=\033[K:cl=\033[2J:\
+:cm=\033[%i%d;%dH:co#80:do=\033[B:\
+:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:\
+:s1=#T:s2=#U:s3=#V:s4=#W:s5=#X:s6=#Y:s7=#Z:s8=#[:s9=#\\:s0=#]:\
+:c1=#^:c2=#_:c3=#`:c4=#a:c5=#b:c6=#c:c7=#d:c8=#e:c9=#f:c0=#g:\
+:a1=#h:a2=#i:a3=#j:a4=#k:a5=#l:a6=#m:a7=#n:a8=#o:a9=#p:a0=#q:\
+:kd=#P:kh=#G:kH=#O:kI=#R:kl=#K:kN=#Q:kP=#I:kr=#M:ku=#H:\
+:li#25:md=\033[1m:me=\033[m:nd=\033[C:se=\033[m:so=\033[7m:\
+:ue=\033[m:up=\033[A:us=\033[4m:",
+#endif
+
+#ifdef TERM_DOSANSI
+#if !ANY_UNIX
+"ansi",
+#endif
+"dosansi",
+":am:bs:ce=\033[K:cl=\033[2J:\
+:cm=\033[%i%d;%dH:co#80:do=\033[B:\
+:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:\
+:s1=#T:s2=#U:s3=#V:s4=#W:s5=#X:s6=#Y:s7=#Z:s8=#[:s9=#\\:s0=#]:\
+:c1=#^:c2=#_:c3=#`:c4=#a:c5=#b:c6=#c:c7=#d:c8=#e:c9=#f:c0=#g:\
+:a1=#h:a2=#i:a3=#j:a4=#k:a5=#l:a6=#m:a7=#n:a8=#o:a9=#p:a0=#q:\
+:kd=#P:kh=#G:kH=#O:kI=#R:kl=#K:kN=#Q:kP=#I:kr=#M:ku=#H:\
+:li#25:md=\033[1m:me=\033[m:nd=\033[C:se=\033[m:so=\033[7m:\
+:ue=\033[m:up=\033[A:us=\033[4m:",
+#endif
+
+#ifdef TERM_RAINBOW
+"vt220",
+"rainbow",
+":al=\033[L:dl=\033[M:am:bs:ce=\033[K:cl=\033[2J:\
+:cm=\033[%i%d;%dH:co#80:do=\033[B:kd=\033[B:kl=\033[D:\
+:kr=\033[C:ku=\033[A:kP=\033[5~:kN=\033[6~:kI=\033[2~:\
+:li#24:md=\033[1m:me=\033[m:nd=\033[C:se=\033[m:so=\033[7m:\
+:ue=\033[m:up=\033[A:us=\033[4m:xn:",
+#endif
+
+#ifdef TERM_VT100
+"vt100-80",
+"vt200-80",
+"vt300-80",
+"vt101-80",
+"vt102-80",
+":al=\033[L:am:bs:ce=\033[K:cl=\033[2J:cm=\033[%i%d;%dH:\
+:co#80:dl=\033[M:do=\033[B:k0=\033[20~:k1=\033[1~:\
+:k2=\033[2~:k3=\033[3~:k4=\033[4~:k5=\033[5~:k6=\033[6~:\
+:k7=\033[17~:k8=\033[18~:k9=\033[19~:kd=\033[B:kh=\033[H:\
+:kH=\033[Y:kI=\033[I:kl=\033[D:kN=\033[U:kP=\033[V:\
+:kr=\033[C:ku=\033[A:li#24:md=\033[1m:me=\033[m:nd=\033[C:\
+:se=\033[m:so=\033[7m:ti=\033[1;24r\033[24;1H:\
+:ue=\033[m:up=\033[A:us=\033[4m:xn:",
+#endif
+
+#ifdef TERM_VT100W
+"vt100-w",
+"vt200-w",
+"vt300-w",
+"vt101-w",
+"vt102-w",
+"vt100-132",
+"vt200-132",
+"vt300-132",
+"vt101-132",
+"vt102-132",
+":al=\033[L:am:bs:ce=\033[K:cl=\033[2J:cm=\033[%i%d;%dH:\
+:co#132:dl=\033[M:do=\033[B:k0=\033[20~:k1=\033[1~:\
+:k2=\033[2~:k3=\033[3~:k4=\033[4~:k5=\033[5~:k6=\033[6~:\
+:k7=\033[17~:k8=\033[18~:k9=\033[19~:kd=\033[B:kh=\033[H:\
+:kH=\033[Y:kI=\033[I:kl=\033[D:kN=\033[U:kP=\033[V:\
+:kr=\033[C:ku=\033[A:li#24:md=\033[1m:me=\033[m:nd=\033[C:\
+:se=\033[m:so=\033[7m:ti=\033[1;24r\033[24;1H:\
+:ue=\033[m:up=\033[A:us=\033[4m:xn:",
+#endif
+
+#ifdef TERM_VT52
+"vt52",
+":do=\n:le=\b:up=\033A:nd=\033C:cm=\033Y%+ %+ :ti=\033e\033v:\
+:sr=\033I:cd=\033J:ce=\033K:cl=\033H\033J:co#80:li#24:\
+:ku=\033A:kd=\033B:kr=\033C:kl=\033D:kb=\b:pt:am:xn:bs:",
+#endif
+
+#ifdef TERM_MINIX
+"minix",
+"ansi",
+"AT386",
+":al=\033[L:am:bs:ce=\033[K:cl=\033[2J:cm=\033[%i%d;%dH:\
+:co#80:dl=\033[M:do=\033[B:k0=\033[20~:k1=\033[1~:\
+:k2=\033[2~:k3=\033[3~:k4=\033[4~:k5=\033[5~:k6=\033[6~:\
+:k7=\033[17~:k8=\033[18~:k9=\033[19~:kd=\033[B:kh=\033[H:\
+:kH=\033[Y:kI=\033[I:kl=\033[D:kN=\033[U:kP=\033[V:\
+:kr=\033[C:ku=\033[A:li#25:md=\033[1m:me=\033[m:nd=\033[C:\
+:se=\033[m:so=\033[7m:ue=\033[m:up=\033[A:us=\033[4m:",
+#endif /* MINIX */
+
+#ifdef TERM_COHERENT
+"coherent",
+"ansipc",
+":al=\033[L:am:bs:ce=\033[K:cl=\033[2J:cm=\033[%i%d;%dH:\
+:co#80:dl=\033[M:do=\033[B:k0=\033[0x:k1=\033[1x:k2=\033[2x:\
+:k3=\033[3x:k4=\033[4x:k5=\033[5x:k6=\033[6x:\
+:k7=\033[7x:k8=\033[8x:k9=\033[9x:kd=\033[B:kh=\033[H:\
+:kH=\033[24H:kI=\033[@:kl=\033[D:kN=\033[U:kP=\033[V:\
+:kr=\033[C:ku=\033[A:li#24:md=\033[1m:me=\033[m:\
+:nd=\033[C:se=\033[m:so=\033[7m:ue=\033[m:up=\033[A:\
+:us=\033[4m:",
+#endif /* COHERENT */
+
+#ifdef TERM_ATARI
+"atari-st",
+"vt52",
+":al=\033L:am:bs:ce=\033K:cl=\033E:cm=\033Y%i%+ %+ :\
+:co#80:dl=\033M:do=\033B:\
+:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:\
+:s1=#T:s2=#U:s3=#V:s4=#W:s5=#X:s6=#Y:s7=#Z:s8=#[:s9=#\\:s0=#]:\
+:c1=#^:c2=#_:c3=#`:c4=#a:c5=#b:c6=#c:c7=#d:c8=#e:c9=#f:c0=#g:\
+:a1=#h:a2=#i:a3=#j:a4=#k:a5=#l:a6=#m:a7=#n:a8=#o:a9=#p:a0=#q:\
+kd=#P:kh=#G:kI=#R:kl=#K:kr=#M:ku=#H:li#25:nd=\033C:se=\033q:\
+:so=\033p:te=:ti=\033e\033v:up=\033A:",
+#endif
+
+#ifdef TERM_925
+"wyse925",
+":xn@:\
+:hs:am:bs:co#80:li#24:cm=\033=%+ %+ :cl=\033*:cd=\033y:\
+:ce=\033t:is=\033l\033\":\
+:al=\033E:dl=\033R:im=:ei=:ic=\033Q:dc=\033W:\
+:ho=\036:nd=\014:bt=\033I:pt:so=\033G4:se=\033G0:sg#1:us=\033G8:ue=\033G0:ug#1:\
+:up=\013:do=\026:kb=\010:ku=\013:kd=\026:kl=\010:kr=\014:\
+:kh=\036:ma=\026\012\014 :\
+:k1=\001@\r:k2=\001A\r:k3=\001B\r:k4=\001C\r:k5=\001D\r:k6=\001E\r:k7=\001F\r:\
+:k8=\001G\r:k9=\001H\r:k0=\001I\r:ko=ic,dc,al,dl,cl,ce,cd,bt:\
+:ts=\033f:fs=\033g:ds=\033h:sr=\033j:",  /* was :xn: for tvi925 alone*/
+#endif
+
+(char *)0
+};
+
+
+static char *fields;
+
+
+/*ARGSUSED*/
+int tgetent(bp, name)
+	char	*bp;	/* buffer for storing the entry -- ignored */
+	char	*name;	/* name of the entry */
+{
+	int	i;
+
+	/* if TERMCAP is defined, and seems to match, then use it */
+	fields = getenv("TERMCAP");
+	if (fields)
+	{
+		for (i = 0; fields[i] && fields[i] != ':'; i++)
+		{
+			if (!strncmp(fields + i, name, strlen(name)))
+			{
+				return 1;
+			}
+		}
+	}
+
+	/* locate the entry in termcap[] */
+	for (i = 0; termcap[i] && strcmp(termcap[i], name); i++)
+	{
+	}
+	if (!termcap[i])
+	{
+		return 0;
+	}
+
+	/* search forward for fields */
+	while (termcap[i][0] != ':')
+	{
+		i++;
+	}
+	fields = termcap[i];
+	return 1;
+}
+
+
+static char *find(id, vtype)
+	char	*id;	/* name of a value to locate */
+	int	vtype;	/* '=' for strings, '#' for numbers, or 0 for bools */
+{
+	int	i;
+
+	/* search for a ':' followed by the two-letter id */
+	for (i = 0; fields[i]; i++)
+	{
+		if (fields[i] == ':'
+		 && fields[i + 1] == id[0]
+		 && fields[i + 2] == id[1])
+		{
+			/* if correct type, then return its value */
+			if (fields[i + 3] == vtype)
+				return &fields[i + 4];
+			else
+				return (char *)0;
+		}
+	}
+	return (char *)0;
+}
+
+int tgetnum(id)
+	char	*id;
+{
+	id = find(id, '#');
+	if (id)
+	{
+		return atoi(id);
+	}
+	return -1;
+}
+
+int tgetflag(id)
+	char	*id;
+{
+	if (find(id, ':'))
+	{
+		return 1;
+	}
+	return 0;
+}
+
+/*ARGSUSED*/
+char *tgetstr(id, bp)
+	char	*id;
+	char	**bp;	/* pointer to pointer to buffer - ignored */
+{
+	char	*cpy;
+
+	/* find the string */
+	id = find(id, '=');
+	if (!id)
+	{
+		return (char *)0;
+	}
+
+	/* copy it into the buffer, and terminate it with NUL */
+	for (cpy = *bp; *id != ':'; )
+	{
+		if (id[0] == '\\' && id[1] == 'E')
+			*cpy++ = '\033', id += 2;
+		else
+			*cpy++ = *id++;
+	}
+	*cpy++ = '\0';
+
+	/* update the bp pointer */
+	id = *bp;
+	*bp = cpy;
+
+	/* return a pointer to the copy of the string */
+	return id;
+}
+
+/*ARGSUSED*/
+char *tgoto(cm, destcol, destrow)
+	char	*cm;	/* cursor movement string -- ignored */
+	int	destcol;/* destination column, 0 - 79 */
+	int	destrow;/* destination row, 0 - 24 */
+{
+	static char buf[30];
+
+#ifdef CRUNCH
+# if TOS
+	sprintf(buf, "\033Y%c%c", ' ' + destrow, ' ' + destcol);
+# else
+	sprintf(buf, "\033[%d;%dH", destrow + 1, destcol + 1);
+# endif
+#else
+	if (cm[1] == 'Y' || cm[1] == '=')
+		sprintf(buf, "\033%c%c%c", cm[1], ' ' + destrow, ' ' + destcol);
+	else
+		sprintf(buf, "\033[%d;%dH", destrow + 1, destcol + 1);
+#endif
+	return buf;
+}
+
+/*ARGSUSED*/
+void tputs(cp, affcnt, outfn)
+	char	*cp;		/* the string to output */
+	int	affcnt;		/* number of affected lines -- ignored */
+	int	(*outfn)();	/* the output function */
+{
+	while (*cp)
+	{
+		(*outfn)(*cp);
+		cp++;
+	}
+}
Index: /trunk/minix/commands/elvis/tio.c
===================================================================
--- /trunk/minix/commands/elvis/tio.c	(revision 9)
+++ /trunk/minix/commands/elvis/tio.c	(revision 9)
@@ -0,0 +1,1026 @@
+/* tio.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains terminal I/O functions */
+
+#include "config.h"
+#include "vi.h"
+#include "ctype.h"
+
+
+/* This function reads in a line from the terminal. */
+int vgets(prompt, buf, bsize)
+	char	prompt;	/* the prompt character, or '\0' for none */
+	char	*buf;	/* buffer into which the string is read */
+	int	bsize;	/* size of the buffer */
+{
+	int	len;	/* how much we've read so far */
+	int	ch;	/* a character from the user */
+	int	quoted;	/* is the next char quoted? */
+	int	tab;	/* column position of cursor */
+	char	widths[132];	/* widths of characters */
+	int	word;	/* index of first letter of word */
+#ifndef NO_DIGRAPH
+	int	erased;	/* 0, or first char of a digraph */
+#endif
+
+	/* show the prompt */
+	move(LINES - 1, 0);
+	tab = 0;
+	if (prompt)
+	{
+		addch(prompt);
+		tab = 1;
+	}
+	clrtoeol();
+	refresh();
+
+	/* read in the line */
+#ifndef NO_DIGRAPH
+	erased =
+#endif
+	quoted = len = 0;
+	for (;;)
+	{
+#ifndef NO_ABBR
+		if (quoted || mode == MODE_EX)
+		{
+			ch = getkey(0);
+		}
+		else
+		{
+			/* maybe expand an abbreviation while getting key */
+			for (word = len; --word >= 0 && isalnum(buf[word]); )
+			{
+			}
+			word++;
+			ch = getabkey(WHEN_EX, &buf[word], len - word);
+		}
+#else
+		ch = getkey(0);
+#endif
+#ifndef NO_EXTENSIONS
+		if (ch == ctrl('O'))
+		{
+			ch = getkey(quoted ? 0 : WHEN_EX);
+		}
+#endif
+
+		/* some special conversions */
+		if (ch == ctrl('D') && len == 0)
+			ch = ctrl('[');
+#ifndef NO_DIGRAPH
+		if (*o_digraph && erased != 0 && ch != '\b')
+		{
+			ch = digraph(erased, ch);
+			erased = 0;
+		}
+#endif
+
+		/* inhibit detection of special chars (except ^J) after a ^V */
+		if (quoted && ch != '\n')
+		{
+			ch |= 256;
+		}
+
+		/* process the character */
+		switch(ch)
+		{
+		  case ctrl('V'):
+			qaddch('^');
+			qaddch('\b');
+			quoted = TRUE;
+			break;
+
+		  case ctrl('['):
+			return -1;
+
+		  case '\n':
+#if OSK
+		  case '\l':
+#else
+		  case '\r':
+#endif
+			clrtoeol();
+			goto BreakBreak;
+
+		  case '\b':
+			if (len > 0)
+			{
+				len--;
+#ifndef NO_DIGRAPH
+				erased = buf[len];
+#endif
+				for (ch = widths[len]; ch > 0; ch--)
+					addch('\b');
+				if (mode == MODE_EX)
+				{
+					clrtoeol();
+				}
+				tab -= widths[len];
+			}
+			else
+			{
+				return -1;
+			}
+			break;
+
+		  default:
+			/* strip off quotation bit */
+			if (ch & 256)
+			{
+				ch &= ~256;
+				qaddch(' ');
+				qaddch('\b');
+			}
+
+			/* add & echo the char */
+			if (len < bsize - 1)
+			{
+				if (ch == '\t' && !quoted)
+				{
+					widths[len] = *o_tabstop - (tab % *o_tabstop);
+					addstr("        " + 8 - widths[len]);
+					tab += widths[len];
+				}
+				else if (ch > 0 && ch < ' ') /* > 0 by GB */
+				{
+					addch('^');
+					addch(ch + '@');
+					widths[len] = 2;
+					tab += 2;
+				}
+				else if (ch == '\177')
+				{
+					addch('^');
+					addch('?');
+					widths[len] = 2;
+					tab += 2;
+				}
+				else
+				{
+					addch(ch);
+					widths[len] = 1;
+					tab++;
+				}
+				buf[len++] = ch;
+			}
+			else
+			{
+				beep();
+			}
+			quoted = FALSE;
+		}
+	}
+BreakBreak:
+	refresh();
+	buf[len] = '\0';
+	return len;
+}
+
+
+static int	manymsgs; /* This variable keeps msgs from overwriting each other */
+static char	pmsg[80]; /* previous message (waiting to be displayed) */
+
+
+static int showmsg()
+{
+	/* if there is no message to show, then don't */
+	if (!manymsgs)
+		return FALSE;
+
+	/* display the message */
+	move(LINES - 1, 0);
+	if (*pmsg)
+	{
+		standout();
+		qaddch(' ');
+		qaddstr(pmsg);
+		qaddch(' ');
+		standend();
+	}
+	clrtoeol();
+
+	manymsgs = FALSE;
+	return TRUE;
+}
+
+
+void endmsgs()
+{
+	if (manymsgs)
+	{
+		showmsg();
+		addch('\n');
+	}
+}
+
+/* Write a message in an appropriate way.  This should really be a varargs
+ * function, but there is no such thing as vwprintw.  Hack!!!
+ *
+ * In MODE_EX or MODE_COLON, the message is written immediately, with a
+ * newline at the end.
+ *
+ * In MODE_VI, the message is stored in a character buffer.  It is not
+ * displayed until getkey() is called.  msg() will call getkey() itself,
+ * if necessary, to prevent messages from being lost.
+ *
+ * msg("")		- clears the message line
+ * msg("%s %d", ...)	- does a printf onto the message line
+ */
+/*VARARGS1*/
+void msg(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
+	char	*fmt;
+	long	arg1, arg2, arg3, arg4, arg5, arg6, arg7;
+{
+	if (mode != MODE_VI)
+	{
+		sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+		qaddstr(pmsg);
+		addch('\n');
+		exrefresh();
+	}
+	else
+	{
+		/* wait for keypress between consecutive msgs */
+		if (manymsgs)
+		{
+			getkey(WHEN_MSG);
+		}
+
+		/* real message */
+		sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+		if (*fmt)
+		{
+			manymsgs = TRUE;
+		}
+	}
+}
+
+
+/* This function calls refresh() if the option exrefresh is set */
+void exrefresh()
+{
+	char	*scan;
+
+	/* If this ex command wrote ANYTHING set exwrote so vi's  :  command
+	 * can tell that it must wait for a user keystroke before redrawing.
+	 */
+	for (scan=kbuf; scan<stdscr; scan++)
+		if (*scan == '\n')
+			exwrote = TRUE;
+
+	/* now we do the refresh thing */
+	if (*o_exrefresh)
+	{
+		refresh();
+	}
+	else
+	{
+		wqrefresh();
+	}
+	if (mode != MODE_VI)
+	{
+		manymsgs = FALSE;
+	}
+}
+
+
+/* This structure is used to store maps and abbreviations.  The distinction
+ * between them is that maps are stored in the list referenced by the "maps"
+ * pointer, while abbreviations are referenced by the "abbrs" pointer.
+ */
+typedef struct _map
+{
+	struct _map	*next;	/* another abbreviation */
+	short		len;	/* length of the "rawin" characters */
+	short		flags;	/* various flags */
+	char		*label;	/* label of the map/abbr, or NULL */
+	char		*rawin;	/* the "rawin" characters */
+	char		*cooked;/* the "cooked" characters */
+} MAP;
+
+static char	keybuf[KEYBUFSIZE];
+static int	cend;	/* end of input characters */
+static int	user;	/* from user through end are chars typed by user */
+static int	next;	/* index of the next character to be returned */
+static MAP	*match;	/* the matching map, found by countmatch() */
+static MAP	*maps;	/* the map table */
+#ifndef NO_ABBR
+static MAP	*abbrs;	/* the abbreviation table */
+#endif
+
+
+
+/* ring the terminal's bell */
+void beep()
+{
+	/* do a visible/audible bell */
+	if (*o_flash)
+	{
+		do_VB();
+		refresh();
+	}
+	else if (*o_errorbells)
+	{
+		ttywrite("\007", 1);
+	}
+
+	/* discard any buffered input, and abort macros */
+	next = user = cend;
+}
+
+
+
+/* This function replaces a "rawin" character sequence with the "cooked" version,
+ * by modifying the internal type-ahead buffer.
+ */
+void execmap(rawlen, cookedstr, visual)
+	int	rawlen;		/* length of rawin text -- string to delete */
+	char	*cookedstr;	/* the cooked text -- string to insert */
+	int	visual;		/* boolean -- chars to be executed in visual mode? */
+{
+	int	cookedlen;
+	char	*src, *dst;
+	int	i;
+
+	/* find the length of the cooked string */
+	cookedlen = strlen(cookedstr);
+#ifndef NO_EXTENSIONS
+	if (visual)
+	{
+		cookedlen *= 2;
+	}
+#endif
+
+	/* if too big to fit in type-ahead buffer, then don't do it */
+	if (cookedlen + (cend - next) - rawlen > KEYBUFSIZE)
+	{
+		return;
+	}
+
+	/* shift to make room for cookedstr at the front of keybuf */
+	src = &keybuf[next + rawlen];
+	dst = &keybuf[cookedlen];
+	i = cend - (next + rawlen);
+	if (src >= dst)
+	{
+		while (i-- > 0)
+		{
+			*dst++ = *src++;
+		}
+	}
+	else
+	{
+		src += i;
+		dst += i;
+		while (i-- > 0)
+		{
+			*--dst = *--src;
+		}
+	}
+
+	/* insert cookedstr, and adjust offsets */
+	cend += cookedlen - rawlen - next;
+	user += cookedlen - rawlen - next;
+	next = 0;
+	for (dst = keybuf, src = cookedstr; *src; )
+	{
+#ifndef NO_EXTENSIONS
+		if (visual)
+		{
+			*dst++ = ctrl('O');
+			cookedlen--;
+		}
+#endif
+		*dst++ = *src++;
+	}
+
+#ifdef DEBUG2
+	{
+#include <stdio.h>
+		FILE	*debout;
+		int		i;
+
+		debout = fopen("debug.out", "a");
+		fprintf(debout, "After execmap(%d, \"%s\", %d)...\n", rawlen, cookedstr, visual);
+		for (i = 0; i < cend; i++)
+		{
+			if (i == next) fprintf(debout, "(next)");
+			if (i == user) fprintf(debout, "(user)");
+			if (UCHAR(keybuf[i]) < ' ')
+				fprintf(debout, "^%c", keybuf[i] ^ '@');
+			else
+				fprintf(debout, "%c", keybuf[i]);
+		}
+		fprintf(debout, "(end)\n");
+		fclose(debout);
+	}
+#endif
+}
+
+/* This function calls ttyread().  If necessary, it will also redraw the screen,
+ * change the cursor shape, display the mode, and update the ruler.  If the
+ * number of characters read is 0, and we didn't time-out, then it exits because
+ * we've apparently reached the end of an EX script.
+ */
+static int fillkeybuf(when, timeout)
+	int	when;	/* mixture of WHEN_XXX flags */
+	int	timeout;/* timeout in 1/10 second increments, or 0 */
+{
+	int	nkeys;
+#ifndef NO_SHOWMODE
+	static int	oldwhen;	/* "when" from last time */
+	static int	oldleft;
+	static long	oldtop;
+	static long	oldnlines;
+	char		*str;
+#endif
+#ifndef NO_CURSORSHAPE
+	static int	oldcurs;
+#endif
+
+#ifdef DEBUG
+	watch();
+#endif
+
+
+#ifndef NO_CURSORSHAPE
+	/* make sure the cursor is the right shape */
+	if (has_CQ)
+	{
+		if (when != oldcurs)
+		{
+			switch (when)
+			{
+			  case WHEN_EX:		do_CX();	break;
+			  case WHEN_VICMD:	do_CV();	break;
+			  case WHEN_VIINP:	do_CI();	break;
+			  case WHEN_VIREP:	do_CR();	break;
+			}
+			oldcurs = when;
+		}
+	}
+#endif
+
+#ifndef NO_SHOWMODE
+	/* if "showmode" then say which mode we're in */
+	if (*o_smd && (when & WHENMASK))
+	{
+		/* redraw the screen before we check to see whether the
+		 * "showmode" message needs to be redrawn.
+		 */
+		redraw(cursor, !(when & WHEN_VICMD));
+
+		/* now the "topline" test should be valid */
+		if (when != oldwhen || topline != oldtop || leftcol != oldleft || nlines != oldnlines)
+		{
+			oldwhen = when;
+			oldtop = topline;
+			oldleft = leftcol;
+			oldnlines = nlines;
+
+			if (when & WHEN_VICMD)	    str = "Command";
+			else if (when & WHEN_VIINP) str = " Input ";
+			else if (when & WHEN_VIREP) str = "Replace";
+			else if (when & WHEN_REP1)  str = " Rep 1 ";
+			else if (when & WHEN_CUT)   str = "BufName";
+			else if (when & WHEN_MARK)  str = "Mark AZ";
+			else if (when & WHEN_CHAR)  str = "Dest Ch";
+			else			    str = (char *)0;
+
+			if (str)
+			{
+				move(LINES - 1, COLS - 10);
+				standout();
+				qaddstr(str);
+				standend();
+			}
+		}
+	}
+#endif
+
+#ifndef NO_EXTENSIONS
+	/* maybe display the ruler */
+	if (*o_ruler && (when & (WHEN_VICMD|WHEN_VIINP|WHEN_VIREP)))
+	{
+		char	buf[20];
+
+		redraw(cursor, !(when & WHEN_VICMD));
+		pfetch(markline(cursor));
+		sprintf(buf, "%7ld,%-4d", markline(cursor), 1 + idx2col(cursor, ptext, when & (WHEN_VIINP|WHEN_VIREP)));
+		move(LINES - 1, COLS - 22);
+		addstr(buf);
+	}
+#endif
+
+	/* redraw, so the cursor is in the right place */
+	if (when & WHENMASK)
+	{
+		redraw(cursor, !(when & (WHENMASK & ~(WHEN_VIREP|WHEN_VIINP))));
+	}
+
+	/* Okay, now we can finally read the rawin keystrokes */
+	refresh();
+	nkeys = ttyread(keybuf + cend, sizeof keybuf - cend, timeout);
+
+	/* if nkeys == 0 then we've reached EOF of an ex script. */
+	if (nkeys == 0 && timeout == 0)
+	{
+		tmpabort(TRUE);
+		move(LINES - 1, 0);
+		clrtoeol();
+		refresh();
+		endwin();
+		exit(1);
+	}
+
+	cend += nkeys;
+	user += nkeys;
+	return nkeys;
+}
+
+
+/* This function counts the number of maps that could match the characters
+ * between &keybuf[next] and &keybuf[cend], including incomplete matches.
+ * The longest comlete match is remembered via the "match" variable.
+ */
+static int countmatch(when)
+	int	when;	/* mixture of WHEN_XXX flags */
+{
+	MAP	*map;
+	int	count;
+
+	/* clear the "match" variable */
+	match = (MAP *)0;
+
+	/* check every map */
+	for (count = 0, map = maps; map; map = map->next)
+	{
+		/* can't match if wrong mode */
+		if ((map->flags & when) == 0)
+		{
+			continue;
+		}
+
+		/* would this be a complete match? */
+		if (map->len <= cend - next)
+		{
+			/* Yes, it would be.  Now does it really match? */
+			if (!strncmp(map->rawin, &keybuf[next], map->len))
+			{
+				count++;
+
+				/* if this is the longest complete match,
+				 * then remember it.
+				 */
+				if (!match || match->len < map->len)
+				{
+					match = map;
+				}
+			}
+		}
+		else
+		{
+			/* No, it wouldn't.  But check for partial match */
+			if (!strncmp(map->rawin, &keybuf[next], cend - next))
+			{
+				count++;
+			}
+		}
+	}
+	return count;
+}
+
+
+#ifndef NO_ABBR
+/* This function checks to see whether a word is an abbreviation.  If it is,
+ * then an appropriate number of backspoace characters is inserted into the
+ * type-ahead buffer, followed by the expanded form of the abbreviation.
+ */
+static void expandabbr(word, wlen)
+	char	*word;
+	int	wlen;
+{
+	MAP	*abbr;
+
+	/* if the next character wouldn't end the word, then don't expand */
+	if (isalnum(keybuf[next]) || keybuf[next] == ctrl('V'))
+	{
+		return;
+	}
+
+	/* find the abbreviation, if any */
+	for (abbr = abbrs;
+	     abbr && (abbr->len != wlen || strncmp(abbr->rawin, word, wlen));
+	     abbr = abbr->next)
+	{
+	}
+
+	/* If an abbreviation was found, then expand it by inserting the long
+	 * version into the type-ahead buffer, and then inserting (in front of
+	 * the long version) enough backspaces to erase to the short version.
+	 */
+	if (abbr)
+	{
+		execmap(0, abbr->cooked, FALSE);
+		while (wlen > 15)
+		{
+			execmap(0, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", FALSE);
+			wlen -= 15;
+		}
+		if (wlen > 0)
+		{
+			execmap(0, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" + 15 - wlen, FALSE);
+		}
+	}
+}
+#endif
+
+
+/* This function calls getabkey() without attempting to expand abbreviations */
+int getkey(when)
+	int	when;	/* mixture of WHEN_XXX flags */
+{
+	return getabkey(when, "", 0);
+}
+
+
+/* This is it.  This function returns keystrokes one-at-a-time, after mapping
+ * and abbreviations have been taken into account.
+ */
+int getabkey(when, word, wlen)
+	int	when;	/* mixture of WHEN_XXX flags */
+	char	*word;	/* a word that may need to be expanded as an abbr */
+	int	wlen;	/* length of "word" -- since "word" might not have \0 */
+{
+	int	matches;
+
+	/* if this key is needed for delay between multiple error messages,
+	 * then reset the manymsgs flag and abort any mapped key sequence.
+	 */
+	if (showmsg())
+	{
+		if (when == WHEN_MSG)
+		{
+#ifndef CRUNCH
+			if (!*o_more)
+			{
+				refresh();
+				return ' ';
+			}
+#endif
+			qaddstr("[More...]");
+			refresh();
+			execmap(user, "", FALSE);
+		}
+	}
+
+#ifdef DEBUG
+	/* periodically check for screwed up internal tables */
+	watch();
+#endif
+
+	/* if buffer empty, read some characters without timeout */
+	if (next >= cend)
+	{
+		next = user = cend = 0;
+		fillkeybuf(when, 0);
+	}
+
+	/* try to map the key, unless already mapped and not ":set noremap" */
+	if (next >= user || *o_remap)
+	{
+		do
+		{
+			do
+			{
+				matches = countmatch(when);
+			} while (matches > 1 && fillkeybuf(when, *o_keytime) > 0);
+			if (matches == 1)
+			{
+				execmap(match->len, match->cooked,
+					(match->flags & WHEN_INMV) != 0 
+					 && (when & (WHEN_VIINP|WHEN_VIREP)) != 0);
+			}
+		} while (*o_remap && matches == 1);
+	}
+
+#ifndef NO_ABBR
+	/* try to expand an abbreviation, except in visual command mode */
+	if (wlen > 0 && (mode & (WHEN_EX|WHEN_VIINP|WHEN_VIREP)) != 0)
+	{
+		expandabbr(word, wlen);
+	}
+#endif
+
+	/* ERASEKEY should always be mapped to '\b'. */
+	if (keybuf[next] == ERASEKEY)
+	{
+		keybuf[next] = '\b';
+	}
+
+	/* return the next key */
+	return keybuf[next++];
+}
+
+/* This function maps or unmaps a key */
+void mapkey(rawin, cooked, when, name)
+	char	*rawin;	/* the input key sequence, before mapping */
+	char	*cooked;/* after mapping -- or NULL to remove map */
+	short	when;	/* bitmap of when mapping should happen */
+	char	*name;	/* name of the key, NULL for no name, "abbr" for abbr */
+{
+	MAP	**head;	/* head of list of maps or abbreviations */
+	MAP	*scan;	/* used for scanning through the list */
+	MAP	*prev;	/* used during deletions */
+
+	/* Is this a map or an abbreviation?  Choose the right list. */
+#ifndef NO_ABBR
+	head = ((!name || strcmp(name, "abbr")) ? &maps : &abbrs);
+#else
+	head = &maps;
+#endif
+
+	/* try to find the map in the list */
+	for (scan = *head, prev = (MAP *)0;
+	     scan && (strcmp(rawin, scan->rawin) ||
+		!(scan->flags & when & (WHEN_EX|WHEN_VICMD|WHEN_VIINP|WHEN_VIREP)));
+	     prev = scan, scan = scan->next)
+	{
+	}
+
+	/* trying to map? (not unmap) */
+	if (cooked && *cooked)
+	{
+		/* if map starts with "visual ", then mark it as a visual map */
+		if (head == &maps && !strncmp(cooked, "visual ", 7))
+		{
+			cooked += 7;
+			when |= WHEN_INMV;
+		}
+
+		/* "visual" maps always work in input mode */
+		if (when & WHEN_INMV)
+		{
+			when |= WHEN_VIINP|WHEN_VIREP|WHEN_POPUP;
+		}
+
+		/* if not already in the list, then allocate a new structure */
+		if (!scan)
+		{
+			scan = (MAP *)malloc(sizeof(MAP));
+			scan->len = strlen(rawin);
+			scan->rawin = malloc(scan->len + 1);
+			strcpy(scan->rawin, rawin);
+			scan->flags = when;
+			scan->label = name;
+			if (*head)
+			{
+				prev->next = scan;
+			}
+			else
+			{
+				*head = scan;
+			}
+			scan->next = (MAP *)0;
+		}
+		else /* recycle old structure */
+		{
+			free(scan->cooked);
+		}
+		scan->cooked = malloc(strlen(cooked) + 1);
+		strcpy(scan->cooked, cooked);
+	}
+	else /* unmapping */
+	{
+		/* if nothing to unmap, then exit silently */
+		if (!scan)
+		{
+			return;
+		}
+
+		/* unlink the structure from the list */
+		if (prev)
+		{
+			prev->next = scan->next;
+		}
+		else
+		{
+			*head = scan->next;
+		}
+
+		/* free it, and the strings that it refers to */
+		free(scan->rawin);
+		free(scan->cooked);
+		free(scan);
+	}
+}
+
+
+/* This function returns a printable version of a string.  It uses tmpblk.c */
+char *printable(str)
+	char	*str;	/* the string to convert */
+{
+	char	*build;	/* used for building the string */
+
+	for (build = tmpblk.c; *str; str++)
+	{
+#if AMIGA
+		if (*str == '\233')
+		{
+			*build++ = '<';
+			*build++ = 'C';
+			*build++ = 'S';
+			*build++ = 'I';
+			*build++ = '>';
+		} else 
+#endif
+		if (UCHAR(*str) < ' ' || *str == '\177')
+		{
+			*build++ = '^';
+			*build++ = *str ^ '@';
+		}
+		else
+		{
+			*build++ = *str;
+		}
+	}
+	*build = '\0';
+	return tmpblk.c;
+}
+
+/* This function displays the contents of either the map table or the
+ * abbreviation table.  User commands call this function as follows:
+ *	:map	dumpkey(WHEN_VICMD, FALSE);
+ *	:map!	dumpkey(WHEN_VIREP|WHEN_VIINP, FALSE);
+ *	:abbr	dumpkey(WHEN_VIINP|WHEN_VIREP, TRUE);
+ *	:abbr!	dumpkey(WHEN_EX|WHEN_VIINP|WHEN_VIREP, TRUE);
+ */
+void dumpkey(when, abbr)
+	int	when;	/* WHEN_XXXX of mappings to be dumped */
+	int	abbr;	/* boolean: dump abbreviations instead of maps? */
+{
+	MAP	*scan;
+	char	*str;
+	int	len;
+
+#ifndef NO_ABBR
+	for (scan = (abbr ? abbrs : maps); scan; scan = scan->next)
+#else
+	for (scan = maps; scan; scan = scan->next)
+#endif
+	{
+		/* skip entries that don't match "when" */
+		if ((scan->flags & when) == 0)
+		{
+			continue;
+		}
+
+		/* dump the key label, if any */
+		if (!abbr)
+		{
+			len = 8;
+			if (scan->label)
+			{
+				qaddstr(scan->label);
+				len -= strlen(scan->label);
+			}
+			do
+			{
+				qaddch(' ');
+			} while (len-- > 0);
+		}
+
+		/* dump the rawin version */
+		str = printable(scan->rawin);
+		qaddstr(str);
+		len = strlen(str);
+		do
+		{
+			qaddch(' ');
+		} while (len++ < 8);
+			
+		/* dump the mapped version */
+#ifndef NO_EXTENSIONS
+		if ((scan->flags & WHEN_INMV) && (when & (WHEN_VIINP|WHEN_VIREP)))
+		{
+			qaddstr("visual ");
+		}
+#endif
+		str = printable(scan->cooked);
+		qaddstr(str);
+		addch('\n');
+		exrefresh();
+	}
+}
+
+#ifndef NO_MKEXRC
+
+static safequote(str)
+	char	*str;
+{
+	char	*build;
+
+	build = tmpblk.c + strlen(tmpblk.c);
+	while (*str)
+	{
+		if (*str <= ' ' && *str >= 1 || *str == '|')
+		{
+			*build++ = ctrl('V');
+		}
+		*build++ = *str++;
+	}
+	*build = '\0';
+}
+
+/* This function saves the contents of either the map table or the
+ * abbreviation table into a file.  Both the "bang" and "no bang" versions
+ * are saved.
+ *	:map	dumpkey(WHEN_VICMD, FALSE);
+ *	:map!	dumpkey(WHEN_VIREP|WHEN_VIINP, FALSE);
+ *	:abbr	dumpkey(WHEN_VIINP|WHEN_VIREP, TRUE);
+ *	:abbr!	dumpkey(WHEN_EX|WHEN_VIINP|WHEN_VIREP, TRUE);
+ */
+savemaps(fd, abbr)
+	int	fd;	/* file descriptor of an open file to write to */
+	int	abbr;	/* boolean: do abbr table? (else do map table) */
+{
+	MAP	*scan;
+	char	*str;
+	int	bang;
+	int	when;
+	int	len;
+
+# ifndef NO_ABBR
+	for (scan = (abbr ? abbrs : maps); scan; scan = scan->next)
+# else
+	for (scan = maps; scan; scan = scan->next)
+# endif
+	{
+		/* skip maps that have labels, except for function keys */
+		if (scan->label && *scan->label != '#')
+		{
+			continue;
+		}
+
+		for (bang = 0; bang < 2; bang++)
+		{
+			/* decide which "when" flags we want */
+# ifndef NO_ABBR
+			if (abbr)
+				when = (bang ? WHEN_EX|WHEN_VIINP|WHEN_VIREP : WHEN_VIINP|WHEN_VIREP);
+			else
+# endif
+				when = (bang ? WHEN_VIREP|WHEN_VIINP : WHEN_VICMD);
+
+			/* skip entries that don't match "when" */
+			if ((scan->flags & when) == 0)
+			{
+				continue;
+			}
+
+			/* write a "map" or "abbr" command name */
+# ifndef NO_ABBR
+			if (abbr)
+				strcpy(tmpblk.c, "abbr");
+			else
+# endif
+				strcpy(tmpblk.c, "map");
+
+			/* maybe write a bang.  Definitely write a space */
+			if (bang)
+				strcat(tmpblk.c, "! ");
+			else
+				strcat(tmpblk.c, " ");
+
+			/* write the rawin version */
+# ifndef NO_FKEY
+			if (scan->label)
+				strcat(tmpblk.c, scan->label);
+			else
+# endif
+				safequote(scan->rawin);
+			strcat(tmpblk.c, " ");
+				
+			/* dump the mapped version */
+# ifndef NO_EXTENSIONS
+			if ((scan->flags & WHEN_INMV) && (when & (WHEN_VIINP|WHEN_VIREP)))
+			{
+				strcat(tmpblk.c, "visual ");
+			}
+# endif
+			safequote(scan->cooked);
+			strcat(tmpblk.c, "\n");
+			twrite(fd, tmpblk.c, strlen(tmpblk.c));
+		}
+	}
+}
+#endif
Index: /trunk/minix/commands/elvis/tmp.c
===================================================================
--- /trunk/minix/commands/elvis/tmp.c	(revision 9)
+++ /trunk/minix/commands/elvis/tmp.c	(revision 9)
@@ -0,0 +1,759 @@
+/* tmp.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains functions which create & readback a TMPFILE */
+
+
+#include "config.h"
+#include "vi.h"
+#if TOS
+# include <stat.h>
+#else
+# if OSK
+#  include "osk.h"
+# else
+#  if AMIGA
+#   include "amistat.h"
+#  else
+#   include <sys/stat.h>
+#  endif
+# endif
+#endif
+#if TURBOC
+# include <process.h>
+#endif
+
+#ifndef NO_MODELINES
+static void do_modelines(l, stop)
+	long	l;	/* line number to start at */
+	long	stop;	/* line number to stop at */
+{
+	char	*str;	/* used to scan through the line */
+	char	*start;	/* points to the start of the line */
+	char	buf[80];
+
+	/* if modelines are disabled, then do nothing */
+	if (!*o_modelines)
+	{
+		return;
+	}
+
+	/* for each line... */
+	for (; l <= stop; l++)
+	{
+		/* for each position in the line.. */
+		for (str = fetchline(l); *str; str++)
+		{
+			/* if it is the start of a modeline command... */
+			if ((str[0] == 'e' && str[1] == 'x'
+			  || str[0] == 'v' && str[1] == 'i')
+			  && str[2] == ':')
+			{
+				start = str += 3;
+
+				/* find the end */
+				for (str = start + strlen(start); *--str != ':'; )
+				{
+				}
+
+				/* if it is a well-formed modeline, execute it */
+				if (str > start && str - start < sizeof buf)
+				{
+					strncpy(buf, start, (int)(str - start));
+					exstring(buf, str - start, '\\');
+					break;
+				}
+			}
+		}
+	}
+}
+#endif
+
+
+/* The FAIL() macro prints an error message and then exits. */
+#define FAIL(why,arg)	mode = MODE_EX; msg(why, arg); endwin(); exit(9)
+
+/* This is the name of the temp file */
+static char	tmpname[80];
+
+/* This function creates the temp file and copies the original file into it.
+ * Returns if successful, or stops execution if it fails.
+ */
+int tmpstart(filename)
+	char		*filename; /* name of the original file */
+{
+	int		origfd;	/* fd used for reading the original file */
+	struct stat	statb;	/* stat buffer, used to examine inode */
+	REG BLK		*this;	/* pointer to the current block buffer */
+	REG BLK		*next;	/* pointer to the next block buffer */
+	int		inbuf;	/* number of characters in a buffer */
+	int		nread;	/* number of bytes read */
+	REG int		j, k;
+	int		i;
+	long		nbytes;
+
+	/* switching to a different file certainly counts as a change */
+	changes++;
+	redraw(MARK_UNSET, FALSE);
+
+	/* open the original file for reading */
+	*origname = '\0';
+	if (filename && *filename)
+	{
+		strcpy(origname, filename);
+		origfd = open(origname, O_RDONLY);
+		if (origfd < 0 && errno != ENOENT)
+		{
+			msg("Can't open \"%s\"", origname);
+			return tmpstart("");
+		}
+		if (origfd >= 0)
+		{
+			if (stat(origname, &statb) < 0)
+			{
+				FAIL("Can't stat \"%s\"", origname);
+			}
+#if TOS
+			if (origfd >= 0 && (statb.st_mode & S_IJDIR))
+#else
+# if OSK
+			if (origfd >= 0 && (statb.st_mode & S_IFDIR))
+# else
+			if (origfd >= 0 && (statb.st_mode & S_IFMT) != S_IFREG)
+# endif
+#endif
+			{
+				msg("\"%s\" is not a regular file", origname);
+				return tmpstart("");
+			}
+		}
+		else
+		{
+			stat(".", &statb);
+		}
+		if (origfd >= 0)
+		{
+			origtime = statb.st_mtime;
+#if OSK
+			if (*o_readonly || !(statb.st_mode &
+				  ((getuid() >> 16) == 0 ? S_IOWRITE | S_IWRITE :
+				  ((statb.st_gid != (getuid() >> 16) ? S_IOWRITE : S_IWRITE)))))
+#endif
+#if AMIGA || MSDOS || (TOS && defined(__GNUC__))
+			if (*o_readonly || !(statb.st_mode & S_IWRITE))
+#endif
+#if TOS && !defined(__GNUC__)
+			if (*o_readonly || (statb.st_mode & S_IJRON))
+#endif
+#if ANY_UNIX
+			if (*o_readonly || !(statb.st_mode &
+				  ((geteuid() == 0) ? 0222 :
+				  ((statb.st_uid != geteuid() ? 0022 : 0200)))))
+#endif
+#if VMS
+			if (*o_readonly)
+#endif
+			{
+				setflag(file, READONLY);
+			}
+		}
+		else
+		{
+			origtime = 0L;
+		}
+	}
+	else
+	{
+		setflag(file, NOFILE);
+		origfd = -1;
+		origtime = 0L;
+		stat(".", &statb);
+	}
+
+	/* make a name for the tmp file */
+	tmpnum++;
+#if MSDOS || TOS
+	/* MS-Dos doesn't allow multiple slashes, but supports drives
+	 * with current directories.
+	 * This relies on TMPNAME beginning with "%s\\"!!!!
+	 */
+	strcpy(tmpname, o_directory);
+	if ((i = strlen(tmpname)) && !strchr(":/\\", tmpname[i-1]))
+		tmpname[i++]=SLASH;
+	sprintf(tmpname+i, TMPNAME+3, getpid(), tmpnum);
+#else
+	sprintf(tmpname, TMPNAME, o_directory, getpid(), tmpnum);
+#endif
+
+	/* make sure nobody else is editing the same file */
+	if (access(tmpname, 0) == 0)
+	{
+		FAIL("Temp file \"%s\" already exists?", tmpname);
+	}
+
+	/* create the temp file */
+#if ANY_UNIX
+	close(creat(tmpname, 0600));		/* only we can read it */
+#else
+	close(creat(tmpname, FILEPERMS));	/* anybody body can read it, alas */
+#endif
+	tmpfd = open(tmpname, O_RDWR | O_BINARY);
+	if (tmpfd < 0)
+	{
+		FAIL("Can't create temp file... Does directory \"%s\" exist?", o_directory);
+		return 1;
+	}
+
+	/* allocate space for the header in the file */
+	write(tmpfd, hdr.c, (unsigned)BLKSIZE);
+	write(tmpfd, tmpblk.c, (unsigned)BLKSIZE);
+
+#ifndef NO_RECYCLE
+	/* initialize the block allocator */
+	/* This must already be done here, before the first attempt
+	 * to write to the new file! GB */
+	garbage();
+#endif
+
+	/* initialize lnum[] */
+	for (i = 1; i < MAXBLKS; i++)
+	{
+		lnum[i] = INFINITY;
+	}
+	lnum[0] = 0;
+
+	/* if there is no original file, then create a 1-line file */
+	if (origfd < 0)
+	{
+		hdr.n[0] = 0;	/* invalid inode# denotes new file */
+
+		this = blkget(1); 	/* get the new text block */
+		strcpy(this->c, "\n");	/* put a line in it */
+
+		lnum[1] = 1L;	/* block 1 ends with line 1 */
+		nlines = 1L;	/* there is 1 line in the file */
+		nbytes = 1L;
+
+		if (*origname)
+		{
+			msg("\"%s\" [NEW FILE]  1 line, 1 char", origname);
+		}
+		else
+		{
+			msg("\"[NO FILE]\"  1 line, 1 char");
+		}
+	}
+	else /* there is an original file -- read it in */
+	{
+		nbytes = nlines = 0;
+
+		/* preallocate 1 "next" buffer */
+		i = 1;
+		next = blkget(i);
+		inbuf = 0;
+
+		/* loop, moving blocks from orig to tmp */
+		for (;;)
+		{
+			/* "next" buffer becomes "this" buffer */
+			this = next;
+
+			/* read [more] text into this block */
+			nread = tread(origfd, &this->c[inbuf], BLKSIZE - 1 - inbuf);
+			if (nread < 0)
+			{
+				close(origfd);
+				close(tmpfd);
+				tmpfd = -1;
+				unlink(tmpname);
+				FAIL("Error reading \"%s\"", origname);
+			}
+
+			/* convert NUL characters to something else */
+			for (j = k = inbuf; k < inbuf + nread; k++)
+			{
+				if (!this->c[k])
+				{
+					setflag(file, HADNUL);
+					this->c[j++] = 0x80;
+				}
+#ifndef CRUNCH
+				else if (*o_beautify && this->c[k] < ' ' && this->c[k] > 0)
+				{
+					if (this->c[k] == '\t'
+					 || this->c[k] == '\n'
+					 || this->c[k] == '\f')
+					{
+						this->c[j++] = this->c[k];
+					}
+					else if (this->c[k] == '\b')
+					{
+						/* delete '\b', but complain */
+						setflag(file, HADBS);
+					}
+					/* else silently delete control char */
+				}
+#endif
+				else
+				{
+					this->c[j++] = this->c[k];
+				}
+			}
+			inbuf = j;
+
+			/* if the buffer is empty, quit */
+			if (inbuf == 0)
+			{
+				goto FoundEOF;
+			}
+
+#if MSDOS || TOS
+/* BAH! MS text mode read fills inbuf, then compresses eliminating \r
+   but leaving garbage at end of buf. The same is true for TURBOC. GB. */
+
+			memset(this->c + inbuf, '\0', BLKSIZE - inbuf);
+#endif
+
+			/* search backward for last newline */
+			for (k = inbuf; --k >= 0 && this->c[k] != '\n';)
+			{
+			}
+			if (k++ < 0)
+			{
+				if (inbuf >= BLKSIZE - 1)
+				{
+					k = 80;
+				}
+				else
+				{
+					k = inbuf;
+				}
+			}
+
+			/* allocate next buffer */
+			next = blkget(++i);
+
+			/* move fragmentary last line to next buffer */
+			inbuf -= k;
+			for (j = 0; k < BLKSIZE; j++, k++)
+			{
+				next->c[j] = this->c[k];
+				this->c[k] = 0;
+			}
+
+			/* if necessary, add a newline to this buf */
+			for (k = BLKSIZE - inbuf; --k >= 0 && !this->c[k]; )
+			{
+			}
+			if (this->c[k] != '\n')
+			{
+				setflag(file, ADDEDNL);
+				this->c[k + 1] = '\n';
+			}
+
+			/* count the lines in this block */
+			for (k = 0; k < BLKSIZE && this->c[k]; k++)
+			{
+				if (this->c[k] == '\n')
+				{
+					nlines++;
+				}
+				nbytes++;
+			}
+			lnum[i - 1] = nlines;
+		}
+FoundEOF:
+
+		/* if this is a zero-length file, add 1 line */
+		if (nlines == 0)
+		{
+			this = blkget(1); 	/* get the new text block */
+			strcpy(this->c, "\n");	/* put a line in it */
+
+			lnum[1] = 1;	/* block 1 ends with line 1 */
+			nlines = 1;	/* there is 1 line in the file */
+			nbytes = 1;
+		}
+
+#if MSDOS || TOS
+		/* each line has an extra CR that we didn't count yet */
+		nbytes += nlines;
+#endif
+
+		/* report the number of lines in the file */
+		msg("\"%s\" %s %ld line%s, %ld char%s",
+			origname,
+			(tstflag(file, READONLY) ? "[READONLY]" : ""),
+			nlines,
+			nlines == 1 ? "" : "s",
+			nbytes,
+			nbytes == 1 ? "" : "s");
+	}
+
+	/* initialize the cursor to start of line 1 */
+	cursor = MARK_FIRST;
+
+	/* close the original file */
+	close(origfd);
+
+	/* any other messages? */
+	if (tstflag(file, HADNUL))
+	{
+		msg("This file contained NULs.  They've been changed to \\x80 chars");
+	}
+	if (tstflag(file, ADDEDNL))
+	{
+		msg("Newline characters have been inserted to break up long lines");
+	}
+#ifndef CRUNCH
+	if (tstflag(file, HADBS))
+	{
+		msg("Backspace characters deleted due to ':set beautify'");
+	}
+#endif
+
+	storename(origname);
+
+#ifndef NO_MODELINES
+	if (nlines > 10)
+	{
+		do_modelines(1L, 5L);
+		do_modelines(nlines - 4L, nlines);
+	}
+	else
+	{
+		do_modelines(1L, nlines);
+	}
+#endif
+
+	/* force all blocks out onto the disk, to support file recovery */
+	blksync();
+
+	return 0;
+}
+
+
+
+/* This function copies the temp file back onto an original file.
+ * Returns TRUE if successful, or FALSE if the file could NOT be saved.
+ */
+int tmpsave(filename, bang)
+	char	*filename;	/* the name to save it to */
+	int	bang;		/* forced write? */
+{
+	int		fd;	/* fd of the file we're writing to */
+	REG int		len;	/* length of a text block */
+	REG BLK		*this;	/* a text block */
+	long		bytes;	/* byte counter */
+	REG int		i;
+
+	/* if no filename is given, assume the original file name */
+	if (!filename || !*filename)
+	{
+		filename = origname;
+	}
+
+	/* if still no file name, then fail */
+	if (!*filename)
+	{
+		msg("Don't know a name for this file -- NOT WRITTEN");
+		return FALSE;
+	}
+
+	/* can't rewrite a READONLY file */
+#if AMIGA
+	if (!strcmp(filename, origname) && tstflag(file, READONLY) && !bang)
+#else
+	if (!strcmp(filename, origname) && *o_readonly && !bang)
+#endif
+	{
+		msg("\"%s\" [READONLY] -- NOT WRITTEN", filename);
+		return FALSE;
+	}
+
+	/* open the file */
+	if (*filename == '>' && filename[1] == '>')
+	{
+		filename += 2;
+		while (*filename == ' ' || *filename == '\t')
+		{
+			filename++;
+		}
+#ifdef O_APPEND
+		fd = open(filename, O_WRONLY|O_APPEND);
+#else
+		fd = open(filename, O_WRONLY);
+		lseek(fd, 0L, 2);
+#endif
+	}
+	else
+	{
+		/* either the file must not exist, or it must be the original
+		 * file, or we must have a bang, or "writeany" must be set.
+		 */
+		if (strcmp(filename, origname) && access(filename, 0) == 0 && !bang
+#ifndef CRUNCH
+		    && !*o_writeany
+#endif
+				   )
+		{
+			msg("File already exists - Use :w! to overwrite");
+			return FALSE;
+		}
+#if VMS
+		/* Create a new VMS version of this file. */
+		{ 
+		char *strrchr(), *ptr = strrchr(filename,';');
+		if (ptr) *ptr = '\0';  /* Snip off any ;number in the name */
+		}
+#endif
+		fd = creat(filename, FILEPERMS);
+	}
+	if (fd < 0)
+	{
+		msg("Can't write to \"%s\" -- NOT WRITTEN", filename);
+		return FALSE;
+	}
+
+	/* write each text block to the file */
+	bytes = 0L;
+	for (i = 1; i < MAXBLKS && (this = blkget(i)) && this->c[0]; i++)
+	{
+		for (len = 0; len < BLKSIZE && this->c[len]; len++)
+		{
+		}
+		if (twrite(fd, this->c, len) < len)
+		{
+			msg("Trouble writing to \"%s\"", filename);
+			if (!strcmp(filename, origname))
+			{
+				setflag(file, MODIFIED);
+			}
+			close(fd);
+			return FALSE;
+		}
+		bytes += len;
+	}
+
+	/* reset the "modified" flag, but not the "undoable" flag */
+	clrflag(file, MODIFIED);
+	significant = FALSE;
+
+	/* report lines & characters */
+#if MSDOS || TOS
+	bytes += nlines; /* for the inserted carriage returns */
+#endif
+	msg("Wrote \"%s\"  %ld lines, %ld characters", filename, nlines, bytes);
+
+	/* close the file */
+	close(fd);
+
+	return TRUE;
+}
+
+
+/* This function deletes the temporary file.  If the file has been modified
+ * and "bang" is FALSE, then it returns FALSE without doing anything; else
+ * it returns TRUE.
+ *
+ * If the "autowrite" option is set, then instead of returning FALSE when
+ * the file has been modified and "bang" is false, it will call tmpend().
+ */
+int tmpabort(bang)
+	int	bang;
+{
+	/* if there is no file, return successfully */
+	if (tmpfd < 0)
+	{
+		return TRUE;
+	}
+
+	/* see if we must return FALSE -- can't quit */
+	if (!bang && tstflag(file, MODIFIED))
+	{
+		/* if "autowrite" is set, then act like tmpend() */
+		if (*o_autowrite)
+			return tmpend(bang);
+		else
+			return FALSE;
+	}
+
+	/* delete the tmp file */
+	cutswitch();
+	strcpy(prevorig, origname);
+	prevline = markline(cursor);
+	*origname = '\0';
+	origtime = 0L;
+	blkinit();
+	nlines = 0;
+	initflags();
+	return TRUE;
+}
+
+/* This function saves the file if it has been modified, and then deletes
+ * the temporary file. Returns TRUE if successful, or FALSE if the file
+ * needs to be saved but can't be.  When it returns FALSE, it will not have
+ * deleted the tmp file, either.
+ */
+int tmpend(bang)
+	int	bang;
+{
+	/* save the file if it has been modified */
+	if (tstflag(file, MODIFIED) && !tmpsave((char *)0, FALSE) && !bang)
+	{
+		return FALSE;
+	}
+
+	/* delete the tmp file */
+	tmpabort(TRUE);
+
+	return TRUE;
+}
+
+
+/* If the tmp file has been changed, then this function will force those
+ * changes to be written to the disk, so that the tmp file will survive a
+ * system crash or power failure.
+ */
+#if AMIGA || MSDOS || TOS
+sync()
+{
+	/* MS-DOS and TOS don't flush their buffers until the file is closed,
+	 * so here we close the tmp file and then immediately reopen it.
+	 */
+	close(tmpfd);
+	tmpfd = open(tmpname, O_RDWR | O_BINARY);
+	return 0;
+}
+#endif
+
+
+/* This function stores the file's name in the second block of the temp file.
+ * SLEAZE ALERT!  SLEAZE ALERT!  The "tmpblk" buffer is probably being used
+ * to store the arguments to a command, so we can't use it here.  Instead,
+ * we'll borrow the buffer that is used for "shift-U".
+ */
+storename(name)
+	char	*name;	/* the name of the file - normally origname */
+{
+#ifndef CRUNCH
+	int	len;
+	char	*ptr;
+#endif
+
+	/* we're going to clobber the U_text buffer, so reset U_line */
+	U_line = 0L;
+
+	if (!name)
+	{
+		strncpy(U_text, "", BLKSIZE);
+		U_text[1] = 127;
+	}
+#ifndef CRUNCH
+	else if (*name != SLASH)
+	{
+		/* get the directory name */
+		ptr = getcwd(U_text, BLKSIZE);
+		if (ptr != U_text)
+		{
+			strcpy(U_text, ptr);
+		}
+
+		/* append a slash to the directory name */
+		len = strlen(U_text);
+		U_text[len++] = SLASH;
+
+		/* append the filename, padded with heaps o' NULs */
+		strncpy(U_text + len, *name ? name : "foo", BLKSIZE - len);
+	}
+#endif
+	else
+	{
+		/* copy the filename into U_text */
+		strncpy(U_text, *name ? name : "foo", BLKSIZE);
+	}
+
+	if (tmpfd >= 0)
+	{
+		/* write the name out to second block of the temp file */
+		lseek(tmpfd, (long)BLKSIZE, 0);
+		write(tmpfd, U_text, (unsigned)BLKSIZE);
+	}
+	return 0;
+}
+
+
+
+/* This function handles deadly signals.  It restores sanity to the terminal
+ * preserves the current temp file, and deletes any old temp files.
+ */
+int deathtrap(sig)
+	int	sig;	/* the deadly signal that we caught */
+{
+	char	*why;
+
+	/* restore the terminal's sanity */
+	endwin();
+
+#ifdef CRUNCH
+	why = "-Elvis died";
+#else
+	/* give a more specific description of how Elvis died */
+	switch (sig)
+	{
+# ifdef SIGHUP
+	  case SIGHUP:	why = "-the modem lost its carrier";		break;
+# endif
+# ifndef DEBUG
+#  ifdef SIGILL
+	  case SIGILL:	why = "-Elvis hit an illegal instruction";	break;
+#  endif
+#  ifdef SIGBUS
+	  case SIGBUS:	why = "-Elvis had a bus error";			break;
+#  endif
+#  if defined(SIGSEGV) && !defined(TOS)
+	  case SIGSEGV:	why = "-Elvis had a segmentation violation";	break;
+#  endif
+#  ifdef SIGSYS
+	  case SIGSYS:	why = "-Elvis munged a system call";		break;
+#  endif
+# endif /* !DEBUG */
+# ifdef SIGPIPE
+	  case SIGPIPE:	why = "-the pipe reader died";			break;
+# endif
+# ifdef SIGTERM
+	  case SIGTERM:	why = "-Elvis was terminated";			break;
+# endif
+# if !MINIX
+#  ifdef SIGUSR1
+	  case SIGUSR1:	why = "-Elvis was killed via SIGUSR1";		break;
+#  endif
+#  ifdef SIGUSR2
+	  case SIGUSR2:	why = "-Elvis was killed via SIGUSR2";		break;
+#  endif
+# endif
+	  default:	why = "-Elvis died";				break;
+	}
+#endif
+
+	/* if we had a temp file going, then preserve it */
+	if (tmpnum > 0 && tmpfd >= 0)
+	{
+		close(tmpfd);
+		sprintf(tmpblk.c, "%s \"%s\" %s", PRESERVE, why, tmpname);
+		system(tmpblk.c);
+	}
+
+	/* delete any old temp files */
+	cutend();
+
+	/* exit with the proper exit status */
+	exit(sig);
+}
Index: /trunk/minix/commands/elvis/unix.c
===================================================================
--- /trunk/minix/commands/elvis/unix.c	(revision 9)
+++ /trunk/minix/commands/elvis/unix.c	(revision 9)
@@ -0,0 +1,226 @@
+/* unix.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains the unix-specific versions the ttyread() functions.
+ * There are actually three versions of ttyread() defined here, because
+ * BSD, SysV, and V7 all need quite different implementations.
+ */
+
+#include "config.h"
+#if ANY_UNIX
+# include "vi.h"
+
+# if BSD
+/* For BSD, we use select() to wait for characters to become available,
+ * and then do a read() to actually get the characters.  We also try to
+ * handle SIGWINCH -- if the signal arrives during the select() call, then
+ * we adjust the o_columns and o_lines variables, and fake a control-L.
+ */
+#  include <sys/types.h>
+#  include <sys/time.h>
+int ttyread(buf, len, time)
+	char	*buf;	/* where to store the gotten characters */
+	int	len;	/* maximum number of characters to read */
+	int	time;	/* maximum time to allow for reading */
+{
+	fd_set	rd;	/* the file descriptors that we want to read from */
+	static	tty;	/* 'y' if reading from tty, or 'n' if not a tty */
+	int	i;
+	struct timeval t;
+	struct timeval *tp;
+
+
+	/* do we know whether this is a tty or not? */
+	if (!tty)
+	{
+		tty = (isatty(0) ? 'y' : 'n');
+	}
+
+	/* compute the timeout value */
+	if (time)
+	{
+		t.tv_sec = time / 10;
+		t.tv_usec = (time % 10) * 100000L;
+		tp = &t;
+	}
+	else
+	{
+		tp = (struct timeval *)0;
+	}
+
+	/* loop until we get characters or a definite EOF */
+	for (;;)
+	{
+		if (tty == 'y')
+		{
+			/* wait until timeout or characters are available */
+			FD_ZERO(&rd);
+			FD_SET(0, &rd);
+			i = select(1, &rd, (fd_set *)0, (fd_set *)0, tp);
+		}
+		else
+		{
+			/* if reading from a file or pipe, never timeout!
+			 * (This also affects the way that EOF is detected)
+			 */
+			i = 1;
+		}
+	
+		/* react accordingly... */
+		switch (i)
+		{
+		  case -1:	/* assume we got an EINTR because of SIGWINCH */
+			if (*o_lines != LINES || *o_columns != COLS)
+			{
+				*o_lines = LINES;
+				*o_columns = COLS;
+#ifndef CRUNCH
+				if (!wset)
+				{
+					*o_window = LINES - 1;
+				}
+#endif
+				if (mode != MODE_EX)
+				{
+					/* pretend the user hit ^L */
+					*buf = ctrl('L');
+					return 1;
+				}
+			}
+			break;
+	
+		  case 0:	/* timeout */
+			return 0;
+	
+		  default:	/* characters available */
+			return read(0, buf, len);
+		}
+	}
+}
+# else
+
+# if M_SYSV
+/* For System-V or Coherent, we use VMIN/VTIME to implement the timeout.
+ * For no timeout, VMIN should be 1 and VTIME should be 0; for timeout,
+ * VMIN should be 0 and VTIME should be the timeout value.
+ */
+#  include <termio.h>
+int ttyread(buf, len, time)
+	char	*buf;	/* where to store the gotten characters */
+	int	len;	/* maximum number of characters to read */
+	int	time;	/* maximum time to allow for reading */
+{
+	struct termio tio;
+	int	bytes;	/* number of bytes actually read */
+
+	/* arrange for timeout */
+	ioctl(0, TCGETA, &tio);
+	if (time)
+	{
+		tio.c_cc[VMIN] = 0;
+		tio.c_cc[VTIME] = time;
+	}
+	else
+	{
+		tio.c_cc[VMIN] = 1;
+		tio.c_cc[VTIME] = 0;
+	}
+	ioctl(0, TCSETA, &tio);
+
+	/* Perform the read.  Loop if EINTR error happens */
+	while ((bytes = read(0, buf, len)) < 0)
+	{
+		/* probably EINTR error because a SIGWINCH was received */
+		if (*o_lines != LINES || *o_columns != COLS)
+		{
+			*o_lines = LINES;
+			*o_columns = COLS;
+#ifndef CRUNCH
+			if (!wset)
+			{
+				*o_window = LINES - 1;
+			}
+#endif
+			if (mode != MODE_EX)
+			{
+				/* pretend the user hit ^L */
+				*buf = ctrl('L');
+				return 1;
+			}
+		}
+	}
+
+	/* return the number of bytes read */
+	return bytes;
+
+	/* NOTE: The terminal may be left in a timeout-mode after this function
+	 * returns.  This shouldn't be a problem since Elvis *NEVER* tries to
+	 * read from the keyboard except through this function.
+	 */
+}
+
+# else /* any other version of UNIX, assume it is V7 compatible */
+
+/* For V7 UNIX (including Minix) we set an alarm() before doing a blocking
+ * read(), and assume that the SIGALRM signal will cause the read() function
+ * to give up.
+ */
+
+#include <setjmp.h>
+
+static jmp_buf env;
+
+/*ARGSUSED*/
+int dummy(signo)
+	int	signo;
+{
+	longjmp(env, 1);
+}
+int ttyread(buf, len, time)
+	char	*buf;	/* where to store the gotten characters */
+	int	len;	/* maximum number of characters to read */
+	int	time;	/* maximum time to allow for reading */
+{
+	/* arrange for timeout */
+#if __GNUC__ || _ANSI
+	signal(SIGALRM, (void (*)()) dummy);
+#else
+	signal(SIGALRM, dummy);
+#endif
+	alarm(time);
+
+	/* perform the blocking read */
+	if (setjmp(env) == 0)
+	{
+		len = read(0, buf, len);
+	}
+	else /* I guess we timed out */
+	{
+		len = 0;
+	}
+
+	/* cancel the alarm */
+#if _ANSI
+	signal(SIGALRM, (void (*)())dummy); /* work around a bug in Minix */
+#else
+	signal(SIGALRM, dummy);		    /* work around a bug in Minix */
+#endif
+	alarm(0);
+
+	/* return the number of bytes read */
+	if (len < 0)
+		len = 0;
+	return len;
+}
+
+# endif /* !(M_SYSV || COHERENT) */
+# endif /* !BSD */
+
+#endif /* ANY_UNIX */
Index: /trunk/minix/commands/elvis/vars.c
===================================================================
--- /trunk/minix/commands/elvis/vars.c	(revision 9)
+++ /trunk/minix/commands/elvis/vars.c	(revision 9)
@@ -0,0 +1,115 @@
+/* vars.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains variables which weren't happy anyplace else */
+
+#include "config.h"
+#include "vi.h"
+
+/*------------------------------------------------------------------------*/
+
+/* used to remember whether the file has been modified */
+struct _viflags	viflags;
+
+/* used to access the tmp file */
+long		lnum[MAXBLKS];
+long		nlines;
+int		tmpfd = -1;
+int		tmpnum;
+#ifndef CRUNCH
+int		wset = FALSE;
+#endif
+
+/* used to keep track of the current file & alternate file */
+long		origtime;
+char		origname[256];
+char		prevorig[256];
+long		prevline = 1;
+
+/* used to track various places in the text */
+MARK		mark[NMARKS];	/* marks 'a through 'z, plus mark '' */
+MARK		cursor;		/* the cursor position within the file */
+
+/* which mode of the editor we're in */
+int		mode;		/* vi mode? ex mode? quitting? */
+
+/* used to manage the args list */
+char		args[BLKSIZE];	/* list of filenames to edit */
+int		argno;		/* index of current file in args list */
+int		nargs;		/* number of filenames in args[] */
+
+/* dummy var, never explicitly referenced */
+int		bavar;		/* used only in BeforeAfter macros */
+
+/* used to detect changes that invalidate cached text/blocks */
+long		changes;	/* incremented when file is changed */
+int		significant;	/* boolean: was a *REAL* change made? */
+
+/* used to support the pfetch() macro */
+int		plen;		/* length of the line */
+long		pline;		/* line number that len refers to */
+long		pchgs;		/* "changes" level that len refers to */
+char		*ptext;		/* text of previous line, if valid */
+
+/* misc temporary storage - mostly for strings */
+BLK		tmpblk;		/* a block used to accumulate changes */
+
+/* screen oriented stuff */
+long		topline;	/* file line number of top line */
+int		leftcol;	/* column number of left col */
+int		physcol;	/* physical column number that cursor is on */
+int		physrow;	/* physical row number that cursor is on */
+
+/* used to help minimize that "[Hit a key to continue]" message */
+int		exwrote;	/* Boolean: was the last ex command wordy? */
+
+/* This variable affects the behaviour of certain functions -- most importantly
+ * the input function.
+ */
+int		doingdot;	/* boolean: are we doing the "." command? */
+
+/* This variable affects the behaviour of the ":s" command, and it is also
+ * used to detect & prohibit nesting of ":g" commands
+ */
+int		doingglobal;	/* boolean: are doing a ":g" command? */
+
+/* This variable is zeroed before a command executes, and later ORed with the
+ * command's flags after the command has been executed.  It is used to force
+ * certain flags to be TRUE for *some* invocations of a particular command.
+ * For example, "/regexp/+offset" forces the LNMD flag, and sometimes a "p"
+ * or "P" command will force FRNT.
+ */
+int		force_flags;
+
+/* These are used for reporting multi-line changes to the user */
+long		rptlines;	/* number of lines affected by a command */
+char		*rptlabel;	/* description of how lines were affected */
+
+/* These store info that pertains to the shift-U command */
+long	U_line;			/* line# of the undoable line, or 0l for none */
+char	U_text[BLKSIZE];	/* contents of the undoable line */
+
+
+#ifndef NO_VISIBLE
+/* These are used to implement the 'v' and 'V' commands */
+MARK	V_from;			/* starting point for v or V */
+int	V_linemd;		/* boolean: doing line-mode version? (V, not v) */
+#endif
+
+/* Bigger stack req'ed for TOS and TURBOC */
+
+#if TOS
+long	_stksize = 16384;
+#endif
+
+#if TURBOC
+#include <dos.h>
+extern unsigned _stklen = 16384U;
+#endif
Index: /trunk/minix/commands/elvis/vcmd.c
===================================================================
--- /trunk/minix/commands/elvis/vcmd.c	(revision 9)
+++ /trunk/minix/commands/elvis/vcmd.c	(revision 9)
@@ -0,0 +1,975 @@
+/* vcmd.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+/* This file contains the functions that handle VI commands */
+
+
+#include "config.h"
+#include "ctype.h"
+#include "vi.h"
+#if MSDOS
+# include <process.h>
+# include <string.h>
+#endif
+#if TOS
+# include <osbind.h>
+# include <string.h>
+#endif
+#if OSK
+# include <stdio.h>
+#endif
+
+
+/* This function puts the editor in EX mode */
+MARK v_quit()
+{
+	move(LINES - 1, 0);
+	mode = MODE_EX;
+	return cursor;
+}
+
+/* This function causes the screen to be redrawn */
+MARK v_redraw()
+{
+	redraw(MARK_UNSET, FALSE);
+	return cursor;
+}
+
+/* This function executes a string of EX commands, and waits for a user keystroke
+ * before returning to the VI screen.  If that keystroke is another ':', then
+ * another EX command is read and executed.
+ */
+/*ARGSUSED*/
+MARK v_1ex(m, text)
+	MARK	m;	/* the current line */
+	char	*text;	/* the first command to execute */
+{
+	/* run the command.  be careful about modes & output */
+	exwrote = (mode == MODE_COLON);
+	doexcmd(text);
+	exrefresh();
+
+	/* if mode is no longer MODE_VI, then we should quit right away! */
+	if (mode != MODE_VI && mode != MODE_COLON)
+		return cursor;
+
+	/* The command did some output.  Wait for a keystoke. */
+	if (exwrote)
+	{
+		mode = MODE_VI;	
+		msg("[Hit <RETURN> to continue]");
+		if (getkey(0) == ':')
+		{	mode = MODE_COLON;
+			addch('\n');
+		}
+		else
+			redraw(MARK_UNSET, FALSE);
+	}
+
+	return cursor;
+}
+
+/* This function undoes the last change */
+/*ARGSUSED*/
+MARK v_undo(m)
+	MARK	m;	/* (ignored) */
+{
+	if (undo())
+	{
+		redraw(MARK_UNSET, FALSE);
+	}
+	return cursor;
+}
+
+/* This function deletes the character(s) that the cursor is on */
+MARK v_xchar(m, cnt, cmd)
+	MARK	m;	/* where to start deletions */
+	long	cnt;	/* number of chars to delete */
+	int	cmd;	/* either 'x' or 'X' */
+{
+	DEFAULT(1);
+
+	/* for 'X', adjust so chars are deleted *BEFORE* cursor */
+	if (cmd == 'X')
+	{
+		if (markidx(m) < cnt)
+			return MARK_UNSET;
+		m -= cnt;
+	}
+
+	/* make sure we don't try to delete more thars than there are */
+	pfetch(markline(m));
+	if (markidx(m + cnt) > plen)
+	{
+		cnt = plen - markidx(m);
+	}
+	if (cnt == 0L)
+	{
+		return MARK_UNSET;
+	}
+
+	/* do it */
+	ChangeText
+	{
+		cut(m, m + cnt);
+		delete(m, m + cnt);
+	}
+	return m;
+}
+
+/* This function defines a mark */
+/*ARGSUSED*/
+MARK v_mark(m, count, key)
+	MARK	m;	/* where the mark will be */
+	long	count;	/* (ignored) */
+	int	key;	/* the ASCII label of the mark */
+{
+	if (key < 'a' || key > 'z')
+	{
+		msg("Marks must be from a to z");
+	}
+	else
+	{
+		mark[key - 'a'] = m;
+	}
+	return m;
+}
+
+/* This function toggles upper & lower case letters */
+MARK v_ulcase(m, cnt)
+	MARK	m;	/* where to make the change */
+	long	cnt;	/* number of chars to flip */
+{
+	REG char 	*pos;
+	REG int		j;
+
+	DEFAULT(1);
+
+	/* fetch the current version of the line */
+	pfetch(markline(m));
+
+	/* for each position in the line */
+	for (j = 0, pos = &ptext[markidx(m)]; j < cnt && *pos; j++, pos++)
+	{
+		if (isupper(*pos))
+		{
+			tmpblk.c[j] = tolower(*pos);
+		}
+		else
+		{
+			tmpblk.c[j] = toupper(*pos);
+		}
+	}
+
+	/* if the new text is different from the old, then change it */
+	if (strncmp(tmpblk.c, &ptext[markidx(m)], j))
+	{
+		ChangeText
+		{
+			tmpblk.c[j] = '\0';
+			change(m, m + j, tmpblk.c);
+		}
+	}
+
+	return m + j;
+}
+
+
+MARK v_replace(m, cnt, key)
+	MARK	m;	/* first char to be replaced */
+	long	cnt;	/* number of chars to replace */
+	int	key;	/* what to replace them with */
+{
+	REG char	*text;
+	REG int		i;
+
+	DEFAULT(1);
+
+	/* map ^M to '\n' */
+	if (key == '\r')
+	{
+		key = '\n';
+	}
+
+	/* make sure the resulting line isn't too long */
+	if (cnt > BLKSIZE - 2 - markidx(m))
+	{
+		cnt = BLKSIZE - 2 - markidx(m);
+	}
+
+	/* build a string of the desired character with the desired length */
+	for (text = tmpblk.c, i = cnt; i > 0; i--)
+	{
+		*text++ = key;
+	}
+	*text = '\0';
+
+	/* make sure cnt doesn't extend past EOL */
+	pfetch(markline(m));
+	key = markidx(m);
+	if (key + cnt > plen)
+	{
+		cnt = plen - key;
+	}
+
+	/* do the replacement */
+	ChangeText
+	{
+		change(m, m + cnt, tmpblk.c);
+	}
+
+	if (*tmpblk.c == '\n')
+	{
+		return (m & ~(BLKSIZE - 1)) + cnt * BLKSIZE;
+	}
+	else
+	{
+		return m + cnt - 1;
+	}
+}
+
+MARK v_overtype(m)
+	MARK		m;	/* where to start overtyping */
+{
+	MARK		end;	/* end of a substitution */
+	static long	width;	/* width of a single-line replace */
+
+	/* the "doingdot" version of replace is really a substitution */
+	if (doingdot)
+	{
+		/* was the last one really repeatable? */
+		if (width < 0)
+		{
+			msg("Can't repeat a multi-line overtype command");
+			return MARK_UNSET;
+		}
+
+		/* replacing nothing by nothing?  Don't bother */
+		if (width == 0)
+		{
+			return m;
+		}
+
+		/* replace some chars by repeated text */
+		return v_subst(m, width);
+	}
+
+	/* Normally, we input starting here, in replace mode */
+	ChangeText
+	{
+		end = input(m, m, WHEN_VIREP, FALSE);
+	}
+
+	/* if we ended on the same line we started on, then this
+	 * overtype is repeatable via the dot key.
+	 */
+	if (markline(end) == markline(m) && end >= m - 1L)
+	{
+		width = end - m + 1L;
+	}
+	else /* it isn't repeatable */
+	{
+		width = -1L;
+	}
+
+	return end;
+}
+
+
+/* This function selects which cut buffer to use */
+/*ARGSUSED*/
+MARK v_selcut(m, cnt, key)
+	MARK	m;
+	long	cnt;
+	int	key;
+{
+	cutname(key);
+	return m;
+}
+
+/* This function pastes text from a cut buffer */
+/*ARGSUSED*/
+MARK v_paste(m, cnt, cmd)
+	MARK	m;	/* where to paste the text */
+	long	cnt;	/* (ignored) */
+	int	cmd;	/* either 'p' or 'P' */
+{
+	MARK	dest;
+
+	ChangeText
+	{
+		/* paste the text, and find out where it ends */
+		dest = paste(m, cmd == 'p', TRUE);
+
+		/* was that a line-mode paste? */
+		if (dest && markline(dest) != markline(m))
+		{
+			/* line-mode pastes leave the cursor at the front
+			 * of the first pasted line.
+			 */
+			dest = m;
+			if (cmd == 'p')
+			{
+				dest += BLKSIZE;
+			}
+			force_flags |= FRNT;
+		}
+	}
+	return dest;
+}
+
+/* This function yanks text into a cut buffer */
+MARK v_yank(m, n)
+	MARK	m, n;	/* range of text to yank */
+{
+	cut(m, n);
+	return m;
+}
+
+/* This function deletes a range of text */
+MARK v_delete(m, n)
+	MARK	m, n;	/* range of text to delete */
+{
+	/* illegal to try and delete nothing */
+	if (n <= m)
+	{
+		return MARK_UNSET;
+	}
+
+	/* Do it */
+	ChangeText
+	{
+		cut(m, n);
+		delete(m, n);
+	}
+	return m;
+}
+
+
+/* This starts input mode without deleting anything */
+MARK v_insert(m, cnt, key)
+	MARK	m;	/* where to start (sort of) */
+	long	cnt;	/* repeat how many times? */
+	int	key;	/* what command is this for? {a,A,i,I,o,O} */
+{
+	int	wasdot;
+	long	reps;
+	int	above;	/* boolean: new line going above old line? */
+
+	DEFAULT(1);
+
+	ChangeText
+	{
+		/* tweak the insertion point, based on command key */
+		above = FALSE;
+		switch (key)
+		{
+		  case 'i':
+			break;
+
+		  case 'a':
+			pfetch(markline(m));
+			if (plen > 0)
+			{
+				m++;
+			}
+			break;
+
+		  case 'I':
+			m = m_front(m, 1L);
+			break;
+
+		  case 'A':
+			pfetch(markline(m));
+			m = (m & ~(BLKSIZE - 1)) + plen;
+			break;
+
+		  case 'O':
+			m &= ~(BLKSIZE - 1);
+			add(m, "\n");
+			above = TRUE;
+			break;
+
+		  case 'o':
+			m = (m & ~(BLKSIZE - 1)) + BLKSIZE;
+			add(m, "\n");
+			break;
+		}
+
+		/* insert the same text once or more */
+		for (reps = cnt, wasdot = doingdot; reps > 0; reps--, doingdot = TRUE)
+		{
+			m = input(m, m, WHEN_VIINP, above) + 1;
+		}
+		if (markidx(m) > 0)
+		{
+			m--;
+		}
+
+		doingdot = wasdot;
+	}
+
+#ifndef CRUNCH
+# ifndef NO_EXTENSIONS
+	if (key == 'i' && *o_inputmode && mode == MODE_VI)
+	{
+		msg("Now in command mode!  To return to input mode, hit <i>");
+	}
+# endif
+#endif
+
+	return m;
+}
+
+/* This starts input mode with some text deleted */
+MARK v_change(m, n)
+	MARK	m, n;	/* the range of text to change */
+{
+	int	lnmode;	/* is this a line-mode change? */
+
+	/* swap them if they're in reverse order */
+	if (m > n)
+	{
+		MARK	tmp;
+		tmp = m;
+		m = n;
+		n = tmp;
+	}
+
+	/* for line mode, retain the last newline char */
+	lnmode = (markidx(m) == 0 && markidx(n) == 0 && m != n);
+	if (lnmode)
+	{
+		n -= BLKSIZE;
+		pfetch(markline(n));
+		n = (n & ~(BLKSIZE - 1)) + plen;
+	}
+
+	ChangeText
+	{
+		cut(m, n);
+		m = input(m, n, WHEN_VIINP, FALSE);
+	}
+
+	return m;
+}
+
+/* This function replaces a given number of characters with input */
+MARK v_subst(m, cnt)
+	MARK	m;	/* where substitutions start */
+	long	cnt;	/* number of chars to replace */
+{
+	DEFAULT(1);
+
+	/* make sure we don't try replacing past EOL */
+	pfetch(markline(m));
+	if (markidx(m) + cnt > plen)
+	{
+		cnt = plen - markidx(m);
+	}
+
+	/* Go for it! */
+	ChangeText
+	{
+		cut(m, m + cnt);
+		m = input(m, m + cnt, WHEN_VIINP, FALSE);
+	}
+	return m;
+}
+
+/* This calls the ex "join" command to join some lines together */
+MARK v_join(m, cnt)
+	MARK	m;	/* the first line to be joined */
+	long	cnt;	/* number of other lines to join */
+{
+	MARK	joint;	/* where the lines were joined */
+
+	DEFAULT(1);
+
+	/* figure out where the joint will be */
+	pfetch(markline(m));
+	joint = (m & ~(BLKSIZE - 1)) + plen;
+
+	/* join the lines */
+	cmd_join(m, m + MARK_AT_LINE(cnt), CMD_JOIN, 0, "");
+
+	/* the cursor should be left at the joint */
+	return joint;
+}
+
+
+/* This calls the ex "<" command to shift some lines left */
+MARK v_lshift(m, n)
+	MARK	m, n;	/* range of lines to shift */
+{
+	/* adjust for inclusive endmarks in ex */
+	n -= BLKSIZE;
+
+	cmd_shift(m, n, CMD_SHIFTL, FALSE, (char *)0);
+
+	return m;
+}
+
+/* This calls the ex ">" command to shift some lines right */
+MARK v_rshift(m, n)
+	MARK	m, n;	/* range of lines to shift */
+{
+	/* adjust for inclusive endmarks in ex */
+	n -= BLKSIZE;
+
+	cmd_shift(m, n, CMD_SHIFTR, FALSE, (char *)0);
+
+	return m;
+}
+
+/* This filters some lines through a preset program, to reformat them */
+MARK v_reformat(m, n)
+	MARK	m, n;	/* range of lines to shift */
+{
+	/* adjust for inclusive endmarks in ex */
+	n -= BLKSIZE;
+
+	/* run the filter command */
+	filter(m, n, o_equalprg, TRUE);
+
+	redraw(MARK_UNSET, FALSE);
+	return m;
+}
+
+
+/* This runs some lines through a filter program */
+MARK v_filter(m, n)
+	MARK	m, n;	/* range of lines to shift */
+{
+	char	cmdln[150];	/* a shell command line */
+
+	/* adjust for inclusive endmarks in ex */
+	n -= BLKSIZE;
+
+	if (vgets('!', cmdln, sizeof(cmdln)) > 0)
+	{
+		filter(m, n, cmdln, TRUE);
+	}
+
+	redraw(MARK_UNSET, FALSE);
+	return m;
+}
+
+
+/* This function runs the ex "file" command to show the file's status */
+MARK v_status()
+{
+	cmd_file(cursor, cursor, CMD_FILE, 0, "");
+	return cursor;
+}
+
+
+/* This function runs the ":&" command to repeat the previous :s// */
+MARK v_again(m, n)
+	MARK	m, n;
+{
+	cmd_substitute(m, n - BLKSIZE, CMD_SUBAGAIN, TRUE, "");
+	return cursor;
+}
+
+
+
+/* This function switches to the previous file, if possible */
+MARK v_switch()
+{
+	if (!*prevorig)
+		msg("No previous file");
+	else
+	{	strcpy(tmpblk.c, prevorig);
+		cmd_edit(cursor, cursor, CMD_EDIT, 0, tmpblk.c);
+	}
+	return cursor;
+}
+
+/* This function does a tag search on a keyword */
+/*ARGSUSED*/
+MARK v_tag(keyword, m, cnt)
+	char	*keyword;
+	MARK	m;
+	long	cnt;
+{
+	/* move the cursor to the start of the tag name, where m is */
+	cursor = m;
+
+	/* perform the tag search */
+	cmd_tag(cursor, cursor, CMD_TAG, 0, keyword);
+
+	return cursor;
+}
+
+#ifndef NO_EXTENSIONS
+/* This function looks up a keyword by calling the helpprog program */
+/*ARGSUSED*/
+MARK v_keyword(keyword, m, cnt)
+	char	*keyword;
+	MARK	m;
+	long	cnt;
+{
+	int	waswarn;
+	char	cmdline[130];
+
+	move(LINES - 1, 0);
+	addstr("---------------------------------------------------------\n");
+	clrtoeol();
+	refresh();
+	sprintf(cmdline, "%s %s", o_keywordprg, keyword);
+	waswarn = *o_warn;
+	*o_warn = FALSE;
+	suspend_curses();
+	if (system(cmdline))
+	{
+		addstr("<<< failed >>>\n");
+	}
+	resume_curses(FALSE);
+	mode = MODE_VI;
+	redraw(MARK_UNSET, FALSE);
+	*o_warn = waswarn;
+
+	return m;
+}
+
+
+
+MARK v_increment(keyword, m, cnt)
+	char	*keyword;
+	MARK	m;
+	long	cnt;
+{
+	static	sign;
+	char	newval[12];
+	long	atol();
+
+	DEFAULT(1);
+
+	/* get one more keystroke, unless doingdot */
+	if (!doingdot)
+	{
+		sign = getkey(0);
+	}
+
+	/* adjust the number, based on that second keystroke */
+	switch (sign)
+	{
+	  case '+':
+	  case '#':
+		cnt = atol(keyword) + cnt;
+		break;
+
+	  case '-':
+		cnt = atol(keyword) - cnt;
+		break;
+
+	  case '=':
+		break;
+
+	  default:
+		return MARK_UNSET;
+	}
+	sprintf(newval, "%ld", cnt);
+
+	ChangeText
+	{
+		change(m, m + strlen(keyword), newval);
+	}
+
+	return m;
+}
+#endif
+
+
+/* This function acts like the EX command "xit" */
+/*ARGSUSED*/
+MARK v_xit(m, cnt, key)
+	MARK	m;	/* ignored */
+	long	cnt;	/* ignored */
+	int	key;	/* must be a second 'Z' */
+{
+	/* if second char wasn't 'Z', fail */
+	if (key != 'Z')
+	{
+		return MARK_UNSET;
+	}
+
+	/* move the cursor to the bottom of the screen */
+	move(LINES - 1, 0);
+	clrtoeol();
+
+	/* do the xit command */
+	cmd_xit(m, m, CMD_XIT, FALSE, "");
+
+	/* return the cursor */
+	return m;
+}
+
+
+/* This function undoes changes to a single line, if possible */
+MARK v_undoline(m)
+	MARK	m;	/* where we hope to undo the change */
+{
+	/* make sure we have the right line in the buffer */
+	if (markline(m) != U_line)
+	{
+		return MARK_UNSET;
+	}
+
+	/* fix it */
+	ChangeText
+	{
+		strcat(U_text, "\n");
+		change(MARK_AT_LINE(U_line), MARK_AT_LINE(U_line + 1), U_text);
+	}
+
+	/* nothing in the buffer anymore */
+	U_line = -1L;
+
+	/* return, with the cursor at the front of the line */
+	return m & ~(BLKSIZE - 1);
+}
+
+
+#ifndef NO_ERRLIST
+MARK v_errlist(m)
+	MARK	m;
+{
+	cmd_errlist(m, m, CMD_ERRLIST, FALSE, "");
+	return cursor;
+}
+#endif
+
+
+#ifndef NO_AT
+/*ARGSUSED*/
+MARK v_at(m, cnt, key)
+	MARK	m;
+	long	cnt;
+	int	key;
+{
+	int	size;
+
+	size = cb2str(key, tmpblk.c, BLKSIZE);
+	if (size <= 0 || size == BLKSIZE)
+	{
+		return MARK_UNSET;
+	}
+
+	execmap(0, tmpblk.c, FALSE);
+	return cursor;
+}
+#endif
+
+
+#ifdef SIGTSTP
+MARK v_suspend()
+{
+	cmd_suspend(MARK_UNSET, MARK_UNSET, CMD_SUSPEND, FALSE, "");
+	return MARK_UNSET;
+}
+#endif
+
+
+#ifndef NO_VISIBLE
+/*ARGSUSED*/
+MARK v_start(m, cnt, cmd)
+	MARK	m;	/* starting point for a v or V command */
+	long	cnt;	/* ignored */
+	int	cmd;	/* either 'v' or 'V' */
+{
+	if (V_from)
+	{
+		V_from = MARK_UNSET;
+	}
+	else
+	{
+		V_from = m;
+		V_linemd = isupper(cmd);
+	}
+	return m;
+}
+#endif
+
+#ifndef NO_POPUP
+# define MENU_HEIGHT 11
+# define MENU_WIDTH  23
+MARK v_popup(m, n)
+	MARK		m, n;	/* the range of text to change */
+{
+	int		i;
+	int		y, x;	/* position where the window will pop up at */
+	int		key;	/* keystroke from the user */
+	int		sel;	/* index of the selected operation */
+	static int	dfltsel;/* default value of sel */
+	static char	*labels[11] =
+	{
+		"ESC cancel!         ",
+		" d  delete (cut)    ",
+		" y  yank (copy)     ",
+		" p  paste after     ",
+		" P  paste before    ",
+		" >  more indented   ",
+		" <  less indented   ",
+		" =  reformat        ",
+		" !  external filter ",
+		" ZZ save & exit     ",
+		" u  undo previous   "
+	};
+
+	/* try to position the menu near the cursor */
+	x = physcol - (MENU_WIDTH / 2);
+	if (x < 0)
+		x = 0;
+	else if (x + MENU_WIDTH + 2 > COLS)
+		x = COLS - MENU_WIDTH - 2;
+	if (markline(cursor) < topline || markline(cursor) > botline)
+		y = 0;
+	else if (markline(cursor) + 1L + MENU_HEIGHT > botline)
+		y = (int)(markline(cursor) - topline) - MENU_HEIGHT;
+	else
+		y = (int)(markline(cursor) - topline) + 1L;
+
+	/* draw the menu */
+	for (sel = 0; sel < MENU_HEIGHT; sel++)
+	{
+		move(y + sel, x);
+		do_POPUP();
+		if (sel == dfltsel)
+			qaddstr("-->");
+		else
+			qaddstr("   ");
+		qaddstr(labels[sel]);
+		do_SE();
+	}
+
+	/* get a selection */
+	move(y + dfltsel, x + 4);
+	for (sel = dfltsel; (key = getkey(WHEN_POPUP)) != '\\' && key != '\r'; )
+	{
+		/* erase the selection arrow */
+		move(y + sel, x);
+		do_POPUP();
+		qaddstr("   ");
+		qaddstr(labels[sel]);
+		do_SE();
+
+		/* process the user's keystroke */
+		if (key == 'j' && sel < MENU_HEIGHT - 1)
+		{
+			sel++;
+		}
+		else if (key == 'k' && sel > 0)
+		{
+			sel--;
+		}
+		else if (key == '\033')
+		{
+			sel = 0;
+			break;
+		}
+		else
+		{
+			for (i = 1; i < MENU_HEIGHT && labels[i][1] != key; i++)
+			{
+			}
+			if (i < MENU_HEIGHT)
+			{
+				sel = i;
+				break;
+			}
+		}
+
+		/* redraw the arrow, possibly in a new place */
+		move(y + sel, x);
+		do_POPUP();
+		qaddstr("-->");
+		qaddstr(labels[sel]);
+		do_SE();
+		move(y + sel, x + 4);
+	}
+
+	/* in most cases, the default selection is "paste after" */
+	dfltsel = 3;
+
+	/* perform the appropriate action */
+	switch (sel)
+	{
+	  case 0:
+		m = cursor;
+		dfltsel = 0;
+		break;
+
+	  case 1: /* delete (cut) */
+		m = v_delete(m, n);
+		break;
+
+	  case 2: /* yank (copy) */
+		m = v_yank(m, n);
+		break;
+
+	  case 3: /* paste after */
+		m = v_paste(n, 1L, 'P');
+		break;
+
+	  case 4: /* paste before */
+		m = v_paste(m, 1L, 'P');
+		dfltsel = 4;
+		break;
+
+	  case 5: /* more indented */
+		m = v_rshift(m, n);
+		dfltsel = 5;
+		break;
+
+	  case 6: /* less indented */
+		m = v_lshift(m, n);
+		dfltsel = 6;
+		break;
+
+	  case 7: /* reformat */
+		m = v_reformat(m, n);
+		dfltsel = 7;
+		break;
+
+	  case 8: /* external filter */
+		m = v_filter(m, n);
+		dfltsel = 0;
+		break;
+
+	  case 9: /* save & exit */
+		/* get confirmation first */
+		do
+		{
+			key = getkey(0);
+		} while (key != '\\' && key != 'Z' && key != '\r'    /* good */
+		      && key != '\033');			     /* bad  */
+		if (key != '\033')
+		{
+			m = v_xit(m, 0L, 'Z');
+		}
+		break;
+
+	  case 10: /* undo previous */
+		m = v_undo(m);
+		dfltsel = 9;
+		break;
+	}
+
+	/* arrange for the menu to be erased (except that "chg from kbd"
+	 * already erased it, and "save & exit" doesn't care)
+	 */
+	if (sel != 5 && sel != 9)
+		redraw(MARK_UNSET, FALSE);
+
+	return m;
+}
+#endif /* undef NO_POPUP */
Index: /trunk/minix/commands/elvis/vi.c
===================================================================
--- /trunk/minix/commands/elvis/vi.c	(revision 9)
+++ /trunk/minix/commands/elvis/vi.c	(revision 9)
@@ -0,0 +1,815 @@
+/* vi.c */
+
+/* Author:
+ *	Steve Kirkendall
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+
+#include "config.h"
+#include "ctype.h"
+#include "vi.h"
+
+
+
+/* This array describes what each key does */
+#define NO_FUNC		(MARK (*)())0
+
+#define NO_ARGS		0
+#define CURSOR		1
+#define CURSOR_CNT_KEY	2
+#define CURSOR_MOVED	3
+#define CURSOR_EOL	4
+#define ZERO		5
+#define DIGIT		6
+#define CURSOR_TEXT	7
+#define KEYWORD		8
+#define ARGSMASK	0x0f
+#define	C_C_K_REP1	(CURSOR_CNT_KEY | 0x10)
+#define C_C_K_CUT	(CURSOR_CNT_KEY | 0x20)
+#define C_C_K_MARK	(CURSOR_CNT_KEY | 0x30)
+#define C_C_K_CHAR	(CURSOR_CNT_KEY | 0x40)
+#ifndef NO_SHOWMODE
+static int keymodes[] = {0, WHEN_REP1, WHEN_CUT, WHEN_MARK, WHEN_CHAR};
+# define KEYMODE(args) (keymodes[(args) >> 4])
+#else
+# define KEYMODE(args) 0
+#endif
+
+static struct keystru
+{
+	MARK	(*func)();	/* the function to run */
+	uchar	args;		/* description of the args needed */
+#ifndef NO_VISIBLE
+	short	flags;
+#else
+	uchar	flags;		/* other stuff */
+#endif
+}
+	vikeys[] =
+{
+/* NUL not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#ifndef NO_EXTENSIONS
+/* ^A  find cursor word */	{m_wsrch,	KEYWORD,	MVMT|NREL|VIZ},
+#else
+/* ^A  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#endif
+/* ^B  page backward	*/	{m_scroll,	CURSOR,		FRNT|VIZ},
+/* ^C  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/* ^D  scroll dn 1/2page*/	{m_scroll,	CURSOR,		NCOL|VIZ},
+/* ^E  scroll up	*/	{m_scroll,	CURSOR,		NCOL|VIZ},
+/* ^F  page forward	*/	{m_scroll,	CURSOR,		FRNT|VIZ},
+/* ^G  show file status	*/	{v_status,	NO_ARGS, 	NO_FLAGS},
+/* ^H  move left, like h*/	{m_left,	CURSOR,		MVMT|VIZ},
+/* ^I  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/* ^J  move down	*/	{m_updnto,	CURSOR,		MVMT|LNMD|VIZ|INCL},
+/* ^K  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/* ^L  redraw screen	*/	{v_redraw,	NO_ARGS,	NO_FLAGS|VIZ},
+/* ^M  mv front next ln */	{m_updnto,	CURSOR,		MVMT|FRNT|LNMD|VIZ|INCL},
+/* ^N  move down	*/	{m_updnto,	CURSOR,		MVMT|LNMD|VIZ|INCL|NCOL},
+/* ^O  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/* ^P  move up		*/	{m_updnto,	CURSOR,		MVMT|LNMD|VIZ|INCL|NCOL},
+/* ^Q  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/* ^R  redraw screen	*/	{v_redraw,	NO_ARGS,	NO_FLAGS|VIZ},
+/* ^S  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/* ^T  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/* ^U  scroll up 1/2page*/	{m_scroll,	CURSOR,		NCOL|VIZ},
+/* ^V  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/* ^W  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/* ^X  move to phys col	*/	{m_tocol,	CURSOR,		MVMT|NREL|VIZ},
+/* ^Y  scroll down	*/	{m_scroll,	CURSOR,		NCOL|VIZ},
+#ifdef SIGTSTP
+/* ^Z  suspend elvis	*/	{v_suspend,	NO_ARGS,	NO_FLAGS},
+#else
+/* ^Z  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#endif
+/* ESC not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/* ^\  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/* ^]  keyword is tag	*/	{v_tag,		KEYWORD,	NO_FLAGS},
+/* ^^  previous file	*/	{v_switch,	CURSOR,		NO_FLAGS},
+/* ^_  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/* SPC move right,like l*/	{m_right,	CURSOR,		MVMT|INCL|VIZ},
+/*  !  run thru filter	*/	{v_filter,	CURSOR_MOVED,	FRNT|LNMD|INCL|VIZ},
+/*  "  select cut buffer*/	{v_selcut,	C_C_K_CUT,	PTMV|VIZ},
+#ifndef NO_EXTENSIONS
+/*  #  increment number	*/	{v_increment,	KEYWORD,	SDOT},
+#else
+/*  #  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#endif
+/*  $  move to rear	*/	{m_rear,	CURSOR,		MVMT|INCL|VIZ},
+/*  %  move to match	*/	{m_match,	CURSOR,		MVMT|INCL|VIZ},
+/*  &  repeat subst	*/	{v_again,	CURSOR_MOVED,	SDOT|NCOL|LNMD|INCL},
+/*  '  move to a mark	*/	{m_tomark,	C_C_K_MARK,	MVMT|FRNT|NREL|LNMD|INCL|VIZ},
+#ifndef NO_SENTENCE
+/*  (  mv back sentence	*/	{m_sentence,	CURSOR,		MVMT|VIZ},
+/*  )  mv fwd sentence	*/	{m_sentence,	CURSOR,		MVMT|VIZ},
+#else
+/*  (  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/*  )  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#endif
+#ifndef NO_ERRLIST
+/*  *  errlist		*/	{v_errlist,	CURSOR,		FRNT|NREL},
+#else
+/*  *  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#endif
+/*  +  mv front next ln */	{m_updnto,	CURSOR,		MVMT|FRNT|LNMD|VIZ|INCL},
+#ifndef NO_CHARSEARCH
+/*  ,  reverse [fFtT] cmd*/	{m__ch,		CURSOR,		MVMT|INCL|VIZ},
+#else
+/*  ,  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#endif
+/*  -  mv front prev ln	*/	{m_updnto,	CURSOR,		MVMT|FRNT|LNMD|VIZ|INCL},
+/*  .  special...	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/*  /  forward search	*/	{m_fsrch,	CURSOR_TEXT,	MVMT|NREL|VIZ},
+/*  0  part of count?	*/	{NO_FUNC,	ZERO,		MVMT|PTMV|VIZ},
+/*  1  part of count	*/	{NO_FUNC,	DIGIT,		PTMV|VIZ},
+/*  2  part of count	*/	{NO_FUNC,	DIGIT,		PTMV|VIZ},
+/*  3  part of count	*/	{NO_FUNC,	DIGIT,		PTMV|VIZ},
+/*  4  part of count	*/	{NO_FUNC,	DIGIT,		PTMV|VIZ},
+/*  5  part of count	*/	{NO_FUNC,	DIGIT,		PTMV|VIZ},
+/*  6  part of count	*/	{NO_FUNC,	DIGIT,		PTMV|VIZ},
+/*  7  part of count	*/	{NO_FUNC,	DIGIT,		PTMV|VIZ},
+/*  8  part of count	*/	{NO_FUNC,	DIGIT,		PTMV|VIZ},
+/*  9  part of count	*/	{NO_FUNC,	DIGIT,		PTMV|VIZ},
+/*  :  run single EX cmd*/	{v_1ex,		CURSOR_TEXT,	NO_FLAGS},
+#ifndef NO_CHARSEARCH
+/*  ;  repeat [fFtT] cmd*/	{m__ch,		CURSOR,		MVMT|INCL|VIZ},
+#else
+/*  ;  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS|VIZ},
+#endif
+/*  <  shift text left	*/	{v_lshift,	CURSOR_MOVED,	SDOT|FRNT|LNMD|INCL|VIZ},
+/*  =  preset filter	*/	{v_reformat,	CURSOR_MOVED,	SDOT|FRNT|LNMD|INCL|VIZ},
+/*  >  shift text right	*/	{v_rshift,	CURSOR_MOVED,	SDOT|FRNT|LNMD|INCL|VIZ},
+/*  ?  backward search	*/	{m_bsrch,	CURSOR_TEXT,	MVMT|NREL|VIZ},
+#ifndef NO_AT
+/*  @  execute a cutbuf */	{v_at,		C_C_K_CUT,	NO_FLAGS},
+#else
+/*  @  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#endif
+/*  A  append at EOL	*/	{v_insert,	CURSOR,		SDOT},
+/*  B  move back Word	*/	{m_bword,	CURSOR,		MVMT|VIZ},
+/*  C  change to EOL	*/	{v_change,	CURSOR_EOL,	SDOT},
+/*  D  delete to EOL	*/	{v_delete,	CURSOR_EOL,	SDOT},
+/*  E  move end of Word	*/	{m_eword,	CURSOR,		MVMT|INCL|VIZ},
+#ifndef NO_CHARSEARCH
+/*  F  move bk to char	*/	{m_Fch,		C_C_K_CHAR,	MVMT|INCL|VIZ},
+#else
+/*  F  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#endif
+/*  G  move to line #	*/	{m_updnto,	CURSOR,		MVMT|NREL|LNMD|FRNT|INCL|VIZ},
+/*  H  move to row	*/	{m_row,		CURSOR,		MVMT|LNMD|FRNT|VIZ|INCL},
+/*  I  insert at front	*/	{v_insert,	CURSOR,		SDOT},
+/*  J  join lines	*/	{v_join,	CURSOR,		SDOT},
+#ifndef NO_EXTENSIONS
+/*  K  look up keyword	*/	{v_keyword,	KEYWORD,	NO_FLAGS},
+#else
+/*  K  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#endif
+/*  L  move to last row	*/	{m_row,		CURSOR,		MVMT|LNMD|FRNT|VIZ|INCL},
+/*  M  move to mid row	*/	{m_row,		CURSOR,		MVMT|LNMD|FRNT|VIZ|INCL},
+/*  N  reverse prev srch*/	{m_Nsrch,	CURSOR,		MVMT|NREL|VIZ},
+/*  O  insert above line*/	{v_insert,	CURSOR,		SDOT},
+/*  P  paste before	*/	{v_paste,	CURSOR,		SDOT},
+/*  Q  quit to EX mode	*/	{v_quit,	NO_ARGS,	NO_FLAGS},
+/*  R  overtype		*/	{v_overtype,	CURSOR,		SDOT},
+/*  S  change line	*/	{v_change,	CURSOR_MOVED,	SDOT},
+#ifndef NO_CHARSEARCH
+/*  T  move bk to char	*/	{m_Tch,		C_C_K_CHAR,	MVMT|INCL|VIZ},
+#else
+/*  T  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#endif
+/*  U  undo whole line	*/	{v_undoline,	CURSOR,		FRNT},
+#ifndef NO_VISIBLE
+/*  V  start visible	*/	{v_start,	CURSOR,		INCL|LNMD|VIZ},
+#else
+/*  V  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#endif
+/*  W  move forward Word*/	{m_fword,	CURSOR,		MVMT|INCL|VIZ},
+/*  X  delete to left	*/	{v_xchar,	CURSOR,		SDOT},
+/*  Y  yank text	*/	{v_yank,	CURSOR_MOVED,	NCOL},
+/*  Z  save file & exit	*/	{v_xit,		CURSOR_CNT_KEY,	NO_FLAGS},
+/*  [  move back section*/	{m_paragraph,	CURSOR,		MVMT|LNMD|NREL|VIZ},
+#ifndef NO_POPUP
+/*  \  pop-up menu	*/	{v_popup,	CURSOR_MOVED,	VIZ},
+#else
+/*  \  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#endif
+/*  ]  move fwd section */	{m_paragraph,	CURSOR,		MVMT|LNMD|NREL|VIZ},
+/*  ^  move to front	*/	{m_front,	CURSOR,		MVMT|VIZ},
+/*  _  current line	*/	{m_updnto,	CURSOR,		MVMT|LNMD|FRNT|INCL},
+/*  `  move to mark	*/	{m_tomark,	C_C_K_MARK,	MVMT|NREL|VIZ},
+/*  a  append at cursor	*/	{v_insert,	CURSOR,		SDOT},
+/*  b  move back word	*/	{m_bword,	CURSOR,		MVMT|VIZ},
+/*  c  change text	*/	{v_change,	CURSOR_MOVED,	SDOT|VIZ},
+/*  d  delete op	*/	{v_delete,	CURSOR_MOVED,	SDOT|VIZ},
+/*  e  move end word	*/	{m_eword,	CURSOR,		MVMT|INCL|VIZ},
+#ifndef NO_CHARSEARCH
+/*  f  move fwd for char*/	{m_fch,		C_C_K_CHAR,	MVMT|INCL|VIZ},
+#else
+/*  f  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#endif
+/*  g  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/*  h  move left	*/	{m_left,	CURSOR,		MVMT|VIZ},
+/*  i  insert at cursor	*/	{v_insert,	CURSOR,		SDOT},
+/*  j  move down	*/	{m_updnto,	CURSOR,		MVMT|NCOL|LNMD|VIZ|INCL},
+/*  k  move up		*/	{m_updnto,	CURSOR,		MVMT|NCOL|LNMD|VIZ|INCL},
+/*  l  move right	*/	{m_right,	CURSOR,		MVMT|INCL|VIZ},
+/*  m  define a mark	*/	{v_mark,	C_C_K_MARK,	NO_FLAGS},
+/*  n  repeat prev srch	*/	{m_nsrch,	CURSOR, 	MVMT|NREL|VIZ},
+/*  o  insert below line*/	{v_insert,	CURSOR,		SDOT},
+/*  p  paste after	*/	{v_paste,	CURSOR,		SDOT},
+/*  q  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+/*  r  replace chars	*/	{v_replace,	C_C_K_REP1,	SDOT},
+/*  s  subst N chars	*/	{v_subst,	CURSOR,		SDOT},
+#ifndef NO_CHARSEARCH
+/*  t  move fwd to char	*/	{m_tch,		C_C_K_CHAR,	MVMT|INCL|VIZ},
+#else
+/*  t  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#endif
+/*  u  undo		*/	{v_undo,	CURSOR,		NO_FLAGS},
+#ifndef NO_VISIBLE
+/*  v  start visible	*/	{v_start,	CURSOR,		INCL|VIZ},
+#else
+/*  v  not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS},
+#endif
+/*  w  move fwd word	*/	{m_fword,	CURSOR,		MVMT|INCL|VIZ},
+/*  x  delete character	*/	{v_xchar,	CURSOR,		SDOT},
+/*  y  yank text	*/	{v_yank,	CURSOR_MOVED,	NCOL|VIZ},
+/*  z  adjust scrn row	*/	{m_z, 		CURSOR_CNT_KEY,	NCOL|VIZ},
+/*  {  back paragraph	*/	{m_paragraph,	CURSOR,		MVMT|LNMD|VIZ},
+/*  |  move to column	*/	{m_tocol,	CURSOR,		MVMT|NREL|VIZ},
+/*  }  fwd paragraph	*/	{m_paragraph,	CURSOR,		MVMT|LNMD|VIZ},
+/*  ~  upper/lowercase	*/	{v_ulcase,	CURSOR,		SDOT},
+/* DEL not defined	*/	{NO_FUNC,	NO_ARGS,	NO_FLAGS}
+};
+
+
+
+void vi()
+{
+	REG int			key;	/* keystroke from user */
+	long			count;	/* numeric argument to some functions */
+	REG struct keystru	*keyptr;/* pointer to vikeys[] element */
+	MARK			tcurs;	/* temporary cursor */
+	int			prevkey;/* previous key, if d/c/y/</>/! */
+	MARK			range;	/* start of range for d/c/y/</>/! */
+	char			text[132];
+	int			dotkey;	/* last "key" of a change */
+	int			dotpkey;/* last "prevkey" of a change */
+	int			dotkey2;/* last extra "getkey()" of a change */
+	int			dotcnt;	/* last "count" of a change */
+	int			firstkey;
+	REG int			i;
+
+	/* tell the redraw() function to start from scratch */
+	redraw(MARK_UNSET, FALSE);
+
+#ifdef lint
+	/* lint says that "range" might be used before it is set.  This
+	 * can't really happen due to the way "range" and "prevkey" are used,
+	 * but lint doesn't know that.  This line is here ONLY to keep lint
+	 * happy.
+	 */
+	range = 0L;
+#endif
+
+	/* safeguard against '.' with no previous command */
+	dotkey = dotpkey = dotkey2 = dotcnt = 0;
+
+	/* go immediately into insert mode, if ":set inputmode" */
+	firstkey = 0;
+#ifndef NO_EXTENSIONS
+	if (*o_inputmode)
+	{
+		firstkey = 'i';
+	}
+#endif
+
+	/* Repeatedly handle VI commands */
+	for (count = 0, prevkey = '\0'; mode == MODE_VI; )
+	{
+		/* if we've moved off the undoable line, then we can't undo it at all */
+		if (markline(cursor) != U_line)
+		{
+			U_line = 0L;
+		}
+
+		/* report any changes from the previous command */
+		if (rptlines >= *o_report)
+		{
+			redraw(cursor, FALSE);
+			msg("%ld line%s %s", rptlines, (rptlines==1?"":"s"), rptlabel);
+		}
+		rptlines = 0L;
+
+		/* get the next command key.  It must be ASCII */
+		if (firstkey)
+		{
+			key = firstkey;
+			firstkey = 0;
+		}
+		else
+		{
+			do
+			{
+				key = getkey(WHEN_VICMD);
+			} while (key < 0 || key > 127);
+		}
+
+		/* Convert a doubled-up operator such as "dd" into "d_" */
+		if (prevkey && key == prevkey)
+		{
+			key = '_';
+		}
+
+		/* look up the structure describing this command */
+		keyptr = &vikeys[key];
+
+		/* '&' and uppercase operators always act like doubled */
+		if (!prevkey && keyptr->args == CURSOR_MOVED
+			&& (key == '&' || isupper(key)))
+		{
+			range = cursor;
+			prevkey = key;
+			key = '_';
+			keyptr = &vikeys[key];
+		}
+
+#ifndef NO_VISIBLE
+		/* if we're in the middle of a v/V command, reject commands
+		 * that aren't operators or movement commands
+		 */
+		if (V_from && !(keyptr->flags & VIZ))
+		{
+			beep();
+			prevkey = 0;
+			count = 0;
+			continue;
+		}
+#endif
+
+		/* if we're in the middle of a d/c/y/</>/! command, reject
+		 * anything but movement.
+		 */
+		if (prevkey && !(keyptr->flags & (MVMT|PTMV)))
+		{
+			beep();
+			prevkey = 0;
+			count = 0;
+			continue;
+		}
+
+		/* set the "dot" variables, if we're supposed to */
+		if (((keyptr->flags & SDOT)
+			|| (prevkey && vikeys[prevkey].flags & SDOT))
+#ifndef NO_VISIBLE
+		    && !V_from
+#endif
+		)
+		{
+			dotkey = key;
+			dotpkey = prevkey;
+			dotkey2 = '\0';
+			dotcnt = count;
+
+			/* remember the line before any changes are made */
+			if (U_line != markline(cursor))
+			{
+				U_line = markline(cursor);
+				strcpy(U_text, fetchline(U_line));
+			}
+		}
+
+		/* if this is "." then set other vars from the "dot" vars */
+		if (key == '.')
+		{
+			key = dotkey;
+			keyptr = &vikeys[key];
+			prevkey = dotpkey;
+			if (prevkey)
+			{
+				range = cursor;
+			}
+			if (count == 0)
+			{
+				count = dotcnt;
+			}
+			doingdot = TRUE;
+
+			/* remember the line before any changes are made */
+			if (U_line != markline(cursor))
+			{
+				U_line = markline(cursor);
+				strcpy(U_text, fetchline(U_line));
+			}
+		}
+		else
+		{
+			doingdot = FALSE;
+		}
+
+		/* process the key as a command */
+		tcurs = cursor;
+		force_flags = NO_FLAGS;
+		switch (keyptr->args & ARGSMASK)
+		{
+		  case ZERO:
+			if (count == 0)
+			{
+				tcurs = cursor & ~(BLKSIZE - 1);
+				break;
+			}
+			/* else fall through & treat like other digits... */
+
+		  case DIGIT:
+			count = count * 10 + key - '0';
+			break;
+
+		  case KEYWORD:
+			/* if not on a keyword, fail */
+			pfetch(markline(cursor));
+			key = markidx(cursor);
+			if (!isalnum(ptext[key]))
+			{
+				tcurs = MARK_UNSET;
+				break;
+			}
+
+			/* find the start of the keyword */
+			while (key > 0 && isalnum(ptext[key - 1]))
+			{
+				key--;
+			}
+			tcurs = (cursor & ~(BLKSIZE - 1)) + key;
+
+			/* copy it into a buffer, and NUL-terminate it */
+			i = 0;
+			do
+			{
+				text[i++] = ptext[key++];
+			} while (isalnum(ptext[key]));
+			text[i] = '\0';
+
+			/* call the function */
+			tcurs = (*keyptr->func)(text, tcurs, count);
+			count = 0L;
+			break;
+
+		  case NO_ARGS:
+			if (keyptr->func)
+			{
+				(*keyptr->func)();
+			}
+			else
+			{
+				beep();
+			}
+			count = 0L;
+			break;
+	
+		  case CURSOR:
+			tcurs = (*keyptr->func)(cursor, count, key, prevkey);
+			count = 0L;
+			break;
+
+		  case CURSOR_CNT_KEY:
+			if (doingdot)
+			{
+				tcurs = (*keyptr->func)(cursor, count, dotkey2);
+			}
+			else
+			{
+				/* get a key */
+				i = getkey(KEYMODE(keyptr->args));
+				if (i == '\033') /* ESC */
+				{
+					count = 0;
+					tcurs = MARK_UNSET;
+					break; /* exit from "case CURSOR_CNT_KEY" */
+				}
+				else if (i == ctrl('V'))
+				{
+					i = getkey(0);
+				}
+
+				/* if part of an SDOT command, remember it */
+				 if (keyptr->flags & SDOT
+				 || (prevkey && vikeys[prevkey].flags & SDOT))
+				{
+					dotkey2 = i;
+				}
+
+				/* do it */
+				tcurs = (*keyptr->func)(cursor, count, i);
+			}
+			count = 0L;
+			break;
+	
+		  case CURSOR_MOVED:
+#ifndef NO_VISIBLE
+			if (V_from)
+			{
+				range = cursor;
+				tcurs = V_from;
+				count = 0L;
+				prevkey = key;
+				key = (V_linemd ? 'V' : 'v');
+				keyptr = &vikeys[key];
+			}
+			else
+#endif
+			{
+				prevkey = key;
+				range = cursor;
+				force_flags = LNMD|INCL;
+			}
+			break;
+
+		  case CURSOR_EOL:
+			prevkey = key;
+			/* a zero-length line needs special treatment */
+			pfetch(markline(cursor));
+			if (plen == 0)
+			{
+				/* act on a zero-length section of text */
+				range = tcurs = cursor;
+				key = '0';
+			}
+			else
+			{
+				/* act like CURSOR_MOVED with '$' movement */
+				range = cursor;
+				tcurs = m_rear(cursor, 1L);
+				key = '$';
+			}
+			count = 0L;
+			keyptr = &vikeys[key];
+			break;
+
+		  case CURSOR_TEXT:
+		  	do
+		  	{	
+				text[0] = key;
+				if (vgets(key, text + 1, sizeof text - 1) >= 0)
+				{
+					/* reassure user that <CR> was hit */
+					qaddch('\r');
+					refresh();
+
+					/* call the function with the text */
+					tcurs = (*keyptr->func)(cursor, text);
+				}
+				else
+				{
+					if (exwrote || mode == MODE_COLON)
+					{
+						redraw(MARK_UNSET, FALSE);
+					}
+					mode = MODE_VI;
+				}
+			} while (mode == MODE_COLON);
+			count = 0L;
+			break;
+		}
+
+		/* if that command took us out of vi mode, then exit the loop
+		 * NOW, without tweaking the cursor or anything.  This is very
+		 * important when mode == MODE_QUIT.
+		 */
+		if (mode != MODE_VI)
+		{
+			break;
+		}
+
+		/* now move the cursor, as appropriate */
+		if (keyptr->args == CURSOR_MOVED)
+		{
+			/* the < and > keys have FRNT,
+			 * but it shouldn't be applied yet
+			 */
+			tcurs = adjmove(cursor, tcurs, 0);
+		}
+		else
+		{
+			tcurs = adjmove(cursor, tcurs, (int)keyptr->flags | force_flags);
+		}
+
+		/* was that the end of a d/c/y/</>/! command? */
+		if (prevkey && ((keyptr->flags & MVMT)
+#ifndef NO_VISIBLE
+					       || V_from
+#endif
+				) && count == 0L)
+		{
+#ifndef NO_VISIBLE
+			/* turn off the hilight */
+			V_from = 0L;
+#endif
+
+			/* if the movement command failed, cancel operation */
+			if (tcurs == MARK_UNSET)
+			{
+				prevkey = 0;
+				count = 0;
+				continue;
+			}
+
+			/* make sure range=front and tcurs=rear.  Either way,
+			 * leave cursor=range since that's where we started.
+			 */
+			cursor = range;
+			if (tcurs < range)
+			{
+				range = tcurs;
+				tcurs = cursor;
+			}
+
+			/* The 'w' and 'W' destinations should never take us
+			 * to the front of a line.  Instead, they should take
+			 * us only to the end of the preceding line.
+			 */
+			if ((keyptr->flags & (MVMT|NREL|LNMD|FRNT|INCL)) == MVMT
+			  && markline(range) < markline(tcurs)
+			  && (markline(tcurs) > nlines || tcurs == m_front(tcurs, 0L)))
+			{
+				tcurs = (tcurs & ~(BLKSIZE - 1)) - BLKSIZE;
+				pfetch(markline(tcurs));
+				tcurs += plen;
+			}
+
+			/* adjust for line mode & inclusion of last char/line */
+			i = (keyptr->flags | vikeys[prevkey].flags);
+			switch ((i | force_flags) & (INCL|LNMD))
+			{
+			  case INCL:
+				tcurs++;
+				break;
+
+			  case INCL|LNMD:
+				tcurs += BLKSIZE;
+				/* fall through... */
+
+			  case LNMD:
+				range &= ~(BLKSIZE - 1);
+				tcurs &= ~(BLKSIZE - 1);
+				break;
+			}
+
+			/* run the function */
+			tcurs = (*vikeys[prevkey].func)(range, tcurs);
+			if (mode == MODE_VI)
+			{
+				(void)adjmove(cursor, cursor, 0);
+				cursor = adjmove(cursor, tcurs, (int)vikeys[prevkey].flags);
+			}
+
+			/* cleanup */
+			prevkey = 0;
+		}
+		else if (!prevkey)
+		{
+			if (tcurs != MARK_UNSET)
+				cursor = tcurs;
+		}
+	}
+}
+
+/* This function adjusts the MARK value that they return; here we make sure
+ * it isn't past the end of the line, and that the column hasn't been
+ * *accidentally* changed.
+ */
+MARK adjmove(old, new, flags)
+	MARK		old;	/* the cursor position before the command */
+	REG MARK	new;	/* the cursor position after the command */
+	int		flags;	/* various flags regarding cursor mvmt */
+{
+	static int	colno;	/* the column number that we want */
+	REG char	*text;	/* used to scan through the line's text */
+	REG int		i;
+
+#ifdef DEBUG
+	watch();
+#endif
+
+	/* if the command failed, bag it! */
+	if (new == MARK_UNSET)
+	{
+		beep();
+		return old;
+	}
+
+	/* if this is a non-relative movement, set the '' mark */
+	if (flags & NREL)
+	{
+		mark[26] = old;
+	}
+
+	/* make sure it isn't past the end of the file */
+	if (markline(new) < 1)
+	{
+		new = MARK_FIRST;
+	}
+	else if (markline(new) > nlines)
+	{
+		new = MARK_LAST;
+	}
+
+	/* fetch the new line */
+	pfetch(markline(new));
+
+	/* move to the front, if we're supposed to */
+	if (flags & FRNT)
+	{
+		new = m_front(new, 1L);
+	}
+
+	/* change the column#, or change the mark to suit the column# */
+	if (!(flags & NCOL))
+	{
+		/* change the column# */
+		i = markidx(new);
+		if (i == BLKSIZE - 1)
+		{
+			new &= ~(BLKSIZE - 1);
+			if (plen > 0)
+			{
+				new += plen - 1;
+			}
+			colno = BLKSIZE * 8; /* one heck of a big colno */
+		}
+		else if (plen > 0)
+		{
+			if (i >= plen)
+			{
+				new = (new & ~(BLKSIZE - 1)) + plen - 1;
+			}
+			colno = idx2col(new, ptext, FALSE);
+		}
+		else
+		{
+			new &= ~(BLKSIZE - 1);
+			colno = 0;
+		}
+	}
+	else
+	{
+		/* adjust the mark to get as close as possible to column# */
+		for (i = 0, text = ptext; i <= colno && *text; text++)
+		{
+			if (*text == '\t' && !*o_list)
+			{
+				i += *o_tabstop - (i % *o_tabstop);
+			}
+			else if (UCHAR(*text) < ' ' || *text == 127)
+			{
+				i += 2;
+			}
+#ifndef NO_CHARATTR
+			else if (*o_charattr && text[0] == '\\' && text[1] == 'f' && text[2])
+			{
+				text += 2; /* plus one more in "for()" stmt */
+			}
+#endif
+			else
+			{
+				i++;
+			}
+		}
+		if (text > ptext)
+		{
+			text--;
+		}
+		new = (new & ~(BLKSIZE - 1)) + (int)(text - ptext);
+	}
+
+	return new;
+}
+
+
+#ifdef DEBUG
+watch()
+{
+	static wasset;
+
+	if (*origname)
+	{
+		wasset = TRUE;
+	}
+	else if (wasset)
+	{
+		mode = MODE_EX;
+		msg("origname was clobbered");
+		endwin();
+		abort();
+	}
+
+	if (wasset && nlines == 0)
+	{
+		mode = MODE_EX;
+		msg("nlines=0");
+		endwin();
+		abort();
+	}
+}
+#endif
Index: /trunk/minix/commands/elvis/vi.h
===================================================================
--- /trunk/minix/commands/elvis/vi.h	(revision 9)
+++ /trunk/minix/commands/elvis/vi.h	(revision 9)
@@ -0,0 +1,596 @@
+/* vi.h */
+
+/* Author:
+ *	Steve Kirkendall
+ *	14407 SW Teal Blvd. #C
+ *	Beaverton, OR 97005
+ *	kirkenda@cs.pdx.edu
+ */
+
+#define VERSION "ELVIS 1.5, by Steve Kirkendall (23 March 1992)"
+#define COPYING	"This version of ELVIS is freely redistributable."
+
+#include <errno.h>
+extern int errno;
+#if TOS && !defined(__GNUC__)
+#define ENOENT (-AEFILNF)
+#endif
+
+#if TOS || VMS
+# include <types.h>
+# define O_RDONLY	0
+# define O_WRONLY	1
+# define O_RDWR		2
+# ifdef __GNUC__
+#  define S_IJDIR	S_IFDIR
+# endif
+#else
+# if OSK
+#  include <modes.h>
+#  define O_RDONLY	S_IREAD
+#  define O_WRONLY	S_IWRITE
+#  define O_RDWR	(S_IREAD | S_IWRITE)
+#  define ENOENT	E_PNNF
+#  define sprintf	Sprintf
+# else
+#  include <sys/types.h>
+#  if COHERENT
+#   include <sys/fcntl.h>
+#  else
+#   include <fcntl.h>
+#  endif
+# endif
+#endif
+
+#ifndef O_BINARY
+# define O_BINARY	0
+#endif
+
+#include "curses.h"
+
+#include <signal.h>
+
+/*------------------------------------------------------------------------*/
+/* Miscellaneous constants.						  */
+
+#define INFINITY	2000000001L	/* a very large integer */
+#define LONGKEY		10		/* longest possible raw :map key */
+#ifndef MAXRCLEN
+# define MAXRCLEN	1000		/* longest possible :@ command */
+#endif
+
+/*------------------------------------------------------------------------*/
+/* These describe how temporary files are divided into blocks             */
+
+#define MAXBLKS	(BLKSIZE / sizeof(unsigned short))
+typedef union
+{
+	char		c[BLKSIZE];	/* for text blocks */
+	unsigned short	n[MAXBLKS];	/* for the header block */
+}
+	BLK;
+
+/*------------------------------------------------------------------------*/
+/* These are used manipulate BLK buffers.                                 */
+
+extern BLK	hdr;		/* buffer for the header block */
+extern BLK	*blkget();	/* given index into hdr.c[], reads block */
+extern BLK	*blkadd();	/* inserts a new block into hdr.c[] */
+
+/*------------------------------------------------------------------------*/
+/* These are used to keep track of various flags                          */
+extern struct _viflags
+{
+	short	file;		/* file flags */
+}
+	viflags;
+
+/* file flags */
+#define NEWFILE		0x0001	/* the file was just created */
+#define READONLY	0x0002	/* the file is read-only */
+#define HADNUL		0x0004	/* the file contained NUL characters */
+#define MODIFIED	0x0008	/* the file has been modified, but not saved */
+#define NOFILE		0x0010	/* no name is known for the current text */
+#define ADDEDNL		0x0020	/* newlines were added to the file */
+#define HADBS		0x0040	/* backspace chars were lost from the file */
+#define UNDOABLE	0x0080	/* file has been modified */
+#define NOTEDITED	0x0100	/* the :file command has been used */
+
+/* macros used to set/clear/test flags */
+#define setflag(x,y)	viflags.x |= y
+#define clrflag(x,y)	viflags.x &= ~y
+#define tstflag(x,y)	(viflags.x & y)
+#define initflags()	viflags.file = 0;
+
+/* The options */
+extern char	o_autoindent[1];
+extern char	o_autoprint[1];
+extern char	o_autotab[1];
+extern char	o_autowrite[1];
+extern char	o_columns[3];
+extern char	o_directory[30];
+extern char	o_edcompatible[1];
+extern char	o_equalprg[80];
+extern char	o_errorbells[1];
+extern char	o_exrefresh[1];
+extern char	o_ignorecase[1];
+extern char	o_keytime[3];
+extern char	o_keywordprg[80];
+extern char	o_lines[3];
+extern char	o_list[1];
+extern char	o_number[1];
+extern char	o_readonly[1];
+extern char	o_remap[1];
+extern char	o_report[3];
+extern char	o_scroll[3];
+extern char	o_shell[60];
+extern char	o_shiftwidth[3];
+extern char	o_sidescroll[3];
+extern char	o_sync[1];
+extern char	o_tabstop[3];
+extern char	o_term[30];
+extern char	o_flash[1];
+extern char	o_warn[1];
+extern char	o_wrapscan[1];
+
+#ifndef CRUNCH
+extern char	o_beautify[1];
+extern char	o_exrc[1];
+extern char	o_mesg[1];
+extern char	o_more[1];
+extern char	o_novice[1];
+extern char	o_prompt[1];
+extern char	o_taglength[3];
+extern char	o_terse[1];
+extern char	o_window[3];
+extern char	o_wrapmargin[3];
+extern char	o_writeany[1];
+#endif
+
+#ifndef NO_ERRLIST
+extern char	o_cc[30];
+extern char	o_make[30];
+#endif
+
+#ifndef NO_CHARATTR
+extern char	o_charattr[1];
+#endif
+
+#ifndef NO_DIGRAPH
+extern char	o_digraph[1];
+extern char	o_flipcase[80];
+#endif
+
+#ifndef NO_SENTENCE
+extern char	o_hideformat[1];
+#endif
+
+#ifndef NO_EXTENSIONS
+extern char	o_inputmode[1];
+extern char	o_ruler[1];
+#endif
+
+#ifndef NO_MAGIC
+extern char	o_magic[1];
+#endif
+
+#ifndef NO_MODELINES
+extern char	o_modelines[1];
+#endif
+
+#ifndef NO_SENTENCE
+extern char	o_paragraphs[30];
+extern char	o_sections[30];
+#endif
+
+#if MSDOS
+extern char	o_pcbios[1];
+#endif
+
+#ifndef NO_SHOWMATCH
+extern char	o_showmatch[1];
+#endif
+
+#ifndef	NO_SHOWMODE
+extern char	o_smd[1];
+#endif
+
+/*------------------------------------------------------------------------*/
+/* These help support the single-line multi-change "undo" -- shift-U      */
+
+extern char	U_text[BLKSIZE];
+extern long	U_line;
+
+/*------------------------------------------------------------------------*/
+/* These are used to refer to places in the text 			  */
+
+typedef long	MARK;
+#define markline(x)	(long)((x) / BLKSIZE)
+#define markidx(x)	(int)((x) & (BLKSIZE - 1))
+#define MARK_UNSET	((MARK)0)
+#define MARK_FIRST	((MARK)BLKSIZE)
+#define MARK_LAST	((MARK)(nlines * BLKSIZE))
+#define MARK_AT_LINE(x)	((MARK)(x) * BLKSIZE)
+
+#define NMARKS	29
+extern MARK	mark[NMARKS];	/* marks a-z, plus mark ' and two temps */
+extern MARK	cursor;		/* mark where line is */
+
+/*------------------------------------------------------------------------*/
+/* These are used to keep track of the current & previous files.	  */
+
+extern long	origtime;	/* modification date&time of the current file */
+extern char	origname[256];	/* name of the current file */
+extern char	prevorig[256];	/* name of the preceding file */
+extern long	prevline;	/* line number from preceding file */
+
+/*------------------------------------------------------------------------*/
+/* misc housekeeping variables & functions				  */
+
+extern int	tmpfd;		/* fd used to access the tmp file */
+extern int	tmpnum;		/* counter used to generate unique filenames */
+extern long	lnum[MAXBLKS];	/* last line# of each block */
+extern long	nlines;		/* number of lines in the file */
+extern char	args[BLKSIZE];	/* file names given on the command line */
+extern int	argno;		/* the current element of args[] */
+extern int	nargs;		/* number of filenames in args */
+extern long	changes;	/* counts changes, to prohibit short-cuts */
+extern int	significant;	/* boolean: was a *REAL* change made? */
+extern BLK	tmpblk;		/* a block used to accumulate changes */
+extern long	topline;	/* file line number of top line */
+extern int	leftcol;	/* column number of left col */
+#define		botline	 (topline + LINES - 2)
+#define		rightcol (leftcol + COLS - (*o_number ? 9 : 1))
+extern int	physcol;	/* physical column number that cursor is on */
+extern int	physrow;	/* physical row number that cursor is on */
+extern int	exwrote;	/* used to detect verbose ex commands */
+extern int	doingdot;	/* boolean: are we doing the "." command? */
+extern int	doingglobal;	/* boolean: are doing a ":g" command? */
+extern long	rptlines;	/* number of lines affected by a command */
+extern char	*rptlabel;	/* description of how lines were affected */
+extern char	*fetchline();	/* read a given line from tmp file */
+extern char	*parseptrn();	/* isolate a regexp in a line */
+extern MARK	paste();	/* paste from cut buffer to a given point */
+extern char	*wildcard();	/* expand wildcards in filenames */
+extern MARK	input();	/* inserts characters from keyboard */
+extern char	*linespec();	/* finds the end of a /regexp/ string */
+#define		ctrl(ch) ((ch)&037)
+#ifndef NO_RECYCLE
+extern long	allocate();	/* allocate a free block of the tmp file */
+#endif
+extern int	trapint();	/* trap handler for SIGINT */
+extern int	deathtrap();	/* trap handler for deadly signals */
+extern void	blkdirty();	/* marks a block as being "dirty" */
+extern void	blkflush();	/* writes a single dirty block to the disk */
+extern void	blksync();	/* forces all "dirty" blocks to disk */
+extern void	blkinit();	/* resets the block cache to "empty" state */
+extern void	beep();		/* rings the terminal's bell */
+extern void	exrefresh();	/* writes text to the screen */
+extern void	msg();		/* writes a printf-style message to the screen */
+extern void	endmsgs();	/* if "manymsgs" is set, then scroll up 1 line */
+extern void	garbage();	/* reclaims any garbage blocks */
+extern void	redraw();	/* updates the screen after a change */
+extern void	resume_curses();/* puts the terminal in "cbreak" mode */
+extern void	beforedo();	/* saves current revision before a new change */
+extern void	afterdo();	/* marks end of a beforedo() change */
+extern void	abortdo();	/* like "afterdo()" followed by "undo()" */
+extern int	undo();		/* restores file to previous undo() */
+extern void	dumpkey();	/* lists key mappings to the screen */
+extern void	mapkey();	/* defines a new key mapping */
+extern void	savekeys();	/* lists key mappings to a file */
+extern void	redrawrange();	/* records clues from modify.c */
+extern void	cut();		/* saves text in a cut buffer */
+extern void	delete();	/* deletes text */
+extern void	add();		/* adds text */
+extern void	change();	/* deletes text, and then adds other text */
+extern void	cutswitch();	/* updates cut buffers when we switch files */
+extern void	do_abbr();	/* defines or lists abbreviations */
+extern void	do_digraph();	/* defines or lists digraphs */
+extern void	exstring();	/* execute a string as EX commands */
+extern void	dumpopts();
+extern void	setopts();
+extern void	saveopts();
+extern void	savedigs();
+extern void	saveabbr();
+extern void	savecolor();
+extern void	cutname();
+extern void	cutname();
+extern void	initopts();
+extern void	cutend();
+#ifndef CRUNCH
+extern int	wset;		/* boolean: has the "window" size been set? */
+#endif
+
+/*------------------------------------------------------------------------*/
+/* macros that are used as control structures                             */
+
+#define BeforeAfter(before, after) for((before),bavar=1;bavar;(after),bavar=0)
+#define ChangeText	BeforeAfter(beforedo(FALSE),afterdo())
+
+extern int	bavar;		/* used only in BeforeAfter macros */
+
+/*------------------------------------------------------------------------*/
+/* These are the movement commands.  Each accepts a mark for the starting */
+/* location & number and returns a mark for the destination.		  */
+
+extern MARK	m_updnto();		/* k j G */
+extern MARK	m_right();		/* h */
+extern MARK	m_left();		/* l */
+extern MARK	m_tocol();		/* | */
+extern MARK	m_front();		/* ^ */
+extern MARK	m_rear();		/* $ */
+extern MARK	m_fword();		/* w */
+extern MARK	m_bword();		/* b */
+extern MARK	m_eword();		/* e */
+extern MARK	m_paragraph();		/* { } [[ ]] */
+extern MARK	m_match();		/* % */
+#ifndef NO_SENTENCE
+ extern MARK	m_sentence();		/* ( ) */
+#endif
+extern MARK	m_tomark();		/* 'm */
+#ifndef NO_EXTENSIONS
+extern MARK	m_wsrch();		/* ^A */
+#endif
+extern MARK	m_nsrch();		/* n */
+extern MARK	m_Nsrch();		/* N */
+extern MARK	m_fsrch();		/* /regexp */
+extern MARK	m_bsrch();		/* ?regexp */
+#ifndef NO_CHARSEARCH
+ extern MARK	m__ch();		/* ; , */
+ extern MARK	m_fch();		/* f */
+ extern MARK	m_tch();		/* t */
+ extern MARK	m_Fch();		/* F */
+ extern MARK	m_Tch();		/* T */
+#endif
+extern MARK	m_row();		/* H L M */
+extern MARK	m_z();			/* z */
+extern MARK	m_scroll();		/* ^B ^F ^E ^Y ^U ^D */
+
+/* Some stuff that is used by movement functions... */
+
+extern MARK	adjmove();		/* a helper fn, used by move fns */
+
+/* This macro is used to set the default value of cnt */
+#define DEFAULT(val)	if (cnt < 1) cnt = (val)
+
+/* These are used to minimize calls to fetchline() */
+extern int	plen;	/* length of the line */
+extern long	pline;	/* line number that len refers to */
+extern long	pchgs;	/* "changes" level that len refers to */
+extern char	*ptext;	/* text of previous line, if valid */
+extern void	pfetch();
+extern char	digraph();
+
+/* This is used to build a MARK that corresponds to a specific point in the
+ * line that was most recently pfetch'ed.
+ */
+#define buildmark(text)	(MARK)(BLKSIZE * pline + (int)((text) - ptext))
+
+
+/*------------------------------------------------------------------------*/
+/* These are used to handle EX commands.				  */
+
+#define  CMD_NULL	0	/* NOT A VALID COMMAND */
+#define  CMD_ABBR	1	/* "define an abbreviation" */
+#define  CMD_ARGS	2	/* "show me the args" */
+#define  CMD_APPEND	3	/* "insert lines after this line" */
+#define  CMD_AT		4	/* "execute a cut buffer's contents via EX" */
+#define  CMD_BANG	5	/* "run a single shell command" */
+#define  CMD_CC		6	/* "run `cc` and then do CMD_ERRLIST" */
+#define  CMD_CD		7	/* "change directories" */
+#define  CMD_CHANGE	8	/* "change some lines" */
+#define	 CMD_COLOR	9	/* "change the default colors" */
+#define  CMD_COPY	10	/* "copy the selected text to a given place" */
+#define  CMD_DELETE	11	/* "delete the selected text" */
+#define  CMD_DIGRAPH	12	/* "add a digraph, or display them all" */
+#define  CMD_EDIT	13	/* "switch to a different file" */
+#define  CMD_EQUAL	14	/* "display a line number" */
+#define  CMD_ERRLIST	15	/* "locate the next error in a list" */
+#define  CMD_FILE	16	/* "show the file's status" */
+#define  CMD_GLOBAL	17	/* "globally search & do a command" */
+#define  CMD_INSERT	18	/* "insert lines before the current line" */
+#define  CMD_JOIN	19	/* "join the selected line & the one after" */
+#define  CMD_LIST	20	/* "print lines, making control chars visible" */
+#define  CMD_MAKE	21	/* "run `make` and then do CMD_ERRLIST" */
+#define  CMD_MAP	22	/* "adjust the keyboard map" */
+#define  CMD_MARK	23	/* "mark this line" */
+#define  CMD_MKEXRC	24	/* "make a .exrc file" */
+#define  CMD_MOVE	25	/* "move the selected text to a given place" */
+#define  CMD_NEXT	26	/* "switch to next file in args" */
+#define  CMD_NUMBER	27	/* "print lines from the file w/ line numbers" */
+#define  CMD_PRESERVE	28	/* "act as though vi crashed" */
+#define  CMD_PREVIOUS	29	/* "switch to the previous file in args" */
+#define  CMD_PRINT	30	/* "print the selected text" */
+#define  CMD_PUT	31	/* "insert any cut lines before this line" */
+#define  CMD_QUIT	32	/* "quit without writing the file" */
+#define  CMD_READ	33	/* "append the given file after this line */
+#define  CMD_RECOVER	34	/* "recover file after vi crashes" - USE -r FLAG */
+#define  CMD_REWIND	35	/* "rewind to first file" */
+#define  CMD_SET	36	/* "set a variable's value" */
+#define  CMD_SHELL	37	/* "run some lines through a command" */
+#define  CMD_SHIFTL	38	/* "shift lines left" */
+#define  CMD_SHIFTR	39	/* "shift lines right" */
+#define  CMD_SOURCE	40	/* "interpret a file's contents as ex commands" */
+#define  CMD_STOP	41	/* same as CMD_SUSPEND */
+#define  CMD_SUBAGAIN	42	/* "repeat the previous substitution" */
+#define  CMD_SUBSTITUTE	43	/* "substitute text in this line" */
+#define  CMD_SUSPEND	44	/* "suspend the vi session" */
+#define  CMD_TR		45	/* "transliterate chars in the selected lines" */
+#define  CMD_TAG	46	/* "go to a particular tag" */
+#define  CMD_UNABBR	47	/* "remove an abbreviation definition" */
+#define  CMD_UNDO	48	/* "undo the previous command" */
+#define  CMD_UNMAP	49	/* "remove a key sequence map */
+#define  CMD_VERSION	50	/* "describe which version this is" */
+#define  CMD_VGLOBAL	51	/* "apply a cmd to lines NOT containing an RE" */
+#define  CMD_VISUAL	52	/* "go into visual mode" */
+#define  CMD_WQUIT	53	/* "write this file out (any case) & quit" */
+#define  CMD_WRITE	54	/* "write the selected(?) text to a given file" */
+#define  CMD_XIT	55	/* "write this file out (if modified) & quit" */
+#define  CMD_YANK	56	/* "copy the selected text into the cut buffer" */
+#ifdef DEBUG
+# define CMD_DEBUG	57	/* access to internal data structures */
+# define CMD_VALIDATE	58	/* check for internal consistency */
+#endif
+typedef int CMD;
+
+extern void	ex();
+extern void	vi();
+extern void	doexcmd();
+
+extern void	cmd_append();
+extern void	cmd_args();
+#ifndef NO_AT
+extern void	cmd_at();
+#endif
+extern void	cmd_cd();
+#ifndef NO_COLOR
+extern void	cmd_color();
+#endif
+extern void	cmd_delete();
+#ifndef NO_DIGRAPH
+extern void	cmd_digraph();
+#endif
+extern void	cmd_edit();
+#ifndef NO_ERRLIST
+extern void	cmd_errlist();
+#endif
+extern void	cmd_file();
+extern void	cmd_global();
+extern void	cmd_join();
+extern void	cmd_mark();
+#ifndef NO_ERRLIST
+extern void	cmd_make();
+#endif
+extern void	cmd_map();
+#ifndef NO_MKEXRC
+extern void	cmd_mkexrc();
+#endif
+extern void	cmd_next();
+extern void	cmd_print();
+extern void	cmd_put();
+extern void	cmd_read();
+extern void	cmd_set();
+extern void	cmd_shell();
+extern void	cmd_shift();
+extern void	cmd_source();
+extern void	cmd_substitute();
+extern void	cmd_tag();
+extern void	cmd_undo();
+extern void	cmd_version();
+extern void	cmd_write();
+extern void	cmd_xit();
+extern void	cmd_move();
+#ifdef DEBUG
+extern void	cmd_debug();
+extern void	cmd_validate();
+#endif
+#ifdef SIGTSTP
+extern void	cmd_suspend();
+#endif
+
+/*----------------------------------------------------------------------*/
+/* These are used to handle VI commands 				*/
+
+extern MARK	v_1ex();	/* : */
+extern MARK	v_mark();	/* m */
+extern MARK	v_quit();	/* Q */
+extern MARK	v_redraw();	/* ^L ^R */
+extern MARK	v_ulcase();	/* ~ */
+extern MARK	v_undo();	/* u */
+extern MARK	v_xchar();	/* x X */
+extern MARK	v_replace();	/* r */
+extern MARK	v_overtype();	/* R */
+extern MARK	v_selcut();	/* " */
+extern MARK	v_paste();	/* p P */
+extern MARK	v_yank();	/* y Y */
+extern MARK	v_delete();	/* d D */
+extern MARK	v_join();	/* J */
+extern MARK	v_insert();	/* a A i I o O */
+extern MARK	v_change();	/* c C */
+extern MARK	v_subst();	/* s */
+extern MARK	v_lshift();	/* < */
+extern MARK	v_rshift();	/* > */
+extern MARK	v_reformat();	/* = */
+extern MARK	v_filter();	/* ! */
+extern MARK	v_status();	/* ^G */
+extern MARK	v_switch();	/* ^^ */
+extern MARK	v_tag();	/* ^] */
+extern MARK	v_xit();	/* ZZ */
+extern MARK	v_undoline();	/* U */
+extern MARK	v_again();	/* & */
+#ifndef NO_EXTENSIONS
+ extern MARK	v_keyword();	/* K */
+ extern MARK	v_increment();	/* * */
+#endif
+#ifndef NO_ERRLIST
+ extern MARK	v_errlist();	/* * */
+#endif
+#ifndef NO_AT
+ extern MARK	v_at();		/* @ */
+#endif
+#ifdef SIGTSTP
+ extern MARK	v_suspend();	/* ^Z */
+#endif
+#ifndef NO_POPUP
+ extern MARK	v_popup();	/* \ */
+#endif
+
+/*----------------------------------------------------------------------*/
+/* These flags describe the quirks of the individual visual commands */
+#define NO_FLAGS	0x00
+#define	MVMT		0x01	/* this is a movement command */
+#define PTMV		0x02	/* this can be *part* of a movement command */
+#define FRNT		0x04	/* after move, go to front of line */
+#define INCL		0x08	/* include last char when used with c/d/y */
+#define LNMD		0x10	/* use line mode of c/d/y */
+#define NCOL		0x20	/* this command can't change the column# */
+#define NREL		0x40	/* this is "non-relative" -- set the '' mark */
+#define SDOT		0x80	/* set the "dot" variables, for the "." cmd */
+#ifndef NO_VISIBLE
+# define VIZ		0x100	/* commands which can be used with 'v' */
+#else
+# define VIZ		0
+#endif
+
+/* This variable is zeroed before a command executes, and later ORed with the
+ * command's flags after the command has been executed.  It is used to force
+ * certain flags to be TRUE for *some* invocations of a particular command.
+ * For example, "/regexp/+offset" forces the LNMD flag, and sometimes a "p"
+ * or "P" command will force FRNT.
+ */
+extern int	force_flags;
+
+/*----------------------------------------------------------------------*/
+/* These describe what mode we're in */
+
+#define MODE_EX		1	/* executing ex commands */
+#define	MODE_VI		2	/* executing vi commands */
+#define	MODE_COLON	3	/* executing an ex command from vi mode */
+#define	MODE_QUIT	4
+extern int	mode;
+
+#define WHEN_VICMD	1	/* getkey: we're reading a VI command */
+#define WHEN_VIINP	2	/* getkey: we're in VI's INPUT mode */
+#define WHEN_VIREP	4	/* getkey: we're in VI's REPLACE mode */
+#define WHEN_EX		8	/* getkey: we're in EX mode */
+#define WHEN_MSG	16	/* getkey: we're at a "more" prompt */
+#define WHEN_POPUP	32	/* getkey: we're in the pop-up menu */
+#define WHEN_REP1	64	/* getkey: we're getting a single char for 'r' */
+#define WHEN_CUT	128	/* getkey: we're getting a cut buffer name */
+#define WHEN_MARK	256	/* getkey: we're getting a mark name */
+#define WHEN_CHAR	512	/* getkey: we're getting a destination for f/F/t/T */
+#define WHEN_INMV	4096	/* in input mode, interpret the key in VICMD mode */
+#define WHEN_FREE	8192	/* free the keymap after doing it once */
+#define WHENMASK	(WHEN_VICMD|WHEN_VIINP|WHEN_VIREP|WHEN_REP1|WHEN_CUT|WHEN_MARK|WHEN_CHAR)
+
+#ifndef NO_VISIBLE
+extern MARK	V_from;
+extern int	V_linemd;
+extern MARK	v_start();
+#endif
+
+#ifdef DEBUG
+# define malloc(size)	dbmalloc(size, __FILE__, __LINE__)
+# define free(ptr)	dbfree(ptr, __FILE__, __LINE__)
+extern char *dbmalloc();
+#endif
Index: /trunk/minix/commands/ftp/Makefile
===================================================================
--- /trunk/minix/commands/ftp/Makefile	(revision 9)
+++ /trunk/minix/commands/ftp/Makefile	(revision 9)
@@ -0,0 +1,33 @@
+# Makefile for ftp
+#
+# 01/25/96 Initial Release	Michael Temari, <temari@ix.netcom.com>
+#
+
+CFLAGS=	-O -D_MINIX -D_POSIX_SOURCE
+LDFLAGS=-i
+BINDIR=/usr/bin
+PROG=	ftp
+
+OBJS=	ftp.o local.o file.o other.o net.o
+
+all:	$(PROG)
+
+CC = exec cc
+
+$(PROG):	$(OBJS)
+	$(CC) $(LDFLAGS) -o $@ $(OBJS)
+	install -S 8kw $@
+
+clean:
+	rm -f $(PROG) $(OBJS)
+
+install:	$(BINDIR)/$(PROG)
+
+$(BINDIR)/$(PROG):	$(PROG)
+	install -cs -o bin $? $@
+
+ftp.o:		ftp.c	ftp.h	local.h	file.h	other.h	net.h
+local.o:	local.c	ftp.h	local.h
+file.o:		file.c	ftp.h		file.h		net.h
+other.o:	other.c	ftp.h			other.h
+net.o:		net.c	ftp.h		file.h		net.h
Index: /trunk/minix/commands/ftp/build
===================================================================
--- /trunk/minix/commands/ftp/build	(revision 9)
+++ /trunk/minix/commands/ftp/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/ftp/file.c
===================================================================
--- /trunk/minix/commands/ftp/file.c	(revision 9)
+++ /trunk/minix/commands/ftp/file.c	(revision 9)
@@ -0,0 +1,922 @@
+/* file.c
+ *
+ * This file is part of ftp.
+ *
+ *
+ * 01/25/96 Initial Release	Michael Temari, <temari@ix.netcom.com>
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "ftp.h"
+#include "file.h"
+#include "net.h"
+
+_PROTOTYPE(static char *dir, (char *path, int full));
+_PROTOTYPE(static int asciisend, (int fd, int fdout));
+_PROTOTYPE(static int binarysend, (int fd, int fdout));
+_PROTOTYPE(static int asciirecv, (int fd, int fdin));
+_PROTOTYPE(static int binaryrecv, (int fd, int fdin));
+_PROTOTYPE(static int asciisize, (int fd, off_t *filesize));
+_PROTOTYPE(static off_t asciisetsize, (int fd, off_t filesize));
+
+static char buffer[512 << sizeof(char *)];
+static char bufout[512 << sizeof(char *)];
+static char line2[512];
+
+static char *dir(path, full)
+char *path;
+int full;
+{
+char cmd[128];
+static char name[32];
+
+   tmpnam(name);
+
+   if(full)
+	sprintf(cmd, "ls -l %s > %s", path, name);
+   else
+	sprintf(cmd, "ls %s > %s", path, name);
+
+   system(cmd);
+
+   return(name);
+}
+
+static int asciisend(fd, fdout)
+int fd;
+int fdout;
+{
+int s, len;
+char c;
+char *p;
+char *op, *ope;
+unsigned long total=0L;
+
+   if(atty) {
+	printf("Sent ");
+	fflush(stdout);
+   }
+
+   op = bufout;
+   ope = bufout + sizeof(bufout) - 3;
+
+   while((s = read(fd, buffer, sizeof(buffer))) > 0) {
+	total += (long)s;
+	p = buffer;
+	while(s-- > 0) {
+		c = *p++;
+		if(c == '\r') {
+			*op++ = '\r';
+			total++;
+		}
+		*op++ = c;
+		if(op >= ope) {
+			write(fdout, bufout, op - bufout);
+			op = bufout;
+		}
+	}
+	if(atty) {
+		printf("%9lu bytes\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", total);
+		fflush(stdout);
+	}
+   }
+   if(op > bufout)
+	write(fdout, bufout, op - bufout);
+   if(atty) {
+	printf("\n");
+	fflush(stdout);
+   }
+
+   return(s);
+}
+
+static int binarysend(fd, fdout)
+int fd;
+int fdout;
+{
+int s;
+unsigned long total=0L;
+
+   if(atty) {
+	printf("Sent ");
+	fflush(stdout);
+   }
+
+   while((s = read(fd, buffer, sizeof(buffer))) > 0) {
+	write(fdout, buffer, s);
+	total += (long)s;
+	if(atty) {
+		printf("%9lu bytes\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", total);
+		fflush(stdout);
+	}
+   }
+   if(atty) {
+	printf("\n");
+	fflush(stdout);
+   }
+
+   return(s);
+}
+
+int sendfile(fd, fdout)
+int fd;
+int fdout;
+{
+int s;
+
+   switch(type) {
+	case TYPE_A:
+		s = asciisend(fd, fdout);
+		break;
+	default:
+		s = binarysend(fd, fdout);
+   }
+
+   if(s < 0)
+	return(-1);
+   else
+	return(0);
+}
+
+static int asciirecv(fd, fdin)
+int fd;
+int fdin;
+{
+int s, len;
+int gotcr;
+char c;
+char *p;
+char *op, *ope;
+unsigned long total=0L;
+
+   if(isatty && fd > 2) {
+	printf("Received ");
+	fflush(stdout);
+   }
+   gotcr = 0;
+   op = bufout; ope = bufout + sizeof(bufout) - 3;
+   while((s = read(fdin, buffer, sizeof(buffer))) > 0) {
+	p = buffer;
+	total += (long)s;
+	while(s-- > 0) {
+		c = *p++;
+		if(gotcr) {
+			gotcr = 0;
+			if(c != '\n')
+				*op++ = '\r';
+		}
+		if(c == '\r')
+			gotcr = 1;
+		else
+			*op++ = c;
+		if(op >= ope) {
+			write(fd, bufout, op - bufout);
+			op = bufout;
+		}
+	}
+	if(atty && fd > 2) {
+		printf("%9lu bytes\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", total);
+		fflush(stdout);
+	}
+   }
+   if(gotcr)
+	*op++ = '\r';
+   if(op > bufout)
+	write(fd, bufout, op - bufout);
+   if(atty && fd > 2) {
+	printf("\n");
+	fflush(stdout);
+   }
+   return(s);
+}
+
+static binaryrecv(fd, fdin)
+int fd;
+int fdin;
+{
+int s;
+unsigned long total=0L;
+
+   if(atty && fd > 2) {
+	printf("Received ");
+	fflush(stdout);
+   }
+   while((s = read(fdin, buffer, sizeof(buffer))) > 0) {
+	write(fd, buffer, s);
+	total += (long)s;
+	if(atty && fd > 2) {
+		printf("%9lu bytes\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", total);
+		fflush(stdout);
+	}
+   }
+   if(atty && fd > 2) {
+	printf("\n");
+	fflush(stdout);
+   }
+   return(s);
+}
+
+int recvfile(fd, fdin)
+int fd;
+int fdin;
+{
+int s;
+
+   switch(type) {
+	case TYPE_A:
+		s = asciirecv(fd, fdin);
+		break;
+	default:
+		s = binaryrecv(fd, fdin);
+   }
+
+   if(s < 0)
+	return(-1);
+   else
+	return(0);
+}
+
+int DOascii()
+{
+int s;
+
+   if(DOcmdcheck())
+	return(0);
+
+   s = DOcommand("TYPE", "A");
+
+   type = TYPE_A;
+
+   return(s);
+}
+
+int DObinary()
+{
+int s;
+
+   if(DOcmdcheck())
+	return(0);
+
+   s = DOcommand("TYPE", "I");
+
+   type = TYPE_I;
+
+   return(s);
+}
+
+int DOpwd()
+{
+int s;
+
+   if(DOcmdcheck())
+	return(0);
+
+   s = DOcommand("PWD", "");
+
+   if(s == 500 || s == 502)
+	s = DOcommand("XPWD", "");
+
+   return(s);
+}
+
+int DOcd()
+{
+char *path;
+int s;
+
+   if(DOcmdcheck())
+	return(0);
+
+   path = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("Path: ", line2, sizeof(line2));
+	path = line2;
+   }
+
+   if(!strcmp(path, ".."))
+   	s = DOcommand("CDUP", "");
+   else
+   	s = DOcommand("CWD", path);
+
+   if(s == 500 || s == 502) {
+	if(!strcmp(path, ".."))
+		s = DOcommand("XCUP", "");
+	else
+		s = DOcommand("XCWD", path);
+   }
+
+   return(s);
+}
+
+int DOmkdir()
+{
+char *path;
+int s;
+
+   if(DOcmdcheck())
+	return(0);
+
+   path = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("Directory: ", line2, sizeof(line2));
+	path = line2;
+   }
+
+   s = DOcommand("MKD", path);
+
+   if(s == 500 || s == 502)
+	s = DOcommand("XMKD", path);
+
+   return(s);
+}
+
+int DOrmdir()
+{
+char *path;
+int s;
+
+   if(DOcmdcheck())
+	return(0);
+
+   path = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("Directory: ", line2, sizeof(line2));
+	path = line2;
+   }
+
+   s = DOcommand("RMD", path);
+
+   if(s == 500 || s == 502)
+	s = DOcommand("XRMD", path);
+
+   return(s);
+}
+
+int DOdelete()
+{
+char *file;
+
+   if(DOcmdcheck())
+	return(0);
+
+   file = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("File: ", line2, sizeof(line2));
+	file = line2;
+   }
+
+   return(DOcommand("DELE", file));
+}
+
+int DOmdtm()
+{
+char *file;
+
+   if(DOcmdcheck())
+	return(0);
+
+   file = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("File: ", line2, sizeof(line2));
+	file = line2;
+   }
+
+   return(DOcommand("MDTM", file));
+}
+
+int DOsize()
+{
+char *file;
+
+   if(DOcmdcheck())
+	return(0);
+
+   file = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("File: ", line2, sizeof(line2));
+	file = line2;
+   }
+
+   return(DOcommand("SIZE", file));
+}
+
+int DOstat()
+{
+char *file;
+
+   if(cmdargc < 2)
+	if(!linkopen) {
+		printf("You must \"OPEN\" a connection first.\n");
+		return(0);
+	} else
+		return(DOcommand("STAT", ""));
+
+   if(DOcmdcheck())
+	return(0);
+
+   file = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("File: ", line2, sizeof(line2));
+	file = line2;
+   }
+
+   return(DOcommand("STAT", file));
+}
+
+int DOlist()
+{
+char *path;
+char *local;
+int fd;
+int s;
+
+   if(DOcmdcheck())
+	return(0);
+
+   path = cmdargv[1];
+
+   if(cmdargc < 2)
+	path = "";
+
+   if(cmdargc < 3)
+	local = "";
+   else
+	local = cmdargv[2];
+
+   if(*local == '\0')
+	fd = 1;
+   else
+	fd = open(local, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+
+   if(fd < 0) {
+	printf("Could not open local file %s. Error %s\n", local, strerror(errno));
+	return(0);
+   }
+
+   s = DOdata("LIST", path, RETR, fd);
+
+   if(fd > 2)
+	close(fd);
+
+   return(s);
+}
+
+int DOnlst()
+{
+char *path;
+char *local;
+int fd;
+int s;
+
+   if(DOcmdcheck())
+	return(0);
+
+   path = cmdargv[1];
+
+   if(cmdargc < 2)
+	path = "";
+
+   if(cmdargc < 3)
+	local = "";
+   else
+	local = cmdargv[2];
+
+   if(*local == '\0')
+	fd = 1;
+   else
+	fd = open(local, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+
+   if(fd < 0) {
+	printf("Could not open local file %s. Error %s\n", local, strerror(errno));
+	return(0);
+   }
+
+   s = DOdata("NLST", path, RETR, fd);
+
+   if(fd > 2)
+	close(fd);
+
+   return(s);
+}
+
+int DOretr()
+{
+char *file, *localfile;
+int fd;
+int s;
+
+   if(DOcmdcheck())
+	return(0);
+
+   file = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("Remote File: ", line2, sizeof(line2));
+	file = line2;
+   }
+
+   if(cmdargc < 3)
+	localfile = file;
+   else
+	localfile = cmdargv[2];
+
+   fd = open(localfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+
+   if(fd < 0) {
+	printf("Could not open local file %s. Error %s\n", localfile, strerror(errno));
+	return(0);
+   }
+
+   s = DOdata("RETR", file, RETR, fd);
+
+   close(fd);
+
+   return(s);
+}
+
+int DOrretr()
+{
+char *file, *localfile;
+int fd;
+int s;
+off_t filesize;
+char restart[16];
+
+   if(DOcmdcheck())
+	return(0);
+
+   file = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("Remote File: ", line2, sizeof(line2));
+	file = line2;
+   }
+
+   if(cmdargc < 3)
+	localfile = file;
+   else
+	localfile = cmdargv[2];
+
+   fd = open(localfile, O_RDWR);
+
+   if(fd < 0) {
+	printf("Could not open local file %s. Error %s\n", localfile, strerror(errno));
+	return(0);
+   }
+
+   if(type == TYPE_A) {
+   	if(asciisize(fd, &filesize)) {
+   		printf("Could not determine ascii file size of %s\n", localfile);
+   		close(fd);
+   		return(0);
+   	}
+   } else
+	filesize = lseek(fd, 0, SEEK_END);
+
+   sprintf(restart, "%lu", filesize);
+
+   s = DOcommand("REST", restart);
+
+   if(s != 350) {
+   	close(fd);
+   	return(s);
+   }
+
+   s = DOdata("RETR", file, RETR, fd);
+
+   close(fd);
+
+   return(s);
+}
+
+int DOMretr()
+{
+char *files;
+int fd, s;
+FILE *fp;
+char name[32];
+
+   if(DOcmdcheck())
+	return(0);
+
+   files = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("Files: ", line2, sizeof(line2));
+	files = line2;
+   }
+
+   tmpnam(name);
+
+   fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+
+   if(fd < 0) {
+	printf("Could not open local file %s. Error %s\n", name, strerror(errno));
+	return(0);
+   }
+
+   s = DOdata("NLST", files, RETR, fd);
+
+   close(fd);
+
+   if(s == 226) {
+	fp = fopen(name, "r");
+	unlink(name);
+	if(fp == (FILE *)NULL) {
+		printf("Unable to open file listing.\n");
+		return(0);
+	}
+	while(fgets(line2, sizeof(line2), fp) != (char *)NULL) {
+		line2[strlen(line2)-1] = '\0';
+		printf("Retrieving file: %s\n", line2); fflush(stdout);
+		fd = open(line2, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+		if(fd < 0)
+			printf("Unable to open local file %s\n", line2);
+		else {
+			s = DOdata("RETR", line2, RETR, fd);
+			close(fd);
+			if(s < 0) break;
+		}
+	}
+	fclose(fp);
+   } else
+	unlink(name);
+
+   return(s);
+}
+
+int DOappe()
+{
+char *file, *remotefile;
+int fd;
+int s;
+
+   if(DOcmdcheck())
+	return(0);
+
+   file = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("Local File: ", line2, sizeof(line2));
+	file = line2;
+   }
+
+   if(cmdargc < 3)
+	remotefile = file;
+   else
+	remotefile = cmdargv[2];
+
+   fd = open(file, O_RDONLY);
+
+   if(fd < 0) {
+	printf("Could not open local file %s. Error %s\n", file, strerror(errno));
+	return(0);
+   }
+
+   s = DOdata("APPE", remotefile, STOR, fd);
+
+   close(fd);
+
+   return(s);
+}
+
+int DOstor()
+{
+char *file, *remotefile;
+int fd;
+int s;
+
+   if(DOcmdcheck())
+	return(0);
+
+   file = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("Local File: ", line2, sizeof(line2));
+	file = line2;
+   }
+
+   if(cmdargc < 3)
+	remotefile = file;
+   else
+	remotefile = cmdargv[2];
+
+   fd = open(file, O_RDONLY);
+
+   if(fd < 0) {
+	printf("Could not open local file %s. Error %s\n", file, strerror(errno));
+	return(0);
+   }
+
+   s = DOdata("STOR", remotefile, STOR, fd);
+
+   close(fd);
+
+   return(s);
+}
+
+int DOrstor()
+{
+char *file, *remotefile;
+int fd;
+int s;
+off_t filesize, rmtsize;
+char restart[16];
+
+   if(DOcmdcheck())
+	return(0);
+
+   file = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("Local File: ", line2, sizeof(line2));
+	file = line2;
+   }
+
+   if(cmdargc < 3)
+	remotefile = file;
+   else
+	remotefile = cmdargv[2];
+
+   s = DOcommand("SIZE", remotefile);
+
+   if(s != 215)
+   	return(s);
+
+   rmtsize = atol(reply+4);
+
+   fd = open(file, O_RDONLY);
+
+   if(fd < 0) {
+	printf("Could not open local file %s. Error %s\n", file, strerror(errno));
+	return(0);
+   }
+
+   if(type == TYPE_A)
+   	filesize = asciisetsize(fd, rmtsize);
+   else
+	filesize = lseek(fd, rmtsize, SEEK_SET);
+
+   if(filesize != rmtsize) {
+	printf("Could not set file start of %s\n", file);
+   	close(fd);
+   	return(0);
+   }
+
+   sprintf(restart, "%lu", rmtsize);
+
+   s = DOcommand("REST", restart);
+
+   if(s != 350) {
+   	close(fd);
+   	return(s);
+   }
+
+   s = DOdata("STOR", remotefile, STOR, fd);
+
+   close(fd);
+
+   return(s);
+}
+
+int DOstou()
+{
+char *file, *remotefile;
+int fd;
+int s;
+
+   if(DOcmdcheck())
+	return(0);
+
+   file = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("Local File: ", line2, sizeof(line2));
+	file = line2;
+   }
+
+   if(cmdargc < 3)
+	remotefile = file;
+   else
+	remotefile = cmdargv[2];
+
+   fd = open(file, O_RDONLY);
+
+   if(fd < 0) {
+	printf("Could not open local file %s. Error %s\n", file, strerror(errno));
+	return(0);
+   }
+
+   s = DOdata("STOU", remotefile, STOR, fd);
+
+   close(fd);
+
+   return(s);
+}
+
+int DOMstor()
+{
+char *files;
+char *name;
+int fd, s;
+FILE *fp;
+
+   if(DOcmdcheck())
+	return(0);
+
+   files = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("Files: ", line2, sizeof(line2));
+	files = line2;
+   }
+
+   name = dir(files, 0);
+
+   fp = fopen(name, "r");
+
+   if(fp == (FILE *)NULL) {
+	printf("Unable to open listing file.\n");
+	return(0);
+   }
+
+   while(fgets(line2, sizeof(line2), fp) != (char *)NULL) {
+	line2[strlen(line2)-1] = '\0';
+	printf("Sending file: %s\n", line2); fflush(stdout);
+	fd = open(line2, O_RDONLY);
+	if(fd < 0)
+		printf("Unable to open local file %s\n", line2);
+	else {
+		s = DOdata("STOR", line2, STOR, fd);
+		close(fd);
+		if(s < 0) break;
+	}
+   }
+   fclose(fp);
+   unlink(name);
+
+   return(s);
+}
+
+static int asciisize(fd, filesize)
+int fd;
+off_t *filesize;
+{
+unsigned long count;
+char *p, *pp;
+int cnt;
+
+   count = 0;
+
+   while((cnt = read(fd, buffer, sizeof(buffer))) > 0) {
+	p = buffer; pp = buffer + cnt;
+	count += cnt;
+	while(p < pp)
+		if(*p++ == '\n')
+			count++;
+   }
+
+   if(cnt == 0) {
+	*filesize = count;
+	return(0);
+   }
+
+   return(1);
+}
+
+static off_t asciisetsize(fd, filesize)
+int fd;
+off_t filesize;
+{
+off_t sp;
+int s;
+
+   sp = 0;
+
+   while(sp < filesize) {
+	s = read(fd, buffer, 1);
+	if(s < 0)
+		return(-1);
+	if(s == 0) break;
+	sp++;
+	if(*buffer == '\n')
+		sp++;
+   }
+
+   return(sp);
+}
Index: /trunk/minix/commands/ftp/file.h
===================================================================
--- /trunk/minix/commands/ftp/file.h	(revision 9)
+++ /trunk/minix/commands/ftp/file.h	(revision 9)
@@ -0,0 +1,30 @@
+/* file.h
+ *
+ * This file is part of ftp.
+ *
+ *
+ * 01/25/96 Initial Release	Michael Temari, <temari@ix.netcom.com>
+ */
+
+_PROTOTYPE(int recvfile, (int fd, int fdin));
+_PROTOTYPE(int sendfile, (int fd, int fdout));
+_PROTOTYPE(int DOascii, (void));
+_PROTOTYPE(int DObinary, (void));
+_PROTOTYPE(int DOpwd, (void));
+_PROTOTYPE(int DOcd, (void));
+_PROTOTYPE(int DOmkdir, (void));
+_PROTOTYPE(int DOrmdir, (void));
+_PROTOTYPE(int DOdelete, (void));
+_PROTOTYPE(int DOmdtm, (void));
+_PROTOTYPE(int DOsize, (void));
+_PROTOTYPE(int DOstat, (void));
+_PROTOTYPE(int DOlist, (void));
+_PROTOTYPE(int DOnlst, (void));
+_PROTOTYPE(int DOretr, (void));
+_PROTOTYPE(int DOrretr, (void));
+_PROTOTYPE(int DOMretr, (void));
+_PROTOTYPE(int DOappe, (void));
+_PROTOTYPE(int DOstor, (void));
+_PROTOTYPE(int DOrstor, (void));
+_PROTOTYPE(int DOstou, (void));
+_PROTOTYPE(int DOMstor, (void));
Index: /trunk/minix/commands/ftp/ftp.c
===================================================================
--- /trunk/minix/commands/ftp/ftp.c	(revision 9)
+++ /trunk/minix/commands/ftp/ftp.c	(revision 9)
@@ -0,0 +1,312 @@
+/* ftp.c by Michael Temari 06/21/92
+ *
+ * ftp          An ftp client program for use with TNET.
+ *
+ * Usage:       ftp [[host] [port]]
+ *
+ * Version:     0.10    06/21/92 (pre-release not yet completed)
+ *              0.20    07/01/92
+ *              0.30    01/15/96 (Minix 1.7.1 initial release)
+ *              0.40    08/27/96
+ *
+ * Author:      Michael Temari, <temari@ix.netcom.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "ftp.h"
+#include "local.h"
+#include "file.h"
+#include "other.h"
+#include "net.h"
+
+FILE *fpcommin;
+FILE *fpcommout;
+
+int linkopen;
+int loggedin;
+int type;
+int format;
+int mode;
+int structure;
+int passive;
+int atty;
+
+int cmdargc;
+char *cmdargv[NUMARGS];
+
+char reply[1024];
+
+_PROTOTYPE(static int makeargs, (char *buff));
+_PROTOTYPE(int DOhelp, (void));
+_PROTOTYPE(int main, (int argc, char *argv[]));
+
+static int makeargs(buff)
+char *buff;
+{
+char *p;
+int i;
+
+   for(i = 0; i < NUMARGS; i++)
+	cmdargv[i] = (char *)0;
+
+   p = buff + strlen(buff) - 1;
+   while(p != buff)
+	if(*p == '\r' || *p == '\n' || isspace(*p))
+		*p-- = '\0';
+	else
+		break;
+
+   p = buff;
+   cmdargc = 0;
+   while(cmdargc < NUMARGS) {
+	while(*p && isspace(*p))
+		p++;
+	if(*p == '\0')
+		break;
+	cmdargv[cmdargc++] = p;
+	while(*p && !isspace(*p)) {
+		if(cmdargc == 1)
+			*p = tolower(*p);
+		p++;
+	}
+	if(*p == '\0')
+		break;
+	*p = '\0';
+	p++;
+   }
+}
+
+int readline(prompt, buff, len)
+char *prompt;
+char *buff;
+int len;
+{
+   printf(prompt); fflush(stdout);
+
+   if(fgets(buff, len, stdin) == (char *)NULL) {
+	printf("\nEnd of file on input!\n");
+	exit(1);
+   }
+
+   *strchr(buff, '\n') = 0;
+
+   if(!atty) {
+	printf("%s\n", buff);
+	fflush(stdout);
+   }
+
+   return(0);
+}
+
+int DOgetreply()
+{
+char *p;
+char buff[6];
+int s;
+int firsttime;
+
+   do {
+	firsttime = 1;
+	do {
+		if(fgets(reply, sizeof(reply), fpcommin) == (char *)0)
+			return(-1);
+		p = reply + strlen(reply) - 1;
+		while(p != reply)
+			if(*p == '\r' || *p == '\n' || isspace(*p))
+				*p-- = '\0';
+			else
+				break;
+		printf("%s\n", reply); fflush(stdout);
+		if(firsttime) {
+			firsttime = 0;
+			strncpy(buff, reply, 4);
+			buff[3] = ' ';
+		}
+	   } while(strncmp(reply, buff, 3) || reply[3] == '-');
+	   s = atoi(buff);
+   } while(s < 200 && s != 125 & s != 150);
+
+   return(s);
+}
+
+int DOcmdcheck()
+{
+   if(!linkopen) {
+	printf("You must \"OPEN\" a connection first.\n");
+	return(1);
+   }
+
+   if(!loggedin) {
+	printf("You must login first.\n");
+	return(1);
+   }
+
+   return(0);
+}
+
+int DOcommand(ftpcommand, ftparg)
+char *ftpcommand;
+char *ftparg;
+{
+   if(*ftparg)
+	fprintf(fpcommout, "%s %s\r\n", ftpcommand, ftparg);
+   else
+   	fprintf(fpcommout, "%s\r\n", ftpcommand);
+
+   fflush(fpcommout);
+
+   return(DOgetreply());
+}
+
+int DOhelp()
+{
+char junk[10];
+
+   printf("Command:      Description\n");
+   printf("!             Escape to a shell\n");
+   printf("append        Append a file to remote host\n");
+   printf("ascii         Set file transfer mode to ascii\n");
+   printf("binary        Set file transfer mode to binary\n");
+   printf("bye           Close connection and exit\n");
+   printf("cd            Change directory on remote host\n");
+   printf("close         Close connection\n");
+   printf("del           Remove file on remote host\n");
+   printf("dir           Display long form remote host directory listing\n");
+   printf("exit          Close connection and exit\n");
+   printf("get           Retrieve a file from remote host\n");
+   printf("help          Display this text\n");
+   printf("lcd           Change directory on local host\n");
+   printf("ldir          Display long form local host directory listing\n");
+   printf("lls           Display local host directory listing\n");
+   printf("lmkdir        Create directory on local host\n");
+   printf("lpwd          Display current directory on local host\n");
+   printf("lrmdir        Remove directory on local host\n");
+   printf("ls            Display remote host directory listing\n");
+   printf("mget          Retrieve multiple files from remote host\n");
+   printf("mkdir         Create directory on remote host\n");
+   printf("mod           Get file modification time\n");
+
+   readline("Press ENTER to continue... ", junk, sizeof(junk));
+
+   printf("mput          Send multiple files to remote host\n");
+   printf("noop          Send the ftp NOOP command\n");
+   printf("open          Open connection to remote host\n");
+   printf("pass          Enter remote user password\n");
+   printf("passive       Toggle passive mode\n");
+   printf("put           Send a file to remote host\n");
+   printf("putu          Send a file to remote host(unique)\n");
+   printf("pwd           Display current directory on remote host\n");
+   printf("quit          Close connection and exit\n");
+   printf("quote         Send raw ftp command to remote host\n");
+   printf("reget         Restart a partial file retrieve from remote host\n");
+   printf("remotehelp    Display ftp commands implemented on remote host\n");
+   printf("reput         Restart a partial file send to remote host\n");
+   printf("rm            Remove file on remote host\n");
+   printf("rmdir         Remove directory on remote host\n");
+   printf("site          Send a site specific command\n");
+   printf("size          Get file size information\n");
+   printf("status        Get connection/file status information\n");
+   printf("system        Get remote system type information\n");
+   printf("user          Enter remote user information\n");
+
+   return(0);
+}
+
+struct commands {
+	char *name;
+	_PROTOTYPE(int (*func), (void));
+};
+
+static struct commands commands[] = {
+        "!",            DOlshell,
+	"append",	DOappe,
+	"ascii",        DOascii,
+	"binary",       DObinary,
+	"bin",          DObinary,
+	"bye",          DOquit,
+	"cd",           DOcd,
+	"close",        DOclose,
+	"del",          DOdelete,
+	"dir",          DOlist,
+	"exit",         DOquit,
+	"get",          DOretr,
+	"help",         DOhelp,
+	"lcd",          DOlcd,
+        "ldir",         DOllist,
+        "lls",          DOlnlst,
+	"lmkdir",       DOlmkdir,
+	"lpwd",         DOlpwd,
+	"lrmdir",       DOlrmdir,
+	"ls",           DOnlst,
+	"mget",         DOMretr,
+	"mkdir",        DOmkdir,
+	"mod",		DOmdtm,
+	"mput",         DOMstor,
+	"noop",         DOnoop,
+	"open",         DOopen,
+	"pass",		DOpass,
+	"passive",      DOpassive,
+	"put",          DOstor,
+	"putu",		DOstou,
+	"pwd",          DOpwd,
+	"quit",         DOquit,
+	"quote",        DOquote,
+	"reget",	DOrretr,
+	"remotehelp",   DOremotehelp,
+	"reput",	DOrstor,
+	"rm",           DOdelete,
+	"rmdir",        DOrmdir,
+	"site",		DOsite,
+	"size",		DOsize,
+	"status",	DOstat,
+	"system",	DOsyst,
+	"user",         DOuser,
+	"",     (int (*)())0
+};
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+int s;
+struct commands *cmd;
+static char buffer[128];
+
+   NETinit();
+
+   FTPinit();
+
+   s = 0;
+
+   if(argc > 1) {
+	sprintf(buffer, "open %s ", argv[1]);
+	makeargs(buffer);
+	s = DOopen();
+	if(atty && s > 0) {
+		sprintf(buffer, "user");
+		makeargs(buffer);
+		s = DOuser();
+	}
+   }
+
+   while(s >= 0) {
+	readline("ftp>", buffer, sizeof(buffer));
+	makeargs(buffer);
+	if(cmdargc == 0) continue;
+	for(cmd = commands; *cmd->name != '\0'; cmd++)
+		if(!strcmp(cmdargv[0], cmd->name))
+			break;
+	if(*cmd->name != '\0')
+		s = (*cmd->func)();
+	else {
+		s = 0;
+		printf("Command \"%s\" not recognized.\n", cmdargv[0]);
+	}
+   }
+
+   return(0);
+}
Index: /trunk/minix/commands/ftp/ftp.h
===================================================================
--- /trunk/minix/commands/ftp/ftp.h	(revision 9)
+++ /trunk/minix/commands/ftp/ftp.h	(revision 9)
@@ -0,0 +1,36 @@
+/* ftp.h
+ *
+ * This file is part of ftp.
+ *
+ *
+ * 01/25/96 Initial Release	Michael Temari, <temari@ix.netcom.com>
+ */
+
+extern FILE *fpcommin;
+extern FILE *fpcommout;
+
+extern int linkopen;
+extern int loggedin;
+extern int type;
+extern int format;
+extern int mode;
+extern int structure;
+extern int passive;
+extern int atty;
+
+#define	NUMARGS	10
+extern int cmdargc;
+extern char *cmdargv[NUMARGS];
+
+extern char reply[1024];
+
+#define	RETR	0
+#define	STOR	1
+
+#define	TYPE_A	0
+#define	TYPE_I	1
+
+_PROTOTYPE(int readline, (char *prompt, char *buff, int len));
+_PROTOTYPE(int DOgetreply, (void));
+_PROTOTYPE(int DOcmdcheck, (void));
+_PROTOTYPE(int DOcommand, (char *ftpcommand, char *ftparg));
Index: /trunk/minix/commands/ftp/local.c
===================================================================
--- /trunk/minix/commands/ftp/local.c	(revision 9)
+++ /trunk/minix/commands/ftp/local.c	(revision 9)
@@ -0,0 +1,128 @@
+/* local.c
+ *
+ * This file is part of ftp.
+ *
+ *
+ * 01/25/96 Initial Release	Michael Temari, <temari@ix.netcom.com>
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "ftp.h"
+#include "local.h"
+
+static char line2[512];
+
+_PROTOTYPE(static void dodir, (char *path, int full));
+
+int DOlpwd()
+{
+   if(getcwd(line2, sizeof(line2)) == (char *)NULL)
+	printf("Could not determine local directory. %s\n", strerror(errno));
+   else
+	printf("Current local directory: %s\n", line2);
+
+   return(0);
+}
+
+int DOlcd()
+{
+char *path;
+int s;
+
+   path = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("Path: ", line2, sizeof(line2));
+	path = line2;
+   }
+
+   if(chdir(path))
+	printf("Could not change local directory. %s\n", strerror(errno));
+   else
+	DOlpwd();
+   
+   return(0);
+}
+
+int DOlmkdir()
+{
+char *path;
+int s;
+
+   path = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("Directory: ", line2, sizeof(line2));
+	path = line2;
+   }
+
+   if(mkdir(path, 0777))
+	printf("Could not make directory %s. %s\n", path, strerror(errno));
+   else
+	printf("Directory created.\n");
+   
+   return(0);
+}
+
+int DOlrmdir()
+{
+char *path;
+int s;
+
+   path = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("Directory: ", line2, sizeof(line2));
+	path = line2;
+   }
+
+   if(rmdir(path))
+	printf("Could not remove directory %s. %s\n", path, strerror(errno));
+   else
+	printf("Directory removed.\n");
+   
+   return(0);
+}
+
+int DOllist(void)
+{
+   dodir(".", 1);
+}
+
+int DOlnlst(void)
+{
+   dodir(".", 0);
+}
+
+int DOlshell(void)
+{
+   system("$SHELL");
+}
+
+static void dodir(path, full)
+char *path;
+int full;
+{
+char cmd[128];
+static char name[32];
+
+   tmpnam(name);
+
+   if(full)
+	sprintf(cmd, "ls -l %s > %s", path, name);
+   else
+	sprintf(cmd, "ls %s > %s", path, name);
+
+   system(cmd);
+   sprintf(cmd, "more %s", name);
+   system(cmd);
+   sprintf(cmd, "rm %s", name);
+   system(cmd);
+}
Index: /trunk/minix/commands/ftp/local.h
===================================================================
--- /trunk/minix/commands/ftp/local.h	(revision 9)
+++ /trunk/minix/commands/ftp/local.h	(revision 9)
@@ -0,0 +1,15 @@
+/* local.h
+ *
+ * This file is part of ftp.
+ *
+ *
+ * 01/25/96 Initial Release	Michael Temari, <temari@ix.netcom.com>
+ */
+
+_PROTOTYPE(int DOlpwd, (void));
+_PROTOTYPE(int DOlcd, (void));
+_PROTOTYPE(int DOlmkdir, (void));
+_PROTOTYPE(int DOlrmdir, (void));
+_PROTOTYPE(int DOllist, (void));
+_PROTOTYPE(int DOlnlst, (void));
+_PROTOTYPE(int DOlshell, (void));
Index: /trunk/minix/commands/ftp/net.c
===================================================================
--- /trunk/minix/commands/ftp/net.c	(revision 9)
+++ /trunk/minix/commands/ftp/net.c	(revision 9)
@@ -0,0 +1,421 @@
+/* net.c
+ *
+ * This file is part of ftp.
+ *
+ *
+ * 01/25/96 Initial Release	Michael Temari, <temari@ix.netcom.com>
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+
+#include "ftp.h"
+#include "file.h"
+#include "net.h"
+
+_PROTOTYPE(void donothing, (int sig));
+
+static int ftpcomm_fd;
+static ipaddr_t myip;
+static ipaddr_t hostip;
+static char host[256];
+static int lpid;
+
+void NETinit()
+{
+int s;
+char *tcp_device;
+int tcp_fd;
+nwio_tcpconf_t nwio_tcpconf;
+
+   /* All this just to get our ip address */
+
+   if((tcp_device = getenv("TCP_DEVICE")) == (char *)NULL)
+	tcp_device = TCP_DEVICE;
+
+   tcp_fd = open(tcp_device, O_RDWR);
+   if(tcp_fd < 0) {
+	perror("ftp: Could not open tcp_device");
+	exit(-1);
+   }
+   s = ioctl(tcp_fd, NWIOGTCPCONF, &nwio_tcpconf);
+   if(s < 0) {
+	perror("ftp: Could not get tcp configuration");
+	exit(-1);
+   }
+
+   myip = nwio_tcpconf.nwtc_locaddr;
+
+   close(tcp_fd);
+}
+
+int DOopen()
+{
+nwio_tcpconf_t tcpconf;
+nwio_tcpcl_t tcpcopt;
+char *tcp_device;
+tcpport_t port;
+int s;
+struct hostent *hp;
+struct servent *servent;
+
+   if(linkopen) {
+	printf("Use \"CLOSE\" to close the connection first.\n");
+	return(0);
+   }
+
+   if(cmdargc < 2)
+	readline("Host: ", host, sizeof(host));
+   else
+	strncpy(host, cmdargv[1], sizeof(host));
+
+   if((servent = getservbyname("ftp", "tcp")) == (struct servent *)NULL) {
+   	fprintf(stderr, "ftp: Could not find ftp tcp service\n");
+   	return(-1);
+   }
+   port = (tcpport_t)servent->s_port;
+
+   hp = gethostbyname(host);
+   if (hp == (struct hostent *)NULL) {
+	hostip = (ipaddr_t)0;
+	printf("Unresolved host %s\n", host);
+	return(0);
+   } else
+	memcpy((char *) &hostip, (char *) hp->h_addr, hp->h_length);
+
+   /* This HACK allows the server to establish data connections correctly */
+   /* when using the loopback device to talk to ourselves */
+   if(hostip == inet_addr("127.0.0.1"))
+	hostip = myip;
+
+   if((tcp_device = getenv("TCP_DEVICE")) == NULL)
+	tcp_device = "/dev/tcp";
+
+   if((ftpcomm_fd = open(tcp_device, O_RDWR)) < 0) {
+	perror("ftp: open error on tcp device");
+	return(-1);
+   }
+
+   tcpconf.nwtc_flags = NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
+   tcpconf.nwtc_remaddr = hostip;
+   tcpconf.nwtc_remport = port;
+
+   s = ioctl(ftpcomm_fd, NWIOSTCPCONF, &tcpconf);
+   if(s < 0) {
+	perror("ftp: ioctl error on NWIOSTCPCONF");
+	close(ftpcomm_fd);
+	return(s);
+   }
+
+   tcpcopt.nwtcl_flags = 0;
+
+   s = ioctl(ftpcomm_fd, NWIOTCPCONN, &tcpcopt);
+   if(s < 0) {
+	perror("ftp: ioctl error on NWIOTCPCONN");
+	close(ftpcomm_fd);
+	return(s);
+   }
+
+   s = ioctl(ftpcomm_fd, NWIOGTCPCONF, &tcpconf);
+   if(s < 0) {
+	perror("ftp: ioctl error on NWIOGTCPCONF");
+	close(ftpcomm_fd);
+	return(s);
+   }
+
+   fpcommin  = fdopen(ftpcomm_fd, "r");
+   fpcommout = fdopen(ftpcomm_fd, "w");
+
+   s = DOgetreply();
+
+   if(s < 0) {
+	fclose(fpcommin);
+	fclose(fpcommout);
+	close(ftpcomm_fd);
+	return(s);
+   }
+
+   if(s != 220) {
+	fclose(fpcommin);
+	fclose(fpcommout);
+	close(ftpcomm_fd);
+	return(0);
+   }
+
+   linkopen = 1;
+
+   return(s);
+}
+
+int DOclose()
+{
+   if(!linkopen) {
+	printf("You can't close a connection that isn't open.\n");
+	return(0);
+   }
+
+   fclose(fpcommin);
+   fclose(fpcommout);
+   close(ftpcomm_fd);
+
+   linkopen = 0;
+   loggedin = 0;
+
+   return(0);
+}
+
+int DOquit()
+{
+int s;
+
+   if(linkopen) {
+	s = DOcommand("QUIT", "");
+	s = DOclose();
+   }
+
+   printf("FTP done.\n");
+
+   exit(0);
+}
+
+void donothing(sig)
+int sig;
+{
+}
+
+int DOdata(datacom, file, direction, fd)
+char *datacom;
+char *file;
+int direction;  /* RETR or STOR */
+int fd;
+{
+nwio_tcpconf_t tcpconf;
+nwio_tcpcl_t tcplopt, tcpcopt;
+char *tcp_device;
+int ftpdata_fd;
+char *buff;
+ipaddr_t ripaddr;
+tcpport_t rport;
+static tcpport_t lport = HTONS(0xF000);
+int s;
+int i;
+int cs;
+int pfd[2];
+char dummy;
+char port[32];
+
+   ripaddr = hostip;
+   rport = HTONS(20);
+
+   /* here we set up a connection to listen on if not passive mode */
+   /* otherwise we use this to connect for passive mode */
+
+   if((tcp_device = getenv("TCP_DEVICE")) == NULL)
+	tcp_device = "/dev/tcp";
+
+   if((ftpdata_fd = open(tcp_device, O_RDWR)) < 0) {
+	perror("ftp: open error on tcp device");
+	return(-1);
+   }
+
+   if(passive) {
+	s = DOcommand("PASV", "");
+	if(s != 227) {
+		close(ftpdata_fd);
+		return(s);
+	}
+	/* decode host and port */
+	buff = reply;
+	while(*buff && (*buff != '(')) buff++;
+	buff++;
+	ripaddr = (ipaddr_t)0;
+	for(i = 0; i < 4; i++) {
+		ripaddr = (ripaddr << 8) + (ipaddr_t)atoi(buff);
+		if((buff = strchr(buff, ',')) == (char *)0) {
+			printf("Could not parse PASV reply\n");
+			return(-1);
+		}
+		buff++;
+	}
+	rport = (tcpport_t)atoi(buff);
+	if((buff = strchr(buff, ',')) == (char *)0) {
+		printf("Could not parse PASV reply\n");
+		return(-1);
+	}
+	buff++;
+	rport = (rport << 8) + (tcpport_t)atoi(buff);
+	ripaddr = ntohl(ripaddr);
+	rport = ntohs(rport);
+   }
+
+   for (;;) {
+	tcpconf.nwtc_flags = NWTC_SET_RA | NWTC_SET_RP;
+	if (passive || ntohs(lport) >= 0xF000) {
+		tcpconf.nwtc_flags |= NWTC_LP_SEL;
+	} else {
+		/* For no good reason Sun hosts don't like it if they have to
+		 * connect to the same port twice in a short time...
+		 */
+		lport = htons(ntohs(lport) + 1);
+		tcpconf.nwtc_flags |= NWTC_LP_SET;
+		tcpconf.nwtc_locport = lport;
+	}
+
+	tcpconf.nwtc_remaddr = ripaddr;
+	tcpconf.nwtc_remport = rport;
+
+	s = ioctl(ftpdata_fd, NWIOSTCPCONF, &tcpconf);
+	if(s < 0) {
+		if (errno == EADDRINUSE) continue;
+		perror("ftp: ioctl error on NWIOSTCPCONF");
+		close(ftpdata_fd);
+		return(s);
+	}
+	break;
+   }
+
+   s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
+   if(s < 0) {
+	perror("ftp: ioctl error on NWIOGTCPCONF");
+	close(ftpdata_fd);
+	return(s);
+   }
+   lport = tcpconf.nwtc_locport;
+
+   if(passive) {
+	tcplopt.nwtcl_flags = 0;
+	s = ioctl(ftpdata_fd, NWIOTCPCONN, &tcpcopt);
+	if(s < 0) {
+		perror("ftp: error on ioctl NWIOTCPCONN");
+		close(ftpdata_fd);
+		return(0);
+	}
+	s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
+	if(s < 0) {
+		perror("ftp: error on ioctl NWIOGTCPCONF");
+		close(ftpdata_fd);
+		return(0);
+	}
+   } else {
+	tcplopt.nwtcl_flags = 0;
+
+	if (pipe(pfd) < 0) {
+		perror("ftp: could not create a pipe");
+		return(s);
+	}
+	lpid = fork();
+	if(lpid < 0) {
+		perror("ftp: could not fork listener");
+		close(ftpdata_fd);
+		close(pfd[0]);
+		close(pfd[1]);
+		return(s);
+	} else if(lpid == 0) {
+		close(pfd[0]);
+		signal(SIGALRM, donothing);
+		alarm(15);
+		close(pfd[1]);
+		s = ioctl(ftpdata_fd, NWIOTCPLISTEN, &tcplopt);
+		alarm(0);
+		if(s < 0)
+			if(errno == EINTR)
+				exit(1);	/* timed out */
+			else
+				exit(-1);	/* error */
+		else
+			exit(0);		/* connection made */
+	}
+	/* Wait for the pipe to close, then the listener is ready (almost). */
+	close(pfd[1]);
+	(void) read(pfd[0], &dummy, 1);
+	close(pfd[0]);
+	while(1) {
+		signal(SIGALRM, donothing);
+		alarm(1);
+		s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
+		alarm(0);
+		if(s == -1) break;
+	}
+   }
+
+#define hiword(x)       ((u16_t)((x) >> 16))
+#define loword(x)       ((u16_t)(x & 0xffff)) 
+#define hibyte(x)       (((x) >> 8) & 0xff)
+#define lobyte(x)       ((x) & 0xff)
+
+   if(!passive) {
+	sprintf(port, "%u,%u,%u,%u,%u,%u",
+		hibyte(hiword(ntohl(myip))), lobyte(hiword(ntohl(myip))),
+		hibyte(loword(ntohl(myip))), lobyte(loword(ntohl(myip))),
+		hibyte(ntohs(lport)), lobyte(ntohs(lport)));
+	s = DOcommand("PORT", port);
+	if(s != 200) {
+		close(ftpdata_fd);
+		kill(lpid, SIGKILL);
+		return(s);
+	}
+   }
+
+   s = DOcommand(datacom, file);
+   if(s == 125 || s == 150) {
+	if(!passive) {
+		while(1) {
+			s = wait(&cs);
+			if(s < 0 || s == lpid)
+				break;
+		}
+		if(s < 0) {
+			perror("wait error:");
+			close(ftpdata_fd);
+			kill(lpid, SIGKILL);
+			return(s);
+		}
+		if((cs & 0x00ff)) {
+			printf("Child listener failed %04x\n", cs);
+			close(ftpdata_fd);
+			return(-1);
+		}
+		cs = (cs >> 8) & 0x00ff;
+		if(cs == 1) {
+			printf("Child listener timed out\n");
+			return(DOgetreply());
+		} else if(cs) {
+			printf("Child listener returned %02x\n", cs);
+			close(ftpdata_fd);
+			return(-1);
+		}
+	}
+	switch(direction) {
+		case RETR:
+			s = recvfile(fd, ftpdata_fd);
+			break;
+		case STOR:
+			s = sendfile(fd, ftpdata_fd);
+			break;
+	}
+	close(ftpdata_fd);
+	s = DOgetreply();
+   } else {
+	if(!passive)
+		kill(lpid, SIGKILL);
+	close(ftpdata_fd);
+   }
+
+   return(s);
+}
Index: /trunk/minix/commands/ftp/net.h
===================================================================
--- /trunk/minix/commands/ftp/net.h	(revision 9)
+++ /trunk/minix/commands/ftp/net.h	(revision 9)
@@ -0,0 +1,13 @@
+/* net.h
+ *
+ * This file is part of ftp.
+ *
+ *
+ * 01/25/96 Initial Release	Michael Temari, <temari@ix.netcom.com>
+ */
+
+_PROTOTYPE(void NETinit, (void));
+_PROTOTYPE(int DOopen, (void));
+_PROTOTYPE(int DOclose, (void));
+_PROTOTYPE(int DOquit, (void));
+_PROTOTYPE(int DOdata, (char *datacom, char *file, int direction, int fd));
Index: /trunk/minix/commands/ftp/other.c
===================================================================
--- /trunk/minix/commands/ftp/other.c	(revision 9)
+++ /trunk/minix/commands/ftp/other.c	(revision 9)
@@ -0,0 +1,163 @@
+/* other.c by Michael Temari 06/21/92
+ *
+ * ftp          An ftp client program for use with TNET.
+ *
+ * Author:      Michael Temari, <temari@ix.netcom.com>
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+
+#include "ftp.h"
+#include "other.h"
+
+void FTPinit()
+{
+   linkopen = 0;
+   loggedin = 0;
+   type = TYPE_A;
+   format = 0;
+   mode = 0;
+   structure = 0;
+   passive = 0;
+   atty = isatty(0);
+}
+
+int DOpass()
+{
+int s;
+struct termios oldtty, newtty;
+char *pass;
+char password[64];
+
+   if(!linkopen) {
+	printf("You must \"OPEN\" a connection first.\n");
+	return(0);
+   }
+
+   pass = cmdargv[1];
+
+   if(cmdargc < 2) {
+	tcgetattr(fileno(stdout), &oldtty);
+	newtty = oldtty;
+	newtty.c_lflag &= ~ECHO;
+	tcsetattr(fileno(stdout), TCSANOW, &newtty);
+	readline("Password: ", password, sizeof(password));
+	tcsetattr(fileno(stdout), TCSANOW, &oldtty);
+	printf("\n");
+	pass = password;
+   }
+
+   s = DOcommand("PASS", pass);
+
+   if(s == 230)
+	loggedin = 1;
+
+   return(s);
+}
+
+int DOuser()
+{
+char *user;
+int s;
+char username[64];
+
+   if(!linkopen) {
+	printf("You must \"OPEN\" a connection first.\n");
+	return(0);
+   }
+
+   loggedin = 0;
+
+   user = cmdargv[1];
+
+   if(cmdargc < 2) {
+	readline("Username: ", username, sizeof(username));
+	user = username;
+   }
+
+   s = DOcommand("USER", user);
+
+   if(atty && s == 331) {
+   	cmdargv[0] = "password";
+   	cmdargc = 1;
+	return(DOpass());
+   }
+
+   if(s == 230)
+	loggedin = 1;
+
+   return(s);
+}
+
+int DOnoop()
+{
+   if(DOcmdcheck())
+	return(0);
+
+   return(DOcommand("NOOP", ""));
+}
+
+int DOpassive()
+{
+   passive = 1 - passive;
+
+   printf("Passive mode is now %s\n", (passive ? "ON" : "OFF"));
+
+   return(0);
+}
+
+int DOsyst()
+{
+   if(DOcmdcheck())
+	return(0);
+
+   return(DOcommand("SYST", ""));
+}
+
+int DOremotehelp()
+{
+   if(!linkopen) {
+	printf("You must \"OPEN\" a connection first.\n");
+	return(0);
+   }
+
+   return(DOcommand("HELP", ""));
+}
+
+int DOquote()
+{
+int i;
+static char args[512];
+
+   args[0] = '\0';
+
+   for(i = 2; i < cmdargc; i++) {
+	if(i != 2)
+		strcat(args, " ");
+	strcat(args, cmdargv[i]);
+   }
+
+   return(DOcommand(cmdargv[1], args));
+}
+
+int DOsite()
+{
+int i;
+static char args[512];
+
+   args[0] = '\0';
+
+   for(i = 1; i < cmdargc; i++) {
+   	if(i != 1)
+		strcat(args, " ");
+	strcat(args, cmdargv[i]);
+   }
+
+   return(DOcommand("SITE", args));
+}
Index: /trunk/minix/commands/ftp/other.h
===================================================================
--- /trunk/minix/commands/ftp/other.h	(revision 9)
+++ /trunk/minix/commands/ftp/other.h	(revision 9)
@@ -0,0 +1,17 @@
+/* other.h
+ *
+ * This file is part of ftp.
+ *
+ *
+ * 01/25/96 Initial Release	Michael Temari, <temari@ix.netcom.com>
+ */
+
+_PROTOTYPE(void FTPinit, (void));
+_PROTOTYPE(int DOpass, (void));
+_PROTOTYPE(int DOuser, (void));
+_PROTOTYPE(int DOnoop, (void));
+_PROTOTYPE(int DOpassive, (void));
+_PROTOTYPE(int DOsyst, (void));
+_PROTOTYPE(int DOremotehelp, (void));
+_PROTOTYPE(int DOquote, (void));
+_PROTOTYPE(int DOsite, (void));
Index: /trunk/minix/commands/ftpd200/Makefile
===================================================================
--- /trunk/minix/commands/ftpd200/Makefile	(revision 9)
+++ /trunk/minix/commands/ftpd200/Makefile	(revision 9)
@@ -0,0 +1,43 @@
+# Makefile for ftpd
+#
+# 01/25/96 Initial Release	Michael Temari, <Michael@TemWare.Com>
+# 2005-02-25 version 2.00
+
+CFLAGS=	-O -D_MINIX -D_POSIX_SOURCE -m
+LDFLAGS=-i
+BINDIR=	/usr/bin
+PROG=	in.ftpd
+MANDIR= /usr/man/man8
+MANPAGE=ftpd.8
+CC = exec cc
+
+OBJS=	ftpd.o access.o file.o net.o
+
+all:	$(PROG)
+
+$(PROG):	$(OBJS)
+	$(CC) $(LDFLAGS) -o $@ $(OBJS)
+	install -S 8kw $@
+
+clean:
+	rm -f $(PROG) $(OBJS)
+
+install:	$(BINDIR)/$(PROG) $(BINDIR)/setup.anonftp $(BINDIR)/ftpdsh
+
+$(BINDIR)/$(PROG):	$(PROG)
+	install -cs -o bin $? $@
+
+$(BINDIR)/setup.anonftp:	setup.anonftp
+	install -c -o bin $? $@
+
+$(BINDIR)/ftpdsh:	ftpdsh
+	install -m 755 -c -o bin $? $@
+
+ftpd.o:		ftpd.c   ftpd.h access.h file.h net.h
+access.o:	access.c ftpd.h access.h
+file.o:		file.c   ftpd.h access.h file.h net.h
+net.o:		net.c    ftpd.h                 net.h
+
+installman:	$(MANDIR)/$(MANPAGE)
+	cp $(MANPAGE) $(MANDIR)
+	echo "You may need to run makewhatis to update man page index"
Index: /trunk/minix/commands/ftpd200/README
===================================================================
--- /trunk/minix/commands/ftpd200/README	(revision 9)
+++ /trunk/minix/commands/ftpd200/README	(revision 9)
@@ -0,0 +1,35 @@
+ftpd200 --- FTP server program for Minix 2.0  
+written by Michael Temari <Michael@TemWare.Com> release 2.00 2005-02-25
+
+Full download: <a href="/pub/contrib/ftpd200.tar.Z">ftpd200.tar.Z</a>
+
+Ftpd is the File Transfer Protocol (FTP) server.  
+
+Important: Release 2.00 incorporates an improved mechanism to restrict
+execution of commands on the server.  This is done through use of a
+shell script, ftpdsh.  Any earlier ftpd version in use on a system
+accessible from the Internet should be upgraded at least to version 1.01,
+version 2.00 is preferable.
+
+Installation: unpack the tarball in /usr/local/src or another directory 
+of your choice:
+zcat < ftpd200.tar.Z | tar xvfp -
+
+The ftpd200 directory will be created.  Read the Makefile to see how
+the program is compiled and installed:
+
+make (or make ftpd) -- compiles the binary
+make install        -- installs /usr/bin/in.ftpd, and ftpdsh. Also installs 
+                       setup.anonftp script.  
+make installman     -- installs new ftpd.8 man page in /usr/local/man/man8
+
+The shell script setup.anonftp sets up and verifies configuration for
+anonymous ftp.  If you provide anonymous ftp you are letting anyone in
+the whole wide world execute a program on your computer.  You want to
+make sure it's set up correctly so outsiders can't mess with things
+they shouldn't.  
+
+This file is included as README in the source directory.  For more
+notes on compiling and installing, also please see the file README2.
+
+notes updated by asw 2005-02-25
Index: /trunk/minix/commands/ftpd200/README2
===================================================================
--- /trunk/minix/commands/ftpd200/README2	(revision 9)
+++ /trunk/minix/commands/ftpd200/README2	(revision 9)
@@ -0,0 +1,34 @@
+README2: additional notes on compiling and installing ftpd.
+
+Note that the Makefile install options will replace files in /usr/bin
+and /usr/man that were installed with the Minix distribution.  If you
+are not sure you want to do this you can either rename the original
+in.ftpd binary, the anonftp.* scripts, and the ftpd.8 man page to
+prevent them from being replaced, or you can edit the Makefile to
+change the directory values:
+  BINDIR= /usr/local/bin
+  MANDIR= /usr/local/man/man8
+ASW's practice is to rename binaries with a suffix that indicates the
+original distribution from which they were obtained, i.e., in.ftpd.203
+for the version distributed with Minix 2.0.3, or with a date code or a
+version number.
+
+If you are sure you want to replace the original ftpd provided with your
+distribution you  may want to copy the contents of the unpacked tarball
+to the main directory tree, in this case /usr/src/commands/ftpd, so that
+a new version will be compiled if you do a general recompilation of all 
+commands using "make all" or "make compile" in /usr/src. ASW's practice
+is generally to make a directory in /usr/local/src for new versions of
+major programs. 
+Also note that if you create a new man page where one did not exist
+previously you will need to run makewhatis to rebuild the whatis
+database, i.e.:
+  makewhatis /usr/man
+or
+  makewhatis /usr/local/man
+
+Important: the scripts for setting up and maintaining an anonymous ftp
+installation haven't been checked for a long time, I would appreciate 
+comments.
+
+ASW 2005-02-06
Index: /trunk/minix/commands/ftpd200/access.c
===================================================================
--- /trunk/minix/commands/ftpd200/access.c	(revision 9)
+++ /trunk/minix/commands/ftpd200/access.c	(revision 9)
@@ -0,0 +1,134 @@
+/* access.c Copyright 1992-2000 by Michael Temari All Rights Reserved
+ *
+ * This file is part of ftpd.
+ *
+ * This file handles:
+ *
+ *      USER PASS QUIT
+ *
+ *
+ * 01/25/96 Initial Release	Michael Temari, <Michael@TemWare.Com>
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+
+#include "ftpd.h"
+#include "access.h"
+
+_PROTOTYPE(static int AreWeIn, (char *name, struct passwd *pwd));
+
+static char *msg530 = "530 Not logged in.\r\n";
+
+/* Returns -1 = not logged in, 0 = loggedin */
+int ChkLoggedIn()
+{
+   if(!loggedin) {
+	printf(msg530);
+	return(-1);
+   } else
+	return(0);
+}
+
+/* what a USER! */
+int doUSER(buff)
+char *buff;
+{
+   loggedin = 0;
+   gotuser = 0;
+   strncpy(username, buff, sizeof(username));
+   username[sizeof(username)-1] = '\0';
+
+   if(*username == '\0') {
+	printf("501 Bad user name.\r\n");
+	return(GOOD);
+   }
+
+   gotuser = 1;
+
+   printf("331 Password required for %s.\r\n", username);
+
+   return(GOOD);
+}
+
+/* secret, secret, secret */
+int doPASS(buff)
+char *buff;
+{
+char *name;
+struct passwd *pwd;
+int bad=0;
+
+   name = username;
+
+   if(!strcmp(name, "anonymous"))
+	name = "ftp";
+
+   if(!gotuser || ((pwd = getpwnam(name)) == (struct passwd *)0))
+	bad = 1;
+   else
+	if(strcmp(name, "ftp")) {
+		if(!strcmp(pwd->pw_passwd, crypt("", pwd->pw_passwd)))
+			bad = 1;
+		if(strcmp(pwd->pw_passwd, crypt(buff, pwd->pw_passwd)))
+			bad = 1;
+	} else {
+		strncpy(anonpass, buff, sizeof(anonpass));
+		anonpass[sizeof(anonpass)-1] = '\0';
+	}
+
+   if(bad) {
+	logit("LOGIN", "FAIL");
+	printf(msg530);
+	return(GOOD);
+   }
+
+   return(AreWeIn(name, pwd));
+}
+
+/* bye, bye don't let the door hit you in the butt on the way out */
+int doQUIT(buff)
+char *buff;
+{
+   printf("221 Service closing, don't be a stranger.\r\n");
+
+   return(BAD);
+}
+
+/* see if this user is okay */
+static int AreWeIn(name, pwd)
+char *name;
+struct passwd *pwd;
+{
+   if(!strcmp(name, "ftp")) {
+	if(chroot(pwd->pw_dir)) {
+		logit("LOGIN", "FAIL");
+		printf("530 Not logged in, could not chroot.\r\n");
+		return(GOOD);
+	}
+	strncpy(newroot, pwd->pw_dir, sizeof(newroot));
+	newroot[sizeof(newroot)-1] = '\0';
+	anonymous = 1;
+	strcpy(pwd->pw_dir, "/");
+   }
+
+   if(setgid(pwd->pw_gid) || setuid(pwd->pw_uid) || chdir(pwd->pw_dir)) {
+	logit("LOGIN", "FAIL");
+	printf(msg530);
+	anonymous = 0;
+   } else {
+	logit("LOGIN", "PASS");
+	showmsg("230", (char *)NULL);
+	printf("230 User %s logged in, directory %s.\r\n",
+		username, pwd->pw_dir);
+	loggedin = 1;
+   }
+
+   return(GOOD);
+}
Index: /trunk/minix/commands/ftpd200/access.h
===================================================================
--- /trunk/minix/commands/ftpd200/access.h	(revision 9)
+++ /trunk/minix/commands/ftpd200/access.h	(revision 9)
@@ -0,0 +1,12 @@
+/* ftpd.h
+ *
+ * This file is part of ftpd.
+ *
+ *
+ * 01/25/96 Initial Release	Michael Temari, <Michael@TemWare.Com>
+ */
+
+_PROTOTYPE(int ChkLoggedIn, (void));
+_PROTOTYPE(int doUSER, (char *buff));
+_PROTOTYPE(int doPASS, (char *buff));
+_PROTOTYPE(int doQUIT, (char *buff));
Index: /trunk/minix/commands/ftpd200/build
===================================================================
--- /trunk/minix/commands/ftpd200/build	(revision 9)
+++ /trunk/minix/commands/ftpd200/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/ftpd200/file.c
===================================================================
--- /trunk/minix/commands/ftpd200/file.c	(revision 9)
+++ /trunk/minix/commands/ftpd200/file.c	(revision 9)
@@ -0,0 +1,1252 @@
+/* file.c Copyright 1992-2000 by Michael Temari All Rights Reserved
+ *
+ * This file is part of ftpd.
+ *
+ * This file handles:
+ *
+ *      ALLO APPE CDUP CWD  DELE LIST MDTM MODE MKD  NLST PWD REST RETR
+ *      RMD  RNFR RNTO SITE SIZE STAT STOR STOU STRU SYST TYPE
+ *
+ * 01/25/96 Initial Release	Michael Temari
+ * 03/09/00 			Michael Temari, <Michael@TemWare.Com>
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/tcp.h>
+
+#include "ftpd.h"
+#include "access.h"
+#include "file.h"
+#include "net.h"
+
+_PROTOTYPE(static int fdxcmd, (int cmd, char *arg));
+_PROTOTYPE(static int endfdxcmd, (int fd));
+_PROTOTYPE(static int asciisize, (char *filename, unsigned long *filesize));
+_PROTOTYPE(static int cnvtfile, (char *name, char **name2));
+_PROTOTYPE(static int procfile, (char *name));
+_PROTOTYPE(static unsigned long fsize, (char *fname));
+_PROTOTYPE(static int sendfile, (char *name, int xmode));
+_PROTOTYPE(static int recvfile, (char *name, int xmode));
+_PROTOTYPE(static char *uniqname, (void));
+_PROTOTYPE(static int docrc, (char *buff, int xmode));
+_PROTOTYPE(static int dofdet, (char *buff));
+_PROTOTYPE(static char *path, (char *fname));
+
+#define	SEND_FILE	0
+#define	SEND_NLST	1
+#define	SEND_LIST	2
+
+#define	RECV_FILE	0
+#define	RECV_APND	1
+#define	RECV_UNIQ	2
+
+#define	CNVT_ERROR	0
+#define	CNVT_NONE	1
+#define	CNVT_TAR	2
+#define	CNVT_TAR_Z	3
+#define	CNVT_COMP	4
+#define	CNVT_TAR_GZ	5
+#define	CNVT_GZIP	6
+#define	CNVT_UNCOMP	7
+
+
+#define	PROG_FTPDSH	"ftpdsh"
+#define	CMD_NLST	1
+#define	CMD_LIST	2
+#define	CMD_CRC		3
+
+static char *msg550 = "550 %s %s.\r\n";
+
+static unsigned long file_restart = 0;
+
+static char rnfr[256];
+static char buffer[8192];
+static char bufout[8192];
+
+static cmdpid = -1;
+
+/* allocate, we don't need no stink'n allocate */
+int doALLO(buff)
+char *buff;
+{
+   printf("202 ALLO command not needed at this site.\r\n");
+
+   return(GOOD);
+}
+
+/* append to a file if it exists */
+int doAPPE(buff)
+char *buff;
+{
+   return(recvfile(buff, RECV_APND));
+}
+
+/* change to parent directory */
+int doCDUP(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+	return(GOOD);
+
+   return(doCWD(".."));
+}
+
+/* change directory */
+int doCWD(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+	return(GOOD);
+
+   if(chdir(buff))
+	printf(msg550, buff, strerror(errno));
+   else {
+	showmsg("250", ".ftpd_msg");
+	printf("250 %s command okay.\r\n", line);
+   }
+
+   return(GOOD);
+}
+
+/* remove a file */
+int doDELE(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+	return(GOOD);
+
+   if(anonymous) {
+	printf("550 Command not allowed for anonymous user\r\n");
+	return(GOOD);
+   }
+
+   if(unlink(buff))
+	printf(msg550, buff, strerror(errno));
+   else {
+	printf("250 File \"%s\" deleted.\r\n", buff);
+	logit("DELE", path(buff));
+   }
+
+   return(GOOD);
+}
+
+/* directory listing */
+int doLIST(buff)
+char *buff;
+{
+   file_restart = 0;
+
+   return(sendfile(buff, SEND_LIST));
+}
+
+/* file modification time, btw when will this be put into an RFC */
+int doMDTM(buff)
+char *buff;
+{
+struct stat st;
+struct tm *t;
+
+   if(ChkLoggedIn())
+	return(GOOD);
+
+   if(stat(buff, &st)) {
+	printf(msg550, buff, strerror(errno));
+	return(GOOD);
+   }
+
+   if((st.st_mode & S_IFMT) != S_IFREG) {
+	printf("550 Not a regular file.\r\n");
+	return(GOOD);
+   }
+
+   t = gmtime(&st.st_mtime);
+
+   printf("215 %04d%02d%02d%02d%02d%02d\r\n",
+	t->tm_year+1900, t->tm_mon+1, t->tm_mday,
+	t->tm_hour, t->tm_min, t->tm_sec);
+
+   return(GOOD);
+}
+
+/* mode */
+int doMODE(buff)
+char *buff;
+{
+   switch(*buff) {
+	case 'b':
+	case 'B':
+		printf("200 Mode set to %c.\r\n", *buff);
+		mode = MODE_B;
+		break;
+	case 's':
+	case 'S':
+		printf("200 Mode set to %c.\r\n", *buff);
+		mode = MODE_S;
+		break;
+	default:
+		printf("501 Unknown mode %c.\r\n", *buff);
+   }
+
+   return(GOOD);
+}
+
+/* make a directory */
+int doMKD(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+	return(GOOD);
+
+   if(anonymous) {
+	printf("550 Command not allowed for anonymous user\r\n");
+	return(GOOD);
+   }
+
+   if(mkdir(buff, 0777))
+	printf(msg550, buff, strerror(errno));
+   else {
+	printf("257 \"%s\" directory created.\r\n", buff);
+	logit("MKD ", path(buff));
+   }
+
+   return(GOOD);
+}
+
+/* name listing */
+int doNLST(buff)
+char *buff;
+{
+   file_restart = 0;
+
+   return(sendfile(buff, SEND_NLST));
+}
+
+/* where are we */
+int doPWD(buff)
+char *buff;
+{
+char dir[128];
+
+   if(ChkLoggedIn())
+	return(GOOD);
+
+   if(getcwd(dir, sizeof(dir)) == (char *)NULL)
+	printf(msg550, buff, strerror(errno));
+   else
+	printf("257 \"%s\" is current directory.\r\n", dir);
+
+   return(GOOD);
+}
+
+/* restart command */
+int doREST(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+	return(GOOD);
+
+   file_restart = atol(buff);
+
+   printf("350 Next file transfer will restart at %lu.\r\n", file_restart);
+
+   return(GOOD);
+}
+
+/* they want a file */
+int doRETR(buff)
+char *buff;
+{
+   return(sendfile(buff, SEND_FILE));
+}
+
+/* remove a directory */
+int doRMD(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+	return(GOOD);
+
+   if(anonymous) {
+	printf("550 Command not allowed for anonymous user\r\n");
+	return(GOOD);
+   }
+
+   if(rmdir(buff))
+	printf(msg550, buff, strerror(errno));
+   else {
+	printf("250 Directory \"%s\" deleted.\r\n", buff);
+	logit("RMD ", path(buff));
+   }
+
+   return(GOOD);
+}
+
+/* rename from */
+int doRNFR(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+	return(GOOD);
+
+   if(anonymous) {
+	printf("550 Command not allowed for anonymous user\r\n");
+	return(GOOD);
+   }
+
+   strncpy(rnfr, buff, sizeof(rnfr));
+   rnfr[sizeof(rnfr)-1] = '\0';
+
+   printf("350 Got RNFR waiting for RNTO.\r\n");
+
+   return(GOOD);
+}
+
+/* rename to */
+int doRNTO(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+	return(GOOD);
+
+   if(anonymous) {
+	printf("550 Command not allowed for anonymous user\r\n");
+	return(GOOD);
+   }
+
+   if(rnfr[0] == '\0') {
+	printf("550 Rename failed.\r\n");
+	return(GOOD);
+   }
+
+   if(rename(rnfr, buff) < 0)
+	printf("550 Rename failed. Error %s\r\n", strerror(errno));
+   else {
+	printf("250 Renamed %s to %s.\r\n", rnfr, buff);
+	logit("RNFR", path(rnfr));
+	logit("RNTO", path(buff));
+   }
+
+   rnfr[0] = '\0';
+
+   return(GOOD);
+}
+
+/* xmode = 0 for multiline crc, xmode <> 0 for single file single line crc */
+static int docrc(buff, xmode)
+char *buff;
+int xmode;
+{
+unsigned short cs;
+long fs;
+int fd;
+int s;
+char *p;
+
+   if((fd = fdxcmd(CMD_CRC, buff)) < 0) {
+	printf("501 Could not obtain CRC.\r\n");
+	return(GOOD);
+   }
+
+   if(xmode == 0)
+	printf("202-SITE CRC \"%s\"\r\n", buff);
+
+   while(1) {
+	p = buffer;
+	while(1) {
+		if((s = read(fd, p, 1)) != 1) {
+			if(xmode == 0)
+				printf("202 SITE CRC DONE.\r\n");
+			else
+				printf("501 Could not obtain CRC.\r\n");
+			endfdxcmd(fd);
+			return(GOOD);
+		}
+		if(*p == '\n') {
+			*p++ = '\r';
+			*p++ = '\n';
+			*p = '\0';
+			break;
+		}
+		p++;
+	}
+	if(xmode != 0)
+		break;
+	printf("    %s", buffer);
+   }
+
+   cs = atoi(buffer);
+
+   fs = atol(buffer+6);
+
+   printf("202 CRC %05u %ld.\r\n", cs, fs);
+
+   endfdxcmd(fd);
+
+   return(GOOD);
+}
+
+/* site specific */
+int doSITE(buff)
+char *buff;
+{
+char *args;
+
+   if(ChkLoggedIn())
+	return(GOOD);
+
+
+   strncpy(line, buff, sizeof(line));
+   line[sizeof(line)-1] = '\0';
+
+   cvtline(&args);
+
+   if(!strcmp(line, "CRC") || !strcmp(line, "CCRC"))
+	return(docrc(args, strcmp(line, "CRC")));
+
+   if(!strcmp(line, "FDET"))
+	return(dofdet(args));
+
+   printf("501 Unknown SITE command %s.\r\n", line);
+
+   return(GOOD);
+}
+
+static unsigned long fsize(fname)
+char *fname;
+{
+struct stat st;
+unsigned long fs = 0L;
+
+   if(stat(fname, &st))
+	return(fs);
+
+   if((st.st_mode & S_IFMT) != S_IFREG)
+	return(fs);
+
+   if(type == TYPE_A)
+	return(fs);
+
+   fs = st.st_size;
+
+   return(fs);
+}
+
+/* file size, btw when will this be put into an RFC */
+int doSIZE(buff)
+char *buff;
+{
+struct stat st;
+unsigned long filesize;
+
+   if(ChkLoggedIn())
+	return(GOOD);
+
+   if(stat(buff, &st)) {
+	printf(msg550, buff, strerror(errno));
+	return(GOOD);
+   }
+
+   if((st.st_mode & S_IFMT) != S_IFREG) {
+	printf("550 Not a regular file.\r\n");
+	return(GOOD);
+   }
+
+   filesize = st.st_size;
+
+   if(type == TYPE_A)
+	if(asciisize(buff, &filesize))
+		return(GOOD);
+
+   printf("215 %lu\r\n", filesize);
+
+   return(GOOD);
+}
+
+/* server status, or file status */
+int doSTAT(buff)
+char *buff;
+{
+time_t now;
+struct tm *tm;
+int fd;
+int s;
+
+   if(!*buff) {
+	(void) time(&now);
+	tm = localtime(&now);
+	printf("211-%s(%s:%u) FTP server status:\r\n",
+		myhostname, inet_ntoa(myipaddr), ntohs(myport));
+	printf("    Version %s  ", FtpdVersion);
+	printf("%s, %02d %s %d %02d:%02d:%02d %s\r\n", days[tm->tm_wday],
+		tm->tm_mday, months[tm->tm_mon], 1900+tm->tm_year,
+		tm->tm_hour, tm->tm_min, tm->tm_sec, tzname[tm->tm_isdst]);
+	printf("    Connected to %s:%u\r\n", inet_ntoa(rmtipaddr), ntohs(rmtport));
+	if(!loggedin)
+		printf("    Not logged in\r\n");
+	else
+		printf("    Logged in %s\r\n", username);
+	printf("    MODE: %s\r\n",(mode == MODE_B) ? "Block" : "Stream");
+	printf("    TYPE: %s\r\n",(type == TYPE_A) ? "Ascii" : "Binary");
+	printf("211 End of status\r\n");
+	return(GOOD);
+   }
+
+   if(ChkLoggedIn())
+	return(GOOD);
+
+   printf("211-Status of %s:\r\n", buff);
+
+   if((fd = fdxcmd(CMD_LIST, buff)) < 0)
+	printf("   Could not retrieve status");
+   else {
+	while((s = read(fd, buffer, 1)) == 1) {
+		if(*buffer == '\n')
+			printf("\r\n");
+		else
+			printf("%c", *buffer);
+	}
+	endfdxcmd(fd);
+   }
+
+   printf("211 End of status\r\n");
+
+   return(GOOD);
+}
+
+/* hey look, we're getting a file */
+int doSTOR(buff)
+char *buff;
+{
+   return(recvfile(buff, RECV_FILE));
+}
+
+/* hey, get a file unique */
+int doSTOU(buff)
+char *buff;
+{
+   return(recvfile(buff, RECV_UNIQ));
+}
+
+/* structure */
+int doSTRU(buff)
+char *buff;
+{
+   switch(*buff) {
+	case 'f':
+	case 'F':
+		printf("200 Structure set to %c.\r\n", *buff);
+		break;
+	default:
+		printf("501 Unknown structure %c.\r\n", *buff);
+   }
+
+   return(GOOD);
+}
+
+/* we're UNIX and proud of it! */
+int doSYST(buff)
+char *buff;
+{
+   printf("215 UNIX Type: L8\r\n");
+
+   return(GOOD);
+}
+
+/* change transfer type */
+int doTYPE(buff)
+char *buff;
+{
+   if(*(buff+1) != '\0') {
+	printf("501 Syntax error in parameters.\r\n");
+	return(GOOD);
+   }
+
+   switch(*buff) {
+	case 'A':
+	case 'a':
+		type = TYPE_A;
+		printf("200 Type set to A.\r\n");
+		break;
+	case 'I':
+	case 'i':
+		type = TYPE_I;
+		printf("200 Type set to I.\r\n");
+		break;
+	default:
+		printf("501 Invalid type %c.\r\n", *buff);
+   }
+
+   return(GOOD);
+}
+
+static int fdxcmd(cmd, arg)
+int   cmd;
+char *arg;
+{
+char xcmd[3];
+char *argv[5];
+int fds[2];
+char *smallenv[] = { "PATH=/bin:/usr/bin:/usr/local/bin", NULL, NULL };
+
+   if((smallenv[1] = getenv("TZ")) != NULL) smallenv[1] -= 3;	/* ouch... */
+
+   sprintf(xcmd, "%d", cmd);
+
+   argv[0] = PROG_FTPDSH;
+   argv[1] = xcmd;
+   argv[2] = arg;
+   argv[3] = (char *)NULL;
+
+   if(pipe(fds) < 0)
+	return(-1);
+
+   if((cmdpid = fork()) < 0) {
+	close(fds[0]);
+	close(fds[1]);
+	return(-1);
+   }
+
+   if(cmdpid == 0) { /* Child */
+	close(fds[0]);
+	close(0);
+	open("/dev/null", O_RDONLY);
+	dup2(fds[1], 1);
+	dup2(fds[1], 2);
+	close(fds[1]);
+	sprintf(argv[0], "/bin/%s", PROG_FTPDSH);
+	execve(argv[0], argv, smallenv);
+	sprintf(argv[0], "/usr/bin/%s", PROG_FTPDSH);
+	execve(argv[0], argv, smallenv);
+	sprintf(argv[0], "/usr/local/bin/%s", PROG_FTPDSH);
+	execve(argv[0], argv, smallenv);
+	exit(0);
+   }
+
+   close(fds[1]);
+
+   return(fds[0]);
+}
+
+/* Same as close if not cmd child started */
+static int endfdxcmd(fd)
+int fd;
+{
+int s;
+int cs;
+
+   close(fd);
+
+   if(cmdpid == -1)
+	return(0);
+
+   s = waitpid(cmdpid, &cs, 0);
+
+   cmdpid = -1;
+
+   return(0);
+}
+
+/* returns -1 = size could not be determined, */
+/*          0 = size determined and in filesize */
+static int asciisize(filename, filesize)
+char *filename;
+unsigned long *filesize;
+{
+unsigned long count;
+int fd;
+char *p, *pp;
+int cnt;
+
+   if((fd = open(filename, O_RDONLY)) < 0) {
+	printf(msg550, filename, strerror(errno));
+	return(-1);
+   }
+
+   count = 0;
+
+   while((cnt = read(fd, buffer, sizeof(buffer))) > 0) {
+	count += cnt;
+	p = buffer;
+	while(cnt > 0)
+		if((pp = memchr(p, '\n', cnt)) != (char *)NULL) {
+			count++;
+			cnt = cnt - 1 - (pp - p);
+			p = pp + 1;
+		} else
+			break;
+   }
+
+   if(cnt == 0) {
+	*filesize = count;
+	close(fd);
+	return(0);
+   }
+
+   printf(msg550, filename, strerror(errno));
+
+   close(fd);
+
+   return(-1);
+}
+
+/* see if we need to run a command to convert the file */
+static int cnvtfile(name, name2)
+char *name;
+char **name2;
+{
+struct stat st;
+static char fname[256];
+char *p;
+int cmode;
+
+   if(!stat(name, &st))			/* file exists can't be a conversion */
+   	if((st.st_mode & S_IFMT) != S_IFREG) {	/* must be regular file */
+		printf("550 Not a regular file.\r\n");
+		return(CNVT_ERROR);
+	} else
+		return(CNVT_NONE);
+
+   if(errno != ENOENT) {	/* doesn't exist is okay, others are not */
+	printf(msg550, name, strerror(errno));
+	return(CNVT_ERROR);
+   }
+
+   /* find out what kind of conversion */
+   strncpy(fname, name, sizeof(fname));
+   fname[sizeof(fname)-1] = '\0';
+
+   p = fname + strlen(fname);
+   cmode = CNVT_ERROR;
+   while(p > fname && cmode == CNVT_ERROR) {
+	if(*p == '.') {
+		if(!strcmp(p, ".tar"))
+			cmode = CNVT_TAR;
+		else
+		if(!strcmp(p, ".tar.Z"))
+			cmode = CNVT_TAR_Z;
+		else
+		if(!strcmp(p, ".Z"))
+			cmode = CNVT_COMP;
+		else
+		if(!strcmp(p, ".tar.gz"))
+			cmode = CNVT_TAR_GZ;
+		else
+		if(!strcmp(p, ".gz"))
+			cmode = CNVT_GZIP;
+
+		if (cmode != CNVT_ERROR) {
+			/* is there a file to convert? */
+			*p = '\0';
+			if (!stat(fname, &st)) break;
+			*p = '.';
+			cmode = CNVT_ERROR;
+		}
+	}
+	p--;
+   }
+
+   if(cmode == CNVT_ERROR) {
+	printf(msg550, fname, strerror(errno));
+	return(CNVT_ERROR);
+   }
+
+   if(cmode == CNVT_COMP || cmode == CNVT_GZIP || cmode == CNVT_UNCOMP)
+	if((st.st_mode & S_IFMT) != S_IFREG) {
+		printf("550 Not a regular file.\r\n");
+		return(CNVT_ERROR);
+	}
+
+   *name2 = fname;
+
+   return(cmode);
+}
+
+static int procfile(name)
+char *name;
+{
+int cmd;
+int fd;
+char *name2;
+
+   cmd = cnvtfile(name, &name2);
+
+   switch(cmd) {
+	case CNVT_TAR:
+		fd = fdxcmd(cmd + 10, name2);
+		break;
+	case CNVT_TAR_Z:
+		fd = fdxcmd(cmd + 10, name2);
+		break;
+	case CNVT_COMP:
+		fd = fdxcmd(cmd + 10, name2);
+		break;
+	case CNVT_TAR_GZ:
+		fd = fdxcmd(cmd + 10, name2);
+		break;
+	case CNVT_GZIP:
+		fd = fdxcmd(cmd + 10, name2);
+		break;
+	case CNVT_UNCOMP:
+		fd = fdxcmd(cmd + 10, name2);
+		break;
+	case CNVT_NONE:
+		fd = open(name, O_RDONLY);
+		break;
+	case CNVT_ERROR:
+	default:
+		return(-1);
+   }
+
+   if(fd < 0)
+	printf(msg550, name, strerror(errno));
+
+   return(fd);
+}
+
+/* oh no, they're taking a file */
+static int sendfile(name, xmode)
+char *name;
+int xmode;
+{
+char *fname;
+int fd, s;
+time_t datastart, dataend;
+unsigned long datacount;
+long kbs;
+char c;
+char *p;
+char *op, *ope;
+off_t sp;
+int doascii;
+unsigned long fs;
+char block[3];
+
+   if(ChkLoggedIn()) 
+	return(GOOD);
+
+   switch(xmode) {
+	case SEND_NLST:
+		fname = "NLST";
+		fd = fdxcmd(CMD_NLST, name);
+		if(fd < 0)
+			printf(msg550, name, strerror(errno));
+		break;
+	case SEND_LIST:
+		fname = "LIST";
+		fd = fdxcmd(CMD_LIST, name);
+		if(fd < 0)
+			printf(msg550, name, strerror(errno));
+		break;
+	default:
+		fname = name;
+		fd = procfile(name);
+		if(fd < 0)
+			logit("FAIL", path(fname));
+		else
+			logit("SEND", path(fname));
+   }
+
+   if(fd < 0)
+	return(GOOD);
+
+   /* set file position at approriate spot */
+   if(file_restart) {
+	if(type == TYPE_A) {
+		sp = 0;
+		while(sp < file_restart) {
+			sp++;
+			s = read(fd, buffer, 1);
+			if(s < 0) {
+				printf(msg550, fname, strerror(errno));
+				endfdxcmd(fd);
+				file_restart = 0;
+				return(GOOD);
+			}
+			if(s == 0) break;
+			if(*buffer == '\n')
+				sp++;
+		}
+	} else {
+		sp = lseek(fd, file_restart, SEEK_SET);
+		if(sp == -1) {
+			printf(msg550, fname, strerror(errno));
+			endfdxcmd(fd);
+			file_restart = 0;
+			return(GOOD);
+		}
+	}
+	if(sp != file_restart) {
+		printf("550 File restart point error. %lu not %lu\r\n", sp, file_restart);
+		endfdxcmd(fd);
+		file_restart = 0;
+		return(GOOD);
+	}
+   }
+   file_restart = 0;
+
+   fs = fsize(fname);
+   if(fs == 0L)
+	printf("%03d File %s okay.  Opening data connection.\r\n",
+		ftpdata_fd >= 0 ? 125 : 150, fname);
+   else
+	printf("%03d Opening %s mode data connection for %s (%ld bytes).\r\n",
+		ftpdata_fd >= 0 ? 125 : 150,
+		type == TYPE_A ? "ASCII" : "BINARY",
+		fname, fs);
+   fflush(stdout);
+
+#ifdef DEBUG
+   fprintf(logfile, "After 125/150 b4 DataConnect\n");
+   fflush(logfile);
+#endif
+
+   if(DataConnect()) {
+	endfdxcmd(fd);
+	return(GOOD);
+   }
+
+#ifdef DEBUG
+   fprintf(logfile, "After DataConnect\n");
+   fflush(logfile);
+   fprintf(logfile, "ftpd: parent %d start sendfile \n", getpid());
+   fflush(logfile);
+#endif
+
+   /* start transfer */
+   doascii = (type == TYPE_A) ||
+   	((xmode == SEND_LIST) || (xmode == SEND_NLST)); /* per RFC1123 4.1.2.7 */
+   datacount = 0;
+   time(&datastart);
+   op = bufout; ope = bufout + sizeof(bufout) - 3;
+   while((s = read(fd, buffer, sizeof(buffer))) > 0) {
+#ifdef DEBUG
+	fprintf(logfile, "sendfile read %d\n", s); fflush(logfile);
+#endif
+	datacount += s;
+	if(doascii) {
+		p = buffer;
+		while(s-- > 0) {
+			c = *p++;
+			if(c == '\n') {
+				*op++ = '\r';
+				datacount++;
+			}
+			*op++ = c;
+			if(op >= ope) {
+				if(mode == MODE_B) {
+					block[0] = '\0';
+					*(u16_t *)&block[1] = htons(op - bufout);
+					write(ftpdata_fd, block, sizeof(block));
+				}
+				write(ftpdata_fd, bufout, op - bufout);
+				op = bufout;
+			}
+		}
+	} else {
+		if(mode == MODE_B) {
+			block[0] = '\0';
+			*(u16_t *)&block[1] = htons(s);
+			write(ftpdata_fd, block, sizeof(block));
+		}
+		s = write(ftpdata_fd, buffer, s);
+	}
+   }
+   if(op > bufout) {
+	if(mode == MODE_B) {
+		block[0] = MODE_B_EOF;
+		*(u16_t *)&block[1] = htons(op - bufout);
+		write(ftpdata_fd, block, sizeof(block));
+	}
+	write(ftpdata_fd, bufout, op - bufout);
+   } else
+	if(mode == MODE_B) {
+		block[0] = MODE_B_EOF;
+		*(u16_t *)&block[1] = htons(0);
+		write(ftpdata_fd, block, sizeof(block));
+	}
+   time(&dataend);
+
+#ifdef DEBUG
+   fprintf(logfile, "ftpd: parent %d end sendfile \n", getpid());
+   fflush(logfile);
+#endif
+
+   endfdxcmd(fd);
+   if(mode != MODE_B) {
+	close(ftpdata_fd); 
+	ftpdata_fd = -1;
+   }
+
+   if(dataend == datastart) dataend++;
+   kbs = (datacount * 100 / (dataend - datastart)) / 1024;
+
+   if(s < 0)
+	printf("451 Transfer aborted.\r\n");
+   else
+	printf("%03d Transfer finished successfully. %ld.%02d KB/s\r\n",
+		mode == MODE_B ? 250 : 226,
+		(long)(kbs / 100), (int)(kbs % 100));
+
+   return(GOOD);
+}
+
+static int recvfile(name, xmode)
+char *name;
+int xmode;
+{
+char *fname;
+time_t datastart, dataend;
+unsigned long datacount;
+long kbs;
+char c;
+char *p;
+char *op, *ope;
+int fd, oflag;
+int s;
+int gotcr;
+off_t sp;
+char block[3];
+unsigned short cnt;
+
+   if(ChkLoggedIn())
+	return(GOOD);
+
+   fname = name;
+
+   switch(xmode) {
+	case RECV_APND:
+		oflag = O_WRONLY | O_APPEND;
+		break;
+	case RECV_UNIQ:
+		fname = uniqname();
+		oflag = O_WRONLY | O_CREAT;
+		break;
+	default:
+		oflag = O_WRONLY | O_CREAT | O_TRUNC;
+   }
+
+   if(file_restart)
+	oflag = O_RDWR;
+
+   fd = open(fname, oflag, (anonymous ? 0000:0600));
+
+   if(fd < 0) {
+	printf(msg550, fname, strerror(errno));
+	return(GOOD);
+   }
+
+   /* log the received file */
+   logit("RECV", path(fname));
+
+   /* set file position at approriate spot */
+   if(file_restart) {
+	if(type == TYPE_A) {
+		sp = 0;
+		while(sp < file_restart) {
+			sp++;
+			s = read(fd, buffer, 1);
+			if(s < 0) {
+				printf(msg550, fname, strerror(errno));
+				close(fd);
+				file_restart = 0;
+				return(GOOD);
+			}
+			if(s == 0) break;
+			if(*buffer == '\n')
+				sp++;
+		}
+	} else {
+		sp = lseek(fd, file_restart, SEEK_SET);
+		if(sp == -1) {
+			printf(msg550, fname, strerror(errno));
+			close(fd);
+			file_restart = 0;
+			return(GOOD);
+		}
+	}
+	if(sp != file_restart) {
+		printf("550 File restart point error. %lu not %lu\r\n", sp, file_restart);
+		close(fd);
+		file_restart = 0;
+		return(GOOD);
+	}
+   }
+   file_restart = 0;
+
+   if(xmode == RECV_UNIQ)
+   	printf("%03d FILE: %s\r\n",
+   		ftpdata_fd >= 0 ? 125 : 150, fname);	/* per RFC1123 4.1.2.9 */
+   else
+	printf("%03d File %s okay.  Opening data connection.\r\n",
+		ftpdata_fd >= 0 ? 125 : 150, fname);
+   fflush(stdout);
+
+   if(DataConnect()) {
+   	close(fd);
+	return(GOOD);
+   }
+
+#ifdef DEBUG
+   fprintf(logfile, "ftpd: parent %d start recvfile \n", getpid());
+   fflush(logfile);
+#endif
+
+   /* start receiving file */
+   datacount = 0;
+   gotcr = 0;
+   op = bufout; ope = bufout + sizeof(bufout) - 3;
+   cnt = 0;
+   time(&datastart);
+   while(1) {
+   	if(mode != MODE_B)
+   		cnt = sizeof(buffer);
+   	else
+   		if(cnt == 0) {
+   			s = read(ftpdata_fd, block, sizeof(block));
+   			cnt = ntohs(*(u16_t *)&block[1]);
+   			s = 0;
+   			if(cnt == 0 && block[0] & MODE_B_EOF)
+   				break;
+   		}
+	s = read(ftpdata_fd, buffer, cnt > sizeof(buffer) ? sizeof(buffer) : cnt);
+	if(s <= 0) break;
+	cnt -= s;
+	datacount += (long)s;
+	if(type == TYPE_A) {
+		p = buffer;
+		while(s-- > 0) {
+			c = *p++;
+			if(gotcr) {
+				gotcr = 0;
+				if(c != '\n')
+					*op++ = '\r';
+			}
+			if(c == '\r')
+				gotcr = 1;
+			else
+				*op++ = c;
+			if(op >= ope) {
+				write(fd, bufout, op - bufout);
+				op = bufout;
+			}
+		}
+	} else
+		write(fd, buffer, s);
+	if(cnt == 0 && mode == MODE_B && block[0] & MODE_B_EOF) {
+		s = 0;
+		break;
+	}
+   }
+   if(gotcr)
+	*op++ = '\r';
+   if(op > bufout)
+	write(fd, bufout, op - bufout);
+   time(&dataend);
+
+#ifdef DEBUG
+   fprintf(logfile, "ftpd: parent %d end recvfile \n", getpid());
+   fflush(logfile);
+#endif
+
+   close(fd);
+   if(mode != MODE_B) {
+	close(ftpdata_fd); 
+	ftpdata_fd = -1;
+   }
+
+   if(dataend == datastart) dataend++;
+   kbs = (datacount * 100 / (dataend - datastart)) / 1024;
+
+   if((mode == MODE_B && cnt != 0) || s != 0)
+	printf("451 Transfer aborted.\r\n");
+   else {
+	printf("%03d Transfer finished successfully. ",
+		mode == MODE_B ? 250 : 226);
+	if(xmode == RECV_UNIQ)
+		printf("Unique file %s. ", fname);
+	printf("%ld.%02d KB/s\r\n", (long)(kbs / 100), (int)(kbs % 100));
+   }
+
+   return(GOOD);
+}
+
+static char *uniqname()
+{
+static char uniq[32];
+int i;
+struct stat st;
+
+   for(i = 0; i < 1000; i++) {
+	sprintf(uniq, "ftpd%d%d", getpid(), i);
+	if(stat(uniq, &st) == -1)
+		return(uniq);
+   }
+   return(uniq);
+}
+
+static char *spath[256];
+static char *path(fname)
+char *fname;
+{
+char dir[128];
+
+   if(getcwd(dir, sizeof(dir)) == (char *)NULL)
+	sprintf(dir, "???");
+
+   if(fname[0] == '/')
+	sprintf((char *)spath, "%s%s", newroot, fname);
+   else
+	if(dir[1] == '\0')
+		sprintf((char *)spath, "%s%s%s", newroot, dir, fname);
+	else
+		sprintf((char *)spath, "%s%s/%s", newroot, dir, fname);
+
+   return((char *)spath);
+}
+
+/* do file detail */
+static int dofdet(buff)
+char *buff;
+{
+struct stat st;
+char ft;
+
+   if(ChkLoggedIn())
+	return(GOOD);
+
+   if(stat(buff, &st)) {
+	printf("501 Could not obtain file detail.\r\n");
+	return(GOOD);
+   }
+   switch(st.st_mode & S_IFMT) {
+   	case S_IFIFO:	ft = 'p'; break;
+   	case S_IFCHR:	ft = 'c'; break;
+   	case S_IFDIR:	ft = 'd'; break;
+   	case S_IFBLK:	ft = 'b'; break;
+   	case S_IFREG:	ft = 'f'; break;
+   	default:	ft = '?'; break;
+   }
+   printf("202 %c %u %u %u %u %u %lu %lu\r\n", 
+   	ft,					/* file type */
+   	st.st_rdev >> 8,			/* Major */
+   	st.st_rdev & 0xff,			/* Minor */
+   	st.st_uid,				/* UID */
+   	st.st_gid,				/* GID */
+   	st.st_mode,				/* File Modes */
+   	st.st_size,				/* SIZE */
+   	st.st_mtime);				/* Mod Time */
+
+   return(GOOD);
+}
Index: /trunk/minix/commands/ftpd200/file.h
===================================================================
--- /trunk/minix/commands/ftpd200/file.h	(revision 9)
+++ /trunk/minix/commands/ftpd200/file.h	(revision 9)
@@ -0,0 +1,32 @@
+/* file.h Copyright 1992-2000 by Michael Temari All Rights Reserved
+ *
+ * This file is part of ftpd.
+ *
+ *
+ * 01/25/96 Initial Release	Michael Temari, <Michael@TemWare.Com>
+ */
+
+_PROTOTYPE(int doALLO, (char *buff));
+_PROTOTYPE(int doAPPE, (char *buff));
+_PROTOTYPE(int doCDUP, (char *buff));
+_PROTOTYPE(int doCWD,  (char *buff));
+_PROTOTYPE(int doDELE, (char *buff));
+_PROTOTYPE(int doLIST, (char *buff));
+_PROTOTYPE(int doMDTM, (char *buff));
+_PROTOTYPE(int doMODE, (char *buff));
+_PROTOTYPE(int doMKD,  (char *buff));
+_PROTOTYPE(int doNLST, (char *buff));
+_PROTOTYPE(int doPWD,  (char *buff));
+_PROTOTYPE(int doREST, (char *buff));
+_PROTOTYPE(int doRETR, (char *buff));
+_PROTOTYPE(int doRMD,  (char *buff));
+_PROTOTYPE(int doRNFR, (char *buff));
+_PROTOTYPE(int doRNTO, (char *buff));
+_PROTOTYPE(int doSITE, (char *buff));
+_PROTOTYPE(int doSIZE, (char *buff));
+_PROTOTYPE(int doSTAT, (char *buff));
+_PROTOTYPE(int doSTOR, (char *buff));
+_PROTOTYPE(int doSTOU, (char *buff));
+_PROTOTYPE(int doSTRU, (char *buff));
+_PROTOTYPE(int doSYST, (char *buff));
+_PROTOTYPE(int doTYPE, (char *buff));
Index: /trunk/minix/commands/ftpd200/ftpd.8
===================================================================
--- /trunk/minix/commands/ftpd200/ftpd.8	(revision 9)
+++ /trunk/minix/commands/ftpd200/ftpd.8	(revision 9)
@@ -0,0 +1,161 @@
+.\" Copyright (c) 1985 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)ftpd.8c	6.4 (Berkeley) 5/28/86
+.\"
+.TH FTPD 8
+.SH NAME
+ftpd, in.ftpd, ftpdsh, setup.anonftp \- DARPA Internet File Transfer Protocol server
+.SH SYNOPSIS
+.B "ftp stream tcp nowait root /usr/bin/in.ftpd in.ftpd"
+.br
+.B "tcpd ftp /usr/bin/in.ftpd"
+.SH DESCRIPTION
+.B Ftpd
+is the DARPA Internet File Transfer Prototocol
+server process.  The server uses the TCP protocol
+and listens at the port specified in the ``ftp''
+service specification; see
+.BR services (5).
+.PP
+The ftp server currently supports the following ftp
+requests;  case is not distinguished.
+.PP
+.nf
+.ta \w'Request        'u
+\fBRequest	Description\fP
+ABOR	abort previous command
+ACCT	specify account (ignored)
+ALLO	allocate storage (vacuously)
+APPE	append to a file
+CDUP	change to parent of current working directory
+CWD	change working directory
+DELE	delete a file
+HELP	give help information
+LIST	give list files in a directory (``ls -lA'')
+MKD	make a directory
+MODE	specify data transfer \fImode\fP
+NLST	give name list of files in directory (``ls'')
+NOOP	do nothing
+PASS	specify password
+PASV	prepare for server-to-server transfer
+PORT	specify data connection port
+PWD	print the current working directory
+QUIT	terminate session
+RETR	retrieve a file
+RMD	remove a directory
+RNFR	specify rename-from file name
+RNTO	specify rename-to file name
+STOR	store a file
+STOU	store a file with a unique name
+STRU	specify data transfer \fIstructure\fP
+TYPE	specify data transfer \fItype\fP
+USER	specify user name
+XCUP	change to parent of current working directory
+XCWD	change working directory
+XMKD	make a directory
+XPWD	print the current working directory
+XRMD	remove a directory
+.fi
+.PP
+The remaining ftp requests specified in Internet RFC 959 are
+recognized, but not implemented.
+.PP
+The ftp server will abort an active file transfer only when the
+ABOR command is preceded by a Telnet "Interrupt Process" (IP)
+signal and a Telnet "Synch" signal in the command Telnet stream,
+as described in Internet RFC 959.
+.PP
+.B Ftpd
+interprets file names according to the ``globbing''
+conventions used by
+.BR csh (1).
+This allows users to utilize the metacharacters ``*?[]{}~''.
+.PP
+.B Ftpd
+authenticates users according to two rules. 
+.IP 1)
+The user name must be in the password data base,
+.BR /etc/passwd ,
+and not have a null password.  In this case a password
+must be provided by the client before any file operations
+may be performed.
+.IP 2)
+If the user name is ``anonymous'' or ``ftp'', an
+anonymous ftp account must be present in the password
+file (user ``ftp'').  In this case the user is allowed
+to log in by specifying any password (by convention this
+is given as the client host's name).
+.PP
+In the last case, 
+.B ftpd
+takes special measures to restrict the client's access privileges.
+The server performs a 
+.BR chroot (2)
+command to the home directory of the ``ftp'' user.
+In order that system security is not breached, it is recommended
+that the ``ftp'' subtree be constructed with care;  the following
+rules are recommended.
+.IP ~ftp)
+Make the home directory owned by ``ftp'' and unwritable by anyone.
+.IP ~ftp/bin)
+Make this directory owned by the super-user and unwritable by
+anyone.  The program
+.BR ls (1)
+must be present to support the list commands.  
+Also, 
+.BR crc (1) 
+must be present to support generating crcs using the site command, 
+.BR tar (1)
+and 
+.BR compress (1)
+must be present to support on-the-fly generation of .tar and .tar.Z archives, 
+.BR gzip (1)
+must be present to support gzip compression, and 
+.BR sh (1)
+must be present to support 
+.BR ftpdsh (8)
+which also must be present. 
+.BR ftpdsh controls which binaries can be used.
+These programs should all have mode 111.
+.IP ~ftp/etc)
+Make this directory owned by the super-user and unwritable by
+anyone.  The files
+.BR passwd (5)
+and
+.BR group (5)
+must be present for the 
+.B ls
+command to work properly.  These files should be mode 444. They can (and 
+should) be stripped down versions so as not to reveal names of users who
+are not owners of files in the ~ftp/pub directory tree. 
+.IP ~ftp/pub)
+Make this directory mode 755 and owned by the super-user.  Create
+directories in it owned by users if those users want to manage an
+anonymous ftp directory.
+.IP ~ftp/pub/incoming)
+Optionally create this directory for anonymous uploads.  Make it mode
+777.  The FTP daemon will create files with mode 266, so remote users
+can write a file, but only local users can do something with it.
+.PP
+The script
+.B setup.anonftp
+can be used to create or check an anonymous FTP tree.
+.SH "SEE ALSO"
+.BR ftp (1).
+.SH BUGS
+The anonymous account is inherently dangerous and should
+avoided when possible.
+.ig \" Minix doesn't have privileged port numbers (yet?)
+.PP
+The server must run as the super-user
+to create sockets with privileged port numbers.  It maintains
+an effective user id of the logged in user, reverting to
+the super-user only when binding addresses to sockets.  The
+possible security holes have been extensively
+scrutinized, but are possibly incomplete.
+..
+.\" man page updated by Al Woodhull 2005-02-25
+
+
Index: /trunk/minix/commands/ftpd200/ftpd.c
===================================================================
--- /trunk/minix/commands/ftpd200/ftpd.c	(revision 9)
+++ /trunk/minix/commands/ftpd200/ftpd.c	(revision 9)
@@ -0,0 +1,405 @@
+/* ftpd.c Copyright 1992-2000 by Michael Temari All Rights Reserved
+ *
+ * ftpd         An FTP server program for use with Minix.
+ *
+ * Usage:       Minix usage: tcpd ftp ftpd
+ *
+ * 06/14/92 Tnet Release	Michael Temari
+ * 01/15/96 0.30		Michael Temari
+ * 01/25/96 0.90		Michael Temari
+ * 03/17/96 0.91		Michael Temari
+ * 06/27/96 0.92		Michael Temari
+ * 07/02/96 0.93		Michael Temari
+ * 07/15/96 0.94		Michael Temari
+ * 08/27/96 0.95		Michael Temari
+ * 02/09/97 0.96		Michael Temari
+ * 02/10/97 0.97		Michael Temari
+ * 09/25/97 0.98		Michael Temari
+ * 03/10/00 0.99		Michael Temari, <Michael@TemWare.Com>
+ * 12/12/03 1.00		Michael Temari, <Michael@TemWare.Com>
+ * 02/06/05 1.01		Michael Temari, <Michael@TemWare.Com>
+ * 02/12/05 2.00		Michael Temari, <Michael@TemWare.Com>
+ */
+
+char *FtpdVersion = "2.00";
+
+#include <sys/types.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+
+#include "ftpd.h"
+#include "access.h"
+#include "file.h"
+#include "net.h"
+
+_PROTOTYPE(static void init, (void));
+_PROTOTYPE(static int doHELP, (char *buff));
+_PROTOTYPE(static int doNOOP, (char *buff));
+_PROTOTYPE(static int doUNIMP, (char *buff));
+_PROTOTYPE(static int getline, (char *line, int len));
+
+FILE *msgfile = (FILE *)NULL;
+
+/* The following defines the inactivity timeout in seconds */
+#define	INACTIVITY_TIMEOUT	60*5
+
+char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+		  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+char line[512];
+
+int type, format, mode, structure;
+int ftpdata_fd = -1;
+int loggedin, gotuser, anonymous;
+char username[80];
+char anonpass[128];
+char newroot[128];
+
+ipaddr_t myipaddr, rmtipaddr, dataaddr;
+tcpport_t myport, rmtport, dataport;
+
+char myhostname[256], rmthostname[256];
+
+#define	FTPD_LOG	"/usr/adm/ftpd.log"
+#define	FTPD_MSG	"/etc/ftpd_msg"
+
+FILE *logfile;
+
+int timeout = 0;
+
+_PROTOTYPE(static int doHELP, (char *buff));
+_PROTOTYPE(int readline, (char **args));
+_PROTOTYPE(void Timeout, (int sig));
+_PROTOTYPE(int main, (int argc, char *argv[]));
+
+struct commands {
+	char *name;
+	_PROTOTYPE(int (*func), (char *buff));
+};
+
+struct commands commands[] = {
+	"ABOR", doUNIMP,
+	"ACCT", doUNIMP,
+	"ALLO", doALLO,
+	"APPE", doAPPE,
+	"CDUP", doCDUP,
+	"CWD",  doCWD,
+	"DELE", doDELE,
+	"HELP", doHELP,
+	"LIST", doLIST,
+	"MDTM", doMDTM,
+	"MKD",  doMKD,
+	"MODE", doMODE,
+	"NLST", doNLST,
+	"NOOP", doNOOP,
+	"PASS", doPASS,
+	"PASV", doPASV,
+	"PORT", doPORT,
+	"PWD",  doPWD,
+	"QUIT", doQUIT,
+	"REIN", doUNIMP,
+	"REST", doREST,
+	"RETR", doRETR,
+	"RMD",  doRMD,
+	"RNFR", doRNFR,
+	"RNTO", doRNTO,
+	"SITE", doSITE,
+	"SIZE", doSIZE,
+	"SMNT", doUNIMP,
+	"STAT", doSTAT,
+	"STOR", doSTOR,
+	"STOU", doSTOU,
+	"STRU", doSTRU,
+	"SYST", doSYST,
+	"TYPE", doTYPE,
+	"USER", doUSER,
+	"XCUP", doCDUP,
+	"XCWD", doCWD,
+	"XMKD", doMKD,
+	"XPWD", doPWD,
+	"XRMD", doRMD,
+	"",     (int (*)())0
+};
+
+static void init()
+{
+   loggedin = 0;
+   gotuser = 0;
+   anonymous = 0;
+   newroot[0] = '\0';
+   type = TYPE_A;
+   format = 0;
+   mode = MODE_S;
+   structure = 0;
+   ftpdata_fd = -1;
+   username[0] = '\0';
+   anonpass[0] = '\0';
+}
+
+/* nothing, nada, zilch... */
+static int doNOOP(buff)
+char *buff;
+{
+   printf("200 NOOP to you too!\r\n");
+
+   return(GOOD);
+}
+
+/* giv'em help, what a USER! */
+static int doHELP(buff)
+char *buff;
+{
+struct commands *cmd;
+char star;
+int i;
+char *space = "    ";
+
+   printf("214-Here is a list of available ftp commands\r\n");
+   printf("    Those with '*' are not yet implemented.\r\n");
+
+   i = 0;
+   for(cmd = commands; *cmd->name != '\0'; cmd++) {
+	if(cmd->func == doUNIMP)
+		star = '*';
+	else
+		star = ' ';
+	printf("     %s%c%s", cmd->name, star, space + strlen(cmd->name));
+	if(++i == 6) {
+		printf("\r\n");
+		i = 0;
+	}
+   }
+
+   if(i)
+	printf("\r\n");
+
+   printf("214 That's all the help you get.\r\n");
+
+   return(GOOD);
+}
+
+/* not implemented */
+static int doUNIMP(buff)
+char *buff;
+{
+   printf("502 Command \"%s\" not implemented!\r\n", line);
+
+   return(GOOD);
+}
+
+/* convert line for use */
+void cvtline(args)
+char **args;
+{
+char *p;
+
+   p = line + strlen(line);
+   while(--p >= line)
+	if(*p == '\r' || *p == '\n' || isspace(*p))
+		*p = '\0';
+	else
+		break;
+
+  p = line;
+
+#ifdef DEBUG
+  logit("COMMAND", line);
+#endif
+
+  while(*p && !isspace(*p)) {
+	*p = toupper(*p);
+	p++;
+  }
+
+  if(*p) {
+	*p = '\0';
+	p++;
+	while(*p && isspace(*p))
+		p++;
+   }
+
+   *args = p;
+
+   return;
+}
+
+static int getline(line, len)
+char *line;
+int len;
+{
+int s;
+int gotcr;
+
+   /* leave room for at end for null */
+   len--;
+
+   /* got to be able to put in at least 1 character */
+   if(len < 1)
+	return(-1);
+
+   gotcr = 0;
+   while(len-- > 0) {
+	s = read(0, line, 1);
+	if(s != 1)
+		return(-1);
+	if(*line == '\n')
+		break;
+	gotcr = (*line == '\r');
+	line++;
+   }
+   if(gotcr)
+	--line;
+
+   *line = '\0';
+
+   return(0);
+}
+
+int readline(args)
+char **args;
+{
+   if(getline(line, sizeof(line)))
+	return(BAD);
+
+   cvtline(args);
+
+   return(GOOD);
+}
+
+/* signal handler for inactivity timeout */
+void Timeout(sig)
+int sig;
+{
+   timeout = 1;
+
+   printf("421 Inactivity timer expired.\r\n");
+}
+
+/* logit */
+void logit(type, parm)
+char *type;
+char *parm;
+{
+time_t now;
+struct tm *tm;
+
+   if(logfile == (FILE *)NULL)
+	return;
+
+   time(&now);
+   tm = localtime(&now);
+   fprintf(logfile, "%4d%02d%02d%02d%02d%02d ",
+	1900+tm->tm_year,
+	tm->tm_mon + 1,
+	tm->tm_mday,
+	tm->tm_hour, tm->tm_min, tm->tm_sec);
+   fprintf(logfile, "%s %s %s %s %s\n",
+	rmthostname, username, anonymous ? anonpass : username, type, parm);
+   fflush(logfile);
+}
+
+void showmsg(reply, filename)
+char *reply;
+char *filename;
+{
+FILE *mfp;
+char *pe;
+static char mline[256];
+
+   if(filename == (char *)NULL)
+	mfp = msgfile;
+   else
+	mfp = fopen(filename, "r");
+
+   if(mfp == (FILE *)NULL)
+	return;
+
+   while(fgets(mline, sizeof(mline), mfp) != (char *)NULL) {
+	pe = mline + strlen(mline);
+	while(--pe >= mline)
+		if(*pe == '\r' || *pe == '\n')
+			*pe = '\0';
+		else
+			break;
+	printf("%s- %s\r\n", reply, mline);
+   }
+
+   if(filename != (char *)NULL)
+	fclose(mfp);
+}
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+struct commands *cmd;
+char *args;
+int status;
+time_t now;
+struct tm *tm;
+int s;
+
+   GetNetInfo();
+
+   /* open transfer log file if it exists */
+   if((logfile = fopen(FTPD_LOG, "r")) != (FILE *)NULL) {
+	fclose(logfile);
+	logfile = fopen(FTPD_LOG, "a");
+   }
+
+   /* open login msg file */
+   msgfile = fopen(FTPD_MSG, "r");
+
+   /* Let's initialize some stuff */
+   init();
+
+   /* Log the connection */
+   logit("CONNECT", "");
+
+   /* Tell 'em we are ready */
+   time(&now);
+   tm = localtime(&now);
+   printf("220 FTP service (Ftpd %s) ready on %s at ",
+   	FtpdVersion, myhostname);
+   printf("%s, %02d %s %d %02d:%02d:%02d %s\r\n", days[tm->tm_wday],
+   	tm->tm_mday, months[tm->tm_mon], 1900+tm->tm_year,
+	tm->tm_hour, tm->tm_min, tm->tm_sec,
+	tzname[tm->tm_isdst]);
+   fflush(stdout);
+
+   /* Loop here getting commands */
+   while(1) {
+	signal(SIGALRM, Timeout);
+	alarm(INACTIVITY_TIMEOUT);
+	if(readline(&args) != GOOD) {
+		if(!timeout)
+			printf("221 Control connection closing (EOF).\r\n");
+		break;
+	}
+	alarm(0);
+	for(cmd = commands; *cmd->name != '\0'; cmd++)
+		if(!strcmp(line, cmd->name))
+			break;
+	if(*cmd->name != '\0')
+		status = (*cmd->func)(args);
+	else {
+		printf("500 Command \"%s\" not recognized.\r\n", line);
+		status = GOOD;
+	}
+	fflush(stdout);
+	if(status != GOOD)
+		break;
+   }
+
+   CleanUpPasv();
+
+   return(-1);
+}
Index: /trunk/minix/commands/ftpd200/ftpd.h
===================================================================
--- /trunk/minix/commands/ftpd200/ftpd.h	(revision 9)
+++ /trunk/minix/commands/ftpd200/ftpd.h	(revision 9)
@@ -0,0 +1,37 @@
+/* ftpd.h Copyright 1992-2000 by Michael Temari All Rights Reserved
+ *
+ * This file is part of ftpd.
+ *
+ *
+ * 01/25/96 Initial Release	Michael Temari, <Michael@TemWare.Com>
+ */
+
+#define	GOOD	0
+#define	BAD	1
+
+#define	TYPE_A	0
+#define	TYPE_I	1
+
+#define	MODE_S	0
+#define	MODE_B	1
+
+#define	MODE_B_EOF	64
+
+extern char *FtpdVersion;
+extern int type, format, mode, structure;
+extern ipaddr_t myipaddr, rmtipaddr, dataaddr;
+extern tcpport_t myport, rmtport, dataport;
+extern int ftpdata_fd;
+extern int loggedin, gotuser, anonymous;
+extern char newroot[128];
+extern char *days[], *months[];
+extern char username[80];
+extern char anonpass[128];
+extern char myhostname[256], rmthostname[256];
+extern char line[512];
+
+extern FILE *logfile;
+
+_PROTOTYPE(void cvtline, (char **args));
+_PROTOTYPE(void logit, (char *type, char *parm));
+_PROTOTYPE(void showmsg, (char *reply, char *filename));
Index: /trunk/minix/commands/ftpd200/ftpdsh
===================================================================
--- /trunk/minix/commands/ftpd200/ftpdsh	(revision 9)
+++ /trunk/minix/commands/ftpd200/ftpdsh	(revision 9)
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+case $1 in
+	1)	ls -A $2 ;;
+	2)	ls -la $2 ;;
+	3)	crc $2 ;;
+	12)	tar cf - $2 ;;
+	13)	tar cf - $2 | compress -q ;;
+	14)	compress -cq $2 ;;
+	15)	tar cf - $2 | gzip ;;
+	16)	tar -c $2 ;;
+	17)	compress -dcq $2 ;;
+esac
+exit
Index: /trunk/minix/commands/ftpd200/net.c
===================================================================
--- /trunk/minix/commands/ftpd200/net.c	(revision 9)
+++ /trunk/minix/commands/ftpd200/net.c	(revision 9)
@@ -0,0 +1,431 @@
+/* net.c Copyright 1992-2000 by Michael Temari All Rights Reserved
+ *
+ * This file is part of ftpd.
+ *
+ * This file handles:
+ *
+ *      PASV PORT
+ *
+ *
+ * 01/25/1995 Initial Release	Michael Temari, <Michael@TemWare.Com>
+ * 02/09/2005 Initial Release	Michael Temari, <Michael@TemWare.Com>
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <time.h>
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/socket.h>
+#include <net/gen/netdb.h>
+
+#include "ftpd.h"
+#include "access.h"
+#include "net.h"
+
+_PROTOTYPE(static void timeout, (int sig));
+
+static char *msg425 = "425-Could not open data connection.\r\n";
+static char *msg501 = "501 Syntax error in parameters.\r\n";
+
+static int gottimeout = 0;
+static int lpid = -1;
+static int didpassive = 0;
+
+/* they must be behind a firewall or using a web browser */
+int doPASV(buff)
+char *buff;
+{
+nwio_tcpconf_t tcpconf;
+nwio_tcpcl_t tcplopt;
+char *tcp_device;
+ipaddr_t ipaddr;
+tcpport_t lport;
+int s;
+time_t starttime;
+int retry;
+
+   if(ChkLoggedIn())
+	return(GOOD);
+
+   CleanUpPasv();
+
+   /* here we set up a connection to listen on */
+   if((tcp_device = getenv("TCP_DEVICE")) == NULL)
+	tcp_device = TCP_DEVICE;
+
+   if(ftpdata_fd >= 0) {
+	close(ftpdata_fd);
+	ftpdata_fd = -1;
+   }
+
+   if((ftpdata_fd = open(tcp_device, O_RDWR)) < 0) {
+	printf(msg425); 
+	printf("425 Could not open tcp_device.  Error %s\r\n", strerror(errno));
+	return(GOOD);
+   }
+
+   tcpconf.nwtc_flags = NWTC_LP_SEL | NWTC_SET_RA | NWTC_UNSET_RP;
+
+   tcpconf.nwtc_remaddr = rmtipaddr;
+   tcpconf.nwtc_remport = htons(0);
+   tcpconf.nwtc_locport = htons(0);
+
+   s = ioctl(ftpdata_fd, NWIOSTCPCONF, &tcpconf);
+   if(s < 0) {
+	printf(msg425);
+	printf("425 Could not ioctl NWIOSTCPCONF. Error %s\r\n", strerror(errno));
+	close(ftpdata_fd);
+	ftpdata_fd = -1;
+	return(GOOD);
+   }
+
+   s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
+   if(s < 0) {
+	printf(msg425);
+	printf("425 Could not NWIOGTCPCONF. Error %s\r\n", strerror(errno));
+	close(ftpdata_fd);
+	ftpdata_fd = -1;
+	return(GOOD);
+   }
+   ipaddr = tcpconf.nwtc_locaddr;
+   lport = tcpconf.nwtc_locport;
+
+   /* Now lets fork a child to do the listening :-( */
+
+   tcplopt.nwtcl_flags = 0;
+
+   lpid = fork();
+   if(lpid < 0) {
+	printf(msg425);
+	printf("425 Could not fork listener.  Error %s\r\n", strerror(errno));
+	close(ftpdata_fd);
+	ftpdata_fd = -1;
+	return(GOOD);
+   } else if(lpid == 0) {
+	retry = 0;
+	while(1) {
+#ifdef DEBUG
+		fprintf(logfile, "ftpd: child %d  parent %d  listen try %d\n", getpid(), getppid(), retry);
+		fflush(logfile);
+#endif
+		s = ioctl(ftpdata_fd, NWIOTCPLISTEN, &tcplopt);
+		if(!(s == -1 && errno == EAGAIN)) break;
+		if(retry++ > 10) break;
+		sleep(1);
+	}
+#ifdef DEBUG
+	fprintf(logfile, "ftpd: child %d  s %d  errno %d\n", getpid(), s, errno);
+	fflush(logfile);
+#endif
+	if(s < 0) 
+		exit(errno);	/* tells parent listen failed */
+	else
+		exit(0);	/* tells parent listen okay */
+   }
+
+#ifdef DEBUG
+   fprintf(logfile, "ftpd: parent %d  wait for %d\n", getpid(), lpid);
+   fflush(logfile);
+#endif
+
+   /* wait for child to be listening, no more than serveral seconds */
+   (void) time(&starttime);
+   while(1) {
+	if(time((time_t *)NULL) > (starttime + 15)) break;
+   	signal(SIGALRM, timeout);
+   	alarm(1);
+   	s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
+#ifdef DEBUG
+	fprintf(logfile, "ftpd: parent %d  child %d  s %d  errno %d start %ld  now %ld\n",
+		getpid(), lpid, s, errno, starttime, time((time_t *)NULL));
+	fflush(logfile);
+#endif
+   	alarm(0);
+   	if(s == -1) break;
+	sleep(1);
+   }
+
+#define hiword(x)       ((u16_t)((x) >> 16))
+#define loword(x)       ((u16_t)(x & 0xffff)) 
+#define hibyte(x)       (((x) >> 8) & 0xff)
+#define lobyte(x)       ((x) & 0xff)
+
+   printf("227 Entering Passive Mode (%u,%u,%u,%u,%u,%u).\r\n",
+		hibyte(hiword(htonl(ipaddr))), lobyte(hiword(htonl(ipaddr))),
+		hibyte(loword(htonl(ipaddr))), lobyte(loword(htonl(ipaddr))),
+		hibyte(htons(lport)), lobyte(htons(lport)));
+
+#ifdef DEBUG
+   fprintf(logfile, "ftpd: parent %d  child %d  send 227\n", getpid(), lpid);
+   fflush(logfile);
+#endif
+
+   didpassive = -1;
+
+   return(GOOD);
+}
+
+/* they want us to connect here */
+int doPORT(buff)
+char *buff;
+{
+u32_t ipaddr;
+u16_t port;
+int i;
+
+   if(ftpdata_fd >= 0) {
+	close(ftpdata_fd);
+	ftpdata_fd = -1;
+   }
+
+   ipaddr = (u32_t)0;
+   for(i = 0; i < 4; i++) {
+	ipaddr = (ipaddr << 8) + (u32_t)atoi(buff);
+	if((buff = strchr(buff, ',')) == (char *)0) {
+		printf(msg501);
+		return(GOOD);
+	}
+	buff++;
+   }
+   port = (u16_t)atoi(buff);
+   if((buff = strchr(buff, ',')) == (char *)0) {
+	printf(msg501);
+	return(0);
+   }
+   buff++;
+   port = (port << 8) + (u16_t)atoi(buff);
+
+   dataaddr = htonl(ipaddr);
+   dataport = htons(port);
+   if(dataaddr != rmtipaddr) {
+	printf(msg501);
+	return(GOOD);
+   }
+
+   printf("200 Port command okay.\r\n");
+
+   return(GOOD);
+}
+
+/* connect, huh? */
+int DataConnect()
+{
+nwio_tcpconf_t tcpconf;
+nwio_tcpcl_t tcpcopt;
+nwio_tcpcl_t tcplopt;
+char *tcp_device;
+int s, cs;
+int retry;
+
+   if(didpassive && ftpdata_fd >= 0) {
+   	didpassive = 0;
+	gottimeout = 0;
+   	signal(SIGALRM, timeout);
+   	alarm(10);
+	while(!gottimeout) {
+		s = waitpid(lpid, &cs, 0);
+		if((s == lpid) || (s < 0 && errno == ECHILD)) break;
+#ifdef DEBUG
+		fprintf(logfile, "ftpd: parent %d  child %d waitpid s %d  cs %04x  errno %d\n", getpid(), lpid, s, cs, errno);
+		fflush(logfile);
+#endif
+	}
+	alarm(0);
+#ifdef DEBUG
+	fprintf(logfile, "ftpd: parent %d  child %d waitpid s %d  cs %04x  errno %d\n", getpid(), lpid, s, cs, errno);
+		fflush(logfile);
+#endif
+	if(gottimeout) {
+#ifdef DEBUG
+		fprintf(logfile, "ftpd: parent %d  child %d  got timeout\n", getpid(), lpid);
+		fflush(logfile);
+#endif
+		kill(lpid, SIGKILL);
+		s = waitpid(lpid, &cs, 0);
+	}
+#ifdef DEBUG
+	fprintf(logfile, "ftpd: parent %d  child %d continuing\n", getpid(), lpid);
+	fflush(logfile);
+#endif
+	lpid = -1;
+	if(gottimeout) {
+		printf(msg425);
+		printf("425 Child listener timeout.\r\n");
+		close(ftpdata_fd);
+		ftpdata_fd = -1;
+		return(BAD);
+	}
+	if(s < 0) {
+		printf(msg425);
+		printf("425 Child listener vanished.\r\n");
+		close(ftpdata_fd);
+		ftpdata_fd = -1;
+		return(BAD);
+	}
+	if((cs & 0x00ff)) {
+		printf(msg425);
+		printf("425 Child listener failed %04x\r\n", cs);
+		close(ftpdata_fd);
+		ftpdata_fd = -1;
+		return(BAD);
+	}
+	cs = (cs >> 8) & 0x00ff;
+	if(cs) {
+		printf(msg425);
+		printf("425 Child listener error %s\r\n", strerror(cs));
+		close(ftpdata_fd);
+		ftpdata_fd = -1;
+		return(BAD);
+	}
+#ifdef DEBUG
+	fprintf(logfile, "ftpd: parent %d  child %d pasv done\n", getpid(), lpid);
+	fflush(logfile);
+#endif
+	return(GOOD);
+   }
+
+   if(ftpdata_fd >= 0)
+   	return(GOOD);
+
+   if((tcp_device = getenv("TCP_DEVICE")) == NULL)
+	tcp_device = TCP_DEVICE;
+
+   if((ftpdata_fd = open(tcp_device, O_RDWR)) < 0) {
+	printf(msg425);
+	printf("425 Could not open tcp_device. Error %s\r\n", strerror(errno));
+	return(BAD);
+   }
+
+   tcpconf.nwtc_flags = NWTC_LP_SET | NWTC_SET_RA | NWTC_SET_RP;
+   tcpconf.nwtc_remaddr = dataaddr;
+   tcpconf.nwtc_remport = dataport;
+   tcpconf.nwtc_locport = htons(20);
+
+   s = ioctl(ftpdata_fd, NWIOSTCPCONF, &tcpconf);
+   if(s < 0) {
+	printf(msg425);
+	printf("425 Could not ioctl NWIOSTCPCONF. Error %s\r\n", strerror(errno));
+	close(ftpdata_fd);
+	ftpdata_fd = -1;
+	return(BAD);
+   }
+
+   s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
+   if(s < 0) {
+	printf(msg425);
+	printf("425 Could not ioctl NWIOGTCPCONF. Error %s\r\n", strerror(errno));
+	close(ftpdata_fd);
+	ftpdata_fd = -1;
+	return(BAD);
+   }
+
+   tcpcopt.nwtcl_flags = 0;
+
+   retry = 0;
+   do  {
+#ifdef DEBUG
+	fprintf(logfile, "try connect\n"); fflush(logfile);
+	fflush(logfile);
+#endif
+	sleep(2);
+	s = ioctl(ftpdata_fd, NWIOTCPCONN, &tcpcopt);
+#ifdef DEBUG
+	fprintf(logfile, "after connect %d %d\n", s, errno);
+	fflush(logfile);
+#endif
+	if(!(s == -1 && errno == EAGAIN)) break;
+	if(retry++ > 10) break;
+	sleep(1);
+   } while(1);
+   if(s < 0) {
+	printf(msg425);
+	printf("425 Could not ioctl NWIOTCPCONN. Error %s\r\n", strerror(errno));
+	close(ftpdata_fd);
+	ftpdata_fd = -1;
+	return(BAD);
+   }
+
+   s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
+   if(s < 0) {
+	printf(msg425);
+	printf("425 Could not ioctl NWIOGTCPCONF. Error %s\r\n", strerror(errno));
+	close(ftpdata_fd);
+	ftpdata_fd = -1;
+	return(BAD);
+   }
+
+   return(GOOD);
+}
+
+/* Clean up stuff we did to get a Pasv connection going */
+int CleanUpPasv()
+{
+int s, cs;
+
+   if(lpid >= 0) {
+	kill(lpid, SIGKILL);
+	while(1) {
+		s = waitpid(lpid, &cs, 0);
+		if(s == lpid || (s == -1 && errno == ECHILD))
+			break;
+	}
+   }
+
+   lpid = -1;
+
+   didpassive = 0;
+
+   return(GOOD);
+}
+
+void GetNetInfo()
+{
+nwio_tcpconf_t tcpconf;
+int s;
+struct hostent *hostent;
+
+   /* Ask the system what our hostname is. */
+   if(gethostname(myhostname, sizeof(myhostname)) < 0)
+	strcpy(myhostname, "unknown");
+
+   /* lets get our ip address and the clients ip address */
+   s = ioctl(0, NWIOGTCPCONF, &tcpconf);
+   if(s < 0) {
+	printf("421 FTP service unable to get remote ip address. Closing.\r\n");
+	fflush(stdout);
+	exit(1);
+   }
+
+   myipaddr = tcpconf.nwtc_locaddr;
+   myport = tcpconf.nwtc_locport;
+   rmtipaddr = tcpconf.nwtc_remaddr;
+   rmtport = tcpconf.nwtc_remport;
+
+   /* Look up the host name of the remote host. */
+   hostent = gethostbyaddr((char *) &rmtipaddr, sizeof(rmtipaddr), AF_INET);
+   if(!hostent)
+	strcpy(rmthostname, inet_ntoa(rmtipaddr));
+   else {
+	strncpy(rmthostname, hostent->h_name, sizeof(rmthostname)-1);
+	rmthostname[sizeof(rmthostname)-1] = '\0';
+   }
+}
+
+static void timeout(sig)
+int sig;
+{
+   gottimeout = 1;
+}
Index: /trunk/minix/commands/ftpd200/net.h
===================================================================
--- /trunk/minix/commands/ftpd200/net.h	(revision 9)
+++ /trunk/minix/commands/ftpd200/net.h	(revision 9)
@@ -0,0 +1,13 @@
+/* net.h Copyright 1992-2000 by Michael Temari All Rights Reserved
+ *
+ * This file is part of ftpd.
+ *
+ *
+ * 01/25/96 Initial Release	Michael Temari, <Michael@TemWare.Com>
+ */
+
+_PROTOTYPE(int doPASV, (char *buff));
+_PROTOTYPE(int doPORT, (char *buff));
+_PROTOTYPE(int DataConnect, (void));
+_PROTOTYPE(int CleanUpPasv, (void));
+_PROTOTYPE(void GetNetInfo, (void));
Index: /trunk/minix/commands/ftpd200/setup.anonftp
===================================================================
--- /trunk/minix/commands/ftpd200/setup.anonftp	(revision 9)
+++ /trunk/minix/commands/ftpd200/setup.anonftp	(revision 9)
@@ -0,0 +1,75 @@
+#!/bin/sh
+# setup.anonftp - Anonymous FTP setup and maintenance.
+#
+# 01/22/96 Initial Release	Al Woodhul, <asw@hampshire.edu>
+# 01/25/96			Michael Temari, <temari@ix.netcom.com>
+#
+
+# What is needed for anon ftp
+
+# ref: Hunt TCP/IP Net Admin pp. 338++
+# ref: Nemeth et al UNIX System Admin Handbook p. 295
+# ref: mail from M. Temari 18.01.96
+
+# programs possibly used by ftpd
+PROGS="sh ls crc tar compress gzip"
+
+echo Checking /etc/passwd
+if grep '^ftp:[^:]*:[1-9][0-9]*:[1-9][0-9]*:[^:]*:/[^:]*:[^:]*$' \
+						/etc/passwd >/dev/null
+then
+  echo -n "OK, ftp entry found: "
+  grep '^ftp:' /etc/passwd
+else
+  echo "Found no entry for ftp in /etc/passwd, please add one with the"
+  echo "home directory pointing to the anonymous FTP directory"
+  exit 1
+fi
+
+# ftp directory
+FTPDIR="`sed '/^ftp:/!d; s/^.*:\\([^:]*\\):[^:]*/\\1/' /etc/passwd`"
+
+if [ `whoami` != root ]
+then
+  echo You must be root to do this
+  exit 1
+fi
+
+echo Setting up for anonymous ftp
+
+echo Making $FTPDIR and subdirectories
+install -d -m 755 -o root -g operator $FTPDIR
+install -d -m 751 -o root -g operator $FTPDIR/bin
+install -d -m 751 -o root -g operator $FTPDIR/dev
+install -d -m 751 -o root -g operator $FTPDIR/etc
+install -d -m 755 -o root -g operator $FTPDIR/pub
+incoming=
+if [ -d $FTPDIR/pub/incoming ]
+then
+	incoming=t
+elif [ -t 0 ]
+then
+	echo -n "Create \"incoming\" directory? [n] "; read yn
+	case "$yn" in
+	[yY]*|ok|sure)	incoming=t
+	esac
+fi
+test "$incoming" && install -d -m 777 -o root -g operator $FTPDIR/pub/incoming
+
+echo Copying files
+for PROG in $PROGS
+do
+  test -f /usr/bin/$PROG && install -lcs /usr/bin/$PROG $FTPDIR/bin
+done
+cp -rp /dev/tcp $FTPDIR/dev/tcp
+install -lcs ftpdsh $FTPDIR/bin
+
+echo Copying a minimum of the password and group files
+sed 's/^\([^:]*\):[^:]*:\([^:]*:[^:]*\):.*$/\1:*:\2:::/' \
+					/etc/passwd >$FTPDIR/etc/passwd
+sed 's/^\([^:]*\):[^:]*:\([^:]*\):.*$/\1:*:\2:/' \
+					/etc/group >$FTPDIR/etc/group
+chown root:operator $FTPDIR/etc/*
+chmod 444 $FTPDIR/etc/*
+
+echo "Anonymous ftp setup complete"
Index: /trunk/minix/commands/httpd/Makefile
===================================================================
--- /trunk/minix/commands/httpd/Makefile	(revision 9)
+++ /trunk/minix/commands/httpd/Makefile	(revision 9)
@@ -0,0 +1,65 @@
+# Makefile for httpd
+#
+# 02/17/1996 			Michael Temari <Michael@TemWare.Com>
+# 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
+# 12/29/2002 			Michael Temari <Michael@TemWare.Com>
+# 07/07/2003			Al Woodhull <awoodhull@hampshire.edu>
+#
+
+CFLAGS=	-O -D_MINIX -D_POSIX_SOURCE -DDAEMON=1
+#CFLAGS=	-O -D_MINIX -D_POSIX_SOURCE -DDAEMON=1 -DDEBUG=9
+LDFLAGS=-i
+BINDIR=/usr/local/bin
+
+HTTPD_OBJS=	httpd.o utility.o request.o process.o reply.o \
+		police.o cgiexec.o net.o config.o pass.o proxy.o
+DIR2HTML_OBJS=	dir2html.o
+
+all:	httpd dir2html
+
+httpd:	$(HTTPD_OBJS)
+	$(CC) $(LDFLAGS) -o $@ $(HTTPD_OBJS)
+	install -S 16kw $@
+
+dir2html:	$(DIR2HTML_OBJS)
+	$(CC) $(LDFLAGS) -o $@ $(DIR2HTML_OBJS)
+	install -S 8kw $@
+
+clean:
+	rm -f httpd $(HTTPD_OBJS) dir2html $(DIR2HTML_OBJS) *.bak
+
+install:	$(BINDIR)/httpd $(BINDIR)/in.httpd $(BINDIR)/dir2html
+
+tar:
+	tar cvf ../httpd.tar Makefile README *.c *.h *.sh *.conf *.mtype
+
+$(BINDIR)/httpd:	httpd
+	install -cs -o bin $? $@
+
+$(BINDIR)/in.httpd:	$(BINDIR)/httpd
+	install -l $? $@
+
+$(BINDIR)/dir2html:	dir2html
+	install -cs -o bin $? $@
+
+httpd.o:	httpd.c		http.h	utility.h	net.h	config.h
+utility.o:	utility.c		utility.h		config.h
+request.o:	request.c	http.h	utility.h		config.h
+process.o:	process.c	http.h	utility.h
+reply.o:	reply.c		http.h	utility.h	net.h	config.h
+police.o:	police.c	http.h	utility.h		config.h pass.h
+cgiexec.o:	cgiexec.c	http.h				config.h
+net.o:		net.c					net.h
+config.o:	config.c		utility.h		config.h
+pass.o:		pass.c		pass.h
+proxy.o:	proxy.c		http.h
+dir2html.o:	dir2html.c
+
+installman:
+	mkdir -p /usr/local/man/man5 
+	mkdir -p /usr/local/man/man8 
+	cp -p httpd.conf.5 http_status.5 /usr/local/man/man5
+	cp -p httpd.8 /usr/local/man/man8
+	makewhatis /usr/local/man
+
+
Index: /trunk/minix/commands/httpd/README
===================================================================
--- /trunk/minix/commands/httpd/README	(revision 9)
+++ /trunk/minix/commands/httpd/README	(revision 9)
@@ -0,0 +1,242 @@
+httpd documentation 7/16/96 by Michael Temari <Michael@TemWare.Com>
+updated 2003-07-05 by Al Woodhull <awoodhull@hampshire.edu>
+
+DISCLAIMER:
+
+Use at own risk etc...
+
+
+COMMENTS:
+
+Please send me any bug reports, comments, questions, etc...  My email
+address is Michael@TemWare.Com
+
+
+BACKGROUND:
+
+httpd is a World Wide Web (WWW) server.  I wrote it from scratch so
+the setup and configuration will not be like other web servers though
+hopefully by reading this document there will be no problems in getting
+my web server up and running on your Minix system.
+
+
+COMPILING:
+
+To compile httpd all you need to do is type "make" in the httpd source
+directory.  There should be no errors or warnings.  If you should run
+out of memory when compiling try adding the -m option to the CFLAGS
+list in the Makefile.
+
+
+INSTALLING:
+
+To install httpd all you need to do is type "make install" in the httpd
+source directory.  By default the place to install httpd is into
+/usr/local/bin.  If you would like to change this then change BINDIR in
+the Makefile.  Httpd will be linked to in.httpd, which is the preferred
+name for a program started by the tcpd internet access control program.
+The program dir2html is also installed -- this provides a directory
+listing when a web client accesses a directory which does not contain a
+file named index.html (or an alternative designated in /etc/httpd.conf).
+The man pages are installed by typing "make installman".
+
+CONFIGURING:
+
+Before running httpd it must be configured.  The name of the default
+configuration file is /etc/httpd.conf or you may pass the configuration
+file name to httpd.  Upon starting up, httpd will parse the configuration
+file and then process requests.  This README file and the sample httpd.conf
+may also help in configuring. The httpd.conf.5 man page presents the same
+information for reference use.
+
+
+The configuration file is an ascii file which consists of lines of the
+following form:
+
+directive LWS [parameters separated by LWS]
+
+NOTE: LWS denotes Linear White Space which is spaces and/or tabs
+
+The following are valid configuration file directives:
+  serverroot user chroot logfile dbgfile dirsend direxec vhost auth
+  proxyauth vpath include mtype 
+
+To make the file more readable, on directives which occupy multiple 
+lines you may omit the directive on lines after the first and begin 
+these lines with LWS.
+
+
+serverroot path
+
+The serverroot directive sets the translation for // to the given path.
+
+
+user username
+
+The user directive causes the server to run as the given username, otherwise
+the server will run as whoever started it (normally root).
+
+
+chroot directory
+
+The chroot directive causes the server to chroot to the given directory after
+the configuration and log files have been opened.  Normally this will be the
+home directory of the given username in the user directive.
+NOTE: /~user will be translated to the home directory of the given user
+      // will be translated to the serverroot directory
+NOTE: if this directive is used then beware of the consequences.
+
+
+logfile filename
+
+The logfile directive tells the server where to log http transactions.
+NOTE: the file must exist to enable logging
+
+
+dbgfile filename
+
+The dbgfile directive tells the server where to log debug http transactions.
+NOTE: the file must exist to enable logging
+
+dirsend filelist
+
+The dirsend directive tells the server that when a directory is requested
+that it should send the first file that it finds in the directory from the
+filelist for the request.
+
+
+direxec program
+
+The direxec directive tells the server that when a directory is requested
+and no file is found from the dirsend directive that it should run the
+given program.
+NOTE: the program normally generates a directory listing on the fly
+NOTE: the program access is considered X with no access restrictions.
+
+
+vhost hostname VhostRoot
+
+vhost is for defining access for virtual hosts.  If none are configured then
+any host is accepted.  If specified then access is only granted for requests
+for hosts which are configured here.  In the Vpath section below the /// gets
+translated to the corresponding VhostRoot.
+
+
+auth authname authdescription access [passwdfile [users]]
+
+The auth directive sets up different authorizations with the server.  The
+authname is the name given to the authorization and is case insensitive.
+The authdescription is the description of the authorization and is what
+the user will see when asked to enter a username and password.  The
+access is one or more of (rwx).  R tells the server the url can be
+read.  W tells the server the url can be overwritten.  X tells the server
+that the url can and should be executed.  Access is in addition to normal
+unix security considerations.  For instance a file that can be written to
+that does not have the W access will have an error returned.  The
+passwdfile is the name of the passwdfile to validate users against.  If
+the passwdfile is given as '.' then the system password file will be used
+which is /etc/passwd.  If no passwdfile is given then no authorization is
+allowed for anyone.  If no users are given then any validated users is
+authorized, otherwise only the given users are allowed.
+
+
+proxyauth authname authdescription access [passwdfile [users]]
+
+proxyauth defines any access authorization to be used for Proxy access
+authname = Same as auth above
+authdescription = Same as auth above
+access = Must be R to allow proxy
+passwdfile = Same as auth above
+users = Same as auth above
+
+
+vpath from to [auth [access]]
+
+The vpath directive sets up url path translations and authorizations.  A
+requested url that matches from will be translated to to with the given
+auth and access.  If auth does not exist then the url will have no access.
+If access is not given then the access is taken from the auth record (see
+above).  A '.' in place of the to means that the server should use a
+translation from another vpath record, but associate the given auth and
+access with the requested url.  A '*' maybe at the end only of the from
+which is a wildcard match.  For example if the from has /AB* then any of
+/ABCDEF or /AB or /ABmichael will match, but /AD or /a will not.  The
+requested url is first checked against each vpath record until an exact
+match (meaning url match from and from had no '*') is found or the end of
+the list.  Therefore a wildcard match will match the last from is the list
+in which it matched.
+NOTE: if at the beginning of the to field
+      /~user will get translated to the home directory of the given user
+      // wile get translated to the serverroot directory
+
+
+include filename
+
+The include directive tells the server to read configuration information
+from the given filename.
+NOTE: normally mtype directives are included from another file
+
+
+mtype mimetype extensions
+
+The mtype directive tells the server what mimetype to associate with files
+which have any of the given extensions.  If no match is found then the file
+will be treated as application/octet-stream.
+NOTE: normally you get mtype directives in included file
+
+
+
+USAGE:
+
+		httpd [-v|-t] [configuration-file]
+
+The -t tells the server to just parse the configuration file so that you
+can test it to see if it is the way you want it.  You may also pass the
+name of your configuration file if it is not the default /etc/httpd.conf.
+
+The -v option prints the server version and then exits.
+
+
+STARTING:
+
+First of all httpd is a server and therefore you will need to start it
+with tcpd.  Tcpd is a program which listens for incoming TCP connections
+on the passed port and when a connection comes in it forks and starts the
+given daemon program.  Therefore to start httpd you use:
+
+		tcpd http /usr/local/bin/in.httpd &
+
+You will more than likely have this line in your /etc/rc or /etc/rc.net
+file so that whenever your system is restarted the web server will also
+be started.  The first parameter http is the port that tcpd is going
+to be listening for connections on.  Here http (which should be defined
+in /etc/services as 80) is the standard port for a web server.  The second
+parameter is the program that tcpd will fork and exec when a connection
+comes in.  The program will then have its stdin and stderr connected to
+the client  Then the web server program will start running with the tcpd
+program waiting for the next connection.  Currently there is no ability to
+limit the number of simultaneous web servers running.  NOTE: At some point
+I will be adding the ability for httpd to start itself without the need of
+tcpd.  That way httpd will already be in memory and have parsed its
+configuration file.
+
+In Minix 2.0.3 and later versions you may use:
+
+		daemonize tcpd http /usr/local/bin/in.httpd
+
+(daemonize is a shell function defined in /usr/etc/rc which starts programs
+as daemons).
+
+
+FINAL WORDS
+
+I wanted to get the server out as soon as possible so I hurried up and
+created this document to help out.  Hopefully it will HELP more than
+it HURTS.  If anyone is interested in writing man pages for httpd or any
+of the other network programs please let me know.
+
+
+Michael Temari
+Michael@TemWare.Com
+
+Please note also the SECURITY document in this directory. (asw 2003-07-05)
Index: /trunk/minix/commands/httpd/SECURITY
===================================================================
--- /trunk/minix/commands/httpd/SECURITY	(revision 9)
+++ /trunk/minix/commands/httpd/SECURITY	(revision 9)
@@ -0,0 +1,48 @@
+SECURITY NOTE 
+
+Al Woodhull <awoodhull@hampshire.edu> 2003-07-05
+
+Running a web server is fun, but it's also not without risks.  If, like
+many Minix users, you are a guest on someone else's network, you need
+to be very careful to operate your server in ways that will not put
+your system at risk or interfere with others on the net.  Here are some
+points to consider: 
+
+- Be sure to touch /usr/adm/httpd.log (or whatever you specify as the log
+file in httpd.conf) before you start your web server for the first time
+-- nothing will be logged if the log file does not exist.  Then look at 
+your log file frequently and be alert for any unusual activity.  
+
+- You may also want to be sure that tcpd is configured to operate in
+PARANOID mode.  That will enable logging of connection attempts and
+allow you to use the serv.access (5) file to limit the kinds of
+connections that your system allows.
+
+- If you enable proxy webserving, be very careful, it can be used by
+people you don't know to visit sites that don't welcome visitors whose
+identity is hidden.  This may cause your network host and ultimately you 
+some unpleasantness.
+
+- The Minix httpd can also support CGI applications.  These are also
+dangerous -- a CGI application allows someone else to execute a program
+on your computer.  Make sure anything you allow this way cannot be
+abused. Many security violations are due to effects of input that was not 
+expected by the original author of a program.
+
+- It's an understatement to say that Minix is not a well-known 
+operating system.  There are not many Minix systems operating as
+servers on the internet.  A consequence of this is that there few, if
+any, people engaged in finding ways to attack weaknesses in Minix.  But
+the idea of "security through obscurity" is deprecated by serious
+computer security experts.  Any operating system or program of any
+degree of complexity is likely to have bugs or features that can be
+exploited in ways the original programmers did not foresee.  You can't
+count on the "good guys" being the first ones to discover a risk.
+There are two things you should be sure to do if you are running a
+network server of any kind: 
+
+(1) be alert for new versions of the program that may fix bugs
+discovered by other users, and 
+
+(2) be sure to report to the program author or maintainer anything you
+observe that looks like a bug or a way the program can be misused.
Index: /trunk/minix/commands/httpd/build
===================================================================
--- /trunk/minix/commands/httpd/build	(revision 9)
+++ /trunk/minix/commands/httpd/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/httpd/cgiexec.c
===================================================================
--- /trunk/minix/commands/httpd/cgiexec.c	(revision 9)
+++ /trunk/minix/commands/httpd/cgiexec.c	(revision 9)
@@ -0,0 +1,255 @@
+/* cgiexec.c by Michael Temari 02/17/96
+ *
+ * This file is part of httpd.
+ *
+ * 02/17/1996 			Michael Temari <Michael@TemWare.Com>
+ * 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
+ * 12/29/2002 			Michael Temari <Michael@TemWare.Com>
+ * 02/08/2005 			Michael Temari <Michael@TemWare.Com>
+ *
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+
+#include "http.h"
+#include "config.h"
+#include "net.h"
+
+_PROTOTYPE(char **cgienv, (struct http_request *rq, struct http_reply *rp));
+_PROTOTYPE(static int addenv, (char *name, char *value, char **buf, int *len));
+
+int cgiexec(rq, rp)
+struct http_request *rq;
+struct http_reply *rp;
+{
+struct stat st;
+char *prog;
+int cmdpid;
+int status;
+char *argv[5];
+int ifds[2];
+int ofds[2];
+static char cmd[2048];
+char **cmdenv;
+int dirflag = 0;
+
+    if(stat(rp->realurl, &st)) {
+    	if(errno == EACCES)
+    		rp->status = HTTP_STATUS_FORBIDDEN;
+    	else
+    		rp->status = HTTP_STATUS_NOT_FOUND;
+    	strcpy(rp->statusmsg, strerror(errno));
+    	return(-1);
+    }
+
+    if((st.st_mode & S_IFMT) == S_IFDIR)
+    	if(direxec != NULL) {
+    		prog = direxec; dirflag = 1;
+    	} else
+    		return(0);
+    else
+    	prog = rp->realurl;
+
+    /* check if prog is allowed to be exec'd */
+    if(!dirflag && !(rp->urlaccess & URLA_EXEC))
+    	return(0);
+
+    /* if cannot exec mode then return */
+    if( (st.st_mode & S_IXUSR) == 0 &&
+    	(st.st_mode & S_IXGRP) == 0 &&
+    	(st.st_mode & S_IXOTH) == 0 )
+	return(0);
+
+   if((cmdenv = cgienv(rq, rp)) == NULL) {
+   	rp->status = HTTP_STATUS_SERVER_ERROR;
+   	strcpy(rp->statusmsg, "Could not setup cgi environment");
+   	return(-1);
+   }
+
+   argv[0] = prog;
+   argv[1] = rp->realurl;
+   argv[2] = rq->url;
+   argv[3] = (char *)NULL;
+
+   if(pipe(ifds) < 0) {
+	rp->status = HTTP_STATUS_NOT_FOUND;
+    	strcpy(rp->statusmsg, strerror(errno));
+	return(-1);
+   }
+
+   if(pipe(ofds) < 0) {
+	rp->status = HTTP_STATUS_NOT_FOUND;
+    	strcpy(rp->statusmsg, strerror(errno));
+    	close(ifds[0]); close(ifds[1]);
+	return(-1);
+   }
+
+   if((cmdpid = fork()) < 0) {
+	close(ifds[0]); close(ofds[0]);
+	close(ifds[1]); close(ofds[1]);
+	rp->status = HTTP_STATUS_NOT_FOUND;
+    	strcpy(rp->statusmsg, strerror(errno));
+	return(-1);
+   }
+
+   /* We don't know how much data is going to be passed back */
+   rp->size = 0;
+
+   if(cmdpid == 0) { /* Child */
+#if 0
+   	if((cmdpid = fork()) < 0) {
+		close(ifds[0]); close(ofds[0]);
+		close(ifds[1]); close(ofds[1]);
+   		exit(-1);
+   	}
+   	if(cmdpid != 0) {
+		close(ifds[0]); close(ofds[0]);
+		close(ifds[1]); close(ofds[1]);
+		exit(0);
+	}
+#endif
+	setsid();
+	close(ifds[0]); close(ofds[1]);
+	dup2(ofds[0], 0);
+	dup2(ifds[1], 1);
+	dup2(ifds[1], 2);
+	close(ifds[1]); close(ofds[0]);
+	execve(argv[0], argv, cmdenv);
+	exit(0);
+   }
+
+#if 0
+   /* Get rid of Zombie child */
+   (void) wait(&status);
+#endif
+
+   close(ifds[1]); close(ofds[0]);
+
+   rp->fd = ifds[0];
+   rp->ofd = ofds[1];
+   rp->pid = cmdpid;
+
+   if(rp->urlaccess & URLA_HEADERS)
+   	rp->headers = -1;
+
+   return(-1);
+}
+
+char **cgienv(rq, rp)
+struct http_request *rq;
+struct http_reply *rp;
+{
+static char buffer[4096];
+char *p, *p2;
+char **e;
+int len;
+char temp[20];
+
+   p = buffer;
+   len = sizeof(buffer);
+
+   if(addenv("PATH", "/usr/local/bin:/bin:/usr/bin", &p, &len)) return(NULL);
+   if(getenv("TZ") != (char *)NULL)
+   	if(addenv("TZ", getenv("TZ"), &p, &len)) return(NULL);
+
+   /* HACK - some of these are hardcoded and should not be MAT 3/17/96 */
+
+   /* HTTP_ */
+
+   if(addenv("SERVER_SOFTWARE", "Temari httpd/1.0", &p, &len)) return(NULL);
+   if(addenv("SERVER_NAME", myhostname, &p, &len)) return(NULL);
+   if(addenv("GATEWAY_INTERFACE", "CGI/1.1", &p, &len)) return(NULL);
+   if(addenv("SERVER_PROTOCOL", "HTTP/1.0", &p, &len)) return(NULL);
+   if(rq->port)
+	sprintf(temp, "%u", rq->port);
+   else
+   	strcpy(temp, "80");
+   if(addenv("SERVER_PORT", temp, &p, &len)) return(NULL);
+   switch(rq->method) {
+   	case HTTP_METHOD_GET:
+		if(addenv("REQUEST_METHOD", "GET", &p, &len)) return(NULL);
+		break;
+   	case HTTP_METHOD_POST:
+		if(addenv("REQUEST_METHOD", "POST", &p, &len)) return(NULL);
+		break;
+   	case HTTP_METHOD_HEAD:
+		if(addenv("REQUEST_METHOD", "HEAD", &p, &len)) return(NULL);
+		break;
+   	case HTTP_METHOD_PUT:
+		if(addenv("REQUEST_METHOD", "PUT", &p, &len)) return(NULL);
+		break;
+	default:
+		if(addenv("REQUEST_METHOD", "UNKNOWN", &p, &len)) return(NULL);
+   }
+   if(addenv("PATH_INFO", "?", &p, &len)) return(NULL);
+   if(addenv("PATH_TRANSLATED", "?", &p, &len)) return(NULL);
+   if(addenv("SCRIPT_NAME", rq->url, &p, &len)) return(NULL);
+   if(addenv("QUERY_STRING", rq->query, &p, &len)) return(NULL);
+   if(addenv("REMOTE_HOST", rmthostname, &p, &len)) return(NULL);
+   if(addenv("REMOTE_ADDR", rmthostaddr, &p, &len)) return(NULL);
+   if(rq->authuser != (char *)NULL)
+	if(addenv("AUTH_USER", rq->authuser, &p, &len)) return(NULL);
+   /* AUTH_TYPE */
+   /* REMOTE_USER */
+   /* REMOTE_IDENT */
+   if(rq->method == HTTP_METHOD_POST) {
+	if(addenv("CONTENT_TYPE", "application/x-www-form-urlencoded", &p, &len)) return(NULL);
+	sprintf(temp, "%lu", rq->size);
+	if(addenv("CONTENT_LENGTH", temp, &p, &len)) return(NULL);
+   }
+   /* COOKIE */
+   if(rq->cookie[0] != '\0')
+   	if(addenv("COOKIE", rq->cookie, &p, &len)) return(NULL);
+   /* HOST */
+   if(addenv("HOST", rq->host, &p, &len)) return(NULL);
+
+   if(len < 1) return(NULL);
+   *p++ = '\0';
+
+   p2 = buffer;
+   e = (char **)p;
+   while(*p2) {
+  	if(len < sizeof(e)) return(NULL);
+  	len -= sizeof(e);
+  	*e++ = p2;
+  	while(*p2) p2++;
+  	p2++;
+   }
+   if(len < sizeof(e)) return(NULL);
+   *e++ = NULL;
+
+   return((char **)p);
+}
+
+static int addenv(name, value, buf, len)
+char *name;
+char *value;
+char **buf;
+int *len;
+{
+char *p;
+int size;
+
+   p = *buf;
+
+   size = strlen(name)+1+strlen(value)+1;
+
+   if(size > *len)
+   	return(-1);
+
+   sprintf(p, "%s=%s", name, value);
+
+   p += size;
+   *buf = p;
+   *len -= size;
+
+   return(0);
+}
Index: /trunk/minix/commands/httpd/config.c
===================================================================
--- /trunk/minix/commands/httpd/config.c	(revision 9)
+++ /trunk/minix/commands/httpd/config.c	(revision 9)
@@ -0,0 +1,813 @@
+/* config.c by Michael Temari 02/26/96
+ *
+ * This file is part of httpd.
+ *
+ * 02/26/1996 			Michael Temari <Michael@TemWare.Com>
+ * 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
+ * 12/29/2002 			Michael Temari <Michael@TemWare.Com>
+ *
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <pwd.h>
+
+#include "utility.h"
+#include "config.h"
+
+struct mtype *mtype = NULL;
+struct msufx *msufx = NULL;
+struct vhost *vhost = NULL;
+struct vpath *vpath = NULL;
+struct dirsend *dirsend = NULL;
+struct auth *auth = NULL;
+struct auth *proxyauth = NULL;
+char *direxec = NULL;
+char *srvrroot = "";
+char *LogFile = NULL;
+char *DbgFile = NULL;
+char *User = NULL;
+char *Chroot = NULL;
+
+_PROTOTYPE(static int doconfig, (char *cfg_file));
+_PROTOTYPE(static int doinclude, (char *parms[], int np));
+_PROTOTYPE(static int domtype, (char *parms[], int np));
+_PROTOTYPE(static struct auth *findauth, (char *name));
+_PROTOTYPE(static int dovhost, (char *parms[], int np));
+_PROTOTYPE(static int dovpath, (char *parms[], int np));
+_PROTOTYPE(static int dosrvrroot, (char *parms[], int np));
+_PROTOTYPE(static int dodirsend, (char *parms[], int np));
+_PROTOTYPE(static int dodirexec, (char *parms[], int np));
+_PROTOTYPE(static char *subvpath, (char *s));
+_PROTOTYPE(static int dologfile, (char *parms[], int np));
+_PROTOTYPE(static int dodbgfile, (char *parms[], int np));
+_PROTOTYPE(static int douser, (char *parms[], int np));
+_PROTOTYPE(static int dochroot, (char *parms[], int np));
+_PROTOTYPE(static int adduser, (struct auth *pauth, char *user));
+_PROTOTYPE(static int doauth, (char *parms[], int np));
+_PROTOTYPE(static int doproxyauth, (char *parms[], int np));
+
+int readconfig(cfg_file, testing)
+char *cfg_file;
+int testing;
+{
+int s;
+char *cfg;
+struct msufx *ps;
+struct mtype *pt;
+struct vhost *ph;
+struct vpath *pv;
+struct dirsend *pd;
+struct auth *pa;
+
+   cfg = HTTPD_CONFIG_FILE;
+   if(cfg_file != (char *)NULL)
+	if(*cfg_file)
+		cfg = cfg_file;
+
+   s = doconfig(cfg);
+
+   if(testing) {
+	printf("ServerRoot: %s\n", srvrroot);
+	printf("UserName: %s\n", User == NULL ? "" : User);
+	printf("Chroot: %s\n", Chroot == NULL ? "" : Chroot);
+	printf("LogFile: %s\n", LogFile == NULL ? "" : LogFile);
+	printf("DbgFile: %s\n", DbgFile == NULL ? "" : DbgFile);
+	printf("DirSend:");
+	for(pd = dirsend; pd != NULL; pd = pd->next)
+   		printf(" %s", pd->file);
+	printf("\n");
+	printf("DirExec: %s\n", direxec == NULL ? "" : direxec);
+	for(ph = vhost; ph != NULL; ph = ph->next)
+		printf("VHost: %s %s\n", ph->hname, ph->root);
+	for(pa = auth; pa != NULL; pa = pa->next)
+   		printf("Auth: %s %s %d %s\n",
+			pa->name, pa->desc, pa->urlaccess, pa->passwdfile);
+	for(pa = proxyauth; pa != NULL; pa = pa->next)
+   		printf("ProxyAuth: %s %s %d %s\n",
+			pa->name, pa->desc, pa->urlaccess, pa->passwdfile);
+	for(pv = vpath; pv != NULL; pv = pv->next)
+   		printf("Vpath: %s %s %s %d\n",
+			pv->from, pv->to, pv->auth->name, pv->urlaccess);
+	for(pt = mtype; pt != NULL; pt = pt->next) {
+   		printf("MType: %s :", pt->mimetype);
+		for(ps = pt->msufx; ps != NULL; ps = ps->tnext)
+		   	printf(" '%s'", ps->suffix);
+		printf("\n");
+	}
+	for(ps = msufx; ps != NULL; ps = ps->snext)
+   		printf("Suffix: %s\t%s\n", ps->suffix, ps->mtype->mimetype);
+   }
+
+   return(s);
+}
+
+static int doconfig(cfg_file)
+char *cfg_file;
+{
+FILE *fp;
+int np;
+int s;
+char *p;
+char ltype[40];
+char *parms[30];
+static char buffer[2048];
+
+   if((fp = fopen(cfg_file, "r")) == (FILE *)NULL) {
+   	fprintf(stderr, "httpd: Could not read %s config file.\n", cfg_file);
+	return(-1);
+   }
+
+   *ltype = '\0';
+
+   while(fgets(buffer, sizeof(buffer), fp) != (char *)NULL) {
+   	if(buffer[0] == '#') continue;	/* skip comments */
+   	np = getparms(buffer, parms, sizeof(parms)/sizeof(parms[0]));
+   	if(np == 0) continue;	/* blank line */
+   	if(parms[0] == (char *)NULL)
+   		parms[0] = ltype;
+   	else {
+   		p = parms[0];
+   		while(*p) *p++ = tolower(*p);
+   		strncpy(ltype, parms[0], sizeof(ltype));
+   	}
+   	s = 0;
+   	if(!strcmp(parms[0], "mtype")) s = domtype(parms, np);
+   	else
+   	if(!strcmp(parms[0], "vhost")) s = dovhost(parms, np);
+   	else
+   	if(!strcmp(parms[0], "vpath")) s = dovpath(parms, np);
+   	else
+   	if(!strcmp(parms[0], "serverroot")) s = dosrvrroot(parms, np);
+   	else
+   	if(!strcmp(parms[0], "dirsend")) s = dodirsend(parms, np);
+   	else
+   	if(!strcmp(parms[0], "direxec")) s = dodirexec(parms, np);
+   	else
+   	if(!strcmp(parms[0], "logfile")) s = dologfile(parms, np);
+   	else
+   	if(!strcmp(parms[0], "dbgfile")) s = dodbgfile(parms, np);
+   	else
+   	if(!strcmp(parms[0], "user")) s = douser(parms, np);
+   	else
+   	if(!strcmp(parms[0], "chroot")) s = dochroot(parms, np);
+   	else
+   	if(!strcmp(parms[0], "auth")) s = doauth(parms, np);
+   	else
+   	if(!strcmp(parms[0], "proxyauth")) s = doproxyauth(parms, np);
+   	else
+	if(!strcmp(parms[0], "include")) s = doinclude(parms, np);
+	else
+   	fprintf(stderr, "httpd: Unknown directive: %s\n", parms[0]);
+   	if(s) {
+   		fprintf(stderr, "httpd: Error processing config file\n");
+		fclose(fp);
+   		return(-1);
+   	}
+   }
+
+   fclose(fp);
+
+   return(0);
+}
+
+static int doinclude(parms, np)
+char *parms[];
+int np;
+{
+char *p;
+
+   if(np < 2) return(0);
+
+   p = subvpath(parms[1]);
+
+   return(doconfig(p));
+}
+
+static int domtype(parms, np)
+char *parms[];
+int np;
+{
+int i;
+struct mtype *pt, *lpt, *newpt;
+struct msufx *ps, *lps, *newps, *psend;
+
+   if(np < 2) return(0);
+
+
+   /* check if this mime type already exists in the list */
+   for(pt = mtype, lpt = NULL; pt != NULL; lpt = pt, pt = pt->next)
+   	if(!strcmp(parms[1], pt->mimetype))
+   		break;
+
+   if(pt == NULL) {		/* not there so add it */
+   	newpt = malloc(sizeof(struct mtype));
+   	if(newpt == NULL) {
+   		fprintf(stderr, "httpd: malloc failed in domtype\n");
+   		return(-1);
+   	}
+   	newpt->mimetype = malloc(strlen(parms[1])+1);
+   	if(newpt->mimetype == NULL) {
+   		fprintf(stderr, "httpd: malloc failed in domtype\n");
+   		return(-1);
+   	}
+   	strcpy(newpt->mimetype, parms[1]);
+   	newpt->msufx = NULL;
+   	newpt->next = NULL;
+   	if(lpt == NULL)
+   		mtype = newpt;
+   	else
+   		lpt->next = newpt;
+   } else
+   	newpt = pt;
+
+   /* find end of suffix list */
+   for(ps = newpt->msufx, lps = NULL; ps != NULL; lps = ps, ps = ps->tnext) ;
+   psend = lps;
+
+   /* if no suffix given then add empty suffix for default */
+   if(np == 2)
+   	strcpy(parms[np++], "");
+
+   /* add each suffix to the mime type */
+   for(i = 2; i < np; i++) {
+	/* a suffix can only be for a single mime type */
+	for(ps = msufx, lps = NULL; ps != NULL; lps = ps, ps = ps->snext) {
+		if(!strcmp(ps->suffix, parms[i])) {
+			fprintf(stderr, "httpd: Suffix already found\n");
+			return(-1);
+		}
+		if(strlen(parms[i]) > strlen(ps->suffix)) break;
+	}
+	newps = malloc(sizeof(struct msufx));
+	if(newps == NULL) {
+   		fprintf(stderr, "httpd: malloc failed in domtype\n");
+   		return(-1);
+   	}
+	newps->suffix = malloc(strlen(parms[i])+1);
+	if(newps->suffix == NULL) {
+   		fprintf(stderr, "httpd: malloc failed in domtype\n");
+   		return(-1);
+   	}
+	strcpy(newps->suffix, parms[i]);
+	newps->mtype = newpt;
+	newps->snext = NULL;
+	newps->tnext = NULL;
+	if(lps == NULL) {
+		msufx = newps;
+		newps->snext = ps;
+	} else {
+		lps->snext = newps;
+		newps->snext = ps;
+	}
+	if(psend == NULL)
+		newpt->msufx = newps;
+	else
+		psend->tnext = newps;
+	psend = newps;
+   }
+
+   return(0);
+}
+
+static struct auth *findauth(name)
+char *name;
+{
+char lname[80];
+char *p, *p2;
+struct auth *a = NULL;
+
+   if(sizeof(lname) < (strlen(name)+1)) {
+   	fprintf(stderr, "httpd: lname too small in findauth\n");
+   	return(a);
+   }
+   p = name; p2 = lname;
+   while(*p)
+	*p2++ = tolower(*p++);
+   *p2 = '\0';
+
+   for(a = auth; a != NULL; a = a->next)
+	if(!strcmp(a->name, lname)) break;
+
+   return(a);
+}
+
+static int dovhost(parms, np)
+char *parms[];
+int np;
+{
+char *hname, *root;
+struct vhost *ph, *lph, *newph;
+
+   if(np < 2) return(0);
+
+   hname = parms[1];
+
+   if(np < 3)
+   	root = "";
+   else
+	root = parms[2];
+
+   for(ph = vhost, lph = NULL; ph != NULL; lph = ph, ph = ph->next)
+	;
+
+   newph = malloc(sizeof(struct vhost));
+   if(newph == NULL) {
+   	fprintf(stderr, "httpd: malloc failed in dovhost\n");
+   	return(-1);
+   }
+   newph->hname = malloc(strlen(hname)+1);
+   if(newph->hname == NULL) {
+   	fprintf(stderr, "httpd: malloc failed in dovhost\n");
+   	return(-1);
+   }
+   strcpy(newph->hname, hname);
+
+   root = subvpath(root);
+
+   newph->root = malloc(strlen(root)+1);
+   if(newph->root == NULL) {
+	fprintf(stderr, "httpd: malloc failed in dovhost\n");
+   	return(-1);
+   }
+   strcpy(newph->root, root);
+
+   if(np > 3)
+   	if(parms[3][0] != '#') {
+		fprintf(stderr, "httpd: junk at end of vhost line\n");
+   		return(-1);
+   	}
+
+   newph->next = NULL;
+   if(lph == NULL) {
+	vhost = newph;
+	newph->next = ph;
+   } else {
+	lph->next = newph;
+	newph->next = ph;
+   }
+
+   return(0);
+}
+
+static int dovpath(parms, np)
+char *parms[];
+int np;
+{
+char *from, *to;
+struct vpath *pv, *lpv, *newpv;
+
+   if(np < 3) return(0);
+
+   from = parms[1];
+   to = parms[2];
+
+   for(pv = vpath, lpv = NULL; pv != NULL; lpv = pv, pv = pv->next)
+	;
+
+   newpv = malloc(sizeof(struct vpath));
+   if(newpv == NULL) {
+   	fprintf(stderr, "httpd: malloc failed in dovpath\n");
+   	return(-1);
+   }
+   newpv->from = malloc(strlen(from)+1);
+   if(newpv->from == NULL) {
+   	fprintf(stderr, "httpd: malloc failed in dovpath\n");
+   	return(-1);
+   }
+   strcpy(newpv->from, from);
+
+   to = subvpath(to);
+
+   newpv->to = malloc(strlen(to)+1);
+   if(newpv->to == NULL) {
+	fprintf(stderr, "httpd: malloc failed in dovpath\n");
+   	return(-1);
+   }
+   strcpy(newpv->to, to);
+
+   newpv->auth = NULL;
+   newpv->urlaccess = -1;
+
+   if(np > 3)
+   	if(parms[3][0] != '#') {
+   		newpv->auth = findauth(parms[3]);
+   		if(np > 4)
+			if(parms[4][0] != '#') {
+				newpv->urlaccess = mkurlaccess(parms[4]);
+				if(np > 5)
+   					if(parms[5][0] != '#') {
+   						fprintf(stderr, "httpd: junk at end of vpath line\n");
+   						return(-1);
+   					}
+			}
+   	}
+
+   newpv->next = NULL;
+   if(lpv == NULL) {
+	vpath = newpv;
+	newpv->next = pv;
+   } else {
+	lpv->next = newpv;
+	newpv->next = pv;
+   }
+
+   return(0);
+}
+
+static int dosrvrroot(parms, np)
+char *parms[];
+int np;
+{
+char *newroot;
+
+   if(np < 2) return(0);
+
+   newroot = subvpath(parms[1]);
+
+   srvrroot = malloc(strlen(newroot)+1);
+   if(srvrroot == NULL) {
+   	fprintf(stderr, "httpd: malloc failed in dosrvrroot\n");
+   	return(-1);
+   }
+   strcpy(srvrroot, newroot);
+   if(srvrroot[strlen(srvrroot)-1] == '/')
+   	srvrroot[strlen(srvrroot)-1] = '\0';
+
+   return(0);
+}
+
+static int dodirsend(parms, np)
+char *parms[];
+int np;
+{
+char *file;
+int i;
+struct dirsend *pd, *lpd, *npd;
+
+   if(np < 2) return(0);
+
+   /* find end of the list */
+   for(pd = dirsend, lpd = NULL; pd != NULL; lpd = pd, pd = pd->next) ;
+
+   for(i = 1; i < np; i++) {
+   	file = parms[i];
+   	if(file[0] == '#') break;
+	npd = malloc(sizeof(struct dirsend));
+	if(npd == NULL) {
+   		fprintf(stderr, "httpd: malloc failed in dodirsend\n");
+   		return(-1);
+	}
+	npd->file = malloc(strlen(file)+1);
+	if(npd->file == NULL) {
+		fprintf(stderr, "httpd: malloc failed in dodirsend\n");
+		return(-1);
+	}
+	strcpy(npd->file, file);
+	npd->next = NULL;
+	if(lpd == NULL)
+		dirsend = npd;
+	else
+		lpd->next = npd;
+	lpd = npd;
+   }
+
+   return(0);
+}
+
+static int dodirexec(parms, np)
+char *parms[];
+int np;
+{
+char *file;
+
+   if(np < 2) return(0);
+
+   if(direxec != NULL) {
+   	fprintf(stderr, "httpd: Error direxec line already present\n");
+   	return(-1);
+   }
+
+   file = subvpath(parms[1]);
+
+   direxec = malloc(strlen(file)+1);
+
+   if(direxec == NULL) {
+	fprintf(stderr, "httpd: malloc failed in dodirexec\n");
+   	return(-1);
+   }
+
+   strcpy(direxec, file);
+
+   if(np > 2)
+   	if(parms[2][0] != '#') {
+   		fprintf(stderr, "httpd: garbage on end of direxec line\n");
+   		return(-1);
+   	}
+
+   return(0);
+}
+
+static char *subvpath(s)
+char *s;
+{
+char *p, *p2;
+int len;
+static char buffer[1024];
+char user[80];
+struct passwd *pwd;
+
+   /* replace beginning // with srvrroot */
+   if(s[0] == '/' && s[1] == '/')
+   	/* but not /// if we have VHOST's */
+   	if(vhost == NULL || s[2] != '/') {
+   		strcpy(buffer, srvrroot);
+   		strncat(buffer, s+1, sizeof(buffer) - strlen(buffer));
+   		buffer[sizeof(buffer)-1] = '\0';
+   		return(buffer);
+	}
+
+   if(s[0] != '/' || s[1] != '~') return(s);
+
+   /* replace beginning /~user with user home directory */
+   p = s + 2;
+   p2 = user;
+   len = sizeof(user) - 1;
+   while(*p && *p != '/' && len-- > 0) *p2++ = *p++;
+   *p2 = '\0';
+   if(*p != '\0' && *p != '/') return(s);
+   if((pwd = getpwnam(user)) == (struct passwd *)NULL) return(s);
+   strcpy(buffer, pwd->pw_dir);
+   strncat(buffer, p, sizeof(buffer) - strlen(buffer));
+   buffer[sizeof(buffer)-1] = '\0';
+
+   return(buffer);
+}
+
+static int dologfile(parms, np)
+char *parms[];
+int np;
+{
+char *p;
+
+   if(np < 2) return(0);
+
+   p = subvpath(parms[1]);
+   LogFile = malloc(strlen(p)+1);
+   if(LogFile == NULL) {
+   	fprintf(stderr, "httpd: malloc failed in dologfile\n");
+   	return(-1);
+   }
+   strcpy(LogFile, p);
+
+   return(0);
+}
+
+static int dodbgfile(parms, np)
+char *parms[];
+int np;
+{
+char *p;
+
+   if(np < 2) return(0);
+
+   p = subvpath(parms[1]);
+   DbgFile = malloc(strlen(p)+1);
+   if(DbgFile == NULL) {
+   	fprintf(stderr, "httpd: malloc failed in dodbgfile\n");
+   	return(-1);
+   }
+   strcpy(DbgFile, p);
+
+   return(0);
+}
+
+static int douser(parms, np)
+char *parms[];
+int np;
+{
+   if(np < 2) return(0);
+
+   User = malloc(strlen(parms[1])+1);
+   if(User == NULL) {
+   	fprintf(stderr, "httpd: malloc failed in douser\n");
+   	return(-1);
+   }
+   strcpy(User, parms[1]);
+
+   return(0);
+}
+
+static int dochroot(parms, np)
+char *parms[];
+int np;
+{
+char *newroot;
+
+   if(np < 2) return(0);
+
+   newroot = subvpath(parms[1]);
+
+   Chroot = malloc(strlen(newroot)+1);
+   if(Chroot == NULL) {
+   	fprintf(stderr, "httpd: malloc failed in dochroot\n");
+   	return(-1);
+   }
+   strcpy(Chroot, newroot);
+
+   return(0);
+}
+
+static int adduser(pauth, user)
+struct auth *pauth;
+char *user;
+{
+struct authuser *pa, *lpa, *newpa;
+
+   for(pa = pauth->users, lpa = NULL; pa != NULL; lpa = pa, pa = pa->next)
+	;
+
+   newpa = malloc(sizeof(struct authuser));
+   if(newpa == NULL) {
+   	fprintf(stderr, "httpd: malloc failed in adduser\n");
+   	return(-1);
+   }
+   newpa->user = malloc(strlen(user)+1);
+   if(newpa->user == NULL) {
+   	fprintf(stderr, "httpd: malloc failed in adduser\n");
+   	return(-1);
+   }
+   strcpy(newpa->user, user);
+
+   newpa->next = NULL;
+   if(lpa == NULL) {
+	pauth->users = newpa;
+	newpa->next = pa;
+   } else {
+	lpa->next = newpa;
+	newpa->next = pa;
+   }
+
+   return(0);
+}
+
+static int doauth(parms, np)
+char *parms[];
+int np;
+{
+int i;
+char *name, *desc, *pf;
+char *p, *p2;
+struct auth *pa, *lpa, *newpa;
+
+   if(np < 3) return(0);
+
+   name = parms[1];
+   desc = parms[2];
+
+   for(pa = auth, lpa = NULL; pa != NULL; lpa = pa, pa = pa->next)
+	;
+
+   newpa = malloc(sizeof(struct auth));
+   if(newpa == NULL) {
+   	fprintf(stderr, "httpd: malloc failed in doauth\n");
+   	return(-1);
+   }
+   newpa->name = malloc(strlen(name)+1);
+   if(newpa->name == NULL) {
+   	fprintf(stderr, "httpd: malloc failed in doauth\n");
+   	return(-1);
+   }
+   p = name; p2 = newpa->name;
+   while(*p)
+	*p2++ = tolower(*p++);
+   *p2 = '\0';
+
+   newpa->desc = malloc(strlen(desc)+1);
+   if(newpa->desc == NULL) {
+	fprintf(stderr, "httpd: malloc failed in doauth\n");
+   	return(-1);
+   }
+   strcpy(newpa->desc, desc);
+
+   newpa->urlaccess = mkurlaccess(parms[3]);
+   newpa->passwdfile = NULL;
+   newpa->users = NULL;
+
+   if(np > 4)
+   	if(parms[4][0] != '#') {
+		if(!strcmp(parms[4], "."))
+			pf = "/etc/passwd";
+		else
+			pf = subvpath(parms[4]);
+   		newpa->passwdfile = malloc(strlen(pf)+1);
+   		if(newpa->passwdfile == NULL) {
+   			fprintf(stderr, "httpd: malloc failed in doauth\n");
+   			return(-1);
+   		}
+   		strcpy(newpa->passwdfile, pf);
+		i = 5;
+		while(i < np) {
+   			if(parms[i][0] == '#')
+				break;
+			if(adduser(newpa, parms[i]))
+				return(-1);
+			i++;
+		}
+   	}
+
+   newpa->next = NULL;
+   if(lpa == NULL) {
+	auth = newpa;
+	newpa->next = pa;
+   } else {
+	lpa->next = newpa;
+	newpa->next = pa;
+   }
+
+   return(0);
+}
+
+static int doproxyauth(parms, np)
+char *parms[];
+int np;
+{
+int i;
+char *name, *desc, *pf;
+char *p, *p2;
+struct auth *pa, *lpa, *newpa;
+
+   if(np < 3) return(0);
+
+   name = parms[1];
+   desc = parms[2];
+
+   if(proxyauth != (struct auth *)NULL) {
+   	fprintf(stderr, "httpd: ProxyAuth defined multiple times using 1st only\n");
+   	return(0);
+   }
+
+   for(pa = proxyauth, lpa = NULL; pa != NULL; lpa = pa, pa = pa->next)
+	;
+
+   newpa = malloc(sizeof(struct auth));
+   if(newpa == NULL) {
+   	fprintf(stderr, "httpd: malloc failed in doproxyauth\n");
+   	return(-1);
+   }
+   newpa->name = malloc(strlen(name)+1);
+   if(newpa->name == NULL) {
+   	fprintf(stderr, "httpd: malloc failed in doproxyauth\n");
+   	return(-1);
+   }
+   p = name; p2 = newpa->name;
+   while(*p)
+	*p2++ = tolower(*p++);
+   *p2 = '\0';
+
+   newpa->desc = malloc(strlen(desc)+1);
+   if(newpa->desc == NULL) {
+	fprintf(stderr, "httpd: malloc failed in doproxyauth\n");
+   	return(-1);
+   }
+   strcpy(newpa->desc, desc);
+
+   newpa->urlaccess = mkurlaccess(parms[3]);
+   newpa->passwdfile = NULL;
+   newpa->users = NULL;
+
+   if(np > 4)
+   	if(parms[4][0] != '#') {
+		if(!strcmp(parms[4], "."))
+			pf = "/etc/passwd";
+		else
+			pf = subvpath(parms[4]);
+   		newpa->passwdfile = malloc(strlen(pf)+1);
+   		if(newpa->passwdfile == NULL) {
+   			fprintf(stderr, "httpd: malloc failed in doauth\n");
+   			return(-1);
+   		}
+   		strcpy(newpa->passwdfile, pf);
+		i = 5;
+		while(i < np) {
+   			if(parms[i][0] == '#')
+				break;
+			if(adduser(newpa, parms[i]))
+				return(-1);
+			i++;
+		}
+   	}
+
+   newpa->next = NULL;
+   if(lpa == NULL) {
+	proxyauth = newpa;
+	newpa->next = pa;
+   } else {
+	lpa->next = newpa;
+	newpa->next = pa;
+   }
+
+   return(0);
+}
Index: /trunk/minix/commands/httpd/config.h
===================================================================
--- /trunk/minix/commands/httpd/config.h	(revision 9)
+++ /trunk/minix/commands/httpd/config.h	(revision 9)
@@ -0,0 +1,84 @@
+/* config.h
+ *
+ * This file is part of httpd.
+ *
+ * 02/26/1996 			Michael Temari <Michael@TemWare.Com>
+ * 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
+ * 12/29/2002 			Michael Temari <Michael@TemWare.Com>
+ * 07/04/2003			Al Woodhull <awoodhull@hampshire.edu>	
+ * 02/08/2005 			Michael Temari <Michael@TemWare.Com>
+ *
+ */
+
+#define VERSION  "Minix httpd 0.994"
+
+struct authuser {
+	char *user;
+	struct authuser *next;
+};
+
+struct auth {
+	char *name;
+	char *desc;
+	int urlaccess;
+	char *passwdfile;
+	struct authuser *users;
+	struct auth *next;
+};
+
+struct msufx {
+	char *suffix;
+	struct mtype *mtype;
+	struct msufx *snext;
+	struct msufx *tnext;
+};
+
+struct mtype {
+	char *mimetype;
+	struct msufx *msufx;
+	struct mtype *next;
+};
+
+struct vhost {
+	char *hname;
+	char *root;
+	struct vhost *next;
+};
+
+struct vpath {
+	char *from;
+	char *to;
+	struct auth *auth;
+	int urlaccess;
+	struct vpath *next;
+};
+
+struct dirsend {
+	char *file;
+	struct dirsend *next;
+};
+
+/* urlaccess bits */
+
+#define	URLA_READ	1
+#define	URLA_WRITE	2
+#define	URLA_EXEC	4
+#define	URLA_HEADERS	8
+
+#define	HTTPD_CONFIG_FILE	"/etc/httpd.conf"
+
+_PROTOTYPE(int readconfig, (char *cfg_file, int testing));
+
+extern struct mtype *mtype;
+extern struct msufx *msufx;
+extern struct vhost *vhost;
+extern struct vpath *vpath;
+extern struct dirsend *dirsend;
+extern struct auth *auth;
+extern struct auth *proxyauth;
+extern char *direxec;
+extern char *srvrroot;
+extern char *LogFile;
+extern char *DbgFile;
+extern char *User;
+extern char *Chroot;
Index: /trunk/minix/commands/httpd/dir2html.c
===================================================================
--- /trunk/minix/commands/httpd/dir2html.c	(revision 9)
+++ /trunk/minix/commands/httpd/dir2html.c	(revision 9)
@@ -0,0 +1,187 @@
+/* dir2html.c by Michael Temari 3/3/96 */
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/stat.h>
+
+typedef struct namelist {	/* Obviously a list of names. */
+	struct namelist	*next;
+	char		name[1];
+} namelist_t;
+
+_PROTOTYPE(static void sort, (namelist_t **anl));
+_PROTOTYPE(static namelist_t *collect, (char *dir));
+_PROTOTYPE(int main, (int argc, char *argv[]));
+
+static void sort(anl)
+namelist_t **anl;
+/* A stable mergesort disguised as line noise.  Must be called like this:
+ *	if (L != NULL && L->next != NULL) sort(&L);
+ */
+{
+    /* static */ namelist_t *nl1, **mid;  /* Need not be local */
+    namelist_t *nl2;
+
+    nl1 = *(mid = &(*anl)->next);
+    do {
+	if ((nl1 = nl1->next) == NULL) break;
+	mid = &(*mid)->next;
+    } while ((nl1 = nl1->next) != NULL);
+
+    nl2 = *mid;
+    *mid = NULL;
+
+    if ((*anl)->next != NULL) sort(anl);
+    if (nl2->next != NULL) sort(&nl2);
+
+    nl1 = *anl;
+    for (;;) {
+	if (strcmp(nl1->name, nl2->name) <= 0) {
+	    if ((nl1 = *(anl = &nl1->next)) == NULL) {
+		*anl = nl2;
+		break;
+	    }
+	} else {
+	    *anl = nl2;
+	    nl2 = *(anl = &nl2->next);
+	    *anl = nl1;
+	    if (nl2 == NULL) break;
+	}
+    }
+}
+
+static namelist_t *collect(dir)
+char *dir;
+/* Return a sorted list of directory entries.  Returns null with errno != 0
+ * on error.
+ */
+{
+    namelist_t *names, **pn = &names;
+    DIR *dp;
+    struct dirent *entry;
+
+    if ((dp = opendir(dir)) == NULL) return NULL;
+
+    while ((entry = readdir(dp)) != NULL) {
+	if (strcmp(entry->d_name, ".") == 0) continue;
+	*pn = malloc(offsetof(namelist_t, name) + strlen(entry->d_name) + 1);
+	if (*pn == NULL) {
+	    closedir(dp);
+	    errno = ENOMEM;
+	    return NULL;
+	}
+	strcpy((*pn)->name, entry->d_name);
+	pn = &(*pn)->next;
+    }
+    closedir(dp);
+    *pn = NULL;
+    if (names != NULL && names->next != NULL) sort(&names);
+    errno = 0;
+    return names;
+}
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+    namelist_t *np;
+    char *rpath, *vpath;
+    static char cwd[1024];
+    static char work[64];
+    char *filename;
+    struct stat st;
+    struct tm *tmp;
+    static char month[][4] = {
+	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+    };
+
+    if(argc > 1) {
+	rpath = argv[1];
+	if (chdir(rpath) < 0) {
+	    fprintf(stderr, "dir2html: %s: %s\n", rpath, strerror(errno));
+	    return(-1);
+    	}
+    } else {
+	if(getcwd(cwd, sizeof(cwd)) == NULL) {
+	    fprintf(stderr, "dir2html: getcwd(): %s", strerror(errno));
+	    return(-1);
+	}
+	rpath = cwd;
+    }
+
+    if(argc > 2) {
+	vpath = argv[2];
+    } else {
+	vpath = rpath;
+    }
+
+    if ((np = collect(".")) == NULL && errno != 0) {
+	fprintf(stderr, "dir2html: %s: %s\n", vpath, strerror(errno));
+	return(-1);
+    }
+
+    printf("<HTML><HEAD><TITLE>Index of %s</TITLE></HEAD>\n", vpath);
+    printf("<BODY>\n");
+    printf("<H1>Index of %s</H1>\n", vpath);
+
+    printf("<PRE>\n");
+    printf("%-22s  %-17s  %s\n", "Name", "Last modified", "Size/Type");
+    printf("<HR>\n");
+
+    while (np != NULL) {
+	errno = 0;
+	filename = np->name;
+	np= np->next;
+
+	if (stat(filename, &st) < 0) continue;
+
+	printf("<A HREF=\"%s%s\">",
+	    filename, S_ISDIR(st.st_mode) ? "/" : "");
+	sprintf(work, "%.23s%s",
+	    filename, S_ISDIR(st.st_mode) ? "/" : "");
+	if (strcmp(filename, "..") == 0) strcpy(work, "Parent Directory");
+	printf("%-22.22s%s</A>",
+	    work, strlen(work) > 22 ? "&gt;" : " ");
+	tmp = localtime(&st.st_mtime);
+	printf(" %02d %s %d %02d:%02d",
+	    tmp->tm_mday, month[tmp->tm_mon], 1900+tmp->tm_year,
+	    tmp->tm_hour, tmp->tm_min);
+	if (S_ISREG(st.st_mode)) {
+	    if (st.st_size < 10240) {
+		sprintf(work, "%lu ", (unsigned long) st.st_size);
+	    } else
+	    if (st.st_size < 10240 * 1024L) {
+		sprintf(work, "%luK",
+		    ((unsigned long) st.st_size - 1) / 1024 + 1);
+	    } else {
+		sprintf(work, "%luM",
+		    ((unsigned long) st.st_size - 1) / (1024 * 1024L) + 1);
+	    }
+	} else {
+	    strcpy(work,
+		S_ISDIR(st.st_mode) ? "[dir]" :
+		S_ISBLK(st.st_mode) ? "[block]" :
+		S_ISCHR(st.st_mode) ? "[char]" :
+		S_ISFIFO(st.st_mode) ? "[pipe]" :
+					"[???]");
+	}
+	printf(" %8s\n", work);
+    }
+
+    printf("</PRE>\n");
+
+    printf("<HR>\n");
+    printf("<SMALL><i>Minix httpd 0.99</i></SMALL>\n");
+    printf("</BODY>\n");
+    printf("</HTML>\n");
+
+    return(0);
+}
Index: /trunk/minix/commands/httpd/dir2html.sh
===================================================================
--- /trunk/minix/commands/httpd/dir2html.sh	(revision 9)
+++ /trunk/minix/commands/httpd/dir2html.sh	(revision 9)
@@ -0,0 +1,42 @@
+# dir2html.sh by Michael Temari 03/03/96
+#
+#!/bin/sh
+if [ $# != 0 ]
+then
+cd $1
+fi
+dname=`pwd`
+fdname=$2
+if [ $dname != / ]
+then
+  dname=${dname}/
+fi
+echo "<HTML>"
+echo "<TITLE>"
+echo Directory of $fdname
+echo "</TITLE>"
+echo "<H1>"
+echo Directory of $fdname
+echo "</H1>"
+echo "<HR>"
+#
+ls $dname |
+{
+while read fname
+do
+lname=$fdname$fname
+echo "<H3>"
+echo -n "<A HREF=\""
+echo -n $lname
+echo -n "\">"
+echo -n $fname
+echo "</A><BR>"
+echo "</H3>"
+done
+}
+echo "<HR>"
+echo "<H6>"
+echo Directory Generated at `date`
+echo "</H6>"
+echo "</HTML>"
+exit 0
Index: /trunk/minix/commands/httpd/http.h
===================================================================
--- /trunk/minix/commands/httpd/http.h	(revision 9)
+++ /trunk/minix/commands/httpd/http.h	(revision 9)
@@ -0,0 +1,118 @@
+/* http.h
+ *
+ * This file is part of httpd.
+ *
+ * 02/17/1996 			Michael Temari <Michael@TemWare.Com>
+ * 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
+ * 12/29/2002			Michael Temari <Michael@TemWare.Com>
+ *
+ */
+
+#define	INDEX_FILE_NAME	"index.html"
+
+#define	HTTP_REQUEST_TYPE_SIMPLE	0
+#define	HTTP_REQUEST_TYPE_FULL		1
+#define	HTTP_REQUEST_TYPE_PROXY		2
+
+#define	HTTP_METHOD_UNKNOWN	0
+#define	HTTP_METHOD_OPTIONS	1
+#define	HTTP_METHOD_GET		2
+#define	HTTP_METHOD_HEAD	3
+#define	HTTP_METHOD_POST	4
+#define	HTTP_METHOD_PUT		5
+#define	HTTP_METHOD_PATCH	6
+#define	HTTP_METHOD_COPY	7
+#define	HTTP_METHOD_MOVE	8
+#define	HTTP_METHOD_DELETE	9
+#define	HTTP_METHOD_LINK	10
+#define	HTTP_METHOD_UNLINK	11
+#define	HTTP_METHOD_TRACE	12
+#define	HTTP_METHOD_WRAPPED	13
+
+#define	HTTP_STATUS_OK			200
+#define	HTTP_STATUS_CREATED		201
+#define	HTTP_STATUS_ACCEPTED		202
+#define	HTTP_STATUS_NO_CONTENT		204
+#define	HTTP_STATUS_MOVED_PERM		301
+#define	HTTP_STATUS_MOVED_TEMP		302
+#define	HTTP_STATUS_NOT_MODIFIED	304
+#define	HTTP_STATUS_USE_PROXY		305
+#define	HTTP_STATUS_BAD_REQUEST		400
+#define	HTTP_STATUS_UNAUTHORIZED	401
+#define	HTTP_STATUS_FORBIDDEN		403
+#define	HTTP_STATUS_NOT_FOUND		404
+#define	HTTP_STATUS_METHOD_NOT_ALLOWED	405
+#define	HTTP_STATUS_PROXY_AUTH_REQRD	407
+#define	HTTP_STATUS_LENGTH_REQUIRED	411
+#define	HTTP_STATUS_SERVER_ERROR	500
+#define	HTTP_STATUS_NOT_IMPLEMENTED	501
+#define	HTTP_STATUS_BAD_GATEWAY		502
+#define	HTTP_STATUS_SERVICE_UNAVAILABLE	503
+#define	HTTP_STATUS_GATEWAY_TIMEOUT	504
+#define	HTTP_STATUS_UNSUPPORTED_VERSION	505
+
+struct http_request {
+	int type;
+	int method;
+	char uri[256];
+	char url[256];
+	char query[256];
+	char host[256];
+	int port;
+	char useragent[256];
+	int vmajor;
+	int vminor;
+	time_t ifmodsince;
+	off_t size;
+	time_t msgdate;
+	int keepopen;
+	char wwwauth[128];
+	char authuser[128];
+	char authpass[128];
+	char cookie[128];
+};
+
+struct http_reply {
+	int status;
+	char statusmsg[128];
+	int keepopen;
+	int headers;
+	char *mtype;
+	char realurl[256];
+	struct auth *auth;
+	int urlaccess;
+	off_t size;
+	time_t modtime;
+	int fd;
+	int ofd;
+	int pid;
+};
+
+/* from httpd.c */
+
+extern FILE *stdlog;
+extern FILE *dbglog;
+
+/* from reply.c */
+
+_PROTOTYPE(int sendreply, (struct http_reply *rp, struct http_request *rq));
+
+/* from request.c */
+
+_PROTOTYPE(int getrequest, (struct http_request *rq));
+
+/* from process.c */
+
+_PROTOTYPE(int processrequest, (struct http_request *rq, struct http_reply *rp));
+
+/* from police.c */
+
+_PROTOTYPE(int police, (struct http_request *rq, struct http_reply *rp));
+
+/* from cgiexec.c */
+
+_PROTOTYPE(int cgiexec, (struct http_request *rq, struct http_reply *rp));
+
+/* from proxy.c */
+
+_PROTOTYPE(void proxy, (struct http_request *rq, struct http_reply *rp));
Index: /trunk/minix/commands/httpd/http_status.5
===================================================================
--- /trunk/minix/commands/httpd/http_status.5	(revision 9)
+++ /trunk/minix/commands/httpd/http_status.5	(revision 9)
@@ -0,0 +1,73 @@
+.TH HTTP_STATUS 5
+.SH 
+http_status \- HTTP status numbers and their meanings
+.SH DESCRIPTION
+These are the HTTP status numbers defined in 
+.BI http.h
+in the source directory,
+.BI /usr/local/src/httpdxxx.
+The message you see on your screen when a page cannot be accessed is 
+normally generated by your browser.
+.P
+HTTP_STATUS_OK                  200
+.br
+HTTP_STATUS_CREATED             201
+.br
+HTTP_STATUS_ACCEPTED            202
+.br
+HTTP_STATUS_NO_CONTENT          204
+.br
+HTTP_STATUS_MOVED_PERM          301
+.br
+HTTP_STATUS_MOVED_TEMP          302
+.br
+HTTP_STATUS_NOT_MODIFIED        304
+.br
+HTTP_STATUS_USE_PROXY           305
+.br
+HTTP_STATUS_BAD_REQUEST         400
+.br
+HTTP_STATUS_UNAUTHORIZED        401
+.br
+HTTP_STATUS_FORBIDDEN           403
+.br
+HTTP_STATUS_NOT_FOUND           404
+.br
+HTTP_STATUS_METHOD_NOT_ALLOWED  405
+.br
+HTTP_STATUS_PROXY_AUTH_REQRD    407
+.br
+HTTP_STATUS_LENGTH_REQUIRED     411
+.br
+HTTP_STATUS_SERVER_ERROR        500
+.br
+HTTP_STATUS_NOT_IMPLEMENTED     501
+.br
+HTTP_STATUS_BAD_GATEWAY         502
+.br
+HTTP_STATUS_SERVICE_UNAVAILABLE 503
+.br
+HTTP_STATUS_GATEWAY_TIMEOUT     504
+.br
+HTTP_STATUS_UNSUPPORTED_VERSION 505
+.br
+
+.SH FILES
+.TP 25n
+.B /usr/local/src/httpdxxx/http.h 
+.SH "SEE ALSO"
+The definitive source of information on the HTTP protocol is the
+.B "World Wide Web Consortium"  
+web page at 
+.B http://www.w3c.org .
+.P
+A draft version of the HTTP 1.1 specification is available on the Minix1
+websites. For more information on status codes go to this URL:
+.B http://minix1.hampshire.edu/http11.html#Status-Codes
+.SH AUTHOR
+The Minix httpd server was created by and is maintained by Michael Temari 
+<Michael@TemWare.Com>
+.br
+This man page was compiled by Al Woodhull <awoodhull@hampshire.edu>
+.P
+updated 2003-07-06
Index: /trunk/minix/commands/httpd/httpd.8
===================================================================
--- /trunk/minix/commands/httpd/httpd.8	(revision 9)
+++ /trunk/minix/commands/httpd/httpd.8	(revision 9)
@@ -0,0 +1,104 @@
+.TH HTTPD 8
+.SH NAME
+httpd, in.httpd, dir2html \- a web server for Minix
+.SH SYNOPSIS
+.B httpd
+.RB [\-t|\-v]
+.RI [ config_file ]
+.br
+.B "tcpd http /usr/local/bin/in.httpd"
+.br 
+.B dir2html
+.RB [directory] 
+.SH DESCRIPTION
+.B httpd
+is a World Wide Web (WWW) server written by Michael Temari.  It was
+written from scratch so the setup and configuration will not be like
+other web servers.
+.P
+.B in.httpd 
+is linked to 
+.B httpd.
+This alternate name is used to indicate the program is a server that is
+started by
+.B tcpd,  
+a program which listens for incoming TCP connections on the passed
+port (defined in 
+.BI /etc/services ).  
+When a connection comes in 
+.B tcpd
+forks and starts the given daemon program, after possibly checking for access
+restrictions and logging the connection.  Therefore to start 
+.B httpd
+you use:
+.br
+.B  "tcpd http /usr/local/bin/in.httpd &"
+.br
+or
+.br
+.B "daemonize tcpd http /usr/local/bin/in.httpd"
+.P
+.B (daemonize 
+is a shell function defined in 
+.BI/usr/etc/rc 
+in Minix 2.0.3 and later releases which starts programs as daemons).
+.P
+.B dir2html
+is an accessory program that produces a directory listing formatted as 
+web page for the current directory or for a directory specified as an 
+argument. It is called by
+.B httpd
+when a web client references a directory that includes no index.html
+file (or whatever alternative to index.html that may be defined in 
+/etc/httpd.conf). Since it writes to standard output it may also be called 
+as a standalone program.
+.P
+Options for 
+.B httpd
+are:
+.SH OPTIONS
+.TP
+.B \-t
+This tells the server to parse the configuration file so that you can
+see if it is the way you want it.  You may also pass the name of your
+configuration file if it is not the default /etc/httpd.conf.
+.TP
+.B \-v
+Shows the server version, then exits.
+.br
+.IR config_file
+normally /etc/httpd.conf
+.SH FILES
+.TP 25n
+.B /etc/httpd.conf
+The configuration file.
+.P
+.B /etc/httpd.mtype
+Extension to configuration file defining MIME types.
+.P
+.B /usr/adm/httpd.log
+Log file. The file must exist for logging to begin.
+.SH "SEE ALSO"
+.BR httpd.conf (5)
+.br
+.BR http_status (5)
+.br
+.BR serv.access (5)
+.br
+.BR tcpd (8)
+.SH NOTES
+Running a server exposed to the Internet is risky to the host system and 
+to the local network. Consult with the owner of your net before you go 
+public. Read the 
+.B SECURITY
+document in the source directory.
+.SH BUGS
+None are known, but there are surely some unknown ones. Be careful!
+.SH AUTHOR
+The Minix httpd server was created by and is maintained by Michael Temari
+<Michael@TemWare.Com>
+.br
+This man page was compiled by Al Woodhull <awoodhull@hampshire.edu>
+.P
+updated 2003-07-06
+
Index: /trunk/minix/commands/httpd/httpd.c
===================================================================
--- /trunk/minix/commands/httpd/httpd.c	(revision 9)
+++ /trunk/minix/commands/httpd/httpd.c	(revision 9)
@@ -0,0 +1,175 @@
+/* httpd.c
+ *
+ * httpd	A Server implementing the HTTP protocol.
+ *
+ * usage:	tcpd http httpd &
+ *
+ * 02/17/1996 			Michael Temari <Michael@TemWare.Com>
+ * 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
+ * 12/29/2002 			Michael Temari <Michael@TemWare.Com>
+ * 07/04/2003			Al Woodhull <awoodhull@hampshire.edu>
+ *
+ */
+
+#include <stdlib.h>	
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include "http.h"
+#include "utility.h"
+#include "net.h"
+#include "config.h"
+
+FILE *stdlog = (FILE *)NULL;
+FILE *dbglog = (FILE *)NULL;
+
+char umsg[80];
+
+_PROTOTYPE(int main, (int argc, char *argv[]));
+
+struct http_request request;
+struct http_reply reply;
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+char *prog;
+int opt_t;
+char *cfg = (char *)NULL;
+struct passwd *pwd;
+int s;
+
+   strcpy(umsg, "Usage: ");
+   strcat(umsg, argv[0]);
+   strcat(umsg, " [-t|v] [config_file]\n");
+
+   /* parse program name */
+   prog = strrchr(*argv, '/');
+   if(prog == (char *)NULL)
+   	prog = *argv;
+   else
+   	prog++;
+   argv++;
+   argc--;
+
+   /* Any options */
+   if(argc)
+        if(argv[0][0] == '-') {
+             switch (argv[0][1]) {
+                  case 't' : opt_t = 1;
+                             argv++;
+                             argc--;
+                             break;
+                  case 'v' : fprintf(stderr, VERSION"\n"); 
+                             exit(EXIT_SUCCESS);
+                             break;
+                  default  : fprintf(stderr, VERSION"\n"); 
+                             fprintf(stderr, umsg); 
+                             exit(EXIT_FAILURE);
+             }
+        }
+
+   /* Did they specify an alternate configuration file? */
+   if(argc) {
+   	cfg = *argv++;
+   	argc--;
+   }
+
+   /* Read the configuration settings */
+   if(readconfig(cfg, opt_t)) {
+   	fprintf(stderr, "httpd: Error reading configuration file.\n");
+   	return(-1);
+   }
+
+   /* Option t is to test configuration only */
+   if(opt_t)
+	return(0);
+
+   /* Open log file for append if it exists */
+   if(LogFile != NULL)
+	if((stdlog = fopen(LogFile, "r")) != (FILE *)NULL) {
+		fclose(stdlog);
+		stdlog = fopen(LogFile, "a");
+	}
+
+   /* Open debug log file for append if it exists */
+   if(DbgFile != NULL)
+	if((dbglog = fopen(DbgFile, "r")) != (FILE *)NULL) {
+		fclose(dbglog);
+		dbglog = fopen(DbgFile, "a");
+   }
+
+#if 0
+   /* Get some network information */
+   GetNetInfo();
+#endif
+
+   /* If user defined then prepare to secure as user given */
+   if(User != NULL)
+	if((pwd = getpwnam(User)) == (struct passwd *)NULL) {
+   		fprintf(stderr, "httpd: unable to find user %s\n", User);
+  	 	return(-1);
+	}
+
+   /* If Chroot defined then secure even more by doing a chroot */
+   if(Chroot != NULL) {
+	if(chroot(Chroot)) {
+		fprintf(stderr, "httpd: unable to chroot\n");
+		return(-1);
+	}
+	if(chdir("/")) {
+   		fprintf(stderr, "httpd: unable to chroot\n");
+   		return(-1);
+	}
+   }
+
+   /* If user defined then secure as user given */
+   if(User != NULL)
+	if(setgid(pwd->pw_gid) || setuid(pwd->pw_uid)) {
+   		fprintf(stderr, "httpd: unable to set user\n");
+   		return(-1);
+	}
+
+#if DAEMON
+   /* Standalone? */
+   if (strncmp(prog, "in.", 3) != 0) {
+       /* Does not start with "in.", so not started from inetd/tcpd. */
+       /* XXX - Port name/number should be a config file option. */
+       daemonloop("http");
+   }
+#endif
+
+   /* Get some network information */
+   GetNetInfo();
+
+   /* log a connection */
+   if(dbglog != (FILE *)NULL) {
+	fprintf(dbglog, "CONNECT: %d %s %s\n", getpid(),
+		rmthostname, logdate((time_t *)NULL));
+	fflush(dbglog);
+   }
+
+   /* loop getting, processing and replying to requests */
+   while(!(s = getrequest(&request))) {
+	if(processrequest(&request, &reply)) break;
+	if(stdlog != (FILE *)NULL) {
+		fprintf(stdlog, "%s %s %d %d %s\n",
+			logdate((time_t *)NULL), rmthostname,
+			request.method, reply.status, request.url);
+		fflush(stdlog);
+	}
+	if(sendreply(&reply, &request)) break;
+	if(!reply.keepopen) break;
+   }
+   if(s == 1 && stdlog != (FILE *)NULL) {
+	fprintf(stdlog, "%s %s %d %d %s\n",
+		logdate((time_t *)NULL), rmthostname,
+		request.method, 999, request.url);
+	fflush(stdlog);
+   }
+
+   return(0);
+}
Index: /trunk/minix/commands/httpd/httpd.conf
===================================================================
--- /trunk/minix/commands/httpd/httpd.conf	(revision 9)
+++ /trunk/minix/commands/httpd/httpd.conf	(revision 9)
@@ -0,0 +1,159 @@
+# httpd.conf Sample httpd.conf file By Michael Temari 7/03/2003
+
+#serverroot path
+#
+# path = sets the translation for //
+#
+# these have special meaning if at beginning of path
+#
+# /~user = gets replaced with user home directory
+
+serverroot	/~www
+
+#user username
+#
+# if present the server will run as the given username otherwise the
+# server will run as who ever started it (normally root).
+
+user www
+
+#chroot directory
+#
+# if present the server will be chroot'ed to the given directory name
+# normally the home directory of username given above.  Be aware if this
+# is set then you can only access stuff off this new root.
+#
+# these have special meaning if at beginning of the directory
+#
+#  //    = gets replaced by serverroot directory
+# /~user = gets replaced with user home directory
+
+#chroot /~www
+
+#logfile filename
+#
+# the file must exist also and a log of http transactions will be kept
+#
+# these have special meaning if at the beginning of the filename
+#
+#  //    = gets replaced by serverroot directory
+# /~user = gets replaced with user home directory
+
+logfile	/usr/adm/httpd.log
+
+#dbgfile filename
+#
+# the file must exist also and a debug log of http transactions will be kept
+#
+# these have special meaning if at the beginning of the filename
+#
+#  //    = gets replaced by serverroot directory
+# /~user = gets replaced with user home directory
+
+dbgfile	/usr/adm/httpd.dbg
+
+# dirsend  [list of files to try until 1st one is found]
+#
+
+dirsend		index.htm
+
+# direxec [script to run for automatic directory page output]
+#
+#
+# these have special meaning if at beginning of script
+#
+#  //    = gets replaced by serverroot directory
+# /~user = gets replaced with user home directory
+#
+
+direxec		/usr/local/bin/dir2html
+
+# vhost hostname VhostRoot
+#
+# vhost is for defining access for virtual hosts.  If none are configured then
+# any host is accepted.  If specified then access is only granted for requests
+# for hosts which are configured here.  In the Vpath section below the /// gets
+# translated to the corresponding VhostRoot.
+
+# vhost	temware.dyndns.org	//doc/
+# vhost	minix.homeip.net	//doc2/
+
+# auth authname authdescription access [passwdfile [users]]
+#
+# auth defines any access authorization to be used in vpath
+#
+# authname = name to give to this authorization (case insensitive)
+# authdescription = Description of this authorization
+# access = r=read, w=write, x=execute, h=headers (other than rwxh then no access)
+# NOTE: r=file should be read, w=file can be overwrote
+# NOTE: x=file should be executed
+# NOTE: h=headers (executing program will produce all http headers)
+# NOTE: access is on top of unix access
+# passwdfile = Name of passwd file to be used (. means /etc/passwd)
+#              (if none given then no user check)
+# users = valid users for this authorization (if none given then all users valid)
+#
+# these have special meaning if at beginning of passwdfile
+#
+#  //    = gets replaced by serverroot directory
+# /~user = gets replaced with user home directory
+#
+
+auth	AnyBody		AnyBody			R
+	System		System_User		R	.
+	Uploads		Uploads			RW	.	root
+
+# proxyauth authname authdescription access [passwdfile [users]]
+#
+# proxyauth defines any access authorization to be used for Proxy access
+#
+# authname = Same as auth above
+# authdescription = Same as auth above
+# access = Must be R to allow proxy
+# passwdfile = Same as auth above
+# users = Same as auth above
+#
+
+# proxyauth
+#	Proxy		Proxy			R	.
+
+
+# vpath from to auth
+#
+# vpath sets up a list of url path translations and authorizations
+#
+#   from = user specified url
+#          *=wildcard, $=wildard, but keep path for passing to program
+#     to = real location
+#   auth = authname from above (null for no authorization)
+# access = r-read, w-write, x-execute (if not given taken from auth record)
+#        = h-headers (executing program will produce all http headers)
+#
+# these have special meaning if at beginning of to or serverroot fields
+#
+#  //    = gets replaced by serverroot directory
+#  ///   = gets replaced by vhost root directory if configured otherwise same as //
+#  .     = specified authorization only, use other translation elsewhere
+# /~user = gets replaced with user home directory
+#
+
+vpath	*			.			AnyBody
+	/*			///			AnyBody
+	/index.htm		.			AnyBody		X
+	/ip			.			AnyBody		X
+	/c1d1$			//exec/cdrom		AnyBody		X
+	/c1d2$			//exec/cdrom		AnyBody		X
+	/uploads*		.			Uploads
+	/src*			/usr/src		AnyBody		R
+
+# include filename
+#
+# include tells the server to continue parsing configuration information
+# in the given filename 
+#
+# these have special meaning if at beginning of filename
+#
+#  //    = gets replaced by serverroot directory
+# /~user = gets replaced with user home directory
+
+include	//etc/httpd.mtype
Index: /trunk/minix/commands/httpd/httpd.conf.5
===================================================================
--- /trunk/minix/commands/httpd/httpd.conf.5	(revision 9)
+++ /trunk/minix/commands/httpd/httpd.conf.5	(revision 9)
@@ -0,0 +1,328 @@
+.TH HTTPD.CONF 5
+.SH NAME
+httpd.conf httpd.mtype \- configuration files for the Minix httpd web server
+.SH SYNOPSIS
+.B /etc/httpd.conf
+.B /etc/httpd.mtype
+.SH DESCRIPTION
+.B /etc/httpd.conf 
+is the configuration file for the Minix httpd web server written by
+Michael Temari.  A sample version is included with the distribution
+archive and is unpacked in the source directory (normally
+.BI /usr/local/src/httpdxxx).
+Also provided is an example
+.B httpd.mtype
+file. This is an extension of the main configuration file which is normally
+included when the main file is read.
+.P
+The makefile does not install 
+.B httpd.conf 
+and 
+.B httpd.mtype
+automatically. The sample files included in the distribution are only  
+examples, you must copy it and edit them for the needs of your own 
+installation.
+.SH CONFIGURATION FILE FORMAT
+.B httpd.conf
+is an ascii file which consists of lines of the following form:
+.P
+.B directive LWS [parameters separated by LWS]
+.br
+NOTE: LWS denotes Linear White Space which is spaces and/or tabs
+.SH CONFIGURATION FILE DIRECTIVES
+The following are valid configuration file directives (listed in the order 
+they appear in the sample 
+.B httpd.conf 
+file provided in the distribution):
+.P
+.B serverroot user chroot logfile dbgfile dirsend direxec vhost auth
+.B proxyauth vpath include mtype 
+.P
+To make the file more readable, for directives which occupy multiple
+lines you may eliminate the directive on lines after the first and begin 
+these lines with LWS.
+
+.SH DESCRIPTIONS OF DIRECTIVES
+.P
+.B serverroot path
+
+The 
+.B serverroot 
+directive sets the translation for 
+.B // 
+to the given 
+.B path.
+
+.B user username
+
+The 
+.B user 
+directive causes the server to run as the given 
+.B username 
+otherwise the server will run as whoever started it (normally root).
+
+.B chroot directory
+
+The 
+.B chroot 
+directive causes the server to chroot to the given directory after
+the configuration and log files have been opened.  Normally this will be the
+home directory of the given username in the user directive.
+.br
+NOTE: 
+.B /~user 
+will be translated to the home directory of
+.B user.
+.br
+NOTE:
+.B // 
+will be translated to the serverroot directory.
+.br
+NOTE: if this directive is used then beware of the consequences.
+
+.B logfile filename
+
+The 
+.B logfile 
+directive tells the server where to log http transactions.
+.br
+NOTE: the log file must exist to enable logging.
+
+.B dbgfile filename
+
+The 
+.B dbgfile 
+directive tells the server where to log debugging of http transactions.
+.br
+NOTE: the debug log file must exist to enable debug logging.
+
+.B dirsend filelist
+
+The 
+.B dirsend 
+directive tells the server that when a directory is requested
+that it should send the first file that it finds in the directory from the
+.B filelist 
+for the request.
+
+.B direxec program
+
+The 
+.B direxec 
+directive tells the server that when a directory is requested
+and no file is found from the 
+.B dirsend 
+directive that it should run the given 
+.B program.
+.br
+NOTE: the program normally generates a directory listing on the fly using
+the 
+.B dir2html
+program.
+.br
+NOTE: the program access is considered 
+.B X 
+with no access restrictions.
+
+.B vhost hostname vhostroot
+
+The 
+.B vhost 
+directive is for defining access for virtual hosts.  If none are configured 
+then any host is accepted.  If specified then access is only granted for 
+requests for hosts which are configured here.  In the 
+.B vpath 
+section below the 
+.B /// 
+gets translated to the corresponding 
+.B vhostroot.
+
+
+.B auth authname authdescription access [passwdfile [users]]
+
+The 
+.B auth 
+directive sets up different authorizations with the server.  The
+.B authname 
+is the name given to the authorization and is case insensitive.
+The 
+.B authdescription 
+is the description of the authorization and is what
+the user will see when asked to enter a username and password.  The
+access is one or more of 
+.B (RWX).  
+.B R 
+tells the server the URL can be read.  
+.B W 
+tells the server the URL can be overwritten.  
+.B X 
+tells the server
+that the URL can and should be executed.  Access is in addition to normal
+Unix security considerations.  For instance a file that can be written to
+that does not have the 
+.B W 
+access will have an error returned.  The
+.B passwdfile 
+is the name of the password file to validate users against.  If
+.B passwdfile 
+is given as 
+.B '.' 
+then the system password file
+.B (/etc/passwd)
+will be used.  If no 
+.B passwdfile 
+is given then no authorization is allowed for anyone.  If no 
+.B users 
+are given then any validated user is authorized, otherwise only the given 
+.B users 
+are allowed.
+
+.B proxyauth authname authdescription access [passwdfile [users]]
+
+The 
+.B proxyauth 
+directive defines access authorization to be used for Proxy access.
+.br
+.B authname 
+= Same as auth above
+.br
+.B authdescription 
+= Same as auth above
+.br
+.B access 
+= Must be R to allow proxy
+.br
+.B passwdfile 
+= Same as auth above
+.br
+.B users 
+= Same as auth above
+
+.B vpath from to [auth [access]]
+
+The 
+.B vpath 
+directive sets up URL path translations and authorizations.  A
+requested  URL that matches 
+.B from 
+will be translated to 
+.B to 
+with the given 
+.B auth 
+and 
+.B access.  
+If 
+.B auth 
+does not exist then the URL will have no 
+.B access.
+If 
+.B access 
+is not given then the access is taken from the 
+.B auth 
+record (see above).  A 
+.B '.' 
+in place of the 
+.B to 
+means that the server should use a translation from another 
+.B vpath 
+record, but associate the given 
+.B auth 
+and access with the requested URL.  A 
+.B '*' 
+may be at the end only of the 
+.B from
+to provide a wildcard match.  For example if the 
+.B from 
+has 
+.B /AB* 
+then any of
+.B /ABCDEF 
+or 
+.B /AB 
+or 
+.B /ABmichael 
+will match, but 
+.B /AD or 
+.B /a 
+will not.  The requested URL is first checked against each 
+.B vpath 
+record until an exact match (meaning URL match 
+.B from 
+and 
+.B from 
+had no 
+.B '*') 
+is found or the end of the list.  Therefore a wildcard match will match 
+the last 
+.B from in the list in which it matched.
+.br
+NOTE: if at the beginning of the to field
+.br
+      /~user will get translated to the home directory of the given user
+.br
+      // wile get translated to the serverroot directory
+
+.B include filename
+
+The 
+.B include 
+directive tells the server to read configuration information
+from the given filename.
+.br
+NOTE: normally you get 
+.B mtype 
+directives in an included file.
+
+.B mtype mimetype extensions
+
+The 
+.B mtype 
+directive tells the server what 
+.B mimetype 
+to associate with files which have any of the given 
+.B extensions.  
+If no match is found then the file will be treated as 
+.B application/octet-stream.
+
+
+.SH FILES
+.B /etc/httpd.conf
+.B /etc/httpd.mtype
+.B /etc/passwd
+.SH "SEE ALSO"
+.BR httpd (8)
+.BR http_status (5)
+.SH NOTES
+The source directory contains a commented sample 
+.B httpd.conf 
+and 
+.B httpd.mtype
+files
+P. 
+You can run the server as
+.B httpd -t /etc/httpd.conf
+to see whether the configuration file is being parsed correctly.
+.P
+Although standard Minix does not have a graphical interface to support
+browsers such as Netscape and Microsoft Internet Explorer, the 
+.B lynx
+browser can be used on 32-bit Minix systems with enough memory. You can point 
+lynx to your own site to browse your own pages.
+When debugging a web server there is nothing quite like browsing your own
+pages to see whether things are working right. That said, be aware that
+different web browsers may vary in how they interpet standard web page 
+features, and will certainly vary in how they interpret "extensions" to
+the HTML standards. So checking a page with several browsers on several 
+platforms is always a good idea.
+.SH BUGS
+Not really a bug, but you can get in trouble if a real directory you want
+to access shares the first part of its name with a 
+.B vpath
+definition. You just have to pay attention to the directory names you use.
+.SH AUTHOR
+The Minix httpd server was created by and is maintained by Michael Temari
+<Michael@TemWare.Com>
+.br
+This man page was compiled by Al Woodhull <awoodhull@hampshire.edu>
+.P
+updated 2003-07-06
Index: /trunk/minix/commands/httpd/httpd.mtype
===================================================================
--- /trunk/minix/commands/httpd/httpd.mtype	(revision 9)
+++ /trunk/minix/commands/httpd/httpd.mtype	(revision 9)
@@ -0,0 +1,40 @@
+# mime types By Michael Temari 12/29/2002 Ver 0.40
+
+# if a file extension is not found in the configuration below the default
+# mime type will be application/octet-stream.  This default can be changed
+# by entering a line with a mime type only with no extension.
+
+mtype
+	application/octet-stream
+	application/compress		.Z
+	application/msword		.doc
+	application/octet-stream	.bin	.exe
+	application/pdf			.pdf
+	application/postscript		.ps	.ai	.eps
+	application/smil		.smil
+	application/x-gtar		.gtar
+	application/x-gzip		.gz
+	application/x-sh		.sh
+	application/x-pn-realaudio	.ra	.ram
+	application/x-tar		.tar
+	application/zip			.zip
+	audio/basic			.au	.snd
+	audio/mpeg			.mp3
+	audio/x-aiff			.aif	.aiff	.aifc
+	audio/x-midi			.mid
+	audio/x-wav			.wav
+	image/bmp			.bmp
+	image/gif			.gif
+	image/jpeg			.jpg	.jpeg	.jpe
+	image/png			.png
+	image/tiff			.tiff	.tif
+	image/x-rgb			.rgb
+	image/x-xbitmap			.xbm
+	multipart/x-www-form-urlencoded	.wfu
+	text/html			.html	.htm
+	text/plain			.txt	.c	.h
+	text/richtext			.rtf	.rtx
+	video/mpeg			.mpg	.mpeg	.mpe
+	video/quicktime			.qt	.mov
+	video/x-msvideo			.avi
+	video/x-sgi-movie		.movie
Index: /trunk/minix/commands/httpd/httpd0993.txt
===================================================================
--- /trunk/minix/commands/httpd/httpd0993.txt	(revision 9)
+++ /trunk/minix/commands/httpd/httpd0993.txt	(revision 9)
@@ -0,0 +1,41 @@
+httpd0993 --- A www server for Minix 2.0  
+written by Michael Temari <Michael@TemWare.Com> release 0.993 2003-07-??
+
+Httpd is a World Wide Web (WWW) server.  I wrote it from scratch so
+the setup and configuration will not be like other web servers though
+hopefully by reading this document there will be no problems in getting
+my web server up and running on your Minix system.
+
+This is the web server in use on minix1.hampshire.edu and
+minix1.bio.umass.edu.
+
+Installation: unpack the tarball in /usr/local/src or another directory 
+of your choice:
+zcat < httpd0993.tar.Z | tar xvfp -
+
+An httpd0993 directory will be created and files will be unpacked
+there.  The README file explains compilation, installation,
+configuration, and use. 
+
+Changes for release 0.993: 
+
+- a new method of authorizing proxy.  You will no longer need the Proxy
+entry in Auth and can remove the http://* entry in vpath.  The old way
+allowed for having different authorizations depending on what URLs were
+asked for via proxy, i.e., you could allow proxy access only to
+http:://www.hampshire.edu/. Now it is just a simple authorization for
+allowing proxy or not.  
+
+- avoids using a Minix 2.0.3 library call that was not present in Minix
+2.0.2, and thus can be compiled with either of the two most recent
+Minix releases.  
+
+- a -v option has been added to display the current version then exit.
+
+- man pages added, other documentation updated.
+
+Changes for release 0.99: You can set a default in the httpd.mtype
+file.  A mime type with no extensions on a line will be the default.
+Previously recompilation was needed to change the default mime type. 
+
+updated 2003-07-07
Index: /trunk/minix/commands/httpd/net.c
===================================================================
--- /trunk/minix/commands/httpd/net.c	(revision 9)
+++ /trunk/minix/commands/httpd/net.c	(revision 9)
@@ -0,0 +1,240 @@
+/* net.c
+ *
+ * This file is part of httpd.
+ *
+ * 01/25/1996 			Michael Temari <Michael@TemWare.Com>
+ * 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
+ * 12/29/2002 			Michael Temari <Michael@TemWare.Com>
+ *
+ */
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/socket.h>
+#include <net/gen/netdb.h>
+
+#include "net.h"
+
+_PROTOTYPE(static void release, (int *fd));
+
+ipaddr_t myipaddr, rmtipaddr;
+tcpport_t myport, rmtport;
+char myhostname[256];
+char rmthostname[256];
+char rmthostaddr[3+1+3+1+3+1+3+1];
+
+void GetNetInfo()
+{
+nwio_tcpconf_t tcpconf;
+int s;
+struct hostent *hostent;
+
+   /* Ask the system what our hostname is. */
+   if(gethostname(myhostname, sizeof(myhostname)) < 0)
+	strcpy(myhostname, "unknown");
+
+   /* lets get our ip address and the clients ip address */
+   s = ioctl(0, NWIOGTCPCONF, &tcpconf);
+   if(s < 0) {
+   	myipaddr = 0;
+   	myport = 0;
+   	rmtipaddr = 0;
+   	rmtport = 0;
+   	strcpy(rmthostname, "??Unknown??");
+	strcpy(rmthostaddr, "???.???.???.???");
+   	return;
+   }
+
+   myipaddr = tcpconf.nwtc_locaddr;
+   myport = tcpconf.nwtc_locport;
+   rmtipaddr = tcpconf.nwtc_remaddr;
+   rmtport = tcpconf.nwtc_remport;
+
+   /* Look up the host name of the remote host. */
+   hostent = gethostbyaddr((char *) &rmtipaddr, sizeof(rmtipaddr), AF_INET);
+   if(!hostent)
+	strncpy(rmthostname, inet_ntoa(rmtipaddr), sizeof(rmthostname)-1);
+   else
+	strncpy(rmthostname, hostent->h_name, sizeof(rmthostname)-1);
+
+   strcpy(rmthostaddr, inet_ntoa(rmtipaddr));
+
+   rmthostname[sizeof(rmthostname)-1] = '\0';
+
+   return;
+}
+
+static void release(fd)
+int *fd;
+{
+   if(*fd != -1) {
+	close(*fd);
+	*fd= -1;
+   }
+}
+
+void daemonloop(service)
+char *service;
+{
+tcpport_t port;
+struct nwio_tcpcl tcplistenopt;
+struct nwio_tcpconf tcpconf;
+struct nwio_tcpopt tcpopt;
+struct servent *servent;
+char *tcp_device;
+int tcp_fd, client_fd, r;
+int pfd[2];
+unsigned stall= 0;
+
+   if((servent= getservbyname(service, "tcp")) == NULL) {
+	unsigned long p;
+	char *end;
+
+	p = strtoul(service, &end, 0);
+	if(p <= 0 || p > 0xFFFF || *end != 0) {
+		fprintf(stderr, "httpd: %s: Unknown service\n", service);
+		exit(1);
+	}
+	port= htons((tcpport_t) p);
+   } else
+	port= servent->s_port;
+
+   /* No client yet. */
+   client_fd= -1;
+
+   while (1) {
+   	if((tcp_device = getenv("TCP_DEVICE")) == NULL)
+   		tcp_device = TCP_DEVICE;
+	if ((tcp_fd= open(tcp_device, O_RDWR)) < 0) {
+			fprintf(stderr, "httpd: Can't open %s: %s",
+				tcp_device, strerror(errno));
+			if (errno == ENOENT || errno == ENODEV
+							|| errno == ENXIO) {
+				exit(1);
+			}
+			goto bad;
+		}
+
+		tcpconf.nwtc_flags= NWTC_LP_SET | NWTC_UNSET_RA | NWTC_UNSET_RP;
+		tcpconf.nwtc_locport= port;
+
+		if (ioctl(tcp_fd, NWIOSTCPCONF, &tcpconf) < 0) {
+			fprintf(stderr, "httpd: Can't configure TCP channel",
+				strerror(errno));
+			exit(1);
+		}
+
+#ifdef NWTO_DEL_RST
+		tcpopt.nwto_flags= NWTO_DEL_RST;
+
+		if (ioctl(tcp_fd, NWIOSTCPOPT, &tcpopt) < 0) {
+			fprintf(stderr, "httpd: Can't set TCP options",
+				strerror(errno));
+			exit(1);
+		}
+#endif
+
+		if (client_fd != -1) {
+			/* We have a client, so start a server for it. */
+
+#ifdef NWTO_DEL_RST
+			tcpopt.nwto_flags= 0;
+			(void) ioctl(client_fd, NWIOSTCPOPT, &tcpopt);
+#endif
+
+			fflush(NULL);
+
+			/* Create a pipe to serve as an error indicator. */
+			if (pipe(pfd) < 0) {
+				fprintf(stderr, "httpd: pipe", strerror(errno));
+				goto bad;
+			}
+
+			/* Fork twice to daemonize child. */
+			switch (fork()) {
+			case -1:
+				fprintf(stderr, "httpd: fork", strerror(errno));
+				close(pfd[0]);
+				close(pfd[1]);
+				goto bad;
+			case 0:
+				close(tcp_fd);
+				close(pfd[0]);
+				switch (fork()) {
+				case -1:
+					fprintf(stderr, "httpd: fork",
+						strerror(errno));
+					write(pfd[1], &errno, sizeof(errno));
+					exit(1);
+				case 0:
+					break;
+				default:
+					exit(0);
+				}
+				dup2(client_fd, 0);
+				dup2(client_fd, 1);
+				close(client_fd);
+				close(pfd[1]);
+
+				/* Break out of the daemon loop, continuing with
+				 * the normal httpd code to serve the client.
+				 */
+				return;
+
+			default:
+				release(&client_fd);
+				close(pfd[1]);
+				wait(NULL);
+				r= read(pfd[0], &errno, sizeof(errno));
+				close(pfd[0]);
+				if (r != 0) goto bad;
+				break;
+			}
+		}
+
+		/* Wait for a new connection. */
+		tcplistenopt.nwtcl_flags= 0;
+
+		while (ioctl(tcp_fd, NWIOTCPLISTEN, &tcplistenopt) < 0) {
+			if (errno != EAGAIN) {
+				fprintf(stderr, "httpd: Unable to listen: %s",
+					strerror(errno));
+			}
+			goto bad;
+		}
+
+		/* We got a connection. */
+		client_fd= tcp_fd;
+		tcp_fd= -1;
+
+		/* All is well, no need to stall. */
+		stall= 0;
+		continue;
+
+	bad:
+		/* All is not well, release resources. */
+		release(&tcp_fd);
+		release(&client_fd);
+
+		/* Wait a bit if this happens more than once. */
+		if (stall != 0) {
+			sleep(stall);
+			stall <<= 1;
+		} else {
+			stall= 1;
+		}
+	}
+}
Index: /trunk/minix/commands/httpd/net.h
===================================================================
--- /trunk/minix/commands/httpd/net.h	(revision 9)
+++ /trunk/minix/commands/httpd/net.h	(revision 9)
@@ -0,0 +1,17 @@
+/* net.h
+ *
+ * This file is part of httpd.
+ *
+ *
+ * 01/25/1996 			Michael Temari <Michael@TemWare.Com>
+ * 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
+ * 12/29/2002			Michael Temari <Michael@TemWare.Com>
+ *
+ */
+
+_PROTOTYPE(void GetNetInfo, (void));
+_PROTOTYPE(void daemonloop, (char *service));
+
+extern char myhostname[256];
+extern char rmthostname[256];
+extern char rmthostaddr[3+1+3+1+3+1+3+1];
Index: /trunk/minix/commands/httpd/pass.c
===================================================================
--- /trunk/minix/commands/httpd/pass.c	(revision 9)
+++ /trunk/minix/commands/httpd/pass.c	(revision 9)
@@ -0,0 +1,213 @@
+/* pass.c
+ *
+ * This file is part of httpd.
+ *
+ * 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
+ * 12/29/2002 			Michael Temari <Michael@TemWare.Com>
+ *
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <pwd.h>
+#ifdef _MINIX
+#include <minix/minlib.h>
+#endif
+
+#define	STD_PASSWD_FILE	"/etc/passwd"
+
+#include "pass.h"
+
+static char buffer[1024];
+static char *pwduser;
+static char *pwdpass;
+static char *pwde[4];
+
+_PROTOTYPE(static int getuser, (char *pwdfile, char *user));
+
+static int getuser(pwdfile, user)
+char *pwdfile;
+char *user;
+{
+FILE *fp;
+char *p;
+int i;
+
+   if((fp = fopen(pwdfile, "r")) == (FILE *)NULL)
+	return(-1);
+
+   for(i = 0; i < 4; i ++) pwde[i] = "";
+
+   while(1) {
+	if(fgets(buffer, sizeof(buffer), fp) == (char *)NULL) {
+		fclose(fp);
+		return(-1);
+	}
+	p = buffer;
+	pwduser = p;
+	while(*p && *p != ':') p++;
+	if(*p != ':') continue;
+	*p++ = '\0';
+	if(strcmp(pwduser, user)) continue;
+	pwdpass = p;
+	while(*p && *p != ':' && *p != '\r' && *p != '\n') p++;
+	if(*p == ':')
+		*p++ = '\0';
+	else {
+		if(*p) *p = '\0';
+		fclose(fp);
+	}
+	for(i = 0; i < 4; i++) {
+		pwde[i] = p;
+		while(*p && *p != ':' && *p != '\r' && *p != '\n') p++;
+		if(*p == ':')
+			*p++ = '\0';
+		else {
+			if(*p) *p = '\0';
+			break;
+		}
+	}
+	fclose(fp);
+
+	return(0);
+   }
+}
+
+int passfile(pwdfile)
+char *pwdfile;
+{
+FILE *fp;
+
+   if(!strcmp(pwdfile, STD_PASSWD_FILE))
+	return(0);
+
+   if((fp = fopen(pwdfile, "r")) == (FILE *)NULL)
+	return(-1);
+
+   fclose(fp);
+
+   return(0);
+}
+
+int passuser(pwdfile, user)
+char *pwdfile;
+char *user;
+{
+   if(!strcmp(pwdfile, STD_PASSWD_FILE))
+	if(getpwnam(user) == (struct passwd *)NULL)
+		return(-1);
+	else
+		return(0);
+
+   return(getuser(pwdfile, user));
+}
+
+int passnone(pwdfile, user)
+char *pwdfile;
+char *user;
+{
+struct passwd *pwd;
+
+   if(!strcmp(pwdfile, STD_PASSWD_FILE))
+	if((pwd = getpwnam(user)) == (struct passwd *)NULL)
+		return(-1);
+	else
+		if(!strcmp(pwd->pw_passwd, crypt("", pwd->pw_passwd)))
+			return(-1);
+		else
+			return(0);
+
+   if(getuser(pwdfile, user))
+	return(-1);
+
+   if(!strcmp(pwdpass, crypt("", pwdpass)))
+	return(-1);
+   else
+	return(0);
+}
+
+int passpass(pwdfile, user, pass)
+char *pwdfile;
+char *user;
+char *pass;
+{
+struct passwd *pwd;
+
+   if(!strcmp(pwdfile, STD_PASSWD_FILE))
+	if((pwd = getpwnam(user)) == (struct passwd *)NULL)
+		return(-1);
+	else
+		if(strcmp(pwd->pw_passwd, crypt(pass, pwd->pw_passwd)))
+			return(-1);
+		else
+			return(0);
+
+   if(getuser(pwdfile, user))
+	return(-1);
+
+   if(strcmp(pwdpass, crypt(pass, pwdpass)))
+	return(-1);
+   else
+	return(0);
+}
+
+int passadd(pwdfile, user, pass, e1, e2, e3, e4)
+char *pwdfile;
+char *user;
+char *pass;
+char *e1;
+char *e2;
+char *e3;
+char *e4;
+{
+FILE *fp;
+time_t salt;
+char sl[2];
+int cn;
+char *ee1;
+char *ee2;
+char *ee3;
+char *ee4;
+
+
+   if(pwdfile == (char *)NULL ||
+	 user == (char *)NULL ||
+	 pass == (char *)NULL)
+	return(PASS_ERROR);
+
+   if(!strcmp(pwdfile, STD_PASSWD_FILE))
+	return(PASS_ERROR);
+
+   if(!getuser(pwdfile, user))
+	return(PASS_USEREXISTS);
+
+   time(&salt);
+   sl[0] = (salt & 077) + '.';
+   sl[1] = ((salt >> 6) & 077) + '.';
+   for (cn = 0; cn < 2; cn++) {
+	if (sl[cn] > '9') sl[cn] += 7;
+	if (sl[cn] > 'Z') sl[cn] += 6;
+   }
+
+   if(e1 == (char *)NULL) ee1 = ""; else ee1 = e1;
+   if(e2 == (char *)NULL) ee2 = ""; else ee2 = e2;
+   if(e3 == (char *)NULL) ee3 = ""; else ee3 = e3;
+   if(e4 == (char *)NULL) ee4 = ""; else ee4 = e4;
+
+   /* XXX need to add locking mechanics to add new user */
+
+   if((fp = fopen(pwdfile, "a")) == (FILE *)NULL)
+	return(PASS_ERROR);
+
+   fprintf(fp, "%s:%s:%s:%s:%s:%s\n", user, crypt(pass, sl), ee1, ee2, ee3, ee4);
+
+   fclose(fp);
+
+   /* XXX need to add unlocking mechanics to add new user */
+
+   return(PASS_GOOD);
+}
Index: /trunk/minix/commands/httpd/pass.h
===================================================================
--- /trunk/minix/commands/httpd/pass.h	(revision 9)
+++ /trunk/minix/commands/httpd/pass.h	(revision 9)
@@ -0,0 +1,18 @@
+/* pass.h
+ *
+ * This file is part of httpd.
+ *
+ * 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
+ * 12/29/2002 Initial Release	Michael Temari <Michael@TemWare.Com>
+ *
+ */
+
+_PROTOTYPE(int passfile, (char *pwdfile));
+_PROTOTYPE(int passuser, (char *pwdfile, char *user));
+_PROTOTYPE(int passnone, (char *pwdfile, char *user));
+_PROTOTYPE(int passpass, (char *pwdfile, char *user, char *pass));
+_PROTOTYPE(int passadd,  (char *pwdfile, char *user, char *pass, char *e1, char *e2, char *e3, char *e4));
+
+#define	PASS_GOOD	0
+#define	PASS_USEREXISTS	1
+#define	PASS_ERROR	-1	
Index: /trunk/minix/commands/httpd/police.c
===================================================================
--- /trunk/minix/commands/httpd/police.c	(revision 9)
+++ /trunk/minix/commands/httpd/police.c	(revision 9)
@@ -0,0 +1,407 @@
+/* police.c
+ *
+ * This file is part of httpd.
+ *
+ * 02/17/1996 			Michael Temari <Michael@TemWare.Com>
+ * 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
+ * 12/29/2002			Michael Temari <Michael@TemWare.Com>
+ *
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "http.h"
+#include "utility.h"
+#include "config.h"
+#include "pass.h"
+
+#define	MATCH_NONE	0
+#define	MATCH_WILD	1
+#define	MATCH_FULL	2
+
+_PROTOTYPE(static int authaccess, (struct http_request *rq, struct http_reply *rp));
+_PROTOTYPE(static void purl, (struct http_request *rq, struct http_reply *rp));
+_PROTOTYPE(static char *virt, (char *to, char *host));
+
+static int authaccess(rq, rp)
+struct http_request *rq;
+struct http_reply *rp;
+{
+struct auth *auth;
+struct authuser *pu;
+
+   /* set authorization to be checked against */
+   if(rq->type == HTTP_REQUEST_TYPE_PROXY)
+   	auth = proxyauth;
+   else
+   	auth = rp->auth;
+
+   /* no authorization so no access to anyone */
+   if(auth == NULL) {
+   	rp->status = HTTP_STATUS_FORBIDDEN;
+   	strcpy(rp->statusmsg, "No Authoriation");
+   	return(-1);
+   }
+
+   /* access must be R for PROXY */
+   if(rq->type == HTTP_REQUEST_TYPE_PROXY)
+	if(!(auth->urlaccess & URLA_READ)) {
+   		rp->status = HTTP_STATUS_FORBIDDEN;
+   		strcpy(rp->statusmsg, "Proxy not authorized");
+   		return(-1);
+	}
+
+   /* no password file so it is a free for all */
+   if(auth->passwdfile == NULL)
+	return(0);
+
+   /* they did not give us an authorized user */
+   if(rq->authuser[0] == '\0') {
+	if(rq->type == HTTP_REQUEST_TYPE_PROXY)
+   		rp->status = HTTP_STATUS_PROXY_AUTH_REQRD;
+   	else
+   		rp->status = HTTP_STATUS_UNAUTHORIZED;
+   	strcpy(rp->statusmsg, "No Authorized User Given");
+   	return(-1);
+   }
+
+   /* check if user okay */
+   pu = auth->users;
+   if(pu == NULL)
+	;	/* no user list we allow anyone in file */
+   else {
+	while(pu != NULL) {
+		if(!strcmp(pu->user, rq->authuser))
+			break;
+		pu = pu->next;
+	}
+	/* user is not in list so no access */
+	if(pu == NULL) {
+		if(rq->type == HTTP_REQUEST_TYPE_PROXY)
+   			rp->status = HTTP_STATUS_PROXY_AUTH_REQRD;
+   		else
+			rp->status = HTTP_STATUS_UNAUTHORIZED;
+		strcpy(rp->statusmsg, "Forbidden User not authorized");
+		return(-1);
+	}
+   }
+
+   /* check if password file exists, if not no access */
+   if(passfile(auth->passwdfile)) {
+   	rp->status = HTTP_STATUS_FORBIDDEN;
+   	strcpy(rp->statusmsg, "Invalid passwd file");
+   	return(-1);
+   }
+
+   /* check if user in password file, if not no access */
+   if(passuser(auth->passwdfile, rq->authuser)) {
+	if(rq->type == HTTP_REQUEST_TYPE_PROXY)
+   		rp->status = HTTP_STATUS_PROXY_AUTH_REQRD;
+   	else
+		rp->status = HTTP_STATUS_UNAUTHORIZED;
+	strcpy(rp->statusmsg, "Forbidden Bad User");
+	return(-1);
+   }
+
+   /* check if a password exists, if not no access */
+   if(passnone(auth->passwdfile, rq->authuser)) {
+	if(rq->type == HTTP_REQUEST_TYPE_PROXY)
+   		rp->status = HTTP_STATUS_PROXY_AUTH_REQRD;
+   	else
+		rp->status = HTTP_STATUS_UNAUTHORIZED;
+	strcpy(rp->statusmsg, "Forbidden no password");
+	return(-1);
+   }
+
+   /* check if password matches, if not no access */
+   if(passpass(auth->passwdfile, rq->authuser, rq->authpass)) {
+	if(rq->type == HTTP_REQUEST_TYPE_PROXY)
+   		rp->status = HTTP_STATUS_PROXY_AUTH_REQRD;
+   	else
+		rp->status = HTTP_STATUS_UNAUTHORIZED;
+	strcpy(rp->statusmsg, "Forbidden bad password");
+	return(-1);
+   }
+
+   /* whew, all the checks passed so I guess we let them have it */
+   return(0);
+}
+
+int police(rq, rp)
+struct http_request *rq;
+struct http_reply *rp;
+{
+int size;
+struct stat st;
+struct dirsend *ds;
+
+   purl(rq, rp);
+
+   rp->mtype = "text/html";
+
+#ifdef DEBUG
+   fprintf(stderr, "httpd: Trying %s\n", rp->realurl);
+#endif
+
+   /* now check authorizations */
+   if(authaccess(rq, rp)) {
+	/* Don't give them any details why authorization failed */
+   	strcpy(rp->statusmsg, "No Access Granted");
+	return(0);
+   }
+
+   /* a proxy request only needs an authorization check */
+   if(rq->type == HTTP_REQUEST_TYPE_PROXY)
+	return(0);
+
+   /* check access to real url */
+   if(stat(rp->realurl, &st)) {
+	if(errno == EACCES)
+		rp->status = HTTP_STATUS_FORBIDDEN;
+	else
+		rp->status = HTTP_STATUS_NOT_FOUND;
+	strcpy(rp->statusmsg, strerror(errno));
+	/* a PUT and NOT FOUND is okay since we are creating */
+	if(rq->method != HTTP_METHOD_PUT || rp->status != HTTP_STATUS_NOT_FOUND)
+		return(0);
+   }
+
+   /* If it is a directory do the appropriate thang! */
+   if(rq->method == HTTP_METHOD_GET || rq->method == HTTP_METHOD_HEAD)
+   if((st.st_mode & S_IFMT) == S_IFDIR) {
+	if(rq->url[strlen(rq->url) - 1] != '/') {
+		strncat(rq->url, "/", sizeof(rq->url) - strlen(rq->url));
+		rp->status = HTTP_STATUS_MOVED_TEMP;
+		sprintf(rp->statusmsg, "Moved to %s", rq->url);
+		return(0);
+	}
+	size = strlen(rq->url);
+	ds = dirsend;
+	while(ds != NULL) {
+		strncpy(rq->url+size, ds->file, sizeof(rq->url)-size);
+		purl(rq, rp);
+		if(stat(rp->realurl, &st)) {
+			if(errno == EACCES)
+				rp->status = HTTP_STATUS_FORBIDDEN;
+			else
+			if(errno != ENOENT)
+				rp->status = HTTP_STATUS_NOT_FOUND;
+		} else
+			break;
+		if(rp->status != HTTP_STATUS_OK) {
+			strcpy(rp->statusmsg, strerror(errno));
+			return(0);
+		}
+		ds = ds->next;
+	}
+	if(ds == NULL) {
+		rq->url[size] = '\0';
+		purl(rq, rp);
+		if(stat(rp->realurl, &st)) {
+	   		if(errno == EACCES)
+   				rp->status = HTTP_STATUS_FORBIDDEN;
+   			else
+				rp->status = HTTP_STATUS_NOT_FOUND;
+			strcpy(rp->statusmsg, strerror(errno));
+			return(0);
+		}
+	}
+   }
+
+   if(rq->method == HTTP_METHOD_PUT && !(rp->urlaccess & URLA_WRITE)) {
+	rp->status = HTTP_STATUS_METHOD_NOT_ALLOWED;
+	strcpy(rp->statusmsg, "Method not allowed");
+	return(0);
+   }
+
+   if(rp->status == HTTP_STATUS_OK) {
+	/* Here is where we check if it is a program or script to run */
+	if(cgiexec(rq, rp))
+   		return(0);
+
+	if((st.st_mode & S_IFMT) == S_IFDIR) {
+		rp->status = HTTP_STATUS_NOT_FOUND;
+		strcpy(rp->statusmsg, "Directory listing not available");
+		return(0);
+	}
+
+	if((st.st_mode & S_IFMT) != S_IFREG) {
+		rp->status = HTTP_STATUS_NOT_FOUND;
+		strcpy(rp->statusmsg, "Not a regular file");
+		return(0);
+	}
+   }
+
+   /* open the URL for updating */
+   if(rq->method == HTTP_METHOD_PUT) {
+	rp->status = HTTP_STATUS_OK;
+	strcpy(rp->statusmsg, "OK");
+	rp->ofd = open(rp->realurl, O_WRONLY | O_CREAT | O_TRUNC);
+	if(rp->ofd < 0) {
+   		if(errno == EACCES)
+   			rp->status = HTTP_STATUS_FORBIDDEN;
+   		else
+			rp->status = HTTP_STATUS_NOT_FOUND;
+		strcpy(rp->statusmsg, strerror(errno));
+		return(0);
+	}
+	return(0);
+   }
+
+   if(!(rp->urlaccess & URLA_READ)) {
+   	rp->status = HTTP_STATUS_FORBIDDEN;
+   	strcpy(rp->statusmsg, "No way...");
+	return(0);
+   }
+
+   rp->mtype = mimetype(rp->realurl);
+
+   rp->size = st.st_size;
+   rp->modtime = st.st_mtime;
+
+   /* open the url if it is a file */
+   rp->fd = open(rp->realurl, O_RDONLY);
+   if(rp->fd < 0) {
+	if(errno == EACCES)
+   		rp->status = HTTP_STATUS_FORBIDDEN;
+   	else
+		rp->status = HTTP_STATUS_NOT_FOUND;
+	strcpy(rp->statusmsg, strerror(errno));
+	return(0);
+   }
+
+   return(0);
+}
+
+static void purl(rq, rp)
+struct http_request *rq;
+struct http_reply *rp;
+{
+struct vpath *pv;
+int gotreal, gotperm;
+char *p;
+int match;
+int len;
+
+   gotreal = 0; gotperm = 0;
+
+#ifdef DEBUG
+   fprintf(stderr, "httpd: Processing url = \"%s\"\n", rq->url);
+#endif
+
+   /* remove any .. references */
+   p = rq->url;
+   while(*p) {
+	while(*p && *p != '/') p++;
+	if(*p != '/') continue;
+	p++;
+	if(*p != '.') continue;
+	p++;
+	if(*p != '.') continue;
+	p++;
+	strcpy(p - 3, p);
+	p = p - 3;
+   }
+
+   for(pv = vpath; pv != NULL; pv = pv->next) {
+   	len = strlen(pv->from) - 1;
+   	if(pv->from[len] == '*' || pv->from[len] == '$')
+   		if(len == 0)
+   			match = MATCH_WILD;
+   		else
+   			match = strncmp(rq->url, pv->from, len) ? MATCH_NONE : MATCH_WILD;
+   	else
+   		if(!strcmp(rq->url, pv->from))
+   			match = MATCH_FULL;
+   		else
+   			match = MATCH_NONE;
+#ifdef DEBUG
+   	fprintf(stderr, "httpd: Trying \"%s\" %d %d %d %s\n",
+		pv->from, match, gotreal, gotperm, pv->auth->name);
+#endif
+   	if(match != MATCH_NONE) {
+		gotperm = 1;
+		rp->auth = pv->auth;
+		if(pv->urlaccess == -1 && rp->auth != NULL)
+			rp->urlaccess = rp->auth->urlaccess;
+		else
+			rp->urlaccess = pv->urlaccess;
+   		if(strcmp(pv->to, ".")) {
+   			gotreal = 1;
+   			strncpy(rp->realurl, virt(pv->to, rq->host), sizeof(rp->realurl));
+			rp->realurl[sizeof(rp->realurl)-1] = '\0';
+			if(match == MATCH_WILD && pv->from[len] != '$') {
+   				strncat(rp->realurl, rq->url+len, sizeof(rp->realurl) - strlen(rp->realurl));
+				rp->realurl[sizeof(rp->realurl)-1] = '\0';
+			}
+   		}
+   	}
+   	if(match == MATCH_FULL) break;
+   }
+
+   if(rp->urlaccess == -1) rp->urlaccess = mkurlaccess("");
+
+   if(!gotreal) {
+	strncpy(rp->realurl, rq->url, sizeof(rp->realurl));
+	rp->realurl[sizeof(rp->realurl)-1] = '\0';
+   }
+
+   if(!gotperm)
+   	rp->auth = NULL;
+
+#ifdef DEBUG
+   fprintf(stderr, "DEBUG: url = \"%s\"  realurl = \"%s\"  auth = \"%s\"\n",
+	rq->url, rp->realurl, ((rp->auth == NULL) ? "No Access" : rp->auth->name));
+   fprintf(stderr, "DEBUG: query = %s\n", rq->query);
+#endif
+
+   return;
+}
+
+static char *virt(to, host)
+char *to;
+char *host;
+{
+static char vroot[256];
+struct vhost *ph;
+
+#ifdef DEBUG
+fprintf(stderr, "virt: %s %s\n", to, host);
+#endif
+
+   if(vhost == NULL) return(to);
+
+   if(to[0] != '/') return(to);
+   if(to[1] != '/') return(to);
+   if(to[2] != '/') return(to);
+
+   vroot[0] = '\0';
+
+   for(ph = vhost; ph != NULL; ph = ph->next) {
+#ifdef DEBUG
+   	fprintf(stderr, "ph: %s %s %s\n", ph->hname, ph->root, vroot);
+#endif
+   	if(!strcmp(ph->hname, "*") && vroot[0] == '\0')
+   		strncpy(vroot, ph->root, sizeof(vroot));
+   	if(!strcasecmp(ph->hname, host)) {
+   		strncpy(vroot, ph->root, sizeof(vroot));
+   		break;
+   	}
+   }
+
+   strncat(vroot, to+3, sizeof(vroot));
+
+#ifdef DEBUG
+   fprintf(stderr, "vroot: %s\n", vroot);
+#endif
+
+   return(vroot);
+}
Index: /trunk/minix/commands/httpd/process.c
===================================================================
--- /trunk/minix/commands/httpd/process.c	(revision 9)
+++ /trunk/minix/commands/httpd/process.c	(revision 9)
@@ -0,0 +1,81 @@
+/* process.c
+ *
+ * This file is part of httpd.
+ *
+ * 02/17/1996 			Michael Temari <Michael@TemWare.Com>
+ * 07/07/1996 Initial Relase	Michael Temari <Michael@TemWare.Com>
+ * 12/29/2002			Michael Temari <Michael@TemWare.Com>
+ *
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "config.h"
+#include "http.h"
+#include "utility.h"
+
+int processrequest(rq, rp)
+struct http_request *rq;
+struct http_reply *rp;
+{
+   /* clear out http_reply */
+   memset(rp, 0, sizeof(*rp));
+   rp->status = HTTP_STATUS_OK;
+   strcpy(rp->statusmsg, "OK");
+   rp->modtime = (time_t) -1;
+   rp->urlaccess = -1;
+   rp->size = 0;
+   rp->fd = -1;
+   rp->ofd = -1;
+   rp->pid = 0;
+
+   /* Simple requests can only be a GET */
+   if(rq->type == HTTP_REQUEST_TYPE_SIMPLE && rq->method != HTTP_METHOD_GET) {
+   	rp->status = HTTP_STATUS_BAD_REQUEST;
+   	strcpy(rp->statusmsg, "Bad request");
+   	return(0);
+   }
+
+   /* I don't know this method */
+   if(rq->method == HTTP_METHOD_UNKNOWN) {
+	rp->status = HTTP_STATUS_NOT_IMPLEMENTED;
+	strcpy(rp->statusmsg, "Method not implemented");
+	return(0);
+   }
+
+   /* Check for access and real location of url */
+   if(police(rq, rp))
+   	return(-1);
+
+   /* We're done if there was an error accessing the url */
+   if(rp->status != HTTP_STATUS_OK)
+   	return(0);
+		
+   /* Check to see if we have a newer version for them */
+   if(rq->method == HTTP_METHOD_GET)
+	if(rq->ifmodsince != (time_t) -1)
+   		if(rq->ifmodsince < time((time_t *)NULL))
+   			if(rp->modtime != (time_t) -1 && rp->modtime <= rq->ifmodsince) {
+   				rp->status = HTTP_STATUS_NOT_MODIFIED;
+   				strcpy(rp->statusmsg, "Not modified");
+   				close(rp->fd);
+   				rp->fd = -1;
+   				return(0);
+   			}
+
+   rp->status = HTTP_STATUS_OK;
+   strcpy(rp->statusmsg, "OK");
+
+   if(rp->size != 0)
+	rp->keepopen = rq->keepopen;
+
+   return(0);
+}
Index: /trunk/minix/commands/httpd/proxy.c
===================================================================
--- /trunk/minix/commands/httpd/proxy.c	(revision 9)
+++ /trunk/minix/commands/httpd/proxy.c	(revision 9)
@@ -0,0 +1,292 @@
+/* proxy.c Copyright 2000 by Michael Temari All Rights Reserved */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <time.h>
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/socket.h>
+#include <net/gen/netdb.h>
+
+#include "config.h"
+#include "http.h"
+#include "utility.h"
+#include "net.h"
+
+_PROTOTYPE(static int connect, (char *host));
+#if 0
+_PROTOTYPE(static int readline, (char *p, int len));
+#endif
+_PROTOTYPE(static int sendout, (int fd, char *data));
+
+static int connect(host)
+char *host;
+{
+nwio_tcpconf_t tcpconf;
+nwio_tcpcl_t tcpcopt;
+char *tcp_device;
+int netfd;
+ipaddr_t nethost;
+tcpport_t netport = 0;
+struct hostent *hp;
+struct servent *sp;
+char *p;
+int s;
+int tries;
+
+   p = host;
+   while(*p && *p != ':') p++;
+   if(*p == ':') {
+   	*p++ = '\0';
+   	netport = htons(atoi(p));
+   }
+
+   if((hp = gethostbyname(host)) == (struct hostent *)NULL) {
+	fprintf(stderr, "Unknown host %s!\n", host);  
+	return(-1);
+   } else
+	memcpy((char *) &nethost, (char *) hp->h_addr, hp->h_length);
+
+   /* Now, to which port must we connect? */
+   if(netport == 0)
+	if((sp = getservbyname("http", "tcp")) == (struct servent *)NULL) {
+		fprintf(stderr, "HTTP port is unknown????\n");
+		return(-1);
+	} else
+		netport = sp->s_port;
+
+   /* Connect to the host */
+   if((tcp_device = getenv("TCP_DEVICE")) == NULL)
+	tcp_device = TCP_DEVICE;
+
+   if((netfd = open(tcp_device, O_RDWR)) < 0) {
+	perror("httpget: opening tcp");
+	return(-1);
+   }
+
+   tcpconf.nwtc_flags = NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
+   tcpconf.nwtc_remaddr = nethost;
+   tcpconf.nwtc_remport = netport;
+
+   s = ioctl(netfd, NWIOSTCPCONF, &tcpconf);
+   if(s < 0) {
+	perror("httpget: NWIOSTCPCONF");
+	close(netfd);
+	return(-1);
+   }
+
+   s = ioctl(netfd, NWIOGTCPCONF, &tcpconf);
+   if(s < 0) {
+	perror("httpget: NWIOGTCPCONF");
+	close(netfd);
+	return(-1);
+   }
+
+   tcpcopt.nwtcl_flags = 0;
+
+   tries = 0;
+   do {
+	s = ioctl(netfd, NWIOTCPCONN, &tcpcopt);
+	if(s == -1 && errno == EAGAIN) {
+		if(tries++ >= 10)
+			break;
+		sleep(10);
+	} else
+		break;
+   } while(1);
+
+   if(s < 0) {
+	perror("httpget: NWIOTCPCONN");
+	close(netfd);
+	return(-1);
+   }
+
+   return(netfd);
+}
+
+char buffer[8192];
+
+#if 0
+static int readline(p, len)
+char *p;
+int len;
+{
+int c;
+int cr = 0;
+int n = 0;
+
+   len--;
+   if(len < 0) return(-1);
+   while(len > 0 && (c = getchar()) != EOF) {
+   	if(c == '\n' && cr) {
+   		*p = '\0';
+   		return(n);
+   	}
+   	if(c == '\r') {
+   		cr = 1;
+   		continue;
+   	}
+   	n++;
+   	*p++ = c;
+   }
+   *p = '\0';
+   return(n);
+}
+#endif
+
+static int sendout(fd, data)
+int fd;
+char *data;
+{
+   if(strlen(data) > 0)
+	write(fd, data, strlen(data));
+	write(fd, "\r\n", 2);
+	if(dbglog != (FILE *)NULL) {
+		fprintf(dbglog, "REPLY: %s\n", data);
+	fflush(dbglog);
+   }
+
+   return(0);
+}
+
+void proxy(rq, rp)
+struct http_request *rq;
+struct http_reply *rp;
+{
+int s;
+char *p;
+char *ps;
+char *b;
+char *host;
+static char user[256];
+static char pass[256];
+char *url;
+char *at;
+int fd;
+int bad;
+
+   while(1) {
+   	bad = 0;
+   	p = rq->uri;
+   	if(tolower(*p++) != 'h') bad++;
+   	if(tolower(*p++) != 't') bad++;
+   	if(tolower(*p++) != 't') bad++;
+   	if(tolower(*p++) != 'p') bad++;
+   	if(tolower(*p++) != ':') bad++;
+   	if(tolower(*p++) != '/') bad++;
+   	if(tolower(*p++) != '/') bad++;
+   	if(bad) {
+		sprintf(buffer, "HTTP/%d.%d 400 Bad Request",
+			rq->vmajor, rq->vminor);
+		sendout(1, buffer);
+		sendout(1, "");
+		sendout(1, "Proxy Request was not http:");
+		return;
+   	}
+   	host = p;
+	while(*p && *p != '/') p++;
+	url = p;
+	*url = '\0';
+	at = strchr(host, '@');
+	if(at != (char *)NULL) {
+		*at = '\0';
+		p = host;
+		while(*p && *p != ':') p++;
+		if(*p)
+			*p++ = '\0';
+		strcpy(user, host);
+		strcpy(pass, p);
+		host = at + 1;
+	} else {
+		user[0] = '\0';
+		pass[0] = '\0';
+	}
+
+   	fd = connect(host);
+   	if(fd < 0) {
+		sprintf(buffer, "HTTP/%d.%d 400 Bad Request",
+			rq->vmajor, rq->vminor);
+		sendout(1, buffer);
+		sendout(1, "");
+		sendout(1, "Could not connect to host");
+		return;
+   	}
+   	if(rq->method == HTTP_METHOD_GET)
+   		write(fd, "GET ", 4); else
+   	if(rq->method == HTTP_METHOD_POST)
+   		write(fd, "POST ", 5);
+   	*url = '/';
+   	if(strlen(url) > 0)
+   		write(fd, url, strlen(url));
+   	write(fd, " ", 1);
+	sprintf(buffer, "HTTP/%d.%d", rq->vmajor, rq->vminor);
+	sendout(fd, buffer);
+   	if(rq->ifmodsince != -1) {
+   		write(fd, "If-Mod-Since: ", 14);
+   		sendout(fd, httpdate(&rq->ifmodsince));
+   	}
+	if(rq->size != 0) {
+		sendout(fd, "Content-Type: application/x-www-form-urlencoded");
+		sprintf(buffer, "Content-Length: %lu", rq->size);
+		sendout(fd, buffer);
+	}
+	if(*rq->cookie) {
+		sprintf(buffer, "Cookie: %s", rq->cookie);
+		sendout(fd, buffer);
+	}
+	if(*rq->useragent) {
+		sprintf(buffer, "User-Agent: %s", rq->useragent);
+		sendout(fd, buffer);
+	}
+	if(*rq->host) {
+		sprintf(buffer, "Host: %s", rq->host);
+		sendout(fd, buffer);
+	}
+	if(*rq->wwwauth) {
+		sprintf(buffer, "Authorization: %s", rq->wwwauth);
+		sendout(fd, buffer);
+	}
+	sprintf(buffer, "X-Forwarded-From: %s", rmthostaddr);
+	sendout(fd, buffer);
+   	sendout(fd, "");
+	if(rq->size != 0) {
+		if(stdlog != (FILE *)NULL) {
+			fprintf(stdlog, "%s %s %d %d ",
+				logdate((time_t *)NULL), rmthostname,
+				rq->method, rp->status);
+			fprintf(stdlog, "proxy %s?", rq->uri);
+		}
+	   	while((s = read(0, buffer, rq->size >
+   			sizeof(buffer) ? sizeof(buffer) : rq->size)) > 0) {
+   			write(fd, buffer, s);
+   			rq->size -= s;
+   			b = buffer;
+   			if(stdlog != (FILE *)NULL)
+   				while(s--) fputc(*b++, stdlog);
+			if(rq->size == 0) break;
+   		}
+   		if(stdlog != (FILE *)NULL) {
+   			fprintf(stdlog, "\n");
+			fflush(stdlog);
+		}
+   	}
+   	while((s = read(fd, buffer, sizeof(buffer))) > 0) {
+   		write(1, buffer, s);
+   	}
+   	close(fd);
+   	return;
+   }
+}
Index: /trunk/minix/commands/httpd/reply.c
===================================================================
--- /trunk/minix/commands/httpd/reply.c	(revision 9)
+++ /trunk/minix/commands/httpd/reply.c	(revision 9)
@@ -0,0 +1,189 @@
+/* reply.c
+ *
+ * This file is part of httpd.
+ *
+ * 02/17/1996 			Michael Temari <Michael@TemWare.Com>
+ * 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
+ * 12/29/2002 			Michael Temari <Michael@TemWare.Com>
+ *
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+
+#include "http.h"
+#include "utility.h"
+#include "net.h"
+#include "config.h"
+
+#define	SERVER	"Server: "VERSION
+
+_PROTOTYPE(static void GotAlarm, (int sig));
+_PROTOTYPE(static int sendout, (char *data));
+
+static void GotAlarm(sig)
+int sig;
+{
+}
+
+static int sendout(data)
+char *data;
+{
+   if(strlen(data) > 0)
+	write(1, data, strlen(data));
+   write(1, "\r\n", 2);
+   if(dbglog != (FILE *)NULL) {
+	fprintf(dbglog, "REPLY: %s\n", data);
+	fflush(dbglog);
+   }
+
+   return(0);
+}
+
+int sendreply(rp, rq)
+struct http_reply *rp;
+struct http_request *rq;
+{
+int s;
+int s2;
+int e;
+static char buffer[8192];
+
+   if(rq->type != HTTP_REQUEST_TYPE_PROXY)
+   /* We're receiving data from a */
+   if(rq->method == HTTP_METHOD_POST ||
+     (rq->method == HTTP_METHOD_PUT && rp->status == HTTP_STATUS_OK)) {
+   	if(rq->type != HTTP_REQUEST_TYPE_FULL)
+   		return(0);
+   	if(rq->method == HTTP_METHOD_PUT)
+   		rp->status = HTTP_STATUS_CREATED;
+   	else
+   		rp->status = HTTP_STATUS_OK;
+   	while(rq->size != 0) {
+   		s = read(0, buffer, (rq->size > sizeof(buffer)) ? sizeof(buffer) : rq->size);
+   		if(s <= 0) {
+   			rp->status = HTTP_STATUS_SERVER_ERROR;
+   			strcpy(rp->statusmsg, strerror(errno));
+   			close(rp->fd);
+   			close(rp->ofd);
+   			break;
+   		}
+   		rq->size -= s;
+   		s2 = write(rp->ofd, buffer, s);
+   		if(s2 != s) break;
+   	}
+   }
+
+   if(rp->status != HTTP_STATUS_OK && rp->status != HTTP_STATUS_CREATED &&
+      rp->status != HTTP_STATUS_NOT_MODIFIED)
+	rp->keepopen = 0;
+
+   if(rp->status == HTTP_STATUS_NOT_MODIFIED) {
+	sprintf(buffer, "<h2>Error %03d %s</h2>",
+		rp->status, rp->statusmsg);
+	rp->size = strlen(buffer);
+	rp->keepopen = rq->keepopen;
+   }
+
+   if(!rp->headers) {
+
+   if((rq->type == HTTP_REQUEST_TYPE_PROXY && rp->status != HTTP_STATUS_OK) ||
+       rq->type == HTTP_REQUEST_TYPE_FULL) {
+	sprintf(buffer, "HTTP/%d.%d %03d %s",
+		rq->vmajor, rq->vminor, rp->status, rp->statusmsg);
+	sendout(buffer);
+	sendout(SERVER);
+	if(rp->status == HTTP_STATUS_MOVED_PERM ||
+	   rp->status == HTTP_STATUS_MOVED_TEMP) {
+#if 1
+	   	sprintf(buffer, "Location: %s", rq->url);
+#else
+	   	sprintf(buffer, "Location: http://%s%s", myhostname, rq->url);
+#endif
+	   	sendout(buffer);
+	}
+	if(rp->keepopen)
+		sendout("Connection: Keep-Alive");
+	else
+		sendout("Connection: Close");
+	if(rp->status == HTTP_STATUS_UNAUTHORIZED && rp->auth != NULL) {
+		sprintf(buffer, "WWW-Authenticate: Basic realm=\"%s\"", rp->auth->desc);
+		sendout(buffer);
+	}
+	if(rp->status == HTTP_STATUS_PROXY_AUTH_REQRD && proxyauth != NULL) {
+		sprintf(buffer, "Proxy-Authenticate: Basic realm=\"%s\"", proxyauth->desc);
+		sendout(buffer);
+	}
+	if(rp->modtime != (time_t) -1) {
+		sprintf(buffer, "Last-Modified: %s", httpdate(&rp->modtime));
+		sendout(buffer);
+	}
+	if(rp->size != 0) {
+		sprintf(buffer, "Content-Length: %lu", rp->size);
+		sendout(buffer);
+	}
+	if(rp->status == HTTP_STATUS_OK) {
+		sprintf(buffer, "Content-Type: %s", rp->mtype);
+		sendout(buffer);
+	} else
+		sendout("Content-Type: text/html");
+	if(!rp->headers)
+		sendout("");
+   } else
+	if(rp->status != HTTP_STATUS_OK)
+		return(0);
+   }
+
+   if(rp->status != HTTP_STATUS_OK && rp->status != HTTP_STATUS_CREATED) {
+	sprintf(buffer, "<h2>Error %03d %s</h2>",
+		rp->status, rp->statusmsg);
+	sendout(buffer);
+	return(0);
+   }
+
+   if(rq->type == HTTP_REQUEST_TYPE_PROXY) {
+   	proxy(rq, rp);
+   	return(0);
+   }
+
+   /* send out entity body */
+   if(rq->method == HTTP_METHOD_GET || rq->method == HTTP_METHOD_POST) {
+   	errno = 0;
+   	while(1) {
+   		alarm(0);
+   		signal(SIGALRM, GotAlarm);
+   		alarm(10);
+   		s = read(rp->fd, buffer, sizeof(buffer));
+   		e = errno;
+   		alarm(0);
+   		if(s > 0) {
+			s2 = write(1, buffer, s);
+			e = errno;
+			if(s2 != s) break;
+			continue;
+		}
+		if(s == 0) break;
+		if(s < 0 && e != EINTR) break;
+   		signal(SIGALRM, GotAlarm);
+   		alarm(2);
+   		s = read(0, buffer, 1);
+   		e = errno;
+   		alarm(0);
+   		if(s < 0 && e != EINTR) break;
+	}
+   }
+
+   close(rp->fd);
+   rp->fd = -1;
+   if(rp->ofd != -1)
+	close(rp->ofd);
+   if(rp->pid != 0 && e != 0) {
+   	kill(-rp->pid, SIGHUP);
+   	rp->pid = 0;
+   }
+
+   return(0);
+}
Index: /trunk/minix/commands/httpd/request.c
===================================================================
--- /trunk/minix/commands/httpd/request.c	(revision 9)
+++ /trunk/minix/commands/httpd/request.c	(revision 9)
@@ -0,0 +1,369 @@
+/* request.c
+ *
+ * This file is part of httpd.
+ *
+ * 02/17/1996 			Michael Temari <Michael@TemWare.Com>
+ * 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
+ * 12/29/2002			Michael Temari <Michael@TemWare.Com>
+ *
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pwd.h>
+#ifdef _MINIX
+#include <minix/minlib.h>
+#endif
+#include <errno.h>
+
+#include "http.h"
+#include "utility.h"
+#include "config.h"
+
+_PROTOTYPE(static void Timeout, (int sig));
+_PROTOTYPE(static int getline, (char *buffer, int size));
+_PROTOTYPE(static void authorize, (char *p, struct http_request *rq));
+_PROTOTYPE(static void decurl, (char *u));
+
+static int TimeOut;
+
+static void Timeout(sig)
+int sig;
+{
+   TimeOut = 1;
+}
+
+static int getline(buffer, size)
+char *buffer;
+int size;
+{
+char *p;
+int s;
+
+   p = buffer;
+
+   while(p < (buffer + size - 1)) {
+   	TimeOut = 0;
+   	signal(SIGALRM, Timeout);
+   	alarm(5*60);
+	s = read(0, p, 1);
+	alarm(0);
+	if(TimeOut)
+		return(-1);
+	if(s != 1)
+		return(-1);
+	if(*p == '\n') break;
+	p++;
+   }
+   *++p = '\0';
+
+   p = &buffer[strlen(buffer) - 1];
+   if(p >= buffer && (*p == '\r' || *p == '\n')) *p-- ='\0';
+   if(p >= buffer && (*p == '\r' || *p == '\n')) *p-- ='\0';
+
+   return(strlen(buffer));
+}
+
+static void authorize(p, rq)
+char *p;
+struct http_request *rq;
+{
+char *s;
+
+   if(toupper(*p++) == 'B' &&
+      toupper(*p++) == 'A' &&
+      toupper(*p++) == 'S' &&
+      toupper(*p++) == 'I' &&
+      toupper(*p++) == 'C' &&
+      toupper(*p++) == ' ') ;
+   else
+   	return;
+
+   s = decode64(p);
+
+   if((p = strchr(s, ':')) == (char *)NULL)
+   	p = "";
+   else
+   	*p++ = '\0';
+
+   strncpy(rq->authuser, s, sizeof(rq->authuser));
+   strncpy(rq->authpass, p, sizeof(rq->authpass));
+
+   return;
+}
+
+int getrequest(rq)
+struct http_request *rq;
+{
+static char line[4096];
+char *p, *p2, *ps;
+int s, len;
+struct vhost *ph;
+
+   /* get request, it may be simple */
+
+   s = getline(line, sizeof(line));
+   if(s < 0)
+	return(-1);
+
+   if(dbglog != (FILE *)NULL) {
+	fprintf(dbglog, "REQUEST: %s\n", line);
+	fflush(dbglog);
+   }
+
+   /* clear http_request */
+   memset(rq, 0, sizeof(*rq));
+   rq->ifmodsince = (time_t) -1;
+
+   /* assume simple request */
+   rq->type = HTTP_REQUEST_TYPE_SIMPLE;
+
+   /* parse the method */
+   p = line;
+   while(*p && !LWS(*p)) {
+   	*p = toupper(*p);
+   	p++;
+   }
+   if(*p) *p++ = '\0';
+
+   if(!strcmp(line, "GET"))
+	rq->method = HTTP_METHOD_GET; else
+   if(!strcmp(line, "HEAD"))
+	rq->method = HTTP_METHOD_HEAD; else
+   if(!strcmp(line, "POST"))
+	rq->method = HTTP_METHOD_POST; else
+   if(!strcmp(line, "PUT"))
+	rq->method = HTTP_METHOD_PUT; else
+#if 0
+   if(!strcmp(line, "OPTIONS"))
+	rq->method = HTTP_METHOD_OPTIONS; else
+   if(!strcmp(line, "PATCH"))
+	rq->method = HTTP_METHOD_PATCH; else
+   if(!strcmp(line, "COPY"))
+	rq->method = HTTP_METHOD_COPY; else
+   if(!strcmp(line, "MOVE"))
+	rq->method = HTTP_METHOD_MOVE; else
+   if(!strcmp(line, "DELETE"))
+	rq->method = HTTP_METHOD_DELETE; else
+   if(!strcmp(line, "LINK"))
+	rq->method = HTTP_METHOD_LINK; else
+   if(!strcmp(line, "UNLINK"))
+	rq->method = HTTP_METHOD_UNLINK; else
+   if(!strcmp(line, "TRACE"))
+	rq->method = HTTP_METHOD_TRACE; else
+   if(!strcmp(line, "WRAPPED"))
+	rq->method = HTTP_METHOD_WRAPPED; else
+#endif
+	rq->method = HTTP_METHOD_UNKNOWN;
+
+   /* parse the requested URI */
+   p2 = rq->uri;
+   len = sizeof(rq->uri) - 1;
+   while(*p && !LWS(*p) && len > 0) {
+	*p2++ = *p++;
+	len--;
+   }
+   *p2 = '\0';
+
+   /* eat up any leftovers if uri was too big */
+   while(*p && !LWS(*p))
+	p++;
+
+   /* save for continued processing later */
+   ps = p;
+
+   /* parse the requested URL */
+   p = rq->uri;
+   p2 = rq->url;
+   len = sizeof(rq->url) - 1;
+   while(*p && !LWS(*p) && *p != '?' && len > 0) {
+	*p2++ = *p++;
+	len--;
+   }
+   *p2 = '\0';
+
+   /* See if there is a query string */
+   if(*p == '?') {
+   	p++;
+   	p2 = rq->query;
+   	len = sizeof(rq->query) - 1;
+   	while(*p && !LWS(*p) && len > 0) {
+   		*p2++ = *p++;
+		len--;
+	}
+   }
+
+   /* eat up any leftovers */
+   while(*p && !LWS(*p)) p++;
+
+   if(rq->url[0] == '\0') {
+   	rq->url[0] = '/';
+   	rq->url[1] = '\0';
+   }
+
+   /* url is a decoded copy of the uri */
+   decurl(rq->url);
+
+   /* restore and continue processing */
+   p = ps;
+
+   /* if this is true it is a simple request */
+   if(*p == '\0')
+	return(0);
+
+   /* parse HTTP version */
+   while(*p && LWS(*p)) p++;
+   if(toupper(*p++) != 'H') return(0);
+   if(toupper(*p++) != 'T') return(0);
+   if(toupper(*p++) != 'T') return(0);
+   if(toupper(*p++) != 'P') return(0);
+   if(        *p++  != '/') return(0);
+
+   /* version major */
+   rq->vmajor = 0;
+   while((*p >= '0') && (*p <= '9'))
+	rq->vmajor = rq->vmajor * 10 + (*p++ - '0');
+   if(*p != '.')
+	return(0);
+   p++;
+
+   /* version minor */
+   rq->vminor = 0;
+   while((*p >= '0') && (*p <= '9'))
+	rq->vminor = rq->vminor * 10 + (*p++ - '0');
+   if(*p)
+	return(0);
+
+   rq->type = HTTP_REQUEST_TYPE_FULL;
+
+   p = rq->uri;
+
+   /* check if it is a proxy request */
+   if(toupper(*p++) == 'H' &&
+      toupper(*p++) == 'T' &&
+      toupper(*p++) == 'T' &&
+      toupper(*p++) == 'P' &&
+      toupper(*p++) == ':')
+      	rq->type = HTTP_REQUEST_TYPE_PROXY;
+
+   /* parse any header fields */
+   while((s = getline(line, sizeof(line))) > 0) {
+   	if(toupper(line[0]) == 'A' &&
+   	   toupper(line[1]) == 'U')
+		if(dbglog != (FILE *)NULL) {
+			fprintf(dbglog, "REQUEST: Authorization:\n");
+			fflush(dbglog);
+		} else ;
+	else
+		if(dbglog != (FILE *)NULL) {
+			fprintf(dbglog, "REQUEST: %s\n", line);
+			fflush(dbglog);
+		}
+	p = line;
+	while(*p && *p != ':') {
+		*p = toupper(*p);
+		p++;
+	}
+	if(*p != ':') continue;		/* bad header field, skip it */
+	*p++ = '\0';
+	while(*p && LWS(*p)) p++;
+
+	/* header field value parsing here */
+	if(!strcmp(line, "HOST")) {
+		strncpy(rq->host, p, sizeof(rq->host));
+		p2 = strrchr(rq->host, ':');
+		if(p2 != (char *)NULL) {
+			*p2++ = '\0';
+			rq->port = atoi(p2);
+		}
+		/* if unknown virtual host then exit quietly */
+		for(ph = vhost; ph != NULL; ph = ph->next) {
+			if(!strcasecmp(ph->hname, "*")) break;
+			if(!strcasecmp(ph->hname, rq->host)) break;
+		}
+		if(rq->type != HTTP_REQUEST_TYPE_PROXY)
+			if(ph == NULL && vhost != NULL) return(1);
+	} else
+	if(!strcmp(line, "USER-AGENT"))
+		strncpy(rq->useragent, p, sizeof(rq->useragent)); else
+	if(!strcmp(line, "CONNECTION"))
+		rq->keepopen = strcasecmp(p, "Keep-Alive") ? 0 : 1; else
+	if(!strcmp(line, "IF-MODIFIED-SINCE"))
+		rq->ifmodsince = httptime(p); else
+	if(!strcmp(line, "CONTENT-LENGTH"))
+		rq->size = atol(p); else
+	if(!strcmp(line, "AUTHORIZATION")) {
+		strncpy(rq->wwwauth, p, sizeof(rq->wwwauth));
+		if(rq->type != HTTP_REQUEST_TYPE_PROXY)
+			authorize(p, rq);
+	} else
+	if(!strcmp(line, "PROXY-AUTHORIZATION")) {
+		if(rq->type == HTTP_REQUEST_TYPE_PROXY)
+			authorize(p, rq);
+	} else
+	if(!strcmp(line, "DATE"))
+		rq->msgdate = httptime(p); else
+	if(!strcmp(line, "COOKIE")) {
+		strncpy(rq->cookie, p, sizeof(rq->cookie)-1);
+		rq->cookie[sizeof(rq->cookie)-1] = '\0';
+	}
+   }
+
+   if(rq->type != HTTP_REQUEST_TYPE_PROXY)
+	if(*rq->host == '\0' && vhost != NULL) return(1);
+
+   if(dbglog != (FILE *)NULL && rq->authuser[0] != '\0') {
+	fprintf(dbglog, "REQUEST: AuthUser=%s\n", rq->authuser);
+	fflush(dbglog);
+   }
+
+   if(s < 0) {
+	fprintf(stderr, "httpd: getrequest: Error getline (header fields)\n");
+	return(-1);
+   }
+
+   return(0);
+}
+
+static void decurl(u)
+char *u;
+{
+char *p;
+char h1, h2;
+char c;
+
+   p = u;
+   while(*p) {
+	switch(*p) {
+   		case '\0':
+   			c = '\0';
+   			break;
+   		case '+':
+   			c = ' ';
+   			p++;
+   			break;
+   		case '%':
+			h1 = '0';
+			h2 = '0';
+			p++;
+			h1 = tolower(*p);
+			if(*p) p++;
+			h2 = tolower(*p);
+			if(*p) p++;
+			c = (h1 > '9') ? (10 + h1 - 'a') : (h1 - '0');
+			c = 16 * c + ((h2 > '9') ? (10 + h2 - 'a') : (h2 - '0'));
+			break;
+		default:
+			c = *p++;
+	}
+	*u++ = c;
+   }
+   *u = '\0';
+}
Index: /trunk/minix/commands/httpd/utility.c
===================================================================
--- /trunk/minix/commands/httpd/utility.c	(revision 9)
+++ /trunk/minix/commands/httpd/utility.c	(revision 9)
@@ -0,0 +1,265 @@
+/* utility.c
+ *
+ * This file is part of httpd
+ *
+ * 02/17/1996 			Michael Temari <Michael@TemWare.Com>
+ * 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
+ * 12/29/2002 Initial Release	Michael Temari <Michael@TemWare.Com>
+ *
+ */
+#include <sys/types.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "utility.h"
+#include "config.h"
+
+const char *days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+			 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+char *logdate(t)
+time_t *t;
+{
+time_t worktime;
+struct tm *tm;
+static char datebuffer[80];
+
+  if(t == (time_t *)NULL)
+	(void) time(&worktime);
+  else
+  	worktime = *t;
+
+   tm = localtime(&worktime);
+
+   sprintf(datebuffer, "%4d%02d%02d%02d%02d%02d",
+		1900+tm->tm_year,
+		tm->tm_mon + 1,
+		tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+   return(datebuffer);
+}
+
+char *httpdate(t)
+time_t *t;
+{
+time_t worktime;
+struct tm *tm;
+static char datebuffer[80];
+
+  if(t == (time_t *)NULL)
+	(void) time(&worktime);
+  else
+  	worktime = *t;
+
+   tm = gmtime(&worktime);
+
+   sprintf(datebuffer, "%s, %02d %s %4d %02d:%02d:%02d GMT",
+   		days[tm->tm_wday],
+		tm->tm_mday, months[tm->tm_mon], 1900+tm->tm_year,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+   return(datebuffer);
+}
+
+time_t httptime(p)
+char *p;
+{
+time_t worktime, gtime, ltime;
+struct tm tm;
+struct tm *tm2;
+int i;
+
+   worktime = (time_t) -1;
+
+   tm.tm_yday = 0;
+   tm.tm_isdst = -1;
+
+   /* day of week */
+   for(i = 0; i < 7; i++)
+	if(!strncmp(p, days[i], 3)) break;
+   if(i < 7)
+	tm.tm_wday = i;
+   else
+	return(worktime);
+   while(*p && *p != ' ') p++;
+   if(!*p) return(worktime);
+   while(*p && *p == ' ') p++;
+   if(!*p) return(worktime);
+
+   if(*p >= '0' && *p <= '9') {
+   	/* day */
+   	if(*(p+1) >= '0' && *(p+1) <= '9')
+		tm.tm_mday = 10 * (*p - '0') + (*(p+1) - '0');
+	else
+		return(worktime);
+	p += 3;
+	/* month */
+	for(i = 0; i < 12; i++)
+		if(!strncmp(p, months[i], 3)) break;
+	if(i < 12)
+		tm.tm_mon = i;
+	else
+		return(worktime);
+	p += 3;
+	if(!*p++) return(worktime);
+	/* year */
+	tm.tm_year = atoi(p);
+	while(*p && *p != ' ') p++;
+	if(*p) p++;
+   } else {
+	/* day */
+	tm.tm_mday = atoi(p);
+	while(*p && *p != ' ') p++;
+	while(*p && *p == ' ') p++;
+	if(!*p) return(worktime);
+   }
+
+   /* hour */
+   if(*p < '0' || *p > '9' || *(p+1) < '0' || *(p+1) > '9' || *(p+2) != ':') return(worktime);
+   tm.tm_hour = 10 * (*p - '0') + (*(p+1) - '0');
+   p += 3;
+
+   /* minute */
+   if(*p < '0' || *p > '9' || *(p+1) < '0' || *(p+1) > '9' || *(p+2) != ':') return(worktime);
+   tm.tm_min  = 10 * (*p - '0') + (*(p+1) - '0');
+   p += 3;
+
+   /* second */
+   if(*p < '0' || *p > '9' || *(p+1) < '0' || *(p+1) > '9' || *(p+2) != ' ') return(worktime);
+   tm.tm_sec  = 10 * (*p - '0') + (*(p+1) - '0');
+   p += 3;
+   while(*p && *p == ' ') p++;
+   if(!*p) return(worktime);
+
+   if(*p >= '0' && *p <= '9')
+   	tm.tm_year = atoi(p);
+   else
+   	if(*p++ != 'G' || *p++ != 'M' || *p++ != 'T')
+   		return(worktime);
+
+   if(tm.tm_year == 0)
+   	return(worktime);
+
+   if(tm.tm_year > 1900)
+	tm.tm_year -= 1900;
+
+   worktime = mktime(&tm);
+
+   gtime = mktime(gmtime(&worktime));
+   tm2 = localtime(&worktime);
+   tm2->tm_isdst = 0;
+   ltime = mktime(tm2);
+
+   worktime = worktime - (gtime - ltime);
+
+   return(worktime);
+}
+
+char *mimetype(url)
+char *url;
+{
+char *p;
+struct msufx *ps;
+char *dmt;
+
+   dmt = (char *) NULL;
+   p = url;
+   while(*p) {
+   	if(*p != '.') {
+   		p++;
+   		continue;
+   	}
+   	for(ps = msufx; ps != NULL; ps = ps->snext)
+   		if(!strcmp(ps->suffix, "") && dmt == (char *) NULL)
+   			dmt = ps->mtype->mimetype;
+   		else
+   			if(!strcmp(p, ps->suffix))
+   				return(ps->mtype->mimetype);
+   	p++;
+   }
+
+   if(dmt == (char *) NULL)
+   	dmt = "application/octet-stream";
+
+   return(dmt);
+}
+
+char *decode64(p)
+char *p;
+{
+static char decode[80];
+char c[4];
+int i;
+int d;
+
+   i = 0;
+   d = 0;
+
+   while(*p) {
+   	if(*p >= 'A' && *p <= 'Z') c[i++] = *p++ - 'A'; else
+   	if(*p >= 'a' && *p <= 'z') c[i++] = *p++ - 'a' + 26; else
+   	if(*p >= '0' && *p <= '9') c[i++] = *p++ - '0' + 52; else
+   	if(*p == '+') c[i++] = *p++ - '+' + 62; else
+   	if(*p == '/') c[i++] = *p++ - '/' + 63; else
+   	if(*p == '=') c[i++] = *p++ - '='; else
+   		return("");
+   	if(i < 4) continue;
+   	decode[d++] = ((c[0] << 2) | (c[1] >> 4));
+   	decode[d++] = ((c[1] << 4) | (c[2] >> 2));
+   	decode[d++] = ((c[2] << 6) |  c[3]);
+   	decode[d] = '\0';
+   	i = 0;
+   }
+
+   return(decode);
+}
+
+int getparms(p, parms, maxparms)
+char *p;
+char *parms[];
+int maxparms;
+{
+int np;
+
+   np = 0;
+
+   if(LWS(*p)) {
+   	while(*p && LWS(*p)) p++;
+   	if(!*p) return(0);
+   	parms[np++] = (char *)NULL;
+   } else
+   	np = 0;
+
+   while(np < maxparms && *p) {
+   	parms[np++] = p;
+   	while(*p && !LWS(*p)) p++;
+   	if(*p) *p++ = '\0';
+   	while(*p && LWS(*p)) p++;
+   }
+
+   return(np);
+}
+
+int mkurlaccess(p)
+char *p;
+{
+int ua;
+
+   ua = 0;
+
+   while(*p) {
+	if(toupper(*p) == 'R') ua |= URLA_READ; else
+	if(toupper(*p) == 'W') ua |= URLA_WRITE; else
+	if(toupper(*p) == 'X') ua |= URLA_EXEC; else
+	if(toupper(*p) == 'H') ua |= URLA_HEADERS; else
+		return(0);
+	p++;
+   }
+
+   return(ua);
+}
Index: /trunk/minix/commands/httpd/utility.h
===================================================================
--- /trunk/minix/commands/httpd/utility.h	(revision 9)
+++ /trunk/minix/commands/httpd/utility.h	(revision 9)
@@ -0,0 +1,19 @@
+/* utility.h
+ *
+ * This file is part of httpd.
+ *
+ * 02/17/1996 			Michael Temari <Michael@TemWare.Com>
+ * 07/07/1996 Initial Release	Michael Temari <Michael@TemWare.Com>
+ * 12/29/2002			Michael Temari <Michael@TemWare.Com>
+ *
+ */
+
+#define	LWS(c)	((c == ' ') || (c == '\t') || (c == '\r') || (c == '\n'))
+
+_PROTOTYPE(char *logdate, (time_t *t));
+_PROTOTYPE(char *httpdate, (time_t *t));
+_PROTOTYPE(time_t httptime, (char *p));
+_PROTOTYPE(char *mimetype, (char *url));
+_PROTOTYPE(char *decode64, (char *p));
+_PROTOTYPE(int getparms, (char *p, char *parms[], int maxparms));
+_PROTOTYPE(int mkurlaccess, (char *p));
Index: /trunk/minix/commands/i386/Makefile
===================================================================
--- /trunk/minix/commands/i386/Makefile	(revision 9)
+++ /trunk/minix/commands/i386/Makefile	(revision 9)
@@ -0,0 +1,27 @@
+# Makefile for commands/i386.
+
+CFLAGS	= -D_MINIX -D_POSIX_SOURCE
+CCLD	= $(CC) -i $(CFLAGS)
+MAKE	= exec make -$(MAKEFLAGS)
+CC = exec cc
+
+all::	acd
+
+acd:	acd.c
+	$(CCLD) -o $@ -DARCH=\"`arch`\" -DDESCR=\"/usr/lib/descr\" $?
+	install -S 50kw $@
+
+install::	/usr/bin/acd /usr/bin/cc /usr/bin/m2 /usr/bin/pc
+
+/usr/bin/acd:	acd
+	install -cs -o bin $? $@
+
+/usr/bin/cc /usr/bin/m2 /usr/bin/pc:	/usr/bin/acd
+	install -l $? $@
+
+clean::
+	rm -rf a.out core acd
+
+all install clean::
+	cd asmconv && $(MAKE) $@
+	cd mtools-3.9.7 && $(MAKE) $@
Index: /trunk/minix/commands/i386/acd.c
===================================================================
--- /trunk/minix/commands/i386/acd.c	(revision 9)
+++ /trunk/minix/commands/i386/acd.c	(revision 9)
@@ -0,0 +1,2701 @@
+/*	acd 1.10 - A compiler driver			Author: Kees J. Bot
+ *								7 Jan 1993
+ * Needs about 25kw heap + stack.
+ */
+char version[] = "1.9";
+
+#define nil 0
+#define _POSIX_SOURCE	1
+#include <sys/types.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <ctype.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#ifndef LIB
+#define LIB	"/usr/lib"	/* Default library directory. */
+#endif
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+
+char *program;		/* Call name. */
+
+int verbose= 0;		/* -v0: Silent.
+			 * -v1: Show abbreviated pass names.
+			 * -v2: Show executed UNIX commands.
+			 * -v3: Show executed ACD commands.
+			 * -v4: Show descr file as it is read.
+			 */
+
+int action= 2;		/*   0: An error occured, don't do anything anymore.
+			 *   1: (-vn) Do not execute, play-act.
+			 *   2: Execute UNIX commands.
+			 */
+
+void report(char *label)
+{
+	if (label == nil || label[0] == 0) {
+		fprintf(stderr, "%s: %s\n", program, strerror(errno));
+	} else {
+		fprintf(stderr, "%s: %s: %s\n",
+					program, label, strerror(errno));
+	}
+	action= 0;
+}
+
+void quit(int exit_code);
+
+void fatal(char *label)
+{
+	report(label);
+	quit(-1);
+}
+
+size_t heap_chunks= 0;
+
+void *allocate(void *mem, size_t size)
+/* Safe malloc/realloc.  (I have heard that one can call realloc with a
+ * null first argument with the effect below, but that is of course to
+ * ridiculous to believe.)
+ */
+{
+	assert(size > 0);
+
+	if (mem != nil) {
+		mem= realloc(mem, size);
+	} else {
+		mem= malloc(size);
+		heap_chunks++;
+	}
+	if (mem == nil) fatal(nil);
+	return mem;
+}
+
+void deallocate(void *mem)
+{
+	if (mem != nil) {
+		free(mem);
+		heap_chunks--;
+	}
+}
+
+char *copystr(const char *s)
+{
+	char *c;
+	c= allocate(nil, (strlen(s)+1) * sizeof(*c));
+	strcpy(c, s);
+	return c;
+}
+
+/* Every object, list, letter, or variable, is made with cells. */
+typedef struct cell {
+	unsigned short	refc;		/* Reference count. */
+	char		type;		/* Type of object. */
+	unsigned char	letter;		/* Simply a letter. */
+	char		*name;		/* Name of a word. */
+	struct cell	*hash;		/* Hash chain. */
+	struct cell	*car, *cdr;	/* To form lists. */
+
+/* For a word: */
+#	define	value	car		/* Value of a variable. */
+#	define	base	cdr		/* Base-name in transformations. */
+#	define	suffix	cdr		/* Suffix in a treat-as. */
+#	define	flags	letter		/* Special flags. */
+
+/* A substitution: */
+#	define	subst	car
+
+} cell_t;
+
+typedef enum type {
+	CELL,		/* A list cell. */
+	STRING,		/* To make a list of characters and substs. */
+	SUBST,		/* Variable to substitute. */
+	/* Unique objects. */
+	LETTER,		/* A letter. */
+	WORD,		/* A string collapses to a word. */
+	EQUALS,		/* = operator, etc. */
+	OPEN,
+	CLOSE,
+	PLUS,
+	MINUS,
+	STAR,
+	INPUT,
+	OUTPUT,
+	WHITE,
+	COMMENT,
+	SEMI,
+	EOLN,
+	N_TYPES		/* number of different types */
+} type_t;
+
+#define is_unique(type) ((type) >= LETTER)
+
+/* Flags on a word. */
+#define W_SET		0x01	/* Not undefined, e.g. assigned to. */
+#define W_RDONLY	0x02	/* Read only. */
+#define W_LOCAL		0x04	/* Local variable, immediate substitution. */
+#define W_TEMP		0x08	/* Name of a temporary file, delete on quit. */
+#define W_SUFF		0x10	/* Has a suffix set on it. */
+
+void princhar(int c)
+/* Print a character, escaped if important to the shell *within* quotes. */
+{
+	if (strchr("\\'\"<>();~$^&*|{}[]?", c) != nil) fputc('\\', stdout);
+	putchar(c);
+}
+
+void prinstr(char *s)
+/* Print a string, in quotes if the shell might not like it. */
+{
+	int q= 0;
+	char *s2= s;
+
+	while (*s2 != 0)
+		if (strchr("~`$^&*()=\\|[]{};'\"<>?", *s2++) != nil) q= 1;
+
+	if (q) fputc('"', stdout);
+	while (*s != 0) princhar(*s++);
+	if (q) fputc('"', stdout);
+}
+
+void prin2(cell_t *p);
+
+void prin1(cell_t *p)
+/* Print a cell structure for debugging purposes. */
+{
+	if (p == nil) {
+		printf("(\b(\b()\b)\b)");
+		return;
+	}
+
+	switch (p->type) {
+	case CELL:
+		printf("(\b(\b(");
+		prin2(p);
+		printf(")\b)\b)");
+		break;
+	case STRING:
+		printf("\"\b\"\b\"");
+		prin2(p);
+		printf("\"\b\"\b\"");
+		break;
+	case SUBST:
+		printf("$\b$\b${%s}", p->subst->name);
+		break;
+	case LETTER:
+		princhar(p->letter);
+		break;
+	case WORD:
+		prinstr(p->name);
+		break;
+	case EQUALS:
+		printf("=\b=\b=");
+		break;
+	case PLUS:
+		printf("+\b+\b+");
+		break;
+	case MINUS:
+		printf("-\b-\b-");
+		break;
+	case STAR:
+		printf("*\b*\b*");
+		break;
+	case INPUT:
+		printf(verbose >= 3 ? "<\b<\b<" : "<");
+		break;
+	case OUTPUT:
+		printf(verbose >= 3 ? ">\b>\b>" : ">");
+		break;
+	default:
+		assert(0);
+	}
+}
+
+void prin2(cell_t *p)
+/* Print a list for debugging purposes. */
+{
+	while (p != nil && p->type <= STRING) {
+		prin1(p->car);
+
+		if (p->type == CELL && p->cdr != nil) fputc(' ', stdout);
+
+		p= p->cdr;
+	}
+	if (p != nil) prin1(p);		/* Dotted pair? */
+}
+
+void prin1n(cell_t *p) { prin1(p); fputc('\n', stdout); }
+
+void prin2n(cell_t *p) { prin2(p); fputc('\n', stdout); }
+
+/* A program is consists of a series of lists at a certain indentation level. */
+typedef struct program {
+	struct program	*next;
+	cell_t		*file;		/* Associated description file. */
+	unsigned	indent;		/* Line indentation level. */
+	unsigned	lineno;		/* Line number where this is found. */
+	cell_t		*line;		/* One line of tokens. */
+} program_t;
+
+program_t *pc;		/* Program Counter (what else?) */
+program_t *nextpc;	/* Next line to execute. */
+
+cell_t *oldcells;	/* Keep a list of old cells, don't deallocate. */
+
+cell_t *newcell(void)
+/* Make a new empty cell. */
+{
+	cell_t *p;
+
+	if (oldcells != nil) {
+		p= oldcells;
+		oldcells= p->cdr;
+		heap_chunks++;
+	} else {
+		p= allocate(nil, sizeof(*p));
+	}
+
+	p->refc= 0;
+	p->type= CELL;
+	p->letter= 0;
+	p->name= nil;
+	p->car= nil;
+	p->cdr= nil;
+	return p;
+}
+
+#define N_CHARS		(1 + (unsigned char) -1)
+#define HASHDENSE	0x400
+
+cell_t *oblist[HASHDENSE + N_CHARS + N_TYPES];
+
+unsigned hashfun(cell_t *p)
+/* Use a blender on a cell. */
+{
+	unsigned h;
+	char *name;
+
+	switch (p->type) {
+	case WORD:
+		h= 0;
+		name= p->name;
+		while (*name != 0) h= (h * 0x1111) + *name++;
+		return h % HASHDENSE;
+	case LETTER:
+		return HASHDENSE + p->letter;
+	default:
+		return HASHDENSE + N_CHARS + p->type;
+	}
+}
+
+cell_t *search(cell_t *p, cell_t ***hook)
+/* Search for *p, return the one found.  *hook may be used to insert or
+ * delete.
+ */
+{
+	cell_t *sp;
+
+	sp= *(*hook= &oblist[hashfun(p)]);
+
+	if (p->type == WORD) {
+		/* More than one name per hash slot. */
+		int cmp= 0;
+
+		while (sp != nil && (cmp= strcmp(p->name, sp->name)) > 0)
+			sp= *(*hook= &sp->hash);
+
+		if (cmp != 0) sp= nil;
+	}
+	return sp;
+}
+
+void dec(cell_t *p)
+/* Decrease the number of references to p, if zero delete and recurse. */
+{
+	if (p == nil || --p->refc > 0) return;
+
+	if (is_unique(p->type)) {
+		/* Remove p from the oblist. */
+		cell_t *o, **hook;
+
+		o= search(p, &hook);
+
+		if (o == p) {
+			/* It's there, remove it. */
+			*hook= p->hash;
+			p->hash= nil;
+		}
+
+		if (p->type == WORD && (p->flags & W_TEMP)) {
+			/* A filename to remove. */
+			if (verbose >= 2) {
+				printf("rm -f ");
+				prinstr(p->name);
+				fputc('\n', stdout);
+			}
+			if (unlink(p->name) < 0 && errno != ENOENT)
+				report(p->name);
+		}
+	}
+	deallocate(p->name);
+	dec(p->car);
+	dec(p->cdr);
+	p->cdr= oldcells;
+	oldcells= p;
+	heap_chunks--;
+}
+
+cell_t *inc(cell_t *p)
+/* Increase the number of references to p. */
+{
+	cell_t *o, **hook;
+
+	if (p == nil) return nil;
+
+	if (++p->refc > 1 || !is_unique(p->type)) return p;
+
+	/* First appearance, put p on the oblist. */
+	o= search(p, &hook);
+
+	if (o == nil) {
+		/* Not there yet, add it. */
+		p->hash= *hook;
+		*hook= p;
+	} else {
+		/* There is another object already there with the same info. */
+		o->refc++;
+		dec(p);
+		p= o;
+	}
+	return p;
+}
+
+cell_t *go(cell_t *p, cell_t *field)
+/* Often happening: You've got p, you want p->field. */
+{
+	field= inc(field);
+	dec(p);
+	return field;
+}
+
+cell_t *cons(type_t type, cell_t *p)
+/* P is to be added to a list (or a string). */
+{
+	cell_t *l= newcell();
+	l->type= type;
+	l->refc++;
+	l->car= p;
+	return l;
+}
+
+cell_t *append(type_t type, cell_t *p)
+/* P is to be appended to a list (or a string). */
+{
+	return p == nil || p->type == type ? p : cons(type, p);
+}
+
+cell_t *findnword(char *name, size_t n)
+/* Find the word with the given name of length n. */
+{
+	cell_t *w= newcell();
+	w->type= WORD;
+	w->name= allocate(nil, (n+1) * sizeof(*w->name));
+	memcpy(w->name, name, n);
+	w->name[n]= 0;
+	return inc(w);
+}
+
+cell_t *findword(char *name)
+/* Find the word with the given null-terminated name. */
+{
+	return findnword(name, strlen(name));
+}
+
+void quit(int exstat)
+/* Remove all temporary names, then exit. */
+{
+	cell_t **op, *p, *v, *b;
+	size_t chunks;
+
+	/* Remove cycles, like X = X. */
+	for (op= oblist; op < oblist + HASHDENSE; op++) {
+		p= *op;
+		while (p != nil) {
+			if (p->value != nil || p->base != nil) {
+				v= p->value;
+				b= p->base;
+				p->value= nil;
+				p->base= nil;
+				p= *op;
+				dec(v);
+				dec(b);
+			} else {
+				p= p->hash;
+			}
+		}
+	}
+	chunks= heap_chunks;
+
+	/* Something may remain on an early quit: tempfiles. */
+	for (op= oblist; op < oblist + HASHDENSE; op++) {
+
+		while (*op != nil) { (*op)->refc= 1; dec(*op); }
+	}
+
+	if (exstat != -1 && chunks > 0) {
+		fprintf(stderr,
+			"%s: internal fault: %d chunks still on the heap\n",
+						program, chunks);
+	}
+	exit(exstat);
+}
+
+void interrupt(int sig)
+{
+	signal(sig, interrupt);
+	if (verbose >= 2) write(1, "# interrupt\n", 12);
+	action= 0;
+}
+
+int extalnum(int c)
+/* Uppercase, lowercase, digit, underscore or anything non-American. */
+{
+	return isalnum(c) || c == '_' || c >= 0200;
+}
+
+char *descr;		/* Name of current description file. */
+FILE *dfp;		/* Open description file. */
+int dch;		/* Input character. */
+unsigned lineno;	/* Line number in file. */
+unsigned indent;	/* Indentation level. */
+
+void getdesc(void)
+{
+	if (dch == EOF) return;
+
+	if (dch == '\n') { lineno++; indent= 0; }
+
+	if ((dch = getc(dfp)) == EOF && ferror(dfp)) fatal(descr);
+
+	if (dch == 0) {
+		fprintf(stderr, "%s: %s is a binary file.\n", program, descr);
+		quit(-1);
+	}
+}
+
+#define E_BASH		0x01	/* Escaped by backslash. */
+#define E_QUOTE		0x02	/* Escaped by double quote. */
+#define E_SIMPLE	0x04	/* More simple characters? */
+
+cell_t *get_token(void)
+/* Read one token from the description file. */
+{
+	int whitetype= 0;
+	static int escape= 0;
+	cell_t *tok;
+	char *name;
+	int n, i;
+
+	if (escape & E_SIMPLE) {
+		/* More simple characters?  (Note: performance hack.) */
+		if (isalnum(dch)) {
+			tok= newcell();
+			tok->type= LETTER;
+			tok->letter= dch;
+			getdesc();
+			return inc(tok);
+		}
+		escape&= ~E_SIMPLE;
+	}
+
+	/* Gather whitespace. */
+	for (;;) {
+		if (dch == '\\' && whitetype == 0) {
+			getdesc();
+			if (isspace(dch)) {
+				/* \ whitespace: remove. */
+				do {
+					getdesc();
+					if (dch == '#' && !(escape & E_QUOTE)) {
+						/* \ # comment */
+						do
+							getdesc();
+						while (dch != '\n'
+								&& dch != EOF);
+					}
+				} while (isspace(dch));
+				continue;
+			}
+			escape|= E_BASH;	/* Escaped character. */
+		}
+
+		if (escape != 0) break;
+
+		if (dch == '#' && (indent == 0 || whitetype != 0)) {
+			/* # Comment. */
+			do getdesc(); while (dch != '\n' && dch != EOF);
+			whitetype= COMMENT;
+			break;
+		}
+
+		if (!isspace(dch) || dch == '\n' || dch == EOF) break;
+
+		whitetype= WHITE;
+
+		indent++;
+		if (dch == '\t') indent= (indent + 7) & ~7;
+
+		getdesc();
+	}
+
+	if (dch == EOF) return nil;
+
+	/* Make a token. */
+	tok= newcell();
+
+	if (whitetype != 0) {
+		tok->type= whitetype;
+		return inc(tok);
+	}
+
+	if (!(escape & E_BASH) && dch == '"') {
+		getdesc();
+		if (!(escape & E_QUOTE)) {
+			/* Start of a string, signal this with a string cell. */
+			escape|= E_QUOTE;
+			tok->type= STRING;
+			return inc(tok);
+		} else {
+			/* End of a string, back to normal mode. */
+			escape&= ~E_QUOTE;
+			deallocate(tok);
+			return get_token();
+		}
+	}
+
+	if (escape & E_BASH
+		|| strchr(escape & E_QUOTE ? "$" : "$=()+-*<>;\n", dch) == nil
+	) {
+		if (dch == '\n') {
+			fprintf(stderr,
+				"\"%s\", line %u: missing closing quote\n",
+				descr, lineno);
+			escape&= ~E_QUOTE;
+			action= 0;
+		}
+		if (escape & E_BASH && dch == 'n') dch= '\n';
+		escape&= ~E_BASH;
+
+		/* A simple character. */
+		tok->type= LETTER;
+		tok->letter= dch;
+		getdesc();
+		escape|= E_SIMPLE;
+		return inc(tok);
+	}
+
+	if (dch != '$') {
+		/* Single character token. */
+		switch (dch) {
+		case '=':	tok->type= EQUALS;	break;
+		case '(':	tok->type= OPEN;	break;
+		case ')':	tok->type= CLOSE;	break;
+		case '+':	tok->type= PLUS;	break;
+		case '-':	tok->type= MINUS;	break;
+		case '*':	tok->type= STAR;	break;
+		case '<':	tok->type= INPUT;	break;
+		case '>':	tok->type= OUTPUT;	break;
+		case ';':	tok->type= SEMI;	break;
+		case '\n':	tok->type= EOLN;	break;
+		}
+		getdesc();
+		return inc(tok);
+	}
+
+	/* Substitution. */
+	getdesc();
+	if (dch == EOF || isspace(dch)) {
+		fprintf(stderr, "\"%s\", line %u: Word expected after '$'\n",
+			descr, lineno);
+		action= 0;
+		deallocate(tok);
+		return get_token();
+	}
+
+	name= allocate(nil, (n= 16) * sizeof(*name));
+	i= 0;
+
+	if (dch == '{' || dch == '('  /* )} */ ) {
+		/* $(X), ${X} */
+		int lpar= dch;		/* ( */
+		int rpar= lpar == '{' ? '}' : ')';
+
+		for (;;) {
+			getdesc();
+			if (dch == rpar) { getdesc(); break; }
+			if (isspace(dch) || dch == EOF) {
+				fprintf(stderr,
+				"\"%s\", line %u: $%c unmatched, no '%c'\n",
+					descr, lineno, lpar, rpar);
+				action= 0;
+				break;
+			}
+			name[i++]= dch;
+			if (i == n)
+				name= allocate(name, (n*= 2) * sizeof(char));
+		}
+	} else
+	if (extalnum(dch)) {
+		/* $X */
+		do {
+			name[i++]= dch;
+			if (i == n)
+				name= allocate(name, (n*= 2) * sizeof(char));
+			getdesc();
+		} while (extalnum(dch));
+	} else {
+		/* $* */
+		name[i++]= dch;
+		getdesc();
+	}
+	name[i++]= 0;
+	name= allocate(name, i * sizeof(char));
+	tok->type= SUBST;
+	tok->subst= newcell();
+	tok->subst->type= WORD;
+	tok->subst->name= name;
+	tok->subst= inc(tok->subst);
+	return inc(tok);
+}
+
+typedef enum how { SUPERFICIAL, PARTIAL, FULL, EXPLODE, IMPLODE } how_t;
+
+cell_t *explode(cell_t *p, how_t how);
+
+cell_t *get_string(cell_t **pp)
+/* Get a string: A series of letters and substs.  Special tokens '=', '+', '-'
+ * and '*' are also recognized if on their own.  A finished string is "exploded"
+ * to a word if it consists of letters only.
+ */
+{
+	cell_t *p= *pp, *s= nil, **ps= &s;
+	int quoted= 0;
+
+	while (p != nil) {
+		switch (p->type) {
+		case STRING:
+			quoted= 1;
+			dec(p);
+			break;
+		case EQUALS:
+		case PLUS:
+		case MINUS:
+		case STAR:
+		case SUBST:
+		case LETTER:
+			*ps= cons(STRING, p);
+			ps= &(*ps)->cdr;
+			break;
+		default:
+			goto got_string;
+		}
+		p= get_token();
+	}
+    got_string:
+	*pp= p;
+
+	/* A single special token must be folded up. */
+	if (!quoted && s != nil && s->cdr == nil) {
+		switch (s->car->type) {
+		case EQUALS:
+		case PLUS:
+		case MINUS:
+		case STAR:
+		case SUBST:
+			return go(s, s->car);
+		}
+	}
+
+	/* Go over the string changing '=', '+', '-', '*' to letters. */
+	for (p= s; p != nil; p= p->cdr) {
+		int c= 0;
+
+		switch (p->car->type) {
+		case EQUALS:
+			c= '='; break;
+		case PLUS:
+			c= '+'; break;
+		case MINUS:
+			c= '-'; break;
+		case STAR:
+			c= '*'; break;
+		}
+		if (c != 0) {
+			dec(p->car);
+			p->car= newcell();
+			p->car->type= LETTER;
+			p->car->letter= c;
+			p->car= inc(p->car);
+		}
+	}
+	return explode(s, SUPERFICIAL);
+}
+
+cell_t *get_list(cell_t **pp, type_t stop)
+/* Read a series of tokens upto a token of type "stop". */
+{
+	cell_t *p= *pp, *l= nil, **pl= &l;
+
+	while (p != nil && p->type != stop
+				&& !(stop == EOLN && p->type == SEMI)) {
+		switch (p->type) {
+		case WHITE:
+		case COMMENT:
+		case SEMI:
+		case EOLN:
+			dec(p);
+			p= get_token();
+			break;
+		case OPEN:
+			/* '(' words ')'. */
+			dec(p);
+			p= get_token();
+			*pl= cons(CELL, get_list(&p, CLOSE));
+			pl= &(*pl)->cdr;
+			dec(p);
+			p= get_token();
+			break;
+		case CLOSE:
+			/* Unexpected closing parenthesis. (*/
+			fprintf(stderr, "\"%s\", line %u: unmatched ')'\n",
+				descr, lineno);
+			action= 0;
+			dec(p);
+			p= get_token();
+			break;
+		case INPUT:
+		case OUTPUT:
+			*pl= cons(CELL, p);
+			pl= &(*pl)->cdr;
+			p= get_token();
+			break;
+		case STRING:
+		case EQUALS:
+		case PLUS:
+		case MINUS:
+		case STAR:
+		case LETTER:
+		case SUBST:
+			*pl= cons(CELL, get_string(&p));
+			pl= &(*pl)->cdr;
+			break;
+		default:
+			assert(0);
+		}
+	}
+
+	if (p == nil && stop == CLOSE) {
+		/* Couldn't get the closing parenthesis. */
+		fprintf(stderr, "\"%s\", lines %u-%u: unmatched '('\n",	/*)*/
+			descr, pc->lineno, lineno);
+		action= 0;
+	}
+	*pp= p;
+	return l;
+}
+
+program_t *get_line(cell_t *file)
+{
+	program_t *l;
+	cell_t *p;
+	static keep_indent= 0;
+	static unsigned old_indent= 0;
+
+	/* Skip leading whitespace to determine the indentation level. */
+	indent= 0;
+	while ((p= get_token()) != nil && p->type == WHITE) dec(p);
+
+	if (p == nil) return nil;		/* EOF */
+
+	if (p->type == EOLN) indent= old_indent;	/* Empty line. */
+
+	/* Make a program line. */
+	pc= l= allocate(nil, sizeof(*l));
+
+	l->next= nil;
+	l->file= inc(file);
+	l->indent= keep_indent ? old_indent : indent;
+	l->lineno= lineno;
+
+	l->line= get_list(&p, EOLN);
+
+	/* If the line ended in a semicolon then keep the indentation level. */
+	keep_indent= (p != nil && p->type == SEMI);
+	old_indent= l->indent;
+
+	dec(p);
+
+	if (verbose >= 4) {
+		if (l->line == nil)
+			fputc('\n', stdout);
+		else {
+			printf("%*s", (int) l->indent, "");
+			prin2n(l->line);
+		}
+	}
+	return l;
+}
+
+program_t *get_prog(void)
+/* Read the description file into core. */
+{
+	cell_t *file;
+	program_t *prog, **ppg= &prog;
+
+	descr= copystr(descr);
+
+	if (descr[0] == '-' && descr[1] == 0) {
+		/* -descr -: Read from standard input. */
+		deallocate(descr);
+		descr= copystr("stdin");
+		dfp= stdin;
+	} else {
+		char *d= descr;
+
+		if (*d == '.' && *++d == '.') d++;
+		if (*d != '/') {
+			/* -descr name: Read /usr/lib/<name>/descr. */
+
+			d= allocate(nil, sizeof(LIB) +
+					(strlen(descr) + 7) * sizeof(*d));
+			sprintf(d, "%s/%s/descr", LIB, descr);
+			deallocate(descr);
+			descr= d;
+		}
+		if ((dfp= fopen(descr, "r")) == nil) fatal(descr);
+	}
+	file= findword(descr);
+	deallocate(descr);
+	descr= file->name;
+
+	/* Preread the first character. */
+	dch= 0;
+	lineno= 1;
+	indent= 0;
+	getdesc();
+
+	while ((*ppg= get_line(file)) != nil) ppg= &(*ppg)->next;
+
+	if (dfp != stdin) (void) fclose(dfp);
+	dec(file);
+
+	return prog;
+}
+
+void makenames(cell_t ***ppr, cell_t *s, char **name, size_t i, size_t *n)
+/* Turn a string of letters and lists into words.  A list denotes a choice
+ * between several paths, like a search on $PATH.
+ */
+{
+	cell_t *p, *q;
+	size_t len;
+
+	/* Simply add letters, skip empty lists. */
+	while (s != nil && (s->car == nil || s->car->type == LETTER)) {
+		if (s->car != nil) {
+			if (i == *n) *name= allocate(*name,
+						(*n *= 2) * sizeof(**name));
+			(*name)[i++]= s->car->letter;
+		}
+		s= s->cdr;
+	}
+
+	/* If the end is reached then make a word out of the result. */
+	if (s == nil) {
+		**ppr= cons(CELL, findnword(*name, i));
+		*ppr= &(**ppr)->cdr;
+		return;
+	}
+
+	/* Elements of a list must be tried one by one. */
+	p= s->car;
+	s= s->cdr;
+
+	while (p != nil) {
+		if (p->type == WORD) {
+			q= p; p= nil;
+		} else {
+			assert(p->type == CELL);
+			q= p->car; p= p->cdr;
+			assert(q != nil);
+			assert(q->type == WORD);
+		}
+		len= strlen(q->name);
+		if (i + len > *n) *name= allocate(*name,
+					(*n += i + len) * sizeof(**name));
+		memcpy(*name + i, q->name, len);
+
+		makenames(ppr, s, name, i+len, n);
+	}
+}
+
+int constant(cell_t *p)
+/* See if a string has been partially evaluated to a constant so that it
+ * can be imploded to a word.
+ */
+{
+	while (p != nil) {
+		switch (p->type) {
+		case CELL:
+		case STRING:
+			if (!constant(p->car)) return 0;
+			p= p->cdr;
+			break;
+		case SUBST:
+			return 0;
+		default:
+			return 1;
+		}
+	}
+	return 1;
+}
+
+cell_t *evaluate(cell_t *p, how_t how);
+
+cell_t *explode(cell_t *s, how_t how)
+/* Explode a string with several choices to just one list of choices. */
+{
+	cell_t *t, *r= nil, **pr= &r;
+	size_t i, n;
+	char *name;
+	struct stat st;
+
+	if (how >= PARTIAL) {
+		/* Evaluate the string, expanding substitutions. */
+		while (s != nil) {
+			assert(s->type == STRING);
+			t= inc(s->car);
+			s= go(s, s->cdr);
+
+			t= evaluate(t, how == IMPLODE ? EXPLODE : how);
+
+			/* A list of one element becomes that element. */
+			if (t != nil && t->type == CELL && t->cdr == nil)
+				t= go(t, t->car);
+
+			/* Append the result, trying to flatten it. */
+			*pr= t;
+
+			/* Find the end of what has just been added. */
+			while ((*pr) != nil) {
+				*pr= append(STRING, *pr);
+				pr= &(*pr)->cdr;
+			}
+		}
+		s= r;
+	}
+
+	/* Is the result a simple string of constants? */
+	if (how <= PARTIAL && !constant(s)) return s;
+
+	/* Explode the string to all possible choices, by now the string is
+	 * a series of characters, words and lists of words.
+	 */
+	r= nil; pr= &r;
+	name= allocate(nil, (n= 16) * sizeof(char));
+	i= 0;
+
+	makenames(&pr, s, &name, i, &n);
+	deallocate(name);
+	assert(r != nil);
+	dec(s);
+	s= r;
+
+	/* "How" may specify that a choice must be made. */
+	if (how == IMPLODE) {
+		if (s->cdr != nil) {
+			/* More than one choice, find the file. */
+			do {
+				assert(s->car->type == WORD);
+				if (stat(s->car->name, &st) >= 0)
+					return go(r, s->car);	/* Found. */
+			} while ((s= s->cdr) != nil);
+		}
+		/* The first name is the default if nothing is found. */
+		return go(r, r->car);
+	}
+
+	/* If the result is a list of one word then return that word, otherwise
+	 * turn it into a string again unless this explode has been called
+	 * by another explode.  (Exploding a string inside a string, the joys
+	 * of recursion.)
+	 */
+	if (s->cdr == nil) return go(s, s->car);
+
+	return how >= EXPLODE ? s : cons(STRING, s);
+}
+
+void modify(cell_t **pp, cell_t *p, type_t mode)
+/* Add or remove the element p from the list *pp. */
+{
+	while (*pp != nil) {
+		*pp= append(CELL, *pp);
+
+		if ((*pp)->car == p) {
+			/* Found it, if adding then exit, else remove. */
+			if (mode == PLUS) break;
+			*pp= go(*pp, (*pp)->cdr);
+		} else
+			pp= &(*pp)->cdr;
+	}
+
+	if (*pp == nil && mode == PLUS) {
+		/* Not found, add it. */
+		*pp= cons(CELL, p);
+	} else
+		dec(p);
+}
+
+int tainted(cell_t *p)
+/* A variable is tainted (must be substituted) if either it is marked as a
+ * local variable, or some subst in its value is.
+ */
+{
+	if (p == nil) return 0;
+
+	switch (p->type) {
+	case CELL:
+	case STRING:
+		return tainted(p->car) || tainted(p->cdr);
+	case SUBST:
+		return p->subst->flags & W_LOCAL || tainted(p->subst->value);
+	default:
+		return 0;
+	}
+}
+
+cell_t *evaluate(cell_t *p, how_t how)
+/* Evaluate an expression, usually the right hand side of an assignment. */
+{
+	cell_t *q, *t, *r= nil, **pr= &r;
+	type_t mode;
+
+	if (p == nil) return nil;
+
+	switch (p->type) {
+	case CELL:
+		break;	/* see below */
+	case STRING:
+		return explode(p, how);
+	case SUBST:
+		if (how >= FULL || tainted(p))
+			p= evaluate(go(p, p->subst->value), how);
+		return p;
+	case EQUALS:
+		fprintf(stderr,
+			"\"%s\", line %u: Can't do nested assignments\n",
+			descr, pc->lineno);
+		action= 0;
+		dec(p);
+		return nil;
+	case LETTER:
+	case WORD:
+	case INPUT:
+	case OUTPUT:
+	case PLUS:
+	case MINUS:
+		return p;
+	default:
+		assert(0);
+	}
+
+	/* It's a list, see if there is a '*' there forcing a full expansion,
+	 * or a '+' or '-' forcing an implosive expansion.  (Yeah, right.)
+	 * Otherwise evaluate each element.
+	 */
+	q = inc(p);
+	while (p != nil) {
+		if ((t= p->car) != nil) {
+			if (t->type == STAR) {
+				if (how < FULL) how= FULL;
+				dec(q);
+				*pr= evaluate(go(p, p->cdr), how);
+				return r;
+			}
+			if (how>=FULL && (t->type == PLUS || t->type == MINUS))
+				break;
+		}
+
+		t= evaluate(inc(t), how);
+		assert(p->type == CELL);
+		p= go(p, p->cdr);
+
+		if (how >= FULL) {
+			/* Flatten the list. */
+			*pr= t;
+		} else {
+			/* Keep the nested list structure. */
+			*pr= cons(CELL, t);
+		}
+
+		/* Find the end of what has just been added. */
+		while ((*pr) != nil) {
+			*pr= append(CELL, *pr);
+			pr= &(*pr)->cdr;
+		}
+	}
+
+	if (p == nil) {
+		/* No PLUS or MINUS: done. */
+		dec(q);
+		return r;
+	}
+
+	/* A PLUS or MINUS, reevaluate the original list implosively. */
+	if (how < IMPLODE) {
+		dec(r);
+		dec(p);
+		return evaluate(q, IMPLODE);
+	}
+	dec(q);
+
+	/* Execute the PLUSes and MINUSes. */
+	while (p != nil) {
+		t= inc(p->car);
+		p= go(p, p->cdr);
+
+		if (t != nil && (t->type == PLUS || t->type == MINUS)) {
+			/* Change the add/subtract mode. */
+			mode= t->type;
+			dec(t);
+			continue;
+		}
+
+		t= evaluate(t, IMPLODE);
+
+		/* Add or remove all elements of t to/from r. */
+		while (t != nil) {
+			if (t->type == CELL) {
+				modify(&r, inc(t->car), mode);
+			} else {
+				modify(&r, t, mode);
+				break;
+			}
+			t= go(t, t->cdr);
+		}
+	}
+	return r;
+}
+
+/* An ACD program can be in three phases: Initialization (the first run
+ * of the program), argument scanning, and compilation.
+ */
+typedef enum phase { INIT, SCAN, COMPILE } phase_t;
+
+phase_t phase;
+
+typedef struct rule {		/* Transformation rule. */
+	struct rule	*next;
+	char		type;		/* arg, transform, combine */
+	char		flags;
+	unsigned short	npaths;		/* Number of paths running through. */
+#	define	match	from		/* Arg matching strings. */
+	cell_t		*from;		/* Transformation source suffixe(s) */
+	cell_t		*to;		/* Destination suffix. */
+	cell_t		*wait;		/* Files waiting to be transformed. */
+	program_t	*prog;		/* Program to execute. */
+	struct rule	*path;		/* Transformation path. */
+} rule_t;
+
+typedef enum ruletype { ARG, PREFER, TRANSFORM, COMBINE } ruletype_t;
+
+#define R_PREFER	0x01		/* A preferred transformation. */
+
+rule_t *rules= nil;
+
+void newrule(ruletype_t type, cell_t *from, cell_t *to)
+/* Make a new rule cell. */
+{
+	rule_t *r= nil, **pr= &rules;
+
+	/* See if there is a rule with the same suffixes, probably a matching
+	 * transform and prefer, or a re-execution of the same arg command.
+	 */
+	while ((r= *pr) != nil) {
+		if (r->from == from && r->to == to) break;
+		pr= &r->next;
+	}
+
+	if (*pr == nil) {
+		/* Add a new rule. */
+		*pr= r= allocate(nil, sizeof(*r));
+
+		r->next= nil;
+		r->type= type;
+		r->flags= 0;
+		r->from= r->to= r->wait= nil;
+		r->path= nil;
+	}
+	if (type == TRANSFORM) r->type= TRANSFORM;
+	if (type == PREFER) r->flags|= R_PREFER;
+	if (type != PREFER) r->prog= pc;
+	dec(r->from); r->from= from;
+	dec(r->to); r->to= to;
+}
+
+int talk(void)
+/* True if verbose and if so indent what is to come. */
+{
+	if (verbose < 3) return 0;
+	printf("%*s", (int) pc->indent, "");
+	return 1;
+}
+
+void unix_exec(cell_t *c)
+/* Execute the list of words p as a UNIX command. */
+{
+	cell_t *v, *a;
+	int fd[2];
+	int *pf;
+	char **argv;
+	int i, n;
+	int r, pid, status;
+
+	if (action == 0) return;	/* Error mode. */
+
+	if (talk() || verbose >= 2) prin2n(c);
+
+	fd[0]= fd[1]= -1;
+
+	argv= allocate(nil, (n= 16) * sizeof(*argv));
+	i= 0;
+
+	/* Gather argv[] and scan for I/O redirection. */
+	for (v= c; v != nil; v= v->cdr) {
+		a= v->car;
+		pf= nil;
+		if (a->type == INPUT) pf= &fd[0];
+		if (a->type == OUTPUT) pf= &fd[1];
+
+		if (pf == nil) {
+			/* An argument. */
+			argv[i++]= a->name;
+			if (i==n) argv= allocate(argv, (n*= 2) * sizeof(*argv));
+			continue;
+		}
+		/* I/O redirection. */
+		if ((v= v->cdr) == nil || (a= v->car)->type != WORD) {
+			fprintf(stderr,
+			"\"%s\", line %u: I/O redirection without a file\n",
+				descr, pc->lineno);
+			action= 0;
+			if (v == nil) break;
+		}
+		if (*pf >= 0) close(*pf);
+
+		if (action >= 2
+			&& (*pf= open(a->name, pf == &fd[0] ? O_RDONLY
+				: O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0
+		) {
+			report(a->name);
+			action= 0;
+		}
+	}
+	argv[i]= nil;
+
+	if (i >= 0 && action > 0 && verbose == 1) {
+		char *name= strrchr(argv[0], '/');
+
+		if (name == nil) name= argv[0]; else name++;
+
+		printf("%s\n", name);
+	}
+	if (i >= 0 && action >= 2) {
+		/* Really execute the command. */
+		fflush(stdout);
+		switch (pid= fork()) {
+		case -1:
+			fatal("fork()");
+		case 0:
+			if (fd[0] >= 0) { dup2(fd[0], 0); close(fd[0]); }
+			if (fd[1] >= 0) { dup2(fd[1], 1); close(fd[1]); }
+			execvp(argv[0], argv);
+			report(argv[0]);
+			exit(-1);
+		}
+	}
+	if (fd[0] >= 0) close(fd[0]);
+	if (fd[1] >= 0) close(fd[1]);
+
+	if (i >= 0 && action >= 2) {
+		/* Wait for the command to terminate. */
+		while ((r= wait(&status)) != pid && (r >= 0 || errno == EINTR));
+
+		if (status != 0) {
+			int sig= WTERMSIG(status);
+
+			if (!WIFEXITED(status)
+					&& sig != SIGINT && sig != SIGPIPE) {
+				fprintf(stderr, "%s: %s: Signal %d%s\n",
+					program, argv[0], sig,
+					status & 0x80 ? " - core dumped" : "");
+			}
+			action= 0;
+		}
+	}
+	deallocate(argv);
+}
+
+/* Special read-only variables ($*) and lists. */
+cell_t *V_star, **pV_star;
+cell_t *L_files, **pL_files= &L_files;
+cell_t *V_in, *V_out, *V_stop, *L_args, *L_predef;
+
+typedef enum exec { DOIT, DONT } exec_t;
+
+void execute(exec_t how, unsigned indent);
+
+int equal(cell_t *p, cell_t *q)
+/* Two lists are equal if they contain each others elements. */
+{
+	cell_t *t, *m1, *m2;
+
+	t= inc(newcell());
+	t->cdr= inc(newcell());
+	t->cdr->cdr= inc(newcell());
+	t->cdr->car= newcell();
+	t->cdr->car->type= MINUS;
+	t->cdr->car= inc(t->cdr->car);
+
+	/* Compute p - q. */
+	t->car= inc(p);
+	t->cdr->cdr->car= inc(q);
+	m1= evaluate(inc(t), IMPLODE);
+	dec(m1);
+
+	/* Compute q - p. */
+	t->car= q;
+	t->cdr->cdr->car= p;
+	m2= evaluate(t, IMPLODE);
+	dec(m2);
+
+	/* Both results must be empty. */
+	return m1 == nil && m2 == nil;
+}
+
+int wordlist(cell_t **pw, int atom)
+/* Check if p is a list of words, typically an imploded list.  Return
+ * the number of words seen, -1 if they are not words (INPUT/OUTPUT?).
+ * If atom is true than a list of one word is turned into a word.
+ */
+{
+	int n= 0;
+	cell_t *p, **pp= pw;
+
+	while (*pp != nil) {
+		*pp= append(CELL, *pp);
+		p= (*pp)->car;
+		n= n >= 0 && p != nil && p->type == WORD ? n+1 : -1;
+		pp= &(*pp)->cdr;
+	}
+	if (atom && n == 1) *pw= go(*pw, (*pw)->car);
+	return n;
+}
+
+char *template;		/* Current name of a temporary file. */
+static char *tp;	/* Current place withing the tempfile. */
+
+char *maketemp(void)
+/* Return a name that can be used as a temporary filename. */
+{
+	int i= 0;
+
+	if (tp == nil) {
+		size_t len= strlen(template);
+
+		template= allocate(template, (len+20) * sizeof(*template));
+		sprintf(template+len, "/acd%d", getpid());
+		tp= template + strlen(template);
+	}
+
+	for (;;) {
+		switch (tp[i]) {
+		case 0:		tp[i]= 'a';
+				tp[i+1]= 0;	return template;
+		case 'z':	tp[i++]= 'a';	break;
+		default:	tp[i]++;	return template;
+		}
+	}
+}
+
+void inittemp(char *tmpdir)
+/* Initialize the temporary filename generator. */
+{
+	template= allocate(nil, (strlen(tmpdir)+20) * sizeof(*template));
+	sprintf(template, "%s/acd%d", tmpdir, getpid());
+	tp= template + strlen(template);
+
+	/* Create a directory within tempdir that we can safely play in. */
+	while (action != 1 && mkdir(template, 0700) < 0) {
+		if (errno == EEXIST) {
+			(void) maketemp();
+		} else {
+			report(template);
+			action= 0;
+		}
+	}
+	if (verbose >= 2) printf("mkdir %s\n", template);
+	while (*tp != 0) tp++;
+	*tp++= '/';
+	*tp= 0;
+}
+
+void deltemp(void)
+/* Remove our temporary temporaries directory. */
+{
+	while (*--tp != '/') {}
+	*tp = 0;
+	if (rmdir(template) < 0 && errno != ENOENT) report(template);
+	if (verbose >= 2) printf("rmdir %s\n", template);
+	deallocate(template);
+}
+
+cell_t *splitenv(char *env)
+/* Split a string from the environment into several words at whitespace
+ * and colons.  Two colons (::) become a dot.
+ */
+{
+	cell_t *r= nil, **pr= &r;
+	char *p;
+
+	do {
+		while (*env != 0 && isspace(*env)) env++;
+
+		if (*env == 0) break;
+
+		p= env;
+		while (*p != 0 && !isspace(*p) && *p != ':') p++;
+
+		*pr= cons(CELL,
+			p == env ? findword(".") : findnword(env, p-env));
+		pr= &(*pr)->cdr;
+		env= p;
+	} while (*env++ != 0);
+	return r;
+}
+
+void key_usage(char *how)
+{
+	fprintf(stderr, "\"%s\", line %u: Usage: %s %s\n",
+		descr, pc->lineno, pc->line->car->name, how);
+	action= 0;
+}
+
+void inappropriate(void)
+{
+	fprintf(stderr, "\"%s\", line %u: wrong execution phase for '%s'\n",
+		descr, pc->lineno, pc->line->car->name);
+	action= 0;
+}
+
+int readonly(cell_t *v)
+{
+	if (v->flags & W_RDONLY) {
+		fprintf(stderr, "\"%s\", line %u: %s is read-only\n",
+			descr, pc->lineno, v->name);
+		action= 0;
+		return 1;
+	}
+	return 0;
+}
+
+void complain(cell_t *err)
+/* acd: err ... */
+{
+	cell_t *w;
+
+	fprintf(stderr, "%s:", program);
+
+	while (err != nil) {
+		if (err->type == CELL) {
+			w= err->car; err= err->cdr;
+		} else {
+			w= err; err= nil;
+		}
+		fprintf(stderr, " %s", w->name);
+	}
+	action= 0;
+}
+
+int keyword(char *name)
+/* True if the current line is headed by the given keyword. */
+{
+	cell_t *t;
+
+	return (t= pc->line) != nil && t->type == CELL
+		&& (t= t->car) != nil && t->type == WORD
+		&& strcmp(t->name, name) == 0;
+}
+
+cell_t *getvar(cell_t *v)
+/* Return a word or the word referenced by a subst. */
+{
+	if (v == nil) return nil;
+	if (v->type == WORD) return v;
+	if (v->type == SUBST) return v->subst;
+	return nil;
+}
+
+void argscan(void), compile(void);
+void transform(rule_t *);
+
+void exec_one(void)
+/* Execute one line of the program. */
+{
+	cell_t *v, *p, *q, *r, *t;
+	unsigned n= 0;
+	static int last_if= 1;
+
+	/* Description file this line came from. */
+	descr= pc->file->name;
+
+	for (p= pc->line; p != nil; p= p->cdr) n++;
+
+	if (n == 0) return;	/* Null statement. */
+
+	p= pc->line;
+	q= p->cdr;
+	r= q == nil ? nil : q->cdr;
+
+	/* Try one by one all the different commands. */
+
+	if (n >= 2 && q->car != nil && q->car->type == EQUALS) {
+		/* An assignment. */
+		int flags;
+
+		if ((v= getvar(p->car)) == nil) {
+			fprintf(stderr,
+				"\"%s\", line %u: Usage: <var> = expr ...\n",
+				descr, pc->lineno);
+			action= 0;
+			return;
+		}
+
+		if (readonly(v)) return;
+
+		flags= v->flags;
+		v->flags|= W_LOCAL|W_RDONLY;
+		t= evaluate(inc(r), PARTIAL);
+		dec(v->value);
+		v->value= t;
+		v->flags= flags | W_SET;
+		if (talk()) {
+			printf("%s =\b=\b= ", v->name);
+			prin2n(t);
+		}
+	} else
+	if (keyword("unset")) {
+		/* Set a variable to "undefined". */
+
+		if (n != 2 || (v= getvar(q->car)) == nil) {
+			key_usage("<var>");
+			return;
+		}
+		if (readonly(v)) return;
+
+		if (talk()) prin2n(p);
+
+		dec(v->value);
+		v->value= nil;
+		v->flags&= ~W_SET;
+	} else
+	if (keyword("import")) {
+		/* Import a variable from the UNIX environment. */
+		char *env;
+
+		if (n != 2 || (v= getvar(q->car)) == nil) {
+			key_usage("<var>");
+			return;
+		}
+		if (readonly(v)) return;
+
+		if ((env= getenv(v->name)) == nil) return;
+
+		if (talk()) printf("import %s=%s\n", v->name, env);
+
+		t= splitenv(env);
+		dec(v->value);
+		v->value= t;
+		v->flags|= W_SET;
+	} else
+	if (keyword("mktemp")) {
+		/* Assign a variable the name of a temporary file. */
+		char *tmp, *suff;
+
+		r= evaluate(inc(r), IMPLODE);
+		if (n == 3 && wordlist(&r, 1) != 1) n= 0;
+
+		if ((n != 2 && n != 3) || (v= getvar(q->car)) == nil) {
+			dec(r);
+			key_usage("<var> [<suffix>]");
+			return;
+		}
+		if (readonly(v)) { dec(r); return; }
+
+		tmp= maketemp();
+		suff= r == nil ? "" : r->name;
+
+		t= newcell();
+		t->type= WORD;
+		t->name= allocate(nil,
+			(strlen(tmp) + strlen(suff) + 1) * sizeof(*t->name));
+		strcpy(t->name, tmp);
+		strcat(t->name, suff);
+		t= inc(t);
+		dec(r);
+		dec(v->value);
+		v->value= t;
+		v->flags|= W_SET;
+		t->flags|= W_TEMP;
+		if (talk()) printf("mktemp %s=%s\n", v->name, t->name);
+	} else
+	if (keyword("temporary")) {
+		/* Mark a word as a temporary file. */
+		cell_t *tmp;
+
+		tmp= evaluate(inc(q), IMPLODE);
+
+		if (wordlist(&tmp, 1) < 0) {
+			dec(tmp);
+			key_usage("<word>");
+			return;
+		}
+		if (talk()) printf("temporary %s\n", tmp->name);
+
+		tmp->flags|= W_TEMP;
+		dec(tmp);
+	} else
+	if (keyword("stop")) {
+		/* Set the suffix to stop the transformation on. */
+		cell_t *suff;
+
+		if (phase > SCAN) { inappropriate(); return; }
+
+		suff= evaluate(inc(q), IMPLODE);
+
+		if (wordlist(&suff, 1) != 1) {
+			dec(suff);
+			key_usage("<suffix>");
+			return;
+		}
+		dec(V_stop);
+		V_stop= suff;
+		if (talk()) printf("stop %s\n", suff->name);
+	} else
+	if (keyword("numeric")) {
+		/* Check if a string denotes a number, like $n in -O$n. */
+		cell_t *num;
+		char *pn;
+
+		num= evaluate(inc(q), IMPLODE);
+
+		if (wordlist(&num, 1) != 1) {
+			dec(num);
+			key_usage("<arg>");
+			return;
+		}
+		if (talk()) printf("numeric %s\n", num->name);
+
+		(void) strtoul(num->name, &pn, 10);
+		if (*pn != 0) {
+			complain(phase == SCAN ? V_star->value : nil);
+			if (phase == SCAN) fputc(':', stderr);
+			fprintf(stderr, " '%s' is not a number\n", num->name);
+		}
+		dec(num);
+	} else
+	if (keyword("error")) {
+		/* Signal an error. */
+		cell_t *err;
+
+		err= evaluate(inc(q), IMPLODE);
+
+		if (wordlist(&err, 0) < 1) {
+			dec(err);
+			key_usage("expr ...");
+			return;
+		}
+
+		if (talk()) { printf("error "); prin2n(err); }
+
+		complain(err);
+		fputc('\n', stderr);
+		dec(err);
+	} else
+	if (keyword("if")) {
+		/* if (list) = (list) using set comparison. */
+		int eq;
+
+		if (n != 4 || r->car == nil || r->car->type != EQUALS) {
+			key_usage("<expr> = <expr>");
+			execute(DONT, pc->indent+1);
+			last_if= 1;
+			return;
+		}
+		q= q->car;
+		r= r->cdr->car;
+		if (talk()) {
+			printf("if ");
+			prin1(t= evaluate(inc(q), IMPLODE));
+			dec(t);
+			printf(" = ");
+			prin1n(t= evaluate(inc(r), IMPLODE));
+			dec(t);
+		}
+		eq= equal(q, r);
+		execute(eq ? DOIT : DONT, pc->indent+1);
+		last_if= eq;
+	} else
+	if (keyword("ifdef") || keyword("ifndef")) {
+		/* Is a variable defined or undefined? */
+		int doit;
+
+		if (n != 2 || (v= getvar(q->car)) == nil) {
+			key_usage("<var>");
+			execute(DONT, pc->indent+1);
+			last_if= 1;
+			return;
+		}
+		if (talk()) prin2n(p);
+
+		doit= ((v->flags & W_SET) != 0) ^ (p->car->name[2] == 'n');
+		execute(doit ? DOIT : DONT, pc->indent+1);
+		last_if= doit;
+	} else
+	if (keyword("iftemp") || keyword("ifhash")) {
+		/* Is a file a temporary file? */
+		/* Does a file need preprocessing? */
+		cell_t *file;
+		int doit= 0;
+
+		file= evaluate(inc(q), IMPLODE);
+
+		if (wordlist(&file, 1) != 1) {
+			dec(file);
+			key_usage("<arg>");
+			return;
+		}
+		if (talk()) printf("%s %s\n", p->car->name, file->name);
+
+		if (p->car->name[2] == 't') {
+			/* iftemp file */
+			if (file->flags & W_TEMP) doit= 1;
+		} else {
+			/* ifhash file */
+			int fd;
+			char hash;
+
+			if ((fd= open(file->name, O_RDONLY)) >= 0) {
+				if (read(fd, &hash, 1) == 1 && hash == '#')
+					doit= 1;
+				close(fd);
+			}
+		}
+		dec(file);
+
+		execute(doit ? DOIT : DONT, pc->indent+1);
+		last_if= doit;
+	} else
+	if (keyword("else")) {
+		/* Else clause for an if, ifdef, or ifndef. */
+		if (n != 1) {
+			key_usage("");
+			execute(DONT, pc->indent+1);
+			return;
+		}
+		if (talk()) prin2n(p);
+
+		execute(!last_if ? DOIT : DONT, pc->indent+1);
+	} else
+	if (keyword("treat")) {
+		/* Treat a file as having a certain suffix. */
+
+		if (phase > SCAN) { inappropriate(); return; }
+
+		if (n == 3) {
+			q= evaluate(inc(q->car), IMPLODE);
+			r= evaluate(inc(r->car), IMPLODE);
+		}
+		if (n != 3 || wordlist(&q, 1) != 1 || wordlist(&r, 1) != 1) {
+			if (n == 3) { dec(q); dec(r); }
+			key_usage("<file> <suffix>");
+			return;
+		}
+		if (talk()) printf("treat %s %s\n", q->name, r->name);
+
+		dec(q->suffix);
+		q->suffix= r;
+		q->flags|= W_SUFF;
+		dec(q);
+	} else
+	if (keyword("apply")) {
+		/* Apply a transformation rule to the current input file. */
+		rule_t *rule, *sav_path;
+		cell_t *sav_wait, *sav_in, *sav_out;
+		program_t *sav_next;
+
+		if (phase != COMPILE) { inappropriate(); return; }
+
+		if (V_star->value->cdr != nil) {
+			fprintf(stderr, "\"%s\", line %u: $* is not one file\n",
+				descr, pc->lineno);
+			action= 0;
+			return;
+		}
+		if (n == 3) {
+			q= evaluate(inc(q->car), IMPLODE);
+			r= evaluate(inc(r->car), IMPLODE);
+		}
+		if (n != 3 || wordlist(&q, 1) != 1 || wordlist(&r, 1) != 1) {
+			if (n == 3) { dec(q); dec(r); }
+			key_usage("<file> <suffix>");
+			return;
+		}
+		if (talk()) printf("apply %s %s\n", q->name, r->name);
+
+		/* Find a rule */
+		for (rule= rules; rule != nil; rule= rule->next) {
+			if (rule->type == TRANSFORM
+				&& rule->from == q && rule->to == r) break;
+		}
+		if (rule == nil) {
+			fprintf(stderr,
+				"\"%s\", line %u: no %s %s transformation\n",
+				descr, pc->lineno, q->name, r->name);
+			action= 0;
+		}
+		dec(q);
+		dec(r);
+		if (rule == nil) return;
+
+		/* Save the world. */
+		sav_path= rule->path;
+		sav_wait= rule->wait;
+		sav_in= V_in->value;
+		sav_out= V_out->value;
+		sav_next= nextpc;
+
+		/* Isolate the rule and give it new input. */
+		rule->path= rule;
+		rule->wait= V_star->value;
+		V_star->value= nil;
+		V_in->value= nil;
+		V_out->value= nil;
+
+		transform(rule);
+
+		/* Retrieve the new $* and repair. */
+		V_star->value= rule->wait;
+		rule->path= sav_path;
+		rule->wait= sav_wait;
+		V_in->value= sav_in;
+		V_out->value= sav_out;
+		V_out->flags= W_SET|W_LOCAL;
+		nextpc= sav_next;
+	} else
+	if (keyword("include")) {
+		/* Include another description file into this program. */
+		cell_t *file;
+		program_t *incl, *prog, **ppg= &prog;
+
+		file= evaluate(inc(q), IMPLODE);
+
+		if (wordlist(&file, 1) != 1) {
+			dec(file);
+			key_usage("<file>");
+			return;
+		}
+		if (talk()) printf("include %s\n", file->name);
+		descr= file->name;
+		incl= pc;
+		prog= get_prog();
+		dec(file);
+
+		/* Raise the program to the include's indent level. */
+		while (*ppg != nil) {
+			(*ppg)->indent += incl->indent;
+			ppg= &(*ppg)->next;
+		}
+
+		/* Kill the include and splice the included program in. */
+		dec(incl->line);
+		incl->line= nil;
+		*ppg= incl->next;
+		incl->next= prog;
+		pc= incl;
+		nextpc= prog;
+	} else
+	if (keyword("arg")) {
+		/* An argument scanning rule. */
+
+		if (phase > SCAN) { inappropriate(); return; }
+
+		if (n < 2) {
+			key_usage("<string> ...");
+			execute(DONT, pc->indent+1);
+			return;
+		}
+		if (talk()) prin2n(p);
+
+		newrule(ARG, inc(q), nil);
+
+		/* Always skip the body, it comes later. */
+		execute(DONT, pc->indent+1);
+	} else
+	if (keyword("transform")) {
+		/* A file transformation rule. */
+
+		if (phase > SCAN) { inappropriate(); return; }
+
+		if (n == 3) {
+			q= evaluate(inc(q->car), IMPLODE);
+			r= evaluate(inc(r->car), IMPLODE);
+		}
+		if (n != 3 || wordlist(&q, 1) != 1 || wordlist(&r, 1) != 1) {
+			if (n == 3) { dec(q); dec(r); }
+			key_usage("<suffix1> <suffix2>");
+			execute(DONT, pc->indent+1);
+			return;
+		}
+		if (talk()) printf("transform %s %s\n", q->name, r->name);
+
+		newrule(TRANSFORM, q, r);
+
+		/* Body comes later. */
+		execute(DONT, pc->indent+1);
+	} else
+	if (keyword("prefer")) {
+		/* Prefer a transformation over others. */
+
+		if (phase > SCAN) { inappropriate(); return; }
+
+		if (n == 3) {
+			q= evaluate(inc(q->car), IMPLODE);
+			r= evaluate(inc(r->car), IMPLODE);
+		}
+		if (n != 3 || wordlist(&q, 1) != 1 || wordlist(&r, 1) != 1) {
+			if (n == 3) { dec(q); dec(r); }
+			key_usage("<suffix1> <suffix2>");
+			return;
+		}
+		if (talk()) printf("prefer %s %s\n", q->name, r->name);
+
+		newrule(PREFER, q, r);
+	} else
+	if (keyword("combine")) {
+		/* A file combination (loader) rule. */
+
+		if (phase > SCAN) { inappropriate(); return; }
+
+		if (n == 3) {
+			q= evaluate(inc(q->car), IMPLODE);
+			r= evaluate(inc(r->car), IMPLODE);
+		}
+		if (n != 3 || wordlist(&q, 0) < 1 || wordlist(&r, 1) != 1) {
+			if (n == 3) { dec(q); dec(r); }
+			key_usage("<suffix-list> <suffix>");
+			execute(DONT, pc->indent+1);
+			return;
+		}
+		if (talk()) {
+			printf("combine ");
+			prin1(q);
+			printf(" %s\n", r->name);
+		}
+
+		newrule(COMBINE, q, r);
+
+		/* Body comes later. */
+		execute(DONT, pc->indent+1);
+	} else
+	if (keyword("scan") || keyword("compile")) {
+		program_t *next= nextpc;
+
+		if (n != 1) { key_usage(""); return; }
+		if (phase != INIT) { inappropriate(); return; }
+
+		if (talk()) prin2n(p);
+
+		argscan();
+		if (p->car->name[0] == 'c') compile();
+		nextpc= next;
+	} else {
+		/* A UNIX command. */
+		t= evaluate(inc(pc->line), IMPLODE);
+		unix_exec(t);
+		dec(t);
+	}
+}
+
+void execute(exec_t how, unsigned indent)
+/* Execute (or skip) all lines with at least the given indent. */
+{
+	int work= 0;	/* Need to execute at least one line. */
+	unsigned firstline;
+	unsigned nice_indent= 0;	/* 0 = Don't know what's nice yet. */
+
+	if (pc == nil) return;	/* End of program. */
+
+	firstline= pc->lineno;
+
+	if (how == DONT) {
+		/* Skipping a body, but is there another guard? */
+		pc= pc->next;
+		if (pc != nil && pc->indent < indent && pc->line != nil) {
+			/* There is one!  Bail out, then it get's executed. */
+			return;
+		}
+	} else {
+		/* Skip lines with a lesser indentation, they are guards for
+		 * the same substatements.  Don't go past empty lines.
+		 */
+		while (pc != nil && pc->indent < indent && pc->line != nil)
+			pc= pc->next;
+	}
+
+	/* Execute all lines with an indentation of at least "indent". */
+	while (pc != nil && pc->indent >= indent) {
+		if (pc->indent != nice_indent && how == DOIT) {
+			if (nice_indent != 0) {
+				fprintf(stderr,
+			"\"%s\", line %u: (warning) sudden indentation shift\n",
+					descr, pc->lineno);
+			}
+			nice_indent= pc->indent;
+		}
+		nextpc= pc->next;
+		if (how == DOIT) exec_one();
+		pc= nextpc;
+		work= 1;
+	}
+
+	if (indent > 0 && !work) {
+		fprintf(stderr, "\"%s\", line %u: empty body, no statements\n",
+			descr, firstline);
+		action= 0;
+	}
+}
+
+int argmatch(int shift, cell_t *match, cell_t *match1, char *arg1)
+/* Try to match an arg rule to the input file list L_args.  Execute the arg
+ * body (pc is set to it) on success.
+ */
+{
+	cell_t *oldval, *v;
+	int m, oldflags;
+	size_t i, len;
+	int minus= 0;
+
+	if (shift) {
+		/* An argument has been accepted and may be shifted to $*. */
+		cell_t **oldpstar= pV_star;
+		*pV_star= L_args;
+		L_args= *(pV_star= &L_args->cdr);
+		*pV_star= nil;
+
+		if (argmatch(0, match->cdr, nil, nil)) return 1;
+
+		/* Undo the damage. */
+		*pV_star= L_args;
+		L_args= *(pV_star= oldpstar);
+		*pV_star= nil;
+		return 0;
+	}
+
+	if (match == nil) {
+		/* A full match, execute the arg body. */
+
+		/* Enable $>. */
+		V_out->flags= W_SET|W_LOCAL;
+
+		if (verbose >= 3) {
+			prin2(pc->line);
+			printf(" =\b=\b= ");
+			prin2n(V_star->value);
+		}
+		execute(DOIT, pc->indent+1);
+
+		/* Append $> to the file list. */
+		if (V_out->value != nil) {
+			*pL_files= cons(CELL, V_out->value);
+			pL_files= &(*pL_files)->cdr;
+		}
+
+		/* Disable $>. */
+		V_out->value= nil;
+		V_out->flags= W_SET|W_LOCAL|W_RDONLY;
+
+		return 1;
+	}
+
+	if (L_args == nil) return 0;	/* Out of arguments to match. */
+
+	/* Match is a list of words, substs and strings containing letters and
+	 * substs.  Match1 is the current element of the first element of match.
+	 * Arg1 is the current character of the first element of L_args.
+	 */
+	if (match1 == nil) {
+		/* match1 is at the end of a string, then arg1 must also. */
+		if (arg1 != nil) {
+			if (*arg1 != 0) return 0;
+			return argmatch(1, match, nil, nil);
+		}
+		/* If both are nil: Initialize. */
+		match1= match->car;
+		arg1= L_args->car->name;
+
+		/* A subst may not match a leading '-'. */
+		if (arg1[0] == '-') minus= 1;
+	}
+
+	if (match1->type == WORD && strcmp(match1->name, arg1) == 0) {
+		/* A simple match of an argument. */
+
+		return argmatch(1, match, nil, nil);
+	}
+
+	if (match1->type == SUBST && !minus) {
+		/* A simple match of a subst. */
+
+		/* The variable gets the first of the arguments as its value. */
+		v= match1->subst;
+		if (v->flags & W_RDONLY) return 0;	/* ouch */
+		oldflags= v->flags;
+		v->flags= W_SET|W_LOCAL|W_RDONLY;
+		oldval= v->value;
+		v->value= inc(L_args->car);
+
+		m= argmatch(1, match, nil, nil);
+
+		/* Recover the value of the variable. */
+		dec(v->value);
+		v->flags= oldflags;
+		v->value= oldval;
+		return m;
+	}
+	if (match1->type != STRING) return 0;
+
+	/* Match the first item in the string. */
+	if (match1->car == nil) return 0;
+
+	if (match1->car->type == LETTER
+			&& match1->car->letter == (unsigned char) *arg1) {
+		/* A letter matches, try the rest of the string. */
+
+		return argmatch(0, match, match1->cdr, arg1+1);
+	}
+
+	/* It can only be a subst in a string now. */
+	len= strlen(arg1);
+	if (match1->car->type != SUBST || minus || len == 0) return 0;
+
+	/* The variable can match from 1 character to all of the argument.
+	 * Matching as few characters as possible happens to be the Right Thing.
+	 */
+	v= match1->car->subst;
+	if (v->flags & W_RDONLY) return 0;	/* ouch */
+	oldflags= v->flags;
+	v->flags= W_SET|W_LOCAL|W_RDONLY;
+	oldval= v->value;
+
+	m= 0;
+	for (i= match1->cdr == nil ? len : 1; !m && i <= len; i++) {
+		v->value= findnword(arg1, i);
+
+		m= argmatch(0, match, match1->cdr, arg1+i);
+
+		dec(v->value);
+	}
+	/* Recover the value of the variable. */
+	v->flags= oldflags;
+	v->value= oldval;
+	return m;
+}
+
+void argscan(void)
+/* Match all the arguments to the arg rules, those that don't match are
+ * used as files for transformation.
+ */
+{
+	rule_t *rule;
+	int m;
+
+	phase= SCAN;
+
+	/* Process all the arguments. */
+	while (L_args != nil) {
+		pV_star= &V_star->value;
+
+		/* Try all the arg rules. */
+		m= 0;
+		for (rule= rules; !m && rule != nil; rule= rule->next) {
+			if (rule->type != ARG) continue;
+
+			pc= rule->prog;
+
+			m= argmatch(0, rule->match, nil, nil);
+		}
+		dec(V_star->value);
+		V_star->value= nil;
+
+		/* On failure, add the first argument to the list of files. */
+		if (!m) {
+			*pL_files= L_args;
+			L_args= *(pL_files= &L_args->cdr);
+			*pL_files= nil;
+		}
+	}
+	phase= INIT;
+}
+
+int member(cell_t *p, cell_t *l)
+/* True if p is a member of list l. */
+{
+	while (l != nil && l->type == CELL) {
+		if (p == l->car) return 1;
+		l= l->cdr;
+	}
+	return p == l;
+}
+
+long basefind(cell_t *f, cell_t *l)
+/* See if f has a suffix in list l + set the base name of f.
+ * -1 if not found, preference number for a short basename otherwise. */
+{
+	cell_t *suff;
+	size_t blen, slen;
+	char *base;
+
+	/* Determine base name of f, with suffix. */
+	if ((base= strrchr(f->name, '/')) == nil) base= f->name; else base++;
+	blen= strlen(base);
+
+	/* Try suffixes. */
+	while (l != nil) {
+		if (l->type == CELL) {
+			suff= l->car; l= l->cdr;
+		} else {
+			suff= l; l= nil;
+		}
+		if (f->flags & W_SUFF) {
+			/* F has a suffix imposed on it. */
+			if (f->suffix == suff) return 0;
+			continue;
+		}
+		slen= strlen(suff->name);
+		if (slen < blen && strcmp(base+blen-slen, suff->name) == 0) {
+			/* Got it! */
+			dec(f->base);
+			f->base= findnword(base, blen-slen);
+			return 10000L * (blen - slen);
+		}
+	}
+	return -1;
+}
+
+#define NO_PATH		2000000000	/* No path found yet. */
+
+long shortest;		/* Length of the shortest path as yet. */
+
+rule_t *findpath(long depth, int seek, cell_t *file, rule_t *start)
+/* Find the path of the shortest transformation to the stop suffix. */
+{
+	rule_t *rule;
+
+	if (action == 0) return nil;
+
+	if (start == nil) {
+		/* No starting point defined, find one using "file". */
+
+		for (rule= rules; rule != nil; rule= rule->next) {
+			if (rule->type < TRANSFORM) continue;
+
+			if ((depth= basefind(file, rule->from)) >= 0) {
+				if (findpath(depth, seek, nil, rule) != nil)
+					return rule;
+			}
+		}
+		return nil;
+	}
+
+	/* Cycle? */
+	if (start->path != nil) {
+		/* We can't have cycles through combines. */
+		if (start->type == COMBINE) {
+			fprintf(stderr,
+				"\"%s\": contains a combine-combine cycle\n",
+				descr);
+			action= 0;
+		}
+		return nil;
+	}
+
+	/* Preferred transformations are cheap. */
+	if (start->flags & R_PREFER) depth-= 100;
+
+	/* Try to go from start closer to the stop suffix. */
+	for (rule= rules; rule != nil; rule= rule->next) {
+		if (rule->type < TRANSFORM) continue;
+
+		if (member(start->to, rule->from)) {
+			start->path= rule;
+			rule->npaths++;
+			if (findpath(depth+1, seek, nil, rule) != nil)
+				return start;
+			start->path= nil;
+			rule->npaths--;
+		}
+	}
+
+	if (V_stop == nil) {
+		fprintf(stderr, "\"%s\": no stop suffix has been defined\n",
+			descr);
+		action= 0;
+		return nil;
+	}
+
+	/* End of the line? */
+	if (start->to == V_stop) {
+		/* Got it. */
+		if (seek) {
+			/* Second hunt, do we find the shortest? */
+			if (depth == shortest) return start;
+		} else {
+			/* Is this path shorter than the last one? */
+			if (depth < shortest) shortest= depth;
+		}
+	}
+	return nil;	/* Fail. */
+}
+
+void transform(rule_t *rule)
+/* Transform the file(s) connected to the rule according to the rule. */
+{
+	cell_t *file, *in, *out;
+	char *base;
+
+	/* Let $* be the list of input files. */
+	while (rule->wait != nil) {
+		file= rule->wait;
+		rule->wait= file->cdr;
+		file->cdr= V_star->value;
+		V_star->value= file;
+	}
+
+	/* Set $< to the basename of the first input file. */
+	file= file->car;
+	V_in->value= in= inc(file->flags & W_SUFF ? file : file->base);
+	file->flags&= ~W_SUFF;
+
+	/* Set $> to the output file name of the transformation. */
+	out= newcell();
+	out->type= WORD;
+	base= rule->path == nil ? in->name : maketemp();
+	out->name= allocate(nil,
+		(strlen(base)+strlen(rule->to->name)+1) * sizeof(*out->name));
+	strcpy(out->name, base);
+	if (rule->path == nil || strchr(rule->to->name, '/') == nil)
+		strcat(out->name, rule->to->name);
+	out= inc(out);
+	if (rule->path != nil) out->flags|= W_TEMP;
+
+	V_out->value= out;
+	V_out->flags= W_SET|W_LOCAL;
+
+	/* Do a transformation.  (Finally) */
+	if (verbose >= 3) {
+		printf("%s ", rule->type==TRANSFORM ? "transform" : "combine");
+		prin2(V_star->value);
+		printf(" %s\n", out->name);
+	}
+	pc= rule->prog;
+	execute(DOIT, pc->indent+1);
+
+	/* Hand $> over to the next rule, it must be a single word. */
+	out= evaluate(V_out->value, IMPLODE);
+	if (wordlist(&out, 1) != 1) {
+		fprintf(stderr,
+		"\"%s\", line %u: $> should be returned as a single word\n",
+			descr, rule->prog->lineno);
+		action= 0;
+	}
+
+	if ((rule= rule->path) != nil) {
+		/* There is a next rule. */
+		dec(out->base);
+		out->base= in;		/* Basename of input file. */
+		file= inc(newcell());
+		file->car= out;
+		file->cdr= rule->wait;
+		rule->wait= file;
+	} else {
+		dec(in);
+		dec(out);
+	}
+
+	/* Undo the damage to $*, $<, and $>. */
+	dec(V_star->value);
+	V_star->value= nil;
+	V_in->value= nil;
+	V_out->value= nil;
+	V_out->flags= W_SET|W_LOCAL|W_RDONLY;
+}
+
+void compile(void)
+{
+	rule_t *rule;
+	cell_t *file, *t;
+
+	phase= COMPILE;
+
+	/* Implode the files list. */
+	L_files= evaluate(L_files, IMPLODE);
+	if (wordlist(&L_files, 0) < 0) {
+		fprintf(stderr, "\"%s\": An assignment to $> contained junk\n",
+			descr);
+		action= 0;
+	}
+
+	while (action != 0 && L_files != nil) {
+		file= L_files->car;
+
+		/* Initialize. */
+		shortest= NO_PATH;
+		for (rule= rules; rule != nil; rule= rule->next)
+			rule->path= nil;
+
+		/* Try all possible transformation paths. */
+		(void) findpath(0L, 0, file, nil);
+
+		if (shortest == NO_PATH) {	/* Can't match the file. */
+			fprintf(stderr,
+			"%s: %s: can't compile, no transformation applies\n",
+				program, file->name);
+			action= 0;
+			return;
+		}
+
+		/* Find the first short path. */
+		if ((rule= findpath(0L, 1, file, nil)) == nil) return;
+
+		/* Transform the file until you hit a combine. */
+		t= inc(newcell());
+		t->car= inc(file);
+		L_files= go(L_files, L_files->cdr);
+		t->cdr= rule->wait;
+		rule->wait= t;
+		while (action != 0 && rule != nil && rule->type != COMBINE) {
+			transform(rule);
+			rule= rule->path;
+		}
+	}
+
+	/* All input files have been transformed to combine rule(s).  Now
+	 * we need to find the combine rule with the least number of paths
+	 * running through it (this combine may be followed by another) and
+	 * transform from there.
+	 */
+	while (action != 0) {
+		int least;
+		rule_t *comb= nil;
+
+		for (rule= rules; rule != nil; rule= rule->next) {
+			rule->path= nil;
+
+			if (rule->type != COMBINE || rule->wait == nil)
+				continue;
+
+			if (comb == nil || rule->npaths < least) {
+				least= rule->npaths;
+				comb= rule;
+			}
+		}
+
+		/* No combine?  Then we're done. */
+		if (comb == nil) break;
+
+		/* Initialize. */
+		shortest= NO_PATH;
+
+		/* Try all possible transformation paths. */
+		(void) findpath(0L, 0, nil, comb);
+
+		if (shortest == NO_PATH) break;
+
+		/* Find the first short path. */
+		if ((rule= findpath(0L, 1, nil, comb)) == nil) return;
+
+		/* Transform until you hit another combine. */
+		do {
+			transform(rule);
+			rule= rule->path;
+		} while (action != 0 && rule != nil && rule->type != COMBINE);
+	}
+	phase= INIT;
+}
+
+cell_t *predef(char *var, char *val)
+/* A predefined variable var with value val, or a special variable. */
+{
+	cell_t *p, *t;
+
+	p= findword(var);
+	if (val != nil) {	/* Predefined. */
+		t= findword(val);
+		dec(p->value);
+		p->value= t;
+		p->flags|= W_SET;
+		if (verbose >= 3) {
+			prin1(p);
+			printf(" =\b=\b= ");
+			prin2n(t);
+		}
+	} else {		/* Special: $* and such. */
+		p->flags= W_SET|W_LOCAL|W_RDONLY;
+	}
+	t= inc(newcell());
+	t->car= p;
+	t->cdr= L_predef;
+	L_predef= t;
+	return p;
+}
+
+void usage(void)
+{
+	fprintf(stderr,
+	"Usage: %s -v<n> -vn<n> -name <name> -descr <descr> -T <dir> ...\n",
+		program);
+	exit(-1);
+}
+
+int main(int argc, char **argv)
+{
+	char *tmpdir;
+	program_t *prog;
+	cell_t **pa;
+	int i;
+
+	/* Call name of the program, decides which description to use. */
+	if ((program= strrchr(argv[0], '/')) == nil)
+		program= argv[0];
+	else
+		program++;
+
+	/* Directory for temporary files. */
+	if ((tmpdir= getenv("TMPDIR")) == nil || *tmpdir == 0)
+		tmpdir= "/tmp";
+
+	/* Transform arguments to a list, processing the few ACD options. */
+	pa= &L_args;
+	for (i= 1; i < argc; i++) {
+		if (argv[i][0] == '-' && argv[i][1] == 'v') {
+			char *a= argv[i]+2;
+
+			if (*a == 'n') { a++; action= 1; }
+			verbose= 2;
+
+			if (*a != 0) {
+				verbose= strtoul(a, &a, 10);
+				if (*a != 0) usage();
+			}
+		} else
+		if (strcmp(argv[i], "-name") == 0) {
+			if (++i == argc) usage();
+			program= argv[i];
+		} else
+		if (strcmp(argv[i], "-descr") == 0) {
+			if (++i == argc) usage();
+			descr= argv[i];
+		} else
+		if (argv[i][0] == '-' && argv[i][1] == 'T') {
+			if (argv[i][2] == 0) {
+				if (++i == argc) usage();
+				tmpdir= argv[i];
+			} else
+				tmpdir= argv[i]+2;
+		} else {
+			/* Any other argument must be processed. */
+			*pa= cons(CELL, findword(argv[i]));
+			pa= &(*pa)->cdr;
+		}
+	}
+#ifndef DESCR
+	/* Default description file is based on the program name. */
+	if (descr == nil) descr= program;
+#else
+	/* Default description file is predefined. */
+	if (descr == nil) descr= DESCR;
+#endif
+
+	inittemp(tmpdir);
+
+	/* Catch user signals. */
+	if (signal(SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, interrupt);
+	if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, interrupt);
+	if (signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, interrupt);
+
+	/* Predefined or special variables. */
+	predef("PROGRAM", program);
+	predef("VERSION", version);
+#ifdef ARCH
+	predef("ARCH", ARCH);		/* Cross-compilers like this. */
+#endif
+	V_star= predef("*", nil);
+	V_in= predef("<", nil);
+	V_out= predef(">", nil);
+
+	/* Read the description file. */
+	if (verbose >= 3) printf("include %s\n", descr);
+	prog= get_prog();
+
+	phase= INIT;
+	pc= prog;
+	execute(DOIT, 0);
+
+	argscan();
+	compile();
+
+	/* Delete all allocated data to test inc/dec balance. */
+	while (prog != nil) {
+		program_t *junk= prog;
+		prog= junk->next;
+		dec(junk->file);
+		dec(junk->line);
+		deallocate(junk);
+	}
+	while (rules != nil) {
+		rule_t *junk= rules;
+		rules= junk->next;
+		dec(junk->from);
+		dec(junk->to);
+		dec(junk->wait);
+		deallocate(junk);
+	}
+	deltemp();
+	dec(V_stop);
+	dec(L_args);
+	dec(L_files);
+	dec(L_predef);
+
+	quit(action == 0 ? 1 : 0);
+}
Index: /trunk/minix/commands/i386/asmconv/Makefile
===================================================================
--- /trunk/minix/commands/i386/asmconv/Makefile	(revision 9)
+++ /trunk/minix/commands/i386/asmconv/Makefile	(revision 9)
@@ -0,0 +1,32 @@
+# Makefile for asmconv.
+
+CFLAGS=		$(OPT)
+LDFLAGS=	-i
+CC = exec cc
+
+all:	asmconv
+
+OBJ=	asm86.o asmconv.o parse_ack.o parse_gnu.o parse_bas.o \
+	tokenize.o emit_ack.o emit_gnu.o
+
+asmconv:	$(OBJ)
+	$(CC) $(LDFLAGS) -o $@ $(OBJ)
+	install -S 8kw $@
+
+install:	/usr/lib/asmconv
+
+/usr/lib/asmconv:	asmconv
+	install -cs -o bin asmconv $@
+
+clean:
+	rm -f $(OBJ) asmconv core
+
+# Dependencies.
+asm86.o:	asm86.h asmconv.h token.h
+asmconv.o:	asmconv.h languages.h asm86.h
+parse_ack.o:	asmconv.h languages.h token.h asm86.h
+parse_gnu.o:	asmconv.h languages.h token.h asm86.h
+parse_bas.o:	asmconv.h languages.h token.h asm86.h
+tokenize.o:	asmconv.h token.h
+emit_ack.o:	asmconv.h languages.h token.h asm86.h
+emit_gnu.o:	asmconv.h languages.h token.h asm86.h
Index: /trunk/minix/commands/i386/asmconv/asm86.c
===================================================================
--- /trunk/minix/commands/i386/asmconv/asm86.c	(revision 9)
+++ /trunk/minix/commands/i386/asmconv/asm86.c	(revision 9)
@@ -0,0 +1,85 @@
+/*	asm86.c - 80X86 assembly intermediate		Author: Kees J. Bot
+ *								24 Dec 1993
+ */
+#define nil 0
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+#include "asm86.h"
+#include "asmconv.h"
+#include "token.h"
+
+expression_t *new_expr(void)
+/* Make a new cell to build an expression. */
+{
+	expression_t *e;
+
+	e= allocate(nil, sizeof(*e));
+	e->operator= -1;
+	e->left= e->middle= e->right= nil;
+	e->name= nil;
+	e->magic= 31624;
+	return e;
+}
+
+void del_expr(expression_t *e)
+/* Delete an expression tree. */
+{
+	if (e != nil) {
+		assert(e->magic == 31624);
+		e->magic= 0;
+		deallocate(e->name);
+		del_expr(e->left);
+		del_expr(e->middle);
+		del_expr(e->right);
+		deallocate(e);
+	}
+}
+
+asm86_t *new_asm86(void)
+/* Make a new cell to hold an 80X86 instruction. */
+{
+	asm86_t *a;
+
+	a= allocate(nil, sizeof(*a));
+	a->opcode= -1;
+	get_file(&a->file, &a->line);
+	a->optype= -1;
+	a->oaz= 0;
+	a->rep= ONCE;
+	a->seg= DEFSEG;
+	a->args= nil;
+	a->magic= 37937;
+	return a;
+}
+
+void del_asm86(asm86_t *a)
+/* Delete an 80X86 instruction. */
+{
+	assert(a != nil);
+	assert(a->magic == 37937);
+	a->magic= 0;
+	del_expr(a->args);
+	deallocate(a);
+}
+
+int isregister(const char *name)
+/* True if the string is a register name.  Return its size. */
+{
+	static char *regs[] = {
+		"al", "bl", "cl", "dl", "ah", "bh", "ch", "dh",
+		"ax", "bx", "cx", "dx", "si", "di", "bp", "sp",
+		"cs", "ds", "es", "fs", "gs", "ss",
+		"eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp",
+		"cr0", "cr1", "cr2", "cr3",
+		"st",
+	};
+	int reg;
+
+	for (reg= 0; reg < arraysize(regs); reg++) {
+		if (strcmp(name, regs[reg]) == 0) {
+			return reg < 8 ? 1 : reg < 22 ? 2 : 4;
+		}
+	}
+	return 0;
+}
Index: /trunk/minix/commands/i386/asmconv/asm86.h
===================================================================
--- /trunk/minix/commands/i386/asmconv/asm86.h	(revision 9)
+++ /trunk/minix/commands/i386/asmconv/asm86.h	(revision 9)
@@ -0,0 +1,250 @@
+/*	asm86.h - 80X86 assembly intermediate		Author: Kees J. Bot
+ *								27 Jun 1993
+ */
+
+typedef enum opcode {	/* 80486 opcodes, from the i486 reference manual.
+			 * Synonyms left out, some new words invented.
+			 */
+	DOT_ALIGN,
+	DOT_ASCII,	DOT_ASCIZ,
+	DOT_ASSERT,			/* Pseudo's invented */
+	DOT_BASE,
+	DOT_COMM,	DOT_LCOMM,
+	DOT_DATA1,
+	DOT_DATA2,
+	DOT_DATA4,
+	DOT_DEFINE,	DOT_EXTERN,
+	DOT_EQU,
+	DOT_FILE,	DOT_LINE,
+	DOT_LABEL,
+	DOT_LIST,	DOT_NOLIST,
+	DOT_SPACE,
+	DOT_SYMB,
+	DOT_TEXT,	DOT_ROM,	DOT_DATA,	DOT_BSS,	DOT_END,
+	DOT_USE16,	DOT_USE32,
+	AAA,
+	AAD,
+	AAM,
+	AAS,
+	ADC,
+	ADD,
+	AND,
+	ARPL,
+	BOUND,
+	BSF,
+	BSR,
+	BSWAP,
+	BT,
+	BTC,
+	BTR,
+	BTS,
+	CALL,	CALLF,			/* CALLF added */
+	CBW,
+	CLC,
+	CLD,
+	CLI,
+	CLTS,
+	CMC,
+	CMP,
+	CMPS,
+	CMPXCHG,
+	CWD,
+	DAA,
+	DAS,
+	DEC,
+	DIV,
+	ENTER,
+	F2XM1,
+	FABS,
+	FADD,	FADDD,	FADDS,	FADDP,	FIADDL,	FIADDS,
+	FBLD,
+	FBSTP,
+	FCHS,
+	FCLEX,
+	FCOMD,	FCOMS,	FCOMPD,	FCOMPS,	FCOMPP,
+	FCOS,
+	FDECSTP,
+	FDIVD,	FDIVS,	FDIVP,	FIDIVL,	FIDIVS,
+	FDIVRD,	FDIVRS,	FDIVRP,	FIDIVRL,	FIDIVRS,
+	FFREE,
+	FICOM,	FICOMP,
+	FILDQ,	FILDL,	FILDS,
+	FINCSTP,
+	FINIT,
+	FISTL,	FISTS,	FISTP,
+	FLDX,	FLDD,	FLDS,
+	FLD1,	FLDL2T,	FLDL2E,	FLDPI,	FLDLG2,	FLDLN2,	FLDZ,
+	FLDCW,
+	FLDENV,
+	FMULD,	FMULS,	FMULP,	FIMULL,	FIMULS,
+	FNOP,
+	FPATAN,
+	FPREM,
+	FPREM1,
+	FPTAN,
+	FRNDINT,
+	FRSTOR,
+	FSAVE,
+	FSCALE,
+	FSIN,
+	FSINCOS,
+	FSQRT,
+	FSTD,	FSTS,	FSTPX,	FSTPD,	FSTPS,
+	FSTCW,
+	FSTENV,
+	FSTSW,
+	FSUBD,	FSUBS,	FSUBP,	FISUBL,	FISUBS,
+	FSUBRD,	FSUBRS,	FSUBPR,	FISUBRL, FISUBRS,
+	FTST,
+	FUCOM,	FUCOMP,	FUCOMPP,
+	FXAM,
+	FXCH,
+	FXTRACT,
+	FYL2X,
+	FYL2XP1,
+	HLT,
+	IDIV,
+	IMUL,
+	IN,
+	INC,
+	INS,
+	INT,	INTO,
+	INVD,
+	INVLPG,
+	IRET,	IRETD,
+	JA,	JAE,	JB,	JBE,	JCXZ,	JE,	JG,	JGE,	JL,
+	JLE,	JNE,	JNO,	JNP,	JNS,	JO,	JP,	JS,
+	JMP,	JMPF,			/* JMPF added */
+	LAHF,
+	LAR,
+	LEA,
+	LEAVE,
+	LGDT,	LIDT,
+	LGS,	LSS,	LDS,	LES,	LFS,
+	LLDT,
+	LMSW,
+	LOCK,
+	LODS,
+	LOOP,	LOOPE,	LOOPNE,
+	LSL,
+	LTR,
+	MOV,
+	MOVS,
+	MOVSX,
+	MOVSXB,
+	MOVZX,
+	MOVZXB,
+	MUL,
+	NEG,
+	NOP,
+	NOT,
+	OR,
+	OUT,
+	OUTS,
+	POP,
+	POPA,
+	POPF,
+	PUSH,
+	PUSHA,
+	PUSHF,
+	RCL,	RCR,	ROL,	ROR,
+	RET,	RETF,			/* RETF added */
+	SAHF,
+	SAL,	SAR,	SHL,	SHR,
+	SBB,
+	SCAS,
+	SETA,	SETAE,	SETB,	SETBE,	SETE,	SETG,	SETGE,	SETL,
+	SETLE,	SETNE,	SETNO,	SETNP,	SETNS,	SETO,	SETP,	SETS,
+	SGDT,	SIDT,
+	SHLD,
+	SHRD,
+	SLDT,
+	SMSW,
+	STC,
+	STD,
+	STI,
+	STOS,
+	STR,
+	SUB,
+	TEST,
+	VERR,	VERW,
+	WAIT,
+	WBINVD,
+	XADD,
+	XCHG,
+	XLAT,
+	XOR
+} opcode_t;
+
+#define is_pseudo(o)	((o) <= DOT_USE32)
+#define N_OPCODES	((int) XOR + 1)
+
+#define OPZ	0x01		/* Operand size prefix. */
+#define ADZ	0x02		/* Address size prefix. */
+
+typedef enum optype {
+	PSEUDO,	JUMP,	BYTE,	WORD,	OWORD		/* Ordered list! */
+} optype_t;
+
+typedef enum repeat {
+	ONCE,	REP,	REPE,	REPNE
+} repeat_t;
+
+typedef enum segment {
+	DEFSEG,	CSEG,	DSEG,	ESEG,	FSEG,	GSEG,	SSEG
+} segment_t;
+
+typedef struct expression {
+	int		operator;
+	struct expression *left, *middle, *right;
+	char		*name;
+	size_t		len;
+	unsigned	magic;
+} expression_t;
+
+typedef struct asm86 {
+	opcode_t	opcode;		/* DOT_TEXT, MOV, ... */
+	char		*file;		/* Name of the file it is found in. */
+	long		line;		/* Line number. */
+	optype_t	optype;		/* Type of operands: byte, word... */
+	int		oaz;		/* Operand/address size prefix? */
+	repeat_t	rep;		/* Repeat prefix used on this instr. */
+	segment_t	seg;		/* Segment override. */
+	expression_t	*args;		/* Arguments in ACK order. */
+	unsigned	magic;
+} asm86_t;
+
+expression_t *new_expr(void);
+void del_expr(expression_t *a);
+asm86_t *new_asm86(void);
+void del_asm86(asm86_t *a);
+int isregister(const char *name);
+
+/*
+ * Format of the arguments of the asm86_t structure:
+ *
+ *
+ * ACK assembly operands	expression_t cell:
+ * or part of operand:		{operator, left, middle, right, name, len}
+ *
+ * [expr]			{'[', nil, expr, nil}
+ * word				{'W', nil, nil, nil, word}
+ * "string"			{'S', nil, nil, nil, "string", strlen("string")}
+ * label = expr			{'=', nil, expr, nil, label}
+ * expr * expr			{'*', expr, nil, expr}
+ * - expr			{'-', nil, expr, nil}
+ * (memory)			{'(', nil, memory, nil}
+ * offset(base)(index*n)	{'O', offset, base, index*n}
+ * base				{'B', nil, nil, nil, base}
+ * index*4			{'4', nil, nil, nil, index}
+ * operand, oplist		{',', operand, nil, oplist}
+ * label :			{':', nil, nil, nil, label}
+ *
+ * The precedence of operators is ignored.  The expression is simply copied
+ * as is, including parentheses.  Problems like missing operators in the
+ * target language will have to be handled by rewriting the source language.
+ * 16-bit or 32-bit registers must be used where they are required by the
+ * target assembler even though ACK makes no difference between 'ax' and
+ * 'eax'.  Asmconv is smart enough to transform compiler output.  Human made
+ * assembly can be fixed up to be transformable.
+ */
Index: /trunk/minix/commands/i386/asmconv/asmconv.c
===================================================================
--- /trunk/minix/commands/i386/asmconv/asmconv.c	(revision 9)
+++ /trunk/minix/commands/i386/asmconv/asmconv.c	(revision 9)
@@ -0,0 +1,157 @@
+/*	asmconv 1.11 - convert 80X86 assembly		Author: Kees J. Bot
+ *								24 Dec 1993
+ */
+static char version[] = "1.11";
+
+#define nil 0
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include "asmconv.h"
+#include "asm86.h"
+#include "languages.h"
+
+void fatal(char *label)
+{
+	fprintf(stderr, "asmconv: %s: %s\n", label, strerror(errno));
+	exit(EXIT_FAILURE);
+}
+
+void *allocate(void *mem, size_t size)
+/* A checked malloc/realloc().  Yes, I know ISO C allows realloc(NULL, size). */
+{
+	mem= mem == nil ? malloc(size) : realloc(mem, size);
+	if (mem == nil) fatal("malloc()");
+	return mem;
+}
+
+void deallocate(void *mem)
+/* Free a malloc()d cell.  (Yes I know ISO C allows free(NULL) */
+{
+	if (mem != nil) free(mem);
+}
+
+char *copystr(const char *s)
+{
+	char *c;
+
+	c= allocate(nil, (strlen(s) + 1) * sizeof(s[0]));
+	strcpy(c, s);
+	return c;
+}
+
+int isanumber(const char *s)
+/* True if s can be turned into a number. */
+{
+	char *end;
+
+	(void) strtol(s, &end, 0);
+	return end != s && *end == 0;
+}
+
+/* "Invisible" globals. */
+int asm_mode32= (sizeof(int) == 4);
+int err_code= EXIT_SUCCESS;
+
+int main(int argc, char **argv)
+{
+	void (*parse_init)(char *file);
+	asm86_t *(*get_instruction)(void);
+	void (*emit_init)(char *file, const char *banner);
+	void (*emit_instruction)(asm86_t *instr);
+	char *lang_parse, *lang_emit, *input_file, *output_file;
+	asm86_t *instr;
+	char banner[80];
+
+	if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'm') {
+		if (strcmp(argv[1], "-mi86") == 0) {
+			set_use16();
+		} else
+		if (strcmp(argv[1], "-mi386") == 0) {
+			set_use32();
+		} else {
+			fprintf(stderr, "asmconv: '%s': unknown machine\n",
+				argv[1]+2);
+		}
+		argc--;
+		argv++;
+	}
+
+	if (argc < 3 || argc > 5) {
+		fprintf(stderr,
+"Usage: asmconv <input-type> <output-type> [input-file [output-file]]\n");
+		exit(EXIT_FAILURE);
+	}
+
+	lang_parse= argv[1];
+	lang_emit= argv[2];
+	input_file= argc < 4 ? nil : argv[3];
+	output_file= argc < 5 ? nil : argv[4];
+
+	/* Choose the parsing routines. */
+	if (strcmp(lang_parse, "ack") == 0) {
+		/* Standard ACK. */
+		parse_init= ack_parse_init;
+		get_instruction= ack_get_instruction;
+	} else
+	if (strcmp(lang_parse, "ncc") == 0) {
+		/* ACK Xenix assembly, a black sheep among ACK assemblies. */
+		parse_init= ncc_parse_init;
+		get_instruction= ncc_get_instruction;
+	} else
+	if (strcmp(lang_parse, "gnu") == 0) {
+		/* GNU assembly.  Parser by R.S. Veldema. */
+		parse_init= gnu_parse_init;
+		get_instruction= gnu_get_instruction;
+	} else
+	if (strcmp(lang_parse, "bas") == 0) {
+		/* Bruce Evans' assembler. */
+		parse_init= bas_parse_init;
+		get_instruction= bas_get_instruction;
+	} else {
+		fprintf(stderr, "asmconv: '%s': unknown input language\n",
+			lang_parse);
+		exit(EXIT_FAILURE);
+	}
+
+	/* Choose the output language. */
+	if (strcmp(lang_emit, "ack") == 0) {
+		/* Standard ACK. */
+		emit_init= ack_emit_init;
+		emit_instruction= ack_emit_instruction;
+	} else
+	if (strcmp(lang_emit, "ncc") == 0) {
+		/* ACK Xenix assembly, can be read by BAS and the 8086 ACK
+		 * ANSI C compiler.  (Allows us to compile the Boot Monitor.)
+		 */
+		emit_init= ncc_emit_init;
+		emit_instruction= ncc_emit_instruction;
+	} else
+	if (strcmp(lang_emit, "gnu") == 0) {
+		/* GNU assembler.  So we can assemble the ACK stuff among the
+		 * kernel sources and in the library.
+		 */
+		emit_init= gnu_emit_init;
+		emit_instruction= gnu_emit_instruction;
+	} else {
+		fprintf(stderr, "asmconv: '%s': unknown output language\n",
+			lang_emit);
+		exit(EXIT_FAILURE);
+	}
+
+	sprintf(banner, "Translated from %s to %s by asmconv %s",
+					lang_parse, lang_emit, version);
+
+	(*parse_init)(input_file);
+	(*emit_init)(output_file, banner);
+	for (;;) {
+		instr= (*get_instruction)();
+		(*emit_instruction)(instr);
+		if (instr == nil) break;
+		del_asm86(instr);
+	}
+	exit(err_code);
+}
Index: /trunk/minix/commands/i386/asmconv/asmconv.h
===================================================================
--- /trunk/minix/commands/i386/asmconv/asmconv.h	(revision 9)
+++ /trunk/minix/commands/i386/asmconv/asmconv.h	(revision 9)
@@ -0,0 +1,24 @@
+/*	asmconv.h - shared functions			Author: Kees J. Bot
+ *								19 Dec 1993
+ */
+
+#define arraysize(a)	(sizeof(a)/sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+#define between(a, c, z)	\
+			((unsigned)((c) - (a)) <= (unsigned)((z) - (a)))
+
+void *allocate(void *mem, size_t size);
+void deallocate(void *mem);
+void fatal(char *label);
+char *copystr(const char *s);
+int isanumber(const char *s);
+
+extern int asm_mode32;	/* In 32 bit mode if true. */
+
+#define use16()		(!asm_mode32)
+#define use32()		((int) asm_mode32)
+#define set_use16()	((void) (asm_mode32= 0))
+#define set_use32()	((void) (asm_mode32= 1))
+
+extern int err_code;	/* Exit code. */
+#define set_error()	((void) (err_code= EXIT_FAILURE))
Index: /trunk/minix/commands/i386/asmconv/build
===================================================================
--- /trunk/minix/commands/i386/asmconv/build	(revision 9)
+++ /trunk/minix/commands/i386/asmconv/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/i386/asmconv/emit_ack.c
===================================================================
--- /trunk/minix/commands/i386/asmconv/emit_ack.c	(revision 9)
+++ /trunk/minix/commands/i386/asmconv/emit_ack.c	(revision 9)
@@ -0,0 +1,621 @@
+/*	emit_ack.c - emit ACK assembly			Author: Kees J. Bot
+ *		     emit NCC assembly				27 Dec 1993
+ */
+#define nil 0
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+#include "asmconv.h"
+#include "token.h"
+#include "asm86.h"
+#include "languages.h"
+
+typedef struct mnemonic {	/* ACK as86 mnemonics translation table. */
+	opcode_t	opcode;
+	char		*name;
+} mnemonic_t;
+
+static mnemonic_t mnemtab[] = {
+	{ AAA,		"aaa"		},
+	{ AAD,		"aad"		},
+	{ AAM,		"aam"		},
+	{ AAS,		"aas"		},
+	{ ADC,		"adc%"		},
+	{ ADD,		"add%"		},
+	{ AND,		"and%"		},
+	{ ARPL,		"arpl"		},
+	{ BOUND,	"bound"		},
+	{ BSF,		"bsf"		},
+	{ BSR,		"bsr"		},
+	{ BSWAP,	"bswap"		},
+	{ BT,		"bt"		},
+	{ BTC,		"btc"		},
+	{ BTR,		"btr"		},
+	{ BTS,		"bts"		},
+	{ CALL,		"call"		},
+	{ CALLF,	"callf"		},
+	{ CBW,		"cbw"		},
+	{ CLC,		"clc"		},
+	{ CLD,		"cld"		},
+	{ CLI,		"cli"		},
+	{ CLTS,		"clts"		},
+	{ CMC,		"cmc"		},
+	{ CMP,		"cmp%"		},
+	{ CMPS,		"cmps%"		},
+	{ CMPXCHG,	"cmpxchg"	},
+	{ CWD,		"cwd"		},
+	{ DAA,		"daa"		},
+	{ DAS,		"das"		},
+	{ DEC,		"dec%"		},
+	{ DIV,		"div%"		},
+	{ DOT_ALIGN,	".align"	},
+	{ DOT_ASCII,	".ascii"	},
+	{ DOT_ASCIZ,	".asciz"	},
+	{ DOT_ASSERT,	".assert"	},
+	{ DOT_BASE,	".base"		},
+	{ DOT_BSS,	".sect .bss"	},
+	{ DOT_COMM,	".comm"		},
+	{ DOT_DATA,	".sect .data"	},
+	{ DOT_DATA1,	".data1"	},
+	{ DOT_DATA2,	".data2"	},
+	{ DOT_DATA4,	".data4"	},
+	{ DOT_DEFINE,	".define"	},
+	{ DOT_END,	".sect .end"	},
+	{ DOT_EXTERN,	".extern"	},
+	{ DOT_FILE,	".file"		},
+	{ DOT_LCOMM,	".comm"		},
+	{ DOT_LINE,	".line"		},
+	{ DOT_LIST,	".list"		},
+	{ DOT_NOLIST,	".nolist"	},
+	{ DOT_ROM,	".sect .rom"	},
+	{ DOT_SPACE,	".space"	},
+	{ DOT_SYMB,	".symb"		},
+	{ DOT_TEXT,	".sect .text"	},
+	{ DOT_USE16,	".use16"	},
+	{ DOT_USE32,	".use32"	},
+	{ ENTER,	"enter"		},
+	{ F2XM1,	"f2xm1"		},
+	{ FABS,		"fabs"		},
+	{ FADD,		"fadd"		},
+	{ FADDD,	"faddd"		},
+	{ FADDP,	"faddp"		},
+	{ FADDS,	"fadds"		},
+	{ FBLD,		"fbld"		},
+	{ FBSTP,	"fbstp"		},
+	{ FCHS,		"fchs"		},
+	{ FCLEX,	"fclex"		},
+	{ FCOMD,	"fcomd"		},
+	{ FCOMPD,	"fcompd"	},
+	{ FCOMPP,	"fcompp"	},
+	{ FCOMPS,	"fcomps"	},
+	{ FCOMS,	"fcoms"		},
+	{ FCOS,		"fcos"		},
+	{ FDECSTP,	"fdecstp"	},
+	{ FDIVD,	"fdivd"		},
+	{ FDIVP,	"fdivp"		},
+	{ FDIVRD,	"fdivrd"	},
+	{ FDIVRP,	"fdivrp"	},
+	{ FDIVRS,	"fdivrs"	},
+	{ FDIVS,	"fdivs"		},
+	{ FFREE,	"ffree"		},
+	{ FIADDL,	"fiaddl"	},
+	{ FIADDS,	"fiadds"	},
+	{ FICOM,	"ficom"		},
+	{ FICOMP,	"ficomp"	},
+	{ FIDIVL,	"fidivl"	},
+	{ FIDIVRL,	"fidivrl"	},
+	{ FIDIVRS,	"fidivrs"	},
+	{ FIDIVS,	"fidivs"	},
+	{ FILDL,	"fildl"		},
+	{ FILDQ,	"fildq"		},
+	{ FILDS,	"filds"		},
+	{ FIMULL,	"fimull"	},
+	{ FIMULS,	"fimuls"	},
+	{ FINCSTP,	"fincstp"	},
+	{ FINIT,	"finit"		},
+	{ FISTL,	"fistl"		},
+	{ FISTP,	"fistp"		},
+	{ FISTS,	"fists"		},
+	{ FISUBL,	"fisubl"	},
+	{ FISUBRL,	"fisubrl"	},
+	{ FISUBRS,	"fisubrs"	},
+	{ FISUBS,	"fisubs"	},
+	{ FLD1,		"fld1"		},
+	{ FLDCW,	"fldcw"		},
+	{ FLDD,		"fldd"		},
+	{ FLDENV,	"fldenv"	},
+	{ FLDL2E,	"fldl2e"	},
+	{ FLDL2T,	"fldl2t"	},
+	{ FLDLG2,	"fldlg2"	},
+	{ FLDLN2,	"fldln2"	},
+	{ FLDPI,	"fldpi"		},
+	{ FLDS,		"flds"		},
+	{ FLDX,		"fldx"		},
+	{ FLDZ,		"fldz"		},
+	{ FMULD,	"fmuld"		},
+	{ FMULP,	"fmulp"		},
+	{ FMULS,	"fmuls"		},
+	{ FNOP,		"fnop"		},
+	{ FPATAN,	"fpatan"	},
+	{ FPREM,	"fprem"		},
+	{ FPREM1,	"fprem1"	},
+	{ FPTAN,	"fptan"		},
+	{ FRNDINT,	"frndint"	},
+	{ FRSTOR,	"frstor"	},
+	{ FSAVE,	"fsave"		},
+	{ FSCALE,	"fscale"	},
+	{ FSIN,		"fsin"		},
+	{ FSINCOS,	"fsincos"	},
+	{ FSQRT,	"fsqrt"		},
+	{ FSTCW,	"fstcw"		},
+	{ FSTD,		"fstd"		},
+	{ FSTENV,	"fstenv"	},
+	{ FSTPD,	"fstpd"		},
+	{ FSTPS,	"fstps"		},
+	{ FSTPX,	"fstpx"		},
+	{ FSTS,		"fsts"		},
+	{ FSTSW,	"fstsw"		},
+	{ FSUBD,	"fsubd"		},
+	{ FSUBP,	"fsubp"		},
+	{ FSUBPR,	"fsubpr"	},
+	{ FSUBRD,	"fsubrd"	},
+	{ FSUBRS,	"fsubrs"	},
+	{ FSUBS,	"fsubs"		},
+	{ FTST,		"ftst"		},
+	{ FUCOM,	"fucom"		},
+	{ FUCOMP,	"fucomp"	},
+	{ FUCOMPP,	"fucompp"	},
+	{ FXAM,		"fxam"		},
+	{ FXCH,		"fxch"		},
+	{ FXTRACT,	"fxtract"	},
+	{ FYL2X,	"fyl2x"		},
+	{ FYL2XP1,	"fyl2xp1"	},
+	{ HLT,		"hlt"		},
+	{ IDIV,		"idiv%"		},
+	{ IMUL,		"imul%"		},
+	{ IN,		"in%"		},
+	{ INC,		"inc%"		},
+	{ INS,		"ins%"		},
+	{ INT,		"int"		},
+	{ INTO,		"into"		},
+	{ INVD,		"invd"		},
+	{ INVLPG,	"invlpg"	},
+	{ IRET,		"iret"		},
+	{ IRETD,	"iretd"		},
+	{ JA,		"ja"		},
+	{ JAE,		"jae"		},
+	{ JB,		"jb"		},
+	{ JBE,		"jbe"		},
+	{ JCXZ,		"jcxz"		},
+	{ JE,		"je"		},
+	{ JG,		"jg"		},
+	{ JGE,		"jge"		},
+	{ JL,		"jl"		},
+	{ JLE,		"jle"		},
+	{ JMP,		"jmp"		},
+	{ JMPF,		"jmpf"		},
+	{ JNE,		"jne"		},
+	{ JNO,		"jno"		},
+	{ JNP,		"jnp"		},
+	{ JNS,		"jns"		},
+	{ JO,		"jo"		},
+	{ JP,		"jp"		},
+	{ JS,		"js"		},
+	{ LAHF,		"lahf"		},
+	{ LAR,		"lar"		},
+	{ LDS,		"lds"		},
+	{ LEA,		"lea"		},
+	{ LEAVE,	"leave"		},
+	{ LES,		"les"		},
+	{ LFS,		"lfs"		},
+	{ LGDT,		"lgdt"		},
+	{ LGS,		"lgs"		},
+	{ LIDT,		"lidt"		},
+	{ LLDT,		"lldt"		},
+	{ LMSW,		"lmsw"		},
+	{ LOCK,		"lock"		},
+	{ LODS,		"lods%"		},
+	{ LOOP,		"loop"		},
+	{ LOOPE,	"loope"		},
+	{ LOOPNE,	"loopne"	},
+	{ LSL,		"lsl"		},
+	{ LSS,		"lss"		},
+	{ LTR,		"ltr"		},
+	{ MOV,		"mov%"		},
+	{ MOVS,		"movs%"		},
+	{ MOVSX,	"movsx"		},
+	{ MOVSXB,	"movsxb"	},
+	{ MOVZX,	"movzx"		},
+	{ MOVZXB,	"movzxb"	},
+	{ MUL,		"mul%"		},
+	{ NEG,		"neg%"		},
+	{ NOP,		"nop"		},
+	{ NOT,		"not%"		},
+	{ OR,		"or%"		},
+	{ OUT,		"out%"		},
+	{ OUTS,		"outs%"		},
+	{ POP,		"pop"		},
+	{ POPA,		"popa"		},
+	{ POPF,		"popf"		},
+	{ PUSH,		"push"		},
+	{ PUSHA,	"pusha"		},
+	{ PUSHF,	"pushf"		},
+	{ RCL,		"rcl%"		},
+	{ RCR,		"rcr%"		},
+	{ RET,		"ret"		},
+	{ RETF,		"retf"		},
+	{ ROL,		"rol%"		},
+	{ ROR,		"ror%"		},
+	{ SAHF,		"sahf"		},
+	{ SAL,		"sal%"		},
+	{ SAR,		"sar%"		},
+	{ SBB,		"sbb%"		},
+	{ SCAS,		"scas%"		},
+	{ SETA,		"seta"		},
+	{ SETAE,	"setae"		},
+	{ SETB,		"setb"		},
+	{ SETBE,	"setbe"		},
+	{ SETE,		"sete"		},
+	{ SETG,		"setg"		},
+	{ SETGE,	"setge"		},
+	{ SETL,		"setl"		},
+	{ SETLE,	"setle"		},
+	{ SETNE,	"setne"		},
+	{ SETNO,	"setno"		},
+	{ SETNP,	"setnp"		},
+	{ SETNS,	"setns"		},
+	{ SETO,		"seto"		},
+	{ SETP,		"setp"		},
+	{ SETS,		"sets"		},
+	{ SGDT,		"sgdt"		},
+	{ SHL,		"shl%"		},
+	{ SHLD,		"shld"		},
+	{ SHR,		"shr%"		},
+	{ SHRD,		"shrd"		},
+	{ SIDT,		"sidt"		},
+	{ SLDT,		"sldt"		},
+	{ SMSW,		"smsw"		},
+	{ STC,		"stc"		},
+	{ STD,		"std"		},
+	{ STI,		"sti"		},
+	{ STOS,		"stos%"		},
+	{ STR,		"str"		},
+	{ SUB,		"sub%"		},
+	{ TEST,		"test%"		},
+	{ VERR,		"verr"		},
+	{ VERW,		"verw"		},
+	{ WAIT,		"wait"		},
+	{ WBINVD,	"wbinvd"	},
+	{ XADD,		"xadd"		},
+	{ XCHG,		"xchg%"		},
+	{ XLAT,		"xlat"		},
+	{ XOR,		"xor%"		},
+};
+
+#define farjmp(o)	((o) == JMPF || (o) == CALLF)
+
+static FILE *ef;
+static long eline= 1;
+static char *efile;
+static char *orig_efile;
+static char *opcode2name_tab[N_OPCODES];
+static enum dialect { ACK, NCC } dialect= ACK;
+
+static void ack_putchar(int c)
+/* LOOK, this programmer checks the return code of putc!  What an idiot, noone
+ * does that!
+ */
+{
+	if (putc(c, ef) == EOF) fatal(orig_efile);
+}
+
+static void ack_printf(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	if (vfprintf(ef, fmt, ap) == EOF) fatal(orig_efile);
+	va_end(ap);
+}
+
+void ack_emit_init(char *file, const char *banner)
+/* Prepare producing an ACK assembly file. */
+{
+	mnemonic_t *mp;
+
+	if (file == nil) {
+		file= "stdout";
+		ef= stdout;
+	} else {
+		if ((ef= fopen(file, "w")) == nil) fatal(file);
+	}
+	orig_efile= file;
+	efile= file;
+	ack_printf("! %s", banner);
+	if (dialect == ACK) {
+		/* Declare the four sections used under Minix. */
+		ack_printf(
+	"\n.sect .text; .sect .rom; .sect .data; .sect .bss\n.sect .text");
+	}
+
+	/* Initialize the opcode to mnemonic translation table. */
+	for (mp= mnemtab; mp < arraylimit(mnemtab); mp++) {
+		assert(opcode2name_tab[mp->opcode] == nil);
+		opcode2name_tab[mp->opcode]= mp->name;
+	}
+}
+
+#define opcode2name(op)		(opcode2name_tab[op] + 0)
+
+static void ack_put_string(const char *s, size_t n)
+/* Emit a string with weird characters quoted. */
+{
+	while (n > 0) {
+		int c= *s;
+
+		if (c < ' ' || c > 0177) {
+			ack_printf("\\%03o", c & 0xFF);
+		} else
+		if (c == '"' || c == '\\') {
+			ack_printf("\\%c", c);
+		} else {
+			ack_putchar(c);
+		}
+		s++;
+		n--;
+	}
+}
+
+static void ack_put_expression(asm86_t *a, expression_t *e, int deref)
+/* Send an expression, i.e. instruction operands, to the output file.  Deref
+ * is true when the rewrite for the ncc dialect may be made.
+ */
+{
+	assert(e != nil);
+
+	switch (e->operator) {
+	case ',':
+		if (dialect == NCC && farjmp(a->opcode)) {
+			/* ACK jmpf seg:off  ->  NCC jmpf off,seg */
+			ack_put_expression(a, e->right, deref);
+			ack_printf(", ");
+			ack_put_expression(a, e->left, deref);
+		} else {
+			ack_put_expression(a, e->left, deref);
+			ack_printf(farjmp(a->opcode) ? ":" : ", ");
+			ack_put_expression(a, e->right, deref);
+		}
+		break;
+	case 'O':
+		if (deref && a->optype == JUMP) ack_putchar('@');
+		if (e->left != nil) ack_put_expression(a, e->left, 0);
+		if (e->middle != nil) ack_put_expression(a, e->middle, 0);
+		if (e->right != nil) ack_put_expression(a, e->right, 0);
+		break;
+	case '(':
+		if (deref && a->optype == JUMP) ack_putchar('@');
+		if (!deref) ack_putchar('(');
+		ack_put_expression(a, e->middle, 0);
+		if (!deref) ack_putchar(')');
+		break;
+	case 'B':
+		ack_printf("(%s)", e->name);
+		break;
+	case '1':
+	case '2':
+	case '4':
+	case '8':
+		ack_printf((use16() && e->operator == '1')
+				? "(%s)" : "(%s*%c)", e->name, e->operator);
+		break;
+	case '+':
+	case '-':
+	case '~':
+		if (e->middle != nil) {
+			if (deref && a->optype != JUMP) ack_putchar('#');
+			ack_putchar(e->operator);
+			ack_put_expression(a, e->middle, 0);
+			break;
+		}
+		/*FALL THROUGH*/
+	case '*':
+	case '/':
+	case '%':
+	case '&':
+	case '|':
+	case '^':
+	case S_LEFTSHIFT:
+	case S_RIGHTSHIFT:
+		if (deref && a->optype != JUMP) ack_putchar('#');
+		ack_put_expression(a, e->left, 0);
+		if (e->operator == S_LEFTSHIFT) {
+			ack_printf("<<");
+		} else
+		if (e->operator == S_RIGHTSHIFT) {
+			ack_printf(">>");
+		} else {
+			ack_putchar(e->operator);
+		}
+		ack_put_expression(a, e->right, 0);
+		break;
+	case '[':
+		if (deref && a->optype != JUMP) ack_putchar('#');
+		ack_putchar('[');
+		ack_put_expression(a, e->middle, 0);
+		ack_putchar(']');
+		break;
+	case 'W':
+		if (deref && a->optype == JUMP && isregister(e->name))
+		{
+			ack_printf("(%s)", e->name);
+			break;
+		}
+		if (deref && a->optype != JUMP && !isregister(e->name)) {
+			ack_putchar('#');
+		}
+		ack_printf("%s", e->name);
+		break;
+	case 'S':
+		ack_putchar('"');
+		ack_put_string(e->name, e->len);
+		ack_putchar('"');
+		break;
+	default:
+		fprintf(stderr,
+		"asmconv: internal error, unknown expression operator '%d'\n",
+			e->operator);
+		exit(EXIT_FAILURE);
+	}
+}
+
+void ack_emit_instruction(asm86_t *a)
+/* Output one instruction and its operands. */
+{
+	int same= 0;
+	char *p;
+	static int high_seg;
+	int deref;
+
+	if (a == nil) {
+		/* Last call */
+		ack_putchar('\n');
+		return;
+	}
+
+	/* Make sure the line number of the line to be emitted is ok. */
+	if ((a->file != efile && strcmp(a->file, efile) != 0)
+				|| a->line < eline || a->line > eline+10) {
+		ack_putchar('\n');
+		ack_printf("# %ld \"%s\"\n", a->line, a->file);
+		efile= a->file;
+		eline= a->line;
+	} else {
+		if (a->line == eline) {
+			ack_printf("; ");
+			same= 1;
+		}
+		while (eline < a->line) {
+			ack_putchar('\n');
+			eline++;
+		}
+	}
+
+	if (a->opcode == DOT_LABEL) {
+		assert(a->args->operator == ':');
+		ack_printf("%s:", a->args->name);
+	} else
+	if (a->opcode == DOT_EQU) {
+		assert(a->args->operator == '=');
+		ack_printf("\t%s = ", a->args->name);
+		ack_put_expression(a, a->args->middle, 0);
+	} else
+	if ((p= opcode2name(a->opcode)) != nil) {
+		char *sep= dialect == ACK ? "" : ";";
+
+		if (!is_pseudo(a->opcode) && !same) ack_putchar('\t');
+
+		switch (a->rep) {
+		case ONCE:	break;
+		case REP:	ack_printf("rep");	break;
+		case REPE:	ack_printf("repe");	break;
+		case REPNE:	ack_printf("repne");	break;
+		default:	assert(0);
+		}
+		if (a->rep != ONCE) {
+			ack_printf(dialect == ACK ? " " : "; ");
+		}
+		switch (a->seg) {
+		case DEFSEG:	break;
+		case CSEG:	ack_printf("cseg");	break;
+		case DSEG:	ack_printf("dseg");	break;
+		case ESEG:	ack_printf("eseg");	break;
+		case FSEG:	ack_printf("fseg");	break;
+		case GSEG:	ack_printf("gseg");	break;
+		case SSEG:	ack_printf("sseg");	break;
+		default:	assert(0);
+		}
+		if (a->seg != DEFSEG) {
+			ack_printf(dialect == ACK ? " " : "; ");
+		}
+		if (a->oaz & OPZ) ack_printf(use16() ? "o32 " : "o16 ");
+		if (a->oaz & ADZ) ack_printf(use16() ? "a32 " : "a16 ");
+
+		if (a->opcode == CBW) {
+			p= !(a->oaz & OPZ) == use16() ? "cbw" : "cwde";
+		}
+
+		if (a->opcode == CWD) {
+			p= !(a->oaz & OPZ) == use16() ? "cwd" : "cdq";
+		}
+
+		if (a->opcode == DOT_COMM && a->args != nil
+			&& a->args->operator == ','
+			&& a->args->left->operator == 'W'
+		) {
+			ack_printf(".define\t%s; ", a->args->left->name);
+		}
+		while (*p != 0) {
+			if (*p == '%') {
+				if (a->optype == BYTE) ack_putchar('b');
+			} else {
+				ack_putchar(*p);
+			}
+			p++;
+		}
+		if (a->args != nil) {
+			ack_putchar('\t');
+			switch (a->opcode) {
+			case IN:
+			case OUT:
+			case INT:
+				deref= 0;
+				break;
+			default:
+				deref= (dialect == NCC && a->optype != PSEUDO);
+			}
+			ack_put_expression(a, a->args, deref);
+		}
+		if (a->opcode == DOT_USE16) set_use16();
+		if (a->opcode == DOT_USE32) set_use32();
+	} else {
+		fprintf(stderr,
+			"asmconv: internal error, unknown opcode '%d'\n",
+			a->opcode);
+		exit(EXIT_FAILURE);
+	}
+}
+
+/* A few ncc mnemonics are different. */
+static mnemonic_t ncc_mnemtab[] = {
+	{ DOT_BSS,	".bss"		},
+	{ DOT_DATA,	".data"		},
+	{ DOT_END,	".end"		},
+	{ DOT_ROM,	".rom"		},
+	{ DOT_TEXT,	".text"		},
+};
+
+void ncc_emit_init(char *file, const char *banner)
+/* The assembly produced by the Minix ACK ANSI C compiler for the 8086 is
+ * different from the normal ACK assembly, and different from the old K&R
+ * assembler.  This brings us endless joy.  (It was supposed to make
+ * translation of the assembly used by the old K&R assembler easier by
+ * not deviating too much from that dialect.)
+ */
+{
+	mnemonic_t *mp;
+
+	dialect= NCC;
+	ack_emit_init(file, banner);
+
+	/* Replace a few mnemonics. */
+	for (mp= ncc_mnemtab; mp < arraylimit(ncc_mnemtab); mp++) {
+		opcode2name_tab[mp->opcode]= mp->name;
+	}
+}
+
+void ncc_emit_instruction(asm86_t *a)
+{
+	ack_emit_instruction(a);
+}
Index: /trunk/minix/commands/i386/asmconv/emit_gnu.c
===================================================================
--- /trunk/minix/commands/i386/asmconv/emit_gnu.c	(revision 9)
+++ /trunk/minix/commands/i386/asmconv/emit_gnu.c	(revision 9)
@@ -0,0 +1,674 @@
+/*	emit_gnu.c - emit GNU assembly			Author: Kees J. Bot
+ *								28 Dec 1993
+ */
+#define nil 0
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+#include "asmconv.h"
+#include "token.h"
+#include "asm86.h"
+#include "languages.h"
+
+typedef struct mnemonic {	/* GNU as386 mnemonics translation table. */
+	opcode_t	opcode;
+	char		*name;
+} mnemonic_t;
+
+static mnemonic_t mnemtab[] = {
+	{ AAA,		"aaa"		},
+	{ AAD,		"aad"		},
+	{ AAM,		"aam"		},
+	{ AAS,		"aas"		},
+	{ ADC,		"adc%"		},
+	{ ADD,		"add%"		},
+	{ AND,		"and%"		},
+	{ ARPL,		"arpl"		},
+	{ BOUND,	"bound%"	},
+	{ BSF,		"bsf%"		},
+	{ BSR,		"bsr%"		},
+	{ BSWAP,	"bswap"		},
+	{ BT,		"bt%"		},
+	{ BTC,		"btc%"		},
+	{ BTR,		"btr%"		},
+	{ BTS,		"bts%"		},
+	{ CALL,		"call"		},
+	{ CALLF,	"lcall"		},
+	{ CBW,		"cbtw"		},
+	{ CLC,		"clc"		},
+	{ CLD,		"cld"		},
+	{ CLI,		"cli"		},
+	{ CLTS,		"clts"		},
+	{ CMC,		"cmc"		},
+	{ CMP,		"cmp%"		},
+	{ CMPS,		"cmps%"		},
+	{ CMPXCHG,	"cmpxchg"	},
+	{ CWD,		"cwtd"		},
+	{ DAA,		"daa"		},
+	{ DAS,		"das"		},
+	{ DEC,		"dec%"		},
+	{ DIV,		"div%"		},
+	{ DOT_ALIGN,	".align"	},
+	{ DOT_ASCII,	".ascii"	},
+	{ DOT_ASCIZ,	".asciz"	},
+	{ DOT_ASSERT,	".assert"	},
+	{ DOT_BASE,	".base"		},
+	{ DOT_BSS,	".bss"		},
+	{ DOT_COMM,	".comm"		},
+	{ DOT_DATA,	".data"		},
+	{ DOT_DATA1,	".byte"		},
+	{ DOT_DATA2,	".short"	},
+	{ DOT_DATA4,	".long"		},
+	{ DOT_DEFINE,	".globl"	},
+	{ DOT_EXTERN,	".globl"	},
+	{ DOT_FILE,	".file"		},
+	{ DOT_LCOMM,	".lcomm"	},
+	{ DOT_LINE,	".line"		},
+	{ DOT_LIST,	".list"		},
+	{ DOT_NOLIST,	".nolist"	},
+	{ DOT_ROM,	".data"		},	/* Minix -- separate I&D. */
+	{ DOT_SPACE,	".space"	},
+	{ DOT_SYMB,	".symb"		},
+	{ DOT_TEXT,	".text"		},
+	{ DOT_USE16,	".use16"	},
+	{ DOT_USE32,	".use32"	},
+	{ ENTER,	"enter"		},
+	{ F2XM1,	"f2xm1"		},
+	{ FABS,		"fabs"		},
+	{ FADD,		"fadd"		},
+	{ FADDD,	"faddl"		},
+	{ FADDP,	"faddp"		},
+	{ FADDS,	"fadds"		},
+	{ FBLD,		"fbld"		},
+	{ FBSTP,	"fbstp"		},
+	{ FCHS,		"fchs"		},
+	{ FCLEX,	"fnclex"	},
+	{ FCOMD,	"fcoml"		},
+	{ FCOMPD,	"fcompl"	},
+	{ FCOMPP,	"fcompp"	},
+	{ FCOMPS,	"fcomps"	},
+	{ FCOMS,	"fcoms"		},
+	{ FCOS,		"fcos"		},
+	{ FDECSTP,	"fdecstp"	},
+	{ FDIVD,	"fdivl"		},
+	{ FDIVP,	"fdivp"		},
+	{ FDIVRD,	"fdivrl"	},
+	{ FDIVRP,	"fdivrp"	},
+	{ FDIVRS,	"fdivrs"	},
+	{ FDIVS,	"fdivs"		},
+	{ FFREE,	"ffree"		},
+	{ FIADDL,	"fiaddl"	},
+	{ FIADDS,	"fiadds"	},
+	{ FICOM,	"ficom"		},
+	{ FICOMP,	"ficomp"	},
+	{ FIDIVL,	"fidivl"	},
+	{ FIDIVRL,	"fidivrl"	},
+	{ FIDIVRS,	"fidivrs"	},
+	{ FIDIVS,	"fidivs"	},
+	{ FILDL,	"fildl"		},
+	{ FILDQ,	"fildq"		},
+	{ FILDS,	"filds"		},
+	{ FIMULL,	"fimull"	},
+	{ FIMULS,	"fimuls"	},
+	{ FINCSTP,	"fincstp"	},
+	{ FINIT,	"fninit"	},
+	{ FISTL,	"fistl"		},
+	{ FISTP,	"fistp"		},
+	{ FISTS,	"fists"		},
+	{ FISUBL,	"fisubl"	},
+	{ FISUBRL,	"fisubrl"	},
+	{ FISUBRS,	"fisubrs"	},
+	{ FISUBS,	"fisubs"	},
+	{ FLD1,		"fld1"		},
+	{ FLDCW,	"fldcw"		},
+	{ FLDD,		"fldl"		},
+	{ FLDENV,	"fldenv"	},
+	{ FLDL2E,	"fldl2e"	},
+	{ FLDL2T,	"fldl2t"	},
+	{ FLDLG2,	"fldlg2"	},
+	{ FLDLN2,	"fldln2"	},
+	{ FLDPI,	"fldpi"		},
+	{ FLDS,		"flds"		},
+	{ FLDX,		"fldt"		},
+	{ FLDZ,		"fldz"		},
+	{ FMULD,	"fmull"		},
+	{ FMULP,	"fmulp"		},
+	{ FMULS,	"fmuls"		},
+	{ FNOP,		"fnop"		},
+	{ FPATAN,	"fpatan"	},
+	{ FPREM,	"fprem"		},
+	{ FPREM1,	"fprem1"	},
+	{ FPTAN,	"fptan"		},
+	{ FRNDINT,	"frndint"	},
+	{ FRSTOR,	"frstor"	},
+	{ FSAVE,	"fnsave"	},
+	{ FSCALE,	"fscale"	},
+	{ FSIN,		"fsin"		},
+	{ FSINCOS,	"fsincos"	},
+	{ FSQRT,	"fsqrt"		},
+	{ FSTCW,	"fnstcw"	},
+	{ FSTD,		"fstl"		},
+	{ FSTENV,	"fnstenv"	},
+	{ FSTPD,	"fstpl"		},
+	{ FSTPS,	"fstps"		},
+	{ FSTPX,	"fstpt"		},
+	{ FSTS,		"fsts"		},
+	{ FSTSW,	"fstsw"		},
+	{ FSUBD,	"fsubl"		},
+	{ FSUBP,	"fsubp"		},
+	{ FSUBPR,	"fsubpr"	},
+	{ FSUBRD,	"fsubrl"	},
+	{ FSUBRS,	"fsubrs"	},
+	{ FSUBS,	"fsubs"		},
+	{ FTST,		"ftst"		},
+	{ FUCOM,	"fucom"		},
+	{ FUCOMP,	"fucomp"	},
+	{ FUCOMPP,	"fucompp"	},
+	{ FXAM,		"fxam"		},
+	{ FXCH,		"fxch"		},
+	{ FXTRACT,	"fxtract"	},
+	{ FYL2X,	"fyl2x"		},
+	{ FYL2XP1,	"fyl2xp1"	},
+	{ HLT,		"hlt"		},
+	{ IDIV,		"idiv%"		},
+	{ IMUL,		"imul%"		},
+	{ IN,		"in%"		},
+	{ INC,		"inc%"		},
+	{ INS,		"ins%"		},
+	{ INT,		"int"		},
+	{ INTO,		"into"		},
+	{ INVD,		"invd"		},
+	{ INVLPG,	"invlpg"	},
+	{ IRET,		"iret"		},
+	{ IRETD,	"iret"		},
+	{ JA,		"ja"		},
+	{ JAE,		"jae"		},
+	{ JB,		"jb"		},
+	{ JBE,		"jbe"		},
+	{ JCXZ,		"jcxz"		},
+	{ JE,		"je"		},
+	{ JG,		"jg"		},
+	{ JGE,		"jge"		},
+	{ JL,		"jl"		},
+	{ JLE,		"jle"		},
+	{ JMP,		"jmp"		},
+	{ JMPF,		"ljmp"		},
+	{ JNE,		"jne"		},
+	{ JNO,		"jno"		},
+	{ JNP,		"jnp"		},
+	{ JNS,		"jns"		},
+	{ JO,		"jo"		},
+	{ JP,		"jp"		},
+	{ JS,		"js"		},
+	{ LAHF,		"lahf"		},
+	{ LAR,		"lar"		},
+	{ LDS,		"lds"		},
+	{ LEA,		"lea%"		},
+	{ LEAVE,	"leave"		},
+	{ LES,		"les"		},
+	{ LFS,		"lfs"		},
+	{ LGDT,		"lgdt"		},
+	{ LGS,		"lgs"		},
+	{ LIDT,		"lidt"		},
+	{ LLDT,		"lldt"		},
+	{ LMSW,		"lmsw"		},
+	{ LOCK,		"lock"		},
+	{ LODS,		"lods%"		},
+	{ LOOP,		"loop"		},
+	{ LOOPE,	"loope"		},
+	{ LOOPNE,	"loopne"	},
+	{ LSL,		"lsl"		},
+	{ LSS,		"lss"		},
+	{ LTR,		"ltr"		},
+	{ MOV,		"mov%"		},
+	{ MOVS,		"movs%"		},
+	{ MOVSX,	"movswl"	},
+	{ MOVSXB,	"movsb%"	},
+	{ MOVZX,	"movzwl"	},
+	{ MOVZXB,	"movzb%"	},
+	{ MUL,		"mul%"		},
+	{ NEG,		"neg%"		},
+	{ NOP,		"nop"		},
+	{ NOT,		"not%"		},
+	{ OR,		"or%"		},
+	{ OUT,		"out%"		},
+	{ OUTS,		"outs%"		},
+	{ POP,		"pop%"		},
+	{ POPA,		"popa%"		},
+	{ POPF,		"popf%"		},
+	{ PUSH,		"push%"		},
+	{ PUSHA,	"pusha%"	},
+	{ PUSHF,	"pushf%"	},
+	{ RCL,		"rcl%"		},
+	{ RCR,		"rcr%"		},
+	{ RET,		"ret"		},
+	{ RETF,		"lret"		},
+	{ ROL,		"rol%"		},
+	{ ROR,		"ror%"		},
+	{ SAHF,		"sahf"		},
+	{ SAL,		"sal%"		},
+	{ SAR,		"sar%"		},
+	{ SBB,		"sbb%"		},
+	{ SCAS,		"scas%"		},
+	{ SETA,		"setab"		},
+	{ SETAE,	"setaeb"	},
+	{ SETB,		"setbb"		},
+	{ SETBE,	"setbeb"	},
+	{ SETE,		"seteb"		},
+	{ SETG,		"setgb"		},
+	{ SETGE,	"setgeb"	},
+	{ SETL,		"setlb"		},
+	{ SETLE,	"setleb"	},
+	{ SETNE,	"setneb"	},
+	{ SETNO,	"setnob"	},
+	{ SETNP,	"setnpb"	},
+	{ SETNS,	"setnsb"	},
+	{ SETO,		"setob"		},
+	{ SETP,		"setpb"		},
+	{ SETS,		"setsb"		},
+	{ SGDT,		"sgdt"		},
+	{ SHL,		"shl%"		},
+	{ SHLD,		"shld%"		},
+	{ SHR,		"shr%"		},
+	{ SHRD,		"shrd%"		},
+	{ SIDT,		"sidt"		},
+	{ SLDT,		"sldt"		},
+	{ SMSW,		"smsw"		},
+	{ STC,		"stc"		},
+	{ STD,		"std"		},
+	{ STI,		"sti"		},
+	{ STOS,		"stos%"		},
+	{ STR,		"str"		},
+	{ SUB,		"sub%"		},
+	{ TEST,		"test%"		},
+	{ VERR,		"verr"		},
+	{ VERW,		"verw"		},
+	{ WAIT,		"wait"		},
+	{ WBINVD,	"wbinvd"	},
+	{ XADD,		"xadd"		},
+	{ XCHG,		"xchg%"		},
+	{ XLAT,		"xlat"		},
+	{ XOR,		"xor%"		},
+};
+
+static FILE *ef;
+static long eline= 1;
+static char *efile;
+static char *orig_efile;
+static char *opcode2name_tab[N_OPCODES];
+
+static void gnu_putchar(int c)
+/* LOOK, this programmer checks the return code of putc!  What an idiot, noone
+ * does that!
+ */
+{
+	if (putc(c, ef) == EOF) fatal(orig_efile);
+}
+
+static void gnu_printf(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	if (vfprintf(ef, fmt, ap) == EOF) fatal(orig_efile);
+	va_end(ap);
+}
+
+void gnu_emit_init(char *file, const char *banner)
+/* Prepare producing a GNU assembly file. */
+{
+	mnemonic_t *mp;
+
+	if (file == nil) {
+		file= "stdout";
+		ef= stdout;
+	} else {
+		if ((ef= fopen(file, "w")) == nil) fatal(file);
+	}
+	orig_efile= file;
+	efile= file;
+	gnu_printf("/ %s", banner);
+
+	/* Initialize the opcode to mnemonic translation table. */
+	for (mp= mnemtab; mp < arraylimit(mnemtab); mp++) {
+		assert(opcode2name_tab[mp->opcode] == nil);
+		opcode2name_tab[mp->opcode]= mp->name;
+	}
+}
+
+#define opcode2name(op)		(opcode2name_tab[op] + 0)
+
+static void gnu_put_string(const char *s, size_t n)
+/* Emit a string with weird characters quoted. */
+{
+	while (n > 0) {
+		int c= *s;
+
+		if (c < ' ' || c > 0177) {
+			gnu_printf("\\%03o", c);
+		} else
+		if (c == '"' || c == '\\') {
+			gnu_printf("\\%c", c & 0xFF);
+		} else {
+			gnu_putchar(c);
+		}
+		s++;
+		n--;
+	}
+}
+
+static void gnu_put_expression(asm86_t *a, expression_t *e, int deref)
+/* Send an expression, i.e. instruction operands, to the output file.  Deref
+ * is true when the rewrite of "x" -> "#x" or "(x)" -> "x" may be made.
+ */
+{
+	assert(e != nil);
+
+	switch (e->operator) {
+	case ',':
+		if (is_pseudo(a->opcode)) {
+			/* Pseudo's are normal. */
+			gnu_put_expression(a, e->left, deref);
+			gnu_printf(", ");
+			gnu_put_expression(a, e->right, deref);
+		} else {
+			/* He who invented GNU assembly has seen one VAX too
+			 * many, operands are given in the wrong order.  This
+			 * makes coding from an Intel databook a real delight.
+			 * A good thing this program allows us to write the
+			 * more normal ACK assembly.
+			 */
+			gnu_put_expression(a, e->right, deref);
+			gnu_printf(", ");
+			gnu_put_expression(a, e->left, deref);
+		}
+		break;
+	case 'O':
+		if (deref && a->optype == JUMP) gnu_putchar('*');
+		if (e->left != nil) gnu_put_expression(a, e->left, 0);
+		gnu_putchar('(');
+		if (e->middle != nil) gnu_put_expression(a, e->middle, 0);
+		if (e->right != nil) {
+			gnu_putchar(',');
+			gnu_put_expression(a, e->right, 0);
+		}
+		gnu_putchar(')');
+		break;
+	case '(':
+		if (!deref) gnu_putchar('(');
+		if (deref && a->optype == JUMP) gnu_putchar('*');
+		gnu_put_expression(a, e->middle, 0);
+		if (!deref) gnu_putchar(')');
+		break;
+	case 'B':
+		gnu_printf("%%%s", e->name);
+		break;
+	case '1':
+	case '2':
+	case '4':
+	case '8':
+		gnu_printf("%%%s,%c", e->name, e->operator);
+		break;
+	case '+':
+	case '-':
+	case '~':
+		if (e->middle != nil) {
+			if (deref && a->optype >= BYTE) gnu_putchar('$');
+			gnu_putchar(e->operator);
+			gnu_put_expression(a, e->middle, 0);
+			break;
+		}
+		/*FALL THROUGH*/
+	case '*':
+	case '/':
+	case '%':
+	case '&':
+	case '|':
+	case '^':
+	case S_LEFTSHIFT:
+	case S_RIGHTSHIFT:
+		if (deref && a->optype >= BYTE) gnu_putchar('$');
+		gnu_put_expression(a, e->left, 0);
+		if (e->operator == S_LEFTSHIFT) {
+			gnu_printf("<<");
+		} else
+		if (e->operator == S_RIGHTSHIFT) {
+			gnu_printf(">>");
+		} else {
+			gnu_putchar(e->operator);
+		}
+		gnu_put_expression(a, e->right, 0);
+		break;
+	case '[':
+		if (deref && a->optype >= BYTE) gnu_putchar('$');
+		gnu_putchar('(');
+		gnu_put_expression(a, e->middle, 0);
+		gnu_putchar(')');
+		break;
+	case 'W':
+		if (isregister(e->name)) {
+			if (a->optype == JUMP) gnu_putchar('*');
+			gnu_printf("%%%s", e->name);
+		} else {
+			if (deref && a->optype >= BYTE) gnu_putchar('$');
+			gnu_printf("%s", e->name);
+		}
+		break;
+	case 'S':
+		gnu_putchar('"');
+		gnu_put_string(e->name, e->len);
+		gnu_putchar('"');
+		break;
+	default:
+		fprintf(stderr,
+		"asmconv: internal error, unknown expression operator '%d'\n",
+			e->operator);
+		exit(EXIT_FAILURE);
+	}
+}
+
+void gnu_emit_instruction(asm86_t *a)
+/* Output one instruction and its operands. */
+{
+	int same= 0;
+	char *p;
+
+	if (a == nil) {
+		/* Last call */
+		gnu_putchar('\n');
+		return;
+	}
+
+	if (use16()) {
+		fprintf(stderr,
+		"asmconv: the GNU assembler can't translate 8086 code\n");
+		exit(EXIT_FAILURE);
+	}
+
+	/* Make sure the line number of the line to be emitted is ok. */
+	if ((a->file != efile && strcmp(a->file, efile) != 0)
+				|| a->line < eline || a->line > eline+10) {
+		gnu_putchar('\n');
+		gnu_printf("# %ld \"%s\"\n", a->line, a->file);
+		efile= a->file;
+		eline= a->line;
+	} else {
+		if (a->line == eline) {
+			gnu_printf("; ");
+			same= 1;
+		}
+		while (eline < a->line) {
+			gnu_putchar('\n');
+			eline++;
+		}
+	}
+
+	if (a->opcode == DOT_LABEL) {
+		assert(a->args->operator == ':');
+		gnu_printf("%s:", a->args->name);
+	} else
+	if (a->opcode == DOT_EQU) {
+		assert(a->args->operator == '=');
+		gnu_printf("\t%s = ", a->args->name);
+		gnu_put_expression(a, a->args->middle, 0);
+	} else
+	if (a->opcode == DOT_ALIGN) {
+		/* GNU .align thinks in powers of two. */
+		unsigned long n;
+		unsigned s;
+
+		assert(a->args->operator == 'W' && isanumber(a->args->name));
+		n= strtoul(a->args->name, nil, 0);
+		for (s= 0; s <= 4 && (1 << s) < n; s++) {}
+		gnu_printf(".align\t%u", s);
+	} else
+	if ((p= opcode2name(a->opcode)) != nil) {
+		if (!is_pseudo(a->opcode) && !same) gnu_putchar('\t');
+
+		switch (a->rep) {
+		case ONCE:	break;
+		case REP:	gnu_printf("rep; ");	break;
+		case REPE:	gnu_printf("repe; ");	break;
+		case REPNE:	gnu_printf("repne; ");	break;
+		default:	assert(0);
+		}
+		switch (a->seg) {
+		/* Kludge to avoid knowing where to put the "%es:" */
+		case DEFSEG:	break;
+		case CSEG:	gnu_printf(".byte 0x2e; ");	break;
+		case DSEG:	gnu_printf(".byte 0x3e; ");	break;
+		case ESEG:	gnu_printf(".byte 0x26; ");	break;
+		case FSEG:	gnu_printf(".byte 0x64; ");	break;
+		case GSEG:	gnu_printf(".byte 0x65; ");	break;
+		case SSEG:	gnu_printf(".byte 0x36; ");	break;
+		default:	assert(0);
+		}
+
+		/* Exceptions, exceptions... */
+		if (a->opcode == CBW) {
+			if (!(a->oaz & OPZ)) p= "cwtl";
+			a->oaz&= ~OPZ;
+		}
+		if (a->opcode == CWD) {
+			if (!(a->oaz & OPZ)) p= "cltd";
+			a->oaz&= ~OPZ;
+		}
+
+		if (a->opcode == RET || a->opcode == RETF) {
+			/* Argument of RET needs a '$'. */
+			a->optype= WORD;
+		}
+
+		if (a->opcode == MUL && a->args != nil
+						&& a->args->operator == ',') {
+			/* Two operand MUL is an IMUL? */
+			p="imul%";
+		}
+
+		/* GAS doesn't understand the interesting combinations. */
+		if (a->oaz & ADZ) gnu_printf(".byte 0x67; ");
+		if (a->oaz & OPZ && strchr(p, '%') == nil)
+			gnu_printf(".byte 0x66; ");
+
+		/* Unsupported instructions that Minix code needs. */
+		if (a->opcode == JMPF && a->args != nil
+					&& a->args->operator == ',') {
+			/* JMPF seg:off. */
+			gnu_printf(".byte 0xEA; .long ");
+			gnu_put_expression(a, a->args->right, 0);
+			gnu_printf("; .short ");
+			gnu_put_expression(a, a->args->left, 0);
+			return;
+		}
+		if (a->opcode == JMPF && a->args != nil
+			&& a->args->operator == 'O'
+			&& a->args->left != nil
+			&& a->args->right == nil
+			&& a->args->middle != nil
+			&& a->args->middle->operator == 'B'
+			&& strcmp(a->args->middle->name, "esp") == 0
+		) {
+			/* JMPF offset(ESP). */
+			gnu_printf(".byte 0xFF,0x6C,0x24,");
+			gnu_put_expression(a, a->args->left, 0);
+			return;
+		}
+		if (a->opcode == MOV && a->args != nil
+			&& a->args->operator == ','
+			&& a->args->left != nil
+			&& a->args->left->operator == 'W'
+			&& (strcmp(a->args->left->name, "ds") == 0
+				|| strcmp(a->args->left->name, "es") == 0)
+			&& a->args->right->operator == 'O'
+			&& a->args->right->left != nil
+			&& a->args->right->right == nil
+			&& a->args->right->middle != nil
+			&& a->args->right->middle->operator == 'B'
+			&& strcmp(a->args->right->middle->name, "esp") == 0
+		) {
+			/* MOV DS, offset(ESP); MOV ES, offset(ESP) */
+			gnu_printf(".byte 0x8E,0x%02X,0x24,",
+				a->args->left->name[0] == 'd' ? 0x5C : 0x44);
+			gnu_put_expression(a, a->args->right->left, 0);
+			return;
+		}
+		if (a->opcode == MOV && a->args != nil
+			&& a->args->operator == ','
+			&& a->args->left != nil
+			&& a->args->left->operator == 'W'
+			&& (strcmp(a->args->left->name, "ds") == 0
+				|| strcmp(a->args->left->name, "es") == 0)
+			&& a->args->right->operator == '('
+			&& a->args->right->middle != nil
+		) {
+			/* MOV DS, (memory); MOV ES, (memory) */
+			gnu_printf(".byte 0x8E,0x%02X; .long ",
+				a->args->left->name[0] == 'd' ? 0x1D : 0x05);
+			gnu_put_expression(a, a->args->right->middle, 0);
+			return;
+		}
+
+		while (*p != 0) {
+			if (*p == '%') {
+				if (a->optype == BYTE) {
+					gnu_putchar('b');
+				} else
+				if (a->optype == WORD) {
+					gnu_putchar((a->oaz & OPZ) ? 'w' : 'l');
+				} else {
+					assert(0);
+				}
+			} else {
+				gnu_putchar(*p);
+			}
+			p++;
+		}
+
+		if (a->args != nil) {
+			static char *aregs[] = { "al", "ax", "eax" };
+
+			gnu_putchar('\t');
+			switch (a->opcode) {
+			case IN:
+				gnu_put_expression(a, a->args, 1);
+				gnu_printf(", %%%s", aregs[a->optype - BYTE]);
+				break;
+			case OUT:
+				gnu_printf("%%%s, ", aregs[a->optype - BYTE]);
+				gnu_put_expression(a, a->args, 1);
+				break;
+			default:
+				gnu_put_expression(a, a->args, 1);
+			}
+		}
+		if (a->opcode == DOT_USE16) set_use16();
+		if (a->opcode == DOT_USE32) set_use32();
+	} else {
+		fprintf(stderr,
+			"asmconv: internal error, unknown opcode '%d'\n",
+			a->opcode);
+		exit(EXIT_FAILURE);
+	}
+}
Index: /trunk/minix/commands/i386/asmconv/languages.h
===================================================================
--- /trunk/minix/commands/i386/asmconv/languages.h	(revision 9)
+++ /trunk/minix/commands/i386/asmconv/languages.h	(revision 9)
@@ -0,0 +1,25 @@
+/*	languages.h - functions that parse or emit assembly
+ *							Author: Kees J. Bot
+ *								27 Dec 1993
+ */
+
+void ack_parse_init(char *file);
+asm86_t *ack_get_instruction(void);
+
+void ncc_parse_init(char *file);
+asm86_t *ncc_get_instruction(void);
+
+void gnu_parse_init(char *file);
+asm86_t *gnu_get_instruction(void);
+
+void bas_parse_init(char *file);
+asm86_t *bas_get_instruction(void);
+
+void ack_emit_init(char *file, const char *banner);
+void ack_emit_instruction(asm86_t *instr);
+
+void ncc_emit_init(char *file, const char *banner);
+void ncc_emit_instruction(asm86_t *instr);
+
+void gnu_emit_init(char *file, const char *banner);
+void gnu_emit_instruction(asm86_t *instr);
Index: /trunk/minix/commands/i386/asmconv/parse_ack.c
===================================================================
--- /trunk/minix/commands/i386/asmconv/parse_ack.c	(revision 9)
+++ /trunk/minix/commands/i386/asmconv/parse_ack.c	(revision 9)
@@ -0,0 +1,910 @@
+/*	parse_ack.c - parse ACK assembly		Author: Kees J. Bot
+ *		      parse NCC assembly			18 Dec 1993
+ */
+#define nil 0
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "asmconv.h"
+#include "token.h"
+#include "asm86.h"
+#include "languages.h"
+
+typedef struct mnemonic {	/* ACK as86 mnemonics translation table. */
+	char		*name;
+	opcode_t	opcode;
+	optype_t	optype;
+} mnemonic_t;
+
+static mnemonic_t mnemtab[] = {			/* This array is sorted. */
+	{ ".align",	DOT_ALIGN,	PSEUDO },
+	{ ".ascii",	DOT_ASCII,	PSEUDO },
+	{ ".asciz",	DOT_ASCIZ,	PSEUDO },
+	{ ".assert",	DOT_ASSERT,	PSEUDO },
+	{ ".base",	DOT_BASE,	PSEUDO },
+	{ ".bss",	DOT_BSS,	PSEUDO },
+	{ ".comm",	DOT_LCOMM,	PSEUDO },
+	{ ".data",	DOT_DATA,	PSEUDO },
+	{ ".data1",	DOT_DATA1,	PSEUDO },
+	{ ".data2",	DOT_DATA2,	PSEUDO },
+	{ ".data4",	DOT_DATA4,	PSEUDO },
+	{ ".define",	DOT_DEFINE,	PSEUDO },
+	{ ".end",	DOT_END,	PSEUDO },
+	{ ".extern",	DOT_EXTERN,	PSEUDO },
+	{ ".file",	DOT_FILE,	PSEUDO },
+	{ ".line",	DOT_LINE,	PSEUDO },
+	{ ".list",	DOT_LIST,	PSEUDO },
+	{ ".nolist",	DOT_NOLIST,	PSEUDO },
+	{ ".rom",	DOT_ROM,	PSEUDO },
+	{ ".space",	DOT_SPACE,	PSEUDO },
+	{ ".symb",	DOT_SYMB,	PSEUDO },
+	{ ".text",	DOT_TEXT,	PSEUDO },
+	{ ".use16",	DOT_USE16,	PSEUDO },
+	{ ".use32",	DOT_USE32,	PSEUDO },
+	{ "aaa",	AAA,		WORD },
+	{ "aad",	AAD,		WORD },
+	{ "aam",	AAM,		WORD },
+	{ "aas",	AAS,		WORD },
+	{ "adc",	ADC,		WORD },
+	{ "adcb",	ADC,		BYTE },
+	{ "add",	ADD,		WORD },
+	{ "addb",	ADD,		BYTE },
+	{ "and",	AND,		WORD },
+	{ "andb",	AND,		BYTE },
+	{ "arpl",	ARPL,		WORD },
+	{ "bound",	BOUND,		WORD },
+	{ "bsf",	BSF,		WORD },
+	{ "bsr",	BSR,		WORD },
+	{ "bswap",	BSWAP,		WORD },
+	{ "bt",		BT,		WORD },
+	{ "btc",	BTC,		WORD },
+	{ "btr",	BTR,		WORD },
+	{ "bts",	BTS,		WORD },
+	{ "call",	CALL,		JUMP },
+	{ "callf",	CALLF,		JUMP },
+	{ "cbw",	CBW,		WORD },
+	{ "cdq",	CWD,		WORD },
+	{ "clc",	CLC,		WORD },
+	{ "cld",	CLD,		WORD },
+	{ "cli",	CLI,		WORD },
+	{ "clts",	CLTS,		WORD },
+	{ "cmc",	CMC,		WORD },
+	{ "cmp",	CMP,		WORD },
+	{ "cmpb",	CMP,		BYTE },
+	{ "cmps",	CMPS,		WORD },
+	{ "cmpsb",	CMPS,		BYTE },
+	{ "cmpxchg",	CMPXCHG,	WORD },
+	{ "cwd",	CWD,		WORD },
+	{ "cwde",	CBW,		WORD },
+	{ "daa",	DAA,		WORD },
+	{ "das",	DAS,		WORD },
+	{ "dec",	DEC,		WORD },
+	{ "decb",	DEC,		BYTE },
+	{ "div",	DIV,		WORD },
+	{ "divb",	DIV,		BYTE },
+	{ "enter",	ENTER,		WORD },
+	{ "f2xm1",	F2XM1,		WORD },
+	{ "fabs",	FABS,		WORD },
+	{ "fadd",	FADD,		WORD },
+	{ "faddd",	FADDD,		WORD },
+	{ "faddp",	FADDP,		WORD },
+	{ "fadds",	FADDS,		WORD },
+	{ "fbld",	FBLD,		WORD },
+	{ "fbstp",	FBSTP,		WORD },
+	{ "fchs",	FCHS,		WORD },
+	{ "fclex",	FCLEX,		WORD },
+	{ "fcomd",	FCOMD,		WORD },
+	{ "fcompd",	FCOMPD,		WORD },
+	{ "fcompp",	FCOMPP,		WORD },
+	{ "fcomps",	FCOMPS,		WORD },
+	{ "fcoms",	FCOMS,		WORD },
+	{ "fcos",	FCOS,		WORD },
+	{ "fdecstp",	FDECSTP,	WORD },
+	{ "fdivd",	FDIVD,		WORD },
+	{ "fdivp",	FDIVP,		WORD },
+	{ "fdivrd",	FDIVRD,		WORD },
+	{ "fdivrp",	FDIVRP,		WORD },
+	{ "fdivrs",	FDIVRS,		WORD },
+	{ "fdivs",	FDIVS,		WORD },
+	{ "ffree",	FFREE,		WORD },
+	{ "fiaddl",	FIADDL,		WORD },
+	{ "fiadds",	FIADDS,		WORD },
+	{ "ficom",	FICOM,		WORD },
+	{ "ficomp",	FICOMP,		WORD },
+	{ "fidivl",	FIDIVL,		WORD },
+	{ "fidivrl",	FIDIVRL,	WORD },
+	{ "fidivrs",	FIDIVRS,	WORD },
+	{ "fidivs",	FIDIVS,		WORD },
+	{ "fildl",	FILDL,		WORD },
+	{ "fildq",	FILDQ,		WORD },
+	{ "filds",	FILDS,		WORD },
+	{ "fimull",	FIMULL,		WORD },
+	{ "fimuls",	FIMULS,		WORD },
+	{ "fincstp",	FINCSTP,	WORD },
+	{ "finit",	FINIT,		WORD },
+	{ "fistl",	FISTL,		WORD },
+	{ "fistp",	FISTP,		WORD },
+	{ "fists",	FISTS,		WORD },
+	{ "fisubl",	FISUBL,		WORD },
+	{ "fisubrl",	FISUBRL,	WORD },
+	{ "fisubrs",	FISUBRS,	WORD },
+	{ "fisubs",	FISUBS,		WORD },
+	{ "fld1",	FLD1,		WORD },
+	{ "fldcw",	FLDCW,		WORD },
+	{ "fldd",	FLDD,		WORD },
+	{ "fldenv",	FLDENV,		WORD },
+	{ "fldl2e",	FLDL2E,		WORD },
+	{ "fldl2t",	FLDL2T,		WORD },
+	{ "fldlg2",	FLDLG2,		WORD },
+	{ "fldln2",	FLDLN2,		WORD },
+	{ "fldpi",	FLDPI,		WORD },
+	{ "flds",	FLDS,		WORD },
+	{ "fldx",	FLDX,		WORD },
+	{ "fldz",	FLDZ,		WORD },
+	{ "fmuld",	FMULD,		WORD },
+	{ "fmulp",	FMULP,		WORD },
+	{ "fmuls",	FMULS,		WORD },
+	{ "fnop",	FNOP,		WORD },
+	{ "fpatan",	FPATAN,		WORD },
+	{ "fprem",	FPREM,		WORD },
+	{ "fprem1",	FPREM1,		WORD },
+	{ "fptan",	FPTAN,		WORD },
+	{ "frndint",	FRNDINT,	WORD },
+	{ "frstor",	FRSTOR,		WORD },
+	{ "fsave",	FSAVE,		WORD },
+	{ "fscale",	FSCALE,		WORD },
+	{ "fsin",	FSIN,		WORD },
+	{ "fsincos",	FSINCOS,	WORD },
+	{ "fsqrt",	FSQRT,		WORD },
+	{ "fstcw",	FSTCW,		WORD },
+	{ "fstd",	FSTD,		WORD },
+	{ "fstenv",	FSTENV,		WORD },
+	{ "fstpd",	FSTPD,		WORD },
+	{ "fstps",	FSTPS,		WORD },
+	{ "fstpx",	FSTPX,		WORD },
+	{ "fsts",	FSTS,		WORD },
+	{ "fstsw",	FSTSW,		WORD },
+	{ "fsubd",	FSUBD,		WORD },
+	{ "fsubp",	FSUBP,		WORD },
+	{ "fsubpr",	FSUBPR,		WORD },
+	{ "fsubrd",	FSUBRD,		WORD },
+	{ "fsubrs",	FSUBRS,		WORD },
+	{ "fsubs",	FSUBS,		WORD },
+	{ "ftst",	FTST,		WORD },
+	{ "fucom",	FUCOM,		WORD },
+	{ "fucomp",	FUCOMP,		WORD },
+	{ "fucompp",	FUCOMPP,	WORD },
+	{ "fxam",	FXAM,		WORD },
+	{ "fxch",	FXCH,		WORD },
+	{ "fxtract",	FXTRACT,	WORD },
+	{ "fyl2x",	FYL2X,		WORD },
+	{ "fyl2xp1",	FYL2XP1,	WORD },
+	{ "hlt",	HLT,		WORD },
+	{ "idiv",	IDIV,		WORD },
+	{ "idivb",	IDIV,		BYTE },
+	{ "imul",	IMUL,		WORD },
+	{ "imulb",	IMUL,		BYTE },
+	{ "in",		IN,		WORD },
+	{ "inb",	IN,		BYTE },
+	{ "inc",	INC,		WORD },
+	{ "incb",	INC,		BYTE },
+	{ "ins",	INS,		WORD },
+	{ "insb",	INS,		BYTE },
+	{ "int",	INT,		WORD },
+	{ "into",	INTO,		JUMP },
+	{ "invd",	INVD,		WORD },
+	{ "invlpg",	INVLPG,		WORD },
+	{ "iret",	IRET,		JUMP },
+	{ "iretd",	IRETD,		JUMP },
+	{ "ja",		JA,		JUMP },
+	{ "jae",	JAE,		JUMP },
+	{ "jb",		JB,		JUMP },
+	{ "jbe",	JBE,		JUMP },
+	{ "jc",		JB,		JUMP },
+	{ "jcxz",	JCXZ,		JUMP },
+	{ "je",		JE,		JUMP },
+	{ "jecxz",	JCXZ,		JUMP },
+	{ "jg",		JG,		JUMP },
+	{ "jge",	JGE,		JUMP },
+	{ "jl",		JL,		JUMP },
+	{ "jle",	JLE,		JUMP },
+	{ "jmp",	JMP,		JUMP },
+	{ "jmpf",	JMPF,		JUMP },
+	{ "jna",	JBE,		JUMP },
+	{ "jnae",	JB,		JUMP },
+	{ "jnb",	JAE,		JUMP },
+	{ "jnbe",	JA,		JUMP },
+	{ "jnc",	JAE,		JUMP },
+	{ "jne",	JNE,		JUMP },
+	{ "jng",	JLE,		JUMP },
+	{ "jnge",	JL,		JUMP },
+	{ "jnl",	JGE,		JUMP },
+	{ "jnle",	JG,		JUMP },
+	{ "jno",	JNO,		JUMP },
+	{ "jnp",	JNP,		JUMP },
+	{ "jns",	JNS,		JUMP },
+	{ "jnz",	JNE,		JUMP },
+	{ "jo",		JO,		JUMP },
+	{ "jp",		JP,		JUMP },
+	{ "js",		JS,		JUMP },
+	{ "jz",		JE,		JUMP },
+	{ "lahf",	LAHF,		WORD },
+	{ "lar",	LAR,		WORD },
+	{ "lds",	LDS,		WORD },
+	{ "lea",	LEA,		WORD },
+	{ "leave",	LEAVE,		WORD },
+	{ "les",	LES,		WORD },
+	{ "lfs",	LFS,		WORD },
+	{ "lgdt",	LGDT,		WORD },
+	{ "lgs",	LGS,		WORD },
+	{ "lidt",	LIDT,		WORD },
+	{ "lldt",	LLDT,		WORD },
+	{ "lmsw",	LMSW,		WORD },
+	{ "lock",	LOCK,		WORD },
+	{ "lods",	LODS,		WORD },
+	{ "lodsb",	LODS,		BYTE },
+	{ "loop",	LOOP,		JUMP },
+	{ "loope",	LOOPE,		JUMP },
+	{ "loopne",	LOOPNE,		JUMP },
+	{ "loopnz",	LOOPNE,		JUMP },
+	{ "loopz",	LOOPE,		JUMP },
+	{ "lsl",	LSL,		WORD },
+	{ "lss",	LSS,		WORD },
+	{ "ltr",	LTR,		WORD },
+	{ "mov",	MOV,		WORD },
+	{ "movb",	MOV,		BYTE },
+	{ "movs",	MOVS,		WORD },
+	{ "movsb",	MOVS,		BYTE },
+	{ "movsx",	MOVSX,		WORD },
+	{ "movsxb",	MOVSXB,		WORD },
+	{ "movzx",	MOVZX,		WORD },
+	{ "movzxb",	MOVZXB,		WORD },
+	{ "mul",	MUL,		WORD },
+	{ "mulb",	MUL,		BYTE },
+	{ "neg",	NEG,		WORD },
+	{ "negb",	NEG,		BYTE },
+	{ "nop",	NOP,		WORD },
+	{ "not",	NOT,		WORD },
+	{ "notb",	NOT,		BYTE },
+	{ "or",		OR,		WORD },
+	{ "orb",	OR,		BYTE },
+	{ "out",	OUT,		WORD },
+	{ "outb",	OUT,		BYTE },
+	{ "outs",	OUTS,		WORD },
+	{ "outsb",	OUTS,		BYTE },
+	{ "pop",	POP,		WORD },
+	{ "popa",	POPA,		WORD },
+	{ "popad",	POPA,		WORD },
+	{ "popf",	POPF,		WORD },
+	{ "push",	PUSH,		WORD },
+	{ "pusha",	PUSHA,		WORD },
+	{ "pushad",	PUSHA,		WORD },
+	{ "pushf",	PUSHF,		WORD },
+	{ "rcl",	RCL,		WORD },
+	{ "rclb",	RCL,		BYTE },
+	{ "rcr",	RCR,		WORD },
+	{ "rcrb",	RCR,		BYTE },
+	{ "ret",	RET,		JUMP },
+	{ "retf",	RETF,		JUMP },
+	{ "rol",	ROL,		WORD },
+	{ "rolb",	ROL,		BYTE },
+	{ "ror",	ROR,		WORD },
+	{ "rorb",	ROR,		BYTE },
+	{ "sahf",	SAHF,		WORD },
+	{ "sal",	SAL,		WORD },
+	{ "salb",	SAL,		BYTE },
+	{ "sar",	SAR,		WORD },
+	{ "sarb",	SAR,		BYTE },
+	{ "sbb",	SBB,		WORD },
+	{ "sbbb",	SBB,		BYTE },
+	{ "scas",	SCAS,		WORD },
+	{ "scasb",	SCAS,		BYTE },
+	{ "seta",	SETA,		BYTE },
+	{ "setae",	SETAE,		BYTE },
+	{ "setb",	SETB,		BYTE },
+	{ "setbe",	SETBE,		BYTE },
+	{ "sete",	SETE,		BYTE },
+	{ "setg",	SETG,		BYTE },
+	{ "setge",	SETGE,		BYTE },
+	{ "setl",	SETL,		BYTE },
+	{ "setna",	SETBE,		BYTE },
+	{ "setnae",	SETB,		BYTE },
+	{ "setnb",	SETAE,		BYTE },
+	{ "setnbe",	SETA,		BYTE },
+	{ "setne",	SETNE,		BYTE },
+	{ "setng",	SETLE,		BYTE },
+	{ "setnge",	SETL,		BYTE },
+	{ "setnl",	SETGE,		BYTE },
+	{ "setnle",	SETG,		BYTE },
+	{ "setno",	SETNO,		BYTE },
+	{ "setnp",	SETNP,		BYTE },
+	{ "setns",	SETNS,		BYTE },
+	{ "seto",	SETO,		BYTE },
+	{ "setp",	SETP,		BYTE },
+	{ "sets",	SETS,		BYTE },
+	{ "setz",	SETE,		BYTE },
+	{ "sgdt",	SGDT,		WORD },
+	{ "shl",	SHL,		WORD },
+	{ "shlb",	SHL,		BYTE },
+	{ "shld",	SHLD,		WORD },
+	{ "shr",	SHR,		WORD },
+	{ "shrb",	SHR,		BYTE },
+	{ "shrd",	SHRD,		WORD },
+	{ "sidt",	SIDT,		WORD },
+	{ "sldt",	SLDT,		WORD },
+	{ "smsw",	SMSW,		WORD },
+	{ "stc",	STC,		WORD },
+	{ "std",	STD,		WORD },
+	{ "sti",	STI,		WORD },
+	{ "stos",	STOS,		WORD },
+	{ "stosb",	STOS,		BYTE },
+	{ "str",	STR,		WORD },
+	{ "sub",	SUB,		WORD },
+	{ "subb",	SUB,		BYTE },
+	{ "test",	TEST,		WORD },
+	{ "testb",	TEST,		BYTE },
+	{ "verr",	VERR,		WORD },
+	{ "verw",	VERW,		WORD },
+	{ "wait",	WAIT,		WORD },
+	{ "wbinvd",	WBINVD,		WORD },
+	{ "xadd",	XADD,		WORD },
+	{ "xchg",	XCHG,		WORD },
+	{ "xchgb",	XCHG,		BYTE },
+	{ "xlat",	XLAT,		WORD },
+	{ "xor",	XOR,		WORD },
+	{ "xorb",	XOR,		BYTE },
+};
+
+static enum dialect { ACK, NCC } dialect= ACK;
+
+void ack_parse_init(char *file)
+/* Prepare parsing of an ACK assembly file. */
+{
+	tok_init(file, '!');
+}
+
+void ncc_parse_init(char *file)
+/* Prepare parsing of an ACK Xenix assembly file.  See emit_ack.c for comments
+ * on this fine assembly dialect.
+ */
+{
+	dialect= NCC;
+	ack_parse_init(file);
+}
+
+static void zap(void)
+/* An error, zap the rest of the line. */
+{
+	token_t *t;
+
+	while ((t= get_token(0))->type != T_EOF && t->symbol != ';')
+		skip_token(1);
+}
+
+static mnemonic_t *search_mnem(char *name)
+/* Binary search for a mnemonic.  (That's why the table is sorted.) */
+{
+	int low, mid, high;
+	int cmp;
+	mnemonic_t *m;
+
+	low= 0;
+	high= arraysize(mnemtab)-1;
+	while (low <= high) {
+		mid= (low + high) / 2;
+		m= &mnemtab[mid];
+
+		if ((cmp= strcmp(name, m->name)) == 0) return m;
+
+		if (cmp < 0) high= mid-1; else low= mid+1;
+	}
+	return nil;
+}
+
+static expression_t *ack_get_C_expression(int *pn)
+/* Read a "C-like" expression.  Note that we don't worry about precedence,
+ * the expression is printed later like it is read.  If the target language
+ * does not have all the operators (like ~) then this has to be repaired by
+ * changing the source file.  (No problem, you still have one source file
+ * to maintain, not two.)
+ */
+{
+	expression_t *e, *a1, *a2;
+	token_t *t;
+
+	if ((t= get_token(*pn))->symbol == '[') {
+		/* [ expr ]: grouping. */
+		(*pn)++;
+		if ((a1= ack_get_C_expression(pn)) == nil) return nil;
+		if (get_token(*pn)->symbol != ']') {
+			parse_err(1, t, "missing ]\n");
+			del_expr(a1);
+			return nil;
+		}
+		(*pn)++;
+		e= new_expr();
+		e->operator= '[';
+		e->middle= a1;
+	} else
+	if (t->type == T_WORD || t->type == T_STRING) {
+		/* Label, number, or string. */
+		e= new_expr();
+		e->operator= t->type == T_WORD ? 'W' : 'S';
+		e->name= allocate(nil, (t->len+1) * sizeof(e->name[0]));
+		memcpy(e->name, t->name, t->len+1);
+		e->len= t->len;
+		(*pn)++;
+	} else
+	if (t->symbol == '+' || t->symbol == '-' || t->symbol == '~') {
+		/* Unary operator. */
+		(*pn)++;
+		if ((a1= ack_get_C_expression(pn)) == nil) return nil;
+		e= new_expr();
+		e->operator= t->symbol;
+		e->middle= a1;
+	} else {
+		parse_err(1, t, "expression syntax error\n");
+		return nil;
+	}
+
+	switch ((t= get_token(*pn))->symbol) {
+	case '+':
+	case '-':
+	case '*':
+	case '/':
+	case '%':
+	case '&':
+	case '|':
+	case '^':
+	case S_LEFTSHIFT:
+	case S_RIGHTSHIFT:
+		(*pn)++;
+		a1= e;
+		if ((a2= ack_get_C_expression(pn)) == nil) {
+			del_expr(a1);
+			return nil;
+		}
+		e= new_expr();
+		e->operator= t->symbol;
+		e->left= a1;
+		e->right= a2;
+	}
+	return e;
+}
+
+static expression_t *ack_get_operand(int *pn, int deref)
+/* Get something like: (memory), offset(base)(index*scale), or simpler. */
+{
+	expression_t *e, *offset, *base, *index;
+	token_t *t;
+	int c;
+
+	/* Is it (memory)? */
+	if (get_token(*pn)->symbol == '('
+		&& ((t= get_token(*pn + 1))->type != T_WORD
+			|| !isregister(t->name))
+	) {
+		/* A memory dereference. */
+		(*pn)++;
+		if ((offset= ack_get_C_expression(pn)) == nil) return nil;
+		if (get_token(*pn)->symbol != ')') {
+			parse_err(1, t, "operand syntax error\n");
+			del_expr(offset);
+			return nil;
+		}
+		(*pn)++;
+		e= new_expr();
+		e->operator= '(';
+		e->middle= offset;
+		return e;
+	}
+
+	/* #constant? */
+	if (dialect == NCC && deref
+			&& ((c= get_token(*pn)->symbol) == '#' || c == '*')) {
+		/* NCC: mov ax,#constant  ->  ACK: mov ax,constant */
+		(*pn)++;
+		return ack_get_C_expression(pn);
+	}
+
+	/* @address? */
+	if (dialect == NCC && get_token(*pn)->symbol == '@') {
+		/* NCC: jmp @address  ->  ACK: jmp (address) */
+		(*pn)++;
+		if ((offset= ack_get_operand(pn, deref)) == nil) return nil;
+		e= new_expr();
+		e->operator= '(';
+		e->middle= offset;
+		return e;
+	}
+
+	/* Offset? */
+	if (get_token(*pn)->symbol != '(') {
+		/* There is an offset. */
+		if ((offset= ack_get_C_expression(pn)) == nil) return nil;
+	} else {
+		/* No offset. */
+		offset= nil;
+	}
+
+	/* (base)? */
+	if (get_token(*pn)->symbol == '('
+		&& (t= get_token(*pn + 1))->type == T_WORD
+		&& isregister(t->name)
+		&& get_token(*pn + 2)->symbol == ')'
+	) {
+		/* A base register expression. */
+		base= new_expr();
+		base->operator= 'B';
+		base->name= copystr(t->name);
+		(*pn)+= 3;
+	} else {
+		/* No base register expression. */
+		base= nil;
+	}
+
+	/* (index*scale)? */
+	if (get_token(*pn)->symbol == '(') {
+		/* An index most likely. */
+		token_t *m= nil;
+
+		if (!(		/* This must be true: */
+			(t= get_token(*pn + 1))->type == T_WORD
+			&& isregister(t->name)
+			&& (get_token(*pn + 2)->symbol == ')' || (
+				get_token(*pn + 2)->symbol == '*'
+				&& (m= get_token(*pn + 3))->type == T_WORD
+				&& strchr("1248", m->name[0]) != nil
+				&& m->name[1] == 0
+				&& get_token(*pn + 4)->symbol == ')'
+			))
+		)) {
+			/* Alas it isn't */
+			parse_err(1, t, "operand syntax error\n");
+			del_expr(offset);
+			del_expr(base);
+			return nil;
+		}
+		/* Found an index. */
+		index= new_expr();
+		index->operator= m == nil ? '1' : m->name[0];
+		index->name= copystr(t->name);
+		(*pn)+= (m == nil ? 3 : 5);
+	} else {
+		/* No index. */
+		index= nil;
+	}
+
+	if (dialect == NCC && deref && base == nil && index == nil
+		&& !(offset != nil && offset->operator == 'W'
+					&& isregister(offset->name))
+	) {
+		/* NCC: mov ax,thing  ->  ACK mov ax,(thing) */
+		e= new_expr();
+		e->operator= '(';
+		e->middle= offset;
+		return e;
+	}
+
+	if (base == nil && index == nil) {
+		/* Return a lone offset as is. */
+		e= offset;
+	} else {
+		e= new_expr();
+		e->operator= 'O';
+		e->left= offset;
+		e->middle= base;
+		e->right= index;
+	}
+	return e;
+}
+
+static expression_t *ack_get_oplist(int *pn, int deref)
+/* Get a comma (or colon for jmpf and callf) separated list of instruction
+ * operands.
+ */
+{
+	expression_t *e, *o1, *o2;
+	token_t *t;
+
+	if ((e= ack_get_operand(pn, deref)) == nil) return nil;
+
+	if ((t= get_token(*pn))->symbol == ',' || t->symbol == ':') {
+		o1= e;
+		(*pn)++;
+		if ((o2= ack_get_oplist(pn, deref)) == nil) {
+			del_expr(o1);
+			return nil;
+		}
+		e= new_expr();
+		e->operator= ',';
+		e->left= o1;
+		e->right= o2;
+	}
+	return e;
+}
+
+static asm86_t *ack_get_statement(void)
+/* Get a pseudo op or machine instruction with arguments. */
+{
+	token_t *t= get_token(0);
+	asm86_t *a;
+	mnemonic_t *m;
+	int n;
+	int prefix_seen;
+	int oaz_prefix;
+	int deref;
+
+	assert(t->type == T_WORD);
+
+	if (strcmp(t->name, ".sect") == 0) {
+		/* .sect .text etc.  Accept only four segment names. */
+		skip_token(1);
+		t= get_token(0);
+		if (t->type != T_WORD || (
+			strcmp(t->name, ".text") != 0
+			&& strcmp(t->name, ".rom") != 0
+			&& strcmp(t->name, ".data") != 0
+			&& strcmp(t->name, ".bss") != 0
+			&& strcmp(t->name, ".end") != 0
+		)) {
+			parse_err(1, t, "weird section name to .sect\n");
+			return nil;
+		}
+	}
+	a= new_asm86();
+
+	/* Process instruction prefixes. */
+	oaz_prefix= 0;
+	for (prefix_seen= 0;; prefix_seen= 1) {
+		if (strcmp(t->name, "o16") == 0) {
+			if (use16()) {
+				parse_err(1, t, "o16 in an 8086 section\n");
+			}
+			oaz_prefix|= OPZ;
+		} else
+		if (strcmp(t->name, "o32") == 0) {
+			if (use32()) {
+				parse_err(1, t, "o32 in an 80386 section\n");
+			}
+			oaz_prefix|= OPZ;
+		} else
+		if (strcmp(t->name, "a16") == 0) {
+			if (use16()) {
+				parse_err(1, t, "a16 in an 8086 section\n");
+			}
+			oaz_prefix|= ADZ;
+		} else
+		if (strcmp(t->name, "a32") == 0) {
+			if (use32()) {
+				parse_err(1, t, "a32 in an 80386 section\n");
+			}
+			oaz_prefix|= ADZ;
+		} else
+		if (strcmp(t->name, "rep") == 0
+			|| strcmp(t->name, "repe") == 0
+			|| strcmp(t->name, "repne") == 0
+			|| strcmp(t->name, "repz") == 0
+			|| strcmp(t->name, "repnz") == 0
+		) {
+			if (a->rep != ONCE) {
+				parse_err(1, t,
+					"can't have more than one rep\n");
+			}
+			switch (t->name[3]) {
+			case 0:		a->rep= REP;	break;
+			case 'e':
+			case 'z':	a->rep= REPE;	break;
+			case 'n':	a->rep= REPNE;	break;
+			}
+		} else
+		if (strchr("cdefgs", t->name[0]) != nil
+					&& strcmp(t->name+1, "seg") == 0) {
+			if (a->seg != DEFSEG) {
+				parse_err(1, t,
+				"can't have more than one segment prefix\n");
+			}
+			switch (t->name[0]) {
+			case 'c':	a->seg= CSEG;	break;
+			case 'd':	a->seg= DSEG;	break;
+			case 'e':	a->seg= ESEG;	break;
+			case 'f':	a->seg= FSEG;	break;
+			case 'g':	a->seg= GSEG;	break;
+			case 's':	a->seg= SSEG;	break;
+			}
+		} else
+		if (!prefix_seen) {
+			/* No prefix here, get out! */
+			break;
+		} else {
+			/* No more prefixes, next must be an instruction. */
+			if (t->type != T_WORD
+				|| (m= search_mnem(t->name)) == nil
+				|| m->optype == PSEUDO
+			) {
+				parse_err(1, t,
+		"machine instruction expected after instruction prefix\n");
+				del_asm86(a);
+				return nil;
+			}
+			if (oaz_prefix != 0 && m->optype != JUMP
+						&& m->optype != WORD) {
+				parse_err(1, t,
+			"'%s' can't have an operand size prefix\n", m->name);
+			}
+			break;
+		}
+
+		/* Skip the prefix and extra newlines. */
+		do {
+			skip_token(1);
+		} while ((t= get_token(0))->symbol == ';');
+	}
+
+	/* All the readahead being done upsets the line counter. */
+	a->line= t->line;
+
+	/* Read a machine instruction or pseudo op. */
+	if ((m= search_mnem(t->name)) == nil) {
+		parse_err(1, t, "unknown instruction '%s'\n", t->name);
+		del_asm86(a);
+		return nil;
+	}
+	a->opcode= m->opcode;
+	a->optype= m->optype;
+	a->oaz= oaz_prefix;
+
+	switch (a->opcode) {
+	case IN:
+	case OUT:
+	case INT:
+		deref= 0;
+		break;
+	default:
+		deref= (a->optype >= BYTE);
+	}
+	n= 1;
+	if (get_token(1)->symbol != ';'
+			&& (a->args= ack_get_oplist(&n, deref)) == nil) {
+		del_asm86(a);
+		return nil;
+	}
+	if (get_token(n)->symbol != ';') {
+		parse_err(1, t, "garbage at end of instruction\n");
+		del_asm86(a);
+		return nil;
+	}
+	switch (a->opcode) {
+	case DOT_ALIGN:
+		/* Restrict .align to have a single numeric argument, some
+		 * assemblers think of the argument as a power of two, so
+		 * we need to be able to change the value.
+		 */
+		if (a->args == nil || a->args->operator != 'W'
+					|| !isanumber(a->args->name)) {
+			parse_err(1, t,
+			  ".align is restricted to one numeric argument\n");
+			del_asm86(a);
+			return nil;
+		}
+		break;
+	case JMPF:
+	case CALLF:
+		/* NCC jmpf off,seg  ->  ACK jmpf seg:off */
+		if (dialect == NCC && a->args != nil
+						&& a->args->operator == ',') {
+			expression_t *t;
+
+			t= a->args->left;
+			a->args->left= a->args->right;
+			a->args->right= t;
+			break;
+		}
+		/*FALL THROUGH*/
+	case JMP:
+	case CALL:
+		/* NCC jmp @(reg)  ->  ACK jmp (reg) */
+		if (dialect == NCC && a->args != nil && (
+			(a->args->operator == '('
+				&& a->args->middle != nil
+				&& a->args->middle->operator == 'O')
+			|| (a->args->operator == 'O'
+				&& a->args->left == nil
+				&& a->args->middle != nil
+				&& a->args->right == nil)
+		)) {
+			expression_t *t;
+
+			t= a->args;
+			a->args= a->args->middle;
+			t->middle= nil;
+			del_expr(t);
+			if (a->args->operator == 'B') a->args->operator= 'W';
+		}
+		break;
+	default:;
+	}
+	skip_token(n+1);
+	return a;
+}
+
+asm86_t *ack_get_instruction(void)
+{
+	asm86_t *a= nil;
+	expression_t *e;
+	token_t *t;
+
+	while ((t= get_token(0))->symbol == ';')
+		skip_token(1);
+
+	if (t->type == T_EOF) return nil;
+
+	if (t->symbol == '#') {
+		/* Preprocessor line and file change. */
+
+		if ((t= get_token(1))->type != T_WORD || !isanumber(t->name)
+			|| get_token(2)->type != T_STRING
+		) {
+			parse_err(1, t, "file not preprocessed?\n");
+			zap();
+		} else {
+			set_file(get_token(2)->name,
+				strtol(get_token(1)->name, nil, 0) - 1);
+
+			/* GNU CPP adds extra cruft, simply zap the line. */
+			zap();
+		}
+		a= ack_get_instruction();
+	} else
+	if (t->type == T_WORD && get_token(1)->symbol == ':') {
+		/* A label definition. */
+		a= new_asm86();
+		a->line= t->line;
+		a->opcode= DOT_LABEL;
+		a->optype= PSEUDO;
+		a->args= e= new_expr();
+		e->operator= ':';
+		e->name= copystr(t->name);
+		skip_token(2);
+	} else
+	if (t->type == T_WORD && get_token(1)->symbol == '=') {
+		int n= 2;
+
+		if ((e= ack_get_C_expression(&n)) == nil) {
+			zap();
+			a= ack_get_instruction();
+		} else
+		if (get_token(n)->symbol != ';') {
+			parse_err(1, t, "garbage after assignment\n");
+			zap();
+			a= ack_get_instruction();
+		} else {
+			a= new_asm86();
+			a->line= t->line;
+			a->opcode= DOT_EQU;
+			a->optype= PSEUDO;
+			a->args= new_expr();
+			a->args->operator= '=';
+			a->args->name= copystr(t->name);
+			a->args->middle= e;
+			skip_token(n+1);
+		}
+	} else
+	if (t->type == T_WORD) {
+		if ((a= ack_get_statement()) == nil) {
+			zap();
+			a= ack_get_instruction();
+		}
+	} else {
+		parse_err(1, t, "syntax error\n");
+		zap();
+		a= ack_get_instruction();
+	}
+	return a;
+}
+
+asm86_t *ncc_get_instruction(void)
+{
+	return ack_get_instruction();
+}
Index: /trunk/minix/commands/i386/asmconv/parse_bas.c
===================================================================
--- /trunk/minix/commands/i386/asmconv/parse_bas.c	(revision 9)
+++ /trunk/minix/commands/i386/asmconv/parse_bas.c	(revision 9)
@@ -0,0 +1,940 @@
+/*	parse_bas.c - parse BCC AS assembly		Author: Kees J. Bot
+ *								13 Nov 1994
+ */
+#define nil 0
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "asmconv.h"
+#include "token.h"
+#include "asm86.h"
+#include "languages.h"
+
+typedef struct mnemonic {	/* BAS mnemonics translation table. */
+	char		*name;
+	opcode_t	opcode;
+	optype_t	optype;
+} mnemonic_t;
+
+static mnemonic_t mnemtab[] = {			/* This array is sorted. */
+	{ ".align",	DOT_ALIGN,	PSEUDO },
+	{ ".ascii",	DOT_ASCII,	PSEUDO },
+	{ ".asciz",	DOT_ASCIZ,	PSEUDO },
+	{ ".assert",	DOT_ASSERT,	PSEUDO },
+	{ ".base",	DOT_BASE,	PSEUDO },
+	{ ".blkb",	DOT_SPACE,	PSEUDO },
+	{ ".bss",	DOT_BSS,	PSEUDO },
+	{ ".byte",	DOT_DATA1,	PSEUDO },
+	{ ".comm",	DOT_COMM,	PSEUDO },
+	{ ".data",	DOT_DATA,	PSEUDO },
+	{ ".define",	DOT_DEFINE,	PSEUDO },
+	{ ".end",	DOT_END,	PSEUDO },
+	{ ".even",	DOT_ALIGN,	PSEUDO },
+	{ ".extern",	DOT_EXTERN,	PSEUDO },
+	{ ".file",	DOT_FILE,	PSEUDO },
+	{ ".globl",	DOT_DEFINE,	PSEUDO },
+	{ ".lcomm",	DOT_LCOMM,	PSEUDO },
+	{ ".line",	DOT_LINE,	PSEUDO },
+	{ ".list",	DOT_LIST,	PSEUDO },
+	{ ".long",	DOT_DATA4,	PSEUDO },
+	{ ".nolist",	DOT_NOLIST,	PSEUDO },
+	{ ".rom",	DOT_ROM,	PSEUDO },
+	{ ".space",	DOT_SPACE,	PSEUDO },
+	{ ".symb",	DOT_SYMB,	PSEUDO },
+	{ ".text",	DOT_TEXT,	PSEUDO },
+	{ ".use16",	DOT_USE16,	PSEUDO },
+	{ ".use32",	DOT_USE32,	PSEUDO },
+	{ ".word",	DOT_DATA2,	PSEUDO },
+	{ ".zerob",	DOT_SPACE,	PSEUDO },
+	{ ".zerow",	DOT_SPACE,	PSEUDO },
+	{ "aaa",	AAA,		WORD },
+	{ "aad",	AAD,		WORD },
+	{ "aam",	AAM,		WORD },
+	{ "aas",	AAS,		WORD },
+	{ "adc",	ADC,		WORD },
+	{ "add",	ADD,		WORD },
+	{ "and",	AND,		WORD },
+	{ "arpl",	ARPL,		WORD },
+	{ "bc",		JB,		JUMP },
+	{ "beq",	JE,		JUMP },
+	{ "bge",	JGE,		JUMP },
+	{ "bgt",	JG,		JUMP },
+	{ "bhi",	JA,		JUMP },
+	{ "bhis",	JAE,		JUMP },
+	{ "ble",	JLE,		JUMP },
+	{ "blo",	JB,		JUMP },
+	{ "blos",	JBE,		JUMP },
+	{ "blt",	JL,		JUMP },
+	{ "bnc",	JAE,		JUMP },
+	{ "bne",	JNE,		JUMP },
+	{ "bound",	BOUND,		WORD },
+	{ "br",		JMP,		JUMP },
+	{ "bsf",	BSF,		WORD },
+	{ "bsr",	BSR,		WORD },
+	{ "bswap",	BSWAP,		WORD },
+	{ "bt",		BT,		WORD },
+	{ "btc",	BTC,		WORD },
+	{ "btr",	BTR,		WORD },
+	{ "bts",	BTS,		WORD },
+	{ "bz",		JE,		JUMP },
+	{ "call",	CALL,		JUMP },
+	{ "callf",	CALLF,		JUMP },
+	{ "cbw",	CBW,		WORD },
+	{ "cdq",	CWD,		WORD },
+	{ "clc",	CLC,		WORD },
+	{ "cld",	CLD,		WORD },
+	{ "cli",	CLI,		WORD },
+	{ "clts",	CLTS,		WORD },
+	{ "cmc",	CMC,		WORD },
+	{ "cmp",	CMP,		WORD },
+	{ "cmps",	CMPS,		WORD },
+	{ "cmpsb",	CMPS,		BYTE },
+	{ "cmpxchg",	CMPXCHG,	WORD },
+	{ "cwd",	CWD,		WORD },
+	{ "cwde",	CBW,		WORD },
+	{ "daa",	DAA,		WORD },
+	{ "das",	DAS,		WORD },
+	{ "dd",		DOT_DATA4,	PSEUDO },
+	{ "dec",	DEC,		WORD },
+	{ "div",	DIV,		WORD },
+	{ "enter",	ENTER,		WORD },
+	{ "export",	DOT_DEFINE,	PSEUDO },
+	{ "f2xm1",	F2XM1,		WORD },
+	{ "fabs",	FABS,		WORD },
+	{ "fadd",	FADD,		WORD },
+	{ "faddd",	FADDD,		WORD },
+	{ "faddp",	FADDP,		WORD },
+	{ "fadds",	FADDS,		WORD },
+	{ "fbld",	FBLD,		WORD },
+	{ "fbstp",	FBSTP,		WORD },
+	{ "fchs",	FCHS,		WORD },
+	{ "fclex",	FCLEX,		WORD },
+	{ "fcomd",	FCOMD,		WORD },
+	{ "fcompd",	FCOMPD,		WORD },
+	{ "fcompp",	FCOMPP,		WORD },
+	{ "fcomps",	FCOMPS,		WORD },
+	{ "fcoms",	FCOMS,		WORD },
+	{ "fcos",	FCOS,		WORD },
+	{ "fdecstp",	FDECSTP,	WORD },
+	{ "fdivd",	FDIVD,		WORD },
+	{ "fdivp",	FDIVP,		WORD },
+	{ "fdivrd",	FDIVRD,		WORD },
+	{ "fdivrp",	FDIVRP,		WORD },
+	{ "fdivrs",	FDIVRS,		WORD },
+	{ "fdivs",	FDIVS,		WORD },
+	{ "ffree",	FFREE,		WORD },
+	{ "fiaddl",	FIADDL,		WORD },
+	{ "fiadds",	FIADDS,		WORD },
+	{ "ficom",	FICOM,		WORD },
+	{ "ficomp",	FICOMP,		WORD },
+	{ "fidivl",	FIDIVL,		WORD },
+	{ "fidivrl",	FIDIVRL,	WORD },
+	{ "fidivrs",	FIDIVRS,	WORD },
+	{ "fidivs",	FIDIVS,		WORD },
+	{ "fildl",	FILDL,		WORD },
+	{ "fildq",	FILDQ,		WORD },
+	{ "filds",	FILDS,		WORD },
+	{ "fimull",	FIMULL,		WORD },
+	{ "fimuls",	FIMULS,		WORD },
+	{ "fincstp",	FINCSTP,	WORD },
+	{ "finit",	FINIT,		WORD },
+	{ "fistl",	FISTL,		WORD },
+	{ "fistp",	FISTP,		WORD },
+	{ "fists",	FISTS,		WORD },
+	{ "fisubl",	FISUBL,		WORD },
+	{ "fisubrl",	FISUBRL,	WORD },
+	{ "fisubrs",	FISUBRS,	WORD },
+	{ "fisubs",	FISUBS,		WORD },
+	{ "fld1",	FLD1,		WORD },
+	{ "fldcw",	FLDCW,		WORD },
+	{ "fldd",	FLDD,		WORD },
+	{ "fldenv",	FLDENV,		WORD },
+	{ "fldl2e",	FLDL2E,		WORD },
+	{ "fldl2t",	FLDL2T,		WORD },
+	{ "fldlg2",	FLDLG2,		WORD },
+	{ "fldln2",	FLDLN2,		WORD },
+	{ "fldpi",	FLDPI,		WORD },
+	{ "flds",	FLDS,		WORD },
+	{ "fldx",	FLDX,		WORD },
+	{ "fldz",	FLDZ,		WORD },
+	{ "fmuld",	FMULD,		WORD },
+	{ "fmulp",	FMULP,		WORD },
+	{ "fmuls",	FMULS,		WORD },
+	{ "fnop",	FNOP,		WORD },
+	{ "fpatan",	FPATAN,		WORD },
+	{ "fprem",	FPREM,		WORD },
+	{ "fprem1",	FPREM1,		WORD },
+	{ "fptan",	FPTAN,		WORD },
+	{ "frndint",	FRNDINT,	WORD },
+	{ "frstor",	FRSTOR,		WORD },
+	{ "fsave",	FSAVE,		WORD },
+	{ "fscale",	FSCALE,		WORD },
+	{ "fsin",	FSIN,		WORD },
+	{ "fsincos",	FSINCOS,	WORD },
+	{ "fsqrt",	FSQRT,		WORD },
+	{ "fstcw",	FSTCW,		WORD },
+	{ "fstd",	FSTD,		WORD },
+	{ "fstenv",	FSTENV,		WORD },
+	{ "fstpd",	FSTPD,		WORD },
+	{ "fstps",	FSTPS,		WORD },
+	{ "fstpx",	FSTPX,		WORD },
+	{ "fsts",	FSTS,		WORD },
+	{ "fstsw",	FSTSW,		WORD },
+	{ "fsubd",	FSUBD,		WORD },
+	{ "fsubp",	FSUBP,		WORD },
+	{ "fsubpr",	FSUBPR,		WORD },
+	{ "fsubrd",	FSUBRD,		WORD },
+	{ "fsubrs",	FSUBRS,		WORD },
+	{ "fsubs",	FSUBS,		WORD },
+	{ "ftst",	FTST,		WORD },
+	{ "fucom",	FUCOM,		WORD },
+	{ "fucomp",	FUCOMP,		WORD },
+	{ "fucompp",	FUCOMPP,	WORD },
+	{ "fxam",	FXAM,		WORD },
+	{ "fxch",	FXCH,		WORD },
+	{ "fxtract",	FXTRACT,	WORD },
+	{ "fyl2x",	FYL2X,		WORD },
+	{ "fyl2xp1",	FYL2XP1,	WORD },
+	{ "hlt",	HLT,		WORD },
+	{ "idiv",	IDIV,		WORD },
+	{ "imul",	IMUL,		WORD },
+	{ "in",		IN,		WORD },
+	{ "inb",	IN,		BYTE },
+	{ "inc",	INC,		WORD },
+	{ "ins",	INS,		WORD },
+	{ "insb",	INS,		BYTE },
+	{ "int",	INT,		WORD },
+	{ "into",	INTO,		JUMP },
+	{ "invd",	INVD,		WORD },
+	{ "invlpg",	INVLPG,		WORD },
+	{ "iret",	IRET,		JUMP },
+	{ "iretd",	IRETD,		JUMP },
+	{ "j",		JMP,		JUMP },
+	{ "ja",		JA,		JUMP },
+	{ "jae",	JAE,		JUMP },
+	{ "jb",		JB,		JUMP },
+	{ "jbe",	JBE,		JUMP },
+	{ "jc",		JB,		JUMP },
+	{ "jcxz",	JCXZ,		JUMP },
+	{ "je",		JE,		JUMP },
+	{ "jecxz",	JCXZ,		JUMP },
+	{ "jeq",	JE,		JUMP },
+	{ "jg",		JG,		JUMP },
+	{ "jge",	JGE,		JUMP },
+	{ "jgt",	JG,		JUMP },
+	{ "jhi",	JA,		JUMP },
+	{ "jhis",	JAE,		JUMP },
+	{ "jl",		JL,		JUMP },
+	{ "jle",	JLE,		JUMP },
+	{ "jlo",	JB,		JUMP },
+	{ "jlos",	JBE,		JUMP },
+	{ "jlt",	JL,		JUMP },
+	{ "jmp",	JMP,		JUMP },
+	{ "jmpf",	JMPF,		JUMP },
+	{ "jna",	JBE,		JUMP },
+	{ "jnae",	JB,		JUMP },
+	{ "jnb",	JAE,		JUMP },
+	{ "jnbe",	JA,		JUMP },
+	{ "jnc",	JAE,		JUMP },
+	{ "jne",	JNE,		JUMP },
+	{ "jng",	JLE,		JUMP },
+	{ "jnge",	JL,		JUMP },
+	{ "jnl",	JGE,		JUMP },
+	{ "jnle",	JG,		JUMP },
+	{ "jno",	JNO,		JUMP },
+	{ "jnp",	JNP,		JUMP },
+	{ "jns",	JNS,		JUMP },
+	{ "jnz",	JNE,		JUMP },
+	{ "jo",		JO,		JUMP },
+	{ "jp",		JP,		JUMP },
+	{ "js",		JS,		JUMP },
+	{ "jz",		JE,		JUMP },
+	{ "lahf",	LAHF,		WORD },
+	{ "lar",	LAR,		WORD },
+	{ "lds",	LDS,		WORD },
+	{ "lea",	LEA,		WORD },
+	{ "leave",	LEAVE,		WORD },
+	{ "les",	LES,		WORD },
+	{ "lfs",	LFS,		WORD },
+	{ "lgdt",	LGDT,		WORD },
+	{ "lgs",	LGS,		WORD },
+	{ "lidt",	LIDT,		WORD },
+	{ "lldt",	LLDT,		WORD },
+	{ "lmsw",	LMSW,		WORD },
+	{ "lock",	LOCK,		WORD },
+	{ "lods",	LODS,		WORD },
+	{ "lodsb",	LODS,		BYTE },
+	{ "loop",	LOOP,		JUMP },
+	{ "loope",	LOOPE,		JUMP },
+	{ "loopne",	LOOPNE,		JUMP },
+	{ "loopnz",	LOOPNE,		JUMP },
+	{ "loopz",	LOOPE,		JUMP },
+	{ "lsl",	LSL,		WORD },
+	{ "lss",	LSS,		WORD },
+	{ "ltr",	LTR,		WORD },
+	{ "mov",	MOV,		WORD },
+	{ "movs",	MOVS,		WORD },
+	{ "movsb",	MOVS,		BYTE },
+	{ "movsx",	MOVSX,		WORD },
+	{ "movzx",	MOVZX,		WORD },
+	{ "mul",	MUL,		WORD },
+	{ "neg",	NEG,		WORD },
+	{ "nop",	NOP,		WORD },
+	{ "not",	NOT,		WORD },
+	{ "or",		OR,		WORD },
+	{ "out",	OUT,		WORD },
+	{ "outb",	OUT,		BYTE },
+	{ "outs",	OUTS,		WORD },
+	{ "outsb",	OUTS,		BYTE },
+	{ "pop",	POP,		WORD },
+	{ "popa",	POPA,		WORD },
+	{ "popad",	POPA,		WORD },
+	{ "popf",	POPF,		WORD },
+	{ "popfd",	POPF,		WORD },
+	{ "push",	PUSH,		WORD },
+	{ "pusha",	PUSHA,		WORD },
+	{ "pushad",	PUSHA,		WORD },
+	{ "pushf",	PUSHF,		WORD },
+	{ "pushfd",	PUSHF,		WORD },
+	{ "rcl",	RCL,		WORD },
+	{ "rcr",	RCR,		WORD },
+	{ "ret",	RET,		JUMP },
+	{ "retf",	RETF,		JUMP },
+	{ "rol",	ROL,		WORD },
+	{ "ror",	ROR,		WORD },
+	{ "sahf",	SAHF,		WORD },
+	{ "sal",	SAL,		WORD },
+	{ "sar",	SAR,		WORD },
+	{ "sbb",	SBB,		WORD },
+	{ "scas",	SCAS,		WORD },
+	{ "seta",	SETA,		BYTE },
+	{ "setae",	SETAE,		BYTE },
+	{ "setb",	SETB,		BYTE },
+	{ "setbe",	SETBE,		BYTE },
+	{ "sete",	SETE,		BYTE },
+	{ "setg",	SETG,		BYTE },
+	{ "setge",	SETGE,		BYTE },
+	{ "setl",	SETL,		BYTE },
+	{ "setna",	SETBE,		BYTE },
+	{ "setnae",	SETB,		BYTE },
+	{ "setnb",	SETAE,		BYTE },
+	{ "setnbe",	SETA,		BYTE },
+	{ "setne",	SETNE,		BYTE },
+	{ "setng",	SETLE,		BYTE },
+	{ "setnge",	SETL,		BYTE },
+	{ "setnl",	SETGE,		BYTE },
+	{ "setnle",	SETG,		BYTE },
+	{ "setno",	SETNO,		BYTE },
+	{ "setnp",	SETNP,		BYTE },
+	{ "setns",	SETNS,		BYTE },
+	{ "seto",	SETO,		BYTE },
+	{ "setp",	SETP,		BYTE },
+	{ "sets",	SETS,		BYTE },
+	{ "setz",	SETE,		BYTE },
+	{ "sgdt",	SGDT,		WORD },
+	{ "shl",	SHL,		WORD },
+	{ "shld",	SHLD,		WORD },
+	{ "shr",	SHR,		WORD },
+	{ "shrd",	SHRD,		WORD },
+	{ "sidt",	SIDT,		WORD },
+	{ "sldt",	SLDT,		WORD },
+	{ "smsw",	SMSW,		WORD },
+	{ "stc",	STC,		WORD },
+	{ "std",	STD,		WORD },
+	{ "sti",	STI,		WORD },
+	{ "stos",	STOS,		WORD },
+	{ "stosb",	STOS,		BYTE },
+	{ "str",	STR,		WORD },
+	{ "sub",	SUB,		WORD },
+	{ "test",	TEST,		WORD },
+	{ "verr",	VERR,		WORD },
+	{ "verw",	VERW,		WORD },
+	{ "wait",	WAIT,		WORD },
+	{ "wbinvd",	WBINVD,		WORD },
+	{ "xadd",	XADD,		WORD },
+	{ "xchg",	XCHG,		WORD },
+	{ "xlat",	XLAT,		WORD },
+	{ "xor",	XOR,		WORD },
+};
+
+void bas_parse_init(char *file)
+/* Prepare parsing of an BAS assembly file. */
+{
+	tok_init(file, '!');
+}
+
+static void zap(void)
+/* An error, zap the rest of the line. */
+{
+	token_t *t;
+
+	while ((t= get_token(0))->type != T_EOF && t->symbol != ';')
+		skip_token(1);
+}
+
+static mnemonic_t *search_mnem(char *name)
+/* Binary search for a mnemonic.  (That's why the table is sorted.) */
+{
+	int low, mid, high;
+	int cmp;
+	mnemonic_t *m;
+
+	low= 0;
+	high= arraysize(mnemtab)-1;
+	while (low <= high) {
+		mid= (low + high) / 2;
+		m= &mnemtab[mid];
+
+		if ((cmp= strcmp(name, m->name)) == 0) return m;
+
+		if (cmp < 0) high= mid-1; else low= mid+1;
+	}
+	return nil;
+}
+
+static expression_t *bas_get_C_expression(int *pn)
+/* Read a "C-like" expression.  Note that we don't worry about precedence,
+ * the expression is printed later like it is read.  If the target language
+ * does not have all the operators (like ~) then this has to be repaired by
+ * changing the source file.  (No problem, you still have one source file
+ * to maintain, not two.)
+ */
+{
+	expression_t *e, *a1, *a2;
+	token_t *t;
+
+	if ((t= get_token(*pn))->symbol == '(') {
+		/* ( expr ): grouping. */
+		(*pn)++;
+		if ((a1= bas_get_C_expression(pn)) == nil) return nil;
+		if (get_token(*pn)->symbol != ')') {
+			parse_err(1, t, "missing )\n");
+			del_expr(a1);
+			return nil;
+		}
+		(*pn)++;
+		e= new_expr();
+		e->operator= '[';
+		e->middle= a1;
+	} else
+	if (t->type == T_WORD || t->type == T_STRING) {
+		/* Label, number, or string. */
+		e= new_expr();
+		e->operator= t->type == T_WORD ? 'W' : 'S';
+		e->name= allocate(nil, (t->len+1) * sizeof(e->name[0]));
+		memcpy(e->name, t->name, t->len+1);
+		e->len= t->len;
+		(*pn)++;
+	} else
+	if (t->symbol == '+' || t->symbol == '-' || t->symbol == '~') {
+		/* Unary operator. */
+		(*pn)++;
+		if ((a1= bas_get_C_expression(pn)) == nil) return nil;
+		e= new_expr();
+		e->operator= t->symbol;
+		e->middle= a1;
+	} else
+	if (t->symbol == '$' && get_token(*pn + 1)->type == T_WORD) {
+		/* A hexadecimal number. */
+		t= get_token(*pn + 1);
+		e= new_expr();
+		e->operator= 'W';
+		e->name= allocate(nil, (t->len+3) * sizeof(e->name[0]));
+		strcpy(e->name, "0x");
+		memcpy(e->name+2, t->name, t->len+1);
+		e->len= t->len+2;
+		(*pn)+= 2;
+	} else {
+		parse_err(1, t, "expression syntax error\n");
+		return nil;
+	}
+
+	switch ((t= get_token(*pn))->symbol) {
+	case '+':
+	case '-':
+	case '*':
+	case '/':
+	case '%':
+	case '&':
+	case '|':
+	case '^':
+	case S_LEFTSHIFT:
+	case S_RIGHTSHIFT:
+		(*pn)++;
+		a1= e;
+		if ((a2= bas_get_C_expression(pn)) == nil) {
+			del_expr(a1);
+			return nil;
+		}
+		e= new_expr();
+		e->operator= t->symbol;
+		e->left= a1;
+		e->right= a2;
+	}
+	return e;
+}
+
+/* We want to know the sizes of the first two operands. */
+static optype_t optypes[2];
+static int op_idx;
+
+static expression_t *bas_get_operand(int *pn)
+/* Get something like: [memory], offset[base+index*scale], or simpler. */
+{
+	expression_t *e, *offset, *base, *index;
+	token_t *t;
+	int c;
+	optype_t optype;
+
+	/* Prefixed by 'byte', 'word' or 'dword'? */
+	if ((t= get_token(*pn))->type == T_WORD && (
+		strcmp(t->name, "byte") == 0
+		|| strcmp(t->name, "word") == 0
+		|| strcmp(t->name, "dword") == 0)
+	) {
+		switch (t->name[0]) {
+		case 'b':	optype= BYTE; break;
+		case 'w':	optype= use16() ? WORD : OWORD; break;
+		case 'd':	optype= use32() ? WORD : OWORD; break;
+		}
+		if (op_idx < arraysize(optypes)) optypes[op_idx++]= optype;
+		(*pn)++;
+
+		/* It may even be "byte ptr"... */
+		if ((t= get_token(*pn))->type == T_WORD
+					&& strcmp(t->name, "ptr") == 0) {
+			(*pn)++;
+		}
+	}
+
+	/* Is it [memory]? */
+	if (get_token(*pn)->symbol == '['
+		&& ((t= get_token(*pn + 1))->type != T_WORD
+			|| !isregister(t->name))
+	) {
+		/* A memory dereference. */
+		(*pn)++;
+		if ((offset= bas_get_C_expression(pn)) == nil) return nil;
+		if (get_token(*pn)->symbol != ']') {
+			parse_err(1, t, "operand syntax error\n");
+			del_expr(offset);
+			return nil;
+		}
+		(*pn)++;
+		e= new_expr();
+		e->operator= '(';
+		e->middle= offset;
+		return e;
+	}
+
+	/* #something? *something? */
+	if ((c= get_token(*pn)->symbol) == '#' || c == '*') {
+		/* '#' and '*' are often used to introduce some constant. */
+		(*pn)++;
+	}
+
+	/* Offset? */
+	if (get_token(*pn)->symbol != '[') {
+		/* There is an offset. */
+		if ((offset= bas_get_C_expression(pn)) == nil) return nil;
+	} else {
+		/* No offset. */
+		offset= nil;
+	}
+
+	/* [base]? [base+? base-? */
+	c= 0;
+	if (get_token(*pn)->symbol == '['
+		&& (t= get_token(*pn + 1))->type == T_WORD
+		&& isregister(t->name)
+		&& ((c= get_token(*pn + 2)->symbol) == ']' || c=='+' || c=='-')
+	) {
+		/* A base register expression. */
+		base= new_expr();
+		base->operator= 'B';
+		base->name= copystr(t->name);
+		(*pn)+= c == ']' ? 3 : 2;
+	} else {
+		/* No base register expression. */
+		base= nil;
+	}
+
+	/* +offset]? -offset]? */
+	if (offset == nil
+		&& (c == '+' || c == '-')
+		&& (t= get_token(*pn + 1))->type == T_WORD
+		&& !isregister(t->name)
+	) {
+		(*pn)++;
+		if ((offset= bas_get_C_expression(pn)) == nil) return nil;
+		if (get_token(*pn)->symbol != ']') {
+			parse_err(1, t, "operand syntax error\n");
+			del_expr(offset);
+			del_expr(base);
+			return nil;
+		}
+		(*pn)++;
+		c= 0;
+	}
+
+	/* [index*scale]? +index*scale]? */
+	if (c == '+' || get_token(*pn)->symbol == '[') {
+		/* An index most likely. */
+		token_t *m= nil;
+
+		if (!(		/* This must be true: */
+			(t= get_token(*pn + 1))->type == T_WORD
+			&& isregister(t->name)
+			&& (get_token(*pn + 2)->symbol == ']' || (
+				get_token(*pn + 2)->symbol == '*'
+				&& (m= get_token(*pn + 3))->type == T_WORD
+				&& strchr("1248", m->name[0]) != nil
+				&& m->name[1] == 0
+				&& get_token(*pn + 4)->symbol == ']'
+			))
+		)) {
+			/* Alas it isn't */
+			parse_err(1, t, "operand syntax error\n");
+			del_expr(offset);
+			del_expr(base);
+			return nil;
+		}
+		/* Found an index. */
+		index= new_expr();
+		index->operator= m == nil ? '1' : m->name[0];
+		index->name= copystr(t->name);
+		(*pn)+= (m == nil ? 3 : 5);
+	} else {
+		/* No index. */
+		index= nil;
+	}
+
+	if (base == nil && index == nil) {
+		/* Return a lone offset as is. */
+		e= offset;
+
+		/* Lone registers tell operand size. */
+		if (offset->operator == 'W' && isregister(offset->name)) {
+			switch (isregister(offset->name)) {
+			case 1:	optype= BYTE; break;
+			case 2:	optype= use16() ? WORD : OWORD; break;
+			case 4:	optype= use32() ? WORD : OWORD; break;
+			}
+			if (op_idx < arraysize(optypes))
+				optypes[op_idx++]= optype;
+		}
+	} else {
+		e= new_expr();
+		e->operator= 'O';
+		e->left= offset;
+		e->middle= base;
+		e->right= index;
+	}
+	return e;
+}
+
+static expression_t *bas_get_oplist(int *pn)
+/* Get a comma (or colon for jmpf and callf) separated list of instruction
+ * operands.
+ */
+{
+	expression_t *e, *o1, *o2;
+	token_t *t;
+
+	if ((e= bas_get_operand(pn)) == nil) return nil;
+
+	if ((t= get_token(*pn))->symbol == ',' || t->symbol == ':') {
+		o1= e;
+		(*pn)++;
+		if ((o2= bas_get_oplist(pn)) == nil) {
+			del_expr(o1);
+			return nil;
+		}
+		e= new_expr();
+		e->operator= ',';
+		e->left= o1;
+		e->right= o2;
+	}
+	return e;
+}
+
+static asm86_t *bas_get_statement(void)
+/* Get a pseudo op or machine instruction with arguments. */
+{
+	token_t *t= get_token(0);
+	asm86_t *a;
+	mnemonic_t *m;
+	int n;
+	int prefix_seen;
+
+
+	assert(t->type == T_WORD);
+
+	if (strcmp(t->name, ".sect") == 0) {
+		/* .sect .text etc.  Accept only four segment names. */
+		skip_token(1);
+		t= get_token(0);
+		if (t->type != T_WORD || (
+			strcmp(t->name, ".text") != 0
+			&& strcmp(t->name, ".rom") != 0
+			&& strcmp(t->name, ".data") != 0
+			&& strcmp(t->name, ".bss") != 0
+			&& strcmp(t->name, ".end") != 0
+		)) {
+			parse_err(1, t, "weird section name to .sect\n");
+			return nil;
+		}
+	}
+	a= new_asm86();
+
+	/* Process instruction prefixes. */
+	for (prefix_seen= 0;; prefix_seen= 1) {
+		if (strcmp(t->name, "rep") == 0
+			|| strcmp(t->name, "repe") == 0
+			|| strcmp(t->name, "repne") == 0
+			|| strcmp(t->name, "repz") == 0
+			|| strcmp(t->name, "repnz") == 0
+		) {
+			if (a->rep != ONCE) {
+				parse_err(1, t,
+					"can't have more than one rep\n");
+			}
+			switch (t->name[3]) {
+			case 0:		a->rep= REP;	break;
+			case 'e':
+			case 'z':	a->rep= REPE;	break;
+			case 'n':	a->rep= REPNE;	break;
+			}
+		} else
+		if (strcmp(t->name, "seg") == 0
+					&& get_token(1)->type == T_WORD) {
+			if (a->seg != DEFSEG) {
+				parse_err(1, t,
+				"can't have more than one segment prefix\n");
+			}
+			switch (get_token(1)->name[0]) {
+			case 'c':	a->seg= CSEG;	break;
+			case 'd':	a->seg= DSEG;	break;
+			case 'e':	a->seg= ESEG;	break;
+			case 'f':	a->seg= FSEG;	break;
+			case 'g':	a->seg= GSEG;	break;
+			case 's':	a->seg= SSEG;	break;
+			}
+			skip_token(1);
+		} else
+		if (!prefix_seen) {
+			/* No prefix here, get out! */
+			break;
+		} else {
+			/* No more prefixes, next must be an instruction. */
+			if (t->type != T_WORD
+				|| (m= search_mnem(t->name)) == nil
+				|| m->optype == PSEUDO
+			) {
+				parse_err(1, t,
+		"machine instruction expected after instruction prefix\n");
+				del_asm86(a);
+				return nil;
+			}
+			break;
+		}
+
+		/* Skip the prefix and extra newlines. */
+		do {
+			skip_token(1);
+		} while ((t= get_token(0))->symbol == ';');
+	}
+
+	/* All the readahead being done upsets the line counter. */
+	a->line= t->line;
+
+	/* Read a machine instruction or pseudo op. */
+	if ((m= search_mnem(t->name)) == nil) {
+		parse_err(1, t, "unknown instruction '%s'\n", t->name);
+		del_asm86(a);
+		return nil;
+	}
+	a->opcode= m->opcode;
+	a->optype= m->optype;
+	if (a->opcode == CBW || a->opcode == CWD) {
+		a->optype= (strcmp(t->name, "cbw") == 0
+		    || strcmp(t->name, "cwd") == 0) == use16() ? WORD : OWORD;
+	}
+	for (op_idx= 0; op_idx < arraysize(optypes); op_idx++)
+		optypes[op_idx]= m->optype;
+	op_idx= 0;
+
+	n= 1;
+	if (get_token(1)->symbol != ';'
+				&& (a->args= bas_get_oplist(&n)) == nil) {
+		del_asm86(a);
+		return nil;
+	}
+
+	if (m->optype == WORD) {
+		/* Does one of the operands overide the optype? */
+		for (op_idx= 0; op_idx < arraysize(optypes); op_idx++) {
+			if (optypes[op_idx] != m->optype)
+				a->optype= optypes[op_idx];
+		}
+	}
+
+	if (get_token(n)->symbol != ';') {
+		parse_err(1, t, "garbage at end of instruction\n");
+		del_asm86(a);
+		return nil;
+	}
+	switch (a->opcode) {
+	case DOT_ALIGN:
+		/* Restrict .align to have a single numeric argument, some
+		 * assemblers think of the argument as a power of two, so
+		 * we need to be able to change the value.
+		 */
+		if (strcmp(t->name, ".even") == 0 && a->args == nil) {
+			/* .even becomes .align 2. */
+			expression_t *e;
+			a->args= e= new_expr();
+			e->operator= 'W';
+			e->name= copystr("2");
+			e->len= 2;
+		}
+		if (a->args == nil || a->args->operator != 'W'
+					|| !isanumber(a->args->name)) {
+			parse_err(1, t,
+			  ".align is restricted to one numeric argument\n");
+			del_asm86(a);
+			return nil;
+		}
+		break;
+	case MOVSX:
+	case MOVZX:
+		/* Types of both operands tell the instruction type. */
+		a->optype= optypes[0];
+		if (optypes[1] == BYTE) {
+			a->opcode= a->opcode == MOVSX ? MOVSXB : MOVZXB;
+		}
+		break;
+	case SAL:
+	case SAR:
+	case SHL:
+	case SHR:
+	case RCL:
+	case RCR:
+	case ROL:
+	case ROR:
+		/* Only the first operand tells the operand size. */
+		a->optype= optypes[0];
+		break;
+	default:;
+	}
+	skip_token(n+1);
+	return a;
+}
+
+asm86_t *bas_get_instruction(void)
+{
+	asm86_t *a= nil;
+	expression_t *e;
+	token_t *t;
+
+	while ((t= get_token(0))->symbol == ';')
+		skip_token(1);
+
+	if (t->type == T_EOF) return nil;
+
+	if (t->symbol == '#') {
+		/* Preprocessor line and file change. */
+
+		if ((t= get_token(1))->type != T_WORD || !isanumber(t->name)
+			|| get_token(2)->type != T_STRING
+		) {
+			parse_err(1, t, "file not preprocessed?\n");
+			zap();
+		} else {
+			set_file(get_token(2)->name,
+				strtol(get_token(1)->name, nil, 0) - 1);
+
+			/* GNU CPP adds extra cruft, simply zap the line. */
+			zap();
+		}
+		a= bas_get_instruction();
+	} else
+	if (t->type == T_WORD && get_token(1)->symbol == ':') {
+		/* A label definition. */
+		a= new_asm86();
+		a->line= t->line;
+		a->opcode= DOT_LABEL;
+		a->optype= PSEUDO;
+		a->args= e= new_expr();
+		e->operator= ':';
+		e->name= copystr(t->name);
+		skip_token(2);
+	} else
+	if (t->type == T_WORD && get_token(1)->symbol == '=') {
+		int n= 2;
+
+		if ((e= bas_get_C_expression(&n)) == nil) {
+			zap();
+			a= bas_get_instruction();
+		} else
+		if (get_token(n)->symbol != ';') {
+			parse_err(1, t, "garbage after assignment\n");
+			zap();
+			a= bas_get_instruction();
+		} else {
+			a= new_asm86();
+			a->line= t->line;
+			a->opcode= DOT_EQU;
+			a->optype= PSEUDO;
+			a->args= new_expr();
+			a->args->operator= '=';
+			a->args->name= copystr(t->name);
+			a->args->middle= e;
+			skip_token(n+1);
+		}
+	} else
+	if (t->type == T_WORD && get_token(1)->type == T_WORD
+				&& strcmp(get_token(1)->name, "lcomm") == 0) {
+		/* Local common block definition. */
+		int n= 2;
+
+		if ((e= bas_get_C_expression(&n)) == nil) {
+			zap();
+			a= bas_get_instruction();
+		} else
+		if (get_token(n)->symbol != ';') {
+			parse_err(1, t, "garbage after lcomm\n");
+			zap();
+			a= bas_get_instruction();
+		} else {
+			a= new_asm86();
+			a->line= t->line;
+			a->opcode= DOT_LCOMM;
+			a->optype= PSEUDO;
+			a->args= new_expr();
+			a->args->operator= ',';
+			a->args->right= e;
+			a->args->left= e= new_expr();
+			e->operator= 'W';
+			e->name= copystr(t->name);
+			e->len= strlen(e->name)+1;
+			skip_token(n+1);
+		}
+	} else
+	if (t->type == T_WORD) {
+		if ((a= bas_get_statement()) == nil) {
+			zap();
+			a= bas_get_instruction();
+		}
+	} else {
+		parse_err(1, t, "syntax error\n");
+		zap();
+		a= bas_get_instruction();
+	}
+	if (a->optype == OWORD) {
+		a->optype= WORD;
+		a->oaz|= OPZ;
+	}
+	return a;
+}
Index: /trunk/minix/commands/i386/asmconv/parse_gnu.c
===================================================================
--- /trunk/minix/commands/i386/asmconv/parse_gnu.c	(revision 9)
+++ /trunk/minix/commands/i386/asmconv/parse_gnu.c	(revision 9)
@@ -0,0 +1,879 @@
+/*	parse_ack.c - parse GNU assembly		Author: R.S. Veldema
+ *							 <rveldema@cs.vu.nl>
+ *								26 Aug 1996
+ */
+#define nil 0
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+#include "asmconv.h"
+#include "token.h"
+#include "asm86.h"
+#include "languages.h"
+
+typedef struct mnemonic {	/* GNU as86 mnemonics translation table. */
+	char		*name;
+	opcode_t	opcode;
+	optype_t	optype;
+} mnemonic_t;
+
+static mnemonic_t mnemtab[] = {			/* This array is sorted. */
+	{ ".align",	DOT_ALIGN,	PSEUDO },
+	{ ".ascii",	DOT_ASCII,	PSEUDO },
+	{ ".asciz",	DOT_ASCIZ,	PSEUDO },
+	{ ".assert",	DOT_ASSERT,	PSEUDO },
+	{ ".base",	DOT_BASE,	PSEUDO },
+	{ ".bss",	DOT_BSS,	PSEUDO },
+	{ ".byte",	DOT_DATA1,	PSEUDO },
+	{ ".comm",	DOT_COMM,	PSEUDO },
+	{ ".data",	DOT_DATA,	PSEUDO },
+	{ ".data1",	DOT_DATA1,	PSEUDO },
+	{ ".data2",	DOT_DATA2,	PSEUDO },
+	{ ".data4",	DOT_DATA4,	PSEUDO },
+	{ ".end",	DOT_END,	PSEUDO },
+	{ ".extern",	DOT_EXTERN,	PSEUDO },
+	{ ".file",	DOT_FILE,	PSEUDO },
+	{ ".globl",	DOT_DEFINE,	PSEUDO },
+	{ ".lcomm",	DOT_LCOMM,	PSEUDO },
+	{ ".line",	DOT_LINE,	PSEUDO },
+	{ ".list",	DOT_LIST,	PSEUDO },
+	{ ".long",	DOT_DATA4,	PSEUDO },
+	{ ".nolist",	DOT_NOLIST,	PSEUDO },
+	{ ".rom",	DOT_ROM,	PSEUDO },
+	{ ".space",	DOT_SPACE,	PSEUDO },
+	{ ".symb",	DOT_SYMB,	PSEUDO },
+	{ ".text",	DOT_TEXT,	PSEUDO },
+	{ ".word",	DOT_DATA2,	PSEUDO },
+	{ "aaa",	AAA,		WORD },
+	{ "aad",	AAD,		WORD },
+	{ "aam",	AAM,		WORD },
+	{ "aas",	AAS,		WORD },
+	{ "adcb",	ADC,		BYTE },
+	{ "adcl",	ADC,		WORD },
+	{ "adcw",	ADC,		OWORD },
+	{ "addb",	ADD,		BYTE },
+	{ "addl",	ADD,		WORD },
+	{ "addw",	ADD,		OWORD },
+	{ "andb",	AND,		BYTE },
+	{ "andl",	AND,		WORD },
+	{ "andw",	AND,		OWORD },
+	{ "arpl",	ARPL,		WORD },
+	{ "bound",	BOUND,		WORD },
+	{ "bsf",	BSF,		WORD },
+	{ "bsr",	BSR,		WORD },
+	{ "bswap",	BSWAP,		WORD },
+	{ "btc",	BTC,		WORD },
+	{ "btl",	BT,		WORD },
+	{ "btr",	BTR,		WORD },
+	{ "bts",	BTS,		WORD },
+	{ "btw",	BT,		OWORD },
+	{ "call",	CALL,		JUMP },
+	{ "callf",	CALLF,		JUMP },
+	{ "cbtw",	CBW,		OWORD },
+	{ "cbw",	CBW,		WORD },
+	{ "cdq",	CWD,		WORD },
+	{ "clc",	CLC,		WORD },
+	{ "cld",	CLD,		WORD },
+	{ "cli",	CLI,		WORD },
+	{ "cltd",	CWD,		WORD },
+	{ "clts",	CLTS,		WORD },
+	{ "cmc",	CMC,		WORD },
+	{ "cmpb",	CMP,		BYTE },
+	{ "cmpl",	CMP,		WORD },
+	{ "cmps",	CMPS,		WORD },
+	{ "cmpsb",	CMPS,		BYTE },
+	{ "cmpw",	CMP,		OWORD },
+	{ "cmpxchg",	CMPXCHG,	WORD },
+	{ "cwd",	CWD,		WORD },
+	{ "cwde",	CBW,		WORD },
+	{ "cwtd",	CWD,		OWORD },
+	{ "cwtl",	CBW,		WORD },
+	{ "daa",	DAA,		WORD },
+	{ "das",	DAS,		WORD },
+	{ "decb",	DEC,		BYTE },
+	{ "decl",	DEC,		WORD },
+	{ "decw",	DEC,		OWORD },
+	{ "divb",	DIV,		BYTE },
+	{ "divl",	DIV,		WORD },
+	{ "divw",	DIV,		OWORD },
+	{ "enter",	ENTER,		WORD },
+	{ "f2xm1",	F2XM1,		WORD },
+	{ "fabs",	FABS,		WORD },
+	{ "fadd",	FADD,		WORD },
+	{ "faddd",	FADDD,		WORD },
+	{ "faddp",	FADDP,		WORD },
+	{ "fadds",	FADDS,		WORD },
+	{ "fbld",	FBLD,		WORD },
+	{ "fbstp",	FBSTP,		WORD },
+	{ "fchs",	FCHS,		WORD },
+	{ "fcomd",	FCOMD,		WORD },
+	{ "fcompd",	FCOMPD,		WORD },
+	{ "fcompp",	FCOMPP,		WORD },
+	{ "fcomps",	FCOMPS,		WORD },
+	{ "fcoms",	FCOMS,		WORD },
+	{ "fcos",	FCOS,		WORD },
+	{ "fdecstp",	FDECSTP,	WORD },
+	{ "fdivd",	FDIVD,		WORD },
+	{ "fdivp",	FDIVP,		WORD },
+	{ "fdivrd",	FDIVRD,		WORD },
+	{ "fdivrp",	FDIVRP,		WORD },
+	{ "fdivrs",	FDIVRS,		WORD },
+	{ "fdivs",	FDIVS,		WORD },
+	{ "ffree",	FFREE,		WORD },
+	{ "fiaddl",	FIADDL,		WORD },
+	{ "fiadds",	FIADDS,		WORD },
+	{ "ficom",	FICOM,		WORD },
+	{ "ficomp",	FICOMP,		WORD },
+	{ "fidivl",	FIDIVL,		WORD },
+	{ "fidivrl",	FIDIVRL,	WORD },
+	{ "fidivrs",	FIDIVRS,	WORD },
+	{ "fidivs",	FIDIVS,		WORD },
+	{ "fildl",	FILDL,		WORD },
+	{ "fildq",	FILDQ,		WORD },
+	{ "filds",	FILDS,		WORD },
+	{ "fimull",	FIMULL,		WORD },
+	{ "fimuls",	FIMULS,		WORD },
+	{ "fincstp",	FINCSTP,	WORD },
+	{ "fistl",	FISTL,		WORD },
+	{ "fistp",	FISTP,		WORD },
+	{ "fists",	FISTS,		WORD },
+	{ "fisubl",	FISUBL,		WORD },
+	{ "fisubrl",	FISUBRL,	WORD },
+	{ "fisubrs",	FISUBRS,	WORD },
+	{ "fisubs",	FISUBS,		WORD },
+	{ "fld1",	FLD1,		WORD },
+	{ "fldcw",	FLDCW,		WORD },
+	{ "fldd",	FLDD,		WORD },
+	{ "fldenv",	FLDENV,		WORD },
+	{ "fldl2e",	FLDL2E,		WORD },
+	{ "fldl2t",	FLDL2T,		WORD },
+	{ "fldlg2",	FLDLG2,		WORD },
+	{ "fldln2",	FLDLN2,		WORD },
+	{ "fldpi",	FLDPI,		WORD },
+	{ "flds",	FLDS,		WORD },
+	{ "fldx",	FLDX,		WORD },
+	{ "fldz",	FLDZ,		WORD },
+	{ "fmuld",	FMULD,		WORD },
+	{ "fmulp",	FMULP,		WORD },
+	{ "fmuls",	FMULS,		WORD },
+	{ "fnclex",	FCLEX,		WORD },
+	{ "fninit",	FINIT,		WORD },
+	{ "fnop",	FNOP,		WORD },
+	{ "fnsave",	FSAVE,		WORD },
+	{ "fnstcw",	FSTCW,		WORD },
+	{ "fnstenv",	FSTENV,		WORD },
+	{ "fpatan",	FPATAN,		WORD },
+	{ "fprem",	FPREM,		WORD },
+	{ "fprem1",	FPREM1,		WORD },
+	{ "fptan",	FPTAN,		WORD },
+	{ "frndint",	FRNDINT,	WORD },
+	{ "frstor",	FRSTOR,		WORD },
+	{ "fscale",	FSCALE,		WORD },
+	{ "fsin",	FSIN,		WORD },
+	{ "fsincos",	FSINCOS,	WORD },
+	{ "fsqrt",	FSQRT,		WORD },
+	{ "fstd",	FSTD,		WORD },
+	{ "fstpd",	FSTPD,		WORD },
+	{ "fstps",	FSTPS,		WORD },
+	{ "fstpx",	FSTPX,		WORD },
+	{ "fsts",	FSTS,		WORD },
+	{ "fstsw",	FSTSW,		WORD },
+	{ "fsubd",	FSUBD,		WORD },
+	{ "fsubp",	FSUBP,		WORD },
+	{ "fsubpr",	FSUBPR,		WORD },
+	{ "fsubrd",	FSUBRD,		WORD },
+	{ "fsubrs",	FSUBRS,		WORD },
+	{ "fsubs",	FSUBS,		WORD },
+	{ "ftst",	FTST,		WORD },
+	{ "fucom",	FUCOM,		WORD },
+	{ "fucomp",	FUCOMP,		WORD },
+	{ "fucompp",	FUCOMPP,	WORD },
+	{ "fxam",	FXAM,		WORD },
+	{ "fxch",	FXCH,		WORD },
+	{ "fxtract",	FXTRACT,	WORD },
+	{ "fyl2x",	FYL2X,		WORD },
+	{ "fyl2xp1",	FYL2XP1,	WORD },
+	{ "hlt",	HLT,		WORD },
+	{ "idivb",	IDIV,		BYTE },
+	{ "idivl",	IDIV,		WORD },
+	{ "idivw",	IDIV,		OWORD },
+	{ "imulb",	IMUL,		BYTE },
+	{ "imull",	IMUL,		WORD },
+	{ "imulw",	IMUL,		OWORD },
+	{ "inb",	IN,		BYTE },
+	{ "incb",	INC,		BYTE },
+	{ "incl",	INC,		WORD },
+	{ "incw",	INC,		OWORD },
+	{ "inl",	IN,		WORD },
+	{ "insb",	INS,		BYTE },
+	{ "insl",	INS,		WORD },
+	{ "insw",	INS,		OWORD },
+	{ "int",	INT,		WORD },
+	{ "into",	INTO,		JUMP },
+	{ "invd",	INVD,		WORD },
+	{ "invlpg",	INVLPG,		WORD },
+	{ "inw",	IN,		OWORD },
+	{ "iret",	IRET,		JUMP },
+	{ "iretd",	IRETD,		JUMP },
+	{ "ja",		JA,		JUMP },
+	{ "jae",	JAE,		JUMP },
+	{ "jb",		JB,		JUMP },
+	{ "jbe",	JBE,		JUMP },
+	{ "jc",		JB,		JUMP },
+	{ "jcxz",	JCXZ,		JUMP },
+	{ "je",		JE,		JUMP },
+	{ "jecxz",	JCXZ,		JUMP },
+	{ "jg",		JG,		JUMP },
+	{ "jge",	JGE,		JUMP },
+	{ "jl",		JL,		JUMP },
+	{ "jle",	JLE,		JUMP },
+	{ "jmp",	JMP,		JUMP },
+	{ "jmpf",	JMPF,		JUMP },
+	{ "jna",	JBE,		JUMP },
+	{ "jnae",	JB,		JUMP },
+	{ "jnb",	JAE,		JUMP },
+	{ "jnbe",	JA,		JUMP },
+	{ "jnc",	JAE,		JUMP },
+	{ "jne",	JNE,		JUMP },
+	{ "jng",	JLE,		JUMP },
+	{ "jnge",	JL,		JUMP },
+	{ "jnl",	JGE,		JUMP },
+	{ "jnle",	JG,		JUMP },
+	{ "jno",	JNO,		JUMP },
+	{ "jnp",	JNP,		JUMP },
+	{ "jns",	JNS,		JUMP },
+	{ "jnz",	JNE,		JUMP },
+	{ "jo",		JO,		JUMP },
+	{ "jp",		JP,		JUMP },
+	{ "js",		JS,		JUMP },
+	{ "jz",		JE,		JUMP },
+	{ "lahf",	LAHF,		WORD },
+	{ "lar",	LAR,		WORD },
+	{ "lds",	LDS,		WORD },
+	{ "leal",	LEA,		WORD },
+	{ "leave",	LEAVE,		WORD },
+	{ "leaw",	LEA,		OWORD },
+	{ "les",	LES,		WORD },
+	{ "lfs",	LFS,		WORD },
+	{ "lgdt",	LGDT,		WORD },
+	{ "lgs",	LGS,		WORD },
+	{ "lidt",	LIDT,		WORD },
+	{ "lldt",	LLDT,		WORD },
+	{ "lmsw",	LMSW,		WORD },
+	{ "lock",	LOCK,		WORD },
+	{ "lods",	LODS,		WORD },
+	{ "lodsb",	LODS,		BYTE },
+	{ "loop",	LOOP,		JUMP },
+	{ "loope",	LOOPE,		JUMP },
+	{ "loopne",	LOOPNE,		JUMP },
+	{ "loopnz",	LOOPNE,		JUMP },
+	{ "loopz",	LOOPE,		JUMP },
+	{ "lsl",	LSL,		WORD },
+	{ "lss",	LSS,		WORD },
+	{ "ltr",	LTR,		WORD },
+	{ "movb",	MOV,		BYTE },
+	{ "movl",	MOV,		WORD },
+	{ "movsb",	MOVS,		BYTE },
+	{ "movsbl",	MOVSXB,		WORD },
+	{ "movsbw",	MOVSXB,		OWORD },
+	{ "movsl",	MOVS,		WORD },
+	{ "movsw",	MOVS,		OWORD },
+	{ "movswl",	MOVSX,		WORD },
+	{ "movw",	MOV,		OWORD },
+	{ "movzbl",	MOVZXB,		WORD },
+	{ "movzbw",	MOVZXB,		OWORD },
+	{ "movzwl",	MOVZX,		WORD },
+	{ "mulb",	MUL,		BYTE },
+	{ "mull",	MUL,		WORD },
+	{ "mulw",	MUL,		OWORD },
+	{ "negb",	NEG,		BYTE },
+	{ "negl",	NEG,		WORD },
+	{ "negw",	NEG,		OWORD },
+	{ "nop",	NOP,		WORD },
+	{ "notb",	NOT,		BYTE },
+	{ "notl",	NOT,		WORD },
+	{ "notw",	NOT,		OWORD },
+	{ "orb",	OR,		BYTE },
+	{ "orl",	OR,		WORD },
+	{ "orw",	OR,		OWORD },
+	{ "outb",	OUT,		BYTE },
+	{ "outl",	OUT,		WORD },
+	{ "outsb",	OUTS,		BYTE },
+	{ "outsl",	OUTS,		WORD },
+	{ "outsw",	OUTS,		OWORD },
+	{ "outw",	OUT,		OWORD },
+	{ "pop",	POP,		WORD },
+	{ "popa",	POPA,		WORD },
+	{ "popad",	POPA,		WORD },
+	{ "popf",	POPF,		WORD },
+	{ "popl",	POP,		WORD },
+	{ "push",	PUSH,		WORD },
+	{ "pusha",	PUSHA,		WORD },
+	{ "pushad",	PUSHA,		WORD },
+	{ "pushf",	PUSHF,		WORD },
+	{ "pushl",	PUSH,		WORD },
+	{ "rclb",	RCL,		BYTE },
+	{ "rcll",	RCL,		WORD },
+	{ "rclw",	RCL,		OWORD },
+	{ "rcrb",	RCR,		BYTE },
+	{ "rcrl",	RCR,		WORD },
+	{ "rcrw",	RCR,		OWORD },
+	{ "ret",	RET,		JUMP },
+	{ "retf",	RETF,		JUMP },
+	{ "rolb",	ROL,		BYTE },
+	{ "roll",	ROL,		WORD },
+	{ "rolw",	ROL,		OWORD },
+	{ "rorb",	ROR,		BYTE },
+	{ "rorl",	ROR,		WORD },
+	{ "rorw",	ROR,		OWORD },
+	{ "sahf",	SAHF,		WORD },
+	{ "salb",	SAL,		BYTE },
+	{ "sall",	SAL,		WORD },
+	{ "salw",	SAL,		OWORD },
+	{ "sarb",	SAR,		BYTE },
+	{ "sarl",	SAR,		WORD },
+	{ "sarw",	SAR,		OWORD },
+	{ "sbbb",	SBB,		BYTE },
+	{ "sbbl",	SBB,		WORD },
+	{ "sbbw",	SBB,		OWORD },
+	{ "scasb",	SCAS,		BYTE },
+	{ "scasl",	SCAS,		WORD },
+	{ "scasw",	SCAS,		OWORD },
+	{ "seta",	SETA,		BYTE },
+	{ "setae",	SETAE,		BYTE },
+	{ "setb",	SETB,		BYTE },
+	{ "setbe",	SETBE,		BYTE },
+	{ "sete",	SETE,		BYTE },
+	{ "setg",	SETG,		BYTE },
+	{ "setge",	SETGE,		BYTE },
+	{ "setl",	SETL,		BYTE },
+	{ "setna",	SETBE,		BYTE },
+	{ "setnae",	SETB,		BYTE },
+	{ "setnb",	SETAE,		BYTE },
+	{ "setnbe",	SETA,		BYTE },
+	{ "setne",	SETNE,		BYTE },
+	{ "setng",	SETLE,		BYTE },
+	{ "setnge",	SETL,		BYTE },
+	{ "setnl",	SETGE,		BYTE },
+	{ "setnle",	SETG,		BYTE },
+	{ "setno",	SETNO,		BYTE },
+	{ "setnp",	SETNP,		BYTE },
+	{ "setns",	SETNS,		BYTE },
+	{ "seto",	SETO,		BYTE },
+	{ "setp",	SETP,		BYTE },
+	{ "sets",	SETS,		BYTE },
+	{ "setz",	SETE,		BYTE },
+	{ "sgdt",	SGDT,		WORD },
+	{ "shlb",	SHL,		BYTE },
+	{ "shldl",	SHLD,		WORD },
+	{ "shll",	SHL,		WORD },
+	{ "shlw",	SHL,		OWORD },
+	{ "shrb",	SHR,		BYTE },
+	{ "shrdl",	SHRD,		WORD },
+	{ "shrl",	SHR,		WORD },
+	{ "shrw",	SHR,		OWORD },
+	{ "sidt",	SIDT,		WORD },
+	{ "sldt",	SLDT,		WORD },
+	{ "smsw",	SMSW,		WORD },
+	{ "stc",	STC,		WORD },
+	{ "std",	STD,		WORD },
+	{ "sti",	STI,		WORD },
+	{ "stosb",	STOS,		BYTE },
+	{ "stosl",	STOS,		WORD },
+	{ "stosw",	STOS,		OWORD },
+	{ "str",	STR,		WORD },
+	{ "subb",	SUB,		BYTE },
+	{ "subl",	SUB,		WORD },
+	{ "subw",	SUB,		OWORD },
+	{ "testb",	TEST,		BYTE },
+	{ "testl",	TEST,		WORD },
+	{ "testw",	TEST,		OWORD },
+	{ "verr",	VERR,		WORD },
+	{ "verw",	VERW,		WORD },
+	{ "wait",	WAIT,		WORD },
+	{ "wbinvd",	WBINVD,		WORD },
+	{ "xadd",	XADD,		WORD },
+	{ "xchgb",	XCHG,		BYTE },
+	{ "xchgl",	XCHG,		WORD },
+	{ "xchgw",	XCHG,		OWORD },
+	{ "xlat",	XLAT,		WORD },
+	{ "xorb",	XOR,		BYTE },
+	{ "xorl",	XOR,		WORD },
+	{ "xorw",	XOR,		OWORD },
+};
+
+void gnu_parse_init(char *file)
+/* Prepare parsing of an GNU assembly file. */
+{
+	tok_init(file, '#');
+}
+
+static void zap(void)
+/* An error, zap the rest of the line. */
+{
+	token_t *t;
+
+	while ((t= get_token(0))->type != T_EOF && t->symbol != ';')
+		skip_token(1);
+}
+
+static mnemonic_t *search_mnem(char *name)
+/* Binary search for a mnemonic.  (That's why the table is sorted.) */
+{
+	int low, mid, high;
+	int cmp;
+	mnemonic_t *m;
+
+	low= 0;
+	high= arraysize(mnemtab)-1;
+	while (low <= high) {
+		mid= (low + high) / 2;
+		m= &mnemtab[mid];
+
+		if ((cmp= strcmp(name, m->name)) == 0) return m;
+
+		if (cmp < 0) high= mid-1; else low= mid+1;
+	}
+	return nil;
+}
+
+static expression_t *gnu_get_C_expression(int *pn)
+/* Read a "C-like" expression.  Note that we don't worry about precedence,
+ * the expression is printed later like it is read.  If the target language
+ * does not have all the operators (like ~) then this has to be repaired by
+ * changing the source file.  (No problem, you still have one source file
+ * to maintain, not two.)
+ */
+{
+	expression_t *e, *a1, *a2;
+	token_t *t;
+
+	if ((t= get_token(*pn))->symbol == '(') {
+		/* ( expr ): grouping. */
+		(*pn)++;
+		if ((a1= gnu_get_C_expression(pn)) == nil) return nil;
+		if (get_token(*pn)->symbol != ')') {
+			parse_err(1, t, "missing )\n");
+			del_expr(a1);
+			return nil;
+		}
+		(*pn)++;
+		e= new_expr();
+		e->operator= '[';
+		e->middle= a1;
+	} else
+	if (t->type == T_WORD || t->type == T_STRING) {
+		/* Label, number, or string. */
+		e= new_expr();
+		e->operator= t->type == T_WORD ? 'W' : 'S';
+		e->name= allocate(nil, (t->len+1) * sizeof(e->name[0]));
+		memcpy(e->name, t->name , t->len+1);
+		e->len= t->len;
+		(*pn)++;
+	} else
+	if (t->symbol == '+' || t->symbol == '-' || t->symbol == '~') {
+		/* Unary operator. */
+		(*pn)++;
+		if ((a1= gnu_get_C_expression(pn)) == nil) return nil;
+		e= new_expr();
+		e->operator= t->symbol;
+		e->middle= a1;
+	} else {
+		parse_err(1, t, "expression syntax error\n");
+		return nil;
+	}
+
+	switch ((t= get_token(*pn))->symbol) {
+	case '%': 
+	case '+':
+	case '-':
+	case '*':
+	case '/':
+	case '&':
+	case '|':
+	case '^':
+	case S_LEFTSHIFT:
+	case S_RIGHTSHIFT:
+		(*pn)++;
+		a1= e;
+		if ((a2= gnu_get_C_expression(pn)) == nil) {
+			del_expr(a1);
+			return nil;
+		}
+		e= new_expr();
+		e->operator= t->symbol;
+		e->left= a1;
+		e->right= a2;
+	}
+	return e;
+}
+
+static expression_t *gnu_get_operand(int *pn, int deref)
+/* Get something like: $immed, memory, offset(%base,%index,scale), or simpler. */
+{
+	expression_t *e, *offset, *base, *index;
+	token_t *t;
+	int c;
+
+	if (get_token(*pn)->symbol == '$') {
+		/* An immediate value. */
+		(*pn)++;
+		return gnu_get_C_expression(pn);
+	}
+
+	if (get_token(*pn)->symbol == '*') {
+		/* Indirection. */
+		(*pn)++;
+		if ((offset= gnu_get_operand(pn, deref)) == nil) return nil;
+		e= new_expr();
+		e->operator= '(';
+		e->middle= offset;
+		return e;
+	}
+
+	if ((get_token(*pn)->symbol == '%')
+		&& (t= get_token(*pn + 1))->type == T_WORD
+		&& isregister(t->name)
+	) {
+		/* A register operand. */
+		(*pn)+= 2;
+		e= new_expr();
+		e->operator= 'W';
+		e->name= copystr(t->name);
+		return e;
+	}
+
+	/* Offset? */
+	if (get_token(*pn)->symbol != '('
+				|| get_token(*pn + 1)->symbol != '%') {
+		/* There is an offset. */
+		if ((offset= gnu_get_C_expression(pn)) == nil) return nil;
+	} else {
+		/* No offset. */
+		offset= nil;
+	}
+
+	/* (%base,%index,scale) ? */
+	base= index= nil;
+	if (get_token(*pn)->symbol == '(') {
+		(*pn)++;
+
+		/* %base ? */
+		if (get_token(*pn)->symbol == '%'
+			&& (t= get_token(*pn + 1))->type == T_WORD
+			&& isregister(t->name)
+		) {
+			/* A base register expression. */
+			base= new_expr();
+			base->operator= 'B';
+			base->name= copystr(t->name);
+			(*pn)+= 2;
+		}
+
+		if (get_token(*pn)->symbol == ',') (*pn)++;
+
+		/* %index ? */
+		if (get_token(*pn)->symbol == '%'
+			&& (t= get_token(*pn + 1))->type == T_WORD
+			&& isregister(t->name)
+		) {
+			/* A index register expression. */
+			index= new_expr();
+			index->operator= '1';		/* for now */
+			index->name= copystr(t->name);
+			(*pn)+= 2;
+		}
+
+		if (get_token(*pn)->symbol == ',') (*pn)++;
+
+		/* scale ? */
+		if ((base != nil || index != nil)
+			&& (t= get_token(*pn))->type == T_WORD
+			&& strchr("1248", t->name[0]) != nil
+			&& t->name[1] == 0
+		) {		
+			if (index == nil) {
+				/* Base is really an index register. */
+				index= base;
+				base= nil;
+			}
+			index->operator= t->name[0];
+			(*pn)++;
+		}
+
+		if (get_token(*pn)->symbol == ')') {
+			/* Ending paren. */
+			(*pn)++;
+		} else {
+			/* Alas. */
+			parse_err(1, t, "operand syntax error\n");
+			del_expr(offset);
+			del_expr(base);
+			del_expr(index);
+			return nil;
+		}
+	}
+
+	if (base == nil && index == nil) {
+		if (deref) {
+			/* Return a lone offset as (offset). */
+			e= new_expr();
+			e->operator= '(';
+			e->middle= offset;
+		} else {
+			/* Return a lone offset as is. */
+			e= offset;
+		}
+	} else {
+		e= new_expr();
+		e->operator= 'O';
+		e->left= offset;
+
+		e->middle= base;
+		e->right= index;
+	}
+	return e;
+}
+
+static expression_t *gnu_get_oplist(int *pn, int deref)
+/* Get a comma (or colon for jmpf and callf) separated list of instruction
+ * operands.
+ */
+{
+	expression_t *e, *o1, *o2;
+	token_t *t;
+
+	if ((e= gnu_get_operand(pn, deref)) == nil) return nil;
+
+	if ((t= get_token(*pn))->symbol == ',' || t->symbol == ':') {
+		o1= e;
+		(*pn)++;
+		if ((o2= gnu_get_oplist(pn, deref)) == nil) {
+			del_expr(o1);
+			return nil;
+		}
+		e= new_expr();
+		e->operator= ',';
+		e->left= o1;
+		e->right= o2;
+	}
+	return e;
+}
+
+
+static asm86_t *gnu_get_statement(void)
+/* Get a pseudo op or machine instruction with arguments. */
+{
+	token_t *t= get_token(0);
+	asm86_t *a;
+	mnemonic_t *m;
+	int n;
+	int prefix_seen;
+	int deref;
+
+	assert(t->type == T_WORD);
+
+	a= new_asm86();
+
+	/* Process instruction prefixes. */
+	for (prefix_seen= 0;; prefix_seen= 1) {
+		if (strcmp(t->name, "rep") == 0
+			|| strcmp(t->name, "repe") == 0
+			|| strcmp(t->name, "repne") == 0
+			|| strcmp(t->name, "repz") == 0
+			|| strcmp(t->name, "repnz") == 0
+		) {
+			if (a->rep != ONCE) {
+				parse_err(1, t,
+					"can't have more than one rep\n");
+			}
+			switch (t->name[3]) {
+			case 0:		a->rep= REP;	break;
+			case 'e':
+			case 'z':	a->rep= REPE;	break;
+			case 'n':	a->rep= REPNE;	break;
+			}
+		} else
+		if (!prefix_seen) {
+			/* No prefix here, get out! */
+			break;
+		} else {
+			/* No more prefixes, next must be an instruction. */
+			if (t->type != T_WORD
+				|| (m= search_mnem(t->name)) == nil
+				|| m->optype == PSEUDO
+			) {
+				parse_err(1, t,
+		"machine instruction expected after instruction prefix\n");
+				del_asm86(a);
+				return nil;
+			}
+			break;
+		}
+
+		/* Skip the prefix and extra newlines. */
+		do {
+			skip_token(1);
+		} while ((t= get_token(0))->symbol == ';');
+	}
+
+	/* All the readahead being done upsets the line counter. */
+	a->line= t->line;
+
+	/* Read a machine instruction or pseudo op. */
+	if ((m= search_mnem(t->name)) == nil) {
+		parse_err(1, t, "unknown instruction '%s'\n", t->name);
+		del_asm86(a);
+		return nil;
+	}
+	a->opcode= m->opcode;
+	a->optype= m->optype;
+	a->oaz= 0;
+	if (a->optype == OWORD) {
+		a->oaz|= OPZ;
+		a->optype= WORD;
+	}
+
+	switch (a->opcode) {
+	case IN:
+	case OUT:
+	case INT:
+		deref= 0;
+		break;
+	default:
+		deref= (a->optype >= BYTE);
+	}
+	n= 1;
+	if (get_token(1)->symbol != ';'
+			&& (a->args= gnu_get_oplist(&n, deref)) == nil) {
+		del_asm86(a);
+		return nil;
+	}
+	if (get_token(n)->symbol != ';') {
+		parse_err(1, t, "garbage at end of instruction\n");
+		del_asm86(a);
+		return nil;
+	}
+	if (!is_pseudo(a->opcode)) {
+		/* GNU operand order is the other way around. */
+		expression_t *e, *t;
+
+		e= a->args;
+		while (e != nil && e->operator == ',') {
+			t= e->right; e->right= e->left; e->left= t;
+			e= e->left;
+		}
+	}
+	switch (a->opcode) {
+	case DOT_ALIGN:
+		/* Delete two argument .align, because ACK can't do it.
+		 * Raise 2 to the power of .align's argument.
+		 */
+		if (a->args == nil || a->args->operator != 'W') {	
+			del_asm86(a);
+			return nil;
+		}
+		if (a->args != nil && a->args->operator == 'W'
+			&& isanumber(a->args->name)
+		) {	
+			unsigned n;
+			char num[sizeof(int) * CHAR_BIT / 3 + 1];
+
+			n= 1 << strtoul(a->args->name, nil, 0);
+			sprintf(num, "%u", n);
+			deallocate(a->args->name);
+			a->args->name= copystr(num);
+		}
+		break;
+	case JMPF:
+	case CALLF:
+		/*FALL THROUGH*/
+	case JMP:
+	case CALL:
+		break;
+	default:;
+	}
+	skip_token(n+1);
+	return a;
+}
+
+
+asm86_t *gnu_get_instruction(void)
+{
+	asm86_t *a= nil;
+	expression_t *e;
+	token_t *t;
+
+	while ((t= get_token(0))->symbol == ';' || t->symbol == '/') {
+		zap();		/* if a comment started by a '/' */
+		skip_token(1);
+	}
+
+	if (t->type == T_EOF) return nil;
+
+	if (t->symbol == '#') {
+		/* Preprocessor line and file change. */
+
+		if ((t= get_token(1))->type != T_WORD || !isanumber(t->name)
+			|| get_token(2)->type != T_STRING
+		) {
+			parse_err(1, t, "file not preprocessed?\n");
+			zap();
+		} else {
+			set_file(get_token(2)->name,
+				strtol(get_token(1)->name, nil, 0) - 1);
+
+			/* GNU CPP adds extra cruft, simply zap the line. */
+			zap();
+		}
+		a= gnu_get_instruction();
+	} else
+	if (t->type == T_WORD && get_token(1)->symbol == ':') {
+		/* A label definition. */
+
+		a= new_asm86();
+		a->line= t->line;
+		a->opcode= DOT_LABEL;
+		a->optype= PSEUDO;
+		a->args= e= new_expr();
+		e->operator= ':';
+		e->name= copystr(t->name);
+		skip_token(2);
+	} else
+	if (t->type == T_WORD && get_token(1)->symbol == '=') {
+		int n= 2;
+
+		if ((e= gnu_get_C_expression(&n)) == nil) {
+			zap();
+			a= gnu_get_instruction();
+		} else
+		if (get_token(n)->symbol != ';') {
+			parse_err(1, t, "garbage after assignment\n");
+			zap();
+			a= gnu_get_instruction();
+		} else {
+			a= new_asm86();
+			a->line= t->line;
+			a->opcode= DOT_EQU;
+			a->optype= PSEUDO;
+			a->args= new_expr();
+			a->args->operator= '=';
+			a->args->name= copystr(t->name);
+			a->args->middle= e;
+			skip_token(n+1);
+		}
+	} else
+	if (t->type == T_WORD) {
+		if ((a= gnu_get_statement()) == nil) {
+			zap();
+			a= gnu_get_instruction();
+		}
+	} else {
+		parse_err(1, t, "syntax error\n");
+		zap();
+		a= gnu_get_instruction();
+	}
+	return a;
+}
Index: /trunk/minix/commands/i386/asmconv/syntax.ack
===================================================================
--- /trunk/minix/commands/i386/asmconv/syntax.ack	(revision 9)
+++ /trunk/minix/commands/i386/asmconv/syntax.ack	(revision 9)
@@ -0,0 +1,107 @@
+asmprog:
+	comment ?
+	statement
+	asmprog ; asmprog
+	asmprog comment ? \n asmprog
+
+letter:
+	[._a-zA-Z]
+
+digit:
+	[0-9]
+
+identifier:
+	letter (letter | digit)*
+	digit [bf]
+
+string:
+	'C-like string sequence'
+	"C-like string sequence"
+
+number:
+	C-like number
+
+comment:
+	! .*
+
+statement:
+	label-definition statement
+	empty
+	assignment
+	instruction
+	pseudo-instruction
+
+label-definition:
+	identifier :
+	digit :
+
+assignment:
+	identifier = expression
+
+instruction:
+	iX86-instruction
+
+pseudo-instruction:
+	.extern identifier (, identifier)*
+	.define identifier (, identifier)*
+	.data1 expression (, expression)*
+	.data2 expression (, expression)*
+	.data4 expression (, expression)*
+	.ascii string
+	.asciz string
+	.align expression
+	.space expression
+	.comm identifier , expression
+	.sect identifier
+	.base expression
+	.assert expression
+	.symb XXX
+	.line XXX
+	.file XXX
+	.nolist
+	.list
+	iX86-pseudo
+
+expression:
+	C-like expression with [ and ] for grouping
+
+iX86-instruction:
+	prefix
+	prefix iX86-instruction
+	identifier
+	identifier iX86operand
+	identifier iX86operand , iX86operand
+	identifier iX86operand : iX86operand
+
+prefix:
+	o16
+	o32
+	a16
+	a32
+	rep
+	repz
+	repnz
+	repe
+	repne
+	cseg | dseg | eseg | fseg | gseg | sseg
+
+iX86operand:
+	register
+	( register )
+	expression
+	( expression )
+	expression ( register )
+	expression ( register * [1248] )
+	expression ? ( register ) ( register )
+	expression ? ( register ) ( register * [1248] )
+
+register:
+	al | bl | cl | dl | ah | bh | ch | dh
+	ax | bx | cx | dx | si | di | bp | sp
+	eax | ebx | ecx | edx | esi | edi | ebp | esp
+	cs | ds | es | fs | gs | ss
+	cr0 | cr1 | cr2 | cr3
+
+iX86-pseudo:
+	.use16
+	.use32
Index: /trunk/minix/commands/i386/asmconv/token.h
===================================================================
--- /trunk/minix/commands/i386/asmconv/token.h	(revision 9)
+++ /trunk/minix/commands/i386/asmconv/token.h	(revision 9)
@@ -0,0 +1,29 @@
+/*	token.h - token definition			Author: Kees J. Bot
+ *								13 Dec 1993
+ */
+
+typedef enum toktype {
+	T_EOF,
+	T_CHAR,
+	T_WORD,
+	T_STRING
+} toktype_t;
+
+typedef struct token {
+	struct token	*next;
+	long		line;
+	toktype_t	type;
+	int		symbol;		/* Single character symbol. */
+	char		*name;		/* Word, number, etc. */
+	size_t		len;		/* Length of string. */
+} token_t;
+
+#define S_LEFTSHIFT	0x100		/* << */
+#define S_RIGHTSHIFT	0x101		/* >> */
+
+void set_file(char *file, long line);
+void get_file(char **file, long *line);
+void parse_err(int err, token_t *where, const char *fmt, ...);
+void tok_init(char *file, int comment);
+token_t *get_token(int n);
+void skip_token(int n);
Index: /trunk/minix/commands/i386/asmconv/tokenize.c
===================================================================
--- /trunk/minix/commands/i386/asmconv/tokenize.c	(revision 9)
+++ /trunk/minix/commands/i386/asmconv/tokenize.c	(revision 9)
@@ -0,0 +1,306 @@
+/*	tokenize.c - split input into tokens		Author: Kees J. Bot
+ *								13 Dec 1993
+ */
+#define nil 0
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "asmconv.h"
+#include "token.h"
+
+static FILE *tf;
+static char *tfile;
+static char *orig_tfile;
+static int tcomment;
+static int tc;
+static long tline;
+static token_t *tq;
+
+static void readtc(void)
+/* Read one character from the input file and put it in the global 'tc'. */
+{
+	static int nl= 0;
+
+	if (nl) tline++;
+	if ((tc= getc(tf)) == EOF && ferror(tf)) fatal(orig_tfile);
+	nl= (tc == '\n');
+}
+
+void set_file(char *file, long line)
+/* Set file name and line number, changed by a preprocessor trick. */
+{
+	deallocate(tfile);
+	tfile= allocate(nil, (strlen(file) + 1) * sizeof(tfile[0]));
+	strcpy(tfile, file);
+	tline= line;
+}
+
+void get_file(char **file, long *line)
+/* Get file name and line number. */
+{
+	*file= tfile;
+	*line= tline;
+}
+
+void parse_err(int err, token_t *t, const char *fmt, ...)
+/* Report a parsing error. */
+{
+	va_list ap;
+
+	fprintf(stderr, "\"%s\", line %ld: ", tfile,
+						t == nil ? tline : t->line);
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	if (err) set_error();
+}
+
+void tok_init(char *file, int comment)
+/* Open the file to tokenize and initialize the tokenizer. */
+{
+	if (file == nil) {
+		file= "stdin";
+		tf= stdin;
+	} else {
+		if ((tf= fopen(file, "r")) == nil) fatal(file);
+	}
+	orig_tfile= file;
+	set_file(file, 1);
+	readtc();
+	tcomment= comment;
+}
+
+static int isspace(int c)
+{
+	return between('\0', c, ' ') && c != '\n';
+}
+
+#define iscomment(c)	((c) == tcomment)
+
+static int isidentchar(int c)
+{
+	return between('a', c, 'z')
+		|| between('A', c, 'Z')
+		|| between('0', c, '9')
+		|| c == '.'
+		|| c == '_'
+		;
+}
+
+static token_t *new_token(void)
+{
+	token_t *new;
+
+	new= allocate(nil, sizeof(*new));
+	new->next= nil;
+	new->line= tline;
+	new->name= nil;
+	new->symbol= -1;
+	return new;
+}
+
+static token_t *get_word(void)
+/* Read one word, an identifier, a number, a label, or a mnemonic. */
+{
+	token_t *w;
+	char *name;
+	size_t i, len;
+
+	i= 0;
+	len= 16;
+	name= allocate(nil, len * sizeof(name[0]));
+
+	while (isidentchar(tc)) {
+		name[i++]= tc;
+		readtc();
+		if (i == len) name= allocate(name, (len*= 2) * sizeof(name[0]));
+	}
+	name[i]= 0;
+	name= allocate(name, (i+1) * sizeof(name[0]));
+	w= new_token();
+	w->type= T_WORD;
+	w->name= name;
+	w->len= i;
+	return w;
+}
+
+static token_t *get_string(void)
+/* Read a single or double quotes delimited string. */
+{
+	token_t *s;
+	int quote;
+	char *str;
+	size_t i, len;
+	int n, j;
+	int seen;
+
+	quote= tc;
+	readtc();
+
+	i= 0;
+	len= 16;
+	str= allocate(nil, len * sizeof(str[0]));
+
+	while (tc != quote && tc != '\n' && tc != EOF) {
+		seen= -1;
+		if (tc == '\\') {
+			readtc();
+			if (tc == '\n' || tc == EOF) break;
+
+			switch (tc) {
+			case 'a':	tc= '\a'; break;
+			case 'b':	tc= '\b'; break;
+			case 'f':	tc= '\f'; break;
+			case 'n':	tc= '\n'; break;
+			case 'r':	tc= '\r'; break;
+			case 't':	tc= '\t'; break;
+			case 'v':	tc= '\v'; break;
+			case 'x':
+				n= 0;
+				for (j= 0; j < 3; j++) {
+					readtc();
+					if (between('0', tc, '9'))
+						tc-= '0' + 0x0;
+					else
+					if (between('A', tc, 'A'))
+						tc-= 'A' + 0xA;
+					else
+					if (between('a', tc, 'a'))
+						tc-= 'a' + 0xa;
+					else {
+						seen= tc;
+						break;
+					}
+					n= n*0x10 + tc;
+				}
+				tc= n;
+				break;
+			default:
+				if (!between('0', tc, '9')) break;
+				n= 0;
+				for (j= 0; j < 3; j++) {
+					if (between('0', tc, '9'))
+						tc-= '0';
+					else {
+						seen= tc;
+						break;
+					}
+					n= n*010 + tc;
+					readtc();
+				}
+				tc= n;
+			}
+		}
+		str[i++]= tc;
+		if (i == len) str= allocate(str, (len*= 2) * sizeof(str[0]));
+
+		if (seen < 0) readtc(); else tc= seen;
+	}
+
+	if (tc == quote) {
+		readtc();
+	} else {
+		parse_err(1, nil, "string contains newline\n");
+	}
+	str[i]= 0;
+	str= allocate(str, (i+1) * sizeof(str[0]));
+	s= new_token();
+	s->type= T_STRING;
+	s->name= str;
+	s->len= i;
+	return s;
+}
+
+static int old_n= 0;		/* To speed up n, n+1, n+2, ... accesses. */
+static token_t **old_ptq= &tq;
+
+token_t *get_token(int n)
+/* Return the n-th token on the input queue. */
+{
+	token_t *t, **ptq;
+
+	assert(n >= 0);
+
+	if (0 && n >= old_n) {
+		/* Go forward from the previous point. */
+		n-= old_n;
+		old_n+= n;
+		ptq= old_ptq;
+	} else {
+		/* Restart from the head of the queue. */
+		old_n= n;
+		ptq= &tq;
+	}
+
+	for (;;) {
+		if ((t= *ptq) == nil) {
+			/* Token queue doesn't have element <n>, read a
+			 * new token from the input stream.
+			 */
+			while (isspace(tc) || iscomment(tc)) {
+				if (iscomment(tc)) {
+					while (tc != '\n' && tc != EOF)
+						readtc();
+				} else {
+					readtc();
+				}
+			}
+
+			if (tc == EOF) {
+				t= new_token();
+				t->type= T_EOF;
+			} else
+			if (isidentchar(tc)) {
+				t= get_word();
+			} else
+			if (tc == '\'' || tc == '"') {
+				t= get_string();
+			} else {
+				if (tc == '\n') tc= ';';
+				t= new_token();
+				t->type= T_CHAR;
+				t->symbol= tc;
+				readtc();
+				if (t->symbol == '<' && tc == '<') {
+					t->symbol= S_LEFTSHIFT;
+					readtc();
+				} else
+				if (t->symbol == '>' && tc == '>') {
+					t->symbol= S_RIGHTSHIFT;
+					readtc();
+				}
+			}
+			*ptq= t;
+		}
+		if (n == 0) break;
+		n--;
+		ptq= &t->next;
+	}
+	old_ptq= ptq;
+	return t;
+}
+
+void skip_token(int n)
+/* Remove n tokens from the input queue.  One is not allowed to skip unread
+ * tokens.
+ */
+{
+	token_t *junk;
+
+	assert(n >= 0);
+
+	while (n > 0) {
+		assert(tq != nil);
+
+		junk= tq;
+		tq= tq->next;
+		deallocate(junk->name);
+		deallocate(junk);
+		n--;
+	}
+	/* Reset the old reference. */
+	old_n= 0;
+	old_ptq= &tq;
+}
Index: /trunk/minix/commands/i386/build
===================================================================
--- /trunk/minix/commands/i386/build	(revision 9)
+++ /trunk/minix/commands/i386/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/i386/mtools-3.9.7/COPYING
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/COPYING	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/COPYING	(revision 9)
@@ -0,0 +1,351 @@
+Copyright (C) 1995 Alain Knaff.
+ You may use, distribute and copy this program according to the terms of the
+GNU General Public License version 2 or later.
+
+ Alain Knaff
+----------------------------------------
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: /trunk/minix/commands/i386/mtools-3.9.7/Makefile
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/Makefile	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/Makefile	(revision 9)
@@ -0,0 +1,399 @@
+# Generated automatically from Makefile.in by configure.
+#
+#       Makefile for Mtools
+#
+# check the Configure file for some examples of device-specific setups
+# Berkeley flavors of Unix should include -DBSD in the CFLAGS.  Pick
+# a lock method... either -DLOCKF, -DFLOCK, or -DFCNTL and put that
+# string in the CFLAGS line below.
+
+# User specified flags
+USERCFLAGS = 
+USERLDFLAGS = -stack 11m
+USERLDLIBS =
+
+MAKEINFO = makeinfo
+TEXI2DVI = texi2dvi
+TEXI2HTML = texi2html
+
+
+# do not edit below this line
+# =============================================================================
+
+SHELL = /bin/sh
+
+top_srcdir=.
+srcdir=.
+
+prefix      = /usr
+exec_prefix = ${prefix}
+bindir      = ${exec_prefix}/bin
+infodir     = ${prefix}/info
+mandir      = ${prefix}/man
+infodir     = ${prefix}/info
+sysconfdir  = /etc
+
+CC         = exec cc -D_MINIX
+CXX        = @CXX@
+MYCFLAGS   = 
+MYCXXFLAGS = 
+CPPFLAGS   = 
+HOST_ID    = -DCPU_i386 -DVENDOR_pc -DOS_Minix 
+DEFS       = -DHAVE_CONFIG_H -DNO_CONFIG $(HOST_ID)
+
+LDFLAGS     = 
+LIBS        = 
+SHLIB       = 
+MACHDEPLIBS = 	
+LN_S        = ln -s
+
+INSTALL         = /usr/bin/install -cs
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA    = ${INSTALL} -m 644
+INSTALL_INFO	= 
+
+.SUFFIXES:
+.SUFFIXES: .o .c
+.SUFFIXES: .o .c
+
+MAN1 = floppyd.1 mattrib.1 mbadblocks.1 mcat.1 mcd.1 mcopy.1 mdel.1 mdeltree.1 mdir.1 \
+mdu.1 mformat.1 mkmanifest.1 mlabel.1 mmd.1 mmount.1 mmove.1 mpartition.1 \
+mrd.1 mread.1 mren.1 mshowfat.1 mtoolstest.1 mtools.1 mtype.1 mzip.1
+MAN1EXT	= 1
+MAN1DIR	= $(mandir)/man${MAN1EXT}
+MAN5	= mtools.5
+MAN5EXT	= 5
+MAN5DIR	= $(mandir)/man${MAN5EXT}
+
+# all files in this directory included in the distribution 
+DIST = \
+COPYING Changelog INSTALL Makefile Makefile.in README Release.notes \
+buffer.c buffer.h codepage.c codepage.h codepages.c config.c \
+config.guess config.h.in config.log config.sub configure configure.in \
+copyfile.c devices.c devices.h dirCache.c dirCache.h directory.c direntry.c \
+expand.c fat.c \
+fat_free.c file.c file.h file_name.c file_read.c files filter.c floppyd.1 \
+floppyd.c floppyd_io.c floppyd_io.h force_io.c fs.h fsP.h \
+getopt.h hash.c htable.h init.c llong.c mainloop.c match.c mattrib.1 \
+mattrib.c mbadblocks.1 mbadblocks.c mcat.1 mcat.c mcd.1 mcd.c mcopy.1 \
+mcopy.c mdel.1 mdel.c mdeltree.1 mdir.1 mdir.c mdu.c mdu.1 mformat.1 \
+mformat.c minfo.c \
+misc.c tty.c scsi.c missFuncs.c mk_direntry.c mkmanifest.1 mkmanifest.c \
+mlabel.1 mlabel.c mmd.1 mmd.c mmount.1 mmount.c mmove.1 mmove.c \
+mpartition.1 mpartition.c mrd.1 \
+mread.1 mren.1 msdos.h mshowfat.1 mtoolstest.1 mtools.1 mtools.5 mtools.c \
+mtools.conf mtools.h mtype.1 nameclash.h patchlevel.c \
+plain_io.c plain_io.h precmd.c privileges.c scripts signal.c stream.c stream.h \
+streamcache.c streamcache.h subdir.c sysincludes.h unixdir.c todo toupper.c \
+vfat.c vfat.h xdf_io.c xdf_io.h
+
+#OBJS1 = buffer.o codepage.o codepages.o config.o copyfile.o devices.o \
+#dirCache.o directory.o direntry.o expand.o fat.o fat_free.o file.o file_name.o \
+#file_read.o filter.o floppyd_io.o force_io.o hash.o init.o llong.o match.o \
+#mainloop.o mattrib.o mbadblocks.o mcat.o mcd.o mcopy.o mdel.o mdir.o \
+#mdoctorfat.o mdu.o \
+#mformat.o minfo.o misc.o missFuncs.o mk_direntry.o mlabel.o mmd.o mmount.o \
+#mmove.o mpartition.o mshowfat.o mzip.o mtools.o patchlevel.o plain_io.o \
+#precmd.o privileges.o scsi.o signal.o stream.o streamcache.o subdir.o \
+#unixdir.o toupper.o tty.o vfat.o xdf_io.o
+
+OBJS1 = buffer.o config.o copyfile.o devices.o \
+dirCache.o directory.o direntry.o expand.o fat.o fat_free.o file.o file_name.o \
+file_read.o filter.o floppyd_io.o force_io.o hash.o init.o llong.o match.o \
+mainloop.o mattrib.o mbadblocks.o mcat.o mcd.o mcopy.o mdel.o mdir.o \
+mdoctorfat.o mdu.o \
+mformat.o minfo.o misc.o missFuncs.o mk_direntry.o mlabel.o mmd.o mmount.o \
+mmove.o mpartition.o mshowfat.o mtools.o patchlevel.o plain_io.o \
+precmd.o privileges.o scsi.o signal.o stream.o streamcache.o subdir.o \
+unixdir.o toupper.o tty.o vfat.o xdf_io.o
+
+OBJS2 = missFuncs.o mkmanifest.o misc.o patchlevel.o
+
+SRCS3 = floppyd.c
+
+OBJS4 = floppyd_installtest.o misc.o expand.o privileges.o
+
+SRCS = buffer.c codepage.c codepages.c config.c copyfile.c devices.c \
+dirCache.c directory.c direntry.c expand.c fat.c fat_free.c file.c file_name.c \
+file_read.c filter.c floppyd_io.c force_io.c hash.c init.c match.c mainloop.c \
+mattrib.c mbadblocks.c mcat.c mcd.c mcopy.c mdel.c mdir.c mdu.c mdoctorfat.c \
+mformat.c minfo.c misc.c \
+missFuncs.c mk_direntry.c mlabel.c mmd.c mmount.c mmove.c mpartition.c \
+mshowfat.c mzip.c mtools.c plain_io.c precmd.c privileges.c scsi.o \
+signal.c stream.c streamcache.c subdir.c unixdir.c toupper.c tty.o vfat.c \
+xdf_io.c mkmanifest.c
+
+
+SCRIPTS = mcheck mxtar uz tgz mcomp
+
+LINKS=mattrib mcat mcd mcopy mdel mdeltree mdir mdu mformat minfo mlabel \
+mmd mmount mmove mpartition mrd mread mren mtype mtoolstest mshowfat \
+mbadblocks mzip
+
+X_CFLAGS = 
+X_LIBS = 
+X_EXTRA_LIBS = 
+X_PRE_LIBS = 
+CFLAGS = $(CPPFLAGS) $(DEFS) $(MYCFLAGS) -I.  -I. $(USERCFLAGS) 
+CXXFLAGS  = $(CPPFLAGS) $(DEFS) $(MYCXXFLAGS) -I.  -I. $(USERCFLAGS) 
+LINK      = $(CC) $(LDFLAGS) $(USERLDFLAGS) 
+ALLLIBS   = $(USERLDLIBS) $(MACHDEPLIBS) $(SHLIB) $(LIBS)
+X_LDFLAGS = $(X_EXTRA_LIBS) $(X_LIBS) $(X_PRE_LIBS) -lXau -lX11 $(LIBS) 
+X_CCFLAGS = $(X_CFLAGS) $(CFLAGS)
+
+all:    mtools
+
+%.o: %.c
+	$(CC) $(CFLAGS) -c $<
+
+#%.o: %.cpp
+#	$(CXX) $(CXXFLAGS) -c $<
+
+mtools: $(OBJS1)
+	$(LINK) $(OBJS1) -o $@ $(ALLLIBS)
+
+mkmanifest: $(OBJS2)
+	$(LINK) $(OBJS2) -o $@ $(ALLLIBS)
+
+floppyd.o: floppyd.c
+	$(CC) $(X_CCFLAGS) -c $<
+
+floppyd: floppyd.o
+	$(LINK) $< -o $@ $(X_LDFLAGS)
+floppyd_installtest: $(OBJS4)
+	$(LINK) $(OBJS4) -o $@ $(ALLLIBS)
+
+
+$(LINKS): mtools
+	rm -f $@ && $(LN_S) mtools $@
+
+mostlyclean:
+	-rm -f *~ *.orig *.o a.out core 2>/dev/null
+
+clean:	mostlyclean
+	-rm -f mtools $(LINKS) floppyd floppyd_installtest mkmanifest *.info* *.dvi *.html 2>/dev/null
+
+
+texclean:
+	-rm mtools.aux mtools.toc mtools.log
+	-rm mtools.cps mtools.pgs mtools.vrs
+	-rm mtools.cp mtools.fn mtools.ky
+	-rm mtools.pg mtools.tp mtools.vr
+
+info: mtools.info
+%.info: %.texi
+	$(MAKEINFO) -I$(srcdir) $< --no-split --output=$@
+
+dvi: mtools.dvi
+%.dvi: %.texi
+	$(TEXI2DVI) $<
+
+ps: mtools.ps
+%.ps: %.dvi
+	dvips -f < $< > $@
+
+pdf: mtools.pdf
+%.pdf: %.ps
+	ps2pdf $< $@
+
+
+html: mtools.html mtools_toc.html
+%.html %_toc.html: %.texi
+	$(TEXI2HTML) $<
+
+# Don't cd, to avoid breaking install-sh references.
+install-info: info
+	$(top_srcdir)/mkinstalldirs $(infodir)
+	if test -f mtools.info; then \
+	  for i in mtools.info*; do \
+	    $(INSTALL_DATA) $$i $(infodir)/$$i; \
+	  done; \
+	else \
+	  for i in $(srcdir)/mtools.info*; do \
+	    $(INSTALL_DATA) $$i $(infodir)/`echo $$i | sed 's|^$(srcdir)/||'`; \
+	  done; \
+	fi; \
+	if [ -n "$(INSTALL_INFO)" ] ; then \
+		if [ -f $(infodir)/dir.info ] ; then \
+			$(INSTALL_INFO) $(infodir)/mtools.info $(infodir)/dir.info; \
+		fi; \
+		if [ -f $(infodir)/dir ] ; then \
+			$(INSTALL_INFO) $(infodir)/mtools.info $(infodir)/dir; \
+		fi; \
+	fi
+
+uninstall-info:
+	cd $(infodir) && rm -f mtools.info*
+
+install:	$(bindir)/mtools
+
+# The manual pages are of such horrible quality that one is better off without
+# them.  (Frankly this whole package is horrible.)  Using -? hopefully gives
+# enough clues for use.  -- kjb
+dontinstall:
+		$(MAN1DIR)/mattrib.1 $(MAN1DIR)/mbadblocks.1 \
+		$(MAN1DIR)/mcd.1 $(MAN1DIR)/mcopy.1 $(MAN1DIR)/mdel.1 \
+		$(MAN1DIR)/mdeltree.1 $(MAN1DIR)/mdir.1 $(MAN1DIR)/mdu.1 \
+		$(MAN1DIR)/mformat.1 $(MAN1DIR)/mlabel.1 \
+		$(MAN1DIR)/mmd.1 $(MAN1DIR)/mmove.1 $(MAN1DIR)/mrd.1 \
+		$(MAN1DIR)/mread.1 $(MAN1DIR)/mren.1 \
+		$(MAN1DIR)/mshowfat.1 $(MAN1DIR)/mtools.1 \
+		$(MAN1DIR)/mtype.1 $(MAN1DIR)/mzip.1
+
+$(bindir)/mtools:	mtools
+	install -c $? $@
+
+$(MAN1DIR)/mattrib.1:	mattrib.1
+	install -lc $? $@
+
+$(MAN1DIR)/mbadblocks.1:	mbadblocks.1
+	install -lc $? $@
+
+$(MAN1DIR)/mcd.1:	mcd.1
+	install -lc $? $@
+
+$(MAN1DIR)/mcopy.1:	mcopy.1
+	install -lc $? $@
+
+$(MAN1DIR)/mdel.1:	mdel.1
+	install -lc $? $@
+
+$(MAN1DIR)/mdeltree.1:	mdeltree.1
+	install -lc $? $@
+
+$(MAN1DIR)/mdir.1:	mdir.1
+	install -lc $? $@
+
+$(MAN1DIR)/mdu.1:	mdu.1
+	install -lc $? $@
+
+$(MAN1DIR)/mformat.1:	mformat.1
+	install -lc $? $@
+
+$(MAN1DIR)/mlabel.1:	mlabel.1
+	install -lc $? $@
+
+$(MAN1DIR)/mmd.1:	mmd.1
+	install -lc $? $@
+
+$(MAN1DIR)/mmove.1:	mmove.1
+	install -lc $? $@
+
+$(MAN1DIR)/mrd.1:	mrd.1
+	install -lc $? $@
+
+$(MAN1DIR)/mread.1:	mread.1
+	install -lc $? $@
+
+$(MAN1DIR)/mren.1:	mren.1
+	install -lc $? $@
+
+$(MAN1DIR)/mshowfat.1:	mshowfat.1
+	install -lc $? $@
+
+$(MAN1DIR)/mtools.1:	mtools.1
+	install -lc $? $@
+
+$(MAN1DIR)/mtype.1:	mtype.1
+	install -lc $? $@
+
+$(MAN1DIR)/mzip.1:	mzip.1
+	install -lc $? $@
+
+#install:	$(bindir)/mtools  install-man install-links \
+#		$(bindir)/mkmanifest install-scripts install-info
+#
+#uninstall:	uninstall-bin uninstall-man uninstall-links \
+#		uninstall-scripts
+
+distclean: clean texclean
+	rm -f config.cache config.h config.status config.log Makefile
+maintainer-clean: distclean
+
+
+#$(bindir)/floppyd: floppyd
+#	$(top_srcdir)/mkinstalldirs $(bindir)
+#	$(INSTALL_PROGRAM) floppyd $(bindir)/floppyd
+#
+#$(bindir)/floppyd_installtest: floppyd_installtest
+#	$(top_srcdir)/mkinstalldirs $(bindir)
+#	$(INSTALL_PROGRAM) floppyd_installtest $(bindir)/floppyd_installtest
+#
+#$(bindir)/mtools: mtools
+#	$(top_srcdir)/mkinstalldirs $(bindir)
+#	$(INSTALL_PROGRAM) mtools $(bindir)/mtools
+#
+#$(bindir)/mkmanifest: mkmanifest
+#	$(top_srcdir)/mkinstalldirs $(bindir)
+#	$(INSTALL_PROGRAM) mkmanifest $(bindir)/mkmanifest
+
+#$(ETCDIR)/mtools: mtools.etc
+#	cp mtools.etc $(ETCDIR)/mtools
+
+install-links: $(bindir)/mtools
+	@for j in $(LINKS); do \
+		rm -f $(bindir)/$$j ; \
+		$(LN_S) mtools $(bindir)/$$j ; \
+		echo $(bindir)/$$j ; \
+	done
+
+## "z" is the older version of "gz"; the name is just *too* short
+install-scripts: $(bindir)/mtools
+	@$(top_srcdir)/mkinstalldirs $(bindir)
+	@for j in $(SCRIPTS) ; do \
+		$(INSTALL_PROGRAM) $(srcdir)/scripts/$$j $(bindir)/$$j ; \
+		echo $(bindir)/$$j ; \
+	done
+	rm -f $(bindir)/lz
+	$(LN_S) uz $(bindir)/lz
+
+install-man:
+	@$(top_srcdir)/mkinstalldirs $(MAN1DIR)
+	@for j in $(MAN1); do \
+		$(INSTALL_DATA) $(srcdir)/$$j $(MAN1DIR)/$$j ; \
+		echo $(MAN1DIR)/$$j ; \
+	done
+	@$(top_srcdir)/mkinstalldirs $(MAN5DIR)
+	@for j in $(MAN5); do \
+		$(INSTALL_DATA) $(srcdir)/$$j $(MAN5DIR)/$$j ; \
+		echo $(MAN5DIR)/$$j ; \
+	done
+
+uninstall-bin:
+	@for j in mtools mkmanifest; do \
+		rm -f $(bindir)/$$j ; \
+		echo $(bindir)/$$j ; \
+	done
+
+uninstall-scripts:
+	@for j in $(SCRIPTS); do \
+		rm -f $(bindir)/$$j ; \
+		echo $(bindir)/$$j ; \
+	done
+
+uninstall-man:
+	@for j in $(MAN1); do \
+		rm -f $(MAN1DIR)/$$j ; \
+		echo $(MAN1DIR)/$$j ; \
+	done
+	@for j in $(MAN5); do \
+		rm -f $(MAN5DIR)/$$j ; \
+		echo $(MAN5DIR)/$$j ; \
+	done
+
+uninstall-links:
+	@for j in $(LINKS); \
+		do rm -f $(bindir)/$$j ; \
+		echo $(bindir)/$$j ; \
+	done
+
+depend: $(SRCS)
+	makedepend -- $(CFLAGS) -- $^
+
+check:
+	echo No self tests included
+# check target needed even if empty, in order to make life easyer for
+# automatic tools to install GNU soft
+
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
Index: /trunk/minix/commands/i386/mtools-3.9.7/README
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/README	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/README	(revision 9)
@@ -0,0 +1,53 @@
+Compilation
+-----------
+
+ Type 'make install'.
+
+ This package has been heavily modified for Minix, and then minimized to
+only those files needed for Minix.  Don't use this as a basis for anything
+else, get the original package instead.  -- kjb
+
+Doc
+---
+
+ The most uptodate doc of this package is the texinfo doc. Type 'make
+info' to get online info doc, and 'make dvi ; dvips mtools.dvi' to get
+a printed copy.  The info doc has a concept index.  Make use of it.
+ You may get an info copy using the following command 'make info'.
+This can then be viewed using emacs' info mode, or using a standalone
+info viewer.
+ Man pages are still present, but contain less information, and are
+less uptodate than the texinfo documentation.
+ If you do not have the necessary tools to view the texinfo doc, you
+may also find it on the Workd Wide Web at the following locations:
+  http://mtools.linux.lu/mtools_toc.html
+  http://www.tux.org/pub/knaff/mtools/mtools_toc.html
+
+Compiler
+--------
+
+ Mtools should be compiled with an Ansi compiler, preferably gcc
+
+Authors
+-------
+
+Original code (versions through 2.0.7?) by Emmet P. Gray (Texas, USA), who
+no longer appears to be reachable by Internet e-mail.  Viktor Dukhovni (at
+Princeton, USA) had major input into v2.0.
+
+Since 2.0.7: maintained primarily and until now informally by Alain
+Knaff (Luxembourg) and David Niemi (Reston, Virginia, USA).
+
+Please report bugs to the mtools mailing list at mtools@www.tux.org.
+Before reporting any problems, check whether they have already been
+fixed in the Alpha patches at http://mtools.linux.lu and
+http://www.tux.org/pub/knaff
+
+You may subscribe to the mtools mailing list by sending a message
+containing 'subscribe mtools' in its body to majordomo@www.tux.org
+
+
+Current Status
+--------------
+
+Stable release 3.3.
Index: /trunk/minix/commands/i386/mtools-3.9.7/buffer.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/buffer.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/buffer.c	(revision 9)
@@ -0,0 +1,365 @@
+/*
+ * Buffer read/write module
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "buffer.h"
+
+typedef struct Buffer_t {
+	Class_t *Class;
+	int refs;
+	Stream_t *Next;
+	Stream_t *Buffer;
+	
+	size_t size;     	/* size of read/write buffer */
+	int dirty;	       	/* is the buffer dirty? */
+
+	int sectorSize;		/* sector size: all operations happen
+				 * in multiples of this */
+	int cylinderSize;	/* cylinder size: preferred alignemnt,
+				 * but for efficiency, less data may be read */
+	int ever_dirty;	       	/* was the buffer ever dirty? */
+	int dirty_pos;
+	int dirty_end;
+	mt_off_t current;		/* first sector in buffer */
+	size_t cur_size;		/* the current size */
+	char *buf;		/* disk read/write buffer */
+} Buffer_t;
+
+/*
+ * Flush a dirty buffer to disk.  Resets Buffer->dirty to zero.
+ * All errors are fatal.
+ */
+
+static int _buf_flush(Buffer_t *Buffer)
+{
+	int ret;
+
+	if (!Buffer->Next || !Buffer->dirty)
+		return 0;
+	if(Buffer->current < 0L) {
+		fprintf(stderr,"Should not happen\n");
+		return -1;
+	}
+#ifdef DEBUG
+	fprintf(stderr, "write %08x -- %02x %08x %08x\n",
+		Buffer,
+		(unsigned char) Buffer->buf[0],
+		Buffer->current + Buffer->dirty_pos,
+		Buffer->dirty_end - Buffer->dirty_pos);
+#endif
+
+	ret = force_write(Buffer->Next, 
+			  Buffer->buf + Buffer->dirty_pos,
+			  Buffer->current + Buffer->dirty_pos,
+			  Buffer->dirty_end - Buffer->dirty_pos);
+	if(ret != Buffer->dirty_end - Buffer->dirty_pos) {
+		if(ret < 0)
+			perror("buffer_flush: write");
+		else
+			fprintf(stderr,"buffer_flush: short write\n");
+		return -1;
+	}
+	Buffer->dirty = 0;
+	Buffer->dirty_end = 0;
+	Buffer->dirty_pos = 0;
+	return 0;
+}
+
+static int invalidate_buffer(Buffer_t *Buffer, mt_off_t start)
+{
+	/*fprintf(stderr, "invalidate %x\n", Buffer);*/
+	if(Buffer->sectorSize == 32) {
+		fprintf(stderr, "refreshing directory\n");
+	}
+
+	if(_buf_flush(Buffer) < 0)
+		return -1;
+
+	/* start reading at the beginning of start's sector
+	 * don't start reading too early, or we might not even reach
+	 * start */
+	Buffer->current = ROUND_DOWN(start, Buffer->sectorSize);
+	Buffer->cur_size = 0;
+	return 0;
+}
+
+#undef OFFSET
+#define OFFSET (start - This->current)
+
+typedef enum position_t {
+	OUTSIDE,
+	APPEND,
+	INSIDE,
+	ERROR 
+} position_t;
+
+static position_t isInBuffer(Buffer_t *This, mt_off_t start, size_t *len)
+{
+	if(start >= This->current &&
+	   start < This->current + This->cur_size) {
+		maximize(*len, This->cur_size - OFFSET);
+		return INSIDE;
+	} else if(start == This->current + This->cur_size &&
+		  This->cur_size < This->size &&
+		  *len >= This->sectorSize) {
+		/* append to the buffer for this, three conditions have to
+		 * be met:
+		 *  1. The start falls exactly at the end of the currently
+		 *     loaded data
+		 *  2. There is still space
+		 *  3. We append at least one sector
+		 */
+		maximize(*len, This->size - This->cur_size);
+		*len = ROUND_DOWN(*len, This->sectorSize);
+		return APPEND;
+	} else {
+		if(invalidate_buffer(This, start) < 0)
+			return ERROR;
+		maximize(*len, This->cylinderSize - OFFSET);
+		maximize(*len, This->cylinderSize - This->current % This->cylinderSize);
+		return OUTSIDE;
+	}
+}
+
+static int buf_read(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
+{
+	size_t length;
+	int offset;
+	char *disk_ptr;
+	int ret;
+	DeclareThis(Buffer_t);	
+
+	if(!len)
+		return 0;	
+
+	/*fprintf(stderr, "buf read %x   %x %x\n", Stream, start, len);*/
+	switch(isInBuffer(This, start, &len)) {
+		case OUTSIDE:
+		case APPEND:
+			/* always load until the end of the cylinder */
+			length = This->cylinderSize -
+				(This->current + This->cur_size) % This->cylinderSize;
+			maximize(length, This->size - This->cur_size);
+
+			/* read it! */
+			ret=READS(This->Next,
+				  This->buf + This->cur_size,
+				  This->current + This->cur_size,
+				  length);
+			if ( ret < 0 )
+				return ret;
+			This->cur_size += ret;
+			if (This->current+This->cur_size < start) {
+				fprintf(stderr, "Short buffer fill\n");
+				exit(1);
+			}														  
+			break;
+		case INSIDE:
+			/* nothing to do */
+			break;
+		case ERROR:
+			return -1;
+	}
+
+	offset = OFFSET;
+	disk_ptr = This->buf + offset;
+	maximize(len, This->cur_size - offset);
+	memcpy(buf, disk_ptr, len);
+	return len;
+}
+
+static int buf_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
+{
+	char *disk_ptr;
+	DeclareThis(Buffer_t);	
+	int offset, ret;
+
+	if(!len)
+		return 0;
+
+	This->ever_dirty = 1;
+
+#ifdef DEBUG
+	fprintf(stderr, "buf write %x   %02x %08x %08x -- %08x %08x -- %08x\n", 
+		Stream, (unsigned char) This->buf[0],
+		start, len, This->current, This->cur_size, This->size);
+	fprintf(stderr, "%d %d %d %x %x\n", 
+		start == This->current + This->cur_size,
+		This->cur_size < This->size,
+		len >= This->sectorSize, len, This->sectorSize);
+#endif
+	switch(isInBuffer(This, start, &len)) {
+		case OUTSIDE:
+#ifdef DEBUG
+			fprintf(stderr, "outside\n");
+#endif
+			if(start % This->cylinderSize || 
+			   len < This->sectorSize) {
+				size_t readSize;
+
+				readSize = This->cylinderSize - 
+					This->current % This->cylinderSize;
+
+				ret=READS(This->Next, This->buf, This->current, readSize);
+				/* read it! */
+				if ( ret < 0 )
+					return ret;
+				This->cur_size = ret;
+				/* for dosemu. Autoextend size */
+				if(!This->cur_size) {
+					memset(This->buf,0,readSize);
+					This->cur_size = readSize;
+				}
+				offset = OFFSET;
+				break;
+			}
+			/* FALL THROUGH */
+		case APPEND:
+#ifdef DEBUG
+			fprintf(stderr, "append\n");
+#endif
+			len = ROUND_DOWN(len, This->sectorSize);
+			offset = OFFSET;
+			maximize(len, This->size - offset);
+			This->cur_size += len;
+			if(This->Next->Class->pre_allocate)
+				PRE_ALLOCATE(This->Next,
+							 This->current + This->cur_size);
+			break;
+		case INSIDE:
+			/* nothing to do */
+#ifdef DEBUG
+			fprintf(stderr, "inside\n");
+#endif
+			offset = OFFSET;
+			maximize(len, This->cur_size - offset);
+			break;
+		case ERROR:
+			return -1;
+		default:
+#ifdef DEBUG
+			fprintf(stderr, "Should not happen\n");
+#endif
+			exit(1);
+	}
+
+	disk_ptr = This->buf + offset;
+
+	/* extend if we write beyond end */
+	if(offset + len > This->cur_size) {
+		len -= (offset + len) % This->sectorSize;
+		This->cur_size = len + offset;
+	}
+
+	memcpy(disk_ptr, buf, len);
+	if(!This->dirty || offset < This->dirty_pos)
+		This->dirty_pos = ROUND_DOWN(offset, This->sectorSize);
+	if(!This->dirty || offset + len > This->dirty_end)
+		This->dirty_end = ROUND_UP(offset + len, This->sectorSize);
+	
+	if(This->dirty_end > This->cur_size) {
+		fprintf(stderr, 
+			"Internal error, dirty end too big %x %x %x %d %x\n",
+			This->dirty_end, (unsigned int) This->cur_size, (unsigned int) len, 
+				(int) offset, (int) This->sectorSize);
+		fprintf(stderr, "offset + len + grain - 1 = %x\n",
+				(int) (offset + len + This->sectorSize - 1));
+		fprintf(stderr, "ROUNDOWN(offset + len + grain - 1) = %x\n",
+				(int)ROUND_DOWN(offset + len + This->sectorSize - 1,
+								This->sectorSize));
+		fprintf(stderr, "This->dirty = %d\n", This->dirty);
+		exit(1);
+	}
+
+	This->dirty = 1;
+	return len;
+}
+
+static int buf_flush(Stream_t *Stream)
+{
+	int ret;
+	DeclareThis(Buffer_t);
+
+	if (!This->ever_dirty)
+		return 0;
+	ret = _buf_flush(This);
+	if(ret == 0)
+		This->ever_dirty = 0;
+	return ret;
+}
+
+
+static int buf_free(Stream_t *Stream)
+{
+	DeclareThis(Buffer_t);
+
+	if(This->buf)
+		free(This->buf);
+	This->buf = 0;
+	return 0;
+}
+
+static Class_t BufferClass = {
+	buf_read,
+	buf_write,
+	buf_flush,
+	buf_free,
+	0, /* set_geom */
+	get_data_pass_through, /* get_data */
+	0, /* pre-allocate */
+};
+
+Stream_t *buf_init(Stream_t *Next, int size, 
+		   int cylinderSize, 
+		   int sectorSize)
+{
+	Buffer_t *Buffer;
+	Stream_t *Stream;
+
+
+	if(size % cylinderSize != 0) {
+		fprintf(stderr, "size not multiple of cylinder size\n");
+		exit(1);
+	}
+	if(cylinderSize % sectorSize != 0) {
+		fprintf(stderr, "cylinder size not multiple of sector size\n");
+		exit(1);
+	}
+
+	if(Next->Buffer){
+		Next->refs--;
+		Next->Buffer->refs++;
+		return Next->Buffer;
+	}
+
+	Stream = (Stream_t *) malloc (sizeof(Buffer_t));
+	if(!Stream)
+		return 0;
+	Buffer = (Buffer_t *) Stream;
+	Buffer->buf = malloc(size);
+	if ( !Buffer->buf){
+		Free(Stream);
+		return 0;
+	}
+	Buffer->size = size;
+	Buffer->dirty = 0;
+	Buffer->cylinderSize = cylinderSize;
+	Buffer->sectorSize = sectorSize;
+
+	Buffer->ever_dirty = 0;
+	Buffer->dirty_pos = 0;
+	Buffer->dirty_end = 0;
+	Buffer->current = 0;
+	Buffer->cur_size = 0; /* buffer currently empty */
+
+	Buffer->Next = Next;
+	Buffer->Class = &BufferClass;
+	Buffer->refs = 1;
+	Buffer->Buffer = 0;
+	Buffer->Next->Buffer = (Stream_t *) Buffer;
+	return Stream;
+}
+
Index: /trunk/minix/commands/i386/mtools-3.9.7/buffer.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/buffer.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/buffer.h	(revision 9)
@@ -0,0 +1,11 @@
+#ifndef MTOOLS_BUFFER_H
+#define MTOOLS_BUFFER_H
+
+#include "stream.h"
+
+Stream_t *buf_init(Stream_t *Next, 
+		   int size, 
+		   int cylinderSize,
+		   int sectorSize);
+
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/build
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/build	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+make && make install
Index: /trunk/minix/commands/i386/mtools-3.9.7/codepage.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/codepage.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/codepage.h	(revision 9)
@@ -0,0 +1,35 @@
+typedef struct Codepage_l {
+	int nr;   
+	unsigned char tounix[128];
+} Codepage_t;
+
+
+typedef struct country_l {
+	int country;
+	int codepage;
+	int default_codepage;
+	int to_upper;
+} country_t;
+
+
+#ifndef NO_CONFIG
+void init_codepage(void);
+unsigned char to_dos(unsigned char c);
+void to_unix(char *a, int n);
+#define mstoupper(c)	mstoupper[(c) & 0x7F]
+
+#else /* NO_CONFIG */
+
+/* Imagine a codepage with 128 uppercase letters for the top 128 characters. */
+#define mstoupper(c)	(c)
+#define to_dos(c)	(c)
+#define to_unix(a, n)	((void) 0)
+#define mstoupper(c)	(c)
+#endif
+
+extern Codepage_t *Codepage;
+extern char *mstoupper;
+extern country_t countries[];
+extern unsigned char toucase[][128];
+extern Codepage_t codepages[];
+extern char *country_string;
Index: /trunk/minix/commands/i386/mtools-3.9.7/config.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/config.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/config.c	(revision 9)
@@ -0,0 +1,808 @@
+#include "sysincludes.h"
+#include "mtools.h"
+#include "codepage.h"
+#include "mtoolsPaths.h"
+
+/* global variables */
+/* they are not really harmful here, because there is only one configuration
+ * file per invocations */
+
+#ifndef NO_CONFIG
+
+#define MAX_LINE_LEN 256
+
+/* scanner */
+static char buffer[MAX_LINE_LEN+1]; /* buffer for the whole line */
+static char *pos; /* position in line */
+static char *token; /* last scanned token */
+static int token_length; /* length of the token */
+static FILE *fp; /* file pointer for configuration file */
+static int linenumber; /* current line number. Only used for printing
+						* error messages */
+static int lastTokenLinenumber; /* line numnber for last token */
+static const char *filename; /* current file name. Only used for printing
+			      * error messages */
+static int file_nr=0;
+
+
+static int flag_mask; /* mask of currently set flags */
+
+/* devices */
+static int cur_devs; /* current number of defined devices */
+static int cur_dev; /* device being filled in. If negative, none */
+static int trusted=0; /* is the currently parsed device entry trusted? */
+static int nr_dev; /* number of devices that the current table can hold */
+static int token_nr; /* number of tokens in line */
+static char letters[][2] = { /* drive letter to letter-as-a-string */
+	"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
+	"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
+};
+
+#endif	/* !NO_CONFIG */
+
+struct device *devices; /* the device table */
+
+/* "environment" variables */
+unsigned int mtools_skip_check=0;
+unsigned int mtools_fat_compatibility=0;
+unsigned int mtools_ignore_short_case=0;
+unsigned int mtools_rate_0=0;
+unsigned int mtools_rate_any=0;
+unsigned int mtools_no_vfat=0;
+unsigned int mtools_numeric_tail=1;
+unsigned int mtools_dotted_dir=0;
+unsigned int mtools_twenty_four_hour_clock=1;
+char *mtools_date_string="mm-dd-yyyy";
+char *country_string=0;
+
+#ifndef NO_CONFIG
+
+typedef struct switches_l {
+    const char *name;
+    caddr_t address;
+    enum {
+	T_INT,
+	T_STRING,
+	T_UINT
+    } type;
+} switches_t;
+
+static switches_t switches[] = {
+    { "MTOOLS_LOWER_CASE", (caddr_t) & mtools_ignore_short_case, T_UINT },
+    { "MTOOLS_FAT_COMPATIBILITY", (caddr_t) & mtools_fat_compatibility, T_UINT },
+    { "MTOOLS_SKIP_CHECK", (caddr_t) & mtools_skip_check, T_UINT },
+    { "MTOOLS_NO_VFAT", (caddr_t) & mtools_no_vfat, T_UINT },
+    { "MTOOLS_RATE_0", (caddr_t) &mtools_rate_0, T_UINT },
+    { "MTOOLS_RATE_ANY", (caddr_t) &mtools_rate_any, T_UINT },
+    { "MTOOLS_NAME_NUMERIC_TAIL", (caddr_t) &mtools_numeric_tail, T_UINT },
+    { "MTOOLS_DOTTED_DIR", (caddr_t) &mtools_dotted_dir, T_UINT },
+    { "MTOOLS_TWENTY_FOUR_HOUR_CLOCK", 
+      (caddr_t) &mtools_twenty_four_hour_clock, T_UINT },
+    { "MTOOLS_DATE_STRING",
+      (caddr_t) &mtools_date_string, T_STRING },
+    { "COUNTRY", (caddr_t) &country_string, T_STRING }
+};
+
+typedef struct {
+    const char *name;
+    int flag;
+} flags_t;
+
+static flags_t openflags[] = {
+#ifdef O_SYNC
+    { "sync",		O_SYNC },
+#endif
+#ifdef O_NDELAY
+    { "nodelay",	O_NDELAY },
+#endif
+#ifdef O_EXCL
+    { "exclusive",	O_EXCL },
+#endif
+    { "none", 0 }  /* hack for those compilers that choke on commas
+		    * after the last element of an array */
+};
+
+static flags_t misc_flags[] = {
+#ifdef USE_XDF
+    { "use_xdf",		USE_XDF_FLAG },
+#endif
+    { "scsi",			SCSI_FLAG },
+    { "nolock",			NOLOCK_FLAG },
+    { "mformat_only",	MFORMAT_ONLY_FLAG },
+    { "filter",			FILTER_FLAG },
+    { "privileged",		PRIV_FLAG },
+    { "vold",			VOLD_FLAG },
+    { "remote",			FLOPPYD_FLAG }
+};
+
+static struct {
+    const char *name;
+    signed char fat_bits;
+    int tracks;
+    unsigned short heads;
+    unsigned short sectors;
+} default_formats[] = {
+    { "hd514",			12, 80, 2, 15 },
+    { "high-density-5-1/4",	12, 80, 2, 15 },
+    { "1.2m",			12, 80, 2, 15 },
+    
+    { "hd312",			12, 80, 2, 18 },
+    { "high-density-3-1/2",	12, 80, 2, 18 },
+    { "1.44m",	 		12, 80, 2, 18 },
+
+    { "dd312",			12, 80, 2, 9 },
+    { "double-density-3-1/2",	12, 80, 2, 9 },
+    { "720k",			12, 80, 2, 9 },
+
+    { "dd514",			12, 40, 2, 9 },
+    { "double-density-5-1/4",	12, 40, 2, 9 },
+    { "360k",			12, 40, 2, 9 },
+
+    { "320k",			12, 40, 2, 8 },
+    { "180k",			12, 40, 1, 9 },
+    { "160k",			12, 40, 1, 8 }
+};
+
+#define OFFS(x) ((caddr_t)&((struct device *)0)->x)
+
+static switches_t dswitches[]= {
+    { "FILE", OFFS(name), T_STRING },
+    { "OFFSET", OFFS(offset), T_UINT },
+    { "PARTITION", OFFS(partition), T_UINT },
+    { "FAT", OFFS(fat_bits), T_INT },
+    { "FAT_BITS", OFFS(fat_bits), T_UINT },
+    { "MODE", OFFS(mode), T_UINT },
+    { "TRACKS",  OFFS(tracks), T_UINT },
+    { "CYLINDERS",  OFFS(tracks), T_UINT },
+    { "HEADS", OFFS(heads), T_UINT },
+    { "SECTORS", OFFS(sectors), T_UINT },
+    { "HIDDEN", OFFS(hidden), T_UINT },
+    { "PRECMD", OFFS(precmd), T_STRING },
+    { "BLOCKSIZE", OFFS(blocksize), T_UINT }
+};
+
+static void syntax(const char *msg, int thisLine)
+{
+    char *drive=NULL;
+    if(thisLine)
+	lastTokenLinenumber = linenumber;
+    if(cur_dev >= 0)
+	drive = devices[cur_dev].drive;
+    fprintf(stderr,"Syntax error at line %d ", lastTokenLinenumber);
+    if(drive) fprintf(stderr, "for drive %s: ", drive);
+    if(token) fprintf(stderr, "column %ld ", (long)(token - buffer));
+    fprintf(stderr, "in file %s: %s\n", filename, msg);
+    exit(1);
+}
+
+static void get_env_conf(void)
+{
+    char *s;
+    int i;
+
+    for(i=0; i< sizeof(switches) / sizeof(*switches); i++) {
+	s = getenv(switches[i].name);
+	if(s) {
+	    if(switches[i].type == T_INT)
+		* ((int *)switches[i].address) = (int) strtol(s,0,0);
+	    if(switches[i].type == T_UINT)
+		* ((int *)switches[i].address) = (unsigned int) strtoul(s,0,0);
+	    else if (switches[i].type == T_STRING)
+		* ((char **)switches[i].address) = s;
+	}
+    }
+}
+
+static int mtools_getline(void)
+{
+    if(!fgets(buffer, MAX_LINE_LEN, fp))
+	return -1;
+    linenumber++;
+    pos = buffer;
+    token_nr = 0;
+    buffer[MAX_LINE_LEN] = '\0';
+    if(strlen(buffer) == MAX_LINE_LEN)
+	syntax("line too long", 1);
+    return 0;
+}
+		
+static void skip_junk(int expect)
+{
+    lastTokenLinenumber = linenumber;
+    while(!pos || !*pos || strchr(" #\n\t", *pos)) {
+	if(!pos || !*pos || *pos == '#') {
+	    if(mtools_getline()) {
+		pos = 0;
+		if(expect)
+		    syntax("end of file unexpected", 1);
+		return;
+	    }
+	} else
+	    pos++;
+    }
+    token_nr++;
+}
+
+/* get the next token */
+static char *get_next_token(void)
+{
+    skip_junk(0);
+    if(!pos) {
+	token_length = 0;
+	token = 0;
+	return 0;
+    }
+    token = pos;
+    token_length = strcspn(token, " \t\n#:=");
+    pos += token_length;
+    return token;
+}
+
+static int match_token(const char *template)
+{
+    return (strlen(template) == token_length &&
+	    !strncasecmp(template, token, token_length));
+}
+
+static void expect_char(char c)
+{
+    char buf[11];
+
+    skip_junk(1);
+    if(*pos != c) {
+	sprintf(buf, "expected %c", c);
+	syntax(buf, 1);
+    }
+    pos++;
+}
+
+static char *get_string(void)
+{
+    char *end, *str;
+
+    skip_junk(1);
+    if(*pos != '"')
+	syntax(" \" expected", 0);
+    str = pos+1;
+    end = strchr(str, '\"');
+    if(!end)
+	syntax("unterminated string constant", 1);
+    *end = '\0';
+    pos = end+1;
+    return str;
+}
+
+static unsigned int get_unumber(void)
+{
+    char *last;
+    unsigned int n;
+
+    skip_junk(1);
+    last = pos;
+    n=(unsigned int) strtoul(pos, &pos, 0);
+    if(last == pos)
+	syntax("numeral expected", 0);
+    pos++;
+    token_nr++;
+    return n;
+}
+
+static unsigned int get_number(void)
+{
+    char *last;
+    int n;
+
+    skip_junk(1);
+    last = pos;
+    n=(int) strtol(pos, &pos, 0);
+    if(last == pos)
+	syntax("numeral expected", 0);
+    pos++;
+    token_nr++;
+    return n;
+}
+
+/* purge all entries pertaining to a given drive from the table */
+static void purge(char drive, int fn)
+{
+    int i,j;
+
+    drive = toupper(drive);
+    for(j=0, i=0; i < cur_devs; i++) {
+	if(devices[i].drive[0] != drive ||
+	   devices[i].drive[1] != 0 ||
+	   devices[i].file_nr == fn)
+	    devices[j++] = devices[i];
+    }
+    cur_devs = j;
+}
+
+static void grow(void)
+{
+    if(cur_devs >= nr_dev - 2) {
+	nr_dev = (cur_devs + 2) << 1;
+	if(!(devices=Grow(devices, nr_dev, struct device))){
+	    printOom();
+	    exit(1);
+	}
+    }
+}
+	
+
+static void init_drive(void)
+{
+    memset((char *)&devices[cur_dev], 0, sizeof(struct device));
+    devices[cur_dev].ssize = 2;
+}
+
+/* prepends a device to the table */
+static void prepend(void)
+{
+    int i;
+
+    grow();
+    for(i=cur_devs; i>0; i--)
+	devices[i] = devices[i-1];
+    cur_dev = 0;
+    cur_devs++;
+    init_drive();
+}
+
+
+/* appends a device to the table */
+static void append(void)
+{
+    grow();
+    cur_dev = cur_devs;
+    cur_devs++;
+    init_drive();
+}
+
+
+static void finish_drive_clause(void)
+{
+    char *drive;
+    if(cur_dev == -1) {
+	trusted = 0;
+	return;
+    }
+    drive = devices[cur_dev].drive;
+    if(!devices[cur_dev].name)
+	syntax("missing filename", 0);
+    if(devices[cur_dev].tracks ||
+       devices[cur_dev].heads ||
+       devices[cur_dev].sectors) {
+	if(!devices[cur_dev].tracks ||
+	   !devices[cur_dev].heads ||
+	   !devices[cur_dev].sectors)
+	    syntax("incomplete geometry: either indicate all of track/heads/sectors or none of them", 0);
+	if(!(devices[cur_dev].misc_flags & 
+	     (MFORMAT_ONLY_FLAG | FILTER_FLAG)))
+	    syntax("if you supply a geometry, you also must supply one of the `mformat_only' or `filter' flags", 0);
+    }
+    devices[cur_dev].file_nr = file_nr;
+    devices[cur_dev].cfg_filename = filename;
+    if(! (flag_mask & PRIV_FLAG) && IS_SCSI(&devices[cur_dev]))
+	devices[cur_dev].misc_flags |= PRIV_FLAG;
+    if(!trusted && (devices[cur_dev].misc_flags & PRIV_FLAG)) {
+	fprintf(stderr,
+		"Warning: privileged flag ignored for drive %s: defined in file %s\n",
+		devices[cur_dev].drive, filename);
+	devices[cur_dev].misc_flags &= ~PRIV_FLAG;
+    }
+    trusted = 0;
+    cur_dev = -1;
+}
+
+static int set_var(struct switches_l *switches, int nr,
+		   caddr_t base_address)
+{
+    int i;
+    for(i=0; i < nr; i++) {
+	if(match_token(switches[i].name)) {
+	    expect_char('=');
+	    if(switches[i].type == T_UINT)
+		* ((int *)((long)switches[i].address+base_address)) = 
+		    get_unumber();
+	    if(switches[i].type == T_INT)
+		* ((int *)((long)switches[i].address+base_address)) = 
+		    get_number();
+	    else if (switches[i].type == T_STRING)
+		* ((char**)((long)switches[i].address+base_address))=
+		    strdup(get_string());
+	    return 0;
+	}
+    }
+    return 1;
+}
+
+static int set_openflags(struct device *dev)
+{
+    int i;
+
+    for(i=0; i < sizeof(openflags) / sizeof(*openflags); i++) {
+	if(match_token(openflags[i].name)) {
+	    dev->mode |= openflags[i].flag;
+	    return 0;
+	}
+    }
+    return 1;
+}
+
+static int set_misc_flags(struct device *dev)
+{
+    int i;
+
+    for(i=0; i < sizeof(misc_flags) / sizeof(*misc_flags); i++) {
+	if(match_token(misc_flags[i].name)) {
+	    flag_mask |= misc_flags[i].flag;
+	    skip_junk(0);
+	    if(pos && *pos == '=') {
+		pos++;
+		switch(get_number()) {
+		    case 0:
+			return 0;
+		    case 1:
+			break;
+		    default:
+			syntax("expected 0 or 1", 0);
+		}
+	    }
+	    dev->misc_flags |= misc_flags[i].flag;
+	    return 0;
+	}
+    }
+    return 1;
+}
+
+static int set_def_format(struct device *dev)
+{
+    int i;
+
+    for(i=0; i < sizeof(default_formats)/sizeof(*default_formats); i++) {
+	if(match_token(default_formats[i].name)) {
+	    if(!dev->ssize)
+		dev->ssize = 2;
+	    if(!dev->tracks)
+		dev->tracks = default_formats[i].tracks;
+	    if(!dev->heads)
+		dev->heads = default_formats[i].heads;
+	    if(!dev->sectors)
+		dev->sectors = default_formats[i].sectors;
+	    if(!dev->fat_bits)
+		dev->fat_bits = default_formats[i].fat_bits;
+	    return 0;
+	}
+    }
+    return 1;
+}    
+
+static void get_codepage(void)
+{
+    int i;
+    unsigned short n;
+
+    if(!Codepage)
+	Codepage = New(Codepage_t);
+    for(i=0; i<128; i++) {
+	n = get_number();
+	if(n > 0xff)
+	    n = 0x5f;
+	Codepage->tounix[i] = n;
+    }	
+}
+
+static void get_toupper(void)
+{
+    int i;
+
+    if(!mstoupper)
+	mstoupper = safe_malloc(128);
+    for(i=0; i<128; i++)
+	mstoupper[i] = get_number();
+}
+
+static void parse_old_device_line(char drive)
+{
+    char name[MAXPATHLEN];
+    int items;
+    long offset;
+    char newdrive;
+
+    /* finish any old drive */
+    finish_drive_clause();
+
+    /* purge out data of old configuration files */
+    purge(drive, file_nr);
+	
+    /* reserve slot */
+    append();
+    items = sscanf(token,"%c %s %i %i %i %i %li",
+		   &newdrive,name,&devices[cur_dev].fat_bits,
+		   &devices[cur_dev].tracks,&devices[cur_dev].heads,
+		   &devices[cur_dev].sectors, &offset);
+    devices[cur_dev].offset = (off_t) offset;
+    switch(items){
+	case 2:
+	    devices[cur_dev].fat_bits = 0;
+	    /* fall thru */
+	case 3:
+	    devices[cur_dev].sectors = 0;
+	    devices[cur_dev].heads = 0;
+	    devices[cur_dev].tracks = 0;
+	    /* fall thru */
+	case 6:
+	    devices[cur_dev].offset = 0;
+	    /* fall thru */
+	default:
+	    break;
+	case 0:
+	case 1:
+	case 4:
+	case 5:
+	    syntax("bad number of parameters", 1);
+	    exit(1);
+    }
+    if(!devices[cur_dev].tracks){
+	devices[cur_dev].sectors = 0;
+	devices[cur_dev].heads = 0;
+    }
+	
+    devices[cur_dev].drive = letters[toupper(newdrive) - 'A'];
+    if (!(devices[cur_dev].name = strdup(name))) {
+	printOom();
+	exit(1);
+    }
+    finish_drive_clause();
+    pos=0;
+}
+
+static int parse_one(int privilege)
+{
+    int action=0;
+
+    get_next_token();
+    if(!token)
+	return 0;
+
+    if((match_token("drive") && ((action = 1)))||
+       (match_token("drive+") && ((action = 2))) ||
+       (match_token("+drive") && ((action = 3))) ||
+       (match_token("clear_drive") && ((action = 4))) ) {
+	/* finish off the previous drive */
+	finish_drive_clause();
+
+	get_next_token();
+	if(token_length != 1)
+	    syntax("drive letter expected", 0);
+
+	if(action==1 || action==4)
+	    /* replace existing drive */			
+	    purge(token[0], file_nr);
+	if(action==4)
+	    return 1;
+	if(action==3)
+	    prepend();
+	else
+	    append();
+	memset((char*)(devices+cur_dev), 0, sizeof(*devices));
+	trusted = privilege;
+	flag_mask = 0;
+	devices[cur_dev].drive = letters[toupper(token[0]) - 'A'];
+	expect_char(':');
+	return 1;
+    }
+    if(token_nr == 1 && token_length == 1) {
+	parse_old_device_line(token[0]);
+	return 1;
+    }
+    if(match_token("default_fucase")) {
+	free(mstoupper);
+	mstoupper=0;
+    }
+    if(match_token("default_tounix")) {
+	Free(Codepage);
+	Codepage = 0;
+    }
+    if(match_token("fucase")) {
+	expect_char(':');
+	get_toupper();
+	return 1;
+    }
+    if(match_token("tounix")) {
+	expect_char(':');
+	get_codepage();
+	return 1;
+    }
+	
+    if((cur_dev < 0 || 
+	(set_var(dswitches,
+		 sizeof(dswitches)/sizeof(*dswitches),
+		 (caddr_t)&devices[cur_dev]) &&
+	 set_openflags(&devices[cur_dev]) &&
+	 set_misc_flags(&devices[cur_dev]) &&
+	 set_def_format(&devices[cur_dev]))) &&
+       set_var(switches,
+	       sizeof(switches)/sizeof(*switches), 0))
+	syntax("unrecognized keyword", 1);
+    return 1;
+}
+
+static int parse(const char *name, int privilege)
+{
+    fp = fopen(name, "r");
+    if(!fp)
+	return 0;
+    file_nr++;
+    filename = strdup(name);
+    linenumber = 0;
+    lastTokenLinenumber = 0;
+    pos = 0;
+    token = 0;
+    cur_dev = -1; /* no current device */
+
+    while(parse_one(privilege));
+    finish_drive_clause();
+    fclose(fp);
+    return 1;
+}
+
+void read_config(void)
+{
+    char *homedir;
+    char *envConfFile;
+    char conf_file[MAXPATHLEN+sizeof(CFG_FILE1)];
+
+	
+    /* copy compiled-in devices */
+    file_nr = 0;
+    cur_devs = nr_const_devices;
+    nr_dev = nr_const_devices + 2;
+    devices = NewArray(nr_dev, struct device);
+    if(!devices) {
+	printOom();
+	exit(1);
+    }
+    if(nr_const_devices)
+	memcpy(devices, const_devices,
+	       nr_const_devices*sizeof(struct device));
+
+    (void) ((parse(CONF_FILE,1) | 
+	     parse(LOCAL_CONF_FILE,1) |
+	     parse(SYS_CONF_FILE,1)) ||
+	    (parse(OLD_CONF_FILE,1) | 
+	     parse(OLD_LOCAL_CONF_FILE,1)));
+    /* the old-name configuration files only get executed if none of the
+     * new-name config files were used */
+
+    homedir = get_homedir();
+    if ( homedir ){
+	strncpy(conf_file, homedir, MAXPATHLEN );
+	conf_file[MAXPATHLEN]='\0';
+	strcat( conf_file, CFG_FILE1);
+	parse(conf_file,0);
+    }
+    memset((char *)&devices[cur_devs],0,sizeof(struct device));
+
+    envConfFile = getenv("MTOOLSRC");
+    if(envConfFile)
+	parse(envConfFile,0);
+
+    /* environmental variables */
+    get_env_conf();
+    if(mtools_skip_check)
+	mtools_fat_compatibility=1;
+    init_codepage();
+}
+
+void mtoolstest(int argc, char **argv, int type)
+{
+    /* testing purposes only */
+    struct device *dev;
+    int i,j;
+    char *drive=NULL;
+    char *path;
+
+    if (argc > 1 && (path = skip_drive(argv[1])) > argv[1]) {
+	drive = get_drive(argv[1], NULL);
+    }
+
+    for (dev=devices; dev->name; dev++) {
+	if(drive && strcmp(drive, dev->drive) != 0)
+	    continue;
+	printf("drive %s:\n", dev->drive);
+	printf("\t#fn=%d mode=%d ",
+	       dev->file_nr, dev->mode);
+	if(dev->cfg_filename)
+	    printf("defined in %s\n", dev->cfg_filename);
+	else
+	    printf("builtin\n");
+	printf("\tfile=\"%s\" fat_bits=%d \n",
+	       dev->name,dev->fat_bits);
+	printf("\ttracks=%d heads=%d sectors=%d hidden=%d\n",
+	       dev->tracks, dev->heads, dev->sectors, dev->hidden);
+	printf("\toffset=0x%lx\n", (long) dev->offset);
+	printf("\tpartition=%d\n", dev->partition);
+
+	if(dev->misc_flags)
+	    printf("\t");
+
+	if(IS_SCSI(dev))
+	    printf("scsi ");
+	if(IS_PRIVILEGED(dev))
+	    printf("privileged");
+	if(IS_MFORMAT_ONLY(dev))
+	    printf("mformat_only ");
+	if(SHOULD_USE_VOLD(dev))
+	    printf("vold ");
+#ifdef USE_XDF
+	if(SHOULD_USE_XDF(dev))
+	    printf("use_xdf ");
+#endif
+	if(dev->misc_flags)
+	    printf("\n");
+
+	if(dev->mode)
+	    printf("\t");
+#ifdef O_SYNC
+	if(dev->mode & O_SYNC)
+	    printf("sync ");
+#endif
+#ifdef O_NDELAY
+	if((dev->mode & O_NDELAY))
+	    printf("nodelay ");
+#endif
+#ifdef O_EXCL
+	if((dev->mode & O_EXCL))
+	    printf("exclusive ");
+#endif
+	if(dev->mode)
+	    printf("\n");
+
+	if(dev->precmd)
+	    printf("\tprecmd=%s\n", dev->precmd);
+
+	printf("\n");
+    }
+	
+    printf("tounix:\n");
+    for(i=0; i < 16; i++) {
+	putchar('\t');
+	for(j=0; j<8; j++)
+	    printf("0x%02x ",
+		   (unsigned char)Codepage->tounix[i*8+j]);
+	putchar('\n');
+    }
+    printf("\nfucase:\n");
+    for(i=0; i < 16; i++) {
+	putchar('\t');
+	for(j=0; j<8; j++)
+	    printf("0x%02x ",
+		   (unsigned char)mstoupper[i*8+j]);
+	putchar('\n');
+    }
+    if(country_string)
+	printf("COUNTRY=%s\n", country_string);
+    printf("mtools_fat_compatibility=%d\n",mtools_fat_compatibility);
+    printf("mtools_skip_check=%d\n",mtools_skip_check);
+    printf("mtools_lower_case=%d\n",mtools_ignore_short_case);
+
+    exit(0);
+}
+
+#else	/* NO_CONFIG */
+
+void read_config(void)
+{
+	/* only compiled-in devices */
+	devices = NewArray(nr_const_devices + 1, struct device);
+	if(!devices) {
+		fprintf(stderr,"Out of memory error\n");
+		exit(1);
+	}
+	if(nr_const_devices)
+	memcpy(devices, const_devices,
+		       nr_const_devices*sizeof(struct device));
+}
+
+#endif /* NO_CONFIG */
Index: /trunk/minix/commands/i386/mtools-3.9.7/config.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/config.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/config.h	(revision 9)
@@ -0,0 +1,301 @@
+/* config.h.  Generated automatically by configure.  */
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* #undef _ALL_SOURCE */
+#endif
+
+/* Define to empty if the keyword does not work.  */
+/* #undef const */
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define as __inline if that's what the C compiler calls it.  */
+#define inline 
+
+/* Define if on MINIX.  */
+#define _MINIX 1
+
+/* Define if the system does not provide POSIX.1 features except
+   with this defined.  */
+#define _POSIX_1_SOURCE 2
+
+/* Define if you need to in order for stat and other things to work.  */
+#define _POSIX_SOURCE 1
+
+/* Define as the return type of signal handlers (int or void).  */
+#define RETSIGTYPE void
+
+/* Define if the `setpgrp' function takes no argument.  */
+#define SETPGRP_VOID 1
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+/* #undef size_t */
+
+/* Define if you have the ANSI C header files.  */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>.  */
+/* #undef TIME_WITH_SYS_TIME */
+
+/* Define if your <sys/time.h> declares struct tm.  */
+/* #undef TM_IN_SYS_TIME */
+
+/* Define if the X Window System is missing or not being used.  */
+#define X_DISPLAY_MISSING 1
+
+/* Define this if you want to use Xdf */
+#define USE_XDF 1
+
+/* Define this if you use mtools together with Solaris' vold */
+/* #undef USING_VOLD */
+
+/* Define this if you use mtools together with the new Solaris' vold
+ * support */
+/* #undef USING_NEW_VOLD */
+
+/* Define for debugging messages */
+/* #undef DEBUG */
+
+/* Define on non Unix OS'es which don't have the concept of tty's */
+/* #undef USE_RAWTERM */
+
+/* Define when sys_errlist is defined in the standard include files */
+/* #undef DECL_SYS_ERRLIST */
+
+/* Define when you want to include floppyd support */
+/* #undef USE_FLOPPYD */
+
+/* Define when the compiler supports LOFF_T type */
+/* #undef HAVE_LOFF_T */
+
+/* Define when the compiler supports OFFSET_T type */
+/* #undef HAVE_OFFSET_T */
+
+/* Define when the compiler supports LONG_LONG type */
+/* #undef HAVE_LONG_LONG */
+
+/* Define when the system has a 64 bit off_t type */
+/* #undef HAVE_OFF_T_64 */
+
+/* Define when you have an LLSEEK prototype */
+/* #undef HAVE_LLSEEK_PROTOTYPE */
+
+/* Define if you have the atexit function.  */
+#define HAVE_ATEXIT 1
+
+/* Define if you have the basename function.  */
+/* #undef HAVE_BASENAME */
+
+/* Define if you have the fchdir function.  */
+#ifdef __minix_vmd
+#define HAVE_FCHDIR 1
+#endif
+
+/* Define if you have the flock function.  */
+/* #undef HAVE_FLOCK */
+
+/* Define if you have the getpass function.  */
+#define HAVE_GETPASS 1
+
+/* Define if you have the gettimeofday function.  */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define if you have the htons function.  */
+/* #undef HAVE_HTONS */
+
+/* Define if you have the llseek function.  */
+/* #undef HAVE_LLSEEK */
+
+/* Define if you have the lockf function.  */
+#define HAVE_LOCKF 1
+
+/* Define if you have the lseek64 function.  */
+/* #undef HAVE_LSEEK64 */
+
+/* Define if you have the media_oldaliases function.  */
+/* #undef HAVE_MEDIA_OLDALIASES */
+
+/* Define if you have the memcpy function.  */
+#define HAVE_MEMCPY 1
+
+/* Define if you have the memmove function.  */
+#define HAVE_MEMMOVE 1
+
+/* Define if you have the memset function.  */
+#define HAVE_MEMSET 1
+
+/* Define if you have the on_exit function.  */
+/* #undef HAVE_ON_EXIT */
+
+/* Define if you have the random function.  */
+#define HAVE_RANDOM 1
+
+/* Define if you have the seteuid function.  */
+/* #undef HAVE_SETEUID */
+
+/* Define if you have the setresuid function.  */
+/* #undef HAVE_SETRESUID */
+
+/* Define if you have the snprintf function.  */
+#define HAVE_SNPRINTF 1
+
+/* Define if you have the srandom function.  */
+#define HAVE_SRANDOM 1
+
+/* Define if you have the strcasecmp function.  */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function.  */
+#define HAVE_STRCHR 1
+
+/* Define if you have the strcspn function.  */
+#define HAVE_STRCSPN 1
+
+/* Define if you have the strdup function.  */
+/* #undef HAVE_STRDUP */
+
+/* Define if you have the strerror function.  */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strncasecmp function.  */
+#define HAVE_STRNCASECMP 1
+
+/* Define if you have the strpbrk function.  */
+#define HAVE_STRPBRK 1
+
+/* Define if you have the strrchr function.  */
+#define HAVE_STRRCHR 1
+
+/* Define if you have the strspn function.  */
+#define HAVE_STRSPN 1
+
+/* Define if you have the strtol function.  */
+#define HAVE_STRTOL 1
+
+/* Define if you have the strtoul function.  */
+#define HAVE_STRTOUL 1
+
+/* Define if you have the tcflush function.  */
+#define HAVE_TCFLUSH 1
+
+/* Define if you have the tcsetattr function.  */
+#define HAVE_TCSETATTR 1
+
+/* Define if you have the tzset function.  */
+#define HAVE_TZSET 1
+
+/* Define if you have the utime function.  */
+#define HAVE_UTIME 1
+
+/* Define if you have the utimes function.  */
+/* #undef HAVE_UTIMES */
+
+/* Define if you have the <arpa/inet.h> header file.  */
+/* #undef HAVE_ARPA_INET_H */
+
+/* Define if you have the <fcntl.h> header file.  */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <getopt.h> header file.  */
+/* #undef HAVE_GETOPT_H */
+
+/* Define if you have the <libc.h> header file.  */
+/* #undef HAVE_LIBC_H */
+
+/* Define if you have the <limits.h> header file.  */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <linux/unistd.h> header file.  */
+/* #undef HAVE_LINUX_UNISTD_H */
+
+/* Define if you have the <malloc.h> header file.  */
+/* #undef HAVE_MALLOC_H */
+
+/* Define if you have the <memory.h> header file.  */
+/* #undef HAVE_MEMORY_H */
+
+/* Define if you have the <mntent.h> header file.  */
+/* #undef HAVE_MNTENT_H */
+
+/* Define if you have the <netdb.h> header file.  */
+/* #undef HAVE_NETDB_H */
+
+/* Define if you have the <netinet/in.h> header file.  */
+/* #undef HAVE_NETINET_IN_H */
+
+/* Define if you have the <sgtty.h> header file.  */
+#define HAVE_SGTTY_H 1
+
+/* Define if you have the <signal.h> header file.  */
+#define HAVE_SIGNAL_H 1
+
+/* Define if you have the <stdlib.h> header file.  */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file.  */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file.  */
+/* #undef HAVE_STRINGS_H */
+
+/* Define if you have the <sys/file.h> header file.  */
+/* #undef HAVE_SYS_FILE_H */
+
+/* Define if you have the <sys/floppy.h> header file.  */
+/* #undef HAVE_SYS_FLOPPY_H */
+
+/* Define if you have the <sys/ioctl.h> header file.  */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the <sys/param.h> header file.  */
+/* #undef HAVE_SYS_PARAM_H */
+
+/* Define if you have the <sys/signal.h> header file.  */
+/* #undef HAVE_SYS_SIGNAL_H */
+
+/* Define if you have the <sys/socket.h> header file.  */
+/* #undef HAVE_SYS_SOCKET_H */
+
+/* Define if you have the <sys/stat.h> header file.  */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/sysmacros.h> header file.  */
+/* #undef HAVE_SYS_SYSMACROS_H */
+
+/* Define if you have the <sys/termio.h> header file.  */
+/* #undef HAVE_SYS_TERMIO_H */
+
+/* Define if you have the <sys/termios.h> header file.  */
+/* #undef HAVE_SYS_TERMIOS_H */
+
+/* Define if you have the <sys/time.h> header file.  */
+/* #undef HAVE_SYS_TIME_H */
+
+/* Define if you have the <termio.h> header file.  */
+/* #undef HAVE_TERMIO_H */
+
+/* Define if you have the <termios.h> header file.  */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <unistd.h> header file.  */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <utime.h> header file.  */
+#define HAVE_UTIME_H 1
+
+/* Define if you have the cam library (-lcam).  */
+/* #undef HAVE_LIBCAM */
+
+/* Define if you have the nsl library (-lnsl).  */
+/* #undef HAVE_LIBNSL */
+
+/* Define if you have the socket library (-lsocket).  */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define if you have the sun library (-lsun).  */
+/* #undef HAVE_LIBSUN */
Index: /trunk/minix/commands/i386/mtools-3.9.7/copyfile.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/copyfile.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/copyfile.c	(revision 9)
@@ -0,0 +1,62 @@
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "file.h"
+#include "llong.h"
+
+/*
+ * Copy the data from source to target
+ */
+
+int copyfile(Stream_t *Source, Stream_t *Target)
+{
+	char buffer[8*16384];
+	int pos;
+	int ret, retw;
+	size_t len;
+	mt_size_t mt_len;
+
+	if (!Source){
+		fprintf(stderr,"Couldn't open source file\n");
+		return -1;
+	}
+
+	if (!Target){
+		fprintf(stderr,"Couldn't open target file\n");
+		return -1;
+	}
+
+	pos = 0;
+	GET_DATA(Source, 0, &mt_len, 0, 0);
+	if (mt_len & ~max_off_t_31) {
+		fprintf(stderr, "File too big\n");
+		return -1;
+	}
+	len = truncBytes32(mt_len);
+	while(1){
+		ret = READS(Source, buffer, (mt_off_t) pos, 8*16384);
+		if (ret < 0 ){
+			perror("file read");
+			return -1;
+		}
+		if(!ret)
+			break;
+		if(got_signal)
+			return -1;
+		if (ret == 0)
+			break;
+		if ((retw = force_write(Target, buffer, (mt_off_t) pos, ret)) != ret){
+			if(retw < 0 )
+				perror("write in copy");
+			else
+				fprintf(stderr,
+					"Short write %d instead of %d\n", retw,
+					ret);
+			if(errno == ENOSPC)
+				got_signal = 1;
+			return ret;
+		}
+		pos += ret;
+	}
+	return pos;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/devices.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/devices.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/devices.c	(revision 9)
@@ -0,0 +1,1115 @@
+/*
+ * This file is modified to perform on the UXP/DS operating system 
+ * by FUJITSU Limited on 1996.6.4
+ */
+
+/*
+ * Device tables.  See the Configure file for a complete description.
+ */
+
+#define NO_TERMIO
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "devices.h"
+
+#define INIT_NOOP
+
+#define DEF_ARG1(x) (x), 0x2,0,(char *)0, 0, 0
+#define DEF_ARG0(x) 0,DEF_ARG1(x)
+
+#define MDEF_ARG 0L,DEF_ARG0(MFORMAT_ONLY_FLAG)
+#define FDEF_ARG 0L,DEF_ARG0(0)
+#define VOLD_DEF_ARG 0L,DEF_ARG0(VOLD_FLAG|MFORMAT_ONLY_FLAG)
+
+#define MED312	12,0,80,2,36,0,MDEF_ARG /* 3 1/2 extra density */
+#define MHD312	12,0,80,2,18,0,MDEF_ARG /* 3 1/2 high density */
+#define MDD312	12,0,80,2, 9,0,MDEF_ARG /* 3 1/2 double density */
+#define MHD514	12,0,80,2,15,0,MDEF_ARG /* 5 1/4 high density */
+#define MDD514	12,0,40,2, 9,0,MDEF_ARG /* 5 1/4 double density (360k) */
+#define MSS514	12,0,40,1, 9,0,MDEF_ARG /* 5 1/4 single sided DD, (180k) */
+#define MDDsmall	12,0,40,2, 8,0,MDEF_ARG /* 5 1/4 double density (320k) */
+#define MSSsmall	12,0,40,1, 8,0,MDEF_ARG /* 5 1/4 single sided DD, (160k) */
+
+#define FED312	12,0,80,2,36,0,FDEF_ARG /* 3 1/2 extra density */
+#define FHD312	12,0,80,2,18,0,FDEF_ARG /* 3 1/2 high density */
+#define FDD312	12,0,80,2, 9,0,FDEF_ARG /* 3 1/2 double density */
+#define FHD514	12,0,80,2,15,0,FDEF_ARG /* 5 1/4 high density */
+#define FDD514	12,0,40,2, 9,0,FDEF_ARG /* 5 1/4 double density (360k) */
+#define FSS514	12,0,40,1, 9,0,FDEF_ARG /* 5 1/4 single sided DD, (180k) */
+#define FDDsmall	12,0,40,2, 8,0,FDEF_ARG /* 5 1/4 double density (320k) */
+#define FSSsmall	12,0,40,1, 8,0,FDEF_ARG /* 5 1/4 single sided DD, (160k) */
+
+#define GENHD	16,0, 0,0, 0,0,MDEF_ARG /* Generic 16 bit FAT fs */
+#define GENFD	12,0,80,2,18,0,MDEF_ARG /* Generic 12 bit FAT fs */
+#define VOLDFD	12,0,80,2,18,0,VOLD_DEF_ARG /* Generic 12 bit FAT fs with vold */
+#define GEN    	 0,0, 0,0, 0,0,MDEF_ARG /* Generic fs of any FAT bits */
+
+#define ZIPJAZ(x,c,h,s,y) 16,(x),(c),(h),(s),(s),0L, 4, \
+		DEF_ARG1((y)|MFORMAT_ONLY_FLAG) /* Jaz disks */
+
+#define JAZ(x)	 ZIPJAZ(x,1021, 64, 32, 0)
+#define RJAZ(x)	 ZIPJAZ(x,1021, 64, 32, SCSI_FLAG|PRIV_FLAG)
+#define ZIP(x)	 ZIPJAZ(x,96, 64, 32, 0)
+#define RZIP(x)	 ZIPJAZ(x,96, 64, 32, SCSI_FLAG|PRIV_FLAG)
+
+#define REMOTE    {"$DISPLAY", 'X', 0,0, 0,0, 0,0,0L, DEF_ARG0(FLOPPYD_FLAG)}
+
+
+
+#if defined(INIT_GENERIC) || defined(INIT_NOOP)
+static int compare_geom(struct device *dev, struct device *orig_dev)
+{
+	if(IS_MFORMAT_ONLY(orig_dev))
+		return 0; /* geometry only for mformatting ==> ok */
+	if(!orig_dev || !orig_dev->tracks || !dev || !dev->tracks)
+		return 0; /* no original device. This is ok */
+	return(orig_dev->tracks != dev->tracks ||
+	       orig_dev->heads != dev->heads ||
+	       orig_dev->sectors  != dev->sectors);
+}
+#endif
+
+#define devices const_devices
+
+
+#ifdef OS_aux
+#define predefined_devices
+struct device devices[] = {
+   {"/dev/floppy0", "A", GENFD },
+   {"/dev/rdsk/c104d0s31", "J", JAZ(O_EXCL) },
+   {"/dev/rdsk/c105d0s31", "Z", ZIP(O_EXCL) },
+   REMOTE
+};
+#endif /* aux */
+
+
+#ifdef OS_lynxos
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/fd1440.0", 	"A", MHD312 },
+	REMOTE
+};
+#endif
+
+
+#ifdef __BEOS__
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/disk/floppy/raw", 	"A", MHD312 },
+	REMOTE
+};
+#endif /* BEBOX */
+
+
+#ifdef OS_hpux
+
+#define predefined_devices
+struct device devices[] = {
+#ifdef OS_hpux10
+/* hpux10 uses different device names according to Frank Maritato
+ * <frank@math.hmc.edu> */
+	{"/dev/floppy/c0t0d0",		"A", MHD312 },
+	{"/dev/floppy/c0t0d1",		"B", MHD312 }, /* guessed by me */
+ 	{"/dev/rscsi",			"C", GENHD }, /* guessed by me */
+#else
+/* Use rfloppy, according to Simao Campos <simao@iris.ctd.comsat.com> */
+	{"/dev/rfloppy/c201d0s0",	"A", FHD312 },
+	{"/dev/rfloppy/c20Ad0s0", 	"A", FHD312 },
+ 	{"/dev/rfloppy/c201d1s0",	"B", FHD312 },
+ 	{"/dev/rfloppy/c20Ad1s0",	"B", FHD312 },
+ 	{"/dev/rscsi",			"C", GENHD },
+#endif
+	{"/dev/rdsk/c201d4",		"J", RJAZ(O_EXCL) },
+	{"/dev/rdsk/c201d4s0",		"J", RJAZ(O_EXCL) },
+	{"/dev/rdsk/c201d5",		"Z", RZIP(O_EXCL) },
+	{"/dev/rdsk/c201d5s0",		"Z", RZIP(O_EXCL) },
+	REMOTE
+};
+
+#ifdef HAVE_SYS_FLOPPY
+/* geometry setting ioctl's contributed by Paolo Zeppegno
+ * <paolo@to.sem.it>, may cause "Not a typewriter" messages on other
+ * versions according to support@vital.com */
+
+#include <sys/floppy.h>
+#undef SSIZE
+
+struct generic_floppy_struct
+{
+  struct floppy_geometry fg;
+};
+
+#define BLOCK_MAJOR 24
+#define CHAR_MAJOR 112
+
+static inline int get_parameters(int fd, struct generic_floppy_struct *floppy)
+{
+	if (ioctl(fd, FLOPPY_GET_GEOMETRY, &(floppy->fg)) != 0) {
+		perror("FLOPPY_GET_GEOMETRY");
+		return(1);
+	}
+	
+	return 0;
+}
+
+#define TRACKS(floppy) floppy.fg.tracks
+#define HEADS(floppy) floppy.fg.heads
+#define SECTORS(floppy) floppy.fg.sectors
+#define FD_SECTSIZE(floppy) floppy.fg.sector_size
+#define FD_SET_SECTSIZE(floppy,v) { floppy.fg.sector_size = v; }
+
+static inline int set_parameters(int fd, struct generic_floppy_struct *floppy, 
+				 struct stat *buf)
+{
+	if (ioctl(fd, FLOPPY_SET_GEOMETRY, &(floppy->fg)) != 0) {
+		perror("");
+		return(1);
+	}
+	
+	return 0;
+}
+#define INIT_GENERIC
+#endif
+
+#endif /* hpux */
+ 
+
+#if (defined(OS_sinix) || defined(VENDOR_sni) || defined(SNI))
+#define predefined_devices
+struct device devices[] = {
+#ifdef CPU_mips     /* for Siemens Nixdorf's  SINIX-N/O (mips) 5.4x SVR4 */
+	{ "/dev/at/flp/f0t",    "A", FHD312},
+	{ "/dev/fd0",           "A", GENFD},
+#else
+#ifdef CPU_i386     /* for Siemens Nixdorf's  SINIX-D/L (intel) 5.4x SVR4 */
+	{ "/dev/fd0135ds18",	"A", FHD312},
+	{ "/dev/fd0135ds9",	"A", FDD312},
+	{ "/dev/fd0",		"A", GENFD},
+	{ "/dev/fd1135ds15",	"B", FHD514},
+	{ "/dev/fd1135ds9",	"B", FDD514},
+	{ "/dev/fd1",		"B", GENFD},
+#endif /* CPU_i386 */
+#endif /*mips*/
+	REMOTE
+};
+#endif
+
+#ifdef OS_ultrix
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/rfd0a",		"A", GENFD}, /* guessed */
+	{"/dev/rfd0c",		"A", GENFD}, /* guessed */
+	REMOTE
+};
+
+#endif
+
+
+#ifdef OS_isc
+#define predefined_devices
+#if (defined(OS_isc2) && defined(OLDSTUFF))
+struct device devices[] = {
+	{"/dev/rdsk/f0d9dt",   	"A", FDD514},
+	{"/dev/rdsk/f0q15dt",	"A", FHD514},
+	{"/dev/rdsk/f0d8dt",	"A", FDDsmall},
+	{"/dev/rdsk/f13ht",	"B", FHD312},
+	{"/dev/rdsk/f13dt",	"B", FDD312},
+	{"/dev/rdsk/0p1",	"C", GENHD},
+	{"/usr/vpix/defaults/C:","D",12, 0, 0, 0, 0,8704L,DEF_ARG0},
+	{"$HOME/vpix/C:", 	"E", 12, 0, 0, 0, 0,8704L,MDEF_ARG},
+	REMOTE
+};
+#else
+/* contributed by larry.jones@sdrc.com (Larry Jones) */
+struct device devices[] = {
+	{"/dev/rfd0",		"A", GEN},
+	{"/dev/rfd1",		"B", GEN},
+	{"/dev/rdsk/0p1",	"C", GEN},
+	{"/usr/vpix/defaults/C:","D", GEN, 1},
+	{"$HOME/vpix/C:", 	"E", GEN, 1},
+	REMOTE
+};
+
+#include <sys/vtoc.h>
+#include <sys/sysmacros.h>
+#undef SSIZE
+#define BLOCK_MAJOR 1
+#define CHAR_MAJOR  1
+#define generic_floppy_struct disk_parms
+int ioctl(int, int, void *);
+
+static int get_parameters(int fd, struct generic_floppy_struct *floppy)
+{
+	mt_off_t off;
+	char buf[512];
+
+	off = lseek(fd, 0, SEEK_CUR);
+	if(off < 0) {
+		perror("device seek 1");
+		exit(1);
+	}
+	if (off == 0) {
+		/* need to read at least 1 sector to get correct info */
+		read(fd, buf, sizeof buf);
+		if(lseek(fd, 0, SEEK_SET) < 0) {
+			perror("device seek 2");
+			exit(1);
+		}
+	}
+	return ioctl(fd, V_GETPARMS, floppy);
+}
+
+#define TRACKS(floppy)  (floppy).dp_cyls
+#define HEADS(floppy)   (floppy).dp_heads
+#define SECTORS(floppy) (floppy).dp_sectors
+#define FD_SECTSIZE(floppy) (floppy).dp_secsiz
+#define FD_SET_SECTSIZE(floppy,v) { (floppy).dp_secsiz = (v); }
+
+static int set_parameters(int fd, struct generic_floppy_struct *floppy,
+	struct stat *buf)
+{
+	return 1;
+}
+
+#define INIT_GENERIC
+#endif
+#endif /* isc */
+
+#ifdef CPU_i370
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/rfd0", "A", GENFD},
+	REMOTE
+};
+#endif /* CPU_i370 */
+
+#ifdef OS_aix
+/* modified by Federico Bianchi */
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/fd0","A",GENFD},
+	REMOTE
+};
+#endif /* aix */
+
+  
+#ifdef OS_osf4
+/* modified by Chris Samuel <chris@rivers.dra.hmg.gb> */
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/fd0c","A",GENFD},
+	REMOTE
+};
+#endif /* OS_osf4 */
+
+
+#ifdef OS_solaris
+
+#ifdef USING_NEW_VOLD
+
+char *alias_name = NULL;
+  
+extern char *media_oldaliases(char *);
+extern char *media_findname(char *);
+
+char *getVoldName(struct device *dev, char *name)
+{
+	char *rname;
+  
+	if(!SHOULD_USE_VOLD(dev))
+		return name;
+
+	/***
+	 * Solaris specific routines to use the volume management
+	 * daemon and libraries to get the correct device name...
+	 ***/
+	rname = media_findname(name);
+#ifdef HAVE_MEDIA_OLDALIASES
+	if (rname == NULL) {
+		if ((alias_name = media_oldaliases(name)) != NULL)
+			rname = media_findname(alias_name);
+	}
+#endif
+	if (rname == NULL) {
+		fprintf(stderr, 
+				"No such volume or no media in device: %s.\n", 
+				name);
+		exit(1);
+	}
+	return rname;
+}
+#endif /* USING_NEW_VOLD */
+
+#define predefined_devices
+struct device devices[] = {
+#ifdef  USING_NEW_VOLD
+	{"floppy", "A", VOLDFD },
+#elif	USING_VOLD
+	{"/vol/dev/aliases/floppy0", "A", GENFD},
+	{"/dev/rdiskette", "B", GENFD},
+#else	/* ! USING_VOLD */
+	{"/dev/rdiskette", "A", GENFD},
+	{"/vol/dev/aliases/floppy0", "B", GENFD},
+#endif	/* USING_VOLD */
+	{"/dev/rdsk/c0t4d0s2", "J", RJAZ(O_NDELAY)},
+	{"/dev/rdsk/c0t5d0s2", "Z", RZIP(O_NDELAY)},
+	REMOTE
+};
+
+
+
+/*
+ * Ofer Licht <ofer@stat.Berkeley.EDU>, May 14, 1997.
+ */
+
+#define INIT_GENERIC
+
+#include <sys/fdio.h>
+#include <sys/mkdev.h>	/* for major() */
+
+struct generic_floppy_struct
+{
+  struct fd_char fdchar;
+};
+
+#define BLOCK_MAJOR 36
+#define CHAR_MAJOR 36
+
+static inline int get_parameters(int fd, struct generic_floppy_struct *floppy)
+{
+	if (ioctl(fd, FDIOGCHAR, &(floppy->fdchar)) != 0) {
+		perror("");
+		ioctl(fd, FDEJECT, NULL);
+		return(1);
+	}
+	return 0;
+}
+
+#define TRACKS(floppy) floppy.fdchar.fdc_ncyl
+#define HEADS(floppy) floppy.fdchar.fdc_nhead
+#define SECTORS(floppy) floppy.fdchar.fdc_secptrack
+/* SECTORS_PER_DISK(floppy) not used */
+#define FD_SECTSIZE(floppy) floppy.fdchar.fdc_sec_size
+#define FD_SET_SECTSIZE(floppy,v) { floppy.fdchar.fdc_sec_size = v; }
+
+static inline int set_parameters(int fd, struct generic_floppy_struct *floppy, 
+				 struct stat *buf)
+{
+	if (ioctl(fd, FDIOSCHAR, &(floppy->fdchar)) != 0) {
+		ioctl(fd, FDEJECT, NULL);
+		perror("");
+		return(1);
+	}
+	return 0;
+}
+#define INIT_GENERIC
+#endif /* solaris */
+
+#ifdef OS_sunos3
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/rfdl0c",	"A", FDD312},
+	{"/dev/rfd0c",	"A", FHD312},
+	REMOTE
+};
+#endif /* OS_sunos3 */
+
+#ifdef OS_xenix
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/fd096ds15",	"A", FHD514},
+	{"/dev/fd048ds9",	"A", FDD514},
+	{"/dev/fd1135ds18",	"B", FHD312},
+	{"/dev/fd1135ds9",	"B", FDD312},
+	{"/dev/hd0d",		"C", GENHD},
+	REMOTE
+};
+#endif /* OS_xenix */
+
+#ifdef OS_sco
+#define predefined_devices
+struct device devices[] = {
+	{ "/dev/fd0135ds18",	"A", FHD312},
+	{ "/dev/fd0135ds9",	"A", FDD312},
+	{ "/dev/fd0",		"A", GENFD},
+	{ "/dev/fd1135ds15",	"B", FHD514},
+	{ "/dev/fd1135ds9",	"B", FDD514},
+	{ "/dev/fd1",		"B", GENFD},
+	{ "/dev/hd0d",		"C", GENHD},
+	REMOTE
+};
+#endif /* OS_sco */
+
+
+#ifdef OS_irix
+#define predefined_devices
+struct device devices[] = {
+  { "/dev/rdsk/fds0d2.3.5hi",	"A", FHD312},
+  { "/dev/rdsk/fds0d2.3.5",	"A", FDD312},
+  { "/dev/rdsk/fds0d2.96",	"A", FHD514},
+  {"/dev/rdsk/fds0d2.48",	"A", FDD514},
+  REMOTE
+};
+#endif /* OS_irix */
+
+
+#ifdef OS_sunos4
+#include <sys/ioctl.h>
+#include <sun/dkio.h>
+
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/rfd0c",	"A", GENFD},
+	{"/dev/rsd4c",	"J", RJAZ(O_NDELAY)},
+	{"/dev/rsd5c",	"Z", RZIP(O_NDELAY)},
+	REMOTE
+};
+
+/*
+ * Stuffing back the floppy parameters into the driver allows for gems
+ * like 10 sector or single sided floppies from Atari ST systems.
+ * 
+ * Martin Schulz, Universite de Moncton, N.B., Canada, March 11, 1991.
+ */
+
+#define INIT_GENERIC
+
+struct generic_floppy_struct
+{
+  struct fdk_char dkbuf;
+  struct dk_map dkmap;
+};
+
+#define BLOCK_MAJOR 16
+#define CHAR_MAJOR 54
+
+static inline int get_parameters(int fd, struct generic_floppy_struct *floppy)
+{
+	if (ioctl(fd, DKIOCGPART, &(floppy->dkmap)) != 0) {
+		perror("DKIOCGPART");
+		ioctl(fd, FDKEJECT, NULL);
+		return(1);
+	}
+	
+	if (ioctl(fd, FDKIOGCHAR, &( floppy->dkbuf)) != 0) {
+		perror("");
+		ioctl(fd, FDKEJECT, NULL);
+		return(1);
+	}
+	return 0;
+}
+
+#define TRACKS(floppy) floppy.dkbuf.ncyl
+#define HEADS(floppy) floppy.dkbuf.nhead
+#define SECTORS(floppy) floppy.dkbuf.secptrack
+#define SECTORS_PER_DISK(floppy) floppy.dkmap.dkl_nblk
+#define FD_SECTSIZE(floppy) floppy.dkbuf.sec_size
+#define FD_SET_SECTSIZE(floppy,v) { floppy.dkbuf.sec_size = v; }
+
+static inline int set_parameters(int fd, struct generic_floppy_struct *floppy, 
+				 struct stat *buf)
+{
+	if (ioctl(fd, FDKIOSCHAR, &(floppy->dkbuf)) != 0) {
+		ioctl(fd, FDKEJECT, NULL);
+		perror("");
+		return(1);
+	}
+	
+	if (ioctl(fd, ( unsigned int) DKIOCSPART, &(floppy->dkmap)) != 0) {
+		ioctl(fd, FDKEJECT, NULL);
+		perror("");
+		return(1);
+	}
+	return 0;
+}
+#define INIT_GENERIC
+#endif /* sparc && sunos */
+
+
+#ifdef DPX1000
+#define predefined_devices
+struct device devices[] = {
+	/* [block device]: DPX1000 has /dev/flbm60, DPX2 has /dev/easyfb */
+	{"/dev/flbm60", "A", MHD514};
+	{"/dev/flbm60", "B", MDD514},
+	{"/dev/flbm60", "C", MDDsmall},
+	{"/dev/flbm60", "D", MSS},
+	{"/dev/flbm60", "E", MSSsmall},
+	REMOTE
+};
+#endif /* DPX1000 */
+
+#ifdef OS_bosx
+#define predefined_devices
+struct device devices[] = {
+	/* [block device]: DPX1000 has /dev/flbm60, DPX2 has /dev/easyfb */
+	{"/dev/easyfb", "A", MHD514},
+	{"/dev/easyfb", "B", MDD514},
+	{"/dev/easyfb", "C", MDDsmall},
+	{"/dev/easyfb", "D", MSS},
+	{"/dev/easyfb", "E", MSSsmall},
+	REMOTE
+};
+#endif /* OS_bosx */
+
+#ifdef OS_linux
+
+const char *error_msg[22]={
+"Missing Data Address Mark",
+"Bad cylinder",
+"Scan not satisfied",
+"Scan equal hit",
+"Wrong cylinder",
+"CRC error in data field",
+"Control Mark = deleted",
+0,
+
+"Missing Address Mark",
+"Write Protect",
+"No Data - unreadable",
+0,
+"OverRun",
+"CRC error in data or address",
+0,
+"End Of Cylinder",
+
+0,
+0,
+0,
+"Not ready",
+"Equipment check error",
+"Seek end" };
+
+
+static inline void print_message(RawRequest_t *raw_cmd,const char *message)
+{
+	int i, code;
+	if(!message)
+		return;
+
+	fprintf(stderr,"   ");
+	for (i=0; i< raw_cmd->cmd_count; i++)
+		fprintf(stderr,"%2.2x ", 
+			(int)raw_cmd->cmd[i] );
+	fprintf(stderr,"\n");
+	for (i=0; i< raw_cmd->reply_count; i++)
+		fprintf(stderr,"%2.2x ",
+			(int)raw_cmd->reply[i] );
+	fprintf(stderr,"\n");
+	code = (raw_cmd->reply[0] <<16) + 
+		(raw_cmd->reply[1] << 8) + 
+		raw_cmd->reply[2];
+	for(i=0; i<22; i++){
+		if ((code & (1 << i)) && error_msg[i])
+			fprintf(stderr,"%s\n",
+				error_msg[i]);
+	}
+}
+
+
+/* return values:
+ *  -1: Fatal error, don't bother retrying.
+ *   0: OK
+ *   1: minor error, retry
+ */
+
+int send_one_cmd(int fd, RawRequest_t *raw_cmd, const char *message)
+{
+	if (ioctl( fd, FDRAWCMD, raw_cmd) >= 0) {
+		if (raw_cmd->reply_count < 7) {
+			fprintf(stderr,"Short reply from FDC\n");
+			return -1;
+		}		
+		return 0;
+	}
+
+	switch(errno) {
+		case EBUSY:
+			fprintf(stderr, "FDC busy, sleeping for a second\n");
+			sleep(1);
+			return 1;
+		case EIO:
+			fprintf(stderr,"resetting controller\n");
+			if(ioctl(fd, FDRESET, 2)  < 0){
+				perror("reset");
+				return -1;
+			}
+			return 1;
+		default:
+			perror(message);
+			return -1;
+	}
+}
+
+
+/*
+ * return values
+ *  -1: error
+ *   0: OK, last sector
+ *   1: more raw commands follow
+ */
+
+int analyze_one_reply(RawRequest_t *raw_cmd, int *bytes, int do_print)
+{
+	
+	if(raw_cmd->reply_count == 7) {
+		int end;
+		
+		if (raw_cmd->reply[3] != raw_cmd->cmd[2]) {
+			/* end of cylinder */
+			end = raw_cmd->cmd[6] + 1;
+		} else {
+			end = raw_cmd->reply[5];
+		}
+
+		*bytes = end - raw_cmd->cmd[4];
+		/* FIXME: over/under run */
+		*bytes = *bytes << (7 + raw_cmd->cmd[5]);
+	} else
+		*bytes = 0;       
+
+	switch(raw_cmd->reply[0] & 0xc0){
+		case 0x40:
+			if ((raw_cmd->reply[0] & 0x38) == 0 &&
+			    (raw_cmd->reply[1]) == 0x80 &&
+			    (raw_cmd->reply[2]) == 0) {
+				*bytes += 1 << (7 + raw_cmd->cmd[5]);
+				break;
+			}
+
+			if ( raw_cmd->reply[1] & ST1_WP ){
+				*bytes = 0;
+				fprintf(stderr,
+					"This disk is write protected\n");
+				return -1;
+			}
+			if(!*bytes && do_print)
+				print_message(raw_cmd, "");
+			return -1;
+		case 0x80:
+			*bytes = 0;
+			fprintf(stderr,
+				"invalid command given\n");
+			return -1;
+		case 0xc0:
+			*bytes = 0;
+			fprintf(stderr,
+				"abnormal termination caused by polling\n");
+			return -1;
+		default:
+			break;
+	}	
+#ifdef FD_RAW_MORE
+	if(raw_cmd->flags & FD_RAW_MORE)
+		return 1;
+#endif
+	return 0;
+}
+
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/fd0", "A", 0, O_EXCL, 80,2, 18,0, MDEF_ARG},
+	{"/dev/fd1", "B", 0, O_EXCL, 0,0, 0,0, FDEF_ARG},
+	/* we assume that the Zip or Jaz drive is the second on the SCSI bus */
+	{"/dev/sdb4","J", GENHD },
+	{"/dev/sdb4","Z", GENHD },
+	/*	{"/dev/sda4","D", GENHD },*/
+	REMOTE
+};
+
+/*
+ * Stuffing back the floppy parameters into the driver allows for gems
+ * like 21 sector or single sided floppies from Atari ST systems.
+ * 
+ * Alain Knaff, Université Joseph Fourier, France, November 12, 1993.
+ */
+
+
+#define INIT_GENERIC
+#define generic_floppy_struct floppy_struct
+#define BLOCK_MAJOR 2
+#define SECTORS(floppy) floppy.sect
+#define TRACKS(floppy) floppy.track
+#define HEADS(floppy) floppy.head
+#define SECTORS_PER_DISK(floppy) floppy.size
+#define STRETCH(floppy) floppy.stretch
+#define USE_2M(floppy) ((floppy.rate & FD_2M) ? 0xff : 0x80 )
+#define SSIZE(floppy) ((((floppy.rate & 0x38) >> 3 ) + 2) % 8)
+
+static inline void set_2m(struct floppy_struct *floppy, int value)
+{
+	if (value & 0x7f)
+		value = FD_2M;
+	else
+		value = 0;
+	floppy->rate = (floppy->rate & ~FD_2M) | value;       
+}
+#define SET_2M set_2m
+
+static inline void set_ssize(struct floppy_struct *floppy, int value)
+{
+	value = (( (value & 7) + 6 ) % 8) << 3;
+
+	floppy->rate = (floppy->rate & ~0x38) | value;	
+}
+
+#define SET_SSIZE set_ssize
+
+static inline int set_parameters(int fd, struct floppy_struct *floppy, 
+				 struct stat *buf)
+{
+	if ( ( MINOR(buf->st_rdev ) & 0x7f ) > 3 )
+		return 1;
+	
+	return ioctl(fd, FDSETPRM, floppy);
+}
+
+static inline int get_parameters(int fd, struct floppy_struct *floppy)
+{
+	return ioctl(fd, FDGETPRM, floppy);
+}
+
+#endif /* linux */
+
+
+/* OS/2, gcc+emx */
+#ifdef __EMX__
+#define predefined_devices
+struct device devices[] = {
+  {"A:", "A", GENFD},
+  {"B:", "B", GENFD},
+};
+#define INIT_NOOP
+#endif
+
+
+
+/*** /jes -- for D.O.S. 486 BL DX2/80 ***/
+#ifdef OS_freebsd
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/rfd0.1440", "A", FHD312},
+	{"/dev/rfd0.720",  "A", FDD312},
+	{"/dev/rfd1.1200", "B", MHD514},
+	{"/dev/sd0s1",     "C", GENHD},
+	REMOTE
+};
+#endif /* __FreeBSD__ */
+ 
+/*** /jes -- for ALR 486 DX4/100 ***/
+#if defined(OS_netbsd)
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/rfd0a", "A", FHD312},
+	{"/dev/rfd0f", "A", FDD312},
+	{"/dev/rfd0f", "S", MDD312},
+	{"/dev/rfd1a", "B", FHD514},
+	{"/dev/rfd1d", "B", FDD514},
+	{"/dev/rfd1d", "T", MDD514},
+	{"/dev/rwd0d", "C", 16, 0, 0, 0, 0, 0, 63L*512L, DEF_ARG0(0)},
+	REMOTE
+};
+#endif /* OS_NetBSD */
+
+/* fgsch@openbsd.org 2000/05/19 */
+#if defined(OS_openbsd)
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/rfd0Bc", "A", FHD312},
+	{"/dev/rfd0Fc", "A", FDD312},
+	{"/dev/rfd1Cc", "B", FHD514},
+	{"/dev/rfd1Dc", "B", FDD514},
+	{"/dev/rwd0c", "C", 16, 0, 0, 0, 0, 0, 63L*512L, DEF_ARG0(0)},
+	REMOTE
+};
+#endif /* OS_openbsd */
+
+
+
+#if (!defined(predefined_devices) && defined (CPU_m68000) && defined (OS_sysv))
+#include <sys/gdioctl.h>
+
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/rfp020",		"A", 12,O_NDELAY,40,2, 9, 0, MDEF_ARG},
+	{"/usr/bin/DOS/dvd000", "C", GENFD},
+	REMOTE
+};
+
+#undef INIT_NOOP
+int init_geom(int fd, struct device *dev, struct device *orig_dev,
+	      struct stat *stat)
+{
+	struct gdctl gdbuf;
+
+	if (ioctl(fd, GDGETA, &gdbuf) == -1) {
+		ioctl(fd, GDDISMNT, &gdbuf);
+		return 1;
+	}
+	if((dev->use_2m & 0x7f) || (dev->ssize & 0x7f))
+		return 1;
+	
+	SET_INT(gdbuf.params.cyls,dev->ntracks);
+	SET_INT(gdbuf.params.heads,dev->nheads);
+	SET_INT(gdbuf.params.psectrk,dev->nsect);
+	dev->ntracks = gdbuf.params.cyls;
+	dev->nheads = gdbuf.params.heads;
+	dev->nsect = gdbuf.params.psectrk;
+	dev->use_2m = 0x80;
+	dev->ssize = 0x82;
+
+	gdbuf.params.pseccyl = gdbuf.params.psectrk * gdbuf.params.heads;
+	gdbuf.params.flags = 1;		/* disk type flag */
+	gdbuf.params.step = 0;		/* step rate for controller */
+	gdbuf.params.sectorsz = 512;	/* sector size */
+
+	if (ioctl(fd, GDSETA, &gdbuf) < 0) {
+		ioctl(fd, GDDISMNT, &gdbuf);
+		return(1);
+	}
+	return(0);
+}
+#endif /* (defined (m68000) && defined (sysv))*/
+
+#ifdef CPU_alpha
+#ifndef OS_osf4
+#ifdef __osf__
+#include <sys/fcntl.h>
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/rfd0c",		"A", GENFD},
+	REMOTE
+};
+#endif
+#endif
+#endif
+
+#ifdef OS_osf
+#ifndef predefined_devices
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/fd0a", "A",  MHD312 } };
+	REMOTE
+#endif
+#endif
+
+
+#ifdef OS_nextstep
+#define predefined_devices
+struct device devices[] = {
+#ifdef CPU_m68k
+	{"/dev/rfd0b", "A", MED312 },
+	REMOTE
+#else
+	{"/dev/rfd0b", "A", MHD312 },
+	REMOTE
+#endif
+};
+#endif
+
+
+#if (!defined(predefined_devices) && defined(OS_sysv4))
+#ifdef __uxp__
+#define predefined_devices
+struct device devices[] = {
+      {"/dev/fpd0",   "A", FHD312},
+      {"/dev/fpd0",   "A", FDD312},
+	  REMOTE
+};
+#else
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/rdsk/f1q15dt",	"B", FHD514},
+	{"/dev/rdsk/f1d9dt",	"B", FDD514},
+	{"/dev/rdsk/f1d8dt",	"B", FDDsmall},
+	{"/dev/rdsk/f03ht",	"A", FHD312},
+	{"/dev/rdsk/f03dt",	"A", FDD312},
+	{"/dev/rdsk/dos",	"C", GENHD},
+	REMOTE
+};
+#endif
+#endif /* sysv4 */
+
+#ifdef OS_Minix
+/* Minix and Minix-vmd device list.  Only present to attach the A: and B:
+ * drive letters to the floppies by default.  Other devices can be given
+ * a drive letter by linking the device file to /dev/dosX, where X is a
+ * drive letter.  Or one can use something like 'fd0:' for a drive name.
+ *						Kees J. Bot <kjb@cs.vu.nl>
+ */
+#include <minix/partition.h>
+#include <minix/u64.h>
+
+#define predefined_devices
+struct device devices[] = {
+	{"/dev/fd0", "A", GEN},
+	{"/dev/fd1", "B", GEN},
+};
+
+#undef INIT_NOOP
+int init_geom(int fd, struct device *dev, struct device *orig_dev,
+	      struct stat *stat)
+{
+	/* Try to obtain the device parameters from the device driver.
+	 * Don't fret if you can't, mtools will use the DOS boot block.
+	 */
+	struct partition geom;
+	unsigned long tot_sectors;
+
+	if (ioctl(fd, DIOCGETP, &geom) == 0) {
+		dev->hidden = div64u(geom.base, 512);
+		tot_sectors = div64u(geom.size, 512);
+		dev->tracks = tot_sectors / (geom.heads * geom.sectors);
+		dev->heads = geom.heads;
+		dev->sectors = geom.sectors;
+	}
+	return(0);
+}
+#endif /* OS_Minix */
+
+#ifdef INIT_GENERIC
+
+#ifndef USE_2M
+#define USE_2M(x) 0x80
+#endif
+
+#ifndef SSIZE
+#define SSIZE(x) 0x82
+#endif
+
+#ifndef SET_2M
+#define SET_2M(x,y) return -1
+#endif
+
+#ifndef SET_SSIZE
+#define SET_SSIZE(x,y) return -1
+#endif
+
+#undef INIT_NOOP
+int init_geom(int fd, struct device *dev, struct device *orig_dev,
+	      struct stat *stat)
+{
+	struct generic_floppy_struct floppy;
+	int change;
+	
+	/* 
+	 * succeed if we don't have a floppy
+	 * this is the case for dosemu floppy image files for instance
+	 */
+	if (!((S_ISBLK(stat->st_mode) && major(stat->st_rdev) == BLOCK_MAJOR)
+#ifdef CHAR_MAJOR
+	      || (S_ISCHR(stat->st_mode) && major(stat->st_rdev) == CHAR_MAJOR) 
+#endif
+		))
+		return compare_geom(dev, orig_dev);
+	
+	/*
+	 * We first try to get the current floppy parameters from the kernel.
+	 * This allows us to
+	 * 1. get the rate
+	 * 2. skip the parameter setting if the parameters are already o.k.
+	 */
+	
+	if (get_parameters( fd, & floppy ) )
+		/* 
+		 * autodetection failure.
+		 * This mostly occurs because of an absent or unformatted disks.
+		 *
+		 * It might also occur because of bizarre formats (for example 
+		 * rate 1 on a 3 1/2 disk).
+
+		 * If this is the case, the user should do an explicit 
+		 * setfdprm before calling mtools
+		 *
+		 * Another cause might be pre-existing wrong parameters. The 
+		 * user should do an setfdprm -c to repair this situation.
+		 *
+		 * ...fail immediately... ( Theoretically, we could try to save
+		 * the situation by trying out all rates, but it would be slow 
+		 * and awkward)
+		 */
+		return 1;
+
+
+	/* 
+	 * if we have already have the correct parameters, keep them.
+	 * the number of tracks doesn't need to match exactly, it may be bigger.
+	 * the number of heads and sectors must match exactly, to avoid 
+	 * miscalculation of the location of a block on the disk
+	 */
+	change = 0;
+	if(compare(dev->sectors, SECTORS(floppy))){
+		SECTORS(floppy) = dev->sectors;
+		change = 1;
+	} else
+		dev->sectors = SECTORS(floppy);
+
+	if(compare(dev->heads, HEADS(floppy))){
+		HEADS(floppy) = dev->heads;
+		change = 1;
+	} else
+		dev->heads = HEADS(floppy);
+	 
+	if(compare(dev->tracks, TRACKS(floppy))){
+		TRACKS(floppy) = dev->tracks;
+		change = 1;
+	} else
+		dev->tracks = TRACKS(floppy);
+
+
+	if(compare(dev->use_2m, USE_2M(floppy))){
+		SET_2M(&floppy, dev->use_2m);
+		change = 1;
+	} else
+		dev->use_2m = USE_2M(floppy);
+	
+	if( ! (dev->ssize & 0x80) )
+		dev->ssize = 0;
+	if(compare(dev->ssize, SSIZE(floppy) + 128)){
+		SET_SSIZE(&floppy, dev->ssize);
+		change = 1;
+	} else
+		dev->ssize = SSIZE(floppy);
+
+	if(!change)
+		/* no change, succeed */
+		return 0;
+
+#ifdef SECTORS_PER_TRACK
+	SECTORS_PER_TRACK(floppy) = dev->sectors * dev->heads;
+#endif
+
+#ifdef SECTORS_PER_DISK
+	SECTORS_PER_DISK(floppy) = dev->sectors * dev->heads * dev->tracks;
+#endif
+	
+#ifdef STRETCH
+	/* ... and the stretch */
+	if ( dev->tracks > 41 ) 
+		STRETCH(floppy) = 0;
+	else
+		STRETCH(floppy) = 1;
+#endif
+	
+	return set_parameters( fd, &floppy, stat) ;
+}
+#endif /* INIT_GENERIC */  
+
+#ifdef INIT_NOOP
+int init_geom(int fd, struct device *dev, struct device *orig_dev,
+			  struct stat *stat)
+{
+	return compare_geom(dev, orig_dev);
+}
+#endif
+
+#ifdef predefined_devices
+const int nr_const_devices = sizeof(const_devices) / sizeof(*const_devices);
+#else
+struct device devices[]={
+	{"/dev/fd0", "A", 0, O_EXCL, 0,0, 0,0, MDEF_ARG},
+	/* to shut up Ultrix's native compiler, we can't make this empty :( */
+};
+const nr_const_devices = 0;
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/devices.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/devices.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/devices.h	(revision 9)
@@ -0,0 +1,169 @@
+#ifdef OS_linux
+
+#ifdef HAVE_SYS_SYSMACROS_H
+
+#include <sys/sysmacros.h>
+#ifndef MAJOR
+#define MAJOR(dev) major(dev)
+#endif  /* MAJOR not defined */
+#ifndef MINOR
+#define MINOR(dev) minor(dev)
+#endif  /* MINOR not defined */
+
+#else
+ 
+#include <linux/fs.h>        /* get MAJOR/MINOR from Linux kernel */
+#ifndef major
+#define major(x) MAJOR(x)
+#endif
+
+#endif /* HAVE_SYS_SYSMACROS_H */
+
+#include <linux/fd.h>
+#include <linux/fdreg.h>
+#include <linux/major.h>
+
+
+typedef struct floppy_raw_cmd RawRequest_t;
+
+UNUSED(static inline void RR_INIT(struct floppy_raw_cmd *request))
+{
+	request->data = 0;
+	request->length = 0;
+	request->cmd_count = 9;
+	request->flags = FD_RAW_INTR | FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK
+#ifdef FD_RAW_SOFTFAILUE
+		| FD_RAW_SOFTFAILURE | FD_RAW_STOP_IF_FAILURE
+#endif
+		;
+	request->cmd[1] = 0;
+	request->cmd[6] = 0;
+	request->cmd[7] = 0x1b;
+	request->cmd[8] = 0xff;
+	request->reply_count = 0;
+}
+
+UNUSED(static inline void RR_SETRATE(struct floppy_raw_cmd *request, int rate))
+{
+	request->rate = rate;
+}
+
+UNUSED(static inline void RR_SETDRIVE(struct floppy_raw_cmd *request,int drive))
+{
+	request->cmd[1] = (request->cmd[1] & ~3) | (drive & 3);
+}
+
+UNUSED(static inline void RR_SETTRACK(struct floppy_raw_cmd *request,int track))
+{
+	request->cmd[2] = track;
+}
+
+UNUSED(static inline void RR_SETPTRACK(struct floppy_raw_cmd *request,
+				       int track))
+{
+	request->track = track;
+}
+
+UNUSED(static inline void RR_SETHEAD(struct floppy_raw_cmd *request, int head))
+{
+	if(head)
+		request->cmd[1] |= 4;
+	else
+		request->cmd[1] &= ~4;
+	request->cmd[3] = head;
+}
+
+UNUSED(static inline void RR_SETSECTOR(struct floppy_raw_cmd *request, 
+				       int sector))
+{
+	request->cmd[4] = sector;
+	request->cmd[6] = sector-1;
+}
+
+UNUSED(static inline void RR_SETSIZECODE(struct floppy_raw_cmd *request, 
+					 int sizecode))
+{
+	request->cmd[5] = sizecode;
+	request->cmd[6]++;
+	request->length += 128 << sizecode;
+}
+
+#if 0
+static inline void RR_SETEND(struct floppy_raw_cmd *request, int end)
+{
+	request->cmd[6] = end;
+}
+#endif
+
+UNUSED(static inline void RR_SETDIRECTION(struct floppy_raw_cmd *request, 
+					  int direction))
+{
+	if(direction == MT_READ) {
+		request->flags |= FD_RAW_READ;
+		request->cmd[0] = FD_READ & ~0x80;
+	} else {
+		request->flags |= FD_RAW_WRITE;
+		request->cmd[0] = FD_WRITE & ~0x80;
+	}
+}
+
+
+UNUSED(static inline void RR_SETDATA(struct floppy_raw_cmd *request, 
+				     caddr_t data))
+{
+	request->data = data;
+}
+
+
+#if 0
+static inline void RR_SETLENGTH(struct floppy_raw_cmd *request, int length)
+{
+	request->length += length;
+}
+#endif
+
+UNUSED(static inline void RR_SETCONT(struct floppy_raw_cmd *request))
+{
+#ifdef FD_RAW_MORE
+	request->flags |= FD_RAW_MORE;
+#endif
+}
+
+
+UNUSED(static inline int RR_SIZECODE(struct floppy_raw_cmd *request))
+{
+	return request->cmd[5];
+}
+
+
+
+UNUSED(static inline int RR_TRACK(struct floppy_raw_cmd *request))
+{
+	return request->cmd[2];
+}
+
+
+UNUSED(static inline int GET_DRIVE(int fd))
+{
+	struct stat statbuf;
+
+	if (fstat(fd, &statbuf) < 0 ){
+		perror("stat");
+		return -1;
+	}
+	  
+	if (!S_ISBLK(statbuf.st_mode) ||
+	    MAJOR(statbuf.st_rdev) != FLOPPY_MAJOR)
+		return -1;
+	
+	return MINOR( statbuf.st_rdev );
+}
+
+
+
+/* void print_message(RawRequest_t *raw_cmd,char *message);*/
+int send_one_cmd(int fd, RawRequest_t *raw_cmd, const char *message);
+int analyze_one_reply(RawRequest_t *raw_cmd, int *bytes, int do_print);
+
+
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/dirCache.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/dirCache.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/dirCache.c	(revision 9)
@@ -0,0 +1,329 @@
+#include "sysincludes.h"
+#include "vfat.h"
+#include "dirCache.h"
+
+
+void myfree(void *a)
+{
+	free(a);
+}
+
+#define free myfree
+
+
+#define BITS_PER_INT (sizeof(unsigned int) * 8)
+
+
+static inline unsigned int rol(unsigned int arg, int shift)
+{
+	arg &= 0xffffffff; /* for 64 bit machines */
+	return (arg << shift) | (arg >> (32 - shift));
+}
+
+
+static int calcHash(char *name)
+{
+	unsigned long hash;
+	int i;
+	unsigned char c;
+
+	hash = 0;
+	i = 0;
+	while(*name) {
+		/* rotate it */
+		hash = rol(hash,5); /* a shift of 5 makes sure we spread quickly
+				     * over the whole width, moreover, 5 is
+				     * prime with 32, which makes sure that
+				     * successive letters cannot cover each 
+				     * other easily */
+		c = toupper(*name);
+		hash ^=  (c * (c+2)) ^ (i * (i+2));
+		hash &= 0xffffffff;
+		i++, name++;
+	}
+	hash = hash * (hash + 2);
+	/* the following two xors make sure all info is spread evenly over all
+	 * bytes. Important if we only keep the low order bits later on */
+	hash ^= (hash & 0xfff) << 12;
+	hash ^= (hash & 0xff000) << 24;
+	return hash;
+}
+
+static int addBit(unsigned int *bitmap, int hash, int checkOnly)
+{
+	int bit, entry;
+
+	bit = 1 << (hash % BITS_PER_INT);
+	entry = (hash / BITS_PER_INT) % DC_BITMAP_SIZE;
+	
+	if(checkOnly)
+		return bitmap[entry] & bit;
+	else {
+		bitmap[entry] |= bit;
+		return 1;
+	}
+}
+
+static int _addHash(dirCache_t *cache, unsigned int hash, int checkOnly)
+{
+	return
+		addBit(cache->bm0, hash, checkOnly) &&
+		addBit(cache->bm1, rol(hash,12), checkOnly) &&
+		addBit(cache->bm2, rol(hash,24), checkOnly);
+}
+
+
+static void addNameToHash(dirCache_t *cache, char *name)
+{	
+	_addHash(cache, calcHash(name), 0);
+}
+
+static void hashDce(dirCache_t *cache, dirCacheEntry_t *dce)
+{
+	if(dce->beginSlot != cache->nrHashed)
+		return;
+	cache->nrHashed = dce->endSlot;
+	if(dce->longName)
+		addNameToHash(cache, dce->longName);
+	addNameToHash(cache, dce->shortName);
+}
+
+int isHashed(dirCache_t *cache, char *name)
+{
+	int ret;
+
+	ret =  _addHash(cache, calcHash(name), 1);
+	return ret;
+}
+
+void checkXYZ(dirCache_t *cache)
+{
+	if(cache->entries[2])
+		printf(" at 2 = %d\n", cache->entries[2]->beginSlot);
+}
+
+
+int growDirCache(dirCache_t *cache, int slot)
+{
+	if(slot < 0) {
+		fprintf(stderr, "Bad slot %d\n", slot);
+		exit(1);
+	}
+
+	if( cache->nr_entries <= slot) {
+		int i;
+		
+		cache->entries = realloc(cache->entries,
+					 (slot+1) * 2 * 
+					 sizeof(dirCacheEntry_t *));
+		if(!cache->entries)
+			return -1;
+		for(i= cache->nr_entries; i < (slot+1) * 2; i++) {
+			cache->entries[i] = 0;
+		}
+		cache->nr_entries = (slot+1) * 2;
+	}
+	return 0;
+}
+
+dirCache_t *allocDirCache(Stream_t *Stream, int slot)
+{       
+	dirCache_t **dcp;
+
+	if(slot < 0) {
+		fprintf(stderr, "Bad slot %d\n", slot);
+		exit(1);
+	}
+
+	dcp = getDirCacheP(Stream);
+	if(!*dcp) {
+		*dcp = New(dirCache_t);
+		if(!*dcp)
+			return 0;
+		(*dcp)->entries = NewArray((slot+1)*2+5, dirCacheEntry_t *);
+		if(!(*dcp)->entries) {
+			free(*dcp);
+			return 0;
+		}
+		(*dcp)->nr_entries = (slot+1) * 2;
+		memset( (*dcp)->bm0, 0, DC_BITMAP_SIZE);
+		memset( (*dcp)->bm1, 0, DC_BITMAP_SIZE);
+		memset( (*dcp)->bm2, 0, DC_BITMAP_SIZE);
+		(*dcp)->nrHashed = 0;
+	} else
+		if(growDirCache(*dcp, slot) < 0)
+			return 0;
+	return *dcp;
+}
+
+static void freeDirCacheRange(dirCache_t *cache, int beginSlot, int endSlot)
+{
+	dirCacheEntry_t *entry;
+	int clearBegin;
+	int clearEnd;
+	int i;
+
+	if(endSlot < beginSlot) {
+		fprintf(stderr, "Bad slots %d %d in free range\n", 
+			beginSlot, endSlot);
+		exit(1);
+	}
+
+	while(beginSlot < endSlot) {
+		entry = cache->entries[beginSlot];
+		if(!entry) {
+			beginSlot++;
+			continue;
+		}
+		
+		clearEnd = entry->endSlot;
+		if(clearEnd > endSlot)
+			clearEnd = endSlot;
+		clearBegin = beginSlot;
+		
+		for(i = clearBegin; i <clearEnd; i++)
+			cache->entries[i] = 0;
+
+		if(entry->endSlot == endSlot)
+			entry->endSlot = beginSlot;
+		else if(entry->beginSlot == beginSlot)
+			entry->beginSlot = endSlot;
+		else {
+			fprintf(stderr, 
+				"Internal error, non contiguous de-allocation\n");
+			fprintf(stderr, "%d %d\n", beginSlot, endSlot);
+			fprintf(stderr, "%d %d\n", entry->beginSlot, 
+				entry->endSlot);
+			exit(1);			
+		}
+
+		if(entry->beginSlot == entry->endSlot) {
+			if(entry->longName)
+				free(entry->longName);
+			if(entry->shortName)
+				free(entry->shortName);
+			free(entry);
+		}
+
+		beginSlot = clearEnd;
+	}
+}
+
+static dirCacheEntry_t *allocDirCacheEntry(dirCache_t *cache, int beginSlot, 
+					   int endSlot,
+					   dirCacheEntryType_t type)
+{
+	dirCacheEntry_t *entry;
+	int i;
+
+	if(growDirCache(cache, endSlot) < 0)
+		return 0;
+
+	entry = New(dirCacheEntry_t);
+	if(!entry)
+		return 0;
+	entry->type = type;
+	entry->longName = 0;
+	entry->shortName = 0;
+	entry->beginSlot = beginSlot;
+	entry->endSlot = endSlot;
+
+	freeDirCacheRange(cache, beginSlot, endSlot);
+	for(i=beginSlot; i<endSlot; i++) {
+		cache->entries[i] = entry;
+	}
+	return entry;
+}
+
+dirCacheEntry_t *addUsedEntry(dirCache_t *cache, int beginSlot, int endSlot, 
+			      char *longName, char *shortName,
+			      struct directory *dir)
+{
+	dirCacheEntry_t *entry;
+
+	if(endSlot < beginSlot) {
+		fprintf(stderr, 
+			"Bad slots %d %d in add used entry\n", 
+			beginSlot, endSlot);
+		exit(1);
+	}
+
+
+	entry = allocDirCacheEntry(cache, beginSlot, endSlot, DCET_USED);
+	if(!entry)
+		return 0;
+	
+	entry->beginSlot = beginSlot;
+	entry->endSlot = endSlot;
+	if(longName)
+		entry->longName = strdup(longName);
+	entry->shortName = strdup(shortName);
+	entry->dir = *dir;
+	hashDce(cache, entry);
+	return entry;
+}
+
+static void mergeFreeSlots(dirCache_t *cache, int slot)
+{
+	dirCacheEntry_t *previous, *next;
+	int i;
+
+	if(slot == 0)
+		return;
+	previous = cache->entries[slot-1];
+	next = cache->entries[slot];
+	if(next && next->type == DCET_FREE &&
+	   previous && previous->type == DCET_FREE) {
+		for(i=next->beginSlot; i < next->endSlot; i++)
+			cache->entries[i] = previous;
+		previous->endSlot = next->endSlot;
+		free(next);		
+	}
+}
+
+dirCacheEntry_t *addFreeEntry(dirCache_t *cache, int beginSlot, int endSlot)
+{
+	dirCacheEntry_t *entry;
+
+	if(beginSlot < cache->nrHashed)
+		cache->nrHashed = beginSlot;
+
+	if(endSlot < beginSlot) {
+		fprintf(stderr, "Bad slots %d %d in add free entry\n", 
+			beginSlot, endSlot);
+		exit(1);
+	}
+
+	if(endSlot == beginSlot)
+		return 0;
+	entry = allocDirCacheEntry(cache, beginSlot, endSlot, DCET_FREE);
+	mergeFreeSlots(cache, beginSlot);
+	mergeFreeSlots(cache, endSlot);
+	return cache->entries[beginSlot];
+}
+
+
+dirCacheEntry_t *addEndEntry(dirCache_t *cache, int pos)
+{
+	return allocDirCacheEntry(cache, pos, pos+1, DCET_END);
+}
+
+dirCacheEntry_t *lookupInDircache(dirCache_t *cache, int pos)
+{
+	if(growDirCache(cache, pos+1) < 0)
+		return 0;
+	return cache->entries[pos];	
+}
+
+void freeDirCache(Stream_t *Stream)
+{
+	dirCache_t *cache, **dcp;
+
+	dcp = getDirCacheP(Stream);
+	cache = *dcp;
+	if(cache) {
+		freeDirCacheRange(cache, 0, cache->nr_entries);
+		free(cache);
+		*dcp = 0;
+	}
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/dirCache.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/dirCache.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/dirCache.h	(revision 9)
@@ -0,0 +1,40 @@
+#ifndef MTOOLS_DIRCACHE_H
+#define MTOOLS_DIRCACHE_H
+
+typedef enum {
+	DCET_FREE,
+	DCET_USED,
+	DCET_END
+} dirCacheEntryType_t;
+
+#define DC_BITMAP_SIZE 128
+
+typedef struct dirCacheEntry_t {
+	dirCacheEntryType_t type;
+	int beginSlot;
+	int endSlot;
+	char *shortName;
+	char *longName;
+	struct directory dir;
+} dirCacheEntry_t;
+
+typedef struct dirCache_t {
+	struct dirCacheEntry_t **entries;
+	int nr_entries;
+	unsigned int nrHashed;
+	unsigned int bm0[DC_BITMAP_SIZE];
+	unsigned int bm1[DC_BITMAP_SIZE];
+	unsigned int bm2[DC_BITMAP_SIZE];
+} dirCache_t;
+
+int isHashed(dirCache_t *cache, char *name);
+int growDirCache(dirCache_t *cache, int slot);
+dirCache_t *allocDirCache(Stream_t *Stream, int slot);
+dirCacheEntry_t *addUsedEntry(dirCache_t *Stream, int begin, int end, 
+			      char *longName, char *shortName,
+			      struct directory *dir);
+void freeDirCache(Stream_t *Stream);
+dirCacheEntry_t *addFreeEntry(dirCache_t *Stream, int begin, int end);
+dirCacheEntry_t *addEndEntry(dirCache_t *Stream, int pos);
+dirCacheEntry_t *lookupInDircache(dirCache_t *Stream, int pos);
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/directory.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/directory.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/directory.c	(revision 9)
@@ -0,0 +1,106 @@
+#include "sysincludes.h"
+#include "msdos.h"
+#include "stream.h"
+#include "mtools.h"
+#include "file.h"
+#include "fs.h"
+
+/* #define DEBUG */
+
+/*
+ * Read a directory entry into caller supplied buffer
+ */
+struct directory *dir_read(direntry_t *entry, int *error)
+{
+	int n;
+	*error = 0;
+	if((n=force_read(entry->Dir, (char *) (&entry->dir), 
+			 (mt_off_t) entry->entry * MDIR_SIZE, 
+			 MDIR_SIZE)) != MDIR_SIZE) {
+		if (n < 0) {
+			*error = -1;
+		}
+		return NULL;
+	}
+	return &entry->dir;
+}
+
+/*
+ * Make a subdirectory grow in length.  Only subdirectories (not root)
+ * may grow.  Returns a 0 on success, 1 on failure (disk full), or -1
+ * on error.
+ */
+
+int dir_grow(Stream_t *Dir, int size)
+{
+	Stream_t *Stream = GetFs(Dir);
+	DeclareThis(FsPublic_t);
+	int ret;
+	int buflen;
+	char *buffer;
+	
+	if (!getfreeMinClusters(Dir, 1))
+		return -1;
+
+	buflen = This->cluster_size * This->sector_size;
+
+	if(! (buffer=malloc(buflen)) ){
+		perror("dir_grow: malloc");
+		return -1;
+	}
+		
+	memset((char *) buffer, '\0', buflen);
+	ret = force_write(Dir, buffer, (mt_off_t) size * MDIR_SIZE, buflen);
+	free(buffer);
+	if(ret < buflen)
+		return -1;
+	return 0;
+}
+
+
+void low_level_dir_write(direntry_t *entry)
+{
+	force_write(entry->Dir, 
+		    (char *) (&entry->dir), 
+		    (mt_off_t) entry->entry * MDIR_SIZE, MDIR_SIZE);
+}
+
+
+/*
+ * Make a directory entry.  Builds a directory entry based on the
+ * name, attribute, starting cluster number, and size.  Returns a pointer
+ * to a static directory structure.
+ */
+
+struct directory *mk_entry(const char *filename, char attr,
+			   unsigned int fat, size_t size, time_t date,
+			   struct directory *ndir)
+{
+	struct tm *now;
+	time_t date2 = date;
+	unsigned char hour, min_hi, min_low, sec;
+	unsigned char year, month_hi, month_low, day;
+
+	now = localtime(&date2);
+	strncpy(ndir->name, filename, 8);
+	strncpy(ndir->ext, filename + 8, 3);
+	ndir->attr = attr;
+	ndir->ctime_ms = 0;
+	hour = now->tm_hour << 3;
+	min_hi = now->tm_min >> 3;
+	min_low = now->tm_min << 5;
+	sec = now->tm_sec / 2;
+	ndir->ctime[1] = ndir->time[1] = hour + min_hi;
+	ndir->ctime[0] = ndir->time[0] = min_low + sec;
+	year = (now->tm_year - 80) << 1;
+	month_hi = (now->tm_mon + 1) >> 3;
+	month_low = (now->tm_mon + 1) << 5;
+	day = now->tm_mday;
+	ndir -> adate[1] = ndir->cdate[1] = ndir->date[1] = year + month_hi;
+	ndir -> adate[0] = ndir->cdate[0] = ndir->date[0] = month_low + day;
+
+	set_word(ndir->start, fat & 0xffff);
+	set_word(ndir->startHi, fat >> 16);
+	set_dword(ndir->size, size);
+	return ndir;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/direntry.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/direntry.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/direntry.c	(revision 9)
@@ -0,0 +1,119 @@
+#include "sysincludes.h"
+#include "msdos.h"
+#include "stream.h"
+#include "file.h"
+#include "mtoolsDirent.h"
+
+void initializeDirentry(direntry_t *entry, Stream_t *Dir)
+{
+	entry->entry = -1;
+/*	entry->parent = getDirentry(Dir);*/
+	entry->Dir = Dir;
+	entry->beginSlot = 0;
+	entry->endSlot = 0;
+}
+
+int isNotFound(direntry_t *entry)
+{
+	return entry->entry == -2;
+}
+
+void rewindEntry(direntry_t *entry)
+{
+	entry->entry = -1;
+}
+
+
+direntry_t *getParent(direntry_t *entry)
+{
+	return getDirentry(entry->Dir);
+}
+
+
+static int getPathLen(direntry_t *entry)
+{
+	int length=0;
+
+	while(1) {
+		if(entry->entry == -3) /* rootDir */
+			return strlen(getDrive(entry->Dir)) + 1 + length + 1;
+		
+		length += 1 + strlen(entry->name);
+		entry = getDirentry(entry->Dir);
+	}
+}
+
+static char *sprintPwd(direntry_t *entry, char *ptr)
+{
+	if(entry->entry == -3) {
+		strcpy(ptr, getDrive(entry->Dir));
+		strcat(ptr, ":/");
+		ptr = strchr(ptr, 0);
+	} else {
+		ptr = sprintPwd(getDirentry(entry->Dir), ptr);
+		if(ptr[-1] != '/')
+			*ptr++ = '/';
+		strcpy(ptr, entry->name);
+		ptr += strlen(entry->name);
+	}
+	return ptr;		
+}
+
+
+#define NEED_ESCAPE "\"$\\"
+
+static void _fprintPwd(FILE *f, direntry_t *entry, int recurs, int escape)
+{
+	if(entry->entry == -3) {
+		fputs(getDrive(entry->Dir), f);
+		putc(':', f);
+		if(!recurs)
+			putc('/', f);
+	} else {
+		_fprintPwd(f, getDirentry(entry->Dir), 1, escape);
+		if (escape && strpbrk(entry->name, NEED_ESCAPE)) {
+			char *ptr;
+			for(ptr = entry->name; *ptr; ptr++) {
+				if (strchr(NEED_ESCAPE, *ptr))
+					putc('\\', f);
+				putc(*ptr, f);
+			}
+		} else {
+			fprintf(f, "/%s", entry->name);
+		}
+	}
+}
+
+void fprintPwd(FILE *f, direntry_t *entry, int escape)
+{
+	if (escape)
+		putc('"', f);
+	_fprintPwd(f, entry, 0, escape);
+	if(escape)
+		putc('"', f);
+}
+
+char *getPwd(direntry_t *entry)
+{
+	int size;
+	char *ret;
+
+	size = getPathLen(entry);
+	ret = malloc(size+1);
+	if(!ret)
+		return 0;
+	sprintPwd(entry, ret);
+	return ret;
+}
+
+int isSubdirOf(Stream_t *inside, Stream_t *outside)
+{
+	while(1) {
+		if(inside == outside) /* both are the same */
+			return 1;
+		if(getDirentry(inside)->entry == -3) /* root directory */
+			return 0;
+		/* look further up */
+		inside = getDirentry(inside)->Dir;
+	}			
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/expand.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/expand.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/expand.c	(revision 9)
@@ -0,0 +1,83 @@
+/*
+ * Do filename expansion with the shell.
+ */
+
+#define EXPAND_BUF	2048
+
+#include "sysincludes.h"
+#include "mtools.h"
+
+
+int safePopenOut(char **command, char *output, int len)
+{
+	int pipefd[2];
+	pid_t pid;
+	int status;
+	int last;
+
+	if(pipe(pipefd)) {
+		return -2;
+	}
+	switch((pid=fork())){
+		case -1:
+			return -2;
+		case 0: /* the son */
+			close(pipefd[0]);
+			destroy_privs();
+			close(1);
+			close(2); /* avoid nasty error messages on stderr */
+			dup(pipefd[1]);
+			close(pipefd[1]);
+			execvp(command[0], command+1);
+			exit(1);
+		default:
+			close(pipefd[1]);
+			break;
+	}
+	last=read(pipefd[0], output, len);
+	kill(pid,9);
+	wait(&status);
+	if(last<0) {
+		return -1;
+	}
+	return last;
+}
+
+
+
+const char *expand(const char *input, char *ans)
+{
+	int last;
+	char buf[256];
+	char *command[] = { "/bin/sh", "sh", "-c", 0, 0 };
+
+	ans[EXPAND_BUF-1]='\0';
+
+	if (input == NULL)
+		return(NULL);
+	if (*input == '\0')
+		return("");
+					/* any thing to expand? */
+	if (!strpbrk(input, "$*(){}[]\\?`~")) {
+		strncpy(ans, input, EXPAND_BUF-1);
+		return(ans);
+	}
+					/* popen an echo */
+#ifdef HAVE_SNPRINTF
+	snprintf(buf, 255, "echo %s", input);
+#else
+	sprintf(buf, "echo %s", input);
+#endif
+
+	command[3]=buf;
+	last=safePopenOut(command, ans, EXPAND_BUF-1);
+	if(last<0) {
+		perror("Pipe read error");
+		exit(1);
+	}
+	if(last)
+		ans[last-1] = '\0';
+	else
+		strncpy(ans, input, EXPAND_BUF-1);
+	return ans;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/fat.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/fat.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/fat.c	(revision 9)
@@ -0,0 +1,929 @@
+#include "sysincludes.h"
+#include "msdos.h"
+#include "stream.h"
+#include "mtools.h"
+#include "fsP.h"
+
+extern Stream_t *default_drive;
+
+#ifdef HAVE_LONG_LONG
+typedef long long fatBitMask;
+#else
+typedef long fatBitMask;
+#endif
+
+typedef struct FatMap_t {
+	unsigned char *data;
+	fatBitMask dirty;
+	fatBitMask valid;
+} FatMap_t;
+
+#define SECT_PER_ENTRY (sizeof(fatBitMask)*8)
+#define ONE ((fatBitMask) 1)
+
+static inline int readSector(Fs_t *This, char *buf, unsigned int off,
+					  size_t size)
+{
+	return READS(This->Next, buf, sectorsToBytes((Stream_t *)This, off), 
+				 size << This->sectorShift);
+}
+
+
+static inline int forceReadSector(Fs_t *This, char *buf, unsigned int off,
+								  size_t size)
+{
+	return force_read(This->Next, buf, sectorsToBytes((Stream_t *)This, off), 
+					  size << This->sectorShift);
+}
+
+
+static inline int writeSector(Fs_t *This, char *buf, unsigned int off,
+							  size_t size)
+{
+	return WRITES(This->Next, buf, sectorsToBytes((Stream_t*)This, off), 
+				  size << This->sectorShift);
+}
+
+static inline int forceWriteSector(Fs_t *This, char *buf, unsigned int off,
+					  size_t size)
+{
+	return force_write(This->Next, buf, sectorsToBytes((Stream_t*)This, off), 
+					   size << This->sectorShift);
+}
+
+
+static FatMap_t *GetFatMap(Fs_t *Stream)
+{
+	int nr_entries,i;
+	FatMap_t *map;
+
+	Stream->fat_error = 0;
+	nr_entries = (Stream->fat_len + SECT_PER_ENTRY - 1) / SECT_PER_ENTRY;
+	map = NewArray(nr_entries, FatMap_t);
+	if(!map)
+		return 0;
+
+	for(i=0; i< nr_entries; i++) {
+		map[i].data = 0;
+		map[i].valid = 0;
+		map[i].dirty = 0;
+	}
+
+	return map;
+}
+
+static inline int locate(Fs_t *Stream, int offset, int *slot, int *bit)
+{
+	if(offset >= Stream->fat_len)
+		return -1;
+	*slot = offset / SECT_PER_ENTRY;
+	*bit = offset % SECT_PER_ENTRY;
+	return 0;
+}
+
+static inline int fatReadSector(Fs_t *This, int sector, int slot, 
+				int bit, int dupe)
+{
+	int fat_start, ret;
+
+	dupe = (dupe + This->primaryFat) % This->num_fat;
+	fat_start = This->fat_start + This->fat_len * dupe;
+	
+	/* first, read as much as the buffer can give us */
+	ret = readSector(This,
+					 (char *)(This->FatMap[slot].data+(bit<<This->sectorShift)),
+					 fat_start+sector,
+					 (SECT_PER_ENTRY - bit%SECT_PER_ENTRY));
+	if(ret < 0)
+		return 0;
+
+	if(ret < This->sector_size) {
+		/* if we got less than one sector's worth, insist to get at
+		 * least one sector */
+		ret = forceReadSector(This,
+							  (char *) (This->FatMap[slot].data + 
+										(bit << This->sectorShift)),
+							  fat_start+sector, 1);
+		if(ret < This->sector_size)
+			return 0;
+		return 1;
+	}
+
+	return ret >> This->sectorShift;
+}
+
+
+static int fatWriteSector(Fs_t *This, int sector, int slot, int bit, int dupe)
+{
+	int fat_start;
+
+	dupe = (dupe + This->primaryFat) % This->num_fat;
+	if(dupe && !This->writeAllFats)
+		return This->sector_size;
+
+	fat_start = This->fat_start + This->fat_len * dupe;
+
+	return forceWriteSector(This,
+							(char *) 
+							(This->FatMap[slot].data + bit * This->sector_size),
+							fat_start+sector, 1);
+}
+
+static unsigned char *loadSector(Fs_t *This,
+				 unsigned int sector, fatAccessMode_t mode,
+				 int recurs)
+{
+	int slot, bit, i, ret;
+
+	if(locate(This,sector, &slot, &bit) < 0)
+		return 0;
+#if 0
+        if (((This->fat_len + SECT_PER_ENTRY - 1) / SECT_PER_ENTRY) <= slot) {
+		fprintf(stderr,"This should not happen\n");
+		fprintf(stderr, "fat_len = %d\n", This->fat_len);
+		fprintf(stderr, "SECT_PER_ENTRY=%d\n", (int)SECT_PER_ENTRY);
+		fprintf(stderr, "sector = %d slot = %d bit=%d\n", 
+			sector, slot, bit);
+		fprintf(stderr, "left = %d",(int)
+			((This->fat_len+SECT_PER_ENTRY-1) / SECT_PER_ENTRY));
+                return 0;
+	}
+#endif
+	if(!This->FatMap[slot].data) {
+		/* allocate the storage space */
+		This->FatMap[slot].data = 
+			malloc(This->sector_size * SECT_PER_ENTRY);
+		if(!This->FatMap[slot].data)
+			return 0;
+		memset(This->FatMap[slot].data, 0xee,
+		       This->sector_size * SECT_PER_ENTRY);
+	}
+
+	if(! (This->FatMap[slot].valid & (ONE << bit))) {
+		ret = -1;
+		for(i=0; i< This->num_fat; i++) {
+			/* read the sector */
+			ret = fatReadSector(This, sector, slot, bit, i);
+
+			if(ret == 0) {
+				fprintf(stderr,
+					"Error reading fat number %d\n", i);
+				continue;
+			}
+			break;
+		}
+
+		/* all copies bad.  Return error */
+		if(ret == 0)
+			return 0;
+
+		for(i=0; i < ret; i++)
+			This->FatMap[slot].valid |= ONE << (bit + i);
+
+		if(!recurs && ret == 1)
+			/* do some prefetching, if we happened to only
+			 * get one sector */
+			loadSector(This, sector+1, mode, 1);
+		if(!recurs && batchmode)
+			for(i=0; i < 1024; i++)
+				loadSector(This, sector+i, mode, 1);
+	}
+
+	if(mode == FAT_ACCESS_WRITE) {
+		This->FatMap[slot].dirty |= ONE << bit;
+		This->fat_dirty = 1;
+	}
+	return This->FatMap[slot].data + (bit << This->sectorShift);
+}
+
+
+static unsigned char *getAddress(Fs_t *Stream,
+				 unsigned int num, fatAccessMode_t mode)
+{
+	unsigned char *ret;
+	int sector;
+	int offset;
+
+	sector = num >> Stream->sectorShift;
+	ret = 0;
+	if(sector == Stream->lastFatSectorNr &&
+	   Stream->lastFatAccessMode >= mode)
+		ret = Stream->lastFatSectorData;
+	if(!ret) {		
+		ret = loadSector(Stream, sector, mode, 0);
+		if(!ret)
+			return 0;
+		Stream->lastFatSectorNr = sector;
+		Stream->lastFatSectorData = ret;
+		Stream->lastFatAccessMode = mode;
+	}
+	offset = num & Stream->sectorMask;
+	return ret+offset;
+}
+
+
+static int readByte(Fs_t *Stream, int start)
+{
+	unsigned char *address;
+	
+	address = getAddress(Stream, start, FAT_ACCESS_READ);
+	if(!address)
+		return -1;
+	return *address;
+}
+
+
+/*
+ * Fat 12 encoding:
+ *	|    byte n     |   byte n+1    |   byte n+2    |
+ *	|7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
+ *	| | | | | | | | | | | | | | | | | | | | | | | | |
+ *	| n+0.0 | n+0.5 | n+1.0 | n+1.5 | n+2.0 | n+2.5 |
+ *	    \_____  \____   \______/________/_____   /
+ *	      ____\______\________/   _____/  ____\_/
+ *	     /     \      \          /       /     \
+ *	| n+1.5 | n+0.0 | n+0.5 | n+2.0 | n+2.5 | n+1.0 |
+ *	|      FAT entry k      |    FAT entry k+1      |
+ */
+ 
+ /*
+ * Get and decode a FAT (file allocation table) entry.  Returns the cluster
+ * number on success or 1 on failure.
+ */
+
+static unsigned int fat12_decode(Fs_t *Stream, unsigned int num)
+{
+	unsigned int start = num * 3 / 2;
+	int byte0 = readByte(Stream, start);
+	int byte1 = readByte(Stream, start+1);
+       
+	if (num < 2 || byte0 < 0 || byte1 < 0 || num > Stream->num_clus+1) {
+		fprintf(stderr,"[1] Bad address %d\n", num);
+		return 1;
+	}
+
+	if (num & 1)
+		return (byte1 << 4) | ((byte0 & 0xf0)>>4);
+	else
+		return ((byte1 & 0xf) << 8) | byte0;
+}
+
+
+/*
+ * Puts a code into the FAT table.  Is the opposite of fat_decode().  No
+ * sanity checking is done on the code.  Returns a 1 on error.
+ */
+static void fat12_encode(Fs_t *Stream, unsigned int num, unsigned int code)
+{
+	int start = num * 3 / 2;
+	unsigned char *address0 = getAddress(Stream, start, FAT_ACCESS_WRITE);
+	unsigned char *address1 = getAddress(Stream, start+1, FAT_ACCESS_WRITE);
+
+	if (num & 1) {
+		/* (odd) not on byte boundary */
+		*address0 = (*address0 & 0x0f) | ((code << 4) & 0xf0);
+		*address1 = (code >> 4) & 0xff;
+	} else {
+		/* (even) on byte boundary */
+		*address0 = code & 0xff;
+		*address1 = (*address1 & 0xf0) | ((code >> 8) & 0x0f);
+	}
+}
+
+
+/*
+ * Fat 16 encoding:
+ *	|    byte n     |   byte n+1    |
+ *	|7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
+ *	| | | | | | | | | | | | | | | | |
+ *	|         FAT entry k           |
+ */
+
+static unsigned int fat16_decode(Fs_t *Stream, unsigned int num)
+{
+	unsigned char *address = getAddress(Stream, num << 1, FAT_ACCESS_READ);
+	return _WORD(address);
+}
+
+static void fat16_encode(Fs_t *Stream, unsigned int num, unsigned int code)
+{       
+	unsigned char *address = getAddress(Stream, num << 1, FAT_ACCESS_WRITE);
+	set_word(address, code);
+}
+
+
+static unsigned int fast_fat16_decode(Fs_t *Stream, unsigned int num)
+{
+	unsigned short *address = 
+		(unsigned short *) getAddress(Stream, num << 1, 
+					      FAT_ACCESS_READ);
+	return *address;
+}
+
+static void fast_fat16_encode(Fs_t *Stream, unsigned int num, unsigned int code)
+{       
+	unsigned short *address = 
+		(unsigned short *) getAddress(Stream, num << 1, 
+					      FAT_ACCESS_WRITE);
+	*address = code;
+}
+
+
+
+
+/*
+ * Fat 32 encoding
+ */
+static unsigned int fat32_decode(Fs_t *Stream, unsigned int num)
+{
+	unsigned char *address = getAddress(Stream, num << 2, FAT_ACCESS_READ);
+	return _DWORD(address);
+}
+
+static void fat32_encode(Fs_t *Stream, unsigned int num, unsigned int code)
+{       
+	unsigned char *address = getAddress(Stream, num << 2, FAT_ACCESS_WRITE);
+	set_dword(address, code);
+}
+
+
+static unsigned int fast_fat32_decode(Fs_t *Stream, unsigned int num)
+{
+	unsigned int *address = 
+		(unsigned int *) getAddress(Stream, num << 2, 
+					    FAT_ACCESS_READ);
+	return *address;
+}
+
+static void fast_fat32_encode(Fs_t *Stream, unsigned int num, unsigned int code)
+{       
+	unsigned int *address = 
+		(unsigned int *) getAddress(Stream, num << 2, 
+					    FAT_ACCESS_WRITE);
+	*address = code;
+}
+
+
+/*
+ * Write the FAT table to the disk.  Up to now the FAT manipulation has
+ * been done in memory.  All errors are fatal.  (Might not be too smart
+ * to wait till the end of the program to write the table.  Oh well...)
+ */
+
+void fat_write(Fs_t *This)
+{
+	int i, j, dups, ret, bit, slot;
+	int fat_start;
+
+	/*fprintf(stderr, "Fat write\n");*/
+
+	if (!This->fat_dirty)
+		return;
+
+	dups = This->num_fat;
+	if (This->fat_error)
+		dups = 1;
+
+
+	for(i=0; i<dups; i++){
+		j = 0;
+		fat_start = This->fat_start + i*This->fat_len;
+		for(slot=0;j<This->fat_len;slot++) {
+			if(!This->FatMap[slot].dirty) {
+				j += SECT_PER_ENTRY;
+				continue;
+			}
+			for(bit=0; 
+			    bit < SECT_PER_ENTRY && j<This->fat_len;
+			    bit++,j++) {
+				if(!(This->FatMap[slot].dirty & (ONE << bit)))
+					continue;
+				ret = fatWriteSector(This,j,slot, bit, i);
+				if (ret < This->sector_size){
+					if (ret < 0 ){
+						perror("error in fat_write");
+						exit(1);
+					} else {
+						fprintf(stderr,
+							"end of file in fat_write\n");
+						exit(1);
+					}
+				}
+				/* if last dupe, zero it out */
+				if(i==dups-1)
+					This->FatMap[slot].dirty &= ~(1<<bit);
+			}
+		}	 
+	}
+	/* write the info sector, if any */
+	if(This->infoSectorLoc && This->infoSectorLoc != MAX32) {
+		/* initialize info sector */
+		InfoSector_t *infoSector;
+		infoSector = (InfoSector_t *) safe_malloc(This->sector_size);
+		set_dword(infoSector->signature1, INFOSECT_SIGNATURE1);
+		memset(infoSector->filler1, sizeof(infoSector->filler1),0);
+		memset(infoSector->filler2, sizeof(infoSector->filler2),0);
+		set_dword(infoSector->signature2, INFOSECT_SIGNATURE2);
+		set_dword(infoSector->pos, This->last);
+		set_dword(infoSector->count, This->freeSpace);
+		set_dword(infoSector->signature3, 0xaa55);
+		if(forceWriteSector(This, (char *)infoSector, This->infoSectorLoc, 1) !=
+		   This->sector_size)
+			fprintf(stderr,"Trouble writing the info sector\n");
+		free(infoSector);
+	}
+	This->fat_dirty = 0;
+	This->lastFatAccessMode = FAT_ACCESS_READ;
+}
+
+
+
+/*
+ * Zero-Fat
+ * Used by mformat.
+ */
+int zero_fat(Fs_t *Stream, int media_descriptor)
+{
+	int i, j;
+	int fat_start;
+	unsigned char *buf;
+
+	buf = malloc(Stream->sector_size);
+	if(!buf) {
+		perror("alloc fat sector buffer");
+		return -1;
+	}
+	for(i=0; i< Stream->num_fat; i++) {
+		fat_start = Stream->fat_start + i*Stream->fat_len;
+		for(j = 0; j < Stream->fat_len; j++) {
+			if(j <= 1)
+				memset(buf, 0, Stream->sector_size);
+			if(!j) {
+				buf[0] = media_descriptor;
+				buf[2] = buf[1] = 0xff;
+				if(Stream->fat_bits > 12)
+					buf[3] = 0xff;
+				if(Stream->fat_bits > 16) {
+					buf[4] = 0xff;
+					buf[5] = 0xff;
+					buf[6] = 0xff;
+					buf[7] = 0x0f;
+				}
+			}
+
+			if(forceWriteSector(Stream, (char *)buf,
+								fat_start + j, 1) !=
+			   Stream->sector_size) {
+				fprintf(stderr,
+						"Trouble initializing a FAT sector\n");
+				free(buf);
+				return -1;
+			}
+		}
+	}
+	
+	free(buf);
+	Stream->FatMap = GetFatMap(Stream);
+	if (Stream->FatMap == NULL) {
+		perror("alloc fat map");
+		return -1;
+	}
+	return 0;
+}
+
+
+void set_fat12(Fs_t *This)
+{
+	This->fat_bits = 12;
+	This->end_fat = 0xfff;
+	This->last_fat = 0xff6;
+	This->fat_decode = fat12_decode;
+	This->fat_encode = fat12_encode;
+}
+
+static char word_endian_test[] = { 0x34, 0x12 };
+
+void set_fat16(Fs_t *This)
+{
+	This->fat_bits = 16;
+	This->end_fat = 0xffff;
+	This->last_fat = 0xfff6;
+
+	if(sizeof(unsigned short) == 2 &&  
+	   * (unsigned short *) word_endian_test == 0x1234) {
+		This->fat_decode = fast_fat16_decode;
+		This->fat_encode = fast_fat16_encode;
+	} else {
+		This->fat_decode = fat16_decode;
+		This->fat_encode = fat16_encode;
+	}
+}
+
+static char dword_endian_test[] = { 0x78, 0x56, 0x34, 0x12 };
+
+void set_fat32(Fs_t *This)
+{
+	This->fat_bits = 32;
+	This->end_fat = 0xfffffff;
+	This->last_fat = 0xffffff6;
+	
+	if(sizeof(unsigned int) == 4 &&  
+	   * (unsigned int *) dword_endian_test == 0x12345678) {
+		This->fat_decode = fast_fat32_decode;
+		This->fat_encode = fast_fat32_encode;
+	} else {
+		This->fat_decode = fat32_decode;
+		This->fat_encode = fat32_encode;
+	}
+}
+
+
+static int check_fat(Fs_t *This)
+{
+	/* 
+	 * This is only a sanity check.  For disks with really big FATs,
+	 * there is no point in checking the whole FAT.
+	 */
+
+	int i, f, tocheck;
+	if(mtools_skip_check)
+		return 0;
+
+	/* too few sectors in the FAT */
+	if(This->fat_len < NEEDED_FAT_SIZE(This))
+		return -1;
+	/* we do not warn about too much sectors in FAT, which may
+	 * happen when a partition has been shrunk using FIPS, or on
+	 * other occurrences */
+	
+	tocheck = This->num_clus;
+	if (tocheck < 0 || tocheck + 1 >= This->last_fat) {
+		fprintf(stderr, "Too many clusters in FAT\n");
+		return -1;
+	}
+
+	if(tocheck > 4096)
+		tocheck = 4096;
+
+	for ( i= 3 ; i < tocheck; i++){
+		f = This->fat_decode(This,i);
+		if (f == 1 || (f < This->last_fat && f > This->num_clus)){
+			fprintf(stderr,
+				"Cluster # at %d too big(%#x)\n", i,f);
+			fprintf(stderr,"Probably non MS-DOS disk\n");
+			return -1;
+		}
+	}
+	return 0;
+}
+
+
+/*
+ * Read the first sector of FAT table into memory.  Crude error detection on
+ * wrong FAT encoding scheme.
+ */
+static int check_media_type(Fs_t *This, struct bootsector *boot, 
+			    unsigned int tot_sectors)
+{
+	unsigned char *address;
+
+	This->num_clus = (tot_sectors - This->clus_start) / This->cluster_size;
+
+	This->FatMap = GetFatMap(This);
+	if (This->FatMap == NULL) {
+		perror("alloc fat map");
+		return -1;
+	}
+
+	address = getAddress(This, 0, FAT_ACCESS_READ);
+	if(!address) {
+		fprintf(stderr,
+			"Could not read first FAT sector\n");
+		return -1;
+	}
+
+	if(mtools_skip_check)
+		return 0;
+
+	if(!address[0] && !address[1] && !address[2])
+		/* Some Atari disks have zeroes where Dos has media descriptor
+		 * and 0xff.  Do not consider this as an error */
+		return 0;
+	
+	if((address[0] != boot->descr && boot->descr >= 0xf0 &&
+	    ((address[0] != 0xf9 && address[0] != 0xf7) 
+	     || boot->descr != 0xf0)) || address[0] < 0xf0) {
+		fprintf(stderr,
+			"Bad media types %02x/%02x, probably non-MSDOS disk\n", 
+				address[0],
+				boot->descr);
+		return -1;
+	}
+
+	if(address[1] != 0xff || address[2] != 0xff){
+		fprintf(stderr,"Initial byte of fat is not 0xff\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int fat_32_read(Fs_t *This, struct bootsector *boot, 
+		       unsigned int tot_sectors)
+{
+	int size;
+
+	This->fat_len = DWORD(ext.fat32.bigFat);
+	This->writeAllFats = !(boot->ext.fat32.extFlags[0] & 0x80);
+	This->primaryFat = boot->ext.fat32.extFlags[0] & 0xf;
+	This->rootCluster = DWORD(ext.fat32.rootCluster);
+	This->clus_start = This->fat_start + This->num_fat * This->fat_len;
+
+	/* read the info sector */
+	size = This->sector_size;
+	This->infoSectorLoc = WORD(ext.fat32.infoSector);
+	if(This->sector_size >= 512 &&
+	   This->infoSectorLoc && This->infoSectorLoc != MAX32) {
+		InfoSector_t *infoSector;
+		infoSector = (InfoSector_t *) safe_malloc(size);
+		if(forceReadSector(This, (char *)infoSector,
+						   This->infoSectorLoc, 1) == This->sector_size &&
+		   _DWORD(infoSector->signature1) == INFOSECT_SIGNATURE1 &&
+		   _DWORD(infoSector->signature2) == INFOSECT_SIGNATURE2) {
+			This->freeSpace = _DWORD(infoSector->count);
+			This->last = _DWORD(infoSector->pos);
+		}
+		free(infoSector);
+	}
+	
+	set_fat32(This);
+	return(check_media_type(This,boot, tot_sectors) ||
+	       check_fat(This));
+}
+
+
+static int old_fat_read(Fs_t *This, struct bootsector *boot, 
+						int config_fat_bits,
+						size_t tot_sectors, int nodups)
+{
+	This->writeAllFats = 1;
+	This->primaryFat = 0;
+	This->dir_start = This->fat_start + This->num_fat * This->fat_len;
+	This->clus_start = This->dir_start + This->dir_len;
+	This->infoSectorLoc = MAX32;
+
+	if(nodups)
+		This->num_fat = 1;
+
+	if(check_media_type(This,boot, tot_sectors))
+		return -1;
+
+	if(This->num_clus > FAT12) {
+		set_fat16(This);
+		/* third FAT byte must be 0xff */
+		if(!mtools_skip_check && readByte(This, 3) != 0xff)
+			return -1;
+	} else
+		set_fat12(This);
+
+	return check_fat(This);
+}
+
+/*
+ * Read the first sector of the  FAT table into memory and initialize 
+ * structures.
+ */
+int fat_read(Fs_t *This, struct bootsector *boot, int fat_bits,
+	   size_t tot_sectors, int nodups)
+{
+	This->fat_error = 0;
+	This->fat_dirty = 0;
+	This->last = MAX32;
+	This->freeSpace = MAX32;
+	This->lastFatSectorNr = 0;
+	This->lastFatSectorData = 0;
+
+	if(This->fat_len)
+		return old_fat_read(This, boot, fat_bits, tot_sectors, nodups);
+	else
+		return fat_32_read(This, boot, tot_sectors);
+}
+
+
+unsigned int fatDecode(Fs_t *This, unsigned int pos)
+{
+	int ret;
+
+	ret = This->fat_decode(This, pos);
+	if(ret && (ret < 2 || ret > This->num_clus+1) && ret < This->last_fat) {
+		fprintf(stderr, "Bad FAT entry %d at %d\n", ret, pos);
+		This->fat_error++;
+	}
+	return ret;
+}
+
+/* append a new cluster */
+void fatAppend(Fs_t *This, unsigned int pos, unsigned int newpos)
+{
+	This->fat_encode(This, pos, newpos);
+	This->fat_encode(This, newpos, This->end_fat);
+	if(This->freeSpace != MAX32)
+		This->freeSpace--;
+}
+
+/* de-allocates the given cluster */
+void fatDeallocate(Fs_t *This, unsigned int pos)
+{
+	This->fat_encode(This, pos, 0);
+	if(This->freeSpace != MAX32)
+		This->freeSpace++;
+}
+
+/* allocate a new cluster */
+void fatAllocate(Fs_t *This, unsigned int pos, unsigned int value)
+{
+	This->fat_encode(This, pos, value);
+	if(This->freeSpace != MAX32)
+		This->freeSpace--;
+}
+
+void fatEncode(Fs_t *This, unsigned int pos, unsigned int value)
+{
+	unsigned int oldvalue = This->fat_decode(This, pos);
+	This->fat_encode(This, pos, value);
+	if(This->freeSpace != MAX32) {
+		if(oldvalue)
+			This->freeSpace++;
+		if(value)
+			This->freeSpace--;
+	}
+}
+
+unsigned int get_next_free_cluster(Fs_t *This, unsigned int last)
+{
+	int i;
+
+	if(This->last != MAX32)
+		last = This->last;
+
+	if (last < 2 ||
+	    last >= This->num_clus+1)
+		last = 1;
+
+	for (i=last+1; i< This->num_clus+2; i++) {
+		if (!fatDecode(This, i)) {
+			This->last = i;
+			return i;
+		}
+	}
+
+	for(i=2; i < last+1; i++) {
+		if (!fatDecode(This, i)) {
+			This->last = i;
+			return i;
+		}
+	}
+
+
+	fprintf(stderr,"No free cluster %d %d\n", This->preallocatedClusters,
+		This->last);
+	return 1;
+}
+
+int fat_error(Stream_t *Dir)
+{
+	Stream_t *Stream = GetFs(Dir);
+	DeclareThis(Fs_t);
+
+	if(This->fat_error)
+		fprintf(stderr,"Fat error detected\n");
+
+	return This->fat_error;
+}
+
+int fat32RootCluster(Stream_t *Dir)
+{
+	Stream_t *Stream = GetFs(Dir);
+	DeclareThis(Fs_t);
+	
+	if(This->fat_bits == 32)
+		return This->rootCluster;
+	else
+		return 0;
+}
+
+
+/*
+ * Get the amount of free space on the diskette
+ */
+
+mt_size_t getfree(Stream_t *Dir)
+{
+	Stream_t *Stream = GetFs(Dir);
+	DeclareThis(Fs_t);
+
+	if(This->freeSpace == MAX32 || This->freeSpace == 0) {
+		register unsigned int i;
+		size_t total;
+
+		total = 0L;
+		for (i = 2; i < This->num_clus + 2; i++)
+			if (!fatDecode(This,i))
+				total++;
+		This->freeSpace = total;
+	}
+	return sectorsToBytes((Stream_t*)This, 
+						  This->freeSpace * This->cluster_size);
+}
+
+
+/*
+ * Ensure that there is a minimum of total sectors free
+ */
+int getfreeMinClusters(Stream_t *Dir, size_t size)
+{
+	Stream_t *Stream = GetFs(Dir);
+	DeclareThis(Fs_t);
+	register unsigned int i, last;
+	size_t total;
+
+	if(batchmode && This->freeSpace == MAX32)
+		getfree(Stream);
+
+	if(This->freeSpace != MAX32) {
+		if(This->freeSpace >= size)
+			return 1;
+		else {
+			fprintf(stderr, "Disk full\n");
+			got_signal = 1;
+			return 0;
+		}
+	}
+
+	total = 0L;
+
+	/* we start at the same place where we'll start later to actually
+	 * allocate the sectors.  That way, the same sectors of the FAT, which
+	 * are already loaded during getfreeMin will be able to be reused 
+	 * during get_next_free_cluster */
+	last = This->last;
+	
+	if ( last < 2 || last >= This->num_clus + 2)
+		last = 1;
+	for (i=last+1; i< This->num_clus+2; i++){
+		if (!fatDecode(This, i))
+			total++;
+		if(total >= size)
+			return 1;				
+	}
+	for(i=2; i < last+1; i++){
+		if (!fatDecode(This, i))
+			total++;
+		if(total >= size)
+			return 1;
+	}
+	fprintf(stderr, "Disk full\n");
+	got_signal = 1;
+	return 0;
+}
+
+
+int getfreeMinBytes(Stream_t *Dir, mt_size_t size)
+{
+	Stream_t *Stream = GetFs(Dir);
+	DeclareThis(Fs_t);
+	size_t size2;
+
+	size2 = size  / (This->sector_size * This->cluster_size);
+	if(size % (This->sector_size * This->cluster_size))
+		size2++;
+	return getfreeMinClusters(Dir, size2);
+}
+
+
+unsigned int getStart(Stream_t *Dir, struct directory *dir)
+{
+	Stream_t *Stream = GetFs(Dir);
+	unsigned int first;
+
+	first = START(dir);
+	if(fat32RootCluster(Stream))
+		first |= STARTHI(dir) << 16;
+	return first;
+}
+
+int fs_free(Stream_t *Stream)
+{
+	DeclareThis(Fs_t);
+
+	if(This->FatMap) {
+		int i, nr_entries;
+		nr_entries = (This->fat_len + SECT_PER_ENTRY - 1) / 
+			SECT_PER_ENTRY;
+		for(i=0; i< nr_entries; i++)
+			if(This->FatMap[i].data)
+				free(This->FatMap[i].data);		
+		free(This->FatMap);
+	}
+	return 0;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/fat_free.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/fat_free.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/fat_free.c	(revision 9)
@@ -0,0 +1,55 @@
+#include "sysincludes.h"
+#include "msdos.h"
+#include "fsP.h"
+#include "mtoolsDirent.h"
+
+/*
+ * Remove a string of FAT entries (delete the file).  The argument is
+ * the beginning of the string.  Does not consider the file length, so
+ * if FAT is corrupted, watch out!
+ */
+
+int fat_free(Stream_t *Dir, unsigned int fat)
+{
+	Stream_t *Stream = GetFs(Dir);
+	DeclareThis(Fs_t);
+	unsigned int next_no_step;
+					/* a zero length file? */
+	if (fat == 0)
+		return(0);
+
+	/* CONSTCOND */
+	while (!This->fat_error) {
+		/* get next cluster number */
+		next_no_step = fatDecode(This,fat);
+		/* mark current cluster as empty */
+		fatDeallocate(This,fat);
+		if (next_no_step >= This->last_fat)
+			break;
+		fat = next_no_step;
+	}
+	return(0);
+}
+
+int fatFreeWithDir(Stream_t *Dir, struct directory *dir)
+{
+	unsigned int first;
+
+	if((!strncmp(dir->name,".      ",8) ||
+	    !strncmp(dir->name,"..     ",8)) &&
+	   !strncmp(dir->ext,"   ",3)) {
+		fprintf(stderr,"Trying to remove . or .. entry\n");
+		return -1;
+	}
+
+	first = START(dir);
+  	if(fat32RootCluster(Dir))
+		first |= STARTHI(dir) << 16;
+	return fat_free(Dir, first);
+}
+
+int fatFreeWithDirentry(direntry_t *entry)
+{
+	return fatFreeWithDir(entry->Dir, &entry->dir);
+}
+    
Index: /trunk/minix/commands/i386/mtools-3.9.7/file.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/file.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/file.c	(revision 9)
@@ -0,0 +1,676 @@
+#include "sysincludes.h"
+#include "msdos.h"
+#include "stream.h"
+#include "mtools.h"
+#include "fsP.h"
+#include "file.h"
+#include "htable.h"
+#include "dirCache.h"
+
+typedef struct File_t {
+	Class_t *Class;
+	int refs;
+	struct Fs_t *Fs;	/* Filesystem that this fat file belongs to */
+	Stream_t *Buffer;
+
+	int (*map)(struct File_t *this, off_t where, size_t *len, int mode,
+			   mt_off_t *res);
+	size_t FileSize;
+
+	size_t preallocatedSize;
+	int preallocatedClusters;
+
+	/* Absolute position of first cluster of file */
+	unsigned int FirstAbsCluNr;
+
+	/* Absolute position of previous cluster */
+	unsigned int PreviousAbsCluNr;
+
+	/* Relative position of previous cluster */
+	unsigned int PreviousRelCluNr;
+	direntry_t direntry;
+	int hint;
+	struct dirCache_t *dcp;
+
+	unsigned int loopDetectRel;
+	unsigned int loopDetectAbs;
+} File_t;
+
+static Class_t FileClass;
+T_HashTable *filehash;
+
+static File_t *getUnbufferedFile(Stream_t *Stream)
+{
+	while(Stream->Class != &FileClass)
+		Stream = Stream->Next;
+	return (File_t *) Stream;
+}
+
+Fs_t *getFs(Stream_t *Stream)
+{
+	return getUnbufferedFile(Stream)->Fs;
+}
+
+struct dirCache_t **getDirCacheP(Stream_t *Stream)
+{
+	return &getUnbufferedFile(Stream)->dcp;
+}
+
+direntry_t *getDirentry(Stream_t *Stream)
+{
+	return &getUnbufferedFile(Stream)->direntry;
+}
+
+
+static int recalcPreallocSize(File_t *This)
+{
+	size_t currentClusters, neededClusters;
+	int clus_size;
+	int neededPrealloc;
+	Fs_t *Fs = This->Fs;
+	int r;
+
+	if(This->FileSize & 0xc0000000) {
+		fprintf(stderr, "Bad filesize\n");
+	}
+	if(This->preallocatedSize & 0xc0000000) {
+		fprintf(stderr, "Bad preallocated size %x\n", 
+				(int) This->preallocatedSize);
+	}
+
+	clus_size = Fs->cluster_size * Fs->sector_size;
+
+	currentClusters = (This->FileSize + clus_size - 1) / clus_size;
+	neededClusters = (This->preallocatedSize + clus_size - 1) / clus_size;
+	neededPrealloc = neededClusters - currentClusters;
+	if(neededPrealloc < 0)
+		neededPrealloc = 0;
+	r = fsPreallocateClusters(Fs, neededPrealloc - This->preallocatedClusters);
+	if(r)
+		return r;
+	This->preallocatedClusters = neededPrealloc;
+	return 0;
+}
+
+static int _loopDetect(unsigned int *oldrel, unsigned int rel, 
+					   unsigned int *oldabs, unsigned int abs)
+{
+	if(*oldrel && rel > *oldrel && abs == *oldabs) {
+		fprintf(stderr, "loop detected! oldrel=%d newrel=%d abs=%d\n",
+				*oldrel, rel, abs);
+		return -1;
+	}
+
+	if(rel >= 2 * *oldrel + 1) {
+		*oldrel = rel;
+		*oldabs = abs;
+	}
+	return 0;
+}
+
+
+static int loopDetect(File_t *This, unsigned int rel, unsigned int abs)
+{
+	return _loopDetect(&This->loopDetectRel, rel, &This->loopDetectAbs, abs);
+}
+
+static unsigned int _countBlocks(Fs_t *This, unsigned int block)
+{
+	unsigned int blocks;
+	unsigned int rel, oldabs, oldrel;
+
+	blocks = 0;
+	
+	oldabs = oldrel = rel = 0;
+
+	while (block <= This->last_fat && block != 1 && block) {
+		blocks++;
+		block = fatDecode(This, block);
+		rel++;
+		if(_loopDetect(&oldrel, rel, &oldabs, block) < 0)
+			block = -1;
+	}
+	return blocks;
+}
+
+unsigned int countBlocks(Stream_t *Dir, unsigned int block)
+{
+	Stream_t *Stream = GetFs(Dir);
+	DeclareThis(Fs_t);
+
+	return _countBlocks(This, block);
+}
+
+/* returns number of bytes in a directory.  Represents a file size, and
+ * can hence be not bigger than 2^32
+ */
+static size_t countBytes(Stream_t *Dir, unsigned int block)
+{
+	Stream_t *Stream = GetFs(Dir);
+	DeclareThis(Fs_t);
+
+	return _countBlocks(This, block) * 
+		This->sector_size * This->cluster_size;
+}
+
+void printFat(Stream_t *Stream)
+{
+	File_t *This = getUnbufferedFile(Stream);
+	unsigned long n;
+	int rel;
+	unsigned long begin, end;
+	int first;
+
+	n = This->FirstAbsCluNr;
+	if(!n) {
+		printf("Root directory or empty file\n");
+		return;
+	}
+
+	rel = 0;
+	first = 1;
+	begin = end = 0;
+	do {
+		if (first || n != end+1) {
+			if (!first) {
+				if (begin != end)
+					printf("-%lu", end);
+				printf("> ");
+			}
+			begin = end = n;
+			printf("<%lu", begin);
+		} else {
+			end++;
+		}
+		first = 0;
+		n = fatDecode(This->Fs, n);
+		rel++;
+		if(loopDetect(This, rel, n) < 0)
+			n = 1;
+	} while (n <= This->Fs->last_fat && n != 1);
+	if(!first) {
+		if (begin != end)
+			printf("-%lu", end);
+		printf(">");
+	}
+}
+
+static int normal_map(File_t *This, off_t where, size_t *len, int mode,
+						   mt_off_t *res)
+{
+	int offset;
+	off_t end;
+	int NrClu; /* number of clusters to read */
+	unsigned int RelCluNr;
+	unsigned int CurCluNr;
+	unsigned int NewCluNr;
+	unsigned int AbsCluNr;
+	int clus_size;
+	Fs_t *Fs = This->Fs;
+
+	*res = 0;
+	clus_size = Fs->cluster_size * Fs->sector_size;
+	offset = where % clus_size;
+
+	if (mode == MT_READ)
+		maximize(*len, This->FileSize - where);
+	if (*len == 0 )
+		return 0;
+
+	if (This->FirstAbsCluNr < 2){
+		if( mode == MT_READ || *len == 0){
+			*len = 0;
+			return 0;
+		}
+		NewCluNr = get_next_free_cluster(This->Fs, 1);
+		if (NewCluNr == 1 ){
+			errno = ENOSPC;
+			return -2;
+		}
+		hash_remove(filehash, (void *) This, This->hint);
+		This->FirstAbsCluNr = NewCluNr;
+		hash_add(filehash, (void *) This, &This->hint);
+		fatAllocate(This->Fs, NewCluNr, Fs->end_fat);
+	}
+
+	RelCluNr = where / clus_size;
+	
+	if (RelCluNr >= This->PreviousRelCluNr){
+		CurCluNr = This->PreviousRelCluNr;
+		AbsCluNr = This->PreviousAbsCluNr;
+	} else {
+		CurCluNr = 0;
+		AbsCluNr = This->FirstAbsCluNr;
+	}
+
+
+	NrClu = (offset + *len - 1) / clus_size;
+	while (CurCluNr <= RelCluNr + NrClu){
+		if (CurCluNr == RelCluNr){
+			/* we have reached the beginning of our zone. Save
+			 * coordinates */
+			This->PreviousRelCluNr = RelCluNr;
+			This->PreviousAbsCluNr = AbsCluNr;
+		}
+		NewCluNr = fatDecode(This->Fs, AbsCluNr);
+		if (NewCluNr == 1 || NewCluNr == 0){
+			fprintf(stderr,"Fat problem while decoding %d %x\n", 
+				AbsCluNr, NewCluNr);
+			exit(1);
+		}
+		if(CurCluNr == RelCluNr + NrClu)			
+			break;
+		if (NewCluNr > Fs->last_fat && mode == MT_WRITE){
+			/* if at end, and writing, extend it */
+			NewCluNr = get_next_free_cluster(This->Fs, AbsCluNr);
+			if (NewCluNr == 1 ){ /* no more space */
+				errno = ENOSPC;
+				return -2;
+			}
+			fatAppend(This->Fs, AbsCluNr, NewCluNr);
+		}
+
+		if (CurCluNr < RelCluNr && NewCluNr > Fs->last_fat){
+			*len = 0;
+			return 0;
+		}
+
+		if (CurCluNr >= RelCluNr && NewCluNr != AbsCluNr + 1)
+			break;
+		CurCluNr++;
+		AbsCluNr = NewCluNr;
+		if(loopDetect(This, CurCluNr, AbsCluNr)) {
+			errno = EIO;
+			return -2;
+		}
+	}
+
+	maximize(*len, (1 + CurCluNr - RelCluNr) * clus_size - offset);
+	
+	end = where + *len;
+	if(batchmode && mode == MT_WRITE && end >= This->FileSize) {
+		*len += ROUND_UP(end, clus_size) - end;
+	}
+
+	if((*len + offset) / clus_size + This->PreviousAbsCluNr-2 >
+		Fs->num_clus) {
+		fprintf(stderr, "cluster too big\n");
+		exit(1);
+	}
+
+	*res = sectorsToBytes((Stream_t*)Fs, 
+						  (This->PreviousAbsCluNr-2) * Fs->cluster_size +
+						  Fs->clus_start) + offset;
+	return 1;
+}
+
+
+static int root_map(File_t *This, off_t where, size_t *len, int mode,
+					mt_off_t *res)
+{
+	Fs_t *Fs = This->Fs;
+
+	if(Fs->dir_len * Fs->sector_size < where) {
+		*len = 0;
+		errno = ENOSPC;
+		return -2;
+	}
+
+	maximize(*len, Fs->dir_len * Fs->sector_size - where);
+        if (*len == 0)
+            return 0;
+	
+	*res = sectorsToBytes((Stream_t*)Fs, Fs->dir_start) + where;
+	return 1;
+}
+	
+
+static int read_file(Stream_t *Stream, char *buf, mt_off_t iwhere, 
+					 size_t len)
+{
+	DeclareThis(File_t);
+	mt_off_t pos;
+	int err;
+	off_t where = truncBytes32(iwhere);
+
+	Stream_t *Disk = This->Fs->Next;
+	
+	err = This->map(This, where, &len, MT_READ, &pos);
+	if(err <= 0)
+		return err;
+	return READS(Disk, buf, pos, len);
+}
+
+static int write_file(Stream_t *Stream, char *buf, mt_off_t iwhere, size_t len)
+{
+	DeclareThis(File_t);
+	mt_off_t pos;
+	int ret;
+	size_t requestedLen;
+	Stream_t *Disk = This->Fs->Next;
+	off_t where = truncBytes32(iwhere);
+	int err;
+
+	requestedLen = len;
+	err = This->map(This, where, &len, MT_WRITE, &pos);
+	if( err <= 0)
+		return err;
+	if(batchmode)
+		ret = force_write(Disk, buf, pos, len);
+	else
+		ret = WRITES(Disk, buf, pos, len);
+	if(ret > requestedLen)
+		ret = requestedLen;
+	if (ret > 0 && where + ret > This->FileSize )
+		This->FileSize = where + ret;
+	recalcPreallocSize(This);
+	return ret;
+}
+
+
+/*
+ * Convert an MSDOS time & date stamp to the Unix time() format
+ */
+
+static int month[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
+					  0, 0, 0 };
+static inline time_t conv_stamp(struct directory *dir)
+{
+	struct tm *tmbuf;
+	long tzone, dst;
+	time_t accum, tmp;
+
+	accum = DOS_YEAR(dir) - 1970; /* years past */
+
+	/* days passed */
+	accum = accum * 365L + month[DOS_MONTH(dir)-1] + DOS_DAY(dir);
+
+	/* leap years */
+	accum += (DOS_YEAR(dir) - 1972) / 4L;
+
+	/* back off 1 day if before 29 Feb */
+	if (!(DOS_YEAR(dir) % 4) && DOS_MONTH(dir) < 3)
+	        accum--;
+	accum = accum * 24L + DOS_HOUR(dir); /* hours passed */
+	accum = accum * 60L + DOS_MINUTE(dir); /* minutes passed */
+	accum = accum * 60L + DOS_SEC(dir); /* seconds passed */
+
+#ifndef OS_Minix
+	/* correct for Time Zone */
+#ifdef HAVE_GETTIMEOFDAY
+	{
+		struct timeval tv;
+		struct timezone tz;
+		
+		gettimeofday(&tv, &tz);
+		tzone = tz.tz_minuteswest * 60L;
+	}
+#else
+#ifdef HAVE_TZSET
+	{
+#ifndef OS_ultrix
+		/* Ultrix defines this to be a different type */
+		extern long timezone;
+#endif
+		tzset();
+		tzone = (long) timezone;
+	}
+#else
+	tzone = 0;
+#endif /* HAVE_TZSET */
+#endif /* HAVE_GETTIMEOFDAY */
+
+	accum += tzone;
+#endif /* OS_Minix */
+
+	/* correct for Daylight Saving Time */
+	tmp = accum;
+	tmbuf = localtime(&tmp);
+#ifndef OS_Minix
+	dst = (tmbuf->tm_isdst) ? (-60L * 60L) : 0L;
+	accum += dst;
+#endif
+	
+	return accum;
+}
+
+
+static int get_file_data(Stream_t *Stream, time_t *date, mt_size_t *size,
+			 int *type, int *address)
+{
+	DeclareThis(File_t);
+
+	if(date)
+		*date = conv_stamp(& This->direntry.dir);
+	if(size)
+		*size = (mt_size_t) This->FileSize;
+	if(type)
+		*type = This->direntry.dir.attr & ATTR_DIR;
+	if(address)
+		*address = This->FirstAbsCluNr;
+	return 0;
+}
+
+
+static int free_file(Stream_t *Stream)
+{
+	DeclareThis(File_t);
+	Fs_t *Fs = This->Fs;
+	fsPreallocateClusters(Fs, -This->preallocatedClusters);       
+	FREE(&This->direntry.Dir);
+	freeDirCache(Stream);
+	return hash_remove(filehash, (void *) Stream, This->hint);
+}
+
+
+static int flush_file(Stream_t *Stream)
+{
+	DeclareThis(File_t);
+	direntry_t *entry = &This->direntry;
+
+	if(isRootDir(Stream)) {
+		return 0;
+	}
+
+	if(This->FirstAbsCluNr != getStart(entry->Dir, &entry->dir)) {
+		set_word(entry->dir.start, This->FirstAbsCluNr & 0xffff);
+		set_word(entry->dir.startHi, This->FirstAbsCluNr >> 16);
+		dir_write(entry);
+	}
+	return 0;
+}
+
+
+static int pre_allocate_file(Stream_t *Stream, mt_size_t isize)
+{
+	DeclareThis(File_t);
+
+	size_t size = truncBytes32(isize);
+
+	if(size > This->FileSize &&
+	   size > This->preallocatedSize) {
+		This->preallocatedSize = size;
+		return recalcPreallocSize(This);
+	} else
+		return 0;
+}
+
+static Class_t FileClass = {
+	read_file, 
+	write_file, 
+	flush_file, /* flush */
+	free_file, /* free */
+	0, /* get_geom */
+	get_file_data,
+	pre_allocate_file
+};
+
+static unsigned int getAbsCluNr(File_t *This)
+{
+	if(This->FirstAbsCluNr)
+		return This->FirstAbsCluNr;
+	if(isRootDir((Stream_t *) This))
+		return 0;
+	return 1;
+}
+
+static unsigned int func1(void *Stream)
+{
+	DeclareThis(File_t);
+
+	return getAbsCluNr(This) ^ (long) This->Fs;
+}
+
+static unsigned int func2(void *Stream)
+{
+	DeclareThis(File_t);
+
+	return getAbsCluNr(This);
+}
+
+static int comp(void *Stream, void *Stream2)
+{
+	DeclareThis(File_t);
+
+	File_t *This2 = (File_t *) Stream2;
+
+	return This->Fs != This2->Fs ||
+		getAbsCluNr(This) != getAbsCluNr(This2);
+}
+
+static void init_hash(void)
+{
+	static int is_initialised=0;
+	
+	if(!is_initialised){
+		make_ht(func1, func2, comp, 20, &filehash);
+		is_initialised = 1;
+	}
+}
+
+
+static Stream_t *_internalFileOpen(Stream_t *Dir, unsigned int first, 
+				   size_t size, direntry_t *entry)
+{
+	Stream_t *Stream = GetFs(Dir);
+	DeclareThis(Fs_t);
+	File_t Pattern;
+	File_t *File;
+
+	init_hash();
+	This->refs++;
+
+	if(first != 1){
+		/* we use the illegal cluster 1 to mark newly created files.
+		 * do not manage those by hashtable */
+		Pattern.Fs = This;
+		Pattern.Class = &FileClass;
+		if(first || (entry && !IS_DIR(entry)))
+			Pattern.map = normal_map;
+		else
+			Pattern.map = root_map;
+		Pattern.FirstAbsCluNr = first;
+		Pattern.loopDetectRel = 0;
+		Pattern.loopDetectAbs = first;
+		if(!hash_lookup(filehash, (T_HashTableEl) &Pattern, 
+				(T_HashTableEl **)&File, 0)){
+			File->refs++;
+			This->refs--;
+			return (Stream_t *) File;
+		}
+	}
+
+	File = New(File_t);
+	if (!File)
+		return NULL;
+	File->dcp = 0;
+	File->preallocatedClusters = 0;
+	File->preallocatedSize = 0;
+	/* memorize dir for date and attrib */
+	File->direntry = *entry;
+	if(entry->entry == -3)
+		File->direntry.Dir = (Stream_t *) File; /* root directory */
+	else
+		COPY(File->direntry.Dir);
+
+	File->Class = &FileClass;
+	File->Fs = This;
+	if(first || (entry && !IS_DIR(entry)))
+		File->map = normal_map;
+	else
+		File->map = root_map; /* FAT 12/16 root directory */
+	if(first == 1)
+		File->FirstAbsCluNr = 0;
+	else
+		File->FirstAbsCluNr = first;
+
+	File->loopDetectRel = 0;
+	File->loopDetectAbs = 0;
+
+	File->PreviousRelCluNr = 0xffff;
+	File->FileSize = size;
+	File->refs = 1;
+	File->Buffer = 0;
+	hash_add(filehash, (void *) File, &File->hint);
+	return (Stream_t *) File;
+}
+
+Stream_t *OpenRoot(Stream_t *Dir)
+{
+	unsigned int num;
+	direntry_t entry;
+	size_t size;
+	Stream_t *file;
+
+	memset(&entry, 0, sizeof(direntry_t));
+
+	num = fat32RootCluster(Dir);
+
+	/* make the directory entry */
+	entry.entry = -3;
+	entry.name[0] = '\0';
+	mk_entry("/", ATTR_DIR, num, 0, 0, &entry.dir);
+
+	if(num)
+		size = countBytes(Dir, num);
+	else {
+		Fs_t *Fs = (Fs_t *) GetFs(Dir);
+		size = Fs->dir_len * Fs->sector_size;
+	}
+	file = _internalFileOpen(Dir, num, size, &entry);
+	bufferize(&file);
+	return file;
+}
+
+
+Stream_t *OpenFileByDirentry(direntry_t *entry)
+{
+	Stream_t *file;
+	unsigned int first;
+	size_t size;
+
+	first = getStart(entry->Dir, &entry->dir);
+
+	if(!first && IS_DIR(entry))
+		return OpenRoot(entry->Dir);
+	if (IS_DIR(entry))
+		size = countBytes(entry->Dir, first);
+	else 
+		size = FILE_SIZE(&entry->dir);
+	file = _internalFileOpen(entry->Dir, first, size, entry);
+	if(IS_DIR(entry)) {
+		bufferize(&file);
+		if(first == 1)
+			dir_grow(file, 0);
+	}
+
+	return file;
+}
+
+
+int isRootDir(Stream_t *Stream)
+{
+	File_t *This = getUnbufferedFile(Stream);
+
+	return This->map == root_map;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/file.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/file.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/file.h	(revision 9)
@@ -0,0 +1,11 @@
+#ifndef MTOOLS_FILE_H
+#define MTOOLS_FILE_H
+
+#include "stream.h"
+#include "mtoolsDirent.h"
+
+Stream_t *OpenFileByDirentry(direntry_t *entry);
+Stream_t *OpenRoot(Stream_t *Dir);
+void printFat(Stream_t *Stream);
+direntry_t *getDirentry(Stream_t *Stream);
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/file_name.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/file_name.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/file_name.c	(revision 9)
@@ -0,0 +1,203 @@
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "vfat.h"
+#include "codepage.h"
+
+/* Write a DOS name + extension into a legal unix-style name.  */
+char *unix_normalize (char *ans, char *name, char *ext)
+{
+	char *a;
+	int j;
+	
+	for (a=ans,j=0; (j<8) && (name[j] > ' '); ++j,++a)
+		*a = name[j];
+	if(*ext > ' ') {
+		*a++ = '.';
+		for (j=0; j<3 && ext[j] > ' '; ++j,++a)
+			*a = ext[j];
+	}
+	*a++ = '\0';
+	return ans;
+}
+
+typedef enum Case_l {
+	NONE,
+	UPPER,
+	LOWER 
+} Case_t;
+
+static void TranslateToDos(const char *s, char *t, int count,
+			   char *end, Case_t *Case, int *mangled)
+{
+	*Case = NONE;
+	for( ;  *s && (s < end || !end); s++) {
+		if(!count) {
+			*mangled |= 3;
+			break;
+		}
+		/* skip spaces & dots */
+		if(*s == ' ' || *s == '.') {
+			*mangled |= 3;
+			continue;
+		}
+
+		/* convert to dos */
+		if((*s) & 0x80) {
+			*mangled |= 1;
+			*t = to_dos(*s);
+		}
+
+		if ((*s & 0x7f) < ' ' ) {
+			*mangled |= 3;
+			*t = '_';
+		} else if (islower((unsigned char)*s)) {
+			*t = toupper(*s);
+			if(*Case == UPPER && !mtools_no_vfat)
+				*mangled |= 1;
+			else
+				*Case = LOWER;
+		} else if (isupper((unsigned char)*s)) {
+			*t = *s;
+			if(*Case == LOWER && !mtools_no_vfat)
+				*mangled |= 1;
+			else
+				*Case = UPPER;
+		} else if((*s) & 0x80)
+			*t = mstoupper(*t);	/* upper case */
+		else
+			*t = *s;
+		count--;
+		t++;
+	}
+}
+
+/* dos_name
+ *
+ * Convert a Unix-style filename to a legal MSDOS name and extension.
+ * Will truncate file and extension names, will substitute
+ * the character '~' for any illegal character(s) in the name.
+ */
+char *dos_name(char *name, int verbose, int *mangled, char *ans)
+{
+	char *s, *ext;
+	register int i;
+	Case_t BaseCase, ExtCase;
+
+	*mangled = 0;
+
+	/* skip drive letter */
+	name = skip_drive(name);
+
+	/* zap the leading path */
+	name = (char *) _basename(name);
+	if ((s = strrchr(name, '\\')))
+		name = s + 1;
+	
+	memset(ans, ' ', 11);
+	ans[11]='\0';
+
+	/* skip leading dots and spaces */
+	i = strspn(name, ". ");
+	if(i) {
+		name += i;
+		*mangled = 3;
+	}
+		
+	ext = strrchr(name, '.');
+
+	/* main name */
+	TranslateToDos(name, ans, 8, ext, &BaseCase, mangled);
+	if(ext)
+		TranslateToDos(ext+1, ans+8, 3, 0, &ExtCase,  mangled);
+
+	if(*mangled & 2)
+		autorename_short(ans, 0);
+
+	if(!*mangled) {
+		if(BaseCase == LOWER)
+			*mangled |= BASECASE;
+		if(ExtCase == LOWER)
+			*mangled |= EXTCASE;
+		if((BaseCase == LOWER || ExtCase == LOWER) &&
+		   !mtools_no_vfat) {
+		  *mangled |= 1;
+		}
+	}
+	return ans;
+}
+
+
+/*
+ * Get rid of spaces in an MSDOS 'raw' name (one that has come from the
+ * directory structure) so that it can be used for regular expression
+ * matching with a Unix filename.  Also used to 'unfix' a name that has
+ * been altered by dos_name().
+ */
+
+char *unix_name(char *name, char *ext, char Case, char *ans)
+{
+	char *s, tname[9], text[4];
+	int i;
+
+	strncpy(tname, (char *) name, 8);
+	tname[8] = '\0';
+	if ((s = strchr(tname, ' ')))
+		*s = '\0';
+
+	if(!(Case & (BASECASE | EXTCASE)) && mtools_ignore_short_case)
+		Case |= BASECASE | EXTCASE;
+
+	if(Case & BASECASE)
+		for(i=0;i<8 && tname[i];i++)
+			tname[i] = tolower(tname[i]);
+
+	strncpy(text, (char *) ext, 3);
+	text[3] = '\0';
+	if ((s = strchr(text, ' ')))
+		*s = '\0';
+
+	if(Case & EXTCASE)
+		for(i=0;i<3 && text[i];i++)
+			text[i] = tolower(text[i]);
+
+	if (*text) {
+		strcpy(ans, tname);
+		strcat(ans, ".");
+		strcat(ans, text);
+	} else
+		strcpy(ans, tname);
+
+	/* fix special characters (above 0x80) */
+	to_unix(ans,11);
+	return(ans);
+}
+
+/* If null encountered, set *end to 0x40 and write nulls rest of way
+ * 950820: Win95 does not like this!  It complains about bad characters.
+ * So, instead: If null encountered, set *end to 0x40, write the null, and
+ * write 0xff the rest of the way (that is what Win95 seems to do; hopefully
+ * that will make it happy)
+ */
+/* Always return num */
+int unicode_write(char *in, struct unicode_char *out, int num, int *end_p)
+{
+	int j;
+
+	for (j=0; j<num; ++j) {
+		out->uchar = '\0';	/* Hard coded to ASCII */
+		if (*end_p)
+			/* Fill with 0xff */
+			out->uchar = out->lchar = (char) 0xff;
+		else {
+			out->lchar = *in;
+			if (! *in) {
+				*end_p = VSE_LAST;
+			}
+		}
+
+		++out;
+		++in;
+	}
+	return num;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/file_read.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/file_read.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/file_read.c	(revision 9)
@@ -0,0 +1,37 @@
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "file.h"
+
+/*
+ * Read the clusters given the beginning FAT entry.  Returns 0 on success.
+ */
+
+int file_read(FILE *fp, Stream_t *Source, int textmode, int stripmode)
+{
+	char buffer[16384];
+	int pos;
+	int ret;
+
+	if (!Source){
+		fprintf(stderr,"Couldn't open source file\n");
+		return -1;
+	}
+	
+	pos = 0;
+	while(1){
+		ret = Source->Class->read(Source, buffer, (mt_off_t) pos, 16384);
+		if (ret < 0 ){
+			perror("file read");
+			return -1;
+		}
+		if ( ret == 0)
+			break;
+		if(!fwrite(buffer, 1, ret, fp)){
+			perror("write");
+			return -1;
+		}
+		pos += ret;
+	}
+	return 0;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/filter.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/filter.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/filter.c	(revision 9)
@@ -0,0 +1,140 @@
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+
+typedef struct Filter_t {
+	Class_t *Class;
+	int refs;
+	Stream_t *Next;
+	Stream_t *Buffer;
+
+	int dospos;
+	int unixpos;
+	int mode;
+	int rw;
+	int lastchar;
+} Filter_t;
+
+#define F_READ 1
+#define F_WRITE 2
+
+/* read filter filters out messy dos' bizarre end of lines and final 0x1a's */
+
+static int read_filter(Stream_t *Stream, char *buf, mt_off_t iwhere, size_t len)
+{
+	DeclareThis(Filter_t);
+	int i,j,ret;
+
+	off_t where = truncBytes32(iwhere);
+
+	if ( where != This->unixpos ){
+		fprintf(stderr,"Bad offset\n");
+		exit(1);
+	}
+	if (This->rw == F_WRITE){
+		fprintf(stderr,"Change of transfer direction!\n");
+		exit(1);
+	}
+	This->rw = F_READ;
+	
+	ret = READS(This->Next, buf, (mt_off_t) This->dospos, len);
+	if ( ret < 0 )
+		return ret;
+
+	j = 0;
+	for (i=0; i< ret; i++){
+		if ( buf[i] == '\r' )
+			continue;
+		if (buf[i] == 0x1a)
+			break;
+		This->lastchar = buf[j++] = buf[i];	
+	}
+
+	This->dospos += i;
+	This->unixpos += j;
+	return j;
+}
+
+static int write_filter(Stream_t *Stream, char *buf, mt_off_t iwhere, 
+						size_t len)
+{
+	DeclareThis(Filter_t);
+	int i,j,ret;
+	char buffer[1025];
+
+	off_t where = truncBytes32(iwhere);
+
+	if(This->unixpos == -1)
+		return -1;
+
+	if (where != This->unixpos ){
+		fprintf(stderr,"Bad offset\n");
+		exit(1);
+	}
+	
+	if (This->rw == F_READ){
+		fprintf(stderr,"Change of transfer direction!\n");
+		exit(1);
+	}
+	This->rw = F_WRITE;
+
+	j=i=0;
+	while(i < 1024 && j < len){
+		if (buf[j] == '\n' ){
+			buffer[i++] = '\r';
+			buffer[i++] = '\n';
+			j++;
+			continue;
+		}
+		buffer[i++] = buf[j++];
+	}
+	This->unixpos += j;
+
+	ret = force_write(This->Next, buffer, (mt_off_t) This->dospos, i);
+	if(ret >0 )
+		This->dospos += ret;
+	if ( ret != i ){
+		/* no space on target file ? */
+		This->unixpos = -1;
+		return -1;
+	}
+	return j;
+}
+
+static int free_filter(Stream_t *Stream)
+{
+	DeclareThis(Filter_t);       
+	char buffer=0x1a;
+
+	/* write end of file */
+	if (This->rw == F_WRITE)
+		return force_write(This->Next, &buffer, (mt_off_t) This->dospos, 1);
+	else
+		return 0;
+}
+
+static Class_t FilterClass = { 
+	read_filter,
+	write_filter,
+	0, /* flush */
+	free_filter,
+	0, /* set geometry */
+	get_data_pass_through,
+	0
+};
+
+Stream_t *open_filter(Stream_t *Next)
+{
+	Filter_t *This;
+
+	This = New(Filter_t);
+	if (!This)
+		return NULL;
+	This->Class = &FilterClass;
+	This->dospos = This->unixpos = This->rw = 0;
+	This->Next = Next;
+	This->refs = 1;
+	This->Buffer = 0;
+
+	return (Stream_t *) This;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/floppyd_io.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/floppyd_io.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/floppyd_io.c	(revision 9)
@@ -0,0 +1,559 @@
+/*
+ * IO to the floppyd daemon running on the local X-Server Host
+ *
+ * written by:
+ *
+ * Peter Schlaile
+ *
+ * udbz@rz.uni-karlsruhe.de
+ *
+ */
+
+#include "sysincludes.h"
+#include "stream.h"
+#include "mtools.h"
+#include "msdos.h"
+#include "scsi.h"
+#include "partition.h"
+#include "floppyd_io.h"
+
+#ifdef USE_FLOPPYD
+
+/* ######################################################################## */
+
+
+typedef unsigned char Byte;
+typedef unsigned long Dword;
+
+char* AuthErrors[] = {
+	"Auth success!",
+	"Auth failed: Packet oversized!",
+	"Auth failed: X-Cookie doesn't match!",
+	"Auth failed: Wrong transmission protocol version!",
+	"Auth failed: Device locked!"
+};
+
+
+typedef struct RemoteFile_t {
+	Class_t *Class;
+	int refs;
+	Stream_t *Next;
+	Stream_t *Buffer;
+	int fd;
+	mt_off_t offset;
+	mt_off_t lastwhere;
+	mt_off_t size;
+} RemoteFile_t;
+
+
+#ifndef HAVE_HTONS
+unsigned short myhtons(unsigned short parm) 
+{
+	Byte val[2];
+	
+	val[0] = (parm >> 8) & 0xff;
+	val[1] = parm        & 0xff;
+
+	return *((unsigned short*) (val));
+}
+#endif
+
+Dword byte2dword(Byte* val) 
+{
+	Dword l;
+	l = (val[0] << 24) + (val[1] << 16) + (val[2] << 8) + val[3];
+
+	return l;
+}	
+
+void dword2byte(Dword parm, Byte* rval) 
+{
+	rval[0] = (parm >> 24) & 0xff;
+	rval[1] = (parm >> 16) & 0xff;
+	rval[2] = (parm >> 8)  & 0xff;
+	rval[3] = parm         & 0xff;
+}
+
+Dword read_dword(int handle) 
+{
+	Byte val[4];
+	
+	read(handle, val, 4);
+
+	return byte2dword(val);
+}
+
+void write_dword(int handle, Dword parm) 
+{
+	Byte val[4];
+
+	dword2byte(parm, val);
+
+	write(handle, val, 4);
+}
+
+
+/* ######################################################################## */
+
+int authenticate_to_floppyd(int sock, char *display)
+{
+	off_t filelen;
+	Byte buf[16];
+	char *command[] = { "xauth", "xauth", "extract", "-", 0, 0 };
+	char *xcookie;
+	Dword errcode;
+
+	command[4] = display;
+
+	filelen=strlen(display);
+	filelen += 100;
+
+	xcookie = (char *) safe_malloc(filelen+4);
+	filelen = safePopenOut(command, xcookie+4, filelen);
+	if(filelen < 1)
+		return AUTH_AUTHFAILED;
+
+	dword2byte(4,buf);
+	dword2byte(FLOPPYD_PROTOCOL_VERSION,buf+4);
+	write(sock, buf, 8);
+
+	if (read_dword(sock) != 4) {
+		return AUTH_WRONGVERSION;
+	}
+
+	errcode = read_dword(sock);
+
+	if (errcode != AUTH_SUCCESS) {
+		return errcode;
+	}
+
+	dword2byte(filelen, xcookie);
+	write(sock, xcookie, filelen+4);
+
+	if (read_dword(sock) != 4) {
+		return AUTH_PACKETOVERSIZE;
+	}
+
+	errcode = read_dword(sock);
+	
+	return errcode;
+}
+
+
+static int floppyd_reader(int fd, char* buffer, int len) 
+{
+	Dword errcode;
+	Dword gotlen;
+	int l;
+	int start;
+	Byte buf[16];
+
+	dword2byte(1, buf);
+	buf[4] = OP_READ;
+	dword2byte(4, buf+5);
+	dword2byte(len, buf+9);
+	write(fd, buf, 13);
+
+	if (read_dword(fd) != 8) {
+		errno = EIO;
+		return -1;
+	}
+
+	gotlen = read_dword(fd);
+	errcode = read_dword(fd);
+
+	if (gotlen != -1) {
+		if (read_dword(fd) != gotlen) {
+			errno = EIO;
+			return -1;
+		}
+		for (start = 0, l = 0; start < gotlen; start += l) {
+			l = read(fd, buffer+start, gotlen-start);
+			if (l == 0) {
+				errno = EIO;
+				return -1;
+			}
+		}
+	} else {
+		errno = errcode;
+	}
+	return gotlen;
+}
+
+static int floppyd_writer(int fd, char* buffer, int len) 
+{
+	Dword errcode;
+	Dword gotlen;
+	Byte buf[16];
+
+	dword2byte(1, buf);
+	buf[4] = OP_WRITE;
+	dword2byte(len, buf+5);
+
+	write(fd, buf, 9);
+        write(fd, buffer, len);
+	
+	if (read_dword(fd) != 8) {
+		errno = EIO;
+		return -1;
+	}
+
+	gotlen = read_dword(fd);
+	errcode = read_dword(fd);
+
+	errno = errcode;
+	
+	return gotlen;
+}
+
+static int floppyd_lseek(int fd, mt_off_t offset, int whence) 
+{
+	Dword errcode;
+	Dword gotlen;
+	Byte buf[32];
+	
+	dword2byte(1, buf);
+	buf[4] = OP_SEEK;
+	
+	dword2byte(8, buf+5);
+	dword2byte(truncBytes32(offset), buf+9);
+	dword2byte(whence, buf+13);
+	
+	write(fd, buf, 17);
+       
+	if (read_dword(fd) != 8) {
+		errno = EIO;
+		return -1;
+	}
+
+	gotlen = read_dword(fd);
+	errcode = read_dword(fd);
+
+	errno = errcode;
+	
+	return gotlen;
+}
+
+/* ######################################################################## */
+
+typedef int (*iofn) (int, char *, int);
+
+static int floppyd_io(Stream_t *Stream, char *buf, mt_off_t where, int len,
+		   iofn io)
+{
+	DeclareThis(RemoteFile_t);
+	int ret;
+
+	where += This->offset;
+
+	if (where != This->lastwhere ){
+		if(floppyd_lseek( This->fd, where, SEEK_SET) < 0 ){
+			perror("floppyd_lseek");
+			This->lastwhere = (mt_off_t) -1;
+			return -1;
+		}
+	}
+	ret = io(This->fd, buf, len);
+	if ( ret == -1 ){
+		perror("floppyd_io");
+		This->lastwhere = (mt_off_t) -1;
+		return -1;
+	}
+	This->lastwhere = where + ret;
+	return ret;
+}
+
+static int floppyd_read(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
+{	
+	return floppyd_io(Stream, buf, where, len, (iofn) floppyd_reader);
+}
+
+static int floppyd_write(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
+{
+	return floppyd_io(Stream, buf, where, len, (iofn) floppyd_writer);
+}
+
+static int floppyd_flush(Stream_t *Stream)
+{
+#if 0
+	Byte buf[16];
+
+	DeclareThis(RemoteFile_t);
+
+	dword2byte(1, buf);
+	buf[4] = OP_FLUSH;
+
+	write(This->fd, buf, 5);
+
+	if (read_dword(This->fd) != 8) {
+		errno = EIO;
+		return -1;
+	}
+
+	read_dword(This->fd);
+	read_dword(This->fd);
+#endif
+	return 0;
+}
+
+static int floppyd_free(Stream_t *Stream)
+{
+	Byte buf[16];
+
+	DeclareThis(RemoteFile_t);
+
+	if (This->fd > 2) {
+		dword2byte(1, buf);
+		buf[4] = OP_CLOSE;
+		write(This->fd, buf, 5);
+		return close(This->fd);
+	} else {
+		return 0;
+	}
+}
+
+static int floppyd_geom(Stream_t *Stream, struct device *dev, 
+		     struct device *orig_dev,
+		     int media, struct bootsector *boot)
+{
+	size_t tot_sectors;
+	int sect_per_track;
+	DeclareThis(RemoteFile_t);
+
+	dev->ssize = 2; /* allow for init_geom to change it */
+	dev->use_2m = 0x80; /* disable 2m mode to begin */
+
+	if(media == 0xf0 || media >= 0x100){		
+		dev->heads = WORD(nheads);
+		dev->sectors = WORD(nsect);
+		tot_sectors = DWORD(bigsect);
+		SET_INT(tot_sectors, WORD(psect));
+		sect_per_track = dev->heads * dev->sectors;
+		tot_sectors += sect_per_track - 1; /* round size up */
+		dev->tracks = tot_sectors / sect_per_track;
+
+	} else if (media >= 0xf8){
+		media &= 3;
+		dev->heads = old_dos[media].heads;
+		dev->tracks = old_dos[media].tracks;
+		dev->sectors = old_dos[media].sectors;
+		dev->ssize = 0x80;
+		dev->use_2m = ~1;
+	} else {
+		fprintf(stderr,"Unknown media type\n");
+		exit(1);
+	}
+
+	This->size = (mt_off_t) 512 * dev->sectors * dev->tracks * dev->heads;
+
+	return 0;
+}
+
+
+static int floppyd_data(Stream_t *Stream, time_t *date, mt_size_t *size,
+		     int *type, int *address)
+{
+	DeclareThis(RemoteFile_t);
+
+	if(date)
+		/* unknown, and irrelevant anyways */
+		*date = 0;
+	if(size)
+		/* the size derived from the geometry */
+		*size = (mt_size_t) This->size;
+	if(type)
+		*type = 0; /* not a directory */
+	if(address)
+		*address = 0;
+	return 0;
+}
+
+/* ######################################################################## */
+
+static Class_t FloppydFileClass = {
+	floppyd_read, 
+	floppyd_write,
+	floppyd_flush,
+	floppyd_free,
+	floppyd_geom,
+	floppyd_data
+};
+
+/* ######################################################################## */
+
+int get_host_and_port(const char* name, char** hostname, char **display,
+					  short* port)
+{
+	char* newname = strdup(name);
+	char* p;
+	char* p2;
+
+	p = newname;
+	while (*p != '/' && *p) p++;
+	p2 = p;
+	if (*p) p++;
+	*p2 = 0;
+	
+	*port = atoi(p);
+	if (*port == 0) {
+		*port = FLOPPYD_DEFAULT_PORT;	
+	}
+
+	*display = strdup(newname);
+
+	p = newname;
+	while (*p != ':' && *p) p++;
+	p2 = p;
+	if (*p) p++;
+	*p2 = 0;
+
+	*port += atoi(p);  /* add display number to the port */
+
+	if (!*newname || strcmp(newname, "unix") == 0) {
+		free(newname);
+		newname = strdup("localhost");
+	}
+
+	*hostname = newname;
+	return 1;
+}
+
+/*
+ *  * Return the IP address of the specified host.
+ *  */
+static IPaddr_t getipaddress(char *ipaddr)
+{
+	
+	struct hostent  *host;
+	IPaddr_t        ip;
+
+	if (((ip = inet_addr(ipaddr)) == INADDR_NONE) &&
+	    (strcmp(ipaddr, "255.255.255.255") != 0)) {
+		
+		if ((host = gethostbyname(ipaddr)) != NULL) {
+			memcpy(&ip, host->h_addr, sizeof(ip));
+		}
+		
+		endhostent();
+	}
+	
+#ifdef DEBUG
+	fprintf(stderr, "IP lookup %s -> 0x%08lx\n", ipaddr, ip);
+#endif
+	  
+	return (ip);
+}
+
+/*
+ *  * Connect to the floppyd server.
+ *  */
+static int connect_to_server(IPaddr_t ip, short port)
+{
+	
+	struct sockaddr_in      addr;
+	int                     sock;
+	
+	/*
+	 * Allocate a socket.
+	 */
+	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		return (-1);
+	}
+	
+	/*
+	 * Set the address to connect to.
+	 */
+	
+	addr.sin_family = AF_INET;
+#ifndef HAVE_HTONS
+	addr.sin_port = myhtons(port);
+#else	
+	addr.sin_port = htons(port);
+#endif	
+	addr.sin_addr.s_addr = ip;
+	
+        /*
+	 * Connect our socket to the above address.
+	 */
+	if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+		return (-1);
+	}
+
+        /*
+	 * Set the keepalive socket option to on.
+	 */
+	{
+		int             on = 1;
+		setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, 
+			   (char *)&on, sizeof(on));
+	}
+	
+	return (sock);
+}
+
+static int ConnectToFloppyd(const char* name);
+
+Stream_t *FloppydOpen(struct device *dev, struct device *dev2,
+					  char *name, int mode, char *errmsg,
+					  int mode2, int locked)
+{
+	RemoteFile_t *This;
+
+	if (!dev ||  !(dev->misc_flags & FLOPPYD_FLAG))
+		return NULL;
+	
+	This = New(RemoteFile_t);
+	if (!This){
+		printOom();
+		return NULL;
+	}
+	This->Class = &FloppydFileClass;
+	This->Next = 0;
+	This->offset = 0;
+	This->lastwhere = 0;
+	This->refs = 1;
+	This->Buffer = 0;
+
+	This->fd = ConnectToFloppyd(name);
+	if (This->fd == -1) {
+		Free(This);
+		return NULL;
+	}
+	return (Stream_t *) This;
+}
+
+static int ConnectToFloppyd(const char* name) 
+{
+	char* hostname;
+	char* display;
+	short port;
+	int rval = get_host_and_port(name, &hostname, &display, &port);
+	int sock;
+	int reply;
+	
+	if (!rval) return -1;
+
+	sock = connect_to_server(getipaddress(hostname), port);
+
+	if (sock == -1) {
+		fprintf(stderr,
+			"Can't connect to floppyd server on %s, port %i!\n",
+			hostname, port);
+		return -1;
+	}
+	
+	reply = authenticate_to_floppyd(sock, display);
+
+	if (reply != 0) {
+		fprintf(stderr, 
+			"Permission denied, authentication failed!\n"
+			"%s\n", AuthErrors[reply]);
+		return -1;
+	}
+	
+	free(hostname);
+	free(display);
+
+	return sock;
+}
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/floppyd_io.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/floppyd_io.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/floppyd_io.h	(revision 9)
@@ -0,0 +1,37 @@
+#ifndef MTOOLS_FLOPPYDIO_H
+#define MTOOLS_FLOPPYDIO_H
+
+#ifdef USE_FLOPPYD
+
+#include "stream.h"
+
+/*extern int ConnectToFloppyd(const char* name, Class_t** ioclass);*/
+Stream_t *FloppydOpen(struct device *dev, struct device *dev2,
+					  char *name, int mode, char *errmsg,
+					  int mode2, int locked);
+
+#define FLOPPYD_DEFAULT_PORT 5703
+#define FLOPPYD_PROTOCOL_VERSION 10
+
+enum FloppydOpcodes {
+	OP_READ,
+	OP_WRITE,
+	OP_SEEK,
+	OP_FLUSH,
+	OP_CLOSE,
+	OP_IOCTL
+};
+
+enum AuthErrorsEnum {
+	AUTH_SUCCESS,
+	AUTH_PACKETOVERSIZE,
+	AUTH_AUTHFAILED,
+	AUTH_WRONGVERSION,
+	AUTH_DEVLOCKED,
+	AUTH_BADPACKET
+};
+
+typedef unsigned long IPaddr_t;
+
+#endif
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/force_io.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/force_io.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/force_io.c	(revision 9)
@@ -0,0 +1,48 @@
+/*
+ * Force I/O to be done to complete transfer length
+ *
+ * written by:
+ *
+ * Alain L. Knaff			
+ * alain@linux.lu
+ *
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "stream.h"
+
+static int force_io(Stream_t *Stream,
+		    char *buf, mt_off_t start, size_t len,
+		    int (*io)(Stream_t *, char *, mt_off_t, size_t))
+{
+	int ret;
+	int done=0;
+	
+	while(len){
+		ret = io(Stream, buf, start, len);
+		if ( ret <= 0 ){
+			if (done)
+				return done;
+			else
+				return ret;
+		}
+		start += ret;
+		done += ret;
+		len -= ret;
+		buf += ret;
+	}
+	return done;
+}
+
+int force_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
+{
+	return force_io(Stream, buf, start, len,
+					Stream->Class->write);
+}
+
+int force_read(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
+{
+	return force_io(Stream, buf, start, len,
+					Stream->Class->read);
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/fs.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/fs.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/fs.h	(revision 9)
@@ -0,0 +1,26 @@
+#ifndef MTOOLS_FS_H
+#define MTOOLS_FS_H
+
+#include "stream.h"
+
+
+typedef struct FsPublic_t {
+	Class_t *Class;
+	int refs;
+	Stream_t *Next;
+	Stream_t *Buffer;
+
+	int serialized;
+	unsigned long serial_number;
+	int cluster_size;
+	unsigned int sector_size;
+} FsPublic_t;
+
+Stream_t *fs_init(char *drive, int mode);
+int fat_free(Stream_t *Dir, unsigned int fat);
+int fatFreeWithDir(Stream_t *Dir, struct directory *dir);
+int fat_error(Stream_t *Dir);
+int fat32RootCluster(Stream_t *Dir);
+char *getDrive(Stream_t *Stream);
+
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/fsP.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/fsP.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/fsP.h	(revision 9)
@@ -0,0 +1,84 @@
+#ifndef MTOOLS_FSP_H
+#define MTOOLS_FSP_H
+
+#include "stream.h"
+#include "msdos.h"
+#include "fs.h"
+
+typedef enum fatAccessMode_t { 
+	FAT_ACCESS_READ, 
+	FAT_ACCESS_WRITE
+} fatAccessMode_t;
+
+typedef struct Fs_t {
+	Class_t *Class;
+	int refs;
+	Stream_t *Next;
+	Stream_t *Buffer;
+	
+	int serialized;
+	unsigned long serial_number;
+	int cluster_size;
+	unsigned int sector_size;
+	int fat_error;
+
+	unsigned int (*fat_decode)(struct Fs_t *This, unsigned int num);
+	void (*fat_encode)(struct Fs_t *This, unsigned int num,
+			   unsigned int code);
+
+	Stream_t *Direct;
+	int fat_dirty;
+	unsigned int fat_start;
+	unsigned int fat_len;
+
+	int num_fat;
+	unsigned int end_fat;
+	unsigned int last_fat;
+	int fat_bits;
+	struct FatMap_t *FatMap;
+
+	int dir_start;
+	int dir_len;
+	int clus_start;
+
+	int num_clus;
+	char *drive; /* for error messages */
+
+	/* fat 32 */
+	unsigned int primaryFat;
+	unsigned int writeAllFats;
+	unsigned int rootCluster;
+	int infoSectorLoc;
+	unsigned int last; /* last sector allocated, or MAX32 if unknown */
+	unsigned int freeSpace; /* free space, or MAX32 if unknown */
+	int preallocatedClusters;
+
+	int lastFatSectorNr;
+	unsigned char *lastFatSectorData;
+	fatAccessMode_t lastFatAccessMode;
+	int sectorMask;
+	int sectorShift;
+} Fs_t;
+
+int fs_free(Stream_t *Stream);
+
+void set_fat12(Fs_t *Fs);
+void set_fat16(Fs_t *Fs);
+void set_fat32(Fs_t *Fs);
+unsigned int get_next_free_cluster(Fs_t *Fs, unsigned int last);
+unsigned int fatDecode(Fs_t *This, unsigned int pos);
+void fatAppend(Fs_t *This, unsigned int pos, unsigned int newpos);
+void fatDeallocate(Fs_t *This, unsigned int pos);
+void fatAllocate(Fs_t *This, unsigned int pos, unsigned int value);
+void fatEncode(Fs_t *This, unsigned int pos, unsigned int value);
+
+int fat_read(Fs_t *This, struct bootsector *boot, int fat_bits,
+			 size_t tot_sectors, int nodups);
+void fat_write(Fs_t *This);
+int zero_fat(Fs_t *Fs, int media_descriptor);
+extern Class_t FsClass;
+int fsPreallocateClusters(Fs_t *Fs, long);
+Fs_t *getFs(Stream_t *Stream);
+
+
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/hash.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/hash.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/hash.c	(revision 9)
@@ -0,0 +1,205 @@
+/*
+ * hash.c - hash table.
+ */
+
+#include "sysincludes.h"
+#include "htable.h"
+#include "mtools.h"
+
+struct hashtable {
+  T_HashFunc f1,f2;
+  T_ComparFunc compar;
+  int size;  /* actual size of the array */
+  int fill;  /* number of deleted or in use slots */
+  int inuse; /* number of slots in use */
+  int max;   /* maximal number of elements to keep efficient */
+  T_HashTableEl *entries;
+};
+
+static int sizes[]={5, 11, 23, 47, 97, 197, 397, 797, 1597, 3203, 6421, 12853,
+		    25717, 51437, 102877, 205759, 411527, 823117, 1646237,
+		    3292489, 6584983, 13169977, 26339969, 52679969, 105359939,
+		    210719881, 421439783, 842879579, 1685759167, 0 };
+static int deleted=0;
+static int unallocated=0;
+
+static int alloc_ht(T_HashTable *H, int size)
+{
+  int i;
+
+  for(i=0; sizes[i]; i++)
+    if (sizes[i] > size*4 )
+      break;
+  if (!sizes[i])
+    for(i=0; sizes[i]; i++)
+      if (sizes[i] > size*2 )
+	break;
+  if (!sizes[i])
+    for(i=0; sizes[i]; i++)
+      if (sizes[i] > size)
+	break;
+  if(!sizes[i])
+    return -1;
+  size = sizes[i];
+  if(size < H->size)
+	  size = H->size; /* never shrink the table */
+  H->max = size * 4 / 5 - 2;
+  H->size = size;
+  H->fill = 0;
+  H->inuse = 0;
+  H->entries = NewArray(size, T_HashTableEl);
+  if (H->entries == NULL)
+    return -1; /* out of memory error */
+  
+  for(i=0; i < size; i++)
+    H->entries[i] = &unallocated;
+  return 0;
+}
+
+int make_ht(T_HashFunc f1, T_HashFunc f2, T_ComparFunc c, int size,
+	    T_HashTable **H)
+{
+  *H = New(T_HashTable);
+  if (*H == NULL){
+    return -1; /* out of memory error */
+  }
+  
+  (*H)->f1 = f1;
+  (*H)->f2 = f2;
+  (*H)->compar = c;
+  (*H)->size = 0;
+  if(alloc_ht(*H,size))
+    return -1;
+  return 0;
+}
+
+int free_ht(T_HashTable *H, T_HashFunc entry_free)
+{
+  int i;
+  if(entry_free)
+    for(i=0; i< H->size; i++)
+      if (H->entries[i] != &unallocated &&
+	  H->entries[i] != &deleted)
+	entry_free(H->entries[i]);
+  Free(H->entries);
+  Free(H);
+  return 0;
+}
+
+/* add into hash table without checking for repeats */
+static int _hash_add(T_HashTable *H,T_HashTableEl *E, int *hint)
+{
+  int f2, pos, ctr;
+
+  pos = H->f1(E) % H->size;
+  f2 = -1;
+  ctr = 0;
+  while(H->entries[pos] != &unallocated &&
+	H->entries[pos] != &deleted){
+    if (f2 == -1)
+      f2 = H->f2(E) % (H->size - 1);
+    pos = (pos+f2+1) % H->size;
+    ctr++;
+  }
+  if(H->entries[pos] == &unallocated)
+     H->fill++; /* only increase fill if the previous element was not yet
+		 * counted, i.e. unallocated */
+  H->inuse++;
+  H->entries[pos] = E;
+  if(hint)
+	  *hint = pos;
+  return 0;
+}
+
+static int rehash(T_HashTable *H)
+{
+  int size,i;
+  T_HashTableEl *oldentries;
+  /* resize the table */
+  
+  size = H->size;
+  oldentries = H->entries;
+  if(alloc_ht(H,((H->inuse+1)*4+H->fill)/5))
+	  return -1;
+
+  for(i=0; i < size; i++){
+    if(oldentries[i] != &unallocated && oldentries[i] != &deleted)
+      _hash_add(H, oldentries[i], 0);
+  }
+  Free(oldentries);
+  return 0;
+}
+
+int hash_add(T_HashTable *H, T_HashTableEl *E, int *hint)
+{
+  if (H->fill >= H->max)
+    rehash(H);
+  if (H->fill == H->size)
+    return -1; /*out of memory error */
+  return _hash_add(H,E, hint);
+}
+
+
+/* add into hash table without checking for repeats */
+static int _hash_lookup(T_HashTable *H,T_HashTableEl *E, T_HashTableEl **E2,
+			int *hint, int isIdentity)
+{
+  int f2, pos, upos, ttl;
+
+  pos = H->f1(E) % H->size;
+  ttl = H->size;
+  f2 = -1;
+  upos = -1;
+  while(ttl &&
+	H->entries[pos] != &unallocated &&
+	(H->entries[pos] == &deleted ||
+	 ((isIdentity || H->compar(H->entries[pos], E) != 0) &&
+	  (!isIdentity || H->entries[pos] != E)))){
+    if (f2 == -1)
+      f2 = H->f2(E) % (H->size - 1);
+    if (upos == -1 && H->entries[pos] == &deleted)
+      upos = pos;
+    pos = (pos+f2+1) % H->size;
+    ttl--;
+  }
+  if(H->entries[pos] == &unallocated || !ttl)
+    return -1;
+  if (upos != -1){
+    H->entries[upos] = H->entries[pos];
+    H->entries[pos] = &deleted;
+    pos = upos;
+  }
+  if(hint)
+    *hint = pos;
+  *E2= H->entries[pos];
+  return 0;
+}
+
+
+int hash_lookup(T_HashTable *H,T_HashTableEl *E, T_HashTableEl **E2,
+		int *hint)
+{
+	return _hash_lookup(H, E, E2, hint, 0);
+}
+
+/* add into hash table without checking for repeats */
+int hash_remove(T_HashTable *H,T_HashTableEl *E, int hint)
+{
+  T_HashTableEl *E2;
+
+  if (hint >=0 && hint < H->size &&
+      H->entries[hint] == E){
+    H->inuse--;
+    H->entries[hint] = &deleted;
+    return 0;
+  }
+
+  if(_hash_lookup(H, E, &E2, &hint, 1)) {
+	  fprintf(stderr, "Removing non-existent entry\n");
+	  exit(1);
+	  return -1;
+  }
+  H->inuse--;
+  H->entries[hint] = &deleted;
+  return 0;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/htable.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/htable.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/htable.h	(revision 9)
@@ -0,0 +1,17 @@
+/*
+ * hashtable
+ */
+
+typedef struct hashtable T_HashTable;
+typedef void *T_HashTableEl;
+typedef unsigned int (*T_HashFunc)(void *);
+typedef int (*T_ComparFunc)(void *, void *);
+
+
+int make_ht(T_HashFunc f1, T_HashFunc f2, T_ComparFunc c, int size, T_HashTable **H);
+int hash_add(T_HashTable *H, T_HashTableEl *E, int *hint);
+int hash_remove(T_HashTable *H, T_HashTableEl *E, int hint);
+int hash_lookup(T_HashTable *H, T_HashTableEl *E, T_HashTableEl **E2,
+		int *hint);
+int free_ht(T_HashTable *H, T_HashFunc entry_free);
+
Index: /trunk/minix/commands/i386/mtools-3.9.7/init.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/init.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/init.c	(revision 9)
@@ -0,0 +1,414 @@
+/*
+ * Initialize an MSDOS diskette.  Read the boot sector, and switch to the
+ * proper floppy disk device to match the format on the disk.  Sets a bunch
+ * of global variables.  Returns 0 on success, or 1 on failure.
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "stream.h"
+#include "mtools.h"
+#include "fsP.h"
+#include "plain_io.h"
+#include "floppyd_io.h"
+#include "xdf_io.h"
+#include "buffer.h"
+
+extern int errno;
+
+
+#ifndef OS_Minix		/* Minix is memory starved. */
+#define FULL_CYL
+#endif
+
+unsigned int num_clus;			/* total number of cluster */
+
+
+/*
+ * Read the boot sector.  We glean the disk parameters from this sector.
+ */
+static int read_boot(Stream_t *Stream, struct bootsector * boot, int size)
+{	
+	/* read the first sector, or part of it */
+	if(!size)
+		size = BOOTSIZE;
+	if(size > 1024)
+		size = 1024;
+
+	if (force_read(Stream, (char *) boot, 0, size) != size)
+		return -1;
+	return 0;
+}
+
+static int fs_flush(Stream_t *Stream)
+{
+	DeclareThis(Fs_t);
+
+	fat_write(This);
+	return 0;
+}
+
+Class_t FsClass = {
+	read_pass_through, /* read */
+	write_pass_through, /* write */
+	fs_flush, 
+	fs_free, /* free */
+	0, /* set geometry */
+	get_data_pass_through,
+	0 /* pre allocate */
+};
+
+static int get_media_type(Stream_t *St, struct bootsector *boot)
+{
+	int media;
+
+	media = boot->descr;
+	if(media < 0xf0){
+		char temp[512];
+		/* old DOS disk. Media descriptor in the first FAT byte */
+		/* old DOS disk always have 512-byte sectors */
+		if (force_read(St,temp,(mt_off_t) 512,512) == 512)
+			media = (unsigned char) temp[0];
+		else
+			media = 0;
+	} else
+		media += 0x100;
+	return media;
+}
+
+
+Stream_t *GetFs(Stream_t *Fs)
+{
+	while(Fs && Fs->Class != &FsClass)
+		Fs = Fs->Next;
+	return Fs;
+}
+
+Stream_t *find_device(char *drive, int mode, struct device *out_dev,
+		      struct bootsector *boot,
+		      char *name, int *media, mt_size_t *maxSize)
+{
+	char errmsg[200];
+	Stream_t *Stream;
+	struct device *dev;
+	int r;
+#ifdef OS_Minix
+	static char *devname;
+	struct device onedevice[2];
+	struct stat stbuf;
+
+	free(devname);
+	devname = safe_malloc((9 + strlen(drive)) * sizeof(devname[0]));
+	strcpy(devname, "/dev/dosX");
+	if (isupper(drive[0]) && drive[1] == 0) {
+		/* single letter device name, use /dev/dos$drive */
+		devname[8]= drive[0];
+	} else
+	if (strchr(drive, '/') == NULL) {
+		/* a simple name, use /dev/$drive */
+		strcpy(devname+5, drive);
+	} else {
+		/* a pathname, use as is. */
+		strcpy(devname, drive);
+	}
+	if (stat(devname, &stbuf) != -1) {
+		memset(onedevice, 0, sizeof(onedevice));
+		onedevice[0].name = devname;
+		onedevice[0].drive = drive;
+		onedevice[1].name = NULL;
+		onedevice[1].drive = NULL;
+		dev = onedevice;
+	} else {
+		dev = devices;
+	}
+#else
+	dev = devices;
+#endif
+
+	Stream = NULL;
+	sprintf(errmsg, "Drive '%s:' not supported", drive);	
+					/* open the device */
+	for (; dev->name; dev++) {
+		FREE(&Stream);
+		if (strcmp(dev->drive, drive) != 0)
+			continue;
+		*out_dev = *dev;
+		expand(dev->name,name);
+#ifdef USING_NEW_VOLD
+		strcpy(name, getVoldName(dev, name));
+#endif
+
+		Stream = 0;
+#ifdef USE_XDF
+		Stream = XdfOpen(out_dev, name, mode, errmsg, 0);
+		if(Stream) {
+			out_dev->use_2m = 0x7f;
+			if(maxSize)
+			    *maxSize = max_off_t_31;
+		}
+#endif
+
+#ifdef USE_FLOPPYD
+		if(!Stream) {
+			Stream = FloppydOpen(out_dev, dev, name, mode, errmsg, 0, 1);
+			if(Stream && maxSize)
+				*maxSize = max_off_t_31;
+		}
+#endif
+
+		if (!Stream)
+			Stream = SimpleFileOpen(out_dev, dev, name, mode,
+						errmsg, 0, 1, maxSize);
+
+		if( !Stream)
+			continue;
+
+		/* read the boot sector */
+		if ((r=read_boot(Stream, boot, out_dev->blocksize)) < 0){
+			sprintf(errmsg,
+				"init %s: could not read boot sector",
+				drive);
+			continue;
+		}
+
+		if((*media= get_media_type(Stream, boot)) <= 0xf0 ){
+			if (boot->jump[2]=='L') 
+				sprintf(errmsg,
+					"diskette %s: is Linux LILO, not DOS", 
+					drive);
+			else 
+				sprintf(errmsg,"init %s: non DOS media", drive);
+			continue;
+		}
+
+		/* set new parameters, if needed */
+		errno = 0;
+		if(SET_GEOM(Stream, out_dev, dev, *media, boot)){
+			if(errno)
+#ifdef HAVE_SNPRINTF
+				snprintf(errmsg, 199,
+					"Can't set disk parameters for %s: %s", 
+					drive, strerror(errno));
+#else
+				sprintf(errmsg,
+					"Can't set disk parameters for %s: %s", 
+					drive, strerror(errno));
+#endif
+			else
+				sprintf(errmsg, 
+					"Can't set disk parameters for %s", 
+					drive);
+			continue;
+		}
+		break;
+	}
+
+	/* print error msg if needed */	
+	if ( dev->drive == 0 ){
+		FREE(&Stream);
+		fprintf(stderr,"%s\n",errmsg);
+		return NULL;
+	}
+#ifdef OS_Minix
+	/* Minix can lseek up to 4G. */
+	if (maxSize) *maxSize = 0xFFFFFFFFUL;
+#endif
+	return Stream;
+}
+
+
+Stream_t *fs_init(char *drive, int mode)
+{
+	int blocksize;
+	int media,i;
+	int nhs;
+	int disk_size = 0;	/* In case we don't happen to set this below */
+	size_t tot_sectors;
+	char name[EXPAND_BUF];
+	int cylinder_size;
+	struct device dev;
+	mt_size_t maxSize;
+
+	struct bootsector boot0;
+#define boot (&boot0)
+	Fs_t *This;
+
+	This = New(Fs_t);
+	if (!This)
+		return NULL;
+
+	This->Direct = NULL;
+	This->Next = NULL;
+	This->refs = 1;
+	This->Buffer = 0;
+	This->Class = &FsClass;
+	This->preallocatedClusters = 0;
+	This->lastFatSectorNr = 0;
+	This->lastFatAccessMode = 0;
+	This->lastFatSectorData = 0;
+	This->drive = drive;
+	This->last = 0;
+
+	This->Direct = find_device(drive, mode, &dev, &boot0, name, &media, 
+							   &maxSize);
+	if(!This->Direct)
+		return NULL;
+	
+	This->sector_size = WORD(secsiz);
+	if(This->sector_size > MAX_SECTOR){
+		fprintf(stderr,"init %s: sector size too big\n", drive);
+		return NULL;
+	}
+
+	i = log_2(This->sector_size);
+
+	if(i == 24) {
+		fprintf(stderr, 
+			"init %c: sector size (%d) not a small power of two\n",
+			drive, This->sector_size);
+		return NULL;
+	}
+	This->sectorShift = i;
+	This->sectorMask = This->sector_size - 1;
+
+
+	cylinder_size = dev.heads * dev.sectors;
+	if (!tot_sectors) tot_sectors = dev.tracks * cylinder_size;
+
+	This->serialized = 0;
+	if ((media & ~7) == 0xf8){
+		i = media & 3;
+		This->cluster_size = old_dos[i].cluster_size;
+		tot_sectors = cylinder_size * old_dos[i].tracks;
+		This->fat_start = 1;
+		This->fat_len = old_dos[i].fat_len;
+		This->dir_len = old_dos[i].dir_len;
+		This->num_fat = 2;
+		This->sector_size = 512;
+		This->sectorShift = 9;
+		This->sectorMask = 511;
+		This->fat_bits = 12;
+		nhs = 0;
+	} else {
+		struct label_blk_t *labelBlock;
+		/*
+		 * all numbers are in sectors, except num_clus 
+		 * (which is in clusters)
+		 */
+		tot_sectors = WORD(psect);
+		if(!tot_sectors) {
+			tot_sectors = DWORD(bigsect);			
+			nhs = DWORD(nhs);
+		} else
+			nhs = WORD(nhs);
+
+
+		This->cluster_size = boot0.clsiz; 		
+		This->fat_start = WORD(nrsvsect);
+		This->fat_len = WORD(fatlen);
+		This->dir_len = WORD(dirents) * MDIR_SIZE / This->sector_size;
+		This->num_fat = boot0.nfat;
+
+		if (This->fat_len) {
+			labelBlock = &boot0.ext.old.labelBlock;
+		} else {
+			labelBlock = &boot0.ext.fat32.labelBlock;
+		}
+
+		if(labelBlock->dos4 == 0x29) {
+			This->serialized = 1;
+			This->serial_number = _DWORD(labelBlock->serial);
+		}
+	}
+
+	if (tot_sectors >= (maxSize >> This->sectorShift)) {
+		fprintf(stderr, "Big disks not supported on this architecture\n");
+		exit(1);
+	}
+
+#ifndef OS_Minix   /* Strange check, MS-DOS isn't that picky. */
+
+	if(!mtools_skip_check && (tot_sectors % dev.sectors)){
+		fprintf(stderr,
+			"Total number of sectors not a multiple of"
+			" sectors per track!\n");
+		fprintf(stderr,
+			"Add mtools_skip_check=1 to your .mtoolsrc file "
+			"to skip this test\n");
+		exit(1);
+	}
+#endif
+
+	/* full cylinder buffering */
+#ifdef FULL_CYL
+	disk_size = (dev.tracks) ? cylinder_size : 512;
+#else /* FULL_CYL */
+	disk_size = (dev.tracks) ? dev.sectors : 512;
+#endif /* FULL_CYL */
+
+#if (defined OS_sysv4 && !defined OS_solaris)
+	/*
+	 * The driver in Dell's SVR4 v2.01 is unreliable with large writes.
+	 */
+        disk_size = 0;
+#endif /* (defined sysv4 && !defined(solaris)) */
+
+#ifdef OS_linux
+	disk_size = cylinder_size;
+#endif
+
+#if 1
+	if(disk_size > 256) {
+		disk_size = dev.sectors;
+		if(dev.sectors % 2)
+			disk_size <<= 1;
+	}
+#endif
+	if (disk_size % 2)
+		disk_size *= 2;
+
+	if(!dev.blocksize || dev.blocksize < This->sector_size)
+		blocksize = This->sector_size;
+	else
+		blocksize = dev.blocksize;
+	if (disk_size)
+		This->Next = buf_init(This->Direct,
+				      8 * disk_size * blocksize,
+				      disk_size * blocksize,
+				      This->sector_size);
+	else
+		This->Next = This->Direct;
+
+	if (This->Next == NULL) {
+		perror("init: allocate buffer");
+		This->Next = This->Direct;
+	}
+
+	/* read the FAT sectors */
+	if(fat_read(This, &boot0, dev.fat_bits, tot_sectors, dev.use_2m&0x7f)){
+		This->num_fat = 1;
+		FREE(&This->Next);
+		Free(This->Next);
+		return NULL;
+	}
+	return (Stream_t *) This;
+}
+
+char *getDrive(Stream_t *Stream)
+{
+	DeclareThis(Fs_t);
+
+	if(This->Class != &FsClass)
+		return getDrive(GetFs(Stream));
+	else
+		return This->drive;
+}
+
+int fsPreallocateClusters(Fs_t *Fs, long size)
+{
+	if(size > 0 && getfreeMinClusters((Stream_t *)Fs, size) != 1)
+		return -1;
+
+	Fs->preallocatedClusters += size;
+	return 0;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/llong.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/llong.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/llong.c	(revision 9)
@@ -0,0 +1,84 @@
+#include "sysincludes.h"
+#include "stream.h"
+#include "fsP.h"
+#include "llong.h"
+#include "mtools.h"
+
+/* Warnings about integer overflow in expression can be ignored.  These are
+ * due to the way that maximal values for those integers are computed: 
+ * intentional overflow from smallest negative number (1000...) to highest 
+ * positive number (0111...) by substraction of 1 */
+#ifdef __GNUC__
+/*
+#warning "The following warnings about integer overflow in expression can be safely ignored"
+*/
+#endif
+
+#if 1
+const mt_off_t max_off_t_31 = MAX_OFF_T_B(31); /* Floppyd */
+const mt_off_t max_off_t_41 = MAX_OFF_T_B(41); /* SCSI */
+const mt_off_t max_off_t_seek = MAX_OFF_T_B(SEEK_BITS); /* SCSI */
+#else
+const mt_off_t max_off_t_31 = MAX_OFF_T_B(10); /* Floppyd */
+const mt_off_t max_off_t_41 = MAX_OFF_T_B(10); /* SCSI */
+const mt_off_t max_off_t_seek = MAX_OFF_T_B(10); /* SCSI */
+#endif
+
+off_t truncBytes32(mt_off_t off)
+{
+	if (off & ~max_off_t_31) {
+		fprintf(stderr, "Internal error, offset too big\n");
+		exit(1);
+	}
+	return (off_t) off;
+}
+
+mt_off_t sectorsToBytes(Stream_t *Stream, off_t off)
+{
+	DeclareThis(Fs_t);
+	return (mt_off_t) off << This->sectorShift;
+}
+
+#if defined HAVE_LLSEEK
+# ifndef HAVE_LLSEEK_PROTOTYPE
+extern long long llseek (int fd, long long offset, int origin);
+# endif
+#endif
+
+#if defined HAVE_LSEEK64
+# ifndef HAVE_LSEEK64_PROTOTYPE
+extern long long lseek64 (int fd, long long offset, int origin);
+# endif
+#endif
+
+
+int mt_lseek(int fd, mt_off_t where, int whence)
+{
+#if defined HAVE_LSEEK64
+	if(lseek64(fd, where, whence) >= 0)
+		return 0;
+	else
+		return -1;
+#elif defined HAVE_LLSEEK
+	if(llseek(fd, where, whence) >= 0)
+		return 0;
+	else
+		return -1;		
+#else
+	if (lseek(fd, (off_t) where, whence) >= 0)
+		return 0;
+	else
+		return 1;
+#endif
+}
+
+int log_2(int size)
+{
+	int i;
+
+	for(i=0; i<24; i++) {
+		if(1 << i == size)
+			return i;
+	}
+	return 24;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/llong.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/llong.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/llong.h	(revision 9)
@@ -0,0 +1,81 @@
+#ifndef MTOOLS_LLONG_H
+#define MTOOLS_LLONG_H
+
+#if 1
+
+
+#ifdef HAVE_OFF_T_64
+/* if off_t is already 64 bits, be happy, and don't worry about the
+ * loff_t and llseek stuff */
+#define MT_OFF_T off_t
+#endif
+
+#ifndef MT_OFF_T
+# ifdef HAVE_LLSEEK
+/* we have llseek. Now, what's its type called? loff_t or offset_t ? */
+#  ifdef HAVE_LOFF_T
+#   define MT_OFF_T loff_t
+#  else
+#   ifdef HAVE_OFFSET_T
+#    define MT_OFF_T offset_t
+#   endif
+#  endif
+# endif
+#endif
+
+#ifndef MT_OFF_T
+/* we still don't have a suitable mt_off_t type...*/
+# ifdef HAVE_LONG_LONG
+/* ... first try long long ... */
+#  define MT_OFF_T long long
+# else
+/* ... and if that fails, fall back on good ole' off_t */
+#  define MT_OFF_T off_t
+# endif
+#endif
+
+typedef MT_OFF_T mt_off_t;
+
+#else
+/* testing: meant to flag dubious assignments between 32 bit length types
+ * and 64 bit ones */
+typedef struct {
+	int lo;
+	int high;
+} *mt_off_t;
+
+
+#endif
+
+typedef mt_off_t mt_size_t;
+
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#define MAX_OFF_T_B(bits) \
+	(((mt_off_t) 1 << min(bits, sizeof(mt_off_t)*8 - 1)) - 1)
+
+#ifdef HAVE_LLSEEK
+# define SEEK_BITS 63
+#else
+# define SEEK_BITS (sizeof(off_t) * 8 - 1)
+#endif
+
+extern const mt_off_t max_off_t_31;
+extern const mt_off_t max_off_t_41;
+extern const mt_off_t max_off_t_seek;
+
+extern off_t truncBytes32(mt_off_t off);
+mt_off_t sectorsToBytes(Stream_t *This, off_t off);
+
+mt_size_t getfree(Stream_t *Stream);
+int getfreeMinBytes(Stream_t *Stream, mt_size_t ref);
+
+Stream_t *find_device(char *drive, int mode, struct device *out_dev,
+					  struct bootsector *boot,
+					  char *name, int *media, mt_size_t *maxSize);
+
+int mt_lseek(int fd, mt_off_t where, int whence);
+
+
+int log_2(int);
+
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/mainloop.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mainloop.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mainloop.c	(revision 9)
@@ -0,0 +1,557 @@
+/*
+ * mainloop.c
+ * Iterating over all the command line parameters, and matching patterns
+ * where needed
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "vfat.h"
+#include "fs.h"
+#include "mainloop.h"
+#include "plain_io.h"
+#include "file.h"
+
+
+int unix_dir_loop(Stream_t *Stream, MainParam_t *mp); 
+int unix_loop(Stream_t *Stream, MainParam_t *mp, char *arg, 
+	      int follow_dir_link);
+
+static int _unix_loop(Stream_t *Dir, MainParam_t *mp, const char *filename)
+{
+	unix_dir_loop(Dir, mp);
+	return GOT_ONE;
+}
+
+int unix_loop(Stream_t *Stream, MainParam_t *mp, char *arg, int follow_dir_link)
+{
+	int ret;
+	int isdir;
+
+	mp->File = NULL;
+	mp->direntry = NULL;
+	mp->unixSourceName = arg;
+	/*	mp->dir.attr = ATTR_ARCHIVE;*/
+	mp->loop = _unix_loop;
+	if((mp->lookupflags & DO_OPEN)){
+		mp->File = SimpleFileOpen(0, 0, arg, O_RDONLY, 0, 0, 0, 0);
+		if(!mp->File){
+			perror(arg);
+#if 0
+			tmp = _basename(arg);
+			strncpy(mp->filename, tmp, VBUFSIZE);
+			mp->filename[VBUFSIZE-1] = '\0';
+#endif
+			return ERROR_ONE;
+		}
+		GET_DATA(mp->File, 0, 0, &isdir, 0);
+		if(isdir) {
+			struct stat buf;
+
+			FREE(&mp->File);
+#ifdef S_ISLNK
+			if(!follow_dir_link &&
+			   lstat(arg, &buf) == 0 &&
+			   S_ISLNK(buf.st_mode)) {
+				/* skip links to directories in order to avoid
+				 * infinite loops */
+				fprintf(stderr, 
+					"skipping directory symlink %s\n", 
+					arg);
+				return 0;				
+			}
+#endif
+			if(! (mp->lookupflags & ACCEPT_DIR))
+				return 0;
+			mp->File = OpenDir(Stream, arg);
+		}
+	}
+
+	if(isdir)
+		ret = mp->dirCallback(0, mp);
+	else
+		ret = mp->unixcallback(mp);
+	FREE(&mp->File);
+	return ret;
+}
+
+
+int isSpecial(const char *name)
+{
+	if(name[0] == '\0')
+		return 1;
+	if(!strcmp(name,"."))
+		return 1;
+	if(!strcmp(name,".."))
+		return 1;
+	return 0;			
+}
+
+
+static int checkForDot(int lookupflags, const char *name)
+{
+	return (lookupflags & NO_DOTS) && isSpecial(name);
+}
+
+
+typedef struct lookupState_t {
+	Stream_t *container;
+	int nbContainers;
+	Stream_t *Dir;
+	int nbDirs;
+	const char *filename;
+} lookupState_t;
+
+static int isUniqueTarget(const char *name)
+{
+	return name && strcmp(name, "-");
+}
+
+static int handle_leaf(direntry_t *direntry, MainParam_t *mp,
+		       lookupState_t *lookupState)
+{
+	Stream_t *MyFile=0;
+	int ret;
+
+	if(got_signal)
+		return ERROR_ONE;
+	if(lookupState) {
+		/* we are looking for a "target" file */
+		switch(lookupState->nbDirs) {
+			case 0: /* no directory yet, open it */
+				lookupState->Dir = OpenFileByDirentry(direntry);
+				lookupState->nbDirs++;
+				/* dump the container, we have
+				 * better now */
+				FREE(&lookupState->container);
+				return 0;
+			case 1: /* we have already a directory */
+				FREE(&lookupState->Dir);
+				fprintf(stderr,"Ambigous\n");
+				return STOP_NOW | ERROR_ONE;
+			default:
+				return STOP_NOW | ERROR_ONE;
+		}
+	}
+
+	mp->direntry = direntry;
+	if(IS_DIR(direntry)) {
+		if(mp->lookupflags & (DO_OPEN | DO_OPEN_DIRS))
+			MyFile = mp->File = OpenFileByDirentry(direntry);
+		ret = mp->dirCallback(direntry, mp);
+	} else {
+		if(mp->lookupflags & DO_OPEN)
+			MyFile = mp->File = OpenFileByDirentry(direntry);
+		ret = mp->callback(direntry, mp);
+	}
+	FREE(&MyFile);
+	if(isUniqueTarget(mp->targetName))
+		ret |= STOP_NOW;
+	return ret;
+}
+
+static int _dos_loop(Stream_t *Dir, MainParam_t *mp, const char *filename)
+{	
+	Stream_t *MyFile=0;
+	direntry_t entry;
+	int ret;
+	int r;
+	
+	ret = 0;
+	r=0;
+	initializeDirentry(&entry, Dir);
+	while(!got_signal &&
+	      (r=vfat_lookup(&entry, filename, -1,
+			     mp->lookupflags, mp->shortname, 
+			     mp->longname)) == 0 ){
+		mp->File = NULL;
+		if(!checkForDot(mp->lookupflags,entry.name)) {
+			MyFile = 0;
+			if((mp->lookupflags & DO_OPEN) ||
+			   (IS_DIR(&entry) && 
+			    (mp->lookupflags & DO_OPEN_DIRS))) {
+				MyFile = mp->File = OpenFileByDirentry(&entry);
+			}
+			if(got_signal)
+				break;
+			mp->direntry = &entry;
+			if(IS_DIR(&entry))
+				ret |= mp->dirCallback(&entry,mp);
+			else
+				ret |= mp->callback(&entry, mp);
+			FREE(&MyFile);
+		}
+		if (fat_error(Dir))
+			ret |= ERROR_ONE;
+		if(mp->fast_quit && (ret & ERROR_ONE))
+			break;
+	}
+	if (r == -2)
+	    return ERROR_ONE;
+	if(got_signal)
+		ret |= ERROR_ONE;
+	return ret;
+}
+
+static int recurs_dos_loop(MainParam_t *mp, const char *filename0, 
+			   const char *filename1,
+			   lookupState_t *lookupState)
+{
+	/* Dir is de-allocated by the same entity which allocated it */
+	const char *ptr;
+	direntry_t entry;
+	int length;
+	int lookupflags;
+	int ret;
+	int have_one;
+	int doing_mcwd;
+	int r;
+
+	while(1) {
+		/* strip dots and // */
+		if(!strncmp(filename0,"./", 2)) {
+			filename0 += 2;
+			continue;
+		}
+		if(!strcmp(filename0,".") && filename1) {
+			filename0 ++;
+			continue;
+		}
+		if(filename0[0] == '/') {
+			filename0++;
+			continue;
+		}
+		if(!filename0[0]) {
+			if(!filename1)
+				break;
+			filename0 = filename1;
+			filename1 = 0;
+			continue;
+		}
+		break;
+	}
+
+	if(!strncmp(filename0,"../", 3) || 
+	   (!strcmp(filename0, "..") && filename1)) {
+		/* up one level */
+		mp->File = getDirentry(mp->File)->Dir;
+		return recurs_dos_loop(mp, filename0+2, filename1, lookupState);
+	}
+
+	doing_mcwd = !!filename1;
+
+	ptr = strchr(filename0, '/');
+	if(!ptr) {			
+		length = strlen(filename0);		
+		ptr = filename1;
+		filename1 = 0;
+	} else {
+		length = ptr - filename0;
+		ptr++;
+	}
+	if(!ptr) {
+		if(mp->lookupflags & OPEN_PARENT) {
+			mp->targetName = filename0;
+			ret = handle_leaf(getDirentry(mp->File), mp, 
+					  lookupState);
+			mp->targetName = 0;
+			return ret;
+		}
+		
+		if(!strcmp(filename0, ".") || !filename0[0]) {
+			return handle_leaf(getDirentry(mp->File), 
+					   mp, lookupState);
+		}
+
+		if(!strcmp(filename0, "..")) {
+			return handle_leaf(getParent(getDirentry(mp->File)), mp,
+					   lookupState);
+		}
+
+		lookupflags = mp->lookupflags;
+		
+		if(lookupState) {
+			lookupState->filename = filename0;
+			if(lookupState->nbContainers + lookupState->nbDirs > 0){
+				/* we have already one target, don't bother 
+				 * with this one. */
+				FREE(&lookupState->container);
+			} else {
+				/* no match yet.  Remember this container for 
+				 * later use */
+				lookupState->container = COPY(mp->File);
+			}
+			lookupState->nbContainers++;
+		}
+	} else
+		lookupflags = ACCEPT_DIR | DO_OPEN | NO_DOTS;
+
+	ret = 0;
+	r = 0;
+	have_one = 0;
+	initializeDirentry(&entry, mp->File);
+	while(!(ret & STOP_NOW) &&
+	      !got_signal &&
+	      (r=vfat_lookup(&entry, filename0, length,
+			     lookupflags | NO_MSG, 
+			     mp->shortname, mp->longname)) == 0 ){
+		if(checkForDot(lookupflags, entry.name))
+			/* while following the path, ignore the
+			 * special entries if they were not
+			 * explicitly given */
+			continue;
+		have_one = 1;
+		if(ptr) {
+			Stream_t *SubDir;
+			SubDir = mp->File = OpenFileByDirentry(&entry);
+			ret |= recurs_dos_loop(mp, ptr, filename1, lookupState);
+			FREE(&SubDir);
+		} else {
+			ret |= handle_leaf(&entry, mp, lookupState);
+			if(isUniqueTarget(mp->targetName))
+				return ret | STOP_NOW;
+		}
+		if(doing_mcwd)
+			break;
+	}
+	if (r == -2)
+		return ERROR_ONE;
+	if(got_signal)
+		return ret | ERROR_ONE;
+	if(doing_mcwd & !have_one)
+		return NO_CWD;
+	return ret;
+}
+
+static int common_dos_loop(MainParam_t *mp, const char *pathname,
+			   lookupState_t *lookupState, int open_mode)
+
+{
+	Stream_t *RootDir;
+	char *cwd;
+	char *drive;
+	char *rest;
+
+	int ret;
+	mp->loop = _dos_loop;
+	
+	drive='\0';
+	cwd = "";
+	if((rest = skip_drive(pathname)) > pathname) {
+		drive = get_drive(pathname, NULL);
+		if (strncmp(pathname, mp->mcwd, rest - pathname) == 0)
+			cwd = skip_drive(mp->mcwd);
+		pathname = rest;
+	} else {
+		drive = get_drive(mp->mcwd, NULL);
+		cwd = skip_drive(mp->mcwd);
+	}
+
+	if(*pathname=='/') /* absolute path name */
+		cwd = "";
+
+	RootDir = mp->File = open_root_dir(drive, open_mode);
+	if(!mp->File)
+		return ERROR_ONE;
+
+	ret = recurs_dos_loop(mp, cwd, pathname, lookupState);
+	if(ret & NO_CWD) {
+		/* no CWD */
+		*mp->mcwd = '\0';
+		unlink_mcwd();
+		ret = recurs_dos_loop(mp, "", pathname, lookupState);
+	}
+	FREE(&RootDir);
+	return ret;
+}
+
+static int dos_loop(MainParam_t *mp, const char *arg)
+{
+	return common_dos_loop(mp, arg, 0, mp->openflags);
+}
+
+
+static int dos_target_lookup(MainParam_t *mp, const char *arg)
+{
+	lookupState_t lookupState;
+	int ret;
+	int lookupflags;
+
+	lookupState.nbDirs = 0;
+	lookupState.Dir = 0;
+	lookupState.nbContainers = 0;
+	lookupState.container = 0;
+
+	lookupflags = mp->lookupflags;
+	mp->lookupflags = DO_OPEN | ACCEPT_DIR;
+	ret = common_dos_loop(mp, arg, &lookupState, O_RDWR);
+	mp->lookupflags = lookupflags;
+	if(ret & ERROR_ONE)
+		return ret;
+
+	if(lookupState.nbDirs) {
+		mp->targetName = 0;
+		mp->targetDir = lookupState.Dir;
+		FREE(&lookupState.container); /* container no longer needed */
+		return ret;
+	}
+
+	switch(lookupState.nbContainers) {
+		case 0:
+			/* no match */
+			fprintf(stderr,"%s: no match for target\n", arg);
+			return MISSED_ONE;
+		case 1:
+			mp->targetName = strdup(lookupState.filename);
+			mp->targetDir = lookupState.container;
+			return ret;
+		default:
+			/* too much */
+			fprintf(stderr, "Ambigous %s\n", arg);
+			return ERROR_ONE;			
+	}
+}
+
+int unix_target_lookup(MainParam_t *mp, const char *arg)
+{
+	char *ptr;
+	mp->unixTarget = strdup(arg);
+	/* try complete filename */
+	if(access(mp->unixTarget, F_OK) == 0)
+		return GOT_ONE;
+	ptr = strrchr(mp->unixTarget, '/');
+	if(!ptr) {
+		mp->targetName = mp->unixTarget;
+		mp->unixTarget = strdup(".");
+		return GOT_ONE;
+	} else {
+		*ptr = '\0';
+		mp->targetName = ptr+1;
+		return GOT_ONE;
+	}
+}
+
+int target_lookup(MainParam_t *mp, const char *arg)
+{
+	if((mp->lookupflags & NO_UNIX) || skip_drive(arg) > arg)
+		return dos_target_lookup(mp, arg);
+	else
+		return unix_target_lookup(mp, arg);
+}
+
+int main_loop(MainParam_t *mp, char **argv, int argc)
+{
+	int i;
+	int ret, Bret;
+	
+	Bret = 0;
+
+	if(argc != 1 && mp->targetName) {
+		fprintf(stderr,
+			"Several file names given, but last argument (%s) not a directory\n", mp->targetName);
+	}
+
+	for (i = 0; i < argc; i++) {
+		if ( got_signal )
+			break;
+		mp->originalArg = argv[i];
+		mp->basenameHasWildcard = strpbrk(_basename(mp->originalArg), 
+						  "*[?") != 0;
+		if (mp->unixcallback && skip_drive(argv[i]) == argv[i])
+			ret = unix_loop(0, mp, argv[i], 1);
+		else
+			ret = dos_loop(mp, argv[i]);
+		
+		if (! (ret & (GOT_ONE | ERROR_ONE)) ) {
+			/* one argument was unmatched */
+			fprintf(stderr, "%s: File \"%s\" not found\n",
+				progname, argv[i]);
+			ret |= ERROR_ONE;
+		}
+		Bret |= ret;
+		if(mp->fast_quit && (Bret & (MISSED_ONE | ERROR_ONE)))
+			break;
+	}
+	FREE(&mp->targetDir);
+	if(Bret & ERROR_ONE)
+		return 1;
+	if ((Bret & GOT_ONE) && ( Bret & MISSED_ONE))
+		return 2;
+	if (Bret & MISSED_ONE)
+		return 1;
+	return 0;
+}
+
+static int dispatchToFile(direntry_t *entry, MainParam_t *mp)
+{
+	if(entry)
+		return mp->callback(entry, mp);
+	else
+		return mp->unixcallback(mp);
+}
+
+
+void init_mp(MainParam_t *mp)
+{
+	fix_mcwd(mp->mcwd);
+	mp->openflags = 0;
+	mp->targetName = 0;
+	mp->targetDir = 0;
+	mp->unixTarget = 0;
+	mp->dirCallback = dispatchToFile;
+	mp->unixcallback = NULL;
+	mp->shortname = mp->longname = 0;
+	mp->File = 0;
+	mp->fast_quit = 0;
+}
+
+const char *mpGetBasename(MainParam_t *mp)
+{
+	if(mp->direntry)
+		return mp->direntry->name;
+	else
+		return _basename(mp->unixSourceName);
+}
+
+void mpPrintFilename(FILE *fp, MainParam_t *mp)
+{
+	if(mp->direntry)
+		fprintPwd(fp, mp->direntry, 0);
+	else
+		fprintf(fp,"%s",mp->originalArg);
+}
+
+const char *mpPickTargetName(MainParam_t *mp)
+{
+	/* picks the target name: either the one explicitly given by the
+	 * user, or the same as the source */
+	if(mp->targetName)
+		return mp->targetName;
+	else
+		return mpGetBasename(mp);
+}
+
+char *mpBuildUnixFilename(MainParam_t *mp)
+{
+	const char *target;
+	char *ret;
+
+	target = mpPickTargetName(mp);
+	ret = malloc(strlen(mp->unixTarget) + 2 + strlen(target));
+	if(!ret)
+		return 0;
+	strcpy(ret, mp->unixTarget);
+	if(*target) {
+#if 1 /* fix for 'mcopy -n x:file existingfile' -- H. Lermen 980816 */
+		if(!mp->targetName && !mp->targetDir) {
+			struct stat buf;
+			if (!stat(ret, &buf) && !S_ISDIR(buf.st_mode))
+				return ret;
+		}
+#endif
+		strcat(ret, "/");
+		strcat(ret, target);
+	}
+	return ret;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mainloop.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mainloop.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mainloop.h	(revision 9)
@@ -0,0 +1,79 @@
+#ifndef MTOOLS_MAINLOOP_H
+#define MTOOLS_MAINLOOP_H
+
+#ifndef OS_Minix
+#include <sys/param.h>
+#endif
+#include "vfat.h"
+#include "mtoolsDirent.h"
+
+typedef struct MainParam_t {
+	/* stuff needing to be initialised by the caller */
+	int (*loop)(Stream_t *Dir, struct MainParam_t *mp, 
+		    const char *filename);
+	int (*dirCallback)(direntry_t *, struct MainParam_t *);
+	int (*callback)(direntry_t *, struct MainParam_t *);
+	int (*unixcallback)(struct MainParam_t *mp);
+
+	void *arg; /* command-specific parameters 
+		    * to be passed to callback */
+
+       	int openflags; /* flags used to open disk */
+	int lookupflags; /* flags used to lookup up using vfat_lookup */
+	int fast_quit; /* for commands manipulating multiple files, quit
+			* as soon as even _one_ file has a problem */
+
+	char *shortname; /* where to put the short name of the matched file */
+	char *longname; /* where to put the long name of the matched file */
+
+	/* out parameters */
+	Stream_t *File;
+
+	direntry_t *direntry;  /* dir of this entry */
+	char *unixSourceName;  /* filename of the last opened Unix source 
+				* file (Unix equiv of Dos direntry) */
+
+	Stream_t *targetDir; /* directory where to place files */
+	char *unixTarget; /* directory on Unix where to put files */
+
+	const char *targetName; /* basename of target file, or NULL if same
+				 * basename as source should be conserved */
+
+	char *originalArg; /* original argument, complete with wildcards */
+	int basenameHasWildcard; /* true if there are wildcards in the
+				  * basename */
+
+
+	/* internal data */
+	char mcwd[MAX_PATH+4];
+
+	char *fileName; /* resolved Unix filename */
+} MainParam_t;
+
+void init_mp(MainParam_t *MainParam);
+int main_loop(MainParam_t *MainParam, char **argv, int argc);
+
+int target_lookup(MainParam_t *mp, const char *arg);
+
+Stream_t *open_root_dir(char *drivename, int flags);
+
+const char *mpGetBasename(MainParam_t *mp); /* statically allocated 
+					     * string */
+
+void mpPrintFilename(FILE *file, MainParam_t *mp);
+const char *mpPickTargetName(MainParam_t *mp); /* statically allocated string */
+
+char *mpBuildUnixFilename(MainParam_t *mp); /* dynamically allocated, must
+					     * be freed */
+
+int isSpecial(const char *name);
+
+#define MISSED_ONE 2  /* set if one cmd line argument didn't match any files */
+#define GOT_ONE 4     /* set if a match was found, used for exit status */
+#define NO_CWD 8     /* file not found while looking for current working 
+		      * directory */
+#define ERROR_ONE 16 /* flat out error, such as problems with target file, 
+			interrupt by user, etc. */
+#define STOP_NOW 32 /* stop as soon as possible, not necessarily an error */
+
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/match.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/match.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/match.c	(revision 9)
@@ -0,0 +1,142 @@
+/*
+ * Do shell-style pattern matching for '?', '\', '[..]', and '*' wildcards.
+ * Returns 1 if match, 0 if not.
+ */
+
+#include "sysincludes.h"
+#include "mtools.h"
+
+
+static int casecmp(char a,char b)
+{
+	return toupper(a) == toupper(b);
+}
+
+static int exactcmp(char a,char b)
+{
+	return a == b;
+}
+
+
+static int parse_range(const char **p, const char *s, char *out, 
+		       int (*compfn)(char a, char b))
+{
+	char table[256];
+	int reverse;
+	int i;
+	short first, last;
+
+	if (**p == '^') {
+		reverse = 1;
+		(*p)++;
+	} else
+		reverse=0;	
+	for(i=0; i<256; i++)
+		table[i]=0;
+	while(**p != ']') {
+		if(!**p)
+			return 0;
+		if((*p)[1] == '-') {
+			first = **p;
+			(*p)+=2;
+			if(**p == ']')
+				last = 256;
+			else
+				last = *((*p)++);				
+			for(i=first; i<last; i++)
+				table[i] = 1;
+		} else
+			table[(int) *((*p)++)] = 1;
+	}
+	if(out)
+		*out = *s;
+	if(table[(int) *s])
+		return 1 ^ reverse;
+	if(compfn == exactcmp)
+		return reverse;
+	if(table[tolower(*s)]) {
+		if(out)
+			*out = tolower(*s);
+		return 1 ^ reverse;
+	}
+	if(table[toupper(*s)]) {
+		if(out)
+			*out = toupper(*s);
+		return 1 ^ reverse;
+	}
+	return reverse;
+}
+
+
+static int _match(const char *s, const char *p, char *out, int Case,
+		  int length,
+		  int (*compfn) (char a, char b))
+{
+	for (; *p != '\0' && length; ) {
+		switch (*p) {
+			case '?':	/* match any one character */
+				if (*s == '\0')
+					return(0);
+				if(out)
+					*(out++) = *s;
+				break;
+			case '*':	/* match everything */
+				while (*p == '*' && length) {
+					p++;
+					length--;
+				}
+
+					/* search for next char in pattern */
+				while(*s) {
+					if(_match(s, p, out, Case, length, 
+						  compfn))
+						return 1;
+					if(out)
+						*out++ = *s;
+					s++;
+				}
+				continue;
+			case '[':	 /* match range of characters */
+				p++;
+				length--;
+				if(!parse_range(&p, s, out++, compfn))
+					return 0;
+				break;
+			case '\\':	/* Literal match with next character */
+				p++;
+				length--;
+				/* fall thru */
+			default:
+				if (!compfn(*s,*p))
+					return(0);
+				if(out)
+					*(out++) = *p;
+				break;
+		}
+		p++;
+		length--;
+		s++;
+	}
+	if(out)
+		*out = '\0';
+
+					/* string ended prematurely ? */
+	if (*s != '\0')
+		return(0);
+	else
+		return(1);
+}
+
+
+int match(const char *s, const char *p, char *out, int Case, int length)
+{
+	int (*compfn)(char a, char b);
+
+	if(Case)
+		compfn = casecmp;
+	else
+		/*compfn = exactcmp;*/
+		compfn = casecmp;
+	return _match(s, p, out, Case, length, compfn);
+}
+
Index: /trunk/minix/commands/i386/mtools-3.9.7/mattrib.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mattrib.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mattrib.c	(revision 9)
@@ -0,0 +1,233 @@
+/*
+ * mattrib.c
+ * Change MSDOS file attribute flags
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "mainloop.h"
+
+typedef struct Arg_t {
+	char add;
+	unsigned char remove;
+	struct MainParam_t mp;
+	int recursive;
+	int doPrintName;
+} Arg_t;
+
+int concise;
+
+static int attrib_file(direntry_t *entry, MainParam_t *mp)
+{
+	Arg_t *arg=(Arg_t *) mp->arg;
+
+	if(entry->entry != -3) {
+		/* if not root directory, change it */
+		entry->dir.attr = (entry->dir.attr & arg->remove) | arg->add;
+		dir_write(entry);
+	}
+	return GOT_ONE;
+}
+
+static int replay_attrib(direntry_t *entry, MainParam_t *mp)
+{
+	if ( (IS_ARCHIVE(entry) && IS_DIR(entry)) ||
+		 (!IS_ARCHIVE(entry) && !IS_DIR(entry)) ||
+		 IS_SYSTEM(entry) || IS_HIDDEN(entry)) {
+
+		printf("mattrib ");
+
+		if (IS_ARCHIVE(entry) && IS_DIR(entry)) {
+			printf("+a ");
+		}
+
+		if (!IS_ARCHIVE(entry) && !IS_DIR(entry)) {
+			printf("-a ");
+		}
+
+		if (IS_SYSTEM(entry)) {
+			printf("+s ");
+		}
+
+		if (IS_HIDDEN(entry)) {
+			printf("+h ");
+		}
+
+		fprintPwd(stdout, entry, 1);
+		printf("\n");
+	}
+	return GOT_ONE;
+}
+
+
+
+static int view_attrib(direntry_t *entry, MainParam_t *mp)
+{
+	printf("  ");
+	if(IS_ARCHIVE(entry))
+		putchar('A');
+	else
+		putchar(' ');
+	fputs("  ",stdout);
+	if(IS_SYSTEM(entry))
+		putchar('S');
+	else
+		putchar(' ');
+	if(IS_HIDDEN(entry))
+		putchar('H');
+	else
+		putchar(' ');
+	if(IS_READONLY(entry))
+		putchar('R');
+	else
+		putchar(' ');
+	printf("     ");
+	fprintPwd(stdout, entry, 0);
+	printf("\n");
+	return GOT_ONE;
+}
+
+
+static int concise_view_attrib(direntry_t *entry, MainParam_t *mp)
+{
+	Arg_t *arg=(Arg_t *) mp->arg;
+
+	if(IS_ARCHIVE(entry))
+		putchar('A');
+	if(IS_DIR(entry))
+		putchar('D');	
+	if(IS_SYSTEM(entry))
+		putchar('S');
+	if(IS_HIDDEN(entry))
+		putchar('H');
+	if(IS_READONLY(entry))
+		putchar('R');
+	if(arg->doPrintName) {
+		putchar(' ');
+		fprintPwd(stdout, entry, 0);
+	}
+	putchar('\n');
+	return GOT_ONE;
+}
+
+static int recursive_attrib(direntry_t *entry, MainParam_t *mp)
+{
+	mp->callback(entry, mp);
+	return mp->loop(mp->File, mp, "*");
+}
+
+
+static void usage(void) NORETURN;
+static void usage(void)
+{
+	fprintf(stderr, "Mtools version %s, dated %s\n", 
+		mversion, mdate);
+	fprintf(stderr, 
+		"Usage: %s [-p/X] [-a|+a] [-h|+h] [-r|+r] [-s|+s] msdosfile [msdosfiles...]\n"
+		"\t-p Replay how mattrib would set up attributes\n"
+		"\t-/ Recursive\n"
+		"\t-X Concise\n",
+		progname);
+	exit(1);
+}
+
+static int letterToCode(int letter)
+{
+	switch (toupper(letter)) {
+		case 'A':
+			return ATTR_ARCHIVE;
+		case 'H':
+			return ATTR_HIDDEN;
+		case 'R':
+			return ATTR_READONLY;
+		case 'S':
+			return ATTR_SYSTEM;
+		default:
+			usage();
+	}
+}
+
+
+void mattrib(int argc, char **argv, int type)
+{
+	Arg_t arg;
+	int view;
+	int c;
+	int concise;
+	int replay;
+	char *ptr;
+
+	arg.add = 0;
+	arg.remove = 0xff;
+	arg.recursive = 0;
+	arg.doPrintName = 1;
+	view = 0;
+	concise = 0;
+	replay = 0;
+	
+	while ((c = getopt(argc, argv, "/ahrsAHRSXp")) != EOF) {
+		switch (c) {
+			default:
+				arg.remove &= ~letterToCode(c);
+				break;
+			case 'p':
+				replay = 1;
+				break;
+			case '/':
+				arg.recursive = 1;
+				break;
+			case 'X':
+				concise = 1;
+				break;
+			case '?':
+				usage();
+		}
+	}
+
+	for(;optind < argc;optind++) {
+		switch(argv[optind][0]) {
+			case '+':
+				for(ptr = argv[optind] + 1; *ptr; ptr++)
+					arg.add |= letterToCode(*ptr);
+				continue;
+			case '-':
+				for(ptr = argv[optind] + 1; *ptr; ptr++)
+					arg.remove &= ~letterToCode(*ptr);
+				continue;
+		}
+		break;
+	}
+
+	if(arg.remove == 0xff && !arg.add)
+		view = 1;
+
+	if (optind >= argc)
+		usage();
+
+	init_mp(&arg.mp);
+	if(view){
+		if(concise) {
+			arg.mp.callback = concise_view_attrib;
+			arg.doPrintName = (argc - optind > 1 ||
+					   arg.recursive ||
+					   strpbrk(argv[optind], "*[?") != 0);
+		} else if (replay) {
+			arg.mp.callback = replay_attrib;
+		} else
+			arg.mp.callback = view_attrib;
+		arg.mp.openflags = O_RDONLY;
+	} else {
+		arg.mp.callback = attrib_file;
+		arg.mp.openflags = O_RDWR;
+	}
+
+	if(arg.recursive)
+		arg.mp.dirCallback = recursive_attrib;
+
+	arg.mp.arg = (void *) &arg;
+	arg.mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR;
+	if(arg.recursive)
+		arg.mp.lookupflags |= DO_OPEN_DIRS | NO_DOTS;
+	exit(main_loop(&arg.mp, argv + optind, argc - optind));
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mbadblocks.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mbadblocks.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mbadblocks.c	(revision 9)
@@ -0,0 +1,77 @@
+/*
+ * mbadblocks.c
+ * Mark bad blocks on disk
+ *
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "mainloop.h"
+#include "fsP.h"
+
+void mbadblocks(int argc, char **argv, int type)
+{
+	int i;
+	char *in_buf;
+	int in_len;
+	off_t start;
+	struct MainParam_t mp;
+	Fs_t *Fs;
+	Stream_t *Dir;
+	int ret;
+
+	if (argc != 2 || skip_drive(argv[1]) == argv[1]) {
+		fprintf(stderr, "Mtools version %s, dated %s\n", 
+			mversion, mdate);
+		fprintf(stderr, "Usage: %s drive:\n", argv[0]);
+		exit(1);
+	}
+
+	init_mp(&mp);
+
+	Dir = open_root_dir(get_drive(argv[1], NULL), O_RDWR);
+	if (!Dir) {
+		fprintf(stderr,"%s: Cannot initialize drive\n", argv[0]);
+		exit(1);
+	}
+
+	Fs = (Fs_t *)GetFs(Dir);
+	in_len = Fs->cluster_size * Fs->sector_size;
+	in_buf = malloc(in_len);
+	if(!in_buf) {
+		FREE(&Dir);
+		printOom();
+		exit(1);
+	}
+	for(i=0; i < Fs->clus_start; i++ ){
+		ret = READS(Fs->Next, 
+					in_buf, sectorsToBytes((Stream_t*)Fs, i), Fs->sector_size);
+		if( ret < 0 ){
+			perror("early error");
+			exit(1);
+		}
+		if(ret < Fs->sector_size){
+			fprintf(stderr,"end of file in file_read\n");
+			exit(1);
+		}
+	}
+		
+	in_len = Fs->cluster_size * Fs->sector_size;
+	for(i=2; i< Fs->num_clus + 2; i++){
+		if(got_signal)
+			break;
+		if(Fs->fat_decode((Fs_t*)Fs,i))
+			continue;
+		start = (i - 2) * Fs->cluster_size + Fs->clus_start;
+		ret = force_read(Fs->Next, in_buf, 
+						 sectorsToBytes((Stream_t*)Fs, start), in_len);
+		if(ret < in_len ){
+			printf("Bad cluster %d found\n", i);
+			fatEncode((Fs_t*)Fs, i, 0xfff7);
+			continue;
+		}
+	}
+	FREE(&Dir);
+	exit(0);
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mcat.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mcat.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mcat.c	(revision 9)
@@ -0,0 +1,129 @@
+/*
+ * mcat.c
+ * Same thing as cat /dev/fd0 or cat file >/dev/fd0
+ * Something, that isn't possible with floppyd anymore.
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "mainloop.h"
+#include "fsP.h"
+#include "xdf_io.h"
+#include "floppyd_io.h"
+#include "plain_io.h"
+
+void usage(void) 
+{
+	fprintf(stderr, "Mtools version %s, dated %s\n", 
+		mversion, mdate);
+	fprintf(stderr, "Usage: mcat [-w] device\n");
+	fprintf(stderr, "       -w write on device else read\n");
+	exit(1);
+}
+
+#define BUF_SIZE 16000
+
+void mcat(int argc, char **argv, int type)
+{
+	struct device *dev;
+	struct device out_dev;
+	char *drive, name[EXPAND_BUF];
+        char errmsg[200];
+        Stream_t *Stream;
+	char buf[BUF_SIZE];
+
+	mt_off_t address = 0;
+
+	char mode = O_RDONLY;
+	int optindex = 1;
+	size_t len;
+
+	noPrivileges = 1;
+
+	if (argc < 2) {
+		usage();
+	}
+
+	if (argv[1][0] == '-') {
+		if (argv[1][1] != 'w') {
+			usage();
+		}
+		mode = O_WRONLY;
+		optindex++;
+	}
+
+	if (argc - optindex < 1)
+		usage();
+
+
+	if (skip_drive(argv[optindex]) == argv[optindex])
+		usage();
+
+        drive = get_drive(argv[optindex], NULL);
+
+        /* check out a drive whose letter and parameters match */       
+        sprintf(errmsg, "Drive '%s:' not supported", drive);    
+        Stream = NULL;
+        for (dev=devices; dev->name; dev++) {
+                FREE(&Stream);
+                if (strcmp(dev->drive, drive) != 0)
+                        continue;
+                out_dev = *dev;
+                expand(dev->name,name);
+#ifdef USING_NEW_VOLD
+                strcpy(name, getVoldName(dev, name));
+#endif
+
+                Stream = 0;
+#ifdef USE_XDF
+                Stream = XdfOpen(&out_dev, name, mode, errmsg, 0);
+				if(Stream)
+                        out_dev.use_2m = 0x7f;
+
+#endif
+
+#ifdef USE_FLOPPYD
+                if(!Stream)
+                        Stream = FloppydOpen(&out_dev, dev, name, 
+					     mode, errmsg, 0, 1);
+#endif
+
+
+                if (!Stream)
+                        Stream = SimpleFileOpen(&out_dev, dev, name, mode,
+						errmsg, 0, 1, 0);
+
+                if( !Stream)
+                        continue;
+                break;
+        }
+
+        /* print error msg if needed */ 
+        if ( dev->drive == 0 ){
+                FREE(&Stream);
+                fprintf(stderr,"%s\n",errmsg);
+                exit(1);
+        }
+
+	if (mode == O_WRONLY) {
+		while ((len = fread(buf, 1, BUF_SIZE, stdin)) 
+		       == BUF_SIZE) {
+			WRITES(Stream, buf, address, BUF_SIZE);
+			address += BUF_SIZE;
+		}
+		if (len)
+			WRITES(Stream, buf, address, len);
+	} else {
+		while ((len = READS(Stream, buf, address, BUF_SIZE)) 
+		       == BUF_SIZE) {
+			fwrite(buf, 1, BUF_SIZE, stdout);
+			address += BUF_SIZE;
+		}
+		if (len)
+			fwrite(buf, 1, len, stdout);
+	}
+
+	FREE(&Stream);
+	exit(0);
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mcd.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mcd.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mcd.c	(revision 9)
@@ -0,0 +1,46 @@
+/*
+ * mcd.c: Change MSDOS directories
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mainloop.h"
+#include "mtools.h"
+
+
+static int mcd_callback(direntry_t *entry, MainParam_t *mp)
+{
+	FILE *fp;
+
+	if (!(fp = open_mcwd("w"))){
+		fprintf(stderr,"mcd: Can't open mcwd .file for writing\n");
+		return ERROR_ONE;
+	}
+	
+	fprintPwd(fp, entry,0);
+	fprintf(fp, "\n");
+	fclose(fp);
+	return GOT_ONE | STOP_NOW;
+}
+
+
+void mcd(int argc, char **argv, int type)
+{
+	struct MainParam_t mp;
+
+	if (argc > 2) {
+		fprintf(stderr, "Mtools version %s, dated %s\n", 
+			mversion, mdate);
+		fprintf(stderr, "Usage: %s: msdosdirectory\n", argv[0]);
+		exit(1);
+	}
+
+	init_mp(&mp);
+	mp.lookupflags = ACCEPT_DIR | NO_DOTS;
+	mp.dirCallback = mcd_callback;
+	if (argc == 1) {
+		printf("%s\n", mp.mcwd);
+		exit(0);
+	} else 
+		exit(main_loop(&mp, argv + 1, 1));
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mcopy.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mcopy.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mcopy.c	(revision 9)
@@ -0,0 +1,584 @@
+/*
+ * mcopy.c
+ * Copy an MSDOS files to and from Unix
+ *
+ */
+
+
+#define LOWERCASE
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "vfat.h"
+#include "mainloop.h"
+#include "plain_io.h"
+#include "nameclash.h"
+#include "file.h"
+#include "fs.h"
+
+
+/*
+ * Preserve the file modification times after the fclose()
+ */
+
+static void set_mtime(const char *target, time_t mtime)
+{
+	if (target && strcmp(target, "-") && mtime != 0L) {
+#ifdef HAVE_UTIMES
+		struct timeval tv[2];	
+		tv[0].tv_sec = mtime;
+		tv[0].tv_usec = 0;
+		tv[1].tv_sec = mtime;
+		tv[1].tv_usec = 0;
+		utimes((char *)target, tv);
+#else
+#ifdef HAVE_UTIME
+		struct utimbuf utbuf;
+
+		utbuf.actime = mtime;
+		utbuf.modtime = mtime;
+		utime(target, &utbuf);
+#endif
+#endif
+	}
+	return;
+}
+
+typedef struct Arg_t {
+	int recursive;
+	int preserveAttributes;
+	int preserveTime;
+	unsigned char attr;
+	char *path;
+	int textmode;
+	int needfilter;
+	int nowarn;
+	int verbose;
+	int type;
+	MainParam_t mp;
+	ClashHandling_t ch;
+} Arg_t;
+
+/* Write the Unix file */
+static int unix_write(direntry_t *entry, MainParam_t *mp, int needfilter)
+{
+	Arg_t *arg=(Arg_t *) mp->arg;
+	time_t mtime;
+	Stream_t *File=mp->File;
+	Stream_t *Target, *Source;
+	struct stat stbuf;
+	int ret;
+	char errmsg[80];
+	char *unixFile;
+
+	File->Class->get_data(File, &mtime, 0, 0, 0);
+
+	if (!arg->preserveTime)
+		mtime = 0L;
+
+	if(arg->type)
+		unixFile = "-";
+	else
+		unixFile = mpBuildUnixFilename(mp);
+	if(!unixFile) {
+		printOom();
+		return ERROR_ONE;
+	}
+
+	/* if we are creating a file, check whether it already exists */
+	if(!arg->type) {
+		if (!arg->nowarn && &arg->type && !access(unixFile, 0)){
+			if( ask_confirmation("File \"%s\" exists, overwrite (y/n) ? ",
+					     unixFile,0)) {
+				free(unixFile);
+				return ERROR_ONE;
+			}
+			
+			/* sanity checking */
+			if (!stat(unixFile, &stbuf) && !S_ISREG(stbuf.st_mode)) {
+				fprintf(stderr,"\"%s\" is not a regular file\n",
+					unixFile);
+				
+				free(unixFile);
+				return ERROR_ONE;
+			}
+		}
+	}
+
+	if(!arg->type && arg->verbose) {
+		fprintf(stderr,"Copying ");
+		mpPrintFilename(stderr,mp);
+		fprintf(stderr,"\n");
+	}
+	
+	if(got_signal) {
+		free(unixFile);
+		return ERROR_ONE;
+	}
+
+	if ((Target = SimpleFileOpen(0, 0, unixFile,
+				     O_WRONLY | O_CREAT | O_TRUNC,
+				     errmsg, 0, 0, 0))) {
+		ret = 0;
+		if(needfilter && arg->textmode){
+			Source = open_filter(COPY(File));
+			if (!Source)
+				ret = -1;
+		} else
+			Source = COPY(File);
+
+		if (ret == 0 )
+			ret = copyfile(Source, Target);
+		FREE(&Source);
+		FREE(&Target);
+		if(ret <= -1){
+			if(!arg->type) {
+				unlink(unixFile);
+				free(unixFile);
+			}
+			return ERROR_ONE;
+		}
+		if(!arg->type) {
+			set_mtime(unixFile, mtime);
+			free(unixFile);
+		}
+		return GOT_ONE;
+	} else {
+		fprintf(stderr,"%s\n", errmsg);
+		if(!arg->type)
+			free(unixFile);
+		return ERROR_ONE;
+	}
+}
+
+static int makeUnixDir(char *filename)
+{
+	if(!mkdir(filename, 0777))
+		return 0;
+	if(errno == EEXIST) {
+		struct stat buf;
+		if(stat(filename, &buf) < 0)
+			return -1;
+		if(S_ISDIR(buf.st_mode))
+			return 0;
+		errno = ENOTDIR;
+	}
+	return -1;
+}
+
+/* Copy a directory to Unix */
+static int unix_copydir(direntry_t *entry, MainParam_t *mp)
+{
+	Arg_t *arg=(Arg_t *) mp->arg;
+	time_t mtime;
+	Stream_t *File=mp->File;
+	int ret;
+	char *unixFile;
+
+	if (!arg->recursive && mp->basenameHasWildcard)
+		return 0;
+
+	File->Class->get_data(File, &mtime, 0, 0, 0);	
+	if (!arg->preserveTime)
+		mtime = 0L;
+	if(!arg->type && arg->verbose) {
+		fprintf(stderr,"Copying ");
+		fprintPwd(stderr, entry,0);
+		fprintf(stderr, "\n");
+	}
+	if(got_signal)
+		return ERROR_ONE;
+	unixFile = mpBuildUnixFilename(mp);
+	if(!unixFile) {
+		printOom();
+		return ERROR_ONE;
+	}
+	if(arg->type || !*mpPickTargetName(mp) || !makeUnixDir(unixFile)) {
+		Arg_t newArg;
+
+		newArg = *arg;
+		newArg.mp.arg = (void *) &newArg;
+		newArg.mp.unixTarget = unixFile;
+		newArg.mp.targetName = 0;
+		newArg.mp.basenameHasWildcard = 1;
+
+		ret = mp->loop(File, &newArg.mp, "*");
+		set_mtime(unixFile, mtime);
+		free(unixFile);
+		return ret | GOT_ONE;		
+	} else {
+		perror("mkdir");
+		fprintf(stderr, 
+			"Failure to make directory %s\n", 
+			unixFile);
+		free(unixFile);
+		return ERROR_ONE;
+	}
+}
+
+static  int dos_to_unix(direntry_t *entry, MainParam_t *mp)
+{
+	return unix_write(entry, mp, 1);
+}
+
+
+static  int unix_to_unix(MainParam_t *mp)
+{
+	return unix_write(0, mp, 0);
+}
+
+
+static int directory_dos_to_unix(direntry_t *entry, MainParam_t *mp)
+{
+	return unix_copydir(entry, mp);
+}
+
+/*
+ * Open the named file for read, create the cluster chain, return the
+ * directory structure or NULL on error.
+ */
+static int writeit(char *dosname,
+		   char *longname,
+		   void *arg0,
+		   direntry_t *entry)
+{
+	Stream_t *Target;
+	time_t now;
+	int type, fat, ret;
+	time_t date;
+	mt_size_t filesize, newsize;
+	Arg_t *arg = (Arg_t *) arg0;
+
+
+
+	if (arg->mp.File->Class->get_data(arg->mp.File,
+									  & date, &filesize, &type, 0) < 0 ){
+		fprintf(stderr, "Can't stat source file\n");
+		return -1;
+	}
+
+	if (type){
+		if (arg->verbose)
+			fprintf(stderr, "\"%s\" is a directory\n", longname);
+		return -1;
+	}
+
+	/*if (!arg->single || arg->recursive)*/
+	if(arg->verbose)
+		fprintf(stderr,"Copying %s\n", longname);
+	if(got_signal)
+		return -1;
+
+	/* will it fit? */
+	if (!getfreeMinBytes(arg->mp.targetDir, filesize))
+		return -1;
+	
+	/* preserve mod time? */
+	if (arg->preserveTime)
+		now = date;
+	else
+		getTimeNow(&now);
+
+	mk_entry(dosname, arg->attr, 1, 0, now, &entry->dir);
+
+	Target = OpenFileByDirentry(entry);
+	if(!Target){
+		fprintf(stderr,"Could not open Target\n");
+		exit(1);
+	}
+	if (arg->needfilter & arg->textmode)
+		Target = open_filter(Target);
+
+
+
+	ret = copyfile(arg->mp.File, Target);
+	GET_DATA(Target, 0, &newsize, 0, &fat);
+	FREE(&Target);
+	if (arg->needfilter & arg->textmode)
+	    newsize++; /* ugly hack: we gathered the size before the Ctrl-Z
+			* was written.  Increment it manually */
+	if(ret < 0 ){
+		fat_free(arg->mp.targetDir, fat);
+		return -1;
+	} else {
+		mk_entry(dosname, arg->attr, fat, truncBytes32(newsize),
+				 now, &entry->dir);
+		return 0;
+	}
+}
+
+
+
+static int dos_write(direntry_t *entry, MainParam_t *mp, int needfilter)
+/* write a messy dos file to another messy dos file */
+{
+	int result;
+	Arg_t * arg = (Arg_t *) (mp->arg);
+	const char *targetName = mpPickTargetName(mp);
+
+	if(entry && arg->preserveAttributes)
+		arg->attr = entry->dir.attr;
+	else
+		arg->attr = ATTR_ARCHIVE;
+
+	arg->needfilter = needfilter;
+	if (entry && mp->targetDir == entry->Dir){
+		arg->ch.ignore_entry = -1;
+		arg->ch.source = entry->entry;
+	} else {
+		arg->ch.ignore_entry = -1;
+		arg->ch.source = -2;
+	}
+	result = mwrite_one(mp->targetDir, targetName, 0,
+			    writeit, (void *)arg, &arg->ch);
+	if(result == 1)
+		return GOT_ONE;
+	else
+		return ERROR_ONE;
+}
+
+static Stream_t *subDir(Stream_t *parent, const char *filename)
+{
+	direntry_t entry;		
+	initializeDirentry(&entry, parent);
+
+	switch(vfat_lookup(&entry, filename, -1, ACCEPT_DIR, 0, 0)) {
+	    case 0:
+		return OpenFileByDirentry(&entry);
+	    case -1:
+		return NULL;
+	    default: /* IO Error */
+		return NULL;
+	}
+}
+
+static int dos_copydir(direntry_t *entry, MainParam_t *mp)
+/* copyes a directory to Dos */
+{
+	Arg_t * arg = (Arg_t *) (mp->arg);
+	Arg_t newArg;
+	time_t now;
+	time_t date;
+	int ret;
+	const char *targetName = mpPickTargetName(mp);
+
+	if (!arg->recursive && mp->basenameHasWildcard)
+		return 0;
+
+	if(entry && isSubdirOf(mp->targetDir, mp->File)) {
+		fprintf(stderr, "Cannot recursively copy directory ");
+		fprintPwd(stderr, entry,0);
+		fprintf(stderr, " into one of its own subdirectories ");
+		fprintPwd(stderr, getDirentry(mp->targetDir),0);
+		fprintf(stderr, "\n");
+		return ERROR_ONE;
+	}
+
+	if (arg->mp.File->Class->get_data(arg->mp.File,
+					  & date, 0, 0, 0) < 0 ){
+		fprintf(stderr, "Can't stat source file\n");
+		return ERROR_ONE;
+	}
+
+	if(!arg->type && arg->verbose)
+		fprintf(stderr,"Copying %s\n", mpGetBasename(mp));
+
+	if(entry && arg->preserveAttributes)
+		arg->attr = entry->dir.attr;
+	else
+		arg->attr = 0;
+
+	if (entry && (mp->targetDir == entry->Dir)){
+		arg->ch.ignore_entry = -1;
+		arg->ch.source = entry->entry;
+	} else {
+		arg->ch.ignore_entry = -1;
+		arg->ch.source = -2;
+	}
+
+	/* preserve mod time? */
+	if (arg->preserveTime)
+		now = date;
+	else
+		getTimeNow(&now);
+
+	newArg = *arg;
+	newArg.mp.arg = &newArg;
+	newArg.mp.targetName = 0;
+	newArg.mp.basenameHasWildcard = 1;
+	if(*targetName) {
+		/* maybe the directory already exist. Use it */
+		newArg.mp.targetDir = subDir(mp->targetDir, targetName);
+		if(!newArg.mp.targetDir)
+			newArg.mp.targetDir = createDir(mp->targetDir, 
+							targetName,
+							&arg->ch, arg->attr, 
+							now);
+	} else
+		newArg.mp.targetDir = mp->targetDir;
+
+	if(!newArg.mp.targetDir)
+		return ERROR_ONE;
+
+	ret = mp->loop(mp->File, &newArg.mp, "*");
+	if(*targetName)
+		FREE(&newArg.mp.targetDir);
+	return ret | GOT_ONE;
+}
+
+
+static int dos_to_dos(direntry_t *entry, MainParam_t *mp)
+{
+	return dos_write(entry, mp, 0);
+}
+
+static int unix_to_dos(MainParam_t *mp)
+{
+	return dos_write(0, mp, 1);
+}
+
+
+static void usage(void)
+{
+	fprintf(stderr,
+		"Mtools version %s, dated %s\n", mversion, mdate);
+	fprintf(stderr,
+		"Usage: %s [-/spabtnmvQB] [-D clash_option] sourcefile targetfile\n", progname);
+	fprintf(stderr,
+		"       %s [-/spabtnmvQB] [-D clash_option] sourcefile [sourcefiles...] targetdirectory\n", 
+		progname);
+	fprintf(stderr,
+		"\t-/ -s Recursive\n"
+		"\t-p Preserve attributes\n"
+		"\t-a -t Textmode\n"
+		"\t-n Overwrite UNIX files without confirmation\n"
+		"\t-m Preserve file time (default under Minix)\n"
+		"\t-v Verbose\n"
+		"\t-Q Quit on the first error\n"
+		"\t-b -B Batch mode (faster, but less crash resistent)\n"
+		"\t-o Overwrite DOS files without confirmation\n");
+	exit(1);
+}
+
+void mcopy(int argc, char **argv, int mtype)
+{
+	Arg_t arg;
+	int c, ret, fastquit;
+	int todir;
+	
+
+	/* get command line options */
+
+	init_clash_handling(& arg.ch);
+
+	/* get command line options */
+	todir = 0;
+	arg.recursive = 0;
+#ifdef OS_Minix
+	arg.preserveTime = 1;	/* Copy file time as DOS does. */
+#else
+	arg.preserveTime = 0;
+#endif
+	arg.preserveAttributes = 0;
+	arg.nowarn = 0;
+	arg.textmode = 0;
+	arg.verbose = 0;
+	arg.type = mtype;
+	fastquit = 0;
+	while ((c = getopt(argc, argv, "abB/sptnmvQD:o")) != EOF) {
+		switch (c) {
+			case 's':
+			case '/':
+				arg.recursive = 1;
+				break;
+			case 'p':
+				arg.preserveAttributes = 1;
+				break;
+			case 'a':
+			case 't':
+				arg.textmode = 1;
+				break;
+			case 'n':
+				arg.nowarn = 1;
+				break;
+			case 'm':
+				arg.preserveTime = 1;
+				break;
+			case 'v':
+				arg.verbose = 1;
+				break;
+			case 'Q':
+				fastquit = 1;
+				break;
+			case 'B':
+			case 'b':
+				batchmode = 1;
+				break;
+			case 'o':
+				handle_clash_options(&arg.ch, c);
+				break;
+			case 'D':
+				if(handle_clash_options(&arg.ch, *optarg))
+					usage();
+				break;
+			case '?':
+				usage();
+			default:
+				break;
+		}
+	}
+
+	if (argc - optind < 1)
+		usage();
+
+	init_mp(&arg.mp);
+	arg.mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR | DO_OPEN | NO_DOTS;
+	arg.mp.fast_quit = fastquit;
+	arg.mp.arg = (void *) &arg;
+	arg.mp.openflags = O_RDONLY;
+
+	/* last parameter is "-", use mtype mode */
+	if(!mtype && !strcmp(argv[argc-1], "-")) {
+		arg.type = mtype = 1;
+		argc--;
+	}
+
+	if(mtype){
+		/* Mtype = copying to stdout */
+		arg.mp.targetName = strdup("-");
+		arg.mp.unixTarget = strdup("");
+		arg.mp.callback = dos_to_unix;
+		arg.mp.dirCallback = unix_copydir;
+		arg.mp.unixcallback = unix_to_unix;		
+	} else {
+		char *target;
+		if (argc - optind == 1) {
+			/* copying to the current directory */
+			target = ".";
+		} else {
+			/* target is the last item mentioned */
+			argc--;
+			target = argv[argc];
+		}
+
+		ret = target_lookup(&arg.mp, target);
+		if(!arg.mp.targetDir && !arg.mp.unixTarget) {
+			fprintf(stderr,"Bad target %s\n", target);
+			exit(1);
+		}
+
+		/* callback functions */
+		if(arg.mp.unixTarget) {
+			arg.mp.callback = dos_to_unix;
+			arg.mp.dirCallback = directory_dos_to_unix;
+			arg.mp.unixcallback = unix_to_unix;
+		} else {
+			arg.mp.dirCallback = dos_copydir;
+			arg.mp.callback = dos_to_dos;
+			arg.mp.unixcallback = unix_to_dos;
+		}
+	}
+
+	exit(main_loop(&arg.mp, argv + optind, argc - optind));
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mdel.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mdel.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mdel.c	(revision 9)
@@ -0,0 +1,173 @@
+/*
+ * mdel.c
+ * Delete an MSDOS file
+ *
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "stream.h"
+#include "mainloop.h"
+#include "fs.h"
+#include "file.h"
+
+typedef struct Arg_t {
+	int deltype;
+	int verbose;
+} Arg_t;
+
+static int del_entry(direntry_t *entry, MainParam_t *mp)
+{
+	Arg_t *arg=(Arg_t *) mp->arg;
+	direntry_t longNameEntry;
+	int i;
+
+	if(got_signal)
+		return ERROR_ONE;
+
+	if(entry->entry == -3) {
+		fprintf(stderr, "Cannot remove root directory\n");
+		return ERROR_ONE;
+	}
+
+	if (arg->verbose) {
+		fprintf(stderr,"Removing ");
+		fprintPwd(stdout, entry,0);
+		putchar('\n');
+	}
+
+	if ((entry->dir.attr & (ATTR_READONLY | ATTR_SYSTEM)) &&
+	    (ask_confirmation("%s: \"%s\" is read only, erase anyway (y/n) ? ",
+			      progname, entry->name)))
+		return ERROR_ONE;
+	if (fatFreeWithDirentry(entry)) 
+		return ERROR_ONE;
+
+	initializeDirentry(&longNameEntry, entry->Dir);
+	for(i=entry->beginSlot; i< entry->endSlot; i++) {
+	    int error;
+	    longNameEntry.entry=i;
+	    dir_read(&longNameEntry, &error);
+	    if(error)
+		break;
+	    longNameEntry.dir.name[0] = (char) DELMARK;
+	    dir_write(&longNameEntry);
+	}
+
+	entry->dir.name[0] = (char) DELMARK;
+	dir_write(entry);
+	return GOT_ONE;
+}
+
+static int del_file(direntry_t *entry, MainParam_t *mp)
+{
+	char shortname[13];
+	direntry_t subEntry;
+	Stream_t *SubDir;
+	Arg_t *arg = (Arg_t *) mp->arg;
+	MainParam_t sonmp;
+	int ret;
+	int r;
+
+	sonmp = *mp;
+	sonmp.arg = mp->arg;
+
+	r = 0;
+	if (IS_DIR(entry)){
+		/* a directory */
+		SubDir = OpenFileByDirentry(entry);
+		initializeDirentry(&subEntry, SubDir);
+		ret = 0;
+		while((r=vfat_lookup(&subEntry, "*", 1,
+				     ACCEPT_DIR | ACCEPT_PLAIN,
+				     shortname, NULL)) == 0 ){
+			if(shortname[0] != DELMARK &&
+			   shortname[0] &&
+			   shortname[0] != '.' ){
+				if(arg->deltype != 2){
+					fprintf(stderr,
+						"Directory ");
+					fprintPwd(stderr, entry,0);
+					fprintf(stderr," non empty\n");
+					ret = ERROR_ONE;
+					break;
+				}
+				if(got_signal) {
+					ret = ERROR_ONE;
+					break;
+				}
+				ret = del_file(&subEntry, &sonmp);
+				if( ret & ERROR_ONE)
+					break;
+				ret = 0;
+			}
+		}
+		FREE(&SubDir);
+		if (r == -2)
+			return ERROR_ONE;
+		if(ret)
+			return ret;
+	}
+	return del_entry(entry, mp);
+}
+
+
+static void usage(void)
+{
+	fprintf(stderr, 
+		"Mtools version %s, dated %s\n", mversion, mdate);
+	fprintf(stderr, 
+		"Usage: %s [-v] msdosfile [msdosfiles...]\n"
+		"\t-v Verbose\n",
+		progname);
+	exit(1);
+}
+
+void mdel(int argc, char **argv, int deltype)
+{
+	Arg_t arg;
+	MainParam_t mp;
+	int c,i;
+
+	arg.verbose = 0;
+	while ((c = getopt(argc, argv, "v")) != EOF) {
+		switch (c) {
+			case 'v':
+				arg.verbose = 1;
+				break;
+			default:
+				usage();
+		}
+	}
+
+	if(argc == optind)
+		usage();
+
+	init_mp(&mp);
+	mp.callback = del_file;
+	mp.arg = (void *) &arg;
+	mp.openflags = O_RDWR;
+	arg.deltype = deltype;
+	switch(deltype){
+	case 0:
+		mp.lookupflags = ACCEPT_PLAIN; /* mdel */
+		break;
+	case 1:
+		mp.lookupflags = ACCEPT_DIR; /* mrd */
+		break;
+	case 2:
+		mp.lookupflags = ACCEPT_DIR | ACCEPT_PLAIN; /* mdeltree */
+		break;
+	}
+	mp.lookupflags |= NO_DOTS;
+	for(i=optind;i<argc;i++) {
+		int b,l;
+		b = skip_drive(argv[i]) - argv[i];
+		l = strlen(argv[i]+b);
+		if(l > 1 && argv[i][b+l-1] == '/')
+			argv[i][b+l-1] = '\0';
+	}
+		
+	exit(main_loop(&mp, argv + optind, argc - optind));
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mdir.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mdir.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mdir.c	(revision 9)
@@ -0,0 +1,579 @@
+/*
+ * mdir.c:
+ * Display an MSDOS directory
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "vfat.h"
+#include "mtools.h"
+#include "file.h"
+#include "mainloop.h"
+#include "fs.h"
+#include "codepage.h"
+
+#ifdef TEST_SIZE
+#include "fsP.h"
+#endif
+
+static int recursive;
+static int wide;
+static int all;
+static int concise;
+static int fast=0;
+#if 0
+static int testmode = 0;
+#endif
+static char *dirPath;
+static char *currentDrive;
+static Stream_t *currentDir;
+
+static int filesInDir; /* files in current dir */
+static int filesOnDrive; /* files on drive */
+	
+static int dirsOnDrive; /* number of listed directories on this drive */
+
+static int debug = 0; /* debug mode */
+
+static mt_size_t bytesInDir;
+static mt_size_t bytesOnDrive;
+static Stream_t *RootDir;	
+
+
+static char shortname[13];
+static char longname[VBUFSIZE];
+
+
+/*
+ * Print an MSDOS directory date stamp.
+ */
+static inline void print_date(struct directory *dir)
+{
+	char year[5];
+	char day[3];
+	char month[3];
+	char *p;
+
+	sprintf(year, "%04d", DOS_YEAR(dir));
+	sprintf(day, "%02d", DOS_DAY(dir));
+	sprintf(month, "%02d", DOS_MONTH(dir));
+
+	for(p=mtools_date_string; *p; p++) {
+		if(!strncasecmp(p, "yyyy", 4)) {
+			printf("%04d", DOS_YEAR(dir));
+			p+= 3;
+			continue;
+		} else if(!strncasecmp(p, "yy", 2)) {
+			printf("%02d", DOS_YEAR(dir) % 100);
+			p++;
+			continue;
+		} else if(!strncasecmp(p, "dd", 2)) {
+			printf("%02d", DOS_DAY(dir));
+			p++;
+			continue;
+		} else if(!strncasecmp(p, "mm", 2)) {
+			printf("%02d", DOS_MONTH(dir));
+			p++;
+			continue;
+		}
+		putchar(*p);
+	}
+}
+
+/*
+ * Print an MSDOS directory time stamp.
+ */
+static inline void print_time(struct directory *dir)
+{
+	char am_pm;
+	int hour = DOS_HOUR(dir);
+       
+	if(!mtools_twenty_four_hour_clock) {
+		am_pm = (hour >= 12) ? 'p' : 'a';
+		if (hour > 12)
+			hour = hour - 12;
+		if (hour == 0)
+			hour = 12;
+	} else
+		am_pm = ' ';
+
+	printf("%2d:%02d%c", hour, DOS_MINUTE(dir), am_pm);
+}
+
+/*
+ * Return a number in dotted notation
+ */
+static const char *dotted_num(mt_size_t num, int width, char **buf)
+{
+	int      len;
+	register char *srcp, *dstp;
+	int size;
+
+	unsigned long numlo;
+	unsigned long numhi;
+
+	if (num < 0) {
+	    /* warn about negative numbers here.  They should not occur */
+	    fprintf(stderr, "Invalid negative number\n");
+	}
+
+	size = width + width;
+	*buf = malloc(size+1);
+
+	if (*buf == NULL)
+		return "";
+	
+	/* Create the number in maximum width; make sure that the string
+	 * length is not exceeded (in %6ld, the result can be longer than 6!)
+	 */
+
+	numlo = num % 1000000000;
+	numhi = num / 1000000000;
+
+	if(numhi && size > 9) {
+		sprintf(*buf, "%.*lu%09lu", size-9, numhi, numlo);
+	} else {
+		sprintf(*buf, "%.*lu", size, numlo);
+	}
+
+	for (srcp=*buf; srcp[1] != '\0'; ++srcp)
+		if (srcp[0] == '0')
+			srcp[0] = ' ';
+		else
+			break;
+	
+	len = strlen(*buf);
+	srcp = (*buf)+len;
+	dstp = (*buf)+len+1;
+
+	for ( ; dstp >= (*buf)+4 && isdigit (srcp[-1]); ) {
+		srcp -= 3;  /* from here we copy three digits */
+		dstp -= 4;  /* that's where we put these 3 digits */
+	}
+
+	/* now finally copy the 3-byte blocks to their new place */
+	while (dstp < (*buf) + len) {
+		dstp[0] = srcp[0];
+		dstp[1] = srcp[1];
+		dstp[2] = srcp[2];
+		if (dstp + 3 < (*buf) + len)
+			/* use spaces instead of dots: they please both
+			 * Americans and Europeans */
+			dstp[3] = ' ';		
+		srcp += 3;
+		dstp += 4;
+	}
+
+	return (*buf) + len-width;
+}
+
+static inline int print_volume_label(Stream_t *Dir, char *drive)
+{
+	Stream_t *Stream = GetFs(Dir);
+	direntry_t entry;
+	DeclareThis(FsPublic_t);
+	char shortname[13];
+	char longname[VBUFSIZE];
+	int r;
+
+	RootDir = OpenRoot(Stream);
+	if(concise)
+		return 0;
+	
+	/* find the volume label */
+
+	initializeDirentry(&entry, RootDir);
+	if((r=vfat_lookup(&entry, 0, 0, ACCEPT_LABEL | MATCH_ANY,
+			  shortname, longname)) ) {
+		if (r == -2) {
+			/* I/O Error */
+			return -1;
+		}
+		printf(" Volume in drive %s has no label", drive);
+	} else if (*longname)
+		printf(" Volume in drive %s is %s (abbr=%s)",
+		       drive, longname, shortname);
+	else
+		printf(" Volume in drive %s is %s",
+		       drive, shortname);
+	if(This->serialized)
+		printf("\n Volume Serial Number is %04lX-%04lX",
+		       (This->serial_number >> 16) & 0xffff, 
+		       This->serial_number & 0xffff);
+	return 0;
+}
+
+
+static void printSummary(int files, mt_size_t bytes)
+{
+	if(!filesInDir)
+		printf("No files\n");
+	else {		
+		char *s1;
+		printf("      %3d file", files);
+		if(files == 1)
+			putchar(' ');
+		else
+			putchar('s');
+		printf("       %s bytes\n",
+		       dotted_num(bytes, 13, &s1));
+		if(s1)
+			free(s1);
+	}
+}
+
+static void leaveDirectory(int haveError);
+
+static void leaveDrive(int haveError)
+{
+	if(!currentDrive)
+		return;
+	leaveDirectory(haveError);
+	if(!concise && !haveError) {
+		char *s1;
+
+		if(dirsOnDrive > 1) {
+			printf("\nTotal files listed:\n");
+			printSummary(filesOnDrive, bytesOnDrive);
+		}
+		if(RootDir && !fast) {
+			mt_off_t bytes = getfree(RootDir);
+			printf("                  %s bytes free\n\n",
+			       dotted_num(bytes,17, &s1));
+#ifdef TEST_SIZE
+			((Fs_t*)GetFs(RootDir))->freeSpace = 0;
+			bytes = getfree(RootDir);
+			printf("                  %s bytes free\n\n",
+			       dotted_num(bytes,17, &s1));
+#endif
+		}
+		if(s1)
+			free(s1);
+	}
+	FREE(&RootDir);
+	currentDrive = NULL;
+}
+
+
+static int enterDrive(Stream_t *Dir, char *drive)
+{
+	int r;
+	if(currentDrive != NULL && strcmp(currentDrive, drive) == 0)
+		return 0; /* still the same */
+	
+	leaveDrive(0);
+	currentDrive = drive;
+	
+	r = print_volume_label(Dir, drive);
+	if (r)
+		return r;
+
+
+	bytesOnDrive = 0;
+	filesOnDrive = 0;
+	dirsOnDrive = 0;
+	return 0;
+}
+
+static char *emptyString="<out-of-memory>";
+
+static void leaveDirectory(int haveError)
+{
+	if(!currentDir)
+		return;
+
+	if (!haveError) {
+		if(dirPath && dirPath != emptyString)
+			free(dirPath);
+		if(wide)
+			putchar('\n');
+		
+		if(!concise)
+			printSummary(filesInDir, bytesInDir);
+	}
+	FREE(&currentDir);
+}
+
+static int enterDirectory(Stream_t *Dir)
+{
+	int r;
+	char *drive;
+	char *slash;
+
+	if(currentDir == Dir)
+		return 0; /* still the same directory */
+
+	leaveDirectory(0);
+
+	drive = getDrive(Dir);
+	r=enterDrive(Dir, drive);
+	if(r)
+		return r;
+	currentDir = COPY(Dir);
+
+	dirPath = getPwd(getDirentry(Dir));
+	if(!dirPath)
+		dirPath=emptyString;
+	if(concise &&
+	    (slash = strrchr(dirPath, '/')) != NULL && slash[1] == '\0')
+		*slash = '\0';
+
+	/* print directory title */
+	if(!concise)
+		printf("\nDirectory for %s\n", dirPath);
+
+	if(!wide && !concise)
+		printf("\n");
+
+	dirsOnDrive++;
+	bytesInDir = 0;
+	filesInDir = 0;
+	return 0;
+}
+
+static int list_file(direntry_t *entry, MainParam_t *mp)
+{
+	unsigned long size;
+	int i;
+	int Case;
+	int r;
+
+	if(!all && (entry->dir.attr & 0x6))
+		return 0;
+
+	if(concise && isSpecial(entry->name))
+		return 0;
+
+	r=enterDirectory(entry->Dir);
+	if (r)
+		return ERROR_ONE;
+	if (wide) {
+		if(filesInDir % 5)
+			putchar(' ');				
+		else
+			putchar('\n');
+	}
+	
+	if(IS_DIR(entry)){
+		size = 0;
+	} else
+		size = FILE_SIZE(&entry->dir);
+	
+	Case = entry->dir.Case;
+	if(!(Case & (BASECASE | EXTCASE)) && 
+	   mtools_ignore_short_case)
+		Case |= BASECASE | EXTCASE;
+	
+	if(Case & EXTCASE){
+		for(i=0; i<3;i++)
+			entry->dir.ext[i] = tolower(entry->dir.ext[i]);
+	}
+	to_unix(entry->dir.ext,3);
+	if(Case & BASECASE){
+		for(i=0; i<8;i++)
+			entry->dir.name[i] = tolower(entry->dir.name[i]);
+	}
+	to_unix(entry->dir.name,8);
+	if(wide){
+		if(IS_DIR(entry))
+			printf("[%s]%*s", shortname,
+			       (int) (15 - 2 - strlen(shortname)), "");
+		else
+			printf("%-15s", shortname);
+	} else if(!concise) {				
+		/* is a subdirectory */
+		if(mtools_dotted_dir)
+			printf("%-13s", shortname);
+		else
+			printf("%-8.8s %-3.3s ",
+			       entry->dir.name, 
+			       entry->dir.ext);
+		if(IS_DIR(entry))
+			printf("<DIR>    ");
+		else
+			printf(" %8ld", (long) size);
+		printf(" ");
+		print_date(&entry->dir);
+		printf("  ");
+		print_time(&entry->dir);
+
+		if(debug)
+			printf(" %s %d ", entry->dir.name, START(&entry->dir));
+		
+		if(*longname)
+			printf(" %s", longname);
+		printf("\n");
+	} else {
+		printf("%s/%s", dirPath, entry->name);
+		if(IS_DIR(entry))
+			putchar('/');
+		putchar('\n');
+	}
+
+	filesOnDrive++;
+	filesInDir++;
+
+	bytesOnDrive += (mt_size_t) size;
+	bytesInDir += (mt_size_t) size;
+	return GOT_ONE;
+}
+
+static int list_non_recurs_directory(direntry_t *entry, MainParam_t *mp)
+{
+	int r;
+	/* list top-level directory
+	 *   If this was matched by wildcard in the basename, list it as
+	 *   file, otherwise, list it as directory */
+	if (mp->basenameHasWildcard) {
+		/* wildcard, list it as file */
+		return list_file(entry, mp);
+	} else {
+		/* no wildcard, list it as directory */
+		MainParam_t subMp;
+
+		r=enterDirectory(mp->File);
+		if(r)
+			return ERROR_ONE;
+
+		subMp = *mp;
+		subMp.dirCallback = subMp.callback;
+		return mp->loop(mp->File, &subMp, "*") | GOT_ONE;
+	}
+}
+
+
+static int list_recurs_directory(direntry_t *entry, MainParam_t *mp)
+{
+	MainParam_t subMp;
+	int ret;
+
+	/* first list the files */
+	subMp = *mp;
+	subMp.lookupflags = ACCEPT_DIR | ACCEPT_PLAIN;
+	subMp.dirCallback = list_file;
+	subMp.callback = list_file;
+
+	ret = mp->loop(mp->File, &subMp, "*");
+
+	/* then list subdirectories */
+	subMp = *mp;
+	subMp.lookupflags = ACCEPT_DIR | NO_DOTS | NO_MSG | DO_OPEN;
+	return ret | mp->loop(mp->File, &subMp, "*");
+}
+
+#if 0
+static int test_directory(direntry_t *entry, MainParam_t *mp)
+{
+	Stream_t *File=mp->File;
+	Stream_t *Target;
+	char errmsg[80];
+
+	if ((Target = SimpleFileOpen(0, 0, "-",
+				     O_WRONLY,
+				     errmsg, 0, 0, 0))) {
+		copyfile(File, Target);
+		FREE(&Target);
+	}
+	return GOT_ONE;
+}
+#endif
+
+static void usage(void)
+{
+		fprintf(stderr, "Mtools version %s, dated %s\n",
+			mversion, mdate);
+		fprintf(stderr, "Usage: %s: [-waXbfds/] msdosdirectory\n",
+			progname);
+		fprintf(stderr,
+			"       %s: [-waXbfds/] msdosfile [msdosfiles...]\n",
+			progname);
+		fprintf(stderr,
+			"\t-w Wide listing\n"
+			"\t-a All, including hidden files\n"
+			"\t-b -X Concise listing\n"
+			"\t-f Fast, no free space summary\n"
+			"\t-d Debug mode\n"
+			"\t-s -/ Recursive\n");
+		exit(1);
+}
+
+
+void mdir(int argc, char **argv, int type)
+{
+	int ret;
+	MainParam_t mp;
+	int faked;
+	int c;
+	char *fakedArgv[] = { "." };
+	
+	concise = 0;
+	recursive = 0;
+	wide = all = 0;
+					/* first argument */
+	while ((c = getopt(argc, argv, "waXbfds/")) != EOF) {
+		switch(c) {
+			case 'w':
+				wide = 1;
+				break;
+			case 'a':
+				all = 1;
+				break;
+			case 'b':
+			case 'X':
+				concise = 1;
+				/*recursive = 1;*/
+				break;
+			case 's':
+			case '/':
+				recursive = 1;
+				break;
+			case 'f':
+				fast = 1;
+				break;
+			case 'd':
+				debug = 1;
+				break;
+#if 0
+			case 't': /* test mode */
+				testmode = 1;
+				break;
+#endif
+			default:
+				usage();
+		}
+	}
+
+	/* fake an argument */
+	faked = 0;
+	if (optind == argc) {
+		argv = fakedArgv;
+		argc = 1;
+		optind = 0;
+	}
+
+	init_mp(&mp);
+	currentDrive = '\0';
+	currentDir = 0;
+	RootDir = 0;
+	dirPath = 0;
+#if 0
+	if (testmode) {
+		mp.lookupflags = ACCEPT_DIR | NO_DOTS;
+		mp.dirCallback = test_directory;
+	} else 
+#endif
+		if(recursive) {
+		mp.lookupflags = ACCEPT_DIR | DO_OPEN_DIRS | NO_DOTS;
+		mp.dirCallback = list_recurs_directory;
+	} else {
+		mp.lookupflags = ACCEPT_DIR | ACCEPT_PLAIN | DO_OPEN_DIRS;
+		mp.dirCallback = list_non_recurs_directory;
+		mp.callback = list_file;
+	}
+	mp.longname = longname;
+	mp.shortname = shortname;
+	ret=main_loop(&mp, argv + optind, argc - optind);
+	leaveDirectory(ret);
+	leaveDrive(ret);
+	exit(ret);
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mdoctorfat.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mdoctorfat.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mdoctorfat.c	(revision 9)
@@ -0,0 +1,166 @@
+/* Test program for doctoring the fat */
+
+
+/*
+ * mcopy.c
+ * Copy an MSDOS files to and from Unix
+ *
+ */
+
+
+#define LOWERCASE
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "vfat.h"
+#include "mainloop.h"
+#include "plain_io.h"
+#include "nameclash.h"
+#include "file.h"
+#include "fs.h"
+#include "fsP.h"
+
+typedef struct Arg_t {
+	char *target;
+	MainParam_t mp;
+	ClashHandling_t ch;
+	Stream_t *sourcefile;
+	unsigned long fat;
+	int markbad;
+	int setsize;
+	unsigned long size;
+	Fs_t *Fs;
+} Arg_t;
+
+static int dos_doctorfat(direntry_t *entry, MainParam_t *mp)
+{
+	Fs_t *Fs = getFs(mp->File);
+	Arg_t *arg=(Arg_t *) mp->arg;
+	
+	if(!arg->markbad && entry->entry != -3) {
+		/* if not root directory, change it */
+		set_word(entry->dir.start, arg->fat & 0xffff);
+		set_word(entry->dir.startHi, arg->fat >> 16);
+		if(arg->setsize)
+			set_dword(entry->dir.size, arg->size);
+		dir_write(entry);		
+	}
+	arg->Fs = Fs; 
+	return GOT_ONE;
+}
+
+static int unix_doctorfat(MainParam_t *mp)
+{
+	fprintf(stderr,"File does not reside on a Dos fs\n");
+	return ERROR_ONE;
+}
+
+
+static void usage(void)
+{
+	fprintf(stderr,
+		"Mtools version %s, dated %s\n", mversion, mdate);
+	fprintf(stderr,
+		"Usage: %s [-b] [-o offset] [-s size] file fat\n", progname);
+	exit(1);
+}
+
+void mdoctorfat(int argc, char **argv, int mtype)
+{
+	Arg_t arg;
+	int c, ret;
+	long address, begin, end;
+	char *number, *eptr;
+	int i, j;
+	long offset;
+	
+	/* get command line options */
+
+	init_clash_handling(& arg.ch);
+
+	offset = 0;
+
+	arg.markbad = 0;
+	arg.setsize = 0;
+
+	/* get command line options */
+	while ((c = getopt(argc, argv, "bo:s:")) != EOF) {
+		switch (c) {
+			case 'b':
+				arg.markbad = 1;
+				break;
+			case 'o':
+				offset = strtoul(optarg,0,0);
+				break;
+			case 's':
+				arg.setsize=1;
+				arg.size = strtoul(optarg,0,0);
+				break;
+			case '?':
+				usage();
+				break;
+		}
+	}
+
+	if (argc - optind < 2)
+		usage();
+
+
+	/* only 1 file to copy... */
+	init_mp(&arg.mp);
+	arg.mp.arg = (void *) &arg;
+		
+	arg.mp.callback = dos_doctorfat;
+	arg.mp.unixcallback = unix_doctorfat;
+	
+	arg.mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR | DO_OPEN;
+	arg.mp.openflags = O_RDWR;
+	arg.fat = strtoul(argv[optind+1], 0, 0) + offset;
+	ret=main_loop(&arg.mp, argv + optind, 1);
+	if(ret)
+		exit(ret);
+	address = 0;
+	for(i=optind+1; i < argc; i++) {
+		number = argv[i];
+		if (*number == '<') {
+			number++;
+		}
+		begin = strtoul(number, &eptr, 0);
+		if (eptr && *eptr == '-') {
+			number = eptr+1;
+			end = strtoul(number, &eptr, 0);
+		} else {
+			end = begin;
+		}
+		if (eptr == number) {
+			fprintf(stderr, "Not a number: %s\n", number);
+			exit(-1);
+		}
+
+		if (eptr && *eptr == '>') {
+			eptr++;
+		}
+		if (eptr && *eptr) {
+			fprintf(stderr, "Not a number: %s\n", eptr);
+			exit(-1);
+		}
+
+		for (j=begin; j <= end; j++) {
+			if(arg.markbad) {
+				arg.Fs->fat_encode(arg.Fs, j+offset, arg.Fs->last_fat ^ 6 ^ 8);
+			} else {
+				if(address) {
+					arg.Fs->fat_encode(arg.Fs, address, j+offset);
+				}
+				address = j+offset;
+			}
+		}
+	}
+
+	if (address && !arg.markbad) {
+		arg.Fs->fat_encode(arg.Fs, address, arg.Fs->end_fat);
+	}
+
+	exit(ret);
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mdu.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mdu.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mdu.c	(revision 9)
@@ -0,0 +1,121 @@
+/*
+ * mdu.c:
+ * Display the space occupied by an MSDOS directory
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "vfat.h"
+#include "mtools.h"
+#include "file.h"
+#include "mainloop.h"
+#include "fs.h"
+#include "codepage.h"
+
+
+typedef struct Arg_t {
+	int all;
+	int inDir;
+	int summary;
+	struct Arg_t *parent;
+	char *target;
+	char *path;
+	unsigned int blocks;
+	MainParam_t mp;
+} Arg_t;
+
+static void usage(void)
+{
+		fprintf(stderr, "Mtools version %s, dated %s\n",
+			mversion, mdate);
+		fprintf(stderr, "Usage: %s [-as] msdosdirectory\n"
+			"\t-a All (also show individual files)\n"
+			"\t-s Summary for directory only\n",
+			progname);
+		exit(1);
+}
+
+static int file_mdu(direntry_t *entry, MainParam_t *mp)
+{
+	unsigned int blocks;
+	Arg_t * arg = (Arg_t *) (mp->arg);
+
+	blocks = countBlocks(entry->Dir,getStart(entry->Dir, &entry->dir));
+	if(arg->all || !arg->inDir) {
+		printf("%-7d ", blocks);
+		fprintPwd(stdout, entry,0);
+		fputc('\n', stdout);
+	}
+	arg->blocks += blocks;
+	return GOT_ONE;
+}
+
+
+static int dir_mdu(direntry_t *entry, MainParam_t *mp)
+{
+	Arg_t *parentArg = (Arg_t *) (mp->arg);
+	Arg_t arg;
+	int ret;
+	
+	arg = *parentArg;
+	arg.mp.arg = (void *) &arg;
+	arg.parent = parentArg;
+	arg.inDir = 1;
+
+	/* account for the space occupied by the directory itself */
+	if(!isRootDir(entry->Dir)) {
+		arg.blocks = countBlocks(entry->Dir,
+					 getStart(entry->Dir, &entry->dir));
+	} else {
+		arg.blocks = 0;
+	}
+
+	/* recursion */
+	ret = mp->loop(mp->File, &arg.mp, "*");
+	if(!arg.summary || !parentArg->inDir) {
+		printf("%-7d ", arg.blocks);
+		fprintPwd(stdout, entry,0);
+		fputc('\n', stdout);
+	}
+	arg.parent->blocks += arg.blocks;
+	return ret;
+}
+
+void mdu(int argc, char **argv, int type)
+{
+	Arg_t arg;
+	int c;
+
+	arg.all = 0;
+	arg.inDir = 0;
+	arg.summary = 0;
+	while ((c = getopt(argc, argv, "as")) != EOF) {
+		switch (c) {
+			case 'a':
+				arg.all = 1;
+				break;
+			case 's':
+				arg.summary = 1;
+				break;
+			case '?':
+				usage();
+		}
+	}
+
+	if (optind >= argc)
+		usage();
+
+	if(arg.summary && arg.all) {
+		fprintf(stderr,"-a and -s options are mutually exclusive\n");
+		usage();
+	}
+
+	init_mp(&arg.mp);
+	arg.mp.callback = file_mdu;
+	arg.mp.openflags = O_RDONLY;
+	arg.mp.dirCallback = dir_mdu;
+
+	arg.mp.arg = (void *) &arg;
+	arg.mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR | DO_OPEN_DIRS | NO_DOTS;
+	exit(main_loop(&arg.mp, argv + optind, argc - optind));
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mformat.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mformat.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mformat.c	(revision 9)
@@ -0,0 +1,1140 @@
+/*
+ * mformat.c
+ */
+
+#define DONT_NEED_WAIT
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "mainloop.h"
+#include "fsP.h"
+#include "file.h"
+#include "plain_io.h"
+#include "floppyd_io.h"
+#include "nameclash.h"
+#include "buffer.h"
+#ifdef USE_XDF
+#include "xdf_io.h"
+#endif
+#include "partition.h"
+
+#ifndef abs
+#define abs(x) ((x)>0?(x):-(x))
+#endif
+
+#ifdef OS_linux
+#include "linux/hdreg.h"
+
+#define _LINUX_STRING_H_
+#define kdev_t int
+#include "linux/fs.h"
+#undef _LINUX_STRING_H_
+
+#endif
+
+
+extern int errno;
+
+static int init_geometry_boot(struct bootsector *boot, struct device *dev,
+			       int sectors0, int rate_0, int rate_any,
+			       int *tot_sectors, int keepBoot)
+{
+	int i;
+	int nb_renum;
+	int sector2;
+	int size2;
+	int j;
+	int sum;
+
+	set_word(boot->nsect, dev->sectors);
+	set_word(boot->nheads, dev->heads);
+
+	*tot_sectors = dev->heads * dev->sectors * dev->tracks - DWORD(nhs);
+
+	if (*tot_sectors < 0x10000){
+		set_word(boot->psect, *tot_sectors);
+		set_dword(boot->bigsect, 0);
+	} else {
+		set_word(boot->psect, 0);
+		set_dword(boot->bigsect, *tot_sectors);
+	}
+
+	if (dev->use_2m & 0x7f){
+		int bootOffset;
+		strncpy(boot->banner, "2M-STV04", 8);
+		boot->ext.old.res_2m = 0;
+		boot->ext.old.fmt_2mf = 6;
+		if ( dev->sectors % ( ((1 << dev->ssize) + 3) >> 2 ))
+			boot->ext.old.wt = 1;
+		else
+			boot->ext.old.wt = 0;
+		boot->ext.old.rate_0= rate_0;
+		boot->ext.old.rate_any= rate_any;
+		if (boot->ext.old.rate_any== 2 )
+			boot->ext.old.rate_any= 1;
+		i=76;
+
+		/* Infp0 */
+		set_word(boot->ext.old.Infp0, i);
+		boot->jump[i++] = sectors0;
+		boot->jump[i++] = 108;
+		for(j=1; j<= sectors0; j++)
+			boot->jump[i++] = j;
+
+		set_word(boot->ext.old.InfpX, i);
+		
+		boot->jump[i++] = 64;
+		boot->jump[i++] = 3;
+		nb_renum = i++;
+		sector2 = dev->sectors;
+		size2 = dev->ssize;
+		j=1;
+		while( sector2 ){
+			while ( sector2 < (1 << size2) >> 2 )
+				size2--;
+			boot->jump[i++] = 128 + j;
+			boot->jump[i++] = j++;
+			boot->jump[i++] = size2;
+			sector2 -= (1 << size2) >> 2;
+		}
+		boot->jump[nb_renum] = ( i - nb_renum - 1 ) / 3;
+
+		set_word(boot->ext.old.InfTm, i);
+
+		sector2 = dev->sectors;
+		size2= dev->ssize;
+		while(sector2){
+			while ( sector2 < 1 << ( size2 - 2) )
+				size2--;
+			boot->jump[i++] = size2;
+			sector2 -= 1 << (size2 - 2 );
+		}
+		
+		set_word(boot->ext.old.BootP,i);
+		bootOffset = i;
+
+		/* checksum */		
+		for (sum=0, j=64; j<i; j++) 
+			sum += boot->jump[j];/* checksum */
+		boot->ext.old.CheckSum=-sum;
+		return bootOffset;
+	} else {
+		if(!keepBoot) {
+			boot->jump[0] = 0xeb;
+			boot->jump[1] = 0;
+			boot->jump[2] = 0x90;
+			strncpy(boot->banner, "MTOOL397", 8);
+			/* It looks like some versions of DOS are
+			 * rather picky about this, and assume default
+			 * parameters without this, ignoring any
+			 * indication about cluster size et al. */
+		}
+		return 0;
+	}
+}
+
+
+static int comp_fat_bits(Fs_t *Fs, int estimate, 
+			 unsigned int tot_sectors, int fat32)
+{
+	int needed_fat_bits;
+
+	needed_fat_bits = 12;
+
+#define MAX_DISK_SIZE(bits,clusters) \
+	TOTAL_DISK_SIZE((bits), Fs->sector_size, (clusters), \
+			Fs->num_fat, MAX_SECT_PER_CLUSTER)
+
+	if(tot_sectors > MAX_DISK_SIZE(12, FAT12))
+		needed_fat_bits = 16;
+	if(fat32 || tot_sectors > MAX_DISK_SIZE(16, FAT16))
+		needed_fat_bits = 32;
+
+#undef MAX_DISK_SIZE
+
+	if(abs(estimate) && abs(estimate) < needed_fat_bits) {
+		if(fat32) {
+			fprintf(stderr,
+				"Contradiction between FAT size on command line and FAT size in conf file\n");
+			exit(1);
+		}
+		fprintf(stderr,
+			"Device too big for a %d bit FAT\n",
+			estimate);
+		exit(1);
+	}
+
+	if(needed_fat_bits == 32 && !fat32 && abs(estimate) !=32){
+		fprintf(stderr,"Warning: Using 32 bit FAT.  Drive will only be accessibly by Win95 OEM / Win98\n");
+	}
+
+	if(!estimate) {
+		int min_fat16_size;
+
+		if(needed_fat_bits > 12)
+			return needed_fat_bits;
+		min_fat16_size = DISK_SIZE(16, Fs->sector_size, FAT12+1,
+					   Fs->num_fat, 1);
+		if(tot_sectors < min_fat16_size)
+			return 12;
+		else if(tot_sectors >= 2* min_fat16_size)
+			return 16; /* heuristics */
+	}
+
+	return estimate;
+}
+
+static void calc_fat_bits2(Fs_t *Fs, unsigned int tot_sectors, int fat_bits)
+{
+	unsigned int rem_sect;
+
+	/*
+	 * the "remaining sectors" after directory and boot
+	 * hasve been accounted for.
+	 */
+	rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
+	switch(abs(fat_bits)) {
+		case 0:
+
+#define MY_DISK_SIZE(bits,clusters) \
+			DISK_SIZE( (bits), Fs->sector_size, (clusters), \
+				   Fs->num_fat, Fs->cluster_size)
+
+			if(rem_sect >= MY_DISK_SIZE(16, FAT12 + 1))
+				/* big enough for FAT16 */
+				set_fat16(Fs);
+			else if(rem_sect <= MY_DISK_SIZE(12, FAT12))
+				 /* small enough for FAT12 */
+				 set_fat12(Fs);
+			else {
+				/* "between two chairs",
+				 * augment cluster size, and
+				 * settle it */
+				if(Fs->cluster_size < MAX_SECT_PER_CLUSTER)
+					Fs->cluster_size <<= 1;
+				set_fat12(Fs);
+			}
+			break;
+#undef MY_DISK_SIZE
+
+		case 12:
+			set_fat12(Fs);
+			break;
+		case 16:
+			set_fat16(Fs);
+			break;
+		case 32:
+			set_fat32(Fs);
+			break;
+	}
+}
+
+static inline void format_root(Fs_t *Fs, char *label, struct bootsector *boot)
+{
+	Stream_t *RootDir;
+	char *buf;
+	int i;
+	struct ClashHandling_t ch;
+	int dirlen;
+
+	init_clash_handling(&ch);
+	ch.name_converter = label_name;
+	ch.ignore_entry = -2;
+
+	buf = safe_malloc(Fs->sector_size);
+	RootDir = OpenRoot((Stream_t *)Fs);
+	if(!RootDir){
+		fprintf(stderr,"Could not open root directory\n");
+		exit(1);
+	}
+
+	memset(buf, '\0', Fs->sector_size);
+
+	if(Fs->fat_bits == 32) {
+		/* on a FAT32 system, we only write one sector,
+		 * as the directory can be extended at will...*/
+		dirlen = 1;
+		fatAllocate(Fs, Fs->rootCluster, Fs->end_fat);
+	} else
+		dirlen = Fs->dir_len; 
+	for (i = 0; i < dirlen; i++)
+		WRITES(RootDir, buf, sectorsToBytes((Stream_t*)Fs, i),  
+			   Fs->sector_size);
+
+	ch.ignore_entry = 1;
+	if(label[0])
+		mwrite_one(RootDir,label, 0, labelit, NULL,&ch);
+
+	FREE(&RootDir);
+	if(Fs->fat_bits == 32)
+		set_word(boot->dirents, 0);
+	else
+		set_word(boot->dirents, Fs->dir_len * (Fs->sector_size / 32));
+	free(buf);
+}
+
+
+static void xdf_calc_fat_size(Fs_t *Fs, unsigned int tot_sectors, int fat_bits)
+{
+	unsigned int rem_sect;
+
+	rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start - 2 * Fs->fat_len;
+
+	if(Fs->fat_len) {
+		/* an XDF disk, we know the fat_size and have to find
+		 * out the rest. We start with a cluster size of 1 and
+		 * keep doubling until everything fits into the
+		 * FAT. This will occur eventually, as our FAT has a
+		 * minimal size of 1 */
+		for(Fs->cluster_size = 1; 1 ; Fs->cluster_size <<= 1) {
+			Fs->num_clus = rem_sect / Fs->cluster_size;
+			if(abs(fat_bits) == 16 || Fs->num_clus > FAT12)
+				set_fat16(Fs);
+			else
+				set_fat12(Fs);
+			if (Fs->fat_len >= NEEDED_FAT_SIZE(Fs))
+				return;
+		}
+	}
+	fprintf(stderr,"Internal error while calculating Xdf fat size\n");
+	exit(1);
+}
+
+
+static void calc_fat_size(Fs_t *Fs, unsigned int tot_sectors)
+{
+	unsigned int rem_sect;
+	int tries;
+	int occupied;
+	
+	tries=0;
+	/* rough estimate of fat size */
+	Fs->fat_len = 1;
+	rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
+	while(1){
+		Fs->num_clus = (rem_sect - 2 * Fs->fat_len ) /Fs->cluster_size;
+		Fs->fat_len = NEEDED_FAT_SIZE(Fs);
+		occupied = 2 * Fs->fat_len + Fs->cluster_size * Fs->num_clus;
+		
+		/* if we have used up more than we have,
+		 * we'll have to reloop */
+		
+		if ( occupied > rem_sect )
+			continue;
+
+
+		/* if we have exactly used up all
+		 * sectors, fine */
+		if ( rem_sect - occupied < Fs->cluster_size )
+			break;
+
+		/* if we have not used up all our
+		 * sectors, try again.  After the second
+		 * try, decrease the amount of available
+		 * space. This is to deal with the case of
+		 * 344 or 345, ..., 1705, ... available
+		 * sectors.  */
+		
+		switch(tries++){
+			default:
+				/* this should never happen */
+				fprintf(stderr,
+					"Internal error in cluster/fat repartition"
+					" calculation.\n");
+				exit(1);
+			case 2:
+				/* FALLTHROUGH */
+			case 1:
+				rem_sect-= Fs->cluster_size;
+				Fs->dir_len += Fs->cluster_size;
+			case 0:
+				continue;
+		}
+	}
+
+	if ( Fs->num_clus > FAT12 && Fs->fat_bits == 12 ){
+		fprintf(stderr,"Too many clusters for this fat size."
+			" Please choose a 16-bit fat in your /etc/mtools"
+			" or .mtoolsrc file\n");
+		exit(1);
+	}
+	if ( Fs->num_clus <= FAT12 && Fs->fat_bits > 12 ){
+		fprintf(stderr,"Too few clusters for this fat size."
+			" Please choose a 12-bit fat in your /etc/mtools"
+			" or .mtoolsrc file\n");
+		exit(1);
+	}
+}
+
+
+static unsigned char bootprog[]=
+{0xfa, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xc0, 0xfc, 0xb9, 0x00, 0x01,
+ 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x80, 0xf3, 0xa5, 0xea, 0x00, 0x00,
+ 0x00, 0x08, 0xb8, 0x01, 0x02, 0xbb, 0x00, 0x7c, 0xba, 0x80, 0x00,
+ 0xb9, 0x01, 0x00, 0xcd, 0x13, 0x72, 0x05, 0xea, 0x00, 0x7c, 0x00,
+ 0x00, 0xcd, 0x19};
+
+static inline void inst_boot_prg(struct bootsector *boot, int offset)
+{
+	memcpy((char *) boot->jump + offset, 
+	       (char *) bootprog, sizeof(bootprog) /sizeof(bootprog[0]));
+	boot->jump[0] = 0xeb;
+	boot->jump[1] = offset - 1;
+	boot->jump[2] = 0x90;
+	set_word(boot->jump + offset + 20, offset + 24);
+}
+
+static void calc_cluster_size(struct Fs_t *Fs, unsigned int tot_sectors,
+			      int fat_bits)
+			      
+{
+	unsigned int max_clusters; /* maximal possible number of sectors for
+				   * this FAT entry length (12/16/32) */
+	unsigned int max_fat_size; /* maximal size of the FAT for this FAT
+				    * entry length (12/16/32) */
+	unsigned int rem_sect; /* remaining sectors after we accounted for
+				* the root directory and boot sector(s) */
+
+	switch(abs(fat_bits)) {
+		case 12:			
+			max_clusters = FAT12;
+			max_fat_size = Fs->num_fat * 
+				FAT_SIZE(12, Fs->sector_size, max_clusters);
+			break;
+		case 16:
+		case 0: /* still hesititating between 12 and 16 */
+			max_clusters = FAT16;
+			max_fat_size = Fs->num_fat * 
+				FAT_SIZE(16, Fs->sector_size, max_clusters);
+			break;
+		case 32:		  
+			Fs->cluster_size = 8;
+			/* According to
+			 * http://www.microsoft.com/kb/articles/q154/9/97.htm,
+			 * Micro$oft does not support FAT32 with less than 4K
+			 */
+			return;
+		default:
+			fprintf(stderr,"Bad fat size\n");
+			exit(1);
+	}
+
+	rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
+
+	/* double the cluster size until we can fill up the disk with
+	 * the maximal number of sectors of this size */
+	while(Fs->cluster_size * max_clusters  + max_fat_size < rem_sect) {
+		if(Fs->cluster_size > 64) {
+			/* bigger than 64. Should fit */
+			fprintf(stderr,
+				"Internal error while calculating cluster size\n");
+			exit(1);
+		}
+		Fs->cluster_size <<= 1;
+	}
+}
+
+
+struct OldDos_t old_dos[]={
+{   40,  9,  1, 4, 1, 2, 0xfc },
+{   40,  9,  2, 7, 2, 2, 0xfd },
+{   40,  8,  1, 4, 1, 1, 0xfe },
+{   40,  8,  2, 7, 2, 1, 0xff },
+{   80,  9,  2, 7, 2, 3, 0xf9 },
+{   80, 15,  2,14, 1, 7, 0xf9 },
+{   80, 18,  2,14, 1, 9, 0xf0 },
+{   80, 36,  2,15, 2, 9, 0xf0 },
+{    1,  8,  1, 1, 1, 1, 0xf0 },
+};
+
+static int old_dos_size_to_geom(int size, int *cyls, int *heads, int *sects)
+{
+	int i;
+	size = size * 2;
+	for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){
+		if (old_dos[i].sectors * 
+		    old_dos[i].tracks * 
+		    old_dos[i].heads == size) {
+			*cyls = old_dos[i].tracks;
+			*heads = old_dos[i].heads;
+			*sects = old_dos[i].sectors;
+			return 0;
+		}
+	}
+	return 1;
+}
+
+
+static void calc_fs_parameters(struct device *dev, unsigned int tot_sectors,
+			       struct Fs_t *Fs, struct bootsector *boot)
+{
+	int i;
+
+	for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){
+		if (dev->sectors == old_dos[i].sectors &&
+		    dev->tracks == old_dos[i].tracks &&
+		    dev->heads == old_dos[i].heads &&
+		    (dev->fat_bits == 0 || abs(dev->fat_bits) == 12)){
+			boot->descr = old_dos[i].media;
+			Fs->cluster_size = old_dos[i].cluster_size;
+			Fs->dir_len = old_dos[i].dir_len;
+			Fs->fat_len = old_dos[i].fat_len;
+			Fs->fat_bits = 12;
+			break;
+		}
+	}
+	if (i == sizeof(old_dos) / sizeof(old_dos[0]) ){
+		/* a non-standard format */
+		if(DWORD(nhs))
+			boot->descr = 0xf8;
+		  else
+			boot->descr = 0xf0;
+
+
+		if(!Fs->cluster_size) {
+			if (dev->heads == 1)
+				Fs->cluster_size = 1;
+			else {
+				Fs->cluster_size = (tot_sectors > 2000 ) ? 1:2;
+				if (dev->use_2m & 0x7f)
+					Fs->cluster_size = 1;
+			}
+		}
+		
+		if(!Fs->dir_len) {
+			if (dev->heads == 1)
+				Fs->dir_len = 4;
+			else
+				Fs->dir_len = (tot_sectors > 2000) ? 11 : 7;
+		}			
+
+		calc_cluster_size(Fs, tot_sectors, dev->fat_bits);
+		if(Fs->fat_len)
+			xdf_calc_fat_size(Fs, tot_sectors, dev->fat_bits);
+		else {
+			calc_fat_bits2(Fs, tot_sectors, dev->fat_bits);
+			calc_fat_size(Fs, tot_sectors);
+		}
+	}
+
+	set_word(boot->fatlen, Fs->fat_len);
+}
+
+
+
+static void calc_fs_parameters_32(unsigned int tot_sectors,
+				  struct Fs_t *Fs, struct bootsector *boot)
+{
+	if(DWORD(nhs))
+		boot->descr = 0xf8;
+	else
+		boot->descr = 0xf0;
+	if(!Fs->cluster_size)
+		/* According to
+		 * http://www.microsoft.com/kb/articles/q154/9/97.htm,
+		 * Micro$oft does not support FAT32 with less than 4K
+		 */
+		Fs->cluster_size = 8;
+	
+	Fs->dir_len = 0;
+	Fs->num_clus = tot_sectors / Fs->cluster_size;
+	set_fat32(Fs);
+	calc_fat_size(Fs, tot_sectors);
+	set_word(boot->fatlen, 0);
+	set_dword(boot->ext.fat32.bigFat, Fs->fat_len);
+}
+
+
+
+
+static void usage(void)
+{
+	fprintf(stderr, 
+		"Mtools version %s, dated %s\n", mversion, mdate);
+	fprintf(stderr, 
+		"Usage: %s [-t tracks] [-h heads] [-n sectors] "
+		"[-v label] [-1] [-4] [-8] [-f size] "
+		"[-N serialnumber] "
+		"[-k] [-B bootsector] [-r root_dir_len] [-L fat_len] "
+		"[-F] [-I fsVersion] [-C] [-c cluster_size] "
+		"[-H hidden_sectors] "
+#ifdef USE_XDF
+		"[-X] "
+#endif
+		"[-S hardsectorsize] [-M softsectorsize] [-3] "
+		"[-2 track0sectors] [-0 rate0] [-A rateany] [-a]"
+		"device\n", progname);
+	exit(1);
+}
+
+void mformat(int argc, char **argv, int dummy)
+{
+	int r; /* generic return value */
+	Fs_t Fs;
+	int hs, hs_set;
+	int arguse_2m = 0;
+	int sectors0=18; /* number of sectors on track 0 */
+	int create = 0;
+	int rate_0, rate_any;
+	int mangled;
+	int argssize=0; /* sector size */
+	int msize=0;
+	int fat32 = 0;
+	struct label_blk_t *labelBlock;
+	int bootOffset;
+
+#ifdef USE_XDF
+	int i;
+	int format_xdf = 0;
+	struct xdf_info info;
+#endif
+	struct bootsector *boot;
+	char *bootSector=0;
+	int c;
+	int keepBoot = 0;
+	struct device used_dev;
+	int argtracks, argheads, argsectors;
+	int tot_sectors;
+	int blocksize;
+
+	char *drive, name[EXPAND_BUF];
+
+	char label[VBUFSIZE], buf[MAX_SECTOR], shortlabel[13];
+	struct device *dev;
+	char errmsg[200];
+
+	unsigned long serial;
+ 	int serial_set;
+	int fsVersion;
+
+	mt_off_t maxSize;
+
+	int Atari = 0; /* should we add an Atari-style serial number ? */
+#ifdef OS_Minix
+	char *devname;
+	struct device onedevice[2];
+	struct stat stbuf;
+#endif
+ 
+	hs = hs_set = 0;
+	argtracks = 0;
+	argheads = 0;
+	argsectors = 0;
+	arguse_2m = 0;
+	argssize = 0x2;
+	label[0] = '\0';
+	serial_set = 0;
+	serial = 0;
+	fsVersion = 0;
+	
+	Fs.cluster_size = 0;
+	Fs.refs = 1;
+	Fs.dir_len = 0;
+	Fs.fat_len = 0;
+	Fs.Class = &FsClass;	
+	rate_0 = mtools_rate_0;
+	rate_any = mtools_rate_any;
+
+	/* get command line options */
+	while ((c = getopt(argc,argv,
+			   "148f:t:n:v:qub"
+			   "kB:r:L:IFCc:Xh:s:l:N:H:M:S:230:Aa"))!= EOF) {
+		switch (c) {
+			/* standard DOS flags */
+			case '1':
+				argheads = 1;
+				break;
+			case '4':
+				argsectors = 9;
+				argtracks = 40;
+				break;
+			case '8':
+				argsectors = 8;
+				argtracks = 40;
+				break;
+			case 'f':
+				r=old_dos_size_to_geom(atoi(optarg),
+						       &argtracks, &argheads,
+						       &argsectors);
+				if(r) {
+					fprintf(stderr, 
+						"Bad size %s\n", optarg);
+					exit(1);
+				}
+				break;
+			case 't':
+				argtracks = atoi(optarg);
+				break;
+
+			case 'n': /*non-standard*/
+			case 's':
+				argsectors = atoi(optarg);
+				break;
+
+			case 'l': /* non-standard */
+			case 'v':
+				strncpy(label, optarg, VBUFSIZE-1);
+				label[VBUFSIZE-1] = '\0';
+				break;
+
+			/* flags supported by Dos but not mtools */
+			case 'q':
+			case 'u':
+			case 'b':
+			/*case 's': leave this for compatibility */
+				fprintf(stderr, 
+					"Flag %c not supported by mtools\n",c);
+				exit(1);
+				
+
+
+			/* flags added by mtools */
+			case 'F':
+				fat32 = 1;
+				break;
+
+
+			case 'S':
+				argssize = atoi(optarg) | 0x80;
+				if(argssize < 0x81)
+					usage();
+				break;
+
+#ifdef USE_XDF
+			case 'X':
+				format_xdf = 1;
+				break;
+#endif
+
+			case '2':
+				arguse_2m = 0xff;
+				sectors0 = atoi(optarg);
+				break;
+			case '3':
+				arguse_2m = 0x80;
+				break;
+
+			case '0': /* rate on track 0 */
+				rate_0 = atoi(optarg);
+				break;
+			case 'A': /* rate on other tracks */
+				rate_any = atoi(optarg);
+				break;
+
+			case 'M':
+				msize = atoi(optarg);
+				if (msize % 256 || msize > 8192 )
+					usage();
+				break;
+
+			case 'N':
+ 				serial = strtoul(optarg,0,16);
+ 				serial_set = 1;
+ 				break;
+			case 'a': /* Atari style serial number */
+				Atari = 1;
+				break;
+
+			case 'C':
+				create = O_CREAT;
+				break;
+
+			case 'H':
+				hs = atoi(optarg);
+				hs_set = 1;
+				break;
+
+			case 'I':
+				fsVersion = strtoul(optarg,0,0);
+				break;
+
+			case 'c':
+				Fs.cluster_size = atoi(optarg);
+				break;
+
+			case 'r': 
+				Fs.dir_len = strtoul(optarg,0,0);
+				break;
+			case 'L':
+				Fs.fat_len = strtoul(optarg,0,0);
+				break;
+
+
+			case 'B':
+				bootSector = optarg;
+				break;
+			case 'k':
+				keepBoot = 1;
+				break;
+			case 'h':
+				argheads = atoi(optarg);
+				break;
+
+			default:
+				usage();
+		}
+	}
+
+	if (argc - optind != 1 ||
+	    skip_drive(argv[optind]) == argv[optind])
+		usage();
+
+#ifdef USE_XDF
+	if(create && format_xdf) {
+		fprintf(stderr,"Create and XDF can't be used together\n");
+		exit(1);
+	}
+#endif
+	
+	drive = get_drive(argv[argc -1], NULL);
+
+#ifdef OS_Minix
+	devname = safe_malloc((9 + strlen(drive)) * sizeof(devname[0]));
+	strcpy(devname, "/dev/dosX");
+	if (isupper(drive[0]) && drive[1] == 0) {
+		/* single letter device name, use /dev/dos$drive */
+		devname[8]= drive[0];
+	} else
+	if (strchr(drive, '/') == NULL) {
+		/* a simple name, use /dev/$drive */
+		strcpy(devname+5, drive);
+	} else {
+		/* a pathname, use as is. */
+		strcpy(devname, drive);
+	}
+	if (stat(devname, &stbuf) != -1) {
+		memset(onedevice, 0, sizeof(onedevice));
+		onedevice[0].name = devname;
+		onedevice[0].drive = drive;
+		onedevice[1].name = NULL;
+		onedevice[1].drive = NULL;
+		dev = onedevice;
+	} else {
+		dev = devices;
+	}
+#else
+	dev = devices;
+#endif
+
+	/* check out a drive whose letter and parameters match */	
+	sprintf(errmsg, "Drive '%s:' not supported", drive);	
+	Fs.Direct = NULL;
+	blocksize = 0;
+	for(;dev->drive;dev++) {
+		FREE(&(Fs.Direct));
+		/* drive name */
+		if (strcmp(dev->drive, drive) != 0)
+			continue;
+		used_dev = *dev;
+
+		SET_INT(used_dev.tracks, argtracks);
+		SET_INT(used_dev.heads, argheads);
+		SET_INT(used_dev.sectors, argsectors);
+		SET_INT(used_dev.use_2m, arguse_2m);
+		SET_INT(used_dev.ssize, argssize);
+		if(hs_set)
+			used_dev.hidden = hs;
+		
+		expand(dev->name, name);
+#ifdef USING_NEW_VOLD
+		strcpy(name, getVoldName(dev, name));
+#endif
+
+#ifdef USE_XDF
+		if(!format_xdf) {
+#endif
+			Fs.Direct = 0;
+#ifdef USE_FLOPPYD
+			Fs.Direct = FloppydOpen(&used_dev, dev, name, O_RDWR | create,
+									errmsg, 0, 1);
+			if(Fs.Direct) {
+				maxSize = max_off_t_31;
+			}
+#endif
+			if(!Fs.Direct) {			
+				Fs.Direct = SimpleFileOpen(&used_dev, dev, name,
+										   O_RDWR | create,
+										   errmsg, 0, 1, &maxSize);
+			}
+#ifdef USE_XDF
+		} else {
+			used_dev.misc_flags |= USE_XDF_FLAG;
+			Fs.Direct = XdfOpen(&used_dev, name, O_RDWR,
+					    errmsg, &info);
+			if(Fs.Direct && !Fs.fat_len)
+				Fs.fat_len = info.FatSize;
+			if(Fs.Direct && !Fs.dir_len)
+				Fs.dir_len = info.RootDirSize;
+		}
+#endif
+
+		if (!Fs.Direct)
+			continue;
+
+#ifdef OS_linux
+		if ((!used_dev.tracks || !used_dev.heads || !used_dev.sectors) &&
+			(!IS_SCSI(dev))) {
+			int fd= get_fd(Fs.Direct);
+			struct stat buf;
+
+			if (fstat(fd, &buf) < 0) {
+				sprintf(errmsg, "Could not stat file (%s)", strerror(errno));
+				continue;						
+			}
+
+			if (S_ISBLK(buf.st_mode)) {
+				struct hd_geometry geom;
+				long size;
+				int sect_per_track;
+
+				if (ioctl(fd, HDIO_GETGEO, &geom) < 0) {
+					sprintf(errmsg, "Could not get geometry of device (%s)",
+							strerror(errno));
+					continue;
+				}
+
+				if (ioctl(fd, BLKGETSIZE, &size) < 0) {
+					sprintf(errmsg, "Could not get size of device (%s)",
+							strerror(errno));
+					continue;
+				}
+
+				sect_per_track = geom.heads * geom.sectors;
+				used_dev.heads = geom.heads;
+				used_dev.sectors = geom.sectors;
+				used_dev.hidden = geom.start % sect_per_track;
+				used_dev.tracks = (size + used_dev.hidden) / sect_per_track;
+			}
+		}
+#endif
+
+		/* no way to find out geometry */
+		if (!used_dev.tracks || !used_dev.heads || !used_dev.sectors){
+			sprintf(errmsg, 
+				"Unknown geometry "
+				"(You must tell the complete geometry "
+				"of the disk, \neither in /etc/mtools.conf or "
+				"on the command line) ");
+			continue;
+		}
+
+#if 0
+		/* set parameters, if needed */
+		if(SET_GEOM(Fs.Direct, &used_dev, 0xf0, boot)){
+			sprintf(errmsg,"Can't set disk parameters: %s", 
+				strerror(errno));
+			continue;
+		}
+#endif
+		Fs.sector_size = 512;
+		if( !(used_dev.use_2m & 0x7f)) {
+			Fs.sector_size = 128 << (used_dev.ssize & 0x7f);
+		}
+
+		SET_INT(Fs.sector_size, msize);
+		{
+		    int i;
+		    for(i = 0; i < 31; i++) {
+			if (Fs.sector_size == 1 << i) {
+			    Fs.sectorShift = i;
+			    break;
+			}
+		    }
+		    Fs.sectorMask = Fs.sector_size - 1;
+		}
+
+		if(!used_dev.blocksize || used_dev.blocksize < Fs.sector_size)
+			blocksize = Fs.sector_size;
+		else
+			blocksize = used_dev.blocksize;
+		
+		if(blocksize > MAX_SECTOR)
+			blocksize = MAX_SECTOR;
+
+		/* do a "test" read */
+		if (!create &&
+		    READS(Fs.Direct, (char *) buf, 0, Fs.sector_size) != 
+		    Fs.sector_size) {
+			sprintf(errmsg, 
+				"Error reading from '%s', wrong parameters?",
+				name);
+			continue;
+		}
+		break;
+	}
+
+
+	/* print error msg if needed */	
+	if ( dev->drive == 0 ){
+		FREE(&Fs.Direct);
+		fprintf(stderr,"%s: %s\n", argv[0],errmsg);
+		exit(1);
+	}
+
+	/* the boot sector */
+	boot = (struct bootsector *) buf;
+	if(bootSector) {
+		int fd;
+
+		fd = open(bootSector, O_RDONLY);
+		if(fd < 0) {
+			perror("open boot sector");
+			exit(1);
+		}
+		read(fd, buf, blocksize);
+		keepBoot = 1;
+	}
+	if(!keepBoot) {
+		memset((char *)boot, '\0', Fs.sector_size);
+		if(Fs.sector_size == 512 && !used_dev.partition) {
+			/* install fake partition table pointing to itself */
+			struct partition *partTable=(struct partition *)
+				(((char*) boot) + 0x1ae);
+			setBeginEnd(&partTable[1], 0,
+						used_dev.heads * used_dev.sectors * used_dev.tracks,
+						used_dev.heads, used_dev.sectors, 1, 0);
+		}
+	}
+	set_dword(boot->nhs, used_dev.hidden);
+
+	Fs.Next = buf_init(Fs.Direct,
+			   blocksize * used_dev.heads * used_dev.sectors,
+			   blocksize * used_dev.heads * used_dev.sectors,
+			   blocksize);
+	Fs.Buffer = 0;
+
+	boot->nfat = Fs.num_fat = 2;
+	if(!keepBoot)
+		set_word(boot->jump + 510, 0xaa55);
+	
+	/* get the parameters */
+	tot_sectors = used_dev.tracks * used_dev.heads * used_dev.sectors - 
+		DWORD(nhs);
+
+	set_word(boot->nsect, dev->sectors);
+	set_word(boot->nheads, dev->heads);
+
+	dev->fat_bits = comp_fat_bits(&Fs,dev->fat_bits, tot_sectors, fat32);
+
+	if(dev->fat_bits == 32) {
+		Fs.primaryFat = 0;
+		Fs.writeAllFats = 1;
+		Fs.fat_start = 32;
+		calc_fs_parameters_32(tot_sectors, &Fs, boot);
+
+		Fs.clus_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
+
+		/* extension flags: mirror fats, and use #0 as primary */
+		set_word(boot->ext.fat32.extFlags,0);
+
+		/* fs version.  What should go here? */
+		set_word(boot->ext.fat32.fsVersion,fsVersion);
+
+		/* root directory */
+		set_dword(boot->ext.fat32.rootCluster, Fs.rootCluster = 2);
+
+		/* info sector */
+		set_word(boot->ext.fat32.infoSector, Fs.infoSectorLoc = 1);
+		Fs.infoSectorLoc = 1;
+
+		/* no backup boot sector */
+		set_word(boot->ext.fat32.backupBoot, 6);
+		
+		labelBlock = & boot->ext.fat32.labelBlock;
+	} else {
+		Fs.infoSectorLoc = 0;
+		Fs.fat_start = 1;
+		calc_fs_parameters(&used_dev, tot_sectors, &Fs, boot);
+		Fs.dir_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
+		Fs.clus_start = Fs.dir_start + Fs.dir_len;
+		labelBlock = & boot->ext.old.labelBlock;
+
+	}
+	
+	if (!keepBoot)
+		/* only zero out physdrive if we don't have a template
+		 * bootsector */
+		labelBlock->physdrive = 0x00;
+	labelBlock->reserved = 0;
+	labelBlock->dos4 = 0x29;
+
+	if (!serial_set || Atari)
+		srandom((long)time (0));
+	if (!serial_set)
+		serial=random();
+	set_dword(labelBlock->serial, serial);	
+	if(!label[0])
+		strncpy(shortlabel, "NO NAME    ",11);
+	else
+		label_name(label, 0, &mangled, shortlabel);
+	strncpy(labelBlock->label, shortlabel, 11);
+	sprintf(labelBlock->fat_type, "FAT%2.2d  ", Fs.fat_bits);
+	labelBlock->fat_type[7] = ' ';
+
+	set_word(boot->secsiz, Fs.sector_size);
+	boot->clsiz = (unsigned char) Fs.cluster_size;
+	set_word(boot->nrsvsect, Fs.fat_start);
+
+	bootOffset = init_geometry_boot(boot, &used_dev, sectors0, 
+					rate_0, rate_any,
+					&tot_sectors, keepBoot);
+	if(!bootOffset) {
+		bootOffset = ((char *) labelBlock) - ((char *) boot) +
+			sizeof(struct label_blk_t);
+	}
+	if(Atari) {
+		boot->banner[4] = 0;
+		boot->banner[5] = random();
+		boot->banner[6] = random();
+		boot->banner[7] = random();
+	}		
+
+	if (create) {
+		WRITES(Fs.Direct, (char *) buf,
+		       sectorsToBytes((Stream_t*)&Fs, tot_sectors-1),
+		       Fs.sector_size);
+	}
+
+	if(!keepBoot)
+		inst_boot_prg(boot, bootOffset);
+	if(dev->use_2m & 0x7f)
+		Fs.num_fat = 1;
+	Fs.lastFatSectorNr = 0;
+	Fs.lastFatSectorData = 0;
+	zero_fat(&Fs, boot->descr);
+	Fs.freeSpace = Fs.num_clus;
+	Fs.last = 2;
+
+#ifdef USE_XDF
+	if(format_xdf)
+		for(i=0; 
+		    i < (info.BadSectors+Fs.cluster_size-1)/Fs.cluster_size; 
+		    i++)
+			fatEncode(&Fs, i+2, 0xfff7);
+#endif
+
+	format_root(&Fs, label, boot);
+	WRITES((Stream_t *)&Fs, (char *) boot, (mt_off_t) 0, Fs.sector_size);
+	if(Fs.fat_bits == 32 && WORD(ext.fat32.backupBoot) != MAX32) {
+		WRITES((Stream_t *)&Fs, (char *) boot, 
+		       sectorsToBytes((Stream_t*)&Fs, WORD(ext.fat32.backupBoot)),
+		       Fs.sector_size);
+	}
+	FLUSH((Stream_t *)&Fs); /* flushes Fs. 
+				 * This triggers the writing of the FAT */
+	FREE(&Fs.Next);
+	Fs.Class->freeFunc((Stream_t *)&Fs);
+#ifdef USE_XDF
+	if(format_xdf && isatty(0) && !getenv("MTOOLS_USE_XDF"))
+		fprintf(stderr,
+			"Note:\n"
+			"Remember to set the \"MTOOLS_USE_XDF\" environmental\n"
+			"variable before accessing this disk\n\n"
+			"Bourne shell syntax (sh, ash, bash, ksh, zsh etc):\n"
+			" export MTOOLS_USE_XDF=1\n\n"
+			"C shell syntax (csh and tcsh):\n"
+			" setenv MTOOLS_USE_XDF 1\n" );	
+#endif
+	exit(0);
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/minfo.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/minfo.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/minfo.c	(revision 9)
@@ -0,0 +1,172 @@
+/*
+ * mlabel.c
+ * Make an MSDOS volume label
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mainloop.h"
+#include "vfat.h"
+#include "mtools.h"
+#include "nameclash.h"
+
+static void usage(void)
+{
+	fprintf(stderr, 
+		"Mtools version %s, dated %s\n", mversion, mdate);
+	fprintf(stderr, 
+		"Usage: %s [-v] drive\n\t-v Verbose\n", progname);
+	exit(1);
+}
+
+
+static void displayInfosector(Stream_t *Stream, struct bootsector *boot)
+{
+	InfoSector_t *infosec;
+
+	if(WORD(ext.fat32.infoSector) == MAX32)
+		return;
+
+	infosec = (InfoSector_t *) safe_malloc(WORD(secsiz));
+	force_read(Stream, (char *) infosec, 
+			   (mt_off_t) WORD(secsiz) * WORD(ext.fat32.infoSector),
+			   WORD(secsiz));
+	printf("\nInfosector:\n");
+	printf("signature=0x%08x\n", _DWORD(infosec->signature1));
+	if(_DWORD(infosec->count) != MAX32)
+		printf("free clusters=%u\n", _DWORD(infosec->count));
+	if(_DWORD(infosec->pos) != MAX32)
+		printf("last allocated cluster=%u\n", _DWORD(infosec->pos));
+}
+
+
+void minfo(int argc, char **argv, int type)
+{
+	struct bootsector boot0;
+#define boot (&boot0)
+	char name[EXPAND_BUF];
+	int media;
+	int tot_sectors;
+	struct device dev;
+	char *drive;
+	int verbose=0;
+	int c;
+	Stream_t *Stream;
+	struct label_blk_t *labelBlock;
+	
+	while ((c = getopt(argc, argv, "v")) != EOF) {
+		switch (c) {
+			case 'v':
+				verbose = 1;
+				break;
+			default:
+				usage();
+		}
+	}
+
+	if(argc == optind)
+		usage();
+
+	for(;optind < argc; optind++) {
+		if(skip_drive(argv[optind]) == argv[optind])
+			usage();
+		drive = get_drive(argv[optind], NULL);
+
+		if(! (Stream = find_device(drive, O_RDONLY, &dev, boot, 
+					   name, &media, 0)))
+			exit(1);
+
+		tot_sectors = DWORD(bigsect);
+		SET_INT(tot_sectors, WORD(psect));
+		printf("device information:\n");
+		printf("===================\n");
+		printf("filename=\"%s\"\n", name);
+		printf("sectors per track: %d\n", dev.sectors);
+		printf("heads: %d\n", dev.heads);
+		printf("cylinders: %d\n\n", dev.tracks);
+		printf("mformat command line: mformat -t %d -h %d -s %d ",
+		       dev.tracks, dev.heads, dev.sectors);
+		if(DWORD(nhs))
+			printf("-H %d ", DWORD(nhs));
+		printf("%s:\n", drive);
+		printf("\n");
+		
+		printf("bootsector information\n");
+		printf("======================\n");
+		printf("banner:\"%8s\"\n", boot->banner);
+		printf("sector size: %d bytes\n", WORD(secsiz));
+		printf("cluster size: %d sectors\n", boot->clsiz);
+		printf("reserved (boot) sectors: %d\n", WORD(nrsvsect));
+		printf("fats: %d\n", boot->nfat);
+		printf("max available root directory slots: %d\n", 
+		       WORD(dirents));
+		printf("small size: %d sectors\n", WORD(psect));
+		printf("media descriptor byte: 0x%x\n", boot->descr);
+		printf("sectors per fat: %d\n", WORD(fatlen));
+		printf("sectors per track: %d\n", WORD(nsect));
+		printf("heads: %d\n", WORD(nheads));
+		printf("hidden sectors: %d\n", DWORD(nhs));
+		printf("big size: %d sectors\n", DWORD(bigsect));
+
+		if(WORD(fatlen)) {
+		    labelBlock = &boot->ext.old.labelBlock;
+		} else {
+		    labelBlock = &boot->ext.fat32.labelBlock;
+		}
+
+		printf("physical drive id: 0x%x\n", 
+		       labelBlock->physdrive);
+		printf("reserved=0x%x\n", 
+		       labelBlock->reserved);
+		printf("dos4=0x%x\n", 
+		       labelBlock->dos4);
+		printf("serial number: %08X\n", 
+		       _DWORD(labelBlock->serial));
+		printf("disk label=\"%11.11s\"\n", 
+		       labelBlock->label);
+		printf("disk type=\"%8.8s\"\n", 
+		       labelBlock->fat_type);
+
+		if(!WORD(fatlen)){
+			printf("Big fatlen=%u\n",
+			       DWORD(ext.fat32.bigFat));
+			printf("Extended flags=0x%04x\n",
+			       WORD(ext.fat32.extFlags));
+			printf("FS version=0x%04x\n",
+			       WORD(ext.fat32.fsVersion));
+			printf("rootCluster=%u\n",
+			       DWORD(ext.fat32.rootCluster));
+			if(WORD(ext.fat32.infoSector) != MAX32)
+				printf("infoSector location=%d\n",
+				       WORD(ext.fat32.infoSector));
+			if(WORD(ext.fat32.backupBoot) != MAX32)
+				printf("backup boot sector=%d\n",
+				       WORD(ext.fat32.backupBoot));
+			displayInfosector(Stream,boot);
+		}
+
+		if(verbose) {
+			int size;
+			unsigned char *buf;
+
+			printf("\n");
+			size = WORD(secsiz);
+			
+			buf = (unsigned char *) malloc(size);
+			if(!buf) {
+				fprintf(stderr, "Out of memory error\n");
+				exit(1);
+			}
+
+			size = READS(Stream, buf, (mt_off_t) 0, size);
+			if(size < 0) {
+				perror("read boot sector");
+				exit(1);
+			}
+
+			print_sector("Boot sector hexdump", buf, size);
+		}
+	}
+
+	exit(0);
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/misc.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/misc.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/misc.c	(revision 9)
@@ -0,0 +1,307 @@
+/*
+ * Miscellaneous routines.
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "stream.h"
+#include "vfat.h"
+#include "mtools.h"
+
+
+void printOom(void)
+{
+	fprintf(stderr, "Out of memory error");
+}
+
+char *get_homedir(void)
+{
+	struct passwd *pw;
+	uid_t uid;
+	char *homedir;
+	char *username;
+	
+	homedir = getenv ("HOME");    
+	/* 
+	 * first we call getlogin. 
+	 * There might be several accounts sharing one uid 
+	 */
+	if ( homedir )
+		return homedir;
+	
+	pw = 0;
+	
+	username = getenv("LOGNAME");
+	if ( !username )
+		username = getlogin();
+	if ( username )
+		pw = getpwnam( username);
+  
+	if ( pw == 0 ){
+		/* if we can't getlogin, look up the pwent by uid */
+		uid = geteuid();
+		pw = getpwuid(uid);
+	}
+	
+	/* we might still get no entry */
+	if ( pw )
+		return pw->pw_dir;
+	return 0;
+}
+
+
+static void get_mcwd_file_name(char *file)
+{
+	char *mcwd_path;
+	char *homedir;
+
+	mcwd_path = getenv("MCWD");
+	if (mcwd_path == NULL || *mcwd_path == '\0'){
+		homedir= get_homedir();
+		if(!homedir)
+			homedir="/tmp";
+		strncpy(file, homedir, MAXPATHLEN-6);
+		file[MAXPATHLEN-6]='\0';
+		strcat( file, "/.mcwd");
+	} else {
+		strncpy(file, mcwd_path, MAXPATHLEN);
+		file[MAXPATHLEN]='\0';
+	}
+}
+
+void unlink_mcwd()
+{
+	char file[MAXPATHLEN+1];
+	get_mcwd_file_name(file);
+	unlink(file);
+}
+
+FILE *open_mcwd(const char *mode)
+{
+	struct stat sbuf;
+	char file[MAXPATHLEN+1];
+	time_t now;
+	
+	get_mcwd_file_name(file);
+	if (*mode == 'r'){
+		if (stat(file, &sbuf) < 0)
+			return NULL;
+		/*
+		 * Ignore the info, if the file is more than 6 hours old
+		 */
+		getTimeNow(&now);
+		if (now - sbuf.st_mtime > 6 * 60 * 60) {
+			fprintf(stderr,
+				"Warning: \"%s\" is out of date, removing it\n",
+				file);
+			unlink(file);
+			return NULL;
+		}
+	}
+	
+	return  fopen(file, mode);
+}
+	
+
+/* Fix the info in the MCWD file to be a proper directory name.
+ * Always has a leading separator.  Never has a trailing separator
+ * (unless it is the path itself).  */
+
+const char *fix_mcwd(char *ans)
+{
+	FILE *fp;
+	char *s;
+	char buf[MAX_PATH];
+
+	fp = open_mcwd("r");
+	if(!fp){
+		strcpy(ans, "A:/");
+		return ans;
+	}
+
+	if (!fgets(buf, MAX_PATH, fp))
+		return("A:/");
+
+	buf[strlen(buf) -1] = '\0';
+	fclose(fp);
+					/* drive letter present? */
+	s = skip_drive(buf);
+	if (s > buf) {
+		strncpy(ans, buf, s - buf);
+		ans[s - buf] = '\0';
+	} else 
+		strcpy(ans, "A:");
+					/* add a leading separator */
+	if (*s != '/' && *s != '\\') {
+		strcat(ans, "/");
+		strcat(ans, s);
+	} else
+		strcat(ans, s);
+
+#if 0
+					/* translate to upper case */
+	for (s = ans; *s; ++s) {
+		*s = toupper(*s);
+		if (*s == '\\')
+			*s = '/';
+	}
+#endif
+					/* if only drive, colon, & separator */
+	if (strlen(ans) == 3)
+		return(ans);
+					/* zap the trailing separator */
+	if (*--s == '/')
+		*s = '\0';
+	return ans;
+}
+
+void *safe_malloc(size_t size)
+{
+	void *p;
+
+	p = malloc(size);
+	if(!p){
+		printOom();
+		exit(1);
+	}
+	return p;
+}
+
+void print_sector(char *message, unsigned char *data, int size)
+{
+	int col;
+	int row;
+
+	printf("%s:\n", message);
+	
+	for(row = 0; row * 16 < size; row++){
+		printf("%03x  ", row * 16);
+		for(col = 0; col < 16; col++)			
+			printf("%02x ", data [row*16+col]);
+		for(col = 0; col < 16; col++) {
+			if(isprint(data [row*16+col]))
+				printf("%c", data [row*16+col]);
+			else
+				printf(".");
+		}
+		printf("\n");
+	}
+}
+
+
+time_t getTimeNow(time_t *now)
+{
+	static int haveTime = 0;
+	static time_t sharedNow;
+
+	if(!haveTime) {
+		time(&sharedNow);
+		haveTime = 1;
+	}
+	if(now)
+		*now = sharedNow;
+	return sharedNow;
+}
+
+char *skip_drive(const char *filename)
+{
+	char *p;
+
+	/* Skip drive name.  Return pointer just after the `:', or a pointer
+	 * to the start of the file name if there is is no drive name.
+	 */
+	p = strchr(filename, ':');
+	return (p == NULL || p == filename) ? (char *) filename : p + 1;
+}
+
+char *get_drive(const char *filename, const char *def)
+{
+	const char *path;
+	char *drive;
+	const char *rest;
+	size_t len;
+
+	/* Return the drive name part of a full filename. */
+
+	path = filename;
+	rest = skip_drive(path);
+	if (rest == path) {
+		if (def == NULL) def = "A:";
+		path = def;
+		rest = skip_drive(path);
+		if (rest == path) {
+			path = "A:";
+			rest = path+2;
+		}
+	}
+	len = rest - path;
+	drive = safe_malloc(len * sizeof(drive[0]));
+	len--;
+	memcpy(drive, path, len);
+	drive[len] = 0;
+	if (len == 1) drive[0] = toupper(drive[0]);
+	return drive;
+}
+
+#if 0
+
+#undef free
+#undef malloc
+
+static int total=0;
+
+void myfree(void *ptr)
+{
+	int *size = ((int *) ptr)-1;
+	total -= *size;
+	fprintf(stderr, "freeing %d bytes at %p total alloced=%d\n",
+		*size, ptr, total);
+	free(size);
+}
+
+void *mymalloc(size_t size)
+{
+	int *ptr;
+	ptr = (int *)malloc(size+sizeof(int));
+	if(!ptr)
+		return 0;
+	*ptr = size;
+	ptr++;
+	total += size;
+	fprintf(stderr, "allocating %d bytes at %p total allocated=%d\n",
+		size, ptr, total);
+	return (void *) ptr;
+}
+
+void *mycalloc(size_t nmemb, size_t size)
+{
+	void *ptr = mymalloc(nmemb * size);
+	if(!ptr)
+		return 0;
+	memset(ptr, 0, size);
+	return ptr;
+}
+
+void *myrealloc(void *ptr, size_t size)
+{
+	int oldsize = ((int *)ptr) [-1];
+	void *new = mymalloc(size);
+	if(!new)
+		return 0;
+	memcpy(new, ptr, oldsize);
+	myfree(ptr);
+	return new;
+}
+
+char *mystrdup(char *src)
+{
+	char *dest;
+	dest = mymalloc(strlen(src)+1);
+	if(!dest)
+		return 0;
+	strcpy(dest, src);
+	return dest;
+}
+
+
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/missFuncs.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/missFuncs.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/missFuncs.c	(revision 9)
@@ -0,0 +1,386 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+This file contains excerpts of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include "sysincludes.h"
+#include "mtools.h"
+
+#ifndef HAVE_STRDUP
+
+
+char *strdup(const char *str)
+{
+    char *nstr;
+
+    if (str == (char*)0)
+        return 0;
+
+    nstr = (char*)malloc((strlen(str) + 1));
+
+    if (nstr == (char*)0)
+    {
+        (void)fprintf(stderr, "strdup(): not enough memory to duplicate `%s'\n",
+		      str);
+	exit(1);
+    }
+
+    (void)strcpy(nstr, str);
+
+    return nstr;
+}
+#endif /* HAVE_STRDUP */
+
+
+#ifndef HAVE_MEMCPY
+/*
+ * Copy contents of memory (with possible overlapping).
+ */
+char *memcpy(char *s1, const char *s2, size_t n)
+{
+	bcopy(s2, s1, n);
+	return(s1);
+}
+#endif
+
+#ifndef HAVE_MEMSET
+/*
+ * Copies the character c, n times to string s
+ */
+char *memset(char *s, char c, size_t n)
+{
+	char *s1 = s;
+
+	while (n > 0) {
+		--n;
+		*s++ = c;
+	}
+	return(s1);
+}
+#endif /* HAVE_MEMSET */
+
+
+#ifndef HAVE_STRCHR
+
+char * strchr (const char* s, int c)
+{
+	if (!s) return NULL;
+	while (*s && *s != c) s++;
+	if (*s) 
+		return (char*) s;
+	else
+		return NULL;
+}
+
+#endif
+
+#ifndef HAVE_STRRCHR
+
+char * strrchr (const char* s1, int c) 
+{
+	char* s = (char*) s1;
+	char* start = (char*) s;
+	if (!s) return NULL;
+	s += strlen(s)-1;
+	while (*s != c && (unsigned long) s != (unsigned long) start) s--;
+	if ((unsigned long) s == (unsigned long) start && *s != c)
+		return NULL;
+	else
+		return s;
+}
+
+#endif
+
+#ifndef HAVE_STRPBRK
+/*
+ * Return ptr to first occurrence of any character from `brkset'
+ * in the character string `string'; NULL if none exists.
+ */
+char *strpbrk(const char *string, const char *brkset)
+{
+	register char *p;
+
+	if (!string || !brkset)
+		return(0);
+	do {
+		for (p = brkset; *p != '\0' && *p != *string; ++p)
+			;
+		if (*p != '\0')
+			return(string);
+	}
+	while (*string++);
+	return(0);
+}
+#endif /* HAVE_STRPBRK */
+
+
+#ifndef HAVE_STRTOUL
+static int getdigit(char a, int max)
+{
+	int dig;
+	
+	if(a < '0')
+		return -1;
+	if(a <= '9') {
+		dig = a - '0';
+	} else if(a >= 'a')
+		dig = a - 'a' + 10;
+	else if(a >= 'A')
+		dig = a - 'A' + 10;
+	if(dig >= max)
+		return -1;
+	else
+		return dig;
+}
+
+unsigned long strtoul(const char *string, char **eptr, int base)
+{
+	int accu, dig;
+
+	if(base < 1 || base > 36) {
+		if(string[0] == '0') {
+			switch(string[1]) {
+			       	case 'x':
+				case 'X':
+					return strtoul(string+2, eptr, 16);
+				case 'b':
+			       	case 'B':
+					return strtoul(string+2, eptr, 2);
+				default:
+					return strtoul(string, eptr, 8);
+			}
+		}
+	       	return strtoul(string, eptr, 10);
+	}
+	if(base == 16 && string[0] == '0' &&
+	   (string[1] == 'x' || string[1] == 'X'))
+		string += 2;
+
+	if(base == 2 && string[0] == '0' &&
+	   (string[1] == 'b' || string[1] == 'B'))
+		string += 2;
+	accu = 0;
+	while( (dig = getdigit(*string, base)) != -1 ) {
+		accu = accu * base + dig;
+		string++;
+	}
+	if(eptr)
+		*eptr = (char *) string;
+	return accu;
+}
+#endif /* HAVE_STRTOUL */
+
+#ifndef HAVE_STRTOL
+long strtol(const char *string, char **eptr, int base)
+{
+	long l;
+
+	if(*string == '-') {
+		return -(long) strtoul(string+1, eptr, base);
+	} else {
+		if (*string == '+')
+			string ++;
+		return (long) strtoul(string, eptr, base);
+	}
+}
+#endif
+
+
+
+#ifndef HAVE_STRSPN
+/* Return the length of the maximum initial segment
+   of S which contains only characters in ACCEPT.  */
+size_t strspn(const char *s, const char *accept)
+{
+  register char *p;
+  register char *a;
+  register size_t count = 0;
+
+  for (p = s; *p != '\0'; ++p)
+    {
+      for (a = accept; *a != '\0'; ++a)
+	if (*p == *a)
+	  break;
+      if (*a == '\0')
+	return count;
+      else
+	++count;
+    }
+
+  return count;
+}
+#endif /* HAVE_STRSPN */
+
+#ifndef HAVE_STRCSPN
+/* Return the length of the maximum inital segment of S
+   which contains no characters from REJECT.  */
+size_t strcspn (const char *s, const char *reject)
+{
+  register size_t count = 0;
+
+  while (*s != '\0')
+    if (strchr (reject, *s++) == NULL)
+      ++count;
+    else
+      return count;
+
+  return count;
+}
+
+#endif /* HAVE_STRCSPN */
+
+#ifndef HAVE_STRERROR
+
+#ifndef DECL_SYS_ERRLIST
+extern char *sys_errlist[];
+#endif
+
+char *strerror(int errno)
+{
+  return sys_errlist[errno];
+}
+#endif
+
+#ifndef HAVE_STRCASECMP
+/* Compare S1 and S2, ignoring case, returning less than, equal to or
+   greater than zero if S1 is lexiographically less than,
+   equal to or greater than S2.  */
+int strcasecmp(const char *s1, const char *s2)
+{
+  register const unsigned char *p1 = (const unsigned char *) s1;
+  register const unsigned char *p2 = (const unsigned char *) s2;
+  unsigned char c1, c2;
+
+  if (p1 == p2)
+    return 0;
+
+  do
+    {
+      c1 = tolower (*p1++);
+      c2 = tolower (*p2++);
+      if (c1 == '\0')
+	break;
+    }
+  while (c1 == c2);
+
+  return c1 - c2;
+}
+#endif
+
+
+
+#ifndef HAVE_STRCASECMP
+/* Compare S1 and S2, ignoring case, returning less than, equal to or
+   greater than zero if S1 is lexiographically less than,
+   equal to or greater than S2.  */
+int strncasecmp(const char *s1, const char *s2, size_t n)
+{
+  register const unsigned char *p1 = (const unsigned char *) s1;
+  register const unsigned char *p2 = (const unsigned char *) s2;
+  unsigned char c1, c2;
+
+  if (p1 == p2)
+    return 0;
+
+  c1 = c2 = 1;
+  while (c1 && c1 == c2 && n-- > 0)
+    {
+      c1 = tolower (*p1++);
+      c2 = tolower (*p2++);
+    }
+
+  return c1 - c2;
+}
+#endif
+
+#ifndef HAVE_GETPASS
+char *getpass(const char *prompt)
+{
+	static char password[129];
+	int l;
+
+	fprintf(stderr,"%s",prompt);
+	fgets(password, 128, stdin);
+	l = strlen(password);
+	if(l && password[l-1] == '\n')
+		password[l-1] = '\0';
+	return password;
+
+}
+#endif
+
+#ifndef HAVE_ATEXIT
+
+#ifdef HAVE_ON_EXIT
+int atexit(void (*function)(void))
+{
+	return on_exit( (void(*)(int,void*)) function, 0);
+}
+#else
+
+typedef struct exitCallback {
+	void (*function) (void);
+	struct exitCallback *next;
+} exitCallback_t;
+
+static exitCallback_t *callback = 0;
+
+int atexit(void (*function) (void))
+{
+	exitCallback_t *newCallback;
+		
+	newCallback = New(exitCallback_t);
+	if(!newCallback) {
+		printOom();
+		exit(1);
+	}
+	newCallback->function = function;
+	newCallback->next = callback;
+	callback = newCallback;
+	return 0;
+}
+#undef exit
+
+void myexit(int code)
+{
+  void (*function)(void);
+
+  while(callback) {
+    function = callback->function;
+    callback = callback->next;
+    function();
+  }
+  exit(code);
+}
+
+#endif
+
+#endif
+
+/*#ifndef HAVE_BASENAME*/
+const char *_basename(const char *filename)
+{
+	char *ptr;
+
+	ptr = strrchr(filename, '/');
+	if(ptr)
+		return ptr+1;
+	else
+		return filename;
+}
+/*#endif*/
+
+
Index: /trunk/minix/commands/i386/mtools-3.9.7/mk_direntry.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mk_direntry.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mk_direntry.c	(revision 9)
@@ -0,0 +1,618 @@
+/*
+ * mk_direntry.c
+ * Make new directory entries, and handles name clashes
+ *
+ */
+
+/*
+ * This file is used by those commands that need to create new directory entries
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "vfat.h"
+#include "nameclash.h"
+#include "fs.h"
+#include "stream.h"
+#include "mainloop.h"
+
+static inline int ask_rename(ClashHandling_t *ch,
+			     char *longname, int isprimary, char *argname)
+{
+	char shortname[13];
+	int mangled;
+
+	/* TODO: Would be nice to suggest "autorenamed" version of name, press 
+	 * <Return> to get it.
+	 */
+#if 0
+	fprintf(stderr,"Entering ask_rename, isprimary=%d.\n", isprimary);
+#endif
+
+	if(!opentty(0))
+		return 0;
+
+#define maxsize (isprimary ?  MAX_VNAMELEN+1 : 11+1)
+#define name (isprimary ? argname : shortname)
+
+	mangled = 0;
+	do {
+		fprintf(stderr, "New %s name for \"%s\": ",
+			isprimary ? "primary" : "secondary", longname);
+		fflush(stderr);
+		if (! fgets(name, maxsize, opentty(0)))
+			return 0;
+
+		/* Eliminate newline(s) in the file name */
+		name[strlen(name)-1]='\0';
+		if (!isprimary)
+			ch->name_converter(shortname,0, &mangled, argname);
+	} while (mangled & 1);
+	return 1;
+#undef maxsize
+#undef name
+}
+
+static inline clash_action ask_namematch(char *name, int isprimary, 
+					 ClashHandling_t *ch, int no_overwrite,
+					 int reason)
+{
+	char ans[10];
+	clash_action a;
+	int perm;
+	char unix_shortname[13];
+
+
+#define EXISTS 0
+#define RESERVED 1
+#define ILLEGALS 2
+
+	static const char *reasons[]= {
+		"already exists",
+		"is reserved",
+		"contains illegal character(s)"};
+
+
+	if (!isprimary)
+		name = unix_normalize(unix_shortname, name, name+8);
+
+	a = ch->action[isprimary];
+
+	if(a == NAMEMATCH_NONE && !opentty(1)) {
+		/* no default, and no tty either . Skip the troublesome file */
+		return NAMEMATCH_SKIP;
+	}
+
+	perm = 0;
+	while (a == NAMEMATCH_NONE) {
+		fprintf(stderr, "%s file name \"%s\" %s.\n",
+			isprimary ? "Long" : "Short", name, reasons[reason]);
+		fprintf(stderr,
+			"a)utorename A)utorename-all r)ename R)ename-all ");
+		if(!no_overwrite)
+			fprintf(stderr,"o)verwrite O)verwrite-all");
+		fprintf(stderr,
+			"\ns)kip S)kip-all q)uit (aArR");
+		if(!no_overwrite)
+			fprintf(stderr,"oO");
+		fprintf(stderr,"sSq): ");
+		fflush(stderr);
+		fflush(opentty(1));
+		if (mtools_raw_tty) {
+			int rep;
+			rep = fgetc(opentty(1));			
+			fputs("\n", stderr);
+			if(rep == EOF)
+				ans[0] = 'q';
+			else
+				ans[0] = rep;
+		} else {
+			fgets(ans, 9, opentty(0));
+		}
+		perm = isupper((unsigned char)ans[0]);
+		switch(tolower((unsigned char)ans[0])) {
+			case 'a':
+				a = NAMEMATCH_AUTORENAME;
+				break;
+			case 'r':
+				if(isprimary)
+					a = NAMEMATCH_PRENAME;
+				else
+					a = NAMEMATCH_RENAME;
+				break;
+			case 'o':
+				if(no_overwrite)
+					continue;
+				a = NAMEMATCH_OVERWRITE;
+				break;
+			case 's':
+				a = NAMEMATCH_SKIP;
+				break;
+			case 'q':
+				perm = 0;
+				a = NAMEMATCH_QUIT;
+				break;
+			default:
+				perm = 0;
+		}
+	}
+
+	/* Keep track of this action in case this file collides again */
+	ch->action[isprimary]  = a;
+	if (perm)
+		ch->namematch_default[isprimary] = a;
+
+	/* if we were asked to overwrite be careful. We can't set the action
+	 * to overwrite, else we get won't get a chance to specify another
+	 * action, should overwrite fail. Indeed, we'll be caught in an
+	 * infinite loop because overwrite will fail the same way for the
+	 * second time */
+	if(a == NAMEMATCH_OVERWRITE)
+		ch->action[isprimary] = NAMEMATCH_NONE;
+	return a;
+}
+
+/* Returns:
+ * 2 if file is to be overwritten
+ * 1 if file was renamed
+ * 0 if it was skipped
+ *
+ * If a short name is involved, handle conversion between the 11-character
+ * fixed-length record DOS name and a literal null-terminated name (e.g.
+ * "COMMAND  COM" (no null) <-> "COMMAND.COM" (null terminated)).
+ *
+ * Also, immediately copy the original name so that messages can use it.
+ */
+static inline clash_action process_namematch(char *name,
+					     char *longname,
+					     int isprimary,
+					     ClashHandling_t *ch,
+					     int no_overwrite,
+					     int reason)
+{
+	clash_action action;
+
+#if 0
+	fprintf(stderr,
+		"process_namematch: name=%s, default_action=%d, ask=%d.\n",
+		name, default_action, ch->ask);
+#endif
+
+	action = ask_namematch(name, isprimary, ch, no_overwrite, reason);
+
+	switch(action){
+	case NAMEMATCH_QUIT:
+		got_signal = 1;
+		return NAMEMATCH_SKIP;
+	case NAMEMATCH_SKIP:
+		return NAMEMATCH_SKIP;
+	case NAMEMATCH_RENAME:
+	case NAMEMATCH_PRENAME:
+		/* We need to rename the file now.  This means we must pass
+		 * back through the loop, a) ensuring there isn't a potential
+		 * new name collision, and b) finding a big enough VSE.
+		 * Change the name, so that it won't collide again.
+		 */
+		ask_rename(ch, longname, isprimary, name);
+		return action;
+	case NAMEMATCH_AUTORENAME:
+		/* Very similar to NAMEMATCH_RENAME, except that we need to
+		 * first generate the name.
+		 * TODO: Remember previous name so we don't
+		 * keep trying the same one.
+		 */
+		if (isprimary) {
+			autorename_long(name, 1);
+			return NAMEMATCH_PRENAME;
+		} else {
+			autorename_short(name, 1);
+			return NAMEMATCH_RENAME;
+		}
+	case NAMEMATCH_OVERWRITE:
+		if(no_overwrite)
+			return NAMEMATCH_SKIP;
+		else
+			return NAMEMATCH_OVERWRITE;
+	default:
+		return NAMEMATCH_NONE;
+	}
+}
+
+
+static void clear_scan(char *longname, int use_longname, struct scan_state *s)
+{
+	s->shortmatch = s->longmatch = s->slot = -1;
+	s->free_end = s->got_slots = s->free_start = 0;
+
+	if (use_longname & 1)
+                s->size_needed = 2 + (strlen(longname)/VSE_NAMELEN);
+	else
+                s->size_needed = 1;
+}
+
+
+static int contains_illegals(const char *string, const char *illegals)
+{
+	for(; *string ; string++)
+		if((*string < ' ' && *string != '\005' && !(*string & 0x80)) ||
+		   strchr(illegals, *string))
+			return 1;
+	return 0;
+}
+
+static int is_reserved(char *ans, int islong)
+{
+	int i;
+	static const char *dev3[] = {"CON", "AUX", "PRN", "NUL", "   "};
+	static const char *dev4[] = {"COM", "LPT" };
+
+	for (i = 0; i < sizeof(dev3)/sizeof(*dev3); i++)
+		if (!strncasecmp(ans, dev3[i], 3) &&
+		    ((islong && !ans[3]) ||
+		     (!islong && !strncmp(ans+3,"     ",5))))
+			return 1;
+
+	for (i = 0; i < sizeof(dev4)/sizeof(*dev4); i++)
+		if (!strncasecmp(ans, dev4[i], 3) &&
+		    (ans[3] >= '1' && ans[3] <= '4') &&
+		    ((islong && !ans[4]) ||
+		     (!islong && !strncmp(ans+4,"    ",4))))
+			return 1;
+	
+	return 0;
+}
+
+static inline clash_action get_slots(Stream_t *Dir,
+				     char *dosname, char *longname,
+				     struct scan_state *ssp,
+				     ClashHandling_t *ch)
+{
+	int error;
+	clash_action ret;
+	int match=0;
+	direntry_t entry;
+	int isprimary;
+	int no_overwrite;
+	int reason;
+	int pessimisticShortRename;
+
+	pessimisticShortRename = (ch->action[0] == NAMEMATCH_AUTORENAME);
+
+	entry.Dir = Dir;
+	no_overwrite = 1;
+	if((is_reserved(longname,1)) ||
+	   longname[strspn(longname,". ")] == '\0'){
+		reason = RESERVED;
+		isprimary = 1;
+	} else if(contains_illegals(longname,long_illegals)) {
+		reason = ILLEGALS;
+		isprimary = 1;
+	} else if(is_reserved(dosname,0)) {
+		reason = RESERVED;
+		ch->use_longname = 1;
+		isprimary = 0;
+	} else if(contains_illegals(dosname,short_illegals)) {
+		reason = ILLEGALS;
+		ch->use_longname = 1;
+		isprimary = 0;
+	} else {
+		reason = EXISTS;
+		clear_scan(longname, ch->use_longname, ssp);
+		switch (lookupForInsert(Dir, dosname, longname, ssp,
+								ch->ignore_entry, 
+								ch->source_entry,
+								pessimisticShortRename && 
+								ch->use_longname)) {
+			case -1:
+				return NAMEMATCH_ERROR;
+				
+			case 0:
+				return NAMEMATCH_SKIP; 
+				/* Single-file error error or skip request */
+				
+			case 5:
+				return NAMEMATCH_GREW;
+				/* Grew directory, try again */
+				
+			case 6:
+				return NAMEMATCH_SUCCESS; /* Success */
+		}	    
+		match = -2;
+		if (ssp->longmatch > -1) {
+			/* Primary Long Name Match */
+#ifdef debug
+			fprintf(stderr,
+				"Got longmatch=%d for name %s.\n", 
+				longmatch, longname);
+#endif			
+			match = ssp->longmatch;
+			isprimary = 1;
+		} else if ((ch->use_longname & 1) && (ssp->shortmatch != -1)) {
+			/* Secondary Short Name Match */
+#ifdef debug
+			fprintf(stderr,
+				"Got secondary short name match for name %s.\n", 
+				longname);
+#endif
+
+			match = ssp->shortmatch;
+			isprimary = 0;
+		} else if (ssp->shortmatch >= 0) {
+			/* Primary Short Name Match */
+#ifdef debug
+			fprintf(stderr,
+				"Got primary short name match for name %s.\n", 
+				longname);
+#endif
+			match = ssp->shortmatch;
+			isprimary = 1;
+		} else 
+			return NAMEMATCH_RENAME;
+
+		if(match > -1) {
+			entry.entry = match;
+			dir_read(&entry, &error);
+			if (error)
+			    return NAMEMATCH_ERROR;
+			/* if we can't overwrite, don't propose it */
+			no_overwrite = (match == ch->source || IS_DIR(&entry));
+		}
+	}
+	ret = process_namematch(isprimary ? longname : dosname, longname,
+				isprimary, ch, no_overwrite, reason);
+	
+	if (ret == NAMEMATCH_OVERWRITE && match > -1){
+		if((entry.dir.attr & 0x5) &&
+		   (ask_confirmation("file is read only, overwrite anyway (y/n) ? ",0,0)))
+			return NAMEMATCH_RENAME;
+		
+		/* Free up the file to be overwritten */
+		if(fatFreeWithDirentry(&entry))
+			return NAMEMATCH_ERROR;
+		
+#if 0
+		if(isprimary &&
+		   match - ssp->match_free + 1 >= ssp->size_needed){
+			/* reuse old entry and old short name for overwrite */
+			ssp->free_start = match - ssp->size_needed + 1;
+			ssp->free_size = ssp->size_needed;
+			ssp->slot = match;
+			ssp->got_slots = 1;
+			strncpy(dosname, dir.name, 3);
+			strncpy(dosname + 8, dir.ext, 3);
+			return ret;
+		} else
+#endif
+			{
+			entry.dir.name[0] = DELMARK;
+			dir_write(&entry);
+			return NAMEMATCH_RENAME;
+		}
+	}
+
+	return ret;
+}
+
+
+static inline int write_slots(Stream_t *Dir,
+			      char *dosname, 
+			      char *longname,
+			      struct scan_state *ssp,
+			      write_data_callback *cb,
+			      void *arg,
+			      int Case)
+{
+	direntry_t entry;
+
+	/* write the file */
+	if (fat_error(Dir))
+		return 0;
+
+	entry.Dir = Dir;
+	entry.entry = ssp->slot;
+	strncpy(entry.name, longname, sizeof(entry.name)-1);
+	entry.name[sizeof(entry.name)-1]='\0';
+	entry.dir.Case = Case & (EXTCASE | BASECASE);
+	if (cb(dosname, longname, arg, &entry) >= 0) {
+		if ((ssp->size_needed > 1) &&
+		    (ssp->free_end - ssp->free_start >= ssp->size_needed)) {
+			ssp->slot = write_vfat(Dir, dosname, longname,
+					       ssp->free_start, &entry);
+		} else {
+			ssp->size_needed = 1;
+			write_vfat(Dir, dosname, 0,
+				   ssp->free_start, &entry);
+		}
+		/* clear_vses(Dir, ssp->free_start + ssp->size_needed, 
+		   ssp->free_end); */
+	} else
+		return 0;
+
+	return 1;	/* Successfully wrote the file */
+}
+
+static void stripspaces(char *name)
+{
+	char *p,*non_space;
+
+	non_space = name;
+	for(p=name; *p; p++)
+		if (*p != ' ')
+			non_space = p;
+	if(name[0])
+		non_space[1] = '\0';
+}
+
+
+int _mwrite_one(Stream_t *Dir,
+		char *argname,
+		char *shortname,
+		write_data_callback *cb,
+		void *arg,
+		ClashHandling_t *ch)
+{
+	char longname[VBUFSIZE];
+	const char *dstname;
+	char dosname[13];
+	int expanded;
+	struct scan_state scan;
+	clash_action ret;
+
+	expanded = 0;
+
+	if(isSpecial(argname)) {
+		fprintf(stderr, "Cannot create entry named . or ..\n");
+		return -1;
+	}
+
+	if(ch->name_converter == dos_name) {
+		if(shortname)
+			stripspaces(shortname);
+		if(argname)
+			stripspaces(argname);
+	}
+
+	if(shortname){
+		ch->name_converter(shortname,0, &ch->use_longname, dosname);
+		if(ch->use_longname & 1){
+			/* short name mangled, treat it as a long name */
+			argname = shortname;
+			shortname = 0;
+		}
+	}
+						
+	/* Skip drive letter */
+	dstname = skip_drive(argname);
+
+	/* Copy original argument dstname to working value longname */
+	strncpy(longname, dstname, VBUFSIZE-1);
+
+	if(shortname) {
+		ch->name_converter(shortname,0, &ch->use_longname, dosname);
+		if(strcmp(shortname, longname))
+			ch->use_longname |= 1;
+	} else
+		ch->name_converter(longname,0, &ch->use_longname, dosname);
+
+	ch->action[0] = ch->namematch_default[0];
+	ch->action[1] = ch->namematch_default[1];
+
+	while (1) {
+		switch((ret=get_slots(Dir, dosname, longname,
+				      &scan, ch))){
+			case NAMEMATCH_ERROR:
+				return -1;	/* Non-file-specific error, 
+						 * quit */
+				
+			case NAMEMATCH_SKIP:
+				return -1;	/* Skip file (user request or 
+						 * error) */
+
+			case NAMEMATCH_PRENAME:
+				ch->name_converter(longname,0,
+						   &ch->use_longname, dosname);
+				continue;
+			case NAMEMATCH_RENAME:
+				continue;	/* Renamed file, loop again */
+
+			case NAMEMATCH_GREW:
+				/* No collision, and not enough slots.
+				 * Try to grow the directory
+				 */
+				if (expanded) {	/* Already tried this 
+						 * once, no good */
+					fprintf(stderr, 
+						"%s: No directory slots\n",
+						progname);
+					return -1;
+				}
+				expanded = 1;
+				
+				if (dir_grow(Dir, scan.max_entry))
+					return -1;
+				continue;
+			case NAMEMATCH_OVERWRITE:
+			case NAMEMATCH_SUCCESS:
+				return write_slots(Dir, dosname, longname,
+						   &scan, cb, arg,
+						   ch->use_longname);
+			default:
+				fprintf(stderr,
+					"Internal error: clash_action=%d\n",
+					ret);
+				return -1;
+		}
+
+	}
+}
+
+int mwrite_one(Stream_t *Dir,
+	       const char *_argname,
+	       const char *_shortname,
+	       write_data_callback *cb,
+	       void *arg,
+	       ClashHandling_t *ch)
+{
+	char *argname;
+	char *shortname;
+	int ret;
+
+	if(_argname)
+		argname = strdup(_argname);
+	else
+		argname = 0;
+	if(_shortname)
+		shortname = strdup(_shortname);
+	else
+		shortname = 0;
+	ret = _mwrite_one(Dir, argname, shortname, cb, arg, ch);
+	if(argname)
+		free(argname);
+	if(shortname)
+		free(shortname);
+	return ret;
+}
+
+void init_clash_handling(ClashHandling_t *ch)
+{
+	ch->ignore_entry = -1;
+	ch->source_entry = -2;
+	ch->nowarn = 0;	/*Don't ask, just do default action if name collision */
+	ch->namematch_default[0] = NAMEMATCH_AUTORENAME;
+	ch->namematch_default[1] = NAMEMATCH_NONE;
+	ch->name_converter = dos_name; /* changed by mlabel */
+	ch->source = -2;
+}
+
+int handle_clash_options(ClashHandling_t *ch, char c)
+{
+	int isprimary;
+	if(isupper(c))
+		isprimary = 0;
+	else
+		isprimary = 1;
+	c = tolower(c);
+	switch(c) {
+		case 'o':
+			/* Overwrite if primary name matches */
+			ch->namematch_default[isprimary] = NAMEMATCH_OVERWRITE;
+			return 0;
+		case 'r':
+				/* Rename primary name interactively */
+			ch->namematch_default[isprimary] = NAMEMATCH_RENAME;
+			return 0;
+		case 's':
+			/* Skip file if primary name collides */
+			ch->namematch_default[isprimary] = NAMEMATCH_SKIP;
+			return 0;
+		case 'm':
+			ch->namematch_default[isprimary] = NAMEMATCH_NONE;
+			return 0;
+		case 'a':
+			ch->namematch_default[isprimary] = NAMEMATCH_AUTORENAME;
+			return 0;
+		default:
+			return -1;
+	}
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mlabel.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mlabel.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mlabel.c	(revision 9)
@@ -0,0 +1,251 @@
+/*
+ * mlabel.c
+ * Make an MSDOS volume label
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mainloop.h"
+#include "vfat.h"
+#include "mtools.h"
+#include "nameclash.h"
+
+char *label_name(char *filename, int verbose, 
+		 int *mangled, char *ans)
+{
+	int len;
+	int i;
+	int have_lower, have_upper;
+
+	strcpy(ans,"           ");
+	len = strlen(filename);
+	if(len > 11){
+		*mangled = 1;
+		len = 11;
+	} else
+		*mangled = 0;
+	strncpy(ans, filename, len);
+	have_lower = have_upper = 0;
+	for(i=0; i<11; i++){
+		if(islower((unsigned char)ans[i]))
+			have_lower = 1;
+		if(isupper(ans[i]))
+			have_upper = 1;
+		ans[i] = toupper((unsigned char)ans[i]);
+
+		if(strchr("^+=/[]:,?*\\<>|\".", ans[i])){
+			*mangled = 1;
+			ans[i] = '~';
+		}
+	}
+	if (have_lower && have_upper)
+		*mangled = 1;
+	return ans;
+}
+
+int labelit(char *dosname,
+	    char *longname,
+	    void *arg0,
+	    direntry_t *entry)
+{
+	time_t now;
+
+	/* find out current time */
+	getTimeNow(&now);
+	mk_entry(dosname, 0x8, 0, 0, now, &entry->dir);
+	return 0;
+}
+
+static void usage(void)
+{
+	fprintf(stderr, "Mtools version %s, dated %s\n",
+		mversion, mdate);
+	fprintf(stderr, "Usage: %s [-vscn] [-N serial] drive:[label]\n"
+		"\t-v Verbose\n"
+		"\t-s Show label\n"
+		"\t-c Clear label\n"
+		"\t-n New random serial number\n"
+		"\t-N New given serial number\n", progname);
+	exit(1);
+}
+
+
+void mlabel(int argc, char **argv, int type)
+{
+    
+	char *drive, *newLabel;
+	int verbose, clear, interactive, show, open_mode;
+	direntry_t entry;
+	int result=0;
+	char longname[VBUFSIZE];
+	char shortname[13];
+	ClashHandling_t ch;
+	struct MainParam_t mp;
+	Stream_t *RootDir;
+	int c;
+	int mangled;
+	enum { SER_NONE, SER_RANDOM, SER_SET }  set_serial = SER_NONE;
+	long serial = 0;
+	int need_write_boot = 0;
+	int have_boot = 0;
+	char *eptr = "";
+	struct bootsector boot;
+	Stream_t *Fs=0;
+	int r;
+	struct label_blk_t *labelBlock;
+
+	init_clash_handling(&ch);
+	ch.name_converter = label_name;
+	ch.ignore_entry = -2;
+
+	verbose = 0;
+	clear = 0;
+	show = 0;
+
+	while ((c = getopt(argc, argv, "vcsnN:")) != EOF) {
+		switch (c) {
+			case 'v':
+				verbose = 1;
+				break;
+			case 'c':
+				clear = 1;
+				break;
+			case 's':
+				show = 1;
+				break;
+			case 'n':
+				set_serial = SER_RANDOM;
+				srandom((long)time (0));
+				serial=random();
+				break;
+			case 'N':
+				set_serial = SER_SET;
+				serial = strtol(optarg, &eptr, 16);
+				if(*eptr) {
+					fprintf(stderr,
+						"%s not a valid serial number\n",
+						optarg);
+					exit(1);
+				}
+				break;
+			default:
+				usage();
+			}
+	}
+
+	if (argc - optind != 1 || skip_drive(argv[optind]) == argv[optind]) 
+		usage();
+
+	init_mp(&mp);
+	newLabel = skip_drive(argv[optind]);
+	interactive = !show && !clear &&!newLabel[0] && 
+		(set_serial == SER_NONE);
+	open_mode = O_RDWR;
+	drive = get_drive(argv[optind], NULL);
+	RootDir = open_root_dir(drive, open_mode);
+	if(strlen(newLabel) > VBUFSIZE) {
+		fprintf(stderr, "Label too long\n");
+		FREE(&RootDir);
+		exit(1);
+	}
+
+	if(!RootDir && open_mode == O_RDWR && !clear && !newLabel[0] &&
+	   ( errno == EACCES || errno == EPERM) ) {
+		show = 1;
+		interactive = 0;
+		RootDir = open_root_dir(drive, O_RDONLY);
+	}	    
+	if(!RootDir) {
+		fprintf(stderr, "%s: Cannot initialize drive\n", argv[0]);
+		exit(1);
+	}
+
+	initializeDirentry(&entry, RootDir);
+	r=vfat_lookup(&entry, 0, 0, ACCEPT_LABEL | MATCH_ANY,
+		      shortname, longname);
+	if (r == -2) {
+		FREE(&RootDir);
+		exit(1);
+	}
+
+	if(show || interactive){
+		if(isNotFound(&entry))
+			printf(" Volume has no label\n");
+		else if (*longname)
+			printf(" Volume label is %s (abbr=%s)\n",
+			       longname, shortname);
+		else
+			printf(" Volume label is %s\n", shortname);
+
+	}
+
+	/* ask for new label */
+	if(interactive){
+		newLabel = longname;
+		fprintf(stderr,"Enter the new volume label : ");
+		fgets(newLabel, VBUFSIZE, stdin);
+		if(newLabel[0])
+			newLabel[strlen(newLabel)-1] = '\0';
+	}
+
+	if((!show || newLabel[0]) && !isNotFound(&entry)){
+		/* if we have a label, wipe it out before putting new one */
+		if(interactive && newLabel[0] == '\0')
+			if(ask_confirmation("Delete volume label (y/n): ",0,0)){
+				FREE(&RootDir);
+				exit(0);
+			}		
+		entry.dir.name[0] = DELMARK;
+		entry.dir.attr = 0; /* for old mlabel */
+		dir_write(&entry);
+	}
+
+	if (newLabel[0] != '\0') {
+		ch.ignore_entry = 1;
+		result = mwrite_one(RootDir,newLabel,0,labelit,NULL,&ch) ? 
+		  0 : 1;
+	}
+
+	have_boot = 0;
+	if( (!show || newLabel[0]) || set_serial != SER_NONE) {
+		Fs = GetFs(RootDir);
+		have_boot = (force_read(Fs,(char *)&boot,0,sizeof(boot)) == 
+			     sizeof(boot));
+	}
+
+	if(_WORD(boot.fatlen)) {
+	    labelBlock = &boot.ext.old.labelBlock;
+	} else {
+	    labelBlock = &boot.ext.fat32.labelBlock;
+	}
+
+	if(!show || newLabel[0]){
+
+		if(!newLabel[0])
+			strncpy(shortname, "NO NAME    ",11);
+		else
+			label_name(newLabel, verbose, &mangled, shortname);
+
+		if(have_boot && boot.descr >= 0xf0 &&
+		   labelBlock->dos4 == 0x29) {
+			strncpy(labelBlock->label, shortname, 11);
+			need_write_boot = 1;
+
+		}
+	}
+
+	if((set_serial != SER_NONE) & have_boot) {
+		if(have_boot && boot.descr >= 0xf0 &&
+		   labelBlock->dos4 == 0x29) {
+			set_dword(labelBlock->serial, serial);	
+			need_write_boot = 1;
+		}
+	}
+
+	if(need_write_boot) {
+		force_write(Fs, (char *)&boot, 0, sizeof(boot));
+	}
+
+	FREE(&RootDir);
+	exit(result);
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mmd.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mmd.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mmd.c	(revision 9)
@@ -0,0 +1,174 @@
+/*
+ * mmd.c
+ * Makes an MSDOS directory
+ */
+
+
+#define LOWERCASE
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "vfat.h"
+#include "mainloop.h"
+#include "plain_io.h"
+#include "nameclash.h"
+#include "file.h"
+#include "fs.h"
+
+/*
+ * Preserve the file modification times after the fclose()
+ */
+
+typedef struct Arg_t {
+	char *target;
+	MainParam_t mp;
+
+	Stream_t *SrcDir;
+	int entry;
+	ClashHandling_t ch;
+	Stream_t *targetDir;
+} Arg_t;
+
+
+typedef struct CreateArg_t {
+	Stream_t *Dir;
+	Stream_t *NewDir;
+	unsigned char attr;
+	time_t mtime;
+} CreateArg_t;
+
+/*
+ * Open the named file for read, create the cluster chain, return the
+ * directory structure or NULL on error.
+ */
+int makeit(char *dosname,
+	    char *longname,
+	    void *arg0,
+	    direntry_t *targetEntry)
+{
+	Stream_t *Target;
+	CreateArg_t *arg = (CreateArg_t *) arg0;
+	int fat;
+	direntry_t subEntry;	
+
+	/* will it fit? At least one cluster must be free */
+	if (!getfreeMinClusters(targetEntry->Dir, 1))
+		return -1;
+	
+	mk_entry(dosname, ATTR_DIR, 1, 0, arg->mtime, &targetEntry->dir);
+	Target = OpenFileByDirentry(targetEntry);
+	if(!Target){
+		fprintf(stderr,"Could not open Target\n");
+		return -1;
+	}
+
+	/* this allocates the first cluster for our directory */
+
+	initializeDirentry(&subEntry, Target);
+
+	subEntry.entry = 1;
+	GET_DATA(targetEntry->Dir, 0, 0, 0, &fat);
+	if (fat == fat32RootCluster(targetEntry->Dir)) {
+	    fat = 0;
+	}
+	mk_entry("..         ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir);
+	dir_write(&subEntry);
+
+	FLUSH((Stream_t *) Target);
+	subEntry.entry = 0;
+	GET_DATA(Target, 0, 0, 0, &fat);
+	mk_entry(".          ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir);
+	dir_write(&subEntry);
+
+	mk_entry(dosname, ATTR_DIR | arg->attr, fat, 0, arg->mtime, 
+		 &targetEntry->dir);
+	arg->NewDir = Target;
+	return 0;
+}
+
+
+static void usage(void)
+{
+	fprintf(stderr,
+		"Mtools version %s, dated %s\n", mversion, mdate);
+	fprintf(stderr,
+		"Usage: %s [-D clash_option] file targetfile\n", progname);
+	fprintf(stderr,
+		"       %s [-D clash_option] file [files...] target_directory\n", 
+		progname);
+	exit(1);
+}
+
+Stream_t *createDir(Stream_t *Dir, const char *filename, ClashHandling_t *ch, 
+					unsigned char attr, time_t mtime)
+{
+	CreateArg_t arg;
+	int ret;
+
+	arg.Dir = Dir;
+	arg.attr = attr;
+	arg.mtime = mtime;
+
+	if (!getfreeMinClusters(Dir, 1))
+		return NULL;
+
+	ret = mwrite_one(Dir, filename,0, makeit, &arg, ch);
+	if(ret < 1)
+		return NULL;
+	else
+		return arg.NewDir;
+}
+
+static int createDirCallback(direntry_t *entry, MainParam_t *mp)
+{
+	Stream_t *ret;
+	time_t now;
+
+	ret = createDir(mp->File, mp->targetName, &((Arg_t *)(mp->arg))->ch, 
+					ATTR_DIR, getTimeNow(&now));
+	if(ret == NULL)
+		return ERROR_ONE;
+	else {
+		FREE(&ret);
+		return GOT_ONE;
+	}
+	
+}
+
+void mmd(int argc, char **argv, int type)
+{
+	Arg_t arg;
+	int c;
+
+	/* get command line options */
+
+	init_clash_handling(& arg.ch);
+
+	/* get command line options */
+	while ((c = getopt(argc, argv, "D:o")) != EOF) {
+		switch (c) {
+			case '?':
+				usage();
+			case 'o':
+				handle_clash_options(&arg.ch, c);
+				break;
+			case 'D':
+				if(handle_clash_options(&arg.ch, *optarg))
+					usage();
+				break;
+			default:
+				break;
+		}
+	}
+
+	if (argc - optind < 1)
+		usage();
+
+	init_mp(&arg.mp);
+	arg.mp.arg = (void *) &arg;
+	arg.mp.openflags = O_RDWR;
+	arg.mp.callback = createDirCallback;
+	arg.mp.lookupflags = OPEN_PARENT | DO_OPEN_DIRS;
+	exit(main_loop(&arg.mp, argv + optind, argc - optind));
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mmount.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mmount.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mmount.c	(revision 9)
@@ -0,0 +1,85 @@
+/*
+ * Mount an MSDOS disk
+ *
+ * written by:
+ *
+ * Alain L. Knaff			
+ * alain@linux.lu
+ *
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+
+#ifdef OS_linux
+#include <sys/wait.h>
+#include "mainloop.h"
+#include "fs.h"
+
+extern int errno;
+
+void mmount(int argc, char **argv, int type)
+{
+	char drive;
+	int pid;
+	int status;
+	struct device dev;
+	char name[EXPAND_BUF];
+	int media;
+	struct bootsector boot;
+	Stream_t *Stream;
+	
+	if (argc<2 || !argv[1][0]  || argv[1][1] != ':' || argv[1][2]){
+		fprintf(stderr,"Usage: %s -V drive:\n", argv[0]);
+		exit(1);
+	}
+	drive = toupper(argv[1][0]);
+	Stream = find_device(drive, O_RDONLY, &dev, &boot, name, &media, 0);
+	if(!Stream)
+		exit(1);
+	FREE(&Stream);
+
+	destroy_privs();
+
+	if ( dev.partition ) {
+		char part_name[4];
+		sprintf(part_name, "%d", dev.partition %1000);
+		strcat(name, part_name); 
+	}
+
+	/* and finally mount it */
+	switch((pid=fork())){
+	case -1:
+		fprintf(stderr,"fork failed\n");
+		exit(1);
+	case 0:
+		close(2);
+		open("/dev/null", O_RDWR);
+		argv[1] = strdup("mount");
+		if ( argc > 2 )
+			execvp("mount", argv + 1 );
+		else
+			execlp("mount", "mount", name, 0);
+		perror("exec mount");
+		exit(1);
+	default:
+		while ( wait(&status) != pid );
+	}	
+	if ( WEXITSTATUS(status) == 0 )
+		exit(0);
+	argv[0] = strdup("mount");
+	argv[1] = strdup("-r");
+	if(!argv[0] || !argv[1]){
+		printOom();
+		exit(1);
+	}
+	if ( argc > 2 )
+		execvp("mount", argv);
+	else
+		execlp("mount", "mount","-r", name, 0);
+	exit(1);
+}
+
+#endif /* linux */
+
Index: /trunk/minix/commands/i386/mtools-3.9.7/mmove.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mmove.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mmove.c	(revision 9)
@@ -0,0 +1,314 @@
+/*
+ * mmove.c
+ * Renames/moves an MSDOS file
+ *
+ */
+
+
+#define LOWERCASE
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "vfat.h"
+#include "mainloop.h"
+#include "plain_io.h"
+#include "nameclash.h"
+#include "file.h"
+#include "fs.h"
+
+/*
+ * Preserve the file modification times after the fclose()
+ */
+
+typedef struct Arg_t {
+	const char *fromname;
+	int verbose;
+	MainParam_t mp;
+
+	direntry_t *entry;
+	ClashHandling_t ch;
+} Arg_t;
+
+
+/*
+ * Open the named file for read, create the cluster chain, return the
+ * directory structure or NULL on error.
+ */
+int renameit(char *dosname,
+	     char *longname,
+	     void *arg0,
+	     direntry_t *targetEntry)
+{
+	Arg_t *arg = (Arg_t *) arg0;
+	int fat;
+
+	targetEntry->dir = arg->entry->dir;
+	strncpy(targetEntry->dir.name, dosname, 8);
+	strncpy(targetEntry->dir.ext, dosname + 8, 3);
+
+	if(IS_DIR(targetEntry)) {
+		direntry_t *movedEntry;
+
+		/* get old direntry. It is important that we do this
+		 * on the actual direntry which is stored in the file,
+		 * and not on a copy, because we will modify it, and the
+		 * modification should be visible at file 
+		 * de-allocation time */
+		movedEntry = getDirentry(arg->mp.File);
+		if(movedEntry->Dir != targetEntry->Dir) {
+			/* we are indeed moving it to a new directory */
+			direntry_t subEntry;
+			Stream_t *oldDir;
+			/* we have a directory here. Change its parent link */
+			
+			initializeDirentry(&subEntry, arg->mp.File);
+
+			switch(vfat_lookup(&subEntry, "..", 2, ACCEPT_DIR,
+					   NULL, NULL)) {
+			    case -1:
+				fprintf(stderr,
+					" Directory has no parent entry\n");
+				break;
+			    case -2:
+				return ERROR_ONE;
+			    case 0:
+				GET_DATA(targetEntry->Dir, 0, 0, 0, &fat);
+				if (fat == fat32RootCluster(targetEntry->Dir)) {
+				    fat = 0;
+				}
+
+				subEntry.dir.start[1] = (fat >> 8) & 0xff;
+				subEntry.dir.start[0] = fat & 0xff;
+				dir_write(&subEntry);
+				if(arg->verbose){
+					fprintf(stderr,
+						"Easy, isn't it? I wonder why DOS can't do this.\n");
+				}
+				break;
+			}
+			
+			/* wipe out original entry */			
+			movedEntry->dir.name[0] = DELMARK;
+			dir_write(movedEntry);
+			
+			/* free the old parent, allocate the new one. */
+			oldDir = movedEntry->Dir;
+			*movedEntry = *targetEntry;
+			COPY(targetEntry->Dir);
+			FREE(&oldDir);
+			return 0;
+		}
+	}
+
+	/* wipe out original entry */
+	arg->mp.direntry->dir.name[0] = DELMARK;
+	dir_write(arg->mp.direntry);
+	return 0;
+}
+
+
+
+static int rename_file(direntry_t *entry, MainParam_t *mp)
+/* rename a messy DOS file to another messy DOS file */
+{
+	int result;
+	Stream_t *targetDir;
+	char *shortname;
+	const char *longname;
+
+	Arg_t * arg = (Arg_t *) (mp->arg);
+
+	arg->entry = entry;
+	targetDir = mp->targetDir;
+
+	if (targetDir == entry->Dir){
+		arg->ch.ignore_entry = -1;
+		arg->ch.source = entry->entry;
+		arg->ch.source_entry = entry->entry;
+	} else {
+		arg->ch.ignore_entry = -1;
+		arg->ch.source = -2;
+	}
+
+	longname = mpPickTargetName(mp);
+	shortname = 0;
+	result = mwrite_one(targetDir, longname, shortname,
+			    renameit, (void *)arg, &arg->ch);
+	if(result == 1)
+		return GOT_ONE;
+	else
+		return ERROR_ONE;
+}
+
+
+static int rename_directory(direntry_t *entry, MainParam_t *mp)
+{
+	int ret;
+
+	/* moves a DOS dir */
+	if(isSubdirOf(mp->targetDir, mp->File)) {
+		fprintf(stderr, "Cannot move directory ");
+		fprintPwd(stderr, entry,0);
+		fprintf(stderr, " into one of its own subdirectories (");
+		fprintPwd(stderr, getDirentry(mp->targetDir),0);
+		fprintf(stderr, ")\n");
+		return ERROR_ONE;
+	}
+
+	if(entry->entry == -3) {
+		fprintf(stderr, "Cannot move a root directory: ");
+		fprintPwd(stderr, entry,0);
+		return ERROR_ONE;
+	}
+
+	ret = rename_file(entry, mp);
+	if(ret & ERROR_ONE)
+		return ret;
+	
+	return ret;
+}
+
+static int rename_oldsyntax(direntry_t *entry, MainParam_t *mp)
+{
+	int result;
+	Stream_t *targetDir;
+	const char *shortname, *longname;
+
+	Arg_t * arg = (Arg_t *) (mp->arg);
+	arg->entry = entry;
+	targetDir = entry->Dir;
+
+	arg->ch.ignore_entry = -1;
+	arg->ch.source = entry->entry;
+	arg->ch.source_entry = entry->entry;
+
+#if 0
+	if(!strcasecmp(mp->shortname, arg->fromname)){
+		longname = mp->longname;
+		shortname = mp->targetName;
+	} else {
+#endif
+		longname = mp->targetName;
+		shortname = 0;
+#if 0
+	}
+#endif
+	result = mwrite_one(targetDir, longname, shortname,
+			    renameit, (void *)arg, &arg->ch);
+	if(result == 1)
+		return GOT_ONE;
+	else
+		return ERROR_ONE;
+}
+
+
+static void usage(void)
+{
+	fprintf(stderr,
+		"Mtools version %s, dated %s\n", mversion, mdate);
+	fprintf(stderr,
+		"Usage: %s [-vo] [-D clash_option] file targetfile\n", progname);
+	fprintf(stderr,
+		"       %s [-vo] [-D clash_option] file [files...] target_directory\n", 
+		progname);
+	fprintf(stderr, "\t-v Verbose\n");
+	exit(1);
+}
+
+void mmove(int argc, char **argv, int oldsyntax)
+{
+	Arg_t arg;
+	int c;
+	char shortname[13];
+	char longname[VBUFSIZE];
+	char *def_drive;
+	int i;
+
+	/* get command line options */
+
+	init_clash_handling(& arg.ch);
+
+	/* get command line options */
+	arg.verbose = 0;
+	while ((c = getopt(argc, argv, "vD:o")) != EOF) {
+		switch (c) {
+			case 'v':	/* dummy option for mcopy */
+				arg.verbose = 1;
+				break;
+			case '?':
+				usage();
+			case 'o':
+				handle_clash_options(&arg.ch, c);
+				break;
+			case 'D':
+				if(handle_clash_options(&arg.ch, *optarg))
+					usage();
+				break;
+			default:
+				break;
+		}
+	}
+
+	if (argc - optind < 2)
+		usage();
+
+	init_mp(&arg.mp);		
+	arg.mp.arg = (void *) &arg;
+	arg.mp.openflags = O_RDWR;
+
+	/* look for a default drive */
+	def_drive = NULL;
+	for(i=optind; i<argc; i++)
+		if(skip_drive(argv[i]) > argv[i]){
+			char *drive = get_drive(argv[i], NULL);
+			if(!def_drive)
+				def_drive = drive;
+			else if(strcmp(def_drive, drive) != 0){
+				fprintf(stderr,
+					"Cannot move files across different drives\n");
+				exit(1);
+			}
+		}
+
+	if(def_drive) {
+		char mcwd[MAXPATHLEN];
+
+		strcpy(mcwd, skip_drive(arg.mp.mcwd));
+		if(strlen(def_drive) + 1 + strlen(mcwd) + 1 > MAXPATHLEN){
+			fprintf(stderr,
+				"Path name to current directory too long\n");
+			exit(1);
+		}
+		strcpy(arg.mp.mcwd, def_drive);
+		strcat(arg.mp.mcwd, ":");
+		strcat(arg.mp.mcwd, mcwd);
+	}
+
+	if (oldsyntax && (argc - optind != 2 || strpbrk(":/", argv[argc-1])))
+		oldsyntax = 0;
+
+	arg.mp.lookupflags = 
+	  ACCEPT_PLAIN | ACCEPT_DIR | DO_OPEN_DIRS | NO_DOTS | NO_UNIX;
+
+	if (!oldsyntax){
+		target_lookup(&arg.mp, argv[argc-1]);
+		arg.mp.callback = rename_file;
+		arg.mp.dirCallback = rename_directory;
+	} else {
+		/* do not look up the target; it will be the same dir as the
+		 * source */
+		arg.fromname = _basename(skip_drive(argv[optind]));
+		arg.mp.targetName = strdup(argv[argc-1]);
+		arg.mp.callback = rename_oldsyntax;
+	}
+
+
+	arg.mp.longname = longname;
+	longname[0]='\0';
+
+	arg.mp.shortname = shortname;
+	shortname[0]='\0';
+
+	exit(main_loop(&arg.mp, argv + optind, argc - optind - 1));
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mpartition.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mpartition.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mpartition.c	(revision 9)
@@ -0,0 +1,706 @@
+/*
+ * mformat.c
+ */
+#define DONT_NEED_WAIT
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "mainloop.h"
+#include "fsP.h"
+#include "file.h"
+#include "plain_io.h"
+#include "nameclash.h"
+#include "buffer.h"
+#include "scsi.h"
+#include "partition.h"
+
+#ifdef OS_linux
+#include "linux/hdreg.h"
+
+#define _LINUX_STRING_H_
+#define kdev_t int
+#include "linux/fs.h"
+#undef _LINUX_STRING_H_
+
+#endif
+
+#define tolinear(x) \
+(sector(x)-1+(head(x)+cyl(x)*used_dev->heads)*used_dev->sectors)
+
+
+static inline void print_hsc(hsc *h)
+{
+	printf(" h=%d s=%d c=%d\n", 
+	       head(*h), sector(*h), cyl(*h));
+}
+
+static void set_offset(hsc *h, int offset, int heads, int sectors)
+{
+	int head, sector, cyl;
+
+	if(! heads || !sectors)
+		head = sector = cyl = 0; /* linear mode */
+	else {
+		sector = offset % sectors;
+		offset = offset / sectors;
+
+		head = offset % heads;
+		cyl = offset / heads;
+		if(cyl > 1023) cyl = 1023;
+	}
+
+	h->head = head;
+	h->sector = ((sector+1) & 0x3f) | ((cyl & 0x300)>>2);
+	h->cyl = cyl & 0xff;
+}
+
+void setBeginEnd(struct partition *partTable, int begin, int end,
+				 int heads, int sectors, int activate, int type)
+{
+	set_offset(&partTable->start, begin, heads, sectors);
+	set_offset(&partTable->end, end-1, heads, sectors);
+	set_dword(partTable->start_sect, begin);
+	set_dword(partTable->nr_sects, end-begin);
+	if(activate)
+		partTable->boot_ind = 0x80;
+	else
+		partTable->boot_ind = 0;
+	if(!type) {
+		if(end-begin < 4096)
+			type = 1; /* DOS 12-bit FAT */
+		else if(end-begin<32*2048)
+			type = 4; /* DOS 16-bit FAT, <32M */
+		else
+			type = 6; /* DOS 16-bit FAT >= 32M */
+	}
+	partTable->sys_ind = type;
+}
+
+int consistencyCheck(struct partition *partTable, int doprint, int verbose,
+		     int *has_activated, int *last_end, int *j, 
+		     struct device *used_dev, int target_partition)
+{
+	int i;
+	int inconsistency;
+	
+	*j = 0;
+	*last_end = 1;
+
+	/* quick consistency check */
+	inconsistency = 0;
+	*has_activated = 0;
+	for(i=1; i<5; i++){
+		if(!partTable[i].sys_ind)
+			continue;
+		if(partTable[i].boot_ind)
+			(*has_activated)++;
+		if((used_dev && 
+		    (used_dev->heads != head(partTable[i].end)+1 ||
+		     used_dev->sectors != sector(partTable[i].end))) ||
+		   sector(partTable[i].start) != 1){
+			fprintf(stderr,
+				"Partition %d is not aligned\n",
+				i);
+			inconsistency=1;
+		}
+		
+		if(*j && *last_end > BEGIN(partTable[i])) {
+			fprintf(stderr,
+				"Partitions %d and %d badly ordered or overlapping\n",
+				*j,i);
+			inconsistency=1;
+		}
+			
+		*last_end = END(partTable[i]);
+		*j = i;
+
+		if(used_dev &&
+		   cyl(partTable[i].start) != 1023 &&
+		   tolinear(partTable[i].start) != BEGIN(partTable[i])) {
+			fprintf(stderr,
+				"Start position mismatch for partition %d\n",
+				i);
+			inconsistency=1;
+		}
+		if(used_dev &&
+		   cyl(partTable[i].end) != 1023 &&
+		   tolinear(partTable[i].end)+1 != END(partTable[i])) {
+			fprintf(stderr,
+				"End position mismatch for partition %d\n",
+				i);
+			inconsistency=1;
+		}
+
+		if(doprint && verbose) {
+			if(i==target_partition)
+				putchar('*');
+			else
+				putchar(' ');
+			printf("Partition %d\n",i);
+
+			printf("  active=%x\n", partTable[i].boot_ind);
+			printf("  start:");
+			print_hsc(&partTable[i].start);
+			printf("  type=0x%x\n", partTable[i].sys_ind);
+			printf("  end:");
+			print_hsc(&partTable[i].end);
+			printf("  start=%d\n", BEGIN(partTable[i]));
+			printf("  nr=%d\n", _DWORD(partTable[i].nr_sects));
+			printf("\n");
+		}
+	}
+	return inconsistency;
+}
+
+/* setsize function.  Determines scsicam mapping if this cannot be inferred from
+ * any existing partitions. Shamelessly snarfed from the Linux kernel ;-) */
+
+/*
+ * Function : static int setsize(unsigned long capacity,unsigned int *cyls,
+ *	unsigned int *hds, unsigned int *secs);
+ *
+ * Purpose : to determine a near-optimal int 0x13 mapping for a
+ *	SCSI disk in terms of lost space of size capacity, storing
+ *	the results in *cyls, *hds, and *secs.
+ *
+ * Returns : -1 on failure, 0 on success.
+ *
+ * Extracted from
+ *
+ * WORKING                                                    X3T9.2
+ * DRAFT                                                        792D
+ *
+ *
+ *                                                        Revision 6
+ *                                                         10-MAR-94
+ * Information technology -
+ * SCSI-2 Common access method
+ * transport and SCSI interface module
+ * 
+ * ANNEX A :
+ *
+ * setsize() converts a read capacity value to int 13h
+ * head-cylinder-sector requirements. It minimizes the value for
+ * number of heads and maximizes the number of cylinders. This
+ * will support rather large disks before the number of heads
+ * will not fit in 4 bits (or 6 bits). This algorithm also
+ * minimizes the number of sectors that will be unused at the end
+ * of the disk while allowing for very large disks to be
+ * accommodated. This algorithm does not use physical geometry. 
+ */
+
+static int setsize(unsigned long capacity,unsigned int *cyls,unsigned int *hds,
+    unsigned int *secs) { 
+    unsigned int rv = 0; 
+    unsigned long heads, sectors, cylinders, temp; 
+
+    cylinders = 1024L;			/* Set number of cylinders to max */ 
+    sectors = 62L;      		/* Maximize sectors per track */ 
+
+    temp = cylinders * sectors;		/* Compute divisor for heads */ 
+    heads = capacity / temp;		/* Compute value for number of heads */
+    if (capacity % temp) {		/* If no remainder, done! */ 
+    	heads++;                	/* Else, increment number of heads */ 
+    	temp = cylinders * heads;	/* Compute divisor for sectors */ 
+    	sectors = capacity / temp;	/* Compute value for sectors per
+					       track */ 
+    	if (capacity % temp) {		/* If no remainder, done! */ 
+      	    sectors++;                  /* Else, increment number of sectors */ 
+      	    temp = heads * sectors;	/* Compute divisor for cylinders */
+      	    cylinders = capacity / temp;/* Compute number of cylinders */ 
+      	} 
+    } 
+    if (cylinders == 0) rv=(unsigned)-1;/* Give error if 0 cylinders */ 
+
+    *cyls = (unsigned int) cylinders;	/* Stuff return values */ 
+    *secs = (unsigned int) sectors; 
+    *hds  = (unsigned int) heads; 
+    return(rv); 
+} 
+
+static void setsize0(unsigned long capacity,unsigned int *cyls,
+		     unsigned int *hds, unsigned int *secs)
+{
+	int r;
+
+	/* 1. First try "Megabyte" sizes */
+	if(capacity < 1024 * 2048 && !(capacity % 1024)) {
+		*cyls = capacity >> 11;
+		*hds  = 64;
+		*secs = 32;
+		return;
+	}
+
+	/* then try scsicam's size */
+	r = setsize(capacity,cyls,hds,secs);
+	if(r || *hds > 255 || *secs > 63) {
+		/* scsicam failed. Do megabytes anyways */
+		*cyls = capacity >> 11;
+		*hds  = 64;
+		*secs = 32;
+		return;
+	}
+}
+
+
+static void usage(void)
+{
+	fprintf(stderr, 
+		"Mtools version %s, dated %s\n", mversion, mdate);
+	fprintf(stderr, 
+		"Usage: %s [-pradcv] [-I [-B bootsect-template] [-s sectors] "
+			"[-t cylinders] "
+		"[-h heads] [-T type] [-b begin] [-l length] "
+		"drive\n", progname);
+	exit(1);
+}
+
+void mpartition(int argc, char **argv, int dummy)
+{
+	Stream_t *Stream;
+	unsigned int dummy2;
+
+	int i,j;
+
+	int sec_per_cyl;
+	int doprint = 0;
+	int verbose = 0;
+	int create = 0;
+	int force = 0;
+	int length = 0;
+	int remove = 0;
+	int initialize = 0;
+	int tot_sectors=0;
+	int type = 0;
+	int begin_set = 0;
+	int size_set = 0;
+	int end_set = 0;
+	int last_end = 0;
+	int activate = 0;
+	int has_activated = 0;
+	int inconsistency=0;
+	int begin=0;
+	int end=0;
+	int sizetest=0;
+	int dirty = 0;
+	int open2flags = NO_OFFSET;
+	
+	int c;
+	struct device used_dev;
+	int argtracks, argheads, argsectors;
+
+	char *drive, name[EXPAND_BUF];
+	unsigned char buf[512];
+	struct partition *partTable=(struct partition *)(buf+ 0x1ae);
+	struct device *dev;
+	char errmsg[200];
+	char *bootSector=0;
+
+	argtracks = 0;
+	argheads = 0;
+	argsectors = 0;
+
+	/* get command line options */
+	while ((c = getopt(argc, argv, "adprcIT:t:h:s:fvpb:l:S:B:")) != EOF) {
+		switch (c) {
+			case 'B':
+				bootSector = optarg;
+				break;
+			case 'a':
+				/* no privs, as it could be abused to
+				 * make other partitions unbootable, or
+				 * to boot a rogue kernel from this one */
+				open2flags |= NO_PRIV;
+				activate = 1;
+				dirty = 1;
+				break;
+			case 'd':
+				activate = -1;
+				dirty = 1;
+				break;
+			case 'p':
+				doprint = 1;
+				break;
+			case 'r':
+				remove = 1;
+				dirty = 1;
+				break;
+			case 'I':
+				/* could be abused to nuke all other 
+				 * partitions */
+				open2flags |= NO_PRIV;
+				initialize = 1;
+				dirty = 1;
+				break;
+			case 'c':
+				create = 1;
+				dirty = 1;
+				break;
+
+			case 'T':
+				/* could be abused to "manually" create
+				 * extended partitions */
+				open2flags |= NO_PRIV;
+				type = strtoul(optarg,0,0);
+				break;
+
+			case 't':
+				argtracks = atoi(optarg);
+				break;
+			case 'h':
+				argheads = atoi(optarg);
+				break;
+			case 's':
+				argsectors = atoi(optarg);
+				break;
+
+			case 'f':
+				/* could be abused by creating overlapping
+				 * partitions and other such Snafu */
+				open2flags |= NO_PRIV;
+				force = 1;
+				break;
+
+			case 'v':
+				verbose++;
+				break;
+			case 'S':
+				/* testing only */
+				/* could be abused to create partitions
+				 * extending beyond the actual size of the
+				 * device */
+				open2flags |= NO_PRIV;
+				tot_sectors = strtoul(optarg,0,0);
+				sizetest = 1;
+				break;
+			case 'b':
+				begin_set = 1;
+				begin = atoi(optarg);
+				break;
+			case 'l':
+				size_set = 1;
+				length = atoi(optarg);
+				break;
+
+			default:
+				usage();
+		}
+	}
+
+	if (argc - optind != 1 || skip_drive(argv[optind]) == argv[optind])
+		usage();
+	
+	drive = get_drive(argv[optind], NULL);
+
+	/* check out a drive whose letter and parameters match */	
+	sprintf(errmsg, "Drive '%s:' not supported", drive);
+	Stream = 0;
+	for(dev=devices;dev->drive;dev++) {
+		FREE(&(Stream));
+		/* drive letter */
+		if (strcmp(dev->drive, drive) != 0)
+			continue;
+		if (dev->partition < 1 || dev->partition > 4) {
+			sprintf(errmsg, 
+				"Drive '%c:' is not a partition", 
+				drive);
+			continue;
+		}
+		used_dev = *dev;
+
+		SET_INT(used_dev.tracks, argtracks);
+		SET_INT(used_dev.heads, argheads);
+		SET_INT(used_dev.sectors, argsectors);
+		
+		expand(dev->name, name);
+		Stream = SimpleFileOpen(&used_dev, dev, name,
+					dirty ? O_RDWR : O_RDONLY, 
+					errmsg, open2flags, 1, 0);
+
+		if (!Stream) {
+#ifdef HAVE_SNPRINTF
+			snprintf(errmsg,199,"init: open: %s", strerror(errno));
+#else
+			sprintf(errmsg,"init: open: %s", strerror(errno));
+#endif
+			continue;
+		}			
+
+
+		/* try to find out the size */
+		if(!sizetest)
+			tot_sectors = 0;
+		if(IS_SCSI(dev)) {
+			unsigned char cmd[10];
+			unsigned char data[10];
+			cmd[0] = SCSI_READ_CAPACITY;
+			memset ((void *) &cmd[2], 0, 8);
+			memset ((void *) &data[0], 137, 10);
+			scsi_cmd(get_fd(Stream), cmd, 10, SCSI_IO_READ,
+				 data, 10, get_extra_data(Stream));
+			
+			tot_sectors = 1 +
+				(data[0] << 24) +
+				(data[1] << 16) +
+				(data[2] <<  8) +
+				(data[3]      );
+			if(verbose)
+				printf("%d sectors in total\n", tot_sectors);
+		}
+
+#ifdef OS_linux
+		if (tot_sectors == 0) {
+			ioctl(get_fd(Stream), BLKGETSIZE, &tot_sectors);
+		}
+#endif
+
+		/* read the partition table */
+		if (READS(Stream, (char *) buf, 0, 512) != 512) {
+#ifdef HAVE_SNPRINTF
+			snprintf(errmsg, 199,
+				"Error reading from '%s', wrong parameters?",
+				name);
+#else
+			sprintf(errmsg,
+				"Error reading from '%s', wrong parameters?",
+				name);
+#endif
+			continue;
+		}
+		if(verbose>=2)
+			print_sector("Read sector", buf, 512);
+		break;
+	}
+
+	/* print error msg if needed */	
+	if ( dev->drive == 0 ){
+		FREE(&Stream);
+		fprintf(stderr,"%s: %s\n", argv[0],errmsg);
+		exit(1);
+	}
+
+	if((used_dev.sectors || used_dev.heads) &&
+	   (!used_dev.sectors || !used_dev.heads)) {
+		fprintf(stderr,"You should either indicate both the number of sectors and the number of heads,\n");
+		fprintf(stderr," or none of them\n");
+		exit(1);
+	}
+
+	if(initialize) {
+		if (bootSector) {
+			int fd;
+			fd = open(bootSector, O_RDONLY);
+			if (fd < 0) {
+				perror("open boot sector");
+				exit(1);
+			}
+			read(fd, (char *) buf, 512);
+		}
+		memset((char *)(partTable+1), 0, 4*sizeof(*partTable));
+		set_dword(((unsigned char*)buf)+510, 0xaa55);
+	}
+
+	/* check for boot signature, and place it if needed */
+	if((buf[510] != 0x55) || (buf[511] != 0xaa)) {
+		fprintf(stderr,"Boot signature not set\n");
+		fprintf(stderr,
+			"Use the -I flag to initialize the partition table, and set the boot signature\n");
+		inconsistency = 1;
+	}
+	
+	if(remove){
+		if(!partTable[dev->partition].sys_ind)
+			fprintf(stderr,
+				"Partition for drive %c: does not exist\n",
+				drive);
+		if((partTable[dev->partition].sys_ind & 0x3f) == 5) {
+			fprintf(stderr,
+				"Partition for drive %c: may be an extended partition\n",
+				drive);
+			fprintf(stderr,
+				"Use the -f flag to remove it anyways\n");
+			inconsistency = 1;
+		}
+		memset(&partTable[dev->partition], 0, sizeof(*partTable));
+	}
+
+	if(create && partTable[dev->partition].sys_ind) {
+		fprintf(stderr,
+			"Partition for drive %c: already exists\n", drive);
+		fprintf(stderr,
+			"Use the -r flag to remove it before attempting to recreate it\n");
+	}
+
+
+	/* find out number of heads and sectors, and whether there is
+	* any activated partition */
+	has_activated = 0;
+	for(i=1; i<5; i++){
+		if(!partTable[i].sys_ind)
+			continue;
+		
+		if(partTable[i].boot_ind)
+			has_activated++;
+
+		/* set geometry from entry */
+		if (!used_dev.heads)
+			used_dev.heads = head(partTable[i].end)+1;
+		if(!used_dev.sectors)
+			used_dev.sectors = sector(partTable[i].end);
+		if(i<dev->partition && !begin_set)
+			begin = END(partTable[i]);
+		if(i>dev->partition && !end_set && !size_set) {
+			end = BEGIN(partTable[i]);
+			end_set = 1;
+		}
+	}
+
+#ifdef OS_linux
+	if(!used_dev.sectors && !used_dev.heads) {
+		if(!IS_SCSI(dev)) {
+			struct hd_geometry geom;
+			if(ioctl(get_fd(Stream), HDIO_GETGEO, &geom) == 0) {
+				used_dev.heads = geom.heads;
+				used_dev.sectors = geom.sectors;
+			}
+		}
+	}
+#endif
+
+	if(!used_dev.sectors && !used_dev.heads) {
+		if(tot_sectors)
+			setsize0(tot_sectors,&dummy2,&used_dev.heads,
+					 &used_dev.sectors);
+		else {
+			used_dev.heads = 64;
+			used_dev.sectors = 32;
+		}
+	}
+
+	if(verbose)
+		fprintf(stderr,"sectors: %d heads: %d %d\n",
+			used_dev.sectors, used_dev.heads, tot_sectors);
+
+	sec_per_cyl = used_dev.sectors * used_dev.heads;
+	if(create) {
+		if(!end_set && tot_sectors) {
+			end = tot_sectors - tot_sectors % sec_per_cyl;
+			end_set = 1;
+		}
+		
+		/* if the partition starts right at the beginning of
+		 * the disk, keep one track unused to allow place for
+		 * the master boot record */
+		if(!begin && !begin_set)
+			begin = used_dev.sectors;
+		if(!size_set && used_dev.tracks) {
+			size_set = 2;
+			length = sec_per_cyl * used_dev.tracks;
+
+			/*  round the size in order to take
+			 * into account any "hidden" sectors */
+
+			/* do we anchor this at the beginning ?*/
+			if(begin_set || dev->partition <= 2 || !end_set)
+				length -= begin % sec_per_cyl;
+			else if(end - length < begin)
+				/* truncate any overlap */
+				length = end - begin;
+		}
+		if(size_set) {
+			if(!begin_set && dev->partition >2 && end_set)
+				begin = end - length;
+			else
+				end = begin + length;
+		} else if(!end_set) {
+			fprintf(stderr,"Unknown size\n");
+			exit(1);
+		}
+
+		setBeginEnd(&partTable[dev->partition], begin, end,
+					used_dev.heads, used_dev.sectors, 
+					!has_activated, type);
+	}
+
+	if(activate) {
+		if(!partTable[dev->partition].sys_ind) {
+			fprintf(stderr,
+				"Partition for drive %c: does not exist\n",
+				drive);
+		} else {
+			switch(activate) {
+				case 1:
+					partTable[dev->partition].boot_ind=0x80;
+					break;
+				case -1:
+					partTable[dev->partition].boot_ind=0x00;
+					break;
+			}
+		}
+	}
+
+
+	inconsistency |= consistencyCheck(partTable, doprint, verbose,
+					  &has_activated, &last_end, &j,
+					  &used_dev, dev->partition);
+
+	if(doprint && !inconsistency && partTable[dev->partition].sys_ind) {
+		printf("The following command will recreate the partition for drive %c:\n", 
+		       drive);
+		used_dev.tracks = 
+			(_DWORD(partTable[dev->partition].nr_sects) +
+			 (BEGIN(partTable[dev->partition]) % sec_per_cyl)) / 
+			sec_per_cyl;
+		printf("mpartition -c -t %d -h %d -s %d -b %u %c:\n",
+		       used_dev.tracks, used_dev.heads, used_dev.sectors,
+		       BEGIN(partTable[dev->partition]), drive);
+	}
+
+	if(tot_sectors && last_end >tot_sectors) {
+		fprintf(stderr,
+			"Partition %d exceeds beyond end of disk\n",
+			j);
+		exit(1);
+	}
+
+	
+	switch(has_activated) {
+		case 0:
+			fprintf(stderr,
+				"Warning: no active (bootable) partition present\n");
+			break;
+		case 1:
+			break;
+		default:
+			fprintf(stderr,
+				"Warning: %d active (bootable) partitions present\n",
+				has_activated);
+			fprintf(stderr,
+				"Usually, a disk should have exactly one active partition\n");
+			break;
+	}
+	
+	if(inconsistency && !force) {
+		fprintf(stderr,
+			"inconsistency detected!\n" );
+		if(dirty)
+			fprintf(stderr,
+				"Retry with the -f switch to go ahead anyways\n");
+		exit(1);
+	}
+
+	if(dirty) {
+		/* write data back to the disk */
+		if(verbose>=2)
+			print_sector("Writing sector", buf, 512);
+		if (WRITES(Stream, (char *) buf, 0, 512) != 512) {
+			fprintf(stderr,"Error writing partition table");
+			exit(1);
+		}
+		if(verbose>=3)
+			print_sector("Sector written", buf, 512);
+		FREE(&Stream);
+	}
+	exit(0);
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/msdos.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/msdos.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/msdos.h	(revision 9)
@@ -0,0 +1,237 @@
+#ifndef MTOOLS_MSDOS_H
+#define MTOOLS_MSDOS_H
+
+/*
+ * msdos common header file
+ */
+
+#define MAX_SECTOR	8192   		/* largest sector size */
+#define MDIR_SIZE	32		/* MSDOS directory entry size in bytes*/
+#define MAX_CLUSTER	8192		/* largest cluster size */
+#define MAX_PATH	128		/* largest MSDOS path length */
+#define MAX_DIR_SECS	64		/* largest directory (in sectors) */
+#define MSECTOR_SIZE    msector_size
+
+#define NEW		1
+#define OLD		0
+
+#define _WORD(x) ((unsigned char)(x)[0] + (((unsigned char)(x)[1]) << 8))
+#define _DWORD(x) (_WORD(x) + (_WORD((x)+2) << 16))
+
+#define DELMARK ((char) 0xe5)
+
+struct directory {
+	char name[8];			/*  0 file name */
+	char ext[3];			/*  8 file extension */
+	unsigned char attr;		/* 11 attribute byte */
+	unsigned char Case;		/* 12 case of short filename */
+	unsigned char ctime_ms;		/* 13 creation time, milliseconds (?) */
+	unsigned char ctime[2];		/* 14 creation time */
+	unsigned char cdate[2];		/* 16 creation date */
+	unsigned char adate[2];		/* 18 last access date */
+	unsigned char startHi[2];	/* 20 start cluster, Hi */
+	unsigned char time[2];		/* 22 time stamp */
+	unsigned char date[2];		/* 24 date stamp */
+	unsigned char start[2];		/* 26 starting cluster number */
+	unsigned char size[4];		/* 28 size of the file */
+};
+
+#define EXTCASE 0x10
+#define BASECASE 0x8
+
+#define MAX32 0xffffffff
+#define MAX_SIZE 0x7fffffff
+
+#define FILE_SIZE(dir)  (_DWORD((dir)->size))
+#define START(dir) (_WORD((dir)->start))
+#define STARTHI(dir) (_WORD((dir)->startHi))
+
+/* ASSUMPTION: long is at least 32 bits */
+UNUSED(static inline void set_dword(unsigned char *data, unsigned long value))
+{
+	data[3] = (value >> 24) & 0xff;
+	data[2] = (value >> 16) & 0xff;
+	data[1] = (value >>  8) & 0xff;
+	data[0] = (value >>  0) & 0xff;
+}
+
+
+/* ASSUMPTION: short is at least 16 bits */
+UNUSED(static inline void set_word(unsigned char *data, unsigned short value))
+{
+	data[1] = (value >>  8) & 0xff;
+	data[0] = (value >>  0) & 0xff;
+}
+
+
+/*
+ *	    hi byte     |    low byte
+ *	|7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
+ *  | | | | | | | | | | | | | | | | |
+ *  \   7 bits    /\4 bits/\ 5 bits /
+ *     year +80     month     day
+ */
+#define	DOS_YEAR(dir) (((dir)->date[1] >> 1) + 1980)
+#define	DOS_MONTH(dir) (((((dir)->date[1]&0x1) << 3) + ((dir)->date[0] >> 5)))
+#define	DOS_DAY(dir) ((dir)->date[0] & 0x1f)
+
+/*
+ *	    hi byte     |    low byte
+ *	|7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
+ *      | | | | | | | | | | | | | | | | |
+ *      \  5 bits /\  6 bits  /\ 5 bits /
+ *         hour      minutes     sec*2
+ */
+#define	DOS_HOUR(dir) ((dir)->time[1] >> 3)
+#define	DOS_MINUTE(dir) (((((dir)->time[1]&0x7) << 3) + ((dir)->time[0] >> 5)))
+#define	DOS_SEC(dir) (((dir)->time[0] & 0x1f) * 2)
+
+
+typedef struct InfoSector_t {
+	unsigned char signature1[4];
+	unsigned char filler1[0x1e0];
+	unsigned char signature2[4];
+	unsigned char count[4];
+	unsigned char pos[4];
+	unsigned char filler2[14];
+	unsigned char signature3[2];
+} InfoSector_t;
+
+#define INFOSECT_SIGNATURE1 0x41615252
+#define INFOSECT_SIGNATURE2 0x61417272
+
+
+typedef struct label_blk_t {
+	unsigned char physdrive;	/* 36 physical drive ? */
+	unsigned char reserved;		/* 37 reserved */
+	unsigned char dos4;		/* 38 dos > 4.0 diskette */
+	unsigned char serial[4];       	/* 39 serial number */
+	char label[11];			/* 43 disk label */
+	char fat_type[8];		/* 54 FAT type */
+} label_blk_t;
+
+/* FAT32 specific info in the bootsector */
+typedef struct fat32_t {
+	unsigned char bigFat[4];	/* 36 nb of sectors per FAT */
+	unsigned char extFlags[2];     	/* 40 extension flags */
+	unsigned char fsVersion[2];	/* 42 ? */
+	unsigned char rootCluster[4];	/* 44 start cluster of root dir */
+	unsigned char infoSector[2];	/* 48 changeable global info */
+	unsigned char backupBoot[2];	/* 50 back up boot sector */
+	unsigned char reserved[6];	/* 52 ? */
+	unsigned char reserved2[6];	/* 52 ? */
+	struct label_blk_t labelBlock;
+} fat32; /* ends at 58 */
+
+typedef struct oldboot_t {
+	struct label_blk_t labelBlock;
+	unsigned char res_2m;		/* 62 reserved by 2M */
+	unsigned char CheckSum;		/* 63 2M checksum (not used) */
+	unsigned char fmt_2mf;		/* 64 2MF format version */
+	unsigned char wt;		/* 65 1 if write track after format */
+	unsigned char rate_0;		/* 66 data transfer rate on track 0 */
+	unsigned char rate_any;		/* 67 data transfer rate on track<>0 */
+	unsigned char BootP[2];		/* 68 offset to boot program */
+	unsigned char Infp0[2];		/* 70 T1: information for track 0 */
+	unsigned char InfpX[2];		/* 72 T2: information for track<>0 */
+	unsigned char InfTm[2];		/* 74 T3: track sectors size table */
+	unsigned char DateF[2];		/* 76 Format date */
+	unsigned char TimeF[2];		/* 78 Format time */
+	unsigned char junk[1024 - 80];	/* 80 remaining data */
+} oldboot_t;
+
+struct bootsector {
+	unsigned char jump[3];		/* 0  Jump to boot code */
+	char banner[8] PACKED;	       	/* 3  OEM name & version */
+	unsigned char secsiz[2] PACKED;	/* 11 Bytes per sector hopefully 512 */
+	unsigned char clsiz;    	/* 13 Cluster size in sectors */
+	unsigned char nrsvsect[2];	/* 14 Number of reserved (boot) sectors */
+	unsigned char nfat;		/* 16 Number of FAT tables hopefully 2 */
+	unsigned char dirents[2] PACKED;/* 17 Number of directory slots */
+	unsigned char psect[2] PACKED; 	/* 19 Total sectors on disk */
+	unsigned char descr;		/* 21 Media descriptor=first byte of FAT */
+	unsigned char fatlen[2];	/* 22 Sectors in FAT */
+	unsigned char nsect[2];		/* 24 Sectors/track */
+	unsigned char nheads[2];	/* 26 Heads */
+	unsigned char nhs[4];		/* 28 number of hidden sectors */
+	unsigned char bigsect[4];	/* 32 big total sectors */
+
+	union {
+		struct fat32_t fat32;
+		struct oldboot_t old;
+	} ext;
+};
+
+#define CHAR(x) (boot->x[0])
+#define WORD(x) (_WORD(boot->x))
+#define DWORD(x) (_DWORD(boot->x))
+#define OFFSET(x) (((char *) (boot->x)) - ((char *)(boot->jump)))
+
+
+extern struct OldDos_t {
+	int tracks;
+	int sectors;
+	int heads;
+	
+	int dir_len;
+	int cluster_size;
+	int fat_len;
+
+	int media;
+} old_dos[];
+
+#define FAT12 4085 /* max. number of clusters described by a 12 bit FAT */
+#define FAT16 65525
+
+#define ATTR_ARCHIVE 0x20
+#define ATTR_DIR 0x10
+#define ATTR_LABEL 0x8
+#define ATTR_SYSTEM 0x4
+#define ATTR_HIDDEN 0x2
+#define ATTR_READONLY 0x1
+
+#define HAS_BIT(entry,x) ((entry)->dir.attr & (x))
+
+#define IS_ARCHIVE(entry) (HAS_BIT((entry),ATTR_ARCHIVE))
+#define IS_DIR(entry) (HAS_BIT((entry),ATTR_DIR))
+#define IS_LABEL(entry) (HAS_BIT((entry),ATTR_LABEL))
+#define IS_SYSTEM(entry) (HAS_BIT((entry),ATTR_SYSTEM))
+#define IS_HIDDEN(entry) (HAS_BIT((entry),ATTR_HIDDEN))
+#define IS_READONLY(entry) (HAS_BIT((entry),ATTR_READONLY))
+
+
+#define MAX_SECT_PER_CLUSTER 64
+/* Experimentally, it turns out that DOS only accepts cluster sizes
+ * which are powers of two, and less than 128 sectors (else it gets a
+ * divide overflow) */
+
+
+#define FAT_SIZE(bits, sec_siz, clusters) \
+	((((clusters)+2) * ((bits)/4) - 1) / 2 / (sec_siz) + 1)
+
+#define NEEDED_FAT_SIZE(x) FAT_SIZE((x)->fat_bits, (x)->sector_size, \
+				    (x)->num_clus)
+
+/* disk size taken by FAT and clusters */
+#define DISK_SIZE(bits, sec_siz, clusters, n, cluster_size) \
+	((n) * FAT_SIZE(bits, sec_siz, clusters) + \
+	 (clusters) * (cluster_size))
+
+#define TOTAL_DISK_SIZE(bits, sec_siz, clusters, n, cluster_size) \
+	(DISK_SIZE(bits, sec_siz, clusters, n, cluster_size) + 2)
+/* approx. total disk size: assume 1 boot sector and one directory sector */
+
+extern const char *mversion;
+extern const char *mdate;
+
+extern char *Version;
+extern char *Date;
+
+
+int init(char drive, int mode);
+
+#define MT_READ 1
+#define MT_WRITE 2
+
+#endif
+
Index: /trunk/minix/commands/i386/mtools-3.9.7/mshowfat.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mshowfat.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mshowfat.c	(revision 9)
@@ -0,0 +1,87 @@
+/*
+ * mcopy.c
+ * Copy an MSDOS files to and from Unix
+ *
+ */
+
+
+#define LOWERCASE
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "vfat.h"
+#include "mainloop.h"
+#include "plain_io.h"
+#include "nameclash.h"
+#include "file.h"
+#include "fs.h"
+
+
+
+typedef struct Arg_t {
+	char *target;
+	MainParam_t mp;
+	ClashHandling_t ch;
+	Stream_t *sourcefile;
+} Arg_t;
+
+static int dos_showfat(direntry_t *entry, MainParam_t *mp)
+{
+	Stream_t *File=mp->File;
+
+	fprintPwd(stdout, entry,0);
+	putchar(' ');
+	printFat(File);
+	printf("\n");
+	return GOT_ONE;
+}
+
+static int unix_showfat(MainParam_t *mp)
+{
+	fprintf(stderr,"File does not reside on a Dos fs\n");
+	return ERROR_ONE;
+}
+
+
+static void usage(void)
+{
+	fprintf(stderr,
+		"Mtools version %s, dated %s\n", mversion, mdate);
+	fprintf(stderr,
+		"Usage: %s file ...\n", progname);
+	exit(1);
+}
+
+void mshowfat(int argc, char **argv, int mtype)
+{
+	Arg_t arg;
+	int c, ret;
+	
+	/* get command line options */
+
+	init_clash_handling(& arg.ch);
+
+	/* get command line options */
+	while ((c = getopt(argc, argv, "")) != EOF) {
+		switch (c) {
+			case '?':
+				usage();
+				break;
+		}
+	}
+
+	if (argc - optind < 1)
+		usage();
+
+	/* only 1 file to copy... */
+	init_mp(&arg.mp);
+	arg.mp.arg = (void *) &arg;
+
+	arg.mp.callback = dos_showfat;
+	arg.mp.unixcallback = unix_showfat;
+
+	arg.mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR | DO_OPEN;
+	ret=main_loop(&arg.mp, argv + optind, argc - optind);
+	exit(ret);
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mtools.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mtools.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mtools.c	(revision 9)
@@ -0,0 +1,186 @@
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "partition.h"
+#include "vfat.h"
+
+const char *progname;
+
+static const struct dispatch {
+	const char *cmd;
+	void (*fn)(int, char **, int);
+	int type;
+} dispatch[] = {
+	{"attrib",mattrib, 0},
+	{"badblocks",mbadblocks, 0},
+	{"cat",mcat, 0},
+	{"cd",mcd, 0},
+	{"copy",mcopy, 0},
+	{"del",mdel, 0},
+	{"deltree",mdel, 2},
+	{"dir",mdir, 0},
+	{"doctorfat",mdoctorfat, 0},
+	{"du",mdu, 0},
+	{"format",mformat, 0},
+	{"info", minfo, 0},
+	{"label",mlabel, 0},
+	{"md",mmd, 0},
+	{"mkdir",mmd, 0},
+#ifdef OS_linux
+	{"mount",mmount, 0},
+#endif
+	{"partition",mpartition, 0},
+	{"rd",mdel, 1},
+	{"rmdir",mdel, 1},
+	{"read",mcopy, 0},
+	{"move",mmove, 0},
+	{"ren",mmove, 1},
+	{"showfat", mshowfat, 0},
+#ifndef NO_CONFIG
+	{"toolstest", mtoolstest, 0},
+#endif
+	{"type",mcopy, 1},
+	{"write",mcopy, 0},
+#ifndef OS_Minix
+	{"zip", mzip, 0}
+#endif
+};
+#define NDISPATCH (sizeof dispatch / sizeof dispatch[0])
+
+int main(int argc,char **argv)
+{
+	const char *name;
+	int i;
+
+	init_privs();
+#ifdef __EMX__
+	_wildcard(&argc,&argv);
+#endif
+
+/*#define PRIV_TEST*/
+
+#ifdef PRIV_TEST
+	{ 
+		int euid;
+		char command[100];
+	
+		printf("INIT: %d %d\n", getuid(), geteuid());
+		drop_privs();
+		printf("DROP: %d %d\n", getuid(), geteuid());
+		reclaim_privs();
+		printf("RECLAIM: %d %d\n", getuid(), geteuid());
+		euid = geteuid();
+		if(argc & 1) {
+			drop_privs();
+			printf("DROP: %d %d\n", getuid(), geteuid());
+		}
+		if(!((argc-1) & 2)) {
+			destroy_privs();
+			printf("DESTROY: %d %d\n", getuid(), geteuid());
+		}
+		sprintf(command, "a.out %d", euid);
+		system(command);
+		return 1;
+	}
+#endif
+
+
+#ifdef __EMX__
+       _wildcard(&argc,&argv);
+#endif 
+
+
+	/* check whether the compiler lays out structures in a sane way */
+	if(sizeof(struct partition) != 16 ||
+	   sizeof(struct directory) != 32 ||
+	   sizeof(struct vfat_subentry) !=32) {
+		fprintf(stderr,"Mtools has not been correctly compiled\n");
+		fprintf(stderr,"Recompile it using a more recent compiler\n");
+		return 137;
+	}
+
+#ifdef __EMX__
+       argv[0] = _getname(argv[0]); _remext(argv[0]); name = argv[0];
+#else  
+	name = _basename(argv[0]);
+#endif
+
+#if 0
+	/* this allows the different tools to be called as "mtools -c <command>"
+	** where <command> is mdir, mdel, mcopy etcetera
+	** Mainly done for the BeOS, which doesn't support links yet.
+	*/
+
+	if(argc >= 3 && 
+	   !strcmp(argv[1], "-c") &&
+	   !strcmp(name, "mtools")) {
+		argc-=2;
+		argv+=2;
+		name = argv[0];
+	}
+#endif
+
+	/* print the version */
+	if(argc >= 2 && 
+	   (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "--version") ==0)) {
+		printf("%c%s version %s, dated %s\n", 
+		       toupper(name[0]), name+1,
+		       mversion, mdate);
+		printf("configured with the following options: ");
+#ifdef USE_XDF
+		printf("enable-xdf ");
+#else
+		printf("disable-xdf ");
+#endif
+#ifdef USING_VOLD
+		printf("enable-vold ");
+#else
+		printf("disable-vold ");
+#endif
+#ifdef USING_NEW_VOLD
+		printf("enable-new-vold ");
+#else
+		printf("disable-new-vold ");
+#endif
+#ifdef DEBUG
+		printf("enable-debug ");
+#else
+		printf("disable-debug ");
+#endif
+#ifdef USE_RAWTERM
+		printf("enable-raw-term ");
+#else
+		printf("disable-raw-term ");
+#endif
+		printf("\n");
+		return 0;
+	}
+
+	if (argc >= 2 && strcmp(name, "mtools") == 0) {
+		/* mtools command ... */
+		argc--;
+		argv++;
+		name = argv[0];
+	}
+	progname = argv[0];
+
+	read_config();
+	setup_signal();
+	for (i = 0; i < NDISPATCH; i++) {
+		if (!strcmp(name,dispatch[i].cmd)
+		    || (name[0] == 'm' && !strcmp(name+1,dispatch[i].cmd)))
+			dispatch[i].fn(argc, argv, dispatch[i].type);
+	}
+	if (strcmp(name,"mtools"))
+		fprintf(stderr,"Unknown mtools command '%s'\n",name);
+	fprintf(stderr,"Usage: mtools [-V] command [-options] arguments ...\n");
+	fprintf(stderr,"Supported commands:");
+	for (i = 0; i < NDISPATCH; i++) {
+		fprintf(stderr, i%8 == 0 ? "\n\t" : ", ");
+		fprintf(stderr, "%s", dispatch[i].cmd);
+	}
+	putc('\n', stderr);
+	fprintf(stderr, "Use 'mtools command -?' for help per command\n");
+
+	return 1;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/mtools.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mtools.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mtools.h	(revision 9)
@@ -0,0 +1,234 @@
+#ifndef MTOOLS_MTOOLS_H
+#define MTOOLS_MTOOLS_H
+
+#include "msdos.h"
+
+#if defined(OS_sco3)
+#define MAXPATHLEN 1024
+#include <signal.h>
+extern int lockf(int, int, off_t);  /* SCO has no proper include file for lockf */
+#endif 
+
+#define SCSI_FLAG 1
+#define PRIV_FLAG 2
+#define NOLOCK_FLAG 4
+#define USE_XDF_FLAG 8
+#define MFORMAT_ONLY_FLAG 16
+#define VOLD_FLAG 32
+#define FLOPPYD_FLAG 64
+#define FILTER_FLAG 128
+
+#define IS_SCSI(x)  ((x) && ((x)->misc_flags & SCSI_FLAG))
+#define IS_PRIVILEGED(x) ((x) && ((x)->misc_flags & PRIV_FLAG))
+#define IS_NOLOCK(x) ((x) && ((x)->misc_flags & NOLOCK_FLAG))
+#define IS_MFORMAT_ONLY(x) ((x) && ((x)->misc_flags & MFORMAT_ONLY_FLAG))
+#define SHOULD_USE_VOLD(x) ((x)&& ((x)->misc_flags & VOLD_FLAG))
+#define SHOULD_USE_XDF(x) ((x)&& ((x)->misc_flags & USE_XDF_FLAG))
+
+typedef struct device {
+	const char *name;       /* full path to device */
+
+	char *drive;	   	    	/* the drive letter / device name */
+	int fat_bits;			/* FAT encoding scheme */
+
+	unsigned int mode;		/* any special open() flags */
+	unsigned int tracks;	/* tracks */
+	unsigned int heads;		/* heads */
+	unsigned int sectors;	/* sectors */
+	unsigned int hidden;	/* number of hidden sectors. Used for
+							 * mformatting partitioned devices */
+
+	off_t offset;	       	/* skip this many bytes */
+
+	unsigned int partition;
+
+	unsigned int misc_flags;
+
+	/* Linux only stuff */
+	unsigned int ssize;
+	unsigned int use_2m;
+
+	char *precmd;		/* command to be executed before opening
+						 * the drive */
+
+	/* internal variables */
+	int file_nr;		/* used during parsing */
+	int blocksize;	        /* size of disk block in bytes */
+
+	const char *cfg_filename; /* used for debugging purposes */
+} device_t;
+
+
+#ifndef OS_linux
+#define BOOTSIZE 512
+#else
+#define BOOTSIZE 256
+#endif
+
+#include "stream.h"
+
+
+extern const char *short_illegals, *long_illegals;
+
+#define maximize(target, max) do { \
+  if(max < 0) { \
+    if(target > 0) \
+      target = 0; \
+  } else if(target > max) { \
+    target = max; \
+  } \
+} while(0)
+
+#define minimize(target, min) do { \
+  if(target < min) \
+    target = min; \
+} while(0) 
+
+int init_geom(int fd, struct device *dev, struct device *orig_dev,
+	      struct stat *stat);
+
+int readwrite_sectors(int fd, /* file descriptor */
+		      int *drive,
+		      int rate,
+		      int seektrack,
+		      int track, int head, int sector, int size, /* address */
+		      char *data, 
+		      int bytes,
+		      int direction,
+		      int retries);
+
+int lock_dev(int fd, int mode, struct device *dev);
+
+char *unix_normalize (char *ans, char *name, char *ext);
+char *dos_name(char *filename, int verbose, int *mangled, char *buffer);
+struct directory *mk_entry(const char *filename, char attr,
+			   unsigned int fat, size_t size, time_t date,
+			   struct directory *ndir);
+int copyfile(Stream_t *Source, Stream_t *Target);
+int getfreeMinClusters(Stream_t *Stream, size_t ref);
+
+FILE *opentty(int mode);
+
+int is_dir(Stream_t *Dir, char *path);
+void bufferize(Stream_t **Dir);
+
+int dir_grow(Stream_t *Dir, int size);
+int match(const char *, const char *, char *, int, int);
+
+char *unix_name(char *name, char *ext, char Case, char *answer);
+void *safe_malloc(size_t size);
+Stream_t *open_filter(Stream_t *Next);
+
+extern int got_signal;
+/* int do_gotsignal(char *, int);
+#define got_signal do_gotsignal(__FILE__, __LINE__) */
+
+void setup_signal(void);
+
+
+#define SET_INT(target, source) \
+if(source)target=source
+
+
+UNUSED(static inline int compare (long ref, long testee))
+{
+	return (ref && ref != testee);
+}
+
+Stream_t *GetFs(Stream_t *Fs);
+
+char *label_name(char *filename, int verbose, 
+		 int *mangled, char *ans);
+
+/* environmental variables */
+extern unsigned int mtools_skip_check;
+extern unsigned int mtools_fat_compatibility;
+extern unsigned int mtools_ignore_short_case;
+extern unsigned int mtools_no_vfat;
+extern unsigned int mtools_numeric_tail;
+extern unsigned int mtools_dotted_dir;
+extern unsigned int mtools_twenty_four_hour_clock;
+extern char *mtools_date_string;
+extern unsigned int mtools_rate_0, mtools_rate_any;
+extern int mtools_raw_tty;
+
+extern int batchmode;
+
+void read_config(void);
+extern struct device *devices;
+extern struct device const_devices[];
+extern const int nr_const_devices;
+
+#define New(type) ((type*)(malloc(sizeof(type))))
+#define Grow(adr,n,type) ((type*)(realloc((char *)adr,n*sizeof(type))))
+#define Free(adr) (free((char *)adr));
+#define NewArray(size,type) ((type*)(calloc((size),sizeof(type))))
+
+void mattrib(int argc, char **argv, int type);
+void mbadblocks(int argc, char **argv, int type);
+void mcat(int argc, char **argv, int type);
+void mcd(int argc, char **argv, int type);
+void mcopy(int argc, char **argv, int type);
+void mdel(int argc, char **argv, int type);
+void mdir(int argc, char **argv, int type);
+void mdoctorfat(int argc, char **argv, int type);
+void mdu(int argc, char **argv, int type);
+void mformat(int argc, char **argv, int type);
+void minfo(int argc, char **argv, int type);
+void mlabel(int argc, char **argv, int type);
+void mmd(int argc, char **argv, int type);
+void mmount(int argc, char **argv, int type);
+void mmove(int argc, char **argv, int type);
+void mpartition(int argc, char **argv, int type);
+void mshowfat(int argc, char **argv, int mtype);
+void mtoolstest(int argc, char **argv, int type);
+void mzip(int argc, char **argv, int type);
+
+extern int noPrivileges;
+void init_privs(void);
+void reclaim_privs(void);
+void drop_privs(void);
+void destroy_privs(void);
+uid_t get_real_uid(void);
+void closeExec(int fd);
+
+extern const char *progname;
+
+void precmd(struct device *dev);
+
+void print_sector(char *message, unsigned char *data, int size);
+time_t getTimeNow(time_t *now);
+
+#ifdef USING_NEW_VOLD
+char *getVoldName(struct device *dev, char *name);
+#endif
+
+
+Stream_t *OpenDir(Stream_t *Parent, const char *filename);
+/* int unix_dir_loop(Stream_t *Stream, MainParam_t *mp); 
+int unix_loop(MainParam_t *mp, char *arg); */
+
+struct dirCache_t **getDirCacheP(Stream_t *Stream);
+int isRootDir(Stream_t *Stream);
+unsigned int getStart(Stream_t *Dir, struct directory *dir);
+unsigned int countBlocks(Stream_t *Dir, unsigned int block);
+char *getDrive(Stream_t *Stream);
+
+
+void printOom(void);
+int ask_confirmation(const char *, const char *, const char *);
+char *get_homedir(void);
+#define EXPAND_BUF 2048
+const char *expand(const char *, char *);
+const char *fix_mcwd(char *);
+FILE *open_mcwd(const char *mode);
+void unlink_mcwd(void);
+char *skip_drive(const char *path);
+char *get_drive(const char *path, const char *def);
+
+int safePopenOut(char **command, char *output, int len);
+
+#define ROUND_DOWN(value, grain) ((value) - (value) % (grain))
+#define ROUND_UP(value, grain) ROUND_DOWN((value) + (grain)-1, (grain))
+
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/mtoolsDirent.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mtoolsDirent.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mtoolsDirent.h	(revision 9)
@@ -0,0 +1,40 @@
+#ifndef MTOOLS_DIRENTRY_H
+#define MTOOLS_DIRENTRY_H
+
+#include "sysincludes.h"
+#include "vfat.h"
+
+typedef struct direntry_t {
+	struct Stream_t *Dir;
+	/* struct direntry_t *parent; parent level */	
+	int entry; /* slot in parent directory (-3 if root) */
+	struct directory dir; /* descriptor in parent directory (random if 
+			       * root)*/
+	char name[MAX_VNAMELEN+1]; /* name in its parent directory, or 
+				    * NULL if root */
+	int beginSlot; /* begin and end slot, for delete */
+	int endSlot;
+} direntry_t;
+
+#include "stream.h"
+
+int vfat_lookup(direntry_t *entry, const char *filename, int length,
+		int flags, char *shortname, char *longname);
+
+struct directory *dir_read(direntry_t *entry, int *error);
+
+void initializeDirentry(direntry_t *entry, struct Stream_t *Dir);
+int isNotFound(direntry_t *entry);
+direntry_t *getParent(direntry_t *entry);
+void dir_write(direntry_t *entry);
+void low_level_dir_write(direntry_t *entry);
+int fatFreeWithDirentry(direntry_t *entry);
+int labelit(char *dosname,
+	    char *longname,
+	    void *arg0,
+	    direntry_t *entry);
+int isSubdirOf(Stream_t *inside, Stream_t *outside);
+char *getPwd(direntry_t *entry);
+void fprintPwd(FILE *f, direntry_t *entry, int escape);
+int write_vfat(Stream_t *, char *, char *, int, direntry_t *);
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/mtoolsPaths.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/mtoolsPaths.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/mtoolsPaths.h	(revision 9)
@@ -0,0 +1,32 @@
+/*
+ * Paths of the configuration files.
+ * This file may be changed by the user as needed.
+ * There are three empty lines between each definition.
+ * These ensure that "local" patches and official patches have
+ * only a very low probability of conflicting.
+ */
+
+
+#define CONF_FILE "/etc/mtools.conf"
+
+
+#define OLD_CONF_FILE "/etc/mtools"
+
+
+
+#define LOCAL_CONF_FILE "/etc/default/mtools.conf"
+/* Use this if you like to keep the configuration file in a non-standard
+ * place such as /etc/default, /opt/etc, /usr/etc, /usr/local/etc ...
+ */
+
+#define SYS_CONF_FILE SYSCONFDIR "/mtools.conf"
+
+#define OLD_LOCAL_CONF_FILE "/etc/default/mtools"
+
+
+
+#define CFG_FILE1 "/.mtoolsrc"
+
+
+
+/* END */
Index: /trunk/minix/commands/i386/mtools-3.9.7/nameclash.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/nameclash.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/nameclash.h	(revision 9)
@@ -0,0 +1,57 @@
+#ifndef MTOOLS_NAMECLASH_H
+#define MTOOLS_NAMECLASH_H
+
+#include "stream.h"
+
+typedef enum clash_action {
+	NAMEMATCH_NONE,
+	NAMEMATCH_AUTORENAME,
+	NAMEMATCH_QUIT,
+	NAMEMATCH_SKIP,
+	NAMEMATCH_RENAME,
+	NAMEMATCH_PRENAME, /* renaming of primary name */
+	NAMEMATCH_OVERWRITE,
+	NAMEMATCH_ERROR,
+	NAMEMATCH_SUCCESS,
+	NAMEMATCH_GREW
+} clash_action;
+
+/* clash handling structure */
+typedef struct ClashHandling_t {
+	clash_action action[2];
+	clash_action namematch_default[2];
+		
+	int nowarn;	/* Don't ask, just do default action if name collision*/
+	int got_slots;
+	int mod_time;
+	/* unsigned int dot; */
+	char *myname;
+	unsigned char *dosname;
+	int single;
+
+	int use_longname;
+	int ignore_entry;
+	int source; /* to prevent the source from overwriting itself */
+	int source_entry; /* to account for the space freed up by the original 
+					   * name */
+	char * (*name_converter)(char *filename, int verbose, 
+				 int *mangled, char *ans);
+} ClashHandling_t;
+
+/* write callback */
+typedef int (write_data_callback)(char *,char *, void *, struct direntry_t *);
+
+int mwrite_one(Stream_t *Dir,
+	       const char *argname,
+	       const char *shortname,
+	       write_data_callback *cb,
+	       void *arg,
+	       ClashHandling_t *ch);
+
+int handle_clash_options(ClashHandling_t *ch, char c);
+void init_clash_handling(ClashHandling_t *ch);
+Stream_t *createDir(Stream_t *Dir, const char *filename, ClashHandling_t *ch,
+		    unsigned char attr, time_t mtime);
+
+
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/partition.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/partition.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/partition.h	(revision 9)
@@ -0,0 +1,31 @@
+typedef struct hsc {
+	unsigned char byte0;
+	unsigned char head;		/* starting head */
+	unsigned char sector;		/* starting sector */
+	unsigned char cyl;		/* starting cylinder */
+} hsc;
+
+#define head(x) ((x).head)
+#define sector(x) ((x).sector & 0x3f)
+#define cyl(x) ((x).cyl | (((x).sector & 0xc0)<<2))
+
+#define BEGIN(p) _DWORD((p).start_sect)
+#define END(p) (_DWORD((p).start_sect)+(_DWORD((p).nr_sects)))
+
+
+struct partition {
+	hsc start;
+	hsc end;
+	unsigned char start_sect[4];	/* starting sector counting from 0 */
+	unsigned char nr_sects[4];     	/* nr of sectors in partition */
+};
+
+#define boot_ind start.byte0
+#define sys_ind end.byte0
+
+int consistencyCheck(struct partition *partTable, int doprint, int verbose,
+		     int *has_activated, int *last_end, int *j, 
+		     struct device *used_dev, int target_partition);
+
+void setBeginEnd(struct partition *partTable, int begin, int end,
+				 int heads, int sector, int activate, int type);
Index: /trunk/minix/commands/i386/mtools-3.9.7/patchlevel.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/patchlevel.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/patchlevel.c	(revision 9)
@@ -0,0 +1,2 @@
+const char *mversion="3.9.7";
+const char *mdate = "1 jun 2000";
Index: /trunk/minix/commands/i386/mtools-3.9.7/plain_io.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/plain_io.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/plain_io.c	(revision 9)
@@ -0,0 +1,749 @@
+/*
+ * Io to a plain file or device
+ *
+ * written by:
+ *
+ * Alain L. Knaff			
+ * alain@linux.lu
+ *
+ */
+
+#include "sysincludes.h"
+#include "stream.h"
+#include "mtools.h"
+#include "msdos.h"
+#include "plain_io.h"
+#include "scsi.h"
+#include "partition.h"
+#include "llong.h"
+
+typedef struct SimpleFile_t {
+    Class_t *Class;
+    int refs;
+    Stream_t *Next;
+    Stream_t *Buffer;
+    struct stat stat;
+    int fd;
+    mt_off_t offset;
+    mt_off_t lastwhere;
+    int seekable;
+    int privileged;
+#ifdef OS_hpux
+    int size_limited;
+#endif
+    int scsi_sector_size;
+    void *extra_data; /* extra system dependant information for scsi */
+} SimpleFile_t;
+
+
+/*
+ * Create an advisory lock on the device to prevent concurrent writes.
+ * Uses either lockf, flock, or fcntl locking methods.  See the Makefile
+ * and the Configure files for how to specify the proper method.
+ */
+
+int lock_dev(int fd, int mode, struct device *dev)
+{
+#if (defined(HAVE_FLOCK) && defined (LOCK_EX) && defined(LOCK_NB))
+	/**/
+#else /* FLOCK */
+
+#if (defined(HAVE_LOCKF) && defined(F_TLOCK))
+	/**/
+#else /* LOCKF */
+
+#if (defined(F_SETLK) && defined(F_WRLCK))
+	struct flock flk;
+
+#endif /* FCNTL */
+#endif /* LOCKF */
+#endif /* FLOCK */
+
+	if(IS_NOLOCK(dev))
+		return 0;
+
+#if (defined(HAVE_FLOCK) && defined (LOCK_EX) && defined(LOCK_NB))
+	if (flock(fd, (mode ? LOCK_EX : LOCK_SH)|LOCK_NB) < 0)
+#else /* FLOCK */
+
+#if (defined(HAVE_LOCKF) && defined(F_TLOCK))
+	if (mode && lockf(fd, F_TLOCK, 0) < 0)
+#else /* LOCKF */
+
+#if (defined(F_SETLK) && defined(F_WRLCK))
+	flk.l_type = mode ? F_WRLCK : F_RDLCK;
+	flk.l_whence = 0;
+	flk.l_start = 0L;
+	flk.l_len = 0L;
+
+	if (fcntl(fd, F_SETLK, &flk) < 0)
+#endif /* FCNTL */
+#endif /* LOCKF */
+#endif /* FLOCK */
+	{
+		if(errno == EINVAL
+#ifdef  EOPNOTSUPP 
+		   || errno ==  EOPNOTSUPP
+#endif
+		  )
+			return 0;
+		else
+			return 1;
+	}
+	return 0;
+}
+
+typedef int (*iofn) (int, char *, int);
+
+
+
+static int file_io(Stream_t *Stream, char *buf, mt_off_t where, int len,
+				   iofn io)
+{
+	DeclareThis(SimpleFile_t);
+	int ret;
+
+	where += This->offset;
+
+	if (This->seekable && where != This->lastwhere ){
+		if(mt_lseek( This->fd, where, SEEK_SET) < 0 ){
+			perror("seek");
+			This->lastwhere = (mt_off_t) -1;
+			return -1;
+		}
+	}
+
+#ifdef OS_hpux
+	/*
+	 * On HP/UX, we can not write more than MAX_LEN bytes in one go.
+	 * If more are written, the write fails with EINVAL
+	 */
+	#define MAX_SCSI_LEN (127*1024)
+	if(This->size_limited && len > MAX_SCSI_LEN)
+		len = MAX_SCSI_LEN;
+#endif
+	ret = io(This->fd, buf, len);
+
+#ifdef OS_hpux
+	if (ret == -1 && 
+		errno == EINVAL && /* if we got EINVAL */
+		len > MAX_SCSI_LEN) {
+		This->size_limited = 1;
+		len = MAX_SCSI_LEN;
+		ret = io(This->fd, buf, len);
+	}
+#endif
+
+	if ( ret == -1 ){
+		perror("plain_io");
+		This->lastwhere = (mt_off_t) -1;
+		return -1;
+	}
+	This->lastwhere = where + ret;
+	return ret;
+}
+	
+
+
+static int file_read(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
+{	
+	return file_io(Stream, buf, where, len, (iofn) read);
+}
+
+static int file_write(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
+{
+	return file_io(Stream, buf, where, len, (iofn) write);
+}
+
+static int file_flush(Stream_t *Stream)
+{
+#if 0
+	DeclareThis(SimpleFile_t);
+
+	return fsync(This->fd);
+#endif
+	return 0;
+}
+
+static int file_free(Stream_t *Stream)
+{
+	DeclareThis(SimpleFile_t);
+
+	if (This->fd > 2)
+		return close(This->fd);
+	else
+		return 0;
+}
+
+static int file_geom(Stream_t *Stream, struct device *dev, 
+		     struct device *orig_dev,
+		     int media, struct bootsector *boot)
+{
+	int ret;
+	DeclareThis(SimpleFile_t);
+	size_t tot_sectors;
+	int BootP, Infp0, InfpX, InfTm;
+	int sectors, j;
+	unsigned char sum;
+	int sect_per_track;
+	struct label_blk_t *labelBlock;
+
+	dev->ssize = 2; /* allow for init_geom to change it */
+	dev->use_2m = 0x80; /* disable 2m mode to begin */
+
+	if(media == 0xf0 || media >= 0x100){		
+		dev->heads = WORD(nheads);
+		dev->sectors = WORD(nsect);
+		tot_sectors = DWORD(bigsect);
+		SET_INT(tot_sectors, WORD(psect));
+		sect_per_track = dev->heads * dev->sectors;
+		tot_sectors += sect_per_track - 1; /* round size up */
+		dev->tracks = tot_sectors / sect_per_track;
+
+		BootP = WORD(ext.old.BootP);
+		Infp0 = WORD(ext.old.Infp0);
+		InfpX = WORD(ext.old.InfpX);
+		InfTm = WORD(ext.old.InfTm);
+		
+		if(WORD(fatlen)) {
+			labelBlock = &boot->ext.old.labelBlock;
+		} else {
+			labelBlock = &boot->ext.fat32.labelBlock;
+		}
+
+		if (boot->descr >= 0xf0 &&
+		    labelBlock->dos4 == 0x29 &&
+		    strncmp( boot->banner,"2M", 2 ) == 0 &&
+		    BootP < 512 && Infp0 < 512 && InfpX < 512 && InfTm < 512 &&
+		    BootP >= InfTm + 2 && InfTm >= InfpX && InfpX >= Infp0 && 
+		    Infp0 >= 76 ){
+			for (sum=0, j=63; j < BootP; j++) 
+				sum += boot->jump[j];/* checksum */
+			dev->ssize = boot->jump[InfTm];
+			if (!sum && dev->ssize <= 7){
+				dev->use_2m = 0xff;
+				dev->ssize |= 0x80; /* is set */
+			}
+		}
+	} else if (media >= 0xf8){
+		media &= 3;
+		dev->heads = old_dos[media].heads;
+		dev->tracks = old_dos[media].tracks;
+		dev->sectors = old_dos[media].sectors;
+		dev->ssize = 0x80;
+		dev->use_2m = ~1;
+	} else {
+		fprintf(stderr,"Unknown media type\n");
+		exit(1);
+	}
+
+	sectors = dev->sectors;
+	dev->sectors = dev->sectors * WORD(secsiz) / 512;
+
+#ifdef JPD
+	printf("file_geom:media=%0X=>cyl=%d,heads=%d,sects=%d,ssize=%d,use2m=%X\n",
+	       media, dev->tracks, dev->heads, dev->sectors, dev->ssize,
+	       dev->use_2m);
+#endif
+	ret = init_geom(This->fd,dev, orig_dev, &This->stat);
+	dev->sectors = sectors;
+#ifdef JPD
+	printf("f_geom: after init_geom(), sects=%d\n", dev->sectors);
+#endif
+	return ret;
+}
+
+
+static int file_data(Stream_t *Stream, time_t *date, mt_size_t *size,
+		     int *type, int *address)
+{
+	DeclareThis(SimpleFile_t);
+
+	if(date)
+		*date = This->stat.st_mtime;
+	if(size)
+		*size = This->stat.st_size;
+	if(type)
+		*type = S_ISDIR(This->stat.st_mode);
+	if(address)
+		*address = 0;
+	return 0;
+}
+
+/* ZIP or other scsi device on Solaris or SunOS system.
+   Since Sun won't accept a non-Sun label on a scsi disk, we must
+   bypass Sun's disk interface and use low-level SCSI commands to read
+   or write the ZIP drive.  We thus replace the file_read and file_write
+   routines with our own scsi_read and scsi_write routines, that use the
+   uscsi ioctl interface.  By James Dugal, jpd@usl.edu, 11-96.  Tested
+   under Solaris 2.5 and SunOS 4.3.1_u1 using GCC.
+
+   Note: the mtools.conf entry for a ZIP drive would look like this:
+(solaris) drive C: file="/dev/rdsk/c0t5d0s2" partition=4  FAT=16 nodelay  exclusive scsi=&
+(sunos) drive C: file="/dev/rsd5c" partition=4  FAT=16 nodelay  exclusive scsi=1
+
+   Note 2: Sol 2.5 wants mtools to be suid-root, to use the ioctl.  SunOS is
+   happy if we just have access to the device, so making mtools sgid to a
+   group called, say, "ziprw" which has rw permission on /dev/rsd5c, is fine.
+ */
+
+#define MAXBLKSPERCMD 255
+
+static void scsi_init(SimpleFile_t *This)
+{
+   int fd = This->fd;
+   unsigned char cdb[10],buf[8];
+
+   memset(cdb, 0, sizeof cdb);
+   memset(buf,0, sizeof(buf));
+   cdb[0]=SCSI_READ_CAPACITY;
+   if (scsi_cmd(fd, (unsigned char *)cdb, 
+		sizeof(cdb), SCSI_IO_READ, buf, sizeof(buf), This->extra_data)==0)
+   {
+       This->scsi_sector_size=
+	       ((unsigned)buf[5]<<16)|((unsigned)buf[6]<<8)|(unsigned)buf[7];
+       if (This->scsi_sector_size != 512)
+	   fprintf(stderr,"  (scsi_sector_size=%d)\n",This->scsi_sector_size);
+   }
+}
+
+int scsi_io(Stream_t *Stream, char *buf,  mt_off_t where, size_t len, int rwcmd)
+{
+	unsigned int firstblock, nsect;
+	int clen,r,max;
+	off_t offset;
+	unsigned char cdb[10];
+	DeclareThis(SimpleFile_t);
+
+	firstblock=truncBytes32((where + This->offset)/This->scsi_sector_size);
+	/* 512,1024,2048,... bytes/sector supported */
+	offset=truncBytes32(where + This->offset - 
+						firstblock*This->scsi_sector_size);
+	nsect=(offset+len+This->scsi_sector_size-1)/ This->scsi_sector_size;
+#if defined(OS_sun) && defined(OS_i386)
+	if (This->scsi_sector_size>512)
+		firstblock*=This->scsi_sector_size/512; /* work around a uscsi bug */
+#endif /* sun && i386 */
+
+	if (len>512) {
+		/* avoid buffer overruns. The transfer MUST be smaller or
+		* equal to the requested size! */
+		while (nsect*This->scsi_sector_size>len)
+			--nsect;
+		if(!nsect) {			
+			fprintf(stderr,"Scsi buffer too small\n");
+			exit(1);
+		}
+		if(rwcmd == SCSI_IO_WRITE && offset) {
+			/* there seems to be no memmove before a write */
+			fprintf(stderr,"Unaligned write\n");
+			exit(1);
+		}
+		/* a better implementation should use bounce buffers.
+		 * However, in normal operation no buffer overruns or
+		 * unaligned writes should happen anyways, as the logical
+		 * sector size is (hopefully!) equal to the physical one
+		 */
+	}
+
+
+	max = scsi_max_length();
+	
+	if (nsect > max)
+		nsect=max;
+	
+	/* set up SCSI READ/WRITE command */
+	memset(cdb, 0, sizeof cdb);
+
+	switch(rwcmd) {
+		case SCSI_IO_READ:
+			cdb[0] = SCSI_READ;
+			break;
+		case SCSI_IO_WRITE:
+			cdb[0] = SCSI_WRITE;
+			break;
+	}
+
+	cdb[1] = 0;
+
+	if (firstblock > 0x1fffff || nsect > 0xff) {
+		/* I suspect that the ZIP drive also understands Group 1
+		 * commands. If that is indeed true, we may chose Group 1
+		 * more agressively in the future */
+
+		cdb[0] |= SCSI_GROUP1;
+		clen=10; /* SCSI Group 1 cmd */
+
+		/* this is one of the rare case where explicit coding is
+		 * more portable than macros... The meaning of scsi command
+		 * bytes is standardised, whereas the preprocessor macros
+		 * handling it might be not... */
+
+		cdb[2] = (unsigned char) (firstblock >> 24) & 0xff;
+		cdb[3] = (unsigned char) (firstblock >> 16) & 0xff;
+		cdb[4] = (unsigned char) (firstblock >> 8) & 0xff;
+		cdb[5] = (unsigned char) firstblock & 0xff;
+		cdb[6] = 0;
+		cdb[7] = (unsigned char) (nsect >> 8) & 0xff;
+		cdb[8] = (unsigned char) nsect & 0xff;
+		cdb[9] = 0;
+	} else {
+		clen = 6; /* SCSI Group 0 cmd */
+		cdb[1] |= (unsigned char) ((firstblock >> 16) & 0x1f);
+		cdb[2] = (unsigned char) ((firstblock >> 8) & 0xff);
+		cdb[3] = (unsigned char) firstblock & 0xff;
+		cdb[4] = (unsigned char) nsect;
+		cdb[5] = 0;
+	}
+	
+	if(This->privileged)
+		reclaim_privs();
+
+	r=scsi_cmd(This->fd, (unsigned char *)cdb, clen, rwcmd, buf,
+		   nsect*This->scsi_sector_size, This->extra_data);
+
+	if(This->privileged)
+		drop_privs();
+
+	if(r) {
+		perror(rwcmd == SCSI_IO_READ ? "SCMD_READ" : "SCMD_WRITE");
+		return -1;
+	}
+#ifdef JPD
+	printf("finished %u for %u\n", firstblock, nsect);
+#endif
+
+#ifdef JPD
+	printf("zip: read or write OK\n");
+#endif
+	if (offset>0) memmove(buf,buf+offset,nsect*This->scsi_sector_size-offset);
+	if (len==256) return 256;
+	else if (len==512) return 512;
+	else return nsect*This->scsi_sector_size-offset;
+}
+
+int scsi_read(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
+{
+	
+#ifdef JPD
+	printf("zip: to read %d bytes at %d\n", len, where);
+#endif
+	return scsi_io(Stream, buf, where, len, SCSI_IO_READ);
+}
+
+int scsi_write(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
+{
+#ifdef JPD
+	Printf("zip: to write %d bytes at %d\n", len, where);
+#endif
+	return scsi_io(Stream, buf, where, len, SCSI_IO_WRITE);
+}
+
+static Class_t ScsiClass = {
+	scsi_read, 
+	scsi_write,
+	file_flush,
+	file_free,
+	file_geom,
+	file_data,
+	0 /* pre-allocate */
+};
+
+
+static Class_t SimpleFileClass = {
+	file_read, 
+	file_write,
+	file_flush,
+	file_free,
+	file_geom,
+	file_data,
+	0 /* pre_allocate */
+};
+
+
+Stream_t *SimpleFileOpen(struct device *dev, struct device *orig_dev,
+			 const char *name, int mode, char *errmsg, 
+			 int mode2, int locked, mt_size_t *maxSize)
+{
+	SimpleFile_t *This;
+#ifdef __EMX__
+HFILE FileHandle;
+ULONG Action;
+APIRET rc;
+#endif
+	This = New(SimpleFile_t);
+	if (!This){
+		printOom();
+		return 0;
+	}
+	This->scsi_sector_size = 512;
+	This->seekable = 1;
+#ifdef OS_hpux
+	This->size_limited = 0;
+#endif
+	This->Class = &SimpleFileClass;
+	if (!name || strcmp(name,"-") == 0 ){
+		if (mode == O_RDONLY)
+			This->fd = 0;
+		else
+			This->fd = 1;
+		This->seekable = 0;
+		This->refs = 1;
+		This->Next = 0;
+		This->Buffer = 0;
+		if (fstat(This->fd, &This->stat) < 0) {
+		    Free(This);
+		    if(errmsg)
+#ifdef HAVE_SNPRINTF
+			snprintf(errmsg,199,"Can't stat -: %s", 
+				strerror(errno));   
+#else
+			sprintf(errmsg,"Can't stat -: %s", 
+				strerror(errno));
+#endif
+		    return NULL;
+		}
+
+		return (Stream_t *) This;
+	}
+
+	
+	if(dev) {
+		if(!(mode2 & NO_PRIV))
+			This->privileged = IS_PRIVILEGED(dev);
+		mode |= dev->mode;
+	}
+
+	precmd(dev);
+	if(IS_PRIVILEGED(dev) && !(mode2 & NO_PRIV))
+		reclaim_privs();
+
+#ifdef __EMX__
+#define DOSOPEN_FLAGS	(OPEN_FLAGS_DASD | OPEN_FLAGS_WRITE_THROUGH | \
+			OPEN_FLAGS_NOINHERIT | OPEN_FLAGS_RANDOM | \
+			OPEN_FLAGS_NO_CACHE)
+#define DOSOPEN_FD_ACCESS (OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE)
+#define DOSOPEN_HD_ACCESS (OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY)
+
+	if (skip_drive(name) > name) {
+		rc = DosOpen(
+			name, &FileHandle, &Action, 0L, FILE_NORMAL,
+			OPEN_ACTION_OPEN_IF_EXISTS, DOSOPEN_FLAGS |
+			(IS_NOLOCK(dev)?DOSOPEN_HD_ACCESS:DOSOPEN_FD_ACCESS),
+			0L);
+#ifdef DEBUG
+		if (rc != NO_ERROR) fprintf (stderr, "DosOpen() returned %d\n", rc);
+#endif
+		if (!IS_NOLOCK(dev)) {
+			rc = DosDevIOCtl(
+			FileHandle, 0x08L, DSK_LOCKDRIVE, 0, 0, 0, 0, 0, 0);
+#ifdef DEBUG
+			if (rc != NO_ERROR) fprintf (stderr, "DosDevIOCtl() returned %d\n", rc);
+#endif
+		}
+		if (rc == NO_ERROR)
+			This->fd = _imphandle(FileHandle); else This->fd = -1;
+	} else
+#endif
+	    {
+		if (IS_SCSI(dev))
+		    This->fd = scsi_open(name, mode, IS_NOLOCK(dev)?0444:0666,
+					 &This->extra_data);
+		else
+		    This->fd = open(name, mode, IS_NOLOCK(dev)?0444:0666);
+	    }
+
+	if(IS_PRIVILEGED(dev) && !(mode2 & NO_PRIV))
+		drop_privs();
+		
+	if (This->fd < 0) {
+		Free(This);
+		if(errmsg)
+#ifdef HAVE_SNPRINTF
+			snprintf(errmsg, 199, "Can't open %s: %s",
+				name, strerror(errno));
+#else
+			sprintf(errmsg, "Can't open %s: %s",
+				name, strerror(errno));
+#endif
+		return NULL;
+	}
+
+	if(IS_PRIVILEGED(dev) && !(mode2 & NO_PRIV))
+		closeExec(This->fd);
+
+#ifdef __EMX__
+	if (*(name+1) != ':')
+#endif
+	if (fstat(This->fd, &This->stat) < 0){
+		Free(This);
+		if(errmsg) {
+#ifdef HAVE_SNPRINTF
+			snprintf(errmsg,199,"Can't stat %s: %s", 
+				name, strerror(errno));
+#else
+			if(strlen(name) > 50) {
+			    sprintf(errmsg,"Can't stat file: %s", 
+				    strerror(errno));
+			} else {
+			    sprintf(errmsg,"Can't stat %s: %s", 
+				name, strerror(errno));
+			}
+#endif
+		}
+		return NULL;
+	}
+#ifndef __EMX__
+	/* lock the device on writes */
+	if (locked && lock_dev(This->fd, mode == O_RDWR, dev)) {
+		if(errmsg)
+#ifdef HAVE_SNPRINTF
+			snprintf(errmsg,199,
+				"plain floppy: device \"%s\" busy (%s):",
+				dev ? dev->name : "unknown", strerror(errno));
+#else
+			sprintf(errmsg,
+				"plain floppy: device \"%s\" busy (%s):",
+				(dev && strlen(dev->name) < 50) ? 
+				 dev->name : "unknown", strerror(errno));
+#endif
+
+		close(This->fd);
+		Free(This);
+		return NULL;
+	}
+#endif
+	/* set default parameters, if needed */
+	if (dev){		
+		if ((IS_MFORMAT_ONLY(dev) || !dev->tracks) &&
+			init_geom(This->fd, dev, orig_dev, &This->stat)){
+			close(This->fd);
+			Free(This);
+			if(errmsg)
+				sprintf(errmsg,"init: set default params");
+			return NULL;
+		}
+		This->offset = (mt_off_t) dev->offset;
+	} else
+		This->offset = 0;
+
+	This->refs = 1;
+	This->Next = 0;
+	This->Buffer = 0;
+
+	if(maxSize) {
+		if (IS_SCSI(dev)) {
+			*maxSize = MAX_OFF_T_B(31+log_2(This->scsi_sector_size));
+		} else {
+			*maxSize = max_off_t_seek;
+		}
+		if(This->offset > *maxSize) {
+			close(This->fd);
+			Free(This);
+			if(errmsg)
+				sprintf(errmsg,"init: Big disks not supported");
+			return NULL;
+		}
+		
+		*maxSize -= This->offset;
+	}
+	/* partitioned drive */
+
+	/* jpd@usl.edu: assume a partitioned drive on these 2 systems is a ZIP*/
+	/* or similar drive that must be accessed by low-level scsi commands */
+	/* AK: introduce new "scsi=1" statement to specifically set
+	 * this option. Indeed, there could conceivably be partitioned
+	 * devices where low level scsi commands will not be needed */
+	if(IS_SCSI(dev)) {
+		This->Class = &ScsiClass;
+		if(This->privileged)
+			reclaim_privs();
+		scsi_init(This);
+		if(This->privileged)
+			drop_privs();
+	}
+	while(!(mode2 & NO_OFFSET) &&
+	      dev && dev->partition && dev->partition <= 4) {
+		int has_activated, last_end, j;
+		unsigned char buf[2048];
+		struct partition *partTable=(struct partition *)(buf+ 0x1ae);
+		size_t partOff;
+		
+		/* read the first sector, or part of it */
+		if (force_read((Stream_t *)This, (char*) buf, 0, 512) != 512)
+			break;
+		if( _WORD(buf+510) != 0xaa55)
+			break;
+
+		partOff = BEGIN(partTable[dev->partition]);
+		if (maxSize) {
+			if (partOff > *maxSize >> 9) {
+				close(This->fd);
+				Free(This);
+				if(errmsg)
+					sprintf(errmsg,"init: Big disks not supported");
+				return NULL;
+			}
+			*maxSize -= (mt_off_t) partOff << 9;
+		}
+			
+		This->offset += (mt_off_t) partOff << 9;
+		if(!partTable[dev->partition].sys_ind) {
+			if(errmsg)
+				sprintf(errmsg,
+					"init: non-existant partition");
+			close(This->fd);
+			Free(This);
+			return NULL;
+		}
+
+		if(!dev->tracks) {
+			dev->heads = head(partTable[dev->partition].end)+1;
+			dev->sectors = sector(partTable[dev->partition].end);
+			dev->tracks = cyl(partTable[dev->partition].end) -
+				cyl(partTable[dev->partition].start)+1;
+		}
+		dev->hidden=dev->sectors*head(partTable[dev->partition].start);
+		if(!mtools_skip_check &&
+		   consistencyCheck((struct partition *)(buf+0x1ae), 0, 0,
+				    &has_activated, &last_end, &j, dev, 0)) {
+			fprintf(stderr,
+				"Warning: inconsistent partition table\n");
+			fprintf(stderr,
+				"Possibly unpartitioned device\n");
+			fprintf(stderr,
+				"\n*** Maybe try without partition=%d in "
+				"device definition ***\n\n",
+				dev->partition);
+			fprintf(stderr,
+                                "If this is a PCMCIA card, or a disk "
+				"partitioned on another computer, this "
+				"message may be in error: add "
+				"mtools_skip_check=1 to your .mtoolsrc "
+				"file to suppress this warning\n");
+
+		}
+		break;
+		/* NOTREACHED */
+	}
+
+	This->lastwhere = -This->offset;
+	/* provoke a seek on those devices that don't start on a partition
+	 * boundary */
+
+	return (Stream_t *) This;
+}
+
+int get_fd(Stream_t *Stream)
+{
+	DeclareThis(SimpleFile_t);
+	
+	return This->fd;
+}
+
+void *get_extra_data(Stream_t *Stream)
+{
+	DeclareThis(SimpleFile_t);
+	
+	return This->extra_data;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/plain_io.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/plain_io.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/plain_io.h	(revision 9)
@@ -0,0 +1,21 @@
+#ifndef MTOOLS_PLAINIO_H
+#define MTOOLS_PLAINIO_H
+
+#include "stream.h"
+#include "msdos.h"
+#ifdef __EMX__
+#include <io.h>
+#endif
+
+/* plain io */
+#define NO_PRIV 1
+#define NO_OFFSET 2
+
+Stream_t *SimpleFileOpen(struct device *dev, struct device *orig_dev,
+			 const char *name, int mode, char *errmsg, int mode2,
+			 int locked, mt_size_t *maxSize);
+int check_parameters(struct device *ref, struct device *testee);
+
+int get_fd(Stream_t *Stream);
+void *get_extra_data(Stream_t *Stream);
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/precmd.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/precmd.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/precmd.c	(revision 9)
@@ -0,0 +1,31 @@
+/*
+ * Do filename expansion with the shell.
+ */
+
+#define EXPAND_BUF	2048
+
+#include "sysincludes.h"
+#include "mtools.h"
+
+void precmd(struct device *dev)
+{
+	int status;
+	pid_t pid;
+
+	if(!dev || !dev->precmd)
+		return;
+	
+	switch((pid=fork())){
+		case -1:
+			perror("Could not fork");
+			exit(1);
+			break;
+		case 0: /* the son */
+			execl("/bin/sh", "sh", "-c", dev->precmd, 0);
+			break;
+		default:
+			wait(&status);
+			break;
+	}
+}
+		
Index: /trunk/minix/commands/i386/mtools-3.9.7/privileges.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/privileges.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/privileges.c	(revision 9)
@@ -0,0 +1,166 @@
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+
+/*#define PRIV_DEBUG*/
+
+#if 0
+#undef HAVE_SETEUID
+#define HAVE_SETRESUID
+#include <asm/unistd.h>
+int setresuid(int a, int b, int c)
+{
+	syscall(164, a, b, c);
+
+}
+#endif
+
+static inline void print_privs(const char *message)
+{
+#ifdef PRIV_DEBUG
+	/* for debugging purposes only */
+	fprintf(stderr,"%s egid=%d rgid=%d\n", message, getegid(), getgid());
+	fprintf(stderr,"%s euid=%d ruid=%d\n", message, geteuid(), getuid());
+#endif
+}
+
+int noPrivileges=0;
+
+
+static gid_t rgid, egid;
+static uid_t ruid, euid;
+
+/* privilege management routines for SunOS and Solaris.  These are
+ * needed in order to issue raw SCSI read/write ioctls.  Mtools drops
+ * its privileges at the beginning, and reclaims them just for the
+ * above-mentioned ioctl's.  Before popen(), exec() or system, it
+ * drops its privileges completely, and issues a warning.
+ */
+
+
+/* group id handling is lots easyer, as long as we don't use group 0.
+ * If you want to use group id's, create a *new* group mtools or
+ * floppy.  Chgrp any devices that you only want to be accessible to
+ * mtools to this group, and give them the appropriate privs.  Make
+ * sure this group doesn't own any other files: be aware that any user
+ * with access to mtools may mformat these files!
+ */
+
+
+static inline void Setuid(uid_t uid)
+{
+#if defined HAVE_SETEUID || defined HAVE_SETRESUID
+	if(euid == 0) {
+#ifdef HAVE_SETEUID
+		seteuid(uid);
+#else
+		setresuid(ruid, uid, euid);
+#endif
+	} else
+#endif
+		setuid(uid);
+}
+
+/* In reclaim_privs and drop privs, we have to manipulate group privileges
+ * when having no root privileges, else we might lose them */
+
+void reclaim_privs(void)
+{
+	if(noPrivileges)
+		return;
+	setgid(egid);
+	Setuid(euid);
+	print_privs("after reclaim privs, both uids should be 0 ");
+}
+
+void drop_privs(void)
+{
+	Setuid(ruid);
+	setgid(rgid);
+	print_privs("after drop_privs, real should be 0, effective should not ");
+}
+
+void destroy_privs(void)
+{
+
+#if defined HAVE_SETEUID || defined HAVE_SETRESUID
+	if(euid == 0) {
+#ifdef HAVE_SETEUID
+		setuid(0); /* get the necessary privs to drop real root id */
+		setuid(ruid); /* this should be enough to get rid of the three
+			       * ids */
+		seteuid(ruid); /* for good measure... just in case we came
+				* accross a system which implemented sane
+				* semantics instead of POSIXly broken
+				* semantics for setuid */
+#else
+		setresuid(ruid, ruid, ruid);
+#endif
+	}
+#endif
+
+	/* we also destroy group privileges */
+	drop_privs();
+
+	/* saved set [ug]id will go away by itself on exec */
+
+	print_privs("destroy_privs, no uid should be zero  ");
+}
+
+
+uid_t get_real_uid(void)
+{
+	return ruid;
+}
+
+void init_privs(void)
+{
+	euid = geteuid();
+	ruid = getuid();
+	egid = getegid();
+	rgid = getgid();
+
+#ifndef F_SETFD
+	if(euid != ruid) {
+		fprintf(stderr,
+			"Setuid installation not supported on this platform\n");
+		fprintf(stderr,
+			"Missing F_SETFD");
+		exit(1);
+	}
+#endif
+	
+	if(euid == 0 && ruid != 0) {
+#ifdef HAVE_SETEUID
+		setuid(0); /* set real uid to 0 */
+#else
+#ifndef HAVE_SETRESUID
+		/* on this machine, it is not possible to reversibly drop
+		 * root privileges.  We print an error and quit */
+
+		/* BEOS is no longer a special case, as both euid and ruid
+		 * return 0, and thus we do not get any longer into this
+		 * branch */
+		fprintf(stderr,
+			"Seteuid call not supported on this architecture.\n");
+		fprintf(stderr,
+			"Mtools cannot be installed setuid root.\n");
+		fprintf(stderr,
+			"However, it can be installed setuid to a non root");
+		fprintf(stderr,
+			"user or setgid to any id.\n");
+		exit(1);
+#endif
+#endif
+	}
+	
+	drop_privs();
+	print_privs("after init, real should be 0, effective should not ");
+}
+
+void closeExec(int fd)
+{
+#ifdef F_SETFD
+	fcntl(fd, F_SETFD, 1);
+#endif
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/scsi.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/scsi.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/scsi.c	(revision 9)
@@ -0,0 +1,274 @@
+/*
+ * scsi.c
+ * Iomega Zip/Jaz drive tool
+ * change protection mode and eject disk
+ */
+
+/* scis.c by Markus Gyger <mgyger@itr.ch> */
+/* This code is based on ftp://gear.torque.net/pub/ziptool.c */
+/* by Grant R. Guenther with the following copyright notice: */
+
+/*  (c) 1996   Grant R. Guenther,  based on work of Itai Nahshon  */
+/*  http://www.torque.net/ziptool.html  */
+
+
+/* A.K. Moved this from mzip.c to a separate file in order to share with
+ * plain_io.c */
+
+#include "sysincludes.h"
+#include "mtools.h"
+#include "scsi.h"
+
+#if defined OS_hpux
+#include <sys/scsi.h>
+#endif
+
+#ifdef OS_solaris
+#include <sys/scsi/scsi.h>
+#endif /* solaris */
+
+#ifdef OS_sunos
+#include <scsi/generic/commands.h>
+#include <scsi/impl/uscsi.h>
+#endif /* sunos */
+
+#ifdef sgi
+#include <sys/dsreq.h>
+#endif
+
+#ifdef OS_linux
+#define SCSI_IOCTL_SEND_COMMAND 1
+struct scsi_ioctl_command {
+    int  inlen;
+    int  outlen;
+    char cmd[5008];
+};
+#endif
+
+#ifdef _SCO_DS
+#include <sys/scsicmd.h>
+#endif
+
+#if (defined(OS_freebsd)) && (__FreeBSD__ >= 2)
+#include <camlib.h>
+#endif
+
+int scsi_max_length(void)
+{
+#ifdef OS_linux
+	return 8;
+#else
+	return 255;
+#endif
+}
+
+int scsi_open(const char *name, int flag, int mode, void **extra_data)
+{
+#if (defined(OS_freebsd)) && (__FreeBSD__ >= 2)
+    struct cam_device *cam_dev;
+    cam_dev = cam_open_device(name, O_RDWR);
+    *extra_data = (void *) cam_dev;
+    if (cam_dev)
+        return cam_dev->fd;
+    else
+        return -1;
+#else
+    return open(name, O_RDONLY
+#ifdef O_NDELAY
+		| O_NDELAY
+#endif
+	/* O_RDONLY  | dev->mode*/);
+#endif
+}
+
+int scsi_cmd(int fd, unsigned char *cdb, int cmdlen, scsi_io_mode_t mode,
+	     void *data, size_t len, void *extra_data)
+{
+#if defined OS_hpux
+	struct sctl_io sctl_io;
+	
+	memset(&sctl_io, 0, sizeof sctl_io);   /* clear reserved fields */
+	memcpy(sctl_io.cdb, cdb, cmdlen);      /* copy command */
+	sctl_io.cdb_length = cmdlen;           /* command length */
+	sctl_io.max_msecs = 2000;              /* allow 2 seconds for cmd */
+
+	switch (mode) {
+		case SCSI_IO_READ:
+			sctl_io.flags = SCTL_READ;
+			sctl_io.data_length = len;
+			sctl_io.data = data;
+			break;
+		case SCSI_IO_WRITE: 
+			sctl_io.flags = 0;
+			sctl_io.data_length = data ? len : 0;
+			sctl_io.data = len ? data : 0;
+			break;
+	}
+
+	if (ioctl(fd, SIOC_IO, &sctl_io) == -1) {
+		perror("scsi_io");
+		return -1;
+	}
+
+	return sctl_io.cdb_status;
+	
+#elif defined OS_sunos || defined OS_solaris
+	struct uscsi_cmd uscsi_cmd;
+	memset(&uscsi_cmd, 0, sizeof uscsi_cmd);
+	uscsi_cmd.uscsi_cdb = (char *)cdb;
+	uscsi_cmd.uscsi_cdblen = cmdlen;
+#ifdef OS_solaris
+	uscsi_cmd.uscsi_timeout = 20;  /* msec? */
+#endif /* solaris */
+	
+	uscsi_cmd.uscsi_buflen = (u_int)len;
+	uscsi_cmd.uscsi_bufaddr = data;
+
+	switch (mode) {
+		case SCSI_IO_READ:
+			uscsi_cmd.uscsi_flags = USCSI_READ;
+			break;
+		case SCSI_IO_WRITE:
+			uscsi_cmd.uscsi_flags = USCSI_WRITE;
+			break;
+	}
+
+	if (ioctl(fd, USCSICMD, &uscsi_cmd) == -1) {
+		perror("scsi_io");
+		return -1;
+	}
+
+	if(uscsi_cmd.uscsi_status) {
+		errno = 0;
+		fprintf(stderr,"scsi status=%x\n",  
+			(unsigned short)uscsi_cmd.uscsi_status);
+		return -1;
+	}
+	
+	return 0;
+	
+#elif defined OS_linux
+	struct scsi_ioctl_command scsi_cmd;
+
+
+	memcpy(scsi_cmd.cmd, cdb, cmdlen);        /* copy command */
+
+	switch (mode) {
+		case SCSI_IO_READ:
+			scsi_cmd.inlen = 0;
+			scsi_cmd.outlen = len;
+			break;
+		case SCSI_IO_WRITE:
+			scsi_cmd.inlen = len;
+			scsi_cmd.outlen = 0;
+			memcpy(scsi_cmd.cmd + cmdlen,data,len);
+			break;
+	}
+	
+	if (ioctl(fd, SCSI_IOCTL_SEND_COMMAND, &scsi_cmd) < 0) {
+		perror("scsi_io");
+		return -1;
+	}
+	
+	switch (mode) {
+		case SCSI_IO_READ:
+			memcpy(data, &scsi_cmd.cmd[0], len);
+			break;
+		case SCSI_IO_WRITE:
+			break;
+    }
+
+	return 0;  /* where to get scsi status? */
+
+#elif defined _SCO_DS
+	struct scsicmd scsi_cmd;
+
+	memset(scsi_cmd.cdb, 0, SCSICMDLEN);	/* ensure zero pad */
+	memcpy(scsi_cmd.cdb, cdb, cmdlen);
+	scsi_cmd.cdb_len = cmdlen;
+	scsi_cmd.data_len = len;
+	scsi_cmd.data_ptr = data;
+	scsi_cmd.is_write = mode == SCSI_IO_WRITE;
+	if (ioctl(fd,SCSIUSERCMD,&scsi_cmd) == -1) {
+		perror("scsi_io");
+		printf("scsi status: host=%x; target=%x\n",
+		(unsigned)scsi_cmd.host_sts,(unsigned)scsi_cmd.target_sts);
+		return -1;
+	}
+	return 0;
+#elif defined sgi
+ 	struct dsreq scsi_cmd;
+
+	scsi_cmd.ds_cmdbuf = (char *)cdb;
+	scsi_cmd.ds_cmdlen = cmdlen;
+	scsi_cmd.ds_databuf = data;
+	scsi_cmd.ds_datalen = len;
+       	switch (mode) {
+	case SCSI_IO_READ:
+	  scsi_cmd.ds_flags = DSRQ_READ|DSRQ_SENSE;
+	  break;
+	case SCSI_IO_WRITE:
+	  scsi_cmd.ds_flags = DSRQ_WRITE|DSRQ_SENSE;
+	  break;
+        } 
+	scsi_cmd.ds_time = 10000;
+	scsi_cmd.ds_link = 0;
+	scsi_cmd.ds_synch =0;
+	scsi_cmd.ds_ret =0;
+	if (ioctl(fd, DS_ENTER, &scsi_cmd) == -1) {
+                perror("scsi_io");
+                return -1;
+        }
+
+        if(scsi_cmd.ds_status) {
+                errno = 0;
+                fprintf(stderr,"scsi status=%x\n",  
+                        (unsigned short)scsi_cmd.ds_status);
+                return -1;
+        }
+        
+        return 0;
+#elif (defined OS_freebsd) && (__FreeBSD__ >= 2)
+#define MSG_SIMPLE_Q_TAG 0x20 /* O/O */
+      union ccb *ccb;
+      int flags;
+      int r;
+      struct cam_device *cam_dev = (struct cam_device *) extra_data;
+
+
+      if (cam_dev==NULL || cam_dev->fd!=fd)
+      {
+                fprintf(stderr,"invalid file descriptor\n");
+              return -1;
+      }
+      ccb = cam_getccb(cam_dev);
+
+      bcopy(cdb, ccb->csio.cdb_io.cdb_bytes, cmdlen);
+
+      if (mode == SCSI_IO_READ)
+              flags = CAM_DIR_IN;
+      else if (data && len)
+              flags = CAM_DIR_OUT;
+      else
+              flags = CAM_DIR_NONE;
+      cam_fill_csio(&ccb->csio,
+                    /* retry */ 1,
+                    /* cbfcnp */ NULL,
+                    flags,
+                    /* tag_action */ MSG_SIMPLE_Q_TAG,
+                    /*data_ptr*/ len ? data : 0,
+                    /*data_len */ data ? len : 0,
+                    96,
+                    cmdlen,
+                    5000);
+                    
+      if (cam_send_ccb(cam_dev, ccb) < 0 ||
+	  (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+	  return -1;
+      }
+      return 0;
+#else
+      fprintf(stderr, "scsi_io not implemented\n");
+      return -1;
+#endif
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/scsi.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/scsi.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/scsi.h	(revision 9)
@@ -0,0 +1,22 @@
+#ifndef __mtools_scsi_h
+#define __mtools_scsi_h
+
+
+#define SCSI_READ 0x8
+#define SCSI_WRITE 0xA
+#define SCSI_IOMEGA 0xC
+#define SCSI_INQUIRY 0x12
+#define SCSI_MODE_SENSE 0x1a
+#define SCSI_START_STOP 0x1b
+#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e
+#define SCSI_GROUP1 0x20
+#define SCSI_READ_CAPACITY 0x25
+
+
+typedef enum { SCSI_IO_READ, SCSI_IO_WRITE } scsi_io_mode_t;
+int scsi_max_length(void);
+int scsi_cmd(int fd, unsigned char cdb[6], int clen, scsi_io_mode_t mode,
+	     void *data, size_t len, void *extra_data);
+int scsi_open(const char *name, int flags, int mode, void **extra_data);
+
+#endif /* __mtools_scsi_h */
Index: /trunk/minix/commands/i386/mtools-3.9.7/signal.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/signal.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/signal.c	(revision 9)
@@ -0,0 +1,35 @@
+#include "sysincludes.h"
+#include "mtools.h"
+
+#undef got_signal
+
+int got_signal = 0;
+
+void signal_handler(int dummy)
+{
+	got_signal = 1;
+#if 0
+	signal(SIGHUP, SIG_IGN);
+	signal(SIGINT, SIG_IGN);
+	signal(SIGTERM, SIG_IGN);
+	signal(SIGQUIT, SIG_IGN);
+#endif
+}
+
+#if 0
+int do_gotsignal(char *f, int n)
+{
+	if(got_signal)
+		fprintf(stderr, "file=%s line=%d\n", f, n);
+	return got_signal;
+}
+#endif
+
+void setup_signal(void)
+{
+	/* catch signals */
+	signal(SIGHUP, (SIG_CAST)signal_handler);
+	signal(SIGINT, (SIG_CAST)signal_handler);
+	signal(SIGTERM, (SIG_CAST)signal_handler);
+	signal(SIGQUIT, (SIG_CAST)signal_handler);
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/stream.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/stream.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/stream.c	(revision 9)
@@ -0,0 +1,65 @@
+#include "sysincludes.h"
+#include "msdos.h"
+#include "stream.h"
+
+int batchmode = 0;
+
+int flush_stream(Stream_t *Stream)
+{
+	int ret=0;
+	if(!batchmode) {
+		if(Stream->Class->flush)
+			ret |= Stream->Class->flush(Stream);
+		if(Stream->Next)
+			ret |= flush_stream(Stream->Next);
+	}
+	return ret;
+}
+
+Stream_t *copy_stream(Stream_t *Stream)
+{
+	if(Stream)
+		Stream->refs++;
+	return Stream;
+}
+
+int free_stream(Stream_t **Stream)
+{
+	int ret=0;
+
+	if(!*Stream)
+		return -1;
+	if(! --(*Stream)->refs){
+		if((*Stream)->Class->flush)
+			ret |= (*Stream)->Class->flush(*Stream);
+		if((*Stream)->Class->freeFunc)
+			ret |= (*Stream)->Class->freeFunc(*Stream);
+		if((*Stream)->Next)
+			ret |= free_stream(&(*Stream)->Next);
+		Free(*Stream);
+	} else if ( (*Stream)->Next )
+		ret |= flush_stream((*Stream)->Next);		
+	*Stream = NULL;
+	return ret;
+}
+
+
+#define GET_DATA(stream, date, size, type, address) \
+(stream)->Class->get_data( (stream), (date), (size), (type), (address) )
+
+
+int get_data_pass_through(Stream_t *Stream, time_t *date, mt_size_t *size,
+			  int *type, int *address)
+{
+       return GET_DATA(Stream->Next, date, size, type, address);
+}
+
+int read_pass_through(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
+{
+	return READS(Stream->Next, buf, start, len);
+}
+
+int write_pass_through(Stream_t *Stream, char *buf, mt_off_t start, size_t len)
+{
+	return WRITES(Stream->Next, buf, start, len);
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/stream.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/stream.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/stream.h	(revision 9)
@@ -0,0 +1,71 @@
+#ifndef MTOOLS_STREAM_H
+#define MTOOLS_STREAM_H
+
+typedef struct Stream_t {
+	struct Class_t *Class;
+	int refs;
+	struct Stream_t *Next;
+	struct Stream_t *Buffer;
+} Stream_t;
+
+#include "mtools.h"
+#include "msdos.h"
+
+#include "llong.h"
+
+typedef struct Class_t {
+	int (*read)(Stream_t *, char *, mt_off_t, size_t);
+	int (*write)(Stream_t *, char *, mt_off_t, size_t);
+	int (*flush)(Stream_t *);
+	int (*freeFunc)(Stream_t *);
+	int (*set_geom)(Stream_t *, device_t *, device_t *, int media,
+					struct bootsector *);
+	int (*get_data)(Stream_t *, time_t *, mt_size_t *, int *, int *);
+	int (*pre_allocate)(Stream_t *, mt_size_t);
+} Class_t;
+
+#define READS(stream, buf, address, size) \
+(stream)->Class->read( (stream), (char *) (buf), (address), (size) )
+
+#define WRITES(stream, buf, address, size) \
+(stream)->Class->write( (stream), (char *) (buf), (address), (size) )
+
+#define SET_GEOM(stream, dev, orig_dev, media, boot) \
+(stream)->Class->set_geom( (stream), (dev), (orig_dev), (media), (boot) )
+
+#define GET_DATA(stream, date, size, type, address) \
+(stream)->Class->get_data( (stream), (date), (size), (type), (address) )
+
+#define PRE_ALLOCATE(stream, size) \
+(stream)->Class->pre_allocate((stream), (size))
+
+int flush_stream(Stream_t *Stream);
+Stream_t *copy_stream(Stream_t *Stream);
+int free_stream(Stream_t **Stream);
+
+#define FLUSH(stream) \
+flush_stream( (stream) )
+
+#define FREE(stream) \
+free_stream( (stream) )
+
+#define COPY(stream) \
+copy_stream( (stream) )
+
+
+#define DeclareThis(x) x *This = (x *) Stream
+
+int force_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len);
+int force_read(Stream_t *Stream, char *buf, mt_off_t start, size_t len);
+
+extern struct Stream_t *default_drive;
+
+int get_data_pass_through(Stream_t *Stream, time_t *date, mt_size_t *size,
+						  int *type, int *address);
+
+int read_pass_through(Stream_t *Stream, char *buf, mt_off_t start, size_t len);
+int write_pass_through(Stream_t *Stream, char *buf, mt_off_t start, size_t len);
+
+
+#endif
+
Index: /trunk/minix/commands/i386/mtools-3.9.7/streamcache.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/streamcache.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/streamcache.c	(revision 9)
@@ -0,0 +1,77 @@
+/*
+ * streamcache.c
+ * Managing a cache of open disks
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "vfat.h"
+#include "fs.h"
+#include "mainloop.h"
+#include "plain_io.h"
+#include "file.h"
+
+static int is_initialized = 0;
+static Stream_t *fss[256]; /* open drives */
+
+static void finish_sc(void)
+{
+	int i;
+
+	for(i=0; i<256; i++){
+		if(fss[i] && fss[i]->refs != 1 )
+			fprintf(stderr,"Streamcache allocation problem:%c %d\n",
+				i, fss[i]->refs);
+		FREE(&(fss[i]));
+	}
+}
+
+static void init_streamcache(void)
+{
+	int i;
+
+	if(is_initialized)
+		return;
+	is_initialized = 1;
+	for(i=0; i<256; i++)
+		fss[i]=0;
+	atexit(finish_sc);
+}
+
+Stream_t *open_root_dir(char *drive, int flags)
+{
+	Stream_t *Fs;
+	int i, k;
+
+	init_streamcache();
+
+	k = -1;
+	for(i=0; i<256; i++) {
+		if (fss[i] == NULL || strcmp(getDrive(fss[i]), drive) == 0) {
+			k = i;
+			break;
+		}
+	}
+
+	if(k == -1) {
+		fprintf(stderr, "Cannot initialize '%s:', out of table space\n",
+			drive);
+		return NULL;
+	}
+
+	/* open the drive */
+	if(fss[k])
+		Fs = fss[k];
+	else {
+		Fs = fs_init(drive, flags);
+		if (!Fs){
+			fprintf(stderr, "Cannot initialize '%s:'\n", drive);
+			return NULL;
+		}
+
+		fss[k] = Fs;
+	}
+
+	return OpenRoot(Fs);
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/subdir.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/subdir.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/subdir.c	(revision 9)
@@ -0,0 +1,26 @@
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "vfat.h"
+#include "file.h"
+#include "buffer.h"
+
+/*
+ * Find the directory and load a new dir_chain[].  A null directory
+ * is OK.  Returns a 1 on error.
+ */
+
+
+void bufferize(Stream_t **Dir)
+{
+	Stream_t *BDir;
+
+	if(!*Dir)
+		return;
+	BDir = buf_init(*Dir, 64*16384, 512, MDIR_SIZE);
+	if(!BDir){
+		FREE(Dir);
+		*Dir = NULL;
+	} else
+		*Dir = BDir;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/sysincludes.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/sysincludes.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/sysincludes.h	(revision 9)
@@ -0,0 +1,518 @@
+/* System includes for mtools */
+
+#ifndef SYSINCLUDES_H
+#define SYSINCLUDES_H
+
+#include "config.h"
+
+/* OS/2 needs __inline__, but for some reason is not autodetected */
+#ifdef __EMX__
+# ifndef inline
+#  define inline __inline__
+# endif
+#endif
+
+/***********************************************************************/
+/*                                                                     */
+/* OS dependancies which cannot be covered by the autoconfigure script */
+/*                                                                     */
+/***********************************************************************/
+
+
+#ifdef OS_aux
+/* A/UX needs POSIX_SOURCE, just as AIX does. Unlike SCO and AIX, it seems
+ * to prefer TERMIO over TERMIOS */
+#ifndef _POSIX_SOURCE
+# define _POSIX_SOURCE
+#endif
+#ifndef POSIX_SOURCE
+# define POSIX_SOURCE
+#endif
+
+#endif
+
+
+/* On AIX, we have to prefer strings.h, as string.h lacks a prototype 
+ * for strcasecmp. On most other architectures, it's string.h which seems
+ * to be more complete */
+#if (defined OS_aix && defined HAVE_STRINGS_H)
+# undef HAVE_STRING_H
+#endif
+
+
+#ifdef OS_ultrix
+/* on ultrix, if termios present, prefer it instead of termio */
+# ifdef HAVE_TERMIOS_H
+#  undef HAVE_TERMIO_H
+# endif
+#endif
+
+#ifdef OS_linux_gnu
+/* RMS strikes again */
+# ifndef OS_linux
+#  define OS_linux
+# endif
+#endif
+
+#ifdef OS_Minix
+/* typedef unsigned char *caddr_t; */
+#endif
+
+
+/***********************************************************************/
+/*                                                                     */
+/* Compiler dependancies                                               */
+/*                                                                     */
+/***********************************************************************/
+
+
+#if defined __GNUC__ && defined __STDC__
+/* gcc -traditional doesn't have PACKED, UNUSED and NORETURN */
+# define PACKED __attribute__ ((packed))
+# if __GNUC__ == 2 && __GNUC_MINOR__ > 6 || __GNUC__ >= 3
+/* gcc 2.6.3 doesn't have "unused" */		/* mool */
+#  define UNUSED(x) x __attribute__ ((unused));x
+# else
+#  define UNUSED(x) x
+# endif
+# define NORETURN __attribute__ ((noreturn))
+#else
+# define UNUSED(x) x
+# define PACKED /* */
+# define NORETURN /* */
+#endif
+
+
+/***********************************************************************/
+/*                                                                     */
+/* Include files                                                       */
+/*                                                                     */
+/***********************************************************************/
+
+
+#include <sys/types.h>
+
+#ifdef OS_Minix
+typedef unsigned long uoff_t;
+#define off_t uoff_t
+#endif
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#include <stdio.h>
+
+#ifndef OS_Minix
+# include <ctype.h>
+#else
+# ifdef __minix_vmd
+#  include <bsd/asciictype.h>	/* Minix-vmd: Ignore locales on purpose. */
+# else
+#  include <ctype.h>		/* Minix: What's that "locale" thing? */
+# endif
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_LINUX_UNISTD_H
+# include <linux/unistd.h>
+#endif
+
+#ifdef HAVE_LIBC_H
+# include <libc.h>
+#endif
+
+#ifdef HAVE_GETOPT_H
+# include <getopt.h>
+#else
+# ifndef OS_Minix
+int getopt();
+extern char *optarg;
+extern int optind, opterr;
+# endif
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#ifdef HAVE_SYS_FILE_H
+# include <sys/file.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+# ifndef sunos
+# include <sys/ioctl.h>
+#endif
+#endif
+/* if we don't have sys/ioctl.h, we rely on unistd to supply a prototype
+ * for it. If it doesn't, we'll only get a (harmless) warning. The idea
+ * is to get mtools compile on as many platforms as possible, but to not
+ * suppress warnings if the platform is broken, as long as these warnings do
+ * not prevent compilation */
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#ifndef NO_TERMIO
+# ifdef HAVE_TERMIO_H
+#  include <termio.h>
+# elif defined HAVE_SYS_TERMIO_H
+#  include <sys/termio.h>
+# endif
+# if !defined OS_ultrix || !(defined HAVE_TERMIO_H || defined HAVE_TERMIO_H)
+/* on Ultrix, avoid double inclusion of both termio and termios */
+#  ifdef HAVE_TERMIOS_H
+#   include <termios.h>
+#  elif defined HAVE_SYS_TERMIOS_H
+#   include <sys/termios.h>
+#  endif
+# endif
+# ifdef HAVE_STTY_H
+#  include <sgtty.h>
+# endif
+#endif
+
+
+#if defined(OS_aux) && !defined(_SYSV_SOURCE)
+/* compiled in POSIX mode, this is left out unless SYSV */
+#define	NCC	8
+struct termio {
+	unsigned short	c_iflag;	/* input modes */
+	unsigned short	c_oflag;	/* output modes */
+	unsigned short	c_cflag;	/* control modes */
+	unsigned short	c_lflag;	/* line discipline modes */
+	char	c_line;			/* line discipline */
+	unsigned char	c_cc[NCC];	/* control chars */
+};
+extern int ioctl(int fildes, int request, void *arg);
+#endif
+
+
+#ifdef HAVE_MNTENT_H
+# include <mntent.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+/* Can only be done here, as BSD is defined in sys/param.h :-( */
+#if defined BSD || defined __BEOS__
+/* on BSD and on BEOS, we prefer gettimeofday, ... */
+# ifdef HAVE_GETTIMEOFDAY
+#  undef HAVE_TZSET
+# endif
+#else /* BSD */
+/* ... elsewhere we prefer tzset */
+# ifdef HAVE_TZSET
+#  undef HAVE_GETTIMEOFDAY
+# endif
+#endif
+
+
+#include <sys/stat.h>
+
+#include <errno.h>
+extern int errno;
+
+#include <pwd.h>
+
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#else
+# ifdef HAVE_STRINGS_H
+#  include <strings.h>
+# endif
+#endif
+
+#ifdef HAVE_MEMORY_H
+# include <memory.h>
+#endif
+
+#ifdef HAVE_MALLOC_H
+# include <malloc.h>
+#endif
+
+#ifdef HAVE_SIGNAL_H
+# include <signal.h>
+#else
+# ifdef HAVE_SYS_SIGNAL_H
+#  include <sys/signal.h>
+# endif
+#endif
+
+#ifdef HAVE_UTIME_H
+# include <utime.h>
+#endif
+
+#ifdef HAVE_SYS_WAIT_H
+# ifndef DONT_NEED_WAIT
+#  include <sys/wait.h>
+# endif
+#endif
+
+
+#ifdef USE_FLOPPYD
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifdef HAVE_X11_XAUTH_H
+#include <X11/Xauth.h>
+#endif
+
+#ifdef HAVE_X11_XLIB_H
+#include <X11/Xlib.h>
+#endif
+
+#endif
+
+#ifndef INADDR_NONE
+#define INADDR_NONE (-1)
+#endif
+
+
+#ifdef sgi
+#define MSGIHACK __EXTENSIONS__
+#undef __EXTENSIONS__
+#endif
+#include <math.h>
+#ifdef sgi
+#define __EXTENSIONS__ MSGIHACK
+#undef MSGIHACK
+#endif
+
+/* missing functions */
+#ifndef HAVE_SRANDOM
+# define srandom srand48
+#endif
+
+#ifndef HAVE_RANDOM
+# define random (long)lrand48
+#endif
+
+#if __minix && !__minix_vmd
+# define srandom srand
+# define random rand
+#endif
+
+#ifndef HAVE_STRCHR
+# define strchr index
+#endif
+
+#ifndef HAVE_STRRCHR
+# define strrchr rindex
+#endif
+
+
+#define SIG_CAST RETSIGTYPE(*)()
+
+#ifndef HAVE_STRDUP
+extern char *strdup(const char *str);
+#endif /* HAVE_STRDUP */
+
+
+#ifndef HAVE_MEMCPY
+extern char *memcpy(char *s1, const char *s2, size_t n);
+#endif
+
+#ifndef HAVE_MEMSET
+extern char *memset(char *s, char c, size_t n);
+#endif /* HAVE_MEMSET */
+
+
+#ifndef HAVE_STRPBRK
+extern char *strpbrk(const char *string, const char *brkset);
+#endif /* HAVE_STRPBRK */
+
+
+#ifndef HAVE_STRTOUL
+unsigned long strtoul(const char *string, char **eptr, int base);
+#endif /* HAVE_STRTOUL */
+
+#ifndef HAVE_STRSPN
+size_t strspn(const char *s, const char *accept);
+#endif /* HAVE_STRSPN */
+
+#ifndef HAVE_STRCSPN
+size_t strcspn(const char *s, const char *reject);
+#endif /* HAVE_STRCSPN */
+
+#ifndef HAVE_STRERROR
+char *strerror(int errno);
+#endif
+
+#ifndef HAVE_ATEXIT
+int atexit(void (*function)(void)); 
+
+#ifndef HAVE_ON_EXIT
+void myexit(int code) NORETURN;
+#define exit myexit
+#endif
+
+#endif
+
+
+#ifndef HAVE_MEMMOVE
+# define memmove(DST, SRC, N) bcopy(SRC, DST, N)
+#endif
+
+#ifndef HAVE_STRCASECMP
+int strcasecmp(const char *s1, const char *s2);
+#endif
+
+#ifndef HAVE_STRNCASECMP
+int strncasecmp(const char *s1, const char *s2, size_t n);
+#endif
+
+#ifndef HAVE_GETPASS
+char *getpass(const char *prompt);
+#endif
+
+#if 0
+#ifndef HAVE_BASENAME
+const char *basename(const char *filename);
+#endif
+#endif
+
+const char *_basename(const char *filename);
+
+#ifndef __STDC__
+# ifndef signed
+#  define signed /**/
+# endif 
+#endif /* !__STDC__ */
+
+
+
+/***************************************************************************/
+/*                                                                         */
+/* Prototypes for systems where the functions exist but not the prototypes */
+/*                                                                         */
+/***************************************************************************/
+
+
+
+/* prototypes which might be missing on some platforms, even if the functions
+ * are present.  Do not declare argument types, in order to avoid conflict
+ * on platforms where the prototypes _are_ correct.  Indeed, for most of
+ * these, there are _several_ "correct" parameter definitions, and not all
+ * platforms use the same.  For instance, some use the const attribute for
+ * strings not modified by the function, and others do not.  By using just
+ * the return type, which rarely changes, we avoid these problems.
+ */
+
+/* Correction:  Now it seems that even return values are not standardized :-(
+  For instance  DEC-ALPHA, OSF/1 3.2d uses ssize_t as a return type for read
+  and write.  NextStep uses a non-void return value for exit, etc.  With the
+  advent of 64 bit system, we'll expect more of these problems in the future.
+  Better uncomment the lot, except on SunOS, which is known to have bad
+  incomplete files.  Add other OS'es with incomplete include files as needed
+  */
+#if (defined OS_sunos || defined OS_ultrix)
+int read();
+int write();
+int fflush();
+char *strdup();
+int strcasecmp();
+int strncasecmp();
+char *getenv();
+unsigned long strtoul();
+int pclose();
+void exit();
+char *getpass();
+int atoi();
+FILE *fdopen();
+FILE *popen();
+#endif
+
+#ifndef MAXPATHLEN
+# ifdef PATH_MAX
+#  define MAXPATHLEN PATH_MAX
+# else
+#  define MAXPATHLEN 1024
+# endif
+#endif
+
+
+#ifndef OS_linux
+# undef USE_XDF
+#endif
+
+#ifdef NO_XDF
+# undef USE_XDF
+#endif
+
+#ifdef __EMX__
+#define INCL_BASE
+#define INCL_DOSDEVIOCTL
+#include <os2.h>
+#endif
+
+#ifdef OS_nextstep
+/* nextstep doesn't have this.  Unfortunately, we cannot test its presence
+   using AC_EGREP_HEADER, as we don't know _which_ header to test, and in
+   the general case utime.h might be non-existent */
+struct utimbuf
+{
+  time_t actime,modtime;
+};
+#endif
+
+/* NeXTStep doesn't have these */
+#if !defined(S_ISREG) && defined (_S_IFMT) && defined (_S_IFREG)
+#define S_ISREG(mode)   (((mode) & (_S_IFMT)) == (_S_IFREG))
+#endif
+
+#if !defined(S_ISDIR) && defined (_S_IFMT) && defined (_S_IFDIR)
+#define S_ISDIR(mode)   (((mode) & (_S_IFMT)) == (_S_IFDIR))
+#endif
+
+
+#if 0
+
+#define malloc(x) mymalloc(x)
+#define calloc(x,y) mycalloc(x,y)
+#define free(x) myfree(x)
+#define realloc(x,y) myrealloc(x,y)
+#define strdup(a) mystrdup(a)
+
+void *mycalloc(size_t nmemb, size_t size);
+void *mymalloc(size_t size);
+void myfree(void *ptr);
+void *myrealloc(void *ptr, size_t size);
+char *mystrdup(char *a);
+
+#endif
+
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/toupper.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/toupper.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/toupper.c	(revision 9)
@@ -0,0 +1,491 @@
+#include "codepage.h"
+
+/* MS-DOS doesn't use the same ASCII code as Unix does. The appearance
+ * of the characters is defined using code pages. These code pages
+ * aren't the same for all countries. For instance, some code pages
+ * don't contain upper case accented characters. This affects two
+ * things, relating to filenames:
+
+ * 1. upper case characters. In short names, only upper case
+ * characters are allowed.  This also holds for accented characters.
+ * For instance, in a code page which doesn't contain accented
+ * uppercase characters, the accented lowercase characters get
+ * transformed into their unaccented counterparts. This is very bad
+ * design. Indeed, stuff like national language support should never
+ * affect filesystem integrity. And it does: A filename which is legal
+ * in one country could be illegal in another one. Bad News for
+ * frequent travellers.
+
+ * 2. long file names: Micro$oft has finally come to their senses and
+ * uses a more standard mapping for the long file names.  They use
+ * Unicode, which is basically a 32 bit version of ASCII. Its first
+ * 256 characters are identical to Unix ASCII. Thus, the code page
+ * also affects the correspondence between the codes used in long
+ * names and those used in short names.
+
+ * Such a bad design is rather unbelievable. That's why I quoted the
+ * translation tables. BEGIN FAIR USE EXCERPT:
+ */
+
+unsigned char toucase[][128]={
+	/* 0 */
+	/* 437 German Umlauts upcased, French accents 
+	 * upcased and lose accent */
+	{ 0x80, 0x9a, 0x45, 0x41, 0x8e, 0x41, 0x8f, 0x80, 
+	  0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x8e, 0x8f, 
+	  0x90, 0x92, 0x92, 0x4f, 0x99, 0x4f, 0x55, 0x55, 
+	  0x59, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 
+	  0x41, 0x49, 0x4f, 0x55, 0xa5, 0xa5, 0xa6, 0xa7, 
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 
+	  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 
+	  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 
+	  0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 
+	  0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 
+	  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
+	  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+
+	/* 1 */
+	{ 0x43, 0x55, 0x45, 0x41, 0x41, 0x41, 0x86, 0x43, 
+	  0x45, 0x45, 0x45, 0x49, 0x49, 0x8d, 0x41, 0x8f, 
+	  0x45, 0x45, 0x45, 0x4f, 0x45, 0x49, 0x55, 0x55, 
+	  0x98, 0x4f, 0x55, 0x9b, 0x9c, 0x55, 0x55, 0x9f, 
+	  0xa0, 0xa1, 0x4f, 0x55, 0xa4, 0xa5, 0xa6, 0xa7, 
+	  0x49, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 
+	  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 
+	  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 
+	  0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 
+	  0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 
+	  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
+	  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+
+	/* 2 */
+	{ 0x80, 0x9a, 0x90, 0x41, 0x8e, 0x41, 0x8f, 0x80, 
+	  0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x8e, 0x8f, 
+	  0x90, 0x92, 0x92, 0x4f, 0x99, 0x4f, 0x55, 0x55, 
+	  0x59, 0x99, 0x9a, 0x9d, 0x9c, 0x9d, 0x9e, 0x9f, 
+	  0x41, 0x49, 0x4f, 0x55, 0xa5, 0xa5, 0xa6, 0xa7, 
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 
+	  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 
+	  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 
+	  0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 
+	  0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 
+	  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
+	  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+
+	/* 3 */
+	{ 0x80, 0x9a, 0x90, 0x41, 0x8e, 0x41, 0x8f, 0x80, 
+	  0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x8e, 0x8f, 
+	  0x90, 0x92, 0x92, 0x4f, 0x99, 0x4f, 0x55, 0x55, 
+	  0x59, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 
+	  0x41, 0x49, 0x4f, 0x55, 0xa5, 0xa5, 0xa6, 0xa7, 
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 
+	  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 
+	  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 
+	  0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 
+	  0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 
+	  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
+	  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+
+	/* 4 
+	 * 437: all accented characters lose their accent */
+	{ 0x80, 0x55, 0x45, 0x41, 0x41, 0x41, 0x8f, 0x80, 
+	  0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x41, 0x8f, 
+	  0x45, 0x92, 0x92, 0x4f, 0x4f, 0x4f, 0x55, 0x55, 
+	  0x98, 0x4f, 0x55, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 
+	  0x41, 0x49, 0x4f, 0x55, 0xa5, 0xa5, 0xa6, 0xa7, 
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 
+	  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 
+	  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 
+	  0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 
+	  0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 
+	  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
+	  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+
+	/* 5 */
+	{ 0x80, 0x9a, 0x90, 0x8f, 0x8e, 0x91, 0x86, 0x80, 
+	  0x89, 0x89, 0x92, 0x8b, 0x8c, 0x98, 0x8e, 0x8f, 
+	  0x90, 0x91, 0x92, 0x8c, 0x99, 0xa9, 0x96, 0x9d, 
+	  0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 
+	  0x86, 0x8b, 0x9f, 0x96, 0xa5, 0xa5, 0xa6, 0xa7, 
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 
+	  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 
+	  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 
+	  0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 
+	  0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 
+	  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
+	  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+
+	/* 6 All accented characters lose their accent
+	   when upcased. C loses cedilla. æ upcased. ø
+	   loses slash. Ð, ñ, ß intact */
+	{ 0x43, 0x55, 0x45, 0x41, 0x41, 0x41, 0x41, 0x43, 
+	  0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x41, 0x41, 
+	  0x45, 0x92, 0x92, 0x4f, 0x4f, 0x4f, 0x55, 0x55, 
+	  0x59, 0x4f, 0x55, 0x4f, 0x9c, 0x4f, 0x9e, 0x9f, 
+	  0x41, 0x49, 0x4f, 0x55, 0xa5, 0xa5, 0xa6, 0xa7, 
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0x41, 0x41, 0x41, 
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0x41, 0x41, 
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 
+	  0xd1, 0xd1, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 
+	  0x49, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0x49, 0xdf, 
+	  0x4f, 0xe1, 0x4f, 0x4f, 0x4f, 0x4f, 0xe6, 0xe8, 
+	  0xe8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xee, 0xef, 
+	  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
+	  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+
+	/* 7: As 6, but German Umlauts keep their Umlaut */
+	{ 0x43, 0x9a, 0x45, 0x41, 0x8e, 0x41, 0x41, 0x43, 
+	  0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x8e, 0x41, 
+	  0x45, 0x92, 0x92, 0x4f, 0x99, 0x4f, 0x55, 0x55, 
+	  0x59, 0x99, 0x9a, 0x4f, 0x9c, 0x4f, 0x9e, 0x9f, 
+	  0x41, 0x49, 0x4f, 0x55, 0xa5, 0xa5, 0xa6, 0xa7, 
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0x41, 0x41, 0x41, 
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0x41, 0x41, 
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 
+	  0xd1, 0xd1, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 
+	  0x49, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0x49, 0xdf, 
+	  0x4f, 0xe1, 0x4f, 0x4f, 0x4f, 0x4f, 0xe6, 0xe8, 
+	  0xe8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xee, 0xef, 
+	  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
+	  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+
+	/* 8: All characters except ÿ keep their accent
+	 */
+	{ 0x80, 0x9a, 0x90, 0xb6, 0x8e, 0xb7, 0x8f, 0x80, 
+	  0xd2, 0xd3, 0xd4, 0xd8, 0xd7, 0xde, 0x8e, 0x8f, 
+	  0x90, 0x92, 0x92, 0xe2, 0x99, 0xe3, 0xea, 0xeb, 
+	  0x59, 0x99, 0x9a, 0x9d, 0x9c, 0x9d, 0x9e, 0x9f, 
+	  0xb5, 0xd6, 0xe0, 0xe9, 0xa5, 0xa5, 0xa6, 0xa7, 
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc7, 0xc7, 
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 
+	  0xd1, 0xd1, 0xd2, 0xd3, 0xd4, 0x49, 0xd6, 0xd7, 
+	  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 
+	  0xe0, 0xe1, 0xe2, 0xe3, 0xe5, 0xe5, 0xe6, 0xe8, 
+	  0xe8, 0xe9, 0xea, 0xeb, 0xed, 0xed, 0xee, 0xef, 
+	  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
+	  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+
+	/* 9: As 6, but Ç and Å preserved */
+	{ 0x80, 0x55, 0x45, 0x41, 0x41, 0x41, 0x8f, 0x80, 
+	  0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x41, 0x8f, 
+	  0x45, 0x92, 0x92, 0x4f, 0x4f, 0x4f, 0x55, 0x55, 
+	  0x98, 0x4f, 0x55, 0x4f, 0x9c, 0x4f, 0x9e, 0x9f, 
+	  0x41, 0x49, 0x4f, 0x55, 0xa5, 0xa5, 0xa6, 0xa7, 
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0x41, 0x41, 0x41, 
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0x41, 0x41, 
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 
+	  0xd1, 0xd1, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 
+	  0x49, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0x49, 0xdf, 
+	  0x4f, 0xe1, 0x4f, 0x4f, 0x4f, 0x4f, 0xe6, 0xe8, 
+	  0xe8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xee, 0xef, 
+	  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
+	  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+
+	/* 10: every accented character keeps its accent */
+	{ 0x80, 0x9a, 0x90, 0xb6, 0x8e, 0xb7, 0x8f, 0x80, 
+	  0xd2, 0xd3, 0xd4, 0xd8, 0xd7, 0xde, 0x8e, 0x8f, 
+	  0x90, 0x92, 0x92, 0xe2, 0x99, 0xe3, 0xea, 0xeb, 
+	  0x98, 0x99, 0x9a, 0x9d, 0x9c, 0x9d, 0x9e, 0x9f, 
+	  0xb5, 0xd6, 0xe0, 0xe9, 0xa5, 0xa5, 0xa6, 0xa7, 
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc7, 0xc7, 
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 
+	  0xd1, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 
+	  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 
+	  0xe0, 0xe1, 0xe2, 0xe3, 0xe5, 0xe5, 0xe6, 0xe8, 
+	  0xe8, 0xe9, 0xea, 0xeb, 0xed, 0xed, 0xee, 0xef, 
+	  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
+	  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+
+	/* 11 */
+	{ 0x80, 0x9a, 0x90, 0xb6, 0x8e, 0xde, 0x8f, 0x80, 
+	  0x9d, 0xd3, 0x8a, 0x8a, 0xd7, 0x8d, 0x8e, 0x8f, 
+	  0x90, 0x91, 0x91, 0xe2, 0x99, 0x95, 0x95, 0x97, 
+	  0x97, 0x99, 0x9a, 0x9b, 0x9b, 0x9d, 0x9e, 0xac, 
+	  0xb5, 0xd6, 0xe0, 0xe9, 0xa4, 0xa4, 0xa6, 0xa6, 
+	  0xa8, 0xa8, 0xaa, 0x8d, 0xac, 0xb8, 0xae, 0xaf, 
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbd, 0xbf, 
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, 
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 
+	  0xd1, 0xd1, 0xd2, 0xd3, 0xd2, 0xd5, 0xd6, 0xd7, 
+	  0xb7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 
+	  0xe0, 0xe1, 0xe2, 0xe3, 0xe3, 0xd5, 0xe6, 0xe6, 
+	  0xe8, 0xe9, 0xe8, 0xeb, 0xed, 0xed, 0xdd, 0xef, 
+	  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
+	  0xf8, 0xf9, 0xfa, 0xeb, 0xfc, 0xfc, 0xfe, 0xff },
+
+
+	/* 14 All accented characters lose their accent, C loses cedilla,
+	 * ø loses slash.  æ upcased. Ð, ñ, ß intact */
+	{ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	  0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+
+	  0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+	  0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+
+	  0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+
+	  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0xc6, 0x43,
+	  0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
+
+	  0xd0, 0xd1, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0xd7,
+	  0x4f, 0x55, 0x55, 0x55, 0x55, 0x59, 0xde, 0xdf,
+
+	  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0xc6, 0x43,
+	  0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
+
+	  0xd0, 0xd1, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0xf7,
+	  0x4f, 0x55, 0x55, 0x55, 0x55, 0x59, 0xde, 0x59  },
+
+
+
+	/* 15 as 14, but German Umlauts (ä, ö, ü) keep their Umlaut when
+	   upcased */
+	{ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	  0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+
+	  0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+	  0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+
+	  0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+
+	  0x41, 0x41, 0x41, 0x41, 0xc4, 0x41, 0xc6, 0x43,
+	  0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
+
+	  0xd0, 0xd1, 0x4f, 0x4f, 0x4f, 0x4f, 0xd6, 0xd7,
+	  0x4f, 0x55, 0x55, 0x55, 0xdc, 0x59, 0xde, 0xdf,
+
+	  0x41, 0x41, 0x41, 0x41, 0xc4, 0x41, 0xc6, 0x43,
+	  0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
+
+	  0xd0, 0xd1, 0x4f, 0x4f, 0x4f, 0x4f, 0xd6, 0xf7,
+	  0x4f, 0x55, 0x55, 0x55, 0xdc, 0x59, 0xde, 0x59  },
+
+
+	/* 16 every accented character except ÿ keeps its accent */
+	{ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	  0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+
+	  0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+	  0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+
+	  0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+
+	  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+	  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+
+	  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xf7,
+	  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x59 },
+
+
+
+	/* 17: As 6, but Ç, Å and ÿ preserved */
+	{ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	  0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+
+	  0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+	  0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+
+	  0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+
+	  0x41, 0x41, 0x41, 0x41, 0x41, 0xc5, 0xc6, 0xc7,
+	  0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
+
+	  0xd0, 0xd1, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0xd7,
+	  0x4f, 0x55, 0x55, 0x55, 0x55, 0x59, 0xde, 0xdf,
+
+	  0x41, 0x41, 0x41, 0x41, 0x41, 0xc5, 0xc6, 0xc7,
+	  0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
+
+	  0xd0, 0xd1, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0xf7,
+	  0x4f, 0x55, 0x55, 0x55, 0x55, 0x59, 0xde, 0xff  },
+
+
+	/* 18 every accented character keeps its accent */
+	{ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	  0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+
+	  0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+	  0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+
+	  0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+
+	  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+	  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+
+	  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xf7,
+	  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xff },
+
+
+	/* 19 */
+	{ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	  0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+	  0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+	  0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+	  0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+	  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+	  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+	  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+	  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+	  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+	  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+	  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+	  0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+	  0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+	  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+	  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
+
+};
+
+country_t countries[]={
+	{   1, 437, 437,   0 },
+	{   1, 850, 437,   6 },
+	{   1, 819, 437,  14 },
+	{  44, 437, 437,   0 },
+	{  44, 850, 437,   6 },
+	{  44, 819, 437,  14 },
+	{  33, 437, 437,   0 },
+	{  33, 850, 437,   6 },
+	{  33, 819, 437,  14 },
+	{  49, 437, 437,   0 },
+	{  49, 850, 437,   7 },
+	{  49, 819, 437,  15 },
+	{  34, 850, 437,   8 },
+	{  34, 819, 437,  16 },
+	{  34, 437, 437,   0 },
+	{  39, 437, 437,   0 },
+	{  39, 850, 437,   6 },
+	{  39, 819, 437,  14 },
+	{  46, 437, 437,   3 },
+	{  46, 850, 437,   8 },
+	{  46, 819, 437,  16 },
+	{  45, 850, 865,   8 },
+	{  45, 819, 865,  16 },
+	{  45, 865, 865,   2 },
+	{  41, 850, 437,   8 },
+	{  41, 819, 437,  16 },
+	{  41, 437, 437,   3 },
+	{  47, 850, 865,   8 },
+	{  47, 819, 865,  16 },
+	{  47, 865, 865,   2 },
+	{  31, 437, 437,   4 },
+	{  31, 850, 437,   9 },
+	{  31, 819, 437,  17 },
+	{  32, 850, 437,   8 },
+	{  32, 819, 437,  16 },
+	{  32, 437, 437,   3 },
+	{ 358, 850, 437,   8 },
+	{ 358, 819, 437,  16 },
+	{ 358, 437, 437,   3 },
+	{   2, 863, 863,   1 },
+	{   2, 850, 863,   6 },
+	{   2, 819, 863,  14 },
+	{ 351, 850, 860,   6 },
+	{ 351, 819, 860,  14 },
+	{ 351, 860, 860,   5 },
+	{   3, 850, 437,   8 },
+	{   3, 819, 437,  16 },
+	{   3, 437, 437,   0 },
+	{  61, 437, 437,   0 },
+	{  61, 850, 437,   6 },
+	{  61, 819, 437,  16 },
+	{  81, 437, 437,   0 },
+	{  81, 819, 437,  14 },
+	{  82, 437, 437,   0 },
+	{  82, 819, 437,  14 },
+	{  86, 437, 437,   0 },
+	{  86, 819, 437,  14 },
+	{  88, 437, 437,   0 },
+	{  88, 819, 437,  14 },
+	{  55, 850, 850,  10 },
+	{  55, 819, 850,  18 },
+	{  55, 437, 850,   0 },
+	{ 354, 850, 850,  10 },
+	{ 354, 819, 850,  18 },
+	{  90, 850, 850,  10 },
+	{  90, 819, 850,  18 },
+	{  38, 852, 852,  11 },
+	{  38, 850, 852,  10 },
+	{  38, 819, 852,  18 },
+	{  42, 852, 852,  11 },
+	{  42, 850, 852,  10 },
+	{  42, 819, 852,  18 },
+	{  48, 852, 852,  11 },
+	{  48, 850, 852,  10 },
+	{  48, 819, 852,  18 },
+	{  36, 852, 852,  11 },
+	{  36, 850, 852,  10 },
+	{  36, 819, 852,  18 },
+	{ 886, 950, 950,  19 }, 	/* for Taiwan support (Country code) */
+	{   0,   0,   0,   0 }
+};
+
+/* END FAIR USE EXCERPT */
Index: /trunk/minix/commands/i386/mtools-3.9.7/tty.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/tty.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/tty.c	(revision 9)
@@ -0,0 +1,201 @@
+#include "sysincludes.h"
+#include "mtools.h"
+
+static FILE *tty=NULL;
+static int notty=0;	
+static int ttyfd=-1;
+#ifdef USE_RAWTERM
+int	mtools_raw_tty = 1;
+#else
+int	mtools_raw_tty = 0;
+#endif
+
+#ifdef USE_RAWTERM
+# if defined TCSANOW && defined HAVE_TCSETATTR
+/* we have tcsetattr & tcgetattr. Good */
+typedef struct termios Terminal;
+#  define stty(a,b)        (void)tcsetattr(a,TCSANOW,b)
+#  define gtty(a,b)        (void)tcgetattr(a,b)
+#  define USE_TCIFLUSH
+
+# elif defined TCSETS && defined TCGETS
+typedef struct termios Terminal;
+#  define stty(a,b) (void)ioctl(a,TCSETS,(char *)b)
+#  define gtty(a,b) (void)ioctl(a,TCGETS,(char *)b)
+#  define USE_TCIFLUSH
+
+# elif defined TCSETA && defined TCGETA
+typedef struct termio Terminal;
+#  define stty(a,b) (void)ioctl(a,TCSETA,(char *)b)
+#  define gtty(a,b) (void)ioctl(a,TCGETA,(char *)b)
+#  define USE_TCIFLUSH
+
+# elif defined(HAVE_SGTTY_H) && defined(TIOCSETP) && defined(TIOCGETP)
+typedef struct sgttyb Terminal;
+#  define stty(a,b) (void)ioctl(a,TIOCSETP,(char *)b)
+#  define gtty(a,b) (void)ioctl(a,TIOCGETP,(char *)b)
+#  define USE_SGTTY
+#  define discard_input(a) /**/
+
+# else
+/* no way to use raw terminal */
+/*
+#  warning Cannot use raw terminal code (disabled)
+*/
+#  undef USE_RAWTERM
+# endif
+
+#endif
+
+#ifdef USE_TCIFLUSH
+# if defined TCIFLUSH && defined HAVE_TCFLUSH
+#  define discard_input(a) tcflush(a,TCIFLUSH)
+# else
+#  define discard_input(a) /**/
+# endif
+#endif
+
+#ifdef USE_RAWTERM
+
+static int tty_mode = -1; /* 1 for raw, 0 for cooked, -1 for initial */
+static int need_tty_reset = 0;
+static int handlerIsSet = 0;
+
+#define restore_tty(a) stty(STDIN,a)
+
+
+#define STDIN ttyfd
+#define FAIL (-1)
+#define DONE 0
+static Terminal in_orig;
+
+/*--------------- Signal Handler routines -------------*/
+
+static void tty_time_out(void)
+{
+	int exit_code;
+	signal(SIGALRM, SIG_IGN);
+	if(tty && need_tty_reset)
+		restore_tty (&in_orig);	
+#if future
+	if (fail_on_timeout)
+		exit_code=SHFAIL;
+	else {
+		if (default_choice && mode_defined) {
+			if (yes_no) {
+				if ('Y' == default_choice)
+					exit_code=0;
+				else
+					exit_code=1;
+			} else
+				exit_code=default_choice-minc+1;
+		} else
+			exit_code=DONE;
+	}
+#else
+	exit_code = DONE;
+#endif
+	exit(exit_code);
+}
+
+static void cleanup_tty(void)
+{ 
+	if(tty && need_tty_reset) {
+		restore_tty (&in_orig);
+		setup_signal();
+	}
+}
+
+static void set_raw_tty(int mode)
+{
+	Terminal in_raw;
+
+	if(mode != tty_mode && mode != -1) {
+		if(!handlerIsSet) {
+			/* Determine existing TTY settings */
+			gtty (STDIN, &in_orig);
+			need_tty_reset = 1;
+
+			/* Restore original TTY settings on exit */
+			atexit(cleanup_tty);
+			handlerIsSet = 1;
+		}
+
+
+		setup_signal();
+		signal (SIGALRM, (SIG_CAST) tty_time_out);
+	
+		/* Change STDIN settings to raw */
+
+		gtty (STDIN, &in_raw);
+		if(mode) {
+#ifdef USE_SGTTY
+			in_raw.sg_flags |= CBREAK;
+#else
+			in_raw.c_lflag &= ~ICANON;
+			in_raw.c_cc[VMIN]=1;
+			in_raw.c_cc[VTIME]=0;			
+#endif
+			stty (STDIN, &in_raw);
+		} else {
+#ifdef USE_SGTTY
+			in_raw.sg_flags &= ~CBREAK;
+#else
+			in_raw.c_lflag |= ICANON;
+#endif
+			stty (STDIN, &in_raw);
+		}
+		tty_mode = mode;
+		discard_input(STDIN);
+	}
+}
+#endif
+
+FILE *opentty(int mode)
+{
+	if(notty)
+		return NULL;
+	if (tty == NULL) {
+		ttyfd = open("/dev/tty", O_RDONLY);
+		if(ttyfd >= 0) {
+			tty = fdopen(ttyfd, "r");
+		}
+	}
+	if  (tty == NULL){
+		if ( !isatty(0) ){
+			notty = 1;
+			return NULL;
+		}
+		ttyfd = 0;
+		tty = stdin;
+	}
+#ifdef USE_RAWTERM
+	if(mtools_raw_tty)
+		set_raw_tty(mode);
+#endif
+	return tty;
+}
+
+int ask_confirmation(const char *format, const char *p1, const char *p2)
+{
+	char ans[10];
+
+	if(!opentty(-1))
+		return 0;
+
+	while (1) {
+		fprintf(stderr, format, p1, p2);
+		fflush(stderr);
+		fflush(opentty(-1));
+		if (mtools_raw_tty) {
+			ans[0] = fgetc(opentty(1));
+			fputs("\n", stderr);
+		} else {
+			fgets(ans,9, opentty(0));
+		}
+		if (ans[0] == 'y' || ans[0] == 'Y')
+			return 0;
+		if (ans[0] == 'n' || ans[0] == 'N')
+			return -1;
+	}
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/unixdir.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/unixdir.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/unixdir.c	(revision 9)
@@ -0,0 +1,144 @@
+#include "sysincludes.h"
+#include "msdos.h"
+#include "stream.h"
+#include "mtools.h"
+#include "fsP.h"
+#include "file.h"
+#include "htable.h"
+#include "mainloop.h"
+#include <dirent.h>
+
+typedef struct Dir_t {
+	Class_t *Class;
+	int refs;
+	Stream_t *Next;
+	Stream_t *Buffer;
+
+	struct stat stat;
+	char *pathname;
+	DIR *dir;
+#ifdef HAVE_FCHDIR
+	int fd;
+#endif
+} Dir_t;
+
+/*#define FCHDIR_MODE*/
+
+static int get_dir_data(Stream_t *Stream, time_t *date, mt_size_t *size,
+			int *type, int *address)
+{
+	DeclareThis(Dir_t);
+
+	if(date)
+		*date = This->stat.st_mtime;
+	if(size)
+		*size = (mt_size_t) This->stat.st_size;
+	if(type)
+		*type = 1;
+	if(address)
+		*address = 0;
+	return 0;
+}
+
+static int dir_free(Stream_t *Stream)
+{
+	DeclareThis(Dir_t);
+
+	Free(This->pathname);
+	closedir(This->dir);
+	return 0;
+}
+
+static Class_t DirClass = { 
+	0, /* read */
+	0, /* write */
+	0, /* flush */
+	dir_free, /* free */
+	0, /* get_geom */
+	get_dir_data ,
+	0 /* pre-allocate */
+};
+
+#ifdef HAVE_FCHDIR
+#define FCHDIR_MODE
+#endif
+
+int unix_dir_loop(Stream_t *Stream, MainParam_t *mp); 
+int unix_loop(Stream_t *Stream, MainParam_t *mp, char *arg, 
+	      int follow_dir_link);
+
+int unix_dir_loop(Stream_t *Stream, MainParam_t *mp)
+{
+	DeclareThis(Dir_t);
+	struct dirent *entry;
+	char *newName;
+	int ret=0;
+
+#ifdef FCHDIR_MODE
+	int fd;
+
+	fd = open(".", O_RDONLY);
+	chdir(This->pathname);
+#endif
+	while((entry=readdir(This->dir)) != NULL) {
+		if(got_signal)
+			break;
+		if(isSpecial(entry->d_name))
+			continue;
+#ifndef FCHDIR_MODE
+		newName = malloc(strlen(This->pathname) + 1 + 
+				 strlen(entry->d_name) + 1);
+		if(!newName) {
+			ret = ERROR_ONE;
+			break;
+		}
+		strcpy(newName, This->pathname);
+		strcat(newName, "/");
+		strcat(newName, entry->d_name);
+#else
+		newName = entry->d_name;
+#endif
+		ret |= unix_loop(Stream, mp, newName, 0);
+#ifndef FCHDIR_MODE
+		free(newName);
+#endif
+	}
+#ifdef FCHDIR_MODE
+	fchdir(fd);
+	close(fd);
+#endif
+	return ret;
+}
+
+Stream_t *OpenDir(Stream_t *Stream, const char *filename)
+{
+	Dir_t *This;
+
+	This = New(Dir_t);
+	
+	This->Class = &DirClass;
+	This->Next = 0;
+	This->refs = 1;
+	This->Buffer = 0;
+	This->pathname = malloc(strlen(filename)+1);
+	if(This->pathname == NULL) {
+		Free(This);
+		return NULL;
+	}
+	strcpy(This->pathname, filename);
+
+	if(stat(filename, &This->stat) < 0) {
+		Free(This->pathname);
+		Free(This);
+		return NULL;
+	}
+
+	This->dir = opendir(filename);
+	if(!This->dir) {
+		Free(This->pathname);
+		Free(This);
+		return NULL;
+	}
+
+	return (Stream_t *) This;
+}
Index: /trunk/minix/commands/i386/mtools-3.9.7/vfat.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/vfat.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/vfat.c	(revision 9)
@@ -0,0 +1,748 @@
+/* vfat.c
+ *
+ * Miscellaneous VFAT-related functions
+ */
+
+#include "sysincludes.h"
+#include "msdos.h"
+#include "mtools.h"
+#include "vfat.h"
+#include "file.h"
+#include "dirCache.h"
+
+/* #define DEBUG */
+
+const char *short_illegals=";+=[]',\"*\\<>/?:|";
+const char *long_illegals = "\"*\\<>/?:|\005";
+
+/* Automatically derive a new name */
+static void autorename(char *name,
+		       char tilda, char dot, const char *illegals,
+		       int limit, int bump)
+{
+	int tildapos, dotpos;
+	unsigned int seqnum=0, maxseq=0;
+	char tmp;
+	char *p;
+	
+#ifdef DEBUG
+	printf("In autorename for name=%s.\n", name);
+#endif
+	tildapos = -1;
+
+	for(p=name; *p ; p++)
+		if((*p < ' ' && *p != '\005') || strchr(illegals, *p)) {
+			*p = '_';
+			bump = 0;
+		}
+
+	for(dotpos=0;
+	    name[dotpos] && dotpos < limit && name[dotpos] != dot ;
+	    dotpos++) {
+		if(name[dotpos] == tilda) {
+			tildapos = dotpos;
+			seqnum = 0;
+			maxseq = 1;
+		} else if (name[dotpos] >= '0' && name[dotpos] <= '9') {
+			seqnum = seqnum * 10 + name[dotpos] - '0';
+			maxseq = maxseq * 10;
+		} else
+			tildapos = -1; /* sequence number interrupted */
+	}
+	if(tildapos == -1) {
+		/* no sequence number yet */
+		if(dotpos > limit - 2) {
+			tildapos = limit - 2;
+			dotpos = limit;
+		} else {
+			tildapos = dotpos;
+			dotpos += 2;
+		}
+		seqnum = 1;
+	} else {
+		if(bump)
+			seqnum++;
+		if(seqnum > 999999) {
+			seqnum = 1;
+			tildapos = dotpos - 2;
+			/* this matches Win95's behavior, and also guarantees
+			 * us that the sequence numbers never get shorter */
+		}
+		if (seqnum == maxseq) {
+		    if(dotpos >= limit)
+			tildapos--;
+		    else
+			dotpos++;
+		}
+	}
+
+	tmp = name[dotpos];
+	if((bump && seqnum == 1) || seqnum > 1 || mtools_numeric_tail)
+		sprintf(name+tildapos,"%c%d",tilda, seqnum);
+	if(dot)
+	    name[dotpos]=tmp;
+	/* replace the character if it wasn't a space */
+}
+
+
+void autorename_short(char *name, int bump)
+{
+	autorename(name, '~', ' ', short_illegals, 8, bump);
+}
+
+void autorename_long(char *name, int bump)
+{
+	autorename(name, '-', '\0', long_illegals, 255, bump);
+}
+
+
+static inline int unicode_read(struct unicode_char *in, char *out, int num)
+{
+	char *end_out = out+num;
+
+	while(out < end_out) {
+		if (in->uchar)
+			*out = '_';
+		else
+			*out = in->lchar;
+		++out;
+		++in;
+	}
+	return num;
+}
+
+
+void clear_vfat(struct vfat_state *v)
+{
+	v->subentries = 0;
+	v->status = 0;
+	v->present = 0;
+}
+
+
+/* sum_shortname
+ *
+ * Calculate the checksum that results from the short name in *dir.
+ *
+ * The sum is formed by circularly right-shifting the previous sum
+ * and adding in each character, from left to right, padding both
+ * the name and extension to maximum length with spaces and skipping
+ * the "." (hence always summing exactly 11 characters).
+ * 
+ * This exact algorithm is required in order to remain compatible
+ * with Microsoft Windows-95 and Microsoft Windows NT 3.5.
+ * Thanks to Jeffrey Richter of Microsoft Systems Journal for
+ * pointing me to the correct algorithm.
+ *
+ * David C. Niemi (niemi@tux.org) 95.01.19
+ */
+static inline unsigned char sum_shortname(char *name)
+{
+	unsigned char sum;
+	char *end = name+11;
+
+	for (sum=0; name<end; ++name)
+		sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) 
+		  + (*name ? *name : ' ');
+	return(sum);
+}
+
+/* check_vfat
+ *
+ * Inspect a directory and any associated VSEs.
+ * Return 1 if the VSEs comprise a valid long file name,
+ * 0 if not.
+ */
+static inline void check_vfat(struct vfat_state *v, struct directory *dir)
+{
+	char name[12];
+
+	if (! v->subentries) {
+#ifdef DEBUG
+		fprintf(stderr, "check_vfat: no VSEs.\n");
+#endif
+		return;
+	}
+
+	strncpy((char *)name, (char *)dir->name, 8);
+	strncpy((char *)name + 8, (char *)dir->ext, 3);
+	name[11] = '\0';
+
+	if (v->sum != sum_shortname(name))
+		return;
+	
+	if( (v->status & ((1<<v->subentries) - 1)) != (1<<v->subentries) - 1)
+		return; /* missing entries */
+
+	/* zero out byte following last entry, for good measure */
+	v->name[VSE_NAMELEN * v->subentries] = 0;
+	v->present = 1;
+}
+
+
+int clear_vses(Stream_t *Dir, int entrySlot, size_t last)
+{
+	direntry_t entry;
+	dirCache_t *cache;
+	int error;
+
+	entry.Dir = Dir;
+	entry.entry = entrySlot;
+
+	/*maximize(last, entry.entry + MAX_VFAT_SUBENTRIES);*/
+	cache = allocDirCache(Dir, last);
+	if(!cache) {
+		fprintf(stderr, "Out of memory error in clear_vses\n");
+		exit(1);
+	}
+	addFreeEntry(cache, entry.entry, last);
+	for (; entry.entry < last; ++entry.entry) {
+#ifdef DEBUG
+		fprintf(stderr,"Clearing entry %d.\n", entry.entry);
+#endif
+		dir_read(&entry, &error);
+		if(error)
+		    return error;
+		if(!entry.dir.name[0] || entry.dir.name[0] == DELMARK)
+			break;
+		entry.dir.name[0] = DELMARK;
+		if (entry.dir.attr == 0xf)
+			entry.dir.attr = '\0';
+		low_level_dir_write(&entry);
+	}
+	return 0;
+}
+
+int write_vfat(Stream_t *Dir, char *shortname, char *longname, int start,
+	       direntry_t *mainEntry)
+{
+	struct vfat_subentry *vse;
+	int vse_id, num_vses;
+	char *c;
+	direntry_t entry;
+	dirCache_t *cache;
+	char unixyName[13];
+	
+	if(longname) {
+#ifdef DEBUG
+		printf("Entering write_vfat with longname=\"%s\", start=%d.\n",
+		       longname,start);
+#endif
+		entry.Dir = Dir;
+		vse = (struct vfat_subentry *) &entry.dir;
+		/* Fill in invariant part of vse */
+		vse->attribute = 0x0f;
+		vse->hash1 = vse->sector_l = vse->sector_u = 0;
+		vse->sum = sum_shortname(shortname);
+#ifdef DEBUG
+		printf("Wrote checksum=%d for shortname %s.\n", 
+		       vse->sum,shortname);
+#endif
+		num_vses = strlen(longname)/VSE_NAMELEN + 1;
+		for (vse_id = num_vses; vse_id; --vse_id) {
+			int end = 0;
+			
+			c = longname + (vse_id - 1) * VSE_NAMELEN;
+			
+			c += unicode_write(c, vse->text1, VSE1SIZE, &end);
+			c += unicode_write(c, vse->text2, VSE2SIZE, &end);
+			c += unicode_write(c, vse->text3, VSE3SIZE, &end);
+
+			vse->id = (vse_id == num_vses) ? (vse_id | VSE_LAST) : vse_id;
+#ifdef DEBUG
+			printf("Writing longname=(%s), VSE %d (%13s) at %d, end = %d.\n",
+			       longname, vse_id, longname + (vse_id-1) * VSE_NAMELEN,
+			       start + num_vses - vse_id, start + num_vses);
+#endif
+			
+			entry.entry = start + num_vses - vse_id;
+			low_level_dir_write(&entry);
+		}
+	} else
+		num_vses = 0;
+	cache = allocDirCache(Dir, start + num_vses + 1);
+	if(!cache) {
+		fprintf(stderr, "Out of memory error\n");
+		exit(1);
+	}
+	unix_name(shortname, shortname+8, 0, unixyName);
+	addUsedEntry(cache, start, start + num_vses + 1, longname, unixyName,
+		     &mainEntry->dir);
+	low_level_dir_write(mainEntry);
+	return start + num_vses;
+}
+
+void dir_write(direntry_t *entry)
+{
+	dirCacheEntry_t *dce;
+	dirCache_t *cache;
+
+	if(entry->entry == -3) {
+		fprintf(stderr, "Attempt to write root directory pointer\n");
+		exit(1);
+	}
+
+	cache = allocDirCache(entry->Dir, entry->entry + 1);
+	if(!cache) {
+		fprintf(stderr, "Out of memory error in dir_write\n");
+		exit(1);
+	}
+	dce = cache->entries[entry->entry];
+	if(dce) {
+		if(entry->dir.name[0] == DELMARK) {
+			addFreeEntry(cache, dce->beginSlot, dce->endSlot);
+		} else {
+			dce->dir = entry->dir;
+		}
+	}
+	low_level_dir_write(entry);
+}
+
+
+/* 
+ * The following function translates a series of vfat_subentries into
+ * data suitable for a dircache entry
+ */
+static inline void parse_vses(direntry_t *entry,			      
+			      struct vfat_state *v)
+{
+	struct vfat_subentry *vse;
+	unsigned char id, last_flag;
+	char *c;
+	
+	vse = (struct vfat_subentry *) &entry->dir;
+	
+	id = vse->id & VSE_MASK;
+	last_flag = (vse->id & VSE_LAST);
+	if (id > MAX_VFAT_SUBENTRIES) {
+		fprintf(stderr, "parse_vses: invalid VSE ID %d at %d.\n",
+			id, entry->entry);
+		return;
+	}
+	
+/* 950819: This code enforced finding the VSEs in order.  Well, Win95
+ * likes to write them in *reverse* order for some bizarre reason!  So
+ * we pretty much have to tolerate them coming in any possible order.
+ * So skip this check, we'll do without it (What does this do, Alain?).
+ *
+ * 950820: Totally rearranged code to tolerate any order but to warn if
+ * they are not in reverse order like Win95 uses.
+ *
+ * 950909: Tolerate any order. We recognize new chains by mismatching
+ * checksums. In the event that the checksums match, new entries silently
+ * overwrite old entries of the same id. This should accept all valid
+ * entries, but may fail to reject invalid entries in some rare cases.
+ */
+
+	/* bad checksum, begin new chain */
+	if(v->sum != vse->sum) {
+		clear_vfat(v);
+		v->sum = vse->sum;
+	}
+	
+#ifdef DEBUG
+	if(v->status & (1 << (id-1)))
+		fprintf(stderr,
+			"parse_vses: duplicate VSE %d\n", vse->id);
+#endif
+	
+	v->status |= 1 << (id-1);
+	if(last_flag)
+		v->subentries = id;
+	
+#ifdef DEBUG
+	if (id > v->subentries)
+		/* simple test to detect entries preceding
+		 * the "last" entry (really the first) */
+		fprintf(stderr,
+			"parse_vses: new VSE %d sans LAST flag\n",
+			vse->id);
+#endif
+
+	c = &(v->name[VSE_NAMELEN * (id-1)]);
+	c += unicode_read(vse->text1, c, VSE1SIZE);
+	c += unicode_read(vse->text2, c, VSE2SIZE);
+	c += unicode_read(vse->text3, c, VSE3SIZE);
+#ifdef DEBUG
+	printf("Read VSE %d at %d, subentries=%d, = (%13s).\n",
+	       id,entry->entry,v->subentries,&(v->name[VSE_NAMELEN * (id-1)]));
+#endif		
+	if (last_flag)
+		*c = '\0';	/* Null terminate long name */
+}
+
+
+static dirCacheEntry_t *vfat_lookup_loop_common(direntry_t *direntry,
+						dirCache_t *cache,
+						int lookForFreeSpace,
+						int *io_error)
+{
+	char newfile[13];
+	int initpos = direntry->entry + 1;
+	struct vfat_state vfat;
+	char *longname;
+	int error;
+
+	/* not yet cached */
+	*io_error = 0;
+	clear_vfat(&vfat);
+	while(1) {
+		++direntry->entry;
+		if(!dir_read(direntry, &error)){
+			if(error) {
+			    *io_error = error;
+			    return NULL;
+			}
+			addFreeEntry(cache, initpos, direntry->entry);
+			return addEndEntry(cache, direntry->entry);
+		}
+		
+		if (direntry->dir.name[0] == '\0'){
+				/* the end of the directory */
+			if(lookForFreeSpace)
+				continue;
+			return addEndEntry(cache, direntry->entry);
+		}
+		if(direntry->dir.name[0] != DELMARK &&
+		   direntry->dir.attr == 0x0f)
+			parse_vses(direntry, &vfat);
+		else
+			/* the main entry */
+			break;
+	}
+	
+	/* If we get here, it's a short name FAT entry, maybe erased.
+	 * thus we should make sure that the vfat structure will be
+	 * cleared before the next loop run */
+	
+	/* deleted file */
+	if (direntry->dir.name[0] == DELMARK) {
+		return addFreeEntry(cache, initpos, 
+				    direntry->entry + 1);
+	}
+	
+	check_vfat(&vfat, &direntry->dir);
+	if(!vfat.present)
+		vfat.subentries = 0;
+	
+	/* mark space between last entry and this one as free */
+	addFreeEntry(cache, initpos, 
+		     direntry->entry - vfat.subentries);
+	
+	if (direntry->dir.attr & 0x8){
+		strncpy(newfile, direntry->dir.name,8);
+		newfile[8]='\0';
+		strncat(newfile, direntry->dir.ext,3);
+		newfile[11]='\0';
+	} else
+		unix_name(direntry->dir.name, 
+			  direntry->dir.ext, 
+			  direntry->dir.Case, 
+			  newfile);
+
+	if(vfat.present)
+		longname = vfat.name;
+	else
+		longname = 0;
+
+	return addUsedEntry(cache, direntry->entry - vfat.subentries,
+			    direntry->entry + 1, longname, 
+			    newfile, &direntry->dir);
+}
+
+static inline dirCacheEntry_t *vfat_lookup_loop_for_read(direntry_t *direntry,
+							 dirCache_t *cache,
+							 int *io_error)
+{
+	int initpos = direntry->entry + 1;
+	dirCacheEntry_t *dce;
+
+	*io_error = 0;
+	dce = cache->entries[initpos];
+	if(dce) {
+		direntry->entry = dce->endSlot - 1;
+		return dce;
+	} else {
+		return vfat_lookup_loop_common(direntry, cache, 0, io_error);
+	}
+}
+
+
+typedef enum result_t {
+	RES_NOMATCH,
+	RES_MATCH,
+	RES_END,
+	RES_ERROR
+} result_t;
+
+
+/* 
+ * 0 does not match
+ * 1 matches
+ * 2 end
+ */
+static result_t checkNameForMatch(struct direntry_t *direntry, 
+				  dirCacheEntry_t *dce,
+				  const char *filename,
+				  char *longname,
+				  char *shortname,
+				  int length,
+				  int flags)
+{
+	switch(dce->type) {
+		case DCET_FREE:
+			return RES_NOMATCH;
+		case DCET_END:
+			return RES_END;
+		case DCET_USED:
+			break;
+		default:
+			fprintf(stderr, "Unexpected entry type %d\n",
+				dce->type);
+			return RES_ERROR;
+	}
+
+	direntry->dir = dce->dir;
+
+	/* make sure the entry is of an accepted type */
+	if((direntry->dir.attr & 0x8) && !(flags & ACCEPT_LABEL))
+		return RES_NOMATCH;
+
+
+	/*---------- multiple files ----------*/
+	if(!((flags & MATCH_ANY) ||
+	     (dce->longName && 
+	      match(dce->longName, filename, direntry->name, 0, length)) ||
+	     match(dce->shortName, filename, direntry->name, 1, length))) {
+
+		return RES_NOMATCH;
+	}
+
+	/* entry of non-requested type, has to come after name
+	 * checking because of clash handling */
+	if(IS_DIR(direntry) && !(flags & ACCEPT_DIR)) {
+		if(!(flags & (ACCEPT_LABEL|MATCH_ANY|NO_MSG)))
+			fprintf(stderr,
+				"Skipping \"%s\", is a directory\n",
+				dce->shortName);
+		return RES_NOMATCH;
+	}
+
+	if(!(direntry->dir.attr & (ATTR_LABEL | ATTR_DIR)) && 
+	   !(flags & ACCEPT_PLAIN)) {
+		if(!(flags & (ACCEPT_LABEL|MATCH_ANY|NO_MSG)))
+			fprintf(stderr,
+				"Skipping \"%s\", is not a directory\n",
+				dce->shortName);
+		return RES_NOMATCH;
+	}
+
+	return RES_MATCH;
+}
+
+
+/*
+ * vfat_lookup looks for filenames in directory dir.
+ * if a name if found, it is returned in outname
+ * if applicable, the file is opened and its stream is returned in File
+ */
+
+int vfat_lookup(direntry_t *direntry, const char *filename, int length,
+		int flags, char *shortname, char *longname)
+{
+	dirCacheEntry_t *dce;
+	result_t result;
+	dirCache_t *cache;
+	int io_error;
+
+	if(length == -1 && filename)
+		length = strlen(filename);
+
+	if (direntry->entry == -2)
+		return -1;
+
+	cache = allocDirCache(direntry->Dir, direntry->entry+1);
+	if(!cache) {
+		fprintf(stderr, "Out of memory error in vfat_lookup [0]\n");
+		exit(1);
+	}
+
+	do {
+		dce = vfat_lookup_loop_for_read(direntry, cache, &io_error);
+		if(!dce) {
+			if (io_error)
+				return -2;
+			fprintf(stderr, "Out of memory error in vfat_lookup\n");
+			exit(1);
+		}
+		result = checkNameForMatch(direntry, dce,
+					   filename, 
+					   longname, shortname,
+					   length, flags);
+	} while(result == RES_NOMATCH);
+
+	if(result == RES_MATCH){
+		if(longname){
+			if(dce->longName)
+				strcpy(longname, dce->longName);
+			else
+				*longname ='\0';
+		}
+		if(shortname)
+			strcpy(shortname, dce->shortName);
+		direntry->beginSlot = dce->beginSlot;
+		direntry->endSlot = dce->endSlot-1;
+		return 0; /* file found */
+	} else {
+		direntry->entry = -2;
+		return -1; /* no file found */
+	}
+}
+
+static inline dirCacheEntry_t *vfat_lookup_loop_for_insert(direntry_t *direntry,
+							   int initpos,
+							   dirCache_t *cache)
+{
+	dirCacheEntry_t *dce;
+	int io_error;
+
+	dce = cache->entries[initpos];
+	if(dce && dce->type != DCET_END) {
+		return dce;
+	} else {
+		direntry->entry = initpos - 1;
+		dce = vfat_lookup_loop_common(direntry, cache, 1, &io_error);
+		if(!dce) {
+			if (io_error) {
+				return NULL;
+			}
+			fprintf(stderr, 
+				"Out of memory error in vfat_lookup_loop\n");
+			exit(1);
+		}
+		return cache->entries[initpos];
+	}
+}
+
+static void accountFreeSlots(struct scan_state *ssp, dirCacheEntry_t *dce)
+{
+	if(ssp->got_slots)
+		return;
+
+	if(ssp->free_end != dce->beginSlot) {
+		ssp->free_start = dce->beginSlot;
+	}
+	ssp->free_end = dce->endSlot;
+
+	if(ssp->free_end - ssp->free_start >= ssp->size_needed) {
+		ssp->got_slots = 1;
+		ssp->slot = ssp->free_start + ssp->size_needed - 1;
+	}
+}
+
+/* lookup_for_insert replaces the old scandir function.  It directly
+ * calls into vfat_lookup_loop, thus eliminating the overhead of the
+ * normal vfat_lookup
+ */
+int lookupForInsert(Stream_t *Dir,
+					char *dosname,
+					char *longname,
+					struct scan_state *ssp, 
+					int ignore_entry,
+					int source_entry,
+					int pessimisticShortRename)
+{
+	direntry_t entry;
+	int ignore_match;
+	dirCacheEntry_t *dce;
+	dirCache_t *cache;
+	int pos; /* position _before_ the next answered entry */
+	char shortName[13];
+
+	ignore_match = (ignore_entry == -2 );
+
+	initializeDirentry(&entry, Dir);
+	ssp->match_free = 0;
+
+	/* hash bitmap of already encountered names.  Speeds up batch appends
+	 * to huge directories, because in the best case, we only need to scan
+	 * the new entries rather than the whole directory */
+	cache = allocDirCache(Dir, 1);
+	if(!cache) {
+		fprintf(stderr, "Out of memory error in lookupForInsert\n");
+		exit(1);
+	}
+
+	if(!ignore_match)
+		unix_name(dosname, dosname + 8, 0, shortName);
+
+	pos = cache->nrHashed;
+	if(source_entry >= 0 ||
+	   (pos && isHashed(cache, longname))) {
+		pos = 0;
+	} else if(pos && !ignore_match && isHashed(cache, shortName)) {
+		if(pessimisticShortRename) {
+			ssp->shortmatch = -2;
+			return 1;
+		}
+		pos = 0;
+	} else if(growDirCache(cache, pos) < 0) {
+		fprintf(stderr, "Out of memory error in vfat_looup [0]\n");
+		exit(1);
+	}
+	do {
+		dce = vfat_lookup_loop_for_insert(&entry, pos, cache);
+		switch(dce->type) {
+			case DCET_FREE:
+				accountFreeSlots(ssp, dce);
+				break;
+			case DCET_USED:
+				if(!(dce->dir.attr & 0x8) &&
+				   dce->endSlot - 1 == source_entry)
+				   accountFreeSlots(ssp, dce);
+
+				/* labels never match, neither does the 
+				 * ignored entry */
+				if( (dce->dir.attr & 0x8) ||
+				    (dce->endSlot - 1 == ignore_entry) )
+					break;
+
+				/* check long name */
+				if((dce->longName && 
+				    !strcasecmp(dce->longName, longname)) ||
+				   (dce->shortName &&
+				    !strcasecmp(dce->shortName, longname))) {
+					ssp->longmatch = dce->endSlot - 1;
+					/* long match is a reason for
+					 * immediate stop */
+					return 1;
+				}
+
+				/* Long name or not, always check for 
+				 * short name match */
+				if (!ignore_match &&
+				    !strcasecmp(shortName, dce->shortName))
+					ssp->shortmatch = dce->endSlot - 1;
+				break;
+			case DCET_END:
+				break;
+		}
+		pos = dce->endSlot;
+	} while(dce->type != DCET_END);
+	if (ssp->shortmatch > -1)
+		return 1;
+	ssp->max_entry = dce->beginSlot;
+	if (ssp->got_slots)
+		return 6;	/* Success */
+
+	/* Need more room.  Can we grow the directory? */
+	if(!isRootDir(Dir))		
+		return 5;	/* OK, try to grow the directory */
+
+	fprintf(stderr, "No directory slots\n");
+	return -1;
+}
+
+
+
+/* End vfat.c */
Index: /trunk/minix/commands/i386/mtools-3.9.7/vfat.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/vfat.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/vfat.h	(revision 9)
@@ -0,0 +1,100 @@
+#ifndef MTOOLS_VFAT_H
+#define MTOOLS_VFAT_H
+
+#include "msdos.h"
+
+/*
+ * VFAT-related common header file
+ */
+#define VFAT_SUPPORT
+
+struct unicode_char {
+	char lchar;
+	char uchar;
+};
+
+
+/* #define MAX_VFAT_SUBENTRIES 32 */ /* Theoretical max # of VSEs */
+#define MAX_VFAT_SUBENTRIES 20		/* Max useful # of VSEs */
+#define VSE_NAMELEN 13
+
+#define VSE1SIZE 5
+#define VSE2SIZE 6
+#define VSE3SIZE 2
+
+#include "stream.h"
+
+struct vfat_subentry {
+	unsigned char id;		/* 0x40 = last; & 0x1f = VSE ID */
+	struct unicode_char text1[VSE1SIZE] PACKED;
+	unsigned char attribute;	/* 0x0f for VFAT */
+	unsigned char hash1;		/* Always 0? */
+	unsigned char sum;		/* Checksum of short name */
+	struct unicode_char text2[VSE2SIZE] PACKED;
+	unsigned char sector_l;		/* 0 for VFAT */
+	unsigned char sector_u;		/* 0 for VFAT */
+	struct unicode_char text3[VSE3SIZE] PACKED;
+};
+
+/* Enough size for a worst case number of full VSEs plus a null */
+#define VBUFSIZE ((MAX_VFAT_SUBENTRIES*VSE_NAMELEN) + 1)
+
+/* Max legal length of a VFAT long name */
+#define MAX_VNAMELEN (255)
+
+#define VSE_PRESENT 0x01
+#define VSE_LAST 0x40
+#define VSE_MASK 0x1f
+
+struct vfat_state {
+	char name[VBUFSIZE];
+	int status; /* is now a bit map of 32 bits */
+	int subentries;
+	unsigned char sum; /* no need to remember the sum for each entry,
+			    * it is the same anyways */
+	int present;
+};
+
+
+struct scan_state {
+	int match_free;
+	int shortmatch;
+	int longmatch;
+	int free_start;
+	int free_end;
+	int slot;
+	int got_slots;
+	int size_needed;
+	int max_entry;
+};
+
+#include "mtoolsDirent.h"
+
+void clear_vfat(struct vfat_state  *);
+int unicode_write(char *, struct unicode_char *, int num, int *end);
+
+int clear_vses(Stream_t *, int, size_t);
+void autorename_short(char *, int);
+void autorename_long(char *, int);
+
+int lookupForInsert(Stream_t *Dir,
+					char *dosname,
+					char *longname,
+					struct scan_state *ssp, 
+					int ignore_entry,
+					int source_entry,
+					int pessimisticShortRename);
+
+#define DO_OPEN 1 /* open all files that are found */
+#define ACCEPT_LABEL 0x08
+#define ACCEPT_DIR 0x10
+#define ACCEPT_PLAIN 0x20
+#define MATCH_ANY 0x40
+#define NO_MSG 0x80
+#define NO_DOTS 0x100 /* accept no dots if matched by wildcard */
+#define DO_OPEN_DIRS 0x400 /* open all directories that are found */
+#define OPEN_PARENT 0x1000  /* in target lookup, open parent
+			     * instead of file itself */
+#define NO_UNIX 0x2000 /* in target lookup, consider all files to reside on
+			* the DOS fs */
+#endif
Index: /trunk/minix/commands/i386/mtools-3.9.7/xdf_io.c
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/xdf_io.c	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/xdf_io.c	(revision 9)
@@ -0,0 +1,696 @@
+/*
+ * Io to an xdf disk
+ *
+ * written by:
+ *
+ * Alain L. Knaff
+ * alain@linux.lu
+ *
+ */
+
+
+#include "sysincludes.h"
+#ifdef OS_linux
+#include "msdos.h"
+#include "mtools.h"
+#include "devices.h"
+#include "xdf_io.h"
+
+extern int errno;
+
+/* Algorithms can't be patented */
+
+typedef struct sector_map {
+	unsigned int head:1;
+	unsigned int size:7;
+} sector_map_t;
+
+
+struct {
+  unsigned char track_size;
+  unsigned int track0_size:7;
+  unsigned int rootskip:1;
+  unsigned char rate;
+  sector_map_t map[9];
+} xdf_table[]= {
+  {
+    19, 16, 0, 0,
+    {	{0,3},	{0,6},	{1,2},	{0,2},	{1,6},	{1,3},	{0,0} }
+  },
+  {
+    23, 19, 0, 0,
+    {	{0,3},	{0,4},	{1,6},	{0,2},	{1,2},	{0,6},	{1,4},	{1,3},	{0,0} }
+  },
+  {
+    46, 37, 0x43, 1,
+    {	{0,3},	{0,4},	{0,5},	{0,7},	{1,3},	{1,4},	{1,5},	{1,7},	{0,0} }
+  },
+  {
+    24, 20, 0, 1,
+    {	{0,5},	{1,6},	{0,6},	{1, 5} }
+  },
+  {
+    48, 41, 0, 1,
+    {	{0,6},	{1,7},	{0,7},	{1, 6} }
+  }
+};
+
+#define NUMBER(x) (sizeof(x)/sizeof(x[0]))
+
+typedef struct {
+	unsigned char begin; /* where it begins */
+	unsigned char end;       
+	unsigned char sector;
+	unsigned char sizecode;
+
+	unsigned int dirty:1;
+	unsigned int phantom:2;
+	unsigned int valid:1;
+	unsigned int head:1;
+} TrackMap_t;
+
+
+
+typedef struct Xdf_t {
+	Class_t *Class;
+	int refs;
+	Stream_t *Next;
+	Stream_t *Buffer;
+
+	int fd;
+	char *buffer;
+	
+	int current_track;
+	
+	sector_map_t *map;
+
+	int track_size;
+	int track0_size;
+	int sector_size;
+	int FatSize;
+	int RootDirSize;
+	TrackMap_t *track_map;
+
+	unsigned char last_sector;
+	unsigned char rate;
+
+	unsigned int stretch:1;
+	unsigned int rootskip:1;
+	signed  int drive:4;
+} Xdf_t;
+
+typedef struct {
+	unsigned char head;
+	unsigned char sector;
+	unsigned char ptr;
+} Compactify_t;
+
+
+static int analyze_reply(RawRequest_t *raw_cmd, int do_print)
+{
+	int ret, bytes, newbytes;
+
+	bytes = 0;
+	while(1) {
+		ret = analyze_one_reply(raw_cmd, &newbytes, do_print);
+		bytes += newbytes;
+		switch(ret) {
+			case 0:
+				return bytes;
+			case 1:
+				raw_cmd++;
+				break;
+			case -1:
+				if(bytes)
+					return bytes;
+				else
+					return 0;
+		}
+	}
+}
+				
+
+
+static int send_cmd(int fd, RawRequest_t *raw_cmd, int nr,
+		    const char *message, int retries)
+{
+	int j;
+	int ret=-1;
+	
+	if(!nr)
+		return 0;
+	for (j=0; j< retries; j++){
+		switch(send_one_cmd(fd, raw_cmd, message)) {
+			case -1:
+				return -1;
+			case 1:
+				j++;
+				continue;
+			case 0:
+				break;
+		}
+		if((ret=analyze_reply(raw_cmd, j)) > 0)
+			return ret; /* ok */
+	}
+	if(j > 1 && j == retries) {
+		fprintf(stderr,"Too many errors, giving up\n");
+		return 0;
+	}
+	return -1;
+}
+
+
+
+#define REC (This->track_map[ptr])
+#define END(x) (This->track_map[(x)].end)
+#define BEGIN(x) (This->track_map[(x)].begin)
+
+static int add_to_request(Xdf_t *This, int ptr,
+			  RawRequest_t *request, int *nr,
+			  int direction, Compactify_t *compactify)
+{
+#if 0
+	if(direction == MT_WRITE) {
+		printf("writing %d: %d %d %d %d [%02x]\n", 
+		       ptr, This->current_track,
+		       REC.head, REC.sector, REC.sizecode,
+		       *(This->buffer + ptr * This->sector_size));
+	} else
+			printf(" load %d.%d\n", This->current_track, ptr);
+#endif
+	if(REC.phantom) {
+		if(direction== MT_READ)			
+			memset(This->buffer + ptr * This->sector_size, 0,
+			       128 << REC.sizecode);
+		return 0;
+	}
+	
+	if(*nr &&
+	   RR_SIZECODE(request+(*nr)-1) == REC.sizecode &&	   
+	   compactify->head == REC.head &&
+	   compactify->ptr + 1 == ptr &&
+	   compactify->sector +1 == REC.sector) {
+		RR_SETSIZECODE(request+(*nr)-1, REC.sizecode);
+	} else {
+		if(*nr)
+			RR_SETCONT(request+(*nr)-1);
+		RR_INIT(request+(*nr));
+		RR_SETDRIVE(request+(*nr), This->drive);
+		RR_SETRATE(request+(*nr), This->rate);
+		RR_SETTRACK(request+(*nr), This->current_track);
+		RR_SETPTRACK(request+(*nr), 
+			     This->current_track << This->stretch);
+		RR_SETHEAD(request+(*nr), REC.head);
+		RR_SETSECTOR(request+(*nr), REC.sector);
+		RR_SETSIZECODE(request+(*nr), REC.sizecode);
+		RR_SETDIRECTION(request+(*nr), direction);
+		RR_SETDATA(request+(*nr),
+			   (caddr_t) This->buffer + ptr * This->sector_size);
+		(*nr)++;
+	}
+	compactify->ptr = ptr;
+	compactify->head = REC.head;
+	compactify->sector = REC.sector;
+	return 0;
+}
+
+
+static void add_to_request_if_invalid(Xdf_t *This, int ptr,
+				     RawRequest_t *request, int *nr,
+				     Compactify_t *compactify)
+{
+	if(!REC.valid)
+		add_to_request(This, ptr, request, nr, MT_READ, compactify);
+
+}
+
+
+static void adjust_bounds(Xdf_t *This, off_t *begin, off_t *end)
+{
+	/* translates begin and end from byte to sectors */
+	*begin = *begin / This->sector_size;
+	*end = (*end + This->sector_size - 1) / This->sector_size;
+}
+
+
+static inline int try_flush_dirty(Xdf_t *This)
+{
+	int ptr, nr, bytes;
+	RawRequest_t requests[100];
+	Compactify_t compactify;
+
+	if(This->current_track < 0)
+		return 0;
+	
+	nr = 0;
+	for(ptr=0; ptr < This->last_sector; ptr=REC.end)
+		if(REC.dirty)
+			add_to_request(This, ptr,
+				       requests, &nr,
+				       MT_WRITE, &compactify);
+#if 1
+	bytes = send_cmd(This->fd,requests, nr, "writing", 4);
+	if(bytes < 0)
+		return bytes;
+#else
+	bytes = 0xffffff;
+#endif
+	for(ptr=0; ptr < This->last_sector; ptr=REC.end)
+		if(REC.dirty) {
+			if(bytes >= REC.end - REC.begin) {
+				bytes -= REC.end - REC.begin;
+				REC.dirty = 0;
+			} else
+				return 1;
+		}
+	return 0;
+}
+
+
+
+static int flush_dirty(Xdf_t *This)
+{	
+	int ret;
+
+	while((ret = try_flush_dirty(This))) {
+		if(ret < 0)		       
+			return ret;
+	}
+	return 0;
+}
+
+
+static int load_data(Xdf_t *This, off_t begin, off_t end, int retries)
+{
+	int ptr, nr, bytes;
+	RawRequest_t requests[100];
+	Compactify_t compactify;
+
+	adjust_bounds(This, &begin, &end);
+	
+	ptr = begin;
+	nr = 0;
+	for(ptr=REC.begin; ptr < end ; ptr = REC.end)
+		add_to_request_if_invalid(This, ptr, requests, &nr,
+					  &compactify);
+	bytes = send_cmd(This->fd,requests, nr, "reading", retries);
+	if(bytes < 0)
+		return bytes;
+	ptr = begin;
+	for(ptr=REC.begin; ptr < end ; ptr = REC.end) {
+		if(!REC.valid) {
+			if(bytes >= REC.end - REC.begin) {
+				bytes -= REC.end - REC.begin;
+				REC.valid = 1;
+			} else if(ptr > begin)
+				return ptr * This->sector_size;
+			else
+				return -1;
+		}
+	}
+	return end * This->sector_size;
+}
+
+static void mark_dirty(Xdf_t *This, off_t begin, off_t end)
+{
+	int ptr;
+
+	adjust_bounds(This, &begin, &end);
+	
+	ptr = begin;
+	for(ptr=REC.begin; ptr < end ; ptr = REC.end) {
+		REC.valid = 1;
+		if(!REC.phantom)
+			REC.dirty = 1;
+	}
+}
+
+
+static int load_bounds(Xdf_t *This, off_t begin, off_t end)
+{
+	off_t lbegin, lend;
+	int endp1, endp2;
+
+	lbegin = begin;
+	lend = end;
+
+	adjust_bounds(This, &lbegin, &lend);	
+
+	if(begin != BEGIN(lbegin) * This->sector_size &&
+	   end != BEGIN(lend) * This->sector_size &&
+	   lend < END(END(lbegin)))
+		/* contiguous end & begin, load them in one go */
+		return load_data(This, begin, end, 4);
+
+	if(begin != BEGIN(lbegin) * This->sector_size) {
+		endp1 = load_data(This, begin, begin, 4);
+		if(endp1 < 0)
+			return endp1;
+	}
+
+	if(end != BEGIN(lend) * This->sector_size) {
+		endp2 = load_data(This, end, end, 4);
+		if(endp2 < 0)
+			return BEGIN(lend) * This->sector_size;
+	}
+	return lend * This->sector_size;
+}
+
+
+static int fill_t0(Xdf_t *This, int ptr, int size, int *sector, int *head)
+{
+	int n;
+
+	for(n = 0; n < size; ptr++,n++) {
+		REC.head = *head;
+		REC.sector = *sector + 129;
+		REC.phantom = 0;
+		(*sector)++;
+		if(!*head && *sector >= This->track0_size - 8) {
+			*sector = 0;
+			*head = 1;
+		}
+	}
+	return ptr;
+}
+
+
+static int fill_phantoms(Xdf_t *This, int ptr, int size)
+{
+	int n;
+
+	for(n = 0; n < size; ptr++,n++)
+		REC.phantom = 1;
+	return ptr;
+}
+
+static void decompose(Xdf_t *This, int where, int len, off_t *begin, 
+					  off_t *end, int boot)
+{
+	int ptr, track;
+	sector_map_t *map;
+	int lbegin, lend;
+	
+	track = where / This->track_size / 1024;
+	
+	*begin = where - track * This->track_size * 1024;
+	*end = where + len - track * This->track_size * 1024;
+	maximize(*end, This->track_size * 1024);
+
+	if(This->current_track == track && !boot)
+		/* already OK, return immediately */
+		return;
+	if(!boot)
+		flush_dirty(This);
+	This->current_track = track;
+
+	if(track) {
+		for(ptr=0, map=This->map; map->size; map++) {
+			/* iterate through all sectors */
+			lbegin = ptr;
+			lend = ptr + (128 << map->size) / This->sector_size;
+			for( ; ptr < lend ; ptr++) {
+				REC.begin = lbegin;
+				REC.end = lend;
+				
+				REC.head = map->head;
+				REC.sector = map->size + 128;
+				REC.sizecode = map->size;
+				
+				REC.valid = 0;
+				REC.dirty = 0;
+				REC.phantom = 0;
+			}
+		}
+		REC.begin = REC.end = ptr;
+	} else {
+		int sector, head;
+
+		head = 0;
+		sector = 0;
+
+		for(ptr=boot; ptr < 2 * This->track_size; ptr++) {
+			REC.begin = ptr;
+			REC.end = ptr+1;
+			
+			REC.sizecode = 2;
+			
+			REC.valid = 0;
+			REC.dirty = 0;
+		}
+
+		/* boot & 1st fat */
+		ptr=fill_t0(This, 0, 1 + This->FatSize, &sector, &head);
+
+		/* second fat */
+		ptr=fill_phantoms(This, ptr, This->FatSize);
+
+		/* root dir */
+		ptr=fill_t0(This, ptr, This->RootDirSize, &sector, &head);
+		
+		/* "bad sectors" at the beginning of the fs */
+		ptr=fill_phantoms(This, ptr, 5);
+
+		if(This->rootskip)
+			sector++;
+
+		/* beginning of the file system */
+		ptr = fill_t0(This, ptr,
+			      (This->track_size - This->FatSize) * 2 -
+			      This->RootDirSize - 6,
+			      &sector, &head);
+	}
+	This->last_sector = ptr;
+}
+
+
+static int xdf_read(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
+{	
+	off_t begin, end;
+	size_t len2;
+	DeclareThis(Xdf_t);
+
+	decompose(This, truncBytes32(where), len, &begin, &end, 0);
+	len2 = load_data(This, begin, end, 4);
+	if(len2 < 0)
+		return len2;
+	len2 -= begin;
+	maximize(len, len2);
+	memcpy(buf, This->buffer + begin, len);
+	return end - begin;
+}
+
+static int xdf_write(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
+{	
+	off_t begin, end;
+	size_t len2;
+	DeclareThis(Xdf_t);
+
+	decompose(This, truncBytes32(where), len, &begin, &end, 0);
+	len2 = load_bounds(This, begin, end);
+	if(len2 < 0)
+		return len2;
+	maximize(end, len2);
+	len2 -= begin;
+	maximize(len, len2);
+	memcpy(This->buffer + begin, buf, len);
+	mark_dirty(This, begin, end);
+	return end - begin;
+}
+
+static int xdf_flush(Stream_t *Stream)
+{
+	DeclareThis(Xdf_t);
+
+	return flush_dirty(This);       
+}
+
+static int xdf_free(Stream_t *Stream)
+{
+	DeclareThis(Xdf_t);
+	Free(This->track_map);
+	Free(This->buffer);
+	return close(This->fd);
+}
+
+
+static int check_geom(struct device *dev, int media, struct bootsector *boot)
+{
+	int sect;
+
+	if(media >= 0xfc && media <= 0xff)
+		return 1; /* old DOS */
+
+	if (!IS_MFORMAT_ONLY(dev)) {
+	    if(compare(dev->sectors, 19) &&
+	       compare(dev->sectors, 23) &&
+	       compare(dev->sectors, 24) &&
+	       compare(dev->sectors, 46) &&
+	       compare(dev->sectors, 48))
+		return 1;
+	    
+	    /* check against contradictory info from configuration file */
+	    if(compare(dev->heads, 2))
+		return 1;
+	}
+
+	/* check against info from boot */
+	if(boot) {
+		sect = WORD(nsect);
+		if((sect != 19 && sect != 23 && sect != 24 &&
+		    sect != 46 && sect != 48) ||
+		   (!IS_MFORMAT_ONLY(dev) && compare(dev->sectors, sect)) || 
+		   WORD(nheads) !=2)
+		    return 1;
+	}
+	return 0;
+}
+
+static void set_geom(struct bootsector *boot, struct device *dev)
+{
+	/* fill in config info to be returned to user */
+	dev->heads = 2;
+	dev->use_2m = 0xff;
+	if(boot) {
+		dev->sectors = WORD(nsect);
+		if(WORD(psect))
+			dev->tracks = WORD(psect) / dev->sectors / 2;
+	}
+}
+
+static int config_geom(Stream_t *Stream, struct device *dev, 
+		       struct device *orig_dev, int media,
+		       struct bootsector *boot)
+{
+	if(check_geom(dev, media, boot))
+		return 1;
+	set_geom(boot,dev);
+	return 0;
+}
+
+static Class_t XdfClass = {
+	xdf_read, 
+	xdf_write, 
+	xdf_flush, 
+	xdf_free, 
+	config_geom, 
+	0, /* get_data */
+	0 /* pre-allocate */
+};
+
+Stream_t *XdfOpen(struct device *dev, char *name,
+		  int mode, char *errmsg, struct xdf_info *info)
+{
+	Xdf_t *This;
+	off_t begin, end;
+	struct bootsector *boot;
+	int type;
+
+	if(dev && (!SHOULD_USE_XDF(dev) || check_geom(dev, 0, 0)))
+		return NULL;
+
+	This = New(Xdf_t);
+	if (!This)
+		return NULL;
+
+	This->Class = &XdfClass;
+	This->sector_size = 512;
+	This->stretch = 0;
+
+	precmd(dev);
+	This->fd = open(name, mode | dev->mode | O_EXCL | O_NDELAY);
+	if(This->fd < 0) {
+#ifdef HAVE_SNPRINTF
+		snprintf(errmsg,199,"xdf floppy: open: \"%s\"", strerror(errno));
+#else
+		sprintf(errmsg,"xdf floppy: open: \"%s\"", strerror(errno));
+#endif
+		goto exit_0;
+	}
+	closeExec(This->fd);
+
+	This->drive = GET_DRIVE(This->fd);
+	if(This->drive < 0)
+		goto exit_1;
+
+	/* allocate buffer */
+	This->buffer = (char *) malloc(96 * 512);
+	if (!This->buffer)
+		goto exit_1;
+
+	This->current_track = -1;
+	This->track_map = (TrackMap_t *)
+		calloc(96, sizeof(TrackMap_t));
+	if(!This->track_map)
+		goto exit_2;
+
+	/* lock the device on writes */
+	if (lock_dev(This->fd, mode == O_RDWR, dev)) {
+#ifdef HAVE_SNPRINTF
+		snprintf(errmsg,199,"xdf floppy: device \"%s\" busy:", 
+			dev->name);
+#else
+		sprintf(errmsg,"xdf floppy: device \"%s\" busy:", 
+			dev->name);
+#endif
+		goto exit_3;
+	}
+
+	/* Before reading the boot sector, assume dummy values suitable
+	 * for reading at least the boot sector */
+	This->track_size = 11;
+	This->track0_size = 6;
+	This->rate = 0;
+	This->FatSize = 9;
+	This->RootDirSize = 1;
+	decompose(This, 0, 512, &begin, &end, 0);
+	if (load_data(This, 0, 1, 1) < 0 ) {
+		This->rate = 0x43;
+		if(load_data(This, 0, 1, 1) < 0)
+			goto exit_3;
+	}
+
+	boot = (struct bootsector *) This->buffer;
+	This->FatSize = WORD(fatlen);
+	This->RootDirSize = WORD(dirents)/16;
+	This->track_size = WORD(nsect);
+	for(type=0; type < NUMBER(xdf_table); type++) {
+		if(xdf_table[type].track_size == This->track_size) {
+			This->map = xdf_table[type].map;
+			This->track0_size = xdf_table[type].track0_size;
+			This->rootskip = xdf_table[type].rootskip;
+			break;
+		}
+	}
+	if(type == NUMBER(xdf_table))
+		goto exit_3;
+
+	if(info) {
+		info->RootDirSize = This->RootDirSize;
+		info->FatSize = This->FatSize;
+		info->BadSectors = 5;
+	}
+	decompose(This, 0, 512, &begin, &end, 1);
+
+	This->refs = 1;
+	This->Next = 0;
+	This->Buffer = 0;
+	if(dev)
+		set_geom(boot, dev);
+	return (Stream_t *) This;
+
+exit_3:
+	Free(This->track_map);
+exit_2:
+	Free(This->buffer);
+exit_1:
+	close(This->fd);
+exit_0:
+	Free(This);
+	return NULL;
+}
+
+#endif
+
+/* Algorithms can't be patented */
+
Index: /trunk/minix/commands/i386/mtools-3.9.7/xdf_io.h
===================================================================
--- /trunk/minix/commands/i386/mtools-3.9.7/xdf_io.h	(revision 9)
+++ /trunk/minix/commands/i386/mtools-3.9.7/xdf_io.h	(revision 9)
@@ -0,0 +1,16 @@
+#ifndef MTOOLS_XDFIO_H
+#define MTOOLS_XDFIO_H
+
+#include "msdos.h"
+#include "stream.h"
+
+struct xdf_info {
+  int FatSize;
+  int RootDirSize;
+  int BadSectors;
+};
+
+Stream_t *XdfOpen(struct device *dev, char *name,
+		  int mode, char *errmsg, struct xdf_info *info);
+
+#endif
Index: /trunk/minix/commands/i86/Makefile
===================================================================
--- /trunk/minix/commands/i86/Makefile	(revision 9)
+++ /trunk/minix/commands/i86/Makefile	(revision 9)
@@ -0,0 +1,23 @@
+# Makefile for commands/i86.
+
+CFLAGS	= -D_MINIX -D_POSIX_SOURCE
+CCLD	= $(CC) -i $(CFLAGS)
+MAKE	= exec make -$(MAKEFLAGS)
+CC = exec cc
+
+all:	cc
+
+cc:	cc.c
+	$(CCLD) -o $@ $?
+	install -S 6kb $@
+
+install:	/usr/bin/cc /usr/bin/m2 /usr/bin/pc
+
+/usr/bin/cc:	cc
+	install -cs -o bin $? $@
+
+/usr/bin/m2 /usr/bin/pc:	/usr/bin/cc
+	install -l $? $@
+
+clean:
+	rm -rf a.out core cc
Index: /trunk/minix/commands/i86/cc.c
===================================================================
--- /trunk/minix/commands/i86/cc.c	(revision 9)
+++ /trunk/minix/commands/i86/cc.c	(revision 9)
@@ -0,0 +1,1059 @@
+/*	Driver for Minix compilers.
+	Written june 1987 by Ceriel J.H. Jacobs, partly derived from old
+	cc-driver, written by Erik Baalbergen.
+	This driver is mostly table-driven, the table being in the form of
+	some global initialized structures.
+*/
+/* $Header: /cvsup/minix/src/commands/i86/cc.c,v 1.1.1.1 2005/04/21 14:54:55 beng Exp $ */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+/* Paths.  (Executables in /usr are first tried with /usr stripped off.) */
+#define SHELL		"/bin/sh"
+#define PP		"/usr/lib/ncpp"
+#define IRREL		"/usr/lib/irrel"
+#define CEM		"/usr/lib/ncem"
+#define M2EM		"/usr/lib/nm2em"
+#define ENCODE		"/usr/lib/em_encode"
+#define OPT		"/usr/lib/nopt"
+#define CG		"/usr/lib/ncg"
+#define AS		"/usr/lib/as"
+#define LD		"/usr/lib/ld"
+#define CV		"/usr/lib/cv"
+#define LIBDIR		"/usr/lib"
+#define CRT		"/usr/lib/ncrtso.o"
+#define PEM		"/usr/lib/npem"
+#define PRT		"/usr/lib/nprtso.o"
+#define M2RT		"/usr/lib/nm2rtso.o"
+#define LIBC            "/usr/lib/libd.a", "/usr/lib/libc.a"
+#define LIBP		"/usr/lib/libp.a", "/usr/lib/libc.a"
+#define LIBM2		"/usr/lib/libm2.a", "/usr/lib/libc.a"
+#define END             "/usr/lib/libe.a", "/usr/lib/end.a"
+#define M2DEF		"-I/usr/lib/m2"
+
+
+/*	every pass that this program knows about has associated with it
+	a structure, containing such information as its name, where it
+	resides, the flags it accepts, and the like.
+*/
+struct passinfo {
+	char *p_name;		/* name of this pass */
+	char *p_path;		/* where is it */
+	char *p_from;		/* suffix of source (comma-separated list) */
+	char *p_to;		/* suffix of destination */
+	char *p_acceptflags;	/* comma separated list; format:
+			   		flag
+			   		flag*
+			   		flag=xxx
+					flag*=xxx[*]
+				   where a star matches a, possibly empty, 
+				   string
+				*/
+	int  p_flags;
+#define INPUT	01		/* needs input file as argument */
+#define OUTPUT	02		/* needs output file as argument */
+#define LOADER	04		/* this pass is the loader */
+#define STDIN	010		/* reads from standard input */
+#define STDOUT	020		/* writes on standard output */
+#define NOCLEAN	040		/* do not remove target if this pass fails */
+#define O_OUTPUT 0100		/* -o outputfile, hack for as */
+#define PREPALWAYS	0200	/* always to be preprocessed */
+#define PREPCOND	0400	/* preprocessed when starting with '#' */
+#define PREPNOLN	01000	/* suppress line number info (cpp -P) */
+};
+
+#define MAXHEAD	10
+#define MAXTAIL	5
+#define MAXPASS	7
+
+/*	Every language handled by this program has a "compile" structure
+	associated with it, describing the start-suffix, how the driver for
+	this language is called, which passes must be called, which flags
+	and arguments must be passed to these passes, etc.
+	The language is determined by the suffix of the argument program.
+	However, if this suffix does not determine a language (DEFLANG),
+	the callname is used.
+	Notice that the 's' suffix does not determine a language, because
+	the input file could have been derived from f.i. a C-program.
+	So, if you use "cc x.s", the C-runtime system will be used, but if
+	you use "as x.s", it will not.
+*/
+struct compile {
+	char *c_suffix;		/* starting suffix of this list of passes */
+	char *c_callname;	/* affects runtime system loaded with program */
+	struct pass {
+		char *pp_name;		/* name of the pass */
+		char *pp_head[MAXHEAD];	/* args in front of filename */
+		char *pp_tail[MAXTAIL];	/* args after filename */
+	} c_passes[MAXPASS];
+	int  c_flags;
+#define DEFLANG		010	/* this suffix determines a language */
+};
+
+struct passinfo passinfo[] = {
+	{ "cpp", PP, "CPP", "i", "wo=o,I*,D*,U*,P", INPUT|STDOUT },
+	{ "irrel", IRREL, "i", "i", "m", INPUT},
+	{ "cem", CEM, "i,c", "k", "m=o,p,wa=a,wo=o,ws=s,w,T*", INPUT|OUTPUT|PREPALWAYS },
+	{ "pc", PEM, "i,p", "k", "n=L,w,a,A,R", INPUT|OUTPUT|PREPCOND },
+	{ "m2", M2EM, "i,mod", "k", "n=L,w*,A,R,W*,3,I*", INPUT|OUTPUT|PREPCOND },
+	{ "encode", ENCODE, "i,e", "k", "", INPUT|STDOUT|PREPCOND|PREPNOLN },
+	{ "opt", OPT, "k", "m", "", STDIN|STDOUT },
+	{ "cg", CG, "m", "s", "O=p4", INPUT|OUTPUT },
+	{ "as", AS, "i,s", "o", "T*", INPUT|O_OUTPUT|PREPCOND },
+	{ "ld", LD, "o", "out", "i,s", INPUT|LOADER },	/* changed */
+	{ "cv", CV, "out", 0, "", INPUT|OUTPUT|NOCLEAN },	/* must come after loader */
+	{ 0}
+};
+
+#define	PREP_FLAGS	"-D_EM_WSIZE=2", "-D_EM_PSIZE=2", "-D_EM_SSIZE=2", \
+			"-D_EM_LSIZE=4", "-D_EM_FSIZE=4", "-D_EM_DSIZE=8", \
+			"-D__ACK__", "-D__minix", "-D__i86"
+
+struct pass preprocessor = { "cpp",
+			    { PREP_FLAGS }
+			    , {0}
+			    };
+
+struct pass prepnoln = { "cpp",
+			    { PREP_FLAGS, "-P" }
+			    , {0}
+			    };
+
+struct pass irrel = { "irrel",
+			    {0}
+			};
+
+/* The "*" in the arguments for the loader indicates the place where the
+ * fp-emulation library should come.
+ */
+struct compile passes[] = {
+{	"c", "cc", 
+	{	{ "cem", {"-L"}, {0} },	/* changed */
+		{ "opt", {0}, {0} },
+		{ "cg", {0}, {0} },
+		{ "as", {"-"}, {0} },
+		{ "ld", {CRT}, /* changed */
+			  {LIBC, "*",  END}},
+		{ "cv", {0}, {0} }
+	},
+	DEFLANG
+},
+{	"p", "pc",
+	{	{ "pc", {0}, {0} },
+		{ "opt", {0}, {0} },
+		{ "cg", {0}, {0} },
+		{ "as", {"-"}, {0} },
+		{ "ld", {PRT}, 
+			  {LIBP,
+			    "*", END}},
+		{ "cv", {0}, {0} }
+	},
+	DEFLANG
+},
+{	"mod", "m2",
+	{	{ "m2", {M2DEF}, {0} },
+		{ "opt", {0}, {0} },
+		{ "cg", {0}, {0} },
+		{ "as", {"-"}, {0} },
+		{ "ld", {M2RT}, 
+			  {LIBM2,
+			    "*", END}},
+		{ "cv", {0}, {0} }
+	},
+	DEFLANG
+},
+{	"e", "encode",
+	{	{ "encode", {0}, {0}},
+		{ "opt", {0}, {0} },
+		{ "cg", {0}, {0} },
+		{ "as", {"-"}, {0} },
+		{ "ld", {0}, {"*", END}},
+		{ "cv", {0}, {0} }
+	},
+	DEFLANG
+},
+{	"s", "as",
+	{	{ "as", {0}, {0}}
+	},
+	0
+},
+{	"CPP", "cpp",
+	{	{ "cpp", {PREP_FLAGS}, {0}}
+	},
+	DEFLANG
+},
+{	0},
+};
+
+#define MAXARGC	150	/* maximum number of arguments allowed in a list */
+#define USTR_SIZE	64	/* maximum length of string variable */
+
+typedef char USTRING[USTR_SIZE];
+
+struct arglist {
+	int al_argc;
+	char *al_argv[MAXARGC];
+};
+
+struct arglist CALLVEC;
+
+int kids = -1;
+
+char *o_FILE = "a.out"; /* default name for executable file */
+
+#define init(a)		((a)->al_argc = 1)
+#define cleanup(str)		(str && remove(str))
+
+char *ProgCall = 0;
+
+int RET_CODE = 0;
+
+char *stopsuffix;
+int v_flag = 0;
+int t_flag = 0;
+int noexec = 0;
+int fp_lib = 1;
+int E_flag = 0;
+int i_flag = 1;
+
+
+USTRING curfil;
+USTRING newfil;
+struct arglist SRCFILES;
+struct arglist LDIRS;
+struct arglist LDFILES;
+struct arglist GEN_LDFILES;
+struct arglist FLAGS;
+
+char *tmpdir = "/tmp";
+char tmpname[64];
+
+struct compile *compbase;
+struct pass *loader;
+struct passinfo *loaderinfo;
+char *source;
+int maxLlen;
+
+_PROTOTYPE(char *library, (char *nm ));
+_PROTOTYPE(void trapcc, (int sig ));
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(int remove, (char *str ));
+_PROTOTYPE(char *alloc, (unsigned u ));
+_PROTOTYPE(int append, (struct arglist *al, char *arg ));
+_PROTOTYPE(int concat, (struct arglist *al1, struct arglist *al2 ));
+_PROTOTYPE(char *mkstr, (char *dst, char *arg1, char *arg2, char *arg3 ));
+_PROTOTYPE(int basename, (char *str, char *dst ));
+_PROTOTYPE(char *extension, (char *fln ));
+_PROTOTYPE(int runvec, (struct arglist *vec, struct passinfo *pass, char *in, char *out ));
+_PROTOTYPE(int prnum, (unsigned x ));
+_PROTOTYPE(int prs, (char *str ));
+_PROTOTYPE(int panic, (char *str ));
+_PROTOTYPE(int pr_vec, (struct arglist *vec ));
+_PROTOTYPE(int ex_vec, (struct arglist *vec ));
+_PROTOTYPE(int mktempname, (char *nm ));
+_PROTOTYPE(int mkbase, (void));
+_PROTOTYPE(int mkloader, (void));
+_PROTOTYPE(int needsprep, (char *name ));
+_PROTOTYPE(int cfile, (char *name ));
+_PROTOTYPE(char *apply, (struct passinfo *pinf, struct compile *cp, char *name, int passindex, int noremove, int first, char *resultname ));
+_PROTOTYPE(int applicable, (struct passinfo *pinf, char *suffix ));
+_PROTOTYPE(char *process, (char *name, int noremove ));
+_PROTOTYPE(int mkvec, (struct arglist *call, char *in, char *out, struct pass *pass, struct passinfo *pinf ));
+_PROTOTYPE(int callld, (struct arglist *in, char *out, struct pass *pass, struct passinfo *pinf ));
+_PROTOTYPE(int clean, (struct arglist *c ));
+_PROTOTYPE(int scanflags, (struct arglist *call, struct passinfo *pinf ));
+
+
+
+char *
+library(nm)
+	char	*nm;
+{
+	static char	f[512];
+	int	Lcount;
+
+	for (Lcount = 0; Lcount < LDIRS.al_argc; Lcount++) {
+		mkstr(f, LDIRS.al_argv[Lcount], "/lib", nm);
+		strcat(f, ".a");
+		if (access(f, 0) != 0) {
+			f[strlen(f)-1] = 'a';
+			if (access(f, 0) != 0) continue;
+		}
+		return f;
+	}
+	mkstr(f, LIBDIR, "/lib", nm);
+	strcat(f, ".a");
+	if (access(f, 0) != 0) {
+		int i = strlen(f) - 1;
+		f[i] = 'a';
+		if (access(f, 0) != 0) f[i] = 'A';
+	}
+	return f;
+}
+
+void trapcc(sig)
+	int sig;
+{
+	signal(sig, SIG_IGN);
+	if (kids != -1) kill(kids, sig);
+	cleanup(newfil);
+	cleanup(curfil);
+	exit(1);
+}
+
+main(argc, argv)
+	char *argv[];
+{
+	char *str;
+	char **argvec;
+	int count;
+	char *file;
+
+	maxLlen = strlen(LIBDIR);
+	ProgCall = *argv++;
+
+	mkbase();
+
+	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
+		signal(SIGHUP, trapcc);
+	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+		signal(SIGINT, trapcc);
+	if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+		signal(SIGQUIT, trapcc);
+	while (--argc > 0) {
+		if (*(str = *argv++) != '-' || str[1] == 0) {
+			append(&SRCFILES, str);
+			continue;
+		}
+
+		if (strcmp(str, "-com") == 0) {
+			i_flag = 0;
+		} else
+		if (strcmp(str, "-sep") == 0) {
+			i_flag = 1;
+		} else {
+			switch (str[1]) {
+
+			case 'c':
+				stopsuffix = "o";
+				if (str[2] == '.') stopsuffix = str + 3;
+				break;
+			case 'f':
+				fp_lib = (strcmp(str+2, "hard") != 0);
+				break;
+			case 'F':
+			case 'W':
+				/* Ignore. */
+				break;
+			case 'L':
+				append(&LDIRS, &str[2]);
+				count = strlen(&str[2]);
+				if (count > maxLlen) maxLlen = count;
+				break;
+			case 'l':
+				append(&SRCFILES, library(&str[2]));
+				break;
+			case 'm':
+				/* Use -m, ignore -mxxx. */
+				if (str[2] == 0) append(&FLAGS, str);
+				break;
+			case 'o':
+				if (argc-- >= 0)
+					o_FILE = *argv++;
+				break;
+			case 'S':
+				stopsuffix = "s";
+				break;
+			case 'E':
+				E_flag = 1;
+				stopsuffix = "i";
+				break;
+			case 'P':
+				stopsuffix = "i";
+				append(&FLAGS, str);
+				break;
+			case 'v':
+				v_flag++;
+				if (str[2] == 'n')
+					noexec = 1;
+				break;
+			case 't':
+				/* save temporaries */
+				t_flag++;
+				break;
+			case '.':
+				if (str[2] == 'o') {
+					/* no runtime start-off */
+					loader->pp_head[0] = 0;
+				}
+				break;
+			case 'i':
+				i_flag++;
+				break;
+			case 'T':
+				tmpdir = &str[2];
+				/*FALLTHROUGH*/
+			default:
+				append(&FLAGS, str);
+
+			}
+		}
+	}
+
+	if (i_flag) append(&FLAGS, "-i");
+
+	mktempname(tmpname);
+
+	count = SRCFILES.al_argc;
+	argvec = &(SRCFILES.al_argv[0]);
+
+	while (count-- > 0) {
+
+		file = *argvec++;
+		source = file;
+
+		file = process(file, 1);
+	
+		if (file && ! stopsuffix) append(&LDFILES, file);
+	}
+
+	clean(&SRCFILES);
+
+	/* loader ... */
+	if (RET_CODE == 0 && LDFILES.al_argc > 0) {
+		register struct passinfo *pp = passinfo;
+
+		while (!(pp->p_flags & LOADER)) pp++;
+		mkstr(newfil, tmpname, pp->p_to, "");
+		callld(&LDFILES, !((pp+1)->p_name) ? o_FILE : newfil, loader, pp);
+		if (RET_CODE == 0) {
+			register int i = GEN_LDFILES.al_argc;
+
+			while (i-- > 0) {
+				remove(GEN_LDFILES.al_argv[i]);
+				free(GEN_LDFILES.al_argv[i]);
+			}
+			if ((++pp)->p_name) {
+				process(newfil, 0);
+			}
+		}
+	}
+	exit(RET_CODE);
+}
+
+remove(str)
+	char *str;
+{
+	if (t_flag)
+		return;
+	if (v_flag) {
+		prs("rm ");
+		prs(str);
+		prs("\n");
+	}
+	if (noexec)
+		return;
+	unlink(str);
+}
+
+char *
+alloc(u)
+	unsigned u;
+{
+	register char *p = malloc(u);
+
+	if (p == 0) panic("no space\n");
+	return p;
+}
+
+append(al, arg)
+	struct arglist *al;
+	char *arg;
+{
+	char *a = alloc((unsigned) (strlen(arg) + 1));
+
+	strcpy(a, arg);
+	if (al->al_argc >= MAXARGC)
+		panic("argument list overflow\n");
+	al->al_argv[(al->al_argc)++] = a;
+}
+
+concat(al1, al2)
+	struct arglist *al1, *al2;
+{
+	register i = al2->al_argc;
+	register char **p = &(al1->al_argv[al1->al_argc]);
+	register char **q = &(al2->al_argv[0]);
+
+	if ((al1->al_argc += i) >= MAXARGC)
+		panic("argument list overflow\n");
+	while (i-- > 0)
+		*p++ = *q++;
+}
+
+char *
+mkstr(dst, arg1, arg2, arg3)
+	char *dst, *arg1, *arg2, *arg3;
+{
+	register char *p;
+	register char *q = dst;
+
+	p = arg1;
+	while (*q++ = *p++);
+	q--;
+	p = arg2;
+	while (*q++ = *p++);
+	q--;
+	p = arg3;
+	while (*q++ = *p++);
+	q--;
+	return dst;
+}
+
+basename(str, dst)
+	char *str;
+	register char *dst;
+{
+	register char *p1 = str;
+	register char *p2 = p1;
+
+	while (*p1)
+		if (*p1++ == '/')
+			p2 = p1;
+	p1--;
+	while (*p1 != '.' && p1 > p2) p1--;
+	if (*p1 == '.') {
+		*p1 = '\0';
+		while (*dst++ = *p2++);
+		*p1 = '.';
+	}
+	else
+		while (*dst++ = *p2++);
+}
+
+char *
+extension(fln)
+	char *fln;
+{
+	register char *fn = fln;
+
+	while (*fn) fn++;
+	while (fn > fln && *fn != '.') fn--;
+	if (fn != fln) return fn+1;
+	return (char *)0;
+}
+
+runvec(vec, pass, in, out)
+	struct arglist *vec;
+	struct passinfo *pass;
+	char *in, *out;
+{
+	int pid, status;
+	int shifted = 0;
+
+	if (
+		strncmp(vec->al_argv[1], "/usr/", 5) == 0
+		&&
+		access(vec->al_argv[1] + 4, 1) == 0
+	) {
+		vec->al_argv[1] += 4;
+		shifted = 1;
+	}
+
+	if (v_flag) {
+		pr_vec(vec);
+		if (pass->p_flags & STDIN) {
+			prs(" <");
+			prs(in);
+		}
+		if (pass->p_flags & STDOUT && !E_flag) {
+			prs(" >");
+			prs(out);
+		}
+		prs("\n");
+	}
+	if (noexec) {
+		if (shifted) vec->al_argv[1] -= 4;
+		clean(vec);
+		return 1;
+	}
+	if ((pid = fork()) == 0) {	/* start up the process */
+		if (pass->p_flags & STDIN && strcmp(in, "-") != 0) {
+			/* redirect standard input */
+			close(0);
+			if (open(in, 0) != 0)
+				panic("cannot open input file\n");
+		}
+		if (pass->p_flags & STDOUT && !E_flag) {
+			/* redirect standard output */
+			close(1);
+			if (creat(out, 0666) != 1)
+				panic("cannot create output file\n");
+		}
+		ex_vec(vec);
+	}
+	if (pid == -1)
+		panic("no more processes\n");
+	kids = pid;
+	wait(&status);
+	if (status) switch(status & 0177) {
+	case SIGHUP:
+	case SIGINT:
+	case SIGQUIT:
+	case SIGTERM:
+	case 0:
+		break;
+	default:
+		if (E_flag && (status & 0177) == SIGPIPE) break;
+		prs(vec->al_argv[1]);
+		prs(" died with signal ");
+		prnum(status & 0177);
+		prs("\n");
+	}
+	if (shifted) vec->al_argv[1] -= 4;
+	clean(vec);
+	kids = -1;
+	return status ? ((RET_CODE = 1), 0) : 1;
+}
+
+prnum(x)
+	register unsigned x;
+{
+	static char numbuf[8];			/* though it prints at most 3 characters */
+	register char *cp = numbuf + sizeof(numbuf) - 1;
+
+	*cp = '\0';
+	while (x >= 10) {
+		*--cp = (x % 10) + '0';
+		x /= 10;
+	}
+	*--cp = x + '0';
+	prs(cp);
+
+}
+
+prs(str)
+	char *str;
+{
+	if (str && *str)
+		write(2, str, strlen(str));
+}
+
+panic(str)
+	char *str;
+{
+	prs(str);
+	trapcc(SIGINT);
+}
+
+pr_vec(vec)
+	register struct arglist *vec;
+{
+	register char **ap = &vec->al_argv[1];
+	
+	vec->al_argv[vec->al_argc] = 0;
+	prs(*ap);
+	while (*++ap) {
+		prs(" ");
+		if (strlen(*ap))
+			prs(*ap);
+		else
+			prs("(empty)");
+	}
+}
+
+ex_vec(vec)
+	register struct arglist *vec;
+{
+	extern int errno;
+
+	vec->al_argv[vec->al_argc] = 0;
+	execv(vec->al_argv[1], &(vec->al_argv[1]));
+	if (errno == ENOEXEC) { /* not an a.out, try it with the SHELL */
+		vec->al_argv[0] = SHELL;
+		execv(SHELL, &(vec->al_argv[0]));
+	}
+	if (access(vec->al_argv[1], 1) == 0) {
+		/* File is executable. */
+		prs("Cannot execute ");
+		prs(vec->al_argv[1]);
+		prs(". Not enough memory.\n");
+		prs("Reduce the memory use of your system and try again\n");
+	} else {
+		prs(vec->al_argv[1]);
+		prs(" is not executable\n");
+	}
+	exit(1);
+}
+
+mktempname(nm)
+	register char *nm;
+{
+	register int i;
+	register int pid = getpid();
+
+	mkstr(nm, tmpdir, "/", compbase->c_callname);
+	while (*nm) nm++;
+
+	for (i = 9; i > 3; i--) {
+		*nm++ = (pid % 10) + '0';
+		pid /= 10;
+	}
+	*nm++ = '.';
+	*nm++ = '\0'; /* null termination */
+}
+
+mkbase()
+{
+	register struct compile *p = passes;
+	USTRING callname;
+	register int len;
+
+	basename(ProgCall, callname);
+	len = strlen(callname);
+	while (p->c_suffix) {
+		if (strcmp(p->c_callname, callname+len-strlen(p->c_callname)) == 0) {
+			compbase = p;
+			mkloader();
+			return;
+		}
+		p++;
+	}
+	/* we should not get here */
+	panic("internal error\n");
+}
+
+mkloader()
+{
+	register struct passinfo *p = passinfo;
+	register struct pass *pass;
+
+	while (!(p->p_flags & LOADER)) p++;
+	loaderinfo = p;
+	pass = &(compbase->c_passes[0]);
+	while (strcmp(pass->pp_name, p->p_name)) pass++;
+	loader = pass;
+}
+
+needsprep(name)
+	char *name;
+{
+	int file;
+	char fc;
+
+	file = open(name,0);
+	if (file <0) return 0;
+	if (read(file, &fc, 1) != 1) fc = 0;
+	close(file);
+	return fc == '#';
+}
+
+cfile(name)
+	char *name;
+{
+	while (*name != '\0' && *name != '.')
+		name++;
+
+	if (*name == '\0') return 0;
+	return (*++name == 'c' && *++name == '\0');
+}
+
+char *
+apply(pinf, cp, name, passindex, noremove, first, resultname)
+	register struct passinfo *pinf;
+	register struct compile *cp;
+	char *name, *resultname;
+{
+	/*	Apply a pass, indicated by "pinf", with args in 
+		cp->c_passes[passindex], to name "name", leaving the result
+		in a file with name "resultname", concatenated with result
+		suffix.
+		When neccessary, the preprocessor is run first.
+		If "noremove" is NOT set, the file "name" is removed.
+	*/
+
+	struct arglist *call = &CALLVEC;
+	struct pass *pass = &(cp->c_passes[passindex]);
+	char *outname;
+
+	if ( /* this pass is the first pass */
+	     first
+	   &&
+	     ( /* preprocessor always needed */
+	       (pinf->p_flags & PREPALWAYS)
+	     ||/* or only when "needsprep" says so */
+	       ( (pinf->p_flags & PREPCOND) && needsprep(name))
+	     )
+	   ) {
+		mkstr(newfil, tmpname, passinfo[0].p_to, "");
+		mkvec(call, name, newfil,
+			(pinf->p_flags & PREPNOLN) ? &prepnoln : &preprocessor,
+			&passinfo[0]);
+		if (! runvec(call, &passinfo[0], name, newfil)) {
+			cleanup(newfil);
+			return 0;
+		}
+
+		/* A .c file must always be mishandled by irrel. */
+		if (cfile(name)) {
+			/* newfil is OK */
+			mkvec(call, newfil, newfil, &irrel, &passinfo[1]);
+			if (! runvec(call, &passinfo[1], newfil, newfil)) {
+				cleanup(newfil);
+				return 0;
+			}
+		}
+		strcpy(curfil, newfil);
+		newfil[0] = '\0';
+		name = curfil;
+		noremove = 0;
+	}
+	if (pinf->p_to) outname = mkstr(newfil, resultname, pinf->p_to, "");
+	else outname = o_FILE;
+	mkvec(call, name, outname, pass, pinf);
+	if (! runvec(call, pinf, name, outname)) {
+		if (! (pinf->p_flags & NOCLEAN)) cleanup(outname);
+		if (! noremove) cleanup(name);
+		return 0;
+	}
+	if (! noremove) cleanup(name);
+	strcpy(curfil, newfil);
+	newfil[0] = '\0';
+	return curfil;
+}
+
+int
+applicable(pinf, suffix)
+	struct passinfo *pinf;
+	char *suffix;
+{
+	/*	Return one if the pass indicated by "pinfo" is applicable to
+		a file with suffix "suffix".
+	*/
+	register char *sfx = pinf->p_from;
+	int l;
+
+	if (! suffix) return 0;
+	l = strlen(suffix);
+	while (*sfx) {
+		register char *p = sfx;
+
+		while (*p && *p != ',') p++;
+		if (l == p - sfx && strncmp(sfx, suffix, l) == 0) {
+			return 1;
+		}
+		if (*p == ',') sfx = p+1;
+		else sfx = p;
+	}
+	return 0;
+}
+		
+char *
+process(name, noremove)
+	char *name;
+{
+	register struct compile *cp = passes;
+	char *suffix = extension(name);
+	USTRING base;
+	register struct pass *pass;
+	register struct passinfo *pinf;
+
+	if (E_flag) {
+		/* -E uses the cpp pass. */
+		suffix = "CPP";
+	}
+
+	if (! suffix) return name;
+
+	basename(name, base);
+
+	while (cp->c_suffix) {
+		if ((cp->c_flags & DEFLANG) &&
+		    strcmp(cp->c_suffix, suffix) == 0)
+			break;
+		cp++;
+	}
+	if (! cp->c_suffix) cp = compbase;
+	pass = cp->c_passes;
+	while (pass->pp_name) {
+		int first = 1;
+
+		for (pinf=passinfo; strcmp(pass->pp_name,pinf->p_name);pinf++)
+			;
+		if (! (pinf->p_flags & LOADER) && applicable(pinf, suffix)) {
+			int cont = ! stopsuffix || ! pinf->p_to ||
+					strcmp(stopsuffix, pinf->p_to) != 0;
+			name = apply(pinf,
+				     cp,
+				     name,
+				     (int) (pass - cp->c_passes),
+				     noremove,
+				     first,
+				     applicable(loaderinfo, pinf->p_to) ||
+				      !cont ?
+					strcat(base, ".") :
+					tmpname);
+			first = noremove = 0;
+			suffix = pinf->p_to;
+			if (!cont || !name) break;
+		}
+		pass++;
+	}
+	if (!noremove && name)
+		append(&GEN_LDFILES, name);
+	return name;
+}
+
+mkvec(call, in, out, pass, pinf)
+	struct arglist *call;
+	char *in, *out;
+	struct pass *pass;
+	register struct passinfo *pinf;
+{
+	register int i;
+
+	init(call);
+	append(call, pinf->p_path);
+	scanflags(call, pinf);
+	if (pass) for (i = 0; i < MAXHEAD; i++)
+		if (pass->pp_head[i])
+			append(call, pass->pp_head[i]);
+		else	break;
+	if (pinf->p_flags & INPUT && strcmp(in, "-") != 0)
+		append(call, in);
+	if (pinf->p_flags & OUTPUT)
+		append(call, out);
+	if (pinf->p_flags & O_OUTPUT) {
+		append(call, "-o");
+		append(call, out);
+	}
+	if (pass) for (i = 0; i < MAXTAIL; i++)
+		if (pass->pp_tail[i])
+			append(call, pass->pp_tail[i]);
+		else	break;
+}
+
+callld(in, out, pass, pinf)
+	struct arglist *in;
+	char *out;
+	struct pass *pass;
+	register struct passinfo *pinf;
+{
+	struct arglist *call = &CALLVEC;
+	register int i;
+
+	init(call);
+	append(call, pinf->p_path);
+	scanflags(call, pinf);
+	append(call, "-o");
+	append(call, out);
+	for (i = 0; i < MAXHEAD; i++)
+		if (pass->pp_head[i])
+			append(call, pass->pp_head[i]);
+		else	break;
+	if (pinf->p_flags & INPUT)
+		concat(call, in);
+	if (pinf->p_flags & OUTPUT)
+		append(call, out);
+	for (i = 0; i < MAXTAIL; i++) {
+		if (pass->pp_tail[i]) {
+			if (pass->pp_tail[i][0] == '-' &&
+			    pass->pp_tail[i][1] == 'l') {
+				append(call, library(&(pass->pp_tail[i][2])));
+			}
+			else if (*(pass->pp_tail[i]) != '*')
+				append(call, pass->pp_tail[i]);
+			else if (fp_lib)
+				append(call, library("fp"));
+		} else	break;
+	}
+	if (! runvec(call, pinf, (char *) 0, out)) {
+		cleanup(out);
+		RET_CODE = 1;
+	}
+}
+
+clean(c)
+	register struct arglist *c;
+{
+	register int i;
+
+	for (i = 1; i < c->al_argc; i++) {
+		free(c->al_argv[i]);
+		c->al_argv[i] = 0;
+	}
+	c->al_argc = 0;
+}
+
+scanflags(call, pinf)
+	struct arglist *call;
+	struct passinfo *pinf;
+{
+	/*	Find out which flags from FLAGS must be passed to pass "pinf",
+		and how. 
+		Append them to "call"
+	*/
+	register int i;
+	USTRING flg;
+
+	for (i = 0; i < FLAGS.al_argc; i++) {
+		register char *q = pinf->p_acceptflags;
+
+		while (*q)  {
+			register char *p = FLAGS.al_argv[i] + 1;
+
+			while (*q && *q == *p) {
+				q++; p++;
+			}
+			if (*q == ',' || !*q) {
+				if (! *p) {
+					/* append literally */
+					append(call, FLAGS.al_argv[i]);
+				}
+				break;
+			}
+			if (*q == '*') {
+				register char *s = flg;
+
+				if (*++q != '=') {
+					/* append literally */
+					append(call, FLAGS.al_argv[i]);
+					break;
+				}
+				*s++ = '-';
+				if (*q) q++;	/* skip ',' */
+				while (*q && *q != ',' && *q != '*') {
+					/* copy replacement flag */
+					*s++ = *q++;
+				}
+				if (*q == '*') {
+					/* copy rest */
+					while (*p) *s++ = *p++;
+				}
+				*s = 0;
+				append(call, flg);
+				break;
+			}
+			if (*q == '=') {
+				/* copy replacement */
+				register char *s = flg;
+
+				*s++ = '-';
+				q++;
+				while (*q && *q != ',') *s++ = *q++;
+				*s = 0;
+				append(call, flg);
+				break;
+			}
+			while (*q && *q++ != ',')
+				;
+		}
+	}
+}
Index: /trunk/minix/commands/ibm/Makefile
===================================================================
--- /trunk/minix/commands/ibm/Makefile	(revision 9)
+++ /trunk/minix/commands/ibm/Makefile	(revision 9)
@@ -0,0 +1,183 @@
+# Makefile for commands/ibm.
+
+# See commands/simple/Makefile for a description.
+
+CFLAGS	= -D_MINIX -D_POSIX_SOURCE
+CCLD	= $(CC) -i $(CFLAGS)
+MAKE	= exec make -$(MAKEFLAGS)
+CC = exec cc
+
+ALL	= \
+	atnormalize \
+	dosread \
+	fdisk \
+	format \
+	loadfont \
+	loadkeys \
+	mixer \
+	autopart \
+	part \
+	partition \
+	playwave \
+	postmort \
+	readclock \
+	recwave \
+	repartition \
+	screendump \
+	sdump \
+
+all:	$(ALL)
+
+dosread:	dosread.c
+	$(CCLD) -o $@ $?
+	install -S 16kw $@
+
+atnormalize:	atnormalize.c
+	$(CCLD) -o $@ $?
+	install -S 16kw $@
+
+fdisk:	fdisk.c
+	$(CCLD) -o $@ $?
+	install -S 4kw $@
+
+format:	format.c
+	$(CCLD) -o $@ $?
+	install -S 4kw $@
+
+loadfont:	loadfont.c
+	$(CCLD) -o $@ $?
+	install -S 4kw $@
+
+loadkeys:	loadkeys.c
+	$(CCLD) -o $@ $?
+	install -S 4kw $@
+
+mixer:	mixer.c
+	$(CCLD) -o $@ $? -lcurses
+	install -S 16kw $@
+
+autopart:	autopart.c
+	$(CCLD) -o $@ $?
+	install -S 11kw $@
+
+part:	part.c
+	$(CCLD) -o $@ $?
+	install -S 11kw $@
+
+partition:	partition.c
+	$(CCLD) -o $@ $?
+	install -S 4kw $@
+
+playwave:	playwave.c
+	$(CCLD) -o $@ $?
+	install -S 16kw $@
+
+postmort:	postmort.c
+	$(CCLD) -o $@ $?
+	install -S 4kw $@
+
+readclock:	readclock.c
+	$(CCLD) -o $@ $?
+	install -S 4kw $@
+
+recwave:	recwave.c
+	$(CCLD) -o $@ $?
+	install -S 16kw $@
+
+repartition:	repartition.c
+	$(CCLD) -o $@ $?
+	install -S 4kw $@
+
+screendump:	screendump.c
+	$(CCLD) -o $@ $?
+	install -S 4kw $@
+
+sdump:	sdump.c
+	$(CCLD) -o $@ $?
+	install -S 4kw $@
+
+install:	\
+	/usr/bin/atnormalize \
+	/usr/bin/dosread \
+		/usr/bin/dosdir \
+		/usr/bin/doswrite \
+	/usr/bin/fdisk \
+	/usr/bin/format \
+	/usr/bin/loadfont \
+	/usr/bin/loadkeys \
+	/usr/bin/mixer \
+	/usr/bin/autopart \
+	/usr/bin/part \
+	/usr/bin/partition \
+	/usr/bin/playwave \
+	/usr/bin/postmort \
+	/usr/bin/readclock \
+	/usr/bin/recwave \
+	/usr/bin/repartition \
+	/usr/bin/screendump \
+	/usr/bin/sdump \
+	/bin/loadkeys \
+	/bin/readclock \
+
+/usr/bin/atnormalize:	atnormalize
+	install -cs -o bin $? $@
+
+/usr/bin/dosread:	dosread
+	install -cs -o bin $? $@
+
+/usr/bin/dosdir /usr/bin/doswrite:	/usr/bin/dosread
+	install -l $? $@
+
+/usr/bin/fdisk:	fdisk
+	install -cs -o bin $? $@
+
+/usr/bin/format:	format
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/loadfont:	loadfont
+	install -cs -o bin $? $@
+
+/usr/bin/loadkeys:	loadkeys
+	install -cs -o bin $? $@
+
+/usr/bin/mixer:	mixer
+	install -cs -o bin $? $@
+
+/usr/bin/autopart:	autopart
+	install -lcs $? $@
+
+/usr/bin/part:	part
+	install -cs -o bin $? $@
+
+/usr/bin/partition:	partition
+	install -cs -o bin $? $@
+
+/usr/bin/playwave:	playwave
+	install -cs -o bin $? $@
+
+/usr/bin/postmort:	postmort
+	install -cs -o bin $? $@
+
+/usr/bin/readclock:	readclock
+	install -cs -o bin $? $@
+
+/usr/bin/recwave:	recwave
+	install -cs -o bin $? $@
+
+/usr/bin/repartition:	repartition
+	install -cs -o bin $? $@
+
+/usr/bin/screendump:	screendump
+	install -cs -o bin $? $@
+
+/usr/bin/sdump:	sdump
+	install -cs -o bin $? $@
+
+/bin/loadkeys:	/usr/bin/loadkeys
+	install -lcs $? $@
+
+/bin/readclock:	/usr/bin/readclock
+	install -lcs $? $@
+
+clean:
+	rm -rf $(ALL) a.out core
Index: /trunk/minix/commands/ibm/atnormalize.c
===================================================================
--- /trunk/minix/commands/ibm/atnormalize.c	(revision 9)
+++ /trunk/minix/commands/ibm/atnormalize.c	(revision 9)
@@ -0,0 +1,43 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <termcap.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <time.h>
+#include <dirent.h>
+#include <limits.h>
+#include <a.out.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/partition.h>
+#include <minix/u64.h>
+#include <ibm/partition.h>
+#include <termios.h>
+#include <stdarg.h>
+
+int main(void)
+{
+	int v, d;
+	char name[20];
+
+	for(d = 0; d < 4; d++) {
+		int device;
+		sprintf(name, "/dev/c0d%d", d);
+		if((device=open(name, O_RDONLY)) >= 0) {
+			v = 0;
+			ioctl(device, DIOCTIMEOUT, &v);
+			close(device);
+		}
+	}
+
+	return 0;
+}
Index: /trunk/minix/commands/ibm/autopart.c
===================================================================
--- /trunk/minix/commands/ibm/autopart.c	(revision 9)
+++ /trunk/minix/commands/ibm/autopart.c	(revision 9)
@@ -0,0 +1,2838 @@
+/*	part 1.57 - Partition table editor		Author: Kees J. Bot
+ *								13 Mar 1992
+ * Needs about 22k heap+stack.
+ *
+ * Forked july 2005 into autopart (Ben Gras), a mode which gives the user
+ * an easier time.
+ *
+ */
+#define nil 0
+#include <sys/types.h>
+#include <stdio.h>
+#include <termcap.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <time.h>
+#include <dirent.h>
+#include <limits.h>
+#include <a.out.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/partition.h>
+#include <minix/u64.h>
+#include <ibm/partition.h>
+#include <termios.h>
+#include <stdarg.h>
+
+/* Declare prototype. */
+static void printstep(int step, char *message);
+
+/* True if a partition is an extended partition. */
+#define ext_part(s)	((s) == 0x05 || (s) == 0x0F)
+
+/* Minix master bootstrap code. */
+static char MASTERBOOT[] = "/usr/mdec/masterboot";
+
+/* Template:
+                      ----first----  --geom/last--  ------sectors-----
+    Device             Cyl Head Sec   Cyl Head Sec      Base      Size        Kb
+    /dev/c0d0                          977    5  17
+    /dev/c0d0:2          0    0   2   976    4  16         2     83043     41521
+Num Sort   Type
+ 0* p0   81 MINIX        0    0   3    33    4   9         3      2880      1440
+ 1  p1   81 MINIX       33    4  10   178    2   2      2883     12284      6142
+ 2  p2   81 MINIX      178    2   3   976    4  16     15167     67878     33939
+ 3  p3   00 None         0    0   0     0    0  -1         0         0         0
+
+ */
+#define MAXSIZE		999999999L
+#define SECTOR_SIZE	512
+#define DEV_FD0		0x200		/* Device number of /dev/fd0 */
+#define DEV_C0D0	0x300		/* Device number of /dev/c0d0 */
+
+int min_region_mb = 500;
+
+#define MIN_REGION_SECTORS (1024*1024*min_region_mb/SECTOR_SIZE)
+
+#define MAX_REGION_MB	4095
+#define MAX_REGION_SECTORS (1024*(1024/SECTOR_SIZE)*MAX_REGION_MB)
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+
+#define SORNOT(n) ((n) == 1 ? "" : "s")
+
+/* screen colours */
+#define COL_RED		1
+#define COL_GREEN	2
+#define COL_ORANGE	3
+#define COL_BLUE	4
+#define COL_MAGENTA	5
+#define COL_CYAN	6
+
+#define SURE_SERIOUS	1
+#define SURE_BACK	2
+
+void col(int col)
+{
+	if(!col) printf("\033[0m");
+	else printf("\033[3%dm", col % 10);
+}
+
+void type2col(int type)
+{
+	switch(type) {
+		/* minix */
+		case 0x80:
+		case MINIX_PART:	col(COL_GREEN);	break;
+
+		/* dos/windows */
+		case 0x0B: case 0x0C: case 0x0E: case 0x0F: case 0x42:
+		case 0x07: 		col(COL_CYAN);		break;
+
+		/* linux */
+		case 0x82: case 0x83:	col(COL_ORANGE);	break;
+	}
+}
+
+int open_ct_ok(int fd)
+{
+	int c = -1;
+	if(ioctl(fd, DIOCOPENCT, &c) < 0) {
+		printf("Warning: couldn't verify opencount, continuing\n");
+		return 1;
+	}
+
+	if(c == 1) return 1;
+	if(c < 1) { printf("Error: open count %d\n", c); }
+
+	return 0;
+}
+
+void report(const char *label)
+{
+	fprintf(stderr, "part: %s: %s\n", label, strerror(errno));
+}
+
+void fatal(const char *label)
+{
+	report(label);
+	exit(1);
+}
+
+struct termios termios;
+
+void save_ttyflags(void)
+/* Save tty attributes for later restoration. */
+{
+	if (tcgetattr(0, &termios) < 0) fatal("");
+}
+
+void restore_ttyflags(void)
+/* Reset the tty flags to how we got 'em. */
+{
+	if (tcsetattr(0, TCSANOW, &termios) < 0) fatal("");
+}
+
+void tty_raw(void)
+/* Set the terminal to raw mode, no signals, no echoing. */
+{
+	struct termios rawterm;
+
+	rawterm= termios;
+	rawterm.c_lflag &= ~(ICANON|ISIG|ECHO);
+	rawterm.c_iflag &= ~(ICRNL);
+	if (tcsetattr(0, TCSANOW, &rawterm) < 0) fatal("");
+}
+
+#define ctrl(c)		((c) == '?' ? '\177' : ((c) & '\37'))
+
+char t_cd[16], t_cm[32], t_so[16], t_se[16], t_md[16], t_me[16];
+int t_li, t_co;
+#define STATUSROW	10
+
+void init_tty(void)
+/* Get terminal capabilities and set the tty to "editor" mode. */
+{
+	char *term;
+	static char termbuf[1024];
+	char *tp;
+
+	if ((term= getenv("TERM")) == nil || tgetent(termbuf, term) != 1) {
+		fprintf(stderr, "part: Can't get terminal capabilities\n");
+		exit(1);
+	}
+	if (tgetstr("cd", (tp= t_cd, &tp)) == nil
+				|| tgetstr("cm", (tp= t_cm, &tp)) == nil) {
+		fprintf(stderr, "part: This terminal is too dumb\n");
+		exit(1);
+	}
+	t_li= tgetnum("li");
+	t_co= tgetnum("co");
+	(void) tgetstr("so", (tp= t_so, &tp));
+	(void) tgetstr("se", (tp= t_se, &tp));
+	(void) tgetstr("md", (tp= t_md, &tp));
+	(void) tgetstr("me", (tp= t_me, &tp));
+
+	save_ttyflags();
+	tty_raw();
+}
+
+void putchr(int c)
+{
+	putchar(c);
+}
+
+void putstr(char *s)
+{
+	int c;
+
+	while ((c= *s++) != 0) putchr(c);
+}
+
+void set_cursor(int row, int col)
+{
+	tputs(tgoto(t_cm, col, row), 1, putchr);
+}
+
+int statusrow= STATUSROW;
+int stat_ktl= 1;
+int need_help= 1;
+
+void stat_start(int serious)
+/* Prepare for printing on a fresh status line, possibly highlighted. */
+{
+	set_cursor(statusrow++, 0);
+	tputs(t_cd, 1, putchr);
+	if (serious) tputs(t_so, 1, putchr);
+}
+
+void stat_end(int ktl)
+/* Closing bracket for stat_start.  Sets "keystrokes to live" of message. */
+{
+	tputs(t_se, 1, putchr);
+	stat_ktl= ktl;
+	need_help= 1;
+}
+
+void stat_reset(void)
+/* Reset the statusline pointer and clear old messages if expired. */
+{
+	if (stat_ktl > 0 && --stat_ktl == 0) {
+		statusrow= STATUSROW;
+		need_help= 1;
+	}
+	if (need_help && statusrow < (24-2)) {
+		if (statusrow > STATUSROW) stat_start(0);
+		stat_start(0);
+		putstr(
+"Type '+' or '-' to change, 'r' to read, '?' for more help, '!' for advice");
+	}
+	statusrow= STATUSROW;
+	need_help= 0;
+}
+
+void clear_screen(void)
+{
+	set_cursor(0, 0);
+	tputs(t_cd, 1, putchr);
+	stat_ktl= 1;
+	stat_reset();
+}
+
+void reset_tty(void)
+/* Reset the tty to cooked mode. */
+{
+	restore_ttyflags();
+	set_cursor(statusrow, 0);
+	tputs(t_cd, 1, putchr);
+}
+
+void *alloc(size_t n)
+{
+	void *m;
+
+	if ((m= malloc(n)) == nil) { reset_tty(); fatal(""); }
+
+	return m;
+}
+
+#ifndef makedev		/* Missing in sys/types.h */
+#define minor(dev)	(((dev) >> MINOR) & BYTE)
+#define major(dev)	(((dev) >> MAJOR) & BYTE)
+#define makedev(major, minor)	\
+			((dev_t) (((major) << MAJOR) | ((minor) << MINOR)))
+#endif
+
+typedef enum parttype { DUNNO, SUBPART, PRIMARY, FLOPPY } parttype_t;
+
+typedef struct device {
+	struct device *next, *prev;	/* Circular dequeue. */
+	dev_t	rdev;			/* Device number (sorting only). */
+	char	*name;			/* E.g. /dev/c0d0 */
+	char	*subname;		/* E.g. /dev/c0d0:2 */
+	parttype_t parttype;
+	int biosdrive;
+} device_t;
+
+typedef struct region {
+	/* A region is either an existing top-level partition
+	 * entry (used_part is non-NULL) or free space (free_*
+	 * contains data).
+	 */
+	struct part_entry used_part;
+	int is_used_part;
+	int tableno;
+	int free_sec_start, free_sec_last;
+} region_t;
+
+/* A disk has between 1 and 2*partitions+1 regions;
+ * the last case is free space before and after every partition.
+ */
+#define NR_REGIONS (2*NR_PARTITIONS+1)
+region_t regions[NR_REGIONS];
+int nr_partitions = 0, nr_regions = 0, free_regions, used_regions;
+int nordonly = 0;
+
+device_t *firstdev= nil, *curdev;
+
+#define MAX_DEVICES 100
+	static struct {
+		device_t *dev;
+		int nr_partitions, free_regions, used_regions, sectors, nr_regions;
+		int biosdrive;
+		region_t regions[NR_REGIONS];
+	} devices[MAX_DEVICES];
+
+void newdevice(char *name, int scanning, int disk_only)
+/* Add a device to the device list.  If scanning is set then we are reading
+ * /dev, so insert the device in device number order and make /dev/c0d0 current.
+ */
+{
+	device_t *new, *nextdev, *prevdev;
+	struct stat st;
+
+	st.st_rdev= 0;
+	if (scanning) {
+		if (stat(name, &st) < 0 || !S_ISBLK(st.st_mode)) return;
+
+		switch (major(st.st_rdev)) {
+		case 3:
+			/* Disk controller */
+			if (minor(st.st_rdev) >= 0x80
+					|| minor(st.st_rdev) % 5 != 0) return;
+			break;
+		default:
+			return;
+		}
+		/* Interesting device found. */
+	} else {
+		if(stat(name, &st) < 0) { perror(name); return; }
+	}
+
+	new= alloc(sizeof(*new));
+	new->rdev= st.st_rdev;
+	new->name= alloc((strlen(name) + 1) * sizeof(new->name[0]));
+	strcpy(new->name, name);
+	new->subname= new->name;
+	new->parttype= DUNNO;
+	if (major(st.st_rdev) == major(DEV_FD0) && minor(st.st_rdev) < 112) {
+		new->parttype= FLOPPY;
+	} else
+	if (st.st_rdev >= DEV_C0D0 && minor(st.st_rdev) < 128
+			&& minor(st.st_rdev) % 5 == 0) {
+		new->parttype= PRIMARY;
+	}
+
+	if (firstdev == nil) {
+		firstdev= new;
+		new->next= new->prev= new;
+		curdev= firstdev;
+		return;
+	}
+	nextdev= firstdev;
+	while (new->rdev >= nextdev->rdev
+				&& (nextdev= nextdev->next) != firstdev) {}
+	prevdev= nextdev->prev;
+	new->next= nextdev;
+	nextdev->prev= new;
+	new->prev= prevdev;
+	prevdev->next= new;
+
+	if (new->rdev < firstdev->rdev) firstdev= new;
+	if (new->rdev == DEV_C0D0) curdev= new;
+	if (curdev->rdev != DEV_C0D0) curdev= firstdev;
+}
+
+void getdevices(int disk_only)
+/* Get all block devices from /dev that look interesting. */
+{
+	DIR *d;
+	struct dirent *e;
+	char name[5 + NAME_MAX + 1];
+
+	if ((d= opendir("/dev")) == nil) fatal("/dev");
+
+	while ((e= readdir(d)) != nil) {
+		strcpy(name, "/dev/");
+		strcpy(name + 5, e->d_name);
+		newdevice(name, 1, disk_only);
+	}
+	(void) closedir(d);
+}
+
+/* One featureful master bootstrap. */
+unsigned char bootstrap[] = {
+0353,0001,0000,0061,0300,0216,0330,0216,0300,0372,0216,0320,0274,0000,0174,0373,
+0275,0276,0007,0211,0346,0126,0277,0000,0006,0271,0000,0001,0374,0363,0245,0352,
+0044,0006,0000,0000,0264,0002,0315,0026,0250,0010,0164,0033,0350,0071,0001,0174,
+0007,0060,0344,0315,0026,0242,0205,0007,0054,0060,0074,0012,0163,0363,0120,0350,
+0046,0001,0205,0007,0130,0353,0012,0240,0002,0006,0204,0300,0165,0003,0351,0147,
+0000,0230,0262,0005,0366,0362,0262,0200,0000,0302,0210,0340,0120,0350,0234,0000,
+0163,0003,0351,0147,0000,0130,0054,0001,0175,0003,0351,0141,0000,0276,0276,0175,
+0211,0357,0271,0040,0000,0363,0245,0200,0301,0004,0211,0356,0215,0174,0020,0070,
+0154,0004,0164,0016,0213,0135,0010,0053,0134,0010,0213,0135,0012,0033,0134,0012,
+0163,0014,0212,0044,0206,0144,0020,0210,0044,0106,0071,0376,0162,0364,0211,0376,
+0201,0376,0356,0007,0162,0326,0342,0322,0211,0356,0264,0020,0366,0344,0001,0306,
+0200,0174,0004,0001,0162,0026,0353,0021,0204,0322,0175,0041,0211,0356,0200,0174,
+0004,0000,0164,0013,0366,0004,0200,0164,0006,0350,0070,0000,0162,0053,0303,0203,
+0306,0020,0201,0376,0376,0007,0162,0346,0350,0215,0000,0211,0007,0376,0302,0204,
+0322,0174,0023,0315,0021,0321,0340,0321,0340,0200,0344,0003,0070,0342,0167,0355,
+0350,0011,0000,0162,0350,0303,0350,0003,0000,0162,0146,0303,0211,0356,0214,0134,
+0010,0214,0134,0012,0277,0003,0000,0122,0006,0127,0264,0010,0315,0023,0137,0007,
+0200,0341,0077,0376,0306,0210,0310,0366,0346,0211,0303,0213,0104,0010,0213,0124,
+0012,0367,0363,0222,0210,0325,0366,0361,0060,0322,0321,0352,0321,0352,0010,0342,
+0210,0321,0376,0301,0132,0210,0306,0273,0000,0174,0270,0001,0002,0315,0023,0163,
+0020,0200,0374,0200,0164,0011,0117,0174,0006,0060,0344,0315,0023,0163,0270,0371,
+0303,0201,0076,0376,0175,0125,0252,0165,0001,0303,0350,0013,0000,0243,0007,0353,
+0005,0350,0004,0000,0227,0007,0353,0376,0136,0255,0126,0211,0306,0254,0204,0300,
+0164,0011,0264,0016,0273,0001,0000,0315,0020,0353,0362,0303,0057,0144,0145,0166,
+0057,0150,0144,0077,0010,0000,0015,0012,0000,0116,0157,0156,0145,0040,0141,0143,
+0164,0151,0166,0145,0015,0012,0000,0122,0145,0141,0144,0040,0145,0162,0162,0157,
+0162,0040,0000,0116,0157,0164,0040,0142,0157,0157,0164,0141,0142,0154,0145,0040,
+0000,0000,
+};
+
+int dirty= 0;
+unsigned char bootblock[SECTOR_SIZE];
+struct part_entry table[1 + NR_PARTITIONS];
+int existing[1 + NR_PARTITIONS];
+unsigned long offset= 0, extbase= 0, extsize;
+int submerged= 0;
+char sort_index[1 + NR_PARTITIONS], sort_order[1 + NR_PARTITIONS];
+unsigned cylinders= 1, heads= 1, sectors= 1, secpcyl= 1;
+unsigned alt_cyls= 1, alt_heads= 1, alt_secs= 1;
+int precise= 0;
+int device= -1;
+
+unsigned long sortbase(struct part_entry *pe)
+{
+	return pe->sysind == NO_PART ? -1 : pe->lowsec;
+}
+
+void sort(void)
+/* Let the sort_index array show the order partitions are sorted in. */
+{
+	int i, j;
+
+	for (i= 1; i <= NR_PARTITIONS; i++) sort_order[i]= i;
+
+	for (i= 1; i <= NR_PARTITIONS; i++) {
+		for (j= 1; j <= NR_PARTITIONS-1; j++) {
+			int sj= sort_order[j], sj1= sort_order[j+1];
+
+			if (sortbase(&table[sj]) > sortbase(&table[sj1])) {
+				sort_order[j]= sj1;
+				sort_order[j+1]= sj;
+			}
+		}
+	}
+	for (i= 1; i <= NR_PARTITIONS; i++) sort_index[sort_order[i]]= i;
+}
+
+void dos2chs(unsigned char *dos, unsigned *chs)
+/* Extract cylinder, head and sector from the three bytes DOS uses to address
+ * a sector.  Note that bits 8 & 9 of the cylinder number come from bit 6 & 7
+ * of the sector byte.  The sector number is rebased to count from 0.
+ */
+{
+	chs[0]= ((dos[1] & 0xC0) << 2) | dos[2];
+	chs[1]= dos[0];
+	chs[2]= (dos[1] & 0x3F) - 1;
+}
+
+void abs2dos(unsigned char *dos, unsigned long pos)
+/* Translate a sector offset to three DOS bytes. */
+{
+	unsigned h, c, s;
+
+	c= pos / secpcyl;
+	h= (pos % secpcyl) / sectors;
+	s= pos % sectors + 1;
+
+	dos[0]= h;
+	dos[1]= s | ((c >> 2) & 0xC0);
+	dos[2]= c & 0xFF;
+}
+
+void recompute0(void)
+/* Recompute the partition size for the device after a geometry change. */
+{
+	if (device < 0) {
+		cylinders= heads= sectors= 1;
+		memset(table, 0, sizeof(table));
+	} else
+	if (!precise && offset == 0) {
+		table[0].lowsec= 0;
+		table[0].size= (unsigned long) cylinders * heads * sectors;
+	}
+	table[0].sysind= device < 0 ? NO_PART : MINIX_PART;
+	secpcyl= heads * sectors;
+}
+
+void guess_geometry(void)
+/* With a bit of work one can deduce the disk geometry from the partition
+ * table.  This may be necessary if the driver gets it wrong.  (If partition
+ * tables didn't have C/H/S numbers we would not care at all...)
+ */
+{
+	int i, n;
+	struct part_entry *pe;
+	unsigned chs[3];
+	unsigned long sec;
+	unsigned h, s;
+	unsigned char HS[256][8];	/* Bit map off all possible H/S */
+
+	alt_cyls= alt_heads= alt_secs= 0;
+
+	/* Initially all possible H/S combinations are possible.  HS[h][0]
+	 * bit 0 is used to rule out a head value.
+	 */
+	for (h= 1; h <= 255; h++) {
+		for (s= 0; s < 8; s++) HS[h][s]= 0xFF;
+	}
+
+	for (i= 0; i < 2*NR_PARTITIONS; i++) {
+		pe= &(table+1)[i >> 1];
+		if (pe->sysind == NO_PART) continue;
+
+		/* Get the end or start sector numbers (in that order). */
+		if ((i & 1) == 0) {
+			dos2chs(&pe->last_head, chs);
+			sec= pe->lowsec + pe->size - 1;
+		} else {
+			dos2chs(&pe->start_head, chs);
+			sec= pe->lowsec;
+		}
+
+		if (chs[0] >= alt_cyls) alt_cyls= chs[0]+1;
+
+		/* Which H/S combinations can be ruled out? */
+		for (h= 1; h <= 255; h++) {
+			if (HS[h][0] == 0) continue;
+			n = 0;
+			for (s= 1; s <= 63; s++) {
+				if ((chs[0] * h + chs[1]) * s + chs[2] != sec) {
+					HS[h][s/8] &= ~(1 << (s%8));
+				}
+				if (HS[h][s/8] & (1 << (s%8))) n++;
+			}
+			if (n == 0) HS[h][0]= 0;
+		}
+	}
+
+	/* See if only one remains. */
+	i= 0;
+	for (h= 1; h <= 255; h++) {
+		if (HS[h][0] == 0) continue;
+		for (s= 1; s <= 63; s++) {
+			if (HS[h][s/8] & (1 << (s%8))) {
+				i++;
+				alt_heads= h;
+				alt_secs= s;
+			}
+		}
+	}
+
+	/* Forget it if more than one choice... */
+	if (i > 1) alt_cyls= alt_heads= alt_secs= 0;
+}
+
+void geometry(void)
+/* Find out the geometry of the device by querying the driver, or by looking
+ * at the partition table.  These numbers are crosschecked to make sure that
+ * the geometry is correct.  Master bootstraps other than the Minix one use
+ * the CHS numbers in the partition table to load the bootstrap of the active
+ * partition.
+ */
+{
+	struct stat dst;
+	int err= 0;
+	struct partition geometry;
+
+	if (submerged) {
+		/* Geometry already known. */
+		sort();
+		return;
+	}
+	precise= 0;
+	cylinders= 0;
+	recompute0();
+	if (device < 0) return;
+
+	/* Try to guess the geometry from the partition table. */
+	guess_geometry();
+
+	/* Try to get the geometry from the driver. */
+	(void) fstat(device, &dst);
+
+	if (S_ISBLK(dst.st_mode) || S_ISCHR(dst.st_mode)) {
+		/* Try to get the drive's geometry from the driver. */
+
+		if (ioctl(device, DIOCGETP, &geometry) < 0)
+			err= errno;
+		else {
+			table[0].lowsec= div64u(geometry.base, SECTOR_SIZE);
+			table[0].size= div64u(geometry.size, SECTOR_SIZE);
+			cylinders= geometry.cylinders;
+			heads= geometry.heads;
+			sectors= geometry.sectors;
+			precise= 1;
+		}
+	} else {
+		err= ENODEV;
+	}
+
+	if (err != 0) {
+		/* Getting the geometry from the driver failed, so use the
+		 * alternate geometry.
+		 */
+		if (alt_heads == 0) {
+			alt_cyls= table[0].size / (64 * 32);
+			alt_heads= 64;
+			alt_secs= 32;
+		}
+
+		cylinders= alt_cyls;
+		heads= alt_heads;
+		sectors= alt_secs;
+
+		stat_start(1);
+		printf("Failure to get the geometry of %s: %s", curdev->name,
+			errno == ENOTTY ? "No driver support" : strerror(err));
+		stat_end(5);
+		stat_start(0);
+		printf("The geometry has been guessed as %ux%ux%u",
+						cylinders, heads, sectors);
+		stat_end(5);
+	} else {
+		if (alt_heads == 0) {
+			alt_cyls= cylinders;
+			alt_heads= heads;
+			alt_secs= sectors;
+		}
+
+		if (heads != alt_heads || sectors != alt_secs) {
+printf(
+"The %ux%ux%u geometry obtained from the driver\n"
+"does not match the %ux%ux%u geometry implied by the partition\n"
+"table. Please use expert mode instead.\n");
+exit(1);
+		}
+	}
+
+	/* Show the base and size of the device instead of the whole drive.
+	 * This makes sense for subpartitioning primary partitions.
+	 */
+	if (precise && ioctl(device, DIOCGETP, &geometry) >= 0) {
+		table[0].lowsec= div64u(geometry.base, SECTOR_SIZE);
+		table[0].size= div64u(geometry.size, SECTOR_SIZE);
+	} else {
+		precise= 0;
+	}
+	recompute0();
+	sort();
+}
+
+typedef struct indicators {	/* Partition type to partition name. */
+	unsigned char	ind;
+	char		name[10];
+} indicators_t;
+
+indicators_t ind_table[]= {
+	{ 0x00,		"None"		},
+	{ 0x01,		"FAT-12"	},
+	{ 0x02,		"XENIX /"	},
+	{ 0x03,		"XENIX usr"	},
+	{ 0x04,		"FAT-16"	},
+	{ 0x05,		"EXTENDED"	},
+	{ 0x06,		"FAT-16"	},
+	{ 0x07,		"HPFS/NTFS"	},
+	{ 0x08,		"AIX"		},
+	{ 0x09,		"COHERENT"	},
+	{ 0x0A,		"OS/2"		},
+	{ 0x0B,		"FAT-32"	},
+	{ 0x0C,		"FAT?"		},
+	{ 0x0E,		"FAT?"		},
+	{ 0x0F,		"EXTENDED"	},
+	{ 0x10,		"OPUS"		},
+	{ 0x40,		"VENIX286"	},
+	{ 0x42,		"W2000 Dyn"	},
+	{ 0x52,		"MICROPORT"	},
+	{ 0x63,		"386/IX"	},
+	{ 0x64,		"NOVELL286"	},
+	{ 0x65,		"NOVELL386"	},
+	{ 0x75,		"PC/IX"		},
+	{ 0x80,		"MINIX-OLD"	},
+	{ 0x81,		"MINIX"		},
+	{ 0x82,		"LINUXswap"	},
+	{ 0x83,		"LINUX"		},
+	{ 0x93,		"AMOEBA"	},
+	{ 0x94,		"AMOEBAbad"	},
+	{ 0xA5,		"386BSD"	},
+	{ 0xB7,		"BSDI"		},
+	{ 0xB8,		"BSDI swap"	},
+	{ 0xC7,		"SYRINX"	},
+	{ 0xDB,		"CPM"		},
+	{ 0xFF,		"BADBLOCKS"	},
+};
+
+char *typ2txt(int ind)
+/* Translate a numeric partition indicator for human eyes. */
+{
+	indicators_t *pind;
+
+	for (pind= ind_table; pind < arraylimit(ind_table); pind++) {
+		if (pind->ind == ind) return pind->name;
+	}
+	return "unknown system";
+}
+
+int round_sysind(int ind, int delta)
+/* Find the next known partition type starting with ind in direction delta. */
+{
+	indicators_t *pind;
+
+	ind= (ind + delta) & 0xFF;
+
+	if (delta < 0) {
+		for (pind= arraylimit(ind_table)-1; pind->ind > ind; pind--) {}
+	} else {
+		for (pind= ind_table; pind->ind < ind; pind++) {}
+	}
+	return pind->ind;
+}
+
+/* Objects on the screen, either simple pieces of the text or the cylinder
+ * number of the start of partition three.
+ */
+typedef enum objtype {
+	O_INFO, O_TEXT, O_DEV, O_SUB,
+	O_TYPTXT, O_SORT, O_NUM, O_TYPHEX,
+	O_CYL, O_HEAD, O_SEC,
+	O_SCYL, O_SHEAD, O_SSEC, O_LCYL, O_LHEAD, O_LSEC, O_BASE, O_SIZE, O_KB
+} objtype_t;
+
+#define rjust(type)	((type) >= O_TYPHEX)
+#define computed(type)	((type) >= O_TYPTXT)
+
+typedef struct object {
+	struct object	*next;
+	objtype_t	type;		/* Text field, cylinder number, etc. */
+	char		flags;		/* Modifiable? */
+	char		row;
+	char		col;
+	char		len;
+	struct part_entry *entry;	/* What does the object refer to? */
+	char		  *text;
+	char		value[20];	/* Value when printed. */
+} object_t;
+
+#define OF_MOD		0x01	/* Object value is modifiable. */
+#define OF_ODD		0x02	/* It has a somewhat odd value. */
+#define OF_BAD		0x04	/* Its value is no good at all. */
+
+/* Events: (Keypress events are the value of the key pressed.) */
+#define E_ENTER		(-1)	/* Cursor moves onto object. */
+#define E_LEAVE		(-2)	/* Cursor leaves object. */
+#define E_WRITE		(-3)	/* Write, but not by typing 'w'. */
+
+/* The O_SIZE objects have a dual identity. */
+enum howend { SIZE, LAST } howend= SIZE;
+
+object_t *world= nil;
+object_t *curobj= nil;
+
+object_t *newobject(objtype_t type, int flags, int row, int col, int len)
+/* Make a new object given a type, flags, position and length on the screen. */
+{
+	object_t *new;
+	object_t **aop= &world;
+
+	new= alloc(sizeof(*new));
+
+	new->type= type;
+	new->flags= flags;
+	new->row= row;
+	new->col= col;
+	new->len= len;
+	new->entry= nil;
+	new->text= "";
+	new->value[0]= 0;
+
+	new->next= *aop;
+	*aop= new;
+
+	return new;
+}
+
+unsigned long entry2base(struct part_entry *pe)
+/* Return the base sector of the partition if defined. */
+{
+	return pe->sysind == NO_PART ? 0 : pe->lowsec;
+}
+
+unsigned long entry2last(struct part_entry *pe)
+{
+	return pe->sysind == NO_PART ? -1 : pe->lowsec + pe->size - 1;
+}
+
+unsigned long entry2size(struct part_entry *pe)
+{
+	return pe->sysind == NO_PART ? 0 : pe->size;
+}
+
+int overlap(unsigned long sec)
+/* See if sec is part of another partition. */
+{
+	struct part_entry *pe;
+
+	for (pe= table + 1; pe <= table + NR_PARTITIONS; pe++) {
+		if (pe->sysind == NO_PART) continue;
+
+		if (pe->lowsec < sec && sec < pe->lowsec + pe->size)
+			return 1;
+	}
+	return 0;
+}
+
+int aligned(unsigned long sec, unsigned unit)
+/* True if sec is aligned to unit or if it is no problem if it is unaligned. */
+{
+	return (offset != 0 && extbase == 0) || (sec % unit == 0);
+}
+
+void print(object_t *op)
+/* Print an object's value if it changed. */
+{
+	struct part_entry *pe= op->entry;
+	int n;
+	unsigned long t;
+	char *name;
+	int oldflags;
+	char oldvalue[20];
+
+	/* Remember the old flags and value. */
+	oldflags= op->flags;
+	strcpy(oldvalue, op->value);
+
+	op->flags&= ~(OF_ODD | OF_BAD);
+
+	switch (op->type) {
+	case O_INFO:		{
+				/* Current field. */
+		static struct field { int type; char *name; } fields[]= {
+			{ O_DEV,	"Select device"		},
+			{ O_NUM,	"Active flag"		},
+			{ O_TYPHEX,	"Hex partition type"	},
+			{ O_TYPTXT,	"Partition type"	},
+			{ O_SCYL,	"Start cylinder"	},
+			{ O_SHEAD,	"Start head"		},
+			{ O_SSEC,	"Start sector"		},
+			{ O_CYL,	"Number of cylinders"	},
+			{ O_HEAD,	"Number of heads"	},
+			{ O_SEC,	"Sectors per track"	},
+			{ O_LCYL,	"Last cylinder"		},
+			{ O_LHEAD,	"Last head"		},
+			{ O_LSEC,	"Last sector"		},
+			{ O_BASE,	"Base sector"		},
+			{ O_SIZE,	"Size in sectors"	},
+			{ O_KB,		"Size in kilobytes"	},
+			{ -1,		"?"			},
+		};
+		struct field *fp= fields;
+
+		while (fp->type >= 0 && fp->type != curobj->type) fp++;
+		strcpy(op->value, fp->name);
+		op->flags|= OF_ODD;
+		break;		}
+	case O_TEXT:
+				/* Simple text field. */
+		strcpy(op->value, op->text);
+		break;
+	case O_DEV:
+	case O_SUB:
+				/* Name of currently edited device. */
+		name= op->type == O_DEV ? curdev->name :
+					offset == 0 ? "" : curdev->subname;
+		if ((n= strlen(name)) < op->len) n= op->len;
+		strcpy(op->value, name + (n - op->len));
+		if (device < 0 && op->type == O_DEV) op->flags|= OF_BAD;
+		break;
+	case O_NUM:
+				/* Position and active flag. */
+		sprintf(op->value, "%d%c", (int) (pe - table - 1),
+					pe->bootind & ACTIVE_FLAG ? '*' : ' ');
+		break;
+	case O_SORT:
+				/* Position if the driver sorts the table. */
+		sprintf(op->value, "%s%d",
+			curdev->parttype >= PRIMARY ? "p" :
+				curdev->parttype == SUBPART ? "s" : "",
+			(curdev->parttype == SUBPART ||
+				curdev->parttype == FLOPPY ? pe - table
+					: sort_index[pe - table]) - 1);
+		break;
+	case O_TYPHEX:
+				/* Hex partition type indicator. */
+		sprintf(op->value, "%02X", pe->sysind);
+		break;
+	case O_TYPTXT:
+				/* Ascii partition type indicator. */
+		strcpy(op->value, typ2txt(pe->sysind));
+		break;
+	case O_SCYL:
+				/* Partition's start cylinder. */
+		sprintf(op->value, "%lu", entry2base(pe) / secpcyl);
+		break;
+	case O_SHEAD:
+				/* Start head. */
+		t= entry2base(pe);
+		sprintf(op->value, "%lu", t % secpcyl / sectors);
+		if (!aligned(t, secpcyl) && t != table[0].lowsec + sectors)
+			op->flags|= OF_ODD;
+		break;
+	case O_SSEC:
+				/* Start sector. */
+		t= entry2base(pe);
+		sprintf(op->value, "%lu", t % sectors);
+		if (!aligned(t, sectors)) op->flags|= OF_ODD;
+		break;
+	case O_CYL:
+				/* Number of cylinders. */
+		sprintf(op->value, "%u", cylinders);
+		break;
+	case O_HEAD:
+				/* Number of heads. */
+		sprintf(op->value, "%u", heads);
+		break;
+	case O_SEC:
+				/* Number of sectors per track. */
+		sprintf(op->value, "%u", sectors);
+		break;
+	case O_LCYL:
+				/* Partition's last cylinder. */
+		t= entry2last(pe);
+		sprintf(op->value, "%lu", t == -1 ? 0 : t / secpcyl);
+		break;
+	case O_LHEAD:
+				/* Partition's last head. */
+		t= entry2last(pe);
+		sprintf(op->value, "%lu", t == -1 ? 0 : t % secpcyl / sectors);
+		if (!aligned(t + 1, secpcyl)) op->flags|= OF_ODD;
+		break;
+	case O_LSEC:
+				/* Partition's last sector. */
+		t= entry2last(pe);
+		sprintf(op->value, t == -1 ? "-1" : "%lu", t % sectors);
+		if (!aligned(t + 1, sectors)) op->flags|= OF_ODD;
+		break;
+	case O_BASE:
+				/* Partition's base sector. */
+		sprintf(op->value, "%lu", entry2base(pe));
+		if (pe->sysind != NO_PART && pe != &table[0]
+		   && (pe->lowsec <= table[0].lowsec || overlap(pe->lowsec)))
+			op->flags|= OF_BAD;
+		break;
+	case O_SIZE:
+				/* Size of partitition in sectors. */
+		t= howend == SIZE ? entry2size(pe) : entry2last(pe);
+		sprintf(op->value, "%lu", pe->sysind == NO_PART ? 0 : t);
+		if (pe->sysind != NO_PART && (pe->size == 0
+		    || pe->lowsec + pe->size > table[0].lowsec + table[0].size
+		    || overlap(pe->lowsec + pe->size)))
+			op->flags|= OF_BAD;
+		break;
+	case O_KB:
+				/* Size of partitition in kilobytes. */
+		sprintf(op->value, "%lu", entry2size(pe) / 2);
+		break;
+	default:
+		sprintf(op->value, "?? %d ??", op->type);
+	}
+
+	if (device < 0 && computed(op->type)) strcpy(op->value, "?");
+
+	/* If a value overflows the print field then show a blank
+	 * reverse video field.
+	 */
+	if ((n= strlen(op->value)) > op->len) {
+		n= 0;
+		op->flags|= OF_BAD;
+	}
+
+	/* Right or left justified? */
+	if (rjust(op->type)) {
+		memmove(op->value + (op->len - n), op->value, n);
+		memset(op->value, ' ', op->len - n);
+	} else {
+		memset(op->value + n, ' ', op->len - n);
+	}
+	op->value[op->len]= 0;
+
+	if ((op->flags & (OF_ODD | OF_BAD)) == (oldflags & (OF_ODD | OF_BAD))
+				&& strcmp(op->value, oldvalue) == 0) {
+		/* The value did not change. */
+		return;
+	}
+
+	set_cursor(op->row, rjust(op->type) ? op->col - (op->len-1) : op->col);
+
+	if (op->flags & OF_BAD) tputs(t_so, 1, putchr);
+	else
+	if (op->flags & OF_ODD) tputs(t_md, 1, putchr);
+	putstr(op->value);
+	if (op->flags & OF_BAD) tputs(t_se, 1, putchr);
+	else
+	if (op->flags & OF_ODD) tputs(t_me, 1, putchr);
+}
+
+void display(void)
+/* Repaint all objects that changed. */
+{
+	object_t *op;
+
+	for (op= world; op != nil; op= op->next) print(op);
+}
+
+int typing;	/* Set if a digit has been typed to set a value. */
+int magic;	/* Changes when using the magic key. */
+
+void event(int ev, object_t *op);
+
+void m_redraw(int ev, object_t *op)
+/* Redraw the screen. */
+{
+	object_t *op2;
+
+	if (ev != ctrl('L')) return;
+
+	clear_screen();
+	for (op2= world; op2 != nil; op2= op2->next) op2->value[0]= 0;
+}
+
+void m_toggle(int ev, object_t *op)
+/* Toggle between the driver and alternate geometry. */
+{
+	unsigned t;
+
+	if (ev != 'X') return;
+	if (alt_cyls == cylinders && alt_heads == heads && alt_secs == sectors)
+		return;
+
+	t= cylinders; cylinders= alt_cyls; alt_cyls= t;
+	t= heads; heads= alt_heads; alt_heads= t;
+	t= sectors; sectors= alt_secs; alt_secs= t;
+	dirty= 1;
+	recompute0();
+}
+
+char size_last[]= "Size";
+
+void m_orientation(int ev, object_t *op)
+{
+	if (ev != ' ') return;
+
+	switch (howend) {
+	case SIZE:
+		howend= LAST;
+		strcpy(size_last, "Last");
+		break;
+	case LAST:
+		howend= SIZE;
+		strcpy(size_last, "Size");
+	}
+}
+
+void m_move(int ev, object_t *op)
+/* Move to the nearest modifiably object in the intended direction.  Objects
+ * on the same row or column are really near.
+ */
+{
+	object_t *near, *op2;
+	unsigned dist, d2, dr, dc;
+
+	if (ev != 'h' && ev != 'j' && ev != 'k' && ev != 'l' && ev != 'H')
+		return;
+
+	if (device < 0) {
+		/* No device open?  Then try to read first. */
+		event('r', op);
+		if (device < 0) return;
+	}
+
+	near= op;
+	dist= -1;
+
+	for (op2= world; op2 != nil; op2= op2->next) {
+		if (op2 == op || !(op2->flags & OF_MOD)) continue;
+
+		dr= abs(op2->row - op->row);
+		dc= abs(op2->col - op->col);
+
+		d2= 25*dr*dr + dc*dc;
+		if (op2->row != op->row && op2->col != op->col) d2+= 1000;
+
+		switch (ev) {
+		case 'h':	/* Left */
+			if (op2->col >= op->col) d2= -1;
+			break;
+		case 'j':	/* Down */
+			if (op2->row <= op->row) d2= -1;
+			break;
+		case 'k':	/* Up */
+			if (op2->row >= op->row) d2= -1;
+			break;
+		case 'l':	/* Right */
+			if (op2->col <= op->col) d2= -1;
+			break;
+		case 'H':	/* Home */
+			if (op2->type == O_DEV) d2= 0;
+		}
+		if (d2 < dist) { near= op2; dist= d2; }
+	}
+	if (near != op) event(E_LEAVE, op);
+	event(E_ENTER, near);
+}
+
+void m_updown(int ev, object_t *op)
+/* Move a partition table entry up or down. */
+{
+	int i, j;
+	struct part_entry tmp;
+	int tmpx;
+
+	if (ev != ctrl('K') && ev != ctrl('J')) return;
+	if (op->entry == nil) return;
+
+	i= op->entry - table;
+	if (ev == ctrl('K')) {
+		if (i <= 1) return;
+		j= i-1;
+	} else {
+		if (i >= NR_PARTITIONS) return;
+		j= i+1;
+	}
+
+	tmp= table[i]; table[i]= table[j]; table[j]= tmp;
+	tmpx= existing[i]; existing[i]= existing[j]; existing[j]= tmpx;
+	sort();
+	dirty= 1;
+	event(ev == ctrl('K') ? 'k' : 'j', op);
+}
+
+void m_enter(int ev, object_t *op)
+/* We've moved onto this object. */
+{
+	if (ev != E_ENTER && ev != ' ' && ev != '<' && ev != '>' && ev != 'X')
+		return;
+	curobj= op;
+	typing= 0;
+	magic= 0;
+}
+
+void m_leave(int ev, object_t *op)
+/* About to leave this object. */
+{
+	if (ev != E_LEAVE) return;
+}
+
+int within(unsigned *var, unsigned low, unsigned value, unsigned high)
+/* Only set *var to value if it looks reasonable. */
+{
+	if (low <= value && value <= high) {
+		*var= value;
+		return 1;
+	} else
+		return 0;
+}
+
+int lwithin(unsigned long *var, unsigned long low, unsigned long value,
+							unsigned long high)
+{
+	if (low <= value && value <= high) {
+		*var= value;
+		return 1;
+	} else
+		return 0;
+}
+
+int nextdevice(object_t *op, int delta)
+/* Select the next or previous device from the device list. */
+{
+	dev_t rdev;
+
+	if (offset != 0) return 0;
+	if (dirty) event(E_WRITE, op);
+	if (dirty) return 0;
+
+	if (device >= 0) {
+		(void) close(device);
+		device= -1;
+	}
+	recompute0();
+
+	rdev= curdev->rdev;
+	if (delta < 0) {
+		do
+			curdev= curdev->prev;
+		while (delta < -1 && major(curdev->rdev) == major(rdev)
+			&& curdev->rdev < rdev);
+	} else {
+		do
+			curdev= curdev->next;
+		while (delta > 1 && major(curdev->rdev) == major(rdev)
+			&& curdev->rdev > rdev);
+	}
+	return 1;
+}
+
+void check_ind(struct part_entry *pe)
+/* If there are no other partitions then make this new one active. */
+{
+	struct part_entry *pe2;
+	int i = 0;
+
+	for (pe2= table + 1; pe2 < table + 1 + NR_PARTITIONS; pe2++, i++)
+		if (pe2->sysind != NO_PART && (pe2->bootind & ACTIVE_FLAG))
+			return;
+
+	pe->bootind= ACTIVE_FLAG;
+	dirty = 1;
+}
+
+int check_existing(struct part_entry *pe)
+/* Check and if not ask if an existing partition may be modified. */
+{
+	static int expert= 0;
+	int c;
+
+	if (expert || pe == nil || !existing[pe - table]) return 1;
+
+	stat_start(1);
+	putstr("Do you wish to modify existing partitions? (y/n) ");
+	fflush(stdout);
+	while ((c= getchar()) != 'y' && c != 'n') {}
+	putchr(c);
+	stat_end(3);
+	return (expert= (c == 'y'));
+}
+
+void m_modify(int ev, object_t *op)
+/* Increment, decrement, set, or toggle the value of an object, using
+ * arithmetic tricks the author doesn't understand either.
+ */
+{
+	object_t *op2;
+	struct part_entry *pe= op->entry;
+	int mul, delta;
+	unsigned level= 1;
+	unsigned long surplus;
+	int radix= op->type == O_TYPHEX ? 0x10 : 10;
+	unsigned long t;
+
+	if (device < 0 && op->type != O_DEV) return;
+
+	switch (ev) {
+	case '-':
+		mul= radix; delta= -1; typing= 0;
+		break;
+	case '+':
+		mul= radix; delta= 1; typing= 0;
+		break;
+	case '\b':
+		if (!typing) return;
+		mul= 1; delta= 0;
+		break;
+	case '\r':
+		typing= 0;
+		return;
+	default:
+		if ('0' <= ev && ev <= '9')
+			delta= ev - '0';
+		else
+		if (radix == 0x10 && 'a' <= ev && ev <= 'f')
+			delta= ev - 'a' + 10;
+		else
+		if (radix == 0x10 && 'A' <= ev && ev <= 'F')
+			delta= ev - 'A' + 10;
+		else
+			return;
+
+		mul= typing ? radix*radix : 0;
+		typing= 1;
+	}
+	magic= 0;
+
+	if (!check_existing(pe)) return;
+
+	switch (op->type) {
+	case O_DEV:
+		if (ev != '-' && ev != '+') return;
+		if (!nextdevice(op, delta)) return;
+		break;
+	case O_CYL:
+		if (!within(&cylinders, 1,
+			cylinders * mul / radix + delta, 1024)) return;
+		recompute0();
+		break;
+	case O_HEAD:
+		if (!within(&heads, 1, heads * mul / radix + delta, 255))
+			return;
+		recompute0();
+		break;
+	case O_SEC:
+		if (!within(&sectors, 1, sectors * mul / radix + delta, 63))
+			return;
+		recompute0();
+		break;
+	case O_NUM:
+		if (ev != '-' && ev != '+') return;
+		for (op2= world; op2 != nil; op2= op2->next) {
+			if (op2->type == O_NUM && ev == '+')
+				op2->entry->bootind= 0;
+		}
+		op->entry->bootind= ev == '+' ? ACTIVE_FLAG : 0;
+		break;
+	case O_TYPHEX:
+		check_ind(pe);
+		pe->sysind= pe->sysind * mul / radix + delta;
+		break;
+	case O_TYPTXT:
+		if (ev != '-' && ev != '+') return;
+		check_ind(pe);
+		pe->sysind= round_sysind(pe->sysind, delta);
+		break;
+	case O_SCYL:
+		level= heads;
+	case O_SHEAD:
+		level*= sectors;
+	case O_SSEC:
+		if (op->type != O_SCYL && ev != '-' && ev != '+') return;
+	case O_BASE:
+		if (pe->sysind == NO_PART) memset(pe, 0, sizeof(*pe));
+		t= pe->lowsec;
+		surplus= t % level;
+		if (!lwithin(&t, 0L,
+			(t / level * mul / radix + delta) * level + surplus,
+			MAXSIZE)) return;
+		if (howend == LAST || op->type != O_BASE)
+			pe->size-= t - pe->lowsec;
+		pe->lowsec= t;
+		check_ind(pe);
+		if (pe->sysind == NO_PART) pe->sysind= MINIX_PART;
+		break;
+	case O_LCYL:
+		level= heads;
+	case O_LHEAD:
+		level*= sectors;
+	case O_LSEC:
+		if (op->type != O_LCYL && ev != '-' && ev != '+') return;
+
+		if (pe->sysind == NO_PART) memset(pe, 0, sizeof(*pe));
+		t= pe->lowsec + pe->size - 1 + level;
+		surplus= t % level - mul / radix * level;
+		if (!lwithin(&t, 0L,
+			(t / level * mul / radix + delta) * level + surplus,
+			MAXSIZE)) return;
+		pe->size= t - pe->lowsec + 1;
+		check_ind(pe);
+		if (pe->sysind == NO_PART) pe->sysind= MINIX_PART;
+		break;
+	case O_KB:
+		level= 2;
+		if (mul == 0) pe->size= 0;	/* new value, no surplus */
+	case O_SIZE:
+		if (pe->sysind == NO_PART) {
+			if (op->type == O_KB || howend == SIZE) {
+				/* First let loose magic to set the base. */
+				event('m', op);
+				magic= 0;
+				pe->size= 0;
+				event(ev, op);
+				return;
+			}
+			memset(pe, 0, sizeof(*pe));
+		}
+		t= (op->type == O_KB || howend == SIZE) ? pe->size
+						: pe->lowsec + pe->size - 1;
+		surplus= t % level;
+		if (!lwithin(&t, 0L,
+			(t / level * mul / radix + delta) * level + surplus,
+			MAXSIZE)) return;
+		pe->size= (op->type == O_KB || howend == SIZE) ? t :
+							t - pe->lowsec + 1;
+		check_ind(pe);
+		if (pe->sysind == NO_PART) pe->sysind= MINIX_PART;
+		break;
+	default:
+		return;
+	}
+
+	/* The order among the entries may have changed. */
+	sort();
+	dirty= 1;
+}
+
+unsigned long spell[3 + 4 * (1+NR_PARTITIONS)];
+int nspells;
+objtype_t touching;
+
+void newspell(unsigned long charm)
+/* Add a new spell, descending order for the base, ascending for the size. */
+{
+	int i, j;
+
+	if (charm - table[0].lowsec > table[0].size) return;
+
+	for (i= 0; i < nspells; i++) {
+		if (charm == spell[i]) return;	/* duplicate */
+
+		if (touching == O_BASE) {
+			if (charm == table[0].lowsec + table[0].size) return;
+			if ((spell[0] - charm) < (spell[0] - spell[i])) break;
+		} else {
+			if (charm == table[0].lowsec) return;
+			if ((charm - spell[0]) < (spell[i] - spell[0])) break;
+		}
+	}
+	for (j= ++nspells; j > i; j--) spell[j]= spell[j-1];
+	spell[i]= charm;
+}
+
+void m_magic(int ev, object_t *op)
+/* Apply magic onto a base or size number. */
+{
+	struct part_entry *pe= op->entry, *pe2;
+	int rough= (offset != 0 && extbase == 0);
+
+	if (ev != 'm' || device < 0) return;
+	typing= 0;
+
+	if (!check_existing(pe)) return;
+
+	if (magic == 0) {
+		/* See what magic we can let loose on this value. */
+		nspells= 1;
+
+		/* First spell, the current value. */
+		switch (op->type) {
+		case O_SCYL:
+		case O_SHEAD:	/* Start of partition. */
+		case O_SSEC:
+		case O_BASE:
+			touching= O_BASE;
+			spell[0]= pe->lowsec;
+			break;
+		case O_LCYL:
+		case O_LHEAD:
+		case O_LSEC:	/* End of partition. */
+		case O_KB:
+		case O_SIZE:
+			touching= O_SIZE;
+			spell[0]= pe->lowsec + pe->size;
+			break;
+		default:
+			return;
+		}
+		if (pe->sysind == NO_PART) {
+			memset(pe, 0, sizeof(*pe));
+			check_ind(pe);
+			pe->sysind= MINIX_PART;
+			spell[0]= 0;
+			if (touching == O_SIZE) {
+				/* First let loose magic on the base. */
+				object_t *op2;
+
+				for (op2= world; op2 != nil; op2= op2->next) {
+					if (op2->row == op->row &&
+							op2->type == O_BASE) {
+						event('m', op2);
+					}
+				}
+				magic= 0;
+				event('m', op);
+				return;
+			}
+		}
+		/* Avoid the first sector on the device. */
+		if (spell[0] == table[0].lowsec) newspell(spell[0] + 1);
+
+		/* Further interesting values are the the bases of other
+		 * partitions or their ends.
+		 */
+		for (pe2= table; pe2 < table + 1 + NR_PARTITIONS; pe2++) {
+			if (pe2 == pe || pe2->sysind == NO_PART) continue;
+			if (pe2->lowsec == table[0].lowsec)
+				newspell(table[0].lowsec + 1);
+			else
+				newspell(pe2->lowsec);
+			newspell(pe2->lowsec + pe2->size);
+			if (touching == O_BASE && howend == SIZE) {
+				newspell(pe2->lowsec - pe->size);
+				newspell(pe2->lowsec + pe2->size - pe->size);
+			}
+			if (pe2->lowsec % sectors != 0) rough= 1;
+		}
+		/* Present values rounded up to the next cylinder unless
+		 * the table is already a mess.  Use "start + 1 track" instead
+		 * of "start + 1 cylinder".  Also add the end of the last
+		 * cylinder.
+		 */
+		if (!rough) {
+			unsigned long n= spell[0];
+			if (n == table[0].lowsec) n++;
+			n= (n + sectors - 1) / sectors * sectors;
+			if (n != table[0].lowsec + sectors)
+				n= (n + secpcyl - 1) / secpcyl * secpcyl;
+			newspell(n);
+			if (touching == O_SIZE)
+				newspell(table[0].size / secpcyl * secpcyl);
+		}
+	}
+	/* Magic has been applied, a spell needs to be chosen. */
+
+	if (++magic == nspells) magic= 0;
+
+	if (touching == O_BASE) {
+		if (howend == LAST) pe->size-= spell[magic] - pe->lowsec;
+		pe->lowsec= spell[magic];
+	} else
+		pe->size= spell[magic] - pe->lowsec;
+
+	/* The order among the entries may have changed. */
+	sort();
+	dirty= 1;
+}
+
+typedef struct diving {
+	struct diving	*up;
+	struct part_entry  old0;
+	char		*oldsubname;
+	parttype_t	oldparttype;
+	unsigned long	oldoffset;
+	unsigned long	oldextbase;
+} diving_t;
+
+diving_t *diving= nil;
+
+void m_in(int ev, object_t *op)
+/* Go down into a primary or extended partition. */
+{
+	diving_t *newdiv;
+	struct part_entry *pe= op->entry, ext;
+	int n;
+
+	if (ev != '>' || device < 0 || pe == nil || pe == &table[0]
+		|| (!(pe->sysind == MINIX_PART && offset == 0)
+					&& !ext_part(pe->sysind))
+		|| pe->size == 0) return;
+
+	ext= *pe;
+	if (extbase != 0) ext.size= extbase + extsize - ext.lowsec;
+
+	if (dirty) event(E_WRITE, op);
+	if (dirty) return;
+	if (device >= 0) { close(device); device= -1; }
+
+	newdiv= alloc(sizeof(*newdiv));
+	newdiv->old0= table[0];
+	newdiv->oldsubname= curdev->subname;
+	newdiv->oldparttype= curdev->parttype;
+	newdiv->oldoffset= offset;
+	newdiv->oldextbase= extbase;
+	newdiv->up= diving;
+	diving= newdiv;
+
+	table[0]= ext;
+
+	n= strlen(diving->oldsubname);
+	curdev->subname= alloc((n + 3) * sizeof(curdev->subname[0]));
+	strcpy(curdev->subname, diving->oldsubname);
+	curdev->subname[n++]= ':';
+	curdev->subname[n++]= '0' + (pe - table - 1);
+	curdev->subname[n]= 0;
+
+	curdev->parttype= curdev->parttype == PRIMARY ? SUBPART : DUNNO;
+	offset= ext.lowsec;
+	if (ext_part(ext.sysind) && extbase == 0) {
+		extbase= ext.lowsec;
+		extsize= ext.size;
+		curdev->parttype= DUNNO;
+	}
+
+	submerged= 1;
+	event('r', op);
+}
+
+void m_out(int ev, object_t *op)
+/* Go up from an extended or subpartition table to its enclosing. */
+{
+	diving_t *olddiv;
+
+	if (ev != '<' || diving == nil) return;
+
+	if (dirty) event(E_WRITE, op);
+	if (dirty) return;
+	if (device >= 0) { close(device); device= -1; }
+
+	olddiv= diving;
+	diving= olddiv->up;
+
+	table[0]= olddiv->old0;
+
+	free(curdev->subname);
+	curdev->subname= olddiv->oldsubname;
+
+	curdev->parttype= olddiv->oldparttype;
+	offset= olddiv->oldoffset;
+	extbase= olddiv->oldextbase;
+
+	free(olddiv);
+
+	event('r', op);
+	if (diving == nil) submerged= 0;	/* We surfaced. */
+}
+
+void installboot(unsigned char *bootblock, char *masterboot)
+/* Install code from a master bootstrap into a boot block. */
+{
+	FILE *mfp;
+	struct exec hdr;
+	int n;
+	char *err;
+
+	if ((mfp= fopen(masterboot, "r")) == nil) {
+		err= strerror(errno);
+		goto m_err;
+	}
+
+	n= fread(&hdr, sizeof(char), A_MINHDR, mfp);
+	if (ferror(mfp)) {
+		err= strerror(errno);
+		fclose(mfp);
+		goto m_err;
+	}
+
+	if (n < A_MINHDR || BADMAG(hdr) || hdr.a_cpu != A_I8086) {
+		err= "Not an 8086 executable";
+		fclose(mfp);
+		goto m_err;
+	}
+
+	if (hdr.a_text + hdr.a_data > PART_TABLE_OFF) {
+		err= "Does not fit in a boot sector";
+		fclose(mfp);
+		goto m_err;
+	}
+
+	fseek(mfp, hdr.a_hdrlen, 0);
+	fread(bootblock, sizeof(char), (size_t) (hdr.a_text + hdr.a_data), mfp);
+	if (ferror(mfp)) {
+		err= strerror(errno);
+		fclose(mfp);
+		goto m_err;
+	}
+	fclose(mfp);
+
+	/* Bootstrap installed. */
+	return;
+
+    m_err:
+	stat_start(1);
+	printf("%s: %s", masterboot, err);
+	stat_end(5);
+}
+
+ssize_t boot_readwrite(int rw)
+/* Read (0) or write (1) the boot sector. */
+{
+	u64_t off64 = mul64u(offset, SECTOR_SIZE);
+	int r;
+
+#if __minix_vmd
+	/* Minix-vmd has a 64 bit seek. */
+	if (fcntl(device, F_SEEK, off64) < 0) return -1;
+#else
+	/* Minix has to gross things with the partition base. */
+	struct partition geom0, geom_seek;
+
+	if (offset >= (LONG_MAX / SECTOR_SIZE - 1)) {
+		/* Move partition base. */
+		if (ioctl(device, DIOCGETP, &geom0) < 0) return -1;
+		geom_seek.base = add64(geom0.base, off64);
+		geom_seek.size = cvu64(cmp64(add64u(off64, SECTOR_SIZE),
+			geom0.size) <= 0 ? _STATIC_BLOCK_SIZE : 0);
+		sync();
+		if (ioctl(device, DIOCSETP, &geom_seek) < 0) return -1;
+		if (lseek(device, (off_t) 0, SEEK_SET) == -1) return -1;
+	} else {
+		/* Can reach this point normally. */
+		if (lseek(device, (off_t) offset * SECTOR_SIZE, SEEK_SET) == -1)
+			return -1;
+	}
+#endif
+
+	switch (rw) {
+	case 0:	r= read(device, bootblock, SECTOR_SIZE);	break;
+	case 1:	r= write(device, bootblock, SECTOR_SIZE);	break;
+	}
+
+#if !__minix_vmd
+	if (offset >= (LONG_MAX / SECTOR_SIZE - 1)) {
+		/* Restore partition base and size. */
+		sync();
+		if (ioctl(device, DIOCSETP, &geom0) < 0) return -1;
+	}
+#endif
+	return r;
+}
+
+int cylinderalign(region_t *reg)
+{
+	if(reg->is_used_part) {
+		if(reg->used_part.lowsec != table[0].lowsec + sectors
+			&& (reg->used_part.lowsec % secpcyl)) {
+			int extra;
+			extra = secpcyl - (reg->used_part.lowsec % secpcyl);
+			reg->used_part.lowsec += extra;
+			reg->used_part.size -= extra;
+		}
+		if((reg->used_part.size+1) % secpcyl) {
+			reg->used_part.size -= secpcyl - ((reg->used_part.size + 1) % secpcyl);
+		}
+		return reg->used_part.size > 0;
+	}
+
+	if(reg->free_sec_start != table[0].lowsec + sectors && (reg->free_sec_start % secpcyl)) {
+		/* Start is unaligned. Round up. */
+		reg->free_sec_start += secpcyl - (reg->free_sec_start % secpcyl);
+	}
+	if((reg->free_sec_last+1) % secpcyl) {
+		/* End is unaligned. Round down. */
+		reg->free_sec_last -= (reg->free_sec_last+1) % secpcyl;
+	}
+	
+	/* Return nonzero if anything remains of the region after rounding. */
+	return reg->free_sec_last > reg->free_sec_start;
+}
+
+void regionize(void)
+{
+	int free_sec, i, si;
+
+	sort();
+
+	free_sec = table[0].lowsec + sectors;
+
+	/* Create region data used in autopart mode. */
+	free_regions = used_regions = nr_regions = nr_partitions = 0;
+	if(table[0].lowsec > table[sort_order[1]].lowsec &&
+		table[sort_order[1]].sysind != NO_PART) {
+		printf("\nSanity check failed on %s - first partition starts before disk.\n"
+			"Please use expert mode to correct it.\n", curdev->name);
+		exit(1);
+	}
+	for(si = 1; si <= NR_PARTITIONS; si++) {
+		i = sort_order[si];
+		if(i < 1 || i > NR_PARTITIONS) {
+			printf("Sorry, something unexpected has happened (%d out of range).\n", i);
+			exit(1);
+		}
+
+		if(table[i].sysind == NO_PART)
+			break;
+
+		/* Free space before this partition? */
+		if(table[i].lowsec > free_sec) {
+			/* Free region before this partition. */
+			regions[nr_regions].free_sec_start = free_sec;
+			regions[nr_regions].free_sec_last = table[i].lowsec-1;
+			regions[nr_regions].is_used_part = 0;
+			if(cylinderalign(&regions[nr_regions])) {
+				nr_regions++;
+				free_regions++;
+			}
+		}
+
+		/* Sanity check. */
+		if(si > 1) {
+			if(table[i].lowsec < table[sort_order[si-1]].lowsec ||
+			   table[i].lowsec < table[sort_order[si-1]].lowsec + table[sort_order[si-1]].size) {
+				printf("\nSanity check failed on %s - partitions overlap.\n"
+					"Please use expert mode to correct it.\n", curdev->name);
+				exit(1);
+			}
+		}
+		if(table[i].size > table[0].size) {
+			printf("\nSanity check failed on %s - partition is larger than disk.\n"
+				"Please use expert mode to correct it.\n", curdev->name);
+			exit(1);
+		}
+		if(table[i].size < 1) {
+			printf("\nSanity check failed on %s - zero-sized partition.\n"
+				"Please use expert mode to correct it.\n", curdev->name);
+			exit(1);
+		} 
+
+		/* Remember used region. */
+		memcpy(&regions[nr_regions].used_part, &table[i], sizeof(table[i]));
+		free_sec = table[i].lowsec+table[i].size;
+		regions[nr_regions].is_used_part = 1;
+		regions[nr_regions].tableno = i;
+		nr_partitions++;
+		nr_regions++;
+		used_regions++;
+	}
+
+	/* Special case: space after partitions. */
+	if(free_sec <   table[0].lowsec + table[0].size-1) {
+		regions[nr_regions].free_sec_start = free_sec;
+		regions[nr_regions].free_sec_last = table[0].lowsec + table[0].size-1;
+		regions[nr_regions].is_used_part = 0;
+		if(cylinderalign(&regions[nr_regions])) {
+			nr_regions++;
+			free_regions++;
+		}
+	}
+
+}
+
+void m_read(int ev, int *biosdrive)
+/* Read the partition table from the current device. */
+{
+	int si, i, mode, n, r, v;
+	struct part_entry *pe;
+
+	if (ev != 'r' || device >= 0) return;
+
+	/* Open() may cause kernel messages: */
+	stat_start(0);
+	fflush(stdout);
+
+	if ((device= open(curdev->name, mode= O_RDWR, 0666)) < 0) {
+		if (device >= 0) { close(device); device= -1; }
+		return;
+	}
+
+	v = 2*HZ;
+	ioctl(device, DIOCTIMEOUT, &v);
+
+	memset(bootblock, 0, sizeof(bootblock));
+
+	n= boot_readwrite(0);
+
+	if (n <= 0) stat_start(1);
+	if (n < 0) {
+		close(device);
+		device= -1;
+	} else
+	if (n < SECTOR_SIZE) {
+		close(device);
+		device= -1;
+		return;
+	}
+	if (n <= 0) stat_end(5);
+
+	if (n < SECTOR_SIZE) n= SECTOR_SIZE;
+
+	if(biosdrive) (*biosdrive)++;
+
+	if(!open_ct_ok(device)) {
+		printf("\n%s: device in use! skipping it.", curdev->subname);
+		fflush(stdout);
+		close(device);
+		device= -1;
+		return;
+	}
+
+	memcpy(table+1, bootblock+PART_TABLE_OFF,
+					NR_PARTITIONS * sizeof(table[1]));
+	if (bootblock[510] != 0x55 || bootblock[511] != 0xAA) {
+		/* Invalid boot block, install bootstrap, wipe partition table.
+		 */
+		memset(bootblock, 0, sizeof(bootblock));
+		installboot(bootblock, MASTERBOOT);
+		memset(table+1, 0, NR_PARTITIONS * sizeof(table[1]));
+	}
+
+	/* Fix an extended partition table up to something mere mortals can
+	 * understand.  Record already defined partitions.
+	 */
+	for (i= 1; i <= NR_PARTITIONS; i++) {
+		pe= &table[i];
+		if (extbase != 0 && pe->sysind != NO_PART)
+			pe->lowsec+= ext_part(pe->sysind) ? extbase : offset;
+		existing[i]= pe->sysind != NO_PART;
+	}
+	geometry();
+	dirty= 0;
+
+	/* Warn about grave dangers ahead. */
+	if (extbase != 0) {
+		stat_start(1);
+		printf("Warning: You are in an extended partition.");
+		stat_end(5);
+	}
+
+	regionize();
+}
+
+void m_write(int ev, object_t *op)
+/* Write the partition table back if modified. */
+{
+	int c;
+	struct part_entry new_table[NR_PARTITIONS], *pe;
+
+	if (ev != 'w' && ev != E_WRITE) return;
+	if (device < 0) { dirty= 0; return; }
+	if (!dirty) {
+		if (ev == 'w') {
+			stat_start(1);
+			printf("%s is not changed, or has already been written",
+							curdev->subname);
+			stat_end(2);
+		}
+		return;
+	}
+
+	if (extbase != 0) {
+		/* Will this stop him?  Probably not... */
+		stat_start(1);
+		printf("You have changed an extended partition.  Bad Idea.");
+		stat_end(5);
+	}
+
+	memcpy(new_table, table+1, NR_PARTITIONS * sizeof(table[1]));
+	for (pe= new_table; pe < new_table + NR_PARTITIONS; pe++) {
+		if (pe->sysind == NO_PART) {
+			memset(pe, 0, sizeof(*pe));
+		} else {
+			abs2dos(&pe->start_head, pe->lowsec);
+			abs2dos(&pe->last_head, pe->lowsec + pe->size - 1);
+
+			/* Fear and loathing time: */
+			if (extbase != 0)
+				pe->lowsec-= ext_part(pe->sysind)
+						? extbase : offset;
+		}
+	}
+	memcpy(bootblock+PART_TABLE_OFF, new_table, sizeof(new_table));
+	bootblock[510]= 0x55;
+	bootblock[511]= 0xAA;
+
+	if (boot_readwrite(1) < 0) {
+		stat_start(1);
+		printf("%s: %s", curdev->name, strerror(errno));
+		stat_end(5);
+		return;
+	}
+	dirty= 0;
+}
+
+void m_shell(int ev, object_t *op)
+/* Shell escape, to do calculations for instance. */
+{
+	int r, pid, status;
+	void (*sigint)(int), (*sigquit)(int), (*sigterm)(int);
+
+	if (ev != 's') return;
+
+	reset_tty();
+	fflush(stdout);
+
+	switch (pid= fork()) {
+	case -1:
+		stat_start(1);
+		printf("can't fork: %s\n", strerror(errno));
+		stat_end(3);
+		break;
+	case 0:
+		if (device >= 0) (void) close(device);
+		execl("/bin/sh", "sh", (char *) nil);
+		r= errno;
+		stat_start(1);
+		printf("/bin/sh: %s\n", strerror(errno));
+		stat_end(3);
+		exit(127);
+	}
+	sigint= signal(SIGINT, SIG_IGN);
+	sigquit= signal(SIGQUIT, SIG_IGN);
+	sigterm= signal(SIGTERM, SIG_IGN);
+	while (pid >= 0 && (r= wait(&status)) >= 0 && r != pid) {}
+	(void) signal(SIGINT, sigint);
+	(void) signal(SIGQUIT, sigquit);
+	(void) signal(SIGTERM, sigterm);
+	tty_raw();
+	if (pid < 0)
+		;
+	else
+	if (WIFEXITED(status) && WEXITSTATUS(status) == 127)
+		stat_start(0);	/* Match the stat_start in the child. */
+	else
+		event(ctrl('L'), op);
+}
+
+void m_dump(struct part_entry *print_table)
+/* Raw dump of the partition table. */
+{
+	struct part_entry *pe;
+	int i;
+	unsigned chs[3];
+
+printf(" Partition + type      Cyl Head Sec   Cyl Head Sec      Base      Size       Kb\n");
+	for (i= 1; i <= NR_PARTITIONS; i++) {
+		pe= &print_table[i];
+		dos2chs(&pe->start_head, chs);
+		printf("%2d%c      %02X%15d%5d%4d",
+			i,
+			pe->bootind & ACTIVE_FLAG ? '*' : ' ',
+			pe->sysind,
+			chs[0], chs[1], chs[2]);
+		dos2chs(&pe->last_head, chs);
+		printf("%6d%5d%4d%10lu%10ld%9lu\n",
+			chs[0], chs[1], chs[2],
+			pe->lowsec,
+			howend == SIZE ? pe->size : pe->size + pe->lowsec - 1,
+			pe->size / 2);
+	}
+}
+
+int quitting= 0;
+
+void m_quit(int ev, object_t *op)
+/* Write the partition table if modified and exit. */
+{
+	if (ev != 'q' && ev != 'x') return;
+
+	quitting= 1;
+
+	if (dirty) event(E_WRITE, op);
+	if (dirty) quitting= 0;
+}
+
+void m_help(int ev, object_t *op)
+/* For people without a clue; let's hope they can find the '?' key. */
+{
+	static struct help {
+		char	*keys;
+		char	*what;
+	} help[]= {
+	 { "? !",		 "This help / more advice!" },
+	 { "+ - (= _ PgUp PgDn)","Select/increment/decrement/make active" },
+	 { "0-9 (a-f)",		 "Enter value" },
+	 { "hjkl (arrow keys)",	 "Move around" },
+	 { "CTRL-K CTRL-J",	 "Move entry up/down" },
+	 { "CTRL-L",		 "Redraw screen" },
+	 { ">",			 "Start a subpartition table" },
+	 { "<",			 "Back to the primary partition table" },
+	 { "m",			 "Cycle through magic values" },
+	 { "spacebar",		 "Show \"Size\" or \"Last\"" },
+	 { "r w",		 "Read/write partition table" },
+	 { "p s q x",		 "Raw dump / Shell escape / Quit / Exit" },
+	 { "y n DEL",		 "Answer \"yes\", \"no\", \"cancel\"" },
+	};
+	static char *advice[] = {
+"* Choose a disk with '+' and '-', then hit 'r'.",
+"* To change any value: Move to it and use '+', '-' or type the desired value.",
+"* To make a new partition:  Move over to the Size or Kb field of an unused",
+"  partition and type the size.  Hit the 'm' key to pad the partition out to",
+"  a cylinder boundary.  Hit 'm' again to pad it out to the end of the disk.",
+"  You can hit 'm' more than once on a base or size field to see several",
+"  interesting values go by.  Note: Other Operating Systems can be picky about",
+"  partitions that are not padded to cylinder boundaries.  Look for highlighted",
+"  head or sector numbers.",
+"* To reuse a partition:  Change the type to MINIX.",
+"* To delete a partition:  Type a zero in the hex Type field.",
+"* To make a partition active:  Type '+' in the Num field.",
+"* To study the list of keys:  Type '?'.",
+	};
+
+	if (ev == '?') {
+		struct help *hp;
+
+		for (hp= help; hp < arraylimit(help); hp++) {
+			stat_start(0);
+			printf("%-25s - %s", hp->keys, hp->what);
+			stat_end(0);
+		}
+		stat_start(0);
+		putstr("Things like ");
+		putstr(t_so); putstr("this"); putstr(t_se);
+		putstr(" must be checked, but ");
+		putstr(t_md); putstr("this"); putstr(t_me);
+		putstr(" is not really a problem");
+		stat_end(0);
+	} else
+	if (ev == '!') {
+		char **ap;
+
+		for (ap= advice; ap < arraylimit(advice); ap++) {
+			stat_start(0);
+			putstr(*ap);
+			stat_end(0);
+		}
+	}
+}
+
+void event(int ev, object_t *op)
+/* Simply call all modifiers for an event, each one knows when to act. */
+{
+	m_help(ev, op);
+	m_redraw(ev, op);
+	m_toggle(ev, op);
+	m_orientation(ev, op);
+	m_move(ev, op);
+	m_updown(ev, op);
+	m_enter(ev, op);
+	m_leave(ev, op);
+	m_modify(ev, op);
+	m_magic(ev, op);
+	m_in(ev, op);
+	m_out(ev, op);
+	m_read(ev, NULL);
+	m_write(ev, op);
+	m_shell(ev, op);
+	m_quit(ev, op);
+}
+
+int keypress(void)
+/* Get a single keypress.  Translate compound keypresses (arrow keys) to
+ * their simpler equivalents.
+ */
+{
+	char ch;
+	int c;
+	int esc= 0;
+
+	set_cursor(curobj->row, curobj->col);
+	fflush(stdout);
+
+	do {
+		if (read(0, &ch, sizeof(ch)) < 0) fatal("stdin");
+		c= (unsigned char) ch;
+		switch (esc) {
+		case 0:
+			switch (c) {
+			case ctrl('['):	esc= 1; break;
+			case '_':	c= '-'; break;
+			case '=':	c= '+'; break;
+			}
+			break;
+		case 1:
+			esc= c == '[' ? 2 : 0;
+			break;
+		case 2:
+			switch (c) {
+			case 'D':	c= 'h';	break;
+			case 'B':	c= 'j';	break;
+			case 'A':	c= 'k';	break;
+			case 'C':	c= 'l';	break;
+			case 'H':	c= 'H';	break;
+			case 'U':
+			case 'S':	c= '-';	break;
+			case 'V':
+			case 'T':	c= '+';	break;
+			}
+			/*FALL THROUGH*/
+		default:
+			esc= 0;
+		}
+	} while (esc > 0);
+
+	switch (c) {
+	case ctrl('B'):	c= 'h';	break;
+	case ctrl('N'):	c= 'j';	break;
+	case ctrl('P'):	c= 'k';	break;
+	case ctrl('F'):	c= 'l';	break;
+	}
+
+	return c;
+}
+
+void mainloop(void)
+/* Get keypress, handle event, display results, reset screen, ad infinitum. */
+{
+	int key;
+
+	while (!quitting) {
+		stat_reset();
+
+		key= keypress();
+
+		event(key, curobj);
+
+		display();
+	}
+}
+
+char *
+prettysizeprint(int kb)
+{
+	int toosmall = 0;
+	static char str[200];
+	char unit = 'k';
+	if(MIN_REGION_SECTORS > kb*2)
+		toosmall = 1;
+	if(kb >= 5*1024) {
+		kb /= 1024;
+		unit = 'M';
+		if(kb >= 5*1024) {
+			kb /= 1024;
+			unit = 'G';
+		}
+	}
+	sprintf(str, "%4d %cB%s", kb, unit,
+		toosmall ? ", too small for MINIX 3" : "");
+	return str;
+}
+
+void
+printregions(region_t *theregions, int indent, int p_nr_partitions, int p_free_regions, int p_nr_regions, int numbers)
+{
+	int r, nofree = 0;
+	region_t *reg;
+	reg = theregions;
+
+	if((p_nr_partitions >= NR_PARTITIONS || !p_free_regions) && p_free_regions)
+		nofree = 1;
+	for(r = 0; r < p_nr_regions; r++, reg++) {
+		unsigned long units;
+		if(reg->is_used_part) {
+			char *name;
+			name = typ2txt(reg->used_part.sysind);
+			printf("%*s", indent, ""); type2col(reg->used_part.sysind);
+			if(numbers) printf("[%d]  ", r);
+			printf("In use by %-10s ", name);
+			units = reg->used_part.size / 2;
+			col(0);
+			printf(" (%s)\n", prettysizeprint(units));
+		} else {
+			printf("%*s", indent, ""); 
+			if(numbers) {
+				if(!nofree) printf("[%d]  ", r);
+				else printf("[-]  ");
+			}
+			printf("Free space           ");
+			units = ((reg->free_sec_last - reg->free_sec_start+1))/2;
+			printf(" (%s)\n", prettysizeprint(units));
+		}
+	}
+
+	if(numbers && p_nr_partitions >= NR_PARTITIONS && p_free_regions) {
+		printf(
+"\nNote: there is free space on this disk, but you can't select it,\n"
+"because there isn't a free slot in the partition table to use it.\n"
+"You can reclaim the free space by deleting an adjacent region.\n");
+	}
+
+	return;
+}
+
+#define IS_YES   3
+#define IS_NO    4
+#define IS_OTHER 5
+int
+is_sure(char *fmt, ...)
+{
+	char yesno[10];
+	va_list ap;
+	va_start (ap, fmt);
+	vprintf(fmt, ap);
+	va_end(ap);
+	printf("  Please enter 'yes' or 'no': ");
+	fflush(stdout);
+	if(!fgets(yesno, sizeof(yesno)-1, stdin)) exit(1);
+
+	if (strcmp(yesno, "yes\n") == 0) return(IS_YES);
+	if (strcmp(yesno, "no\n") == 0) return(IS_NO);
+	return IS_OTHER;
+}
+
+void warn(char *message)
+{
+	printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b ! %s\n",message);
+}
+
+int
+may_kill_region(void)
+{
+        int confirmation;
+	char line[100];
+	int r, i;
+
+	if(used_regions < 1) return 1;
+
+	printf("\n -- Delete in-use region? --\n\n");
+
+	printregions(regions, 3, nr_partitions, free_regions, nr_regions, 1);
+	printf("\nEnter the region number to delete or ENTER to continue: ");
+	fflush(NULL);
+	fgets(line, sizeof(line)-2, stdin);
+	if(!isdigit(line[0]))
+		return 1;
+
+	r=atoi(line);
+	if(r < 0 || r >= nr_regions) {
+		printf("This choice is out of range.\n");
+		return 0;
+	}
+
+	if(!regions[r].is_used_part) {
+		printf("This region is not in use.\n");
+		return 0;
+	}
+
+	i = regions[r].tableno;
+
+	printf("\nPlease confirm that you want to delete region %d, losing all data it", r); 
+	printf("\ncontains. You're disk is not actually updated right away, but still.");
+	printf("\n\n");
+
+ 	do {
+		confirmation = is_sure("Are you sure you want to continue?");
+		if (confirmation == IS_NO) return 0;
+	} while (confirmation != IS_YES);
+
+		table[i].sysind = NO_PART;
+		dirty = 1;
+		regionize();
+
+	/* User may go again. */
+	return 0;
+}
+
+
+region_t *
+select_region(void)
+{
+	int r, rem, rn, done = 0;
+	static char line[100];
+	region_t *reg;
+	int nofree = 0;
+
+	printstep(2, "Select a disk region");
+
+	if(nr_regions < 1) {
+		printf("\nNo regions found - maybe the drive is too small.\n"
+			"Please try expert mode.\n");
+		exit(1);
+	}
+
+	if(nr_partitions >= NR_PARTITIONS || !free_regions) {
+		if(free_regions) {
+			nofree = 1;
+		}
+	}
+
+
+	printf("\nPlease select the region that you want to use for the MINIX 3 setup.");
+	printf("\nIf you select an in-use region it will be overwritten by MINIX. The");
+	printf("\nfollowing region%s were found on the selected disk:\n\n",
+		SORNOT(nr_regions));
+	printregions(regions, 3, nr_partitions, free_regions, nr_regions, 1);
+
+
+	printf("\n");
+	do {
+		printf("Enter the region number to use or type 'delete': ");
+		if(nr_regions == 1) printf(" [0] ");
+		fflush(NULL);
+
+		if(!fgets(line, sizeof(line)-2, stdin))
+			exit(1);
+
+		if (nr_regions == 1 && line[0] == '\n') {
+		    rn = 0;
+		    done = 1;
+		}
+		else {
+			if(strcmp(line,"delete\n") == 0) {
+				may_kill_region();
+				return NULL;
+			}
+
+			if(sscanf(line, "%d", &rn) != 1)  {
+				warn("invalid choice");
+				continue;
+			}
+
+			if(rn < 0 || rn >= nr_regions) {
+				warn("out of range");
+				continue;
+			}
+
+			if(nofree && !regions[rn].is_used_part) {
+				warn("not available");
+				continue;
+			}
+
+			done = 1;
+		} 
+	} while(! done);
+
+	return(&regions[rn]);
+}
+
+static void printstep(int step, char *str)
+{
+	int n;
+	n = printf("\n --- Substep 4.%d: %s ---", step, str);
+	while(n++ < 73) printf("-");
+	printf("\n");
+}
+
+device_t *
+select_disk(void)
+{
+	int done = 0;
+	int i, choice, drives;
+	static char line[500];
+	int biosdrive = 0;
+
+	printstep(1, "Select a disk to install MINIX 3");
+	printf("\nProbing for disks. This may take a short while.");
+
+		i = 0;
+		curdev=firstdev;
+
+		for(; i < MAX_DEVICES;) {
+			printf("."); 
+			fflush(stdout);
+			m_read('r', &biosdrive);
+			if(device >= 0) {
+				devices[i].dev = curdev;
+				devices[i].free_regions = free_regions;
+				devices[i].nr_regions = nr_regions;
+				devices[i].nr_partitions = nr_partitions;
+				devices[i].used_regions = used_regions;
+				devices[i].sectors = table[0].size;
+				curdev->biosdrive = biosdrive-1;
+				memcpy(devices[i].regions, regions, sizeof(regions));
+				i++;
+			}
+
+			nextdevice(NULL, 1);
+			if(curdev == firstdev)
+				break;
+		}
+
+		drives = i;
+
+		if(drives < 1) {
+			printf("\nFound no drives - can't partition.\n");
+			exit(1);
+		}
+
+		printf(" Probing done.\n"); 
+		printf("The following disk%s %s found on your system:\n\n", SORNOT(drives),
+			drives == 1 ? "was" : "were");
+
+			for(i = 0; i < drives; i++) {
+				printf("  ");
+				printf("Disk [%d]:  ", i);
+				printf("%s, ", devices[i].dev->name);
+				printf("%s\n", prettysizeprint(devices[i].sectors/2));
+				printregions(devices[i].regions, 8,
+					devices[i].nr_partitions,
+					devices[i].free_regions,
+					devices[i].nr_regions, 0);
+			}
+	
+	   printf("\n");
+		do {
+			printf("Enter the disk number to use: ");
+	   		if (drives == 1) printf("[0] ");
+			fflush(NULL);
+			if(!fgets(line, sizeof(line)-2, stdin))
+				exit(1);
+			if (line[0] == '\n' && drives == 1) {
+				choice = 0;
+				done = 1;
+			} else {
+			    if(sscanf(line, "%d", &choice) != 1) {
+				warn("choose a disk");
+			 	continue;
+			    }
+			    if(choice < 0 || choice >= i) {
+				warn("out of range");
+				continue;
+			    }
+			    done = 1;
+			}
+		} while(! done);
+	return devices[choice].dev;
+}
+
+int
+scribble_region(region_t *reg, struct part_entry **pe, int *made_new)
+{
+	int ex, trunc = 0, changed = 0, i;
+	struct part_entry *newpart;
+	if(reg->is_used_part && reg->used_part.size > MAX_REGION_SECTORS) {
+		reg->used_part.size = MAX_REGION_SECTORS;
+		trunc = 1;
+		changed = 1;
+		cylinderalign(reg);
+	}
+	if(!reg->is_used_part) {
+		ex = reg->free_sec_last - reg->free_sec_start + 1;
+		if(ex > MAX_REGION_SECTORS) {
+			reg->free_sec_last -= ex - MAX_REGION_SECTORS;
+			trunc = 1;
+			changed = 1;
+			cylinderalign(reg);
+		}
+		if(made_new) *made_new = 1;
+	} else if(made_new) *made_new = 0;
+#if 0
+	if(trunc) {
+		printf("\nWill only use %dMB.\n", MAX_REGION_MB);
+	}
+#endif
+	if(!reg->is_used_part) {
+		for(i = 1; i <= NR_PARTITIONS; i++)
+			if(table[i].sysind == NO_PART)
+				break;
+		if(i > NR_PARTITIONS) {
+			/* Bug, should've been caught earlier. */
+			printf("Couldn't find a free slot. Please try expert mode.\n");
+			exit(1);
+		}
+		newpart = &table[i];
+		newpart->lowsec = reg->free_sec_start;
+		newpart->size = reg->free_sec_last - reg->free_sec_start + 1;
+		changed = 1;
+		newpart->sysind = MINIX_PART;
+	} else  {
+		newpart = &reg->used_part;
+	}
+	*pe = newpart;
+	changed = 1;
+	dirty = 1;
+	return changed;
+}
+
+int
+sanitycheck_failed(char *dev, struct part_entry *pe)
+{
+	struct partition part;
+	int fd;
+	unsigned long it_lowsec, it_secsize;
+
+	if((fd = open(dev, O_RDONLY)) < 0) {
+		perror(dev);
+		return 1;
+	}
+
+	if (ioctl(fd, DIOCGETP, &part) < 0) {
+		fprintf(stderr, "DIOCGETP failed\n");
+		perror(dev);
+		return 1;
+	}
+
+	if(!open_ct_ok(fd)) {
+		printf("\nAutopart error: the disk is in use. This means that although a\n"
+			"new table has been written, it won't be in use by the system\n"
+			"until it's no longer in use (or a reboot is done). Just in case,\n"
+			"I'm not going to continue. Please un-use the disk (or reboot) and try\n"
+			"again.\n\n");
+		return 1;
+	}
+
+	close(fd);
+
+	it_lowsec = div64u(part.base, SECTOR_SIZE);
+	it_secsize = div64u(part.size, SECTOR_SIZE);
+
+	if(it_lowsec != pe->lowsec || it_secsize != pe->size) {
+		fprintf(stderr, "\nReturned and set numbers don't match up!\n");
+		fprintf(stderr, "This can happen if the disk is still opened.\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int
+do_autopart(int resultfd)
+{
+	int confirmation;
+	region_t *r;
+	struct part_entry *pe;
+	char sure[50];
+	struct part_entry orig_table[1 + NR_PARTITIONS];
+	int region, disk, newp;
+
+	nordonly = 1; 
+
+	do {
+		curdev = select_disk();
+	} while(!curdev);
+
+	if(device >= 0) {
+		close(device);
+		device = -1;
+	}
+	recompute0();
+
+	m_read('r', NULL);
+
+	memcpy(orig_table, table, sizeof(table));
+
+	do {
+		/* Show regions. */
+		r = select_region();
+	} while(!r);	/* Back to step 2. */
+
+	/* Write things. */
+	if(scribble_region(r, &pe, &newp)) {
+		char *name;
+		int i, found = -1;
+		char partbuf[100], devname[100];
+		struct part_entry *tpe;
+
+		printstep(3, "Confirm your choices");
+
+		region =  (int)(r-regions); 
+		/* disk = (int) (curdev-devices); */
+
+		printf("\nThis is the point of no return.  You have selected to install MINIX 3\n");
+		printf("into region %d of disk %s.  Please confirm that you want\n",
+			region, curdev->name);
+		printf("to use this selection to install MINIX 3.\n\n");
+
+		do {
+			confirmation = is_sure("Are you sure you want to continue?");
+			if (confirmation == IS_NO) return 1;
+		} while (confirmation != IS_YES);
+
+		/* Retrieve partition number in sorted order that we
+		 * have scribbled in.
+		 */
+		sort();
+		for(i = 1; i <= NR_PARTITIONS; i++) {
+			int si;
+			si = sort_order[i];
+			if(si < 1 || si > NR_PARTITIONS) {
+				fprintf(stderr, "Autopart internal error (out of range) (nothing written).\n");
+				exit(1);
+			}
+			if(table[si].lowsec == pe->lowsec) {
+				if(found > 0) {
+					fprintf(stderr, "Autopart internal error (part found twice) (nothing written).\n");
+					exit(1);
+				}
+				check_ind(&table[si]);
+				table[si].sysind = MINIX_PART;
+				found = i;
+				tpe = &table[si];
+			}
+		}
+		if(found < 1) {
+			fprintf(stderr, "Autopart internal error (part not found) (nothing written).\n");
+			exit(1);
+		}
+		m_write('w', NULL);
+		if(dirty) {
+			fprintf(stderr, "Autopart internal error (couldn't update disk).\n");
+			exit(1);
+		}
+		name=strrchr(curdev->name, '/');
+		if(!name) name = curdev->name;
+		else name++;
+
+		sprintf(partbuf, "%sp%d d%dp%d\n", name, found-1,
+			curdev->biosdrive, found-1);
+		sprintf(devname, "/dev/%sp%d", name, found-1);
+		if(resultfd >= 0 && write(resultfd, partbuf, strlen(partbuf)) < strlen(partbuf)) {
+			fprintf(stderr, "Autopart internal error (couldn't write result).\n");
+			exit(1);
+		}
+		if(device >= 0) {
+			close(device);
+			device = -1;
+		}
+
+#if 0
+		m_dump(orig_table);
+		printf("\n");
+		m_dump(table);
+#endif
+
+		if(sanitycheck_failed(devname, tpe)) {
+			fprintf(stderr, "Autopart internal error (disk sanity check failed).\n");
+			exit(1);
+		}
+
+		if(newp) {
+			int fd;
+			if((fd=open(devname, O_WRONLY)) < 0) {
+				perror(devname);
+			} else {
+				/* Clear any subpartitioning. */
+				static unsigned char sub[2048];
+				sub[510] = 0x55;
+				sub[511] = 0xAA;
+				write(fd, sub, sizeof(sub));
+				close(fd);
+			}
+		}
+		return 0;
+	}
+
+	return 1;
+}
+
+int main(int argc, char **argv)
+{
+	object_t *op;
+	int i, r, key;
+	struct part_entry *pe;
+	char *name;
+	int autopart = 0;
+	int resultfd = -1;
+
+	/* Autopilot mode if invoked as autopart. */
+	if(!(name = strrchr(argv[0], '/'))) name = argv[0];
+	else name++;
+	if(!strcmp(name, "autopart"))
+		autopart = 1;
+
+    if(!autopart) {
+	/* Define a few objects to show on the screen.  First text: */
+	op= newobject(O_INFO, 0, 0,  2, 19);
+	op= newobject(O_TEXT, 0, 0, 22, 13); op->text= "----first----";
+	op= newobject(O_TEXT, 0, 0, 37, 13); op->text= "--geom/last--";
+	op= newobject(O_TEXT, 0, 0, 52, 18); op->text= "------sectors-----";
+	op= newobject(O_TEXT, 0, 1,  4,  6); op->text= "Device";
+	op= newobject(O_TEXT, 0, 1, 23, 12); op->text= "Cyl Head Sec";
+	op= newobject(O_TEXT, 0, 1, 38, 12); op->text= "Cyl Head Sec";
+	op= newobject(O_TEXT, 0, 1, 56,  4); op->text= "Base";
+	op= newobject(O_TEXT, 0, 1, 66,  4); op->text= size_last;
+	op= newobject(O_TEXT, 0, 1, 78,  2); op->text= "Kb";
+	op= newobject(O_TEXT, 0, 4,  0, 15); op->text= "Num Sort   Type";
+
+	/* The device is the current object: */
+    curobj= newobject(O_DEV,  OF_MOD, 2,  4, 15);
+	op= newobject(O_SUB,       0, 3,  4, 15);
+
+	/* Geometry: */
+	op= newobject(O_CYL,  OF_MOD, 2, 40,  5); op->entry= &table[0];
+	op= newobject(O_HEAD, OF_MOD, 2, 45,  3); op->entry= &table[0];
+	op= newobject(O_SEC,  OF_MOD, 2, 49,  2); op->entry= &table[0];
+
+	/* Objects for the device: */
+	op= newobject(O_SCYL,  0, 3, 25,  5); op->entry= &table[0];
+	op= newobject(O_SHEAD, 0, 3, 30,  3); op->entry= &table[0];
+	op= newobject(O_SSEC,  0, 3, 34,  2); op->entry= &table[0];
+	op= newobject(O_LCYL,  0, 3, 40,  5); op->entry= &table[0];
+	op= newobject(O_LHEAD, 0, 3, 45,  3); op->entry= &table[0];
+	op= newobject(O_LSEC,  0, 3, 49,  2); op->entry= &table[0];
+	op= newobject(O_BASE,  0, 3, 59,  9); op->entry= &table[0];
+	op= newobject(O_SIZE,  0, 3, 69,  9); op->entry= &table[0];
+	op= newobject(O_KB,    0, 3, 79,  9); op->entry= &table[0];
+
+	/* Objects for each partition: */
+	for (r= 5, pe= table+1; pe <= table+NR_PARTITIONS; r++, pe++) {
+		op= newobject(O_NUM,    OF_MOD, r,  1,  2); op->entry= pe;
+		op= newobject(O_SORT,        0, r,  5,  2); op->entry= pe;
+		op= newobject(O_TYPHEX, OF_MOD, r, 10,  2); op->entry= pe;
+		op= newobject(O_TYPTXT, OF_MOD, r, 12,  9); op->entry= pe;
+		op= newobject(O_SCYL,   OF_MOD, r, 25,  5); op->entry= pe;
+		op= newobject(O_SHEAD,  OF_MOD, r, 30,  3); op->entry= pe;
+		op= newobject(O_SSEC,   OF_MOD, r, 34,  2); op->entry= pe;
+		op= newobject(O_LCYL,   OF_MOD, r, 40,  5); op->entry= pe;
+		op= newobject(O_LHEAD,  OF_MOD, r, 45,  3); op->entry= pe;
+		op= newobject(O_LSEC,   OF_MOD, r, 49,  2); op->entry= pe;
+		op= newobject(O_BASE,   OF_MOD, r, 59,  9); op->entry= pe;
+		op= newobject(O_SIZE,   OF_MOD, r, 69,  9); op->entry= pe;
+		op= newobject(O_KB,     OF_MOD, r, 79,  9); op->entry= pe;
+	}
+     } else {
+     	int c;
+     	/* autopart uses getopt() */
+     	while((c = getopt(argc, argv, "m:f:")) != EOF) {
+     		switch(c) {
+			case 'm':
+				min_region_mb = atoi(optarg);
+				break;
+     			case 'f':
+				/* Make sure old data file is gone. */
+     				unlink(optarg);
+     				if((resultfd=open(optarg, O_CREAT | O_WRONLY | O_TRUNC)) < 0) {
+     					perror(optarg);
+     					return 1;
+     				}
+     				sync();	/* Make sure no old data file lingers. */
+     				break;
+     			default:
+     				fprintf(stderr, "Unknown option\n");
+     				return 1;
+     		}
+     	}
+     }
+     argc -= optind;
+     argv += optind;
+
+	for (i= 0; i < argc; i++) {
+	 newdevice(argv[i], 0, 0);
+	 }
+
+	if (firstdev == nil) {
+		getdevices(autopart);
+		key= ctrl('L');
+	} else {
+		key= 'r';
+	}
+
+	if(autopart) {
+		int r;
+		if (firstdev == nil) {
+			fprintf(stderr, "autopart couldn't find any devices.\n");
+			return 1;
+		}
+		r = do_autopart(resultfd);
+		if(resultfd >= 0) { close(resultfd); }
+		return r;
+	}
+
+	if (firstdev != nil) {
+		init_tty();
+		clear_screen();
+		event(key, curobj);
+		display();
+		mainloop();
+		reset_tty();
+	}
+	exit(0);
+}
Index: /trunk/minix/commands/ibm/backup.c
===================================================================
--- /trunk/minix/commands/ibm/backup.c	(revision 9)
+++ /trunk/minix/commands/ibm/backup.c	(revision 9)
@@ -0,0 +1,398 @@
+/* readclock - read the real time clock		Authors: T. Holm & E. Froese */
+
+/************************************************************************/
+/*									*/
+/*   readclock.c							*/
+/*									*/
+/*		Read the clock value from the 64 byte CMOS RAM		*/
+/*		area, then set system time.				*/
+/*									*/
+/*		If the machine ID byte is 0xFC or 0xF8, the device	*/
+/*		/dev/mem exists and can be opened for reading,		*/
+/*		and no errors in the CMOS RAM are reported by the	*/
+/*		RTC, then the time is read from the clock RAM		*/
+/*		area maintained by the RTC.				*/
+/*									*/
+/*		The clock RAM values are decoded and fed to mktime	*/
+/*		to make a time_t value, then stime(2) is called.	*/
+/*									*/
+/*		This fails if:						*/
+/*									*/
+/*		If the machine ID does not match 0xFC or 0xF8 (no	*/
+/*		error message.)						*/
+/*									*/
+/*		If the machine ID is 0xFC or 0xF8 and /dev/mem		*/
+/*		is missing, or cannot be accessed.			*/
+/*									*/
+/*		If the RTC reports errors in the CMOS RAM.		*/
+/*									*/
+/************************************************************************/
+/*    origination          1987-Dec-29              efth                */
+/*    robustness	   1990-Oct-06		    C. Sylvain		*/
+/* incorp. B. Evans ideas  1991-Jul-06		    C. Sylvain		*/
+/*    set time & calibrate 1992-Dec-17		    Kees J. Bot		*/
+/*    clock timezone	   1993-Oct-10		    Kees J. Bot		*/
+/*    set CMOS clock	   1994-Jun-12		    Kees J. Bot		*/
+/************************************************************************/
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <signal.h>
+#include <ibm/portio.h>
+#include <ibm/cmos.h>
+#include <sys/svrctl.h>
+
+int nflag = 0;		/* Tell what, but don't do it. */
+int wflag = 0;		/* Set the CMOS clock. */
+int Wflag = 0;		/* Also set the CMOS clock register bits. */
+int y2kflag = 0;	/* Interpret 1980 as 2000 for clock with Y2K bug. */
+
+char clocktz[128];	/* Timezone of the clock. */
+
+#define MACH_ID_ADDR	0xFFFFE		/* BIOS Machine ID at FFFF:000E */
+
+#define PC_AT		   0xFC		/* Machine ID byte for PC/AT,
+					   PC/XT286, and PS/2 Models 50, 60 */
+#define PS_386		   0xF8		/* Machine ID byte for PS/2 Model 80 */
+
+/* Manufacturers usually use the ID value of the IBM model they emulate.
+ * However some manufacturers, notably HP and COMPAQ, have had different
+ * ideas in the past.
+ *
+ * Machine ID byte information source:
+ *	_The Programmer's PC Sourcebook_ by Thom Hogan,
+ *	published by Microsoft Press
+ */
+
+void errmsg(char *s);
+void get_time(struct tm *t);
+int read_register(int reg_addr);
+void set_time(struct tm *t);
+void write_register(int reg_addr, int value);
+int bcd_to_dec(int n);
+int dec_to_bcd(int n);
+void usage(void);
+
+int main(int argc, char **argv)
+{
+  struct tm time1;
+  struct tm time2;
+  struct tm tmnow;
+  char date[64];
+  time_t now, rtc;
+  int i, mem;
+  unsigned char mach_id, cmos_state;
+  struct sysgetenv sysgetenv;
+
+  /* Open /dev/mem to get access to physical memory. */
+  if ((mem = open("/dev/mem", O_RDONLY)) == -1) {
+	errmsg( "Permission denied." );
+	exit(1);
+  }
+  if (lseek(mem, (off_t) MACH_ID_ADDR, SEEK_SET) == -1
+		|| read(mem, (void *) &mach_id, sizeof(mach_id)) < 0) {
+	mach_id = -1;
+  }
+  if (mach_id != PS_386 && mach_id != PC_AT) {
+	errmsg( "Machine ID unknown." );
+	fprintf( stderr, "Machine ID byte = %02x\n", mach_id );
+
+	exit(1);
+  }
+  cmos_state = read_register(CMOS_STATUS);
+  if (cmos_state & (CS_LOST_POWER | CS_BAD_CHKSUM | CS_BAD_TIME)) {
+	errmsg( "CMOS RAM error(s) found..." );
+	fprintf( stderr, "CMOS state = 0x%02x\n", cmos_state );
+
+	if (cmos_state & CS_LOST_POWER)
+	    errmsg( "RTC lost power. Reset CMOS RAM with SETUP." );
+	if (cmos_state & CS_BAD_CHKSUM)
+	    errmsg( "CMOS RAM checksum is bad. Run SETUP." );
+	if (cmos_state & CS_BAD_TIME)
+	    errmsg( "Time invalid in CMOS RAM. Reset clock." );
+	exit(1);
+  }
+
+  /* Process options. */
+  while (argc > 1) {
+	char *p = *++argv;
+
+	if (*p++ != '-') usage();
+
+	while (*p != 0) {
+		switch (*p++) {
+		case 'n':	nflag = 1;	break;
+		case 'w':	wflag = 1;	break;
+		case 'W':	Wflag = 1;	break;
+		case '2':	y2kflag = 1;	break;
+		default:	usage();
+		}
+	}
+	argc--;
+  }
+  if (Wflag) wflag = 1;		/* -W implies -w */
+
+  /* The hardware clock may run in a different time zone, likely GMT or
+   * winter time.  Select that time zone.
+   */
+  strcpy(clocktz, "TZ=");
+  sysgetenv.key = "TZ";
+  sysgetenv.keylen = 2+1;
+  sysgetenv.val = clocktz+3;
+  sysgetenv.vallen = sizeof(clocktz)-3;
+  if (svrctl(SYSGETENV, &sysgetenv) == 0) {
+	putenv(clocktz);
+	tzset();
+  }
+
+  /* Read the CMOS real time clock. */
+  for (i = 0; i < 10; i++) {
+	get_time(&time1);
+	now = time(NULL);
+
+	time1.tm_isdst = -1;	/* Do timezone calculations. */
+	time2 = time1;
+
+	rtc= mktime(&time1);	/* Transform to a time_t. */
+	if (rtc != -1) break;
+
+	fprintf(stderr,
+"readclock: Invalid time read from CMOS RTC: %d-%02d-%02d %02d:%02d:%02d\n",
+		time2.tm_year+1900, time2.tm_mon+1, time2.tm_mday,
+		time2.tm_hour, time2.tm_min, time2.tm_sec);
+	sleep(5);
+  }
+  if (i == 10) exit(1);
+
+  if (!wflag) {
+	/* Set system time. */
+	if (nflag) {
+		printf("stime(%lu)\n", (unsigned long) rtc);
+	} else {
+		if (stime(&rtc) < 0) {
+			errmsg( "Not allowed to set time." );
+			exit(1);
+		}
+	}
+	tmnow = *localtime(&rtc);
+	if (strftime(date, sizeof(date),
+				"%a %b %d %H:%M:%S %Z %Y", &tmnow) != 0) {
+		if (date[8] == '0') date[8]= ' ';
+		printf("Result: %s\n", date);
+	}
+  } else {
+	/* Set the CMOS clock to the system time. */
+	tmnow = *localtime(&now);
+	if (nflag) {
+		printf("%04d-%02d-%02d %02d:%02d:%02d\n",
+			tmnow.tm_year + 1900,
+			tmnow.tm_mon + 1,
+			tmnow.tm_mday,
+			tmnow.tm_hour,
+			tmnow.tm_min,
+			tmnow.tm_sec);
+	} else {
+		set_time(&tmnow);
+	}
+  }
+  exit(0);
+}
+
+void errmsg(char *s)
+{
+  static char *prompt = "readclock: ";
+
+  fprintf(stderr, "%s%s\n", prompt, s);
+  prompt = "";
+}
+
+
+/***********************************************************************/
+/*                                                                     */
+/*    get_time( time )                                                 */
+/*                                                                     */
+/*    Update the structure pointed to by time with the current time    */
+/*    as read from CMOS RAM of the RTC.				       */
+/*    If necessary, the time is converted into a binary format before  */
+/*    being stored in the structure.                                   */
+/*                                                                     */
+/***********************************************************************/
+
+int dead;
+void timeout(int sig) { dead= 1; }
+
+void get_time(struct tm *t)
+{
+  int osec, n;
+  unsigned long i;
+  struct sigaction sa;
+
+  /* Start a timer to keep us from getting stuck on a dead clock. */
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = 0;
+  sa.sa_handler = timeout;
+  sigaction(SIGALRM, &sa, NULL);
+  dead = 0;
+  alarm(5);
+
+  do {
+	osec = -1;
+	n = 0;
+	do {
+		if (dead) {
+			fprintf(stderr, "readclock: CMOS clock appears dead\n");
+			exit(1);
+		}
+
+		/* Clock update in progress? */
+		if (read_register(RTC_REG_A) & RTC_A_UIP) continue;
+
+		t->tm_sec = read_register(RTC_SEC);
+		if (t->tm_sec != osec) {
+			/* Seconds changed.  First from -1, then because the
+			 * clock ticked, which is what we're waiting for to
+			 * get a precise reading.
+			 */
+			osec = t->tm_sec;
+			n++;
+		}
+	} while (n < 2);
+
+	/* Read the other registers. */
+	t->tm_min = read_register(RTC_MIN);
+	t->tm_hour = read_register(RTC_HOUR);
+	t->tm_mday = read_register(RTC_MDAY);
+	t->tm_mon = read_register(RTC_MONTH);
+	t->tm_year = read_register(RTC_YEAR);
+
+	/* Time stable? */
+  } while (read_register(RTC_SEC) != t->tm_sec
+	|| read_register(RTC_MIN) != t->tm_min
+	|| read_register(RTC_HOUR) != t->tm_hour
+	|| read_register(RTC_MDAY) != t->tm_mday
+	|| read_register(RTC_MONTH) != t->tm_mon
+	|| read_register(RTC_YEAR) != t->tm_year);
+
+  if ((read_register(RTC_REG_B) & RTC_B_DM_BCD) == 0) {
+	/* Convert BCD to binary (default RTC mode). */
+	t->tm_year = bcd_to_dec(t->tm_year);
+	t->tm_mon = bcd_to_dec(t->tm_mon);
+	t->tm_mday = bcd_to_dec(t->tm_mday);
+	t->tm_hour = bcd_to_dec(t->tm_hour);
+	t->tm_min = bcd_to_dec(t->tm_min);
+	t->tm_sec = bcd_to_dec(t->tm_sec);
+  }
+  t->tm_mon--;	/* Counts from 0. */
+
+  /* Correct the year, good until 2080. */
+  if (t->tm_year < 80) t->tm_year += 100;
+
+  if (y2kflag) {
+	/* Clock with Y2K bug, interpret 1980 as 2000, good until 2020. */
+	if (t->tm_year < 100) t->tm_year += 20;
+  }
+}
+
+
+int read_register(int reg_addr)
+{
+  int r;
+
+  intr_disable();
+  outb(RTC_INDEX, reg_addr);
+  r= inb(RTC_IO);
+  intr_enable();
+  return r;
+}
+
+
+
+/***********************************************************************/
+/*                                                                     */
+/*    set_time( time )                                                 */
+/*                                                                     */
+/*    Set the CMOS RTC to the time found in the structure.             */
+/*                                                                     */
+/***********************************************************************/
+
+void set_time(struct tm *t)
+{
+  int regA, regB;
+
+  if (Wflag) {
+	/* Set A and B registers to their proper values according to the AT
+	 * reference manual.  (For if it gets messed up, but the BIOS doesn't
+	 * repair it.)
+	 */
+	write_register(RTC_REG_A, RTC_A_DV_OK | RTC_A_RS_DEF);
+	write_register(RTC_REG_B, RTC_B_24);
+  }
+
+  /* Inhibit updates. */
+  regB= read_register(RTC_REG_B);
+  write_register(RTC_REG_B, regB | RTC_B_SET);
+
+  t->tm_mon++;	/* Counts from 1. */
+
+  if (y2kflag) {
+	/* Set the clock back 20 years to avoid Y2K bug, good until 2020. */
+	if (t->tm_year >= 100) t->tm_year -= 20;
+  }
+
+  if ((regB & 0x04) == 0) {
+	/* Convert binary to BCD (default RTC mode) */
+	t->tm_year = dec_to_bcd(t->tm_year % 100);
+	t->tm_mon = dec_to_bcd(t->tm_mon);
+	t->tm_mday = dec_to_bcd(t->tm_mday);
+	t->tm_hour = dec_to_bcd(t->tm_hour);
+	t->tm_min = dec_to_bcd(t->tm_min);
+	t->tm_sec = dec_to_bcd(t->tm_sec);
+  }
+  write_register(RTC_YEAR, t->tm_year);
+  write_register(RTC_MONTH, t->tm_mon);
+  write_register(RTC_MDAY, t->tm_mday);
+  write_register(RTC_HOUR, t->tm_hour);
+  write_register(RTC_MIN, t->tm_min);
+  write_register(RTC_SEC, t->tm_sec);
+
+  /* Stop the clock. */
+  regA= read_register(RTC_REG_A);
+  write_register(RTC_REG_A, regA | RTC_A_DV_STOP);
+
+  /* Allow updates and restart the clock. */
+  write_register(RTC_REG_B, regB);
+  write_register(RTC_REG_A, regA);
+}
+
+
+void write_register(int reg_addr, int value)
+{
+  intr_disable();
+  outb(RTC_INDEX, reg_addr);
+  outb(RTC_IO, value);
+  intr_enable();
+}
+
+int bcd_to_dec(int n)
+{
+  return ((n >> 4) & 0x0F) * 10 + (n & 0x0F);
+}
+
+int dec_to_bcd(int n)
+{
+  return ((n / 10) << 4) | (n % 10);
+}
+
+void usage(void)
+{
+  fprintf(stderr, "Usage: readclock [-nwW2]\n");
+  exit(1);
+}
Index: /trunk/minix/commands/ibm/build
===================================================================
--- /trunk/minix/commands/ibm/build	(revision 9)
+++ /trunk/minix/commands/ibm/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/ibm/dosread.c
===================================================================
--- /trunk/minix/commands/ibm/dosread.c	(revision 9)
+++ /trunk/minix/commands/ibm/dosread.c	(revision 9)
@@ -0,0 +1,1120 @@
+/* dos{dir|read|write} - {list|read|write} MS-DOS disks	 Author: M. Huisjes */
+
+/* Dosdir - list MS-DOS directories. doswrite - write stdin to DOS-file
+ * dosread - read DOS-file to stdout
+ *
+ * Author: Michiel Huisjes.
+ *
+ * Usage: dos... [-lra] drive [file/dir]
+ *	  l: Give long listing.
+ *	  r: List recursively.
+ *	  a: Set ASCII bit.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <sys/times.h>
+#include <unistd.h>
+
+
+#define MAX_CLUSTER_SIZE	4096
+#define MAX_ROOT_ENTRIES	512
+#define FAT_START		512L	/* After bootsector */
+#define ROOTADDR		(FAT_START + 2L * fat_size)
+#define clus_add(cl_no)		((long) (((long) cl_no - 2L) \
+				 * (long) cluster_size \
+				 + data_start \
+			        ))
+struct dir_entry {
+  unsigned char d_name[8];
+  unsigned char d_ext[3];
+  unsigned char d_attribute;
+  unsigned char d_reserved[10];
+  unsigned short d_time;
+  unsigned short d_date;
+  unsigned short d_cluster;
+  unsigned long d_size;
+};
+
+typedef struct dir_entry DIRECTORY;
+
+#define NOT_USED	0x00
+#define ERASED		0xE5
+#define DIR		0x2E
+#define DIR_SIZE	(sizeof (struct dir_entry))
+#define SUB_DIR		0x10
+#define NIL_DIR		((DIRECTORY *) 0)
+
+#define LAST_CLUSTER12	0xFFF
+#define LAST_CLUSTER	0xFFFF
+#define FREE		0x000
+#define BAD		0xFF0
+#define BAD16		0xFFF0
+
+typedef int BOOL;
+
+#define TRUE	1
+#define FALSE	0
+#define NIL_PTR	((char *) 0)
+
+#define DOS_TIME	315532800L	/* 1970 - 1980 */
+
+#define READ			0
+#define WRITE			1
+
+#define FIND	3
+#define LABEL	4
+#define ENTRY	5
+#define find_entry(d, e, p)	directory(d, e, FIND, p)
+#define list_dir(d, e, f)	(void) directory(d, e, f, NIL_PTR)
+#define label()			directory(root, root_entries, LABEL, NIL_PTR)
+#define new_entry(d, e)		directory(d, e, ENTRY, NIL_PTR)
+
+#define is_dir(d)		((d)->d_attribute & SUB_DIR)
+
+#define STD_OUT			1
+
+char	*cmnd;
+
+static int disk;	/* File descriptor for disk I/O */
+
+static DIRECTORY root[MAX_ROOT_ENTRIES];
+static DIRECTORY save_entry;
+static char drive[] = "/dev/dosX";
+#define DRIVE_NR	(sizeof (drive) - 2)
+static char null[MAX_CLUSTER_SIZE], *device = drive, path[128];
+static long data_start;
+static long mark;	/* offset of directory entry to be written */
+static unsigned short total_clusters, cluster_size, root_entries, sub_entries;
+static unsigned long fat_size;
+
+static BOOL Rflag, Lflag, Aflag, dos_read, dos_write, dos_dir, fat_16 = 0;
+static BOOL big_endian;
+
+/* maximum size of a cooked 12bit FAT. Also Size of 16bit FAT cache
+ * if not enough memory for whole FAT
+ */
+#define COOKED_SIZE		8192
+/* raw FAT. Only used for 12bit FAT to make conversion easier 
+ */
+static unsigned char	*raw_fat;
+/* Cooked FAT. May be only part of the FAT for 16 bit FATs
+ */
+static unsigned short	*cooked_fat;
+/* lowest and highest entry in fat cache
+ */
+static unsigned short	fat_low = USHRT_MAX,
+			fat_high = 0;
+static BOOL		fat_dirty = FALSE;
+static unsigned int	cache_size;
+
+
+/* Prototypes. */
+_PROTOTYPE(void usage, (char *prog_name) );
+_PROTOTYPE(unsigned c2u2, (unsigned char *ucarray) );
+_PROTOTYPE(unsigned long c4u4, (unsigned char *ucarray) );
+_PROTOTYPE(void determine, (void));
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(DIRECTORY *directory, (DIRECTORY *dir, int entries, BOOL function, char *pathname) );
+_PROTOTYPE(void extract, (DIRECTORY *entry) );
+_PROTOTYPE(void make_file, (DIRECTORY *dir_ptr, int entries, char *name) );
+_PROTOTYPE(void fill_date, (DIRECTORY *entry) );
+_PROTOTYPE(char *make_name, (DIRECTORY *dir_ptr, int dir_fl) );
+_PROTOTYPE(int fill, (char *buffer, size_t size) );
+_PROTOTYPE(void xmodes, (int mode) );
+_PROTOTYPE(void show, (DIRECTORY *dir_ptr, char *name) );
+_PROTOTYPE(void free_blocks, (void));
+_PROTOTYPE(DIRECTORY *read_cluster, (unsigned int cluster) );
+_PROTOTYPE(unsigned short free_cluster, (BOOL leave_fl) );
+_PROTOTYPE(void link_fat, (unsigned int cl_1, unsigned int cl_2) );
+_PROTOTYPE(unsigned short next_cluster, (unsigned int cl_no) );
+_PROTOTYPE(char *slash, (char *str) );
+_PROTOTYPE(void add_path, (char *file, BOOL slash_fl) );
+_PROTOTYPE(void disk_io, (BOOL op, unsigned long seek, void *address, unsigned bytes) );
+_PROTOTYPE(void flush_fat, (void));
+_PROTOTYPE(void read_fat, (unsigned int cl_no));
+_PROTOTYPE(BOOL free_range, (unsigned short *first, unsigned short *last));
+_PROTOTYPE(long lmin, (long a, long b));
+
+
+void usage(prog_name)
+register char *prog_name;
+{
+  fprintf (stderr, "Usage: %s [%s\n", prog_name,
+	     (dos_dir ? "-lr] drive [dir]" : "-a] drive file"));
+  exit(1);
+}
+
+unsigned c2u2(ucarray)
+unsigned char *ucarray;
+{
+  return ucarray[0] + (ucarray[1] << 8);	/* parens vital */
+}
+
+unsigned long c4u4(ucarray)
+unsigned char *ucarray;
+{
+  return ucarray[0] + ((unsigned long) ucarray[1] << 8) +
+		      ((unsigned long) ucarray[2] << 16) +
+		      ((unsigned long) ucarray[3] << 24);
+}
+
+void determine()
+{
+  struct dosboot {
+	unsigned char cjump[2];	/* unsigneds avoid bugs */
+	unsigned char nop;
+	unsigned char name[8];
+	unsigned char cbytepers[2];	/* don't use shorts, etc */
+	unsigned char secpclus;		/* to avoid struct member */
+	unsigned char creservsec[2];	/* alignment and byte */
+	unsigned char fats;		/* order bugs */
+	unsigned char cdirents[2];
+	unsigned char ctotsec[2];
+	unsigned char media;
+	unsigned char csecpfat[2];
+	unsigned char csecptrack[2];
+	unsigned char cheads[2];
+	unsigned char chiddensec[2];
+	unsigned char dos4hidd2[2];
+	unsigned char dos4totsec[4];
+	/* Char    fill[476]; */
+  } boot;
+  unsigned short boot_magic;	/* last of boot block */
+  unsigned bytepers, reservsec, dirents;
+  unsigned secpfat, secptrack, heads, hiddensec;
+  unsigned long totsec;
+  unsigned char fat_info, fat_check;
+  unsigned short endiantest = 1;
+  int errcount = 0;
+
+  big_endian = !(*(unsigned char *)&endiantest);
+
+  /* Read Bios-Parameterblock */
+  disk_io(READ, 0L, &boot, sizeof boot);
+  disk_io(READ, 0x1FEL, &boot_magic, sizeof boot_magic);
+
+  /* Convert some arrays */
+  bytepers = c2u2(boot.cbytepers);
+  reservsec = c2u2(boot.creservsec);
+  dirents = c2u2(boot.cdirents);
+  totsec = c2u2(boot.ctotsec);
+  if (totsec == 0) totsec = c4u4(boot.dos4totsec);
+  secpfat = c2u2(boot.csecpfat);
+  secptrack = c2u2(boot.csecptrack);
+  heads = c2u2(boot.cheads);
+
+  /* The `hidden sectors' are the sectors before the partition.
+   * The calculation here is probably wrong (I think the dos4hidd2
+   * bytes are the msbs), but that doesn't matter, since the
+   * value isn't used anyway
+   */
+  hiddensec = c2u2(boot.chiddensec);
+  if (hiddensec == 0) hiddensec = c2u2 (boot.dos4hidd2);
+
+  /* Safety checking */
+  if (boot_magic != 0xAA55) {
+	fprintf (stderr, "%s: magic != 0xAA55\n", cmnd);
+	++errcount;
+  }
+
+  /* Check sectors per track instead of inadequate media byte */
+  if (secptrack < 15 &&		/* assume > 15 hard disk & wini OK */
+#ifdef SECT10			/* BIOS modified for 10 sec/track */
+      secptrack != 10 &&
+#endif
+#ifdef SECT8			/* BIOS modified for 8 sec/track */
+      secptrack != 8 &&
+#endif
+      secptrack != 9) {
+	fprintf (stderr, "%s: %d sectors per track not supported\n", cmnd, secptrack);
+	++errcount;
+  }
+  if (bytepers == 0) {
+	fprintf (stderr, "%s: bytes per sector == 0\n", cmnd);
+	++errcount;
+  }
+  if (boot.secpclus == 0) {
+	fprintf (stderr, "%s: sectors per cluster == 0\n", cmnd);
+	++errcount;
+  }
+  if (boot.fats != 2 && dos_write) {
+	fprintf (stderr, "%s: fats != 2\n", cmnd);
+	++errcount;
+  }
+  if (reservsec != 1) {
+	fprintf (stderr, "%s: reserved != 1\n", cmnd);
+	++errcount;
+  }
+  if (errcount != 0) {
+	fprintf (stderr, "%s: Can't handle disk\n", cmnd);
+	exit(2);
+  }
+
+  /* Calculate everything. */
+  if (boot.secpclus == 0) boot.secpclus = 1;
+  total_clusters =
+	(totsec - boot.fats * secpfat - reservsec -
+	 dirents * 32L / bytepers		    ) / boot.secpclus + 2;
+  	/* first 2 entries in FAT aren't used */
+  cluster_size = bytepers * boot.secpclus;
+  fat_size = (unsigned long) secpfat * (unsigned long) bytepers;
+  data_start = (long) bytepers + (long) boot.fats * fat_size
+	+ (long) dirents *32L;
+  root_entries = dirents;
+  sub_entries = boot.secpclus * bytepers / 32;
+  if (total_clusters > 4096) fat_16 = 1;
+
+  /* Further safety checking */
+  if (cluster_size > MAX_CLUSTER_SIZE) {
+	fprintf (stderr, "%s: cluster size too big\n", cmnd);
+	++errcount;
+  }
+
+  disk_io(READ, FAT_START, &fat_info, 1);
+  disk_io(READ, FAT_START + fat_size, &fat_check, 1);
+  if (fat_check != fat_info) {
+	fprintf (stderr, "%s: Disk type in FAT copy differs from disk type in FAT original.\n", cmnd);
+	++errcount;
+  }
+  if (errcount != 0) {
+	fprintf (stderr, "%s: Can't handle disk\n", cmnd);
+	exit(2);
+  }
+}
+
+int main(argc, argv)
+int argc;
+register char *argv[];
+{
+  register char *arg_ptr = slash(argv[0]);
+  DIRECTORY *entry;
+  short idx = 1;
+  char dev_nr = '0';
+
+  cmnd = arg_ptr;	/* needed for error messages */
+  if (!strcmp(arg_ptr, "dosdir"))
+	dos_dir = TRUE;
+  else if (!strcmp(arg_ptr, "dosread"))
+	dos_read = TRUE;
+  else if (!strcmp(arg_ptr, "doswrite"))
+	dos_write = TRUE;
+  else {
+	fprintf (stderr, "%s: Program should be named dosread, doswrite or dosdir.\n", cmnd);
+	exit(1);
+  }
+
+  if (argc == 1) usage(argv[0]);
+
+  if (argv[1][0] == '-') {
+	for (arg_ptr = &argv[1][1]; *arg_ptr; arg_ptr++) {
+		if (*arg_ptr == 'l' && dos_dir) {
+			Lflag = TRUE;
+		} else if (*arg_ptr == 'r' && dos_dir) {
+			Rflag = TRUE;
+		} else if (*arg_ptr == 'a' && !dos_dir) {
+			assert ('\n' == 10);
+			assert ('\r' == 13);
+			Aflag = TRUE;
+		} else {
+			usage(argv[0]);
+		}
+	}
+	idx++;
+  }
+  if (idx == argc) usage(argv[0]);
+
+  if (strlen(argv[idx]) > 1) {
+	device = argv[idx++];
+
+	/* If the device does not contain a / we assume that it
+	 * is the name of a device in /dev. Instead of prepending
+	 * /dev/ we try to chdir there.
+	 */
+	if (strchr(device, '/') == NULL && chdir("/dev") < 0) {
+		perror("/dev");
+		exit(1);
+	}
+  } else {
+	if ((dev_nr = toupper (*argv[idx++])) < 'A' || dev_nr > 'Z')
+		usage(argv[0]);
+
+	device[DRIVE_NR] = dev_nr;
+  }
+
+  if ((disk = open(device, dos_write ? O_RDWR : O_RDONLY)) < 0) {
+	fprintf (stderr, "%s: cannot open %s: %s\n",
+		 cmnd, device, strerror (errno));
+	exit(1);
+  }
+  determine();
+  disk_io(READ, ROOTADDR, root, DIR_SIZE * root_entries);
+
+  if (dos_dir && Lflag) {
+	entry = label();
+	printf ("Volume in drive %c ", dev_nr);
+	if (entry == NIL_DIR)
+		printf("has no label.\n\n");
+	else
+		printf ("is %.11s\n\n", entry->d_name);
+  }
+  if (argv[idx] == NIL_PTR) {
+	if (!dos_dir) usage(argv[0]);
+	if (Lflag) printf ("Root directory:\n");
+	list_dir(root, root_entries, FALSE);
+	if (Lflag) free_blocks();
+	fflush (stdout);
+	exit(0);
+  }
+  for (arg_ptr = argv[idx]; *arg_ptr; arg_ptr++)
+	if (*arg_ptr == '\\')	*arg_ptr = '/';
+	else		     	*arg_ptr = toupper (*arg_ptr);
+  if (*--arg_ptr == '/') *arg_ptr = '\0';	/* skip trailing '/' */
+
+  add_path(argv[idx], FALSE);
+  add_path("/", FALSE);
+
+  if (dos_dir && Lflag) printf ( "Directory %s:\n", path);
+
+  entry = find_entry(root, root_entries, argv[idx]);
+
+  if (dos_dir) {
+	list_dir(entry, sub_entries, FALSE);
+	if (Lflag) free_blocks();
+  } else if (dos_read)
+	extract(entry);
+  else {
+	if (entry != NIL_DIR) {
+		fflush (stdout);
+		if (is_dir(entry))
+			fprintf (stderr, "%s: %s is a directory.\n", cmnd, path);
+		else
+			fprintf (stderr, "%s: %s already exists.\n", cmnd, argv[idx]);
+		exit(1);
+	}
+	add_path(NIL_PTR, TRUE);
+
+	if (*path) make_file(find_entry(root, root_entries, path),
+			  sub_entries, slash(argv[idx]));
+	else
+		make_file(root, root_entries, argv[idx]);
+  }
+
+  (void) close(disk);
+  fflush (stdout);
+  exit(0);
+  return(0);
+}
+
+
+/* General directory search routine.
+ * 
+ * dir:
+ *	Points to one or more directory entries
+ * entries:
+ *	number of entries
+ *	if entries == root_entries, dir points to the entire
+ *	root directory. Otherwise it points to a single directory
+ *	entry describing the directory to be searched.
+ *	
+ * function:
+ *	FIND ... find pathname relative to directory dir.
+ *	LABEL ... find first label entry in dir.
+ *	ENTRY ... create a new empty entry.
+ *	FALSE ... list directory
+ *
+ * pathname:
+ *	name of the file to be found or directory to be listed.
+ *	must be in upper case, pathname components must be
+ *	separated by slashes, but can be longer than than 
+ *	8+3 characters (The rest is ignored).
+ */
+DIRECTORY *directory(dir, entries, function, pathname)
+DIRECTORY *dir;
+int entries;
+int function;
+register char *pathname;
+{
+  register DIRECTORY *dir_ptr = dir;
+  DIRECTORY *mem = NIL_DIR;
+  unsigned short cl_no = dir->d_cluster;
+  unsigned short type, last = 0;
+  char file_name[14];
+  char *name;
+  int i = 0;
+
+  if (function == FIND) {
+	while (*pathname != '/' && *pathname != '.' && *pathname &&
+	       i < 8) {
+		file_name[i++] = *pathname++;
+	}
+	if (*pathname == '.') {
+		int j = 0;
+		file_name[i++] = *pathname++;
+		while (*pathname != '/' && *pathname != '.' && *pathname &&
+		       j++ < 3) {
+			file_name[i++] = *pathname++;
+		}
+	}
+	while (*pathname != '/' && *pathname) pathname++;
+	file_name[i] = '\0';
+  }
+  do {
+	if (entries != root_entries) {
+		mem = dir_ptr = read_cluster(cl_no);
+		last = cl_no;
+		cl_no = next_cluster(cl_no);
+	}
+	for (i = 0; i < entries; i++, dir_ptr++) {
+		type = dir_ptr->d_name[0] & 0x0FF;
+		if (function == ENTRY) {
+			if (type == NOT_USED || type == ERASED) {
+				if (!mem)
+					mark = ROOTADDR + (long) i *(long) DIR_SIZE;
+				else
+					mark = clus_add(last) + (long) i *(long) DIR_SIZE;
+				return dir_ptr;
+			}
+			continue;
+		}
+		if (type == NOT_USED) break;
+		if (dir_ptr->d_attribute & 0x08) {
+			if (function == LABEL) return dir_ptr;
+			continue;
+		}
+		if (type == DIR || type == ERASED || function == LABEL)
+			continue;
+		type = is_dir(dir_ptr);
+		name = make_name(dir_ptr,
+				 (function == FIND) ?  FALSE : type);
+		if (function == FIND) {
+			if (strcmp(file_name, name) != 0) continue;
+			if (!type) {
+				if (dos_dir || *pathname) {
+					fflush (stdout);
+					fprintf (stderr, "%s: Not a directory: %s\n", cmnd, file_name);
+					exit(1);
+				}
+			} else if (*pathname == '\0' && dos_read) {
+				fflush (stdout);
+				fprintf (stderr, "%s: %s is a directory.\n", cmnd, path);
+				exit(1);
+			}
+			if (*pathname) {
+				dir_ptr = find_entry(dir_ptr,
+					 sub_entries, pathname + 1);
+			}
+			if (mem) {
+				if (dir_ptr) {
+					memcpy((char *)&save_entry, (char *)dir_ptr, DIR_SIZE);
+					dir_ptr = &save_entry;
+				}
+				free( (void *) mem);
+			}
+			return dir_ptr;
+		} else {
+			if (function == FALSE) {
+				show(dir_ptr, name);
+			} else if (type) {	/* Recursive */
+				printf ( "Directory %s%s:\n", path, name);
+				add_path(name, FALSE);
+				list_dir(dir_ptr, sub_entries, FALSE);
+				add_path(NIL_PTR, FALSE);
+			}
+		}
+	}
+	if (mem) free( (void *) mem);
+  } while (cl_no != LAST_CLUSTER && mem);
+
+  switch (function) {
+      case FIND:
+	if (dos_write && *pathname == '\0') return NIL_DIR;
+	fflush (stdout);
+	fprintf (stderr, "%s: Cannot find `%s'.\n", cmnd, file_name);
+	exit(1);
+      case LABEL:
+	return NIL_DIR;
+      case ENTRY:
+	if (!mem) {
+		fflush (stdout);
+		fprintf (stderr, "%s: No entries left in root directory.\n", cmnd);
+		exit(1);
+	}
+	cl_no = free_cluster(TRUE);
+	link_fat(last, cl_no);
+	link_fat(cl_no, LAST_CLUSTER);
+	disk_io(WRITE, clus_add(cl_no), null, cluster_size);
+
+	return new_entry(dir, entries);
+      case FALSE:
+	if (Rflag) {
+		printf ("\n");
+		list_dir(dir, entries, TRUE);
+	}
+  }
+  return NULL;
+}
+
+void extract(entry)
+register DIRECTORY *entry;
+{
+  register unsigned short cl_no = entry->d_cluster;
+  char buffer[MAX_CLUSTER_SIZE];
+  int rest, i;
+
+  if (entry->d_size == 0)	/* Empty file */
+	return;
+
+  do {
+	disk_io(READ, clus_add(cl_no), buffer, cluster_size);
+	rest = (entry->d_size > (long) cluster_size) ? cluster_size : (short) entry->d_size;
+
+	if (Aflag) {
+		for (i = 0; i < rest; i ++) {
+			if (buffer [i] != '\r') putchar (buffer [i]);
+		}
+		if (ferror (stdout)) {
+			fprintf (stderr, "%s: cannot write to stdout: %s\n",
+				 cmnd, strerror (errno));
+			exit (1);
+		}
+	} else {
+		if (fwrite (buffer, 1, rest, stdout) != rest) {
+			fprintf (stderr, "%s: cannot write to stdout: %s\n",
+				 cmnd, strerror (errno));
+			exit (1);
+		}
+	}
+	entry->d_size -= (long) rest;
+	cl_no = next_cluster(cl_no);
+	if (cl_no == BAD16) {
+		fflush (stdout);
+		fprintf (stderr, "%s: reserved cluster value %x encountered.\n",
+			 cmnd, cl_no);
+		exit (1);
+	}
+  } while (entry->d_size && cl_no != LAST_CLUSTER);
+
+  if (cl_no != LAST_CLUSTER)
+	fprintf (stderr, "%s: Too many clusters allocated for file.\n", cmnd);
+  else if (entry->d_size != 0)
+	fprintf (stderr, "%s: Premature EOF: %ld bytes left.\n", cmnd,
+		     entry->d_size);
+}
+
+
+/* Minimum of two long values
+ */
+long lmin (a, b)
+long a, b;
+{
+	if (a < b) return a;
+	else return b;
+}
+
+
+void make_file(dir_ptr, entries, name)
+DIRECTORY *dir_ptr;
+int entries;
+char *name;
+{
+  register DIRECTORY *entry = new_entry(dir_ptr, entries);
+  register char *ptr;
+  char buffer[MAX_CLUSTER_SIZE];
+  unsigned short cl_no = 0;
+  int i, r;
+  long size = 0L;
+  unsigned short first_cluster, last_cluster;
+  long chunk;
+
+  memset (&entry->d_name[0], ' ', 11);    /* clear entry */
+  for (i = 0, ptr = name; i < 8 && *ptr != '.' && *ptr; i++)
+	entry->d_name[i] = *ptr++;
+  while (*ptr != '.' && *ptr) ptr++;
+  if (*ptr == '.') ptr++;
+  for (i = 0; i < 3 && *ptr != '.' && *ptr; i++) entry->d_ext[i] = *ptr++;
+
+  for (i = 0; i < 10; i++) entry->d_reserved[i] = '\0';
+  entry->d_attribute = '\0';
+
+  entry->d_cluster = 0;
+
+  while (free_range (&first_cluster, &last_cluster)) {
+	do {
+		unsigned short	nr_clus;
+
+		chunk = lmin ((long) (last_cluster - first_cluster + 1) *
+			     		  cluster_size,
+			      (long) MAX_CLUSTER_SIZE);
+		r = fill(buffer, chunk);
+		if (r == 0) goto done;
+		nr_clus = (r + cluster_size - 1) / cluster_size;
+		disk_io(WRITE, clus_add(first_cluster), buffer, r);
+
+		for (i = 0; i < nr_clus; i ++) {
+			if (entry->d_cluster == 0)
+				cl_no = entry->d_cluster = first_cluster;
+			else {
+				link_fat(cl_no, first_cluster);
+				cl_no = first_cluster;
+			}
+			first_cluster ++;
+		}
+
+		size += r;
+	} while (first_cluster <= last_cluster);
+  }
+  fprintf (stderr, "%s: disk full. File truncated\n", cmnd);
+done:
+  if (entry->d_cluster != 0) link_fat(cl_no, LAST_CLUSTER);
+  entry->d_size = size;
+  fill_date(entry);
+  disk_io(WRITE, mark, entry, DIR_SIZE);
+
+  if (fat_dirty) flush_fat ();
+
+}
+
+
+#define SEC_MIN	60L
+#define SEC_HOUR	(60L * SEC_MIN)
+#define SEC_DAY	(24L * SEC_HOUR)
+#define SEC_YEAR	(365L * SEC_DAY)
+#define SEC_LYEAR	(366L * SEC_DAY)
+
+unsigned short mon_len[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+void fill_date(entry)
+DIRECTORY *entry;
+{
+  register long cur_time = time((long *) 0) - DOS_TIME;
+  unsigned short year = 0, month = 1, day, hour, minutes, seconds;
+  int i;
+  long tmp;
+
+  if (cur_time < 0)		/* Date not set on booting ... */
+	cur_time = 0;
+  for (;;) {
+	tmp = (year % 4 == 0) ? SEC_LYEAR : SEC_YEAR;
+	if (cur_time < tmp) break;
+	cur_time -= tmp;
+	year++;
+  }
+
+  day = (unsigned short) (cur_time / SEC_DAY);
+  cur_time -= (long) day *SEC_DAY;
+
+  hour = (unsigned short) (cur_time / SEC_HOUR);
+  cur_time -= (long) hour *SEC_HOUR;
+
+  minutes = (unsigned short) (cur_time / SEC_MIN);
+  cur_time -= (long) minutes *SEC_MIN;
+
+  seconds = (unsigned short) cur_time;
+
+  mon_len[1] = (year % 4 == 0) ? 29 : 28;
+  i = 0;
+  while (day >= mon_len[i]) {
+	month++;
+	day -= mon_len[i++];
+  }
+  day++;
+
+  entry->d_date = (year << 9) | (month << 5) | day;
+  entry->d_time = (hour << 11) | (minutes << 5) | seconds;
+}
+
+char *make_name(dir_ptr, dir_fl)
+register DIRECTORY *dir_ptr;
+short dir_fl;
+{
+  static char name_buf[14];
+  register char *ptr = name_buf;
+  short i;
+
+  for (i = 0; i < 8; i++) *ptr++ = dir_ptr->d_name[i];
+
+  while (*--ptr == ' ');
+  assert (ptr >= name_buf);
+
+  ptr++;
+  if (dir_ptr->d_ext[0] != ' ') {
+	*ptr++ = '.';
+	for (i = 0; i < 3; i++) *ptr++ = dir_ptr->d_ext[i];
+	while (*--ptr == ' ');
+	ptr++;
+  }
+  if (dir_fl) *ptr++ = '/';
+  *ptr = '\0';
+
+  return name_buf;
+}
+
+
+int fill(buffer, size)
+register char *buffer;
+size_t	size;
+{
+  static BOOL nl_mark = FALSE;
+  char *last = &buffer[size];
+  char *begin = buffer;
+  register int c;
+
+  while (buffer < last) {
+  	if (nl_mark) {
+  		*buffer ++ = '\n';
+  		nl_mark = FALSE;
+  	} else {
+		c = getchar();
+		if (c == EOF) break;
+		if (Aflag && c == '\n') {
+			*buffer ++ = '\r';
+			nl_mark = TRUE;
+		} else {
+			*buffer++ = c;
+		}
+	}
+  }
+
+  return (buffer - begin);
+}
+
+#define HOUR	0xF800		/* Upper 5 bits */
+#define MIN	0x07E0		/* Middle 6 bits */
+#define YEAR	0xFE00		/* Upper 7 bits */
+#define MONTH	0x01E0		/* Mid 4 bits */
+#define DAY	0x01F		/* Lowest 5 bits */
+
+char *month[] = {
+	 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+void xmodes(mode)
+int mode;
+{
+  printf ( "\t%c%c%c%c%c", (mode & SUB_DIR) ? 'd' : '-',
+	     (mode & 02) ? 'h' : '-', (mode & 04) ? 's' : '-',
+	     (mode & 01) ? '-' : 'w', (mode & 0x20) ? 'a' : '-');
+}
+
+void show(dir_ptr, name)
+DIRECTORY *dir_ptr;
+char *name;
+{
+  register unsigned short e_date = dir_ptr->d_date;
+  register unsigned short e_time = dir_ptr->d_time;
+  unsigned short next;
+  char bname[20];
+  short i = 0;
+
+  while (*name && *name != '/') bname[i++] = *name++;
+  bname[i] = '\0';
+  if (!Lflag) {
+	printf ( "%s\n", bname);
+	return;
+  }
+  xmodes( (int) dir_ptr->d_attribute);
+  printf ( "\t%s%s", bname, strlen(bname) < 8 ? "\t\t" : "\t");
+  i = 1;
+  if (is_dir(dir_ptr)) {
+	next = dir_ptr->d_cluster;
+	while ((next = next_cluster(next)) != LAST_CLUSTER) i++;
+	printf ("%8ld", (long) i * (long) cluster_size);
+  } else
+	printf ("%8ld", dir_ptr->d_size);
+  printf (" %02d:%02d %2d %s %d\n", ((e_time & HOUR) >> 11),
+	     ((e_time & MIN) >> 5), (e_date & DAY),
+   month[((e_date & MONTH) >> 5) - 1], ((e_date & YEAR) >> 9) + 1980);
+}
+
+void free_blocks()
+{
+  register unsigned short cl_no;
+  long nr_free = 0;
+  long nr_bad = 0;
+
+  for (cl_no = 2; cl_no < total_clusters; cl_no++) {
+	switch (next_cluster(cl_no)) {
+	    case FREE:	nr_free++;	break;
+	    case BAD16:	nr_bad++;	break;
+	}
+  }
+
+  printf ("Free space: %ld bytes.\n", nr_free * (long) cluster_size);
+  if (nr_bad != 0)
+	printf ("Bad sectors: %ld bytes.\n", nr_bad * (long) cluster_size);
+}
+
+
+DIRECTORY *read_cluster(cluster)
+register unsigned int cluster;
+{
+  register DIRECTORY *sub_dir;
+
+  if ((sub_dir = malloc(cluster_size)) == NULL) {
+	fprintf (stderr, "%s: Cannot set break!\n", cmnd);
+	exit(1);
+  }
+  disk_io(READ, clus_add(cluster), sub_dir, cluster_size);
+
+  return sub_dir;
+}
+
+static unsigned short cl_index = 2;
+
+/* find a range of consecutive free clusters. Return TRUE if found
+ * and return the first and last cluster in the |*first| and |*last|.
+ * If no free clusters are left, return FALSE.
+ *
+ * Warning: Assumes that all of the range is used before the next call
+ *	to free_range or free_cluster.
+ */
+BOOL free_range (first, last)
+unsigned short *first, *last;
+{
+  while (cl_index < total_clusters && next_cluster(cl_index) != FREE)
+	cl_index++;
+  if (cl_index >= total_clusters) return FALSE;
+  *first = cl_index;
+  while (cl_index < total_clusters && next_cluster(cl_index) == FREE)
+	cl_index++;
+  *last = cl_index - 1;
+  return TRUE;
+}
+
+
+/* find a free cluster.
+ * Return the number of the free cluster or a number > |total_clusters|
+ * if none is found.
+ * If |leave_fl| is TRUE, the the program will be terminated if 
+ * no free cluster can be found
+ *
+ * Warning: Assumes that the cluster is used before the next call
+ *	to free_range or free_cluster.
+ */
+unsigned short free_cluster(leave_fl)
+BOOL leave_fl;
+{
+  while (cl_index < total_clusters && next_cluster(cl_index) != FREE)
+	cl_index++;
+
+  if (leave_fl && cl_index >= total_clusters) {
+	fprintf (stderr, "%s: Diskette full. File not added.\n", cmnd);
+	exit(1);
+  }
+  return cl_index++;
+}
+
+
+/* read a portion of the fat containing |cl_no| into the cache
+ */
+void read_fat (cl_no) 
+  unsigned int cl_no;
+{
+
+  if (!cooked_fat) {
+  	/* Read the fat for the first time. We have to allocate all the
+  	 * buffers
+  	 */
+  	if (fat_16) {
+		/* FAT consists of little endian shorts. Easy to convert
+		 */
+		if ((cooked_fat = malloc (fat_size)) == NULL) {
+			/* Oops, FAT doesn't fit into memory, just read
+			 * a chunk
+			 */
+			if ((cooked_fat = malloc (COOKED_SIZE)) == NULL) {
+				fprintf (stderr, "%s: not enough memory for FAT cache. Use chmem\n",
+					 cmnd);
+				exit (1);
+			}
+			cache_size = COOKED_SIZE / 2;
+		} else {
+			cache_size = fat_size / 2;
+		}
+	} else {
+		/* 12 bit FAT. Difficult encoding, but small. Keep
+		 * both raw FAT and cooked version in memory.
+		 */
+		if ((cooked_fat = malloc (total_clusters * sizeof (short))) == NULL ||
+		    (raw_fat = malloc (fat_size)) == NULL) {
+			fprintf (stderr, "%s: not enough memory for FAT cache. Use chmem\n",
+				 cmnd);
+			exit (1);
+		}
+		cache_size = total_clusters;
+	}
+  }
+  fat_low = cl_no / cache_size * cache_size;
+  fat_high = fat_low + cache_size - 1;
+
+  if (!fat_16) {
+  	unsigned short	*cp;
+  	unsigned char	*rp;
+  	unsigned short	i;
+
+	disk_io (READ, FAT_START, raw_fat, fat_size);
+	for (rp = raw_fat, cp = cooked_fat, i = 0;
+	     i < cache_size;
+	     rp += 3, i += 2) {
+	     	*cp = *rp + ((*(rp + 1) & 0x0f) << 8);
+	     	if (*cp == BAD) *cp = BAD16;
+	     	else if (*cp == LAST_CLUSTER12) *cp = LAST_CLUSTER;
+	     	cp ++;
+	     	*cp = ((*(rp + 1) & 0xf0) >> 4) + (*(rp + 2) << 4);
+	     	if (*cp == BAD) *cp = BAD16;
+	     	else if (*cp == LAST_CLUSTER12) *cp = LAST_CLUSTER;
+	     	cp ++;
+	}
+  } else {
+
+	assert (sizeof (short) == 2);
+	assert (CHAR_BIT == 8);		/* just in case */
+
+	disk_io (READ, FAT_START + fat_low * 2, (void *)cooked_fat, cache_size * 2);
+	if (big_endian) {
+		unsigned short	*cp;
+		unsigned char	*rp;
+		unsigned short	i;
+
+		for (i = 0, rp = (unsigned char *)cooked_fat /* sic */, cp = cooked_fat;
+		     i < cache_size;
+		     rp += 2, cp ++, i ++) {
+		     	*cp = c2u2 (rp);
+		}
+	}
+  }
+}
+
+
+/* flush the fat cache out to disk
+ */
+void flush_fat ()
+{
+  if (fat_16) {
+	if (big_endian) {
+		unsigned short	*cp;
+		unsigned char	*rp;
+		unsigned short	i;
+
+		for (i = 0, rp = (unsigned char *)cooked_fat /* sic */, cp = cooked_fat;
+		     i < cache_size;
+		     rp += 2, cp ++, i ++) {
+		     	*rp = *cp;
+		     	*(rp + 1) = *cp >> 8;
+		}
+	}
+	disk_io (WRITE, FAT_START + fat_low * 2, (void *)cooked_fat, cache_size * 2);
+	disk_io (WRITE, FAT_START + fat_size + fat_low * 2, (void *)cooked_fat, cache_size * 2);
+  } else {
+  	unsigned short	*cp;
+  	unsigned char	*rp;
+  	unsigned short	i;
+
+	for (rp = raw_fat, cp = cooked_fat, i = 0;
+	     i < cache_size;
+	     rp += 3, cp += 2, i += 2) {
+	     	*rp = *cp;
+	     	*(rp + 1) = ((*cp & 0xf00) >> 8) |
+	     		    ((*(cp + 1) & 0x00f) << 4);
+	     	*(rp + 2) = ((*(cp + 1) & 0xff0) >> 4);
+	}
+	disk_io (WRITE, FAT_START, raw_fat, fat_size);
+	disk_io (WRITE, FAT_START + fat_size, raw_fat, fat_size);
+  }
+}
+
+
+/* make cl_2 the successor of cl_1
+ */
+void link_fat(cl_1, cl_2)
+unsigned int cl_1;
+unsigned int cl_2;
+{
+  if (cl_1 < fat_low || cl_1 > fat_high) {
+  	if (fat_dirty) flush_fat ();
+  	read_fat (cl_1);
+  }
+  cooked_fat [cl_1 - fat_low] = cl_2;
+  fat_dirty = TRUE;
+}
+
+
+unsigned short next_cluster(cl_no)
+register unsigned int cl_no;
+{
+  if (cl_no < fat_low || cl_no > fat_high) {
+  	if (fat_dirty) flush_fat ();
+  	read_fat (cl_no);
+  }
+  return cooked_fat [cl_no - fat_low];
+}
+
+char *slash(str)
+register char *str;
+{
+  register char *result = str;
+
+  while (*str)
+	if (*str++ == '/') result = str;
+
+  return result;
+}
+
+void add_path(file, slash_fl)
+char *file;
+BOOL slash_fl;
+{
+  register char *ptr = path;
+
+  while (*ptr) ptr++;
+
+  if (file == NIL_PTR) {
+	if (ptr != path) ptr--;
+	if (ptr != path) do {
+			ptr--;
+		} while (*ptr != '/' && ptr != path);
+	if (ptr != path && !slash_fl) *ptr++ = '/';
+	*ptr = '\0';
+  } else
+	strcpy (ptr, file);
+}
+
+
+void disk_io(op, seek, address, bytes)
+register BOOL op;
+unsigned long seek;
+void *address;
+register unsigned bytes;
+{
+  unsigned int r;
+
+  if (lseek(disk, seek, SEEK_SET) < 0L) {
+	fflush (stdout);
+	fprintf (stderr, "%s: Bad lseek: %s\n", cmnd, strerror (errno));
+	exit(1);
+  }
+  if (op == READ)
+	r = read(disk, (char *) address, bytes);
+  else {
+	r = write(disk, (char *) address, bytes);
+  }
+
+  if (r != bytes) {
+  	fprintf (stderr, "%s: read error: %s\n", cmnd, strerror (errno));
+  	exit (1);
+  }
+}
+
+char dosread_c_rcs_id [] = 
+	"$Id: dosread.c,v 1.2 2005/07/13 10:02:14 beng Exp $";
Index: /trunk/minix/commands/ibm/fdisk.c
===================================================================
--- /trunk/minix/commands/ibm/fdisk.c	(revision 9)
+++ /trunk/minix/commands/ibm/fdisk.c	(revision 9)
@@ -0,0 +1,1009 @@
+/* fdisk - partition a hard disk	Author: Jakob Schripsema */
+
+/* Run this with:
+ *
+ *	fdisk [-hheads] [-ssectors] [device]
+ *
+ * e.g.,
+ *
+ *	fdisk				(to get the default)
+ *	fdisk -h4 -s17 /dev/hd0		(MINIX default)
+ *	fdisk -h4 -s17 c:		(DOS default)
+ *	fdisk -h6 -s25 /dev/hd5		(second drive, probably RLL)
+ *	fdisk junkfile			(to experiment safely)
+ *
+ * The device is opened in read-only mode if the file permissions do not
+ * permit read-write mode, so it is convenient to use a login account with
+ * only read permission to look at the partition table safely.
+ *
+ * Compile with:
+ *
+ *	cc -i -o fdisk fdisk.c		(MINIX)
+ *	cl -DDOS fdisk.c		(DOS with MS C compiler)
+ *
+ * This was modified extensively by Bruce Evans 28 Dec 89.
+ * The new version has not been tried with DOS.  The open modes are suspect
+ * (everyone should convert to use fcntl.h).
+ *
+ * Changed 18 Dec 92 by Kees J. Bot: Bootstrap code and geometry from device.
+ *
+ * modified 01 March 95 by asw: updated list of known partition types. Also
+ * changed display format slightly to allow for partition type names of
+ * up to 9 chars (previous format allowed for 7, but there were already
+ * some 8 char names in the list).
+*/
+
+#include <sys/types.h>
+#include <ibm/partition.h>
+#include <minix/partition.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+#ifdef DOS
+#include <dos.h>
+#define DEFAULT_DEV	"c:"
+#define LOAD_OPEN_MODE	0x8000
+#define SAVE_CREAT_MODE	0644
+#else
+#define DEFAULT_DEV	"/dev/hd0"
+#define LOAD_OPEN_MODE	0
+#define SAVE_CREAT_MODE	0644
+#define UNIX			/* for MINIX */
+#endif
+
+/* Constants */
+
+#define	DEFAULT_NHEAD	4	/* # heads		 */
+#define	DEFAULT_NSEC	17	/* sectors / track	 */
+#define SECSIZE		512	/* sector size		 */
+#define	OK		0
+#define	ERR		1
+
+#define CYL_MASK	0xc0	/* mask to extract cyl bits from sec field */
+#define CYL_SHIFT	2	/* shift to extract cyl bits from sec field */
+#define SEC_MASK	0x3f	/* mask to extract sec bits from sec field */
+
+/* Globals  */
+char rawsecbuf[SECSIZE + sizeof(long)];
+char *secbuf;
+int badbases;
+int badsizes;
+int badorders;
+char *devname;
+int nhead;
+int nsec;
+int ncyl = 1024;
+int readonly;
+int override= 0;
+
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(void getgeom, (void));
+_PROTOTYPE(int getboot, (char *buffer));
+_PROTOTYPE(int putboot, (char *buffer));
+_PROTOTYPE(int load_from_file, (void));
+_PROTOTYPE(int save_to_file, (void));
+_PROTOTYPE(int dpl_partitions, (int rawflag));
+_PROTOTYPE(int chk_table, (void));
+_PROTOTYPE(int sec_to_hst, (long logsec, unsigned char *hd, unsigned char *sec,
+							 unsigned char *cyl));
+_PROTOTYPE(int mark_partition, (struct part_entry *pe));
+_PROTOTYPE(int change_partition, (struct part_entry *entry));
+_PROTOTYPE(int get_a_char, (void));
+_PROTOTYPE(int print_menu, (void));
+_PROTOTYPE(void adj_base, (struct part_entry *pe));
+_PROTOTYPE(void adj_size, (struct part_entry *pe));
+_PROTOTYPE(struct part_entry *ask_partition, (void));
+_PROTOTYPE(void footnotes, (void));
+_PROTOTYPE(int get_an_int, (char *prompt, int *intptr));
+_PROTOTYPE(void list_part_types, (void));
+_PROTOTYPE(void mark_npartition, (struct part_entry *pe));
+_PROTOTYPE(int mygets, (char *buf, int length));
+_PROTOTYPE(char *systype, (int type));
+_PROTOTYPE(void toggle_active, (struct part_entry *pe));
+_PROTOTYPE(void usage, (void));
+
+/* One featureful master bootstrap. */
+char bootstrap[] = {
+0353,0001,0000,0061,0300,0216,0330,0216,0300,0372,0216,0320,0274,0000,0174,0373,
+0275,0276,0007,0211,0346,0126,0277,0000,0006,0271,0000,0001,0374,0363,0245,0352,
+0044,0006,0000,0000,0264,0002,0315,0026,0250,0010,0164,0033,0350,0071,0001,0174,
+0007,0060,0344,0315,0026,0242,0205,0007,0054,0060,0074,0012,0163,0363,0120,0350,
+0046,0001,0205,0007,0130,0353,0012,0240,0002,0006,0204,0300,0165,0003,0351,0147,
+0000,0230,0262,0005,0366,0362,0262,0200,0000,0302,0210,0340,0120,0350,0234,0000,
+0163,0003,0351,0147,0000,0130,0054,0001,0175,0003,0351,0141,0000,0276,0276,0175,
+0211,0357,0271,0040,0000,0363,0245,0200,0301,0004,0211,0356,0215,0174,0020,0070,
+0154,0004,0164,0016,0213,0135,0010,0053,0134,0010,0213,0135,0012,0033,0134,0012,
+0163,0014,0212,0044,0206,0144,0020,0210,0044,0106,0071,0376,0162,0364,0211,0376,
+0201,0376,0356,0007,0162,0326,0342,0322,0211,0356,0264,0020,0366,0344,0001,0306,
+0200,0174,0004,0001,0162,0026,0353,0021,0204,0322,0175,0041,0211,0356,0200,0174,
+0004,0000,0164,0013,0366,0004,0200,0164,0006,0350,0070,0000,0162,0053,0303,0203,
+0306,0020,0201,0376,0376,0007,0162,0346,0350,0215,0000,0211,0007,0376,0302,0204,
+0322,0174,0023,0315,0021,0321,0340,0321,0340,0200,0344,0003,0070,0342,0167,0355,
+0350,0011,0000,0162,0350,0303,0350,0003,0000,0162,0146,0303,0211,0356,0214,0134,
+0010,0214,0134,0012,0277,0003,0000,0122,0006,0127,0264,0010,0315,0023,0137,0007,
+0200,0341,0077,0376,0306,0210,0310,0366,0346,0211,0303,0213,0104,0010,0213,0124,
+0012,0367,0363,0222,0210,0325,0366,0361,0060,0322,0321,0352,0321,0352,0010,0342,
+0210,0321,0376,0301,0132,0210,0306,0273,0000,0174,0270,0001,0002,0315,0023,0163,
+0020,0200,0374,0200,0164,0011,0117,0174,0006,0060,0344,0315,0023,0163,0270,0371,
+0303,0201,0076,0376,0175,0125,0252,0165,0001,0303,0350,0013,0000,0243,0007,0353,
+0005,0350,0004,0000,0227,0007,0353,0376,0136,0255,0126,0211,0306,0254,0204,0300,
+0164,0011,0264,0016,0273,0001,0000,0315,0020,0353,0362,0303,0057,0144,0145,0166,
+0057,0150,0144,0077,0010,0000,0015,0012,0000,0116,0157,0156,0145,0040,0141,0143,
+0164,0151,0166,0145,0015,0012,0000,0122,0145,0141,0144,0040,0145,0162,0162,0157,
+0162,0040,0000,0116,0157,0164,0040,0142,0157,0157,0164,0141,0142,0154,0145,0040,
+0000,0000,
+};
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+  int argn;
+  char *argp;
+  int ch;
+
+  /* Init */
+
+  nhead = DEFAULT_NHEAD;
+  nsec = DEFAULT_NSEC;
+  for (argn = 1; argn < argc && (argp = argv[argn])[0] == '-'; ++argn) {
+	if (argp[1] == 'h')
+		nhead = atoi(argp + 2);
+	else
+		if (argp[1] == 's') nsec = atoi(argp + 2);
+	else
+		usage();
+	override= 1;
+  }
+
+  if (argn == argc)
+	devname = DEFAULT_DEV;
+  else if (argn == argc - 1)
+	devname = argv[argn];
+  else
+	usage();
+
+  /* Align the sector buffer in such a way that the partition table is at
+   * a mod 4 offset in memory.  Some weird people add alignment checks to
+   * their Minix!
+   */
+  secbuf = rawsecbuf;
+  while ((long)(secbuf + PART_TABLE_OFF) % sizeof(long) != 0) secbuf++;
+
+  getgeom();
+  getboot(secbuf);
+  chk_table();
+
+  do {
+	putchar('\n');
+	dpl_partitions(0);
+	printf(
+	  "\n(Enter 'h' for help.  A null line will abort any operation) ");
+	ch = get_a_char();
+	putchar('\n');
+	switch (ch) {
+	    case '+':	footnotes();			break;
+	    case 'a':	toggle_active(ask_partition());	break;
+	    case 'B':	adj_base(ask_partition()); 	break;
+	    case 'c':	change_partition(ask_partition());	break;
+	    case 'h':	print_menu();			break;
+	    case 'l':	load_from_file();	  	break;
+	    case 'm':	mark_partition(ask_partition());	break;
+	    case 'n':	mark_npartition(ask_partition());	break;
+	    case 'p':	dpl_partitions(1);  		break;
+	    case 0:
+	    case 'q':	exit(0);
+	    case 'S':	adj_size(ask_partition()); 	break;
+	    case 's':	save_to_file();	  		break;
+	    case 't':	list_part_types();	 	break;
+	    case 'v':
+		printf("Partition table is %svalid\n",
+			chk_table() == OK ? "" : "in");
+		break;
+	    case 'w':
+		if (readonly)
+			printf("Write disabled\n");
+		else if(chk_table() == OK) {
+			putboot(secbuf);
+			printf(
+	"Partition table has been updated and the file system synced.\n");
+			printf("Please reboot now.\n");
+			exit(0);
+		} else
+			printf("Not written\n");
+		break;
+	    default:	printf(" %c ????\n", ch);	break;
+  	}
+  }
+  while (1);
+}
+
+
+#ifdef UNIX
+
+void getgeom()
+{
+  struct partition geom;
+  int fd, r;
+
+  if (override) return;
+
+  if ((fd= open(devname, O_RDONLY)) < 0) return;
+
+  r = ioctl(fd, DIOCGETP, &geom);
+  close(fd);
+  if (r < 0) return;
+
+  nhead = geom.heads;
+  nsec = geom.sectors;
+  ncyl = geom.cylinders;
+
+  printf("Geometry of %s: %dx%dx%d\n", devname, ncyl, nhead, nsec);
+}
+
+static int devfd;
+
+getboot(buffer)
+char *buffer;
+{
+  devfd = open(devname, 2);
+  if (devfd < 0) {
+	printf("No write permission on %s\n", devname);
+	readonly = 1;
+	devfd = open(devname, 0);
+  }
+  if (devfd < 0) {
+	printf("Cannot open device %s\n", devname);
+	exit(1);
+  }
+  if (read(devfd, buffer, SECSIZE) != SECSIZE) {
+	printf("Cannot read boot sector\n");
+	exit(1);
+  }
+  if (* (unsigned short *) &buffer[510] != 0xAA55) {
+	printf("Invalid boot sector on %s.\n", devname);
+	printf("Partition table reset and boot code installed.\n");
+	memset(buffer, 0, 512);
+	memcpy(buffer, bootstrap, sizeof(bootstrap));
+	* (unsigned short *) &buffer[510] = 0xAA55;
+  }
+}
+
+putboot(buffer)
+char *buffer;
+{
+  if (lseek(devfd, 0L, 0) < 0) {
+	printf("Seek error during write\n");
+	exit(1);
+  }
+  if (write(devfd, buffer, SECSIZE) != SECSIZE) {
+	printf("Write error\n");
+	exit(1);
+  }
+  sync();
+}
+
+#endif
+
+
+load_from_file()
+{
+/* Load buffer from file  */
+
+  char file[80];
+  int fd;
+
+  printf("Enter name of file to load from: ");
+  if (!mygets(file, (int) sizeof file)) return;
+  fd = open(file, LOAD_OPEN_MODE);
+  if (fd < 0) {
+	printf("Cannot open %s\n", file);
+	return;
+  }
+  if (read(fd, secbuf, SECSIZE) != SECSIZE || close(fd) != 0) {
+	printf("Read error\n");
+	exit(1);
+  }
+  printf("Loaded from %s OK\n", file);
+  chk_table();
+}
+
+
+save_to_file()
+{
+/* Save to file  */
+
+  char file[80];
+  int fd;
+
+  printf("Enter name of file to save to: ");
+  if (!mygets(file, (int) sizeof file)) return;
+  if(chk_table() != OK) printf("Saving anyway\n");
+  fd = creat(file, SAVE_CREAT_MODE);
+#ifdef DOS
+  if (fd < 0) {
+	printf("Cannot creat %s\n", file);
+	return;
+  }
+  close(fd);
+  fd = open(file, 0x8001);
+#endif
+  if (fd < 0)
+	printf("Cannot open %s\n", file);
+  else if (write(fd, secbuf, SECSIZE) != SECSIZE || close(fd) != 0)
+	printf("Write error\n");
+  else
+	printf("Saved to %s OK\n", file);
+}
+
+
+dpl_partitions(rawflag)
+int rawflag;
+{
+/* Display partition table */
+
+  char active[5];
+  char basefootnote;
+  int cyl_mask;
+  int devnum;
+  char *format;
+  int i;
+  int i1;
+  char orderfootnote;
+  struct part_entry *pe;
+  struct part_entry *pe1;
+  int sec_mask;
+  char sizefootnote;
+  char type[10];
+
+  badbases = 0;
+  badsizes = 0;
+  badorders = 0;
+  if (rawflag) {
+	cyl_mask = 0;		/* no contribution of cyl to sec */
+	sec_mask = 0xff;
+        format =
+"%2d   %3d%c  %4s %-9s  x%02x %3d  x%02x   x%02x %3d  x%02x %7ld%c%7ld %7ld%c\n";
+  } else {
+	cyl_mask = CYL_MASK;
+	sec_mask = SEC_MASK;
+	format =
+"%2d   %3d%c  %4s %-9s %4d %3d %3d   %4d %3d  %3d %7ld%c%7ld %7ld%c\n";
+  }
+  printf(
+"                          ----first----  -----last----  --------sectors-------\n"
+	);
+  printf(
+"Num Sorted Act  Type     Cyl Head Sec   Cyl Head Sec    Base    Last    Size\n"
+	);
+  pe = (struct part_entry *) &secbuf[PART_TABLE_OFF];
+  for (i = 1; i <= NR_PARTITIONS; i++, pe++) {
+	if (rawflag) {
+		sprintf(active, "0x%02x", pe->bootind);
+		sprintf(type, "0x%02x", pe->sysind);
+	} else {
+		sprintf(active, "%s", pe->bootind == ACTIVE_FLAG ? "A  " : "");
+		sprintf(type, "%s", systype(pe->sysind));
+	}
+
+	/* Prepare warnings about confusing setups from old versions. */
+	basefootnote = orderfootnote = sizefootnote = ' ';
+	if (pe->sysind == MINIX_PART && pe->lowsec & 1) {
+		basefootnote = '+';
+		++badbases;
+	}
+	if (pe->size & 1) {
+		sizefootnote = '-';
+		++badsizes;
+	}
+
+	/* Calculate the "device numbers" resulting from the misguided sorting
+	 * in the wini drivers.  The drivers use this conditional for
+	 * swapping wn[j] > wn[j+1]:
+	 *
+	 *	if ((wn[j].wn_low == 0 && wn[j+1].wn_low != 0) ||
+	 *	    (wn[j].wn_low > wn[j+1].wn_low && wn[j+1].wn_low != 0)) {
+	 *
+	 * which simplifies to:
+	 *
+	 *	if (wn[j+1].wn_low != 0 &&
+	 *	    (wn[j].wn_low == 0 || wn[j].wn_low > wn[j+1].wn_low)) {
+	 */
+	devnum = 1;
+	for (i1 = 1, pe1 = (struct part_entry *) &secbuf[PART_TABLE_OFF];
+	     i1 <= NR_PARTITIONS; ++i1, ++pe1)
+		if (pe1->lowsec == 0 && pe->lowsec == 0 && pe1 < pe ||
+		    pe1->lowsec != 0 &&
+		    (pe->lowsec == 0 || pe->lowsec > pe1->lowsec))
+			++devnum;	/* pe1 contents < pe contents */
+	if (devnum != i) {
+		orderfootnote = '#';
+		++badorders;
+	}
+
+	printf(format,
+		i,
+		devnum,
+		orderfootnote,
+		active,
+		type,
+		pe->start_cyl + ((pe->start_sec & cyl_mask) << CYL_SHIFT),
+		pe->start_head,
+		pe->start_sec & sec_mask,
+		pe->last_cyl + ((pe->last_sec & cyl_mask) << CYL_SHIFT),
+		pe->last_head,
+		pe->last_sec & sec_mask,
+		pe->lowsec,
+		basefootnote,
+		pe->lowsec + (pe->size == 0 ? 0 : pe->size - 1),
+		pe->size,
+		sizefootnote);
+  }
+}
+
+
+int chk_table()
+{
+/* Check partition table */
+
+  int active;
+  unsigned char cylinder;
+  unsigned char head;
+  int i;
+  int i1;
+  int maxhead;
+  int maxsec;
+  struct part_entry *pe;
+  struct part_entry *pe1;
+  unsigned char sector;
+  int seenpart;
+  int status;
+
+  active = 0;
+  maxhead = 0;
+  maxsec = 0;
+  pe = (struct part_entry *) &secbuf[PART_TABLE_OFF];
+  seenpart = 0;
+  status = OK;
+  for (i = 1; i <= NR_PARTITIONS; i++, ++pe) {
+	if (pe->bootind == ACTIVE_FLAG) active++;
+	sec_to_hst(pe->lowsec, &head, &sector, &cylinder);
+	if (pe->size == 0 && pe->lowsec == 0) sector = 0;
+	if (head != pe->start_head || sector != pe->start_sec ||
+	    cylinder != pe->start_cyl) {
+		printf("Inconsistent base in partition %d.\n", i);
+		printf("Suspect head and sector parameters.\n");
+		status = ERR;
+	}
+	if (pe->size != 0 || pe->lowsec != 0)
+	      sec_to_hst(pe->lowsec + pe->size - 1, &head, &sector, &cylinder);
+	if (head != pe->last_head || sector != pe->last_sec ||
+	    cylinder != pe->last_cyl) {
+		printf("Inconsistent size in partition %d.\n", i);
+		printf("Suspect head and sector parameters.\n");
+		status = ERR;
+	}
+	if (pe->size == 0) continue;
+	seenpart = 1;
+	for (i1 = i + 1, pe1 = pe + 1; i1 <= NR_PARTITIONS; ++i1, ++pe1) {
+		if (pe->lowsec >= pe1->lowsec &&
+		    pe->lowsec < pe1->lowsec + pe1->size ||
+		    pe->lowsec + pe->size - 1 >= pe1->lowsec &&
+		    pe->lowsec + pe->size - 1 < pe1->lowsec + pe1->size)
+		{
+			printf("Overlap between partitions %d and %d\n",
+				i, i1);
+			status = ERR;
+		}
+	}
+	if (pe->lowsec + pe->size < pe->lowsec) {
+		printf("Overflow from preposterous size in partition %d.\n",
+			i);
+		status = ERR;
+	}
+	if (maxhead < pe->start_head) maxhead = pe->start_head;
+	if (maxhead < pe->last_head) maxhead = pe->last_head;
+	if (maxsec < (pe->start_sec & SEC_MASK))
+		maxsec = (pe->start_sec & SEC_MASK);
+	if (maxsec < (pe->last_sec & SEC_MASK))
+		maxsec = (pe->last_sec & SEC_MASK);
+  }
+  if (seenpart) {
+	if (maxhead + 1 != nhead || maxsec != nsec) {
+		printf(
+	"Disk appears to have mis-specified number of heads or sectors.\n");
+		printf("Try  fdisk -h%d -s%d %s  instead of\n",
+			maxhead + 1, maxsec, devname);
+		printf("     fdisk -h%d -s%d %s\n", nhead, nsec, devname);
+		seenpart = 0;
+	}
+  } else {
+	printf(
+	"Empty table - skipping test on number of heads and sectors.\n");
+	printf("Assuming %d heads and %d sectors.\n", nhead, nsec);
+  }
+  if (!seenpart) printf("Do not write the table if you are not sure!.\n");
+  if (active > 1) {
+	printf("%d active partitions\n", active);
+	status = ERR;	
+  }
+  return(status);
+}
+
+sec_to_hst(logsec, hd, sec, cyl)
+long logsec;
+unsigned char *hd, *sec, *cyl;
+{
+/* Convert a logical sector number to  head / sector / cylinder */
+
+  int bigcyl;
+
+  bigcyl = logsec / (nhead * nsec);
+  *sec = (logsec % nsec) + 1 + ((bigcyl >> CYL_SHIFT) & CYL_MASK);
+  *cyl = bigcyl;
+  *hd = (logsec % (nhead * nsec)) / nsec;
+}
+
+mark_partition(pe)
+struct part_entry *pe;
+{
+/* Mark a partition as being of type MINIX. */
+
+  if (pe != NULL) {
+	pe->sysind = MINIX_PART;
+	printf("Partition type is now MINIX\n");
+  }
+}
+
+change_partition(entry)
+struct part_entry *entry;
+{
+/* Get partition info : first & last cylinder */
+
+  int first, last;
+  long low, high;
+  int ch;
+
+  if (entry == NULL) return;
+  while (1) {
+	if (!get_an_int("\tEnter first cylinder (an integer >= 0): ", &first))
+		return;
+	if (first >= 0) break;
+	printf("\t\tThat looks like %d which is negative\n", first);
+  }
+  while (1) {
+	if (!get_an_int(
+	"\tEnter last cylinder (an integer >= the first cylinder): ", &last))
+		return;
+	if (last >= first) break;
+	printf("\t\tThat looks like %d which is too small\n", last);
+  }
+  if (first == 0 && last == 0) {
+	entry->bootind = 0;
+	entry->start_head = 0;
+	entry->start_sec = 0;
+	entry->start_cyl = 0;
+	entry->sysind = NO_PART;
+	entry->last_head = 0;
+	entry->last_sec = 0;
+	entry->last_cyl = 0;
+	entry->lowsec = 0;
+	entry->size = 0;
+	printf("Partition deleted\n");
+	return;
+  }
+  low = first & 0xffff;
+  low = low * nsec * nhead;
+  if (low == 0) low = 1;	/* sec0 is master boot record */
+  high = last & 0xffff;
+  high = (high + 1) * nsec * nhead - 1;
+  entry->lowsec = low;
+  entry->size = high - low + 1;
+  if (entry->size & 1) {
+	/* Adjust size to even since Minix works with blocks of 2 sectors. */
+	--high;
+	--entry->size;
+	printf("Size reduced by 1 to make it even\n");
+  }
+  sec_to_hst(low, &entry->start_head, &entry->start_sec, &entry->start_cyl);
+  sec_to_hst(high, &entry->last_head, &entry->last_sec, &entry->last_cyl);
+  printf("Base of partition changed to %ld, size changed to %ld\n",
+	 entry->lowsec, entry->size);
+
+  /* Accept the MINIX partition type.  Usually ignore foreign types, so this
+   * fdisk can be used on foreign partitions.  Don't allow NO_PART, because
+   * many DOS fdisks crash on it.
+   */
+  if (entry->sysind == NO_PART) {
+	entry->sysind = MINIX_PART;
+	printf("Partition type changed from None to MINIX\n");
+  } else if (entry->sysind == MINIX_PART)
+	printf("Leaving partition type as MINIX\n");
+  else while (1) {
+	printf("\tChange partition type from %s to MINIX? (y/n) ",
+		systype(entry->sysind));
+	ch = get_a_char();
+	if (ch == 0 || ch == 'n') {
+		printf("Leaving partition type as %s\n",
+			systype(entry->sysind));
+		break;
+	} else if (ch == 'y') {
+		entry->sysind = MINIX_PART;
+		printf("Partition type changed from %s to MINIX\n",
+			systype(entry->sysind));
+		break;
+	}
+  }
+
+  if (entry->bootind == ACTIVE_FLAG)
+	printf("Leaving partition active\n");
+  else while (1) {
+	printf("\tChange partition to active? (y/n) ");
+	ch = get_a_char();
+	if (ch == 0 || ch == 'n') {
+		printf("Leaving partition inactive\n");
+		break;
+	} else if (ch == 'y') {
+		toggle_active(entry);
+		break;
+	}
+  }
+}
+
+get_a_char()
+{
+/* Read 1 character and discard rest of line */
+
+  char buf[80];
+  int ch;
+
+  if (!mygets(buf, (int) sizeof buf)) return(0);
+  return(*buf);
+}
+
+print_menu()
+{
+  printf("Type a command letter, then a carriage return:\n");
+  printf("   + - explain any footnotes (+, -, #)\n");
+  printf("   a - toggle an active flag\n");
+  printf("   B - adjust a base sector\n");
+  printf("   c - change a partition\n");
+  printf("   l - load boot block (including partition table) from a file\n");
+  printf("   m - mark a partition as a MINIX partition\n");
+  printf("   n - mark a partition as a non-MINIX partition\n");
+  printf("   p - print raw partition table\n");
+  printf("   q - quit without making any changes\n");
+  printf("   S - adjust a size (by changing the last sector)\n");
+  printf("   s - save boot block (including partition table) on a file\n");
+  printf("   t - print known partition types\n");
+  printf("   v - verify partition table\n");
+ if (readonly)
+  printf("   w - write (disabled)\n");
+ else
+  printf("   w - write changed partition table back to disk and exit\n");
+}
+
+
+/* Here are the DOS routines for reading and writing the boot sector. */
+
+#ifdef DOS
+
+union REGS regs;
+struct SREGS sregs;
+int drivenum;
+
+getboot(buffer)
+char *buffer;
+{
+/* Read boot sector  */
+
+  segread(&sregs);		/* get ds */
+
+  if (devname[1] != ':') {
+	printf("Invalid drive %s\n", devname);
+	exit(1);
+  }
+  if (*devname >= 'a') *devname += 'A' - 'a';
+  drivenum = (*devname - 'C') & 0xff;
+  if (drivenum < 0 || drivenum > 7) {
+	printf("Funny drive number %d\n", drivenum);
+	exit(1);
+  }
+  regs.x.ax = 0x201;		/* read 1 sectors	 */
+  regs.h.ch = 0;		/* cylinder		 */
+  regs.h.cl = 1;		/* first sector = 1	 */
+  regs.h.dh = 0;		/* head = 0		 */
+  regs.h.dl = 0x80 + drivenum;	/* drive = 0		 */
+  sregs.es = sregs.ds;		/* buffer address	 */
+  regs.x.bx = (int) buffer;
+
+  int86x(0x13, &regs, &regs, &sregs);
+  if (regs.x.cflag) {
+	printf("Cannot read boot sector\n");
+	exit(1);
+  }
+}
+
+
+putboot(buffer)
+char *buffer;
+{
+/* Write boot sector  */
+
+  regs.x.ax = 0x301;		/* read 1 sectors	 */
+  regs.h.ch = 0;		/* cylinder		 */
+  regs.h.cl = 1;		/* first sector = 1	 */
+  regs.h.dh = 0;		/* head = 0		 */
+  regs.h.dl = 0x80 + drivenum;	/* drive = 0		 */
+  sregs.es = sregs.ds;		/* buffer address	 */
+  regs.x.bx = (int) buffer;
+
+  int86x(0x13, &regs, &regs, &sregs);
+  if (regs.x.cflag) {
+	printf("Cannot write boot sector\n");
+	exit(1);
+  }
+}
+
+#endif
+
+void adj_base(pe)
+struct part_entry *pe;
+{
+/* Adjust base sector of partition, usually to make it even. */
+
+  int adj;
+
+  if (pe == NULL) return;
+  while (1) {
+	
+	if (!get_an_int("\tEnter adjustment to base (an integer): ", &adj))
+		return;
+	if (pe->lowsec + adj < 1)
+		printf(
+    "\t\tThat would make the base %d and too small\n", pe->lowsec + adj);
+	else if (pe->size - adj < 1)
+		printf(
+    "\t\tThat would make the size %d and too small\n", pe->size - adj);
+	else
+		break;
+  }
+  pe->lowsec += adj; 
+  pe->size -= adj;
+  sec_to_hst(pe->lowsec, &pe->start_head, &pe->start_sec, &pe->start_cyl);
+  printf("Base of partition adjusted to %ld, size adjusted to %ld\n",
+	 pe->lowsec, pe->size);
+}
+
+void adj_size(pe)
+struct part_entry *pe;
+{
+/* Adjust size of partition by reducing high sector. */
+
+  int adj;
+
+  if (pe == NULL) return;
+  while (1) {
+	if (!get_an_int("\tEnter adjustment to size (an integer): ", &adj))
+		return;
+	if (pe->size + adj >= 1) break;
+	printf("\t\tThat would make the size %d and too small \n",
+		pe->size + adj);
+  }
+  pe->size += adj;
+  sec_to_hst(pe->lowsec + pe->size - 1,
+	     &pe->last_head, &pe->last_sec, &pe->last_cyl);
+  printf("Size of partition adjusted to %ld\n", pe->size);
+}
+
+struct part_entry *ask_partition()
+{
+/* Ask for a valid partition number and return its entry. */
+
+  int num;
+
+  while (1) {
+	
+	if (!get_an_int("Enter partition number (1 to 4): ", &num))
+		return(NULL);
+	if (num >= 1 && num <= NR_PARTITIONS) break;
+	printf("\tThat does not look like 1 to 4\n");
+  }
+  printf("Partition %d\n", num);
+  return((struct part_entry *) &secbuf[PART_TABLE_OFF] + (num - 1));
+}
+
+void footnotes()
+{
+/* Explain the footnotes. */
+
+  if (badbases != 0) {
+	printf(
+"+ The old Minix wini drivers (before V1.5) discarded odd base sectors.\n");
+	printf(
+"  This causes some old (Minix) file systems to be offset by 1 sector.\n");
+	printf(
+"  To use these with the new drivers, increase the base by 1 using 'B'.\n");
+  }
+
+  if (badsizes != 0) {
+	if (badbases != 0) putchar('\n');
+	printf(
+"- Minix cannot access the last sector on an odd-sized partition.  This\n");
+	printf(
+"  causes trouble for programs like dosread.  This program will by default\n");
+	printf(
+"  only create partitions with even sizes.  If possible, the current odd\n");
+	printf(
+"  sizes should be decreased by 1 using 'S'.  This is safe for all Minix\n");
+	printf(
+"  partitions, and may be safe for other partitions which are about to be\n");
+	printf(
+"  reformatted.\n");
+  }
+
+  if (badorders!= 0 ) {
+	if (badbases != 0 || badsizes != 0) putchar('\n');
+	printf(
+"# The partitions are in a funny order. This is normal if they were created\n");
+	printf(
+"  by DOS fdisks prior to DOS 3.3.  The Minix wini drivers further confuse\n");
+	printf(
+"  the order by sorting the partitions on their base.  Be careful if the\n");
+	printf(
+"  device numbers of unchanged partitions have changed.\n");
+  }
+}
+
+int get_an_int(prompt, intptr)
+char *prompt;
+int *intptr;
+{
+/* Read an int from the start of line of stdin, discard rest of line. */
+
+  char buf[80];
+
+  while (1) {
+	printf("%s", prompt);
+	if (!mygets(buf, (int) sizeof buf)) return(0);
+	if ((sscanf(buf, "%d", intptr)) == 1) return(1);
+	printf("\t\tThat does not look like an integer\n");
+  }
+}
+
+void list_part_types()
+{
+/* Print all known partition types. */
+
+  int column;
+  int type;
+
+  for (column = 0, type = 0; type < 0x100; ++type)
+	if (strcmp(systype(type), "Unknown") != 0) {
+		printf("0x%02x: %-9s", type, systype(type));
+		column += 16;
+		if (column < 80)
+			putchar(' ');
+		else {
+			putchar('\n');
+			column = 0;
+		}
+	}
+  if (column != 0) putchar('\n');
+}
+
+void mark_npartition(pe)
+struct part_entry *pe;
+{
+/* Mark a partition with arbitrary type. */
+
+  char buf[80];
+  unsigned type;
+
+  if (pe == NULL) return;
+  printf("\nKnown partition types are:\n\n");
+  list_part_types();
+  while (1) {
+	printf("\nEnter partition type (in 2-digit hex): ");
+	if (!mygets(buf, (int) sizeof buf)) return;
+	if (sscanf(buf, "%x", &type) != 1)
+		printf("Invalid hex number\n");
+  	else if (type >= 0x100)
+		printf("Hex number too large\n");
+	else
+		break;
+  }
+  pe->sysind = type;
+  printf("Partition type changed to 0x%02x (%s)\n", type, systype(type));
+}
+
+int mygets(buf, length)
+char *buf;
+int length;			/* as for fgets(), but must be >= 2 */
+{
+/* Get a non-empty line of maximum length 'length'. */
+
+  while (1) {
+	fflush(stdout);
+	if (fgets(buf, length, stdin) == NULL) {
+		putchar('\n');
+		return(0);
+	}
+	if (strrchr(buf, '\n') != NULL) *strrchr(buf, '\n') = 0;
+	if (*buf != 0) return(1);
+	printf("Use the EOF character to create a null line.\n");
+	printf("Otherwise, please type something before the newline: ");
+  }
+}
+
+char *systype(type)
+int type;
+{
+/* Convert system indicator into system name. */
+/* asw 01.03.95: added types based on info in kjb's part.c and output
+ * from Linux (1.0.8) fdisk. Note comments here, there are disagreements.
+*/
+  switch(type) {
+	case NO_PART: 
+	           return("None");
+	case 1:    return("DOS-12");
+	case 2:    return("XENIX");
+	case 3:    return("XENIX usr");
+	case 4:    return("DOS-16");
+	case 5:    return("DOS-EXT");
+	case 6:    return("DOS-BIG");
+	case 7:    return("HPFS");
+	case 8:    return("AIX");
+	case 9:    return("COHERENT");	/* LINUX says AIX bootable */
+	case 0x0a: return("OS/2");	/* LINUX says OPUS */
+	case 0x10: return("OPUS");
+	case 0x40: return("VENIX286");
+	case 0x51: return("NOVELL?");
+	case 0x52: return("MICROPORT");
+	case 0x63: return("386/IX");	/*LINUX calls this GNU HURD */
+	case 0x64: return("NOVELL286");
+	case 0x65: return("NOVELL386");
+	case 0x75: return("PC/IX");
+	case 0x80: return("MINIX old");
+	case 0x81: return("MINIX");
+	case 0x82: return("LINUXswap");
+	case 0x83: return("LINUX");
+	case 0x93: return("AMOEBA");
+	case 0x94: return("AMOEBAbad");
+	case 0xa5: return("386BSD");
+	case 0xb7: return("BSDI");
+	case 0xb8: return("BSDIswap");
+	case 0xc7: return("Syrinx");
+	case 0xDB: return("CP/M");
+	case 0xe1: return("DOS acc");
+	case 0xe3: return("DOS r/o");
+	case 0xf2: return("DOS 2ary");
+	case 0xFF: return("Badblocks");
+	default:   return("Unknown");
+  }
+}
+
+void toggle_active(pe)
+struct part_entry *pe;
+{
+/* Toggle active flag of a partition. */
+
+  if (pe == NULL) return;
+  pe->bootind = (pe->bootind == ACTIVE_FLAG) ? 0 : ACTIVE_FLAG;
+  printf("Partition changed to %sactive\n", pe->bootind ? "" : "in");
+}
+
+void usage()
+{
+/* Print usage message and exit. */
+
+  printf("Usage: fdisk [-hheads] [-ssectors] [device]\n");
+  exit(1);
+}
+
Index: /trunk/minix/commands/ibm/format.c
===================================================================
--- /trunk/minix/commands/ibm/format.c	(revision 9)
+++ /trunk/minix/commands/ibm/format.c	(revision 9)
@@ -0,0 +1,422 @@
+/*	format 1.1 - format PC floppy disk		Author: Kees J. Bot
+ *								5 Mar 1994
+ */
+#define nil 0
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <limits.h>
+#include <ibm/diskparm.h>
+#include <minix/minlib.h>
+
+/* Constants. */
+#define SECTOR_SIZE	512
+#define NR_HEADS	  2
+#define MAX_SECTORS	 18	/* 1.44Mb is the largest. */
+
+/* Name error in <ibm/diskparm.h>, left over from the days floppies were
+ * single sided.
+ */
+#define sectors_per_track	sectors_per_cylinder
+
+/* From floppy device number to drive/type/format-bit and back.  See fd(4). */
+#define isfloppy(dev)		(((dev) & 0xFF00) == 0x0200)
+#define fl_drive(dev)		(((dev) & 0x0003) >> 0)
+#define fl_type(dev)		(((dev) & 0x007C) >> 2)
+#define fl_format(dev)		(((dev) & 0x0080) >> 7)
+#define fl_makedev(drive, type, fmt)	\
+	((dev_t) (0x0200 | ((fmt) << 7) | ((type) << 2) | ((drive) << 0)))
+
+/* Recognize floppy types. */
+#define NR_TYPES		7	/* # non-auto types */
+#define isflauto(type)		((type) == 0)
+#define isfltyped(type)		((unsigned) ((type) - 1) < NR_TYPES)
+#define isflpart(type)		((unsigned) (type) >= 28)
+
+/* Formatting parameters per type.  (Most of these parameters have no use
+ * for formatting, disk_parameter_s probably matches a BIOS parameter table.)
+ */
+typedef struct disk_parameter_s	fmt_params_t;
+
+typedef struct type_parameters {
+	unsigned		media_size;
+	unsigned		drive_size;
+	fmt_params_t		fmt_params;
+} type_parameters_t;
+
+#define DC	0	/* Don't care. */
+
+type_parameters_t parameters[NR_TYPES] = {
+	/* mediasize       s1     off   sec/cyl  dlen       fill    start */
+	/*       drivesize     s2   sizecode  gap    fmtgap     settle    */
+  /* pc */ {  360,  360, { DC, DC, DC, 2,  9, DC, DC, 0x50, 0xF6, DC, DC }},
+  /* at */ { 1200, 1200, { DC, DC, DC, 2, 15, DC, DC, 0x54, 0xF6, DC, DC }},
+  /* qd */ {  360,  720, { DC, DC, DC, 2,  9, DC, DC, 0x50, 0xF6, DC, DC }},
+  /* ps */ {  720,  720, { DC, DC, DC, 2,  9, DC, DC, 0x50, 0xF6, DC, DC }},
+  /* pat */{  360, 1200, { DC, DC, DC, 2,  9, DC, DC, 0x50, 0xF6, DC, DC }},
+  /* qh */ {  720, 1200, { DC, DC, DC, 2,  9, DC, DC, 0x50, 0xF6, DC, DC }},
+  /* PS */ { 1440, 1440, { DC, DC, DC, 2, 18, DC, DC, 0x54, 0xF6, DC, DC }},
+};
+
+/* Per sector ID to be sent to the controller by the driver. */
+typedef struct sector_id {
+	unsigned char	cyl;
+	unsigned char	head;
+	unsigned char	sector;
+	unsigned char	sector_size_code;
+} sector_id_t;
+
+/* Data to be "written" to the driver to format a track.  (lseek to the track
+ * first.)  The first sector contains sector ID's, the second format params.
+ */
+
+typedef struct track_data {
+	sector_id_t	sec_ids[SECTOR_SIZE / sizeof(sector_id_t)];
+	fmt_params_t	fmt_params;
+	char		padding[SECTOR_SIZE - sizeof(fmt_params_t)];
+} track_data_t;
+
+void report(const char *label)
+{
+	fprintf(stderr, "format: %s: %s\n", label, strerror(errno));
+}
+
+void fatal(const char *label)
+{
+	report(label);
+	exit(1);
+}
+
+void format_track(int ffd, unsigned type, unsigned cyl, unsigned head)
+/* Format a single track on a floppy. */
+{
+	type_parameters_t *tparams= &parameters[type - 1];
+	track_data_t track_data;
+	off_t track_pos;
+	unsigned sector;
+	unsigned nr_sectors= tparams->fmt_params.sectors_per_track;
+	sector_id_t *sid;
+
+	memset(&track_data, 0, sizeof(track_data));
+
+	/* Set the sector id's.  (Note that sectors count from 1.) */
+	for (sector= 0; sector <= nr_sectors; sector++) {
+		sid= &track_data.sec_ids[sector];
+
+		sid->cyl= cyl;
+		sid->head= head;
+		sid->sector= sector + 1;
+		sid->sector_size_code= tparams->fmt_params.sector_size_code;
+	}
+
+	/* Format parameters. */
+	track_data.fmt_params= tparams->fmt_params;
+
+	/* Seek to the right track. */
+	track_pos= (off_t) (cyl * NR_HEADS + head) * nr_sectors * SECTOR_SIZE;
+	if (lseek(ffd, track_pos, SEEK_SET) == -1) {
+		fprintf(stderr,
+		"format: seeking to cyl %u, head %u (pos %ld) failed: %s\n",
+			cyl, head, track_pos, strerror(errno));
+		exit(1);
+	}
+
+	/* Format track. */
+	if (write(ffd, &track_data, sizeof(track_data)) < 0) {
+		fprintf(stderr,
+			"format: formatting cyl %d, head %d failed: %s\n",
+			cyl, head, strerror(errno));
+		exit(1);
+	}
+}
+
+void verify_track(int vfd, unsigned type, unsigned cyl, unsigned head)
+/* Verify a track by reading it.  On error read sector by sector. */
+{
+	type_parameters_t *tparams= &parameters[type - 1];
+	off_t track_pos;
+	unsigned sector;
+	unsigned nr_sectors= tparams->fmt_params.sectors_per_track;
+	size_t track_bytes;
+	static char buf[MAX_SECTORS * SECTOR_SIZE];
+	static unsigned bad_count;
+
+	/* Seek to the right track. */
+	track_pos= (off_t) (cyl * NR_HEADS + head) * nr_sectors * SECTOR_SIZE;
+	if (lseek(vfd, track_pos, SEEK_SET) == -1) {
+		fprintf(stderr,
+		"format: seeking to cyl %u, head %u (pos %ld) failed: %s\n",
+			cyl, head, track_pos, strerror(errno));
+		exit(1);
+	}
+
+	/* Read the track whole. */
+	track_bytes= nr_sectors * SECTOR_SIZE;
+	if (read(vfd, buf, track_bytes) == track_bytes) return;
+
+	/* An error occurred, retry sector by sector. */
+	for (sector= 0; sector < nr_sectors; sector++) {
+		if (lseek(vfd, track_pos, SEEK_SET) == -1) {
+			fprintf(stderr,
+	"format: seeking to cyl %u, head %u, sector %u (pos %ld) failed: %s\n",
+				cyl, head, sector, track_pos, strerror(errno));
+			exit(1);
+		}
+
+		switch (read(vfd, buf, SECTOR_SIZE)) {
+		case -1:
+			fprintf(stderr,
+		"format: bad sector at cyl %u, head %u, sector %u (pos %ld)\n",
+				cyl, head, sector, track_pos);
+			bad_count++;
+			break;
+		case SECTOR_SIZE:
+			/* Fine. */
+			break;
+		default:
+			fprintf(stderr, "format: short read at pos %ld\n",
+				track_pos);
+			bad_count++;
+		}
+		track_pos+= SECTOR_SIZE;
+		if (bad_count >= nr_sectors) {
+	fprintf(stderr, "format: too many bad sectors, floppy unusable\n");
+			exit(1);
+		}
+	}
+}
+
+void format_device(unsigned drive, unsigned type, int verify)
+{
+	int ffd, vfd;
+	char *fmt_dev, *ver_dev;
+	struct stat st;
+	unsigned cyl, head;
+	unsigned nr_cyls;
+	type_parameters_t *tparams= &parameters[type - 1];
+	int verbose= isatty(1);
+
+	fmt_dev= tmpnam(nil);
+
+	if (mknod(fmt_dev, S_IFCHR | 0700, fl_makedev(drive, type, 1)) < 0) {
+		fprintf(stderr, "format: making format device failed: %s\n",
+			strerror(errno));
+		exit(1);
+	}
+
+	if ((ffd= open(fmt_dev, O_WRONLY)) < 0 || fstat(ffd, &st) < 0) {
+		report(fmt_dev);
+		(void) unlink(fmt_dev);
+		exit(1);
+	}
+
+	(void) unlink(fmt_dev);
+
+	if (st.st_rdev != fl_makedev(drive, type, 1)) {
+		/* Someone is trying to trick me. */
+		exit(1);
+	}
+
+	if (verify) {
+		ver_dev= tmpnam(nil);
+
+		if (mknod(ver_dev, S_IFCHR | 0700, fl_makedev(drive, type, 0))
+									< 0) {
+			fprintf(stderr,
+				"format: making verify device failed: %s\n",
+				strerror(errno));
+			exit(1);
+		}
+
+		if ((vfd= open(ver_dev, O_RDONLY)) < 0) {
+			report(ver_dev);
+			(void) unlink(ver_dev);
+			exit(1);
+		}
+
+		(void) unlink(ver_dev);
+	}
+
+	nr_cyls= tparams->media_size * (1024 / SECTOR_SIZE) / NR_HEADS
+				/ tparams->fmt_params.sectors_per_track;
+
+	if (verbose) {
+		printf("Formatting a %uk diskette in a %uk drive\n",
+			tparams->media_size, tparams->drive_size);
+	}
+
+	for (cyl= 0; cyl < nr_cyls; cyl++) {
+		for (head= 0; head < NR_HEADS; head++) {
+			if (verbose) {
+				printf(" Cyl. %2u, Head %u\r", cyl, head);
+				fflush(stdout);
+			}
+#if __minix_vmd
+			/* After formatting a track we are too late to format
+			 * the next track.  So we can sleep at most 1/6 sec to
+			 * allow the above printf to get displayed before we
+			 * lock Minix into the floppy driver again.
+			 */
+			usleep(50000);	/* 1/20 sec will do. */
+#endif
+			format_track(ffd, type, cyl, head);
+			if (verify) verify_track(vfd, type, cyl, head);
+		}
+	}
+	if (verbose) fputc('\n', stdout);
+}
+
+void usage(void)
+{
+	fprintf(stderr,
+		"Usage: format [-v] <device> [<media size> [<drive size>]]\n");
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	char *device;
+	unsigned drive;
+	unsigned type;
+	unsigned media_size;
+	unsigned drive_size;
+	int verify= 0;
+	struct stat st0, st;
+	FILE *mfp;
+	char special[PATH_MAX + 1], mounted_on[PATH_MAX + 1];
+	char version[10], rw_flag[10];
+
+	/* Option -v. */
+	while (argc > 1 && argv[1][0] == '-') {
+		char *p;
+
+		for (p= argv[1]; *p == '-' || *p == 'v'; p++) {
+			if (*p == 'v') verify= 1;
+		}
+		if (*p != 0) usage();
+		argc--;
+		argv++;
+		if (strcmp(argv[0], "--") == 0) break;
+	}
+
+	if (argc < 2 || argc > 4) usage();
+
+	/* Check if the caller has read-write permission.  Use the access()
+	 * call to check with the real uid & gid.  This program is usually
+	 * set-uid root.
+	 */
+	device= argv[1];
+	if (stat(device, &st0) < 0
+		|| access(device, R_OK|W_OK) < 0
+		|| stat(device, &st) < 0
+		|| (errno= EACCES, 0)	/* set errno for following tests */
+		|| st.st_dev != st0.st_dev
+		|| st.st_ino != st0.st_ino
+	) {
+		fatal(device);
+	}
+
+	if ((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
+						|| !isfloppy(st.st_rdev)) {
+		fprintf(stderr, "format: %s: not a floppy device\n", device);
+		exit(1);
+	}
+
+	drive= fl_drive(st.st_rdev);
+	type= fl_type(st.st_rdev);
+
+	/* The drive should not be mounted. */
+	if (load_mtab("mkfs") < 0) return;
+
+	while (get_mtab_entry(special, mounted_on, version, rw_flag) == 0) {
+		if (stat(special, &st) >= 0 && isfloppy(st.st_rdev)
+					&& fl_drive(st.st_rdev) == drive) {
+			fprintf(stderr, "format: %s is mounted on %s\n",
+				device, mounted_on);
+			exit(1);
+		}
+	}
+
+	if (isflauto(type)) {
+		/* Auto type 0 requires size(s). */
+		unsigned long lmedia, ldrive;
+		char *end;
+
+		if (argc < 3) {
+			fprintf(stderr,
+			"format: no size specified for auto floppy device %s\n",
+				device);
+			usage();
+		}
+
+		lmedia= strtoul(argv[2], &end, 10);
+		if (end == argv[2] || *end != 0 || lmedia > 20 * 1024)
+			usage();
+
+		if (argc == 4) {
+			ldrive= strtoul(argv[3], &end, 10);
+			if (end == argv[3] || *end != 0 || ldrive > 20 * 1024)
+				usage();
+		} else {
+			ldrive= lmedia;
+		}
+
+		/* Silently correct wrong ordered sizes. */
+		if (lmedia > ldrive) {
+			media_size= ldrive;
+			drive_size= lmedia;
+		} else {
+			media_size= lmedia;
+			drive_size= ldrive;
+		}
+
+		/* A 1.44M drive can do 720k diskettes with no extra tricks.
+		 * Diddle with the 720k params so it is found.
+		 */
+		if (media_size == 720 && drive_size == 1440)
+			parameters[4 - 1].drive_size= 1440;
+
+		/* Translate the auto type to a known type. */
+		for (type= 1; type <= NR_TYPES; type++) {
+			if (parameters[type - 1].media_size == media_size
+				&& parameters[type - 1].drive_size == drive_size
+			) break;
+		}
+
+		if (!isfltyped(type)) {
+			fprintf(stderr,
+			"format: can't format a %uk floppy in a %uk drive\n",
+				media_size, drive_size);
+			exit(1);
+		}
+	} else
+	if (isfltyped(type)) {
+		/* No sizes needed for a non-auto type. */
+
+		if (argc > 2) {
+			fprintf(stderr,
+	"format: no sizes need to be specified for non-auto floppy device %s\n",
+				device);
+			usage();
+		}
+	} else
+	if (isflpart(type)) {
+		fprintf(stderr,
+			"format: floppy partition %s can't be formatted\n",
+			device);
+		exit(1);
+	} else {
+		fprintf(stderr,
+			"format: %s: can't format strange type %d\n",
+			device, type);
+	}
+
+	format_device(drive, type, verify);
+	exit(0);
+}
Index: /trunk/minix/commands/ibm/loadfont.c
===================================================================
--- /trunk/minix/commands/ibm/loadfont.c	(revision 9)
+++ /trunk/minix/commands/ibm/loadfont.c	(revision 9)
@@ -0,0 +1,122 @@
+/* loadfont.c - Load custom font into EGA, VGA video card
+ *
+ * Author: Hrvoje Stipetic (hs@hck.hr) Jun-1995.
+ *
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+void tell(char *s)
+{
+  write(2, s, strlen(s));
+}
+
+char *itoa(unsigned i)
+{
+  static char a[3*sizeof(int)];
+  char *p = a+sizeof(a)-1;
+
+  do {
+	*--p = '0' + i%10;
+  } while ((i /= 10) > 0);
+
+  return p;
+}
+
+void report(char *say)
+{
+  int err = errno;
+  tell("loadfont: ");
+  if (say != NULL) {
+	tell(say);
+	tell(": ");
+  }
+  tell(strerror(err));
+  tell("\n");
+}
+
+void usage(void)
+{
+  tell("Usage: loadfont fontfile\n");
+  exit(1);
+}
+
+
+int main(int argc, char *argv[])
+{
+  static u8_t font[256][32];
+  static u8_t font_file[256 * (16+14+8) + 1];
+  u8_t *ff;
+  int fd, size, tsize, ch, ln;
+  struct winsize ws;
+
+
+  if (argc != 2)
+	usage();
+
+  if ((fd = open(argv[1], O_RDONLY)) < 0) {
+	report(argv[1]);
+	exit(1);
+  }
+
+  switch (read(fd, font_file, sizeof(font_file))) {
+  case 256 * 8:
+  	size = 8;
+  	break;
+  case 256 * 14:
+  	size = 14;
+  	break;
+  case 256 * 16:
+  	size = 16;
+  	break;
+  case 256 * (16+14+8):
+  	size = 0;
+  	break;
+  case -1:
+	report(argv[1]);
+	exit(1);
+  default:
+	tell("loadfont: ");
+	tell(argv[1]);
+	tell(": fontfile is not an 8x8, 8x14, 8x16, or compound font\n");
+	exit(1);
+  }
+  close(fd);
+
+  if (ioctl(0, TIOCGWINSZ, &ws) < 0 || (errno= ENOTTY, ws.ws_row == 0)) {
+	report(NULL);
+	exit(1);
+  }
+  tsize = ws.ws_ypixel / ws.ws_row;
+
+  if (size == 0) {
+	if (tsize >= 16) {
+		ff = font_file + 256 * (0);
+	} else
+	if (tsize >= 14) {
+		ff = font_file + 256 * (16);
+	} else {
+		ff = font_file + 256 * (16 + 14);
+	}
+	size = tsize;
+  } else {
+	ff = font_file;
+  }
+
+  for (ch = 0; ch < 256; ch++) {
+	for (ln = 0; ln < size; ln++) font[ch][ln] = ff[ch * size + ln]; 
+  }
+
+  if (ioctl(0, TIOCSFON, font) < 0) {
+	report(NULL);
+	exit(1);
+  }
+  exit(0);
+}
Index: /trunk/minix/commands/ibm/loadkeys.c
===================================================================
--- /trunk/minix/commands/ibm/loadkeys.c	(revision 9)
+++ /trunk/minix/commands/ibm/loadkeys.c	(revision 9)
@@ -0,0 +1,91 @@
+/*	loadkeys - load national keyboard map		Author: Marcus Hampel
+ */
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <minix/keymap.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#if __minix_vmd
+#define KBD_DEVICE	"/dev/kbd"
+#else
+#define KBD_DEVICE	"/dev/console"
+#endif
+
+u16_t keymap[NR_SCAN_CODES * MAP_COLS];
+u8_t comprmap[4 + NR_SCAN_CODES * MAP_COLS * 9/8 * 2 + 1];
+
+
+void tell(char *s)
+{
+  write(2, s, strlen(s));
+}
+
+
+void fatal(char *say)
+{
+  int err = errno;
+  tell("loadkeys: ");
+  if (say != NULL) {
+	tell(say);
+	tell(": ");
+  }
+  tell(strerror(err));
+  tell("\n");
+  exit(1);
+}
+
+
+void usage(void)
+{
+  tell("Usage: loadkeys mapfile\n");
+  exit(1);
+}
+
+
+int main(int argc, char *argv[])
+{
+  u8_t *cm;
+  u16_t *km;
+  int fd, n, fb;
+
+  if (argc != 2)
+	usage();
+
+  if ((fd = open(argv[1], O_RDONLY)) < 0) fatal(argv[1]);
+
+  if (read(fd, comprmap, sizeof(comprmap)) < 0) fatal(argv[1]);
+
+  if (memcmp(comprmap, KEY_MAGIC, 4) != 0) {
+	tell("loadkeys: ");
+	tell(argv[1]);
+	tell(": not a keymap file\n");
+	exit(1);
+  }
+  close(fd);
+
+  /* Decompress the keymap data. */
+  cm = comprmap + 4;
+  n = 8;
+  for (km = keymap; km < keymap + NR_SCAN_CODES * MAP_COLS; km++) {
+	if (n == 8) {
+		/* Need a new flag byte. */
+		fb = *cm++;
+		n = 0;
+	}
+	*km = *cm++;			/* Low byte. */
+	if (fb & (1 << n)) {
+		*km |= (*cm++ << 8);	/* One of the few special keys. */
+	}
+	n++;
+  }
+
+  if ((fd = open(KBD_DEVICE, O_WRONLY)) < 0) fatal(KBD_DEVICE);
+
+  if (ioctl(fd, KIOCSMAP, keymap) < 0) fatal(KBD_DEVICE);
+
+  return 0;
+}
Index: /trunk/minix/commands/ibm/mixer.c
===================================================================
--- /trunk/minix/commands/ibm/mixer.c	(revision 9)
+++ /trunk/minix/commands/ibm/mixer.c	(revision 9)
@@ -0,0 +1,658 @@
+/*   
+ *  mixer
+ *
+ *  Michel R. Prevenier.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <curses.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <minix/sound.h>
+
+#define CURS_CTRL	'\033'
+#define ESCAPE		27
+#define UP   		'A'
+#define DOWN		'B'
+#define LEFT		'D'
+#define RIGHT		'C'
+#define SPACE		' '
+
+
+_PROTOTYPE ( int main, (int arg, char **argv));
+_PROTOTYPE ( void usage, (void));
+_PROTOTYPE ( void non_interactive, (void));
+_PROTOTYPE ( void setup_screen, (void));
+_PROTOTYPE ( int read_settings, (void));
+_PROTOTYPE ( int write_settings, (void));
+_PROTOTYPE ( void rdwr_levels, (int flag));
+_PROTOTYPE ( void rdwr_inputs, (int flag));
+_PROTOTYPE ( void rdwr_outputs, (int flag));
+_PROTOTYPE ( void create_slider, (int x, int y, enum Device device));
+_PROTOTYPE ( void show_inputs, (int x, int y));
+_PROTOTYPE ( void show_outputs, (int x, int y));
+_PROTOTYPE ( char *d_name, (enum Device device, char *name));
+_PROTOTYPE ( void user_interface, (void));
+_PROTOTYPE ( void terminate, (int s));
+
+WINDOW *main_win;
+int old_stdin;
+int fd;
+char name[9];
+char *file_name;
+struct volume_level levels[9];
+struct inout_ctrl inputs_left[9];
+struct inout_ctrl inputs_right[9];
+struct inout_ctrl outputs[9];
+
+
+void usage()
+{
+  fprintf(stderr, "Usage: mixer [-r]\n");
+  exit(-1);
+}
+
+
+void terminate(s)
+int s;
+{
+  /* Restore terminal parameters and exit */
+
+  (void) fcntl(0,F_SETFL,old_stdin);
+  move(23, 0);			
+  refresh();			
+  resetty();
+  endwin();			
+  exit(1);		
+}
+
+
+int write_settings()
+{
+  /* Write the current mixer settings to $HOME/.mixer */
+
+  int fd;
+
+  if ((fd = creat(file_name, 0x124)) > 0)
+  {
+    write(fd, levels, sizeof(levels));
+    write(fd, inputs_left, sizeof(inputs_left));
+    write(fd, inputs_right, sizeof(inputs_right));
+    write(fd, outputs, sizeof(outputs));
+    close(fd);
+    return 1;
+  }
+
+  return 0;
+}
+
+
+int read_settings()
+{
+  /* Restore mixer settings saved in $HOME/.mixer */
+
+  int fd;
+
+  if ((fd = open(file_name, O_RDONLY)) > 0)
+  {
+    read(fd, levels, sizeof(levels));
+    read(fd, inputs_left, sizeof(inputs_left));
+    read(fd, inputs_right, sizeof(inputs_right));
+    read(fd, outputs, sizeof(outputs));
+    close(fd);
+    rdwr_levels(1);
+    rdwr_outputs(1);
+    rdwr_inputs(1);
+    return 1;
+  }
+  return 0;
+}
+
+
+void rdwr_levels(flag)
+int flag;             /* 0 = read, 1 = write */
+{
+  /* Get or set mixer settings */
+
+  int i;
+  int cmd;
+ 
+  cmd = (flag == 0 ? MIXIOGETVOLUME : MIXIOSETVOLUME);  
+  
+  for(i = Master; i <= Bass; i++)
+    (void) (ioctl(fd, cmd, &levels[i])); 
+}    
+
+
+void rdwr_inputs(flag)
+int flag;              /* 0 = read, 1 = write */
+{
+  /* Get or set input settings */
+
+  int i;
+  int cmd_left, cmd_right;
+  
+  cmd_left = (flag == 0 ? MIXIOGETINPUTLEFT : MIXIOSETINPUTLEFT);  
+  cmd_right = (flag == 0 ? MIXIOGETINPUTRIGHT : MIXIOSETINPUTRIGHT);  
+
+  for(i = Fm; i <= Mic; i++)
+  {
+    (void) (ioctl(fd, cmd_left, &inputs_left[i])); 
+    (void) (ioctl(fd, cmd_right, &inputs_right[i])); 
+  }
+}
+
+
+void rdwr_outputs(flag)
+int flag;               /* 0 = read, 1 = write */
+{
+  /* Get or set output settings */
+
+  int i;
+  int cmd; 
+
+  cmd = (flag == 0 ? MIXIOGETOUTPUT : MIXIOSETOUTPUT);  
+
+  for(i = Cd; i <= Mic; i++)
+    (void) (ioctl(fd, cmd, &outputs[i])); 
+}
+
+
+int main(argc, argv)
+int argc;
+char **argv;
+
+{
+  int i;
+  char *home_ptr;
+  int fd2;
+
+  /* Open mixer */
+  if ((fd = open("/dev/mixer",O_RDONLY)) < 0)
+  {
+    fprintf(stderr, "Cannot open /dev/mixer\n");
+    exit(-1);
+  }
+
+  /* Get user's home directory and construct the $HOME/.mixer
+   * file name 
+   */
+  home_ptr = getenv("HOME");
+  file_name = malloc(strlen(home_ptr)+strlen("mixer.ini\0"));
+  if (file_name == (char *)0) 
+  {
+    fprintf(stderr, "Not enough memory\n");
+    exit(-1);
+  }
+  strncpy(file_name, home_ptr, strlen(home_ptr));
+  strncpy(file_name+strlen(home_ptr), "/.mixer\0", 9);
+
+  /* Fill in the device numbers */    
+  for(i = Master; i <= Bass; i++) 
+  {
+    levels[i].device = i;
+    inputs_left[i].device = i;
+    inputs_right[i].device = i;
+    outputs[i].device = i;
+  }
+
+  /* Get arguments */
+  if (argc > 1)
+  {
+    if (strncmp(argv[1], "-r", 2) == 0)
+    {
+      if (read_settings())
+      {
+        printf("Mixer settings restored\n");
+        exit(0);
+      }
+      else
+      {
+        fprintf(stderr, "Could not restore mixer settings\n");
+        exit(-1);
+      }
+    } 
+    else usage();
+  }
+
+  /* Initialize windows. */
+  (void) initscr();
+  signal(SIGINT, terminate);
+  old_stdin = fcntl(0,F_GETFL);
+  cbreak();
+  noecho();
+  main_win = newwin(23,80,0,0);
+  scrollok(main_win, FALSE);
+
+  /* Read all current mixer settings */
+  rdwr_levels(0);
+  rdwr_inputs(0);
+  rdwr_outputs(0);
+
+  /* Set up the user screen and handle user input */
+  setup_screen();
+  user_interface();
+}
+
+
+void user_interface()
+{
+  /* This is the user interface. */
+ 
+  char c;
+  int x,y;
+  int right;
+  int input_scr, input_pos;
+  int output_scr, output_pos;
+  int max_level;
+  enum Device device;
+  int fd2;
+ 
+  device = Master;
+  right = 0;
+  input_scr = 0;
+  output_scr = 0;
+  input_pos = 0;
+  output_pos = 0;
+
+  while(1)
+  {
+    if (input_scr)
+    {
+      y = device + 9;
+      x = 51 + input_pos + (device == Mic ? 2 : 0);
+    }
+    else if (output_scr)
+    {
+      y = device + 15;
+      x = 53 + output_pos + (device == Mic ? 4 : 0);
+    }
+    else
+    {
+      y = (device != Speaker ? 2 : 1) + 
+          (device - (device < Treble ? 0 : Treble)) * 3 + 
+          (right == 0 ? 0 : 1);
+      if (!right)
+        x = 9 + levels[device].left / (device < Speaker ? 2 : 1 ) +
+              (device > Speaker ? 39 : 0);
+      else
+        x = 9 + levels[device].right / (device < Speaker ? 2 : 1) +
+              (device > Speaker ? 39 : 0);
+    }
+    
+    wmove(main_win,y,x);
+    wrefresh(main_win);
+    c = wgetch(main_win);
+
+    switch(c)
+    {
+      case CURS_CTRL:
+      {
+        (void) wgetch(main_win);
+        c = wgetch(main_win);
+        
+        switch(c)
+        { 
+          case DOWN: 
+          {
+           if (output_scr) 
+           {
+             if (device < Mic)
+             {
+                device++;
+                if (device == Mic) output_pos = 0;
+             }
+           }
+           else if (right || input_scr)
+           {
+             if (!input_scr)
+             {
+               if (device < Bass) 
+               {
+                 device++;         
+                 right = 0;
+               }
+               else
+               {  
+                 input_scr = 1;
+                 input_pos = 0;
+                 device = Fm;
+               }
+             }
+             else
+             {
+               if (device < Mic) 
+               {
+                 device++;
+                 if (device == Mic && input_pos > 8) input_pos = 8;
+               }
+               else 
+               { 
+                 device = Cd; 
+                 output_scr = 1; 
+                 input_scr = 0; 
+                 output_pos = 0; 
+               }
+             }
+           }
+           else 
+           {
+             if (device != Mic && device != Speaker)  right = 1;
+             else { device++; right = 0; }
+           }
+          };break;
+          case UP: 
+          {
+           if (output_scr) 
+           {
+             if (device > Cd) device--;
+             else 
+             {
+               device = Mic; 
+               output_scr = 0;
+               input_scr = 1;
+             }
+           }
+           else if (!right || input_scr)
+           {
+             if (input_scr)
+             {
+               if (device > Fm) device--;
+               else 
+               {
+                 input_scr = 0;
+                 device = Bass;
+                 right = 1;
+               }
+             }
+             else 
+             {
+               if (device > Master) 
+               {
+                 device--;         
+                 if (device != Mic && device != Speaker) right = 1;
+               }
+             }
+           }
+           else 
+             right = 0;
+          };break;
+          case RIGHT: 
+          {
+            if (output_scr) 
+            {
+              if (output_pos < 8 && device != Mic) output_pos = 8;
+            }
+            else if (!input_scr)
+            {
+              if (device < Speaker) max_level = 31;
+              else if (device > Speaker) max_level = 15;
+              else max_level = 4;
+
+              if (!right) 
+              {
+                if (levels[device].left < max_level) levels[device].left+=
+                  (device < Speaker ? 2 : 1);
+              }
+              else
+              {
+                if (levels[device].right < max_level) levels[device].right+=
+                  (device < Speaker ? 2 : 1);
+              }
+              ioctl(fd, MIXIOSETVOLUME, &levels[device]); 
+              ioctl(fd, MIXIOGETVOLUME, &levels[device]); 
+              create_slider(1 + (device < Treble ? 0 : 39), 
+                            (device - (device < Treble ? 0 : Treble))*3 +
+                            (device != Speaker ? 2 : 1), device);
+            }
+            else
+            {
+              if ((device != Mic && input_pos < 12) ||
+                  (device == Mic && input_pos < 8))
+                input_pos += (4 + (device == Mic ? 4 : 0));
+            }
+          };break;
+          case LEFT: 
+          {
+            if (output_scr)
+            {
+              if (output_pos > 0) output_pos = 0;
+            }
+            else if (!input_scr)
+            {
+              if (!right)
+              {
+                if (levels[device].left > 0) levels[device].left-=
+                  (device < Speaker ? 2 : 1);
+              }
+              else
+              {
+                if (levels[device].right > 0) levels[device].right-=
+                  (device < Speaker ? 2 : 1);
+              }
+              ioctl(fd, MIXIOSETVOLUME, &levels[device]); 
+              ioctl(fd, MIXIOGETVOLUME, &levels[device]); 
+              create_slider(1 + (device < Treble ? 0 : 39), 
+                            (device - (device < Treble ? 0 : Treble))*3 +
+                            (device != Speaker ? 2 : 1), device);
+            }
+            else
+            {
+              if (input_pos > 0) 
+                input_pos -= (4 + (device == Mic ? 4 : 0));
+            } 
+          };break;
+        } 
+      };break;
+    case SPACE:
+      {
+        if (output_scr)
+        {
+          switch(output_pos)
+          {
+            case 0:
+            case 4:
+            {
+              outputs[device].left = 
+               (outputs[device].left == ON ? OFF : ON);
+              ioctl(fd, MIXIOSETOUTPUT, &outputs[device]);
+            };break;
+            case 8:
+            {
+              outputs[device].right = 
+               (outputs[device].right == ON ? OFF : ON);
+              ioctl(fd, MIXIOSETOUTPUT, &outputs[device]);
+            };break;
+          }
+          ioctl(fd, MIXIOGETOUTPUT, &outputs[device]);
+          show_outputs(41,16);
+        }
+        else if (input_scr)
+        { 
+          switch(input_pos)
+          {
+            case 0:
+            {
+              inputs_left[device].left = 
+               (inputs_left[device].left == ON ? OFF : ON);
+              ioctl(fd, MIXIOSETINPUTLEFT, &inputs_left[device]);
+            };break;
+            case 4:
+            {
+              inputs_left[device].right = 
+               (inputs_left[device].right == ON ? OFF : ON);
+              ioctl(fd, MIXIOSETINPUTLEFT, &inputs_left[device]);
+            };break;
+            case 8:
+            {
+              inputs_right[device].left = 
+               (inputs_right[device].left == ON ? OFF : ON);
+              ioctl(fd, MIXIOSETINPUTRIGHT, &inputs_right[device]);
+            };break;
+            case 12:
+            {
+              inputs_right[device].right = 
+               (inputs_right[device].right == ON ? OFF : ON);
+              ioctl(fd, MIXIOSETINPUTRIGHT, &inputs_right[device]);
+            };break;
+          }
+          ioctl(fd, MIXIOGETINPUTLEFT, &inputs_left[device]);
+          ioctl(fd, MIXIOGETINPUTRIGHT, &inputs_right[device]);
+          show_inputs(41,8);
+        }
+      };break;
+      case 's':
+      {
+        if (write_settings())  
+          mvwprintw(main_win,22,28, "mixer settings saved");
+        else
+          mvwprintw(main_win,22,28, "error: file not saved");
+        wrefresh(main_win);
+        sleep(1);
+        mvwprintw(main_win,22,28, "                           ");
+      };break;
+      case 'r':
+      {
+        if (read_settings())
+          mvwprintw(main_win,22,28, "mixer settings restored");
+        else
+          mvwprintw(main_win,22,28, "error: could not open");
+        wrefresh(main_win);
+        sleep(1);
+        setup_screen();
+      };break;
+      case 'e': terminate(1);
+    }
+  } 
+}
+
+
+char *d_name(device, name)
+enum Device device;
+char *name;
+{
+  /* Convert the device number to a name */
+
+  switch (device)
+  {
+    case Master:	strncpy(name, "Master  \0", 9);break;
+    case Dac:		strncpy(name, "Dac     \0", 9);break;
+    case Fm:		strncpy(name, "Fm      \0", 9);break;
+    case Cd:		strncpy(name, "CD      \0", 9);break;
+    case Line:		strncpy(name, "Line    \0", 9);break;
+    case Mic:		strncpy(name, "Mic     \0", 9);break;
+    case Speaker:	strncpy(name, "Speaker \0", 9);break;
+    case Treble:	strncpy(name, "Treble  \0", 9);break;
+    case Bass:		strncpy(name, "Bass    \0", 9);break;
+  }
+  return name;
+}
+
+
+void create_slider(x, y, device)
+int x;
+int y;
+enum Device device;
+{
+  /* Create a slider on the screen */
+
+  int left;
+  int right;
+  int i;
+
+  mvwprintw(main_win,y,x, "%s", d_name(device, name));
+
+  left = levels[device].left / (device < Speaker ? 2 : 1); 
+  right = levels[device].right / (device < Speaker ? 2 : 1); 
+
+  for (i = 0; i < 16; i++)
+  {
+    if (device != Speaker || i < 4)
+      mvwprintw(main_win,y,x+i+8, (i == left ? "*" : "-"));
+    if (device < Mic || device > Speaker) 
+      mvwprintw(main_win,y+1,x+i+8, (i == right ? "*" : "-"));
+  }
+
+  if (device < Mic || device > Speaker)
+  {
+    mvwprintw(main_win,y,x+i+10, "left");
+    mvwprintw(main_win,y+1,x+i+10, "right");
+  }
+  wrefresh(main_win);
+} 
+  
+void show_inputs(x,y)
+int x;
+int y;
+{
+  /* Show the input settings */
+
+  int i;
+
+  mvwprintw(main_win,y,x,  "             Rec-In  ");
+  mvwprintw(main_win,y+1,x,"          left    right");
+  mvwprintw(main_win,y+2,x,"          l   r   l   r");
+  for (i = Fm; i <= Line; i++)
+  {
+    mvwprintw(main_win,y+i+1,x,  "%s  %d   %d   %d   %d", 
+      d_name(i, (char *)name),
+      (inputs_left[i].left == ON ? 1 : 0),
+      (inputs_left[i].right == ON ? 1 : 0),
+      (inputs_right[i].left == ON ? 1 : 0),
+      (inputs_right[i].right == ON ? 1 : 0));
+  }
+  mvwprintw(main_win,y+i+1,x,  "%s    %d       %d", 
+    d_name(Mic, (char *)name),
+    (inputs_left[Mic].left == ON ? 1 : 0),
+    (inputs_right[Mic].left == ON ? 1 : 0));
+  wrefresh(main_win);
+}
+
+void show_outputs(x,y)
+int x;
+int y;
+{
+  /* Show the output settings */
+
+  int i;
+
+  mvwprintw(main_win,y,x,      "            Mix-Out  ");
+  mvwprintw(main_win,y+1,x,    "          left    right");
+  for (i = Cd; i <= Line; i++)
+  {
+    mvwprintw(main_win,y+i-1,x,"%s    %d       %d", 
+      d_name(i, (char *)name),
+      (outputs[i].left == ON ? 1 : 0),
+      (outputs[i].right == ON ? 1 : 0));
+  }
+  mvwprintw(main_win,y+i-1,x,"%s        %d", 
+    d_name(Mic, (char *)name),
+    (outputs[Mic].left == ON ? 1 : 0));
+
+  wrefresh(main_win);
+}
+
+
+void setup_screen()
+{
+  int i;
+
+  wclear(main_win);
+  mvwprintw(main_win,0,23,"------- Mixer Controls -------");
+  wrefresh(main_win);
+ 
+  for(i = 0; i <= Speaker; i++)
+   create_slider(1, i*3+(i <= Mic ? 2 : 1), i);
+
+   create_slider(40, 2, Treble);
+   create_slider(40, 5, Bass);
+ 
+   show_inputs(41,8);
+   show_outputs(41,16);
+}
Index: /trunk/minix/commands/ibm/part.c
===================================================================
--- /trunk/minix/commands/ibm/part.c	(revision 9)
+++ /trunk/minix/commands/ibm/part.c	(revision 9)
@@ -0,0 +1,2124 @@
+/*	part 1.57 - Partition table editor		Author: Kees J. Bot
+ *								13 Mar 1992
+ * Needs about 22k heap+stack.
+ */
+#define nil 0
+#include <sys/types.h>
+#include <stdio.h>
+#include <termcap.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <time.h>
+#include <dirent.h>
+#include <limits.h>
+#include <a.out.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/partition.h>
+#include <minix/u64.h>
+#include <ibm/partition.h>
+#include <termios.h>
+
+/* True if a partition is an extended partition. */
+#define ext_part(s)	((s) == 0x05 || (s) == 0x0F)
+
+/* Minix master bootstrap code. */
+static char MASTERBOOT[] = "/usr/mdec/masterboot";
+
+/* Template:
+                      ----first----  --geom/last--  ------sectors-----
+    Device             Cyl Head Sec   Cyl Head Sec      Base      Size        Kb
+    /dev/c0d0                          977    5  17
+    /dev/c0d0:2          0    0   2   976    4  16         2     83043     41521
+Num Sort   Type
+ 0* p0   81 MINIX        0    0   3    33    4   9         3      2880      1440
+ 1  p1   81 MINIX       33    4  10   178    2   2      2883     12284      6142
+ 2  p2   81 MINIX      178    2   3   976    4  16     15167     67878     33939
+ 3  p3   00 None         0    0   0     0    0  -1         0         0         0
+
+ */
+#define MAXSIZE		999999999L	/* Will 1T be enough this year? */
+#define SECTOR_SIZE	512
+#define DEV_FD0		0x200		/* Device number of /dev/fd0 */
+#define DEV_C0D0	0x300		/* Device number of /dev/c0d0 */
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+
+void report(const char *label)
+{
+	fprintf(stderr, "part: %s: %s\n", label, strerror(errno));
+}
+
+void fatal(const char *label)
+{
+	report(label);
+	exit(1);
+}
+
+struct termios termios;
+
+void save_ttyflags(void)
+/* Save tty attributes for later restoration. */
+{
+	if (tcgetattr(0, &termios) < 0) fatal("");
+}
+
+void restore_ttyflags(void)
+/* Reset the tty flags to how we got 'em. */
+{
+	if (tcsetattr(0, TCSANOW, &termios) < 0) fatal("");
+}
+
+void tty_raw(void)
+/* Set the terminal to raw mode, no signals, no echoing. */
+{
+	struct termios rawterm;
+
+	rawterm= termios;
+	rawterm.c_lflag &= ~(ICANON|ISIG|ECHO);
+	rawterm.c_iflag &= ~(ICRNL);
+	if (tcsetattr(0, TCSANOW, &rawterm) < 0) fatal("");
+}
+
+#define ctrl(c)		((c) == '?' ? '\177' : ((c) & '\37'))
+
+char t_cd[16], t_cm[32], t_so[16], t_se[16], t_md[16], t_me[16];
+int t_li, t_co;
+#define STATUSROW	10
+
+void init_tty(void)
+/* Get terminal capabilities and set the tty to "editor" mode. */
+{
+	char *term;
+	static char termbuf[1024];
+	char *tp;
+
+	if ((term= getenv("TERM")) == nil || tgetent(termbuf, term) != 1) {
+		fprintf(stderr, "part: Can't get terminal capabilities\n");
+		exit(1);
+	}
+	if (tgetstr("cd", (tp= t_cd, &tp)) == nil
+				|| tgetstr("cm", (tp= t_cm, &tp)) == nil) {
+		fprintf(stderr, "part: This terminal is too dumb\n");
+		exit(1);
+	}
+	t_li= tgetnum("li");
+	t_co= tgetnum("co");
+	(void) tgetstr("so", (tp= t_so, &tp));
+	(void) tgetstr("se", (tp= t_se, &tp));
+	(void) tgetstr("md", (tp= t_md, &tp));
+	(void) tgetstr("me", (tp= t_me, &tp));
+
+	save_ttyflags();
+	tty_raw();
+}
+
+void putchr(int c)
+{
+	putchar(c);
+}
+
+void putstr(char *s)
+{
+	int c;
+
+	while ((c= *s++) != 0) putchr(c);
+}
+
+void set_cursor(int row, int col)
+{
+	tputs(tgoto(t_cm, col, row), 1, putchr);
+}
+
+int statusrow= STATUSROW;
+int stat_ktl= 1;
+int need_help= 1;
+
+void stat_start(int serious)
+/* Prepare for printing on a fresh status line, possibly highlighted. */
+{
+	set_cursor(statusrow++, 0);
+	tputs(t_cd, 1, putchr);
+	if (serious) tputs(t_so, 1, putchr);
+}
+
+void stat_end(int ktl)
+/* Closing bracket for stat_start.  Sets "keystrokes to live" of message. */
+{
+	tputs(t_se, 1, putchr);
+	stat_ktl= ktl;
+	need_help= 1;
+}
+
+void stat_reset(void)
+/* Reset the statusline pointer and clear old messages if expired. */
+{
+	if (stat_ktl > 0 && --stat_ktl == 0) {
+		statusrow= STATUSROW;
+		need_help= 1;
+	}
+	if (need_help && statusrow < (24-2)) {
+		if (statusrow > STATUSROW) stat_start(0);
+		stat_start(0);
+		putstr(
+"Type '+' or '-' to change, 'r' to read, '?' for more help, 'q' to exit");
+	}
+	statusrow= STATUSROW;
+	need_help= 0;
+}
+
+void clear_screen(void)
+{
+	set_cursor(0, 0);
+	tputs(t_cd, 1, putchr);
+	stat_ktl= 1;
+	stat_reset();
+}
+
+void reset_tty(void)
+/* Reset the tty to cooked mode. */
+{
+	restore_ttyflags();
+	set_cursor(statusrow, 0);
+	tputs(t_cd, 1, putchr);
+}
+
+void *alloc(size_t n)
+{
+	void *m;
+
+	if ((m= malloc(n)) == nil) { reset_tty(); fatal(""); }
+
+	return m;
+}
+
+#ifndef makedev		/* Missing in sys/types.h */
+#define minor(dev)	(((dev) >> MINOR) & BYTE)
+#define major(dev)	(((dev) >> MAJOR) & BYTE)
+#define makedev(major, minor)	\
+			((dev_t) (((major) << MAJOR) | ((minor) << MINOR)))
+#endif
+
+typedef enum parttype { DUNNO, SUBPART, PRIMARY, FLOPPY } parttype_t;
+
+typedef struct device {
+	struct device *next, *prev;	/* Circular dequeue. */
+	dev_t	rdev;			/* Device number (sorting only). */
+	char	*name;			/* E.g. /dev/c0d0 */
+	char	*subname;		/* E.g. /dev/c0d0:2 */
+	parttype_t parttype;
+} device_t;
+
+device_t *firstdev= nil, *curdev;
+
+void newdevice(char *name, int scanning)
+/* Add a device to the device list.  If scanning is set then we are reading
+ * /dev, so insert the device in device number order and make /dev/c0d0 current.
+ */
+{
+	device_t *new, *nextdev, *prevdev;
+	struct stat st;
+
+	st.st_rdev= 0;
+	if (scanning) {
+		if (stat(name, &st) < 0 || !S_ISBLK(st.st_mode)) return;
+
+		switch (major(st.st_rdev)) {
+		case 2:
+			/* Floppy */
+			if (minor(st.st_rdev) >= 4) return;
+			break;
+		case 3:
+		case 8:
+		case 10:
+		case 12:
+		case 16:
+			/* Disk controller */
+			if (minor(st.st_rdev) >= 0x80
+					|| minor(st.st_rdev) % 5 != 0) return;
+			break;
+		default:
+			return;
+		}
+		/* Interesting device found. */
+	} else {
+		(void) stat(name, &st);
+	}
+
+	new= alloc(sizeof(*new));
+	new->rdev= st.st_rdev;
+	new->name= alloc((strlen(name) + 1) * sizeof(new->name[0]));
+	strcpy(new->name, name);
+	new->subname= new->name;
+	new->parttype= DUNNO;
+	if (major(st.st_rdev) == major(DEV_FD0) && minor(st.st_rdev) < 112) {
+		new->parttype= FLOPPY;
+	} else
+	if (st.st_rdev >= DEV_C0D0 && minor(st.st_rdev) < 128
+			&& minor(st.st_rdev) % 5 == 0) {
+		new->parttype= PRIMARY;
+	}
+
+	if (firstdev == nil) {
+		firstdev= new;
+		new->next= new->prev= new;
+		curdev= firstdev;
+		return;
+	}
+	nextdev= firstdev;
+	while (new->rdev >= nextdev->rdev
+				&& (nextdev= nextdev->next) != firstdev) {}
+	prevdev= nextdev->prev;
+	new->next= nextdev;
+	nextdev->prev= new;
+	new->prev= prevdev;
+	prevdev->next= new;
+
+	if (new->rdev < firstdev->rdev) firstdev= new;
+	if (new->rdev == DEV_C0D0) curdev= new;
+	if (curdev->rdev != DEV_C0D0) curdev= firstdev;
+}
+
+void getdevices(void)
+/* Get all block devices from /dev that look interesting. */
+{
+	DIR *d;
+	struct dirent *e;
+	char name[5 + NAME_MAX + 1];
+
+	if ((d= opendir("/dev")) == nil) fatal("/dev");
+
+	while ((e= readdir(d)) != nil) {
+		strcpy(name, "/dev/");
+		strcpy(name + 5, e->d_name);
+		newdevice(name, 1);
+	}
+	(void) closedir(d);
+}
+
+/* One featureful master bootstrap. */
+unsigned char bootstrap[] = {
+0353,0001,0000,0061,0300,0216,0330,0216,0300,0372,0216,0320,0274,0000,0174,0373,
+0275,0276,0007,0211,0346,0126,0277,0000,0006,0271,0000,0001,0374,0363,0245,0352,
+0044,0006,0000,0000,0264,0002,0315,0026,0250,0010,0164,0033,0350,0071,0001,0174,
+0007,0060,0344,0315,0026,0242,0205,0007,0054,0060,0074,0012,0163,0363,0120,0350,
+0046,0001,0205,0007,0130,0353,0012,0240,0002,0006,0204,0300,0165,0003,0351,0147,
+0000,0230,0262,0005,0366,0362,0262,0200,0000,0302,0210,0340,0120,0350,0234,0000,
+0163,0003,0351,0147,0000,0130,0054,0001,0175,0003,0351,0141,0000,0276,0276,0175,
+0211,0357,0271,0040,0000,0363,0245,0200,0301,0004,0211,0356,0215,0174,0020,0070,
+0154,0004,0164,0016,0213,0135,0010,0053,0134,0010,0213,0135,0012,0033,0134,0012,
+0163,0014,0212,0044,0206,0144,0020,0210,0044,0106,0071,0376,0162,0364,0211,0376,
+0201,0376,0356,0007,0162,0326,0342,0322,0211,0356,0264,0020,0366,0344,0001,0306,
+0200,0174,0004,0001,0162,0026,0353,0021,0204,0322,0175,0041,0211,0356,0200,0174,
+0004,0000,0164,0013,0366,0004,0200,0164,0006,0350,0070,0000,0162,0053,0303,0203,
+0306,0020,0201,0376,0376,0007,0162,0346,0350,0215,0000,0211,0007,0376,0302,0204,
+0322,0174,0023,0315,0021,0321,0340,0321,0340,0200,0344,0003,0070,0342,0167,0355,
+0350,0011,0000,0162,0350,0303,0350,0003,0000,0162,0146,0303,0211,0356,0214,0134,
+0010,0214,0134,0012,0277,0003,0000,0122,0006,0127,0264,0010,0315,0023,0137,0007,
+0200,0341,0077,0376,0306,0210,0310,0366,0346,0211,0303,0213,0104,0010,0213,0124,
+0012,0367,0363,0222,0210,0325,0366,0361,0060,0322,0321,0352,0321,0352,0010,0342,
+0210,0321,0376,0301,0132,0210,0306,0273,0000,0174,0270,0001,0002,0315,0023,0163,
+0020,0200,0374,0200,0164,0011,0117,0174,0006,0060,0344,0315,0023,0163,0270,0371,
+0303,0201,0076,0376,0175,0125,0252,0165,0001,0303,0350,0013,0000,0243,0007,0353,
+0005,0350,0004,0000,0227,0007,0353,0376,0136,0255,0126,0211,0306,0254,0204,0300,
+0164,0011,0264,0016,0273,0001,0000,0315,0020,0353,0362,0303,0057,0144,0145,0166,
+0057,0150,0144,0077,0010,0000,0015,0012,0000,0116,0157,0156,0145,0040,0141,0143,
+0164,0151,0166,0145,0015,0012,0000,0122,0145,0141,0144,0040,0145,0162,0162,0157,
+0162,0040,0000,0116,0157,0164,0040,0142,0157,0157,0164,0141,0142,0154,0145,0040,
+0000,0000,
+};
+
+int dirty= 0;
+unsigned char bootblock[SECTOR_SIZE];
+struct part_entry table[1 + NR_PARTITIONS];
+int existing[1 + NR_PARTITIONS];
+unsigned long offset= 0, extbase= 0, extsize;
+int submerged= 0;
+char sort_index[1 + NR_PARTITIONS];
+unsigned cylinders= 1, heads= 1, sectors= 1, secpcyl= 1;
+unsigned alt_cyls= 1, alt_heads= 1, alt_secs= 1;
+int precise= 0;
+int device= -1;
+
+unsigned long sortbase(struct part_entry *pe)
+{
+	return pe->sysind == NO_PART ? -1 : pe->lowsec;
+}
+
+void sort(void)
+/* Let the sort_index array show the order partitions are sorted in. */
+{
+	int i, j;
+	int idx[1 + NR_PARTITIONS];
+
+	for (i= 1; i <= NR_PARTITIONS; i++) idx[i]= i;
+
+	for (i= 1; i <= NR_PARTITIONS; i++) {
+		for (j= 1; j <= NR_PARTITIONS-1; j++) {
+			int sj= idx[j], sj1= idx[j+1];
+
+			if (sortbase(&table[sj]) > sortbase(&table[sj1])) {
+				idx[j]= sj1;
+				idx[j+1]= sj;
+			}
+		}
+	}
+	for (i= 1; i <= NR_PARTITIONS; i++) sort_index[idx[i]]= i;
+}
+
+void dos2chs(unsigned char *dos, unsigned *chs)
+/* Extract cylinder, head and sector from the three bytes DOS uses to address
+ * a sector.  Note that bits 8 & 9 of the cylinder number come from bit 6 & 7
+ * of the sector byte.  The sector number is rebased to count from 0.
+ */
+{
+	chs[0]= ((dos[1] & 0xC0) << 2) | dos[2];
+	chs[1]= dos[0];
+	chs[2]= (dos[1] & 0x3F) - 1;
+}
+
+void abs2dos(unsigned char *dos, unsigned long pos)
+/* Translate a sector offset to three DOS bytes. */
+{
+	unsigned h, c, s;
+
+	c= pos / secpcyl;
+	h= (pos % secpcyl) / sectors;
+	s= pos % sectors + 1;
+
+	dos[0]= h;
+	dos[1]= s | ((c >> 2) & 0xC0);
+	dos[2]= c & 0xFF;
+}
+
+void recompute0(void)
+/* Recompute the partition size for the device after a geometry change. */
+{
+	if (device < 0) {
+		cylinders= heads= sectors= 1;
+		memset(table, 0, sizeof(table));
+	} else
+	if (!precise && offset == 0) {
+		table[0].lowsec= 0;
+		table[0].size= (unsigned long) cylinders * heads * sectors;
+	}
+	table[0].sysind= device < 0 ? NO_PART : MINIX_PART;
+	secpcyl= heads * sectors;
+}
+
+void guess_geometry(void)
+/* With a bit of work one can deduce the disk geometry from the partition
+ * table.  This may be necessary if the driver gets it wrong.  (If partition
+ * tables didn't have C/H/S numbers we would not care at all...)
+ */
+{
+	int i, n;
+	struct part_entry *pe;
+	unsigned chs[3];
+	unsigned long sec;
+	unsigned h, s;
+	unsigned char HS[256][8];	/* Bit map off all possible H/S */
+
+	alt_cyls= alt_heads= alt_secs= 0;
+
+	/* Initially all possible H/S combinations are possible.  HS[h][0]
+	 * bit 0 is used to rule out a head value.
+	 */
+	for (h= 1; h <= 255; h++) {
+		for (s= 0; s < 8; s++) HS[h][s]= 0xFF;
+	}
+
+	for (i= 0; i < 2*NR_PARTITIONS; i++) {
+		pe= &(table+1)[i >> 1];
+		if (pe->sysind == NO_PART) continue;
+
+		/* Get the end or start sector numbers (in that order). */
+		if ((i & 1) == 0) {
+			dos2chs(&pe->last_head, chs);
+			sec= pe->lowsec + pe->size - 1;
+		} else {
+			dos2chs(&pe->start_head, chs);
+			sec= pe->lowsec;
+		}
+
+		if (chs[0] >= alt_cyls) alt_cyls= chs[0]+1;
+
+		/* Which H/S combinations can be ruled out? */
+		for (h= 1; h <= 255; h++) {
+			if (HS[h][0] == 0) continue;
+			n = 0;
+			for (s= 1; s <= 63; s++) {
+				if ((chs[0] * h + chs[1]) * s + chs[2] != sec) {
+					HS[h][s/8] &= ~(1 << (s%8));
+				}
+				if (HS[h][s/8] & (1 << (s%8))) n++;
+			}
+			if (n == 0) HS[h][0]= 0;
+		}
+	}
+
+	/* See if only one remains. */
+	i= 0;
+	for (h= 1; h <= 255; h++) {
+		if (HS[h][0] == 0) continue;
+		for (s= 1; s <= 63; s++) {
+			if (HS[h][s/8] & (1 << (s%8))) {
+				i++;
+				alt_heads= h;
+				alt_secs= s;
+			}
+		}
+	}
+
+	/* Forget it if more than one choice... */
+	if (i > 1) alt_cyls= alt_heads= alt_secs= 0;
+}
+
+void geometry(void)
+/* Find out the geometry of the device by querying the driver, or by looking
+ * at the partition table.  These numbers are crosschecked to make sure that
+ * the geometry is correct.  Master bootstraps other than the Minix one use
+ * the CHS numbers in the partition table to load the bootstrap of the active
+ * partition.
+ */
+{
+	struct stat dst;
+	int err= 0;
+	struct partition geometry;
+
+	if (submerged) {
+		/* Geometry already known. */
+		sort();
+		return;
+	}
+	precise= 0;
+	cylinders= 0;
+	recompute0();
+	if (device < 0) return;
+
+	/* Try to guess the geometry from the partition table. */
+	guess_geometry();
+
+	/* Try to get the geometry from the driver. */
+	(void) fstat(device, &dst);
+
+	if (S_ISBLK(dst.st_mode) || S_ISCHR(dst.st_mode)) {
+		/* Try to get the drive's geometry from the driver. */
+
+		if (ioctl(device, DIOCGETP, &geometry) < 0)
+			err= errno;
+		else {
+			table[0].lowsec= div64u(geometry.base, SECTOR_SIZE);
+			table[0].size= div64u(geometry.size, SECTOR_SIZE);
+			cylinders= geometry.cylinders;
+			heads= geometry.heads;
+			sectors= geometry.sectors;
+			precise= 1;
+		}
+	} else {
+		err= ENODEV;
+	}
+
+	if (err != 0) {
+		/* Getting the geometry from the driver failed, so use the
+		 * alternate geometry.
+		 */
+		if (alt_heads == 0) {
+			alt_cyls= table[0].size / (64 * 32);
+			alt_heads= 64;
+			alt_secs= 32;
+		}
+
+		cylinders= alt_cyls;
+		heads= alt_heads;
+		sectors= alt_secs;
+
+		stat_start(1);
+		printf("Failure to get the geometry of %s: %s", curdev->name,
+			errno == ENOTTY ? "No driver support" : strerror(err));
+		stat_end(5);
+		stat_start(0);
+		printf("The geometry has been guessed as %ux%ux%u",
+						cylinders, heads, sectors);
+		stat_end(5);
+	} else {
+		if (alt_heads == 0) {
+			alt_cyls= cylinders;
+			alt_heads= heads;
+			alt_secs= sectors;
+		}
+
+		if (heads != alt_heads || sectors != alt_secs) {
+			stat_start(1);
+			printf("WARNING:");
+			stat_end(10);
+			stat_start(0);
+			printf(
+"The %ux%ux%u geometry obtained from the device driver does not match",
+				cylinders, heads, sectors);
+			stat_end(10);
+			stat_start(0);
+			printf(
+"the %ux%ux%u geometry implied by the partition table.  Hit 'X' to switch",
+				alt_cyls, alt_heads, alt_secs);
+			stat_end(10);
+			stat_start(0);
+			printf(
+"between the two geometries to see what is best.  Note that the geometry");
+			stat_end(10);
+			stat_start(0);
+			printf(
+"must be correct when the table is written or the system may not boot!");
+			stat_end(10);
+		}
+	}
+
+	/* Show the base and size of the device instead of the whole drive.
+	 * This makes sense for subpartitioning primary partitions.
+	 */
+	if (precise && ioctl(device, DIOCGETP, &geometry) >= 0) {
+		table[0].lowsec= div64u(geometry.base, SECTOR_SIZE);
+		table[0].size= div64u(geometry.size, SECTOR_SIZE);
+	} else {
+		precise= 0;
+	}
+	recompute0();
+	sort();
+}
+
+typedef struct indicators {	/* Partition type to partition name. */
+	unsigned char	ind;
+	char		name[10];
+} indicators_t;
+
+indicators_t ind_table[]= {
+	{ 0x00,		"None"		},
+	{ 0x01,		"FAT-12"	},
+	{ 0x02,		"XENIX /"	},
+	{ 0x03,		"XENIX usr"	},
+	{ 0x04,		"FAT-16"	},
+	{ 0x05,		"EXTENDED"	},
+	{ 0x06,		"FAT-16"	},
+	{ 0x07,		"HPFS/NTFS"	},
+	{ 0x08,		"AIX"		},
+	{ 0x09,		"COHERENT"	},
+	{ 0x0A,		"OS/2"		},
+	{ 0x0B,		"FAT-32"	},
+	{ 0x0C,		"FAT?"		},
+	{ 0x0E,		"FAT?"		},
+	{ 0x0F,		"EXTENDED"	},
+	{ 0x10,		"OPUS"		},
+	{ 0x40,		"VENIX286"	},
+	{ 0x42,		"W2000 Dyn"	},
+	{ 0x52,		"MICROPORT"	},
+	{ 0x63,		"386/IX"	},
+	{ 0x64,		"NOVELL286"	},
+	{ 0x65,		"NOVELL386"	},
+	{ 0x75,		"PC/IX"		},
+	{ 0x80,		"MINIX-OLD"	},
+	{ 0x81,		"MINIX"		},
+	{ 0x82,		"LINUXswap"	},
+	{ 0x83,		"LINUX"		},
+	{ 0x93,		"AMOEBA"	},
+	{ 0x94,		"AMOEBAbad"	},
+	{ 0xA5,		"386BSD"	},
+	{ 0xB7,		"BSDI"		},
+	{ 0xB8,		"BSDI swap"	},
+	{ 0xC7,		"SYRINX"	},
+	{ 0xDB,		"CPM"		},
+	{ 0xFF,		"BADBLOCKS"	},
+};
+
+char *typ2txt(int ind)
+/* Translate a numeric partition indicator for human eyes. */
+{
+	indicators_t *pind;
+
+	for (pind= ind_table; pind < arraylimit(ind_table); pind++) {
+		if (pind->ind == ind) return pind->name;
+	}
+	return "";
+}
+
+int round_sysind(int ind, int delta)
+/* Find the next known partition type starting with ind in direction delta. */
+{
+	indicators_t *pind;
+
+	ind= (ind + delta) & 0xFF;
+
+	if (delta < 0) {
+		for (pind= arraylimit(ind_table)-1; pind->ind > ind; pind--) {}
+	} else {
+		for (pind= ind_table; pind->ind < ind; pind++) {}
+	}
+	return pind->ind;
+}
+
+/* Objects on the screen, either simple pieces of the text or the cylinder
+ * number of the start of partition three.
+ */
+typedef enum objtype {
+	O_INFO, O_TEXT, O_DEV, O_SUB,
+	O_TYPTXT, O_SORT, O_NUM, O_TYPHEX,
+	O_CYL, O_HEAD, O_SEC,
+	O_SCYL, O_SHEAD, O_SSEC, O_LCYL, O_LHEAD, O_LSEC, O_BASE, O_SIZE, O_KB
+} objtype_t;
+
+#define rjust(type)	((type) >= O_TYPHEX)
+#define computed(type)	((type) >= O_TYPTXT)
+
+typedef struct object {
+	struct object	*next;
+	objtype_t	type;		/* Text field, cylinder number, etc. */
+	char		flags;		/* Modifiable? */
+	char		row;
+	char		col;
+	char		len;
+	struct part_entry *entry;	/* What does the object refer to? */
+	char		  *text;
+	char		value[20];	/* Value when printed. */
+} object_t;
+
+#define OF_MOD		0x01	/* Object value is modifiable. */
+#define OF_ODD		0x02	/* It has a somewhat odd value. */
+#define OF_BAD		0x04	/* Its value is no good at all. */
+
+/* Events: (Keypress events are the value of the key pressed.) */
+#define E_ENTER		(-1)	/* Cursor moves onto object. */
+#define E_LEAVE		(-2)	/* Cursor leaves object. */
+#define E_WRITE		(-3)	/* Write, but not by typing 'w'. */
+
+/* The O_SIZE objects have a dual identity. */
+enum howend { SIZE, LAST } howend= SIZE;
+
+object_t *world= nil;
+object_t *curobj= nil;
+
+object_t *newobject(objtype_t type, int flags, int row, int col, int len)
+/* Make a new object given a type, flags, position and length on the screen. */
+{
+	object_t *new;
+	object_t **aop= &world;
+
+	new= alloc(sizeof(*new));
+
+	new->type= type;
+	new->flags= flags;
+	new->row= row;
+	new->col= col;
+	new->len= len;
+	new->entry= nil;
+	new->text= "";
+	new->value[0]= 0;
+
+	new->next= *aop;
+	*aop= new;
+
+	return new;
+}
+
+unsigned long entry2base(struct part_entry *pe)
+/* Return the base sector of the partition if defined. */
+{
+	return pe->sysind == NO_PART ? 0 : pe->lowsec;
+}
+
+unsigned long entry2last(struct part_entry *pe)
+{
+	return pe->sysind == NO_PART ? -1 : pe->lowsec + pe->size - 1;
+}
+
+unsigned long entry2size(struct part_entry *pe)
+{
+	return pe->sysind == NO_PART ? 0 : pe->size;
+}
+
+int overlap(unsigned long sec)
+/* See if sec is part of another partition. */
+{
+	struct part_entry *pe;
+
+	for (pe= table + 1; pe <= table + NR_PARTITIONS; pe++) {
+		if (pe->sysind == NO_PART) continue;
+
+		if (pe->lowsec < sec && sec < pe->lowsec + pe->size)
+			return 1;
+	}
+	return 0;
+}
+
+int aligned(unsigned long sec, unsigned unit)
+/* True if sec is aligned to unit or if it is no problem if it is unaligned. */
+{
+	return (offset != 0 && extbase == 0) || (sec % unit == 0);
+}
+
+void print(object_t *op)
+/* Print an object's value if it changed. */
+{
+	struct part_entry *pe= op->entry;
+	int n;
+	unsigned long t;
+	char *name;
+	int oldflags;
+	char oldvalue[20];
+
+	/* Remember the old flags and value. */
+	oldflags= op->flags;
+	strcpy(oldvalue, op->value);
+
+	op->flags&= ~(OF_ODD | OF_BAD);
+
+	switch (op->type) {
+	case O_INFO:		{
+				/* Current field. */
+		static struct field { int type; char *name; } fields[]= {
+			{ O_DEV,	"Select device"		},
+			{ O_NUM,	"Active flag"		},
+			{ O_TYPHEX,	"Hex partition type"	},
+			{ O_TYPTXT,	"Partition type"	},
+			{ O_SCYL,	"Start cylinder"	},
+			{ O_SHEAD,	"Start head"		},
+			{ O_SSEC,	"Start sector"		},
+			{ O_CYL,	"Number of cylinders"	},
+			{ O_HEAD,	"Number of heads"	},
+			{ O_SEC,	"Sectors per track"	},
+			{ O_LCYL,	"Last cylinder"		},
+			{ O_LHEAD,	"Last head"		},
+			{ O_LSEC,	"Last sector"		},
+			{ O_BASE,	"Base sector"		},
+			{ O_SIZE,	"Size in sectors"	},
+			{ O_KB,		"Size in kilobytes"	},
+			{ -1,		"?"			},
+		};
+		struct field *fp= fields;
+
+		while (fp->type >= 0 && fp->type != curobj->type) fp++;
+		strcpy(op->value, fp->name);
+		op->flags|= OF_ODD;
+		break;		}
+	case O_TEXT:
+				/* Simple text field. */
+		strcpy(op->value, op->text);
+		break;
+	case O_DEV:
+	case O_SUB:
+				/* Name of currently edited device. */
+		name= op->type == O_DEV ? curdev->name :
+					offset == 0 ? "" : curdev->subname;
+		if ((n= strlen(name)) < op->len) n= op->len;
+		strcpy(op->value, name + (n - op->len));
+		if (device < 0 && op->type == O_DEV) op->flags|= OF_BAD;
+		break;
+	case O_NUM:
+				/* Position and active flag. */
+		sprintf(op->value, "%d%c", (int) (pe - table - 1),
+					pe->bootind & ACTIVE_FLAG ? '*' : ' ');
+		break;
+	case O_SORT:
+				/* Position if the driver sorts the table. */
+		sprintf(op->value, "%s%d",
+			curdev->parttype >= PRIMARY ? "p" :
+				curdev->parttype == SUBPART ? "s" : "",
+			(curdev->parttype == SUBPART ||
+				curdev->parttype == FLOPPY ? pe - table
+					: sort_index[pe - table]) - 1);
+		break;
+	case O_TYPHEX:
+				/* Hex partition type indicator. */
+		sprintf(op->value, "%02X", pe->sysind);
+		break;
+	case O_TYPTXT:
+				/* Ascii partition type indicator. */
+		strcpy(op->value, typ2txt(pe->sysind));
+		break;
+	case O_SCYL:
+				/* Partition's start cylinder. */
+		sprintf(op->value, "%lu", entry2base(pe) / secpcyl);
+		break;
+	case O_SHEAD:
+				/* Start head. */
+		t= entry2base(pe);
+		sprintf(op->value, "%lu", t % secpcyl / sectors);
+		if (!aligned(t, secpcyl) && t != table[0].lowsec + sectors)
+			op->flags|= OF_ODD;
+		break;
+	case O_SSEC:
+				/* Start sector. */
+		t= entry2base(pe);
+		sprintf(op->value, "%lu", t % sectors);
+		if (!aligned(t, sectors)) op->flags|= OF_ODD;
+		break;
+	case O_CYL:
+				/* Number of cylinders. */
+		sprintf(op->value, "%u", cylinders);
+		break;
+	case O_HEAD:
+				/* Number of heads. */
+		sprintf(op->value, "%u", heads);
+		break;
+	case O_SEC:
+				/* Number of sectors per track. */
+		sprintf(op->value, "%u", sectors);
+		break;
+	case O_LCYL:
+				/* Partition's last cylinder. */
+		t= entry2last(pe);
+		sprintf(op->value, "%lu", t == -1 ? 0 : t / secpcyl);
+		break;
+	case O_LHEAD:
+				/* Partition's last head. */
+		t= entry2last(pe);
+		sprintf(op->value, "%lu", t == -1 ? 0 : t % secpcyl / sectors);
+		if (!aligned(t + 1, secpcyl)) op->flags|= OF_ODD;
+		break;
+	case O_LSEC:
+				/* Partition's last sector. */
+		t= entry2last(pe);
+		sprintf(op->value, t == -1 ? "-1" : "%lu", t % sectors);
+		if (!aligned(t + 1, sectors)) op->flags|= OF_ODD;
+		break;
+	case O_BASE:
+				/* Partition's base sector. */
+		sprintf(op->value, "%lu", entry2base(pe));
+		if (pe->sysind != NO_PART && pe != &table[0]
+		   && (pe->lowsec <= table[0].lowsec || overlap(pe->lowsec)))
+			op->flags|= OF_BAD;
+		break;
+	case O_SIZE:
+				/* Size of partitition in sectors. */
+		t= howend == SIZE ? entry2size(pe) : entry2last(pe);
+		sprintf(op->value, "%lu", pe->sysind == NO_PART ? 0 : t);
+		if (pe->sysind != NO_PART && (pe->size == 0
+		    || pe->lowsec + pe->size > table[0].lowsec + table[0].size
+		    || overlap(pe->lowsec + pe->size)))
+			op->flags|= OF_BAD;
+		break;
+	case O_KB:
+				/* Size of partitition in kilobytes. */
+		sprintf(op->value, "%lu", entry2size(pe) / 2);
+		break;
+	default:
+		sprintf(op->value, "?? %d ??", op->type);
+	}
+
+	if (device < 0 && computed(op->type)) strcpy(op->value, "?");
+
+	/* If a value overflows the print field then show a blank
+	 * reverse video field.
+	 */
+	if ((n= strlen(op->value)) > op->len) {
+		n= 0;
+		op->flags|= OF_BAD;
+	}
+
+	/* Right or left justified? */
+	if (rjust(op->type)) {
+		memmove(op->value + (op->len - n), op->value, n);
+		memset(op->value, ' ', op->len - n);
+	} else {
+		memset(op->value + n, ' ', op->len - n);
+	}
+	op->value[op->len]= 0;
+
+	if ((op->flags & (OF_ODD | OF_BAD)) == (oldflags & (OF_ODD | OF_BAD))
+				&& strcmp(op->value, oldvalue) == 0) {
+		/* The value did not change. */
+		return;
+	}
+
+	set_cursor(op->row, rjust(op->type) ? op->col - (op->len-1) : op->col);
+
+	if (op->flags & OF_BAD) tputs(t_so, 1, putchr);
+	else
+	if (op->flags & OF_ODD) tputs(t_md, 1, putchr);
+	putstr(op->value);
+	if (op->flags & OF_BAD) tputs(t_se, 1, putchr);
+	else
+	if (op->flags & OF_ODD) tputs(t_me, 1, putchr);
+}
+
+void display(void)
+/* Repaint all objects that changed. */
+{
+	object_t *op;
+
+	for (op= world; op != nil; op= op->next) print(op);
+}
+
+int typing;	/* Set if a digit has been typed to set a value. */
+int magic;	/* Changes when using the magic key. */
+
+void event(int ev, object_t *op);
+
+void m_redraw(int ev, object_t *op)
+/* Redraw the screen. */
+{
+	object_t *op2;
+
+	if (ev != ctrl('L')) return;
+
+	clear_screen();
+	for (op2= world; op2 != nil; op2= op2->next) op2->value[0]= 0;
+}
+
+void m_toggle(int ev, object_t *op)
+/* Toggle between the driver and alternate geometry. */
+{
+	unsigned t;
+
+	if (ev != 'X') return;
+	if (alt_cyls == cylinders && alt_heads == heads && alt_secs == sectors)
+		return;
+
+	t= cylinders; cylinders= alt_cyls; alt_cyls= t;
+	t= heads; heads= alt_heads; alt_heads= t;
+	t= sectors; sectors= alt_secs; alt_secs= t;
+	dirty= 1;
+	recompute0();
+}
+
+char size_last[]= "Size";
+
+void m_orientation(int ev, object_t *op)
+{
+	if (ev != ' ') return;
+
+	switch (howend) {
+	case SIZE:
+		howend= LAST;
+		strcpy(size_last, "Last");
+		break;
+	case LAST:
+		howend= SIZE;
+		strcpy(size_last, "Size");
+	}
+}
+
+void m_move(int ev, object_t *op)
+/* Move to the nearest modifiably object in the intended direction.  Objects
+ * on the same row or column are really near.
+ */
+{
+	object_t *near, *op2;
+	unsigned dist, d2, dr, dc;
+
+	if (ev != 'h' && ev != 'j' && ev != 'k' && ev != 'l' && ev != 'H')
+		return;
+
+	if (device < 0) {
+		/* No device open?  Then try to read first. */
+		event('r', op);
+		if (device < 0) return;
+	}
+
+	near= op;
+	dist= -1;
+
+	for (op2= world; op2 != nil; op2= op2->next) {
+		if (op2 == op || !(op2->flags & OF_MOD)) continue;
+
+		dr= abs(op2->row - op->row);
+		dc= abs(op2->col - op->col);
+
+		d2= 25*dr*dr + dc*dc;
+		if (op2->row != op->row && op2->col != op->col) d2+= 1000;
+
+		switch (ev) {
+		case 'h':	/* Left */
+			if (op2->col >= op->col) d2= -1;
+			break;
+		case 'j':	/* Down */
+			if (op2->row <= op->row) d2= -1;
+			break;
+		case 'k':	/* Up */
+			if (op2->row >= op->row) d2= -1;
+			break;
+		case 'l':	/* Right */
+			if (op2->col <= op->col) d2= -1;
+			break;
+		case 'H':	/* Home */
+			if (op2->type == O_DEV) d2= 0;
+		}
+		if (d2 < dist) { near= op2; dist= d2; }
+	}
+	if (near != op) event(E_LEAVE, op);
+	event(E_ENTER, near);
+}
+
+void m_updown(int ev, object_t *op)
+/* Move a partition table entry up or down. */
+{
+	int i, j;
+	struct part_entry tmp;
+	int tmpx;
+
+	if (ev != ctrl('K') && ev != ctrl('J')) return;
+	if (op->entry == nil) return;
+
+	i= op->entry - table;
+	if (ev == ctrl('K')) {
+		if (i <= 1) return;
+		j= i-1;
+	} else {
+		if (i >= NR_PARTITIONS) return;
+		j= i+1;
+	}
+
+	tmp= table[i]; table[i]= table[j]; table[j]= tmp;
+	tmpx= existing[i]; existing[i]= existing[j]; existing[j]= tmpx;
+	sort();
+	dirty= 1;
+	event(ev == ctrl('K') ? 'k' : 'j', op);
+}
+
+void m_enter(int ev, object_t *op)
+/* We've moved onto this object. */
+{
+	if (ev != E_ENTER && ev != ' ' && ev != '<' && ev != '>' && ev != 'X')
+		return;
+	curobj= op;
+	typing= 0;
+	magic= 0;
+}
+
+void m_leave(int ev, object_t *op)
+/* About to leave this object. */
+{
+	if (ev != E_LEAVE) return;
+}
+
+int within(unsigned *var, unsigned low, unsigned value, unsigned high)
+/* Only set *var to value if it looks reasonable. */
+{
+	if (low <= value && value <= high) {
+		*var= value;
+		return 1;
+	} else
+		return 0;
+}
+
+int lwithin(unsigned long *var, unsigned long low, unsigned long value,
+							unsigned long high)
+{
+	if (low <= value && value <= high) {
+		*var= value;
+		return 1;
+	} else
+		return 0;
+}
+
+int nextdevice(object_t *op, int delta)
+/* Select the next or previous device from the device list. */
+{
+	dev_t rdev;
+
+	if (offset != 0) return 0;
+	if (dirty) event(E_WRITE, op);
+	if (dirty) return 0;
+
+	if (device >= 0) {
+		(void) close(device);
+		device= -1;
+	}
+	recompute0();
+
+	rdev= curdev->rdev;
+	if (delta < 0) {
+		do
+			curdev= curdev->prev;
+		while (delta < -1 && major(curdev->rdev) == major(rdev)
+			&& curdev->rdev < rdev);
+	} else {
+		do
+			curdev= curdev->next;
+		while (delta > 1 && major(curdev->rdev) == major(rdev)
+			&& curdev->rdev > rdev);
+	}
+	return 1;
+}
+
+void check_ind(struct part_entry *pe)
+/* If there are no other partitions then make this new one active. */
+{
+	struct part_entry *pe2;
+
+	if (pe->sysind != NO_PART) return;
+
+	for (pe2= table + 1; pe2 < table + 1 + NR_PARTITIONS; pe2++)
+		if (pe2->sysind != NO_PART || pe2->bootind & ACTIVE_FLAG) break;
+
+	if (pe2 == table + 1 + NR_PARTITIONS) pe->bootind= ACTIVE_FLAG;
+}
+
+int check_existing(struct part_entry *pe)
+/* Check and if not ask if an existing partition may be modified. */
+{
+	static int expert= 0;
+	int c;
+
+	if (expert || pe == nil || !existing[pe - table]) return 1;
+
+	stat_start(1);
+	putstr("Do you wish to modify existing partitions? (y/n) ");
+	fflush(stdout);
+	while ((c= getchar()) != 'y' && c != 'n') {}
+	putchr(c);
+	stat_end(3);
+	return (expert= (c == 'y'));
+}
+
+void m_modify(int ev, object_t *op)
+/* Increment, decrement, set, or toggle the value of an object, using
+ * arithmetic tricks the author doesn't understand either.
+ */
+{
+	object_t *op2;
+	struct part_entry *pe= op->entry;
+	int mul, delta;
+	unsigned level= 1;
+	unsigned long surplus;
+	int radix= op->type == O_TYPHEX ? 0x10 : 10;
+	unsigned long t;
+
+	if (device < 0 && op->type != O_DEV) return;
+
+	switch (ev) {
+	case '-':
+		mul= radix; delta= -1; typing= 0;
+		break;
+	case '+':
+		mul= radix; delta= 1; typing= 0;
+		break;
+	case '\b':
+		if (!typing) return;
+		mul= 1; delta= 0;
+		break;
+	case '\r':
+		typing= 0;
+		return;
+	default:
+		if ('0' <= ev && ev <= '9')
+			delta= ev - '0';
+		else
+		if (radix == 0x10 && 'a' <= ev && ev <= 'f')
+			delta= ev - 'a' + 10;
+		else
+		if (radix == 0x10 && 'A' <= ev && ev <= 'F')
+			delta= ev - 'A' + 10;
+		else
+			return;
+
+		mul= typing ? radix*radix : 0;
+		typing= 1;
+	}
+	magic= 0;
+
+	if (!check_existing(pe)) return;
+
+	switch (op->type) {
+	case O_DEV:
+		if (ev != '-' && ev != '+') return;
+		if (!nextdevice(op, delta)) return;
+		break;
+	case O_CYL:
+		if (!within(&cylinders, 1,
+			cylinders * mul / radix + delta, 1024)) return;
+		recompute0();
+		break;
+	case O_HEAD:
+		if (!within(&heads, 1, heads * mul / radix + delta, 255))
+			return;
+		recompute0();
+		break;
+	case O_SEC:
+		if (!within(&sectors, 1, sectors * mul / radix + delta, 63))
+			return;
+		recompute0();
+		break;
+	case O_NUM:
+		if (ev != '-' && ev != '+') return;
+		for (op2= world; op2 != nil; op2= op2->next) {
+			if (op2->type == O_NUM && ev == '+')
+				op2->entry->bootind= 0;
+		}
+		op->entry->bootind= ev == '+' ? ACTIVE_FLAG : 0;
+		break;
+	case O_TYPHEX:
+		check_ind(pe);
+		pe->sysind= pe->sysind * mul / radix + delta;
+		break;
+	case O_TYPTXT:
+		if (ev != '-' && ev != '+') return;
+		check_ind(pe);
+		pe->sysind= round_sysind(pe->sysind, delta);
+		break;
+	case O_SCYL:
+		level= heads;
+	case O_SHEAD:
+		level*= sectors;
+	case O_SSEC:
+		if (op->type != O_SCYL && ev != '-' && ev != '+') return;
+	case O_BASE:
+		if (pe->sysind == NO_PART) memset(pe, 0, sizeof(*pe));
+		t= pe->lowsec;
+		surplus= t % level;
+		if (!lwithin(&t, 0L,
+			(t / level * mul / radix + delta) * level + surplus,
+			MAXSIZE)) return;
+		if (howend == LAST || op->type != O_BASE)
+			pe->size-= t - pe->lowsec;
+		pe->lowsec= t;
+		check_ind(pe);
+		if (pe->sysind == NO_PART) pe->sysind= MINIX_PART;
+		break;
+	case O_LCYL:
+		level= heads;
+	case O_LHEAD:
+		level*= sectors;
+	case O_LSEC:
+		if (op->type != O_LCYL && ev != '-' && ev != '+') return;
+
+		if (pe->sysind == NO_PART) memset(pe, 0, sizeof(*pe));
+		t= pe->lowsec + pe->size - 1 + level;
+		surplus= t % level - mul / radix * level;
+		if (!lwithin(&t, 0L,
+			(t / level * mul / radix + delta) * level + surplus,
+			MAXSIZE)) return;
+		pe->size= t - pe->lowsec + 1;
+		check_ind(pe);
+		if (pe->sysind == NO_PART) pe->sysind= MINIX_PART;
+		break;
+	case O_KB:
+		level= 2;
+		if (mul == 0) pe->size= 0;	/* new value, no surplus */
+	case O_SIZE:
+		if (pe->sysind == NO_PART) {
+			if (op->type == O_KB || howend == SIZE) {
+				/* First let loose magic to set the base. */
+				event('m', op);
+				magic= 0;
+				pe->size= 0;
+				event(ev, op);
+				return;
+			}
+			memset(pe, 0, sizeof(*pe));
+		}
+		t= (op->type == O_KB || howend == SIZE) ? pe->size
+						: pe->lowsec + pe->size - 1;
+		surplus= t % level;
+		if (!lwithin(&t, 0L,
+			(t / level * mul / radix + delta) * level + surplus,
+			MAXSIZE)) return;
+		pe->size= (op->type == O_KB || howend == SIZE) ? t :
+							t - pe->lowsec + 1;
+		check_ind(pe);
+		if (pe->sysind == NO_PART) pe->sysind= MINIX_PART;
+		break;
+	default:
+		return;
+	}
+
+	/* The order among the entries may have changed. */
+	sort();
+	dirty= 1;
+}
+
+unsigned long spell[3 + 4 * (1+NR_PARTITIONS)];
+int nspells;
+objtype_t touching;
+
+void newspell(unsigned long charm)
+/* Add a new spell, descending order for the base, ascending for the size. */
+{
+	int i, j;
+
+	if (charm - table[0].lowsec > table[0].size) return;
+
+	for (i= 0; i < nspells; i++) {
+		if (charm == spell[i]) return;	/* duplicate */
+
+		if (touching == O_BASE) {
+			if (charm == table[0].lowsec + table[0].size) return;
+			if ((spell[0] - charm) < (spell[0] - spell[i])) break;
+		} else {
+			if (charm == table[0].lowsec) return;
+			if ((charm - spell[0]) < (spell[i] - spell[0])) break;
+		}
+	}
+	for (j= ++nspells; j > i; j--) spell[j]= spell[j-1];
+	spell[i]= charm;
+}
+
+void m_magic(int ev, object_t *op)
+/* Apply magic onto a base or size number. */
+{
+	struct part_entry *pe= op->entry, *pe2;
+	int rough= (offset != 0 && extbase == 0);
+
+	if (ev != 'm' || device < 0) return;
+	typing= 0;
+
+	if (!check_existing(pe)) return;
+
+	if (magic == 0) {
+		/* See what magic we can let loose on this value. */
+		nspells= 1;
+
+		/* First spell, the current value. */
+		switch (op->type) {
+		case O_SCYL:
+		case O_SHEAD:	/* Start of partition. */
+		case O_SSEC:
+		case O_BASE:
+			touching= O_BASE;
+			spell[0]= pe->lowsec;
+			break;
+		case O_LCYL:
+		case O_LHEAD:
+		case O_LSEC:	/* End of partition. */
+		case O_KB:
+		case O_SIZE:
+			touching= O_SIZE;
+			spell[0]= pe->lowsec + pe->size;
+			break;
+		default:
+			return;
+		}
+		if (pe->sysind == NO_PART) {
+			memset(pe, 0, sizeof(*pe));
+			check_ind(pe);
+			pe->sysind= MINIX_PART;
+			spell[0]= 0;
+			if (touching == O_SIZE) {
+				/* First let loose magic on the base. */
+				object_t *op2;
+
+				for (op2= world; op2 != nil; op2= op2->next) {
+					if (op2->row == op->row &&
+							op2->type == O_BASE) {
+						event('m', op2);
+					}
+				}
+				magic= 0;
+				event('m', op);
+				return;
+			}
+		}
+		/* Avoid the first sector on the device. */
+		if (spell[0] == table[0].lowsec) newspell(spell[0] + 1);
+
+		/* Further interesting values are the the bases of other
+		 * partitions or their ends.
+		 */
+		for (pe2= table; pe2 < table + 1 + NR_PARTITIONS; pe2++) {
+			if (pe2 == pe || pe2->sysind == NO_PART) continue;
+			if (pe2->lowsec == table[0].lowsec)
+				newspell(table[0].lowsec + 1);
+			else
+				newspell(pe2->lowsec);
+			newspell(pe2->lowsec + pe2->size);
+			if (touching == O_BASE && howend == SIZE) {
+				newspell(pe2->lowsec - pe->size);
+				newspell(pe2->lowsec + pe2->size - pe->size);
+			}
+			if (pe2->lowsec % sectors != 0) rough= 1;
+		}
+		/* Present values rounded up to the next cylinder unless
+		 * the table is already a mess.  Use "start + 1 track" instead
+		 * of "start + 1 cylinder".  Also add the end of the last
+		 * cylinder.
+		 */
+		if (!rough) {
+			unsigned long n= spell[0];
+			if (n == table[0].lowsec) n++;
+			n= (n + sectors - 1) / sectors * sectors;
+			if (n != table[0].lowsec + sectors)
+				n= (n + secpcyl - 1) / secpcyl * secpcyl;
+			newspell(n);
+			if (touching == O_SIZE)
+				newspell(table[0].size / secpcyl * secpcyl);
+		}
+	}
+	/* Magic has been applied, a spell needs to be chosen. */
+
+	if (++magic == nspells) magic= 0;
+
+	if (touching == O_BASE) {
+		if (howend == LAST) pe->size-= spell[magic] - pe->lowsec;
+		pe->lowsec= spell[magic];
+	} else
+		pe->size= spell[magic] - pe->lowsec;
+
+	/* The order among the entries may have changed. */
+	sort();
+	dirty= 1;
+}
+
+typedef struct diving {
+	struct diving	*up;
+	struct part_entry  old0;
+	char		*oldsubname;
+	parttype_t	oldparttype;
+	unsigned long	oldoffset;
+	unsigned long	oldextbase;
+} diving_t;
+
+diving_t *diving= nil;
+
+void m_in(int ev, object_t *op)
+/* Go down into a primary or extended partition. */
+{
+	diving_t *newdiv;
+	struct part_entry *pe= op->entry, ext;
+	int n;
+
+	if (ev != '>' || device < 0 || pe == nil || pe == &table[0]
+		|| (!(pe->sysind == MINIX_PART && offset == 0)
+					&& !ext_part(pe->sysind))
+		|| pe->size == 0) return;
+
+	ext= *pe;
+	if (extbase != 0) ext.size= extbase + extsize - ext.lowsec;
+
+	if (dirty) event(E_WRITE, op);
+	if (dirty) return;
+	if (device >= 0) { close(device); device= -1; }
+
+	newdiv= alloc(sizeof(*newdiv));
+	newdiv->old0= table[0];
+	newdiv->oldsubname= curdev->subname;
+	newdiv->oldparttype= curdev->parttype;
+	newdiv->oldoffset= offset;
+	newdiv->oldextbase= extbase;
+	newdiv->up= diving;
+	diving= newdiv;
+
+	table[0]= ext;
+
+	n= strlen(diving->oldsubname);
+	curdev->subname= alloc((n + 3) * sizeof(curdev->subname[0]));
+	strcpy(curdev->subname, diving->oldsubname);
+	curdev->subname[n++]= ':';
+	curdev->subname[n++]= '0' + (pe - table - 1);
+	curdev->subname[n]= 0;
+
+	curdev->parttype= curdev->parttype == PRIMARY ? SUBPART : DUNNO;
+	offset= ext.lowsec;
+	if (ext_part(ext.sysind) && extbase == 0) {
+		extbase= ext.lowsec;
+		extsize= ext.size;
+		curdev->parttype= DUNNO;
+	}
+
+	submerged= 1;
+	event('r', op);
+}
+
+void m_out(int ev, object_t *op)
+/* Go up from an extended or subpartition table to its enclosing. */
+{
+	diving_t *olddiv;
+
+	if (ev != '<' || diving == nil) return;
+
+	if (dirty) event(E_WRITE, op);
+	if (dirty) return;
+	if (device >= 0) { close(device); device= -1; }
+
+	olddiv= diving;
+	diving= olddiv->up;
+
+	table[0]= olddiv->old0;
+
+	free(curdev->subname);
+	curdev->subname= olddiv->oldsubname;
+
+	curdev->parttype= olddiv->oldparttype;
+	offset= olddiv->oldoffset;
+	extbase= olddiv->oldextbase;
+
+	free(olddiv);
+
+	event('r', op);
+	if (diving == nil) submerged= 0;	/* We surfaced. */
+}
+
+void installboot(unsigned char *bootblock, char *masterboot)
+/* Install code from a master bootstrap into a boot block. */
+{
+	FILE *mfp;
+	struct exec hdr;
+	int n;
+	char *err;
+
+	if ((mfp= fopen(masterboot, "r")) == nil) {
+		err= strerror(errno);
+		goto m_err;
+	}
+
+	n= fread(&hdr, sizeof(char), A_MINHDR, mfp);
+	if (ferror(mfp)) {
+		err= strerror(errno);
+		fclose(mfp);
+		goto m_err;
+	}
+
+	if (n < A_MINHDR || BADMAG(hdr) || hdr.a_cpu != A_I8086) {
+		err= "Not an 8086 executable";
+		fclose(mfp);
+		goto m_err;
+	}
+
+	if (hdr.a_text + hdr.a_data > PART_TABLE_OFF) {
+		err= "Does not fit in a boot sector";
+		fclose(mfp);
+		goto m_err;
+	}
+
+	fseek(mfp, hdr.a_hdrlen, 0);
+	fread(bootblock, sizeof(char), (size_t) (hdr.a_text + hdr.a_data), mfp);
+	if (ferror(mfp)) {
+		err= strerror(errno);
+		fclose(mfp);
+		goto m_err;
+	}
+	fclose(mfp);
+
+	/* Bootstrap installed. */
+	return;
+
+    m_err:
+	stat_start(1);
+	printf("%s: %s", masterboot, err);
+	stat_end(5);
+}
+
+ssize_t boot_readwrite(int rw)
+/* Read (0) or write (1) the boot sector. */
+{
+	u64_t off64 = mul64u(offset, SECTOR_SIZE);
+	int r;
+
+#if __minix_vmd
+	/* Minix-vmd has a 64 bit seek. */
+	if (fcntl(device, F_SEEK, off64) < 0) return -1;
+#else
+	/* Minix has to gross things with the partition base. */
+	struct partition geom0, geom_seek;
+
+	if (offset >= (LONG_MAX / SECTOR_SIZE - 1)) {
+		/* Move partition base. */
+		if (ioctl(device, DIOCGETP, &geom0) < 0) return -1;
+		geom_seek.base = add64(geom0.base, off64);
+		geom_seek.size = cvu64(cmp64(add64u(off64, SECTOR_SIZE),
+			geom0.size) <= 0 ? _STATIC_BLOCK_SIZE : 0);
+		sync();
+		if (ioctl(device, DIOCSETP, &geom_seek) < 0) return -1;
+		if (lseek(device, (off_t) 0, SEEK_SET) == -1) return -1;
+	} else {
+		/* Can reach this point normally. */
+		if (lseek(device, (off_t) offset * SECTOR_SIZE, SEEK_SET) == -1)
+			return -1;
+	}
+#endif
+
+	switch (rw) {
+	case 0:	r= read(device, bootblock, SECTOR_SIZE);	break;
+	case 1:	r= write(device, bootblock, SECTOR_SIZE);	break;
+	}
+
+#if !__minix_vmd
+	if (offset >= (LONG_MAX / SECTOR_SIZE - 1)) {
+		/* Restore partition base and size. */
+		sync();
+		if (ioctl(device, DIOCSETP, &geom0) < 0) return -1;
+	}
+#endif
+	return r;
+}
+
+void m_read(int ev, object_t *op)
+/* Read the partition table from the current device. */
+{
+	int i, mode, n;
+	struct part_entry *pe;
+
+	if (ev != 'r' || device >= 0) return;
+
+	/* Open() may cause kernel messages: */
+	stat_start(0);
+	fflush(stdout);
+
+	if (((device= open(curdev->name, mode= O_RDWR, 0666)) < 0
+		&& (errno != EACCES
+			|| (device= open(curdev->name, mode= O_RDONLY)) < 0))
+	) {
+		stat_start(1);
+		printf("%s: %s", curdev->name, strerror(errno));
+		stat_end(5);
+		if (device >= 0) { close(device); device= -1; }
+		return;
+	}
+
+	/* Assume up to five lines of kernel messages. */
+	statusrow+= 5-1;
+	stat_end(5);
+
+	if (mode == O_RDONLY) {
+		stat_start(1);
+		printf("%s: Readonly", curdev->name);
+		stat_end(5);
+	}
+	memset(bootblock, 0, sizeof(bootblock));
+
+	n= boot_readwrite(0);
+
+	if (n <= 0) stat_start(1);
+	if (n < 0) {
+		printf("%s: %s", curdev->name, strerror(errno));
+		close(device);
+		device= -1;
+	} else
+	if (n < SECTOR_SIZE) printf("%s: Unexpected EOF", curdev->subname);
+	if (n <= 0) stat_end(5);
+
+	if (n < SECTOR_SIZE) n= SECTOR_SIZE;
+
+	memcpy(table+1, bootblock+PART_TABLE_OFF,
+					NR_PARTITIONS * sizeof(table[1]));
+	for (i= 1; i <= NR_PARTITIONS; i++) {
+		if ((table[i].bootind & ~ACTIVE_FLAG) != 0) break;
+	}
+	if (i <= NR_PARTITIONS || bootblock[510] != 0x55
+				|| bootblock[511] != 0xAA) {
+		/* Invalid boot block, install bootstrap, wipe partition table.
+		 */
+		memset(bootblock, 0, sizeof(bootblock));
+		installboot(bootblock, MASTERBOOT);
+		memset(table+1, 0, NR_PARTITIONS * sizeof(table[1]));
+		stat_start(1);
+		printf("%s: Invalid partition table (reset)", curdev->subname);
+		stat_end(5);
+	}
+
+	/* Fix an extended partition table up to something mere mortals can
+	 * understand.  Record already defined partitions.
+	 */
+	for (i= 1; i <= NR_PARTITIONS; i++) {
+		pe= &table[i];
+		if (extbase != 0 && pe->sysind != NO_PART)
+			pe->lowsec+= ext_part(pe->sysind) ? extbase : offset;
+		existing[i]= pe->sysind != NO_PART;
+	}
+	geometry();
+	dirty= 0;
+
+	/* Warn about grave dangers ahead. */
+	if (extbase != 0) {
+		stat_start(1);
+		printf("Warning: You are in an extended partition.");
+		stat_end(5);
+	}
+}
+
+void m_write(int ev, object_t *op)
+/* Write the partition table back if modified. */
+{
+	int c;
+	struct part_entry new_table[NR_PARTITIONS], *pe;
+
+	if (ev != 'w' && ev != E_WRITE) return;
+	if (device < 0) { dirty= 0; return; }
+	if (!dirty) {
+		if (ev == 'w') {
+			stat_start(1);
+			printf("%s is not changed, or has already been written",
+							curdev->subname);
+			stat_end(2);
+		}
+		return;
+	}
+
+	if (bootblock[510] != 0x55 || bootblock[511] != 0xAA) {
+		/* Invalid boot block, warn user. */
+		stat_start(1);
+		printf("Warning: About to write a new table on %s",
+							curdev->subname);
+		stat_end(5);
+	}
+	if (extbase != 0) {
+		/* Will this stop the luser?  Probably not... */
+		stat_start(1);
+		printf("You have changed an extended partition.  Bad Idea.");
+		stat_end(5);
+	}
+	stat_start(1);
+	putstr("Save partition table? (y/n) ");
+	fflush(stdout);
+
+	while ((c= getchar()) != 'y' && c != 'n' && c != ctrl('?')) {}
+
+	if (c == ctrl('?')) putstr("DEL"); else putchr(c);
+	stat_end(5);
+	if (c == 'n' && ev == E_WRITE) dirty= 0;
+	if (c != 'y') return;
+
+	memcpy(new_table, table+1, NR_PARTITIONS * sizeof(table[1]));
+	for (pe= new_table; pe < new_table + NR_PARTITIONS; pe++) {
+		if (pe->sysind == NO_PART) {
+			memset(pe, 0, sizeof(*pe));
+		} else {
+			abs2dos(&pe->start_head, pe->lowsec);
+			abs2dos(&pe->last_head, pe->lowsec + pe->size - 1);
+
+			/* Fear and loathing time: */
+			if (extbase != 0)
+				pe->lowsec-= ext_part(pe->sysind)
+						? extbase : offset;
+		}
+	}
+	memcpy(bootblock+PART_TABLE_OFF, new_table, sizeof(new_table));
+	bootblock[510]= 0x55;
+	bootblock[511]= 0xAA;
+
+	if (boot_readwrite(1) < 0) {
+		stat_start(1);
+		printf("%s: %s", curdev->name, strerror(errno));
+		stat_end(5);
+		return;
+	}
+	dirty= 0;
+}
+
+void m_shell(int ev, object_t *op)
+/* Shell escape, to do calculations for instance. */
+{
+	int r, pid, status;
+	void (*sigint)(int), (*sigquit)(int), (*sigterm)(int);
+
+	if (ev != 's') return;
+
+	reset_tty();
+	fflush(stdout);
+
+	switch (pid= fork()) {
+	case -1:
+		stat_start(1);
+		printf("can't fork: %s\n", strerror(errno));
+		stat_end(3);
+		break;
+	case 0:
+		if (device >= 0) (void) close(device);
+		execl("/bin/sh", "sh", (char *) nil);
+		r= errno;
+		stat_start(1);
+		printf("/bin/sh: %s\n", strerror(errno));
+		stat_end(3);
+		exit(127);
+	}
+	sigint= signal(SIGINT, SIG_IGN);
+	sigquit= signal(SIGQUIT, SIG_IGN);
+	sigterm= signal(SIGTERM, SIG_IGN);
+	while (pid >= 0 && (r= wait(&status)) >= 0 && r != pid) {}
+	(void) signal(SIGINT, sigint);
+	(void) signal(SIGQUIT, sigquit);
+	(void) signal(SIGTERM, sigterm);
+	tty_raw();
+	if (pid < 0)
+		;
+	else
+	if (WIFEXITED(status) && WEXITSTATUS(status) == 127)
+		stat_start(0);	/* Match the stat_start in the child. */
+	else
+		event(ctrl('L'), op);
+}
+
+void m_dump(int ev, object_t *op)
+/* Raw dump of the partition table. */
+{
+	struct part_entry table[NR_PARTITIONS], *pe;
+	int i;
+	unsigned chs[3];
+
+	if (ev != 'p' || device < 0) return;
+
+	memcpy(table, bootblock+PART_TABLE_OFF,
+					NR_PARTITIONS * sizeof(table[0]));
+	for (i= 0; i < NR_PARTITIONS; i++) {
+		pe= &table[i];
+		stat_start(0);
+		dos2chs(&pe->start_head, chs);
+		printf("%2d%c      %02X%15d%5d%4d",
+			i+1,
+			pe->bootind & ACTIVE_FLAG ? '*' : ' ',
+			pe->sysind,
+			chs[0], chs[1], chs[2]);
+		dos2chs(&pe->last_head, chs);
+		printf("%6d%5d%4d%10lu%10ld%9lu",
+			chs[0], chs[1], chs[2],
+			pe->lowsec,
+			howend == SIZE ? pe->size : pe->size + pe->lowsec - 1,
+			pe->size / 2);
+		stat_end(10);
+	}
+	stat_start(0);
+	printf("(Raw dump of the original %.40s table)",
+		curdev->subname);
+	stat_end(10);
+}
+
+int quitting= 0;
+
+void m_quit(int ev, object_t *op)
+/* Write the partition table if modified and exit. */
+{
+	if (ev != 'q' && ev != 'x') return;
+
+	quitting= 1;
+
+	if (dirty) event(E_WRITE, op);
+	if (dirty) quitting= 0;
+}
+
+void m_help(int ev, object_t *op)
+/* For people without a clue; let's hope they can find the '?' key. */
+{
+	static struct help {
+		char	*keys;
+		char	*what;
+	} help[]= {
+	 { "? !",		 "This help / more advice!" },
+	 { "+ - (= _ PgUp PgDn)","Select/increment/decrement/make active" },
+	 { "0-9 (a-f)",		 "Enter value" },
+	 { "hjkl (arrow keys)",	 "Move around" },
+	 { "CTRL-K CTRL-J",	 "Move entry up/down" },
+	 { "CTRL-L",		 "Redraw screen" },
+	 { ">",			 "Start a subpartition table" },
+	 { "<",			 "Back to the primary partition table" },
+	 { "m",			 "Cycle through magic values" },
+	 { "spacebar",		 "Show \"Size\" or \"Last\"" },
+	 { "r w",		 "Read/write partition table" },
+	 { "p s q x",		 "Raw dump / Shell escape / Quit / Exit" },
+	 { "y n DEL",		 "Answer \"yes\", \"no\", \"cancel\"" },
+	};
+	static char *advice[] = {
+"* Choose a disk with '+' and '-', then hit 'r'.",
+"* To change any value: Move to it and use '+', '-' or type the desired value.",
+"* To make a new partition:  Move over to the Size or Kb field of an unused",
+"  partition and type the size.  Hit the 'm' key to pad the partition out to",
+"  a cylinder boundary.  Hit 'm' again to pad it out to the end of the disk.",
+"  You can hit 'm' more than once on a base or size field to see several",
+"  interesting values go by.  Note: Other Operating Systems can be picky about",
+"  partitions that are not padded to cylinder boundaries.  Look for highlighted",
+"  head or sector numbers.",
+"* To reuse a partition:  Change the type to MINIX.",
+"* To delete a partition:  Type a zero in the hex Type field.",
+"* To make a partition active:  Type '+' in the Num field.",
+"* To study the list of keys:  Type '?'.",
+	};
+
+	if (ev == '?') {
+		struct help *hp;
+
+		for (hp= help; hp < arraylimit(help); hp++) {
+			stat_start(0);
+			printf("%-25s - %s", hp->keys, hp->what);
+			stat_end(0);
+		}
+		stat_start(0);
+		putstr("Things like ");
+		putstr(t_so); putstr("this"); putstr(t_se);
+		putstr(" must be checked, but ");
+		putstr(t_md); putstr("this"); putstr(t_me);
+		putstr(" is not really a problem");
+		stat_end(0);
+	} else
+	if (ev == '!') {
+		char **ap;
+
+		for (ap= advice; ap < arraylimit(advice); ap++) {
+			stat_start(0);
+			putstr(*ap);
+			stat_end(0);
+		}
+	}
+}
+
+void event(int ev, object_t *op)
+/* Simply call all modifiers for an event, each one knows when to act. */
+{
+	m_help(ev, op);
+	m_redraw(ev, op);
+	m_toggle(ev, op);
+	m_orientation(ev, op);
+	m_move(ev, op);
+	m_updown(ev, op);
+	m_enter(ev, op);
+	m_leave(ev, op);
+	m_modify(ev, op);
+	m_magic(ev, op);
+	m_in(ev, op);
+	m_out(ev, op);
+	m_read(ev, op);
+	m_write(ev, op);
+	m_shell(ev, op);
+	m_dump(ev, op);
+	m_quit(ev, op);
+}
+
+int keypress(void)
+/* Get a single keypress.  Translate compound keypresses (arrow keys) to
+ * their simpler equivalents.
+ */
+{
+	char ch;
+	int c;
+	int esc= 0;
+
+	set_cursor(curobj->row, curobj->col);
+	fflush(stdout);
+
+	do {
+		if (read(0, &ch, sizeof(ch)) < 0) fatal("stdin");
+		c= (unsigned char) ch;
+		switch (esc) {
+		case 0:
+			switch (c) {
+			case ctrl('['):	esc= 1; break;
+			case '_':	c= '-'; break;
+			case '=':	c= '+'; break;
+			}
+			break;
+		case 1:
+			esc= c == '[' ? 2 : 0;
+			break;
+		case 2:
+			switch (c) {
+			case 'D':	c= 'h';	break;
+			case 'B':	c= 'j';	break;
+			case 'A':	c= 'k';	break;
+			case 'C':	c= 'l';	break;
+			case 'H':	c= 'H';	break;
+			case 'U':
+			case 'S':	c= '-';	break;
+			case 'V':
+			case 'T':	c= '+';	break;
+			}
+			/*FALL THROUGH*/
+		default:
+			esc= 0;
+		}
+	} while (esc > 0);
+
+	switch (c) {
+	case ctrl('B'):	c= 'h';	break;
+	case ctrl('N'):	c= 'j';	break;
+	case ctrl('P'):	c= 'k';	break;
+	case ctrl('F'):	c= 'l';	break;
+	}
+
+	return c;
+}
+
+void mainloop(void)
+/* Get keypress, handle event, display results, reset screen, ad infinitum. */
+{
+	int key;
+
+	while (!quitting) {
+		stat_reset();
+
+		key= keypress();
+
+		event(key, curobj);
+
+		display();
+	}
+}
+
+int main(int argc, char **argv)
+{
+	object_t *op;
+	int i, r, key;
+	struct part_entry *pe;
+
+	/* Define a few objects to show on the screen.  First text: */
+	op= newobject(O_INFO, 0, 0,  2, 19);
+	op= newobject(O_TEXT, 0, 0, 22, 13); op->text= "----first----";
+	op= newobject(O_TEXT, 0, 0, 37, 13); op->text= "--geom/last--";
+	op= newobject(O_TEXT, 0, 0, 52, 18); op->text= "------sectors-----";
+	op= newobject(O_TEXT, 0, 1,  4,  6); op->text= "Device";
+	op= newobject(O_TEXT, 0, 1, 23, 12); op->text= "Cyl Head Sec";
+	op= newobject(O_TEXT, 0, 1, 38, 12); op->text= "Cyl Head Sec";
+	op= newobject(O_TEXT, 0, 1, 56,  4); op->text= "Base";
+	op= newobject(O_TEXT, 0, 1, 66,  4); op->text= size_last;
+	op= newobject(O_TEXT, 0, 1, 78,  2); op->text= "Kb";
+	op= newobject(O_TEXT, 0, 4,  0, 15); op->text= "Num Sort   Type";
+
+	/* The device is the current object: */
+    curobj= newobject(O_DEV,  OF_MOD, 2,  4, 15);
+	op= newobject(O_SUB,       0, 3,  4, 15);
+
+	/* Geometry: */
+	op= newobject(O_CYL,  OF_MOD, 2, 40,  5); op->entry= &table[0];
+	op= newobject(O_HEAD, OF_MOD, 2, 45,  3); op->entry= &table[0];
+	op= newobject(O_SEC,  OF_MOD, 2, 49,  2); op->entry= &table[0];
+
+	/* Objects for the device: */
+	op= newobject(O_SCYL,  0, 3, 25,  5); op->entry= &table[0];
+	op= newobject(O_SHEAD, 0, 3, 30,  3); op->entry= &table[0];
+	op= newobject(O_SSEC,  0, 3, 34,  2); op->entry= &table[0];
+	op= newobject(O_LCYL,  0, 3, 40,  5); op->entry= &table[0];
+	op= newobject(O_LHEAD, 0, 3, 45,  3); op->entry= &table[0];
+	op= newobject(O_LSEC,  0, 3, 49,  2); op->entry= &table[0];
+	op= newobject(O_BASE,  0, 3, 59,  9); op->entry= &table[0];
+	op= newobject(O_SIZE,  0, 3, 69,  9); op->entry= &table[0];
+	op= newobject(O_KB,    0, 3, 79,  9); op->entry= &table[0];
+
+	/* Objects for each partition: */
+	for (r= 5, pe= table+1; pe <= table+NR_PARTITIONS; r++, pe++) {
+		op= newobject(O_NUM,    OF_MOD, r,  1,  2); op->entry= pe;
+		op= newobject(O_SORT,        0, r,  5,  2); op->entry= pe;
+		op= newobject(O_TYPHEX, OF_MOD, r, 10,  2); op->entry= pe;
+		op= newobject(O_TYPTXT, OF_MOD, r, 12,  9); op->entry= pe;
+		op= newobject(O_SCYL,   OF_MOD, r, 25,  5); op->entry= pe;
+		op= newobject(O_SHEAD,  OF_MOD, r, 30,  3); op->entry= pe;
+		op= newobject(O_SSEC,   OF_MOD, r, 34,  2); op->entry= pe;
+		op= newobject(O_LCYL,   OF_MOD, r, 40,  5); op->entry= pe;
+		op= newobject(O_LHEAD,  OF_MOD, r, 45,  3); op->entry= pe;
+		op= newobject(O_LSEC,   OF_MOD, r, 49,  2); op->entry= pe;
+		op= newobject(O_BASE,   OF_MOD, r, 59,  9); op->entry= pe;
+		op= newobject(O_SIZE,   OF_MOD, r, 69,  9); op->entry= pe;
+		op= newobject(O_KB,     OF_MOD, r, 79,  9); op->entry= pe;
+	}
+
+	for (i= 1; i < argc; i++) newdevice(argv[i], 0);
+
+	if (firstdev == nil) {
+		getdevices();
+		key= ctrl('L');
+	} else {
+		key= 'r';
+	}
+
+	if (firstdev != nil) {
+		init_tty();
+		clear_screen();
+		event(key, curobj);
+		display();
+		mainloop();
+		reset_tty();
+	}
+	exit(0);
+}
Index: /trunk/minix/commands/ibm/partition.c
===================================================================
--- /trunk/minix/commands/ibm/partition.c	(revision 9)
+++ /trunk/minix/commands/ibm/partition.c	(revision 9)
@@ -0,0 +1,437 @@
+/*	partition 1.13 - Make a partition table		Author: Kees J. Bot
+ *								27 Apr 1992
+ */
+#define nil ((void*)0)
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/partition.h>
+#include <minix/u64.h>
+#include <ibm/partition.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <limits.h>
+
+#define SECTOR_SIZE	512
+
+#define arraysize(a)	(sizeof(a)/sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+
+char *arg0;
+
+void report(const char *label)
+{
+	fprintf(stderr, "%s: %s: %s\n", arg0, label, strerror(errno));
+}
+
+void fatal(const char *label)
+{
+	report(label);
+	exit(1);
+}
+
+#ifndef makedev
+#define minor(dev)	(((dev) >> MINOR) & BYTE)
+#define major(dev)	(((dev) >> MAJOR) & BYTE)
+#define makedev(major, minor)	\
+			((dev_t) (((major) << MAJOR) | ((minor) << MINOR)))
+#endif
+
+int aflag;			/* Add a new partition to the current table. */
+int mflag;			/* Minix rules, no need for alignment. */
+int rflag;			/* Report current partitions. */
+int fflag;			/* Force making a table even if too small. */
+int nflag;			/* Play-act, don't really do it. */
+
+int cylinders, heads, sectors;	/* Device's geometry */
+int pad;			/* Partitions must be padded. */
+
+/* Descriptions of the device to divide and the partitions to make, including
+ * gaps between partitions.
+ */
+char *device;
+struct part_entry primary, table[2 * NR_PARTITIONS + 1];
+int npart;
+
+/* Extra flags at construction time. */
+#define EXPAND_FLAG	0x01	/* Add the remaining sectors to this one */
+#define EXIST_FLAG	0x02	/* Use existing partition */
+
+void find_exist(struct part_entry *exist, int sysind, int nr)
+{
+	int f;
+	u16_t signature;
+	struct part_entry oldtable[NR_PARTITIONS];
+	int n, i;
+	u32_t minlow, curlow;
+	struct part_entry *cur;
+	char *nr_s[] = { "", "second ", "third ", "fourth" };
+
+	if ((f= open(device, O_RDONLY)) < 0
+
+		|| lseek(f, (off_t) PART_TABLE_OFF, SEEK_SET) == -1
+
+		|| read(f, oldtable, sizeof(oldtable)) < 0
+
+		|| read(f, &signature, sizeof(signature)) < 0
+
+		|| close(f) < 0
+	) fatal(device);
+
+	minlow= 0;
+	n= 0;
+	for (;;) {
+		curlow= -1;
+		cur= nil;
+		for (i= 0; i < NR_PARTITIONS; i++) {
+			if (signature == 0xAA55
+				&& oldtable[i].sysind != NO_PART
+				&& oldtable[i].lowsec >= minlow
+				&& oldtable[i].lowsec < curlow
+			) {
+				cur= &oldtable[i];
+				curlow= oldtable[i].lowsec;
+			}
+		}
+		if (n == nr) break;
+		n++;
+		minlow= curlow+1;
+	}
+
+	if (cur == nil || cur->sysind != sysind) {
+		fprintf(stderr,
+		"%s: Can't find a %sexisting partition of type 0x%02X\n",
+			arg0, nr_s[nr], sysind);
+		exit(1);
+	}
+	*exist = *cur;
+}
+
+void write_table(void)
+{
+	int f;
+	u16_t signature= 0xAA55;
+	struct part_entry newtable[NR_PARTITIONS];
+	int i;
+
+	if (nflag) {
+		printf("(Table not written)\n");
+		return;
+	}
+
+	for (i= 0; i < NR_PARTITIONS; i++) newtable[i]= table[1 + 2*i];
+
+	if ((f= open(device, O_WRONLY)) < 0
+
+		|| lseek(f, (off_t) PART_TABLE_OFF, SEEK_SET) == -1
+
+		|| write(f, newtable, sizeof(newtable)) < 0
+
+		|| write(f, &signature, sizeof(signature)) < 0
+
+		|| close(f) < 0
+	) fatal(device);
+}
+
+void sec2dos(unsigned long sec, unsigned char *dos)
+/* Translate a sector number into the three bytes DOS uses. */
+{
+	unsigned secspcyl= heads * sectors;
+	unsigned cyl;
+
+	cyl= sec / secspcyl;
+	dos[2]= cyl;
+	dos[1]= ((sec % sectors) + 1) | ((cyl >> 2) & 0xC0);
+	dos[0]= (sec % secspcyl) / sectors;
+}
+
+void show_chs(unsigned long pos)
+{
+	int cyl, head, sec;
+
+	if (pos == -1) {
+		cyl= head= 0;
+		sec= -1;
+	} else {
+		cyl= pos / (heads * sectors);
+		head= (pos / sectors) - (cyl * heads);
+		sec= pos % sectors;
+	}
+	printf("  %4d/%03d/%02d", cyl, head, sec);
+}
+
+void show_part(struct part_entry *p)
+{
+	static int banner= 0;
+	int n;
+
+	n= p - table;
+	if ((n % 2) == 0) return;
+
+	if (!banner) {
+		printf(
+	"Part     First         Last         Base      Size       Kb\n");
+		banner= 1;
+	}
+
+	printf("%3d ", (n-1) / 2);
+	show_chs(p->lowsec);
+	show_chs(p->lowsec + p->size - 1);
+	printf("  %8lu  %8lu  %7lu\n", p->lowsec, p->size, p->size / 2);
+}
+
+void usage(void)
+{
+	fprintf(stderr,
+		"Usage: partition [-mfn] device [type:]length[+*] ...\n");
+	exit(1);
+}
+
+#define between(a, c, z)	((unsigned) ((c) - (a)) <= ((z) - (a)))
+
+void parse(char *descr)
+{
+	int seen= 0, sysind, flags, c;
+	unsigned long lowsec, size;
+
+	lowsec= 0;
+
+	if (strchr(descr, ':') == nil) {
+		/* A hole. */
+		if ((npart % 2) != 0) {
+			fprintf(stderr, "%s: Two holes can't be adjacent.\n",
+				arg0);
+			exit(1);
+		}
+		sysind= NO_PART;
+		seen|= 1;
+	} else {
+		/* A partition. */
+		if ((npart % 2) == 0) {
+			/* Need a hole before this partition. */
+			if (npart == 0) {
+				/* First hole contains the partition table. */
+				table[0].size= 1;
+			}
+			npart++;
+		}
+		sysind= 0;
+		for (;;) {
+			c= *descr++;
+			if (between('0', c, '9'))
+				c= (c - '0') + 0x0;
+			else
+			if (between('a', c, 'z'))
+				c= (c - 'a') + 0xa;
+			else
+			if (between('A', c, 'Z'))
+				c= (c - 'A') + 0xA;
+			else
+				break;
+			sysind= 0x10 * sysind + c;
+			seen|= 1;
+		}
+		if (c != ':') usage();
+	}
+
+	flags= 0;
+
+	if (strncmp(descr, "exist", 5) == 0 && (npart % 2) == 1) {
+		struct part_entry exist;
+
+		find_exist(&exist, sysind, (npart - 1) / 2);
+		sysind= exist.sysind;
+		lowsec= exist.lowsec;
+		size= exist.size;
+		flags |= EXIST_FLAG;
+		descr += 5;
+		c= *descr++;
+		seen|= 2;
+	} else {
+		size= 0;
+		while (between('0', (c= *descr++), '9')) {
+			size= 10 * size + (c - '0');
+			seen|= 2;
+		}
+	}
+
+	for (;;) {
+		if (c == '*')
+			flags|= ACTIVE_FLAG;
+		else
+		if (c == '+' && !(flags & EXIST_FLAG))
+			flags|= EXPAND_FLAG;
+		else
+			break;
+		c= *descr++;
+	}
+
+	if (seen != 3 || c != 0) usage();
+
+	if (npart == arraysize(table)) {
+		fprintf(stderr, "%s: too many partitions, only %d possible.\n",
+			arg0, NR_PARTITIONS);
+		exit(1);
+	}
+	table[npart].bootind= flags;
+	table[npart].sysind= sysind;
+	table[npart].lowsec= lowsec;
+	table[npart].size= size;
+	npart++;
+}
+
+void geometry(void)
+/* Get the geometry of the drive the device lives on, and the base and size
+ * of the device.
+ */
+{
+	int fd;
+	struct partition geometry;
+	struct stat sb;
+
+	if ((fd= open(device, O_RDONLY)) < 0) fatal(device);
+
+	/* Get the geometry of the drive, and the device's base and size. */
+	if (ioctl(fd, DIOCGETP, &geometry) < 0)
+	{
+		/* Use the same fake geometry as part. */
+		if (fstat(fd, &sb) < 0)
+			fatal(device);
+		geometry.base= cvul64(0);
+		geometry.size= cvul64(sb.st_size);
+		geometry.sectors= 32;
+		geometry.heads= 64;
+		geometry.cylinders= (sb.st_size-1)/SECTOR_SIZE/
+			(geometry.sectors*geometry.heads) + 1;
+	}
+	close(fd);
+	primary.lowsec= div64u(geometry.base, SECTOR_SIZE);
+	primary.size= div64u(geometry.size, SECTOR_SIZE);
+	cylinders= geometry.cylinders;
+	heads= geometry.heads;
+	sectors= geometry.sectors;
+
+	/* Is this a primary partition table?  If so then pad partitions. */
+	pad= (!mflag && primary.lowsec == 0);
+}
+
+void boundary(struct part_entry *pe, int exp)
+/* Expand or reduce a primary partition to a track or cylinder boundary to
+ * avoid giving the fdisk's of simpler operating systems a fit.
+ */
+{
+	unsigned n;
+
+	n= !pad ? 1 : pe == &table[0] ? sectors : heads * sectors;
+	if (exp) pe->size+= n - 1;
+	pe->size= ((pe->lowsec + pe->size) / n * n) - pe->lowsec;
+}
+
+void distribute(void)
+/* Fit the partitions onto the device.  Try to start and end them on a
+ * cylinder boundary if so required.  The first partition is to start on
+ * track 1, not on cylinder 1.
+ */
+{
+	struct part_entry *pe, *exp;
+	long count;
+	unsigned long base, size, oldbase;
+
+	do {
+		exp= nil;
+		base= primary.lowsec;
+		count= primary.size;
+
+		for (pe= table; pe < arraylimit(table); pe++) {
+			oldbase= base;
+			if (pe->bootind & EXIST_FLAG) {
+				if (base > pe->lowsec) {
+					fprintf(stderr,
+	"%s: fixed partition %d is preceded by too big partitions/holes\n",
+						arg0, ((pe - table) - 1) / 2);
+					exit(1);
+				}
+				exp= nil;	/* XXX - Extend before? */
+			} else {
+				pe->lowsec= base;
+				boundary(pe, 1);
+				if (pe->bootind & EXPAND_FLAG) exp= pe;
+			}
+			base= pe->lowsec + pe->size;
+			count-= base - oldbase;
+		}
+		if (count < 0) {
+			if (fflag) break;
+			fprintf(stderr, "%s: %s is %ld sectors too small\n",
+				arg0, device, -count);
+			exit(1);
+		}
+		if (exp != nil) {
+			/* Add leftover space to the partition marked for
+			 * expanding.
+			 */
+			exp->size+= count;
+			boundary(exp, 0);
+			exp->bootind&= ~EXPAND_FLAG;
+		}
+	} while (exp != nil);
+
+	for (pe= table; pe < arraylimit(table); pe++) {
+		if (pe->sysind == NO_PART) {
+			memset(pe, 0, sizeof(*pe));
+		} else {
+			sec2dos(pe->lowsec, &pe->start_head);
+			sec2dos(pe->lowsec + pe->size - 1, &pe->last_head);
+			pe->bootind&= ACTIVE_FLAG;
+		}
+		show_part(pe);
+	}
+}
+
+int main(int argc, char **argv)
+{
+	int i;
+
+	if ((arg0= strrchr(argv[0], '/')) == nil) arg0= argv[0]; else arg0++;
+
+	i= 1;
+	while (i < argc && argv[i][0] == '-') {
+		char *opt= argv[i++] + 1;
+
+		if (opt[0] == '-' && opt[1] == 0) break;
+
+		while (*opt != 0) switch (*opt++) {
+		case 'a':	aflag= 1;	break;
+		case 'm':	mflag= 1;	break;
+		case 'r':	rflag= 1;	break;
+		case 'f':	fflag= 1;	break;
+		case 'n':	nflag= 1;	break;
+		default:	usage();
+		}
+	}
+
+	if (rflag) {
+		if (aflag) usage();
+		if ((argc - i) != 1) usage();
+		fprintf(stderr, "%s: -r is not yet implemented\n");
+		exit(1);
+	} else {
+		if ((argc - i) < 1) usage();
+		if (aflag) fprintf(stderr, "%s: -a is not yet implemented\n");
+
+		device= argv[i++];
+		geometry();
+
+		while (i < argc) parse(argv[i++]);
+
+		distribute();
+		write_table();
+	}
+	exit(0);
+}
Index: /trunk/minix/commands/ibm/playwave.c
===================================================================
--- /trunk/minix/commands/ibm/playwave.c	(revision 9)
+++ /trunk/minix/commands/ibm/playwave.c	(revision 9)
@@ -0,0 +1,201 @@
+/*   
+ *  playwave.c
+ *
+ *  Play sound files in wave format. Only MicroSoft PCM is supported. 
+ *
+ *  Michel R. Prevenier.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <minix/sound.h>
+
+_PROTOTYPE( void main, (int argc, char **argv));
+_PROTOTYPE( void usage, (void));
+
+/******* Wave format definitions *********/
+
+#define RIFF_ID		0x46464952
+#define WAVE_ID1	0x45564157
+#define WAVE_ID2	0x20746D66
+#define DATA_ID		0x61746164
+#define MS_PCM_FORMAT	0x0001
+	
+#define WORD	short  
+#define DWORD   unsigned long
+
+struct RIFF_fields
+{
+  DWORD RIFF_id;
+  DWORD RIFF_len;
+  DWORD WAVE_id1;
+  DWORD WAVE_id2;
+  DWORD data_ptr;
+} r_fields; 
+
+struct common_fields
+{
+  WORD  FormatTag;
+  WORD  Channels;
+  DWORD SamplesPerSec;
+  DWORD AvgBytesPerSec;
+  WORD  BlockAlign;
+} c_fields;
+
+struct specific_fields
+{
+  WORD BitsPerSample;
+} s_fields;
+
+DWORD data_id;
+DWORD data_len;
+
+/******** End of wave definitions *********/
+
+
+void usage()
+{
+  fprintf(stderr, "Usage: playwav [-i] file\n");
+  exit(-1);
+}
+
+
+void main ( int argc, char *argv[] )
+{
+  int i, audio, file;
+  char *buffer, *file_name;
+  unsigned int sign;
+  unsigned int fragment_size;
+  unsigned int channels;
+  unsigned int bits;
+  long data_pos;  
+  int showinfo = 0;
+
+  /* Check Parameters */
+  if (argc > 2)
+  {
+    if (strncmp(argv[1], "-i", 2) == 0)
+    {
+      showinfo = 1;
+      file_name = argv[2];
+    }
+    else
+      usage();
+  }
+  else file_name = argv[1];
+
+  /* Open DSP */
+  if ((audio = open("/dev/audio", O_RDWR)) < 0) 
+  {
+    printf("Cannot open /dev/audio\n");
+    exit(-1);
+  }
+
+  /* Get maximum fragment size and try to allocate a buffer */
+  ioctl(audio, DSPIOMAX, &fragment_size);
+  if ((buffer = malloc(fragment_size)) == (char *)0)
+  {
+    fprintf(stderr, "Cannot allocate buffer\n");
+    exit(-1);
+  } 
+  ioctl(audio, DSPIOSIZE, &fragment_size);
+
+  /* Open wav file */
+  if((file = open(file_name, O_RDONLY)) < 0)
+  {
+    printf("Cannot open %s\n", file_name);
+    exit(-1);
+  }
+
+  /* Check for valid wave format */
+  read(file, &r_fields, 20);
+  if(r_fields.RIFF_id != RIFF_ID)
+  {
+      printf("%s not in RIFF format\n", file_name);
+      exit(1);
+  }
+  if(r_fields.WAVE_id1 != WAVE_ID1 || r_fields.WAVE_id2 != WAVE_ID2)
+  {
+      printf("%s not in WAVE format\n", file_name);
+      exit(1);
+  }
+
+  /* Store data_chunk position */
+  data_pos = lseek(file, 0L, 1) + r_fields.data_ptr;
+
+  /* Read the common and specific fields */
+  read(file, &c_fields, 14);
+  read(file, &s_fields, 2);
+
+  /* Check for valid wave format, we can only play MicroSoft PCM */
+  if(c_fields.FormatTag != MS_PCM_FORMAT)
+  {
+    printf("%s not in MicroSoft PCM format\n", file_name);
+    exit(1);
+  }
+
+  /* Set DSP parameters */
+  channels = c_fields.Channels;
+  channels--;
+  bits = s_fields.BitsPerSample;
+  ioctl(audio, DSPIOSTEREO, &channels); 
+  ioctl(audio, DSPIORATE, &c_fields.SamplesPerSec);
+  ioctl(audio, DSPIOBITS, &bits); 
+  sign = (bits == 16 ? 1 : 0);
+  ioctl(audio, DSPIOSIGN, &sign); 
+
+  /* Goto data chunk */
+  lseek(file, data_pos, SEEK_SET);
+
+  /* Check for valid data chunk */
+  read(file, &data_id, sizeof(data_id));
+  if(data_id != DATA_ID)
+  {
+    printf("Invalid data chunk\n");
+    exit(1);
+  }
+
+  /* Get length of data */
+  read(file, &data_len, sizeof(data_len));
+
+  if (showinfo)
+  {
+    printf("\nBits per sample   : %d \n", s_fields.BitsPerSample);
+    printf("Stereo            : %s \n", (c_fields.Channels == 1 ? "yes" : "no"));
+    printf("Samples per second: %ld \n", c_fields.SamplesPerSec); 
+    printf("Average bytes/sec : %ld \n", c_fields.AvgBytesPerSec);
+    printf("Block alignment   : %d \n", c_fields.BlockAlign);
+    printf("Datalength (bytes): %ld \n\n", data_len);
+  }
+    
+  /* Play data */
+  while(data_len > 0)
+  {
+    if (data_len > fragment_size) 
+    {
+      /* Read next fragment */
+      read(file, buffer, fragment_size); 
+      data_len-= fragment_size;
+    }
+    else 
+    { 
+      /* Read until end of file and fill rest of buffer with silence,
+       * in PCM this means: fill buffer with last played value
+       */
+      read(file, buffer, data_len); 
+      for (i = data_len; i< fragment_size; i++) 
+        buffer[i] = buffer[(int)data_len-1];
+      data_len = 0;
+    }
+
+    /* Copy data to DSP */
+    write(audio, buffer,  fragment_size);
+  }
+}
Index: /trunk/minix/commands/ibm/postmort.c
===================================================================
--- /trunk/minix/commands/ibm/postmort.c	(revision 9)
+++ /trunk/minix/commands/ibm/postmort.c	(revision 9)
@@ -0,0 +1,656 @@
+/* postmort - post mortem dump		Author: C. W. Rose */
+
+/* Postmort: perform post-mortem on PC Minix 1.7 core files.
+ *
+ */
+
+ /* The 1.5 core file structure is a struct mem_map, the segment memory map,
+  * followed by a struct proc, the process table, followed by a dump of the
+  * text, data, and stack segments.
+  * 
+  * This is the 8086/Intel version; 386 and 68K will differ.  It defaults to
+  * using the name 'core' for the core file, and 'a.out' for the symbol file.
+  * If there is no 'a.out', it will try and read the symbol table from
+  * 'symbol.out', then give up.  A non-existant symbol table is not a fatal
+  * error unless the -s option was used.
+  * 
+  * The PC 1.5 kernel dump routines are odd - they dump the memory maps twice,
+  * the second time as part of the kernel process table, and the kernel
+  * process table size must be a multiple of 4.  Should a core file have a
+  * header with a magic number in future?
+  * 
+  * The kernel include file paths need to be edited for each machine. */
+
+#include <sys/types.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <limits.h>
+#include <timers.h>
+#include <signal.h>
+#include <stdlib.h>
+
+#undef EXTERN			/* <minix/const.h> defined this */
+#define EXTERN			/* so we get proc & mproc */
+#include "../../kernel/const.h"
+#include "../../kernel/type.h"
+#include "../../kernel/proc.h"
+#undef printf			/* kernel's const.h defined this */
+#include "../../servers/pm/mproc.h"
+
+#include <a.out.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#undef NULL
+#include <string.h>
+#include <unistd.h>
+
+#define FALSE		0
+#undef TRUE
+#define TRUE		~FALSE
+#define OK		1
+#define FAILED		-1
+
+#define CORE		"core"
+#define AOUT		"a.out"
+#define SYMB		"symbol.out"
+#define LINE_LEN	16
+#define MAXSYM		200
+#define SYMLEN		8
+
+/* Global variables */
+int opt_c = FALSE;		/* name of core file */
+int opt_d = FALSE;		/* dump raw data and stack segments */
+int opt_p = FALSE;		/* dump the kernel process table */
+int opt_s = FALSE;		/* name of symbol file */
+int opt_t = FALSE;		/* trace back the stack */
+int opt_x = FALSE;		/* debugging flag */
+
+char progname[20];		/* program name */
+char *segment_name[] = {	/* array of segment names */
+  "Text",
+  "Data",
+  "Stack"
+};
+
+int dbglvl = 0;			/* debugging level */
+int maxsym;			/* maximum symbol number */
+unsigned int baseptr;		/* reference copy of stack base pointer */
+unsigned int stackptr;		/* reference copy of stack pointer */
+long int lengths[NR_LOCAL_SEGS];	/* segment lengths */
+long int bases[NR_LOCAL_SEGS];	/* segment base addresses */
+
+struct sym {			/* symbol table addresses and labels */
+  unsigned int addr;
+  char label[SYMLEN + 1];
+} symtab[MAXSYM];
+
+/* Used by getopt(3) package */
+extern int optind, opterr, optopt;
+extern char *optarg;
+
+_PROTOTYPE(int binary, (int uc, char *sp));
+_PROTOTYPE(void dump_all_segs, (int fd));
+_PROTOTYPE(void dump_maps, (struct mem_map * mp));
+_PROTOTYPE(void dump_one_seg, (int fd, int segindex));
+_PROTOTYPE(void dump_proc_table, (struct proc * pt));
+_PROTOTYPE(void dump_registers, (struct proc * pt));
+_PROTOTYPE(void dump_sym_tab, (struct sym *st));
+_PROTOTYPE(void dump_stack, (struct stackframe_s * sp));
+_PROTOTYPE(int main, (int argc, char *argv[]));
+_PROTOTYPE(int parse_line, (char *ps));
+_PROTOTYPE(int read_symbol, (int fd));
+_PROTOTYPE(void stack_trace, (int fd));
+_PROTOTYPE(void usage, (void));
+
+
+/* B i n a r y
+ *
+ * Produce a binary representation of an 8-bit number.
+ */
+int binary(ucc, sp)
+int ucc;
+char *sp;
+{
+  int j;
+  unsigned char k, uc;
+
+  uc = (unsigned char) ucc;
+  for (k = 0x80, j = 0; j < 8; j++) {
+	if ((uc & k) == 0)
+		*sp++ = '0';
+	else
+		*sp++ = '1';
+	if (j == 3) *sp++ = '$';
+	k >>= 1;
+  }
+  *sp = '\0';
+
+  return(0);
+}
+
+
+/* D u m p _ a l l _ s e g s
+ *
+ * Dump all the segments except for text
+ */
+void dump_all_segs(fd)
+int fd;
+{
+  int j;
+  long int start;
+
+  start = (long) (NR_LOCAL_SEGS * sizeof(struct mem_map)) + sizeof(struct proc);
+  for (j = 1; j < NR_LOCAL_SEGS; j++) {
+	start += lengths[j - 1];
+	(void) lseek(fd, start, 0);
+	printf("\n");
+	dump_one_seg(fd, j);
+  }
+}
+
+
+/* D u m p _ m a p s
+ *
+ * Dump the memory maps
+ */
+void dump_maps(mp)
+struct mem_map *mp;
+{
+  int j;
+  long int vir, phy, len;
+
+  printf("\t  Virtual\t  Physical\tLength\n");
+  printf("\t  address\t  address\n");
+  for (j = 0; j < NR_LOCAL_SEGS; j++) {
+	vir = (long) mp[j].mem_vir << CLICK_SHIFT;
+	phy = (long) mp[j].mem_phys << CLICK_SHIFT;
+	len = (long) mp[j].mem_len << CLICK_SHIFT;
+	printf("%s:\t0x%08.8lx\t0x%08.8lx\t%8ld (0x%08.8lx)\n",
+	       segment_name[j], vir, phy, len, len);
+	lengths[j] = len;
+	bases[j] = vir;
+  }
+}
+
+
+/* D u m p _ o n e _ s e g
+ *
+ * Dump a single segment
+ */
+void dump_one_seg(fd, segindex)
+int fd, segindex;
+{
+  unsigned char dlen[LINE_LEN];
+  int i, amt, amt_read;
+  long int len, offset;
+
+  printf("%s segment\n\n", segment_name[segindex]);
+  len = lengths[segindex];
+  amt = LINE_LEN;
+  for (offset = 0; offset < len; offset += amt) {
+	if ((len - offset) < LINE_LEN) amt = (int) (len - offset);
+	if (dbglvl > 0)
+		printf("Length %ld, offset %ld, amt %d\n", len, offset, amt);
+	if ((amt_read = read(fd, (char *) dlen, (unsigned int) amt)) == -1) {
+		printf("Unexpected end of file\n");
+		exit(1);
+	}
+	printf("%08.8lx: ", bases[segindex] + offset);
+	for (i = 0; i < amt_read; i++) {
+		if (i == LINE_LEN / 2) printf("- ");
+		printf("%02.2x ", dlen[i]);
+	}
+	printf("  ");
+	for (i = 0; i < amt_read; i++) {
+		if (isprint(dlen[i]))
+			(void) putchar((char) dlen[i]);
+		else
+			(void) putchar('.');
+	}
+	(void) putchar('\n');
+	if (dbglvl > 0 && amt_read != amt)
+		printf("wanted = %d, got = %d, offset = %ld\n",
+		       amt, amt_read, offset);
+  }
+}
+
+
+/* D u m p _ p r o c _ t a b l e
+ *
+ * Dump the entire kernel proc table
+ */
+void dump_proc_table(pt)
+struct proc *pt;
+{
+  printf("Kernel process table entries:\n\n");
+#if 0
+  printf("Process' registers:			0x%04.4x\n", pt->p_reg);	/* struct stackframe_s */
+  printf("Selector in gdt:			0x%04.4x\n", pt->p_ldt_sel);	/* reg_t */
+  printf("Descriptors for code and data:	0x%04.4x\n", pt->p_ldt[2]);	/* struct segdesc_s */
+#endif
+  printf("Number of this process:			0x%04.4x\n", pt->p_nr);	/* int */
+#if 0
+  printf("Nonzero if blocked by busy task:	0x%04.4x\n", pt->p_ntf_blocked);	/* int */
+  printf("Nonzero if held by busy syscall:	0x%04.4x\n", pt->p_ntf_held);	/* int */
+  printf("Next in chain of held-up processes:	0x%04.4x\n", pt->p_ntf_nextheld);	/* struct proc * */
+#endif
+  printf("SENDING, RECEIVING, etc.:		0x%04.4x\n", pt->p_rts_flags);	/* int */
+#if 0
+  printf("Memory map:				0x%04.4x\n", pt->p_map[NR_LOCAL_SEGS]);	/* struct mem_map */
+#endif
+#if DEAD_CODE
+  printf("Process id passed in from MM:		0x%04.4x\n", pt->p_pid);	/* int */
+#endif
+#if 0
+  printf("User time in ticks:			%ld\n", pt->user_time);	/* time_t */
+  printf("Sys time in ticks:			%ld\n", pt->sys_time);	/* time_t */
+  printf("Cumulative user time of children:	%ld\n", pt->child_utime);	/* time_t */
+  printf("Cumulative sys time of children:	%ld\n", pt->child_stime);	/* time_t */
+  printf("Ticks used in current quantum:	%d\n", pt->quantum_time);	/* int */
+  printf("Ticks used in last quantum:		%d\n", pt->quantum_last);	/* int */
+  printf("Current priority of the process:	%d\n", pt->curr_prio);	/* int */
+  printf("Base priority of the process:		%d\n", pt->base_prio);	/* int */
+  printf("Scale for profiling, 0 = none:	%u\n", pt->p_pscale);	/* unsigned */
+  printf("Profiling pc lower boundary:		%d\n", pt->p_plow);	/* vir_bytes */
+  printf("Profiling pc upper boundary:		%d\n", pt->p_phigh);	/* vir_bytes */
+  printf("Profiling buffer:			%d\n", pt->p_pbuf);	/* vir_bytes */
+  printf("Profiling buffer size:		%d\n", pt->p_psiz);	/* vir_bytes */
+#endif
+#if 0
+  printf("First proc wishing to send:		0x%04.4x\n", pt->p_callerq);	/* struct proc * */
+  printf("Link to next proc wishing to send:	0x%04.4x\n", pt->p_sendlink);	/* struct proc * */
+  printf("Pointer to message buffer:		0x%04.4x\n", pt->p_messbuf);	/* message * */
+#endif
+  printf("Expecting message from:			0x%04.4x\n", pt->p_getfrom_e);	/* int */
+#if 0
+  printf("Pointer to next ready process:	0x%04.4x\n", pt->p_nextready);	/* struct proc * */
+#endif
+  printf("Bit map for pending signals 1-16:	0x%04.4x\n", pt->p_pending);	/* int */
+#if 0
+  printf("Count of pending/unfinished signals:	0x%04.4x\n", pt->p_pendcount);	/* unsigned */
+#endif
+}
+
+
+/* D u m p _ r e g i s t e r s
+ *
+ * Dump the registers from the proc table
+ */
+void dump_registers(pt)
+struct proc *pt;
+{
+  char buff[32];
+  unsigned char uc;
+
+  /* Print the registers */
+  dump_stack(&pt->p_reg);
+
+  /* Build up a binary representation of the signal flags */
+  uc = (pt->p_pending >> 8) & 0xff;
+  (void) binary((int) uc, buff);
+  buff[9] = '$';
+  uc = pt->p_pending & 0xff;
+  (void) binary((int) uc, buff + 10);
+  printf("Pending signals = %s\n", buff);
+}
+
+
+/* D u m p _ s y m _ t a b
+ *
+ * Dump the symbol table
+ */
+void dump_sym_tab(st)
+struct sym *st;
+{
+  int j;
+
+  printf("Symbol table entries (text):\n\n");
+  for (j = 0; j < maxsym; j++) 
+	printf("0x%08.8x T %s\n", symtab[j].addr, symtab[j].label);
+}
+
+
+/* D u m p _ s t a c k
+ *
+ * Dump the stack frame
+ */
+void dump_stack(sp)
+struct stackframe_s *sp;
+{
+  char buff[32];
+  unsigned char uc;
+
+  /* Build up the binary PSW representation */
+  uc = (sp->psw >> 8) & 0xff;
+  (void) binary((int) uc, buff);
+  uc = sp->psw & 0xff;
+  buff[9] = '$';
+  (void) binary((int) uc, buff + 10);
+
+  /* Print all the information */
+  printf("Stack Frame:\tPC = %04.4x\t\t   PSW = %s\n",
+         sp->pc, buff);
+  printf("\t\t\t\t\tStatus = ____ ODIT SZ_A _P_C\n");
+
+  printf("  ax	bx	cx	dx	di	si\n");
+  printf("  %04.4x\t%04.4x\t%04.4x\t%04.4x\t%04.4x\t%04.4x\n",
+         sp->retreg, sp->bx, sp->cx, sp->dx, sp->di, sp->si);
+  printf("  sp	bp	ss\n");
+  printf("  %04.4x\t%04.4x\t%04.4x\n",
+         sp->sp, sp->fp, sp->ss);
+  printf("  cs	ds	es\n");
+  printf("  %04.4x\t%04.4x\t%04.4x\n",
+         sp->cs, sp->ds, sp->es);
+
+  /* Store for future reference */
+  stackptr = sp->sp;
+  baseptr = sp->fp;
+  if (dbglvl > 0)
+	printf("\nStack pointer 0x%x, Base pointer 0x%x\n", stackptr, baseptr);
+}
+
+
+/* M a i n
+ *
+ * Main program
+ */
+main(argc, argv)
+int argc;
+char *argv[];
+{
+  int j, fdc, fds;
+  char *cp, corefile[132], symbfile[132];
+  struct proc proc_entry;
+  struct mem_map mp_segs[NR_LOCAL_SEGS];
+
+  /* Initial set up */
+  if ((cp = strrchr(argv[0], '/')) == (char *) NULL)
+	cp = argv[0];
+  else
+	cp++;
+  strncpy(progname, cp, 19);
+  strncpy(corefile, CORE, 131);
+  strncpy(symbfile, AOUT, 131);
+
+  /* Parse arguments */
+  opterr = 0;
+  while ((j = getopt(argc, argv, "c:dps:tx:")) != EOF) {
+	switch (j & 0177) {
+	    case 'c':
+		opt_c = TRUE;
+		strncpy(corefile, optarg, 131);
+		break;
+	    case 'd':	opt_d = TRUE;	break;
+	    case 'p':	opt_p = TRUE;	break;
+	    case 's':
+		opt_s = TRUE;
+		strncpy(symbfile, optarg, 131);
+		break;
+	    case 't':	opt_t = TRUE;	break;
+	    case 'x':
+		dbglvl = atoi(optarg);
+		opt_x = TRUE;
+		break;
+	    case '?':
+	    default:
+		usage();
+		exit(1);
+		break;
+	}
+  }
+
+  /* We must have a core file */
+  if ((fdc = open(corefile, O_RDONLY)) == -1) {
+	fprintf(stderr, "Cannot open %s\n", corefile);
+	exit(1);
+  }
+
+  /* We'd like an a.out file or a symbol table */
+  if ((fds = open(symbfile, O_RDONLY)) == -1) {
+	if (opt_s)
+		j = FAILED;
+	else {
+		strncpy(symbfile, AOUT, 131);
+		if ((fds = open(symbfile, O_RDONLY)) == -1)
+			j = FAILED;
+		else
+			j = read_symbol(fds);
+	}
+  } else
+	j = read_symbol(fds);
+
+  /* Only fatal if we insisted */
+  if (opt_s && j == FAILED) {
+	fprintf(stderr, "Cannot find symbols in %s\n", symbfile);
+	exit(1);
+  }
+
+  /* Read the process table */
+  if (dbglvl > 0) {
+	printf("\n");
+	printf("Size of mproc entry %d\n", NR_LOCAL_SEGS * sizeof(struct mem_map));
+	printf("Size of process table %d\n", sizeof(proc_entry));
+  }
+  if (read(fdc, (char *) mp_segs, sizeof(mp_segs)) != sizeof(mp_segs) ||
+      read(fdc, (char *) &proc_entry,
+	 sizeof(struct proc)) != sizeof(struct proc)) {
+	fprintf(stderr, "Cannot open %s\n", corefile);
+	exit(1);
+  }
+
+  /* Do the work */
+#if 0
+  dump_maps(mp_segs);		/* duplicated in the kernel */
+  printf("\n");
+	/* XXX broken */
+  dump_maps(proc_entry.p_map);
+#endif
+  printf("\n");
+  dump_registers(&proc_entry);
+  if (opt_t) {
+	printf("\n");
+	stack_trace(fdc);
+  }
+  if (opt_p) {
+	printf("\n");
+	dump_proc_table(&proc_entry);
+  }
+  if (opt_d) {
+	printf("\n");
+	dump_sym_tab(symtab);
+	dump_all_segs(fdc);
+  }
+
+  /* Wrap up */
+  (void) close(fdc);
+  if (fds != -1) (void) close(fds);
+
+  exit(0);
+  /* NOTREACHED */
+}
+
+
+/* P a r s e _ l i n e
+ *
+ * Parse a line of the symbol table
+ */
+int parse_line(ps)
+char *ps;
+{
+  char c, s[80];
+  int j, k;
+  unsigned int u;
+
+  /* We must have space in the table */
+  if (maxsym == MAXSYM) return(FAILED);
+
+  /* Lines must be a minimum length to contain information */
+  if (strlen(ps) < 8) return(FAILED);
+
+  /* Lines must have a definite structure */
+  if (ps[1] != ' ' || ps[6] != ' ') return(FAILED);
+  for (j = 2; j < 6; j++)
+	if (!isxdigit(ps[j])) return(FAILED);
+  if (sscanf(ps, "%c %x %s", &c, &u, s) != 3) return (FAILED);
+
+  if (dbglvl > 0) printf("Address 0x%04.4x, label %s\n", u, s);
+
+  /* Load the symbol table in sorted order */
+  for (j = 0; j < maxsym; j++) {
+	if (u < symtab[j].addr) {
+		for (k = maxsym; k > j; k--) symtab[k] = symtab[k - 1];
+		break;
+	}
+  }
+  symtab[j].addr = u;
+  strncpy(symtab[j].label, s, SYMLEN);
+  maxsym++;
+
+  return(OK);
+}
+
+
+/* R e a d _ s y m b o l
+ *
+ * Read the symbol table
+ */
+int read_symbol(fd)
+int fd;
+{
+  char sym[80], buff[BUFSIZ];
+  int j, k, m;
+  long int offset;
+  struct exec *ep;
+  struct nlist *np;
+
+  /* We collect only text symbols, since that's all that's needed here */
+
+  /* Initialise the buffer */
+  if ((j = read(fd, buff, BUFSIZ)) == 0 || j == -1) return(FAILED);
+
+  k = maxsym = 0;
+
+  /* Find out what we've got */
+  ep = (struct exec *) buff;
+  np = (struct nlist *) buff;
+  if (BADMAG(*ep)) {
+	/* Must be a separate symbol table */
+	while (TRUE) {
+		if (buff[k] == 'T') {
+			for (m = 0; m < 78; m++) {
+				sym[m] = buff[k];
+				if (++k == j) {
+					if ((j = read(fd, buff, BUFSIZ)) == 0 || j == -1)
+						break;
+					k = 0;
+				}
+				if (buff[k] == '\n') break;
+			}
+			sym[m + 1] = '\0';
+			(void) parse_line(sym);
+		}
+		if (++k == j) {
+			if ((j = read(fd, buff, BUFSIZ)) == 0 || j == -1)
+				break;
+			k = 0;
+		}
+	}
+  } else if (ep->a_syms != 0L) {
+	/* There's symbols in them thar hills */
+	offset = 8 * sizeof(long) + ep->a_text + ep->a_data;
+	if (lseek(fd, offset, 0) == -1L) return(FAILED);
+	/* Symbols are in an unsorted list */
+	while (read(fd, buff, sizeof(struct nlist)) == sizeof(struct nlist)) {
+		if (np->n_sclass == (N_TEXT + C_EXT)) {	/* external text symbols */
+			for (j = 0; j < maxsym; j++) {
+				if (np->n_value < symtab[j].addr) {
+					for (k = maxsym; k > j; k--)
+						symtab[k] = symtab[k - 1];
+					break;
+				}
+			}
+			symtab[j].addr = np->n_value;
+			strncpy(symtab[j].label, np->n_name, SYMLEN);
+			if (maxsym++ == MAXSYM) break;
+		}
+	}
+  } else if (opt_s)
+	return(FAILED);
+
+  if (dbglvl > 0) {
+	for (m = 0; m < maxsym; m++) printf("Addr 0x%04.4x, label %s\n",
+		       symtab[m].addr, symtab[m].label);
+	printf("Maxsym %d\n", maxsym);
+  }
+  return(OK);
+}
+
+
+/* S t a c k _ t r a c e
+ *
+ * Trace back down the stack frames.
+ *
+ * WARNING: very, very, non-portable code
+ */
+void stack_trace(fd)
+int fd;
+{
+  int j;
+  unsigned int framepointer, lastpointer, returnvalue, end;
+  long int offset, bp;
+
+  /* Bp actually gives the offset from the base of the data segment */
+  bp = (long) (NR_LOCAL_SEGS * sizeof(struct mem_map)) + sizeof(struct proc)
+	+ lengths[0] + lengths[1] - bases[2];
+  if ((offset = lseek(fd, bp + (long int) baseptr, 0)) == -1L) return;
+  end = (bases[2] + lengths[2] - 1) & 0xffff;
+
+  if (dbglvl > 0)
+	printf("Baseptr %x, End %x, Bp %ld, Offset %ld\n", baseptr, end, bp, offset);
+
+  /* Print the header, then try to backtrace  */
+  printf("Stack back trace:\n\n");
+  printf("Frame address.  Contents.  Return address.");
+  if (maxsym != 0) printf("  Previous label.");
+  printf("\n");
+
+  lastpointer = baseptr;
+  while (TRUE) {
+	/* Read the frame pointer and return address values */
+	if (read(fd, (char *) &framepointer, sizeof(int)) == -1 ||
+	    read(fd, (char *) &returnvalue, sizeof(int)) == -1)
+		break;
+
+	/* Look up the return address - ignored if maxsym == 0 */
+	for (j = 0; j < maxsym; j++) {
+		if (symtab[j].addr >= returnvalue) break;
+	}
+	if (j > 0) j--;
+	printf("    0x%04.4x        0x%04.4x      0x%04.4x          %s\n",
+	       lastpointer, framepointer, returnvalue,
+	       (maxsym == 0) ? "" : symtab[j].label);
+
+	/* If the result is clearly invalid, quit */
+	if (framepointer == 0 || framepointer >= end || framepointer <= lastpointer)
+		break;
+
+	/* Otherwise try to move to the next frame base */
+	lastpointer = framepointer;
+	if ((offset = lseek(fd, bp + (long int) framepointer, 0)) == -1L || offset == 0L)
+		break;
+  }
+}
+
+
+/* U s a g e
+ *
+ * Usage message
+ */
+void usage()
+{
+  fprintf(stderr, "Usage: %s [-dpt] [-c corefile] [-s symbfile]\n", progname);
+}
Index: /trunk/minix/commands/ibm/readclock.c
===================================================================
--- /trunk/minix/commands/ibm/readclock.c	(revision 9)
+++ /trunk/minix/commands/ibm/readclock.c	(revision 9)
@@ -0,0 +1,226 @@
+/* setime - set the system time from the real time clock
+					Authors: T. Holm & E. Froese
+					Adapted by: Jorrit .N. Herder */
+
+/************************************************************************/
+/*   Readclock was updated for security reasons: openeing /dev/mem no	*/
+/*   longer automatically grants I/O privileges to the calling process	*/
+/*   so that the CMOS' clock could not be read from this program. The	*/
+/*   new approach is to rely on the FS to do the CMOS I/O, via the new  */
+/*   system call CMOSTIME (which only reads the current clock value and */
+/*   cannot update the CMOS clock). 					*/
+/*   The original readclock.c is still available under backup.c.	*/
+/************************************************************************/
+/*									*/
+/*   readclock.c							*/
+/*									*/
+/*		Read the clock value from the 64 byte CMOS RAM		*/
+/*		area, then set system time.				*/
+/*									*/
+/*		If the machine ID byte is 0xFC or 0xF8, the device	*/
+/*		/dev/mem exists and can be opened for reading,		*/
+/*		and no errors in the CMOS RAM are reported by the	*/
+/*		RTC, then the time is read from the clock RAM		*/
+/*		area maintained by the RTC.				*/
+/*									*/
+/*		The clock RAM values are decoded and fed to mktime	*/
+/*		to make a time_t value, then stime(2) is called.	*/
+/*									*/
+/*		This fails if:						*/
+/*									*/
+/*		If the machine ID does not match 0xFC or 0xF8 (no	*/
+/*		error message.)						*/
+/*									*/
+/*		If the machine ID is 0xFC or 0xF8 and /dev/mem		*/
+/*		is missing, or cannot be accessed.			*/
+/*									*/
+/*		If the RTC reports errors in the CMOS RAM.		*/
+/*									*/
+/************************************************************************/
+/*    origination          1987-Dec-29              efth                */
+/*    robustness	   1990-Oct-06		    C. Sylvain		*/
+/* incorp. B. Evans ideas  1991-Jul-06		    C. Sylvain		*/
+/*    set time & calibrate 1992-Dec-17		    Kees J. Bot		*/
+/*    clock timezone	   1993-Oct-10		    Kees J. Bot		*/
+/*    set CMOS clock	   1994-Jun-12		    Kees J. Bot		*/
+/*    removed set CMOS	   2004-Sep-06		    Jorrit N. Herder    */
+/************************************************************************/
+
+#include <minix/callnr.h>
+#include <minix/config.h>
+#include <minix/type.h>
+#include <minix/const.h>
+#include <minix/com.h>
+#include <minix/syslib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioc_cmos.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <signal.h>
+#include <ibm/portio.h>
+#include <ibm/cmos.h>
+#include <sys/svrctl.h>
+
+#define MAX_RETRIES	1
+
+int nflag = 0;		/* Tell what, but don't do it. */
+int y2kflag = 0;	/* Interpret 1980 as 2000 for clock with Y2K bug. */
+
+char clocktz[128];	/* Timezone of the clock. */
+
+#define MACH_ID_ADDR	0xFFFFE		/* BIOS Machine ID at FFFF:000E */
+
+#define PC_AT		   0xFC		/* Machine ID byte for PC/AT,
+					   PC/XT286, and PS/2 Models 50, 60 */
+#define PS_386		   0xF8		/* Machine ID byte for PS/2 Model 80 */
+
+/* Manufacturers usually use the ID value of the IBM model they emulate.
+ * However some manufacturers, notably HP and COMPAQ, have had different
+ * ideas in the past.
+ *
+ * Machine ID byte information source:
+ *	_The Programmer's PC Sourcebook_ by Thom Hogan,
+ *	published by Microsoft Press
+ */
+
+void errmsg(char *s);
+int bcd_to_dec(int n);
+int dec_to_bcd(int n);
+void usage(void);
+
+#define CMOS_DEV "/dev/cmos"
+
+PUBLIC int main(int argc, char **argv)
+{
+  int fd;
+  struct tm time1;
+  struct tm time2;
+  struct tm tmnow;
+  char date[64];
+  time_t now, rtc;
+  int i, s, mem;
+  unsigned char mach_id, cmos_state;
+  struct sysgetenv sysgetenv;
+  message m;
+  int request;
+
+
+  /* Process options. */
+  while (argc > 1) {
+	char *p = *++argv;
+
+	if (*p++ != '-') usage();
+
+	while (*p != 0) {
+		switch (*p++) {
+		case 'n':	nflag = 1;	break;
+		case '2':	y2kflag = 1;	break;
+		default:	usage();
+		}
+	}
+	argc--;
+  }
+
+#if DEAD_CODE
+  /* The hardware clock may run in a different time zone, likely GMT or
+   * winter time.  Select that time zone.
+   */
+  strcpy(clocktz, "TZ=");
+  sysgetenv.key = "TZ";
+  sysgetenv.keylen = 2+1;
+  sysgetenv.val = clocktz+3;
+  sysgetenv.vallen = sizeof(clocktz)-3;
+  if (svrctl(SYSGETENV, &sysgetenv) == 0) {
+	putenv(clocktz);
+	tzset();
+  }
+#endif
+
+  /* Read the CMOS real time clock. */
+  for (i = 0; i < MAX_RETRIES; i++) {
+
+	/* sleep, unless first iteration */
+	if (i > 0) sleep(5);
+
+	/* Open the CMOS device to read the system time. */
+	if ((fd = open(CMOS_DEV, O_RDONLY)) < 0) {
+		perror(CMOS_DEV);
+		fprintf(stderr, "Couldn't open CMOS device.\n");
+		exit(1);
+	}
+        request = (y2kflag) ? CIOCGETTIME : CIOCGETTIMEY2K;
+	if ((s=ioctl(fd, request, (void *) &time1)) < 0) {
+		perror("ioctl");
+		fprintf(stderr, "Couldn't do CMOS ioctl.\n");
+		exit(1);
+	}
+	close(fd);
+
+	now = time(NULL);
+
+	time1.tm_isdst = -1;	/* Do timezone calculations. */
+	time2 = time1;
+
+	rtc= mktime(&time1);	/* Transform to a time_t. */
+	if (rtc != -1) {
+		break;
+	}
+
+	fprintf(stderr,
+"readclock: Invalid time read from CMOS RTC: %d-%02d-%02d %02d:%02d:%02d\n",
+		time2.tm_year+1900, time2.tm_mon+1, time2.tm_mday,
+		time2.tm_hour, time2.tm_min, time2.tm_sec);
+  }
+  if (i >= MAX_RETRIES) exit(1);
+
+  /* Now set system time. */
+  if (nflag) {
+		printf("stime(%lu)\n", (unsigned long) rtc);
+  } else {
+	if (stime(&rtc) < 0) {
+		errmsg( "Not allowed to set time." );
+		exit(1);
+	}
+  }
+  tmnow = *localtime(&rtc);
+  if (strftime(date, sizeof(date),
+			"%a %b %d %H:%M:%S %Z %Y", &tmnow) != 0) {
+	if (date[8] == '0') date[8]= ' ';
+#if 0
+	printf("%s [CMOS read via FS, see command/ibm/readclock.c]\n", date);
+#endif
+  }
+  exit(0);
+}
+
+void errmsg(char *s)
+{
+  static char *prompt = "readclock: ";
+
+  fprintf(stderr, "%s%s\n", prompt, s);
+  prompt = "";
+}
+
+
+int bcd_to_dec(int n)
+{
+  return ((n >> 4) & 0x0F) * 10 + (n & 0x0F);
+}
+
+int dec_to_bcd(int n)
+{
+  return ((n / 10) << 4) | (n % 10);
+}
+
+void usage(void)
+{
+  fprintf(stderr, "Usage: settime [-n2]\n");
+  exit(1);
+}
Index: /trunk/minix/commands/ibm/recwave.c
===================================================================
--- /trunk/minix/commands/ibm/recwave.c	(revision 9)
+++ /trunk/minix/commands/ibm/recwave.c	(revision 9)
@@ -0,0 +1,237 @@
+/*   
+ *  recwave.c
+ *
+ *  Record sound files in wave format. Only MicroSoft PCM is supported. 
+ *
+ *  Michel R. Prevenier.
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <minix/sound.h>
+
+_PROTOTYPE (void main, (int argc, char **argv));
+_PROTOTYPE (void usage, (void));
+_PROTOTYPE ( void write_wave_header, (void));
+_PROTOTYPE ( void terminate, (int s));
+
+
+/******* Wave format definitions *********/
+
+#define RIFF_ID		0x46464952
+#define WAVE_ID1	0x45564157
+#define WAVE_ID2	0x20746D66
+#define DATA_ID		0x61746164
+#define MS_PCM_FORMAT	0x0001
+
+#define WORD	short 
+#define DWORD   unsigned long
+
+struct RIFF_fields
+{
+  DWORD RIFF_id;
+  DWORD RIFF_len;
+  DWORD WAVE_id1;
+  DWORD WAVE_id2;
+  DWORD data_ptr;
+} r_fields; 
+
+struct common_fields
+{
+  WORD  FormatTag;
+  WORD  Channels;
+  DWORD SamplesPerSec;
+  DWORD AvgBytesPerSec;
+  WORD  BlockAlign;
+} c_fields;
+
+struct specific_fields
+{
+  WORD BitsPerSample;
+} s_fields;
+
+DWORD data_id;
+DWORD data_len;
+
+/******** End of wave format definitions *********/
+
+/* Default recording values */
+unsigned int sign = 0; 
+unsigned int bits = 8; 
+unsigned int stereo = 0; 
+unsigned int rate = 22050; 
+unsigned int time = 10;
+
+int old_stdin;
+struct termios old_tty, new_tty;
+int audio, file;
+
+void usage()
+{
+  fprintf(stderr, "Usage: recwav [-b -s -r] file_name\n");
+  exit(-1);
+}
+
+void terminate(s)
+int s;
+{
+  /* Restore terminal parameters */
+  tcsetattr(0, TCSANOW, &old_tty);
+  (void) fcntl(0,F_SETFL,old_stdin);
+  close(audio);
+  close(file);
+  exit(0);		
+}
+
+void write_wave_header()
+{
+  /* RIFF fields */
+  r_fields.RIFF_id = RIFF_ID;
+  r_fields.WAVE_id1 = WAVE_ID1;
+  r_fields.WAVE_id2 = WAVE_ID2;
+  r_fields.data_ptr = 16;
+  r_fields.RIFF_len = 20 + r_fields.data_ptr + data_len;
+
+  /* MicroSoft PCM specific fields */
+  s_fields.BitsPerSample = bits;
+
+  /* Common fields */
+  c_fields.FormatTag = MS_PCM_FORMAT;
+  c_fields.Channels = stereo + 1;
+  c_fields.SamplesPerSec = rate;
+  c_fields.AvgBytesPerSec =  c_fields.Channels * rate * (bits / 8);
+  c_fields.BlockAlign = c_fields.Channels * (bits / 8);
+
+  /* Data chunk */
+  data_id = DATA_ID;
+
+  /* Write wave-file header */
+  lseek(file, 0L, SEEK_SET);
+  write(file, &r_fields, 20);
+  write(file, &c_fields, 14);
+  write(file, &s_fields, 2);
+  write(file, &data_id, sizeof(data_id)); 
+  write(file, &data_len, sizeof(data_len)); 
+}
+
+
+void main(argc, argv)
+int argc;
+char **argv;
+{
+  unsigned int fragment_size;
+  char *buffer, *file_name;
+  char c;
+  int i;
+
+  /* Read parameters */
+  if (argc < 2) usage();
+
+  i = 1;
+  while (argv[i][0] == '-' && i < argc)
+  {
+    if (strncmp(argv[i], "-b", 2) == 0)
+      bits = atoi(argv[i] + 2);
+    else if (strncmp(argv[i], "-s", 2) == 0) 
+      stereo = atoi(argv[i] + 2);
+    else if (strncmp(argv[i], "-r", 2) == 0) 
+      rate = (unsigned int) atol(argv[i] + 2);
+    else usage();
+    i++;
+  }
+  if (i == argc) usage();
+
+  file_name = argv[i];
+
+  /* Some sanity checks */
+  if ((bits != 8 && bits != 16) || 
+      (rate < 4000 || rate > 44100) ||
+      (stereo != 0 && stereo != 1))
+  {
+    fprintf(stderr, "Invalid parameters\n");
+    exit(-1);
+  }
+
+  /* Open DSP */
+  if ((audio = open("/dev/rec", O_RDWR)) < 0) 
+  {
+    fprintf(stderr, "Cannot open /dev/rec\n");
+    exit(-1);
+  }
+
+  /* Get maximum fragment size and try to allocate a buffer */
+  ioctl(audio, DSPIOMAX, &fragment_size);
+  if ((buffer = malloc(fragment_size)) == (char *) 0)
+  {
+    fprintf(stderr, "Cannot allocate buffer\n");
+    exit(-1);
+  } 
+
+  /* Set sample parameters */
+  ioctl(audio, DSPIOSIZE, &fragment_size); 
+  ioctl(audio, DSPIOSTEREO, &stereo); 
+  ioctl(audio, DSPIORATE, &rate);
+  ioctl(audio, DSPIOBITS, &bits); 
+  sign = (bits == 16 ? 1 : 0);
+  ioctl(audio, DSPIOSIGN, &sign); 
+
+  /* Create sample file */
+  if ((file = creat(file_name, 511)) < 0) 
+  {
+    fprintf(stderr, "Cannot create %s\n", argv[1]);
+    exit(-1);
+  } 
+  /* Skip wave header */
+  lseek(file, (long)(sizeof(r_fields) + 
+                     sizeof(c_fields) + 
+                     sizeof(s_fields) + 
+                     sizeof(data_id) + 
+                     sizeof(data_len)), SEEK_SET); 
+
+  printf("\nBits per sample   : %u\n", bits);
+  printf("Stereo            : %s\n", (stereo == 1 ? "yes" : "no"));
+  printf("Samples per second: %u\n", rate);
+
+  /* Set terminal parameters and remember the old ones */
+  tcgetattr(0, &old_tty);
+  new_tty = old_tty;
+  new_tty.c_lflag &= ~(ICANON|ECHO);
+  old_stdin = fcntl(0, F_GETFL);
+
+  /* Catch break signal to be able to restore terminal parameters in case
+   * of a user interrupt
+   */
+  signal(SIGINT, terminate);
+
+  /* Go to non-blocking mode */
+  tcsetattr(0, TCSANOW, &new_tty);
+  (void) fcntl(0, F_SETFL, old_stdin | O_NONBLOCK);
+
+  printf("\nPress spacebar to start sampling...\n");
+  while(!(read(0, &c, 1) == 1 && c == ' '));
+
+  printf("Sampling, press spacebar to stop...\n");
+  while(!(read(0, &c, 1) == 1 && c == ' '))
+  {
+    /* Read sample fragment and write to sample file */
+    read(audio, buffer, fragment_size);
+    write(file, buffer, fragment_size);
+    data_len+= fragment_size;
+  }
+  printf("%ld bytes sampled. \n\n", data_len);
+ 
+  /* Construct the wave header in front of the raw sample data */
+  write_wave_header();
+  
+  /* Restore terminal parameters and exit */
+  terminate(1);
+}
Index: /trunk/minix/commands/ibm/repartition.c
===================================================================
--- /trunk/minix/commands/ibm/repartition.c	(revision 9)
+++ /trunk/minix/commands/ibm/repartition.c	(revision 9)
@@ -0,0 +1,283 @@
+/*	repartition 1.18 - Load a partition table	Author: Kees J. Bot
+ *								30 Nov 1991
+ */
+#define nil 0
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/partition.h>
+#include <minix/u64.h>
+#include <ibm/partition.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <dirent.h>
+#include <limits.h>
+
+#define DEV_FD0		0x200
+
+#define SECTOR_SIZE	512
+
+#define arraysize(a)	(sizeof(a)/sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+
+char *arg0;
+char *dev_file;		/* Device to repartition. */
+
+#ifndef S_ISLNK
+/* There were no symlinks in medieval times. */
+#define lstat		stat
+#endif
+
+void report(const char *label)
+{
+	fprintf(stderr, "%s: %s: %s\n", arg0, label, strerror(errno));
+}
+
+void fatal(const char *label)
+{
+	report(label);
+	exit(1);
+}
+
+#ifndef makedev
+#define minor(dev)	(((dev) >> MINOR) & BYTE)
+#define major(dev)	(((dev) >> MAJOR) & BYTE)
+#define makedev(major, minor)	\
+			((dev_t) (((major) << MAJOR) | ((minor) << MINOR)))
+#endif
+
+#define MINOR_d0p0s0	128
+
+void partsort(struct part_entry *pe)
+/* DOS has the misguided idea that partition tables must be sorted. */
+{
+  int i,j;
+  struct part_entry tmp;
+
+  for (i = 0; i < NR_PARTITIONS; i++)
+	for (j = 0; j < NR_PARTITIONS-1; j++)
+		if ((pe[j].sysind == NO_PART && pe[j+1].sysind != NO_PART) ||
+		 (pe[j].lowsec > pe[j+1].lowsec && pe[j+1].sysind != NO_PART)) {
+			tmp = pe[j];
+			pe[j] = pe[j+1];
+			pe[j+1] = tmp;
+		}
+}
+
+char *finddev(dev_t device)
+/* Find the device next to dev_file with the given device number. */
+{
+	DIR *dp;
+	struct dirent *de;
+	static char name[PATH_MAX];
+	char *np;
+	size_t nlen;
+	struct stat st;
+
+	if ((np= strrchr(dev_file, '/')) == nil) np= dev_file; else np++;
+	nlen= np - dev_file;
+	if (nlen > PATH_MAX - NAME_MAX - 1) {
+		fprintf(stderr, "%s: %s: Name is way too long\n",
+			arg0, dev_file);
+		exit(1);
+	}
+	memcpy(name, dev_file, nlen);
+
+	if ((dp= opendir("/dev")) == nil) fatal("/dev");
+	while ((de= readdir(dp)) != nil) {
+		strcpy(name+nlen, de->d_name);
+		if (lstat(name, &st) == 0
+			&& (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))
+			&& st.st_rdev == device
+		) {
+			closedir(dp);
+			return name;
+		}
+	}
+	fprintf(stderr, "%s: Can't find partition devices associated with %s\n",
+		arg0, dev_file);
+	exit(1);
+}
+
+#define DSETP	0
+#define DGETP	1
+
+int diocntl(dev_t device, int request, struct partition *entry)
+/* Get or set the geometry of a device. */
+{
+	char *name;
+	int r, f, err;
+	struct partition geometry;
+
+	name= finddev(device);
+	if ((f= open(name, O_RDONLY)) < 0) return -1;
+	r= ioctl(f, request == DSETP ? DIOCSETP : DIOCGETP, (void *) entry);
+	err= errno;
+	(void) close(f);
+	errno= err;
+	return r;
+}
+
+struct partition geometry;	/* Geometry of the device. */
+
+void print_chs(unsigned long sector)
+{
+	unsigned secspcyl = geometry.heads * geometry.sectors;
+	int delta= 0;
+
+	if (sector == -1) { sector= 0; delta= -1; }
+
+	printf(" %5d/%03d/%02d",
+		(int) (sector / secspcyl),
+		(int) (sector % secspcyl) / geometry.sectors,
+		(int) (sector % geometry.sectors) + delta);
+}
+
+void show_part(char *name, unsigned long base, unsigned long size)
+{
+	int i;
+	static int len= 0;
+
+	if (len == 0) {
+		len= strlen(name) + 3;
+		printf("device");
+		for (i = 6; i < len; i++) fputc(' ', stdout);
+		printf(
+	"      first         last        base      size        kb\n");
+	}
+
+	printf("%s", name);
+	for (i = strlen(name); i < len; i++) fputc(' ', stdout);
+
+	print_chs(base);
+	print_chs(base + size - 1);
+	printf(" %9lu %9lu %9lu\n", base, size, size / (1024/SECTOR_SIZE));
+}
+
+int main(int argc, char **argv)
+{
+	struct stat hdst;
+	struct partition whole, entry;
+	struct part_entry table[4], *pe;
+	int drive, par, device, incr;
+	int partf;
+	char *table_file;
+	int hd_major, hd_minor;
+	int needsort;
+	int shrink;		/* True if partitions are shrinked to fit. */
+	unsigned long base, size, limit;
+
+	if ((arg0= strrchr(argv[0], '/')) == nil) arg0= argv[0]; else arg0++;
+
+	if (argc < 2 || argc > 3) {
+		fprintf(stderr,
+			"Usage: %s device [partition-file]\n", arg0);
+		exit(1);
+	}
+	dev_file= argv[1];
+	table_file= argv[argc - 1];
+	shrink= (argc == 2);
+
+	if (stat(dev_file, &hdst) < 0) fatal(dev_file);
+
+	/* Geometry (to print nice numbers.) */
+	if (diocntl(hdst.st_rdev, DGETP, &geometry) < 0) fatal(dev_file);
+
+	if (!S_ISBLK(hdst.st_mode)) {
+		fprintf(stderr, "%s: %s is not a device\n", arg0, dev_file);
+		exit(1);
+	}
+	hd_major= major(hdst.st_rdev);
+	hd_minor= minor(hdst.st_rdev);
+
+	if (hd_minor >= MINOR_d0p0s0) {
+		errno= EINVAL;
+		fatal(dev_file);
+	}
+
+	if (hd_major == major(DEV_FD0)) {
+		/* HD is actually a floppy. */
+		if (hd_minor >= 4) {
+			errno= EINVAL;
+			fatal(dev_file);
+		}
+		device= hd_minor + (28 << 2);
+		incr= 4;
+		needsort= 0;
+	} else
+	if (hd_minor % (1 + NR_PARTITIONS) == 0) {
+		/* Partitioning hd0, hd5, ... */
+		device= hd_minor + 1;
+		incr= 1;
+		needsort= 1;
+	} else {
+		/* Subpartitioning hd[1-4], hd[6-9], ... */
+		drive= hd_minor / (1 + NR_PARTITIONS);
+		par= hd_minor % (1 + NR_PARTITIONS) - 1;
+
+		device= MINOR_d0p0s0
+				+ (drive * NR_PARTITIONS + par) * NR_PARTITIONS;
+		if (device + NR_PARTITIONS - 1 > BYTE) {
+			errno= EINVAL;
+			fatal(dev_file);
+		}
+		incr= 1;
+		needsort= 0;
+	}
+	/* Device is now the first of the minor devices to be repartitioned. */
+
+	/* Read the partition table from the boot block. */
+	if ((partf= open(table_file, O_RDONLY)) < 0
+		|| lseek(partf, (off_t) PART_TABLE_OFF, SEEK_SET) == -1
+		|| (par= read(partf, (char *) table, (int) sizeof(table))) < 0
+	) fatal(table_file);
+
+	if (par < sizeof(table)) {
+		fprintf(stderr, "%s: %s does not contain a partition table\n",
+			arg0, table_file);
+		exit(1);
+	}
+	if (needsort) partsort(table);
+
+	/* Show the geometry of the affected drive or partition. */
+	if (diocntl(hdst.st_rdev, DGETP, &whole) < 0) fatal(dev_file);
+
+	/* Use sector numbers. */
+	base = div64u(whole.base, SECTOR_SIZE);
+	size = div64u(whole.size, SECTOR_SIZE);
+	limit = base + size;
+
+	show_part(dev_file, base, size);
+
+	/* Send the partition table entries to the device driver. */
+	for (par= 0; par < NR_PARTITIONS; par++, device+= incr) {
+		pe = &table[par];
+		if (shrink && pe->size != 0) {
+			/* Shrink the partition entry to fit within the
+			 * enclosing device just like the driver does.
+			 */
+			unsigned long part_limit= pe->lowsec + pe->size;
+
+			if (part_limit < pe->lowsec) part_limit= limit;
+			if (part_limit > limit) part_limit= limit;
+			if (pe->lowsec < base) pe->lowsec= base;
+			if (part_limit < pe->lowsec) part_limit= pe->lowsec;
+			pe->size= part_limit - pe->lowsec;
+		}
+
+		entry.base= mul64u(pe->lowsec, SECTOR_SIZE);
+		entry.size= mul64u(pe->size, SECTOR_SIZE);
+		if (diocntl(makedev(hd_major, device), DSETP, &entry) < 0)
+			fatal(dev_file);
+
+		show_part(finddev(makedev(hd_major, device)),
+							pe->lowsec, pe->size);
+	}
+	exit(0);
+}
Index: /trunk/minix/commands/ibm/screendump.c
===================================================================
--- /trunk/minix/commands/ibm/screendump.c	(revision 9)
+++ /trunk/minix/commands/ibm/screendump.c	(revision 9)
@@ -0,0 +1,136 @@
+/*	screendump 1.2 - dump the contents of the console
+ *							Author: Kees J. Bot
+ *								16 Dec 1994
+ */
+#define nil 0
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#define BIOS_CRTBASE	0x00463L	/* BIOS parameters: CRT base. */
+#define CRTBASE_MONO	0x03B4		/* Value of CRT base for mono mode. */
+
+#define MONO_BASE	0xB0000L	/* Screen memory in monochrome mode. */
+#define COLOR_BASE	0xB8000L	/* ... colour mode. */
+
+#define DEF_COLS	80		/* Default screen geometry. */
+#define DEF_ROWS	25
+
+#define MAX_COLS	132		/* Maximum screen geometry. */
+#define MAX_ROWS	60
+
+char MEMORY[] =		"/dev/mem";	/* Memory device to read screen. */
+int mfd;				/* Open memory device. */
+
+void tell(const char *message)
+{
+	write(2, message, strlen(message));
+}
+
+void fatal(const char *label)
+{
+	const char *err= strerror(errno);
+
+	tell("screendump: ");
+	tell(label);
+	tell(": ");
+	tell(err);
+	tell("\n");
+	exit(1);
+}
+
+long video_base(void)
+/* Is it monochrome or colour? */
+{
+	static unsigned short bios_crtbase;
+
+	if (lseek(mfd, (off_t) BIOS_CRTBASE, SEEK_SET) == -1) fatal(MEMORY);
+	switch (read(mfd, &bios_crtbase, sizeof(bios_crtbase))) {
+	case -1:
+		fatal(MEMORY);
+	default:
+		tell("screendump: can't obtain BIOS parameter: short read\n");
+		exit(1);
+	case sizeof(bios_crtbase):
+		/* Fine */;
+	}
+
+	return bios_crtbase == CRTBASE_MONO ? MONO_BASE : COLOR_BASE;
+}
+
+void main(void)
+{
+	static unsigned char screen[MAX_COLS * MAX_ROWS * 2];
+	unsigned char *ps;
+	long base;
+	int lfd;
+	int row;
+	int nrows, ncols;
+	struct winsize winsize;
+
+	/* Open the memory device. */
+	if ((mfd= open(MEMORY, O_RDONLY)) < 0) fatal(MEMORY);
+
+	base= video_base();
+
+	/* Read screen memory. */
+	if (lseek(mfd, base, SEEK_SET) == -1) fatal(MEMORY);
+
+	switch (read(mfd, screen, sizeof(screen))) {
+	case -1:
+		fatal(MEMORY);
+	default:
+		tell("screendump: can't obtain screen dump: short read\n");
+		exit(1);
+	case sizeof(screen):
+		/* Fine */;
+	}
+
+	/* Try to obtain the screen geometry from /dev/log. */
+	ncols= DEF_COLS;
+	nrows= DEF_ROWS;
+	if ((lfd= open("/dev/log", O_WRONLY)) != -1
+		&& ioctl(lfd, TIOCGWINSZ, &winsize) == 0
+	) {
+		if (40 <= winsize.ws_col && winsize.ws_col <= MAX_COLS) {
+			ncols= winsize.ws_col;
+		}
+		if (25 <= winsize.ws_row && winsize.ws_row <= MAX_COLS) {
+			nrows= winsize.ws_row;
+		}
+	}
+	if (lfd != -1) close(lfd);
+
+	/* Print the contents of the screen line by line.  Omit trailing
+	 * blanks.  Note that screen memory consists of pairs of characters
+	 * and attribute bytes.
+	 */
+	ps= screen;
+	for (row= 0; row < nrows; row++) {
+		char line[MAX_COLS + 1];
+		char *pl= line;
+		int column;
+		int blanks= 0;
+
+		for (column= 0; column < ncols; column++) {
+			if (*ps <= ' ') {
+				/* Skip trailing junk. */
+				blanks++;
+			} else {
+				/* Reinsert blanks and add a character. */
+				while (blanks > 0) { *pl++= ' '; blanks--; }
+				*pl++= *ps;
+			}
+			/* Skip character and attribute byte. */
+			ps+= 2;
+		}
+		*pl++= '\n';
+		if (write(1, line, pl - line) < 0) fatal("stdout");
+	}
+	exit(0);
+}
Index: /trunk/minix/commands/ibm/sdump.c
===================================================================
--- /trunk/minix/commands/ibm/sdump.c	(revision 9)
+++ /trunk/minix/commands/ibm/sdump.c	(revision 9)
@@ -0,0 +1,191 @@
+/* sdump - dump memory */
+
+#include <minix/config.h>
+#include <sys/types.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <timers.h>
+#include <signal.h>
+
+#undef EXTERN
+#define EXTERN
+#include "../../servers/pm/const.h"
+#include "../../servers/pm/type.h"
+#include "../../servers/pm/mproc.h"
+#include "../../kernel/const.h"
+#include "../../kernel/type.h"
+#include "../../kernel/proc.h"
+#undef printf			/* printf was misdefined by the sys headers */
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define STACK_BYTES 30000
+
+char *default_core = "core";
+int stack[STACK_BYTES / sizeof (int)];
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void read_segmap, (int fd, struct mproc *mp, long *seg_size));
+_PROTOTYPE(void read_registers, (int fd, struct proc *p));
+_PROTOTYPE(void dump_stack, (int fd, struct mproc *mp, long *seg_size));
+_PROTOTYPE(void error, (char *s1, char *s2));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int fd;
+  long seg_size[NR_LOCAL_SEGS];	/* segment sizes in bytes */
+  struct mproc *mp;
+  struct proc *p;
+  char *file;
+
+  if (argc > 2) error("Usage: rdump [core_file]\n", "");
+
+  if (argc == 1)
+	file = default_core;
+  else
+	file = argv[1];
+
+  if ( (fd = open(file, O_RDONLY)) < 0) error("Cannot open", file);
+
+  mp = &mproc[0];
+  p = &proc[0];
+  read_segmap(fd, mp, seg_size);
+  read_registers(fd, p);
+  dump_stack(fd, mp, seg_size);
+  return(0);
+}
+
+void read_segmap(fd, mp, seg_size)
+int fd;
+struct mproc *mp;
+long seg_size[NR_LOCAL_SEGS];
+{
+  int i, segmap_size;
+
+  /* Read in the segment map. */
+  segmap_size = sizeof mp->mp_seg;
+  if (read(fd, (char *) mp, segmap_size) != segmap_size)
+	error("Cannot read segmap map from core image file", "");
+
+  for (i = 0; i < NR_LOCAL_SEGS; i++)
+	seg_size[i] = (long) mp->mp_seg[i].mem_len << CLICK_SHIFT;
+  printf("Seg sizes in bytes:  Text: %ld  Data: %ld, Stack: %ld\n",
+	 seg_size[T], seg_size[D], seg_size[S]);
+}
+
+void read_registers(fd, p)
+int fd;
+struct proc *p;
+{
+  int proctblsize;
+  struct stackframe_s r;
+
+  proctblsize = sizeof (struct proc);
+  if (read(fd, (char *) p, proctblsize) != proctblsize)
+	error("Cannot read process table from core image file", "");
+  r = p->p_reg;
+
+  /* Print proc table. */
+  printf("\n");
+#if (CHIP == INTEL)
+#if _WORD_SIZE == 4
+  printf("eax=%8lX   ebx=%8lX   ecx=%8lX   edx=%8lX\n",
+	 r.retreg, r.bx, r.cx, r.dx);
+  printf("esi=%8lX   edi=%8lX   ebp=%8lX   esp=%8lX   eip=%8lX\n",
+	 r.si, r.di, r.fp, r.sp, r.pc);
+  printf(" ds=%8lX    es=%8lX                   ss=%8lX    cs=%8lX\n",
+	 r.ds, r.es, r.ss, r.cs);
+  printf(" fs=%8lX    gs=%8lX                                  ef=%8lX\n",
+         r.fs, r.gs, r.psw);
+#else
+  printf(
+"ax=%4X  bx=%4X  cx=%4X  dx=%4X  si=%4X  di=%4X  bp=%4X  sp=%4X  ip=%4X\n",
+	 r.retreg, r.bx, r.cx, r.dx, r.si, r.di, r.fp, r.sp, r.pc);
+  printf(
+" f=%4X                             ds=%4X  es=%4X           ss=%4X  cs=%4X\n",
+	 r.psw, r.ds, r.es, r.ss, r.cs);
+#endif
+#endif /* (CHIP == INTEL) */
+#if (CHIP == M68000)
+  printf("pc=%8lx   psw=%4x\n", r.pc, r.psw);
+  printf("d0=%8lx   d1=%8lx   d2=%8lx   d3=%8lx\n", r.retreg, r.d1, r.d2, r.d3);
+  printf("d4=%8lx   d5=%8lx   d6=%8lx   d7=%8lx\n", r.d4, r.d5, r.d6, r.d7);
+  printf("a0=%8lx   a1=%8lx   a2=%8lx   a3=%8lx\n", r.a0, r.a1, r.a2, r.a3);
+  printf("a4=%8lx   a5=%8lx   a6=%8lx   a7=%8lx\n", r.a4, r.a5, r.a6, r.sp);
+#endif
+  printf("\n");
+}
+
+void dump_stack(fd, mp, seg_size)
+int fd;
+struct mproc *mp;
+long seg_size[NR_LOCAL_SEGS];
+{
+  unsigned char ch;
+  char format[32];
+  int word, i, stack_size, j;
+  vir_bytes v, vi;
+
+  /* Seek past text and data segments. */
+  lseek(fd, seg_size[T] + seg_size[D], SEEK_CUR);
+  v = mp->mp_seg[S].mem_vir << CLICK_SHIFT;
+
+  stack_size = (int) seg_size[S];
+  if (stack_size != seg_size[S] || stack_size < 0 || stack_size > STACK_BYTES)
+	error("Stack too large", "");
+
+  /* Dump the stack. */
+  if (read(fd, (char *) stack, stack_size) != stack_size)
+	error("Error reading stack from core file", "");
+
+#define BYTES(num)      ((unsigned) sizeof (num))
+#define DEC_DIGITS(num) (sizeof (num) <= 2 ? 6 : 11)	/* for 16/32 bit num */
+#define HEX_DIGITS(num) (((unsigned) sizeof (num) * CHAR_BIT + 3) / 4)
+
+  printf("%*s   %*s  %*s  %*s\n",
+	 HEX_DIGITS(vi), "Addr",
+	 HEX_DIGITS(word), "Hex",
+	 DEC_DIGITS(word), "Dec",
+	 BYTES(word), "Char");
+
+  /* The format string depends messily on the size of various things. */
+  strcpy(format, "%*");
+  if (sizeof v > sizeof (int)) strcat(format, "l");
+  strcat(format, "X:  %*");
+  if (sizeof word > sizeof (int)) strcat(format, "l");
+  strcat(format, "X  %*");
+  if (sizeof word > sizeof (int)) strcat(format, "l");
+  strcat(format, "d  ");
+  
+  for (i = stack_size / sizeof (int) - 1, vi = v + stack_size - sizeof (int);
+       i >= 0; --i, vi -= sizeof (int)) {
+	word = stack[i];
+	printf(format,
+	       HEX_DIGITS(vi), vi,
+	       HEX_DIGITS(word), word,
+	       DEC_DIGITS(word), word);
+	for (j = 0; j < BYTES(word); ++j, word >>= CHAR_BIT) {
+		ch = (unsigned char) word;
+		if (!isprint(ch)) ch = '.';
+		putchar(ch);
+	}
+	putchar('\n');
+  }
+}
+
+void error(s1, s2)
+char *s1, *s2;
+{
+  printf("%s %s\n", s1, s2);
+  exit(1);
+}
Index: /trunk/minix/commands/indent/Makefile
===================================================================
--- /trunk/minix/commands/indent/Makefile	(revision 9)
+++ /trunk/minix/commands/indent/Makefile	(revision 9)
@@ -0,0 +1,22 @@
+# Makefile for indent
+
+CFLAGS= -c -O -D_MINIX -D_POSIX_SOURCE -wo -m
+CC = exec cc
+
+all:	indent
+
+OBJ = args.o comment.o lexi.o indent.o parse.o io.o
+
+indent: ${OBJ}
+	$(CC) -o indent -i ${OBJ}
+	install -S 32kw $@
+
+install:	/usr/bin/indent
+
+/usr/bin/indent:	indent
+	install -cs -o bin indent $@
+
+$(OBJ): globs.h codes.h
+
+clean:
+	rm -f *.bak *.o core indent
Index: /trunk/minix/commands/indent/args.c
===================================================================
--- /trunk/minix/commands/indent/args.c	(revision 9)
+++ /trunk/minix/commands/indent/args.c	(revision 9)
@@ -0,0 +1,287 @@
+/**
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1980 The Regents of the University of California.
+ * Copyright (c) 1976 Board of Trustees of the University of Illinois.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley, the University of Illinois,
+ * Urbana, and Sun Microsystems, Inc.  The name of either University
+ * or Sun Microsystems may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * Argument scanning and profile reading code.  Default parameters are set
+ * here as well.
+ */
+
+#define PUBLIC extern
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include "globs.h"
+#include "proto.h"
+
+/* profile types */
+#define	PRO_SPECIAL	1		/* special case */
+#define	PRO_BOOL	2		/* boolean */
+#define	PRO_INT		3		/* integer */
+#define PRO_FONT	4		/* troff font */
+
+/* profile specials for booleans */
+#define	ON		1		/* turn it on */
+#define	OFF		0		/* turn it off */
+
+/* profile specials for specials */
+#define	IGN		1		/* ignore it */
+#define	CLI		2		/* case label indent (float) */
+#define	STDIN		3		/* use stdin */
+#define	KEY		4		/* type (keyword) */
+
+/*
+ * N.B.: because of the way the table here is scanned, options whose names
+ * are substrings of other options must occur later; that is, with -lp vs -l,
+ * -lp must be first.  Also, while (most) booleans occur more than once, the
+ * last default value is the one actually assigned.
+ */
+struct pro
+{
+   char           *p_name;		/* name, eg -bl, -cli */
+   int             p_type;		/* type (int, bool, special) */
+   int             p_default;		/* the default value (if int) */
+   int             p_special;		/* depends on type */
+   int            *p_obj;		/* the associated variable */
+}               pro[] =
+
+{
+
+   "T", PRO_SPECIAL, 0, KEY, 0,
+   "bacc", PRO_BOOL, false, ON, &bl_around,
+   "badp", PRO_BOOL, false, ON, &bl_at_proctop,
+   "bad", PRO_BOOL, false, ON, &bl_aft_decl,
+   "bap", PRO_BOOL, false, ON, &bl_a_procs,
+   "bbb", PRO_BOOL, false, ON, &bl_bef_bk,
+   "bc", PRO_BOOL, true, OFF, &ps.leave_comma,
+   "bl", PRO_BOOL, true, OFF, &btype_2,
+   "br", PRO_BOOL, true, ON, &btype_2,
+   "bs", PRO_BOOL, false, ON, &Bill_Shannon,
+   "cdb", PRO_BOOL, true, ON, &del_on_bl,
+   "cd", PRO_INT, 0, 0, &ps.decl_com_ind,
+   "ce", PRO_BOOL, true, ON, &cuddle_else,
+   "ci", PRO_INT, 0, 0, &continuation_indent,
+   "cli", PRO_SPECIAL, 0, CLI, 0,
+   "c", PRO_INT, 33, 0, &ps.com_ind,
+   "di", PRO_INT, 16, 0, &ps.decl_indent,
+   "dj", PRO_BOOL, false, ON, &ps.ljust_decl,
+   "d", PRO_INT, 0, 0, &ps.unindent_displace,
+   "eei", PRO_BOOL, false, ON, &ex_expr_indent,
+   "ei", PRO_BOOL, true, ON, &ps.else_if,
+   "fbc", PRO_FONT, 0, 0, (int *) &blkcomf,
+   "fbx", PRO_FONT, 0, 0, (int *) &boxcomf,
+   "fb", PRO_FONT, 0, 0, (int *) &bodyf,
+   "fc1", PRO_BOOL, true, ON, &format_col1_comments,
+   "fc", PRO_FONT, 0, 0, (int *) &scomf,
+   "fk", PRO_FONT, 0, 0, (int *) &keywordf,
+   "fs", PRO_FONT, 0, 0, (int *) &stringf,
+   "ip", PRO_BOOL, true, ON, &ps.indent_parameters,
+   "i", PRO_INT, 8, 0, &ps.ind_size,
+   "lc", PRO_INT, 0, 0, &bk_max_col,
+   "lp", PRO_BOOL, true, ON, &lineup_to_parens,
+   "l", PRO_INT, 78, 0, &max_col,
+   "nbacc", PRO_BOOL, false, OFF, &bl_around,
+   "nbadp", PRO_BOOL, false, OFF, &bl_at_proctop,
+   "nbad", PRO_BOOL, false, OFF, &bl_aft_decl,
+   "nbap", PRO_BOOL, false, OFF, &bl_a_procs,
+   "nbbb", PRO_BOOL, false, OFF, &bl_bef_bk,
+   "nbc", PRO_BOOL, true, ON, &ps.leave_comma,
+   "nbs", PRO_BOOL, false, OFF, &Bill_Shannon,
+   "ncdb", PRO_BOOL, true, OFF, &del_on_bl,
+   "nce", PRO_BOOL, true, OFF, &cuddle_else,
+   "ndj", PRO_BOOL, false, OFF, &ps.ljust_decl,
+   "neei", PRO_BOOL, false, OFF, &ex_expr_indent,
+   "nei", PRO_BOOL, true, OFF, &ps.else_if,
+   "nfc1", PRO_BOOL, true, OFF, &format_col1_comments,
+   "nip", PRO_BOOL, true, OFF, &ps.indent_parameters,
+   "nlp", PRO_BOOL, true, OFF, &lineup_to_parens,
+   "npcs", PRO_BOOL, false, OFF, &proc_calls_space,
+   "npro", PRO_SPECIAL, 0, IGN, 0,
+   "npsl", PRO_BOOL, true, OFF, &proc_str_line,
+   "nps", PRO_BOOL, false, OFF, &ptr_binop,
+   "nsc", PRO_BOOL, true, OFF, &star_comment_cont,
+   "nsob", PRO_BOOL, false, OFF, &swallow_opt_bl,
+   "nv", PRO_BOOL, false, OFF, &verbose,
+   "pcs", PRO_BOOL, false, ON, &proc_calls_space,
+   "psl", PRO_BOOL, true, ON, &proc_str_line,
+   "ps", PRO_BOOL, false, ON, &ptr_binop,
+   "sc", PRO_BOOL, true, ON, &star_comment_cont,
+   "sob", PRO_BOOL, false, ON, &swallow_opt_bl,
+   "st", PRO_SPECIAL, 0, STDIN, 0,
+   "troff", PRO_BOOL, false, ON, &troff,
+   "v", PRO_BOOL, false, ON, &verbose,
+   /* whew! */
+   0, 0, 0, 0, 0
+};
+
+/*
+ * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles
+ * arguments given in these files.
+ */
+void set_profile()
+{
+   register FILE  *f;
+   char            fname[BUFSIZ];
+   static char     prof[] = ".indent.pro";
+
+   sprintf(fname, "%s/%s", getenv("HOME"), prof);
+   if ((f = fopen(fname, "r")) != NULL)
+   {
+      scan_profile(f);
+      (void) fclose(f);
+   }
+   if ((f = fopen(prof, "r")) != NULL)
+   {
+      scan_profile(f);
+      (void) fclose(f);
+   }
+}
+
+void scan_profile(f)
+   register FILE  *f;
+{
+   register int    i;
+   register char  *p;
+   char            buf[BUFSIZ];
+
+   while (1)
+   {
+      for (p = buf; (i = getc(f)) != EOF && (*p = (char)i) > ' '; ++p);
+      if (p != buf)
+      {
+	 *p++ = 0;
+	 if (verbose)
+	    printf("profile: %s\n", buf);
+	 set_option(buf);
+      } else if (i == EOF)
+	 return;
+   }
+}
+
+char           *param_start;
+
+int eqin(s1, s2)
+   register char  *s1;
+   register char  *s2;
+{
+   while (*s1)
+   {
+      if (*s1++ != *s2++)
+	 return (false);
+   }
+   param_start = s2;
+   return (true);
+}
+
+/*
+ * Set the defaults.
+ */
+void set_defaults()
+{
+   register struct pro *p;
+
+   /* Because ps.case_indent is a float, we can't initialize it from
+      the table: */
+   ps.case_indent = 0;			/* -cli0.0 */
+   for (p = pro; p->p_name; p++)
+      if (p->p_type != PRO_SPECIAL && p->p_type != PRO_FONT)
+	 *p->p_obj = p->p_default;
+}
+
+void set_option(arg)
+   register char  *arg;
+{
+   register struct pro *p;
+
+   arg++;				/* ignore leading "-" */
+   for (p = pro; p->p_name; p++)
+      if (*p->p_name == *arg && eqin(p->p_name, arg))
+	 goto found;
+   fprintf(stderr, "indent: unknown parameter \"%s\"\n", arg - 1);
+   exit(1);
+found:
+   switch (p->p_type)
+   {
+
+   case PRO_SPECIAL:
+      switch (p->p_special)
+      {
+
+      case IGN:
+	 break;
+
+      case CLI:
+	 if (*param_start == 0)
+	    goto need_param;
+	 ps.case_indent = atoi(param_start);
+	 break;
+
+      case STDIN:
+	 if (input == 0)
+	    input = stdin;
+	 if (output == 0)
+	    output = stdout;
+	 break;
+
+      case KEY:
+	 if (*param_start == 0)
+	    goto need_param;
+	 {
+	    register char  *str = (char *) malloc(strlen(param_start) + 1);
+	    strcpy(str, param_start);
+	    addkey(str, 4);
+	 }
+	 break;
+
+      default:
+	 fprintf(stderr, "\
+indent: set_option: internal error: p_special %d\n", p->p_special);
+	 exit(1);
+      }
+      break;
+
+   case PRO_BOOL:
+      if (p->p_special == OFF)
+	 *p->p_obj = false;
+      else
+	 *p->p_obj = true;
+      break;
+
+   case PRO_INT:
+      if (*param_start == 0)
+      {
+   need_param:
+	 fprintf(stderr, "indent: ``%s'' requires a parameter\n",
+		 arg - 1);
+	 exit(1);
+      }
+      *p->p_obj = atoi(param_start);
+      break;
+
+   case PRO_FONT:
+      parsefont((struct fstate *) p->p_obj, param_start);
+      break;
+
+   default:
+      fprintf(stderr, "indent: set_option: internal error: p_type %d\n",
+	      p->p_type);
+      exit(1);
+   }
+}
Index: /trunk/minix/commands/indent/build
===================================================================
--- /trunk/minix/commands/indent/build	(revision 9)
+++ /trunk/minix/commands/indent/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/indent/codes.h
===================================================================
--- /trunk/minix/commands/indent/codes.h	(revision 9)
+++ /trunk/minix/commands/indent/codes.h	(revision 9)
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1980 The Regents of the University of California.
+ * Copyright (c) 1976 Board of Trustees of the University of Illinois.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley, the University of Illinois,
+ * Urbana, and Sun Microsystems, Inc.  The name of either University
+ * or Sun Microsystems may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#)indent_codes.h	5.6 (Berkeley) 9/15/88
+ */
+
+#define newline		1
+#define lparen		2
+#define rparen		3
+#define unary_op	4
+#define binary_op	5
+#define postop		6
+#define question	7
+#define casestmt	8
+#define colon		9
+#define semicolon	10
+#define lbrace		11
+#define rbrace		12
+#define ident		13
+#define comma		14
+#define comment		15
+#define swstmt		16
+#define preesc		17
+#define form_feed	18
+#define decl		19
+#define sp_paren	20
+#define sp_nparen	21
+#define ifstmt		22
+#define whilestmt	23
+#define forstmt		24
+#define stmt		25
+#define stmtl		26
+#define elselit		27
+#define dolit		28
+#define dohead		29
+#define ifhead		30
+#define elsehead	31
+#define period		32
Index: /trunk/minix/commands/indent/comment.c
===================================================================
--- /trunk/minix/commands/indent/comment.c	(revision 9)
+++ /trunk/minix/commands/indent/comment.c	(revision 9)
@@ -0,0 +1,458 @@
+/**
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1980 The Regents of the University of California.
+ * Copyright (c) 1976 Board of Trustees of the University of Illinois.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley, the University of Illinois,
+ * Urbana, and Sun Microsystems, Inc.  The name of either University
+ * or Sun Microsystems may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * NAME: pr_comment
+ *
+ * FUNCTION: This routine takes care of scanning and printing comments.
+ *
+ * ALGORITHM: 1) Decide where the comment should be aligned, and if lines should
+ * be broken. 2) If lines should not be broken and filled, just copy up to
+ * end of comment. 3) If lines should be filled, then scan thru input_buffer
+ * copying characters to com_buf.  Remember where the last blank, tab, or
+ * newline was.  When line is filled, print up to last blank and continue
+ * copying.
+ *
+ * HISTORY: November 1976	D A Willcox of CAC	Initial coding 12/6/76
+ *  A Willcox of CAC	Modification to handle UNIX-style comments
+ *
+ */
+
+
+/*
+ * this routine processes comments.  It makes an attempt to keep comments
+ * from going over the max line length.  If a line is too long, it moves
+ * everything from the last blank to the next comment line.  Blanks and tabs
+ * from the beginning of the input line are removed
+ */
+
+
+#define PUBLIC extern
+#include <stdlib.h>
+#include "globs.h"
+#include "proto.h"
+
+
+void pr_comment()
+{
+   int             now_col;		/* column we are in now */
+
+   int             adj_max_col;		/* Adjusted max_col for when we
+					 * decide to spill comments
+					 *  over the right margin
+					 */
+
+   char           *last_bl;		/* points to the last blank in
+					 * the output buffer 
+					 */
+
+   char           *t_ptr;		/* used for moving string */
+
+   int             unix_comment;	/* tri-state variable used to
+					 * decide if it is a unix-style
+					 * comment. 0 means only blanks
+					 * since / *, 1 means regular
+					 * style comment, 2 means unix
+					 * style comment 
+					 */
+
+   int             break_delim = del_on_bl;
+   int             l_just_saw_decl = ps.just_saw_decl;
+   /* int         ps.last_nl = 0; */	/* true iff the last
+				      	   sig thing we have seen is a nl */
+
+   int             one_liner = 1;	/* true iff this comment is a
+					   one-liner */
+   adj_max_col = max_col;
+   ps.just_saw_decl = 0;
+   last_bl = 0;				/* no blanks found so far */
+   ps.box_com = false;			/* at first, assume that we are
+					   not in a boxed comment or
+					   some other comment that
+					   should not be touched */
+   ++ps.out_coms;			/* keep track of number of
+					   comments */
+   unix_comment = 1;			/* set flag to let us figure
+					   out if there is a unix-style
+					   comment ** DISABLED: use 0
+					   to reenable this hack! */
+
+   /* Figure where to align and how to treat the comment */
+
+   if (ps.col_1 && !format_col1_comments)
+   {					/* if comment starts in column
+					   1 it should not be touched */
+      ps.box_com = true;
+      ps.com_col = 1;
+   } else
+   {
+      if (*buf_ptr == '-' || *buf_ptr == '*')
+      {
+	 ps.box_com = true;		/* a comment with a '-' or '*'
+					   immediately after the / * is
+					   assumed to be a boxed
+					   comment */
+	 break_delim = 0;
+      }
+      if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code))
+      {
+	 /* klg: check only if this line is blank */
+	 /* If this (*and previous lines are*) blank, dont put comment
+	    way out at left */
+	 ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1;
+	 adj_max_col = bk_max_col;
+	 if (ps.com_col <= 1)
+	    ps.com_col = 1 + !format_col1_comments;
+      } else
+      {
+	 register        target_col;
+	 break_delim = 0;
+	 if (s_code != e_code)
+	    target_col = count_spaces(code_target(), s_code);
+	 else
+	 {
+	    target_col = 1;
+	    if (s_lab != e_lab)
+	       target_col = count_spaces(label_target(), s_lab);
+	 }
+	 ps.com_col = ps.decl_on_line || ps.ind_level == 0 ? ps.decl_com_ind : ps.com_ind;
+	 if (ps.com_col < target_col)
+	    ps.com_col = ((target_col + 7) & ~7) + 1;
+	 if (ps.com_col + 24 > adj_max_col)
+	    adj_max_col = ps.com_col + 24;
+      }
+   }
+   if (ps.box_com)
+   {
+      buf_ptr[-2] = 0;
+      ps.n_comment_delta = 1 - count_spaces(1, in_buffer);
+      buf_ptr[-2] = '/';
+   } else
+   {
+      ps.n_comment_delta = 0;
+      while (*buf_ptr == ' ' || *buf_ptr == '\t')
+	 buf_ptr++;
+   }
+   ps.comment_delta = 0;
+   *e_com++ = '/';			/* put '/ *' into buffer */
+   *e_com++ = '*';
+   if (*buf_ptr != ' ' && !ps.box_com)
+      *e_com++ = ' ';
+
+   *e_com = '\0';
+   if (troff)
+   {
+      now_col = 1;
+      adj_max_col = 80;
+   } else
+      now_col = count_spaces(ps.com_col, s_com);	/* figure what column we
+							   would be in if we
+							   printed the comment
+							   now */
+
+   /* Start to copy the comment */
+
+   while (1)
+   {					/* this loop will go until the
+					   comment is copied */
+      if (*buf_ptr > 040 && *buf_ptr != '*')
+	 ps.last_nl = 0;
+      if (e_com >= l_com)
+      {
+	 register        nsize = l_com - s_com + 400;
+	 combuf = (char *) realloc(combuf, nsize);
+	 e_com = combuf + (e_com - s_com) + 1;
+	 l_com = combuf + nsize - 5;
+	 s_com = combuf + 1;
+      }
+      switch (*buf_ptr)
+      {					/* this checks for various spcl
+					   cases */
+      case 014:			/* check for a form feed */
+	 if (!ps.box_com)
+	 {				/* in a text comment, break the
+					   line here */
+	    ps.use_ff = true;
+	    /* fix so dump_line uses a form feed */
+	    dump_line();
+	    last_bl = 0;
+	    *e_com++ = ' ';
+	    *e_com++ = '*';
+	    *e_com++ = ' ';
+	    while (*++buf_ptr == ' ' || *buf_ptr == '\t');
+	 } else
+	 {
+	    if (++buf_ptr >= buf_end)
+	       fill_buffer();
+	    *e_com++ = 014;
+	 }
+	 break;
+
+      case '\n':
+	 if (had_eof)
+	 {				/* check for unexpected eof */
+	    printf("Unterminated comment\n");
+	    *e_com = '\0';
+	    dump_line();
+	    return;
+	 }
+	 one_liner = 0;
+	 if (ps.box_com || ps.last_nl)
+	 {				/* if this is a boxed comment,
+					   we dont ignore the newline */
+	    if (s_com == e_com)
+	    {
+	       *e_com++ = ' ';
+	       *e_com++ = ' ';
+	    }
+	    *e_com = '\0';
+	    if (!ps.box_com && e_com - s_com > 3)
+	    {
+	       if (break_delim == 1 && s_com[0] == '/'
+		   && s_com[1] == '*' && s_com[2] == ' ')
+	       {
+		  char           *t = e_com;
+		  break_delim = 2;
+		  e_com = s_com + 2;
+		  *e_com = 0;
+		  if (bl_bef_bk)
+		     prefix_blankline_requested = 1;
+		  dump_line();
+		  e_com = t;
+		  s_com[0] = s_com[1] = s_com[2] = ' ';
+	       }
+	       dump_line();
+	       if (e_com >= l_com)
+	       {
+		  register        nsize = l_com - s_com + 400;
+		  combuf = (char *) realloc(combuf, nsize);
+		  e_com = combuf + (e_com - s_com) + 1;
+		  l_com = combuf + nsize - 5;
+		  s_com = combuf + 1;
+	       }
+	       *e_com++ = ' ';
+	       *e_com++ = ' ';
+	    }
+	    dump_line();
+	    now_col = ps.com_col;
+	 } else
+	 {
+	    ps.last_nl = 1;
+	    if (unix_comment != 1)
+	    {				/* we not are in unix_style
+					   comment */
+	       if (unix_comment == 0 && s_code == e_code)
+	       {
+		  /* if it is a UNIX-style comment, ignore the
+		     requirement that previous line be blank for
+		     unindention */
+		  ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1;
+		  if (ps.com_col <= 1)
+		     ps.com_col = 2;
+	       }
+	       unix_comment = 2;	/* permanently remember that we
+					   are in this type of comment */
+	       dump_line();
+	       ++line_no;
+	       now_col = ps.com_col;
+	       *e_com++ = ' ';
+	       /* fix so that the star at the start of the line will
+	          line up */
+	       do			/* flush leading white space */
+		  if (++buf_ptr >= buf_end)
+		     fill_buffer();
+	       while (*buf_ptr == ' ' || *buf_ptr == '\t');
+	       break;
+	    }
+	    if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t')
+	       last_bl = e_com - 1;
+	    /* if there was a space at the end of the last line,
+	       remember where it was */
+	    else
+	    {				/* otherwise, insert one */
+	       last_bl = e_com;
+	       *e_com++ = ' ';
+	       if (e_com >= l_com)
+	       {
+		  register        nsize = l_com - s_com + 400;
+		  combuf = (char *) realloc(combuf, nsize);
+		  e_com = combuf + (e_com - s_com) + 1;
+		  l_com = combuf + nsize - 5;
+		  s_com = combuf + 1;
+	       }
+	       ++now_col;
+	    }
+	 }
+	 ++line_no;			/* keep track of input line
+					   number */
+	 if (!ps.box_com)
+	 {
+	    int             nstar = 1;
+	    do
+	    {				/* flush any blanks and/or tabs
+					   at start of next line */
+	       if (++buf_ptr >= buf_end)
+		  fill_buffer();
+	       if (*buf_ptr == '*' && --nstar >= 0)
+	       {
+		  if (++buf_ptr >= buf_end)
+		     fill_buffer();
+		  if (*buf_ptr == '/')
+		     goto end_of_comment;
+	       }
+	    } while (*buf_ptr == ' ' || *buf_ptr == '\t');
+	 } else if (++buf_ptr >= buf_end)
+	    fill_buffer();
+	 break;				/* end of case for newline */
+
+      case '*':			/* must check for possibility
+					   of being at end of comment */
+	 if (++buf_ptr >= buf_end)	/* get to next char after * */
+	    fill_buffer();
+
+	 if (unix_comment == 0)		/* set flag to show we are not
+					   in unix-style comment */
+	    unix_comment = 1;
+
+	 if (*buf_ptr == '/')
+	 {				/* it is the end!!! */
+      end_of_comment:
+	    if (++buf_ptr >= buf_end)
+	       fill_buffer();
+
+	    if (*(e_com - 1) != ' ' && !ps.box_com)
+	    {				/* insure blank before end */
+	       *e_com++ = ' ';
+	       ++now_col;
+	    }
+	    if (break_delim == 1 && !one_liner && s_com[0] == '/'
+		&& s_com[1] == '*' && s_com[2] == ' ')
+	    {
+	       char           *t = e_com;
+	       break_delim = 2;
+	       e_com = s_com + 2;
+	       *e_com = 0;
+	       if (bl_bef_bk)
+		  prefix_blankline_requested = 1;
+	       dump_line();
+	       e_com = t;
+	       s_com[0] = s_com[1] = s_com[2] = ' ';
+	    }
+	    if (break_delim == 2 && e_com > s_com + 3
+		 /* now_col > adj_max_col - 2 && !ps.box_com */ )
+	    {
+	       *e_com = '\0';
+	       dump_line();
+	       now_col = ps.com_col;
+	    }
+	    if (e_com >= l_com)
+	    {
+	       register        nsize = l_com - s_com + 400;
+	       combuf = (char *) realloc(combuf, nsize);
+	       e_com = combuf + (e_com - s_com) + 1;
+	       l_com = combuf + nsize - 5;
+	       s_com = combuf + 1;
+	    }
+	    *e_com++ = '*';
+	    *e_com++ = '/';
+	    *e_com = '\0';
+	    ps.just_saw_decl = l_just_saw_decl;
+	    return;
+	 } else
+	 {				/* handle isolated '*' */
+	    *e_com++ = '*';
+	    ++now_col;
+	 }
+	 break;
+      default:				/* we have a random char */
+	 if (unix_comment == 0 && *buf_ptr != ' ' && *buf_ptr != '\t')
+	    unix_comment = 1;		/* we are not in unix-style
+					   comment */
+
+	 *e_com = *buf_ptr++;
+	 if (buf_ptr >= buf_end)
+	    fill_buffer();
+
+	 if (*e_com == '\t')		/* keep track of column */
+	    now_col = ((now_col - 1) & tabmask) + tabsize + 1;
+	 else if (*e_com == '\b')	/* this is a backspace */
+	    --now_col;
+	 else
+	    ++now_col;
+
+	 if (*e_com == ' ' || *e_com == '\t')
+	    last_bl = e_com;
+	 /* remember we saw a blank */
+
+	 ++e_com;
+	 if (now_col > adj_max_col && !ps.box_com && unix_comment == 1 && e_com[-1] > ' ')
+	 {
+	    /* the comment is too long, it must be broken up */
+	    if (break_delim == 1 && s_com[0] == '/'
+		&& s_com[1] == '*' && s_com[2] == ' ')
+	    {
+	       char           *t = e_com;
+	       break_delim = 2;
+	       e_com = s_com + 2;
+	       *e_com = 0;
+	       if (bl_bef_bk)
+		  prefix_blankline_requested = 1;
+	       dump_line();
+	       e_com = t;
+	       s_com[0] = s_com[1] = s_com[2] = ' ';
+	    }
+	    if (last_bl == 0)
+	    {				/* we have seen no blanks */
+	       last_bl = e_com;		/* fake it */
+	       *e_com++ = ' ';
+	    }
+	    *e_com = '\0';		/* print what we have */
+	    *last_bl = '\0';
+	    while (last_bl > s_com && last_bl[-1] < 040)
+	       *--last_bl = 0;
+	    e_com = last_bl;
+	    dump_line();
+
+	    *e_com++ = ' ';		/* add blanks for continuation */
+	    *e_com++ = ' ';
+	    *e_com++ = ' ';
+
+	    t_ptr = last_bl + 1;
+	    last_bl = 0;
+	    if (t_ptr >= e_com)
+	    {
+	       while (*t_ptr == ' ' || *t_ptr == '\t')
+		  t_ptr++;
+	       while (*t_ptr != '\0')
+	       {			/* move unprinted part of
+					   comment down in buffer */
+		  if (*t_ptr == ' ' || *t_ptr == '\t')
+		     last_bl = e_com;
+		  *e_com++ = *t_ptr++;
+	       }
+	    }
+	    *e_com = '\0';
+	    now_col = count_spaces(ps.com_col, s_com);	/* recompute current
+							   position */
+	 }
+	 break;
+      }
+   }
+}
Index: /trunk/minix/commands/indent/globs.h
===================================================================
--- /trunk/minix/commands/indent/globs.h	(revision 9)
+++ /trunk/minix/commands/indent/globs.h	(revision 9)
@@ -0,0 +1,308 @@
+/**
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1980 The Regents of the University of California.
+ * Copyright (c) 1976 Board of Trustees of the University of Illinois.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley, the University of Illinois,
+ * Urbana, and Sun Microsystems, Inc.  The name of either University
+ * or Sun Microsystems may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#)indent_globs.h	5.7 (Berkeley) 9/15/88
+ */
+
+#include <stdio.h>
+
+#define BACKSLASH '\\'
+#define bufsize 200			/* size of internal buffers */
+#define inp_bufs 600			/* size of input buffer */
+#define sc_size 5000			/* size of save_com buffer */
+#define label_offset 2			/* number of levels a label is
+					   placed to left of code */
+
+#define tabsize 8			/* the size of a tab */
+#define tabmask 0177770			/* mask used when figuring
+					   length of lines with tabs */
+
+
+#define false 0
+#define true  !false
+
+
+PUBLIC FILE    *input;			/* the fid for the input file */
+PUBLIC FILE    *output;			/* the output file */
+
+PUBLIC char    *labbuf;			/* buffer for label */
+PUBLIC char    *s_lab;			/* start ... */
+PUBLIC char    *e_lab;			/* .. and end of stored label */
+PUBLIC char    *l_lab;			/* limit of label buffer */
+
+PUBLIC char    *codebuf;		/* buffer for code section */
+PUBLIC char    *s_code;			/* start ... */
+PUBLIC char    *e_code;			/* .. and end of stored code */
+PUBLIC char    *l_code;			/* limit of code section */
+
+PUBLIC char    *combuf;			/* buffer for comments */
+PUBLIC char    *s_com;			/* start ... */
+PUBLIC char    *e_com;			/* ... and end of stored
+					   comments */
+PUBLIC char    *l_com;			/* limit of comment buffer */
+
+PUBLIC char     in_buffer[inp_bufs];	/* input buffer */
+PUBLIC char    *buf_ptr;		/* ptr to next character to be
+					   taken from in_buffer */
+PUBLIC char    *buf_end;		/* ptr to first after last char
+					   in in_buffer */
+
+PUBLIC char     save_com[sc_size];	/* input text is saved here
+					   when looking for the brace
+					   after an if, while, etc */
+PUBLIC char    *sc_end;			/* pointer into save_com buffer */
+
+PUBLIC char    *bp_save;		/* saved value of buf_ptr when
+					   taking input from save_com */
+PUBLIC char    *be_save;		/* similarly saved value of
+					   buf_end */
+
+PUBLIC char     token[bufsize];		/* the last token scanned */
+
+
+PUBLIC int      ptr_binop;		/* pointer as binop */
+PUBLIC int      bl_aft_decl;		/* blanklines after
+					   declarations */
+PUBLIC int      bl_bef_bk;		/* blanklines before
+					   blockcomments */
+PUBLIC int      bl_a_procs;		/* blanklines after procs */
+PUBLIC int      bl_around;		/* blanklines around
+					   conditional compilation */
+PUBLIC int      swallow_opt_bl;		/* swallow optional blanklines */
+PUBLIC int      n_real_blanklines;
+PUBLIC int      prefix_blankline_requested;
+PUBLIC int      postfix_blankline_requested;
+PUBLIC int      break_comma;		/* when true and not in parens,
+					   break after a comma */
+PUBLIC int      btype_2;		/* when true, brace should be
+					   on same line as if, while,
+					   etc */
+PUBLIC long     case_ind;		/* indentation level to be used
+					   for a "case n:" */
+PUBLIC int      code_lines;		/* count of lines with code */
+PUBLIC int      had_eof;		/* set to true when input is
+					   exhausted */
+PUBLIC int      line_no;		/* the current line number. */
+PUBLIC int      max_col;		/* the maximum allowable line
+					   length */
+PUBLIC int      verbose;		/* when true, non-essential
+					   error messages are printed */
+PUBLIC int      cuddle_else;		/* true if else should cuddle
+					   up to '}' */
+PUBLIC int      star_comment_cont;	/* true iff comment
+					   continuation lines should
+					   have stars at the beginning
+					   of each line. */
+PUBLIC int      del_on_bl;		/* comment_delimiter_on_blanklin
+					    e */
+PUBLIC int      troff;			/* true iff were generating
+					   troff input */
+PUBLIC int      proc_str_line;		/* if true, the names of
+					   procedures being defined get
+					   placed in column 1 (ie. a
+					   newline is placed between
+					   the type of the procedure
+					   and its name) */
+PUBLIC int      proc_calls_space;	/* If true, procedure calls
+					   look like: foo(bar) rather
+					   than foo (bar) */
+PUBLIC int      format_col1_comments;	/* If comments which start in
+					   column 1 are to be magically
+					   reformatted (just like
+					   comments that begin in later
+					   columns) */
+PUBLIC int      inhibit_formatting;	/* true if INDENT OFF is in
+					   effect */
+PUBLIC int      suppress_blanklines;	/* set iff following blanklines
+					   should be suppressed */
+PUBLIC int      continuation_indent;	/* set to the indentation
+					   between the edge of code and
+					   continuation lines */
+PUBLIC int      lineup_to_parens;	/* if true, continued code
+					   within parens will be lined
+					   up to the open paren */
+PUBLIC int      Bill_Shannon;		/* true iff a blank should
+					   always be inserted after
+					   sizeof */
+PUBLIC int      bl_at_proctop;		/* This is vaguely similar to
+					   blanklines_after_declarations
+					    except that it only applies
+					   to the first set of
+					   declarations in a procedure
+					   (just after the first '{')
+					   and it causes a blank line
+					   to be generated even if
+					   there are no declarations */
+PUBLIC int      bk_max_col;
+PUBLIC int      ex_expr_indent;		/* True if continuation lines
+					   from the expression part of
+					   "if(e)", "while(e)",
+					   "for(e;e;e)" should be
+					   indented an extra tab stop
+					   so that they don't conflict
+					   with the code that follows */
+
+/* -troff font state information */
+
+struct fstate
+{
+   char            font[4];
+   char            size;
+   int             allcaps;
+};
+
+PUBLIC struct fstate
+                keywordf,		/* keyword font */
+                stringf,		/* string font */
+                boxcomf,		/* Box comment font */
+                blkcomf,		/* Block comment font */
+                scomf,			/* Same line comment font */
+                bodyf;			/* major body font */
+
+
+#define STACKSIZE 150
+
+PUBLIC struct parser_state
+{
+   int             last_token;
+   struct fstate   cfont;		/* Current font */
+   int             p_stack[STACKSIZE];	/* this is the parsers stack */
+   int             il[STACKSIZE];	/* this stack stores
+					   indentation levels */
+   long            cstk[STACKSIZE];	/* used to store case stmt
+					   indentation levels */
+   int             box_com;		/* set to true when we are in a
+					   "boxed" comment. In that
+					   case, the first non-blank
+					   char should be lined up with
+					   the / in / *     */
+   int             comment_delta, n_comment_delta;
+   int             cast_mask;		/* indicates which close parens
+					   close off casts */
+   int             sizeof_mask;		/* indicates which close parens
+					   close off sizeof''s */
+   int             block_init;		/* true iff inside a block
+					   initialization */
+   int             block_init_level;	/* The level of brace nesting
+					   in an initialization */
+   int             last_nl;		/* this is true if the last
+					   thing scanned was a newline */
+   int             in_or_st;		/* Will be true iff there has
+					   been a declarator (e.g. int
+					   or char) and no left paren
+					   since the last semicolon.
+					   When true, a '{' is starting
+					   a structure definition or an
+					   initialization list */
+   int             bl_line;		/* set to 1 by dump_line if the
+					   line is blank */
+   int             col_1;		/* set to true if the last
+					   token started in column 1 */
+   int             com_col;		/* this is the column in which
+					   the current coment should
+					   start */
+   int             com_ind;		/* the column in which comments
+					   to the right of code should
+					   start */
+   int             com_lines;		/* the number of lines with
+					   comments, set by dump_line */
+   int             dec_nest;		/* current nesting level for
+					   structure or init */
+   int             decl_com_ind;	/* the column in which comments
+					   after declarations should be
+					   put */
+   int             decl_on_line;	/* set to true if this line of
+					   code has part of a
+					   declaration on it */
+   int             i_l_follow;		/* the level to which ind_level
+					   should be set after the
+					   current line is printed */
+   int             in_decl;		/* set to true when we are in a
+					   declaration stmt.  The
+					   processing of braces is then
+					   slightly different */
+   int             in_stmt;		/* set to 1 while in a stmt */
+   int             ind_level;		/* the current indentation
+					   level */
+   int             ind_size;		/* the size of one indentation
+					   level */
+   int             ind_stmt;		/* set to 1 if next line should
+					   have an extra indentation
+					   level because we are in the
+					   middle of a stmt */
+   int             last_u_d;		/* set to true after scanning a
+					   token which forces a
+					   following operator to be
+					   unary */
+   int             leave_comma;		/* if true, never break
+					   declarations after commas */
+   int             ljust_decl;		/* true if declarations should
+					   be left justified */
+   int             out_coms;		/* the number of comments
+					   processed, set by pr_comment */
+   int             out_lines;		/* the number of lines written,
+					   set by dump_line */
+   int             p_l_follow;		/* used to remember how to
+					   indent following statement */
+   int             paren_level;		/* parenthesization level. used
+					   to indent within stmts */
+   short           paren_indents[20];	/* column positions of each
+					   paren */
+   int             pcase;		/* set to 1 if the current line
+					   label is a case.  It is
+					   printed differently from a
+					   regular label */
+   int             search_brace;	/* set to true by parse when it
+					   is necessary to buffer up
+					   all info up to the start of
+					   a stmt after an if, while,
+					   etc */
+   int             unindent_displace;	/* comments not to the right of
+					   code will be placed this
+					   many indentation levels to
+					   the left of code */
+   int             use_ff;		/* set to one if the current
+					   line should be terminated
+					   with a form feed */
+   int             want_blank;		/* set to true when the
+					   following token should be
+					   prefixed by a blank. (Said
+					   prefixing is ignored in some
+					   cases.) */
+   int             else_if;		/* True iff else if pairs
+					   should be handled specially */
+   int             decl_indent;		/* column to indent declared
+					   identifiers to */
+   int             its_a_keyword;
+   int             sizeof_keyword;
+   int             dumped_decl_indent;
+   int            case_indent;		/* The distance to indent case
+					   labels from the switch
+					   statement */
+   int             in_par_decl;
+   int             indent_parameters;
+   int             tos;			/* pointer to top of stack */
+   char            procname[100];	/* The name of the current
+					   procedure */
+   int             just_saw_decl;
+}               ps;
+
+PUBLIC int      ifdef_level;
+PUBLIC struct parser_state state_stack[5];
+PUBLIC struct parser_state match_state[5];
Index: /trunk/minix/commands/indent/indent.c
===================================================================
--- /trunk/minix/commands/indent/indent.c	(revision 9)
+++ /trunk/minix/commands/indent/indent.c	(revision 9)
@@ -0,0 +1,1374 @@
+/**
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1980 The Regents of the University of California.
+ * Copyright (c) 1976 Board of Trustees of the University of Illinois.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley, the University of Illinois,
+ * Urbana, and Sun Microsystems, Inc.  The name of either University
+ * or Sun Microsystems may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* ported to MINIX by: Robert R. Hall <hall@pnet01.cts.com>  */
+
+#define _POSIX_SOURCE 1
+#define	PUBLIC
+#define NAME_SIZE _POSIX_NAME_MAX
+
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include "globs.h"
+#include "codes.h"
+#include "proto.h"
+
+char           *in_name = "Standard Input";	/* will always point to
+						   name of input file */
+char           *out_name = "Standard Output";	/* will always point to
+						   name of output file */
+char            bakfile[60];
+
+void main(argc, argv)
+   int             argc;
+   char          **argv;
+{
+
+   extern int      found_err;		/* flag set in diag() on error */
+   int             dec_ind;		/* current indentation for
+					   declarations */
+   int             di_stack[20];	/* a stack of structure
+					   indentation levels */
+   int             flushed_nl;		/* used when buffering up
+					   comments to remember that a
+					   newline was passed over */
+   int             force_nl;		/* when true, code must be
+					   broken */
+   int             hd_type;		/* used to store type of stmt
+					   for if (...), for (...), etc */
+   register int    i;			/* local loop counter */
+   int             scase;		/* set to true when we see a
+					   case, so we will know what
+					   to do with the following
+					   colon */
+   int             sp_sw;		/* when true, we are in the
+					   expressin of if(...),
+					   while(...), etc. */
+   int             squest;		/* when this is positive, we
+					   have seen a ? without the
+					   matching : in a <c>?<s>:<s>
+					   construct */
+   register char  *t_ptr;		/* used for copying tokens */
+   int             type_code;		/* the type of token, returned
+					   by lexi */
+
+   int             last_else = 0;	/* true iff last keyword was an
+					   else */
+
+
+   /*-----------------------------------------------*\
+    |		      INITIALIZATION		      |
+    \*-----------------------------------------------*/
+
+
+   ps.p_stack[0] = stmt;		/* this is the parser's stack */
+   ps.last_nl = true;			/* this is true if the last
+					   thing scanned was a newline */
+   ps.last_token = semicolon;
+   combuf = (char *) malloc(bufsize);
+   labbuf = (char *) malloc(bufsize);
+   codebuf = (char *) malloc(bufsize);
+   l_com = combuf + bufsize - 5;
+   l_lab = labbuf + bufsize - 5;
+   l_code = codebuf + bufsize - 5;
+   combuf[0] = codebuf[0] = labbuf[0] = ' ';	/* set up code, label,
+						   and comment buffers */
+   combuf[1] = codebuf[1] = labbuf[1] = '\0';
+   ps.else_if = 1;			/* Default else-if special
+					   processing to on */
+   s_lab = e_lab = labbuf + 1;
+   s_code = e_code = codebuf + 1;
+   s_com = e_com = combuf + 1;
+
+   buf_ptr = buf_end = in_buffer;
+   line_no = 1;
+   had_eof = ps.in_decl = ps.decl_on_line = break_comma = false;
+   sp_sw = force_nl = false;
+   ps.in_or_st = false;
+   ps.bl_line = true;
+   dec_ind = 0;
+   di_stack[ps.dec_nest = 0] = 0;
+   ps.want_blank = ps.in_stmt = ps.ind_stmt = false;
+
+
+   scase = ps.pcase = false;
+   squest = 0;
+   sc_end = 0;
+   bp_save = 0;
+   be_save = 0;
+
+   output = 0;
+
+
+
+   /*--------------------------------------------------*\
+    |   		COMMAND LINE SCAN		 |
+    \*--------------------------------------------------*/
+
+#ifdef undef
+   max_col = 78;			/* -l78 */
+   lineup_to_parens = 1;		/* -lp */
+   ps.ljust_decl = 0;			/* -ndj */
+   ps.com_ind = 33;			/* -c33 */
+   star_comment_cont = 1;		/* -sc */
+   ps.ind_size = 8;			/* -i8 */
+   verbose = 0;
+   ps.decl_indent = 16;			/* -di16 */
+   ps.indent_parameters = 1;		/* -ip */
+   ps.decl_com_ind = 0;			/* if this is not set to some
+					   positive value by an arg, we
+					   will set this equal to
+					   ps.com_ind */
+   btype_2 = 1;				/* -br */
+   cuddle_else = 1;			/* -ce */
+   ps.unindent_displace = 0;		/* -d0 */
+   ps.case_indent = 0;			/* -cli0 */
+   format_col1_comments = 1;		/* -fc1 */
+   procnames_start_line = 1;		/* -psl */
+   proc_calls_space = 0;		/* -npcs */
+   comment_delimiter_on_blankline = 1;	/* -cdb */
+   ps.leave_comma = 1;			/* -nbc */
+#endif
+
+   for (i = 1; i < argc; ++i)
+      if (strcmp(argv[i], "-npro") == 0)
+	 break;
+   set_defaults();
+   if (i >= argc)
+      set_profile();
+
+   for (i = 1; i < argc; ++i)
+   {
+
+      /* look thru args (if any) for changes to defaults */
+      if (argv[i][0] != '-')
+      {					/* no flag on parameter */
+	 if (input == 0)
+	 {				/* we must have the input file */
+	    in_name = argv[i];		/* remember name of input file */
+	    input = fopen(in_name, "r");
+	    if (input == 0)
+	    {				/* check for open error */
+	       fprintf(stderr, "indent: can't open %s\n", argv[i]);
+	       exit(1);
+	    }
+	    continue;
+	 } else if (output == 0)
+	 {				/* we have the output file */
+	    out_name = argv[i];		/* remember name of output file */
+	    if (strcmp(in_name, out_name) == 0)
+	    {				/* attempt to overwrite the
+					   file */
+	       fprintf(stderr, "indent: input and output files must be different\n");
+	       exit(1);
+	    }
+	    output = fopen(out_name, "w");
+	    if (output == 0)
+	    {				/* check for create error */
+	       fprintf(stderr, "indent: can't create %s\n", argv[i]);
+	       exit(1);
+	    }
+	    continue;
+	 }
+	 fprintf(stderr, "indent: unknown parameter: %s\n", argv[i]);
+	 exit(1);
+      } else
+	 set_option(argv[i]);
+   }					/* end of for */
+   if (input == 0)
+   {
+      fprintf(stderr, "indent: usage: indent file [ outfile ] [ options ]\n");
+      exit(1);
+   }
+   if (output == 0)
+      if (troff)
+	 output = stdout;
+      else
+      {
+	 out_name = in_name;
+	 bakcopy();
+      }
+   if (ps.com_ind <= 1)
+      ps.com_ind = 2;			/* dont put normal comments
+					   before column 2 */
+   if (troff)
+   {
+      if (bodyf.font[0] == 0)
+	 parsefont(&bodyf, "R");
+      if (scomf.font[0] == 0)
+	 parsefont(&scomf, "I");
+      if (blkcomf.font[0] == 0)
+	 blkcomf = scomf, blkcomf.size += 2;
+      if (boxcomf.font[0] == 0)
+	 boxcomf = blkcomf;
+      if (stringf.font[0] == 0)
+	 parsefont(&stringf, "L");
+      if (keywordf.font[0] == 0)
+	 parsefont(&keywordf, "B");
+      writefdef(&bodyf, 'B');
+      writefdef(&scomf, 'C');
+      writefdef(&blkcomf, 'L');
+      writefdef(&boxcomf, 'X');
+      writefdef(&stringf, 'S');
+      writefdef(&keywordf, 'K');
+   }
+   if (bk_max_col <= 0)
+      bk_max_col = max_col;
+   if (ps.decl_com_ind <= 0)		/* if not specified by user,
+					   set this */
+      ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind;
+   if (continuation_indent == 0)
+      continuation_indent = ps.ind_size;
+   fill_buffer();			/* get first batch of stuff
+					   into input buffer */
+
+   parse(semicolon);
+   {
+      register char  *p = buf_ptr;
+      register        col = 1;
+
+      while (1)
+      {
+	 if (*p == ' ')
+	    col++;
+	 else if (*p == '\t')
+	    col = ((col - 1) & ~7) + 9;
+	 else
+	    break;
+	 p++;
+      };
+      if (col > ps.ind_size)
+	 ps.ind_level = ps.i_l_follow = col / ps.ind_size;
+   }
+   if (troff)
+   {
+      register char  *p = in_name, *beg = in_name;
+
+      while (*p)
+	 if (*p++ == '/')
+	    beg = p;
+      fprintf(output, ".Fn \"%s\"\n", beg);
+   }
+   /* START OF MAIN LOOP */
+
+   while (1)
+   {					/* this is the main loop.  it
+					   will go until we reach eof */
+      int             is_procname;
+
+      type_code = lexi();		/* lexi reads one token.  The
+					   actual characters read are
+					   stored in "token". lexi
+					   returns a code indicating
+					   the type of token */
+      is_procname = ps.procname[0];
+
+      /* The following code moves everything following an if (), while
+         (), else, etc. up to the start of the following stmt to a
+         buffer. This allows proper handling of both kinds of brace
+         placement. */
+
+      flushed_nl = false;
+      while (ps.search_brace)
+      {					/* if we scanned an if(),
+					   while(), etc., we might need
+					   to copy stuff into a buffer
+					   we must loop, copying stuff
+					   into save_com, until we find
+					   the start of the stmt which
+					   follows the if, or whatever */
+	 switch (type_code)
+	 {
+	 case newline:
+	    ++line_no;
+	    flushed_nl = true;
+	 case form_feed:
+	    break;			/* form feeds and newlines
+					   found here will be ignored */
+
+	 case lbrace:			/* this is a brace that starts
+					   the compound stmt */
+	    if (sc_end == 0)
+	    {				/* ignore buffering if a
+					   comment wasnt stored up */
+	       ps.search_brace = false;
+	       goto check_type;
+	    }
+	    if (btype_2)
+	    {
+	       save_com[0] = '{';	/* we either want to put the
+					   brace right after the if */
+	       goto sw_buffer;		/* go to common code to get out
+					   of this loop */
+	    }
+/*
+ * Something is buffered up in save_com, and -bl processing is in effect.
+ * Add the brace after the comment so it will come out on the next line.
+ */
+	    flushed_nl = 0;	/* comment can start on the same line */
+	    *sc_end++ = '\n';	/* break line after comment */
+	    *sc_end++ = '{';
+	    goto sw_buffer;
+
+	 case comment:			/* we have a comment, so we
+					   must copy it into the buffer */
+	    if (!flushed_nl || sc_end != 0)
+	    {
+	       if (sc_end == 0)
+	       {			/* if this is the first
+					   comment, we must set up the
+					   buffer */
+		  save_com[0] = save_com[1] = ' ';
+		  sc_end = &(save_com[2]);
+	       } else
+	       {
+		  *sc_end++ = '\n';	/* add newline between comments */
+		  *sc_end++ = ' ';
+		  --line_no;
+	       }
+	       *sc_end++ = '/';		/* copy in start of comment */
+	       *sc_end++ = '*';
+
+	       for (;;)
+	       {			/* loop until we get to the end
+					   of the comment */
+		  *sc_end = *buf_ptr++;
+		  if (buf_ptr >= buf_end)
+		     fill_buffer();
+
+		  if (*sc_end++ == '*' && *buf_ptr == '/')
+		     break;		/* we are at end of comment */
+
+		  if (sc_end >= &(save_com[sc_size]))
+		  {			/* check for temp buffer
+					   overflow */
+		     diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever.");
+		     fflush(output);
+		     exit(1);
+		  }
+	       }
+	       *sc_end++ = '/';		/* add ending slash */
+	       if (++buf_ptr >= buf_end)/* get past / in buffer */
+		  fill_buffer();
+	       break;
+	    }
+	 default:			/* it is the start of a normal
+					   statment */
+	    if (flushed_nl)		/* if we flushed a newline,
+					   make sure it is put back */
+	       force_nl = true;
+	    if ((type_code == sp_paren && *token == 'i'
+		    && last_else && ps.else_if)
+		|| (type_code == sp_nparen && *token == 'e'
+		    && e_code != s_code && e_code[-1] == '}'))
+	       force_nl = false;
+
+	    if (sc_end == 0)
+	    {				/* ignore buffering if comment
+					   wasnt saved up */
+	       ps.search_brace = false;
+	       goto check_type;
+	    }
+	    if (force_nl)
+	    {				/* if we should insert a nl
+					   here, put it into the buffer */
+	       force_nl = false;
+	       --line_no;		/* this will be re-increased
+					   when the nl is read from the
+					   buffer */
+	       *sc_end++ = '\n';
+	       *sc_end++ = ' ';
+	       if (verbose && !flushed_nl)	/* print error msg if
+						   the line was not
+						   already broken */
+		  diag(0, "Line broken");
+	       flushed_nl = false;
+	    }
+	    for (t_ptr = token; *t_ptr; ++t_ptr)
+	       *sc_end++ = *t_ptr;	/* copy token into temp buffer */
+	    ps.procname[0] = 0;
+
+      sw_buffer:
+	    ps.search_brace = false;	/* stop looking for start of
+					   stmt */
+	    bp_save = buf_ptr;		/* save current input buffer */
+	    be_save = buf_end;
+	    buf_ptr = save_com;		/* fix so that subsequent calls
+					   to lexi will take tokens out
+					   of save_com */
+	    *sc_end++ = ' ';		/* add trailing blank, just in
+					   case */
+	    buf_end = sc_end;
+	    sc_end = 0;
+	    break;
+	 }				/* end of switch */
+	 if (type_code != 0)		/* we must make this check,
+					   just in case there was an
+					   unexpected EOF */
+	    type_code = lexi();		/* read another token */
+	 /* if (ps.search_brace) ps.procname[0] = 0; */
+	 if ((is_procname = ps.procname[0]) && flushed_nl
+	     && !proc_str_line && ps.in_decl
+	     && type_code == ident)
+	    flushed_nl = 0;
+      }					/* end of while (search_brace) */
+      last_else = 0;
+check_type:
+      if (type_code == 0)
+      {					/* we got eof */
+	 if (s_lab != e_lab || s_code != e_code
+	     || s_com != e_com)		/* must dump end of line */
+	    dump_line();
+	 if (ps.tos > 1)		/* check for balanced braces */
+	    diag(1, "Stuff missing from end of file.");
+
+	 if (verbose)
+	 {
+	    printf("There were %d output lines and %d comments\n",
+		   ps.out_lines, ps.out_coms);
+	    printf("(Lines with comments)/(Lines with code): %6d\n",
+		   ps.com_lines / code_lines);
+	 }
+	 fflush(output);
+	 exit(found_err);
+      }
+      if (
+	  (type_code != comment) &&
+	  (type_code != newline) &&
+	  (type_code != preesc) &&
+	  (type_code != form_feed))
+      {
+	 if (force_nl &&
+	     (type_code != semicolon) &&
+	     (type_code != lbrace || !btype_2))
+	 {
+	    /* we should force a broken line here */
+	    if (verbose && !flushed_nl)
+	       diag(0, "Line broken");
+	    flushed_nl = false;
+	    dump_line();
+	    ps.want_blank = false;	/* dont insert blank at line
+					   start */
+	    force_nl = false;
+	 }
+	 ps.in_stmt = true;		/* turn on flag which causes an
+					   extra level of indentation.
+					   this is turned off by a ; or
+					   '}' */
+	 if (s_com != e_com)
+	 {				/* the turkey has embedded a
+					   comment in a line. fix it */
+	    *e_code++ = ' ';
+	    for (t_ptr = s_com; *t_ptr; ++t_ptr)
+	    {
+	       if (e_code >= l_code)
+	       {
+		  register        nsize = l_code - s_code + 400;
+		  codebuf = (char *) realloc(codebuf, nsize);
+		  e_code = codebuf + (e_code - s_code) + 1;
+		  l_code = codebuf + nsize - 5;
+		  s_code = codebuf + 1;
+	       }
+	       *e_code++ = *t_ptr;
+	    }
+	    *e_code++ = ' ';
+	    *e_code = '\0';		/* null terminate code sect */
+	    ps.want_blank = false;
+	    e_com = s_com;
+	 }
+      } else if (type_code != comment)	/* preserve force_nl thru a
+					   comment */
+	 force_nl = false;		/* cancel forced newline after
+					   newline, form feed, etc */
+
+
+
+      /*-----------------------------------------------------*\
+        |	   do switch on type of token scanned		|
+        \*-----------------------------------------------------*/
+      if (e_code >= l_code)
+      {
+	 register        nsize = l_code - s_code + 400;
+	 codebuf = (char *) realloc(codebuf, nsize);
+	 e_code = codebuf + (e_code - s_code) + 1;
+	 l_code = codebuf + nsize - 5;
+	 s_code = codebuf + 1;
+      }
+      switch (type_code)
+      {					/* now, decide what to do with
+					   the token */
+
+      case form_feed:			/* found a form feed in line */
+	 ps.use_ff = true;		/* a form feed is treated much
+					   like a newline */
+	 dump_line();
+	 ps.want_blank = false;
+	 break;
+
+      case newline:
+	 if (ps.last_token != comma || ps.p_l_follow > 0
+	     || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com)
+	 {
+	    dump_line();
+	    ps.want_blank = false;
+	 }
+	 ++line_no;			/* keep track of input line
+					   number */
+	 break;
+
+      case lparen:			/* got a '(' or '[' */
+	 ++ps.p_l_follow;		/* count parens to make Healy
+					   happy */
+	 if (ps.want_blank && *token != '[' &&
+	     (ps.last_token != ident || proc_calls_space
+	      || (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon))))
+	    *e_code++ = ' ';
+	 if (ps.in_decl && !ps.block_init)
+	    if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl)
+	    {
+	       ps.dumped_decl_indent = 1;
+	       sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
+	       e_code += strlen(e_code);
+	    } else
+	    {
+	       while ((e_code - s_code) < dec_ind)
+	       {
+		  if (e_code >= l_code)
+		  {
+		     register        nsize = l_code - s_code + 400;
+		     codebuf = (char *) realloc(codebuf, nsize);
+		     e_code = codebuf + (e_code - s_code) + 1;
+		     l_code = codebuf + nsize - 5;
+		     s_code = codebuf + 1;
+		  }
+		  *e_code++ = ' ';
+	       }
+	       *e_code++ = token[0];
+	    }
+	 else
+	    *e_code++ = token[0];
+	 ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code;
+	 if (sp_sw && ps.p_l_follow == 1 && ex_expr_indent
+	     && ps.paren_indents[0] < 2 * ps.ind_size)
+	    ps.paren_indents[0] = 2 * ps.ind_size;
+	 ps.want_blank = false;
+	 if (ps.in_or_st && *token == '(' && ps.tos <= 2)
+	 {
+	    /* this is a kluge to make sure that declarations will be
+	       aligned right if proc decl has an explicit type on it,
+	       i.e. "int a(x) {..." */
+	    parse(semicolon);		/* I said this was a kluge... */
+	    ps.in_or_st = false;	/* turn off flag for structure
+					   decl or initialization */
+	 }
+	 if (ps.sizeof_keyword)
+	    ps.sizeof_mask |= 1 << ps.p_l_follow;
+	 break;
+
+      case rparen:			/* got a ')' or ']' */
+	 if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask)
+	 {
+	    ps.last_u_d = true;
+	    ps.cast_mask &= (1 << ps.p_l_follow) - 1;
+	 }
+	 ps.sizeof_mask &= (1 << ps.p_l_follow) - 1;
+	 if (--ps.p_l_follow < 0)
+	 {
+	    ps.p_l_follow = 0;
+	    diag(0, "Extra %c", *token);
+	 }
+	 if (e_code == s_code)		/* if the paren starts the line */
+	    ps.paren_level = ps.p_l_follow;	/* then indent it */
+
+	 *e_code++ = token[0];
+	 ps.want_blank = true;
+
+	 if (sp_sw && (ps.p_l_follow == 0))
+	 {				/* check for end of if (...),
+					   or some such */
+	    sp_sw = false;
+	    force_nl = true;		/* must force newline after if */
+	    ps.last_u_d = true;		/* inform lexi that a following
+					   operator is unary */
+	    ps.in_stmt = false;		/* dont use stmt continuation
+					   indentation */
+
+	    parse(hd_type);		/* let parser worry about if,
+					   or whatever */
+	 }
+	 ps.search_brace = btype_2;	/* this should insure that
+					   constructs such as
+					   main(){...} and int[]{...}
+					   have their braces put in the
+					   right place */
+	 break;
+
+      case unary_op:			/* this could be any unary
+					   operation */
+	 if (ps.want_blank)
+	    *e_code++ = ' ';
+
+	 if (troff && !ps.dumped_decl_indent && ps.in_decl && !is_procname)
+	 {
+	    sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
+	    ps.dumped_decl_indent = 1;
+	    e_code += strlen(e_code);
+	 } else
+	 {
+	    char           *res = token;
+
+	    if (ps.in_decl && !ps.block_init)
+	    {				/* if this is a unary op in a
+					   declaration, we should
+					   indent this token */
+	       for (i = 0; token[i]; ++i);	/* find length of token */
+	       while ((e_code - s_code) < (dec_ind - i))
+	       {
+		  if (e_code >= l_code)
+		  {
+		     register        nsize = l_code - s_code + 400;
+		     codebuf = (char *) realloc(codebuf, nsize);
+		     e_code = codebuf + (e_code - s_code) + 1;
+		     l_code = codebuf + nsize - 5;
+		     s_code = codebuf + 1;
+		  }
+		  *e_code++ = ' ';	/* pad it */
+	       }
+	    }
+	    if (troff && token[0] == '-' && token[1] == '>')
+	       res = "\\(->";
+	    for (t_ptr = res; *t_ptr; ++t_ptr)
+	    {
+	       if (e_code >= l_code)
+	       {
+		  register        nsize = l_code - s_code + 400;
+		  codebuf = (char *) realloc(codebuf, nsize);
+		  e_code = codebuf + (e_code - s_code) + 1;
+		  l_code = codebuf + nsize - 5;
+		  s_code = codebuf + 1;
+	       }
+	       *e_code++ = *t_ptr;
+	    }
+	 }
+	 ps.want_blank = false;
+	 break;
+
+      case binary_op:			/* any binary operation */
+	 if (ps.want_blank)
+	    *e_code++ = ' ';
+	 {
+	    char           *res = token;
+
+	    if (troff)
+	       switch (token[0])
+	       {
+	       case '<':
+		  if (token[1] == '=')
+		     res = "\\(<=";
+		  break;
+	       case '>':
+		  if (token[1] == '=')
+		     res = "\\(>=";
+		  break;
+	       case '!':
+		  if (token[1] == '=')
+		     res = "\\(!=";
+		  break;
+	       case '|':
+		  if (token[1] == '|')
+		     res = "\\(br\\(br";
+		  else if (token[1] == 0)
+		     res = "\\(br";
+		  break;
+	       }
+	    for (t_ptr = res; *t_ptr; ++t_ptr)
+	    {
+	       if (e_code >= l_code)
+	       {
+		  register        nsize = l_code - s_code + 400;
+		  codebuf = (char *) realloc(codebuf, nsize);
+		  e_code = codebuf + (e_code - s_code) + 1;
+		  l_code = codebuf + nsize - 5;
+		  s_code = codebuf + 1;
+	       }
+	       *e_code++ = *t_ptr;	/* move the operator */
+	    }
+	 }
+	 ps.want_blank = true;
+	 break;
+
+      case postop:			/* got a trailing ++ or -- */
+	 *e_code++ = token[0];
+	 *e_code++ = token[1];
+	 ps.want_blank = true;
+	 break;
+
+      case question:			/* got a ? */
+	 squest++;			/* this will be used when a
+					   later colon appears so we
+					   can distinguish the
+					   <c>?<n>:<n> construct */
+	 if (ps.want_blank)
+	    *e_code++ = ' ';
+	 *e_code++ = '?';
+	 ps.want_blank = true;
+	 break;
+
+      case casestmt:			/* got word 'case' or 'default' */
+	 scase = true;			/* so we can process the later
+					   colon properly */
+	 goto copy_id;
+
+      case colon:			/* got a ':' */
+	 if (squest > 0)
+	 {				/* it is part of the <c>?<n>:
+					   <n> construct */
+	    --squest;
+	    if (ps.want_blank)
+	       *e_code++ = ' ';
+	    *e_code++ = ':';
+	    ps.want_blank = true;
+	    break;
+	 }
+	 if (ps.in_decl)
+	 {
+	    *e_code++ = ':';
+	    ps.want_blank = false;
+	    break;
+	 }
+	 ps.in_stmt = false;		/* seeing a label does not
+					   imply we are in a stmt */
+	 for (t_ptr = s_code; *t_ptr; ++t_ptr)
+	    *e_lab++ = *t_ptr;		/* turn everything so far into
+					   a label */
+	 e_code = s_code;
+	 *e_lab++ = ':';
+	 *e_lab++ = ' ';
+	 *e_lab = '\0';
+
+	 force_nl = ps.pcase = scase;	/* ps.pcase will be used by
+					   dump_line to decide how to
+					   indent the label. force_nl
+					   will force a case n: to be
+					   on a line by itself */
+	 scase = false;
+	 ps.want_blank = false;
+	 break;
+
+      case semicolon:			/* got a ';' */
+	 ps.in_or_st = false;		/* we are not in an
+					   initialization or structure
+					   declaration */
+	 scase = false;			/* these will only need
+					   resetting in a error */
+	 squest = 0;
+	 if (ps.last_token == rparen)
+	    ps.in_par_decl = 0;
+	 ps.cast_mask = 0;
+	 ps.sizeof_mask = 0;
+	 ps.block_init = 0;
+	 ps.block_init_level = 0;
+	 ps.just_saw_decl--;
+
+	 if (ps.in_decl && s_code == e_code && !ps.block_init)
+	    while ((e_code - s_code) < (dec_ind - 1))
+	    {
+	       if (e_code >= l_code)
+	       {
+		  register        nsize = l_code - s_code + 400;
+		  codebuf = (char *) realloc(codebuf, nsize);
+		  e_code = codebuf + (e_code - s_code) + 1;
+		  l_code = codebuf + nsize - 5;
+		  s_code = codebuf + 1;
+	       }
+	       *e_code++ = ' ';
+	    }
+
+	 ps.in_decl = (ps.dec_nest > 0);/* if we were in a first level
+					   structure declaration, we
+					   arent any more */
+
+	 if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0)
+	 {
+
+	    /* This should be true iff there were unbalanced parens in
+	       the stmt.  It is a bit complicated, because the
+	       semicolon might be in a for stmt */
+	    diag(1, "Unbalanced parens");
+	    ps.p_l_follow = 0;
+	    if (sp_sw)
+	    {				/* this is a check for a if,
+					   while, etc. with unbalanced
+					   parens */
+	       sp_sw = false;
+	       parse(hd_type);		/* dont lose the if, or
+					   whatever */
+	    }
+	 }
+	 *e_code++ = ';';
+	 ps.want_blank = true;
+	 ps.in_stmt = (ps.p_l_follow > 0);	/* we are no longer in
+						   the middle of a stmt */
+
+	 if (!sp_sw)
+	 {				/* if not if for (;;) */
+	    parse(semicolon);		/* let parser know about end of
+					   stmt */
+	    force_nl = true;		/* force newline after a end of
+					   stmt */
+	 }
+	 break;
+
+      case lbrace:			/* got a '{' */
+	 ps.in_stmt = false;		/* dont indent the {} */
+	 if (!ps.block_init)
+	    force_nl = true;		/* force other stuff on same
+					   line as '{' onto new line */
+	 else if (ps.block_init_level <= 0)
+	    ps.block_init_level = 1;
+	 else
+	    ps.block_init_level++;
+
+	 if (s_code != e_code && !ps.block_init)
+	 {
+	    if (!btype_2)
+	    {
+	       dump_line();
+	       ps.want_blank = false;
+	    } else if (ps.in_par_decl && !ps.in_or_st)
+	    {
+	       ps.i_l_follow = 0;
+	       dump_line();
+	       ps.want_blank = false;
+	    }
+	 }
+	 if (ps.in_par_decl)
+	    prefix_blankline_requested = 0;
+
+	 if (ps.p_l_follow > 0)
+	 {				/* check for preceeding
+					   unbalanced parens */
+	    diag(1, "Unbalanced parens");
+	    ps.p_l_follow = 0;
+	    if (sp_sw)
+	    {				/* check for unclosed if, for,
+					   etc. */
+	       sp_sw = false;
+	       parse(hd_type);
+	       ps.ind_level = ps.i_l_follow;
+	    }
+	 }
+	 if (s_code == e_code)
+	    ps.ind_stmt = false;	/* dont put extra indentation
+					   on line with '{' */
+	 if (ps.in_decl && ps.in_or_st)
+	 {				/* this is either a structure
+					   declaration or an init */
+	    di_stack[ps.dec_nest++] = dec_ind;
+	    /* ?		dec_ind = 0; */
+	 } else
+	 {
+	    ps.decl_on_line = false;	/* we cant be in the middle of
+					   a declaration, so dont do
+					   special indentation of
+					   comments */
+	    if (bl_at_proctop
+		&& ps.in_par_decl)
+	       postfix_blankline_requested = 1;
+	    ps.in_par_decl = 0;
+	 }
+	 dec_ind = 0;
+	 parse(lbrace);			/* let parser know about this */
+	 if (ps.want_blank)		/* put a blank before '{' if
+					   '{' is not at start of line */
+	    *e_code++ = ' ';
+	 ps.want_blank = false;
+	 *e_code++ = '{';
+	 ps.just_saw_decl = 0;
+	 break;
+
+      case rbrace:			/* got a '}' */
+	 if (ps.p_stack[ps.tos] == decl && !ps.block_init)	/* semicolons can be
+								   omitted in
+								   declarations */
+	    parse(semicolon);
+	 if (ps.p_l_follow)
+	 {				/* check for unclosed if, for,
+					   else. */
+	    diag(1, "Unbalanced parens");
+	    ps.p_l_follow = 0;
+	    sp_sw = false;
+	 }
+	 ps.just_saw_decl = 0;
+	 ps.block_init_level--;
+	 if (s_code != e_code && !ps.block_init)
+	 {				/* '}' must be first on line */
+	    if (verbose)
+	       diag(0, "Line broken");
+	    dump_line();
+	 }
+	 *e_code++ = '}';
+	 ps.want_blank = true;
+	 ps.in_stmt = ps.ind_stmt = false;
+	 if (ps.dec_nest > 0)
+	 {				/* we are in multi-level
+					   structure declaration */
+	    dec_ind = di_stack[--ps.dec_nest];
+	    if (ps.dec_nest == 0 && !ps.in_par_decl)
+	       ps.just_saw_decl = 2;
+	    ps.in_decl = true;
+	 }
+	 prefix_blankline_requested = 0;
+	 parse(rbrace);			/* let parser know about this */
+	 ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead
+	    && ps.il[ps.tos] >= ps.ind_level;
+	 if (ps.tos <= 1 && bl_a_procs && ps.dec_nest <= 0)
+	    postfix_blankline_requested = 1;
+	 break;
+
+      case swstmt:			/* got keyword "switch" */
+	 sp_sw = true;
+	 hd_type = swstmt;		/* keep this for when we have
+					   seen the expression */
+	 goto copy_id;			/* go move the token into
+					   buffer */
+
+      case sp_paren:			/* token is if, while, for */
+	 sp_sw = true;			/* the interesting stuff is
+					   done after the expression is
+					   scanned */
+	 hd_type = (*token == 'i' ? ifstmt :
+		    (*token == 'w' ? whilestmt : forstmt));
+
+	 /* remember the type of header for later use by parser */
+	 goto copy_id;			/* copy the token into line */
+
+      case sp_nparen:			/* got else, do */
+	 ps.in_stmt = false;
+	 if (*token == 'e')
+	 {
+	    if (e_code != s_code && (!cuddle_else || e_code[-1] != '}'))
+	    {
+	       if (verbose)
+		  diag(0, "Line broken");
+	       dump_line();		/* make sure this starts a line */
+	       ps.want_blank = false;
+	    }
+	    force_nl = true;		/* also, following stuff must
+					   go onto new line */
+	    last_else = 1;
+	    parse(elselit);
+	 } else
+	 {
+	    if (e_code != s_code)
+	    {				/* make sure this starts a line */
+	       if (verbose)
+		  diag(0, "Line broken");
+	       dump_line();
+	       ps.want_blank = false;
+	    }
+	    force_nl = true;		/* also, following stuff must
+					   go onto new line */
+	    last_else = 0;
+	    parse(dolit);
+	 }
+	 goto copy_id;			/* move the token into line */
+
+      case decl:			/* we have a declaration type
+					   (int, register, etc.) */
+	 parse(decl);			/* let parser worry about
+					   indentation */
+	 if (ps.last_token == rparen && ps.tos <= 1)
+	 {
+	    ps.in_par_decl = 1;
+	    if (s_code != e_code)
+	    {
+	       dump_line();
+	       ps.want_blank = 0;
+	    }
+	 }
+	 if (ps.in_par_decl && ps.indent_parameters && ps.dec_nest == 0)
+	 {
+	    ps.ind_level = ps.i_l_follow = 1;
+	    ps.ind_stmt = 0;
+	 }
+	 ps.in_or_st = true;		/* this might be a structure or
+					   initialization declaration */
+	 ps.in_decl = ps.decl_on_line = true;
+	 if ( /* !ps.in_or_st && */ ps.dec_nest <= 0)
+	    ps.just_saw_decl = 2;
+	 prefix_blankline_requested = 0;
+	 for (i = 0; token[i++];);	/* get length of token */
+
+	 /* dec_ind = e_code - s_code + (ps.decl_indent>i ?
+	    ps.decl_indent : i); */
+	 dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i;
+	 goto copy_id;
+
+      case ident:			/* got an identifier or
+					   constant */
+	 if (ps.in_decl)
+	 {				/* if we are in a declaration,
+					   we must indent identifier */
+	    if (ps.want_blank)
+	       *e_code++ = ' ';
+	    ps.want_blank = false;
+	    if (is_procname == 0 || !proc_str_line)
+	    {
+	       if (!ps.block_init)
+		  if (troff && !ps.dumped_decl_indent)
+		  {
+		     sprintf(e_code, "\n.De %dp+\200p\n", dec_ind * 7);
+		     ps.dumped_decl_indent = 1;
+		     e_code += strlen(e_code);
+		  } else
+		     while ((e_code - s_code) < dec_ind)
+		     {
+			if (e_code >= l_code)
+			{
+			   register        nsize = l_code - s_code + 400;
+			   codebuf = (char *) realloc(codebuf, nsize);
+			   e_code = codebuf + (e_code - s_code) + 1;
+			   l_code = codebuf + nsize - 5;
+			   s_code = codebuf + 1;
+			}
+			*e_code++ = ' ';
+		     }
+	    } else
+	    {
+	       if (dec_ind && s_code != e_code)
+		  dump_line();
+	       dec_ind = 0;
+	       ps.want_blank = false;
+	    }
+	 } else if (sp_sw && ps.p_l_follow == 0)
+	 {
+	    sp_sw = false;
+	    force_nl = true;
+	    ps.last_u_d = true;
+	    ps.in_stmt = false;
+	    parse(hd_type);
+	 }
+   copy_id:
+	 if (ps.want_blank)
+	    *e_code++ = ' ';
+	 if (troff && ps.its_a_keyword)
+	 {
+	    e_code = chfont(&bodyf, &keywordf, e_code);
+	    for (t_ptr = token; *t_ptr; ++t_ptr)
+	    {
+	       if (e_code >= l_code)
+	       {
+		  register        nsize = l_code - s_code + 400;
+		  codebuf = (char *) realloc(codebuf, nsize);
+		  e_code = codebuf + (e_code - s_code) + 1;
+		  l_code = codebuf + nsize - 5;
+		  s_code = codebuf + 1;
+	       }
+	       *e_code++ = keywordf.allcaps && islower(*t_ptr)
+		  ? toupper(*t_ptr) : *t_ptr;
+	    }
+	    e_code = chfont(&keywordf, &bodyf, e_code);
+	 } else
+	    for (t_ptr = token; *t_ptr; ++t_ptr)
+	    {
+	       if (e_code >= l_code)
+	       {
+		  register        nsize = l_code - s_code + 400;
+		  codebuf = (char *) realloc(codebuf, nsize);
+		  e_code = codebuf + (e_code - s_code) + 1;
+		  l_code = codebuf + nsize - 5;
+		  s_code = codebuf + 1;
+	       }
+	       *e_code++ = *t_ptr;
+	    }
+	 ps.want_blank = true;
+	 break;
+
+      case period:			/* treat a period kind of like
+					   a binary operation */
+	 *e_code++ = '.';		/* move the period into line */
+	 ps.want_blank = false;		/* dont put a blank after a
+					   period */
+	 break;
+
+      case comma:
+	 ps.want_blank = (s_code != e_code);	/* only put blank after
+						   comma if comma does
+						   not start the line */
+	 if (ps.in_decl && is_procname == 0 && !ps.block_init)
+	    while ((e_code - s_code) < (dec_ind - 1))
+	    {
+	       if (e_code >= l_code)
+	       {
+		  register        nsize = l_code - s_code + 400;
+		  codebuf = (char *) realloc(codebuf, nsize);
+		  e_code = codebuf + (e_code - s_code) + 1;
+		  l_code = codebuf + nsize - 5;
+		  s_code = codebuf + 1;
+	       }
+	       *e_code++ = ' ';
+	    }
+
+	 *e_code++ = ',';
+	 if (ps.p_l_follow == 0)
+	 {
+	    if (ps.block_init_level <= 0)
+	       ps.block_init = 0;
+	    if (break_comma && !ps.leave_comma)
+	       force_nl = true;
+	 }
+	 break;
+
+      case preesc:			/* got the character '#' */
+	 if ((s_com != e_com) ||
+	     (s_lab != e_lab) ||
+	     (s_code != e_code))
+	    dump_line();
+	 *e_lab++ = '#';		/* move whole line to 'label'
+					   buffer */
+	 {
+	    int             in_comment = 0;
+	    int             com_start = 0;
+	    char            quote = 0;
+	    int             com_end = 0;
+
+	    while (*buf_ptr != '\n' || in_comment)
+	    {
+	       if (e_lab >= l_lab)
+	       {
+		  register        nsize = l_lab - s_lab + 400;
+		  labbuf = (char *) realloc(labbuf, nsize);
+		  e_lab = labbuf + (e_lab - s_lab) + 1;
+		  l_lab = labbuf + nsize - 5;
+		  s_lab = labbuf + 1;
+	       }
+	       *e_lab = *buf_ptr++;
+	       if (buf_ptr >= buf_end)
+		  fill_buffer();
+	       switch (*e_lab++)
+	       {
+	       case BACKSLASH:
+		  if (troff)
+		     *e_lab++ = BACKSLASH;
+		  if (!in_comment)
+		  {
+		     *e_lab++ = *buf_ptr++;
+		     if (buf_ptr >= buf_end)
+			fill_buffer();
+		  }
+		  break;
+	       case '/':
+		  if (*buf_ptr == '*' && !in_comment && !quote)
+		  {
+		     in_comment = 1;
+		     *e_lab++ = *buf_ptr++;
+		     com_start = e_lab - s_lab - 2;
+		  }
+		  break;
+	       case '"':
+		  if (quote == '"')
+		     quote = 0;
+		  break;
+	       case '\'':
+		  if (quote == '\'')
+		     quote = 0;
+		  break;
+	       case '*':
+		  if (*buf_ptr == '/' && in_comment)
+		  {
+		     in_comment = 0;
+		     *e_lab++ = *buf_ptr++;
+		     com_end = e_lab - s_lab;
+		  }
+		  break;
+	       }
+	    }
+
+	    while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
+	       e_lab--;
+	    if (e_lab - s_lab == com_end && bp_save == 0)
+	    {				/* comment on preprocessor line */
+	       if (sc_end == 0)		/* if this is the first
+					   comment, we must set up the
+					   buffer */
+		  sc_end = &(save_com[0]);
+	       else
+	       {
+		  *sc_end++ = '\n';	/* add newline between comments */
+		  *sc_end++ = ' ';
+		  --line_no;
+	       }
+	       memcpy(sc_end, s_lab + com_start, com_end - com_start);
+	       sc_end += com_end - com_start;
+	       if (sc_end >= &save_com[sc_size])
+		  abort();
+	       e_lab = s_lab + com_start;
+	       while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
+		  e_lab--;
+	       bp_save = buf_ptr;	/* save current input buffer */
+	       be_save = buf_end;
+	       buf_ptr = save_com;	/* fix so that subsequent calls
+					   to lexi will take tokens out
+					   of save_com */
+	       *sc_end++ = ' ';		/* add trailing blank, just in
+					   case */
+	       buf_end = sc_end;
+	       sc_end = 0;
+	    }
+	    *e_lab = '\0';		/* null terminate line */
+	    ps.pcase = false;
+	 }
+
+	 if (strncmp(s_lab, "#if", 3) == 0)
+	 {
+	    if (bl_around)
+	    {
+	       register        c;
+	       prefix_blankline_requested++;
+	       while ((c = getc(input)) == '\n');
+	       ungetc(c, input);
+	    }
+	    if (ifdef_level < sizeof state_stack / sizeof state_stack[0])
+	    {
+	       match_state[ifdef_level].tos = -1;
+	       state_stack[ifdef_level++] = ps;
+	    } else
+	       diag(1, "#if stack overflow");
+	 } else if (strncmp(s_lab, "#else", 5) == 0)
+	    if (ifdef_level <= 0)
+	       diag(1, "Unmatched #else");
+	    else
+	    {
+	       match_state[ifdef_level - 1] = ps;
+	       ps = state_stack[ifdef_level - 1];
+	    }
+	 else if (strncmp(s_lab, "#endif", 6) == 0)
+	 {
+	    if (ifdef_level <= 0)
+	       diag(1, "Unmatched #endif");
+	    else
+	    {
+	       ifdef_level--;
+
+#ifdef undef
+	       /* This match needs to be more intelligent before the
+	          message is useful */
+	       if (match_state[ifdef_level].tos >= 0
+		   && bcmp(&ps, &match_state[ifdef_level], sizeof ps))
+		  diag(0, "Syntactically inconsistant #ifdef alternatives.");
+#endif
+	    }
+	    if (bl_around)
+	    {
+	       postfix_blankline_requested++;
+	       n_real_blanklines = 0;
+	    }
+	 }
+	 break;				/* subsequent processing of the
+					   newline character will cause
+					   the line to be printed */
+
+      case comment:			/* we have gotten a / *  this is
+					   a biggie */
+	 if (flushed_nl)
+	 {				/* we should force a broken
+					   line here */
+	    flushed_nl = false;
+	    dump_line();
+	    ps.want_blank = false;	/* dont insert blank at line
+					   start */
+	    force_nl = false;
+	 }
+	 pr_comment();
+	 break;
+      }					/* end of big switch stmt */
+
+      *e_code = '\0';			/* make sure code section is
+					   null terminated */
+      if (type_code != comment && type_code != newline && type_code != preesc)
+	 ps.last_token = type_code;
+   }					/* end of main while (1) loop */
+}
+
+/*
+ * copy input file to backup file if in_name is /blah/blah/blah/file, then
+ * backup file will be ".Bfile" then make the backup file the input and
+ * original input file the output
+ */
+void bakcopy()
+{
+   int             n, bakchn;
+   char            buff[8 * 1024];
+   register char  *p;
+
+   /* construct file name .Bfile */
+   for (p = in_name; *p; p++);		/* skip to end of string */
+   while (p > in_name && *p != '/')	/* find last '/' */
+      p--;
+   if (*p == '/')
+      p++;
+   sprintf(bakfile, "%s.BAK", p);
+   if (strlen(p) >= NAME_SIZE) *bakfile ^= 040;	/* toggle char */
+
+   /* copy in_name to backup file */
+   bakchn = creat(bakfile, 0600);
+   if (bakchn < 0)
+   {
+      fprintf(stderr, "indent: can't create backup file \"%s\"\n", bakfile);
+      exit(1);
+   }
+   while (n = read(fileno(input), buff, sizeof buff))
+      if (write(bakchn, buff, n) != n)
+      {
+	 fprintf(stderr, "indent: error writing backup file \"%s\"\n",
+		 bakfile);
+	 exit(1);
+      }
+   if (n < 0)
+   {
+      fprintf(stderr, "indent: error reading input file \"%s\"\n", in_name);
+      exit(1);
+   }
+   close(bakchn);
+   fclose(input);
+
+   /* re-open backup file as the input file */
+   input = fopen(bakfile, "r");
+   if (input == 0)
+   {
+      fprintf(stderr, "indent: can't re-open backup file\n");
+      exit(1);
+   }
+   /* now the original input file will be the output */
+   output = fopen(in_name, "w");
+   if (output == 0)
+   {
+      fprintf(stderr, "indent: can't create %s\n", in_name);
+      unlink(bakfile);
+      exit(1);
+   }
+}
Index: /trunk/minix/commands/indent/indent.pro
===================================================================
--- /trunk/minix/commands/indent/indent.pro	(revision 9)
+++ /trunk/minix/commands/indent/indent.pro	(revision 9)
@@ -0,0 +1,1 @@
+-bap -bbb -br -ncdb -cli0.5 -di1 -lp -npsl -nfc1 -nip
Index: /trunk/minix/commands/indent/io.c
===================================================================
--- /trunk/minix/commands/indent/io.c	(revision 9)
+++ /trunk/minix/commands/indent/io.c	(revision 9)
@@ -0,0 +1,639 @@
+/**
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1980 The Regents of the University of California.
+ * Copyright (c) 1976 Board of Trustees of the University of Illinois.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley, the University of Illinois,
+ * Urbana, and Sun Microsystems, Inc.  The name of either University
+ * or Sun Microsystems may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define PUBLIC extern
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include "globs.h"
+#include "proto.h"
+
+
+int             comment_open;
+static          paren_target;
+
+void dump_line()
+{					/* dump_line is the routine
+					   that actually effects the
+					   printing of the new source.
+					   It prints the label section,
+					   followed by the code section
+					   with the appropriate nesting
+					   level, followed by any
+					   comments */
+   register int    cur_col, target_col;
+   static          not_first_line;
+
+   if (ps.procname[0])
+   {
+      if (troff)
+      {
+	 if (comment_open)
+	 {
+	    comment_open = 0;
+	    fprintf(output, ".*/\n");
+	 }
+	 fprintf(output, ".Pr \"%s\"\n", ps.procname);
+      }
+      ps.ind_level = 0;
+      ps.procname[0] = 0;
+   }
+   if (s_code == e_code && s_lab == e_lab && s_com == e_com)
+   {
+      if (suppress_blanklines > 0)
+	 suppress_blanklines--;
+      else
+      {
+	 ps.bl_line = true;
+	 n_real_blanklines++;
+      }
+   } else if (!inhibit_formatting)
+   {
+      suppress_blanklines = 0;
+      ps.bl_line = false;
+      if (prefix_blankline_requested && not_first_line)
+	 if (swallow_opt_bl)
+	 {
+	    if (n_real_blanklines == 1)
+	       n_real_blanklines = 0;
+	 } else
+	 {
+	    if (n_real_blanklines == 0)
+	       n_real_blanklines = 1;
+	 }
+      while (--n_real_blanklines >= 0)
+	 putc('\n', output);
+      n_real_blanklines = 0;
+      if (ps.ind_level == 0)
+	 ps.ind_stmt = 0;		/* this is a class A kludge.
+					   dont do additional statement
+					   indentation if we are at
+					   bracket level 0 */
+
+      if (e_lab != s_lab || e_code != s_code)
+	 ++code_lines;			/* keep count of lines with
+					   code */
+
+
+      if (e_lab != s_lab)
+      {					/* print lab, if any */
+	 if (comment_open)
+	 {
+	    comment_open = 0;
+	    fprintf(output, ".*/\n");
+	 }
+	 while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
+	    e_lab--;
+	 cur_col = pad_output(1, label_target());
+	 fprintf(output, "%.*s", (int)(e_lab - s_lab), s_lab);
+	 cur_col = count_spaces(cur_col, s_lab);
+      } else
+	 cur_col = 1;			/* there is no label section */
+
+      ps.pcase = false;
+
+      if (s_code != e_code)
+      {					/* print code section, if any */
+	 register char  *p;
+
+	 if (comment_open)
+	 {
+	    comment_open = 0;
+	    fprintf(output, ".*/\n");
+	 }
+	 target_col = code_target();
+	 {
+	    register        i;
+
+	    for (i = 0; i < ps.p_l_follow; i++)
+	       if (ps.paren_indents[i] >= 0)
+		  ps.paren_indents[i] = -(ps.paren_indents[i] + target_col);
+	 }
+	 cur_col = pad_output(cur_col, target_col);
+	 for (p = s_code; p < e_code; p++)
+	    if (*p == (char) 0200)
+	       fprintf(output, "%d", target_col * 7);
+	    else
+	       putc(*p, output);
+	 cur_col = count_spaces(cur_col, s_code);
+      }
+      if (s_com != e_com)
+	 if (troff)
+	 {
+	    int             all_here = 0;
+	    register char  *p;
+
+	    if (e_com[-1] == '/' && e_com[-2] == '*')
+	       e_com -= 2, all_here++;
+	    while (e_com > s_com && e_com[-1] == ' ')
+	       e_com--;
+	    *e_com = 0;
+	    p = s_com;
+	    while (*p == ' ')
+	       p++;
+	    if (p[0] == '/' && p[1] == '*')
+	       p += 2, all_here++;
+	    else if (p[0] == '*')
+	       p += p[1] == '/' ? 2 : 1;
+	    while (*p == ' ')
+	       p++;
+	    if (*p == 0)
+	       goto inhibit_newline;
+	    if (comment_open < 2 && ps.box_com)
+	    {
+	       comment_open = 0;
+	       fprintf(output, ".*/\n");
+	    }
+	    if (comment_open == 0)
+	    {
+	       if ('a' <= *p && *p <= 'z')
+		  *p = *p + 'A' - 'a';
+	       if (e_com - p < 50 && all_here == 2)
+	       {
+		  register char  *follow = p;
+		  fprintf(output, "\n.nr C! \\w\1");
+		  while (follow < e_com)
+		  {
+		     switch (*follow)
+		     {
+		     case '\n':
+			putc(' ', output);
+		     case 1:
+			break;
+		     case '\\':
+			putc('\\', output);
+		     default:
+			putc(*follow, output);
+		     }
+		     follow++;
+		  }
+		  putc(1, output);
+	       }
+	       fprintf(output, "\n./* %dp %d %dp\n",
+		       ps.com_col * 7,
+		    (s_code != e_code || s_lab != e_lab) - ps.box_com,
+		       target_col * 7);
+	    }
+	    comment_open = 1 + ps.box_com;
+	    while (*p)
+	    {
+	       if (*p == BACKSLASH)
+		  putc(BACKSLASH, output);
+	       putc(*p++, output);
+	    }
+	 } else
+	 {				/* print comment, if any */
+	    register        target = ps.com_col;
+	    register char  *com_st = s_com;
+
+	    target += ps.comment_delta;
+	    while (*com_st == '\t')
+	       com_st++, target += 8;	/* ? */
+	    while (target <= 0)
+	       if (*com_st == ' ')
+		  target++, com_st++;
+	       else if (*com_st == '\t')
+		  target = ((target - 1) & ~7) + 9, com_st++;
+	       else
+		  target = 1;
+	    if (cur_col > target)
+	    {				/* if comment cant fit on this
+					   line, put it on next line */
+	       putc('\n', output);
+	       cur_col = 1;
+	       ++ps.out_lines;
+	    }
+	    while (e_com > com_st && isspace(e_com[-1]))
+	       e_com--;
+	    cur_col = pad_output(cur_col, target);
+	    if (!ps.box_com)
+	    {
+	       if (star_comment_cont && (com_st[1] != '*' || e_com <= com_st + 1))
+		  if (com_st[1] == ' ' && com_st[0] == ' ' && e_com > com_st + 1)
+		     com_st[1] = '*';
+		  else
+		     fwrite(" * ", com_st[0] == '\t' ? 2 : com_st[0] == '*' ? 1 : 3, 1, output);
+	    }
+	    fwrite(com_st, (int)(e_com - com_st), 1, output);
+	    ps.comment_delta = ps.n_comment_delta;
+	    cur_col = count_spaces(cur_col, com_st);
+	    ++ps.com_lines;		/* count lines with comments */
+	 }
+      if (ps.use_ff)
+	 putc('\014', output);
+      else
+	 putc('\n', output);
+inhibit_newline:
+      ++ps.out_lines;
+      if (ps.just_saw_decl == 1 && bl_aft_decl)
+      {
+	 prefix_blankline_requested = 1;
+	 ps.just_saw_decl = 0;
+      } else
+	 prefix_blankline_requested = postfix_blankline_requested;
+      postfix_blankline_requested = 0;
+   }
+   ps.decl_on_line = ps.in_decl;	/* if we are in the middle of a
+					   declaration, remember that
+					   fact for proper comment
+					   indentation */
+   ps.ind_stmt = ps.in_stmt & ~ps.in_decl;	/* next line should be
+						   indented if we have
+						   not completed this
+						   stmt and if we are
+						   not in the middle of
+						   a declaration */
+   ps.use_ff = false;
+   ps.dumped_decl_indent = 0;
+   *(e_lab = s_lab) = '\0';		/* reset buffers */
+   *(e_code = s_code) = '\0';
+   *(e_com = s_com) = '\0';
+   ps.ind_level = ps.i_l_follow;
+   ps.paren_level = ps.p_l_follow;
+   paren_target = -ps.paren_indents[ps.paren_level - 1];
+   not_first_line = 1;
+   return;
+}
+
+int code_target()
+{
+   register        target_col = ps.ind_size * ps.ind_level + 1;
+
+   if (ps.paren_level)
+      if (!lineup_to_parens)
+	 target_col += continuation_indent * ps.paren_level;
+      else
+      {
+	 register        w;
+	 register        t = paren_target;
+
+	 if ((w = count_spaces(t, s_code) - max_col) > 0
+	     && count_spaces(target_col, s_code) <= max_col)
+	 {
+	    t -= w + 1;
+	    if (t > target_col)
+	       target_col = t;
+	 } else
+	    target_col = t;
+      }
+   else if (ps.ind_stmt)
+      target_col += continuation_indent;
+   return target_col;
+}
+
+int label_target()
+{
+   return
+      ps.pcase ? (int) (case_ind * ps.ind_size) + 1
+      : *s_lab == '#' ? 1
+      : ps.ind_size * (ps.ind_level - label_offset) + 1;
+}
+
+
+/*
+ * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
+ *
+ * All rights reserved
+ *
+ *
+ * NAME: fill_buffer
+ *
+ * FUNCTION: Reads one block of input into input_buffer
+ *
+ * HISTORY: initial coding 	November 1976	D A Willcox of CAC 1/7/77 A
+ * Willcox of CAC	Added check for switch back to partly full input
+ * buffer from temporary buffer
+ *
+ */
+
+void
+fill_buffer()
+{					/* this routine reads stuff
+					   from the input */
+   register char  *p;
+   register int    i;
+   register FILE  *f = input;
+
+   if (bp_save != 0)
+   {					/* there is a partly filled
+					   input buffer left */
+      buf_ptr = bp_save;		/* dont read anything, just
+					   switch buffers */
+      buf_end = be_save;
+      bp_save = be_save = 0;
+      if (buf_ptr < buf_end)
+	 return;			/* only return if there is
+					   really something in this
+					   buffer */
+   }
+   for (p = buf_ptr = in_buffer;;)
+   {
+      if ((i = getc(f)) == EOF)
+      {
+	 *p++ = ' ';
+	 *p++ = '\n';
+	 had_eof = true;
+	 break;
+      }
+      *p++ = (char)i;
+      if (i == '\n')
+	 break;
+   }
+   buf_end = p;
+   if (p[-2] == '/' && p[-3] == '*')
+   {
+      if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0)
+	 fill_buffer();			/* flush indent error message */
+      else
+      {
+	 int             com = 0;
+
+	 p = in_buffer;
+	 while (*p == ' ' || *p == '\t')
+	    p++;
+	 if (*p == '/' && p[1] == '*')
+	 {
+	    p += 2;
+	    while (*p == ' ' || *p == '\t')
+	       p++;
+	    if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E'
+		&& p[4] == 'N' && p[5] == 'T')
+	    {
+	       p += 6;
+	       while (*p == ' ' || *p == '\t')
+		  p++;
+	       if (*p == '*')
+		  com = 1;
+	       else if (*p == 'O')
+		  if (*++p == 'N')
+		     p++, com = 1;
+		  else if (*p == 'F' && *++p == 'F')
+		     p++, com = 2;
+	       while (*p == ' ' || *p == '\t')
+		  p++;
+	       if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com)
+	       {
+		  if (s_com != e_com || s_lab != e_lab || s_code != e_code)
+		     dump_line();
+		  if (!(inhibit_formatting = com - 1))
+		  {
+		     n_real_blanklines = 0;
+		     postfix_blankline_requested = 0;
+		     prefix_blankline_requested = 0;
+		     suppress_blanklines = 1;
+		  }
+	       }
+	    }
+	 }
+      }
+   }
+   if (inhibit_formatting)
+   {
+      p = in_buffer;
+      do
+	 putc(*p, output);
+      while (*p++ != '\n');
+   }
+   return;
+}
+
+/*
+ * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
+ *
+ * All rights reserved
+ *
+ *
+ * NAME: pad_output
+ *
+ * FUNCTION: Writes tabs and spaces to move the current column up to the desired
+ * position.
+ *
+ * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf.
+ *
+ * PARAMETERS: current		integer		The current column target
+ * nteger		The desired column
+ *
+ * RETURNS: Integer value of the new column.  (If current >= target, no action
+ * is taken, and current is returned.
+ *
+ * GLOBALS: None
+ *
+ * CALLS: write (sys)
+ *
+ * CALLED BY: dump_line
+ *
+ * HISTORY: initial coding 	November 1976	D A Willcox of CAC
+ *
+ */
+
+int pad_output(current, target)		/* writes tabs and blanks (if
+					   necessary) to get the
+					   current output position up
+					   to the target column */
+   int             current;		/* the current column value */
+   int             target;		/* position we want it at */
+{
+   register int    curr;		/* internal column pointer */
+   register int    tcur;
+
+   if (troff)
+      fprintf(output, "\\h'|%dp'", (target - 1) * 7);
+   else
+   {
+      if (current >= target)
+	 return (current);		/* line is already long enough */
+      curr = current;
+      while ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target)
+      {
+	 putc('\t', output);
+	 curr = tcur;
+      }
+      while (curr++ < target)
+	 putc(' ', output);		/* pad with final blanks */
+   }
+   return (target);
+}
+
+/*
+ * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
+ *
+ * All rights reserved
+ *
+ *
+ * NAME: count_spaces
+ *
+ * FUNCTION: Find out where printing of a given string will leave the current
+ * character position on output.
+ *
+ * ALGORITHM: Run thru input string and add appropriate values to current
+ * position.
+ *
+ * RETURNS: Integer value of position after printing "buffer" starting in column
+ * "current".
+ *
+ * HISTORY: initial coding 	November 1976	D A Willcox of CAC
+ *
+ */
+
+int
+count_spaces(current, buffer)
+/*
+ * this routine figures out where the character position will be after
+ * printing the text in buffer starting at column "current"
+ */
+   int             current;
+   char           *buffer;
+{
+   register char  *buf;			/* used to look thru buffer */
+   register int    cur;			/* current character counter */
+
+   cur = current;
+
+   for (buf = buffer; *buf != '\0'; ++buf)
+   {
+      switch (*buf)
+      {
+
+      case '\n':
+      case 014:			/* form feed */
+	 cur = 1;
+	 break;
+
+      case '\t':
+	 cur = ((cur - 1) & tabmask) + tabsize + 1;
+	 break;
+
+      case '':				/* this is a backspace */
+	 --cur;
+	 break;
+
+      default:
+	 ++cur;
+	 break;
+      }					/* end of switch */
+   }					/* end of for loop */
+   return (cur);
+}
+
+int             found_err;
+void diag(level, msg, a, b)
+int level;
+char *msg;
+int a, b;
+{
+   if (level)
+      found_err = 1;
+   if (output == stdout)
+   {
+      fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no);
+      fprintf(stdout, msg, a, b);
+      fprintf(stdout, " */\n");
+   } else
+   {
+      fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no);
+      fprintf(stderr, msg, a, b);
+      fprintf(stderr, "\n");
+   }
+}
+
+void writefdef(f, nm)
+   register struct fstate *f;
+   int nm;
+{
+   fprintf(output, ".ds f%c %s\n.nr s%c %d\n",
+	   nm, f->font, nm, f->size);
+}
+
+char           *
+chfont(of, nf, s)
+   register struct fstate *of, *nf;
+   char           *s;
+{
+   if (of->font[0] != nf->font[0]
+       || of->font[1] != nf->font[1])
+   {
+      *s++ = '\\';
+      *s++ = 'f';
+      if (nf->font[1])
+      {
+	 *s++ = '(';
+	 *s++ = nf->font[0];
+	 *s++ = nf->font[1];
+      } else
+	 *s++ = nf->font[0];
+   }
+   if (nf->size != of->size)
+   {
+      *s++ = '\\';
+      *s++ = 's';
+      if (nf->size < of->size)
+      {
+	 *s++ = '-';
+	 *s++ = (char)'0' + of->size - nf->size;
+      } else
+      {
+	 *s++ = '+';
+	 *s++ = (char)'0' + nf->size - of->size;
+      }
+   }
+   return s;
+}
+
+
+void parsefont(f, s0)
+   register struct fstate *f;
+   char           *s0;
+{
+   register char  *s = s0;
+   int             sizedelta = 0;
+   memset(f, '\0', sizeof *f);
+   while (*s)
+   {
+      if (isdigit(*s))
+	 f->size = f->size * 10 + *s - '0';
+      else if (isupper(*s))
+	 if (f->font[0])
+	    f->font[1] = *s;
+	 else
+	    f->font[0] = *s;
+      else if (*s == 'c')
+	 f->allcaps = 1;
+      else if (*s == '+')
+	 sizedelta++;
+      else if (*s == '-')
+	 sizedelta--;
+      else
+      {
+	 fprintf(stderr, "indent: bad font specification: %s\n", s0);
+	 exit(1);
+      }
+      s++;
+   }
+   if (f->font[0] == 0)
+      f->font[0] = 'R';
+   if (bodyf.size == 0)
+      bodyf.size = 11;
+   if (f->size == 0)
+      f->size = bodyf.size + sizedelta;
+   else if (sizedelta > 0)
+      f->size += bodyf.size;
+   else
+      f->size = bodyf.size - f->size;
+}
Index: /trunk/minix/commands/indent/lexi.c
===================================================================
--- /trunk/minix/commands/indent/lexi.c	(revision 9)
+++ /trunk/minix/commands/indent/lexi.c	(revision 9)
@@ -0,0 +1,571 @@
+/**
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1980 The Regents of the University of California.
+ * Copyright (c) 1976 Board of Trustees of the University of Illinois.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley, the University of Illinois,
+ * Urbana, and Sun Microsystems, Inc.  The name of either University
+ * or Sun Microsystems may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * Here we have the token scanner for indent.  It scans off one token and
+ * puts it in the global variable "token".  It returns a code, indicating the
+ * type of token scanned.
+ */
+
+#define PUBLIC extern
+#include <ctype.h>
+#include <string.h>
+#include "globs.h"
+#include "codes.h"
+#include "proto.h"
+
+#define alphanum 1
+#define opchar 3
+
+struct templ
+{
+   char           *rwd;
+   int             rwcode;
+};
+
+struct templ    specials[100] =
+{
+   "switch", 1,
+   "case", 2,
+   "break", 0,
+   "struct", 3,
+   "union", 3,
+   "enum", 3,
+   "default", 2,
+   "int", 4,
+   "char", 4,
+   "float", 4,
+   "double", 4,
+   "long", 4,
+   "short", 4,
+   "typedef", 4,
+   "unsigned", 4,
+   "register", 4,
+   "static", 4,
+   "global", 4,
+   "extern", 4,
+   "void", 4,
+   "goto", 0,
+   "return", 0,
+   "if", 5,
+   "while", 5,
+   "for", 5,
+   "else", 6,
+   "do", 6,
+   "sizeof", 7,
+   0, 0
+};
+
+char            chartype[128] =
+{					/* this is used to facilitate
+					   the decision of what type
+					   (alphanumeric, operator)
+					   each character is */
+   0, 0, 0, 0, 0, 0, 0, 0,
+   0, 0, 0, 0, 0, 0, 0, 0,
+   0, 0, 0, 0, 0, 0, 0, 0,
+   0, 0, 0, 0, 0, 0, 0, 0,
+   0, 3, 0, 0, 1, 3, 3, 0,
+   0, 0, 3, 3, 0, 3, 0, 3,
+   1, 1, 1, 1, 1, 1, 1, 1,
+   1, 1, 0, 0, 3, 3, 3, 3,
+   0, 1, 1, 1, 1, 1, 1, 1,
+   1, 1, 1, 1, 1, 1, 1, 1,
+   1, 1, 1, 1, 1, 1, 1, 1,
+   1, 1, 1, 0, 0, 0, 3, 1,
+   0, 1, 1, 1, 1, 1, 1, 1,
+   1, 1, 1, 1, 1, 1, 1, 1,
+   1, 1, 1, 1, 1, 1, 1, 1,
+   1, 1, 1, 0, 3, 0, 3, 0
+};
+
+
+
+
+int
+lexi()
+{
+   register char  *tok;			/* local pointer to next char
+					   in token */
+   int             unary_delim;		/* this is set to 1 if the
+					   current token
+					
+					forces a following operator to
+					   be unary */
+   static int      last_code;		/* the last token type returned */
+   static int      l_struct;		/* set to 1 if the last token
+					   was 'struct' */
+   int             code;		/* internal code to be returned */
+   char            qchar;		/* the delimiter character for
+					   a string */
+
+   tok = token;				/* point to start of place to
+					   save token */
+   unary_delim = false;
+   ps.col_1 = ps.last_nl;		/* tell world that this token
+					   started in column 1 iff the
+					   last thing scanned was nl */
+   ps.last_nl = false;
+
+   while (*buf_ptr == ' ' || *buf_ptr == '\t')
+   {					/* get rid of blanks */
+      ps.col_1 = false;			/* leading blanks imply token
+					   is not in column 1 */
+      if (++buf_ptr >= buf_end)
+	 fill_buffer();
+   }
+
+   /* Scan an alphanumeric token */
+   if (chartype[*buf_ptr] == alphanum || (buf_ptr[0] == '.' && isdigit(buf_ptr[1])))
+   {
+      /* we have a character or number */
+      register char  *j;		/* used for searching thru list
+					   of
+					
+					reserved words */
+      register struct templ *p;
+
+      if (isdigit(*buf_ptr) || (buf_ptr[0] == '.' && isdigit(buf_ptr[1])))
+      {
+	 int             seendot = 0, seenexp = 0;
+	 if (*buf_ptr == '0' &&
+	     (buf_ptr[1] == 'x' || buf_ptr[1] == 'X'))
+	 {
+	    *tok++ = *buf_ptr++;
+	    *tok++ = *buf_ptr++;
+	    while (isxdigit(*buf_ptr))
+	       *tok++ = *buf_ptr++;
+	 } else
+	    while (1)
+	    {
+	       if (*buf_ptr == '.')
+		  if (seendot)
+		     break;
+		  else
+		     seendot++;
+	       *tok++ = *buf_ptr++;
+	       if (!isdigit(*buf_ptr) && *buf_ptr != '.')
+		  if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp)
+		     break;
+		  else
+		  {
+		     seenexp++;
+		     seendot++;
+		     *tok++ = *buf_ptr++;
+		     if (*buf_ptr == '+' || *buf_ptr == '-')
+			*tok++ = *buf_ptr++;
+		  }
+	    }
+	 if (*buf_ptr == 'L' || *buf_ptr == 'l')
+	    *tok++ = *buf_ptr++;
+      } else
+	 while (chartype[*buf_ptr] == alphanum)
+	 {				/* copy it over */
+	    *tok++ = *buf_ptr++;
+	    if (buf_ptr >= buf_end)
+	       fill_buffer();
+	 }
+      *tok++ = '\0';
+      while (*buf_ptr == ' ' || *buf_ptr == '\t')
+      {					/* get rid of blanks */
+	 if (++buf_ptr >= buf_end)
+	    fill_buffer();
+      }
+      ps.its_a_keyword = false;
+      ps.sizeof_keyword = false;
+      if (l_struct)
+      {					/* if last token was 'struct',
+					   then this token should be
+					   treated as a declaration */
+	 l_struct = false;
+	 last_code = ident;
+	 ps.last_u_d = true;
+	 return (decl);
+      }
+      ps.last_u_d = false;		/* Operator after indentifier
+					   is binary */
+      last_code = ident;		/* Remember that this is the
+					   code we will return */
+
+      /* This loop will check if the token is a keyword. */
+      for (p = specials; (j = p->rwd) != 0; p++)
+      {
+	 tok = token;			/* point at scanned token */
+	 if (*j++ != *tok++ || *j++ != *tok++)
+	    continue;			/* This test depends on the
+					   fact that identifiers are
+					   always at least 1 character
+					   long (ie. the first two
+					   bytes of the identifier are
+					   always meaningful) */
+	 if (tok[-1] == 0)
+	    break;			/* If its a one-character
+					   identifier */
+	 while (*tok++ == *j)
+	    if (*j++ == 0)
+	       goto found_keyword;	/* I wish that C had a
+					   multi-level break... */
+      }
+      if (p->rwd)
+      {					/* we have a keyword */
+   found_keyword:
+	 ps.its_a_keyword = true;
+	 ps.last_u_d = true;
+	 switch (p->rwcode)
+	 {
+	 case 1:			/* it is a switch */
+	    return (swstmt);
+	 case 2:			/* a case or default */
+	    return (casestmt);
+
+	 case 3:			/* a "struct" */
+	    if (ps.p_l_follow)
+	       break;			/* inside parens: cast */
+	    l_struct = true;
+
+	    /* Next time around, we will want to know that we have had
+	       a 'struct' */
+	 case 4:			/* one of the declaration
+					   keywords */
+	    if (ps.p_l_follow)
+	    {
+	       ps.cast_mask |= 1 << ps.p_l_follow;
+	       break;			/* inside parens: cast */
+	    }
+	    last_code = decl;
+	    return (decl);
+
+	 case 5:			/* if, while, for */
+	    return (sp_paren);
+
+	 case 6:			/* do, else */
+	    return (sp_nparen);
+
+	 case 7:
+	    ps.sizeof_keyword = true;
+	 default:			/* all others are treated like
+					   any other identifier */
+	    return (ident);
+	 }				/* end of switch */
+      }					/* end of if (found_it) */
+      if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0)
+      {
+	 register char  *tp = buf_ptr;
+	 while (tp < buf_end)
+	    if (*tp++ == ')' && *tp == ';')
+	       goto not_proc;
+	 strncpy(ps.procname, token, sizeof ps.procname - 1);
+	 ps.in_par_decl = 1;
+   not_proc:;
+      }
+      /* The following hack attempts to guess whether or not the
+         current token is in fact a declaration keyword -- one that has
+         been typedefd */
+      if (((*buf_ptr == '*' && buf_ptr[1] != '=') || isalpha(*buf_ptr) || *buf_ptr == '_')
+	  && !ps.p_l_follow
+	  && !ps.block_init
+	  && (ps.last_token == rparen || ps.last_token == semicolon ||
+	      ps.last_token == decl ||
+	      ps.last_token == lbrace || ps.last_token == rbrace))
+      {
+	 ps.its_a_keyword = true;
+	 ps.last_u_d = true;
+	 last_code = decl;
+	 return decl;
+      }
+      if (last_code == decl)		/* if this is a declared
+					   variable, then following
+					   sign is unary */
+	 ps.last_u_d = true;		/* will make "int a -1" work */
+      last_code = ident;
+      return (ident);			/* the ident is not in the list */
+   }					/* end of procesing for alpanum
+					   character */
+   /* l l l Scan a non-alphanumeric token */
+   *tok++ = *buf_ptr;			/* if it is only a
+					   one-character token, it is
+					   moved here */
+   *tok = '\0';
+   if (++buf_ptr >= buf_end)
+      fill_buffer();
+
+   switch (*token)
+   {
+   case '\n':
+      unary_delim = ps.last_u_d;
+      ps.last_nl = true;		/* remember that we just had a
+					   newline */
+      code = (had_eof ? 0 : newline);
+
+      /* if data has been exausted, the newline is a dummy, and we
+         should return code to stop */
+      break;
+
+   case '\'':				/* start of quoted character */
+   case '"':				/* start of string */
+      qchar = *token;
+      if (troff)
+      {
+	 tok[-1] = '`';
+	 if (qchar == '"')
+	    *tok++ = '`';
+	 tok = chfont(&bodyf, &stringf, tok);
+      }
+      do
+      {					/* copy the string */
+	 while (1)
+	 {				/* move one character or
+					   [/<char>]<char> */
+	    if (*buf_ptr == '\n')
+	    {
+	       printf("%d: Unterminated literal\n", line_no);
+	       goto stop_lit;
+	    }
+	    *tok = *buf_ptr++;
+	    if (buf_ptr >= buf_end)
+	       fill_buffer();
+	    if (had_eof || ((tok - token) > (bufsize - 2)))
+	    {
+	       printf("Unterminated literal\n");
+	       ++tok;
+	       goto stop_lit;
+	       /* get outof literal copying loop */
+	    }
+	    if (*tok == BACKSLASH)
+	    {				/* if escape, copy extra char */
+	       if (*buf_ptr == '\n')	/* check for escaped newline */
+		  ++line_no;
+	       if (troff)
+	       {
+		  *++tok = BACKSLASH;
+		  if (*buf_ptr == BACKSLASH)
+		     *++tok = BACKSLASH;
+	       }
+	       *++tok = *buf_ptr++;
+	       ++tok;			/* we must increment this again
+					   because we copied two chars */
+	       if (buf_ptr >= buf_end)
+		  fill_buffer();
+	    } else
+	       break;			/* we copied one character */
+	 }				/* end of while (1) */
+      } while (*tok++ != qchar);
+      if (troff)
+      {
+	 tok = chfont(&stringf, &bodyf, tok - 1);
+	 if (qchar == '"')
+	    *tok++ = '\'';
+      }
+stop_lit:
+      code = ident;
+      break;
+
+   case ('('):
+   case ('['):
+      unary_delim = true;
+      code = lparen;
+      break;
+
+   case (')'):
+   case (']'):
+      code = rparen;
+      break;
+
+   case '#':
+      unary_delim = ps.last_u_d;
+      code = preesc;
+      break;
+
+   case '?':
+      unary_delim = true;
+      code = question;
+      break;
+
+   case (':'):
+      code = colon;
+      unary_delim = true;
+      break;
+
+   case (';'):
+      unary_delim = true;
+      code = semicolon;
+      break;
+
+   case ('{'):
+      unary_delim = true;
+
+      /* if (ps.in_or_st) ps.block_init = 1; */
+      code = ps.block_init ? lparen : lbrace;
+      break;
+
+   case ('}'):
+      unary_delim = true;
+      code = ps.block_init ? rparen : rbrace;
+      break;
+
+   case 014:				/* a form feed */
+      unary_delim = ps.last_u_d;
+      ps.last_nl = true;		/* remember this so we can set
+					   'ps.col_1' right */
+      code = form_feed;
+      break;
+
+   case (','):
+      unary_delim = true;
+      code = comma;
+      break;
+
+   case '.':
+      unary_delim = false;
+      code = period;
+      break;
+
+   case '-':
+   case '+':				/* check for -, +, --, ++ */
+      code = (ps.last_u_d ? unary_op : binary_op);
+      unary_delim = true;
+
+      if (*buf_ptr == token[0])
+      {
+	 /* check for doubled character */
+	 *tok++ = *buf_ptr++;
+	 /* buffer overflow will be checked at end of loop */
+	 if (last_code == ident || last_code == rparen)
+	 {
+	    code = (ps.last_u_d ? unary_op : postop);
+	    /* check for following ++ or -- */
+	    unary_delim = false;
+	 }
+      } else if (*buf_ptr == '=')
+	 /* check for operator += */
+	 *tok++ = *buf_ptr++;
+      else if (*buf_ptr == '>')
+      {
+	 /* check for operator -> */
+	 *tok++ = *buf_ptr++;
+	 if (!ptr_binop)
+	 {
+	    unary_delim = false;
+	    code = unary_op;
+	    ps.want_blank = false;
+	 }
+      }
+      break;				/* buffer overflow will be
+					   checked at end of switch */
+
+   case '=':
+      if (ps.in_or_st)
+	 ps.block_init = 1;
+#ifdef undef
+      if (chartype[*buf_ptr] == opchar)
+      {					/* we have two char assignment */
+	 tok[-1] = *buf_ptr++;
+	 if ((tok[-1] == '<' || tok[-1] == '>') && tok[-1] == *buf_ptr)
+	    *tok++ = *buf_ptr++;
+	 *tok++ = '=';			/* Flip =+ to += */
+	 *tok = 0;
+      }
+#else
+      if (*buf_ptr == '=')
+      {					/* == */
+	 *tok++ = '=';			/* Flip =+ to += */
+	 buf_ptr++;
+	 *tok = 0;
+      }
+#endif
+      code = binary_op;
+      unary_delim = true;
+      break;
+      /* can drop thru!!! */
+
+   case '>':
+   case '<':
+   case '!':				/* ops like <, <<, <=, !=, etc */
+      if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=')
+      {
+	 *tok++ = *buf_ptr;
+	 if (++buf_ptr >= buf_end)
+	    fill_buffer();
+      }
+      if (*buf_ptr == '=')
+	 *tok++ = *buf_ptr++;
+      code = (ps.last_u_d ? unary_op : binary_op);
+      unary_delim = true;
+      break;
+
+   default:
+      if (token[0] == '/' && *buf_ptr == '*')
+      {
+	 /* it is start of comment */
+	 *tok++ = '*';
+
+	 if (++buf_ptr >= buf_end)
+	    fill_buffer();
+
+	 code = comment;
+	 unary_delim = ps.last_u_d;
+	 break;
+      }
+      while (*(tok - 1) == *buf_ptr || *buf_ptr == '=')
+      {
+	 /* handle ||, &&, etc, and also things as in int *****i */
+	 *tok++ = *buf_ptr;
+	 if (++buf_ptr >= buf_end)
+	    fill_buffer();
+      }
+      code = (ps.last_u_d ? unary_op : binary_op);
+      unary_delim = true;
+
+
+   }					/* end of switch */
+   if (code != newline)
+   {
+      l_struct = false;
+      last_code = code;
+   }
+   if (buf_ptr >= buf_end)		/* check for input buffer empty */
+      fill_buffer();
+   ps.last_u_d = unary_delim;
+   *tok = '\0';				/* null terminate the token */
+   return (code);
+}
+
+/*
+ * Add the given keyword to the keyword table, using val as the keyword type
+ */
+void addkey(key, val)
+   char           *key;
+   int val;
+{
+   register struct templ *p = specials;
+   while (p->rwd)
+      if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0)
+	 return;
+      else
+	 p++;
+   if (p >= specials + sizeof specials / sizeof specials[0])
+      return;				/* For now, table overflows are
+					   silently ignored */
+   p->rwd = key;
+   p->rwcode = val;
+   p[1].rwd = 0;
+   p[1].rwcode = 0;
+   return;
+}
Index: /trunk/minix/commands/indent/parse.c
===================================================================
--- /trunk/minix/commands/indent/parse.c	(revision 9)
+++ /trunk/minix/commands/indent/parse.c	(revision 9)
@@ -0,0 +1,320 @@
+/**
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1980 The Regents of the University of California.
+ * Copyright (c) 1976 Board of Trustees of the University of Illinois.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley, the University of Illinois,
+ * Urbana, and Sun Microsystems, Inc.  The name of either University
+ * or Sun Microsystems may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define PUBLIC	extern
+#include "./globs.h"
+#include "./codes.h"
+#include "proto.h"
+
+
+
+
+void parse(tk)
+   int             tk;			/* the code for the construct
+					   scanned */
+{
+   int             i;
+
+#ifdef debug
+   printf("%2d - %s\n", tk, token);
+#endif
+
+   while (ps.p_stack[ps.tos] == ifhead && tk != elselit)
+   {
+      /* true if we have an if without an else */
+      ps.p_stack[ps.tos] = stmt;	/* apply the if(..) stmt ::=
+					   stmt reduction */
+      reduce();				/* see if this allows any
+					   reduction */
+   }
+
+
+   switch (tk)
+   {					/* go on and figure out what to
+					   do with the input */
+
+   case decl:				/* scanned a declaration word */
+      ps.search_brace = btype_2;
+      /* indicate that following brace should be on same line */
+      if (ps.p_stack[ps.tos] != decl)
+      {					/* only put one declaration
+					   onto stack */
+	 break_comma = true;		/* while in declaration,
+					   newline should be forced
+					   after comma */
+	 ps.p_stack[++ps.tos] = decl;
+	 ps.il[ps.tos] = ps.i_l_follow;
+
+	 if (ps.ljust_decl)
+	 {				/* only do if we want left
+					   justified declarations */
+	    ps.ind_level = 0;
+	    for (i = ps.tos - 1; i > 0; --i)
+	       if (ps.p_stack[i] == decl)
+		  ++ps.ind_level;	/* indentation is number of
+					   declaration levels deep we
+					   are */
+	    ps.i_l_follow = ps.ind_level;
+	 }
+      }
+      break;
+
+   case ifstmt:			/* scanned if (...) */
+      if (ps.p_stack[ps.tos] == elsehead && ps.else_if)	/* "else if ..." */
+	 ps.i_l_follow = ps.il[ps.tos];
+   case dolit:				/* 'do' */
+   case forstmt:			/* for (...) */
+      ps.p_stack[++ps.tos] = tk;
+      ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
+      ++ps.i_l_follow;			/* subsequent statements should
+					   be indented 1 */
+      ps.search_brace = btype_2;
+      break;
+
+   case lbrace:			/* scanned { */
+      break_comma = false;		/* don't break comma in an
+					   initial list */
+      if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl
+	  || ps.p_stack[ps.tos] == stmtl)
+	 ++ps.i_l_follow;		/* it is a random, isolated
+					   stmt group or a declaration */
+      else
+      {
+	 if (s_code == e_code)
+	 {
+	    /* only do this if there is nothing on the line */
+	    --ps.ind_level;
+	    /* it is a group as part of a while, for, etc. */
+	    if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1)
+	       --ps.ind_level;
+	    /* for a switch, brace should be two levels out from the
+	       code */
+	 }
+      }
+
+      ps.p_stack[++ps.tos] = lbrace;
+      ps.il[ps.tos] = ps.ind_level;
+      ps.p_stack[++ps.tos] = stmt;
+      /* allow null stmt between braces */
+      ps.il[ps.tos] = ps.i_l_follow;
+      break;
+
+   case whilestmt:			/* scanned while (...) */
+      if (ps.p_stack[ps.tos] == dohead)
+      {
+	 /* it is matched with do stmt */
+	 ps.ind_level = ps.i_l_follow = ps.il[ps.tos];
+	 ps.p_stack[++ps.tos] = whilestmt;
+	 ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
+      } else
+      {					/* it is a while loop */
+	 ps.p_stack[++ps.tos] = whilestmt;
+	 ps.il[ps.tos] = ps.i_l_follow;
+	 ++ps.i_l_follow;
+	 ps.search_brace = btype_2;
+      }
+
+      break;
+
+   case elselit:			/* scanned an else */
+
+      if (ps.p_stack[ps.tos] != ifhead)
+	 diag(1, "Unmatched 'else'");
+      else
+      {
+	 ps.ind_level = ps.il[ps.tos];	/* indentation for else should
+					   be same as for if */
+	 ps.i_l_follow = ps.ind_level + 1;	/* everything following
+						   should be in 1 level */
+	 ps.p_stack[ps.tos] = elsehead;
+	 /* remember if with else */
+	 ps.search_brace = btype_2 | ps.else_if;
+      }
+      break;
+
+   case rbrace:			/* scanned a } */
+      /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
+      if (ps.p_stack[ps.tos - 1] == lbrace)
+      {
+	 ps.ind_level = ps.i_l_follow = ps.il[--ps.tos];
+	 ps.p_stack[ps.tos] = stmt;
+      } else
+	 diag(1, "Stmt nesting error.");
+      break;
+
+   case swstmt:			/* had switch (...) */
+      ps.p_stack[++ps.tos] = swstmt;
+      ps.cstk[ps.tos] = case_ind;
+      /* save current case indent level */
+      ps.il[ps.tos] = ps.i_l_follow;
+      case_ind = ps.i_l_follow + ps.case_indent;	/* cases should be one
+							   level down from
+							   switch */
+      ps.i_l_follow += ps.case_indent + 1;	/* statements should be
+						   two levels in */
+      ps.search_brace = btype_2;
+      break;
+
+   case semicolon:			/* this indicates a simple stmt */
+      break_comma = false;		/* turn off flag to break after
+					   commas in a declaration */
+      ps.p_stack[++ps.tos] = stmt;
+      ps.il[ps.tos] = ps.ind_level;
+      break;
+
+   default:				/* this is an error */
+      diag(1, "Unknown code to parser");
+      return;
+
+
+   }					/* end of switch */
+
+   reduce();				/* see if any reduction can be
+					   done */
+
+#ifdef debug
+   for (i = 1; i <= ps.tos; ++i)
+      printf("(%d %d)", ps.p_stack[i], ps.il[i]);
+   printf("\n");
+#endif
+
+   return;
+}
+
+/*
+ * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
+ *
+ * All rights reserved
+ *
+ *
+ * NAME: reduce
+ *
+ * FUNCTION: Implements the reduce part of the parsing algorithm
+ *
+ * ALGORITHM: The following reductions are done.  Reductions are repeated until
+ * no more are possible.
+ *
+ * Old TOS		New TOS <stmt> <stmt>	<stmtl> <stmtl> <stmt>	<stmtl> do
+ * <stmt>	"dostmt" if <stmt>	"ifstmt" switch <stmt>	<stmt> decl
+ * <stmt>	<stmt> "ifelse" <stmt>	<stmt> for <stmt>	<stmt> while
+ * <stmt>	<stmt> "dostmt" while	<stmt>
+ *
+ * On each reduction, ps.i_l_follow (the indentation for the following line) is
+ * set to the indentation level associated with the old TOS.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNS: Nothing
+ *
+ * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos =
+ *
+ * CALLS: None
+ *
+ * CALLED BY: parse
+ *
+ * HISTORY: initial coding 	November 1976	D A Willcox of CAC
+ *
+ */
+
+/*----------------------------------------------*\
+|   REDUCTION PHASE				    |
+\*----------------------------------------------*/
+void reduce()
+{
+
+   register int    i;
+
+   for (;;)
+   {					/* keep looping until there is
+					   nothing left to reduce */
+
+      switch (ps.p_stack[ps.tos])
+      {
+
+      case stmt:
+	 switch (ps.p_stack[ps.tos - 1])
+	 {
+
+	 case stmt:
+	 case stmtl:
+	    /* stmtl stmt or stmt stmt */
+	    ps.p_stack[--ps.tos] = stmtl;
+	    break;
+
+	 case dolit:			/* <do> <stmt> */
+	    ps.p_stack[--ps.tos] = dohead;
+	    ps.i_l_follow = ps.il[ps.tos];
+	    break;
+
+	 case ifstmt:
+	    /* <if> <stmt> */
+	    ps.p_stack[--ps.tos] = ifhead;
+	    for (i = ps.tos - 1;
+		 (
+		  ps.p_stack[i] != stmt
+		  &&
+		  ps.p_stack[i] != stmtl
+		  &&
+		  ps.p_stack[i] != lbrace
+		  );
+		 --i);
+	    ps.i_l_follow = ps.il[i];
+	    /* for the time being, we will assume that there is no else
+	       on this if, and set the indentation level accordingly.
+	       If an else is scanned, it will be fixed up later */
+	    break;
+
+	 case swstmt:
+	    /* <switch> <stmt> */
+	    case_ind = ps.cstk[ps.tos - 1];
+
+	 case decl:			/* finish of a declaration */
+	 case elsehead:
+	    /* <<if> <stmt> else> <stmt> */
+	 case forstmt:
+	    /* <for> <stmt> */
+	 case whilestmt:
+	    /* <while> <stmt> */
+	    ps.p_stack[--ps.tos] = stmt;
+	    ps.i_l_follow = ps.il[ps.tos];
+	    break;
+
+	 default:			/* <anything else> <stmt> */
+	    return;
+
+	 }				/* end of section for <stmt> on
+					   top of stack */
+	 break;
+
+      case whilestmt:			/* while (...) on top */
+	 if (ps.p_stack[ps.tos - 1] == dohead)
+	 {
+	    /* it is termination of a do while */
+	    ps.p_stack[--ps.tos] = stmt;
+	    break;
+	 } else
+	    return;
+
+      default:				/* anything else on top */
+	 return;
+
+      }
+   }
+}
Index: /trunk/minix/commands/indent/proto.h
===================================================================
--- /trunk/minix/commands/indent/proto.h	(revision 9)
+++ /trunk/minix/commands/indent/proto.h	(revision 9)
@@ -0,0 +1,26 @@
+/* _PROTOTYPE(   void diag, (int level,char *msg, int a, int b)    ); */
+void diag();			/* HACK.  should be varargs */
+
+_PROTOTYPE(   void set_profile, (void )    );
+_PROTOTYPE(   void scan_profile, (FILE *f)    );
+_PROTOTYPE(   int eqin, (char *s1,char *s2)    );
+_PROTOTYPE(   void set_defaults, (void )    );
+_PROTOTYPE(   void set_option, (char *arg)    );
+_PROTOTYPE(   void pr_comment, (void )    );
+_PROTOTYPE(   void main, (int argc,char * *argv)    );
+_PROTOTYPE(   void bakcopy, (void )    );
+_PROTOTYPE(   void dump_line, (void )    );
+_PROTOTYPE(   int code_target, (void )    );
+_PROTOTYPE(   int label_target, (void )    );
+_PROTOTYPE(   void fill_buffer, (void )    );
+_PROTOTYPE(   int pad_output, (int current,int target)    );
+_PROTOTYPE(   int count_spaces, (int current,char *buffer)    );
+_PROTOTYPE(   void writefdef, (struct fstate *f,int nm)    );
+_PROTOTYPE(   char *chfont, (struct fstate *of,struct fstate *nf,char *s)    );
+_PROTOTYPE(   void parsefont, (struct fstate *f,char *s0)    );
+_PROTOTYPE(   int lexi, (void )    );
+_PROTOTYPE(   void addkey, (char *key,int val)    );
+_PROTOTYPE(   void makext, (char *newname,char *newext)    );
+_PROTOTYPE(   void parse, (int tk)    );
+_PROTOTYPE(   void reduce, (void )    );
+
Index: /trunk/minix/commands/m4/Ack.m4
===================================================================
--- /trunk/minix/commands/m4/Ack.m4	(revision 9)
+++ /trunk/minix/commands/m4/Ack.m4	(revision 9)
@@ -0,0 +1,2 @@
+define(ack, `ifelse($1,0,incr($2),$2,0,`ack(DECR($1),1)',
+`ack(DECR($1), ack($1,DECR($2)))')')
Index: /trunk/minix/commands/m4/Hanoi.m4
===================================================================
--- /trunk/minix/commands/m4/Hanoi.m4	(revision 9)
+++ /trunk/minix/commands/m4/Hanoi.m4	(revision 9)
@@ -0,0 +1,7 @@
+define(hanoi, `trans(A, B, C, $1)')
+
+define(moved,`move disk from $1 to $2
+')
+
+define(trans, `ifelse($4,1,`moved($1,$2)',
+	`trans($1,$3,$2,DECR($4))moved($1,$2)trans($3,$2,$1,DECR($4))')')
Index: /trunk/minix/commands/m4/Hash.m4
===================================================================
--- /trunk/minix/commands/m4/Hash.m4	(revision 9)
+++ /trunk/minix/commands/m4/Hash.m4	(revision 9)
@@ -0,0 +1,17 @@
+dnl	This probably will not run on any m4 that cannot
+dnl	handle char constants in eval.
+dnl
+changequote(<,>) define(HASHVAL,99) dnl
+define(hash,<eval(str(substr($1,1),0)%HASHVAL)>) dnl
+define(str,
+	<ifelse($1,",$2,
+		<str(substr(<$1>,1),<eval($2+'substr($1,0,1)')>)>)
+	>) dnl
+define(KEYWORD,<$1,hash($1),>) dnl
+define(TSTART,
+<struct prehash {
+	char *keyword;
+	int   hashval;
+} keytab[] = {>) dnl
+define(TEND,<	"",0
+};>) dnl
Index: /trunk/minix/commands/m4/M4.out
===================================================================
--- /trunk/minix/commands/m4/M4.out	(revision 9)
+++ /trunk/minix/commands/m4/M4.out	(revision 9)
@@ -0,0 +1,462 @@
+#
+# test file for mp (not comprehensive)
+#
+# v7 m4 does not have `decr'.
+#
+
+#
+# include string macros
+#
+
+
+
+
+
+#
+# create some fortrash strings for an even uglier language
+#
+integer TEXT(5)
+data TEXT(1)/LETt/
+data TEXT(2)/LETe/
+data TEXT(3)/LETx/
+data TEXT(4)/LETt/
+
+data TEXT(5)/EOS/
+
+integer DATA(5)
+data DATA(1)/LETd/
+data DATA(2)/LETa/
+data DATA(3)/LETt/
+data DATA(4)/LETa/
+
+data DATA(5)/EOS/
+
+integer BEGIN(6)
+data BEGIN(1)/LETb/
+data BEGIN(2)/LETe/
+data BEGIN(3)/LETg/
+data BEGIN(4)/LETi/
+data BEGIN(5)/LETn/
+
+data BEGIN(6)/EOS/
+
+integer END(4)
+data END(1)/LETe/
+data END(2)/LETn/
+data END(3)/LETd/
+
+data END(4)/EOS/
+
+integer IF(3)
+data IF(1)/LETi/
+data IF(2)/LETf/
+
+data IF(3)/EOS/
+
+integer THEN(5)
+data THEN(1)/LETt/
+data THEN(2)/LETh/
+data THEN(3)/LETe/
+data THEN(4)/LETn/
+
+data THEN(5)/EOS/
+
+integer ELSE(5)
+data ELSE(1)/LETe/
+data ELSE(2)/LETl/
+data ELSE(3)/LETs/
+data ELSE(4)/LETe/
+
+data ELSE(5)/EOS/
+
+integer CASE(5)
+data CASE(1)/LETc/
+data CASE(2)/LETa/
+data CASE(3)/LETs/
+data CASE(4)/LETe/
+
+data CASE(5)/EOS/
+
+integer REPEAT(7)
+data REPEAT(1)/LETr/
+data REPEAT(2)/LETe/
+data REPEAT(3)/LETp/
+data REPEAT(4)/LETe/
+data REPEAT(5)/LETa/
+data REPEAT(6)/LETt/
+
+data REPEAT(7)/EOS/
+
+integer WHILE(6)
+data WHILE(1)/LETw/
+data WHILE(2)/LETh/
+data WHILE(3)/LETi/
+data WHILE(4)/LETl/
+data WHILE(5)/LETe/
+
+data WHILE(6)/EOS/
+
+integer DEFAULT(8)
+data DEFAULT(1)/LETd/
+data DEFAULT(2)/LETe/
+data DEFAULT(3)/LETf/
+data DEFAULT(4)/LETa/
+data DEFAULT(5)/LETu/
+data DEFAULT(6)/LETl/
+data DEFAULT(7)/LETt/
+
+data DEFAULT(8)/EOS/
+
+integer UNTIL(6)
+data UNTIL(1)/LETu/
+data UNTIL(2)/LETn/
+data UNTIL(3)/LETt/
+data UNTIL(4)/LETi/
+data UNTIL(5)/LETl/
+
+data UNTIL(6)/EOS/
+
+integer FUNCTION(9)
+data FUNCTION(1)/LETf/
+data FUNCTION(2)/LETu/
+data FUNCTION(3)/LETn/
+data FUNCTION(4)/LETc/
+data FUNCTION(5)/LETt/
+data FUNCTION(6)/LETi/
+data FUNCTION(7)/LETo/
+data FUNCTION(8)/LETn/
+
+data FUNCTION(9)/EOS/
+
+integer PROCEDURE(10)
+data PROCEDURE(1)/LETp/
+data PROCEDURE(2)/LETr/
+data PROCEDURE(3)/LETo/
+data PROCEDURE(4)/LETc/
+data PROCEDURE(5)/LETe/
+data PROCEDURE(6)/LETd/
+data PROCEDURE(7)/LETu/
+data PROCEDURE(8)/LETr/
+data PROCEDURE(9)/LETe/
+
+data PROCEDURE(10)/EOS/
+
+integer EXTERNAL(9)
+data EXTERNAL(1)/LETe/
+data EXTERNAL(2)/LETx/
+data EXTERNAL(3)/LETt/
+data EXTERNAL(4)/LETe/
+data EXTERNAL(5)/LETr/
+data EXTERNAL(6)/LETn/
+data EXTERNAL(7)/LETa/
+data EXTERNAL(8)/LETl/
+
+data EXTERNAL(9)/EOS/
+
+integer FORWARD(8)
+data FORWARD(1)/LETf/
+data FORWARD(2)/LETo/
+data FORWARD(3)/LETr/
+data FORWARD(4)/LETw/
+data FORWARD(5)/LETa/
+data FORWARD(6)/LETr/
+data FORWARD(7)/LETd/
+
+data FORWARD(8)/EOS/
+
+integer TYPE(5)
+data TYPE(1)/LETt/
+data TYPE(2)/LETy/
+data TYPE(3)/LETp/
+data TYPE(4)/LETe/
+
+data TYPE(5)/EOS/
+
+integer VAR(4)
+data VAR(1)/LETv/
+data VAR(2)/LETa/
+data VAR(3)/LETr/
+
+data VAR(4)/EOS/
+
+integer CONST(6)
+data CONST(1)/LETc/
+data CONST(2)/LETo/
+data CONST(3)/LETn/
+data CONST(4)/LETs/
+data CONST(5)/LETt/
+
+data CONST(6)/EOS/
+
+integer PROGRAM(8)
+data PROGRAM(1)/LETp/
+data PROGRAM(2)/LETr/
+data PROGRAM(3)/LETo/
+data PROGRAM(4)/LETg/
+data PROGRAM(5)/LETr/
+data PROGRAM(6)/LETa/
+data PROGRAM(7)/LETm/
+
+data PROGRAM(8)/EOS/
+
+integer INPUT(6)
+data INPUT(1)/LETi/
+data INPUT(2)/LETn/
+data INPUT(3)/LETp/
+data INPUT(4)/LETu/
+data INPUT(5)/LETt/
+
+data INPUT(6)/EOS/
+
+integer OUTPUT(7)
+data OUTPUT(1)/LETo/
+data OUTPUT(2)/LETu/
+data OUTPUT(3)/LETt/
+data OUTPUT(4)/LETp/
+data OUTPUT(5)/LETu/
+data OUTPUT(6)/LETt/
+
+data OUTPUT(7)/EOS/
+
+#
+
+
+defined
+#
+# v7 m4 does this wrong. The right output is
+#      this is A vEry lon sEntEnCE
+# see m4 documentation for translit.
+#
+this is A vEry lon sEntEnCE
+#
+# include towers-of-hanoi
+#
+
+
+
+
+
+
+#
+# some reasonable set of disks
+#
+move disk from A to C
+move disk from A to B
+move disk from C to B
+move disk from A to C
+move disk from B to A
+move disk from B to C
+move disk from A to C
+move disk from A to B
+move disk from C to B
+move disk from C to A
+move disk from B to A
+move disk from C to B
+move disk from A to C
+move disk from A to B
+move disk from C to B
+move disk from A to C
+move disk from B to A
+move disk from B to C
+move disk from A to C
+move disk from B to A
+move disk from C to B
+move disk from C to A
+move disk from B to A
+move disk from B to C
+move disk from A to C
+move disk from A to B
+move disk from C to B
+move disk from A to C
+move disk from B to A
+move disk from B to C
+move disk from A to C
+move disk from A to B
+move disk from C to B
+move disk from C to A
+move disk from B to A
+move disk from C to B
+move disk from A to C
+move disk from A to B
+move disk from C to B
+move disk from C to A
+move disk from B to A
+move disk from B to C
+move disk from A to C
+move disk from B to A
+move disk from C to B
+move disk from C to A
+move disk from B to A
+move disk from C to B
+move disk from A to C
+move disk from A to B
+move disk from C to B
+move disk from A to C
+move disk from B to A
+move disk from B to C
+move disk from A to C
+move disk from A to B
+move disk from C to B
+move disk from C to A
+move disk from B to A
+move disk from C to B
+move disk from A to C
+move disk from A to B
+move disk from C to B
+
+#
+# include ackermann's function
+#
+
+
+#
+# something like (3,3) will blow away un*x m4.
+#
+9
+#
+# include a square_root function for fixed nums
+#
+
+
+
+#
+# some square roots.
+#
+3
+10
+negative-square-root
+146
+#
+# some textual material for enjoyment.
+#
+[taken from the 'Clemson University Computer Newsletter',
+ September 1981, pp. 6-7]
+
+I am a wizard in the magical Kingdom of Transformation and I
+slay dragons for a living.  Actually, I am a systems programmer.
+One of the problems with systems programming is explaining to
+non-computer enthusiasts what that is.  All of the terms I use to
+describe my job are totally meaningless to them.  Usually my response
+to questions about my work is to say as little as possible.  For
+instance, if someone asks what happened at work this week, I say
+"Nothing much" and then I change the subject.
+
+With the assistance of my brother, a mechanical engineer, I have devised
+an analogy that everyone can understand.  The analogy describes the
+"Kingdom of Transformation" where travelers wander and are magically
+transformed.  This kingdom is the computer and the travelers are information.
+The purpose of the computer is to change information to a more meaningful
+forma.  The law of conservation applies here:  The computer never creates
+and never intentionally destroys data.  With no further ado, let us travel
+to the Kingdom of Transformation:
+
+In a land far, far away, there is a magical kingdom called the Kingdom of
+Transformation.  A king rules over this land and employs a Council of
+Wizardry.  The main purpose of this kingdom is to provide a way for
+neighboring kingdoms to transform citizens into more useful citizens.  This
+is done by allowing the citizens to enter the kingdom at one of its ports
+and to travel any of the many routes in the kingdom.  They are magically
+transformed along the way.  The income of the Kingdom of Transformation
+comes from the many toll roads within its boundaries.
+
+The Kingdom of Transformation was created when several kingdoms got
+together and discovered a mutual need for new talents and abilities for
+citizens.  They employed CTK, Inc. (Creators of Transformation, Inc.) to
+create this kingdom.  CTK designed the country, its transportation routes,
+and its laws of transformation, and created the major highway system.
+
+Hazards
+=======
+
+Because magic is not truly controllable, CTK invariably, but unknowingly,
+creates dragons.  Dragons are huge fire-breathing beasts which sometimes
+injure or kill travelers.  Fortunately, they do not travel, but always
+remain near their den.
+
+Other hazards also exist which are potentially harmful.  As the roads
+become older and more weatherbeaten, pot-holes will develop, trees will
+fall on travelers, etc.  CTK maintenance men are called to fix these
+problems.
+
+Wizards
+=======
+
+The wizards play a major role in creating and maintaining the kingdom but
+get little credit for their work because it is performed secretly.  The
+wizards do not wan the workers or travelers to learn their incantations
+because many laws would be broken and chaos would result.
+
+CTK's grand design is always general enough to be applicable in many
+different situations.  As a result, it is often difficult to use.  The
+first duty of the wizards is to tailor the transformation laws so as to be
+more beneficial and easier to use in their particular environment.
+
+After creation of the kingdom, a major duty of the wizards is to search for
+and kill dragons.  If travelers do not return on time or if they return
+injured, the ruler of the country contacts the wizards.  If the wizards
+determine that the injury or death occurred due to the traveler's
+negligence, they provide the traveler's country with additional warnings.
+If not, they must determine if the cause was a road hazard or a dragon.  If
+the suspect a road hazard, they call in a CTK maintenance man to locate the
+hazard and to eliminate it, as in repairing the pothole in the road.  If
+they think that cause was a dragon, then they must find and slay it.
+
+The most difficult part of eliminating a dragon is finding it.  Sometimes
+the wizard magically knows where the dragon's lair it, but often the wizard
+must send another traveler along the same route and watch to see where he
+disappears.  This sounds like a failsafe method for finding dragons (and a
+suicide mission for thr traveler) but the second traveler does not always
+disappear.  Some dragons eat any traveler who comes too close; others are
+very picky.
+
+The wizards may call in CTK who designed the highway system and
+transformation laws to help devise a way to locate the dragon.  CTK also
+helps provide the right spell or incantation to slay the dragon. (There is
+no general spell to slay dragons; each dragon must be eliminated with a
+different spell.)
+
+Because neither CTK nor wizards are perfect, spells to not always work
+correctly.  At best, nothing happens when the wrong spell is uttered.  At
+worst, the dragon becomes a much larger dragon or multiplies into several
+smaller ones.  In either case, new spells must be found.
+
+If all existing dragons are quiet (i.e. have eaten sufficiently), wizards
+have time to do other things.  They hide in castles and practice spells and
+incatations.  They also devise shortcuts for travelers and new laws of
+transformation.
+
+Changes in the Kingdom
+======================
+
+As new transformation kingdoms are created and old ones are maintained,
+CTK, Inc. is constantly learning new things.  It learns ways to avoid
+creating some of the dragons that they have previously created.  It also
+discovers new and better laws of transformation.  As a result, CTK will
+periodically create a new grand design which is far better than the old.
+The wizards determine when is a good time to implement this new design.
+This is when the tourist season is slow or when no important travelers
+(VIPs) are to arrive.  The kingdom must be closed for the actual
+implementation and is leter reopened as a new and better place to go.
+
+A final question you might ask is what happens when the number of tourists
+becomes too great for the kingdom to handle in a reasonable period of time
+(i.e., the tourist lines at the ports are too long).  The Kingdom of
+Transformation has three options: (1) shorten the paths that a tourist must
+travel, or (2) convince CTK to develop a faster breed of horses so that the
+travelers can finish sooner, or (3) annex more territories so that the
+kingdom can handle more travelers.
+
+Thus ends the story of the Kingdom of Transformation.  I hope this has
+explained my job to you:  I slay dragons for a living.
+
+#
+#should do an automatic undivert..
+#
+
+diversion #1
+
+diversion #2
+
+diversion #3
+
+diversion #4
Index: /trunk/minix/commands/m4/Makefile
===================================================================
--- /trunk/minix/commands/m4/Makefile	(revision 9)
+++ /trunk/minix/commands/m4/Makefile	(revision 9)
@@ -0,0 +1,27 @@
+# Makefile for M4
+
+#	-DEXTENDED	#if you like to get paste & spaste macros.
+#	-DVOID 		#if your C compiler does NOT support void.
+#	-DGETOPT	#if you STILL do not have getopt in your library.
+#	-DDUFFCP	#if you do not have fast memcpy in your library.
+#
+
+CFLAGS = -DEXTENDED -O -D_POSIX_SOURCE -D_MINIX
+CC = exec cc
+
+OBJ =  main.o eval.o serv.o look.o misc.o expr.o
+INCL =  mdef.h extr.h patchlevel.h
+
+all:	m4
+
+m4: $(OBJ) $(INCL)
+	cc -i -o m4 $(OBJ)
+	install -S 4kw m4
+
+install:	/usr/bin/m4
+
+/usr/bin/m4:	m4
+	install -cs -o bin m4 $@
+
+clean:	
+	rm -f *.o m4 core *bak
Index: /trunk/minix/commands/m4/READ_ME
===================================================================
--- /trunk/minix/commands/m4/READ_ME	(revision 9)
+++ /trunk/minix/commands/m4/READ_ME	(revision 9)
@@ -0,0 +1,32 @@
+This code *is* PD. You (public) have all the rights to the code.  [But
+this also means you (singular) do not have any *extra* rights to the code,
+hence it is impossible for you to restrict the use and distribution of
+this code (original) in any way.]
+
+Dedication:
+
+This posting is a dedication to an old 750 that started out running 4.1BSD
+and had 1.5 meg, 1 dz11, and 2 Rk07 drives.  It was named yetti [sic] by
+accident, and was managed by the author until its retirement two years
+ago. [the name yetti now identifies a different machine]
+
+If you have any important fixes and/or speed improvements, I am much
+interested. I am also interested in hearing about any unique applica-
+tions of M4. I am NOT interested in gratuitous hacks or "neat"
+kitchen-sink features. 
+
+Author:
+	Usenet: uunet!utai!yunexus!oz || oz@nexus.yorku.ca
+	Bitnet: oz@yulibra.BITNET
+	Phonet: [416] 736-5257 x 3976
+
+
+enjoy.	oz
+
+Testing: 
+
+This directory contains a test file called test.m4.  To use it, type
+
+	m4 <Test.m4 >out
+
+The output file, out, should be identical to M4.out
Index: /trunk/minix/commands/m4/Sqroot.m4
===================================================================
--- /trunk/minix/commands/m4/Sqroot.m4	(revision 9)
+++ /trunk/minix/commands/m4/Sqroot.m4	(revision 9)
@@ -0,0 +1,7 @@
+define(square_root, 
+	`ifelse(eval($1<0),1,negative-square-root,
+			     `square_root_aux($1, 1, eval(($1+1)/2))')')
+define(square_root_aux,
+	`ifelse($3, $2, $3,
+		$3, eval($1/$2), $3,
+		`square_root_aux($1, $3, eval(($3+($1/$3))/2))')')
Index: /trunk/minix/commands/m4/String.m4
===================================================================
--- /trunk/minix/commands/m4/String.m4	(revision 9)
+++ /trunk/minix/commands/m4/String.m4	(revision 9)
@@ -0,0 +1,8 @@
+
+define(string,`integer $1(len(substr($2,1)))
+str($1,substr($2,1),0)
+data $1(len(substr($2,1)))/EOS/
+')
+
+define(str,`ifelse($2,",,data $1(incr($3))/`LET'substr($2,0,1)/
+`str($1,substr($2,1),incr($3))')')
Index: /trunk/minix/commands/m4/Test.m4
===================================================================
--- /trunk/minix/commands/m4/Test.m4	(revision 9)
+++ /trunk/minix/commands/m4/Test.m4	(revision 9)
@@ -0,0 +1,206 @@
+#
+# test file for mp (not comprehensive)
+#
+# v7 m4 does not have `decr'.
+#
+define(DECR,`eval($1-1)')
+#
+# include string macros
+#
+include(String.m4)
+#
+# create some fortrash strings for an even uglier language
+#
+string(TEXT, "text")
+string(DATA, "data")
+string(BEGIN, "begin")
+string(END, "end")
+string(IF, "if")
+string(THEN, "then")
+string(ELSE, "else")
+string(CASE, "case")
+string(REPEAT, "repeat")
+string(WHILE, "while")
+string(DEFAULT, "default")
+string(UNTIL, "until")
+string(FUNCTION, "function")
+string(PROCEDURE, "procedure")
+string(EXTERNAL, "external")
+string(FORWARD, "forward")
+string(TYPE, "type")
+string(VAR, "var")
+string(CONST, "const")
+string(PROGRAM, "program")
+string(INPUT, "input")
+string(OUTPUT, "output")
+#
+divert(2)
+diversion #1
+divert(3)
+diversion #2
+divert(4)
+diversion #3
+divert(5)
+diversion #4
+divert(0)
+define(abc,xxx)
+ifdef(`abc',defined,undefined)
+#
+# v7 m4 does this wrong. The right output is
+#      this is A vEry lon sEntEnCE
+# see m4 documentation for translit.
+#
+translit(`this is a very long sentence', abcdefg, ABCDEF)
+#
+# include towers-of-hanoi
+#
+include(Hanoi.m4)
+#
+# some reasonable set of disks
+#
+hanoi(6)
+#
+# include ackermann's function
+#
+include(Ack.m4)
+#
+# something like (3,3) will blow away un*x m4.
+#
+ack(2,3)
+#
+# include a square_root function for fixed nums
+#
+include(Sqroot.m4)
+#
+# some square roots.
+#
+square_root(15)
+square_root(100)
+square_root(-4)
+square_root(21372)
+#
+# some textual material for enjoyment.
+#
+[taken from the 'Clemson University Computer Newsletter',
+ September 1981, pp. 6-7]
+
+I am a wizard in the magical Kingdom of Transformation and I
+slay dragons for a living.  Actually, I am a systems programmer.
+One of the problems with systems programming is explaining to
+non-computer enthusiasts what that is.  All of the terms I use to
+describe my job are totally meaningless to them.  Usually my response
+to questions about my work is to say as little as possible.  For
+instance, if someone asks what happened at work this week, I say
+"Nothing much" and then I change the subject.
+
+With the assistance of my brother, a mechanical engineer, I have devised
+an analogy that everyone can understand.  The analogy describes the
+"Kingdom of Transformation" where travelers wander and are magically
+transformed.  This kingdom is the computer and the travelers are information.
+The purpose of the computer is to change information to a more meaningful
+forma.  The law of conservation applies here:  The computer never creates
+and never intentionally destroys data.  With no further ado, let us travel
+to the Kingdom of Transformation:
+
+In a land far, far away, there is a magical kingdom called the Kingdom of
+Transformation.  A king rules over this land and employs a Council of
+Wizardry.  The main purpose of this kingdom is to provide a way for
+neighboring kingdoms to transform citizens into more useful citizens.  This
+is done by allowing the citizens to enter the kingdom at one of its ports
+and to travel any of the many routes in the kingdom.  They are magically
+transformed along the way.  The income of the Kingdom of Transformation
+comes from the many toll roads within its boundaries.
+
+The Kingdom of Transformation was created when several kingdoms got
+together and discovered a mutual need for new talents and abilities for
+citizens.  They employed CTK, Inc. (Creators of Transformation, Inc.) to
+create this kingdom.  CTK designed the country, its transportation routes,
+and its laws of transformation, and created the major highway system.
+
+Hazards
+=======
+
+Because magic is not truly controllable, CTK invariably, but unknowingly,
+creates dragons.  Dragons are huge fire-breathing beasts which sometimes
+injure or kill travelers.  Fortunately, they do not travel, but always
+remain near their den.
+
+Other hazards also exist which are potentially harmful.  As the roads
+become older and more weatherbeaten, pot-holes will develop, trees will
+fall on travelers, etc.  CTK maintenance men are called to fix these
+problems.
+
+Wizards
+=======
+
+The wizards play a major role in creating and maintaining the kingdom but
+get little credit for their work because it is performed secretly.  The
+wizards do not wan the workers or travelers to learn their incantations
+because many laws would be broken and chaos would result.
+
+CTK's grand design is always general enough to be applicable in many
+different situations.  As a result, it is often difficult to use.  The
+first duty of the wizards is to tailor the transformation laws so as to be
+more beneficial and easier to use in their particular environment.
+
+After creation of the kingdom, a major duty of the wizards is to search for
+and kill dragons.  If travelers do not return on time or if they return
+injured, the ruler of the country contacts the wizards.  If the wizards
+determine that the injury or death occurred due to the traveler's
+negligence, they provide the traveler's country with additional warnings.
+If not, they must determine if the cause was a road hazard or a dragon.  If
+the suspect a road hazard, they call in a CTK maintenance man to locate the
+hazard and to eliminate it, as in repairing the pothole in the road.  If
+they think that cause was a dragon, then they must find and slay it.
+
+The most difficult part of eliminating a dragon is finding it.  Sometimes
+the wizard magically knows where the dragon's lair it, but often the wizard
+must send another traveler along the same route and watch to see where he
+disappears.  This sounds like a failsafe method for finding dragons (and a
+suicide mission for thr traveler) but the second traveler does not always
+disappear.  Some dragons eat any traveler who comes too close; others are
+very picky.
+
+The wizards may call in CTK who designed the highway system and
+transformation laws to help devise a way to locate the dragon.  CTK also
+helps provide the right spell or incantation to slay the dragon. (There is
+no general spell to slay dragons; each dragon must be eliminated with a
+different spell.)
+
+Because neither CTK nor wizards are perfect, spells to not always work
+correctly.  At best, nothing happens when the wrong spell is uttered.  At
+worst, the dragon becomes a much larger dragon or multiplies into several
+smaller ones.  In either case, new spells must be found.
+
+If all existing dragons are quiet (i.e. have eaten sufficiently), wizards
+have time to do other things.  They hide in castles and practice spells and
+incatations.  They also devise shortcuts for travelers and new laws of
+transformation.
+
+Changes in the Kingdom
+======================
+
+As new transformation kingdoms are created and old ones are maintained,
+CTK, Inc. is constantly learning new things.  It learns ways to avoid
+creating some of the dragons that they have previously created.  It also
+discovers new and better laws of transformation.  As a result, CTK will
+periodically create a new grand design which is far better than the old.
+The wizards determine when is a good time to implement this new design.
+This is when the tourist season is slow or when no important travelers
+(VIPs) are to arrive.  The kingdom must be closed for the actual
+implementation and is leter reopened as a new and better place to go.
+
+A final question you might ask is what happens when the number of tourists
+becomes too great for the kingdom to handle in a reasonable period of time
+(i.e., the tourist lines at the ports are too long).  The Kingdom of
+Transformation has three options: (1) shorten the paths that a tourist must
+travel, or (2) convince CTK to develop a faster breed of horses so that the
+travelers can finish sooner, or (3) annex more territories so that the
+kingdom can handle more travelers.
+
+Thus ends the story of the Kingdom of Transformation.  I hope this has
+explained my job to you:  I slay dragons for a living.
+
+#
+#should do an automatic undivert..
+#
Index: /trunk/minix/commands/m4/build
===================================================================
--- /trunk/minix/commands/m4/build	(revision 9)
+++ /trunk/minix/commands/m4/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/m4/eval.c
===================================================================
--- /trunk/minix/commands/m4/eval.c	(revision 9)
+++ /trunk/minix/commands/m4/eval.c	(revision 9)
@@ -0,0 +1,331 @@
+/*
+ * eval.c
+ * Facility: m4 macro processor
+ * by: oz
+ */
+
+#include "mdef.h"
+#include "extr.h"
+
+/*
+ * eval - evaluate built-in macros.
+ *	  argc - number of elements in argv.
+ *	  argv - element vector :
+ *			argv[0] = definition of a user
+ *				  macro or nil if built-in.
+ *			argv[1] = name of the macro or
+ *				  built-in.
+ *			argv[2] = parameters to user-defined
+ *			   .	  macro or built-in.
+ *			   .
+ *
+ * Note that the minimum value for argc is 3. A call in the form
+ * of macro-or-builtin() will result in:
+ *			argv[0] = nullstr
+ *			argv[1] = macro-or-builtin
+ *			argv[2] = nullstr
+ *
+ */
+
+void eval (argv, argc, td)
+register char *argv[];
+register int argc;
+register int  td;
+{
+	register int c, n;
+	static int sysval;
+
+#ifdef DEBUG
+	printf("argc = %d\n", argc);
+	for (n = 0; n < argc; n++)
+		printf("argv[%d] = %s\n", n, argv[n]);
+#endif
+	/*
+	 * if argc == 3 and argv[2] is null,
+	 * then we have macro-or-builtin() type call.
+	 * We adjust argc to avoid further checking..
+	 *
+	 */
+	if (argc == 3 && !*(argv[2]))
+		argc--;
+
+	switch (td & ~STATIC) {
+
+	case DEFITYPE:
+		if (argc > 2)
+			dodefine(argv[2], (argc > 3) ? argv[3] : null);
+		break;
+
+	case PUSDTYPE:
+		if (argc > 2)
+			dopushdef(argv[2], (argc > 3) ? argv[3] : null);
+		break;
+
+	case DUMPTYPE:
+		dodump(argv, argc);
+		break;
+
+	case EXPRTYPE:
+		/*
+		 * doexpr - evaluate arithmetic expression
+		 *
+		 */
+		if (argc > 2)
+			pbnum(expr(argv[2]));
+		break;
+
+	case IFELTYPE:
+		if (argc > 4)
+			doifelse(argv, argc);
+		break;
+
+	case IFDFTYPE:
+		/*
+		 * doifdef - select one of two alternatives based
+		 *	     on the existence of another definition
+		 */
+		if (argc > 3) {
+			if (lookup(argv[2]) != nil)
+				pbstr(argv[3]);
+			else if (argc > 4)
+				pbstr(argv[4]);
+		}
+		break;
+
+	case LENGTYPE:
+		/*
+		 * dolen - find the length of the argument
+		 *
+		 */
+		if (argc > 2)
+			pbnum((argc > 2) ? strlen(argv[2]) : 0);
+		break;
+
+	case INCRTYPE:
+		/*
+		 * doincr - increment the value of the argument
+		 *
+		 */
+		if (argc > 2)
+			pbnum(atoi(argv[2]) + 1);
+		break;
+
+	case DECRTYPE:
+		/*
+		 * dodecr - decrement the value of the argument
+		 *
+		 */
+		if (argc > 2)
+			pbnum(atoi(argv[2]) - 1);
+		break;
+
+#if unix || vms
+
+	case SYSCTYPE:
+		/*
+		 * dosys - execute system command
+		 *
+		 */
+		if (argc > 2)
+			sysval = system(argv[2]);
+		break;
+
+	case SYSVTYPE:
+		/*
+		 * dosysval - return value of the last system call.
+		 *
+		 */
+		pbnum(sysval);
+		break;
+#endif
+
+	case INCLTYPE:
+		if (argc > 2)
+			if (!doincl(argv[2])) {
+				fprintf(stderr,"m4: %s: ",argv[2]);
+				error("cannot open for read.");
+			}
+		break;
+
+	case SINCTYPE:
+		if (argc > 2)
+			(void) doincl(argv[2]);
+		break;
+#ifdef EXTENDED
+	case PASTTYPE:
+		if (argc > 2)
+			if (!dopaste(argv[2])) {
+				fprintf(stderr,"m4: %s: ",argv[2]);
+				error("cannot open for read.");
+			}
+		break;
+
+	case SPASTYPE:
+		if (argc > 2)
+			(void) dopaste(argv[2]);
+		break;
+#endif
+	case CHNQTYPE:
+		dochq(argv, argc);
+		break;
+
+	case CHNCTYPE:
+		dochc(argv, argc);
+		break;
+
+	case SUBSTYPE:
+		/*
+		 * dosub - select substring
+		 *
+		 */
+		if (argc > 3)
+			dosub(argv,argc);
+		break;
+
+	case SHIFTYPE:
+		/*
+		 * doshift - push back all arguments except the
+		 *	     first one (i.e. skip argv[2])
+		 */
+		if (argc > 3) {
+			for (n = argc-1; n > 3; n--) {
+				putback(rquote);
+				pbstr(argv[n]);
+				putback(lquote);
+				putback(',');
+			}
+			putback(rquote);
+			pbstr(argv[3]);
+			putback(lquote);
+		}
+		break;
+
+	case DIVRTYPE:
+		if (argc > 2 && (n = atoi(argv[2])) != 0)
+			dodiv(n);
+		else {
+			active = stdout;
+			oindex = 0;
+		}
+		break;
+
+	case UNDVTYPE:
+		doundiv(argv, argc);
+		break;
+
+	case DIVNTYPE:
+		/*
+		 * dodivnum - return the number of current
+		 * output diversion
+		 *
+		 */
+		pbnum(oindex);
+		break;
+
+	case UNDFTYPE:
+		/*
+		 * doundefine - undefine a previously defined
+		 *		macro(s) or m4 keyword(s).
+		 */
+		if (argc > 2)
+			for (n = 2; n < argc; n++)
+				remhash(argv[n], ALL);
+		break;
+
+	case POPDTYPE:
+		/*
+		 * dopopdef - remove the topmost definitions of
+		 *	      macro(s) or m4 keyword(s).
+		 */
+		if (argc > 2)
+			for (n = 2; n < argc; n++)
+				remhash(argv[n], TOP);
+		break;
+
+	case MKTMTYPE:
+		/*
+		 * dotemp - create a temporary file
+		 *
+		 */
+		if (argc > 2)
+			pbstr(mktemp(argv[2]));
+		break;
+
+	case TRNLTYPE:
+		/*
+		 * dotranslit - replace all characters in the
+		 *		source string that appears in
+		 *		the "from" string with the corresponding
+		 *		characters in the "to" string.
+		 *
+		 */
+		if (argc > 3) {
+			char temp[MAXTOK];
+			if (argc > 4)
+				map(temp, argv[2], argv[3], argv[4]);
+			else
+				map(temp, argv[2], argv[3], null);
+			pbstr(temp);
+		}
+		else
+		    if (argc > 2)
+			pbstr(argv[2]);
+		break;
+
+	case INDXTYPE:
+		/*
+		 * doindex - find the index of the second argument
+		 *	     string in the first argument string.
+		 *	     -1 if not present.
+		 */
+		pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
+		break;
+
+	case ERRPTYPE:
+		/*
+		 * doerrp - print the arguments to stderr file
+		 *
+		 */
+		if (argc > 2) {
+			for (n = 2; n < argc; n++)
+				fprintf(stderr,"%s ", argv[n]);
+			fprintf(stderr, "\n");
+		}
+		break;
+
+	case DNLNTYPE:
+		/*
+		 * dodnl - eat-up-to and including newline
+		 *
+		 */
+		while ((c = gpbc()) != '\n' && c != EOF)
+			;
+		break;
+
+	case M4WRTYPE:
+		/*
+		 * dom4wrap - set up for wrap-up/wind-down activity
+		 *
+		 */
+		m4wraps = (argc > 2) ? strsave(argv[2]) : null;
+		break;
+
+	case EXITTYPE:
+		/*
+		 * doexit - immediate exit from m4.
+		 *
+		 */
+		exit((argc > 2) ? atoi(argv[2]) : 0);
+		break;
+
+	case DEFNTYPE:
+		if (argc > 2)
+			for (n = 2; n < argc; n++)
+				dodefn(argv[n]);
+		break;
+
+	default:
+		error("m4: major botch in eval.");
+		break;
+	}
+}
Index: /trunk/minix/commands/m4/expr.c
===================================================================
--- /trunk/minix/commands/m4/expr.c	(revision 9)
+++ /trunk/minix/commands/m4/expr.c	(revision 9)
@@ -0,0 +1,587 @@
+/*
+ *      expression evaluator: performs a standard recursive
+ *      descent parse to evaluate any expression permissible
+ *      within the following grammar:
+ *
+ *      expr    :       query EOS
+ *      query   :       lor
+ *              |       lor "?" query ":" query
+ *      lor     :       land { "||" land }
+ *      land    :       bor { "&&" bor }
+ *      bor     :       bxor { "|" bxor }
+ *      bxor    :       band { "^" band }
+ *      band    :       eql { "&" eql }
+ *      eql     :       relat { eqrel relat }
+ *      relat   :       shift { rel shift }
+ *      shift   :       primary { shop primary }
+ *      primary :       term { addop term }
+ *      term    :       unary { mulop unary }
+ *      unary   :       factor
+ *              |       unop unary
+ *      factor  :       constant
+ *              |       "(" query ")"
+ *      constant:       num
+ *              |       "'" CHAR "'"
+ *      num     :       decnum
+ *              |       "0" octnum
+ *		|	"0x" hexnum
+ *	octnum	:	OCTDIGIT
+ *		|	OCTDIGIT octnum
+ *	decnum	:	DECDIGIT
+ *		|	DECDIGIT decnum
+ *	hexnum	:	HEXDIGIT
+ *		|	HEXDIGIT hexnum
+ *      shop    :       "<<"
+ *              |       ">>"
+ *      eqlrel  :       "="
+ *              |       "=="
+ *              |       "!="
+ *      rel     :       "<"
+ *              |       ">"
+ *              |       "<="
+ *              |       ">="
+ *
+ *
+ *      This expression evaluator is lifted from a public-domain
+ *      C Pre-Processor included with the DECUS C Compiler distribution.
+ *      It is hacked somewhat to be suitable for m4.
+ *
+ *      Originally by:  Mike Lutz
+ *                      Bob Harper
+ */
+ 
+#include "mdef.h"
+
+#define TRUE    1
+#define FALSE   0
+#define EOS     (char) 0
+#define EQL     0
+#define NEQ     1
+#define LSS     2
+#define LEQ     3
+#define GTR     4
+#define GEQ     5
+ 
+static char *nxtch;     /* Parser scan pointer */
+ 
+/*
+ * For longjmp
+ */
+#include <setjmp.h>
+static jmp_buf  expjump;
+ 
+/*
+ * macros:
+ *
+ *      ungetch - Put back the last character examined.
+ *      getch   - return the next character from expr string.
+ */
+#define ungetch()       nxtch--
+#define getch()         *nxtch++
+ 
+int expr(expbuf)
+char *expbuf;
+{
+        register int rval;
+ 
+        nxtch = expbuf;
+        if (setjmp(expjump) != 0)
+                return (FALSE);
+        rval = query();
+        if (skipws() == EOS)
+                return(rval);
+        experr("Ill-formed expression");
+	/* NOTREACHED */
+	return(0);
+}
+ 
+/*
+ * query : lor | lor '?' query ':' query
+ *
+ */
+int query()
+{
+        register int bool, true_val, false_val;
+ 
+        bool = lor();
+        if (skipws() != '?') {
+                ungetch();
+                return(bool);
+        }
+ 
+        true_val = query();
+        if (skipws() != ':')
+                experr("Bad query");
+ 
+        false_val = query();
+        return(bool ? true_val : false_val);
+}
+ 
+/*
+ * lor : land { '||' land }
+ *
+ */
+int lor()
+{
+        register int c, vl, vr;
+ 
+        vl = land();
+        while ((c = skipws()) == '|' && getch() == '|') {
+                vr = land();
+                vl = vl || vr;
+        }
+ 
+        if (c == '|')
+                ungetch();
+        ungetch();
+        return(vl);
+}
+ 
+/*
+ * land : bor { '&&' bor }
+ *
+ */
+int land()
+{
+        register int c, vl, vr;
+ 
+        vl = bor();
+        while ((c = skipws()) == '&' && getch() == '&') {
+                vr = bor();
+                vl = vl && vr;
+        }
+ 
+        if (c == '&')
+                ungetch();
+        ungetch();
+        return(vl);
+}
+ 
+/*
+ * bor : bxor { '|' bxor }
+ *
+ */
+int bor()
+{
+        register int vl, vr, c;
+ 
+        vl = bxor();
+        while ((c = skipws()) == '|' && getch() != '|') {
+                ungetch();
+                vr = bxor();
+                vl |= vr;
+        }
+ 
+        if (c == '|')
+                ungetch();
+        ungetch();
+        return(vl);
+}
+ 
+/*
+ * bxor : band { '^' band }
+ *
+ */
+int bxor()
+{
+        register int vl, vr;
+ 
+        vl = band();
+        while (skipws() == '^') {
+                vr = band();
+                vl ^= vr;
+        }
+ 
+        ungetch();
+        return(vl);
+}
+ 
+/*
+ * band : eql { '&' eql }
+ *
+ */
+int band()
+{
+        register int vl, vr, c;
+ 
+        vl = eql();
+        while ((c = skipws()) == '&' && getch() != '&') {
+                ungetch();
+                vr = eql();
+                vl &= vr;
+        }
+ 
+        if (c == '&')
+                ungetch();
+        ungetch();
+        return(vl);
+}
+ 
+/*
+ * eql : relat { eqrel relat }
+ *
+ */
+int eql()
+{
+        register int vl, vr, rel;
+ 
+        vl = relat();
+        while ((rel = geteql()) != -1) {
+                vr = relat();
+ 
+                switch (rel) {
+ 
+                case EQL:
+                        vl = (vl == vr);
+                        break;
+                case NEQ:
+                        vl = (vl != vr);
+                        break;
+                }
+        }
+        return(vl);
+}
+ 
+/*
+ * relat : shift { rel shift }
+ *
+ */
+int relat()
+{
+        register int vl, vr, rel;
+ 
+        vl = shift();
+        while ((rel = getrel()) != -1) {
+ 
+                vr = shift();
+                switch (rel) {
+ 
+                case LEQ:
+                        vl = (vl <= vr);
+                        break;
+                case LSS:
+                        vl = (vl < vr);
+                        break;
+                case GTR:
+                        vl = (vl > vr);
+                        break;
+                case GEQ:
+                        vl = (vl >= vr);
+                        break;
+                }
+        }
+        return(vl);
+}
+ 
+/*
+ * shift : primary { shop primary }
+ *
+ */
+int shift()
+{
+        register int vl, vr, c;
+ 
+        vl = primary();
+        while (((c = skipws()) == '<' || c == '>') && c == getch()) {
+                vr = primary();
+ 
+                if (c == '<')
+                        vl <<= vr;
+                else
+                        vl >>= vr;
+        }
+ 
+        if (c == '<' || c == '>')
+                ungetch();
+        ungetch();
+        return(vl);
+}
+ 
+/*
+ * primary : term { addop term }
+ *
+ */
+int primary()
+{
+        register int c, vl, vr;
+ 
+        vl = term();
+        while ((c = skipws()) == '+' || c == '-') {
+                vr = term();
+                if (c == '+')
+                        vl += vr;
+                else
+                        vl -= vr;
+        }
+ 
+        ungetch();
+        return(vl);
+}
+ 
+/*
+ * <term> := <unary> { <mulop> <unary> }
+ *
+ */
+int term()
+{
+        register int c, vl, vr;
+ 
+        vl = unary();
+        while ((c = skipws()) == '*' || c == '/' || c == '%') {
+                vr = unary();
+ 
+                switch (c) {
+                case '*':
+                        vl *= vr;
+                        break;
+                case '/':
+                        vl /= vr;
+                        break;
+                case '%':
+                        vl %= vr;
+                        break;
+                }
+        }
+        ungetch();
+        return(vl);
+}
+ 
+/*
+ * unary : factor | unop unary
+ *
+ */
+int unary()
+{
+        register int val, c;
+ 
+        if ((c = skipws()) == '!' || c == '~' || c == '-') {
+                val = unary();
+ 
+                switch (c) {
+                case '!':
+                        return(! val);
+                case '~':
+                        return(~ val);
+                case '-':
+                        return(- val);
+                }
+        }
+ 
+        ungetch();
+        return(factor());
+}
+ 
+/*
+ * factor : constant | '(' query ')'
+ *
+ */
+int factor()
+{
+        register int val;
+ 
+        if (skipws() == '(') {
+                val = query();
+                if (skipws() != ')')
+                        experr("Bad factor");
+                return(val);
+        }
+ 
+        ungetch();
+        return(constant());
+}
+ 
+/*
+ * constant: num | 'char'
+ *
+ */
+int constant()
+{
+        /*
+         * Note: constant() handles multi-byte constants
+         */
+ 
+        register int    i;
+        register int    value;
+        register char   c;
+        int             v[sizeof (int)];
+ 
+        if (skipws() != '\'') {
+                ungetch();
+                return(num());
+        }
+        for (i = 0; i < sizeof(int); i++) {
+                if ((c = getch()) == '\'') {
+                        ungetch();
+                        break;
+                }
+                if (c == '\\') {
+                        switch (c = getch()) {
+                        case '0':
+                        case '1':
+                        case '2':
+                        case '3':
+                        case '4':
+                        case '5':
+                        case '6':
+                        case '7':
+                                ungetch();
+                                c = num();
+                                break;
+                        case 'n':
+                                c = 012;
+                                break;
+                        case 'r':
+                                c = 015;
+                                break;
+                        case 't':
+                                c = 011;
+                                break;
+                        case 'b':
+                                c = 010;
+                                break;
+                        case 'f':
+                                c = 014;
+                                break;
+                        }
+                }
+                v[i] = c;
+        }
+        if (i == 0 || getch() != '\'')
+                experr("Illegal character constant");
+        for (value = 0; --i >= 0;) {
+                value <<= 8;
+                value += v[i];
+        }
+        return(value);
+}
+ 
+/*
+ * num : digit | num digit
+ *
+ */
+int num()
+{
+        register int rval, c, base;
+        int ndig;
+ 
+        ndig = 0;
+        if ((c = skipws()) == '0') {
+        	c = getch ();
+        	if (c == 'x' || c == 'X') {
+        		base = 16;
+        		c = getch ();
+        	} else {
+        		base = 8;
+        		ndig = 1;
+        	}
+        } else {
+        	base = 10;
+        }
+        rval = 0;
+        for (;;) {
+		if (isdigit(c))         c -= '0';
+		else if (isupper (c))   c -= ('A' - 10);
+		else if (islower (c))   c -= ('a' - 10);
+		else                    break;
+		if (c < 0 || c >= base)
+			break;
+
+                rval *= base;
+                rval += c;
+                c = getch();
+                ndig++;
+        }
+        ungetch();
+        if (ndig)
+                return(rval);
+        experr("Bad constant");
+	/* NOTREACHED */
+	return(0);
+}
+ 
+/*
+ * eqlrel : '=' | '==' | '!='
+ *
+ */
+int geteql()
+{
+        register int c1, c2;
+ 
+        c1 = skipws();
+        c2 = getch();
+ 
+        switch (c1) {
+ 
+        case '=':
+                if (c2 != '=')
+                        ungetch();
+                return(EQL);
+ 
+        case '!':
+                if (c2 == '=')
+                        return(NEQ);
+                ungetch();
+                ungetch();
+                return(-1);
+ 
+        default:
+                ungetch();
+                ungetch();
+                return(-1);
+        }
+}
+ 
+/*
+ * rel : '<' | '>' | '<=' | '>='
+ *
+ */
+int getrel()
+{
+        register int c1, c2;
+ 
+        c1 = skipws();
+        c2 = getch();
+ 
+        switch (c1) {
+ 
+        case '<':
+                if (c2 == '=')
+                        return(LEQ);
+                ungetch();
+                return(LSS);
+ 
+        case '>':
+                if (c2 == '=')
+                        return(GEQ);
+                ungetch();
+                return(GTR);
+ 
+        default:
+                ungetch();
+                ungetch();
+                return(-1);
+        }
+}
+ 
+/*
+ * Skip over any white space and return terminating char.
+ */
+int skipws()
+{
+        register char c;
+ 
+        while ((c = getch()) <= ' ' && c > EOS)
+                ;
+        return(c);
+}
+ 
+/*
+ * Error handler - resets environment to eval(), prints an error,
+ * and returns FALSE.
+ */
+int experr(msg)
+char *msg;
+{
+        printf("mp: %s\n",msg);
+        longjmp(expjump, -1);          /* Force eval() to return FALSE */
+}
Index: /trunk/minix/commands/m4/extr.h
===================================================================
--- /trunk/minix/commands/m4/extr.h	(revision 9)
+++ /trunk/minix/commands/m4/extr.h	(revision 9)
@@ -0,0 +1,21 @@
+extern ndptr hashtab[];		/* hash table for macros etc.  */
+extern char buf[];		/* push-back buffer	       */
+extern char *bp;		/* first available character   */
+extern char *endpbb;		/* end of push-back buffer     */
+extern stae mstack[];		/* stack of m4 machine         */
+extern char *ep;		/* first free char in strspace */
+extern char *endest;		/* end of string space	       */
+extern int sp; 			/* current m4  stack pointer   */
+extern int fp; 			/* m4 call frame pointer       */
+extern FILE *infile[];		/* input file stack (0=stdin)  */
+extern FILE *outfile[];		/* diversion array(0=bitbucket)*/
+extern FILE *active;		/* active output file pointer  */
+extern char *m4temp;		/* filename for diversions     */
+extern int ilevel;		/* input file stack pointer    */
+extern int oindex;		/* diversion index..	       */
+extern char *null;		/* as it says.. just a null..  */
+extern char *m4wraps;		/* m4wrap string default..     */
+extern char lquote;		/* left quote character  (`)   */
+extern char rquote;		/* right quote character (')   */
+extern char scommt;		/* start character for comment */
+extern char ecommt;		/* end character for comment   */
Index: /trunk/minix/commands/m4/look.c
===================================================================
--- /trunk/minix/commands/m4/look.c	(revision 9)
+++ /trunk/minix/commands/m4/look.c	(revision 9)
@@ -0,0 +1,110 @@
+/*
+ * look.c
+ * Facility: m4 macro processor
+ * by: oz
+ */
+
+#include "mdef.h"
+#include "extr.h"
+
+/*
+ *  hash - compute hash value using the proverbial
+ *	   hashing function. Taken from K&R.
+ */
+int hash (name)
+register char *name;
+{
+	register int h = 0;
+	while (*name)
+		h += *name++;
+	return (h % HASHSIZE);
+}
+
+/*
+ * lookup - find name in the hash table
+ *
+ */
+ndptr lookup(name)
+char *name;
+{
+	register ndptr p;
+
+	for (p = hashtab[hash(name)]; p != nil; p = p->nxtptr)
+		if (strcmp(name, p->name) == 0)
+			break;
+	return (p);
+}
+
+/*
+ * addent - hash and create an entry in the hash
+ *	    table. The new entry is added in front
+ *	    of a hash bucket.
+ */
+ndptr addent(name)
+char *name;
+{
+	register int h;
+	ndptr p;
+
+	h = hash(name);
+	if ((p = (ndptr) malloc(sizeof(struct ndblock))) != NULL) {
+		p->nxtptr = hashtab[h];
+		hashtab[h] = p;
+		p->name = strsave(name);
+	}
+	else
+		error("m4: no more memory.");
+	return p;
+}
+
+/*
+ * remhash - remove an entry from the hashtable
+ *
+ */
+void remhash(name, all)
+char *name;
+int all;
+{
+	register int h;
+	register ndptr xp, tp, mp;
+
+	h = hash(name);
+	mp = hashtab[h];
+	tp = nil;
+	while (mp != nil) {
+		if (strcmp(mp->name, name) == 0) {
+			mp = mp->nxtptr;
+			if (tp == nil) {
+				freent(hashtab[h]);
+				hashtab[h] = mp;
+			}
+			else {
+				xp = tp->nxtptr;
+				tp->nxtptr = mp;
+				freent(xp);
+			}
+			if (!all)
+				break;
+		}
+		else {
+			tp = mp;
+			mp = mp->nxtptr;
+		}
+	}
+}
+
+/*
+ * freent - free a hashtable information block
+ *
+ */
+void freent(p)
+ndptr p;
+{
+	if (!(p->type & STATIC)) {
+		free(p->name);
+		if (p->defn != null)
+			free(p->defn);
+	}
+	free(p);
+}
+
Index: /trunk/minix/commands/m4/main.c
===================================================================
--- /trunk/minix/commands/m4/main.c	(revision 9)
+++ /trunk/minix/commands/m4/main.c	(revision 9)
@@ -0,0 +1,457 @@
+/*
+ * main.c
+ * Facility: m4 macro processor
+ * by: oz
+ */
+
+#include "mdef.h"
+
+/*
+ * m4 - macro processor
+ *
+ * PD m4 is based on the macro tool distributed with the software 
+ * tools (VOS) package, and described in the "SOFTWARE TOOLS" and 
+ * "SOFTWARE TOOLS IN PASCAL" books. It has been expanded to include 
+ * most of the command set of SysV m4, the standard UN*X macro processor.
+ *
+ * Since both PD m4 and UN*X m4 are based on SOFTWARE TOOLS macro,
+ * there may be certain implementation similarities between
+ * the two. The PD m4 was produced without ANY references to m4
+ * sources.
+ *
+ * References:
+ *
+ *	Software Tools distribution: macro
+ *
+ *	Kernighan, Brian W. and P. J. Plauger, SOFTWARE
+ *	TOOLS IN PASCAL, Addison-Wesley, Mass. 1981
+ *
+ *	Kernighan, Brian W. and P. J. Plauger, SOFTWARE
+ *	TOOLS, Addison-Wesley, Mass. 1976
+ *
+ *	Kernighan, Brian W. and Dennis M. Ritchie,
+ *	THE M4 MACRO PROCESSOR, Unix Programmer's Manual,
+ *	Seventh Edition, Vol. 2, Bell Telephone Labs, 1979
+ *
+ *	System V man page for M4
+ *
+ * Modification History:
+ *
+ * Jan 28 1986 Oz	Break the whole thing into little
+ *			pieces, for easier (?) maintenance.
+ *
+ * Dec 12 1985 Oz	Optimize the code, try to squeeze
+ *			few microseconds out..
+ *
+ * Dec 05 1985 Oz	Add getopt interface, define (-D),
+ *			undefine (-U) options.
+ *
+ * Oct 21 1985 Oz	Clean up various bugs, add comment handling.
+ *
+ * June 7 1985 Oz	Add some of SysV m4 stuff (m4wrap, pushdef,
+ *			popdef, decr, shift etc.).
+ *
+ * June 5 1985 Oz	Initial cut.
+ *
+ * Implementation Notes:
+ *
+ * [1]	PD m4 uses a different (and simpler) stack mechanism than the one 
+ *	described in Software Tools and Software Tools in Pascal books. 
+ *	The triple stack nonsense is replaced with a single stack containing 
+ *	the call frames and the arguments. Each frame is back-linked to a 
+ * 	previous stack frame, which enables us to rewind the stack after 
+ * 	each nested call is completed. Each argument is a character pointer 
+ *	to the beginning of the argument string within the string space.
+ *	The only exceptions to this are (*) arg 0 and arg 1, which are
+ * 	the macro definition and macro name strings, stored dynamically
+ *	for the hash table.
+ *
+ *	    .					   .
+ *	|   .	|  <-- sp			|  .  |
+ *	+-------+				+-----+
+ *	| arg 3 ------------------------------->| str |
+ *	+-------+				|  .  |
+ *	| arg 2 --------------+ 		   .
+ *	+-------+	      |
+ *	    *		      |			|     |
+ *	+-------+	      | 		+-----+
+ *	| plev	|  <-- fp     +---------------->| str |
+ *	+-------+				|  .  |
+ *	| type	|				   .
+ *	+-------+
+ *	| prcf	-----------+		plev: paren level
+ *	+-------+  	   |		type: call type
+ *	|   .	| 	   |		prcf: prev. call frame
+ *	    .	   	   |
+ *	+-------+	   |
+ *	|	<----------+
+ *	+-------+
+ *
+ * [2]	We have three types of null values:
+ *
+ *		nil  - nodeblock pointer type 0
+ *		null - null string ("")
+ *		NULL - Stdio-defined NULL
+ *
+ */
+
+ndptr hashtab[HASHSIZE];	/* hash table for macros etc.  */
+char buf[BUFSIZE];		/* push-back buffer	       */
+char *bp = buf; 		/* first available character   */
+char *endpbb = buf+BUFSIZE;	/* end of push-back buffer     */
+stae mstack[STACKMAX+1]; 	/* stack of m4 machine         */
+char strspace[STRSPMAX+1];	/* string space for evaluation */
+char *ep = strspace;		/* first free char in strspace */
+char *endest= strspace+STRSPMAX;/* end of string space	       */
+int sp; 			/* current m4  stack pointer   */
+int fp; 			/* m4 call frame pointer       */
+FILE *infile[MAXINP];		/* input file stack (0=stdin)  */
+FILE *outfile[MAXOUT];		/* diversion array(0=bitbucket)*/
+FILE *active;			/* active output file pointer  */
+char *m4temp;			/* filename for diversions     */
+int ilevel = 0; 		/* input file stack pointer    */
+int oindex = 0; 		/* diversion index..	       */
+char *null = "";                /* as it says.. just a null..  */
+char *m4wraps = "";             /* m4wrap string default..     */
+char lquote = LQUOTE;		/* left quote character  (`)   */
+char rquote = RQUOTE;		/* right quote character (')   */
+char scommt = SCOMMT;		/* start character for comment */
+char ecommt = ECOMMT;		/* end character for comment   */
+struct keyblk keywrds[] = {	/* m4 keywords to be installed */
+	"include",      INCLTYPE,
+	"sinclude",     SINCTYPE,
+	"define",       DEFITYPE,
+	"defn",         DEFNTYPE,
+	"divert",       DIVRTYPE,
+	"expr",         EXPRTYPE,
+	"eval",         EXPRTYPE,
+	"substr",       SUBSTYPE,
+	"ifelse",       IFELTYPE,
+	"ifdef",        IFDFTYPE,
+	"len",          LENGTYPE,
+	"incr",         INCRTYPE,
+	"decr",         DECRTYPE,
+	"dnl",          DNLNTYPE,
+	"changequote",  CHNQTYPE,
+	"changecom",    CHNCTYPE,
+	"index",        INDXTYPE,
+#ifdef EXTENDED
+	"paste",        PASTTYPE,
+	"spaste",       SPASTYPE,
+#endif
+	"popdef",       POPDTYPE,
+	"pushdef",      PUSDTYPE,
+	"dumpdef",      DUMPTYPE,
+	"shift",        SHIFTYPE,
+	"translit",     TRNLTYPE,
+	"undefine",     UNDFTYPE,
+	"undivert",     UNDVTYPE,
+	"divnum",       DIVNTYPE,
+	"maketemp",     MKTMTYPE,
+	"errprint",     ERRPTYPE,
+	"m4wrap",       M4WRTYPE,
+	"m4exit",       EXITTYPE,
+#if unix || vms
+	"syscmd",       SYSCTYPE,
+	"sysval",       SYSVTYPE,
+#endif
+#if unix
+	"unix",         MACRTYPE,
+#else
+#if vms
+	"vms",          MACRTYPE,
+#endif
+#endif
+};
+
+#define MAXKEYS	(sizeof(keywrds)/sizeof(struct keyblk))
+
+extern int optind;
+extern char *optarg;
+
+int main(argc,argv)
+int argc;
+char *argv[];
+{
+	register int c;
+	register int n;
+	char *p;
+	static char divnam[] = DIVNAM;
+
+	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+		signal(SIGINT, onintr);
+#ifdef NONZEROPAGES
+	initm4();
+#endif
+	initkwds();
+
+	while ((c = getopt(argc, argv, "tD:U:o:")) != EOF) {
+		switch(c) {
+
+		case 'D':               /* define something..*/
+			for (p = optarg; *p; p++)
+				if (*p == '=')
+					break;
+			if (*p)
+				*p++ = EOS;
+			dodefine(optarg, p);
+			break;
+		case 'U':               /* undefine...       */
+			remhash(optarg, TOP);
+			break;
+		case 'o':		/* specific output   */
+		case '?':
+		default:
+			usage();
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	if(argc > 1) { usage(); }
+	infile[0] = stdin;		/* default input (naturally) */
+	if(argc == 1) {
+		if(!(infile[0] = fopen(argv[0], "r"))) {
+			perror(argv[0]);
+			return 1;
+		}
+	}
+
+	active = stdout;		/* default active output     */
+	m4temp = mktemp(divnam);	/* filename for diversions   */
+
+	sp = -1;			/* stack pointer initialized */
+	fp = 0; 			/* frame pointer initialized */
+
+	macro();			/* get some work done here   */
+
+	if (*m4wraps) { 		/* anything for rundown ??   */
+		ilevel = 0;		/* in case m4wrap includes.. */
+		putback(EOF);		/* eof is a must !!	     */
+		pbstr(m4wraps); 	/* user-defined wrapup act   */
+		macro();		/* last will and testament   */
+	}
+	else				/* default wrap-up: undivert */
+		for (n = 1; n < MAXOUT; n++)
+			if (outfile[n] != NULL)
+				getdiv(n);
+
+					/* remove bitbucket if used  */
+	if (outfile[0] != NULL) {
+		(void) fclose(outfile[0]);
+		m4temp[UNIQUE] = '0';
+#if vms
+		(void) remove(m4temp);
+#else
+		(void) unlink(m4temp);
+#endif
+	}
+
+	exit(0);
+}
+
+/*
+ * macro - the work horse..
+ *
+ */
+void macro() {
+	char token[MAXTOK];
+	register char *s;
+	register int t, l;
+	register ndptr p;
+	register int  nlpar;
+
+	cycle {
+		if ((t = gpbc()) == '_' || isalpha(t)) {
+			putback(t);
+			if ((p = inspect(s = token)) == nil) {
+				if (sp < 0)
+					while (*s)
+						putc(*s++, active);
+				else
+					while (*s)
+						chrsave(*s++);
+			}
+			else {
+		/*
+		 * real thing.. First build a call frame:
+		 *
+		 */
+				pushf(fp);	/* previous call frm */
+				pushf(p->type); /* type of the call  */
+				pushf(0);	/* parenthesis level */
+				fp = sp;	/* new frame pointer */
+		/*
+		 * now push the string arguments:
+		 *
+		 */
+				pushs(p->defn);	      /* defn string */
+				pushs(p->name);	      /* macro name  */
+				pushs(ep);	      /* start next..*/
+
+				putback(l = gpbc());
+				if (l != LPAREN)  {   /* add bracks  */
+					putback(RPAREN);
+					putback(LPAREN);
+				}
+			}
+		}
+		else if (t == EOF) {
+			if (sp > -1)
+				error("m4: unexpected end of input");
+			if (--ilevel < 0)
+				break;			/* all done thanks.. */
+			(void) fclose(infile[ilevel+1]);
+			continue;
+		}
+	/*
+	 * non-alpha single-char token seen..
+	 * [the order of else if .. stmts is
+	 * important.]
+	 *
+	 */
+		else if (t == lquote) { 		/* strip quotes */
+			nlpar = 1;
+			do {
+				if ((l = gpbc()) == rquote)
+					nlpar--;
+				else if (l == lquote)
+					nlpar++;
+				else if (l == EOF)
+					error("m4: missing right quote");
+				if (nlpar > 0) {
+					if (sp < 0)
+						putc(l, active);
+					else
+						chrsave(l);
+				}
+			}
+			while (nlpar != 0);
+		}
+
+		else if (sp < 0) {		/* not in a macro at all */
+			if (t == scommt) {	/* comment handling here */
+				putc(t, active);
+				while ((t = gpbc()) != ecommt)
+					putc(t, active);
+			}
+			putc(t, active);	/* output directly..	 */
+		}
+
+		else switch(t) {
+
+		case LPAREN:
+			if (PARLEV > 0)
+				chrsave(t);
+			while (isspace(l = gpbc()))
+				;		/* skip blank, tab, nl.. */
+			putback(l);
+			PARLEV++;
+			break;
+
+		case RPAREN:
+			if (--PARLEV > 0)
+				chrsave(t);
+			else {			/* end of argument list */
+				chrsave(EOS);
+
+				if (sp == STACKMAX)
+					error("m4: internal stack overflow");
+
+				if (CALTYP == MACRTYPE)
+					expand((char**)mstack+fp+1,(int)sp-fp);
+				else
+					eval((char**)mstack+fp+1,sp-fp,CALTYP);
+
+				ep = PREVEP;	/* flush strspace */
+				sp = PREVSP;	/* previous sp..  */
+				fp = PREVFP;	/* rewind stack...*/
+			}
+			break;
+
+		case COMMA:
+			if (PARLEV == 1)	{
+				chrsave(EOS);		/* new argument   */
+				while (isspace(l = gpbc()))
+					;
+				putback(l);
+				pushs(ep);
+			}
+			break;
+		default:
+			chrsave(t);			/* stack the char */
+			break;
+		}
+	}
+}
+
+
+/*
+ * build an input token..
+ * consider only those starting with _ or A-Za-z. This is a
+ * combo with lookup to speed things up.
+ */
+ndptr
+inspect(tp) 
+register char *tp;
+{
+	register int h = 0;
+	register char c;
+	register char *name = tp;
+	register char *etp = tp+MAXTOK;
+	register ndptr p;
+
+	while (tp < etp && (isalnum(c = gpbc()) || c == '_'))
+		h += (*tp++ = c);
+	putback(c);
+	if (tp == etp)
+		error("m4: token too long");
+	*tp = EOS;
+	for (p = hashtab[h%HASHSIZE]; p != nil; p = p->nxtptr)
+		if (strcmp(name, p->name) == 0)
+			break;
+	return(p);
+}
+
+#ifdef NONZEROPAGES
+/*
+ * initm4 - initialize various tables. Useful only if your system 
+ * does not know anything about demand-zero pages.
+ *
+ */
+void initm4()
+{
+	register int i;
+
+	for (i = 0; i < HASHSIZE; i++)
+		hashtab[i] = nil;
+	for (i = 0; i < MAXOUT; i++)
+		outfile[i] = NULL;
+}
+#endif
+
+/*
+ * initkwds - initialise m4 keywords as fast as possible. 
+ * This very similar to install, but without certain overheads,
+ * such as calling lookup. Malloc is not used for storing the 
+ * keyword strings, since we simply use the static  pointers
+ * within keywrds block. We also assume that there is enough memory 
+ * to at least install the keywords (i.e. malloc won't fail).
+ *
+ */
+void initkwds() {
+	register int i;
+	register int h;
+	register ndptr p;
+
+	for (i = 0; i < MAXKEYS; i++) {
+		h = hash(keywrds[i].knam);
+		p = (ndptr) malloc(sizeof(struct ndblock));
+		p->nxtptr = hashtab[h];
+		hashtab[h] = p;
+		p->name = keywrds[i].knam;
+		p->defn = null;
+		p->type = keywrds[i].ktyp | STATIC;
+	}
+}
Index: /trunk/minix/commands/m4/mdef.h
===================================================================
--- /trunk/minix/commands/m4/mdef.h	(revision 9)
+++ /trunk/minix/commands/m4/mdef.h	(revision 9)
@@ -0,0 +1,276 @@
+/*
+ * mdef.h
+ * Facility: m4 macro processor
+ * by: oz
+ */
+
+
+#define unix	1	/* (kjb) */
+
+#ifndef unix
+#define unix 0
+#endif 
+
+#ifndef vms
+#define vms 0
+#endif
+
+#if vms
+
+#include stdio
+#include ctype
+#include signal
+
+#else 
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#endif
+
+/*
+ *
+ * m4 constants..
+ *
+ */
+ 
+#define MACRTYPE        1
+#define DEFITYPE        2
+#define EXPRTYPE        3
+#define SUBSTYPE        4
+#define IFELTYPE        5
+#define LENGTYPE        6
+#define CHNQTYPE        7
+#define SYSCTYPE        8
+#define UNDFTYPE        9
+#define INCLTYPE        10
+#define SINCTYPE        11
+#define PASTTYPE        12
+#define SPASTYPE        13
+#define INCRTYPE        14
+#define IFDFTYPE        15
+#define PUSDTYPE        16
+#define POPDTYPE        17
+#define SHIFTYPE        18
+#define DECRTYPE        19
+#define DIVRTYPE        20
+#define UNDVTYPE        21
+#define DIVNTYPE        22
+#define MKTMTYPE        23
+#define ERRPTYPE        24
+#define M4WRTYPE        25
+#define TRNLTYPE        26
+#define DNLNTYPE        27
+#define DUMPTYPE        28
+#define CHNCTYPE        29
+#define INDXTYPE        30
+#define SYSVTYPE        31
+#define EXITTYPE        32
+#define DEFNTYPE        33
+ 
+#define STATIC          128
+
+/*
+ * m4 special characters
+ */
+ 
+#define ARGFLAG         '$'
+#define LPAREN          '('
+#define RPAREN          ')'
+#define LQUOTE          '`'
+#define RQUOTE          '\''
+#define COMMA           ','
+#define SCOMMT          '#'
+#define ECOMMT          '\n'
+
+/*
+ * definitions of diversion files. If the name of
+ * the file is changed, adjust UNIQUE to point to the
+ * wildcard (*) character in the filename.
+ */
+
+#if unix
+#define DIVNAM  "/tmp/m4*XXXXXX"        /* unix diversion files    */
+#define UNIQUE          7               /* unique char location    */
+#else
+#if vms
+#define DIVNAM  "sys$login:m4*XXXXXX"   /* vms diversion files     */
+#define UNIQUE          12              /* unique char location    */
+#else
+#define DIVNAM	"\M4*XXXXXX"		/* msdos diversion files   */
+#define	UNIQUE	    3			/* unique char location    */
+#endif
+#endif
+
+/*
+ * other important constants
+ */
+
+#define EOS             (char) 0
+#define MAXINP          10              /* maximum include files   */
+#define MAXOUT          10              /* maximum # of diversions */
+#define MAXSTR          512             /* maximum size of string  */
+#define BUFSIZE         4096            /* size of pushback buffer */
+#define STACKMAX        1024            /* size of call stack      */
+#define STRSPMAX        4096            /* size of string space    */
+#define MAXTOK          MAXSTR          /* maximum chars in a tokn */
+#define HASHSIZE        199             /* maximum size of hashtab */
+ 
+#define ALL             1
+#define TOP             0
+ 
+#define TRUE            1
+#define FALSE           0
+#define cycle           for(;;)
+
+#ifdef VOID
+#define void            int             /* define if void is void. */
+#endif
+
+/*
+ * m4 data structures
+ */
+ 
+typedef struct ndblock *ndptr;
+ 
+struct ndblock {                /* hastable structure         */
+        char    *name;          /* entry name..               */
+        char    *defn;          /* definition..               */
+        int     type;           /* type of the entry..        */
+        ndptr   nxtptr;         /* link to next entry..       */
+};
+ 
+#define nil     ((ndptr) 0)
+ 
+struct keyblk {
+        char    *knam;          /* keyword name */
+        int     ktyp;           /* keyword type */
+};
+
+typedef union {			/* stack structure */
+	int	sfra;		/* frame entry  */
+	char 	*sstr;		/* string entry */
+} stae;
+
+/*
+ * macros for readibility and/or speed
+ *
+ *      gpbc()  - get a possibly pushed-back character
+ *      min()   - select the minimum of two elements
+ *      pushf() - push a call frame entry onto stack
+ *      pushs() - push a string pointer onto stack
+ */
+#define gpbc() 	 (bp > buf) ? *--bp : getc(infile[ilevel])
+#define min(x,y) ((x > y) ? y : x)
+#define pushf(x) if (sp < STACKMAX) mstack[++sp].sfra = (x)
+#define pushs(x) if (sp < STACKMAX) mstack[++sp].sstr = (x)
+
+/*
+ *	    .				   .
+ *	|   .	|  <-- sp		|  .  |
+ *	+-------+			+-----+
+ *	| arg 3 ----------------------->| str |
+ *	+-------+			|  .  |
+ *	| arg 2 ---PREVEP-----+ 	   .
+ *	+-------+	      |
+ *	    .		      |		|     |
+ *	+-------+	      | 	+-----+
+ *	| plev	|  PARLEV     +-------->| str |
+ *	+-------+			|  .  |
+ *	| type	|  CALTYP		   .
+ *	+-------+
+ *	| prcf	---PREVFP--+
+ *	+-------+  	   |
+ *	|   .	|  PREVSP  |
+ *	    .	   	   |
+ *	+-------+	   |
+ *	|	<----------+
+ *	+-------+
+ *
+ */
+#define PARLEV  (mstack[fp].sfra)
+#define CALTYP  (mstack[fp-1].sfra)
+#define PREVEP	(mstack[fp+3].sstr)
+#define PREVSP	(fp-3)
+#define PREVFP	(mstack[fp-2].sfra)
+
+/* function prototypes */
+
+/* eval.c */
+
+_PROTOTYPE(void eval, (char *argv [], int argc, int td ));
+
+/* expr.c */
+
+_PROTOTYPE(int expr, (char *expbuf ));
+_PROTOTYPE(int query, (void));
+_PROTOTYPE(int lor, (void));
+_PROTOTYPE(int land, (void));
+_PROTOTYPE(int bor, (void));
+_PROTOTYPE(int bxor, (void));
+_PROTOTYPE(int band, (void));
+_PROTOTYPE(int eql, (void));
+_PROTOTYPE(int relat, (void));
+_PROTOTYPE(int shift, (void));
+_PROTOTYPE(int primary, (void));
+_PROTOTYPE(int term, (void));
+_PROTOTYPE(int unary, (void));
+_PROTOTYPE(int factor, (void));
+_PROTOTYPE(int constant, (void));
+_PROTOTYPE(int num, (void));
+_PROTOTYPE(int geteql, (void));
+_PROTOTYPE(int getrel, (void));
+_PROTOTYPE(int skipws, (void));
+_PROTOTYPE(int experr, (char *msg ));
+
+/* look.c */
+
+_PROTOTYPE(int hash, (char *name ));
+_PROTOTYPE(ndptr lookup, (char *name ));
+_PROTOTYPE(ndptr addent, (char *name ));
+_PROTOTYPE(void remhash, (char *name, int all ));
+_PROTOTYPE(void freent, (ndptr p ));
+
+/* main.c */
+
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(void macro, (void));
+_PROTOTYPE(ndptr inspect, (char *tp ));
+_PROTOTYPE(void initm4, (void));
+_PROTOTYPE(void initkwds, (void));
+
+/* misc.c */
+
+_PROTOTYPE(int indx, (char *s1, char *s2 ));
+_PROTOTYPE(void putback, (int c ));
+_PROTOTYPE(void pbstr, (char *s ));
+_PROTOTYPE(void pbnum, (int n ));
+_PROTOTYPE(void chrsave, (int c ));
+_PROTOTYPE(void getdiv, (int ind ));
+_PROTOTYPE(void error, (char *s ));
+_PROTOTYPE(void onintr, (int s ));
+_PROTOTYPE(void killdiv, (void));
+_PROTOTYPE(char *strsave, (char *s ));
+_PROTOTYPE(void usage, (void));
+
+/* serv.c */
+
+_PROTOTYPE(void expand, (char *argv [], int argc ));
+_PROTOTYPE(void dodefine, (char *name, char *defn ));
+_PROTOTYPE(void dodefn, (char *name ));
+_PROTOTYPE(void dopushdef, (char *name, char *defn ));
+_PROTOTYPE(void dodump, (char *argv [], int argc ));
+_PROTOTYPE(void doifelse, (char *argv [], int argc ));
+_PROTOTYPE(int doincl, (char *ifile ));
+_PROTOTYPE(int dopaste, (char *pfile ));
+_PROTOTYPE(void dochq, (char *argv [], int argc ));
+_PROTOTYPE(void dochc, (char *argv [], int argc ));
+_PROTOTYPE(void dodiv, (int n ));
+_PROTOTYPE(void doundiv, (char *argv [], int argc ));
+_PROTOTYPE(void dosub, (char *argv [], int argc ));
+_PROTOTYPE(void map, (char *dest, char *src, char *from, char *to ));
Index: /trunk/minix/commands/m4/misc.c
===================================================================
--- /trunk/minix/commands/m4/misc.c	(revision 9)
+++ /trunk/minix/commands/m4/misc.c	(revision 9)
@@ -0,0 +1,292 @@
+/*
+ * misc.c
+ * Facility: m4 macro processor
+ * by: oz
+ */
+ 
+#include "mdef.h"
+#include "extr.h" 
+ 
+/*
+ * indx - find the index of second str in the
+ *        first str.
+ */
+int indx(s1, s2)
+char *s1;
+char *s2;
+{
+        register char *t;
+        register char *p;
+        register char *m;
+ 
+        for (p = s1; *p; p++) {
+                for (t = p, m = s2; *m && *m == *t; m++, t++)
+                        ;
+                if (!*m)
+                        return(p - s1);
+        }
+        return (-1);
+}
+ 
+/*
+ *  putback - push character back onto input
+ *
+ */
+void putback (c)
+char c;
+{
+        if (bp < endpbb)
+                *bp++ = c;
+        else
+                error("m4: too many characters pushed back");
+}
+ 
+/*
+ *  pbstr - push string back onto input
+ *          putback is replicated to improve
+ *          performance.
+ *
+ */
+void pbstr(s)
+register char *s;
+{
+        register char *es;
+	register char *zp;
+
+	es = s;
+	zp = bp;
+
+        while (*es)
+                es++;
+        es--;
+        while (es >= s)
+                if (zp < endpbb)
+                        *zp++ = *es--;
+        if ((bp = zp) == endpbb)
+                error("m4: too many characters pushed back");
+}
+ 
+/*
+ *  pbnum - convert number to string, push back on input.
+ *
+ */
+void pbnum (n)
+int n;
+{
+        register int num;
+ 
+        num = (n < 0) ? -n : n;
+        do {
+                putback(num % 10 + '0');
+        }
+        while ((num /= 10) > 0);
+
+        if (n < 0) putback('-');
+}
+ 
+/*
+ *  chrsave - put single char on string space
+ *
+ */
+void chrsave (c)
+char c;
+{
+/***        if (sp < 0)
+                putc(c, active);
+        else ***/ if (ep < endest)
+                *ep++ = c;
+        else
+                error("m4: string space overflow");
+}
+ 
+/*
+ * getdiv - read in a diversion file, and
+ *          trash it.
+ */
+void getdiv(ind)
+int ind;
+{
+        register int c;
+        register FILE *dfil;
+ 
+        if (active == outfile[ind])
+                error("m4: undivert: diversion still active.");
+        (void) fclose(outfile[ind]);
+        outfile[ind] = NULL;
+        m4temp[UNIQUE] = ind + '0';
+        if ((dfil = fopen(m4temp, "r")) == NULL)
+                error("m4: cannot undivert.");
+        else
+                while((c = getc(dfil)) != EOF)
+                        putc(c, active);
+        (void) fclose(dfil);
+
+#if vms
+        if (remove(m4temp))
+#else
+	if (unlink(m4temp) == -1)
+#endif
+                error("m4: cannot unlink.");
+}
+ 
+/*
+ * Very fatal error. Close all files
+ * and die hard.
+ */
+void error(s)
+char *s;
+{
+        killdiv();
+        fprintf(stderr,"%s\n",s);
+        exit(1);
+}
+ 
+/*
+ * Interrupt handling
+ */
+static char *msg = "\ninterrupted.";
+ 
+void onintr(s) 
+int s;				/* ANSI requires the parameter */
+{
+        error(msg);
+}
+ 
+/*
+ * killdiv - get rid of the diversion files
+ *
+ */
+void killdiv() {
+        register int n;
+ 
+        for (n = 0; n < MAXOUT; n++)
+                if (outfile[n] != NULL) {
+                        (void) fclose (outfile[n]);
+                        m4temp[UNIQUE] = n + '0';
+#if vms
+			(void) remove (m4temp);
+#else
+                        (void) unlink (m4temp);
+#endif
+                }
+}
+ 
+/*
+ * save a string somewhere..
+ *
+ */
+char *strsave(s)
+char *s;
+{
+	register int n;
+        char *p;
+
+	n = strlen(s)+1;
+	p = (char *) malloc(n);
+        if (p != NULL) (void) memcpy(p, s, n);
+        return (p);
+}
+ 
+void usage() {
+        fprintf(stderr, "Usage: m4 [-Dname[=val]] [-Uname]\n");
+        exit(1);
+}
+
+#ifdef GETOPT
+/*
+ * H. Spencer getopt - get option letter from argv
+ * 
+ *
+#include <stdio.h>
+ *
+ */
+
+char	*optarg;	/* Global argument pointer. */
+int	optind = 0;	/* Global argv index. */
+
+static char	*scan = NULL;	/* Private scan pointer. */
+
+int
+getopt(argc, argv, optstring)
+int argc;
+char *argv[];
+char *optstring;
+{
+	register char c;
+	register char *place;
+
+	optarg = NULL;
+
+	if (scan == NULL || *scan == '\0') {
+		if (optind == 0)
+			optind++;
+	
+		if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
+			return(EOF);
+		if (strcmp(argv[optind], "--")==0) {
+			optind++;
+			return(EOF);
+		}
+	
+		scan = argv[optind]+1;
+		optind++;
+	}
+
+	c = *scan++;
+	place = index(optstring, c);
+
+	if (place == NULL || c == ':') {
+		fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
+		return('?');
+	}
+
+	place++;
+	if (*place == ':') {
+		if (*scan != '\0') {
+			optarg = scan;
+			scan = NULL;
+		} else {
+			optarg = argv[optind];
+			optind++;
+		}
+	}
+
+	return(c);
+}
+   
+#endif
+
+#ifdef DUFFCP
+/*
+ * This code uses Duff's Device (tm Tom Duff)
+ * to unroll the copying loop:
+ * while (count-- > 0)
+ *	*to++ = *from++;
+ */
+
+#define COPYBYTE 	*to++ = *from++
+
+void memcpy(to, from, count)
+register char *from, *to;
+register int count;
+{
+	if (count > 0) {
+		register int loops = (count+8-1) >> 3;	/* div 8 round up */
+
+		switch (count&(8-1)) {			/* mod 8 */
+		case 0: do {
+			COPYBYTE;
+		case 7:	COPYBYTE;
+		case 6:	COPYBYTE;
+		case 5:	COPYBYTE;
+		case 4:	COPYBYTE;
+		case 3:	COPYBYTE;
+		case 2:	COPYBYTE;
+		case 1:	COPYBYTE;
+			} while (--loops > 0);
+		}
+
+	}
+}
+
+#endif
Index: /trunk/minix/commands/m4/patchlevel.h
===================================================================
--- /trunk/minix/commands/m4/patchlevel.h	(revision 9)
+++ /trunk/minix/commands/m4/patchlevel.h	(revision 9)
@@ -0,0 +1,1 @@
+#define PATCHLEVEL 1
Index: /trunk/minix/commands/m4/serv.c
===================================================================
--- /trunk/minix/commands/m4/serv.c	(revision 9)
+++ /trunk/minix/commands/m4/serv.c	(revision 9)
@@ -0,0 +1,423 @@
+/*
+ * serv.c
+ * Facility: m4 macro processor
+ * by: oz
+ */
+ 
+#include "mdef.h"
+#include "extr.h" 
+
+char *dumpfmt = "`%s'\t`%s'\n"; /* format string for dumpdef   */
+ 
+/*
+ * expand - user-defined macro expansion
+ *
+ */
+void expand(argv, argc)
+register char *argv[];
+register int argc;
+{
+        register char *t;
+        register char *p;
+        register int  n;
+        register int  argno;
+ 
+        t = argv[0];    /* defn string as a whole */
+        p = t;
+        while (*p)
+                p++;
+        p--;            /* last character of defn */
+        while (p > t) {
+                if (*(p-1) != ARGFLAG)
+                        putback(*p);
+                else {
+                        switch (*p) {
+ 
+                        case '#':
+                                pbnum(argc-2);
+                                break;
+                        case '0':
+                        case '1':
+                        case '2':
+                        case '3':
+                        case '4':
+                        case '5':
+                        case '6':
+                        case '7':
+                        case '8':
+                        case '9':
+                                if ((argno = *p - '0') < argc-1)
+                                        pbstr(argv[argno+1]);
+                                break;
+                        case '*':
+                                for (n = argc - 1; n > 2; n--) {
+                                        pbstr(argv[n]);
+                                        putback(',');
+                                }
+                                pbstr(argv[2]);
+                                break;
+                        default :
+                                putback(*p);
+                                break;
+                        }
+                        p--;
+                }
+                p--;
+        }
+        if (p == t)         /* do last character */
+                putback(*p);
+}
+ 
+/*
+ * dodefine - install definition in the table
+ *
+ */
+void dodefine(name, defn)
+register char *name;
+register char *defn;
+{
+        register ndptr p;
+ 
+        if (!*name)
+                error("m4: null definition.");
+        if (strcmp(name, defn) == 0)
+                error("m4: recursive definition.");
+        if ((p = lookup(name)) == nil)
+                p = addent(name);
+        else if (p->defn != null)
+                free(p->defn);
+        if (!*defn)
+                p->defn = null;
+        else
+                p->defn = strsave(defn);
+        p->type = MACRTYPE;
+}
+ 
+/*
+ * dodefn - push back a quoted definition of
+ *      the given name.
+ */
+ 
+void dodefn(name)
+char *name;
+{
+        register ndptr p;
+ 
+        if ((p = lookup(name)) != nil && p->defn != null) {
+                putback(rquote);
+                pbstr(p->defn);
+                putback(lquote);
+        }
+}
+     
+/*
+ * dopushdef - install a definition in the hash table
+ *      without removing a previous definition. Since
+ *      each new entry is entered in *front* of the
+ *      hash bucket, it hides a previous definition from
+ *      lookup.
+ */
+void dopushdef(name, defn)
+register char *name;
+register char *defn;
+{
+        register ndptr p;
+ 
+        if (!*name)
+                error("m4: null definition");
+        if (strcmp(name, defn) == 0)
+                error("m4: recursive definition.");
+        p = addent(name);
+        if (!*defn)
+                p->defn = null;
+        else
+                p->defn = strsave(defn);
+        p->type = MACRTYPE;
+}
+ 
+/*
+ * dodumpdef - dump the specified definitions in the hash
+ *      table to stderr. If nothing is specified, the entire
+ *      hash table is dumped.
+ *
+ */
+void dodump(argv, argc)
+register char *argv[];
+register int argc;
+{
+        register int n;
+        ndptr p;
+ 
+        if (argc > 2) {
+                for (n = 2; n < argc; n++)
+                        if ((p = lookup(argv[n])) != nil)
+                                fprintf(stderr, dumpfmt, p->name,
+                                p->defn);
+        }
+        else {
+                for (n = 0; n < HASHSIZE; n++)
+                        for (p = hashtab[n]; p != nil; p = p->nxtptr)
+                                fprintf(stderr, dumpfmt, p->name,
+                                p->defn);
+        }
+}
+ 
+/*
+ * doifelse - select one of two alternatives - loop.
+ *
+ */
+void doifelse(argv,argc)
+register char *argv[];
+register int argc;
+{
+        cycle {
+                if (strcmp(argv[2], argv[3]) == 0)
+                        pbstr(argv[4]);
+                else if (argc == 6)
+                        pbstr(argv[5]);
+                else if (argc > 6) {
+                        argv += 3;
+                        argc -= 3;
+                        continue;
+                }
+                break;
+        }
+}
+ 
+/*
+ * doinclude - include a given file.
+ *
+ */
+int doincl(ifile)
+char *ifile;
+{
+        if (ilevel+1 == MAXINP)
+                error("m4: too many include files.");
+        if ((infile[ilevel+1] = fopen(ifile, "r")) != NULL) {
+                ilevel++;
+                return (1);
+        }
+        else
+                return (0);
+}
+ 
+#ifdef EXTENDED
+/*
+ * dopaste - include a given file without any
+ *           macro processing.
+ */
+int dopaste(pfile)
+char *pfile;
+{
+        FILE *pf;
+        register int c;
+ 
+        if ((pf = fopen(pfile, "r")) != NULL) {
+                while((c = getc(pf)) != EOF)
+                        putc(c, active);
+                (void) fclose(pf);
+                return(1);
+        }
+        else
+                return(0);
+}
+#endif
+ 
+/*
+ * dochq - change quote characters
+ *
+ */
+void dochq(argv, argc)
+register char *argv[];
+register int argc;
+{
+        if (argc > 2) {
+                if (*argv[2])
+                        lquote = *argv[2];
+                if (argc > 3) {
+                        if (*argv[3])
+                                rquote = *argv[3];
+                }
+                else
+                        rquote = lquote;
+        }
+        else {
+                lquote = LQUOTE;
+                rquote = RQUOTE;
+        }
+}
+ 
+/*
+ * dochc - change comment characters
+ *
+ */
+void dochc(argv, argc)
+register char *argv[];
+register int argc;
+{
+        if (argc > 2) {
+                if (*argv[2])
+                        scommt = *argv[2];
+                if (argc > 3) {
+                        if (*argv[3])
+                                ecommt = *argv[3];
+                }
+                else
+                        ecommt = ECOMMT;
+        }
+        else {
+                scommt = SCOMMT;
+                ecommt = ECOMMT;
+        }
+}
+ 
+/*
+ * dodivert - divert the output to a temporary file
+ *
+ */
+void dodiv(n)
+register int n;
+{
+        if (n < 0 || n >= MAXOUT)
+                n = 0;                  /* bitbucket */
+        if (outfile[n] == NULL) {
+                m4temp[UNIQUE] = n + '0';
+                if ((outfile[n] = fopen(m4temp, "w")) == NULL)
+                        error("m4: cannot divert.");
+        }
+        oindex = n;
+        active = outfile[n];
+}
+ 
+/*
+ * doundivert - undivert a specified output, or all
+ *              other outputs, in numerical order.
+ */
+void doundiv(argv, argc)
+register char *argv[];
+register int argc;
+{
+        register int ind;
+        register int n;
+ 
+        if (argc > 2) {
+                for (ind = 2; ind < argc; ind++) {
+                        n = atoi(argv[ind]);
+                        if (n > 0 && n < MAXOUT && outfile[n] != NULL)
+                                getdiv(n);
+ 
+                }
+        }
+        else
+                for (n = 1; n < MAXOUT; n++)
+                        if (outfile[n] != NULL)
+                                getdiv(n);
+}
+ 
+/*
+ * dosub - select substring
+ *
+ */
+void dosub (argv, argc)
+register char *argv[];
+register int  argc;
+{
+        register char *ap, *fc, *k;
+        register int nc;
+ 
+        if (argc < 5)
+                nc = MAXTOK;
+        else
+#ifdef EXPR
+                nc = expr(argv[4]);
+#else
+		nc = atoi(argv[4]);
+#endif
+        ap = argv[2];                   /* target string */
+#ifdef EXPR
+        fc = ap + expr(argv[3]);        /* first char */
+#else
+        fc = ap + atoi(argv[3]);        /* first char */
+#endif
+        if (fc >= ap && fc < ap+strlen(ap))
+                for (k = fc+min(nc,strlen(fc))-1; k >= fc; k--)
+                        putback(*k);
+}
+ 
+/*
+ * map:
+ * map every character of s1 that is specified in from
+ * into s3 and replace in s. (source s1 remains untouched)
+ *
+ * This is a standard implementation of map(s,from,to) function of ICON 
+ * language. Within mapvec, we replace every character of "from" with 
+ * the corresponding character in "to". If "to" is shorter than "from", 
+ * than the corresponding entries are null, which means that those 
+ * characters dissapear altogether. Furthermore, imagine 
+ * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case, 
+ * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s' 
+ * ultimately maps to `*'. In order to achieve this effect in an efficient 
+ * manner (i.e. without multiple passes over the destination string), we 
+ * loop over mapvec, starting with the initial source character. if the 
+ * character value (dch) in this location is different than the source 
+ * character (sch), sch becomes dch, once again to index into mapvec, until 
+ * the character value stabilizes (i.e. sch = dch, in other words 
+ * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary 
+ * character, it will stabilize, since mapvec[0] == 0 at all times. At the 
+ * end, we restore mapvec* back to normal where mapvec[n] == n for 
+ * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is 
+ * about 5 times faster than any algorithm that makes multiple passes over 
+ * destination string.
+ *
+ */
+     
+void map(dest,src,from,to)
+register char *dest;
+register char *src;
+register char *from;
+register char *to;
+{
+        register char *tmp;
+        register char sch, dch;
+        static char mapvec[128] = {
+                0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+                12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+                24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+                36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+                48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+                60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+                72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+                84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+                96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+                108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+                120, 121, 122, 123, 124, 125, 126, 127
+        };
+ 
+        if (*src) {
+                tmp = from;
+	/*
+	 * create a mapping between "from" and "to"
+	 */
+                while (*from)
+                        mapvec[*from++] = (*to) ? *to++ : (char) 0;
+     
+                while (*src) {
+                        sch = *src++;
+                        dch = mapvec[sch];
+                        while (dch != sch) {
+                                sch = dch;
+                                dch = mapvec[sch];
+                        }
+                        if (*dest = dch)
+                                dest++;
+                }
+	/*
+	 * restore all the changed characters
+	 */
+                while (*tmp) {
+                        mapvec[*tmp] = *tmp;
+                        tmp++;
+                }
+        }
+        *dest = (char) 0;
+}
Index: /trunk/minix/commands/make/Makefile
===================================================================
--- /trunk/minix/commands/make/Makefile	(revision 9)
+++ /trunk/minix/commands/make/Makefile	(revision 9)
@@ -0,0 +1,22 @@
+# Makefile for make (!)
+
+CFLAGS = -O -Dunix -D_MINIX -D_POSIX_SOURCE
+CC = exec cc
+
+OBJ =	check.o input.o macro.o main.o make.o reader.o rules.o archive.o
+
+all:	make
+
+make :	$(OBJ)
+	$(CC) -i -o make $(OBJ)
+	install -S 330k make
+
+install:	/usr/bin/make
+
+/usr/bin/make:	make
+	install -c -o bin make $@
+ 
+$(OBJ): h.h
+
+clean:
+	rm -f *.o *.bak core make
Index: /trunk/minix/commands/make/archive.c
===================================================================
--- /trunk/minix/commands/make/archive.c	(revision 9)
+++ /trunk/minix/commands/make/archive.c	(revision 9)
@@ -0,0 +1,309 @@
+/*	archive.c - archive support			Author: Kees J. Bot
+ *								13 Nov 1993
+ */
+#include "h.h"
+
+#ifdef unix
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+
+/* ASCII ar header. */
+
+#define ASCII_ARMAG	"!<arch>\n"
+#define ASCII_SARMAG	8
+#define ASCII_ARFMAG	"`\n"
+
+struct ascii_ar_hdr {
+	char	ar_name[16];
+	char	ar_date[12];
+	char	ar_uid[6];
+	char	ar_gid[6];
+	char	ar_mode[8];
+	char	ar_size[10];
+	char	ar_fmag[2];
+};
+
+/* ACK ar header. */
+
+#define	ACK_ARMAG	0177545
+#define ACK_AALMAG	0177454
+
+struct ack_ar_hdr {
+	char		ar_name[14];
+	unsigned long	ar_date;
+	unsigned char	ar_uid;
+	unsigned char	ar_gid;
+	unsigned short	ar_mode;
+	unsigned long	ar_size;
+};
+
+typedef struct archname {
+	struct archname	*next;		/* Next on the hash chain. */
+	char		name[16];	/* One archive entry. */
+	time_t		date;		/* The timestamp. */
+	/* (no need for other attibutes) */
+} archname_t;
+
+static size_t namelen;			/* Max name length, 14 or 16. */
+
+#define HASHSIZE	(64 << sizeof(int))
+
+static archname_t *nametab[HASHSIZE];
+
+_PROTOTYPE( static int hash, (char *name) );
+_PROTOTYPE( static int searchtab, (char *name, time_t *date, int scan) );
+_PROTOTYPE( static void deltab, (void) );
+_PROTOTYPE( static long ar_atol, (char *s, size_t n) );
+_PROTOTYPE( static int read_ascii_archive, (int afd) );
+_PROTOTYPE( static int read_ack_archive, (int afd) );
+
+static char *lpar, *rpar;	/* Leave these at '(' and ')'. */
+
+int is_archive_ref(name) char *name;
+/* True if name is of the form "archive(file)". */
+{
+  char *p = name;
+
+  while (*p != 0 && *p != '(' && *p != ')') p++;
+  lpar = p;
+  if (*p++ != '(') return 0;
+
+  while (*p != 0 && *p != '(' && *p != ')') p++;
+  rpar = p;
+  if (*p++ != ')') return 0;
+
+  return *p == 0;
+}
+
+static int hash(name) char *name;
+/* Compute a hash value out of a name. */
+{
+	unsigned h = 0;
+	unsigned char *p = (unsigned char *) name;
+	int n = namelen;
+
+	while (*p != 0) {
+		h = h * 0x1111 + *p++;
+		if (--n == 0) break;
+	}
+
+	return h % arraysize(nametab);
+}
+
+static int searchtab(name, date, scan) char *name; time_t *date; int scan;
+/* Enter a name to the table, or return the date of one already there. */
+{
+	archname_t **pnp, *np;
+	int cmp = 1;
+
+	pnp = &nametab[hash(name)];
+
+	while ((np = *pnp) != NULL
+			&& (cmp = strncmp(name, np->name, namelen)) > 0) {
+		pnp= &np->next;
+	}
+
+	if (cmp != 0) {
+		if (scan) {
+			errno = ENOENT;
+			return -1;
+		}
+		if ((np = (archname_t *) malloc(sizeof(*np))) == NULL)
+			fatal("No memory for archive name cache",(char *)0,0);
+		strncpy(np->name, name, namelen);
+		np->date = *date;
+		np->next = *pnp;
+		*pnp = np;
+	}
+	if (scan) *date = np->date;
+	return 0;
+}
+
+static void deltab()
+/* Delete the name cache, a different library is to be read. */
+{
+	archname_t **pnp, *np, *junk;
+
+	for (pnp = nametab; pnp < arraylimit(nametab); pnp++) {
+		for (np = *pnp; np != NULL; ) {
+			junk = np;
+			np = np->next;
+			free(junk);
+		}
+		*pnp = NULL;
+	}
+}
+
+static long ar_atol(s, n) char *s; size_t n;
+/* Transform a string into a number.  Ignore the space padding. */
+{
+  long l= 0;
+
+  while (n > 0) {
+	if (*s != ' ') l= l * 10 + (*s - '0');
+	s++;
+	n--;
+  }
+  return l;
+}
+
+static int read_ascii_archive(afd)
+int afd;
+/* Read a modern ASCII type archive. */
+{
+  struct ascii_ar_hdr hdr;
+  off_t pos= 8;
+  char *p;
+  time_t date;
+
+  namelen = 16;
+
+  for (;;) {
+	if (lseek(afd, pos, SEEK_SET) == -1) return -1;
+
+	switch (read(afd, &hdr, sizeof(hdr))) {
+	case sizeof(hdr):
+		break;
+	case -1:
+		return -1;
+	default:
+		return 0;
+	}
+
+	if (strncmp(hdr.ar_fmag, ASCII_ARFMAG, sizeof(hdr.ar_fmag)) != 0) {
+		errno= EINVAL;
+		return -1;
+	}
+
+	/* Strings are space padded! */
+	for (p= hdr.ar_name; p < hdr.ar_name + sizeof(hdr.ar_name); p++) {
+		if (*p == ' ') {
+			*p= 0;
+			break;
+		}
+	}
+
+	/* Add a file to the cache. */
+	date = ar_atol(hdr.ar_date, sizeof(hdr.ar_date));
+	searchtab(hdr.ar_name, &date, 0);
+
+	pos+= sizeof(hdr) + ar_atol(hdr.ar_size, sizeof(hdr.ar_size));
+	pos= (pos + 1) & (~ (off_t) 1);
+  }
+}
+
+static int read_ack_archive(afd)
+int afd;
+/* Read an ACK type archive. */
+{
+  unsigned char raw_hdr[14 + 4 + 1 + 1 + 2 + 4];
+  struct ack_ar_hdr hdr;
+  off_t pos= 2;
+  time_t date;
+
+  namelen = 14;
+
+  for (;;) {
+	if (lseek(afd, pos, SEEK_SET) == -1) return -1;
+
+	switch (read(afd, raw_hdr, sizeof(raw_hdr))) {
+	case sizeof(raw_hdr):
+		break;
+	case -1:
+		return -1;
+	default:
+		return 0;
+	}
+
+	/* Copy the useful fields from the raw bytes transforming PDP-11
+	 * style numbers to native format.
+	 */
+	memcpy(hdr.ar_name, raw_hdr + 0, 14);
+	hdr.ar_date=	  (long) raw_hdr[14 + 1] << 24
+			| (long) raw_hdr[14 + 0] << 16
+			| (long) raw_hdr[14 + 3] <<  8
+			| (long) raw_hdr[14 + 2] <<  0;
+	hdr.ar_size=	  (long) raw_hdr[22 + 1] << 24
+			| (long) raw_hdr[22 + 0] << 16
+			| (long) raw_hdr[22 + 3] <<  8
+			| (long) raw_hdr[22 + 2] <<  0;
+
+	/* Add a file to the cache. */
+	date = hdr.ar_date;
+	searchtab(hdr.ar_name, &date, 0);
+
+	pos= (pos + 26 + hdr.ar_size + 1) & (~ (off_t) 1);
+  }
+}
+
+int archive_stat(name, stp) char *name; struct stat *stp;
+/* Search an archive for a file and return that file's stat info. */
+{
+  int afd;
+  int r= -1;
+  char magic[8];
+  char *file;
+  static dev_t ardev;
+  static ino_t arino = 0;
+  static time_t armtime;
+
+  if (!is_archive_ref(name)) { errno = EINVAL; return -1; }
+  *lpar= 0;
+  *rpar= 0;
+  file= lpar + 1;
+
+  if (stat(name, stp) < 0) goto bail_out;
+
+  if (stp->st_ino != arino || stp->st_dev != ardev) {
+	/* Either the first (and probably only) library, or a different
+	 * library.
+	 */
+	arino = stp->st_ino;
+	ardev = stp->st_dev;
+	armtime = stp->st_mtime;
+	deltab();
+
+	if ((afd= open(name, O_RDONLY)) < 0) goto bail_out;
+
+	switch (read(afd, magic, sizeof(magic))) {
+	case 8:
+		if (strncmp(magic, ASCII_ARMAG, 8) == 0) {
+			r= read_ascii_archive(afd);
+			break;
+		}
+		if ((magic[0] & 0xFF) == ((ACK_AALMAG >> 0) & 0xFF)
+			&& (magic[1] & 0xFF) == ((ACK_AALMAG >> 8) & 0xFF)
+		) {
+			r= read_ack_archive(afd);
+			break;
+		}
+		/*FALL THROUGH*/
+	default:
+		errno = EINVAL;
+		/*FALL THROUGH*/
+	case -1:
+		/* r= -1 */;
+	}
+	{ int e= errno; close(afd); errno= e; }
+  } else {
+	/* Library is cached. */
+	r = 0;
+  }
+
+  if (r == 0) {
+	/* Search the cache. */
+	r = searchtab(file, &stp->st_mtime, 1);
+	if (stp->st_mtime > armtime) stp->st_mtime = armtime;
+  }
+
+bail_out:
+  /* Repair the name(file) thing. */
+  *lpar= '(';
+  *rpar= ')';
+  return r;
+}
+#endif
Index: /trunk/minix/commands/make/build
===================================================================
--- /trunk/minix/commands/make/build	(revision 9)
+++ /trunk/minix/commands/make/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/make/check.c
===================================================================
--- /trunk/minix/commands/make/check.c	(revision 9)
+++ /trunk/minix/commands/make/check.c	(revision 9)
@@ -0,0 +1,128 @@
+/*************************************************************************
+ *
+ *  m a k e :   c h e c k . c
+ *
+ *  debugging stuff: Check structures for make.
+ *========================================================================
+ * Edition history
+ *
+ *  #    Date                         Comments                       By
+ * --- -------- ---------------------------------------------------- ---
+ *   1    ??                                                         ??
+ *   2 23.08.89 adapted to new name tree structure                   RAL
+ *   3 30.08.89 indention changed                                    PSH,RAL
+ *   4 06.09.89 prt output redirected to stdout                      RAL
+ * ------------ Version 2.0 released ------------------------------- RAL
+ *
+ *************************************************************************/
+
+#include "h.h"
+
+
+/*
+ *	Prints out the structures as defined in memory.  Good for check
+ *	that you make file does what you want (and for debugging make).
+ */
+void prt()
+{
+  register struct name   *np;
+  register struct depend *dp;
+  register struct line   *lp;
+  register struct cmd    *cp;
+  register struct macro  *mp;
+
+  register int   		i;
+
+  for (mp = macrohead; mp; mp = mp->m_next)
+	printf("%s = %s\n", mp->m_name, mp->m_val);
+
+  putchar('\n');
+
+  for (i = 0; i <= maxsuffarray ; i++)
+	    for (np = suffparray[i]->n_next; np; np = np->n_next)
+	    {
+		if (np->n_flag & N_DOUBLE)
+			printf("%s::\n", np->n_name);
+		else
+			printf("%s:\n", np->n_name);
+		if (np == firstname)
+			printf("(MAIN NAME)\n");
+		for (lp = np->n_line; lp; lp = lp->l_next)
+		{
+			putchar(':');
+			for (dp = lp->l_dep; dp; dp = dp->d_next)
+				printf(" %s", dp->d_name->n_name);
+			putchar('\n');
+
+			for (cp = lp->l_cmd; cp; cp = cp->c_next)
+#ifdef os9
+				printf("-   %s\n", cp->c_cmd);
+#else
+				printf("-\t%s\n", cp->c_cmd);
+#endif
+			putchar('\n');
+		}
+		putchar('\n');
+	    }
+}
+
+
+/*
+ *	Recursive routine that does the actual checking.
+ */
+void check(np)
+struct name *np;
+{
+  register struct depend *dp;
+  register struct line   *lp;
+
+
+	if (np->n_flag & N_MARK)
+		fatal("Circular dependency from %s", np->n_name,0);
+
+	np->n_flag |= N_MARK;
+
+	for (lp = np->n_line; lp; lp = lp->l_next)
+		for (dp = lp->l_dep; dp; dp = dp->d_next)
+			check(dp->d_name);
+
+	np->n_flag &= ~N_MARK;
+}
+
+
+/*
+ *	Look for circular dependancies.
+ *	ie.
+ *		a: b
+ *		b: a
+ *	is a circular dep
+ */
+void circh()
+{
+  register struct name *np;
+  register int          i;
+
+
+  for (i = 0; i <= maxsuffarray ; i++)
+	   for (np = suffparray[i]->n_next; np; np = np->n_next)
+		check(np);
+}
+
+
+/*
+ *	Check the target .PRECIOUS, and mark its dependentd as precious
+ */
+void precious()
+{
+  register struct depend *dp;
+  register struct line   *lp;
+  register struct name   *np;
+
+
+  if (!((np = newname(".PRECIOUS"))->n_flag & N_TARG))
+	return;
+
+  for (lp = np->n_line; lp; lp = lp->l_next)
+	for (dp = lp->l_dep; dp; dp = dp->d_next)
+		dp->d_name->n_flag |= N_PREC;
+}
Index: /trunk/minix/commands/make/h.h
===================================================================
--- /trunk/minix/commands/make/h.h	(revision 9)
+++ /trunk/minix/commands/make/h.h	(revision 9)
@@ -0,0 +1,319 @@
+/*************************************************************************
+ *
+ *  m a k e :   h . h
+ *
+ *  include file for make
+ *========================================================================
+ * Edition history
+ *
+ *  #    Date                         Comments                       By
+ * --- -------- ---------------------------------------------------- ---
+ *   1    ??                                                         ??
+ *   2 23.08.89 LZ increased,N_EXISTS added,suffix as macro added    RAL
+ *   3 30.08.89 macro flags added, indention changed                 PSH,RAL
+ *   4 03.09.89 fixed LZ eliminated, struct str added,...            RAL
+ *   5 06.09.89 TABCHAR,M_MAKE added                                 RAL
+ *   6 09.09.89 tos support added, EXTERN,INIT,PARMS added           PHH,RAL
+ *   7 17.09.89 __STDC__ added, make1 decl. fixed , N_EXEC added     RAL
+ * ------------ Version 2.0 released ------------------------------- RAL
+ *
+ *************************************************************************/
+
+#ifdef unix
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <utime.h>
+#include <stdio.h>
+#include <limits.h>
+#endif
+
+#ifdef eon
+#include <sys/stat.h>
+#include <sys/err.h>
+#endif
+
+#ifdef os9
+#include <time.h>
+#include <os9.h>
+#include <modes.h>
+#include <direct.h>
+#include <errno.h>
+#endif
+
+#ifdef tos
+struct DOSTIME {short time,date; };     /* time structure of TOS */
+
+#ifdef LATTICE
+#include <error.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <osbind.h>
+#endif /* LATTICE */
+
+#ifdef TURBO
+#include <tos.h>
+#include <errno.h>
+#include <string.h>
+#endif /* TURBO */
+
+#endif /* tos */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <assert.h>
+
+#ifdef eon
+#define MNOENT ER_NOTF
+#else
+#define MNOENT ENOENT
+#endif
+
+#ifndef uchar
+#ifdef os9
+#define uchar  char
+#define void   int
+#define fputc  putc
+#else
+#define uchar  unsigned char
+#endif
+#endif
+
+#define bool   uchar
+#ifndef time_t
+#define time_t long
+#endif
+#define TRUE   (1)
+#define FALSE  (0)
+#define max(a,b) ((a)>(b)?(a):(b))
+
+#ifdef unix
+#define DEFN1   "makefile"
+#define DEFN2   "Makefile"
+#endif
+#ifdef eon
+#define DEFN1   "makefile"
+#define DEFN2   "Makefile"
+#endif
+#ifdef tos
+#define DEFN1   "makefile."
+#define DEFN2   (char *)0
+#endif
+#ifdef os9
+#define DEFN1   "makefile"
+#define DEFN2   (char *)0
+#endif
+
+
+#ifdef os9
+#define TABCHAR ' '
+#else
+#define TABCHAR '\t'
+#endif
+
+#define LZ1	(2048)		/*  Initial input/expand string size  */
+#define LZ2	(256)		/*  Initial input/expand string size  */
+
+
+
+/*
+ *	A name.  This represents a file, either to be made, or existant
+ */
+
+struct name
+{
+  struct name  *n_next;		/* Next in the list of names */
+  char         *n_name;		/* Called */
+  struct line  *n_line;		/* Dependencies */
+  time_t        n_time;		/* Modify time of this name */
+  uchar         n_flag;		/* Info about the name */
+};
+
+#define N_MARK    0x01			/* For cycle check */
+#define N_DONE    0x02			/* Name looked at */
+#define N_TARG    0x04			/* Name is a target */
+#define N_PREC    0x08			/* Target is precious */
+#define N_DOUBLE  0x10			/* Double colon target */
+#define N_EXISTS  0x20			/* File exists */
+#define N_ERROR   0x40			/* Error occured */
+#define N_EXEC    0x80			/* Commands executed */
+
+/*
+ *	Definition of a target line.
+ */
+struct	line
+{
+  struct line    *l_next;		/* Next line (for ::) */
+  struct depend  *l_dep;		/* Dependents for this line */
+  struct cmd     *l_cmd;		/* Commands for this line */
+};
+
+
+/*
+ *	List of dependents for a line
+ */
+struct	depend
+{
+  struct depend  *d_next;		/* Next dependent */
+  struct name    *d_name;		/* Name of dependent */
+};
+
+
+/*
+ *	Commands for a line
+ */
+struct	cmd
+{
+  struct cmd  *c_next;		/* Next command line */
+  char        *c_cmd;		/* Command line */
+};
+
+
+/*
+ *	Macro storage
+ */
+struct	macro
+{
+  struct macro *m_next;	/* Next variable */
+  char *m_name;		/* Called ... */
+  char *m_val;		/* Its value */
+  uchar m_flag;		/* Infinite loop check */
+};
+
+
+#define M_MARK		0x01	/* for infinite loop check */
+#define M_OVERRIDE	0x02	/* command-line override */
+#define M_MAKE		0x04	/* for MAKE macro */
+
+/*
+ *	String
+ */
+struct	str
+{
+  char **ptr;		/* ptr to real ptr. to string */
+  int    len;		/* length of string */
+  int    pos;		/* position */
+};
+
+
+/* Declaration, definition & initialization of variables */
+
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+#ifndef INIT
+#define INIT(x)
+#endif
+
+extern int    errno;
+extern char **environ;
+
+EXTERN char *myname;
+EXTERN bool  domake   INIT(TRUE);  /*  Go through the motions option  */
+EXTERN bool  ignore   INIT(FALSE); /*  Ignore exit status option      */
+EXTERN bool  conterr  INIT(FALSE); /*  continue on errors  */
+EXTERN bool  silent   INIT(FALSE); /*  Silent option  */
+EXTERN bool  print    INIT(FALSE); /*  Print debuging information  */
+EXTERN bool  rules    INIT(TRUE);  /*  Use inbuilt rules  */
+EXTERN bool  dotouch  INIT(FALSE); /*  Touch files instead of making  */
+EXTERN bool  quest    INIT(FALSE); /*  Question up-to-dateness of file  */
+EXTERN bool  useenv   INIT(FALSE); /*  Env. macro def. overwrite makefile def.*/
+EXTERN bool  dbginfo  INIT(FALSE); /*  Print lot of debugging information */
+EXTERN bool  ambigmac INIT(TRUE);  /*  guess undef. ambiguous macros (*,<) */
+EXTERN struct name  *firstname;
+EXTERN char         *str1;
+EXTERN char         *str2;
+EXTERN struct str    str1s;
+EXTERN struct str    str2s;
+EXTERN struct name **suffparray; /* ptr. to array of ptrs. to name chains */
+EXTERN int           sizesuffarray INIT(20); /* size of suffarray */
+EXTERN int           maxsuffarray INIT(0);   /* last used entry in suffarray */
+EXTERN struct macro *macrohead;
+EXTERN bool          expmake; /* TRUE if $(MAKE) has been expanded */
+EXTERN char	    *makefile;     /*  The make file  */
+EXTERN int           lineno;
+
+#ifdef tos
+#ifdef LATTICE
+EXTERN int _mneed INIT(60000);    /* VERY important for TOS with LATTICE C*/
+#endif /* LATTICE */
+#endif /* tos */
+#ifdef eon
+#define MEMSPACE  (16384)
+EXTERN unsigned  memspace = MEMSPACE;
+#endif
+
+#define  suffix(name)   strrchr(name,(int)'.')
+
+EXTERN int _ctypech;
+#define mylower(x)  (islower(_ctypech=(x)) ? _ctypech :tolower(_ctypech))
+#define myupper(x)  (isupper(_ctypech=(x)) ? _ctypech :toupper(_ctypech))
+
+/* Prototypes. */
+struct sgtbuf;
+
+/* check.c */
+_PROTOTYPE(void prt, (void));
+_PROTOTYPE(void check, (struct name *np ));
+_PROTOTYPE(void circh, (void));
+_PROTOTYPE(void precious, (void));
+
+/* input.c */
+_PROTOTYPE(void init, (void));
+_PROTOTYPE(void strrealloc, (struct str *strs ));
+_PROTOTYPE(struct name *newname, (char *name ));
+_PROTOTYPE(struct name *testname, (char *name ));
+_PROTOTYPE(struct depend *newdep, (struct name *np, struct depend *dp ));
+_PROTOTYPE(struct cmd *newcmd, (char *str, struct cmd *cp ));
+_PROTOTYPE(void newline, (struct name *np, struct depend *dp, struct cmd *cp, 
+								   int flag ));
+_PROTOTYPE(void input, (FILE *fd ));
+
+/* macro.c */
+_PROTOTYPE(struct macro *getmp, (char *name ));
+_PROTOTYPE(char *getmacro, (char *name ));
+_PROTOTYPE(struct macro *setmacro, (char *name, char *val ));
+_PROTOTYPE(void setDFmacro, (char *name, char *val ));
+_PROTOTYPE(void doexp, (struct str *to, char *from ));
+_PROTOTYPE(void expand, (struct str *strs ));
+
+/* main.c */
+_PROTOTYPE(void main, (int argc, char **argv ));
+_PROTOTYPE(void setoption, (char option ));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(void fatal, (char *msg, char *a1, int a2 ));
+
+/* make.c */
+_PROTOTYPE(int dosh, (char *string, char *shell ));
+_PROTOTYPE(int makeold, (char *name ));
+_PROTOTYPE(void docmds1, (struct name *np, struct line *lp ));
+_PROTOTYPE(void docmds, (struct name *np ));
+_PROTOTYPE(int Tosexec, (char *string ));
+_PROTOTYPE(time_t mstonix, (unsigned int date, unsigned int time ));
+_PROTOTYPE(void getmdate, (int fd, struct sgtbuf *tbp ));
+_PROTOTYPE(time_t cnvtime, (struct sgtbuf *tbp ));
+_PROTOTYPE(void modtime, (struct name *np ));
+_PROTOTYPE(void touch, (struct name *np ));
+_PROTOTYPE(int make, (struct name *np, int level ));
+_PROTOTYPE(void make1, (struct name *np, struct line *lp, struct depend *qdp, 
+					char *basename, char *inputname ));
+_PROTOTYPE(void implmacros, (struct name *np, struct line *lp, 
+					char **pbasename, char **pinputname ));
+_PROTOTYPE(void dbgprint, (int level, struct name *np, char *comment ));
+
+/* reader.c */
+_PROTOTYPE(void error, (char *msg, char *a1 ));
+_PROTOTYPE(bool getline, (struct str *strs, FILE *fd ));
+_PROTOTYPE(char *gettok, (char **ptr ));
+
+/* rules.c */
+_PROTOTYPE(bool dyndep, (struct name *np, char **pbasename,char **pinputname));
+_PROTOTYPE(void makerules, (void));
+
+/* archive.c */
+_PROTOTYPE(int is_archive_ref, (char *name));
+_PROTOTYPE(int archive_stat, (char *name, struct stat *stp));
Index: /trunk/minix/commands/make/input.c
===================================================================
--- /trunk/minix/commands/make/input.c	(revision 9)
+++ /trunk/minix/commands/make/input.c	(revision 9)
@@ -0,0 +1,439 @@
+/*************************************************************************
+ *
+ *  m a k e :   i n p u t . c
+ *
+ *  Parse a makefile
+ *========================================================================
+ * Edition history
+ *
+ *  #    Date                         Comments                       By
+ * --- -------- ---------------------------------------------------- ---
+ *   1    ??                                                         ??
+ *   2 23.08.89 new name tree structure introduced to speed up make,
+ *              testname introduced to shrink the memory usage       RAL
+ *   3 30.08.89 indention changed                                    PSH,RAL
+ *   4 03.09.89 fixed LZ eliminated                                  RAL
+ *   5 06.09.89 ; command added                                      RAL
+ * ------------ Version 2.0 released ------------------------------- RAL
+ *
+ *************************************************************************/
+
+
+#include "h.h"
+
+
+static struct name *lastrrp;
+static struct name *freerp = (struct name *)NULL;
+
+void init()
+{
+  if( (suffparray = (struct name **) malloc( sizesuffarray *
+           sizeof(struct name *)))  == (struct name **) NULL)
+     fatal("No memory for suffarray",(char *)0,0);
+  if ((*suffparray = (struct name *)malloc(sizeof (struct name)))
+                          == (struct name *)0)
+     fatal("No memory for name",(char *)0,0);
+  (*suffparray)->n_next = (struct name *)0;
+
+  if ((str1 = (char *) malloc(LZ1)) == ((char *)0))
+     fatal("No memory for str1",(char *)0,0);
+  str1s.ptr = &str1;
+  str1s.len = LZ1;
+  if ((str2 = (char *) malloc(LZ2)) == (char *)0)
+     fatal("No memory for str2",(char *)0,0);
+  str2s.ptr = &str2;
+  str2s.len = LZ2;
+}
+
+void strrealloc(strs)
+struct str *strs;
+{
+  strs->len *= 2;
+  *strs->ptr = (char *) realloc(*strs->ptr, strs->len + 16);
+  if(*strs->ptr == (char *) NULL)
+       fatal("No memory for string reallocation",(char *)0,0);
+}
+
+/*
+ *	Intern a name.  Return a pointer to the name struct
+ */
+struct name *newname(name)
+char *name;
+{
+  register struct name *rp;
+  register struct name *rrp;
+  register char        *cp;
+
+  register int           i;
+  register char         *suff;   /* ptr. to suffix in current name */
+  register struct name **sp;     /* ptr. to ptr. to chain of names */
+
+  if ( (suff = suffix(name)) != (char *)NULL) {
+     for (i = 1, sp = suffparray, sp++;
+          i <= maxsuffarray && strcmp(suff, (*sp)->n_name) != 0;
+          sp++,i++);
+     if (i > maxsuffarray) {
+        if ( i >= sizesuffarray) { /* must realloc suffarray */
+           sizesuffarray *= 2;
+           if( (suffparray = (struct name **) realloc((char *) suffparray,
+                sizesuffarray * sizeof(struct name *))) == (struct name **) NULL)
+              fatal("No memory for suffarray",(char *)0,0);
+        }
+        maxsuffarray++;
+        sp = &suffparray[i];
+        if ((*sp = (struct name *)malloc(sizeof (struct name)))
+                                   == (struct name *)0)
+           fatal("No memory for name",(char *)0,0);
+        (*sp)->n_next = (struct name *)0;
+        if ((cp = (char *) malloc(strlen(suff)+1)) == (char *)0)
+           fatal("No memory for name",(char *)0,0);
+        strcpy(cp, suff);
+        (*sp)->n_name = cp;
+     }
+  }
+  else
+     sp = suffparray;
+
+  for ( rp = (*sp)->n_next, rrp = *sp; rp; rp = rp->n_next, rrp = rrp->n_next )
+     if (strcmp(name, rp->n_name) == 0)  return rp;
+
+  if ( freerp ==  (struct name *)NULL) {
+     if ((rp = (struct name *)malloc(sizeof (struct name))) == (struct name *)0)
+        fatal("No memory for name",(char *)0,0);
+  }
+  else  {
+     rp = freerp;
+     freerp =  (struct name *)NULL;
+  }
+  rrp->n_next = rp;
+  rp->n_next = (struct name *)0;
+  if ((cp = (char *) malloc(strlen(name)+1)) == (char *)0)
+     fatal("No memory for name",(char *)0,0);
+  strcpy(cp, name);
+  rp->n_name = cp;
+  rp->n_line = (struct line *)0;
+  rp->n_time = (time_t)0;
+  rp->n_flag = 0;
+  lastrrp = rrp;
+
+  return rp;
+}
+
+/*
+ *     Test a name.
+ *     If the name already exists return the ptr. to its name structure.
+ *     Else if the file exists 'intern' the name and return the ptr.
+ *     Otherwise don't waste memory and return a NULL pointer
+ */
+struct name *testname(name)
+char *name;
+{
+  register struct name *rp;
+
+  lastrrp = (struct name *)NULL;
+  rp = newname( name);
+  if (rp->n_line || rp->n_flag & N_EXISTS)
+     return(rp);
+  modtime(rp);
+  if (rp->n_flag & N_EXISTS)
+     return(rp);
+  if (lastrrp != (struct name *)NULL) {
+     free (rp->n_name);
+     lastrrp->n_next = (struct name *)NULL;
+     freerp = rp;
+  }
+  return((struct name *)NULL);
+}
+
+
+
+/*
+ *	Add a dependant to the end of the supplied list of dependants.
+ *	Return the new head pointer for that list.
+ */
+struct depend *newdep(np, dp)
+struct name   *np;
+struct depend *dp;
+{
+  register struct depend *rp;
+  register struct depend *rrp;
+
+
+  if ((rp = (struct depend *)malloc(sizeof (struct depend)))
+          == (struct depend *)0)
+	fatal("No memory for dependant",(char *)0,0);
+  rp->d_next = (struct depend *)0;
+  rp->d_name = np;
+
+  if (dp == (struct depend *)0)  return rp;
+
+  for (rrp = dp; rrp->d_next; rrp = rrp->d_next) ;
+
+  rrp->d_next = rp;
+
+  return dp;
+}
+
+
+/*
+ *	Add a command to the end of the supplied list of commands.
+ *	Return the new head pointer for that list.
+ */
+struct cmd *newcmd(str, cp)
+char       *str;
+struct cmd *cp;
+{
+  register struct cmd *rp;
+  register struct cmd *rrp;
+  register char       *rcp;
+
+
+  if (rcp = strrchr(str, '\n'))  *rcp = '\0';	/*  Loose newline  */
+
+  while (isspace(*str))  str++;
+
+  if (*str == '\0')  return cp;		/*  If nothing left, the exit  */
+
+  if ((rp = (struct cmd *)malloc(sizeof (struct cmd))) == (struct cmd *)0)
+	fatal("No memory for command",(char *)0,0);
+  rp->c_next = (struct cmd *)0;
+  if ((rcp = (char *) malloc(strlen(str)+1)) == (char *)0)
+	fatal("No memory for command",(char *)0,0);
+  strcpy(rcp, str);
+  rp->c_cmd = rcp;
+
+  if (cp == (struct cmd *)0)  return rp;
+
+  for (rrp = cp; rrp->c_next; rrp = rrp->c_next) ;
+
+  rrp->c_next = rp;
+
+  return cp;
+}
+
+
+/*
+ *	Add a new 'line' of stuff to a target.  This check to see
+ *	if commands already exist for the target.  If flag is set,
+ *	the line is a double colon target.
+ *
+ *	Kludges:
+ *	i)  If the new name begins with a '.', and there are no dependents,
+ *	    then the target must cease to be a target.  This is for .SUFFIXES.
+ *	ii) If the new name begins with a '.', with no dependents and has
+ *	    commands, then replace the current commands.  This is for
+ *	    redefining commands for a default rule.
+ *	Neither of these free the space used by dependents or commands,
+ *	since they could be used by another target.
+ */
+
+void newline(np, dp, cp, flag)
+struct name   *np;
+struct depend *dp;
+struct cmd    *cp;
+int            flag;
+{
+  bool                  hascmds = FALSE;  /*  Target has commands  */
+  register struct line *rp;
+  register struct line *rrp;
+
+
+  /* Handle the .SUFFIXES case */
+  if (np->n_name[0] == '.' && !dp && !cp) {
+	for (rp = np->n_line; rp; rp = rrp) {
+		rrp = rp->l_next;
+		free(rp);
+	}
+	np->n_line = (struct line *)0;
+	np->n_flag &= ~N_TARG;
+	return;
+  }
+
+  /* This loop must happen since rrp is used later. */
+  for ( rp = np->n_line, rrp = (struct line *)0; rp; rrp = rp, rp = rp->l_next)
+	if (rp->l_cmd)  hascmds = TRUE;
+
+  if (hascmds && cp && !(np->n_flag & N_DOUBLE))
+	/* Handle the implicit rules redefinition case */
+	if (np->n_name[0] == '.' && dp == (struct depend *)0) {
+		np->n_line->l_cmd = cp;
+		return;
+	}
+	else
+		error("Commands defined twice for target %s", np->n_name);
+  if (np->n_flag & N_TARG)
+	if (!(np->n_flag & N_DOUBLE) != !flag)		/* like xor */
+		error("Inconsistent rules for target %s", np->n_name);
+
+  if ((rp = (struct line *)malloc(sizeof (struct line))) == (struct line *)0)
+	fatal("No memory for line",(char *)0,0);
+  rp->l_next = (struct line *)0;
+  rp->l_dep = dp;
+  rp->l_cmd = cp;
+
+  if (rrp)
+         rrp->l_next = rp;
+  else
+         np->n_line = rp;
+
+  np->n_flag |= N_TARG;
+  if (flag)  np->n_flag |= N_DOUBLE;
+}
+
+
+/*
+ *	Parse input from the makefile, and construct a tree structure
+ *	of it.
+ */
+void input(fd)
+FILE *fd;
+{
+  char          *p;		/*  General  */
+  char          *q;
+  register char *a;
+  struct name   *np;
+  struct depend *dp;
+  struct cmd    *cp;
+  bool dbl;
+
+
+  if (getline(&str1s, fd))  return;	/*  Read the first line  */
+
+  for(;;) {
+	if (*str1 == TABCHAR)	/*  Rules without targets  */
+		error("Rules not allowed here",(char *)0);
+
+	p = str1;
+
+	while (isspace(*p))  p++;	/*  Find first target  */
+
+
+	while (((q = strchr(p, '=')) != (char *)0) &&
+	    (p != q) && (q[-1] == '\\'))	/*  Find value */
+	{
+		a = q - 1;	/*  Del \ chr; move rest back  */
+		p = q;
+		while(*a++ = *q++)
+			;
+	}
+
+	if (q != (char *)0) {
+
+		*q++ = '\0';		/*  Separate name and val  */
+		while (isspace(*q))
+			q++;
+		if (p = strrchr(q, '\n'))
+			*p = '\0';
+
+		p = str1;
+		if ((a = gettok(&p)) == (char *)0)
+			error("No macro name",(char *)0);
+
+		setmacro(a, q);
+
+		if (getline(&str1s, fd))
+			return;
+		continue;
+	}
+
+	/* include? */
+	p = str1;
+	while (isspace(*p)) p++;
+	if (strncmp(p, "include", 7) == 0 && isspace(p[7])) {
+		char *old_makefile = makefile;
+		int old_lineno = lineno;
+		FILE *ifd;
+
+		p += 8;
+		memmove(str1, p, strlen(p)+1);
+		expand(&str1s);
+		p = str1;
+		while (isspace(*p)) p++;
+
+		if ((q = malloc(strlen(p)+1)) == (char *)0)
+			fatal("No memory for include",(char *)0,0);
+
+		strcpy(q, p);
+		p = q;
+		while ((makefile = gettok(&q)) != (char *)0) {
+			if ((ifd = fopen(makefile, "r")) == (FILE *)0)
+				fatal("Can't open %s: %s", makefile, errno);
+			lineno = 0;
+			input(ifd);
+			fclose(ifd);
+		}
+		free(p);
+		makefile = old_makefile;
+		lineno = old_lineno;
+
+		if (getline(&str1s, fd))
+			return;
+		continue;
+	}
+
+	/* Search for commands on target line --- do not expand them ! */
+	q = str1;
+	cp = (struct cmd *)0;
+	if ((a = strchr(q, ';')) != (char *)0) {
+		*a++ = '\0';	/*  Separate dependents and commands */
+		if ( a) cp = newcmd(a, cp);
+	}
+
+	expand(&str1s);
+	p = str1;
+
+	while (isspace(*p)) p++;
+
+	while (((q = strchr(p, ':')) != (char *)0) &&
+	    (p != q) && (q[-1] == '\\'))	/*  Find dependents  */
+	{
+		a = q - 1;	/*  Del \ chr; move rest back  */
+		p = q;
+		while(*a++ = *q++) ;
+	}
+
+	if (q == (char *)0)
+		error("No targets provided",(char *)0);
+
+	*q++ = '\0';	/*  Separate targets and dependents  */
+
+	if (*q == ':') {		/* Double colon */
+		dbl = 1;
+		q++;
+	}
+	else
+		dbl = 0;
+
+	for (dp = (struct depend *)0; ((p = gettok(&q)) != (char *)0);)
+				/*  get list of dep's */
+	{
+		np = newname(p);		/*  Intern name  */
+		dp = newdep(np, dp);		/*  Add to dep list */
+	}
+
+	*((q = str1) + strlen(str1) + 1) = '\0';
+		/*  Need two nulls for gettok (Remember separation)  */
+
+	if (getline(&str2s, fd) == FALSE) {		/*  Get commands  */
+		while (*str2 == TABCHAR) {
+			cp = newcmd(&str2[0], cp);
+			if (getline(&str2s, fd))
+				break;
+		}
+	}
+
+	while ((p = gettok(&q)) != (char *)0)	/* Get list of targ's */
+	{
+		np = newname(p);		/*  Intern name  */
+		newline(np, dp, cp, dbl);
+		if (!firstname && p[0] != '.')
+			firstname = np;
+	}
+
+	if (feof(fd))				/*  EOF?  */
+		return;
+
+	while (strlen(str2) >= str1s.len) strrealloc(&str1s);
+	strcpy(str1, str2);
+  }
+}
Index: /trunk/minix/commands/make/macro.c
===================================================================
--- /trunk/minix/commands/make/macro.c	(revision 9)
+++ /trunk/minix/commands/make/macro.c	(revision 9)
@@ -0,0 +1,197 @@
+/*************************************************************************
+ *
+ *  m a k e :   m a c r o . c
+ *
+ *  Macro control for make
+ *========================================================================
+ * Edition history
+ *
+ *  #    Date                         Comments                       By
+ * --- -------- ---------------------------------------------------- ---
+ *   1    ??                                                         ??
+ *   2 23.08.89 Error message corrected                              RAL
+ *   3 30.08.89 macro flags added, indention ch.                     PSH,RAL
+ *   4 03.09.89 fixed LZ eliminated, doexp(...) changed              RAL
+ *   5 06.09.89 M_MAKE added, setDFmacro added                       RAL
+ *   6 20.09.89 work around for Minix PC ACK bug                     BE,RAL
+ * ------------ Version 2.0 released ------------------------------- RAL
+ *
+ *************************************************************************/
+
+#include "h.h"
+
+
+static char   buf[256];
+
+struct macro *getmp(name)
+char *name;
+{
+  register struct macro *rp;
+
+  for (rp = macrohead; rp; rp = rp->m_next)
+		if (strcmp(name, rp->m_name) == 0)
+			return rp;
+  return (struct macro *)0;
+}
+
+
+char *getmacro(name)
+char *name;
+{
+  struct macro *mp;
+
+  if (mp = getmp(name))
+		return mp->m_val;
+/*	else*/
+		return "";
+}
+
+
+struct macro *setmacro(name, val)
+char *name;
+char *val;
+{
+  register struct macro *rp;
+  register char         *cp;
+
+
+		/*  Replace macro definition if it exists  */
+  for (rp = macrohead; rp; rp = rp->m_next)
+	if (strcmp(name, rp->m_name) == 0) {
+		if(rp->m_flag & M_OVERRIDE) return rp;	/* mustn't change */
+		free(rp->m_val);	/*  Free space from old  */
+		break;
+		}
+
+	if (!rp)		/*  If not defined, allocate space for new  */
+	{
+		if ((rp = (struct macro *)malloc(sizeof (struct macro)))
+					 == (struct macro *)0)
+			fatal("No memory for macro",(char *)0,0);
+
+		rp->m_next = macrohead;
+		macrohead = rp;
+		rp->m_flag = FALSE;
+
+		if ((cp = (char *) malloc(strlen(name)+1)) == (char *)0)
+			fatal("No memory for macro",(char *)0,0);
+		strcpy(cp, name);
+		rp->m_name = cp;
+	}
+
+	if ((cp = (char *) malloc(strlen(val)+1)) == (char *)0)
+		fatal("No memory for macro",(char *)0,0);
+	strcpy(cp, val);		/*  Copy in new value  */
+	rp->m_val = cp;
+
+  return rp;
+}
+
+
+void setDFmacro(name, val)
+char *name;
+char *val;
+{
+  char        *c,*tmp;
+  int          len;
+  static char  filename[]="@F";
+  static char  dirname[] ="@D";
+
+  setmacro(name,val);
+  *filename = *name;
+  *dirname  = *name;
+  /* Null string -- not defined macro */
+  if ( !(*val)) {
+     setmacro(filename,"");
+     setmacro(dirname,"");
+     return;
+  }
+  if (!(c = strrchr(val,(int)'/'))) {
+     setmacro(filename,val);
+     setmacro(dirname,"./");
+     return;
+  }
+  setmacro(filename,c+1);
+  len = c - val + 1;
+  if((tmp = (char *) malloc(len + 1)) == (char *) 0)
+     fatal("No memory for tmp",(char *)0,0);
+  strncpy(tmp,val,len);
+  tmp[len] = '\0';
+  setmacro(dirname,tmp);
+  free(tmp);
+  return;
+}
+
+/*
+ *	Do the dirty work for expand
+ */
+void doexp(to, from)
+struct str *to;
+char  *from;
+{
+  register char *rp;
+  register char *p;
+  char *q;
+  struct macro *mp;
+
+
+  rp = from;
+  p  = &(*to->ptr)[to->pos];
+  while (*rp) {
+	if (*rp != '$') {
+		*p++ = *rp++;
+		to->pos++;
+	}
+	else {
+		q = buf;
+		if (*++rp == '{')
+			while (*++rp && *rp != '}')
+				*q++ = *rp;
+		else if (*rp == '(')
+			while (*++rp && *rp != ')')
+				*q++ = *rp;
+		else if (!*rp) {
+			*p++ = '$';
+			to->pos++;
+			goto bail;
+		}
+		else
+			*q++ = *rp;
+		*q = '\0';
+		if (*rp)
+			rp++;
+		if (!(mp = getmp(buf)))
+			mp = setmacro(buf, "");
+		if (mp->m_flag & M_MARK)
+			fatal("Infinitely recursive macro %s", mp->m_name,0);
+		mp->m_flag |= M_MARK;
+		if ( mp->m_flag & M_MAKE) expmake = TRUE;
+		doexp(to, mp->m_val);
+		p = &(*to->ptr)[to->pos];
+		mp->m_flag &= ~M_MARK;
+	}
+  bail:
+	if (to->pos >= to->len) {
+		strrealloc(to);
+		p = &(*to->ptr)[to->pos];
+	}
+  }
+  *p = '\0';
+}
+
+
+/*
+ *	Expand any macros in str.
+ */
+void expand(strs)
+struct str *strs;
+{
+  char  *a;
+
+  if ((a = (char *) malloc(strlen(*strs->ptr)+1)) == (char *)0)
+     fatal("No memory for temporary string",(char *)0,0);
+  strcpy(a, *strs->ptr);
+  strs->pos = 0;
+  doexp(strs, a);
+  free(a);
+}
Index: /trunk/minix/commands/make/main.c
===================================================================
--- /trunk/minix/commands/make/main.c	(revision 9)
+++ /trunk/minix/commands/make/main.c	(revision 9)
@@ -0,0 +1,288 @@
+/*************************************************************************
+ *
+ *  m a k e :   m a i n . c
+ *
+ *========================================================================
+ * Edition history
+ *
+ *  #    Date                         Comments                       By
+ * --- -------- ---------------------------------------------------- ---
+ *   1    ??                                                         ??
+ *   2 01.07.89 strcmp(makefile,..) only if makefile a valid ptr.    RAL
+ *   3 23.08.89 initname() added                                     RAL
+ *   4 30.08.89 argument parsing impr., indention ch., macro fl. add.PSH,RAL
+ *   5 03.09.89 k-option added, initname -> init changed             RAL
+ *   6 06.09.89 environment, MAKEFLAGS, e,d,a options added,         RAL
+ *   7 09.09.89 tos support added, fatal args added, fopen makefile  PHH,RAL
+ *   8 17.09.89 setoptions fixed for __STDC__                        RAL
+ * ------------ Version 2.0 released ------------------------------- RAL
+ *
+ *************************************************************************/
+
+/*
+ *	make:
+ *
+ *	-a try to guess undefined ambiguous macros (*,<)
+ *	-d print debugging info
+ *	-e environment macro def. overwrite makefile def.
+ *	-f makefile name
+ *	-i ignore exit status
+ *	-k continue on errors
+ *	-n pretend to make
+ *	-p print all macros & targets
+ *	-q question up-to-dateness of target.  Return exit status 1 if not
+ *	-r don't not use inbuilt rules
+ *	-s make silently
+ *	-t touch files instead of making them
+ *	-m Change memory requirements (EON only)
+ */
+
+#define EXTERN
+#define INIT(x) = x
+#define INITARRAY
+#include "h.h"
+
+static char version[]= "2.0";
+
+static FILE *ifd;           /*  Input file desciptor  */
+static char *ptrmakeflags;
+
+/* There must be enough 'space' for all possible flags ! */
+static char  makeflags[] = "MAKEFLAGS=                    ";
+
+void main(argc, argv)
+int    argc;
+char **argv;
+{
+  register char        *p;		/*  For argument processing  */
+  int                   estat = 0;	/*  For question  */
+  register struct name *np;
+  struct macro         *mp;
+  int                   targc;		/* temporary for multiple scans */
+  char                **targv;
+  char                **nargv;		/* for removing items from argv */
+  char                **envp;      /* enivironment ptr */
+
+
+  ptrmakeflags = &makeflags[10];
+  myname = (argc-- < 1) ? "make" : *argv++;
+#ifdef tos
+  myname = "Make";
+#endif
+
+  targc = argc;
+  targv = nargv = argv;
+  while (targc--) {
+	if((p = strchr(*targv, '=')) != (char *)NULL) {
+		*p = '\0';
+		mp = setmacro(*targv, p + 1);
+		mp->m_flag |= M_OVERRIDE;
+		--argc;
+	} else
+		*nargv++ = *targv;
+
+	++targv;
+  }
+
+  targc = argc;
+  targv = nargv = argv;
+  while (targc--) {
+	if (**targv == '-') {
+		--argc;
+		p = *targv++;
+		while (*++p != '\0') {
+			switch(mylower(*p)) {
+			case 'f':	/*  Alternate file name  */
+				if (*++p == '\0') {
+					--argc;
+					if (targc-- == 0)
+						usage();
+					p = *targv++;
+				}
+				makefile = p;
+				goto end_of_args;
+#ifdef eon
+			case 'm':	/*  Change space requirements  */
+				if (*++p == '\0') {
+					--argc;
+					if (targc-- <= 0)
+						usage();
+					p = *targv++;
+				}
+				memspace = atoi(p);
+				goto end_of_args;
+#endif
+			default :
+				setoption(*p);
+				break;
+			}
+		}
+	end_of_args:;
+	} else
+		*nargv++ = *targv++;
+  }
+
+  /* evaluate and update environment MAKEFLAGS */
+  if((p =getenv("MAKEFLAGS")) != (char *)0)
+	while(*p) setoption(*p++);
+  for( p = ptrmakeflags; !isspace((int)*p); p++) ;
+  *p = '\0';
+  putenv(makeflags);
+
+
+#ifdef eon
+  if (initalloc(memspace) == 0xffff)  /*  Must get memory for alloc  */
+	fatal("Cannot initalloc memory",(char *)0,0);
+#endif
+
+  if (makefile && strcmp(makefile, "-") == 0)  /*   use stdin as makefile  */
+	ifd = stdin;
+  else if (!makefile) {    /*  If no file, then use default */
+	if ((ifd = fopen(makefile = DEFN1, "r")) == (FILE *)0) {
+		if (errno != MNOENT || !DEFN2)
+			fatal("Can't open %s: %s", DEFN1, errno);
+		else if ((ifd = fopen(makefile = DEFN2, "r")) == (FILE *)0)
+			fatal("Can't open %s: %s", DEFN2, errno);
+	}
+  }
+  else if ((ifd = fopen(makefile, "r")) == (FILE *)0)
+	fatal("Can't open %s: %s", makefile, errno);
+
+  init();
+
+  makerules();
+
+  mp = setmacro("MAKE", myname);
+  mp->m_flag |= M_MAKE;
+  setmacro("$", "$");
+
+  /* set environment macros */
+  envp = environ; /* get actual environment ptr. */
+  while (*envp) {
+	if((p = strchr(*envp, '=')) != (char *)NULL) {
+		*p = '\0';
+		mp = setmacro(*envp, p + 1);
+		*p = '=';
+		if (useenv) mp->m_flag |= M_OVERRIDE;
+	} else
+		fatal("invalid environment: %s",*envp,0);
+
+	++envp;
+  }
+
+  input(ifd);	/*  Input all the gunga  */
+  fclose(ifd);	/*  Finished with makefile  */
+  lineno = 0;	/*  Any calls to error now print no line number */
+
+  if (print)
+	prt();	/*  Print out structures  */
+
+  np = newname(".SILENT");
+  if (np->n_flag & N_TARG)  silent = TRUE;
+
+  np = newname(".IGNORE");
+  if (np->n_flag & N_TARG)  ignore = TRUE;
+
+  precious();
+
+  if (!firstname)
+	fatal("No targets defined",(char *)0,0);
+
+  circh();	/*  Check circles in target definitions  */
+
+  if (!argc)
+	estat = make(firstname, 0);
+  else
+	while (argc--) {
+		estat |= make(newname(*argv++), 0);
+	}
+
+  if (quest)
+	exit(estat);
+  else
+		exit(0);
+}
+
+#ifdef __STDC__
+void setoption(char option)
+#else
+void setoption(option)
+char option;
+#endif
+{
+  register char *c;
+
+  option = mylower(option);
+  switch(option) {
+	case 'n':	/*  Pretend mode  */
+		domake = FALSE;
+		break;
+	case 'i':	/*  Ignore fault mode  */
+		ignore = TRUE;
+		break;
+	case 'k':	/*  Continue on errror  */
+		conterr = TRUE;
+		break;
+	case 's':	/*  Silent about commands  */
+		silent = TRUE;
+		break;
+	case 'p':
+		print = TRUE;
+		break;
+	case 'r':
+		rules = FALSE;
+		break;
+	case 't':
+		dotouch = TRUE;
+		break;
+	case 'q':
+		quest = TRUE;
+		break;
+	case 'e':
+		useenv = TRUE;
+		break;
+	case 'd':
+		dbginfo = TRUE;
+		break;
+	case 'a':
+		ambigmac = TRUE;
+		break;
+	default:	/*  Wrong option  */
+		usage();
+  }
+  for( c = ptrmakeflags; !isspace((int)*c); c++)
+	if ( *c == option) return;
+  *c = option;
+}
+
+void usage()
+{
+  fprintf(stderr, "Syntax: %s [{options | macro=val | target}]\n", myname);
+  fprintf(stderr, "Function: maintaining computer programs      V%s\n",version);
+  fprintf(stderr, "Options : -a : try to guess undefined ambiguous macros (*,<)\n");
+  fprintf(stderr, "          -d : print debugging information\n");
+  fprintf(stderr, "          -e : environment macro def. overwrite makefile def.\n");
+  fprintf(stderr, "          -f filename : makefile name (default: makefile, Makefile)\n");
+  fprintf(stderr, "          -i : ignore exit status of executed commands\n");
+  fprintf(stderr, "          -k : continue with unrelated branches on errors\n");
+  fprintf(stderr, "          -n : pretend to make\n");
+  fprintf(stderr, "          -p : print all macros & targets\n");
+  fprintf(stderr, "          -q : question up-to-dateness of target\n");
+  fprintf(stderr, "          -r : don't use inbuilt rules\n");
+  fprintf(stderr, "          -s : make silently\n");
+  fprintf(stderr, "          -t : touch files instead of making them\n");
+  fprintf(stderr, "Environment: MAKEFLAGS\n");
+  exit(1);
+}
+
+
+void fatal(msg, a1, a2)
+char *msg;
+char *a1;
+int   a2;
+{
+  fprintf(stderr, "%s: ", myname);
+  fprintf(stderr, msg, a1, strerror(a2));
+  fputc('\n', stderr);
+  exit(1);
+}
Index: /trunk/minix/commands/make/make.c
===================================================================
--- /trunk/minix/commands/make/make.c	(revision 9)
+++ /trunk/minix/commands/make/make.c	(revision 9)
@@ -0,0 +1,782 @@
+/*************************************************************************
+ *
+ *  m a k e :   m a k e . c
+ *
+ *  Do the actual making for make plus system dependent stuff
+ *========================================================================
+ * Edition history
+ *
+ *  #    Date                         Comments                       By
+ * --- -------- ---------------------------------------------------- ---
+ *   1    ??                                                         ??
+ *   2 01.07.89 $<,$* bugs fixed                                     RAL
+ *   3 23.08.89 (time_t)time((time_t*)0) bug fixed, N_EXISTS added   RAL
+ *   4 30.08.89 leading sp. in cmd. output eliminated, indention ch. PSH,RAL
+ *   5 03.09.89 :: time fixed, error output -> stderr, N_ERROR intr.
+ *              fixed LZ elimintaed                                  RAL
+ *   6 07.09.89 implmacro, DF macros,debug stuff added               RAL
+ *   7 09.09.89 tos support added                                    PHH,RAL
+ *   8 17.09.89 make1 arg. fixed, N_EXEC introduced                  RAL
+ * ------------ Version 2.0 released ------------------------------- RAL
+ *     18.05.90 fixed -n bug with silent rules.  (Now echos them.)   PAN
+ *
+ *************************************************************************/
+
+#include "h.h"
+#include <sys/wait.h>
+#include <unistd.h>
+
+_PROTOTYPE(static void tellstatus, (FILE *out, char *name, int status));
+
+static bool  execflag;
+
+/*
+ *	Exec a shell that returns exit status correctly (/bin/esh).
+ *	The standard EON shell returns the process number of the last
+ *	async command, used by the debugger (ugg).
+ *	[exec on eon is like a fork+exec on unix]
+ */
+int dosh(string, shell)
+char *string;
+char *shell;
+{
+  int number;
+
+#ifdef unix
+  return system(string);
+#endif
+#ifdef tos
+  return Tosexec(string);
+#endif
+#ifdef eon
+  return ((number = execl(shell, shell,"-c", string, 0)) == -1) ?
+	-1:	/* couldn't start the shell */
+	wait(number);	/* return its exit status */
+#endif
+#ifdef os9
+  int	status, pid;
+
+  strcat(string, "\n");
+  if ((number = os9fork(shell, strlen(string), string, 0, 0, 0)) == -1)
+	return -1;		/* Couldn't start a shell */
+  do {
+	if ((pid = wait(&status)) == -1)
+		return -1;	/* child already died!?!? */
+  } while (pid != number);
+
+  return status;
+#endif
+}
+
+
+#ifdef unix
+/*
+ *    Make a file look very outdated after an error trying to make it.
+ *    Don't remove, this keeps hard links intact.  (kjb)
+ */
+int makeold(name) char *name;
+{
+  struct utimbuf a;
+
+  a.actime = a.modtime = 0;	/* The epoch */
+
+  return utime(name, &a);
+}
+#endif
+
+
+static void tellstatus(out, name, status)
+FILE *out;
+char *name;
+int status;
+{
+  char cwd[PATH_MAX];
+
+  fprintf(out, "%s in %s: ",
+	name, getcwd(cwd, sizeof(cwd)) == NULL ? "?" : cwd);
+
+  if (WIFEXITED(status)) {
+	fprintf(out, "Exit code %d", WEXITSTATUS(status));
+  } else {
+	fprintf(out, "Signal %d%s",
+		WTERMSIG(status), status & 0x80 ? " - core dumped" : "");
+  }
+}
+
+
+/*
+ *	Do commands to make a target
+ */
+void docmds1(np, lp)
+struct name *np;
+struct line *lp;
+{
+  register char       *q;
+  register char       *p;
+  register struct cmd *cp;
+  bool                 ssilent;
+  bool                 signore;
+  int                  estat;
+  char                *shell;
+
+
+  if (*(shell = getmacro("SHELL")) == '\0')
+#ifdef eon
+	shell = ":bin/esh";
+#endif
+#ifdef unix
+	shell = "/bin/sh";
+#endif
+#ifdef os9
+	shell = "shell";
+#endif
+#ifdef tos
+	shell = "DESKTOP";      /* TOS has no shell */
+#endif
+
+  for (cp = lp->l_cmd; cp; cp = cp->c_next) {
+	execflag = TRUE;
+	strcpy(str1, cp->c_cmd);
+	expmake = FALSE;
+	expand(&str1s);
+	q = str1;
+	ssilent = silent;
+	signore = ignore;
+	while ((*q == '@') || (*q == '-')) {
+		if (*q == '@')	   /*  Specific silent  */
+			ssilent = TRUE;
+		else		   /*  Specific ignore  */
+			signore = TRUE;
+		if (!domake) putchar(*q);  /* Show all characters. */
+		q++;		   /*  Not part of the command  */
+	}
+
+	for (p=q; *p; p++) {
+		if (*p == '\n' && p[1] != '\0') {
+			*p = ' ';
+			if (!ssilent || !domake)
+				fputs("\\\n", stdout);
+		}
+		else if (!ssilent || !domake)
+			putchar(*p);
+	}
+	if (!ssilent || !domake)
+		putchar('\n');
+
+	if (domake || expmake) {	/*  Get the shell to execute it  */
+		fflush(stdout);
+		if ((estat = dosh(q, shell)) != 0) {
+		    if (estat == -1)
+			fatal("Couldn't execute %s", shell,0);
+		    else if (signore) {
+			tellstatus(stdout, myname, estat);
+			printf(" (Ignored)\n");
+		    } else {
+			tellstatus(stderr, myname, estat);
+			fprintf(stderr, "\n");
+			if (!(np->n_flag & N_PREC))
+#ifdef unix
+			    if (makeold(np->n_name) == 0)
+				fprintf(stderr,"%s: made '%s' look old.\n", myname, np->n_name);
+#else
+			    if (unlink(np->n_name) == 0)
+				fprintf(stderr,"%s: '%s' removed.\n", myname, np->n_name);
+#endif
+			if (!conterr) exit(estat != 0);
+			np->n_flag |= N_ERROR;
+			return;
+		    }
+		}
+	}
+  }
+}
+
+
+void docmds(np)
+struct name *np;
+{
+  register struct line *lp;
+
+  for (lp = np->n_line; lp; lp = lp->l_next)
+	docmds1(np, lp);
+}
+
+#ifdef tos
+/*
+ *      execute the command submitted by make,
+ *      needed because TOS has no internal shell,
+ *      so we use Pexec to do the job
+ *        v 1.1 of 10/sep/89 by yeti
+ */
+
+#define DELM1 ';'
+#define DELM2 ' '
+#define DELM3 ','
+
+int Tosexec(string)
+char *string;
+{
+  register char *help, *help2, c;
+  register unsigned char l=1;
+  char progname[80], command[255], plain[15];
+  static char **envp,*env;
+  register int error,i;
+
+  /* generate strange TOS environment (RAL) */
+  for ( i = 0, envp = environ; *envp; envp++) i += strlen(*envp) +1;
+  if ((env = malloc(i+1)) == (char *)0)
+     fatal("No memory for TOS environment",(char *)0,0);
+  for ( envp = environ, help = env; *envp; envp++) {
+     strcpy ( help, *envp);
+     while ( *(help++)) ;
+  }
+  *help = '\0';
+
+  help = progname;
+  while((*help++=*string++) != ' '); /* progname is command name */
+  *--help = '\0';
+
+  l = strlen(string);             /* build option list */
+  command[0] = l;                 /* TOS likes it complicated */
+  strcpy(&command[1],string);
+  if ((error = (int) Pexec(0,progname,command,env)) != -33) {
+    free(env);
+    return(error);
+  }
+
+  /* could'nt find program, try to search the PATH */
+  if((help=strrchr(progname,'\\')) != (char *) 0)  /* just the */
+          strcpy(plain,++help);                     /* name     */
+  else if((help=strrchr(progname,'/')) != (char *) 0)
+          strcpy(plain,++help);
+  else if((help=strrchr(progname,':')) != (char *) 0)
+          strcpy(plain,++help);
+  else
+          strcpy(plain,progname);
+
+  if(*(help=getmacro("PATH")) == '\0') {
+    free(env);
+    return(-33);
+  }
+  c = 1;
+  while(c)
+  {       help2 = &progname[-1];
+          i = 0;
+          while((c=*help++) != '\0' && i<80 && c != DELM1
+                 && c != DELM2 && c != DELM3)
+                  *++help2 = c, i++;
+          *++help2 = '\\';
+          strcpy(++help2,plain);
+          if((error=(int) Pexec(0,progname,command,env))!=-33) {
+                  free(env);
+                  return(error);
+          }
+  }
+  free(env);
+  return(-33);
+}
+
+
+/* (stolen from ZOO -- thanks to Rahul Dehsi)
+Function mstonix() accepts an MSDOS format date and time and returns
+a **IX format time.  No adjustment is done for timezone.
+*/
+
+time_t mstonix (date, time)
+unsigned int date, time;
+{
+   int year, month, day, hour, min, sec, daycount;
+   time_t longtime;
+   /* no. of days to beginning of month for each month */
+   static int dsboy[12] = { 0, 31, 59, 90, 120, 151, 181, 212,
+                              243, 273, 304, 334};
+
+   if (date == 0 && time == 0)			/* special case! */
+      return (0L);
+
+   /* part of following code is common to zoolist.c */
+   year  =  (((unsigned int) date >> 9) & 0x7f) + 1980;
+   month =  ((unsigned int) date >> 5) & 0x0f;
+   day   =  date        & 0x1f;
+
+   hour =  ((unsigned int) time >> 11)& 0x1f;
+   min   =  ((unsigned int) time >> 5) & 0x3f;
+   sec   =  ((unsigned int) time & 0x1f) * 2;
+
+/* DEBUG and leap year fixes thanks to Mark Alexander <uunet!amdahl!drivax!alexande>*/
+#ifdef DEBUG
+   printf ("mstonix:  year=%d  month=%d  day=%d  hour=%d  min=%d  sec=%d\n",
+         year, month, day, hour, min, sec);
+#endif
+   /* Calculate days since 1970/01/01 */
+   daycount = 365 * (year - 1970) +    /* days due to whole years */
+               (year - 1969) / 4 +     /* days due to leap years */
+               dsboy[month-1] +        /* days since beginning of this year */
+               day-1;                  /* days since beginning of month */
+
+   if (year % 4 == 0 &&
+       year % 400 != 0 && month >= 3)  /* if this is a leap year and month */
+      daycount++;                      /* is March or later, add a day */
+
+   /* Knowing the days, we can find seconds */
+   longtime = daycount * 24L * 60L * 60L    +
+          hour * 60L * 60L   +   min * 60   +    sec;
+	return (longtime);
+}
+#endif /* tos */
+
+#ifdef os9
+/*
+ *	Some stuffing around to get the modified time of a file
+ *	in an os9 file system
+ */
+void getmdate(fd, tbp)
+int fd;
+struct sgtbuf *tbp;
+{
+  struct registers     regs;
+  static struct fildes fdbuf;
+
+
+  regs.rg_a = fd;
+  regs.rg_b = SS_FD;
+  regs.rg_x = &fdbuf;
+  regs.rg_y = sizeof (fdbuf);
+
+  if (_os9(I_GETSTT, &regs) == -1) {
+	errno = regs.rg_b & 0xff;
+	return -1;
+  }
+  if (tbp)
+  {
+	_strass(tbp, fdbuf.fd_date, sizeof (fdbuf.fd_date));
+	tbp->t_second = 0;	/* Files are only acurate to mins */
+  }
+  return 0;
+}
+
+
+/*
+ *	Kludge routine to return an aproximation of how many
+ *	seconds since 1980.  Dates will be in order, but will not
+ *	be lineer
+ */
+time_t cnvtime(tbp)
+struct sgtbuf *tbp;
+{
+  long acc;
+
+  acc = tbp->t_year - 80;		/* Baseyear is 1980 */
+  acc = acc * 12 + tbp->t_month;
+  acc = acc * 31 + tbp->t_day;
+  acc = acc * 24 + tbp->t_hour;
+  acc = acc * 60 + tbp->t_minute;
+  acc = acc * 60 + tbp->t_second;
+
+  return acc;
+}
+
+
+/*
+ *	Get the current time in the internal format
+ */
+void time(tp)
+time_t *tp;
+{
+  struct sgtbuf tbuf;
+
+
+  if (getime(&tbuf) < 0)
+	return -1;
+
+  if (tp)
+	*tp = cnvtime(&tbuf);
+
+  return 0;
+}
+#endif
+
+
+/*
+ *	Get the modification time of a file.  If the first
+ *	doesn't exist, it's modtime is set to 0.
+ */
+void modtime(np)
+struct name *np;
+{
+#ifdef unix
+  struct stat info;
+  int r;
+
+  if (is_archive_ref(np->n_name)) {
+	r = archive_stat(np->n_name, &info);
+  } else {
+	r = stat(np->n_name, &info);
+  }
+  if (r < 0) {
+	if (errno != ENOENT)
+		fatal("Can't open %s: %s", np->n_name, errno);
+
+	np->n_time = 0L;
+	np->n_flag &= ~N_EXISTS;
+  } else {
+	np->n_time = info.st_mtime;
+	np->n_flag |= N_EXISTS;
+  }
+#endif
+#ifdef tos
+  struct DOSTIME fm;
+  int fd;
+
+  if((fd=Fopen(np->n_name,0)) < 0) {
+        np->n_time = 0L;
+	np->n_flag &= ~N_EXISTS;
+  }
+  else {
+        Fdatime(&fm,fd,0);
+        Fclose(fd);
+        np->n_time = mstonix((unsigned int)fm.date,(unsigned int)fm.time);
+        np->n_flag |= N_EXISTS;
+  }
+#endif
+#ifdef eon
+  struct stat  info;
+  int          fd;
+
+  if ((fd = open(np->n_name, 0)) < 0) {
+	if (errno != ER_NOTF)
+		fatal("Can't open %s: %s", np->n_name, errno);
+
+	np->n_time = 0L;
+	np->n_flag &= ~N_EXISTS;
+  }
+  else if (getstat(fd, &info) < 0)
+	fatal("Can't getstat %s: %s", np->n_name, errno);
+  else {
+	np->n_time = info.st_mod;
+	np->n_flag |= N_EXISTS;
+  }
+
+  close(fd);
+#endif
+#ifdef os9
+  struct sgtbuf  info;
+  int            fd;
+
+  if ((fd = open(np->n_name, 0)) < 0) {
+  if (errno != E_PNNF)
+		fatal("Can't open %s: %s", np->n_name, errno);
+
+	np->n_time = 0L;
+	np->n_flag &= ~N_EXISTS;
+  }
+  else if (getmdate(fd, &info) < 0)
+	fatal("Can't getstat %s: %s", np->n_name, errno);
+  else {
+	np->n_time = cnvtime(&info);
+	np->n_flag |= N_EXISTS;
+  }
+
+  close(fd);
+#endif
+}
+
+
+/*
+ *	Update the mod time of a file to now.
+ */
+void touch(np)
+struct name *np;
+{
+  char  c;
+  int   fd;
+
+  if (!domake || !silent) printf("touch(%s)\n", np->n_name);
+
+  if (domake) {
+#ifdef unix
+	struct utimbuf   a;
+
+	a.actime = a.modtime = time((time_t *)NULL);
+	if (utime(np->n_name, &a) < 0)
+		printf("%s: '%s' not touched - non-existant\n",
+				myname, np->n_name);
+#endif
+#ifdef tos
+        struct DOSTIME fm;
+        int fd;
+
+        if((fd=Fopen(np->n_name,0)) < 0) {
+                printf("%s: '%s' not touched - non-existant\n",
+                                myname, np->n_name);
+        }
+        else {
+                fm.date = Tgetdate();
+                fm.time = Tgettime();
+                Fdatime(&fm,fd,1);
+                Fclose(fd);
+        }
+#endif
+#ifdef eon
+	if ((fd = open(np->n_name, 0)) < 0)
+		printf("%s: '%s' not touched - non-existant\n",
+				myname, np->n_name);
+	else
+	{
+		uread(fd, &c, 1, 0);
+		uwrite(fd, &c, 1);
+	}
+	close(fd);
+#endif
+#ifdef os9
+	/*
+	 *	Strange that something almost as totally useless
+	 *	as this is easy to do in os9!
+	 */
+	if ((fd = open(np->n_name, S_IWRITE)) < 0)
+		printf("%s: '%s' not touched - non-existant\n",
+				myname, np->n_name);
+	close(fd);
+#endif
+  }
+}
+
+
+/*
+ *	Recursive routine to make a target.
+ */
+int make(np, level)
+struct name *np;
+int          level;
+{
+  register struct depend  *dp;
+  register struct line    *lp;
+  register struct depend  *qdp;
+  time_t  now, t, dtime = 0;
+  bool    dbgfirst     = TRUE;
+  char   *basename  = (char *) 0;
+  char   *inputname = (char *) 0;
+
+  if (np->n_flag & N_DONE) {
+     if(dbginfo) dbgprint(level,np,"already done");
+     return 0;
+  }
+
+  modtime(np);		/*  Gets modtime of this file  */
+
+  while (time(&now) == np->n_time) {
+     /* Time of target is equal to the current time.  This bothers us, because
+      * we can't tell if it needs to be updated if we update a file it depends
+      * on within a second.  So wait until the second is over.
+      */
+     usleep(10000);
+  }
+
+  if (rules) {
+     for (lp = np->n_line; lp; lp = lp->l_next)
+        if (lp->l_cmd)
+           break;
+     if (!lp)
+        dyndep(np,&basename,&inputname);
+  }
+
+  if (!(np->n_flag & (N_TARG | N_EXISTS))) {
+     fprintf(stderr,"%s: Don't know how to make %s\n", myname, np->n_name);
+     if (conterr) {
+        np->n_flag |= N_ERROR;
+        if (dbginfo) dbgprint(level,np,"don't know how to make");
+        return 0;
+     }
+     else  exit(1);
+  }
+
+  for (qdp = (struct depend *)0, lp = np->n_line; lp; lp = lp->l_next) {
+     for (dp = lp->l_dep; dp; dp = dp->d_next) {
+        if(dbginfo && dbgfirst) {
+           dbgprint(level,np," {");
+           dbgfirst = FALSE;
+        }
+        make(dp->d_name, level+1);
+        if (np->n_time < dp->d_name->n_time)
+           qdp = newdep(dp->d_name, qdp);
+        dtime = max(dtime, dp->d_name->n_time);
+        if (dp->d_name->n_flag & N_ERROR) np->n_flag |= N_ERROR;
+        if (dp->d_name->n_flag & N_EXEC ) np->n_flag |= N_EXEC;
+     }
+     if (!quest && (np->n_flag & N_DOUBLE) &&
+           (np->n_time < dtime || !( np->n_flag & N_EXISTS))) {
+        execflag = FALSE;
+        make1(np, lp, qdp, basename, inputname); /* free()'s qdp */
+        dtime = 0;
+        qdp = (struct depend *)0;
+        if(execflag) np->n_flag |= N_EXEC;
+     }
+  }
+
+  np->n_flag |= N_DONE;
+
+  if (quest) {
+     t = np->n_time;
+     np->n_time = now;
+     return (t < dtime);
+  }
+  else if ((np->n_time < dtime || !( np->n_flag & N_EXISTS))
+               && !(np->n_flag & N_DOUBLE)) {
+     execflag = FALSE;
+     make1(np, (struct line *)0, qdp, basename, inputname); /* free()'s qdp */
+     np->n_time = now;
+     if ( execflag) np->n_flag |= N_EXEC;
+  }
+  else if ( np->n_flag & N_EXEC ) {
+     np->n_time = now;
+  }
+
+  if (dbginfo) {
+     if(dbgfirst) {
+        if(np->n_flag & N_ERROR)
+              dbgprint(level,np,"skipped because of error");
+        else if(np->n_flag & N_EXEC)
+              dbgprint(level,np,"successfully made");
+        else  dbgprint(level,np,"is up to date");
+     }
+     else {
+        if(np->n_flag & N_ERROR)
+              dbgprint(level,(struct name *)0,"} skipped because of error");
+        else if(np->n_flag & N_EXEC)
+              dbgprint(level,(struct name *)0,"} successfully made");
+        else  dbgprint(level,(struct name *)0,"} is up to date");
+     }
+  }
+  if (level == 0 && !(np->n_flag & N_EXEC))
+     printf("%s: '%s' is up to date\n", myname, np->n_name);
+
+  if(basename)
+     free(basename);
+  return 0;
+}
+
+
+void make1(np, lp, qdp, basename, inputname)
+struct name *np;
+struct line *lp;
+register struct depend *qdp;
+char        *basename;
+char        *inputname;
+{
+  register struct depend *dp;
+  size_t l1, l2;
+
+  if (dotouch)
+    touch(np);
+  else if (!(np->n_flag & N_ERROR)) {
+    strcpy(str1, "");
+
+    if(!inputname) {
+       inputname = str1;  /* default */
+       if (ambigmac) implmacros(np,lp,&basename,&inputname);
+    }
+    setDFmacro("<",inputname);
+
+    if(!basename)
+       basename = str1;
+    setDFmacro("*",basename);
+
+    for (dp = qdp; dp; dp = qdp) {
+       l1= strlen(str1);
+       l2= strlen(dp->d_name->n_name);
+       while (l1 + 1 + l2 +1 > str1s.len)
+       		strrealloc(&str1s);
+       if (strlen(str1))
+          strcat(str1, " ");
+       strcat(str1, dp->d_name->n_name);
+       qdp = dp->d_next;
+       free(dp);
+    }
+    setmacro("?", str1);
+    setDFmacro("@", np->n_name);
+
+    if (lp)		/* lp set if doing a :: rule */
+       docmds1(np, lp);
+    else
+       docmds(np);
+  }
+}
+
+void implmacros(np,lp, pbasename,pinputname)
+struct name *np;
+struct line *lp;
+char        **pbasename;		/*  Name without suffix  */
+char        **pinputname;
+{
+  struct line   *llp;
+  register char *p;
+  register char *q;
+  register char *suff;				/*  Old suffix  */
+  int            baselen;
+  struct depend *dp;
+  bool           dpflag = FALSE;
+
+  /* get basename out of target name */
+  p = str2;
+  q = np->n_name;
+  suff = suffix(q);
+  while ( *q && (q < suff || !suff)) *p++ = *q++;
+  *p = '\0';
+  if ((*pbasename = (char *) malloc(strlen(str2)+1)) == (char *)0 )
+     fatal("No memory for basename",(char *)0,0);
+  strcpy(*pbasename,str2);
+  baselen = strlen(str2);
+
+  if ( lp)
+     llp = lp;
+  else
+     llp = np->n_line;
+
+  while (llp) {
+     for (dp = llp->l_dep; dp; dp = dp->d_next) {
+        if( strncmp(*pbasename,dp->d_name->n_name,baselen) == 0) {
+           *pinputname = dp->d_name->n_name;
+           return;
+        }
+        if( !dpflag) {
+           *pinputname = dp->d_name->n_name;
+           dpflag = TRUE;
+        }
+     }
+     if (lp) break;
+     llp = llp->l_next;
+  }
+
+#if NO_WE_DO_WANT_THIS_BASENAME
+  free(*pbasename);  /* basename ambiguous or no dependency file */
+  *pbasename = (char *)0;
+#endif
+  return;
+}
+
+void dbgprint(level,np,comment)
+int          level;
+struct name *np;
+char        *comment;
+{
+  char *timep;
+
+  if(np) {
+     timep = ctime(&np->n_time);
+     timep[24] = '\0';
+     fputs(&timep[4],stdout);
+  }
+  else fputs("                    ",stdout);
+  fputs("   ",stdout);
+  while(level--) fputs("  ",stdout);
+  if (np) {
+     fputs(np->n_name,stdout);
+     if (np->n_flag & N_DOUBLE) fputs("  :: ",stdout);
+     else                       fputs("  : ",stdout);
+  }
+  fputs(comment,stdout);
+  putchar((int)'\n');
+  fflush(stdout);
+  return;
+}
+
Index: /trunk/minix/commands/make/reader.c
===================================================================
--- /trunk/minix/commands/make/reader.c	(revision 9)
+++ /trunk/minix/commands/make/reader.c	(revision 9)
@@ -0,0 +1,134 @@
+/*************************************************************************
+ *
+ *  m a k e :   r e a d e r . c
+ *
+ *  Read in makefile
+ *========================================================================
+ * Edition history
+ *
+ *  #    Date                         Comments                       By
+ * --- -------- ---------------------------------------------------- ---
+ *   1    ??                                                         ??
+ *   2 23.08.89 cast to NULL added                                   RAL
+ *   3 30.08.89 indention changed                                    PSH,RAL
+ *   4 03.09.89 fixed LZ eliminated                                  RAL
+ * ------------ Version 2.0 released ------------------------------- RAL
+ *
+ *************************************************************************/
+
+#include "h.h"
+
+
+/*
+ *	Syntax error handler.  Print message, with line number, and exits.
+ */
+void error(msg, a1)
+char *msg;
+char *a1;
+{
+  fprintf(stderr, "%s: ", myname);
+  fprintf(stderr, msg, a1);
+  if (lineno)  fprintf(stderr, " in %s near line %d", makefile, lineno);
+  fputc('\n', stderr);
+  exit(1);
+}
+
+
+/*
+ *	Read a line into the supplied string.  Remove
+ *	comments, ignore blank lines. Deal with	quoted (\) #, and
+ *	quoted newlines.  If EOF return TRUE.
+ *
+ *	The comment handling code has been changed to leave comments and
+ *	backslashes alone in shell commands (lines starting with a tab).
+ *	This is not what POSIX wants, but what all makes do.  (KJB)
+ */
+bool getline(strs, fd)
+struct str *strs;
+FILE *fd;
+{
+  register char *p;
+  char          *q;
+  int            c;
+
+  for (;;) {
+	strs->pos = 0;
+	for (;;) {
+		do {
+			if (strs->pos >= strs->len)
+				strrealloc(strs);
+			if ((c = getc(fd)) == EOF)
+				return TRUE;		/* EOF */
+			(*strs->ptr)[strs->pos++] = c;
+		} while (c != '\n');
+
+		lineno++;
+
+		if (strs->pos >= 2 && (*strs->ptr)[strs->pos - 2] == '\\') {
+			(*strs->ptr)[strs->pos - 2] = '\n';
+			strs->pos--;
+		} else {
+			break;
+		}
+	}
+
+	if (strs->pos >= strs->len)
+		strrealloc(strs);
+	(*strs->ptr)[strs->pos] = '\0';
+
+	p = q =  *strs->ptr;
+	while (isspace(*q)) q++;
+	if (*p != '\t' || *q == '#') {
+		while (((q = strchr(p, '#')) != (char *)0) &&
+		    (p != q) && (q[-1] == '\\'))
+		{
+			char	*a;
+
+			a = q - 1;	/*  Del \ chr; move rest back  */
+			p = q;
+			while (*a++ = *q++)
+				;
+		}
+		if (q != (char *)0)
+			{
+			q[0] = '\n';
+			q[1] = '\0';
+		}
+	}
+
+	p = *strs->ptr;
+	while (isspace(*p))	/*  Checking for blank  */
+		p++;
+
+	if (*p != '\0')
+		return FALSE;
+  }
+}
+
+
+/*
+ *	Get a word from the current line, surounded by white space.
+ *	return a pointer to it. String returned has no white spaces
+ *	in it.
+ */
+char  *gettok(ptr)
+register char **ptr;
+{
+  register char *p;
+
+
+  while (isspace(**ptr))	/*  Skip spaces  */
+	(*ptr)++;
+
+  if (**ptr == '\0')	/*  Nothing after spaces  */
+	return ((char *)NULL);
+
+  p = *ptr;		/*  word starts here  */
+
+  while ((**ptr != '\0') && (!isspace(**ptr)))
+	(*ptr)++;	/*  Find end of word  */
+
+  *(*ptr)++ = '\0';	/*  Terminate it  */
+
+  return(p);
+}
Index: /trunk/minix/commands/make/rules.c
===================================================================
--- /trunk/minix/commands/make/rules.c	(revision 9)
+++ /trunk/minix/commands/make/rules.c	(revision 9)
@@ -0,0 +1,314 @@
+/*************************************************************************
+ *
+ *  m a k e :   r u l e s . c
+ *
+ *  Control of the implicit suffix rules
+ *========================================================================
+ * Edition history
+ *
+ *  #    Date                         Comments                       By
+ * --- -------- ---------------------------------------------------- ---
+ *   1    ??                                                         ??
+ *   2 01.07.89 $<,$* bugs fixed, impl. r. ending in expl. r. added  RAL
+ *   3 23.08.89 suffix as macro, testname intr., algorithem to find
+ *              source dep. made more intelligent (see Readme3)      RAL
+ *   4 30.08.89 indention changed                                    PSH,RAL
+ *   5 03.09.89 fixed LZ eliminated                                  RAL
+ *   6 07.09.89 rules of type '.c', .DEFAULT added, dep. search impr.RAL
+ * ------------ Version 2.0 released ------------------------------- RAL
+ *
+ *************************************************************************/
+
+#include "h.h"
+
+
+/*
+ *	Dynamic dependency.  This routine applies the suffis rules
+ *	to try and find a source and a set of rules for a missing
+ *	target.  If found, np is made into a target with the implicit
+ *	source name, and rules.  Returns TRUE if np was made into
+ *	a target.
+ */
+bool dyndep(np,pbasename,pinputname)
+struct name  *np;
+char        **pbasename;		/*  Name without suffix  */
+char        **pinputname;
+{
+  register char *p;
+  register char *q;
+  register char *suff;				/*  Old suffix  */
+  struct name   *op = (struct name *)0,*optmp;	/*  New dependent  */
+  struct name   *sp;				/*  Suffix  */
+  struct line   *lp,*nlp;
+  struct depend *dp,*ndp;
+  struct cmd    *cmdp;
+  char          *newsuff;
+  bool           depexists = FALSE;
+
+
+  p = str1;
+  q = np->n_name;
+  suff = suffix(q);
+  while (*q && (q < suff || !suff)) *p++ = *q++;
+  *p = '\0';
+  if ((*pbasename = (char *) malloc(strlen(str1)+1)) == (char *)0 )
+     fatal("No memory for basename",(char *)0,0);
+  strcpy(*pbasename,str1);
+  if ( !suff) suff = p - str1 + *pbasename;  /* set suffix to nullstring */
+
+  if (!((sp = newname(".SUFFIXES"))->n_flag & N_TARG))  return FALSE;
+
+  /* search all .SUFFIXES lines */
+  for (lp = sp->n_line; lp; lp = lp->l_next)
+     /* try all suffixes */
+     for (dp = lp->l_dep; dp; dp = dp->d_next) {
+        /* compose implicit rule name (.c.o)...*/
+        newsuff = dp->d_name->n_name;
+        while (strlen(suff)+strlen(newsuff)+1 >= str1s.len) strrealloc(&str1s);
+        p = str1;
+        q = newsuff;
+        while (*p++ = *q++) ;
+        p--;
+        q = suff;
+        while (*p++ = *q++) ;
+        /* look if the rule exists */
+        sp = newname(str1);
+        if (sp->n_flag & N_TARG) {
+           /* compose resulting dependency name */
+           while (strlen(*pbasename) + strlen(newsuff)+1 >= str1s.len)
+              strrealloc(&str1s);
+           q = *pbasename;
+           p = str1;
+           while (*p++ = *q++) ;
+           p--;
+           q = newsuff;
+           while (*p++ = *q++) ;
+           /* test if dependency file or an explicit rule exists */
+           if ((optmp= testname(str1)) != (struct name *)0) {
+              /* store first possible dependency as default */
+              if ( op == (struct name *)0) {
+                 op = optmp;
+                 cmdp = sp->n_line->l_cmd;
+              }
+              /* check if testname is an explicit dependency */
+              for ( nlp=np->n_line; nlp; nlp=nlp->l_next) {
+                 for( ndp=nlp->l_dep; ndp; ndp=ndp->d_next) {
+                    if ( strcmp( ndp->d_name->n_name, str1) == 0) {
+                       op = optmp;
+                       cmdp = sp->n_line->l_cmd;
+                       ndp = (struct depend *) 0;
+                       goto found2;
+                    }
+                    depexists = TRUE;
+                 }
+              }
+              /* if no explicit dependencies : accept testname */
+              if (!depexists)  goto found;
+           }
+        }
+     }
+
+  if ( op == (struct name *)0) {
+     if( np->n_flag & N_TARG) {     /* DEFAULT handling */
+        if (!((sp = newname(".DEFAULT"))->n_flag & N_TARG))  return FALSE;
+        if (!(sp->n_line)) return FALSE;
+        cmdp = sp->n_line->l_cmd;
+        for ( nlp=np->n_line; nlp; nlp=nlp->l_next) {
+           if ( ndp=nlp->l_dep) {
+              op = ndp->d_name;
+              ndp = (struct depend *)0;
+              goto found2;
+           }
+        }
+        newline(np, (struct depend *)0, cmdp, 0);
+        *pinputname = (char *)0;
+        *pbasename  = (char *)0;
+        return TRUE;
+     }
+  else return FALSE;
+  }
+
+found:
+  ndp = newdep(op, (struct depend *)0);
+found2:
+  newline(np, ndp, cmdp, 0);
+  *pinputname = op->n_name;
+  return TRUE;
+}
+
+
+/*
+ *	Make the default rules
+ */
+void makerules()
+{
+  struct cmd    *cp;
+  struct name   *np;
+  struct depend *dp;
+
+
+#ifdef eon
+  setmacro("BDSCC", "asm");
+  /*	setmacro("BDSCFLAGS", "");	*/
+  cp = newcmd("$(BDSCC) $(BDSCFLAGS) -n $<", (struct cmd *)0);
+  np = newname(".c.o");
+  newline(np, (struct depend *)0, cp, 0);
+
+  setmacro("CC", "c");
+  setmacro("CFLAGS", "-O");
+  cp = newcmd("$(CC) $(CFLAGS) -c $<", (struct cmd *)0);
+  np = newname(".c.obj");
+  newline(np, (struct depend *)0, cp, 0);
+
+  setmacro("M80", "asm -n");
+  /*	setmacro("M80FLAGS", "");	*/
+  cp = newcmd("$(M80) $(M80FLAGS) $<", (struct cmd *)0);
+  np = newname(".mac.o");
+  newline(np, (struct depend *)0, cp, 0);
+
+  setmacro("AS", "zas");
+  /*	setmacro("ASFLAGS", "");	*/
+  cp = newcmd("$(ZAS) $(ASFLAGS) -o $@ $<", (struct cmd *)0);
+  np = newname(".as.obj");
+  newline(np, (struct depend *)0, cp, 0);
+
+  np = newname(".as");
+  dp = newdep(np, (struct depend *)0);
+  np = newname(".obj");
+  dp = newdep(np, dp);
+  np = newname(".c");
+  dp = newdep(np, dp);
+  np = newname(".o");
+  dp = newdep(np, dp);
+  np = newname(".mac");
+  dp = newdep(np, dp);
+  np = newname(".SUFFIXES");
+  newline(np, dp, (struct cmd *)0, 0);
+#endif
+
+#ifdef tos
+#define unix
+#endif
+
+/*
+ *	Some of the UNIX implicit rules
+ */
+
+#ifdef unix
+
+  setmacro("CC", "cc");
+  setmacro("CFLAGS", "");
+
+  cp = newcmd("$(CC) -S $(CFLAGS) $<", (struct cmd *)0);
+  np = newname(".c.s");
+  newline(np, (struct depend *)0, cp, 0);
+
+  cp = newcmd("$(CC) -c $(CFLAGS) $<", (struct cmd *)0);
+  np = newname(".c.o");
+  newline(np, (struct depend *)0, cp, 0);
+
+#if this_rule_is_a_bit_too_much_of_a_good_thing
+#ifdef MINIXPC
+  cp = newcmd("$(CC) $(CFLAGS) -i -o $@ $<", (struct cmd *)0);
+#else
+  cp = newcmd("$(CC) $(CFLAGS) -o $@ $<", (struct cmd *)0);
+#endif /* MINIXPC */
+  np = newname(".c");
+  newline(np, (struct depend *)0, cp, 0);
+#endif
+
+  cp = newcmd("$(CC) -c $(CFLAGS) $<", (struct cmd *)0);
+  np = newname(".s.o");
+  newline(np, (struct depend *)0, cp, 0);
+
+  setmacro("YACC", "yacc");
+  /*setmacro("YFLAGS", "");	*/
+  cp = newcmd("$(YACC) $(YFLAGS) $<", (struct cmd *)0);
+  cp = newcmd("mv y.tab.c $@", cp);
+  np = newname(".y.c");
+  newline(np, (struct depend *)0, cp, 0);
+
+  cp = newcmd("$(YACC) $(YFLAGS) $<", (struct cmd *)0);
+  cp = newcmd("$(CC) $(CFLAGS) -c y.tab.c", cp);
+  cp = newcmd("mv y.tab.o $@", cp);
+  np = newname(".y.o");
+  cp = newcmd("rm y.tab.c", cp);
+  newline(np, (struct depend *)0, cp, 0);
+
+  setmacro("FLEX", "flex");
+  cp = newcmd("$(FLEX) $(FLEX_FLAGS) $<", (struct cmd *)0);
+  cp = newcmd("mv lex.yy.c $@", cp);
+  np = newname(".l.c");
+  newline(np, (struct depend *)0, cp, 0);
+
+  cp = newcmd("$(FLEX) $(FLEX_FLAGS) $<", (struct cmd *)0);
+  cp = newcmd("$(CC) $(CFLAGS) -c lex.yy.c", cp);
+  cp = newcmd("mv lex.yy.o $@", cp);
+  np = newname(".l.o");
+  cp = newcmd("rm lex.yy.c", cp);
+  newline(np, (struct depend *)0, cp, 0);
+
+  np = newname(".o");
+  dp = newdep(np, (struct depend *)0);
+  np = newname(".s");
+  dp = newdep(np, dp);
+  np = newname(".c");
+  dp = newdep(np, dp);
+  np = newname(".y");
+  dp = newdep(np, dp);
+  np = newname(".l");
+  dp = newdep(np, dp);
+  np = newname(".SUFFIXES");
+  newline(np, dp, (struct cmd *)0, 0);
+
+#endif /* unix */
+
+
+#ifdef os9
+/*
+ *	Fairlight use an enhanced version of the C sub-system.
+ *	They have a specialised macro pre-processor.
+ */
+  setmacro("CC", "cc");
+  setmacro("CFLAGS", "-z");
+  cp = newcmd("$(CC) $(CFLAGS) -r $<", (struct cmd *)0);
+
+  np = newname(".c.r");
+  newline(np, (struct depend *)0, cp, 0);
+  np = newname(".ca.r");
+  newline(np, (struct depend *)0, cp, 0);
+  np = newname(".a.r");
+  newline(np, (struct depend *)0, cp, 0);
+  np = newname(".o.r");
+  newline(np, (struct depend *)0, cp, 0);
+  np = newname(".mc.r");
+  newline(np, (struct depend *)0, cp, 0);
+  np = newname(".mca.r");
+  newline(np, (struct depend *)0, cp, 0);
+  np = newname(".ma.r");
+  newline(np, (struct depend *)0, cp, 0);
+  np = newname(".mo.r");
+  newline(np, (struct depend *)0, cp, 0);
+
+  np = newname(".r");
+  dp = newdep(np, (struct depend *)0);
+  np = newname(".mc");
+  dp = newdep(np, dp);
+  np = newname(".mca");
+  dp = newdep(np, dp);
+  np = newname(".c");
+  dp = newdep(np, dp);
+  np = newname(".ca");
+  dp = newdep(np, dp);
+  np = newname(".ma");
+  dp = newdep(np, dp);
+  np = newname(".mo");
+  dp = newdep(np, dp);
+  np = newname(".o");
+  dp = newdep(np, dp);
+  np = newname(".a");
+  dp = newdep(np, dp);
+  np = newname(".SUFFIXES");
+  newline(np, dp, (struct cmd *)0, 0);
+#endif
+}
Index: /trunk/minix/commands/mdb/Dist
===================================================================
--- /trunk/minix/commands/mdb/Dist	(revision 9)
+++ /trunk/minix/commands/mdb/Dist	(revision 9)
@@ -0,0 +1,38 @@
+Mdb (Minix debugger) Distribution
+=================================
+
+Version: 	2.6.0
+Date:		Sept 9/96
+Author:		Philip Murton
+E-mail:		philip.murton@utoronto.ca
+
+
+Files included: 
+===============
+
+Dist		This file
+Makefile	Makefile 
+MDB.TXT		Cover file
+README		README file 
+a.out.h		GNU a.out.h (copied to /usr/include/gnu)
+core.c		core file functions
+decode.c	Optional for syscalls support
+gnu_load.c	Optional for GNU EXEC support
+io.c		I/O done here
+ioctl.c		Optional for syscalls support
+kernel.c	kernel functions
+log		Log from sample command file (See README)
+mdb.c		main program
+mdb.h		main header
+mdb.1		man page
+mdbdis86.c	Disassembler 
+mdbexp.c	Expression parsing
+misc.c		misc functions including help
+gnu_sym.c	Optional for GNU EXEC support
+proto.h		Prototypes 
+ptrace.2	man page
+sample		sample command file
+sym.c		Symbolic names read from exec file
+syscalls.c	Optional for syscalls support
+trace.c		ptrace() called here
+
Index: /trunk/minix/commands/mdb/MDB.TXT
===================================================================
--- /trunk/minix/commands/mdb/MDB.TXT	(revision 9)
+++ /trunk/minix/commands/mdb/MDB.TXT	(revision 9)
@@ -0,0 +1,25 @@
+INFORMATION on mdb version 2.6.0 (Sept 9/96).
+   
+MDB is the MINIX debugger which allows you to place breakpoints and
+control the execution of a program. It has a lot of the features that
+you would expect in a program debugger; for example, stack traces and
+single step execution.
+
+The current version works with MINIX for PC and was developed and tested
+under MINIX 1.7.x (32 bit version). It should work with 16 bit MINIX. 
+
+How to Install
+
+1) Unpack mdb.tar.Z and review additional information in the README file.
+   (If you got this from the Minix CD-ROM or an MS-DOS system rename 
+   MDB.TAZ to mdb.tar.Z)   
+2) Edit Makefile for Compiler and extra options as required.
+3) make 
+4) make install
+5) make install_man
+
+Comments to:
+
+Philip Murton. 
+philip.murton@utoronto.ca
+
Index: /trunk/minix/commands/mdb/Makefile
===================================================================
--- /trunk/minix/commands/mdb/Makefile	(revision 9)
+++ /trunk/minix/commands/mdb/Makefile	(revision 9)
@@ -0,0 +1,129 @@
+#
+# Makefile for mdb
+#
+#
+# Edit as indicated below.
+#
+USR		=/usr
+#
+# (1) For Compiler and target system:
+#
+#
+# For ANSI C and Minix 1.7.x 32-bit 
+#
+CC		=exec cc 
+LD		=exec cc
+LDFLAGS		=-i
+TARGET		=mdb
+STACK		=200000
+#
+# (2) If kernel and mm are not in "/usr/src" change this
+#
+SYSTEM	=$(USR)/src
+#
+# (3) Select Options
+# 
+# i)   For GNU_EXEC Support, uncomment:
+#
+#FOR_GNU		=gnu_sym.o gnu_load.o
+#DEF_GNU		=-DGNU_SUPPORT
+# 
+# ii)  For tracing of syscalls, uncomment:
+#
+#FOR_SYSCALLS 	=syscalls.o decode.o ioctl.o
+#DEF_SYSCALLS	=-DSYSCALLS_SUPPORT
+#
+# iii) For no debugging of mdb, uncomment:
+#
+#DEF_DEBUG	=-DNDEBUG
+
+EXTRA_OBJS	=$(FOR_GNU) $(FOR_SYSCALLS)
+EXTRA_DEFS	=$(DEF_GNU) $(DEF_SYSCALLS) $(DEF_DEBUG)
+
+all:	$(TARGET)
+
+CFLAGS	=-I$(SYSTEM) -I$(SYSTEM)/servers -I$(INCLUDE) -D_MINIX -D_POSIX_SOURCE $(EXTRA_DEFS)
+
+# For various included files or system files
+# 
+INCLUDE		=$(USR)/include
+KERNEL		=$(SYSTEM)/kernel
+PTRACE		=$(INCLUDE)/sys/ptrace.h
+
+
+# Header files from pm (used by core.c) 
+#
+MMFILES=	$(SYSTEM)/servers/pm/const.h \
+		$(SYSTEM)/servers/pm/type.h \
+		$(SYSTEM)/servers/pm/mproc.h
+
+# Header files from system and kernel in "mdb.h" 
+#
+SYSFILES=	$(INCLUDE)/minix/config.h \
+		$(INCLUDE)/minix/const.h \
+		$(INCLUDE)/ansi.h \
+		$(INCLUDE)/minix/type.h \
+		$(INCLUDE)/limits.h \
+		$(INCLUDE)/errno.h \
+		$(INCLUDE)/sys/types.h \
+		$(KERNEL)/const.h \
+		$(KERNEL)/type.h \
+		$(KERNEL)/proc.h
+
+# Common objects 
+#
+OBJCOMMON	=mdb.o mdbexp.o kernel.o sym.o trace.o core.o misc.o io.o
+
+# Common source
+#
+SRCCOMMON	=mdb.c mdbexp.c kernel.o sym.c trace.c core.c misc.c io.c
+
+# Object files for PC
+#
+OBJPC		=$(OBJCOMMON) mdbdis86.o 
+
+# Source file
+#
+SRCPC		=$(SRCCOMMON) mdbdis86.c
+
+
+mdb:	$(OBJPC) $(EXTRA_OBJS)
+	$(LD) $(LDFLAGS) -o mdb $(OBJPC) $(EXTRA_OBJS)
+	install -S $(STACK) mdb
+
+#
+# Dependencies for objects
+#
+mdb.o:		mdb.c mdb.h $(SYSFILES) proto.h
+mdbdis86.o:	mdbdis86.c mdb.h $(SYSFILES) proto.h
+mdbexp.o:	mdbexp.c mdb.h $(SYSFILES) proto.h
+sym.o:		sym.c mdb.h $(SYSFILES) proto.h
+trace.o:	trace.c mdb.h $(PTRACE) $(SYSFILES) proto.h
+core.o:		core.c mdb.h $(MMFILES) $(SYSFILES) proto.h
+misc.o:		misc.c mdb.h  $(SYSFILES) proto.h
+io.o:		io.c mdb.h $(SYSFILES) proto.h
+
+syscalls.o:	syscalls.c mdb.h $(SYSFILES) proto.h
+decode.o:	decode.c mdb.h $(INCLUDE)/minix/callnr.h $(SYSFILES) proto.h
+ioctl.o:	ioctl.c mdb.h  $(SYSFILES) proto.h
+
+gnu_sym.o:	gnu_sym.c mdb.h $(INCLUDE)/gnu/a.out.h $(SYSFILES) proto.h
+gnu_load.o:	gnu_load.c $(INCLUDE)/gnu/a.out.h $(SYSFILES) proto.h
+
+$(INCLUDE)/gnu/a.out.h:	a.out.h
+		install -c -o bin a.out.h $(INCLUDE)/gnu
+
+
+#
+# install
+#
+
+install:	mdb 
+		install -cs -o bin mdb /usr/bin
+
+install_man:	mdb.1 ptrace.2
+		install -c -o bin mdb.1 /usr/man/man1
+		install -c -o bin ptrace.2 /usr/man/man2
+clean:
+		rm -f *.o mdb
+
Index: /trunk/minix/commands/mdb/README
===================================================================
--- /trunk/minix/commands/mdb/README	(revision 9)
+++ /trunk/minix/commands/mdb/README	(revision 9)
@@ -0,0 +1,32 @@
+README for mdb version 2.6.0
+
+Sept 9/96
+
+Please note the following: 
+
+1) Has been tested with Minix 1.7.4 (32-bit version).
+   A previous version was tested with Minix 1.7.x (16 bit version).
+   Some optional parts of mdb have not been extensively tested. 
+   This is especially true on the code to trace system calls.
+   See options in Makefile.
+
+2) I know that the commands are somewhat cryptic; thus  
+   there are currently two types of 'help' for mdb
+   a) the "?" gives a help page. 
+   b) typing "command ?" will give help on a specific command. 
+
+3) The sample comand file and log output. 
+   To test this, type something like the following 
+   "mdb -llog.new /usr/bin/sleep @sample"
+   The output "log.new' should be similar to the distributed "log" file;
+   but not necessarily exactly the same.
+
+4) Man pages need some more work.
+
+5) See top part of mdb.c for version history.
+
+Send comments to Philip Murton. Thanks. 
+
+philip.murton@utoronto.ca
+
+
Index: /trunk/minix/commands/mdb/a.out.h
===================================================================
--- /trunk/minix/commands/mdb/a.out.h	(revision 9)
+++ /trunk/minix/commands/mdb/a.out.h	(revision 9)
@@ -0,0 +1,299 @@
+/* 
+ * MINIX 1.7.x
+ * GNU version based on Linux 1.1.45 version
+ * if _MINIX_EXEC defined use old MINIX GNU format
+ */
+
+#ifndef __A_OUT_GNU_H__
+#define __A_OUT_GNU_H__
+
+#define __GNU_EXEC_MACROS__
+
+#ifndef __STRUCT_EXEC_OVERRIDE__
+
+struct exec
+{
+  unsigned long a_info;		/* Use macros N_MAGIC, etc for access */
+  unsigned a_text;		/* length of text, in bytes */
+  unsigned a_data;		/* length of data, in bytes */
+  unsigned a_bss;		/* length of uninitialized data area for file, in bytes */
+  unsigned a_syms;		/* length of symbol table data in file, in bytes */
+  unsigned a_entry;		/* start address */
+  unsigned a_trsize;		/* length of relocation info for text, in bytes */
+  unsigned a_drsize;		/* length of relocation info for data, in bytes */
+#ifdef	_MINIX_EXEC
+  unsigned a_smagic;		/* SMAGIC */
+  unsigned a_memsize;		/* Dynamic Memory Size */
+#endif
+};
+
+#ifdef	_MINIX_EXEC
+#define GNU_SMAGIC	0xdeadbabe
+#define GNU_DYNMEM	(64 * 1024)
+#else
+#define GNU_STACK	64	/* Default Stack */
+#endif
+
+#endif /* __STRUCT_EXEC_OVERRIDE__ */
+
+/* these go in the N_MACHTYPE field */
+enum machine_type {
+#if defined (M_OLDSUN2)
+  M__OLDSUN2 = M_OLDSUN2,
+#else
+  M_OLDSUN2 = 0,
+#endif
+#if defined (M_68010)
+  M__68010 = M_68010,
+#else
+  M_68010 = 1,
+#endif
+#if defined (M_68020)
+  M__68020 = M_68020,
+#else
+  M_68020 = 2,
+#endif
+#if defined (M_SPARC)
+  M__SPARC = M_SPARC,
+#else
+  M_SPARC = 3,
+#endif
+  /* skip a bunch so we don't run into any of sun's numbers */
+  M_386 = 100
+};
+
+#if !defined (N_MAGIC)
+#define N_MAGIC(exec) ((exec).a_info & 0xffff)
+#endif
+#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
+#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
+#define N_SET_INFO(exec, magic, type, flags) \
+	((exec).a_info = ((magic) & 0xffff) \
+	 | (((int)(type) & 0xff) << 16) \
+	 | (((flags) & 0xff) << 24))
+#define N_SET_MAGIC(exec, magic) \
+	((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
+
+#define N_SET_MACHTYPE(exec, machtype) \
+	((exec).a_info = \
+	 ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
+
+#define N_SET_FLAGS(exec, flags) \
+	((exec).a_info = \
+	 ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
+
+#ifdef	_MINIX
+#define N_SET_MEMORY(exec, mem) \
+	((exec).a_info = \
+	 ((exec).a_info & 0x0000FFFF) | (((mem) & 0xFFFF) << 16))
+#define N_MEMORY(exec) (((exec).a_info >> 16) & 0xFFFF)
+#endif
+
+/* Code indicating object file or impure executable.  */
+#define OMAGIC 0407
+/* Code indicating pure executable.  */
+#define NMAGIC 0410
+/* Code indicating demand-paged executable.  */
+#define ZMAGIC 0413
+/* This indicates a demand-paged executable with the header in the text. 
+   The first page is unmapped to help trap NULL pointer references */
+#define QMAGIC 0314
+
+/* Code indicating core file.  */
+#define CMAGIC 0421
+
+#if !defined (N_BADMAG)
+#define N_BADMAG(x)	  (N_MAGIC(x) != OMAGIC		\
+			&& N_MAGIC(x) != NMAGIC		\
+  			&& N_MAGIC(x) != ZMAGIC \
+		        && N_MAGIC(x) != QMAGIC)
+#endif
+
+#define _N_HDROFF(x) (1024 - sizeof (struct exec))
+
+#if !defined (N_TXTOFF)
+#define N_TXTOFF(x) \
+ (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \
+  (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
+#endif
+
+#if !defined (N_DATOFF)
+#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
+#endif
+
+#if !defined (N_TRELOFF)
+#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
+#endif
+
+#if !defined (N_DRELOFF)
+#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
+#endif
+
+#if !defined (N_SYMOFF)
+#define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize)
+#endif
+
+#if !defined (N_STROFF)
+#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
+#endif
+
+/* Address of text segment in memory after it is loaded.  */
+#if !defined (N_TXTADDR)
+#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? PAGE_SIZE : 0)
+#endif
+
+/* Address of data segment in memory after it is loaded.
+   Note that it is up to you to define SEGMENT_SIZE
+   on machines not listed here.  */
+#if defined(vax) || defined(hp300) || defined(pyr)
+#define SEGMENT_SIZE page_size
+#endif
+#ifdef	sony
+#define	SEGMENT_SIZE	0x2000
+#endif	/* Sony.  */
+#ifdef is68k
+#define SEGMENT_SIZE 0x20000
+#endif
+#if defined(m68k) && defined(PORTAR)
+#define PAGE_SIZE 0x400
+#define SEGMENT_SIZE PAGE_SIZE
+#endif
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE	1024
+#endif
+
+#ifndef SEGMENT_SIZE
+#define SEGMENT_SIZE	PAGE_SIZE
+#endif
+
+#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
+
+#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
+
+#ifndef N_DATADDR
+#define N_DATADDR(x) \
+    (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
+     : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+#endif
+
+/* Address of bss segment in memory after it is loaded.  */
+#if !defined (N_BSSADDR)
+#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
+#endif
+
+
+#if !defined (N_NLIST_DECLARED)
+struct nlist {
+  union {
+    char *n_name;
+    struct nlist *n_next;
+    long n_strx;
+  } n_un;
+  unsigned char n_type;
+  char n_other;
+  short n_desc;
+  unsigned long n_value;
+};
+#endif /* no N_NLIST_DECLARED.  */
+
+#if !defined (N_UNDF)
+#define N_UNDF 0
+#endif
+#if !defined (N_ABS)
+#define N_ABS 2
+#endif
+#if !defined (N_TEXT)
+#define N_TEXT 4
+#endif
+#if !defined (N_DATA)
+#define N_DATA 6
+#endif
+#if !defined (N_BSS)
+#define N_BSS 8
+#endif
+#if !defined (N_FN)
+#define N_FN 15
+#endif
+
+#if !defined (N_EXT)
+#define N_EXT 1
+#endif
+#if !defined (N_TYPE)
+#define N_TYPE 036
+#endif
+#if !defined (N_STAB)
+#define N_STAB 0340
+#endif
+
+/* The following type indicates the definition of a symbol as being
+   an indirect reference to another symbol.  The other symbol
+   appears as an undefined reference, immediately following this symbol.
+
+   Indirection is asymmetrical.  The other symbol's value will be used
+   to satisfy requests for the indirect symbol, but not vice versa.
+   If the other symbol does not have a definition, libraries will
+   be searched to find a definition.  */
+#define N_INDR 0xa
+
+/* The following symbols refer to set elements.
+   All the N_SET[ATDB] symbols with the same name form one set.
+   Space is allocated for the set in the text section, and each set
+   element's value is stored into one word of the space.
+   The first word of the space is the length of the set (number of elements).
+
+   The address of the set is made into an N_SETV symbol
+   whose name is the same as the name of the set.
+   This symbol acts like a N_DATA global symbol
+   in that it can satisfy undefined external references.  */
+
+/* These appear as input to LD, in a .o file.  */
+#define	N_SETA	0x14		/* Absolute set element symbol */
+#define	N_SETT	0x16		/* Text set element symbol */
+#define	N_SETD	0x18		/* Data set element symbol */
+#define	N_SETB	0x1A		/* Bss set element symbol */
+
+/* This is output from LD.  */
+#define N_SETV	0x1C		/* Pointer to set vector in data area.  */
+
+
+#if !defined (N_RELOCATION_INFO_DECLARED)
+/* This structure describes a single relocation to be performed.
+   The text-relocation section of the file is a vector of these structures,
+   all of which apply to the text section.
+   Likewise, the data-relocation section applies to the data section.  */
+
+struct relocation_info
+{
+  /* Address (within segment) to be relocated.  */
+  int r_address;
+  /* The meaning of r_symbolnum depends on r_extern.  */
+  unsigned int r_symbolnum:24;
+  /* Nonzero means value is a pc-relative offset
+     and it should be relocated for changes in its own address
+     as well as for changes in the symbol or section specified.  */
+  unsigned int r_pcrel:1;
+  /* Length (as exponent of 2) of the field to be relocated.
+     Thus, a value of 2 indicates 1<<2 bytes.  */
+  unsigned int r_length:2;
+  /* 1 => relocate with value of symbol.
+          r_symbolnum is the index of the symbol
+	  in file's the symbol table.
+     0 => relocate with the address of a segment.
+          r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
+	  (the N_EXT bit may be set also, but signifies nothing).  */
+  unsigned int r_extern:1;
+  /* Four bits that aren't used, but when writing an object file
+     it is desirable to clear them.  */
+#ifdef NS32K
+  unsigned r_bsr:1;
+  unsigned r_disp:1;
+  unsigned r_pad:2;
+#else
+  unsigned int r_pad:4;
+#endif
+};
+#endif /* no N_RELOCATION_INFO_DECLARED.  */
+
+
+#endif /* __A_OUT_GNU_H__ */
Index: /trunk/minix/commands/mdb/build
===================================================================
--- /trunk/minix/commands/mdb/build	(revision 9)
+++ /trunk/minix/commands/mdb/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/mdb/core.c
===================================================================
--- /trunk/minix/commands/mdb/core.c	(revision 9)
+++ /trunk/minix/commands/mdb/core.c	(revision 9)
@@ -0,0 +1,394 @@
+/* 
+ * core.c for mdb
+ *
+ * reads information from 'core' file
+ * Partly derived from 'adb' by D. Dugger.
+ */
+#include <pm/const.h>
+
+#include "mdb.h"
+
+#include <signal.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ptrace.h>
+
+#include <pm/type.h>
+#include <pm/mproc.h>
+
+#include <kernel/const.h>
+#include <kernel/type.h>
+#include <kernel/proc.h>
+
+/* defined in kernel.c */
+extern struct proc *prc; 
+
+#include "proto.h"
+
+#define BSIZE  512
+#define LOGBS  9
+
+PRIVATE struct file {
+  int fid;
+  char *name;
+  long cblock;
+  long tmap[3];
+  long dmap[3];
+  long smap[3];
+  char buf[BSIZE + BSIZE];
+} Core_File, *core_file;
+
+#define b1	tmap[0]
+#define e1	tmap[1]
+#define f1	tmap[2]
+#define b2	dmap[0]
+#define e2	dmap[1]
+#define f2	dmap[2]
+#define b3	smap[0]
+#define e3	smap[1]
+#define f3	smap[2]
+
+PRIVATE long cnt[3];			/* Sizes of segments   */
+PRIVATE int h_size;			/* Size of core header */
+PRIVATE char def_name[] = "core";	/* Default core name   */
+
+#define SIZE_MP_SEG (sizeof(struct mem_map) * NR_LOCAL_SEGS)
+#define SIZE_KINFO sizeof(struct proc)
+#define SIZE_HEADER SIZE_MP_SEG
+
+FORWARD _PROTOTYPE( int kernel_info , (int fd ));
+FORWARD _PROTOTYPE( void setmap , (struct file *fp ));
+FORWARD _PROTOTYPE( void read_info , (struct file *fp ));
+FORWARD _PROTOTYPE( void ill_addr , (long d , int segment ));
+FORWARD _PROTOTYPE( long map_addr , (long d , int segment ));
+FORWARD _PROTOTYPE( unsigned long c_status, (void));
+FORWARD _PROTOTYPE( long getn, (long d, int s) );
+
+/* 
+ * set and display mapping for core file 
+ */
+PRIVATE void setmap(fp)
+struct file *fp;
+{
+long h = (long) h_size;
+
+  fp->b1 = st_addr;
+  fp->e1 = st_addr + cnt[T];
+  fp->f1 = h;
+
+  fp->b2 = sd_addr; 
+  fp->e2 = sd_addr + cnt[D];
+  fp->f2 = cnt[T] + h;
+
+  fp->b3 = sk_addr;
+  fp->e3 = sk_addr + cnt[S];
+  fp->f3 = cnt[T] + cnt[D] + h;
+
+#ifdef MINIX_PC
+  if(is_separate) {
+	if ( end_addr < et_addr ) end_addr = et_addr;
+  }
+  else {
+	fp->b2 = st_addr;
+	fp->e2 = st_addr + cnt[T] + cnt[D];
+	fp->f2 = h;
+	end_addr = fp->e2;
+
+	fp->b1 = 0;
+	fp->e1 = -1;
+	fp->f1 = 0;
+  }
+#endif
+  Printf("From core file:\n");
+  Printf("T\t%8lx %8lx %8lx\n", core_file->b1, core_file->e1, core_file->f1);
+  Printf("D\t%8lx %8lx %8lx\n", core_file->b2, core_file->e2, core_file->f2);
+  Printf("S\t%8lx %8lx %8lx\n", core_file->b3, core_file->e3, core_file->f3);
+  Printf("\n");
+
+}
+
+/* Print mapping */
+PUBLIC void prtmap()
+{
+  Printf("%s I & D space\t", (is_separate) ? "Separate " : "Combined ");
+  if (corepid > 0) {
+	Printf("File: %s\n\n", core_file->name);
+	setmap(core_file);
+	disp_maps();
+  }
+  else {
+	Printf("Pid:  %d\n\n", curpid);
+	update();
+	disp_maps();
+  }
+}
+
+/* Illegal address */
+PRIVATE void ill_addr(d, segment)
+long d;
+int segment;
+{
+  Printf("Bad addr=%lx seg=%d",d,segment);
+  mdb_error("\n");
+}
+
+/* Map virtual address -> core file addresses
+ * depends on current segment if Separate I & D
+ */
+PRIVATE long map_addr(d, segment)
+long d;
+int segment;
+{
+#ifdef MINIX_PC
+  if (is_separate) 
+	switch (segment) {
+	    case T:
+		if (d >= core_file->b1 && d < core_file->e1)
+			d += core_file->f1 - core_file->b1;
+		else
+			ill_addr(d,segment);
+		break;
+	    case D:
+	    case S:
+		if (d >= core_file->b2 && d < core_file->e2)
+			d += core_file->f2 - core_file->b2;
+		else if (d >= core_file->b3 && d < core_file->e3)
+			d += core_file->f3 - core_file->b3;
+		else
+			ill_addr(d,segment);
+		break;
+	}
+  else {
+#endif
+	if (d >= core_file->b1 && d < core_file->e1)
+		d += core_file->f1 - core_file->b1;
+	else if (d >= core_file->b2 && d < core_file->e2)
+		d += core_file->f2 - core_file->b2;
+	else if (d >= core_file->b3 && d < core_file->e3)
+		d += core_file->f3 - core_file->b3;
+	else
+		ill_addr(d,segment);
+#ifdef	MINIX_PC
+  }
+#endif
+  return d;
+}
+
+
+/* Get value with address d and segment s */
+PRIVATE long getn(d, s)
+long d;
+int s;
+{
+  long b;
+  register int o,i;
+  union {
+	unsigned long l;
+	unsigned char c[4];
+  } data;
+
+  /* Map address */
+  d = map_addr(d, s);
+
+  b = d >> LOGBS;
+  o = d & (BSIZE - 1);
+
+  if (core_file->cblock != b) {
+	core_file->cblock = b;
+	lseek(core_file->fid, b << LOGBS, 0);
+	read(core_file->fid, core_file->buf, sizeof(core_file->buf));
+  }
+
+  for(i = 0; i<4; i++) 
+	data.c[i] = core_file->buf[o+i];
+
+#ifdef DEBUG
+  if (debug) 
+	Printf("getn at %8lx val %8lx\n", d, data.l);
+#endif
+  return data.l;
+}
+
+/* Read kernel info from core file into lbuf[] */
+PRIVATE int kernel_info(fd)
+int fd;
+{
+  int r;
+  int ks;
+
+  /* Round SIZE_KINFO to multiple of sizeof(long) */
+  /* See mm/signal.c to see how a 'core' file is written */
+  ks = ( SIZE_KINFO / sizeof(long) ) * sizeof(long);  	
+  r = read(fd, (char *)lbuf, ks);
+  return(r == ks) ? ks : -1;
+}
+
+/* 
+ * Print status info from core  - returns PC
+ */
+PRIVATE unsigned long c_status()
+{
+  fprintf(stderr, "WARNING: don't know pid from core; using proc nr for pid.\n");
+
+  Printf("Proc = %6d\n", prc->p_nr);
+
+  /* Set current pid to that of core */
+  curpid = corepid = prc->p_nr;
+  disp_maps();
+  Printf("\nPC  = 0x%0*lx\t", 2 * ADDRSIZE, PC_MEMBER(prc) & MASK(ADDRSIZE));
+  symbolic((long) PC_MEMBER(prc), '\n');
+  dasm((long) PC_MEMBER(prc), 1, 1);
+  return PC_MEMBER(prc);
+}
+
+/* Read memory maps and kernel info from core file */
+PRIVATE void read_info(fp)
+struct file *fp;
+{
+  struct mproc mm_info;
+  struct mproc *rmp;
+  int r;
+  int i;
+
+  rmp = &mm_info;
+  lseek(fp->fid, 0L, 0L);
+
+  /* First read memory map of all segments. */
+  if (read(fp->fid, (char *) rmp->mp_seg, (int) SIZE_MP_SEG) < 0) {
+	close(fp->fid);
+	Printf("mdb: cannot read core header\n");
+	fp->fid = -1;
+	return; 
+  }
+  h_size = SIZE_HEADER;
+
+  /* Read kernel dependent info */
+  r = kernel_info(fp->fid);
+  if (r < 0) {
+	close(fp->fid);
+	Printf("mdb: cannot read kernel info from 'core' file\n");
+	fp->fid = -1;
+	return;
+  } else
+	h_size += r;
+
+  /* copy info */ 	
+  for (i = T; i <= S; i++)
+	cnt[i] = (long) rmp->mp_seg[i].mem_len << CLICK_SHIFT;
+
+  /* This needs to be set for map_addr() below */
+  if(coreonly && cnt[T] != 0) is_separate = TRUE;
+
+  st_addr = (long) rmp->mp_seg[T].mem_vir << CLICK_SHIFT;
+  et_addr = st_addr + ((long) rmp->mp_seg[T].mem_len << CLICK_SHIFT);
+
+  sd_addr = (long) rmp->mp_seg[D].mem_vir << CLICK_SHIFT;
+  end_addr = ed_addr = 
+	sd_addr + ((long) rmp->mp_seg[D].mem_len << CLICK_SHIFT);
+
+  sk_addr = (long) rmp->mp_seg[S].mem_vir << CLICK_SHIFT;
+  sk_size = (long) rmp->mp_seg[S].mem_len << CLICK_SHIFT;
+
+  setmap(fp);
+}
+
+/* initialization for core files 
+ * returns PC address from core file 
+ */ 
+PUBLIC unsigned long core_init(filename)
+char *filename;
+{
+  core_file = &Core_File;
+  core_file->name = (filename != NULL) ? filename : def_name;
+
+  core_file->fid = open(core_file->name, 0);
+  if (filename != NULL && core_file->fid < 0) {
+	Printf("mdb - warning cannot open: %s\n", core_file->name);
+	return -1;
+  }
+
+  core_file->b1 = core_file->b2 = core_file->b3 = 0;
+  core_file->e1 = core_file->e2 = core_file->e3 = -1;
+  core_file->f1 = core_file->f2 = core_file->f3 = 0;
+  core_file->cblock = -1;
+
+  if (core_file->fid > 0) {
+	read_info(core_file);
+	return c_status();
+  }
+  return 0;
+}
+
+
+/* initialization for a file ( -f option )  
+ * always returns 0
+ * Similar to core files.
+ */ 
+PUBLIC unsigned long file_init(filename)
+char *filename;
+{
+  core_file = &Core_File;
+  core_file->name = (filename != NULL) ? filename : def_name;
+
+  core_file->fid = open(core_file->name, 0);
+  if (filename != NULL && core_file->fid < 0) {
+	Printf("mdb - warning cannot open: %s\n", core_file->name);
+	return -1;
+  }
+
+  core_file->b1 = core_file->b2 = core_file->b3 = 0;
+  core_file->e1 = core_file->e2 = core_file->e3 = -1;
+  core_file->f1 = core_file->f2 = core_file->f3 = 0;
+  core_file->cblock = -1;
+
+  is_separate = FALSE;	
+  core_file->e1 = file_size(core_file->fid);
+  curpid = corepid = 1;
+  return 0;
+
+}
+
+/* 
+ * Read from core file 
+ * Called by mdbtrace()
+ */
+PUBLIC long read_core(req,  addr, data)
+int req;
+long addr, data;
+{
+int i;
+int segment;
+long val;
+
+	switch (req) {
+	    case T_GETINS:
+	    case T_GETDATA:
+		/* Check segment and address - call getn to read core file */
+		segment = (req == T_GETINS) ? T : D;
+		addr &= MASK(ADDRSIZE);
+		val = getn(addr, segment);
+#ifdef  DEBUG
+		if (debug) Printf("val=>%lx\n", val);
+#endif
+		return val;
+		break;
+	    case T_GETUSER:
+		/* Convert addr to index to long array */
+		i = (int) (addr >> 2);
+#ifdef DEBUG
+		if (debug) Printf("lbuf[%d] %lx\n", i, lbuf[i]);
+#endif
+		return lbuf[i];
+		break;
+	    case T_OK:
+	    case T_EXIT:	
+		return 0L;
+		break;
+	    default:
+		mdb_error("Not supported with 'core' files\n");
+	}
+}
+
Index: /trunk/minix/commands/mdb/decode.c
===================================================================
--- /trunk/minix/commands/mdb/decode.c	(revision 9)
+++ /trunk/minix/commands/mdb/decode.c	(revision 9)
@@ -0,0 +1,360 @@
+/* 
+ * decode.c for mdb -- decodes a Minix system call
+ */
+#include "mdb.h"
+#ifdef SYSCALLS_SUPPORT
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#define ptrace mdbtrace
+#include <sys/ptrace.h>
+#include <minix/type.h>
+#include <minix/callnr.h>
+#include "proto.h"
+
+FORWARD _PROTOTYPE( void get_message, (message *m, unsigned bx) );
+FORWARD _PROTOTYPE( void get_data, (char *s, unsigned bx, int cnt) );
+
+PRIVATE message sent;
+PRIVATE message recv;
+PRIVATE unsigned saved_addr;
+PRIVATE int last_call;
+
+#define NOSYS		0
+#define NOP		1
+
+#define _M1		0x0100
+#define _M2		0x0200
+#define _M3		0x0400
+#define _M4		0x0800
+
+#define _M13		0x0500
+
+#define M1_I1		(_M1|1)
+#define M1_I2		(_M1|2)
+#define M1_I3		(_M1|4)
+#define M1_P1		(_M1|8)
+#define M1_P2		(_M1|16)
+#define M1_P3		(_M1|32)
+
+#define M2_I1		(_M2|1)
+#define M2_I2		(_M2|2)
+#define M2_I3		(_M2|4)
+#define M2_L1		(_M2|8)
+#define M2_L2		(_M2|16)
+#define M2_P1		(_M2|32)
+
+#define M3_I1		(_M3|1)
+#define M3_I2		(_M3|2)
+#define M3_P1		(_M3|4)
+#define M3_C1		(_M3|8)
+
+#define M4_L1		(_M4|1)
+#define M4_L2		(_M4|2)
+#define M4_L3		(_M4|4)
+#define M4_L4		(_M4|8)
+#define M4_L5		(_M4|16)
+
+#define M13_OPEN	(_M13|1)
+
+#define M1_I12		(M1_I1|M1_I2)
+#define M1_NAME1	(M1_I1|M1_P1)
+#define M1_NAME2	(M1_I2|M1_P2)
+#define M1_2NAMES	(M1_I1|M1_P1|M1_I2|M1_P2)
+#define M1_SIGACTION	(M1_I2|M1_P1|M1_P2|M1_P3)
+
+#define M2_IOCTL	(M2_I1|M2_I3|M2_L1|M2_L2)
+#define M2_4P		(M2_I1|M2_I2|M2_L1|M2_L2)
+#define M2_SIGRETURN	(M2_I2|M2_L1|M2_P1)
+#define M2_SIGPROC	(M2_I1|M2_L1)
+#define M2_UTIME	(M2_I1|M2_I2|M2_L1|M2_L2|M2_P1)
+
+#define M3_LOAD 	(M3_I1|M3_C1)
+
+struct decode_system {
+	int syscall;
+	unsigned int sflag;
+	unsigned int rflag;
+	char *name;
+} decode[NCALLS] = {  	
+	0,		NOSYS,		NOP,	NULL,
+	EXIT,		M1_I1,		NOP,	"EXIT",
+	FORK,		NOP,		NOP,	"FORK",
+	READ,		M1_I12,		NOP,	"READ",
+	WRITE,		M1_I12,		NOP,	"WRITE",
+ 	OPEN,		M13_OPEN,	NOP,	"OPEN",
+	CLOSE,		M1_I1,		NOP,	"CLOSE",
+	WAIT,		NOP,		M2_I1,	"WAIT",
+	CREAT,		M3_LOAD,	NOP,	"CREAT",
+	LINK,		M1_2NAMES,	NOP,	"LINK",
+	UNLINK,		M3_LOAD,	NOP,	"UNLINK",
+	WAITPID,	M1_I1,		M2_I1,	"WAITPID",
+	CHDIR,		M3_LOAD,	NOP,	"CHDIR",
+	TIME,		NOP,		M2_L1,	"TIME",
+	MKNOD,		M1_NAME1,	NOP,	"MKNOD",
+	CHMOD,		M3_LOAD,	NOP,	"CHMOD",
+	CHOWN,		M1_NAME1,	NOP,	"CHOWN",
+	BRK,		M1_P1,		M2_P1,	"BRK",
+	STAT,		M1_NAME1,	NOP,	"STAT",
+	LSEEK,		M1_I1,		NOP,	"LSEEK",
+	GETPID,		NOP,		NOP,	"GETPID",
+	MOUNT,		M1_2NAMES,	NOP,	"MOUNT",
+	UMOUNT,		M3_LOAD,	NOP,	"UMOUNT",
+	SETUID,		M1_I1,		NOP,	"SETUID",
+	GETUID,		NOP,		NOP,	"GETUID",
+	STIME,		M2_L1,		NOP,	"STIME",
+	PTRACE,		M2_4P,		NOP,	"PTRACE",
+	ALARM,		M1_I1,		NOP,	"ALARM",
+	FSTAT,		M1_I1,		NOP,	"FSTAT",
+	PAUSE,		NOP,		NOP,	"PAUSE",
+	UTIME,		M2_UTIME,	NOP,	"UTIME",
+	31,		NOSYS,		NOP,	NULL,
+	32,		NOSYS,		NOP,	NULL,
+	ACCESS,		M3_LOAD,	NOP,	"ACCESS",
+	34,		NOSYS,		NOP,	NULL,
+	35,		NOSYS,		NOP,	NULL,
+	SYNC,		NOP,		NOP,	"SYNC",
+	KILL,		M1_I12,		NOP,	"KILL",
+	RENAME,		M1_2NAMES,	NOP,	"RENAME",
+	MKDIR,		M1_NAME1,	NOP,	"MKDIR",
+	RMDIR,		M3_LOAD,	NOP,	"RMDIR",
+	DUP,		NOP,		NOP,	"DUP",
+	PIPE,		NOP,		M1_I12,	"PIPE",
+	TIMES,		M4_L5,		NOP,	"TIMES",
+	44,		NOSYS,		NOP,	NULL,
+	45,		NOSYS,		NOP,	NULL,
+	SETGID,		M1_I1,		NOP,	"SETGID",
+	GETGID,		NOP,		NOP,	"GETGID",
+	SIGNAL,		NOP,		NOP,	"SIGNAL",
+	49,		NOSYS,		NOP,	NULL,
+	50,		NOSYS,		NOP,	NULL,
+	51,		NOSYS,		NOP,	NULL,
+	52,		NOSYS,		NOP,	NULL,
+	53,		NOSYS,		NOP,	NULL,
+	IOCTL,		M2_IOCTL,	M2_IOCTL,	"IOCTL",
+	FCNTL,		M1_I12,		NOP,	"FCNTL",
+#if	ENABLE_SYMLINK
+	RDLINK,		M1_NAME1,	NOP,	"RDLINK",
+	SLINK,		M1_NAME1,	NOP,	"SLINK",
+	LSTAT,		M1_NAME1,	NOP,	"LSTAT",
+#else
+	56,		NOSYS,		NOP,	NULL,
+	57,		NOSYS,		NOP,	NULL,
+	58,		NOSYS,		NOP,	NULL,
+#endif
+	EXEC,		M1_NAME1,	NOP,	"EXEC",
+	UMASK,		M1_I1,		NOP,	"UMASK",
+	CHROOT,		M3_LOAD,	NOP,	"CHROOT",
+	SETSID,		NOP,		NOP,	"SETSID",
+	GETPGRP,	NOP,		NOP,	"GETPGRP",
+	KSIG,		NOSYS,		NOP,	"KSIG",
+	UNPAUSE,	NOSYS,		NOP,	"UNPAUSE",
+	66,		NOSYS,		NOP,	NULL,
+	REVIVE,		NOSYS,		NOP,	"REVIVE",
+	TASK_REPLY,	NOSYS,		NOP,	"TASK_REPLY",
+   	69,		NOSYS,		NOP,	NULL,
+	70,		NOSYS,		NOP,	NULL,
+	SIGACTION,	M1_SIGACTION,	NOP,	"SIGACTION",
+	SIGSUSPEND,	M2_L1,		NOP,	"SIGSUSPEND",
+	SIGPENDING,	NOP,		M2_L1,	"SIGPENDING",
+	SIGPROCMASK,	M2_SIGPROC,	NOP,	"SIGPROCMASK",
+	SIGRETURN,	M2_SIGRETURN,	NOP,	"SIGRETURN",
+	REBOOT,		M1_I1,		NOP,	"REBOOT"
+};
+
+PRIVATE void get_message(m,bx)
+message *m;
+unsigned bx;
+{
+  unsigned addr;
+  int i;
+  long buffer[ MESS_SIZE/4 + 1 ];
+
+  addr = bx;  
+  for (i = 0; i< sizeof(buffer)/4; i++)
+	buffer[i] = ptrace(T_GETDATA,curpid,
+		(long) (addr+i*4) ,0L);
+
+  memcpy(m,buffer,MESS_SIZE);
+
+}
+
+PRIVATE void get_data(s, bx, cnt)
+char *s;
+unsigned bx;
+int cnt;
+{
+  unsigned addr;
+  int i,nl;
+  long buffer[PATH_MAX/4 + 1];
+
+  addr = bx;
+  nl = (cnt / 4) + 1;  
+  for (i = 0; i< nl; i++)
+	buffer[i] = ptrace(T_GETDATA, curpid, (long) (addr+i*4) ,0L);
+
+  memcpy(s, buffer, cnt);
+}
+
+
+PUBLIC void decode_result()
+{
+
+   /* Update message */
+   get_message(&recv,saved_addr);
+   Printf("result=%d\n", recv.m_type);
+
+   if (last_call < 0 || last_call >NCALLS) {
+	Printf("Bad call in decode_result\n");
+	return;
+   }	 
+
+   switch (decode[last_call].rflag) {
+   case NOP:	
+		return; 
+		break;
+   case M1_I12:
+		Printf("m1_l1=%d m1_i2=%d ",recv.m1_i1,recv.m1_i2);
+		break;
+   case M2_IOCTL:
+		decode_ioctl('R',&recv);
+		break;
+   case M2_P1:	
+		Printf("m2_p1=%lx ",(unsigned long)recv.m2_p1);
+		break;
+   case M2_L1:	
+		Printf("m2_l1=%lx ",recv.m2_l1);
+		break;
+   case M2_I1:
+		Printf("m2_i1=%x ",recv.m2_i1);
+		break;
+   default:	
+		Printf("rflag=%d ",decode[last_call].rflag);
+		break;
+   }
+   Printf("\n");	
+}
+
+
+void decode_message(bx)
+unsigned bx;
+{
+int t; 
+int slen;
+unsigned int flag;
+char path[PATH_MAX];
+
+   /* Save address of message */
+   saved_addr = bx;
+   get_message(&sent,bx);
+
+   t = sent.m_type;
+   
+   if ( t <= 0 || t >= NCALLS ) {
+	Printf("Bad call - not in range\n");
+	last_call = 0;
+	return;
+   }
+
+   flag = decode[t].sflag;
+
+   if ( flag == NOSYS) {
+	Printf("Bad call - not in system\n");
+	last_call = 0;
+	return;
+   }
+   else 
+  	last_call = t; 
+
+   Printf(" type %s (%d) ", decode[last_call].name, last_call);
+
+   switch (flag) {
+   case NOP:	
+		break;
+   case M1_I1:	
+   case M1_I12:	
+		Printf("i1=%d ",sent.m1_i1);
+		if ( flag == M1_I1) break;
+   case M1_I2:	
+		Printf("i2=%d ",sent.m1_i2);
+		break;
+   case M1_P1:	
+		Printf("p1=%lx ",(unsigned long)sent.m1_p1);
+		break;
+   case M1_NAME1:
+   case M1_2NAMES:
+		slen = sent.m1_i1;
+		get_data(path, (unsigned long) sent.m1_p1, slen);
+		path[slen] = '\0';
+		Printf("s1=%s ",path);
+		if ( flag == M1_NAME1) break;
+		slen = sent.m1_i2;
+		get_data(path, (unsigned long) sent.m1_p2, slen);
+		path[slen] = '\0';
+		Printf("s2=%s ",path);
+		break;
+   case M2_UTIME:
+		if ( sent.m2_i1 == 0 )
+			slen = sent.m2_i2;
+		else
+			slen = sent.m2_i1;
+		get_data(path, (unsigned long) sent.m2_p1, slen);
+		path[slen] = '\0';
+		Printf("p1=%s ",path);
+		if ( sent.m2_i1 != 0 )
+			Printf("l1=%lx l2=%lx ",sent.m2_l1,sent.m2_l2);
+		break;
+   case M1_SIGACTION:
+		Printf("m1_i2=%d p1=%lx p2=%lx p3=%lx\n",
+			sent.m1_i2,
+			(unsigned long)sent.m1_p1,
+			(unsigned long)sent.m1_p2,
+			(unsigned long)sent.m1_p3);
+		break;
+   case M2_4P:	Printf("m2_i1=%d m2_i2=%d m2_l1=%lx m2_l2=%lx ",
+			sent.m2_i1,sent.m2_i2,sent.m2_l1,sent.m2_l2);
+		break;
+   case M2_L1:
+		Printf("m2_l1=%ld ",sent.m2_l1);
+		break;
+   case M2_IOCTL:
+		decode_ioctl('S',&sent);
+		break;
+   case M2_SIGRETURN:
+		Printf("m2_i2=%d l1=%lx p1=%lx ",
+			sent.m2_i2,sent.m2_l1,
+			(unsigned long)sent.m1_p1);
+		break;
+   case M2_SIGPROC:
+		Printf("m2_i1=%d l1=%lx ", sent.m2_i1,sent.m2_l1);
+		break;
+   case M13_OPEN:
+		if (sent.m1_i2 & O_CREAT) {
+			slen = sent.m1_i1;
+			get_data(path, (unsigned long) sent.m1_p1, slen);
+			path[slen] = '\0';
+			Printf("s1=%s ",path);
+			break;
+		} 		
+		/* fall to M3_LOAD */
+   case M3_LOAD:
+		slen = sent.m3_i1;
+		if ( slen <= M3_STRING) 
+			strncpy(path,sent.m3_ca1,M3_STRING);
+		else
+			get_data(path, (unsigned long) sent.m3_ca1, slen);
+		path[slen] = '\0';
+		Printf("m3_name=%s ",path);
+		break;
+   case M4_L5:
+		Printf("m4_l5=%ld ",sent.m4_l5);
+		break;
+   default:	Printf("sflag=%d ",decode[last_call].sflag);
+		break;
+   }
+   Printf("\n");
+}
+
+#endif /* SYSCALLS_SUPPORT */
Index: /trunk/minix/commands/mdb/gnu_load.c
===================================================================
--- /trunk/minix/commands/mdb/gnu_load.c	(revision 9)
+++ /trunk/minix/commands/mdb/gnu_load.c	(revision 9)
@@ -0,0 +1,76 @@
+/* 
+ * gnu_load for mdb.c
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <gnu/a.out.h>
+
+_PROTOTYPE( unsigned int gnu_load, (char *filename, struct nlist **start) );
+_PROTOTYPE( void do_error, (char *message) );
+
+unsigned int gnu_load( filename, start)
+char *filename;
+struct nlist **start;
+{
+        struct exec header;
+	unsigned int nsym, string_size;
+        char *names;
+        struct nlist *p;
+	int fd;
+
+	if ( (fd = open( filename, 0)) < 0 ||
+	     read( fd, (char *) &header, sizeof header ) != sizeof header )
+	{
+                do_error( "gnu_load" );
+                if ( fd >= 0) close( fd );
+		return 0;
+        }       
+
+        if ( lseek( fd, N_STROFF( header ), 0 ) != N_STROFF( header ) )
+        {
+                do_error( "gnu_load - reading header" );
+                close( fd );
+		return 0;
+        }
+
+        if ( read( fd, (char *) &string_size, sizeof string_size ) < 0 )
+        {
+                do_error( "gnu_load - reading header" );
+                close( fd );
+		return 0;
+        }
+        
+        if ( (int) header.a_syms < 0 || 
+		(unsigned) header.a_syms != header.a_syms ||
+             (*start = (struct nlist *) malloc( (unsigned) header.a_syms + 
+                        string_size ))
+                                == (struct nlist *) NULL &&
+             header.a_syms != 0 )
+        {
+                close( fd );
+                return 0;
+        }
+
+        lseek( fd, N_SYMOFF( header ), 0 );
+
+        if ( read( fd, (char *) *start, (int) header.a_syms + string_size ) < 0 )
+        {
+                do_error( "gnu_load - reading symbols" );
+                close( fd );
+                return 0;
+        }
+        close( fd );
+
+        nsym = (unsigned int) header.a_syms / sizeof (struct nlist);
+        names = (char *) *start + header.a_syms;
+	
+        for ( p = *start; p < *start + nsym; p++) 
+                if(p->n_un.n_strx)
+                        p->n_un.n_name = names + p->n_un.n_strx;
+
+	return nsym;
+}
Index: /trunk/minix/commands/mdb/gnu_sym.c
===================================================================
--- /trunk/minix/commands/mdb/gnu_sym.c	(revision 9)
+++ /trunk/minix/commands/mdb/gnu_sym.c	(revision 9)
@@ -0,0 +1,365 @@
+/* 
+ * gnu_sym.c for mdb 
+ * copied and modified from sym.c
+ * Support GNU Exec symbol tables
+ */
+
+#include "mdb.h"
+
+#ifdef	EXTRA_SYMBOLS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#if	GNU_SUPPORT
+#include <gnu/a.out.h>
+#endif
+#include "proto.h"
+
+#if	GNU_SUPPORT
+_PROTOTYPE( PUBLIC unsigned int gnu_load, (char *filename, struct nlist **start) );
+#endif
+
+struct symtab_s
+{
+	struct nlist *start;
+	struct nlist *end;
+	unsigned int nsym;
+};
+
+PRIVATE struct symtab_s symtab;
+
+FORWARD _PROTOTYPE( void gnu_sort , (struct nlist *array , struct nlist *top ));
+FORWARD _PROTOTYPE( int gnu_symeq , (char *t , struct nlist *sp ));
+FORWARD _PROTOTYPE( int gnu_symprefix , (char *t , struct nlist *sp ));
+FORWARD _PROTOTYPE( struct nlist *gnu_sname, (char *name, int is_text, int allflag) );
+FORWARD _PROTOTYPE( struct nlist *gnu_sval, (off_t value, int where) );
+FORWARD _PROTOTYPE( void gnu_sym, (struct nlist *sp, off_t off) );
+
+PUBLIC void gnu_init( filename )
+char *filename;
+{
+	register struct symtab_s *tp;
+
+	tp = &symtab;
+		
+	tp->nsym = gnu_load(filename, &tp->start);
+	tp->end = tp->start + tp->nsym;
+
+	/* sort on value only, name search not used much and storage a problem */
+	Printf("Sorting %d GNU symbols ....", tp->nsym );
+	gnu_sort( tp->start, tp->end );
+	Printf("\n");
+}
+
+
+
+PUBLIC long gnu_symbolvalue( name, is_text )
+char *name;
+int is_text;
+{
+  register struct nlist *sp;
+  sp = gnu_sname(name,is_text,0);
+  if (sp != NULL)  
+	return sp->n_value;
+  else
+	return 0L;
+}
+
+
+PRIVATE struct nlist *gnu_sname( name, is_text, allflag )
+char *name;
+int is_text;
+int allflag;
+{
+	char *s;
+	unsigned char sclass;
+	int schar;
+	char *send;
+	register struct nlist *sp;
+	register struct symtab_s *tp;
+
+	tp = &symtab;
+
+	if ( allflag )
+	{
+		/* find and print all matching symbols */
+		for ( sp = tp->start; sp < tp->end; ++sp )
+		{
+			if ( gnu_symprefix( name, sp ) )
+			{
+				sp = sp;
+				for ( s = sp->n_un.n_name, send = s + strlen(s);
+				      *s != 0 && s < send; ++s )
+					outbyte( *s );
+				for ( ; s <= send; ++s )
+					outspace();
+				switch( sp->n_type & N_TYPE )
+				{
+					case N_ABS: schar = 'a'; break;
+					case N_TEXT: schar = 't'; break;
+					case N_DATA: schar = 'd'; break;
+					case N_BSS: schar = 'b'; break;
+					default: schar = '?'; break;
+				}
+				if ( (sp->n_type & N_EXT) && schar != '?' )
+					schar += 'A' - 'a';
+				outbyte( schar );
+				outspace();
+				outh32( sp->n_value );
+				outbyte('\n');
+			}
+		}
+	}
+	else
+	{
+		/* find symbol by dumb linear search */
+		for ( sp = tp->start; sp < tp->end; ++sp )
+		{
+			sclass = sp->n_type & N_TYPE;
+			if ( (is_text && sclass == N_TEXT ||
+			      !is_text && (sclass == N_DATA || sclass == N_BSS)) &&
+					 gnu_symeq( name, sp ) )
+				return sp;
+		}
+	}
+	return NULL;
+}
+
+PRIVATE struct nlist *gnu_sval( value, where )
+off_t value;
+int where;
+{
+	int left;
+	int middle;
+	int right;
+	unsigned char sclass;
+	register struct nlist *sp;
+	register struct symtab_s *tp;
+
+	tp = &symtab;
+
+	/* find last symbol with value <= desired one by binary search */
+	for ( left = 0, right = tp->nsym - 1; left <= right; )
+	{
+		middle = (left + right) / 2;
+		sp = tp->start + middle;
+		if ( value < sp->n_value )
+			right = middle - 1;
+		else
+			left = middle + 1;
+	}
+	if ( right >= 0 )
+		/* otherwise tp->start + right may wrap around to > tp->start !! */
+		for ( sp = tp->start + right; sp >= tp->start; --sp )
+		{
+			if ( !(sp->n_type & N_EXT) ) continue; 
+			sclass = sp->n_type & N_TYPE;
+			if ( (where == CSEG && sclass == N_TEXT ||
+						where != CSEG && (sclass == N_DATA || sclass == N_BSS)) )
+			return sp;
+		}
+	return NULL;
+}
+
+
+PRIVATE void gnu_sym( sp, off )
+struct nlist *sp;
+off_t off;
+{
+	register char *s;
+	char *send;
+
+	for ( s = sp->n_un.n_name, send = s + strlen(s); *s != 0 && s < send; ++s )
+		outbyte( *s );
+	if ( (off -= sp->n_value) != 0 )
+	{
+		outbyte( '+' );
+		printhex(off);
+	}
+}
+
+/* shell sort symbols on value */
+
+PRIVATE void gnu_sort( array, top )
+struct nlist *array;
+struct nlist *top;
+{
+	int gap;
+	int i;
+	int j;
+	register struct nlist *left;
+	register struct nlist *right;
+	struct nlist swaptemp;
+	int size;
+
+	size = top - array;
+	/* choose gaps according to Knuth V3 p95 */
+	for ( gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j )
+		;
+	do
+	{
+		for ( j = gap; j < size; ++j )
+			for ( i = j - gap; i >= 0; i -= gap )
+			{
+				left = array + i; 
+				right = array + (i + gap);
+				if ( (off_t) left->n_value <=
+				     right->n_value )
+					break;
+				swaptemp = *left;
+				*left = *right;
+				*right = swaptemp;
+			}
+	}
+	while ( (gap /= 3) != 0 );
+}
+
+PUBLIC void gnu_symbolic( value, separator )
+off_t value;
+int separator;
+{
+	register struct nlist *sp;
+	long off;
+
+	if (value < st_addr || value > end_addr) {
+		outstr("0x");
+		printhex(value);
+		outbyte(separator);
+		return;
+	}
+
+	if ( (sp = gnu_sval( value, CSEG )) != NULL )
+	{
+		gnu_sym( sp, value );
+	}
+	else if ( (sp = gnu_sval( value, DSEG )) != NULL )
+	{
+		gnu_sym( sp, value );
+	}
+	else
+	{
+		outstr("_start");
+		off = value - st_addr; 
+		if ( off != 0 )  
+		{
+		outbyte( '+' );
+		printhex(off);
+		}
+	}
+	outbyte( separator );
+}
+
+
+PRIVATE int gnu_symeq( t, sp )
+register char *t;
+struct nlist *sp;
+{
+	return strncmp( t, sp->n_un.n_name, strlen(t) ) == 0;
+}
+
+PRIVATE int gnu_symprefix( t, sp )
+register char *t;
+struct nlist *sp;
+{
+	register char *s;
+	char *send;
+
+	for ( ; *t == '_'; ++t )
+		;
+	for ( s = sp->n_un.n_name, send = s + strlen(s);
+	      s < send && *s == '_'; ++s )
+		;
+	return strncmp( s, t, send - s ) == 0;
+}
+
+
+
+/* list all symbols - test for selection criteria */
+
+PUBLIC void gnu_listsym( tchar )
+char tchar;
+{
+	register struct symtab_s *tp;
+	register struct nlist *sp;
+	char *s;
+	char *send;
+	char schar;
+
+	outbyte('\n');	
+	tp = &symtab;
+    	for ( sp = tp->start; sp < tp->end; ++sp )
+	{
+	     switch( sp->n_type & N_TYPE )
+	     {
+			case N_ABS:	schar = 'a'; break;
+			case N_TEXT:	schar = 't'; break;
+			case N_DATA:	schar = 'd'; break;
+			case N_BSS:	schar = 'b'; break;
+			default: 	schar = '?'; break;
+	     }
+
+	     if ( (sp->n_type & N_EXT) && schar != '?' )
+		schar += 'A' - 'a';
+
+	     /* check for selection */	
+	     if ( tchar != '*' && schar != tchar)
+		continue; 	
+
+	     /* print symbol type and value */	
+	     outh32( sp->n_value );
+	     outspace();
+	     outbyte( schar );
+	     outbyte( '\t' );	
+	     for ( s = sp->n_un.n_name, send = s + strlen(s);
+		 *s != 0 && s < send; ++s ) outbyte( *s );
+	     outbyte('\n');	
+	}
+}
+
+PUBLIC int gnu_text_symbol(value)
+off_t value;
+{
+struct nlist *sp;
+
+    if ((sp = gnu_sval(value, CSEG)) != NULL && sp->n_value == value)
+    {
+	gnu_sym(sp, value);
+	return TRUE;
+    }
+    else
+	return FALSE;
+}
+
+PUBLIC int gnu_finds_data(off,data_seg)
+off_t off;
+int data_seg;
+{
+struct nlist *sp;
+
+	if ((sp = gnu_sval(off, data_seg)) != NULL)
+   	{
+	    gnu_sym(sp, off);
+	    return TRUE;
+    	}
+    	else 
+	    return FALSE;
+}
+
+PUBLIC int gnu_finds_pc(pc)
+off_t pc;
+{
+struct nlist *sp;
+
+	if ((sp = gnu_sval(pc, CSEG)) != NULL)
+    	{
+	    gnu_sym(sp, pc);
+	    return TRUE;
+        }
+	else
+	    return FALSE;
+}
+
+
+#endif /* EXTRA_SYMBOLS */
Index: /trunk/minix/commands/mdb/io.c
===================================================================
--- /trunk/minix/commands/mdb/io.c	(revision 9)
+++ /trunk/minix/commands/mdb/io.c	(revision 9)
@@ -0,0 +1,304 @@
+/* 
+ * io.c for mdb
+ * all the i/o is here
+ * NB: Printf()
+ */
+#include "mdb.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+#include "proto.h"
+
+#define OUTBUFSIZE	512
+#define PAGESIZE	24
+
+PRIVATE int forceupper = FALSE;
+PRIVATE int someupper = FALSE;
+PRIVATE int stringcount = 0;
+PRIVATE char *string_ptr = NULL;	/* stringptr ambiguous at 8th char */
+PRIVATE char *stringstart = NULL;
+
+PRIVATE char outbuf[OUTBUFSIZE];
+PRIVATE FILE *cmdfile = stdin;
+PRIVATE FILE *outfile = stdout;
+PRIVATE FILE *logfile;
+PRIVATE int lineno;
+
+_PROTOTYPE( int _doprnt, (const char *format, va_list ap, FILE *stream ));
+
+PUBLIC char *get_cmd(cbuf, csize)
+char *cbuf;
+int csize;
+{
+char *r;
+
+  fflush(stdout);
+  if( cmdfile == stdin && outfile == stdout )
+	printf("* ");
+  r = fgets(cbuf, csize, cmdfile);
+  if ( r == NULL && cmdfile != stdin ) {
+	cmdfile = stdin;
+	return get_cmd(cbuf, csize);
+  }
+
+  if ( logfile != NULL ) { 
+	fprintf( logfile, "%s", cbuf );		
+	lineno++;
+  }
+
+  return r;
+}
+
+PUBLIC void openin(s)
+char *s;
+{
+char *t;
+
+  if ((t = strchr(s,'\n')) != NULL) *t = '\0';
+  if ((t = strchr(s,' ')) != NULL) *t = '\0';
+  cmdfile = fopen(s,"r");
+  if (cmdfile == NULL) {
+	Printf("Cannot open %s for input\n",s);
+	cmdfile = stdin; 
+  }
+}
+
+
+/* Special version of printf 
+ * really sprintf()
+ * from MINIX library
+ * followed by outstr()
+ */
+PUBLIC int Printf(const char *format, ...)
+{
+	va_list ap;
+	int retval;
+	FILE tmp_stream;
+
+	va_start(ap, format);
+
+	tmp_stream._fd     = -1;
+	tmp_stream._flags  = _IOWRITE + _IONBF + _IOWRITING;
+	tmp_stream._buf    = (unsigned char *) outbuf;
+	tmp_stream._ptr    = (unsigned char *) outbuf;
+	tmp_stream._count  = 512;
+
+	retval = _doprnt(format, ap, &tmp_stream);
+	putc('\0',&tmp_stream);
+
+	va_end(ap);
+
+        outstr(outbuf);
+
+	return retval;
+}
+
+/* 
+ * Set logging options 
+ */
+PUBLIC void logging( c, name )
+int c;
+char *name;
+{
+char *t;
+
+  if ( c == 'q' && logfile != NULL ) {
+	fclose(logfile);
+	return;
+  }
+
+  if ((t = strchr(name,'\n')) != NULL) *t = '\0';
+  if ((t = strchr(name,' ' )) != NULL) *t = '\0';
+  if ( logfile != NULL ) fclose(logfile);
+ 
+  if ( strlen(name) > 0 ) {
+	logfile = fopen(name,"w");
+
+	if (logfile == NULL) {
+		Printf("Cannot open %s for output\n",name);
+		return; 
+	}
+
+	/* Close standard output file for L */
+  	if ( c == 'L' ) {
+		fclose(outfile);
+		outfile = NULL;
+  	}
+  }
+  else 
+  /* Reset */
+  {
+	if ( logfile != NULL ) fclose(logfile);
+	outfile = stdout;
+	outbyte('\n');
+  }
+
+}
+
+/* Output system error string */
+PUBLIC void do_error(m)
+char *m;
+{
+    outstr(m);
+    outstr(": ");
+    outstr(strerror(errno));   
+    outstr("\n");
+}
+
+PUBLIC void closestring()
+{
+/* close string device */
+
+    stringcount = 0;
+    stringstart = string_ptr = NULL;
+}
+
+PUBLIC int mytolower(ch)
+int ch;
+{
+/* convert char to lower case */
+
+    if (ch >= 'A' && ch <= 'Z')
+	ch += 'a' - 'A';
+    return ch;
+}
+
+
+PUBLIC void openstring(string)
+char *string;
+{
+/* open string device */
+
+    stringcount = 0;
+    stringstart = string_ptr = string;
+}
+
+PUBLIC void outbyte(byte)
+int byte;
+{
+/* print char to currently open output devices */
+
+    if (forceupper && byte >= 'a' && byte <= 'z')
+	byte += 'A' - 'a';
+    if (string_ptr != NULL)
+    {
+	if ((*string_ptr++ = byte) == '\t')
+	    stringcount = 8 * (stringcount / 8 + 1);
+	else
+	    ++stringcount;
+    }
+    else 
+    {
+	if ( paging && byte == '\n' ) {
+		lineno++;		
+		if ( lineno >= PAGESIZE) {
+			if ( cmdfile == stdin ) {
+			     printf("\nMore...any key to continue");
+			     fgets( outbuf, OUTBUFSIZE-1, cmdfile );
+		     	}
+		}
+		lineno = 0;
+	}
+
+	if ( outfile != NULL )  
+		putc(byte,outfile);
+	/* Do not log CR */
+	if ( logfile != NULL && byte != '\r' ) 	
+		putc(byte,logfile); 
+    }
+}
+
+
+PUBLIC void outcomma()
+{
+/* print comma */
+
+    outbyte(',');
+}
+
+PRIVATE char hexdigits[] = "0123456789ABCDEF";
+PUBLIC void outh4(num)
+unsigned num;
+{
+/* print 4 bits hex */
+
+    outbyte(hexdigits[num % 16]);
+}
+
+PUBLIC void outh8(num)
+unsigned num;
+{
+/* print 8 bits hex */
+
+    outh4(num / 16);
+    outh4(num);
+}
+
+PUBLIC void outh16(num)
+unsigned num;
+{
+/* print 16 bits hex */
+
+    outh8(num / 256);
+    outh8(num);
+}
+
+PUBLIC void outh32(num)
+unsigned num;
+{
+/* print 32 bits hex */
+
+    outh16((u16_t) (num >> 16));
+    outh16((u16_t) num);
+}
+
+PUBLIC void outspace()
+{
+/* print space */
+
+    outbyte(' ');
+}
+
+PUBLIC void outstr(s)
+register char *s;
+{
+/* print string */
+
+    while (*s)
+	outbyte(*s++);
+}
+
+PUBLIC void outtab()
+{
+/* print tab */
+
+    outbyte('\t');
+}
+
+PUBLIC void outustr(s)
+register char *s;
+{
+/* print string, perhaps converting case to upper */
+
+    forceupper = someupper;
+    while (*s)
+	outbyte(*s++);
+    forceupper = FALSE;
+}
+
+
+PUBLIC int stringpos()
+{
+/* return current offset of string device */
+
+    return string_ptr - stringstart;
+}
+
+PUBLIC int stringtab()
+{
+/* return current "tab" spot of string device */
+
+    return stringcount;
+}
+
Index: /trunk/minix/commands/mdb/ioctl.c
===================================================================
--- /trunk/minix/commands/mdb/ioctl.c	(revision 9)
+++ /trunk/minix/commands/mdb/ioctl.c	(revision 9)
@@ -0,0 +1,146 @@
+/* 
+ * ioctl.c for mdb -- decode an IOCTL system call
+ */
+#include "mdb.h"
+#ifdef SYSCALLS_SUPPORT
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <minix/type.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include "proto.h"
+
+PRIVATE int get_request;
+
+PRIVATE char *rnames[] = {
+	"TIOCGETP",  
+	"TIOCSETP",
+	"TIOCGETC",
+	"TIOCSETC"
+};
+
+#define GETPNAME	0
+#define SETPNAME	1
+#define GETCNAME	2
+#define SETCNAME	3
+
+/* 
+ * decode ioctl call
+ * send or receive = 'R' or 'S'
+ */
+void decode_ioctl(sr, m)
+int sr;
+message *m;
+{
+int rq;
+int request, device;
+int high;
+long spek, flags;
+int ispeed, ospeed, speed, erase, kill;
+int t_intrc, t_quitc, t_startc, t_stopc, t_brk, t_eof;
+
+   device  = m->m2_i1;
+   request = m->m2_i3;
+   spek    = m->m2_l1;
+   flags   = m->m2_l2;
+
+#ifdef DEBUG
+   if( debug )
+   Printf("%c device=%d request=%c|%d m2_l1=%lx m2_l2=%lx\n",
+	sr,device,
+	(request >> 8) & BYTE,
+	request & BYTE,
+	spek,flags);
+#endif 
+
+   if ( sr == 'R') request = get_request;
+
+   switch(request) {
+     case TIOCGETP:
+     case TIOCSETP:
+	rq = (request == TIOCGETP) ? GETPNAME : SETPNAME;
+	if (sr == 'S') {
+		get_request = request;
+		Printf( "Sending %s ",rnames[rq] );
+		if ( request == TIOCGETP ) break;
+	}
+		
+	if ( (sr == 'R') && (request == TIOCSETP) ) break;
+
+	erase = (spek >> 8) & BYTE;
+	kill  = spek & BYTE;
+  	flags = flags & 0xFFFF;
+	speed = (spek >> 16) & 0xFFFFL;
+	ispeed = speed & BYTE;
+	ospeed = (speed >> 8) & BYTE;
+	Printf("%s erase=%d kill=%d speed=%d/%d flags=%lx ",
+		rnames[rq], erase, kill, ispeed, ospeed, flags);
+	break;
+
+     case TIOCGETC:
+     case TIOCSETC:
+	rq = (request == TIOCGETC) ? GETCNAME : SETCNAME;
+	if (sr == 'S') {
+		get_request = request;
+		Printf( "Sending %s ",rnames[rq] );
+		if ( request == TIOCGETC ) break;
+	}
+
+	if ( (sr == 'R') && (request == TIOCSETC) ) break;
+
+  	t_intrc  = (spek >> 24) & BYTE;
+  	t_quitc  = (spek >> 16) & BYTE;
+  	t_startc = (spek >>  8) & BYTE;
+  	t_stopc  = (spek >>  0) & BYTE;
+	t_brk    = flags & BYTE;
+	t_eof    = (flags >> 8 ) & BYTE;
+	Printf("%s int %d quit %d start %d stop %d brk %d eof %d\n",
+		rnames[rq],
+		t_intrc, t_quitc, t_startc, t_stopc, t_brk, t_eof);
+	break;
+
+     default:
+
+#ifdef	__i86	/* 16 bit */	
+	if ( sr == 'S' ) {
+		Printf("Sending ");
+		get_request = request;
+	}
+	else
+		Printf("Receiving ");
+	
+	Printf("Other IOCTL device=%d request=%c|%d\n",
+		device, (request >> 8) & BYTE, request & BYTE );
+
+	break;
+#endif
+
+#ifdef	__i386	      /* 32 bit encoding */
+	if ( sr == 'S' ) {
+		Printf("Sending (%lx) ",   request);
+		get_request = request;
+	}
+	else
+		Printf("Receiving (%lx) ", request);
+	
+	high = ( request & 0xFFFF0000 ) >> 16 ;
+	request &= _IOCTYPE_MASK;
+
+	Printf("Other IOCTL device=%d request=%c|%d flags=%x size =%d\n",
+		device, (request >> 8) & BYTE, request & BYTE,
+		(high  &  ~_IOCPARM_MASK ),
+		(high  &   _IOCPARM_MASK )
+		);
+	break;
+#endif
+     }	
+     Printf("\n");
+}
+
+
+#endif /* SYSCALLS_SUPPORT */
Index: /trunk/minix/commands/mdb/kernel.c
===================================================================
--- /trunk/minix/commands/mdb/kernel.c	(revision 9)
+++ /trunk/minix/commands/mdb/kernel.c	(revision 9)
@@ -0,0 +1,249 @@
+/*
+ * kernel.c for mdb
+ */
+
+#include "mdb.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define ptrace mdbtrace
+#include <sys/ptrace.h>
+#include "proto.h"
+
+#include <kernel/const.h>
+#include <kernel/type.h>
+#include <kernel/proc.h>
+
+/* Define these here */
+/* buffer for proc and pointer to proc */
+
+#define SIZ (1 + sizeof(struct proc)/sizeof(long))
+
+struct proc *prc;
+long lbuf[SIZ];		
+
+PRIVATE char segment_name[] = "TDS";
+
+/* 
+ * Display memory maps 
+ */
+PUBLIC void disp_maps()
+{
+  int i;
+  long int vir, phy, len;
+
+  Printf("\t  Virtual\t  Physical\tLength\n");
+  Printf("\t  address\t  address\n");
+  for (i = 0; i < strlen(segment_name); i++) {
+	vir = (long) prc->p_memmap[i].mem_vir << CLICK_SHIFT;
+	phy = (long) prc->p_memmap[i].mem_phys << CLICK_SHIFT;
+	len = (long) prc->p_memmap[i].mem_len << CLICK_SHIFT;
+	Printf("%c:\t0x%08.8lx\t0x%08.8lx\t%8ld (0x%08.8lx)\n",
+	       segment_name[i], vir, phy, len, len);
+  }
+}
+
+PUBLIC void update()
+{
+  int i;
+
+  for (i = 0; i < (SIZ - 1); i++)
+	lbuf[i] = ptrace(T_GETUSER, curpid, (long) (i * sizeof(long)), 0L);
+
+  st_addr = (long) prc->p_memmap[T].mem_vir << CLICK_SHIFT;
+  et_addr = st_addr + ( (long) prc->p_memmap[T].mem_len << CLICK_SHIFT );
+
+  sd_addr  = (long) prc->p_memmap[D].mem_vir << CLICK_SHIFT;
+  ed_addr = end_addr = 
+		sd_addr + ( (long) prc->p_memmap[D].mem_len << CLICK_SHIFT );
+
+  sk_addr = (long) prc->p_memmap[S].mem_vir << CLICK_SHIFT;
+  sk_size = (long) prc->p_memmap[S].mem_len << CLICK_SHIFT;
+
+#ifdef MINIX_PC
+  if ( end_addr < et_addr ) end_addr = et_addr;
+#endif
+
+}
+
+PUBLIC int disp_regs()
+{
+   int i;
+
+   if (curpid <= 0) {
+	Printf("No active process.\n");
+	return 1;
+   }
+
+/* Look at kernel/type.h see how this data from the stackframe is laid out */
+
+#if defined(MINIX_PC) && defined(__i86)
+   Printf("\
+ es   ds   di   si   bp   bx   dx   cx   ax   ip   cs   psw  sp   ss\
+\n");
+   for (i = 0; i < 16; i++) 
+	if ( i != 5 && i != 10 ) Printf("%04x ", ((reg_t *) &prc->p_reg)[i]);
+   Printf("\n");
+#endif
+
+#if defined(MINIX_PC) && defined(__i386)
+   Printf("\n");
+   Printf("\
+ fs  gs   ds  es    edi      esi      ebp      ebx      edx\n");
+   for (i = 0; i < 8; i++) 
+	if ( i != 6 ) Printf("%08lx ", ((reg_t *) &prc->p_reg)[i]);
+   Printf("\n\
+  ecx      eax      eip       cs      psw      esp       ss\n");
+   for (; i < 16; i++) 
+	if ( i != 10 ) Printf("%08lx ", ((reg_t *) &prc->p_reg)[i]);
+   Printf("\n");
+#endif
+
+#ifdef MINIX_ST
+   Printf("\npc=%lx psw=%x\n\n",(long)PC_MEMBER(prc), PSW_MEMBER(prc));
+   Printf(
+"      0        1        2        3        4        5        6        7\nD");
+   for (i = 0; i < 8; i++) Printf(" %08lx", ((reg_t *) &prc->p_reg)[i]);
+   Printf("\nA");
+   for (; i < NR_REGS; i++) Printf(" %08lx", ((reg_t *) &prc->p_reg)[i]);
+   Printf(" %08lx\n\n", (long)SP_MEMBER(prc));
+#endif
+   return 0;
+}
+
+/* System dependent core */
+
+#ifdef MINIX_PC
+
+#ifdef __i386
+PRIVATE char regs[] = "fs gs ds es di si bp    bx dx cx ax    ip cs ps sp ss";
+#else
+PRIVATE char regs[] = "es ds di si bp    bx dx cx ax    ip cs ps sp ss";
+#endif
+
+/* Get register for pid at offset k */
+PUBLIC long get_reg(pid, k)
+int pid;
+long k;
+{
+  long off;
+  long val;
+  int reg_size;
+
+  /* Calculate size of register */
+  reg_size = (k < N_REG16 * 2) ? 2 : sizeof(reg_t);
+
+  /* Adjust offset */
+  off = k - (k & (sizeof(long) - 1));
+
+  val = ptrace(T_GETUSER, pid, off, 0L);
+
+  if (k & (sizeof(long) - 1))
+	val >>= BITSIZE(reg_size);
+  else
+	val &= MASK(reg_size);
+  return val;
+}
+
+
+/* Set register for pid at offset k */
+PUBLIC void set_reg(pid, k, value)
+int pid;
+long k;
+long value;
+{
+  long off;
+
+  /* Adjust offset */
+  off = k - (k & (sizeof(long) - 1));
+
+  ptrace(T_SETUSER, pid, off, value);
+
+}
+
+
+PUBLIC long reg_addr(s)
+char *s;
+{
+  long val;
+  char *t;
+  char *send;
+  char q[3];
+
+  if (*s == ' ')
+	mdb_error("Invalid syntax\n");
+  q[0] = tolower(*s);
+  q[1] = tolower(*++s);
+  q[2] = '\0';
+
+  t = regs;
+  send = regs + sizeof(regs);
+  while (t < send) {
+	if (strncmp(q, t, 2) == 0) {
+		val = (long) (t - regs);
+		val /= 3L;
+		if (val < N_REG16 - 1)
+			val = val * 2;
+		else
+			val = (N_REG16 - 1) * 2 +
+				(val - N_REG16 + 1) * sizeof(reg_t);
+		return val;
+	}
+	t += 3;
+  }
+  Printf("Unknown register: %s", q);
+  mdb_error("\n");
+}
+
+
+PUBLIC int outsegreg(num)
+off_t num;
+{
+/* print segment register */
+
+    if ((num % HCLICK_SIZE) != 0 || num >= 0x100000)
+    {
+	Printf("%08x",num);
+	return 8;
+    }
+    Printf("%04x", (u16_t) (num / HCLICK_SIZE) );
+    return 4;
+}
+
+#endif
+
+#ifdef MINIX_ST
+
+/* Get register for pid at offset k */
+PUBLIC long get_reg(pid, k)
+int pid;
+long k;
+{
+  return ptrace(T_GETUSER, pid, k, 0L);
+}
+
+PUBLIC long reg_addr(s)
+char *s;
+{
+  long val;
+
+  switch (*s++) {
+      case 'a':
+      case 'A':	val = 32;	break;
+      case 'd':
+      case 'D':	val = 0;	break;
+      case 'P':
+      case 'p': if (*s != 'c' && *s != 'C') goto error;
+		return 64; 
+		break;
+      default:	goto error;
+  }
+  if (*s >= '0' && *s <= '7') 
+	return val + 4 * (*s - '0');
+error:
+  Printf("Unknown register: %2.2s", s);
+  mdb_error("\n");
+}
+
+#endif
Index: /trunk/minix/commands/mdb/mdb.1
===================================================================
--- /trunk/minix/commands/mdb/mdb.1	(revision 9)
+++ /trunk/minix/commands/mdb/mdb.1	(revision 9)
@@ -0,0 +1,154 @@
+.TH MDB 1
+.SH NAME
+mdb \- Minix debugger
+.SH SYNOPSIS
+.B mdb
+.RB [ \-fc ]
+.I file
+.br
+.B mdb 
+.BR [-L|-l]log\-file
+.I exec-file 
+.RI [ core\-file ]
+.RI [ @command\-file ]
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B mdb
+is the Minix debugger. 
+.SH OPTIONS
+Its command line options are:
+.TP
+.B \-f
+Just examine the specified file.
+.TP
+.B \-c
+Examine 'core' file. No exec-file will be supplied.
+.TP
+.B \-Llog\-file
+Log to file only
+.TP
+.B \-llog\-file
+Log to file.
+.SP 
+.IR exec\-file
+Unless the -c option has been specified, the exec-file is required.
+.SP
+.IR core\-file
+The core-file is optional.
+.SP
+If the core-file is supplied, 
+.B mdb
+assumes that the user wishes to examine the core file.
+Otherwise 
+.B mdb 
+assumes that the user will run the exec-file and trace it.
+.SP
+.IR @command\-file
+.B mdb 
+executes command from command-file.
+.SH OVERVIEW
+.br
+.B mdb 
+commands are of the form: 
+.I [ expression ]
+.I command
+.SP
+.I expression
+can be of the form:
+.IP
+.I address 
+which defaults to text segment
+.IP
+address 
+.I overriden
+by 
+.I T:
+for Text segment
+or 
+.I D:
+for Data segment
+or
+.I S:
+for Stack segment
+.IP
+.I symbol
+where 
+.B mdb 
+does a lookup for the symbol first as a 
+.I text 
+symbol and then as a 
+.I data 
+symbol.
+.SP
+.TP
+.I command
+.SP
+The help command is ?. 
+.SP
+For detailed help on a command type: 
+.I command ?.
+.SP
+A semi-colon can be used to separate commands on a line.
+.SP
+.SH MDB COMMANDS
+.SP
+! Shell escape
+.SP
+#  Set Variable or register
+.SP 
+Tt Current call / Backtrace all
+.SP
+/nsf Display for n size s with format f
+.SP
+Xx [n] Disasm / & display reg for n instructions
+.SP
+Rr a Run / with arguments a
+.SP
+Cc [n] Continue with current signal / no signal n times
+.SP
+Ii [n] Single step with / no signal for n instructions
+.SP
+Mm t n Trace until / Stop when modified t type for n instructions
+.SP
+k  Kill
+.SP
+Bb Display / Set Break-pt
+.SP
+Dd Delete all / one break-points
+.SP
+P Toggle Pagging
+.SP
+Ll name Log to file name / and to standard output
+.SP
+Vv Toggle debug flag / Version info
+.SP
+V Version info
+.SP
+e [t] List symbols for type t
+.SP
+y Print segment mappings
+.SP
+s [n] Dump stack for n words
+.SP
+z [a] Trace syscalls with address a
+.SP
+? Help - short help
+.SP
+@ file Execute commands from file
+.SP
+Qq Quit / and kill traced process
+.SP
+.SH "SEE ALSO"
+.SP
+trace(2).
+.SH DIAGNOSTICS
+
+.SH NOTES
+
+.SH BUGS
+
+.SH AUTHOR
+Philip Murton and others
Index: /trunk/minix/commands/mdb/mdb.c
===================================================================
--- /trunk/minix/commands/mdb/mdb.c	(revision 9)
+++ /trunk/minix/commands/mdb/mdb.c	(revision 9)
@@ -0,0 +1,1028 @@
+/*
+ * mdb.c - MINIX program debugger
+ *
+ * Written by Bruce D. Szablak
+ *
+ * This free software is provided for non-commerical use. No warrantee
+ * of fitness for any use is implied. You get what you pay for. Anyone
+ * may make modifications and distribute them, but please keep this header
+ * in the distribution.
+ */
+
+/*
+ * Originally ported to MINIX-PC and MINIX-386 by Bruce Evans.
+ * NB: the original sym.c and mdbdis86.c come from his 'db'
+ *
+ * Added by Philip Murton:
+ *
+ *  2.0		'Core' file functions
+ *  2.1		Support for GNU exec
+ *  2.2		Changes for Minix 1.6.x Beta
+ *  2.3		Changes for Minix 1.7.0 and trace syscalls
+ *  2.4		Changes for Minix 1.7.2 and clean up
+ *  2.5.1	Add better help 
+ *  2.5.2	Added io.c for logging options
+ *  2.5.3	Minor changes and tested with Minix 1.7.4
+ *  2.5.4	Command arguments processing improved (Thanks to Will Rose)
+ *  2.6.0	Final Version for MINIX CD (Sept/96)
+ */
+
+#define _MAIN_MDB
+#include "mdb.h"
+
+#include <minix/type.h>
+
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/wait.h>
+#define ptrace mdbtrace
+#include <sys/ptrace.h>
+#include <setjmp.h>
+#include "proto.h"
+
+#include <kernel/const.h>
+#include <kernel/type.h>
+#include <kernel/proc.h>
+
+/* buffer for proc and pointer to proc */
+extern struct proc *prc;
+
+#define MAXLINE	128
+#define MAXARG	20
+
+PRIVATE unsigned long lastexp = 0L;	/* last expression and segment */
+PRIVATE int lastseg = NOSEG;
+PRIVATE char *prog;		/* prog name */
+PRIVATE char sbuf[MAXLINE];
+PRIVATE char cbuf[MAXLINE];
+PRIVATE char *cmd;		/* current command   */
+PRIVATE char *cmdstart;		/* start of command  */
+PRIVATE jmp_buf mainlp;
+
+
+struct b_pnt {
+  struct b_pnt *nxt, *prv;
+  long addr;
+  long oldval;
+  char cmd[1];
+} *b_head, *curpnt;
+
+_PROTOTYPE( void main , (int argc, char *argv[]));
+
+FORWARD _PROTOTYPE( void cleanup , (void));
+FORWARD _PROTOTYPE( void freepnt , (struct b_pnt *pnt ));
+FORWARD _PROTOTYPE( void findbpnt , (int verbose ));
+FORWARD _PROTOTYPE( int exebpnt , (int restart ));
+FORWARD _PROTOTYPE( void catch , (int sig ));
+FORWARD _PROTOTYPE( int run , (char *name , char *argstr , int tflg ));
+FORWARD _PROTOTYPE( int dowait , (void));
+FORWARD _PROTOTYPE( void backtrace , (int all ));
+FORWARD _PROTOTYPE( void modify , (long addr , int cnt , int verbose , int size ));
+FORWARD _PROTOTYPE( void display , (long addr , int req ));
+FORWARD _PROTOTYPE( void fill , (long addr , int req ));
+FORWARD _PROTOTYPE( void dorun , (char *cmd ));
+FORWARD _PROTOTYPE( void not_for_core , (void));
+FORWARD _PROTOTYPE( void command , (void));
+
+
+PRIVATE void cleanup()
+{
+  curpid = 0;
+  curpnt = NULL;
+  while (b_head) freepnt(b_head);
+}
+
+PRIVATE void findbpnt(verbose)
+int verbose;
+{
+  for (curpnt = b_head; curpnt; curpnt = curpnt->nxt) {
+	if (curpnt->addr == PC_MEMBER(prc) - BREAKPOINT_ADVANCE) {
+		ptrace(T_SETINS, curpid, curpnt->addr, curpnt->oldval);
+		ptrace(T_SETUSER, curpid, PC_OFF, curpnt->addr);
+#if	SYSCALLS_SUPPORT
+		if( syscalls ) 
+			do_syscall(curpnt->addr);
+		else if (curpnt->cmd[0] != '\n')
+#else
+		if (curpnt->cmd[0] != '\n')
+#endif
+			cmd = strcpy(cbuf, curpnt->cmd);
+		else if (verbose)
+			Printf("Breakpoint hit.\n");
+		return;
+	}
+  }
+  if (verbose) Printf("Unknown breakpoint hit.\n");
+}
+
+PRIVATE int exebpnt(restart)
+int restart;
+{
+  ptrace(T_STEP, curpid, 0L, (long) restart);
+  if (dowait() == 0) return TRUE;
+  ptrace(T_SETINS, curpid, curpnt->addr, BREAK(curpnt->oldval));
+  curpnt = NULL;
+  return FALSE;
+}
+
+
+PRIVATE void freepnt(pnt)
+struct b_pnt *pnt;
+{
+  if (pnt->prv)
+	pnt->prv->nxt = pnt->nxt;
+  else
+	b_head = pnt->nxt;
+  if (pnt->nxt) pnt->nxt->prv = pnt->prv;
+  if (curpid > 0) ptrace(T_SETINS, curpid, pnt->addr, pnt->oldval);
+  free(pnt);
+  if (pnt == curpnt) curpnt = NULL;
+}
+
+
+PUBLIC long breakpt(addr, cmd)
+long addr;
+char *cmd;
+{
+  struct b_pnt *new;
+
+  if (curpid <= 0) {
+	Printf("No active process.\n");
+	return 0L;
+  }
+  for (new = b_head; new; new = new->nxt)
+	if (new->addr == addr) {
+		Printf("Breakpoint already exists here.\n");
+		return 0L;
+	}
+  new = (struct b_pnt *) malloc(sizeof(struct b_pnt) + strlen(cmd));
+  if (new == NULL) {
+	Printf("No room for new breakpoint.\n");
+	return 0L;
+  }
+  new->nxt = b_head;
+  new->prv = 0;
+  if (b_head) b_head->prv = new;
+  b_head = new;
+  new->addr = addr;
+  strcpy(new->cmd, cmd);
+  new->oldval = ptrace(T_GETINS, curpid, addr, 0L);
+  ptrace(T_SETINS, curpid, addr, BREAK(new->oldval));
+  if (ptrace(T_GETINS, curpid, addr, 0L) != BREAK(new->oldval)) {
+	do_error("Can't set breakpoint");
+	freepnt(new);
+	return 0L;
+  }
+  return new->oldval;
+}
+
+PRIVATE void catch(sig)
+int sig;
+{
+  signal(sig, catch);
+  if (sig == SIGINT || sig == SIGQUIT) return;
+  tstart(T_EXIT, 0, sig, 0);
+  exit(0);
+}
+
+
+PRIVATE int dowait()
+{
+  int stat;
+
+  if (corepid > 0) return cursig = 0;
+  while (wait(&stat) != curpid) {};
+  if ( WIFEXITED(stat) ) {
+	if (WEXITSTATUS(stat) != 127) 
+		Printf("child exited with status %d\n", WEXITSTATUS(stat));
+	cleanup();
+	return 0;
+  }
+  if ( WIFSIGNALED(stat) ) {
+	Printf("child terminated by signal %d\n", WTERMSIG(stat) );
+	if (_LOW(stat) & 0x80) Printf("(core dumped)\n");
+	cleanup();
+	return 0;
+  }
+  return cursig = WSTOPSIG(stat);
+}
+
+
+
+PUBLIC void tstart(req, verbose, val, cnt)
+int req, verbose, val, cnt;
+{
+  if (curpid == 0) {
+	if (verbose) Printf("No active process.\n");
+	return;
+  }
+  if (req == T_EXIT) {
+	ptrace(T_EXIT, curpid, 0L, (long) val);
+	dowait();
+	return;
+  }
+  if (cnt == 0) cnt = 1;
+  do {
+	if (curpnt) {
+		if (exebpnt(val)) return;
+		if (req == T_RESUME) cnt++;
+		val = 0;
+	} else {
+		ptrace(req, curpid, 0L, (long) val);
+		if (dowait() == 0) return;
+		val = 0;
+		switch (cursig) {
+		    case SIGEMT:	/* breakpoint */
+			update();
+			findbpnt(cnt <= 1);
+			break;
+		    case SIGTRAP:	/* trace trap? */
+			if (req == T_STEP) break;
+		    default:		/* signal */
+			val = cursig;
+			break;
+		}
+	}
+  }
+  while (--cnt > 0);
+  update();
+  if ( verbose ) dasm((long) PC_MEMBER(prc), 1, 1);
+}
+
+PRIVATE int run(name, argstr, tflg)
+char *name, *argstr;
+int tflg;
+{
+  int procid;
+  char *argv[MAXARG], *inf = NULL, *outf = NULL;
+  int argc;
+
+  if ((procid = fork()) == 0) {
+	/* trace me */
+	if (tflg) ptrace(T_OK, 0, 0L, 0L); 
+	argv[0] = name;
+	for (argc = 1;;) {
+		argstr = skip(argstr);
+		if (*argstr == '\n' || *argstr == ';') {
+			argv[argc] = 0;
+			if (inf) freopen(inf, "r", stdin);
+			if (outf) freopen(outf, "w", stdout);
+			if (tflg) {
+				execv(name, argv);
+				do_error("execv");
+			} else {
+				execvp(name, argv);
+				do_error("execvp");
+			}
+			exit(127);
+		}
+		if (*argstr == '<')
+			inf = argstr + 1;
+		else if (*argstr == '>')
+			outf = argstr + 1;
+		else if (argc == MAXARG) {
+			Printf("Too many arguments.\n");
+			exit(127);
+		} else
+			argv[argc++] = argstr;
+		while (!isspace(*argstr)) argstr++;
+		if (*argstr == '\n') argstr[1] = '\n', argstr[2] = 0;
+		*argstr++ = 0;
+	}
+  }
+  if (procid < 0) do_error("Fork failed.\n");
+  return procid;
+}
+
+
+PRIVATE void dorun(cmd)
+char *cmd;
+{
+  if (curpid = run(prog, cmd, 1)) {
+	if (dowait()) {
+		ptrace(T_SETUSER, curpid, BP_OFF, 0L);
+		update();
+		Printf("Process stopped.\n");
+	}
+  }
+}
+
+/* 
+ * backtrace - inspect the stack
+ */ 
+PRIVATE void backtrace(all)
+int all;
+{
+  unsigned long pc, bp, off, val, obp;
+
+  if (curpid <= 0) {
+	Printf("No process.\n");
+	return;
+  }
+  pc = get_reg(curpid,PC_OFF);
+  bp = get_reg(curpid,BP_OFF);
+  if (bp == 0) {
+	Printf("No active frame.\n");
+	return;
+  }
+  errno = 0;
+  do {
+	symbolic(pc, '(');
+	pc = (ptrace(T_GETDATA, curpid, bp + ADDRSIZE, 0L)
+	      >> SHIFT(ADDRSIZE)) & MASK(ADDRSIZE);
+	off = ptrace(T_GETINS, curpid, pc, 0L);
+#ifdef	DEBUG
+	if(debug)
+	    Printf("Return address %lx Value %lx\n",pc,off);
+#endif
+	obp = bp;
+	bp += 2 * ADDRSIZE;
+
+	/* Check for various instruction used to restore the stack. 
+	 * Should gives us the number of arguments.
+	 * This is obvious dependent on interal features of the 
+	 * compiler used.
+         */ 
+	if (ADDQ(off)) off = ADDQ_CNT(off) + bp;
+#ifdef __mc68000__
+	else if (LEA(off))
+		off = LEA_DISP(off) + bp;
+#endif
+	else if (ADDA(off))
+		off = ADDA_CNT(ptrace(T_GETINS, curpid, pc + 2, 0L)) + bp;
+#if (CHIP == INTEL)
+	else if (INCSP2(off))
+		off = bp + 2*INTSIZE;
+	else if (POPBX2(off))
+		off = bp + 2*INTSIZE;
+	else if (POPCX2(off))
+		off = bp + 2*INTSIZE;
+	else if (POPBX(off))
+		off = bp + INTSIZE;
+	else if (POPCX(off))
+		off = bp + INTSIZE;
+#endif
+	else
+		goto skiplp;
+
+#ifdef DEBUG
+	if (debug) 
+	    Printf("Number of arguments: %d\n",(off-bp)/INTSIZE);
+#endif
+
+	for (;;) {
+		if (errno) return;
+		val = (ptrace(T_GETDATA, curpid, bp, 0L)
+		       >> SHIFT(INTSIZE)) & MASK(INTSIZE);
+		Printf("0x%0*lx", 2 * INTSIZE, val);
+		bp += INTSIZE;
+		if (bp >= off) break;
+		Printf(",");
+	}
+
+skiplp:
+	Printf(")\n");
+	bp = (long) ( (reg_t) ptrace(T_GETDATA, curpid, obp, 0L) );
+#ifdef	DEBUG
+	if(debug)
+		Printf("Old BP %lx New %lx\n",obp,bp);
+#endif
+  }
+  while (all && (reg_t) bp);
+}
+
+PRIVATE void modify(addr, cnt, verbose, size)
+long addr;
+int cnt, verbose, size;
+{
+  long curval, off;
+
+  if (curpid == 0) {
+	Printf("No active process.\n");
+	return;
+  }
+  curval = ptrace(T_GETDATA, curpid, addr, 0L) & MASK(size);
+  do {
+	if (cursig == SIGTRAP) cursig = 0;
+	if (verbose) {
+		off = get_reg(curpid, PC_OFF);
+		dasm(off, 1, 0);
+	}
+	if (curpnt && exebpnt(cursig))
+		return;
+	else {
+		ptrace(T_STEP, curpid, addr, 0L);
+		switch (dowait()) {
+		    case 0:
+			return;
+		    case SIGEMT:
+			update();
+			findbpnt(0);
+			break;
+		}
+	}
+	if (curval != ptrace(T_GETDATA, curpid, addr, 0L) & MASK(size)) {
+		Printf("Modification detected\n");
+		break;
+	}
+  }
+  while (--cnt);
+  update();
+  dasm((long) PC_MEMBER(prc), 1, 1);
+  return;
+}
+
+PRIVATE void display(addr, req)
+long addr;
+int req;
+{
+  int count, size, out, shift;
+  long val, msk;
+  char fmt;
+
+  if (curpid == 0) {
+	Printf("No active process\n");
+	return;
+  }
+  if (req == T_GETDATA && seg == T) req = T_GETINS;
+  count = strtol(cmd, &cmd, 0);
+  if (count == 0) count = 1;
+  cmd = skip(cmd);
+  if (*cmd == 'i' || *cmd == 'I') {
+	dasm(addr, count, *cmd == 'i');
+	return;
+  }
+  if (*cmd == 'y') {
+	symbolic(addr, '\n');
+	return;
+  }
+  switch (*cmd++) {
+      case 'b':	size = sizeof(char);	break;
+      case 'h':	size = sizeof(short);	break;
+      case 'l':	size = sizeof(long);	break;
+      default:  
+	size = sizeof(int);
+	--cmd;
+	break;
+  }
+  switch (fmt = *cmd) {
+      case 'X':
+      case 'D':	
+	size = sizeof(long);
+	break;
+      case 's':
+	addr = ptrace(req, curpid, addr, 0L);
+	req = T_GETDATA;
+      /* Fallthrough */	
+      case 'a':	
+      case 'c':
+	size = sizeof(char);	
+	break;
+  }
+  out = 0;
+  msk = MASK(size);
+  shift = SHIFT(size);
+  do {
+	val = (ptrace(req, curpid, addr, 0L) >> shift) & msk;
+	if (out == 0) Printf("\n0x%0*lx: ", 2 * ADDRSIZE,
+		       (addr >> SHIFT(ADDRSIZE)) & MASK(ADDRSIZE));
+	switch (fmt) {
+	    case 'c':
+		Printf(isprint((int) (UCHAR(val))) ? "   %c " : "\\%03o ",
+					(int) (UCHAR(val)));
+		if (++out == 8) out = 0;
+		break;
+	    case 'u':
+		Printf("%12lu ", val);
+		if (++out == 4) out = 0;
+		break;
+	    case 'x':
+	    case 'X':
+		Printf("%*lx ", 2 * size, val);
+		if (++out == (size == 4 ? 4 : 8)) out = 0;
+		break;
+	    case 'o':
+		Printf("%*lo ", 3 * size, val);
+		if (++out == (size == 4 ? 4 : 8)) out = 0;
+		break;
+	    case 's':
+	    case 'a':
+		if (val)
+			Printf("%c",val);
+		else
+			goto exitlp;
+		if (++out == 64) out = 0;
+		break;
+	    default:
+	    case 'd':
+	    case 'D':
+		Printf("%12ld ", val);
+		if (++out == 4) out = 0;
+		break;
+	}
+	addr += size;
+  }
+  while (--count > 0 || fmt == 's' || fmt == 'a');
+exitlp:
+  Printf("\n");
+}
+
+PRIVATE void fill(addr, req)
+long addr;
+int req;
+{
+  int count, size, shift;
+  long val, msk, nval;
+
+  if (curpid == 0) {
+	Printf("No active process\n");
+	return;
+  }
+  
+  if (req == T_GETDATA && seg == T) {
+	req = T_GETINS;
+	Printf("mdb: warning - modifying text\n");
+  }
+  count = strtol(cmd, &cmd, 0);
+  if ( count == 0 ) count = 1;
+  switch (*cmd++) {
+      case 'b':	size = sizeof(char);	break;
+      case 'h':	size = sizeof(short);	break;
+      case 'l':	size = sizeof(long);	break;
+      default:
+	size = sizeof(int);
+	--cmd;
+	break;
+  }
+  shift = SHIFT(size);
+  msk = MASK(size);
+  cmd = getexp(cmd, &nval, &seg);
+
+#ifdef DEBUG
+  if (debug)
+	Printf("Filling for Count=%d Size=%d val=%lx\n",count,size,nval);
+#endif
+
+  nval <<= shift;
+  do {
+	val = ptrace(req, curpid, addr, 0L) | (nval & msk);
+	val &= (nval | ~msk);
+	ptrace(req + 3, curpid, addr, val);
+	addr += size;
+  }
+  while (--count > 0);
+}
+
+PRIVATE void not_for_core()
+{
+  if (corepid > 0)
+	mdb_error("Illegal command for 'core' file\n");
+}
+
+PRIVATE void command()
+{
+  char c, *p;
+  int i;
+  int size;
+  int stat;
+  long exp, lj, lk;
+  struct b_pnt *bp;
+
+  seg = NOSEG;		/* don't restrict segment expressions are in */
+  cmdstart = cmd = skip(cmd);
+  cmd = getexp(cmd, &exp, &seg);
+
+  if (cmd == cmdstart) {	
+	/* Not an expression */
+	if (corepid < 0) {	/* default to pc for running processs */
+		seg = T;
+		exp = PC_MEMBER(prc);
+	} else {
+		seg = lastseg;
+		exp = lastexp;
+	}
+
+	/* Is it a help command */
+	cmd = skip(cmd+1);
+	if (*cmd == '?') {
+ 		help_on(*cmdstart);
+		*cmd = '\n';
+		return;
+	}
+	else
+	    	cmd = cmdstart;
+  }
+
+  if (seg == NOSEG) seg = T;	/* Absolute becomes Text */
+  lastexp = exp;		/* save last expression	 */
+  lastseg = seg;
+#ifdef DEBUG
+  if(debug)
+	Printf("Current address 0x%0*lx and segment %d\n",  2 * ADDRSIZE, exp, seg);
+
+#endif
+
+  /* Check commands */
+  switch (c = *cmd++) {
+      case 'r':		/* illegal for 'core' files */
+      case 'R':
+      case 'k':
+      case 'B':
+      case 'd':
+      case 'D':		not_for_core();	
+			break;
+
+      case 'b':		/* illegal for 'core' files     */
+      case 'c':		/* Otherwise run process first  */
+      case 'C':
+      case 'm':
+      case 'M':
+#if	SYSCALLS_SUPPORT
+      case 'z':
+#endif
+      case 'i':
+      case 'I':		not_for_core();
+			if (curpid <= 0) dorun("\n");
+			break;
+
+      case 's':		if (curpid <= 0) dorun("\n");
+			break;
+	
+      default:		break;
+  }
+
+  switch (c) {
+      case '!':		/* escape to shell */
+	if (cmd == cmdstart + 1) {
+		cmd = skip(cmd);
+		if (*cmd == '\n' || *cmd == ';') {
+			i = run("/bin/sh", "\n", 0);
+		} else {
+			for (p = cmd + 1; *p && !isspace(*p); p++) {
+			};
+			*p++ = 0;
+			i = run(cmd, *p ? p : "\n", 0);
+		}
+		if (i > 0) while (wait(&stat) != i) {};
+		break;
+	}
+	if (corepid > 0) longjmp(mainlp, 0);
+	break;
+      case 'T':		/* top line of backtrace */
+	backtrace(0);
+	break;
+      case 't':		/* back trace */
+	backtrace(1);
+	break;
+      case '/':		/* print variable value */
+	display(exp, T_GETDATA);
+	break;
+      case 'x':		/* print registers and instruction */
+	if (disp_regs()) break;
+	/* FALLTHROUGH */
+      case 'X':		/* print instruction - X n [, n] */
+	lj = strtol(cmd, &cmd, 0);
+	lk = 0;
+	if (*cmd != '\0') 
+		lk = strtol(++cmd, &cmd, 0);
+	if (curpid > 0)
+		dasm(exp + lk, lj ? lj : 1, 1);
+	else
+		Printf("No active process.\n");
+	break;
+      case 'R':		/* run program with no args */
+      case 'r':		/* run program with args (possibly defaulted) */
+	tstart(T_EXIT, 0, 0, 0);
+	if (c == 'r') {
+		cmd = skip(cmd);
+		if (*cmd == '\n' || *cmd == ';')
+			cmd = sbuf;
+		else
+			strcpy(sbuf, cmd);
+	} else {
+		cmd = "\n";
+	}
+	dorun(cmd);
+	break;
+      case 'c':		/* continue program - ignore signal */
+	cursig = 0;
+      case 'C':		/* continue program - handle signal */
+	i = 0;
+	if (seg == T && curpnt == 0 && cmd != cmdstart + 1) {
+		breakpt(exp, "\n");
+		curpnt = b_head;
+		ptrace(T_SETINS, curpid, curpnt->addr, curpnt->oldval);
+		i = 1;
+	}
+	tstart(T_RESUME, 1, cursig, (int) strtol(cmd, &cmd, 0));
+	/* remove temporary bp */
+	if (i) freepnt(b_head);
+	if (cursig == SIGEMT) return;
+	if (curpid) Printf("Process stopped by signal %d\n", cursig);
+	break;
+      case 'i':		/* single step - ignore signal */
+	tstart(T_STEP, 1, 0, (int) strtol(cmd, &cmd, 0));
+	break;
+      case 'I':		/* single step - handle signal */
+	tstart(T_STEP, 1, cursig, (int) strtol(cmd, &cmd, 0));
+	break;
+      case 'm':		/* single step until location modified */
+      case 'M':		/* single step until location modified - verbose */
+	cmd = skip(cmd);
+	switch (*cmd++) {
+	    case 'b':	size = sizeof(char);	break;
+	    case 'h':	size = sizeof(short);	break;
+	    case 'l':	size = sizeof(long);	break;
+	    default:
+		size = sizeof(int);
+		--cmd;
+		break;
+	}
+	modify(exp, (int) strtol(cmd, &cmd, 0), c == 'M', size);
+	break;
+      case 'k':		/* kill current program */
+	tstart(T_EXIT, 1, 0, 0);
+	break;
+      case 'b':		/* set a breakpoint at the given line */
+#ifdef	MINIX_PC
+	if (seg != T || exp > end_addr ) {
+#else
+	if (seg != T || exp < st_addr || exp > et_addr ) {
+#endif	
+		Printf("Address not in text space.\n");
+		return;
+	}
+	breakpt(exp, skip(cmd));
+	cmd = "\n";
+	return;
+      case 'B':		/* print list of currently active breakpoints */
+	for (i = 1, bp = b_head; bp; bp = bp->nxt, i++) {
+		Printf("%2d: ", i);
+		symbolic((long) bp->addr, '\t');
+		Printf("(0x%lx)\t- %s", bp->addr, bp->cmd);
+	}
+	break;
+      case 'd':		/* delete breakpoint */
+	if (seg == T) {
+		for (bp = b_head; bp && bp->addr != exp; bp = bp->nxt);
+		if (bp) {
+			freepnt(bp);
+			break;
+		}
+	}
+	Printf("No such breakpoint.\n");
+	break;
+      case 'D':		/* delete all breakpoints */
+	while (b_head) freepnt(b_head);
+	break;
+      case 's':
+	dump_stack( strtol(cmd, &cmd, 0) );
+	break;
+      case 'P':
+	paging = !paging;
+	if (paging) Printf("Paging is ON\n");
+	break;
+      case 'l':
+      case 'L':
+	logging(c,skip(cmd));
+	break;
+#if	SYSCALLS_SUPPORT
+      case 'z':
+	start_syscall( strtol(cmd, &cmd, 0) );
+	if ( syscalls ) 
+		Printf("Break point set - use the 'c n' command\n");
+	break;
+#endif
+      case 'q':		/* quit */
+	tstart(T_EXIT, 0, 0, 0);
+	logging(c,cmd);
+      case 'Q':
+	exit(0);	
+	break;
+      case '\n':
+      case ';':
+	if (isdigit(*cmdstart))
+		symbolic(exp, '\n');
+	else
+	        Printf("0x%0*lx\n", 2 * ADDRSIZE, exp);
+	--cmd;
+	break;
+#ifdef	DEBUG
+      case 'v':		/* toggle debug */
+	debug = !debug;
+	if (debug) Printf("Debug flag ON\n");
+	break;
+#endif
+      case 'e':		/* list symbols */
+	listsym(cmd);
+	break;
+      case 'y':		/* print mapping */
+	prtmap();
+	break;
+      case '?':		/* print help */
+	help_page();
+	break;
+      case 'V':		/* print version info */
+	version_info();
+	break;
+      case '@':		/* command file  */
+	cmd = skip(cmd);
+	openin(cmd);
+	*cmd = '\n';
+	return;
+      case '#':		/* set register or variable */
+	cmd = skip(cmd + 1);
+	if (*cmd == '$') {
+		cmd++;
+		i = reg_addr(cmd); 
+		set_reg(curpid, i, strtol(cmd+2, &cmd, 0) );
+		update();
+		break;
+	}
+	cmd = getexp(cmd, &exp, &seg);
+	fill(exp, T_GETDATA);
+	break;
+      default:  
+	help_page();
+	break;
+  }
+  while (*cmd != '\n' && *cmd != ';') ++cmd;
+  if (*cmd == ';') cmd = skip(cmd + 1);
+}
+
+PUBLIC void mdb_error(s)
+char *s;
+{
+  Printf("%s",s);
+  longjmp(mainlp, 0);
+}
+
+PUBLIC void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, c;
+  char *p, *q, *r;
+  int opt_c = FALSE;	/* load core file */
+  int opt_f = FALSE;	/* load object file */
+  int opt_l = FALSE;	/* log to file */
+  int opt_L = FALSE;	/* log to file and screen */
+
+
+  prc = (struct proc *) lbuf;
+  strcpy(sbuf, "\n");
+  corepid = -1;	/* set to indicate none */
+  prog = p = q = r = NULL;
+
+  if ( argc == 1 )
+  {
+	help_page();
+	exit(0);
+  }
+
+  /* Possible combinations of arguments:
+   * A single file name:
+   *	If the name is 'core', the coreonly flag is set.
+   * The -c flag: examine a core file.
+   *	One filename is required with this flag.
+   * The -f flag: examine an object file.
+   *	One file name is required with this flag.
+   * The -L or -l flag: write to a log file.
+   *	One file name is required with these flags.
+   * The -x flag: turn on debugging.
+   *	Used for debugging, and followed by an integer
+   *	argument which is the debugging level.
+   *
+   * If any files remain on the argument list, the first
+   * file is an executable, and the second a core file.
+   * If any filename starts with '@' it is assumed to
+   * to be a command file.  Only one command file is
+   * loaded.
+   */
+
+  /* check for default file name and fake out getopt */
+  if (strcmp(argv[1], "core") == 0) {
+	for (i = argc ; i > 1 ; i--)
+		argv[i] = argv[i - 1];
+	argv[i] = "-c";
+	argc++;
+  }
+
+  /* parse options */
+  opterr = 0;
+  while ((i = getopt(argc, argv, "c:f:L:l:x:")) != EOF) {
+	switch (i & 0377) {
+	case 'c':		/* examine a core file */
+		if (opt_c == TRUE || opt_f == TRUE) {
+			help_page();
+			exit(1);
+		}
+		p = optarg;
+		opt_c = TRUE;
+		break;
+	case 'f':		/* examine an object file */
+		if (opt_c == TRUE || opt_f == TRUE) {
+			help_page();
+			exit(1);
+		}
+		p = optarg;
+		opt_f = TRUE;
+		break;
+	case 'l':		/* start logging */
+		if (opt_l == TRUE || opt_L == TRUE) {
+			help_page();
+			exit(1);
+		}
+		opt_l = TRUE;
+		logging(i, optarg);
+		break;
+	case 'L':		/* start logging */
+		if (opt_l == TRUE || opt_L == TRUE) {
+			help_page();
+			exit(1);
+		}
+		opt_L = TRUE;
+		logging(i, optarg);
+		break;
+#ifdef DEBUG
+	case 'x':		/* set debug level */
+		debug = atoi(optarg);
+		break;
+#endif
+	case '?':		/* default arguments arrive here */
+	default:
+		help_page();
+		exit(1);
+	}
+  }
+
+  /* can't cope without filenames */
+  if (!opt_c && !opt_f && optind >= argc) {
+	help_page();
+	exit(1);
+  }
+
+  /* any remaining arguments are (optional) file names */
+  for (i = optind ; i < argc ; i++) {
+	if (*argv[i] == '@') {			/* command file */
+		if (r == NULL) r = argv[i] + 1;
+	}
+	/* you can't combine a -c or -f object file and a core file */
+	else if (!opt_c && !opt_f && p == NULL) p = argv[i];
+	else if (q == NULL) q = argv[i];	/* core file */
+  }
+
+  /* initialise stuff - fairly tricky logic */
+  coreonly = opt_c;
+  fileonly = opt_f;
+  /* when examining files, prog == NULL */
+  if (!opt_c && !opt_f) {
+	prog = p;
+	syminit(prog);
+  }
+
+  /* file_init is called for non-core files. 
+   * It is very similar to core_init. It opens the file and set
+   * various pointers so that we can read it using the same routines
+   * as a core file. 
+   * NB: Currently there is no special provision to handle object files.
+   */
+
+  /* A comment from Will Rose:
+   * It would be nice to have
+   * symbol tables available when reading a core
+   * or a.out, either as part of the executable or
+   * as a separate file.
+   * At least three separate types of file structure
+   * may be used by mdb - core files, a.out files, and
+   * object files (which may have several flavours).
+   * A set of routines is needed for each type, with
+   * a function switch table initialised  when mdb is
+   * started up.
+   */
+
+  if (opt_c) lastexp = core_init(p);
+  if (opt_f) lastexp = file_init(p);
+  if (q != NULL) lastexp = core_init(q);
+  if (r != NULL) openin(r);
+  for (i = 1; i < _NSIG; i++) signal(i, catch);
+
+  setjmp(mainlp);
+
+  while (get_cmd( cbuf, MAXLINE ) != NULL) {
+	if (strlen(cbuf) == sizeof(cbuf) - 1) {
+		Printf("Command line too long.\n");
+		continue;
+	}
+	cmd = cbuf;
+	command();
+	while (*cmd != '\n') command();
+  }
+  tstart(T_EXIT, 0, 0, 0);
+  exit(0);
+}
Index: /trunk/minix/commands/mdb/mdb.h
===================================================================
--- /trunk/minix/commands/mdb/mdb.h	(revision 9)
+++ /trunk/minix/commands/mdb/mdb.h	(revision 9)
@@ -0,0 +1,182 @@
+/*
+ * mdb.h for mdb
+ */ 
+#define MDBVERSION	"2.6"
+#define MDBBUILD	0
+
+#define	MINIX_SYMBOLS	1
+#define	GNU_SYMBOLS	2
+
+/*
+ * Handle options here 
+ */
+#ifndef GNU_SUPPORT
+#define	GNU_SUPPORT		0
+#endif
+
+#ifndef SYSCALLS_SUPPORT
+#define SYSCALLS_SUPPORT	0
+#endif
+
+#ifdef DEBUG
+#undef DEBUG
+#endif
+
+#ifdef  NDEBUG
+#undef  DEBUG
+#else
+#define DEBUG			1
+#endif
+
+#ifdef	__i386
+#define EXTRA_SYMBOLS		GNU_SUPPORT
+#else
+#define EXTRA_SYMBOLS		0
+#endif
+
+
+#include <minix/config.h>
+#include <ansi.h>
+#include <sys/types.h>
+
+#include <minix/const.h>
+#include <minix/type.h>
+
+#include <limits.h>
+#include <errno.h>
+#include <minix/ipc.h>
+#include <timers.h>
+
+#undef printf		/* defined as printk in <minix/const.h> */
+
+#if (CHIP == M68000)
+#define __mc68000__	/* controls processor-dependent stuff */
+#if (MACHINE == ATARI)
+#define MINIX_ST	/* controls system-dependent stuff */
+#else
+#error "only the MINIX_ST 1.5.x implementation works on 68K's"
+#endif
+#endif
+
+#if (CHIP == INTEL)
+#if (MACHINE == IBM_PC)
+#define MINIX_PC
+#else
+#error "only the MINIX_PC 1.5.x and later versions works on *86's"
+#endif
+#endif
+
+#ifdef MINIX_ST	
+#define BP_OFF ((long)&((struct proc *)0)->p_reg.a6)
+#define PC_MEMBER(rp) ((rp)->p_reg.pc)
+#define PC_OFF ((long)&((struct proc *)0)->p_reg.pc)
+#define SP_MEMBER(rp) ((rp)->p_reg.sp)
+#define PSW_MEMBER(rp) ((rp)->p_reg.psw)
+#endif
+
+#ifdef MINIX_PC
+#define BP_OFF ((long)&((struct proc *)0)->p_reg.fp)
+#define PC_MEMBER(rp) ((rp)->p_reg.pc)
+#define PC_OFF ((long)&((struct proc *)0)->p_reg.pc)
+#endif
+
+#define ADDRSIZE	_WORD_SIZE
+#define BITSIZE(size)	(8 * (size))
+#define INTSIZE		(sizeof(int))	/* not quite right for cross-debugger */
+#define LONGSIZE	(sizeof(long))
+#define UCHAR(x)	((x) & 0xFF)
+#define NOSEG		(-1)	/* no segment */
+
+/* use hardware codes for segments for simplest decoding */
+#define CSEG		0x2E	/* 8088 through 80386 */
+#define DSEG		0x3E
+
+#if (CHIP == INTEL )
+#ifdef __i86
+#define N_REG16	2
+#endif
+#ifdef __i386
+#define N_REG16	4  /* 16 bit registers at start of stackframe */ 
+#endif
+#ifndef N_REG16
+#error "N_REG16 not defined"
+#endif
+#endif
+
+#if (CHIP == INTEL )
+#define ADDA(l) ((u16_t) (l) == 0xC481)
+
+#ifdef __i386
+#define ADDA_CNT(l) ((i32_t) (l))
+#else
+#define ADDA_CNT(l) ((i16_t) (l))
+#endif
+
+#define ADDQ(l) ((u16_t) (l) == 0xC483)
+#define ADDQ_CNT(l) (((((l) >> 16) + 128) & 0x000000FF) - 128)
+#define BREAK(l) (0x000000CC | ((l) & 0xFFFFFF00))
+#define BREAKPOINT_ADVANCE 1
+#define INCSP2(l) ((u16_t) (l) == 0x4444)
+#define POPBX2(l) ((u16_t) (l) == 0x5B5B)
+#define POPBX(l)  ( (l & 0xFF) == 0x5B) 
+
+/* Added for ANSI CC */
+#define POPCX2(l) ((u16_t) (l) == 0x5959)
+#define POPCX(l)  ( (l & 0xFF) == 0x59) 
+
+#endif
+
+#ifdef __mc68000__
+#define ADDA(l) ((int)((l) >> 16) == 0xDFFC)
+#define ADDA_CNT(l) (l)
+#define ADDQ(l) (((l >> 16) & 0xF13F) == 0x500F)
+#define ADDQ_CNT(l) (((((l) >> 25) - 1) & 7) + 1)
+#define BREAK(l) (0xA0000000 | ((l) & 0xFFFF))
+#define BREAKPOINT_ADVANCE 0
+#define BYTES_SWAPPED	/* this assumes WORDS_SWAPPED too */
+#define LEA(l) (((l) >> 16) == 0x4FEF)
+#define LEA_DISP(l) ((long)( l & 0xFFFF)) 
+#endif
+
+#define MASK(size) ((size) >= LONGSIZE ? -1L : (1L << BITSIZE(size)) - 1)
+
+#ifdef BYTES_SWAPPED
+#define SHIFT(size) BITSIZE(LONGSIZE - (size))
+#else
+#define SHIFT(size) (0)
+#endif
+
+#ifdef _MAIN_MDB
+#undef EXTERN
+#define EXTERN
+#endif
+
+extern long lbuf[];		/* buffer for proc	  */ 
+
+EXTERN long st_addr;		/* starting address of text  */
+EXTERN long et_addr;		/* ending address of text    */
+EXTERN long sd_addr;		/* starting address of data  */
+EXTERN long ed_addr;		/* ending address of data  */
+EXTERN long end_addr;		/* ending address of text/data */
+EXTERN long sk_addr;		/* starting address of stack   */
+EXTERN long sk_size;		/* size of stack   */
+EXTERN int curpid;		/* current pid of process/core */
+EXTERN int corepid;		/* pid of core file */
+EXTERN int coreonly;		/* core file only   */
+EXTERN int fileonly;		/* file only        */
+EXTERN int cursig;		/* current signal   */
+EXTERN int seg;			/* segment 	    */
+EXTERN int is_separate;		/* separate I & D   */ 
+EXTERN int paging;		/* paging flag      */
+#ifdef	DEBUG
+EXTERN int debug;		/* debug flag	    */
+#endif
+#if	SYSCALLS_SUPPORT
+EXTERN int syscalls;		/* trace syscalls   */
+#endif
+
+#ifdef _MAIN_MDB
+#undef EXTERN
+#define EXTERN extern
+#endif
+
Index: /trunk/minix/commands/mdb/mdbdis86.c
===================================================================
--- /trunk/minix/commands/mdb/mdbdis86.c	(revision 9)
+++ /trunk/minix/commands/mdb/mdbdis86.c	(revision 9)
@@ -0,0 +1,1564 @@
+/* 
+ * mdbdis86.c for mdb.c - 8086-386 and 8087 disassembler
+ * From Bruce Evans db
+ */
+
+#include "mdb.h"
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include "proto.h"
+
+struct address_s
+{
+    off_t off;
+    off_t base;
+};
+
+PRIVATE int bits32;
+PRIVATE struct address_s uptr;
+
+FORWARD _PROTOTYPE( u8_t  get8, (void) );
+FORWARD _PROTOTYPE( u16_t get16, (void) );
+FORWARD _PROTOTYPE( u32_t get32, (void) );
+FORWARD _PROTOTYPE( u8_t  peek_byte,  (off_t addr) );
+FORWARD _PROTOTYPE( u16_t peek_word,  (off_t addr) );
+FORWARD _PROTOTYPE( int puti, (void) );
+FORWARD _PROTOTYPE( int outsegaddr, (struct address_s *addr) );
+FORWARD _PROTOTYPE( int outssegaddr, (struct address_s *addr) );
+FORWARD _PROTOTYPE( int show1instruction , (void));
+
+/************************* UNASM ******************************/
+
+
+#define LINDIRECT	'['
+#define RINDIRECT	']'
+
+#define BASE_MASK	0x07
+#define INDEX_MASK	0x38
+#define INDEX_SHIFT	3
+#define MOD_MASK	0xC0	/* mod reg r/m  is  mmrrrRRR */
+#define REG_MOD		0xC0
+#define MEM0_MOD	0x00
+#define MEM1_MOD	0x40
+#define MEM2_MOD	0x80
+#define REG_MASK	0x38
+#define REG_SHIFT	3
+#define RM_MASK		0x07
+#define RM_SHIFT	0
+#define SS_MASK		0xC0
+#define SS_SHIFT	6
+
+#define SIGNBIT		0x02	/* opcode bits xxxxxxsw for immediates */
+#define WORDBIT		0x01
+#define TOREGBIT	0x02	/* opcode bit for non-immediates */
+
+#define MAX_SIGNED_CHAR	0x7F	/* will assume 2's complement */
+#define MAX_UNSIGNED_CHAR	0xFF
+
+typedef unsigned opcode_pt;	/* promote to unsigned and not int */
+
+typedef int reg_pt;
+typedef int su16_t;
+typedef int su8_pt;
+
+FORWARD _PROTOTYPE(  su8_pt get8s , (void));
+FORWARD _PROTOTYPE(  void getmodregrm , (void));
+FORWARD _PROTOTYPE(  void i_00_to_3f , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_40_to_5f , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_60_to_6f , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_70_to_7f , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_80 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_88 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_90 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_98 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_a0 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_a8 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_b0 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_b8 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_c0 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_c8 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_d0 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_d8 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_e0 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_e8 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_f0 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void i_f8 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void outad , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void outad1 , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void outalorx , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void outax , (void));
+FORWARD _PROTOTYPE(  void outbptr , (void));
+FORWARD _PROTOTYPE(  void outbwptr , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void outea , (opcode_pt wordflags ));
+FORWARD _PROTOTYPE(  void outf1 , (void));
+FORWARD _PROTOTYPE(  void out32offset , (void));
+FORWARD _PROTOTYPE(  void outfishy , (void));
+FORWARD _PROTOTYPE(  void outgetaddr , (void));
+FORWARD _PROTOTYPE(  void outimmed , (opcode_pt signwordflag ));
+FORWARD _PROTOTYPE(  void outpc , (off_t pc ));
+FORWARD _PROTOTYPE(  void outsegpc , (void));
+FORWARD _PROTOTYPE(  void oututstr , (char *s ));
+FORWARD _PROTOTYPE(  void outword , (void));
+FORWARD _PROTOTYPE(  void outwptr , (void));
+FORWARD _PROTOTYPE(  void outwsize , (void));
+FORWARD _PROTOTYPE(  void pagef , (void));
+FORWARD _PROTOTYPE(  void shift , (opcode_pt opc ));
+FORWARD _PROTOTYPE(  void checkmemory , (void));
+FORWARD _PROTOTYPE(  void CL , (void));
+FORWARD _PROTOTYPE(  void Eb , (void));
+FORWARD _PROTOTYPE(  void Ev , (void));
+FORWARD _PROTOTYPE(  void EvGv , (void));
+FORWARD _PROTOTYPE(  void EvIb , (void));
+FORWARD _PROTOTYPE(  void Ew , (void));
+FORWARD _PROTOTYPE(  void EwRw , (void));
+FORWARD _PROTOTYPE(  void Gv , (void));
+FORWARD _PROTOTYPE(  void Gv1 , (void));
+FORWARD _PROTOTYPE(  void GvEv , (void));
+FORWARD _PROTOTYPE(  void GvEw , (void));
+FORWARD _PROTOTYPE(  void GvM , (void));
+FORWARD _PROTOTYPE(  void GvMa , (void));
+FORWARD _PROTOTYPE(  void GvMp , (void));
+FORWARD _PROTOTYPE(  void Ib , (void));
+FORWARD _PROTOTYPE(  void Iw , (void));
+FORWARD _PROTOTYPE(  void Iv , (void));
+FORWARD _PROTOTYPE(  void Jb , (void));
+FORWARD _PROTOTYPE(  void Jv , (void));
+FORWARD _PROTOTYPE(  void Ms , (void));
+
+_PROTOTYPE( typedef void (*pfv_t),(opcode_pt opc ));
+
+PRIVATE pfv_t optable[] =
+{
+ i_00_to_3f,
+ i_00_to_3f,
+ i_00_to_3f,
+ i_00_to_3f,
+ i_00_to_3f,
+ i_00_to_3f,
+ i_00_to_3f,
+ i_00_to_3f,
+ i_40_to_5f,
+ i_40_to_5f,
+ i_40_to_5f,
+ i_40_to_5f,
+ i_60_to_6f,
+ i_60_to_6f,
+ i_70_to_7f,
+ i_70_to_7f,
+ i_80,
+ i_88,
+ i_90,
+ i_98,
+ i_a0,
+ i_a8,
+ i_b0,
+ i_b8,
+ i_c0,
+ i_c8,
+ i_d0,
+ i_d8,
+ i_e0,
+ i_e8,
+ i_f0,
+ i_f8,
+};
+
+PRIVATE char fishy[] = "???";
+PRIVATE char movtab[] = "mov\t";
+
+PRIVATE char *genreg[] =
+{
+ "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
+ "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
+ "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
+};
+
+PRIVATE char *segreg[] =
+{
+ "es", "cs", "ss", "ds", "fs", "gs", "?s", "?s",
+};
+
+PRIVATE char *indreg[] =
+{
+ "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx",
+};
+
+PRIVATE char *str_00_to_3f[] =
+{
+ /* index by (opcode >> 3) & 7 */
+ "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp",
+};
+
+PRIVATE char *sstr_00_to_3f[] =
+{
+ /* index ((opc>>2) & 0x0E) + (opc & 7) - 6 */
+ "push\tes", "pop\tes", "push\tcs", "pop\tcs",
+ "push\tss", "pop\tss", "push\tds", "pop\tds",
+ "es:", "daa", "cs:", "das", "ss:", "aaa", "ds:", "aas",
+};
+
+PRIVATE char *sstr_0f[] =
+{
+ "push\tfs", "pop\tfs", fishy, "bt\t", "shld\t", "shld\t", fishy, fishy,
+ "push\tgs", "pop\tgs", fishy, "bts\t", "shrd\t", "shrd\t", fishy, "imul\t",
+ fishy, fishy, "lss\t", "btr\t", "lfs\t", "lgs\t", "movzx\t", "movzx\t",
+ fishy, fishy, "", "btc\t", "bsf\t", "bsr\t", "movsx\t", "movsx\t",
+};
+
+PRIVATE char *ssstr_0f[] =
+{
+ "sldt\t", "str\t", "lldt\t", "ltr\t", "verr\t", "verw\t", fishy, fishy,
+ "sgdt\t", "sidt\t", "lgdt\t", "lidt\t", "smsw\t", fishy, "lmsw\t", fishy,
+ fishy, fishy, fishy, fishy, "bt\t", "bts\t", "btr\t", "btc\t",
+};
+
+PRIVATE char *str_40_to_5f[] =
+{
+ /* index by (opcode >> 3) & 3 */
+ "inc\t", "dec\t", "push\t", "pop\t",
+};
+
+PRIVATE char *str_60_to_6f[] =
+{
+ "pusha", "popa", "bound\t", "arpl\t", "fs:", "gs:", "os:", "as:",
+ "push\t", "imul\t", "push\t", "imul\t", "insb", "ins", "outsb", "outs",
+};
+
+PRIVATE char *str_flags[] =
+{
+ /* opcodes 0x70 to 0x7F, and 0x0F80 to 0x0F9F */
+ "o", "no", "b", "nb", "z", "nz", "be", "a",
+ "s", "ns", "pe", "po", "l", "ge", "le", "g",
+};
+
+PRIVATE char *str_98[] =
+{
+ "cbw", "cwd", "call\t", "wait", "pushf", "popf", "sahf", "lahf",
+ "cwde", "cdq", "call\t", "wait", "pushfd", "popfd", "sahf", "lahf",
+};
+
+PRIVATE char *str_a0[] =
+{
+ movtab, movtab, movtab, movtab, "movsb", "movs", "cmpsb", "cmps",
+};
+
+PRIVATE char *str_a8[] =
+{
+ "test\t", "test\t", "stosb", "stos", "lodsb", "lods", "scasb", "scas",
+};
+
+PRIVATE char *str_c0[] =
+{
+ "", "", "ret\t", "ret", "les\t", "lds\t", movtab, movtab,
+};
+
+PRIVATE char *str_c8[] =
+{
+ "enter\t", "leave", "retf\t", "retf", "int\t3", "int\t", "into", "iret",
+};
+
+PRIVATE char *str_d0[] =
+{
+ "aam", "aad", "db\td6", "xlat",
+};
+
+PRIVATE char *sstr_d0[] =
+{
+ "rol", "ror", "rcl", "rcr", "shl", "shr", fishy, "sar",
+};
+
+PRIVATE char *str_d8[] =
+{
+ "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr",
+ "fld", NULL, "fst", "fstp", "fldenv", "fldcw", "fstenv", "fstcw",
+ "fiadd", "fimul", "ficom", "ficomp", "fisub", "fisubr", "fidiv", "fidivr",
+ "fild", NULL, "fist", "fistp", NULL, "fld", NULL, "fstp",
+ "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr",
+ "fld", NULL, "fst", "fstp", "frstor", NULL, "fsave", "fstsw",
+ "fiadd", "fimul", "ficom", "ficomp", "fisub", "fisubr", "fidiv", "fidivr",
+ "fild", NULL, "fist", "fistp", "fbld", "fild", "fbstp", "fistp",
+};
+
+PRIVATE char *str1_d8[] =
+{
+ "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr",
+ "fld", "fxch", "\0\0", NULL, "\0\10", "\0\20", "\0\30", "\0\40",
+ NULL, NULL, NULL, NULL, NULL, "\0\50", NULL, NULL,
+ NULL, NULL, NULL, NULL, "\0\60", NULL, NULL, NULL,
+ "fadd", "fmul", NULL, NULL, "fsubr", "fsub", "fdivr", "fdiv",
+ "ffree", NULL, "fst", "fstp", "fucom", "fucomp", NULL, NULL,
+ "faddp", "fmulp", NULL, "\0\70", "fsubrp", "fsubp", "fdivrp", "fdivp",
+ NULL, NULL, NULL, NULL, "\0\100", NULL, NULL, NULL,
+};
+
+PRIVATE unsigned char size_d8[] =
+{
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 14-28, 2, 14-28, 2,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 0, 10, 0, 10,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 8, 8, 94-108, 0, 94-108, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 10, 8, 10, 8,
+};
+
+PRIVATE char *sstr_d8[] =
+{
+ "fnop", NULL, NULL, NULL,			/* D9D0 */
+ NULL, NULL, NULL, NULL,
+ "fchs", "fabs", NULL, NULL,			/* D9E0 */
+ "ftst", "fxam", NULL, NULL,
+ "fld1", "fldl2t", "fldl2e", "fldpi",		/* D9E8 */
+ "fldlg2", "fldln2", "fldz", NULL,
+ "f2xm1", "fyl2x", "fptan", "fpatan",		/* D9F0 */
+ "fxtract", "fprem1", "fdecstp", "fincstp",
+ "fprem", "fyl2xp1", "fsqrt", "fsincos",	/* D9F8 */
+ "frndint", "fscale", "fsin", "fcos",
+ NULL, "fucompp", NULL, NULL,			/* DAE8 */
+ NULL, NULL, NULL, NULL,
+ "feni", "fdisi", "fclex", "finit",		/* DBE0 */
+ "fsetpm", NULL, NULL, NULL,
+ NULL, "fcompp", NULL, NULL,			/* DED8 */
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,			/* DFE0 */
+ "fstsw\tax", NULL, NULL, NULL,
+};
+
+PRIVATE char *str_e0[] =
+{
+ "loopnz\t", "loopz\t", "loop\t", "jcxz\t",
+ "in\t", "in\t", "out\t", "out\t",
+};
+
+PRIVATE char *str_e8[] =
+{
+ "call\t", "jmp\t", "jmp\t", "jmp\t",
+ "in\t", "in\t", "out\t", "out\t",
+};
+
+PRIVATE char *str_f0[] =
+{
+ "lock\t", "db\tf1", "repnz\t", "repz\t",
+ "hlt", "cmc",
+ /* other 2 from sstr_f0 */
+};
+
+PRIVATE char *sstr_f0[] =
+{
+ "test\t", fishy, "not\t", "neg\t",
+ "mul\t", "imul\t", "div\t", "idiv\t",
+};
+
+PRIVATE char *str_f8[] =
+{
+ "clc", "stc", "cli", "sti",
+ "cld", "std",
+ /* other 2 from sstr_f8 */
+};
+
+PRIVATE char *sstr_f8[] =
+{
+ "inc\t", "dec\t", "call\t", "call\tfar ",
+ "jmp\t", "jmp\tfar ", "push\t", "???\t",
+};
+
+PRIVATE int data_seg;		/* data segment (munged name for asld) */
+PRIVATE unsigned hasize;	/* half address size in bits */
+PRIVATE unsigned hdefsize;
+PRIVATE unsigned hosize;	/* half operand size in bits */
+				/* for easy index into reg tables */
+PRIVATE opcode_pt mod;
+PRIVATE off_t offtable[2];
+PRIVATE off_t *offptr;
+PRIVATE off_t *off1ptr;
+PRIVATE opcode_pt reg;
+PRIVATE opcode_pt rm;
+
+PRIVATE su8_pt get8s()
+{
+    u8_t got;
+
+    if ((got = get8()) > MAX_SIGNED_CHAR)
+	got -= (MAX_UNSIGNED_CHAR + 1);
+    return got;
+}
+
+PRIVATE void getmodregrm()
+{
+    opcode_pt modregrm;
+    
+    modregrm = get8();
+    mod = modregrm & MOD_MASK;
+    reg = (modregrm & REG_MASK) >> REG_SHIFT;
+    rm = (modregrm & RM_MASK) >> RM_SHIFT;
+}
+
+PRIVATE void i_00_to_3f(opc)
+opcode_pt opc;
+{
+    opcode_pt sub;
+    
+    if (opc == 15)
+	pagef();
+    else if ((sub = opc & 7) >= 6)
+    {
+	outustr((sstr_00_to_3f - 6)[((opc >> 2) & 0x0E) + sub]);
+	if (!(opc & 1))
+	    data_seg = opc;
+    }
+    else
+    {
+	oututstr(str_00_to_3f[(opc >> 3) & 7]);
+	if (sub == 4)
+	{
+	    outustr(genreg[0]);
+	    outcomma();
+	    Ib();
+	}
+	else if (sub == 5)
+	{
+	    outax();
+	    outcomma();
+	    Iv();
+	}
+	else
+	    outad(sub);
+    }
+}
+
+PRIVATE void i_40_to_5f(opc)
+opcode_pt opc;
+{
+    outustr(str_40_to_5f[(opc >> 3) & 3]);
+    outustr(genreg[hosize + (opc & 7)]);
+}
+
+PRIVATE void i_60_to_6f(opc)
+opcode_pt opc;
+{
+/* most for 386, some for 286 */
+
+    outustr((str_60_to_6f - 0x60)[opc]);
+    switch (opc)
+    {
+    case 0x60:
+    case 0x61:
+	if (hosize == 16)
+	    outwsize();
+	break;
+    case 0x62:
+	GvMa();
+	break;
+    case 0x63:
+	EwRw();
+	break;
+    case 0x64:
+    case 0x65:
+	data_seg = opc;
+	break;
+    case 0x66:
+	hosize = (16 + 8) - hdefsize;
+	break;
+    case 0x67:
+	hasize = (16 + 8) - hdefsize;
+	break;
+    case 0x68:
+	outword();
+	Iv();
+	break;
+    case 0x6A:
+	outword();
+	outimmed(SIGNBIT | WORDBIT);
+	break;
+    case 0x69:
+	GvEv();
+	outcomma();
+	Iv();
+	break;
+    case 0x6B:
+	GvEv();
+	outcomma();
+	outimmed(SIGNBIT | WORDBIT);
+	break;
+    case 0x6D:
+    case 0x6F:
+	outwsize();
+	break;
+    }
+}
+
+PRIVATE void i_70_to_7f(opc)
+opcode_pt opc;
+{
+    outustr("j");
+    oututstr((str_flags - 0x70)[opc]);
+    Jb();
+}
+
+PRIVATE void i_80(opc)
+opcode_pt opc;
+{
+    if (opc >= 4)
+    {
+	outustr(opc >= 6 ? "xchg\t" : "test\t");
+	outad(opc);
+    }
+    else
+    {
+	getmodregrm();
+	oututstr(str_00_to_3f[reg]);
+	outbwptr(opc);
+	outea(opc);
+	outcomma();
+	outimmed(opc);
+#ifdef SIGNED_LOGICALS
+	if (opc & SIGNBIT && (reg == 1 || reg == 4 || reg == 6))
+	    /* and, or and xor with signe extension are not documented in some
+	     * 8086 and 80286 manuals, but make sense and work
+	     */
+	    outfishy();
+#endif
+    }
+}
+
+PRIVATE void i_88(opc)
+opcode_pt opc;
+{
+    if (opc < 4)
+    {
+	outustr(movtab);
+	outad(opc);
+    }
+    else if (opc == 5)
+    {
+	oututstr("lea");
+	GvM();
+    }
+    else if (opc == 7)
+    {
+	oututstr("pop");
+	getmodregrm();
+	outwptr();
+	Ev();
+	if (reg != 0)
+	    outfishy();
+    }
+    else
+    {
+	getmodregrm();
+	outustr(movtab);
+	if (!(opc & TOREGBIT))
+	{
+	    Ev();
+	    outcomma();
+	}
+	outustr(segreg[reg]);
+	if (opc & TOREGBIT)
+	{
+	    outcomma();
+	    Ev();
+	}
+    }
+}
+
+PRIVATE void i_90(opc)
+opcode_pt opc;
+{
+    if (opc == 0)
+	outustr("nop");
+    else
+    {
+	outustr("xchg\t");
+	outax();
+	outcomma();
+	outustr(genreg[hosize + opc]);
+    }
+}
+
+PRIVATE void i_98(opc)
+opcode_pt opc;
+{
+    outustr((str_98 - 8)[opc + hosize]);
+    if (opc == 2)
+	outsegpc();
+}
+
+PRIVATE void i_a0(opc)
+opcode_pt opc;
+{
+    outustr(str_a0[opc]);
+    if (opc < 4)
+    {
+	mod = MEM0_MOD;		/* fake */
+	reg = 0;		/* fake ax */
+	if (hasize == 16)
+	    rm = 5;		/* fake [d16] */
+	else
+	    rm = 6;		/* fake [d32] */
+	outad1(opc ^ TOREGBIT);
+    }
+    else if (opc & 1)
+	outwsize();
+}
+
+PRIVATE void i_a8(opc)
+opcode_pt opc;
+{
+    outustr(str_a8[opc]);
+    if (opc < 2)
+    {
+	outalorx(opc);
+	outcomma();
+	outimmed(opc);
+    }
+    else if (opc & 1)
+	outwsize();
+}
+
+PRIVATE void i_b0(opc)
+opcode_pt opc;
+{
+    outustr(movtab);
+    outustr(genreg[opc]);
+    outcomma();
+    Ib();
+}
+
+PRIVATE void i_b8(opc)
+opcode_pt opc;
+{
+    outustr(movtab);
+    outustr(genreg[hosize + opc]);
+    outcomma();
+    Iv();
+}
+
+PRIVATE void i_c0(opc)
+opcode_pt opc;
+{
+    outustr(str_c0[opc]);
+    if (opc >= 6)
+    {
+	getmodregrm();
+	outbwptr(opc);
+	outea(opc);
+	outcomma();
+	outimmed(opc & WORDBIT);
+	if (reg != 0)
+	    /* not completely decoded (like DEBUG) */
+	    outfishy();
+    }
+    else if (opc >= 4)
+	GvMp();
+    else if (opc == 2)
+	Iv();
+    else if (opc < 2)
+	shift(opc);
+}
+
+PRIVATE void i_c8(opc)
+opcode_pt opc;
+{
+    outustr(str_c8[opc]);
+    if (opc == 0)
+    {
+	Iw();
+	outcomma();
+	Ib();
+    }
+    if (opc == 2)
+	Iv();
+    else if (opc == 5)
+	Ib();
+    else if (opc == 7 && hosize == 16)
+	outwsize();
+}
+
+PRIVATE void i_d0(opc)
+opcode_pt opc;
+{
+    opcode_pt aabyte;
+
+    if (opc < 4)
+	shift(opc | 0xD0);
+    else
+    {
+	outustr((str_d0 - 4)[opc]);
+	if (opc < 6 && (aabyte = get8()) != 0x0A)
+	{
+	    outtab();
+	    outh8(aabyte);
+	    outfishy();
+	}
+    }
+}
+
+PRIVATE void i_d8(opc)
+opcode_pt opc;
+{
+    opcode_pt esc;
+    char *str;
+
+    getmodregrm();
+    esc = (opc << 3) | reg;
+    if ((str = (mod == REG_MOD ? str1_d8 : str_d8)[esc]) == NULL)
+    {
+escape:
+	oututstr("esc");
+	outh8(esc);
+	outcomma();
+	outea(0);
+	return;
+    }
+    if (*str == 0)
+    {
+	str = sstr_d8[str[1] + rm];
+	if (str == NULL)
+	    goto escape;
+	outustr(str);
+	return;
+    }
+    outustr(str);
+    outtab(); 
+    if (mod == REG_MOD)
+    {
+	if (opc == 0 && reg != 2 && reg != 3)
+	    outustr("st,");
+	outf1();
+	if (opc == 4 || opc == 6)
+	    outustr(",st");
+	return; 
+    }
+    switch(size_d8[esc])
+    {
+    case 4:
+	outustr("d");
+    case 2:
+	outwptr();
+	break;
+    case 8:
+	outustr("q");
+	outwptr();
+	break;
+    case 10:
+	outustr("t");
+	outbptr();
+	break;
+    }
+    outea(opc);
+}
+
+PRIVATE void i_e0(opc)
+opcode_pt opc;
+{
+    outustr(str_e0[opc]);
+    if (opc < 4)
+	Jb();
+    else if (opc < 6)
+    {
+	outalorx(opc);
+	outcomma();
+	Ib();
+    }
+    else
+    {
+	Ib();
+	outcomma();
+	outalorx(opc);
+    }
+}
+
+PRIVATE void i_e8(opc)
+opcode_pt opc;
+{
+    outustr(str_e8[opc]);
+    if (opc < 2)
+	Jv();
+    else if (opc == 2)
+	outsegpc();
+    else if (opc == 3)
+	Jb();
+    else
+    {
+	if (opc & TOREGBIT)
+	{
+	    outustr(genreg[10]);
+	    outcomma();
+	    outalorx(opc);
+	}
+	else
+	{
+	    outalorx(opc);
+	    outcomma();
+	    outustr(genreg[10]);
+	}
+    }
+}
+
+PRIVATE void i_f0(opc)
+opcode_pt opc;
+{
+    if (opc < 6)
+	outustr(str_f0[opc]);
+    else
+    {
+	getmodregrm();
+	outustr(sstr_f0[reg]);
+	outbwptr(opc);
+	outea(opc);
+	if (reg == 0)
+	{
+	    outcomma();
+	    outimmed(opc & WORDBIT);
+	}
+    }
+}
+
+PRIVATE void i_f8(opc)
+opcode_pt opc;
+{
+    if (opc < 6)
+	outustr(str_f8[opc]);
+    else
+    {
+	getmodregrm();
+	if (opc == 6 && reg >= 2)
+	    outustr("fishy\t");
+	else
+	    outustr(sstr_f8[reg]);
+	outbwptr(opc);
+	outea(opc);
+    }
+}
+
+PRIVATE void outad(opc)
+opcode_pt opc;
+{
+    getmodregrm();
+    outad1(opc);
+}
+
+PRIVATE void outad1(opc)
+opcode_pt opc;
+{
+    if (!(opc & TOREGBIT))
+    {
+	outea(opc);
+	outcomma();
+    }
+    if (opc & WORDBIT)
+	Gv1();
+    else
+	outustr(genreg[reg]);
+    if (opc & TOREGBIT)
+    {
+	outcomma();
+	outea(opc);
+    }
+}
+
+PRIVATE void outalorx(opc)
+opcode_pt opc;
+{
+    if (opc & WORDBIT)
+	outax();
+    else
+	outustr(genreg[0]);
+}
+
+PRIVATE void outax()
+{
+    outustr(genreg[hosize]);
+}
+
+PRIVATE void outbptr()
+{
+    outustr("byte ptr ");
+}
+
+PRIVATE void outbwptr(opc)
+opcode_pt opc;
+{
+    if (mod != REG_MOD)
+    {
+	if (opc & WORDBIT)
+	    outwptr();
+	else
+	    outbptr();
+    }
+}
+
+PRIVATE void outea(wordflags)
+opcode_pt wordflags;
+{
+    reg_pt base;
+    reg_pt index;
+    opcode_pt ss;
+    opcode_pt ssindexbase;
+
+    if (mod == REG_MOD)
+	outustr(genreg[hosize * (wordflags & WORDBIT) + rm]);
+    else
+    {
+	outbyte(LINDIRECT);
+	if (hasize == 16)
+	{
+	    if (rm == 4)
+	    {
+		base = (ssindexbase = get8()) & BASE_MASK;
+		if (mod == MEM0_MOD && base == 5)
+		    outgetaddr();
+		else
+		    outustr((genreg + 16)[base]);
+		ss = (ssindexbase & SS_MASK) >> SS_SHIFT;
+		if ((index = (ssindexbase & INDEX_MASK) >> INDEX_SHIFT) != 4)
+		{
+		    outbyte('+');
+		    outustr((genreg + 16)[index]);
+		    outstr("\0\0\0*2\0*4\0*8\0" + (3 * ss));
+		}
+	    }
+	    else if (mod == MEM0_MOD && rm == 5)
+		outgetaddr();
+	    else
+		outustr((genreg + 16)[rm]);
+	}
+	else if (mod == MEM0_MOD && rm == 6)
+	    outgetaddr();
+	else
+	    outustr(indreg[rm]);
+	if (mod == MEM1_MOD)
+	    /* fake sign extension to get +- */
+	    outimmed(SIGNBIT | WORDBIT);
+	else if (mod == MEM2_MOD)
+	{
+	    outbyte('+');
+#if (_WORD_SIZE == 4)
+	    out32offset();
+#else
+	    outgetaddr();
+#endif
+	}
+	outbyte(RINDIRECT);
+	if (hasize == 16 && rm == 4 && index == 4 && ss != 0)
+	    outfishy();
+    }
+}
+
+PRIVATE void outf1()
+{
+    outustr("st(");
+    outbyte((int) (rm + '0'));
+    outbyte(')');
+}
+
+#if (_WORD_SIZE == 4)
+
+PRIVATE void out32offset()
+{
+    off_t off;
+
+    if (hasize == 16)
+	off = get32();
+    else
+	outfishy();
+
+    outh32(off);
+}
+#endif
+
+PRIVATE void outfishy()
+{
+    outustr("\t???");
+}
+
+PRIVATE void outgetaddr()
+{
+    off_t off;
+
+    if (hasize == 16)
+	off = get32();
+    else
+	off = get16();
+
+    if ( finds_data(off,data_seg) )
+  	*offptr++ = off;
+    else if (hasize == 16)
+	outh32(off);
+    else
+	outh16((u16_t) off);
+}
+
+PRIVATE void outimmed(signwordflag)
+opcode_pt signwordflag;
+{
+    su8_pt byte;
+
+    if (signwordflag & WORDBIT)
+    {
+	if (signwordflag & SIGNBIT)
+	{
+	    if ((byte = get8s()) < 0)
+	    {
+		outbyte('-');
+		byte = -byte;
+	    }
+	    else
+		outbyte('+');
+	    outh8((u8_t) byte);
+	}
+	else
+	    Iv();
+    }
+    else
+	Ib();
+}
+
+PRIVATE void outpc(pc)
+off_t pc;
+{
+    if (hosize == 8)
+	pc = (u16_t) pc;
+
+    if ( finds_pc(pc) )
+	*offptr++ = pc;
+    else if (hosize == 16)
+	outh32(pc);
+    else
+	outh16((u16_t) pc);
+}
+
+PRIVATE void outsegpc()
+{
+    off_t oldbase;
+    off_t pc;
+
+    if (hosize == 16)
+	pc = get32();
+    else
+	pc = get16();
+    oldbase = uptr.base;
+    outh16((u16_t) (uptr.base = get16()));	/* fake seg for lookup of pc */
+			/* TODO - convert to offset in protected mode */
+    outbyte(':');
+    outpc(pc);
+    uptr.base = oldbase;
+}
+
+PRIVATE void oututstr(s)
+char *s;
+{
+    outustr(s);
+    outtab();
+}
+
+PRIVATE void outword()
+{
+    outustr("dword " + ((16 - hosize) >> 3));
+}
+
+PRIVATE void outwptr()
+{
+    outword();
+    outustr("ptr ");
+}
+
+PRIVATE void outwsize()
+{
+    if (hosize == 16)
+	outustr("d");
+    else
+	outustr("w");
+}
+
+PRIVATE void pagef()
+{
+    opcode_pt opc;
+    int regbad;
+
+    if ((opc = get8()) <= 1 || opc == 0xBA)
+    {
+	if (opc == 0xBA)
+	    opc = 16;
+	else
+	    opc *= 8;
+	getmodregrm();
+	outustr(ssstr_0f[opc += reg]);
+	if (opc < 6 || opc == 12 || opc == 14)
+	    Ew();
+	else if (opc >= 8 && opc < 13)
+	    Ms();
+	else if (opc >= 20)
+	{
+	    outbwptr(WORDBIT);
+	    EvIb();
+	}
+    }
+    else if (opc < 4)
+    {
+	oututstr("lar\0lsl" + 4 * (opc - 2));
+	GvEw();
+    }
+    else if (opc == 5)
+    {
+	outustr("loadall");
+	outfishy();
+    }
+    else if (opc == 6)
+	outustr("clts");
+    else if (opc < 0x20)
+	outstr(fishy);
+    else if (opc < 0x27 && opc != 0x25)
+    {
+	outustr(movtab);
+	getmodregrm();
+	hosize = 16;
+	if (!(opc & TOREGBIT))
+	{
+	    Ev();		/* Rd() since hosize is 16 */
+	    outcomma();
+	}
+	regbad = FALSE;
+	if (opc & 1)
+	{
+	    outustr("dr");
+	    if (reg == 4 || reg == 5)
+		regbad = TRUE;
+	}
+	else if (opc < 0x24)
+	{
+	    outustr("cr");
+	    if (reg >= 4 || reg == 1)
+		regbad = TRUE;
+	}
+	else
+	{
+	    outustr("tr");
+	    if (reg < 6)
+		regbad = TRUE;
+	}
+	outbyte((int) (reg + '0'));
+	if (opc & TOREGBIT)
+	{
+	    outcomma();
+	    Ev();
+	}
+	if (regbad || mod != REG_MOD)
+	    outfishy();
+    }
+    else if (opc < 0x80)
+	outstr(fishy);
+    else if (opc < 0x90)
+    {
+	outustr("j");
+	oututstr((str_flags - 0x80)[opc]);
+	Jv();
+    }
+    else if (opc < 0xA0)
+    {
+	outustr("set");
+	oututstr((str_flags - 0x90)[opc]);
+	getmodregrm();
+	outbwptr(0);
+	Eb();
+    }
+    else if (opc < 0xC0)
+    {
+	outustr((sstr_0f - 0xA0)[opc]);
+	switch (opc)
+	{
+	case 0xA3:
+	case 0xAB:
+	case 0xB3:
+	case 0xBB:
+	    EvGv();
+	    break;
+	case 0xA4:
+	case 0xAC:
+	    EvGv();
+	    outcomma();
+	    Ib();
+	    break;
+	case 0xA5:
+	case 0xAD:
+	    EvGv();
+	    outcomma();
+	    CL();
+	    break;
+	case 0xAF:
+	case 0xBC:
+	case 0xBD:
+	    GvEv();
+	    break;
+	case 0xB2:
+	case 0xB4:
+	case 0xB5:
+	    GvMp();
+	    break;
+	case 0xB6:
+	case 0xBE:
+	    Gv();
+	    outcomma();
+	    outbwptr(opc);
+	    Eb();
+	    break;
+	case 0xB7:
+	case 0xBF:
+	    Gv();
+	    outcomma();
+	    hosize = 8;		/* done in Ew(), but too late */
+	    outbwptr(opc);
+	    Ew();
+	    break;
+	}
+    }
+    else
+	outstr(fishy);
+}
+
+PRIVATE int puti()
+{
+    static int hadprefix;
+    opcode_pt opcode;
+
+more:
+    offptr = offtable;
+    opcode = get8();
+    if (!hadprefix)
+    {
+	data_seg = DSEG;
+	hdefsize = 8;
+	if (bits32)
+	    hdefsize = 16;
+	hosize =
+	    hasize = hdefsize;
+    }
+    (*optable[opcode >> 3])(opcode < 0x80 ? opcode : opcode & 7);
+    if (offptr > offtable)
+    {
+	if (stringtab() >= 31)
+	{
+	    outspace();
+	    outspace();
+	}
+	else
+	    while (stringtab() < 32)
+		outtab();
+	outbyte(';');
+	for (off1ptr = offtable; off1ptr < offptr; ++off1ptr)
+	{
+	    outspace();
+	    if (*off1ptr < 0x10000)
+		outh16((u16_t) *off1ptr);
+	    else
+		outh32(*off1ptr);
+	}
+	offptr = offtable;
+    }
+    if ((opcode & 0xE7) == 0x26 ||
+	opcode >= 0x64 && opcode < 0x68 ||
+	opcode == 0xF0 || opcode == 0xF2 || opcode == 0xF3)
+	/* not finished instruction for 0x26, 0x2E, 0x36, 0x3E seg overrides
+	 * and 0x64, 0x65 386 seg overrides
+	 * and 0x66, 0x67 386 size prefixes
+	 * and 0xF0 lock, 0xF2 repne, 0xF3 rep
+	 */
+    {
+	hadprefix = TRUE;
+	goto more;		/* TODO - print prefixes better */
+	return FALSE;
+    }
+    hadprefix = FALSE;
+    return TRUE;
+}
+
+PRIVATE void shift(opc)
+opcode_pt opc;
+{
+    getmodregrm();
+    oututstr(sstr_d0[reg]);
+    outbwptr(opc);
+    outea(opc);
+    outcomma();
+    if (opc < 0xD0)
+	Ib();
+    else if (opc & 2)
+	CL();
+    else
+	outbyte('1');
+}
+
+PRIVATE void checkmemory()
+{
+    if (mod == REG_MOD)
+	outfishy();
+}
+
+PRIVATE void CL()
+{
+    outustr(genreg[1]);
+}
+
+PRIVATE void Eb()
+{
+    outea(0);
+}
+
+PRIVATE void Ev()
+{
+    outea(WORDBIT);
+}
+
+PRIVATE void EvGv()
+{
+    getmodregrm();
+    Ev();
+    outcomma();
+    Gv1();
+}
+
+PRIVATE void EvIb()
+{
+    Ev();
+    outcomma();
+    Ib();
+}
+
+PRIVATE void Ew()
+{
+    hosize = 8;
+    Ev();
+}
+
+PRIVATE void EwRw()
+{
+    hosize = 8;
+    EvGv();
+}
+
+PRIVATE void Gv()
+{
+    getmodregrm();
+    Gv1();
+}
+
+PRIVATE void Gv1()
+{
+    outustr(genreg[hosize + reg]);
+}
+
+PRIVATE void GvEv()
+{
+    Gv();
+    outcomma();
+    Ev();
+}
+
+PRIVATE void GvEw()
+{
+    Gv();
+    outcomma();
+    Ew();
+}
+
+PRIVATE void GvM()
+{
+    GvEv();
+    checkmemory();
+}
+
+PRIVATE void GvMa()
+{
+    GvM();
+}
+
+PRIVATE void GvMp()
+{
+    GvM();
+}
+
+PRIVATE void Ib()
+{
+    outh8(get8());
+}
+
+PRIVATE void Iw()
+{
+    outh16(get16());
+}
+
+PRIVATE void Iv()
+{
+    if (hosize == 16)
+	outh32(get32());
+    else
+	Iw();
+}
+
+PRIVATE void Jb()
+{
+    off_t pcjump;
+
+    pcjump = get8s();
+    outpc(pcjump + uptr.off);
+}
+
+PRIVATE void Jv()
+{
+    off_t pcjump;
+
+    if (hosize == 16)
+	pcjump = get32();
+    else
+	pcjump = (su16_t) get16();
+    outpc(pcjump + uptr.off);
+}
+
+PRIVATE void Ms()
+{
+    Ev();
+    checkmemory();
+}
+
+/********************* DASM ******************************/
+
+PUBLIC long dasm( addr, count, symflg )
+long addr;
+int count;
+int symflg;
+{
+#if (_WORD_SIZE == 4)
+	bits32 = TRUE;		/* Set mode */
+#else
+	bits32 = FALSE;
+#endif
+	uptr.off = addr;
+	uptr.base = 0;		/* not known */
+	while ( count-- != 0 && show1instruction() )
+		;
+}
+
+
+PRIVATE int show1instruction()
+{
+    register int column;
+    int idone;
+    static char line[81];
+    int maxcol;
+    struct address_s newuptr;
+    struct address_s olduptr;
+
+    outbyte('\r');
+    do
+    {
+	if ( text_symbol(uptr.off) ) {
+	    outbyte(':');
+	    outbyte('\n');
+	}
+	olduptr = uptr;
+	openstring(line);
+	idone = puti();
+	line[stringpos()] = 0;
+	closestring();
+	newuptr = uptr;
+	uptr = olduptr;
+	column = outssegaddr(&uptr);
+	while (uptr.off != newuptr.off)
+	{
+	    outh8(get8());
+	    column += 2;
+	}
+	maxcol = bits32 ? 24 : 16;
+	while (column < maxcol)
+	{
+	    outtab();
+	    column += 8;
+	}
+	outtab();
+	outstr(line);
+	outbyte('\n');
+    }
+    while (!idone);		/* eat all prefixes */
+    return TRUE;
+}
+
+
+PRIVATE u8_t get8()
+{
+/* get 8 bits current instruction pointer and advance pointer */
+
+    u8_t temp;
+
+    temp = peek_byte(uptr.off + uptr.base);
+    ++uptr.off;
+    return temp;
+}
+
+PRIVATE u16_t get16()
+{
+/* get 16 bits from current instruction pointer and advance pointer */
+
+    u16_t temp;
+
+    temp = peek_word(uptr.off + uptr.base);
+    uptr.off += 2;
+    return temp;
+}
+
+PRIVATE u32_t get32()
+{
+/* get 32 bits from current instruction pointer and advance pointer */
+
+    u32_t temp;
+
+    temp = peek_dword(uptr.off + uptr.base);
+    uptr.off += 4;
+    return temp;
+}
+
+
+PRIVATE int outsegaddr(addr)
+struct address_s *addr;
+{
+/* print segmented address */
+
+    int bytes_printed;
+
+    bytes_printed = 2;
+	bytes_printed = outsegreg(addr->base);
+    if (bytes_printed > 4)
+	outbyte('+');
+    else
+	outbyte(':');
+    ++bytes_printed;
+    if (addr->off >= 0x10000)
+    {
+	outh32(addr->off);
+	return bytes_printed + 8;
+    }
+    outh16((u16_t) addr->off);
+    return bytes_printed + 4;
+}
+
+PRIVATE int outssegaddr(addr)
+struct address_s *addr;
+{
+/* print 32 bit segmented address and 2 spaces */
+
+    int bytes_printed;
+
+    bytes_printed = outsegaddr(addr);
+    outspace();
+    outspace();
+    return bytes_printed + 2;
+}
+
+PRIVATE u8_t peek_byte(addr)
+off_t addr;
+{
+    return (u8_t) peek_dword(addr) & 0xFF; /* 8 bits only */
+}
+
+PRIVATE u16_t peek_word(addr)
+off_t addr;
+{
+    return (u16_t) peek_dword(addr);
+}
Index: /trunk/minix/commands/mdb/mdbexp.c
===================================================================
--- /trunk/minix/commands/mdb/mdbexp.c	(revision 9)
+++ /trunk/minix/commands/mdb/mdbexp.c	(revision 9)
@@ -0,0 +1,157 @@
+/*
+ * mdbexp.c - MINIX expresion parser
+ *
+ * Written by Bruce D. Szablak
+ *
+ * This free software is provided for non-commerical use. No warrantee
+ * of fitness for any use is implied. You get what you pay for. Anyone
+ * may make modifications and distribute them, but please keep this header
+ * in the distribution.
+ */
+
+#include "mdb.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "proto.h"
+
+FORWARD _PROTOTYPE(long value , (char *s , char **s_p , int *seg_p ));
+FORWARD _PROTOTYPE(long lookup , (char *s , char **s_p , int *seg_p ));
+
+#define idchar(c) (isalpha(c) || isdigit(c) || (c) == '_')
+
+/* 
+ * Get an expression for mdb
+ */
+PUBLIC char *getexp(buf, exp_p, seg_p)
+char *buf;
+int *seg_p;
+long *exp_p;
+{
+  long v = 0L;
+
+  buf = skip(buf);
+  if ((isalpha(*buf) && (isspace(buf[1]) || buf[1] == ';')) 
+      || *buf == '\n'
+      || *buf == ';'
+      || *buf == '/'
+      || *buf == '!'
+      || *buf == '?'
+      || *buf == '@'
+      || *buf == '#') {
+	*exp_p = 0L;
+	return buf;
+  }
+  v = value(buf, &buf, seg_p);
+  buf = skip(buf);
+  if (*buf == '+')
+	v += value(skip(buf + 1), &buf, seg_p);
+  else if (*buf == '-')
+	v -= value(skip(buf + 1), &buf, seg_p);
+  *exp_p = v;
+  return skip(buf);
+}
+
+/* 
+ * Get value 
+ *
+ * 	\c 	escaped characters
+ * 	digits	number
+ * 	$xx	registers 
+ *	\n	0L
+ *	then calls lookup for symbols
+ */
+PRIVATE long value(s, s_p, seg_p)
+char *s, **s_p;
+int *seg_p;
+{
+  long k;
+
+  if (*s == '\'') {		/* handle character constants here */
+	*s_p = s + 2;
+	return s[1];
+  }
+  if (*s == '-' || isdigit(*s))
+	return strtol(s, s_p, 0);
+  if (*s == '$') {
+	k = reg_addr(s + 1);
+	*s_p = s + 3;
+	return get_reg(curpid, k);
+	k = reg_addr(s + 1);
+	*s_p = s + 3;
+	return get_reg(curpid, k);
+  }
+  if (*s == '\n') {
+	*s_p = s + 1;
+	return 0L;
+  }
+  return lookup(s, s_p, seg_p);
+}
+
+/* 
+ * Lookup symbol - return value
+ * Handle special cases: _start T: D: S: 
+ * then call symbolvalue()
+ */
+PRIVATE long lookup(s, s_p, seg_p)
+char *s, **s_p;
+int *seg_p;
+{
+  long value;
+  char c;
+  int l;
+
+  for (l = 1; idchar(s[l]); ++l) {}
+  c = s[l];
+  s[l] = 0;
+
+  if (strcmp("_start", s) == 0) {
+	*seg_p = T;
+	if (c == ':') c = '+';
+	*(*s_p = s + 6) = c;
+	return st_addr;
+  }
+  if (strcmp("T", s) == 0) {
+	*seg_p = T;
+	if (c == ':') c = '+';
+	*(*s_p = s + 1) = c;
+	return st_addr;
+  }
+  if (strcmp("D", s) == 0) {
+	*seg_p = D;
+	if (c == ':') c = '+';
+	*(*s_p = s + 1) = c;
+	return sd_addr;
+  }
+  if (strcmp("S", s) == 0) {
+	*seg_p = S;
+	if (c == ':') c = '+';
+	*(*s_p = s + 1) = c;
+	return sk_addr;
+  }
+
+  if ((value = symbolvalue(s, TRUE)) != 0L) {
+	*seg_p = T;
+	*(*s_p = s + l) = c;
+	return value;
+  }
+
+  if ((value = symbolvalue(s, FALSE)) != 0L) {
+	*seg_p = D;
+	*(*s_p = s + l) = c;
+	return value;
+  }
+
+  Printf("%s: ", s);
+  mdb_error("symbol not found\n");
+}
+
+/* Skip spaces */
+PUBLIC char *skip(s)
+register char *s;
+{
+  while (isspace(*s)) ++s;
+  return *s ? s : s - 1;
+}
+
Index: /trunk/minix/commands/mdb/misc.c
===================================================================
--- /trunk/minix/commands/mdb/misc.c	(revision 9)
+++ /trunk/minix/commands/mdb/misc.c	(revision 9)
@@ -0,0 +1,289 @@
+/* 
+ *  misc.c for mdb
+ */
+
+#include "mdb.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#define ptrace mdbtrace
+#include <sys/ptrace.h>
+#include "proto.h"
+
+FORWARD _PROTOTYPE( void pr_ascii , (long val , int size ));
+
+/* Print ascii */
+PRIVATE void pr_ascii(val, size)
+long val;
+int size;
+{
+  int i;
+  int v;
+  int sh;
+
+#ifdef	BYTES_SWAPPED
+  sh = 8 * size;
+#else
+  sh = 0;
+#endif
+
+  for (i = 0; i < size; i++) {
+	v = (int) (val >> sh) & 0xFF;
+#ifdef	BYTES_SWAPPED
+	sh -= 8;
+#else
+	sh += 8;
+#endif
+	Printf(isprint(v) ? "%c" : "\\%03o", v);
+  }
+  Printf("\n");
+}
+
+/* Dump stack */
+PUBLIC void dump_stack(cnt)
+long cnt;
+{
+  vir_bytes v, vi;
+  long val, sp;
+  int num, size, nmode;
+
+  size = INTSIZE;		/* size of stack element */
+  num = (int) cnt;
+  if (num <= 0) num = 0;
+  if (num > sk_size) num = (int) sk_size / size;
+  nmode = num;			/* Save mode */
+
+  /* Get current SP */
+  sp = get_reg(curpid, reg_addr("sp"));
+
+  /* Starting address is top of stack seg -1 */
+  vi = (vir_bytes) sk_addr + (vir_bytes) sk_size - size;
+
+  /* Ending address */
+  v = (vir_bytes) end_addr;
+  if (nmode == 0) v = MAX(v, sp);
+
+  Printf("Stack Dump SP=%*lx\nAddr\tHex\tAscii\n", 2 * size, sp);
+  do {
+	val = (ptrace(T_GETDATA, curpid, (long) vi, 0L) >> SHIFT(size))
+								& MASK(size);
+	Printf("%*lx\t", 2 * ADDRSIZE, (vi >> SHIFT(ADDRSIZE))
+						       & MASK(ADDRSIZE));
+	Printf("%*lx\t", 2 * size, val);
+	pr_ascii(val, size);
+	num -= 1;
+	vi -= size;
+  } while (vi >= v && (nmode ? num > 0 : 1));
+
+}
+
+
+/* Get file size */ 
+PUBLIC off_t file_size(fd)
+int fd;
+{
+struct stat st;
+
+  if(fstat(fd,&st) <0 ) {
+	Printf("Cannot stat\n");
+	return 0L;
+  }
+  else
+	return st.st_size;
+}
+
+/* Print help page */
+PUBLIC void help_page()
+{
+  outstr("\nHelp for mdb. For more details, type 'command ?'\n");
+  outstr("!#\t- Shell escape / Set Variable or register\n");
+  outstr("Tt\t- Current call / Backtrace all\n");
+  outstr("/nsf\t- Display for n size s with format f\n");
+  outstr("Xx [n]\t- Disasm / & display reg for n instructions\n");
+  outstr("Rr a\t- Run / with arguments a\n");
+  outstr("Cc [n]\t- Continue with current signal / no signal n times\n");
+  outstr("Ii [n]\t- Single step with / no signal for n instructions\n");
+  outstr("Mm t n\t- Trace until / Stop when modified t type for n instructions\n");
+  outstr("k \t- Kill traced process\n");
+  outstr("Bb\t- Display / Set Break-pt\n");
+  outstr("Dd\t- Delete all / one break-points\n");
+  outstr("P\t- Toggle Paging\n");
+  outstr("Ll name\t- Log to file name / and to standard output\n");
+#ifdef  DEBUG
+  outstr("Vv\t- Version info / Toggle debug flag\n");
+#else
+  outstr("V\t- Version info\n");
+#endif
+  outstr("e [t]\t- List symbols for type t\n");
+  outstr("y\t- Print segment mappings\n");
+  outstr("s [n]\t- Dump stack for n words\n");
+#if	SYSCALLS_SUPPORT
+  outstr("z [a]\t- Trace syscalls with address a\n");
+#endif
+  outstr("? \t- Help - this screen\n");
+  outstr("@ file\t- Execute commands from file\n");
+  outstr("Qq\t- Quit / and kill traced process\n");
+#ifdef DEBUG
+  outstr("Usage: mdb -x debug-level [-Ll]logfile exec-file core-file @command-file\n");
+#else
+  outstr("Usage: mdb [-Ll]logfile exec-file core-file @command-file\n");
+#endif
+  outstr("       mdb [-fc] file\n");
+}
+
+PUBLIC void version_info()
+{
+	Printf("\nmdb version %s.%d for Minix", MDBVERSION, MDBBUILD );
+	Printf(" %s.%s",  OS_RELEASE, OS_VERSION);
+#ifdef MINIX_PC
+#ifdef __i386
+	Printf(" (32-bit)");
+#else
+	Printf(" (16-bit)");
+#endif
+#endif
+#ifdef MINIX_ST
+	Printf("-ST");
+#endif
+	Printf("\n");
+}
+
+/* Print help message on command */
+PUBLIC void help_on(h)
+int h;
+{
+
+  switch (h) {
+  case '/':	
+	outstr("<address> /nsf\t- Display for n items of size s with format f from address\n");
+	outstr("\t  n defaults to 1\n");
+	outstr("\t  s defaults to size of int\n");
+	outstr("\t    can be b for byte h for short l for long\n");
+	outstr("\t  f defaults to d for decimal\n");
+	outstr("\t    can be x X o d D c s or u as in printf\n");
+	outstr("\t    y treat value as address\n");
+	outstr("\t    i disasm\n");
+	break;
+  case '@':	
+	outstr("@ file\t- Execute commands from file\n");
+	break;
+  case '#':	
+	outstr("# <address> cs value\t- Set Variable(s) at address to value\n");
+	outstr("\t\t\t  for c count and size s\n");
+ 	outstr("\t\t\t  b for byte h for short or l for long\n");
+	outstr("\t\t\t  Count or size must be specified\n");
+	outstr("# $xx value\t\t- Set register $xx to value\n");
+	break;
+  case 'C':	
+	outstr("C [n]\t- Continue with curent signal n times\n");
+	outstr("\t  n defaults to 1\n");
+	break;
+  case 'c':	
+	outstr("c [n]\t- Continue with no signal n times\n");
+	outstr("\t  n defaults to 1\n");
+	break;
+  case 'e':
+	outstr("e [t]\t- List symbols for type t\n");
+	break;
+  case 's':
+	outstr("s [n]\t- Dump stack for n words\n");
+	outstr("\t  n defaults to whole stack\n");
+	break;
+  case 'I':
+	outstr("I n\t- Single step with signal for n instructions n defaults to 1\n");
+	break;
+  case 'i':
+	outstr("i n\t- Single step with no signal for n instructions n defaults to 1\n");
+	break;
+  case 'M':
+  case 'm':
+	if ( h == 'M') 
+		outstr("<address> M t n\t- Trace until\n");
+	else
+		outstr("<address> m t n\t- Stop when\n");
+	outstr("\t\t<address> is modified t type for n instructions\n");
+	outstr("\t\tn defaults to 1\n");
+	outstr("\t\tb for byte h for short l for long defaults to size of int\n");
+	break;
+  case 'T':	
+	outstr("T\t- Display current call\n");
+	break;
+  case 't':
+	outstr("t\t- Backtrace all calls\n");
+	break;
+  case '!':
+	outstr("![command]\t- Shell escape or spawn command\n");
+	break;
+  case 'R':	
+	outstr("R\t- Run the exec-file\n");
+	break;
+  case 'r':
+	outstr("r [arguments]\t- Run the exec-file with arguments\n");
+	break;
+  case 'k':
+	outstr("k\t- Kill traced process\n");
+	break;
+  case 'B':
+	outstr("B\t- Display all the Break points\n");
+	break;
+  case 'b':
+	outstr("<address> b [commands]\t- Set Break-pt at address\n");
+	outstr("\t\t\t  commands will be executed by mdb at break-pt\n");
+	break;
+  case 'D':
+	outstr("D\t- Delete all break-points\n");
+	break;
+  case 'd':
+	outstr("<address> d\t- Delete one break-point at address\n");
+	break;
+  case 'q':
+	outstr("q\t- Quit mdb (and kill traced program)\n");
+	break;
+  case 'Q':
+	outstr("Q\t- Quit mdb immediately\n");
+	break;
+  case 'P':
+	outstr("P\t- Toggle Paging\n");
+	outstr("\t  Defaults is OFF\n");
+	break;
+  case 'L':
+	outstr("L name\t- Log to file name\n");
+	outstr("L\t- Reset output to standard output\n");
+	break;
+  case 'l':
+	outstr("l name\t- Log to file name and standard output\n");
+	outstr("l\t- Reset output to standard output\n");
+	outstr("\t  Defaults to none\n");
+	break;
+#ifdef  DEBUG
+  case 'v':
+	outstr("v\t- Toggle debug flag\n");
+	break;
+#endif
+  case 'V':
+	outstr("V\t- Print Version Information for mdb\n");
+	break;
+  case 'X':
+	outstr("<address> X [n] [offset]\t- Disasm for n instructions\n");
+	outstr("\t\t\t  Starting at address+offset\n");
+	break;
+  case 'x':
+	outstr("<address> x [n] offset\t- Disasm & display registers for n instructions\n");
+	outstr("\t\t\t  Starting at address+offset\n");
+	break;
+  case 'y':
+	outstr("y\t- Print segment mappings\n");
+	break;
+#if	SYSCALLS_SUPPORT
+  case 'z':
+	outstr("z [address]\t- Trace system calls using address\n");
+	outstr("\t\t  If the exec-file has symbols, mdb looks for __sendrec\n");
+	break;
+#endif
+  default:
+	Printf("No help on command '%c' is available\n",h);
+	break;
+  }
+}
+
Index: /trunk/minix/commands/mdb/proto.h
===================================================================
--- /trunk/minix/commands/mdb/proto.h	(revision 9)
+++ /trunk/minix/commands/mdb/proto.h	(revision 9)
@@ -0,0 +1,105 @@
+/* 
+ * proto.h for mdb 
+ */
+
+/* core.c */
+
+_PROTOTYPE( void prtmap, (void) );
+_PROTOTYPE( unsigned long core_init, (char *filename) );
+_PROTOTYPE( unsigned long file_init, (char *filename) );
+_PROTOTYPE( long read_core, (int req, long addr, long data) );
+
+/* mdb.c */ 
+
+_PROTOTYPE( void mdb_error, (char *s) );
+_PROTOTYPE( long breakpt , (long addr , char *cmd ));
+_PROTOTYPE( void tstart , (int req , int verbose , int val , int cnt ));
+
+/* io.c */
+
+_PROTOTYPE( char *get_cmd , (char *cbuf, int csize) );
+_PROTOTYPE( void openin , (char *s ));
+_PROTOTYPE( void logging, (int c, char *name) );
+_PROTOTYPE( void do_error, (char *message) );
+_PROTOTYPE( int Printf, (const char *format, ...));
+_PROTOTYPE( void outbyte, (int byte) );
+_PROTOTYPE( void outcomma, (void) );
+_PROTOTYPE( void outh8,  (unsigned num) );
+_PROTOTYPE( void outh16, (unsigned num) );
+_PROTOTYPE( void outh32, (unsigned num) );
+_PROTOTYPE( void outh4,  (unsigned num) );
+_PROTOTYPE( void outspace, (void) );
+_PROTOTYPE( void outstr, (char *s) );
+_PROTOTYPE( void outtab, (void) );
+_PROTOTYPE( void outustr, (char *s) );
+_PROTOTYPE( void closestring, (void) );
+_PROTOTYPE( int mytolower, (int ch) );
+_PROTOTYPE( void openstring, (char *string) );
+_PROTOTYPE( int stringpos, (void) );
+_PROTOTYPE( int stringtab, (void) );
+
+/* mdbdis86.c */
+
+_PROTOTYPE( long dasm, (long addr, int count, int symflg) );
+
+/* mdbexp.c */ 
+
+_PROTOTYPE( char *getexp, (char *buf, long *exp_p, int *seg_p) );
+_PROTOTYPE( char *skip, (char *s) );
+
+/* kernel.c */
+_PROTOTYPE( long get_reg, (int pid, long k) );
+_PROTOTYPE( void set_reg, (int pid, long k, long value) );
+_PROTOTYPE( long reg_addr, (char *s) );
+_PROTOTYPE( int disp_regs, (void) );
+_PROTOTYPE( int outsegreg, (off_t num) );
+_PROTOTYPE( void update , (void));
+_PROTOTYPE( void disp_maps , (void));
+
+/* misc.c */
+
+_PROTOTYPE( void dump_stack, (long count) );
+_PROTOTYPE( off_t file_size, (int fd) );
+_PROTOTYPE( void help_on, (int h) );
+_PROTOTYPE( void version_info, (void) );
+_PROTOTYPE( void help_page, (void) );
+
+#if EXTRA_SYMBOLS
+/* gnu_sym.c */
+_PROTOTYPE( void gnu_init, (char *filename) );
+_PROTOTYPE( long gnu_symbolvalue, (char *name, int is_text ) );
+_PROTOTYPE( void gnu_symbolic, (off_t value, int separator) );
+_PROTOTYPE( void gnu_listsym, (int tchar) );
+_PROTOTYPE( int gnu_text_symbol, (off_t value) );
+_PROTOTYPE( int gnu_finds_pc, (off_t pc) );
+_PROTOTYPE( int gnu_finds_data, (off_t off, int data_seg) );
+#endif /* EXTRA_SYMBOLS */
+
+/* sym.c */
+_PROTOTYPE( void syminit, (char *filename) );
+_PROTOTYPE( long symbolvalue, (char *name, int is_text ) );
+_PROTOTYPE( void printhex, (off_t v) );
+_PROTOTYPE( void symbolic, (off_t value, int separator) );
+_PROTOTYPE( void listsym, (char *cmd) );
+_PROTOTYPE( int text_symbol, (off_t value) );
+_PROTOTYPE( int finds_pc, (off_t pc) );
+_PROTOTYPE( int finds_data, (off_t off, int data_seg) );
+
+/* trace.c */
+_PROTOTYPE( long mdbtrace, (int req, int pid, long addr, long data) );
+_PROTOTYPE( u32_t peek_dword, (off_t addr));
+
+#if SYSCALLS_SUPPORT
+
+/* syscalls.c */
+_PROTOTYPE( void start_syscall, (long addr) );
+_PROTOTYPE( void do_syscall, (long addr) );
+
+/* decode.c */
+_PROTOTYPE( void decode_message, (unsigned addr) );
+_PROTOTYPE( void decode_result, (void) );
+
+/* ioctl.c */
+_PROTOTYPE( void decode_ioctl, (int sr, message *m) );
+
+#endif /* SYSCALLS_SUPPORT */
Index: /trunk/minix/commands/mdb/ptrace.2
===================================================================
--- /trunk/minix/commands/mdb/ptrace.2	(revision 9)
+++ /trunk/minix/commands/mdb/ptrace.2	(revision 9)
@@ -0,0 +1,87 @@
+.TH PTRACE 2
+.SH NAME
+ptrace \- ptrace system call. 
+.SH SYNOPSIS
+.ft B
+.nf
+.sp
+#include <sys/ptrace.h>
+
+long ptrace( int req, pid_t pid, long addr, long data)
+
+.fi
+.ft P
+.SH DESCRIPTION
+.sp
+Ptrace(2) is called with following arguments:
+.sp 
+.br
+req
+request
+.br
+pid 
+process id
+.br
+addr
+address
+.br
+data
+data
+.br
+.SH REQUESTS
+.sp
+.I
+T_STOP
+stop the process.
+.br
+.I
+T_OK
+enable tracing by parent for this process. 
+.br
+.I
+T_GETINS
+return value from instruction space 
+.br
+.I
+T_GETDATA
+return value from data space. 
+.br
+.I
+T_GETUSER
+return value from process table. See proc.h in kernel.
+.br
+.I
+T_SETINS
+set value from instruction space. 
+.br
+.I
+T_SETDATA
+set value from data space.
+.br
+.I
+T_SETUSER
+set value in process table. 
+.br
+.I
+T_RESUME
+resume execution.
+.br
+.I
+T_EXIT
+exit. Turn off tracing.
+.br
+.I
+T_STEP
+set trace bit to enable single step.
+.SH "SEE ALSO"
+.sp
+mdb(1)
+.SH DIAGNOSTICS
+.sp
+errno is set by ptrace().
+.SH FILES
+.sp
+/usr/src/kernel/proc.h for process table info. 
+
+
+
Index: /trunk/minix/commands/mdb/sample
===================================================================
--- /trunk/minix/commands/mdb/sample	(revision 9)
+++ /trunk/minix/commands/mdb/sample	(revision 9)
@@ -0,0 +1,9 @@
+r 10 
+y
+__sendrec b 
+B
+c
+x 2
+t
+q
+
Index: /trunk/minix/commands/mdb/sym.c
===================================================================
--- /trunk/minix/commands/mdb/sym.c	(revision 9)
+++ /trunk/minix/commands/mdb/sym.c	(revision 9)
@@ -0,0 +1,546 @@
+/* 
+ * sym.c for mdb 
+ */
+
+#include "mdb.h"
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <a.out.h>
+#include "proto.h"
+
+#if	GNU_SUPPORT
+#define ZMAGIC 0413
+#define NMAGIC 0410
+#define QMAGIC 0314
+#endif
+
+struct symtab_s
+{
+	struct nlist *start;
+	struct nlist *end;
+	int text;
+	int data;
+	unsigned nsym;
+};
+
+PRIVATE struct symtab_s symtab;
+PRIVATE int type_of_exec;
+
+FORWARD _PROTOTYPE( int check_exec, (struct exec *hdr) );
+FORWARD _PROTOTYPE( void sortsyms , (struct nlist *array , struct nlist *top ));
+FORWARD _PROTOTYPE( int symeq , (char *t , struct nlist *sp ));
+FORWARD _PROTOTYPE( int symprefix , (char *t , struct nlist *sp ));
+FORWARD _PROTOTYPE( struct nlist *findsname, (char *name, int is_text, int allflag) );
+FORWARD _PROTOTYPE( void outsym, (struct nlist *sp, off_t off) );
+FORWARD _PROTOTYPE( struct nlist *findsval, (off_t value, int where) );
+
+PUBLIC void syminit( filename )
+char *filename;
+{
+	int fd;
+	struct exec header;
+	register struct symtab_s *tp;
+
+	tp = &symtab;
+	if ( (fd = open( filename, O_RDONLY)) < 0) {
+		fprintf(stderr, "Couldn't open %s.\n", filename);
+		perror(filename);
+		exit(1);
+	}
+
+	if( read( fd, (char *) &header, sizeof header ) != sizeof header )
+	{
+		fprintf(stderr, "Couldn't read %d bytes from %s.\n", sizeof(header), filename);
+		close( fd );
+		exit(1);
+	}	
+	type_of_exec = check_exec(&header);
+
+#if	EXTRA_SYMBOLS
+	if ( type_of_exec == GNU_SYMBOLS) {
+		close(fd);
+		gnu_init(filename);
+		return;
+	}
+#endif
+
+	/* For MINIX EXEC */
+	if ( lseek( fd, A_SYMPOS( header ), 0 ) != A_SYMPOS( header ) )
+	{
+		do_error( "mdb - reading header" );
+		close( fd );
+		exit(1);
+	}
+	if ( (int) header.a_syms < 0 ||
+             (unsigned) header.a_syms != header.a_syms ||
+	     (tp->start = (struct nlist *) malloc( (unsigned) header.a_syms ))
+	     			== (struct nlist *) NULL &&
+	     header.a_syms != 0 )
+	{
+		Printf("mdb: no room for symbol table" );
+		close( fd );
+		return;
+	}
+	if ( read( fd, (char *) tp->start, (int) header.a_syms ) < 0 )
+	{
+		do_error( "mdb - reading symbol table" );
+		close( fd );
+		return;
+	}
+	close( fd );
+	tp->nsym = (unsigned) header.a_syms / sizeof (struct nlist);
+	tp->end = tp->start + tp->nsym;
+	tp->text = 0x07;
+	tp->data = 0x0F;
+
+	/* sort on value only, name search not used much and storage a problem */
+	Printf("Sorting %d MINIX symbols ....", tp->nsym );
+	sortsyms( tp->start, tp->end );
+	Printf("\n");
+}
+
+/* Check exec file 
+ * return type of exec
+ * or exit
+ */
+PRIVATE int check_exec(hdr)
+struct exec *hdr;
+{
+long magic;
+
+  /* Check MAGIC number */
+  if (hdr->a_magic[0] != A_MAGIC0 || hdr->a_magic[1] != A_MAGIC1) {
+#if	GNU_SUPPORT
+	memcpy(&magic, hdr, sizeof(long));
+	/* Clear bits */
+	magic &= 0xFFFF;
+
+	if ( magic == ZMAGIC || magic == QMAGIC ) {
+	    is_separate = FALSE;
+	    return GNU_SYMBOLS;
+	}
+	if ( magic == NMAGIC ) {
+	    is_separate = TRUE;
+	    return GNU_SYMBOLS;
+	}
+#endif
+	Printf("mdb: invalid magic number in exec header - %02x %02x\n",
+	hdr->a_magic[0], 
+	hdr->a_magic[1]);
+	exit(1);
+  }
+
+  /* Check CPU */
+#if (CHIP == INTEL)
+#if (_WORD_SIZE == 4)
+  if (hdr->a_cpu != A_I80386)
+#else
+  if (hdr->a_cpu != A_I8086)
+#endif
+#endif 
+#if (CHIP == M68000)
+  if (hdr->a_cpu != A_M68K)
+#endif 
+  {
+ 	Printf("mdb: invalid cpu in exec header - %04x\n",
+	hdr->a_cpu);
+	exit(1);
+  }
+
+  is_separate = FALSE;
+#ifdef MINIX_PC
+  if (hdr->a_flags & A_SEP)
+  	is_separate = TRUE;
+#endif 
+/* 
+ * A_EXEC is not being set by current cc 
+ * It was set in Minix 1.5.0
+ */ 
+#if 0 
+  /* Check flags - separate I & D or not */
+  if (hdr->a_flags & A_EXEC)
+	is_separate = FALSE;
+  else {
+	Printf("mdb: object file not exec %04x\n", 
+	hdr->a_flags);
+	exit(1);
+  }
+#endif
+  return MINIX_SYMBOLS;
+}
+
+
+PUBLIC long symbolvalue( name, is_text )
+char *name;
+int is_text;
+{
+register struct nlist *sp;
+
+#if	EXTRA_SYMBOLS
+	if ( type_of_exec == GNU_SYMBOLS )
+		return gnu_symbolvalue( name, is_text );
+#endif
+	
+	/* For MINIX EXEC */
+	sp = findsname(name, is_text, 0);
+	if (sp != NULL) 
+		return sp->n_value;
+	else 
+		return 0L;
+}
+
+PRIVATE struct nlist *findsname( name, is_text, allflag )
+char *name;
+int is_text;
+int allflag;
+{
+	char *s;
+	unsigned char sclass;
+	int schar;
+	char *send;
+	register struct nlist *sp;
+	register struct symtab_s *tp;
+
+	tp = &symtab;
+	if ( allflag )
+	{
+		/* find and print all matching symbols */
+		for ( sp = tp->start; sp < tp->end; ++sp )
+		{
+			if ( symprefix( name, sp ) )
+			{
+				sp = sp;
+				for ( s = sp->n_name, send = s + sizeof sp->n_name;
+				      *s != 0 && s < send; ++s )
+					outbyte( *s );
+				for ( ; s <= send; ++s )
+					outspace();
+				switch( sp->n_sclass & N_SECT )
+				{
+					case N_ABS: schar = 'a'; break;
+					case N_TEXT: schar = 't'; break;
+					case N_DATA: schar = 'd'; break;
+					case N_BSS: schar = 'b'; break;
+					default: schar = '?'; break;
+				}
+				if ( (sp->n_sclass & N_CLASS) == C_EXT && schar != '?' )
+					schar += 'A' - 'a';
+				outbyte( schar );
+				outspace();
+#if (_WORD_SIZE == 2)
+				outh16( (u16_t) sp->n_value );
+#else
+				outh32( sp->n_value );
+#endif
+				outbyte('\n');
+			}
+		}
+	}
+	else
+	{
+		/* find symbol by dumb linear search */
+		for ( sp = tp->start; sp < tp->end; ++sp )
+		{
+			sclass = sp->n_sclass & N_SECT;
+			if ( (is_text && sclass == N_TEXT ||
+			      !is_text && (sclass == N_DATA || sclass == N_BSS)) &&
+					 symeq( name, sp ) )
+				return sp;
+		}
+	}
+	return NULL;
+}
+
+PRIVATE struct nlist *findsval( value, where )
+off_t value;
+int where;
+{
+	int left;
+	int middle;
+	int right;
+	unsigned char sclass;
+	register struct nlist *sp;
+	register struct symtab_s *tp;
+
+	tp = &symtab;
+
+	/* find last symbol with value <= desired one by binary search */
+	for ( left = 0, right = tp->nsym - 1; left <= right; )
+	{
+		middle = (left + right) / 2;
+		sp = tp->start + middle;
+		if ( value < sp->n_value )
+			right = middle - 1;
+		else
+			left = middle + 1;
+	}
+	if ( right >= 0 )
+		/* otherwise tp->start + right may wrap around to > tp->start !! */
+		for ( sp = tp->start + right; sp >= tp->start; --sp )
+		{
+			if ( (sp->n_sclass & N_CLASS) != C_EXT ) continue; 
+			sclass = sp->n_sclass & N_SECT;
+			if ( (where == CSEG && sclass == N_TEXT ||
+						where != CSEG && (sclass == N_DATA || sclass == N_BSS)) )
+			return sp;
+		}
+	return NULL;
+}
+
+
+PUBLIC void printhex(v)
+off_t v;
+{
+    if ( v >= 65536L )
+	outh32( v );
+    else if ( v >= 256 )
+	outh16( (u16_t) v );
+    else
+	outh8(  (u8_t) v );
+}
+
+
+PRIVATE void outsym( sp, off )
+struct nlist *sp;
+off_t off;
+{
+	register char *s;
+	char *send;
+
+	for ( s = sp->n_name, send = s + sizeof sp->n_name; *s != 0 && s < send; ++s )
+		outbyte( *s );
+	if ( (off -= sp->n_value) != 0 )
+	{
+		outbyte( '+' );
+		printhex(off);
+	}
+}
+
+/* shell sort symbols on value */
+
+PRIVATE void sortsyms( array, top )
+struct nlist *array;
+struct nlist *top;
+{
+	int gap;
+	int i;
+	int j;
+	register struct nlist *left;
+	register struct nlist *right;
+	struct nlist swaptemp;
+	int size;
+
+	size = top - array;
+	/* choose gaps according to Knuth V3 p95 */
+	for ( gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j )
+		;
+	do
+	{
+		for ( j = gap; j < size; ++j )
+			for ( i = j - gap; i >= 0; i -= gap )
+			{
+				left = array + i; 
+				right = array + (i + gap);
+				if ( (off_t) left->n_value <=
+				     right->n_value )
+					break;
+				swaptemp = *left;
+				*left = *right;
+				*right = swaptemp;
+			}
+	}
+	while ( (gap /= 3) != 0 );
+}
+
+PUBLIC void symbolic( value, separator )
+off_t value;
+int separator;
+{
+	register struct nlist *sp;
+	long off;
+
+#if	EXTRA_SYMBOLS
+	if ( type_of_exec == GNU_SYMBOLS ) {
+		gnu_symbolic( value, separator );
+		return;
+	}
+#endif
+
+	/* For MINIX EXEC */
+
+	if (value < st_addr || value > end_addr) {
+		outstr("0x");
+		printhex(value);
+		outbyte(separator);
+		return;
+	}
+
+	if ( (sp = findsval( value, CSEG )) != NULL )
+	{
+		outsym( sp, value );
+	}
+	else if ( (sp = findsval( value, DSEG )) != NULL )
+	{
+		outsym( sp, value );
+	}
+	else
+	{
+		outstr("_start");
+		off = value - st_addr; 
+		if ( off != 0 )  
+		{
+		outbyte( '+' );
+		printhex(off);
+		}
+	}
+	outbyte( separator );
+}
+
+
+PRIVATE int symeq( t, sp )
+register char *t;
+struct nlist *sp;
+{
+	return strncmp( t, sp->n_name, sizeof sp->n_name ) == 0;
+}
+
+PRIVATE int symprefix( t, sp )
+register char *t;
+struct nlist *sp;
+{
+	register char *s;
+	char *send;
+
+	for ( ; *t == '_'; ++t )
+		;
+	for ( s = sp->n_name, send = s + sizeof sp->n_name;
+	      s < send && *s == '_'; ++s )
+		;
+	return strncmp( s, t, (size_t)(send - s) ) == 0;
+}
+
+
+
+/* list all symbols - test for selection criteria */
+
+PUBLIC void listsym(cmd)
+char *cmd;
+{
+	register struct symtab_s *tp;
+	register struct nlist *sp;
+	char *s;
+	char *send;
+	char schar;	
+	char tchar;
+
+	/* set selection */
+	cmd = skip(cmd+1);
+	if( *cmd == '\n' || *cmd == ';' ) 
+		tchar = '*';
+	else
+		tchar = *cmd;
+
+#if	EXTRA_SYMBOLS
+	if ( type_of_exec == GNU_SYMBOLS ) {
+		gnu_listsym(tchar);
+		return;
+	}
+#endif
+
+	/* For MINIX EXEC */
+
+	tp = &symtab;
+    	for ( sp = tp->start; sp < tp->end; ++sp )
+	{
+	     switch( sp->n_sclass & N_SECT )
+	     {
+			case N_ABS:	schar = 'a'; break;
+			case N_TEXT:	schar = 't'; break;
+			case N_DATA:	schar = 'd'; break;
+			case N_BSS:	schar = 'b'; break;
+			default: 	schar = '?'; break;
+	     }
+
+	     if ( (sp->n_sclass & N_CLASS) == C_EXT && schar != '?' )
+		schar += 'A' - 'a';
+
+	     /* check for selection */	
+	     if ( tchar != '*' && schar != tchar)
+		continue; 	
+
+	     /* print symbol type and value */	
+	     for ( s = sp->n_name, send = s + sizeof sp->n_name;
+		 *s != 0 && s < send; ++s ) outbyte( *s );
+	     for ( ; s <= send; ++s ) outspace();
+	     outbyte( schar );
+	     outspace();
+#if (_WORD_SIZE == 2)
+	     outh16( (u16_t) sp->n_value );
+#else
+	     outh32( sp->n_value );
+#endif
+	     outbyte('\n');
+	}
+}
+
+
+PUBLIC int text_symbol(value)
+off_t value;
+{
+struct nlist *sp;
+
+#if	EXTRA_SYMBOLS
+	if ( type_of_exec == GNU_SYMBOLS ) 
+	    return gnu_text_symbol(value);
+#endif
+
+	if ((sp = findsval(value, CSEG)) != NULL && sp->n_value == value)
+	{
+	    outsym(sp, value);
+	    return TRUE;
+	 }
+	else
+	    return FALSE;
+}
+
+PUBLIC int finds_data(off,data_seg)
+off_t off;
+int data_seg;
+{
+struct nlist *sp;
+
+#if	EXTRA_SYMBOLS
+	if ( type_of_exec == GNU_SYMBOLS )
+		return gnu_finds_data(off,data_seg);
+#endif
+
+	if ((sp = findsval(off, data_seg)) != NULL)
+   	{
+	    outsym(sp, off);
+	    return TRUE;
+    	}
+    	else 
+	    return FALSE;
+}
+
+PUBLIC int finds_pc(pc)
+off_t pc;
+{
+struct nlist *sp;
+
+#if	EXTRA_SYMBOLS
+	if ( type_of_exec == GNU_SYMBOLS )
+		return gnu_finds_pc(pc);
+#endif
+
+	if ((sp = findsval(pc, CSEG)) != NULL)
+    	{
+	    outsym(sp, pc);
+	    return TRUE;
+        }
+	else
+	    return FALSE;
+}
Index: /trunk/minix/commands/mdb/syscalls.c
===================================================================
--- /trunk/minix/commands/mdb/syscalls.c	(revision 9)
+++ /trunk/minix/commands/mdb/syscalls.c	(revision 9)
@@ -0,0 +1,85 @@
+/* 
+ * syscall.c for mdb 
+ */
+#include "mdb.h"
+#ifdef SYSCALLS_SUPPORT
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ptrace.h>
+#include "proto.h"
+
+#define SYSCALL_NAME	"__sendrec"
+#ifdef __i386
+#define SYSCALL_OFFSET	0xF
+#define SYSCALL_OLD	0x21CD
+#else
+#define SYSCALL_OFFSET  0xE
+#define SYSCALL_OLD	0x20CD
+#endif
+
+PRIVATE long intaddr;
+
+PUBLIC void start_syscall(addr)
+long addr;
+{
+long old; 
+
+  syscalls = FALSE;
+
+  if ( addr == 0 ) {
+	intaddr = symbolvalue( SYSCALL_NAME, TRUE );
+  	if ( intaddr == 0 ) 
+		return;
+	intaddr += SYSCALL_OFFSET;
+  }
+  else {
+	intaddr = addr;
+	Printf("Using %lx as syscall address\n",addr);
+  }
+
+  old = breakpt(intaddr,"\n");
+
+  /* Check instruction */
+  if ( (old & 0xFFFF) == SYSCALL_OLD)
+	syscalls = TRUE;
+
+}
+
+PUBLIC void do_syscall(addr)
+long addr;
+{
+  unsigned reg_ax,reg_bx;
+
+  if ( addr != intaddr ) return;
+
+  Printf("syscall to ");
+
+  reg_ax = get_reg(curpid,reg_addr("AX"));
+
+  switch (reg_ax) {
+  case 0:	Printf(" MM ");
+		break;
+  case 1:	Printf(" FS ");
+		break;
+  case 2:	Printf(" INET ");
+		break;
+  default:	Printf("Invalid dest = %d", reg_ax);
+		exit(0);
+  }
+
+
+  reg_bx = get_reg(curpid,reg_addr("BX"));
+  decode_message(reg_bx);
+
+  /* Single step */	
+  tstart(T_STEP, 0, 0, 1);
+
+  /* Check return code */
+  reg_ax = get_reg(curpid,reg_addr("AX"));
+  if ( reg_ax != 0 )
+	Printf("syscall failed AX=%d\n",reg_ax);
+  else 
+	decode_result();
+}
+
+#endif /* SYSCALLS_SUPPORT */
Index: /trunk/minix/commands/mdb/trace.c
===================================================================
--- /trunk/minix/commands/mdb/trace.c	(revision 9)
+++ /trunk/minix/commands/mdb/trace.c	(revision 9)
@@ -0,0 +1,51 @@
+/* 
+ * trace.c for mdb 
+ */
+
+#include "mdb.h"
+#include <stdio.h>
+#include <sys/ptrace.h>
+#include "proto.h"
+
+/* mdbtrace()
+ * Call ptrace and check for error if debugging running process
+ * Otherwise read 'core' file
+ */ 
+PUBLIC long mdbtrace(req, pid, addr, data)
+int req, pid;
+long addr, data;
+{
+  long val;
+  int i;
+  int segment;
+
+#ifdef  DEBUG
+  if (debug) Printf("ptrace: req=%d pid=%d addr=%lx data=%lx\n",
+		req, pid, addr, data);
+#endif
+
+  if (corepid < 0) 
+  {
+	errno = 0;
+	/* Call normal ptrace and check for error */
+	val = ptrace(req, pid, addr, data);
+	if (errno != 0) {
+		do_error("mdb ptrace error ");
+		mdb_error("\n");
+	}
+#ifdef  DEBUG
+	if (debug) Printf("ptrace: val=>%lx\n", val);
+#endif
+	return val;
+  } 
+  else
+	return read_core(req, addr, data);
+}
+
+/* Used by disassembler */
+PUBLIC u32_t peek_dword(addr)
+off_t addr;
+{
+    return mdbtrace(T_GETINS, curpid, addr, 0L);
+}
+
Index: /trunk/minix/commands/mined/Makefile
===================================================================
--- /trunk/minix/commands/mined/Makefile	(revision 9)
+++ /trunk/minix/commands/mined/Makefile	(revision 9)
@@ -0,0 +1,23 @@
+# Makefile for mined
+
+CC = exec cc
+
+CFLAGS	= -O -wo -D_MINIX -D_POSIX_SOURCE
+
+OBJ = mined1.o mined2.o
+
+all:	mined
+
+mined:	$(OBJ)
+	$(CC) -i -o $@ $(OBJ)
+	install -S 64k $@
+
+install:	/usr/bin/mined
+
+/usr/bin/mined:	mined
+	install -cs -o bin mined $@
+
+$(OBJ):	mined.h
+
+clean:
+	rm -f mined *.o *.s core *.bak
Index: /trunk/minix/commands/mined/build
===================================================================
--- /trunk/minix/commands/mined/build	(revision 9)
+++ /trunk/minix/commands/mined/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/mined/mined.h
===================================================================
--- /trunk/minix/commands/mined/mined.h	(revision 9)
+++ /trunk/minix/commands/mined/mined.h	(revision 9)
@@ -0,0 +1,373 @@
+/*========================================================================*
+ *				Mined.h					  *
+ *========================================================================*/
+
+#include <minix/config.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+
+#ifndef YMAX
+#ifdef UNIX
+#include <stdio.h>
+#undef putchar
+#undef getchar
+#undef NULL
+#undef EOF
+extern char *CE, *VS, *SO, *SE, *CL, *AL, *CM;
+#define YMAX		49
+#else
+#define YMAX		24		/* Maximum y coordinate starting at 0 */
+/* Escape sequences. */
+extern char *enter_string;	/* String printed on entering mined */
+extern char *rev_video;		/* String for starting reverse video */
+extern char *normal_video;	/* String for leaving reverse video */
+extern char *rev_scroll;	/* String for reverse scrolling */
+extern char *pos_string;	/* Absolute cursor positioning */
+#define X_PLUS	' '		/* To be added to x for cursor sequence */
+#define Y_PLUS	' '		/* To be added to y for cursor sequence */
+#endif /* UNIX */
+
+#define XMAX		79		/* Maximum x coordinate starting at 0*/
+#define SCREENMAX	(YMAX - 1)	/* Number of lines displayed */
+#define XBREAK		(XMAX - 0)	/* Line shift at this coordinate */
+#define SHIFT_SIZE	25		/* Number of chars to shift */
+#define SHIFT_MARK	'!'		/* Char indicating line continues */
+#define MAX_CHARS	1024		/* Maximum chars on one line */
+
+/* LINE_START must be rounded up to the lowest SHIFT_SIZE */
+#define LINE_START	(((-MAX_CHARS - 1) / SHIFT_SIZE) * SHIFT_SIZE \
+  				   - SHIFT_SIZE)
+#define LINE_END	(MAX_CHARS + 1)	/* Highest x-coordinate for line */
+
+#define LINE_LEN	(XMAX + 1)	/* Number of characters on line */
+#define SCREEN_SIZE	(XMAX * YMAX)	/* Size of I/O buffering */
+#define BLOCK_SIZE	1024
+
+/* Return values of functions */
+#define ERRORS		-1
+#define NO_LINE		(ERRORS - 1)	/* Must be < 0 */
+#define FINE	 	(ERRORS + 1)
+#define NO_INPUT	(ERRORS + 2)
+
+#define STD_OUT	 	1		/* File descriptor for terminal */
+
+#if (CHIP == INTEL)
+#define MEMORY_SIZE	(50 * 1024)	/* Size of data space to malloc */
+#endif
+
+#define REPORT	2			/* Report change of lines on # lines */
+
+typedef int FLAG;
+
+/* General flags */
+#define	FALSE		0
+#define	TRUE		1
+#define	NOT_VALID	2
+#define	VALID		3
+#define	OFF		4
+#define	ON		5
+
+/* Expression flags */
+#define	FORWARD		6
+#define	REVERSE		7
+
+/* Yank flags */
+#define	SMALLER		8
+#define	BIGGER		9
+#define	SAME		10
+#define	EMPTY		11
+#define	NO_DELETE	12
+#define	DELETE		13
+#define	READ		14
+#define	WRITE		15
+
+/*
+ * The Line structure.  Each line entry contains a pointer to the next line,
+ * a pointer to the previous line, a pointer to the text and an unsigned char
+ * telling at which offset of the line printing should start (usually 0).
+ */
+struct Line {
+  struct Line *next;
+  struct Line *prev;
+  char *text;
+  unsigned char shift_count;
+};
+
+typedef struct Line LINE;
+
+/* Dummy line indicator */
+#define DUMMY		0x80
+#define DUMMY_MASK	0x7F
+
+/* Expression definitions */
+#define NO_MATCH	0
+#define MATCH		1
+#define REG_ERROR	2
+
+#define BEGIN_LINE	(2 * REG_ERROR)
+#define END_LINE	(2 * BEGIN_LINE)
+
+/*
+ * The regex structure. Status can be any of 0, BEGIN_LINE or REG_ERROR. In
+ * the last case, the result.err_mess field is assigned. Start_ptr and end_ptr
+ * point to the match found. For more details see the documentation file.
+ */
+struct regex {
+  union {
+  	char *err_mess;
+  	int *expression;
+  } result;
+  char status;
+  char *start_ptr;
+  char *end_ptr;
+};
+
+typedef struct regex REGEX;
+
+/* NULL definitions */
+#define NIL_PTR		((char *) 0)
+#define NIL_LINE	((LINE *) 0)
+#define NIL_REG		((REGEX *) 0)
+#define NIL_INT		((int *) 0)
+
+/*
+ * Forward declarations
+ */
+extern int nlines;		/* Number of lines in file */
+extern LINE *header;		/* Head of line list */
+extern LINE *tail;		/* Last line in line list */
+extern LINE *top_line;		/* First line of screen */
+extern LINE *bot_line;		/* Last line of screen */
+extern LINE *cur_line;		/* Current line in use */
+extern char *cur_text;		/* Pointer to char on current line in use */
+extern int last_y;		/* Last y of screen. Usually SCREENMAX */
+extern int ymax;
+extern int screenmax;
+extern char screen[SCREEN_SIZE];/* Output buffer for "writes" and "reads" */
+
+extern int x, y;			/* x, y coordinates on screen */
+extern FLAG modified;			/* Set when file is modified */
+extern FLAG stat_visible;		/* Set if status_line is visible */
+extern FLAG writable;			/* Set if file cannot be written */
+extern FLAG quit;			/* Set when quit character is typed */
+extern FLAG rpipe;		/* Set if file should be read from stdin */
+extern int input_fd;			/* Fd for command input */
+extern FLAG loading;			/* Set if we're loading a file */
+extern int out_count;			/* Index in output buffer */
+extern char file_name[LINE_LEN];	/* Name of file in use */
+extern char text_buffer[MAX_CHARS];	/* Buffer for modifying text */
+extern char *blank_line;		/* Clear line to end */
+
+extern char yank_file[];		/* Temp file for buffer */
+extern FLAG yank_status;		/* Status of yank_file */
+extern long chars_saved;		/* Nr of chars saved in buffer */
+
+/*
+ * Empty output buffer
+ */
+#define clear_buffer()			(out_count = 0)
+
+/*
+ * Print character on terminal
+ */
+#define putchar(c)			(void) write_char(STD_OUT, (c))
+
+/*
+ * Ring bell on terminal
+ */
+#define ring_bell()			putchar('\07')
+
+/*
+ * Print string on terminal
+ */
+#define string_print(str)		(void) writeline(STD_OUT, (str))
+
+/*
+ * Flush output buffer
+ */
+#define flush()				(void) flush_buffer(STD_OUT)
+
+/*
+ * Convert cnt to nearest tab position
+ */
+#define tab(cnt)			(((cnt) + 8) & ~07)
+#define is_tab(c)			((c) == '\t')
+
+/*
+ * Word defenitions
+ */
+#define white_space(c)	((c) == ' ' || (c) == '\t')
+#define alpha(c)	((c) != ' ' && (c) != '\t' && (c) != '\n')
+
+/*
+ * Print line on terminal at offset 0 and clear tail of line
+ */
+#define line_print(line)		put_line(line, 0, TRUE)
+
+/*
+ * Move to coordinates and set textp. (Don't use address)
+ */
+#define move_to(nx, ny)			move((nx), NIL_PTR, (ny))
+
+/*
+ * Move to coordinates on screen as indicated by textp.
+ */
+#define move_address(address)		move(0, (address), y)
+
+/*
+ * Functions handling status_line. ON means in reverse video.
+ */
+#define status_line(str1, str2)	(void) bottom_line(ON, (str1), \
+						    (str2), NIL_PTR, FALSE)
+#define error(str1, str2)	(void) bottom_line(ON, (str1), \
+						    (str2), NIL_PTR, FALSE)
+#define get_string(str1,str2, fl) bottom_line(ON, (str1), NIL_PTR, (str2), fl)
+#define clear_status()		(void) bottom_line(OFF, NIL_PTR, NIL_PTR, \
+						    NIL_PTR, FALSE)
+
+/*
+ * Print info about current file and buffer.
+ */
+#define fstatus(mess, cnt)	file_status((mess), (cnt), file_name, \
+					     nlines, writable, modified)
+
+/*
+ * Get real shift value.
+ */
+#define get_shift(cnt)		((cnt) & DUMMY_MASK)
+
+#endif /* YMAX */
+
+/* mined1.c */
+
+_PROTOTYPE(void FS, (void));
+_PROTOTYPE(void VI, (void));
+_PROTOTYPE(int WT, (void));
+_PROTOTYPE(void XWT, (void));
+_PROTOTYPE(void SH, (void));
+_PROTOTYPE(LINE *proceed, (LINE *line, int count ));
+_PROTOTYPE(int bottom_line, (FLAG revfl, char *s1, char *s2, char *inbuf, FLAG statfl ));
+_PROTOTYPE(int count_chars, (LINE *line ));
+_PROTOTYPE(void move, (int new_x, char *new_address, int new_y ));
+_PROTOTYPE(int find_x, (LINE *line, char *address ));
+_PROTOTYPE(char *find_address, (LINE *line, int x_coord, int *old_x ));
+_PROTOTYPE(int length_of, (char *string ));
+_PROTOTYPE(void copy_string, (char *to, char *from ));
+_PROTOTYPE(void reset, (LINE *head_line, int screen_y ));
+_PROTOTYPE(void set_cursor, (int nx, int ny ));
+_PROTOTYPE(void open_device, (void));
+_PROTOTYPE(int getchar, (void));
+_PROTOTYPE(void display, (int x_coord, int y_coord, LINE *line, int count ));
+_PROTOTYPE(int write_char, (int fd, int c ));
+_PROTOTYPE(int writeline, (int fd, char *text ));
+_PROTOTYPE(void put_line, (LINE *line, int offset, FLAG clear_line ));
+_PROTOTYPE(int flush_buffer, (int fd ));
+_PROTOTYPE(void bad_write, (int fd ));
+_PROTOTYPE(void catch, (int sig ));
+_PROTOTYPE(void abort_mined, (void));
+_PROTOTYPE(void raw_mode, (FLAG state ));
+_PROTOTYPE(void panic, (char *message ));
+_PROTOTYPE(char *alloc, (int bytes ));
+_PROTOTYPE(void free_space, (char *p ));
+/*
+#ifdef UNIX
+_PROTOTYPE(void (*key_map [128]), (void));
+#else
+_PROTOTYPE(void (*key_map [256]), (void));
+#endif
+*/
+_PROTOTYPE(void initialize, (void));
+_PROTOTYPE(char *basename, (char *path ));
+_PROTOTYPE(void load_file, (char *file ));
+_PROTOTYPE(int get_line, (int fd, char *buffer ));
+_PROTOTYPE(LINE *install_line, (char *buffer, int length ));
+_PROTOTYPE(void main, (int argc, char *argv []));
+_PROTOTYPE(void RD, (void));
+_PROTOTYPE(void I, (void));
+_PROTOTYPE(void XT, (void));
+_PROTOTYPE(void ESC, (void));
+_PROTOTYPE(int ask_save, (void));
+_PROTOTYPE(int line_number, (void));
+_PROTOTYPE(void file_status, (char *message, long count, char *file, int lines,
+						 FLAG writefl, FLAG changed ));
+#if __STDC__
+void build_string(char *buf, char *fmt, ...);
+#else
+void build_string();
+#endif
+_PROTOTYPE(char *num_out, (long number ));
+_PROTOTYPE(int get_number, (char *message, int *result ));
+_PROTOTYPE(int input, (char *inbuf, FLAG clearfl ));
+_PROTOTYPE(int get_file, (char *message, char *file ));
+_PROTOTYPE(int _getchar, (void));
+_PROTOTYPE(void _flush, (void));
+_PROTOTYPE(void _putchar, (int c ));
+_PROTOTYPE(void get_term, (void));
+
+/* mined2.c */
+
+_PROTOTYPE(void UP, (void));
+_PROTOTYPE(void DN, (void));
+_PROTOTYPE(void LF, (void));
+_PROTOTYPE(void RT, (void));
+_PROTOTYPE(void HIGH, (void));
+_PROTOTYPE(void LOW, (void));
+_PROTOTYPE(void BL, (void));
+_PROTOTYPE(void EL, (void));
+_PROTOTYPE(void GOTO, (void));
+_PROTOTYPE(void PD, (void));
+_PROTOTYPE(void PU, (void));
+_PROTOTYPE(void HO, (void));
+_PROTOTYPE(void EF, (void));
+_PROTOTYPE(void SU, (void));
+_PROTOTYPE(void SD, (void));
+_PROTOTYPE(int forward_scroll, (void));
+_PROTOTYPE(int reverse_scroll, (void));
+_PROTOTYPE(void MP, (void));
+_PROTOTYPE(void move_previous_word, (FLAG remove ));
+_PROTOTYPE(void MN, (void));
+_PROTOTYPE(void move_next_word, (FLAG remove ));
+_PROTOTYPE(void DCC, (void));
+_PROTOTYPE(void DPC, (void));
+_PROTOTYPE(void DLN, (void));
+_PROTOTYPE(void DNW, (void));
+_PROTOTYPE(void DPW, (void));
+_PROTOTYPE(void S, (int character ));
+_PROTOTYPE(void CTL, (void));
+_PROTOTYPE(void LIB, (void));
+_PROTOTYPE(LINE *line_insert, (LINE *line, char *string, int len ));
+_PROTOTYPE(int insert, (LINE *line, char *location, char *string ));
+_PROTOTYPE(LINE *line_delete, (LINE *line ));
+_PROTOTYPE(void delete, (LINE *start_line, char *start_textp, LINE *end_line, char *end_textp ));
+_PROTOTYPE(void PT, (void));
+_PROTOTYPE(void IF, (void));
+_PROTOTYPE(void file_insert, (int fd, FLAG old_pos ));
+_PROTOTYPE(void WB, (void));
+_PROTOTYPE(void MA, (void));
+_PROTOTYPE(void YA, (void));
+_PROTOTYPE(void DT, (void));
+_PROTOTYPE(void set_up, (FLAG remove ));
+_PROTOTYPE(FLAG checkmark, (void));
+_PROTOTYPE(int legal, (void));
+_PROTOTYPE(void yank, (LINE *start_line, char *start_textp, LINE *end_line, char *end_textp, FLAG remove ));
+_PROTOTYPE(int scratch_file, (FLAG mode ));
+_PROTOTYPE(void SF, (void));
+_PROTOTYPE(void SR, (void));
+_PROTOTYPE(REGEX *get_expression, (char *message ));
+_PROTOTYPE(void GR, (void));
+_PROTOTYPE(void LR, (void));
+_PROTOTYPE(void change, (char *message, FLAG file ));
+_PROTOTYPE(char *substitute, (LINE *line, REGEX *program, char *replacement ));
+_PROTOTYPE(void search, (char *message, FLAG method ));
+_PROTOTYPE(int find_y, (LINE *match_line ));
+_PROTOTYPE(void finished, (REGEX *program, int *last_exp ));
+_PROTOTYPE(void compile, (char *pattern, REGEX *program ));
+_PROTOTYPE(LINE *match, (REGEX *program, char *string, FLAG method ));
+_PROTOTYPE(int line_check, (REGEX *program, char *string, FLAG method ));
+_PROTOTYPE(int check_string, (REGEX *program, char *string, int *expression ));
+_PROTOTYPE(int star, (REGEX *program, char *end_position, char *string, int *expression ));
+_PROTOTYPE(int in_list, (int *list, int c, int list_length, int opcode ));
+_PROTOTYPE(void dummy_line, (void));
Index: /trunk/minix/commands/mined/mined1.c
===================================================================
--- /trunk/minix/commands/mined/mined1.c	(revision 9)
+++ /trunk/minix/commands/mined/mined1.c	(revision 9)
@@ -0,0 +1,1987 @@
+/*
+ * Part one of the mined editor.
+ */
+
+/*
+ * Author: Michiel Huisjes.
+ * 
+ * 1. General remarks.
+ * 
+ *   Mined is a screen editor designed for the MINIX operating system.
+ *   It is meant to be used on files not larger than 50K and to be fast.
+ *   When mined starts up, it reads the file into its memory to minimize
+ *   disk access. The only time that disk access is needed is when certain
+ *   save, write or copy commands are given.
+ * 
+ *   Mined has the style of Emacs or Jove, that means that there are no modes.
+ *   Each character has its own entry in an 256 pointer to function array,
+ *   which is called when that character is typed. Only ASCII characters are
+ *   connected with a function that inserts that character at the current
+ *   location in the file. Two execptions are <linefeed> and <tab> which are
+ *   inserted as well. Note that the mapping between commands and functions
+ *   called is implicit in the table. Changing the mapping just implies
+ *   changing the pointers in this table.
+ * 
+ *   The display consists of SCREENMAX + 1 lines and XMAX + 1 characters. When
+ *   a line is larger (or gets larger during editing) than XBREAK characters,
+ *   the line is either shifted SHIFT_SIZE characters to the left (which means
+ *   that the first SHIFT_SIZE characters are not printed) or the end of the
+ *   line is marked with the SHIFT_MARK character and the rest of the line is
+ *   not printed.  A line can never exceed MAX_CHARS characters. Mined will
+ *   always try to keep the cursor on the same line and same (relative)
+ *   x-coordinate if nothing changed. So if you scroll one line up, the cursor
+ *   stays on the same line, or when you move one line down, the cursor will
+ *   move to the same place on the line as it was on the previous.
+ *   Every character on the line is available for editing including the
+ *   linefeed at the the of the line. When the linefeed is deleted, the current
+ *   line and the next line are joined. The last character of the file (which
+ *   is always a linefeed) can never be deleted.
+ *   The bottomline (as indicated by YMAX + 1) is used as a status line during
+ *   editing. This line is usually blank or contains information mined needs
+ *   during editing. This information (or rather questions) is displayed in
+ *   reverse video.
+ * 
+ *   The terminal modes are changed completely. All signals like start/stop,
+ *   interrupt etc. are unset. The only signal that remains is the quit signal.
+ *   The quit signal (^\) is the general abort signal for mined. Typing a ^\
+ *   during searching or when mined is asking for filenames, etc. will abort
+ *   the function and mined will return to the main loop.  Sending a quit
+ *   signal during the main loop will abort the session (after confirmation)
+ *   and the file is not (!) saved.
+ *   The session will also be aborted when an unrecoverable error occurs. E.g
+ *   when there is no more memory available. If the file has been modified,
+ *   mined will ask if the file has to be saved or not.
+ *   If there is no more space left on the disk, mined will just give an error 
+ *   message and continue.
+ * 
+ *   The number of system calls are minized. This is done to keep the editor
+ *   as fast as possible. I/O is done in SCREEN_SIZE reads/writes. Accumulated
+ *   output is also flushed at the end of each character typed.
+ * 
+ * 2. Regular expressions
+ *   
+ *   Mined has a build in regular expression matcher, which is used for
+ *   searching and replace routines. A regular expression consists of a
+ *   sequence of:
+ * 
+ *      1. A normal character matching that character.
+ *      2. A . matching any character.
+ *      3. A ^ matching the begin of a line.
+ *      4. A $ (as last character of the pattern) mathing the end of a line.
+ *      5. A \<character> matching <character>.
+ *      6. A number of characters enclosed in [] pairs matching any of these
+ *        characters. A list of characters can be indicated by a '-'. So
+ *        [a-z] matches any letter of the alphabet. If the first character
+ *        after the '[' is a '^' then the set is negated (matching none of
+ *        the characters). 
+ *        A ']', '^' or '-' can be escaped by putting a '\' in front of it.
+ *        Of course this means that a \ must be represented by \\.
+ *      7. If one of the expressions as described in 1-6 is followed by a
+ *        '*' than that expressions matches a sequence of 0 or more of
+ *        that expression.
+ * 
+ *   Parsing of regular expression is done in two phases. In the first phase
+ *   the expression is compiled into a more comprehensible form. In the second
+ *   phase the actual matching is done. For more details see 3.6.
+ * 
+ * 
+ * 3. Implementation of mined.
+ * 
+ *   3.1 Data structures.
+ * 
+ *      The main data structures are as follows. The whole file is kept in a
+ *      double linked list of lines. The LINE structure looks like this:
+ * 
+ *         typedef struct Line {
+ *              struct Line *next;
+ *              struct Line *prev;
+ *              char *text;
+ *              unsigned char shift_count;
+ *         } LINE;
+ * 
+ *      Each line entry contains a pointer to the next line, a pointer to the
+ *      previous line and a pointer to the text of that line. A special field
+ *      shift_count contains the number of shifts (in units of SHIFT_SIZE)
+ *      that is performed on that line. The total size of the structure is 7
+ *      bytes so a file consisting of 1000 empty lines will waste a lot of
+ *      memory. A LINE structure is allocated for each line in the file. After
+ *      that the number of characters of the line is counted and sufficient
+ *      space is allocated to store them (including a linefeed and a '\0').
+ *      The resulting address is assigned to the text field in the structure.
+ * 
+ *      A special structure is allocated and its address is assigned to the
+ *      variable header as well as the variable tail. The text field of this
+ *      structure is set to NIL_PTR. The tail->prev of this structure points
+ *      to the last LINE of the file and the header->next to the first LINE.
+ *      Other LINE *variables are top_line and bot_line which point to the
+ *      first line resp. the last line on the screen.
+ *      Two other variables are important as well. First the LINE *cur_line,
+ *      which points to the LINE currently in use and the char *cur_text,
+ *      which points to the character at which the cursor stands.
+ *      Whenever an ASCII character is typed, a new line is build with this
+ *      character inserted. Then the old data space (pointed to by
+ *      cur_line->text) is freed, data space for the new line is allocated and
+ *      assigned to cur_line->text.
+ * 
+ *      Two global variables called x and y represent the x and y coordinates
+ *      from the cursor. The global variable nlines contains the number of
+ *      lines in the file. Last_y indicates the maximum y coordinate of the
+ *      screen (which is usually SCREENMAX).
+ * 
+ *      A few strings must be initialized by hand before compiling mined.
+ *      These string are enter_string, which is printed upon entering mined,
+ *      rev_video (turn on reverse video), normal_video, rev_scroll (perform a
+ *      reverse scroll) and pos_string. The last string should hold the
+ *      absolute position string to be printed for cursor motion. The #define
+ *      X_PLUS and Y_PLUS should contain the characters to be added to the
+ *      coordinates x and y (both starting at 0) to finish cursor positioning.
+ * 
+ *   3.2 Starting up.
+ *      
+ *      Mined can be called with or without argument and the function
+ *      load_file () is called with these arguments. load_file () checks
+ *      if the file exists if it can be read and if it is writable and
+ *      sets the writable flag accordingly. If the file can be read, 
+ *      load_file () reads a line from the file and stores this line into
+ *      a structure by calling install_line () and line_insert () which
+ *      installs the line into the double linked list, until the end of the
+ *      file is reached.
+ *      Lines are read by the function get_line (), which buffers the
+ *      reading in blocks of SCREEN_SIZE. Load_file () also initializes the
+ *      LINE *variables described above.
+ * 
+ *   3.3 Moving around.
+ * 
+ *      Several commands are implemented for moving through the file.
+ *      Moving up (UP), down (DN) left (LF) and right (RT) are done by the
+ *      arrow keys. Moving one line below the screen scrolls the screen one
+ *      line up. Moving one line above the screen scrolls the screen one line
+ *      down. The functions forward_scroll () and reverse_scroll () take care
+ *      of that.
+ *      Several other move functions exist: move to begin of line (BL), end of
+ *      line (EL) top of screen (HIGH), bottom of screen (LOW), top of file
+ *      (HO), end of file (EF), scroll one page down (PD), scroll one page up
+ *      (PU), scroll one line down (SD), scroll one line up (SU) and move to a
+ *      certain line number (GOTO).
+ *      Two functions called MN () and MP () each move one word further or 
+ *      backwards. A word is a number of non-blanks seperated by a space, a
+ *      tab or a linefeed.
+ * 
+ *   3.4 Modifying text.
+ * 
+ *      The modifying commands can be separated into two modes. The first
+ *      being inserting text, and the other deleting text. Two functions are
+ *      created for these purposes: insert () and delete (). Both are capable
+ *      of deleting or inserting large amounts of text as well as one
+ *      character. Insert () must be given the line and location at which
+ *      the text must be inserted. Is doesn't make any difference whether this
+ *      text contains linefeeds or not. Delete () must be given a pointer to
+ *      the start line, a pointer from where deleting should start on that
+ *      line and the same information about the end position. The last
+ *      character of the file will never be deleted. Delete () will make the
+ *      necessary changes to the screen after deleting, but insert () won't.
+ *      The functions for modifying text are: insert one char (S), insert a
+ *      file (file_insert (fd)), insert a linefeed and put cursor back to
+ *      end of line (LIB), delete character under the cursor (DCC), delete
+ *      before cursor (even linefeed) (DPC), delete next word (DNW), delete
+ *      previous word (DPC) and delete to end of line (if the cursor is at
+ *      a linefeed delete line) (DLN).
+ * 
+ *   3.5 Yanking.
+ * 
+ *      A few utilities are provided for yanking pieces of text. The function
+ *      MA () marks the current position in the file. This is done by setting 
+ *      LINE *mark_line and char *mark_text to the current position. Yanking
+ *      of text can be done in two modes. The first mode just copies the text
+ *      from the mark to the current position (or visa versa) into a buffer
+ *      (YA) and the second also deletes the text (DT). Both functions call
+ *      the function set_up () with the delete flag on or off. Set_up ()
+ *      checks if the marked position is still a valid one (by using
+ *      check_mark () and legal ()), and then calls the function yank () with
+ *      a start and end position in the file. This function copies the text
+ *      into a scratch_file as indicated by the variable yank_file. This
+ *      scratch_file is made uniq by the function scratch_file (). At the end
+ *      of copying yank will (if necessary) delete the text. A global flag
+ *      called yank_status keeps track of the buffer (or file) status. It is
+ *      initialized on NOT_VALID and set to EMPTY (by set_up ()) or VALID (by
+ *      yank ()). Several things can be done with the buffer. It can be
+ *      inserted somewhere else in the file (PT) or it can be copied into
+ *      another file (WB), which will be prompted for.
+ * 
+ *   3.6 Search and replace routines.
+ * 
+ *      Searching for strings and replacing strings are done by regular
+ *      expressions. For any expression the function compile () is called
+ *      with as argument the expression to compile. Compile () returns a
+ *      pointer to a structure which looks like this:
+ * 
+ *         typedef struct regex {
+ *              union {
+ *                    char *err_mess;
+ *                    int *expression;
+ *              } result;
+ *              char status;
+ *              char *start_ptr;
+ *              char *end_ptr;
+ *         } REGEX;
+ *      
+ *    If something went wrong during compiling (e.g. an illegal expression
+ *    was given), the function reg_error () is called, which sets the status
+ *    field to REG_ERROR and the err_mess field to the error message. If the
+ *    match must be anchored at the beginning of the line (end of line), the
+ *    status field is set to BEGIN_LINE (END_LINE). If none of these special
+ *    cases are true, the field is set to 0 and the function finished () is
+ *    called.  Finished () allocates space to hold the compiled expression
+ *    and copies this expression into the expression field of the union
+ *    (bcopy ()). Matching is done by the routines match() and line_check().
+ *    Match () takes as argument the REGEX *program, a pointer to the
+ *    startposition on the current line, and a flag indicating FORWARD or
+ *    REVERSE search.  Match () checks out the whole file until a match is
+ *    found. If match is found it returns a pointer to the line in which the
+ *    match was found else it returns a NIL_LINE. Line_check () takes the
+ *    same arguments, but return either MATCH or NO_MATCH.
+ *    During checking, the start_ptr and end_ptr fields of the REGEX
+ *    structure are assigned to the start and end of the match. 
+ *    Both functions try to find a match by walking through the line
+ *    character by character. For each possibility, the function
+ *    check_string () is called with as arguments the REGEX *program and the
+ *    string to search in. It starts walking through the expression until
+ *    the end of the expression or the end of the string is reached.
+ *    Whenever a * is encountered, this position of the string is marked,
+ *    the maximum number of matches are performed and the function star ()
+ *    is called in order to try to find the longest match possible. Star ()
+ *    takes as arguments the REGEX program, the current position of the
+ *    string, the marked position and the current position of the expression
+ *    Star () walks from the current position of the string back to the
+ *    marked position, and calls string_check () in order to find a match.
+ *    It returns MATCH or NO_MATCH, just as string_check () does.
+ *    Searching is now easy. Both search routines (forward (SF) and
+ *    backwards search (SR)) call search () with an apropiate message and a
+ *    flag indicating FORWARD or REVERSE search. Search () will get an
+ *    expression from the user by calling get_expression(). Get_expression()
+ *    returns a pointer to a REGEX structure or NIL_REG upon errors and
+ *    prompts for the expression. If no expression if given, the previous is
+ *    used instead. After that search will call match (), and if a match is
+ *    found, we can move to that place in the file by the functions find_x()
+ *    and find_y () which will find display the match on the screen.
+ *    Replacing can be done in two ways. A global replace (GR) or a line
+ *    replace (LR). Both functions call change () with a message an a flag
+ *    indicating global or line replacement. Change () will prompt for the
+ *    expression and for the replacement. Every & in the replacement pattern
+ *    means substitute the match instead. An & can be escaped by a \. When
+ *    a match is found, the function substitute () will perform the
+ *    substitution.
+ * 
+ *  3.6 Miscellaneous commands.
+ * 
+ *    A few commands haven't be discussed yet. These are redraw the screen
+ *    (RD) fork a shell (SH), print file status (FS), write file to disc
+ *    (WT), insert a file at current position (IF), leave editor (XT) and
+ *    visit another file (VI). The last two functions will check if the file
+ *    has been modified. If it has, they will ask if you want to save the
+ *    file by calling ask_save ().
+ *    The function ESC () will repeat a command n times. It will prompt for
+ *    the number. Aborting the loop can be done by sending the ^\ signal.
+ * 
+ *  3.7 Utility functions.
+ * 
+ *    Several functions exists for internal use. First allocation routines:
+ *    alloc (bytes) and newline () will return a pointer to free data space
+ *    if the given size. If there is no more memory available, the function
+ *    panic () is called.
+ *    Signal handling: The only signal that can be send to mined is the 
+ *    SIGQUIT signal. This signal, functions as a general abort command.
+ *    Mined will abort if the signal is given during the main loop. The 
+ *    function abort_mined () takes care of that.
+ *    Panic () is a function with as argument a error message. It will print
+ *    the message and the error number set by the kernel (errno) and will
+ *    ask if the file must be saved or not. It resets the terminal
+ *    (raw_mode ()) and exits.
+ *    String handling routines like copy_string(to, from), length_of(string)
+ *    and build_string (buffer, format, arg1, arg2, ...). The latter takes
+ *    a description of the string out out the format field and puts the
+ *    result in the buffer. (It works like printf (3), but then into a
+ *    string). The functions status_line (string1, string2), error (string1,
+ *    string2), clear_status () and bottom_line () all print information on
+ *    the status line.
+ *    Get_string (message, buffer) reads a string and getchar () reads one
+ *    character from the terminal.
+ *    Num_out ((long) number) prints the number into a 11 digit field
+ *    without leading zero's. It returns a pointer to the resulting string.
+ *    File_status () prints all file information on the status line.
+ *    Set_cursor (x, y) prints the string to put the cursor at coordinates
+ *    x and y.
+ *    Output is done by four functions: writeline(fd,string), clear_buffer()
+ *    write_char (fd, c) and flush_buffer (fd). Three defines are provided
+ *    to write on filedescriptor STD_OUT (terminal) which is used normally:
+ *    string_print (string), putchar (c) and flush (). All these functions
+ *    use the global I/O buffer screen and the global index for this array
+ *    called out_count. In this way I/O can be buffered, so that reads or
+ *    writes can be done in blocks of SCREEN_SIZE size.
+ *    The following functions all handle internal line maintenance. The
+ *    function proceed (start_line, count) returns the count'th line after
+ *    start_line.  If count is negative, the count'th line before the
+ *    start_line is returned. If header or tail is encountered then that
+ *    will be returned. Display (x, y, start_line, count) displays count
+ *    lines starting at coordinates [x, y] and beginning at start_line. If
+ *    the header or tail is encountered, empty lines are displayed instead.
+ *    The function reset (head_line, ny) reset top_line, last_y, bot_line,
+ *    cur_line and y-coordinate. This is not a neat way to do the
+ *    maintenance, but it sure saves a lot of code. It is usually used in
+ *    combination with display ().
+ *    Put_line(line, offset, clear_line), prints a line (skipping characters
+ *    according to the line->shift_size field) until XBREAK - offset
+ *    characters are printed or a '\n' is encountered. If clear_line is
+ *	  TRUE, spaces are printed until XBREAK - offset characters.
+ *	  Line_print (line) is a #define from put_line (line, 0, TRUE).
+ *    Moving is done by the functions move_to (x, y), move_addres (address)
+ *    and move (x, adress, y). This function is the most important one in
+ *    mined. New_y must be between 0 and last_y, new_x can be about
+ *    anything, address must be a pointer to an character on the current
+ *    line (or y). Move_to () first adjust the y coordinate together with
+ *    cur_line. If an address is given, it finds the corresponding
+ *    x-coordinate. If an new x-coordinate was given, it will try to locate
+ *    the corresponding character. After that it sets the shift_count field
+ *    of cur_line to an apropiate number according to new_x. The only thing
+ *    left to do now is to assign the new values to cur_line, cur_text, x
+ *    and y.
+ * 
+ * 4. Summary of commands.
+ *  
+ *  CURSOR MOTION
+ *    up-arrow  Move cursor 1 line up.  At top of screen, reverse scroll
+ *    down-arrow  Move cursor 1 line down.  At bottom, scroll forward.
+ *    left-arrow  Move cursor 1 character left or to end of previous line
+ *    right-arrow Move cursor 1 character right or to start of next line
+ *    CTRL-A   Move cursor to start of current line
+ *    CTRL-Z   Move cursor to end of current line
+ *    CTRL-^   Move cursor to top of screen
+ *    CTRL-_   Move cursor to bottom of screen
+ *    CTRL-F   Forward to start of next word (even to next line)
+ *    CTRL-B   Backward to first character of previous word
+ *   
+ *  SCREEN MOTION
+ *    Home key  Move cursor to first character of file
+ *    End key   Move cursor to last character of file
+ *    PgUp    Scroll backward 1 page. Bottom line becomes top line
+ *    PgD    Scroll backward 1 page. Top line becomes bottom line
+ *    CTRL-D   Scroll screen down one line (reverse scroll)
+ *    CTRL-U   Scroll screen up one line (forward scroll)
+ *   
+ *  MODIFYING TEXT
+ *    ASCII char  Self insert character at cursor
+ *    tab    Insert tab at cursor
+ *    backspace  Delete the previous char (left of cursor), even line feed
+ *    Del    Delete the character under the cursor
+ *    CTRL-N   Delete next word
+ *    CTRL-P   Delete previous word
+ *    CTRL-O   Insert line feed at cursor and back up 1 character
+ *    CTRL-T   Delete tail of line (cursor to end); if empty, delete line
+ *    CTRL-@   Set the mark (remember the current location)
+ *    CTRL-K   Delete text from the mark to current position save on file
+ *    CTRL-C   Save the text from the mark to the current position
+ *    CTRL-Y   Insert the contents of the save file at current position
+ *    CTRL-Q   Insert the contents of the save file into a new file
+ *    CTRL-G   Insert a file at the current position
+ *   
+ *  MISCELLANEOUS
+ *    CTRL-E   Erase and redraw the screen
+ *    CTRL-V   Visit file (read a new file); complain if old one changed
+ *    CTRL-W   Write the current file back to the disk
+ *    numeric +  Search forward (prompt for regular expression)
+ *    numeric -  Search backward (prompt for regular expression)
+ *    numeric 5  Print the current status of the file
+ *    CTRL-R   (Global) Replace str1 by str2 (prompts for each string)
+ *    CTRL-L   (Line) Replace string1 by string2
+ *    CTRL-S   Fork off a shell and wait for it to finish
+ *    CTRL-X   EXIT (prompt if file modified)
+ *    CTRL-]   Go to a line. Prompts for linenumber
+ *    CTRL-\   Abort whatever editor was doing and start again
+ *    escape key  Repeat a command count times; (prompts for count)
+ */
+
+/*  ========================================================================  *
+ *				Utilities				      *	
+ *  ========================================================================  */
+
+#include "mined.h"
+#include <signal.h>
+#include <termios.h>
+#include <limits.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+extern int errno;
+int ymax = YMAX;
+int screenmax = SCREENMAX;
+
+
+/*
+ * Print file status.
+ */
+void FS()
+{
+  fstatus(file_name[0] ? "" : "[buffer]", -1L);
+}
+
+/*
+ * Visit (edit) another file. If the file has been modified, ask the user if
+ * he wants to save it.
+ */
+void VI()
+{
+  char new_file[LINE_LEN];	/* Buffer to hold new file name */
+
+  if (modified == TRUE && ask_save() == ERRORS)
+  	return;
+  
+/* Get new file name */
+  if (get_file("Visit file:", new_file) == ERRORS)
+  	return;
+
+/* Free old linked list, initialize global variables and load new file */
+  initialize();
+#ifdef UNIX
+  tputs(CL, 0, _putchar);
+#else
+  string_print (enter_string);
+#endif /* UNIX */
+  load_file(new_file[0] == '\0' ? NIL_PTR : new_file);
+}
+
+/*
+ * Write file in core to disc.
+ */
+int WT()
+{
+  register LINE *line;
+  register long count = 0L;	/* Nr of chars written */
+  char file[LINE_LEN];		/* Buffer for new file name */
+  int fd;				/* Filedescriptor of file */
+
+  if (modified == FALSE) {
+	error ("Write not necessary.", NIL_PTR);
+	return FINE;
+  }
+
+/* Check if file_name is valid and if file can be written */
+  if (file_name[0] == '\0' || writable == FALSE) {
+  	if (get_file("Enter file name:", file) != FINE)
+  		return ERRORS;
+  	copy_string(file_name, file);		/* Save file name */
+  }
+  if ((fd = creat(file_name, 0644)) < 0) {	/* Empty file */
+  	error("Cannot create ", file_name);
+  	writable = FALSE;
+  	return ERRORS;
+  }
+  else
+  	writable = TRUE;
+
+  clear_buffer();
+
+  status_line("Writing ", file_name);
+  for (line = header->next; line != tail; line = line->next) {
+	if (line->shift_count & DUMMY) {
+		if (line->next == tail && line->text[0] == '\n')
+			continue;
+	}
+  	if (writeline(fd, line->text) == ERRORS) {
+  		count = -1L;
+  		break;
+  	}
+  	count += (long) length_of(line->text);
+  }
+
+  if (count > 0L && flush_buffer(fd) == ERRORS)
+  	count = -1L;
+
+  (void) close(fd);
+
+  if (count == -1L)
+  	return ERRORS;
+
+  modified = FALSE;
+  rpipe = FALSE;		/* File name is now assigned */
+
+/* Display how many chars (and lines) were written */
+  fstatus("Wrote", count);
+  return FINE;
+}
+
+/* Call WT and discard value returned. */
+void XWT()
+{
+  (void) WT();
+}
+
+
+
+/*
+ * Call an interactive shell.
+ */
+void SH()
+{
+  register int w;
+  int pid, status;
+  char *shell;
+
+  if ((shell = getenv("SHELL")) == NIL_PTR) shell = "/bin/sh";
+
+  switch (pid = fork()) {
+  	case -1:			/* Error */
+  		error("Cannot fork.", NIL_PTR);
+  		return;
+  	case 0:				/* This is the child */
+  		set_cursor(0, ymax);
+  		putchar('\n');
+  		flush();
+  		raw_mode(OFF);
+		if (rpipe) {			/* Fix stdin */
+			close (0);
+			if (open("/dev/tty", 0) < 0)
+				exit (126);
+		}
+  		execl(shell, shell, (char *) 0);
+  		exit(127);			/* Exit with 127 */
+  	default :				/* This is the parent */
+  		signal(SIGINT, SIG_IGN);
+  		signal(SIGQUIT, SIG_IGN);
+  		do {
+  			w = wait(&status);
+  		} while (w != -1 && w != pid);
+  }
+
+  raw_mode(ON);
+  RD();
+
+  if ((status >> 8) == 127)		/* Child died with 127 */
+  	error("Cannot exec ", shell);
+  else if ((status >> 8) == 126)
+  	error("Cannot open /dev/tty as fd #0", NIL_PTR);
+}
+
+/*
+ * Proceed returns the count'th line after `line'. When count is negative
+ * it returns the count'th line before `line'. When the next (previous)
+ * line is the tail (header) indicating EOF (tof) it stops.
+ */
+LINE *proceed(line, count)
+register LINE *line;
+register int count;
+{
+  if (count < 0)
+  	while (count++ < 0 && line != header)
+  		line = line->prev;
+  else
+  	while (count-- > 0 && line != tail)
+  		line = line->next;
+  return line;
+}
+
+/*
+ * Show concatenation of s1 and s2 on the status line (bottom of screen)
+ * If revfl is TRUE, turn on reverse video on both strings. Set stat_visible
+ * only if bottom_line is visible.
+ */
+int bottom_line(revfl, s1, s2, inbuf, statfl)
+FLAG revfl;
+char *s1, *s2;
+char *inbuf;
+FLAG statfl;
+{
+  int ret = FINE;
+  char buf[LINE_LEN];
+  register char *p = buf;
+
+  *p++ = ' ';
+  if (s1 != NIL_PTR)
+	while (*p = *s1++)
+		p++;
+  if (s2 != NIL_PTR)
+	while (*p = *s2++)
+		p++;
+  *p++ = ' ';
+  *p++ = 0;
+
+  if (revfl == ON && stat_visible == TRUE)
+	clear_status ();
+  set_cursor(0, ymax);
+  if (revfl == ON) {		/* Print rev. start sequence */
+#ifdef UNIX
+  	tputs(SO, 0, _putchar);
+#else
+  	string_print(rev_video);
+#endif /* UNIX */
+  	stat_visible = TRUE;
+  }
+  else				/* Used as clear_status() */
+  	stat_visible = FALSE;
+
+  string_print(buf);
+  
+  if (inbuf != NIL_PTR)
+  	ret = input(inbuf, statfl);
+
+  /* Print normal video */
+#ifdef UNIX
+  tputs(SE, 0, _putchar);
+  tputs(CE, 0, _putchar);
+#else
+  string_print(normal_video);
+  string_print(blank_line);	/* Clear the rest of the line */
+#endif /* UNIX */
+  if (inbuf != NIL_PTR)
+  	set_cursor(0, ymax);
+  else
+  	set_cursor(x, y);	/* Set cursor back to old position */
+  flush();			/* Perform the actual write */
+  if (ret != FINE)
+  	clear_status();
+  return ret;
+}
+
+/*
+ * Count_chars() count the number of chars that the line would occupy on the
+ * screen. Counting starts at the real x-coordinate of the line.
+ */
+int count_chars(line)
+LINE *line;
+{
+  register int cnt = get_shift(line->shift_count) * -SHIFT_SIZE;
+  register char *textp = line->text;
+
+/* Find begin of line on screen */
+  while (cnt < 0) {
+  	if (is_tab(*textp++))
+  		cnt = tab(cnt);
+  	else
+  		cnt++;
+  }
+
+/* Count number of chars left */
+  cnt = 0;
+  while (*textp != '\n') {
+  	if (is_tab(*textp++))
+  		 cnt = tab(cnt);
+  	else
+  		cnt++;
+  }
+  return cnt;
+}
+
+/*
+ * Move to coordinates nx, ny at screen.  The caller must check that scrolling
+ * is not needed.
+ * If new_x is lower than 0 or higher than XBREAK, move_to() will check if
+ * the line can be shifted. If it can it sets(or resets) the shift_count field
+ * of the current line accordingly.
+ * Move also sets cur_text to the right char.
+ * If we're moving to the same x coordinate, try to move the the x-coordinate
+ * used on the other previous call.
+ */
+void move(new_x, new_address, new_y)
+register int new_x;
+int new_y;
+char *new_address;
+{
+  register LINE *line = cur_line;	/* For building new cur_line */
+  int shift = 0;			/* How many shifts to make */
+  static int rel_x = 0;		/* Remember relative x position */
+  int tx = x;
+
+/* Check for illegal values */
+  if (new_y < 0 || new_y > last_y)
+  	return;
+
+/* Adjust y-coordinate and cur_line */
+  if (new_y < y)
+  	while (y != new_y) {
+  		y--;
+  		line = line->prev;
+  	}
+  else
+  	while (y != new_y) {
+  		y++;
+  		line = line->next;
+  	}
+
+/* Set or unset relative x-coordinate */
+  if (new_address == NIL_PTR) {
+  	new_address = find_address(line, (new_x == x) ? rel_x : new_x , &tx);
+	if (new_x != x)
+		rel_x = tx;
+  	new_x = tx;
+  }
+  else
+  	rel_x = new_x = find_x(line, new_address);
+
+/* Adjust shift_count if new_x lower than 0 or higher than XBREAK */
+  if (new_x < 0 || new_x >= XBREAK) {
+  	if (new_x > XBREAK || (new_x == XBREAK && *new_address != '\n'))
+  		shift = (new_x - XBREAK) / SHIFT_SIZE + 1;
+  	else {
+  		shift = new_x / SHIFT_SIZE;
+		if (new_x % SHIFT_SIZE)
+			shift--;
+  	}
+
+  	if (shift != 0) {
+  		line->shift_count += shift;
+  		new_x = find_x(line, new_address);
+  		set_cursor(0, y);
+  		line_print(line);
+  		rel_x = new_x;
+  	}
+  }
+
+/* Assign and position cursor */
+  x = new_x;
+  cur_text = new_address;
+  cur_line = line;
+  set_cursor(x, y);
+}
+
+/*
+ * Find_x() returns the x coordinate belonging to address.
+ * (Tabs are expanded).
+ */
+int find_x(line, address)
+LINE *line;
+char *address;
+{
+  register char *textp = line->text;
+  register int nx = get_shift(line->shift_count) * -SHIFT_SIZE;
+
+  while (textp != address && *textp != '\0') {
+  	if (is_tab(*textp++)) 	/* Expand tabs */
+  		nx = tab(nx);
+  	else
+  		nx++;
+  }
+  return nx;
+}
+
+/*
+ * Find_address() returns the pointer in the line with offset x_coord.
+ * (Tabs are expanded).
+ */
+char *find_address(line, x_coord, old_x)
+LINE *line;
+int x_coord;
+int *old_x;
+{
+  register char *textp = line->text;
+  register int tx = get_shift(line->shift_count) * -SHIFT_SIZE;
+
+  while (tx < x_coord && *textp != '\n') {
+  	if (is_tab(*textp)) {
+  		if (*old_x - x_coord == 1 && tab(tx) > x_coord)
+  			break;		/* Moving left over tab */
+  		else
+  			tx = tab(tx);
+  	}
+  	else
+  		tx++;
+  	textp++;
+  }
+  
+  *old_x = tx;
+  return textp;
+}
+
+/*
+ * Length_of() returns the number of characters int the string `string'
+ * excluding the '\0'.
+ */
+int length_of(string)
+register char *string;
+{
+  register int count = 0;
+
+  if (string != NIL_PTR) {
+  	while (*string++ != '\0')
+  		count++;
+  }
+  return count;
+}
+
+/*
+ * Copy_string() copies the string `from' into the string `to'. `To' must be
+ * long enough to hold `from'.
+ */
+void copy_string(to, from)
+register char *to;
+register char *from;
+{
+  while (*to++ = *from++)
+  	;
+}
+
+/*
+ * Reset assigns bot_line, top_line and cur_line according to `head_line'
+ * which must be the first line of the screen, and an y-coordinate,
+ * which will be the current y-coordinate (if it isn't larger than last_y)
+ */
+void reset(head_line, screen_y)
+LINE *head_line;
+int screen_y;
+{
+  register LINE *line;
+
+  top_line = line = head_line;
+
+/* Search for bot_line (might be last line in file) */
+  for (last_y = 0; last_y < nlines - 1 && last_y < screenmax
+						&& line->next != tail; last_y++)
+  	line = line->next;
+
+  bot_line = line;
+  y = (screen_y > last_y) ? last_y : screen_y;
+
+/* Set cur_line according to the new y value */
+  cur_line = proceed(top_line, y);
+}
+
+/*
+ * Set cursor at coordinates x, y.
+ */
+void set_cursor(nx, ny)
+int nx, ny;
+{
+#ifdef UNIX
+  extern char *tgoto();
+
+  tputs(tgoto(CM, nx, ny), 0, _putchar);
+#else
+  char text_buffer[10];
+
+  build_string(text_buffer, pos_string, ny+1, nx+1);
+  string_print(text_buffer);
+#endif /* UNIX */
+}
+
+/*
+ * Routine to open terminal when mined is used in a pipeline.
+ */
+void open_device()
+{
+  if ((input_fd = open("/dev/tty", 0)) < 0)
+	panic("Cannot open /dev/tty for read");
+}
+
+/*
+ * Getchar() reads one character from the terminal. The character must be
+ * masked with 0377 to avoid sign extension.
+ */
+int getchar()
+{
+#ifdef UNIX
+  return (_getchar() & 0377);
+#else
+  char c;
+
+  if (read(input_fd, &c, 1) != 1 && quit == FALSE)
+  	panic("Can't read one char from fd #0");
+
+  return c & 0377;
+#endif /* UNIX */
+}
+
+/*
+ * Display() shows count lines on the terminal starting at the given
+ * coordinates. When the tail of the list is encountered it will fill the
+ * rest of the screen with blank_line's.
+ * When count is negative, a backwards print from `line' will be done.
+ */
+void display(x_coord, y_coord, line, count)
+int x_coord, y_coord;
+register LINE *line;
+register int count;
+{
+  set_cursor(x_coord, y_coord);
+
+/* Find new startline if count is negative */
+  if (count < 0) {
+  	line = proceed(line, count);
+  	count = -count;
+  }
+
+/* Print the lines */
+  while (line != tail && count-- >= 0) {
+  	line_print(line);
+  	line = line->next;
+  }
+
+/* Print the blank lines (if any) */
+  if (loading == FALSE) {
+	while (count-- >= 0) {
+#ifdef UNIX
+		tputs(CE, 0, _putchar);
+#else
+		string_print(blank_line);
+#endif /* UNIX */
+		putchar('\n');
+	}
+  }
+}
+
+/*
+ * Write_char does a buffered output. 
+ */
+int write_char(fd, c)
+int fd;
+char c;
+{
+  screen [out_count++] = c;
+  if (out_count == SCREEN_SIZE)		/* Flush on SCREEN_SIZE chars */
+  	return flush_buffer(fd);
+  return FINE;
+}
+
+/*
+ * Writeline writes the given string on the given filedescriptor.
+ */
+int writeline(fd, text)
+register int fd;
+register char *text;
+{
+  while(*text)
+  	 if (write_char(fd, *text++) == ERRORS)
+  		return ERRORS;
+  return FINE;
+}
+
+/*
+ * Put_line print the given line on the standard output. If offset is not zero
+ * printing will start at that x-coordinate. If the FLAG clear_line is TRUE,
+ * then (screen) line will be cleared when the end of the line has been
+ * reached.
+ */
+void put_line(line, offset, clear_line)
+LINE *line;				/* Line to print */
+int offset;				/* Offset to start */
+FLAG clear_line;			/* Clear to eoln if TRUE */
+{
+  register char *textp = line->text;
+  register int count = get_shift(line->shift_count) * -SHIFT_SIZE;
+  int tab_count;			/* Used in tab expansion */
+
+/* Skip all chars as indicated by the offset and the shift_count field */
+  while (count < offset) {
+  	if (is_tab(*textp++))
+  		count = tab(count);
+  	else
+  		count++;
+  }
+
+  while (*textp != '\n' && count < XBREAK) {
+  	if (is_tab(*textp)) {		/* Expand tabs to spaces */
+  		tab_count = tab(count);
+  		while (count < XBREAK && count < tab_count) {
+  			count++;
+  			putchar(' ');
+  		}
+  		textp++;
+  	}
+  	else {
+		if (*textp >= '\01' && *textp <= '\037') {
+#ifdef UNIX
+			tputs(SO, 0, _putchar);
+#else
+			string_print (rev_video);
+#endif /* UNIX */
+  			putchar(*textp++ + '\100');
+#ifdef UNIX
+			tputs(SE, 0, _putchar);
+#else
+			string_print (normal_video);
+#endif /* UNIX */
+		}
+		else
+  			putchar(*textp++);
+  		count++;
+  	}
+  }
+
+/* If line is longer than XBREAK chars, print the shift_mark */
+  if (count == XBREAK && *textp != '\n')
+  	putchar(textp[1]=='\n' ? *textp : SHIFT_MARK);
+
+/* Clear the rest of the line is clear_line is TRUE */
+  if (clear_line == TRUE) {
+#ifdef	UNIX
+  	tputs(CE, 0, _putchar);
+#else
+	string_print(blank_line);
+#endif /* UNIX */
+  	putchar('\n');
+  }
+}
+
+/*
+ * Flush the I/O buffer on filedescriptor fd.
+ */
+int flush_buffer(fd)
+int fd;
+{
+  if (out_count <= 0)		/* There is nothing to flush */
+  	return FINE;
+#ifdef UNIX
+  if (fd == STD_OUT) {
+  	printf("%.*s", out_count, screen);
+  	_flush();
+  }
+  else
+#endif /* UNIX */
+  if (write(fd, screen, out_count) != out_count) {
+  	bad_write(fd);
+  	return ERRORS;
+  }
+  clear_buffer();		/* Empty buffer */
+  return FINE;
+}
+
+/*
+ * Bad_write() is called when a write failed. Notify the user.
+ */
+void bad_write(fd)
+int fd;
+{
+  if (fd == STD_OUT)		/* Cannot write to terminal? */
+  	exit(1);
+  
+  clear_buffer();
+  build_string(text_buffer, "Command aborted: %s (File incomplete)",
+  		            (errno == ENOSPC || errno == -ENOSPC) ?
+  			    "No space on device" : "Write error");
+  error(text_buffer, NIL_PTR);
+}
+
+/*
+ * Catch the SIGQUIT signal (^\) send to mined. It turns on the quitflag.
+ */
+void catch(sig)
+int sig;
+{
+/* Reset the signal */
+  signal(SIGQUIT, catch);
+  quit = TRUE;
+}
+
+/*
+ * Abort_mined() will leave mined. Confirmation is asked first.
+ */
+void abort_mined()
+{
+  quit = FALSE;
+
+/* Ask for confirmation */
+  status_line("Really abort? ", NIL_PTR);
+  if (getchar() != 'y') {
+  	clear_status();
+  	return;
+  }
+
+/* Reset terminal */
+  raw_mode(OFF);
+  set_cursor(0, ymax);
+  putchar('\n');
+  flush();
+#ifdef UNIX
+  abort();
+#else
+  exit(1);
+#endif /* UNIX */
+}
+
+#define UNDEF	_POSIX_VDISABLE
+
+/*
+ * Set and reset tty into CBREAK or old mode according to argument `state'. It
+ * also sets all signal characters (except for ^\) to UNDEF. ^\ is caught.
+ */
+void raw_mode(state)
+FLAG state;
+{
+  static struct termios old_tty;
+  static struct termios new_tty;
+
+  if (state == OFF) {
+  	tcsetattr(input_fd, TCSANOW, &old_tty);
+  	return;
+  }
+
+/* Save old tty settings */
+  tcgetattr(input_fd, &old_tty);
+
+/* Set tty to CBREAK mode */
+  tcgetattr(input_fd, &new_tty);
+  new_tty.c_lflag &= ~(ICANON|ECHO|ECHONL);
+  new_tty.c_iflag &= ~(IXON|IXOFF);
+
+/* Unset signal chars, leave only SIGQUIT set to ^\ */
+  new_tty.c_cc[VINTR] = new_tty.c_cc[VSUSP] = UNDEF;
+  new_tty.c_cc[VQUIT] = '\\' & 037;
+  signal(SIGQUIT, catch);		/* Which is caught */
+
+  tcsetattr(input_fd, TCSANOW, &new_tty);
+}
+
+/*
+ * Panic() is called with an error number and a message. It is called when
+ * something unrecoverable has happened.
+ * It writes the message to the terminal, resets the tty and exits.
+ * Ask the user if he wants to save his file.
+ */
+void panic(message)
+register char *message;
+{
+  extern char yank_file[];
+
+#ifdef UNIX
+  tputs(CL, 0, _putchar);
+  build_string(text_buffer, "%s\nError code %d\n", message, errno);
+#else
+  build_string(text_buffer, "%s%s\nError code %d\n", enter_string, message, errno);
+#endif /* UNIX */
+  (void) write(STD_OUT, text_buffer, length_of(text_buffer));
+
+  if (loading == FALSE)
+  	XT();			/* Check if file can be saved */
+  else
+  	(void) unlink(yank_file);
+  raw_mode(OFF);
+
+#ifdef UNIX
+  abort();
+#else
+  exit(1);
+#endif /* UNIX */
+}
+
+char *alloc(bytes)
+int bytes;
+{
+  char *p;
+
+  p = malloc((unsigned) bytes);
+  if (p == NIL_PTR) {
+	if (loading == TRUE)
+		panic("File too big.");
+	panic("Out of memory.");
+  }
+  return(p);
+}
+
+void free_space(p)
+char *p;
+{
+  free(p);
+}
+
+/*  ========================================================================  *
+ *				Main loops				      *
+ *  ========================================================================  */
+
+/* The mapping between input codes and functions. */
+
+void (*key_map[256])() = {       /* map ASCII characters to functions */
+   /* 000-017 */ MA, BL, MP, YA, SD, RD, MN, IF, DPC, S, S, DT, LR, S, DNW,LIB,
+   /* 020-037 */ DPW, WB, GR, SH, DLN, SU, VI, XWT, XT, PT, EL, ESC, I, GOTO,
+		 HIGH, LOW,
+   /* 040-057 */ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+   /* 060-077 */ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+   /* 100-117 */ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+   /* 120-137 */ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+   /* 140-157 */ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+   /* 160-177 */ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, DCC,
+   /* 200-217 */ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+   /* 220-237 */ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+   /* 240-257 */ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+   /* 260-277 */ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+   /* 300-317 */ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+   /* 320-337 */ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+   /* 340-357 */ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+   /* 360-377 */ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+};
+
+int nlines;			/* Number of lines in file */
+LINE *header;			/* Head of line list */
+LINE *tail;			/* Last line in line list */
+LINE *cur_line;			/* Current line in use */
+LINE *top_line;			/* First line of screen */
+LINE *bot_line;			/* Last line of screen */
+char *cur_text;			/* Current char on current line in use */
+int last_y;			/* Last y of screen. Usually SCREENMAX */
+char screen[SCREEN_SIZE];	/* Output buffer for "writes" and "reads" */
+
+int x, y;			/* x, y coordinates on screen */
+FLAG modified = FALSE;		/* Set when file is modified */
+FLAG stat_visible;		/* Set if status_line is visible */
+FLAG writable;			/* Set if file cannot be written */
+FLAG loading;			/* Set if we are loading a file. */
+FLAG quit = FALSE;		/* Set when quit character is typed */
+FLAG rpipe = FALSE;		/* Set if file should be read from stdin */
+int input_fd = 0;		/* Fd for command input */
+int out_count;			/* Index in output buffer */
+char file_name[LINE_LEN];	/* Name of file in use */
+char text_buffer[MAX_CHARS];	/* Buffer for modifying text */
+
+/* Escape sequences. */
+#ifdef UNIX
+char *CE, *VS, *SO, *SE, *CL, *AL, *CM;
+#else
+char   *enter_string = "\033[H\033[J";	/* String printed on entering mined */
+char   *pos_string = "\033[%d;%dH";	/* Absolute cursor position */
+char   *rev_scroll = "\033M";		/* String for reverse scrolling */
+char   *rev_video = "\033[7m";		/* String for starting reverse video */
+char   *normal_video = "\033[m";	/* String for leaving reverse video */
+char   *blank_line = "\033[K";		/* Clear line to end */
+#endif /* UNIX */
+
+/* 
+ * Yank variables.
+ */
+FLAG yank_status = NOT_VALID;		/* Status of yank_file */
+char yank_file[] = "/tmp/mined.XXXXXX";
+long chars_saved;			/* Nr of chars in buffer */
+
+/*
+ * Initialize is called when a another file is edited. It free's the allocated
+ * space and sets modified back to FALSE and fixes the header/tail pointer.
+ */
+void initialize()
+{
+  register LINE *line, *next_line;
+
+/* Delete the whole list */
+  for (line = header->next; line != tail; line = next_line) {
+  	next_line = line->next;
+  	free_space(line->text);
+  	free_space((char*)line);
+  }
+
+/* header and tail should point to itself */
+  line->next = line->prev = line;
+  x = y = 0;
+  rpipe = modified = FALSE;
+}
+
+/*
+ * Basename() finds the absolute name of the file out of a given path_name.
+ */
+char *basename(path)
+char *path;
+{
+  register char *ptr = path;
+  register char *last = NIL_PTR;
+
+  while (*ptr != '\0') {
+  	if (*ptr == '/')
+  		last = ptr;
+  	ptr++;
+  }
+  if (last == NIL_PTR)
+  	return path;
+  if (*(last + 1) == '\0') {	/* E.g. /usr/tmp/pipo/ */
+  	*last = '\0';
+  	return basename(path);/* Try again */
+  }
+  return last + 1;
+}
+
+/*
+ * Load_file loads the file `file' into core. If file is a NIL_PTR or the file
+ * couldn't be opened, just some initializations are done, and a line consisting
+ * of a `\n' is installed.
+ */
+void load_file(file)
+char *file;
+{
+  register LINE *line = header;
+  register int len;
+  long nr_of_chars = 0L;
+  int fd = -1;			/* Filedescriptor for file */
+
+  nlines = 0;			/* Zero lines to start with */
+
+/* Open file */
+  writable = TRUE;		/* Benefit of the doubt */
+  if (file == NIL_PTR) {
+	if (rpipe == FALSE)
+  		status_line("No file.", NIL_PTR);
+	else {
+		fd = 0;
+		file = "standard input";
+	}
+	file_name[0] = '\0';
+  }
+  else {
+  	copy_string(file_name, file);	/* Save file name */
+  	if (access(file, 0) < 0)	/* Cannot access file. */
+  		status_line("New file ", file);
+  	else if ((fd = open(file, 0)) < 0)
+  		status_line("Cannot open ", file);
+  	else if (access(file, 2) != 0)	/* Set write flag */
+  		writable = FALSE;
+  }
+
+/* Read file */
+  loading = TRUE;				/* Loading file, so set flag */
+
+  if (fd >= 0) {
+  	status_line("Reading ", file);
+  	while ((len = get_line(fd, text_buffer)) != ERRORS) {
+  		line = line_insert(line, text_buffer, len);
+  		nr_of_chars += (long) len;
+  	}
+  	if (nlines == 0)		/* The file was empty! */
+  		line = line_insert(line, "\n", 1);
+  	clear_buffer();		/* Clear output buffer */
+  	cur_line = header->next;
+  	fstatus("Read", nr_of_chars);
+  	(void) close(fd);		/* Close file */
+  }
+  else					/* Just install a "\n" */
+  	(void) line_insert(line, "\n", 1);
+
+  reset(header->next, 0);		/* Initialize pointers */
+
+/* Print screen */
+  display (0, 0, header->next, last_y);
+  move_to (0, 0);
+  flush();				/* Flush buffer */
+  loading = FALSE;			/* Stop loading, reset flag */
+}
+
+
+/*
+ * Get_line reads one line from filedescriptor fd. If EOF is reached on fd,
+ * get_line() returns ERRORS, else it returns the length of the string.
+ */
+int get_line(fd, buffer)
+int fd;
+register char *buffer;
+{
+  static char *last = NIL_PTR;
+  static char *current = NIL_PTR;
+  static int read_chars;
+  register char *cur_pos = current;
+  char *begin = buffer;
+
+  do {
+  	if (cur_pos == last) {
+  		if ((read_chars = read(fd, screen, SCREEN_SIZE)) <= 0)
+  			break;
+  		last = &screen[read_chars];
+  		cur_pos = screen;
+  	}
+	if (*cur_pos == '\0')
+		*cur_pos = ' ';
+  } while ((*buffer++ = *cur_pos++) != '\n');
+
+  current = cur_pos;
+  if (read_chars <= 0) {
+  	if (buffer == begin)
+  		return ERRORS;
+  	if (*(buffer - 1) != '\n')
+  		if (loading == TRUE) /* Add '\n' to last line of file */
+  			*buffer++ = '\n';
+  		else {
+  			*buffer = '\0';
+  			return NO_LINE;
+  		}
+  }
+
+  *buffer = '\0';
+  return buffer - begin;
+}
+
+/*
+ * Install_line installs the buffer into a LINE structure It returns a pointer
+ * to the allocated structure.
+ */
+LINE *install_line(buffer, length)
+char *buffer;
+int length;
+{
+  register LINE *new_line = (LINE *) alloc(sizeof(LINE));
+
+  new_line->text = alloc(length + 1);
+  new_line->shift_count = 0;
+  copy_string(new_line->text, buffer);
+
+  return new_line;
+}
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+/* mined is the Minix editor. */
+
+  register int index;		/* Index in key table */
+  struct winsize winsize;
+
+#ifdef UNIX
+  get_term();
+  tputs(VS, 0, _putchar);
+  tputs(CL, 0, _putchar);
+#else
+  string_print(enter_string);			/* Hello world */
+#endif /* UNIX */
+  if (ioctl(STD_OUT, TIOCGWINSZ, &winsize) == 0 && winsize.ws_row != 0) {
+	ymax = winsize.ws_row - 1;
+	screenmax = ymax - 1;
+  }
+
+  if (!isatty(0)) {		/* Reading from pipe */
+	if (argc != 1) {
+		write(2, "Cannot find terminal.\n", 22);
+		exit (1);
+	}
+	rpipe = TRUE;
+	modified = TRUE;	/* Set modified so he can write */
+	open_device();
+  }
+
+  raw_mode(ON);			/* Set tty to appropriate mode */
+
+  header = tail = (LINE *) alloc(sizeof(LINE));	/* Make header of list*/
+  header->text = NIL_PTR;
+  header->next = tail->prev = header;
+
+/* Load the file (if any) */
+  if (argc < 2)
+  	load_file(NIL_PTR);
+  else {
+  	(void) get_file(NIL_PTR, argv[1]);	/* Truncate filename */
+  	load_file(argv[1]);
+  }
+
+ /* Main loop of the editor. */
+  for (;;) {
+  	index = getchar();
+  	if (stat_visible == TRUE)
+  		clear_status();
+  	if (quit == TRUE)
+  		abort_mined();
+  	else {			/* Call the function for this key */
+  		(*key_map[index])(index);
+  		flush();       /* Flush output (if any) */
+  		if (quit == TRUE)
+  			quit = FALSE;
+  	}
+  }
+  /* NOTREACHED */
+}
+
+/*  ========================================================================  *
+ *				Miscellaneous				      *
+ *  ========================================================================  */
+
+/*
+ * Redraw the screen
+ */
+void RD()
+{
+/* Clear screen */
+#ifdef UNIX
+  tputs(VS, 0, _putchar);
+  tputs(CL, 0, _putchar);
+#else
+  string_print(enter_string);
+#endif /* UNIX */
+
+/* Print first page */
+  display(0, 0, top_line, last_y);
+
+/* Clear last line */
+  set_cursor(0, ymax);
+#ifdef UNIX
+  tputs(CE, 0, _putchar);
+#else
+  string_print(blank_line);
+#endif /* UNIX */
+  move_to(x, y);
+}
+
+/*
+ * Ignore this keystroke.
+ */
+void I()
+{
+}
+
+/*
+ * Leave editor. If the file has changed, ask if the user wants to save it.
+ */
+void XT()
+{
+  if (modified == TRUE && ask_save() == ERRORS)
+  	return;
+
+  raw_mode(OFF);
+  set_cursor(0, ymax);
+  putchar('\n');
+  flush();
+  (void) unlink(yank_file);		/* Might not be necessary */
+  exit(0);
+}
+
+void (*escfunc(c))()
+int c;
+{
+#if (CHIP == M68000)
+#ifndef COMPAT
+  int ch;
+#endif
+#endif
+  if (c == '[') {
+	/* Start of ASCII escape sequence. */
+	c = getchar();
+#if (CHIP == M68000)
+#ifndef COMPAT
+	if ((c >= '0') && (c <= '9')) ch = getchar();
+	/* ch is either a tilde or a second digit */
+#endif
+#endif
+	switch (c) {
+	case 'H': return(HO);
+	case 'A': return(UP);
+	case 'B': return(DN);
+	case 'C': return(RT);
+	case 'D': return(LF);
+#if (CHIP == M68000)
+#ifndef COMPAT
+	/* F1 = ESC [ 1 ~ */
+	/* F2 = ESC [ 2 ~ */
+	/* F3 = ESC [ 3 ~ */
+	/* F4 = ESC [ 4 ~ */
+	/* F5 = ESC [ 5 ~ */
+	/* F6 = ESC [ 6 ~ */
+	/* F7 = ESC [ 17 ~ */
+	/* F8 = ESC [ 18 ~ */
+	case '1': 
+	 	  switch (ch) {
+		  case '~': return(SF);
+		  case '7': (void) getchar(); return(MA);
+		  case '8': (void) getchar(); return(CTL);
+                  }
+	case '2': return(SR);
+	case '3': return(PD);
+	case '4': return(PU);
+	case '5': return(FS);
+	case '6': return(EF);
+#endif
+#endif
+#if (CHIP == INTEL)
+	case 'G': return(FS);
+	case 'S': return(SR);
+	case 'T': return(SF);
+	case 'U': return(PD);
+	case 'V': return(PU);
+	case 'Y': return(EF);
+#endif
+	}
+	return(I);
+  }
+#if (CHIP == M68000)
+#ifdef COMPAT
+  if (c == 'O') {
+	/* Start of ASCII function key escape sequence. */
+	switch (getchar()) {
+	case 'P': return(SF);
+	case 'Q': return(SR);
+	case 'R': return(PD);
+	case 'S': return(PU);
+	case 'T': return(FS);
+	case 'U': return(EF);
+	case 'V': return(MA);
+	case 'W': return(CTL);
+	}
+    }
+#endif
+#endif
+  return(I);
+}
+
+/*
+ * ESC() wants a count and a command after that. It repeats the 
+ * command count times. If a ^\ is given during repeating, stop looping and
+ * return to main loop.
+ */
+void ESC()
+{
+  register int count = 0;
+  register void (*func)();
+  int index;
+
+  index = getchar();
+  while (index >= '0' && index <= '9' && quit == FALSE) {
+  	count *= 10;
+  	count += index - '0';
+  	index = getchar();
+  }
+  if (count == 0) {
+	count = 1;
+	func = escfunc(index);
+  } else {
+	func = key_map[index];
+	if (func == ESC)
+		func = escfunc(getchar());
+  }
+
+  if (func == I) {	/* Function assigned? */
+  	clear_status();
+  	return;
+  }
+
+  while (count-- > 0 && quit == FALSE) {
+  	if (stat_visible == TRUE)
+  		clear_status();
+  	(*func)(index);
+  	flush();
+  }
+
+  if (quit == TRUE)		/* Abort has been given */
+  	error("Aborted", NIL_PTR);
+}
+
+/*
+ * Ask the user if he wants to save his file or not.
+ */
+int ask_save()
+{
+  register int c;
+
+  status_line(file_name[0] ? basename(file_name) : "[buffer]" ,
+					     " has been modified. Save? (y/n)");
+
+  while((c = getchar()) != 'y' && c != 'n' && quit == FALSE) {
+  	ring_bell();
+  	flush();
+  }
+
+  clear_status();
+
+  if (c == 'y')
+  	return WT();
+
+  if (c == 'n')
+  	return FINE;
+
+  quit = FALSE;	/* Abort character has been given */
+  return ERRORS;
+}
+
+/*
+ * Line_number() finds the line number we're on.
+ */
+int line_number()
+{
+  register LINE *line = header->next;
+  register int count = 1;
+
+  while (line != cur_line) {
+  	count++;
+  	line = line->next;
+  }
+  
+  return count;
+}
+  
+/*
+ * Display a line telling how many chars and lines the file contains. Also tell
+ * whether the file is readonly and/or modified.
+ */
+void file_status(message, count, file, lines, writefl, changed)
+char *message;
+register long count;		/* Contains number of characters in file */
+char *file;
+int lines;
+FLAG writefl, changed;
+{
+  register LINE *line;
+  char msg[LINE_LEN + 40];/* Buffer to hold line */
+  char yank_msg[LINE_LEN];/* Buffer for msg of yank_file */
+
+  if (count < 0)		/* Not valid. Count chars in file */
+  	for (line = header->next; line != tail; line = line->next)
+  		count += length_of(line->text);
+
+  if (yank_status != NOT_VALID)	/* Append buffer info */
+  	build_string(yank_msg, " Buffer: %D char%s.", chars_saved,
+						(chars_saved == 1L) ? "" : "s");
+  else
+  	yank_msg[0] = '\0';
+
+  build_string(msg, "%s %s%s%s %d line%s %D char%s.%s Line %d", message,
+  		    (rpipe == TRUE && *message != '[') ? "standard input" : basename(file),
+  		    (changed == TRUE) ? "*" : "",
+  		    (writefl == FALSE) ? " (Readonly)" : "",
+  		    lines, (lines == 1) ? "" : "s", 
+		    count, (count == 1L) ? "" : "s",
+		    yank_msg, line_number());
+
+  if (length_of(msg) + 1 > LINE_LEN - 4) {
+  	msg[LINE_LEN - 4] = SHIFT_MARK;	/* Overflow on status line */
+  	msg[LINE_LEN - 3] = '\0';
+  }
+  status_line(msg, NIL_PTR);		/* Print the information */
+}
+
+/*
+ * Build_string() prints the arguments as described in fmt, into the buffer.
+ * %s indicates an argument string, %d indicated an argument number.
+ */
+#if __STDC__
+void build_string(char *buf, char *fmt, ...)
+{
+#else
+void build_string(buf, fmt, va_alist)
+char *buf, *fmt;
+va_dcl
+{
+#endif
+  va_list argptr;
+  char *scanp;
+
+#if __STDC__
+  va_start(argptr, fmt);
+#else
+  va_start(argptr);
+#endif
+
+  while (*fmt) {
+  	if (*fmt == '%') {
+  		fmt++;
+  		switch (*fmt++) {
+  		case 's' :
+  			scanp = va_arg(argptr, char *);
+  			break;
+  		case 'd' :
+  			scanp = num_out((long) va_arg(argptr, int));
+  			break;
+  		case 'D' :
+  			scanp = num_out((long) va_arg(argptr, long));
+  			break;
+  		default :
+  			scanp = "";
+  		}
+  		while (*buf++ = *scanp++)
+  			;
+  		buf--;
+  	}
+  	else
+  		*buf++ = *fmt++;
+  }
+  va_end(argptr);
+  *buf = '\0';
+}
+
+/*
+ * Output an (unsigned) long in a 10 digit field without leading zeros.
+ * It returns a pointer to the first digit in the buffer.
+ */
+char *num_out(number)
+long number;
+{
+  static char num_buf[11];		/* Buffer to build number */
+  register long digit;			/* Next digit of number */
+  register long pow = 1000000000L;	/* Highest ten power of long */
+  FLAG digit_seen = FALSE;
+  int i;
+
+  for (i = 0; i < 10; i++) {
+  	digit = number / pow;		/* Get next digit */
+  	if (digit == 0L && digit_seen == FALSE && i != 9)
+  		num_buf[i] = ' ';
+  	else {
+  		num_buf[i] = '0' + (char) digit;
+  		number -= digit * pow;	/* Erase digit */
+  		digit_seen = TRUE;
+  	}
+  	pow /= 10L;			/* Get next digit */
+  }
+  for (i = 0; num_buf[i] == ' '; i++)	/* Skip leading spaces */
+  	;
+  return (&num_buf[i]);
+}
+
+/*
+ * Get_number() read a number from the terminal. The last character typed in is
+ * returned.  ERRORS is returned on a bad number. The resulting number is put
+ * into the integer the arguments points to.
+ */
+int get_number(message, result)
+char *message;
+int *result;
+{
+  register int index;
+  register int count = 0;
+
+  status_line(message, NIL_PTR);
+
+  index = getchar();
+  if (quit == FALSE && (index < '0' || index > '9')) {
+  	error("Bad count", NIL_PTR);
+  	return ERRORS;
+  }
+
+/* Convert input to a decimal number */
+  while (index >= '0' && index <= '9' && quit == FALSE) {
+  	count *= 10;
+  	count += index - '0';
+  	index = getchar();
+  }
+
+  if (quit == TRUE) {
+  	clear_status();
+  	return ERRORS;
+  }
+
+  *result = count;
+  return index;
+}
+
+/*
+ * Input() reads a string from the terminal.  When the KILL character is typed,
+ * it returns ERRORS.
+ */
+int input(inbuf, clearfl)
+char *inbuf;
+FLAG clearfl;
+{
+  register char *ptr;
+  register char c;			/* Character read */
+
+  ptr = inbuf;
+
+  *ptr = '\0';
+  while (quit == FALSE) {
+  	flush();
+  	switch (c = getchar()) {
+  		case '\b' :		/* Erase previous char */
+  			if (ptr > inbuf) {
+  				ptr--;
+#ifdef UNIX
+  				tputs(SE, 0, _putchar);
+#else
+  				string_print(normal_video);
+#endif /* UNIX */
+  				if (is_tab(*ptr))
+  					string_print(" \b\b\b  \b\b");
+  				else
+  					string_print(" \b\b \b");
+#ifdef UNIX
+  				tputs(SO, 0, _putchar);
+#else
+  				string_print(rev_video);
+#endif /* UNIX */
+  				string_print(" \b");
+  				*ptr = '\0';
+  			}
+  			else
+  				ring_bell();
+  			break;
+  		case '\n' :		/* End of input */
+  			/* If inbuf is empty clear status_line */
+  			return (ptr == inbuf && clearfl == TRUE) ? NO_INPUT :FINE;
+  		default :		/* Only read ASCII chars */
+  			if ((c >= ' ' && c <= '~') || c == '\t') {
+  				*ptr++ = c;
+  				*ptr = '\0';
+  				if (c == '\t')
+  					string_print("^I");
+  				else
+  					putchar(c);
+  				string_print(" \b");
+  			}
+  			else
+  				ring_bell();
+  	}
+  }
+  quit = FALSE;
+  return ERRORS;
+}
+
+/*
+ * Get_file() reads a filename from the terminal. Filenames longer than 
+ * FILE_LENGHT chars are truncated.
+ */
+int get_file(message, file)
+char *message, *file;
+{
+  char *ptr;
+  int ret;
+
+  if (message == NIL_PTR || (ret = get_string(message, file, TRUE)) == FINE) {
+  	if (length_of((ptr = basename(file))) > NAME_MAX)
+  		ptr[NAME_MAX] = '\0';
+  }
+  return ret;
+}
+
+/*  ========================================================================  *
+ *				UNIX I/O Routines			      *
+ *  ========================================================================  */
+
+#ifdef UNIX
+#undef putchar
+
+int _getchar()
+{
+  char c;
+
+  if (read(input_fd, &c, 1) != 1 && quit == FALSE)
+	panic ("Cannot read 1 byte from input");
+  return c & 0377;
+}
+
+void _flush()
+{
+  (void) fflush(stdout);
+}
+
+void _putchar(c)
+char c;
+{
+  (void) write_char(STD_OUT, c);
+}
+
+void get_term()
+{
+  static char termbuf[50];
+  extern char *tgetstr(), *getenv();
+  char *loc = termbuf;
+  char entry[1024];
+
+  if (tgetent(entry, getenv("TERM")) <= 0) {
+  	printf("Unknown terminal.\n");
+  	exit(1);
+  }
+
+  AL = tgetstr("al", &loc);
+  CE = tgetstr("ce", &loc);
+  VS = tgetstr("vs", &loc);
+  CL = tgetstr("cl", &loc);
+  SO = tgetstr("so", &loc);
+  SE = tgetstr("se", &loc);
+  CM = tgetstr("cm", &loc);
+  ymax = tgetnum("li") - 1;
+  screenmax = ymax - 1;
+
+  if (!CE || !SO || !SE || !CL || !AL || !CM) {
+  	printf("Sorry, no mined on this type of terminal\n");
+  	exit(1);
+  }
+}
+#endif /* UNIX */
Index: /trunk/minix/commands/mined/mined2.c
===================================================================
--- /trunk/minix/commands/mined/mined2.c	(revision 9)
+++ /trunk/minix/commands/mined/mined2.c	(revision 9)
@@ -0,0 +1,1724 @@
+/*
+ * Part 2 of the mined editor.
+ */
+
+/*  ========================================================================  *
+ *				Move Commands				      *	
+ *  ========================================================================  */
+
+#include "mined.h"
+#include <string.h>
+
+/*
+ * Move one line up.
+ */
+void UP()
+{
+  if (y == 0) {		/* Top line of screen. Scroll one line */
+  	(void) reverse_scroll();
+  	move_to(x, y);
+  }
+  else			/* Move to previous line */
+  	move_to(x, y - 1);
+}
+
+/*
+ * Move one line down.
+ */
+void DN()
+{
+  if (y == last_y) {	/* Last line of screen. Scroll one line */
+	if (bot_line->next == tail && bot_line->text[0] != '\n') {
+		dummy_line();		/* Create new empty line */
+		DN();
+		return;
+	}
+	else {
+		(void) forward_scroll();
+		move_to(x, y);
+	}
+  }
+  else			/* Move to next line */
+  	move_to(x, y + 1);
+}
+
+/*
+ * Move left one position.
+ */
+void LF()
+{
+  if (x == 0 && get_shift(cur_line->shift_count) == 0) {/* Begin of line */
+	if (cur_line->prev != header) {
+		UP();					/* Move one line up */
+		move_to(LINE_END, y);
+	}
+  }
+  else
+  	move_to(x - 1, y);
+}
+
+/*
+ * Move right one position.
+ */
+void RT()
+{
+  if (*cur_text == '\n') {
+  	if (cur_line->next != tail) {		/* Last char of file */
+		DN();				/* Move one line down */
+		move_to(LINE_START, y);
+	}
+  }
+  else
+  	move_to(x + 1, y);
+}
+
+/*
+ * Move to coordinates [0, 0] on screen.
+ */
+void HIGH()
+{
+  move_to(0, 0);
+}
+
+/*
+ * Move to coordinates [0, YMAX] on screen.
+ */
+void LOW()
+{
+  move_to(0, last_y);
+}
+
+/*
+ * Move to begin of line.
+ */
+void BL()
+{
+  move_to(LINE_START, y);
+}
+
+/*
+ * Move to end of line.
+ */
+void EL()
+{
+  move_to(LINE_END, y);
+}
+
+/*
+ * GOTO() prompts for a linenumber and moves to that line.
+ */
+void GOTO()
+{
+  int number;
+  LINE *line;
+
+  if (get_number("Please enter line number.", &number) == ERRORS)
+  	return;
+
+  if (number <= 0 || (line = proceed(header->next, number - 1)) == tail)
+  	error("Illegal line number: ", num_out((long) number));
+  else
+  	move_to(x, find_y(line));
+}
+
+/*
+ * Scroll forward one page or to eof, whatever comes first. (Bot_line becomes 
+ * top_line of display.) Try to leave the cursor on the same line. If this is
+ * not possible, leave cursor on the line halfway the page.
+ */
+void PD()
+{
+  register int i;
+
+  for (i = 0; i < screenmax; i++)
+  	if (forward_scroll() == ERRORS)
+  		break;			/* EOF reached */
+  if (y - i < 0)				/* Line no longer on screen */
+  	move_to(0, screenmax >> 1);
+  else
+  	move_to(0, y - i);
+}
+
+
+/*
+ * Scroll backwards one page or to top of file, whatever comes first. (Top_line
+ * becomes bot_line of display).  The very bottom line (YMAX) is always blank.
+ * Try to leave the cursor on the same line. If this is not possible, leave
+ * cursor on the line halfway the page.
+ */
+void PU()
+{
+  register int i;
+
+  for (i = 0; i < screenmax; i++)
+  	if (reverse_scroll() == ERRORS)
+  		break;			/* Top of file reached */
+  set_cursor(0, ymax);			/* Erase very bottom line */
+#ifdef UNIX
+  tputs(CE, 0, _putchar);
+#else
+  string_print(blank_line);
+#endif /* UNIX */
+  if (y + i > screenmax)			/* line no longer on screen */
+  	move_to(0, screenmax >> 1);
+  else
+  	move_to(0, y + i);
+}
+
+/*
+ * Go to top of file, scrolling if possible, else redrawing screen.
+ */
+void HO()
+{
+  if (proceed(top_line, -screenmax) == header)
+  	PU();			/* It fits. Let PU do it */
+  else {
+  	reset(header->next, 0);/* Reset top_line, etc. */
+  	RD();			/* Display full page */
+  }
+  move_to(LINE_START, 0);
+}
+
+/*
+ * Go to last line of file, scrolling if possible, else redrawing screen
+ */
+void EF()
+{
+  if (tail->prev->text[0] != '\n')
+	dummy_line();
+  if (proceed(bot_line, screenmax) == tail)
+  	PD();			/* It fits. Let PD do it */
+  else {
+  	reset(proceed(tail->prev, -screenmax), screenmax);
+  	RD();			/* Display full page */
+  }
+  move_to(LINE_START, last_y);
+}
+
+/*
+ * Scroll one line up. Leave the cursor on the same line (if possible).
+ */
+void SU()
+{
+  if (top_line->prev == header)	/* Top of file. Can't scroll */
+  	return;
+
+  (void) reverse_scroll();
+  set_cursor(0, ymax);		/* Erase very bottom line */
+#ifdef UNIX
+  tputs(CE, 0, _putchar);
+#else
+  string_print(blank_line);
+#endif /* UNIX */
+  move_to(x, (y == screenmax) ? screenmax : y + 1);
+}
+
+/*
+ * Scroll one line down. Leave the cursor on the same line (if possible).
+ */
+void SD()
+{
+  if (forward_scroll() != ERRORS) 
+  	move_to(x, (y == 0) ? 0 : y - 1);
+  else
+  	set_cursor(x, y);
+}
+
+/*
+ * Perform a forward scroll. It returns ERRORS if we're at the last line of the
+ * file.
+ */
+int forward_scroll()
+{
+  if (bot_line->next == tail)		/* Last line of file. No dice */
+  	return ERRORS;
+  top_line = top_line->next;
+  bot_line = bot_line->next;
+  cur_line = cur_line->next;
+  set_cursor(0, ymax);
+  line_print(bot_line);
+
+  return FINE;
+}
+
+/*
+ * Perform a backwards scroll. It returns ERRORS if we're at the first line
+ * of the file.
+ */
+int reverse_scroll()
+{
+  if (top_line->prev == header)
+  	return ERRORS;		/* Top of file. Can't scroll */
+
+  if (last_y != screenmax)	/* Reset last_y if necessary */
+  	last_y++;
+  else
+  	bot_line = bot_line->prev;	/* Else adjust bot_line */
+  top_line = top_line->prev;
+  cur_line = cur_line->prev;
+
+/* Perform the scroll */
+  set_cursor(0, 0);
+#ifdef UNIX
+  tputs(AL, 0, _putchar);
+#else
+  string_print(rev_scroll);
+#endif /* UNIX */
+  set_cursor(0, 0);
+  line_print(top_line);
+
+  return FINE;
+}
+
+/*
+ * A word is defined as a number of non-blank characters separated by tabs
+ * spaces or linefeeds.
+ */
+
+/*
+ * MP() moves to the start of the previous word. A word is defined as a
+ * number of non-blank characters separated by tabs spaces or linefeeds.
+ */
+void MP()
+{
+  move_previous_word(NO_DELETE);
+}
+
+void move_previous_word(remove)
+FLAG remove;
+{
+  register char *begin_line;
+  register char *textp;
+  char start_char = *cur_text;
+  char *start_pos = cur_text;
+
+/* Fist check if we're at the beginning of line. */
+  if (cur_text == cur_line->text) {
+  	if (cur_line->prev == header)
+  		return;
+  	start_char = '\0';
+  }
+
+  LF();
+
+  begin_line = cur_line->text;
+  textp = cur_text;
+
+/* Check if we're in the middle of a word. */
+  if (!alpha(*textp) || !alpha(start_char)) {
+  	while (textp != begin_line && (white_space(*textp) || *textp == '\n'))
+  		textp--;
+  }
+
+/* Now we're at the end of previous word. Skip non-blanks until a blank comes */
+  while (textp != begin_line && alpha(*textp))
+  	textp--;
+
+/* Go to the next char if we're not at the beginning of the line */
+  if (textp != begin_line && *textp != '\n')
+  	textp++;
+
+/* Find the x-coordinate of this address, and move to it */
+  move_address(textp);
+  if (remove == DELETE)
+  	delete(cur_line, textp, cur_line, start_pos);
+}
+
+/*
+ * MN() moves to the start of the next word. A word is defined as a number of
+ * non-blank characters separated by tabs spaces or linefeeds. Always keep in
+ * mind that the pointer shouldn't pass the '\n'.
+ */
+void MN()
+{
+  move_next_word(NO_DELETE);
+}
+
+void move_next_word(remove)
+FLAG remove;
+{
+  register char *textp = cur_text;
+
+/* Move to the end of the current word. */
+  while (*textp != '\n' && alpha(*textp))
+  	textp++;
+
+/* Skip all white spaces */
+  while (*textp != '\n' && white_space(*textp))
+  	textp++;
+/* If we're deleting. delete the text in between */
+  if (remove == DELETE) {
+  	delete(cur_line, cur_text, cur_line, textp);
+  	return;
+  }
+
+/* If we're at end of line. move to the first word on the next line. */
+  if (*textp == '\n' && cur_line->next != tail) {
+  	DN();
+  	move_to(LINE_START, y);
+  	textp = cur_text;
+  	while (*textp != '\n' && white_space(*textp))
+  		textp++;
+  }
+  move_address(textp);
+}
+
+/*  ========================================================================  *
+ *				Modify Commands				      *
+ *  ========================================================================  */
+
+/*
+ * DCC deletes the character under the cursor.  If this character is a '\n' the
+ * current line is joined with the next one.
+ * If this character is the only character of the line, the current line will
+ * be deleted.
+ */
+void DCC()
+{
+  if (*cur_text == '\n')
+  	delete(cur_line,cur_text, cur_line->next,cur_line->next->text);
+  else
+  	delete(cur_line, cur_text, cur_line, cur_text + 1);
+}
+
+/*
+ * DPC deletes the character on the left side of the cursor.  If the cursor is
+ * at the beginning of the line, the last character if the previous line is
+ * deleted. 
+ */
+void DPC()
+{
+  if (x == 0 && cur_line->prev == header)
+  	return;			/* Top of file */
+  
+  LF();				/* Move one left */
+  DCC();				/* Delete character under cursor */
+}
+
+/*
+ * DLN deletes all characters until the end of the line. If the current
+ * character is a '\n', then delete that char.
+ */
+void DLN()
+{
+  if (*cur_text == '\n')
+  	DCC();
+  else
+  	delete(cur_line, cur_text, cur_line, cur_text + length_of(cur_text) -1);
+}
+
+/*
+ * DNW() deletes the next word (as described in MN())
+ */
+void DNW()
+{
+  if (*cur_text == '\n')
+  	DCC();
+  else
+  	move_next_word(DELETE);
+}
+
+/*
+ * DPW() deletes the next word (as described in MP())
+ */
+void DPW()
+{
+  if (cur_text == cur_line->text)
+  	DPC();
+  else
+  	move_previous_word(DELETE);
+}
+
+/*
+ * Insert character `character' at current location.
+ */
+void S(character)
+register char character;
+{
+  static char buffer[2];
+
+  buffer[0] = character;
+/* Insert the character */
+  if (insert(cur_line, cur_text, buffer) == ERRORS)
+  	return;
+
+/* Fix screen */
+  if (character == '\n') {
+  	set_cursor(0, y);
+  	if (y == screenmax) {		/* Can't use display */
+  		line_print(cur_line);
+  		(void) forward_scroll();
+  	}
+  	else {
+  		reset(top_line, y);	/* Reset pointers */
+  		display(0, y, cur_line, last_y - y);
+  	}
+  	move_to(0, (y == screenmax) ? y : y + 1);
+  }
+  else if (x + 1 == XBREAK)/* If line must be shifted, just call move_to*/
+  	move_to(x + 1, y);
+  else {			 /* else display rest of line */
+  	put_line(cur_line, x, FALSE);
+  	move_to(x + 1, y);
+  }
+}
+
+/*
+ * CTL inserts a control-char at the current location. A message that this
+ * function is called is displayed at the status line.
+ */
+void CTL()
+{
+  register char ctrl;
+
+  status_line("Enter control character.", NIL_PTR);
+  if ((ctrl = getchar()) >= '\01' && ctrl <= '\037') {
+  	S(ctrl);		/* Insert the char */
+	clear_status();
+  }
+  else
+	error ("Unknown control character", NIL_PTR);
+}
+
+/*
+ * LIB insert a line at the current position and moves back to the end of
+ * the previous line.
+ */
+void LIB()
+{
+  S('\n');	  		/* Insert the line */
+  UP();				/* Move one line up */
+  move_to(LINE_END, y);		/* Move to end of this line */
+}
+
+/*
+ * Line_insert() inserts a new line with text pointed to by `string'.
+ * It returns the address of the new line.
+ */
+LINE *line_insert(line, string, len)
+register LINE *line;
+char *string;
+int len;
+{
+  register LINE *new_line;
+
+/* Allocate space for LINE structure and text */
+  new_line = install_line(string, len);
+
+/* Install the line into the double linked list */
+  new_line->prev = line;
+  new_line->next = line->next;
+  line->next = new_line;
+  new_line->next->prev = new_line;
+
+/* Increment nlines */
+  nlines++;
+
+  return new_line;
+}
+
+/*
+ * Insert() insert the string `string' at the given line and location.
+ */
+int insert(line, location, string)
+register LINE *line;
+char *location, *string;
+{
+  register char *bufp = text_buffer;	/* Buffer for building line */
+  register char *textp = line->text;
+
+  if (length_of(textp) + length_of(string) >= MAX_CHARS) {
+  	error("Line too long", NIL_PTR);
+  	return ERRORS;
+  }
+
+  modified = TRUE;			/* File has been modified */
+
+/* Copy part of line until `location' has been reached */
+  while (textp != location)
+  	*bufp++ = *textp++;
+  
+/* Insert string at this location */
+  while (*string != '\0')
+  	*bufp++ = *string++;
+  *bufp = '\0';
+  
+  if (*(string - 1) == '\n')		/* Insert a new line */
+  	(void) line_insert(line, location, length_of(location));
+  else					/* Append last part of line */
+  	copy_string(bufp, location);
+
+/* Install the new text in this line */
+  free_space(line->text);
+  line->text = alloc(length_of(text_buffer) + 1);
+  copy_string(line->text, text_buffer);
+
+  return FINE;
+}
+
+/*
+ * Line_delete() deletes the argument line out of the line list. The pointer to
+ * the next line is returned.
+ */
+LINE *line_delete(line)
+register LINE *line;
+{
+  register LINE *next_line = line->next;
+
+/* Delete the line */
+  line->prev->next = line->next;
+  line->next->prev = line->prev;
+
+/* Free allocated space */
+  free_space(line->text);
+  free_space((char*)line);
+
+/* Decrement nlines */
+  nlines--;
+
+  return next_line;
+}
+
+/*
+ * Delete() deletes all the characters (including newlines) between the
+ * startposition and endposition and fixes the screen accordingly. It
+ * returns the number of lines deleted.
+ */
+void delete(start_line, start_textp, end_line, end_textp)
+register LINE *start_line;
+LINE *end_line;
+char *start_textp, *end_textp;
+{
+  register char *textp = start_line->text;
+  register char *bufp = text_buffer;	/* Storage for new line->text */
+  LINE *line, *stop;
+  int line_cnt = 0;			/* Nr of lines deleted */
+  int count = 0;
+  int shift = 0;				/* Used in shift calculation */
+  int nx = x;
+
+  modified = TRUE;			/* File has been modified */
+
+/* Set up new line. Copy first part of start line until start_position. */
+  while (textp < start_textp) {
+  	*bufp++ = *textp++;
+  	count++;
+  }
+
+/* Check if line doesn't exceed MAX_CHARS */
+  if (count + length_of(end_textp) >= MAX_CHARS) {
+  	error("Line too long", NIL_PTR);
+  	return;
+  }
+
+/* Copy last part of end_line if end_line is not tail */
+  copy_string(bufp, (end_textp != NIL_PTR) ? end_textp : "\n");
+
+/* Delete all lines between start and end_position (including end_line) */
+  line = start_line->next;
+  stop = end_line->next;
+  while (line != stop && line != tail) {
+  	line = line_delete(line);
+  	line_cnt++;
+  }
+
+/* Check if last line of file should be deleted */
+  if (end_textp == NIL_PTR && length_of(start_line->text) == 1 && nlines > 1) {
+  	start_line = start_line->prev;
+  	(void) line_delete(start_line->next);
+  	line_cnt++;
+  }
+  else {	/* Install new text */
+  	free_space(start_line->text);
+  	start_line->text = alloc(length_of(text_buffer) + 1);
+  	copy_string(start_line->text, text_buffer);
+  }
+
+/* Fix screen. First check if line is shifted. Perhaps we should shift it back*/
+  if (get_shift(start_line->shift_count)) {
+  	shift = (XBREAK - count_chars(start_line)) / SHIFT_SIZE;
+  	if (shift > 0) {		/* Shift line `shift' back */
+  		if (shift >= get_shift(start_line->shift_count))
+  			start_line->shift_count = 0;
+  		else
+  			start_line->shift_count -= shift;
+  		nx += shift * SHIFT_SIZE;/* Reset x value */
+  	}
+  }
+
+  if (line_cnt == 0) {		    /* Check if only one line changed */
+  	if (shift > 0) {	    /* Reprint whole line */
+  		set_cursor(0, y);
+  		line_print(start_line);
+  	}
+  	else {			    /* Just display last part of line */
+  		set_cursor(x, y);
+  		put_line(start_line, x, TRUE);
+  	}
+  	move_to(nx, y);	   /* Reset cur_text */
+  	return;
+  }
+
+  shift = last_y;	   /* Save value */
+  reset(top_line, y);
+  display(0, y, start_line, shift - y);
+  move_to((line_cnt == 1) ? nx : 0, y);
+}
+
+/*  ========================================================================  *
+ *				Yank Commands				      *	
+ *  ========================================================================  */
+
+LINE *mark_line;			/* For marking position. */
+char *mark_text;
+int lines_saved;			/* Nr of lines in buffer */
+
+/*
+ * PT() inserts the buffer at the current location.
+ */
+void PT()
+{
+  register int fd;		/* File descriptor for buffer */
+
+  if ((fd = scratch_file(READ)) == ERRORS)
+  	error("Buffer is empty.", NIL_PTR);
+  else {
+  	file_insert(fd, FALSE);/* Insert the buffer */
+  	(void) close(fd);
+  }
+}
+
+/*
+ * IF() prompt for a filename and inserts the file at the current location 
+ * in the file.
+ */
+void IF()
+{
+  register int fd;		/* File descriptor of file */
+  char name[LINE_LEN];		/* Buffer for file name */
+
+/* Get the file name */
+  if (get_file("Get and insert file:", name) != FINE)
+  	return;
+  
+  if ((fd = open(name, 0)) < 0)
+  	error("Cannot open ", name);
+  else {
+  	file_insert(fd, TRUE);	/* Insert the file */
+  	(void) close(fd);
+  }
+}
+
+/*
+ * File_insert() inserts a an opened file (as given by filedescriptor fd)
+ * at the current location.
+ */
+void file_insert(fd, old_pos)
+int fd;
+FLAG old_pos;
+{
+  char line_buffer[MAX_CHARS];		/* Buffer for next line */
+  register LINE *line = cur_line;
+  register int line_count = nlines;	/* Nr of lines inserted */
+  LINE *page = cur_line;
+  int ret = ERRORS;
+  
+/* Get the first piece of text (might be ended with a '\n') from fd */
+  if (get_line(fd, line_buffer) == ERRORS)
+  	return;				/* Empty file */
+
+/* Insert this text at the current location. */
+  if (insert(line, cur_text, line_buffer) == ERRORS)
+  	return;
+
+/* Repeat getting lines (and inserting lines) until EOF is reached */
+  while ((ret = get_line(fd, line_buffer)) != ERRORS && ret != NO_LINE)
+  	line = line_insert(line, line_buffer, ret);
+  
+  if (ret == NO_LINE) {		/* Last line read not ended by a '\n' */
+  	line = line->next;
+  	(void) insert(line, line->text, line_buffer);
+  }
+
+/* Calculate nr of lines added */
+  line_count = nlines - line_count;
+
+/* Fix the screen */
+  if (line_count == 0) {		/* Only one line changed */
+  	set_cursor(0, y);
+  	line_print(line);
+  	move_to((old_pos == TRUE) ? x : x + length_of(line_buffer), y);
+  }
+  else {				/* Several lines changed */
+  	reset(top_line, y);	/* Reset pointers */
+  	while (page != line && page != bot_line->next)
+  		page = page->next;
+  	if (page != bot_line->next || old_pos == TRUE)
+  		display(0, y, cur_line, screenmax - y);
+  	if (old_pos == TRUE)
+  		move_to(x, y);
+  	else if (ret == NO_LINE)
+		move_to(length_of(line_buffer), find_y(line));
+	else 
+		move_to(0, find_y(line->next));
+  }
+
+/* If nr of added line >= REPORT, print the count */
+  if (line_count >= REPORT)
+  	status_line(num_out((long) line_count), " lines added.");
+}
+
+/*
+ * WB() writes the buffer (yank_file) into another file, which
+ * is prompted for.
+ */
+void WB()
+{
+  register int new_fd;		/* Filedescriptor to copy file */
+  int yank_fd;			/* Filedescriptor to buffer */
+  register int cnt;		/* Count check for read/write */
+  int ret = 0;			/* Error check for write */
+  char file[LINE_LEN];		/* Output file */
+  
+/* Checkout the buffer */
+  if ((yank_fd = scratch_file(READ)) == ERRORS) {
+  	error("Buffer is empty.", NIL_PTR);
+  	return;
+  }
+
+/* Get file name */
+  if (get_file("Write buffer to file:", file) != FINE)
+  	return;
+  
+/* Creat the new file */
+  if ((new_fd = creat(file, 0644)) < 0) {
+  	error("Cannot create ", file);
+  	return;
+  }
+
+  status_line("Writing ", file);
+  
+/* Copy buffer into file */
+  while ((cnt = read(yank_fd, text_buffer, sizeof(text_buffer))) > 0)
+  	if (write(new_fd, text_buffer, cnt) != cnt) {
+  		bad_write(new_fd);
+  		ret = ERRORS;
+  		break;
+  	}
+
+/* Clean up open files and status_line */
+  (void) close(new_fd);
+  (void) close(yank_fd);
+
+  if (ret != ERRORS)			/* Bad write */
+  	file_status("Wrote", chars_saved, file, lines_saved, TRUE, FALSE);
+}
+
+/*
+ * MA sets mark_line (mark_text) to the current line (text pointer). 
+ */
+void MA()
+{
+  mark_line = cur_line;
+  mark_text = cur_text;
+  status_line("Mark set", NIL_PTR);
+}
+
+/*
+ * YA() puts the text between the marked position and the current
+ * in the buffer.
+ */
+void YA()
+{
+  set_up(NO_DELETE);
+}
+
+/*
+ * DT() is essentially the same as YA(), but in DT() the text is deleted.
+ */
+void DT()
+{
+  set_up(DELETE);
+}
+
+/*
+ * Set_up is an interface to the actual yank. It calls checkmark () to check
+ * if the marked position is still valid. If it is, yank is called with the
+ * arguments in the right order.
+ */
+void set_up(remove)
+FLAG remove;				/* DELETE if text should be deleted */
+{
+  switch (checkmark()) {
+  	case NOT_VALID :
+  		error("Mark not set.", NIL_PTR);
+  		return;
+  	case SMALLER :
+  		yank(mark_line, mark_text, cur_line, cur_text, remove);
+  		break;
+  	case BIGGER :
+  		yank(cur_line, cur_text, mark_line, mark_text, remove);
+  		break;
+  	case SAME :		/* Ignore stupid behaviour */
+  		yank_status = EMPTY;
+  		chars_saved = 0L;
+  		status_line("0 characters saved in buffer.", NIL_PTR);
+  		break;
+  }
+}
+
+/*
+ * Check_mark() checks if mark_line and mark_text are still valid pointers. If
+ * they are it returns SMALLER if the marked position is before the current,
+ * BIGGER if it isn't or SAME if somebody didn't get the point.
+ * NOT_VALID is returned when mark_line and/or mark_text are no longer valid.
+ * Legal() checks if mark_text is valid on the mark_line.
+ */
+FLAG checkmark()
+{
+  register LINE *line;
+  FLAG cur_seen = FALSE;
+
+/* Special case: check is mark_line and cur_line are the same. */
+  if (mark_line == cur_line) {
+  	if (mark_text == cur_text)	/* Even same place */
+  		return SAME;
+  	if (legal() == ERRORS)		/* mark_text out of range */
+  		return NOT_VALID;
+  	return (mark_text < cur_text) ? SMALLER : BIGGER;
+  }
+
+/* Start looking for mark_line in the line structure */
+  for (line = header->next; line != tail; line = line->next) {
+  	if (line == cur_line)
+  		cur_seen = TRUE;
+  	else if (line == mark_line)
+  		break;
+  }
+
+/* If we found mark_line (line != tail) check for legality of mark_text */
+  if (line == tail || legal() == ERRORS)
+  	return NOT_VALID;
+
+/* cur_seen is TRUE if cur_line is before mark_line */
+  return (cur_seen == TRUE) ? BIGGER : SMALLER;
+}
+
+/*
+ * Legal() checks if mark_text is still a valid pointer.
+ */
+int legal()
+{
+  register char *textp = mark_line->text;
+
+/* Locate mark_text on mark_line */
+  while (textp != mark_text && *textp++ != '\0')
+  	;
+  return (*textp == '\0') ? ERRORS : FINE;
+}
+
+/*
+ * Yank puts all the text between start_position and end_position into
+ * the buffer.
+ * The caller must check that the arguments to yank() are valid. (E.g. in
+ * the right order)
+ */
+void yank(start_line, start_textp, end_line, end_textp, remove)
+LINE *start_line, *end_line;
+char *start_textp, *end_textp;
+FLAG remove;				/* DELETE if text should be deleted */
+{
+  register LINE *line = start_line;
+  register char *textp = start_textp;
+  int fd;
+
+/* Creat file to hold buffer */
+  if ((fd = scratch_file(WRITE)) == ERRORS)
+  	return;
+  
+  chars_saved = 0L;
+  lines_saved = 0;
+  status_line("Saving text.", NIL_PTR);
+
+/* Keep writing chars until the end_location is reached. */
+  while (textp != end_textp) {
+  	if (write_char(fd, *textp) == ERRORS) {
+  		(void) close(fd);
+  		return;
+  	}
+  	if (*textp++ == '\n') {	/* Move to the next line */
+  		line = line->next;
+  		textp = line->text;
+  		lines_saved++;
+  	}
+  	chars_saved++;
+  }
+
+/* Flush the I/O buffer and close file */
+  if (flush_buffer(fd) == ERRORS) {
+  	(void) close(fd);
+  	return;
+  }
+  (void) close(fd);
+  yank_status = VALID;
+
+/*
+ * Check if the text should be deleted as well. If it should, the following
+ * hack is used to save a lot of code. First move back to the start_position.
+ * (This might be the location we're on now!) and them delete the text.
+ * It might be a bit confusing the first time somebody uses it.
+ * Delete() will fix the screen.
+ */
+  if (remove == DELETE) {
+  	move_to(find_x(start_line, start_textp), find_y(start_line));
+  	delete(start_line, start_textp, end_line, end_textp);
+  }
+
+  status_line(num_out(chars_saved), " characters saved in buffer.");
+}
+
+/*
+ * Scratch_file() creates a uniq file in /usr/tmp. If the file couldn't
+ * be created other combinations of files are tried until a maximum
+ * of MAXTRAILS times. After MAXTRAILS times, an error message is given
+ * and ERRORS is returned.
+ */
+
+#define MAXTRAILS	26
+
+int scratch_file(mode)
+FLAG mode;				/* Can be READ or WRITE permission */
+{
+  static int trials = 0;		/* Keep track of trails */
+  register char *y_ptr, *n_ptr;
+  int fd;				/* Filedescriptor to buffer */
+
+/* If yank_status == NOT_VALID, scratch_file is called for the first time */
+  if (yank_status == NOT_VALID && mode == WRITE) { /* Create new file */
+  	/* Generate file name. */
+	y_ptr = &yank_file[11];
+	n_ptr = num_out((long) getpid());
+	while ((*y_ptr = *n_ptr++) != '\0')
+		y_ptr++;
+	*y_ptr++ = 'a' + trials;
+	*y_ptr = '\0';
+  	/* Check file existence */
+  	if (access(yank_file, 0) == 0 || (fd = creat(yank_file, 0644)) < 0) {
+  		if (trials++ >= MAXTRAILS) {
+  			error("Unable to creat scratchfile.", NIL_PTR);
+  			return ERRORS;
+  		}
+  		else
+  			return scratch_file(mode);/* Have another go */
+  	}
+  }
+  else if ((mode == READ && (fd = open(yank_file, 0)) < 0) ||
+			(mode == WRITE && (fd = creat(yank_file, 0644)) < 0)) {
+  	yank_status = NOT_VALID;
+  	return ERRORS;
+  }
+
+  clear_buffer();
+  return fd;
+}
+
+/*  ========================================================================  *
+ *				Search Routines				      *	
+ *  ========================================================================  */
+
+/*
+ * A regular expression consists of a sequence of:
+ * 	1. A normal character matching that character.
+ * 	2. A . matching any character.
+ * 	3. A ^ matching the begin of a line.
+ * 	4. A $ (as last character of the pattern) mathing the end of a line.
+ * 	5. A \<character> matching <character>.
+ * 	6. A number of characters enclosed in [] pairs matching any of these
+ * 	   characters. A list of characters can be indicated by a '-'. So
+ * 	   [a-z] matches any letter of the alphabet. If the first character
+ * 	   after the '[' is a '^' then the set is negated (matching none of
+ * 	   the characters). 
+ * 	   A ']', '^' or '-' can be escaped by putting a '\' in front of it.
+ * 	7. If one of the expressions as described in 1-6 is followed by a
+ * 	   '*' than that expressions matches a sequence of 0 or more of
+ * 	   that expression.
+ */
+
+char typed_expression[LINE_LEN];	/* Holds previous expr. */
+
+/*
+ * SF searches forward for an expression.
+ */
+void SF()
+{
+  search("Search forward:", FORWARD);
+}
+
+/*
+ * SF searches backwards for an expression.
+ */
+void SR()
+{
+  search("Search reverse:", REVERSE);
+}
+
+/*
+ * Get_expression() prompts for an expression. If just a return is typed, the
+ * old expression is used. If the expression changed, compile() is called and
+ * the returning REGEX structure is returned. It returns NIL_REG upon error.
+ * The save flag indicates whether the expression should be appended at the
+ * message pointer.
+ */
+REGEX *get_expression(message)
+char *message;
+{
+  static REGEX program;			/* Program of expression */
+  char exp_buf[LINE_LEN];			/* Buffer for new expr. */
+
+  if (get_string(message, exp_buf, FALSE) == ERRORS)
+  	return NIL_REG;
+  
+  if (exp_buf[0] == '\0' && typed_expression[0] == '\0') {
+  	error("No previous expression.", NIL_PTR);
+  	return NIL_REG;
+  }
+
+  if (exp_buf[0] != '\0') {		/* A new expr. is typed */
+  	copy_string(typed_expression, exp_buf);/* Save expr. */
+  	compile(exp_buf, &program);	/* Compile new expression */
+  }
+
+  if (program.status == REG_ERROR) {	/* Error during compiling */
+  	error(program.result.err_mess, NIL_PTR);
+  	return NIL_REG;
+  }
+  return &program;
+}
+
+/*
+ * GR() a replaces all matches from the current position until the end
+ * of the file.
+ */
+void GR()
+{
+  change("Global replace:", VALID);
+}
+
+/*
+ * LR() replaces all matches on the current line.
+ */
+void LR()
+{
+  change("Line replace:", NOT_VALID);
+}
+
+/*
+ * Change() prompts for an expression and a substitution pattern and changes
+ * all matches of the expression into the substitution. change() start looking
+ * for expressions at the current line and continues until the end of the file
+ * if the FLAG file is VALID.
+ */
+void change(message, file)
+char *message;				/* Message to prompt for expression */
+FLAG file;
+{
+  char mess_buf[LINE_LEN];	/* Buffer to hold message */
+  char replacement[LINE_LEN];	/* Buffer to hold subst. pattern */
+  REGEX *program;			/* Program resulting from compilation */
+  register LINE *line = cur_line;
+  register char *textp;
+  long lines = 0L;		/* Nr of lines on which subs occurred */
+  long subs = 0L;			/* Nr of subs made */
+  int page = y;			/* Index to check if line is on screen*/
+
+/* Save message and get expression */
+  copy_string(mess_buf, message);
+  if ((program = get_expression(mess_buf)) == NIL_REG)
+  	return;
+  
+/* Get substitution pattern */
+  build_string(mess_buf, "%s %s by:", mess_buf, typed_expression);
+  if (get_string(mess_buf, replacement, FALSE) == ERRORS)
+  	return;
+  
+  set_cursor(0, ymax);
+  flush();
+/* Substitute until end of file */
+  do {
+  	if (line_check(program, line->text, FORWARD)) {
+  		lines++;
+  		/* Repeat sub. on this line as long as we find a match*/
+  		do {
+  			subs++;	/* Increment subs */
+  			if ((textp = substitute(line, program,replacement))
+								     == NIL_PTR)
+  				return;	/* Line too long */
+  		} while ((program->status & BEGIN_LINE) != BEGIN_LINE &&
+			 (program->status & END_LINE) != END_LINE &&
+					  line_check(program, textp, FORWARD));
+  		/* Check to see if we can print the result */
+  		if (page <= screenmax) {
+  			set_cursor(0, page);
+  			line_print(line);
+  		}
+  	}
+  	if (page <= screenmax)
+  		page++;
+  	line = line->next;
+  } while (line != tail && file == VALID && quit == FALSE);
+
+  copy_string(mess_buf, (quit == TRUE) ? "(Aborted) " : "");
+/* Fix the status line */
+  if (subs == 0L && quit == FALSE)
+  	error("Pattern not found.", NIL_PTR);
+  else if (lines >= REPORT || quit == TRUE) {
+  	build_string(mess_buf, "%s %D substitutions on %D lines.", mess_buf,
+								   subs, lines);
+  	status_line(mess_buf, NIL_PTR);
+  }
+  else if (file == NOT_VALID && subs >= REPORT)
+  	status_line(num_out(subs), " substitutions.");
+  else
+  	clear_status();
+  move_to (x, y);
+}
+
+/*
+ * Substitute() replaces the match on this line by the substitute pattern
+ * as indicated by the program. Every '&' in the replacement is replaced by 
+ * the original match. A \ in the replacement escapes the next character.
+ */
+char *substitute(line, program, replacement)
+LINE *line;
+REGEX *program;
+char *replacement;		/* Contains replacement pattern */
+{
+  register char *textp = text_buffer;
+  register char *subp = replacement;
+  char *linep = line->text;
+  char *amp;
+
+  modified = TRUE;
+
+/* Copy part of line until the beginning of the match */
+  while (linep != program->start_ptr)
+  	*textp++ = *linep++;
+  
+/*
+ * Replace the match by the substitution pattern. Each occurrence of '&' is
+ * replaced by the original match. A \ escapes the next character.
+ */
+  while (*subp != '\0' && textp < &text_buffer[MAX_CHARS]) {
+  	if (*subp == '&') {		/* Replace the original match */
+  		amp = program->start_ptr;
+  		while (amp < program->end_ptr && textp<&text_buffer[MAX_CHARS])
+  			*textp++ = *amp++;
+  		subp++;
+  	}
+  	else {
+  		if (*subp == '\\' && *(subp + 1) != '\0')
+  			subp++;
+  		*textp++ = *subp++;
+  	}
+  }
+
+/* Check for line length not exceeding MAX_CHARS */
+  if (length_of(text_buffer) + length_of(program->end_ptr) >= MAX_CHARS) {
+  	error("Substitution result: line too big", NIL_PTR);
+  	return NIL_PTR;
+  }
+
+/* Append last part of line to the new build line */
+  copy_string(textp, program->end_ptr);
+
+/* Free old line and install new one */
+  free_space(line->text);
+  line->text = alloc(length_of(text_buffer) + 1);
+  copy_string(line->text, text_buffer);
+
+  return(line->text + (textp - text_buffer));
+}
+
+/*
+ * Search() calls get_expression to fetch the expression. If this went well,
+ * the function match() is called which returns the line with the next match.
+ * If this line is the NIL_LINE, it means that a match could not be found.
+ * Find_x() and find_y() display the right page on the screen, and return
+ * the right coordinates for x and y. These coordinates are passed to move_to()
+ */
+void search(message, method)
+char *message;
+FLAG method;
+{
+  register REGEX *program;
+  register LINE *match_line;
+
+/* Get the expression */
+  if ((program = get_expression(message)) == NIL_REG)
+  	return;
+
+  set_cursor(0, ymax);
+  flush();
+/* Find the match */
+  if ((match_line = match(program, cur_text, method)) == NIL_LINE) {
+  	if (quit == TRUE)
+  		status_line("Aborted", NIL_PTR);
+  	else
+  		status_line("Pattern not found.", NIL_PTR);
+  	return;
+  }
+
+  move(0, program->start_ptr, find_y(match_line));
+  clear_status();
+}
+
+/*
+ * find_y() checks if the matched line is on the current page.  If it is, it
+ * returns the new y coordinate, else it displays the correct page with the
+ * matched line in the middle and returns the new y value;
+ */
+int find_y(match_line)
+LINE *match_line;
+{
+  register LINE *line;
+  register int count = 0;
+
+/* Check if match_line is on the same page as currently displayed. */
+  for (line = top_line; line != match_line && line != bot_line->next;
+  						      line = line->next)
+  	count++;
+  if (line != bot_line->next)
+  	return count;
+
+/* Display new page, with match_line in center. */
+  if ((line = proceed(match_line, -(screenmax >> 1))) == header) {
+  /* Can't display in the middle. Make first line of file top_line */
+  	count = 0;
+  	for (line = header->next; line != match_line; line = line->next)
+  		count++;
+  	line = header->next;
+  }
+  else	/* New page is displayed. Set cursor to middle of page */
+  	count = screenmax >> 1;
+
+/* Reset pointers and redraw the screen */
+  reset(line, 0);
+  RD();
+
+  return count;
+}
+
+/* Opcodes for characters */
+#define	NORMAL		0x0200
+#define DOT		0x0400
+#define EOLN		0x0800
+#define STAR		0x1000
+#define BRACKET		0x2000
+#define NEGATE		0x0100
+#define DONE		0x4000
+
+/* Mask for opcodes and characters */
+#define LOW_BYTE	0x00FF
+#define HIGH_BYTE	0xFF00
+
+/* Previous is the contents of the previous address (ptr) points to */
+#define previous(ptr)		(*((ptr) - 1))
+
+/* Buffer to store outcome of compilation */
+int exp_buffer[BLOCK_SIZE];
+
+/* Errors often used */
+char *too_long = "Regular expression too long";
+
+/*
+ * Reg_error() is called by compile() is something went wrong. It set the
+ * status of the structure to error, and assigns the error field of the union.
+ */
+#define reg_error(str)	program->status = REG_ERROR, \
+  					program->result.err_mess = (str)
+/*
+ * Finished() is called when everything went right during compilation. It
+ * allocates space for the expression, and copies the expression buffer into
+ * this field.
+ */
+void finished(program, last_exp)
+register REGEX *program;
+int *last_exp;
+{
+  register int length = (last_exp - exp_buffer) * sizeof(int);
+
+/* Allocate space */
+  program->result.expression = (int *) alloc(length);
+/* Copy expression. (expression consists of ints!) */
+  bcopy(exp_buffer, program->result.expression, length);
+}
+
+/*
+ * Compile compiles the pattern into a more comprehensible form and returns a 
+ * REGEX structure. If something went wrong, the status field of the structure
+ * is set to REG_ERROR and an error message is set into the err_mess field of
+ * the union. If all went well the expression is saved and the expression
+ * pointer is set to the saved (and compiled) expression.
+ */
+void compile(pattern, program)
+register char *pattern;			/* Pointer to pattern */
+REGEX *program;
+{
+  register int *expression = exp_buffer;
+  int *prev_char;			/* Pointer to previous compiled atom */
+  int *acct_field;		/* Pointer to last BRACKET start */
+  FLAG negate;			/* Negate flag for BRACKET */
+  char low_char;			/* Index for chars in BRACKET */
+  char c;
+
+/* Check for begin of line */
+  if (*pattern == '^') {
+  	program->status = BEGIN_LINE;
+  	pattern++;
+  }
+  else {
+  	program->status = 0;
+/* If the first character is a '*' we have to assign it here. */
+  	if (*pattern == '*') {
+  		*expression++ = '*' + NORMAL;
+  		pattern++;
+  	}
+  }
+
+  for (; ;) {
+  	switch (c = *pattern++) {
+  	case '.' :
+  		*expression++ = DOT;
+  		break;
+  	case '$' :
+  		/*
+  		 * Only means EOLN if it is the last char of the pattern
+  		 */
+  		if (*pattern == '\0') {
+  			*expression++ = EOLN | DONE;
+  			program->status |= END_LINE;
+  			finished(program, expression);
+  			return;
+  		}
+  		else
+  			*expression++ = NORMAL + '$';
+  		break;
+  	case '\0' :
+  		*expression++ = DONE;
+  		finished(program, expression);
+  		return;
+  	case '\\' :
+  		/* If last char, it must! mean a normal '\' */
+  		if (*pattern == '\0')
+  			*expression++ = NORMAL + '\\';
+  		else
+  			*expression++ = NORMAL + *pattern++;
+  		break;
+  	case '*' :
+  		/*
+  		 * If the previous expression was a [] find out the
+  		 * begin of the list, and adjust the opcode.
+  		 */
+  		prev_char = expression - 1;
+  		if (*prev_char & BRACKET)
+  			*(expression - (*acct_field & LOW_BYTE))|= STAR;
+  		else
+  			*prev_char |= STAR;
+  		break;
+  	case '[' :
+  		/*
+  		 * First field in expression gives information about
+  		 * the list.
+  		 * The opcode consists of BRACKET and if necessary
+  		 * NEGATE to indicate that the list should be negated
+  		 * and/or STAR to indicate a number of sequence of this 
+  		 * list.
+  		 * The lower byte contains the length of the list.
+  		 */
+  		acct_field = expression++;
+  		if (*pattern == '^') {	/* List must be negated */
+  			pattern++;
+  			negate = TRUE;
+  		}
+  		else
+  			negate = FALSE;
+  		while (*pattern != ']') {
+  			if (*pattern == '\0') {
+  				reg_error("Missing ]");
+  				return;
+  			}
+  			if (*pattern == '\\')
+  				pattern++;
+  			*expression++ = *pattern++;
+  			if (*pattern == '-') {
+  						/* Make list of chars */
+  				low_char = previous(pattern);
+  				pattern++;	/* Skip '-' */
+  				if (low_char++ > *pattern) {
+  					reg_error("Bad range in [a-z]");
+  					return;
+  				}
+  				/* Build list */
+  				while (low_char <= *pattern)
+  					*expression++ = low_char++;
+  				pattern++;
+  			}
+  			if (expression >= &exp_buffer[BLOCK_SIZE]) {
+  				reg_error(too_long);
+  				return;
+  			}
+  		}
+  		pattern++;			/* Skip ']' */
+  		/* Assign length of list in acct field */
+  		if ((*acct_field = (expression - acct_field)) == 1) {
+  			reg_error("Empty []");
+  			return;
+  		}
+  		/* Assign negate and bracket field */
+  		*acct_field |= BRACKET;
+  		if (negate == TRUE)
+  			*acct_field |= NEGATE;
+  		/*
+  		 * Add BRACKET to opcode of last char in field because
+  		 * a '*' may be following the list.
+  		 */
+  		previous(expression) |= BRACKET;
+  		break;
+  	default :
+  		*expression++ = c + NORMAL;
+  	}
+  	if (expression == &exp_buffer[BLOCK_SIZE]) {
+  		reg_error(too_long);
+  		return;
+  	}
+  }
+  /* NOTREACHED */
+}
+
+/*
+ * Match gets as argument the program, pointer to place in current line to 
+ * start from and the method to search for (either FORWARD or REVERSE).
+ * Match() will look through the whole file until a match is found.
+ * NIL_LINE is returned if no match could be found.
+ */
+LINE *match(program, string, method)
+REGEX *program;
+char *string;
+register FLAG method;
+{
+  register LINE *line = cur_line;
+  char old_char;				/* For saving chars */
+
+/* Corrupted program */
+  if (program->status == REG_ERROR)
+  	return NIL_LINE;
+
+/* Check part of text first */
+  if (!(program->status & BEGIN_LINE)) {
+  	if (method == FORWARD) {
+  		if (line_check(program, string + 1, method) == MATCH)
+  			return cur_line;	/* Match found */
+  	}
+  	else if (!(program->status & END_LINE)) {
+  		old_char = *string;	/* Save char and */
+  		*string = '\n';		/* Assign '\n' for line_check */
+  		if (line_check(program, line->text, method) == MATCH) {
+  			*string = old_char; /* Restore char */
+  			return cur_line;    /* Found match */
+  		}
+  		*string = old_char;	/* No match, but restore char */
+  	}
+  }
+
+/* No match in last (or first) part of line. Check out rest of file */
+  do {
+  	line = (method == FORWARD) ? line->next : line->prev;
+  	if (line->text == NIL_PTR)	/* Header/tail */
+  		continue;
+  	if (line_check(program, line->text, method) == MATCH)
+  		return line;
+  } while (line != cur_line && quit == FALSE);
+
+/* No match found. */
+  return NIL_LINE;
+}
+
+/*
+ * Line_check() checks the line (or rather string) for a match. Method
+ * indicates FORWARD or REVERSE search. It scans through the whole string
+ * until a match is found, or the end of the string is reached.
+ */
+int line_check(program, string, method)
+register REGEX *program;
+char *string;
+FLAG method;
+{
+  register char *textp = string;
+
+/* Assign start_ptr field. We might find a match right away! */
+  program->start_ptr = textp;
+
+/* If the match must be anchored, just check the string. */
+  if (program->status & BEGIN_LINE)
+  	return check_string(program, string, NIL_INT);
+  
+  if (method == REVERSE) {
+  	/* First move to the end of the string */
+  	for (textp = string; *textp != '\n'; textp++)
+  		;
+  	/* Start checking string until the begin of the string is met */
+  	while (textp >= string) {
+  		program->start_ptr = textp;
+  		if (check_string(program, textp--, NIL_INT))
+  			return MATCH;
+  	}
+  }
+  else {
+  	/* Move through the string until the end of is found */
+	while (quit == FALSE && *textp != '\0') {
+  		program->start_ptr = textp;
+  		if (check_string(program, textp, NIL_INT))
+  			return MATCH;
+		if (*textp == '\n')
+			break;
+		textp++;
+  	}
+  }
+
+  return NO_MATCH;
+}
+
+/*
+ * Check() checks of a match can be found in the given string. Whenever a STAR
+ * is found during matching, then the begin position of the string is marked
+ * and the maximum number of matches is performed. Then the function star()
+ * is called which starts to finish the match from this position of the string
+ * (and expression). Check() return MATCH for a match, NO_MATCH is the string 
+ * couldn't be matched or REG_ERROR for an illegal opcode in expression.
+ */
+int check_string(program, string, expression)
+REGEX *program;
+register char *string;
+int *expression;
+{
+  register int opcode;		/* Holds opcode of next expr. atom */
+  char c;				/* Char that must be matched */
+  char *mark;			/* For marking position */
+  int star_fl;			/* A star has been born */
+
+  if (expression == NIL_INT)
+  	expression = program->result.expression;
+
+/* Loop until end of string or end of expression */
+  while (quit == FALSE && !(*expression & DONE) &&
+					   *string != '\0' && *string != '\n') {
+  	c = *expression & LOW_BYTE;	  /* Extract match char */
+  	opcode = *expression & HIGH_BYTE; /* Extract opcode */
+  	if (star_fl = (opcode & STAR)) {  /* Check star occurrence */
+  		opcode &= ~STAR;	  /* Strip opcode */
+  		mark = string;		  /* Mark current position */
+  	}
+  	expression++;		/* Increment expr. */
+  	switch (opcode) {
+  	case NORMAL :
+  		if (star_fl)
+  			while (*string++ == c)	/* Skip all matches */
+  				;
+  		else if (*string++ != c)
+  			return NO_MATCH;
+  		break;
+  	case DOT :
+  		string++;
+  		if (star_fl)			/* Skip to eoln */
+  			while (*string != '\0' && *string++ != '\n')
+  				;
+  		break;
+  	case NEGATE | BRACKET:
+  	case BRACKET :
+  		if (star_fl)
+  			while (in_list(expression, *string++, c, opcode)
+								       == MATCH)
+  				;
+  		else if (in_list(expression, *string++, c, opcode) == NO_MATCH)
+  			return NO_MATCH;
+  		expression += c - 1;	/* Add length of list */
+  		break;
+  	default :
+  		panic("Corrupted program in check_string()");
+  	}
+  	if (star_fl) 
+  		return star(program, mark, string, expression);
+  }
+  if (*expression & DONE) {
+  	program->end_ptr = string;	/* Match ends here */
+  	/*
+  	 * We might have found a match. The last thing to do is check
+  	 * whether a '$' was given at the end of the expression, or
+  	 * the match was found on a null string. (E.g. [a-z]* always
+  	 * matches) unless a ^ or $ was included in the pattern.
+  	 */
+  	if ((*expression & EOLN) && *string != '\n' && *string != '\0')
+  		return NO_MATCH;
+	if (string == program->start_ptr && !(program->status & BEGIN_LINE)
+					 && !(*expression & EOLN))
+  		return NO_MATCH;
+  	return MATCH;
+  }
+  return NO_MATCH;
+}
+
+/*
+ * Star() calls check_string() to find out the longest match possible.
+ * It searches backwards until the (in check_string()) marked position
+ * is reached, or a match is found.
+ */
+int star(program, end_position, string, expression)
+REGEX *program;
+register char *end_position;
+register char *string;
+int *expression;
+{
+  do {
+  	string--;
+  	if (check_string(program, string, expression))
+  		return MATCH;
+  } while (string != end_position);
+
+  return NO_MATCH;
+}
+
+/*
+ * In_list() checks if the given character is in the list of []. If it is
+ * it returns MATCH. if it isn't it returns NO_MATCH. These returns values
+ * are reversed when the NEGATE field in the opcode is present.
+ */
+int in_list(list, c, list_length, opcode)
+register int *list;
+char c;
+register int list_length;
+int opcode;
+{
+  if (c == '\0' || c == '\n')	/* End of string, never matches */
+  	return NO_MATCH;
+  while (list_length-- > 1) {	/* > 1, don't check acct_field */
+  	if ((*list & LOW_BYTE) == c)
+  		return (opcode & NEGATE) ? NO_MATCH : MATCH;
+  	list++;
+  }
+  return (opcode & NEGATE) ? MATCH : NO_MATCH;
+}
+
+/*
+ * Dummy_line() adds an empty line at the end of the file. This is sometimes
+ * useful in combination with the EF and DN command in combination with the
+ * Yank command set.
+ */
+void dummy_line()
+{
+	(void) line_insert(tail->prev, "\n", 1);
+	tail->prev->shift_count = DUMMY;
+	if (last_y != screenmax) {
+		last_y++;
+		bot_line = bot_line->next;
+	}
+}
Index: /trunk/minix/commands/patch/EXTERN.h
===================================================================
--- /trunk/minix/commands/patch/EXTERN.h	(revision 9)
+++ /trunk/minix/commands/patch/EXTERN.h	(revision 9)
@@ -0,0 +1,21 @@
+/* $Header: /cvsup/minix/src/commands/patch/EXTERN.h,v 1.1.1.1 2005/04/21 14:55:10 beng Exp $
+ *
+ * $Log: EXTERN.h,v $
+ * Revision 1.1.1.1  2005/04/21 14:55:10  beng
+ * Initial import of pre-3.0.1
+ *
+ * Revision 1.1.1.1  2005/04/20 13:33:18  beng
+ * Initial import of minix 2.0.4
+ *
+ * Revision 2.0  86/09/17  15:35:37  lwall
+ * Baseline for netwide release.
+ * 
+ */
+
+#undef EXT
+#define EXT extern
+
+#undef INIT
+#define INIT(x)
+
+#undef DOINIT
Index: /trunk/minix/commands/patch/INTERN.h
===================================================================
--- /trunk/minix/commands/patch/INTERN.h	(revision 9)
+++ /trunk/minix/commands/patch/INTERN.h	(revision 9)
@@ -0,0 +1,21 @@
+/* $Header: /cvsup/minix/src/commands/patch/INTERN.h,v 1.1.1.1 2005/04/21 14:55:10 beng Exp $
+ *
+ * $Log: INTERN.h,v $
+ * Revision 1.1.1.1  2005/04/21 14:55:10  beng
+ * Initial import of pre-3.0.1
+ *
+ * Revision 1.1.1.1  2005/04/20 13:33:18  beng
+ * Initial import of minix 2.0.4
+ *
+ * Revision 2.0  86/09/17  15:35:58  lwall
+ * Baseline for netwide release.
+ * 
+ */
+
+#undef EXT
+#define EXT
+
+#undef INIT
+#define INIT(x) = x
+
+#define DOINIT
Index: /trunk/minix/commands/patch/Makefile
===================================================================
--- /trunk/minix/commands/patch/Makefile	(revision 9)
+++ /trunk/minix/commands/patch/Makefile	(revision 9)
@@ -0,0 +1,28 @@
+# Makefile for patch
+
+CFLAGS= -O -DVOIDSIG -wo -D_MINIX -D_POSIX_SOURCE -DSMALL
+
+CC = exec cc
+
+OBJ = patch.o pch.o inp.o util.o version.o
+
+all:	patch
+
+patch: $(OBJ)
+	cc -i -o patch $(OBJ)
+	install -S 1M patch
+
+install:	/usr/bin/patch
+
+/usr/bin/patch:	patch
+	install -cs -o bin patch $@
+
+patch.o:	config.h common.h patch.c inp.h pch.h util.h version.h
+pch.o:		config.h common.h pch.c pch.h util.h
+inp.o:		config.h common.h inp.c inp.h util.h
+util.o:		config.h common.h util.c util.h
+version.o:	config.h common.h version.c version.h patchlevel.h util.h
+
+
+clean:	
+	rm -f *.bak *.o *.s core patch
Index: /trunk/minix/commands/patch/build
===================================================================
--- /trunk/minix/commands/patch/build	(revision 9)
+++ /trunk/minix/commands/patch/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/patch/common.h
===================================================================
--- /trunk/minix/commands/patch/common.h	(revision 9)
+++ /trunk/minix/commands/patch/common.h	(revision 9)
@@ -0,0 +1,162 @@
+/* $Header: /cvsup/minix/src/commands/patch/common.h,v 1.1.1.1 2005/04/21 14:55:10 beng Exp $
+ *
+ * $Log: common.h,v $
+ * Revision 1.1.1.1  2005/04/21 14:55:10  beng
+ * Initial import of pre-3.0.1
+ *
+ * Revision 1.1.1.1  2005/04/20 13:33:18  beng
+ * Initial import of minix 2.0.4
+ *
+ * Revision 2.0.1.2  88/06/22  20:44:53  lwall
+ * patch12: sprintf was declared wrong
+ * 
+ * Revision 2.0.1.1  88/06/03  15:01:56  lwall
+ * patch10: support for shorter extensions.
+ * 
+ * Revision 2.0  86/09/17  15:36:39  lwall
+ * Baseline for netwide release.
+ * 
+ */
+
+#define DEBUGGING
+
+#include "config.h"
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+/* shut lint up about the following when return value ignored */
+
+#define Signal (void)signal
+#define Unlink (void)unlink
+#define Lseek (void)lseek
+#define Fseek (void)fseek
+#define Fstat (void)fstat
+#define Pclose (void)pclose
+#define Close (void)close
+#define Fclose (void)fclose
+#define Fflush (void)fflush
+#define Sprintf (void)sprintf
+#define Mktemp (void)mktemp
+#define Strcpy (void)strcpy
+#define Strcat (void)strcat
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include <ctype.h>
+#include <signal.h>
+#include <stdio.h>
+
+/* constants */
+
+#define TRUE (1)
+#define FALSE (0)
+
+#define MAXHUNKSIZE 100000		/* is this enough lines? */
+#define INITHUNKMAX 125			/* initial dynamic allocation size */
+#define MAXLINELEN 1024
+#define BUFFERSIZE 1024
+#define SCCSPREFIX "s."
+#define GET "get -e %s"
+#define RCSSUFFIX ",v"
+#define CHECKOUT "co -l %s"
+
+#ifdef FLEXFILENAMES
+#define ORIGEXT ".orig"
+#define REJEXT ".rej"
+#else
+#define ORIGEXT "~"
+#define REJEXT "#"
+#endif
+
+/* handy definitions */
+
+#define Null(t) ((t)0)
+#define Nullch Null(char *)
+#define Nullfp Null(FILE *)
+#define Nulline Null(LINENUM)
+
+#define Ctl(ch) ((ch) & 037)
+
+#define strNE(s1,s2) (strcmp(s1, s2))
+#define strEQ(s1,s2) (!strcmp(s1, s2))
+#define strnNE(s1,s2,l) (strncmp(s1, s2, l))
+#define strnEQ(s1,s2,l) (!strncmp(s1, s2, l))
+
+/* typedefs */
+
+typedef int bool;
+typedef long LINENUM;			/* must be signed */
+typedef unsigned MEM;			/* what to feed malloc */
+
+/* globals */
+
+EXT int Argc;				/* guess */
+EXT char **Argv;
+EXT int Argc_last;			/* for restarting plan_b */
+EXT char **Argv_last;
+
+EXT struct stat filestat;		/* file statistics area */
+EXT int filemode INIT(0644);
+
+EXT char buf[MAXLINELEN];		/* general purpose buffer */
+EXT FILE *ofp INIT(Nullfp);		/* output file pointer */
+EXT FILE *rejfp INIT(Nullfp);		/* reject file pointer */
+
+EXT bool using_plan_a INIT(TRUE);	/* try to keep everything in memory */
+EXT bool out_of_mem INIT(FALSE);	/* ran out of memory in plan a */
+
+#define MAXFILEC 2
+EXT int filec INIT(0);			/* how many file arguments? */
+EXT char *filearg[MAXFILEC];
+EXT bool ok_to_create_file INIT(FALSE);
+EXT char *bestguess INIT(Nullch);	/* guess at correct filename */
+
+EXT char *outname INIT(Nullch);
+EXT char rejname[128];
+
+EXT char *origext INIT(Nullch);
+EXT char *origprae INIT(Nullch);
+
+EXT char TMPOUTNAME[] INIT("/tmp/patchoXXXXXX");
+EXT char TMPINNAME[] INIT("/tmp/patchiXXXXXX");	/* might want /usr/tmp here */
+EXT char TMPREJNAME[] INIT("/tmp/patchrXXXXXX");
+EXT char TMPPATNAME[] INIT("/tmp/patchpXXXXXX");
+#ifdef SMALL
+EXT char TMPSTRNAME[] INIT("/tmp/patchsXXXXXX");
+#endif
+EXT bool toutkeep INIT(FALSE);
+EXT bool trejkeep INIT(FALSE);
+
+EXT LINENUM last_offset INIT(0);
+#ifdef DEBUGGING
+EXT int debug INIT(0);
+#endif
+EXT LINENUM maxfuzz INIT(2);
+EXT bool force INIT(FALSE);
+EXT bool verbose INIT(TRUE);
+EXT bool reverse INIT(FALSE);
+EXT bool noreverse INIT(FALSE);
+EXT bool skip_rest_of_patch INIT(FALSE);
+EXT int strippath INIT(957);
+EXT bool canonicalize INIT(FALSE);
+
+#define CONTEXT_DIFF 1
+#define NORMAL_DIFF 2
+#define ED_DIFF 3
+#define NEW_CONTEXT_DIFF 4
+EXT int diff_type INIT(0);
+
+EXT bool do_defines INIT(FALSE);	/* patch using ifdef, ifndef, etc. */
+EXT char if_defined[128];		/* #ifdef xyzzy */
+EXT char not_defined[128];		/* #ifndef xyzzy */
+EXT char else_defined[] INIT("#else\n");/* #else */
+EXT char end_defined[128];		/* #endif xyzzy */
+
+EXT char *revision INIT(Nullch);	/* prerequisite revision, if any */
+
+_PROTOTYPE(void my_exit , (int status ));
Index: /trunk/minix/commands/patch/config.h
===================================================================
--- /trunk/minix/commands/patch/config.h	(revision 9)
+++ /trunk/minix/commands/patch/config.h	(revision 9)
@@ -0,0 +1,23 @@
+/* config.h
+ * This file was produced by running the Configure script.
+ * Feel free to modify any of this as the need arises.
+ */
+
+/* How many register declarations are paid attention to? */
+
+#define Reg1 register
+#define Reg2 register
+#define Reg3
+#define Reg4
+#define Reg5
+#define Reg6
+#define Reg7 
+#define Reg8 
+#define Reg9 
+#define Reg10 
+#define Reg11 
+#define Reg12 
+#define Reg13 
+#define Reg14 
+#define Reg15 
+#define Reg16 
Index: /trunk/minix/commands/patch/inp.c
===================================================================
--- /trunk/minix/commands/patch/inp.c	(revision 9)
+++ /trunk/minix/commands/patch/inp.c	(revision 9)
@@ -0,0 +1,331 @@
+/* $Header: /cvsup/minix/src/commands/patch/inp.c,v 1.1.1.1 2005/04/21 14:55:10 beng Exp $
+ *
+ * $Log: inp.c,v $
+ * Revision 1.1.1.1  2005/04/21 14:55:10  beng
+ * Initial import of pre-3.0.1
+ *
+ * Revision 1.1.1.1  2005/04/20 13:33:18  beng
+ * Initial import of minix 2.0.4
+ *
+ * Revision 2.0.1.1  88/06/03  15:06:13  lwall
+ * patch10: made a little smarter about sccs files
+ * 
+ * Revision 2.0  86/09/17  15:37:02  lwall
+ * Baseline for netwide release.
+ * 
+ */
+
+#include "EXTERN.h"
+#include "common.h"
+#include "util.h"
+#include "pch.h"
+#include "INTERN.h"
+#include "inp.h"
+
+/* Input-file-with-indexable-lines abstract type */
+
+static long i_size;			/* size of the input file */
+static char *i_womp;			/* plan a buffer for entire file */
+static char **i_ptr;			/* pointers to lines in i_womp */
+
+static int tifd = -1;			/* plan b virtual string array */
+static char *tibuf[2];			/* plan b buffers */
+static LINENUM tiline[2] = {-1, -1};	/* 1st line in each buffer */
+static LINENUM lines_per_buf;		/* how many lines per buffer */
+static int tireclen;			/* length of records in tmp file */
+
+/* New patch--prepare to edit another file. */
+
+void
+re_input()
+{
+    if (using_plan_a) {
+	i_size = 0;
+#ifndef lint
+	if (i_ptr != Null(char**))
+	    free((char *)i_ptr);
+#endif
+	if (i_womp != Nullch)
+	    free(i_womp);
+	i_womp = Nullch;
+	i_ptr = Null(char **);
+    }
+    else {
+#ifndef SMALL
+	using_plan_a = TRUE;		/* maybe the next one is smaller */
+#endif
+	Close(tifd);
+	tifd = -1;
+	free(tibuf[0]);
+	free(tibuf[1]);
+	tibuf[0] = tibuf[1] = Nullch;
+	tiline[0] = tiline[1] = -1;
+	tireclen = 0;
+    }
+}
+
+/* Constuct the line index, somehow or other. */
+
+void
+scan_input(filename)
+char *filename;
+{
+#ifndef SMALL
+    if (!plan_a(filename))
+#endif
+	plan_b(filename);
+    if (verbose) {
+	say3("Patching file %s using Plan %s...\n", filename,
+	  (using_plan_a ? "A" : "B") );
+    }
+}
+
+#ifndef SMALL
+/* Try keeping everything in memory. */
+
+bool
+plan_a(filename)
+char *filename;
+{
+    int ifd;
+    Reg1 char *s;
+    Reg2 LINENUM iline;
+
+    if (ok_to_create_file && stat(filename, &filestat) < 0) {
+	if (verbose)
+	    say2("(Creating file %s...)\n",filename);
+	makedirs(filename, TRUE);
+	close(creat(filename, 0666));
+    }
+    if (stat(filename, &filestat) < 0) {
+	Sprintf(buf, "RCS/%s%s", filename, RCSSUFFIX);
+	if (stat(buf, &filestat) >= 0 || stat(buf+4, &filestat) >= 0) {
+	    Sprintf(buf, CHECKOUT, filename);
+	    if (verbose)
+		say2("Can't find %s--attempting to check it out from RCS.\n",
+		    filename);
+	    if (system(buf) || stat(filename, &filestat))
+		fatal2("Can't check out %s.\n", filename);
+	}
+	else {
+	    Sprintf(buf+20, "SCCS/%s%s", SCCSPREFIX, filename);
+	    if (stat(s=buf+20, &filestat) >= 0 ||
+	      stat(s=buf+25, &filestat) >= 0) {
+		Sprintf(buf, GET, s);
+		if (verbose)
+		    say2("Can't find %s--attempting to get it from SCCS.\n",
+			filename);
+		if (system(buf) || stat(filename, &filestat))
+		    fatal2("Can't get %s.\n", filename);
+	    }
+	    else
+		fatal2("Can't find %s.\n", filename);
+	}
+    }
+    filemode = filestat.st_mode;
+    if ((filemode & S_IFMT) & ~S_IFREG)
+	fatal2("%s is not a normal file--can't patch.\n", filename);
+    i_size = filestat.st_size;
+    if (out_of_mem) {
+	set_hunkmax();		/* make sure dynamic arrays are allocated */
+	out_of_mem = FALSE;
+	return FALSE;			/* force plan b because plan a bombed */
+    }
+#ifdef lint
+    i_womp = Nullch;
+#else
+    i_womp = malloc((MEM)(i_size+2));	/* lint says this may alloc less than */
+					/* i_size, but that's okay, I think. */
+#endif
+    if (i_womp == Nullch)
+	return FALSE;
+    if ((ifd = open(filename, 0)) < 0)
+	fatal2("Can't open file %s\n", filename);
+#ifndef lint
+    if (read(ifd, i_womp, (int)i_size) != i_size) {
+	Close(ifd);	/* probably means i_size > 15 or 16 bits worth */
+	free(i_womp);	/* at this point it doesn't matter if i_womp was */
+	return FALSE;	/*   undersized. */
+    }
+#endif
+    Close(ifd);
+    if (i_size && i_womp[i_size-1] != '\n')
+	i_womp[i_size++] = '\n';
+    i_womp[i_size] = '\0';
+
+    /* count the lines in the buffer so we know how many pointers we need */
+
+    iline = 0;
+    for (s=i_womp; *s; s++) {
+	if (*s == '\n')
+	    iline++;
+    }
+#ifdef lint
+    i_ptr = Null(char**);
+#else
+    i_ptr = (char **)malloc((MEM)((iline + 2) * sizeof(char *)));
+#endif
+    if (i_ptr == Null(char **)) {	/* shucks, it was a near thing */
+	free((char *)i_womp);
+	return FALSE;
+    }
+    
+    /* now scan the buffer and build pointer array */
+
+    iline = 1;
+    i_ptr[iline] = i_womp;
+    for (s=i_womp; *s; s++) {
+	if (*s == '\n')
+	    i_ptr[++iline] = s+1;	/* these are NOT null terminated */
+    }
+    input_lines = iline - 1;
+
+    /* now check for revision, if any */
+
+    if (revision != Nullch) { 
+	if (!rev_in_string(i_womp)) {
+	    if (force) {
+		if (verbose)
+		    say2(
+"Warning: this file doesn't appear to be the %s version--patching anyway.\n",
+			revision);
+	    }
+	    else {
+		ask2(
+"This file doesn't appear to be the %s version--patch anyway? [n] ",
+		    revision);
+	    if (*buf != 'y')
+		fatal1("Aborted.\n");
+	    }
+	}
+	else if (verbose)
+	    say2("Good.  This file appears to be the %s version.\n",
+		revision);
+    }
+    return TRUE;			/* plan a will work */
+}
+#endif
+
+/* Keep (virtually) nothing in memory. */
+
+void
+plan_b(filename)
+char *filename;
+{
+    Reg3 FILE *ifp;
+    Reg1 int i = 0;
+    Reg2 int maxlen = 1;
+    Reg4 bool found_revision = (revision == Nullch);
+
+    using_plan_a = FALSE;
+    if ((ifp = fopen(filename, "r")) == Nullfp)
+	fatal2("Can't open file %s\n", filename);
+    if ((tifd = creat(TMPINNAME, 0666)) < 0)
+	fatal2("Can't open file %s\n", TMPINNAME);
+    while (fgets(buf, sizeof buf, ifp) != Nullch) {
+	if (revision != Nullch && !found_revision && rev_in_string(buf))
+	    found_revision = TRUE;
+	if ((i = strlen(buf)) > maxlen)
+	    maxlen = i;			/* find longest line */
+    }
+    if (revision != Nullch) {
+	if (!found_revision) {
+	    if (force) {
+		if (verbose)
+		    say2(
+"Warning: this file doesn't appear to be the %s version--patching anyway.\n",
+			revision);
+	    }
+	    else {
+		ask2(
+"This file doesn't appear to be the %s version--patch anyway? [n] ",
+		    revision);
+		if (*buf != 'y')
+		    fatal1("Aborted.\n");
+	    }
+	}
+	else if (verbose)
+	    say2("Good.  This file appears to be the %s version.\n",
+		revision);
+    }
+    Fseek(ifp, 0L, 0);		/* rewind file */
+    lines_per_buf = BUFFERSIZE / maxlen;
+    tireclen = maxlen;
+    tibuf[0] = (char *)malloc((MEM)(BUFFERSIZE + 1));
+    tibuf[1] = (char *)malloc((MEM)(BUFFERSIZE + 1));
+    if (tibuf[1] == Nullch)
+	fatal1("Can't seem to get enough memory.\n");
+    for (i=1; ; i++) {
+	if (! (i % lines_per_buf))	/* new block */
+	    if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
+		fatal1("patch: can't write temp file.\n");
+	if (fgets(tibuf[0] + maxlen * (i%lines_per_buf), maxlen + 1, ifp)
+	  == Nullch) {
+	    input_lines = i - 1;
+	    if (i % lines_per_buf)
+		if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
+		    fatal1("patch: can't write temp file.\n");
+	    break;
+	}
+    }
+    Fclose(ifp);
+    Close(tifd);
+    if ((tifd = open(TMPINNAME, 0)) < 0) {
+	fatal2("Can't reopen file %s\n", TMPINNAME);
+    }
+}
+
+/* Fetch a line from the input file, \n terminated, not necessarily \0. */
+
+char *
+ifetch(line,whichbuf)
+Reg1 LINENUM line;
+int whichbuf;				/* ignored when file in memory */
+{
+    if (line < 1 || line > input_lines)
+	return "";
+    if (using_plan_a)
+	return i_ptr[line];
+    else {
+	LINENUM offline = line % lines_per_buf;
+	LINENUM baseline = line - offline;
+
+	if (tiline[0] == baseline)
+	    whichbuf = 0;
+	else if (tiline[1] == baseline)
+	    whichbuf = 1;
+	else {
+	    tiline[whichbuf] = baseline;
+#ifndef lint		/* complains of long accuracy */
+	    Lseek(tifd, (long)baseline / lines_per_buf * BUFFERSIZE, 0);
+#endif
+	    if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0)
+		fatal2("Error reading tmp file %s.\n", TMPINNAME);
+	}
+	return tibuf[whichbuf] + (tireclen*offline);
+    }
+}
+
+/* True if the string argument contains the revision number we want. */
+
+bool
+rev_in_string(string)
+char *string;
+{
+    Reg1 char *s;
+    Reg2 int patlen;
+
+    if (revision == Nullch)
+	return TRUE;
+    patlen = strlen(revision);
+    if (strnEQ(string,revision,patlen) && isspace(s[patlen]))
+	return TRUE;
+    for (s = string; *s; s++) {
+	if (isspace(*s) && strnEQ(s+1, revision, patlen) && 
+		isspace(s[patlen+1] )) {
+	    return TRUE;
+	}
+    }
+    return FALSE;
+}
+
Index: /trunk/minix/commands/patch/inp.h
===================================================================
--- /trunk/minix/commands/patch/inp.h	(revision 9)
+++ /trunk/minix/commands/patch/inp.h	(revision 9)
@@ -0,0 +1,24 @@
+/* $Header: /cvsup/minix/src/commands/patch/inp.h,v 1.1.1.1 2005/04/21 14:55:10 beng Exp $
+ *
+ * $Log: inp.h,v $
+ * Revision 1.1.1.1  2005/04/21 14:55:10  beng
+ * Initial import of pre-3.0.1
+ *
+ * Revision 1.1.1.1  2005/04/20 13:33:18  beng
+ * Initial import of minix 2.0.4
+ *
+ * Revision 2.0  86/09/17  15:37:25  lwall
+ * Baseline for netwide release.
+ * 
+ */
+
+EXT LINENUM input_lines INIT(0);	/* how long is input file in lines */
+EXT LINENUM last_frozen_line INIT(0);	/* how many input lines have been */
+					/* irretractibly output */
+
+_PROTOTYPE(bool rev_in_string , (char *string ));
+_PROTOTYPE(void scan_input , (char *filename ));
+_PROTOTYPE(bool plan_a , (char *filename )); 
+_PROTOTYPE(void plan_b , (char *filename ));
+_PROTOTYPE(char *ifetch , (Reg1 LINENUM line , int whichbuf ));
+_PROTOTYPE(void re_input , (void));
Index: /trunk/minix/commands/patch/patch.c
===================================================================
--- /trunk/minix/commands/patch/patch.c	(revision 9)
+++ /trunk/minix/commands/patch/patch.c	(revision 9)
@@ -0,0 +1,843 @@
+char rcsid[] =
+	"$Header: /cvsup/minix/src/commands/patch/patch.c,v 1.1.1.1 2005/04/21 14:55:10 beng Exp $";
+
+/* patch - a program to apply diffs to original files
+ *
+ * Copyright 1986, Larry Wall
+ *
+ * This program may be copied as long as you don't try to make any
+ * money off of it, or pretend that you wrote it.
+ *
+ * $Log: patch.c,v $
+ * Revision 1.1.1.1  2005/04/21 14:55:10  beng
+ * Initial import of pre-3.0.1
+ *
+ * Revision 1.1.1.1  2005/04/20 13:33:19  beng
+ * Initial import of minix 2.0.4
+ *
+ * Revision 2.0.1.6  88/06/22  20:46:39  lwall
+ * patch12: rindex() wasn't declared
+ * 
+ * Revision 2.0.1.5  88/06/03  15:09:37  lwall
+ * patch10: exit code improved.
+ * patch10: better support for non-flexfilenames.
+ * 
+ * Revision 2.0.1.4  87/02/16  14:00:04  lwall
+ * Short replacement caused spurious "Out of sync" message.
+ * 
+ * Revision 2.0.1.3  87/01/30  22:45:50  lwall
+ * Improved diagnostic on sync error.
+ * Moved do_ed_script() to pch.c.
+ * 
+ * Revision 2.0.1.2  86/11/21  09:39:15  lwall
+ * Fuzz factor caused offset of installed lines.
+ * 
+ * Revision 2.0.1.1  86/10/29  13:10:22  lwall
+ * Backwards search could terminate prematurely.
+ * 
+ * Revision 2.0  86/09/17  15:37:32  lwall
+ * Baseline for netwide release.
+ * 
+ * Revision 1.5  86/08/01  20:53:24  lwall
+ * Changed some %d's to %ld's.
+ * Linted.
+ * 
+ * Revision 1.4  86/08/01  19:17:29  lwall
+ * Fixes for machines that can't vararg.
+ * Added fuzz factor.
+ * Generalized -p.
+ * General cleanup.
+ * 
+ * 85/08/15 van%ucbmonet@berkeley
+ * Changes for 4.3bsd diff -c.
+ *
+ * Revision 1.3  85/03/26  15:07:43  lwall
+ * Frozen.
+ * 
+ * Revision 1.2.1.9  85/03/12  17:03:35  lwall
+ * Changed pfp->_file to fileno(pfp).
+ * 
+ * Revision 1.2.1.8  85/03/12  16:30:43  lwall
+ * Check i_ptr and i_womp to make sure they aren't null before freeing.
+ * Also allow ed output to be suppressed.
+ * 
+ * Revision 1.2.1.7  85/03/12  15:56:13  lwall
+ * Added -p option from jromine@uci-750a.
+ * 
+ * Revision 1.2.1.6  85/03/12  12:12:51  lwall
+ * Now checks for normalness of file to patch.
+ * 
+ * Revision 1.2.1.5  85/03/12  11:52:12  lwall
+ * Added -D (#ifdef) option from joe@fluke.
+ * 
+ * Revision 1.2.1.4  84/12/06  11:14:15  lwall
+ * Made smarter about SCCS subdirectories.
+ * 
+ * Revision 1.2.1.3  84/12/05  11:18:43  lwall
+ * Added -l switch to do loose string comparison.
+ * 
+ * Revision 1.2.1.2  84/12/04  09:47:13  lwall
+ * Failed hunk count not reset on multiple patch file.
+ * 
+ * Revision 1.2.1.1  84/12/04  09:42:37  lwall
+ * Branch for sdcrdcf changes.
+ * 
+ * Revision 1.2  84/11/29  13:29:51  lwall
+ * Linted.  Identifiers uniqified.  Fixed i_ptr malloc() bug.  Fixed
+ * multiple calls to mktemp().  Will now work on machines that can only
+ * read 32767 chars.  Added -R option for diffs with new and old swapped.
+ * Various cosmetic changes.
+ * 
+ * Revision 1.1  84/11/09  17:03:58  lwall
+ * Initial revision
+ * 
+ */
+/*
+ * 1992-01-15
+ * Modified by Saeko & Kouichi Hirabayashi to fit small memory (64K+64K)
+ * system by adding "#if[n]def SMALL" parts.
+ */
+
+#include "INTERN.h"
+#include "common.h"
+#include "EXTERN.h"
+#include "version.h"
+#include "util.h"
+#include "pch.h"
+#include "inp.h"
+
+/* procedures */
+
+_PROTOTYPE(int main , (int argc , char **argv ));
+_PROTOTYPE(void reinitialize_almost_everything , (void));
+_PROTOTYPE(void get_some_switches , (void));
+_PROTOTYPE(LINENUM locate_hunk , (LINENUM fuzz ));
+_PROTOTYPE(void abort_hunk , (void));
+_PROTOTYPE(void apply_hunk , (LINENUM where ));
+_PROTOTYPE(void init_output , (char *name ));
+_PROTOTYPE(void init_reject , (char *name ));
+_PROTOTYPE(void copy_till , (Reg1 LINENUM lastline ));
+_PROTOTYPE(void spew_output , (void));
+_PROTOTYPE(void dump_line , (LINENUM line ));
+_PROTOTYPE(bool patch_match , (LINENUM base , LINENUM offset , LINENUM fuzz ));
+_PROTOTYPE(bool similar , (Reg1 char *a , Reg2 char *b , Reg3 int len ));
+
+/* Apply a set of diffs as appropriate. */
+
+int main(argc,argv)
+int argc;
+char **argv;
+{
+    LINENUM where;
+    LINENUM newwhere;
+    LINENUM fuzz;
+    LINENUM mymaxfuzz;
+    int hunk = 0;
+    int failed = 0;
+    int failtotal = 0;
+    int i;
+
+    setbuf(stderr, serrbuf);
+    for (i = 0; i<MAXFILEC; i++)
+	filearg[i] = Nullch;
+    Mktemp(TMPOUTNAME);
+    Mktemp(TMPINNAME);
+    Mktemp(TMPREJNAME);
+    Mktemp(TMPPATNAME);
+#ifdef SMALL
+    Mktemp(TMPSTRNAME);
+#endif
+
+    /* parse switches */
+    Argc = argc;
+    Argv = argv;
+    get_some_switches();
+    
+    /* make sure we clean up /tmp in case of disaster */
+    set_signals(0);
+
+    for (
+	open_patch_file(filearg[1]);
+	there_is_another_patch();
+	reinitialize_almost_everything()
+    ) {					/* for each patch in patch file */
+
+	if (outname == Nullch)
+	    outname = savestr(filearg[0]);
+    
+	/* initialize the patched file */
+	if (!skip_rest_of_patch)
+	    init_output(TMPOUTNAME);
+    
+	/* for ed script just up and do it and exit */
+	if (diff_type == ED_DIFF) {
+	    do_ed_script();
+	    continue;
+	}
+    
+	/* initialize reject file */
+	init_reject(TMPREJNAME);
+    
+	/* find out where all the lines are */
+	if (!skip_rest_of_patch)
+	    scan_input(filearg[0]);
+    
+	/* from here on, open no standard i/o files, because malloc */
+	/* might misfire and we can't catch it easily */
+    
+	/* apply each hunk of patch */
+	hunk = 0;
+	failed = 0;
+	out_of_mem = FALSE;
+	while (another_hunk()) {
+	    hunk++;
+	    fuzz = Nulline;
+	    mymaxfuzz = pch_context();
+	    if (maxfuzz < mymaxfuzz)
+		mymaxfuzz = maxfuzz;
+	    if (!skip_rest_of_patch) {
+		do {
+		    where = locate_hunk(fuzz);
+		    if (hunk == 1 && where == Nulline && !force) {
+						/* dwim for reversed patch? */
+			if (!pch_swap()) {
+			    if (fuzz == Nulline)
+				say1(
+"Not enough memory to try swapped hunk!  Assuming unswapped.\n");
+			    continue;
+			}
+			reverse = !reverse;
+			where = locate_hunk(fuzz);  /* try again */
+			if (where == Nulline) {	    /* didn't find it swapped */
+			    if (!pch_swap())         /* put it back to normal */
+				fatal1("Lost hunk on alloc error!\n");
+			    reverse = !reverse;
+			}
+			else if (noreverse) {
+			    if (!pch_swap())         /* put it back to normal */
+				fatal1("Lost hunk on alloc error!\n");
+			    reverse = !reverse;
+			    say1(
+"Ignoring previously applied (or reversed) patch.\n");
+			    skip_rest_of_patch = TRUE;
+			}
+			else {
+			    ask3(
+"%seversed (or previously applied) patch detected!  %s -R? [y] ",
+				reverse ? "R" : "Unr",
+				reverse ? "Assume" : "Ignore");
+			    if (*buf == 'n') {
+				ask1("Apply anyway? [n] ");
+				if (*buf != 'y')
+				    skip_rest_of_patch = TRUE;
+				where = Nulline;
+				reverse = !reverse;
+				if (!pch_swap())  /* put it back to normal */
+				    fatal1("Lost hunk on alloc error!\n");
+			    }
+			}
+		    }
+		} while (!skip_rest_of_patch && where == Nulline &&
+		    ++fuzz <= mymaxfuzz);
+
+		if (skip_rest_of_patch) {		/* just got decided */
+		    Fclose(ofp);
+		    ofp = Nullfp;
+		}
+	    }
+
+	    newwhere = pch_newfirst() + last_offset;
+	    if (skip_rest_of_patch) {
+		abort_hunk();
+		failed++;
+		if (verbose)
+		    say3("Hunk #%d ignored at %ld.\n", hunk, newwhere);
+	    }
+	    else if (where == Nulline) {
+		abort_hunk();
+		failed++;
+		if (verbose)
+		    say3("Hunk #%d failed at %ld.\n", hunk, newwhere);
+	    }
+	    else {
+		apply_hunk(where);
+		if (verbose) {
+		    say3("Hunk #%d succeeded at %ld", hunk, newwhere);
+		    if (fuzz)
+			say2(" with fuzz %ld", fuzz);
+		    if (last_offset)
+			say3(" (offset %ld line%s)",
+			    last_offset, last_offset==1L?"":"s");
+		    say1(".\n");
+		}
+	    }
+	}
+
+	if (out_of_mem && using_plan_a) {
+	    Argc = Argc_last;
+	    Argv = Argv_last;
+	    say1("\n\nRan out of memory using Plan A--trying again...\n\n");
+	    continue;
+	}
+    
+	assert(hunk);
+    
+	/* finish spewing out the new file */
+	if (!skip_rest_of_patch)
+	    spew_output();
+	
+	/* and put the output where desired */
+	ignore_signals();
+	if (!skip_rest_of_patch) {
+	    if (move_file(TMPOUTNAME, outname) < 0) {
+		toutkeep = TRUE;
+		chmod(TMPOUTNAME, filemode);
+	    }
+	    else
+		chmod(outname, filemode);
+	}
+	Fclose(rejfp);
+	rejfp = Nullfp;
+	if (failed) {
+	    failtotal += failed;
+	    if (!*rejname) {
+		Strcpy(rejname, outname);
+#ifndef FLEXFILENAMES
+		{
+		    char *s = rindex(rejname,'/');
+
+		    if (!s)
+			s = rejname;
+		    if (strlen(s) > 13)
+			if (s[12] == '.')	/* try to preserve difference */
+			    s[12] = s[13];	/* between .h, .c, .y, etc. */
+			s[13] = '\0';
+		}
+#endif
+		Strcat(rejname, REJEXT);
+	    }
+	    if (skip_rest_of_patch) {
+		say4("%d out of %d hunks ignored--saving rejects to %s\n",
+		    failed, hunk, rejname);
+	    }
+	    else {
+		say4("%d out of %d hunks failed--saving rejects to %s\n",
+		    failed, hunk, rejname);
+	    }
+	    if (move_file(TMPREJNAME, rejname) < 0)
+		trejkeep = TRUE;
+	}
+	set_signals(1);
+    }
+#ifdef SMALL
+    if (sfp != Nullfp)
+	Fclose(sfp);
+#endif
+    my_exit(failtotal);
+}
+
+/* Prepare to find the next patch to do in the patch file. */
+
+void
+reinitialize_almost_everything()
+{
+    re_patch();
+    re_input();
+
+    input_lines = 0;
+    last_frozen_line = 0;
+
+    filec = 0;
+    if (filearg[0] != Nullch && !out_of_mem) {
+	free(filearg[0]);
+	filearg[0] = Nullch;
+    }
+
+    if (outname != Nullch) {
+	free(outname);
+	outname = Nullch;
+    }
+
+    last_offset = 0;
+
+    diff_type = 0;
+
+    if (revision != Nullch) {
+	free(revision);
+	revision = Nullch;
+    }
+
+    reverse = FALSE;
+    skip_rest_of_patch = FALSE;
+
+    get_some_switches();
+
+    if (filec >= 2)
+	fatal1("You may not change to a different patch file.\n");
+}
+
+/* Process switches and filenames up to next '+' or end of list. */
+
+void
+get_some_switches()
+{
+    Reg1 char *s;
+
+    rejname[0] = '\0';
+    Argc_last = Argc;
+    Argv_last = Argv;
+    if (!Argc)
+	return;
+    for (Argc--,Argv++; Argc; Argc--,Argv++) {
+	s = Argv[0];
+	if (strEQ(s, "+")) {
+	    return;			/* + will be skipped by for loop */
+	}
+	if (*s != '-' || !s[1]) {
+	    if (filec == MAXFILEC)
+		fatal1("Too many file arguments.\n");
+	    filearg[filec++] = savestr(s);
+	}
+	else {
+	    switch (*++s) {
+	    case 'b':
+		origext = savestr(Argv[1]);
+		Argc--,Argv++;
+		break;
+	    case 'B':
+		origprae = savestr(Argv[1]);
+		Argc--,Argv++;
+		break;
+	    case 'c':
+		diff_type = CONTEXT_DIFF;
+		break;
+	    case 'd':
+		if (!*++s) {
+		    Argc--,Argv++;
+		    s = Argv[0];
+		}
+		if (chdir(s) < 0)
+		    fatal2("Can't cd to %s.\n", s);
+		break;
+	    case 'D':
+	    	do_defines = TRUE;
+		if (!*++s) {
+		    Argc--,Argv++;
+		    s = Argv[0];
+		}
+		if (!isalpha(*s))
+		    fatal1("Argument to -D not an identifier.\n");
+		Sprintf(if_defined, "#ifdef %s\n", s);
+		Sprintf(not_defined, "#ifndef %s\n", s);
+		Sprintf(end_defined, "#endif /* %s */\n", s);
+		break;
+	    case 'e':
+		diff_type = ED_DIFF;
+		break;
+	    case 'f':
+		force = TRUE;
+		break;
+	    case 'F':
+		if (*++s == '=')
+		    s++;
+		maxfuzz = atoi(s);
+		break;
+	    case 'l':
+		canonicalize = TRUE;
+		break;
+	    case 'n':
+		diff_type = NORMAL_DIFF;
+		break;
+	    case 'N':
+		noreverse = TRUE;
+		break;
+	    case 'o':
+		outname = savestr(Argv[1]);
+		Argc--,Argv++;
+		break;
+	    case 'p':
+		if (*++s == '=')
+		    s++;
+		strippath = atoi(s);
+		break;
+	    case 'r':
+		Strcpy(rejname, Argv[1]);
+		Argc--,Argv++;
+		break;
+	    case 'R':
+		reverse = TRUE;
+		break;
+	    case 's':
+		verbose = FALSE;
+		break;
+	    case 'S':
+		skip_rest_of_patch = TRUE;
+		break;
+	    case 'v':
+		version();
+		break;
+#ifdef DEBUGGING
+	    case 'x':
+		debug = atoi(s+1);
+		break;
+#endif
+	    default:
+		fatal2("Unrecognized switch: %s\n", Argv[0]);
+	    }
+	}
+    }
+}
+
+/* Attempt to find the right place to apply this hunk of patch. */
+
+LINENUM
+locate_hunk(fuzz)
+LINENUM fuzz;
+{
+    Reg1 LINENUM first_guess = pch_first() + last_offset;
+    Reg2 LINENUM offset;
+    LINENUM pat_lines = pch_ptrn_lines();
+    Reg3 LINENUM max_pos_offset = input_lines - first_guess
+				- pat_lines + 1; 
+    Reg4 LINENUM max_neg_offset = first_guess - last_frozen_line - 1
+				+ pch_context();
+
+    if (!pat_lines)			/* null range matches always */
+	return first_guess;
+    if (max_neg_offset >= first_guess)	/* do not try lines < 0 */
+	max_neg_offset = first_guess - 1;
+    if (first_guess <= input_lines && patch_match(first_guess, Nulline, fuzz))
+	return first_guess;
+    for (offset = 1; ; offset++) {
+	Reg5 bool check_after = (offset <= max_pos_offset);
+	Reg6 bool check_before = (offset <= max_neg_offset);
+
+	if (check_after && patch_match(first_guess, offset, fuzz)) {
+#ifdef DEBUGGING
+	    if (debug & 1)
+		say3("Offset changing from %ld to %ld\n", last_offset, offset);
+#endif
+	    last_offset = offset;
+	    return first_guess+offset;
+	}
+	else if (check_before && patch_match(first_guess, -offset, fuzz)) {
+#ifdef DEBUGGING
+	    if (debug & 1)
+		say3("Offset changing from %ld to %ld\n", last_offset, -offset);
+#endif
+	    last_offset = -offset;
+	    return first_guess-offset;
+	}
+	else if (!check_before && !check_after)
+	    return Nulline;
+    }
+}
+
+/* We did not find the pattern, dump out the hunk so they can handle it. */
+
+void
+abort_hunk()
+{
+    Reg1 LINENUM i;
+    Reg2 LINENUM pat_end = pch_end();
+    /* add in last_offset to guess the same as the previous successful hunk */
+    LINENUM oldfirst = pch_first() + last_offset;
+    LINENUM newfirst = pch_newfirst() + last_offset;
+    LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1;
+    LINENUM newlast = newfirst + pch_repl_lines() - 1;
+    char *stars = (diff_type == NEW_CONTEXT_DIFF ? " ****" : "");
+    char *minuses = (diff_type == NEW_CONTEXT_DIFF ? " ----" : " -----");
+
+    fprintf(rejfp, "***************\n");
+    for (i=0; i<=pat_end; i++) {
+	switch (pch_char(i)) {
+	case '*':
+	    if (oldlast < oldfirst)
+		fprintf(rejfp, "*** 0%s\n", stars);
+	    else if (oldlast == oldfirst)
+		fprintf(rejfp, "*** %ld%s\n", oldfirst, stars);
+	    else
+		fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst, oldlast, stars);
+	    break;
+	case '=':
+	    if (newlast < newfirst)
+		fprintf(rejfp, "--- 0%s\n", minuses);
+	    else if (newlast == newfirst)
+		fprintf(rejfp, "--- %ld%s\n", newfirst, minuses);
+	    else
+		fprintf(rejfp, "--- %ld,%ld%s\n", newfirst, newlast, minuses);
+	    break;
+	case '\n':
+	    fprintf(rejfp, "%s", pfetch(i));
+	    break;
+	case ' ': case '-': case '+': case '!':
+	    fprintf(rejfp, "%c %s", pch_char(i), pfetch(i));
+	    break;
+	default:
+	    say1("Fatal internal error in abort_hunk().\n"); 
+	    abort();
+	}
+    }
+}
+
+/* We found where to apply it (we hope), so do it. */
+
+void
+apply_hunk(where)
+LINENUM where;
+{
+    Reg1 LINENUM old = 1;
+    Reg2 LINENUM lastline = pch_ptrn_lines();
+    Reg3 LINENUM new = lastline+1;
+#define OUTSIDE 0
+#define IN_IFNDEF 1
+#define IN_IFDEF 2
+#define IN_ELSE 3
+    Reg4 int def_state = OUTSIDE;
+    Reg5 bool R_do_defines = do_defines;
+    Reg6 LINENUM pat_end = pch_end();
+
+    where--;
+    while (pch_char(new) == '=' || pch_char(new) == '\n')
+	new++;
+    
+    while (old <= lastline) {
+	if (pch_char(old) == '-') {
+	    copy_till(where + old - 1);
+	    if (R_do_defines) {
+		if (def_state == OUTSIDE) {
+		    fputs(not_defined, ofp);
+		    def_state = IN_IFNDEF;
+		}
+		else if (def_state == IN_IFDEF) {
+		    fputs(else_defined, ofp);
+		    def_state = IN_ELSE;
+		}
+		fputs(pfetch(old), ofp);
+	    }
+	    last_frozen_line++;
+	    old++;
+	}
+	else if (new > pat_end)
+	    break;
+	else if (pch_char(new) == '+') {
+	    copy_till(where + old - 1);
+	    if (R_do_defines) {
+		if (def_state == IN_IFNDEF) {
+		    fputs(else_defined, ofp);
+		    def_state = IN_ELSE;
+		}
+		else if (def_state == OUTSIDE) {
+		    fputs(if_defined, ofp);
+		    def_state = IN_IFDEF;
+		}
+	    }
+	    fputs(pfetch(new), ofp);
+	    new++;
+	}
+	else {
+	    if (pch_char(new) != pch_char(old)) {
+		say3("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n",
+		    pch_hunk_beg() + old,
+		    pch_hunk_beg() + new);
+#ifdef DEBUGGING
+		say3("oldchar = '%c', newchar = '%c'\n",
+		    pch_char(old), pch_char(new));
+#endif
+		my_exit(1);
+	    }
+	    if (pch_char(new) == '!') {
+		copy_till(where + old - 1);
+		if (R_do_defines) {
+		   fputs(not_defined, ofp);
+		   def_state = IN_IFNDEF;
+		}
+		while (pch_char(old) == '!') {
+		    if (R_do_defines) {
+			fputs(pfetch(old), ofp);
+		    }
+		    last_frozen_line++;
+		    old++;
+		}
+		if (R_do_defines) {
+		    fputs(else_defined, ofp);
+		    def_state = IN_ELSE;
+		}
+		while (pch_char(new) == '!') {
+		    fputs(pfetch(new), ofp);
+		    new++;
+		}
+		if (R_do_defines) {
+		    fputs(end_defined, ofp);
+		    def_state = OUTSIDE;
+		}
+	    }
+	    else {
+		assert(pch_char(new) == ' ');
+		old++;
+		new++;
+	    }
+	}
+    }
+    if (new <= pat_end && pch_char(new) == '+') {
+	copy_till(where + old - 1);
+	if (R_do_defines) {
+	    if (def_state == OUTSIDE) {
+	    	fputs(if_defined, ofp);
+		def_state = IN_IFDEF;
+	    }
+	    else if (def_state == IN_IFNDEF) {
+		fputs(else_defined, ofp);
+		def_state = IN_ELSE;
+	    }
+	}
+	while (new <= pat_end && pch_char(new) == '+') {
+	    fputs(pfetch(new), ofp);
+	    new++;
+	}
+    }
+    if (R_do_defines && def_state != OUTSIDE) {
+	fputs(end_defined, ofp);
+    }
+}
+
+/* Open the new file. */
+
+void
+init_output(name)
+char *name;
+{
+    ofp = fopen(name, "w");
+    if (ofp == Nullfp)
+	fatal2("patch: can't create %s.\n", name);
+}
+
+/* Open a file to put hunks we can't locate. */
+
+void
+init_reject(name)
+char *name;
+{
+    rejfp = fopen(name, "w");
+    if (rejfp == Nullfp)
+	fatal2("patch: can't create %s.\n", name);
+}
+
+/* Copy input file to output, up to wherever hunk is to be applied. */
+
+void
+copy_till(lastline)
+Reg1 LINENUM lastline;
+{
+    Reg2 LINENUM R_last_frozen_line = last_frozen_line;
+
+    if (R_last_frozen_line > lastline)
+	say1("patch: misordered hunks! output will be garbled.\n");
+    while (R_last_frozen_line < lastline) {
+	dump_line(++R_last_frozen_line);
+    }
+    last_frozen_line = R_last_frozen_line;
+}
+
+/* Finish copying the input file to the output file. */
+
+void
+spew_output()
+{
+#ifdef DEBUGGING
+    if (debug & 256)
+	say3("il=%ld lfl=%ld\n",input_lines,last_frozen_line);
+#endif
+    if (input_lines)
+	copy_till(input_lines);		/* dump remainder of file */
+    Fclose(ofp);
+    ofp = Nullfp;
+}
+
+/* Copy one line from input to output. */
+
+void
+dump_line(line)
+LINENUM line;
+{
+    Reg1 char *s;
+    Reg2 char R_newline = '\n';
+
+    /* Note: string is not null terminated. */
+    for (s=ifetch(line, 0); putc(*s, ofp) != R_newline; s++) ;
+}
+
+/* Does the patch pattern match at line base+offset? */
+
+bool
+patch_match(base, offset, fuzz)
+LINENUM base;
+LINENUM offset;
+LINENUM fuzz;
+{
+    Reg1 LINENUM pline = 1 + fuzz;
+    Reg2 LINENUM iline;
+    Reg3 LINENUM pat_lines = pch_ptrn_lines() - fuzz;
+
+    for (iline=base+offset+fuzz; pline <= pat_lines; pline++,iline++) {
+	if (canonicalize) {
+	    if (!similar(ifetch(iline, (offset >= 0)),
+			 pfetch(pline),
+			 pch_line_len(pline) ))
+		return FALSE;
+	}
+	else if (strnNE(ifetch(iline, (offset >= 0)),
+		   pfetch(pline),
+		   pch_line_len(pline) ))
+	    return FALSE;
+    }
+    return TRUE;
+}
+
+/* Do two lines match with canonicalized white space? */
+
+bool
+similar(a,b,len)
+Reg1 char *a;
+Reg2 char *b;
+Reg3 int len;
+{
+    while (len) {
+	if (isspace(*b)) {		/* whitespace (or \n) to match? */
+	    if (!isspace(*a))		/* no corresponding whitespace? */
+		return FALSE;
+	    while (len && isspace(*b) && *b != '\n')
+		b++,len--;		/* skip pattern whitespace */
+	    while (isspace(*a) && *a != '\n')
+		a++;			/* skip target whitespace */
+	    if (*a == '\n' || *b == '\n')
+		return (*a == *b);	/* should end in sync */
+	}
+	else if (*a++ != *b++)		/* match non-whitespace chars */
+	    return FALSE;
+	else
+	    len--;			/* probably not necessary */
+    }
+    return TRUE;			/* actually, this is not reached */
+					/* since there is always a \n */
+}
+
+/* Exit with cleanup. */
+
+void
+my_exit(status)
+int status;
+{
+    Unlink(TMPINNAME);
+    if (!toutkeep) {
+	Unlink(TMPOUTNAME);
+    }
+    if (!trejkeep) {
+	Unlink(TMPREJNAME);
+    }
+    Unlink(TMPPATNAME);
+#ifdef SMALL
+    Unlink(TMPSTRNAME);
+#endif
+    exit(status);
+}
Index: /trunk/minix/commands/patch/patchlevel.h
===================================================================
--- /trunk/minix/commands/patch/patchlevel.h	(revision 9)
+++ /trunk/minix/commands/patch/patchlevel.h	(revision 9)
@@ -0,0 +1,1 @@
+#define PATCHLEVEL 12
Index: /trunk/minix/commands/patch/pch.c
===================================================================
--- /trunk/minix/commands/patch/pch.c	(revision 9)
+++ /trunk/minix/commands/patch/pch.c	(revision 9)
@@ -0,0 +1,1307 @@
+/* $Header: /cvsup/minix/src/commands/patch/pch.c,v 1.1.1.1 2005/04/21 14:55:11 beng Exp $
+ *
+ * $Log: pch.c,v $
+ * Revision 1.1.1.1  2005/04/21 14:55:11  beng
+ * Initial import of pre-3.0.1
+ *
+ * Revision 1.1.1.1  2005/04/20 13:33:19  beng
+ * Initial import of minix 2.0.4
+ *
+ * Revision 2.0.1.7  88/06/03  15:13:28  lwall
+ * patch10: Can now find patches in shar scripts.
+ * patch10: Hunks that swapped and then swapped back could core dump.
+ * 
+ * Revision 2.0.1.6  87/06/04  16:18:13  lwall
+ * pch_swap didn't swap p_bfake and p_efake.
+ * 
+ * Revision 2.0.1.5  87/01/30  22:47:42  lwall
+ * Improved responses to mangled patches.
+ * 
+ * Revision 2.0.1.4  87/01/05  16:59:53  lwall
+ * New-style context diffs caused double call to free().
+ * 
+ * Revision 2.0.1.3  86/11/14  10:08:33  lwall
+ * Fixed problem where a long pattern wouldn't grow the hunk.
+ * Also restored p_input_line when backtracking so error messages are right.
+ * 
+ * Revision 2.0.1.2  86/11/03  17:49:52  lwall
+ * New-style delete triggers spurious assertion error.
+ * 
+ * Revision 2.0.1.1  86/10/29  15:52:08  lwall
+ * Could falsely report new-style context diff.
+ * 
+ * Revision 2.0  86/09/17  15:39:37  lwall
+ * Baseline for netwide release.
+ * 
+ */
+
+#include "EXTERN.h"
+#include "common.h"
+#include "util.h"
+#include "INTERN.h"
+#include "pch.h"
+
+/* Patch (diff listing) abstract type. */
+
+static long p_filesize;			/* size of the patch file */
+static LINENUM p_first;			/* 1st line number */
+static LINENUM p_newfirst;		/* 1st line number of replacement */
+static LINENUM p_ptrn_lines;		/* # lines in pattern */
+static LINENUM p_repl_lines;		/* # lines in replacement text */
+static LINENUM p_end = -1;		/* last line in hunk */
+static LINENUM p_max;			/* max allowed value of p_end */
+static LINENUM p_context = 3;		/* # of context lines */
+static LINENUM p_input_line = 0;	/* current line # from patch file */
+#ifdef SMALL
+static long *p_line = Null(long *);	/* the text of the hunk */
+#else
+static char **p_line = Null(char**);	/* the text of the hunk */
+#endif
+static short *p_len = Null(short*);	/* length of each line */
+static char *p_char = Nullch;		/* +, -, and ! */
+static int hunkmax = INITHUNKMAX;	/* size of above arrays to begin with */
+static int p_indent;			/* indent to patch */
+static LINENUM p_base;			/* where to intuit this time */
+static LINENUM p_bline;			/* line # of p_base */
+static LINENUM p_start;			/* where intuit found a patch */
+static LINENUM p_sline;			/* and the line number for it */
+static LINENUM p_hunk_beg;		/* line number of current hunk */
+static LINENUM p_efake = -1;		/* end of faked up lines--don't free */
+static LINENUM p_bfake = -1;		/* beg of faked up lines */
+
+/* Prepare to look for the next patch in the patch file. */
+
+void
+re_patch()
+{
+    p_first = Nulline;
+    p_newfirst = Nulline;
+    p_ptrn_lines = Nulline;
+    p_repl_lines = Nulline;
+    p_end = (LINENUM)-1;
+    p_max = Nulline;
+    p_indent = 0;
+}
+
+/* Open the patch file at the beginning of time. */
+
+void
+open_patch_file(filename)
+char *filename;
+{
+    if (filename == Nullch || !*filename || strEQ(filename, "-")) {
+	pfp = fopen(TMPPATNAME, "w");
+	if (pfp == Nullfp)
+	    fatal2("patch: can't create %s.\n", TMPPATNAME);
+	while (fgets(buf, sizeof buf, stdin) != Nullch)
+	    fputs(buf, pfp);
+	Fclose(pfp);
+	filename = TMPPATNAME;
+    }
+    pfp = fopen(filename, "r");
+    if (pfp == Nullfp)
+	fatal2("patch file %s not found\n", filename);
+    Fstat(fileno(pfp), &filestat);
+    p_filesize = filestat.st_size;
+    next_intuit_at(0L,1L);			/* start at the beginning */
+    set_hunkmax();
+}
+
+/* Make sure our dynamically realloced tables are malloced to begin with. */
+
+void
+set_hunkmax()
+{
+#ifndef lint
+#ifdef SMALL
+    if (p_line == Null(long*))
+#else
+    if (p_line == Null(char**))
+#endif
+#ifdef SMALL
+	p_line = (long *) malloc((MEM)hunkmax * sizeof(long));
+#else
+	p_line = (char**) malloc((MEM)hunkmax * sizeof(char *));
+#endif
+    if (p_len == Null(short*))
+	p_len  = (short*) malloc((MEM)hunkmax * sizeof(short));
+#endif
+    if (p_char == Nullch)
+	p_char = (char*)  malloc((MEM)hunkmax * sizeof(char));
+}
+
+/* Enlarge the arrays containing the current hunk of patch. */
+
+void
+grow_hunkmax()
+{
+    hunkmax *= 2;
+    /* 
+     * Note that on most systems, only the p_line array ever gets fresh memory
+     * since p_len can move into p_line's old space, and p_char can move into
+     * p_len's old space.  Not on PDP-11's however.  But it doesn't matter.
+     */
+#ifdef SMALL
+    assert(p_line != Null(long*) && p_len != Null(short*) && p_char != Nullch);
+#else
+    assert(p_line != Null(char**) && p_len != Null(short*) && p_char != Nullch);
+#endif
+#ifndef lint
+#ifdef SMALL
+    p_line = (long*) realloc((char*)p_line, (MEM)hunkmax * sizeof(long));
+#else
+    p_line = (char**) realloc((char*)p_line, (MEM)hunkmax * sizeof(char *));
+#endif
+    p_len  = (short*) realloc((char*)p_len,  (MEM)hunkmax * sizeof(short));
+    p_char = (char*)  realloc((char*)p_char, (MEM)hunkmax * sizeof(char));
+#endif
+#ifdef SMALL
+    if (p_line != Null(long*) && p_len != Null(short*) && p_char != Nullch)
+#else
+    if (p_line != Null(char**) && p_len != Null(short*) && p_char != Nullch)
+#endif
+	return;
+    if (!using_plan_a)
+	fatal1("patch: out of memory (grow_hunkmax)\n");
+    out_of_mem = TRUE;		/* whatever is null will be allocated again */
+				/* from within plan_a(), of all places */
+}
+
+/* True if the remainder of the patch file contains a diff of some sort. */
+
+bool
+there_is_another_patch()
+{
+    if (p_base != 0L && p_base >= p_filesize) {
+	if (verbose)
+	    say1("done\n");
+	return FALSE;
+    }
+    if (verbose)
+	say1("Hmm...");
+    diff_type = intuit_diff_type();
+    if (!diff_type) {
+	if (p_base != 0L) {
+	    if (verbose)
+		say1("  Ignoring the trailing garbage.\ndone\n");
+	}
+	else
+	    say1("  I can't seem to find a patch in there anywhere.\n");
+	return FALSE;
+    }
+    if (verbose)
+	say3("  %sooks like %s to me...\n",
+	    (p_base == 0L ? "L" : "The next patch l"),
+	    diff_type == CONTEXT_DIFF ? "a context diff" :
+	    diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
+	    diff_type == NORMAL_DIFF ? "a normal diff" :
+	    "an ed script" );
+    if (p_indent && verbose)
+	say3("(Patch is indented %d space%s.)\n", p_indent, p_indent==1?"":"s");
+    skip_to(p_start,p_sline);
+    while (filearg[0] == Nullch) {
+	if (force) {
+	    say1("No file to patch.  Skipping...\n");
+	    filearg[0] = savestr(bestguess);
+	    return TRUE;
+	}
+	ask1("File to patch: ");
+	if (*buf != '\n') {
+	    if (bestguess)
+		free(bestguess);
+	    bestguess = savestr(buf);
+	    filearg[0] = fetchname(buf, 0, FALSE);
+	}
+	if (filearg[0] == Nullch) {
+	    ask1("No file found--skip this patch? [n] ");
+	    if (*buf != 'y') {
+		continue;
+	    }
+	    if (verbose)
+		say1("Skipping patch...\n");
+	    filearg[0] = fetchname(bestguess, 0, TRUE);
+	    skip_rest_of_patch = TRUE;
+	    return TRUE;
+	}
+    }
+    return TRUE;
+}
+
+/* Determine what kind of diff is in the remaining part of the patch file. */
+
+int
+intuit_diff_type()
+{
+    Reg4 long this_line = 0;
+    Reg5 long previous_line;
+    Reg6 long first_command_line = -1;
+    long fcl_line;
+    Reg7 bool last_line_was_command = FALSE;
+    Reg8 bool this_is_a_command = FALSE;
+    Reg9 bool stars_last_line = FALSE;
+    Reg10 bool stars_this_line = FALSE;
+    Reg3 int indent;
+    Reg1 char *s;
+    Reg2 char *t;
+    char *indtmp = Nullch;
+    char *oldtmp = Nullch;
+    char *newtmp = Nullch;
+    char *indname = Nullch;
+    char *oldname = Nullch;
+    char *newname = Nullch;
+    Reg11 int retval;
+    bool no_filearg = (filearg[0] == Nullch);
+
+    ok_to_create_file = FALSE;
+    Fseek(pfp, p_base, 0);
+    p_input_line = p_bline - 1;
+    for (;;) {
+	previous_line = this_line;
+	last_line_was_command = this_is_a_command;
+	stars_last_line = stars_this_line;
+	this_line = ftell(pfp);
+	indent = 0;
+	p_input_line++;
+	if (fgets(buf, sizeof buf, pfp) == Nullch) {
+	    if (first_command_line >= 0L) {
+					/* nothing but deletes!? */
+		p_start = first_command_line;
+		p_sline = fcl_line;
+		retval = ED_DIFF;
+		goto scan_exit;
+	    }
+	    else {
+		p_start = this_line;
+		p_sline = p_input_line;
+		retval = 0;
+		goto scan_exit;
+	    }
+	}
+	for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
+	    if (*s == '\t')
+		indent += 8 - (indent % 8);
+	    else
+		indent++;
+	}
+	for (t=s; isdigit(*t) || *t == ','; t++) ; 
+	this_is_a_command = (isdigit(*s) &&
+	  (*t == 'd' || *t == 'c' || *t == 'a') );
+	if (first_command_line < 0L && this_is_a_command) { 
+	    first_command_line = this_line;
+	    fcl_line = p_input_line;
+	    p_indent = indent;		/* assume this for now */
+	}
+	if (!stars_last_line && strnEQ(s, "*** ", 4))
+	    oldtmp = savestr(s+4);
+	else if (strnEQ(s, "--- ", 4))
+	    newtmp = savestr(s+4);
+	else if (strnEQ(s, "Index:", 6))
+	    indtmp = savestr(s+6);
+	else if (strnEQ(s, "Prereq:", 7)) {
+	    for (t=s+7; isspace(*t); t++) ;
+	    revision = savestr(t);
+	    for (t=revision; *t && !isspace(*t); t++) ;
+	    *t = '\0';
+	    if (!*revision) {
+		free(revision);
+		revision = Nullch;
+	    }
+	}
+	if ((!diff_type || diff_type == ED_DIFF) &&
+	  first_command_line >= 0L &&
+	  strEQ(s, ".\n") ) {
+	    p_indent = indent;
+	    p_start = first_command_line;
+	    p_sline = fcl_line;
+	    retval = ED_DIFF;
+	    goto scan_exit;
+	}
+	stars_this_line = strnEQ(s, "********", 8);
+	if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line &&
+		 strnEQ(s, "*** ", 4)) {
+	    if (!atol(s+4))
+		ok_to_create_file = TRUE;
+	    /* if this is a new context diff the character just before */
+	    /* the newline is a '*'. */
+	    while (*s != '\n')
+		s++;
+	    p_indent = indent;
+	    p_start = previous_line;
+	    p_sline = p_input_line - 1;
+	    retval = (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
+	    goto scan_exit;
+	}
+	if ((!diff_type || diff_type == NORMAL_DIFF) && 
+	  last_line_was_command &&
+	  (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2)) ) {
+	    p_start = previous_line;
+	    p_sline = p_input_line - 1;
+	    p_indent = indent;
+	    retval = NORMAL_DIFF;
+	    goto scan_exit;
+	}
+    }
+  scan_exit:
+    if (no_filearg) {
+	if (indtmp != Nullch)
+	    indname = fetchname(indtmp, strippath, ok_to_create_file);
+	if (oldtmp != Nullch)
+	    oldname = fetchname(oldtmp, strippath, ok_to_create_file);
+	if (newtmp != Nullch)
+	    newname = fetchname(newtmp, strippath, ok_to_create_file);
+	if (oldname && newname) {
+	    if (strlen(oldname) < strlen(newname))
+		filearg[0] = savestr(oldname);
+	    else
+		filearg[0] = savestr(newname);
+	}
+	else if (oldname)
+	    filearg[0] = savestr(oldname);
+	else if (newname)
+	    filearg[0] = savestr(newname);
+	else if (indname)
+	    filearg[0] = savestr(indname);
+    }
+    if (bestguess) {
+	free(bestguess);
+	bestguess = Nullch;
+    }
+    if (filearg[0] != Nullch)
+	bestguess = savestr(filearg[0]);
+    else if (indtmp != Nullch)
+	bestguess = fetchname(indtmp, strippath, TRUE);
+    else {
+	if (oldtmp != Nullch)
+	    oldname = fetchname(oldtmp, strippath, TRUE);
+	if (newtmp != Nullch)
+	    newname = fetchname(newtmp, strippath, TRUE);
+	if (oldname && newname) {
+	    if (strlen(oldname) < strlen(newname))
+		bestguess = savestr(oldname);
+	    else
+		bestguess = savestr(newname);
+	}
+	else if (oldname)
+	    bestguess = savestr(oldname);
+	else if (newname)
+	    bestguess = savestr(newname);
+    }
+    if (indtmp != Nullch)
+	free(indtmp);
+    if (oldtmp != Nullch)
+	free(oldtmp);
+    if (newtmp != Nullch)
+	free(newtmp);
+    if (indname != Nullch)
+	free(indname);
+    if (oldname != Nullch)
+	free(oldname);
+    if (newname != Nullch)
+	free(newname);
+    return retval;
+}
+
+/* Remember where this patch ends so we know where to start up again. */
+
+void
+next_intuit_at(file_pos,file_line)
+long file_pos;
+long file_line;
+{
+    p_base = file_pos;
+    p_bline = file_line;
+}
+
+/* Basically a verbose fseek() to the actual diff listing. */
+
+void
+skip_to(file_pos,file_line)
+long file_pos;
+long file_line;
+{
+    char *ret;
+
+    assert(p_base <= file_pos);
+    if (verbose && p_base < file_pos) {
+	Fseek(pfp, p_base, 0);
+	say1("The text leading up to this was:\n--------------------------\n");
+	while (ftell(pfp) < file_pos) {
+	    ret = fgets(buf, sizeof buf, pfp);
+	    assert(ret != Nullch);
+	    say2("|%s", buf);
+	}
+	say1("--------------------------\n");
+    }
+    else
+	Fseek(pfp, file_pos, 0);
+    p_input_line = file_line - 1;
+}
+
+/* True if there is more of the current diff listing to process. */
+
+bool
+another_hunk()
+{
+    Reg1 char *s;
+    Reg8 char *ret;
+    Reg2 int context = 0;
+
+    while (p_end >= 0) {
+	if (p_end == p_efake)
+	    p_end = p_bfake;		/* don't free twice */
+#ifndef SMALL
+	else
+	    free(p_line[p_end]);
+#endif
+	p_end--;
+    }
+    assert(p_end == -1);
+    p_efake = -1;
+#ifdef SMALL
+    if (sfp != Nullfp)
+	Fclose(sfp);
+    sfp = fopen(TMPSTRNAME, "w");
+    if (sfp == Nullfp)
+	fatal2("patch: can't create %s.\n", TMPSTRNAME);
+#endif
+
+    p_max = hunkmax;			/* gets reduced when --- found */
+    if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) {
+	long line_beginning = ftell(pfp);
+					/* file pos of the current line */
+	LINENUM repl_beginning = 0;	/* index of --- line */
+	Reg4 LINENUM fillcnt = 0;	/* #lines of missing ptrn or repl */
+	Reg5 LINENUM fillsrc;		/* index of first line to copy */
+	Reg6 LINENUM filldst;		/* index of first missing line */
+	bool ptrn_spaces_eaten = FALSE;	/* ptrn was slightly misformed */
+	Reg9 bool repl_could_be_missing = TRUE;
+					/* no + or ! lines in this hunk */
+	bool repl_missing = FALSE;	/* we are now backtracking */
+	long repl_backtrack_position = 0;
+					/* file pos of first repl line */
+	LINENUM repl_patch_line;	/* input line number for same */
+	Reg7 LINENUM ptrn_copiable = 0;
+					/* # of copiable lines in ptrn */
+
+	ret = pgets(buf, sizeof buf, pfp);
+	p_input_line++;
+	if (ret == Nullch || strnNE(buf, "********", 8)) {
+	    next_intuit_at(line_beginning,p_input_line);
+	    return FALSE;
+	}
+	p_context = 100;
+	p_hunk_beg = p_input_line + 1;
+	while (p_end < p_max) {
+	    line_beginning = ftell(pfp);
+	    ret = pgets(buf, sizeof buf, pfp);
+	    p_input_line++;
+	    if (ret == Nullch) {
+		if (p_max - p_end < 4)
+		    Strcpy(buf, "  \n");  /* assume blank lines got chopped */
+		else {
+		    if (repl_beginning && repl_could_be_missing) {
+			repl_missing = TRUE;
+			goto hunk_done;
+		    }
+		    fatal1("Unexpected end of file in patch.\n");
+		}
+	    }
+	    p_end++;
+	    assert(p_end < hunkmax);
+	    p_char[p_end] = *buf;
+#ifdef zilog
+	    p_line[(short)p_end] = Nullch;
+#else
+#ifdef SMALL
+	    p_line[p_end] = -1L;
+	    p_len[p_end] = 0;
+#else
+	    p_line[p_end] = Nullch;
+#endif
+#endif
+	    switch (*buf) {
+	    case '*':
+		if (strnEQ(buf, "********", 8)) {
+		    if (repl_beginning && repl_could_be_missing) {
+			repl_missing = TRUE;
+			goto hunk_done;
+		    }
+		    else
+			fatal2("Unexpected end of hunk at line %ld.\n",
+			    p_input_line);
+		}
+		if (p_end != 0) {
+		    if (repl_beginning && repl_could_be_missing) {
+			repl_missing = TRUE;
+			goto hunk_done;
+		    }
+		    fatal3("Unexpected *** at line %ld: %s", p_input_line, buf);
+		}
+		context = 0;
+#ifdef SMALL
+		p_line[p_end] = saveStr(buf, p_len+p_end);
+#else
+		p_line[p_end] = savestr(buf);
+		if (out_of_mem) {
+		    p_end--;
+		    return FALSE;
+		}
+#endif
+		for (s=buf; *s && !isdigit(*s); s++) ;
+		if (!*s)
+		    goto malformed;
+		if (strnEQ(s,"0,0",3))
+		    strcpy(s,s+2);
+		p_first = (LINENUM) atol(s);
+		while (isdigit(*s)) s++;
+		if (*s == ',') {
+		    for (; *s && !isdigit(*s); s++) ;
+		    if (!*s)
+			goto malformed;
+		    p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1;
+		}
+		else if (p_first)
+		    p_ptrn_lines = 1;
+		else {
+		    p_ptrn_lines = 0;
+		    p_first = 1;
+		}
+		p_max = p_ptrn_lines + 6;	/* we need this much at least */
+		while (p_max >= hunkmax)
+		    grow_hunkmax();
+		p_max = hunkmax;
+		break;
+	    case '-':
+		if (buf[1] == '-') {
+		    if (repl_beginning ||
+			(p_end != p_ptrn_lines + 1 + (p_char[p_end-1] == '\n')))
+		    {
+			if (p_end == 1) {
+			    /* `old' lines were omitted - set up to fill */
+			    /* them in from 'new' context lines. */
+			    p_end = p_ptrn_lines + 1;
+			    fillsrc = p_end + 1;
+			    filldst = 1;
+			    fillcnt = p_ptrn_lines;
+			}
+			else {
+			    if (repl_beginning) {
+				if (repl_could_be_missing){
+				    repl_missing = TRUE;
+				    goto hunk_done;
+				}
+				fatal3(
+"Duplicate \"---\" at line %ld--check line numbers at line %ld.\n",
+				    p_input_line, p_hunk_beg + repl_beginning);
+			    }
+			    else {
+				fatal4(
+"%s \"---\" at line %ld--check line numbers at line %ld.\n",
+				    (p_end <= p_ptrn_lines
+					? "Premature"
+					: "Overdue" ),
+				    p_input_line, p_hunk_beg);
+			    }
+			}
+		    }
+		    repl_beginning = p_end;
+		    repl_backtrack_position = ftell(pfp);
+		    repl_patch_line = p_input_line;
+#ifdef SMALL
+		    p_line[p_end] = saveStr(buf, p_len+p_end);
+#else
+		    p_line[p_end] = savestr(buf);
+		    if (out_of_mem) {
+			p_end--;
+			return FALSE;
+		    }
+#endif
+		    p_char[p_end] = '=';
+		    for (s=buf; *s && !isdigit(*s); s++) ;
+		    if (!*s)
+			goto malformed;
+		    p_newfirst = (LINENUM) atol(s);
+		    while (isdigit(*s)) s++;
+		    if (*s == ',') {
+			for (; *s && !isdigit(*s); s++) ;
+			if (!*s)
+			    goto malformed;
+			p_repl_lines = ((LINENUM)atol(s)) - p_newfirst + 1;
+		    }
+		    else if (p_newfirst)
+			p_repl_lines = 1;
+		    else {
+			p_repl_lines = 0;
+			p_newfirst = 1;
+		    }
+		    p_max = p_repl_lines + p_end;
+		    if (p_max > MAXHUNKSIZE)
+			fatal4("Hunk too large (%ld lines) at line %ld: %s",
+			      p_max, p_input_line, buf);
+		    while (p_max >= hunkmax)
+			grow_hunkmax();
+		    if (p_repl_lines != ptrn_copiable)
+			repl_could_be_missing = FALSE;
+		    break;
+		}
+		goto change_line;
+	    case '+':  case '!':
+		repl_could_be_missing = FALSE;
+	      change_line:
+		if (buf[1] == '\n' && canonicalize)
+		    strcpy(buf+1," \n");
+		if (!isspace(buf[1]) && buf[1] != '>' && buf[1] != '<' &&
+		  repl_beginning && repl_could_be_missing) {
+		    repl_missing = TRUE;
+		    goto hunk_done;
+		}
+		if (context > 0) {
+		    if (context < p_context)
+			p_context = context;
+		    context = -1000;
+		}
+#ifdef SMALL
+		p_line[p_end] = saveStr(buf+2, p_len+p_end);
+#else
+		p_line[p_end] = savestr(buf+2);
+		if (out_of_mem) {
+		    p_end--;
+		    return FALSE;
+		}
+#endif
+		break;
+	    case '\t': case '\n':	/* assume the 2 spaces got eaten */
+		if (repl_beginning && repl_could_be_missing &&
+		  (!ptrn_spaces_eaten || diff_type == NEW_CONTEXT_DIFF) ) {
+		    repl_missing = TRUE;
+		    goto hunk_done;
+		}
+#ifdef SMALL
+		p_line[p_end] = saveStr(buf, p_len+p_end);
+#else
+		p_line[p_end] = savestr(buf);
+		if (out_of_mem) {
+		    p_end--;
+		    return FALSE;
+		}
+#endif
+		if (p_end != p_ptrn_lines + 1) {
+		    ptrn_spaces_eaten |= (repl_beginning != 0);
+		    context++;
+		    if (!repl_beginning)
+			ptrn_copiable++;
+		    p_char[p_end] = ' ';
+		}
+		break;
+	    case ' ':
+		if (!isspace(buf[1]) &&
+		  repl_beginning && repl_could_be_missing) {
+		    repl_missing = TRUE;
+		    goto hunk_done;
+		}
+		context++;
+		if (!repl_beginning)
+		    ptrn_copiable++;
+#ifdef SMALL
+		p_line[p_end] = saveStr(buf+2, p_len+p_end);
+#else
+		p_line[p_end] = savestr(buf+2);
+		if (out_of_mem) {
+		    p_end--;
+		    return FALSE;
+		}
+#endif
+		break;
+	    default:
+		if (repl_beginning && repl_could_be_missing) {
+		    repl_missing = TRUE;
+		    goto hunk_done;
+		}
+		goto malformed;
+	    }
+	    /* set up p_len for strncmp() so we don't have to */
+	    /* assume null termination */
+#ifndef SMALL
+	    if (p_line[p_end])
+		p_len[p_end] = strlen(p_line[p_end]);
+	    else
+		p_len[p_end] = 0;
+#endif
+	}
+	
+    hunk_done:
+	if (p_end >=0 && !repl_beginning)
+	    fatal2("No --- found in patch at line %ld\n", pch_hunk_beg());
+
+	if (repl_missing) {
+	    
+	    /* reset state back to just after --- */
+	    p_input_line = repl_patch_line;
+#ifndef SMALL
+	    for (p_end--; p_end > repl_beginning; p_end--)
+		free(p_line[p_end]);
+#endif
+	    Fseek(pfp, repl_backtrack_position, 0);
+	    
+	    /* redundant 'new' context lines were omitted - set */
+	    /* up to fill them in from the old file context */
+	    fillsrc = 1;
+	    filldst = repl_beginning+1;
+	    fillcnt = p_repl_lines;
+	    p_end = p_max;
+	}
+
+	if (diff_type == CONTEXT_DIFF &&
+	  (fillcnt || (p_first > 1 && ptrn_copiable > 2*p_context)) ) {
+	    if (verbose)
+		say4("%s\n%s\n%s\n",
+"(Fascinating--this is really a new-style context diff but without",
+"the telltale extra asterisks on the *** line that usually indicate",
+"the new style...)");
+	    diff_type = NEW_CONTEXT_DIFF;
+	}
+	
+	/* if there were omitted context lines, fill them in now */
+	if (fillcnt) {
+	    p_bfake = filldst;		/* remember where not to free() */
+	    p_efake = filldst + fillcnt - 1;
+	    while (fillcnt-- > 0) {
+		while (fillsrc <= p_end && p_char[fillsrc] != ' ')
+		    fillsrc++;
+		if (fillsrc > p_end)
+		    fatal2("Replacement text or line numbers mangled in hunk at line %ld\n",
+			p_hunk_beg);
+		p_line[filldst] = p_line[fillsrc];
+		p_char[filldst] = p_char[fillsrc];
+		p_len[filldst] = p_len[fillsrc];
+		fillsrc++; filldst++;
+	    }
+	    while (fillsrc <= p_end && fillsrc != repl_beginning &&
+	      p_char[fillsrc] != ' ')
+		fillsrc++;
+#ifdef DEBUGGING
+	    if (debug & 64)
+		printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n",
+		    fillsrc,filldst,repl_beginning,p_end+1);
+#endif
+	    assert(fillsrc==p_end+1 || fillsrc==repl_beginning);
+	    assert(filldst==p_end+1 || filldst==repl_beginning);
+	}
+    }
+    else {				/* normal diff--fake it up */
+	char hunk_type;
+	Reg3 int i;
+	LINENUM min, max;
+	long line_beginning = ftell(pfp);
+
+	p_context = 0;
+	ret = pgets(buf, sizeof buf, pfp);
+	p_input_line++;
+	if (ret == Nullch || !isdigit(*buf)) {
+	    next_intuit_at(line_beginning,p_input_line);
+	    return FALSE;
+	}
+	p_first = (LINENUM)atol(buf);
+	for (s=buf; isdigit(*s); s++) ;
+	if (*s == ',') {
+	    p_ptrn_lines = (LINENUM)atol(++s) - p_first + 1;
+	    while (isdigit(*s)) s++;
+	}
+	else
+	    p_ptrn_lines = (*s != 'a');
+	hunk_type = *s;
+	if (hunk_type == 'a')
+	    p_first++;			/* do append rather than insert */
+	min = (LINENUM)atol(++s);
+	for (; isdigit(*s); s++) ;
+	if (*s == ',')
+	    max = (LINENUM)atol(++s);
+	else
+	    max = min;
+	if (hunk_type == 'd')
+	    min++;
+	p_end = p_ptrn_lines + 1 + max - min + 1;
+	if (p_end > MAXHUNKSIZE)
+	    fatal4("Hunk too large (%ld lines) at line %ld: %s",
+		  p_end, p_input_line, buf);
+	while (p_end >= hunkmax)
+	    grow_hunkmax();
+	p_newfirst = min;
+	p_repl_lines = max - min + 1;
+	Sprintf(buf, "*** %ld,%ld\n", p_first, p_first + p_ptrn_lines - 1);
+#ifdef SMALL
+	p_line[0] = saveStr(buf, p_len);
+#else
+	p_line[0] = savestr(buf);
+	if (out_of_mem) {
+	    p_end = -1;
+	    return FALSE;
+	}
+#endif
+	p_char[0] = '*';
+	for (i=1; i<=p_ptrn_lines; i++) {
+	    ret = pgets(buf, sizeof buf, pfp);
+	    p_input_line++;
+	    if (ret == Nullch)
+		fatal2("Unexpected end of file in patch at line %ld.\n",
+		  p_input_line);
+	    if (*buf != '<')
+		fatal2("< expected at line %ld of patch.\n", p_input_line);
+#ifdef SMALL
+	    p_line[i] = saveStr(buf+2, p_len+i);
+#else
+	    p_line[i] = savestr(buf+2);
+	    if (out_of_mem) {
+		p_end = i-1;
+		return FALSE;
+	    }
+#endif
+#ifndef SMALL
+	    p_len[i] = strlen(p_line[i]);
+#endif
+	    p_char[i] = '-';
+	}
+	if (hunk_type == 'c') {
+	    ret = pgets(buf, sizeof buf, pfp);
+	    p_input_line++;
+	    if (ret == Nullch)
+		fatal2("Unexpected end of file in patch at line %ld.\n",
+		    p_input_line);
+	    if (*buf != '-')
+		fatal2("--- expected at line %ld of patch.\n", p_input_line);
+	}
+	Sprintf(buf, "--- %ld,%ld\n", min, max);
+#ifdef SMALL
+	p_line[i] = saveStr(buf, p_len+i);
+#else
+	p_line[i] = savestr(buf);
+	if (out_of_mem) {
+	    p_end = i-1;
+	    return FALSE;
+	}
+#endif
+	p_char[i] = '=';
+	for (i++; i<=p_end; i++) {
+	    ret = pgets(buf, sizeof buf, pfp);
+	    p_input_line++;
+	    if (ret == Nullch)
+		fatal2("Unexpected end of file in patch at line %ld.\n",
+		    p_input_line);
+	    if (*buf != '>')
+		fatal2("> expected at line %ld of patch.\n", p_input_line);
+#ifdef SMALL
+	    p_line[i] = saveStr(buf+2, p_len+i);
+#else
+	    p_line[i] = savestr(buf+2);
+	    if (out_of_mem) {
+		p_end = i-1;
+		return FALSE;
+	    }
+#endif
+#ifndef SMALL
+	    p_len[i] = strlen(p_line[i]);
+#endif
+	    p_char[i] = '+';
+	}
+    }
+    if (reverse)			/* backwards patch? */
+	if (!pch_swap())
+	    say1("Not enough memory to swap next hunk!\n");
+#ifdef SMALL
+    Fclose(sfp);
+    sfp = fopen(TMPSTRNAME, "r");
+#endif
+#ifdef DEBUGGING
+    if (debug & 2) {
+	int i;
+	char special;
+
+	for (i=0; i <= p_end; i++) {
+	    if (i == p_ptrn_lines)
+		special = '^';
+	    else
+		special = ' ';
+#ifdef SMALL
+	    fprintf(stderr, "%3d %c %c %s", i, p_char[i], special, pfetch(i));
+#else
+	    fprintf(stderr, "%3d %c %c %s", i, p_char[i], special, p_line[i]);
+#endif
+	    Fflush(stderr);
+	}
+    }
+#endif
+    if (p_end+1 < hunkmax)	/* paranoia reigns supreme... */
+	p_char[p_end+1] = '^';  /* add a stopper for apply_hunk */
+    return TRUE;
+
+malformed:
+#ifdef SMALL
+    Fclose(sfp);
+    sfp = Nullfp;
+#endif
+    fatal3("Malformed patch at line %ld: %s", p_input_line, buf);
+		/* about as informative as "Syntax error" in C */
+    return FALSE;	/* for lint */
+}
+
+/* Input a line from the patch file, worrying about indentation. */
+
+char *
+pgets(bf,sz,fp)
+char *bf;
+int sz;
+FILE *fp;
+{
+    char *ret = fgets(bf, sz, fp);
+    Reg1 char *s;
+    Reg2 int indent = 0;
+
+    if (p_indent && ret != Nullch) {
+	for (s=buf;
+	  indent < p_indent && (*s == ' ' || *s == '\t' || *s == 'X'); s++) {
+	    if (*s == '\t')
+		indent += 8 - (indent % 7);
+	    else
+		indent++;
+	}
+	if (buf != s)
+	    Strcpy(buf, s);
+    }
+    return ret;
+}
+
+/* Reverse the old and new portions of the current hunk. */
+
+bool
+pch_swap()
+{
+#ifdef SMALL
+    long *tp_line;		/* the text of the hunk */
+#else
+    char **tp_line;		/* the text of the hunk */
+#endif
+    short *tp_len;		/* length of each line */
+    char *tp_char;		/* +, -, and ! */
+    Reg1 LINENUM i;
+    Reg2 LINENUM n;
+    bool blankline = FALSE;
+    Reg3 char *s;
+
+    i = p_first;
+    p_first = p_newfirst;
+    p_newfirst = i;
+    
+    /* make a scratch copy */
+
+    tp_line = p_line;
+    tp_len = p_len;
+    tp_char = p_char;
+#ifdef SMALL
+    p_line = Null(long*);	/* force set_hunkmax to allocate again */
+#else
+    p_line = Null(char**);	/* force set_hunkmax to allocate again */
+#endif
+    p_len = Null(short*);
+    p_char = Nullch;
+    set_hunkmax();
+#ifdef SMALL
+    if (p_line == Null(long*) || p_len == Null(short*) || p_char == Nullch) {
+#else
+    if (p_line == Null(char**) || p_len == Null(short*) || p_char == Nullch) {
+#endif
+#ifndef lint
+#ifdef SMALL
+	if (p_line == Null(long*))
+#else
+	if (p_line == Null(char**))
+#endif
+	    free((char*)p_line);
+	p_line = tp_line;
+	if (p_len == Null(short*))
+	    free((char*)p_len);
+	p_len = tp_len;
+#endif
+	if (p_char == Nullch)
+	    free((char*)p_char);
+	p_char = tp_char;
+	return FALSE;		/* not enough memory to swap hunk! */
+    }
+
+    /* now turn the new into the old */
+
+    i = p_ptrn_lines + 1;
+    if (tp_char[i] == '\n') {		/* account for possible blank line */
+	blankline = TRUE;
+	i++;
+    }
+    if (p_efake >= 0) {			/* fix non-freeable ptr range */
+	if (p_efake <= i)
+	    n = p_end - i + 1;
+	else
+	    n = -i;
+	p_efake += n;
+	p_bfake += n;
+    }
+    for (n=0; i <= p_end; i++,n++) {
+	p_line[n] = tp_line[i];
+	p_char[n] = tp_char[i];
+	if (p_char[n] == '+')
+	    p_char[n] = '-';
+	p_len[n] = tp_len[i];
+    }
+    if (blankline) {
+	i = p_ptrn_lines + 1;
+	p_line[n] = tp_line[i];
+	p_char[n] = tp_char[i];
+	p_len[n] = tp_len[i];
+	n++;
+    }
+    assert(p_char[0] == '=');
+    p_char[0] = '*';
+#ifdef SMALL
+    strEdit(p_line[0], '*', '-');
+#else
+    for (s=p_line[0]; *s; s++)
+	if (*s == '-')
+	    *s = '*';
+#endif
+
+    /* now turn the old into the new */
+
+    assert(tp_char[0] == '*');
+    tp_char[0] = '=';
+#ifdef SMALL
+    strEdit(tp_line[0], '-', '*');
+#else
+    for (s=tp_line[0]; *s; s++)
+	if (*s == '*')
+	    *s = '-';
+#endif
+    for (i=0; n <= p_end; i++,n++) {
+	p_line[n] = tp_line[i];
+	p_char[n] = tp_char[i];
+	if (p_char[n] == '-')
+	    p_char[n] = '+';
+	p_len[n] = tp_len[i];
+    }
+    assert(i == p_ptrn_lines + 1);
+    i = p_ptrn_lines;
+    p_ptrn_lines = p_repl_lines;
+    p_repl_lines = i;
+#ifndef lint
+#ifdef SMALL
+    if (tp_line == Null(long*))
+#else
+    if (tp_line == Null(char**))
+#endif
+	free((char*)tp_line);
+    if (tp_len == Null(short*))
+	free((char*)tp_len);
+#endif
+    if (tp_char == Nullch)
+	free((char*)tp_char);
+    return TRUE;
+}
+
+/* Return the specified line position in the old file of the old context. */
+
+LINENUM
+pch_first()
+{
+    return p_first;
+}
+
+/* Return the number of lines of old context. */
+
+LINENUM
+pch_ptrn_lines()
+{
+    return p_ptrn_lines;
+}
+
+/* Return the probable line position in the new file of the first line. */
+
+LINENUM
+pch_newfirst()
+{
+    return p_newfirst;
+}
+
+/* Return the number of lines in the replacement text including context. */
+
+LINENUM
+pch_repl_lines()
+{
+    return p_repl_lines;
+}
+
+/* Return the number of lines in the whole hunk. */
+
+LINENUM
+pch_end()
+{
+    return p_end;
+}
+
+/* Return the number of context lines before the first changed line. */
+
+LINENUM
+pch_context()
+{
+    return p_context;
+}
+
+/* Return the length of a particular patch line. */
+
+short
+pch_line_len(line)
+LINENUM line;
+{
+    return p_len[line];
+}
+
+/* Return the control character (+, -, *, !, etc) for a patch line. */
+
+char
+pch_char(line)
+LINENUM line;
+{
+    return p_char[line];
+}
+
+/* Return a pointer to a particular patch line. */
+
+#ifdef SMALL
+long
+saveStr(str, plen)
+char *str;
+short *plen;
+{
+    long pos, ftell();
+    int len;
+
+    pos = ftell(sfp);
+    len = strlen(str);
+    fwrite(str, sizeof(char), len+1, sfp);
+    *plen = len;
+    return pos;
+}
+
+char *
+pfetch(line)
+LINENUM line;
+{
+    static char *s, strbuf[BUFSIZ];
+    int i, c;
+
+    if (p_line[line] == -1L)
+	return Nullch;
+    else {
+	Fseek(sfp, p_line[line], 0);
+	for (i = 0, s = strbuf;
+		i < BUFSIZ && (c = fgetc(sfp)) != EOF && c; i++)
+	    *s++ = c;
+	if (i == BUFSIZ)
+		fatal2("too long line (%.40s ..\n", strbuf);
+    }
+    *s = '\0';
+    return strbuf;
+}
+
+void
+strEdit(pos, to, from)
+long pos;
+int to, from;
+{
+    static char *s, strbuf[BUFSIZ];
+    int i, c;
+
+    if (pos != -1L) {
+	for (i = 0, s = strbuf;
+		i < BUFSIZ && (c = fgetc(sfp)) != EOF && c; i++)
+	    *s++ = c;
+	for (s = strbuf; *s; s++)
+	    if (*s == from)
+		*s = to;
+	fwrite(strbuf, sizeof(char), i+1, sfp);
+    }
+}
+#else
+char *
+pfetch(line)
+LINENUM line;
+{
+    return p_line[line];
+}
+#endif
+
+/* Return where in the patch file this hunk began, for error messages. */
+
+LINENUM
+pch_hunk_beg()
+{
+    return p_hunk_beg;
+}
+
+/* Apply an ed script by feeding ed itself. */
+
+void
+do_ed_script()
+{
+    Reg1 char *t;
+    Reg2 long beginning_of_this_line;
+    Reg3 bool this_line_is_command = FALSE;
+    Reg4 FILE *pipefp;
+
+    if (!skip_rest_of_patch) {
+	Unlink(TMPOUTNAME);
+	copy_file(filearg[0], TMPOUTNAME);
+	if (verbose)
+	    Sprintf(buf, "/bin/ed %s", TMPOUTNAME);
+	else
+	    Sprintf(buf, "/bin/ed - %s", TMPOUTNAME);
+	pipefp = popen(buf, "w");
+    }
+    for (;;) {
+	beginning_of_this_line = ftell(pfp);
+	if (pgets(buf, sizeof buf, pfp) == Nullch) {
+	    next_intuit_at(beginning_of_this_line,p_input_line);
+	    break;
+	}
+	p_input_line++;
+	for (t=buf; isdigit(*t) || *t == ','; t++) ;
+	this_line_is_command = (isdigit(*buf) &&
+	  (*t == 'd' || *t == 'c' || *t == 'a') );
+	if (this_line_is_command) {
+	    if (!skip_rest_of_patch)
+		fputs(buf, pipefp);
+	    if (*t != 'd') {
+		while (pgets(buf, sizeof buf, pfp) != Nullch) {
+		    p_input_line++;
+		    if (!skip_rest_of_patch)
+			fputs(buf, pipefp);
+		    if (strEQ(buf, ".\n"))
+			break;
+		}
+	    }
+	}
+	else {
+	    next_intuit_at(beginning_of_this_line,p_input_line);
+	    break;
+	}
+    }
+    if (skip_rest_of_patch)
+	return;
+    fprintf(pipefp, "w\n");
+    fprintf(pipefp, "q\n");
+    Fflush(pipefp);
+    Pclose(pipefp);
+    ignore_signals();
+    if (move_file(TMPOUTNAME, outname) < 0) {
+	toutkeep = TRUE;
+	chmod(TMPOUTNAME, filemode);
+    }
+    else
+	chmod(outname, filemode);
+    set_signals(1);
+}
Index: /trunk/minix/commands/patch/pch.h
===================================================================
--- /trunk/minix/commands/patch/pch.h	(revision 9)
+++ /trunk/minix/commands/patch/pch.h	(revision 9)
@@ -0,0 +1,48 @@
+/* $Header: /cvsup/minix/src/commands/patch/pch.h,v 1.1.1.1 2005/04/21 14:55:11 beng Exp $
+ *
+ * $Log: pch.h,v $
+ * Revision 1.1.1.1  2005/04/21 14:55:11  beng
+ * Initial import of pre-3.0.1
+ *
+ * Revision 1.1.1.1  2005/04/20 13:33:19  beng
+ * Initial import of minix 2.0.4
+ *
+ * Revision 2.0.1.1  87/01/30  22:47:16  lwall
+ * Added do_ed_script().
+ * 
+ * Revision 2.0  86/09/17  15:39:57  lwall
+ * Baseline for netwide release.
+ * 
+ */
+
+EXT FILE *pfp INIT(Nullfp);		/* patch file pointer */
+#ifdef SMALL
+EXT FILE *sfp INIT(Nullfp);		/* string file pointer */
+#endif
+
+_PROTOTYPE(void re_patch , (void));
+_PROTOTYPE(void open_patch_file , (char *filename ));
+_PROTOTYPE(void set_hunkmax , (void));
+_PROTOTYPE(void grow_hunkmax , (void));
+_PROTOTYPE(bool there_is_another_patch , (void));
+_PROTOTYPE(int intuit_diff_type , (void));
+_PROTOTYPE(void next_intuit_at , (long file_pos , long file_line ));
+_PROTOTYPE(void skip_to , (long file_pos , long file_line ));
+_PROTOTYPE(bool another_hunk , (void));
+_PROTOTYPE(char *pgets , (char *bf , int sz , FILE *fp ));
+_PROTOTYPE(bool pch_swap , (void));
+_PROTOTYPE(LINENUM pch_first , (void));
+_PROTOTYPE(LINENUM pch_ptrn_lines , (void));
+_PROTOTYPE(LINENUM pch_newfirst , (void));
+_PROTOTYPE(LINENUM pch_repl_lines , (void));
+_PROTOTYPE(LINENUM pch_end , (void));
+_PROTOTYPE(LINENUM pch_context , (void));
+_PROTOTYPE(short pch_line_len , (LINENUM line ));
+_PROTOTYPE(char pch_char , (LINENUM line ));
+_PROTOTYPE(char *pfetch , (LINENUM line ));
+_PROTOTYPE(LINENUM pch_hunk_beg , (void));
+_PROTOTYPE(void do_ed_script , (void));
+#ifdef SMALL
+_PROTOTYPE(long saveStr , (char *string , short *length ));
+_PROTOTYPE(void strEdit , (long pos , int from , int to ));
+#endif
Index: /trunk/minix/commands/patch/util.c
===================================================================
--- /trunk/minix/commands/patch/util.c	(revision 9)
+++ /trunk/minix/commands/patch/util.c	(revision 9)
@@ -0,0 +1,361 @@
+#include "EXTERN.h"
+#include "common.h"
+#include "INTERN.h"
+#include "util.h"
+
+/* Rename a file, copying it if necessary. */
+
+int
+move_file(from,to)
+char *from, *to;
+{
+    char bakname[512];
+    Reg1 char *s;
+    Reg2 int i;
+    Reg3 int fromfd;
+
+    /* to stdout? */
+
+    if (strEQ(to, "-")) {
+#ifdef DEBUGGING
+	if (debug & 4)
+	    say2("Moving %s to stdout.\n", from);
+#endif
+	fromfd = open(from, 0);
+	if (fromfd < 0)
+	    fatal2("patch: internal error, can't reopen %s\n", from);
+	while ((i=read(fromfd, buf, sizeof buf)) > 0)
+	    if (write(1, buf, i) != i)
+		fatal1("patch: write failed\n");
+	Close(fromfd);
+	return 0;
+    }
+
+	if (origprae) {
+		Strcpy (bakname, origprae);
+    	Strcat(bakname, to);
+	} else {
+   		Strcpy(bakname, to);
+    	Strcat(bakname, origext?origext:ORIGEXT);
+	}
+    if (stat(to, &filestat) >= 0) {	/* output file exists */
+	dev_t to_device = filestat.st_dev;
+	ino_t to_inode  = filestat.st_ino;
+	char *simplename = bakname;
+	
+	for (s=bakname; *s; s++) {
+	    if (*s == '/')
+		simplename = s+1;
+	}
+	/* find a backup name that is not the same file */
+	while (stat(bakname, &filestat) >= 0 &&
+		to_device == filestat.st_dev && to_inode == filestat.st_ino) {
+	    for (s=simplename; *s && !islower(*s); s++) ;
+	    if (*s)
+		*s = toupper(*s);
+	    else
+		Strcpy(simplename, simplename+1);
+	}
+	while (unlink(bakname) >= 0) ;	/* while() is for benefit of Eunice */
+#ifdef DEBUGGING
+	if (debug & 4)
+	    say3("Moving %s to %s.\n", to, bakname);
+#endif
+	if (link(to, bakname) < 0) {
+	    say3("patch: can't backup %s, output is in %s\n",
+		to, from);
+	    return -1;
+	}
+	while (unlink(to) >= 0) ;
+    }
+#ifdef DEBUGGING
+    if (debug & 4)
+	say3("Moving %s to %s.\n", from, to);
+#endif
+    if (link(from, to) < 0) {		/* different file system? */
+	Reg4 int tofd;
+	
+	tofd = creat(to, 0666);
+	if (tofd < 0) {
+	    say3("patch: can't create %s, output is in %s.\n",
+	      to, from);
+	    return -1;
+	}
+	fromfd = open(from, 0);
+	if (fromfd < 0)
+	    fatal2("patch: internal error, can't reopen %s\n", from);
+	while ((i=read(fromfd, buf, sizeof buf)) > 0)
+	    if (write(tofd, buf, i) != i)
+		fatal1("patch: write failed\n");
+	Close(fromfd);
+	Close(tofd);
+    }
+    Unlink(from);
+    return 0;
+}
+
+/* Copy a file. */
+
+void
+copy_file(from,to)
+char *from, *to;
+{
+    Reg3 int tofd;
+    Reg2 int fromfd;
+    Reg1 int i;
+    
+    tofd = creat(to, 0666);
+    if (tofd < 0)
+	fatal2("patch: can't create %s.\n", to);
+    fromfd = open(from, 0);
+    if (fromfd < 0)
+	fatal2("patch: internal error, can't reopen %s\n", from);
+    while ((i=read(fromfd, buf, sizeof buf)) > 0)
+	if (write(tofd, buf, i) != i)
+	    fatal2("patch: write (%s) failed\n", to);
+    Close(fromfd);
+    Close(tofd);
+}
+
+/* Allocate a unique area for a string. */
+
+char *
+savestr(s)
+Reg1 char *s;
+{
+    Reg3 char *rv;
+    Reg2 char *t;
+
+    if (!s)
+	s = "Oops";
+    t = s;
+    while (*t++);
+    rv = (char *)malloc((MEM) (t - s));
+    if (rv == Nullch) {
+	if (using_plan_a)
+	    out_of_mem = TRUE;
+	else
+	    fatal1("patch: out of memory (savestr)\n");
+    }
+    else {
+	t = rv;
+	while (*t++ = *s++);
+    }
+    return rv;
+}
+
+#if defined(lint) && defined(CANVARARG)
+
+/*VARARGS ARGSUSED*/
+say(pat) char *pat; { ; }
+/*VARARGS ARGSUSED*/
+fatal(pat) char *pat; { ; }
+/*VARARGS ARGSUSED*/
+ask(pat) char *pat; { ; }
+
+#else
+
+/* Vanilla terminal output (buffered). */
+
+void
+say(pat,arg1,arg2,arg3)
+char *pat;
+long arg1,arg2,arg3;
+{
+    fprintf(stderr, pat, arg1, arg2, arg3);
+    Fflush(stderr);
+}
+
+/* Terminal output, pun intended. */
+
+void				/* very void */
+fatal(pat,arg1,arg2,arg3)
+char *pat;
+long arg1,arg2,arg3;
+{
+    say(pat, arg1, arg2, arg3);
+    my_exit(1);
+}
+
+/* Get a response from the user, somehow or other. */
+
+void
+ask(pat,arg1,arg2,arg3)
+char *pat;
+long arg1,arg2,arg3;
+{
+    int ttyfd;
+    int r;
+    bool tty2 = isatty(2);
+
+    Sprintf(buf, pat, arg1, arg2, arg3);
+    Fflush(stderr);
+    write(2, buf, strlen(buf));
+    if (tty2) {				/* might be redirected to a file */
+	r = read(2, buf, sizeof buf);
+    }
+    else if (isatty(1)) {		/* this may be new file output */
+	Fflush(stdout);
+	write(1, buf, strlen(buf));
+	r = read(1, buf, sizeof buf);
+    }
+    else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
+					/* might be deleted or unwriteable */
+	write(ttyfd, buf, strlen(buf));
+	r = read(ttyfd, buf, sizeof buf);
+	Close(ttyfd);
+    }
+    else if (isatty(0)) {		/* this is probably patch input */
+	Fflush(stdin);
+	write(0, buf, strlen(buf));
+	r = read(0, buf, sizeof buf);
+    }
+    else {				/* no terminal at all--default it */
+	buf[0] = '\n';
+	r = 1;
+    }
+    if (r <= 0)
+	buf[0] = 0;
+    else
+	buf[r] = '\0';
+    if (!tty2)
+	say1(buf);
+}
+#endif /* lint */
+
+/* How to handle certain events when not in a critical region. */
+
+void
+set_signals(reset)
+int reset;
+{
+#ifndef lint
+#ifdef VOIDSIG
+    static void (*hupval)(),(*intval)();
+#else
+    static int (*hupval)(),(*intval)();
+#endif
+
+    if (!reset) {
+	hupval = signal(SIGHUP, SIG_IGN);
+	if (hupval != SIG_IGN)
+#ifdef VOIDSIG
+	    hupval = my_exit;
+#else
+	    hupval = (int(*)())my_exit;
+#endif
+	intval = signal(SIGINT, SIG_IGN);
+	if (intval != SIG_IGN)
+#ifdef VOIDSIG
+	    intval = my_exit;
+#else
+	    intval = (int(*)())my_exit;
+#endif
+    }
+    Signal(SIGHUP, hupval);
+    Signal(SIGINT, intval);
+#endif
+}
+
+/* How to handle certain events when in a critical region. */
+
+void
+ignore_signals()
+{
+#ifndef lint
+    Signal(SIGHUP, SIG_IGN);
+    Signal(SIGINT, SIG_IGN);
+#endif
+}
+
+/* Make sure we'll have the directories to create a file. */
+
+void
+makedirs(filename,striplast)
+Reg1 char *filename;
+bool striplast;
+{
+    char tmpbuf[256];
+    Reg2 char *s = tmpbuf;
+    char *dirv[20];
+    Reg3 int i;
+    Reg4 int dirvp = 0;
+
+    while (*filename) {
+	if (*filename == '/') {
+	    filename++;
+	    dirv[dirvp++] = s;
+	    *s++ = '\0';
+	}
+	else {
+	    *s++ = *filename++;
+	}
+    }
+    *s = '\0';
+    dirv[dirvp] = s;
+    if (striplast)
+	dirvp--;
+    if (dirvp < 0)
+	return;
+    strcpy(buf, "mkdir");
+    s = buf;
+    for (i=0; i<=dirvp; i++) {
+	while (*s) s++;
+	*s++ = ' ';
+	strcpy(s, tmpbuf);
+	*dirv[i] = '/';
+    }
+    system(buf);
+}
+
+/* Make filenames more reasonable. */
+
+char *
+fetchname(at,strip_leading,assume_exists)
+char *at;
+int strip_leading;
+int assume_exists;
+{
+    char *s;
+    char *name;
+    Reg1 char *t;
+    char tmpbuf[200];
+
+    if (!at)
+	return Nullch;
+    s = savestr(at);
+    for (t=s; isspace(*t); t++) ;
+    name = t;
+#ifdef DEBUGGING
+    if (debug & 128)
+	say4("fetchname %s %d %d\n",name,strip_leading,assume_exists);
+#endif
+    if (strnEQ(name, "/dev/null", 9))	/* so files can be created by diffing */
+	return Nullch;			/*   against /dev/null. */
+    for (; *t && !isspace(*t); t++)
+	if (*t == '/')
+	    if (--strip_leading >= 0)
+		name = t+1;
+    *t = '\0';
+    if (name != s && *s != '/') {
+	name[-1] = '\0';
+	if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) {
+	    name[-1] = '/';
+	    name=s;
+	}
+    }
+    name = savestr(name);
+    Sprintf(tmpbuf, "RCS/%s", name);
+    free(s);
+    if (stat(name, &filestat) < 0 && !assume_exists) {
+	Strcat(tmpbuf, RCSSUFFIX);
+	if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) {
+	    Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name);
+	    if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) {
+		free(name);
+		name = Nullch;
+	    }
+	}
+    }
+    return name;
+}
Index: /trunk/minix/commands/patch/util.h
===================================================================
--- /trunk/minix/commands/patch/util.h	(revision 9)
+++ /trunk/minix/commands/patch/util.h	(revision 9)
@@ -0,0 +1,80 @@
+/* $Header: /cvsup/minix/src/commands/patch/util.h,v 1.1.1.1 2005/04/21 14:55:11 beng Exp $
+ *
+ * $Log: util.h,v $
+ * Revision 1.1.1.1  2005/04/21 14:55:11  beng
+ * Initial import of pre-3.0.1
+ *
+ * Revision 1.1.1.1  2005/04/20 13:33:20  beng
+ * Initial import of minix 2.0.4
+ *
+ * Revision 2.0  86/09/17  15:40:06  lwall
+ * Baseline for netwide release.
+ * 
+ */
+
+/* and for those machine that can't handle a variable argument list */
+
+#ifdef CANVARARG
+
+#define say1 say
+#define say2 say
+#define say3 say
+#define say4 say
+#define ask1 ask
+#define ask2 ask
+#define ask3 ask
+#define ask4 ask
+#define fatal1 fatal
+#define fatal2 fatal
+#define fatal3 fatal
+#define fatal4 fatal
+
+#else /* hope they allow multi-line macro actual arguments */
+
+#ifdef lint
+
+#define say1(a) say(a, 0, 0, 0)
+#define say2(a,b) say(a, (b)==(b), 0, 0)
+#define say3(a,b,c) say(a, (b)==(b), (c)==(c), 0)
+#define say4(a,b,c,d) say(a, (b)==(b), (c)==(c), (d)==(d))
+#define ask1(a) ask(a, 0, 0, 0)
+#define ask2(a,b) ask(a, (b)==(b), 0, 0)
+#define ask3(a,b,c) ask(a, (b)==(b), (c)==(c), 0)
+#define ask4(a,b,c,d) ask(a, (b)==(b), (c)==(c), (d)==(d))
+#define fatal1(a) fatal(a, 0, 0, 0)
+#define fatal2(a,b) fatal(a, (b)==(b), 0, 0)
+#define fatal3(a,b,c) fatal(a, (b)==(b), (c)==(c), 0)
+#define fatal4(a,b,c,d) fatal(a, (b)==(b), (c)==(c), (d)==(d))
+
+#else /* lint */
+    /* if this doesn't work, try defining CANVARARG above */
+#define say1(a) say(a, Nullch, Nullch, Nullch)
+#define say2(a,b) say(a, b, Nullch, Nullch)
+#define say3(a,b,c) say(a, b, c, Nullch)
+#define say4 say
+#define ask1(a) ask(a, Nullch, Nullch, Nullch)
+#define ask2(a,b) ask(a, b, Nullch, Nullch)
+#define ask3(a,b,c) ask(a, b, c, Nullch)
+#define ask4 ask
+#define fatal1(a) fatal(a, Nullch, Nullch, Nullch)
+#define fatal2(a,b) fatal(a, b, Nullch, Nullch)
+#define fatal3(a,b,c) fatal(a, b, c, Nullch)
+#define fatal4 fatal
+
+#endif /* lint */
+
+/* if neither of the above work, join all multi-line macro calls. */
+#endif
+
+EXT char serrbuf[BUFSIZ];		/* buffer for stderr */
+
+_PROTOTYPE(int move_file , (char *from , char *to ));
+_PROTOTYPE(void copy_file , (char *from , char *to ));
+_PROTOTYPE(char *savestr , (Reg1 char *s ));
+void say();
+void fatal();
+void ask();
+_PROTOTYPE(void set_signals , (int reset ));
+_PROTOTYPE(void ignore_signals , (void));
+_PROTOTYPE(void makedirs , (Reg1 char *filename , bool striplast ));
+_PROTOTYPE(char *fetchname , (char *at , int strip_leading , int assume_exists ));
Index: /trunk/minix/commands/patch/version.c
===================================================================
--- /trunk/minix/commands/patch/version.c	(revision 9)
+++ /trunk/minix/commands/patch/version.c	(revision 9)
@@ -0,0 +1,34 @@
+/* $Header: /cvsup/minix/src/commands/patch/version.c,v 1.1.1.1 2005/04/21 14:55:11 beng Exp $
+ *
+ * $Log: version.c,v $
+ * Revision 1.1.1.1  2005/04/21 14:55:11  beng
+ * Initial import of pre-3.0.1
+ *
+ * Revision 1.1.1.1  2005/04/20 13:33:20  beng
+ * Initial import of minix 2.0.4
+ *
+ * Revision 2.0  86/09/17  15:40:11  lwall
+ * Baseline for netwide release.
+ * 
+ */
+
+#include "EXTERN.h"
+#include "common.h"
+#include "util.h"
+#include "INTERN.h"
+#include "patchlevel.h"
+#include "version.h"
+
+/* Print out the version number and die. */
+
+void
+version()
+{
+    extern char rcsid[];
+
+#ifdef lint
+    rcsid[0] = rcsid[0];
+#else
+    fatal3("%s\nPatch level: %d\n", rcsid, PATCHLEVEL);
+#endif
+}
Index: /trunk/minix/commands/patch/version.h
===================================================================
--- /trunk/minix/commands/patch/version.h	(revision 9)
+++ /trunk/minix/commands/patch/version.h	(revision 9)
@@ -0,0 +1,15 @@
+/* $Header: /cvsup/minix/src/commands/patch/version.h,v 1.1.1.1 2005/04/21 14:55:11 beng Exp $
+ *
+ * $Log: version.h,v $
+ * Revision 1.1.1.1  2005/04/21 14:55:11  beng
+ * Initial import of pre-3.0.1
+ *
+ * Revision 1.1.1.1  2005/04/20 13:33:20  beng
+ * Initial import of minix 2.0.4
+ *
+ * Revision 2.0  86/09/17  15:40:14  lwall
+ * Baseline for netwide release.
+ * 
+ */
+
+_PROTOTYPE(void version , (void));
Index: /trunk/minix/commands/pax/Makefile
===================================================================
--- /trunk/minix/commands/pax/Makefile	(revision 9)
+++ /trunk/minix/commands/pax/Makefile	(revision 9)
@@ -0,0 +1,21 @@
+# Makefile for pax
+
+CC = exec cc
+CFLAGS = -O -D_POSIX_SOURCE -DNET2_STAT=1 -D_MINIX=1
+LDFLAGS= -i
+
+all:	pax
+
+OBJ = ar_io.o ar_subs.o buf_subs.o cache.o cpio.o file_subs.o ftree.o \
+gen_subs.o getoldopt.o options.o pat_rep.o pax.o sel_subs.o \
+tables.o tar.o tty_subs.o fgetln.o
+
+pax:	$(OBJ)
+	$(CC) $(LDFLAGS) -o $@ $(OBJ)
+	install -S 256k $@
+
+install: pax
+	install -cs -o bin pax /usr/bin/pax
+
+clean:	
+	rm -f *.o *.bak core pax
Index: /trunk/minix/commands/pax/ar_io.c
===================================================================
--- /trunk/minix/commands/pax/ar_io.c	(revision 9)
+++ /trunk/minix/commands/pax/ar_io.c	(revision 9)
@@ -0,0 +1,1298 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)ar_io.c	8.2 (Berkeley) 4/18/94";
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mtio.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "pax.h"
+#include "options.h"
+#include "extern.h"
+
+/*
+ * Routines which deal directly with the archive I/O device/file.
+ */
+
+#define DMOD		0666		/* default mode of created archives */
+#define EXT_MODE	O_RDONLY	/* open mode for list/extract */
+#define AR_MODE		(O_WRONLY | O_CREAT | O_TRUNC)	/* mode for archive */
+#define APP_MODE	O_RDWR		/* mode for append */
+
+static char none[] = "<NONE>";		/* pseudo name for no file */
+static char stdo[] = "<STDOUT>";	/* pseudo name for stdout */
+static char stdn[] = "<STDIN>";		/* pseudo name for stdin */
+static int arfd = -1;			/* archive file descriptor */
+static int artyp = ISREG;		/* archive type: file/FIFO/tape */
+static int arvol = 1;			/* archive volume number */
+static int lstrval = -1;		/* return value from last i/o */
+static int io_ok;			/* i/o worked on volume after resync */
+static int did_io;			/* did i/o ever occur on volume? */
+static int done;			/* set via tty termination */
+static struct stat arsb;		/* stat of archive device at open */
+static int invld_rec;			/* tape has out of spec record size */
+static int wr_trail = 1;		/* trailer was rewritten in append */
+static int can_unlnk = 0;		/* do we unlink null archives?  */
+const char *arcname;		  	/* printable name of archive */
+const char *gzip_program;		/* name of gzip program */
+static pid_t zpid = -1;			/* pid of child process */
+
+static int get_phys(void);
+extern sigset_t s_mask;
+static void ar_start_gzip(int, const char *, int);
+
+/*
+ * ar_open()
+ *	Opens the next archive volume. Determines the type of the device and
+ *	sets up block sizes as required by the archive device and the format.
+ *	Note: we may be called with name == NULL on the first open only.
+ * Return:
+ *	-1 on failure, 0 otherwise
+ */
+
+int
+ar_open(const char *name)
+{
+	struct mtget mb;
+
+	if (arfd != -1)
+		(void)close(arfd);
+	arfd = -1;
+	can_unlnk = did_io = io_ok = invld_rec = 0;
+	artyp = ISREG;
+	flcnt = 0;
+
+	/*
+	 * open based on overall operation mode
+	 */
+	switch (act) {
+	case LIST:
+	case EXTRACT:
+		if (name == NULL) {
+			arfd = STDIN_FILENO;
+			arcname = stdn;
+		} else if ((arfd = open(name, EXT_MODE, DMOD)) < 0)
+			syswarn(0, errno, "Failed open to read on %s", name);
+		if (arfd != -1 && gzip_program != NULL)
+			ar_start_gzip(arfd, gzip_program, 0);
+		break;
+	case ARCHIVE:
+		if (name == NULL) {
+			arfd = STDOUT_FILENO;
+			arcname = stdo;
+		} else if ((arfd = open(name, AR_MODE, DMOD)) < 0)
+			syswarn(0, errno, "Failed open to write on %s", name);
+		else
+			can_unlnk = 1;
+		if (arfd != -1 && gzip_program != NULL)
+			ar_start_gzip(arfd, gzip_program, 1);
+		break;
+	case APPND:
+		if (name == NULL) {
+			arfd = STDOUT_FILENO;
+			arcname = stdo;
+		} else if ((arfd = open(name, APP_MODE, DMOD)) < 0)
+			syswarn(0, errno, "Failed open to read/write on %s",
+				name);
+		break;
+	case COPY:
+		/*
+		 * arfd not used in COPY mode
+		 */
+		arcname = none;
+		lstrval = 1;
+		return(0);
+	}
+	if (arfd < 0)
+		return(-1);
+
+	if (chdname != NULL)
+		if (chdir(chdname) != 0) {
+			syswarn(1, errno, "Failed chdir to %s", chdname);
+			return(-1);
+		}
+	/*
+	 * set up is based on device type
+	 */
+	if (fstat(arfd, &arsb) < 0) {
+		syswarn(0, errno, "Failed stat on %s", arcname);
+		(void)close(arfd);
+		arfd = -1;
+		can_unlnk = 0;
+		return(-1);
+	}
+	if (S_ISDIR(arsb.st_mode)) {
+		paxwarn(0, "Cannot write an archive on top of a directory %s",
+		    arcname);
+		(void)close(arfd);
+		arfd = -1;
+		can_unlnk = 0;
+		return(-1);
+	}
+
+	if (S_ISCHR(arsb.st_mode))
+		artyp = ioctl(arfd, MTIOCGET, &mb) ? ISCHR : ISTAPE;
+	else if (S_ISBLK(arsb.st_mode))
+		artyp = ISBLK;
+	else if ((lseek(arfd, (off_t)0L, SEEK_CUR) == -1) && (errno == ESPIPE))
+		artyp = ISPIPE;
+	else
+		artyp = ISREG;
+
+	/*
+	 * make sure we beyond any doubt that we only can unlink regular files
+	 * we created
+	 */
+	if (artyp != ISREG)
+		can_unlnk = 0;
+	/*
+	 * if we are writing, we are done
+	 */
+	if (act == ARCHIVE) {
+		blksz = rdblksz = wrblksz;
+		lstrval = 1;
+		return(0);
+	}
+
+	/*
+	 * set default blksz on read. APPNDs writes rdblksz on the last volume
+	 * On all new archive volumes, we shift to wrblksz (if the user
+	 * specified one, otherwize we will continue to use rdblksz). We
+	 * must to set blocksize based on what kind of device the archive is
+	 * stored.
+	 */
+	switch(artyp) {
+	case ISTAPE:
+		/*
+		 * Tape drives come in at least two flavors. Those that support
+		 * variable sized records and those that have fixed sized
+		 * records. They must be treated differently. For tape drives
+		 * that support variable sized records, we must make large
+		 * reads to make sure we get the entire record, otherwise we
+		 * will just get the first part of the record (up to size we
+		 * asked). Tapes with fixed sized records may or may not return
+		 * multiple records in a single read. We really do not care
+		 * what the physical record size is UNLESS we are going to
+		 * append. (We will need the physical block size to rewrite
+		 * the trailer). Only when we are appending do we go to the
+		 * effort to figure out the true PHYSICAL record size.
+		 */
+		blksz = rdblksz = MAXBLK;
+		break;
+	case ISPIPE:
+	case ISBLK:
+	case ISCHR:
+		/*
+		 * Blocksize is not a major issue with these devices (but must
+		 * be kept a multiple of 512). If the user specified a write
+		 * block size, we use that to read. Under append, we must
+		 * always keep blksz == rdblksz. Otherwise we go ahead and use
+		 * the device optimal blocksize as (and if) returned by stat
+		 * and if it is within pax specs.
+		 */
+		if ((act == APPND) && wrblksz) {
+			blksz = rdblksz = wrblksz;
+			break;
+		}
+
+#if 0	/* Not on minix */
+		if ((arsb.st_blksize > 0) && (arsb.st_blksize < MAXBLK) &&
+		    ((arsb.st_blksize % BLKMULT) == 0))
+			rdblksz = arsb.st_blksize;
+		else
+#endif
+			rdblksz = DEVBLK;
+		/*
+		 * For performance go for large reads when we can without harm
+		 */
+		if ((act == APPND) || (artyp == ISCHR))
+			blksz = rdblksz;
+		else
+			blksz = MAXBLK;
+		break;
+	case ISREG:
+		/*
+		 * if the user specified wrblksz works, use it. Under appends
+		 * we must always keep blksz == rdblksz
+		 */
+		if ((act == APPND) && wrblksz && ((arsb.st_size%wrblksz)==0)){
+			blksz = rdblksz = wrblksz;
+			break;
+		}
+		/*
+		 * See if we can find the blocking factor from the file size
+		 */
+		for (rdblksz = MAXBLK; rdblksz > 0; rdblksz -= BLKMULT)
+			if ((arsb.st_size % rdblksz) == 0)
+				break;
+		/*
+		 * When we cannot find a match, we may have a flawed archive.
+		 */
+		if (rdblksz <= 0)
+			rdblksz = FILEBLK;
+		/*
+		 * for performance go for large reads when we can
+		 */
+		if (act == APPND)
+			blksz = rdblksz;
+		else
+			blksz = MAXBLK;
+		break;
+	default:
+		/*
+		 * should never happen, worse case, slow...
+		 */
+		blksz = rdblksz = BLKMULT;
+		break;
+	}
+	lstrval = 1;
+	return(0);
+}
+
+/*
+ * ar_close()
+ *	closes archive device, increments volume number, and prints i/o summary
+ */
+void
+ar_close(void)
+{
+	int status;
+
+	if (arfd < 0) {
+		did_io = io_ok = flcnt = 0;
+		return;
+	}
+
+	/*
+	 * Close archive file. This may take a LONG while on tapes (we may be
+	 * forced to wait for the rewind to complete) so tell the user what is
+	 * going on (this avoids the user hitting control-c thinking pax is
+	 * broken).
+	 */
+	if (vflag && (artyp == ISTAPE)) {
+		if (vfpart)
+			(void)putc('\n', listf);
+		(void)fprintf(listf,
+			"%s: Waiting for tape drive close to complete...",
+			argv0);
+		(void)fflush(listf);
+	}
+
+	/*
+	 * if nothing was written to the archive (and we created it), we remove
+	 * it
+	 */
+	if (can_unlnk && (fstat(arfd, &arsb) == 0) && (S_ISREG(arsb.st_mode)) &&
+	    (arsb.st_size == 0)) {
+		(void)unlink(arcname);
+		can_unlnk = 0;
+	}
+
+	/*
+	 * for a quick extract/list, pax frequently exits before the child
+	 * process is done
+	 */
+	if ((act == LIST || act == EXTRACT) && nflag && zpid > 0)
+		kill(zpid, SIGINT);
+
+	(void)close(arfd);
+
+	/* Do not exit before child to ensure data integrity */
+	if (zpid > 0)
+		waitpid(zpid, &status, 0);
+
+	if (vflag && (artyp == ISTAPE)) {
+		(void)fputs("done.\n", listf);
+		vfpart = 0;
+		(void)fflush(listf);
+	}
+	arfd = -1;
+
+	if (!io_ok && !did_io) {
+		flcnt = 0;
+		return;
+	}
+	did_io = io_ok = 0;
+
+	/*
+	 * The volume number is only increased when the last device has data
+	 * and we have already determined the archive format.
+	 */
+	if (frmt != NULL)
+		++arvol;
+
+	if (!vflag) {
+		flcnt = 0;
+		return;
+	}
+
+	/*
+	 * Print out a summary of I/O for this archive volume.
+	 */
+	if (vfpart) {
+		(void)putc('\n', listf);
+		vfpart = 0;
+	}
+
+	/*
+	 * If we have not determined the format yet, we just say how many bytes
+	 * we have skipped over looking for a header to id. there is no way we
+	 * could have written anything yet.
+	 */
+	if (frmt == NULL) {
+#	ifdef NET2_STAT
+		(void)fprintf(listf, "%s: unknown format, %lu bytes skipped.\n",
+		    argv0, rdcnt);
+#	else
+		(void)fprintf(listf, "%s: unknown format, %ju bytes skipped.\n",
+		    argv0, (uintmax_t)rdcnt);
+#	endif
+		(void)fflush(listf);
+		flcnt = 0;
+		return;
+	}
+
+	if (strcmp(NM_CPIO, argv0) == 0)
+		(void)fprintf(listf, "%llu blocks\n",
+		    (unsigned long)((rdcnt ? rdcnt : wrcnt) / 5120));
+	else if (strcmp(NM_TAR, argv0) != 0)
+		(void)fprintf(listf,
+#	ifdef NET2_STAT
+		    "%s: %s vol %d, %lu files, %lu bytes read, %lu bytes written.\n",
+		    argv0, frmt->name, arvol-1, flcnt, rdcnt, wrcnt);
+#	else
+		    "%s: %s vol %d, %ju files, %ju bytes read, %ju bytes written.\n",
+		    argv0, frmt->name, arvol-1, (uintmax_t)flcnt,
+		    (uintmax_t)rdcnt, (uintmax_t)wrcnt);
+#	endif
+	(void)fflush(listf);
+	flcnt = 0;
+}
+
+/*
+ * ar_drain()
+ *	drain any archive format independent padding from an archive read
+ *	from a socket or a pipe. This is to prevent the process on the
+ *	other side of the pipe from getting a SIGPIPE (pax will stop
+ *	reading an archive once a format dependent trailer is detected).
+ */
+void
+ar_drain(void)
+{
+	int res;
+	char drbuf[MAXBLK];
+
+	/*
+	 * we only drain from a pipe/socket. Other devices can be closed
+	 * without reading up to end of file. We sure hope that pipe is closed
+	 * on the other side so we will get an EOF.
+	 */
+	if ((artyp != ISPIPE) || (lstrval <= 0))
+		return;
+
+	/*
+	 * keep reading until pipe is drained
+	 */
+	while ((res = read(arfd, drbuf, sizeof(drbuf))) > 0)
+		;
+	lstrval = res;
+}
+
+/*
+ * ar_set_wr()
+ *	Set up device right before switching from read to write in an append.
+ *	device dependent code (if required) to do this should be added here.
+ *	For all archive devices we are already positioned at the place we want
+ *	to start writing when this routine is called.
+ * Return:
+ *	0 if all ready to write, -1 otherwise
+ */
+
+int
+ar_set_wr(void)
+{
+	off_t cpos;
+
+	/*
+	 * we must make sure the trailer is rewritten on append, ar_next()
+	 * will stop us if the archive containing the trailer was not written
+	 */
+	wr_trail = 0;
+
+	/*
+	 * Add any device dependent code as required here
+	 */
+	if (artyp != ISREG)
+		return(0);
+	/*
+	 * Ok we have an archive in a regular file. If we were rewriting a
+	 * file, we must get rid of all the stuff after the current offset
+	 * (it was not written by pax).
+	 */
+	if (((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) ||
+	    (ftruncate(arfd, cpos) < 0)) {
+		syswarn(1, errno, "Unable to truncate archive file");
+		return(-1);
+	}
+	return(0);
+}
+
+/*
+ * ar_app_ok()
+ *	check if the last volume in the archive allows appends. We cannot check
+ *	this until we are ready to write since there is no spec that says all
+ *	volumes in a single archive have to be of the same type...
+ * Return:
+ *	0 if we can append, -1 otherwise.
+ */
+
+int
+ar_app_ok(void)
+{
+	if (artyp == ISPIPE) {
+		paxwarn(1, "Cannot append to an archive obtained from a pipe.");
+		return(-1);
+	}
+
+	if (!invld_rec)
+		return(0);
+	paxwarn(1,"Cannot append, device record size %d does not support %s spec",
+		rdblksz, argv0);
+	return(-1);
+}
+
+/*
+ * ar_read()
+ *	read up to a specified number of bytes from the archive into the
+ *	supplied buffer. When dealing with tapes we may not always be able to
+ *	read what we want.
+ * Return:
+ *	Number of bytes in buffer. 0 for end of file, -1 for a read error.
+ */
+
+int
+ar_read(char *buf, int cnt)
+{
+	int res = 0;
+
+	/*
+	 * if last i/o was in error, no more reads until reset or new volume
+	 */
+	if (lstrval <= 0)
+		return(lstrval);
+
+	/*
+	 * how we read must be based on device type
+	 */
+	switch (artyp) {
+	case ISTAPE:
+		if ((res = read(arfd, buf, cnt)) > 0) {
+			/*
+			 * CAUTION: tape systems may not always return the same
+			 * sized records so we leave blksz == MAXBLK. The
+			 * physical record size that a tape drive supports is
+			 * very hard to determine in a uniform and portable
+			 * manner.
+			 */
+			io_ok = 1;
+			if (res != rdblksz) {
+				/*
+				 * Record size changed. If this is happens on
+				 * any record after the first, we probably have
+				 * a tape drive which has a fixed record size
+				 * we are getting multiple records in a single
+				 * read). Watch out for record blocking that
+				 * violates pax spec (must be a multiple of
+				 * BLKMULT).
+				 */
+				rdblksz = res;
+				if (rdblksz % BLKMULT)
+					invld_rec = 1;
+			}
+			return(res);
+		}
+		break;
+	case ISREG:
+	case ISBLK:
+	case ISCHR:
+	case ISPIPE:
+	default:
+		/*
+		 * Files are so easy to deal with. These other things cannot
+		 * be trusted at all. So when we are dealing with character
+		 * devices and pipes we just take what they have ready for us
+		 * and return. Trying to do anything else with them runs the
+		 * risk of failure.
+		 */
+		if ((res = read(arfd, buf, cnt)) > 0) {
+			io_ok = 1;
+			return(res);
+		}
+		break;
+	}
+
+	/*
+	 * We are in trouble at this point, something is broken...
+	 */
+	lstrval = res;
+	if (res < 0)
+		syswarn(1, errno, "Failed read on archive volume %d", arvol);
+	else
+		paxwarn(0, "End of archive volume %d reached", arvol);
+	return(res);
+}
+
+/*
+ * ar_write()
+ *	Write a specified number of bytes in supplied buffer to the archive
+ *	device so it appears as a single "block". Deals with errors and tries
+ *	to recover when faced with short writes.
+ * Return:
+ *	Number of bytes written. 0 indicates end of volume reached and with no
+ *	flaws (as best that can be detected). A -1 indicates an unrecoverable
+ *	error in the archive occured.
+ */
+
+int
+ar_write(char *buf, int bsz)
+{
+	int res;
+	off_t cpos;
+
+	/*
+	 * do not allow pax to create a "bad" archive. Once a write fails on
+	 * an archive volume prevent further writes to it.
+	 */
+	if (lstrval <= 0)
+		return(lstrval);
+
+	if ((res = write(arfd, buf, bsz)) == bsz) {
+		wr_trail = 1;
+		io_ok = 1;
+		return(bsz);
+	}
+	/*
+	 * write broke, see what we can do with it. We try to send any partial
+	 * writes that may violate pax spec to the next archive volume.
+	 */
+	if (res < 0)
+		lstrval = res;
+	else
+		lstrval = 0;
+
+	switch (artyp) {
+	case ISREG:
+		if ((res > 0) && (res % BLKMULT)) {
+			/*
+		 	 * try to fix up partial writes which are not BLKMULT
+			 * in size by forcing the runt record to next archive
+			 * volume
+		 	 */
+			if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0)
+				break;
+			cpos -= (off_t)res;
+			if (ftruncate(arfd, cpos) < 0)
+				break;
+			res = lstrval = 0;
+			break;
+		}
+		if (res >= 0)
+			break;
+		/*
+		 * if file is out of space, handle it like a return of 0
+		 */
+		if ((errno == ENOSPC) || (errno == EFBIG)
+#ifdef EDQUOT
+			|| (errno == EDQUOT)
+#endif
+			)
+			res = lstrval = 0;
+		break;
+	case ISTAPE:
+	case ISCHR:
+	case ISBLK:
+		if (res >= 0)
+			break;
+		if (errno == EACCES) {
+			paxwarn(0, "Write failed, archive is write protected.");
+			res = lstrval = 0;
+			return(0);
+		}
+		/*
+		 * see if we reached the end of media, if so force a change to
+		 * the next volume
+		 */
+		if ((errno == ENOSPC) || (errno == EIO) || (errno == ENXIO))
+			res = lstrval = 0;
+		break;
+	case ISPIPE:
+	default:
+		/*
+		 * we cannot fix errors to these devices
+		 */
+		break;
+	}
+
+	/*
+	 * Better tell the user the bad news...
+	 * if this is a block aligned archive format, we may have a bad archive
+	 * if the format wants the header to start at a BLKMULT boundary. While
+	 * we can deal with the mis-aligned data, it violates spec and other
+	 * archive readers will likely fail. if the format is not block
+	 * aligned, the user may be lucky (and the archive is ok).
+	 */
+	if (res >= 0) {
+		if (res > 0)
+			wr_trail = 1;
+		io_ok = 1;
+	}
+
+	/*
+	 * If we were trying to rewrite the trailer and it didn't work, we
+	 * must quit right away.
+	 */
+	if (!wr_trail && (res <= 0)) {
+		paxwarn(1,"Unable to append, trailer re-write failed. Quitting.");
+		return(res);
+	}
+
+	if (res == 0)
+		paxwarn(0, "End of archive volume %d reached", arvol);
+	else if (res < 0)
+		syswarn(1, errno, "Failed write to archive volume: %d", arvol);
+	else if (!frmt->blkalgn || ((res % frmt->blkalgn) == 0))
+		paxwarn(0,"WARNING: partial archive write. Archive MAY BE FLAWED");
+	else
+		paxwarn(1,"WARNING: partial archive write. Archive IS FLAWED");
+	return(res);
+}
+
+/*
+ * ar_rdsync()
+ *	Try to move past a bad spot on a flawed archive as needed to continue
+ *	I/O. Clears error flags to allow I/O to continue.
+ * Return:
+ *	0 when ok to try i/o again, -1 otherwise.
+ */
+
+int
+ar_rdsync(void)
+{
+	long fsbz;
+	off_t cpos;
+	off_t mpos;
+	struct mtop mb;
+
+	/*
+	 * Fail resync attempts at user request (done) or this is going to be
+	 * an update/append to an existing archive. If last i/o hit media end,
+	 * we need to go to the next volume not try a resync.
+	 */
+	if ((done > 0) || (lstrval == 0))
+		return(-1);
+
+	if ((act == APPND) || (act == ARCHIVE)) {
+		paxwarn(1, "Cannot allow updates to an archive with flaws.");
+		return(-1);
+	}
+	if (io_ok)
+		did_io = 1;
+
+	switch(artyp) {
+	case ISTAPE:
+		/*
+		 * if the last i/o was a successful data transfer, we assume
+		 * the fault is just a bad record on the tape that we are now
+		 * past. If we did not get any data since the last resync try
+		 * to move the tape forward one PHYSICAL record past any
+		 * damaged tape section. Some tape drives are stubborn and need
+		 * to be pushed.
+		 */
+		if (io_ok) {
+			io_ok = 0;
+			lstrval = 1;
+			break;
+		}
+		mb.mt_op = MTFSR;
+		mb.mt_count = 1;
+		if (ioctl(arfd, MTIOCTOP, &mb) < 0)
+			break;
+		lstrval = 1;
+		break;
+	case ISREG:
+	case ISCHR:
+	case ISBLK:
+		/*
+		 * try to step over the bad part of the device.
+		 */
+		io_ok = 0;
+#if 0
+	/* no blksize on minix */
+		if (((fsbz = arsb.st_blksize) <= 0) || (artyp != ISREG))
+#endif
+			fsbz = BLKMULT;
+		if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0)
+			break;
+		mpos = fsbz - (cpos % (off_t)fsbz);
+		if (lseek(arfd, mpos, SEEK_CUR) < 0)
+			break;
+		lstrval = 1;
+		break;
+	case ISPIPE:
+	default:
+		/*
+		 * cannot recover on these archive device types
+		 */
+		io_ok = 0;
+		break;
+	}
+	if (lstrval <= 0) {
+		paxwarn(1, "Unable to recover from an archive read failure.");
+		return(-1);
+	}
+	paxwarn(0, "Attempting to recover from an archive read failure.");
+	return(0);
+}
+
+/*
+ * ar_fow()
+ *	Move the I/O position within the archive foward the specified number of
+ *	bytes as supported by the device. If we cannot move the requested
+ *	number of bytes, return the actual number of bytes moved in skipped.
+ * Return:
+ *	0 if moved the requested distance, -1 on complete failure, 1 on
+ *	partial move (the amount moved is in skipped)
+ */
+
+int
+ar_fow(off_t sksz, off_t *skipped)
+{
+	off_t cpos;
+	off_t mpos;
+
+	*skipped = 0;
+	if (sksz <= 0)
+		return(0);
+
+	/*
+	 * we cannot move foward at EOF or error
+	 */
+	if (lstrval <= 0)
+		return(lstrval);
+
+	/*
+	 * Safer to read forward on devices where it is hard to find the end of
+	 * the media without reading to it. With tapes we cannot be sure of the
+	 * number of physical blocks to skip (we do not know physical block
+	 * size at this point), so we must only read foward on tapes!
+	 */
+	if (artyp != ISREG)
+		return(0);
+
+	/*
+	 * figure out where we are in the archive
+	 */
+	if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) >= 0) {
+		/*
+	 	 * we can be asked to move farther than there are bytes in this
+		 * volume, if so, just go to file end and let normal buf_fill()
+		 * deal with the end of file (it will go to next volume by
+		 * itself)
+	 	 */
+		if ((mpos = cpos + sksz) > arsb.st_size) {
+			*skipped = arsb.st_size - cpos;
+			mpos = arsb.st_size;
+		} else
+			*skipped = sksz;
+		if (lseek(arfd, mpos, SEEK_SET) >= 0)
+			return(0);
+	}
+	syswarn(1, errno, "Forward positioning operation on archive failed");
+	lstrval = -1;
+	return(-1);
+}
+
+/*
+ * ar_rev()
+ *	move the i/o position within the archive backwards the specified byte
+ *	count as supported by the device. With tapes drives we RESET rdblksz to
+ *	the PHYSICAL blocksize.
+ *	NOTE: We should only be called to move backwards so we can rewrite the
+ *	last records (the trailer) of an archive (APPEND).
+ * Return:
+ *	0 if moved the requested distance, -1 on complete failure
+ */
+
+int
+ar_rev(off_t sksz)
+{
+	off_t cpos;
+	struct mtop mb;
+	int phyblk;
+
+	/*
+	 * make sure we do not have try to reverse on a flawed archive
+	 */
+	if (lstrval < 0)
+		return(lstrval);
+
+	switch(artyp) {
+	case ISPIPE:
+		if (sksz <= 0)
+			break;
+		/*
+		 * cannot go backwards on these critters
+		 */
+		paxwarn(1, "Reverse positioning on pipes is not supported.");
+		lstrval = -1;
+		return(-1);
+	case ISREG:
+	case ISBLK:
+	case ISCHR:
+	default:
+		if (sksz <= 0)
+			break;
+
+		/*
+		 * For things other than files, backwards movement has a very
+		 * high probability of failure as we really do not know the
+		 * true attributes of the device we are talking to (the device
+		 * may not even have the ability to lseek() in any direction).
+		 * First we figure out where we are in the archive.
+		 */
+		if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) {
+			syswarn(1, errno,
+			   "Unable to obtain current archive byte offset");
+			lstrval = -1;
+			return(-1);
+		}
+
+		/*
+		 * we may try to go backwards past the start when the archive
+		 * is only a single record. If this hapens and we are on a
+		 * multi volume archive, we need to go to the end of the
+		 * previous volume and continue our movement backwards from
+		 * there.
+		 */
+		if ((cpos -= sksz) < (off_t)0L) {
+			if (arvol > 1) {
+				/*
+				 * this should never happen
+				 */
+				paxwarn(1,"Reverse position on previous volume.");
+				lstrval = -1;
+				return(-1);
+			}
+			cpos = (off_t)0L;
+		}
+		if (lseek(arfd, cpos, SEEK_SET) < 0) {
+			syswarn(1, errno, "Unable to seek archive backwards");
+			lstrval = -1;
+			return(-1);
+		}
+		break;
+	case ISTAPE:
+		/*
+	 	 * Calculate and move the proper number of PHYSICAL tape
+		 * blocks. If the sksz is not an even multiple of the physical
+		 * tape size, we cannot do the move (this should never happen).
+		 * (We also cannot handler trailers spread over two vols).
+		 * get_phys() also makes sure we are in front of the filemark.
+	 	 */
+		if ((phyblk = get_phys()) <= 0) {
+			lstrval = -1;
+			return(-1);
+		}
+
+		/*
+		 * make sure future tape reads only go by physical tape block
+		 * size (set rdblksz to the real size).
+		 */
+		rdblksz = phyblk;
+
+		/*
+		 * if no movement is required, just return (we must be after
+		 * get_phys() so the physical blocksize is properly set)
+		 */
+		if (sksz <= 0)
+			break;
+
+		/*
+		 * ok we have to move. Make sure the tape drive can do it.
+		 */
+		if (sksz % phyblk) {
+			paxwarn(1,
+			    "Tape drive unable to backspace requested amount");
+			lstrval = -1;
+			return(-1);
+		}
+
+		/*
+		 * move backwards the requested number of bytes
+		 */
+		mb.mt_op = MTBSR;
+		mb.mt_count = sksz/phyblk;
+		if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
+			syswarn(1,errno, "Unable to backspace tape %d blocks.",
+			    mb.mt_count);
+			lstrval = -1;
+			return(-1);
+		}
+		break;
+	}
+	lstrval = 1;
+	return(0);
+}
+
+/*
+ * get_phys()
+ *	Determine the physical block size on a tape drive. We need the physical
+ *	block size so we know how many bytes we skip over when we move with
+ *	mtio commands. We also make sure we are BEFORE THE TAPE FILEMARK when
+ *	return.
+ *	This is one really SLOW routine...
+ * Return:
+ *	physical block size if ok (ok > 0), -1 otherwise
+ */
+
+static int
+get_phys(void)
+{
+	int padsz = 0;
+	int res;
+	int phyblk;
+	struct mtop mb;
+	char scbuf[MAXBLK];
+
+	/*
+	 * move to the file mark, and then back up one record and read it.
+	 * this should tell us the physical record size the tape is using.
+	 */
+	if (lstrval == 1) {
+		/*
+		 * we know we are at file mark when we get back a 0 from
+		 * read()
+		 */
+		while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0)
+			padsz += res;
+		if (res < 0) {
+			syswarn(1, errno, "Unable to locate tape filemark.");
+			return(-1);
+		}
+	}
+
+	/*
+	 * move backwards over the file mark so we are at the end of the
+	 * last record.
+	 */
+	mb.mt_op = MTBSF;
+	mb.mt_count = 1;
+	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
+		syswarn(1, errno, "Unable to backspace over tape filemark.");
+		return(-1);
+	}
+
+	/*
+	 * move backwards so we are in front of the last record and read it to
+	 * get physical tape blocksize.
+	 */
+	mb.mt_op = MTBSR;
+	mb.mt_count = 1;
+	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
+		syswarn(1, errno, "Unable to backspace over last tape block.");
+		return(-1);
+	}
+	if ((phyblk = read(arfd, scbuf, sizeof(scbuf))) <= 0) {
+		syswarn(1, errno, "Cannot determine archive tape blocksize.");
+		return(-1);
+	}
+
+	/*
+	 * read foward to the file mark, then back up in front of the filemark
+	 * (this is a bit paranoid, but should be safe to do).
+	 */
+	while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0)
+		;
+	if (res < 0) {
+		syswarn(1, errno, "Unable to locate tape filemark.");
+		return(-1);
+	}
+	mb.mt_op = MTBSF;
+	mb.mt_count = 1;
+	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
+		syswarn(1, errno, "Unable to backspace over tape filemark.");
+		return(-1);
+	}
+
+	/*
+	 * set lstrval so we know that the filemark has not been seen
+	 */
+	lstrval = 1;
+
+	/*
+	 * return if there was no padding
+	 */
+	if (padsz == 0)
+		return(phyblk);
+
+	/*
+	 * make sure we can move backwards over the padding. (this should
+	 * never fail).
+	 */
+	if (padsz % phyblk) {
+		paxwarn(1, "Tape drive unable to backspace requested amount");
+		return(-1);
+	}
+
+	/*
+	 * move backwards over the padding so the head is where it was when
+	 * we were first called (if required).
+	 */
+	mb.mt_op = MTBSR;
+	mb.mt_count = padsz/phyblk;
+	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
+		syswarn(1,errno,"Unable to backspace tape over %d pad blocks",
+		    mb.mt_count);
+		return(-1);
+	}
+	return(phyblk);
+}
+
+/*
+ * ar_next()
+ *	prompts the user for the next volume in this archive. For some devices
+ *	we may allow the media to be changed. Otherwise a new archive is
+ *	prompted for. By pax spec, if there is no controlling tty or an eof is
+ *	read on tty input, we must quit pax.
+ * Return:
+ *	0 when ready to continue, -1 when all done
+ */
+
+int
+ar_next(void)
+{
+	char buf[PAXPATHLEN+2];
+	static int freeit = 0;
+	sigset_t o_mask;
+
+	/*
+	 * WE MUST CLOSE THE DEVICE. A lot of devices must see last close, (so
+	 * things like writing EOF etc will be done) (Watch out ar_close() can
+	 * also be called via a signal handler, so we must prevent a race.
+	 */
+	if (sigprocmask(SIG_BLOCK, &s_mask, &o_mask) < 0)
+		syswarn(0, errno, "Unable to set signal mask");
+	ar_close();
+	if (sigprocmask(SIG_SETMASK, &o_mask, NULL) < 0)
+		syswarn(0, errno, "Unable to restore signal mask");
+
+	if (done || !wr_trail || strcmp(NM_TAR, argv0) == 0)
+		return(-1);
+
+	tty_prnt("\nATTENTION! %s archive volume change required.\n", argv0);
+
+	/*
+	 * if i/o is on stdin or stdout, we cannot reopen it (we do not know
+	 * the name), the user will be forced to type it in.
+	 */
+	if (strcmp(arcname, stdo) && strcmp(arcname, stdn) && (artyp != ISREG)
+	    && (artyp != ISPIPE)) {
+		if (artyp == ISTAPE) {
+			tty_prnt("%s ready for archive tape volume: %d\n",
+				arcname, arvol);
+			tty_prnt("Load the NEXT TAPE on the tape drive");
+		} else {
+			tty_prnt("%s ready for archive volume: %d\n",
+				arcname, arvol);
+			tty_prnt("Load the NEXT STORAGE MEDIA (if required)");
+		}
+
+		if ((act == ARCHIVE) || (act == APPND))
+			tty_prnt(" and make sure it is WRITE ENABLED.\n");
+		else
+			tty_prnt("\n");
+
+		for(;;) {
+			tty_prnt("Type \"y\" to continue, \".\" to quit %s,",
+				argv0);
+			tty_prnt(" or \"s\" to switch to new device.\nIf you");
+			tty_prnt(" cannot change storage media, type \"s\"\n");
+			tty_prnt("Is the device ready and online? > ");
+
+			if ((tty_read(buf,sizeof(buf))<0) || !strcmp(buf,".")){
+				done = 1;
+				lstrval = -1;
+				tty_prnt("Quitting %s!\n", argv0);
+				vfpart = 0;
+				return(-1);
+			}
+
+			if ((buf[0] == '\0') || (buf[1] != '\0')) {
+				tty_prnt("%s unknown command, try again\n",buf);
+				continue;
+			}
+
+			switch (buf[0]) {
+			case 'y':
+			case 'Y':
+				/*
+				 * we are to continue with the same device
+				 */
+				if (ar_open(arcname) >= 0)
+					return(0);
+				tty_prnt("Cannot re-open %s, try again\n",
+					arcname);
+				continue;
+			case 's':
+			case 'S':
+				/*
+				 * user wants to open a different device
+				 */
+				tty_prnt("Switching to a different archive\n");
+				break;
+			default:
+				tty_prnt("%s unknown command, try again\n",buf);
+				continue;
+			}
+			break;
+		}
+	} else
+		tty_prnt("Ready for archive volume: %d\n", arvol);
+
+	/*
+	 * have to go to a different archive
+	 */
+	for (;;) {
+		tty_prnt("Input archive name or \".\" to quit %s.\n", argv0);
+		tty_prnt("Archive name > ");
+
+		if ((tty_read(buf, sizeof(buf)) < 0) || !strcmp(buf, ".")) {
+			done = 1;
+			lstrval = -1;
+			tty_prnt("Quitting %s!\n", argv0);
+			vfpart = 0;
+			return(-1);
+		}
+		if (buf[0] == '\0') {
+			tty_prnt("Empty file name, try again\n");
+			continue;
+		}
+		if (!strcmp(buf, "..")) {
+			tty_prnt("Illegal file name: .. try again\n");
+			continue;
+		}
+		if (strlen(buf) > PAXPATHLEN) {
+			tty_prnt("File name too long, try again\n");
+			continue;
+		}
+
+		/*
+		 * try to open new archive
+		 */
+		if (ar_open(buf) >= 0) {
+			if (freeit) {
+				(void)free((char *)(uintptr_t)arcname);
+				freeit = 0;
+			}
+			if ((arcname = strdup(buf)) == NULL) {
+				done = 1;
+				lstrval = -1;
+				paxwarn(0, "Cannot save archive name.");
+				return(-1);
+			}
+			freeit = 1;
+			break;
+		}
+		tty_prnt("Cannot open %s, try again\n", buf);
+		continue;
+	}
+	return(0);
+}
+
+/*
+ * ar_start_gzip()
+ * starts the gzip compression/decompression process as a child, using magic
+ * to keep the fd the same in the calling function (parent).
+ */
+static void
+ar_start_gzip(int fd, const char *gzip_prog, int wr)
+{
+	int fds[2];
+	const char *gzip_flags;
+
+	if (pipe(fds) < 0)
+		err(1, "could not pipe");
+	zpid = fork();
+	if (zpid < 0)
+		err(1, "could not fork");
+
+	/* parent */
+	if (zpid) {
+		if (wr)
+			dup2(fds[1], fd);
+		else
+			dup2(fds[0], fd);
+		close(fds[0]);
+		close(fds[1]);
+	} else {
+		if (wr) {
+			dup2(fds[0], STDIN_FILENO);
+			dup2(fd, STDOUT_FILENO);
+			gzip_flags = "-c";
+		} else {
+			dup2(fds[1], STDOUT_FILENO);
+			dup2(fd, STDIN_FILENO);
+			gzip_flags = "-dc";
+		}
+		close(fds[0]);
+		close(fds[1]);
+		if (execlp(gzip_prog, gzip_prog, gzip_flags,
+		    (char *)NULL) < 0)
+			err(1, "could not exec");
+		/* NOTREACHED */
+	}
+}
Index: /trunk/minix/commands/pax/ar_subs.c
===================================================================
--- /trunk/minix/commands/pax/ar_subs.c	(revision 9)
+++ /trunk/minix/commands/pax/ar_subs.c	(revision 9)
@@ -0,0 +1,1237 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)ar_subs.c	8.2 (Berkeley) 4/18/94";
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "pax.h"
+#include "extern.h"
+
+static void wr_archive(ARCHD *, int is_app);
+static int get_arc(void);
+static int next_head(ARCHD *);
+extern sigset_t s_mask;
+
+/*
+ * Routines which control the overall operation modes of pax as specified by
+ * the user: list, append, read ...
+ */
+
+static char hdbuf[BLKMULT];		/* space for archive header on read */
+u_long flcnt;				/* number of files processed */
+
+/*
+ * list()
+ *	list the contents of an archive which match user supplied pattern(s)
+ *	(no pattern matches all).
+ */
+
+void
+list(void)
+{
+	ARCHD *arcn;
+	int res;
+	ARCHD archd;
+	time_t now;
+
+	arcn = &archd;
+	/*
+	 * figure out archive type; pass any format specific options to the
+	 * archive option processing routine; call the format init routine. We
+	 * also save current time for ls_list() so we do not make a system
+	 * call for each file we need to print. If verbose (vflag) start up
+	 * the name and group caches.
+	 */
+	if ((get_arc() < 0) || ((*frmt->options)() < 0) ||
+	    ((*frmt->st_rd)() < 0))
+		return;
+
+	if (vflag && ((uidtb_start() < 0) || (gidtb_start() < 0)))
+		return;
+
+	now = time(NULL);
+
+	/*
+	 * step through the archive until the format says it is done
+	 */
+	while (next_head(arcn) == 0) {
+		/*
+		 * check for pattern, and user specified options match.
+		 * When all patterns are matched we are done.
+		 */
+		if ((res = pat_match(arcn)) < 0)
+			break;
+
+		if ((res == 0) && (sel_chk(arcn) == 0)) {
+			/*
+			 * pattern resulted in a selected file
+			 */
+			if (pat_sel(arcn) < 0)
+				break;
+
+			/*
+			 * modify the name as requested by the user if name
+			 * survives modification, do a listing of the file
+			 */
+			if ((res = mod_name(arcn)) < 0)
+				break;
+			if (res == 0)
+				ls_list(arcn, now, stdout);
+		}
+
+		/*
+		 * skip to next archive format header using values calculated
+		 * by the format header read routine
+		 */
+		if (rd_skip(arcn->skip + arcn->pad) == 1)
+			break;
+	}
+
+	/*
+	 * all done, let format have a chance to cleanup, and make sure that
+	 * the patterns supplied by the user were all matched
+	 */
+	(void)(*frmt->end_rd)();
+	(void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
+	ar_close();
+	pat_chk();
+}
+
+/*
+ * extract()
+ *	extract the member(s) of an archive as specified by user supplied
+ *	pattern(s) (no patterns extracts all members)
+ */
+
+void
+extract(void)
+{
+	ARCHD *arcn;
+	int res;
+	off_t cnt;
+	ARCHD archd;
+	struct stat sb;
+	int fd;
+	time_t now;
+
+	arcn = &archd;
+	/*
+	 * figure out archive type; pass any format specific options to the
+	 * archive option processing routine; call the format init routine;
+	 * start up the directory modification time and access mode database
+	 */
+	if ((get_arc() < 0) || ((*frmt->options)() < 0) ||
+	    ((*frmt->st_rd)() < 0) || (dir_start() < 0))
+		return;
+
+	/*
+	 * When we are doing interactive rename, we store the mapping of names
+	 * so we can fix up hard links files later in the archive.
+	 */
+	if (iflag && (name_start() < 0))
+		return;
+
+	now = time(NULL);
+
+	/*
+	 * step through each entry on the archive until the format read routine
+	 * says it is done
+	 */
+	while (next_head(arcn) == 0) {
+
+		/*
+		 * check for pattern, and user specified options match. When
+		 * all the patterns are matched we are done
+		 */
+		if ((res = pat_match(arcn)) < 0)
+			break;
+
+		if ((res > 0) || (sel_chk(arcn) != 0)) {
+			/*
+			 * file is not selected. skip past any file data and
+			 * padding and go back for the next archive member
+			 */
+			(void)rd_skip(arcn->skip + arcn->pad);
+			continue;
+		}
+
+		/*
+		 * with -u or -D only extract when the archive member is newer
+		 * than the file with the same name in the file system (nos
+		 * test of being the same type is required).
+		 * NOTE: this test is done BEFORE name modifications as
+		 * specified by pax. this operation can be confusing to the
+		 * user who might expect the test to be done on an existing
+		 * file AFTER the name mod. In honesty the pax spec is probably
+		 * flawed in this respect.
+		 */
+		if ((uflag || Dflag) && ((lstat(arcn->name, &sb) == 0))) {
+			if (uflag && Dflag) {
+				if ((arcn->sb.st_mtime <= sb.st_mtime) &&
+				    (arcn->sb.st_ctime <= sb.st_ctime)) {
+					(void)rd_skip(arcn->skip + arcn->pad);
+					continue;
+				}
+			} else if (Dflag) {
+				if (arcn->sb.st_ctime <= sb.st_ctime) {
+					(void)rd_skip(arcn->skip + arcn->pad);
+					continue;
+				}
+			} else if (arcn->sb.st_mtime <= sb.st_mtime) {
+				(void)rd_skip(arcn->skip + arcn->pad);
+				continue;
+			}
+		}
+
+		/*
+		 * this archive member is now been selected. modify the name.
+		 */
+		if ((pat_sel(arcn) < 0) || ((res = mod_name(arcn)) < 0))
+			break;
+		if (res > 0) {
+			/*
+			 * a bad name mod, skip and purge name from link table
+			 */
+			purg_lnk(arcn);
+			(void)rd_skip(arcn->skip + arcn->pad);
+			continue;
+		}
+
+		/*
+		 * Non standard -Y and -Z flag. When the existing file is
+		 * same age or newer skip
+		 */
+		if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
+			if (Yflag && Zflag) {
+				if ((arcn->sb.st_mtime <= sb.st_mtime) &&
+				    (arcn->sb.st_ctime <= sb.st_ctime)) {
+					(void)rd_skip(arcn->skip + arcn->pad);
+					continue;
+				}
+			} else if (Yflag) {
+				if (arcn->sb.st_ctime <= sb.st_ctime) {
+					(void)rd_skip(arcn->skip + arcn->pad);
+					continue;
+				}
+			} else if (arcn->sb.st_mtime <= sb.st_mtime) {
+				(void)rd_skip(arcn->skip + arcn->pad);
+				continue;
+			}
+		}
+
+		if (vflag) {
+			if (vflag > 1)
+				ls_list(arcn, now, listf);
+			else {
+				(void)fputs(arcn->name, listf);
+				vfpart = 1;
+			}
+		}
+
+		/*
+		 * if required, chdir around.
+		 */
+		if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL))
+			if (chdir(arcn->pat->chdname) != 0)
+				syswarn(1, errno, "Cannot chdir to %s",
+				    arcn->pat->chdname);
+
+		/*
+		 * all ok, extract this member based on type
+		 */
+		if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG)) {
+			/*
+			 * process archive members that are not regular files.
+			 * throw out padding and any data that might follow the
+			 * header (as determined by the format).
+			 */
+			if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
+				res = lnk_creat(arcn);
+			else
+				res = node_creat(arcn);
+
+			(void)rd_skip(arcn->skip + arcn->pad);
+			if (res < 0)
+				purg_lnk(arcn);
+
+			if (vflag && vfpart) {
+				(void)putc('\n', listf);
+				vfpart = 0;
+			}
+			continue;
+		}
+		/*
+		 * we have a file with data here. If we can not create it, skip
+		 * over the data and purge the name from hard link table
+		 */
+		if ((fd = file_creat(arcn)) < 0) {
+			(void)rd_skip(arcn->skip + arcn->pad);
+			purg_lnk(arcn);
+			continue;
+		}
+		/*
+		 * extract the file from the archive and skip over padding and
+		 * any unprocessed data
+		 */
+		res = (*frmt->rd_data)(arcn, fd, &cnt);
+		file_close(arcn, fd);
+		if (vflag && vfpart) {
+			(void)putc('\n', listf);
+			vfpart = 0;
+		}
+		if (!res)
+			(void)rd_skip(cnt + arcn->pad);
+
+		/*
+		 * if required, chdir around.
+		 */
+		if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL))
+			if (fchdir(cwdfd) != 0)
+				syswarn(1, errno,
+				    "Can't fchdir to starting directory");
+	}
+
+	/*
+	 * all done, restore directory modes and times as required; make sure
+	 * all patterns supplied by the user were matched; block off signals
+	 * to avoid chance for multiple entry into the cleanup code.
+	 */
+	(void)(*frmt->end_rd)();
+	(void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
+	ar_close();
+	proc_dir();
+	pat_chk();
+}
+
+/*
+ * wr_archive()
+ *	Write an archive. used in both creating a new archive and appends on
+ *	previously written archive.
+ */
+
+static void
+wr_archive(ARCHD *arcn, int is_app)
+{
+	int res;
+	int hlk;
+	int wr_one;
+	off_t cnt;
+	int (*wrf)(ARCHD *);
+	int fd = -1;
+	time_t now;
+
+	/*
+	 * if this format supports hard link storage, start up the database
+	 * that detects them.
+	 */
+	if (((hlk = frmt->hlk) == 1) && (lnk_start() < 0))
+		return;
+
+	/*
+	 * start up the file traversal code and format specific write
+	 */
+	if ((ftree_start() < 0) || ((*frmt->st_wr)() < 0))
+		return;
+	wrf = frmt->wr;
+
+	/*
+	 * When we are doing interactive rename, we store the mapping of names
+	 * so we can fix up hard links files later in the archive.
+	 */
+	if (iflag && (name_start() < 0))
+		return;
+
+	/*
+	 * if this not append, and there are no files, we do no write a trailer
+	 */
+	wr_one = is_app;
+
+	now = time(NULL);
+
+	/*
+	 * while there are files to archive, process them one at at time
+	 */
+	while (next_file(arcn) == 0) {
+		/*
+		 * check if this file meets user specified options match.
+		 */
+		if (sel_chk(arcn) != 0) {
+			ftree_notsel();
+			continue;
+		}
+		fd = -1;
+		if (uflag) {
+			/*
+			 * only archive if this file is newer than a file with
+			 * the same name that is already stored on the archive
+			 */
+			if ((res = chk_ftime(arcn)) < 0)
+				break;
+			if (res > 0)
+				continue;
+		}
+
+		/*
+		 * this file is considered selected now. see if this is a hard
+		 * link to a file already stored
+		 */
+		ftree_sel(arcn);
+		if (hlk && (chk_lnk(arcn) < 0))
+			break;
+
+		if ((arcn->type == PAX_REG) || (arcn->type == PAX_HRG) ||
+		    (arcn->type == PAX_CTG)) {
+			/*
+			 * we will have to read this file. by opening it now we
+			 * can avoid writing a header to the archive for a file
+			 * we were later unable to read (we also purge it from
+			 * the link table).
+			 */
+			if ((fd = open(arcn->org_name, O_RDONLY, 0)) < 0) {
+				syswarn(1,errno, "Unable to open %s to read",
+					arcn->org_name);
+				purg_lnk(arcn);
+				continue;
+			}
+		}
+
+		/*
+		 * Now modify the name as requested by the user
+		 */
+		if ((res = mod_name(arcn)) < 0) {
+			/*
+			 * name modification says to skip this file, close the
+			 * file and purge link table entry
+			 */
+			rdfile_close(arcn, &fd);
+			purg_lnk(arcn);
+			break;
+		}
+
+		if ((res > 0) || (docrc && (set_crc(arcn, fd) < 0))) {
+			/*
+			 * unable to obtain the crc we need, close the file,
+			 * purge link table entry
+			 */
+			rdfile_close(arcn, &fd);
+			purg_lnk(arcn);
+			continue;
+		}
+
+		if (vflag) {
+			if (vflag > 1)
+				ls_list(arcn, now, listf);
+			else {
+				(void)fputs(arcn->name, listf);
+				vfpart = 1;
+			}
+		}
+		++flcnt;
+
+		/*
+		 * looks safe to store the file, have the format specific
+		 * routine write routine store the file header on the archive
+		 */
+		if ((res = (*wrf)(arcn)) < 0) {
+			rdfile_close(arcn, &fd);
+			break;
+		}
+		wr_one = 1;
+		if (res > 0) {
+			/*
+			 * format write says no file data needs to be stored
+			 * so we are done messing with this file
+			 */
+			if (vflag && vfpart) {
+				(void)putc('\n', listf);
+				vfpart = 0;
+			}
+			rdfile_close(arcn, &fd);
+			continue;
+		}
+
+		/*
+		 * Add file data to the archive, quit on write error. if we
+		 * cannot write the entire file contents to the archive we
+		 * must pad the archive to replace the missing file data
+		 * (otherwise during an extract the file header for the file
+		 * which FOLLOWS this one will not be where we expect it to
+		 * be).
+		 */
+		res = (*frmt->wr_data)(arcn, fd, &cnt);
+		rdfile_close(arcn, &fd);
+		if (vflag && vfpart) {
+			(void)putc('\n', listf);
+			vfpart = 0;
+		}
+		if (res < 0)
+			break;
+
+		/*
+		 * pad as required, cnt is number of bytes not written
+		 */
+		if (((cnt > 0) && (wr_skip(cnt) < 0)) ||
+		    ((arcn->pad > 0) && (wr_skip(arcn->pad) < 0)))
+			break;
+	}
+
+	/*
+	 * tell format to write trailer; pad to block boundary; reset directory
+	 * mode/access times, and check if all patterns supplied by the user
+	 * were matched. block off signals to avoid chance for multiple entry
+	 * into the cleanup code
+	 */
+	if (wr_one) {
+		(*frmt->end_wr)();
+		wr_fin();
+	}
+	(void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
+	ar_close();
+	if (tflag)
+		proc_dir();
+	ftree_chk();
+}
+
+/*
+ * append()
+ *	Add file to previously written archive. Archive format specified by the
+ *	user must agree with archive. The archive is read first to collect
+ *	modification times (if -u) and locate the archive trailer. The archive
+ *	is positioned in front of the record with the trailer and wr_archive()
+ *	is called to add the new members.
+ *	PAX IMPLEMENTATION DETAIL NOTE:
+ *	-u is implemented by adding the new members to the end of the archive.
+ *	Care is taken so that these do not end up as links to the older
+ *	version of the same file already stored in the archive. It is expected
+ *	when extraction occurs these newer versions will over-write the older
+ *	ones stored "earlier" in the archive (this may be a bad assumption as
+ *	it depends on the implementation of the program doing the extraction).
+ *	It is really difficult to splice in members without either re-writing
+ *	the entire archive (from the point were the old version was), or having
+ *	assistance of the format specification in terms of a special update
+ *	header that invalidates a previous archive record. The POSIX spec left
+ *	the method used to implement -u unspecified. This pax is able to
+ *	over write existing files that it creates.
+ */
+
+void
+append(void)
+{
+	ARCHD *arcn;
+	int res;
+	ARCHD archd;
+	FSUB *orgfrmt;
+	int udev;
+	off_t tlen;
+
+	arcn = &archd;
+	orgfrmt = frmt;
+
+	/*
+	 * Do not allow an append operation if the actual archive is of a
+	 * different format than the user specified format.
+	 */
+	if (get_arc() < 0)
+		return;
+	if ((orgfrmt != NULL) && (orgfrmt != frmt)) {
+		paxwarn(1, "Cannot mix current archive format %s with %s",
+		    frmt->name, orgfrmt->name);
+		return;
+	}
+
+	/*
+	 * pass the format any options and start up format
+	 */
+	if (((*frmt->options)() < 0) || ((*frmt->st_rd)() < 0))
+		return;
+
+	/*
+	 * if we only are adding members that are newer, we need to save the
+	 * mod times for all files we see.
+	 */
+	if (uflag && (ftime_start() < 0))
+		return;
+
+	/*
+	 * some archive formats encode hard links by recording the device and
+	 * file serial number (inode) but copy the file anyway (multiple times)
+	 * to the archive. When we append, we run the risk that newly added
+	 * files may have the same device and inode numbers as those recorded
+	 * on the archive but during a previous run. If this happens, when the
+	 * archive is extracted we get INCORRECT hard links. We avoid this by
+	 * remapping the device numbers so that newly added files will never
+	 * use the same device number as one found on the archive. remapping
+	 * allows new members to safely have links among themselves. remapping
+	 * also avoids problems with file inode (serial number) truncations
+	 * when the inode number is larger than storage space in the archive
+	 * header. See the remap routines for more details.
+	 */
+	if ((udev = frmt->udev) && (dev_start() < 0))
+		return;
+
+	/*
+	 * reading the archive may take a long time. If verbose tell the user
+	 */
+	if (vflag) {
+		(void)fprintf(listf,
+			"%s: Reading archive to position at the end...", argv0);
+		vfpart = 1;
+	}
+
+	/*
+	 * step through the archive until the format says it is done
+	 */
+	while (next_head(arcn) == 0) {
+		/*
+		 * check if this file meets user specified options.
+		 */
+		if (sel_chk(arcn) != 0) {
+			if (rd_skip(arcn->skip + arcn->pad) == 1)
+				break;
+			continue;
+		}
+
+		if (uflag) {
+			/*
+			 * see if this is the newest version of this file has
+			 * already been seen, if so skip.
+			 */
+			if ((res = chk_ftime(arcn)) < 0)
+				break;
+			if (res > 0) {
+				if (rd_skip(arcn->skip + arcn->pad) == 1)
+					break;
+				continue;
+			}
+		}
+
+		/*
+		 * Store this device number. Device numbers seen during the
+		 * read phase of append will cause newly appended files with a
+		 * device number seen in the old part of the archive to be
+		 * remapped to an unused device number.
+		 */
+		if ((udev && (add_dev(arcn) < 0)) ||
+		    (rd_skip(arcn->skip + arcn->pad) == 1))
+			break;
+	}
+
+	/*
+	 * done, finish up read and get the number of bytes to back up so we
+	 * can add new members. The format might have used the hard link table,
+	 * purge it.
+	 */
+	tlen = (*frmt->end_rd)();
+	lnk_end();
+
+	/*
+	 * try to position for write, if this fails quit. if any error occurs,
+	 * we will refuse to write
+	 */
+	if (appnd_start(tlen) < 0)
+		return;
+
+	/*
+	 * tell the user we are done reading.
+	 */
+	if (vflag && vfpart) {
+		(void)fputs("done.\n", listf);
+		vfpart = 0;
+	}
+
+	/*
+	 * go to the writing phase to add the new members
+	 */
+	wr_archive(arcn, 1);
+}
+
+/*
+ * archive()
+ *	write a new archive
+ */
+
+void
+archive(void)
+{
+	ARCHD archd;
+
+	/*
+	 * if we only are adding members that are newer, we need to save the
+	 * mod times for all files; set up for writing; pass the format any
+	 * options write the archive
+	 */
+	if ((uflag && (ftime_start() < 0)) || (wr_start() < 0))
+		return;
+	if ((*frmt->options)() < 0)
+		return;
+
+	wr_archive(&archd, 0);
+}
+
+/*
+ * copy()
+ *	copy files from one part of the file system to another. this does not
+ *	use any archive storage. The EFFECT OF THE COPY IS THE SAME as if an
+ *	archive was written and then extracted in the destination directory
+ *	(except the files are forced to be under the destination directory).
+ */
+
+void
+copy(void)
+{
+	ARCHD *arcn;
+	int res;
+	int fddest;
+	char *dest_pt;
+	int dlen;
+	int drem;
+	int fdsrc = -1;
+	struct stat sb;
+	ARCHD archd;
+	char dirbuf[PAXPATHLEN+1];
+
+	arcn = &archd;
+	/*
+	 * set up the destination dir path and make sure it is a directory. We
+	 * make sure we have a trailing / on the destination
+	 */
+	dlen = l_strncpy(dirbuf, dirptr, sizeof(dirbuf) - 1);
+	dest_pt = dirbuf + dlen;
+	if (*(dest_pt-1) != '/') {
+		*dest_pt++ = '/';
+		++dlen;
+	}
+	*dest_pt = '\0';
+	drem = PAXPATHLEN - dlen;
+
+	if (stat(dirptr, &sb) < 0) {
+		syswarn(1, errno, "Cannot access destination directory %s",
+			dirptr);
+		return;
+	}
+	if (!S_ISDIR(sb.st_mode)) {
+		paxwarn(1, "Destination is not a directory %s", dirptr);
+		return;
+	}
+
+	/*
+	 * start up the hard link table; file traversal routines and the
+	 * modification time and access mode database
+	 */
+	if ((lnk_start() < 0) || (ftree_start() < 0) || (dir_start() < 0))
+		return;
+
+	/*
+	 * When we are doing interactive rename, we store the mapping of names
+	 * so we can fix up hard links files later in the archive.
+	 */
+	if (iflag && (name_start() < 0))
+		return;
+
+	/*
+	 * set up to cp file trees
+	 */
+	cp_start();
+
+	/*
+	 * while there are files to archive, process them
+	 */
+	while (next_file(arcn) == 0) {
+		fdsrc = -1;
+
+		/*
+		 * check if this file meets user specified options
+		 */
+		if (sel_chk(arcn) != 0) {
+			ftree_notsel();
+			continue;
+		}
+
+		/*
+		 * if there is already a file in the destination directory with
+		 * the same name and it is newer, skip the one stored on the
+		 * archive.
+		 * NOTE: this test is done BEFORE name modifications as
+		 * specified by pax. this can be confusing to the user who
+		 * might expect the test to be done on an existing file AFTER
+		 * the name mod. In honesty the pax spec is probably flawed in
+		 * this respect
+		 */
+		if (uflag || Dflag) {
+			/*
+			 * create the destination name
+			 */
+			if (*(arcn->name) == '/')
+				res = 1;
+			else
+				res = 0;
+			if ((arcn->nlen - res) > drem) {
+				paxwarn(1, "Destination pathname too long %s",
+					arcn->name);
+				continue;
+			}
+			(void)strncpy(dest_pt, arcn->name + res, drem);
+			dirbuf[PAXPATHLEN] = '\0';
+
+			/*
+			 * if existing file is same age or newer skip
+			 */
+			res = lstat(dirbuf, &sb);
+			*dest_pt = '\0';
+
+		    	if (res == 0) {
+				if (uflag && Dflag) {
+					if ((arcn->sb.st_mtime<=sb.st_mtime) &&
+			    		    (arcn->sb.st_ctime<=sb.st_ctime))
+						continue;
+				} else if (Dflag) {
+					if (arcn->sb.st_ctime <= sb.st_ctime)
+						continue;
+				} else if (arcn->sb.st_mtime <= sb.st_mtime)
+					continue;
+			}
+		}
+
+		/*
+		 * this file is considered selected. See if this is a hard link
+		 * to a previous file; modify the name as requested by the
+		 * user; set the final destination.
+		 */
+		ftree_sel(arcn);
+		if ((chk_lnk(arcn) < 0) || ((res = mod_name(arcn)) < 0))
+			break;
+		if ((res > 0) || (set_dest(arcn, dirbuf, dlen) < 0)) {
+			/*
+			 * skip file, purge from link table
+			 */
+			purg_lnk(arcn);
+			continue;
+		}
+
+		/*
+		 * Non standard -Y and -Z flag. When the exisiting file is
+		 * same age or newer skip
+		 */
+		if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
+			if (Yflag && Zflag) {
+				if ((arcn->sb.st_mtime <= sb.st_mtime) &&
+				    (arcn->sb.st_ctime <= sb.st_ctime))
+					continue;
+			} else if (Yflag) {
+				if (arcn->sb.st_ctime <= sb.st_ctime)
+					continue;
+			} else if (arcn->sb.st_mtime <= sb.st_mtime)
+				continue;
+		}
+
+		if (vflag) {
+			(void)fputs(arcn->name, listf);
+			vfpart = 1;
+		}
+		++flcnt;
+
+		/*
+		 * try to create a hard link to the src file if requested
+		 * but make sure we are not trying to overwrite ourselves.
+		 */
+		if (lflag)
+			res = cross_lnk(arcn);
+		else
+			res = chk_same(arcn);
+		if (res <= 0) {
+			if (vflag && vfpart) {
+				(void)putc('\n', listf);
+				vfpart = 0;
+			}
+			continue;
+		}
+
+		/*
+		 * have to create a new file
+		 */
+		if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG)) {
+			/*
+			 * create a link or special file
+			 */
+			if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
+				res = lnk_creat(arcn);
+			else
+				res = node_creat(arcn);
+			if (res < 0)
+				purg_lnk(arcn);
+			if (vflag && vfpart) {
+				(void)putc('\n', listf);
+				vfpart = 0;
+			}
+			continue;
+		}
+
+		/*
+		 * have to copy a regular file to the destination directory.
+		 * first open source file and then create the destination file
+		 */
+		if ((fdsrc = open(arcn->org_name, O_RDONLY, 0)) < 0) {
+			syswarn(1, errno, "Unable to open %s to read",
+			    arcn->org_name);
+			purg_lnk(arcn);
+			continue;
+		}
+		if ((fddest = file_creat(arcn)) < 0) {
+			rdfile_close(arcn, &fdsrc);
+			purg_lnk(arcn);
+			continue;
+		}
+
+		/*
+		 * copy source file data to the destination file
+		 */
+		cp_file(arcn, fdsrc, fddest);
+		file_close(arcn, fddest);
+		rdfile_close(arcn, &fdsrc);
+
+		if (vflag && vfpart) {
+			(void)putc('\n', listf);
+			vfpart = 0;
+		}
+	}
+
+	/*
+	 * restore directory modes and times as required; make sure all
+	 * patterns were selected block off signals to avoid chance for
+	 * multiple entry into the cleanup code.
+	 */
+	(void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
+	ar_close();
+	proc_dir();
+	ftree_chk();
+}
+
+/*
+ * next_head()
+ *	try to find a valid header in the archive. Uses format specific
+ *	routines to extract the header and id the trailer. Trailers may be
+ *	located within a valid header or in an invalid header (the location
+ *	is format specific. The inhead field from the option table tells us
+ *	where to look for the trailer).
+ *	We keep reading (and resyncing) until we get enough contiguous data
+ *	to check for a header. If we cannot find one, we shift by a byte
+ *	add a new byte from the archive to the end of the buffer and try again.
+ *	If we get a read error, we throw out what we have (as we must have
+ *	contiguous data) and start over again.
+ *	ASSUMED: headers fit within a BLKMULT header.
+ * Return:
+ *	0 if we got a header, -1 if we are unable to ever find another one
+ *	(we reached the end of input, or we reached the limit on retries. see
+ *	the specs for rd_wrbuf() for more details)
+ */
+
+static int
+next_head(ARCHD *arcn)
+{
+	int ret;
+	char *hdend;
+	int res;
+	int shftsz;
+	int hsz;
+	int in_resync = 0; 	/* set when we are in resync mode */
+	int cnt = 0;			/* counter for trailer function */
+	int first = 1;			/* on 1st read, EOF isn't premature. */
+
+	/*
+	 * set up initial conditions, we want a whole frmt->hsz block as we
+	 * have no data yet.
+	 */
+	res = hsz = frmt->hsz;
+	hdend = hdbuf;
+	shftsz = hsz - 1;
+	for(;;) {
+		/*
+		 * keep looping until we get a contiguous FULL buffer
+		 * (frmt->hsz is the proper size)
+		 */
+		for (;;) {
+			if ((ret = rd_wrbuf(hdend, res)) == res)
+				break;
+
+			/*
+			 * If we read 0 bytes (EOF) from an archive when we
+			 * expect to find a header, we have stepped upon
+			 * an archive without the customary block of zeroes
+			 * end marker.  It's just stupid to error out on
+			 * them, so exit gracefully.
+			 */
+			if (first && ret == 0)
+				return(-1);
+			first = 0;
+
+			/*
+			 * some kind of archive read problem, try to resync the
+			 * storage device, better give the user the bad news.
+			 */
+			if ((ret == 0) || (rd_sync() < 0)) {
+				paxwarn(1,"Premature end of file on archive read");
+				return(-1);
+			}
+			if (!in_resync) {
+				if (act == APPND) {
+					paxwarn(1,
+					  "Archive I/O error, cannot continue");
+					return(-1);
+				}
+				paxwarn(1,"Archive I/O error. Trying to recover.");
+				++in_resync;
+			}
+
+			/*
+			 * oh well, throw it all out and start over
+			 */
+			res = hsz;
+			hdend = hdbuf;
+		}
+
+		/*
+		 * ok we have a contiguous buffer of the right size. Call the
+		 * format read routine. If this was not a valid header and this
+		 * format stores trailers outside of the header, call the
+		 * format specific trailer routine to check for a trailer. We
+		 * have to watch out that we do not mis-identify file data or
+		 * block padding as a header or trailer. Format specific
+		 * trailer functions must NOT check for the trailer while we
+		 * are running in resync mode. Some trailer functions may tell
+		 * us that this block cannot contain a valid header either, so
+		 * we then throw out the entire block and start over.
+		 */
+		if ((*frmt->rd)(arcn, hdbuf) == 0)
+			break;
+
+		if (!frmt->inhead) {
+			/*
+			 * this format has trailers outside of valid headers
+			 */
+			if ((ret = (*frmt->trail_tar)(hdbuf,in_resync,&cnt)) == 0){
+				/*
+				 * valid trailer found, drain input as required
+				 */
+				ar_drain();
+				return(-1);
+			}
+
+			if (ret == 1) {
+				/*
+				 * we are in resync and we were told to throw
+				 * the whole block out because none of the
+				 * bytes in this block can be used to form a
+				 * valid header
+				 */
+				res = hsz;
+				hdend = hdbuf;
+				continue;
+			}
+		}
+
+		/*
+		 * Brute force section.
+		 * not a valid header. We may be able to find a header yet. So
+		 * we shift over by one byte, and set up to read one byte at a
+		 * time from the archive and place it at the end of the buffer.
+		 * We will keep moving byte at a time until we find a header or
+		 * get a read error and have to start over.
+		 */
+		if (!in_resync) {
+			if (act == APPND) {
+				paxwarn(1,"Unable to append, archive header flaw");
+				return(-1);
+			}
+			paxwarn(1,"Invalid header, starting valid header search.");
+			++in_resync;
+		}
+		memmove(hdbuf, hdbuf+1, shftsz);
+		res = 1;
+		hdend = hdbuf + shftsz;
+	}
+
+	/*
+	 * ok got a valid header, check for trailer if format encodes it in the
+	 * the header.
+	 */
+	if (frmt->inhead && ((*frmt->trail_cpio)(arcn) == 0)) {
+		/*
+		 * valid trailer found, drain input as required
+		 */
+		ar_drain();
+		return(-1);
+	}
+
+	++flcnt;
+	return(0);
+}
+
+/*
+ * get_arc()
+ *	Figure out what format an archive is. Handles archive with flaws by
+ *	brute force searches for a legal header in any supported format. The
+ *	format id routines have to be careful to NOT mis-identify a format.
+ *	ASSUMED: headers fit within a BLKMULT header.
+ * Return:
+ *	0 if archive found -1 otherwise
+ */
+
+static int
+get_arc(void)
+{
+	int i;
+	int hdsz = 0;
+	int res;
+	int minhd = BLKMULT;
+	char *hdend;
+	int notice = 0;
+
+	/*
+	 * find the smallest header size in all archive formats and then set up
+	 * to read the archive.
+	 */
+	for (i = 0; ford[i] >= 0; ++i) {
+		if (fsub[ford[i]].hsz < minhd)
+			minhd = fsub[ford[i]].hsz;
+	}
+	if (rd_start() < 0)
+		return(-1);
+	res = BLKMULT;
+	hdsz = 0;
+	hdend = hdbuf;
+	for(;;) {
+		for (;;) {
+			/*
+			 * fill the buffer with at least the smallest header
+			 */
+			i = rd_wrbuf(hdend, res);
+			if (i > 0)
+				hdsz += i;
+			if (hdsz >= minhd)
+				break;
+
+			/*
+			 * if we cannot recover from a read error quit
+			 */
+			if ((i == 0) || (rd_sync() < 0))
+				goto out;
+
+			/*
+			 * when we get an error none of the data we already
+			 * have can be used to create a legal header (we just
+			 * got an error in the middle), so we throw it all out
+			 * and refill the buffer with fresh data.
+			 */
+			res = BLKMULT;
+			hdsz = 0;
+			hdend = hdbuf;
+			if (!notice) {
+				if (act == APPND)
+					return(-1);
+				paxwarn(1,"Cannot identify format. Searching...");
+				++notice;
+			}
+		}
+
+		/*
+		 * we have at least the size of the smallest header in any
+		 * archive format. Look to see if we have a match. The array
+		 * ford[] is used to specify the header id order to reduce the
+		 * chance of incorrectly id'ing a valid header (some formats
+		 * may be subsets of each other and the order would then be
+		 * important).
+		 */
+		for (i = 0; ford[i] >= 0; ++i) {
+			if ((*fsub[ford[i]].id)(hdbuf, hdsz) < 0)
+				continue;
+			frmt = &(fsub[ford[i]]);
+			/*
+			 * yuck, to avoid slow special case code in the extract
+			 * routines, just push this header back as if it was
+			 * not seen. We have left extra space at start of the
+			 * buffer for this purpose. This is a bit ugly, but
+			 * adding all the special case code is far worse.
+			 */
+			pback(hdbuf, hdsz);
+			return(0);
+		}
+
+		/*
+		 * We have a flawed archive, no match. we start searching, but
+		 * we never allow additions to flawed archives
+		 */
+		if (!notice) {
+			if (act == APPND)
+				return(-1);
+			paxwarn(1, "Cannot identify format. Searching...");
+			++notice;
+		}
+
+		/*
+		 * brute force search for a header that we can id.
+		 * we shift through byte at a time. this is slow, but we cannot
+		 * determine the nature of the flaw in the archive in a
+		 * portable manner
+		 */
+		if (--hdsz > 0) {
+			memmove(hdbuf, hdbuf+1, hdsz);
+			res = BLKMULT - hdsz;
+			hdend = hdbuf + hdsz;
+		} else {
+			res = BLKMULT;
+			hdend = hdbuf;
+			hdsz = 0;
+		}
+	}
+
+    out:
+	/*
+	 * we cannot find a header, bow, apologize and quit
+	 */
+	paxwarn(1, "Sorry, unable to determine archive format.");
+	return(-1);
+}
Index: /trunk/minix/commands/pax/buf_subs.c
===================================================================
--- /trunk/minix/commands/pax/buf_subs.c	(revision 9)
+++ /trunk/minix/commands/pax/buf_subs.c	(revision 9)
@@ -0,0 +1,993 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)buf_subs.c	8.2 (Berkeley) 4/18/94";
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "pax.h"
+#include "extern.h"
+
+/*
+ * routines which implement archive and file buffering
+ */
+
+#define MINFBSZ		512		/* default block size for hole detect */
+#define MAXFLT		10		/* default media read error limit */
+
+/*
+ * Need to change bufmem to dynamic allocation when the upper
+ * limit on blocking size is removed (though that will violate pax spec)
+ * MAXBLK define and tests will also need to be updated.
+ */
+static char bufmem[MAXBLK+BLKMULT];	/* i/o buffer + pushback id space */
+static char *buf;			/* normal start of i/o buffer */
+static char *bufend;			/* end or last char in i/o buffer */
+static char *bufpt;			/* read/write point in i/o buffer */
+int blksz = MAXBLK;			/* block input/output size in bytes */
+int wrblksz;				/* user spec output size in bytes */
+int maxflt = MAXFLT;			/* MAX consecutive media errors */
+int rdblksz;				/* first read blksize (tapes only) */
+off_t wrlimit;				/* # of bytes written per archive vol */
+off_t wrcnt;				/* # of bytes written on current vol */
+off_t rdcnt;				/* # of bytes read on current vol */
+
+/*
+ * wr_start()
+ *	set up the buffering system to operate in a write mode
+ * Return:
+ *	0 if ok, -1 if the user specified write block size violates pax spec
+ */
+
+int
+wr_start(void)
+{
+	buf = &(bufmem[BLKMULT]);
+	/*
+	 * Check to make sure the write block size meets pax specs. If the user
+	 * does not specify a blocksize, we use the format default blocksize.
+	 * We must be picky on writes, so we do not allow the user to create an
+	 * archive that might be hard to read elsewhere. If all ok, we then
+	 * open the first archive volume
+	 */
+	if (!wrblksz)
+		wrblksz = frmt->bsz;
+	if (wrblksz > MAXBLK) {
+		paxwarn(1, "Write block size of %d too large, maximum is: %d",
+			wrblksz, MAXBLK);
+		return(-1);
+	}
+	if (wrblksz % BLKMULT) {
+		paxwarn(1, "Write block size of %d is not a %d byte multiple",
+		    wrblksz, BLKMULT);
+		return(-1);
+	}
+	if (wrblksz > MAXBLK_POSIX) {
+		paxwarn(0, "Write block size of %d larger than POSIX max %d, archive may not be portable",
+			wrblksz, MAXBLK_POSIX);
+		return(-1);
+	}
+
+	/*
+	 * we only allow wrblksz to be used with all archive operations
+	 */
+	blksz = rdblksz = wrblksz;
+	if ((ar_open(arcname) < 0) && (ar_next() < 0))
+		return(-1);
+	wrcnt = 0;
+	bufend = buf + wrblksz;
+	bufpt = buf;
+	return(0);
+}
+
+/*
+ * rd_start()
+ *	set up buffering system to read an archive
+ * Return:
+ *	0 if ok, -1 otherwise
+ */
+
+int
+rd_start(void)
+{
+	/*
+	 * leave space for the header pushback (see get_arc()). If we are
+	 * going to append and user specified a write block size, check it
+	 * right away
+	 */
+	buf = &(bufmem[BLKMULT]);
+	if ((act == APPND) && wrblksz) {
+		if (wrblksz > MAXBLK) {
+			paxwarn(1,"Write block size %d too large, maximum is: %d",
+				wrblksz, MAXBLK);
+			return(-1);
+		}
+		if (wrblksz % BLKMULT) {
+			paxwarn(1, "Write block size %d is not a %d byte multiple",
+		    	wrblksz, BLKMULT);
+			return(-1);
+		}
+	}
+
+	/*
+	 * open the archive
+	 */
+	if ((ar_open(arcname) < 0) && (ar_next() < 0))
+		return(-1);
+	bufend = buf + rdblksz;
+	bufpt = bufend;
+	rdcnt = 0;
+	return(0);
+}
+
+/*
+ * cp_start()
+ *	set up buffer system for copying within the file system
+ */
+
+void
+cp_start(void)
+{
+	buf = &(bufmem[BLKMULT]);
+	rdblksz = blksz = MAXBLK;
+}
+
+/*
+ * appnd_start()
+ *	Set up the buffering system to append new members to an archive that
+ *	was just read. The last block(s) of an archive may contain a format
+ *	specific trailer. To append a new member, this trailer has to be
+ *	removed from the archive. The first byte of the trailer is replaced by
+ *	the start of the header of the first file added to the archive. The
+ *	format specific end read function tells us how many bytes to move
+ *	backwards in the archive to be positioned BEFORE the trailer. Two
+ *	different postions have to be adjusted, the O.S. file offset (e.g. the
+ *	position of the tape head) and the write point within the data we have
+ *	stored in the read (soon to become write) buffer. We may have to move
+ *	back several records (the number depends on the size of the archive
+ *	record and the size of the format trailer) to read up the record where
+ *	the first byte of the trailer is recorded. Trailers may span (and
+ *	overlap) record boundries.
+ *	We first calculate which record has the first byte of the trailer. We
+ *	move the OS file offset back to the start of this record and read it
+ *	up. We set the buffer write pointer to be at this byte (the byte where
+ *	the trailer starts). We then move the OS file pointer back to the
+ *	start of this record so a flush of this buffer will replace the record
+ *	in the archive.
+ *	A major problem is rewriting this last record. For archives stored
+ *	on disk files, this is trival. However, many devices are really picky
+ *	about the conditions under which they will allow a write to occur.
+ *	Often devices restrict the conditions where writes can be made writes,
+ *	so it may not be feasable to append archives stored on all types of
+ *	devices.
+ * Return:
+ *	0 for success, -1 for failure
+ */
+
+int
+appnd_start(off_t skcnt)
+{
+	int res;
+	off_t cnt;
+
+	if (exit_val != 0) {
+		paxwarn(0, "Cannot append to an archive that may have flaws.");
+		return(-1);
+	}
+	/*
+	 * if the user did not specify a write blocksize, inherit the size used
+	 * in the last archive volume read. (If a is set we still use rdblksz
+	 * until next volume, cannot shift sizes within a single volume).
+	 */
+	if (!wrblksz)
+		wrblksz = blksz = rdblksz;
+	else
+		blksz = rdblksz;
+
+	/*
+	 * make sure that this volume allows appends
+	 */
+	if (ar_app_ok() < 0)
+		return(-1);
+
+	/*
+	 * Calculate bytes to move back and move in front of record where we
+	 * need to start writing from. Remember we have to add in any padding
+	 * that might be in the buffer after the trailer in the last block. We
+	 * travel skcnt + padding ROUNDED UP to blksize.
+	 */
+	skcnt += bufend - bufpt;
+	if ((cnt = (skcnt/blksz) * blksz) < skcnt)
+		cnt += blksz;
+	if (ar_rev((off_t)cnt) < 0)
+		goto out;
+
+	/*
+	 * We may have gone too far if there is valid data in the block we are
+	 * now in front of, read up the block and position the pointer after
+	 * the valid data.
+	 */
+	if ((cnt -= skcnt) > 0) {
+		/*
+		 * watch out for stupid tape drives. ar_rev() will set rdblksz
+		 * to be real physical blocksize so we must loop until we get
+		 * the old rdblksz (now in blksz). If ar_rev() fouls up the
+		 * determination of the physical block size, we will fail.
+		 */
+		bufpt = buf;
+		bufend = buf + blksz;
+		while (bufpt < bufend) {
+			if ((res = ar_read(bufpt, rdblksz)) <= 0)
+				goto out;
+			bufpt += res;
+		}
+		if (ar_rev((off_t)(bufpt - buf)) < 0)
+			goto out;
+		bufpt = buf + cnt;
+		bufend = buf + blksz;
+	} else {
+		/*
+		 * buffer is empty
+		 */
+		bufend = buf + blksz;
+		bufpt = buf;
+	}
+	rdblksz = blksz;
+	rdcnt -= skcnt;
+	wrcnt = 0;
+
+	/*
+	 * At this point we are ready to write. If the device requires special
+	 * handling to write at a point were previously recorded data resides,
+	 * that is handled in ar_set_wr(). From now on we operate under normal
+	 * ARCHIVE mode (write) conditions
+	 */
+	if (ar_set_wr() < 0)
+		return(-1);
+	act = ARCHIVE;
+	return(0);
+
+    out:
+	paxwarn(1, "Unable to rewrite archive trailer, cannot append.");
+	return(-1);
+}
+	
+/*
+ * rd_sync()
+ *	A read error occurred on this archive volume. Resync the buffer and
+ *	try to reset the device (if possible) so we can continue to read. Keep
+ *	trying to do this until we get a valid read, or we reach the limit on
+ *	consecutive read faults (at which point we give up). The user can
+ *	adjust the read error limit through a command line option.
+ * Returns:
+ *	0 on success, and -1 on failure
+ */
+
+int
+rd_sync(void)
+{
+	int errcnt = 0;
+	int res;
+
+	/*
+	 * if the user says bail out on first fault, we are out of here...
+	 */
+	if (maxflt == 0)
+		return(-1);
+	if (act == APPND) {
+		paxwarn(1, "Unable to append when there are archive read errors.");
+		return(-1);
+	}
+
+	/*
+	 * poke at device and try to get past media error
+	 */
+	if (ar_rdsync() < 0) {
+		if (ar_next() < 0)
+			return(-1);
+		else
+			rdcnt = 0;
+	}
+
+	for (;;) {
+		if ((res = ar_read(buf, blksz)) > 0) {
+			/*
+			 * All right! got some data, fill that buffer
+			 */
+			bufpt = buf;
+			bufend = buf + res;
+			rdcnt += res;
+			return(0);
+		}
+
+		/*
+		 * Oh well, yet another failed read...
+		 * if error limit reached, ditch. o.w. poke device to move past
+		 * bad media and try again. if media is badly damaged, we ask
+		 * the poor (and upset user at this point) for the next archive
+		 * volume. remember the goal on reads is to get the most we
+		 * can extract out of the archive.
+		 */
+		if ((maxflt > 0) && (++errcnt > maxflt))
+			paxwarn(0,"Archive read error limit (%d) reached",maxflt);
+		else if (ar_rdsync() == 0)
+			continue;
+		if (ar_next() < 0)
+			break;
+		rdcnt = 0;
+		errcnt = 0;
+	}
+	return(-1);
+}
+
+/*
+ * pback()
+ *	push the data used during the archive id phase back into the I/O
+ *	buffer. This is required as we cannot be sure that the header does NOT
+ *	overlap a block boundry (as in the case we are trying to recover a
+ *	flawed archived). This was not designed to be used for any other
+ *	purpose. (What software engineering, HA!)
+ *	WARNING: do not even THINK of pback greater than BLKMULT, unless the
+ *	pback space is increased.
+ */
+
+void
+pback(char *pt, int cnt)
+{
+	bufpt -= cnt;
+	memcpy(bufpt, pt, cnt);
+	return;
+}
+
+/*
+ * rd_skip()
+ *	skip foward in the archive during an archive read. Used to get quickly
+ *	past file data and padding for files the user did NOT select.
+ * Return:
+ *	0 if ok, -1 failure, and 1 when EOF on the archive volume was detected.
+ */
+
+int
+rd_skip(off_t skcnt)
+{
+	off_t res;
+	off_t cnt;
+	off_t skipped = 0;
+
+	/*
+	 * consume what data we have in the buffer. If we have to move foward
+	 * whole records, we call the low level skip function to see if we can
+	 * move within the archive without doing the expensive reads on data we
+	 * do not want.
+	 */
+	if (skcnt == 0)
+		return(0);
+	res = MIN((bufend - bufpt), skcnt);
+	bufpt += res;
+	skcnt -= res;
+
+	/*
+	 * if skcnt is now 0, then no additional i/o is needed
+	 */
+	if (skcnt == 0)
+		return(0);
+
+	/*
+	 * We have to read more, calculate complete and partial record reads
+	 * based on rdblksz. we skip over "cnt" complete records
+	 */
+	res = skcnt%rdblksz;
+	cnt = (skcnt/rdblksz) * rdblksz;
+
+	/*
+	 * if the skip fails, we will have to resync. ar_fow will tell us
+	 * how much it can skip over. We will have to read the rest.
+	 */
+	if (ar_fow(cnt, &skipped) < 0)
+		return(-1);
+	res += cnt - skipped;
+	rdcnt += skipped;
+
+	/*
+	 * what is left we have to read (which may be the whole thing if
+	 * ar_fow() told us the device can only read to skip records);
+	 */
+	while (res > 0L) {
+		cnt = bufend - bufpt;
+		/*
+		 * if the read fails, we will have to resync
+		 */
+		if ((cnt <= 0) && ((cnt = buf_fill()) < 0))
+			return(-1);
+		if (cnt == 0)
+			return(1);
+		cnt = MIN(cnt, res);
+		bufpt += cnt;
+		res -= cnt;
+	}
+	return(0);
+}
+
+/*
+ * wr_fin()
+ *	flush out any data (and pad if required) the last block. We always pad
+ *	with zero (even though we do not have to). Padding with 0 makes it a
+ *	lot easier to recover if the archive is damaged. zero paddding SHOULD
+ *	BE a requirement....
+ */
+
+void
+wr_fin(void)
+{
+	if (bufpt > buf) {
+		memset(bufpt, 0, bufend - bufpt);
+		bufpt = bufend;
+		(void)buf_flush(blksz);
+	}
+}
+
+/*
+ * wr_rdbuf()
+ *	fill the write buffer from data passed to it in a buffer (usually used
+ *	by format specific write routines to pass a file header). On failure we
+ *	punt. We do not allow the user to continue to write flawed archives.
+ *	We assume these headers are not very large (the memory copy we use is
+ *	a bit expensive).
+ * Return:
+ *	0 if buffer was filled ok, -1 o.w. (buffer flush failure)
+ */
+
+int
+wr_rdbuf(char *out, int outcnt)
+{
+	int cnt;
+
+	/*
+	 * while there is data to copy copy into the write buffer. when the
+	 * write buffer fills, flush it to the archive and continue
+	 */
+	while (outcnt > 0) {
+		cnt = bufend - bufpt;
+		if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0))
+			return(-1);
+		/*
+		 * only move what we have space for
+		 */
+		cnt = MIN(cnt, outcnt);
+		memcpy(bufpt, out, cnt);
+		bufpt += cnt;
+		out += cnt;
+		outcnt -= cnt;
+	}
+	return(0);
+}
+
+/*
+ * rd_wrbuf()
+ *	copy from the read buffer into a supplied buffer a specified number of
+ *	bytes. If the read buffer is empty fill it and continue to copy.
+ *	usually used to obtain a file header for processing by a format
+ *	specific read routine.
+ * Return
+ *	number of bytes copied to the buffer, 0 indicates EOF on archive volume,
+ *	-1 is a read error
+ */
+
+int
+rd_wrbuf(char *in, int cpcnt)
+{
+	int res;
+	int cnt;
+	int incnt = cpcnt;
+
+	/*
+	 * loop until we fill the buffer with the requested number of bytes
+	 */
+	while (incnt > 0) {
+		cnt = bufend - bufpt;
+		if ((cnt <= 0) && ((cnt = buf_fill()) <= 0)) {
+			/*
+			 * read error, return what we got (or the error if
+			 * no data was copied). The caller must know that an
+			 * error occured and has the best knowledge what to
+			 * do with it
+			 */
+			if ((res = cpcnt - incnt) > 0)
+				return(res);
+			return(cnt);
+		}
+
+		/*
+		 * calculate how much data to copy based on whats left and
+		 * state of buffer
+		 */
+		cnt = MIN(cnt, incnt);
+		memcpy(in, bufpt, cnt);
+		bufpt += cnt;
+		incnt -= cnt;
+		in += cnt;
+	}
+	return(cpcnt);
+}
+
+/*
+ * wr_skip()
+ *	skip forward during a write. In other words add padding to the file.
+ *	we add zero filled padding as it makes flawed archives much easier to
+ *	recover from. the caller tells us how many bytes of padding to add
+ *	This routine was not designed to add HUGE amount of padding, just small
+ *	amounts (a few 512 byte blocks at most)
+ * Return:
+ *	0 if ok, -1 if there was a buf_flush failure
+ */
+
+int
+wr_skip(off_t skcnt)
+{
+	int cnt;
+
+	/*
+	 * loop while there is more padding to add
+	 */
+	while (skcnt > 0L) {
+		cnt = bufend - bufpt;
+		if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0))
+			return(-1);
+		cnt = MIN(cnt, skcnt);
+		memset(bufpt, 0, cnt);
+		bufpt += cnt;
+		skcnt -= cnt;
+	}
+	return(0);
+}
+
+/*
+ * wr_rdfile()
+ *	fill write buffer with the contents of a file. We are passed an	open
+ *	file descriptor to the file and the archive structure that describes the
+ *	file we are storing. The variable "left" is modified to contain the
+ *	number of bytes of the file we were NOT able to write to the archive.
+ *	it is important that we always write EXACTLY the number of bytes that
+ *	the format specific write routine told us to. The file can also get
+ *	bigger, so reading to the end of file would create an improper archive,
+ *	we just detect this case and warn the user. We never create a bad
+ *	archive if we can avoid it. Of course trying to archive files that are
+ *	active is asking for trouble. It we fail, we pass back how much we
+ *	could NOT copy and let the caller deal with it.
+ * Return:
+ *	0 ok, -1 if archive write failure. a short read of the file returns a
+ *	0, but "left" is set to be greater than zero.
+ */
+
+int
+wr_rdfile(ARCHD *arcn, int ifd, off_t *left)
+{
+	int cnt;
+	int res = 0;
+	off_t size = arcn->sb.st_size;
+	struct stat sb;
+
+	/*
+	 * while there are more bytes to write
+	 */
+	while (size > 0L) {
+		cnt = bufend - bufpt;
+		if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0)) {
+			*left = size;
+			return(-1);
+		}
+		cnt = MIN(cnt, size);
+		if ((res = read(ifd, bufpt, cnt)) <= 0)
+			break;
+		size -= res;
+		bufpt += res;
+	}
+
+	/*
+	 * better check the file did not change during this operation
+	 * or the file read failed.
+	 */
+	if (res < 0)
+		syswarn(1, errno, "Read fault on %s", arcn->org_name);
+	else if (size != 0L)
+		paxwarn(1, "File changed size during read %s", arcn->org_name);
+	else if (fstat(ifd, &sb) < 0)
+		syswarn(1, errno, "Failed stat on %s", arcn->org_name);
+	else if (arcn->sb.st_mtime != sb.st_mtime)
+		paxwarn(1, "File %s was modified during copy to archive",
+			arcn->org_name);
+	*left = size;
+	return(0);
+}
+
+/*
+ * rd_wrfile()
+ *	extract the contents of a file from the archive. If we are unable to
+ *	extract the entire file (due to failure to write the file) we return
+ *	the numbers of bytes we did NOT process. This way the caller knows how
+ *	many bytes to skip past to find the next archive header. If the failure
+ *	was due to an archive read, we will catch that when we try to skip. If
+ *	the format supplies a file data crc value, we calculate the actual crc
+ *	so that it can be compared to the value stored in the header
+ * NOTE:
+ *	We call a special function to write the file. This function attempts to
+ *	restore file holes (blocks of zeros) into the file. When files are
+ *	sparse this saves space, and is a LOT faster. For non sparse files
+ *	the performance hit is small. As of this writing, no archive supports
+ *	information on where the file holes are.
+ * Return:
+ *	0 ok, -1 if archive read failure. if we cannot write the entire file,
+ *	we return a 0 but "left" is set to be the amount unwritten
+ */
+
+int
+rd_wrfile(ARCHD *arcn, int ofd, off_t *left)
+{
+	int cnt = 0;
+	off_t size = arcn->sb.st_size;
+	int res = 0;
+	char *fnm = arcn->name;
+	int isem = 1;
+	int rem;
+	int sz = MINFBSZ;
+ 	struct stat sb;
+	u_long crc = 0L;
+
+	/*
+	 * pass the blocksize of the file being written to the write routine,
+	 * if the size is zero, use the default MINFBSZ
+	 */
+	if (fstat(ofd, &sb) == 0) {
+#if 0
+	/* not under minix */
+		if (sb.st_blksize > 0)
+			sz = (int)sb.st_blksize;
+#endif
+	} else
+		syswarn(0,errno,"Unable to obtain block size for file %s",fnm);
+	rem = sz;
+	*left = 0L;
+
+	/*
+	 * Copy the archive to the file the number of bytes specified. We have
+	 * to assume that we want to recover file holes as none of the archive
+	 * formats can record the location of file holes.
+	 */
+	while (size > 0L) {
+		cnt = bufend - bufpt;
+		/*
+		 * if we get a read error, we do not want to skip, as we may
+		 * miss a header, so we do not set left, but if we get a write
+		 * error, we do want to skip over the unprocessed data.
+		 */
+		if ((cnt <= 0) && ((cnt = buf_fill()) <= 0))
+			break;
+		cnt = MIN(cnt, size);
+		if ((res = file_write(ofd,bufpt,cnt,&rem,&isem,sz,fnm)) <= 0) {
+			*left = size;
+			break;
+		}
+
+		if (docrc) {
+			/*
+			 * update the actual crc value
+			 */
+			cnt = res;
+			while (--cnt >= 0)
+				crc += *bufpt++ & 0xff;
+		} else
+			bufpt += res;
+		size -= res;
+	}
+
+	/*
+	 * if the last block has a file hole (all zero), we must make sure this
+	 * gets updated in the file. We force the last block of zeros to be
+	 * written. just closing with the file offset moved forward may not put
+	 * a hole at the end of the file.
+	 */
+	if (isem && (arcn->sb.st_size > 0L))
+		file_flush(ofd, fnm, isem);
+
+	/*
+	 * if we failed from archive read, we do not want to skip
+	 */
+	if ((size > 0L) && (*left == 0L))
+		return(-1);
+
+	/*
+	 * some formats record a crc on file data. If so, then we compare the
+	 * calculated crc to the crc stored in the archive
+	 */
+	if (docrc && (size == 0L) && (arcn->crc != crc))
+		paxwarn(1,"Actual crc does not match expected crc %s",arcn->name);
+	return(0);
+}
+
+/*
+ * cp_file()
+ *	copy the contents of one file to another. used during -rw phase of pax
+ *	just as in rd_wrfile() we use a special write function to write the
+ *	destination file so we can properly copy files with holes.
+ */
+
+void
+cp_file(ARCHD *arcn, int fd1, int fd2)
+{
+	int cnt;
+	off_t cpcnt = 0L;
+	int res = 0;
+	char *fnm = arcn->name;
+	int no_hole = 0;
+	int isem = 1;
+	int rem;
+	int sz = MINFBSZ;
+	struct stat sb;
+
+	/*
+	 * check for holes in the source file. If none, we will use regular
+	 * write instead of file write.
+	 */
+#if 0
+	/* not under minix */
+	 if (((off_t)(arcn->sb.st_blocks * BLKMULT)) >= arcn->sb.st_size)
+#endif
+		++no_hole;
+
+	/*
+	 * pass the blocksize of the file being written to the write routine,
+	 * if the size is zero, use the default MINFBSZ
+	 */
+	if (fstat(fd2, &sb) == 0) {
+#if 0
+	/* not under minix */
+		if (sb.st_blksize > 0)
+			sz = sb.st_blksize;
+#endif
+	} else
+		syswarn(0,errno,"Unable to obtain block size for file %s",fnm);
+	rem = sz;
+
+	/*
+	 * read the source file and copy to destination file until EOF
+	 */
+	for(;;) {
+		if ((cnt = read(fd1, buf, blksz)) <= 0)
+			break;
+		if (no_hole)
+			res = write(fd2, buf, cnt);
+		else
+			res = file_write(fd2, buf, cnt, &rem, &isem, sz, fnm);
+		if (res != cnt)
+			break;
+		cpcnt += cnt;
+	}
+
+	/*
+	 * check to make sure the copy is valid.
+	 */
+	if (res < 0)
+		syswarn(1, errno, "Failed write during copy of %s to %s",
+			arcn->org_name, arcn->name);
+	else if (cpcnt != arcn->sb.st_size)
+		paxwarn(1, "File %s changed size during copy to %s",
+			arcn->org_name, arcn->name);
+	else if (fstat(fd1, &sb) < 0)
+		syswarn(1, errno, "Failed stat of %s", arcn->org_name);
+	else if (arcn->sb.st_mtime != sb.st_mtime)
+		paxwarn(1, "File %s was modified during copy to %s",
+			arcn->org_name, arcn->name);
+
+	/*
+	 * if the last block has a file hole (all zero), we must make sure this
+	 * gets updated in the file. We force the last block of zeros to be
+	 * written. just closing with the file offset moved forward may not put
+	 * a hole at the end of the file.
+	 */
+	if (!no_hole && isem && (arcn->sb.st_size > 0L))
+		file_flush(fd2, fnm, isem);
+	return;
+}
+
+/*
+ * buf_fill()
+ *	fill the read buffer with the next record (or what we can get) from
+ *	the archive volume.
+ * Return:
+ *	Number of bytes of data in the read buffer, -1 for read error, and
+ *	0 when finished (user specified termination in ar_next()).
+ */
+
+int
+buf_fill(void)
+{
+	int cnt;
+	static int fini = 0;
+
+	if (fini)
+		return(0);
+
+	for(;;) {
+		/*
+		 * try to fill the buffer. on error the next archive volume is
+		 * opened and we try again.
+		 */
+		if ((cnt = ar_read(buf, blksz)) > 0) {
+			bufpt = buf;
+			bufend = buf + cnt;
+			rdcnt += cnt;
+			return(cnt);
+		}
+
+		/*
+		 * errors require resync, EOF goes to next archive
+		 */
+		if (cnt < 0)
+			break;
+		if (ar_next() < 0) {
+			fini = 1;
+			return(0);
+		}
+		rdcnt = 0;
+	}
+	exit_val = 1;
+	return(-1);
+}
+
+/*
+ * buf_flush()
+ *	force the write buffer to the archive. We are passed the number of
+ *	bytes in the buffer at the point of the flush. When we change archives
+ *	the record size might change. (either larger or smaller).
+ * Return:
+ *	0 if all is ok, -1 when a write error occurs.
+ */
+
+int
+buf_flush(int bufcnt)
+{
+	int cnt;
+	int push = 0;
+	int totcnt = 0;
+
+	/*
+	 * if we have reached the user specified byte count for each archive
+	 * volume, prompt for the next volume. (The non-standrad -R flag).
+	 * NOTE: If the wrlimit is smaller than wrcnt, we will always write
+	 * at least one record. We always round limit UP to next blocksize.
+	 */
+	if ((wrlimit > 0) && (wrcnt > wrlimit)) {
+		paxwarn(0, "User specified archive volume byte limit reached.");
+		if (ar_next() < 0) {
+			wrcnt = 0;
+			exit_val = 1;
+			return(-1);
+		}
+		wrcnt = 0;
+
+		/*
+		 * The new archive volume might have changed the size of the
+		 * write blocksize. if so we figure out if we need to write
+		 * (one or more times), or if there is now free space left in
+		 * the buffer (it is no longer full). bufcnt has the number of
+		 * bytes in the buffer, (the blocksize, at the point we were
+		 * CALLED). Push has the amount of "extra" data in the buffer
+		 * if the block size has shrunk from a volume change.
+		 */
+		bufend = buf + blksz;
+		if (blksz > bufcnt)
+			return(0);
+		if (blksz < bufcnt)
+			push = bufcnt - blksz;
+	}
+
+	/*
+	 * We have enough data to write at least one archive block
+	 */
+	for (;;) {
+		/*
+		 * write a block and check if it all went out ok
+		 */
+		cnt = ar_write(buf, blksz);
+		if (cnt == blksz) {
+			/*
+			 * the write went ok
+			 */
+			wrcnt += cnt;
+			totcnt += cnt;
+			if (push > 0) {
+				/* we have extra data to push to the front.
+				 * check for more than 1 block of push, and if
+				 * so we loop back to write again
+				 */
+				memcpy(buf, bufend, push);
+				bufpt = buf + push;
+				if (push >= blksz) {
+					push -= blksz;
+					continue;
+				}
+			} else
+				bufpt = buf;
+			return(totcnt);
+		} else if (cnt > 0) {
+			/*
+			 * Oh drat we got a partial write!
+			 * if format doesnt care about alignment let it go,
+			 * we warned the user in ar_write().... but this means
+			 * the last record on this volume violates pax spec....
+			 */
+			totcnt += cnt;
+			wrcnt += cnt;
+			bufpt = buf + cnt;
+			cnt = bufcnt - cnt;
+			memcpy(buf, bufpt, cnt);
+			bufpt = buf + cnt;
+			if (!frmt->blkalgn || ((cnt % frmt->blkalgn) == 0))
+				return(totcnt);
+			break;
+		}
+
+		/*
+		 * All done, go to next archive
+		 */
+		wrcnt = 0;
+		if (ar_next() < 0)
+			break;
+
+		/*
+		 * The new archive volume might also have changed the block
+		 * size. if so, figure out if we have too much or too little
+		 * data for using the new block size
+		 */
+		bufend = buf + blksz;
+		if (blksz > bufcnt)
+			return(0);
+		if (blksz < bufcnt)
+			push = bufcnt - blksz;
+	}
+
+	/*
+	 * write failed, stop pax. we must not create a bad archive!
+	 */
+	exit_val = 1;
+	return(-1);
+}
Index: /trunk/minix/commands/pax/build
===================================================================
--- /trunk/minix/commands/pax/build	(revision 9)
+++ /trunk/minix/commands/pax/build	(revision 9)
@@ -0,0 +1,1 @@
+make
Index: /trunk/minix/commands/pax/cache.c
===================================================================
--- /trunk/minix/commands/pax/cache.c	(revision 9)
+++ /trunk/minix/commands/pax/cache.c	(revision 9)
@@ -0,0 +1,430 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)cache.c	8.1 (Berkeley) 5/31/93";
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdio.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "pax.h"
+#include "cache.h"
+#include "extern.h"
+
+/*
+ * routines that control user, group, uid and gid caches (for the archive
+ * member print routine).
+ * IMPORTANT:
+ * these routines cache BOTH hits and misses, a major performance improvement
+ */
+
+static	int pwopn = 0;		/* is password file open */
+static	int gropn = 0;		/* is group file open */
+static UIDC **uidtb = NULL;	/* uid to name cache */
+static GIDC **gidtb = NULL;	/* gid to name cache */
+static UIDC **usrtb = NULL;	/* user name to uid cache */
+static GIDC **grptb = NULL;	/* group name to gid cache */
+
+/*
+ * uidtb_start
+ *	creates an an empty uidtb
+ * Return:
+ *	0 if ok, -1 otherwise
+ */
+
+int
+uidtb_start(void)
+{
+	static int fail = 0;
+
+	if (uidtb != NULL)
+		return(0);
+	if (fail)
+		return(-1);
+	if ((uidtb = (UIDC **)calloc(UID_SZ, sizeof(UIDC *))) == NULL) {
+		++fail;
+		paxwarn(1, "Unable to allocate memory for user id cache table");
+		return(-1);
+	}
+	return(0);
+}
+
+/*
+ * gidtb_start
+ *	creates an an empty gidtb
+ * Return:
+ *	0 if ok, -1 otherwise
+ */
+
+int
+gidtb_start(void)
+{
+	static int fail = 0;
+
+	if (gidtb != NULL)
+		return(0);
+	if (fail)
+		return(-1);
+	if ((gidtb = (GIDC **)calloc(GID_SZ, sizeof(GIDC *))) == NULL) {
+		++fail;
+		paxwarn(1, "Unable to allocate memory for group id cache table");
+		return(-1);
+	}
+	return(0);
+}
+
+/*
+ * usrtb_start
+ *	creates an an empty usrtb
+ * Return:
+ *	0 if ok, -1 otherwise
+ */
+
+int
+usrtb_start(void)
+{
+	static int fail = 0;
+
+	if (usrtb != NULL)
+		return(0);
+	if (fail)
+		return(-1);
+	if ((usrtb = (UIDC **)calloc(UNM_SZ, sizeof(UIDC *))) == NULL) {
+		++fail;
+		paxwarn(1, "Unable to allocate memory for user name cache table");
+		return(-1);
+	}
+	return(0);
+}
+
+/*
+ * grptb_start
+ *	creates an an empty grptb
+ * Return:
+ *	0 if ok, -1 otherwise
+ */
+
+int
+grptb_start(void)
+{
+	static int fail = 0;
+
+	if (grptb != NULL)
+		return(0);
+	if (fail)
+		return(-1);
+	if ((grptb = (GIDC **)calloc(GNM_SZ, sizeof(GIDC *))) == NULL) {
+		++fail;
+		paxwarn(1,"Unable to allocate memory for group name cache table");
+		return(-1);
+	}
+	return(0);
+}
+
+/*
+ * name_uid()
+ *	caches the name (if any) for the uid. If frc set, we always return the
+ *	the stored name (if valid or invalid match). We use a simple hash table.
+ * Return
+ *	Pointer to stored name (or an empty string).
+ */
+
+const char *
+name_uid(uid_t uid, int frc)
+{
+	struct passwd *pw;
+	UIDC *ptr;
+
+	if ((uidtb == NULL) && (uidtb_start() < 0))
+		return("");
+
+	/*
+	 * see if we have this uid cached
+	 */
+	ptr = uidtb[uid % UID_SZ];
+	if ((ptr != NULL) && (ptr->valid > 0) && (ptr->uid == uid)) {
+		/*
+		 * have an entry for this uid
+		 */
+		if (frc || (ptr->valid == VALID))
+			return(ptr->name);
+		return("");
+	}
+
+	/*
+	 * No entry for this uid, we will add it
+	 */
+	if (!pwopn) {
+		setpassent(1);
+		++pwopn;
+	}
+	if (ptr == NULL)
+		ptr = uidtb[uid % UID_SZ] = (UIDC *)malloc(sizeof(UIDC));
+
+	if ((pw = getpwuid(uid)) == NULL) {
+		/*
+		 * no match for this uid in the local password file
+		 * a string that is the uid in numeric format
+		 */
+		if (ptr == NULL)
+			return("");
+		ptr->uid = uid;
+		ptr->valid = INVALID;
+#		ifdef NET2_STAT
+		(void)snprintf(ptr->name, sizeof(ptr->name), "%u", uid);
+#		else
+		(void)snprintf(ptr->name, sizeof(ptr->name), "%lu",
+			       (unsigned long)uid);
+#		endif
+		if (frc == 0)
+			return("");
+	} else {
+		/*
+		 * there is an entry for this uid in the password file
+		 */
+		if (ptr == NULL)
+			return(pw->pw_name);
+		ptr->uid = uid;
+		(void)strncpy(ptr->name, pw->pw_name, UNMLEN - 1);
+		ptr->name[UNMLEN-1] = '\0';
+		ptr->valid = VALID;
+	}
+	return(ptr->name);
+}
+
+/*
+ * name_gid()
+ *	caches the name (if any) for the gid. If frc set, we always return the
+ *	the stored name (if valid or invalid match). We use a simple hash table.
+ * Return
+ *	Pointer to stored name (or an empty string).
+ */
+
+const char *
+name_gid(gid_t gid, int frc)
+{
+	struct group *gr;
+	GIDC *ptr;
+
+	if ((gidtb == NULL) && (gidtb_start() < 0))
+		return("");
+
+	/*
+	 * see if we have this gid cached
+	 */
+	ptr = gidtb[gid % GID_SZ];
+	if ((ptr != NULL) && (ptr->valid > 0) && (ptr->gid == gid)) {
+		/*
+		 * have an entry for this gid
+		 */
+		if (frc || (ptr->valid == VALID))
+			return(ptr->name);
+		return("");
+	}
+
+	/*
+	 * No entry for this gid, we will add it
+	 */
+	if (!gropn) {
+		setgroupent(1);
+		++gropn;
+	}
+	if (ptr == NULL)
+		ptr = gidtb[gid % GID_SZ] = (GIDC *)malloc(sizeof(GIDC));
+
+	if ((gr = getgrgid(gid)) == NULL) {
+		/*
+		 * no match for this gid in the local group file, put in
+		 * a string that is the gid in numeric format
+		 */
+		if (ptr == NULL)
+			return("");
+		ptr->gid = gid;
+		ptr->valid = INVALID;
+#		ifdef NET2_STAT
+		(void)snprintf(ptr->name, sizeof(ptr->name), "%u", gid);
+#		else
+		(void)snprintf(ptr->name, sizeof(ptr->name), "%lu",
+			       (unsigned long)gid);
+#		endif
+		if (frc == 0)
+			return("");
+	} else {
+		/*
+		 * there is an entry for this group in the group file
+		 */
+		if (ptr == NULL)
+			return(gr->gr_name);
+		ptr->gid = gid;
+		(void)strncpy(ptr->name, gr->gr_name, GNMLEN - 1);
+		ptr->name[GNMLEN-1] = '\0';
+		ptr->valid = VALID;
+	}
+	return(ptr->name);
+}
+
+/*
+ * uid_name()
+ *	caches the uid for a given user name. We use a simple hash table.
+ * Return
+ *	the uid (if any) for a user name, or a -1 if no match can be found
+ */
+
+int
+uid_name(char *name, uid_t *uid)
+{
+	struct passwd *pw;
+	UIDC *ptr;
+	int namelen;
+
+	/*
+	 * return -1 for mangled names
+	 */
+	if (((namelen = strlen(name)) == 0) || (name[0] == '\0'))
+		return(-1);
+	if ((usrtb == NULL) && (usrtb_start() < 0))
+		return(-1);
+
+	/*
+	 * look up in hash table, if found and valid return the uid,
+	 * if found and invalid, return a -1
+	 */
+	ptr = usrtb[st_hash(name, namelen, UNM_SZ)];
+	if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
+		if (ptr->valid == INVALID)
+			return(-1);
+		*uid = ptr->uid;
+		return(0);
+	}
+
+	if (!pwopn) {
+		setpassent(1);
+		++pwopn;
+	}
+
+	if (ptr == NULL)
+		ptr = usrtb[st_hash(name, namelen, UNM_SZ)] =
+		  (UIDC *)malloc(sizeof(UIDC));
+
+	/*
+	 * no match, look it up, if no match store it as an invalid entry,
+	 * or store the matching uid
+	 */
+	if (ptr == NULL) {
+		if ((pw = getpwnam(name)) == NULL)
+			return(-1);
+		*uid = pw->pw_uid;
+		return(0);
+	}
+	(void)strncpy(ptr->name, name, UNMLEN - 1);
+	ptr->name[UNMLEN-1] = '\0';
+	if ((pw = getpwnam(name)) == NULL) {
+		ptr->valid = INVALID;
+		return(-1);
+	}
+	ptr->valid = VALID;
+	*uid = ptr->uid = pw->pw_uid;
+	return(0);
+}
+
+/*
+ * gid_name()
+ *	caches the gid for a given group name. We use a simple hash table.
+ * Return
+ *	the gid (if any) for a group name, or a -1 if no match can be found
+ */
+
+int
+gid_name(char *name, gid_t *gid)
+{
+	struct group *gr;
+	GIDC *ptr;
+	int namelen;
+
+	/*
+	 * return -1 for mangled names
+	 */
+	if (((namelen = strlen(name)) == 0) || (name[0] == '\0'))
+		return(-1);
+	if ((grptb == NULL) && (grptb_start() < 0))
+		return(-1);
+
+	/*
+	 * look up in hash table, if found and valid return the uid,
+	 * if found and invalid, return a -1
+	 */
+	ptr = grptb[st_hash(name, namelen, GID_SZ)];
+	if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
+		if (ptr->valid == INVALID)
+			return(-1);
+		*gid = ptr->gid;
+		return(0);
+	}
+
+	if (!gropn) {
+		setgroupent(1);
+		++gropn;
+	}
+	if (ptr == NULL)
+		ptr = grptb[st_hash(name, namelen, GID_SZ)] =
+		  (GIDC *)malloc(sizeof(GIDC));
+
+	/*
+	 * no match, look it up, if no match store it as an invalid entry,
+	 * or store the matching gid
+	 */
+	if (ptr == NULL) {
+		if ((gr = getgrnam(name)) == NULL)
+			return(-1);
+		*gid = gr->gr_gid;
+		return(0);
+	}
+
+	(void)strncpy(ptr->name, name, GNMLEN - 1);
+	ptr->name[GNMLEN-1] = '\0';
+	if ((gr = getgrnam(name)) == NULL) {
+		ptr->valid = INVALID;
+		return(-1);
+	}
+	ptr->valid = VALID;
+	*gid = ptr->gid = gr->gr_gid;
+	return(0);
+}
Index: /trunk/minix/commands/pax/cache.h
===================================================================
--- /trunk/minix/commands/pax/cache.h	(revision 9)
+++ /trunk/minix/commands/pax/cache.h	(revision 9)
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *      @(#)cache.h	8.1 (Berkeley) 5/31/93
+ * $FreeBSD: src/bin/pax/cache.h,v 1.9 2004/04/06 20:06:48 markm Exp $
+ */
+
+/*
+ * Constants and data structures used to implement group and password file
+ * caches. Traditional passwd/group cache routines perform quite poorly with
+ * archives. The chances of hitting a valid lookup with an archive is quite a
+ * bit worse than with files already resident on the file system. These misses
+ * create a MAJOR performance cost. To address this problem, these routines
+ * cache both hits and misses.
+ *
+ * NOTE:  name lengths must be as large as those stored in ANY PROTOCOL and
+ * as stored in the passwd and group files. CACHE SIZES MUST BE PRIME
+ */
+#define UNMLEN		32	/* >= user name found in any protocol */
+#define GNMLEN		32	/* >= group name found in any protocol */
+#define UID_SZ		317	/* size of user_name/uid cache */
+#define UNM_SZ		317	/* size of user_name/uid cache */
+#define GID_SZ		251	/* size of gid cache */
+#define GNM_SZ		317	/* size of group name cache */
+#define VALID		1	/* entry and name are valid */
+#define INVALID		2	/* entry valid, name NOT valid */
+
+/*
+ * Node structures used in the user, group, uid, and gid caches.
+ */
+
+typedef struct uidc {
+	int valid;		/* is this a valid or a miss entry */
+	char name[UNMLEN];	/* uid name */
+	uid_t uid;		/* cached uid */
+} UIDC;
+
+typedef struct gidc {
+	int valid;		/* is this a valid or a miss entry */
+	char name[GNMLEN];	/* gid name */
+	gid_t gid;		/* cached gid */
+} GIDC;
Index: /trunk/minix/commands/pax/cpio.c
===================================================================
--- /trunk/minix/commands/pax/cpio.c	(revision 9)
+++ /trunk/minix/commands/pax/cpio.c	(revision 9)
@@ -0,0 +1,1152 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)cpio.c	8.1 (Berkeley) 5/31/93";
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "pax.h"
+#include "cpio.h"
+#include "extern.h"
+
+static int rd_nm(ARCHD *, int);
+static int rd_ln_nm(ARCHD *);
+static int com_rd(ARCHD *);
+
+/*
+ * Routines which support the different cpio versions
+ */
+
+static int swp_head;		/* binary cpio header byte swap */
+
+/*
+ * Routines common to all versions of cpio
+ */
+
+/*
+ * cpio_strd()
+ *	Fire up the hard link detection code
+ * Return:
+ *      0 if ok -1 otherwise (the return values of lnk_start())
+ */
+
+int
+cpio_strd(void)
+{
+	return(lnk_start());
+}
+
+/*
+ * cpio_trail()
+ *	Called to determine if a header block is a valid trailer. We are
+ *	passed the block, the in_sync flag (which tells us we are in resync
+ *	mode; looking for a valid header), and cnt (which starts at zero)
+ *	which is used to count the number of empty blocks we have seen so far.
+ * Return:
+ *	0 if a valid trailer, -1 if not a valid trailer,
+ */
+
+int
+cpio_trail(ARCHD *arcn)
+{
+	/*
+	 * look for trailer id in file we are about to process
+	 */
+	if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0))
+		return(0);
+	return(-1);
+}
+
+/*
+ * com_rd()
+ *	operations common to all cpio read functions.
+ * Return:
+ *	0
+ */
+
+static int
+com_rd(ARCHD *arcn)
+{
+	arcn->skip = 0;
+	arcn->pat = NULL;
+	arcn->org_name = arcn->name;
+	switch(arcn->sb.st_mode & C_IFMT) {
+	case C_ISFIFO:
+		arcn->type = PAX_FIF;
+		break;
+	case C_ISDIR:
+		arcn->type = PAX_DIR;
+		break;
+	case C_ISBLK:
+		arcn->type = PAX_BLK;
+		break;
+	case C_ISCHR:
+		arcn->type = PAX_CHR;
+		break;
+	case C_ISLNK:
+		arcn->type = PAX_SLK;
+		break;
+	case C_ISOCK:
+		arcn->type = PAX_SCK;
+		break;
+	case C_ISCTG:
+	case C_ISREG:
+	default:
+		/*
+		 * we have file data, set up skip (pad is set in the format
+		 * specific sections)
+		 */
+		arcn->sb.st_mode = (arcn->sb.st_mode & 0xfff) | C_ISREG;
+		arcn->type = PAX_REG;
+		arcn->skip = arcn->sb.st_size;
+		break;
+	}
+	if (chk_lnk(arcn) < 0)
+		return(-1);
+	return(0);
+}
+
+/*
+ * cpio_end_wr()
+ *	write the special file with the name trailer in the proper format
+ * Return:
+ *	result of the write of the trailer from the cpio specific write func
+ */
+
+int
+cpio_endwr(void)
+{
+	ARCHD last;
+
+	/*
+	 * create a trailer request and call the proper format write function
+	 */
+	memset(&last, 0, sizeof(last));
+	last.nlen = sizeof(TRAILER) - 1;
+	last.type = PAX_REG;
+	last.sb.st_nlink = 1;
+	(void)strcpy(last.name, TRAILER);
+	return((*frmt->wr)(&last));
+}
+
+/*
+ * rd_nam()
+ *	read in the file name which follows the cpio header
+ * Return:
+ *	0 if ok, -1 otherwise
+ */
+
+static int
+rd_nm(ARCHD *arcn, int nsz)
+{
+	/*
+	 * do not even try bogus values
+	 */
+	if ((nsz == 0) || (nsz > (int)sizeof(arcn->name))) {
+		paxwarn(1, "Cpio file name length %d is out of range", nsz);
+		return(-1);
+	}
+
+	/*
+	 * read the name and make sure it is not empty and is \0 terminated
+	 */
+	if ((rd_wrbuf(arcn->name,nsz) != nsz) || (arcn->name[nsz-1] != '\0') ||
+	    (arcn->name[0] == '\0')) {
+		paxwarn(1, "Cpio file name in header is corrupted");
+		return(-1);
+	}
+	return(0);
+}
+
+/*
+ * rd_ln_nm()
+ *	read in the link name for a file with links. The link name is stored
+ *	like file data (and is NOT \0 terminated!)
+ * Return:
+ *	0 if ok, -1 otherwise
+ */
+
+static int
+rd_ln_nm(ARCHD *arcn)
+{
+	/*
+	 * check the length specified for bogus values
+	 */
+	if ((arcn->sb.st_size == 0) ||
+	    ((size_t)arcn->sb.st_size >= sizeof(arcn->ln_name))) {
+#		ifdef NET2_STAT
+		paxwarn(1, "Cpio link name length is invalid: %lu",
+		    arcn->sb.st_size);
+#		else
+		paxwarn(1, "Cpio link name length is invalid: %ju",
+		    (uintmax_t)arcn->sb.st_size);
+#		endif
+		return(-1);
+	}
+
+	/*
+	 * read in the link name and \0 terminate it
+	 */
+	if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) !=
+	    (int)arcn->sb.st_size) {
+		paxwarn(1, "Cpio link name read error");
+		return(-1);
+	}
+	arcn->ln_nlen = arcn->sb.st_size;
+	arcn->ln_name[arcn->ln_nlen] = '\0';
+
+	/*
+	 * watch out for those empty link names
+	 */
+	if (arcn->ln_name[0] == '\0') {
+		paxwarn(1, "Cpio link name is corrupt");
+		return(-1);
+	}
+	return(0);
+}
+
+/*
+ * Routines common to the extended byte oriented cpio format
+ */
+
+/*
+ * cpio_id()
+ *      determine if a block given to us is a valid extended byte oriented
+ *	cpio header
+ * Return:
+ *      0 if a valid header, -1 otherwise
+ */
+
+int
+cpio_id(char *blk, int size)
+{
+	if ((size < (int)sizeof(HD_CPIO)) ||
+	    (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0))
+		return(-1);
+	return(0);
+}
+
+/*
+ * cpio_rd()
+ *	determine if a buffer is a byte oriented extended cpio archive entry.
+ *	convert and store the values in the ARCHD parameter.
+ * Return:
+ *	0 if a valid header, -1 otherwise.
+ */
+
+int
+cpio_rd(ARCHD *arcn, char *buf)
+{
+	int nsz;
+	HD_CPIO *hd;
+
+	/*
+	 * check that this is a valid header, if not return -1
+	 */
+	if (cpio_id(buf, sizeof(HD_CPIO)) < 0)
+		return(-1);
+	hd = (HD_CPIO *)buf;
+
+	/*
+	 * byte oriented cpio (posix) does not have padding! extract the octal
+	 * ascii fields from the header
+	 */
+	arcn->pad = 0L;
+	arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT);
+	arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT);
+	arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT);
+	arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT);
+	arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT);
+	arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
+	    OCT);
+	arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT);
+#ifdef NET2_STAT
+	arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime),
+	    OCT);
+#else
+	arcn->sb.st_mtime = (time_t)asc_uqd(hd->c_mtime, sizeof(hd->c_mtime),
+	    OCT);
+#endif
+	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
+#ifdef NET2_STAT
+	arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize),
+	    OCT);
+#else
+	arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,sizeof(hd->c_filesize),
+	    OCT);
+#endif
+
+	/*
+	 * check name size and if valid, read in the name of this entry (name
+	 * follows header in the archive)
+	 */
+	if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2)
+		return(-1);
+	arcn->nlen = nsz - 1;
+	if (rd_nm(arcn, nsz) < 0)
+		return(-1);
+
+	if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
+		/*
+	 	 * no link name to read for this file
+	 	 */
+		arcn->ln_nlen = 0;
+		arcn->ln_name[0] = '\0';
+		return(com_rd(arcn));
+	}
+
+	/*
+	 * check link name size and read in the link name. Link names are
+	 * stored like file data.
+	 */
+	if (rd_ln_nm(arcn) < 0)
+		return(-1);
+
+	/*
+	 * we have a valid header (with a link)
+	 */
+	return(com_rd(arcn));
+}
+
+/*
+ * cpio_endrd()
+ *      no cleanup needed here, just return size of the trailer (for append)
+ * Return:
+ *      size of trailer header in this format
+ */
+
+off_t
+cpio_endrd(void)
+{
+	return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER)));
+}
+
+/*
+ * cpio_stwr()
+ *	start up the device mapping table
+ * Return:
+ *	0 if ok, -1 otherwise (what dev_start() returns)
+ */
+
+int
+cpio_stwr(void)
+{
+	return(dev_start());
+}
+
+/*
+ * cpio_wr()
+ *	copy the data in the ARCHD to buffer in extended byte oriented cpio
+ *	format.
+ * Return
+ *      0 if file has data to be written after the header, 1 if file has NO
+ *	data to write after the header, -1 if archive write failed
+ */
+
+int
+cpio_wr(ARCHD *arcn)
+{
+	HD_CPIO *hd;
+	int nsz;
+	char hdblk[sizeof(HD_CPIO)];
+
+	/*
+	 * check and repair truncated device and inode fields in the header
+	 */
+	if (map_dev(arcn, (u_long)CPIO_MASK, (u_long)CPIO_MASK) < 0)
+		return(-1);
+
+	arcn->pad = 0L;
+	nsz = arcn->nlen + 1;
+	hd = (HD_CPIO *)hdblk;
+	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
+		arcn->sb.st_rdev = 0;
+
+	switch(arcn->type) {
+	case PAX_CTG:
+	case PAX_REG:
+	case PAX_HRG:
+		/*
+		 * set data size for file data
+		 */
+#		ifdef NET2_STAT
+		if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
+		    sizeof(hd->c_filesize), OCT)) {
+#		else
+		if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
+		    sizeof(hd->c_filesize), OCT)) {
+#		endif
+			paxwarn(1,"File is too large for cpio format %s",
+			    arcn->org_name);
+			return(1);
+		}
+		break;
+	case PAX_SLK:
+		/*
+		 * set data size to hold link name
+		 */
+		if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
+		    sizeof(hd->c_filesize), OCT))
+			goto out;
+		break;
+	default:
+		/*
+		 * all other file types have no file data
+		 */
+		if (ul_asc((u_long)0, hd->c_filesize, sizeof(hd->c_filesize),
+		     OCT))
+			goto out;
+		break;
+	}
+
+	/*
+	 * copy the values to the header using octal ascii
+	 */
+	if (ul_asc((u_long)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) ||
+	    ul_asc((u_long)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev),
+		OCT) ||
+	    ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
+		OCT) ||
+	    ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
+		OCT) ||
+	    ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
+		OCT) ||
+	    ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
+		OCT) ||
+	    ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
+		 OCT) ||
+	    ul_asc((u_long)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev),
+		OCT) ||
+	    ul_asc((u_long)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime),
+		OCT) ||
+	    ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT))
+		goto out;
+
+	/*
+	 * write the file name to the archive
+	 */
+	if ((wr_rdbuf(hdblk, (int)sizeof(HD_CPIO)) < 0) ||
+	    (wr_rdbuf(arcn->name, nsz) < 0)) {
+		paxwarn(1, "Unable to write cpio header for %s", arcn->org_name);
+		return(-1);
+	}
+
+	/*
+	 * if this file has data, we are done. The caller will write the file
+	 * data, if we are link tell caller we are done, go to next file
+	 */
+	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
+	    (arcn->type == PAX_HRG))
+		return(0);
+	if (arcn->type != PAX_SLK)
+		return(1);
+
+	/*
+	 * write the link name to the archive, tell the caller to go to the
+	 * next file as we are done.
+	 */
+	if (wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) {
+		paxwarn(1,"Unable to write cpio link name for %s",arcn->org_name);
+		return(-1);
+	}
+	return(1);
+
+    out:
+	/*
+	 * header field is out of range
+	 */
+	paxwarn(1, "Cpio header field is too small to store file %s",
+	    arcn->org_name);
+	return(1);
+}
+
+/*
+ * Routines common to the system VR4 version of cpio (with/without file CRC)
+ */
+
+/*
+ * vcpio_id()
+ *      determine if a block given to us is a valid system VR4 cpio header
+ *	WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header
+ *	uses HEX
+ * Return:
+ *      0 if a valid header, -1 otherwise
+ */
+
+int
+vcpio_id(char *blk, int size)
+{
+	if ((size < (int)sizeof(HD_VCPIO)) ||
+	    (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0))
+		return(-1);
+	return(0);
+}
+
+/*
+ * crc_id()
+ *      determine if a block given to us is a valid system VR4 cpio header
+ *	WITH crc. WATCH it the magic cookies are in OCTAL the header uses HEX
+ * Return:
+ *      0 if a valid header, -1 otherwise
+ */
+
+int
+crc_id(char *blk, int size)
+{
+	if ((size < (int)sizeof(HD_VCPIO)) ||
+	    (strncmp(blk, AVCMAGIC, (int)sizeof(AVCMAGIC) - 1) != 0))
+		return(-1);
+	return(0);
+}
+
+/*
+ * crc_strd()
+ w	set file data CRC calculations. Fire up the hard link detection code
+ * Return:
+ *      0 if ok -1 otherwise (the return values of lnk_start())
+ */
+
+int
+crc_strd(void)
+{
+	docrc = 1;
+	return(lnk_start());
+}
+
+/*
+ * vcpio_rd()
+ *	determine if a buffer is a system VR4 archive entry. (with/without CRC)
+ *	convert and store the values in the ARCHD parameter.
+ * Return:
+ *	0 if a valid header, -1 otherwise.
+ */
+
+int
+vcpio_rd(ARCHD *arcn, char *buf)
+{
+	HD_VCPIO *hd;
+	dev_t devminor;
+	dev_t devmajor;
+	int nsz;
+
+	/*
+	 * during the id phase it was determined if we were using CRC, use the
+	 * proper id routine.
+	 */
+	if (docrc) {
+		if (crc_id(buf, sizeof(HD_VCPIO)) < 0)
+			return(-1);
+	} else {
+		if (vcpio_id(buf, sizeof(HD_VCPIO)) < 0)
+			return(-1);
+	}
+
+	hd = (HD_VCPIO *)buf;
+	arcn->pad = 0L;
+
+	/*
+	 * extract the hex ascii fields from the header
+	 */
+	arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), HEX);
+	arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), HEX);
+	arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX);
+	arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX);
+#ifdef NET2_STAT
+	arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX);
+#else
+	arcn->sb.st_mtime = (time_t)asc_uqd(hd->c_mtime,sizeof(hd->c_mtime),HEX);
+#endif
+	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
+#ifdef NET2_STAT
+	arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,
+	    sizeof(hd->c_filesize), HEX);
+#else
+	arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,
+	    sizeof(hd->c_filesize), HEX);
+#endif
+	arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
+	    HEX);
+	devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX);
+	devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX);
+	arcn->sb.st_dev = TODEV(devmajor, devminor);
+	devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_maj), HEX);
+	devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_min), HEX);
+	arcn->sb.st_rdev = TODEV(devmajor, devminor);
+	arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX);
+
+	/*
+	 * check the length of the file name, if ok read it in, return -1 if
+	 * bogus
+	 */
+	if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2)
+		return(-1);
+	arcn->nlen = nsz - 1;
+	if (rd_nm(arcn, nsz) < 0)
+		return(-1);
+
+	/*
+	 * skip padding. header + filename is aligned to 4 byte boundries
+	 */
+	if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)
+		return(-1);
+
+	/*
+	 * if not a link (or a file with no data), calculate pad size (for
+	 * padding which follows the file data), clear the link name and return
+	 */
+	if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
+		/*
+		 * we have a valid header (not a link)
+		 */
+		arcn->ln_nlen = 0;
+		arcn->ln_name[0] = '\0';
+		arcn->pad = VCPIO_PAD(arcn->sb.st_size);
+		return(com_rd(arcn));
+	}
+
+	/*
+	 * read in the link name and skip over the padding
+	 */
+	if ((rd_ln_nm(arcn) < 0) ||
+	    (rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0))
+		return(-1);
+
+	/*
+	 * we have a valid header (with a link)
+	 */
+	return(com_rd(arcn));
+}
+
+/*
+ * vcpio_endrd()
+ *      no cleanup needed here, just return size of the trailer (for append)
+ * Return:
+ *      size of trailer header in this format
+ */
+
+off_t
+vcpio_endrd(void)
+{
+	return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) +
+		(VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER)))));
+}
+
+/*
+ * crc_stwr()
+ *	start up the device mapping table, enable crc file calculation
+ * Return:
+ *	0 if ok, -1 otherwise (what dev_start() returns)
+ */
+
+int
+crc_stwr(void)
+{
+	docrc = 1;
+	return(dev_start());
+}
+
+/*
+ * vcpio_wr()
+ *	copy the data in the ARCHD to buffer in system VR4 cpio
+ *	(with/without crc) format.
+ * Return
+ *	0 if file has data to be written after the header, 1 if file has
+ *	NO data to write after the header, -1 if archive write failed
+ */
+
+int
+vcpio_wr(ARCHD *arcn)
+{
+	HD_VCPIO *hd;
+	unsigned int nsz;
+	char hdblk[sizeof(HD_VCPIO)];
+
+	/*
+	 * check and repair truncated device and inode fields in the cpio
+	 * header
+	 */
+	if (map_dev(arcn, (u_long)VCPIO_MASK, (u_long)VCPIO_MASK) < 0)
+		return(-1);
+	nsz = arcn->nlen + 1;
+	hd = (HD_VCPIO *)hdblk;
+	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
+		arcn->sb.st_rdev = 0;
+
+	/*
+	 * add the proper magic value depending whether we were asked for
+	 * file data crc's, and the crc if needed.
+	 */
+	if (docrc) {
+		if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic),
+	    		OCT) ||
+		    ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum),
+	    		HEX))
+			goto out;
+	} else {
+		if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic),
+	    		OCT) ||
+		    ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX))
+			goto out;
+	}
+
+	switch(arcn->type) {
+	case PAX_CTG:
+	case PAX_REG:
+	case PAX_HRG:
+		/*
+		 * caller will copy file data to the archive. tell him how
+		 * much to pad.
+		 */
+		arcn->pad = VCPIO_PAD(arcn->sb.st_size);
+#		ifdef NET2_STAT
+		if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
+		    sizeof(hd->c_filesize), HEX)) {
+#		else
+		if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
+		    sizeof(hd->c_filesize), HEX)) {
+#		endif
+			paxwarn(1,"File is too large for sv4cpio format %s",
+			    arcn->org_name);
+			return(1);
+		}
+		break;
+	case PAX_SLK:
+		/*
+		 * no file data for the caller to process, the file data has
+		 * the size of the link
+		 */
+		arcn->pad = 0L;
+		if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
+		    sizeof(hd->c_filesize), HEX))
+			goto out;
+		break;
+	default:
+		/*
+		 * no file data for the caller to process
+		 */
+		arcn->pad = 0L;
+		if (ul_asc((u_long)0L, hd->c_filesize, sizeof(hd->c_filesize),
+		    HEX))
+			goto out;
+		break;
+	}
+
+	/*
+	 * set the other fields in the header
+	 */
+	if (ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
+		HEX) ||
+	    ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
+		HEX) ||
+	    ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
+		HEX) ||
+	    ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
+    		HEX) ||
+	    ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime),
+    		HEX) ||
+	    ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
+    		HEX) ||
+	    ul_asc((u_long)major(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj),
+		HEX) ||
+	    ul_asc((u_long)minor(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min),
+		HEX) ||
+	    ul_asc((u_long)major(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj),
+		HEX) ||
+	    ul_asc((u_long)minor(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min),
+		HEX) ||
+	    ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX))
+		goto out;
+
+	/*
+	 * write the header, the file name and padding as required.
+	 */
+	if ((wr_rdbuf(hdblk, (int)sizeof(HD_VCPIO)) < 0) ||
+	    (wr_rdbuf(arcn->name, (int)nsz) < 0)  ||
+	    (wr_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)) {
+		paxwarn(1,"Could not write sv4cpio header for %s",arcn->org_name);
+		return(-1);
+	}
+
+	/*
+	 * if we have file data, tell the caller we are done, copy the file
+	 */
+	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
+	    (arcn->type == PAX_HRG))
+		return(0);
+
+	/*
+	 * if we are not a link, tell the caller we are done, go to next file
+	 */
+	if (arcn->type != PAX_SLK)
+		return(1);
+
+	/*
+	 * write the link name, tell the caller we are done.
+	 */
+	if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
+	    (wr_skip((off_t)(VCPIO_PAD(arcn->ln_nlen))) < 0)) {
+		paxwarn(1,"Could not write sv4cpio link name for %s",
+		    arcn->org_name);
+		return(-1);
+	}
+	return(1);
+
+    out:
+	/*
+	 * header field is out of range
+	 */
+	paxwarn(1,"Sv4cpio header field is too small for file %s",arcn->org_name);
+	return(1);
+}
+
+/*
+ * Routines common to the old binary header cpio
+ */
+
+/*
+ * bcpio_id()
+ *      determine if a block given to us is an old binary cpio header
+ *	(with/without header byte swapping)
+ * Return:
+ *      0 if a valid header, -1 otherwise
+ */
+
+int
+bcpio_id(char *blk, int size)
+{
+	if (size < (int)sizeof(HD_BCPIO))
+		return(-1);
+
+	/*
+	 * check both normal and byte swapped magic cookies
+	 */
+	if (((u_short)SHRT_EXT(blk)) == MAGIC)
+		return(0);
+	if (((u_short)RSHRT_EXT(blk)) == MAGIC) {
+		if (!swp_head)
+			++swp_head;
+		return(0);
+	}
+	return(-1);
+}
+
+/*
+ * bcpio_rd()
+ *	determine if a buffer is an old binary archive entry. (It may have byte
+ *	swapped header) convert and store the values in the ARCHD parameter.
+ *	This is a very old header format and should not really be used.
+ * Return:
+ *	0 if a valid header, -1 otherwise.
+ */
+
+int
+bcpio_rd(ARCHD *arcn, char *buf)
+{
+	HD_BCPIO *hd;
+	int nsz;
+
+	/*
+	 * check the header
+	 */
+	if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0)
+		return(-1);
+
+	arcn->pad = 0L;
+	hd = (HD_BCPIO *)buf;
+	if (swp_head) {
+		/*
+		 * header has swapped bytes on 16 bit boundaries
+		 */
+		arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev));
+		arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino));
+		arcn->sb.st_mode = (mode_t)(RSHRT_EXT(hd->h_mode));
+		arcn->sb.st_uid = (uid_t)(RSHRT_EXT(hd->h_uid));
+		arcn->sb.st_gid = (gid_t)(RSHRT_EXT(hd->h_gid));
+		arcn->sb.st_nlink = (nlink_t)(RSHRT_EXT(hd->h_nlink));
+		arcn->sb.st_rdev = (dev_t)(RSHRT_EXT(hd->h_rdev));
+		arcn->sb.st_mtime = (time_t)(RSHRT_EXT(hd->h_mtime_1));
+		arcn->sb.st_mtime =  (arcn->sb.st_mtime << 16) |
+			((time_t)(RSHRT_EXT(hd->h_mtime_2)));
+		arcn->sb.st_size = (off_t)(RSHRT_EXT(hd->h_filesize_1));
+		arcn->sb.st_size = (arcn->sb.st_size << 16) |
+			((off_t)(RSHRT_EXT(hd->h_filesize_2)));
+		nsz = (int)(RSHRT_EXT(hd->h_namesize));
+	} else {
+		arcn->sb.st_dev = (dev_t)(SHRT_EXT(hd->h_dev));
+		arcn->sb.st_ino = (ino_t)(SHRT_EXT(hd->h_ino));
+		arcn->sb.st_mode = (mode_t)(SHRT_EXT(hd->h_mode));
+		arcn->sb.st_uid = (uid_t)(SHRT_EXT(hd->h_uid));
+		arcn->sb.st_gid = (gid_t)(SHRT_EXT(hd->h_gid));
+		arcn->sb.st_nlink = (nlink_t)(SHRT_EXT(hd->h_nlink));
+		arcn->sb.st_rdev = (dev_t)(SHRT_EXT(hd->h_rdev));
+		arcn->sb.st_mtime = (time_t)(SHRT_EXT(hd->h_mtime_1));
+		arcn->sb.st_mtime =  (arcn->sb.st_mtime << 16) |
+			((time_t)(SHRT_EXT(hd->h_mtime_2)));
+		arcn->sb.st_size = (off_t)(SHRT_EXT(hd->h_filesize_1));
+		arcn->sb.st_size = (arcn->sb.st_size << 16) |
+			((off_t)(SHRT_EXT(hd->h_filesize_2)));
+		nsz = (int)(SHRT_EXT(hd->h_namesize));
+	}
+	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
+
+	/*
+	 * check the file name size, if bogus give up. otherwise read the file
+	 * name
+	 */
+	if (nsz < 2)
+		return(-1);
+	arcn->nlen = nsz - 1;
+	if (rd_nm(arcn, nsz) < 0)
+		return(-1);
+
+	/*
+	 * header + file name are aligned to 2 byte boundries, skip if needed
+	 */
+	if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)
+		return(-1);
+
+	/*
+	 * if not a link (or a file with no data), calculate pad size (for
+	 * padding which follows the file data), clear the link name and return
+	 */
+	if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){
+		/*
+		 * we have a valid header (not a link)
+		 */
+		arcn->ln_nlen = 0;
+		arcn->ln_name[0] = '\0';
+		arcn->pad = BCPIO_PAD(arcn->sb.st_size);
+		return(com_rd(arcn));
+	}
+
+	if ((rd_ln_nm(arcn) < 0) ||
+	    (rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0))
+		return(-1);
+
+	/*
+	 * we have a valid header (with a link)
+	 */
+	return(com_rd(arcn));
+}
+
+/*
+ * bcpio_endrd()
+ *      no cleanup needed here, just return size of the trailer (for append)
+ * Return:
+ *      size of trailer header in this format
+ */
+
+off_t
+bcpio_endrd(void)
+{
+	return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) +
+		(BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER)))));
+}
+
+/*
+ * bcpio_wr()
+ *	copy the data in the ARCHD to buffer in old binary cpio format
+ *	There is a real chance of field overflow with this critter. So we
+ *	always check the conversion is ok. nobody in his their right mind
+ *	should write an achive in this format...
+ * Return
+ *      0 if file has data to be written after the header, 1 if file has NO
+ *	data to write after the header, -1 if archive write failed
+ */
+
+int
+bcpio_wr(ARCHD *arcn)
+{
+	HD_BCPIO *hd;
+	int nsz;
+	char hdblk[sizeof(HD_BCPIO)];
+	off_t t_offt;
+	int t_int;
+	time_t t_timet;
+
+	/*
+	 * check and repair truncated device and inode fields in the cpio
+	 * header
+	 */
+	if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0)
+		return(-1);
+
+	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
+		arcn->sb.st_rdev = 0;
+	hd = (HD_BCPIO *)hdblk;
+
+	switch(arcn->type) {
+	case PAX_CTG:
+	case PAX_REG:
+	case PAX_HRG:
+		/*
+		 * caller will copy file data to the archive. tell him how
+		 * much to pad.
+		 */
+		arcn->pad = BCPIO_PAD(arcn->sb.st_size);
+		hd->h_filesize_1[0] = CHR_WR_0(arcn->sb.st_size);
+		hd->h_filesize_1[1] = CHR_WR_1(arcn->sb.st_size);
+		hd->h_filesize_2[0] = CHR_WR_2(arcn->sb.st_size);
+		hd->h_filesize_2[1] = CHR_WR_3(arcn->sb.st_size);
+		t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1));
+		t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2)));
+		if (arcn->sb.st_size != t_offt) {
+			paxwarn(1,"File is too large for bcpio format %s",
+			    arcn->org_name);
+			return(1);
+		}
+		break;
+	case PAX_SLK:
+		/*
+		 * no file data for the caller to process, the file data has
+		 * the size of the link
+		 */
+		arcn->pad = 0L;
+		hd->h_filesize_1[0] = CHR_WR_0(arcn->ln_nlen);
+		hd->h_filesize_1[1] = CHR_WR_1(arcn->ln_nlen);
+		hd->h_filesize_2[0] = CHR_WR_2(arcn->ln_nlen);
+		hd->h_filesize_2[1] = CHR_WR_3(arcn->ln_nlen);
+		t_int = (int)(SHRT_EXT(hd->h_filesize_1));
+		t_int = (t_int << 16) | ((int)(SHRT_EXT(hd->h_filesize_2)));
+		if (arcn->ln_nlen != t_int)
+			goto out;
+		break;
+	default:
+		/*
+		 * no file data for the caller to process
+		 */
+		arcn->pad = 0L;
+		hd->h_filesize_1[0] = (char)0;
+		hd->h_filesize_1[1] = (char)0;
+		hd->h_filesize_2[0] = (char)0;
+		hd->h_filesize_2[1] = (char)0;
+		break;
+	}
+
+	/*
+	 * build up the rest of the fields
+	 */
+	hd->h_magic[0] = CHR_WR_2(MAGIC);
+	hd->h_magic[1] = CHR_WR_3(MAGIC);
+	hd->h_dev[0] = CHR_WR_2(arcn->sb.st_dev);
+	hd->h_dev[1] = CHR_WR_3(arcn->sb.st_dev);
+	if (arcn->sb.st_dev != (dev_t)(SHRT_EXT(hd->h_dev)))
+		goto out;
+	hd->h_ino[0] = CHR_WR_2(arcn->sb.st_ino);
+	hd->h_ino[1] = CHR_WR_3(arcn->sb.st_ino);
+	if (arcn->sb.st_ino != (ino_t)(SHRT_EXT(hd->h_ino)))
+		goto out;
+	hd->h_mode[0] = CHR_WR_2(arcn->sb.st_mode);
+	hd->h_mode[1] = CHR_WR_3(arcn->sb.st_mode);
+	if (arcn->sb.st_mode != (mode_t)(SHRT_EXT(hd->h_mode)))
+		goto out;
+	hd->h_uid[0] = CHR_WR_2(arcn->sb.st_uid);
+	hd->h_uid[1] = CHR_WR_3(arcn->sb.st_uid);
+	if (arcn->sb.st_uid != (uid_t)(SHRT_EXT(hd->h_uid)))
+		goto out;
+	hd->h_gid[0] = CHR_WR_2(arcn->sb.st_gid);
+	hd->h_gid[1] = CHR_WR_3(arcn->sb.st_gid);
+	if (arcn->sb.st_gid != (gid_t)(SHRT_EXT(hd->h_gid)))
+		goto out;
+	hd->h_nlink[0] = CHR_WR_2(arcn->sb.st_nlink);
+	hd->h_nlink[1] = CHR_WR_3(arcn->sb.st_nlink);
+	if (arcn->sb.st_nlink != (nlink_t)(SHRT_EXT(hd->h_nlink)))
+		goto out;
+	hd->h_rdev[0] = CHR_WR_2(arcn->sb.st_rdev);
+	hd->h_rdev[1] = CHR_WR_3(arcn->sb.st_rdev);
+	if (arcn->sb.st_rdev != (dev_t)(SHRT_EXT(hd->h_rdev)))
+		goto out;
+	hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime);
+	hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime);
+	hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime);
+	hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime);
+	t_timet = (time_t)(SHRT_EXT(hd->h_mtime_1));
+	t_timet =  (t_timet << 16) | ((time_t)(SHRT_EXT(hd->h_mtime_2)));
+	if (arcn->sb.st_mtime != t_timet)
+		goto out;
+	nsz = arcn->nlen + 1;
+	hd->h_namesize[0] = CHR_WR_2(nsz);
+	hd->h_namesize[1] = CHR_WR_3(nsz);
+	if (nsz != (int)(SHRT_EXT(hd->h_namesize)))
+		goto out;
+
+	/*
+	 * write the header, the file name and padding as required.
+	 */
+	if ((wr_rdbuf(hdblk, (int)sizeof(HD_BCPIO)) < 0) ||
+	    (wr_rdbuf(arcn->name, nsz) < 0) ||
+	    (wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) {
+		paxwarn(1, "Could not write bcpio header for %s", arcn->org_name);
+		return(-1);
+	}
+
+	/*
+	 * if we have file data, tell the caller we are done
+	 */
+	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
+	    (arcn->type == PAX_HRG))
+		return(0);
+
+	/*
+	 * if we are not a link, tell the caller we are done, go to next file
+	 */
+	if (arcn->type != PAX_SLK)
+		return(1);
+
+	/*
+	 * write the link name, tell the caller we are done.
+	 */
+	if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
+	    (wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) {
+		paxwarn(1,"Could not write bcpio link name for %s",arcn->org_name);
+		return(-1);
+	}
+	return(1);
+
+    out:
+	/*
+	 * header field is out of range
+	 */
+	paxwarn(1,"Bcpio header field is too small for file %s", arcn->org_name);
+	return(1);
+}
Index: /trunk/minix/commands/pax/cpio.h
===================================================================
--- /trunk/minix/commands/pax/cpio.h	(revision 9)
+++ /trunk/minix/commands/pax/cpio.h	(revision 9)
@@ -0,0 +1,148 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)cpio.h	8.1 (Berkeley) 5/31/93
+ * $FreeBSD: src/bin/pax/cpio.h,v 1.7 2004/04/06 20:06:48 markm Exp $
+ */
+
+/*
+ * Defines common to all versions of cpio
+ */
+#define TRAILER		"TRAILER!!!"	/* name in last archive record */
+
+/*
+ * Header encoding of the different file types
+ */
+#define	C_ISDIR		 040000		/* Directory */
+#define	C_ISFIFO	 010000		/* FIFO */
+#define	C_ISREG		0100000		/* Regular file */
+#define	C_ISBLK		 060000		/* Block special file */
+#define	C_ISCHR		 020000		/* Character special file */
+#define	C_ISCTG		0110000		/* Reserved for contiguous files */
+#define	C_ISLNK		0120000		/* Reserved for symbolic links */
+#define	C_ISOCK		0140000		/* Reserved for sockets */
+#define C_IFMT		0170000		/* type of file */
+
+/*
+ * Data Interchange Format - Extended cpio header format - POSIX 1003.1-1990
+ */
+typedef struct {
+	char	c_magic[6];		/* magic cookie */
+	char	c_dev[6];		/* device number */
+	char	c_ino[6];		/* inode number */
+	char	c_mode[6];		/* file type/access */
+	char	c_uid[6];		/* owners uid */
+	char	c_gid[6];		/* owners gid */
+	char	c_nlink[6];		/* # of links at archive creation */
+	char	c_rdev[6];		/* block/char major/minor # */
+	char	c_mtime[11];		/* modification time */
+	char	c_namesize[6];		/* length of pathname */
+	char	c_filesize[11];		/* length of file in bytes */
+} HD_CPIO;
+
+#define	MAGIC		070707		/* transportable archive id */
+
+#ifdef _PAX_
+#define	AMAGIC		"070707"	/* ascii equivalent string of MAGIC */
+#define CPIO_MASK	0x3ffff		/* bits valid in the dev/ino fields */
+					/* used for dev/inode remaps */
+#endif /* _PAX_ */
+
+/*
+ * Binary cpio header structure
+ *
+ * CAUTION! CAUTION! CAUTION!
+ * Each field really represents a 16 bit short (NOT ASCII). Described as
+ * an array of chars in an attempt to improve portability!!
+ */
+typedef struct {
+	u_char	h_magic[2];
+	u_char	h_dev[2];
+	u_char	h_ino[2];
+	u_char	h_mode[2];
+	u_char	h_uid[2];
+	u_char	h_gid[2];
+	u_char	h_nlink[2];
+	u_char	h_rdev[2];
+	u_char	h_mtime_1[2];
+	u_char	h_mtime_2[2];
+	u_char	h_namesize[2];
+	u_char	h_filesize_1[2];
+	u_char	h_filesize_2[2];
+} HD_BCPIO;
+
+#ifdef _PAX_
+/*
+ * extraction and creation macros for binary cpio
+ */
+#define SHRT_EXT(ch)	((((unsigned)(ch)[0])<<8) | (((unsigned)(ch)[1])&0xff))
+#define RSHRT_EXT(ch)	((((unsigned)(ch)[1])<<8) | (((unsigned)(ch)[0])&0xff))
+#define CHR_WR_0(val)	((char)(((val) >> 24) & 0xff))
+#define CHR_WR_1(val)	((char)(((val) >> 16) & 0xff))
+#define CHR_WR_2(val)	((char)(((val) >> 8) & 0xff))
+#define CHR_WR_3(val)	((char)((val) & 0xff))
+
+/*
+ * binary cpio masks and pads
+ */
+#define BCPIO_PAD(x)	((2 - ((x) & 1)) & 1)	/* pad to next 2 byte word */
+#define BCPIO_MASK	0xffff			/* mask for dev/ino fields */
+#endif /* _PAX_ */
+
+/*
+ * System VR4 cpio header structure (with/without file data crc)
+ */
+typedef struct {
+	char	c_magic[6];		/* magic cookie */
+	char	c_ino[8];		/* inode number */
+	char	c_mode[8];		/* file type/access */
+	char	c_uid[8];		/* owners uid */
+	char	c_gid[8];		/* owners gid */
+	char	c_nlink[8];		/* # of links at archive creation */
+	char	c_mtime[8];		/* modification time */
+	char	c_filesize[8];		/* length of file in bytes */
+	char	c_maj[8];		/* block/char major # */
+	char	c_min[8];		/* block/char minor # */
+	char	c_rmaj[8];		/* special file major # */
+	char	c_rmin[8];		/* special file minor # */
+	char	c_namesize[8];		/* length of pathname */
+	char	c_chksum[8];		/* 0 OR CRC of bytes of FILE data */
+} HD_VCPIO;
+
+#define	VMAGIC		070701		/* sVr4 new portable archive id */
+#define	VCMAGIC		070702		/* sVr4 new portable archive id CRC */
+#ifdef _PAX_
+#define	AVMAGIC		"070701"	/* ascii string of above */
+#define	AVCMAGIC	"070702"	/* ascii string of above */
+#define VCPIO_PAD(x)	((4 - ((x) & 3)) & 3)	/* pad to next 4 byte word */
+#define VCPIO_MASK	0xffffffff	/* mask for dev/ino fields */
+#endif /* _PAX_ */
Index: /trunk/minix/commands/pax/extern.h
===================================================================
--- /trunk/minix/commands/pax/extern.h	(revision 9)
+++ /trunk/minix/commands/pax/extern.h	(revision 9)
@@ -0,0 +1,293 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)extern.h	8.2 (Berkeley) 4/18/94
+ * $FreeBSD: src/bin/pax/extern.h,v 1.16 2005/01/12 03:25:55 brian Exp $
+ */
+
+/*
+ * External references from each source file
+ */
+
+/*
+ * ar_io.c
+ */
+extern const char *arcname;
+extern const char *gzip_program;
+int ar_open(const char *);
+void ar_close(void);
+void ar_drain(void);
+int ar_set_wr(void);
+int ar_app_ok(void);
+int ar_read(char *, int);
+int ar_write(char *, int);
+int ar_rdsync(void);
+int ar_fow(off_t, off_t *);
+int ar_rev(off_t );
+int ar_next(void);
+
+/*
+ * ar_subs.c
+ */
+extern u_long flcnt;
+void list(void);
+void extract(void);
+void append(void);
+void archive(void);
+void copy(void);
+
+/*
+ * buf_subs.c
+ */
+extern int blksz;
+extern int wrblksz;
+extern int maxflt;
+extern int rdblksz;
+extern off_t wrlimit;
+extern off_t rdcnt;
+extern off_t wrcnt;
+int wr_start(void);
+int rd_start(void);
+void cp_start(void);
+int appnd_start(off_t);
+int rd_sync(void);
+void pback(char *, int);
+int rd_skip(off_t);
+void wr_fin(void);
+int wr_rdbuf(char *, int);
+int rd_wrbuf(char *, int);
+int wr_skip(off_t);
+int wr_rdfile(ARCHD *, int, off_t *);
+int rd_wrfile(ARCHD *, int, off_t *);
+void cp_file(ARCHD *, int, int);
+int buf_fill(void);
+int buf_flush(int);
+
+/*
+ * cache.c
+ */
+int uidtb_start(void);
+int gidtb_start(void);
+int usrtb_start(void);
+int grptb_start(void);
+const char * name_uid(uid_t, int);
+const char * name_gid(gid_t, int);
+int uid_name(char *, uid_t *);
+int gid_name(char *, gid_t *);
+
+/*
+ * cpio.c
+ */
+int cpio_strd(void);
+int cpio_trail(ARCHD *);
+int cpio_endwr(void);
+int cpio_id(char *, int);
+int cpio_rd(ARCHD *, char *);
+off_t cpio_endrd(void);
+int cpio_stwr(void);
+int cpio_wr(ARCHD *);
+int vcpio_id(char *, int);
+int crc_id(char *, int);
+int crc_strd(void);
+int vcpio_rd(ARCHD *, char *);
+off_t vcpio_endrd(void);
+int crc_stwr(void);
+int vcpio_wr(ARCHD *);
+int bcpio_id(char *, int);
+int bcpio_rd(ARCHD *, char *);
+off_t bcpio_endrd(void);
+int bcpio_wr(ARCHD *);
+
+/*
+ * file_subs.c
+ */
+int file_creat(ARCHD *);
+void file_close(ARCHD *, int);
+int lnk_creat(ARCHD *);
+int cross_lnk(ARCHD *);
+int chk_same(ARCHD *);
+int node_creat(ARCHD *);
+int unlnk_exist(char *, int);
+int chk_path(char *, uid_t, gid_t);
+void set_ftime(char *fnm, time_t mtime, time_t atime, int frc);
+int set_ids(char *, uid_t, gid_t);
+int set_lids(char *, uid_t, gid_t);
+void set_pmode(char *, mode_t);
+int file_write(int, char *, int, int *, int *, int, char *);
+void file_flush(int, char *, int);
+void rdfile_close(ARCHD *, int *);
+int set_crc(ARCHD *, int);
+
+/*
+ * ftree.c
+ */
+int ftree_start(void);
+int ftree_add(char *, int);
+void ftree_sel(ARCHD *);
+void ftree_notsel(void);
+void ftree_chk(void);
+int next_file(ARCHD *);
+
+/*
+ * gen_subs.c
+ */
+void ls_list(ARCHD *, time_t, FILE *);
+void ls_tty(ARCHD *);
+int l_strncpy(char *, const char *, int);
+u_long asc_ul(char *, int, int);
+int ul_asc(u_long, char *, int, int);
+#ifndef NET2_STAT
+u_quad_t asc_uqd(char *, int, int);
+int uqd_asc(u_quad_t, char *, int, int);
+#endif
+
+/*
+ * getoldopt.c
+ */
+int getoldopt(int, char **, const char *);
+
+/*
+ * options.c
+ */
+extern FSUB fsub[];
+extern int ford[];
+void options(int, char **);
+OPLIST * opt_next(void);
+int opt_add(const char *);
+int bad_opt(void);
+char *chdname;
+
+/*
+ * pat_rep.c
+ */
+int rep_add(char *);
+int pat_add(char *, char *);
+void pat_chk(void);
+int pat_sel(ARCHD *);
+int pat_match(ARCHD *);
+int mod_name(ARCHD *);
+int set_dest(ARCHD *, char *, int);
+
+/*
+ * pax.c
+ */
+extern int act;
+extern FSUB *frmt;
+extern int cflag;
+extern int cwdfd;
+extern int dflag;
+extern int iflag;
+extern int kflag;
+extern int lflag;
+extern int nflag;
+extern int tflag;
+extern int uflag;
+extern int vflag;
+extern int Dflag;
+extern int Hflag;
+extern int Lflag;
+extern int Xflag;
+extern int Yflag;
+extern int Zflag;
+extern int vfpart;
+extern int patime;
+extern int pmtime;
+extern int nodirs;
+extern int pmode;
+extern int pids;
+extern int rmleadslash;
+extern int exit_val;
+extern int docrc;
+extern char *dirptr;
+extern const char *argv0;
+extern FILE *listf;
+extern char *tempfile;
+extern char *tempbase;
+
+void sig_cleanup(int);
+
+/*
+ * sel_subs.c
+ */
+int sel_chk(ARCHD *);
+int grp_add(char *);
+int usr_add(char *);
+int trng_add(char *);
+
+/*
+ * tables.c
+ */
+int lnk_start(void);
+int chk_lnk(ARCHD *);
+void purg_lnk(ARCHD *);
+void lnk_end(void);
+int ftime_start(void);
+int chk_ftime(ARCHD *);
+int name_start(void);
+int add_name(char *, int, char *);
+void sub_name(char *, int *, size_t);
+int dev_start(void);
+int add_dev(ARCHD *);
+int map_dev(ARCHD *, u_long, u_long);
+int atdir_start(void);
+void atdir_end(void);
+void add_atdir(char *, dev_t, ino_t, time_t, time_t);
+int get_atdir(dev_t, ino_t, time_t *, time_t *);
+int dir_start(void);
+void add_dir(char *, int, struct stat *, int);
+void proc_dir(void);
+u_int st_hash(char *, int, int);
+
+/*
+ * tar.c
+ */
+int tar_endwr(void);
+off_t tar_endrd(void);
+int tar_trail(char *, int, int *);
+int tar_id(char *, int);
+int tar_opt(void);
+int tar_rd(ARCHD *, char *);
+int tar_wr(ARCHD *);
+int ustar_strd(void);
+int ustar_stwr(void);
+int ustar_id(char *, int);
+int ustar_rd(ARCHD *, char *);
+int ustar_wr(ARCHD *);
+
+/*
+ * tty_subs.c
+ */
+int tty_init(void);
+void tty_prnt(const char *, ...);
+int tty_read(char *, int);
+void paxwarn(int, const char *, ...);
+void syswarn(int, int, const char *, ...);
Index: /trunk/minix/commands/pax/fgetln.c
===================================================================
--- /trunk/minix/commands/pax/fgetln.c	(revision 9)
+++ /trunk/minix/commands/pax/fgetln.c	(revision 9)
@@ -0,0 +1,38 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *
+fgetln(FILE *fp, size_t *lenp)
+{
+#define EXTRA 80
+	char *buf = NULL;
+	int used = 0, len = 0, remain = 0, final = 0;
+	while(!final) {
+		char *b;
+		int r;
+		if(remain < EXTRA) {
+			int newlen;
+			char *newbuf;
+			newlen = len + EXTRA;
+			if(!(newbuf = realloc(buf, newlen))) {
+				if(buf) free(buf);
+				return NULL;
+			}
+			buf = newbuf;
+			len = newlen;
+			remain += EXTRA;
+		}
+		buf[used] = '\0';
+		if(!fgets(buf + used, remain, fp))
+			break;
+		r = strlen(buf+used);
+		used += r;
+		remain -= r;
+		len += r;
+	}
+	*lenp = len;
+	return buf;
+}
+
Index: /trunk/minix/commands/pax/file_subs.c
===================================================================
--- /trunk/minix/commands/pax/file_subs.c	(revision 9)
+++ /trunk/minix/commands/pax/file_subs.c	(revision 9)
@@ -0,0 +1,989 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)file_subs.c	8.1 (Berkeley) 5/31/93";
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <utime.h>
+#include <sys/uio.h>
+#include <stdlib.h>
+#include "pax.h"
+#include "options.h"
+#include "extern.h"
+
+static int
+mk_link(char *,struct stat *,char *, int);
+
+/*
+ * routines that deal with file operations such as: creating, removing;
+ * and setting access modes, uid/gid and times of files
+ */
+
+#define FILEBITS		(S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
+#define SETBITS			(S_ISUID | S_ISGID)
+#define ABITS			(FILEBITS | SETBITS)
+
+/*
+ * file_creat()
+ *	Create and open a file.
+ * Return:
+ *	file descriptor or -1 for failure
+ */
+
+int
+file_creat(ARCHD *arcn)
+{
+	int fd = -1;
+	mode_t file_mode;
+	int oerrno;
+
+	/*
+	 * assume file doesn't exist, so just try to create it, most times this
+	 * works. We have to take special handling when the file does exist. To
+	 * detect this, we use O_EXCL. For example when trying to create a
+	 * file and a character device or fifo exists with the same name, we
+	 * can accidently open the device by mistake (or block waiting to open)
+	 * If we find that the open has failed, then figure spend the effort to
+	 * figure out why. This strategy was found to have better average
+	 * performance in common use than checking the file (and the path)
+	 * first with lstat.
+	 */
+	file_mode = arcn->sb.st_mode & FILEBITS;
+	if ((fd = open(arcn->name, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,
+	    file_mode)) >= 0)
+		return(fd);
+
+	/*
+	 * the file seems to exist. First we try to get rid of it (found to be
+	 * the second most common failure when traced). If this fails, only
+	 * then we go to the expense to check and create the path to the file
+	 */
+	if (unlnk_exist(arcn->name, arcn->type) != 0)
+		return(-1);
+
+	for (;;) {
+		/*
+		 * try to open it again, if this fails, check all the nodes in
+		 * the path and give it a final try. if chk_path() finds that
+		 * it cannot fix anything, we will skip the last attempt
+		 */
+		if ((fd = open(arcn->name, O_WRONLY | O_CREAT | O_TRUNC,
+		    file_mode)) >= 0)
+			break;
+		oerrno = errno;
+		if (nodirs || chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
+			syswarn(1, oerrno, "Unable to create %s", arcn->name);
+			return(-1);
+		}
+	}
+	return(fd);
+}
+
+/*
+ * file_close()
+ *	Close file descriptor to a file just created by pax. Sets modes,
+ *	ownership and times as required.
+ * Return:
+ *	0 for success, -1 for failure
+ */
+
+void
+file_close(ARCHD *arcn, int fd)
+{
+	int res = 0;
+
+	if (fd < 0)
+		return;
+	if (close(fd) < 0)
+		syswarn(0, errno, "Unable to close file descriptor on %s",
+		    arcn->name);
+
+	/*
+	 * set owner/groups first as this may strip off mode bits we want
+	 * then set file permission modes. Then set file access and
+	 * modification times.
+	 */
+	if (pids)
+		res = set_ids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid);
+
+	/*
+	 * IMPORTANT SECURITY NOTE:
+	 * if not preserving mode or we cannot set uid/gid, then PROHIBIT
+	 * set uid/gid bits
+	 */
+	if (!pmode || res)
+		arcn->sb.st_mode &= ~(SETBITS);
+	if (pmode)
+		set_pmode(arcn->name, arcn->sb.st_mode);
+	if (patime || pmtime)
+		set_ftime(arcn->name, arcn->sb.st_mtime, arcn->sb.st_atime, 0);
+}
+
+/*
+ * lnk_creat()
+ *	Create a hard link to arcn->ln_name from arcn->name. arcn->ln_name
+ *	must exist;
+ * Return:
+ *	0 if ok, -1 otherwise
+ */
+
+int
+lnk_creat(ARCHD *arcn)
+{
+	struct stat sb;
+
+	/*
+	 * we may be running as root, so we have to be sure that link target
+	 * is not a directory, so we lstat and check
+	 */
+	if (lstat(arcn->ln_name, &sb) < 0) {
+		syswarn(1,errno,"Unable to link to %s from %s", arcn->ln_name,
+		    arcn->name);
+		return(-1);
+	}
+
+	if (S_ISDIR(sb.st_mode)) {
+		paxwarn(1, "A hard link to the directory %s is not allowed",
+		    arcn->ln_name);
+		return(-1);
+	}
+
+	return(mk_link(arcn->ln_name, &sb, arcn->name, 0));
+}
+
+/*
+ * cross_lnk()
+ *	Create a hard link to arcn->org_name from arcn->name. Only used in copy
+ *	with the -l flag. No warning or error if this does not succeed (we will
+ *	then just create the file)
+ * Return:
+ *	1 if copy() should try to create this file node
+ *	0 if cross_lnk() ok, -1 for fatal flaw (like linking to self).
+ */
+
+int
+cross_lnk(ARCHD *arcn)
+{
+	/*
+	 * try to make a link to original file (-l flag in copy mode). make sure
+	 * we do not try to link to directories in case we are running as root
+	 * (and it might succeed).
+	 */
+	if (arcn->type == PAX_DIR)
+		return(1);
+	return(mk_link(arcn->org_name, &(arcn->sb), arcn->name, 1));
+}
+
+/*
+ * chk_same()
+ *	In copy mode if we are not trying to make hard links between the src
+ *	and destinations, make sure we are not going to overwrite ourselves by
+ *	accident. This slows things down a little, but we have to protect all
+ *	those people who make typing errors.
+ * Return:
+ *	1 the target does not exist, go ahead and copy
+ *	0 skip it file exists (-k) or may be the same as source file
+ */
+
+int
+chk_same(ARCHD *arcn)
+{
+	struct stat sb;
+
+	/*
+	 * if file does not exist, return. if file exists and -k, skip it
+	 * quietly
+	 */
+	if (lstat(arcn->name, &sb) < 0)
+		return(1);
+	if (kflag)
+		return(0);
+
+	/*
+	 * better make sure the user does not have src == dest by mistake
+	 */
+	if ((arcn->sb.st_dev == sb.st_dev) && (arcn->sb.st_ino == sb.st_ino)) {
+		paxwarn(1, "Unable to copy %s, file would overwrite itself",
+		    arcn->name);
+		return(0);
+	}
+	return(1);
+}
+
+/*
+ * mk_link()
+ *	try to make a hard link between two files. if ign set, we do not
+ *	complain.
+ * Return:
+ *	0 if successful (or we are done with this file but no error, such as
+ *	finding the from file exists and the user has set -k).
+ *	1 when ign was set to indicates we could not make the link but we
+ *	should try to copy/extract the file as that might work (and is an
+ *	allowed option). -1 an error occurred.
+ */
+
+static int
+mk_link(char *to, struct stat *to_sb, char *from,
+	int ign)
+{
+	struct stat sb;
+	int oerrno;
+
+	/*
+	 * if from file exists, it has to be unlinked to make the link. If the
+	 * file exists and -k is set, skip it quietly
+	 */
+	if (lstat(from, &sb) == 0) {
+		if (kflag)
+			return(0);
+
+		/*
+		 * make sure it is not the same file, protect the user
+		 */
+		if ((to_sb->st_dev==sb.st_dev)&&(to_sb->st_ino == sb.st_ino)) {
+			paxwarn(1, "Unable to link file %s to itself", to);
+			return(-1);;
+		}
+
+		/*
+		 * try to get rid of the file, based on the type
+		 */
+		if (S_ISDIR(sb.st_mode)) {
+			if (rmdir(from) < 0) {
+				syswarn(1, errno, "Unable to remove %s", from);
+				return(-1);
+			}
+		} else if (unlink(from) < 0) {
+			if (!ign) {
+				syswarn(1, errno, "Unable to remove %s", from);
+				return(-1);
+			}
+			return(1);
+		}
+	}
+
+	/*
+	 * from file is gone (or did not exist), try to make the hard link.
+	 * if it fails, check the path and try it again (if chk_path() says to
+	 * try again)
+	 */
+	for (;;) {
+		if (link(to, from) == 0)
+			break;
+		oerrno = errno;
+		if (!nodirs && chk_path(from, to_sb->st_uid, to_sb->st_gid) == 0)
+			continue;
+		if (!ign) {
+			syswarn(1, oerrno, "Could not link to %s from %s", to,
+			    from);
+			return(-1);
+		}
+		return(1);
+	}
+
+	/*
+	 * all right the link was made
+	 */
+	return(0);
+}
+
+/*
+ * node_creat()
+ *	create an entry in the file system (other than a file or hard link).
+ *	If successful, sets uid/gid modes and times as required.
+ * Return:
+ *	0 if ok, -1 otherwise
+ */
+
+int
+node_creat(ARCHD *arcn)
+{
+	int res;
+	int ign = 0;
+	int oerrno;
+	int pass = 0;
+	mode_t file_mode;
+	struct stat sb;
+
+	/*
+	 * create node based on type, if that fails try to unlink the node and
+	 * try again. finally check the path and try again. As noted in the
+	 * file and link creation routines, this method seems to exhibit the
+	 * best performance in general use workloads.
+	 */
+	file_mode = arcn->sb.st_mode & FILEBITS;
+
+	for (;;) {
+		switch(arcn->type) {
+		case PAX_DIR:
+			res = mkdir(arcn->name, file_mode);
+			if (ign)
+				res = 0;
+			break;
+		case PAX_CHR:
+			file_mode |= S_IFCHR;
+			res = mknod(arcn->name, file_mode, arcn->sb.st_rdev);
+			break;
+		case PAX_BLK:
+			file_mode |= S_IFBLK;
+			res = mknod(arcn->name, file_mode, arcn->sb.st_rdev);
+			break;
+		case PAX_FIF:
+			res = mkfifo(arcn->name, file_mode);
+			break;
+		case PAX_SCK:
+			/*
+			 * Skip sockets, operation has no meaning under BSD
+			 */
+			paxwarn(0,
+			    "%s skipped. Sockets cannot be copied or extracted",
+			    arcn->name);
+			return(-1);
+		case PAX_SLK:
+			res = symlink(arcn->ln_name, arcn->name);
+			break;
+		case PAX_CTG:
+		case PAX_HLK:
+		case PAX_HRG:
+		case PAX_REG:
+		default:
+			/*
+			 * we should never get here
+			 */
+			paxwarn(0, "%s has an unknown file type, skipping",
+				arcn->name);
+			return(-1);
+		}
+
+		/*
+		 * if we were able to create the node break out of the loop,
+		 * otherwise try to unlink the node and try again. if that
+		 * fails check the full path and try a final time.
+		 */
+		if (res == 0)
+			break;
+
+		/*
+		 * we failed to make the node
+		 */
+		oerrno = errno;
+		if ((ign = unlnk_exist(arcn->name, arcn->type)) < 0)
+			return(-1);
+
+		if (++pass <= 1)
+			continue;
+
+		if (nodirs || chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
+			syswarn(1, oerrno, "Could not create: %s", arcn->name);
+			return(-1);
+		}
+	}
+
+	/*
+	 * we were able to create the node. set uid/gid, modes and times
+	 */
+	if (pids)
+		res = ((arcn->type == PAX_SLK) ?
+		    set_lids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid) :
+		    set_ids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid));
+	else
+		res = 0;
+
+	/*
+	 * symlinks are done now.
+	 */
+	if (arcn->type == PAX_SLK)
+		return(0);
+
+	/*
+	 * IMPORTANT SECURITY NOTE:
+	 * if not preserving mode or we cannot set uid/gid, then PROHIBIT any
+	 * set uid/gid bits
+	 */
+	if (!pmode || res)
+		arcn->sb.st_mode &= ~(SETBITS);
+	if (pmode)
+		set_pmode(arcn->name, arcn->sb.st_mode);
+
+	if (arcn->type == PAX_DIR && strcmp(NM_CPIO, argv0) != 0) {
+		/*
+		 * Dirs must be processed again at end of extract to set times
+		 * and modes to agree with those stored in the archive. However
+		 * to allow extract to continue, we may have to also set owner
+		 * rights. This allows nodes in the archive that are children
+		 * of this directory to be extracted without failure. Both time
+		 * and modes will be fixed after the entire archive is read and
+		 * before pax exits.
+		 */
+		if (access(arcn->name, R_OK | W_OK | X_OK) < 0) {
+			if (lstat(arcn->name, &sb) < 0) {
+				syswarn(0, errno,"Could not access %s (stat)",
+				    arcn->name);
+				set_pmode(arcn->name,file_mode | S_IRWXU);
+			} else {
+				/*
+				 * We have to add rights to the dir, so we make
+				 * sure to restore the mode. The mode must be
+				 * restored AS CREATED and not as stored if
+				 * pmode is not set.
+				 */
+				set_pmode(arcn->name,
+				    ((sb.st_mode & FILEBITS) | S_IRWXU));
+				if (!pmode)
+					arcn->sb.st_mode = sb.st_mode;
+			}
+
+			/*
+			 * we have to force the mode to what was set here,
+			 * since we changed it from the default as created.
+			 */
+			add_dir(arcn->name, arcn->nlen, &(arcn->sb), 1);
+		} else if (pmode || patime || pmtime)
+			add_dir(arcn->name, arcn->nlen, &(arcn->sb), 0);
+	}
+
+	if (patime || pmtime)
+		set_ftime(arcn->name, arcn->sb.st_mtime, arcn->sb.st_atime, 0);
+	return(0);
+}
+
+/*
+ * unlnk_exist()
+ *	Remove node from file system with the specified name. We pass the type
+ *	of the node that is going to replace it. When we try to create a
+ *	directory and find that it already exists, we allow processing to
+ *	continue as proper modes etc will always be set for it later on.
+ * Return:
+ *	0 is ok to proceed, no file with the specified name exists
+ *	-1 we were unable to remove the node, or we should not remove it (-k)
+ *	1 we found a directory and we were going to create a directory.
+ */
+
+int
+unlnk_exist(char *name, int type)
+{
+	struct stat sb;
+
+	/*
+	 * the file does not exist, or -k we are done
+	 */
+	if (lstat(name, &sb) < 0)
+		return(0);
+	if (kflag)
+		return(-1);
+
+	if (S_ISDIR(sb.st_mode)) {
+		/*
+		 * try to remove a directory, if it fails and we were going to
+		 * create a directory anyway, tell the caller (return a 1)
+		 */
+		if (rmdir(name) < 0) {
+			if (type == PAX_DIR)
+				return(1);
+			syswarn(1,errno,"Unable to remove directory %s", name);
+			return(-1);
+		}
+		return(0);
+	}
+
+	/*
+	 * try to get rid of all non-directory type nodes
+	 */
+	if (unlink(name) < 0) {
+		syswarn(1, errno, "Could not unlink %s", name);
+		return(-1);
+	}
+	return(0);
+}
+
+/*
+ * chk_path()
+ *	We were trying to create some kind of node in the file system and it
+ *	failed. chk_path() makes sure the path up to the node exists and is
+ *	writeable. When we have to create a directory that is missing along the
+ *	path somewhere, the directory we create will be set to the same
+ *	uid/gid as the file has (when uid and gid are being preserved).
+ *	NOTE: this routine is a real performance loss. It is only used as a
+ *	last resort when trying to create entries in the file system.
+ * Return:
+ *	-1 when it could find nothing it is allowed to fix.
+ *	0 otherwise
+ */
+
+int
+chk_path( char *name, uid_t st_uid, gid_t st_gid)
+{
+	char *spt = name;
+	struct stat sb;
+	int retval = -1;
+
+	/*
+	 * watch out for paths with nodes stored directly in / (e.g. /bozo)
+	 */
+	if (*spt == '/')
+		++spt;
+
+	for(;;) {
+		/*
+		 * work foward from the first / and check each part of the path
+		 */
+		spt = strchr(spt, '/');
+		if (spt == NULL)
+			break;
+		*spt = '\0';
+
+		/*
+		 * if it exists we assume it is a directory, it is not within
+		 * the spec (at least it seems to read that way) to alter the
+		 * file system for nodes NOT EXPLICITLY stored on the archive.
+		 * If that assumption is changed, you would test the node here
+		 * and figure out how to get rid of it (probably like some
+		 * recursive unlink()) or fix up the directory permissions if
+		 * required (do an access()).
+		 */
+		if (lstat(name, &sb) == 0) {
+			*(spt++) = '/';
+			continue;
+		}
+
+		/*
+		 * the path fails at this point, see if we can create the
+		 * needed directory and continue on
+		 */
+		if (mkdir(name, S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
+			*spt = '/';
+			retval = -1;
+			break;
+		}
+
+		/*
+		 * we were able to create the directory. We will tell the
+		 * caller that we found something to fix, and it is ok to try
+		 * and create the node again.
+		 */
+		retval = 0;
+		if (pids)
+			(void)set_ids(name, st_uid, st_gid);
+
+		/*
+		 * make sure the user doen't have some strange umask that
+		 * causes this newly created directory to be unusable. We fix
+		 * the modes and restore them back to the creation default at
+		 * the end of pax
+		 */
+		if ((access(name, R_OK | W_OK | X_OK) < 0) &&
+		    (lstat(name, &sb) == 0)) {
+			set_pmode(name, ((sb.st_mode & FILEBITS) | S_IRWXU));
+			add_dir(name, spt - name, &sb, 1);
+		}
+		*(spt++) = '/';
+		continue;
+	}
+	return(retval);
+}
+
+/*
+ * set_ftime()
+ *	Set the access time and modification time for a named file. If frc is
+ *	non-zero we force these times to be set even if the user did not
+ *	request access and/or modification time preservation (this is also
+ *	used by -t to reset access times).
+ *	When ign is zero, only those times the user has asked for are set, the
+ *	other ones are left alone. We do not assume the un-documented feature
+ *	of many utimes() implementations that consider a 0 time value as a do
+ *	not set request.
+ */
+
+void
+set_ftime(char *fnm, time_t mtime, time_t atime, int frc)
+{
+#if 0
+	static struct timeval tv[2] = {{0L, 0L}, {0L, 0L}};
+#endif
+	struct stat sb;
+	struct utimbuf ut;
+
+#if 0
+	tv[0].tv_sec = atime;
+	tv[1].tv_sec = mtime;
+#endif
+
+	ut.actime = atime;
+	ut.modtime = mtime;
+
+	if (!frc && (!patime || !pmtime)) {
+		/*
+		 * if we are not forcing, only set those times the user wants
+		 * set. We get the current values of the times if we need them.
+		 */
+		if (lstat(fnm, &sb) == 0) {
+			if (!patime)
+				ut.actime = sb.st_atime;
+			if (!pmtime)
+				ut.modtime = sb.st_mtime;
+		} else
+			syswarn(0,errno,"Unable to obtain file stats %s", fnm);
+	}
+
+	/*
+	 * set the times
+	 */
+	if (utime(fnm, &ut) < 0)
+		syswarn(1, errno, "Access/modification time set failed on: %s",
+		    fnm);
+	return;
+}
+
+/*
+ * set_ids()
+ *	set the uid and gid of a file system node
+ * Return:
+ *	0 when set, -1 on failure
+ */
+
+int
+set_ids(char *fnm, uid_t uid, gid_t gid)
+{
+	if (chown(fnm, uid, gid) < 0) {
+		/*
+		 * ignore EPERM unless in verbose mode or being run by root.
+		 * if running as pax, POSIX requires a warning.
+		 */
+		if (strcmp(NM_PAX, argv0) == 0 || errno != EPERM || vflag ||
+		    geteuid() == 0)
+			syswarn(1, errno, "Unable to set file uid/gid of %s",
+			    fnm);
+		return(-1);
+	}
+	return(0);
+}
+
+/*
+ * set_lids()
+ *	set the uid and gid of a file system node
+ * Return:
+ *	0 when set, -1 on failure
+ */
+
+int
+set_lids(char *fnm, uid_t uid, gid_t gid)
+{
+
+#if 0
+	if (lchown(fnm, uid, gid) < 0) {
+		/*
+		 * ignore EPERM unless in verbose mode or being run by root.
+		 * if running as pax, POSIX requires a warning.
+		 */
+		if (strcmp(NM_PAX, argv0) == 0 || errno != EPERM || vflag ||
+		    geteuid() == 0)
+			syswarn(1, errno, "Unable to set file uid/gid of %s",
+			    fnm);
+		return(-1);
+	}
+#else
+	return(-1);	/* No lchown() in minix. */
+#endif
+	return(0);
+}
+
+/*
+ * set_pmode()
+ *	Set file access mode
+ */
+
+void
+set_pmode(char *fnm, mode_t mode)
+{
+	mode &= ABITS;
+	if (chmod(fnm, mode) < 0)
+		syswarn(1, errno, "Could not set permissions on %s", fnm);
+	return;
+}
+
+/*
+ * file_write()
+ *	Write/copy a file (during copy or archive extract). This routine knows
+ *	how to copy files with lseek holes in it. (Which are read as file
+ *	blocks containing all 0's but do not have any file blocks associated
+ *	with the data). Typical examples of these are files created by dbm
+ *	variants (.pag files). While the file size of these files are huge, the
+ *	actual storage is quite small (the files are sparse). The problem is
+ *	the holes read as all zeros so are probably stored on the archive that
+ *	way (there is no way to determine if the file block is really a hole,
+ *	we only know that a file block of all zero's can be a hole).
+ *	At this writing, no major archive format knows how to archive files
+ *	with holes. However, on extraction (or during copy, -rw) we have to
+ *	deal with these files. Without detecting the holes, the files can
+ *	consume a lot of file space if just written to disk. This replacement
+ *	for write when passed the basic allocation size of a file system block,
+ *	uses lseek whenever it detects the input data is all 0 within that
+ *	file block. In more detail, the strategy is as follows:
+ *	While the input is all zero keep doing an lseek. Keep track of when we
+ *	pass over file block boundries. Only write when we hit a non zero
+ *	input. once we have written a file block, we continue to write it to
+ *	the end (we stop looking at the input). When we reach the start of the
+ *	next file block, start checking for zero blocks again. Working on file
+ *	block boundries significantly reduces the overhead when copying files
+ *	that are NOT very sparse. This overhead (when compared to a write) is
+ *	almost below the measurement resolution on many systems. Without it,
+ *	files with holes cannot be safely copied. It does has a side effect as
+ *	it can put holes into files that did not have them before, but that is
+ *	not a problem since the file contents are unchanged (in fact it saves
+ *	file space). (Except on paging files for diskless clients. But since we
+ *	cannot determine one of those file from here, we ignore them). If this
+ *	ever ends up on a system where CTG files are supported and the holes
+ *	are not desired, just do a conditional test in those routines that
+ *	call file_write() and have it call write() instead. BEFORE CLOSING THE
+ *	FILE, make sure to call file_flush() when the last write finishes with
+ *	an empty block. A lot of file systems will not create an lseek hole at
+ *	the end. In this case we drop a single 0 at the end to force the
+ *	trailing 0's in the file.
+ *	---Parameters---
+ *	rem: how many bytes left in this file system block
+ *	isempt: have we written to the file block yet (is it empty)
+ *	sz: basic file block allocation size
+ *	cnt: number of bytes on this write
+ *	str: buffer to write
+ * Return:
+ *	number of bytes written, -1 on write (or lseek) error.
+ */
+
+int
+file_write(int fd, char *str, int cnt, int *rem, int *isempt, int sz,
+	char *name)
+{
+	char *pt;
+	char *end;
+	int wcnt;
+	char *st = str;
+
+	/*
+	 * while we have data to process
+	 */
+	while (cnt) {
+		if (!*rem) {
+			/*
+			 * We are now at the start of file system block again
+			 * (or what we think one is...). start looking for
+			 * empty blocks again
+			 */
+			*isempt = 1;
+			*rem = sz;
+		}
+
+		/*
+		 * only examine up to the end of the current file block or
+		 * remaining characters to write, whatever is smaller
+		 */
+		wcnt = MIN(cnt, *rem);
+		cnt -= wcnt;
+		*rem -= wcnt;
+		if (*isempt) {
+			/*
+			 * have not written to this block yet, so we keep
+			 * looking for zero's
+			 */
+			pt = st;
+			end = st + wcnt;
+
+			/*
+			 * look for a zero filled buffer
+			 */
+			while ((pt < end) && (*pt == '\0'))
+				++pt;
+
+			if (pt == end) {
+				/*
+				 * skip, buf is empty so far
+				 */
+				if (lseek(fd, (off_t)wcnt, SEEK_CUR) < 0) {
+					syswarn(1,errno,"File seek on %s",
+					    name);
+					return(-1);
+				}
+				st = pt;
+				continue;
+			}
+			/*
+			 * drat, the buf is not zero filled
+			 */
+			*isempt = 0;
+		}
+
+		/*
+		 * have non-zero data in this file system block, have to write
+		 */
+		if (write(fd, st, wcnt) != wcnt) {
+			syswarn(1, errno, "Failed write to file %s", name);
+			return(-1);
+		}
+		st += wcnt;
+	}
+	return(st - str);
+}
+
+/*
+ * file_flush()
+ *	when the last file block in a file is zero, many file systems will not
+ *	let us create a hole at the end. To get the last block with zeros, we
+ *	write the last BYTE with a zero (back up one byte and write a zero).
+ */
+
+void
+file_flush(int fd, char *fname, int isempt)
+{
+	static char blnk[] = "\0";
+
+	/*
+	 * silly test, but make sure we are only called when the last block is
+	 * filled with all zeros.
+	 */
+	if (!isempt)
+		return;
+
+	/*
+	 * move back one byte and write a zero
+	 */
+	if (lseek(fd, (off_t)-1, SEEK_CUR) < 0) {
+		syswarn(1, errno, "Failed seek on file %s", fname);
+		return;
+	}
+
+	if (write(fd, blnk, 1) < 0)
+		syswarn(1, errno, "Failed write to file %s", fname);
+	return;
+}
+
+/*
+ * rdfile_close()
+ *	close a file we have beed reading (to copy or archive). If we have to
+ *	reset access time (tflag) do so (the times are stored in arcn).
+ */
+
+void
+rdfile_close(ARCHD *arcn, int *fd)
+{
+	/*
+	 * make sure the file is open
+	 */
+	if (*fd < 0)
+		return;
+
+	(void)close(*fd);
+	*fd = -1;
+	if (!tflag)
+		return;
+
+	/*
+	 * user wants last access time reset
+	 */
+	set_ftime(arcn->org_name, arcn->sb.st_mtime, arcn->sb.st_atime, 1);
+	return;
+}
+
+/*
+ * set_crc()
+ *	read a file to calculate its crc. This is a real drag. Archive formats
+ *	that have this, end up reading the file twice (we have to write the
+ *	header WITH the crc before writing the file contents. Oh well...
+ * Return:
+ *	0 if was able to calculate the crc, -1 otherwise
+ */
+
+int
+set_crc(ARCHD *arcn, int fd)
+{
+	int i;
+	int res;
+	off_t cpcnt = 0L;
+	u_long size;
+	unsigned long crc = 0L;
+	char tbuf[FILEBLK];
+	struct stat sb;
+
+	if (fd < 0) {
+		/*
+		 * hmm, no fd, should never happen. well no crc then.
+		 */
+		arcn->crc = 0L;
+		return(0);
+	}
+
+#if 0
+	/* not in minix */
+	if ((size = (u_long)arcn->sb.st_blksize) > (u_long)sizeof(tbuf))
+		size = (u_long)sizeof(tbuf);
+#endif
+
+	/*
+	 * read all the bytes we think that there are in the file. If the user
+	 * is trying to archive an active file, forget this file.
+	 */
+	for(;;) {
+		if ((res = read(fd, tbuf, size)) <= 0)
+			break;
+		cpcnt += res;
+		for (i = 0; i < res; ++i)
+			crc += (tbuf[i] & 0xff);
+	}
+
+	/*
+	 * safety check. we want to avoid archiving files that are active as
+	 * they can create inconsistant archive copies.
+	 */
+	if (cpcnt != arcn->sb.st_size)
+		paxwarn(1, "File changed size %s", arcn->org_name);
+	else if (fstat(fd, &sb) < 0)
+		syswarn(1, errno, "Failed stat on %s", arcn->org_name);
+	else if (arcn->sb.st_mtime != sb.st_mtime)
+		paxwarn(1, "File %s was modified during read", arcn->org_name);
+	else if (lseek(fd, (off_t)0L, SEEK_SET) < 0)
+		syswarn(1, errno, "File rewind failed on: %s", arcn->org_name);
+	else {
+		arcn->crc = crc;
+		return(0);
+	}
+	return(-1);
+}
Index: /trunk/minix/commands/pax/ftree.c
===================================================================
--- /trunk/minix/commands/pax/ftree.c	(revision 9)
+++ /trunk/minix/commands/pax/ftree.c	(revision 9)
@@ -0,0 +1,535 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)ftree.c	8.2 (Berkeley) 4/18/94";
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fts.h>
+#include "pax.h"
+#include "ftree.h"
+#include "extern.h"
+
+/*
+ * routines to interface with the fts library function.
+ *
+ * file args supplied to pax are stored on a single linked list (of type FTREE)
+ * and given to fts to be processed one at a time. pax "selects" files from
+ * the expansion of each arg into the corresponding file tree (if the arg is a
+ * directory, otherwise the node itself is just passed to pax). The selection
+ * is modified by the -n and -u flags. The user is informed when a specific
+ * file arg does not generate any selected files. -n keeps expanding the file
+ * tree arg until one of its files is selected, then skips to the next file
+ * arg. when the user does not supply the file trees as command line args to
+ * pax, they are read from stdin
+ */
+
+static FTS *ftsp = NULL;		/* current FTS handle */
+static int ftsopts;			/* options to be used on fts_open */
+static char *farray[2];			/* array for passing each arg to fts */
+static FTREE *fthead = NULL;		/* head of linked list of file args */
+static FTREE *fttail = NULL;		/* tail of linked list of file args */
+static FTREE *ftcur = NULL;		/* current file arg being processed */
+static FTSENT *ftent = NULL;		/* current file tree entry */
+static int ftree_skip;			/* when set skip to next file arg */
+
+static int ftree_arg(void);
+
+/*
+ * ftree_start()
+ *	initialize the options passed to fts_open() during this run of pax
+ *	options are based on the selection of pax options by the user
+ *	fts_start() also calls fts_arg() to open the first valid file arg. We
+ *	also attempt to reset directory access times when -t (tflag) is set.
+ * Return:
+ *	0 if there is at least one valid file arg to process, -1 otherwise
+ */
+
+int
+ftree_start(void)
+{
+	/*
+	 * Set up the operation mode of fts, open the first file arg. We must
+	 * use FTS_NOCHDIR, as the user may have to open multiple archives and
+	 * if fts did a chdir off into the boondocks, we may create an archive
+	 * volume in a place where the user did not expect to.
+	 */
+	ftsopts = FTS_NOCHDIR;
+
+	/*
+	 * optional user flags that effect file traversal
+	 * -H command line symlink follow only (half follow)
+	 * -L follow sylinks (logical)
+	 * -P do not follow sylinks (physical). This is the default.
+	 * -X do not cross over mount points
+	 * -t preserve access times on files read.
+	 * -n select only the first member of a file tree when a match is found
+	 * -d do not extract subtrees rooted at a directory arg.
+	 */
+	if (Lflag)
+		ftsopts |= FTS_LOGICAL;
+	else
+		ftsopts |= FTS_PHYSICAL;
+	if (Hflag)
+#	ifdef NET2_FTS
+		paxwarn(0, "The -H flag is not supported on this version");
+#	else
+		ftsopts |= FTS_COMFOLLOW;
+#	endif
+	if (Xflag)
+		ftsopts |= FTS_XDEV;
+
+	if ((fthead == NULL) && ((farray[0] = malloc(PAXPATHLEN+2)) == NULL)) {
+		paxwarn(1, "Unable to allocate memory for file name buffer");
+		return(-1);
+	}
+
+	if (ftree_arg() < 0)
+		return(-1);
+	if (tflag && (atdir_start() < 0))
+		return(-1);
+	return(0);
+}
+
+/*
+ * ftree_add()
+ *	add the arg to the linked list of files to process. Each will be
+ *	processed by fts one at a time
+ * Return:
+ *	0 if added to the linked list, -1 if failed
+ */
+
+int
+ftree_add(char *str, int chflg)
+{
+	FTREE *ft;
+	int len;
+
+	/*
+	 * simple check for bad args
+	 */
+	if ((str == NULL) || (*str == '\0')) {
+		paxwarn(0, "Invalid file name argument");
+		return(-1);
+	}
+
+	/*
+	 * allocate FTREE node and add to the end of the linked list (args are
+	 * processed in the same order they were passed to pax). Get rid of any
+	 * trailing / the user may pass us. (watch out for / by itself).
+	 */
+	if ((ft = (FTREE *)malloc(sizeof(FTREE))) == NULL) {
+		paxwarn(0, "Unable to allocate memory for filename");
+		return(-1);
+	}
+
+	if (((len = strlen(str) - 1) > 0) && (str[len] == '/'))
+		str[len] = '\0';
+	ft->fname = str;
+	ft->refcnt = 0;
+	ft->chflg = chflg;
+	ft->fow = NULL;
+	if (fthead == NULL) {
+		fttail = fthead = ft;
+		return(0);
+	}
+	fttail->fow = ft;
+	fttail = ft;
+	return(0);
+}
+
+/*
+ * ftree_sel()
+ *	this entry has been selected by pax. bump up reference count and handle
+ *	-n and -d processing.
+ */
+
+void
+ftree_sel(ARCHD *arcn)
+{
+	/*
+	 * set reference bit for this pattern. This linked list is only used
+	 * when file trees are supplied pax as args. The list is not used when
+	 * the trees are read from stdin.
+	 */
+	if (ftcur != NULL)
+		ftcur->refcnt = 1;
+
+	/*
+	 * if -n we are done with this arg, force a skip to the next arg when
+	 * pax asks for the next file in next_file().
+	 * if -d we tell fts only to match the directory (if the arg is a dir)
+	 * and not the entire file tree rooted at that point.
+	 */
+	if (nflag)
+		ftree_skip = 1;
+
+	if (!dflag || (arcn->type != PAX_DIR))
+		return;
+
+	if (ftent != NULL)
+		(void)fts_set(ftsp, ftent, FTS_SKIP);
+}
+
+/*
+ * ftree_notsel()
+ *	this entry has not been selected by pax.
+ */
+
+void
+ftree_notsel()
+{
+	if (ftent != NULL)
+		(void)fts_set(ftsp, ftent, FTS_SKIP);
+}
+
+/*
+ * ftree_chk()
+ *	called at end on pax execution. Prints all those file args that did not
+ *	have a selected member (reference count still 0)
+ */
+
+void
+ftree_chk(void)
+{
+	FTREE *ft;
+	int wban = 0;
+
+	/*
+	 * make sure all dir access times were reset.
+	 */
+	if (tflag)
+		atdir_end();
+
+	/*
+	 * walk down list and check reference count. Print out those members
+	 * that never had a match
+	 */
+	for (ft = fthead; ft != NULL; ft = ft->fow) {
+		if ((ft->refcnt > 0) || ft->chflg)
+			continue;
+		if (wban == 0) {
+			paxwarn(1,"WARNING! These file names were not selected:");
+			++wban;
+		}
+		(void)fprintf(stderr, "%s\n", ft->fname);
+	}
+}
+
+/*
+ * ftree_arg()
+ *	Get the next file arg for fts to process. Can be from either the linked
+ *	list or read from stdin when the user did not them as args to pax. Each
+ *	arg is processed until the first successful fts_open().
+ * Return:
+ *	0 when the next arg is ready to go, -1 if out of file args (or EOF on
+ *	stdin).
+ */
+
+static int
+ftree_arg(void)
+{
+	char *pt;
+
+	/*
+	 * close off the current file tree
+	 */
+	if (ftsp != NULL) {
+		(void)fts_close(ftsp);
+		ftsp = NULL;
+	}
+
+	/*
+	 * keep looping until we get a valid file tree to process. Stop when we
+	 * reach the end of the list (or get an eof on stdin)
+	 */
+	for(;;) {
+		if (fthead == NULL) {
+			/*
+			 * the user didn't supply any args, get the file trees
+			 * to process from stdin;
+			 */
+			if (fgets(farray[0], PAXPATHLEN+1, stdin) == NULL)
+				return(-1);
+			if ((pt = strchr(farray[0], '\n')) != NULL)
+				*pt = '\0';
+		} else {
+			/*
+			 * the user supplied the file args as arguments to pax
+			 */
+			if (ftcur == NULL)
+				ftcur = fthead;
+			else if ((ftcur = ftcur->fow) == NULL)
+				return(-1);
+			if (ftcur->chflg) {
+				/* First fchdir() back... */
+				if (fchdir(cwdfd) < 0) {
+					syswarn(1, errno,
+					  "Can't fchdir to starting directory");
+					return(-1);
+				}
+				if (chdir(ftcur->fname) < 0) {
+					syswarn(1, errno, "Can't chdir to %s",
+					    ftcur->fname);
+					return(-1);
+				}
+				continue;
+			} else
+				farray[0] = ftcur->fname;
+		}
+
+		/*
+		 * Watch it, fts wants the file arg stored in an array of char
+		 * ptrs, with the last one a null. We use a two element array
+		 * and set farray[0] to point at the buffer with the file name
+		 * in it. We cannot pass all the file args to fts at one shot
+		 * as we need to keep a handle on which file arg generates what
+		 * files (the -n and -d flags need this). If the open is
+		 * successful, return a 0.
+		 */
+		if ((ftsp = fts_open(farray, ftsopts, NULL)) != NULL)
+			break;
+	}
+	return(0);
+}
+
+/*
+ * next_file()
+ *	supplies the next file to process in the supplied archd structure.
+ * Return:
+ *	0 when contents of arcn have been set with the next file, -1 when done.
+ */
+
+int
+next_file(ARCHD *arcn)
+{
+	int cnt;
+	time_t atime;
+	time_t mtime;
+
+	/*
+	 * ftree_sel() might have set the ftree_skip flag if the user has the
+	 * -n option and a file was selected from this file arg tree. (-n says
+	 * only one member is matched for each pattern) ftree_skip being 1
+	 * forces us to go to the next arg now.
+	 */
+	if (ftree_skip) {
+		/*
+		 * clear and go to next arg
+		 */
+		ftree_skip = 0;
+		if (ftree_arg() < 0)
+			return(-1);
+	}
+
+	/*
+	 * loop until we get a valid file to process
+	 */
+	for(;;) {
+		if ((ftent = fts_read(ftsp)) == NULL) {
+			/*
+			 * out of files in this tree, go to next arg, if none
+			 * we are done
+			 */
+			if (ftree_arg() < 0)
+				return(-1);
+			continue;
+		}
+
+		/*
+		 * handle each type of fts_read() flag
+		 */
+		switch(ftent->fts_info) {
+		case FTS_D:
+		case FTS_DEFAULT:
+		case FTS_F:
+		case FTS_SL:
+		case FTS_SLNONE:
+			/*
+			 * these are all ok
+			 */
+			break;
+		case FTS_DP:
+			/*
+			 * already saw this directory. If the user wants file
+			 * access times reset, we use this to restore the
+			 * access time for this directory since this is the
+			 * last time we will see it in this file subtree
+			 * remember to force the time (this is -t on a read
+			 * directory, not a created directory).
+			 */
+#			ifdef NET2_FTS
+			if (!tflag || (get_atdir(ftent->fts_statb.st_dev,
+			    ftent->fts_statb.st_ino, &mtime, &atime) < 0))
+#			else
+			if (!tflag || (get_atdir(ftent->fts_statp->st_dev,
+			    ftent->fts_statp->st_ino, &mtime, &atime) < 0))
+#			endif
+				continue;
+			set_ftime(ftent->fts_path, mtime, atime, 1);
+			continue;
+		case FTS_DC:
+			/*
+			 * fts claims a file system cycle
+			 */
+			paxwarn(1,"File system cycle found at %s",ftent->fts_path);
+			continue;
+		case FTS_DNR:
+#			ifdef NET2_FTS
+			syswarn(1, errno,
+#			else
+			syswarn(1, ftent->fts_errno,
+#			endif
+			    "Unable to read directory %s", ftent->fts_path);
+			continue;
+		case FTS_ERR:
+#			ifdef NET2_FTS
+			syswarn(1, errno,
+#			else
+			syswarn(1, ftent->fts_errno,
+#			endif
+			    "File system traversal error");
+			continue;
+		case FTS_NS:
+		case FTS_NSOK:
+#			ifdef NET2_FTS
+			syswarn(1, errno,
+#			else
+			syswarn(1, ftent->fts_errno,
+#			endif
+			    "Unable to access %s", ftent->fts_path);
+			continue;
+		}
+
+		/*
+		 * ok got a file tree node to process. copy info into arcn
+		 * structure (initialize as required)
+		 */
+		arcn->skip = 0;
+		arcn->pad = 0;
+		arcn->ln_nlen = 0;
+		arcn->ln_name[0] = '\0';
+#		ifdef NET2_FTS
+		arcn->sb = ftent->fts_statb;
+#		else
+		arcn->sb = *(ftent->fts_statp);
+#		endif
+
+		/*
+		 * file type based set up and copy into the arcn struct
+		 * SIDE NOTE:
+		 * we try to reset the access time on all files and directories
+		 * we may read when the -t flag is specified. files are reset
+		 * when we close them after copying. we reset the directories
+		 * when we are done with their file tree (we also clean up at
+		 * end in case we cut short a file tree traversal). However
+		 * there is no way to reset access times on symlinks.
+		 */
+		switch(S_IFMT & arcn->sb.st_mode) {
+		case S_IFDIR:
+			arcn->type = PAX_DIR;
+			if (!tflag)
+				break;
+			add_atdir(ftent->fts_path, arcn->sb.st_dev,
+			    arcn->sb.st_ino, arcn->sb.st_mtime,
+			    arcn->sb.st_atime);
+			break;
+		case S_IFCHR:
+			arcn->type = PAX_CHR;
+			break;
+		case S_IFBLK:
+			arcn->type = PAX_BLK;
+			break;
+		case S_IFREG:
+			/*
+			 * only regular files with have data to store on the
+			 * archive. all others will store a zero length skip.
+			 * the skip field is used by pax for actual data it has
+			 * to read (or skip over).
+			 */
+			arcn->type = PAX_REG;
+			arcn->skip = arcn->sb.st_size;
+			break;
+		case S_IFLNK:
+			arcn->type = PAX_SLK;
+			/*
+			 * have to read the symlink path from the file
+			 */
+			if ((cnt = readlink(ftent->fts_path, arcn->ln_name,
+			    PAXPATHLEN - 1)) < 0) {
+				syswarn(1, errno, "Unable to read symlink %s",
+				    ftent->fts_path);
+				continue;
+			}
+			/*
+			 * set link name length, watch out readlink does not
+			 * always NUL terminate the link path
+			 */
+			arcn->ln_name[cnt] = '\0';
+			arcn->ln_nlen = cnt;
+			break;
+#if 0
+		case S_IFSOCK:
+			/*
+			 * under BSD storing a socket is senseless but we will
+			 * let the format specific write function make the
+			 * decision of what to do with it.
+			 */
+			arcn->type = PAX_SCK;
+			break;
+#endif
+		case S_IFIFO:
+			arcn->type = PAX_FIF;
+			break;
+		}
+		break;
+	}
+
+	/*
+	 * copy file name, set file name length
+	 */
+	arcn->nlen = l_strncpy(arcn->name, ftent->fts_path, sizeof(arcn->name) - 1);
+	arcn->name[arcn->nlen] = '\0';
+	arcn->org_name = ftent->fts_path;
+	return(0);
+}
Index: /trunk/minix/commands/pax/ftree.h
===================================================================
--- /trunk/minix/commands/pax/ftree.h	(revision 9)
+++ /trunk/minix/commands/pax/ftree.h	(revision 9)
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)ftree.h	8.1 (Berkeley) 5/31/93
+ * $FreeBSD: src/bin/pax/ftree.h,v 1.7 2004/04/06 20:06:48 markm Exp $
+ */
+
+/*
+ * Data structure used by the ftree.c routines to store the file args to be
+ * handed to fts(). It keeps a reference count of which args generated a
+ * "selected" member
+ */
+
+typedef struct ftree {
+	char		*fname;		/* file tree name */
+	int		refcnt;		/* has tree had a selected file? */
+	int		chflg;		/* change directory flag */
+	struct ftree	*fow;		/* pointer to next entry on list */
+} FTREE;
Index: /trunk/minix/commands/pax/gen_subs.c
===================================================================
--- /trunk/minix/commands/pax/gen_subs.c	(revision 9)
+++ /trunk/minix/commands/pax/gen_subs.c	(revision 9)
@@ -0,0 +1,414 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)gen_subs.c	8.1 (Berkeley) 5/31/93";
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <utmp.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "pax.h"
+#include "extern.h"
+
+/*
+ * a collection of general purpose subroutines used by pax
+ */
+
+/*
+ * constants used by ls_list() when printing out archive members
+ */
+#define MODELEN 20
+#define DATELEN 64
+#define SIXMONTHS	 ((365 / 2) * 86400)
+#define CURFRMTM	"%b %e %H:%M"
+#define OLDFRMTM	"%b %e  %Y"
+#define CURFRMTD	"%e %b %H:%M"
+#define OLDFRMTD	"%e %b  %Y"
+#ifndef UT_NAMESIZE
+#define UT_NAMESIZE	8
+#endif
+#define UT_GRPSIZE	6
+
+static int d_first = -1;
+
+/*
+ * ls_list()
+ *	list the members of an archive in ls format
+ */
+
+void
+ls_list(ARCHD *arcn, time_t now, FILE *fp)
+{
+	struct stat *sbp;
+	char f_mode[MODELEN];
+	char f_date[DATELEN];
+	const char *timefrmt;
+
+	/*
+	 * if not verbose, just print the file name
+	 */
+	if (!vflag) {
+		(void)fprintf(fp, "%s\n", arcn->name);
+		(void)fflush(fp);
+		return;
+	}
+
+	if (d_first < 0)
+		d_first = 0;
+	/*
+	 * user wants long mode
+	 */
+	sbp = &(arcn->sb);
+#if 0
+	strmode(sbp->st_mode, f_mode);
+#else
+	strcpy(f_mode, "");
+#endif
+
+	/*
+	 * time format based on age compared to the time pax was started.
+	 */
+	if ((sbp->st_mtime + SIXMONTHS) <= now)
+		timefrmt = d_first ? OLDFRMTD : OLDFRMTM;
+	else
+		timefrmt = d_first ? CURFRMTD : CURFRMTM;
+
+	/*
+	 * print file mode, link count, uid, gid and time
+	 */
+#if 0
+	if (strftime(f_date,DATELEN,timefrmt,localtime(&(sbp->st_mtime))) == 0)
+#endif
+		f_date[0] = '\0';
+	(void)fprintf(fp, "%s%2u %-*s %-*s ", f_mode, sbp->st_nlink,
+		UT_NAMESIZE, name_uid(sbp->st_uid, 1), UT_GRPSIZE,
+		name_gid(sbp->st_gid, 1));
+
+	/*
+	 * print device id's for devices, or sizes for other nodes
+	 */
+	if ((arcn->type == PAX_CHR) || (arcn->type == PAX_BLK))
+#		ifdef NET2_STAT
+		(void)fprintf(fp, "%4u,%4u ", major(sbp->st_rdev),
+		    minor(sbp->st_rdev));
+#		else
+		(void)fprintf(fp, "%4lu,%4lu ", (unsigned long)major(sbp->st_rdev),
+		    (unsigned long)minor(sbp->st_rdev));
+#		endif
+	else {
+#		ifdef NET2_STAT
+		(void)fprintf(fp, "%9lu ", sbp->st_size);
+#		else
+		(void)fprintf(fp, "%9ju ", (uintmax_t)sbp->st_size);
+#		endif
+	}
+
+	/*
+	 * print name and link info for hard and soft links
+	 */
+	(void)fprintf(fp, "%s %s", f_date, arcn->name);
+	if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
+		(void)fprintf(fp, " == %s\n", arcn->ln_name);
+	else if (arcn->type == PAX_SLK)
+		(void)fprintf(fp, " => %s\n", arcn->ln_name);
+	else
+		(void)putc('\n', fp);
+	(void)fflush(fp);
+	return;
+}
+
+/*
+ * tty_ls()
+ * 	print a short summary of file to tty.
+ */
+
+void
+ls_tty(ARCHD *arcn)
+{
+	char f_date[DATELEN];
+	char f_mode[MODELEN];
+	const char *timefrmt;
+
+	if (d_first < 0)
+		d_first = 0;
+
+	if ((arcn->sb.st_mtime + SIXMONTHS) <= time(NULL))
+		timefrmt = d_first ? OLDFRMTD : OLDFRMTM;
+	else
+		timefrmt = d_first ? CURFRMTD : CURFRMTM;
+
+	/*
+	 * convert time to string, and print
+	 */
+#if 0
+	if (strftime(f_date, DATELEN, timefrmt,
+	    localtime(&(arcn->sb.st_mtime))) == 0)
+#endif
+		f_date[0] = '\0';
+#if 0
+	strmode(arcn->sb.st_mode, f_mode);
+#else
+	strcpy(f_mode, "");
+#endif
+	tty_prnt("%s%s %s\n", f_mode, f_date, arcn->name);
+	return;
+}
+
+/*
+ * l_strncpy()
+ *	copy src to dest up to len chars (stopping at first '\0').
+ *	when src is shorter than len, pads to len with '\0'. 
+ * Return:
+ *	number of chars copied. (Note this is a real performance win over
+ *	doing a strncpy(), a strlen(), and then a possible memset())
+ */
+
+int
+l_strncpy(char *dest, const char *src, int len)
+{
+	char *stop;
+	char *start;
+
+	stop = dest + len;
+	start = dest;
+	while ((dest < stop) && (*src != '\0'))
+		*dest++ = *src++;
+	len = dest - start;
+	while (dest < stop)
+		*dest++ = '\0';
+	return(len);
+}
+
+/*
+ * asc_ul()
+ *	convert hex/octal character string into a u_long. We do not have to
+ *	check for overflow! (the headers in all supported formats are not large
+ *	enough to create an overflow).
+ *	NOTE: strings passed to us are NOT TERMINATED.
+ * Return:
+ *	unsigned long value
+ */
+
+u_long
+asc_ul(char *str, int len, int base)
+{
+	char *stop;
+	u_long tval = 0;
+
+	stop = str + len;
+
+	/*
+	 * skip over leading blanks and zeros
+	 */
+	while ((str < stop) && ((*str == ' ') || (*str == '0')))
+		++str;
+
+	/*
+	 * for each valid digit, shift running value (tval) over to next digit
+	 * and add next digit
+	 */
+	if (base == HEX) {
+		while (str < stop) {
+			if ((*str >= '0') && (*str <= '9'))
+				tval = (tval << 4) + (*str++ - '0');
+			else if ((*str >= 'A') && (*str <= 'F'))
+				tval = (tval << 4) + 10 + (*str++ - 'A');
+			else if ((*str >= 'a') && (*str <= 'f'))
+				tval = (tval << 4) + 10 + (*str++ - 'a');
+			else
+				break;
+		}
+	} else {
+ 		while ((str < stop) && (*str >= '0') && (*str <= '7'))
+			tval = (tval << 3) + (*str++ - '0');
+	}
+	return(tval);
+}
+
+/*
+ * ul_asc()
+ *	convert an unsigned long into an hex/oct ascii string. pads with LEADING
+ *	ascii 0's to fill string completely
+ *	NOTE: the string created is NOT TERMINATED.
+ */
+
+int
+ul_asc(u_long val, char *str, int len, int base)
+{
+	char *pt;
+	u_long digit;
+
+	/*
+	 * WARNING str is not '\0' terminated by this routine
+	 */
+	pt = str + len - 1;
+
+	/*
+	 * do a tailwise conversion (start at right most end of string to place
+	 * least significant digit). Keep shifting until conversion value goes
+	 * to zero (all digits were converted)
+	 */
+	if (base == HEX) {
+		while (pt >= str) {
+			if ((digit = (val & 0xf)) < 10)
+				*pt-- = '0' + (char)digit;
+			else
+				*pt-- = 'a' + (char)(digit - 10);
+			if ((val = (val >> 4)) == (u_long)0)
+				break;
+		}
+	} else {
+		while (pt >= str) {
+			*pt-- = '0' + (char)(val & 0x7);
+			if ((val = (val >> 3)) == (u_long)0)
+				break;
+		}
+	}
+
+	/*
+	 * pad with leading ascii ZEROS. We return -1 if we ran out of space.
+	 */
+	while (pt >= str)
+		*pt-- = '0';
+	if (val != (u_long)0)
+		return(-1);
+	return(0);
+}
+
+#ifndef NET2_STAT
+/*
+ * asc_uqd()
+ *	convert hex/octal character string into a u_quad_t. We do not have to
+ *	check for overflow! (the headers in all supported formats are not large
+ *	enough to create an overflow).
+ *	NOTE: strings passed to us are NOT TERMINATED.
+ * Return:
+ *	u_quad_t value
+ */
+
+u_quad_t
+asc_uqd(char *str, int len, int base)
+{
+	char *stop;
+	u_quad_t tval = 0;
+
+	stop = str + len;
+
+	/*
+	 * skip over leading blanks and zeros
+	 */
+	while ((str < stop) && ((*str == ' ') || (*str == '0')))
+		++str;
+
+	/*
+	 * for each valid digit, shift running value (tval) over to next digit
+	 * and add next digit
+	 */
+	if (base == HEX) {
+		while (str < stop) {
+			if ((*str >= '0') && (*str <= '9'))
+				tval = (tval << 4) + (*str++ - '0');
+			else if ((*str >= 'A') && (*str <= 'F'))
+				tval = (tval << 4) + 10 + (*str++ - 'A');
+			else if ((*str >= 'a') && (*str <= 'f'))
+				tval = (tval << 4) + 10 + (*str++ - 'a');
+			else
+				break;
+		}
+	} else {
+ 		while ((str < stop) && (*str >= '0') && (*str <= '7'))
+			tval = (tval << 3) + (*str++ - '0');
+	}
+	return(tval);
+}
+
+/*
+ * uqd_asc()
+ *	convert an u_quad_t into a hex/oct ascii string. pads with LEADING
+ *	ascii 0's to fill string completely
+ *	NOTE: the string created is NOT TERMINATED.
+ */
+
+int
+uqd_asc(u_quad_t val, char *str, int len, int base)
+{
+	char *pt;
+	u_quad_t digit;
+
+	/*
+	 * WARNING str is not '\0' terminated by this routine
+	 */
+	pt = str + len - 1;
+
+	/*
+	 * do a tailwise conversion (start at right most end of string to place
+	 * least significant digit). Keep shifting until conversion value goes
+	 * to zero (all digits were converted)
+	 */
+	if (base == HEX) {
+		while (pt >= str) {
+			if ((digit = (val & 0xf)) < 10)
+				*pt-- = '0' + (char)digit;
+			else
+				*pt-- = 'a' + (char)(digit - 10);
+			if ((val = (val >> 4)) == (u_quad_t)0)
+				break;
+		}
+	} else {
+		while (pt >= str) {
+			*pt-- = '0' + (char)(val & 0x7);
+			if ((val = (val >> 3)) == (u_quad_t)0)
+				break;
+		}
+	}
+
+	/*
+	 * pad with leading ascii ZEROS. We return -1 if we ran out of space.
+	 */
+	while (pt >= str)
+		*pt-- = '0';
+	if (val != (u_quad_t)0)
+		return(-1);
+	return(0);
+}
+#endif
Index: /trunk/minix/commands/pax/getoldopt.c
===================================================================
--- /trunk/minix/commands/pax/getoldopt.c	(revision 9)
+++ /trunk/minix/commands/pax/getoldopt.c	(revision 9)
@@ -0,0 +1,70 @@
+/*	$OpenBSD: getoldopt.c,v 1.4 2000/01/22 20:24:51 deraadt Exp $	*/
+/*	$NetBSD: getoldopt.c,v 1.3 1995/03/21 09:07:28 cgd Exp $	*/
+
+/*-
+ * Plug-compatible replacement for getopt() for parsing tar-like
+ * arguments.  If the first argument begins with "-", it uses getopt;
+ * otherwise, it uses the old rules used by tar, dump, and ps.
+ *
+ * Written 25 August 1985 by John Gilmore (ihnp4!hoptoad!gnu) and placed
+ * in the Pubic Domain for your edification and enjoyment.
+ */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pax.h"
+#include "extern.h"
+
+int
+getoldopt(int argc, char **argv, const char *optstring)
+{
+	static char	*key;		/* Points to next keyletter */
+	static char	use_getopt;	/* !=0 if argv[1][0] was '-' */
+	char		c;
+	char		*place;
+
+	optarg = NULL;
+
+	if (key == NULL) {		/* First time */
+		if (argc < 2) return EOF;
+		key = argv[1];
+		if (*key == '-')
+			use_getopt++;
+		else
+			optind = 2;
+	}
+
+	if (use_getopt)
+		return getopt(argc, argv, optstring);
+
+	c = *key++;
+	if (c == '\0') {
+		key--;
+		return EOF;
+	}
+	place = strchr(optstring, c);
+
+	if (place == NULL || c == ':') {
+		fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
+		return('?');
+	}
+
+	place++;
+	if (*place == ':') {
+		if (optind < argc) {
+			optarg = argv[optind];
+			optind++;
+		} else {
+			fprintf(stderr, "%s: %c argument missing\n",
+				argv[0], c);
+			return('?');
+		}
+	}
+
+	return(c);
+}
Index: /trunk/minix/commands/pax/options.c
===================================================================
--- /trunk/minix/commands/pax/options.c	(revision 9)
+++ /trunk/minix/commands/pax/options.c	(revision 9)
@@ -0,0 +1,1591 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define _POSIX_SOURCE 1
+#define _MINIX 1
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)options.c	8.2 (Berkeley) 4/18/94";
+#endif /* not lint */
+#endif
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mtio.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <minix/paths.h>
+
+#include <sys/types.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+
+
+#include "pax.h"
+#include "options.h"
+#include "cpio.h"
+#include "tar.h"
+#include "extern.h"
+
+/*
+ * Routines which handle command line options
+ */
+
+static char flgch[] = FLGCH;	/* list of all possible flags */
+static OPLIST *ophead = NULL;	/* head for format specific options -x */
+static OPLIST *optail = NULL;	/* option tail */
+
+static int no_op(void);
+static void printflg(unsigned int);
+static int c_frmt(const void *, const void *);
+static off_t str_offt(char *);
+static char *getline(FILE *fp);
+static void pax_options(int, char **);
+static void pax_usage(void);
+static void tar_options(int, char **);
+static void tar_usage(void);
+static void cpio_options(int, char **);
+static void cpio_usage(void);
+
+/* errors from getline */
+#define GETLINE_FILE_CORRUPT 1
+#define GETLINE_OUT_OF_MEM 2
+static int getline_error;
+
+
+#define GZIP_CMD	"gzip"		/* command to run as gzip */
+#define COMPRESS_CMD	"compress"	/* command to run as compress */
+#define BZIP2_CMD	"bzip2"		/* command to run as gzip */
+
+/*
+ *	Format specific routine table - MUST BE IN SORTED ORDER BY NAME
+ *	(see pax.h for description of each function)
+ *
+ * 	name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
+ *	read, end_read, st_write, write, end_write, trail,
+ *	rd_data, wr_data, options
+ */
+
+FSUB fsub[] = {
+/* 0: OLD BINARY CPIO */
+	{"bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
+	bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, cpio_trail,
+	NULL, rd_wrfile, wr_rdfile, bad_opt},
+
+/* 1: OLD OCTAL CHARACTER CPIO */
+	{"cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
+	cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, cpio_trail,
+	NULL, rd_wrfile, wr_rdfile, bad_opt},
+
+/* 2: SVR4 HEX CPIO */
+	{"sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
+	vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, cpio_trail,
+	NULL, rd_wrfile, wr_rdfile, bad_opt},
+
+/* 3: SVR4 HEX CPIO WITH CRC */
+	{"sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
+	vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, cpio_trail,
+	NULL, rd_wrfile, wr_rdfile, bad_opt},
+
+/* 4: OLD TAR */
+	{"tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
+	tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, NULL, tar_trail,
+	rd_wrfile, wr_rdfile, tar_opt},
+
+/* 5: POSIX USTAR */
+	{"ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
+	ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, NULL, tar_trail,
+	rd_wrfile, wr_rdfile, bad_opt},
+};
+#define F_OCPIO	0	/* format when called as cpio -6 */
+#define F_ACPIO	1	/* format when called as cpio -c */
+#define F_CPIO	3	/* format when called as cpio */
+#define F_OTAR	4	/* format when called as tar -o */
+#define F_TAR	5	/* format when called as tar */
+#define DEFLT	5	/* default write format from list above */
+
+/*
+ * ford is the archive search order used by get_arc() to determine what kind
+ * of archive we are dealing with. This helps to properly id  archive formats
+ * some formats may be subsets of others....
+ */
+int ford[] = {5, 4, 3, 2, 1, 0, -1 };
+
+/*
+ * options()
+ *	figure out if we are pax, tar or cpio. Call the appropriate options
+ *	parser
+ */
+
+void
+options(int argc, char **argv)
+{
+
+	/*
+	 * Are we acting like pax, tar or cpio (based on argv[0])
+	 */
+	if ((argv0 = strrchr(argv[0], '/')) != NULL)
+		argv0++;
+	else
+		argv0 = argv[0];
+
+	if (strcmp(NM_TAR, argv0) == 0) {
+		tar_options(argc, argv);
+		return;
+	}
+	else if (strcmp(NM_CPIO, argv0) == 0) {
+		cpio_options(argc, argv);
+		return;
+	}
+	/*
+	 * assume pax as the default
+	 */
+	argv0 = NM_PAX;
+	pax_options(argc, argv);
+	return;
+}
+
+/*
+ * pax_options()
+ *	look at the user specified flags. set globals as required and check if
+ *	the user specified a legal set of flags. If not, complain and exit
+ */
+
+static void
+pax_options(int argc, char **argv)
+{
+	int c;
+	size_t i;
+	unsigned int flg = 0;
+	unsigned int bflg = 0;
+	char *pt;
+	FSUB tmp;
+
+	/*
+	 * process option flags
+	 */
+	while ((c=getopt(argc,argv,"ab:cdf:iklno:p:rs:tuvwx:zB:DE:G:HLPT:U:XYZ"))
+	    != -1) {
+		switch (c) {
+		case 'a':
+			/*
+			 * append
+			 */
+			flg |= AF;
+			break;
+		case 'b':
+			/*
+			 * specify blocksize
+			 */
+			flg |= BF;
+			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
+				paxwarn(1, "Invalid block size %s", optarg);
+				pax_usage();
+			}
+			break;
+		case 'c':
+			/*
+			 * inverse match on patterns
+			 */
+			cflag = 1;
+			flg |= CF;
+			break;
+		case 'd':
+			/*
+			 * match only dir on extract, not the subtree at dir
+			 */
+			dflag = 1;
+			flg |= DF;
+			break;
+		case 'f':
+			/*
+			 * filename where the archive is stored
+			 */
+			arcname = optarg;
+			flg |= FF;
+			break;
+		case 'i':
+			/*
+			 * interactive file rename
+			 */
+			iflag = 1;
+			flg |= IF;
+			break;
+		case 'k':
+			/*
+			 * do not clobber files that exist
+			 */
+			kflag = 1;
+			flg |= KF;
+			break;
+		case 'l':
+			/*
+			 * try to link src to dest with copy (-rw)
+			 */
+			lflag = 1;
+			flg |= LF;
+			break;
+		case 'n':
+			/*
+			 * select first match for a pattern only
+			 */
+			nflag = 1;
+			flg |= NF;
+			break;
+		case 'o':
+			/*
+			 * pass format specific options
+			 */
+			flg |= OF;
+			if (opt_add(optarg) < 0)
+				pax_usage();
+			break;
+		case 'p':
+			/*
+			 * specify file characteristic options
+			 */
+			for (pt = optarg; *pt != '\0'; ++pt) {
+				switch(*pt) {
+				case 'a':
+					/*
+					 * do not preserve access time
+					 */
+					patime = 0;
+					break;
+				case 'e':
+					/*
+					 * preserve user id, group id, file
+					 * mode, access/modification times
+					 */
+					pids = 1;
+					pmode = 1;
+					patime = 1;
+					pmtime = 1;
+					break;
+				case 'm':
+					/*
+					 * do not preserve modification time
+					 */
+					pmtime = 0;
+					break;
+				case 'o':
+					/*
+					 * preserve uid/gid
+					 */
+					pids = 1;
+					break;
+				case 'p':
+					/*
+					 * preserver file mode bits
+					 */
+					pmode = 1;
+					break;
+				default:
+					paxwarn(1, "Invalid -p string: %c", *pt);
+					pax_usage();
+					break;
+				}
+			}
+			flg |= PF;
+			break;
+		case 'r':
+			/*
+			 * read the archive
+			 */
+			flg |= RF;
+			break;
+		case 's':
+			/*
+			 * file name substitution name pattern
+			 */
+			if (rep_add(optarg) < 0) {
+				pax_usage();
+				break;
+			}
+			flg |= SF;
+			break;
+		case 't':
+			/*
+			 * preserve access time on file system nodes we read
+			 */
+			tflag = 1;
+			flg |= TF;
+			break;
+		case 'u':
+			/*
+			 * ignore those older files
+			 */
+			uflag = 1;
+			flg |= UF;
+			break;
+		case 'v':
+			/*
+			 * verbose operation mode
+			 */
+			vflag = 1;
+			flg |= VF;
+			break;
+		case 'w':
+			/*
+			 * write an archive
+			 */
+			flg |= WF;
+			break;
+		case 'x':
+			/*
+			 * specify an archive format on write
+			 */
+			tmp.name = optarg;
+			if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
+			    sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL) {
+				flg |= XF;
+				break;
+			}
+			paxwarn(1, "Unknown -x format: %s", optarg);
+			(void)fputs("pax: Known -x formats are:", stderr);
+			for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
+				(void)fprintf(stderr, " %s", fsub[i].name);
+			(void)fputs("\n\n", stderr);
+			pax_usage();
+			break;
+		case 'z':
+			/*
+			 * use gzip.  Non standard option.
+			 */
+			gzip_program = GZIP_CMD;
+			break;
+		case 'B':
+			/*
+			 * non-standard option on number of bytes written on a
+			 * single archive volume.
+			 */
+			if ((wrlimit = str_offt(optarg)) <= 0) {
+				paxwarn(1, "Invalid write limit %s", optarg);
+				pax_usage();
+			}
+			if (wrlimit % BLKMULT) {
+				paxwarn(1, "Write limit is not a %d byte multiple",
+				    BLKMULT);
+				pax_usage();
+			}
+			flg |= CBF;
+			break;
+		case 'D':
+			/*
+			 * On extraction check file inode change time before the
+			 * modification of the file name. Non standard option.
+			 */
+			Dflag = 1;
+			flg |= CDF;
+			break;
+		case 'E':
+			/*
+			 * non-standard limit on read faults
+			 * 0 indicates stop after first error, values
+			 * indicate a limit, "NONE" try forever
+			 */
+			flg |= CEF;
+			if (strcmp(NONE, optarg) == 0)
+				maxflt = -1;
+			else if ((maxflt = atoi(optarg)) < 0) {
+				paxwarn(1, "Error count value must be positive");
+				pax_usage();
+			}
+			break;
+		case 'G':
+			/*
+			 * non-standard option for selecting files within an
+			 * archive by group (gid or name)
+			 */
+			if (grp_add(optarg) < 0) {
+				pax_usage();
+				break;
+			}
+			flg |= CGF;
+			break;
+		case 'H':
+			/*
+			 * follow command line symlinks only
+			 */
+			Hflag = 1;
+			flg |= CHF;
+			break;
+		case 'L':
+			/*
+			 * follow symlinks
+			 */
+			Lflag = 1;
+			flg |= CLF;
+			break;
+		case 'P':
+			/*
+			 * do NOT follow symlinks (default)
+			 */
+			Lflag = 0;
+			flg |= CPF;
+			break;
+		case 'T':
+			/*
+			 * non-standard option for selecting files within an
+			 * archive by modification time range (lower,upper)
+			 */
+			if (trng_add(optarg) < 0) {
+				pax_usage();
+				break;
+			}
+			flg |= CTF;
+			break;
+		case 'U':
+			/*
+			 * non-standard option for selecting files within an
+			 * archive by user (uid or name)
+			 */
+			if (usr_add(optarg) < 0) {
+				pax_usage();
+				break;
+			}
+			flg |= CUF;
+			break;
+		case 'X':
+			/*
+			 * do not pass over mount points in the file system
+			 */
+			Xflag = 1;
+			flg |= CXF;
+			break;
+		case 'Y':
+			/*
+			 * On extraction check file inode change time after the
+			 * modification of the file name. Non standard option.
+			 */
+			Yflag = 1;
+			flg |= CYF;
+			break;
+		case 'Z':
+			/*
+			 * On extraction check modification time after the
+			 * modification of the file name. Non standard option.
+			 */
+			Zflag = 1;
+			flg |= CZF;
+			break;
+		default:
+			pax_usage();
+			break;
+		}
+	}
+
+	/*
+	 * figure out the operation mode of pax read,write,extract,copy,append
+	 * or list. check that we have not been given a bogus set of flags
+	 * for the operation mode.
+	 */
+	if (ISLIST(flg)) {
+		act = LIST;
+		listf = stdout;
+		bflg = flg & BDLIST;
+	} else if (ISEXTRACT(flg)) {
+		act = EXTRACT;
+		bflg = flg & BDEXTR;
+	} else if (ISARCHIVE(flg)) {
+		act = ARCHIVE;
+		bflg = flg & BDARCH;
+	} else if (ISAPPND(flg)) {
+		act = APPND;
+		bflg = flg & BDARCH;
+	} else if (ISCOPY(flg)) {
+		act = COPY;
+		bflg = flg & BDCOPY;
+	} else
+		pax_usage();
+	if (bflg) {
+		printflg(flg);
+		pax_usage();
+	}
+
+	/*
+	 * if we are writing (ARCHIVE) we use the default format if the user
+	 * did not specify a format. when we write during an APPEND, we will
+	 * adopt the format of the existing archive if none was supplied.
+	 */
+	if (!(flg & XF) && (act == ARCHIVE))
+		frmt = &(fsub[DEFLT]);
+
+	/*
+	 * process the args as they are interpreted by the operation mode
+	 */
+	switch (act) {
+	case LIST:
+	case EXTRACT:
+		for (; optind < argc; optind++)
+			if (pat_add(argv[optind], NULL) < 0)
+				pax_usage();
+		break;
+	case COPY:
+		if (optind >= argc) {
+			paxwarn(0, "Destination directory was not supplied");
+			pax_usage();
+		}
+		--argc;
+		dirptr = argv[argc];
+		/* FALLTHROUGH */
+	case ARCHIVE:
+	case APPND:
+		for (; optind < argc; optind++)
+			if (ftree_add(argv[optind], 0) < 0)
+				pax_usage();
+		/*
+		 * no read errors allowed on updates/append operation!
+		 */
+		maxflt = 0;
+		break;
+	}
+}
+
+
+/*
+ * tar_options()
+ *	look at the user specified flags. set globals as required and check if
+ *	the user specified a legal set of flags. If not, complain and exit
+ */
+
+static void
+tar_options(int argc, char **argv)
+{
+	int c;
+	int fstdin = 0;
+	int Oflag = 0;
+	int nincfiles = 0;
+	int incfiles_max = 0;
+	struct incfile {
+		char *file;
+		char *dir;
+	};
+	struct incfile *incfiles = NULL;
+
+	/*
+	 * Set default values.
+	 */
+	rmleadslash = 1;
+
+	/*
+	 * process option flags
+	 */
+	while ((c = getoldopt(argc, argv,
+	    "b:cef:hjmopqruts:vwxyzBC:HI:LOPXZ014578")) != -1) {
+		switch(c) {
+		case 'b':
+			/*
+			 * specify blocksize in 512-byte blocks
+			 */
+			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
+				paxwarn(1, "Invalid block size %s", optarg);
+				tar_usage();
+			}
+			wrblksz *= 512;		/* XXX - check for int oflow */
+			break;
+		case 'c':
+			/*
+			 * create an archive
+			 */
+			act = ARCHIVE;
+			break;
+		case 'e':
+			/*
+			 * stop after first error
+			 */
+			maxflt = 0;
+			break;
+		case 'f':
+			/*
+			 * filename where the archive is stored
+			 */
+			if ((optarg[0] == '-') && (optarg[1]== '\0')) {
+				/*
+				 * treat a - as stdin
+				 */
+				fstdin = 1;
+				arcname = NULL;
+				break;
+			}
+			fstdin = 0;
+			arcname = optarg;
+			break;
+		case 'h':
+			/*
+			 * follow symlinks
+			 */
+			Lflag = 1;
+			break;
+		case 'j':
+		case 'y':
+			/*
+			 * use bzip2.  Non standard option.
+			 */
+			gzip_program = BZIP2_CMD;
+			break;
+		case 'm':
+			/*
+			 * do not preserve modification time
+			 */
+			pmtime = 0;
+			break;
+		case 'o':
+			if (opt_add("write_opt=nodir") < 0)
+				tar_usage();
+		case 'O':
+			Oflag = 1;
+			break;
+		case 'p':
+			/*
+			 * preserve uid/gid and file mode, regardless of umask
+			 */
+			pmode = 1;
+			pids = 1;
+			break;
+		case 'q':
+			/*
+			 * select first match for a pattern only
+			 */
+			nflag = 1;
+			break;
+		case 'r':
+		case 'u':
+			/*
+			 * append to the archive
+			 */
+			act = APPND;
+			break;
+		case 's':
+			/*
+			 * file name substitution name pattern
+			 */
+			if (rep_add(optarg) < 0) {
+				tar_usage();
+				break;
+			}
+			break;
+		case 't':
+			/*
+			 * list contents of the tape
+			 */
+			act = LIST;
+			break;
+		case 'v':
+			/*
+			 * verbose operation mode
+			 */
+			vflag++;
+			break;
+		case 'w':
+			/*
+			 * interactive file rename
+			 */
+			iflag = 1;
+			break;
+		case 'x':
+			/*
+			 * extract an archive, preserving mode,
+			 * and mtime if possible.
+			 */
+			act = EXTRACT;
+			pmtime = 1;
+			break;
+		case 'z':
+			/*
+			 * use gzip.  Non standard option.
+			 */
+			gzip_program = GZIP_CMD;
+			break;
+		case 'B':
+			/*
+			 * Nothing to do here, this is pax default
+			 */
+			break;
+		case 'C':
+			chdname = optarg;
+			break;
+		case 'H':
+			/*
+			 * follow command line symlinks only
+			 */
+			Hflag = 1;
+			break;
+		case 'I':
+			if (++nincfiles > incfiles_max) {
+				incfiles_max = nincfiles + 3;
+				incfiles = realloc(incfiles,
+				    sizeof(*incfiles) * incfiles_max);
+				if (incfiles == NULL) {
+					paxwarn(0, "Unable to allocate space "
+					    "for option list");
+					exit(1);
+				}
+			}
+			incfiles[nincfiles - 1].file = optarg;
+			incfiles[nincfiles - 1].dir = chdname;
+			break;
+		case 'L':
+			/*
+			 * follow symlinks
+			 */
+			Lflag = 1;
+			break;
+		case 'P':
+			/*
+			 * do not remove leading '/' from pathnames
+			 */
+			rmleadslash = 0;
+			break;
+		case 'X':
+			/*
+			 * do not pass over mount points in the file system
+			 */
+			Xflag = 1;
+			break;
+		case 'Z':
+			/*
+			 * use compress.
+			 */
+			gzip_program = COMPRESS_CMD;
+			break;
+		case '0':
+			arcname = DEV_0;
+			break;
+		case '1':
+			arcname = DEV_1;
+			break;
+		case '4':
+			arcname = DEV_4;
+			break;
+		case '5':
+			arcname = DEV_5;
+			break;
+		case '7':
+			arcname = DEV_7;
+			break;
+		case '8':
+			arcname = DEV_8;
+			break;
+		default:
+			tar_usage();
+			break;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Traditional tar behaviour (pax uses stderr unless in list mode) */
+	if (fstdin == 1 && act == ARCHIVE)
+		listf = stderr;
+	else
+		listf = stdout;
+
+	/* Traditional tar behaviour (pax wants to read file list from stdin) */
+	if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0)
+		exit(0);
+
+	/*
+	 * if we are writing (ARCHIVE) specify tar, otherwise run like pax
+	 * (unless -o specified)
+	 */
+	if (act == ARCHIVE || act == APPND)
+		frmt = &(fsub[Oflag ? F_OTAR : F_TAR]);
+	else if (Oflag) {
+		paxwarn(1, "The -O/-o options are only valid when writing an archive");
+		tar_usage();		/* only valid when writing */
+	}
+
+	/*
+	 * process the args as they are interpreted by the operation mode
+	 */
+	switch (act) {
+	case LIST:
+	case EXTRACT:
+	default:
+		{
+			int sawpat = 0;
+			char *file, *dir = NULL;
+
+			while (nincfiles || *argv != NULL) {
+				/*
+				 * If we queued up any include files,
+				 * pull them in now.  Otherwise, check
+				 * for -I and -C positional flags.
+				 * Anything else must be a file to
+				 * extract.
+				 */
+				if (nincfiles) {
+					file = incfiles->file;
+					dir = incfiles->dir;
+					incfiles++;
+					nincfiles--;
+				} else if (strcmp(*argv, "-I") == 0) {
+					if (*++argv == NULL)
+						break;
+					file = *argv++;
+					dir = chdname;
+				} else
+					file = NULL;
+				if (file != NULL) {
+					FILE *fp;
+					char *str;
+
+					if (strcmp(file, "-") == 0)
+						fp = stdin;
+					else if ((fp = fopen(file, "r")) == NULL) {
+						paxwarn(1, "Unable to open file '%s' for read", file);
+						tar_usage();
+					}
+					while ((str = getline(fp)) != NULL) {
+						if (pat_add(str, dir) < 0)
+							tar_usage();
+						sawpat = 1;
+					}
+					if (strcmp(file, "-") != 0)
+						fclose(fp);
+					if (getline_error) {
+						paxwarn(1, "Problem with file '%s'", file);
+						tar_usage();
+					}
+				} else if (strcmp(*argv, "-C") == 0) {
+					if (*++argv == NULL)
+						break;
+					chdname = *argv++;
+				} else if (pat_add(*argv++, chdname) < 0)
+					tar_usage();
+				else
+					sawpat = 1;
+			}
+			/*
+			 * if patterns were added, we are doing	chdir()
+			 * on a file-by-file basis, else, just one
+			 * global chdir (if any) after opening input.
+			 */
+			if (sawpat > 0)
+				chdname = NULL;	
+		}
+		break;
+	case ARCHIVE:
+	case APPND:
+		if (chdname != NULL) {	/* initial chdir() */
+			if (ftree_add(chdname, 1) < 0)
+				tar_usage();
+		}
+
+		while (nincfiles || *argv != NULL) {
+			char *file, *dir = NULL;
+
+			/*
+			 * If we queued up any include files, pull them in
+			 * now.  Otherwise, check for -I and -C positional
+			 * flags.  Anything else must be a file to include
+			 * in the archive.
+			 */
+			if (nincfiles) {
+				file = incfiles->file;
+				dir = incfiles->dir;
+				incfiles++;
+				nincfiles--;
+			} else if (strcmp(*argv, "-I") == 0) {
+				if (*++argv == NULL)
+					break;
+				file = *argv++;
+				dir = NULL;
+			} else
+				file = NULL;
+			if (file != NULL) {
+				FILE *fp;
+				char *str;
+
+				/* Set directory if needed */
+				if (dir) {
+					if (ftree_add(dir, 1) < 0)
+						tar_usage();
+				}
+
+				if (strcmp(file, "-") == 0)
+					fp = stdin;
+				else if ((fp = fopen(file, "r")) == NULL) {
+					paxwarn(1, "Unable to open file '%s' for read", file);
+					tar_usage();
+				}
+				while ((str = getline(fp)) != NULL) {
+					if (ftree_add(str, 0) < 0)
+						tar_usage();
+				}
+				if (strcmp(file, "-") != 0)
+					fclose(fp);
+				if (getline_error) {
+					paxwarn(1, "Problem with file '%s'",
+					    file);
+					tar_usage();
+				}
+			} else if (strcmp(*argv, "-C") == 0) {
+				if (*++argv == NULL)
+					break;
+				if (ftree_add(*argv++, 1) < 0)
+					tar_usage();
+			} else if (ftree_add(*argv++, 0) < 0)
+				tar_usage();
+		}
+		/*
+		 * no read errors allowed on updates/append operation!
+		 */
+		maxflt = 0;
+		break;
+	}
+	if (!fstdin && ((arcname == NULL) || (*arcname == '\0'))) {
+		arcname = getenv("TAPE");
+		if ((arcname == NULL) || (*arcname == '\0'))
+			arcname = _PATH_DEFTAPE;
+	}
+}
+
+static int
+mkpath(char *path)
+{
+	struct stat sb;
+	char *slash;
+	int done = 0;
+
+	slash = path;
+
+	while (!done) {
+		slash += strspn(slash, "/");
+		slash += strcspn(slash, "/");
+
+		done = (*slash == '\0');
+		*slash = '\0';
+
+		if (stat(path, &sb)) {
+			if (errno != ENOENT || mkdir(path, 0777)) {
+				paxwarn(1, "%s", path);
+				return (-1);
+			}
+		} else if (!S_ISDIR(sb.st_mode)) {
+			syswarn(1, ENOTDIR, "%s", path);
+			return (-1);
+		}
+
+		if (!done)
+			*slash = '/';
+	}
+
+	return (0);
+}
+/*
+ * cpio_options()
+ *	look at the user specified flags. set globals as required and check if
+ *	the user specified a legal set of flags. If not, complain and exit
+ */
+
+static void
+cpio_options(int argc, char **argv)
+{
+	int c;
+	size_t i;
+	char *str;
+	FSUB tmp;
+	FILE *fp;
+
+	kflag = 1;
+	pids = 1;
+	pmode = 1;
+	pmtime = 0;
+	arcname = NULL;
+	dflag = 1;
+	act = -1;
+	nodirs = 1;
+	while ((c=getopt(argc,argv,"abcdfiklmoprstuvzABC:E:F:H:I:LO:SZ6")) != -1)
+		switch (c) {
+			case 'a':
+				/*
+				 * preserve access time on files read
+				 */
+				tflag = 1;
+				break;
+			case 'b':
+				/*
+				 * swap bytes and half-words when reading data
+				 */
+				break;
+			case 'c':
+				/*
+				 * ASCII cpio header
+				 */
+				frmt = &(fsub[F_ACPIO]);
+				break;
+			case 'd':
+				/*
+				 * create directories as needed
+				 */
+				nodirs = 0;
+				break;
+			case 'f':
+				/*
+				 * invert meaning of pattern list
+				 */
+				cflag = 1;
+				break;
+			case 'i':
+				/*
+				 * restore an archive
+				 */
+				act = EXTRACT;
+				break;
+			case 'k':
+				break;
+			case 'l':
+				/*
+				 * use links instead of copies when possible
+				 */
+				lflag = 1;
+				break;
+			case 'm':
+				/*
+				 * preserve modification time
+				 */
+				pmtime = 1;
+				break;
+			case 'o':
+				/*
+				 * create an archive
+				 */
+				act = ARCHIVE;
+				frmt = &(fsub[F_CPIO]);
+				break;
+			case 'p':
+				/*
+				 * copy-pass mode
+				 */
+				act = COPY;
+				break;
+			case 'r':
+				/*
+				 * interactively rename files
+				 */
+				iflag = 1;
+				break;
+			case 's':
+				/*
+				 * swap bytes after reading data
+				 */
+				break;
+			case 't':
+				/*
+				 * list contents of archive
+				 */
+				act = LIST;
+				listf = stdout;
+				break;
+			case 'u':
+				/*
+				 * replace newer files
+				 */
+				kflag = 0;
+				break;
+			case 'v':
+				/*
+				 * verbose operation mode
+				 */
+				vflag = 1;
+				break;
+			case 'z':
+				/*
+				 * use gzip.  Non standard option.
+				 */
+				gzip_program = GZIP_CMD;
+				break;
+			case 'A':
+				/*
+				 * append mode
+				 */
+				act = APPND;
+				break;
+			case 'B':
+				/*
+				 * Use 5120 byte block size
+				 */
+				wrblksz = 5120;
+				break;
+			case 'C':
+				/*
+				 * set block size in bytes
+				 */
+				wrblksz = atoi(optarg);
+				break;
+			case 'E':
+				/*
+				 * file with patterns to extract or list
+				 */
+				if ((fp = fopen(optarg, "r")) == NULL) {
+					paxwarn(1, "Unable to open file '%s' for read", optarg);
+					cpio_usage();
+				}
+				while ((str = getline(fp)) != NULL) {
+					pat_add(str, NULL);
+				}
+				fclose(fp);
+				if (getline_error) {
+					paxwarn(1, "Problem with file '%s'", optarg);
+					cpio_usage();
+				}
+				break;
+			case 'F':
+			case 'I':
+			case 'O':
+				/*
+				 * filename where the archive is stored
+				 */
+				if ((optarg[0] == '-') && (optarg[1]== '\0')) {
+					/*
+					 * treat a - as stdin
+					 */
+					arcname = NULL;
+					break;
+				}
+				arcname = optarg;
+				break;
+			case 'H':
+				/*
+				 * specify an archive format on write
+				 */
+				tmp.name = optarg;
+				if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
+				    sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL)
+					break;
+				paxwarn(1, "Unknown -H format: %s", optarg);
+				(void)fputs("cpio: Known -H formats are:", stderr);
+				for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
+					(void)fprintf(stderr, " %s", fsub[i].name);
+				(void)fputs("\n\n", stderr);
+				cpio_usage();
+				break;
+			case 'L':
+				/*
+				 * follow symbolic links
+				 */
+				Lflag = 1;
+				break;
+			case 'S':
+				/*
+				 * swap halfwords after reading data
+				 */
+				break;
+			case 'Z':
+				/*
+				 * use compress.  Non standard option.
+				 */
+				gzip_program = COMPRESS_CMD;
+				break;
+			case '6':
+				/*
+				 * process Version 6 cpio format
+				 */
+				frmt = &(fsub[F_OCPIO]);
+				break;
+			case '?':
+			default:
+				cpio_usage();
+				break;
+		}
+	argc -= optind;
+	argv += optind;
+
+	/*
+	 * process the args as they are interpreted by the operation mode
+	 */
+	switch (act) {
+		case LIST:
+		case EXTRACT:
+			while (*argv != NULL)
+				if (pat_add(*argv++, NULL) < 0)
+					cpio_usage();
+			break;
+		case COPY:
+			if (*argv == NULL) {
+				paxwarn(0, "Destination directory was not supplied");
+				cpio_usage();
+			}
+			dirptr = *argv;
+			if (mkpath(dirptr) < 0)
+				cpio_usage();
+			--argc;
+			++argv;
+			/* FALLTHROUGH */
+		case ARCHIVE:
+		case APPND:
+			if (*argv != NULL)
+				cpio_usage();
+			/*
+			 * no read errors allowed on updates/append operation!
+			 */
+			maxflt = 0;
+			while ((str = getline(stdin)) != NULL) {
+				ftree_add(str, 0);
+			}
+			if (getline_error) {
+				paxwarn(1, "Problem while reading stdin");
+				cpio_usage();
+			}
+			break;
+		default:
+			cpio_usage();
+			break;
+	}
+}
+
+/*
+ * printflg()
+ *	print out those invalid flag sets found to the user
+ */
+
+static void
+printflg(unsigned int flg)
+{
+	int nxt;
+	int pos = 0;
+
+	(void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
+	while ((nxt = ffs(flg)) != 0) {
+		flg = flg >> nxt;
+		pos += nxt;
+		(void)fprintf(stderr, " -%c", flgch[pos-1]);
+	}
+	(void)putc('\n', stderr);
+}
+
+/*
+ * c_frmt()
+ *	comparison routine used by bsearch to find the format specified
+ *	by the user
+ */
+
+static int
+c_frmt(const void *a, const void *b)
+{
+	return(strcmp(((const FSUB *)a)->name, ((const FSUB *)b)->name));
+}
+
+/*
+ * opt_next()
+ *	called by format specific options routines to get each format specific
+ *	flag and value specified with -o
+ * Return:
+ *	pointer to next OPLIST entry or NULL (end of list).
+ */
+
+OPLIST *
+opt_next(void)
+{
+	OPLIST *opt;
+
+	if ((opt = ophead) != NULL)
+		ophead = ophead->fow;
+	return(opt);
+}
+
+/*
+ * bad_opt()
+ *	generic routine used to complain about a format specific options
+ *	when the format does not support options.
+ */
+
+int
+bad_opt(void)
+{
+	OPLIST *opt;
+
+	if (ophead == NULL)
+		return(0);
+	/*
+	 * print all we were given
+	 */
+	paxwarn(1,"These format options are not supported");
+	while ((opt = opt_next()) != NULL)
+		(void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
+	pax_usage();
+	return(0);
+}
+
+/*
+ * opt_add()
+ *	breaks the value supplied to -o into an option name and value. Options
+ *	are given to -o in the form -o name-value,name=value
+ *	multiple -o may be specified.
+ * Return:
+ *	0 if format in name=value format, -1 if -o is passed junk.
+ */
+
+int
+opt_add(const char *str)
+{
+	OPLIST *opt;
+	char *frpt;
+	char *pt;
+	char *endpt;
+	char *lstr;
+
+	if ((str == NULL) || (*str == '\0')) {
+		paxwarn(0, "Invalid option name");
+		return(-1);
+	}
+	if ((lstr = strdup(str)) == NULL) {
+		paxwarn(0, "Unable to allocate space for option list");
+		return(-1);
+	}
+	frpt = endpt = lstr;
+
+	/*
+	 * break into name and values pieces and stuff each one into a
+	 * OPLIST structure. When we know the format, the format specific
+	 * option function will go through this list
+	 */
+	while ((frpt != NULL) && (*frpt != '\0')) {
+		if ((endpt = strchr(frpt, ',')) != NULL)
+			*endpt = '\0';
+		if ((pt = strchr(frpt, '=')) == NULL) {
+			paxwarn(0, "Invalid options format");
+			free(lstr);
+			return(-1);
+		}
+		if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
+			paxwarn(0, "Unable to allocate space for option list");
+			free(lstr);
+			return(-1);
+		}
+		*pt++ = '\0';
+		opt->name = frpt;
+		opt->value = pt;
+		opt->fow = NULL;
+		if (endpt != NULL)
+			frpt = endpt + 1;
+		else
+			frpt = NULL;
+		if (ophead == NULL) {
+			optail = ophead = opt;
+			continue;
+		}
+		optail->fow = opt;
+		optail = opt;
+	}
+	return(0);
+}
+
+/*
+ * str_offt()
+ *	Convert an expression of the following forms to an off_t > 0.
+ * 	1) A positive decimal number.
+ *	2) A positive decimal number followed by a b (mult by 512).
+ *	3) A positive decimal number followed by a k (mult by 1024).
+ *	4) A positive decimal number followed by a m (mult by 512).
+ *	5) A positive decimal number followed by a w (mult by sizeof int)
+ *	6) Two or more positive decimal numbers (with/without k,b or w).
+ *	   separated by x (also * for backwards compatibility), specifying
+ *	   the product of the indicated values.
+ * Return:
+ *	0 for an error, a positive value o.w.
+ */
+
+static off_t
+str_offt(char *val)
+{
+	char *expr;
+	off_t num, t;
+
+#	ifdef NET2_STAT
+	num = strtol(val, &expr, 0);
+	if ((num == LONG_MAX) || (num <= 0) || (expr == val))
+#	else
+	num = strtoq(val, &expr, 0);
+	if ((num == QUAD_MAX) || (num <= 0) || (expr == val))
+#	endif
+		return(0);
+
+	switch(*expr) {
+	case 'b':
+		t = num;
+		num *= 512;
+		if (t > num)
+			return(0);
+		++expr;
+		break;
+	case 'k':
+		t = num;
+		num *= 1024;
+		if (t > num)
+			return(0);
+		++expr;
+		break;
+	case 'm':
+		t = num;
+		num *= 1048576;
+		if (t > num)
+			return(0);
+		++expr;
+		break;
+	case 'w':
+		t = num;
+		num *= sizeof(int);
+		if (t > num)
+			return(0);
+		++expr;
+		break;
+	}
+
+	switch(*expr) {
+		case '\0':
+			break;
+		case '*':
+		case 'x':
+			t = num;
+			num *= str_offt(expr + 1);
+			if (t > num)
+				return(0);
+			break;
+		default:
+			return(0);
+	}
+	return(num);
+}
+
+char *fgetln(FILE *f, size_t *);
+
+static char *
+getline(FILE *f)
+{
+	char *name, *temp;
+	size_t len;
+
+	name = fgetln(f, &len);
+	if (!name) {
+		getline_error = ferror(f) ? GETLINE_FILE_CORRUPT : 0;
+		return(0);
+	}
+	if (name[len-1] != '\n')
+		len++;
+	temp = malloc(len);
+	if (!temp) {
+		getline_error = GETLINE_OUT_OF_MEM;
+		return(0);
+	}
+	memcpy(temp, name, len-1);
+	temp[len-1] = 0;
+	return(temp);
+}
+			
+/*
+ * no_op()
+ *	for those option functions where the archive format has nothing to do.
+ * Return:
+ *	0
+ */
+
+static int
+no_op(void)
+{
+	return(0);
+}
+
+/*
+ * pax_usage()
+ *	print the usage summary to the user
+ */
+
+static void
+pax_usage(void)
+{
+	(void)fputs("usage: pax [-cdnvz] [-E limit] [-f archive] ", stderr);
+	(void)fputs("[-s replstr] ... [-U user] ...", stderr);
+	(void)fputs("\n	   [-G group] ... ", stderr);
+	(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
+	(void)fputs("[pattern ...]\n", stderr);
+	(void)fputs("       pax -r [-cdiknuvzDYZ] [-E limit] ", stderr);
+	(void)fputs("[-f archive] [-o options] ... \n", stderr);
+	(void)fputs("	   [-p string] ... [-s replstr] ... ", stderr);
+	(void)fputs("[-U user] ... [-G group] ...\n	   ", stderr);
+	(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
+	(void)fputs(" [pattern ...]\n", stderr);
+	(void)fputs("       pax -w [-dituvzHLPX] [-b blocksize] ", stderr);
+	(void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr);
+	(void)fputs("	   [-B bytes] [-s replstr] ... ", stderr);
+	(void)fputs("[-o options] ... [-U user] ...", stderr);
+	(void)fputs("\n	   [-G group] ... ", stderr);
+	(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
+	(void)fputs("[file ...]\n", stderr);
+	(void)fputs("       pax -r -w [-diklntuvDHLPXYZ] ", stderr);
+	(void)fputs("[-p string] ... [-s replstr] ...", stderr);
+	(void)fputs("\n	   [-U user] ... [-G group] ... ", stderr);
+	(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
+	(void)fputs("\n	   [file ...] directory\n", stderr);
+	exit(1);
+}
+
+/*
+ * tar_usage()
+ *	print the usage summary to the user
+ */
+
+static void
+tar_usage(void)
+{
+	(void)fputs("usage: tar [-]{crtux}[-befhjmopqsvwyzHLOPXZ014578] [blocksize] ",
+		 stderr);
+	(void)fputs("[archive] [replstr] [-C directory] [-I file] [file ...]\n",
+	    stderr);
+	exit(1);
+}
+
+/*
+ * cpio_usage()
+ *	print the usage summary to the user
+ */
+
+static void
+cpio_usage(void)
+{
+	(void)fputs("usage: cpio -o [-aABcLvVzZ] [-C bytes] [-H format] [-O archive]\n", stderr);
+	(void)fputs("               [-F archive] < name-list [> archive]\n", stderr);
+	(void)fputs("       cpio -i [-bBcdfmnrsStuvVzZ6] [-C bytes] [-E file] [-H format]\n", stderr);
+	(void)fputs("               [-I archive] [-F archive] [pattern...] [< archive]\n", stderr);
+	(void)fputs("       cpio -p [-adlLmuvV] destination-directory < name-list\n", stderr);
+	exit(1);
+}
Index: /trunk/minix/commands/pax/options.h
===================================================================
--- /trunk/minix/commands/pax/options.h	(revision 9)
+++ /trunk/minix/commands/pax/options.h	(revision 9)
@@ -0,0 +1,110 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)options.h	8.2 (Berkeley) 4/18/94
+ * $FreeBSD: src/bin/pax/options.h,v 1.6 2004/04/06 20:06:48 markm Exp $
+ */
+
+/*
+ * argv[0] names. Used for tar and cpio emulation
+ */
+
+#define NM_TAR  "tar"
+#define NM_CPIO "cpio"
+#define NM_PAX  "pax"
+
+/*
+ * Constants used to specify the legal sets of flags in pax. For each major
+ * operation mode of pax, a set of illegal flags is defined. If any one of
+ * those illegal flags are found set, we scream and exit
+ */
+#define NONE	"none"
+
+/*
+ * flags (one for each option).
+ */
+#define	AF	0x00000001
+#define	BF	0x00000002
+#define	CF	0x00000004
+#define	DF	0x00000008
+#define	FF	0x00000010
+#define	IF	0x00000020
+#define	KF	0x00000040
+#define	LF	0x00000080
+#define	NF	0x00000100
+#define	OF	0x00000200
+#define	PF	0x00000400
+#define	RF	0x00000800
+#define	SF	0x00001000
+#define	TF	0x00002000
+#define	UF	0x00004000
+#define	VF	0x00008000
+#define	WF	0x00010000
+#define	XF	0x00020000
+#define	CBF	0x00040000	/* nonstandard extension */
+#define	CDF	0x00080000	/* nonstandard extension */
+#define	CEF	0x00100000	/* nonstandard extension */
+#define	CGF	0x00200000	/* nonstandard extension */
+#define	CHF	0x00400000	/* nonstandard extension */
+#define	CLF	0x00800000	/* nonstandard extension */
+#define	CPF	0x01000000	/* nonstandard extension */
+#define	CTF	0x02000000	/* nonstandard extension */
+#define	CUF	0x04000000	/* nonstandard extension */
+#define	CXF	0x08000000
+#define	CYF	0x10000000	/* nonstandard extension */
+#define	CZF	0x20000000	/* nonstandard extension */
+
+/*
+ * ascii string indexed by bit position above (alter the above and you must
+ * alter this string) used to tell the user what flags caused us to complain
+ */
+#define FLGCH	"abcdfiklnoprstuvwxBDEGHLPTUXYZ"
+
+/*
+ * legal pax operation bit patterns
+ */
+
+#define ISLIST(x)	(((x) & (RF|WF)) == 0)
+#define	ISEXTRACT(x)	(((x) & (RF|WF)) == RF)
+#define ISARCHIVE(x)	(((x) & (AF|RF|WF)) == WF)
+#define ISAPPND(x)	(((x) & (AF|RF|WF)) == (AF|WF))
+#define	ISCOPY(x)	(((x) & (RF|WF)) == (RF|WF))
+#define	ISWRITE(x)	(((x) & (RF|WF)) == WF)
+
+/*
+ * Illegal option flag subsets based on pax operation
+ */
+
+#define	BDEXTR	(AF|BF|LF|TF|WF|XF|CBF|CHF|CLF|CPF|CXF)
+#define	BDARCH	(CF|KF|LF|NF|PF|RF|CDF|CEF|CYF|CZF)
+#define	BDCOPY	(AF|BF|FF|OF|XF|CBF|CEF)
+#define	BDLIST (AF|BF|IF|KF|LF|OF|PF|RF|TF|UF|WF|XF|CBF|CDF|CHF|CLF|CPF|CXF|CYF|CZF)
Index: /trunk/minix/commands/pax/pat_rep.c
===================================================================
--- /trunk/minix/commands/pax/pat_rep.c	(revision 9)
+++ /trunk/minix/commands/pax/pat_rep.c	(revision 9)
@@ -0,0 +1,1128 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)pat_rep.c	8.2 (Berkeley) 4/18/94";
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef NET2_REGEX
+#include <regexp.h>
+#else
+#include <regex.h>
+#endif
+#include "pax.h"
+#include "pat_rep.h"
+#include "extern.h"
+
+/*
+ * routines to handle pattern matching, name modification (regular expression
+ * substitution and interactive renames), and destination name modification for
+ * copy (-rw). Both file name and link names are adjusted as required in these
+ * routines.
+ */
+
+#define MAXSUBEXP	10		/* max subexpressions, DO NOT CHANGE */
+static PATTERN *pathead = NULL;		/* file pattern match list head */
+static PATTERN *pattail = NULL;		/* file pattern match list tail */
+static REPLACE *rephead = NULL;		/* replacement string list head */
+static REPLACE *reptail = NULL;		/* replacement string list tail */
+
+static int rep_name(char *, int *, int);
+static int tty_rename(ARCHD *);
+static int fix_path(char *, int *, char *, int);
+static int fn_match(char *, char *, char **);
+static char * range_match(char *, int);
+#ifdef NET2_REGEX
+static int resub(regexp *, char *, char *, char *);
+#else
+static int resub(regex_t *, regmatch_t *, char *, char *, char *);
+#endif
+
+/*
+ * rep_add()
+ *	parses the -s replacement string; compiles the regular expression
+ *	and stores the compiled value and it's replacement string together in
+ *	replacement string list. Input to this function is of the form:
+ *		/old/new/pg
+ *	The first char in the string specifies the delimiter used by this
+ *	replacement string. "Old" is a regular expression in "ed" format which
+ *	is compiled by regcomp() and is applied to filenames. "new" is the
+ *	substitution string; p and g are options flags for printing and global
+ *	replacement (over the single filename)
+ * Return:
+ *	0 if a proper replacement string and regular expression was added to
+ *	the list of replacement patterns; -1 otherwise.
+ */
+
+int
+rep_add(char *str)
+{
+	char *pt1;
+	char *pt2;
+	REPLACE *rep;
+#	ifndef NET2_REGEX
+	int res;
+	char rebuf[BUFSIZ];
+#	endif
+
+	/*
+	 * throw out the bad parameters
+	 */
+	if ((str == NULL) || (*str == '\0')) {
+		paxwarn(1, "Empty replacement string");
+		return(-1);
+	}
+
+	/*
+	 * first character in the string specifies what the delimiter is for
+	 * this expression
+	 */
+	if ((pt1 = strchr(str+1, *str)) == NULL) {
+		paxwarn(1, "Invalid replacement string %s", str);
+		return(-1);
+	}
+
+	/*
+	 * allocate space for the node that handles this replacement pattern
+	 * and split out the regular expression and try to compile it
+	 */
+	if ((rep = (REPLACE *)malloc(sizeof(REPLACE))) == NULL) {
+		paxwarn(1, "Unable to allocate memory for replacement string");
+		return(-1);
+	}
+
+	*pt1 = '\0';
+#	ifdef NET2_REGEX
+	if ((rep->rcmp = regcomp(str+1)) == NULL) {
+#	else
+	if ((res = regcomp(&(rep->rcmp), str+1, 0)) != 0) {
+		regerror(res, &(rep->rcmp), rebuf, sizeof(rebuf));
+		paxwarn(1, "%s while compiling regular expression %s", rebuf, str);
+#	endif
+		(void)free((char *)rep);
+		return(-1);
+	}
+
+	/*
+	 * put the delimiter back in case we need an error message and
+	 * locate the delimiter at the end of the replacement string
+	 * we then point the node at the new substitution string
+	 */
+	*pt1++ = *str;
+	if ((pt2 = strchr(pt1, *str)) == NULL) {
+#		ifdef NET2_REGEX
+		(void)free((char *)rep->rcmp);
+#		else
+		regfree(&(rep->rcmp));
+#		endif
+		(void)free((char *)rep);
+		paxwarn(1, "Invalid replacement string %s", str);
+		return(-1);
+	}
+
+	*pt2 = '\0';
+	rep->nstr = pt1;
+	pt1 = pt2++;
+	rep->flgs = 0;
+
+	/*
+	 * set the options if any
+	 */
+	while (*pt2 != '\0') {
+		switch(*pt2) {
+		case 'g':
+		case 'G':
+			rep->flgs  |= GLOB;
+			break;
+		case 'p':
+		case 'P':
+			rep->flgs  |= PRNT;
+			break;
+		default:
+#			ifdef NET2_REGEX
+			(void)free((char *)rep->rcmp);
+#			else
+			regfree(&(rep->rcmp));
+#			endif
+			(void)free((char *)rep);
+			*pt1 = *str;
+			paxwarn(1, "Invalid replacement string option %s", str);
+			return(-1);
+		}
+		++pt2;
+	}
+
+	/*
+	 * all done, link it in at the end
+	 */
+	rep->fow = NULL;
+	if (rephead == NULL) {
+		reptail = rephead = rep;
+		return(0);
+	}
+	reptail->fow = rep;
+	reptail = rep;
+	return(0);
+}
+
+/*
+ * pat_add()
+ *	add a pattern match to the pattern match list. Pattern matches are used
+ *	to select which archive members are extracted. (They appear as
+ *	arguments to pax in the list and read modes). If no patterns are
+ *	supplied to pax, all members in the archive will be selected (and the
+ *	pattern match list is empty).
+ * Return:
+ *	0 if the pattern was added to the list, -1 otherwise
+ */
+
+int
+pat_add(char *str, char *chdnam)
+{
+	PATTERN *pt;
+
+	/*
+	 * throw out the junk
+	 */
+	if ((str == NULL) || (*str == '\0')) {
+		paxwarn(1, "Empty pattern string");
+		return(-1);
+	}
+
+	/*
+	 * allocate space for the pattern and store the pattern. the pattern is
+	 * part of argv so do not bother to copy it, just point at it. Add the
+	 * node to the end of the pattern list
+	 */
+	if ((pt = (PATTERN *)malloc(sizeof(PATTERN))) == NULL) {
+		paxwarn(1, "Unable to allocate memory for pattern string");
+		return(-1);
+	}
+
+	pt->pstr = str;
+	pt->pend = NULL;
+	pt->plen = strlen(str);
+	pt->fow = NULL;
+	pt->flgs = 0;
+	pt->chdname = chdnam;
+
+	if (pathead == NULL) {
+		pattail = pathead = pt;
+		return(0);
+	}
+	pattail->fow = pt;
+	pattail = pt;
+	return(0);
+}
+
+/*
+ * pat_chk()
+ *	complain if any the user supplied pattern did not result in a match to
+ *	a selected archive member.
+ */
+
+void
+pat_chk(void)
+{
+	PATTERN *pt;
+	int wban = 0;
+
+	/*
+	 * walk down the list checking the flags to make sure MTCH was set,
+	 * if not complain
+	 */
+	for (pt = pathead; pt != NULL; pt = pt->fow) {
+		if (pt->flgs & MTCH)
+			continue;
+		if (!wban) {
+			paxwarn(1, "WARNING! These patterns were not matched:");
+			++wban;
+		}
+		(void)fprintf(stderr, "%s\n", pt->pstr);
+	}
+}
+
+/*
+ * pat_sel()
+ *	the archive member which matches a pattern was selected. Mark the
+ *	pattern as having selected an archive member. arcn->pat points at the
+ *	pattern that was matched. arcn->pat is set in pat_match()
+ *
+ *	NOTE: When the -c option is used, we are called when there was no match
+ *	by pat_match() (that means we did match before the inverted sense of
+ *	the logic). Now this seems really strange at first, but with -c  we
+ *	need to keep track of those patterns that cause an archive member to NOT
+ *	be selected (it found an archive member with a specified pattern)
+ * Return:
+ *	0 if the pattern pointed at by arcn->pat was tagged as creating a
+ *	match, -1 otherwise.
+ */
+
+int
+pat_sel(ARCHD *arcn)
+{
+	PATTERN *pt;
+	PATTERN **ppt;
+	int len;
+
+	/*
+	 * if no patterns just return
+	 */
+	if ((pathead == NULL) || ((pt = arcn->pat) == NULL))
+		return(0);
+
+	/*
+	 * when we are NOT limited to a single match per pattern mark the
+	 * pattern and return
+	 */
+	if (!nflag) {
+		pt->flgs |= MTCH;
+		return(0);
+	}
+
+	/*
+	 * we reach this point only when we allow a single selected match per
+	 * pattern, if the pattern matches a directory and we do not have -d
+	 * (dflag) we are done with this pattern. We may also be handed a file
+	 * in the subtree of a directory. in that case when we are operating
+	 * with -d, this pattern was already selected and we are done
+	 */
+	if (pt->flgs & DIR_MTCH)
+		return(0);
+
+	if (!dflag && ((pt->pend != NULL) || (arcn->type == PAX_DIR))) {
+		/*
+		 * ok we matched a directory and we are allowing
+		 * subtree matches but because of the -n only its children will
+		 * match. This is tagged as a DIR_MTCH type.
+		 * WATCH IT, the code assumes that pt->pend points
+		 * into arcn->name and arcn->name has not been modified.
+		 * If not we will have a big mess. Yup this is another kludge
+		 */
+
+		/*
+		 * if this was a prefix match, remove trailing part of path
+		 * so we can copy it. Future matches will be exact prefix match
+		 */
+		if (pt->pend != NULL)
+			*pt->pend = '\0';
+
+		if ((pt->pstr = strdup(arcn->name)) == NULL) {
+			paxwarn(1, "Pattern select out of memory");
+			if (pt->pend != NULL)
+				*pt->pend = '/';
+			pt->pend = NULL;
+			return(-1);
+		}
+
+		/*
+		 * put the trailing / back in the source string
+		 */
+		if (pt->pend != NULL) {
+			*pt->pend = '/';
+			pt->pend = NULL;
+		}
+		pt->plen = strlen(pt->pstr);
+
+		/*
+		 * strip off any trailing /, this should really never happen
+		 */
+		len = pt->plen - 1;
+		if (*(pt->pstr + len) == '/') {
+			*(pt->pstr + len) = '\0';
+			pt->plen = len;
+		}
+		pt->flgs = DIR_MTCH | MTCH;
+		arcn->pat = pt;
+		return(0);
+	}
+
+	/*
+	 * we are then done with this pattern, so we delete it from the list
+	 * because it can never be used for another match.
+	 * Seems kind of strange to do for a -c, but the pax spec is really
+	 * vague on the interaction of -c -n and -d. We assume that when -c
+	 * and the pattern rejects a member (i.e. it matched it) it is done.
+	 * In effect we place the order of the flags as having -c last.
+	 */
+	pt = pathead;
+	ppt = &pathead;
+	while ((pt != NULL) && (pt != arcn->pat)) {
+		ppt = &(pt->fow);
+		pt = pt->fow;
+	}
+
+	if (pt == NULL) {
+		/*
+		 * should never happen....
+		 */
+		paxwarn(1, "Pattern list inconsistant");
+		return(-1);
+	}
+	*ppt = pt->fow;
+	(void)free((char *)pt);
+	arcn->pat = NULL;
+	return(0);
+}
+
+/*
+ * pat_match()
+ *	see if this archive member matches any supplied pattern, if a match
+ *	is found, arcn->pat is set to point at the potential pattern. Later if
+ *	this archive member is "selected" we process and mark the pattern as
+ *	one which matched a selected archive member (see pat_sel())
+ * Return:
+ *	0 if this archive member should be processed, 1 if it should be
+ *	skipped and -1 if we are done with all patterns (and pax should quit
+ *	looking for more members)
+ */
+
+int
+pat_match(ARCHD *arcn)
+{
+	PATTERN *pt;
+
+	arcn->pat = NULL;
+
+	/*
+	 * if there are no more patterns and we have -n (and not -c) we are
+	 * done. otherwise with no patterns to match, matches all
+	 */
+	if (pathead == NULL) {
+		if (nflag && !cflag)
+			return(-1);
+		return(0);
+	}
+
+	/*
+	 * have to search down the list one at a time looking for a match.
+	 */
+	pt = pathead;
+	while (pt != NULL) {
+		/*
+		 * check for a file name match unless we have DIR_MTCH set in
+		 * this pattern then we want a prefix match
+		 */
+		if (pt->flgs & DIR_MTCH) {
+			/*
+			 * this pattern was matched before to a directory
+			 * as we must have -n set for this (but not -d). We can
+			 * only match CHILDREN of that directory so we must use
+			 * an exact prefix match (no wildcards).
+			 */
+			if ((arcn->name[pt->plen] == '/') &&
+			    (strncmp(pt->pstr, arcn->name, pt->plen) == 0))
+				break;
+		} else if (fn_match(pt->pstr, arcn->name, &pt->pend) == 0)
+			break;
+		pt = pt->fow;
+	}
+
+	/*
+	 * return the result, remember that cflag (-c) inverts the sense of a
+	 * match
+	 */
+	if (pt == NULL)
+		return(cflag ? 0 : 1);
+
+	/*
+	 * We had a match, now when we invert the sense (-c) we reject this
+	 * member. However we have to tag the pattern a being successful, (in a
+	 * match, not in selecting an archive member) so we call pat_sel() here.
+	 */
+	arcn->pat = pt;
+	if (!cflag)
+		return(0);
+
+	if (pat_sel(arcn) < 0)
+		return(-1);
+	arcn->pat = NULL;
+	return(1);
+}
+
+/*
+ * fn_match()
+ * Return:
+ *	0 if this archive member should be processed, 1 if it should be
+ *	skipped and -1 if we are done with all patterns (and pax should quit
+ *	looking for more members)
+ *	Note: *pend may be changed to show where the prefix ends.
+ */
+
+static int
+fn_match(char *pattern, char *string, char **pend)
+{
+	char c;
+	char test;
+
+	*pend = NULL;
+	for (;;) {
+		switch (c = *pattern++) {
+		case '\0':
+			/*
+			 * Ok we found an exact match
+			 */
+			if (*string == '\0')
+				return(0);
+
+			/*
+			 * Check if it is a prefix match
+			 */
+			if ((dflag == 1) || (*string != '/'))
+				return(-1);
+
+			/*
+			 * It is a prefix match, remember where the trailing
+			 * / is located
+			 */
+			*pend = string;
+			return(0);
+		case '?':
+			if ((test = *string++) == '\0')
+				return (-1);
+			break;
+		case '*':
+			c = *pattern;
+			/*
+			 * Collapse multiple *'s.
+			 */
+			while (c == '*')
+				c = *++pattern;
+
+			/*
+			 * Optimized hack for pattern with a * at the end
+			 */
+			if (c == '\0')
+				return (0);
+
+			/*
+			 * General case, use recursion.
+			 */
+			while ((test = *string) != '\0') {
+				if (!fn_match(pattern, string, pend))
+					return (0);
+				++string;
+			}
+			return (-1);
+		case '[':
+			/*
+			 * range match
+			 */
+			if (((test = *string++) == '\0') ||
+			    ((pattern = range_match(pattern, test)) == NULL))
+				return (-1);
+			break;
+		case '\\':
+		default:
+			if (c != *string++)
+				return (-1);
+			break;
+		}
+	}
+	/* NOTREACHED */
+}
+
+static char *
+range_match(char *pattern, int test)
+{
+	char c;
+	char c2;
+	int negate;
+	int ok = 0;
+
+	if ((negate = (*pattern == '!')) != 0)
+		++pattern;
+
+	while ((c = *pattern++) != ']') {
+		/*
+		 * Illegal pattern
+		 */
+		if (c == '\0')
+			return (NULL);
+
+		if ((*pattern == '-') && ((c2 = pattern[1]) != '\0') &&
+		    (c2 != ']')) {
+			if ((c <= test) && (test <= c2))
+				ok = 1;
+			pattern += 2;
+		} else if (c == test)
+			ok = 1;
+	}
+	return (ok == negate ? NULL : pattern);
+}
+
+/*
+ * mod_name()
+ *	modify a selected file name. first attempt to apply replacement string
+ *	expressions, then apply interactive file rename. We apply replacement
+ *	string expressions to both filenames and file links (if we didn't the
+ *	links would point to the wrong place, and we could never be able to
+ *	move an archive that has a file link in it). When we rename files
+ *	interactively, we store that mapping (old name to user input name) so
+ *	if we spot any file links to the old file name in the future, we will
+ *	know exactly how to fix the file link.
+ * Return:
+ *	0 continue to  process file, 1 skip this file, -1 pax is finished
+ */
+
+int
+mod_name(ARCHD *arcn)
+{
+	int res = 0;
+
+	/*
+	 * Strip off leading '/' if appropriate.
+	 * Currently, this option is only set for the tar format.
+	 */
+	if (rmleadslash && arcn->name[0] == '/') {
+		if (arcn->name[1] == '\0') {
+			arcn->name[0] = '.';
+		} else {
+			(void)memmove(arcn->name, &arcn->name[1],
+			    strlen(arcn->name));
+			arcn->nlen--;
+		}
+		if (rmleadslash < 2) {
+			rmleadslash = 2;
+			paxwarn(0, "Removing leading / from absolute path names in the archive");
+		}
+	}
+	if (rmleadslash && arcn->ln_name[0] == '/' &&
+	    (arcn->type == PAX_HLK || arcn->type == PAX_HRG)) {
+		if (arcn->ln_name[1] == '\0') {
+			arcn->ln_name[0] = '.';
+		} else {
+			(void)memmove(arcn->ln_name, &arcn->ln_name[1],
+			    strlen(arcn->ln_name));
+			arcn->ln_nlen--;
+		}
+		if (rmleadslash < 2) {
+			rmleadslash = 2;
+			paxwarn(0, "Removing leading / from absolute path names in the archive");
+		}
+	}
+
+	/*
+	 * IMPORTANT: We have a problem. what do we do with symlinks?
+	 * Modifying a hard link name makes sense, as we know the file it
+	 * points at should have been seen already in the archive (and if it
+	 * wasn't seen because of a read error or a bad archive, we lose
+	 * anyway). But there are no such requirements for symlinks. On one
+	 * hand the symlink that refers to a file in the archive will have to
+	 * be modified to so it will still work at its new location in the
+	 * file system. On the other hand a symlink that points elsewhere (and
+	 * should continue to do so) should not be modified. There is clearly
+	 * no perfect solution here. So we handle them like hardlinks. Clearly
+	 * a replacement made by the interactive rename mapping is very likely
+	 * to be correct since it applies to a single file and is an exact
+	 * match. The regular expression replacements are a little harder to
+	 * justify though. We claim that the symlink name is only likely
+	 * to be replaced when it points within the file tree being moved and
+	 * in that case it should be modified. what we really need to do is to
+	 * call an oracle here. :)
+	 */
+	if (rephead != NULL) {
+		/*
+		 * we have replacement strings, modify the name and the link
+		 * name if any.
+		 */
+		if ((res = rep_name(arcn->name, &(arcn->nlen), 1)) != 0)
+			return(res);
+
+		if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
+		    (arcn->type == PAX_HRG)) &&
+		    ((res = rep_name(arcn->ln_name, &(arcn->ln_nlen), 0)) != 0))
+			return(res);
+	}
+
+	if (iflag) {
+		/*
+		 * perform interactive file rename, then map the link if any
+		 */
+		if ((res = tty_rename(arcn)) != 0)
+			return(res);
+		if ((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
+		    (arcn->type == PAX_HRG))
+			sub_name(arcn->ln_name, &(arcn->ln_nlen), sizeof(arcn->ln_name));
+	}
+	return(res);
+}
+
+/*
+ * tty_rename()
+ *	Prompt the user for a replacement file name. A "." keeps the old name,
+ *	a empty line skips the file, and an EOF on reading the tty, will cause
+ *	pax to stop processing and exit. Otherwise the file name input, replaces
+ *	the old one.
+ * Return:
+ *	0 process this file, 1 skip this file, -1 we need to exit pax
+ */
+
+static int
+tty_rename(ARCHD *arcn)
+{
+	char tmpname[PAXPATHLEN+2];
+	int res;
+
+	/*
+	 * prompt user for the replacement name for a file, keep trying until
+	 * we get some reasonable input. Archives may have more than one file
+	 * on them with the same name (from updates etc). We print verbose info
+	 * on the file so the user knows what is up.
+	 */
+	tty_prnt("\nATTENTION: %s interactive file rename operation.\n", argv0);
+
+	for (;;) {
+		ls_tty(arcn);
+		tty_prnt("Input new name, or a \".\" to keep the old name, ");
+		tty_prnt("or a \"return\" to skip this file.\n");
+		tty_prnt("Input > ");
+		if (tty_read(tmpname, sizeof(tmpname)) < 0)
+			return(-1);
+		if (strcmp(tmpname, "..") == 0) {
+			tty_prnt("Try again, illegal file name: ..\n");
+			continue;
+		}
+		if (strlen(tmpname) > PAXPATHLEN) {
+			tty_prnt("Try again, file name too long\n");
+			continue;
+		}
+		break;
+	}
+
+	/*
+	 * empty file name, skips this file. a "." leaves it alone
+	 */
+	if (tmpname[0] == '\0') {
+		tty_prnt("Skipping file.\n");
+		return(1);
+	}
+	if ((tmpname[0] == '.') && (tmpname[1] == '\0')) {
+		tty_prnt("Processing continues, name unchanged.\n");
+		return(0);
+	}
+
+	/*
+	 * ok the name changed. We may run into links that point at this
+	 * file later. we have to remember where the user sent the file
+	 * in order to repair any links.
+	 */
+	tty_prnt("Processing continues, name changed to: %s\n", tmpname);
+	res = add_name(arcn->name, arcn->nlen, tmpname);
+	arcn->nlen = l_strncpy(arcn->name, tmpname, sizeof(arcn->name) - 1);
+	arcn->name[arcn->nlen] = '\0';
+	if (res < 0)
+		return(-1);
+	return(0);
+}
+
+/*
+ * set_dest()
+ *	fix up the file name and the link name (if any) so this file will land
+ *	in the destination directory (used during copy() -rw).
+ * Return:
+ *	0 if ok, -1 if failure (name too long)
+ */
+
+int
+set_dest(ARCHD *arcn, char *dest_dir, int dir_len)
+{
+	if (fix_path(arcn->name, &(arcn->nlen), dest_dir, dir_len) < 0)
+		return(-1);
+
+	/*
+	 * It is really hard to deal with symlinks here, we cannot be sure
+	 * if the name they point was moved (or will be moved). It is best to
+	 * leave them alone.
+	 */
+	if ((arcn->type != PAX_HLK) && (arcn->type != PAX_HRG))
+		return(0);
+
+	if (fix_path(arcn->ln_name, &(arcn->ln_nlen), dest_dir, dir_len) < 0)
+		return(-1);
+	return(0);
+}
+
+/*
+ * fix_path
+ *	concatenate dir_name and or_name and store the result in or_name (if
+ *	it fits). This is one ugly function.
+ * Return:
+ *	0 if ok, -1 if the final name is too long
+ */
+
+static int
+fix_path( char *or_name, int *or_len, char *dir_name, int dir_len)
+{
+	char *src;
+	char *dest;
+	char *start;
+	int len;
+
+	/*
+	 * we shift the or_name to the right enough to tack in the dir_name
+	 * at the front. We make sure we have enough space for it all before
+	 * we start. since dest always ends in a slash, we skip of or_name
+	 * if it also starts with one.
+	 */
+	start = or_name;
+	src = start + *or_len;
+	dest = src + dir_len;
+	if (*start == '/') {
+		++start;
+		--dest;
+	}
+	if ((len = dest - or_name) > PAXPATHLEN) {
+		paxwarn(1, "File name %s/%s, too long", dir_name, start);
+		return(-1);
+	}
+	*or_len = len;
+
+	/*
+	 * enough space, shift
+	 */
+	while (src >= start)
+		*dest-- = *src--;
+	src = dir_name + dir_len - 1;
+
+	/*
+	 * splice in the destination directory name
+	 */
+	while (src >= dir_name)
+		*dest-- = *src--;
+
+	*(or_name + len) = '\0';
+	return(0);
+}
+
+/*
+ * rep_name()
+ *	walk down the list of replacement strings applying each one in order.
+ *	when we find one with a successful substitution, we modify the name
+ *	as specified. if required, we print the results. if the resulting name
+ *	is empty, we will skip this archive member. We use the regexp(3)
+ *	routines (regexp() ought to win a prize as having the most cryptic
+ *	library function manual page).
+ *	--Parameters--
+ *	name is the file name we are going to apply the regular expressions to
+ *	(and may be modified)
+ *	nlen is the length of this name (and is modified to hold the length of
+ *	the final string).
+ *	prnt is a flag that says whether to print the final result.
+ * Return:
+ *	0 if substitution was successful, 1 if we are to skip the file (the name
+ *	ended up empty)
+ */
+
+static int
+rep_name(char *name, int *nlen, int prnt)
+{
+	REPLACE *pt;
+	char *inpt;
+	char *outpt;
+	char *endpt;
+	char *rpt;
+	int found = 0;
+	int res;
+#	ifndef NET2_REGEX
+	regmatch_t pm[MAXSUBEXP];
+#	endif
+	char nname[PAXPATHLEN+1];	/* final result of all replacements */
+	char buf1[PAXPATHLEN+1];	/* where we work on the name */
+
+	/*
+	 * copy the name into buf1, where we will work on it. We need to keep
+	 * the orig string around so we can print out the result of the final
+	 * replacement. We build up the final result in nname. inpt points at
+	 * the string we apply the regular expression to. prnt is used to
+	 * suppress printing when we handle replacements on the link field
+	 * (the user already saw that substitution go by)
+	 */
+	pt = rephead;
+	(void)strcpy(buf1, name);
+	inpt = buf1;
+	outpt = nname;
+	endpt = outpt + PAXPATHLEN;
+
+	/*
+	 * try each replacement string in order
+	 */
+	while (pt != NULL) {
+		do {
+			/*
+			 * check for a successful substitution, if not go to
+			 * the next pattern, or cleanup if we were global
+			 */
+#			ifdef NET2_REGEX
+			if (regexec(pt->rcmp, inpt) == 0)
+#			else
+			if (regexec(&(pt->rcmp), inpt, MAXSUBEXP, pm, 0) != 0)
+#			endif
+				break;
+
+			/*
+			 * ok we found one. We have three parts, the prefix
+			 * which did not match, the section that did and the
+			 * tail (that also did not match). Copy the prefix to
+			 * the final output buffer (watching to make sure we
+			 * do not create a string too long).
+			 */
+			found = 1;
+#			ifdef NET2_REGEX
+			rpt = pt->rcmp->startp[0];
+#			else
+			rpt = inpt + pm[0].rm_so;
+#			endif
+
+			while ((inpt < rpt) && (outpt < endpt))
+				*outpt++ = *inpt++;
+			if (outpt == endpt)
+				break;
+
+			/*
+			 * for the second part (which matched the regular
+			 * expression) apply the substitution using the
+			 * replacement string and place it the prefix in the
+			 * final output. If we have problems, skip it.
+			 */
+#			ifdef NET2_REGEX
+			if ((res = resub(pt->rcmp,pt->nstr,outpt,endpt)) < 0) {
+#			else
+			if ((res = resub(&(pt->rcmp),pm,pt->nstr,outpt,endpt))
+			    < 0) {
+#			endif
+				if (prnt)
+					paxwarn(1, "Replacement name error %s",
+					    name);
+				return(1);
+			}
+			outpt += res;
+
+			/*
+			 * we set up to look again starting at the first
+			 * character in the tail (of the input string right
+			 * after the last character matched by the regular
+			 * expression (inpt always points at the first char in
+			 * the string to process). If we are not doing a global
+			 * substitution, we will use inpt to copy the tail to
+			 * the final result. Make sure we do not overrun the
+			 * output buffer
+			 */
+#			ifdef NET2_REGEX
+			inpt = pt->rcmp->endp[0];
+#			else
+			inpt += pm[0].rm_eo - pm[0].rm_so;
+#			endif
+
+			if ((outpt == endpt) || (*inpt == '\0'))
+				break;
+
+			/*
+			 * if the user wants global we keep trying to
+			 * substitute until it fails, then we are done.
+			 */
+		} while (pt->flgs & GLOB);
+
+		if (found)
+			break;
+
+		/*
+		 * a successful substitution did NOT occur, try the next one
+		 */
+		pt = pt->fow;
+	}
+
+	if (found) {
+		/*
+		 * we had a substitution, copy the last tail piece (if there is
+		 * room) to the final result
+		 */
+		while ((outpt < endpt) && (*inpt != '\0'))
+			*outpt++ = *inpt++;
+
+		*outpt = '\0';
+		if ((outpt == endpt) && (*inpt != '\0')) {
+			if (prnt)
+				paxwarn(1,"Replacement name too long %s >> %s",
+				    name, nname);
+			return(1);
+		}
+
+		/*
+		 * inform the user of the result if wanted
+		 */
+		if (prnt && (pt->flgs & PRNT)) {
+			if (*nname == '\0')
+				(void)fprintf(stderr,"%s >> <empty string>\n",
+				    name);
+			else
+				(void)fprintf(stderr,"%s >> %s\n", name, nname);
+		}
+
+		/*
+		 * if empty inform the caller this file is to be skipped
+		 * otherwise copy the new name over the orig name and return
+		 */
+		if (*nname == '\0')
+			return(1);
+		*nlen = l_strncpy(name, nname, PAXPATHLEN + 1);
+		name[PAXPATHLEN] = '\0';
+	}
+	return(0);
+}
+
+#ifdef NET2_REGEX
+/*
+ * resub()
+ *	apply the replacement to the matched expression. expand out the old
+ * 	style ed(1) subexpression expansion.
+ * Return:
+ *	-1 if error, or the number of characters added to the destination.
+ */
+
+static int
+resub(regexp *prog, char *src, char *dest, char *destend)
+{
+	char *spt;
+	char *dpt;
+	char c;
+	int no;
+	int len;
+
+	spt = src;
+	dpt = dest;
+	while ((dpt < destend) && ((c = *spt++) != '\0')) {
+		if (c == '&')
+			no = 0;
+		else if ((c == '\\') && (*spt >= '0') && (*spt <= '9'))
+			no = *spt++ - '0';
+		else {
+ 			if ((c == '\\') && ((*spt == '\\') || (*spt == '&')))
+ 				c = *spt++;
+ 			*dpt++ = c;
+			continue;
+		}
+ 		if ((prog->startp[no] == NULL) || (prog->endp[no] == NULL) ||
+		    ((len = prog->endp[no] - prog->startp[no]) <= 0))
+			continue;
+
+		/*
+		 * copy the subexpression to the destination.
+		 * fail if we run out of space or the match string is damaged
+		 */
+		if (len > (destend - dpt))
+			len = destend - dpt;
+		if (l_strncpy(dpt, prog->startp[no], len) != len)
+			return(-1);
+		dpt += len;
+	}
+	return(dpt - dest);
+}
+
+#else
+
+/*
+ * resub()
+ *	apply the replacement to the matched expression. expand out the old
+ * 	style ed(1) subexpression expansion.
+ * Return:
+ *	-1 if error, or the number of characters added to the destination.
+ */
+
+static int
+resub(regex_t *rp, regmatch_t *pm, char *src, char *dest,
+	char *destend)
+{
+	char *spt;
+	char *dpt;
+	char c;
+	regmatch_t *pmpt;
+	int len;
+	int subexcnt;
+
+	spt =  src;
+	dpt = dest;
+	subexcnt = rp->re_nsub;
+	while ((dpt < destend) && ((c = *spt++) != '\0')) {
+		/*
+		 * see if we just have an ordinary replacement character
+		 * or we refer to a subexpression.
+		 */
+		if (c == '&') {
+			pmpt = pm;
+		} else if ((c == '\\') && (*spt >= '0') && (*spt <= '9')) {
+			/*
+			 * make sure there is a subexpression as specified
+			 */
+			if ((len = *spt++ - '0') > subexcnt)
+				return(-1);
+			pmpt = pm + len;
+		} else {
+ 			/*
+			 * Ordinary character, just copy it
+			 */
+ 			if ((c == '\\') && ((*spt == '\\') || (*spt == '&')))
+ 				c = *spt++;
+ 			*dpt++ = c;
+			continue;
+		}
+
+		/*
+		 * continue if the subexpression is bogus
+		 */
+		if ((pmpt->rm_so < 0) || (pmpt->rm_eo < 0) ||
+		    ((len = pmpt->rm_eo - pmpt->rm_so) <= 0))
+			continue;
+
+		/*
+		 * copy the subexpression to the destination.
+		 * fail if we run out of space or the match string is damaged
+		 */
+		if (len > (destend - dpt))
+			len = destend - dpt;
+		if (l_strncpy(dpt, src + pmpt->rm_so, len) != len)
+			return(-1);
+		dpt += len;
+	}
+	return(dpt - dest);
+}
+#endif
Index: /trunk/minix/commands/pax/pat_rep.h
===================================================================
--- /trunk/minix/commands/pax/pat_rep.h	(revision 9)
+++ /trunk/minix/commands/pax/pat_rep.h	(revision 9)
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)pat_rep.h	8.1 (Berkeley) 5/31/93
+ * $FreeBSD: src/bin/pax/pat_rep.h,v 1.6 2004/04/06 20:06:48 markm Exp $
+ */
+
+/*
+ * data structure for storing user supplied replacement strings (-s)
+ */
+typedef struct replace {
+	char		*nstr;	/* the new string we will substitute with */
+#	ifdef NET2_REGEX
+	regexp		*rcmp;	/* compiled regular expression used to match */
+#	else
+	regex_t		rcmp;	/* compiled regular expression used to match */
+#	endif
+	int		flgs;	/* print conversions? global in operation?  */
+#define	PRNT		0x1
+#define	GLOB		0x2
+	struct replace	*fow;	/* pointer to next pattern */
+} REPLACE;
Index: /trunk/minix/commands/pax/pax.c
===================================================================
--- /trunk/minix/commands/pax/pax.c	(revision 9)
+++ /trunk/minix/commands/pax/pax.c	(revision 9)
@@ -0,0 +1,439 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char const copyright[] =
+"@(#) Copyright (c) 1992, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)pax.c	8.2 (Berkeley) 4/18/94";
+#endif /* not lint */
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <minix/paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "pax.h"
+#include "extern.h"
+static int gen_init(void);
+
+/*
+ * PAX main routines, general globals and some simple start up routines
+ */
+
+/*
+ * Variables that can be accessed by any routine within pax
+ */
+int	act = DEFOP;		/* read/write/append/copy */
+FSUB	*frmt = NULL;		/* archive format type */
+int	cflag;			/* match all EXCEPT pattern/file */
+int	cwdfd;			/* starting cwd */
+int	dflag;			/* directory member match only  */
+int	iflag;			/* interactive file/archive rename */
+int	kflag;			/* do not overwrite existing files */
+int	lflag;			/* use hard links when possible */
+int	nflag;			/* select first archive member match */
+int	tflag;			/* restore access time after read */
+int	uflag;			/* ignore older modification time files */
+int	vflag;			/* produce verbose output */
+int	Dflag;			/* same as uflag except inode change time */
+int	Hflag;			/* follow command line symlinks (write only) */
+int	Lflag;			/* follow symlinks when writing */
+int	Xflag;			/* archive files with same device id only */
+int	Yflag;			/* same as Dflg except after name mode */
+int	Zflag;			/* same as uflg except after name mode */
+int	vfpart;			/* is partial verbose output in progress */
+int	patime = 1;		/* preserve file access time */
+int	pmtime = 1;		/* preserve file modification times */
+int	nodirs;			/* do not create directories as needed */
+int	pmode;			/* preserve file mode bits */
+int	pids;			/* preserve file uid/gid */
+int	rmleadslash = 0;	/* remove leading '/' from pathnames */
+int	exit_val;		/* exit value */
+int	docrc;			/* check/create file crc */
+char	*dirptr;		/* destination dir in a copy */
+const	char *argv0;		/* root of argv[0] */
+sigset_t s_mask;		/* signal mask for cleanup critical sect */
+FILE	*listf;			/* file pointer to print file list to */
+char	*tempfile;		/* tempfile to use for mkstemp(3) */
+char	*tempbase;		/* basename of tempfile to use for mkstemp(3) */
+
+/*
+ *	PAX - Portable Archive Interchange
+ *
+ * 	A utility to read, write, and write lists of the members of archive
+ *	files and copy directory hierarchies. A variety of archive formats
+ *	are supported (some are described in POSIX 1003.1 10.1):
+ *
+ *		ustar - 10.1.1 extended tar interchange format
+ *		cpio  - 10.1.2 extended cpio interchange format
+ *		tar - old BSD 4.3 tar format
+ *		binary cpio - old cpio with binary header format
+ *		sysVR4 cpio -  with and without CRC
+ *
+ * This version is a superset of IEEE Std 1003.2b-d3
+ *
+ * Summary of Extensions to the IEEE Standard:
+ *
+ * 1	READ ENHANCEMENTS
+ * 1.1	Operations which read archives will continue to operate even when
+ *	processing archives which may be damaged, truncated, or fail to meet
+ *	format specs in several different ways. Damaged sections of archives
+ *	are detected and avoided if possible. Attempts will be made to resync
+ *	archive read operations even with badly damaged media.
+ * 1.2	Blocksize requirements are not strictly enforced on archive read.
+ *	Tapes which have variable sized records can be read without errors.
+ * 1.3	The user can specify via the non-standard option flag -E if error
+ *	resync operation should stop on a media error, try a specified number
+ *	of times to correct, or try to correct forever.
+ * 1.4	Sparse files (lseek holes) stored on the archive (but stored with blocks
+ *	of all zeros will be restored with holes appropriate for the target
+ *	file system
+ * 1.5	The user is notified whenever something is found during archive
+ *	read operations which violates spec (but the read will continue).
+ * 1.6	Multiple archive volumes can be read and may span over different
+ *	archive devices
+ * 1.7	Rigidly restores all file attributes exactly as they are stored on the
+ *	archive.
+ * 1.8	Modification change time ranges can be specified via multiple -T
+ *	options. These allow a user to select files whose modification time
+ *	lies within a specific time range.
+ * 1.9	Files can be selected based on owner (user name or uid) via one or more
+ *	-U options.
+ * 1.10	Files can be selected based on group (group name or gid) via one o
+ *	more -G options.
+ * 1.11	File modification time can be checked against existing file after
+ *	name modification (-Z)
+ *
+ * 2	WRITE ENHANCEMENTS
+ * 2.1	Write operation will stop instead of allowing a user to create a flawed
+ *	flawed archive (due to any problem).
+ * 2.2	Archives written by pax are forced to strictly conform to both the
+ *	archive and pax the specific format specifications.
+ * 2.3	Blocking size and format is rigidly enforced on writes.
+ * 2.4	Formats which may exhibit header overflow problems (they have fields
+ *	too small for large file systems, such as inode number storage), use
+ *	routines designed to repair this problem. These techniques still
+ *	conform to both pax and format specifications, but no longer truncate
+ *	these fields. This removes any restrictions on using these archive
+ *	formats on large file systems.
+ * 2.5	Multiple archive volumes can be written and may span over different
+ *	archive devices
+ * 2.6	A archive volume record limit allows the user to specify the number
+ *	of bytes stored on an archive volume. When reached the user is
+ *	prompted for the next archive volume. This is specified with the
+ *	non-standard -B flag. The limit is rounded up to the next blocksize.
+ * 2.7	All archive padding during write use zero filled sections. This makes
+ *	it much easier to pull data out of flawed archive during read
+ *	operations.
+ * 2.8	Access time reset with the -t applies to all file nodes (including
+ *	directories).
+ * 2.9	Symbolic links can be followed with -L (optional in the spec).
+ * 2.10	Modification or inode change time ranges can be specified via
+ *	multiple -T options. These allow a user to select files whose
+ *	modification or inode change time lies within a specific time range.
+ * 2.11	Files can be selected based on owner (user name or uid) via one or more
+ *	-U options.
+ * 2.12	Files can be selected based on group (group name or gid) via one o
+ *	more -G options.
+ * 2.13	Symlinks which appear on the command line can be followed (without
+ *	following other symlinks; -H flag)
+ *
+ * 3	COPY ENHANCEMENTS
+ * 3.1	Sparse files (lseek holes) can be copied without expanding the holes
+ *	into zero filled blocks. The file copy is created with holes which are
+ *	appropriate for the target file system
+ * 3.2	Access time as well as modification time on copied file trees can be
+ *	preserved with the appropriate -p options.
+ * 3.3	Access time reset with the -t applies to all file nodes (including
+ *	directories).
+ * 3.4	Symbolic links can be followed with -L (optional in the spec).
+ * 3.5	Modification or inode change time ranges can be specified via
+ *	multiple -T options. These allow a user to select files whose
+ *	modification or inode change time lies within a specific time range.
+ * 3.6	Files can be selected based on owner (user name or uid) via one or more
+ *	-U options.
+ * 3.7	Files can be selected based on group (group name or gid) via one o
+ *	more -G options.
+ * 3.8	Symlinks which appear on the command line can be followed (without
+ *	following other symlinks; -H flag)
+ * 3.9  File inode change time can be checked against existing file before
+ *	name modification (-D)
+ * 3.10 File inode change time can be checked against existing file after
+ *	name modification (-Y)
+ * 3.11	File modification time can be checked against existing file after
+ *	name modification (-Z)
+ *
+ * 4	GENERAL ENHANCEMENTS
+ * 4.1	Internal structure is designed to isolate format dependent and
+ *	independent functions. Formats are selected via a format driver table.
+ *	This encourages the addition of new archive formats by only having to
+ *	write those routines which id, read and write the archive header.
+ */
+
+/*
+ * main()
+ *	parse options, set up and operate as specified by the user.
+ *	any operational flaw will set exit_val to non-zero
+ * Return: 0 if ok, 1 otherwise
+ */
+
+int
+main(int argc, char *argv[])
+{
+	const char *tmpdir;
+	size_t tdlen;
+
+	(void) setlocale(LC_ALL, "");
+	listf = stderr;
+	/*
+	 * Keep a reference to cwd, so we can always come back home.
+	 */
+	cwdfd = open(".", O_RDONLY);
+	if (cwdfd < 0) {
+		syswarn(0, errno, "Can't open current working directory.");
+		return(exit_val);
+	}
+
+	/*
+	 * Where should we put temporary files?
+	 */
+	if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
+		tmpdir = _PATH_TMP;
+	tdlen = strlen(tmpdir);
+	while(tdlen > 0 && tmpdir[tdlen - 1] == '/')
+		tdlen--;
+	tempfile = malloc(tdlen + 1 + sizeof(_TFILE_BASE));
+	if (tempfile == NULL) {
+		paxwarn(1, "Cannot allocate memory for temp file name.");
+		return(exit_val);
+	}
+	if (tdlen)
+		memcpy(tempfile, tmpdir, tdlen);
+	tempbase = tempfile + tdlen;
+	*tempbase++ = '/';
+
+	/*
+	 * parse options, determine operational mode, general init
+	 */
+	options(argc, argv);
+	if ((gen_init() < 0) || (tty_init() < 0))
+		return(exit_val);
+
+	/*
+	 * select a primary operation mode
+	 */
+	switch(act) {
+	case EXTRACT:
+		extract();
+		break;
+	case ARCHIVE:
+		archive();
+		break;
+	case APPND:
+		if (gzip_program != NULL)
+			err(1, "can not gzip while appending");
+		append();
+		break;
+	case COPY:
+		copy();
+		break;
+	default:
+	case LIST:
+		list();
+		break;
+	}
+	return(exit_val);
+}
+
+/*
+ * sig_cleanup()
+ *	when interrupted we try to do whatever delayed processing we can.
+ *	This is not critical, but we really ought to limit our damage when we
+ *	are aborted by the user.
+ * Return:
+ *	never....
+ */
+
+void
+sig_cleanup(int which_sig)
+{
+	/*
+	 * restore modes and times for any dirs we may have created
+	 * or any dirs we may have read. Set vflag and vfpart so the user
+	 * will clearly see the message on a line by itself.
+	 */
+	vflag = vfpart = 1;
+#if 0
+	/* ignore this under minix */
+	if (which_sig == SIGXCPU)
+		paxwarn(0, "Cpu time limit reached, cleaning up.");
+	else
+#endif
+		paxwarn(0, "Signal caught, cleaning up.");
+
+	ar_close();
+	proc_dir();
+	if (tflag)
+		atdir_end();
+	exit(1);
+}
+
+/*
+ * gen_init()
+ *	general setup routines. Not all are required, but they really help
+ *	when dealing with a medium to large sized archives.
+ */
+
+static int
+gen_init(void)
+{
+#if 0
+	struct rlimit reslimit;
+#endif
+	struct sigaction n_hand;
+	struct sigaction o_hand;
+
+#if 0
+	/*
+	 * Really needed to handle large archives. We can run out of memory for
+	 * internal tables really fast when we have a whole lot of files...
+	 */
+	if (getrlimit(RLIMIT_DATA , &reslimit) == 0){
+		reslimit.rlim_cur = reslimit.rlim_max;
+		(void)setrlimit(RLIMIT_DATA , &reslimit);
+	}
+
+	/*
+	 * should file size limits be waived? if the os limits us, this is
+	 * needed if we want to write a large archive
+	 */
+	if (getrlimit(RLIMIT_FSIZE , &reslimit) == 0){
+		reslimit.rlim_cur = reslimit.rlim_max;
+		(void)setrlimit(RLIMIT_FSIZE , &reslimit);
+	}
+
+	/*
+	 * increase the size the stack can grow to
+	 */
+	if (getrlimit(RLIMIT_STACK , &reslimit) == 0){
+		reslimit.rlim_cur = reslimit.rlim_max;
+		(void)setrlimit(RLIMIT_STACK , &reslimit);
+	}
+
+	/*
+	 * not really needed, but doesn't hurt
+	 */
+	if (getrlimit(RLIMIT_RSS , &reslimit) == 0){
+		reslimit.rlim_cur = reslimit.rlim_max;
+		(void)setrlimit(RLIMIT_RSS , &reslimit);
+	}
+#endif
+
+	/*
+	 * signal handling to reset stored directory times and modes. Since
+	 * we deal with broken pipes via failed writes we ignore it. We also
+	 * deal with any file size limit thorugh failed writes. Cpu time
+	 * limits are caught and a cleanup is forced.
+	 */
+
+	if ((sigemptyset(&s_mask) < 0) || (sigaddset(&s_mask, SIGTERM) < 0) ||
+	    (sigaddset(&s_mask,SIGINT) < 0)||(sigaddset(&s_mask,SIGHUP) < 0) ||
+	    (sigaddset(&s_mask,SIGPIPE) < 0)||(sigaddset(&s_mask,SIGQUIT)<0) 
+#if 0
+	    || (sigaddset(&s_mask,SIGXCPU) < 0)||(sigaddset(&s_mask,SIGXFSZ)<0)
+#endif
+	    ) {
+		paxwarn(1, "Unable to set up signal mask");
+		return(-1);
+	}
+	memset(&n_hand, 0, sizeof n_hand);
+	n_hand.sa_mask = s_mask;
+	n_hand.sa_flags = 0;
+	n_hand.sa_handler = sig_cleanup;
+
+	if ((sigaction(SIGHUP, &n_hand, &o_hand) < 0) &&
+	    (o_hand.sa_handler == SIG_IGN) &&
+	    (sigaction(SIGHUP, &o_hand, &o_hand) < 0))
+		goto out;
+
+	if ((sigaction(SIGTERM, &n_hand, &o_hand) < 0) &&
+	    (o_hand.sa_handler == SIG_IGN) &&
+	    (sigaction(SIGTERM, &o_hand, &o_hand) < 0))
+		goto out;
+
+	if ((sigaction(SIGINT, &n_hand, &o_hand) < 0) &&
+	    (o_hand.sa_handler == SIG_IGN) &&
+	    (sigaction(SIGINT, &o_hand, &o_hand) < 0))
+		goto out;
+
+	if ((sigaction(SIGQUIT, &n_hand, &o_hand) < 0) &&
+	    (o_hand.sa_handler == SIG_IGN) &&
+	    (sigaction(SIGQUIT, &o_hand, &o_hand) < 0))
+		goto out;
+
+#if 0
+	if ((sigaction(SIGXCPU, &n_hand, &o_hand) < 0) &&
+	    (o_hand.sa_handler == SIG_IGN) &&
+	    (sigaction(SIGXCPU, &o_hand, &o_hand) < 0))
+		goto out;
+#endif
+
+	n_hand.sa_handler = SIG_IGN;
+	if ((sigaction(SIGPIPE, &n_hand, &o_hand) < 0)
+#if 0
+	 || (sigaction(SIGXFSZ, &n_hand, &o_hand) < 0)
+#endif
+	    )
+
+
+		goto out;
+	return(0);
+
+    out:
+	syswarn(1, errno, "Unable to set up signal handler");
+	return(-1);
+}
Index: /trunk/minix/commands/pax/pax.h
===================================================================
--- /trunk/minix/commands/pax/pax.h	(revision 9)
+++ /trunk/minix/commands/pax/pax.h	(revision 9)
@@ -0,0 +1,251 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)pax.h	8.2 (Berkeley) 4/18/94
+ * $FreeBSD: src/bin/pax/pax.h,v 1.18 2004/04/06 20:06:48 markm Exp $
+ */
+
+
+#include <minix/config.h>
+#include <minix/const.h>
+
+/*
+ * BSD PAX global data structures and constants.
+ */
+
+#define	MAXBLK		64512	/* MAX blocksize supported (posix SPEC) */
+				/* WARNING: increasing MAXBLK past 32256 */
+				/* will violate posix spec. */
+#define	MAXBLK_POSIX	32256	/* MAX blocksize supported as per POSIX */
+#define BLKMULT		512	/* blocksize must be even mult of 512 bytes */
+				/* Don't even think of changing this */
+#define DEVBLK		8192	/* default read blksize for devices */
+#define FILEBLK		10240	/* default read blksize for files */
+#define PAXPATHLEN	3072	/* maximum path length for pax. MUST be */
+				/* longer than the system PATH_MAX */
+
+/*
+ * Pax modes of operation
+ */
+#define	LIST		0	/* List the file in an archive */
+#define	EXTRACT		1	/* extract the files in an archive */
+#define ARCHIVE		2	/* write a new archive */
+#define APPND		3	/* append to the end of an archive */
+#define	COPY		4	/* copy files to destination dir */
+#define DEFOP		LIST	/* if no flags default is to LIST */
+
+/*
+ * Device type of the current archive volume
+ */
+#define ISREG		0	/* regular file */
+#define ISCHR		1	/* character device */
+#define ISBLK		2	/* block device */
+#define ISTAPE		3	/* tape drive */
+#define ISPIPE		4	/* pipe/socket */
+
+typedef struct archd ARCHD;
+typedef struct fsub FSUB;
+typedef struct oplist OPLIST;
+typedef struct pattern PATTERN;
+
+/*
+ * Format Specific Routine Table
+ *
+ * The format specific routine table allows new archive formats to be quickly
+ * added. Overall pax operation is independent of the actual format used to
+ * form the archive. Only those routines which deal directly with the archive
+ * are tailored to the oddities of the specific format. All other routines are
+ * independent of the archive format. Data flow in and out of the format
+ * dependent routines pass pointers to ARCHD structure (described below).
+ */
+struct fsub {
+	const char *name;	/* name of format, this is the name the user */
+				/* gives to -x option to select it. */
+	int bsz;		/* default block size. used when the user */
+				/* does not specify a blocksize for writing */
+				/* Appends continue to with the blocksize */
+				/* the archive is currently using. */
+	int hsz;		/* Header size in bytes. this is the size of */
+				/* the smallest header this format supports. */
+				/* Headers are assumed to fit in a BLKMULT. */
+				/* If they are bigger, get_head() and */
+				/* get_arc() must be adjusted */
+	int udev;		/* does append require unique dev/ino? some */
+				/* formats use the device and inode fields */
+				/* to specify hard links. when members in */
+				/* the archive have the same inode/dev they */
+				/* are assumed to be hard links. During */
+				/* append we may have to generate unique ids */
+				/* to avoid creating incorrect hard links */
+	int hlk;		/* does archive store hard links info? if */
+				/* not, we do not bother to look for them */
+				/* during archive write operations */
+	int blkalgn;		/* writes must be aligned to blkalgn boundary */
+	int inhead;		/* is the trailer encoded in a valid header? */
+				/* if not, trailers are assumed to be found */
+				/* in invalid headers (i.e like tar) */
+	int (*id)(char *, int);	/* checks if a buffer is a valid header */
+				/* returns 1 if it is, o.w. returns a 0 */
+	int (*st_rd)(void);	/* initialize routine for read. so format */
+				/* can set up tables etc before it starts */
+				/* reading an archive */
+	int (*rd)(ARCHD *, char *);
+				/* read header routine. passed a pointer to */
+				/* ARCHD. It must extract the info from the */
+				/* format and store it in the ARCHD struct. */
+				/* This routine is expected to fill all the */
+				/* fields in the ARCHD (including stat buf) */
+				/* 0 is returned when a valid header is */
+				/* found. -1 when not valid. This routine */
+				/* set the skip and pad fields so the format */
+				/* independent routines know the amount of */
+				/* padding and the number of bytes of data */
+				/* which follow the header. This info is */
+				/* used skip to the next file header */
+	off_t (*end_rd)(void);	/* read cleanup. Allows format to clean up */
+				/* and MUST RETURN THE LENGTH OF THE TRAILER */
+				/* RECORD (so append knows how many bytes */
+				/* to move back to rewrite the trailer) */
+	int (*st_wr)(void);	/* initialize routine for write operations */
+	int (*wr)(ARCHD *);	/* write archive header. Passed an ARCHD */
+				/* filled with the specs on the next file to */
+				/* archived. Returns a 1 if no file data is */
+				/* is to be stored; 0 if file data is to be */
+				/* added. A -1 is returned if a write */
+				/* operation to the archive failed. this */
+				/* function sets the skip and pad fields so */
+				/* the proper padding can be added after */
+				/* file data. This routine must NEVER write */
+				/* a flawed archive header. */
+	int (*end_wr)(void);	/* end write. write the trailer and do any */
+				/* other format specific functions needed */
+				/* at the end of an archive write */
+	int (*trail_cpio)(ARCHD *);
+	int (*trail_tar)(char *, int, int *);
+				/* returns 0 if a valid trailer, -1 if not */
+				/* For formats which encode the trailer */
+				/* outside of a valid header, a return value */
+				/* of 1 indicates that the block passed to */
+				/* it can never contain a valid header (skip */
+				/* this block, no point in looking at it)  */
+	int (*rd_data)(ARCHD *, int, off_t *);
+				/* read/process file data from the archive */
+	int (*wr_data)(ARCHD *, int, off_t *);
+				/* write/process file data to the archive */
+	int (*options)(void);	/* process format specific options (-o) */
+};
+
+/*
+ * Pattern matching structure
+ *
+ * Used to store command line patterns
+ */
+struct pattern {
+	char		*pstr;		/* pattern to match, user supplied */
+	char		*pend;		/* end of a prefix match */
+	char		*chdname;	/* the dir to change to if not NULL.  */
+	int		plen;		/* length of pstr */
+	int		flgs;		/* processing/state flags */
+#define MTCH		0x1		/* pattern has been matched */
+#define DIR_MTCH	0x2		/* pattern matched a directory */
+	struct pattern	*fow;		/* next pattern */
+};
+
+/*
+ * General Archive Structure (used internal to pax)
+ *
+ * This structure is used to pass information about archive members between
+ * the format independent routines and the format specific routines. When
+ * new archive formats are added, they must accept requests and supply info
+ * encoded in a structure of this type. The name fields are declared statically
+ * here, as there is only ONE of these floating around, size is not a major
+ * consideration. Eventually converting the name fields to a dynamic length
+ * may be required if and when the supporting operating system removes all
+ * restrictions on the length of pathnames it will resolve.
+ */
+struct archd {
+	int nlen;			/* file name length */
+	char name[PAXPATHLEN+1];	/* file name */
+	int ln_nlen;			/* link name length */
+	char ln_name[PAXPATHLEN+1];	/* name to link to (if any) */
+	char *org_name;			/* orig name in file system */
+	PATTERN *pat;			/* ptr to pattern match (if any) */
+	struct stat sb;			/* stat buffer see stat(2) */
+	off_t pad;			/* bytes of padding after file xfer */
+	off_t skip;			/* bytes of real data after header */
+					/* IMPORTANT. The st_size field does */
+					/* not always indicate the amount of */
+					/* data following the header. */
+	u_long crc;			/* file crc */
+	int type;			/* type of file node */
+#define PAX_DIR		1		/* directory */
+#define PAX_CHR		2		/* character device */
+#define PAX_BLK		3		/* block device */
+#define PAX_REG		4		/* regular file */
+#define PAX_SLK		5		/* symbolic link */
+#define PAX_SCK		6		/* socket */
+#define PAX_FIF		7		/* fifo */
+#define PAX_HLK		8		/* hard link */
+#define PAX_HRG		9		/* hard link to a regular file */
+#define PAX_CTG		10		/* high performance file */
+};
+
+/*
+ * Format Specific Options List
+ *
+ * Used to pass format options to the format options handler
+ */
+struct oplist {
+	char		*name;		/* option variable name e.g. name= */
+	char		*value;		/* value for option variable */
+	struct oplist	*fow;		/* next option */
+};
+
+/*
+ * General Macros
+ */
+#ifndef MIN
+#define	       MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+#define TODEV(x, y)	makedev((x), (y))
+
+/*
+ * General Defines
+ */
+#define HEX		16
+#define OCT		8
+#define _PAX_		1
+#define _TFILE_BASE	"paxXXXXXXXXXX"
+
+#define err(c, str) { perror(str); exit(c); }
+#define setpassent(a) setpwent()
+#define setgroupent(a) setgrent()
Index: /trunk/minix/commands/pax/sel_subs.c
===================================================================
--- /trunk/minix/commands/pax/sel_subs.c	(revision 9)
+++ /trunk/minix/commands/pax/sel_subs.c	(revision 9)
@@ -0,0 +1,605 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)sel_subs.c	8.1 (Berkeley) 5/31/93";
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <time.h>
+#include <grp.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "pax.h"
+#include "sel_subs.h"
+#include "extern.h"
+
+static int str_sec(char *, time_t *);
+static int usr_match(ARCHD *);
+static int grp_match(ARCHD *);
+static int trng_match(ARCHD *);
+
+static TIME_RNG *trhead = NULL;		/* time range list head */
+static TIME_RNG *trtail = NULL;		/* time range list tail */
+static USRT **usrtb = NULL;		/* user selection table */
+static GRPT **grptb = NULL;		/* group selection table */
+
+/*
+ * Routines for selection of archive members
+ */
+
+/*
+ * sel_chk()
+ *	check if this file matches a specified uid, gid or time range
+ * Return:
+ *	0 if this archive member should be processed, 1 if it should be skipped
+ */
+
+int
+sel_chk(ARCHD *arcn)
+{
+	if (((usrtb != NULL) && usr_match(arcn)) ||
+	    ((grptb != NULL) && grp_match(arcn)) ||
+	    ((trhead != NULL) && trng_match(arcn)))
+		return(1);
+	return(0);
+}
+
+/*
+ * User/group selection routines
+ *
+ * Routines to handle user selection of files based on the file uid/gid. To
+ * add an entry, the user supplies either then name or the uid/gid starting with
+ * a # on the command line. A \# will escape the #.
+ */
+
+/*
+ * usr_add()
+ *	add a user match to the user match hash table
+ * Return:
+ *	0 if added ok, -1 otherwise;
+ */
+
+int
+usr_add(char *str)
+{
+	u_int indx;
+	USRT *pt;
+	struct passwd *pw;
+	uid_t uid;
+
+	/*
+	 * create the table if it doesn't exist
+	 */
+	if ((str == NULL) || (*str == '\0'))
+		return(-1);
+	if ((usrtb == NULL) &&
+ 	    ((usrtb = (USRT **)calloc(USR_TB_SZ, sizeof(USRT *))) == NULL)) {
+		paxwarn(1, "Unable to allocate memory for user selection table");
+		return(-1);
+	}
+
+	/*
+	 * figure out user spec
+	 */
+	if (str[0] != '#') {
+		/*
+		 * it is a user name, \# escapes # as first char in user name
+		 */
+		if ((str[0] == '\\') && (str[1] == '#'))
+			++str;
+		if ((pw = getpwnam(str)) == NULL) {
+			paxwarn(1, "Unable to find uid for user: %s", str);
+			return(-1);
+		}
+		uid = (uid_t)pw->pw_uid;
+	} else
+#		ifdef NET2_STAT
+		uid = (uid_t)atoi(str+1);
+#		else
+		uid = (uid_t)strtoul(str+1, NULL, 10);
+#		endif
+	endpwent();
+
+	/*
+	 * hash it and go down the hash chain (if any) looking for it
+	 */
+	indx = ((unsigned)uid) % USR_TB_SZ;
+	if ((pt = usrtb[indx]) != NULL) {
+		while (pt != NULL) {
+			if (pt->uid == uid)
+				return(0);
+			pt = pt->fow;
+		}
+	}
+
+	/*
+	 * uid is not yet in the table, add it to the front of the chain
+	 */
+	if ((pt = (USRT *)malloc(sizeof(USRT))) != NULL) {
+		pt->uid = uid;
+		pt->fow = usrtb[indx];
+		usrtb[indx] = pt;
+		return(0);
+	}
+	paxwarn(1, "User selection table out of memory");
+	return(-1);
+}
+
+/*
+ * usr_match()
+ *	check if this files uid matches a selected uid.
+ * Return:
+ *	0 if this archive member should be processed, 1 if it should be skipped
+ */
+
+static int
+usr_match(ARCHD *arcn)
+{
+	USRT *pt;
+
+	/*
+	 * hash and look for it in the table
+	 */
+	pt = usrtb[((unsigned)arcn->sb.st_uid) % USR_TB_SZ];
+	while (pt != NULL) {
+		if (pt->uid == arcn->sb.st_uid)
+			return(0);
+		pt = pt->fow;
+	}
+
+	/*
+	 * not found
+	 */
+	return(1);
+}
+
+/*
+ * grp_add()
+ *	add a group match to the group match hash table
+ * Return:
+ *	0 if added ok, -1 otherwise;
+ */
+
+int
+grp_add(char *str)
+{
+	u_int indx;
+	GRPT *pt;
+	struct group *gr;
+	gid_t gid;
+
+	/*
+	 * create the table if it doesn't exist
+	 */
+	if ((str == NULL) || (*str == '\0'))
+		return(-1);
+	if ((grptb == NULL) &&
+ 	    ((grptb = (GRPT **)calloc(GRP_TB_SZ, sizeof(GRPT *))) == NULL)) {
+		paxwarn(1, "Unable to allocate memory fo group selection table");
+		return(-1);
+	}
+
+	/*
+	 * figure out user spec
+	 */
+	if (str[0] != '#') {
+		/*
+		 * it is a group name, \# escapes # as first char in group name
+		 */
+		if ((str[0] == '\\') && (str[1] == '#'))
+			++str;
+		if ((gr = getgrnam(str)) == NULL) {
+			paxwarn(1,"Cannot determine gid for group name: %s", str);
+			return(-1);
+		}
+		gid = gr->gr_gid;
+	} else
+#		ifdef NET2_STAT
+		gid = (gid_t)atoi(str+1);
+#		else
+		gid = (gid_t)strtoul(str+1, NULL, 10);
+#		endif
+	endgrent();
+
+	/*
+	 * hash it and go down the hash chain (if any) looking for it
+	 */
+	indx = ((unsigned)gid) % GRP_TB_SZ;
+	if ((pt = grptb[indx]) != NULL) {
+		while (pt != NULL) {
+			if (pt->gid == gid)
+				return(0);
+			pt = pt->fow;
+		}
+	}
+
+	/*
+	 * gid not in the table, add it to the front of the chain
+	 */
+	if ((pt = (GRPT *)malloc(sizeof(GRPT))) != NULL) {
+		pt->gid = gid;
+		pt->fow = grptb[indx];
+		grptb[indx] = pt;
+		return(0);
+	}
+	paxwarn(1, "Group selection table out of memory");
+	return(-1);
+}
+
+/*
+ * grp_match()
+ *	check if this files gid matches a selected gid.
+ * Return:
+ *	0 if this archive member should be processed, 1 if it should be skipped
+ */
+
+static int
+grp_match(ARCHD *arcn)
+{
+	GRPT *pt;
+
+	/*
+	 * hash and look for it in the table
+	 */
+	pt = grptb[((unsigned)arcn->sb.st_gid) % GRP_TB_SZ];
+	while (pt != NULL) {
+		if (pt->gid == arcn->sb.st_gid)
+			return(0);
+		pt = pt->fow;
+	}
+
+	/*
+	 * not found
+	 */
+	return(1);
+}
+
+/*
+ * Time range selection routines
+ *
+ * Routines to handle user selection of files based on the modification and/or
+ * inode change time falling within a specified time range (the non-standard
+ * -T flag). The user may specify any number of different file time ranges.
+ * Time ranges are checked one at a time until a match is found (if at all).
+ * If the file has a mtime (and/or ctime) which lies within one of the time
+ * ranges, the file is selected. Time ranges may have a lower and/or an upper
+ * value. These ranges are inclusive. When no time ranges are supplied to pax
+ * with the -T option, all members in the archive will be selected by the time
+ * range routines. When only a lower range is supplied, only files with a
+ * mtime (and/or ctime) equal to or younger are selected. When only an upper
+ * range is supplied, only files with a mtime (and/or ctime) equal to or older
+ * are selected. When the lower time range is equal to the upper time range,
+ * only files with a mtime (or ctime) of exactly that time are selected.
+ */
+
+/*
+ * trng_add()
+ *	add a time range match to the time range list.
+ *	This is a non-standard pax option. Lower and upper ranges are in the
+ *	format: [yy[mm[dd[hh]]]]mm[.ss] and are comma separated.
+ *	Time ranges are based on current time, so 1234 would specify a time of
+ *	12:34 today.
+ * Return:
+ *	0 if the time range was added to the list, -1 otherwise
+ */
+
+int
+trng_add(char *str)
+{
+	TIME_RNG *pt;
+	char *up_pt = NULL;
+	char *stpt;
+	char *flgpt;
+	int dot = 0;
+
+	/*
+	 * throw out the badly formed time ranges
+	 */
+	if ((str == NULL) || (*str == '\0')) {
+		paxwarn(1, "Empty time range string");
+		return(-1);
+	}
+
+	/*
+	 * locate optional flags suffix /{cm}.
+	 */
+	if ((flgpt = strrchr(str, '/')) != NULL)
+		*flgpt++ = '\0';
+
+	for (stpt = str; *stpt != '\0'; ++stpt) {
+		if ((*stpt >= '0') && (*stpt <= '9'))
+			continue;
+		if ((*stpt == ',') && (up_pt == NULL)) {
+			*stpt = '\0';
+			up_pt = stpt + 1;
+			dot = 0;
+			continue;
+		}
+
+		/*
+		 * allow only one dot per range (secs)
+		 */
+		if ((*stpt == '.') && (!dot)) {
+			++dot;
+			continue;
+		}
+		paxwarn(1, "Improperly specified time range: %s", str);
+		goto out;
+	}
+
+	/*
+	 * allocate space for the time range and store the limits
+	 */
+	if ((pt = (TIME_RNG *)malloc(sizeof(TIME_RNG))) == NULL) {
+		paxwarn(1, "Unable to allocate memory for time range");
+		return(-1);
+	}
+
+	/*
+	 * by default we only will check file mtime, but usee can specify
+	 * mtime, ctime (inode change time) or both.
+	 */
+	if ((flgpt == NULL) || (*flgpt == '\0'))
+		pt->flgs = CMPMTME;
+	else {
+		pt->flgs = 0;
+		while (*flgpt != '\0') {
+			switch(*flgpt) {
+			case 'M':
+			case 'm':
+				pt->flgs |= CMPMTME;
+				break;
+			case 'C':
+			case 'c':
+				pt->flgs |= CMPCTME;
+				break;
+			default:
+				paxwarn(1, "Bad option %c with time range %s",
+				    *flgpt, str);
+				goto out;
+			}
+			++flgpt;
+		}
+	}
+
+	/*
+	 * start off with the current time
+	 */
+	pt->low_time = pt->high_time = time(NULL);
+	if (*str != '\0') {
+		/*
+		 * add lower limit
+		 */
+		if (str_sec(str, &(pt->low_time)) < 0) {
+			paxwarn(1, "Illegal lower time range %s", str);
+			(void)free((char *)pt);
+			goto out;
+		}
+		pt->flgs |= HASLOW;
+	}
+
+	if ((up_pt != NULL) && (*up_pt != '\0')) {
+		/*
+		 * add upper limit
+		 */
+		if (str_sec(up_pt, &(pt->high_time)) < 0) {
+			paxwarn(1, "Illegal upper time range %s", up_pt);
+			(void)free((char *)pt);
+			goto out;
+		}
+		pt->flgs |= HASHIGH;
+
+		/*
+		 * check that the upper and lower do not overlap
+		 */
+		if (pt->flgs & HASLOW) {
+			if (pt->low_time > pt->high_time) {
+				paxwarn(1, "Upper %s and lower %s time overlap",
+					up_pt, str);
+				(void)free((char *)pt);
+				return(-1);
+			}
+		}
+	}
+
+	pt->fow = NULL;
+	if (trhead == NULL) {
+		trtail = trhead = pt;
+		return(0);
+	}
+	trtail->fow = pt;
+	trtail = pt;
+	return(0);
+
+    out:
+	paxwarn(1, "Time range format is: [yy[mm[dd[hh]]]]mm[.ss][/[c][m]]");
+	return(-1);
+}
+
+/*
+ * trng_match()
+ *	check if this files mtime/ctime falls within any supplied time range.
+ * Return:
+ *	0 if this archive member should be processed, 1 if it should be skipped
+ */
+
+static int
+trng_match(ARCHD *arcn)
+{
+	TIME_RNG *pt;
+
+	/*
+	 * have to search down the list one at a time looking for a match.
+	 * remember time range limits are inclusive.
+	 */
+	pt = trhead;
+	while (pt != NULL) {
+		switch(pt->flgs & CMPBOTH) {
+		case CMPBOTH:
+			/*
+			 * user wants both mtime and ctime checked for this
+			 * time range
+			 */
+			if (((pt->flgs & HASLOW) &&
+			    (arcn->sb.st_mtime < pt->low_time) &&
+			    (arcn->sb.st_ctime < pt->low_time)) ||
+			    ((pt->flgs & HASHIGH) &&
+			    (arcn->sb.st_mtime > pt->high_time) &&
+			    (arcn->sb.st_ctime > pt->high_time))) {
+				pt = pt->fow;
+				continue;
+			}
+			break;
+		case CMPCTME:
+			/*
+			 * user wants only ctime checked for this time range
+			 */
+			if (((pt->flgs & HASLOW) &&
+			    (arcn->sb.st_ctime < pt->low_time)) ||
+			    ((pt->flgs & HASHIGH) &&
+			    (arcn->sb.st_ctime > pt->high_time))) {
+				pt = pt->fow;
+				continue;
+			}
+			break;
+		case CMPMTME:
+		default:
+			/*
+			 * user wants only mtime checked for this time range
+			 */
+			if (((pt->flgs & HASLOW) &&
+			    (arcn->sb.st_mtime < pt->low_time)) ||
+			    ((pt->flgs & HASHIGH) &&
+			    (arcn->sb.st_mtime > pt->high_time))) {
+				pt = pt->fow;
+				continue;
+			}
+			break;
+		}
+		break;
+	}
+
+	if (pt == NULL)
+		return(1);
+	return(0);
+}
+
+/*
+ * str_sec()
+ *	Convert a time string in the format of [yy[mm[dd[hh]]]]mm[.ss] to gmt
+ *	seconds. Tval already has current time loaded into it at entry.
+ * Return:
+ *	0 if converted ok, -1 otherwise
+ */
+
+static int
+str_sec(char *str, time_t *tval)
+{
+	struct tm *lt;
+	char *dot = NULL;
+
+	lt = localtime(tval);
+	if ((dot = strchr(str, '.')) != NULL) {
+		/*
+		 * seconds (.ss)
+		 */
+		*dot++ = '\0';
+		if (strlen(dot) != 2)
+			return(-1);
+		if ((lt->tm_sec = ATOI2(dot)) > 61)
+			return(-1);
+	} else
+		lt->tm_sec = 0;
+
+	switch (strlen(str)) {
+	case 10:
+		/*
+		 * year (yy)
+		 * watch out for year 2000
+		 */
+		if ((lt->tm_year = ATOI2(str)) < 69)
+			lt->tm_year += 100;
+		str += 2;
+		/* FALLTHROUGH */
+	case 8:
+		/*
+		 * month (mm)
+		 * watch out months are from 0 - 11 internally
+		 */
+		if ((lt->tm_mon = ATOI2(str)) > 12)
+			return(-1);
+		--lt->tm_mon;
+		str += 2;
+		/* FALLTHROUGH */
+	case 6:
+		/*
+		 * day (dd)
+		 */
+		if ((lt->tm_mday = ATOI2(str)) > 31)
+			return(-1);
+		str += 2;
+		/* FALLTHROUGH */
+	case 4:
+		/*
+		 * hour (hh)
+		 */
+		if ((lt->tm_hour = ATOI2(str)) > 23)
+			return(-1);
+		str += 2;
+		/* FALLTHROUGH */
+	case 2:
+		/*
+		 * minute (mm)
+		 */
+		if ((lt->tm_min = ATOI2(str)) > 59)
+			return(-1);
+		break;
+	default:
+		return(-1);
+	}
+	/*
+	 * convert broken-down time to GMT clock time seconds
+	 */
+	if ((*tval = mktime(lt)) == -1)
+		return(-1);
+	return(0);
+}
Index: /trunk/minix/commands/pax/sel_subs.h
===================================================================
--- /trunk/minix/commands/pax/sel_subs.h	(revision 9)
+++ /trunk/minix/commands/pax/sel_subs.h	(revision 9)
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)sel_subs.h	8.1 (Berkeley) 5/31/93
+ * $FreeBSD: src/bin/pax/sel_subs.h,v 1.6 2004/04/06 20:06:48 markm Exp $
+ */
+
+/*
+ * data structure for storing uid/grp selects (-U, -G non standard options)
+ */
+
+#define USR_TB_SZ	317		/* user selection table size */
+#define GRP_TB_SZ	317		/* user selection table size */
+
+typedef struct usrt {
+	uid_t uid;
+	struct usrt *fow;		/* next uid */
+} USRT;
+
+typedef struct grpt {
+	gid_t gid;
+	struct grpt *fow;		/* next gid */
+} GRPT;
+
+/*
+ * data structure for storing user supplied time ranges (-T option)
+ */
+
+#define ATOI2(s)	((((s)[0] - '0') * 10) + ((s)[1] - '0'))
+
+typedef struct time_rng {
+	time_t		low_time;	/* lower inclusive time limit */
+	time_t		high_time;	/* higher inclusive time limit */
+	int		flgs;		/* option flags */
+#define	HASLOW		0x01		/* has lower time limit */
+#define HASHIGH		0x02		/* has higher time limit */
+#define CMPMTME		0x04		/* compare file modification time */
+#define CMPCTME		0x08		/* compare inode change time */
+#define CMPBOTH	(CMPMTME|CMPCTME)	/* compare inode and mod time */
+	struct time_rng	*fow;		/* next pattern */
+} TIME_RNG;
Index: /trunk/minix/commands/pax/tables.c
===================================================================
--- /trunk/minix/commands/pax/tables.c	(revision 9)
+++ /trunk/minix/commands/pax/tables.c	(revision 9)
@@ -0,0 +1,1284 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)tables.c	8.1 (Berkeley) 5/31/93";
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "pax.h"
+#include "tables.h"
+#include "extern.h"
+
+/*
+ * Routines for controlling the contents of all the different databases pax
+ * keeps. Tables are dynamically created only when they are needed. The
+ * goal was speed and the ability to work with HUGE archives. The databases
+ * were kept simple, but do have complex rules for when the contents change.
+ * As of this writing, the POSIX library functions were more complex than
+ * needed for this application (pax databases have very short lifetimes and
+ * do not survive after pax is finished). Pax is required to handle very
+ * large archives. These database routines carefully combine memory usage and
+ * temporary file storage in ways which will not significantly impact runtime
+ * performance while allowing the largest possible archives to be handled.
+ * Trying to force the fit to the POSIX databases routines was not considered
+ * time well spent.
+ */
+
+static HRDLNK **ltab = NULL;	/* hard link table for detecting hard links */
+static FTM **ftab = NULL;	/* file time table for updating arch */
+static NAMT **ntab = NULL;	/* interactive rename storage table */
+static DEVT **dtab = NULL;	/* device/inode mapping tables */
+static ATDIR **atab = NULL;	/* file tree directory time reset table */
+static int dirfd = -1;		/* storage for setting created dir time/mode */
+static u_long dircnt;		/* entries in dir time/mode storage */
+static int ffd = -1;		/* tmp file for file time table name storage */
+
+static DEVT *chk_dev(dev_t, int);
+
+/*
+ * hard link table routines
+ *
+ * The hard link table tries to detect hard links to files using the device and
+ * inode values. We do this when writing an archive, so we can tell the format
+ * write routine that this file is a hard link to another file. The format
+ * write routine then can store this file in whatever way it wants (as a hard
+ * link if the format supports that like tar, or ignore this info like cpio).
+ * (Actually a field in the format driver table tells us if the format wants
+ * hard link info. if not, we do not waste time looking for them). We also use
+ * the same table when reading an archive. In that situation, this table is
+ * used by the format read routine to detect hard links from stored dev and
+ * inode numbers (like cpio). This will allow pax to create a link when one
+ * can be detected by the archive format.
+ */
+
+/*
+ * lnk_start
+ *	Creates the hard link table.
+ * Return:
+ *	0 if created, -1 if failure
+ */
+
+int
+lnk_start(void)
+{
+	if (ltab != NULL)
+		return(0);
+ 	if ((ltab = (HRDLNK **)calloc(L_TAB_SZ, sizeof(HRDLNK *))) == NULL) {
+		paxwarn(1, "Cannot allocate memory for hard link table");
+		return(-1);
+	}
+	return(0);
+}
+
+/*
+ * chk_lnk()
+ *	Looks up entry in hard link hash table. If found, it copies the name
+ *	of the file it is linked to (we already saw that file) into ln_name.
+ *	lnkcnt is decremented and if goes to 1 the node is deleted from the
+ *	database. (We have seen all the links to this file). If not found,
+ *	we add the file to the database if it has the potential for having
+ *	hard links to other files we may process (it has a link count > 1)
+ * Return:
+ *	if found returns 1; if not found returns 0; -1 on error
+ */
+
+int
+chk_lnk(ARCHD *arcn)
+{
+	HRDLNK *pt;
+	HRDLNK **ppt;
+	u_int indx;
+
+	if (ltab == NULL)
+		return(-1);
+	/*
+	 * ignore those nodes that cannot have hard links
+	 */
+	if ((arcn->type == PAX_DIR) || (arcn->sb.st_nlink <= 1))
+		return(0);
+
+	/*
+	 * hash inode number and look for this file
+	 */
+	indx = ((unsigned)arcn->sb.st_ino) % L_TAB_SZ;
+	if ((pt = ltab[indx]) != NULL) {
+		/*
+		 * it's hash chain in not empty, walk down looking for it
+		 */
+		ppt = &(ltab[indx]);
+		while (pt != NULL) {
+			if ((pt->ino == arcn->sb.st_ino) &&
+			    (pt->dev == arcn->sb.st_dev))
+				break;
+			ppt = &(pt->fow);
+			pt = pt->fow;
+		}
+
+		if (pt != NULL) {
+			/*
+			 * found a link. set the node type and copy in the
+			 * name of the file it is to link to. we need to
+			 * handle hardlinks to regular files differently than
+			 * other links.
+			 */
+			arcn->ln_nlen = l_strncpy(arcn->ln_name, pt->name,
+				sizeof(arcn->ln_name) - 1);
+			arcn->ln_name[arcn->ln_nlen] = '\0';
+			if (arcn->type == PAX_REG)
+				arcn->type = PAX_HRG;
+			else
+				arcn->type = PAX_HLK;
+
+			/*
+			 * if we have found all the links to this file, remove
+			 * it from the database
+			 */
+			if (--pt->nlink <= 1) {
+				*ppt = pt->fow;
+				(void)free((char *)pt->name);
+				(void)free((char *)pt);
+			}
+			return(1);
+		}
+	}
+
+	/*
+	 * we never saw this file before. It has links so we add it to the
+	 * front of this hash chain
+	 */
+	if ((pt = (HRDLNK *)malloc(sizeof(HRDLNK))) != NULL) {
+		if ((pt->name = strdup(arcn->name)) != NULL) {
+			pt->dev = arcn->sb.st_dev;
+			pt->ino = arcn->sb.st_ino;
+			pt->nlink = arcn->sb.st_nlink;
+			pt->fow = ltab[indx];
+			ltab[indx] = pt;
+			return(0);
+		}
+		(void)free((char *)pt);
+	}
+
+	paxwarn(1, "Hard link table out of memory");
+	return(-1);
+}
+
+/*
+ * purg_lnk
+ *	remove reference for a file that we may have added to the data base as
+ *	a potential source for hard links. We ended up not using the file, so
+ *	we do not want to accidently point another file at it later on.
+ */
+
+void
+purg_lnk(ARCHD *arcn)
+{
+	HRDLNK *pt;
+	HRDLNK **ppt;
+	u_int indx;
+
+	if (ltab == NULL)
+		return;
+	/*
+	 * do not bother to look if it could not be in the database
+	 */
+	if ((arcn->sb.st_nlink <= 1) || (arcn->type == PAX_DIR) ||
+	    (arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
+		return;
+
+	/*
+	 * find the hash chain for this inode value, if empty return
+	 */
+	indx = ((unsigned)arcn->sb.st_ino) % L_TAB_SZ;
+	if ((pt = ltab[indx]) == NULL)
+		return;
+
+	/*
+	 * walk down the list looking for the inode/dev pair, unlink and
+	 * free if found
+	 */
+	ppt = &(ltab[indx]);
+	while (pt != NULL) {
+		if ((pt->ino == arcn->sb.st_ino) &&
+		    (pt->dev == arcn->sb.st_dev))
+			break;
+		ppt = &(pt->fow);
+		pt = pt->fow;
+	}
+	if (pt == NULL)
+		return;
+
+	/*
+	 * remove and free it
+	 */
+	*ppt = pt->fow;
+	(void)free((char *)pt->name);
+	(void)free((char *)pt);
+}
+
+/*
+ * lnk_end()
+ *	Pull apart an existing link table so we can reuse it. We do this between
+ *	read and write phases of append with update. (The format may have
+ *	used the link table, and we need to start with a fresh table for the
+ *	write phase).
+ */
+
+void
+lnk_end(void)
+{
+	int i;
+	HRDLNK *pt;
+	HRDLNK *ppt;
+
+	if (ltab == NULL)
+		return;
+
+	for (i = 0; i < L_TAB_SZ; ++i) {
+		if (ltab[i] == NULL)
+			continue;
+		pt = ltab[i];
+		ltab[i] = NULL;
+
+		/*
+		 * free up each entry on this chain
+		 */
+		while (pt != NULL) {
+			ppt = pt;
+			pt = ppt->fow;
+			(void)free((char *)ppt->name);
+			(void)free((char *)ppt);
+		}
+	}
+	return;
+}
+
+/*
+ * modification time table routines
+ *
+ * The modification time table keeps track of last modification times for all
+ * files stored in an archive during a write phase when -u is set. We only
+ * add a file to the archive if it is newer than a file with the same name
+ * already stored on the archive (if there is no other file with the same
+ * name on the archive it is added). This applies to writes and appends.
+ * An append with an -u must read the archive and store the modification time
+ * for every file on that archive before starting the write phase. It is clear
+ * that this is one HUGE database. To save memory space, the actual file names
+ * are stored in a scatch file and indexed by an in memory hash table. The
+ * hash table is indexed by hashing the file path. The nodes in the table store
+ * the length of the filename and the lseek offset within the scratch file
+ * where the actual name is stored. Since there are never any deletions to this
+ * table, fragmentation of the scratch file is never an issue. Lookups seem to
+ * not exhibit any locality at all (files in the database are rarely
+ * looked up more than once...). So caching is just a waste of memory. The
+ * only limitation is the amount of scatch file space available to store the
+ * path names.
+ */
+
+/*
+ * ftime_start()
+ *	create the file time hash table and open for read/write the scratch
+ *	file. (after created it is unlinked, so when we exit we leave
+ *	no witnesses).
+ * Return:
+ *	0 if the table and file was created ok, -1 otherwise
+ */
+
+int
+ftime_start(void)
+{
+
+	if (ftab != NULL)
+		return(0);
+ 	if ((ftab = (FTM **)calloc(F_TAB_SZ, sizeof(FTM *))) == NULL) {
+		paxwarn(1, "Cannot allocate memory for file time table");
+		return(-1);
+	}
+
+	/*
+	 * get random name and create temporary scratch file, unlink name
+	 * so it will get removed on exit
+	 */
+	memcpy(tempbase, _TFILE_BASE, sizeof(_TFILE_BASE));
+	if ((ffd = mkstemp(tempfile)) < 0) {
+		syswarn(1, errno, "Unable to create temporary file: %s",
+		    tempfile);
+		return(-1);
+	}
+	(void)unlink(tempfile);
+
+	return(0);
+}
+
+/*
+ * chk_ftime()
+ *	looks up entry in file time hash table. If not found, the file is
+ *	added to the hash table and the file named stored in the scratch file.
+ *	If a file with the same name is found, the file times are compared and
+ *	the most recent file time is retained. If the new file was younger (or
+ *	was not in the database) the new file is selected for storage.
+ * Return:
+ *	0 if file should be added to the archive, 1 if it should be skipped,
+ *	-1 on error
+ */
+
+int
+chk_ftime(ARCHD *arcn)
+{
+	FTM *pt;
+	int namelen;
+	u_int indx;
+	char ckname[PAXPATHLEN+1];
+
+	/*
+	 * no info, go ahead and add to archive
+	 */
+	if (ftab == NULL)
+		return(0);
+
+	/*
+	 * hash the pathname and look up in table
+	 */
+	namelen = arcn->nlen;
+	indx = st_hash(arcn->name, namelen, F_TAB_SZ);
+	if ((pt = ftab[indx]) != NULL) {
+		/*
+		 * the hash chain is not empty, walk down looking for match
+		 * only read up the path names if the lengths match, speeds
+		 * up the search a lot
+		 */
+		while (pt != NULL) {
+			if (pt->namelen == namelen) {
+				/*
+				 * potential match, have to read the name
+				 * from the scratch file.
+				 */
+				if (lseek(ffd,pt->seek,SEEK_SET) != pt->seek) {
+					syswarn(1, errno,
+					    "Failed ftime table seek");
+					return(-1);
+				}
+				if (read(ffd, ckname, namelen) != namelen) {
+					syswarn(1, errno,
+					    "Failed ftime table read");
+					return(-1);
+				}
+
+				/*
+				 * if the names match, we are done
+				 */
+				if (!strncmp(ckname, arcn->name, namelen))
+					break;
+			}
+
+			/*
+			 * try the next entry on the chain
+			 */
+			pt = pt->fow;
+		}
+
+		if (pt != NULL) {
+			/*
+			 * found the file, compare the times, save the newer
+			 */
+			if (arcn->sb.st_mtime > pt->mtime) {
+				/*
+				 * file is newer
+				 */
+				pt->mtime = arcn->sb.st_mtime;
+				return(0);
+			}
+			/*
+			 * file is older
+			 */
+			return(1);
+		}
+	}
+
+	/*
+	 * not in table, add it
+	 */
+	if ((pt = (FTM *)malloc(sizeof(FTM))) != NULL) {
+		/*
+		 * add the name at the end of the scratch file, saving the
+		 * offset. add the file to the head of the hash chain
+		 */
+		if ((pt->seek = lseek(ffd, (off_t)0, SEEK_END)) >= 0) {
+			if (write(ffd, arcn->name, namelen) == namelen) {
+				pt->mtime = arcn->sb.st_mtime;
+				pt->namelen = namelen;
+				pt->fow = ftab[indx];
+				ftab[indx] = pt;
+				return(0);
+			}
+			syswarn(1, errno, "Failed write to file time table");
+		} else
+			syswarn(1, errno, "Failed seek on file time table");
+	} else
+		paxwarn(1, "File time table ran out of memory");
+
+	if (pt != NULL)
+		(void)free((char *)pt);
+	return(-1);
+}
+
+/*
+ * Interactive rename table routines
+ *
+ * The interactive rename table keeps track of the new names that the user
+ * assigns to files from tty input. Since this map is unique for each file
+ * we must store it in case there is a reference to the file later in archive
+ * (a link). Otherwise we will be unable to find the file we know was
+ * extracted. The remapping of these files is stored in a memory based hash
+ * table (it is assumed since input must come from /dev/tty, it is unlikely to
+ * be a very large table).
+ */
+
+/*
+ * name_start()
+ *	create the interactive rename table
+ * Return:
+ *	0 if successful, -1 otherwise
+ */
+
+int
+name_start(void)
+{
+	if (ntab != NULL)
+		return(0);
+ 	if ((ntab = (NAMT **)calloc(N_TAB_SZ, sizeof(NAMT *))) == NULL) {
+		paxwarn(1, "Cannot allocate memory for interactive rename table");
+		return(-1);
+	}
+	return(0);
+}
+
+/*
+ * add_name()
+ *	add the new name to old name mapping just created by the user.
+ *	If an old name mapping is found (there may be duplicate names on an
+ *	archive) only the most recent is kept.
+ * Return:
+ *	0 if added, -1 otherwise
+ */
+
+int
+add_name(char *oname, int onamelen, char *nname)
+{
+	NAMT *pt;
+	u_int indx;
+
+	if (ntab == NULL) {
+		/*
+		 * should never happen
+		 */
+		paxwarn(0, "No interactive rename table, links may fail\n");
+		return(0);
+	}
+
+	/*
+	 * look to see if we have already mapped this file, if so we
+	 * will update it
+	 */
+	indx = st_hash(oname, onamelen, N_TAB_SZ);
+	if ((pt = ntab[indx]) != NULL) {
+		/*
+		 * look down the has chain for the file
+		 */
+		while ((pt != NULL) && (strcmp(oname, pt->oname) != 0))
+			pt = pt->fow;
+
+		if (pt != NULL) {
+			/*
+			 * found an old mapping, replace it with the new one
+			 * the user just input (if it is different)
+			 */
+			if (strcmp(nname, pt->nname) == 0)
+				return(0);
+
+			(void)free((char *)pt->nname);
+			if ((pt->nname = strdup(nname)) == NULL) {
+				paxwarn(1, "Cannot update rename table");
+				return(-1);
+			}
+			return(0);
+		}
+	}
+
+	/*
+	 * this is a new mapping, add it to the table
+	 */
+	if ((pt = (NAMT *)malloc(sizeof(NAMT))) != NULL) {
+		if ((pt->oname = strdup(oname)) != NULL) {
+			if ((pt->nname = strdup(nname)) != NULL) {
+				pt->fow = ntab[indx];
+				ntab[indx] = pt;
+				return(0);
+			}
+			(void)free((char *)pt->oname);
+		}
+		(void)free((char *)pt);
+	}
+	paxwarn(1, "Interactive rename table out of memory");
+	return(-1);
+}
+
+/*
+ * sub_name()
+ *	look up a link name to see if it points at a file that has been
+ *	remapped by the user. If found, the link is adjusted to contain the
+ *	new name (oname is the link to name)
+ */
+
+void
+sub_name(char *oname, int *onamelen, size_t onamesize)
+{
+	NAMT *pt;
+	u_int indx;
+
+	if (ntab == NULL)
+		return;
+	/*
+	 * look the name up in the hash table
+	 */
+	indx = st_hash(oname, *onamelen, N_TAB_SZ);
+	if ((pt = ntab[indx]) == NULL)
+		return;
+
+	while (pt != NULL) {
+		/*
+		 * walk down the hash chain looking for a match
+		 */
+		if (strcmp(oname, pt->oname) == 0) {
+			/*
+			 * found it, replace it with the new name
+			 * and return (we know that oname has enough space)
+			 */
+			*onamelen = l_strncpy(oname, pt->nname, onamesize - 1);
+			oname[*onamelen] = '\0';
+			return;
+		}
+		pt = pt->fow;
+	}
+
+	/*
+	 * no match, just return
+	 */
+	return;
+}
+
+/*
+ * device/inode mapping table routines
+ * (used with formats that store device and inodes fields)
+ *
+ * device/inode mapping tables remap the device field in an archive header. The
+ * device/inode fields are used to determine when files are hard links to each
+ * other. However these values have very little meaning outside of that. This
+ * database is used to solve one of two different problems.
+ *
+ * 1) when files are appended to an archive, while the new files may have hard
+ * links to each other, you cannot determine if they have hard links to any
+ * file already stored on the archive from a prior run of pax. We must assume
+ * that these inode/device pairs are unique only within a SINGLE run of pax
+ * (which adds a set of files to an archive). So we have to make sure the
+ * inode/dev pairs we add each time are always unique. We do this by observing
+ * while the inode field is very dense, the use of the dev field is fairly
+ * sparse. Within each run of pax, we remap any device number of a new archive
+ * member that has a device number used in a prior run and already stored in a
+ * file on the archive. During the read phase of the append, we store the
+ * device numbers used and mark them to not be used by any file during the
+ * write phase. If during write we go to use one of those old device numbers,
+ * we remap it to a new value.
+ *
+ * 2) Often the fields in the archive header used to store these values are
+ * too small to store the entire value. The result is an inode or device value
+ * which can be truncated. This really can foul up an archive. With truncation
+ * we end up creating links between files that are really not links (after
+ * truncation the inodes are the same value). We address that by detecting
+ * truncation and forcing a remap of the device field to split truncated
+ * inodes away from each other. Each truncation creates a pattern of bits that
+ * are removed. We use this pattern of truncated bits to partition the inodes
+ * on a single device to many different devices (each one represented by the
+ * truncated bit pattern). All inodes on the same device that have the same
+ * truncation pattern are mapped to the same new device. Two inodes that
+ * truncate to the same value clearly will always have different truncation
+ * bit patterns, so they will be split from away each other. When we spot
+ * device truncation we remap the device number to a non truncated value.
+ * (for more info see table.h for the data structures involved).
+ */
+
+/*
+ * dev_start()
+ *	create the device mapping table
+ * Return:
+ *	0 if successful, -1 otherwise
+ */
+
+int
+dev_start(void)
+{
+	if (dtab != NULL)
+		return(0);
+ 	if ((dtab = (DEVT **)calloc(D_TAB_SZ, sizeof(DEVT *))) == NULL) {
+		paxwarn(1, "Cannot allocate memory for device mapping table");
+		return(-1);
+	}
+	return(0);
+}
+
+/*
+ * add_dev()
+ *	add a device number to the table. this will force the device to be
+ *	remapped to a new value if it be used during a write phase. This
+ *	function is called during the read phase of an append to prohibit the
+ *	use of any device number already in the archive.
+ * Return:
+ *	0 if added ok, -1 otherwise
+ */
+
+int
+add_dev(ARCHD *arcn)
+{
+	if (chk_dev(arcn->sb.st_dev, 1) == NULL)
+		return(-1);
+	return(0);
+}
+
+/*
+ * chk_dev()
+ *	check for a device value in the device table. If not found and the add
+ *	flag is set, it is added. This does NOT assign any mapping values, just
+ *	adds the device number as one that need to be remapped. If this device
+ *	is already mapped, just return with a pointer to that entry.
+ * Return:
+ *	pointer to the entry for this device in the device map table. Null
+ *	if the add flag is not set and the device is not in the table (it is
+ *	not been seen yet). If add is set and the device cannot be added, null
+ *	is returned (indicates an error).
+ */
+
+static DEVT *
+chk_dev(dev_t dev, int add)
+{
+	DEVT *pt;
+	u_int indx;
+
+	if (dtab == NULL)
+		return(NULL);
+	/*
+	 * look to see if this device is already in the table
+	 */
+	indx = ((unsigned)dev) % D_TAB_SZ;
+	if ((pt = dtab[indx]) != NULL) {
+		while ((pt != NULL) && (pt->dev != dev))
+			pt = pt->fow;
+
+		/*
+		 * found it, return a pointer to it
+		 */
+		if (pt != NULL)
+			return(pt);
+	}
+
+	/*
+	 * not in table, we add it only if told to as this may just be a check
+	 * to see if a device number is being used.
+	 */
+	if (add == 0)
+		return(NULL);
+
+	/*
+	 * allocate a node for this device and add it to the front of the hash
+	 * chain. Note we do not assign remaps values here, so the pt->list
+	 * list must be NULL.
+	 */
+	if ((pt = (DEVT *)malloc(sizeof(DEVT))) == NULL) {
+		paxwarn(1, "Device map table out of memory");
+		return(NULL);
+	}
+	pt->dev = dev;
+	pt->list = NULL;
+	pt->fow = dtab[indx];
+	dtab[indx] = pt;
+	return(pt);
+}
+/*
+ * map_dev()
+ *	given an inode and device storage mask (the mask has a 1 for each bit
+ *	the archive format is able to store in a header), we check for inode
+ *	and device truncation and remap the device as required. Device mapping
+ *	can also occur when during the read phase of append a device number was
+ *	seen (and was marked as do not use during the write phase). WE ASSUME
+ *	that unsigned longs are the same size or bigger than the fields used
+ *	for ino_t and dev_t. If not the types will have to be changed.
+ * Return:
+ *	0 if all ok, -1 otherwise.
+ */
+
+int
+map_dev(ARCHD *arcn, u_long dev_mask, u_long ino_mask)
+{
+	DEVT *pt;
+	DLIST *dpt;
+	static dev_t lastdev = 0;	/* next device number to try */
+	int trc_ino = 0;
+	int trc_dev = 0;
+	ino_t trunc_bits = 0;
+	ino_t nino;
+
+	if (dtab == NULL)
+		return(0);
+	/*
+	 * check for device and inode truncation, and extract the truncated
+	 * bit pattern.
+	 */
+	if ((arcn->sb.st_dev & (dev_t)dev_mask) != arcn->sb.st_dev)
+		++trc_dev;
+	if ((nino = arcn->sb.st_ino & (ino_t)ino_mask) != arcn->sb.st_ino) {
+		++trc_ino;
+		trunc_bits = arcn->sb.st_ino & (ino_t)(~ino_mask);
+	}
+
+	/*
+	 * see if this device is already being mapped, look up the device
+	 * then find the truncation bit pattern which applies
+	 */
+	if ((pt = chk_dev(arcn->sb.st_dev, 0)) != NULL) {
+		/*
+		 * this device is already marked to be remapped
+		 */
+		for (dpt = pt->list; dpt != NULL; dpt = dpt->fow)
+			if (dpt->trunc_bits == trunc_bits)
+				break;
+
+		if (dpt != NULL) {
+			/*
+			 * we are being remapped for this device and pattern
+			 * change the device number to be stored and return
+			 */
+			arcn->sb.st_dev = dpt->dev;
+			arcn->sb.st_ino = nino;
+			return(0);
+		}
+	} else {
+		/*
+		 * this device is not being remapped YET. if we do not have any
+		 * form of truncation, we do not need a remap
+		 */
+		if (!trc_ino && !trc_dev)
+			return(0);
+
+		/*
+		 * we have truncation, have to add this as a device to remap
+		 */
+		if ((pt = chk_dev(arcn->sb.st_dev, 1)) == NULL)
+			goto bad;
+
+		/*
+		 * if we just have a truncated inode, we have to make sure that
+		 * all future inodes that do not truncate (they have the
+		 * truncation pattern of all 0's) continue to map to the same
+		 * device number. We probably have already written inodes with
+		 * this device number to the archive with the truncation
+		 * pattern of all 0's. So we add the mapping for all 0's to the
+		 * same device number.
+		 */
+		if (!trc_dev && (trunc_bits != 0)) {
+			if ((dpt = (DLIST *)malloc(sizeof(DLIST))) == NULL)
+				goto bad;
+			dpt->trunc_bits = 0;
+			dpt->dev = arcn->sb.st_dev;
+			dpt->fow = pt->list;
+			pt->list = dpt;
+		}
+	}
+
+	/*
+	 * look for a device number not being used. We must watch for wrap
+	 * around on lastdev (so we do not get stuck looking forever!)
+	 */
+	while (++lastdev > 0) {
+		if (chk_dev(lastdev, 0) != NULL)
+			continue;
+		/*
+		 * found an unused value. If we have reached truncation point
+		 * for this format we are hosed, so we give up. Otherwise we
+		 * mark it as being used.
+		 */
+		if (((lastdev & ((dev_t)dev_mask)) != lastdev) ||
+		    (chk_dev(lastdev, 1) == NULL))
+			goto bad;
+		break;
+	}
+
+	if ((lastdev <= 0) || ((dpt = (DLIST *)malloc(sizeof(DLIST))) == NULL))
+		goto bad;
+
+	/*
+	 * got a new device number, store it under this truncation pattern.
+	 * change the device number this file is being stored with.
+	 */
+	dpt->trunc_bits = trunc_bits;
+	dpt->dev = lastdev;
+	dpt->fow = pt->list;
+	pt->list = dpt;
+	arcn->sb.st_dev = lastdev;
+	arcn->sb.st_ino = nino;
+	return(0);
+
+    bad:
+	paxwarn(1, "Unable to fix truncated inode/device field when storing %s",
+	    arcn->name);
+	paxwarn(0, "Archive may create improper hard links when extracted");
+	return(0);
+}
+
+/*
+ * directory access/mod time reset table routines (for directories READ by pax)
+ *
+ * The pax -t flag requires that access times of archive files to be the same
+ * before being read by pax. For regular files, access time is restored after
+ * the file has been copied. This database provides the same functionality for
+ * directories read during file tree traversal. Restoring directory access time
+ * is more complex than files since directories may be read several times until
+ * all the descendants in their subtree are visited by fts. Directory access
+ * and modification times are stored during the fts pre-order visit (done
+ * before any descendants in the subtree is visited) and restored after the
+ * fts post-order visit (after all the descendants have been visited). In the
+ * case of premature exit from a subtree (like from the effects of -n), any
+ * directory entries left in this database are reset during final cleanup
+ * operations of pax. Entries are hashed by inode number for fast lookup.
+ */
+
+/*
+ * atdir_start()
+ *	create the directory access time database for directories READ by pax.
+ * Return:
+ *	0 is created ok, -1 otherwise.
+ */
+
+int
+atdir_start(void)
+{
+	if (atab != NULL)
+		return(0);
+ 	if ((atab = (ATDIR **)calloc(A_TAB_SZ, sizeof(ATDIR *))) == NULL) {
+		paxwarn(1,"Cannot allocate space for directory access time table");
+		return(-1);
+	}
+	return(0);
+}
+
+
+/*
+ * atdir_end()
+ *	walk through the directory access time table and reset the access time
+ *	of any directory who still has an entry left in the database. These
+ *	entries are for directories READ by pax
+ */
+
+void
+atdir_end(void)
+{
+	ATDIR *pt;
+	int i;
+
+	if (atab == NULL)
+		return;
+	/*
+	 * for each non-empty hash table entry reset all the directories
+	 * chained there.
+	 */
+	for (i = 0; i < A_TAB_SZ; ++i) {
+		if ((pt = atab[i]) == NULL)
+			continue;
+		/*
+		 * remember to force the times, set_ftime() looks at pmtime
+		 * and patime, which only applies to things CREATED by pax,
+		 * not read by pax. Read time reset is controlled by -t.
+		 */
+		for (; pt != NULL; pt = pt->fow)
+			set_ftime(pt->name, pt->mtime, pt->atime, 1);
+	}
+}
+
+/*
+ * add_atdir()
+ *	add a directory to the directory access time table. Table is hashed
+ *	and chained by inode number. This is for directories READ by pax
+ */
+
+void
+add_atdir(char *fname, dev_t dev, ino_t ino, time_t mtime, time_t atime)
+{
+	ATDIR *pt;
+	u_int indx;
+
+	if (atab == NULL)
+		return;
+
+	/*
+	 * make sure this directory is not already in the table, if so just
+	 * return (the older entry always has the correct time). The only
+	 * way this will happen is when the same subtree can be traversed by
+	 * different args to pax and the -n option is aborting fts out of a
+	 * subtree before all the post-order visits have been made).
+	 */
+	indx = ((unsigned)ino) % A_TAB_SZ;
+	if ((pt = atab[indx]) != NULL) {
+		while (pt != NULL) {
+			if ((pt->ino == ino) && (pt->dev == dev))
+				break;
+			pt = pt->fow;
+		}
+
+		/*
+		 * oops, already there. Leave it alone.
+		 */
+		if (pt != NULL)
+			return;
+	}
+
+	/*
+	 * add it to the front of the hash chain
+	 */
+	if ((pt = (ATDIR *)malloc(sizeof(ATDIR))) != NULL) {
+		if ((pt->name = strdup(fname)) != NULL) {
+			pt->dev = dev;
+			pt->ino = ino;
+			pt->mtime = mtime;
+			pt->atime = atime;
+			pt->fow = atab[indx];
+			atab[indx] = pt;
+			return;
+		}
+		(void)free((char *)pt);
+	}
+
+	paxwarn(1, "Directory access time reset table ran out of memory");
+	return;
+}
+
+/*
+ * get_atdir()
+ *	look up a directory by inode and device number to obtain the access
+ *	and modification time you want to set to. If found, the modification
+ *	and access time parameters are set and the entry is removed from the
+ *	table (as it is no longer needed). These are for directories READ by
+ *	pax
+ * Return:
+ *	0 if found, -1 if not found.
+ */
+
+int
+get_atdir(dev_t dev, ino_t ino, time_t *mtime, time_t *atime)
+{
+	ATDIR *pt;
+	ATDIR **ppt;
+	u_int indx;
+
+	if (atab == NULL)
+		return(-1);
+	/*
+	 * hash by inode and search the chain for an inode and device match
+	 */
+	indx = ((unsigned)ino) % A_TAB_SZ;
+	if ((pt = atab[indx]) == NULL)
+		return(-1);
+
+	ppt = &(atab[indx]);
+	while (pt != NULL) {
+		if ((pt->ino == ino) && (pt->dev == dev))
+			break;
+		/*
+		 * no match, go to next one
+		 */
+		ppt = &(pt->fow);
+		pt = pt->fow;
+	}
+
+	/*
+	 * return if we did not find it.
+	 */
+	if (pt == NULL)
+		return(-1);
+
+	/*
+	 * found it. return the times and remove the entry from the table.
+	 */
+	*ppt = pt->fow;
+	*mtime = pt->mtime;
+	*atime = pt->atime;
+	(void)free((char *)pt->name);
+	(void)free((char *)pt);
+	return(0);
+}
+
+/*
+ * directory access mode and time storage routines (for directories CREATED
+ * by pax).
+ *
+ * Pax requires that extracted directories, by default, have their access/mod
+ * times and permissions set to the values specified in the archive. During the
+ * actions of extracting (and creating the destination subtree during -rw copy)
+ * directories extracted may be modified after being created. Even worse is
+ * that these directories may have been created with file permissions which
+ * prohibits any descendants of these directories from being extracted. When
+ * directories are created by pax, access rights may be added to permit the
+ * creation of files in their subtree. Every time pax creates a directory, the
+ * times and file permissions specified by the archive are stored. After all
+ * files have been extracted (or copied), these directories have their times
+ * and file modes reset to the stored values. The directory info is restored in
+ * reverse order as entries were added to the data file from root to leaf. To
+ * restore atime properly, we must go backwards. The data file consists of
+ * records with two parts, the file name followed by a DIRDATA trailer. The
+ * fixed sized trailer contains the size of the name plus the off_t location in
+ * the file. To restore we work backwards through the file reading the trailer
+ * then the file name.
+ */
+
+/*
+ * dir_start()
+ *	set up the directory time and file mode storage for directories CREATED
+ *	by pax.
+ * Return:
+ *	0 if ok, -1 otherwise
+ */
+
+int
+dir_start(void)
+{
+
+	if (dirfd != -1)
+		return(0);
+
+	/*
+	 * unlink the file so it goes away at termination by itself
+	 */
+	memcpy(tempbase, _TFILE_BASE, sizeof(_TFILE_BASE));
+	if ((dirfd = mkstemp(tempfile)) >= 0) {
+		(void)unlink(tempfile);
+		return(0);
+	}
+	paxwarn(1, "Unable to create temporary file for directory times: %s",
+	    tempfile);
+	return(-1);
+}
+
+/*
+ * add_dir()
+ *	add the mode and times for a newly CREATED directory
+ *	name is name of the directory, psb the stat buffer with the data in it,
+ *	frc_mode is a flag that says whether to force the setting of the mode
+ *	(ignoring the user set values for preserving file mode). Frc_mode is
+ *	for the case where we created a file and found that the resulting
+ *	directory was not writeable and the user asked for file modes to NOT
+ *	be preserved. (we have to preserve what was created by default, so we
+ *	have to force the setting at the end. this is stated explicitly in the
+ *	pax spec)
+ */
+
+void
+add_dir(char *name, int nlen, struct stat *psb, int frc_mode)
+{
+	DIRDATA dblk;
+
+	if (dirfd < 0)
+		return;
+
+	/*
+	 * get current position (where file name will start) so we can store it
+	 * in the trailer
+	 */
+	if ((dblk.npos = lseek(dirfd, 0L, SEEK_CUR)) < 0) {
+		paxwarn(1,"Unable to store mode and times for directory: %s",name);
+		return;
+	}
+
+	/*
+	 * write the file name followed by the trailer
+	 */
+	dblk.nlen = nlen + 1;
+	dblk.mode = psb->st_mode & 0xffff;
+	dblk.mtime = psb->st_mtime;
+	dblk.atime = psb->st_atime;
+	dblk.frc_mode = frc_mode;
+	if ((write(dirfd, name, dblk.nlen) == dblk.nlen) &&
+	    (write(dirfd, (char *)&dblk, sizeof(dblk)) == sizeof(dblk))) {
+		++dircnt;
+		return;
+	}
+
+	paxwarn(1,"Unable to store mode and times for created directory: %s",name);
+	return;
+}
+
+/*
+ * proc_dir()
+ *	process all file modes and times stored for directories CREATED
+ *	by pax
+ */
+
+void
+proc_dir(void)
+{
+	char name[PAXPATHLEN+1];
+	DIRDATA dblk;
+	u_long cnt;
+
+	if (dirfd < 0)
+		return;
+	/*
+	 * read backwards through the file and process each directory
+	 */
+	for (cnt = 0; cnt < dircnt; ++cnt) {
+		/*
+		 * read the trailer, then the file name, if this fails
+		 * just give up.
+		 */
+		if (lseek(dirfd, -((off_t)sizeof(dblk)), SEEK_CUR) < 0)
+			break;
+		if (read(dirfd,(char *)&dblk, sizeof(dblk)) != sizeof(dblk))
+			break;
+		if (lseek(dirfd, dblk.npos, SEEK_SET) < 0)
+			break;
+		if (read(dirfd, name, dblk.nlen) != dblk.nlen)
+			break;
+		if (lseek(dirfd, dblk.npos, SEEK_SET) < 0)
+			break;
+
+		/*
+		 * frc_mode set, make sure we set the file modes even if
+		 * the user didn't ask for it (see file_subs.c for more info)
+		 */
+		if (pmode || dblk.frc_mode)
+			set_pmode(name, dblk.mode);
+		if (patime || pmtime)
+			set_ftime(name, dblk.mtime, dblk.atime, 0);
+	}
+
+	(void)close(dirfd);
+	dirfd = -1;
+	if (cnt != dircnt)
+		paxwarn(1,"Unable to set mode and times for created directories");
+	return;
+}
+
+/*
+ * database independent routines
+ */
+
+/*
+ * st_hash()
+ *	hashes filenames to a u_int for hashing into a table. Looks at the tail
+ *	end of file, as this provides far better distribution than any other
+ *	part of the name. For performance reasons we only care about the last
+ *	MAXKEYLEN chars (should be at LEAST large enough to pick off the file
+ *	name). Was tested on 500,000 name file tree traversal from the root
+ *	and gave almost a perfectly uniform distribution of keys when used with
+ *	prime sized tables (MAXKEYLEN was 128 in test). Hashes (sizeof int)
+ *	chars at a time and pads with 0 for last addition.
+ * Return:
+ *	the hash value of the string MOD (%) the table size.
+ */
+
+u_int
+st_hash(char *name, int len, int tabsz)
+{
+	char *pt;
+	char *dest;
+	char *end;
+	int i;
+	u_int key = 0;
+	int steps;
+	int res;
+	u_int val;
+
+	/*
+	 * only look at the tail up to MAXKEYLEN, we do not need to waste
+	 * time here (remember these are pathnames, the tail is what will
+	 * spread out the keys)
+	 */
+	if (len > MAXKEYLEN) {
+		pt = &(name[len - MAXKEYLEN]);
+		len = MAXKEYLEN;
+	} else
+		pt = name;
+
+	/*
+	 * calculate the number of u_int size steps in the string and if
+	 * there is a runt to deal with
+	 */
+	steps = len/sizeof(u_int);
+	res = len % sizeof(u_int);
+
+	/*
+	 * add up the value of the string in unsigned integer sized pieces
+	 * too bad we cannot have unsigned int aligned strings, then we
+	 * could avoid the expensive copy.
+	 */
+	for (i = 0; i < steps; ++i) {
+		end = pt + sizeof(u_int);
+		dest = (char *)&val;
+		while (pt < end)
+			*dest++ = *pt++;
+		key += val;
+	}
+
+	/*
+	 * add in the runt padded with zero to the right
+	 */
+	if (res) {
+		val = 0;
+		end = pt + res;
+		dest = (char *)&val;
+		while (pt < end)
+			*dest++ = *pt++;
+		key += val;
+	}
+
+	/*
+	 * return the result mod the table size
+	 */
+	return(key % tabsz);
+}
Index: /trunk/minix/commands/pax/tables.h
===================================================================
--- /trunk/minix/commands/pax/tables.h	(revision 9)
+++ /trunk/minix/commands/pax/tables.h	(revision 9)
@@ -0,0 +1,169 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)tables.h	8.1 (Berkeley) 5/31/93
+ * $FreeBSD: src/bin/pax/tables.h,v 1.10 2004/04/06 20:06:48 markm Exp $
+ */
+
+/*
+ * data structures and constants used by the different databases kept by pax
+ */
+
+/*
+ * Hash Table Sizes MUST BE PRIME, if set too small performance suffers.
+ * Probably safe to expect 500000 inodes per tape. Assuming good key
+ * distribution (inodes) chains of under 50 long (worse case) is ok.
+ */
+#define L_TAB_SZ	2503		/* hard link hash table size */
+#define F_TAB_SZ	50503		/* file time hash table size */
+#define N_TAB_SZ	541		/* interactive rename hash table */
+#define D_TAB_SZ	317		/* unique device mapping table */
+#define A_TAB_SZ	317		/* ftree dir access time reset table */
+#define MAXKEYLEN	64		/* max number of chars for hash */
+
+/*
+ * file hard link structure (hashed by dev/ino and chained) used to find the
+ * hard links in a file system or with some archive formats (cpio)
+ */
+typedef struct hrdlnk {
+	char		*name;	/* name of first file seen with this ino/dev */
+	dev_t		dev;	/* files device number */
+	ino_t		ino;	/* files inode number */
+	u_long		nlink;	/* expected link count */
+	struct hrdlnk	*fow;
+} HRDLNK;
+
+/*
+ * Archive write update file time table (the -u, -C flag), hashed by filename.
+ * Filenames are stored in a scratch file at seek offset into the file. The
+ * file time (mod time) and the file name length (for a quick check) are
+ * stored in a hash table node. We were forced to use a scratch file because
+ * with -u, the mtime for every node in the archive must always be available
+ * to compare against (and this data can get REALLY large with big archives).
+ * By being careful to read only when we have a good chance of a match, the
+ * performance loss is not measurable (and the size of the archive we can
+ * handle is greatly increased).
+ */
+typedef struct ftm {
+	int		namelen;	/* file name length */
+	time_t		mtime;		/* files last modification time */
+	off_t		seek;		/* location in scratch file */
+	struct ftm	*fow;
+} FTM;
+
+/*
+ * Interactive rename table (-i flag), hashed by orig filename.
+ * We assume this will not be a large table as this mapping data can only be
+ * obtained through interactive input by the user. Nobody is going to type in
+ * changes for 500000 files? We use chaining to resolve collisions.
+ */
+
+typedef struct namt {
+	char		*oname;		/* old name */
+	char		*nname;		/* new name typed in by the user */
+	struct namt	*fow;
+} NAMT;
+
+/*
+ * Unique device mapping tables. Some protocols (e.g. cpio) require that the
+ * <c_dev,c_ino> pair will uniquely identify a file in an archive unless they
+ * are links to the same file. Appending to archives can break this. For those
+ * protocols that have this requirement we map c_dev to a unique value not seen
+ * in the archive when we append. We also try to handle inode truncation with
+ * this table. (When the inode field in the archive header are too small, we
+ * remap the dev on writes to remove accidental collisions).
+ *
+ * The list is hashed by device number using chain collision resolution. Off of
+ * each DEVT are linked the various remaps for this device based on those bits
+ * in the inode which were truncated. For example if we are just remapping to
+ * avoid a device number during an update append, off the DEVT we would have
+ * only a single DLIST that has a truncation id of 0 (no inode bits were
+ * stripped for this device so far). When we spot inode truncation we create
+ * a new mapping based on the set of bits in the inode which were stripped off.
+ * so if the top four bits of the inode are stripped and they have a pattern of
+ * 0110...... (where . are those bits not truncated) we would have a mapping
+ * assigned for all inodes that has the same 0110.... pattern (with this dev
+ * number of course). This keeps the mapping sparse and should be able to store
+ * close to the limit of files which can be represented by the optimal
+ * combination of dev and inode bits, and without creating a fouled up archive.
+ * Note we also remap truncated devs in the same way (an exercise for the
+ * dedicated reader; always wanted to say that...:)
+ */
+
+typedef struct devt {
+	dev_t		dev;	/* the orig device number we now have to map */
+	struct devt	*fow;	/* new device map list */
+	struct dlist	*list;	/* map list based on inode truncation bits */
+} DEVT;
+
+typedef struct dlist {
+	ino_t trunc_bits;	/* truncation pattern for a specific map */
+	dev_t dev;		/* the new device id we use */
+	struct dlist *fow;
+} DLIST;
+
+/*
+ * ftree directory access time reset table. When we are done with with a
+ * subtree we reset the access and mod time of the directory when the tflag is
+ * set. Not really explicitly specified in the pax spec, but easy and fast to
+ * do (and this may have even been intended in the spec, it is not clear).
+ * table is hashed by inode with chaining.
+ */
+
+typedef struct atdir {
+	char *name;	/* name of directory to reset */
+	dev_t dev;	/* dev and inode for fast lookup */
+	ino_t ino;
+	time_t mtime;	/* access and mod time to reset to */
+	time_t atime;
+	struct atdir *fow;
+} ATDIR;
+
+/*
+ * created directory time and mode storage entry. After pax is finished during
+ * extraction or copy, we must reset directory access modes and times that
+ * may have been modified after creation (they no longer have the specified
+ * times and/or modes). We must reset time in the reverse order of creation,
+ * because entries are added  from the top of the file tree to the bottom.
+ * We MUST reset times from leaf to root (it will not work the other
+ * direction).  Entries are recorded into a spool file to make reverse
+ * reading faster.
+ */
+
+typedef struct dirdata {
+	int nlen;	/* length of the directory name (includes \0) */
+	off_t npos;	/* position in file where this dir name starts */
+	mode_t mode;	/* file mode to restore */
+	time_t mtime;	/* mtime to set */
+	time_t atime;	/* atime to set */
+	int frc_mode;	/* do we force mode settings? */
+} DIRDATA;
Index: /trunk/minix/commands/pax/tar.c
===================================================================
--- /trunk/minix/commands/pax/tar.c	(revision 9)
+++ /trunk/minix/commands/pax/tar.c	(revision 9)
@@ -0,0 +1,1121 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)tar.c	8.2 (Berkeley) 4/18/94";
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "pax.h"
+#include "extern.h"
+#include "tar.h"
+
+/*
+ * Routines for reading, writing and header identify of various versions of tar
+ */
+
+static u_long tar_chksm(char *, int);
+static char *name_split(char *, int);
+static int ul_oct(u_long, char *, int, int);
+#ifndef NET2_STAT
+static int uqd_oct(u_quad_t, char *, int, int);
+#endif
+
+/*
+ * Routines common to all versions of tar
+ */
+
+static int tar_nodir;			/* do not write dirs under old tar */
+
+/*
+ * tar_endwr()
+ *	add the tar trailer of two null blocks
+ * Return:
+ *	0 if ok, -1 otherwise (what wr_skip returns)
+ */
+
+int
+tar_endwr(void)
+{
+	return(wr_skip((off_t)(NULLCNT*BLKMULT)));
+}
+
+/*
+ * tar_endrd()
+ *	no cleanup needed here, just return size of trailer (for append)
+ * Return:
+ *	size of trailer (2 * BLKMULT)
+ */
+
+off_t
+tar_endrd(void)
+{
+	return((off_t)(NULLCNT*BLKMULT));
+}
+
+/*
+ * tar_trail()
+ *	Called to determine if a header block is a valid trailer. We are passed
+ *	the block, the in_sync flag (which tells us we are in resync mode;
+ *	looking for a valid header), and cnt (which starts at zero) which is
+ *	used to count the number of empty blocks we have seen so far.
+ * Return:
+ *	0 if a valid trailer, -1 if not a valid trailer, or 1 if the block
+ *	could never contain a header.
+ */
+
+int
+tar_trail(char *buf, int in_resync, int *cnt)
+{
+	int i;
+
+	/*
+	 * look for all zero, trailer is two consecutive blocks of zero
+	 */
+	for (i = 0; i < BLKMULT; ++i) {
+		if (buf[i] != '\0')
+			break;
+	}
+
+	/*
+	 * if not all zero it is not a trailer, but MIGHT be a header.
+	 */
+	if (i != BLKMULT)
+		return(-1);
+
+	/*
+	 * When given a zero block, we must be careful!
+	 * If we are not in resync mode, check for the trailer. Have to watch
+	 * out that we do not mis-identify file data as the trailer, so we do
+	 * NOT try to id a trailer during resync mode. During resync mode we
+	 * might as well throw this block out since a valid header can NEVER be
+	 * a block of all 0 (we must have a valid file name).
+	 */
+	if (!in_resync && (++*cnt >= NULLCNT))
+		return(0);
+	return(1);
+}
+
+/*
+ * ul_oct()
+ *	convert an unsigned long to an octal string. many oddball field
+ *	termination characters are used by the various versions of tar in the
+ *	different fields. term selects which kind to use. str is '0' padded
+ *	at the front to len. we are unable to use only one format as many old
+ *	tar readers are very cranky about this.
+ * Return:
+ *	0 if the number fit into the string, -1 otherwise
+ */
+
+static int
+ul_oct(u_long val, char *str, int len, int term)
+{
+	char *pt;
+
+	/*
+	 * term selects the appropriate character(s) for the end of the string
+	 */
+	pt = str + len - 1;
+	switch(term) {
+	case 3:
+		*pt-- = '\0';
+		break;
+	case 2:
+		*pt-- = ' ';
+		*pt-- = '\0';
+		break;
+	case 1:
+		*pt-- = ' ';
+		break;
+	case 0:
+	default:
+		*pt-- = '\0';
+		*pt-- = ' ';
+		break;
+	}
+
+	/*
+	 * convert and blank pad if there is space
+	 */
+	while (pt >= str) {
+		*pt-- = '0' + (char)(val & 0x7);
+		if ((val = val >> 3) == (u_long)0)
+			break;
+	}
+
+	while (pt >= str)
+		*pt-- = '0';
+	if (val != (u_long)0)
+		return(-1);
+	return(0);
+}
+
+#ifndef NET2_STAT
+/*
+ * uqd_oct()
+ *	convert an u_quad_t to an octal string. one of many oddball field
+ *	termination characters are used by the various versions of tar in the
+ *	different fields. term selects which kind to use. str is '0' padded
+ *	at the front to len. we are unable to use only one format as many old
+ *	tar readers are very cranky about this.
+ * Return:
+ *	0 if the number fit into the string, -1 otherwise
+ */
+
+static int
+uqd_oct(u_quad_t val, char *str, int len, int term)
+{
+	char *pt;
+
+	/*
+	 * term selects the appropriate character(s) for the end of the string
+	 */
+	pt = str + len - 1;
+	switch(term) {
+	case 3:
+		*pt-- = '\0';
+		break;
+	case 2:
+		*pt-- = ' ';
+		*pt-- = '\0';
+		break;
+	case 1:
+		*pt-- = ' ';
+		break;
+	case 0:
+	default:
+		*pt-- = '\0';
+		*pt-- = ' ';
+		break;
+	}
+
+	/*
+	 * convert and blank pad if there is space
+	 */
+	while (pt >= str) {
+		*pt-- = '0' + (char)(val & 0x7);
+		if ((val = val >> 3) == 0)
+			break;
+	}
+
+	while (pt >= str)
+		*pt-- = '0';
+	if (val != (u_quad_t)0)
+		return(-1);
+	return(0);
+}
+#endif
+
+/*
+ * tar_chksm()
+ *	calculate the checksum for a tar block counting the checksum field as
+ *	all blanks (BLNKSUM is that value pre-calculated, the sum of 8 blanks).
+ *	NOTE: we use len to short circuit summing 0's on write since we ALWAYS
+ *	pad headers with 0.
+ * Return:
+ *	unsigned long checksum
+ */
+
+static u_long
+tar_chksm(char *blk, int len)
+{
+	char *stop;
+	char *pt;
+	u_long chksm = BLNKSUM;	/* initial value is checksum field sum */
+
+	/*
+	 * add the part of the block before the checksum field
+	 */
+	pt = blk;
+	stop = blk + CHK_OFFSET;
+	while (pt < stop)
+		chksm += (u_long)(*pt++ & 0xff);
+	/*
+	 * move past the checksum field and keep going, spec counts the
+	 * checksum field as the sum of 8 blanks (which is pre-computed as
+	 * BLNKSUM).
+	 * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding
+	 * starts, no point in summing zero's)
+	 */
+	pt += CHK_LEN;
+	stop = blk + len;
+	while (pt < stop)
+		chksm += (u_long)(*pt++ & 0xff);
+	return(chksm);
+}
+
+/*
+ * Routines for old BSD style tar (also made portable to sysV tar)
+ */
+
+/*
+ * tar_id()
+ *	determine if a block given to us is a valid tar header (and not a USTAR
+ *	header). We have to be on the lookout for those pesky blocks of	all
+ *	zero's.
+ * Return:
+ *	0 if a tar header, -1 otherwise
+ */
+
+int
+tar_id(char *blk, int size)
+{
+	HD_TAR *hd;
+	HD_USTAR *uhd;
+
+	if (size < BLKMULT)
+		return(-1);
+	hd = (HD_TAR *)blk;
+	uhd = (HD_USTAR *)blk;
+
+	/*
+	 * check for block of zero's first, a simple and fast test, then make
+	 * sure this is not a ustar header by looking for the ustar magic
+	 * cookie. We should use TMAGLEN, but some USTAR archive programs are
+	 * wrong and create archives missing the \0. Last we check the
+	 * checksum. If this is ok we have to assume it is a valid header.
+	 */
+	if (hd->name[0] == '\0')
+		return(-1);
+	if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0)
+		return(-1);
+	if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
+		return(-1);
+	return(0);
+}
+
+/*
+ * tar_opt()
+ *	handle tar format specific -o options
+ * Return:
+ *	0 if ok -1 otherwise
+ */
+
+int
+tar_opt(void)
+{
+	OPLIST *opt;
+
+	while ((opt = opt_next()) != NULL) {
+		if (strcmp(opt->name, TAR_OPTION) ||
+		    strcmp(opt->value, TAR_NODIR)) {
+			paxwarn(1, "Unknown tar format -o option/value pair %s=%s",
+			    opt->name, opt->value);
+			paxwarn(1,"%s=%s is the only supported tar format option",
+			    TAR_OPTION, TAR_NODIR);
+			return(-1);
+		}
+
+		/*
+		 * we only support one option, and only when writing
+		 */
+		if ((act != APPND) && (act != ARCHIVE)) {
+			paxwarn(1, "%s=%s is only supported when writing.",
+			    opt->name, opt->value);
+			return(-1);
+		}
+		tar_nodir = 1;
+	}
+	return(0);
+}
+
+
+/*
+ * tar_rd()
+ *	extract the values out of block already determined to be a tar header.
+ *	store the values in the ARCHD parameter.
+ * Return:
+ *	0
+ */
+
+int
+tar_rd(ARCHD *arcn, char *buf)
+{
+	HD_TAR *hd;
+	char *pt;
+
+	/*
+	 * we only get proper sized buffers passed to us
+	 */
+	if (tar_id(buf, BLKMULT) < 0)
+		return(-1);
+	arcn->org_name = arcn->name;
+	arcn->sb.st_nlink = 1;
+	arcn->pat = NULL;
+
+	/*
+	 * copy out the name and values in the stat buffer
+	 */
+	hd = (HD_TAR *)buf;
+	/*
+	 * old tar format specifies the name always be null-terminated,
+	 * but let's be robust to broken archives.
+	 * the same applies to handling links below.
+	 */
+	arcn->nlen = l_strncpy(arcn->name, hd->name,
+	    MIN(sizeof(hd->name), sizeof(arcn->name)) - 1);
+	arcn->name[arcn->nlen] = '\0';
+	arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) &
+	    0xfff);
+	arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
+	arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
+#ifdef NET2_STAT
+	arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+	arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
+#else
+	arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
+	arcn->sb.st_mtime = (time_t)asc_uqd(hd->mtime, sizeof(hd->mtime), OCT);
+#endif
+	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
+
+	/*
+	 * have to look at the last character, it may be a '/' and that is used
+	 * to encode this as a directory
+	 */
+	pt = &(arcn->name[arcn->nlen - 1]);
+	arcn->pad = 0;
+	arcn->skip = 0;
+	switch(hd->linkflag) {
+	case SYMTYPE:
+		/*
+		 * symbolic link, need to get the link name and set the type in
+		 * the st_mode so -v printing will look correct.
+		 */
+		arcn->type = PAX_SLK;
+		arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
+		    MIN(sizeof(hd->linkname), sizeof(arcn->ln_name)) - 1);
+		arcn->ln_name[arcn->ln_nlen] = '\0';
+		arcn->sb.st_mode |= S_IFLNK;
+		break;
+	case LNKTYPE:
+		/*
+		 * hard link, need to get the link name, set the type in the
+		 * st_mode and st_nlink so -v printing will look better.
+		 */
+		arcn->type = PAX_HLK;
+		arcn->sb.st_nlink = 2;
+		arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
+		    MIN(sizeof(hd->linkname), sizeof(arcn->ln_name)) - 1);
+		arcn->ln_name[arcn->ln_nlen] = '\0';
+
+		/*
+		 * no idea of what type this thing really points at, but
+		 * we set something for printing only.
+		 */
+		arcn->sb.st_mode |= S_IFREG;
+		break;
+	case DIRTYPE:
+		/*
+		 * It is a directory, set the mode for -v printing
+		 */
+		arcn->type = PAX_DIR;
+		arcn->sb.st_mode |= S_IFDIR;
+		arcn->sb.st_nlink = 2;
+		arcn->ln_name[0] = '\0';
+		arcn->ln_nlen = 0;
+		break;
+	case AREGTYPE:
+	case REGTYPE:
+	default:
+		/*
+		 * If we have a trailing / this is a directory and NOT a file.
+		 */
+		arcn->ln_name[0] = '\0';
+		arcn->ln_nlen = 0;
+		if (*pt == '/') {
+			/*
+			 * it is a directory, set the mode for -v printing
+			 */
+			arcn->type = PAX_DIR;
+			arcn->sb.st_mode |= S_IFDIR;
+			arcn->sb.st_nlink = 2;
+		} else {
+			/*
+			 * have a file that will be followed by data. Set the
+			 * skip value to the size field and calculate the size
+			 * of the padding.
+			 */
+			arcn->type = PAX_REG;
+			arcn->sb.st_mode |= S_IFREG;
+			arcn->pad = TAR_PAD(arcn->sb.st_size);
+			arcn->skip = arcn->sb.st_size;
+		}
+		break;
+	}
+
+	/*
+	 * strip off any trailing slash.
+	 */
+	if (*pt == '/') {
+		*pt = '\0';
+		--arcn->nlen;
+	}
+	return(0);
+}
+
+/*
+ * tar_wr()
+ *	write a tar header for the file specified in the ARCHD to the archive.
+ *	Have to check for file types that cannot be stored and file names that
+ *	are too long. Be careful of the term (last arg) to ul_oct, each field
+ *	of tar has it own spec for the termination character(s).
+ *	ASSUMED: space after header in header block is zero filled
+ * Return:
+ *	0 if file has data to be written after the header, 1 if file has NO
+ *	data to write after the header, -1 if archive write failed
+ */
+
+int
+tar_wr(ARCHD *arcn)
+{
+	HD_TAR *hd;
+	int len;
+	char hdblk[sizeof(HD_TAR)];
+
+	/*
+	 * check for those file system types which tar cannot store
+	 */
+	switch(arcn->type) {
+	case PAX_DIR:
+		/*
+		 * user asked that dirs not be written to the archive
+		 */
+		if (tar_nodir)
+			return(1);
+		break;
+	case PAX_CHR:
+		paxwarn(1, "Tar cannot archive a character device %s",
+		    arcn->org_name);
+		return(1);
+	case PAX_BLK:
+		paxwarn(1, "Tar cannot archive a block device %s", arcn->org_name);
+		return(1);
+	case PAX_SCK:
+		paxwarn(1, "Tar cannot archive a socket %s", arcn->org_name);
+		return(1);
+	case PAX_FIF:
+		paxwarn(1, "Tar cannot archive a fifo %s", arcn->org_name);
+		return(1);
+	case PAX_SLK:
+	case PAX_HLK:
+	case PAX_HRG:
+		if (arcn->ln_nlen >= (int)sizeof(hd->linkname)) {
+			paxwarn(1,"Link name too long for tar %s", arcn->ln_name);
+			return(1);
+		}
+		break;
+	case PAX_REG:
+	case PAX_CTG:
+	default:
+		break;
+	}
+
+	/*
+	 * check file name len, remember extra char for dirs (the / at the end)
+	 */
+	len = arcn->nlen;
+	if (arcn->type == PAX_DIR)
+		++len;
+	if (len >= (int)sizeof(hd->name)) {
+		paxwarn(1, "File name too long for tar %s", arcn->name);
+		return(1);
+	}
+
+	/*
+	 * copy the data out of the ARCHD into the tar header based on the type
+	 * of the file. Remember many tar readers want the unused fields to be
+	 * padded with zero. We set the linkflag field (type), the linkname
+	 * (or zero if not used),the size, and set the padding (if any) to be
+	 * added after the file data (0 for all other types, as they only have
+	 * a header)
+	 */
+	hd = (HD_TAR *)hdblk;
+	l_strncpy(hd->name, arcn->name, sizeof(hd->name) - 1);
+	hd->name[sizeof(hd->name) - 1] = '\0';
+	arcn->pad = 0;
+
+	if (arcn->type == PAX_DIR) {
+		/*
+		 * directories are the same as files, except have a filename
+		 * that ends with a /, we add the slash here. No data follows,
+		 * dirs, so no pad.
+		 */
+		hd->linkflag = AREGTYPE;
+		memset(hd->linkname, 0, sizeof(hd->linkname));
+		hd->name[len-1] = '/';
+		if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
+			goto out;
+	} else if (arcn->type == PAX_SLK) {
+		/*
+		 * no data follows this file, so no pad
+		 */
+		hd->linkflag = SYMTYPE;
+		l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
+		hd->linkname[sizeof(hd->linkname) - 1] = '\0';
+		if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
+			goto out;
+	} else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
+		/*
+		 * no data follows this file, so no pad
+		 */
+		hd->linkflag = LNKTYPE;
+		l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
+		hd->linkname[sizeof(hd->linkname) - 1] = '\0';
+		if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
+			goto out;
+	} else {
+		/*
+		 * data follows this file, so set the pad
+		 */
+		hd->linkflag = AREGTYPE;
+		memset(hd->linkname, 0, sizeof(hd->linkname));
+#		ifdef NET2_STAT
+		if (ul_oct((u_long)arcn->sb.st_size, hd->size,
+		    sizeof(hd->size), 1)) {
+#		else
+		if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
+		    sizeof(hd->size), 1)) {
+#		endif
+			paxwarn(1,"File is too large for tar %s", arcn->org_name);
+			return(1);
+		}
+		arcn->pad = TAR_PAD(arcn->sb.st_size);
+	}
+
+	/*
+	 * copy those fields that are independent of the type
+	 */
+	if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) ||
+	    ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) ||
+	    ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) ||
+	    ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1))
+		goto out;
+
+	/*
+	 * calculate and add the checksum, then write the header. A return of
+	 * 0 tells the caller to now write the file data, 1 says no data needs
+	 * to be written
+	 */
+	if (ul_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum,
+	    sizeof(hd->chksum), 3))
+		goto out;
+	if (wr_rdbuf(hdblk, sizeof(HD_TAR)) < 0)
+		return(-1);
+	if (wr_skip((off_t)(BLKMULT - sizeof(HD_TAR))) < 0)
+		return(-1);
+	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
+		return(0);
+	return(1);
+
+    out:
+	/*
+	 * header field is out of range
+	 */
+	paxwarn(1, "Tar header field is too small for %s", arcn->org_name);
+	return(1);
+}
+
+/*
+ * Routines for POSIX ustar
+ */
+
+/*
+ * ustar_strd()
+ *	initialization for ustar read
+ * Return:
+ *	0 if ok, -1 otherwise
+ */
+
+int
+ustar_strd(void)
+{
+	if ((usrtb_start() < 0) || (grptb_start() < 0))
+		return(-1);
+	return(0);
+}
+
+/*
+ * ustar_stwr()
+ *	initialization for ustar write
+ * Return:
+ *	0 if ok, -1 otherwise
+ */
+
+int
+ustar_stwr(void)
+{
+	if ((uidtb_start() < 0) || (gidtb_start() < 0))
+		return(-1);
+	return(0);
+}
+
+/*
+ * ustar_id()
+ *	determine if a block given to us is a valid ustar header. We have to
+ *	be on the lookout for those pesky blocks of all zero's
+ * Return:
+ *	0 if a ustar header, -1 otherwise
+ */
+
+int
+ustar_id(char *blk, int size)
+{
+	HD_USTAR *hd;
+
+	if (size < BLKMULT)
+		return(-1);
+	hd = (HD_USTAR *)blk;
+
+	/*
+	 * check for block of zero's first, a simple and fast test then check
+	 * ustar magic cookie. We should use TMAGLEN, but some USTAR archive
+	 * programs are fouled up and create archives missing the \0. Last we
+	 * check the checksum. If ok we have to assume it is a valid header.
+	 */
+	if (hd->name[0] == '\0')
+		return(-1);
+	if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0)
+		return(-1);
+	if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
+		return(-1);
+	return(0);
+}
+
+/*
+ * ustar_rd()
+ *	extract the values out of block already determined to be a ustar header.
+ *	store the values in the ARCHD parameter.
+ * Return:
+ *	0
+ */
+
+int
+ustar_rd(ARCHD *arcn, char *buf)
+{
+	HD_USTAR *hd;
+	char *dest;
+	int cnt = 0;
+	dev_t devmajor;
+	dev_t devminor;
+
+	/*
+	 * we only get proper sized buffers
+	 */
+	if (ustar_id(buf, BLKMULT) < 0)
+		return(-1);
+	arcn->org_name = arcn->name;
+	arcn->sb.st_nlink = 1;
+	arcn->pat = NULL;
+	arcn->nlen = 0;
+	hd = (HD_USTAR *)buf;
+
+	/*
+	 * see if the filename is split into two parts. if, so joint the parts.
+	 * we copy the prefix first and add a / between the prefix and name.
+	 */
+	dest = arcn->name;
+	if (*(hd->prefix) != '\0') {
+		cnt = l_strncpy(dest, hd->prefix,
+		    MIN(sizeof(hd->prefix), sizeof(arcn->name) - 2));
+		dest += cnt;
+		*dest++ = '/';
+		cnt++;
+	}
+	/*
+	 * ustar format specifies the name may be unterminated
+	 * if it fills the entire field.  this also applies to
+	 * the prefix and the linkname.
+	 */
+	arcn->nlen = cnt + l_strncpy(dest, hd->name,
+	    MIN(sizeof(hd->name), sizeof(arcn->name) - cnt - 1));
+	arcn->name[arcn->nlen] = '\0';
+
+	/*
+	 * follow the spec to the letter. we should only have mode bits, strip
+	 * off all other crud we may be passed.
+	 */
+	arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) &
+	    0xfff);
+#ifdef NET2_STAT
+	arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+	arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
+#else
+	arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
+	arcn->sb.st_mtime = (time_t)asc_uqd(hd->mtime, sizeof(hd->mtime), OCT);
+#endif
+	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
+
+	/*
+	 * If we can find the ascii names for gname and uname in the password
+	 * and group files we will use the uid's and gid they bind. Otherwise
+	 * we use the uid and gid values stored in the header. (This is what
+	 * the POSIX spec wants).
+	 */
+	hd->gname[sizeof(hd->gname) - 1] = '\0';
+	if (gid_name((char *) hd->gname, (gid_t *) &(arcn->sb.st_gid)) < 0)
+		arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
+	hd->uname[sizeof(hd->uname) - 1] = '\0';
+	if (uid_name(hd->uname, &(arcn->sb.st_uid)) < 0)
+		arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
+
+	/*
+	 * set the defaults, these may be changed depending on the file type
+	 */
+	arcn->ln_name[0] = '\0';
+	arcn->ln_nlen = 0;
+	arcn->pad = 0;
+	arcn->skip = 0;
+	arcn->sb.st_rdev = (dev_t)0;
+
+	/*
+	 * set the mode and PAX type according to the typeflag in the header
+	 */
+	switch(hd->typeflag) {
+	case FIFOTYPE:
+		arcn->type = PAX_FIF;
+		arcn->sb.st_mode |= S_IFIFO;
+		break;
+	case DIRTYPE:
+		arcn->type = PAX_DIR;
+		arcn->sb.st_mode |= S_IFDIR;
+		arcn->sb.st_nlink = 2;
+
+		/*
+		 * Some programs that create ustar archives append a '/'
+		 * to the pathname for directories. This clearly violates
+		 * ustar specs, but we will silently strip it off anyway.
+		 */
+		if (arcn->name[arcn->nlen - 1] == '/')
+			arcn->name[--arcn->nlen] = '\0';
+		break;
+	case BLKTYPE:
+	case CHRTYPE:
+		/*
+		 * this type requires the rdev field to be set.
+		 */
+		if (hd->typeflag == BLKTYPE) {
+			arcn->type = PAX_BLK;
+			arcn->sb.st_mode |= S_IFBLK;
+		} else {
+			arcn->type = PAX_CHR;
+			arcn->sb.st_mode |= S_IFCHR;
+		}
+		devmajor = (dev_t)asc_ul(hd->devmajor,sizeof(hd->devmajor),OCT);
+		devminor = (dev_t)asc_ul(hd->devminor,sizeof(hd->devminor),OCT);
+		arcn->sb.st_rdev = TODEV(devmajor, devminor);
+		break;
+	case SYMTYPE:
+	case LNKTYPE:
+		if (hd->typeflag == SYMTYPE) {
+			arcn->type = PAX_SLK;
+			arcn->sb.st_mode |= S_IFLNK;
+		} else {
+			arcn->type = PAX_HLK;
+			/*
+			 * so printing looks better
+			 */
+			arcn->sb.st_mode |= S_IFREG;
+			arcn->sb.st_nlink = 2;
+		}
+		/*
+		 * copy the link name
+		 */
+		arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
+		    MIN(sizeof(hd->linkname), sizeof(arcn->ln_name) - 1));
+		arcn->ln_name[arcn->ln_nlen] = '\0';
+		break;
+	case CONTTYPE:
+	case AREGTYPE:
+	case REGTYPE:
+	default:
+		/*
+		 * these types have file data that follows. Set the skip and
+		 * pad fields.
+		 */
+		arcn->type = PAX_REG;
+		arcn->pad = TAR_PAD(arcn->sb.st_size);
+		arcn->skip = arcn->sb.st_size;
+		arcn->sb.st_mode |= S_IFREG;
+		break;
+	}
+	return(0);
+}
+
+/*
+ * ustar_wr()
+ *	write a ustar header for the file specified in the ARCHD to the archive
+ *	Have to check for file types that cannot be stored and file names that
+ *	are too long. Be careful of the term (last arg) to ul_oct, we only use
+ *	'\0' for the termination character (this is different than picky tar)
+ *	ASSUMED: space after header in header block is zero filled
+ * Return:
+ *	0 if file has data to be written after the header, 1 if file has NO
+ *	data to write after the header, -1 if archive write failed
+ */
+
+int
+ustar_wr(ARCHD *arcn)
+{
+	HD_USTAR *hd;
+	char *pt;
+	char hdblk[sizeof(HD_USTAR)];
+
+	/*
+	 * check for those file system types ustar cannot store
+	 */
+	if (arcn->type == PAX_SCK) {
+		paxwarn(1, "Ustar cannot archive a socket %s", arcn->org_name);
+		return(1);
+	}
+
+	/*
+	 * check the length of the linkname
+	 */
+	if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
+	    (arcn->type == PAX_HRG)) &&
+	    (arcn->ln_nlen > (int)sizeof(hd->linkname))) {
+		paxwarn(1, "Link name too long for ustar %s", arcn->ln_name);
+		return(1);
+	}
+
+	/*
+	 * split the path name into prefix and name fields (if needed). if
+	 * pt != arcn->name, the name has to be split
+	 */
+	if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) {
+		paxwarn(1, "File name too long for ustar %s", arcn->name);
+		return(1);
+	}
+	hd = (HD_USTAR *)hdblk;
+	arcn->pad = 0L;
+
+	/*
+	 * split the name, or zero out the prefix
+	 */
+	if (pt != arcn->name) {
+		/*
+		 * name was split, pt points at the / where the split is to
+		 * occur, we remove the / and copy the first part to the prefix
+		 */
+		*pt = '\0';
+		l_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix));
+		*pt++ = '/';
+	} else
+		memset(hd->prefix, 0, sizeof(hd->prefix));
+
+	/*
+	 * copy the name part. this may be the whole path or the part after
+	 * the prefix.  both the name and prefix may fill the entire field.
+	 */
+	l_strncpy(hd->name, pt, sizeof(hd->name));
+
+	/*
+	 * set the fields in the header that are type dependent
+	 */
+	switch(arcn->type) {
+	case PAX_DIR:
+		hd->typeflag = DIRTYPE;
+		memset(hd->linkname, 0, sizeof(hd->linkname));
+		memset(hd->devmajor, 0, sizeof(hd->devmajor));
+		memset(hd->devminor, 0, sizeof(hd->devminor));
+		if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
+			goto out;
+		break;
+	case PAX_CHR:
+	case PAX_BLK:
+		if (arcn->type == PAX_CHR)
+			hd->typeflag = CHRTYPE;
+		else
+			hd->typeflag = BLKTYPE;
+		memset(hd->linkname, 0, sizeof(hd->linkname));
+		if (ul_oct((u_long)major(arcn->sb.st_rdev), hd->devmajor,
+		   sizeof(hd->devmajor), 3) ||
+		   ul_oct((u_long)minor(arcn->sb.st_rdev), hd->devminor,
+		   sizeof(hd->devminor), 3) ||
+		   ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
+			goto out;
+		break;
+	case PAX_FIF:
+		hd->typeflag = FIFOTYPE;
+		memset(hd->linkname, 0, sizeof(hd->linkname));
+		memset(hd->devmajor, 0, sizeof(hd->devmajor));
+		memset(hd->devminor, 0, sizeof(hd->devminor));
+		if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
+			goto out;
+		break;
+	case PAX_SLK:
+	case PAX_HLK:
+	case PAX_HRG:
+		if (arcn->type == PAX_SLK)
+			hd->typeflag = SYMTYPE;
+		else
+			hd->typeflag = LNKTYPE;
+		/* the link name may occupy the entire field in ustar */
+		l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
+		memset(hd->devmajor, 0, sizeof(hd->devmajor));
+		memset(hd->devminor, 0, sizeof(hd->devminor));
+		if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
+			goto out;
+		break;
+	case PAX_REG:
+	case PAX_CTG:
+	default:
+		/*
+		 * file data with this type, set the padding
+		 */
+		if (arcn->type == PAX_CTG)
+			hd->typeflag = CONTTYPE;
+		else
+			hd->typeflag = REGTYPE;
+		memset(hd->linkname, 0, sizeof(hd->linkname));
+		memset(hd->devmajor, 0, sizeof(hd->devmajor));
+		memset(hd->devminor, 0, sizeof(hd->devminor));
+		arcn->pad = TAR_PAD(arcn->sb.st_size);
+#		ifdef NET2_STAT
+		if (ul_oct((u_long)arcn->sb.st_size, hd->size,
+		    sizeof(hd->size), 3)) {
+#		else
+		if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
+		    sizeof(hd->size), 3)) {
+#		endif
+			paxwarn(1,"File is too long for ustar %s",arcn->org_name);
+			return(1);
+		}
+		break;
+	}
+
+	l_strncpy(hd->magic, TMAGIC, TMAGLEN);
+	l_strncpy(hd->version, TVERSION, TVERSLEN);
+
+	/*
+	 * set the remaining fields. Some versions want all 16 bits of mode
+	 * we better humor them (they really do not meet spec though)....
+	 */
+	if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) ||
+	    ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3)  ||
+	    ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) ||
+	    ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
+		goto out;
+	l_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname));
+	l_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname));
+
+	/*
+	 * calculate and store the checksum write the header to the archive
+	 * return 0 tells the caller to now write the file data, 1 says no data
+	 * needs to be written
+	 */
+	if (ul_oct(tar_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum,
+	   sizeof(hd->chksum), 3))
+		goto out;
+	if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0)
+		return(-1);
+	if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0)
+		return(-1);
+	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
+		return(0);
+	return(1);
+
+    out:
+    	/*
+	 * header field is out of range
+	 */
+	paxwarn(1, "Ustar header field is too small for %s", arcn->org_name);
+	return(1);
+}
+
+/*
+ * name_split()
+ *	see if the name has to be split for storage in a ustar header. We try
+ *	to fit the entire name in the name field without splitting if we can.
+ *	The split point is always at a /
+ * Return
+ *	character pointer to split point (always the / that is to be removed
+ *	if the split is not needed, the points is set to the start of the file
+ *	name (it would violate the spec to split there). A NULL is returned if
+ *	the file name is too long
+ */
+
+static char *
+name_split(char *name, int len)
+{
+	char *start;
+
+	/*
+	 * check to see if the file name is small enough to fit in the name
+	 * field. if so just return a pointer to the name.
+	 */
+	if (len <= TNMSZ)
+		return(name);
+	if (len > (TPFSZ + TNMSZ + 1))
+		return(NULL);
+
+	/*
+	 * we start looking at the biggest sized piece that fits in the name
+	 * field. We walk forward looking for a slash to split at. The idea is
+	 * to find the biggest piece to fit in the name field (or the smallest
+	 * prefix we can find)
+	 */
+	start = name + len - TNMSZ - 1;
+	while ((*start != '\0') && (*start != '/'))
+		++start;
+
+	/*
+	 * if we hit the end of the string, this name cannot be split, so we
+	 * cannot store this file.
+	 */
+	if (*start == '\0')
+		return(NULL);
+	len = start - name;
+
+	/*
+	 * NOTE: /str where the length of str == TNMSZ can not be stored under
+	 * the p1003.1-1990 spec for ustar. We could force a prefix of / and
+	 * the file would then expand on extract to //str. The len == 0 below
+	 * makes this special case follow the spec to the letter.
+	 */
+	if ((len > TPFSZ) || (len == 0))
+		return(NULL);
+
+	/*
+	 * ok have a split point, return it to the caller
+	 */
+	return(start);
+}
Index: /trunk/minix/commands/pax/tar.h
===================================================================
--- /trunk/minix/commands/pax/tar.h	(revision 9)
+++ /trunk/minix/commands/pax/tar.h	(revision 9)
@@ -0,0 +1,145 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)tar.h	8.2 (Berkeley) 4/18/94
+ * $FreeBSD: src/bin/pax/tar.h,v 1.7 2004/04/06 20:06:49 markm Exp $
+ */
+
+/*
+ * defines and data structures common to all tar formats
+ */
+#define CHK_LEN		8		/* length of checksum field */
+#define TNMSZ		100		/* size of name field */
+#ifdef _PAX_
+#define NULLCNT		2		/* number of null blocks in trailer */
+#define CHK_OFFSET	148		/* start of checksum field */
+#define BLNKSUM		256L		/* sum of checksum field using ' ' */
+#endif /* _PAX_ */
+
+/*
+ * Values used in typeflag field in all tar formats
+ * (only REGTYPE, LNKTYPE and SYMTYPE are used in old BSD tar headers)
+ */
+#define	REGTYPE		'0'		/* Regular File */
+#define	AREGTYPE	'\0'		/* Regular File */
+#define	LNKTYPE		'1'		/* Link */
+#define	SYMTYPE		'2'		/* Symlink */
+#define	CHRTYPE		'3'		/* Character Special File */
+#define	BLKTYPE		'4'		/* Block Special File */
+#define	DIRTYPE		'5'		/* Directory */
+#define	FIFOTYPE	'6'		/* FIFO */
+#define	CONTTYPE	'7'		/* high perf file */
+
+/*
+ * Mode field encoding of the different file types - values in octal
+ */
+#define TSUID		04000		/* Set UID on execution */
+#define TSGID		02000		/* Set GID on execution */
+#define TSVTX		01000		/* Reserved */
+#define TUREAD		00400		/* Read by owner */
+#define TUWRITE		00200		/* Write by owner */
+#define TUEXEC		00100		/* Execute/Search by owner */
+#define TGREAD		00040		/* Read by group */
+#define TGWRITE		00020		/* Write by group */
+#define TGEXEC		00010		/* Execute/Search by group */
+#define TOREAD		00004		/* Read by other */
+#define TOWRITE		00002		/* Write by other */
+#define TOEXEC		00001		/* Execute/Search by other */
+
+#ifdef _PAX_
+/*
+ * Pad with a bit mask, much faster than doing a mod but only works on powers
+ * of 2. Macro below is for block of 512 bytes.
+ */
+#define TAR_PAD(x)	((512 - ((x) & 511)) & 511)
+#endif /* _PAX_ */
+
+/*
+ * structure of an old tar header as it appeared in BSD releases
+ */
+typedef struct {
+	char name[TNMSZ];		/* name of entry */
+	char mode[8]; 			/* mode */
+	char uid[8]; 			/* uid */
+	char gid[8];			/* gid */
+	char size[12];			/* size */
+	char mtime[12];			/* modification time */
+	char chksum[CHK_LEN];		/* checksum */
+	char linkflag;			/* norm, hard, or sym. */
+	char linkname[TNMSZ];		/* linked to name */
+} HD_TAR;
+
+#ifdef _PAX_
+/*
+ * -o options for BSD tar to not write directories to the archive
+ */
+#define TAR_NODIR	"nodir"
+#define TAR_OPTION	"write_opt"
+
+/*
+ * default device names
+ */
+#define	DEV_0		"/dev/rmt0"
+#define	DEV_1		"/dev/rmt1"
+#define	DEV_4		"/dev/rmt4"
+#define	DEV_5		"/dev/rmt5"
+#define	DEV_7		"/dev/rmt7"
+#define	DEV_8		"/dev/rmt8"
+#endif /* _PAX_ */
+
+/*
+ * Data Interchange Format - Extended tar header format - POSIX 1003.1-1990
+ */
+#define TPFSZ		155
+#define	TMAGIC		"ustar"		/* ustar and a null */
+#define	TMAGLEN		6
+#define	TVERSION	"00"		/* 00 and no null */
+#define	TVERSLEN	2
+
+typedef struct {
+	char name[TNMSZ];		/* name of entry */
+	char mode[8]; 			/* mode */
+	char uid[8]; 			/* uid */
+	char gid[8];			/* gid */
+	char size[12];			/* size */
+	char mtime[12];			/* modification time */
+	char chksum[CHK_LEN];		/* checksum */
+	char typeflag;			/* type of file. */
+	char linkname[TNMSZ];		/* linked to name */
+	char magic[TMAGLEN];		/* magic cookie */
+	char version[TVERSLEN];		/* version */
+	char uname[32];			/* ascii owner name */
+	char gname[32];			/* ascii group name */
+	char devmajor[8];		/* major device number */
+	char devminor[8];		/* minor device number */
+	char prefix[TPFSZ];		/* linked to name */
+} HD_USTAR;
Index: /trunk/minix/commands/pax/tty_subs.c
===================================================================
--- /trunk/minix/commands/pax/tty_subs.c	(revision 9)
+++ /trunk/minix/commands/pax/tty_subs.c	(revision 9)
@@ -0,0 +1,189 @@
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)tty_subs.c	8.2 (Berkeley) 4/18/94";
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include "pax.h"
+#include "extern.h"
+#include <stdarg.h>
+
+/*
+ * routines that deal with I/O to and from the user
+ */
+
+#define DEVTTY	  "/dev/tty"      /* device for interactive i/o */
+static FILE *ttyoutf = NULL;		/* output pointing at control tty */
+static FILE *ttyinf = NULL;		/* input pointing at control tty */
+
+/*
+ * tty_init()
+ *	try to open the controlling terminal (if any) for this process. if the
+ *	open fails, future ops that require user input will get an EOF
+ */
+
+int
+tty_init(void)
+{
+	int ttyfd;
+
+	if ((ttyfd = open(DEVTTY, O_RDWR)) >= 0) {
+		if ((ttyoutf = fdopen(ttyfd, "w")) != NULL) {
+			if ((ttyinf = fdopen(ttyfd, "r")) != NULL)
+				return(0);
+			(void)fclose(ttyoutf);
+		}
+		(void)close(ttyfd);
+	}
+
+	if (iflag) {
+		paxwarn(1, "Fatal error, cannot open %s", DEVTTY);
+		return(-1);
+	}
+	return(0);
+}
+
+/*
+ * tty_prnt()
+ *	print a message using the specified format to the controlling tty
+ *	if there is no controlling terminal, just return.
+ */
+
+void
+tty_prnt(const char *fmt, ...)
+{
+	va_list ap;
+	if (ttyoutf == NULL)
+		return;
+	va_start(ap, fmt);
+	(void)vfprintf(ttyoutf, fmt, ap);
+	va_end(ap);
+	(void)fflush(ttyoutf);
+}
+
+/*
+ * tty_read()
+ *	read a string from the controlling terminal if it is open into the
+ *	supplied buffer
+ * Return:
+ *	0 if data was read, -1 otherwise.
+ */
+
+int
+tty_read(char *str, int len)
+{
+	char *pt;
+
+	if ((--len <= 0) || (ttyinf == NULL) || (fgets(str,len,ttyinf) == NULL))
+		return(-1);
+	*(str + len) = '\0';
+
+	/*
+	 * strip off that trailing newline
+	 */
+	if ((pt = strchr(str, '\n')) != NULL)
+		*pt = '\0';
+	return(0);
+}
+
+/*
+ * paxwarn()
+ *	write a warning message to stderr. if "set" the exit value of pax
+ *	will be non-zero.
+ */
+
+void
+paxwarn(int set, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	if (set)
+		exit_val = 1;
+	/*
+	 * when vflag we better ship out an extra \n to get this message on a
+	 * line by itself
+	 */
+	if (vflag && vfpart) {
+		(void)fflush(listf);
+		(void)fputc('\n', stderr);
+		vfpart = 0;
+	}
+	(void)fprintf(stderr, "%s: ", argv0);
+	(void)vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	(void)fputc('\n', stderr);
+}
+
+/*
+ * syswarn()
+ *	write a warning message to stderr. if "set" the exit value of pax
+ *	will be non-zero.
+ */
+
+void
+syswarn(int set, int errnum, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	if (set)
+		exit_val = 1;
+	/*
+	 * when vflag we better ship out an extra \n to get this message on a
+	 * line by itself
+	 */
+	if (vflag && vfpart) {
+		(void)fflush(listf);
+		(void)fputc('\n', stderr);
+		vfpart = 0;
+	}
+	(void)fprintf(stderr, "%s: ", argv0);
+	(void)vfprintf(stderr, fmt, ap);
+	va_end(ap);
+
+	/*
+	 * format and print the errno
+	 */
+	if (errnum > 0)
+		(void)fprintf(stderr, " <%s>", strerror(errnum));
+	(void)fputc('\n', stderr);
+}
Index: /trunk/minix/commands/ps/Makefile
===================================================================
--- /trunk/minix/commands/ps/Makefile	(revision 9)
+++ /trunk/minix/commands/ps/Makefile	(revision 9)
@@ -0,0 +1,25 @@
+# Makefile for the process status utility.
+#
+u=/usr
+CC=	exec cc
+CFLAGS=	-O -D_MINIX -D_POSIX_SOURCE
+MAKE=	exec make -$(MAKEFLAGS)
+
+all: ps
+
+# process status utility
+ps:	ps.c /usr/include/minix/config.h /usr/include/minix/const.h \
+		../../kernel/const.h ../../kernel/type.h \
+		../../kernel/proc.h ../../servers/pm/mproc.h \
+		../../servers/fs/fproc.h ../../servers/fs/const.h
+	$(CC) -i $(CFLAGS) -o $@ ps.c
+	install -S 32kw $@
+install:	/usr/bin/ps
+/usr/bin/ps:	ps
+	install -cs -o bin -g kmem -m 2755 $? $@
+
+
+
+# clean up compile results
+clean:
+	rm -f *.bak ps 
Index: /trunk/minix/commands/ps/build
===================================================================
--- /trunk/minix/commands/ps/build	(revision 9)
+++ /trunk/minix/commands/ps/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/ps/ps.c
===================================================================
--- /trunk/minix/commands/ps/ps.c	(revision 9)
+++ /trunk/minix/commands/ps/ps.c	(revision 9)
@@ -0,0 +1,605 @@
+/* ps - print status			Author: Peter Valkenburg */
+
+/* Ps.c, Peter Valkenburg (valke@psy.vu.nl), january 1990.
+ *
+ * This is a V7 ps(1) look-alike for MINIX >= 1.5.0.
+ * It does not support the 'k' option (i.e. cannot read memory from core file).
+ * If you want to compile this for non-IBM PC architectures, the header files
+ * require that you have your CHIP, MACHINE etc. defined.
+ * Full syntax:
+ *	ps [-][aeflx]
+ * Option `a' gives all processes, `l' for detailed info, `x' includes even
+ * processes without a terminal.
+ * The `f' and `e' options were added by Kees Bot for the convenience of 
+ * Solaris users accustomed to these options. The `e' option is equivalent to 
+ * `a' and `f' is equivalent to  -l. These do not appear in the usage message.
+ *
+ * VERY IMPORTANT NOTE:
+ *	To compile ps, the kernel/, fs/ and pm/ source directories must be in
+ *	../../ relative to the directory where ps is compiled (normally the
+ *	tools source directory).
+ *
+ *	If you want your ps to be useable by anyone, you can arrange the
+ *	following access permissions (note the protected memory files and set
+ *	*group* id on ps):
+ *	-rwxr-sr-x  1 bin   kmem       11916 Jul  4 15:31 /bin/ps
+ *	crw-r-----  1 bin   kmem      1,   1 Jan  1  1970 /dev/mem
+ *	crw-r-----  1 bin   kmem      1,   2 Jan  1  1970 /dev/kmem
+ */
+
+/* Some technical comments on this implementation:
+ *
+ * Most fields are similar to V7 ps(1), except for CPU, NICE, PRI which are
+ * absent, RECV which replaces WCHAN, and PGRP that is an extra.
+ * The info is obtained from the following fields of proc, mproc and fproc:
+ * F	- kernel status field, p_rts_flags
+ * S	- kernel status field, p_rts_flags; mm status field, mp_flags (R if p_rts_flags
+ *	  is 0; Z if mp_flags == ZOMBIE; T if mp_flags == STOPPED; else W).
+ * UID	- mm eff uid field, mp_effuid
+ * PID	- mm pid field, mp_pid
+ * PPID	- mm parent process index field, mp_parent (used as index in proc).
+ * PGRP - mm process group field, mp_procgrp
+ * SZ	- kernel text size + physical stack address - physical data address
+ *			   + stack size
+ *	  p_memmap[T].mem_len + p_memmap[S].mem_phys - p_memmap[D].mem_phys
+ *			   + p_memmap[S].mem_len
+ * RECV	- kernel process index field for message receiving, p_getfrom
+ *	  If sleeping, mm's mp_flags, or fs's fp_task are used for more info.
+ * TTY	- fs controlling tty device field, fp_tty.
+ * TIME	- kernel user + system times fields, user_time + sys_time
+ * CMD	- system process index (converted to mnemonic name by using the p_name
+ *	  field), or user process argument list (obtained by reading the stack
+ *	  frame; the resulting address is used to get the argument vector from
+ *	  user space and converted into a concatenated argument list).
+ */
+
+#include <minix/config.h>
+#include <minix/endpoint.h>
+#include <limits.h>
+#include <timers.h>
+#include <sys/types.h>
+
+#include <minix/const.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <minix/com.h>
+#include <fcntl.h>
+#include <a.out.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <ttyent.h>
+
+#include "../../kernel/const.h"
+#include "../../kernel/type.h"
+#include "../../kernel/proc.h"
+
+#include "../../servers/pm/mproc.h"
+#include "../../servers/fs/fproc.h"
+#include "../../servers/fs/const.h"
+
+
+/*----- ps's local stuff below this line ------*/
+
+
+#define mindev(dev)	(((dev)>>MINOR) & 0377)	/* yield minor device */
+#define majdev(dev)	(((dev)>>MAJOR) & 0377)	/* yield major device */
+
+#define	TTY_MAJ		4	/* major device of console */
+
+/* Structure for tty name info. */
+typedef struct {
+  char tty_name[NAME_MAX + 1];	/* file name in /dev */
+  dev_t tty_dev;		/* major/minor pair */
+} ttyinfo_t;
+
+ttyinfo_t *ttyinfo;		/* ttyinfo holds actual tty info */
+size_t n_ttyinfo;		/* Number of tty info slots */
+
+/* Macro to convert memory offsets to rounded kilo-units */
+#define	off_to_k(off)	((unsigned) (((off) + 512) / 1024))
+
+
+/* Number of tasks and processes and addresses of the main process tables. */
+int nr_tasks, nr_procs;		
+vir_bytes proc_addr, mproc_addr, fproc_addr;	
+extern int errno;
+
+/* Process tables of the kernel, MM, and FS. */
+struct proc *ps_proc;
+struct mproc *ps_mproc;
+struct fproc *ps_fproc;
+
+/* Where is INIT? */
+int init_proc_nr;
+#define low_user init_proc_nr
+
+#define	KMEM_PATH	"/dev/kmem"	/* opened for kernel proc table */
+#define	MEM_PATH	"/dev/mem"	/* opened for pm/fs + user processes */
+
+int kmemfd, memfd;		/* file descriptors of [k]mem */
+
+/* Short and long listing formats:
+ *
+ *   PID TTY  TIME CMD
+ * ppppp tttmmm:ss cccccccccc...
+ *
+ *   F S UID   PID  PPID  PGRP   SZ       RECV TTY  TIME CMD
+ * fff s uuu ppppp ppppp ppppp ssss rrrrrrrrrr tttmmm:ss cccccccc...
+ */
+#define S_HEADER "  PID TTY  TIME CMD\n"
+#define S_FORMAT "%5s %3s %s %s\n"
+#define L_HEADER "  F S UID   PID  PPID  PGRP     SZ         RECV TTY  TIME CMD\n"
+#define L_FORMAT "%3o %c %3d %5s %5d %5d %6d %12s %3s %s %s\n"
+
+
+struct pstat {			/* structure filled by pstat() */
+  dev_t ps_dev;			/* major/minor of controlling tty */
+  uid_t ps_ruid;		/* real uid */
+  uid_t ps_euid;		/* effective uid */
+  pid_t ps_pid;			/* process id */
+  pid_t ps_ppid;		/* parent process id */
+  int ps_pgrp;			/* process group id */
+  int ps_flags;			/* kernel flags */
+  int ps_mflags;		/* mm flags */
+  int ps_ftask;			/* (possibly pseudo) fs suspend task */
+  char ps_state;		/* process state */
+  vir_bytes ps_tsize;		/* text size (in bytes) */
+  vir_bytes ps_dsize;		/* data size (in bytes) */
+  vir_bytes ps_ssize;		/* stack size (in bytes) */
+  phys_bytes ps_vtext;		/* virtual text offset */
+  phys_bytes ps_vdata;		/* virtual data offset */
+  phys_bytes ps_vstack;		/* virtual stack offset */
+  phys_bytes ps_text;		/* physical text offset */
+  phys_bytes ps_data;		/* physical data offset */
+  phys_bytes ps_stack;		/* physical stack offset */
+  int ps_recv;			/* process number to receive from */
+  time_t ps_utime;		/* accumulated user time */
+  time_t ps_stime;		/* accumulated system time */
+  char *ps_args;		/* concatenated argument string */
+  vir_bytes ps_procargs;	/* initial stack frame from MM */
+};
+
+/* Ps_state field values in pstat struct above */
+#define	Z_STATE		'Z'	/* Zombie */
+#define	W_STATE		'W'	/* Waiting */
+#define	S_STATE		'S'	/* Sleeping */
+#define	R_STATE		'R'	/* Runnable */
+#define	T_STATE		'T'	/* stopped (Trace) */
+
+_PROTOTYPE(char *tname, (Dev_t dev_nr ));
+_PROTOTYPE(char *taskname, (int p_nr ));
+_PROTOTYPE(char *prrecv, (struct pstat *bufp ));
+_PROTOTYPE(void disaster, (int sig ));
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(char *get_args, (struct pstat *bufp ));
+_PROTOTYPE(int pstat, (int p_nr, struct pstat *bufp ));
+_PROTOTYPE(int addrread, (int fd, phys_clicks base, vir_bytes addr, 
+						    char *buf, int nbytes ));
+_PROTOTYPE(void usage, (char *pname ));
+_PROTOTYPE(void err, (char *s ));
+_PROTOTYPE(int gettynames, (void));
+
+
+/*
+ * Tname returns mnemonic string for dev_nr. This is "?" for maj/min pairs that
+ * are not found.  It uses the ttyinfo array (prepared by gettynames).
+ * Tname assumes that the first three letters of the tty's name can be omitted
+ * and returns the rest (except for the console, which yields "co").
+ */
+char *tname(dev_nr)
+Dev_t dev_nr;
+{
+  int i;
+
+  if (majdev(dev_nr) == TTY_MAJ && mindev(dev_nr) == 0) return "co";
+
+  for (i = 0; i < n_ttyinfo && ttyinfo[i].tty_name[0] != '\0'; i++)
+	if (ttyinfo[i].tty_dev == dev_nr)
+		return ttyinfo[i].tty_name + 3;
+
+  return "?";
+}
+
+/* Return canonical task name of task p_nr; overwritten on each call (yucch) */
+char *taskname(p_nr)
+int p_nr;
+{
+  return ps_proc[_ENDPOINT_P(p_nr) + nr_tasks].p_name;
+}
+
+/* Prrecv prints the RECV field for process with pstat buffer pointer bufp.
+ * This is either "ANY", "taskname", or "(blockreason) taskname".
+ */
+char *prrecv(bufp)
+struct pstat *bufp;
+{
+  char *blkstr, *task;		/* reason for blocking and task */
+  static char recvstr[20];
+
+  if (bufp->ps_recv == ANY) return "ANY";
+
+  task = taskname(bufp->ps_recv);
+  if (bufp->ps_state != S_STATE) return task;
+
+  blkstr = "?";
+  if (bufp->ps_recv == PM_PROC_NR) {
+	if (bufp->ps_mflags & PAUSED)
+		blkstr = "pause";
+	else if (bufp->ps_mflags & WAITING)
+		blkstr = "wait";
+	else if (bufp->ps_mflags & SIGSUSPENDED)
+		blkstr = "ssusp";
+  } else if (bufp->ps_recv == FS_PROC_NR) {
+	if (-bufp->ps_ftask == XPIPE)
+		blkstr = "pipe";
+	else if (-bufp->ps_ftask == XPOPEN)
+		blkstr = "popen";
+	else if (-bufp->ps_ftask == XLOCK)
+		blkstr = "flock";
+	else if(-bufp->ps_ftask == XSELECT)
+		blkstr = "select";
+	else if(-bufp->ps_ftask >= 0)
+		blkstr = taskname(-bufp->ps_ftask);
+	else
+		blkstr = "??";
+  }
+  (void) sprintf(recvstr, "(%s) %s", blkstr, task);
+  return recvstr;
+}
+
+/* If disaster is called some of the system parameters imported into ps are
+ * probably wrong.  This tends to result in memory faults.
+ */
+void disaster(sig)
+int sig;
+{
+  fprintf(stderr, "Ooops, got signal %d\n", sig);
+  fprintf(stderr, "Was ps recompiled since the last kernel change?\n");
+  exit(3);
+}
+
+/* Main interprets arguments, gets system addresses, opens [k]mem, reads in
+ * process tables from kernel/pm/fs and calls pstat() for relevant entries.
+ */
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i;
+  struct pstat buf;
+  int db_fd;
+  int uid = getuid();		/* real uid of caller */
+  char *opt;
+  int opt_all = FALSE;		/* -a */
+  int opt_long = FALSE;		/* -l */
+  int opt_notty = FALSE;	/* -x */
+  char *ke_path;		/* paths of kernel, */
+  char *mm_path;		/* mm, */
+  char *fs_path;		/* and fs used in ps -U */
+  char pid[2 + sizeof(pid_t) * 3];
+  unsigned long ustime;
+  char cpu[sizeof(clock_t) * 3 + 1 + 2];
+  struct kinfo kinfo;
+  int s;
+
+  (void) signal(SIGSEGV, disaster);	/* catch a common crash */
+
+  /* Parse arguments; a '-' need not be present (V7/BSD compatability) */
+  for (i = 1; i < argc; i++) {
+	opt = argv[i];
+	if (opt[0] == '-') opt++;
+	while (*opt != 0) switch (*opt++) {
+		case 'a':	opt_all = TRUE;			break;
+		case 'e':	opt_all = opt_notty = TRUE;	break;
+		case 'f':
+		case 'l':	opt_long = TRUE;		break;
+		case 'x':	opt_notty = TRUE;		break;
+		default:	usage(argv[0]);
+	}
+  }
+
+  /* Open memory devices and get PS info from the kernel */
+  if ((kmemfd = open(KMEM_PATH, O_RDONLY)) == -1) err(KMEM_PATH);
+  if ((memfd = open(MEM_PATH, O_RDONLY)) == -1) err(MEM_PATH);
+  if (gettynames() == -1) err("Can't get tty names");
+
+  getsysinfo(PM_PROC_NR, SI_PROC_ADDR, &mproc_addr);
+  getsysinfo(FS_PROC_NR, SI_PROC_ADDR, &fproc_addr);
+  getsysinfo(PM_PROC_NR, SI_KINFO, &kinfo);
+  proc_addr = kinfo.proc_addr;
+  nr_tasks = kinfo.nr_tasks;	
+  nr_procs = kinfo.nr_procs;
+
+  /* Allocate memory for process tables */
+  ps_proc = (struct proc *) malloc((nr_tasks + nr_procs) * sizeof(ps_proc[0]));
+  ps_mproc = (struct mproc *) malloc(nr_procs * sizeof(ps_mproc[0]));
+  ps_fproc = (struct fproc *) malloc(nr_procs * sizeof(ps_fproc[0]));
+  if (ps_proc == NULL || ps_mproc == NULL || ps_fproc == NULL)
+	err("Out of memory");
+
+  /* Get kernel process table */
+  if (addrread(kmemfd, (phys_clicks) 0,
+		proc_addr, (char *) ps_proc,
+		(nr_tasks + nr_procs) * sizeof(ps_proc[0]))
+			!= (nr_tasks + nr_procs) * sizeof(ps_proc[0]))
+	err("Can't get kernel proc table from /dev/kmem");
+
+  /* Get mm/fs process tables */
+  if (addrread(memfd, ps_proc[nr_tasks + PM_PROC_NR].p_memmap[D].mem_phys,
+		mproc_addr, (char *) ps_mproc,
+		nr_procs * sizeof(ps_mproc[0]))
+			!= nr_procs * sizeof(ps_mproc[0]))
+	err("Can't get mm proc table from /dev/mem");
+  if (addrread(memfd, ps_proc[nr_tasks + FS_PROC_NR].p_memmap[D].mem_phys,
+		fproc_addr, (char *) ps_fproc,
+		nr_procs * sizeof(ps_fproc[0]))
+			!= nr_procs * sizeof(ps_fproc[0]))
+	err("Can't get fs proc table from /dev/mem");
+
+  /* We need to know where INIT hangs out. */
+  for (i = FS_PROC_NR; i < nr_procs; i++) {
+	if (strcmp(ps_proc[nr_tasks + i].p_name, "init") == 0) break;
+  }
+  init_proc_nr = i;
+
+  /* Now loop through process table and handle each entry */
+  printf("%s", opt_long ? L_HEADER : S_HEADER);
+  for (i = -nr_tasks; i < nr_procs; i++) {
+	if (pstat(i, &buf) != -1 &&
+	    (opt_all || buf.ps_euid == uid || buf.ps_ruid == uid) &&
+	    (opt_notty || majdev(buf.ps_dev) == TTY_MAJ)) {
+		if (buf.ps_pid == 0 && i != PM_PROC_NR) {
+			sprintf(pid, "(%d)", i);
+		} else {
+			sprintf(pid, "%d", buf.ps_pid);
+		}
+
+		ustime = (buf.ps_utime + buf.ps_stime) / HZ;
+		if (ustime < 60 * 60) {
+			sprintf(cpu, "%2lu:%02lu", ustime / 60, ustime % 60);
+		} else
+		if (ustime < 100L * 60 * 60) {
+			ustime /= 60;
+			sprintf(cpu, "%2luh%02lu", ustime / 60, ustime % 60);
+		} else {
+			sprintf(cpu, "%4luh", ustime / 3600);
+		}
+
+		if (opt_long) printf(L_FORMAT,
+			       buf.ps_flags, buf.ps_state,
+			       buf.ps_euid, pid, buf.ps_ppid, 
+			       buf.ps_pgrp,
+			       off_to_k((buf.ps_tsize
+					 + buf.ps_stack - buf.ps_data
+					 + buf.ps_ssize)),
+			       (buf.ps_flags & RECEIVING ?
+				prrecv(&buf) :
+				""),
+			       tname((Dev_t) buf.ps_dev),
+			       cpu,
+			       i <= init_proc_nr || buf.ps_args == NULL
+				       ? taskname(i) : buf.ps_args);
+		else
+			printf(S_FORMAT,
+			       pid, tname((Dev_t) buf.ps_dev),
+			       cpu,
+			       i <= init_proc_nr || buf.ps_args == NULL
+				       ? taskname(i) : buf.ps_args);
+	}
+  }
+  return(0);
+}
+
+char *get_args(bufp)
+struct pstat *bufp;
+{
+  int nargv;
+  int cnt;			/* # of bytes read from stack frame */
+  int neos;			/* # of '\0's seen in argv string space */
+  phys_bytes iframe;
+  long l;
+  char *cp, *args;
+  static union stack {
+	vir_bytes stk_i;
+	char *stk_cp;
+	char stk_c;
+  } stk[ARG_MAX / sizeof(char *)];
+  union stack *sp;
+
+  /* Phys address of the original stack frame. */
+  iframe = bufp->ps_procargs - bufp->ps_vstack + bufp->ps_stack;
+
+  /* Calculate the number of bytes to read from user stack */
+  l = (phys_bytes) bufp->ps_ssize - (iframe - bufp->ps_stack);
+  if (l > ARG_MAX) l = ARG_MAX;
+  cnt = l;
+
+  /* Get cnt bytes from user initial stack to local stack buffer */
+  if (lseek(memfd, (off_t) iframe, 0) < 0)
+	return NULL; 
+
+  if ( read(memfd, (char *)stk, cnt) != cnt ) 
+	return NULL;
+
+  sp = stk;
+  nargv = (int) sp[0].stk_i;  /* number of argv arguments */
+
+  /* See if argv[0] is with the bytes we read in */
+  l = (long) sp[1].stk_cp - (long) bufp->ps_procargs;
+
+  if ( ( l < 0 ) || ( l > cnt ) )  
+	return NULL;
+
+  /* l is the offset of the argv[0] argument */
+  /* change for concatenation the '\0' to space, for nargv elements */
+
+  args = &((char *) stk)[(int)l]; 
+  neos = 0;
+  for (cp = args; cp < &((char *) stk)[cnt]; cp++)
+	if (*cp == '\0')
+		if (++neos >= nargv)
+			break;
+		else
+			*cp = ' ';
+  if (cp == args) return NULL;
+  *cp = '\0';
+
+  return args;
+
+}
+
+/* Pstat collects info on process number p_nr and returns it in buf.
+ * It is assumed that tasks do not have entries in fproc/mproc.
+ */
+int pstat(p_nr, bufp)
+int p_nr;
+struct pstat *bufp;
+{
+  int p_ki = p_nr + nr_tasks;	/* kernel proc index */
+
+  if (p_nr < -nr_tasks || p_nr >= nr_procs) return -1;
+
+  if ((ps_proc[p_ki].p_rts_flags == SLOT_FREE)
+  				&& !(ps_mproc[p_nr].mp_flags & IN_USE))
+	return -1;
+
+  bufp->ps_flags = ps_proc[p_ki].p_rts_flags;
+
+  if (p_nr >= low_user) {
+	bufp->ps_dev = ps_fproc[p_nr].fp_tty;
+	bufp->ps_ftask = ps_fproc[p_nr].fp_task;
+  } else {
+	bufp->ps_dev = 0;
+	bufp->ps_ftask = 0;
+  }
+
+  if (p_nr >= 0) {
+	bufp->ps_ruid = ps_mproc[p_nr].mp_realuid;
+	bufp->ps_euid = ps_mproc[p_nr].mp_effuid;
+	bufp->ps_pid = ps_mproc[p_nr].mp_pid;
+	bufp->ps_ppid = ps_mproc[ps_mproc[p_nr].mp_parent].mp_pid;
+	bufp->ps_pgrp = ps_mproc[p_nr].mp_procgrp;
+	bufp->ps_mflags = ps_mproc[p_nr].mp_flags;
+  } else {
+	bufp->ps_pid = 0;
+	bufp->ps_ppid = 0;
+	bufp->ps_ruid = bufp->ps_euid = 0;
+	bufp->ps_pgrp = 0;
+	bufp->ps_mflags = 0;
+  }
+
+  /* State is interpretation of combined kernel/mm flags for non-tasks */
+  if (p_nr >= low_user) {		/* non-tasks */
+	if (ps_mproc[p_nr].mp_flags & ZOMBIE)
+		bufp->ps_state = Z_STATE;	/* zombie */
+	else if (ps_mproc[p_nr].mp_flags & STOPPED)
+		bufp->ps_state = T_STATE;	/* stopped (traced) */
+	else if (ps_proc[p_ki].p_rts_flags == 0)
+		bufp->ps_state = R_STATE;	/* in run-queue */
+	else if (ps_mproc[p_nr].mp_flags & (WAITING | PAUSED | SIGSUSPENDED) ||
+		 ps_fproc[p_nr].fp_suspended == SUSPENDED)
+		bufp->ps_state = S_STATE;	/* sleeping */
+	else
+		bufp->ps_state = W_STATE;	/* a short wait */
+  } else {			/* tasks are simple */
+	if (ps_proc[p_ki].p_rts_flags == 0)
+		bufp->ps_state = R_STATE;	/* in run-queue */
+	else
+		bufp->ps_state = W_STATE;	/* other i.e. waiting */
+  }
+
+  bufp->ps_tsize = (size_t) ps_proc[p_ki].p_memmap[T].mem_len << CLICK_SHIFT;
+  bufp->ps_dsize = (size_t) ps_proc[p_ki].p_memmap[D].mem_len << CLICK_SHIFT;
+  bufp->ps_ssize = (size_t) ps_proc[p_ki].p_memmap[S].mem_len << CLICK_SHIFT;
+  bufp->ps_vtext = (off_t) ps_proc[p_ki].p_memmap[T].mem_vir << CLICK_SHIFT;
+  bufp->ps_vdata = (off_t) ps_proc[p_ki].p_memmap[D].mem_vir << CLICK_SHIFT;
+  bufp->ps_vstack = (off_t) ps_proc[p_ki].p_memmap[S].mem_vir << CLICK_SHIFT;
+  bufp->ps_text = (off_t) ps_proc[p_ki].p_memmap[T].mem_phys << CLICK_SHIFT;
+  bufp->ps_data = (off_t) ps_proc[p_ki].p_memmap[D].mem_phys << CLICK_SHIFT;
+  bufp->ps_stack = (off_t) ps_proc[p_ki].p_memmap[S].mem_phys << CLICK_SHIFT;
+
+  bufp->ps_recv = _ENDPOINT_P(ps_proc[p_ki].p_getfrom_e);
+
+  bufp->ps_utime = ps_proc[p_ki].p_user_time;
+  bufp->ps_stime = ps_proc[p_ki].p_sys_time;
+
+  bufp->ps_procargs = ps_mproc[p_nr].mp_procargs;
+
+  if (bufp->ps_state == Z_STATE)
+	bufp->ps_args = "<defunct>";
+  else if (p_nr > init_proc_nr)
+	bufp->ps_args = get_args(bufp);
+
+  return 0;
+}
+
+/* Addrread reads nbytes from offset addr to click base of fd into buf. */
+int addrread(fd, base, addr, buf, nbytes)
+int fd;
+phys_clicks base;
+vir_bytes addr;
+char *buf;
+int nbytes;
+{
+  if (lseek(fd, ((off_t) base << CLICK_SHIFT) + addr, 0) < 0)
+	return -1;
+
+  return read(fd, buf, nbytes);
+}
+
+void usage(pname)
+char *pname;
+{
+  fprintf(stderr, "Usage: %s [-][aeflx]\n", pname);
+  exit(1);
+}
+
+void err(s)
+char *s;
+{
+  extern int errno;
+
+  if (errno == 0)
+	fprintf(stderr, "ps: %s\n", s);
+  else
+	fprintf(stderr, "ps: %s: %s\n", s, strerror(errno));
+
+  exit(2);
+}
+
+/* Fill ttyinfo by fstatting character specials in /dev. */
+int gettynames()
+{
+  static char dev_path[] = "/dev/";
+  struct stat statbuf;
+  static char path[sizeof(dev_path) + NAME_MAX];
+  int index;
+  struct ttyent *ttyp;
+
+  index = 0;
+  while ((ttyp = getttyent()) != NULL) {
+	strcpy(path, dev_path);
+	strcat(path, ttyp->ty_name);
+	if (stat(path, &statbuf) == -1 || !S_ISCHR(statbuf.st_mode))
+		continue;
+	if (index >= n_ttyinfo) {
+		n_ttyinfo= (index+16) * 2;
+		ttyinfo = realloc(ttyinfo, n_ttyinfo * sizeof(ttyinfo[0]));
+		if (ttyinfo == NULL) err("Out of memory");
+	}
+	ttyinfo[index].tty_dev = statbuf.st_rdev;
+	strcpy(ttyinfo[index].tty_name, ttyp->ty_name);
+	index++;
+  }
+  endttyent();
+  while (index < n_ttyinfo) ttyinfo[index++].tty_dev= 0;
+
+  return 0;
+}
Index: /trunk/minix/commands/reboot/Makefile
===================================================================
--- /trunk/minix/commands/reboot/Makefile	(revision 9)
+++ /trunk/minix/commands/reboot/Makefile	(revision 9)
@@ -0,0 +1,43 @@
+# Makefile for shutdown / halt / reboot.
+
+CFLAGS=$(OPT) -D_MINIX -D_POSIX_SOURCE
+LDFLAGS=-i
+CC=exec cc
+
+PROGRAMS=	shutdown halt tinyhalt
+MANUALS=	shutdown.8 halt.8 reboot.2 reboot.8
+
+all:	$(PROGRAMS)
+
+shutdown:	shutdown.o sh_wall.o log.o
+	$(CC) $(LDFLAGS) -o shutdown shutdown.o sh_wall.o log.o
+	install -S 4kw $@
+
+halt:	halt.o log.o
+	$(CC) $(LDFLAGS) -o halt halt.o log.o
+	install -S 4kw $@
+
+tinyhalt:	tinyhalt.c
+	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $?
+	install -S 4kw $@
+
+install:	/usr/bin/halt /usr/bin/reboot /usr/bin/shutdown \
+		/bin/halt /bin/reboot
+
+/usr/bin/halt:	halt
+	install -cs -o root -g operator -m 744 $? $@
+
+/usr/bin/reboot:	/usr/bin/halt
+	install -l $? $@
+
+/usr/bin/shutdown:	shutdown
+	install -cs -o root -g operator -m 4754 $? $@
+
+/bin/halt:	tinyhalt
+	install -cs -o root -g operator -m 744 $? $@
+
+/bin/reboot:	/bin/halt
+	install -l $? $@
+
+clean:
+	rm -f *.o a.out core $(PROGRAMS)
Index: /trunk/minix/commands/reboot/README
===================================================================
--- /trunk/minix/commands/reboot/README	(revision 9)
+++ /trunk/minix/commands/reboot/README	(revision 9)
@@ -0,0 +1,52 @@
+This a new implementation of a shutdown procedure. It allows 
+the system to go down graciously with informing the
+users. This package contains 3 programs:
+
+- halt = Immediately stop the system, no info to users
+- shutdown = Inform users, close down the system properly
+- wall = Vincent Archer's implementation of wall (Write all)
+
+Installing
+
+Shutdown and halt use a new systemcall, which I've added to
+MM. Therefor there are several diff's which should be applied:
+
+callnr.hd - New callnr for reboot(2)
+	   Diff against /usr/include/minix/callnr.h.
+	   Those of you using a symlink package should
+	   change the number and mm/table.c into a free
+	   number. I used 54, LSTAT.
+param.hd - Defines reboot_flag as a part of the messages
+proto.hd - Add's prototype for do_reboot()
+table.cd - Interpretation of the systemcall to MM
+mm.cd -	   I have added the do_reboot code to mm/getset.c but
+	   I couldn't find a getset.c to create a useable diff :-(
+	   So you can add where you want it. It is pure code, no diff.
+
+Now edit log.c and search for ``host''. Change this into your
+systemname or make it empty.
+
+Shutdown and halt log their actions in /usr/adm/log, edit the
+makefile and undefine -DLOG if you don't want this (this at the end of
+the makefile). You can change SHUT_LOG in shutdown.c and log.c if you
+want it in another file.
+
+Then type a `make'. This will take a minute or so (13 sec. with bcc :-).
+Remember to build a new image and update the ps_database.
+
+Type `make install' to place the program's where I've got them.
+Use them, try them and let me now if you've got problems running
+something.
+
+I have tested to sources both on 16-bits and 32-bits MINIX. I have compiled
+it with gcc, bcc and ACK, so that shouldn't really give a problem. Maybe
+the standard MINIX-make chokes on the makefile, atleast mine did.
+
+NOTE:
+	Make install does not place the man-pages somewhere. You should
+	do this yourself.
+
+--
+Edvard Tuinder        ed@pulstar.NL.mugnet.org    v892231@si.hhs.NL
+Student Computer Science
+Haagse Hogeschool, The Hague, The Netherlands
Index: /trunk/minix/commands/reboot/build
===================================================================
--- /trunk/minix/commands/reboot/build	(revision 9)
+++ /trunk/minix/commands/reboot/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/reboot/halt.c
===================================================================
--- /trunk/minix/commands/reboot/halt.c	(revision 9)
+++ /trunk/minix/commands/reboot/halt.c	(revision 9)
@@ -0,0 +1,133 @@
+/* halt / reboot - halt or reboot system (depends on name)
+
+   halt   - calling reboot() with RBT_HALT
+   reboot - calling reboot() with RBT_REBOOT
+
+   author: Edvard Tuinder   v892231@si.hhs.NL
+
+   This program calls the library function reboot(2) which performs
+   the system-call do_reboot. 
+
+ */
+
+#define _POSIX_SOURCE	1
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+void write_log _ARGS(( void ));
+void usage _ARGS(( void ));
+int main _ARGS(( int argc, char *argv[] ));
+
+char *prog;
+char *reboot_code = "delay; boot";
+
+void
+usage()
+{
+  fprintf(stderr, "Usage: %s [-hrRf] [-x reboot-code]\n", prog);
+  exit(1);
+}
+
+int
+main(argc,argv)
+int argc;
+char **argv;
+{
+  int flag = -1;		/* default action unknown */
+  int fast = 0;			/* fast halt/reboot, don't bother being nice. */
+  int i;
+  struct stat dummy;
+  char *monitor_code = "";
+  pid_t pid;
+
+  if ((prog = strrchr(argv[0],'/')) == NULL) prog = argv[0]; else prog++;
+
+  if (strcmp(prog, "halt") == 0) flag = RBT_HALT;
+  if (strcmp(prog, "reboot") == 0) flag = RBT_REBOOT;
+
+  i = 1;
+  while (i < argc && argv[i][0] == '-') {
+    char *opt = argv[i++] + 1;
+
+    if (*opt == '-' && opt[1] == 0) break;	/* -- */
+
+    while (*opt != 0) switch (*opt++) {
+      case 'h': flag = RBT_HALT; 	break;
+      case 'r': flag = RBT_REBOOT; 	break;
+      case 'R': flag = RBT_RESET; 	break;
+      case 'f': fast = 1; break;
+      case 'x':
+	flag = RBT_MONITOR;
+	if (*opt == 0) {
+	  if (i == argc) usage();
+	  opt = argv[i++];
+	}
+	monitor_code = opt;
+	opt = "";
+	break;
+      default:
+	usage();
+    }
+  }
+
+  if (i != argc) usage();
+
+  if (flag == -1) {
+    fprintf(stderr, "Don't know what to do when named '%s'\n", prog);
+    exit(1);
+  }
+
+  if (flag == RBT_REBOOT) {
+	flag = RBT_MONITOR;		/* set monitor code for reboot */
+	monitor_code = reboot_code;
+  }
+
+  if (stat("/usr/bin", &dummy) < 0) {
+    /* It seems that /usr isn't present, let's assume "-f." */
+    fast = 1;
+  }
+
+  signal(SIGHUP, SIG_IGN);
+  signal(SIGTERM, SIG_IGN);
+
+  /* Skip this part for fast shut down. */
+  if (! fast) {
+    /* Run the shutdown scripts. */
+    switch ((pid = fork())) {
+      case -1:
+	fprintf(stderr, "%s: can't fork(): %s\n", prog, strerror(errno));
+	exit(1);
+      case 0:
+	execl("/bin/sh", "sh", "/etc/rc", "down", (char *) NULL);
+	fprintf(stderr, "%s: can't execute: /bin/sh: %s\n",
+	  prog, strerror(errno));
+	exit(1);
+      default:
+	while (waitpid(pid, NULL, 0) != pid) {}
+    }
+  }
+
+  /* Tell init to stop spawning getty's. */
+  kill(1, SIGTERM);
+
+  /* Give everybody a chance to die peacefully. */
+  printf("Sending SIGTERM to all processes ...\n");
+  kill(-1, SIGTERM);
+  sleep(1);
+
+  write_log();
+
+  sync();
+
+  reboot(flag, monitor_code, strlen(monitor_code));
+  fprintf(stderr, "%s: reboot(): %s\n", strerror(errno));
+  return 1;
+}
Index: /trunk/minix/commands/reboot/log.c
===================================================================
--- /trunk/minix/commands/reboot/log.c	(revision 9)
+++ /trunk/minix/commands/reboot/log.c	(revision 9)
@@ -0,0 +1,81 @@
+/*
+  log - log the shutdown's and the halt's
+
+  Author: Edvard Tuinder  <v892231@si.hhs.NL>
+
+  shutdown is logged in /usr/adm/wtmp and in /usr/adm/log (if desired)
+  halt is logged only in /usr/adm/wtmp as `halt' to prevent last from
+       reporting halt's as crashes.
+
+ */
+
+#define _POSIX_SOURCE	1
+#include <sys/types.h>
+#include <stdio.h>
+#include <utmp.h>
+#include <pwd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+#undef WTMP
+
+static char WTMP[] = "/usr/adm/wtmp";	/* Record of logins and logouts. */
+static char SHUT_LOG[] = "/usr/adm/log";
+
+char who[8];
+extern char *prog;
+static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+			 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+void write_log _ARGS(( void ));
+
+void write_log()
+{
+  int fd;
+  static struct utmp wtmp;
+  static struct passwd *pwd;
+  char mes[90];
+  struct tm *tm;
+  time_t now;
+  struct utsname utsname;
+  char *host = "localhost";
+
+  time(&now);
+  tm = localtime(&now);
+
+  if (uname(&utsname) >= 0) host = utsname.nodename;
+
+  pwd = getpwuid(getuid());
+  if (pwd == (struct passwd *)0)
+    strcpy (who,"root");
+  else
+    strcpy (who,pwd->pw_name);
+  fd = open(WTMP,O_APPEND|O_WRONLY,1);
+  if (fd) {
+    if (strcmp(prog,"reboot"))
+      strcpy (wtmp.ut_user, prog);
+    else
+      strcpy (wtmp.ut_user, "shutdown"); /* last ... */
+    strcpy (wtmp.ut_id, "~~");
+    strcpy (wtmp.ut_line, "~");
+    wtmp.ut_pid = 0;
+    wtmp.ut_type = BOOT_TIME;
+    wtmp.ut_time = now;
+    wtmp.ut_host[0]= '\0';
+    write (fd, (char *) &wtmp,sizeof(struct utmp));
+    close(fd);
+  }
+  fd = open(SHUT_LOG,O_APPEND|O_WRONLY,1);
+  if (!fd) 
+    perror ("open");
+  else {
+    sprintf (mes,"%s %02d %02d:%02d:%02d %s: system %s by %s@%s\n",
+	month[tm->tm_mon],tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,
+	prog,prog,who,host);
+    write (fd,mes,strlen(mes));
+    close(fd);
+  }
+  return;
+}
Index: /trunk/minix/commands/reboot/sh_wall.c
===================================================================
--- /trunk/minix/commands/reboot/sh_wall.c	(revision 9)
+++ /trunk/minix/commands/reboot/sh_wall.c	(revision 9)
@@ -0,0 +1,109 @@
+/* wall - write to all logged in users			Author: V. Archer */
+/*
+   Edvard Tuinder    v892231@si.hhs.NL
+    Modified some things to include this with my shutdown/halt
+    package
+ */
+
+#define _POSIX_SOURCE	1
+#include <sys/types.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+#include <utmp.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+#include <sys/stat.h>
+#undef UTMP
+
+static char UTMP[] = "/etc/utmp";	/* Currently logged in users. */
+
+void wall _ARGS(( char *when, char *extra ));
+void crnlcat _ARGS(( char *message, char *more ));
+
+void
+wall(when, extra)
+char *when;			/* When is shutdown */
+char *extra;			/* If non-nil, why is the shutdown */
+{
+  struct utmp utmp;
+  char utmptty[5 + sizeof(utmp.ut_line) + 1];
+  char message[1024];
+  struct passwd *pw;
+  int utmpfd, ttyfd;
+  char *ourtty, *ourname;
+  time_t now;
+  struct utsname utsname;
+  struct stat con_st, tty_st;
+
+  if (ourtty = ttyname(1)) {
+	if (ourname = strrchr(ourtty, '/')) ourtty = ourname+1;
+  } else ourtty = "system task";
+  if (pw = getpwuid(getuid())) ourname = pw->pw_name;
+  else ourname = "unknown";
+
+  time(&now);
+  if (uname(&utsname) != 0) strcpy(utsname.nodename, "?");
+  sprintf(message, "\r\nBroadcast message from %s@%s (%s)\r\n%.24s...\r\n",
+		ourname, utsname.nodename, ourtty, ctime(&now));
+
+  crnlcat(message, when);
+  crnlcat(message, extra);
+
+/* Search the UTMP database for all logged-in users. */
+
+  if ((utmpfd = open(UTMP, O_RDONLY)) < 0) {
+	fprintf(stderr, "Cannot open utmp file\r\n");
+	return;
+  }
+
+  /* first the console */
+  strcpy(utmptty, "/dev/console");
+  if ((ttyfd = open(utmptty, O_WRONLY | O_NONBLOCK)) < 0) {
+	perror(utmptty);
+  } else {
+	fstat(ttyfd, &con_st);
+	write(ttyfd, message, strlen(message));
+	close(ttyfd);
+  }
+
+  while (read(utmpfd, (char *) &utmp, sizeof(utmp)) == sizeof(utmp)) {
+	/* is this the user we are looking for? */
+	if (utmp.ut_type != USER_PROCESS) continue;
+
+	strncpy(utmptty+5, utmp.ut_line, sizeof(utmp.ut_line));
+	utmptty[5 + sizeof(utmp.ut_line) + 1] = 0;
+	if ((ttyfd = open(utmptty, O_WRONLY | O_NONBLOCK)) < 0) {
+		perror(utmptty);
+		continue;
+	}
+	fstat(ttyfd, &tty_st);
+	if (tty_st.st_rdev != con_st.st_rdev)
+		write(ttyfd, message, strlen(message));
+	close(ttyfd);
+  }
+  close(utmpfd);
+  return;
+}
+
+void
+crnlcat(message, more)
+char *message, *more;
+{
+  char *p = message;
+  char *m = more;
+  char *end = message + 1024 - 1;
+
+  while (p < end && *p != 0) *p++;
+
+  while (p < end && *m != 0) {
+    if (*m == '\n' && (p == message || p[-1] != '\n')) {
+      *p++ = '\r';
+      if (p == end) p--;
+    }
+    *p++ = *m++;
+  }
+  *p = 0;
+}
Index: /trunk/minix/commands/reboot/shutdown.c
===================================================================
--- /trunk/minix/commands/reboot/shutdown.c	(revision 9)
+++ /trunk/minix/commands/reboot/shutdown.c	(revision 9)
@@ -0,0 +1,409 @@
+/*
+  shutdown - close down the system graciously
+
+  Author: Edvard Tuinder  <v892231@si.hhs.NL>
+
+  This program informs the users that the system is going
+  down, when and why. After that a shutdown notice is written in
+  both /usr/adm/wtmp and by syslog(3).  Then reboot(2) is called
+  to really close the system.
+
+  This actually is a ``nice'' halt(8).
+
+  Options are supposed to be as with BSD
+   -h: shutdown and halt the system
+   -r: shutdown and reboot
+   -k: stop an already running shutdown
+   -o: obsolete: not implemented
+
+  New Minix options:
+   -C: crash check, i.e. is the last wtmp entry a shutdown entry?
+   -x: let the monitor execute the given code
+   -R: reset the system
+ */
+
+#define _POSIX_SOURCE	1
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <time.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <errno.h>
+#undef WTMP
+
+static char WTMP[] =		"/usr/adm/wtmp";
+static char SHUT_PID[] =	"/usr/run/shutdown.pid";
+static char NOLOGIN[] =		"/etc/nologin";
+
+#ifndef __STDC__
+#define inform_user_time inf_time
+#define inform_user      inf_user
+#endif
+
+void usage _ARGS(( void ));
+void write_pid _ARGS(( void ));
+int inform_user_time _ARGS(( void ));
+void inform_user _ARGS(( void ));
+void terminate _ARGS(( void ));
+void wall _ARGS(( char *when, char *extra ));
+int crash_check _ARGS(( void ));
+void parse_time _ARGS(( char *arg ));
+void get_message _ARGS(( void ));
+void main _ARGS(( int argc, char *argv[] ));
+char *itoa _ARGS(( int n ));
+
+long wait_time=0L;
+char message[1024];
+char info[80];
+int reboot_flag='h';			/* default is halt */
+char *reboot_code="";			/* optional monitor code */
+int info_min, info_hour;
+char *prog;
+
+void parse_time (arg)
+char *arg;
+{
+  char *p = arg;
+  int hours, minutes;
+  time_t now;
+  struct tm *tm;
+  int delta = 0;
+  int bad = 0;
+  
+  if (p[0] == '+') { delta = 1; p++; }
+
+  hours = strtoul(p, &p, 10);
+  if (*p == 0 && delta) {
+    minutes = hours;
+    hours = 0;
+  } else {
+    if (*p != ':' && *p != '.')
+      bad = 1;
+    else
+      p++;
+    minutes = strtoul(p, &p, 10);
+    if (*p != 0) bad = 1;
+  }
+  if (bad) {
+    fprintf(stderr,"Invalid time specification `%s'\n",arg);
+    usage();
+  }
+
+  time(&now);
+  tm = localtime(&now);
+
+  if (!delta) {
+    hours -= tm->tm_hour;
+    minutes -= tm->tm_min;
+  }
+
+  if (minutes < 0) {
+    minutes += 60;
+    hours--;
+  }
+  if (hours < 0) hours += 24;	/* Time after midnight. */
+
+  tm->tm_hour += hours;
+  tm->tm_min += minutes;
+  (void) mktime(tm);
+  info_hour = tm->tm_hour;
+  info_min  = tm->tm_min;
+
+  sprintf(info,
+    "The system will shutdown in %d hour%s and %d minute%s at %02d:%02d\n\n",
+    hours,hours==1?"":"s",minutes,minutes==1?"":"s",info_hour,info_min);
+
+  wait_time += hours * 3600 + minutes * 60;
+  return;
+}
+
+void main(argc,argv)
+int argc;
+char *argv[];
+{
+  int i, now = 0, nologin = 0, want_terminate = 0, want_message = 0, check = 0;
+  char *opt;
+  int tty;
+  static char HALT1[] = "-?";
+  static char *HALT[] = { "shutdown", HALT1, NULL, NULL };
+
+  /* Parse options. */
+  for (i = 1; i < argc && argv[i][0] == '-'; i++) {
+    if (argv[i][1] == '-' && argv[i][2] == 0) {
+      /* -- */
+      i++;
+      break;
+    }
+    for (opt = argv[i] + 1; *opt != 0; opt++) {
+      switch (*opt) {
+      case 'k':
+	want_terminate = 1;
+	break;
+      case 'h':
+      case 'r':
+      case 'x':
+	reboot_flag = *opt;
+	if (reboot_flag == 'x') {
+	  if (*++opt == 0) {
+	    if (++i == argc) {
+	      fprintf (stderr,"shutdown: option '-x' requires an argument\n");
+	      usage();
+	    }
+	    opt=argv[i];
+	  }
+	  reboot_code=opt;
+	  opt="";
+	}
+	break;
+      case 'R':
+	reboot_flag = 'R';
+	break;
+      case 'm':
+	want_message = 1;
+	break;
+      case 'C':
+	check = 1;
+	break;
+      default:
+	fprintf (stderr,"shutdown: invalid option '-%c'\n",*opt);
+	usage();
+	break;
+      }
+    }
+  }
+  if ((argc - i) > 2) usage();
+
+  if (check) exit(crash_check() ? 0 : 2);
+
+  if (i == argc) {
+    /* No timespec, assume "now". */
+    now = 1;
+  } else {
+    if (!strcmp(argv[i], "now"))
+      now++;
+    else
+      parse_time(argv[i]);
+  }
+
+  if ((argc - i) == 2) {
+    /* One line message */
+    strcat(message, argv[i+1]);
+    strcat(message, "\n");
+  }
+
+  if (want_terminate) terminate();
+  if (want_message) get_message();
+
+  puts(info);
+
+  prog = strrchr(*argv,'/');
+  if (prog == (char *)0)
+    prog = *argv;
+  else
+    prog++;
+    
+  if (!now) {
+    /* Daemonize. */
+    switch (fork()) {
+    case 0:
+      break;
+    case -1:
+      fprintf(stderr, "%s: can't fork\n", prog);
+      exit(1);
+    default:
+      exit(0);
+    }
+    /* Detach from the terminal (if any). */
+    if ((tty = open("/dev/tty", O_RDONLY)) != -1) {
+      close(tty);
+      setsid();
+    }
+    write_pid();
+  }
+
+  for (;;) {
+    if (wait_time <= 5 * 60 && !nologin && !now) {
+      close(creat(NOLOGIN,00644));
+      nologin = 1;
+    }
+    if (wait_time <= 60) break;
+    if(inform_user_time())
+      inform_user();
+    sleep (60);
+    wait_time -= 60;
+  }
+  
+  if (!now) {
+    inform_user();
+    sleep (30);				/* Last minute before shutdown */
+    wait_time -= 30;
+    inform_user();
+    sleep (30);				/* Last 30 seconds before shutdown */
+  }
+  wait_time = 0;
+  inform_user();
+
+  unlink(SHUT_PID);			/* No way of stopping anymore */
+  unlink(NOLOGIN);
+
+  HALT[1][1] = reboot_flag;
+  if (reboot_flag == 'x') HALT[2] = reboot_code;
+#if __minix_vmd
+  execv("/usr/sbin/halt", HALT);
+#else
+  execv("/usr/bin/halt", HALT);
+#endif
+  if (errno != ENOENT)
+    fprintf(stderr, "Can't execute 'halt': %s\n", strerror(errno));
+
+  sleep(2);
+  reboot(RBT_HALT);
+  fprintf(stderr, "Reboot call failed: %s\n", strerror(errno));
+  exit(1);
+}
+
+void usage()
+{
+  fputs("Usage: shutdown [-hrRmk] [-x code] [time [message]]\n", stderr);
+  fputs("       -h -> halt system after shutdown\n", stderr);
+  fputs("       -r -> reboot system after shutdown\n", stderr);
+  fputs("       -R -> reset system after shutdown\n", stderr);
+  fputs("       -x -> return to the monitor doing...\n", stderr);
+  fputs("       -m -> read a shutdown message from standard input\n", stderr);
+  fputs("       -k -> stop an already running shutdown\n", stderr);
+  fputs("       code -> boot monitor code to be executed\n", stderr);
+  fputs("       time -> keyword ``now'', minutes before shutdown ``+5'',\n", stderr);
+  fputs("               or absolute time specification ``11:20''\n", stderr);
+  fputs("       message -> short shutdown message\n", stderr);
+  exit(1);
+}
+
+void terminate()
+{
+  FILE *in;
+  pid_t pid;
+  char c_pid[5];
+  char buf[80];
+
+  in = fopen(SHUT_PID,"r");
+  if (in == (FILE *)0) {
+    fputs ("Can't get pid of shutdown process, probably not running shutdown\n", stderr);
+    exit(1);
+  }
+  fgets(c_pid,5,in);
+  fclose(in);
+  pid = atoi(c_pid);
+  if (kill(pid,9) == -1)
+    fputs("Can't kill the shutdown process, probably not running anymore\n",stderr);
+  else
+    puts("Shutdown process terminated");
+  unlink(SHUT_PID);
+  unlink(NOLOGIN);
+#ifdef not_very_useful
+  in = fopen (SHUT_LOG,"a");
+  if (in == (FILE *)0)
+    exit(0);
+  sprintf (buf, "Shutdown with pid %d terminated\n",pid);
+  fputs(buf,in);
+  fclose(in);
+#endif
+  exit(0);
+}
+
+void get_message()
+{
+  char line[80];
+  int max_lines=12;
+
+  puts ("Type your message. End with ^D at an empty line");
+  fputs ("shutdown> ",stdout);fflush(stdout);
+  while (fgets(line,80,stdin) != (char *)0) {
+    strcat (message,line);
+    bzero(line,strlen(line));
+    fputs ("shutdown> ",stdout);fflush(stdout);
+  }
+  putc('\n',stdout);fflush(stdout);
+}
+
+int inform_user_time()
+{
+  int min;
+
+  min = wait_time /60;
+
+  if (min == 60 || min == 30 || min == 15 || min == 10 || min <= 5)
+    return 1;
+  else
+    return 0;
+}
+
+void inform_user()
+{
+  int hour, minute;
+  char mes[80];
+
+  hour = 0;
+  minute = wait_time / 60;
+  while (minute >= 60) {
+    minute -= 60;
+    hour++;
+  }
+
+  if (hour)
+    sprintf(mes,
+    "\nThe system will shutdown in %d hour%s and %d minute%s at %.02d:%.02d\n\n",
+    hour,hour==1?"":"s",minute,minute==1?"":"s",info_hour,info_min);
+  else
+  if (minute > 1)
+    sprintf(mes,
+    "\nThe system will shutdown in %d minutes at %.02d:%.02d\n\n",
+    minute,info_hour,info_min);
+  else
+  if (wait_time > 1)
+    sprintf(mes,
+    "\nThe system will shutdown in %d seconds\n\n",
+    wait_time);
+  else
+    sprintf(mes,
+    "\nThe system will shutdown NOW\n\n");
+
+  wall(mes,message);
+}
+
+void write_pid()
+{
+  char pid[5];
+  int fd;
+
+  fd = creat(SHUT_PID,00600);
+  if (!fd)
+    return;
+  strncpy (pid,itoa(getpid()), sizeof(pid));
+  write (fd,pid,sizeof(pid));
+  close(fd);
+  return;
+}
+
+int crash_check()
+{
+  struct utmp last;
+  int fd, crashed;
+  struct stat st;
+
+  if (stat(WTMP, &st) < 0 || st.st_size == 0) return 0;
+  if ((fd = open(WTMP, O_RDONLY)) < 0) return 0;
+
+  crashed = (lseek(fd, - (off_t) sizeof(last), SEEK_END) == -1
+    || read(fd, (void *) &last, sizeof(last)) != sizeof(last)
+    || last.ut_line[0] != '~'
+    || (strncmp(last.ut_user, "shutdown", sizeof(last.ut_user))
+     && strncmp(last.ut_user, "halt", sizeof(last.ut_user))));
+  close(fd);
+  return crashed;
+}
Index: /trunk/minix/commands/reboot/tinyhalt.c
===================================================================
--- /trunk/minix/commands/reboot/tinyhalt.c	(revision 9)
+++ /trunk/minix/commands/reboot/tinyhalt.c	(revision 9)
@@ -0,0 +1,43 @@
+/*	tinyhalt 1.0 - small forerunner			Author: Kees J. Bot
+ *
+ * Disk space on the root file system is a scarce resource.  This little
+ * program sits in /sbin.  It normally calls the real halt/reboot, but if
+ * that isn't available then it simply calls reboot().  Can't do any logging
+ * of the event anyhow.
+ */
+#define nil 0
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+
+int main(int argc, char **argv)
+{
+	int flag;
+	char *prog;
+	char *reboot_code = "delay; boot";
+
+	/* Try to run the real McCoy. */
+#if __minix_vmd
+	execv("/usr/sbin/halt", argv);
+#else
+	execv("/usr/bin/halt", argv);
+#endif
+
+	if ((prog = strrchr(*argv,'/')) == nil) prog= argv[0]; else prog++;
+
+	sleep(1);	/* Not too fast. */
+  	signal(SIGHUP, SIG_IGN);
+  	signal(SIGTERM, SIG_IGN);
+	kill(1, SIGTERM);
+	kill(-1, SIGTERM);
+	sleep(1);
+
+	reboot(strcmp(prog, "reboot") == 0 ? RBT_MONITOR : RBT_HALT,
+		reboot_code, strlen(reboot_code));
+
+	write(2, "reboot call failed\n", 19);
+	return 1;
+}
Index: /trunk/minix/commands/rlogind/Makefile
===================================================================
--- /trunk/minix/commands/rlogind/Makefile	(revision 9)
+++ /trunk/minix/commands/rlogind/Makefile	(revision 9)
@@ -0,0 +1,24 @@
+# Makefile for rlogind.
+
+CFLAGS	= $(OPT) -D_MINIX
+CC = exec cc
+LDFLAGS	=
+
+all:	rlogind
+
+OBJ=	rlogind.o setup.o
+
+rlogind:	$(OBJ)
+	$(CC) $(LDFLAGS) -o $@ $(OBJ)
+	install -S 8kw $@
+
+install:	/usr/bin/in.rlogind
+
+/usr/bin/in.rlogind:	rlogind
+	install -c $? $@
+
+clean:
+	rm -f *.o rlogind core a.out
+
+# Dependencies.
+$(OBJ):		rlogind.h
Index: /trunk/minix/commands/rlogind/build
===================================================================
--- /trunk/minix/commands/rlogind/build	(revision 9)
+++ /trunk/minix/commands/rlogind/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/rlogind/rlogind.c
===================================================================
--- /trunk/minix/commands/rlogind/rlogind.c	(revision 9)
+++ /trunk/minix/commands/rlogind/rlogind.c	(revision 9)
@@ -0,0 +1,455 @@
+/*
+rlogind.c
+
+Created:	by Philip Homburg <philip@cs.vu.nl>
+Log:		Utmp improvement by Kees Bot <kjb@cs.vu.nl>
+		Split to compile easier on i86 by kjb
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <net/hton.h>
+#define EXTERN
+#include "rlogind.h"
+
+char pty_str[]= "/dev/ptyXX";
+char tty_str[]= "/dev/ttyXX";
+char hex_str[16]= "0123456789abcdef";
+
+char PATH_UTMP[] = "/etc/utmp";		/* current logins */
+char PATH_WTMP[] = "/usr/adm/wtmp";	/* login/logout history */
+
+char term[64]= "TERM=";
+#define ENVSIZE (sizeof("TERM=")-1)	/* skip null for concatenation. */
+int confirmed= 0;
+char *env[2];
+char *args[10];
+
+static void do_child(int tty_fd, char *tty_str);
+static void dealloc_term(int slot, char *tty_str, int pid);
+static void wtmp(char *user, char *id, char *line, int pid, int type, int slot);
+static void setup_term(int fd);
+static speed_t num2speed(int num);
+static int do_control(char *buf, int cnt);
+static void readall(char *buf, int cnt);
+
+int main(int argc, char *argv[])
+{
+	int error;
+	int i, j= 0;
+	int tty_fd, pty_fd;
+	int login_pid, write_pid;
+	int count, bytes, tmp_count;
+	char *lp= 0, *cp;
+	struct stat struct_stat;
+	int slot;
+
+	prog_name= argv[0];
+
+	/* Check if the remote user is allowed in. */
+	authenticate();
+
+	write(1, "", 1);	/* Send the '\0' */
+	confirmed= 1;
+
+	/* We try to convince the other side not the do ^S/^Q, the rlogin
+	 * protocol indicates the we only send this when XOFF is turned off
+	 * but we don't know when this happens so we tell the other side that
+	 * it is turned off.
+	 */
+	tcp_urg(1, 1);
+
+	write(1, "\220", 1);
+
+	tcp_urg(1, 0);
+
+	/* Let's look for a pty. */
+	pty_fd= -1;
+	for (i= 'p'; i <= 'z'; i++)
+	{
+		pty_str[sizeof(pty_str)-3]= i;
+		pty_str[sizeof(pty_str)-2]= '0';
+		error= stat(pty_str, &struct_stat);
+		if (error == -1)
+			continue;
+		for (j= 0; j < 16; j++)
+		{
+			pty_str[sizeof(pty_str)-2]= hex_str[j];
+			pty_fd= open(pty_str, O_RDWR);
+			if (pty_fd != -1)
+				break;
+		}
+		if (pty_fd != -1)
+			break;
+	}
+	if (pty_fd == -1)
+	{
+		printf("%s: out of ptys\r\n", prog_name);
+		exit(1);
+	}
+	tty_str[sizeof(pty_str)-3]= i;
+	tty_str[sizeof(pty_str)-2]= hex_str[j];
+
+	tty_fd= open(tty_str, O_RDWR);
+	if (tty_fd == -1)
+	{
+		printf("%s: unable to open '%s': %s\r\n", prog_name, tty_str,
+			strerror(errno));
+		exit(1);
+	}
+
+	slot= fttyslot(tty_fd);
+
+	login_pid= fork();
+	if (login_pid == -1)
+	{
+		printf("%s: unable to fork: %s\r\n", prog_name,
+			strerror(errno));
+		exit(1);
+	}
+	if (login_pid == 0)
+	{
+		close(pty_fd);
+		wtmp("", "", tty_str, login_pid, LOGIN_PROCESS, slot);
+		do_child(tty_fd, tty_str);
+	}
+	close(tty_fd);
+
+	write_pid= fork();
+	if (write_pid == -1)
+	{
+		printf("%s: unable to fork: %s\r\n", prog_name,
+			strerror(errno));
+		exit(1);
+	}
+	if (write_pid == 0)
+	{
+		dup2(pty_fd, 0);
+		count= 0;
+		for (;;)
+		{
+			if (!count)
+			{
+				count= read(0, line, sizeof(line));
+				if (count <= 0)
+					break;
+				lp= line;
+			}
+			bytes= write(1, lp, count);
+			if (bytes <= 0 || bytes > count)
+				break;
+			lp += bytes;
+			count -= bytes;
+		}
+		kill(getppid(), SIGKILL);
+		dealloc_term(slot, tty_str, login_pid);
+		_exit(1);
+	}
+
+	dup2(pty_fd, 1);
+	count= 0;
+	for (;;)
+	{
+		if (!count)
+		{
+			count= read(0, line, sizeof(line));
+			if (count <= 0)
+				break;
+			lp= line;
+		}
+		tmp_count= count;
+		cp= memchr(lp, 255, count);
+		if (cp)
+		{
+			tmp_count= cp-lp;
+			if (tmp_count == 0)
+			{
+				tmp_count= do_control(lp, count);
+				if (tmp_count)
+				{
+					lp += tmp_count;
+					count -= tmp_count;
+					continue;
+				}
+			}
+		}
+		bytes= write(1, lp, tmp_count);
+		if (bytes <= 0 || bytes > count)
+			break;
+		lp += bytes;
+		count -= bytes;
+	}
+	kill(write_pid, SIGKILL);
+	dealloc_term(slot, tty_str, login_pid);
+	return(0);
+}
+
+static void do_child(int tty_fd, char *tty_str)
+{
+	int ctty_fd, tst_fd;
+	FILE *tty_file;
+	int sav_errno;
+	char **argp;
+
+	/* Set up the terminal attributes. */
+	setup_term(tty_fd);
+
+	/* Let's start the new session. */
+	setsid();
+	ctty_fd= open(tty_str, O_RDWR);
+	if (ctty_fd == -1)
+	{
+		printf("%s(do_child): unable to open '%s': %s\r\n",
+			prog_name, tty_str, strerror(errno));
+		exit(1);
+	}
+	/* Test if we really got a controlling tty. */
+	tst_fd= open("/dev/tty", O_RDWR);
+	if (tst_fd == -1)
+	{
+		printf(
+	"%s(do_child): '%s' didn't result in a controlling tty (%s)\r\n",
+			prog_name, tty_str, strerror(errno));
+		exit(1);
+	}
+
+	argp= args;
+	*argp++= "login";
+	*argp++= "-p";
+	*argp++= "-h";
+	*argp++= hostname;
+	if (authenticated)
+		*argp++= "-f";
+	if (lusername[0] != '\0')
+		*argp++= lusername;
+
+	/* We reached the point of no return. */
+	close(tst_fd);
+	close(tty_fd);
+
+	if (ctty_fd != 0)
+	{
+		dup2(ctty_fd, 0);
+		close(ctty_fd);
+		ctty_fd= 0;
+	}
+	dup2(ctty_fd, 1);
+#if DEBUG
+	fprintf(stderr, "execing login\r\n"); 
+#endif
+	dup2(ctty_fd, 2);
+	execve("/bin/login", args, env);
+	if (errno == ENOENT) execve("/usr/bin/login", args, env);
+	sav_errno= errno;
+	tty_file= fdopen(2, "w");
+	if (tty_file)
+	{
+		fprintf(tty_file, "%s(do_child): unable to exec login: %s\r\n",
+			prog_name, strerror(sav_errno));
+		fflush(tty_file);
+	}
+	_exit(1);
+}
+
+static void dealloc_term(int slot, char *tty_str, int pid)
+{
+  wtmp("", "", tty_str, pid, DEAD_PROCESS, slot);
+
+  /* Finally we reset the owner and mode of the terminal. */
+  chown(tty_str, 0, 0);
+  chmod(tty_str, 0666);
+}
+
+static void wtmp(
+	char *user,		/* name of user */
+	char *id,		/* inittab ID */
+	char *line,		/* TTY name */
+	int pid,		/* PID of process */
+	int type,		/* TYPE of entry */
+	int slot)		/* slot number in UTMP */
+{
+/* Log an event into the UTMP and WTMP files. */
+
+  struct utmp utmp;		/* UTMP/WTMP User Accounting */
+  int fd= -1;
+  int log = 1;			/* log in wtmp */
+  char *p;
+
+  /* Strip the /dev part of the TTY name. */
+  p = strrchr(line, '/');
+  if (p != 0)
+	line= p+1;
+
+  if (type == DEAD_PROCESS) {
+	/* Don't add a logout entry for just a dying login. */
+	if ((fd = open(PATH_UTMP, O_RDONLY)) < 0) return;
+	if (lseek(fd, (off_t) slot * sizeof(utmp), SEEK_SET) != -1
+		&& read(fd, (void *) &utmp, sizeof(utmp)) == sizeof(utmp))
+	{
+		if (utmp.ut_type != INIT_PROCESS
+				&& utmp.ut_type != USER_PROCESS)
+			log= 0;
+	}
+	close(fd);
+  }
+  if (type == LOGIN_PROCESS) log= 0;	/* and don't log this one */
+
+  /* Clear the utmp record. */
+  memset((void *) &utmp, 0, sizeof(utmp));
+
+  /* Enter new values. */
+  strncpy(utmp.ut_name, user, sizeof(utmp.ut_name));
+  strncpy(utmp.ut_id, id, sizeof(utmp.ut_id));
+  strncpy(utmp.ut_line, line, sizeof(utmp.ut_line));
+  strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host));
+  utmp.ut_pid = pid;
+  utmp.ut_type = type;
+  utmp.ut_time = time((time_t *)0);
+
+  if (log) {
+	if ((fd = open(PATH_WTMP, O_WRONLY | O_APPEND)) < 0) return;
+	write(fd, (char *) &utmp, sizeof(struct utmp));
+	close(fd);
+  }
+
+  /* write entry to utmp */
+  if ((fd = open(PATH_UTMP, O_WRONLY)) < 0) return;
+  if (lseek(fd, (off_t) slot * sizeof(utmp), SEEK_SET) != -1)
+	write(fd, (char *) &utmp, sizeof(struct utmp));
+  close(fd);
+}
+
+void fatal(int fd, char *msg, int err)
+{
+	int len;
+	char buf[80], *bp;
+
+	bp= buf;
+	if (!confirmed)
+		*bp++= '\1';
+	if (err)
+		len= sprintf(bp, "rlogind: %s: %s.\r\n", msg, strerror(err));
+	else
+		len= sprintf(bp, "rlogind: %s.\r\n", msg);
+	write(fd, buf, bp+len-buf);
+	exit(1);
+}
+
+static void setup_term(int fd)
+{
+	char *cp, *speed;
+	struct termios tt;
+	speed_t spd;
+	int num;
+	char *check;
+
+	cp= strchr(term, '/');
+	if (cp)
+	{
+		tcgetattr(fd, &tt);
+		*cp++= '\0';
+		speed= cp;
+		cp= strchr(speed, '/');
+		if (cp)
+			*cp++= '\0';
+		num= strtol(speed, &check, 0);
+		spd= num2speed(num);
+		if (spd != B0 && check[0] == '\0')
+		{
+			cfsetospeed(&tt, spd);
+			cfsetispeed(&tt, spd);
+		}
+		tcsetattr(fd, TCSANOW, &tt);
+	}
+	env[0]= term;
+	env[1]= 0;
+}
+
+static speed_t num2speed(int num)
+{
+	static struct 
+	{
+		int num;
+		speed_t value;
+	} speed_table[]=
+	{
+		{ 0, B0, }, { 50, B50, }, { 75, B75, }, { 110, B110, },
+		{ 134, B134, }, { 150, B150, }, { 200, B200, }, { 300, B300, },
+		{ 600, B600, }, { 1200, B1200, }, { 1800, B1800, },
+		{ 2400, B2400, }, { 4800, B4800, }, { 9600, B9600, },
+		{ 19200, B19200, }, { 38400, B38400, },
+		{ -1, -1 },
+	};
+	int i;
+
+	for (i= 0; speed_table[i].num != -1; i++)
+	{
+		if (speed_table[i].num == num)
+			return (speed_table[i].value);
+	}
+	return B0;
+}
+
+static int do_control(char *cp, int cnt)
+{
+	char buf[20];
+	struct winsize winsize;
+
+	if (cnt > sizeof(buf))
+		cnt= sizeof(buf);
+
+	memcpy(buf, cp, cnt);
+
+	/* Let's fetch the first 2 bytes. */
+	if (cnt < 2)
+		readall(buf+cnt, 2-cnt);
+	if ((unsigned char)buf[1] != 255)
+		return 0;
+
+	/* Let's fetch the first 4 bytes. */
+	if (cnt < 4)
+		readall(buf+cnt, 4-cnt);
+	if (buf[2] != 's' || buf[3] != 's')
+		return 0;
+
+	/* Let's fetch a winsize structure. */
+	if (cnt < 4 + sizeof(winsize))
+		readall(buf+cnt, 4 + sizeof(winsize) - cnt);
+
+	memcpy(&winsize, buf+4, sizeof(winsize));
+	winsize.ws_row= ntohs(winsize.ws_row);
+	winsize.ws_col= ntohs(winsize.ws_col);
+	winsize.ws_xpixel= ntohs(winsize.ws_xpixel);
+	winsize.ws_ypixel= ntohs(winsize.ws_ypixel);
+#if DEBUG
+	fprintf(stderr, "setting window size to %d, %d\r\n", winsize.ws_row,
+		winsize.ws_col);
+#endif
+	ioctl(1, TIOCSWINSZ, &winsize);
+	return 4 + sizeof(winsize);
+}
+
+static void readall(char *buf, int cnt)
+{
+	int res;
+
+	while(cnt)
+	{
+		res= read(0, buf, cnt);
+		if (res <= 0)
+			return;
+		buf += cnt;
+		cnt -= res;
+	}
+}
Index: /trunk/minix/commands/rlogind/rlogind.h
===================================================================
--- /trunk/minix/commands/rlogind/rlogind.h	(revision 9)
+++ /trunk/minix/commands/rlogind/rlogind.h	(revision 9)
@@ -0,0 +1,24 @@
+/*
+in.rld.h
+*/
+
+#define NMAX	30
+
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+EXTERN char *prog_name;
+EXTERN char hostname[256+1];
+EXTERN char line[1024];
+EXTERN char lusername[NMAX+1], rusername[NMAX+1];
+EXTERN char term[64];
+EXTERN int authenticated;
+
+/* in.rld.c: */
+void fatal(int fd, char *msg, int err);
+
+/* setup.c: */
+void authenticate(void);
+int do_rlogin(void);
+void tcp_urg(int fd, int on);
Index: /trunk/minix/commands/rlogind/setup.c
===================================================================
--- /trunk/minix/commands/rlogind/setup.c	(revision 9)
+++ /trunk/minix/commands/rlogind/setup.c	(revision 9)
@@ -0,0 +1,92 @@
+/*
+setup.c
+*/
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <net/netlib.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/netdb.h>
+#include <net/gen/socket.h>
+#include "rlogind.h"
+
+static void getstr(char *buf, int cnt, char *errmsg);
+
+void authenticate(void)
+{
+	int result;
+	struct nwio_tcpconf tcpconf;
+	struct hostent *hostent;
+	char c;
+
+	/* Let's lookup the hostname for the connection. */
+	result= ioctl (0, NWIOGTCPCONF, &tcpconf);
+	if (result<0)
+	{
+		fprintf(stderr, "%s: ioctl(NWIOTCPCONF): %s\r\n", 
+			prog_name, strerror(errno));
+		exit(1);
+	}
+	hostent= gethostbyaddr((char *)&tcpconf.nwtc_remaddr,
+		sizeof(tcpconf.nwtc_remaddr), AF_INET);
+	if (hostent)
+	{
+		strncpy(hostname, hostent->h_name, sizeof(hostname)-1);
+		hostname[sizeof(hostname)-1]= '\0';
+	}
+	else
+	{
+		strcpy(hostname, inet_ntoa(tcpconf.nwtc_remaddr));
+	}
+
+	authenticated = 0;
+
+	getstr(&c, 1, "protocol violation");
+	getstr(rusername, sizeof(rusername), "remuser too long");
+	getstr(lusername, sizeof(lusername), "locuser too long");
+	strcpy(term, "TERM=");
+	getstr(term+5, sizeof(term)-5, "Terminal type too long");
+
+#if DEBUG
+	fprintf(stderr, "got lu= %s, ru= %s, te= %s\r\n", lusername, rusername,
+		term);
+#endif
+	if (iruserok(tcpconf.nwtc_remaddr, 0, rusername, lusername) == 0)
+		authenticated = 1;
+}
+
+static void getstr(char *buf, int cnt, char *errmsg)
+{
+	char c;
+
+	errno= 0;
+	do
+	{
+		if (read(0, &c, 1) != 1)
+			fatal(1, "read failed", errno);
+		cnt--;
+		if (cnt < 0)
+			fatal(1, errmsg, 0);
+		*buf++= c;
+	} while(c != 0);
+}
+
+void tcp_urg(int fd, int on)
+{
+	struct nwio_tcpopt tcpopt;
+
+	tcpopt.nwto_flags= on ? (NWTO_BSD_URG | NWTO_SND_URG) : NWTO_SND_NOTURG;
+	if (ioctl(1, NWIOSTCPOPT, &tcpopt) == -1)
+	{
+		fprintf(stderr, "rlogind: NWIOSTCPOPT failed: %s\r\n",
+			strerror(errno));
+	}
+}
Index: /trunk/minix/commands/scripts/DESCRIBE.sh
===================================================================
--- /trunk/minix/commands/scripts/DESCRIBE.sh	(revision 9)
+++ /trunk/minix/commands/scripts/DESCRIBE.sh	(revision 9)
@@ -0,0 +1,188 @@
+#!/bin/sh
+#
+# DESCRIBE 2.2 - Describe the given devices.		Author: Kees J. Bot
+#
+# BUGS
+# - Arguments may not contain shell metacharacters.
+
+case $# in
+0)	flag=; set -$- /dev ;;
+*)	flag=d ;;
+esac
+
+ls -l$flag $* | \
+sed	-e '/^total/d' \
+	-e '/^[^bc]/s/.* /BAD BAD /' \
+	-e '/^[bc]/s/.* \([0-9][0-9]*\), *\([0-9][0-9]*\).* /\1 \2 /' \
+| {
+ex=0	# exit code
+
+while read major minor path
+do
+    case $path in
+    /*)	name=`expr $path : '.*/\\(.*\\)$'`
+	;;
+    *)	name=$path
+    esac
+    dev= des=
+
+    case $major in	# One of the controllers?  What is its controller nr?
+    3)	ctrlr=0	;;
+    8)	ctrlr=1	;;
+    10)	ctrlr=2	;;
+    12)	ctrlr=3	;;
+    esac
+
+    case $major,$minor in
+    1,0)	des="RAM disk" dev=ram
+	;;
+    1,1)	des="memory" dev=mem
+	;;
+    1,2)	des="kernel memory" dev=kmem
+	;;
+    1,3)	des="null device, data sink" dev=null
+	;;
+    2,*)	drive=`expr $minor % 4`
+	case `expr $minor - $drive` in
+	0)	des='auto density' dev="fd$drive"
+	    ;;
+	4)	des='360k, 5.25"' dev="pc$drive"
+	    ;;
+	8)	des='1.2M, 5.25"' dev="at$drive"
+	    ;;
+	12)	des='360k in 720k, 5.25"' dev="qd$drive"
+	    ;;
+	16)	des='720k, 3.5"' dev="ps$drive"
+	    ;;
+	20)	des='360k in 1.2M, 5.25"' dev="pat$drive"
+	    ;;
+	24)	des='720k in 1.2M, 5.25"' dev="qh$drive"
+	    ;;
+	28)	des='1.44M, 3.5"' dev="PS$drive"
+	    ;;
+	112)	des='auto partition 0' dev="fd${drive}p0"
+	    ;;
+	116)	des='auto partition 1' dev="fd${drive}p1"
+	    ;;
+	120)	des='auto partition 2' dev="fd${drive}p2"
+	    ;;
+	124)	des='auto partition 3' dev="fd${drive}p3"
+	    ;;
+	*)	dev=BAD
+	esac
+	des="floppy drive $drive ($des)"
+	;;
+    [38],[05]|[38],[123][05]|1[02],[05]|1[02],[123][05])
+	drive=`expr $minor / 5`
+	des="controller $ctrlr disk $drive" dev=c${ctrlr}d${drive}
+	;;
+    [38],?|[38],[123]?|1[02],?|1[02],[123]?)
+	drive=`expr $minor / 5`
+	par=`expr $minor % 5 - 1`
+	des="controller $ctrlr disk $drive partition $par"
+	dev=c${ctrlr}d${drive}p${par}
+	;;
+    [38],12[89]|[38],1[3-9]?|[38],2??|1[02],12[89]|1[02],1[3-9]?|1[02],2??)
+	drive=`expr \\( $minor - 128 \\) / 16`
+	par=`expr \\( \\( $minor - 128 \\) / 4 \\) % 4`
+	sub=`expr \\( $minor - 128 \\) % 4`
+	des="hard disk $drive, partition $par, subpartition $sub"
+	des="controller $ctrlr disk $drive partition $par slice $sub"
+	#par=`expr $drive '*' 5 + $par`
+	dev=c${ctrlr}d${drive}p${par}s${sub}
+	;;
+    [38],6[4-9]|[38],7?|1[02],6[4-9]|1[02],7?)
+	tape=`expr \\( $minor - 64 \\) / 2`
+	case $minor in
+	*[02468])
+	    des="controller $ctrlr tape $tape (non-rewinding)"
+	    dev=c${ctrlr}t${tape}n
+	    ;;
+	*[13579])
+	    des="controller $ctrlr tape $tape (rewinding)"
+	    dev=c${ctrlr}t${tape}
+	esac
+	;;
+    4,0)	des="console device" dev=console
+	;;
+    4,[1-7])des="virtual console $minor" dev=ttyc$minor
+	;;
+    4,15)	des="diagnostics device" dev=log
+	;;
+    4,1[6-9])
+	line=`expr $minor - 16`
+	des="serial line $line" dev=tty0$line
+	;;
+    4,12[89]|4,1[3-8]?|4,19[01])
+	p=`expr \\( $minor - 128 \\) / 16 | tr '0123' 'pqrs'`
+	n=`expr $minor % 16`
+	test $n -ge 10 && n=`expr $n - 10 | tr '012345' 'abcdef'`
+	des="pseudo tty `expr $minor - 128`" dev=tty$p$n
+	;;
+    4,???)
+	p=`expr \\( $minor - 192 \\) / 16 | tr '0123' 'pqrs'`
+	n=`expr $minor % 16`
+	test $n -ge 10 && n=`expr $n - 10 | tr '012345' 'abcdef'`
+	des="controller of tty$p$n" dev=pty$p$n
+	;;
+    5,0)	des="anonymous tty" dev=tty
+	;;
+    6,0)	des="line printer, parallel port" dev=lp
+	;;
+    7,*)
+	d=`expr $minor % 8`
+	n=`expr $minor / 8`
+	case $d in
+	0)  case $name in
+	    psip*)
+		des="Pseudo IP #$n" dev=psip
+		;;
+	    *)  des="raw ethernet #$n" dev=eth
+	    esac
+	    ;;
+	1)  des="raw IP #$n" dev=ip
+	    ;;
+	2)  des="TCP/IP #$n" dev=tcp
+	    ;;
+	3)  des="UDP #$n" dev=udp
+	esac
+	case $d in
+	[0123])
+	    if [ "$name" = "$dev" ]
+	    then
+		des="$des (default)"
+	    else
+		dev=$dev$n
+	    fi
+	esac
+	;;
+    13,0)
+	des="audio" dev=audio
+	;;
+    14,0)
+	des="audio mixer" dev=mixer
+	;;
+    BAD,BAD)
+	des= dev=
+	;;
+    *)	dev=BAD
+    esac
+
+    case $name:$dev in
+    *:)
+	echo "$path: not a device" >&2
+	ex=1
+	;;
+    *:*BAD*)
+	echo "$path: cannot describe: major=$major, minor=$minor" >&2
+	ex=1
+	;;
+    $dev:*)
+	echo "$path: $des"
+	;;
+    *:*)	echo "$path: nonstandard name for $dev: $des"
+    esac
+done
+
+exit $ex
+}
Index: /trunk/minix/commands/scripts/M.sh
===================================================================
--- /trunk/minix/commands/scripts/M.sh	(revision 9)
+++ /trunk/minix/commands/scripts/M.sh	(revision 9)
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+#	M, U - mount or unmount standard devices.
+
+case $#:$2 in
+1:|2:-r)	;;
+*)	echo "Usage: $0 <abbreviation> [-r]" >&2; exit 1
+esac
+
+. /etc/fstab
+
+dev=$1 dir=$1
+
+case $1 in
+0)	dev=/dev/fd0 dir=fd0 ;;
+1)	dev=/dev/fd1 dir=fd1 ;;
+PS0|at0|fd0|pat0|pc0|ps0)	dev=/dev/$dev dir=fd0 ;;
+PS1|at1|fd1|pat1|pc1|ps1)	dev=/dev/$dev dir=fd1 ;;
+root)	dev=$root ;;
+tmp)	dev=$tmp ;;
+usr)	dev=$usr ;;
+*)	dev=/dev/$dev dir=mnt
+esac
+
+case $0 in
+*M)	mount $dev /$dir $2 ;;
+*U)	umount $dev
+esac
Index: /trunk/minix/commands/scripts/MAKEDEV.sh
===================================================================
--- /trunk/minix/commands/scripts/MAKEDEV.sh	(revision 9)
+++ /trunk/minix/commands/scripts/MAKEDEV.sh	(revision 9)
@@ -0,0 +1,267 @@
+#!/bin/sh
+#
+# MAKEDEV 3.3 - Make special devices.			Author: Kees J. Bot
+
+case $1 in
+-n)	e=echo; shift ;;	# Just echo when -n is given.
+*)	e=
+esac
+
+case $#:$1 in
+1:std)		# Standard devices.
+    set -$- mem fd0 fd1 fd0p0 fd1p0 \
+	c0d0 c0d0p0 c0d0p0s0 c0d1 c0d1p0 c0d1p0s0 \
+	c0d2 c0d2p0 c0d2p0s0 c0d3 c0d3p0 c0d3p0s0 \
+	c0d4 c0d4p0 c0d4p0s0 c0d5 c0d5p0 c0d5p0s0 \
+	c0d6 c0d6p0 c0d6p0s0 c0d7 c0d7p0 c0d7p0s0 \
+	tty ttyc1 ttyc2 ttyc3 tty00 tty01 tty02 tty03 \
+	ttyp0 ttyp1 ttyp2 ttyp3 ttyp4 ttyp5 ttyp6 ttyp7 ttyp8 ttyp9 \
+	ttypa ttypb ttypc ttypd ttype ttypf \
+	ttyq0 ttyq1 ttyq2 ttyq3 ttyq4 ttyq5 ttyq6 ttyq7 ttyq8 ttyq9 \
+	ttyqa ttyqb ttyqc ttyqd ttyqe ttyqf \
+	eth klog random cmos rescue
+    ;;
+0:|1:-\?)
+    cat >&2 <<EOF
+Usage:	$0 [-n] key ...
+Where key is one of the following:
+  ram mem kmem null boot zero	  # One of these makes all these memory devices
+  fd0 fd1 ...		  # Floppy devices for drive 0, 1, ...
+  fd0p0 fd1p0 ...	  # Make floppy partitions fd0p[0-3], fd1p[0-3], ...
+  c0d0 c0d1 ...		  # Make disks c0d0, c0d1, ...
+  c0d0p0 c0d1p0 ...	  # Make partitions c0d0p[0-3], c0d1p[0-3], ...
+  c0d0p0s0 c0d1p0s0 ...	  # Subparts c0d0p[0-3]s[0-3], c0d1p[0-3]s[0-3], ...
+  c1d0(p0)(s0)		  # Likewise for controller 1
+  c0t0 c0t1 c1t0 ...	  # Make tape devices c0t0, c0t0n, c0t1, ...
+  console lp tty log	  # One of these makes all four
+  ttyc1 ... ttyc7         # Virtual consoles
+  tty00 ... tty03         # Make serial lines
+  ttyp0 ... ttyq0 ...     # Make tty, pty pairs
+  eth ip tcp udp	  # One of these makes some TCP/IP devices
+  audio mixer		  # Make audio devices
+  klog                    # Make /dev/klog
+  random                  # Make /dev/random, /dev/urandom
+  cmos                    # Make /dev/cmos
+  kbd                     # Make /dev/kbd
+  kbdaux                  # Make /dev/kbdaux
+  rescue                  # Make /dev/rescue
+  video                   # Make /dev/video
+  std			  # All standard devices
+EOF
+    exit 1
+esac
+
+umask 077
+ex=0
+
+for dev
+do
+    case $dev in	# One of the controllers?  Precompute major device nr.
+    c0*) maj=3  ;;
+    c1*) maj=8  ;;
+    c2*) maj=10 ;;
+    c3*) maj=12 ;;
+    esac
+
+    case $dev in
+    ram|mem|kmem|null|boot|zero)
+	# Memory devices.
+	#
+	$e mknod ram b 1 0;	$e chmod 600 ram
+	$e mknod mem c 1 1;	$e chmod 640 mem
+	$e mknod kmem c 1 2;	$e chmod 640 kmem
+	$e mknod null c 1 3;	$e chmod 666 null
+	$e mknod boot b 1 4;	$e chmod 600 ram
+	$e mknod zero c 1 5;	$e chmod 644 zero
+	$e chgrp kmem ram mem kmem null boot zero
+	;;
+    fd[0-3])
+	# Floppy disk drive n.
+	#
+	d=`expr $dev : '.*\\(.\\)'`	# Drive number.
+	$e mknod $dev  b 2 $d
+	$e chmod 666 $dev
+	;;
+    pc[0-3]|at[0-3]|qd[0-3]|ps[0-3]|pat[0-3]|qh[0-3]|PS[0-3])
+	# Obsolete density locked floppy disk drive n.
+	#
+	d=`expr $dev : '.*\\(.\\)'`	# Drive number.
+	m=$d				# Minor device number.
+
+	$e mknod pc$d  b 2 $m;	m=`expr $m + 4`
+	$e mknod at$d  b 2 $m;	m=`expr $m + 4`
+	$e mknod qd$d  b 2 $m;	m=`expr $m + 4`
+	$e mknod ps$d  b 2 $m;	m=`expr $m + 4`
+	$e mknod pat$d b 2 $m;	m=`expr $m + 4`
+	$e mknod qh$d  b 2 $m;	m=`expr $m + 4`
+	$e mknod PS$d  b 2 $m;	m=`expr $m + 4`
+
+	$e chmod 666 pc$d at$d qd$d ps$d pat$d qh$d PS$d
+	;;
+    fd[0-3]p[0-3])
+	# Floppy disk partitions.
+	#
+	n=`expr $dev : '\\(.*\\)..'`	# Name prefix.
+	d=`expr $dev : '..\\(.\\)'`	# Drive number.
+	m=`expr 112 + $d`		# Minor of partition 0.
+	alldev=
+
+	for p in 0 1 2 3
+	do
+	    m=`expr 112 + $d + $p '*' 4` # Minor of partition $p.
+	    $e mknod ${n}p${p} b 2 $m	# Make e.g. fd0p0 - fd0p3
+	    alldev="$alldev ${n}p${p}"
+	done
+	$e chmod 666 $alldev
+	;;
+    c[0-3]d[0-7])
+	# Whole disk devices.
+	d=`expr $dev : '...\\(.\\)'`	# Disk number.
+	m=`expr $d '*' 5`		# Minor device number.
+	$e mknod $dev b $maj $m
+	$e chmod 600 $dev
+	;;
+    c[0-3]d[0-7]p[0-3])
+	# Disk primary partitions.
+	n=`expr $dev : '\\(.*\\).'`	# Name prefix.
+	d=`expr $dev : '...\\(.\\)'`	# Disk number.
+	alldev=
+
+	for p in 0 1 2 3
+	do
+	    m=`expr $d '*' 5 + 1 + $p`	# Minor device number.
+	    $e mknod $n$p b $maj $m
+	    alldev="$alldev $n$p"
+	done
+	$e chmod 600 $alldev
+	;;
+    c[0-3]d[0-7]p[0-3]s[0-3])
+	# Disk subpartition.
+	n=`expr $dev : '\\(.*\\)...'`	# Name prefix.
+	d=`expr $dev : '...\\(.\\)'`	# Disk number.
+	alldev=
+
+	for p in 0 1 2 3
+	do
+	    for s in 0 1 2 3
+	    do
+		m=`expr 128 + $d '*' 16 + $p '*' 4 + $s`  # Minor device nr.
+		$e mknod ${n}${p}s${s} b $maj $m
+		alldev="$alldev ${n}${p}s${s}"
+	    done
+	done
+	$e chmod 600 $alldev
+	;;
+    c[0-3]t[0-7]|c[0-3]t[0-7]n)
+	# Tape devices.
+	n=`expr $dev : '\\(....\\)'`	# Name prefix.
+	t=`expr $dev : '...\\(.\\)'`	# Tape number.
+	m=`expr 64 + $t '*' 2`		# Minor device number.
+	$e mknod ${n}n c $maj $m
+	$e mknod ${n} c $maj `expr $m + 1`
+	$e chmod 660 ${n}n ${n}
+	;;
+    console|lp|tty|log|kbd|kbdaux|video)
+	# Console, line printer, anonymous tty, diagnostics device,
+	# raw keyboard, ps/2 mouse, video.
+	$e mknod console c 4 0
+	$e chmod 600 console
+	$e chgrp tty console
+	$e mknod tty c 5 0
+	$e chmod 666 tty
+	$e mknod lp c 6 0
+	$e chown daemon lp
+	$e chgrp daemon lp
+	$e chmod 200 lp
+	$e mknod log c 4 15
+	$e chmod 222 log
+	$e mknod kbd c 4 127
+	$e mknod kbdaux c 4 126
+	$e chmod 660 kbd kbdaux
+	$e chgrp operator kbd kbdaux
+	$e mknod video c 4 125
+	$e chmod 600 video
+	$e chgrp operator video
+	;;
+    ttyc[1-7])
+	# Virtual consoles.
+	#
+	m=`expr $dev : '....\\(.*\\)'`	# Minor device number.
+	$e mknod $dev c 4 $m
+	$e chgrp tty $dev
+	$e chmod 600 $dev
+	;;
+    tty0[0-3])
+	# Serial lines.
+	#
+	n=`expr $dev : '.*\\(.\\)'`
+	$e mknod $dev c 4 `expr $n + 16`
+	$e chmod 666 $dev
+	$e chgrp tty $dev
+	;;
+    tty[p-s][0-9a-f]|pty[p-s][0-9a-f])
+	# Pseudo ttys.
+	#
+	dev=`expr $dev : '...\\(..\\)'`
+	g=`expr $dev : '\\(.\\)'`	# Which group.
+	g=`echo $g | tr 'pqrs' '0123'`
+	n=`expr $dev : '.\\(.\\)'`	# Which pty in the group.
+	case $n in
+	[a-f])	n=1`echo $n | tr 'abcdef' '012345'`
+	esac
+
+	$e mknod tty$dev c 4 `expr $g '*' 16 + $n + 128`
+	$e mknod pty$dev c 4 `expr $g '*' 16 + $n + 192`
+	$e chgrp tty tty$dev pty$dev
+	$e chmod 666 tty$dev pty$dev
+	;;
+    eth|ip|tcp|udp|eth0|ip0|tcp0|udp0)
+	# TCP/IP devices.
+	#
+	$e mknod eth0 c 7 0		# Network 0 (Ethernet)
+	$e mknod ip0 c 7 1
+	$e mknod tcp0 c 7 2
+	$e mknod udp0 c 7 3
+	$e chmod 600 eth0 ip0
+	$e chmod 666 tcp0 udp0
+	$e ln -f eth0 eth		# Default interface
+	$e ln -f ip0 ip
+	$e ln -f tcp0 tcp
+	$e ln -f udp0 udp
+	;;
+    audio|mixer)
+	# Audio devices.
+	#
+   $e mknod audio c 13 0
+   $e mknod rec c 13 1
+   $e mknod mixer c 13 2
+   $e chmod 666 audio rec mixer
+	;;
+    random|urandom)
+	# random data generator.
+	$e mknod random c 16 0;	$e chmod 644 random
+	$e mknod urandom c 16 0; $e chmod 644 urandom
+	$e chgrp operator random urandom
+	;;
+    cmos)
+    	# cmos device (set/get system time).
+    	$e mknod cmos c 17 0
+	$e chmod 600 cmos
+	;;
+    rescue)
+    	# rescue device
+    	$e mknod rescue b 9 0
+	$e chmod 644 rescue
+	;;
+    klog)
+    	# logging device.
+    	$e mknod klog c 15 0
+	$e chmod 600 klog
+	;;
+    *)
+	echo "$0: don't know about $dev" >&2
+	ex=1
+    esac
+done
+
+exit $ex
Index: /trunk/minix/commands/scripts/Makefile
===================================================================
--- /trunk/minix/commands/scripts/Makefile	(revision 9)
+++ /trunk/minix/commands/scripts/Makefile	(revision 9)
@@ -0,0 +1,180 @@
+# Makefile for cmd/scripts.
+
+CFLAGS	= -D_MINIX -D_POSIX_SOURCE
+CCLD	= $(CC) -i $(CFLAGS)
+MAKE	= exec make -$(MAKEFLAGS) install
+
+all:		# Does nothing
+
+install:	usr root
+
+# Commands on the /usr partition.
+usr:	\
+	/usr/bin/DESCRIBE \
+	/usr/bin/M \
+		/usr/bin/U \
+	/usr/bin/MAKEDEV \
+	/usr/bin/bigmake \
+	/usr/bin/adduser \
+	/usr/bin/binpackage \
+	/usr/bin/binpackages \
+	/usr/bin/cd \
+		/usr/bin/[ \
+		/usr/bin/command \
+		/usr/bin/easypack \
+		/usr/bin/echo \
+		/usr/bin/expr \
+		/usr/bin/false \
+		/usr/bin/getopts \
+		/usr/bin/getpack \
+		/usr/bin/read \
+		/usr/bin/test \
+		/usr/bin/true \
+		/usr/bin/umask \
+		/usr/bin/wait \
+	/usr/bin/checkhier \
+	/usr/bin/clear \
+		/usr/bin/clr \
+	/usr/bin/makewhatis \
+	/usr/bin/mkdep \
+	/usr/bin/mkdist \
+	/bin/setup \
+	/usr/bin/binsizes \
+	/usr/bin/rotate \
+	/usr/bin/floppysetup \
+	/usr/bin/packit \
+	/usr/bin/packman \
+	/usr/bin/spell \
+	/usr/bin/srccrc \
+	/usr/bin/svclog \
+	/usr/bin/version \
+	/usr/bin/whatis \
+		/usr/bin/apropos \
+	/usr/bin/whereis \
+
+# Commands on the root partition.
+root:	\
+	/bin/M \
+		/bin/U \
+	/bin/cd \
+		/bin/[ \
+		/bin/command \
+		/bin/echo \
+		/bin/expr \
+		/bin/false \
+		/bin/getopts \
+		/bin/read \
+		/bin/test \
+		/bin/true \
+		/bin/umask \
+		/bin/wait \
+
+clean:
+
+/usr/bin/DESCRIBE:	DESCRIBE.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/M:	M.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/U:	/usr/bin/M
+	install -m 755 -l $? $@
+
+/usr/bin/MAKEDEV:	MAKEDEV.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/bigmake:	bigmake.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/binpackage:	binpackage.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/binpackages:	binpackages.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/adduser:	adduser.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/cd:	cd.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/[ /usr/bin/command /usr/bin/echo /usr/bin/expr /usr/bin/false \
+/usr/bin/getopts /usr/bin/read /usr/bin/test /usr/bin/true /usr/bin/umask \
+/usr/bin/wait:	/usr/bin/cd
+	install -m 755 -l $? $@
+
+/usr/bin/easypack:	easypack.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/getpack:	getpack.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/checkhier:	checkhier.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/clear:	clear.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/clr:	/usr/bin/clear
+	install -m 755 -l $? $@
+
+/usr/bin/makewhatis:	makewhatis.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/mkdep:	mkdep.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/mkdist:	mkdist.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/floppysetup:	floppysetup.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/rotate:	rotate.sh
+	install -m 755 -c -o bin $? $@
+
+/bin/setup:	setup.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/binsizes:	binsizes.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/packit:	packit.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/packman:	packman.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/spell:	spell.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/srccrc:	srccrc.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/svclog:	svclog.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/version:	version.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/whatis:	whatis.sh
+	install -m 755 -c -o bin $? $@
+
+/usr/bin/apropos:	/usr/bin/whatis
+	install -m 755 -l $? $@
+
+/usr/bin/whereis:	whereis.sh
+	install -m 755 -c -o bin $? $@
+
+/bin/M:	/usr/bin/M
+	install -m 755 -c -o bin $? $@
+
+/bin/U:	/bin/M
+	install -m 755 -l $? $@
+
+/bin/cd:	/usr/bin/cd
+	install -m 755 -lc $? $@
+
+/bin/[ /bin/command /bin/echo /bin/expr /bin/false /bin/getopts \
+/bin/read /bin/test /bin/true /bin/umask /bin/wait:	/bin/cd
+	install -m 755 -l $? $@
Index: /trunk/minix/commands/scripts/adduser.sh
===================================================================
--- /trunk/minix/commands/scripts/adduser.sh	(revision 9)
+++ /trunk/minix/commands/scripts/adduser.sh	(revision 9)
@@ -0,0 +1,121 @@
+#!/bin/sh
+#
+#	adduser 1.0 - add a new user to the system	Author: Kees J. Bot
+#								16 Jan 1996
+
+# Check arguments.
+case "$#" in
+3)	user="$1"; group="$2"; home="$3"
+	;;
+*)	echo "Usage: adduser user group home-dir" >&2; exit 1
+esac
+
+# We need to be root.
+case "`id`" in
+'uid=0('*)
+	;;
+*)	echo "adduser: you must be root to add users" >&2; exit 1
+esac
+
+# User and group names must be alphanumeric and no longer than 8 characters.
+len=`expr "$user" : '[a-z][a-z0-9]*$'`
+if [ "$len" -eq 0 -o "$len" -gt 8 ]
+then
+	echo >&2 \
+"adduser: the user name must be alphanumeric and no longer than 8 characters"
+	exit 1
+fi
+
+len=`expr "$group" : '[a-z][a-z0-9]*$'`
+if [ "$len" -eq 0 -o "$len" -gt 8 ]
+then
+	echo >&2 \
+"adduser: the group name must be alphanumeric and no longer than 8 characters"
+	exit 1
+fi
+
+# The new user name must not exist, but the group must exist.
+if grep "^$user:" /etc/passwd >/dev/null
+then
+	echo "adduser: user $user already exists" >&2
+	exit 1
+fi
+
+gid=`sed -e "/^$group:/!d" -e 's/^[^:]*:[^:]*:\\([^:]*\\):.*/\\1/' /etc/group`
+if [ `expr "$gid" : '[0-9]*$'` -eq 0 ]
+then
+	echo "adduser: group $group does not exist" >&2
+	exit 1
+fi
+
+# Find the first free user-id of 10 or higher.
+uid=10
+while grep "^[^:]*:[^:]*:$uid:.*" /etc/passwd >/dev/null
+do
+	uid=`expr $uid + 1`
+done
+
+# No interruptions.
+trap '' 1 2 3 15
+
+# Lock the password file.
+ln /etc/passwd /etc/ptmp || {
+	echo "adduser: password file busy, try again later"
+	exit 1
+}
+
+# Make the new home directory, it should not exist already.
+mkdir "$home" || {
+	rm -rf /etc/ptmp
+	exit 1
+}
+
+# Make the new home directory by copying the honorary home directory of our
+# fearless leader.
+echo cpdir /usr/ast "$home"
+cpdir /usr/ast "$home" || {
+	rm -rf /etc/ptmp "$home"
+	exit 1
+}
+
+# Change the ownership to the new user.
+echo chown -R $uid:$gid "$home"
+chown -R $uid:$group "$home" || {
+	rm -rf /etc/ptmp "$home"
+	exit 1
+}
+
+# Is there a shadow password file?  If so add an entry.
+if [ -f /etc/shadow ]
+then
+	echo "echo $user::0:0::: >>/etc/shadow"
+	echo "$user::0:0:::" >>/etc/shadow || {
+		rm -rf /etc/ptmp "$home"
+		exit 1
+	}
+	pwd="##$user"
+else
+	pwd=
+fi
+
+# Finish up by adding a password file entry.
+echo "echo $user:$pwd:$uid:$gid:$user:$home: >>/etc/passwd"
+echo "$user:$pwd:$uid:$gid:$user:$home:" >>/etc/passwd || {
+	rm -rf /etc/ptmp "$home"
+	exit 1
+}
+
+# Remove the lock.
+rm /etc/ptmp || exit
+
+echo "
+The new user $user has been added to the system.  Note that the password,
+full name, and shell may be changed with the commands passwd(1), chfn(1),
+and chsh(1).  The password is now empty, so only console logins are possible."
+if [ $gid = 0 ]
+then
+	echo "\
+Also note that a new operator needs an executable search path (\$PATH) that
+does not contain the current directory (an empty field or "." in \$PATH)."
+fi
+exit 0
Index: /trunk/minix/commands/scripts/bigmake.sh
===================================================================
--- /trunk/minix/commands/scripts/bigmake.sh	(revision 9)
+++ /trunk/minix/commands/scripts/bigmake.sh	(revision 9)
@@ -0,0 +1,6 @@
+#!/bin/sh
+binsizes big
+make $*
+c=$?
+binsizes normal
+exit $c
Index: /trunk/minix/commands/scripts/binpackage.sh
===================================================================
--- /trunk/minix/commands/scripts/binpackage.sh	(revision 9)
+++ /trunk/minix/commands/scripts/binpackage.sh	(revision 9)
@@ -0,0 +1,66 @@
+#!/bin/sh 
+
+PI=.postinstall
+INFO=.minixpackage
+
+set -e
+
+# No trailing slashes in the directory, because we want to base the
+# package filename on it.
+dir=`echo "$1" | sed 's/\/*$//'`
+
+if [ $# -ne 2 ]
+then	echo "Usage: $0 sourcedir packagedir"
+	exit 1
+fi
+
+if [ ! -d "$dir" ]
+then	echo "Error: $dir isn't a directory."
+	exit 1
+fi
+
+here=`pwd`
+
+case "$dir" in
+/*) srcdir="$dir" ;;
+*) srcdir="$here/$dir" ;;
+esac
+
+case $2 in
+/*) pdir="$2" ;;
+*) pdir="$here/$2" ;;
+esac
+
+packagestart=$srcdir/now
+findlist=$srcdir/findlist
+tar=$srcdir/"`basename ${dir}`".tar
+tarbz=$tar.bz2
+
+mkdir $pdir 2>/dev/null || true
+binsizes=big
+rc=$dir/.binpackage
+if [ -f $rc ]
+then	 . $rc
+fi
+binsizes $binsizes
+touch $packagestart
+sleep 1
+cd $dir
+
+if [ ! -f build -a ! -f build.minix ]
+then	echo "Error: No build or build.minix script in $dir."
+	exit 1
+fi
+
+if [ -f build.minix ]
+then	sh -e build.minix
+else	sh -e build
+fi
+
+echo " * Building package"
+echo "Minix package $dir built `date`." >$INFO
+( echo $INFO ; if [ -f $PI ]; then echo $PI; fi; find / -cnewer $packagestart | egrep -v "^($srcdir|/(dev|tmp)|/usr/(tmp|log|adm|run)|/etc/utmp|/var/run)" ) | pax -w -d | bzip2 >$tarbz
+rm -f $packagestart $findlist $tarcmd
+binsizes normal
+mv $tarbz $pdir
+exit 0
Index: /trunk/minix/commands/scripts/binpackages.sh
===================================================================
--- /trunk/minix/commands/scripts/binpackages.sh	(revision 9)
+++ /trunk/minix/commands/scripts/binpackages.sh	(revision 9)
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+pdir=Packages
+
+for d in */build
+do
+	dir="`echo $d | sed 's/\/build$//'`"
+	if [ ! -f $pdir/$dir.tar.gz ]
+	then
+		echo " * $dir"
+		binpackage $dir $pdir
+	fi
+done
Index: /trunk/minix/commands/scripts/binsizes.sh
===================================================================
--- /trunk/minix/commands/scripts/binsizes.sh	(revision 9)
+++ /trunk/minix/commands/scripts/binsizes.sh	(revision 9)
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+t=/etc/binary_sizes
+
+if [ "$#" -ne 1 ]
+then	echo "Usage: $0 <big|normal>"
+	exit 1
+fi
+
+if [ "$1" != normal ]
+then	t=$t.$1
+fi
+
+chmem =250000 /usr/lib/* /usr/lib/i386/* >/dev/null 2>&1
+chmem =600000 /usr/lib/ego/*  >/dev/null 2>&1
+if [ -f $t ]
+then	cat "$t" | while read line
+	do	awk '{ print "chmem =" $2 " " $1 " 2>&1 | grep -v area.changed.from  || exit 1"}'
+	done | /bin/sh -e || exit 1
+else
+	echo "$0: $t does not exist" >&2
+	exit 1
+fi
+exit 0
Index: /trunk/minix/commands/scripts/build
===================================================================
--- /trunk/minix/commands/scripts/build	(revision 9)
+++ /trunk/minix/commands/scripts/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/scripts/cd.sh
===================================================================
--- /trunk/minix/commands/scripts/cd.sh	(revision 9)
+++ /trunk/minix/commands/scripts/cd.sh	(revision 9)
@@ -0,0 +1,11 @@
+#!/bin/sh
+#
+# cd 1.3 - equivalents for normally builtin commands.	Author: Kees J. Bot
+
+case $0 in
+*/*)	command="`expr "$0" : '.*/\(.*\)'`"
+	;;
+*)	command="$0"
+esac
+
+"$command" "$@"
Index: /trunk/minix/commands/scripts/checkhier.sh
===================================================================
--- /trunk/minix/commands/scripts/checkhier.sh	(revision 9)
+++ /trunk/minix/commands/scripts/checkhier.sh	(revision 9)
@@ -0,0 +1,181 @@
+#!/bin/sh
+#
+#	checkhier 2.7 - check the directory hierarchy	Author: Kees J. Bot
+#								7 May 1995
+
+case "`id`" in
+'uid=0('*)	;;
+*)	echo "$0: must be run by root" >&2
+	exit 1
+esac
+
+# List of all interesting top level files and directories, with mode,
+# owner and group.  Only the key files are listed, the rest is owned
+# by bin, has mode 755 or 644, and is not critical to the operation of
+# the system.
+{
+	cat <<'EOF'
+drwxr-xr-x	root	operator	/
+drwxr-xr-x	bin	operator	/bin
+drwxr-xr-x	root	operator	/dev
+drwxr-xr-x	root	operator	/etc
+-rw-r--r--	root	operator	/etc/fstab
+-rw-r--r--	root	operator	/etc/group
+-rw-r--r--	root	operator	/etc/hostname.file
+-rw-r--r--	root	operator	/etc/inet.conf
+-rw-r--r--	root	operator	/etc/motd
+-rw-r--r--	root	operator	/etc/mtab
+-rw-r--r--	root	operator	/etc/passwd
+-rw-r--r--	root	operator	/etc/profile
+-rw-r--r--	root	operator	/etc/protocols
+-rw-r--r--	root	operator	/etc/rc
+-rw-r--r--	root	operator	/etc/services
+-rw-------	root	operator	/etc/shadow
+-rw-r--r--	root	operator	/etc/termcap
+-rw-r--r--	root	operator	/etc/ttytab
+-rw-r--r--	root	operator	/etc/utmp
+dr-xr-xr-x	root	operator	/mnt
+dr-xr-xr-x	root	operator	/root
+drwxrwxrwx	root	operator	/tmp
+drwxr-xr-x	root	operator	/usr
+drwxr-xr-x	root	operator	/usr/adm
+-rw-r--r--	root	operator	/usr/adm/lastlog
+-rw-r--r--	root	operator	/usr/adm/wtmp
+drwxr-xr-x	ast	other		/usr/ast
+drwxr-xr-x	bin	operator	/usr/bin
+drwxr-xr-x	root	operator	/usr/etc
+drwxr-xr-x	bin	operator	/usr/include
+drwxr-xr-x	bin	operator	/usr/lib
+drwxrwxr-x	root	operator	/usr/local
+drwxrwxr-x	bin	operator	/usr/local/bin
+drwxrwxr-x	bin	operator	/usr/local/include
+drwxrwxr-x	bin	operator	/usr/local/lib
+drwxrwxr-x	bin	operator	/usr/local/man
+drwxrwxr-x	bin	operator	/usr/local/src
+drwxr-xr-x	bin	operator	/usr/man
+drwxr-xr-x	bin	operator	/usr/mdec
+drwx------	root	operator	/usr/preserve
+drwxr-xr-x	root	operator	/usr/run
+drwxr-xr-x	root	operator	/usr/spool
+drwx--x--x	root	operator	/usr/spool/at
+drwx--x--x	root	operator	/usr/spool/at/past
+drwx------	root	operator	/usr/spool/crontabs
+drwxrwxr-x	root	uucp		/usr/spool/locks
+drwx------	daemon	daemon		/usr/spool/lpd
+drwxr-xr-x	bin	operator	/usr/src
+drwxrwxrwx	root	operator	/usr/tmp
+-rwsr-xr-x	root	?		/usr/bin/at
+-rwsr-xr-x	root	?		/usr/bin/chfn
+-rwsr-xr-x	root	?		/usr/bin/chsh
+-rwsr-xr-x	root	?		/usr/bin/df
+-rwsr-xr-x	root	?		/usr/bin/elvprsv
+-rwsr-xr-x	root	?		/usr/bin/elvrec
+-rwsr-xr-x	root	?		/usr/bin/format
+-rwsr-xr-x	root	?		/usr/bin/hostaddr
+-rwsr-xr-x	root	?		/usr/bin/install
+-rwsr-xr-x	daemon	?		/usr/bin/lpd
+-rwsr-xr-x	root	?		/usr/bin/mail
+-rwsr-xr-x	root	?		/usr/bin/mount
+-rwsr-xr-x	root	?		/usr/bin/passwd
+-rwsr-xr-x	root	?		/usr/bin/ping
+-rwxr-sr-x	?	kmem		/usr/bin/ps
+-rwsr-xr--	root	?		/usr/bin/shutdown
+-rwsr-xr-x	root	?		/usr/bin/su
+-rwxr-sr-x	?	uucp		/usr/bin/term
+-rwsr-xr-x	root	?		/usr/bin/umount
+-rwxr-sr-x	?	tty		/usr/bin/write
+EOF
+
+} | {
+	# Check if each file has the proper attributes.  Offer a correction
+	# if not.
+	banner="\
+# List of commands to fix the top level hierarchy.  Do not apply these
+# commands blindly, but check and repair by hand.
+"
+
+	while read mode owner group file
+	do
+	    ( # "fix" a memory leak in set...
+
+		set -$- `ls -ld $file 2>/dev/null` '' '' '' ''
+		curmode=$1 curowner=$3 curgroup=$4
+		test $owner = '?' && curowner=$owner
+		test $group = '?' && curgroup=$group
+
+		# File types?
+		if [ x`expr "$mode" : '\\(.\\)'` != \
+					x`expr "$curmode" : '\\(.\\)'` ]
+		then
+			case $curmode in
+			?*)	echo "${banner}rm -r $file"
+				banner=
+			esac
+			curmode= curowner= curgroup=
+			case $mode in
+			d*)	echo "${banner}mkdir $file"
+				;;
+			-*)	echo "${banner}> $file"
+				;;
+			*)	echo "$0: $mode $file: unknown filetype" >&2
+				exit 1
+			esac
+			banner=
+		fi
+
+		# Mode?
+		if [ x$mode != x$curmode ]
+		then
+			octmode=
+			m=$mode
+			for i in u g o
+			do
+				r=0 w=0 x=0
+				case $m in
+				?r??*)		r=4
+				esac
+				case $m in
+				??w?*)		w=2
+				esac
+				case $m in
+				???[xst]*)	x=1
+				esac
+				octmode=$octmode`expr $r + $w + $x`
+				m=`expr $m : '...\\(.*\\)'`
+			done
+			r=0 w=0 x=0
+			case $mode in
+			???[sS=]??????)	r=4
+			esac
+			case $mode in
+			??????[sS=]???)	w=2
+			esac
+			case $mode in
+			?????????[tT=])	x=1
+			esac
+			case $r$w$x in
+			000)	;;
+			*)	octmode=`expr $r + $w + $x`$octmode
+			esac
+
+			echo "${banner}chmod $octmode $file"
+			banner=
+		fi
+
+		# Ownership?
+		if [ x$owner != x$curowner -o x$group != x$curgroup ]
+		then
+			echo "${banner}chown $owner:$group $file"
+			banner=
+		fi
+
+		# The Minix shell forgets processes, so wait explicitly.
+		wait
+
+	    case "$banner" in '') exit 1;; *) exit 0;; esac) || banner=
+	done
+	case "$banner" in
+	'')	exit 1
+	esac
+	exit 0
+}
Index: /trunk/minix/commands/scripts/clear.sh
===================================================================
--- /trunk/minix/commands/scripts/clear.sh	(revision 9)
+++ /trunk/minix/commands/scripts/clear.sh	(revision 9)
@@ -0,0 +1,6 @@
+#!/bin/sh
+#
+#	clear 1.0 - clear the screen			Author: Kees J. Bot
+#								30 Mar 1996
+export PATH=/bin:/usr/bin
+exec tget -str cl
Index: /trunk/minix/commands/scripts/easypack.sh
===================================================================
--- /trunk/minix/commands/scripts/easypack.sh	(revision 9)
+++ /trunk/minix/commands/scripts/easypack.sh	(revision 9)
@@ -0,0 +1,118 @@
+#!/bin/sh
+
+# This script gets and installs a package from the Website.
+# It is called by getpack package1 ...
+# A package must be in the form of pack.tar.bz2 and must
+# include a build script that makes and installs it.
+# The build script should succeed if installation works, else fail
+
+# Examples:
+#	easypack awk elle telnet	# fetch and install 3 packages
+#	easypack -o awk elle telnet	# fetch and replace existing packs
+
+SOURCE_DIR=/usr/src/commands		# where the source is deposited
+OVERWRITE=0				# can an installed package be overwritten?
+SOFTWARE_DIR="http://www.minix3.org/software"	# Tested and approved S/W
+BETA_DIR="http://www.minix3.org/beta_software"	# Untested software
+
+
+# Check for at least one parameter
+case $# in
+0)	echo Usage: $0 package ...
+	exit ;;
+esac
+
+# Change to source directory
+ORIG_DIR=`pwd`
+rm -f Log			# remove old debugging log
+cd $SOURCE_DIR || exit
+
+if [ "`id -u`" -ne 0 ]
+then
+	# Check for write permission here
+	if test ! -w . 
+	   then echo You do not have write permission for $SOURCE_DIR
+	   exit 1
+	fi
+fi
+
+# Check for -o flag; if found, set OVERWRITE
+if test $1 = "-o"
+   then OVERWRITE=1
+        shift
+fi
+
+# Loop on the packages
+for i
+do # Check to see if it exists. Don't overwrite unless -o given
+   echo " " ; echo Start fetching package $i 
+   echo " " >>$ORIG_DIR/Log
+   echo ------------- Start fetching $i ------------------ >>$ORIG_DIR/Log
+   if test -r $i
+      then # Directory already exists. May it be overwritten?
+	   if test $OVERWRITE = 0
+              then echo $i already exists. Skipping this package
+                   continue
+	      else # Remove the directory
+		   rm -rf $i
+		   echo Existing directory $i removed
+	   fi
+    fi
+
+   # Remove any junk from previous attempts
+   rm -f $i.tar.bz2 $i.tar
+
+   # Get the package
+   URL=$SOFTWARE_DIR/$i.tar.bz2
+   URL1=$URL
+   TARBZ=$i.tar.bz2
+   if urlget $URL >$TARBZ 2>/dev/null
+   then :
+   else # It is not in the directory of tested software. Try beta dir.
+	   URL=$BETA_DIR/$TARBZ
+	   if urlget $URL >$TARBZ 2>/dev/null
+	   then :
+	   else
+	   	   echo Cannot get $i.
+		   echo "   " Tried $URL1
+		   echo "   " Tried $URL
+		   echo "   " Skipping this package
+		   rm -f $TARBZ
+		   continue
+	   fi
+   fi
+
+   # We got it. Unpack it.
+   echo Package $i fetched
+   bunzip2 $TARBZ || smallbunzip2 $TARBZ
+   tar xf $i.tar
+   if test ! -d $i
+      then echo Unable to unpack $i
+	   continue
+      else echo Package $i unpacked
+   fi
+
+   # It is now unpacked. Build it
+   cd $i
+   binsizes big
+   if [ -f build.minix ]
+   then	sh build.minix >>$ORIG_DIR/Log 2>&1
+	r=$?
+   else	sh build >>$ORIG_DIR/Log 2>&1
+	r=$?
+   fi
+   if [ $r -eq 0 ] 
+      then echo Package $i installed
+      else echo Package $i failed to install, see Log
+   fi
+   if [ -f .postinstall ]
+   then	echo Running postinstall script.
+	sh -e .postinstall
+   fi
+   binsizes normal
+
+   # Clean up
+   cd ..
+   rm -f $i.tar $TARBZ # Remove whatever is still lying around
+done
+
Index: /trunk/minix/commands/scripts/floppysetup.sh
===================================================================
--- /trunk/minix/commands/scripts/floppysetup.sh	(revision 9)
+++ /trunk/minix/commands/scripts/floppysetup.sh	(revision 9)
@@ -0,0 +1,408 @@
+#!/bin/sh
+#
+#	setup 4.1 - install a Minix distribution	Author: Kees J. Bot
+#								20 Dec 1994
+
+PATH=/bin:/usr/bin
+export PATH
+
+usage()
+{
+    cat >&2 <<'EOF'
+Usage:	setup		# Install a skeleton system on the hard disk.
+	setup /usr	# Install the rest of the system (binaries or sources).
+
+	# To install from other things then floppies:
+
+	urlget http://... | setup /usr		# Read from a web site.
+	urlget ftp://... | setup /usr		# Read from an FTP site.
+	mtools copy c0d0p0:... - | setup /usr	# Read from the C: drive.
+	dosread c0d0p0 ... | setup /usr		# Likewise if no mtools.
+EOF
+    exit 1
+}
+
+# No options.
+while getopts '' opt; do usage; done
+shift `expr $OPTIND - 1`
+
+# Installing a floppy set?
+case $# in
+0)  # No, we're installing a skeleton system on the hard disk.
+    ;;
+1)
+    cd "$1" || exit
+
+    # Annoying message still there?
+    grep "'setup /usr'" /etc/issue >/dev/null 2>&1 && rm -f /etc/issue
+
+    if [ -t 0 ]
+    then
+	size=bad
+	while [ "$size" = bad ]
+	do
+	    echo -n "\
+What is the size of the images on the diskettes? [all] "; read size
+
+	    case $size in
+	    ''|360|720|1200|1440)
+		;;
+	    *)	echo "Sorry, I don't believe \"$size\", try again." >&2
+		size=bad
+	    esac
+	done
+
+	drive=
+	while [ -z "$drive" ]
+	do
+	    echo -n "What floppy drive to use? [0] "; read drive
+
+	    case $drive in
+	    '')	drive=0
+		;;
+	    [01])
+		;;
+	    *)	echo "It must be 0 or 1, not \"$drive\"."
+		drive=
+	    esac
+	done
+
+	vol -r $size /dev/fd$drive | uncompress | tar xvfp -
+    else
+	# Standard input is where we can get our files from.
+	uncompress | tar xvfp -
+    fi
+
+    echo Done.
+    exit
+    ;;
+*)
+    usage
+esac
+
+# Installing Minix on the hard disk.
+# Must be in / or we can't mount or umount.
+if [ ! -f /CD ]
+then
+	case "`pwd`" in
+	/?*)
+	    echo "Please type 'cd /' first, you are locking up `pwd`" >&2	
+	    exit 1
+	esac
+fi
+
+case "$0" in
+/tmp/*)
+    rm -f "$0"
+    ;;
+*)  cp -p "$0" /tmp/setup
+    exec /tmp/setup
+esac
+
+# Find out what we are running from.
+exec 9<&0 </etc/mtab			# Mounted file table.
+read thisroot rest			# Current root (/dev/ram or /dev/fd?)
+read fdusr rest				# USR (/dev/fd? or /dev/fd?p2)
+exec 0<&9 9<&-
+
+# What do we know about ROOT?
+case $thisroot:$fdusr in
+/dev/ram:/dev/fd0p2)	fdroot=/dev/fd0		# Combined ROOT+USR in drive 0
+			;;
+/dev/ram:/dev/fd1p2)	fdroot=/dev/fd1		# Combined ROOT+USR in drive 1
+			;;
+/dev/ram:/dev/fd*)	fdroot=unknown		# ROOT is some other floppy
+			;;
+/dev/fd*:/dev/fd*)	fdroot=$thisroot	# ROOT is mounted directly
+			;;
+*)			fdroot=$thisroot	# ?
+    if [ -f /CD ]
+    then
+    	:
+    else
+	    echo -n "\
+It looks like Minix has been installed on disk already.  Are you sure you
+know what you are doing? [n] "
+	    read yn
+	    case "$yn" in
+	    [yY]*|sure)	;;
+	    *)	exit
+	    esac
+     fi
+esac
+
+echo -n "\
+This is the Minix installation script.
+
+Note 1: If the screen blanks suddenly then hit CTRL+F3 to select \"software
+	scrolling\".
+
+Note 2: If things go wrong then hit DEL and start over.
+
+Note 3: The installation procedure is described in the manual page
+	usage(8).  It will be hard without it.
+
+Note 4: Some questions have default answers, like this: [y]
+	Simply hit RETURN (or ENTER) if you want to choose that answer.
+
+Note 5: If you see a colon (:) then you should hit RETURN to continue.
+:"
+read ret
+
+echo "
+What type of keyboard do you have?  You can choose one of:
+"
+ls -C /usr/lib/keymaps | sed -e 's/\.map//g' -e 's/^/    /'
+echo -n "
+Keyboard type? [us-std] "; read keymap
+test -n "$keymap" && loadkeys "/usr/lib/keymaps/$keymap.map"
+
+echo -n "
+Minix needs one primary partition of at about 210 MB for a full install
+with sources.  (The full install also fits in about 180 MB, but it
+needs more if fully recompiled.  Add more space to taste.)
+
+  * Minix currently only understands filesystems up to 4GB, so don't make
+    it bigger.
+
+If there is no free space on your disk then you have to back up one of the
+other partitions, shrink, and reinstall.  See the appropriate manuals of the
+the operating systems currently installed.  Restart your Minix installation
+after you have made space.
+
+To make this partition you will be put in the editor \"part\".  Follow the
+advice under the '!' key to make a new partition of type MINIX.  Do not
+touch an existing partition unless you know precisely what you are doing!
+Please note the name of the partition (e.g. c0d0p1, c0d1p3, c1d1p0) you
+make.  (See the devices section in usage(8) on Minix device names.)
+:"
+read ret
+
+primary=
+while [ -z "$primary" ]
+do
+    part || exit
+
+    echo -n "
+Please finish the name of the primary partition you have created:
+(Just type RETURN if you want to rerun \"part\")                   /dev/"
+    read primary
+done
+
+root=${primary}s0
+swap=${primary}s1
+usr=${primary}s2
+
+hex2int()
+{
+    # Translate hexadecimal to integer.
+    local h d i
+
+    h=$1
+    i=0
+    while [ -n "$h" ]
+    do
+	d=$(expr $h : '\(.\)')
+	h=$(expr $h : '.\(.*\)')
+	d=$(expr \( 0123456789ABCDEF : ".*$d" \) - 1)
+	i=$(expr $i \* 16 + $d)
+    done
+    echo $i
+}
+
+# Ask user about networking
+echo ""
+echo "Minix currently supports the Intel Pro/100 and RealTek 8139 "
+echo "Ethernet cards. Please choose: "
+echo ""
+echo "0. No Ethernet card (no networking)"
+echo "1. An Intel Pro/100 Ethernet card is installed"
+echo "2. A Realtek 8139 Ethernet card is installed"
+echo "3. A different Ethernet card is installed (no networking)"
+echo ""
+echo "You can always change your mind after the install."
+echo ""
+echo "Choice? "
+read eth
+driver=""
+inetparams=""
+case "$eth" in
+	1)	driver=FXP;	inetparams="servers=inet;" ;;
+	2)	driver=RTL8139;	inetparams="servers=inet;" ;;
+esac
+
+# Compute the amount of memory available to Minix.
+memsize=0
+ifs="$IFS"
+IFS=','
+set -- $(sysenv memory)
+IFS="$ifs"
+
+for mem
+do
+    mem=$(expr $mem : '.*:\(.*\)')
+    memsize=$(expr $memsize + $(hex2int $mem) / 1024)
+done
+
+# Compute an advised swap size.
+swapadv=0
+case `arch` in
+i86)
+    test $memsize -lt 4096 && swapadv=$(expr 4096 - $memsize)
+    ;;
+*)  test $memsize -lt 6144 && swapadv=$(expr 6144 - $memsize)
+esac
+
+echo -n "
+How much swap space would you like?  Swapspace is only needed if this
+system is memory starved, like a 16-bit system with less then 2M, or a
+32-bit system with less then 4M.  Minix swapping isn't very good yet, so
+there is no need for it otherwise.
+		    Size in kilobytes? [$swapadv] "
+swapsize=
+read swapsize
+test -z "$swapsize" && swapsize=$swapadv
+
+echo -n "
+You have created a partition named:	/dev/$primary
+The following subpartitions are about to be created on /dev/$primary:
+
+    Root subpartition:	/dev/$root	16 MB
+    Swap subpartition:	/dev/$swap	$swapsize kb
+    /usr subpartition:	/dev/$usr	rest of $primary
+
+Hit return if everything looks fine, or hit DEL to bail out if you want to
+think it over.  The next step will destroy /dev/$primary.
+:"
+read ret
+					# Secondary master bootstrap.
+installboot -m /dev/$primary /usr/mdec/masterboot >/dev/null || exit
+
+					# Partition the primary.
+p3=0:0
+test "$swapsize" -gt 0 && p3=81:`expr $swapsize \* 2`
+partition /dev/$primary 1 81:32768* $p3 81:0+ || exit
+
+if [ "$swapsize" -gt 0 ]
+then
+    # We must have that swap, now!
+    mkswap -f /dev/$swap || exit
+    mount -s /dev/$swap || exit
+else
+    # Forget about swap.
+    swap=
+fi
+
+echo "
+Migrating to disk...
+"
+
+mkfs /dev/$usr
+echo "\
+Scanning /dev/$usr for bad blocks.  (Hit DEL to stop the scan if you are
+absolutely sure that there can not be any bad blocks.  Otherwise just wait.)"
+trap ': nothing' 2
+readall -b /dev/$usr | sh
+sleep 2
+trap 2
+
+mount /dev/$usr /mnt || exit		# Mount the intended /usr.
+
+cpdir -v /usr /mnt || exit		# Copy the usr floppy.
+
+umount /dev/$usr || exit		# Unmount the intended /usr.
+
+umount $fdusr				# Unmount the /usr floppy.
+
+mount /dev/$usr /usr || exit		# A new /usr
+
+if [ $fdroot = unknown ]
+then
+    echo "
+By now the floppy USR has been copied to /dev/$usr, and it is now in use as
+/usr.  Please insert the installation ROOT floppy in a floppy drive."
+
+    drive=
+    while [ -z "$drive" ]
+    do
+	echo -n "What floppy drive is it in? [0] "; read drive
+
+	case $drive in
+	'')	drive=0
+	    ;;
+	[01])
+	    ;;
+	*)	echo "It must be 0 or 1, not \"$drive\"."
+	    drive=
+	esac
+    done
+    fdroot=/dev/fd$drive
+fi
+
+echo "
+Copying $fdroot to /dev/$root
+"
+
+mkfs /dev/$root || exit
+mount /dev/$root /mnt || exit
+if [ -d /boot ]
+then
+    # Running from the floppy itself (or installation CD).
+    cpdir -vx / /mnt || exit
+    chmod 555 /mnt/usr
+else
+    # Running from the RAM disk, root image is on a floppy.
+    mount $fdroot /root || exit
+    cpdir -v /root /mnt || exit
+    umount $fdroot || exit
+    cpdir -f /dev /mnt/dev		# Copy any extra MAKEDEV'd devices
+fi
+
+# CD remnants that aren't for the installed system
+rm /mnt/etc/issue /mnt/CD 2>/dev/null
+					# Change /etc/fstab.
+echo >/mnt/etc/fstab "\
+# Poor man's File System Table.
+
+root=/dev/$root
+${swap:+swap=/dev/$swap}
+usr=/dev/$usr"
+
+					# National keyboard map.
+test -n "$keymap" && cp -p "/usr/lib/keymaps/$keymap.map" /mnt/etc/keymap
+
+# Set inet.conf to correct driver
+if [ -n "$driver" ]
+then	echo "eth0 $driver 0 { default; };" >/mnt/etc/inet.conf
+fi
+
+umount /dev/$root || exit		# Unmount the new root.
+
+# Compute size of the second level file block cache.
+case `arch` in
+i86)
+    cache=`expr "0$memsize" - 1024`
+    test $cache -lt 32 && cache=0
+    test $cache -gt 512 && cache=512
+    ;;
+*)
+    cache=`expr "0$memsize" - 2560`
+    test $cache -lt 64 && cache=0
+    test $cache -gt 1024 && cache=1024
+esac
+echo "Second level file system block cache set to $cache kb."
+if [ $cache -eq 0 ]; then cache=; else cache="ramsize=$cache"; fi
+
+					# Make bootable.
+installboot -d /dev/$root /usr/mdec/bootblock /boot/boot >/dev/null || exit
+edparams /dev/$root "rootdev=$root; ramimagedev=$root; $cache; $inetparams; save" || exit
+pfile="/usr/src/tools/fdbootparams"
+echo "Remembering boot parameters in ${pfile}."
+echo "rootdev=$root; ramimagedev=$root; $cache; save" >$pfile || exit
+sync
+
+echo "
+Please type 'halt' to exit Minix.
+You can type 'boot $primary' to try the newly installed Minix system.  See
+\"TESTING\" in the usage manual."
+
Index: /trunk/minix/commands/scripts/getpack.sh
===================================================================
--- /trunk/minix/commands/scripts/getpack.sh	(revision 9)
+++ /trunk/minix/commands/scripts/getpack.sh	(revision 9)
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+if [ $# -ne 1 ]
+then	echo "Usage: $0 <url>"
+	exit 1
+fi
+
+if [ -z "$HOME" ]
+then	echo "Where is your \$HOME? "
+	exit 1
+fi
+
+if [ ! -d "$HOME" ]
+then	echo "Where is your \$HOME ($HOME) ? "
+	exit 1
+fi
+
+tmpdir=$HOME/getpack$$
+tmpfile=package
+tmpfiletar=$tmpfile.tar
+tmpfiletargz=$tmpfile.tar.gz
+
+mkdir -m 700 $tmpdir || exit 1
+cd $tmpdir || exit 1
+
+urlget "$1" >$tmpfiletargz
+
+gzip -d $tmpfiletargz || exit 1
+tar xf $tmpfiletar || exit 1
+make && make install && echo "Ok."
Index: /trunk/minix/commands/scripts/makewhatis.sh
===================================================================
--- /trunk/minix/commands/scripts/makewhatis.sh	(revision 9)
+++ /trunk/minix/commands/scripts/makewhatis.sh	(revision 9)
@@ -0,0 +1,85 @@
+#!/bin/sh
+#
+# makewhatis 2.0 - make whatis(5) database.	Author: Kees J. Bot.
+#
+# Make the whatis database of a man directory from the manual pages.
+
+case $1 in
+-*)	set -$- x x
+esac
+
+case $# in
+1)	;;
+*)	echo "Usage: $0 <mandir>" >&2
+	exit 1
+esac
+
+cd $1 || exit
+
+{
+	# First pass, gathering the .SH NAME lines in various forms.
+
+	# First the man[1-8] directories, the titles are under the .SH NAME
+	# section header.
+	for chap in 1 2 3 4 5 6 7 8
+	do
+		for page in man$chap/*.$chap
+		do
+		   if	test -f "$page"; then	# (Old sh barfs on 'continue')
+
+			sed -e 's/	/ /g
+				s/"NAME"/NAME/g
+				/^\.SH NAME/,/^\.SH /!d
+				/^\.SH /d
+				s/\\f.//g	# should not be needed
+				s/\\s[+-].//g
+				s/\\s.//g
+				s/\\//
+				'"s/ - / ($chap) - /" < "$page"
+		   fi
+		done
+	done
+
+	# The Minix "Book style" documents, look for .CD
+	for page in man9/*.9
+	do
+	   if	test -f "$page"; then
+
+		sed -e 's/	/ /g
+			/^\.CD /!d
+			s/^[^"]*"//
+			s/"[^"]*$//
+			s/\\(en/-/g
+			s/\\f.//g
+			s/\\s[+-].//g
+			s/\\s.//g
+			s/\\\*(M2/MINIX/g
+			s/\\//
+			'"s/ - / (9) - /" < "$page"
+	   fi
+	done
+
+	# Some people throw extra flat text files into the cat[1-9]
+	# directories.  It would be nice if man(1) can find them.
+	trap 'rm -f /tmp/mkw[cmn]$$; exit 1' 1 2 15
+	for chap in 1 2 3 4 5 6 7 8 9
+	do
+		ls cat$chap 2>/dev/null >/tmp/mkwc$$
+		ls man$chap 2>/dev/null >/tmp/mkwm$$
+		comm -23 /tmp/mkwc$$ /tmp/mkwm$$ >/tmp/mkwn$$
+		sed -e "/.*\\.$chap\$/!d
+			s/\\.$chap\$/ ($chap) - ???/" < /tmp/mkwn$$
+	done
+	rm -f /tmp/mkw[cmn]$$
+} | {
+	# Second pass, remove empty lines, leading and trailing spaces,
+	# multiple spaces to one space, remove lines without a dash.
+	sed -e 's/  */ /g
+		s/^ //
+		s/ $//
+		/^$/d
+		/-/!d'
+} | {
+	# Third pass, sort by section.
+	sort -t'(' +1 -o whatis
+}
Index: /trunk/minix/commands/scripts/mkdep.sh
===================================================================
--- /trunk/minix/commands/scripts/mkdep.sh	(revision 9)
+++ /trunk/minix/commands/scripts/mkdep.sh	(revision 9)
@@ -0,0 +1,55 @@
+#!/bin/sh
+#
+#	mkdep 1.1 - Generate Makefile dependencies.	Author: Kees J. Bot
+#
+# Does what 'cc -M' should do, but no compiler gets it right, they all
+# strip the leading path of the '.o' file.)
+#
+# Added option to generate .depend files in subdirectories of given dir.
+# 							Jorrit N. Herder
+
+case $# in
+
+# Display help ...
+0)	
+	echo "Usage: mkdep 'cpp command' file ..." >&2
+	echo "       mkdep directory" >&2
+;;
+
+# Create .depend files ...
+1)
+	echo "Creating .depend files in $1"
+	for dir in `find $1 -type d ! -name CVS`
+	do
+		touch $dir/.depend
+	done
+
+;;
+
+
+# Get dependencies ... 
+*)
+	cpp="$1"; shift
+
+	for f
+	do
+		: < "$f" || exit
+
+		o=`expr "$f" : '\(.*\)\..*'`.o
+
+		echo
+
+		$cpp "$f" | \
+			sed -e '/^#/!d
+				s/.*"\(.*\)".*/\1/
+				s:^\./::' \
+			    -e "s:^:$o\:	:" | \
+			sort -u
+	done
+esac
+
+exit 0
+
+#
+# $PchId: mkdep.sh,v 1.3 1998/07/23 21:24:38 philip Exp $
+#
Index: /trunk/minix/commands/scripts/mkdist.sh
===================================================================
--- /trunk/minix/commands/scripts/mkdist.sh	(revision 9)
+++ /trunk/minix/commands/scripts/mkdist.sh	(revision 9)
@@ -0,0 +1,301 @@
+#!/bin/sh
+#
+#	mkdist 3.6 - Make a Minix distribution		Author: Kees J. Bot
+#								20 Dec 1994
+
+system=`uname`
+
+usage()
+{
+    case $system in
+    Minix)	echo "Usage: $0" >&2
+	;;
+    Minix-vmd)	echo "Usage: $0 base-path root-device usr-device" >&2
+    esac
+    exit 1
+}
+
+# No options.
+while getopts '' opt; do usage; done
+shift `expr $OPTIND - 1`
+
+case $system:$# in
+Minix:0)
+    # Interactive.
+    case "$0" in
+    /tmp/*)
+	rm -f "$0"
+	;;
+    *)  # Move out of /usr.
+	cp -p "$0" /tmp/mkdist
+	exec /tmp/mkdist
+    esac
+    std=t
+    base=/
+    export PATH=/bin:/usr/bin
+    ;;
+Minix-vmd:3)
+    # Called by an external script from Minix-vmd to help make a distribution.
+    std=
+    base="$1" rootdev="$2" usrdev="$3"
+esac
+
+usrlist="
+bin
+bin/MAKEDEV
+bin/arch
+bin/badblocks
+bin/chmod
+bin/clone
+bin/compress
+bin/cp
+bin/cpdir
+bin/df
+`test -f $base/usr/bin/mtools || echo bin/dosdir bin/dosread bin/doswrite`
+`test -f $base/usr/bin/mtools && echo bin/mtools`
+bin/edparams
+bin/getty
+bin/grep
+bin/installboot
+bin/isodir
+bin/isoinfo
+bin/isoread
+bin/kill
+bin/ln
+bin/login
+bin/ls
+bin/mined
+bin/mkdir
+bin/mkfs
+bin/mknod
+bin/mkswap
+bin/mv
+bin/od
+bin/part
+bin/partition
+bin/readall
+bin/repartition
+bin/rm
+bin/rmdir
+bin/sed
+bin/setup
+bin/shutdown
+bin/sleep
+bin/sort
+bin/stty
+bin/sysenv
+bin/tar
+bin/uname
+bin/uncompress
+bin/update
+bin/vol
+bin/zcat
+etc
+etc/rc
+lib
+lib/keymaps
+`cd $base/usr && echo lib/keymaps/*`
+lib/pwdauth
+mdec
+mdec/boot
+mdec/bootblock
+mdec/jumpboot
+mdec/masterboot
+tmp
+"
+
+if [ "$std" ]
+then
+    # Find the root device, and the real root device.
+    . /etc/fstab
+    realroot=`printroot -r`
+    if [ $realroot = $root ]
+    then
+	rootdir=/
+    else
+	umount $root >/dev/null 2>&1
+	mount $root /root || exit
+	rootdir=/root
+    fi
+
+    echo -n "
+The installation root and /usr can be put on either one diskette of at least
+1.2 Mb, or on two diskettes of at least 720 kb.
+
+Do you want to use a single diskette of at least 1.2 Mb? [y] "; read single
+
+    case $single in
+    ''|[yY]*|sure)
+	single=t
+	;;
+    *)  single=
+    esac
+
+    echo -n "Which drive to use? [0] "; read drive
+
+    case $drive in
+    '') drive=0
+	;;
+    [01])	;;
+    *)  echo "Please type '0' or '1'" >&2; exit 1
+    esac
+
+    if [ "$single" ]
+    then
+	echo -n "Insert the root+usr diskette in drive $drive and hit RETURN"
+    else
+	echo -n "Insert the root diskette in drive $drive and hit RETURN"
+    fi
+    read ret
+
+    rootdev=/dev/fd$drive
+    v1=-1
+else
+    rootdir=$base
+    v1='-t 1'
+fi
+
+umount $rootdev 2>/dev/null
+if [ "$std" ]
+then
+    umount ${rootdev}p1 2>/dev/null
+    umount ${rootdev}p2 2>/dev/null
+else
+    umount $rootdir/minix 2>/dev/null
+    umount $rootdir/etc 2>/dev/null
+fi
+mkfs $v1 -i 272 $rootdev 480 || exit
+mount $rootdev /mnt || exit
+if [ "$std" ]
+then
+    partition -mf $rootdev 0 81:960 81:240 81:240 >/dev/null || exit
+    repartition $rootdev >/dev/null || exit
+    mkfs $v1 ${rootdev}p1 || exit
+    mkfs $v1 ${rootdev}p2 || exit
+    mount ${rootdev}p1 $rootdir/minix || exit	# Hide /minix and /etc
+    mount ${rootdev}p2 $rootdir/etc 2>/dev/null # (complains about /etc/mtab)
+else
+    install -d /tmp/.minix || exit
+    install -d /tmp/.etc || exit		# Hide /minix and /etc
+    mount -t lo /tmp/.minix $rootdir/minix || exit
+    mount -t lo /tmp/.etc $rootdir/etc || exit
+fi
+cpdir -vx $rootdir /mnt || exit
+install -d -o 0 -g 0 -m 755 /mnt || exit
+install -d -o 0 -g 0 -m 555 /mnt/root || exit
+install -d -o 0 -g 0 -m 555 /mnt/mnt || exit
+install -d -o 0 -g 0 -m 555 /mnt/usr || exit
+if [ "$std" ]
+then
+    umount ${rootdev}p2 2>/dev/null	# Unhide /etc
+    umount ${rootdev}p1 || exit		# Unhide /minix
+else
+    umount $rootdir/etc || exit		# Unhide /etc
+    umount $rootdir/minix || exit	# Unhide /minix
+fi
+install -d -o 2 -g 0 -m 755 /mnt/minix || exit
+install -d -o 2 -g 0 -m 755 /mnt/etc || exit
+set `ls -t $rootdir/minix`	# Install the latest kernel
+install -c $rootdir/minix/$1 /mnt/minix/`echo $1 | sed 's/r[0-9]*$//` || exit
+cpdir -v $base/usr/src/etc /mnt/etc || exit	# Install a fresh /etc
+chown -R 0:0 /mnt/etc				# Patch up owner and mode
+chmod 600 /mnt/etc/shadow
+
+# Change /etc/fstab.
+echo >/mnt/etc/fstab "\
+# Poor man's File System Table.
+
+root=unknown
+usr=unknown"
+
+# How to install?
+echo >/mnt/etc/issue "\
+
+Login as root and run 'setup' to install Minix."
+
+umount $rootdev || exit
+test "$std" && umount $root 2>/dev/null
+installboot -d $rootdev $base/usr/mdec/bootblock boot >/dev/null
+
+# Partition the root floppy whether necessary or not.  (Two images can be
+# concatenated, or a combined image can be split later.)
+partition -mf $rootdev 0 81:960 0:0 81:1440 81:480 >/dev/null || exit
+
+if [ "$std" ]
+then
+    if [ "$single" ]
+    then
+	repartition $rootdev >/dev/null
+	usrdev=${rootdev}p2
+    else
+	echo -n "Insert the usr diskette in drive $drive and hit RETURN"
+	read ret
+	usrdev=$rootdev
+    fi
+fi
+
+mkfs $v1 -i 96 $usrdev 720 || exit
+mount $usrdev /mnt || exit
+install -d -o 0 -g 0 -m 755 /mnt || exit
+(cd $base/usr && exec tar cfD - $usrlist) | (cd /mnt && exec tar xvfp -) || exit
+umount $usrdev || exit
+
+# Put a "boot the other drive" bootblock on the /usr floppy.
+installboot -m $usrdev /usr/mdec/masterboot >/dev/null
+
+# We're done for Minix-vmd here, it has its own ideas on how to package /usr.
+test "$std" || exit 0
+
+# Guess the size of /usr in compressed form.  Assume compression down to 60%
+# of the original size.  Use "disk megabytes" of 1000*1024 for a safe guess.
+set -$- `df | grep "^$usr"`
+size=`expr \\( $4 \\* 6 / 10 + 999 \\) / 1000`
+
+echo -n "
+You now need enough diskettes to hold /usr in compressed form, close to
+$size Mb total.  "
+
+size=
+while [ -z "$size" ]
+do
+    if [ "$single" ]; then defsize=1440; else defsize=720; fi
+
+    echo -n "What is the size of the diskettes? [$defsize] "; read size
+
+    case $size in
+    '')	size=$defsize
+	;;
+    360|720|1200|1440)
+	;;
+    *)	echo "Sorry, I don't believe \"$size\", try again." >&2
+	size=
+    esac
+done
+
+drive=
+while [ -z "$drive" ]
+do
+    echo -n "What floppy drive to use? [0] "; read drive
+
+    case $drive in
+    '')	drive=0
+	;;
+    [01])
+	;;
+    *)	echo "It must be 0 or 1, not \"$drive\"."
+	drive=
+    esac
+done
+
+echo "
+Enter the floppies in drive $drive when asked to.  Mark them with the volume
+numbers!
+"
+sleep 2
+
+if [ `arch` = i86 ]; then bits=13; else bits=16; fi
+
+>/tmp/DONE
+cd /usr && tar cvf - . /tmp/DONE \
+    | compress -b$bits | vol -w $size /dev/fd$drive &&
+echo Done.
Index: /trunk/minix/commands/scripts/packit.sh
===================================================================
--- /trunk/minix/commands/scripts/packit.sh	(revision 9)
+++ /trunk/minix/commands/scripts/packit.sh	(revision 9)
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+PI=.postinstall
+TMP=/usr/tmp
+PATH=/bin:/usr/bin:/usr/local/bin
+
+if [ "$#" -ne 1  ]
+then
+	echo "Usage: $0 <package file>"
+	exit 1
+fi
+
+dir=`pwd`
+if [ "$1" = "-" ]
+then f=""
+else	case "$1" in
+	/*) f="$1" ;;
+	*) f="$dir/$1" ;;
+	esac
+fi
+
+cd $TMP
+rm -f $PI
+
+if [ -f $PI ]
+then	echo "$PI is in $TMP, please remove it first."
+	exit 1
+fi
+
+if [ ! -f $f ]
+then	echo "Couldn't find package $f."
+	exit 1
+fi
+
+# can we execute bunzip2?
+if bunzip2 --help 2>&1 | grep usage >/dev/null
+then	BUNZIP2=bunzip2
+else	BUNZIP2=smallbunzip2
+fi
+
+cat $f | $BUNZIP2 | pax -r -p e
+if [ -f $PI ]
+then
+	sh -e $PI
+	rm -f $PI
+fi
+
+for d in /usr/man /usr/local/man /usr/gnu/man /usr/X11R6/man
+do	if [ -d "$d" ]
+	then makewhatis $d
+	fi
+done
Index: /trunk/minix/commands/scripts/packman.sh
===================================================================
--- /trunk/minix/commands/scripts/packman.sh	(revision 9)
+++ /trunk/minix/commands/scripts/packman.sh	(revision 9)
@@ -0,0 +1,241 @@
+#!/bin/sh
+
+RC=/usr/etc/rc.package
+CDDIR=PACKAGES
+CDMP=/mnt
+CDPACK=${CDMP}/install/packages
+CDSRC=${CDMP}/install/package-sources
+SRC=/usr/src/commands
+LISTFILE=/etc/packages
+LISTURL=http://www.minix3.org/packages/List
+TMPDIR=/usr/tmp/packages
+mkdir -p $TMPDIR
+URL1=http://www.minix3.org/packages
+URL2=http://www.minix3.org/beta_packages
+SRCURL1=http://www.minix3.org/software
+SRCURL2=http://www.minix3.org/beta_software
+
+# can we execute bunzip2?
+if bunzip2 --help 2>&1 | grep usage >/dev/null
+then    BUNZIP2=bunzip2 
+else    BUNZIP2=smallbunzip2
+fi
+
+if id | fgrep "uid=0(" >/dev/null
+then	:
+else	echo "Please run $0 as root."
+	exit 1
+fi
+
+chmod 700 $TMPDIR
+
+if [ -f "$RC" ]
+then	. "$RC"
+fi
+
+cd /
+
+cdpackages=""
+if [ -n "$cddrive" ]
+then	pack=${cddrive}p2
+	umount $pack >/dev/null 2>&1 || true
+	if mount -r $pack $CDMP
+	then	fn="$CDPACK/List"
+		cdpackages=$fn
+		if [ ! -f $cdpackages ]
+		then	cdpackages=""
+			echo "No package list found on CD in $fn."
+		fi
+	else	echo "CD mount failed."
+	fi
+else	echo "Don't know where the install CD is. You can set it in $RC."
+fi
+
+# For local testing
+#cdpackages=/usr/bigports/Packages/List
+#CDPACK=/usr/bigports/Packages
+#CDSRC=/usr/bigports/Sources
+
+if [ "$cdpackages" = "" ]
+then	echo "Skipping CD packages."
+else	cont=y
+	while [ $cont = y ]
+	do	n="`wc -l $cdpackages | awk '{ print $1 }'`"
+		sourcef=$CDSRC/SizeMB
+		binf=$CDPACK/SizeMB
+		if [ -f $binf -a -f $sourcef ]
+		then	sourcemb="`cat $sourcef`"
+			binmb="`cat $binf`"
+			sourcesize=" (`expr $binmb + $sourcemb` MB uncompressed)"
+		else	sourcesize=""
+		fi
+		if [ -f $binf ]
+		then	binmb="`cat $binf`"
+			binsize=" ($binmb MB uncompressed)"
+		else	binsize=""
+		fi
+
+		echo "There are $n CD packages."
+		echo "Please choose:"
+		echo " 1  Install all $n binary packages$binsize from CD"
+		echo " 2  Install all $n binary packages + sources from CD$sourcesize"
+		echo " 3  Display the list of packages on CD"
+		echo " 4  Let me select individual packages to install from CD or network."
+		echo " 5  Exit."
+		echo -n "Choice: [4] "
+		read in
+		case "$in" in
+		1|2)
+			cd $CDPACK || exit
+			echo " * Installing binaries .."
+			for f in *.tar.bz2
+			do	echo "Installing $f binaries .."
+				packit $f && echo Installed $f
+			done
+			if [ "$in" = 2 ]
+			then
+				cd $SRC || exit
+				echo " * Installing sources in $SRC .."
+				for f in $CDSRC/*.tar.bz2
+				do	echo "$f .."
+					$BUNZIP2 -dc $f | tar xf - 
+				done
+			fi
+			;;
+		3)
+			( echo "Displaying list; press q to leave it, space for more."
+			  cat "$CDPACK/List" | awk -F'|' '{ printf "%-20s %s\n", $1, $2 }'
+			) | more
+			;;
+		""|4)
+			echo "Ok, showing packages to install." ; echo
+			cont=n
+			;;
+		5)
+			exit 0
+			;;
+		esac
+	done
+	echo -n "Press RETURN to continue .. "
+	read xyzzy
+fi
+
+TMPF=$TMPDIR/.list.$$
+rm -f $TMPF
+rm -f $TMPDIR/.*	# Remove any remaining .postinstall script or .list*
+
+netpackages=""
+if ( : </dev/tcp ) 2>/dev/null
+then	if [ -f $LISTFILE ]
+	then	echo -n "Update package list from network? (y/N) "
+		read y
+	else	echo "No package list found - retrieving initial version."
+		y=y
+	fi
+	if [ "$y" = y -o "$y" = Y ]
+	then	echo "Fetching package list."
+		urlget $LISTURL >$TMPF && mv $TMPF $LISTFILE || echo "Update not successful."
+	fi
+	netpackages=$LISTFILE
+	if [ ! -f "$netpackages" -o ! `cat "$netpackages" 2>/dev/null | wc -l | awk '{ print $1 }'` -gt 1 ]
+	then	netpackages=""
+	fi
+else	echo "No working network detected."
+fi
+
+if [ "$netpackages" = "" ]
+then	echo "Skipping network packages."
+	if [ "$cdpackages" = "" ]
+	then	echo "No packages found."
+		exit 1
+	fi
+fi
+
+cont=y
+while [ "$cont" = y ]
+do	cd $TMPDIR
+	echo ""
+	echo "Showing you a list of packages using more. Press q when"
+	echo "you want to leave the list."
+	echo -n "Press RETURN to continue.."
+	read xyzzy
+	echo "Package list:"
+	(	echo "No.|Source|Package|Description"
+		(
+		if [ -f "$netpackages" ]
+		then	sed <$netpackages 's/^/net\|/'
+		fi
+		if [ -f "$cdpackages" ]
+		then	sed <$cdpackages 's/^/cdrom\|/'
+		fi
+		) | sort -t'|' +1 | awk '{ n++; printf "%d|%s\n", n, $0 }' 
+	) >$TMPF
+	awk -F'|' <$TMPF '{ printf "%3s %-6s %-15s %s\n", $1, $2, $3, $4 }' | more
+	echo -n "Package to install? [RETURN for none] "
+	read packno
+	ok=y
+	pat="^$packno|"
+	if [ "`grep $pat $TMPF | wc -l | awk '{ print $1 }'`" -ne 1 ]
+	then	if [ "$packno" ]
+		then	echo "Wrong package number."
+		fi
+		ok=n
+	fi
+	if [ $ok = y ]
+	then	source="`grep $pat $TMPF | awk -F'|' '{ print $2 }'`"
+		packagename="`grep $pat $TMPF | awk -F'|' '{ print $3 }'`"
+		file=$packagename.tar.bz2
+		case $source in
+		net*)	echo -n "Get source of $packagename? (y/N) "
+			read src
+			echo "Retrieving binary from primary location into $TMPDIR .."
+			srcurl=""
+			if urlget $URL1/$file >$file
+			then	echo "Retrieved ok. Installing .."
+				packit $file && echo Installed ok.
+				srcurl=$SRCURL1/$file
+			else	echo "Retrying from Beta binary location.."
+				if urlget $URL2/$file >$file
+				then	echo "Retrieved ok. Installing .."
+					packit $file  && echo Installed ok.
+					srcurl=$SRCURL2/$file
+				else echo "Retrieval failed."
+				fi
+			fi
+			if [ "$src" = y -o "$src" = Y ]
+			then	(	cd $SRC || exit
+					srcfile=${packagename}-src.tar.bz2
+					echo "Retrieving source from $srcurl .."
+					urlget $srcurl >$srcfile || exit
+					echo "Source retrieved in $SRC/$srcfile."
+					$BUNZIP2 -dc $srcfile | tar xf - >/dev/null || exit
+					echo "Source unpacked in $SRC."
+				)
+			fi
+			;;
+		cdrom*)
+			if [ -f $CDPACK/$file ]
+			then	echo "Installing from $CDPACK/$file .."
+				packit $CDPACK/$file
+			else	echo "$CDPACK/$file not found."
+			fi
+			srcfile=$CDSRC/${packagename}-src.tar.bz2
+			if [ -f $srcfile ]
+			then
+				echo -n "Get source of $packagename? (y/N) "
+				read src
+				if [ "$src" = y -o "$src" = Y ]
+				then	(	cd $SRC || exit
+						$BUNZIP2 -dc $srcfile | tar xf - || exit
+						echo "Source $srcfile unpacked in $SRC."
+					)
+				fi
+			else	echo "No source on CD for $packagename."
+			fi
+			;;
+		esac
+	else	cont=n
+	fi
+done
+
+rm -f $TMPDIR/.*	# Remove any remaining .postinstall script or .list*
Index: /trunk/minix/commands/scripts/postinstall.sh
===================================================================
--- /trunk/minix/commands/scripts/postinstall.sh	(revision 9)
+++ /trunk/minix/commands/scripts/postinstall.sh	(revision 9)
@@ -0,0 +1,11 @@
+#!/bin/sh
+echo -n "Would you like to install binary packages from the CD? (y/N) "
+read y
+if [ "$y" = y -o "$y" = Y ]
+then	echo "Ok, showing you a list of packages, please type y"
+	echo "for every package you want installed."
+	/usr/bin/packme
+else	echo "Ok, not installing binary packages."
+fi
+echo "Use the 'packme' command after rebooting MINIX to get another chance"
+echo "to install binary packages."
Index: /trunk/minix/commands/scripts/rotate.sh
===================================================================
--- /trunk/minix/commands/scripts/rotate.sh	(revision 9)
+++ /trunk/minix/commands/scripts/rotate.sh	(revision 9)
@@ -0,0 +1,31 @@
+#!/bin/sh
+BZIP=/usr/local/bin/bzip2
+RM="rm -f"
+MV="mv -f"
+
+if [ $# -ne 2 ]
+then	echo "Usage: $0 <log> <keep>"
+	exit 1
+fi
+
+if [ ! -f "$1" ]
+then	 exit 1
+fi
+
+if [ ! -x "$BZIP" ]
+then	exit 1
+fi
+
+if [ "$2" -le 0 ]
+then	echo "Keep at least 1 copy please."
+	exit 1
+fi
+
+k="$2"
+$RM "$1.$k" 2>/dev/null || exit 1
+while [ "$k" -ge 2 ]
+do	prev="`expr $k - 1`"
+	$MV $1.$prev.bz2 $1.$k.bz2 2>/dev/null 
+	k=$prev
+done
+$BZIP -c $1 >$1.1.bz2 && : >$1
Index: /trunk/minix/commands/scripts/setup.sh
===================================================================
--- /trunk/minix/commands/scripts/setup.sh	(revision 9)
+++ /trunk/minix/commands/scripts/setup.sh	(revision 9)
@@ -0,0 +1,647 @@
+#!/bin/sh
+#
+#	setup 4.1 - install a MINIX distribution	
+#
+# Changes:
+#    Aug     2005   robustness checks and beautifications  (Jorrit N. Herder)
+#    Jul     2005   extended with autopart and networking  (Ben Gras)
+#    Dec 20, 1994   created  (Kees J. Bot)
+#						
+
+LOCALRC=/usr/etc/rc.local
+MYLOCALRC=/mnt/etc/rc.local
+ROOTMB=16
+ROOTSECTS="`expr $ROOTMB '*' 1024 '*' 2`"
+USRKBFILE=/.usrkb
+if [ ! -f "$USRKBFILE" ]
+then	echo "Are you really running from CD?"
+	echo "No $USRKBFILE file."
+	exit 1
+fi
+USRKB="`cat /.usrkb`"
+TOTALMB="`expr 3 + $USRKB / 1024 + $ROOTMB`"
+ROOTFILES="`cat /.rootfiles`"
+USRFILES="`cat /.usrfiles`"
+EXTRASRCFILES="`cat /.extrasrcfiles`"
+EXTRASRCKB="`cat /.extrasrckb`"
+
+# Install size without extra sources (rounded up)
+NOSRCMB="`expr $TOTALMB - $EXTRASRCKB / 1024`"
+NOSRCUSRFILES="`expr $USRFILES - $EXTRASRCFILES`"
+
+if [ "$EXTRASRCKB" -lt 1 ]
+then	 
+	echo "Are you really running from CD?"
+	echo "Something wrong with the extra-source-kb on CD."
+	exit 1
+fi
+
+if [ "$EXTRASRCFILES" -lt 1 ]
+then	 
+	echo "Are you really running from CD?"
+	echo "Something wrong with the extra-source-files estimate on CD."
+	exit 1
+fi
+
+if [ "$TOTALMB" -lt 1 ]
+then	 
+	echo "Are you really running from CD?"
+	echo "Something wrong with size estimate on CD."
+	exit 1
+fi
+
+if [ "$ROOTFILES" -lt 1 ]
+then	 
+	echo "Are you really running from CD?"
+	echo "Something wrong with root files count on CD."
+	exit 1
+fi
+
+if [ "$USRFILES" -lt 1 ]
+then	 
+	echo "Are you really running from CD?"
+	echo "Something wrong with usr files count on CD."
+	exit 1
+fi
+
+PATH=/bin:/usr/bin
+export PATH
+
+
+usage()
+{
+    cat >&2 <<'EOF'
+Usage:	setup		# Install a skeleton system on the hard disk.
+	setup /usr	# Install the rest of the system (binaries or sources).
+
+	# To install from other things then floppies:
+
+	urlget http://... | setup /usr		# Read from a web site.
+	urlget ftp://... | setup /usr		# Read from an FTP site.
+	mtools copy c0d0p0:... - | setup /usr	# Read from the C: drive.
+	dosread c0d0p0 ... | setup /usr		# Likewise if no mtools.
+EOF
+    exit 1
+}
+
+warn() 
+{
+  echo -e "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b ! $1"
+}
+
+# No options.
+while getopts '' opt; do usage; done
+shift `expr $OPTIND - 1`
+
+if [ "$USER" != root ]
+then	echo "Please run setup as root."
+	exit 1
+fi
+
+# Find out what we are running from.
+exec 9<&0 </etc/mtab			# Mounted file table.
+read thisroot rest			# Current root (/dev/ram or /dev/fd?)
+read fdusr rest				# USR (/dev/fd? or /dev/fd?p2)
+exec 0<&9 9<&-
+
+# What do we know about ROOT?
+case $thisroot:$fdusr in
+/dev/ram:/dev/fd0p2)	fdroot=/dev/fd0		# Combined ROOT+USR in drive 0
+			;;
+/dev/ram:/dev/fd1p2)	fdroot=/dev/fd1		# Combined ROOT+USR in drive 1
+			;;
+/dev/ram:/dev/fd*)	fdroot=unknown		# ROOT is some other floppy
+			;;
+/dev/fd*:/dev/fd*)	fdroot=$thisroot	# ROOT is mounted directly
+			;;
+*)			fdroot=$thisroot	# ?
+esac
+
+echo -n "
+Welcome to the MINIX 3 setup script.  This script will guide you in setting up
+MINIX on your machine.  Please consult the manual for detailed instructions.
+
+Note 1: If the screen blanks, hit CTRL+F3 to select \"software scrolling\".
+Note 2: If things go wrong then hit CTRL+C to abort and start over.
+Note 3: Default answers, like [y], can simply be chosen by hitting ENTER.
+Note 4: If you see a colon (:) then you should hit ENTER to continue.
+:"
+read ret
+
+# begin Step 1
+echo ""
+echo " --- Step 1: Select keyboard type --------------------------------------"
+echo ""
+
+    echo "What type of keyboard do you have?  You can choose one of:"
+    echo ""
+    ls -C /usr/lib/keymaps | sed -e 's/\.map//g' -e 's/^/    /'
+    echo ""
+step1=""
+while [ "$step1" != ok ]
+do
+    echo -n "Keyboard type? [us-std] "; read keymap
+    test -n "$keymap" || keymap=us-std
+    if loadkeys "/usr/lib/keymaps/$keymap.map" 2>/dev/null 
+    then step1=ok 
+    else warn "invalid keyboard"
+    fi
+done
+# end Step 1
+
+# begin Step 2
+echo ""
+echo " --- Step 2: Select your Ethernet chip ---------------------------------"
+echo ""
+
+# Ask user about networking
+echo "MINIX 3 currently supports the following Ethernet cards. Please choose: "
+    echo ""
+    echo "0. No Ethernet card (no networking)"
+    echo "1. Intel Pro/100"
+    echo "2. 3Com 501 or 3Com 509 based card"
+    echo "3. Realtek 8139 based card"
+    echo "4. Realtek 8029 based card (also emulated by Qemu)"
+    echo "   Note: If you want to use this in Qemu, set 'qemu_pci=1' in the boot monitor."
+    echo "5. NE2000, 3com 503 or WD based card (also emulated by Bochs)"
+    echo "6. AMD LANCE (also emulated by VMWare)"
+    echo "7. Different Ethernet card (no networking)"
+    echo ""
+    echo "You can always change your mind after the setup."
+    echo ""
+step2=""
+while [ "$step2" != ok ]
+do
+    eth=""
+    echo -n "Ethernet card? [0] "; read eth
+    test -z $eth && eth=0
+    driver=""
+    driverargs=""
+    case "$eth" in
+        0) step2="ok"; ;;    
+	1) step2="ok";	driver=fxp;      ;;
+	2) step2="ok";	driver=dpeth;    driverargs="#dpeth_arg='DPETH0=port:irq:memory'";
+	   echo ""
+           echo "Note: After installing, edit $LOCALRC to the right configuration."
+		;;
+	3) step2="ok";	driver=rtl8139;  ;;
+	4) step2="ok";	driver=dp8390;   driverargs="dp8390_arg='DPETH0=pci'";	;;
+	5) step2="ok";	driver=dp8390;   driverargs="dp8390_arg='DPETH0=240:9'"; 
+	   echo ""
+           echo "Note: After installing, edit $LOCALRC to the right configuration."
+           echo " chose option 4, the defaults for emulation by Bochs have been set."
+		;;
+        6) driver="lance"; driverargs="lance_arg='LANCE0=on'"; step2="ok"; ;;    
+        7) step2="ok"; ;;    
+        *) warn "choose a number"
+    esac
+done
+# end Step 2
+
+# begin Step 3
+step3=""
+while [ "$step3" != ok ]
+do
+	echo ""
+	echo " --- Step 3: Select minimal or full distribution -----------------------"
+	echo ""
+	echo "You can install MINIX as (M)inimal or (F)ull. (M)inimal"
+	echo "includes only the binary system and basic system sources."
+	echo "(F)ull also includes commands sources."
+	echo ""
+	echo "Please select:"
+	echo "  (M)inimal install (only basic sources) ($NOSRCMB MB required)"
+	echo "  (F)ull install (full install) ($TOTALMB MB required)"
+	echo " "
+	echo -n "Basic (M)inimal or (F)ull install? [F] "
+	read conf
+	case "$conf" in
+	"") 	step3="ok"; nobigsource="" ;;
+	[Ff]*)	step3="ok"; nobigsource="" ;;
+	[Mm]*)	step3="ok"; nobigsource="1"; TOTALMB=$NOSRCMB; USRFILES=$NOSRCUSRFILES ;;
+	esac
+done
+# end Step 3
+
+# begin Step 4
+step4=""
+while [ "$step4" != ok ]
+do
+	echo ""
+	echo " --- Step 4: Create or select a partition for MINIX 3 -------------------"
+	echo ""
+
+    echo "Now you need to create a MINIX 3 partition on your hard disk."
+    echo "It has to have $TOTALMB MB at the very least."
+    echo "You can also select one that's already there."
+    echo " "
+    echo "If you have an existing installation, reinstalling will let you"
+    echo "keep your current partitioning and subpartitioning, and overwrite"
+    echo "everything except your s1 subpartition (/home). If you want to"
+    echo "reinstall, select your existing minix partition."
+    echo " "
+    echo "Unless you are an expert, you are advised to use the automated"
+    echo "step-by-step help in setting up."
+    echo ""
+    ok=""
+    while [ "$ok" = "" ]
+    do
+	    echo -n "Press ENTER for automatic mode, or type 'expert': "
+	    read mode
+	    if [ -z "$mode" ]; then auto="1"; ok="yes"; fi 
+	    if [ "$mode" = expert ]; then auto=""; ok="yes"; fi
+	    if [ "$ok" != yes ]; then warn "try again"; fi 
+    done
+
+	primary=
+
+	if [ -z "$auto" ]
+	then
+		# Expert mode
+		echo -n "
+MINIX needs one primary partition of $TOTALMB MB for a full install,
+plus what you want for /home.
+The maximum file system currently supported is 4 GB.
+
+If there is no free space on your disk then you have to choose an option:
+   (1) Delete one or more partitions
+   (2) Allocate an existing partition to MINIX 3
+   (3) Exit setup and shrink a partition using a different OS
+
+To make this partition you will be put in the editor \"part\".  Follow the
+advice under the '!' key to make a new partition of type MINIX.  Do not
+touch an existing partition unless you know precisely what you are doing!
+Please note the name of the partition (e.g. c0d0p1, c0d1p3, c1d1p0) you
+make.  (See the devices section in usage(8) on MINIX device names.)
+:"
+		read ret
+
+		while [ -z "$primary" ]
+		do
+		    part || exit
+
+		    echo -n "
+Please finish the name of the primary partition you have created:
+(Just type ENTER if you want to rerun \"part\")                   /dev/"
+		    read primary
+		done
+		echo ""
+		echo "This is the point of no return.  You have selected to install MINIX"
+		echo "on partition /dev/$primary.  Please confirm that you want to use this"
+		echo "selection to install MINIX."
+		echo ""
+		confirmation=""
+		while [ -z "$confirmation" -o "$confirmation" != yes -a "$confirmation" != no ]
+		do
+			echo -n "Are you sure you want to continue? Please enter 'yes' or 'no': "
+			read confirmation
+			if [ "$confirmation" = yes ]; then step4=ok; fi
+		done
+		biosdrivename="Actual BIOS device name unknown, due to expert mode."
+	else
+		if [ "$auto" = "1" ]
+		then
+			# Automatic mode
+			PF="/tmp/pf"
+			if autopart -m$TOTALMB -f$PF
+			then	if [ -s "$PF" ]
+				then
+					set `cat $PF`
+					bd="$1"
+					bdn="$2"
+					biosdrivename="Probably, the right command is \"boot $bdn\"."
+					if [ -b "/dev/$bd" ]
+					then	primary="$bd"
+					else	echo "Funny device $bd from autopart."
+					fi
+				else
+					echo "Didn't find output from autopart."
+				fi 
+			else	echo "Autopart tool failed. Trying again."
+			fi
+
+			# Reset at retries and timeouts in case autopart left
+			# them messy.
+			atnormalize
+
+			if [ -n "$primary" ]; then step4=ok; fi
+		fi
+	fi
+
+	if [ ! -b "/dev/$primary" ]
+	then	echo "/dev/$primary is not a block device."
+		step4=""
+	else
+		devsize="`devsize /dev/$primary`"
+
+		if [ "$devsize" -lt 1 ]
+		then	echo "/dev/$primary is a 0-sized device."
+			step4=""
+		fi
+	fi
+done	# while step4 != ok
+# end Step 4
+
+root=${primary}s0
+home=${primary}s1
+usr=${primary}s2
+umount /dev/$root 2>/dev/null && echo "Unmounted $root for you."
+umount /dev/$home 2>/dev/null && echo "Unmounted $home for you."
+umount /dev/$usr 2>/dev/null && echo "Unmounted $usr for you."
+
+devsizemb="`expr $devsize / 1024 / 2`"
+maxhome="`expr $devsizemb - $TOTALMB - 1`"
+
+if [ "$devsizemb" -lt "$TOTALMB" ]
+then	echo "The selected partition ($devsizemb MB) is too small."
+	echo "You'll need $TOTALMB MB at least."
+	exit 1
+fi
+
+if [ "$maxhome" -lt 1 ]
+then	echo "Note: you can't have /home with that size partition."
+	maxhome=0
+fi
+
+TMPMP=/m
+mkdir $TMPMP >/dev/null 2>&1
+
+confirm=""
+
+while [ "$confirm" = "" ]
+do
+	auto=""
+	echo ""
+echo " --- Step 5: Reinstall choice ------------------------------------------"
+	if mount -r /dev/$home $TMPMP >/dev/null 2>&1
+	then	umount /dev/$home >/dev/null 2>&1
+		echo ""
+		echo "You have selected an existing MINIX 3 partition."
+		echo "Type F for full installation (to overwrite entire partition)"
+		echo "Type R for a reinstallation (existing /home will not be affected)"
+		echo ""
+		echo -n "(F)ull or (R)einstall? [R] "
+		read conf
+		case "$conf" in
+		"") 	confirm="ok"; auto="r"; ;;
+		[Rr]*)	confirm="ok"; auto="r"; ;;
+		[Ff]*)	confirm="ok"; auto="" ;;
+		esac
+
+	else	echo ""
+		echo "No old /home found. Doing full install."
+		echo ""
+		confirm="ok";
+	fi
+
+done
+
+rmdir $TMPMP
+
+nohome="0"
+
+homesize=""
+if [ ! "$auto" = r ]
+then	
+echo ""
+echo " --- Step 6: Select the size of /home ----------------------------------"
+	while [ -z "$homesize" ]
+	do
+
+		# 20% of what is left over after / and /usr
+		# are taken.
+		defmb="`expr $maxhome / 5`"
+		if [ "$defmb" -gt "$maxhome" ]
+		then
+			defmb=$maxhome
+		fi
+
+		echo ""
+		echo "MINIX will take up $TOTALMB MB, without /home."
+		echo -n "How big do you want your /home to be in MB (0-$maxhome) ? [$defmb] "
+		read homesize
+		if [ "$homesize" = "" ] ; then homesize=$defmb; fi
+		if [ "$homesize" -lt 1 ]
+		then	nohome=1
+			echo "Ok, not making a /home."
+			homesize=0
+		else
+			if [ "$homesize" -gt "$maxhome" ]
+			then	echo "That won't fit!"
+				homesize=""
+			else
+				echo ""
+				echo -n "$homesize MB Ok? [Y] "
+				read ok
+				[ "$ok" = Y -o "$ok" = y -o "$ok" = "" ] || homesize=""
+			fi
+		fi
+		echo ""
+	done
+	# Homesize in sectors
+	homemb="$homesize MB"
+	homesize="`expr $homesize '*' 1024 '*' 2`"
+else
+	homepart="`devsize /dev/$home`"
+	homesize="`expr $homepart / 2 / 1024`"
+	if [ "$homesize" -gt "$maxhome" ]
+	then
+		echo "Sorry, but your /home is too big ($homesize MB) to leave enough"
+		echo "space on the rest of the partition ($devsizemb MB) for your"
+		echo "selected installation size ($TOTALMB MB)."
+		exit 1
+	fi
+	# Homesize unchanged (reinstall)
+	homesize=exist
+	homemb="current size"
+fi
+
+blockdefault=4
+
+if [ ! "$auto" = "r" ]
+then
+	echo ""
+echo " --- Step 7: Select a block size ---------------------------------------"
+	echo ""
+	
+	echo "The maximum (and default) file system block size is $blockdefault KB."
+	echo "For a small disk or small RAM you may want 1 or 2 KB blocks."
+	echo ""
+	
+	while [ -z "$blocksize" ]
+	do	
+		echo -n "Block size in kilobytes? [$blockdefault] "; read blocksize
+		test -z "$blocksize" && blocksize=$blockdefault
+		if [ "$blocksize" -ne 1 -a "$blocksize" -ne 2 -a "$blocksize" -ne $blockdefault ]
+		then	
+			warn "1, 2 or 4 please"
+			blocksize=""
+		fi
+	done
+else
+	blocksize=$blockdefault
+fi
+
+blocksizebytes="`expr $blocksize '*' 1024`"
+
+echo "
+You have selected to (re)install MINIX 3 in the partition /dev/$primary.
+The following subpartitions are now being created on /dev/$primary:
+
+    Root subpartition:	/dev/$root	$ROOTMB MB
+    /home subpartition:	/dev/$home	$homemb
+    /usr subpartition:	/dev/$usr	rest of $primary
+"
+					# Secondary master bootstrap.
+installboot -m /dev/$primary /usr/mdec/masterboot >/dev/null || exit
+					# Partition the primary.
+partition /dev/$primary 1 81:${ROOTSECTS}* 81:$homesize 81:0+ > /dev/null || exit
+
+echo "Creating /dev/$root for / .."
+mkfs -B $blocksizebytes /dev/$root || exit
+
+if [ "$nohome" = 0 ]
+then
+	if [ ! "$auto" = r ]
+	then	echo "Creating /dev/$home for /home .."
+		mkfs -B $blocksizebytes /dev/$home || exit
+	fi
+else	echo "Skipping /home"
+fi
+
+echo "Creating /dev/$usr for /usr .."
+mkfs -B $blocksizebytes /dev/$usr || exit
+
+echo ""
+echo " --- Step 8: Wait for bad block detection ------------------------------"
+echo ""
+echo "Scanning disk for bad blocks.  Hit CTRL+C to stop the scan if you are"
+echo "sure that there can not be any bad blocks.  Otherwise just wait."
+
+trap ': nothing;echo' 2
+
+echo ""
+echo "Scanning /dev/$root for bad blocks:"
+readall -b /dev/$root | sh
+
+if [ "$nohome" = 0 ]
+then
+	echo ""
+	echo "Scanning /dev/$home for bad blocks:"
+	readall -b /dev/$home | sh
+	fshome="home=/dev/$home"
+else	fshome=""
+fi
+
+echo ""
+echo "Scanning /dev/$usr for bad blocks:"
+readall -b /dev/$usr | sh
+
+trap 2
+
+echo ""
+echo " --- Step 9: Wait for files to be copied -------------------------------"
+echo ""
+echo "This is the final step of the MINIX 3 setup.  All files will now be"
+echo "copied to your hard disk.  This may take a while."
+echo ""
+
+mount /dev/$usr /mnt >/dev/null || exit		# Mount the intended /usr.
+
+(cd /usr || exit 1
+ if [ "$nobigsource" = 1 ]
+ then	list="`ls | fgrep -v src. | fgrep -v install`"
+ else	list="`ls | fgrep -v install`"
+ fi
+ for d in $list
+ do	
+ 	cpdir -v $d /mnt/$d
+ done
+) | progressbar "$USRFILES" || exit	# Copy the usr floppy.
+
+if [ -d /mnt/src.commands ]
+then	mv /mnt/src.commands /mnt/src/commands
+fi
+
+if [ -d /mnt/src.contrib ]
+then	mv /mnt/src.contrib /mnt/src/contrib
+fi
+					# Set inet.conf to correct driver
+if [ -n "$driver" ]
+then	echo "$driverargs" >$MYLOCALRC
+fi
+
+umount /dev/$usr >/dev/null || exit		# Unmount the intended /usr.
+mount /dev/$root /mnt >/dev/null || exit
+
+# Running from the installation CD.
+cpdir -vx / /mnt | progressbar "$ROOTFILES" || exit	
+cp /mnt/etc/motd.install /mnt/etc/motd
+
+# Fix /var/log
+rm /mnt/var/log
+ln -s /usr/log /mnt/var/log
+
+if [ -n "$driver" ]
+then	echo "eth0 $driver 0 { default; };" >/mnt/etc/inet.conf
+fi
+
+# CD remnants that aren't for the installed system
+rm /mnt/etc/issue /mnt/CD /mnt/.* 2>/dev/null
+					# Change /etc/fstab. (No swap.)
+					# ${swap:+swap=/dev/$swap}
+echo >/mnt/etc/fstab "\
+# Poor man's File System Table.
+
+root=/dev/$root
+usr=/dev/$usr
+$fshome"
+
+					# National keyboard map.
+test -n "$keymap" && cp -p "/usr/lib/keymaps/$keymap.map" /mnt/etc/keymap
+
+umount /dev/$root >/dev/null || exit	# Unmount the new root.
+mount /dev/$usr /mnt >/dev/null || exit
+
+# Make bootable.
+installboot -d /dev/$root /usr/mdec/bootblock /boot/boot >/dev/null || exit
+
+edparams /dev/$root "rootdev=$root; ramimagedev=$root; minix(1,Start MINIX 3 (requires at least 16 MB RAM)) { image=/boot/image_big; boot; }; smallminix(2,Start Small MINIX 3 (intended for 8 MB RAM systems)) { image=/boot/image_small; boot; }; newminix(3,Start Custom MINIX 3) { unset image; boot }; main() { echo By default, MINIX 3 will automatically load in 3 seconds.; echo Press ESC to enter the monitor for special configuration.; trap 3000 boot; menu; }; save" || exit
+pfile="/mnt/src/tools/fdbootparams"
+echo "rootdev=$root; ramimagedev=$root; save" >$pfile
+# Save name of CD drive
+cddrive="`mount | grep usr | awk '{ print $1 }' | sed 's/p.*//'`" 
+echo "cddrive=$cddrive" >>/mnt/etc/rc.package
+
+bios="`echo $primary | sed -e 's/d./dX/g' -e 's/c.//g'`"
+
+if [ ! "$auto" = "r" ]
+then	if mount /dev/$home /home 2>/dev/null
+	then	for u in bin ast
+		do	if mkdir ~$u
+			then	echo " * Creating home directory for $u in ~$u"
+				cpdir /usr/ast ~$u
+				chown -R $u:operator ~$u
+			else	echo " * Couldn't create ~$u"
+			fi
+		done
+		umount /dev/$home
+	fi
+fi
+
+echo "Saving random data.."
+dd if=/dev/random of=/mnt/adm/random.dat bs=1024 count=1
+
+echo "
+Please type 'shutdown' to exit MINIX 3 and enter the boot monitor. At
+the boot monitor prompt, type 'boot $bios', where X is the bios drive
+number of the drive you installed on, to try your new MINIX system.
+$biosdrivename
+
+This ends the MINIX 3 setup script.  After booting your newly set up system,
+you can run the test suites as indicated in the setup manual.  You also 
+may want to take care of local configuration, such as securing your system
+with a password.  Please consult the usage manual for more information. 
+
+"
+
Index: /trunk/minix/commands/scripts/spell.sh
===================================================================
--- /trunk/minix/commands/scripts/spell.sh	(revision 9)
+++ /trunk/minix/commands/scripts/spell.sh	(revision 9)
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+#	spell 1.1 - show unknown words			Author: Kees J. Bot
+#								28 Apr 1995
+
+dict=words
+
+while getopts 'd:' opt
+do
+	case $opt in
+	d)	dict="$OPTARG"
+		;;
+	?)	echo "Usage: spell [-d dict] [file ...]" >&2; exit 1
+	esac
+done
+shift `expr $OPTIND - 1`
+
+case "$dict" in
+*/*)	;;
+*)	dict="/usr/lib/dict/$dict"
+esac
+
+{
+	if [ $# = 0 ]
+	then
+		prep
+	else
+		for file
+		do
+			prep "$file"
+		done
+	fi
+} | {
+	sort -u | comm -23 - "$dict"
+}
Index: /trunk/minix/commands/scripts/srccrc.sh
===================================================================
--- /trunk/minix/commands/scripts/srccrc.sh	(revision 9)
+++ /trunk/minix/commands/scripts/srccrc.sh	(revision 9)
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+#	srccrc 1.0 - compute CRC checksums of the entire source tree
+#							Author: Kees J. Bot
+cd /usr || exit
+
+{
+	# List the file names of all files in /usr/include and /usr/src.
+	find include src/* -type f
+} | {
+	# Sort the list to make them comparable.
+	sort
+} | {
+	# Remove files like *.o, *.bak, etc.
+	sed -e '/\.o$/d
+		/\.a$/d
+		/\.bak$/d
+		/\/a\.out$/d
+		/\/core$/d
+		/\/bin\/[^/]*$/d'
+} | {
+	# Compute checksums.
+	xargs crc
+}
Index: /trunk/minix/commands/scripts/svclog.sh
===================================================================
--- /trunk/minix/commands/scripts/svclog.sh	(revision 9)
+++ /trunk/minix/commands/scripts/svclog.sh	(revision 9)
@@ -0,0 +1,6 @@
+#!/bin/sh
+#
+svc=`basename $1 ,S`,S
+if test \( ! -r $svc \) -a -d "SVC" ; then svc=SVC/$svc ; fi
+grep '^#\*\*\*SVC' $svc
+
Index: /trunk/minix/commands/scripts/version.sh
===================================================================
--- /trunk/minix/commands/scripts/version.sh	(revision 9)
+++ /trunk/minix/commands/scripts/version.sh	(revision 9)
@@ -0,0 +1,2 @@
+#!/bin/sh
+cat /etc/version
Index: /trunk/minix/commands/scripts/whatis.sh
===================================================================
--- /trunk/minix/commands/scripts/whatis.sh	(revision 9)
+++ /trunk/minix/commands/scripts/whatis.sh	(revision 9)
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# whatis/apropos 1.3 - search whatis(5) database for commands
+#							Author: Kees J. Bot
+# BUGS
+#	whatis file must be as if created by makewhatis(8).
+#
+# This version includes a fix by Michael Haardt originally posted to 
+# comp.os.minix in July 1999.  Fixes for grep provided by Michael in May
+# 1999 caused whatis to break, this is now fixed.   (ASW 2004-12-12)
+
+all='exit 0'
+
+case "$1" in
+-a)	all="found='exit 0'"
+	shift
+esac
+
+case $#:$0 in
+1:*whatis)
+	;;
+1:*apropos)
+	all="found='exit 0'"
+	;;
+*)	echo "Usage: `basename $0` [-a] <keyword>" >&2
+	exit 1
+esac
+
+IFS=":$IFS"
+MANPATH="${MANPATH-/usr/local/man:/usr/man}"
+
+found=
+
+for m in $MANPATH
+do
+	for w in $m/whatis
+	do
+		test -f $w || continue
+
+		case $0 in
+		*whatis)
+			grep '^\('$1'\|[^(]* '$1'\)[ ,][^(]*(' $w && eval $all
+			;;
+		*apropos)
+			grep -i "$1" $w && eval $all
+		esac
+	done
+done
+
+$found
+
+echo "`basename $0`: $1: not found" >&2
+exit 1
Index: /trunk/minix/commands/scripts/whereis.sh
===================================================================
--- /trunk/minix/commands/scripts/whereis.sh	(revision 9)
+++ /trunk/minix/commands/scripts/whereis.sh	(revision 9)
@@ -0,0 +1,23 @@
+#!/bin/sh
+: List all system directories containing the argument
+: Author: Terrence W. Holm
+if test $# -ne 1; then
+  echo "Usage:  whereis  name"
+  exit 1
+fi
+
+path="/bin /lib /etc\
+      /usr/bin /usr/lib\
+      /usr/include /usr/include/sys"
+
+for dir in $path; do
+  for file in $dir/$1 $dir/$1.*; do
+    if test -f $file; then
+      echo $file 
+    elif test -d $file; then
+      echo $file/
+      fi
+    done
+  done
+
+exit 0
Index: /trunk/minix/commands/sh/Makefile
===================================================================
--- /trunk/minix/commands/sh/Makefile	(revision 9)
+++ /trunk/minix/commands/sh/Makefile	(revision 9)
@@ -0,0 +1,29 @@
+# Makefile for sh
+
+CFLAGS	= -O -D_MINIX -D_POSIX_SOURCE -wa
+LDFLAGS	= -i
+CC = exec cc
+
+OBJ	= sh1.o sh2.o sh3.o sh4.o sh5.o sh6.o
+
+all:	sh
+
+sh:	$(OBJ)
+	cc $(LDFLAGS) -o $@ $(OBJ)
+	install -S 11kw sh
+
+install:	/usr/bin/msh
+
+/usr/bin/msh:	sh
+	install -cs -o bin $? $@
+
+#/usr/bin/sh:	/usr/bin/msh
+#	install -l $? $@
+#
+#/bin/sh:	/usr/bin/msh
+#	install -lcs $? $@
+
+$(OBJ):	sh.h
+
+clean:
+	rm -f sh *.o *.bak core
Index: /trunk/minix/commands/sh/build
===================================================================
--- /trunk/minix/commands/sh/build	(revision 9)
+++ /trunk/minix/commands/sh/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/sh/sh.h
===================================================================
--- /trunk/minix/commands/sh/sh.h	(revision 9)
+++ /trunk/minix/commands/sh/sh.h	(revision 9)
@@ -0,0 +1,383 @@
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+/* Need a way to have void used for ANSI, nothing for K&R. */
+#ifndef _ANSI
+#undef _VOID
+#define _VOID
+#endif
+
+/* -------- sh.h -------- */
+/*
+ * shell
+ */
+
+#define	LINELIM	4096
+#define	NPUSH	8	/* limit to input nesting */
+
+#define	NOFILE	20	/* Number of open files */
+#define	NUFILE	10	/* Number of user-accessible files */
+#define	FDBASE	10	/* First file usable by Shell */
+
+/*
+ * values returned by wait
+ */
+#define	WAITSIG(s) ((s)&0177)
+#define	WAITVAL(s) (((s)>>8)&0377)
+#define	WAITCORE(s) (((s)&0200)!=0)
+
+/*
+ * library and system defintions
+ */
+#ifdef __STDC__
+typedef void xint;	/* base type of jmp_buf, for not broken compilers */
+#else
+typedef char * xint;	/* base type of jmp_buf, for broken compilers */
+#endif
+
+/*
+ * shell components
+ */
+/* #include "area.h" */
+/* #include "word.h" */
+/* #include "io.h" */
+/* #include "var.h" */
+
+#define	QUOTE	0200
+
+#define	NOBLOCK	((struct op *)NULL)
+#define	NOWORD	((char *)NULL)
+#define	NOWORDS	((char **)NULL)
+#define	NOPIPE	((int *)NULL)
+
+/*
+ * Description of a command or an operation on commands.
+ * Might eventually use a union.
+ */
+struct op {
+	int	type;	/* operation type, see below */
+	char	**words;	/* arguments to a command */
+	struct	ioword	**ioact;	/* IO actions (eg, < > >>) */
+	struct op *left;
+	struct op *right;
+	char	*str;	/* identifier for case and for */
+};
+
+#define	TCOM	1	/* command */
+#define	TPAREN	2	/* (c-list) */
+#define	TPIPE	3	/* a | b */
+#define	TLIST	4	/* a [&;] b */
+#define	TOR	5	/* || */
+#define	TAND	6	/* && */
+#define	TFOR	7
+#define	TDO	8
+#define	TCASE	9
+#define	TIF	10
+#define	TWHILE	11
+#define	TUNTIL	12
+#define	TELIF	13
+#define	TPAT	14	/* pattern in case */
+#define	TBRACE	15	/* {c-list} */
+#define	TASYNC	16	/* c & */
+
+/*
+ * actions determining the environment of a process
+ */
+#define	BIT(i)	(1<<(i))
+#define	FEXEC	BIT(0)	/* execute without forking */
+
+/*
+ * flags to control evaluation of words
+ */
+#define	DOSUB	1	/* interpret $, `, and quotes */
+#define	DOBLANK	2	/* perform blank interpretation */
+#define	DOGLOB	4	/* interpret [?* */
+#define	DOKEY	8	/* move words with `=' to 2nd arg. list */
+#define	DOTRIM	16	/* trim resulting string */
+
+#define	DOALL	(DOSUB|DOBLANK|DOGLOB|DOKEY|DOTRIM)
+
+Extern	char	**dolv;
+Extern	int	dolc;
+Extern	int	exstat;
+Extern  char	gflg;
+Extern  int	talking;	/* interactive (talking-type wireless) */
+Extern  int	execflg;
+Extern  int	multiline;	/* \n changed to ; */
+Extern  struct	op	*outtree;	/* result from parser */
+
+Extern	xint	*failpt;
+Extern	xint	*errpt;
+
+struct	brkcon {
+	jmp_buf	brkpt;
+	struct	brkcon	*nextlev;
+} ;
+Extern	struct brkcon	*brklist;
+Extern	int	isbreak;
+
+/*
+ * redirection
+ */
+struct ioword {
+	short	io_unit;	/* unit affected */
+	short	io_flag;	/* action (below) */
+	char	*io_name;	/* file name */
+};
+#define	IOREAD	1	/* < */
+#define	IOHERE	2	/* << (here file) */
+#define	IOWRITE	4	/* > */
+#define	IOCAT	8	/* >> */
+#define	IOXHERE	16	/* ${}, ` in << */
+#define	IODUP	32	/* >&digit */
+#define	IOCLOSE	64	/* >&- */
+
+#define	IODEFAULT (-1)	/* token for default IO unit */
+
+Extern	struct	wdblock	*wdlist;
+Extern	struct	wdblock	*iolist;
+
+/*
+ * parsing & execution environment
+ */
+extern struct	env {
+	char	*linep;
+	struct	io	*iobase;
+	struct	io	*iop;
+	xint	*errpt;
+	int	iofd;
+	struct	env	*oenv;
+} e;
+
+/*
+ * flags:
+ * -e: quit on error
+ * -k: look for name=value everywhere on command line
+ * -n: no execution
+ * -t: exit after reading and executing one command
+ * -v: echo as read
+ * -x: trace
+ * -u: unset variables net diagnostic
+ */
+extern	char	*flag;
+
+extern	char	*null;	/* null value for variable */
+extern	int	intr;	/* interrupt pending */
+
+Extern	char	*trap[_NSIG+1];
+Extern	char	ourtrap[_NSIG+1];
+Extern	int	trapset;	/* trap pending */
+
+extern	int	heedint;	/* heed interrupt signals */
+
+Extern	int	yynerrs;	/* yacc */
+
+Extern	char	line[LINELIM];
+extern	char	*elinep;
+
+/*
+ * other functions
+ */
+#ifdef __STDC__
+int (*inbuilt(char *s ))(void);
+#else
+int (*inbuilt())();
+#endif
+_PROTOTYPE(char *rexecve , (char *c , char **v , char **envp ));
+_PROTOTYPE(char *space , (int n ));
+_PROTOTYPE(char *strsave , (char *s , int a ));
+_PROTOTYPE(char *evalstr , (char *cp , int f ));
+_PROTOTYPE(char *putn , (int n ));
+_PROTOTYPE(char *itoa , (unsigned u , int n ));
+_PROTOTYPE(char *unquote , (char *as ));
+_PROTOTYPE(struct var *lookup , (char *n ));
+_PROTOTYPE(int rlookup , (char *n ));
+_PROTOTYPE(struct wdblock *glob , (char *cp , struct wdblock *wb ));
+_PROTOTYPE(int subgetc , (int ec , int quoted ));
+_PROTOTYPE(char **makenv , (void));
+_PROTOTYPE(char **eval , (char **ap , int f ));
+_PROTOTYPE(int setstatus , (int s ));
+_PROTOTYPE(int waitfor , (int lastpid , int canintr ));
+
+_PROTOTYPE(void onintr , (int s )); /* SIGINT handler */
+
+_PROTOTYPE(int newenv , (int f ));
+_PROTOTYPE(void quitenv , (void));
+_PROTOTYPE(void err , (char *s ));
+_PROTOTYPE(int anys , (char *s1 , char *s2 ));
+_PROTOTYPE(int any , (int c , char *s ));
+_PROTOTYPE(void next , (int f ));
+_PROTOTYPE(void setdash , (void));
+_PROTOTYPE(void onecommand , (void));
+_PROTOTYPE(void runtrap , (int i ));
+_PROTOTYPE(void xfree , (char *s ));
+_PROTOTYPE(int letter , (int c ));
+_PROTOTYPE(int digit , (int c ));
+_PROTOTYPE(int letnum , (int c ));
+_PROTOTYPE(int gmatch , (char *s , char *p ));
+
+/*
+ * error handling
+ */
+_PROTOTYPE(void leave , (void)); /* abort shell (or fail in subshell) */
+_PROTOTYPE(void fail , (void));	 /* fail but return to process next command */
+_PROTOTYPE(void warn , (char *s ));
+_PROTOTYPE(void sig , (int i ));	 /* default signal handler */
+
+/* -------- var.h -------- */
+
+struct	var {
+	char	*value;
+	char	*name;
+	struct	var	*next;
+	char	status;
+};
+#define	COPYV	1	/* flag to setval, suggesting copy */
+#define	RONLY	01	/* variable is read-only */
+#define	EXPORT	02	/* variable is to be exported */
+#define	GETCELL	04	/* name & value space was got with getcell */
+
+Extern	struct	var	*vlist;		/* dictionary */
+
+Extern	struct	var	*homedir;	/* home directory */
+Extern	struct	var	*prompt;	/* main prompt */
+Extern	struct	var	*cprompt;	/* continuation prompt */
+Extern	struct	var	*path;		/* search path for commands */
+Extern	struct	var	*shell;		/* shell to interpret command files */
+Extern	struct	var	*ifs;		/* field separators */
+
+_PROTOTYPE(int yyparse , (void));
+_PROTOTYPE(struct var *lookup , (char *n ));
+_PROTOTYPE(void setval , (struct var *vp , char *val ));
+_PROTOTYPE(void nameval , (struct var *vp , char *val , char *name ));
+_PROTOTYPE(void export , (struct var *vp ));
+_PROTOTYPE(void ronly , (struct var *vp ));
+_PROTOTYPE(int isassign , (char *s ));
+_PROTOTYPE(int checkname , (char *cp ));
+_PROTOTYPE(int assign , (char *s , int cf ));
+_PROTOTYPE(void putvlist , (int f , int out ));
+_PROTOTYPE(int eqname , (char *n1 , char *n2 ));
+
+_PROTOTYPE(int execute , (struct op *t , int *pin , int *pout , int act ));
+
+/* -------- io.h -------- */
+/* io buffer */
+struct iobuf {
+  unsigned id;				/* buffer id */
+  char buf[512];			/* buffer */
+  char *bufp;				/* pointer into buffer */
+  char *ebufp;				/* pointer to end of buffer */
+};
+
+/* possible arguments to an IO function */
+struct ioarg {
+	char	*aword;
+	char	**awordlist;
+	int	afile;		/* file descriptor */
+	unsigned afid;		/* buffer id */
+	long	afpos;		/* file position */
+	struct iobuf *afbuf;	/* buffer for this file */
+};
+Extern struct ioarg ioargstack[NPUSH];
+#define AFID_NOBUF	(~0)
+#define AFID_ID		0
+
+/* an input generator's state */
+struct	io {
+	int	(*iofn)(_VOID);
+	struct	ioarg	*argp;
+	int	peekc;
+	char	prev;		/* previous character read by readc() */
+	char	nlcount;	/* for `'s */
+	char	xchar;		/* for `'s */
+	char	task;		/* reason for pushed IO */
+};
+Extern	struct	io	iostack[NPUSH];
+#define	XOTHER	0	/* none of the below */
+#define	XDOLL	1	/* expanding ${} */
+#define	XGRAVE	2	/* expanding `'s */
+#define	XIO	3	/* file IO */
+
+/* in substitution */
+#define	INSUB()	(e.iop->task == XGRAVE || e.iop->task == XDOLL)
+
+/*
+ * input generators for IO structure
+ */
+_PROTOTYPE(int nlchar , (struct ioarg *ap ));
+_PROTOTYPE(int strchar , (struct ioarg *ap ));
+_PROTOTYPE(int qstrchar , (struct ioarg *ap ));
+_PROTOTYPE(int filechar , (struct ioarg *ap ));
+_PROTOTYPE(int herechar , (struct ioarg *ap ));
+_PROTOTYPE(int linechar , (struct ioarg *ap ));
+_PROTOTYPE(int gravechar , (struct ioarg *ap , struct io *iop ));
+_PROTOTYPE(int qgravechar , (struct ioarg *ap , struct io *iop ));
+_PROTOTYPE(int dolchar , (struct ioarg *ap ));
+_PROTOTYPE(int wdchar , (struct ioarg *ap ));
+_PROTOTYPE(void scraphere , (void));
+_PROTOTYPE(void freehere , (int area ));
+_PROTOTYPE(void gethere , (void));
+_PROTOTYPE(void markhere , (char *s , struct ioword *iop ));
+_PROTOTYPE(int herein , (char *hname , int xdoll ));
+_PROTOTYPE(int run , (struct ioarg *argp , int (*f)(_VOID)));
+
+/*
+ * IO functions
+ */
+_PROTOTYPE(int eofc , (void));
+_PROTOTYPE(int getc , (int ec ));
+_PROTOTYPE(int readc , (void));
+_PROTOTYPE(void unget , (int c ));
+_PROTOTYPE(void ioecho , (int c ));
+_PROTOTYPE(void prs , (char *s ));
+_PROTOTYPE(void putc , (int c ));
+_PROTOTYPE(void prn , (unsigned u ));
+_PROTOTYPE(void closef , (int i ));
+_PROTOTYPE(void closeall , (void));
+
+/*
+ * IO control
+ */
+_PROTOTYPE(void pushio , (struct ioarg *argp , int (*fn)(_VOID)));
+_PROTOTYPE(int remap , (int fd ));
+_PROTOTYPE(int openpipe , (int *pv ));
+_PROTOTYPE(void closepipe , (int *pv ));
+_PROTOTYPE(struct io *setbase , (struct io *ip ));
+
+extern	struct	ioarg	temparg;	/* temporary for PUSHIO */
+#define	PUSHIO(what,arg,gen) ((temparg.what = (arg)),pushio(&temparg,(gen)))
+#define	RUN(what,arg,gen) ((temparg.what = (arg)), run(&temparg,(gen)))
+
+/* -------- word.h -------- */
+#ifndef WORD_H
+#define	WORD_H	1
+struct	wdblock {
+	short	w_bsize;
+	short	w_nword;
+	/* bounds are arbitrary */
+	char	*w_words[1];
+};
+
+_PROTOTYPE(struct wdblock *addword , (char *wd , struct wdblock *wb ));
+_PROTOTYPE(struct wdblock *newword , (int nw ));
+_PROTOTYPE(char **getwords , (struct wdblock *wb ));
+#endif
+
+/* -------- area.h -------- */
+
+/*
+ * storage allocation
+ */
+_PROTOTYPE(char *getcell , (unsigned nbytes ));
+_PROTOTYPE(void garbage , (void));
+_PROTOTYPE(void setarea , (char *cp , int a ));
+_PROTOTYPE(int getarea , (char *cp ));
+_PROTOTYPE(void freearea , (int a ));
+_PROTOTYPE(void freecell , (char *cp ));
+
+Extern	int	areanum;	/* current allocation area */
+
+#define	NEW(type) (type *)getcell(sizeof(type))
+#define	DELETE(obj)	freecell((char *)obj)
Index: /trunk/minix/commands/sh/sh1.c
===================================================================
--- /trunk/minix/commands/sh/sh1.c	(revision 9)
+++ /trunk/minix/commands/sh/sh1.c	(revision 9)
@@ -0,0 +1,952 @@
+#define Extern extern
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#include <setjmp.h>
+#include "sh.h"
+/* -------- sh.c -------- */
+/*
+ * shell
+ */
+
+/* #include "sh.h" */
+
+int	intr;
+int	inparse;
+char	flags['z'-'a'+1];
+char	*flag = flags-'a';
+char	*elinep = line+sizeof(line)-5;
+char	*null	= "";
+int	heedint =1;
+struct	env	e ={line, iostack, iostack-1,
+		    (xint *)NULL, FDBASE, (struct env *)NULL};
+
+extern	char	**environ;	/* environment pointer */
+
+/*
+ * default shell, search rules
+ */
+char	shellname[] = "/bin/sh";
+char	search[] = ":/bin:/usr/bin";
+
+_PROTOTYPE(void (*qflag), (int)) = SIG_IGN;
+
+_PROTOTYPE(int main, (int argc, char **argv ));
+_PROTOTYPE(int newfile, (char *s ));
+_PROTOTYPE(static char *findeq, (char *cp ));
+_PROTOTYPE(static char *cclass, (char *p, int sub ));
+_PROTOTYPE(void initarea, (void));
+
+int main(argc, argv)
+int argc;
+register char **argv;
+{
+	register int f;
+	register char *s;
+	int cflag;
+	char *name, **ap;
+	int (*iof)();
+
+	initarea();
+	if ((ap = environ) != NULL) {
+		while (*ap)
+			assign(*ap++, !COPYV);
+		for (ap = environ; *ap;)
+			export(lookup(*ap++));
+	}
+	closeall();
+	areanum = 1;
+
+	shell = lookup("SHELL");
+	if (shell->value == null)
+		setval(shell, shellname);
+	export(shell);
+
+	homedir = lookup("HOME");
+	if (homedir->value == null)
+		setval(homedir, "/");
+	export(homedir);
+
+	setval(lookup("$"), itoa(getpid(), 5));
+
+	path = lookup("PATH");
+	if (path->value == null)
+		setval(path, search);
+	export(path);
+
+	ifs = lookup("IFS");
+	if (ifs->value == null)
+		setval(ifs, " \t\n");
+
+	prompt = lookup("PS1");
+	if (prompt->value == null)
+#ifndef UNIXSHELL
+		setval(prompt, "$ ");
+#else
+		setval(prompt, "% ");
+#endif
+
+	if (geteuid() == 0) {
+		setval(prompt, "# ");
+		prompt->status &= ~EXPORT;
+	}
+	cprompt = lookup("PS2");
+	if (cprompt->value == null)
+		setval(cprompt, "> ");
+
+	iof = filechar;
+	cflag = 0;
+	name = *argv++;
+	if (--argc >= 1) {
+		if(argv[0][0] == '-' && argv[0][1] != '\0') {
+			for (s = argv[0]+1; *s; s++)
+				switch (*s) {
+				case 'c':
+					prompt->status &= ~EXPORT;
+					cprompt->status &= ~EXPORT;
+					setval(prompt, "");
+					setval(cprompt, "");
+					cflag = 1;
+					if (--argc > 0)
+						PUSHIO(aword, *++argv, iof = nlchar);
+					break;
+	
+				case 'q':
+					qflag = SIG_DFL;
+					break;
+
+				case 's':
+					/* standard input */
+					break;
+
+				case 't':
+					prompt->status &= ~EXPORT;
+					setval(prompt, "");
+					iof = linechar;
+					break;
+	
+				case 'i':
+					talking++;
+				default:
+					if (*s>='a' && *s<='z')
+						flag[*s]++;
+				}
+		} else {
+			argv--;
+			argc++;
+		}
+		if (iof == filechar && --argc > 0) {
+			setval(prompt, "");
+			setval(cprompt, "");
+			prompt->status &= ~EXPORT;
+			cprompt->status &= ~EXPORT;
+			if (newfile(name = *++argv))
+				exit(1);
+		}
+	}
+	setdash();
+	if (e.iop < iostack) {
+		PUSHIO(afile, 0, iof);
+		if (isatty(0) && isatty(1) && !cflag)
+			talking++;
+	}
+	signal(SIGQUIT, qflag);
+	if (name && name[0] == '-') {
+		talking++;
+		if ((f = open(".profile", 0)) >= 0)
+			next(remap(f));
+		if ((f = open("/etc/profile", 0)) >= 0)
+			next(remap(f));
+	}
+	if (talking)
+		signal(SIGTERM, sig);
+	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+		signal(SIGINT, onintr);
+	dolv = argv;
+	dolc = argc;
+	dolv[0] = name;
+	if (dolc > 1)
+		for (ap = ++argv; --argc > 0;)
+			if (assign(*ap = *argv++, !COPYV))
+				dolc--;	/* keyword */
+			else
+				ap++;
+	setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
+
+	for (;;) {
+		if (talking && e.iop <= iostack)
+			prs(prompt->value);
+		onecommand();
+	}
+}
+
+void
+setdash()
+{
+	register char *cp, c;
+	char m['z'-'a'+1];
+
+	cp = m;
+	for (c='a'; c<='z'; c++)
+		if (flag[c])
+			*cp++ = c;
+	*cp = 0;
+	setval(lookup("-"), m);
+}
+
+int
+newfile(s)
+register char *s;
+{
+	register f;
+
+	if (strcmp(s, "-") != 0) {
+		f = open(s, 0);
+		if (f < 0) {
+			prs(s);
+			err(": cannot open");
+			return(1);
+		}
+	} else
+		f = 0;
+	next(remap(f));
+	return(0);
+}
+
+void
+onecommand()
+{
+	register i;
+	jmp_buf m1;
+
+	while (e.oenv)
+		quitenv();
+	areanum = 1;
+	freehere(areanum);
+	freearea(areanum);
+	garbage();
+	wdlist = 0;
+	iolist = 0;
+	e.errpt = 0;
+	e.linep = line;
+	yynerrs = 0;
+	multiline = 0;
+	inparse = 1;
+	intr = 0;
+	execflg = 0;
+	setjmp(failpt = m1);	/* Bruce Evans' fix */
+	if (setjmp(failpt = m1) || yyparse() || intr) {
+		while (e.oenv)
+			quitenv();
+		scraphere();
+		if (!talking && intr)
+			leave();
+		inparse = 0;
+		intr = 0;
+		return;
+	}
+	inparse = 0;
+	brklist = 0;
+	intr = 0;
+	execflg = 0;
+	if (!flag['n'])
+		execute(outtree, NOPIPE, NOPIPE, 0);
+	if (!talking && intr) {
+		execflg = 0;
+		leave();
+	}
+	if ((i = trapset) != 0) {
+		trapset = 0;
+		runtrap(i);
+	}
+}
+
+void
+fail()
+{
+	longjmp(failpt, 1);
+	/* NOTREACHED */
+}
+
+void
+leave()
+{
+	if (execflg)
+		fail();
+	scraphere();
+	freehere(1);
+	runtrap(0);
+	exit(exstat);
+	/* NOTREACHED */
+}
+
+void
+warn(s)
+register char *s;
+{
+	if(*s) {
+		prs(s);
+		exstat = -1;
+	}
+	prs("\n");
+	if (flag['e'])
+		leave();
+}
+
+void
+err(s)
+char *s;
+{
+	warn(s);
+	if (flag['n'])
+		return;
+	if (!talking)
+		leave();
+	if (e.errpt)
+		longjmp(e.errpt, 1);
+	closeall();
+	e.iop = e.iobase = iostack;
+}
+
+int
+newenv(f)
+int f;
+{
+	register struct env *ep;
+
+	if (f) {
+		quitenv();
+		return(1);
+	}
+	ep = (struct env *) space(sizeof(*ep));
+	if (ep == NULL) {
+		while (e.oenv)
+			quitenv();
+		fail();
+	}
+	*ep = e;
+	e.oenv = ep;
+	e.errpt = errpt;
+	return(0);
+}
+
+void
+quitenv()
+{
+	register struct env *ep;
+	register fd;
+
+	if ((ep = e.oenv) != NULL) {
+		fd = e.iofd;
+		e = *ep;
+		/* should close `'d files */
+		DELETE(ep);
+		while (--fd >= e.iofd)
+			close(fd);
+	}
+}
+
+/*
+ * Is any character from s1 in s2?
+ */
+int
+anys(s1, s2)
+register char *s1, *s2;
+{
+	while (*s1)
+		if (any(*s1++, s2))
+			return(1);
+	return(0);
+}
+
+/*
+ * Is character c in s?
+ */
+int
+any(c, s)
+register int c;
+register char *s;
+{
+	while (*s)
+		if (*s++ == c)
+			return(1);
+	return(0);
+}
+
+char *
+putn(n)
+register int n;
+{
+	return(itoa(n, -1));
+}
+
+char *
+itoa(u, n)
+register unsigned u;
+int n;
+{
+	register char *cp;
+	static char s[20];
+	int m;
+
+	m = 0;
+	if (n < 0 && (int) u < 0) {
+		m++;
+		u = -u;
+	}
+	cp = s+sizeof(s);
+	*--cp = 0;
+	do {
+		*--cp = u%10 + '0';
+		u /= 10;
+	} while (--n > 0 || u);
+	if (m)
+		*--cp = '-';
+	return(cp);
+}
+
+void
+next(f)
+int f;
+{
+	PUSHIO(afile, f, filechar);
+}
+
+void
+onintr(s)
+int s;				/* ANSI C requires a parameter */
+{
+	signal(SIGINT, onintr);
+	intr = 1;
+	if (talking) {
+		if (inparse) {
+			prs("\n");
+			fail();
+		}
+	}
+	else if (heedint) {
+		execflg = 0;
+		leave();
+	}
+}
+
+int
+letter(c)
+register c;
+{
+	return((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_');
+}
+
+int
+digit(c)
+register c;
+{
+	return(c >= '0' && c <= '9');
+}
+
+int
+letnum(c)
+register c;
+{
+	return(letter(c) || digit(c));
+}
+
+char *
+space(n)
+int n;
+{
+	register char *cp;
+
+	if ((cp = getcell(n)) == 0)
+		err("out of string space");
+	return(cp);
+}
+
+char *
+strsave(s, a)
+register char *s;
+int a;
+{
+	register char *cp, *xp;
+
+	if ((cp = space(strlen(s)+1)) != NULL) {
+		setarea((char *)cp, a);
+		for (xp = cp; (*xp++ = *s++) != '\0';)
+			;
+		return(cp);
+	}
+	return("");
+}
+
+void
+xfree(s)
+register char *s;
+{
+	DELETE(s);
+}
+
+/*
+ * trap handling
+ */
+void
+sig(i)
+register int i;
+{
+	trapset = i;
+	signal(i, sig);
+}
+
+void runtrap(i)
+int i;
+{
+	char *trapstr;
+
+	if ((trapstr = trap[i]) == NULL)
+		return;
+	if (i == 0)
+		trap[i] = 0;
+	RUN(aword, trapstr, nlchar);
+}
+
+/* -------- var.c -------- */
+/* #include "sh.h" */
+
+/*
+ * Find the given name in the dictionary
+ * and return its value.  If the name was
+ * not previously there, enter it now and
+ * return a null value.
+ */
+struct var *
+lookup(n)
+register char *n;
+{
+	register struct var *vp;
+	register char *cp;
+	register int c;
+	static struct var dummy;
+
+	if (digit(*n)) {
+		dummy.name = n;
+		for (c = 0; digit(*n) && c < 1000; n++)
+			c = c*10 + *n-'0';
+		dummy.status = RONLY;
+		dummy.value = c <= dolc? dolv[c]: null;
+		return(&dummy);
+	}
+	for (vp = vlist; vp; vp = vp->next)
+		if (eqname(vp->name, n))
+			return(vp);
+	cp = findeq(n);
+	vp = (struct var *)space(sizeof(*vp));
+	if (vp == 0 || (vp->name = space((int)(cp-n)+2)) == 0) {
+		dummy.name = dummy.value = "";
+		return(&dummy);
+	}
+	for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++)
+		;
+	if (*cp == 0)
+		*cp = '=';
+	*++cp = 0;
+	setarea((char *)vp, 0);
+	setarea((char *)vp->name, 0);
+	vp->value = null;
+	vp->next = vlist;
+	vp->status = GETCELL;
+	vlist = vp;
+	return(vp);
+}
+
+/*
+ * give variable at `vp' the value `val'.
+ */
+void
+setval(vp, val)
+struct var *vp;
+char *val;
+{
+	nameval(vp, val, (char *)NULL);
+}
+
+/*
+ * if name is not NULL, it must be
+ * a prefix of the space `val',
+ * and end with `='.
+ * this is all so that exporting
+ * values is reasonably painless.
+ */
+void
+nameval(vp, val, name)
+register struct var *vp;
+char *val, *name;
+{
+	register char *cp, *xp;
+	char *nv;
+	int fl;
+
+	if (vp->status & RONLY) {
+		for (xp = vp->name; *xp && *xp != '=';)
+			putc(*xp++);
+		err(" is read-only");
+		return;
+	}
+	fl = 0;
+	if (name == NULL) {
+		xp = space(strlen(vp->name)+strlen(val)+2);
+		if (xp == 0)
+			return;
+		/* make string:  name=value */
+		setarea((char *)xp, 0);
+		name = xp;
+		for (cp = vp->name; (*xp = *cp++) && *xp!='='; xp++)
+			;
+		if (*xp++ == 0)
+			xp[-1] = '=';
+		nv = xp;
+		for (cp = val; (*xp++ = *cp++) != '\0';)
+			;
+		val = nv;
+		fl = GETCELL;
+	}
+	if (vp->status & GETCELL)
+		xfree(vp->name);	/* form new string `name=value' */
+	vp->name = name;
+	vp->value = val;
+	vp->status |= fl;
+}
+
+void
+export(vp)
+struct var *vp;
+{
+	vp->status |= EXPORT;
+}
+
+void
+ronly(vp)
+struct var *vp;
+{
+	if (letter(vp->name[0]))	/* not an internal symbol ($# etc) */
+		vp->status |= RONLY;
+}
+
+int
+isassign(s)
+register char *s;
+{
+	if (!letter((int)*s))
+		return(0);
+	for (; *s != '='; s++)
+		if (*s == 0 || !letnum(*s))
+			return(0);
+	return(1);
+}
+
+int
+assign(s, cf)
+register char *s;
+int cf;
+{
+	register char *cp;
+	struct var *vp;
+
+	if (!letter(*s))
+		return(0);
+	for (cp = s; *cp != '='; cp++)
+		if (*cp == 0 || !letnum(*cp))
+			return(0);
+	vp = lookup(s);
+	nameval(vp, ++cp, cf == COPYV? (char *)NULL: s);
+	if (cf != COPYV)
+		vp->status &= ~GETCELL;
+	return(1);
+}
+
+int
+checkname(cp)
+register char *cp;
+{
+	if (!letter(*cp++))
+		return(0);
+	while (*cp)
+		if (!letnum(*cp++))
+			return(0);
+	return(1);
+}
+
+void
+putvlist(f, out)
+register int f, out;
+{
+	register struct var *vp;
+
+	for (vp = vlist; vp; vp = vp->next)
+		if (vp->status & f && letter(*vp->name)) {
+			if (vp->status & EXPORT)
+				write(out, "export ", 7);
+			if (vp->status & RONLY)
+				write(out, "readonly ", 9);
+			write(out, vp->name, (int)(findeq(vp->name) - vp->name));
+			write(out, "\n", 1);
+		}
+}
+
+int
+eqname(n1, n2)
+register char *n1, *n2;
+{
+	for (; *n1 != '=' && *n1 != 0; n1++)
+		if (*n2++ != *n1)
+			return(0);
+	return(*n2 == 0 || *n2 == '=');
+}
+
+static char *
+findeq(cp)
+register char *cp;
+{
+	while (*cp != '\0' && *cp != '=')
+		cp++;
+	return(cp);
+}
+
+/* -------- gmatch.c -------- */
+/*
+ * int gmatch(string, pattern)
+ * char *string, *pattern;
+ *
+ * Match a pattern as in sh(1).
+ */
+
+#define	CMASK	0377
+#define	QUOTE	0200
+#define	QMASK	(CMASK&~QUOTE)
+#define	NOT	'!'	/* might use ^ */
+
+int
+gmatch(s, p)
+register char *s, *p;
+{
+	register int sc, pc;
+
+	if (s == NULL || p == NULL)
+		return(0);
+	while ((pc = *p++ & CMASK) != '\0') {
+		sc = *s++ & QMASK;
+		switch (pc) {
+		case '[':
+			if ((p = cclass(p, sc)) == NULL)
+				return(0);
+			break;
+
+		case '?':
+			if (sc == 0)
+				return(0);
+			break;
+
+		case '*':
+			s--;
+			do {
+				if (*p == '\0' || gmatch(s, p))
+					return(1);
+			} while (*s++ != '\0');
+			return(0);
+
+		default:
+			if (sc != (pc&~QUOTE))
+				return(0);
+		}
+	}
+	return(*s == 0);
+}
+
+static char *
+cclass(p, sub)
+register char *p;
+register int sub;
+{
+	register int c, d, not, found;
+
+	if ((not = *p == NOT) != 0)
+		p++;
+	found = not;
+	do {
+		if (*p == '\0')
+			return((char *)NULL);
+		c = *p & CMASK;
+		if (p[1] == '-' && p[2] != ']') {
+			d = p[2] & CMASK;
+			p++;
+		} else
+			d = c;
+		if (c == sub || (c <= sub && sub <= d))
+			found = !not;
+	} while (*++p != ']');
+	return(found? p+1: (char *)NULL);
+}
+
+/* -------- area.c -------- */
+#define	REGSIZE		sizeof(struct region)
+#define GROWBY		256
+#undef	SHRINKBY	64
+#define FREE 32767
+#define BUSY 0
+#define	ALIGN (sizeof(int)-1)
+
+/* #include "area.h" */
+
+struct region {
+	struct	region *next;
+	int	area;
+};
+
+/*
+ * All memory between (char *)areabot and (char *)(areatop+1) is
+ * exclusively administered by the area management routines.
+ * It is assumed that sbrk() and brk() manipulate the high end.
+ */
+static	struct region *areabot;		/* bottom of area */
+static	struct region *areatop;		/* top of area */
+static	struct region *areanxt;		/* starting point of scan */
+
+void
+initarea()
+{
+	while ((int)sbrk(0) & ALIGN)
+		sbrk(1);
+	areabot = (struct region *)sbrk(REGSIZE);
+	areabot->next = areabot;
+	areabot->area = BUSY;
+	areatop = areabot;
+	areanxt = areabot;
+}
+
+char *
+getcell(nbytes)
+unsigned nbytes;
+{
+	register int nregio;
+	register struct region *p, *q;
+	register i;
+
+	if (nbytes == 0)
+		abort();	/* silly and defeats the algorithm */
+	/*
+	 * round upwards and add administration area
+	 */
+	nregio = (nbytes+(REGSIZE-1))/REGSIZE + 1;
+	for (p = areanxt;;) {
+		if (p->area > areanum) {
+			/*
+			 * merge free cells
+			 */
+			while ((q = p->next)->area > areanum && q != areanxt)
+				p->next = q->next;
+			/*
+			 * exit loop if cell big enough
+			 */
+			if (q >= p + nregio)
+				goto found;
+		}
+		p = p->next;
+		if (p == areanxt)
+			break;
+	}
+	i = nregio >= GROWBY ? nregio : GROWBY;
+	p = (struct region *)sbrk(i * REGSIZE);
+	if (p == (struct region *)-1)
+		return((char *)NULL);
+	p--;
+	if (p != areatop)
+		abort();	/* allocated areas are contiguous */
+	q = p + i;
+	p->next = q;
+	p->area = FREE;
+	q->next = areabot;
+	q->area = BUSY;
+	areatop = q;
+found:
+	/*
+	 * we found a FREE area big enough, pointed to by 'p', and up to 'q'
+	 */
+	areanxt = p + nregio;
+	if (areanxt < q) {
+		/*
+		 * split into requested area and rest
+		 */
+		if (areanxt+1 > q)
+			abort();	/* insufficient space left for admin */
+		areanxt->next = q;
+		areanxt->area = FREE;
+		p->next = areanxt;
+	}
+	p->area = areanum;
+	return((char *)(p+1));
+}
+
+void
+freecell(cp)
+char *cp;
+{
+	register struct region *p;
+
+	if ((p = (struct region *)cp) != NULL) {
+		p--;
+		if (p < areanxt)
+			areanxt = p;
+		p->area = FREE;
+	}
+}
+
+void
+freearea(a)
+register int a;
+{
+	register struct region *p, *top;
+
+	top = areatop;
+	for (p = areabot; p != top; p = p->next)
+		if (p->area >= a)
+			p->area = FREE;
+}
+
+void
+setarea(cp,a)
+char *cp;
+int a;
+{
+	register struct region *p;
+
+	if ((p = (struct region *)cp) != NULL)
+		(p-1)->area = a;
+}
+
+int
+getarea(cp)
+char *cp;
+{
+	return ((struct region*)cp-1)->area;
+}
+
+void
+garbage()
+{
+	register struct region *p, *q, *top;
+
+	top = areatop;
+	for (p = areabot; p != top; p = p->next) {
+		if (p->area > areanum) {
+			while ((q = p->next)->area > areanum)
+				p->next = q->next;
+			areanxt = p;
+		}
+	}
+#ifdef SHRINKBY
+	if (areatop >= q + SHRINKBY && q->area > areanum) {
+		brk((char *)(q+1));
+		q->next = areabot;
+		q->area = BUSY;
+		areatop = q;
+	}
+#endif
+}
Index: /trunk/minix/commands/sh/sh2.c
===================================================================
--- /trunk/minix/commands/sh/sh2.c	(revision 9)
+++ /trunk/minix/commands/sh/sh2.c	(revision 9)
@@ -0,0 +1,800 @@
+#define Extern extern
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#include <setjmp.h>
+#include "sh.h"
+
+/* -------- csyn.c -------- */
+/*
+ * shell: syntax (C version)
+ */
+
+typedef union {
+	char	*cp;
+	char	**wp;
+	int	i;
+	struct	op *o;
+} YYSTYPE;
+#define	WORD	256
+#define	LOGAND	257
+#define	LOGOR	258
+#define	BREAK	259
+#define	IF	260
+#define	THEN	261
+#define	ELSE	262
+#define	ELIF	263
+#define	FI	264
+#define	CASE	265
+#define	ESAC	266
+#define	FOR	267
+#define	WHILE	268
+#define	UNTIL	269
+#define	DO	270
+#define	DONE	271
+#define	IN	272
+#define	YYERRCODE 300
+
+/* flags to yylex */
+#define	CONTIN	01	/* skip new lines to complete command */
+
+/* #include "sh.h" */
+#define	SYNTAXERR	zzerr()
+static	int	startl;
+static	int	peeksym;
+static	int	nlseen;
+static	int	iounit = IODEFAULT;
+
+static	YYSTYPE	yylval;
+
+_PROTOTYPE(static struct op *pipeline, (int cf ));
+_PROTOTYPE(static struct op *andor, (void));
+_PROTOTYPE(static struct op *c_list, (void));
+_PROTOTYPE(static int synio, (int cf ));
+_PROTOTYPE(static void musthave, (int c, int cf ));
+_PROTOTYPE(static struct op *simple, (void));
+_PROTOTYPE(static struct op *nested, (int type, int mark ));
+_PROTOTYPE(static struct op *command, (int cf ));
+_PROTOTYPE(static struct op *dogroup, (int onlydone ));
+_PROTOTYPE(static struct op *thenpart, (void));
+_PROTOTYPE(static struct op *elsepart, (void));
+_PROTOTYPE(static struct op *caselist, (void));
+_PROTOTYPE(static struct op *casepart, (void));
+_PROTOTYPE(static char **pattern, (void));
+_PROTOTYPE(static char **wordlist, (void));
+_PROTOTYPE(static struct op *list, (struct op *t1, struct op *t2 ));
+_PROTOTYPE(static struct op *block, (int type, struct op *t1, struct op *t2, char **wp ));
+_PROTOTYPE(static struct op *newtp, (void));
+_PROTOTYPE(static struct op *namelist, (struct op *t ));
+_PROTOTYPE(static char **copyw, (void));
+_PROTOTYPE(static void word, (char *cp ));
+_PROTOTYPE(static struct ioword **copyio, (void));
+_PROTOTYPE(static struct ioword *io, (int u, int f, char *cp ));
+_PROTOTYPE(static void zzerr, (void));
+_PROTOTYPE(void yyerror, (char *s ));
+_PROTOTYPE(static int yylex, (int cf ));
+_PROTOTYPE(int collect, (int c, int c1 ));
+_PROTOTYPE(int dual, (int c ));
+_PROTOTYPE(static void diag, (int ec ));
+_PROTOTYPE(static char *tree, (unsigned size ));
+_PROTOTYPE(void printf, (char *s ));
+
+int
+yyparse()
+{
+	startl  = 1;
+	peeksym = 0;
+	yynerrs = 0;
+	outtree = c_list();
+	musthave('\n', 0);
+	return(yynerrs!=0);
+}
+
+static struct op *
+pipeline(cf)
+int cf;
+{
+	register struct op *t, *p;
+	register int c;
+
+	t = command(cf);
+	if (t != NULL) {
+		while ((c = yylex(0)) == '|') {
+			if ((p = command(CONTIN)) == NULL)
+				SYNTAXERR;
+			if (t->type != TPAREN && t->type != TCOM) {
+				/* shell statement */
+				t = block(TPAREN, t, NOBLOCK, NOWORDS);
+			}
+			t = block(TPIPE, t, p, NOWORDS);
+		}
+		peeksym = c;
+	}
+	return(t);
+}
+
+static struct op *
+andor()
+{
+	register struct op *t, *p;
+	register int c;
+
+	t = pipeline(0);
+	if (t != NULL) {
+		while ((c = yylex(0)) == LOGAND || c == LOGOR) {
+			if ((p = pipeline(CONTIN)) == NULL)
+				SYNTAXERR;
+			t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS);
+		}
+		peeksym = c;
+	}
+	return(t);
+}
+
+static struct op *
+c_list()
+{
+	register struct op *t, *p;
+	register int c;
+
+	t = andor();
+	if (t != NULL) {
+		if((peeksym = yylex(0)) == '&')
+			t = block(TASYNC, t, NOBLOCK, NOWORDS);
+		while ((c = yylex(0)) == ';' || c == '&' || (multiline && c == '\n')) {
+			if ((p = andor()) == NULL)
+				return(t);
+			if((peeksym = yylex(0)) == '&')
+				p = block(TASYNC, p, NOBLOCK, NOWORDS);
+			t = list(t, p);
+		}
+		peeksym = c;
+	}
+	return(t);
+}
+
+
+static int
+synio(cf)
+int cf;
+{
+	register struct ioword *iop;
+	register int i;
+	register int c;
+
+	if ((c = yylex(cf)) != '<' && c != '>') {
+		peeksym = c;
+		return(0);
+	}
+	i = yylval.i;
+	musthave(WORD, 0);
+	iop = io(iounit, i, yylval.cp);
+	iounit = IODEFAULT;
+	if (i & IOHERE)
+		markhere(yylval.cp, iop);
+	return(1);
+}
+
+static void
+musthave(c, cf)
+int c, cf;
+{
+	if ((peeksym = yylex(cf)) != c)
+		SYNTAXERR;
+	peeksym = 0;
+}
+
+static struct op *
+simple()
+{
+	register struct op *t;
+
+	t = NULL;
+	for (;;) {
+		switch (peeksym = yylex(0)) {
+		case '<':
+		case '>':
+			(void) synio(0);
+			break;
+
+		case WORD:
+			if (t == NULL) {
+				t = newtp();
+				t->type = TCOM;
+			}
+			peeksym = 0;
+			word(yylval.cp);
+			break;
+
+		default:
+			return(t);
+		}
+	}
+}
+
+static struct op *
+nested(type, mark)
+int type, mark;
+{
+	register struct op *t;
+
+	multiline++;
+	t = c_list();
+	musthave(mark, 0);
+	multiline--;
+	return(block(type, t, NOBLOCK, NOWORDS));
+}
+
+static struct op *
+command(cf)
+int cf;
+{
+	register struct op *t;
+	struct wdblock *iosave;
+	register int c;
+
+	iosave = iolist;
+	iolist = NULL;
+	if (multiline)
+		cf |= CONTIN;
+	while (synio(cf))
+		cf = 0;
+	switch (c = yylex(cf)) {
+	default:
+		peeksym = c;
+		if ((t = simple()) == NULL) {
+			if (iolist == NULL)
+				return((struct op *)NULL);
+			t = newtp();
+			t->type = TCOM;
+		}
+		break;
+
+	case '(':
+		t = nested(TPAREN, ')');
+		break;
+
+	case '{':
+		t = nested(TBRACE, '}');
+		break;
+
+	case FOR:
+		t = newtp();
+		t->type = TFOR;
+		musthave(WORD, 0);
+		startl = 1;
+		t->str = yylval.cp;
+		multiline++;
+		t->words = wordlist();
+		if ((c = yylex(0)) != '\n' && c != ';')
+			peeksym = c;
+		t->left = dogroup(0);
+		multiline--;
+		break;
+
+	case WHILE:
+	case UNTIL:
+		multiline++;
+		t = newtp();
+		t->type = c == WHILE? TWHILE: TUNTIL;
+		t->left = c_list();
+		t->right = dogroup(1);
+		t->words = NULL;
+		multiline--;
+		break;
+
+	case CASE:
+		t = newtp();
+		t->type = TCASE;
+		musthave(WORD, 0);
+		t->str = yylval.cp;
+		startl++;
+		multiline++;
+		musthave(IN, CONTIN);
+		startl++;
+		t->left = caselist();
+		musthave(ESAC, 0);
+		multiline--;
+		break;
+
+	case IF:
+		multiline++;
+		t = newtp();
+		t->type = TIF;
+		t->left = c_list();
+		t->right = thenpart();
+		musthave(FI, 0);
+		multiline--;
+		break;
+	}
+	while (synio(0))
+		;
+	t = namelist(t);
+	iolist = iosave;
+	return(t);
+}
+
+static struct op *
+dogroup(onlydone)
+int onlydone;
+{
+	register int c;
+	register struct op *list;
+
+	c = yylex(CONTIN);
+	if (c == DONE && onlydone)
+		return((struct op *)NULL);
+	if (c != DO)
+		SYNTAXERR;
+	list = c_list();
+	musthave(DONE, 0);
+	return(list);
+}
+
+static struct op *
+thenpart()
+{
+	register int c;
+	register struct op *t;
+
+	if ((c = yylex(0)) != THEN) {
+		peeksym = c;
+		return((struct op *)NULL);
+	}
+	t = newtp();
+	t->type = 0;
+	t->left = c_list();
+	if (t->left == NULL)
+		SYNTAXERR;
+	t->right = elsepart();
+	return(t);
+}
+
+static struct op *
+elsepart()
+{
+	register int c;
+	register struct op *t;
+
+	switch (c = yylex(0)) {
+	case ELSE:
+		if ((t = c_list()) == NULL)
+			SYNTAXERR;
+		return(t);
+
+	case ELIF:
+		t = newtp();
+		t->type = TELIF;
+		t->left = c_list();
+		t->right = thenpart();
+		return(t);
+
+	default:
+		peeksym = c;
+		return((struct op *)NULL);
+	}
+}
+
+static struct op *
+caselist()
+{
+	register struct op *t;
+
+	t = NULL;
+	while ((peeksym = yylex(CONTIN)) != ESAC)
+		t = list(t, casepart());
+	return(t);
+}
+
+static struct op *
+casepart()
+{
+	register struct op *t;
+
+	t = newtp();
+	t->type = TPAT;
+	t->words = pattern();
+	musthave(')', 0);
+	t->left = c_list();
+	if ((peeksym = yylex(CONTIN)) != ESAC)
+		musthave(BREAK, CONTIN);
+	return(t);
+}
+
+static char **
+pattern()
+{
+	register int c, cf;
+
+	cf = CONTIN;
+	do {
+		musthave(WORD, cf);
+		word(yylval.cp);
+		cf = 0;
+	} while ((c = yylex(0)) == '|');
+	peeksym = c;
+	word(NOWORD);
+	return(copyw());
+}
+
+static char **
+wordlist()
+{
+	register int c;
+
+	if ((c = yylex(0)) != IN) {
+		peeksym = c;
+		return((char **)NULL);
+	}
+	startl = 0;
+	while ((c = yylex(0)) == WORD)
+		word(yylval.cp);
+	word(NOWORD);
+	peeksym = c;
+	return(copyw());
+}
+
+/*
+ * supporting functions
+ */
+static struct op *
+list(t1, t2)
+register struct op *t1, *t2;
+{
+	if (t1 == NULL)
+		return(t2);
+	if (t2 == NULL)
+		return(t1);
+	return(block(TLIST, t1, t2, NOWORDS));
+}
+
+static struct op *
+block(type, t1, t2, wp)
+int type;
+struct op *t1, *t2;
+char **wp;
+{
+	register struct op *t;
+
+	t = newtp();
+	t->type = type;
+	t->left = t1;
+	t->right = t2;
+	t->words = wp;
+	return(t);
+}
+
+struct res {
+	char	*r_name;
+	int	r_val;
+} restab[] = {
+	"for",		FOR,
+	"case",		CASE,
+	"esac",		ESAC,
+	"while",	WHILE,
+	"do",		DO,
+	"done",		DONE,
+	"if",		IF,
+	"in",		IN,
+	"then",		THEN,
+	"else",		ELSE,
+	"elif",		ELIF,
+	"until",	UNTIL,
+	"fi",		FI,
+
+	";;",		BREAK,
+	"||",		LOGOR,
+	"&&",		LOGAND,
+	"{",		'{',
+	"}",		'}',
+
+	0,
+};
+
+int
+rlookup(n)
+register char *n;
+{
+	register struct res *rp;
+
+	for (rp = restab; rp->r_name; rp++)
+		if (strcmp(rp->r_name, n) == 0)
+			return(rp->r_val);
+	return(0);
+}
+
+static struct op *
+newtp()
+{
+	register struct op *t;
+
+	t = (struct op *)tree(sizeof(*t));
+	t->type = 0;
+	t->words = NULL;
+	t->ioact = NULL;
+	t->left = NULL;
+	t->right = NULL;
+	t->str = NULL;
+	return(t);
+}
+
+static struct op *
+namelist(t)
+register struct op *t;
+{
+	if (iolist) {
+		iolist = addword((char *)NULL, iolist);
+		t->ioact = copyio();
+	} else
+		t->ioact = NULL;
+	if (t->type != TCOM) {
+		if (t->type != TPAREN && t->ioact != NULL) {
+			t = block(TPAREN, t, NOBLOCK, NOWORDS);
+			t->ioact = t->left->ioact;
+			t->left->ioact = NULL;
+		}
+		return(t);
+	}
+	word(NOWORD);
+	t->words = copyw();
+	return(t);
+}
+
+static char **
+copyw()
+{
+	register char **wd;
+
+	wd = getwords(wdlist);
+	wdlist = 0;
+	return(wd);
+}
+
+static void
+word(cp)
+char *cp;
+{
+	wdlist = addword(cp, wdlist);
+}
+
+static struct ioword **
+copyio()
+{
+	register struct ioword **iop;
+
+	iop = (struct ioword **) getwords(iolist);
+	iolist = 0;
+	return(iop);
+}
+
+static struct ioword *
+io(u, f, cp)
+int u;
+int f;
+char *cp;
+{
+	register struct ioword *iop;
+
+	iop = (struct ioword *) tree(sizeof(*iop));
+	iop->io_unit = u;
+	iop->io_flag = f;
+	iop->io_name = cp;
+	iolist = addword((char *)iop, iolist);
+	return(iop);
+}
+
+static void
+zzerr()
+{
+	yyerror("syntax error");
+}
+
+void
+yyerror(s)
+char *s;
+{
+	yynerrs++;
+	if (talking && e.iop <= iostack) {
+		multiline = 0;
+		while (eofc() == 0 && yylex(0) != '\n')
+			;
+	}
+	err(s);
+	fail();
+}
+
+static int
+yylex(cf)
+int cf;
+{
+	register int c, c1;
+	int atstart;
+
+	if ((c = peeksym) > 0) {
+		peeksym = 0;
+		if (c == '\n')
+			startl = 1;
+		return(c);
+	}
+	nlseen = 0;
+	e.linep = line;
+	atstart = startl;
+	startl = 0;
+	yylval.i = 0;
+
+loop:
+	while ((c = getc(0)) == ' ' || c == '\t')
+		;
+	switch (c) {
+	default:
+		if (any(c, "0123456789")) {
+			unget(c1 = getc(0));
+			if (c1 == '<' || c1 == '>') {
+				iounit = c - '0';
+				goto loop;
+			}
+			*e.linep++ = c;
+			c = c1;
+		}
+		break;
+
+	case '#':
+		while ((c = getc(0)) != 0 && c != '\n')
+			;
+		unget(c);
+		goto loop;
+
+	case 0:
+		return(c);
+
+	case '$':
+		*e.linep++ = c;
+		if ((c = getc(0)) == '{') {
+			if ((c = collect(c, '}')) != '\0')
+				return(c);
+			goto pack;
+		}
+		break;
+
+	case '`':
+	case '\'':
+	case '"':
+		if ((c = collect(c, c)) != '\0')
+			return(c);
+		goto pack;
+
+	case '|':
+	case '&':
+	case ';':
+		if ((c1 = dual(c)) != '\0') {
+			startl = 1;
+			return(c1);
+		}
+		startl = 1;
+		return(c);
+	case '^':
+		startl = 1;
+		return('|');
+	case '>':
+	case '<':
+		diag(c);
+		return(c);
+
+	case '\n':
+		nlseen++;
+		gethere();
+		startl = 1;
+		if (multiline || cf & CONTIN) {
+			if (talking && e.iop <= iostack)
+				prs(cprompt->value);
+			if (cf & CONTIN)
+				goto loop;
+		}
+		return(c);
+
+	case '(':
+	case ')':
+		startl = 1;
+		return(c);
+	}
+
+	unget(c);
+
+pack:
+	while ((c = getc(0)) != 0 && !any(c, "`$ '\"\t;&<>()|^\n"))
+		if (e.linep >= elinep)
+			err("word too long");
+		else
+			*e.linep++ = c;
+	unget(c);
+	if(any(c, "\"'`$"))
+		goto loop;
+	*e.linep++ = '\0';
+	if (atstart && (c = rlookup(line))!=0) {
+		startl = 1;
+		return(c);
+	}
+	yylval.cp = strsave(line, areanum);
+	return(WORD);
+}
+
+int
+collect(c, c1)
+register c, c1;
+{
+	char s[2];
+
+	*e.linep++ = c;
+	while ((c = getc(c1)) != c1) {
+		if (c == 0) {
+			unget(c);
+			s[0] = c1;
+			s[1] = 0;
+			prs("no closing "); yyerror(s);
+			return(YYERRCODE);
+		}
+		if (talking && c == '\n' && e.iop <= iostack)
+			prs(cprompt->value);
+		*e.linep++ = c;
+	}
+	*e.linep++ = c;
+	return(0);
+}
+
+int
+dual(c)
+register c;
+{
+	char s[3];
+	register char *cp = s;
+
+	*cp++ = c;
+	*cp++ = getc(0);
+	*cp = 0;
+	if ((c = rlookup(s)) == 0)
+		unget(*--cp);
+	return(c);
+}
+
+static void
+diag(ec)
+register int ec;
+{
+	register int c;
+
+	c = getc(0);
+	if (c == '>' || c == '<') {
+		if (c != ec)
+			zzerr();
+		yylval.i = ec == '>'? IOWRITE|IOCAT: IOHERE;
+		c = getc(0);
+	} else
+		yylval.i = ec == '>'? IOWRITE: IOREAD;
+	if (c != '&' || yylval.i == IOHERE)
+		unget(c);
+	else
+		yylval.i |= IODUP;
+}
+
+static char *
+tree(size)
+unsigned size;
+{
+	register char *t;
+
+	if ((t = getcell(size)) == NULL) {
+		prs("command line too complicated\n");
+		fail();
+		/* NOTREACHED */
+	}
+	return(t);
+}
+
+/* VARARGS1 */
+/* ARGSUSED */
+void 
+printf(s)	/* yyparse calls it */
+char *s;
+{
+}
+
Index: /trunk/minix/commands/sh/sh3.c
===================================================================
--- /trunk/minix/commands/sh/sh3.c	(revision 9)
+++ /trunk/minix/commands/sh/sh3.c	(revision 9)
@@ -0,0 +1,1147 @@
+#define Extern extern
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <stddef.h>
+#include <time.h>
+#include <sys/times.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#undef NULL
+#include "sh.h"
+
+/* -------- exec.c -------- */
+/* #include "sh.h" */
+
+/*
+ * execute tree
+ */
+
+static	char	*signame[] = {
+	"Signal 0",
+	"Hangup",
+	(char *)NULL,	/* interrupt */
+	"Quit",
+	"Illegal instruction",
+	"Trace/BPT trap",
+	"Abort",
+	"EMT trap",
+	"Floating exception",
+	"Killed",
+	"Bus error",
+	"Memory fault",
+	"Bad system call",
+	(char *)NULL,	/* broken pipe */
+	"Alarm clock",
+	"Terminated",
+};
+#define	NSIGNAL (sizeof(signame)/sizeof(signame[0]))
+
+
+_PROTOTYPE(static int forkexec, (struct op *t, int *pin, int *pout, int act, char **wp, int *pforked ));
+_PROTOTYPE(static int parent, (void));
+_PROTOTYPE(int iosetup, (struct ioword *iop, int pipein, int pipeout ));
+_PROTOTYPE(static void echo, (char **wp ));
+_PROTOTYPE(static struct op **find1case, (struct op *t, char *w ));
+_PROTOTYPE(static struct op *findcase, (struct op *t, char *w ));
+_PROTOTYPE(static void brkset, (struct brkcon *bc ));
+_PROTOTYPE(int dolabel, (void));
+_PROTOTYPE(int dochdir, (struct op *t ));
+_PROTOTYPE(int doshift, (struct op *t ));
+_PROTOTYPE(int dologin, (struct op *t ));
+_PROTOTYPE(int doumask, (struct op *t ));
+_PROTOTYPE(int doexec, (struct op *t ));
+_PROTOTYPE(int dodot, (struct op *t ));
+_PROTOTYPE(int dowait, (struct op *t ));
+_PROTOTYPE(int doread, (struct op *t ));
+_PROTOTYPE(int doeval, (struct op *t ));
+_PROTOTYPE(int dotrap, (struct op *t ));
+_PROTOTYPE(int getsig, (char *s ));
+_PROTOTYPE(void setsig, (int n, void (*f)()));
+_PROTOTYPE(int getn, (char *as ));
+_PROTOTYPE(int dobreak, (struct op *t ));
+_PROTOTYPE(int docontinue, (struct op *t ));
+_PROTOTYPE(static int brkcontin, (char *cp, int val ));
+_PROTOTYPE(int doexit, (struct op *t ));
+_PROTOTYPE(int doexport, (struct op *t ));
+_PROTOTYPE(int doreadonly, (struct op *t ));
+_PROTOTYPE(static void rdexp, (char **wp, void (*f)(), int key));
+_PROTOTYPE(static void badid, (char *s ));
+_PROTOTYPE(int doset, (struct op *t ));
+_PROTOTYPE(void varput, (char *s, int out ));
+_PROTOTYPE(int dotimes, (void));
+
+int
+execute(t, pin, pout, act)
+register struct op *t;
+int *pin, *pout;
+int act;
+{
+	register struct op *t1;
+	int i, pv[2], rv, child, a;
+	char *cp, **wp, **wp2;
+	struct var *vp;
+	struct brkcon bc;
+
+	if (t == NULL)
+		return(0);
+	rv = 0;
+	a = areanum++;
+	wp = (wp2 = t->words) != NULL
+	     ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY)
+	     : NULL;
+
+	switch(t->type) {
+	case TPAREN:
+	case TCOM:
+		rv = forkexec(t, pin, pout, act, wp, &child);
+		if (child) {
+			exstat = rv;
+			leave();
+		}
+		break;
+
+	case TPIPE:
+		if ((rv = openpipe(pv)) < 0)
+			break;
+		pv[0] = remap(pv[0]);
+		pv[1] = remap(pv[1]);
+		(void) execute(t->left, pin, pv, 0);
+		rv = execute(t->right, pv, pout, 0);
+		break;
+
+	case TLIST:
+		(void) execute(t->left, pin, pout, 0);
+		rv = execute(t->right, pin, pout, 0);
+		break;
+
+	case TASYNC:
+		i = parent();
+		if (i != 0) {
+			if (i != -1) {
+				setval(lookup("!"), putn(i));
+				if (pin != NULL)
+					closepipe(pin);
+				if (talking) {
+					prs(putn(i));
+					prs("\n");
+				}
+			} else
+				rv = -1;
+			setstatus(rv);
+		} else {
+			signal(SIGINT, SIG_IGN);
+			signal(SIGQUIT, SIG_IGN);
+			if (talking)
+				signal(SIGTERM, SIG_DFL);
+			talking = 0;
+			if (pin == NULL) {
+				close(0);
+				open("/dev/null", 0);
+			}
+			exit(execute(t->left, pin, pout, FEXEC));
+		}
+		break;
+
+	case TOR:
+	case TAND:
+		rv = execute(t->left, pin, pout, 0);
+		if ((t1 = t->right)!=NULL && (rv == 0) == (t->type == TAND))
+			rv = execute(t1, pin, pout, 0);
+		break;
+
+	case TFOR:
+		if (wp == NULL) {
+			wp = dolv+1;
+			if ((i = dolc) < 0)
+				i = 0;
+		} else {
+			i = -1;
+			while (*wp++ != NULL)
+				;			
+		}
+		vp = lookup(t->str);
+		while (setjmp(bc.brkpt))
+			if (isbreak)
+				goto broken;
+		brkset(&bc);
+		for (t1 = t->left; i-- && *wp != NULL;) {
+			setval(vp, *wp++);
+			rv = execute(t1, pin, pout, 0);
+		}
+		brklist = brklist->nextlev;
+		break;
+
+	case TWHILE:
+	case TUNTIL:
+		while (setjmp(bc.brkpt))
+			if (isbreak)
+				goto broken;
+		brkset(&bc);
+		t1 = t->left;
+		while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))
+			rv = execute(t->right, pin, pout, 0);
+		brklist = brklist->nextlev;
+		break;
+
+	case TIF:
+	case TELIF:
+	 	if (t->right != NULL) {
+		rv = !execute(t->left, pin, pout, 0) ?
+			execute(t->right->left, pin, pout, 0):
+			execute(t->right->right, pin, pout, 0);
+		}
+		break;
+
+	case TCASE:
+		if ((cp = evalstr(t->str, DOSUB|DOTRIM)) == 0)
+			cp = "";
+		if ((t1 = findcase(t->left, cp)) != NULL)
+			rv = execute(t1, pin, pout, 0);
+		break;
+
+	case TBRACE:
+/*
+		if (iopp = t->ioact)
+			while (*iopp)
+				if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {
+					rv = -1;
+					break;
+				}
+*/
+		if (rv >= 0 && (t1 = t->left))
+			rv = execute(t1, pin, pout, 0);
+		break;
+	}
+
+broken:
+	t->words = wp2;
+	isbreak = 0;
+	freehere(areanum);
+	freearea(areanum);
+	areanum = a;
+	if (talking && intr) {
+		closeall();
+		fail();
+	}
+	if ((i = trapset) != 0) {
+		trapset = 0;
+		runtrap(i);
+	}
+	return(rv);
+}
+
+static int
+forkexec(t, pin, pout, act, wp, pforked)
+register struct op *t;
+int *pin, *pout;
+int act;
+char **wp;
+int *pforked;
+{
+	int i, rv, (*shcom)();
+	register int f;
+	char *cp;
+	struct ioword **iopp;
+	int resetsig;
+	char **owp;
+
+	owp = wp;
+	resetsig = 0;
+	*pforked = 0;
+	shcom = NULL;
+	rv = -1;	/* system-detected error */
+	if (t->type == TCOM) {
+		while ((cp = *wp++) != NULL)
+			;
+		cp = *wp;
+
+		/* strip all initial assignments */
+		/* not correct wrt PATH=yyy command  etc */
+		if (flag['x'])
+			echo (cp ? wp: owp);
+		if (cp == NULL && t->ioact == NULL) {
+			while ((cp = *owp++) != NULL && assign(cp, COPYV))
+				;
+			return(setstatus(0));
+		}
+		else if (cp != NULL)
+			shcom = inbuilt(cp);
+	}
+	t->words = wp;
+	f = act;
+	if (shcom == NULL && (f & FEXEC) == 0) {
+		i = parent();
+		if (i != 0) {
+			if (i == -1)
+				return(rv);
+			if (pin != NULL)
+				closepipe(pin);
+			return(pout==NULL? setstatus(waitfor(i,0)): 0);
+		}
+		if (talking) {
+			signal(SIGINT, SIG_IGN);
+			signal(SIGQUIT, SIG_IGN);
+			resetsig = 1;
+		}
+		talking = 0;
+		intr = 0;
+		(*pforked)++;
+		brklist = 0;
+		execflg = 0;
+	}
+	if (owp != NULL)
+		while ((cp = *owp++) != NULL && assign(cp, COPYV))
+			if (shcom == NULL)
+				export(lookup(cp));
+#ifdef COMPIPE
+	if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) {
+		err("piping to/from shell builtins not yet done");
+		return(-1);
+	}
+#endif
+	if (pin != NULL) {
+		dup2(pin[0], 0);
+		closepipe(pin);
+	}
+	if (pout != NULL) {
+		dup2(pout[1], 1);
+		closepipe(pout);
+	}
+	if ((iopp = t->ioact) != NULL) {
+		if (shcom != NULL && shcom != doexec) {
+			prs(cp);
+			err(": cannot redirect shell command");
+			return(-1);
+		}
+		while (*iopp)
+			if (iosetup(*iopp++, pin!=NULL, pout!=NULL))
+				return(rv);
+	}
+	if (shcom)
+		return(setstatus((*shcom)(t)));
+	/* should use FIOCEXCL */
+	for (i=FDBASE; i<NOFILE; i++)
+		close(i);
+	if (resetsig) {
+		signal(SIGINT, SIG_DFL);
+		signal(SIGQUIT, SIG_DFL);
+	}
+	if (t->type == TPAREN)
+		exit(execute(t->left, NOPIPE, NOPIPE, FEXEC));
+	if (wp[0] == NULL)
+		exit(0);
+	cp = rexecve(wp[0], wp, makenv());
+	prs(wp[0]); prs(": "); warn(cp);
+	if (!execflg)
+		trap[0] = NULL;
+	leave();
+	/* NOTREACHED */
+}
+
+/*
+ * common actions when creating a new child
+ */
+static int
+parent()
+{
+	register int i;
+
+	i = fork();
+	if (i != 0) {
+		if (i == -1)
+			warn("try again");
+	}
+	return(i);
+}
+
+/*
+ * 0< 1> are ignored as required
+ * within pipelines.
+ */
+int
+iosetup(iop, pipein, pipeout)
+register struct ioword *iop;
+int pipein, pipeout;
+{
+	register u;
+	char *cp, *msg;
+
+	if (iop->io_unit == IODEFAULT)	/* take default */
+		iop->io_unit = iop->io_flag&(IOREAD|IOHERE)? 0: 1;
+	if (pipein && iop->io_unit == 0)
+		return(0);
+	if (pipeout && iop->io_unit == 1)
+		return(0);
+	msg = iop->io_flag&(IOREAD|IOHERE)? "open": "create";
+	if ((iop->io_flag & IOHERE) == 0) {
+		cp = iop->io_name;
+		if ((cp = evalstr(cp, DOSUB|DOTRIM)) == NULL)
+			return(1);
+	}
+	if (iop->io_flag & IODUP) {
+		if (cp[1] || (!digit(*cp) && *cp != '-')) {
+			prs(cp);
+			err(": illegal >& argument");
+			return(1);
+		}
+		if (*cp == '-')
+			iop->io_flag = IOCLOSE;
+		iop->io_flag &= ~(IOREAD|IOWRITE);
+	}
+	switch (iop->io_flag) {
+	case IOREAD:
+		u = open(cp, 0);
+		break;
+
+	case IOHERE:
+	case IOHERE|IOXHERE:
+		u = herein(iop->io_name, iop->io_flag&IOXHERE);
+		cp = "here file ";
+		break;
+
+	case IOWRITE|IOCAT:
+		if ((u = open(cp, 1)) >= 0) {
+			lseek(u, (long)0, 2);
+			break;
+		}
+	case IOWRITE:
+		u = creat(cp, 0666);
+		break;
+
+	case IODUP:
+		u = dup2(*cp-'0', iop->io_unit);
+		break;
+
+	case IOCLOSE:
+		close(iop->io_unit);
+		return(0);
+	}
+	if (u < 0) {
+		int e=errno;
+		prs(cp);
+                if (iop->io_flag&IOHERE) prs(iop->io_name);
+		prs(": cannot ");
+	        prs(msg);
+	        prs(" (");
+	        prs(strerror(e));
+		warn(")");
+		return(1);
+	} else {
+		if (u != iop->io_unit) {
+			dup2(u, iop->io_unit);
+			close(u);
+		}
+	}
+	return(0);
+}
+
+static void
+echo(wp)
+register char **wp;
+{
+	register i;
+
+	prs("+");
+	for (i=0; wp[i]; i++) {
+		if (i)
+			prs(" ");
+		prs(wp[i]);
+	}
+	prs("\n");
+}
+
+static struct op **
+find1case(t, w)
+struct op *t;
+char *w;
+{
+	register struct op *t1;
+	struct op **tp;
+	register char **wp, *cp;
+
+	if (t == NULL)
+		return((struct op **)NULL);
+	if (t->type == TLIST) {
+		if ((tp = find1case(t->left, w)) != NULL)
+			return(tp);
+		t1 = t->right;	/* TPAT */
+	} else
+		t1 = t;
+	for (wp = t1->words; *wp;)
+		if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp))
+			return(&t1->left);
+	return((struct op **)NULL);
+}
+
+static struct op *
+findcase(t, w)
+struct op *t;
+char *w;
+{
+	register struct op **tp;
+
+	return((tp = find1case(t, w)) != NULL? *tp: (struct op *)NULL);
+}
+
+/*
+ * Enter a new loop level (marked for break/continue).
+ */
+static void
+brkset(bc)
+struct brkcon *bc;
+{
+	bc->nextlev = brklist;
+	brklist = bc;
+}
+
+/*
+ * Wait for the last process created.
+ * Print a message for each process found
+ * that was killed by a signal.
+ * Ignore interrupt signals while waiting
+ * unless `canintr' is true.
+ */
+int
+waitfor(lastpid, canintr)
+register int lastpid;
+int canintr;
+{
+	register int pid, rv;
+	int s;
+	int oheedint = heedint;
+
+	heedint = 0;
+	rv = 0;
+	do {
+		pid = wait(&s);
+		if (pid == -1) {
+			if (errno != EINTR || canintr)
+				break;
+		} else {
+			if ((rv = WAITSIG(s)) != 0) {
+				if (rv < NSIGNAL) {
+					if (signame[rv] != NULL) {
+						if (pid != lastpid) {
+							prn(pid);
+							prs(": ");
+						}
+						prs(signame[rv]);
+					}
+				} else {
+					if (pid != lastpid) {
+						prn(pid);
+						prs(": ");
+					}
+					prs("Signal "); prn(rv); prs(" ");
+				}
+				if (WAITCORE(s))
+					prs(" - core dumped");
+				if (rv >= NSIGNAL || signame[rv])
+					prs("\n");
+				rv = -1;
+			} else
+				rv = WAITVAL(s);
+		}
+	} while (pid != lastpid);
+	heedint = oheedint;
+	if (intr)
+		if (talking) {
+			if (canintr)
+				intr = 0;
+		} else {
+			if (exstat == 0) exstat = rv;
+			onintr(0);
+		}
+	return(rv);
+}
+
+int
+setstatus(s)
+register int s;
+{
+	exstat = s;
+	setval(lookup("?"), putn(s));
+	return(s);
+}
+
+/*
+ * PATH-searching interface to execve.
+ * If getenv("PATH") were kept up-to-date,
+ * execvp might be used.
+ */
+char *
+rexecve(c, v, envp)
+char *c, **v, **envp;
+{
+	register int i;
+	register char *sp, *tp;
+	int eacces = 0, asis = 0;
+
+	sp = any('/', c)? "": path->value;
+	asis = *sp == '\0';
+	while (asis || *sp != '\0') {
+		asis = 0;
+		tp = e.linep;
+		for (; *sp != '\0'; tp++)
+			if ((*tp = *sp++) == ':') {
+				asis = *sp == '\0';
+				break;
+			}
+		if (tp != e.linep)
+			*tp++ = '/';
+		for (i = 0; (*tp++ = c[i++]) != '\0';)
+			;
+		execve(e.linep, v, envp);
+		switch (errno) {
+		case ENOEXEC:
+			*v = e.linep;
+			tp = *--v;
+			*v = e.linep;
+			execve("/bin/sh", v, envp);
+			*v = tp;
+			return("no Shell");
+
+		case ENOMEM:
+			return("program too big");
+
+		case E2BIG:
+			return("argument list too long");
+
+		case EACCES:
+			eacces++;
+			break;
+		}
+	}
+	return(errno==ENOENT ? "not found" : "cannot execute");
+}
+
+/*
+ * Run the command produced by generator `f'
+ * applied to stream `arg'.
+ */
+int
+run(argp, f)
+struct ioarg *argp;
+int (*f)();
+{
+	struct op *otree;
+	struct wdblock *swdlist;
+	struct wdblock *siolist;
+	jmp_buf ev, rt;
+	xint *ofail;
+	int rv;
+
+	areanum++;
+	swdlist = wdlist;
+	siolist = iolist;
+	otree = outtree;
+	ofail = failpt;
+	rv = -1;
+	if (newenv(setjmp(errpt = ev)) == 0) {
+		wdlist = 0;
+		iolist = 0;
+		pushio(argp, f);
+		e.iobase = e.iop;
+		yynerrs = 0;
+		if (setjmp(failpt = rt) == 0 && yyparse() == 0)
+			rv = execute(outtree, NOPIPE, NOPIPE, 0);
+		quitenv();
+	}
+	wdlist = swdlist;
+	iolist = siolist;
+	failpt = ofail;
+	outtree = otree;
+	freearea(areanum--);
+	return(rv);
+}
+
+/* -------- do.c -------- */
+/* #include "sh.h" */
+
+/*
+ * built-in commands: doX
+ */
+
+int
+dolabel()
+{
+	return(0);
+}
+
+int
+dochdir(t)
+register struct op *t;
+{
+	register char *cp, *er;
+
+	if ((cp = t->words[1]) == NULL && (cp = homedir->value) == NULL)
+		er = ": no home directory";
+	else if(chdir(cp) < 0)
+		er = ": bad directory";
+	else
+		return(0);
+	prs(cp != NULL? cp: "cd");
+	err(er);
+	return(1);
+}
+
+int
+doshift(t)
+register struct op *t;
+{
+	register n;
+
+	n = t->words[1]? getn(t->words[1]): 1;
+	if(dolc < n) {
+		err("nothing to shift");
+		return(1);
+	}
+	dolv[n] = dolv[0];
+	dolv += n;
+	dolc -= n;
+	setval(lookup("#"), putn(dolc));
+	return(0);
+}
+
+/*
+ * execute login and newgrp directly
+ */
+int
+dologin(t)
+struct op *t;
+{
+	register char *cp;
+
+	if (talking) {
+		signal(SIGINT, SIG_DFL);
+		signal(SIGQUIT, SIG_DFL);
+	}
+	cp = rexecve(t->words[0], t->words, makenv());
+	prs(t->words[0]); prs(": "); err(cp);
+	return(1);
+}
+
+int
+doumask(t)
+register struct op *t;
+{
+	register int i, n;
+	register char *cp;
+
+	if ((cp = t->words[1]) == NULL) {
+		i = umask(0);
+		umask(i);
+		for (n=3*4; (n-=3) >= 0;)
+			putc('0'+((i>>n)&07));
+		putc('\n');
+	} else {
+		for (n=0; *cp>='0' && *cp<='9'; cp++)
+			n = n*8 + (*cp-'0');
+		umask(n);
+	}
+	return(0);
+}
+
+int
+doexec(t)
+register struct op *t;
+{
+	register i;
+	jmp_buf ex;
+	xint *ofail;
+
+	t->ioact = NULL;
+	for(i = 0; (t->words[i]=t->words[i+1]) != NULL; i++)
+		;
+	if (i == 0)
+		return(1);
+	execflg = 1;
+	ofail = failpt;
+	if (setjmp(failpt = ex) == 0)
+		execute(t, NOPIPE, NOPIPE, FEXEC);
+	failpt = ofail;
+	execflg = 0;
+	return(1);
+}
+
+int
+dodot(t)
+struct op *t;
+{
+	register i;
+	register char *sp, *tp;
+	char *cp;
+
+	if ((cp = t->words[1]) == NULL)
+		return(0);
+	sp = any('/', cp)? ":": path->value;
+	while (*sp) {
+		tp = e.linep;
+		while (*sp && (*tp = *sp++) != ':')
+			tp++;
+		if (tp != e.linep)
+			*tp++ = '/';
+		for (i = 0; (*tp++ = cp[i++]) != '\0';)
+			;
+		if ((i = open(e.linep, 0)) >= 0) {
+			exstat = 0;
+			next(remap(i));
+			return(exstat);
+		}
+	}
+	prs(cp);
+	err(": not found");
+	return(-1);
+}
+
+int
+dowait(t)
+struct op *t;
+{
+	register i;
+	register char *cp;
+
+	if ((cp = t->words[1]) != NULL) {
+		i = getn(cp);
+		if (i == 0)
+			return(0);
+	} else
+		i = -1;
+	setstatus(waitfor(i, 1));
+	return(0);
+}
+
+int
+doread(t)
+struct op *t;
+{
+	register char *cp, **wp;
+	register nb;
+	register int  nl = 0;
+
+	if (t->words[1] == NULL) {
+		err("Usage: read name ...");
+		return(1);
+	}
+	for (wp = t->words+1; *wp; wp++) {
+		for (cp = e.linep; !nl && cp < elinep-1; cp++)
+			if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) ||
+			    (nl = (*cp == '\n')) ||
+			    (wp[1] && any(*cp, ifs->value)))
+				break;
+		*cp = 0;
+		if (nb <= 0)
+			break;
+		setval(lookup(*wp), e.linep);
+	}
+	return(nb <= 0);
+}
+
+int
+doeval(t)
+register struct op *t;
+{
+	return(RUN(awordlist, t->words+1, wdchar));
+}
+
+int
+dotrap(t)
+register struct op *t;
+{
+	register int  n, i;
+	register int  resetsig;
+
+	if (t->words[1] == NULL) {
+		for (i=0; i<=_NSIG; i++)
+			if (trap[i]) {
+				prn(i);
+				prs(": ");
+				prs(trap[i]);
+				prs("\n");
+			}
+		return(0);
+	}
+	resetsig = digit(*t->words[1]);
+	for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) {
+		n = getsig(t->words[i]);
+		xfree(trap[n]);
+		trap[n] = 0;
+		if (!resetsig) {
+			if (*t->words[1] != '\0') {
+				trap[n] = strsave(t->words[1], 0);
+				setsig(n, sig);
+			} else
+				setsig(n, SIG_IGN);
+		} else {
+			if (talking)
+				if (n == SIGINT)
+					setsig(n, onintr);
+				else
+					setsig(n, n == SIGQUIT ? SIG_IGN 
+							       : SIG_DFL);
+			else
+				setsig(n, SIG_DFL);
+		}
+	}
+	return(0);
+}
+
+int
+getsig(s)
+char *s;
+{
+	register int n;
+
+	if ((n = getn(s)) < 0 || n > _NSIG) {
+		err("trap: bad signal number");
+		n = 0;
+	}
+	return(n);
+}
+
+void
+setsig(n, f)
+register n;
+_PROTOTYPE(void (*f), (int));
+{
+	if (n == 0)
+		return;
+	if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
+		ourtrap[n] = 1;
+		signal(n, f);
+	}
+}
+
+int
+getn(as)
+char *as;
+{
+	register char *s;
+	register n, m;
+
+	s = as;
+	m = 1;
+	if (*s == '-') {
+		m = -1;
+		s++;
+	}
+	for (n = 0; digit(*s); s++)
+		n = (n*10) + (*s-'0');
+	if (*s) {
+		prs(as);
+		err(": bad number");
+	}
+	return(n*m);
+}
+
+int
+dobreak(t)
+struct op *t;
+{
+	return(brkcontin(t->words[1], 1));
+}
+
+int
+docontinue(t)
+struct op *t;
+{
+	return(brkcontin(t->words[1], 0));
+}
+
+static int
+brkcontin(cp, val)
+register char *cp;
+int val;
+{
+	register struct brkcon *bc;
+	register nl;
+
+	nl = cp == NULL? 1: getn(cp);
+	if (nl <= 0)
+		nl = 999;
+	do {
+		if ((bc = brklist) == NULL)
+			break;
+		brklist = bc->nextlev;
+	} while (--nl);
+	if (nl) {
+		err("bad break/continue level");
+		return(1);
+	}
+	isbreak = val;
+	longjmp(bc->brkpt, 1);
+	/* NOTREACHED */
+}
+
+int
+doexit(t)
+struct op *t;
+{
+	register char *cp;
+
+	execflg = 0;
+	if ((cp = t->words[1]) != NULL)
+		setstatus(getn(cp));
+	leave();
+	/* NOTREACHED */
+}
+
+int
+doexport(t)
+struct op *t;
+{
+	rdexp(t->words+1, export, EXPORT);
+	return(0);
+}
+
+int
+doreadonly(t)
+struct op *t;
+{
+	rdexp(t->words+1, ronly, RONLY);
+	return(0);
+}
+
+static void
+rdexp(wp, f, key)
+register char **wp;
+void (*f)();
+int key;
+{
+	if (*wp != NULL) {
+		for (; *wp != NULL; wp++)
+			if (checkname(*wp))
+				(*f)(lookup(*wp));
+			else
+				badid(*wp);
+	} else
+		putvlist(key, 1);
+}
+
+static void
+badid(s)
+register char *s;
+{
+	prs(s);
+	err(": bad identifier");
+}
+
+int
+doset(t)
+register struct op *t;
+{
+	register struct var *vp;
+	register char *cp;
+	register n;
+
+	if ((cp = t->words[1]) == NULL) {
+		for (vp = vlist; vp; vp = vp->next)
+			varput(vp->name, 1);
+		return(0);
+	}
+	if (*cp == '-') {
+		/* bad: t->words++; */
+		for(n = 0; (t->words[n]=t->words[n+1]) != NULL; n++)
+			;
+		if (*++cp == 0)
+			flag['x'] = flag['v'] = 0;
+		else
+			for (; *cp; cp++)
+				switch (*cp) {
+				case 'e':
+					if (!talking)
+						flag['e']++;
+					break;
+
+				default:
+					if (*cp>='a' && *cp<='z')
+						flag[*cp]++;
+					break;
+				}
+		setdash();
+	}
+	if (t->words[1]) {
+		t->words[0] = dolv[0];
+		for (n=1; t->words[n]; n++)
+			setarea((char *)t->words[n], 0);
+		dolc = n-1;
+		dolv = t->words;
+		setval(lookup("#"), putn(dolc));
+		setarea((char *)(dolv-1), 0);
+	}
+	return(0);
+}
+
+void
+varput(s, out)
+register char *s;
+int out;
+{
+	if (letnum(*s)) {
+		write(out, s, strlen(s));
+		write(out, "\n", 1);
+	}
+}
+
+
+#define	SECS	60L
+#define	MINS	3600L
+
+int
+dotimes()
+{
+	struct tms tbuf;
+
+	times(&tbuf);
+
+	prn((int)(tbuf.tms_cutime / MINS));
+	prs("m");
+	prn((int)((tbuf.tms_cutime % MINS) / SECS));
+	prs("s ");
+	prn((int)(tbuf.tms_cstime / MINS));
+	prs("m");
+	prn((int)((tbuf.tms_cstime % MINS) / SECS));
+	prs("s\n");
+	return(0);
+}
+
+struct	builtin {
+	char	*command;
+	int	(*fn)();
+};
+static struct	builtin	builtin[] = {
+	":",		dolabel,
+	"cd",		dochdir,
+	"shift",	doshift,
+	"exec",		doexec,
+	"wait",		dowait,
+	"read",		doread,
+	"eval",		doeval,
+	"trap",		dotrap,
+	"break",	dobreak,
+	"continue",	docontinue,
+	"exit",		doexit,
+	"export",	doexport,
+	"readonly",	doreadonly,
+	"set",		doset,
+	".",		dodot,
+	"umask",	doumask,
+	"login",	dologin,
+	"newgrp",	dologin,
+	"times",	dotimes,
+	0,
+};
+
+int (*inbuilt(s))()
+register char *s;
+{
+	register struct builtin *bp;
+
+	for (bp = builtin; bp->command != NULL; bp++)
+		if (strcmp(bp->command, s) == 0)
+			return(bp->fn);
+	return((int(*)())NULL);
+}
+
Index: /trunk/minix/commands/sh/sh4.c
===================================================================
--- /trunk/minix/commands/sh/sh4.c	(revision 9)
+++ /trunk/minix/commands/sh/sh4.c	(revision 9)
@@ -0,0 +1,779 @@
+#define Extern extern
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include <limits.h>
+#include <signal.h>
+#include <errno.h>
+#include <setjmp.h>
+#include "sh.h"
+
+/* -------- eval.c -------- */
+/* #include "sh.h" */
+/* #include "word.h" */
+
+/*
+ * ${}
+ * `command`
+ * blank interpretation
+ * quoting
+ * glob
+ */
+
+_PROTOTYPE(static int expand, (char *cp, struct wdblock **wbp, int f ));
+_PROTOTYPE(static char *blank, (int f ));
+_PROTOTYPE(static int dollar, (int quoted ));
+_PROTOTYPE(static int grave, (int quoted ));
+_PROTOTYPE(void globname, (char *we, char *pp ));
+_PROTOTYPE(static char *generate, (char *start1, char *end1, char *middle, char *end ));
+_PROTOTYPE(static int anyspcl, (struct wdblock *wb ));
+_PROTOTYPE(static int xstrcmp, (char *p1, char *p2 ));
+_PROTOTYPE(void glob0, (char *a0, unsigned int a1, int a2, int (*a3)(char *, char *)));
+_PROTOTYPE(void glob1, (char *base, char *lim ));
+_PROTOTYPE(void glob2, (char *i, char *j ));
+_PROTOTYPE(void glob3, (char *i, char *j, char *k ));
+_PROTOTYPE(char *memcopy, (char *ato, char *from, int nb ));
+
+char **
+eval(ap, f)
+register char **ap;
+int f;
+{
+	struct wdblock *wb;
+	char **wp;
+	char **wf;
+	jmp_buf ev;
+
+	wp = NULL;
+	wb = NULL;
+	wf = NULL;
+	if (newenv(setjmp(errpt = ev)) == 0) {
+		while (*ap && isassign(*ap))
+			expand(*ap++, &wb, f & ~DOGLOB);
+		if (flag['k']) {
+			for (wf = ap; *wf; wf++) {
+				if (isassign(*wf))
+					expand(*wf, &wb, f & ~DOGLOB);
+			}
+		}
+		for (wb = addword((char *)0, wb); *ap; ap++) {
+			if (!flag['k'] || !isassign(*ap))
+				expand(*ap, &wb, f & ~DOKEY);
+		}
+		wb = addword((char *)0, wb);
+		wp = getwords(wb);
+		quitenv();
+	} else
+		gflg = 1;
+	return(gflg? (char **)NULL: wp);
+}
+
+/*
+ * Make the exported environment from the exported
+ * names in the dictionary. Keyword assignments
+ * will already have been done.
+ */
+char **
+makenv()
+
+{
+	register struct wdblock *wb;
+	register struct var *vp;
+
+	wb = NULL;
+	for (vp = vlist; vp; vp = vp->next)
+		if (vp->status & EXPORT)
+			wb = addword(vp->name, wb);
+	wb = addword((char *)0, wb);
+	return(getwords(wb));
+}
+
+char *
+evalstr(cp, f)
+register char *cp;
+int f;
+{
+	struct wdblock *wb;
+
+	wb = NULL;
+	if (expand(cp, &wb, f)) {
+		if (wb == NULL || wb->w_nword == 0 || (cp = wb->w_words[0]) == NULL)
+			cp = "";
+		DELETE(wb);
+	} else
+		cp = NULL;
+	return(cp);
+}
+
+static int
+expand(cp, wbp, f)
+register char *cp;
+register struct wdblock **wbp;
+int f;
+{
+	jmp_buf ev;
+
+	gflg = 0;
+	if (cp == NULL)
+		return(0);
+	if (!anys("$`'\"", cp) &&
+	    !anys(ifs->value, cp) &&
+	    ((f&DOGLOB)==0 || !anys("[*?", cp))) {
+		cp = strsave(cp, areanum);
+		if (f & DOTRIM)
+			unquote(cp);
+		*wbp = addword(cp, *wbp);
+		return(1);
+	}
+	if (newenv(setjmp(errpt = ev)) == 0) {
+		PUSHIO(aword, cp, strchar);
+		e.iobase = e.iop;
+		while ((cp = blank(f)) && gflg == 0) {
+			e.linep = cp;
+			cp = strsave(cp, areanum);
+			if ((f&DOGLOB) == 0) {
+				if (f & DOTRIM)
+					unquote(cp);
+				*wbp = addword(cp, *wbp);
+			} else
+				*wbp = glob(cp, *wbp);
+		}
+		quitenv();
+	} else
+		gflg = 1;
+	return(gflg == 0);
+}
+
+/*
+ * Blank interpretation and quoting
+ */
+static char *
+blank(f)
+int f;
+{
+	register c, c1;
+	register char *sp;
+	int scanequals, foundequals;
+
+	sp = e.linep;
+	scanequals = f & DOKEY;
+	foundequals = 0;
+
+loop:
+	switch (c = subgetc('"', foundequals)) {
+	case 0:
+		if (sp == e.linep)
+			return(0);
+		*e.linep++ = 0;
+		return(sp);
+
+	default:
+		if (f & DOBLANK && any(c, ifs->value))
+			goto loop;
+		break;
+
+	case '"':
+	case '\'':
+		scanequals = 0;
+		if (INSUB())
+			break;
+		for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
+			if (c == 0)
+				break;
+			if (c == '\'' || !any(c, "$`\""))
+				c |= QUOTE;
+			*e.linep++ = c;
+		}
+		c = 0;
+	}
+	unget(c);
+	if (!letter(c))
+		scanequals = 0;
+	for (;;) {
+		c = subgetc('"', foundequals);
+		if (c == 0 ||
+		    (f & DOBLANK && any(c, ifs->value)) ||
+		    (!INSUB() && any(c, "\"'"))) {
+		        scanequals = 0;
+			unget(c);
+			if (any(c, "\"'"))
+				goto loop;
+			break;
+		}
+		if (scanequals)
+			if (c == '=') {
+				foundequals = 1;
+				scanequals  = 0;
+			}
+			else if (!letnum(c))
+				scanequals = 0;
+		*e.linep++ = c;
+	}
+	*e.linep++ = 0;
+	return(sp);
+}
+
+/*
+ * Get characters, substituting for ` and $
+ */
+int
+subgetc(ec, quoted)
+register char ec;
+int quoted;
+{
+	register char c;
+
+again:
+	c = getc(ec);
+	if (!INSUB() && ec != '\'') {
+		if (c == '`') {
+			if (grave(quoted) == 0)
+				return(0);
+			e.iop->task = XGRAVE;
+			goto again;
+		}
+		if (c == '$' && (c = dollar(quoted)) == 0) {
+			e.iop->task = XDOLL;
+			goto again;
+		}
+	}
+	return(c);
+}
+
+/*
+ * Prepare to generate the string returned by ${} substitution.
+ */
+static int
+dollar(quoted)
+int quoted;
+{
+	int otask;
+	struct io *oiop;
+	char *dolp;
+	register char *s, c, *cp;
+	struct var *vp;
+
+	c = readc();
+	s = e.linep;
+	if (c != '{') {
+		*e.linep++ = c;
+		if (letter(c)) {
+			while ((c = readc())!=0 && letnum(c))
+				if (e.linep < elinep)
+					*e.linep++ = c;
+			unget(c);
+		}
+		c = 0;
+	} else {
+		oiop = e.iop;
+		otask = e.iop->task;
+		e.iop->task = XOTHER;
+		while ((c = subgetc('"', 0))!=0 && c!='}' && c!='\n')
+			if (e.linep < elinep)
+				*e.linep++ = c;
+		if (oiop == e.iop)
+			e.iop->task = otask;
+		if (c != '}') {
+			err("unclosed ${");
+			gflg++;
+			return(c);
+		}
+	}
+	if (e.linep >= elinep) {
+		err("string in ${} too long");
+		gflg++;
+		e.linep -= 10;
+	}
+	*e.linep = 0;
+	if (*s)
+		for (cp = s+1; *cp; cp++)
+			if (any(*cp, "=-+?")) {
+				c = *cp;
+				*cp++ = 0;
+				break;
+			}
+	if (s[1] == 0 && (*s == '*' || *s == '@')) {
+		if (dolc > 1) {
+			/* currently this does not distinguish $* and $@ */
+			/* should check dollar */
+			e.linep = s;
+			PUSHIO(awordlist, dolv+1, dolchar);
+			return(0);
+		} else {	/* trap the nasty ${=} */
+			s[0] = '1';
+			s[1] = 0;
+		}
+	}
+	e.linep = s;
+	vp = lookup(s);
+	if ((dolp = vp->value) == null) {
+		switch (c) {
+		case '=':
+			if (digit(*s)) {
+				err("cannot use ${...=...} with $n");
+				gflg++;
+				break;
+			}
+			cp = evalstr(strsave(cp, areanum),DOSUB);
+			setval(vp, cp);
+			dolp = vp->value;
+			break;
+
+		case '-':
+			dolp = evalstr(strsave(cp, areanum),DOSUB);
+			break;
+
+		case '?':
+			if (*cp == 0) {
+				prs("missing value for ");
+				err(s);
+			} else
+			        err(evalstr(strsave(cp, areanum),DOSUB));
+			gflg++;
+			break;
+		}
+	} else if (c == '+') {
+		dolp = evalstr(strsave(cp, areanum),DOSUB);
+	}
+	if (flag['u'] && dolp == null) {
+		prs("unset variable: ");
+		err(s);
+		gflg++;
+	}
+	PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
+	return(0);
+}
+
+/*
+ * Run the command in `...` and read its output.
+ */
+static int
+grave(quoted)
+int quoted;
+{
+        int otask;
+        struct io *oiop;
+	register char *cp,*s;
+	register int i,c;
+	int pf[2];
+
+	c = readc();
+        s = e.linep;
+        *e.linep++ = c;
+	oiop = e.iop;
+	otask = e.iop->task;
+	e.iop->task = XOTHER;
+	while ((c = subgetc('\'', 0))!=0 && c!='`')
+		if (e.linep < elinep)
+			*e.linep++ = c;
+	if (oiop == e.iop)
+		e.iop->task = otask;
+	if (c != '`') {
+		err("no closing `");
+		return(0);
+	}
+	if (openpipe(pf) < 0)
+		return(0);
+	if ((i = fork()) == -1) {
+		closepipe(pf);
+		err("try again");
+		return(0);
+	}
+	if (i != 0) {
+		e.linep = s;
+		close(pf[1]);
+		PUSHIO(afile, remap(pf[0]), quoted? qgravechar: gravechar);
+		return(1);
+	}
+	*e.linep = 0;
+	/* allow trapped signals */
+	for (i=0; i<=_NSIG; i++)
+		if (ourtrap[i] && signal(i, SIG_IGN) != SIG_IGN)
+			signal(i, SIG_DFL);
+	dup2(pf[1], 1);
+	closepipe(pf);
+	flag['e'] = 0;
+	flag['v'] = 0;
+	flag['n'] = 0;
+	cp = strsave(e.linep = s, 0);
+	areanum = 1;
+	inithere();
+	freearea(areanum);	/* free old space */
+	e.oenv = NULL;
+	e.iop = (e.iobase = iostack) - 1;
+	unquote(cp);
+	talking = 0;
+	PUSHIO(aword, cp, nlchar);
+	onecommand();
+	exit(1);
+}
+
+char *
+unquote(as)
+register char *as;
+{
+	register char *s;
+
+	if ((s = as) != NULL)
+		while (*s)
+			*s++ &= ~QUOTE;
+	return(as);
+}
+
+/* -------- glob.c -------- */
+/* #include "sh.h" */
+
+/*
+ * glob
+ */
+
+#define	scopy(x) strsave((x), areanum)
+#define	BLKSIZ	512
+#define	NDENT	((BLKSIZ+sizeof(struct direct)-1)/sizeof(struct direct))
+
+static	struct wdblock	*cl, *nl;
+static	char	spcl[] = "[?*";
+
+struct wdblock *
+glob(cp, wb)
+char *cp;
+struct wdblock *wb;
+{
+	register i;
+	register char *pp;
+
+	if (cp == 0)
+		return(wb);
+	i = 0;
+	for (pp = cp; *pp; pp++)
+		if (any(*pp, spcl))
+			i++;
+		else if (!any(*pp & ~QUOTE, spcl))
+			*pp &= ~QUOTE;
+	if (i != 0) {
+		for (cl = addword(scopy(cp), (struct wdblock *)0); anyspcl(cl); cl = nl) {
+			nl = newword(cl->w_nword*2);
+			for(i=0; i<cl->w_nword; i++) { /* for each argument */
+				for (pp = cl->w_words[i]; *pp; pp++)
+					if (any(*pp, spcl)) {
+						globname(cl->w_words[i], pp);
+						break;
+					}
+				if (*pp == '\0')
+					nl = addword(scopy(cl->w_words[i]), nl);
+			}
+			for(i=0; i<cl->w_nword; i++)
+				DELETE(cl->w_words[i]);
+			DELETE(cl);
+		}
+		for(i=0; i<cl->w_nword; i++)
+			unquote(cl->w_words[i]);
+		glob0((char *)cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
+		if (cl->w_nword) {
+			for (i=0; i<cl->w_nword; i++)
+				wb = addword(cl->w_words[i], wb);
+			DELETE(cl);
+			return(wb);
+		}
+	}
+	wb = addword(unquote(cp), wb);
+	return(wb);
+}
+
+void
+globname(we, pp)
+char *we;
+register char *pp;
+{
+	register char *np, *cp;
+	char *name, *gp, *dp;
+	int dn, j, n, k;
+	struct direct ent[NDENT];
+	char dname[NAME_MAX+1];
+	struct stat dbuf;
+
+	for (np = we; np != pp; pp--)
+		if (pp[-1] == '/')
+			break;
+	for (dp = cp = space((int)(pp-np)+3); np < pp;)
+		*cp++ = *np++;
+	*cp++ = '.';
+	*cp = '\0';
+	for (gp = cp = space(strlen(pp)+1); *np && *np != '/';)
+		*cp++ = *np++;
+	*cp = '\0';
+	dn = open(dp, 0);
+	if (dn < 0) {
+		DELETE(dp);
+		DELETE(gp);
+		return;
+	}
+	dname[NAME_MAX] = '\0';
+	while ((n = read(dn, (char *)ent, sizeof(ent))) >= sizeof(*ent)) {
+		n /= sizeof(*ent);
+		for (j=0; j<n; j++) {
+			if (ent[j].d_ino == 0)
+				continue;
+			strncpy(dname, ent[j].d_name, NAME_MAX);
+			if (dname[0] == '.')
+				if (*gp != '.')
+					continue;
+			for(k=0; k<NAME_MAX; k++)
+				if (any(dname[k], spcl))
+					dname[k] |= QUOTE;
+			if (gmatch(dname, gp)) {
+				name = generate(we, pp, dname, np);
+				if (*np && !anys(np, spcl)) {
+					if (stat(name,&dbuf)) {
+						DELETE(name);
+						continue;
+					}
+				}
+				nl = addword(name, nl);
+			}
+		}
+	}
+	close(dn);
+	DELETE(dp);
+	DELETE(gp);
+}
+
+/*
+ * generate a pathname as below.
+ * start..end1 / middle end
+ * the slashes come for free
+ */
+static char *
+generate(start1, end1, middle, end)
+char *start1;
+register char *end1;
+char *middle, *end;
+{
+	char *p;
+	register char *op, *xp;
+
+	p = op = space((int)(end1-start1)+strlen(middle)+strlen(end)+2);
+	for (xp = start1; xp != end1;)
+		*op++ = *xp++;
+	for (xp = middle; (*op++ = *xp++) != '\0';)
+		;
+	op--;
+	for (xp = end; (*op++ = *xp++) != '\0';)
+		;
+	return(p);
+}
+
+static int
+anyspcl(wb)
+register struct wdblock *wb;
+{
+	register i;
+	register char **wd;
+
+	wd = wb->w_words;
+	for (i=0; i<wb->w_nword; i++)
+		if (anys(spcl, *wd++))
+			return(1);
+	return(0);
+}
+
+static int
+xstrcmp(p1, p2)
+char *p1, *p2;
+{
+	return(strcmp(*(char **)p1, *(char **)p2));
+}
+
+/* -------- word.c -------- */
+/* #include "sh.h" */
+/* #include "word.h" */
+
+#define	NSTART	16	/* default number of words to allow for initially */
+
+struct wdblock *
+newword(nw)
+register int nw;
+{
+	register struct wdblock *wb;
+
+	wb = (struct wdblock *) space(sizeof(*wb) + nw*sizeof(char *));
+	wb->w_bsize = nw;
+	wb->w_nword = 0;
+	return(wb);
+}
+
+struct wdblock *
+addword(wd, wb)
+char *wd;
+register struct wdblock *wb;
+{
+	register struct wdblock *wb2;
+	register nw;
+
+	if (wb == NULL)
+		wb = newword(NSTART);
+	if ((nw = wb->w_nword) >= wb->w_bsize) {
+		wb2 = newword(nw * 2);
+		memcopy((char *)wb2->w_words, (char *)wb->w_words, nw*sizeof(char *));
+		wb2->w_nword = nw;
+		DELETE(wb);
+		wb = wb2;
+	}
+	wb->w_words[wb->w_nword++] = wd;
+	return(wb);
+}
+
+char **
+getwords(wb)
+register struct wdblock *wb;
+{
+	register char **wd;
+	register nb;
+
+	if (wb == NULL)
+		return((char **)NULL);
+	if (wb->w_nword == 0) {
+		DELETE(wb);
+		return((char **)NULL);
+	}
+	wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
+	memcopy((char *)wd, (char *)wb->w_words, nb);
+	DELETE(wb);	/* perhaps should done by caller */
+	return(wd);
+}
+
+_PROTOTYPE(int (*func), (char *, char *));
+int	globv;
+
+void
+glob0(a0, a1, a2, a3)
+char *a0;
+unsigned a1;
+int a2;
+_PROTOTYPE(int (*a3), (char *, char *));
+{
+	func = a3;
+	globv = a2;
+	glob1(a0, a0 + a1 * a2);
+}
+
+void
+glob1(base, lim)
+char *base, *lim;
+{
+	register char *i, *j;
+	int v2;
+	char *lptr, *hptr;
+	int c;
+	unsigned n;
+
+
+	v2 = globv;
+
+top:
+	if ((n=(int)(lim-base)) <= v2)
+		return;
+	n = v2 * (n / (2*v2));
+	hptr = lptr = base+n;
+	i = base;
+	j = lim-v2;
+	for(;;) {
+		if (i < lptr) {
+			if ((c = (*func)(i, lptr)) == 0) {
+				glob2(i, lptr -= v2);
+				continue;
+			}
+			if (c < 0) {
+				i += v2;
+				continue;
+			}
+		}
+
+begin:
+		if (j > hptr) {
+			if ((c = (*func)(hptr, j)) == 0) {
+				glob2(hptr += v2, j);
+				goto begin;
+			}
+			if (c > 0) {
+				if (i == lptr) {
+					glob3(i, hptr += v2, j);
+					i = lptr += v2;
+					goto begin;
+				}
+				glob2(i, j);
+				j -= v2;
+				i += v2;
+				continue;
+			}
+			j -= v2;
+			goto begin;
+		}
+
+
+		if (i == lptr) {
+			if (lptr-base >= lim-hptr) {
+				glob1(hptr+v2, lim);
+				lim = lptr;
+			} else {
+				glob1(base, lptr);
+				base = hptr+v2;
+			}
+			goto top;
+		}
+
+
+		glob3(j, lptr -= v2, i);
+		j = hptr -= v2;
+	}
+}
+
+void
+glob2(i, j)
+char *i, *j;
+{
+	register char *index1, *index2, c;
+	int m;
+
+	m = globv;
+	index1 = i;
+	index2 = j;
+	do {
+		c = *index1;
+		*index1++ = *index2;
+		*index2++ = c;
+	} while(--m);
+}
+
+void
+glob3(i, j, k)
+char *i, *j, *k;
+{
+	register char *index1, *index2, *index3;
+	int c;
+	int m;
+
+	m = globv;
+	index1 = i;
+	index2 = j;
+	index3 = k;
+	do {
+		c = *index1;
+		*index1++ = *index3;
+		*index3++ = *index2;
+		*index2++ = c;
+	} while(--m);
+}
+
+char *
+memcopy(ato, from, nb)
+register char *ato, *from;
+register int nb;
+{
+	register char *to;
+
+	to = ato;
+	while (--nb >= 0)
+		*to++ = *from++;
+	return(ato);
+}
Index: /trunk/minix/commands/sh/sh5.c
===================================================================
--- /trunk/minix/commands/sh/sh5.c	(revision 9)
+++ /trunk/minix/commands/sh/sh5.c	(revision 9)
@@ -0,0 +1,681 @@
+#define Extern extern
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#include <setjmp.h>
+#include "sh.h"
+
+/* -------- io.c -------- */
+/* #include "sh.h" */
+
+/*
+ * shell IO
+ */
+
+static struct iobuf sharedbuf = {AFID_NOBUF};
+static struct iobuf mainbuf = {AFID_NOBUF};
+static unsigned bufid = AFID_ID;	/* buffer id counter */
+
+struct ioarg temparg = {0, 0, 0, AFID_NOBUF, 0};
+
+_PROTOTYPE(static void readhere, (char **name, char *s, int ec ));
+_PROTOTYPE(void pushio, (struct ioarg *argp, int (*fn)()));
+_PROTOTYPE(static int xxchar, (struct ioarg *ap ));
+_PROTOTYPE(void tempname, (char *tname ));
+
+int
+getc(ec)
+register int ec;
+{
+	register int c;
+
+	if(e.linep > elinep) {
+		while((c=readc()) != '\n' && c)
+			;
+		err("input line too long");
+		gflg++;
+		return(c);
+	}
+	c = readc();
+ 	if (ec != '\'' && e.iop->task != XGRAVE) {
+		if(c == '\\') {
+			c = readc();
+			if (c == '\n' && ec != '\"')
+				return(getc(ec));
+			c |= QUOTE;
+		}
+	}
+	return(c);
+}
+
+void
+unget(c)
+int c;
+{
+	if (e.iop >= e.iobase)
+		e.iop->peekc = c;
+}
+
+int
+eofc()
+
+{
+  return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
+}
+
+int
+readc()
+{
+	register c;
+
+	for (; e.iop >= e.iobase; e.iop--)
+		if ((c = e.iop->peekc) != '\0') {
+			e.iop->peekc = 0;
+			return(c);
+		}
+		else {
+		    if (e.iop->prev != 0) {
+		        if ((c = (*e.iop->iofn)(e.iop->argp, e.iop)) != '\0') {
+			        if (c == -1) {
+				        e.iop++;
+				        continue;
+			        }
+			        if (e.iop == iostack)
+				        ioecho(c);
+			        return(e.iop->prev = c);
+		        }
+		        else if (e.iop->task == XIO && e.iop->prev != '\n') {
+			        e.iop->prev = 0;
+				if (e.iop == iostack)
+					ioecho('\n');
+			        return '\n';
+		        }
+		    }
+		    if (e.iop->task == XIO) {
+			if (multiline)
+			    return e.iop->prev = 0;
+			if (talking && e.iop == iostack+1)
+			    prs(prompt->value);
+		    }
+		}
+	if (e.iop >= iostack)
+		return(0);
+	leave();
+	/* NOTREACHED */
+}
+
+void
+ioecho(c)
+char c;
+{
+	if (flag['v'])
+		write(2, &c, sizeof c);
+}
+
+void
+pushio(argp, fn)
+struct ioarg *argp;
+int (*fn)();
+{
+	if (++e.iop >= &iostack[NPUSH]) {
+		e.iop--;
+		err("Shell input nested too deeply");
+		gflg++;
+		return;
+	}
+	e.iop->iofn = fn;
+
+	if (argp->afid != AFID_NOBUF)
+	  e.iop->argp = argp;
+	else {
+	  e.iop->argp  = ioargstack + (e.iop - iostack);
+	  *e.iop->argp = *argp;
+	  e.iop->argp->afbuf = e.iop == &iostack[0] ? &mainbuf : &sharedbuf;
+	  if (isatty(e.iop->argp->afile) == 0 &&
+	      (e.iop == &iostack[0] ||
+	       lseek(e.iop->argp->afile, 0L, 1) != -1)) {
+	    if (++bufid == AFID_NOBUF)
+	      bufid = AFID_ID;
+	    e.iop->argp->afid  = bufid;
+	  }
+	}
+
+	e.iop->prev  = ~'\n';
+	e.iop->peekc = 0;
+	e.iop->xchar = 0;
+	e.iop->nlcount = 0;
+	if (fn == filechar || fn == linechar)
+		e.iop->task = XIO;
+	else if (fn == gravechar || fn == qgravechar)
+		e.iop->task = XGRAVE;
+	else
+		e.iop->task = XOTHER;
+}
+
+struct io *
+setbase(ip)
+struct io *ip;
+{
+	register struct io *xp;
+
+	xp = e.iobase;
+	e.iobase = ip;
+	return(xp);
+}
+
+/*
+ * Input generating functions
+ */
+
+/*
+ * Produce the characters of a string, then a newline, then EOF.
+ */
+int
+nlchar(ap)
+register struct ioarg *ap;
+{
+	register int c;
+
+	if (ap->aword == NULL)
+		return(0);
+	if ((c = *ap->aword++) == 0) {
+		ap->aword = NULL;
+		return('\n');
+	}
+	return(c);
+}
+
+/*
+ * Given a list of words, produce the characters
+ * in them, with a space after each word.
+ */
+int
+wdchar(ap)
+register struct ioarg *ap;
+{
+	register char c;
+	register char **wl;
+
+	if ((wl = ap->awordlist) == NULL)
+		return(0);
+	if (*wl != NULL) {
+		if ((c = *(*wl)++) != 0)
+			return(c & 0177);
+		ap->awordlist++;
+		return(' ');
+	}
+	ap->awordlist = NULL;
+	return('\n');
+}
+
+/*
+ * Return the characters of a list of words,
+ * producing a space between them.
+ */
+int
+dolchar(ap)
+register struct ioarg *ap;
+{
+	register char *wp;
+
+	if ((wp = *ap->awordlist++) != NULL) {
+		PUSHIO(aword, wp, *ap->awordlist == NULL? strchar: xxchar);
+		return(-1);
+	}
+	return(0);
+}
+
+static int
+xxchar(ap)
+register struct ioarg *ap;
+{
+	register int c;
+
+	if (ap->aword == NULL)
+		return(0);
+	if ((c = *ap->aword++) == '\0') {
+		ap->aword = NULL;
+		return(' ');
+	}
+	return(c);
+}
+
+/*
+ * Produce the characters from a single word (string).
+ */
+int
+strchar(ap)
+register struct ioarg *ap;
+{
+	register int c;
+
+	if (ap->aword == NULL || (c = *ap->aword++) == 0)
+		return(0);
+	return(c);
+}
+
+/*
+ * Produce quoted characters from a single word (string).
+ */
+int
+qstrchar(ap)
+register struct ioarg *ap;
+{
+	register int c;
+
+	if (ap->aword == NULL || (c = *ap->aword++) == 0)
+		return(0);
+	return(c|QUOTE);
+}
+
+/*
+ * Return the characters from a file.
+ */
+int
+filechar(ap)
+register struct ioarg *ap;
+{
+	register int i;
+	char c;
+	struct iobuf *bp = ap->afbuf;
+
+	if (ap->afid != AFID_NOBUF) {
+	  if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) {
+	    if (i)
+	      lseek(ap->afile, ap->afpos, 0);
+	    do {
+	      i = read(ap->afile, bp->buf, sizeof(bp->buf));
+	    } while (i < 0 && errno == EINTR);
+	    if (i <= 0) {
+	      closef(ap->afile);
+	      return 0;
+	    }
+	    bp->id = ap->afid;
+	    bp->ebufp = (bp->bufp  = bp->buf) + i;
+	  }
+	  ap->afpos++;
+	  return *bp->bufp++ & 0177;
+	}
+
+	do {
+		i = read(ap->afile, &c, sizeof(c));
+	} while (i < 0 && errno == EINTR);
+	return(i == sizeof(c)? c&0177: (closef(ap->afile), 0));
+}
+
+/*
+ * Return the characters from a here temp file.
+ */
+int
+herechar(ap)
+register struct ioarg *ap;
+{
+	char c;
+
+
+	if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
+		close(ap->afile);
+		c = 0;
+	}
+	return (c);
+
+}
+
+/*
+ * Return the characters produced by a process (`...`).
+ * Quote them if required, and remove any trailing newline characters.
+ */
+int
+gravechar(ap, iop)
+struct ioarg *ap;
+struct io *iop;
+{
+	register int c;
+
+	if ((c = qgravechar(ap, iop)&~QUOTE) == '\n')
+		c = ' ';
+	return(c);
+}
+
+int
+qgravechar(ap, iop)
+register struct ioarg *ap;
+struct io *iop;
+{
+	register int c;
+
+	if (iop->xchar) {
+		if (iop->nlcount) {
+			iop->nlcount--;
+			return('\n'|QUOTE);
+		}
+		c = iop->xchar;
+		iop->xchar = 0;
+	} else if ((c = filechar(ap)) == '\n') {
+		iop->nlcount = 1;
+		while ((c = filechar(ap)) == '\n')
+			iop->nlcount++;
+		iop->xchar = c;
+		if (c == 0)
+			return(c);
+		iop->nlcount--;
+		c = '\n';
+	}
+	return(c!=0? c|QUOTE: 0);
+}
+
+/*
+ * Return a single command (usually the first line) from a file.
+ */
+int
+linechar(ap)
+register struct ioarg *ap;
+{
+	register int c;
+
+	if ((c = filechar(ap)) == '\n') {
+		if (!multiline) {
+			closef(ap->afile);
+			ap->afile = -1;	/* illegal value */
+		}
+	}
+	return(c);
+}
+
+void
+prs(s)
+register char *s;
+{
+	if (*s)
+		write(2, s, strlen(s));
+}
+
+void
+putc(c)
+char c;
+{
+	write(2, &c, sizeof c);
+}
+
+void
+prn(u)
+unsigned u;
+{
+	prs(itoa(u, 0));
+}
+
+void
+closef(i)
+register int i;
+{
+	if (i > 2)
+		close(i);
+}
+
+void
+closeall()
+{
+	register u;
+
+	for (u=NUFILE; u<NOFILE;)
+		close(u++);
+}
+
+/*
+ * remap fd into Shell's fd space
+ */
+int
+remap(fd)
+register int fd;
+{
+	register int i;
+	int map[NOFILE];
+
+	if (fd < e.iofd) {
+		for (i=0; i<NOFILE; i++)
+			map[i] = 0;
+		do {
+			map[fd] = 1;
+			fd = dup(fd);
+		} while (fd >= 0 && fd < e.iofd);
+		for (i=0; i<NOFILE; i++)
+			if (map[i])
+				close(i);
+		if (fd < 0)
+			err("too many files open in shell");
+	}
+	return(fd);
+}
+
+int
+openpipe(pv)
+register int *pv;
+{
+	register int i;
+
+	if ((i = pipe(pv)) < 0)
+		err("can't create pipe - try again");
+	return(i);
+}
+
+void
+closepipe(pv)
+register int *pv;
+{
+	if (pv != NULL) {
+		close(*pv++);
+		close(*pv);
+	}
+}
+
+/* -------- here.c -------- */
+/* #include "sh.h" */
+
+/*
+ * here documents
+ */
+
+struct	here {
+	char	*h_tag;
+	int	h_dosub;
+	struct	ioword *h_iop;
+	struct	here	*h_next;
+};
+
+static	struct here *inhere;		/* list of hear docs while parsing */
+static	struct here *acthere;		/* list of active here documents */
+
+void
+inithere()
+{
+	inhere=acthere=(struct here*)0;
+}
+
+void
+markhere(s, iop)
+register char *s;
+struct ioword *iop;
+{
+	register struct here *h, *lh;
+
+	h = (struct here *) space(sizeof(struct here));
+	if (h == 0)
+		return;
+	h->h_tag = evalstr(s, DOSUB);
+	if (h->h_tag == 0)
+		return;
+	h->h_iop = iop;
+	iop->io_name = 0;
+	h->h_next = NULL;
+	if (inhere == 0)
+		inhere = h;
+	else
+		for (lh = inhere; lh!=NULL; lh = lh->h_next)
+			if (lh->h_next == 0) {
+				lh->h_next = h;
+				break;
+			}
+	iop->io_flag |= IOHERE|IOXHERE;
+	for (s = h->h_tag; *s; s++)
+		if (*s & QUOTE) {
+			iop->io_flag &= ~ IOXHERE;
+			*s &= ~ QUOTE;
+		}
+	h->h_dosub = iop->io_flag & IOXHERE;
+}
+
+void
+gethere()
+{
+	register struct here *h, *hp;
+
+	/* Scan here files first leaving inhere list in place */
+	for (hp = h = inhere; h != NULL; hp = h, h = h->h_next)
+	  readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub? 0: '\'');
+
+	/* Make inhere list active - keep list intact for scraphere */
+	if (hp != NULL) {
+	  hp->h_next = acthere;
+	  acthere    = inhere;
+	  inhere     = NULL;
+	}
+}
+
+static void
+readhere(name, s, ec)
+char **name;
+register char *s;
+int ec;
+{
+	int tf;
+	char tname[30];
+	register c;
+	jmp_buf ev;
+	char line [LINELIM+1];
+	char *next;
+
+	tempname(tname);
+	*name = strsave(tname, areanum);
+	tf = creat(tname, 0600);
+	if (tf < 0)
+		return;
+	if (newenv(setjmp(errpt = ev)) != 0)
+		unlink(tname);
+	else {
+		pushio(e.iop->argp, e.iop->iofn);
+		e.iobase = e.iop;
+		for (;;) {
+			if (talking && e.iop <= iostack)
+				prs(cprompt->value);
+			next = line;
+			while ((c = readc()) != '\n' && c) {
+				if (next >= &line[LINELIM]) {
+					c = 0;
+					break;
+				}
+				*next++ = c;
+			}
+			*next = 0;
+			if (strcmp(s, line) == 0 || c == 0)
+				break;
+			*next++ = '\n';
+			write (tf, line, (int)(next-line));
+		}
+		if (c == 0) {
+			prs("here document `"); prs(s); err("' unclosed");
+		}
+		quitenv();
+	}
+	close(tf);
+}
+
+/*
+ * open here temp file.
+ * if unquoted here, expand here temp file into second temp file.
+ */
+int
+herein(hname, xdoll)
+char *hname;
+int xdoll;
+{
+	register hf, tf;
+
+	if (hname == 0)
+		return(-1);
+	hf = open(hname, 0);
+	if (hf < 0)
+		return (-1);
+	if (xdoll) {
+		char c;
+		char tname[30];
+		jmp_buf ev;
+
+		tempname(tname);
+		if ((tf = creat(tname, 0600)) < 0)
+			return (-1);
+		if (newenv(setjmp(errpt = ev)) == 0) {
+			PUSHIO(afile, hf, herechar);
+			setbase(e.iop);
+			while ((c = subgetc(0, 0)) != 0) {
+				char c1 = c&~QUOTE;
+
+				if (c&QUOTE && !any(c1,"`$\\"))
+					write(tf,"\\",1);
+				write(tf, &c1, 1);
+			}
+			quitenv();
+		} else
+			unlink(tname);
+		close(tf);
+		tf = open(tname, 0);
+		unlink(tname);
+		return (tf);
+	} else
+		return (hf);
+}
+
+void
+scraphere()
+{
+	register struct here *h;
+
+	for (h = inhere; h != NULL; h = h->h_next) {
+		if (h->h_iop && h->h_iop->io_name)
+		  unlink(h->h_iop->io_name);
+	}
+	inhere = NULL;
+}
+
+/* unlink here temp files before a freearea(area) */
+void
+freehere(area)
+int area;
+{
+	register struct here *h, *hl;
+
+	hl = NULL;
+	for (h = acthere; h != NULL; h = h->h_next)
+		if (getarea((char *) h) >= area) {
+			if (h->h_iop->io_name != NULL)
+				unlink(h->h_iop->io_name);
+			if (hl == NULL)
+				acthere = h->h_next;
+			else
+				hl->h_next = h->h_next;
+		} else
+			hl = h;
+}
+
+void
+tempname(tname)
+char *tname;
+{
+	static int inc;
+	register char *cp, *lp;
+
+	for (cp = tname, lp = "/tmp/shtm"; (*cp = *lp++) != '\0'; cp++)
+		;
+	lp = putn(getpid()*1000 + inc++);
+	for (; (*cp = *lp++) != '\0'; cp++)
+		;
+}
Index: /trunk/minix/commands/sh/sh6.c
===================================================================
--- /trunk/minix/commands/sh/sh6.c	(revision 9)
+++ /trunk/minix/commands/sh/sh6.c	(revision 9)
@@ -0,0 +1,8 @@
+#define Extern
+
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#include <setjmp.h>
+#include "sh.h"
+
Index: /trunk/minix/commands/simple/Makefile
===================================================================
--- /trunk/minix/commands/simple/Makefile	(revision 9)
+++ /trunk/minix/commands/simple/Makefile	(revision 9)
@@ -0,0 +1,1732 @@
+# Makefile for commands/simple.
+
+CFLAGS	= -D_MINIX -D_POSIX_SOURCE
+SYS	= ../..
+SERVERS = ../../servers
+CCLD	= $(CC) -i $(CFLAGS)
+CC	= exec cc
+
+# This Makefile is large, but that is because it lists all actions that must
+# be taken to compile and install all the simple commands.  If there were only
+# one command then it would look like this:
+#
+# ALL	= \
+#	cat \			need the 'cat' executable
+#
+# all:	$(ALL)			default rule, make all binaries
+#
+# cat:	cat.c			'cat' is made from 'cat.c'
+#	$(CCLD) -o $@ $?	compile 'cat.c' ($?) to 'cat' ($@)
+#	install -S 4kw $@	stack size is 8k (8086) or 16k (others)
+#
+# install:	\		rule to install all binaries
+#	/usr/bin/cat \		one can find 'cat' in /usr/bin
+#	/bin/cat \		important binaries are also in /bin
+#
+# /usr/bin/cat:	cat
+#	install -cs -o bin $? $@	copy 'cat' to '/usr/bin/cat' (-c),
+#					strip symbol table (-s)
+#
+# /bin/cat:	/usr/bin/cat
+#	install -lcs $? $@	install '/bin/cat' by linking (if possible)
+#				or copying (otherwise)
+#
+# Some of the binaries are installed under more than one name.  The extra
+# names are indented by one extra tab in the install rule.
+# If you want to add a command then insert it at the appropriate position
+# in sorted order.  Search around for the command just above or below the
+# the new command and add new rules for the new command near those places.
+# Observe four key things:
+#	What to make, how to make, what to install, how to install.
+
+ALL	= \
+	add_route \
+	arp \
+	at \
+	backup \
+	badblocks \
+	banner \
+	basename \
+	cal \
+	calendar \
+	cat \
+	cdiff \
+	cdprobe \
+	cgrep \
+	chmem \
+	chmod \
+	chown \
+	chroot \
+	ci \
+	cksum \
+	cleantmp \
+	cmp \
+	co \
+	comm \
+	compress \
+	cp \
+	crc \
+	cut \
+	date \
+	dd \
+	decomp16 \
+	dev2name \
+	devsize \
+	df \
+	dhrystone \
+	diff \
+	dirname \
+	du \
+	ed \
+	eject \
+	env \
+	expand \
+	factor \
+	fgrep \
+	file \
+	find \
+	finger \
+	fix \
+	fold \
+	fortune \
+	fsck \
+	fsck1 \
+	getty \
+	gomoku \
+	grep \
+	head \
+	host \
+	hostaddr \
+	id \
+	ifconfig \
+	ifdef \
+	in.fingerd \
+	in.rshd \
+	installx \
+	intr \
+	irdpd \
+	isoread \
+	join \
+	kill \
+	last \
+	leave \
+	life \
+	loadramdisk \
+	login \
+	look \
+	lp \
+	lpd \
+	ls \
+	mail \
+	man \
+	mesg \
+	mkdir \
+	mkfifo \
+	mkfs \
+	mknod \
+	mkproto \
+	mkswap \
+	modem \
+	mount \
+	mt \
+	nm \
+	newroot \
+	nonamed \
+	nice \
+	od \
+	passwd \
+	paste \
+	ping \
+	pr \
+	pr_routes \
+	progressbar \
+	prep \
+	printf \
+	printroot \
+	printenv \
+	proto \
+	pwd \
+	pwdauth \
+	ramdisk \
+	rarpd \
+	rcp \
+	rawspeed \
+	rdate \
+	readall \
+	rev \
+	readfs \
+	remsync \
+	rget \
+	rlogin \
+	rmdir \
+	rsh \
+	sed \
+	shar \
+	size \
+	sleep \
+	slip \
+	sort \
+	split \
+	stat \
+	strings \
+	strip \
+	stty \
+	su \
+	sum \
+	swapfs \
+	sync \
+	synctree \
+	sysenv \
+	tail \
+	tar \
+	tcpd \
+	tcpdp \
+	tcpstat \
+	tee \
+	term \
+	termcap \
+	tget \
+	time \
+	touch \
+	top \
+	tr \
+	truncate \
+	treecmp \
+	tsort \
+	ttt \
+	tty \
+	udpstat \
+	umount \
+	uname \
+	unexpand \
+	uniq \
+	update \
+	uud \
+	uue \
+	vol \
+	wc \
+	which \
+	who \
+	whoami \
+	write \
+	writeisofs \
+	xargs \
+	yes \
+	#
+
+all:	$(ALL)
+
+add_route:	add_route.c
+	$(CCLD) -o $@ add_route.c
+	@install -S 4kw $@
+
+arp:	arp.c
+	$(CCLD) -o $@ arp.c
+	@install -S 4kw $@
+
+at:	at.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+backup:	backup.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+badblocks:	badblocks.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+banner:	banner.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+basename:	basename.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+cal:	cal.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+calendar:	calendar.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+cat:	cat.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+cdiff:	cdiff.c
+	$(CCLD) -o $@ $?
+	@install -S 28kw $@
+
+cdprobe: cdprobe.c
+	$(CCLD) -o $@ $?
+	@install -S 28kw $@
+
+cgrep:	cgrep.c
+	$(CCLD) -o $@ $?
+	@install -S 5kw $@
+
+chmem:	chmem.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+chmod:	chmod.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+chown:	chown.c
+	$(CCLD) -o $@ $?
+	@install -S 16kw $@
+
+chroot:	chroot.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+ci:	ci.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+cksum:	cksum.c
+	$(CCLD) -o $@ $?
+	@install -S 8kw $@
+
+cleantmp:	cleantmp.c
+	$(CCLD) -o $@ $?
+	@install -S 8kw $@
+
+cmp:	cmp.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+co:	co.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+comm:	comm.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+compress:	compress.c
+	$(CCLD) -o $@ $?
+	@install -S 450k $@
+
+cp:    cp.c
+	$(CCLD) -o $@ $?
+	@install -S 32kw $@
+
+crc:	crc.c
+	$(CCLD) -o $@ $?
+	@install -S 8kw $@
+
+cut:	cut.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+date:	date.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+dd:	dd.c
+	$(CCLD) -o $@ $?
+	@install -S 20kw $@
+
+decomp16:	decomp16.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+dev2name:	dev2name.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+devsize:	devsize.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+df:	df.c
+	$(CCLD) -I$(SYS) -o $@ $?
+	@install -S 4kw $@
+
+dhrystone:	dhrystone.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+diff:	diff.c
+	$(CCLD) -o $@ $?
+	@install -S 40kw $@
+
+dirname:	dirname.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+du:	du.c
+	$(CCLD) -o $@ $?
+	@install -S 256kw $@
+
+ed:	ed.c
+	$(CCLD) -o $@ $?
+	@install -S 32kw $@
+
+eject:	eject.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+env:	env.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+expand:	expand.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+factor:	factor.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+fgrep:	fgrep.c
+	$(CCLD) -o $@ $?
+	@install -S 10kw $@
+
+file:	file.c
+	$(CCLD) -o $@ $?
+	@install -S 25kw $@
+
+find:	find.c
+	$(CCLD) -o $@ $?
+	@install -S 25kw $@
+
+finger:	finger.c
+	$(CCLD) -o $@ finger.c
+	@install -S 8kw $@
+
+fix:	fix.c
+	$(CCLD) -o $@ fix.c
+	@install -S 32kw $@
+
+fold:	fold.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+fortune:	fortune.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+fsck:	fsck.c
+	$(CCLD) -o $@ $?
+	@install -S 4096k $@
+
+fsck1:	fsck1.c
+	$(CCLD) -o $@ $?
+	@install -S 32kw $@
+
+getty:	getty.c /usr/include/minix/config.h
+	$(CCLD) -o $@ getty.c
+	@install -S 4kw $@
+
+gomoku:	gomoku.c
+	$(CCLD) -o $@ $? -lcurses
+	@install -S 8kw $@
+
+grep:	grep.c
+	$(CCLD) -o $@ $?
+	@install -S 32kw $@
+
+head:	head.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+host:	host.c
+	$(CCLD) -wo -o $@ host.c
+	@install -S 4kw $@
+
+hostaddr:	hostaddr.c
+	$(CCLD) -o $@ hostaddr.c
+	@install -S 8kw $@
+
+id:	id.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+ifconfig:	ifconfig.c
+	$(CCLD) -o $@ ifconfig.c
+	@install -S 4kw $@
+
+ifdef:	ifdef.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+in.fingerd:	in.fingerd.c
+	$(CCLD) -o $@ in.fingerd.c
+	@install -S 4kw $@
+
+in.rshd:	in.rshd.c
+	$(CCLD) -o $@ in.rshd.c
+	@install -S 4kw $@
+
+installx:	install.c	# Note: avoided confict with 'install' rule.
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+intr:	intr.c
+	$(CCLD) -o $@ intr.c
+	@install -S 4kw $@
+
+irdpd:	irdpd.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+isoread:	isoread.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+join:	join.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+kill:	kill.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+last:	last.c
+	$(CCLD) -o $@ $?
+	@install -S 5kw $@
+
+leave:	leave.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+life:	life.c
+	$(CCLD) -o $@ $? -lcurses
+	@install -S 15kw $@
+
+loadramdisk:	loadramdisk.c
+	$(CCLD) -o $@ $?
+	install -S 4kw $@
+
+login:	login.c
+	$(CCLD) -o $@ $?
+	install -S 4kw $@
+
+look:	look.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+lp:	lp.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+lpd:	lpd.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+ls:	ls.c
+	$(CCLD) -o $@ $?
+	@install -S 20kw $@
+
+mail:	mail.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+man:	man.c
+	$(CCLD) -o $@ $?
+	@install -S 10kw $@
+
+mesg:	mesg.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+mkdir:	mkdir.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+mkfifo:	mkfifo.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+mkfs:	mkfs.c
+	$(CCLD) -o $@ $?
+	@install -S 20kw $@
+
+mknod:	mknod.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+mkproto:	mkproto.c
+	$(CCLD) -o $@ $?
+	@install -S 20kw $@
+
+mkswap:	mkswap.c
+	$(CCLD) -I$(SYS) -o $@ $?
+	@install -S 4kw $@
+
+modem:	modem.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+mount:	mount.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+mt:	mt.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+newroot:	newroot.c
+	$(CCLD) -o $@ $?
+	@install -S 32kw $@
+
+nm:	nm.c
+	$(CCLD) -o $@ $?
+	@install -S 32kw $@
+
+nice:	nice.c
+	$(CCLD) -o $@ $?
+	@install -S 8kw $@
+
+nonamed:	nonamed.c
+	$(CCLD) -o $@ $?
+	@install -S 8kw $@
+
+od:	od.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+passwd:	passwd.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+paste:	paste.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+ping:	ping.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+pr:	pr.c
+	$(CCLD) -o $@ $?
+	@install -S 16kw $@
+
+pr_routes:	pr_routes.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+progressbar:	progressbar.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+prep:	prep.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+printf:	printf.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+printenv:	printenv.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+printroot:	printroot.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+proto:	proto.c
+	$(CCLD) -o $@ $?
+	@install -S 15kw $@
+
+pwd:	pwd.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+pwdauth:	pwdauth.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+ramdisk:	ramdisk.c
+	$(CCLD) -o $@ ramdisk.c
+	@install -S 4kw $@
+
+rarpd:	rarpd.c
+	$(CCLD) -o $@ rarpd.c
+	@install -S 4kw $@
+
+rcp:	rcp.c
+	$(CCLD) -o $@ rcp.c
+	@install -S 8kw $@
+
+rawspeed:	rawspeed.c
+	$(CCLD) -o $@ rawspeed.c
+	@install -S 512k $@
+
+rdate:	rdate.c
+	$(CCLD) -o $@ rdate.c
+	@install -S 8kw $@
+
+rev:	rev.c
+	$(CCLD) -o $@ rev.c
+	@install -S 8kw $@
+
+readall:	readall.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+readfs:	readfs.c
+	$(CCLD) -o $@ $?
+	@install -S 25kw $@
+
+remsync:	remsync.c
+	$(CCLD) -o $@ $?
+	@install -S 256k $@
+
+rget:	rget.c
+	$(CCLD) -o $@ $?
+	@install -S 8kw $@
+
+rlogin:	rlogin.c
+	$(CCLD) -o $@ $?
+	@install -S 8kw $@
+
+rmdir:	rmdir.c
+	$(CCLD) -o $@ $?
+	@install -S 15kw $@
+
+rsh:	rsh.c
+	$(CCLD) -o $@ rsh.c
+	@install -S 8kw $@
+
+sed:	sed.c
+	$(CCLD) -o $@ $?
+	@install -S 8kw $@
+
+shar:	shar.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+size:	size.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+sleep:	sleep.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+slip:	slip.c
+	$(CCLD) -o $@ $?
+	@install -S 20k $@
+
+sort:	sort.c
+	$(CCLD) -o $@ $?
+	@install -S 30kw $@
+
+split:	split.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+stat:	stat.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+strings:	strings.c
+	$(CCLD) -o $@ $?
+	@install -S 8kw $@
+
+strip:	strip.c
+	$(CCLD) -o $@ $?
+	@install -S 8kw $@
+
+stty:	stty.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+su:	su.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+sum:	sum.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+swapfs:	swapfs.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+sync:	sync.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+synctree:	synctree.c
+	$(CCLD) -o $@ -wo $?
+	install -S 256kw $@
+
+sysenv:	sysenv.c
+	$(CCLD) -o $@ -wo $?
+	@install -S 4kw $@
+
+tail:	tail.c
+	$(CCLD) -o $@ $?
+	@install -S 16kw $@
+
+tar:	tar.c
+	$(CCLD) -o $@ $?
+	@install -S 256kw $@
+
+tcpd:	tcpd.c
+	$(CCLD) -o $@ -DPARANOID=0 tcpd.c
+	@install -S 4kw $@
+
+tcpdp:	tcpd.c
+	$(CCLD) -o $@ -DPARANOID=1 tcpd.c
+	@install -S 8kw $@
+
+tcpstat:	tcpstat.c
+	$(CCLD) -o $@ -I$(SERVERS) tcpstat.c
+	@install -S 8kw $@
+
+tee:	tee.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+term:	term.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+termcap:	termcap.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+tget:	tget.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+time:	time.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+touch:	touch.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+top:	top.c
+	$(CCLD) -o $@ $? -lcurses
+
+tr:	tr.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+tsort:	tsort.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+treecmp:	treecmp.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+truncate:	truncate.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+ttt:	ttt.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+tty:	tty.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+udpstat:	udpstat.c
+	$(CCLD) -o $@ -I$(SERVERS) $?
+	@install -S 32k $@
+
+umount:	umount.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+uname:	uname.c /usr/include/minix/config.h
+	$(CCLD) -o $@ uname.c
+	@install -S 4kw $@
+
+unexpand:	unexpand.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+uniq:	uniq.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+update:	update.c
+	$(CCLD) -o $@ $?
+	@install -S 2kw $@
+
+uud:	uud.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+uue:	uue.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+vol:	vol.c
+	$(CCLD) -o $@ $?
+	@install -S 80k $@	# note: '-S' is upper limit to 'vol -m'
+
+wc:	wc.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+which:	which.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+who:	who.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+whoami:	whoami.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+write:	write.c
+	$(CCLD) -o $@ $?
+
+writeisofs:	writeisofs.c
+	$(CCLD) -o $@ $?
+
+xargs:	xargs.c
+	$(CCLD) -o $@ $?
+	@install -S 16kw $@
+
+yes:	yes.c
+	$(CCLD) -o $@ $?
+	@install -S 4kw $@
+
+install:	\
+	/usr/bin/add_route \
+		/usr/bin/del_route \
+	/usr/bin/arp \
+	/usr/bin/at \
+	/usr/bin/backup \
+	/usr/bin/restore \
+	/usr/bin/rev \
+	/usr/bin/badblocks \
+	/usr/bin/banner \
+	/usr/bin/basename \
+	/usr/bin/cal \
+	/usr/bin/calendar \
+	/usr/bin/cat \
+	/usr/bin/cdiff \
+	/usr/bin/cdprobe \
+	/usr/bin/cgrep \
+	/usr/bin/chmem \
+	/usr/bin/chmod \
+	/usr/bin/chown \
+	/bin/chroot \
+		/usr/bin/chgrp \
+	/usr/bin/ci \
+	/usr/bin/cksum \
+	/usr/bin/cleantmp \
+	/usr/bin/cmp \
+	/usr/bin/co \
+	/usr/bin/comm \
+	/usr/bin/compress \
+		/usr/bin/uncompress \
+		/usr/bin/zcat \
+	/bin/cp \
+	/bin/rm \
+	/bin/mv \
+	/bin/ln \
+	/usr/bin/cp \
+		/usr/bin/clone \
+		/usr/bin/cpdir \
+		/usr/bin/ln \
+		/usr/bin/mv \
+		/usr/bin/rm \
+		/bin/rm \
+	/usr/bin/crc \
+	/usr/bin/cut \
+	/usr/bin/date \
+	/usr/bin/dd \
+	/usr/bin/decomp16 \
+	/bin/dev2name \
+	/usr/bin/devsize \
+	/usr/bin/df \
+	/usr/bin/dhrystone \
+	/usr/bin/diff \
+	/usr/bin/dirname \
+	/usr/bin/du \
+	/usr/bin/ed \
+	/usr/bin/eject \
+	/usr/bin/env \
+	/usr/bin/expand \
+	/usr/bin/factor \
+	/usr/bin/fgrep \
+	/usr/bin/file \
+	/usr/bin/find \
+	/usr/bin/finger \
+	/usr/bin/fix \
+	/usr/bin/fold \
+	/usr/bin/fortune \
+	/usr/bin/fsck \
+	/usr/bin/fsck1 \
+	/bin/getty \
+	/usr/bin/getty \
+	/usr/bin/gomoku \
+	/usr/bin/grep \
+		/usr/bin/egrep \
+	/usr/bin/head \
+	/usr/bin/host \
+	/usr/bin/hostaddr \
+	/usr/bin/id \
+	/usr/bin/ifconfig \
+	/usr/bin/ifdef \
+	/usr/bin/in.fingerd \
+	/usr/bin/in.rshd \
+	/bin/install \
+	/usr/bin/install \
+	/usr/bin/intr \
+	/usr/bin/irdpd \
+	/usr/bin/isoread \
+		/usr/bin/isodir \
+		/usr/bin/isoinfo \
+	/usr/bin/join \
+	/usr/bin/kill \
+	/usr/bin/last \
+		/usr/bin/uptime \
+	/usr/bin/leave \
+	/usr/bin/life \
+	/usr/bin/loadramdisk \
+	/usr/bin/login \
+	/usr/bin/look \
+	/usr/bin/lp \
+	/usr/bin/lpd \
+	/usr/bin/ls \
+	/bin/ls \
+	/usr/bin/mail \
+	/usr/bin/man \
+	/usr/bin/mesg \
+	/usr/bin/mkdir \
+	/usr/bin/mkfifo \
+	/usr/bin/mkfs \
+	/usr/bin/mknod \
+	/usr/bin/mkproto \
+	/usr/bin/mkswap \
+	/usr/bin/modem \
+	/usr/bin/mount \
+	/usr/bin/mt \
+	/usr/bin/newroot \
+	/usr/bin/nm \
+	/usr/bin/nice \
+	/usr/bin/nonamed \
+	/usr/bin/od \
+	/usr/bin/passwd \
+		/usr/bin/chfn \
+		/usr/bin/chsh \
+	/usr/bin/paste \
+	/usr/bin/ping \
+	/usr/bin/pr \
+	/usr/bin/pr_routes \
+	/usr/bin/progressbar \
+	/usr/bin/prep \
+	/usr/bin/printf \
+	/usr/bin/printenv \
+	/usr/bin/printroot \
+	/usr/bin/proto \
+	/usr/bin/pwd \
+	/usr/lib/pwdauth \
+	/usr/bin/ramdisk \
+	/usr/bin/rarpd \
+	/usr/bin/rcp \
+	/usr/bin/rawspeed \
+	/usr/bin/rdate \
+	/usr/bin/readall \
+	/usr/bin/readlink \
+	/usr/bin/readfs \
+	/usr/bin/remsync \
+	/usr/bin/rget \
+		/usr/bin/rput \
+	/usr/bin/rlogin \
+	/usr/bin/rmdir \
+	/usr/bin/rsh \
+	/usr/bin/sed \
+	/bin/sed \
+	/usr/bin/shar \
+	/usr/bin/size \
+	/usr/bin/sleep \
+	/usr/bin/slip \
+	/usr/bin/sort \
+	/usr/bin/split \
+	/usr/bin/stat \
+		/usr/bin/fstat \
+	/usr/bin/strings \
+	/usr/bin/strip \
+	/usr/bin/stty \
+	/usr/bin/su \
+	/usr/bin/sum \
+	/usr/bin/swapfs \
+	/usr/bin/sync \
+	/usr/bin/synctree \
+	/usr/bin/sysenv \
+	/bin/sysenv \
+	/usr/bin/tail \
+	/usr/bin/tar \
+	/usr/bin/tcpd \
+	/usr/bin/tcpdp \
+	/usr/bin/tcpstat \
+	/usr/bin/tee \
+	/usr/bin/term \
+	/usr/bin/termcap \
+	/usr/bin/tget \
+	/usr/bin/time \
+	/usr/bin/top \
+	/usr/bin/touch \
+	/usr/bin/tr \
+	/usr/bin/treecmp \
+	/usr/bin/truncate \
+	/usr/bin/tsort \
+	/usr/bin/ttt \
+	/usr/bin/tty \
+	/usr/bin/udpstat \
+	/usr/bin/umount \
+	/usr/bin/uname \
+		/usr/bin/arch \
+	/usr/bin/unexpand \
+	/usr/bin/uniq \
+	/usr/bin/update \
+	/usr/bin/uud \
+		/usr/bin/uudecode \
+	/usr/bin/uue \
+		/usr/bin/uuencode \
+	/usr/bin/vol \
+	/usr/bin/wc \
+	/usr/bin/which \
+	/usr/bin/who \
+	/usr/bin/whoami \
+	/usr/bin/write \
+	/usr/bin/writeisofs \
+	/usr/bin/xargs \
+	/usr/bin/yes \
+	/usr/bin/udpstat \
+	/bin/cat \
+	/bin/date \
+	/bin/fsck \
+	/bin/intr \
+	/bin/mount \
+	/bin/printroot \
+	/bin/pwd \
+	/bin/sync \
+	/bin/umount \
+	#
+
+/usr/bin/add_route:	add_route
+	install -cs -o bin $? $@
+
+/usr/bin/del_route:	/usr/bin/add_route
+	install -l $? $@
+
+/usr/bin/arp:	arp
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/at:	at
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/backup:	backup
+	install -cs -o bin $? $@
+
+/usr/bin/restore:	/usr/bin/backup
+	install -l $? $@
+
+/usr/bin/badblocks:	badblocks
+	install -cs -o bin $? $@
+
+/usr/bin/banner:	banner
+	install -cs -o bin $? $@
+
+/usr/bin/basename:	basename
+	install -cs -o bin $? $@
+
+/usr/bin/cal:	cal
+	install -cs -o bin $? $@
+
+/usr/bin/calendar:	calendar
+	install -cs -o bin $? $@
+
+/usr/bin/cat:	cat
+	install -cs -o bin $? $@
+
+/usr/bin/cdiff:	cdiff
+	install -cs -o bin $? $@
+
+/usr/bin/cdprobe: cdprobe
+	install -cs -o bin $? $@
+
+/usr/bin/cgrep:	cgrep
+	install -cs -o bin $? $@
+
+/usr/bin/chmem:	chmem
+	install -cs -o bin $? $@
+
+/usr/bin/chmod:	chmod
+	install -cs -o bin $? $@
+
+/usr/bin/chown:	chown
+	install -cs -o bin $? $@
+
+/bin/chroot:	chroot
+	install -cs -o bin $? $@
+
+/usr/bin/chgrp:	/usr/bin/chown
+	install -l $? $@
+
+/usr/bin/ci:	ci
+	install -cs -o bin $? $@
+
+/usr/bin/cksum:	cksum
+	install -cs -o bin $? $@
+
+/usr/bin/cleantmp:	cleantmp
+	install -cs -o bin $? $@
+
+/usr/bin/cmp:	cmp
+	install -cs -o bin $? $@
+
+/usr/bin/co:	co
+	install -cs -o bin $? $@
+
+/usr/bin/comm:	comm
+	install -cs -o bin $? $@
+
+/usr/bin/compress:	compress
+	install -cs -o bin $? $@
+
+/usr/bin/uncompress /usr/bin/zcat:	/usr/bin/compress
+	install -l $? $@
+
+/bin/cp:	cp
+	install -cs -o bin $? $@
+
+/usr/bin/cp:	cp
+	install -cs -o bin $? $@
+
+/usr/bin/clone /usr/bin/cpdir \
+/usr/bin/ln /usr/bin/mv /usr/bin/rm:	/usr/bin/cp
+	install -l $? $@
+
+/bin/ln /bin/mv /bin/rm:	/bin/cp
+	install -l $? $@
+
+/usr/bin/crc:	crc
+	install -cs -o bin $? $@
+
+/usr/bin/cut:	cut
+	install -cs -o bin $? $@
+
+/usr/bin/date:	date
+	install -cs -o bin $? $@
+
+/usr/bin/dd:	dd
+	install -cs -o bin $? $@
+
+/bin/dev2name:	dev2name
+	install -cs -o bin $? $@
+
+/usr/bin/devsize:	devsize
+	install -cs -o bin $? $@
+
+/usr/bin/decomp16:	decomp16
+	install -cs -o bin $? $@
+
+/usr/bin/df:	df
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/dhrystone:	dhrystone
+	install -cs -o bin $? $@
+
+/usr/bin/diff:	diff
+	install -cs -o bin $? $@
+
+/usr/bin/dirname:	dirname
+	install -cs -o bin $? $@
+
+/usr/bin/du:	du
+	install -cs -o bin $? $@
+
+/usr/bin/ed:	ed
+	install -cs -o bin $? $@
+
+/usr/bin/eject:	eject
+	install -cs -o bin $? $@
+
+/usr/bin/env:	env
+	install -cs -o bin $? $@
+
+/usr/bin/expand:	expand
+	install -cs -o bin $? $@
+
+/usr/bin/factor:	factor
+	install -cs -o bin $? $@
+
+/usr/bin/fgrep:	fgrep
+	install -cs -o bin $? $@
+
+/usr/bin/file:	file
+	install -cs -o bin $? $@
+
+/usr/bin/find:	find
+	install -cs -o bin $? $@
+
+/usr/bin/finger:	finger
+	install -cs -o bin $? $@
+
+/usr/bin/fix:	fix
+	install -cs -o bin $? $@
+
+/usr/bin/fold:	fold
+	install -cs -o bin $? $@
+
+/usr/bin/fortune:	fortune
+	install -cs -o bin $? $@
+
+/usr/bin/fsck:	fsck
+	install -cs -o bin $? $@
+
+/usr/bin/fsck1:	fsck1
+	install -cs -o bin $? $@
+
+/bin/getty:	getty
+	install -cs -o bin $? $@
+
+/usr/bin/getty:	getty
+	install -cs -o bin $? $@
+
+/usr/bin/gomoku:	gomoku
+	install -cs -o bin $? $@
+
+/usr/bin/grep:	grep
+	install -cs -o bin $? $@
+
+/usr/bin/egrep:	/usr/bin/grep
+	install -l $? $@
+
+/usr/bin/head:	head
+	install -cs -o bin $? $@
+
+/usr/bin/host:	host
+	install -cs -o bin $? $@
+
+/usr/bin/hostaddr:	hostaddr
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/id:	id
+	install -cs -o bin $? $@
+
+/usr/bin/ifconfig:	ifconfig
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/ifdef:	ifdef
+	install -cs -o bin $? $@
+
+/usr/bin/in.fingerd:	in.fingerd
+	install -cs -o bin $? $@
+
+/usr/bin/in.rshd:	in.rshd
+	install -cs -o bin $? $@
+
+/bin/install:	installx
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/install:	installx
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/intr:	intr
+	install -cs -o bin $? $@
+
+/usr/bin/irdpd:	irdpd
+	install -cs -o bin $? $@
+
+/usr/bin/isoread:	isoread
+	install -cs -o bin $? $@
+
+/usr/bin/isodir /usr/bin/isoinfo:	/usr/bin/isoread
+	install -l $? $@
+
+/usr/bin/join:	join
+	install -cs -o bin $? $@
+
+/usr/bin/kill:	kill
+	install -cs -o bin $? $@
+
+/usr/bin/last:	last
+	install -cs -o bin $? $@
+
+/usr/bin/uptime:	/usr/bin/last
+	install -l $? $@
+
+/usr/bin/leave:	leave
+	install -cs -o bin $? $@
+
+/usr/bin/life:	life
+	install -cs -o bin $? $@
+
+/usr/bin/loadramdisk:	loadramdisk
+	install -cs -o bin $? $@
+
+/usr/bin/login:	login
+	install -cs -o bin $? $@
+
+/usr/bin/look:	look
+	install -cs -o bin $? $@
+
+/usr/bin/lp:	lp
+	install -cs -o bin $? $@
+
+/usr/bin/lpd:	lpd
+	install -cs -o daemon -m 4755 $? $@
+
+/usr/bin/ls:	ls
+	install -cs -o bin $? $@
+
+/bin/ls:	ls
+	install -cs -o bin $? $@
+
+/usr/bin/mail:	mail
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/man:	man
+	install -cs -o bin $? $@
+
+/usr/bin/mesg:	mesg
+	install -cs -o bin $? $@
+
+/usr/bin/mkdir:	mkdir
+	install -cs -o bin $? $@
+
+/usr/bin/mkfifo:	mkfifo
+	install -cs -o bin $? $@
+
+/usr/bin/mkfs:	mkfs
+	install -cs -o bin $? $@
+
+/usr/bin/mknod:	mknod
+	install -cs -o bin $? $@
+
+/usr/bin/mkproto:	mkproto
+	install -cs -o bin $? $@
+
+/usr/bin/mkswap:	mkswap
+	install -cs -o bin $? $@
+
+/usr/bin/modem:	modem
+	install -cs -o bin $? $@
+
+/usr/bin/mount:	mount
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/mt:	mt
+	install -cs -o bin $? $@
+
+/usr/bin/newroot:	newroot
+	install -cs -o bin $? $@
+
+/usr/bin/nm:	nm
+	install -cs -o bin $? $@
+
+/usr/bin/nice:	nice
+	install -cs -o bin $? $@
+
+/usr/bin/nonamed:	nonamed
+	install -cs -o bin $? $@
+
+/usr/bin/od:	od
+	install -cs -o bin $? $@
+
+/usr/bin/passwd:	passwd
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/chfn /usr/bin/chsh:	/usr/bin/passwd
+	install -l $? $@
+
+/usr/bin/paste:	paste
+	install -cs -o bin $? $@
+
+/usr/bin/ping:	ping
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/pr:	pr
+	install -cs -o bin $? $@
+
+/usr/bin/pr_routes:	pr_routes
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/progressbar:	progressbar
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/prep:	prep
+	install -cs -o bin $? $@
+
+/usr/bin/printf:	printf
+	install -cs -o bin $? $@
+
+/usr/bin/printenv:	printenv
+	install -cs -o bin $? $@
+
+/usr/bin/printroot:	printroot
+	install -cs -o bin $? $@
+
+/usr/bin/proto:	proto
+	install -cs -o bin $? $@
+
+/usr/bin/pwd:	pwd
+	install -cs -o bin $? $@
+
+/usr/lib/pwdauth:	pwdauth
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/ramdisk:	ramdisk
+	install -cs -o bin $? $@
+
+/usr/bin/rarpd:	rarpd
+	install -cs -o bin $? $@
+
+/usr/bin/rcp:	rcp
+	install -cs -o bin $? $@
+
+/usr/bin/rawspeed:	rawspeed
+	install -cs -o bin $? $@
+
+/usr/bin/rdate:	rdate
+	install -cs -o bin $? $@
+
+/usr/bin/readall:	readall
+	install -cs -o bin $? $@
+
+/usr/bin/readlink:	/usr/bin/stat
+	install -l $? $@
+
+/usr/bin/readfs:	readfs
+	install -cs -o bin $? $@
+
+/usr/bin/remsync:	remsync
+	install -cs -o bin $? $@
+
+/usr/bin/rev:	rev
+	install -cs -o bin $? $@
+
+/usr/bin/rget:	rget
+	install -cs -o bin $? $@
+
+/usr/bin/rput:	/usr/bin/rget
+	install -l $? $@
+
+/usr/bin/rlogin:	rlogin
+	install -cs -o bin $? $@
+
+/usr/bin/rmdir:	rmdir
+	install -cs -o bin $? $@
+
+/usr/bin/rsh:	rsh
+	install -cs -o bin $? $@
+
+/usr/bin/sed:	sed
+	install -cs -o bin $? $@
+
+/bin/sed:	sed
+	install -cs -o bin $? $@
+
+/usr/bin/shar:	shar
+	install -cs -o bin $? $@
+
+/usr/bin/size:	size
+	install -cs -o bin $? $@
+
+/usr/bin/sleep:	sleep
+	install -cs -o bin $? $@
+
+/usr/bin/slip:	slip
+	install -cs -o bin $? $@
+
+/usr/bin/sort:	sort
+	install -cs -o bin $? $@
+
+/usr/bin/split:	split
+	install -cs -o bin $? $@
+
+/usr/bin/stat:	stat
+	install -cs -o bin $? $@
+
+/usr/bin/fstat:	/usr/bin/stat
+	install -l $? $@
+
+/usr/bin/strings:	strings
+	install -cs -o bin $? $@
+
+/usr/bin/strip:	strip
+	install -cs -o bin $? $@
+
+/usr/bin/stty:	stty
+	install -cs -o bin $? $@
+
+/usr/bin/su:	su
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/sum:	sum
+	install -cs -o bin $? $@
+
+/usr/bin/swapfs:	swapfs
+	install -cs -o bin $? $@
+
+/usr/bin/sync:	sync
+	install -cs -o bin $? $@
+
+/usr/bin/synctree:	synctree
+	install -cs -o bin $? $@
+
+/bin/sysenv:	sysenv
+	install -cs -o bin $? $@
+
+/usr/bin/sysenv:	sysenv
+	install -cs -o bin $? $@
+
+/usr/bin/tail:	tail
+	install -cs -o bin $? $@
+
+/usr/bin/tar:	tar
+	install -cs -o bin $? $@
+
+/usr/bin/tcpd:	tcpd
+	install -cs -o bin $? $@
+
+/usr/bin/tcpdp:	tcpdp
+	install -cs -o bin $? $@
+
+/usr/bin/tcpstat:	tcpstat
+	install -cs -o bin $? $@
+
+/usr/bin/tee:	tee
+	install -cs -o bin $? $@
+
+/usr/bin/term:	term
+	install -cs -o bin -g uucp -m 2755 $? $@
+
+/usr/bin/termcap:	termcap
+	install -cs -o bin $? $@
+
+/usr/bin/tget:	tget
+	install -cs -o bin $? $@
+
+/usr/bin/time:	time
+	install -cs -o bin $? $@
+
+/usr/bin/top:	top
+	install -cs -o bin $? $@
+
+/usr/bin/touch:	touch
+	install -cs -o bin $? $@
+
+/usr/bin/tr:	tr
+	install -cs -o bin $? $@
+
+/usr/bin/treecmp:	treecmp
+	install -cs -o bin $? $@
+
+/usr/bin/truncate:	truncate
+	install -cs -o bin $? $@
+
+/usr/bin/tsort:	tsort
+	install -cs -o bin $? $@
+
+/usr/bin/ttt:	ttt
+	install -cs -o bin $? $@
+
+/usr/bin/tty:	tty
+	install -cs -o bin $? $@
+
+/usr/bin/udpstat:	udpstat
+	install -cs -o bin $? $@
+
+/usr/bin/umount:	umount
+	install -cs -o root -m 4755 $? $@
+
+/usr/bin/uname:	uname
+	install -cs -o bin $? $@
+
+/usr/bin/arch:	/usr/bin/uname
+	install -l $? $@
+
+/usr/bin/unexpand:	unexpand
+	install -cs -o bin $? $@
+
+/usr/bin/uniq:	uniq
+	install -cs -o bin $? $@
+
+/usr/bin/update:	update
+	install -cs -o bin $? $@
+
+/usr/bin/uud:	uud
+	install -cs -o bin $? $@
+
+/usr/bin/uudecode:	/usr/bin/uud
+	install -l $? $@
+
+/usr/bin/uue:	uue
+	install -cs -o bin $? $@
+
+/usr/bin/uuencode:	/usr/bin/uue
+	install -l $? $@
+
+/usr/bin/vol:	vol
+	install -cs -o bin $? $@
+
+/usr/bin/wc:	wc
+	install -cs -o bin $? $@
+
+/usr/bin/which:	which
+	install -cs -o bin $? $@
+
+/usr/bin/who:	who
+	install -cs -o bin $? $@
+
+/usr/bin/whoami:	whoami
+	install -cs -o bin $? $@
+
+/usr/bin/write:	write
+	install -cs -o bin -g tty -m 2755 $? $@
+
+/usr/bin/writeisofs:	writeisofs
+	install -cs -S 2M -o bin $? $@
+
+/usr/bin/xargs:	xargs
+	install -cs -o bin $? $@
+
+/usr/bin/yes:	yes
+	install -cs -o bin $? $@
+
+/bin/cat:	/usr/bin/cat
+	install -lcs $? $@
+
+/bin/date:	/usr/bin/date
+	install -lcs $? $@
+
+/bin/fsck:	/usr/bin/fsck
+	install -lcs $? $@
+
+/bin/intr:	/usr/bin/intr
+	install -lcs $? $@
+
+/bin/mount:	/usr/bin/mount
+	install -lcs $? $@
+
+/bin/printroot:	/usr/bin/printroot
+	install -lcs $? $@
+
+/bin/pwd:	/usr/bin/pwd
+	install -lcs $? $@
+
+/bin/sync:	/usr/bin/sync
+	install -lcs $? $@
+
+/bin/umount:	/usr/bin/umount
+	install -lcs $? $@
+
+clean:
+	rm -rf $(ALL) a.out core
Index: /trunk/minix/commands/simple/add_route.c
===================================================================
--- /trunk/minix/commands/simple/add_route.c	(revision 9)
+++ /trunk/minix/commands/simple/add_route.c	(revision 9)
@@ -0,0 +1,347 @@
+/*
+add_route.c
+
+Created August 7, 1991 by Philip Homburg
+*/
+
+#define _POSIX_C_SOURCE	2
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <net/hton.h>
+#include <net/netlib.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/route.h>
+#include <net/gen/socket.h>
+#include <net/gen/ip_io.h>
+
+static char *prog_name;
+static enum { ADD, DEL } action;
+
+static void usage(void);
+static int name_to_ip(char *name, ipaddr_t *addr);
+static int parse_cidr(char *cidr, ipaddr_t *addr, ipaddr_t *mask);
+
+int main(int argc, char *argv[])
+{
+	struct netent *netent;
+	ipaddr_t gateway, destination, netmask, defaultmask=0;
+	u8_t high_byte;
+	nwio_route_t route;
+	int ip_fd, itab;
+	int r;
+	int metric;
+	char *check;
+	char *ip_device;
+	char *netmask_str, *metric_str, *destination_str, *gateway_str;
+	int c;
+	char *d_arg, *g_arg, *m_arg, *n_arg, *I_arg;
+	int i_flag, o_flag, D_flag, v_flag;
+	int cidr;
+
+	prog_name= strrchr(argv[0], '/');
+	if (prog_name == NULL) prog_name= argv[0]; else prog_name++;
+
+	if (strcmp(prog_name, "add_route") == 0)
+		action= ADD;
+	else if (strcmp(prog_name, "del_route") == 0)
+		action= DEL;
+	else
+	{
+		fprintf(stderr, "Don't know what to do when named '%s'\n",
+			prog_name);
+		exit(1);
+	}
+
+	i_flag= 0;
+	o_flag= 0;
+	D_flag= 0;
+	v_flag= 0;
+	g_arg= NULL;
+	d_arg= NULL;
+	m_arg= NULL;
+	n_arg= NULL;
+	I_arg= NULL;
+	while ((c= getopt(argc, argv, "iovDg:d:m:n:I:?")) != -1)
+	{
+		switch(c)
+		{
+		case 'i':
+			if (i_flag)
+				usage();
+			i_flag= 1;
+			break;
+		case 'o':
+			if (o_flag)
+				usage();
+			o_flag= 1;
+			break;
+		case 'v':
+			if (v_flag)
+				usage();
+			v_flag= 1;
+			break;
+		case 'D':
+			if (D_flag)
+				usage();
+			D_flag= 1;
+			break;
+		case 'g':
+			if (g_arg)
+				usage();
+			g_arg= optarg;
+			break;
+		case 'd':
+			if (d_arg)
+				usage();
+			d_arg= optarg;
+			break;
+		case 'm':
+			if (m_arg)
+				usage();
+			m_arg= optarg;
+			break;
+		case 'n':
+			if (n_arg)
+				usage();
+			n_arg= optarg;
+			break;
+		case 'I':
+			if (I_arg)
+				usage();
+			I_arg= optarg;
+			break;
+		case '?':
+			usage();
+		default:
+			fprintf(stderr, "%s: getopt failed\n", prog_name);
+			exit(1);
+		}
+	}
+	if (optind != argc)
+		usage();
+	if (i_flag && o_flag)
+		usage();
+	itab= i_flag;
+
+	if (i_flag)
+	{
+		if (g_arg == NULL || d_arg == NULL || m_arg == NULL)
+			usage();
+	}
+	else
+	{
+		if (g_arg == NULL || (d_arg == NULL && n_arg != NULL))
+		{
+			usage();
+		}
+	}
+		
+	gateway_str= g_arg;
+	destination_str= d_arg;
+	metric_str= m_arg;
+	netmask_str= n_arg;
+	ip_device= I_arg;
+
+	if (!name_to_ip(gateway_str, &gateway))
+	{
+		fprintf(stderr, "%s: unknown host '%s'\n", prog_name,
+								gateway_str);
+		exit(1);
+	}
+
+	destination= 0;
+	netmask= 0;
+	cidr= 0;
+
+	if (destination_str)
+	{
+		if (parse_cidr(destination_str, &destination, &netmask))
+			cidr= 1;
+		else if (inet_aton(destination_str, &destination))
+			;
+		else if ((netent= getnetbyname(destination_str)) != NULL)
+			destination= netent->n_net;
+		else if (!name_to_ip(destination_str, &destination))
+		{
+			fprintf(stderr, "%s: unknown network/host '%s'\n",
+				prog_name, destination_str);
+			exit(1);
+		}
+		high_byte= *(u8_t *)&destination;
+		if (!(high_byte & 0x80))	/* class A or 0 */
+		{
+			if (destination)
+				defaultmask= HTONL(0xff000000);
+		}
+		else if (!(high_byte & 0x40))	/* class B */
+		{
+			defaultmask= HTONL(0xffff0000);
+		}
+		else if (!(high_byte & 0x20))	/* class C */
+		{
+			defaultmask= HTONL(0xffffff00);
+		}
+		else				/* class D is multicast ... */
+		{
+			fprintf(stderr, "%s: Warning: Martian address '%s'\n",
+				prog_name, inet_ntoa(destination));
+			defaultmask= HTONL(0xffffffff);
+		}
+		if (destination & ~defaultmask)
+		{
+			/* host route */
+			defaultmask= HTONL(0xffffffff);
+		}
+		if (!cidr)
+			netmask= defaultmask;
+	}
+
+	if (netmask_str)
+	{
+		if (cidr)
+			usage();
+		if (inet_aton(netmask_str, &netmask) == 0)
+		{
+			fprintf(stderr, "%s: illegal netmask'%s'\n", prog_name,
+				netmask_str);
+			exit(1);
+		}
+	}
+
+	if (metric_str)
+	{
+		metric= strtol(metric_str, &check, 0);
+		if (check[0] != '\0' || metric < 1)
+		{
+			fprintf(stderr, "%s: illegal metric %s\n",
+				prog_name, metric_str);
+		}
+	}
+	else
+		metric= 1;
+		
+	if (!ip_device)
+		ip_device= getenv("IP_DEVICE");
+	if (!ip_device)
+		ip_device= IP_DEVICE;
+
+	ip_fd= open(ip_device, O_RDWR);
+	if (ip_fd == -1)
+	{
+		fprintf(stderr, "%s: unable to open('%s'): %s\n",
+			prog_name, ip_device, strerror(errno));
+		exit(1);
+	}
+
+	if (v_flag)
+	{
+		printf("%s %s route to %s ",
+			action == ADD ? "adding" : "deleting",
+			itab ? "input" : "output",
+			inet_ntoa(destination));
+		printf("with netmask %s ", inet_ntoa(netmask));
+		printf("using gateway %s", inet_ntoa(gateway));
+		if (itab && action == ADD)
+			printf(" at distance %d", metric);
+		printf("\n");
+	}
+
+	route.nwr_ent_no= 0;
+	route.nwr_dest= destination;
+	route.nwr_netmask= netmask;
+	route.nwr_gateway= gateway;
+	route.nwr_dist= action == ADD ? metric : 0;
+	route.nwr_flags= (action == DEL && D_flag) ? 0 : NWRF_STATIC;
+	route.nwr_pref= 0;
+	route.nwr_mtu= 0;
+
+	if (action == ADD)
+		r= ioctl(ip_fd, itab ? NWIOSIPIROUTE : NWIOSIPOROUTE, &route);
+	else
+		r= ioctl(ip_fd, itab ? NWIODIPIROUTE : NWIODIPOROUTE, &route);
+	if (r == -1)
+	{
+		fprintf(stderr, "%s: NWIO%cIP%cROUTE: %s\n",
+			prog_name,
+			action == ADD ? 'S' : 'D',
+			itab ? 'I' : 'O',
+			strerror(errno));
+		exit(1);
+	}
+	return(0);
+}
+
+static void usage(void)
+{
+	fprintf(stderr,
+		"Usage: %s\n"
+		"\t[-o] %s-g gw [-d dst [-n netmask]] %s[-I ipdev] [-v]\n"
+		"\t-i %s-g gw -d dst [-n netmask] %s[-I ipdev] [-v]\n"
+		"Note: <dst> may be in CIDR notation\n",
+		prog_name,
+		action == DEL ? "[-D] " : "",
+		action == ADD ? "[-m metric] " : "",
+		action == DEL ? "[-D] " : "",
+		action == ADD ? "-m metric " : ""
+	);
+	exit(1);
+}
+
+static int name_to_ip(char *name, ipaddr_t *addr)
+{
+	/* Translate a name to an IP address.  Try first with inet_aton(), then
+	 * with gethostbyname().  (The latter can also recognize an IP address,
+	 * but only decimals with at least one dot).)
+	 */
+	struct hostent *hostent;
+
+	if (!inet_aton(name, addr)) {
+		if ((hostent= gethostbyname(name)) == NULL) return 0;
+		if (hostent->h_addrtype != AF_INET) return 0;
+		if (hostent->h_length != sizeof(*addr)) return 0;
+		memcpy(addr, hostent->h_addr, sizeof(*addr));
+	}
+	return 1;
+}
+
+static int parse_cidr(char *cidr, ipaddr_t *addr, ipaddr_t *mask)
+{
+	char *slash, *check;
+	ipaddr_t a;
+	int ok;
+	unsigned long len;
+
+	if ((slash= strchr(cidr, '/')) == NULL)
+		return 0;
+
+	*slash++= 0;
+	ok= 1;
+
+	if (!inet_aton(cidr, &a))
+		ok= 0;
+
+	len= strtoul(slash, &check, 10);
+	if (check == slash || *check != 0 || len > 32)
+		ok= 0;
+
+	*--slash= '/';
+	if (!ok)
+		return 0;
+	*addr= a;
+	*mask= htonl(len == 0 ? 0 : (0xFFFFFFFF << (32-len)) & 0xFFFFFFFF);
+	return 1;
+}
+
+/*
+ * $PchId: add_route.c,v 1.6 2001/04/20 10:45:07 philip Exp $
+ */
Index: /trunk/minix/commands/simple/arp.c
===================================================================
--- /trunk/minix/commands/simple/arp.c	(revision 9)
+++ /trunk/minix/commands/simple/arp.c	(revision 9)
@@ -0,0 +1,473 @@
+/*
+arp.c
+
+Created:	Jan 2001 by Philip Homburg <philip@f-mnx.phicoh.com>
+
+Manipulate ARP table
+*/
+
+#define _POSIX_C_SOURCE 2
+#define _MINIX_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+
+#include <net/netlib.h>
+#include <net/gen/ether.h>
+#include <net/gen/if_ether.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/ip_io.h>
+#include <net/gen/netdb.h>
+#include <net/gen/socket.h>
+
+#include <net/gen/arp_io.h>
+
+char *progname;
+static int ipfd= -1;
+static int do_setuid= 0;
+
+static void do_open(char *devname);
+static void show_one(char *hostname, int do_num);
+static void show_all(int do_num);
+static void print_one(ipaddr_t ipaddr, nwio_arp_t *arpp, int do_num);
+static void delete_all(void);
+static void delete(char *hostname);
+static void do_set(char *hostname, char *ethername, int temp, int pub,
+	int optdelete);
+static ipaddr_t nametoipaddr(char *hostname);
+static void fatal(char *fmt, ...);
+static void usage(void);
+
+int main(int argc, char *argv[])
+{
+	int c;
+	char *hostname, *ethername;
+	int do_temp, do_pub;
+	int a_flag, d_flag, n_flag, s_flag, S_flag;
+	char *I_arg;
+
+	(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
+
+	a_flag= d_flag= n_flag= s_flag= S_flag= 0;
+	I_arg= NULL;
+	while(c= getopt(argc, argv, "adnsS?I:"), c != -1)
+	{
+		switch(c)
+		{
+		case '?':	usage();
+		case 'a':	a_flag= 1; break;
+		case 'd':	d_flag= 1; break;
+		case 'n':	n_flag= 1; break;
+		case 's':	s_flag= 1; break;
+		case 'S':	S_flag= 1; break;
+		case 'I':	I_arg= optarg; break;
+		default:	fatal("getopt failed: '%c'", c);
+		}
+	}
+
+	hostname= NULL;		/* lint */
+	ethername= NULL;	/* lint */
+	do_temp= do_pub= 0;	/* lint */
+
+	if (n_flag + d_flag + s_flag + S_flag > 1)
+		usage();
+	if (s_flag || S_flag)
+	{
+		if (optind >= argc) usage();
+		hostname= argv[optind++];
+
+		if (optind >= argc) usage();
+		ethername= argv[optind++];
+
+		do_temp= do_pub= 0;
+		while (optind < argc) 
+		{
+			if (strcasecmp(argv[optind], "temp") == 0)
+			{
+				do_temp= 1;
+				optind++;
+				continue;
+			}
+			if (strcasecmp(argv[optind], "pub") == 0)
+			{
+				do_pub= 1;
+				optind++;
+				continue;
+			}
+			usage();
+		}
+	}
+	else if (d_flag)
+	{
+		if (!a_flag)
+		{
+			if (optind >= argc)
+				usage();
+			hostname= argv[optind++];
+			if (optind != argc)
+				usage();
+		}
+	}
+	else if (a_flag)
+	{
+		if (optind != argc)
+			usage();
+		do_setuid= 1;
+	}
+	else
+	{
+		if (optind >= argc)
+			usage();
+		hostname= argv[optind++];
+		if (optind != argc)
+			usage();
+		do_setuid= 1;
+	}
+
+	do_open(I_arg);
+	if (d_flag)
+	{
+		if (a_flag)
+			delete_all();
+		else
+			delete(hostname);
+	}
+	else if (s_flag || S_flag)
+		do_set(hostname, ethername, do_temp, do_pub, S_flag);
+	else if (a_flag)
+		show_all(n_flag);
+	else
+		show_one(hostname, n_flag);
+	exit(0);
+}
+
+static void do_open(char *devname)
+{
+	size_t l;
+	char *check;
+
+	if (do_setuid && devname)
+	{
+		/* Only strings that consist of IP_DEVICE optionally 
+		 * followed by a number are allowed.
+		 */
+		l= strlen(IP_DEVICE);
+		if (strncmp(devname, IP_DEVICE, l) != 0)
+			do_setuid= 0;
+		else if (strlen(devname) == l)
+			; /* OK */
+		else
+		{
+			strtoul(devname+l, &check, 10);
+			if (check[0] != '\0')
+				do_setuid= 0;
+		}
+	}
+	if (!devname)
+		devname= IP_DEVICE;
+	if (!do_setuid)
+	{
+		setuid(getuid());
+		setgid(getgid());
+	}
+	ipfd= open(devname, O_RDWR);
+	if (ipfd == -1)
+		fatal("unable to open '%s': %s", devname, strerror(errno));
+}
+
+static void show_one(char *hostname, int do_num)
+{
+	int r;
+	ipaddr_t ipaddr;
+	nwio_arp_t arp;
+
+	ipaddr= nametoipaddr(hostname);
+
+	arp.nwa_ipaddr= ipaddr;
+	r= ioctl(ipfd, NWIOARPGIP, &arp);
+	if (r == -1 && errno == ENOENT)
+	{
+		print_one(ipaddr, NULL, do_num);
+		exit(1);
+	}
+	if (r == -1)
+		fatal("NWIOARPGIP failed: %s", strerror(errno));
+	print_one(ipaddr, &arp, do_num);
+}
+
+static void show_all(int do_num)
+{
+	int ind, max, i, r;
+	nwio_arp_t *arptab;
+	nwio_arp_t arp;
+
+	/* First get all entries */
+	max= 10;
+	ind= 0;
+	arptab= malloc(max * sizeof(*arptab));
+	if (arptab == NULL)
+	{
+		fatal("out of memory, can't get %d bytes",
+			max*sizeof(*arptab));
+	}
+	arp.nwa_entno= 0;
+	for (;;)
+	{
+		if (ind == max)
+		{
+			max *= 2;
+			arptab= realloc(arptab, max * sizeof(*arptab));
+			if (!arptab)
+			{
+				fatal("out of memory, can't get %d bytes",
+					max*sizeof(*arptab));
+			}
+		}
+		r= ioctl(ipfd, NWIOARPGNEXT, &arp);
+		if (r == -1 && errno == ENOENT)
+			break;
+		if (r == -1)
+			fatal("NWIOARPGNEXT failed: %s", strerror(errno));
+		arptab[ind]= arp;
+		ind++;
+	}
+
+	for (i= 0; i<ind; i++)
+		print_one(0, &arptab[i], do_num);
+}
+
+static void print_one(ipaddr_t ipaddr, nwio_arp_t *arpp, int do_num)
+{
+	u32_t flags;
+	struct hostent *he;
+
+	if (arpp)
+		ipaddr= arpp->nwa_ipaddr;
+	if (!do_num)
+		he= gethostbyaddr((char *)&ipaddr, sizeof(ipaddr), AF_INET);
+	else
+		he= NULL;
+	if (he)
+		printf("%s (%s)", he->h_name, inet_ntoa(ipaddr));
+	else
+		printf("%s", inet_ntoa(ipaddr));
+	if (!arpp)
+	{
+		printf(" -- no entry\n");
+		return;
+	}
+	flags= arpp->nwa_flags;
+	if (flags & NWAF_INCOMPLETE)
+		printf(" is incomplete");
+	else if (flags & NWAF_DEAD)
+		printf(" is dead");
+	else
+	{
+		printf(" is at %s", ether_ntoa(&arpp->nwa_ethaddr));
+		if (flags & NWAF_PERM)
+			printf(" permanent");
+		if (flags & NWAF_PUB)
+			printf(" published");
+	}
+	printf("\n");
+}
+
+static void delete_all(void)
+{
+	int ind, max, i, r;
+	nwio_arp_t *arptab;
+	nwio_arp_t arp;
+
+	/* First get all entries */
+	max= 10;
+	ind= 0;
+	arptab= malloc(max * sizeof(*arptab));
+	if (arptab == NULL)
+	{
+		fatal("out of memory, can't get %d bytes",
+			max*sizeof(*arptab));
+	}
+	arp.nwa_entno= 0;
+	for (;;)
+	{
+		if (ind == max)
+		{
+			max *= 2;
+			arptab= realloc(arptab, max * sizeof(*arptab));
+			if (arptab == NULL)
+			{
+				fatal("out of memory, can't get %d bytes",
+					max*sizeof(*arptab));
+			}
+		}
+		r= ioctl(ipfd, NWIOARPGNEXT, &arp);
+		if (r == -1 && errno == ENOENT)
+			break;
+		if (r == -1)
+			fatal("NWIOARPGNEXT failed: %s", strerror(errno));
+		arptab[ind]= arp;
+		ind++;
+	}
+
+	for (i= 0; i<ind; i++)
+	{
+		r= ioctl(ipfd, NWIOARPDIP, &arptab[i]);
+		if (r == 0)
+			continue;
+		if (errno == EINVAL || errno == ENOENT)
+		{
+			/* Entry is incomplete of entry is already deleted */
+			continue;
+		}
+		fatal("unable to delete host %s: %s",
+			inet_ntoa(arptab[i].nwa_ipaddr), strerror(errno));
+	}
+}
+
+static void delete(char *hostname)
+{
+	int r;
+	ipaddr_t ipaddr;
+	nwio_arp_t arp;
+
+	ipaddr= nametoipaddr(hostname);
+	arp.nwa_ipaddr= ipaddr;
+	r= ioctl(ipfd, NWIOARPDIP, &arp);
+	if (r == 0)
+		return;
+	if (errno == ENOENT)
+	{
+		print_one(ipaddr, NULL, 0);
+		exit(1);
+	}
+	fatal("unable to delete host %s: %s", inet_ntoa(ipaddr),
+		errno == EINVAL ? "entry is incomplete" : strerror(errno));
+}
+
+static void do_set(char *hostname, char *ethername, int temp, int pub,
+	int optdelete)
+{
+	int r;
+	ipaddr_t ipaddr;
+	ether_addr_t *eap;
+	ether_addr_t ethaddr;
+	nwio_arp_t arp;
+	nwio_ipconf_t ipconf;
+
+	ipaddr= nametoipaddr(hostname);
+	if (pub && strcasecmp(ethername, "auto") == 0)
+	{
+		r= ioctl(ipfd, NWIOGIPCONF, &ipconf);
+		if (r == -1)
+			fatal("NWIOGIPCONF failed: %s", strerror(errno));
+		arp.nwa_ipaddr= ipconf.nwic_ipaddr;
+		r= ioctl(ipfd, NWIOARPGIP, &arp);
+		if (r == -1)
+			fatal("NWIOARPGIP failed: %s", strerror(errno));
+		ethaddr= arp.nwa_ethaddr;
+	}
+	else if (eap= ether_aton(ethername), eap != NULL)
+		ethaddr= *eap;
+	else if (ether_hostton(ethername, &ethaddr) != 0)
+	{
+		fatal("unable to parse ethernet address '%s'",
+			ethername);
+	}
+
+	if (optdelete)
+	{
+		arp.nwa_ipaddr= ipaddr;
+		r= ioctl(ipfd, NWIOARPDIP, &arp);
+		if (r == -1 && errno != ENOENT)
+		{
+			fatal("unable to delete entry for host %s: %s",
+				inet_ntoa(ipaddr),
+				errno == EINVAL ? "incomplete entry" :
+				strerror(errno));
+		}
+	}
+
+	arp.nwa_ipaddr= ipaddr;
+	arp.nwa_ethaddr= ethaddr;
+	arp.nwa_flags= 0;
+	if (pub)
+		arp.nwa_flags |= NWAF_PUB;
+	if (!temp)
+		arp.nwa_flags |= NWAF_PERM;
+	r= ioctl(ipfd, NWIOARPSIP, &arp);
+	if (r == -1)
+	{
+		fatal("unable to set arp entry: %s",
+			errno == EEXIST ? "entry exists" : strerror(errno));
+	}
+}
+
+static ipaddr_t nametoipaddr(char *hostname)
+{
+	ipaddr_t ipaddr;
+	struct hostent *he;
+
+	if (inet_aton(hostname, &ipaddr) == 0)
+	{
+		he= gethostbyname(hostname);
+		if (!he)
+			fatal("unknown hostname '%s'", hostname);
+		if (he->h_addrtype != AF_INET ||
+			he->h_length != sizeof(ipaddr))
+		{
+			fatal("strange host '%s': addrtype %d, length %d",
+				he->h_addrtype, he->h_length);
+		}
+		memcpy(&ipaddr, he->h_addr, sizeof(ipaddr));
+	}
+	return ipaddr;
+}
+
+#if 0
+static char *ether_ntoa(struct ether_addr *eap)
+{
+	static char buf[]= "xx:xx:xx:xx:xx:xx";
+
+	sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+		eap->ea_addr[0], eap->ea_addr[1],
+		eap->ea_addr[2], eap->ea_addr[3],
+		eap->ea_addr[4], eap->ea_addr[5]);
+	return buf;
+}
+#endif
+
+static void fatal(char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	fprintf(stderr, "%s: ", progname);
+	vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+	va_end(ap);
+
+	exit(1);
+}
+
+static void usage(void)
+{
+	fprintf(stderr, "Usage:\tarp [-I ip-dev] [-n] hostname\n"
+		"\tarp [-I ip-dev] [-n] -a\n"
+		"\tarp [-I ip-dev] -d hostname\n"
+		"\tarp [-I ip-dev] -d -a\n"
+		"\tarp [-I ip-dev] -s hostname ether-addr [temp] [pub]\n"
+		"\tarp [-I ip-dev] -S hostname ether-addr [temp] [pub]\n");
+	exit(1);
+}
+
+/*
+ * $PchId: arp.c,v 1.3 2005/01/31 22:31:45 philip Exp $
+ */
Index: /trunk/minix/commands/simple/at.c
===================================================================
--- /trunk/minix/commands/simple/at.c	(revision 9)
+++ /trunk/minix/commands/simple/at.c	(revision 9)
@@ -0,0 +1,223 @@
+/* at - run a command at a specified time	Author: Jan Looyen */
+
+#include <sys/types.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <limits.h>
+#include <signal.h>
+#include <errno.h>
+
+#define	STARTDAY	0	/* see ctime(3)	 */
+#define	LEAPDAY		STARTDAY+59
+#define	MAXDAYNR	STARTDAY+365
+#define	NODAY		-2
+char CRONPID[]	=	"/usr/run/cron.pid";
+
+_PROTOTYPE(int main, (int argc, char **argv, char **envp));
+_PROTOTYPE(int getltim, (char *t));
+_PROTOTYPE(int getlday, (char *m, char *d));
+_PROTOTYPE(int digitstring, (char *s));
+
+int main(argc, argv, envp)
+int argc;
+char **argv, **envp;
+{
+  int i, c, mask, ltim, year, lday = NODAY;
+  char buf[64], job[30], pastjob[35], *dp, *sp;
+  struct tm *p;
+  long clk;
+  FILE *fp;
+  char pwd[PATH_MAX+1];
+
+/*-------------------------------------------------------------------------*
+ *	check arguments	& pipe to "pwd"				           *
+ *-------------------------------------------------------------------------*/
+  if (argc < 2 || argc > 5) {
+	fprintf(stderr, "Usage: %s time [month day] [file]\n", argv[0]);
+	exit(1);
+  }
+  if ((ltim = getltim(argv[1])) == -1) {
+	fprintf(stderr, "%s: wrong time specification\n", argv[0]);
+	exit(1);
+  }
+  if ((argc == 4 || argc == 5) && (lday = getlday(argv[2], argv[3])) == -1) {
+	fprintf(stderr, "%s: wrong date specification\n", argv[0]);
+	exit(1);
+  }
+  if ((argc == 3 || argc == 5) && open(argv[argc - 1], O_RDONLY) == -1) {
+	fprintf(stderr, "%s: cannot find: %s\n", argv[0], argv[argc - 1]);
+	exit(1);
+  }
+  if (getcwd(pwd, sizeof(pwd)) == NULL) {
+	fprintf(stderr, "%s: cannot determine current directory: %s\n",
+		argv[0], strerror(errno));
+	exit(1);
+  }
+
+/*-------------------------------------------------------------------------*
+ *	determine execution time and create 'at' job file		   *
+ *-------------------------------------------------------------------------*/
+  time(&clk);
+  p = localtime(&clk);
+  year = p->tm_year;
+  if (lday == NODAY) {		/* no [month day] given */
+	lday = p->tm_yday;
+	if (ltim <= (p->tm_hour * 100 + p->tm_min)) {
+		lday++;
+		if ((lday == MAXDAYNR && (year % 4)) || lday == MAXDAYNR + 1) {
+			lday = STARTDAY;
+			year++;
+		}
+	}
+  } else
+	switch (year % 4) {
+	    case 0:
+		if (lday < p->tm_yday ||
+		    (lday == p->tm_yday &&
+		    ltim <= (p->tm_hour * 100 + p->tm_min))) {
+			year++;
+			if (lday > LEAPDAY) lday--;
+		}
+		break;
+	    case 1:
+	    case 2:
+		if (lday > LEAPDAY) lday--;
+		if (lday < p->tm_yday ||
+		    (lday == p->tm_yday &&
+		     ltim <= (p->tm_hour * 100 + p->tm_min)))
+			year++;
+		break;
+	    case 3:
+		if (lday < ((lday > LEAPDAY) ? p->tm_yday + 1 : p->tm_yday) ||
+		    (lday ==((lday > LEAPDAY) ? p->tm_yday + 1 : p->tm_yday) &&
+		     ltim <= (p->tm_hour * 100 + p->tm_min)))
+			year++;
+		else if (lday > LEAPDAY)
+			lday--;
+		break;
+	}
+  sprintf(job, "/usr/spool/at/%02d.%03d.%04d.%02d",
+	year % 100, lday, ltim, getpid() % 100);
+  sprintf(pastjob, "/usr/spool/at/past/%02d.%03d.%04d.%02d",
+	year % 100, lday, ltim, getpid() % 100);
+  mask= umask(0077);
+  if ((fp = fopen(pastjob, "w")) == NULL) {
+	fprintf(stderr, "%s: cannot create %s: %s\n",
+		argv[0], pastjob, strerror(errno));
+	exit(1);
+  }
+
+/*-------------------------------------------------------------------------*
+ *	write environment and command(s) to 'at'job file		   *
+ *-------------------------------------------------------------------------*/
+  i = 0;
+  while ((sp= envp[i++]) != NULL) {
+	dp = buf;
+	while ((c= *sp++) != '\0' && c != '=' && dp < buf+sizeof(buf)-1)
+		*dp++ = c;
+	if (c != '=') continue;
+	*dp = '\0';
+	fprintf(fp, "%s='", buf);
+	while (*sp != 0) {
+		if (*sp == '\'')
+			fprintf(fp, "'\\''");
+		else
+			fputc(*sp, fp);
+		sp++;
+	}
+	fprintf(fp, "'; export %s\n", buf);
+  }
+  fprintf(fp, "cd '%s'\n", pwd);
+  fprintf(fp, "umask %o\n", mask);
+  if (argc == 3 || argc == 5)
+	fprintf(fp, "%s\n", argv[argc - 1]);
+  else				/* read from stdinput */
+	while ((c = getchar()) != EOF) putc(c, fp);
+  fclose(fp);
+
+  if (chown(pastjob, getuid(), getgid()) == -1) {
+	fprintf(stderr, "%s: cannot set ownership of %s: %s\n",
+		argv[0], pastjob, strerror(errno));
+	unlink(pastjob);
+	exit(1);
+  }
+  /* "Arm" the job. */
+  if (rename(pastjob, job) == -1) {
+	fprintf(stderr, "%s: cannot move %s to %s: %s\n",
+		argv[0], pastjob, job, strerror(errno));
+	unlink(pastjob);
+	exit(1);
+  }
+  printf("%s: %s created\n", argv[0], job);
+
+  /* Alert cron to the new situation. */
+  if ((fp= fopen(CRONPID, "r")) != NULL) {
+	unsigned long pid;
+
+	pid= 0;
+	while ((c= fgetc(fp)) != EOF && c != '\n') {
+		if ((unsigned) (c - '0') >= 10) { pid= 0; break; }
+		pid= 10*pid + (c - '0');
+		if (pid >= 30000) { pid= 0; break; }
+	}
+	if (pid > 1) kill((pid_t) pid, SIGHUP);
+  }
+  return(0);
+}
+
+/*-------------------------------------------------------------------------*
+ *	getltim()		return((time OK) ? daytime : -1)	   *
+ *-------------------------------------------------------------------------*/
+int getltim(t)
+char *t;
+{
+  if (t[4] == '\0' && t[3] >= '0' && t[3] <= '9' &&
+      t[2] >= '0' && t[2] <= '5' && t[1] >= '0' && t[1] <= '9' &&
+      (t[0] == '0' || t[0] == '1' || (t[1] <= '3' && t[0] == '2')))
+	return(atoi(t));
+  else
+	return(-1);
+}
+
+/*-------------------------------------------------------------------------*
+ *	getlday()		return ((date OK) ? yearday : -1)	   *
+ *-------------------------------------------------------------------------*/
+int getlday(m, d)
+char *m, *d;
+{
+  int i, day, im;
+  static int cumday[] = {0, 0, 31, 60, 91, 121, 152,
+		       182, 213, 244, 274, 305, 335};
+  static struct date {
+	char *mon;
+	int dcnt;
+  } *pc, kal[] = {
+	{ "Jan", 31 }, { "Feb", 29 }, { "Mar", 31 }, { "Apr", 30 },
+	{ "May", 31 }, { "Jun", 30 }, { "Jul", 31 }, { "Aug", 31 },
+	{ "Sep", 30 }, { "Oct", 31 }, { "Nov", 30 }, { "Dec", 31 },
+  };
+
+  pc = kal;
+  im = (digitstring(m)) ? atoi(m) : 0;
+  m[0] &= 0337;
+  for (i = 1; i < 13 && strcmp(m, pc->mon) && im != i; i++, pc++);
+  if (i < 13 && (day = (digitstring(d)) ? atoi(d) : 0) && day <= pc->dcnt) {
+	if (!STARTDAY) day--;
+	return(day + cumday[i]);
+  } else
+	return(-1);
+}
+
+
+
+int digitstring(s)
+char *s;
+{
+  while (*s >= '0' && *s <= '9') s++;
+  return((*s == '\0') ? 1 : 0);
+}
Index: /trunk/minix/commands/simple/backup.c
===================================================================
--- /trunk/minix/commands/simple/backup.c	(revision 9)
+++ /trunk/minix/commands/simple/backup.c	(revision 9)
@@ -0,0 +1,589 @@
+/* backup - backup a directory		Author: Andy Tanenbaum */
+
+/* This program recursively backs up a directory.  It has two typical uses:
+ *
+ * 1. Backing up a directory to 1 or more diskettes
+ * 2. Backing up RAM disk to a shadow directory on hard disk
+ *
+ * The backup directory or medium may be empty, in which case, the entire
+ * source directory is copied, or it may contain an old backup, in which
+ * case only those files that are new or out of date are copied.  In this
+ * respect, 'backup' resembles 'make', except that no 'makefile' is needed.
+ * The backed up copy may optionally be compressed to save space.
+ *
+ * The following flags exist:
+ *
+ *	-d  At the top level, only back up directories (not loose files)
+ *	-j  Don't copy junk: *.Z, *.bak, *.log, a.out, and core
+ *	-m  If ENOSPC encountered, ask for another diskette
+ *	-n  No directories, only loose files are backed up
+ *	-o  Don't copy *.o files
+ *	-r  Restore files (ie. uncompress if necessary)
+ *	-s  Don't copy *.s files
+ *	-t  Set creation date of target-file equal to cdate of source-file
+ *	-v  Verbose (announce what is being done)
+ *	-z  Compress on backup/uncompress on restore
+ *
+ * Patches:
+ *	30 Mar 91.	Added restore option.  cwr. 
+ *	 9 Sep 91.	Changed user interface.  cwr.
+ *	21 Jan 93.	Revised error messages.  cwr.
+ *	29 Mar 95.	Added -o, NARROW define.  cwr.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <utime.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <dirent.h>
+
+#define NAME_SIZE _DIRENT_NAME_LEN
+
+#undef NARROW			/* Width of verbose output */
+#define COPY_SIZE 4096
+#define MAX_ENTRIES 512
+#define MAX_PATH 256
+#define NONFATAL 0
+#define FATAL 1
+#define NO_SAVINGS 512		/* compress can return code 2 */
+#define OUT_OF_SPACE 2
+
+struct dirent dir_ent[MAX_ENTRIES];
+int entries = 0;
+
+struct sorted {
+  int mode;			/* file mode */
+  char *namep;			/* pointer to name in dir_buf */
+  long acctime;			/* time of last access */
+  long modtime;			/* time of last modification */
+} sorted[MAX_ENTRIES];
+
+char copybuf[COPY_SIZE];
+char *pname;
+int dflag, jflag, mflag, nflag, oflag, rflag, sflag, tflag, vflag, zflag;
+
+extern int errno;
+extern char **environ;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void maketarget, (char *dir2));
+_PROTOTYPE(int make_dir, (char *dir));
+_PROTOTYPE(int stat_all, (char *dir1, int n));
+_PROTOTYPE(void sort_dir, (int m));
+_PROTOTYPE(void process, (int m, char *dir1, char *dir2));
+_PROTOTYPE(void swap, (struct sorted *sp1, struct sorted *sp2));
+_PROTOTYPE(int copy, (char *dir1, struct sorted *sp, char *cbuf2));
+_PROTOTYPE(int zcopy, (char *src, char *targ));
+_PROTOTYPE(void copydir, (char *dir1, char *dir2, char *namep));
+_PROTOTYPE(void newdisk, (char *dir));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(void error, (int type, char *s1, char *s2, char *s3));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int ct, n, m, fd;
+  char *dir1, *dir2, *cp, c;
+  struct stat s;
+  struct dirent *e;
+  DIR *DIR1, *DIR2;
+
+  (void) sync();
+
+  /* Get the flags */
+  if ((pname = strrchr(argv[0], '/')) == (char *)NULL)
+	pname = argv[0];
+  else
+	pname++;
+  if (argc < 3 || argc > 4) usage();
+  if (argc == 4) {
+	cp = argv[1];
+	if (*cp++ != '-') usage();
+	while ((c = *cp++) != '\0') {
+		switch (c) {
+		    case 'd':	dflag++;	break;
+		    case 'j':	jflag++;	break;
+		    case 'm':	mflag++;	break;
+		    case 'n':	nflag++;	break;
+		    case 'o':	oflag++;	break;
+		    case 's':	sflag++;	break;
+		    case 'r':	rflag++;	break;
+		    case 't':	tflag++;	break;
+		    case 'v':	vflag++;	break;
+		    case 'z':	zflag++;	break;
+		    default:	usage();
+		}
+	}
+	dir1 = argv[2];
+	dir2 = argv[3];
+  } else {
+	dir1 = argv[1];
+	dir2 = argv[2];
+  }
+  if (!strcmp(pname, "restore") && !rflag) rflag++;
+
+  /* Check for a valid source */
+  if (stat(dir1, &s) < 0) error(FATAL, "cannot stat ", dir1, "");
+  if ((s.st_mode & S_IFMT) != S_IFDIR) error(FATAL, "non-directory ", dir1, "");
+
+  /* Read in the source directory */
+  if(!(DIR1 = opendir(dir1))) {
+  	perror(dir1);
+  	return 1;
+  }
+  while(entries < MAX_ENTRIES && (e=readdir(DIR1)))
+  	memcpy(&dir_ent[entries++], e, sizeof(*e));
+  closedir(DIR1);
+  if (entries == MAX_ENTRIES)
+	error(FATAL, "directory ", dir1, " is too large");
+
+  /* Create the target directory. */
+  maketarget(dir2);
+
+  /* Stat all the entries. */
+  n = entries;
+  m = stat_all(dir1, n);
+
+  /* Remove non-entries and sort what's left. */
+  sort_dir(m);
+
+  /* Process each of the m entries one at a time. */
+  process(m, dir1, dir2);
+  return(0);
+}
+
+
+void maketarget(dir2)
+char *dir2;
+{
+/* The target directory is created if it does not already exist. */
+
+  char *p, c, dbuf[MAX_PATH];
+
+  if (access(dir2, 6) == 0)
+	return;			/* if target exists, we're done */
+  if (make_dir(dir2) == 0) return;	/* we just made it */
+
+  /* We have to try creating all the higher level directories. */
+  strcpy(dbuf, dir2);
+  p = dbuf + 1;
+  while (1) {
+	while (*p != '/' && *p != '\0') p++;
+	c = *p;			/* either / or \0 */
+	*p = 0;
+	make_dir(dbuf);
+	if (c == '\0') return;
+	*p = c;
+	p++;
+  }
+}
+
+int make_dir(dir)
+char *dir;
+{
+/* Create a directory. */
+  int pid, status;
+
+  if ((pid = fork()) < 0)
+	error(FATAL, "cannot fork off mkdir to create ", dir, "");
+  if (pid > 0) {
+	/* Parent process waits for child (mkdir). */
+	wait(&status);
+	return(status);
+  } else {
+	/* Child process executes mkdir */
+	close(2);		/* don't want mkdir's error messages */
+	execle("/bin/mkdir", "mkdir", dir, (char *) 0, environ);
+	execle("/usr/bin/mkdir", "mkdir", dir, (char *) 0, environ);
+	error(FATAL, "cannot execute mkdir", "", "");
+  }
+  return(0);
+}
+
+
+int stat_all(dir1, n)
+char *dir1;
+int n;
+{
+/* Stat all the directory entries.  By doing this all at once, the disk
+ * head can stay in the inode area.
+ */
+
+  int i, j;
+  char cbuf[MAX_PATH];
+  struct stat s;
+
+  for (i = 0; i < n; i++) {
+	/* Mark "." and ".." as null entries, as well as unstatable ones. */
+	if (strcmp(dir_ent[i].d_name, ".") == 0) dir_ent[i].d_ino = 0;
+	if (strcmp(dir_ent[i].d_name, "..") == 0) dir_ent[i].d_ino = 0;
+	if (dir_ent[i].d_ino == 0) continue;
+
+	/* Stat the file. */
+	snprintf(cbuf, sizeof(cbuf), "%s/%s", dir1, dir_ent[i].d_name);
+	if (stat(cbuf, &s) < 0) {
+		error(NONFATAL, "cannot stat ", cbuf, "");
+		dir_ent[i].d_ino = 0;	/* mark as unusable */
+		continue;
+	}
+	sorted[i].mode = s.st_mode;
+	sorted[i].acctime = s.st_atime;
+	sorted[i].modtime = s.st_mtime;
+	sorted[i].namep = dir_ent[i].d_name;
+	sorted[i].namep[NAME_SIZE-1] = '\0';
+  }
+
+  /* Squeeze out all the entries whose ino field is 0. */
+  j = 0;
+  for (i = 0; i < n; i++) {
+	if (dir_ent[i].d_ino != 0) {
+		sorted[j] = sorted[i];
+		j++;
+	}
+  }
+  return(j);
+}
+
+
+void sort_dir(m)
+int m;
+{
+/* Sort the directory using bubble sort. */
+
+  struct sorted *sp1, *sp2;
+
+  for (sp1 = &sorted[0]; sp1 < &sorted[m - 1]; sp1++) {
+	for (sp2 = sp1 + 1; sp2 < &sorted[m]; sp2++) {
+		if (strcmp(sp1->namep, sp2->namep) > 0)
+			swap(sp1, sp2);
+	}
+  }
+}
+
+
+void process(m, dir1, dir2)
+int m;
+char *dir1, *dir2;
+{
+/* Process each entry in sorted[].  If it is a regular file, stat the target
+ * file.  The the source is newer, copy it.  If the entry is a directory,
+ * recursively call the entire program to process the directory.
+ */
+
+  int er, fmode, res;
+  struct sorted *sp;
+  struct stat s;
+  char cbuf[MAX_PATH];
+
+  for (sp = &sorted[0]; sp < &sorted[m]; sp++) {
+  	int namlen;
+	fmode = sp->mode & S_IFMT;
+	if (fmode == S_IFREG) {
+		/* Regular file.  Construct target name and stat it. */
+		snprintf(cbuf, sizeof(cbuf), "%s/%s", dir2, sp->namep);
+		namlen = strlen(sp->namep);
+		/* Switch between compressed and uncompressed file names */
+		if (zflag && !rflag && strncmp((sp->namep + namlen - 2), ".Z", (size_t)2)
+				&& (namlen <= (NAME_SIZE - 2)))
+			strncat(cbuf, ".Z", (size_t)2);
+		if (zflag && rflag && !strncmp((sp->namep + namlen - 2), ".Z", (size_t)2))
+			cbuf[strlen(cbuf) - 2] = '\0';
+		er = stat(cbuf, &s);
+		if (er < 0 || sp->modtime > s.st_mtime) {
+			res = copy(dir1, sp, cbuf);
+		} else {
+			res = NONFATAL;
+		}
+
+		/* Check status of the copy. */
+		if (res == OUT_OF_SPACE) {
+			printf("Out of space while copying to %s\n", cbuf);
+			/* We ran out of space copying a regular file. */
+			if (mflag == 0)
+				error(FATAL, "Quitting, disk full", "", "");
+
+			/* If -m, ask for new diskette and continue. */
+			newdisk(dir2);
+			sp--;
+			continue;
+		}
+	} else if (fmode == S_IFDIR) {
+		/* Directory.  Execute this program recursively. */
+		copydir(dir1, dir2, sp->namep);
+	} else if (fmode == S_IFBLK || fmode == S_IFCHR) {
+		/* Special file. */
+		strncpy(cbuf, sp->namep, sizeof(cbuf));
+		printf("%s is special file.  Not backed up.\n", cbuf);
+	}
+  }
+}
+
+
+
+
+void swap(sp1, sp2)
+struct sorted *sp1, *sp2;
+{
+/* Swap two directory entries. */
+
+  struct sorted d;
+
+  d = *sp1;
+  *sp1 = *sp2;
+  *sp2 = d;
+}
+
+
+int copy(dir1, sp, cbuf2)
+struct sorted *sp;
+char *dir1, *cbuf2;
+{
+/* Copy a regular file. */
+
+  int fd1, fd2, nr, nw, res, n;
+  char cbuf1[MAX_PATH], *p;
+#ifdef NARROW
+  char *msg = (rflag || strcmp(pname, "backup")) ? "Restored" : "Backing up";
+#endif
+
+  /* If the -j or -o or -s flags were given, suppress certain files. */
+  p = sp->namep;
+  n = strlen(p);
+  if (n > NAME_SIZE) n = NAME_SIZE;
+  if (jflag) {
+	if (strcmp(p, "a.out") == 0) return(0);
+	if (strcmp(p, "core") == 0) return (0);
+	if (strcmp(p + n - 2, ".Z") == 0) return (0);
+	if (strcmp(p + n - 4, ".bak") == 0) return (0);
+	if (strcmp(p + n - 4, ".log") == 0) return (0);
+  }
+  if (oflag) {
+	if (strcmp(p + n - 2, ".o") == 0) return(0);
+  }
+  if (sflag) {
+	if (strcmp(p + n - 2, ".s") == 0) return(0);
+  }
+  res = 0;
+  if (dflag) return(0);		/* backup -d means only directories */
+  strcpy(cbuf1, dir1);
+  strncat(cbuf1, "/", (size_t)1);
+  strncat(cbuf1, sp->namep, (size_t)NAME_SIZE);	/* cbuf1 = source file name */
+
+  /* At this point, cbuf1 contains the source file name, cbuf2 the target. */
+  fd1 = open(cbuf1, O_RDONLY);
+  if (fd1 < 0) {
+	error(NONFATAL, "cannot open ", cbuf1, "");
+	return(res);
+  }
+  fd2 = creat(cbuf2, (sp->mode | S_IWUSR) & 07777);
+  if (fd2 < 0) {
+	if (errno == ENFILE) {
+		close(fd1);
+		return(OUT_OF_SPACE);
+	}
+	error(NONFATAL, "cannot create ", cbuf2, "");
+	close(fd1);
+	return(res);
+  }
+
+  /* Both files are now open.  Do the copying. */
+  if (!rflag && strncmp((sp->namep + n - 2), ".Z", (size_t)2) ||
+		rflag && !strncmp((sp->namep + n - 2), ".Z", (size_t)2)) {
+	if (zflag && (rflag || (n <= (NAME_SIZE - 2)))) {
+		close(fd1);
+		close(fd2);
+		res = zcopy(cbuf1, cbuf2);
+		if (tflag) utime(cbuf2, (struct utimbuf *) & (sp->acctime));
+		if (res != 0) unlink(cbuf2); /* if error, get rid of the corpse */
+#ifdef NARROW
+		if (vflag && res == 0) printf("%s %s\n", msg, cbuf1);
+#else
+		if (vflag && res == 0) {
+			printf("%-37.37s -> %-37.37s\n", cbuf1, cbuf2);
+			if (strlen(cbuf1) > 37 || strlen(cbuf2) > 37)
+				printf("%37.37s    %37.37s\n",
+				(strlen(cbuf1) > 37) ? (cbuf1 + 37) : "",
+				(strlen(cbuf2) > 37) ? (cbuf2 + 37) : "");
+		}
+#endif
+		return(res);
+	}
+  }
+  while (1) {
+	nr = read(fd1, copybuf, COPY_SIZE);
+	if (nr == 0) break;
+	if (nr < 0) {
+		error(NONFATAL, "read error on ", cbuf1, "");
+		res = EIO;
+		break;
+	}
+	nw = write(fd2, copybuf, nr);
+	if (nw < 0) {
+		if (errno == ENOSPC) {
+			/* Device is full. */
+			res = OUT_OF_SPACE;
+			break;
+		}
+
+		/* True write error. */
+		error(NONFATAL, "write error on ", cbuf2, "");
+		res = EIO;
+		break;
+	}
+  }
+  if (res == 0) {
+#ifdef NARROW
+ 	if (vflag) printf("%s %s\n", msg, cbuf1);
+#else
+	if (vflag) {
+		printf("%-37.37s -> %-37.37s\n", cbuf1, cbuf2);
+		if (strlen(cbuf1) > 37 || strlen(cbuf2) > 37)
+			printf("%37.37s    %37.37s\n",
+			(strlen(cbuf1) > 37) ? (cbuf1 + 37) : "",
+			(strlen(cbuf2) > 37) ? (cbuf2 + 37) : "");
+	}
+#endif
+  } else {
+	unlink(cbuf2);
+  }
+  close(fd1);
+  close(fd2);
+  if (tflag) utime(cbuf2, (struct utimbuf *) & (sp->acctime));
+  return(res);
+}
+
+
+int zcopy(src, targ)
+char *src, *targ;
+{
+
+  int pid, status, res, s;
+  char fbuf[20];
+
+  /* These flags go for compress and gzip. */
+  strcpy(fbuf, "-c");
+  if (rflag)
+	strcat(fbuf, "d");
+  else
+	strcat(fbuf, "f");
+
+  if ((pid = fork()) < 0) error(FATAL, "cannot fork", "", "");
+  if (pid > 0) {
+	wait(&status);
+
+	/* Error codes 0 and 2 are ok, assume others mean disk is full. */
+	res = (status == 0 || status == NO_SAVINGS ? 0 : OUT_OF_SPACE);
+	return(res);
+  } else {
+	/* Child must execute compress. */
+	close(1);
+	s = open(targ, O_RDWR);
+	if (s < 0) error(FATAL, "cannot write on ", "targ", "");
+	execle("/usr/bin/gzip", "gzip", fbuf, src, (char *)0, environ);
+	execle("/usr/local/bin/gzip", "gzip", fbuf, src, (char *)0, environ);
+	execle("/bin/compress", "compress", fbuf, src, (char *)0, environ);
+	execle("/usr/bin/compress", "compress", fbuf, src, (char *)0, environ);
+	error(FATAL, "cannot exec gzip or compress", "", "");
+  }
+  return(0);
+}
+
+
+void copydir(dir1, dir2, namep)
+char *dir1, *dir2, *namep;
+{
+/* Copy a directory. */
+
+  int pid, status;
+  char fbuf[20], d1buf[MAX_PATH], d2buf[MAX_PATH];
+
+  if (nflag) return;	/* backup -n means no directories */
+
+  fbuf[0] = '\0';
+
+  /* Handle directory copy by forking off 'backup' ! */
+  if (jflag || mflag || oflag || rflag || sflag || tflag || vflag || zflag)
+	strcpy(fbuf, "-");
+  if (jflag) strcat(fbuf, "j");
+  if (mflag) strcat(fbuf, "m");
+  if (oflag) strcat(fbuf, "o");
+  if (rflag) strcat(fbuf, "r");
+  if (sflag) strcat(fbuf, "s");
+  if (tflag) strcat(fbuf, "t");
+  if (vflag) strcat(fbuf, "v");
+  if (zflag) strcat(fbuf, "z");
+  snprintf(d1buf, sizeof(d1buf), "%s/%s", dir1, namep);
+  snprintf(d2buf, sizeof(d2buf), "%s/%s", dir2, namep);
+
+  if ((pid = fork()) < 0) error(FATAL, "cannot fork", "", "");
+  if (pid > 0) {
+	/* Parent waits for child, then returns. */
+	wait(&status);
+	return;
+  }
+
+  if (fbuf[0] == '-') {
+	execle(pname, pname, fbuf, d1buf, d2buf, (char *) 0, environ);
+	execle("/bin/backup", "backup", fbuf, d1buf, d2buf, (char *)0,environ);
+	execle("/usr/bin/backup","backup",fbuf,d1buf,d2buf,(char *)0,environ);
+	error(FATAL, "cannot recursively exec backup", "", "");
+  } else {
+	execle(pname, pname, d1buf, d2buf, (char *) 0, environ);
+	execle("/bin/backup", "backup", d1buf, d2buf, (char *)0,environ);
+	execle("/usr/bin/backup","backup", d1buf, d2buf, (char *)0,environ);
+	error(FATAL, "cannot recursively exec backup", "", "");
+  }
+}
+
+void newdisk(dir)
+char *dir;
+{
+/* Ask for a new diskette. A big problem is that this program does not
+ * know which device is being used and where it is mounted on.  As an
+ * emergency solution, fork off a shell and ask the user to do the work.
+ */
+
+  int pid, status;
+
+  printf("\nDiskette full. Please do the following:\n");
+  printf("   1. Unmount the diskette using /etc/umount\n");
+  printf("   2. Physically replace the diskette by the next one.\n");
+  printf("   3. Mount the new diskette using /etc/mount\n");
+  printf("   4. Type CTRL-D to return to the backup/restore program\n");
+
+  if ((pid = fork()) < 0) error(FATAL, "cannot fork", "", "");
+  if (pid > 0) {
+	wait(&status);
+	maketarget(dir);	/* make the directory */
+  } else {
+	execle("/bin/sh", "sh", "-i", (char *) 0, environ);
+	execle("/usr/bin/sh", "sh", "-i", (char *) 0, environ);
+	error(FATAL, "cannot execute shell to ask for new diskette", "", "");
+  }
+}
+
+void usage()
+{
+  fprintf(stderr, "Usage: %s [-djmnorstvz] dir1 dir2\n", pname);
+  exit(2);
+}
+
+
+void error(type, s1, s2, s3)
+int type;
+char *s1, *s2, *s3;
+{
+  fprintf(stderr, "%s: %s%s%s\n", pname, s1, s2, s3);
+
+  if (type == NONFATAL)
+	return;
+  else
+	exit(type);
+}
Index: /trunk/minix/commands/simple/badblocks.c
===================================================================
--- /trunk/minix/commands/simple/badblocks.c	(revision 9)
+++ /trunk/minix/commands/simple/badblocks.c	(revision 9)
@@ -0,0 +1,657 @@
+/* badblocks - collect bad blocks in a file	Author: Jacob Bunschoten */
+
+/* Usage "badblocks block_special [Up_to_7_blocks]" */
+
+/* This program is written to handle BADBLOCKS on a hard or floppy disk.
+ * The program asks for block_numbers. These numbers can be obtained with
+ * the program readall, written by A. Tanenbaum.  It then creates a
+ * file on the disk containing up to 7 bad blocks.
+ *
+ * BUG:
+ *
+ *	When the zone_size > block_size it can happen that
+ *	the zone is already allocated. This means some
+ *	file is using this zone and may use all the blocks including
+ *	the bad one. This can be cured by inspecting the zone_bitmap
+ *	(is already done) and change the file if this zone is used.
+ *	This means that another zone must be allocated and
+ *	the inode wich claims this zone must be found and changed.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <minix/config.h>
+#include <minix/type.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <stdlib.h>
+
+#include "../../servers/fs/const.h"	/* must be included before stdio.h */
+#undef printf			/* so its define of printf can be undone */
+#include "../../servers/fs/type.h"
+
+#include <string.h>
+#include <stdio.h>
+
+#define EXTERN extern
+#include "../../servers/fs/super.h"
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void rw_super, (int flag));
+_PROTOTYPE(void get_super, (void));
+_PROTOTYPE(void put_super, (void));
+_PROTOTYPE(void rw_inode, (struct stat * stat_ptr, int rw_mode));
+_PROTOTYPE(void get_inode, (struct stat * stat_ptr));
+_PROTOTYPE(void put_inode, (struct stat * stat_ptr));
+_PROTOTYPE(long rd_cmdline, (int argc, char *argv[]));
+_PROTOTYPE(void modify, (int nr_blocks));
+_PROTOTYPE(void save_blk, (block_t blk_num));
+_PROTOTYPE(void reset_blks, (void));
+_PROTOTYPE(void show_blks, (void));
+_PROTOTYPE(int blk_is_used, (block_t blk_num));
+_PROTOTYPE(int blk_ok, (block_t num));
+_PROTOTYPE(void set_bit, (zone_t num));
+_PROTOTYPE(long rd_num, (void));
+_PROTOTYPE(int ok, (char *str));
+_PROTOTYPE(void done, (int nr));
+
+/* 		Super block table.
+ *
+ * 	The disk layout is:
+ *
+ *      Item        # block
+ *    boot block      1
+ *    super block     1
+ *    inode map     s_imap_blocks
+ *    zone map      s_zmap_blocks
+ *    inodes        (s_ninodes + 1 + inodes_per_block - 1)/inodes_per_block
+ *    unused
+ *    data zones    (s_nzones - s_firstdatazone) << s_log_zone_size
+ *
+ */
+
+#define OK	0
+#define NOT_OK	1
+#define QUIT	2
+
+#define READ 	0
+#define WRITE	1
+
+#define HARMLESS	0
+#define DIR_CREATED	1
+#define DEV_MOUNTED	2
+#define FILE_EXISTS	3
+#define SUCCESS		4
+
+#define BYTE         0377
+#define BLOCK_SIZE   1024
+#define SIZE_OF_INT   (sizeof (int) )
+
+/* Define V_NR_DZONES as the larger of V1_NR_DZONES and V2_NR_DZONES. */
+#if (V1_NR_DZONES > V2_NR_DZONES)
+#define V_NR_DZONES V1_NR_DZONES
+#define V_SMALLER   V2_NR_DZONES
+#else
+#define V_NR_DZONES V2_NR_DZONES
+#define V_SMALLER   V1_NR_DZONES
+#endif
+
+#if 0
+struct super_block {
+  ino_t s_ninodes;		/* # usable inodes on the minor device */
+  zone1_t s_nzones;		/* total device size, including bit maps etc */
+  short s_imap_blocks;		/* # of blocks used by inode bit map */
+  short s_zmap_blocks;		/* # of blocks used by zone bit map */
+  zone1_t s_firstdatazone;	/* number of first data zone */
+  short s_log_zone_size;	/* log2 of blocks/zone */
+  off_t s_max_size;		/* maximum file size on this device */
+  short s_magic;		/* magic number to recognize super-blocks */
+  short s_pad;			/* try to avoid compiler-dependent padding */
+  zone_t s_zones;		/* number of zones (replaces s_nzones in V2) */
+} super_block;
+#endif
+
+ /* ====== globals ======= */
+
+char *dev_name;
+char f_name[] = ".Bad_XXXXXX";
+char file_name[50];
+char dir_name[] = "/tmpXXXXXX";
+
+block_t block[V_NR_DZONES + 1];	/* last block contains zero */
+int interactive;		/* 1 if interactive (argc == 2) */
+int position = 2;		/* next block # is argv[position] */
+
+FILE *f;
+int fd;
+int eofseen;			/* set if '\n' seen */
+struct stat stat_buf;
+struct super_block *sp, sbs;
+int inodes_per_block;
+size_t inode_size;
+int v1fs = 0, v2fs = 0;			/* TRUE for V1 file system, FALSE for V2 */
+
+d1_inode d1inode;		/* declare a V1 disk inode */
+d1_inode *ip1;
+d2_inode d2inode;		/* declare a V2 disk inode */
+d2_inode *ip2;
+
+
+ /* ====== super block routines ======= */
+
+void rw_super(flag)
+int flag;
+{				/* read or write a superblock */
+  int rwd;
+
+  lseek(fd, 0L, SEEK_SET);	/* rewind */
+  lseek(fd, (long) BLOCK_SIZE, SEEK_SET);	/* seek */
+
+  if (flag == READ)
+	rwd = read(fd, (char *) sp, SUPER_SIZE);
+  else
+	rwd = write(fd, (char *) sp, SUPER_SIZE);
+  if (rwd != SUPER_SIZE) {	/* ok ? */
+	printf("Bad %s in get_super() (should be %u is %d)\n",
+	       flag == READ ? "read" : "write",
+	       (unsigned) SUPER_SIZE, rwd);
+	done(DIR_CREATED);
+  }
+}
+
+void get_super()
+ /* Get super_block. global pointer sp is used */
+{
+  rw_super(READ);
+
+  if (sp->s_magic == SUPER_MAGIC) {
+	/* This is a V1 file system. */
+	v1fs = 1;		/* file system is not V2 */
+  } else if (sp->s_magic == SUPER_V2) {
+	/* This is a V2 file system. */
+	v2fs = 1;		/* this is a V2 file system */
+  } else if (sp->s_magic == SUPER_V3) {
+	v1fs = v2fs = 0;		/* this is a V3 file system */
+  } else {
+	/* Neither V1 nor V2 nor V3. */
+	printf("Bad magic number in super_block (0x%x)\n",
+	       (unsigned) sp->s_magic);
+	done(DIR_CREATED);
+  }
+}
+
+
+void put_super()
+{
+  rw_super(WRITE);
+}
+
+ /* ========== inode routines =========== */
+
+void rw_inode(stat_ptr, rw_mode)
+struct stat *stat_ptr;
+int rw_mode;
+{
+  int rwd;
+  ino_t i_num;
+  block_t blk, offset;
+
+
+  i_num = stat_ptr->st_ino;
+
+  blk = (block_t) (2 + sp->s_imap_blocks + sp->s_zmap_blocks);
+  blk += (block_t) ((i_num - 1) / inodes_per_block);
+  blk *= (block_t) (BLOCK_SIZE);/* this block */
+
+  offset = (block_t) ((i_num - 1) % inodes_per_block);
+  offset *= (block_t) (inode_size);	/* and this offset */
+
+  lseek(fd, (off_t) 0, SEEK_SET);	/* rewind */
+  lseek(fd, (off_t) (blk + offset), SEEK_SET);	/* seek */
+
+  /* Pointer is at the inode */
+  if (v1fs) {
+	/* This is a V1 file system. */
+	if (rw_mode == READ) {	/* read it */
+		rwd = read(fd, (char *) ip1, inode_size);
+	} else {		/* write it */
+		rwd = write(fd, (char *) ip1, inode_size);
+	}
+  } else {
+	/* This is a V2 file system. */
+	if (rw_mode == READ) {	/* read it */
+		rwd = read(fd, (char *) ip2, inode_size);
+	} else {		/* write it */
+		rwd = write(fd, (char *) ip2, inode_size);
+	}
+  }
+
+  if (rwd != inode_size) {	/* ok ? */
+	printf("Bad %s in get_inode()\n", (rw_mode == READ) ? "read" :
+	       "write");
+	done(DIR_CREATED);
+  }
+}
+
+void get_inode(stat_ptr)
+struct stat *stat_ptr;
+{
+
+  int cnt;
+
+  rw_inode(stat_ptr, READ);
+
+  if (v1fs) {
+	for (cnt = 0; cnt < V1_NR_TZONES; cnt++)
+		ip1->d1_zone[cnt] = 0;	/* Just to be safe */
+  } else {
+	for (cnt = 0; cnt < V2_NR_TZONES; cnt++)
+		ip2->d2_zone[cnt] = 0;	/* Just to be safe */
+  }
+}
+
+void put_inode(stat_ptr)
+struct stat *stat_ptr;
+{
+  rw_inode(stat_ptr, WRITE);
+}
+
+
+ /* ==============  main program ================= */
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int cnt, finished;
+  block_t blk_nr;
+  struct stat dev_stat;
+  FILE *fp;
+  int block_size;
+
+  sp = &sbs;
+  ip1 = &d1inode;
+  ip2 = &d2inode;
+
+  if (argc < 2 || argc > 9) {
+	fprintf(stderr, "Usage: %s block_special [up_to_7_blocks]\n", argv[0]);
+	done(HARMLESS);
+  }
+  interactive = (argc == 2 ? 1 : 0);
+
+  /* Do some test. */
+  if (geteuid()) {
+	printf("Sorry, not in superuser mode \n");
+	printf("Set_uid bit must be on or you must become super_user\n");
+	done(HARMLESS);
+  }
+  dev_name = argv[1];
+  mktemp(dir_name);
+  if (mkdir(dir_name, 0777) == -1) {
+	fprintf(stderr, "%s is already used in system\n", dir_name);
+	done(HARMLESS);
+  }
+
+  /* Mount device. This call may fail. */
+  mount(dev_name, dir_name, 0);
+  /* Succes. dev was mounted, try to umount */
+
+  /* Umount device. Playing with the file system while other processes
+   * have access to this device is asking for trouble */
+  if (umount(dev_name) == -1) {
+	printf("Could not umount device %s.\n", dev_name);
+	done(HARMLESS);
+  }
+  mktemp(f_name);
+  /* Create "/tmpXXXXpid/.BadXXpid" */
+  strcat(file_name, dir_name);
+  strcat(file_name, "/");
+  strcat(file_name, f_name);
+
+  if (mount(dev_name, dir_name, 0) == -1) {	/* this call should work */
+	fprintf(stderr, "Could not mount device anymore\n");
+	done(HARMLESS);
+  }
+  if (stat(file_name, &stat_buf) != -1) {
+	printf("File %s already exists\n", file_name);
+	done(DEV_MOUNTED);
+  }
+  if ((fp = fopen(file_name, "w")) == NULL) {
+	printf("Cannot create file %s\n", file_name);
+	done(DEV_MOUNTED);
+  }
+  chmod(file_name, 0);		/* "useless" file */
+  if (stat(file_name, &stat_buf) == -1) {
+	printf("What? Second call from stat failed\n");
+	done(FILE_EXISTS);
+  }
+
+  /* Stat buf must be safed. We can now calculate the inode on disk */
+  fclose(fp);
+
+  /* ===== the badblock file is created ===== */
+
+  if (umount(dev_name) == -1) {
+	printf("Can not umount device anymore??? \n");
+	done(DIR_CREATED);
+  }
+  if ((fd = open(dev_name, O_RDWR)) == -1) {
+	printf("Can not open device %s\n", dev_name);
+	done(DEV_MOUNTED);
+  }
+  if (fstat(fd, &dev_stat) == -1) {
+	printf("fstat on device %s failed\n", dev_name);
+	done(DEV_MOUNTED);
+  }
+  if ((dev_stat.st_mode & S_IFMT) != S_IFBLK) {
+	printf("Device \"%s\" is not a block_special.\n", dev_name);
+	done(DEV_MOUNTED);
+  }
+  get_super();
+  if (sp->s_log_zone_size) {
+	printf("Block_size != zone_size.");
+	printf("This program can not handle it\n");
+	done(DIR_CREATED);
+  }
+  if(v1fs || v2fs) block_size = 1024;
+  else block_size = sp->s_block_size;
+
+  /* The number of inodes in a block differs in V1 and V2. */
+  if (v1fs) {
+	inodes_per_block = V1_INODES_PER_BLOCK;
+	inode_size = V1_INODE_SIZE;
+  } else {
+	inodes_per_block = V2_INODES_PER_BLOCK(block_size);
+	inode_size = V2_INODE_SIZE;
+  }
+
+  get_inode(&stat_buf);
+
+  for (finished = 0; !finished;) {
+	if (interactive)
+		printf("Give up to %d bad block numbers separated by spaces\n",
+		       V_SMALLER);
+	reset_blks();
+	cnt = 0;		/* cnt keep track of the zone's */
+	while (cnt < V_SMALLER) {
+		int tst;
+
+		if (interactive)
+			blk_nr = rd_num();
+		else
+			blk_nr = rd_cmdline(argc, argv);
+		if (blk_nr == -1) break;
+		tst = blk_ok(blk_nr);
+
+		/* Test if this block is free */
+		if (tst == OK) {
+			cnt++;
+			save_blk(blk_nr);
+		} else if (tst == QUIT)
+			break;
+	}
+	if (interactive) show_blks();
+	if (!cnt) done(FILE_EXISTS);
+	if (interactive) {
+		switch (ok("All these blocks ok <y/n/q> (y:Device will change) ")) {
+		    case OK:	finished = 1;	break;
+		    case NOT_OK:
+			break;
+		    case QUIT:	done(FILE_EXISTS);
+		}
+	} else {
+		finished = 1;
+	}
+  }
+
+  modify(cnt);
+  close(fd);			/* free device */
+  done(SUCCESS);
+  return(0);
+}
+
+long rd_cmdline(argc, argv)
+int argc;
+char *argv[];
+{
+  if (position == argc) return(-1);
+  return(atol(argv[position++]));
+}
+
+
+void modify(nr_blocks)
+int nr_blocks;
+{
+  int i;
+
+  if (nr_blocks == 0) return;
+  if (v1fs) {
+	/* This is a V1 file system. */
+	for (i = 0; i < nr_blocks; i++) {
+		set_bit(block[i]);
+		ip1->d1_zone[i] = block[i];
+	}
+  } else {
+	/* This is a V2 file system. */
+	for (i = 0; i < nr_blocks; i++) {
+		set_bit(block[i]);
+		ip2->d2_zone[i] = block[i];
+	}
+  }
+  if (v1fs) {
+	ip1->d1_size = (long) (BLOCK_SIZE * nr_blocks);	/* give file size */
+	ip1->d1_mtime = 0;	/* Who wants a file from 1970? */
+  } else {
+	ip2->d2_size = (long) (BLOCK_SIZE * nr_blocks);	/* give file size */
+	ip2->d2_atime = ip2->d2_mtime = ip2->d2_ctime = 0;
+  }
+
+  put_inode(&stat_buf);		/* save the inode on disk */
+  put_super();			/* bit_maps too */
+}
+
+
+static blk_cnt = 0;
+
+void save_blk(blk_num)
+block_t blk_num;
+{
+  block[blk_cnt++] = blk_num;
+}
+
+void reset_blks()
+{
+  int i;
+
+  for (i = 0; i <= V_NR_DZONES; i++)
+	block[i] = 0;		/* Note: Last block_number is set to zero */
+  blk_cnt = 0;
+}
+
+void show_blks()
+{
+  int i;
+
+  for (i = 0; i < blk_cnt; i++)
+	printf("Block[%d] = %lu\n", i, (unsigned long) block[i]);
+}
+
+int blk_is_used(blk_num)
+block_t blk_num;
+{				/* return TRUE(1) if used */
+  int i;
+
+  for (i = 0; block[i] && block[i] != blk_num; i++);
+  return(block[i] != 0) ? 1 : 0;
+}
+
+
+ /* ===== bitmap handling ======	 */
+
+#define BIT_MAP_SHIFT	13
+#define INT_BITS	(SIZE_OF_INT << 3)
+
+int blk_ok(num)			/* is this zone free (y/n) */
+block_t num;
+{
+  block_t blk_offset;
+  int rd;
+  int blk, offset, words, bit, tst_word;
+  zone_t z_num;
+
+  if (blk_is_used(num)) {
+	printf("Duplicate block (%lu) given\n", (unsigned long) num);
+	return NOT_OK;
+  }
+
+  /* Assumption zone_size == block_size */
+
+  z_num = num - (sp->s_firstdatazone - 1);	/* account offset */
+
+  /* Calculate the word in the bitmap. */
+  blk = z_num >> BIT_MAP_SHIFT;	/* which block */
+  offset = z_num - (blk << BIT_MAP_SHIFT);	/* offset */
+  words = z_num / INT_BITS;	/* which word */
+
+  blk_offset = (block_t) (2 + sp->s_imap_blocks);	/* zone map */
+  blk_offset *= (block_t) BLOCK_SIZE;	/* of course in block */
+  blk_offset += (block_t) (words * SIZE_OF_INT);	/* offset */
+
+
+  lseek(fd, (off_t) 0, SEEK_SET);	/* rewind */
+  lseek(fd, (off_t) blk_offset, SEEK_SET);	/* set pointer at word */
+
+  rd = read(fd, (char *) &tst_word, SIZE_OF_INT);
+  if (rd != SIZE_OF_INT) {
+	printf("Read error in bitmap\n");
+	done(DIR_CREATED);
+  }
+
+  /* We have the tst_word, check if bit was off */
+  bit = offset % INT_BITS;
+
+  if (((tst_word >> bit) & 01) == 0)	/* free */
+	return OK;
+  else {
+	printf("Bad number %lu. ", (unsigned long) num);
+	printf("This zone (block) is marked in bitmap\n");
+	return NOT_OK;
+  }
+}
+
+void set_bit(num)		/* write in the bitmap */
+zone_t num;
+{
+  int rwd;
+  long blk_offset;
+  int blk, offset, words, tst_word, bit;
+  unsigned z_num;
+
+  z_num = num - (sp->s_firstdatazone - 1);
+
+  blk = z_num >> BIT_MAP_SHIFT;	/* which block */
+  offset = z_num - (blk << BIT_MAP_SHIFT);	/* offset in block */
+  words = z_num / INT_BITS;	/* which word */
+
+  blk_offset = (long) (2 + sp->s_imap_blocks);
+  blk_offset *= (long) BLOCK_SIZE;
+  blk_offset += (long) (words * SIZE_OF_INT);
+
+
+  lseek(fd, (off_t) 0, SEEK_SET);	/* rewind */
+  lseek(fd, (off_t) blk_offset, SEEK_SET);
+
+  rwd = read(fd, (char *) &tst_word, SIZE_OF_INT);
+  if (rwd != SIZE_OF_INT) {
+	printf("Read error in bitmap\n");
+	done(DEV_MOUNTED);
+  }
+  bit = offset % INT_BITS;
+  if (((tst_word >> bit) & 01) == 0) {	/* free */
+	lseek(fd, 0L, SEEK_SET);/* rewind */
+	lseek(fd, (off_t) blk_offset, SEEK_SET);
+	tst_word |= (1 << bit);	/* not free anymore */
+	rwd = write(fd, (char *) &tst_word, SIZE_OF_INT);
+	if (rwd != SIZE_OF_INT) {
+		printf("Bad write in zone map\n");
+		printf("Check file system \n");
+		done(DIR_CREATED);
+	}
+	return;
+  }
+  printf("Bit map indicates that block %lu is in use. Not marked.\n",
+	 (unsigned long) num);
+/*  done(DIR_CREATED); */
+  return;
+}
+
+ /* ======= interactive interface ======= */
+
+long rd_num()
+{				/* read a number from stdin */
+  long num;
+  int c;
+
+  if (eofseen) return(-1);
+  do {
+	c = getchar();
+	if (c == EOF || c == '\n') return(-1);
+  } while (c != '-' && (c < '0' || c > '9'));
+
+  if (c == '-') {
+	printf("Block numbers must be positive\n");
+	exit(1);
+  }
+  num = 0;
+  while (c >= '0' && c <= '9') {
+	num *= 10;
+	num += c - '0';
+	c = getchar();
+	if (c == '\n') eofseen = 1;
+  }
+  return num;
+}
+
+
+
+int ok(str)
+char *str;
+{
+  int c;
+
+  for (;;) {
+	printf("%s", str);
+	while ((c = getchar()) != EOF &&
+	       c != 'y' && c != 'n' && c != 'q')
+		if (c != '\n') printf(" Bad character %c\n", (char) c);
+	switch (c) {
+	    case EOF:
+		return QUIT;
+	    case 'y':
+		return OK;
+	    case 'n':
+		return NOT_OK;
+	    case 'q':	return QUIT;
+	}
+	printf("\n");
+  }
+}
+
+
+void done(nr)
+int nr;
+{
+  switch (nr) {
+      case SUCCESS:
+      case FILE_EXISTS:
+	unlink(file_name);
+      case DEV_MOUNTED:
+	umount(dev_name);
+      case DIR_CREATED:
+	rmdir(dir_name);
+      case HARMLESS:;
+  }
+  sync();
+  exit(nr == SUCCESS ? 0 : 1);
+}
Index: /trunk/minix/commands/simple/banner.c
===================================================================
--- /trunk/minix/commands/simple/banner.c	(revision 9)
+++ /trunk/minix/commands/simple/banner.c	(revision 9)
@@ -0,0 +1,153 @@
+/* banner - print a banner		Author: Brian Wallis */
+
+/*****************************************************************
+ *
+ * SYSVbanner.c
+ *
+ * This is a PD version of the SYS V banner program (at least I think
+ * it is compatible to SYS V) which I wrote to use with the clock
+ * program written by:
+ **     DCF, Inc.
+ **     14623 North 49th Place
+ **     Scottsdale, AZ 85254
+ * and published in the net comp.sources.misc newsgroup in early July
+ * since the BSD banner program works quite differently.
+ *
+ * There is no copyright or responsibility accepted for the use
+ * of this software.
+ *
+ * Brian Wallis, brw@jim.odr.oz, 4 July 1988
+ *
+ *****************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+
+_PROTOTYPE(int main, (int argc, char **argv));
+
+char *glyphs[] = {
+	  "         @@@  @@   @@  @ @   @@@@@          @@     @@@  ",
+	  "         @@@  @@   @@  @ @  @  @  @@@   @  @  @    @@@  ",
+	  "         @@@   @   @ @@@@@@@@  @   @@  @    @@      @   ",
+	  "          @            @ @   @@@@@    @    @@@     @    ",
+	  "                     @@@@@@@   @  @  @    @   @ @       ",
+	  "         @@@           @ @  @  @  @ @  @@ @    @        ",
+	  "         @@@           @ @   @@@@@ @   @@  @@@@ @       ",
+
+	  "   @@    @@                                            @",
+	  "  @        @   @   @    @                             @ ",
+	  " @          @   @ @     @                            @  ",
+	  " @          @ @@@@@@@ @@@@@   @@@   @@@@@           @   ",
+	  " @          @   @ @     @     @@@                  @    ",
+	  "  @        @   @   @    @      @            @@@   @     ",
+	  "   @@    @@                   @             @@@  @      ",
+
+	  "  @@@     @    @@@@@  @@@@@ @      @@@@@@@ @@@@@ @@@@@@@",
+	  " @   @   @@   @     @@     @@    @ @      @     @@    @ ",
+	  "@   @ @ @ @         @      @@    @ @      @          @  ",
+	  "@  @  @   @    @@@@@  @@@@@ @@@@@@@ @@@@@ @@@@@@    @   ",
+	  "@ @   @   @   @            @     @       @@     @  @    ",
+	  " @   @    @   @      @     @     @ @     @@     @  @    ",
+	  "  @@@   @@@@@ @@@@@@@ @@@@@      @  @@@@@  @@@@@   @    ",
+
+	  " @@@@@  @@@@@          @@@      @           @     @@@@@ ",
+	  "@     @@     @  @@@    @@@     @             @   @     @",
+	  "@     @@     @  @@@           @     @@@@@     @        @",
+	  " @@@@@  @@@@@@         @@@   @                 @     @@ ",
+	  "@     @      @         @@@    @     @@@@@     @     @   ",
+	  "@     @@     @  @@@     @      @             @          ",
+	  " @@@@@  @@@@@   @@@    @        @           @       @   ",
+
+	  " @@@@@    @   @@@@@@  @@@@@ @@@@@@ @@@@@@@@@@@@@@ @@@@@ ",
+	  "@     @  @ @  @     @@     @@     @@      @      @     @",
+	  "@ @@@ @ @   @ @     @@      @     @@      @      @      ",
+	  "@ @ @ @@     @@@@@@@ @      @     @@@@@@  @@@@@  @  @@@@",
+	  "@ @@@@ @@@@@@@@     @@      @     @@      @      @     @",
+	  "@     @@     @@     @@     @@     @@      @      @     @",
+	  " @@@@@ @     @@@@@@@  @@@@@ @@@@@@ @@@@@@@@       @@@@@ ",
+
+	  "@     @  @*@        @@    @ @      @     @@     @@@@@@@@",
+	  "@     @   @         @@   @  @      @@   @@@@    @@     @",
+	  "@     @   @         @@  @   @      @ @ @ @@ @   @@     @",
+	  "@@@@@@@   @         @@@@    @      @  @  @@  @  @@     @",
+	  "@     @   @   @     @@  @   @      @     @@   @ @@     @",
+	  "@     @   @   @     @@   @  @      @     @@    @@@     @",
+	  "@     @  @@@   @@@@@ @    @ @@@@@@@@     @@     @@@@@@@@",
+
+	  "@@@@@@  @@@@@ @@@@@@  @@@@@ @@@@@@@@     @@     @@     @",
+	  "@     @@     @@     @@     @   @   @     @@     @@  @  @",
+	  "@     @@     @@     @@         @   @     @@     @@  @  @",
+	  "@@@@@@ @     @@@@@@@  @@@@@    @   @     @@     @@  @  @",
+	  "@      @   @ @@   @        @   @   @     @ @   @ @  @  @",
+	  "@      @    @ @    @ @     @   @   @     @  @ @  @  @  @",
+	  "@       @@@@ @@     @ @@@@@    @    @@@@@    @    @@ @@ ",
+
+	  "@     @@     @@@@@@@@ @@@@@ @       @@@@@    @          ",
+	  " @   @  @   @      @  @      @          @   @ @         ",
+	  "  @ @    @ @      @   @       @         @  @   @        ",
+	  "   @      @      @    @        @        @               ",
+	  "  @ @     @     @     @         @       @               ",
+	  " @   @    @    @      @          @      @               ",
+	  "@     @   @   @@@@@@@ @@@@@       @ @@@@@        @@@@@@@",
+
+	  "  @@@                                                   ",
+	  "  @@@     @@   @@@@@   @@@@  @@@@@  @@@@@@ @@@@@@  @@@@ ",
+	  "   @     @  @  @    @ @    @ @    @ @      @      @    @",
+	  "    @   @    @ @@@@@  @      @    @ @@@@@  @@@@@  @     ",
+	  "        @@@@@@ @    @ @      @    @ @      @      @  @@@",
+	  "        @    @ @    @ @    @ @    @ @      @      @    @",
+	  "        @    @ @@@@@   @@@@  @@@@@  @@@@@@ @       @@@@ ",
+
+	  "                                                        ",
+	  " @    @    @        @ @    @ @      @    @ @    @  @@@@ ",
+	  " @    @    @        @ @   @  @      @@  @@ @@   @ @    @",
+	  " @@@@@@    @        @ @@@@   @      @ @@ @ @ @  @ @    @",
+	  " @    @    @        @ @  @   @      @    @ @  @ @ @    @",
+	  " @    @    @   @    @ @   @  @      @    @ @   @@ @    @",
+	  " @    @    @    @@@@  @    @ @@@@@@ @    @ @    @  @@@@ ",
+
+	  "                                                        ",
+	  " @@@@@   @@@@  @@@@@   @@@@   @@@@@ @    @ @    @ @    @",
+	  " @    @ @    @ @    @ @         @   @    @ @    @ @    @",
+	  " @    @ @    @ @    @  @@@@     @   @    @ @    @ @    @",
+	  " @@@@@  @  @ @ @@@@@       @    @   @    @ @    @ @ @@ @",
+	  " @      @   @  @   @  @    @    @   @    @  @  @  @@  @@",
+	  " @       @@@ @ @    @  @@@@     @    @@@@    @@   @    @",
+
+	  "                       @@@     @     @@@   @@    @ @ @ @",
+	  " @    @  @   @ @@@@@@ @        @        @ @  @  @ @ @ @ ",
+	  "  @  @    @ @      @  @        @        @     @@ @ @ @ @",
+	  "   @@      @      @  @@                 @@        @ @ @ ",
+	  "   @@      @     @    @        @        @        @ @ @ @",
+	  "  @  @     @    @     @        @        @         @ @ @ ",
+	  " @    @    @   @@@@@@  @@@     @     @@@         @ @ @ @"
+};
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int a, b, c, len, ind;
+  char line[80];
+
+  for (argv++; --argc; argv++) {
+	len = strlen(*argv);
+	if (len > 10) len = 10;
+	for (a = 0; a < 7; a++) {
+		for (b = 0; b < len; b++) {
+			if ((ind = (*argv)[b] - ' ') < 0) ind = 0;
+			for (c = 0; c < 7; c++) {
+				line[b * 8 + c] = glyphs[(ind / 8 * 7) + a][(ind % 8 * 7) + c] == '@' ? ind + ' ' : ' ';
+			}
+			line[b * 8 + 7] = ' ';
+		}
+		for (b = len * 8 - 1; b >= 0; b--) {
+			if (line[b] != ' ') break;
+			line[b] = '\0';
+		}
+		printf("%s\n", line);
+	}
+	printf("\n");
+  }
+  return(0);
+}
Index: /trunk/minix/commands/simple/basename.c
===================================================================
--- /trunk/minix/commands/simple/basename.c	(revision 9)
+++ /trunk/minix/commands/simple/basename.c	(revision 9)
@@ -0,0 +1,76 @@
+/* basename - print last part of a path      Authors: B. Garfolo & P. Nelson */
+
+/* Basename - print the last part of a path.
+ *
+ *    For MINIX  --  Conforms to POSIX - P1003.2/D10
+ *      Exception -- it ignores the LC environment variables.
+ *
+ *    Original MINIX author:  Blaine Garfolo
+ *    POSIX rewrite author:   Philip A. Nelson
+ *
+ *    POSIX version - October 20, 1990
+ *      Feb 14, 1991: changed rindex to strrchr. (PAN)
+ *
+ */
+
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define EOS '\0'
+
+_PROTOTYPE(int main, (int argc, char **argv));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  char *result_string;		/* The pointer into argv[1]. */
+  char *temp;			/* Used to move around in argv[1]. */
+  int suffix_len;		/* Length of the suffix. */
+  int suffix_start;		/* Where the suffix should start. */
+
+
+  /* Check for the correct number of arguments. */
+  if ((argc < 2) || (argc > 3)) {
+	fprintf(stderr, "Usage: basename string [suffix] \n");
+	exit(1);
+  }
+
+  /* Check for all /'s */
+  for (temp = argv[1]; *temp == '/'; temp++)	/* Move to next char. */
+	;
+  if (*temp == EOS) {
+	printf("/\n");
+	exit(0);
+  }
+
+  /* Build the basename. */
+  result_string = argv[1];
+
+  /* Find the last /'s */
+  temp = strrchr(result_string, '/');
+
+  if (temp != NULL) {
+	/* Remove trailing /'s. */
+	while ((*(temp + 1) == EOS) && (*temp == '/')) *temp-- = EOS;
+
+	/* Set result_string to last part of path. */
+	if (*temp != '/') temp = strrchr(result_string, '/');
+	if (temp != NULL && *temp == '/') result_string = temp + 1;
+  }
+
+  /* Remove the suffix, if any. */
+  if (argc > 2) {
+	suffix_len = strlen(argv[2]);
+	suffix_start = strlen(result_string) - suffix_len;
+	if (suffix_start > 0)
+		if (strcmp(result_string + suffix_start, argv[2]) == EOS)
+			*(result_string + suffix_start) = EOS;
+  }
+
+  /* Print the resultant string. */
+  printf("%s\n", result_string);
+  return(0);
+}
Index: /trunk/minix/commands/simple/build
===================================================================
--- /trunk/minix/commands/simple/build	(revision 9)
+++ /trunk/minix/commands/simple/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/simple/cal.c
===================================================================
--- /trunk/minix/commands/simple/cal.c	(revision 9)
+++ /trunk/minix/commands/simple/cal.c	(revision 9)
@@ -0,0 +1,315 @@
+/* cal - print a calendar		Author: Maritn Minow */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#define do3months	domonth
+#define	IO_SUCCESS	0	/* Unix definitions		 */
+#define	IO_ERROR	1
+#define	EOS	0
+
+#define	ENTRY_SIZE	3	/* 3 bytes per value		 */
+#define DAYS_PER_WEEK	7	/* Sunday, etc.			 */
+#define	WEEKS_PER_MONTH	6	/* Max. weeks in a month	 */
+#define	MONTHS_PER_LINE	3	/* Three months across		 */
+#define	MONTH_SPACE	3	/* Between each month		 */
+
+char *badarg = {"Bad argument\n"};
+char *how = {"Usage: cal [month] year\n"};
+
+/* Calendar() stuffs data into layout[],
+ * output() copies from layout[] to outline[], (then trims blanks).
+ */
+char layout[MONTHS_PER_LINE][WEEKS_PER_MONTH][DAYS_PER_WEEK][ENTRY_SIZE];
+char outline[(MONTHS_PER_LINE * DAYS_PER_WEEK * ENTRY_SIZE)
+       + (MONTHS_PER_LINE * MONTH_SPACE)
+       + 1];
+
+char *weekday = " S  M Tu  W Th  F  S";
+char *monthname[] = {
+	     "???",		/* No month 0	 */
+	     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void doyear, (int year));
+_PROTOTYPE(void domonth, (int year, int month));
+_PROTOTYPE(void output, (int nmonths));
+_PROTOTYPE(void calendar, (int year, int month, int indx));
+_PROTOTYPE(void usage, (char *s));
+_PROTOTYPE(int date, (int year, int month, int week, int wday));
+_PROTOTYPE(void setmonth, (int year, int month));
+_PROTOTYPE(int getdate, (int week, int wday));
+_PROTOTYPE(static int Jan1, (int year));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  register int year;
+
+  register int arg1val;
+  int arg1len;
+  int arg2val;
+
+  if (argc <= 1) {
+	usage(how);
+  } else {
+	arg1val = atoi(argv[1]);
+	arg1len = strlen(argv[1]);
+	if (argc == 2) {
+		/* Only one argument, if small, it's a month.  If
+		 * large, it's a year.  Note: cal		0082	Year
+		 * 0082 cal		82	Year 0082 */
+		if (arg1len <= 2 && arg1val <= 12)
+			do3months(year, arg1val);
+		else
+			doyear(arg1val);
+	} else {
+		/* Two arguments, allow 1980 12 or 12 1980 */
+		arg2val = atoi(argv[2]);
+		if (arg1len > 2)
+			do3months(arg1val, arg2val);
+		else
+			do3months(arg2val, arg1val);
+	}
+  }
+  return(IO_SUCCESS);
+}
+
+void doyear(year)
+int year;
+/* Print the calendar for an entire year. */
+{
+  register int month;
+
+  if (year < 1 || year > 9999) usage(badarg);
+  if (year < 100)
+	printf("\n\n\n                                 00%2d\n\n", year);
+  else
+	printf("\n\n\n%35d\n\n", year);
+  for (month = 1; month <= 12; month += MONTHS_PER_LINE) {
+	printf("%12s%23s%23s\n",
+	       monthname[month],
+	       monthname[month + 1],
+	       monthname[month + 2]);
+	printf("%s   %s   %s\n", weekday, weekday, weekday);
+	calendar(year, month + 0, 0);
+	calendar(year, month + 1, 1);
+	calendar(year, month + 2, 2);
+	output(3);
+#if MONTHS_PER_LINE != 3
+#error  "the above will not work"
+#endif
+  }
+  printf("\n\n\n");
+}
+
+void domonth(year, month)
+int year;
+int month;
+/* Do one specific month -- note: no longer used */
+{
+  if (year < 1 || year > 9999) usage(badarg);
+  if (month <= 0 || month > 12) usage(badarg);
+  printf("%9s%5d\n\n%s\n", monthname[month], year, weekday);
+  calendar(year, month, 0);
+  output(1);
+  printf("\n\n");
+}
+
+void output(nmonths)
+int nmonths;			/* Number of months to do	 */
+/* Clean up and output the text. */
+{
+  register int week;
+  register int month;
+  register char *outp;
+  int i;
+  char tmpbuf[21], *p;
+
+  for (week = 0; week < WEEKS_PER_MONTH; week++) {
+	outp = outline;
+	for (month = 0; month < nmonths; month++) {
+		/* The -1 in the following removes the unwanted
+		 * leading blank from the entry for Sunday. */
+		p = &layout[month][week][0][1];
+		for (i = 0; i < 20; i++) tmpbuf[i] = *p++;
+		tmpbuf[20] = 0;
+		sprintf(outp, "%s   ", tmpbuf);
+		outp += (DAYS_PER_WEEK * ENTRY_SIZE) + MONTH_SPACE - 1;
+	}
+	while (outp > outline && outp[-1] == ' ') outp--;
+	*outp = EOS;
+	printf("%s\n", outline);
+  }
+}
+
+void calendar(year, month, indx)
+int year;
+int month;
+int indx;			/* Which of the three months		 */
+/* Actually build the calendar for this month. */
+{
+  register char *tp;
+  int week;
+  register int wday;
+  register int today;
+
+  setmonth(year, month);
+  for (week = 0; week < WEEKS_PER_MONTH; week++) {
+	for (wday = 0; wday < DAYS_PER_WEEK; wday++) {
+		tp = &layout[indx][week][wday][0];
+		*tp++ = ' ';
+		today = getdate(week, wday);
+		if (today <= 0) {
+			*tp++ = ' ';
+			*tp++ = ' ';
+		} else if (today < 10) {
+			*tp++ = ' ';
+			*tp = (today + '0');
+		} else {
+			*tp++ = (today / 10) + '0';
+			*tp = (today % 10) + '0';
+		}
+	}
+  }
+}
+
+void usage(s)
+char *s;
+{
+/* Fatal parameter error. */
+
+  fprintf(stderr, "%s", s);
+  exit(IO_ERROR);
+}
+
+/* Calendar routines, intended for eventual porting to TeX
+ *
+ * date(year, month, week, wday)
+ *	Returns the date on this week (0 is first, 5 last possible)
+ *	and day of the week (Sunday == 0)
+ *	Note: January is month 1.
+ *
+ * setmonth(year, month)
+ *	Parameters are as above, sets getdate() for this month.
+ *
+ * int
+ * getdate(week, wday)
+ *	Parameters are as above, uses the data set by setmonth()
+ */
+
+/* This structure is used to pass data between setmonth() and getdate().
+ * It needs considerable expansion if the Julian->Gregorian change is
+ * to be extended to other countries.
+ */
+
+static struct {
+  int this_month;		/* month number used in 1752 checking	 */
+  int feb;			/* Days in February for this month	 */
+  int sept;			/* Days in September for this month	 */
+  int days_in_month;		/* Number of days in this month		 */
+  int dow_first;		/* Day of week of the 1st day in month	 */
+} info;
+
+static int day_month[] = {	/* 30 days hath September...		 */
+		  0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+int date(year, month, week, wday)
+int year;			/* Calendar date being computed		 */
+int month;			/* January == 1				 */
+int week;			/* Week in the month 0..5 inclusive	 */
+int wday;			/* Weekday, Sunday == 0			 */
+/* Return the date of the month that fell on this week and weekday.
+ * Return zero if it's out of range.
+ */
+{
+  setmonth(year, month);
+  return(getdate(week, wday));
+}
+
+void setmonth(year, month)
+int year;			/* Year to compute		 */
+int month;			/* Month, January is month 1	 */
+/* Setup the parameters needed to compute this month
+ * (stored in the info structure).
+ */
+{
+  register int i;
+
+  if (month < 1 || month > 12) {/* Verify caller's parameters	 */
+	info.days_in_month = 0;	/* Garbage flag			 */
+	return;
+  }
+  info.this_month = month;	/* used in 1752	checking	 */
+  info.dow_first = Jan1(year);	/* Day of January 1st for now	 */
+  info.feb = 29;		/* Assume leap year		 */
+  info.sept = 30;		/* Assume normal year		 */
+  /* Determine whether it's an ordinary year, a leap year or the
+   * magical calendar switch year of 1752. */
+  switch ((Jan1(year + 1) + 7 - info.dow_first) % 7) {
+      case 1:			/* Not a leap year		 */
+	info.feb = 28;
+      case 2:			/* Ordinary leap year		 */
+	break;
+
+      default:			/* The magical moment arrives	 */
+	info.sept = 19;		/* 19 days hath September	 */
+	break;
+  }
+  info.days_in_month =
+	(month == 2) ? info.feb
+	: (month == 9) ? info.sept
+	: day_month[month];
+  for (i = 1; i < month; i++) {
+	switch (i) {		/* Special months?		 */
+	    case 2:		/* February			 */
+		info.dow_first += info.feb;
+		break;
+
+	    case 9:	info.dow_first += info.sept;	break;
+
+	    default:
+		info.dow_first += day_month[i];
+		break;
+	}
+  }
+  info.dow_first %= 7;		/* Now it's Sunday to Saturday	 */
+}
+
+int getdate(week, wday)
+int week;
+int wday;
+{
+  register int today;
+
+  /* Get a first guess at today's date and make sure it's in range. */
+  today = (week * 7) + wday - info.dow_first + 1;
+  if (today <= 0 || today > info.days_in_month)
+	return(0);
+  else if (info.sept == 19 && info.this_month == 9
+	 && today >= 3)		/* The magical month?	 */
+	return(today + 11);	/* If so, some dates changed	 */
+  else				/* Otherwise,			 */
+	return(today);		/* Return the date		 */
+}
+
+static int Jan1(year)
+int year;
+/* Return day of the week for Jan 1 of the specified year. */
+{
+  register int day;
+
+  day = year + 4 + ((year + 3) / 4);	/* Julian Calendar	 */
+  if (year > 1800) {		/* If it's recent, do	 */
+	day -= ((year - 1701) / 100);	/* Clavian correction	 */
+	day += ((year - 1601) / 400);	/* Gregorian correction	 */
+  }
+  if (year > 1752)		/* Adjust for Gregorian	 */
+	day += 3;		/* calendar		 */
+  return(day % 7);
+}
Index: /trunk/minix/commands/simple/calendar.c
===================================================================
--- /trunk/minix/commands/simple/calendar.c	(revision 9)
+++ /trunk/minix/commands/simple/calendar.c	(revision 9)
@@ -0,0 +1,232 @@
+/* calendar - reminder service		Authors: S. & K. Hirabayashi */
+
+/* Permission is hereby granted for nonprofit use. */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <regexp.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termcap.h>
+#include <unistd.h>
+#include <utime.h>
+#include <stdio.h>
+
+/* Change these two lines for your system needs. */
+#define MAIL1	"/usr/bin/mail"
+#define MAIL2	"/bin/mail"
+#define PASSWD	"/etc/passwd"	/* system password file */
+#define MAX_EXP		4	/* see date_exp() function */
+
+char *mail;			/* mail command path ("/bin/mail" etc) */
+regexp *exp[MAX_EXP];		/* date expressions */
+int nexp;			/* # of the date expressions */
+char calfile[PATH_MAX];		/* calendar file for the user */
+
+int rflg;			/* consult aged 'calendar' file and touch */
+int mflg;			/* mail (multi user) service */
+char *cmd;			/* the name of this command */
+char buf[BUFSIZ];
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void calendar, (void));
+_PROTOTYPE(char *getstr, (char *s, int n));
+_PROTOTYPE(int newaccess, (char *file));
+_PROTOTYPE(void grep, (char *file, char *user));
+_PROTOTYPE(int date_exp, (void));
+_PROTOTYPE(char *date_pat, (time_t t));
+/*
+_PROTOTYPE(void regerror, (char *s));
+*/
+_PROTOTYPE(void error, (char *s, char *t));
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  char *s;
+
+  cmd = *argv;
+  while (--argc > 0 && (*++argv)[0] == '-') {
+	s = argv[0] + 1;
+	if (*s == '\0')
+		mflg++;		/* mail service */
+	else if (strcmp(s, "r") == 0)
+		rflg++, mflg++;
+  }
+
+  if (mflg) {			/* check mailing agent */
+	if (access(MAIL1, X_OK) == 0)
+		mail = MAIL1;
+	else if (access(MAIL2, X_OK) == 0)
+		mail = MAIL2;
+	else
+		error("cannot find %s", MAIL1);
+  }
+  nexp = date_exp();
+  calendar();
+  exit(0);
+}
+
+void calendar()
+{
+  int i;
+  char *s;
+  FILE *fp;
+
+  if (!mflg) {
+	grep("calendar", "");
+	return;
+  }
+
+  /* Mail sevice */
+  if ((fp = fopen(PASSWD, "r")) == (FILE *) NULL)
+	error("cannot open %s", PASSWD);
+
+  while (fgets(buf, BUFSIZ, fp) != (char *) NULL) {
+	for (i = 0, s = buf; *s && *s != '\n'; s++)
+		if (*s == ':') i++;
+	*s = '\0';
+	if (i != 6) error("illegal '/etc/passwd' format: %s", buf);
+
+	/* Calendar file = ${HOME}/calendar */
+	sprintf(calfile, "%s/%s", getstr(buf, 5), "calendar");
+
+	if ((access(calfile, R_OK) != 0) || (rflg && !newaccess(calfile)))
+		continue;
+
+	grep(calfile, getstr(buf, 0));
+  }
+
+  fclose(fp);
+}
+
+char *getstr(s, n)
+char *s;
+int n;
+{
+/* Returns the string value of the n-th field in the record (s) */
+  int i;
+  char *t;
+  static char str[512];
+
+  for (i = 0; i < n && *s; s++)
+	if (*s == ':') i++;		/* field separator */
+  for (i = 0, t = str; *s && *s != ':' && i < 511; i++) *t++ = *s++;
+  *t = '\0';
+  return str;
+}
+
+int newaccess(file)
+char *file;			/* file name */
+{
+/* Check whether the file has been touched today. */
+
+  int r = 0;
+  struct tm *tm;
+  struct stat stbuf;
+  time_t clk;
+  char newdate[8], olddate[8];
+
+  time(&clk);
+  tm = localtime(&clk);
+  sprintf(newdate, "%02d%02d%02d", tm->tm_year, tm->tm_mon + 1, tm->tm_mday);
+
+  if (stat(file, &stbuf) == -1) error("cannot stat %s", file);
+  tm = localtime(&stbuf.st_mtime);
+  sprintf(olddate, "%02d%02d%02d", tm->tm_year, tm->tm_mon + 1, tm->tm_mday);
+
+  if (strcmp(newdate, olddate) != 0) {
+	utime(file, NULL);	/* touch */
+	r++;
+  }
+  return r;
+}
+
+void grep(file, user)
+char *file, *user;
+{				/* grep 'exp[]' [| mail user] */
+  int i;
+  char command[128];		/* mail command */
+  FILE *ifp, *ofp;
+
+  if ((ifp = fopen(file, "r")) == (FILE *) NULL)
+	error("cannot open %s", file);
+  if (*user != '\0') {
+	sprintf(command, "%s %s", mail, user);
+	ofp = (FILE *) NULL;
+  } else {
+	ofp = stdout;
+  }
+
+  while (fgets(buf, BUFSIZ, ifp) != (char *) NULL) {
+	for (i = 0; i < nexp; i++) {
+		if (regexec(exp[i], buf, 1)) {
+			if ((ofp == (FILE *) NULL) &&
+				  (ofp = popen(command, "w")) == (FILE *) NULL)
+				error("cannot popen %s", mail);
+			fputs(buf, ofp);
+			break;
+		}
+	}
+  }
+
+  fclose(ifp);
+  if (ofp == stdout)
+	fflush(ofp);
+  else if (ofp != (FILE *) NULL)
+	pclose(ofp);
+}
+
+int date_exp()
+{
+/* Set compiled regular expressions into the exp[] array. */
+  static int n[] = {2, 2, 2, 2, 2, 4, 3};
+  int i, r, wday;
+  time_t clk;
+
+  time(&clk);
+  wday = localtime(&clk)->tm_wday;
+  r = n[wday];
+  if (r > MAX_EXP) error("too many date expressions", "");
+  for (i = 0; i < r; i++) {
+	exp[i] = regcomp(date_pat(clk));
+	clk += 60 * 60 * 24L;	/* 24 hours */
+  }
+  return(r);
+}
+
+char *date_pat(t)
+time_t t;
+{				/* returns date expression for the time (t) */
+  static char *month[] = {
+	 "[Jj]an", "[Ff]eb", "[Mm]ar", "[Aa]pr", "[Mm]ay", "[Jj]un",
+	  "[Jj]ul", "[Aa]ug", "[Ss]ep", "[Oo]ct", "[Nn]ov", "[Dd]ec"
+  };
+  static char str[512];
+  struct tm *tm;
+
+  tm = localtime(&t);
+  sprintf(str,
+	"(^|[ \t(,;])(((%s[^ \t]*[ \t])|0*%d/|\\*/)(0*%d|\\*))([^0123456789]|$)",
+	month[tm->tm_mon], tm->tm_mon + 1, tm->tm_mday);
+
+  return str;
+}
+
+void regerror(s)
+const char *s;
+{				/* regcomp() needs this */
+  error("REGULAR EXPRESSION ERROR (%s)", (char *) s);
+}
+
+void error(s, t)
+char *s, *t;
+{
+  fprintf(stderr, "%s: ", cmd);
+  fprintf(stderr, s, t);
+  fprintf(stderr, "\n");
+  exit(1);
+}
Index: /trunk/minix/commands/simple/cat.c
===================================================================
--- /trunk/minix/commands/simple/cat.c	(revision 9)
+++ /trunk/minix/commands/simple/cat.c	(revision 9)
@@ -0,0 +1,138 @@
+/* cat - concatenates files  		Author: Andy Tanenbaum */
+
+/* 30 March 1990 - Slightly modified for efficiency by Norbert Schlenker. */
+/* 23 March 2002 - Proper error messages by Kees J. Bot. */
+
+
+#include <errno.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <minix/minlib.h>
+#include <stdio.h>
+
+#define CHUNK_SIZE	(2048 * sizeof(char *))
+
+static int unbuffered;
+static char ibuf[CHUNK_SIZE];
+static char obuf[CHUNK_SIZE];
+static char *op = obuf;
+
+int main(int argc, char **argv);
+static void copyout(char *file, int fd);
+static void output(char *buf, size_t count);
+static void report(char *label);
+static void fatal(char *label);
+
+static char STDIN[] = "standard input";
+static char STDOUT[] = "standard output";
+
+static int excode = 0;
+
+int main(int argc, char *argv[])
+{
+  int i, fd;
+
+  i = 1;
+  while (i < argc && argv[i][0] == '-') {
+	char *opt = argv[i] + 1;
+
+	if (opt[0] == 0) break;				/* - */
+	i++;
+	if (opt[0] == '-' && opt[1] == 0) break;	/* -- */
+
+	while (*opt != 0) switch (*opt++) {
+	case 'u':
+		unbuffered = 1;
+		break;
+	default:
+		std_err("Usage: cat [-u] [file ...]\n");
+		exit(1);
+	}
+  }
+
+  if (i >= argc) {
+	copyout(STDIN, STDIN_FILENO);
+  } else {
+	while (i < argc) {
+		char *file = argv[i++];
+
+		if (file[0] == '-' && file[1] == 0) {
+			copyout(STDIN, STDIN_FILENO);
+		} else {
+			fd = open(file, O_RDONLY);
+			if (fd < 0) {
+				report(file);
+			} else {
+				copyout(file, fd);
+				close(fd);
+			}
+		}
+	}
+  }
+  output(obuf, (op - obuf));
+  return(excode);
+}
+
+static void copyout(char *file, int fd)
+{
+  int n;
+
+  while (1) {
+	n = read(fd, ibuf, CHUNK_SIZE);
+	if (n < 0) fatal(file);
+	if (n == 0) return;
+	if (unbuffered || (op == obuf && n == CHUNK_SIZE)) {
+		output(ibuf, n);
+	} else {
+		int bytes_left;
+
+		bytes_left = &obuf[CHUNK_SIZE] - op;
+		if (n <= bytes_left) {
+			memcpy(op, ibuf, (size_t)n);
+			op += n;
+		} else {
+			memcpy(op, ibuf, (size_t)bytes_left);
+			output(obuf, CHUNK_SIZE);
+			n -= bytes_left;
+			memcpy(obuf, ibuf + bytes_left, (size_t)n);
+			op = obuf + n;
+		}
+	}
+  }
+}
+
+static void output(char *buf, size_t count)
+{
+  ssize_t n;
+
+  while (count > 0) {
+	n = write(STDOUT_FILENO, buf, count);
+	if (n <= 0) {
+		if (n < 0) fatal(STDOUT);
+		std_err("cat: standard output: EOF\n");
+		exit(1);
+	}
+	buf += n;
+	count -= n;
+  }
+}
+
+static void report(char *label)
+{
+  int e = errno;
+  std_err("cat: ");
+  std_err(label);
+  std_err(": ");
+  std_err(strerror(e));
+  std_err("\n");
+  excode = 1;
+}
+
+static void fatal(char *label)
+{
+  report(label);
+  exit(1);
+}
Index: /trunk/minix/commands/simple/cdiff.c
===================================================================
--- /trunk/minix/commands/simple/cdiff.c	(revision 9)
+++ /trunk/minix/commands/simple/cdiff.c	(revision 9)
@@ -0,0 +1,365 @@
+/* cdiff - context diff			Author: Larry Wall */
+
+/* Cdiff - turns a regular diff into a new-style context diff
+ *
+ * Usage: cdiff file1 file2
+ */
+
+#define PATCHLEVEL 2
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdio.h>
+
+char buff[512];
+
+FILE *inputfp, *oldfp, *newfp;
+
+int oldmin, oldmax, newmin, newmax;
+int oldbeg, oldend, newbeg, newend;
+int preoldmax, prenewmax;
+int preoldbeg, preoldend, prenewbeg, prenewend;
+int oldwanted, newwanted;
+
+char *oldhunk, *newhunk;
+char *progname;
+size_t oldsize, oldalloc, newsize, newalloc;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void dumphunk, (void));
+_PROTOTYPE(char *getold, (int targ));
+_PROTOTYPE(char *getnew, (int targ));
+_PROTOTYPE(void *xmalloc, (size_t size));
+_PROTOTYPE(void *xrealloc, (void *ptr, size_t size));
+
+#define Nullfp (FILE*)0
+#define Nullch (char*)0
+#define ENOUGH (NAME_MAX + PATH_MAX + 1)
+#define CRC_END 12
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  FILE *crcfp;
+  char *old, *new;
+  int context = 3;
+  struct stat statbuf;
+  register char *s;
+  char op;
+  char *newmark, *oldmark;
+  char sysbuf1[ENOUGH], sysbuf2[ENOUGH];
+  int len;
+  char *line;
+  int i;
+  int status;
+
+  progname = argv[0];
+  oldalloc = 512;
+  oldhunk = (char *) xmalloc(oldalloc);
+  newalloc = 512;
+  newhunk = (char *) xmalloc(newalloc);
+
+  for (argc--, argv++; argc; argc--, argv++) {
+	if (argv[0][0] != '-') break;
+
+	if (argv[0][1] == 'c') context = atoi(argv[0] + 2);
+  }
+
+  if (argc != 2) {
+	fprintf(stderr, "Usage: cdiff old new\n");
+	exit(2);
+  }
+  old = argv[0];
+  new = argv[1];
+
+  oldfp = fopen(old, "r");
+  if (!oldfp) {
+	fprintf(stderr, "Can't open %s\n", old);
+	exit(2);
+  }
+  newfp = fopen(new, "r");
+  if (!newfp) {
+	fprintf(stderr, "Can't open %s\n", new);
+	exit(2);
+  }
+
+  /* Compute crcs by popen()ing crc and reading the output.  Do this before
+   * popen()ing diff to do the work.  popen() attempts to support multiple
+   * clients, but the 1.3-1.6.24b versions don't succeed.
+   */
+  sprintf(sysbuf1, "crc %s", old);
+  crcfp = popen(sysbuf1, "r");
+  if (!crcfp) {
+	/* The only advantage of cdiff over diff is that it prints crcs, so
+	 * give up easily if crc fails.
+	 */
+	fprintf(stderr, "Can't execute crc %s\n", old);
+	exit(2);
+  }
+  fgets(sysbuf1, sizeof(sysbuf1), crcfp);
+  sysbuf1[CRC_END] = '\0';
+  status = pclose(crcfp);
+  if (status != 0) {
+	fprintf(stderr, "crc %s returned bad status %d\n", old, status);
+	exit(2);
+  }
+  sprintf(sysbuf2, "crc %s", new);
+  crcfp = popen(sysbuf2, "r");
+  if (!crcfp) {
+	fprintf(stderr, "Can't execute crc %s\n", new);
+	exit(2);
+  }
+  fgets(sysbuf2, sizeof(sysbuf2), crcfp);
+  sysbuf2[CRC_END] = '\0';
+  status = pclose(crcfp);
+  if (status != 0) {
+	fprintf(stderr, "crc %s returned bad status %d\n", new, status);
+	exit(2);
+  }
+
+  sprintf(buff, "diff %s %s 2>/dev/null", old, new);
+  inputfp = popen(buff, "r");
+  if (!inputfp) {
+	fprintf(stderr, "Can't execute diff %s %s\n", old, new);
+	exit(2);
+  }
+
+  fstat(fileno(oldfp), &statbuf);
+  printf("*** %s  crc=%s\t%s", old, sysbuf1, ctime(&statbuf.st_mtime));
+  fstat(fileno(newfp), &statbuf);
+  printf("--- %s  crc=%s\t%s", new, sysbuf2, ctime(&statbuf.st_mtime));
+
+  preoldend = -1000;
+
+  while (fgets(buff, sizeof buff, inputfp) != Nullch) {
+	if (isdigit(*buff)) {
+		oldmin = atoi(buff);
+		for (s = buff; isdigit(*s); s++);
+		if (*s == ',') {
+			s++;
+			oldmax = atoi(s);
+			for (; isdigit(*s); s++);
+		} else {
+			oldmax = oldmin;
+		}
+		if (*s != 'a' && *s != 'd' && *s != 'c') {
+			fprintf(stderr, "Unparseable input: %s\n", s);
+			exit(2);
+		}
+		op = *s;
+		s++;
+		newmin = atoi(s);
+		for (; isdigit(*s); s++);
+		if (*s == ',') {
+			s++;
+			newmax = atoi(s);
+			for (; isdigit(*s); s++);
+		} else {
+			newmax = newmin;
+		}
+		if (*s != '\n' && *s != ' ') {
+			fprintf(stderr, "Unparseable input: %s\n", s);
+			exit(2);
+		}
+		newmark = oldmark = "! ";
+		if (op == 'a') {
+			oldmin++;
+			newmark = "+ ";
+		}
+		if (op == 'd') {
+			newmin++;
+			oldmark = "- ";
+		}
+		oldbeg = oldmin - context;
+		oldend = oldmax + context;
+		if (oldbeg < 1) oldbeg = 1;
+		newbeg = newmin - context;
+		newend = newmax + context;
+		if (newbeg < 1) newbeg = 1;
+
+		if (preoldend < oldbeg - 1) {
+			if (preoldend >= 0) {
+				dumphunk();
+			}
+			preoldbeg = oldbeg;
+			prenewbeg = newbeg;
+			oldwanted = newwanted = 0;
+			oldsize = newsize = 0;
+		} else {	/* we want to append to previous hunk */
+			oldbeg = preoldmax + 1;
+			newbeg = prenewmax + 1;
+		}
+
+		for (i = oldbeg; i <= oldmax; i++) {
+			line = getold(i);
+			if (!line) {
+				oldend = oldmax = i - 1;
+				break;
+			}
+			len = strlen(line) + 2;
+			if (oldsize + len + 1 >= oldalloc) {
+				oldalloc *= 2;
+				oldhunk = (char *) xrealloc(oldhunk, oldalloc);
+			}
+			if (i >= oldmin) {
+				strcpy(oldhunk + oldsize, oldmark);
+				oldwanted++;
+			} else {
+				strcpy(oldhunk + oldsize, "  ");
+			}
+			strcpy(oldhunk + oldsize + 2, line);
+			oldsize += len;
+		}
+		preoldmax = oldmax;
+		preoldend = oldend;
+
+		for (i = newbeg; i <= newmax; i++) {
+			line = getnew(i);
+			if (!line) {
+				newend = newmax = i - 1;
+				break;
+			}
+			len = strlen(line) + 2;
+			if (newsize + len + 1 >= newalloc) {
+				newalloc *= 2;
+				newhunk = (char *) xrealloc(newhunk, newalloc);
+			}
+			if (i >= newmin) {
+				strcpy(newhunk + newsize, newmark);
+				newwanted++;
+			} else {
+				strcpy(newhunk + newsize, "  ");
+			}
+			strcpy(newhunk + newsize + 2, line);
+			newsize += len;
+		}
+		prenewmax = newmax;
+		prenewend = newend;
+	}
+  }
+
+  if (preoldend >= 0) {
+	dumphunk();
+  }
+  status = pclose(inputfp);
+  if (!WIFEXITED(status)) exit(2);
+  status = WEXITSTATUS(status);
+  return(status == 0 || status == 1 ? status : 2);
+}
+
+void dumphunk()
+{
+  int i;
+  char *line;
+  int len;
+
+  for (i = preoldmax + 1; i <= preoldend; i++) {
+	line = getold(i);
+	if (!line) {
+		preoldend = i - 1;
+		break;
+	}
+	len = strlen(line) + 2;
+	if (oldsize + len + 1 >= oldalloc) {
+		oldalloc *= 2;
+		oldhunk = (char *) xrealloc(oldhunk, oldalloc);
+	}
+	strcpy(oldhunk + oldsize, "  ");
+	strcpy(oldhunk + oldsize + 2, line);
+	oldsize += len;
+  }
+  for (i = prenewmax + 1; i <= prenewend; i++) {
+	line = getnew(i);
+	if (!line) {
+		prenewend = i - 1;
+		break;
+	}
+	len = strlen(line) + 2;
+	if (newsize + len + 1 >= newalloc) {
+		newalloc *= 2;
+		newhunk = (char *) xrealloc(newhunk, newalloc);
+	}
+	strcpy(newhunk + newsize, "  ");
+	strcpy(newhunk + newsize + 2, line);
+	newsize += len;
+  }
+  printf("***************\n");
+  if (preoldbeg >= preoldend) {
+	printf("*** %d ****\n", preoldend);
+  } else {
+	printf("*** %d,%d ****\n", preoldbeg, preoldend);
+  }
+  if (oldwanted) {
+	printf("%s", oldhunk);
+  }
+  oldsize = 0;
+  *oldhunk = '\0';
+  if (prenewbeg >= prenewend) {
+	printf("--- %d ----\n", prenewend);
+  } else {
+	printf("--- %d,%d ----\n", prenewbeg, prenewend);
+  }
+  if (newwanted) {
+	printf("%s", newhunk);
+  }
+  newsize = 0;
+  *newhunk = '\0';
+}
+
+char *getold(targ)
+int targ;
+{
+  static int oldline = 0;
+
+  while (fgets(buff, sizeof buff, oldfp) != Nullch) {
+	oldline++;
+	if (oldline == targ) return buff;
+  }
+  return Nullch;
+}
+
+char *getnew(targ)
+int targ;
+{
+  static int newline = 0;
+
+  while (fgets(buff, sizeof buff, newfp) != Nullch) {
+	newline++;
+	if (newline == targ) return buff;
+  }
+  return Nullch;
+}
+
+void *xmalloc(size)
+size_t size;
+{
+  void *ptr;
+
+  ptr = malloc(size);
+  if (ptr == NULL) {
+	fprintf(stderr, "%s: out of memory\n", progname);
+	exit(2);
+  }
+  return(ptr);
+}
+
+void *xrealloc(ptr, size)
+void *ptr;
+size_t size;
+{
+  ptr = realloc(ptr, size);
+  if (ptr == NULL) {
+	fprintf(stderr, "%s: out of memory\n", progname);
+	exit(2);
+  }
+  return(ptr);
+}
Index: /trunk/minix/commands/simple/cdprobe.c
===================================================================
--- /trunk/minix/commands/simple/cdprobe.c	(revision 9)
+++ /trunk/minix/commands/simple/cdprobe.c	(revision 9)
@@ -0,0 +1,130 @@
+/* This file contains some code to guess where we have to load the
+ * RAM image device from, if started from CD. (In this case it's hard
+ * to tell where this is without diving into BIOS heuristics.)
+ *
+ * There is some nasty hard-codery in here ( MINIX cd label) that can be
+ * improved on.
+ *
+ * Changes:
+ *   Jul 14, 2005   Created (Ben Gras)
+ *   Feb 10, 2006   Changed into a standalone program (Philip Homburg)
+ */
+
+#define CD_SECTOR	2048
+#define SUPER_OFF	1024
+#define AT_MINORS	8
+#define MAGIC_OFF	24
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../../servers/fs/const.h"
+
+char pvd[CD_SECTOR];
+
+/*===========================================================================*
+ *				cdprobe					     *
+ *===========================================================================*/
+int main(void)
+{
+	int i, r, fd, minor, found;
+	off_t pos;
+	u16_t *magicp;
+	char name1[]= "/dev/c0dX";
+	char name2[]= "/dev/c0dXpY";
+
+	found= 0;
+	for(i = 0; i < AT_MINORS; i++) {
+		name1[8]= '0' + i;
+
+		fd = open(name1, O_RDONLY);
+		if (fd < 0)
+		{
+			if (errno != ENXIO)
+			{
+				fprintf(stderr, "open '%s' failed: %s\n",
+					name1, strerror(errno));
+			}
+			continue;
+		}
+
+		pos= lseek(fd, 16*CD_SECTOR, SEEK_SET);
+		if (pos != 16*CD_SECTOR)
+		{
+			/* Strange, do we need to issue a warning? */
+			close(fd);
+			continue;
+		}
+		r = read(fd, pvd, sizeof(pvd));
+		if (r != sizeof(pvd))
+		{
+			fprintf(stderr,
+				"error reading CD label from '%s': %s\n",
+				name1, strerror(errno));
+			close(fd);
+			continue;
+		}
+		close(fd);
+
+		/* Check PVD ID. */
+		if (pvd[0] !=  1  || pvd[1] != 'C' || pvd[2] != 'D' ||
+		   pvd[3] != '0' || pvd[4] != '0' || pvd[5] != '1' ||
+		   pvd[6] != 1 ||
+		   strncmp(pvd + 40, "MINIX", 5) != 0) {
+		   	continue;
+		}
+
+		/* 3. Both c0dXp1 and p2 should have a superblock. */
+		found= 1;	/* Assume everything is okay */
+		for (minor = 1; minor <= 2; minor++) {
+			name2[8]= '0' + i;
+			name2[10]= '0' + minor;
+
+			fd = open(name2, O_RDONLY);
+			if (fd < 0)
+			{
+				if (errno != ENXIO)
+				{
+					fprintf(stderr,
+						"open '%s' failed: %s\n",
+						name2, strerror(errno));
+				}
+				found= 0;
+				break;
+			}
+			r = read(fd, pvd, sizeof(pvd));
+			if (r != sizeof(pvd))
+			{
+				fprintf(stderr,
+				"error reading super block from '%s': %s\n",
+					name2, strerror(errno));
+				close(fd);
+				found= 0;
+				break;
+			}
+			close(fd);
+
+			magicp= (u16_t *)&pvd[SUPER_OFF+MAGIC_OFF];
+			if (*magicp != SUPER_V3)
+			{
+				fprintf(stderr, "bad super block on %s\n",
+					name2);
+				found= 0;
+				break;
+			}
+		}
+
+		if (found)
+		{
+			printf("%s\n", name1);
+			exit(0);
+		}
+	}
+
+	return 1;
+}
+
Index: /trunk/minix/commands/simple/cgrep.c
===================================================================
--- /trunk/minix/commands/simple/cgrep.c	(revision 9)
+++ /trunk/minix/commands/simple/cgrep.c	(revision 9)
@@ -0,0 +1,379 @@
+/* cgrep - grep and display context	Author: Mark Mallet */
+
+/*
+        Nov 19 1984     Mark Mallett   (mem@zinn.MV.COM)
+
+mem	860224	Modified to do r/e (regular expression) parsing on unix
+mem	860324	Added -f, -n; added code to number lines correctly on output.
+mem	870325	Added support for regcmp()/regex() style regular expression
+  library; redid some conditionals to provide better mix'n'match.
+mem	870326	Don't try to print the filename if reading from stdin.
+  Add -w option.  Fix a small problem which occasionally allowed
+  the separator to come out between adjacent lines of the file.
+mem	871119	Fix semantics of call to regcmp(): the NULL terminating the
+  argument list was missing.  It worked, but probably only
+  due to some bizarre coincidence.
+dro	890109  Minor mods to compile under Minix
+
+*/
+
+#define  OS_UNIX		/* Define this for unix systems */
+ /* #define	REGEX *//* Define this for re_comp/re_exec library */
+#define  REGCMP			/* Define this to use regcmp/regex */
+ /* #define	OS_CPM *//* Define this for CP/M-80 */
+
+
+/* Don't touch these */
+#define	NOREGEXP		/* Set this for no regular expression */
+#ifdef	REGEX
+#undef	NOREGEXP
+#endif	/* REGEX */
+
+#ifdef	REGCMP
+#undef	NOREGEXP
+#endif	/* REGCMP */
+
+
+#ifdef OS_CPM
+#include "stdio.h"
+#include "ctype.h"
+#endif /* OS_CPM */
+
+#ifdef OS_UNIX
+#include <sys/types.h>
+#include <sys/dir.h>		/* Either here or in sys directory - dro */
+#include <ctype.h>
+#include <limits.h>		/* should have this                - dro */
+#include <regexp.h>		/* should have this                - dro */
+#include <stdlib.h>
+#include <stdio.h>
+#endif /* OS_UNIX */
+
+
+/* Local definitions */
+
+#ifndef	NULL
+#define	NULL	((char *)0)
+#endif	/* NULL */
+
+#ifndef NUL
+#define NUL     '\000'
+#endif
+
+#ifndef TRUE
+#define TRUE    1
+#define FALSE   0
+#endif
+
+
+/* Internal data declared global */
+
+
+/* Internal routines */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void dosrch, (char *ifnm));
+_PROTOTYPE(void shwlin, (char *fnm, int linnum, char *line));
+_PROTOTYPE(int matlin, (char *line));
+_PROTOTYPE(void regerror, (const char *s));
+
+/* External data */
+
+
+/* Local data */
+
+static int Debug = {FALSE};	/* Debug enabled flag */
+static int Lcur = {0};		/* Current line (in Lines array) */
+static char **Lines = {NULL};	/* Lines pointer array */
+static int Linlen = {100};	/* Line length */
+static int Lone = {0};		/* Line one (in Lines array) */
+static int Nmr = {0};		/* Number of matched regions */
+static char *Pat = {NULL};	/* Pattern */
+static char Shwfile = {TRUE};	/* Show file name... */
+static char Shwline = {TRUE};	/* Show line number */
+static int Waft = {0};		/* Window after */
+static int Wbef = {0};		/* Window before */
+static int Wsiz = {0};		/* Window size */
+
+regexp *Re;			/* Result from reg compilation */
+
+int main(argc, argv)
+int argc;			/* Argument count */
+char **argv;			/* Argument values */
+
+{
+  int i;			/* Scratch */
+  int n;			/* Scratch again */
+  int c;			/* A character */
+  char *aptr;			/* Argument pointer */
+  int nf;			/* number of files on command line */
+
+  nf = 0;			/* No files on line */
+
+  for (i = 1; i < argc; i++) {	/* Look at args */
+	if (argv[i][0] != '-') {/* If option */
+		if (Pat == NULL) {	/* If no pattern yet given */
+			Pat = argv[i];	/* point here */
+#ifdef	REGEX
+			if ((Re = re_comp(Pat)) != NULL) {
+				fprintf(stderr, "cgrep: %s\n", re);
+				exit(1);
+			}
+#endif	/* REGEX */
+
+#ifdef	REGCMP
+			if ((Re = regcomp(Pat)) == NULL) {
+				fprintf(stderr, "cgrep: error in regular expression.\n");
+				exit(1);
+			}
+#endif	/* REGCMP */
+
+		} else {	/* This must be a file to search */
+			nf++;	/* Count it */
+			dosrch(argv[i]);	/* Search */
+		}
+	} else {		/* Option char */
+		c = argv[i][1];	/* Get option char */
+		if (isupper(c))	/* Trap idiot definition of tolower */
+			c = tolower(c);	/* Don't care about case */
+		n = i;
+		aptr = NULL;	/* Find arg, if any */
+		if (argv[i][2] != NUL) {
+			aptr = &argv[i][2];
+			n = i;	/* Where to set i if we use this arg */
+		} else if (i < argc - 1) {	/* use next.. */
+			n = i + 1;
+			aptr = argv[n];
+		}
+		switch (c) {	/* Process the option */
+		    case 'a':	/* Lines after */
+			Waft = atoi(aptr);
+			Lines = NULL;
+			i = n;
+			break;
+
+		    case 'b':	/* Lines before */
+			Wbef = atoi(aptr);
+			Lines = NULL;
+			i = n;
+			break;
+
+/* Disable debug output
+                    case 'd':	Debug = TRUE;	                 break;
+*/
+
+		    case 'f':	/* Suppress filename on output */
+			Shwfile = FALSE;
+			break;
+
+		    case 'l':	/* Line length */
+			Linlen = atoi(aptr);
+			Lines = NULL;
+			i = n;
+			break;
+
+		    case 'n':	/* Suppress line number on output */
+			Shwline = FALSE;
+			break;
+
+		    case 'w':	/* Window: lines before and after */
+			Waft = Wbef = atoi(aptr);
+			Lines = NULL;
+			i = n;
+			break;
+
+		    default:
+			fprintf(stderr, "Invalid option %s\n", argv[i]);
+			exit(1);
+		}
+	}
+  }
+
+  if (Pat == NULL) {		/* If no pattern given */
+	fprintf(stderr,
+		"Usage: cgrep [-a n] [-b n] [-f] [-l n] [-n] [-w n] pattern [filename... ]\n");
+	exit(1);
+  }
+  if (nf == 0)			/* No files processed ? */
+	dosrch((char *)NULL);		/* Do standard input */
+  return(0);
+}
+
+ /* Dosrch (ifnm) Perform the search 
+  * Accepts :
+  * 
+  * ifn             Input file name
+  * 
+  * 
+  * Returns :
+  * 
+  * 
+  */
+
+void dosrch(ifnm)
+char *ifnm;			/* Input filelname */
+
+{
+  FILE *ifp;			/* Input fp */
+  char *lptr;			/* Line pointer */
+  int i;			/* Scratch */
+  int prtaft;			/* Print-after count */
+  int linnum;			/* Line number */
+  int nlb;			/* Number of lines buffered */
+
+  if (ifnm != NULL) {		/* If file name given */
+	ifp = fopen(ifnm, "r");	/* Open it for read access */
+	if (ifp == NULL) {
+		fprintf(stderr, "Can not open file %s\n", ifnm);
+		return;
+	}
+  } else
+	ifp = stdin;
+
+  if (Lines == NULL) {		/* If no line table allocated.. */
+	Wsiz = Wbef + 2;	/* Determine total window size */
+	Lines = (char **) calloc((size_t)Wsiz, sizeof(char *));
+	/* Allocate pointer table */
+	for (i = 0; i < Wsiz; i++)	/* Allocate line buffers */
+		Lines[i] = (char *) calloc((size_t)Linlen, sizeof(char));
+  }
+  Lcur = Lone = 0;		/* Setup line pointers */
+  nlb = 0;			/* No lines buffered */
+  linnum = 0;			/* Line number is zero */
+  prtaft = -(Wbef + 1);		/* Make sure separator given first time */
+
+  for (;;) {			/* Loop through the file */
+	lptr = Lines[Lcur];	/* Get pointer to current line */
+	if (++Lcur == Wsiz)	/* Bump curr pointer and wrap */
+		Lcur = 0;	/* if hit end */
+	if (Lone == Lcur)	/* If wrapped to beginning of window */
+		if (++Lone == Wsiz)	/* Bump beginning */
+			Lone = 0;	/* and wrap if hit end */
+
+	if (fgets(lptr, Linlen, ifp) != lptr) break;	/* if end of file */
+
+	linnum++;		/* Count line number */
+	if (matlin(lptr)) {	/* If matching line */
+		if (prtaft < (-Wbef))	/* Check for separator needed */
+			if ((Nmr++ > 0) && ((Wbef > 0) || (Waft > 0)))
+				printf("----------------------------------------------------------------------------\n");
+		while (Lone != Lcur) {	/* Until we close the window */
+			shwlin(ifnm, linnum - nlb, Lines[Lone]);
+			/* Show the line */
+			if (++Lone == Wsiz) Lone = 0;
+			nlb--;
+		}
+		nlb = 0;	/* No lines buffered */
+		prtaft = Waft;	/* Print n lines after */
+	} else {		/* Didn't match */
+		if (prtaft-- > 0) {	/* If must print lines after */
+			shwlin(ifnm, linnum, lptr);
+			/* Show the line */
+			Lone = Lcur;	/* Match pointers */
+		} else if (nlb < Wbef)	/* Count lines buffered */
+			nlb++;
+	}
+  }
+
+  if (ifnm != NULL) fclose(ifp);
+}
+
+ /* Shwlin (fnm, linnum, line) Show a matching line 
+  * 
+  * Accepts :
+  * 
+  * fnm             File name
+  * 
+  * linnum          Line number
+  * 
+  * line            Line to show
+  * 
+  * 
+  * Returns :
+  * 
+  * 
+  */
+
+void shwlin(fnm, linnum, line)
+char *fnm;			/* File name */
+int linnum;			/* Line number */
+char *line;			/* Line (with newline at end) to print */
+
+{
+  if (Shwfile && (fnm != NULL)) printf("%s%s", fnm, Shwline ? " " : ":");
+  if (Shwline) printf("@%05d:", linnum);
+  printf("%s", line);
+}
+
+ /* Matlin (line) Perform match against pattern and line 
+  * 
+  * Accepts :
+  * 
+  * line            Address of line to match
+  * 
+  * 
+  * Returns :
+  * 
+  * <value>         TRUE if match FALSE if not
+  * 
+  * 
+  */
+
+
+int matlin(line)
+char *line;			/* Line to match */
+
+{
+  int rtncode;			/* Return value from this routine */
+
+
+#ifdef	NOREGEXP
+  char *pptr, *lptr, *tlptr;
+  int c1, c2;
+#endif /* NOREGEXP */
+
+  if (Debug) printf("Matching %s against %s", Pat, line);
+
+#ifdef	REGEX
+  rtncode = re_exec(line);	/* Hand off to r/e evaluator */
+#endif	/* REGEX */
+
+#ifdef	REGCMP
+  rtncode = (regexec(Re, line, TRUE) != 0);
+#endif /* REGCMP */
+
+#ifdef	NOREGEX			/* Have to do menial comparison.. */
+  lptr = line;			/* Init line pointer */
+
+  for (rtncode = -1; rtncode < 0;) {
+	tlptr = lptr++;		/* Get temp ptr to line */
+	pptr = Pat;		/* Get ptr to pattern */
+	while (TRUE) {
+		if ((c1 = *pptr++) == NUL) {
+			rtncode = 1;	/* GOOD return value */
+			break;
+		}
+		if ((c2 = *tlptr++) == NUL) {
+			rtncode = 0;	/* BAD return value */
+			break;
+		}
+		if (isupper(c1)) c1 = tolower(c1);
+		if (isupper(c2)) c2 = tolower(c2);
+		if (c1 != c2) break;
+	}
+  }
+#endif	/* NOREGEX */
+
+
+  if (Debug) printf("matlin returned %s\n", rtncode ? "TRUE" : "FALSE");
+  return(rtncode);
+}
+
+
+
+void regerror(s)
+const char *s;
+{
+  printf("%s\n", (char *) s);
+  exit(1);
+}
Index: /trunk/minix/commands/simple/chmem.c
===================================================================
--- /trunk/minix/commands/simple/chmem.c	(revision 9)
+++ /trunk/minix/commands/simple/chmem.c	(revision 9)
@@ -0,0 +1,148 @@
+/* chmem - set total memory size for execution	Author: Andy Tanenbaum */
+
+#include <minix/config.h>
+#include <sys/types.h>
+#include <a.out.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define MAX_8086     0x10000L	/* maximum allocation size for 8086 */
+#define MAX_386	  0x7FFFFFFFL	/* etc */
+#define MAX_68K   0x7FFFFFFFL
+#define MAX_SPARC 0x20000000L	/* No more than 512MB on a SparcStation! */
+
+char *progname;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void error, (char *s1, char *s2));
+_PROTOTYPE(void usage, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+/* The 8088 architecture does not make it possible to catch stacks that grow
+ * big.  The only way to deal with this problem is to let the stack grow down
+ * towards the data segment and the data segment grow up towards the stack.
+ * Normally, a total of 64K is allocated for the two of them, but if the
+ * programmer knows that a smaller amount is sufficient, he can change it
+ * using chmem.
+ *
+ * chmem =4096 prog  sets the total space for stack + data growth to 4096
+ * chmem +200  prog  increments the total space for stack + data growth by 200
+ */
+
+  char *p;
+  int fd = -1, separate;
+  size_t s;
+  long lsize, olddynam, newdynam, newtot, overflow;
+  struct exec exec;
+  char cpu;
+  long max;
+  int last_failed = 0, any_failed = 0;
+
+  progname = argv[0];
+  if (argc < 3) usage();
+  p = argv[1];
+  if (*p != '=' && *p != '+' && *p != '-') usage();
+  lsize = atol(p + 1);
+  s = sizeof(struct exec);
+
+  if (lsize < 0) {
+	error(p + 1, "is negative");
+	exit(1);
+  }
+  argc -= 1;
+  argv += 1;
+
+  while (--argc) {
+	if(last_failed) any_failed = 1;
+
+	/* Unless we reach the end of this loop, this one failed. */
+	last_failed = 1;
+	++argv;
+	if(fd != -1) close(fd);
+	fd = open(*argv, O_RDWR);
+	if (fd < 0) {
+		error("can't open", *argv);
+		continue;
+	}
+	if (read(fd, (char *) &exec, s) != s) {
+		error("can't read header in", *argv);
+		continue;
+	}
+	if (BADMAG(exec)) {
+		error(*argv, "is not executable");
+		continue;
+	}
+	separate = (exec.a_flags & A_SEP ? 1 : 0);
+	cpu = exec.a_cpu;
+
+#if (CHIP == M68000)
+	if (cpu == A_I8086) cpu = A_M68K;
+#endif
+
+	switch (cpu) {
+	    case A_I8086:	max = MAX_8086;	break;
+	    case A_I80386:	max = MAX_386;	break;
+	    case A_M68K:	max = MAX_68K;	break;
+	    case A_SPARC:	max = MAX_SPARC;	break;
+	    default:
+		error("bad CPU type in", *argv);
+		continue;
+	}
+
+	if (lsize > max) {
+		error("size is too large for", *argv);
+		continue;
+	}
+	olddynam = exec.a_total - exec.a_data - exec.a_bss;
+	if (separate == 0) olddynam -= exec.a_text;
+
+	if (*p == '=')
+		newdynam = lsize;
+	else if (*p == '+')
+		newdynam = olddynam + lsize;
+	else if (*p == '-')
+		newdynam = olddynam - lsize;
+
+	newtot = exec.a_data + exec.a_bss + newdynam;
+	if (separate == 0) newtot += exec.a_text;
+	overflow = (newtot > max ? newtot - max : 0);
+	newdynam -= overflow;
+	newtot -= overflow;
+	exec.a_total = newtot;
+	lseek(fd, (long) 0, SEEK_SET);
+	if (write(fd, (char *) &exec, s) != s) {
+		error("can't modify", *argv);
+		continue;
+	}
+	printf("%s: Stack+malloc area changed from %ld to %ld bytes.\n",
+	       *argv, olddynam, newdynam);
+
+	/* This one didn't fail. */
+	last_failed = 0;
+  }
+  return(any_failed || last_failed ? 1 : 0);
+}
+
+void error(s1, s2)
+char *s1;
+char *s2;
+{
+  fprintf(stderr, "%s: %s ", progname, s1);
+  if (errno != 0)
+	perror(s2);
+  else
+	fprintf(stderr, "%s\n", s2);
+  errno = 0;
+}
+
+void usage()
+{
+  fprintf(stderr, "Usage: %s {=+-} amount file\n", progname);
+  exit(1);
+}
Index: /trunk/minix/commands/simple/chmod.c
===================================================================
--- /trunk/minix/commands/simple/chmod.c	(revision 9)
+++ /trunk/minix/commands/simple/chmod.c	(revision 9)
@@ -0,0 +1,254 @@
+/* chmod - Change file modes				Author: V. Archer */
+
+/* Copyright 1991 by Vincent Archer
+ *	You may freely redistribute this software, in source or binary
+ *	form, provided that you do not alter this copyright mention in any
+ *	way.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <minix/minlib.h>
+#include <stdio.h>
+
+#ifndef S_ISLNK
+#define S_ISLNK(mode)	0
+#define lstat		stat
+#endif
+
+#define USR_MODES (S_ISUID|S_IRWXU)
+#define GRP_MODES (S_ISGID|S_IRWXG)
+#define EXE_MODES (S_IXUSR|S_IXGRP|S_IXOTH)
+#ifdef S_ISVTX
+#define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO|S_ISVTX)
+#else
+#define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO)
+#endif
+
+
+/* Common variables */
+char *symbolic;
+mode_t new_mode, u_mask;
+int rflag, errors;
+struct stat st;
+char path[PATH_MAX + 1];
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(mode_t parsemode, (char *symbolic, mode_t oldmode));
+_PROTOTYPE(int do_change, (char *name));
+_PROTOTYPE(void usage, (void));
+
+/* Parse a P1003.2 4.7.7-conformant symbolic mode. */
+mode_t parsemode(char *symbolic, mode_t oldmode)
+{
+  mode_t who, mask, newmode, tmpmask;
+  char action;
+
+  newmode = oldmode & ALL_MODES;
+  while (*symbolic) {
+	who = 0;
+	for (; *symbolic; symbolic++) {
+		if (*symbolic == 'a') {
+			who |= ALL_MODES;
+			continue;
+		}
+		if (*symbolic == 'u') {
+			who |= USR_MODES;
+			continue;
+		}
+		if (*symbolic == 'g') {
+			who |= GRP_MODES;
+			continue;
+		}
+		if (*symbolic == 'o') {
+			who |= S_IRWXO;
+			continue;
+		}
+		break;
+	}
+	if (!*symbolic || *symbolic == ',') usage();
+	while (*symbolic) {
+		if (*symbolic == ',') break;
+		switch (*symbolic) {
+		    default:
+			usage();
+		    case '+':
+		    case '-':
+		    case '=':	action = *symbolic++;
+		}
+		mask = 0;
+		for (; *symbolic; symbolic++) {
+			if (*symbolic == 'u') {
+				tmpmask = newmode & S_IRWXU;
+				mask |= tmpmask | (tmpmask << 3) | (tmpmask << 6);
+				symbolic++;
+				break;
+			}
+			if (*symbolic == 'g') {
+				tmpmask = newmode & S_IRWXG;
+				mask |= tmpmask | (tmpmask >> 3) | (tmpmask << 3);
+				symbolic++;
+				break;
+			}
+			if (*symbolic == 'o') {
+				tmpmask = newmode & S_IRWXO;
+				mask |= tmpmask | (tmpmask >> 3) | (tmpmask >> 6);
+				symbolic++;
+				break;
+			}
+			if (*symbolic == 'r') {
+				mask |= S_IRUSR | S_IRGRP | S_IROTH;
+				continue;
+			}
+			if (*symbolic == 'w') {
+				mask |= S_IWUSR | S_IWGRP | S_IWOTH;
+				continue;
+			}
+			if (*symbolic == 'x') {
+				mask |= EXE_MODES;
+				continue;
+			}
+			if (*symbolic == 's') {
+				mask |= S_ISUID | S_ISGID;
+				continue;
+			}
+			if (*symbolic == 'X') {
+				if (S_ISDIR(oldmode) || (oldmode & EXE_MODES))
+					mask |= EXE_MODES;
+				continue;
+			}
+#ifdef S_ISVTX
+			if (*symbolic == 't') {
+				mask |= S_ISVTX;
+				who |= S_ISVTX;
+				continue;
+			}
+#endif
+			break;
+		}
+		switch (action) {
+		    case '=':
+			if (who)
+				newmode &= ~who;
+			else
+				newmode = 0;
+		    case '+':
+			if (who)
+				newmode |= who & mask;
+			else
+				newmode |= mask & (~u_mask);
+			break;
+		    case '-':
+			if (who)
+				newmode &= ~(who & mask);
+			else
+				newmode &= ~mask | u_mask;
+		}
+	}
+	if (*symbolic) symbolic++;
+  }
+  return(newmode);
+}
+
+
+/* Main module. The single option possible (-R) does not warrant a call to
+ * the getopt() stuff.
+ */
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int ex_code = 0;
+
+  argc--;
+  argv++;
+
+  if (argc && strcmp(*argv, "-R") == 0) {
+	argc--;
+	argv++;
+	rflag = 1;
+  } else
+	rflag = 0;
+
+  if (!argc--) usage();
+  if (!strcmp(argv[0], "--")) {	/* Allow chmod -- -r, as in Draft11 example */
+	if (!argc--) usage();
+	argv++;
+  }
+  symbolic = *argv++;
+  if (!argc) usage();
+
+  if (*symbolic >= '0' && *symbolic <= '7') {
+	new_mode = 0;
+	while (*symbolic >= '0' && *symbolic <= '7')
+		new_mode = (new_mode << 3) | (*symbolic++ & 07);
+	if (*symbolic) usage();
+	new_mode &= ALL_MODES;
+	symbolic = (char *) 0;
+  } else
+	u_mask = umask(0);
+
+  while (argc--)
+	if (do_change(*argv++)) ex_code = 1;
+  return(ex_code);
+}
+
+
+/* Apply a mode change to a given file system element. */
+int do_change(name)
+char *name;
+{
+  mode_t m;
+  DIR *dirp;
+  struct dirent *entp;
+  char *namp;
+
+  if (lstat(name, &st)) {
+	perror(name);
+	return(1);
+  }
+  if (S_ISLNK(st.st_mode) && rflag) return(0);	/* Note: violates POSIX. */
+  if (!symbolic)
+	m = new_mode;
+  else
+	m = parsemode(symbolic, st.st_mode);
+  if (chmod(name, m)) {
+	perror(name);
+	errors = 1;
+  } else
+	errors = 0;
+
+  if (S_ISDIR(st.st_mode) && rflag) {
+	if (!(dirp = opendir(name))) {
+		perror(name);
+		return(1);
+	}
+	if (name != path) strcpy(path, name);
+	namp = path + strlen(path);
+	*namp++ = '/';
+	while (entp = readdir(dirp))
+		if (entp->d_name[0] != '.' ||
+		    (entp->d_name[1] &&
+		     (entp->d_name[1] != '.' || entp->d_name[2]))) {
+			strcpy(namp, entp->d_name);
+			errors |= do_change(path);
+		}
+	closedir(dirp);
+	*--namp = '\0';
+  }
+  return(errors);
+}
+
+
+/* Display Posix prototype */
+void usage()
+{
+  std_err("Usage: chmod [-R] mode file...\n");
+  exit(1);
+}
Index: /trunk/minix/commands/simple/chown.c
===================================================================
--- /trunk/minix/commands/simple/chown.c	(revision 9)
+++ /trunk/minix/commands/simple/chown.c	(revision 9)
@@ -0,0 +1,168 @@
+/* chown/chgrp - Change file ownership			Author: V. Archer */
+
+/* Copyright 1991 by Vincent Archer
+ *	You may freely redistribute this software, in source or binary
+ *	form, provided that you do not alter this copyright mention in any
+ *	way.
+ */
+
+/* Changed  3 Feb 93 by Kees J. Bot:  setuid execution nonsense removed.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <pwd.h>
+#include <grp.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <minix/minlib.h>
+#include <stdio.h>
+
+#ifndef S_ISLNK
+#define S_ISLNK(mode)	0
+#define lstat		stat
+#endif
+
+#define S_IUGID (S_ISUID|S_ISGID)
+
+/* Global variables, such as flags and path names */
+int gflag, oflag, rflag, error;
+char *pgmname, path[PATH_MAX + 1];
+uid_t nuid;
+gid_t ngid;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void do_chown, (char *file));
+_PROTOTYPE(void usage, (void));
+
+/* Main module. If chown(1) is invoked as chgrp(1), the behaviour is nearly
+ * identical, except that the default when a single name is given as an
+ * argument is to take a group id rather than an user id. This allow the
+ * non-Posix "chgrp user:group file".
+ * The single option switch used by chown/chgrp (-R) does not warrant a
+ * call to the getopt stuff. The two others flags (-g, -u) are set from
+ * the program name and arguments.
+ */
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  char *id, *id2;
+  struct group *grp;
+  struct passwd *pwp;
+
+  if (pgmname = strrchr(*argv, '/'))
+	pgmname++;
+  else
+	pgmname = *argv;
+  argc--;
+  argv++;
+  gflag = strcmp(pgmname, "chgrp");
+
+  if (argc && **argv == '-' && argv[0][1] == 'R') {
+	argc--;
+	argv++;
+	rflag = 1;
+  }
+  if (argc < 2) usage();
+
+  id = *argv++;
+  argc--;
+  if (id2 = strchr(id, ':')) *id2++ = '\0';
+  if (!id2 && !gflag) {
+	id2 = id;
+	id = 0;
+  }
+  if (id) {
+	if (isdigit(*id))
+		nuid = atoi(id);
+	else {
+		if (!(pwp = getpwnam(id))) {
+			std_err(id);
+			std_err(": unknown user name\n");
+			exit(1);
+		}
+		nuid = pwp->pw_uid;
+	}
+	oflag = 1;
+  } else
+	oflag = 0;
+
+  if (id2) {
+	if (isdigit(*id2))
+		ngid = atoi(id2);
+	else {
+		if (!(grp = getgrnam(id2))) {
+			std_err(id2);
+			std_err(": unknown group name\n");
+			exit(1);
+		}
+		ngid = grp->gr_gid;
+	}
+	gflag = 1;
+  } else
+	gflag = 0;
+
+  error = 0;
+  while (argc--) do_chown(*argv++);
+  return(error);
+}
+
+/* Apply the user/group modification here.
+ */
+void do_chown(file)
+char *file;
+{
+  DIR *dirp;
+  struct dirent *entp;
+  char *namp;
+  struct stat st;
+
+  if (lstat(file, &st)) {
+	perror(file);
+	error = 1;
+	return;
+  }
+
+  if (S_ISLNK(st.st_mode) && rflag) return;	/* Note: violates POSIX. */
+
+  if (chown(file, oflag ? nuid : st.st_uid, gflag ? ngid : st.st_gid)) {
+	perror(file);
+	error = 1;
+  }
+
+  if (S_ISDIR(st.st_mode) && rflag) {
+	if (!(dirp = opendir(file))) {
+		perror(file);
+		error = 1;
+		return;
+	}
+	if (path != file) strcpy(path, file);
+	namp = path + strlen(path);
+	*namp++ = '/';
+	while (entp = readdir(dirp))
+		if (entp->d_name[0] != '.' ||
+		    (entp->d_name[1] &&
+		     (entp->d_name[1] != '.' || entp->d_name[2]))) {
+			strcpy(namp, entp->d_name);
+			do_chown(path);
+		}
+	closedir(dirp);
+	*--namp = '\0';
+  }
+}
+
+/* Posix prototype of the chown/chgrp function */
+void usage()
+{
+  std_err("Usage: ");
+  std_err(pgmname);
+  std_err(gflag ? " owner[:group]" : " [owner:]group");
+  std_err(" file...\n");
+  exit(1);
+}
Index: /trunk/minix/commands/simple/chroot.c
===================================================================
--- /trunk/minix/commands/simple/chroot.c	(revision 9)
+++ /trunk/minix/commands/simple/chroot.c	(revision 9)
@@ -0,0 +1,28 @@
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/wait.h>
+
+int
+main(int argc, char *argv[])
+{
+	int status;
+
+	if(argc != 3) {
+		fprintf(stderr, "usage: %s <root> <command>\n", argv[0]);
+		return 1;
+	}
+
+	if(chroot(argv[1]) < 0) {
+		perror("chroot");
+		return 1;
+	}
+
+	status = system(argv[2]);
+	if(WIFEXITED(status))
+		return WEXITSTATUS(status);
+	return 1;
+}
+
Index: /trunk/minix/commands/simple/ci.c
===================================================================
--- /trunk/minix/commands/simple/ci.c	(revision 9)
+++ /trunk/minix/commands/simple/ci.c	(revision 9)
@@ -0,0 +1,343 @@
+/* ci - check in 			Author: Peter S. Housel 12/17/87 */
+
+#include <sys/types.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <stdio.h>
+
+#define SUFFIX		",S"	/* svc indicator */
+#define SVCDIR		"SVC"	/* svc postfix indicator */
+
+#define LINELEN		256	/* maximum line length */
+
+#ifndef PATCH
+#define FIX		"fix $1 Fix.$1 > New.$1; mv New.$1 $1\n"
+#else
+#define FIX		"patch -n -s $1 < Fix.$1; rm -f $1.orig\n"
+#endif /* !PATCH */
+
+#ifdef MAXPATHLEN
+#define PATHLEN MAXPATHLEN
+#else
+#define PATHLEN 128		/* buffer length for filenames */
+#endif
+
+int unlocked = 0;		/* leave unlocked after checkin */
+int relock = 0;			/* lock next revision after checkin */
+char file[PATHLEN];		/* file to be checked in */
+char svc[PATHLEN];		/* filename for svc file */
+char newsvc[PATHLEN];		/* new copy of SVC file */
+char line[LINELEN];		/* temporary line buffer */
+char *p;			/* scratch character pointer */
+
+FILE *svcfp;			/* svc file */
+FILE *origfp, *newfp;		/* "orig" and "new" temp files */
+FILE *srcfp;			/* source file */
+int rev;			/* new revision number */
+int status;			/* wait() buffer */
+struct stat stb1, stb2;		/* stat buffers for size compare */
+char original[] = "/tmp/cioXXXXXX";	/* previous revision */
+char diffout[] = "/tmp/cidXXXXXX";	/* diffs */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void rundiff, (void));
+_PROTOTYPE(void logmsg, (FILE *fp));
+_PROTOTYPE(void fname, (char *src, char *dst));
+_PROTOTYPE(void svcname, (char *src, char *dst));
+_PROTOTYPE(int lockcheck, (FILE *fp, int rev));
+_PROTOTYPE(void onintr, (int dummy));
+_PROTOTYPE(void clean, (void));
+_PROTOTYPE(char *whoami, (void));
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+#ifdef perprintf
+  char errbuf[BUFSIZ];
+  setbuf(stderr, errbuf);
+  perprintf(stderr);
+#endif
+
+  while (++argv, --argc) {
+	if ('-' == (*argv)[0]) {
+		if ('u' == (*argv)[1])
+			++unlocked;
+		else if ('l' == (*argv)[1])
+			++relock;
+		else {
+			fprintf(stderr, "ci: illegal option -%c\n", (*argv)[1]);
+			exit(1);
+		}
+	} else
+		break;
+  }
+
+  if (1 != argc) {
+	fprintf(stderr, "ci: bad number of files arguments\n");
+	exit(1);
+  }
+  fname(*argv, file);
+  svcname(file, svc);
+
+  fprintf(stderr, "%s -> %s\n", file, svc);
+
+  signal(SIGHUP, onintr);
+  signal(SIGINT, onintr);
+  signal(SIGTERM, onintr);
+
+#ifndef BSD
+  if (NULL == (p = strrchr(file, '/')))
+	p = file;
+  else
+	++p;
+
+  if (strlen(p) > 13) {
+	fprintf(stderr, "ci: filename %s is too long\n", p);
+	exit(1);
+  }
+#endif /* !BSD */
+
+  strcpy(newsvc, svc);
+  *(strrchr(newsvc, ',')) = ';';	/* temporary file will be "file;S" */
+
+  if (NULL == (newfp = fopen(newsvc, "w"))) {
+	perror("ci: can't create SVC temporary");
+	exit(1);
+  }
+  (void) mktemp(original);
+  (void) mktemp(diffout);
+
+  if (NULL != (svcfp = fopen(svc, "r"))) {	/* does svc-file exist? */
+	fgets(line, LINELEN, svcfp);
+	if (1 != sscanf(line, "# %d", &rev)) {
+		fprintf(stderr, "ci: %s: illegal SVC file header\n", svc);
+		exit(1);
+	}
+	++rev;
+
+	if (!lockcheck(svcfp, rev)) {
+		fprintf(stderr, "Revision %d not locked\n", rev);
+		clean();
+		exit(1);
+	}
+	if (NULL == (origfp = fopen(original, "w"))) {
+		fprintf(stderr, "ci: can't create %s", original);
+		perror(" ");
+	}
+	fgets(line, LINELEN, svcfp);	/* skip "cat <<***MAIN-eof***" line */
+
+	while (NULL != fgets(line, LINELEN, svcfp)
+	       && strcmp(line, "***MAIN-eof***\n")) {
+		fputs(line, origfp);
+		if (ferror(origfp)) {
+			perror("ci: origfile");
+			exit(1);
+		}
+	}
+	fclose(origfp);
+
+	rundiff();
+
+	if (0 != stat(original, &stb1) || 0 != stat(diffout, &stb2)) {
+		perror("ci: can't stat original or diffout");
+		clean();
+		exit(1);
+	}
+  } else {			/* no - create one */
+	rev = 1;
+  }
+
+  fprintf(newfp, "# %d\n", rev);
+  fprintf(newfp, "cat <<***MAIN-eof*** >$1\n");
+  if (NULL == (srcfp = fopen(file, "r"))) {
+	perror("ci: can't read source file");
+	clean();
+	exit(1);
+  }
+  while (NULL != fgets(line, LINELEN, srcfp)) fputs(line, newfp);
+  fclose(srcfp);
+  fputs("***MAIN-eof***\n", newfp);
+
+  if (rev > 1) {
+	fprintf(newfp, "if test $2 -ge %d ; then rm -f Fix.$1 ; exit 0 ; fi ; cat <<***%d-eof*** >Fix.$1\n", rev, rev);
+	p = (stb1.st_size <= stb2.st_size) ? original : diffout;
+	if (NULL == (origfp = fopen(p, "r"))) {
+		perror("can't open diff output file");
+		clean();
+		exit(1);
+	}
+	while (NULL != fgets(line, LINELEN, origfp)) fputs(line, newfp);
+	fclose(origfp);
+	fprintf(newfp, "***%d-eof***\n", rev);
+	fputs((original == p) ? "mv Fix.$1 $1\n" : FIX, newfp);
+	logmsg(newfp);
+	while (NULL != fgets(line, LINELEN, svcfp) && strncmp(line, "#***SVCLOCK***", (size_t)14))
+		fputs(line, newfp);
+  } else {
+	logmsg(newfp);
+	fputs("rm -f Fix.$1\n", newfp);
+  }
+
+  if (relock) {
+	fprintf(stderr, "(relocking into revision %d)\n", rev + 1);
+	fprintf(newfp, "#***SVCLOCK*** %s %d\n", whoami(), rev + 1);
+  }
+  signal(SIGHUP, SIG_IGN);	/* disable during critical section */
+  signal(SIGINT, SIG_IGN);
+
+  if (ferror(newfp) || fclose(newfp) || ((rev > 1) && unlink(svc))
+      || link(newsvc, svc)) {
+	fprintf(stderr, "SVC file write/link error - Checkin aborted\n");
+	clean();
+	exit(1);
+  } else
+	fprintf(stderr, "Checkin complete.\n");
+
+  if (stat(svc, &stb1) < 0 || chmod(svc, stb1.st_mode & 0555) < 0)
+	perror("ci: can't chmod SVC file");
+
+  if (unlocked) {
+	if (stat(file, &stb1) < 0 || chmod(file, stb1.st_mode & 0555) < 0)
+		perror("ci: can't chmod source file");
+  } else if (relock) {
+	if (stat(file, &stb1) < 0 || chmod(file, stb1.st_mode | 0200) < 0)
+		perror("ci: can't chmod source file");
+  } else
+	unlink(file);
+
+  clean();
+  return(0);
+}
+
+void rundiff()
+{				/* do "diff file original > diffout" */
+  int fd;			/* redirected output file */
+
+  switch (fork()) {
+      case -1:
+	perror("ci: fork");	/* error */
+	clean();
+	exit(1);
+
+      case 0:			/* child */
+	if ((fd = creat(diffout, 0600)) < 0 || -1 == dup2(fd, 1)) {
+		perror("ci: diffout");
+		clean();
+		exit(1);
+	}
+	close(fd);
+	execlp("diff", "diff", file, original, (char *) 0);
+	perror("ci: exec diff failed");
+	exit(1);
+
+      default:	break;		/* parent */
+}
+  wait(&status);
+  if (0 != status && 1 << 8 != status) {
+	fprintf(stderr, "ci: bad return status (0x%x) from diff\n", status);
+	clean();
+	exit(1);
+  }
+}
+
+void logmsg(fp)
+FILE *fp;
+{
+  long now;
+
+  time(&now);
+  fprintf(stderr, "Enter log message for revision %d (end with ^D or '.'):\n", rev);
+  fprintf(fp, "#***SVC*** revision %d %s %s", rev, file, ctime(&now));
+  while (NULL != gets(line) && strcmp(line, "."))
+	fprintf(fp, "#***SVC*** %s\n", line);
+}
+
+void fname(src, dst)
+char *src, *dst;
+{
+  char *p;
+  strcpy(dst, src);
+  p = &dst[strlen(src) - strlen(SUFFIX)];
+  if (!strcmp(p, SUFFIX)) *p = '\0';
+}
+
+void svcname(src, dst)
+char *src, *dst;
+{
+  char *p;
+
+  strcpy(dst, src);
+  strcat(dst, SUFFIX);
+
+  if (0 != access(dst, 4)) {
+	char dirname[PATHLEN];
+	if (NULL != (p = strrchr(src, '/')))
+		strncpy(dirname, src, (size_t)(p - src + 1));
+	else
+		dirname[0] = '\0';
+	strcat(dirname, SVCDIR);
+
+	if (0 == access(dirname, 1)) {
+		strcpy(dst, dirname);
+		if (NULL == p) {
+			strcat(dst, "/");
+			strcat(dst, src);
+		} else
+			strcat(dst, p);
+		strcat(dst, SUFFIX);
+	}
+  }
+}
+
+int lockcheck(fp, rev)
+FILE *fp;
+int rev;
+{
+  char lock[40], check[40];
+  long pos;
+  int ret;
+
+  sprintf(lock, "#***SVCLOCK*** %s %d\n", whoami(), rev);
+
+  pos = ftell(fp);
+  fseek(fp, -((long) strlen(lock)), 2);
+  fgets(check, 40, fp);
+  ret = (0 == strcmp(lock, check));
+  fseek(fp, pos, 0);
+
+  return ret;
+}
+
+void onintr(dummy)
+int dummy; /* to keep the compiler happy */
+{
+  fprintf(stderr, "Interrupt - Aborting checkin, cleaning up\n");
+  clean();
+  exit(1);
+}
+
+void clean()
+{
+  if (strlen(original))		/* if only more programs made this check! */
+	unlink(original);
+  if (strlen(diffout)) unlink(diffout);
+  if (strlen(newsvc)) unlink(newsvc);
+}
+
+char *whoami()
+{
+  struct passwd *pw;
+
+  if (NULL != (pw = getpwuid(getuid())))
+	return pw->pw_name;
+  else
+	return "nobody";
+}
Index: /trunk/minix/commands/simple/cksum.c
===================================================================
--- /trunk/minix/commands/simple/cksum.c	(revision 9)
+++ /trunk/minix/commands/simple/cksum.c	(revision 9)
@@ -0,0 +1,155 @@
+/* cksum.c - Display file checksums and block counts	Author: V. Archer */
+
+/* Copyright 1991 by Vincent Archer
+ *	You may freely redistribute this software, in source or binary
+ *	form, provided that you do not alter this copyright mention in any
+ *	way.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+int error;
+
+/* Table from P1003.2 (4.9/Fig 4.1). In fact, this table was taken from zmodem
+ * and rewritten to look like the Draft 11 example.
+ */
+unsigned long crctab[] = {
+		  0x7fffffff,
+	 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+	 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e,
+	 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+	 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d,
+	 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0,
+	 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63,
+	 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+	 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa,
+	 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75,
+	 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180,
+	 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+	 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87,
+	 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+	 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5,
+	 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+	 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4,
+	 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b,
+	 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea,
+	 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+	 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541,
+	 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc,
+	 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f,
+	 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+	 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e,
+	 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+	 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c,
+	 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+	 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b,
+	 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2,
+	 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671,
+	 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+	 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8,
+	 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767,
+	 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6,
+	 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+	 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795,
+	 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+	 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b,
+	 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+	 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82,
+	 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d,
+	 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8,
+	 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+	 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff,
+	 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee,
+	 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d,
+	 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+	 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c,
+	 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+	 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02,
+	  0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void crc, (int fd, char *name));
+_PROTOTYPE(unsigned long strncrc, (unsigned char *b, int n, unsigned long s));
+
+static int aux;
+
+/* Routine straight out of 4.9.10 */
+unsigned long strncrc(b, n, s)
+register unsigned char *b;	/* byte sequence to checksum */
+register int n;			/* length of sequence */
+register unsigned long s;	/* initial checksum value */
+{
+  register int i;
+
+  while (n-- > 0) {
+	/* Compute the index to the crc table */
+	i = (s >> 24) ^ ((unsigned int) (*b++));
+
+	if (i == 0) {
+		/* Replace an intermediate zero with the next value
+		 * from the sequence */
+		i = aux++;
+		if (aux >= sizeof(crctab) / sizeof(crctab[0])) aux = 0;
+	}
+
+	/* New checksum value */
+	s = (s << 8) ^ crctab[i];
+  }
+  return(s);
+}
+
+/* Main module. No options switches allowed, none parsed. */
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  argc--;
+  error = 0;
+  if (!argc)
+	crc(0, (char *) 0);
+  else
+	for (argv++; argc--; argv++) crc(open(*argv, O_RDONLY), *argv);
+  return(error);
+}
+
+/* Compute crc and size of input file descriptor. */
+void crc(fd, name)
+int fd;
+char *name;
+{
+  off_t f_size;
+  unsigned long crc;
+  int nb;
+  unsigned char buffer[1024];
+
+  if (fd < 0) {
+	perror(name);
+	error = 1;
+	return;
+  }
+  crc = 0;
+  f_size = 0;
+  aux = 0;
+  for (;;) {
+	nb = read(fd, (char *) buffer, sizeof(buffer));
+	if (nb < 0) {
+		close(fd);
+		perror(name ? name : "stdin");
+		error = 1;
+		return;
+	}
+	if (!nb) break;
+	f_size += nb;
+	crc = strncrc(buffer, nb, crc);
+  }
+  close(fd);
+  printf("%lu %ld", crc, f_size);
+  if (name)
+	printf(" %s\n", name);
+  else
+	putchar('\n');
+}
Index: /trunk/minix/commands/simple/cleantmp.c
===================================================================
--- /trunk/minix/commands/simple/cleantmp.c	(revision 9)
+++ /trunk/minix/commands/simple/cleantmp.c	(revision 9)
@@ -0,0 +1,361 @@
+/*	cleantmp 1.6 - clean out a tmp dir.		Author: Kees J. Bot
+ *								11 Apr 1991
+ */
+#define nil 0
+#include <sys/types.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <time.h>
+#include <dirent.h>
+#include <errno.h>
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+
+#ifndef S_ISLNK
+/* There were no symlinks in medieval times. */
+#define lstat stat
+#endif
+
+#ifndef DEBUG
+#define NDEBUG
+#endif
+#include <assert.h>
+
+#define SEC_DAY	(24 * 3600L)	/* A full day in seconds */
+#define DOTDAYS	14		/* Don't remove tmp/.* in at least 14 days. */
+
+void report(const char *label)
+{
+	fprintf(stderr, "cleantmp: %s: %s\n", label, strerror(errno));
+}
+
+void fatal(const char *label)
+{
+	report(label);
+	exit(1);
+}
+
+void *alloc(size_t s)
+{
+	void *mem;
+
+	if ((mem= (void *) malloc(s)) == nil) fatal("");
+	return mem;
+}
+
+int force= 0;			/* Force remove all. */
+int debug= 0;			/* Debug level. */
+
+void days2time(unsigned long days, time_t *retired, time_t *dotretired)
+{
+	struct tm *tm;
+	time_t t;
+
+	time(&t);
+
+	tm= localtime(&t);
+	tm->tm_hour= 0;
+	tm->tm_min= 0;
+	tm->tm_sec= 0;	/* Step back to midnight of this day. */
+	t= mktime(tm);
+
+	if (t < (days - 1) * SEC_DAY) {
+		*retired= *dotretired= 0;
+	} else {
+		*retired= t - (days - 1) * SEC_DAY;
+		*dotretired= t - (DOTDAYS - 1) * SEC_DAY;
+		if (*dotretired > *retired) *dotretired= *retired;
+	}
+	if (debug >= 2) fprintf(stderr, "Retired:    %s", ctime(retired));
+	if (debug >= 2) fprintf(stderr, "Dotretired: %s", ctime(dotretired));
+}
+
+/* Path name construction, addpath adds a component, delpath removes it.
+ * The string 'path' is used throughout the program as the file under
+ * examination.
+ */
+
+char *path;	/* Path name constructed in path[]. */
+int plen= 0, pidx= 0;	/* Lenght/index for path[]. */
+
+void addpath(int *didx, char *name)
+/* Add a component to path. (name may also be a full path at the first call)
+ * The index where the current path ends is stored in *pdi.
+ */
+{
+	if (plen == 0) path= (char *) alloc((plen= 32) * sizeof(path[0]));
+
+	*didx= pidx;	/* Record point to go back to for delpath. */
+
+	if (pidx > 0 && path[pidx-1] != '/') path[pidx++]= '/';
+
+	do {
+		if (*name != '/' || pidx == 0 || path[pidx-1] != '/') {
+			if (pidx == plen &&
+				(path= (char *) realloc((void *) path,
+					(plen*= 2) * sizeof(path[0]))) == nil
+			) fatal("");
+			path[pidx++]= *name;
+		}
+	} while (*name++ != 0);
+
+	--pidx;		/* Put pidx back at the null.  The path[pidx++]= '/'
+			 * statement will overwrite it at the next call.
+			 */
+	assert(pidx < plen);
+}
+
+void delpath(int didx)
+{
+	assert(0 <= didx);
+	assert(didx <= pidx);
+	path[pidx= didx]= 0;
+}
+
+struct file {
+	struct file	*next;
+	char		*name;
+};
+
+struct file *listdir(void)
+{
+	DIR *dp;
+	struct dirent *entry;
+	struct file *first, **last= &first;
+
+	if ((dp= opendir(path)) == nil) {
+		report(path);
+		return nil;
+	}
+
+	while ((entry= readdir(dp)) != nil) {
+		struct file *new;
+
+		if (strcmp(entry->d_name, ".") == 0
+			|| strcmp(entry->d_name, "..") == 0) continue;
+
+		new= (struct file *) alloc(sizeof(*new));
+		new->name= (char *) alloc((size_t) strlen(entry->d_name) + 1);
+		strcpy(new->name, entry->d_name);
+
+		*last= new;
+		last= &new->next;
+	}
+	closedir(dp);
+	*last= nil;
+
+	return first;
+}
+
+struct file *shorten(struct file *list)
+{
+	struct file *junk;
+
+	assert(list != nil);
+
+	junk= list;
+	list= list->next;
+
+	free((void *) junk->name);
+	free((void *) junk);
+
+	return list;
+}
+
+/* Hash list of files to ignore. */
+struct file *ignore_list[1024];
+size_t n_ignored= 0;
+
+unsigned ihash(char *name)
+/* A simple hashing function on a file name. */
+{
+	unsigned h= 0;
+
+	while (*name != 0) h= (h * 0x1111) + *name++;
+
+	return h & (arraysize(ignore_list) - 1);
+}
+
+void do_ignore(int add, char *name)
+/* Add or remove a file to/from the list of files to ignore. */
+{
+	struct file **ipp, *ip;
+
+	ipp= &ignore_list[ihash(name)];
+	while ((ip= *ipp) != nil) {
+		if (strcmp(name, ip->name) <= 0) break;
+		ipp= &ip->next;
+	}
+
+	if (add) {
+		ip= alloc(sizeof(*ip));
+		ip->name= alloc((strlen(name) + 1) * sizeof(ip->name[0]));
+		strcpy(ip->name, name);
+		ip->next= *ipp;
+		*ipp= ip;
+		n_ignored++;
+	} else {
+		assert(ip != nil);
+		*ipp= ip->next;
+		free(ip->name);
+		free(ip);
+		n_ignored--;
+	}
+}
+
+int is_ignored(char *name)
+/* Is a file in the list of ignored files? */
+{
+	struct file *ip;
+	int r;
+
+	ip= ignore_list[ihash(name)];
+	while (ip != nil) {
+		if ((r = strcmp(name, ip->name)) <= 0) return (r == 0);
+		ip= ip->next;
+	}
+	return 0;
+}
+
+#define is_ignored(name) (n_ignored > 0 && (is_ignored)(name))
+
+time_t retired, dotretired;
+
+enum level { TOP, DOWN };
+
+void cleandir(enum level level, time_t retired)
+{
+	struct file *list;
+	struct stat st;
+	time_t ret;
+
+	if (debug >= 2) fprintf(stderr, "Cleaning %s\n", path);
+
+	list= listdir();
+
+	while (list != nil) {
+		int didx;
+
+		ret= (level == TOP && list->name[0] == '.') ?
+			dotretired : retired;
+			/* don't rm tmp/.* too soon. */
+
+		addpath(&didx, list->name);
+
+		if (is_ignored(path)) {
+			if (debug >= 1) fprintf(stderr, "ignoring %s\n", path);
+			do_ignore(0, path);
+		} else
+		if (is_ignored(list->name)) {
+			if (debug >= 1) fprintf(stderr, "ignoring %s\n", path);
+		} else
+		if (lstat(path, &st) < 0) {
+			report(path);
+		} else
+		if (S_ISDIR(st.st_mode)) {
+			cleandir(DOWN, ret);
+			if (force || st.st_mtime < ret) {
+				if (debug < 3 && rmdir(path) < 0) {
+					if (errno != ENOTEMPTY
+							&& errno != EEXIST) {
+						report(path);
+					}
+				} else {
+					if (debug >= 1) {
+						fprintf(stderr,
+							"rmdir %s\n", path);
+					}
+				}
+			}
+		} else {
+			if (force || (st.st_atime < ret
+					&& st.st_mtime < ret
+					&& st.st_ctime < ret)
+			) {
+				if (debug < 3 && unlink(path) < 0) {
+					if (errno != ENOENT) {
+						report(path);
+					}
+				} else {
+					if (debug >= 1) {
+						fprintf(stderr,
+							"rm %s\n", path);
+					}
+				}
+			}
+		}
+		delpath(didx);
+		list= shorten(list);
+	}
+}
+
+void usage(void)
+{
+	fprintf(stderr,
+	"Usage: cleantmp [-d[level]] [-i file ] ... -days|-f directory ...\n");
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	int i;
+	unsigned long days;
+
+	i= 1;
+	while (i < argc && argv[i][0] == '-') {
+		char *opt= argv[i++] + 1;
+
+		if (opt[0] == '-' && opt[1] == 0) break;
+
+		if (opt[0] == 'd') {
+			debug= 1;
+			if (opt[1] != 0) debug= atoi(opt + 1);
+		} else
+		if (opt[0] == 'i') {
+			if (*++opt == 0) {
+				if (i == argc) usage();
+				opt= argv[i++];
+			}
+			do_ignore(1, opt);
+		} else
+		if (opt[0] == 'f' && opt[1] == 0) {
+			force= 1;
+			days= 1;
+		} else {
+			char *end;
+			days= strtoul(opt, &end, 10);
+			if (*opt == 0 || *end != 0
+				|| days == 0
+				|| ((time_t) (days * SEC_DAY)) / SEC_DAY != days
+			) {
+				fprintf(stderr,
+				"cleantmp: %s is not a valid number of days\n",
+					opt);
+				exit(1);
+			}
+		}
+	}
+	if (days == 0) usage();
+
+	days2time(days, &retired, &dotretired);
+
+	while (i < argc) {
+		int didx;
+
+		if (argv[i][0] == 0) {
+			fprintf(stderr, "cleantmp: empty pathname!\n");
+			exit(1);
+		}
+		addpath(&didx, argv[i]);
+		cleandir(TOP, retired);
+		delpath(didx);
+		assert(path[0] == 0);
+		i++;
+	}
+	exit(0);
+}
Index: /trunk/minix/commands/simple/cmp.c
===================================================================
--- /trunk/minix/commands/simple/cmp.c	(revision 9)
+++ /trunk/minix/commands/simple/cmp.c	(revision 9)
@@ -0,0 +1,129 @@
+/* cmp - compare two files		Author: Kees J. Bot.  */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+_PROTOTYPE(void fatal, (char *label));
+_PROTOTYPE(int cmp, (int fd1, int fd2));
+_PROTOTYPE(void Usage, (void));
+_PROTOTYPE(int main, (int argc, char **argv));
+
+#define BLOCK	4096
+
+static int loud = 0, silent = 0;
+static char *name1, *name2;
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  int fd1, fd2;
+
+  /* Process the '-l' or '-s' option. */
+  while (argc > 1 && argv[1][0] == '-' && argv[1][1] != 0) {
+  	if (argv[1][2] != 0) Usage();
+
+  	switch (argv[1][1]) {
+  	case '-':
+  		/* '--': no-op option. */
+  		break;
+  	case 'l':
+		loud = 1;
+		break;
+	case 's':
+		silent = 1;
+		break;
+	default:
+		Usage();
+	}
+	argc--;
+	argv++;
+  }
+  if (argc != 3) Usage();
+
+  /* Open the first file, '-' means standard input. */
+  if (argv[1][0] == '-' && argv[1][1] == 0) {
+	name1 = "stdin";
+	fd1 = 0;
+  } else {
+	name1 = argv[1];
+	if ((fd1 = open(name1, 0)) < 0) fatal(name1);
+  }
+
+  /* Second file likewise. */
+  if (argv[2][0] == '-' && argv[2][1] == 0) {
+	name2 = "stdin";
+	fd2 = 0;
+  } else {
+	name2 = argv[2];
+	if ((fd2 = open(name2, 0)) < 0) fatal(name2);
+  }
+
+  exit(cmp(fd1, fd2));
+}
+
+int cmp(fd1, fd2)
+int fd1, fd2;
+{
+  static char buf1[BLOCK], buf2[BLOCK];
+  int n1 = 0, n2 = 0, i1 = 0, i2 = 0, c1, c2;
+  off_t pos = 0, line = 1;
+  int eof = 0, differ = 0;
+
+  for (;;) {
+	if (i1 == n1) {
+		pos += n1;
+
+		if ((n1 = read(fd1, buf1, sizeof(buf1))) <= 0) {
+			if (n1 < 0) fatal(name1);
+			eof |= 1;
+		}
+		i1 = 0;
+	}
+	if (i2 == n2) {
+		if ((n2 = read(fd2, buf2, sizeof(buf2))) <= 0) {
+			if (n2 < 0) fatal(name2);
+			eof |= 2;
+		}
+		i2 = 0;
+	}
+	if (eof != 0) break;
+
+	c1 = buf1[i1++];
+	c2 = buf2[i2++];
+
+	if (c1 != c2) {
+		if (!loud) {
+			if (!silent) {
+				printf("%s %s differ: char %ld, line %ld\n",
+				       name1, name2, pos + i1, line);
+			}
+			return(1);
+		}
+		printf("%10ld %3o %3o\n", pos + i1, c1 & 0xFF, c2 & 0xFF);
+		differ = 1;
+	}
+	if (c1 == '\n') line++;
+  }
+  if (eof == (1 | 2)) return(differ);
+  if (!silent) fprintf(stderr, "cmp: EOF on %s\n", eof == 1 ? name1 : name2);
+  return(1);
+}
+
+void fatal(label)
+char *label;
+{
+  if (!silent) fprintf(stderr, "cmp: %s: %s\n", label, strerror(errno));
+  exit(2);
+}
+
+void Usage()
+{
+  fprintf(stderr, "Usage: cmp [-l | -s] file1 file2\n");
+  exit(2);
+}
Index: /trunk/minix/commands/simple/co.c
===================================================================
--- /trunk/minix/commands/simple/co.c	(revision 9)
+++ /trunk/minix/commands/simple/co.c	(revision 9)
@@ -0,0 +1,252 @@
+/* co - check out			Author: Peter S. Housel 12/24/87 */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define SUFFIX		",S"	/* svc indicator */
+#define SVCDIR		"SVC"	/* svc postfix indicator */
+
+#define LINELEN		256	/* maximum line length */
+
+#ifdef MAXPATHLEN
+#define PATHLEN MAXPATHLEN
+#else
+#define PATHLEN 128		/* buffer length for filenames */
+#endif
+
+char file[PATHLEN];		/* file to be checked in */
+char svc[PATHLEN];		/* filename for svc file */
+char newsvc[PATHLEN];		/* new copy of SVC file */
+char line[LINELEN];		/* temporary line buffer */
+char *p;			/* scratch character pointer */
+
+FILE *svcfp;			/* svc file */
+int rev;			/* old revision number */
+int lastrev, lockrev;		/* latest file revision, lock into */
+int status;			/* wait() buffer */
+int svclock;			/* lock the SVC file */
+struct stat stb;		/* stat() buffer */
+char *base;			/* basename of file */
+
+char difftemp[PATHLEN];		/* extract() fix/patch input */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void fname, (char *src, char *dst));
+_PROTOTYPE(void svcname, (char *src, char *dst));
+_PROTOTYPE(void extract, (char *script, char *out, int rev));
+_PROTOTYPE(char *basename, (char *name));
+_PROTOTYPE(char *whoami, (void));
+_PROTOTYPE(int getyn, (void));
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+#ifdef perprintf
+  char errbuf[BUFSIZ];
+  setbuf(stderr, errbuf);
+  perprintf(stderr);
+#endif
+
+  while (++argv, --argc) {
+	if ('-' == (*argv)[0]) {
+		if ('r' == (*argv)[1]) {
+			--argc;
+			rev = atoi(*++argv);
+			if (rev < 1) {
+				fprintf(stderr, "Illegal revision number\n");
+				exit(1);
+			}
+		} else if ('l' == (*argv)[1])
+			++svclock;
+		else {
+			fprintf(stderr, "co: illegal option -%c\n", (*argv)[1]);
+			exit(1);
+		}
+	} else
+		break;
+  }
+
+  if (1 != argc) {
+	fprintf(stderr, "co: bad number of files arguments\n");
+	exit(1);
+  }
+  fname(*argv, file);
+  svcname(file, svc);
+
+  fprintf(stderr, "%s -> %s\n", svc, base = basename(file));
+
+  if (NULL == (svcfp = fopen(svc, "r"))) {
+	perror("co: can't read SVC file");
+	exit(1);
+  }
+  if (1 != fscanf(svcfp, "# %d", &lastrev) || lastrev < 1) {
+	fprintf(stderr, "co: illegal SVC file format\n");
+	exit(1);
+  }
+  fclose(svcfp);
+
+  if (stat(base, &stb) >= 0 && (stb.st_mode & 0222)) {
+	fprintf(stderr, "Writable %s exists - overwrite (n/y)? ", base);
+	if (!getyn()) {
+		fprintf(stderr, "Checkout aborted\n");
+		exit(1);
+	}
+  }
+  if (strlen(base)) unlink(base);
+  if (0 == rev) rev = lastrev;
+  fprintf(stderr, "Checking out revision %d", rev);
+  extract(svc, base, rev);
+
+  if (svclock) {
+	lockrev = lastrev + 1;
+	fprintf(stderr, "; Locking into revision %d\n", lockrev);
+	if (stat(svc, &stb) < 0 || chmod(svc, stb.st_mode | 0200) < 0)
+		perror("co: can't chmod SVC file");
+
+	if (stat(base, &stb) < 0 || chmod(base, stb.st_mode | 0200) < 0)
+		perror("co: can't chmod source file");
+
+	if (NULL == (svcfp = fopen(svc, "a"))
+	    || (fprintf(svcfp, "#***SVCLOCK*** %s %d\n", whoami(), lockrev), ferror(svcfp))) {
+		fprintf(stderr, "co: can't lock %s\n", svc);
+		exit(1);
+	}
+	if (stat(svc, &stb) < 0 || chmod(svc, stb.st_mode & 0555))
+		perror("co: can't chmod SVC file");
+  } else {
+	putchar('\n');
+	if (stat(base, &stb) < 0 || chmod(base, stb.st_mode & 0555))
+		perror("co: can't chmod source file");
+  }
+
+  return(0);
+}
+
+
+void fname(src, dst)
+char *src, *dst;
+{
+  char *p;
+  strcpy(dst, src);
+  p = &dst[strlen(src) - strlen(SUFFIX)];
+  if (!strcmp(p, SUFFIX)) *p = '\0';
+}
+
+void svcname(src, dst)
+char *src, *dst;
+{
+  char *p;
+
+  strcpy(dst, src);
+  strcat(dst, SUFFIX);
+
+  if (0 != access(dst, 4)) {
+	char dirname[PATHLEN];
+	if (NULL != (p = strrchr(src, '/')))
+		strncpy(dirname, src, (size_t)(p - src) + 1);
+	else
+		dirname[0] = '\0';
+	strcat(dirname, SVCDIR);
+
+	if (0 == access(dirname, 1)) {
+		strcpy(dst, dirname);
+		if (NULL == p) {
+			strcat(dst, "/");
+			strcat(dst, src);
+		} else
+			strcat(dst, p);
+		strcat(dst, SUFFIX);
+	}
+  }
+}
+
+void extract(script, out, rev)
+char *script, *out;
+int rev;
+{
+  FILE *outfp;
+  int testrev;
+  char buf[80];
+
+  sprintf(difftemp, "Fix.%s", out);
+
+  svcfp = fopen(script, "r");
+  fgets(line, LINELEN, svcfp);	/* skip '# rev' line */
+  fgets(line, LINELEN, svcfp);	/* skip 'cat <***MAIN-eof***' line */
+
+  if (NULL == (outfp = fopen(out, "w"))) {
+	perror("co: can't create output file");
+	return;
+  }
+  while (NULL != fgets(line, LINELEN, svcfp) &&
+	  strcmp(line, "***MAIN-eof***\n"))
+	fputs(line, outfp);
+
+  fclose(outfp);
+
+  while (NULL != fgets(line, LINELEN, svcfp)) {
+	if (!strncmp(line, "if ", (size_t)3)) {
+		sscanf(line, "if test $2 -ge %d", &testrev);
+		if (rev >= testrev) {
+			unlink(difftemp);
+			return;
+		}
+		if (NULL == (outfp = fopen(difftemp, "w"))) {
+			perror("co: can't create output file");
+			return;
+		}
+		sprintf(buf, "***%d-eof***\n", testrev);
+		while (NULL != fgets(line, LINELEN, svcfp) &&
+							strcmp(line, buf))
+			fputs(line, outfp);
+		fclose(outfp);
+	} else if (!strncmp(line, "mv ", (size_t)3)) {
+		sprintf(buf, "mv Fix.%s %s", out, out);
+		system(buf);
+	} else if (!strncmp(line, "fix ", (size_t)4)) {
+		sprintf(buf, "fix %s Fix.%s > New.%s; mv New.%s %s", out, out, out, out, out);
+		system(buf);
+	} else if (!strncmp(line, "patch ", (size_t)6)) {
+		sprintf(buf, "patch -n -s %s < Fix.%s; rm -f %s.orig", out, out, out);
+		system(buf);
+	} else {		/* ignore */
+	}
+  }
+
+  unlink(difftemp);
+  return;
+}
+
+char *basename(name)
+char *name;
+{
+  char *p;
+
+  if (NULL == (p = strrchr(name, '/')))
+	return name;
+  else
+	return p + 1;
+}
+
+char *whoami()
+{
+  struct passwd *pw;
+
+  if (NULL != (pw = getpwuid(getuid())))
+	return pw->pw_name;
+  else
+	return "nobody";
+}
+
+int getyn()
+{
+  char ans[10];
+
+  return(NULL != fgets(ans, 10, stdin)) && ('y' == ans[0] || 'Y' == ans[0]);
+}
Index: /trunk/minix/commands/simple/comm.c
===================================================================
--- /trunk/minix/commands/simple/comm.c	(revision 9)
+++ /trunk/minix/commands/simple/comm.c	(revision 9)
@@ -0,0 +1,206 @@
+/* comm - select lines from two sorted files	Author: Martin C. Atkins */
+
+/*
+ *	This program was written by:
+ *		Martin C. Atkins,
+ *		University of York,
+ *		Heslington,
+ *		York. Y01 5DD
+ *		England
+ *	and is released into the public domain, on the condition
+ *	that this comment is always included without alteration.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <minix/minlib.h>
+#include <stdio.h>
+
+#define BUFFER_SIZE (512)
+#define LINMAX (600)
+
+struct file {
+  char *name;			/* the file's name */
+  int fd;			/* the file descripter */
+  char buf[BUFFER_SIZE];		/* buffer storage */
+  char *next;			/* the next character to read */
+  char *endp;			/* the first invalid character */
+  int seeneof;			/* an end of file has been seen */
+} files[2];
+
+char lines[2][LINMAX];
+
+int colflgs[3] = {1, 2, 3};	/* number of tabs + 1: 0 => no column */
+
+static char *umsg = "Usage: comm [-[123]] file1 file2\n";
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(void error, (char *s, char *f));
+_PROTOTYPE(void eopen, (char *fn, struct file *file));
+_PROTOTYPE(int getbuf, (struct file *file));
+_PROTOTYPE(int readline, (int fno));
+_PROTOTYPE(void comm, (void));
+_PROTOTYPE(void putcol, (int col, char *buf));
+_PROTOTYPE(void cpycol, (int col));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int cnt;
+  if (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
+	char *ap;
+	for (ap = &argv[1][1]; *ap; ap++) switch (*ap) {
+		    case '1':
+		    case '2':
+		    case '3':
+			cnt = *ap - '1';
+			if (colflgs[cnt] == 0) break;
+			colflgs[cnt] = 0;
+			for (cnt++; cnt < 3; cnt++) colflgs[cnt]--;
+			break;
+		    default:	usage();
+		}
+	argc--;
+	argv++;
+  }
+  if (argc != 3) usage();
+  eopen(argv[1], &files[0]);
+  eopen(argv[2], &files[1]);
+  comm();
+  return(0);
+}
+
+void usage()
+{
+
+  std_err(umsg);
+  exit(1);
+}
+
+void error(s, f)
+char *s, *f;
+{
+  std_err("comm: ");
+  std_err(s);
+  if (f) std_err(f);
+  std_err("\n");
+  exit(1);
+}
+
+void eopen(fn, file)
+char *fn;
+struct file *file;
+{
+  file->name = fn;
+  file->next = file->endp = &file->buf[0];
+  file->seeneof = 0;
+  if (fn[0] == '-' && fn[1] == '\0')
+	file->fd = 0;
+  else if ((file->fd = open(fn, O_RDONLY)) < 0)
+	error("can't open ", fn);
+}
+
+
+int getbuf(file)
+struct file *file;
+{
+/* Get a buffer-full from the file.  Return true if no characters
+ * were obtained because we are at end of file.
+ */
+  int n;
+
+  if (file->seeneof) return(1);
+  if ((n = read(file->fd, &file->buf[0], BUFFER_SIZE)) < 0)
+	error("read error on ", file->name);
+  if (n == 0) {
+	file->seeneof++;
+	return 1;
+  }
+  file->next = &file->buf[0];
+  file->endp = &file->buf[n];
+  return(0);
+}
+
+
+int readline(fno)
+int fno;
+{
+/* Read up to the next '\n' character to buf.
+ * Return a complete line, even if end of file occurs within a line.
+ * Return false at end of file/
+ */
+  register struct file *file = &files[fno];
+  char *buf = lines[fno];
+
+  if (file->next == file->endp && getbuf(file)) return(0);
+  while ((*buf++ = *file->next++) != '\n')
+	if (file->next == file->endp && getbuf(file)) {
+		*buf++ = '\n';
+		*buf = '\0';
+		return(1);
+	}
+  *buf = '\0';
+  return(1);
+}
+
+void comm()
+{
+  register int res;
+
+  if (!readline(0)) {
+	cpycol(1);
+	return;
+  }
+  if (!readline(1)) {
+	putcol(0, lines[0]);
+	cpycol(0);
+	return;
+  }
+  for (;;) {
+	if ((res = strcmp(lines[0], lines[1])) != 0) {
+		res = res > 0;
+		putcol(res, lines[res]);
+		if (!readline(res)) {
+			putcol(!res, lines[!res]);
+			cpycol(!res);
+			return;
+		}
+	} else {
+		putcol(2, lines[0]);	/* files[1]lin == f2lin */
+		if (!readline(0)) {
+			cpycol(1);
+			return;
+		}
+		if (!readline(1)) {
+			putcol(0, lines[0]);
+			cpycol(0);
+			return;
+		}
+	}
+  }
+
+  /* NOTREACHED */
+}
+
+void putcol(col, buf)
+int col;
+char *buf;
+{
+  int cnt;
+
+  if (colflgs[col] == 0) return;
+  for (cnt = 0; cnt < colflgs[col] - 1; cnt++) printf("\t");
+  printf("%s", buf);
+}
+
+void cpycol(col)
+int col;
+{
+  if (colflgs[col]) while (readline(col))
+		putcol(col, lines[col]);
+}
Index: /trunk/minix/commands/simple/compress.c
===================================================================
--- /trunk/minix/commands/simple/compress.c	(revision 9)
+++ /trunk/minix/commands/simple/compress.c	(revision 9)
@@ -0,0 +1,1617 @@
+/* compress - Reduce file size using Modified Lempel-Ziv encoding */
+
+/*
+ * compress.c - File compression ala IEEE Computer, June 1984.
+ *
+ * Authors:	Spencer W. Thomas	(decvax!harpo!utah-cs!utah-gr!thomas)
+ *		Jim McKie		(decvax!mcvax!jim)
+ *		Steve Davies		(decvax!vax135!petsd!peora!srd)
+ *		Ken Turkowski		(decvax!decwrl!turtlevax!ken)
+ *		James A. Woods		(decvax!ihnp4!ames!jaw)
+ *		Joe Orost		(decvax!vax135!petsd!joe)
+ *
+ *		Richard Todd		Port to MINIX
+ *		Andy Tanenbaum		Cleanup
+ *
+ *
+ * Algorithm from "A Technique for High Performance Data Compression",
+ * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
+ *
+ * Usage: compress [-dfvc] [-b bits] [file ...]
+ * Inputs:
+ *	-d:	    If given, decompression is done instead.
+ *
+ *      -c:         Write output on stdout.
+ *
+ *      -b:         Parameter limits the max number of bits/code.
+ *
+ *	-f:	    Forces output file to be generated, even if one already
+ *		    exists, and even if no space is saved by compressing.
+ *		    If -f is not used, the user will be prompted if stdin is
+ *		    a tty, otherwise, the output file will not be overwritten.
+ *
+ *      -v:	    Write compression statistics
+ *
+ * 	file ...:   Files to be compressed.  If none specified, stdin
+ *		    is used.
+ * Outputs:
+ *	file.Z:	    Compressed form of file with same mode, owner, and utimes
+ * 	or stdout   (if stdin used as input)
+ *
+ * Assumptions:
+ *	When filenames are given, replaces with the compressed version
+ *	(.Z suffix) only if the file decreases in size.
+ * Algorithm:
+ * 	Modified Lempel-Ziv method (LZW).  Basically finds common
+ * substrings and replaces them with a variable size code.  This is
+ * deterministic, and can be done on the fly.  Thus, the decompression
+ * procedure needs no input table, but tracks the way the table was built.
+ */
+
+
+#define AZTEC86 1
+
+#define	min(a,b)	((a>b) ? b : a)
+
+/*
+ * Set USERMEM to the maximum amount of physical user memory available
+ * in bytes.  USERMEM is used to determine the maximum BITS that can be used
+ * for compression.
+ *
+ * SACREDMEM is the amount of physical memory saved for others; compress
+ * will hog the rest.
+ */
+#ifndef SACREDMEM
+#define SACREDMEM	0
+#endif
+
+#ifndef USERMEM
+# define USERMEM 	450000	/* default user memory */
+#endif
+
+#define REGISTER register
+#define DOTZ ".Z"
+
+#include <limits.h>
+#include <dirent.h>
+
+/* The default for Minix is -b13, but we can do -b16 if the machine can. */
+#define DEFAULTBITS 13
+#if INT_MAX == 32767
+# define BITS 13
+#else
+# define BITS 16
+#endif
+
+#ifdef USERMEM
+# if USERMEM >= (433484+SACREDMEM)
+#  define PBITS	16
+# else
+#  if USERMEM >= (229600+SACREDMEM)
+#   define PBITS	15
+#  else
+#   if USERMEM >= (127536+SACREDMEM)
+#    define PBITS	14
+#   else
+#    if USERMEM >= (73464+SACREDMEM)
+#     define PBITS	13
+#    else
+#     define PBITS	12
+#    endif
+#   endif
+#  endif
+# endif
+# undef USERMEM
+#endif /* USERMEM */
+
+#ifdef PBITS		/* Preferred BITS for this memory size */
+# ifndef BITS
+#  define BITS PBITS
+# endif
+#endif /* PBITS */
+
+#if BITS == 16
+# define HSIZE	69001		/* 95% occupancy */
+#endif
+#if BITS == 15
+# define HSIZE	35023		/* 94% occupancy */
+#endif
+#if BITS == 14
+# define HSIZE	18013		/* 91% occupancy */
+#endif
+#if BITS == 13
+# define HSIZE	9001		/* 91% occupancy */
+#endif
+#if BITS <= 12
+# define HSIZE	5003		/* 80% occupancy */
+#endif
+
+
+/*
+ * a code_int must be able to hold 2**BITS values of type int, and also -1
+ */
+#if BITS > 15
+typedef long int	code_int;
+#else
+typedef int		code_int;
+#endif
+
+#ifdef SIGNED_COMPARE_SLOW
+typedef unsigned long int count_int;
+typedef unsigned short int count_short;
+#else
+typedef long int	  count_int;
+#endif
+
+#ifdef NO_UCHAR
+ typedef char	char_type;
+#else
+ typedef	unsigned char	char_type;
+#endif /* UCHAR */
+char_type magic_header[] = "\037\235";	/* 1F 9D */
+
+/* Defines for third byte of header */
+#define BIT_MASK	0x1f
+#define BLOCK_MASK	0x80
+/* Masks 0x40 and 0x20 are free.  I think 0x20 should mean that there is
+   a fourth header byte (for expansion).
+*/
+#define INIT_BITS 9			/* initial number of bits/code */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utime.h>
+#include <stdio.h>
+
+#define ARGVAL() (*++(*argv) || (--argc && *++argv))
+
+int n_bits;				/* number of bits/code */
+int maxbits = DEFAULTBITS;		/* user settable max # bits/code */
+code_int maxcode;			/* maximum code, given n_bits */
+code_int maxmaxcode = 1 << BITS;	/* should NEVER generate this code */
+#ifdef COMPATIBLE		/* But wrong! */
+# define MAXCODE(n_bits)	(1 << (n_bits) - 1)
+#else
+# define MAXCODE(n_bits)	((1 << (n_bits)) - 1)
+#endif /* COMPATIBLE */
+
+#ifndef AZTEC86
+	count_int htab [HSIZE];
+	unsigned short codetab [HSIZE];
+#else
+	count_int *htab;
+	unsigned short *codetab;
+#	define HTABSIZE ((size_t)(HSIZE*sizeof(count_int)))
+#	define CODETABSIZE ((size_t)(HSIZE*sizeof(unsigned short)))
+
+
+#define htabof(i)	htab[i]
+#define codetabof(i)	codetab[i]
+#endif	/* XENIX_16 */
+code_int hsize = HSIZE;			/* for dynamic table sizing */
+count_int fsize;
+
+/*
+ * To save much memory, we overlay the table used by compress() with those
+ * used by decompress().  The tab_prefix table is the same size and type
+ * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
+ * get this from the beginning of htab.  The output stack uses the rest
+ * of htab, and contains characters.  There is plenty of room for any
+ * possible stack (stack used to be 8000 characters).
+ */
+
+#define tab_prefixof(i)	codetabof(i)
+#ifdef XENIX_16
+# define tab_suffixof(i)	((char_type *)htab[(i)>>15])[(i) & 0x7fff]
+# define de_stack		((char_type *)(htab2))
+#else	/* Normal machine */
+# define tab_suffixof(i)	((char_type *)(htab))[i]
+# define de_stack		((char_type *)&tab_suffixof(1<<BITS))
+#endif	/* XENIX_16 */
+
+code_int free_ent = 0;			/* first unused entry */
+int exit_stat = 0;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void Usage, (void));
+_PROTOTYPE(void compress, (void));
+_PROTOTYPE(void onintr, (int dummy));
+_PROTOTYPE(void oops, (int dummy));
+_PROTOTYPE(void output, (code_int code));
+_PROTOTYPE(int foreground, (void));
+_PROTOTYPE(void decompress, (void));
+_PROTOTYPE(code_int getcode, (void)); 
+_PROTOTYPE(void writeerr, (void));
+_PROTOTYPE(void copystat, (char *ifname, char *ofname));
+_PROTOTYPE(int foreground, (void));
+_PROTOTYPE(void cl_block , (void));
+_PROTOTYPE(void cl_hash, (count_int hsize));
+_PROTOTYPE(void prratio, (FILE *stream, long int num, long int den));
+_PROTOTYPE(void version, (void));
+
+void Usage() {
+#ifdef DEBUG
+fprintf(stderr,"Usage: compress [-dDVfc] [-b maxbits] [file ...]\n");
+}
+int debug = 0;
+#else
+fprintf(stderr,"Usage: compress [-dfvcV] [-b maxbits] [file ...]\n");
+}
+#endif /* DEBUG */
+int nomagic = 0;	/* Use a 3-byte magic number header, unless old file */
+int zcat_flg = 0;	/* Write output on stdout, suppress messages */
+int quiet = 0;		/* don't tell me about compression */
+
+/*
+ * block compression parameters -- after all codes are used up,
+ * and compression rate changes, start over.
+ */
+int block_compress = BLOCK_MASK;
+int clear_flg = 0;
+long int ratio = 0;
+#define CHECK_GAP 10000	/* ratio check interval */
+count_int checkpoint = CHECK_GAP;
+/*
+ * the next two codes should not be changed lightly, as they must not
+ * lie within the contiguous general code space.
+ */ 
+#define FIRST	257	/* first free entry */
+#define	CLEAR	256	/* table clear output code */
+
+int force = 0;
+char ofname [100];
+#ifdef DEBUG
+int verbose = 0;
+#endif /* DEBUG */
+
+#ifndef METAWARE
+#ifdef AZTEC86
+void
+#else
+int
+#endif
+#ifndef __STDC__
+(*bgnd_flag)();
+#else
+(*bgnd_flag)(int);
+#endif
+#endif
+
+int do_decomp = 0;
+
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+    int overwrite = 0;	/* Do not overwrite unless given -f flag */
+    char tempname[100];
+    char **filelist, **fileptr;
+    char *cp;
+    struct stat statbuf;
+#ifndef METAWARE
+    if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
+	signal ( SIGINT, onintr );
+	signal ( SIGSEGV, oops );
+    }
+#endif
+#ifdef AZTEC86
+#ifdef METAWARE
+	_setmode(NULL,_ALL_FILES_BINARY);
+	_setmode(stdin,_BINARY);
+	_setmode(stdout,_BINARY);
+	_setmode(stderr,_TEXT);
+#endif
+	if (NULL == (htab = (count_int *)malloc(HTABSIZE)))
+	{
+		fprintf(stderr,"Can't allocate htab\n");
+		exit(1);
+	}
+	if (NULL == (codetab = (unsigned short *)malloc(CODETABSIZE)))
+	{
+		fprintf(stderr,"Can't allocate codetab\n");
+		exit(1);
+	}
+#endif
+#ifdef COMPATIBLE
+    nomagic = 1;	/* Original didn't have a magic number */
+#endif /* COMPATIBLE */
+
+    filelist = fileptr = (char **)(malloc((size_t)(argc * sizeof(*argv))));
+    *filelist = NULL;
+
+    if((cp = strrchr(argv[0], '/')) != 0) {
+	cp++;
+    } else {
+	cp = argv[0];
+    }
+    if(strcmp(cp, "uncompress") == 0) {
+	do_decomp = 1;
+    } else if(strcmp(cp, "zcat") == 0) {
+	do_decomp = 1;
+	zcat_flg = 1;
+    }
+
+#ifdef BSD4_2
+    /* 4.2BSD dependent - take it out if not */
+    setlinebuf( stderr );
+#endif /* BSD4_2 */
+
+    /* Argument Processing
+     * All flags are optional.
+     * -D => debug
+     * -V => print Version; debug verbose
+     * -d => do_decomp
+     * -v => unquiet
+     * -f => force overwrite of output file
+     * -n => no header: useful to uncompress old files
+     * -b maxbits => maxbits.  If -b is specified, then maxbits MUST be
+     *	    given also.
+     * -c => cat all output to stdout
+     * -C => generate output compatible with compress 2.0.
+     * if a string is left, must be an input filename.
+     */
+    for (argc--, argv++; argc > 0; argc--, argv++) 
+	{
+		if (**argv == '-') 
+		{	/* A flag argument */
+		    while (*++(*argv)) 
+			{	/* Process all flags in this arg */
+				switch (**argv) 
+				{
+#ifdef DEBUG
+			    case 'D':
+					debug = 1;
+					break;
+			    case 'V':
+					verbose = 1;
+					version();
+					break;
+#else
+			    case 'V':
+					version();
+					break;
+#endif /* DEBUG */
+			    case 'v':
+					quiet = 0;
+					break;
+			    case 'd':
+					do_decomp = 1;
+					break;
+			    case 'f':
+			    case 'F':
+					overwrite = 1;
+					force = 1;
+					break;
+			    case 'n':
+					nomagic = 1;
+					break;
+			    case 'C':
+					block_compress = 0;
+					break;
+			    case 'b':
+					if (!ARGVAL()) 
+					{
+					    fprintf(stderr, "Missing maxbits\n");
+					    Usage();
+					    exit(1);
+					}
+					maxbits = atoi(*argv);
+					goto nextarg;
+			    case 'c':
+					zcat_flg = 1;
+					break;
+			    case 'q':
+					quiet = 1;
+					break;
+			    default:
+					fprintf(stderr, "Unknown flag: '%c'; ", **argv);
+					Usage();
+					exit(1);
+				}
+		    }
+		}
+		else 
+		{		/* Input file name */
+		    *fileptr++ = *argv;	/* Build input file list */
+		    *fileptr = NULL;
+		    /* process nextarg; */
+		}
+		nextarg: continue;
+    }
+
+    if(maxbits < INIT_BITS) maxbits = INIT_BITS;
+    if (maxbits > BITS) maxbits = BITS;
+    maxmaxcode = 1 << maxbits;
+
+    if (*filelist != NULL) 
+	{
+		for (fileptr = filelist; *fileptr; fileptr++) 
+		{
+		    exit_stat = 0;
+		    if (do_decomp != 0) 
+			{			/* DECOMPRESSION */
+				/* Check for .Z suffix */
+#ifndef PCDOS
+				if (strcmp(*fileptr + strlen(*fileptr) - 2, DOTZ) != 0) 
+#else
+				if (strcmp(*fileptr + strlen(*fileptr) - 1, DOTZ) != 0) 
+#endif
+				{
+				    /* No .Z: tack one on */
+				    strcpy(tempname, *fileptr);
+#ifndef PCDOS
+				    strcat(tempname, DOTZ);
+#else
+					/* either tack one on or replace last character */
+					{
+						char *dot;
+						if (NULL == (dot = strchr(tempname,'.')))
+						{
+							strcat(tempname,".Z");
+						}
+						else
+						/* if there is a dot then either tack a z on
+						   or replace last character */
+						{
+							if (strlen(dot) < 4)
+								strcat(tempname,DOTZ);
+							else
+								dot[3] = 'Z';
+						}
+					}
+#endif
+				    *fileptr = tempname;
+				}
+				/* Open input file */
+				if ((freopen(*fileptr, "r", stdin)) == NULL) 
+				{
+					perror(*fileptr); continue;
+				}
+				/* Check the magic number */
+				if (nomagic == 0) 
+				{
+					unsigned magic1, magic2;
+				    if (((magic1 = getc(stdin)) != (magic_header[0] & 0xFF))
+				     || ((magic2 = getc(stdin)) != (magic_header[1] & 0xFF))) 
+					{
+						fprintf(stderr, 
+						"%s: not in compressed format %x %x\n",
+					    *fileptr,magic1,magic2);
+					    continue;
+				    }
+				    maxbits = getc(stdin);	/* set -b from file */
+				    block_compress = maxbits & BLOCK_MASK;
+				    maxbits &= BIT_MASK;
+				    maxmaxcode = 1 << maxbits;
+				    if(maxbits > BITS) 
+					{
+						fprintf(stderr,
+					"%s: compressed with %d bits, can only handle %d bits\n",
+						*fileptr, maxbits, BITS);
+						continue;
+				    }
+				}
+				/* Generate output filename */
+				strcpy(ofname, *fileptr);
+#ifndef PCDOS
+				ofname[strlen(*fileptr) - 2] = '\0';  /* Strip off .Z */
+#else
+				/* kludge to handle various common three character extension */
+				{
+					char *dot; 
+					char fixup = '\0';
+					/* first off, map name to upper case */
+					for (dot = ofname; *dot; dot++)
+						*dot = toupper(*dot);
+					if (NULL == (dot = strchr(ofname,'.')))
+					{
+						fprintf(stderr,"Bad filename %s\n",ofname);
+						exit(1);
+					}
+					if (strlen(dot) == 4)
+					/* we got three letter extensions */
+					{
+						if (strcmp(dot,".EXZ") == 0)
+							fixup = 'E';
+						else if (strcmp(dot,".COZ") == 0)
+							fixup = 'M';
+						else if (strcmp(dot,".BAZ") == 0)
+							fixup = 'S';
+						else if (strcmp(dot,".OBZ") == 0)
+							fixup = 'J';
+						else if (strcmp(dot,".SYZ") == 0)
+							fixup = 'S';
+						else if (strcmp(dot,".DOZ") == 0)
+							fixup = 'C';
+
+					} 
+					/* replace the Z */
+					ofname[strlen(*fileptr) - 1] = fixup;
+				}
+#endif
+		    } else 
+			{					/* COMPRESSION */
+				if (strcmp(*fileptr + strlen(*fileptr) - 2, DOTZ) == 0) 
+				{
+			    	fprintf(stderr, "%s: already has .Z suffix -- no change\n",
+				    *fileptr);
+				    continue;
+				}
+				/* Open input file */
+				if ((freopen(*fileptr, "r", stdin)) == NULL) 
+				{
+				    perror(*fileptr); continue;
+				}
+				(void)stat( *fileptr, &statbuf );
+				fsize = (long) statbuf.st_size;
+				/*
+				 * tune hash table size for small files -- ad hoc,
+				 * but the sizes match earlier #defines, which
+				 * serve as upper bounds on the number of output codes. 
+				 */
+				hsize = HSIZE; /*lint -e506 -e712 */
+				if ( fsize < (1 << 12) )
+				    hsize = min ( 5003, HSIZE );
+				else if ( fsize < (1 << 13) )
+				    hsize = min ( 9001, HSIZE );
+				else if ( fsize < (1 << 14) )
+				    hsize = min ( 18013, HSIZE );
+				else if ( fsize < (1 << 15) )
+				    hsize = min ( 35023, HSIZE );
+				else if ( fsize < 47000 )
+				    hsize = min ( 50021, HSIZE ); /*lint +e506 +e712 */
+
+				/* Generate output filename */
+				strcpy(ofname, *fileptr);
+#ifndef BSD4_2		/* Short filenames */
+				if ((cp=strrchr(ofname,'/')) != NULL)
+					cp++;
+				else
+					cp = ofname;
+				if (strlen(cp) >= _DIRENT_NAME_LEN-3) 
+				{
+				    fprintf(stderr,"%s: filename too long to tack on .Z\n",cp);
+				    continue;
+				}
+#ifdef PCDOS
+				else
+				{
+					/* either tack one on or replace last character */
+					char *dot;
+					if (NULL == (dot = strchr(cp,'.')))
+					{
+						strcat(cp,".Z");
+					}
+					else
+					/* if there is a dot then either tack a z on
+					   or replace last character */
+					{
+						if (strlen(dot) < 4)
+							strcat(cp,DOTZ);
+						else
+							dot[3] = 'Z';
+					}
+				}
+#endif
+#endif  /* BSD4_2		Long filenames allowed */
+#ifndef PCDOS
+			/* PCDOS takes care of this above */
+				strcat(ofname, DOTZ);
+#endif
+		    }
+		    /* Check for overwrite of existing file */
+		    if (overwrite == 0 && zcat_flg == 0) 
+			{
+				if (stat(ofname, &statbuf) == 0) 
+				{
+				    char response[2]; int fd;
+				    response[0] = 'n';
+				    fprintf(stderr, "%s already exists;", ofname);
+				    if (foreground()) 
+					{
+						fd = open("/dev/tty", O_RDONLY);
+						fprintf(stderr, 
+						" do you wish to overwrite %s (y or n)? ", ofname);
+						fflush(stderr);
+						(void)read(fd, response, 2);
+						while (response[1] != '\n') 
+						{
+						    if (read(fd, response+1, 1) < 0) 
+							{	/* Ack! */
+								perror("stderr"); 
+								break;
+						    }
+						}
+						close(fd);
+				    }
+				    if (response[0] != 'y') 
+					{
+						fprintf(stderr, "\tnot overwritten\n");
+						continue;
+				    }
+				}
+		    }
+		    if(zcat_flg == 0) 
+			{		/* Open output file */
+				if (freopen(ofname, "w", stdout) == NULL) 
+				{
+				    perror(ofname);
+				    continue;
+				}
+				if(!quiet)
+					fprintf(stderr, "%s: ", *fileptr);
+		    }
+
+		    /* Actually do the compression/decompression */
+		    if (do_decomp == 0)	
+				compress();
+#ifndef DEBUG
+		    else			
+				decompress();
+#else
+		    else if (debug == 0)	
+				decompress();
+		    else			
+				printcodes();
+		    if (verbose)		
+				dump_tab();
+#endif /* DEBUG */
+		    if(zcat_flg == 0) 
+			{
+				copystat(*fileptr, ofname);	/* Copy stats */
+				if((exit_stat == 1) || (!quiet))
+					putc('\n', stderr);
+		    }
+		}
+    } else 
+	{		/* Standard input */
+		if (do_decomp == 0) 
+		{
+			compress();
+#ifdef DEBUG
+			if(verbose)		dump_tab();
+#endif /* DEBUG */
+			if(!quiet)
+				putc('\n', stderr);
+		} else 
+		{
+		    /* Check the magic number */
+		    if (nomagic == 0) 
+			{
+				if ((getc(stdin)!=(magic_header[0] & 0xFF))
+				 || (getc(stdin)!=(magic_header[1] & 0xFF))) 
+				{
+				    fprintf(stderr, "stdin: not in compressed format\n");
+				    exit(1);
+				}
+				maxbits = getc(stdin);	/* set -b from file */
+				block_compress = maxbits & BLOCK_MASK;
+				maxbits &= BIT_MASK;
+				maxmaxcode = 1 << maxbits;
+				fsize = 100000;		/* assume stdin large for USERMEM */
+				if(maxbits > BITS) 
+				{
+					fprintf(stderr,
+					"stdin: compressed with %d bits, can only handle %d bits\n",
+					maxbits, BITS);
+					exit(1);
+				}
+		    }
+#ifndef DEBUG
+		    decompress();
+#else
+		    if (debug == 0)	decompress();
+		    else		printcodes();
+		    if (verbose)	dump_tab();
+#endif /* DEBUG */
+		}
+    }
+    return(exit_stat);
+}
+
+static int offset;
+long int in_count = 1;			/* length of input */
+long int bytes_out;			/* length of compressed output */
+long int out_count = 0;			/* # of codes output (for debugging) */
+
+/*
+ * compress stdin to stdout
+ *
+ * Algorithm:  use open addressing double hashing (no chaining) on the 
+ * prefix code / next character combination.  We do a variant of Knuth's
+ * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+ * secondary probe.  Here, the modular division first probe is gives way
+ * to a faster exclusive-or manipulation.  Also do block compression with
+ * an adaptive reset, whereby the code table is cleared when the compression
+ * ratio decreases, but after the table fills.  The variable-length output
+ * codes are re-sized at this point, and a special CLEAR code is generated
+ * for the decompressor.  Late addition:  construct the table according to
+ * file size for noticeable speed improvement on small files.  Please direct
+ * questions about this implementation to ames!jaw.
+ */
+
+void compress() 
+{
+    REGISTER long fcode;
+    REGISTER code_int i = 0;
+    REGISTER int c;
+    REGISTER code_int ent;
+#ifdef XENIX_16
+    REGISTER code_int disp;
+#else	/* Normal machine */
+    REGISTER int disp;
+#endif
+    REGISTER code_int hsize_reg;
+    REGISTER int hshift;
+
+#ifndef COMPATIBLE
+    if (nomagic == 0) 
+	{
+		putc(magic_header[0],stdout); 
+		putc(magic_header[1],stdout);
+		putc((char)(maxbits | block_compress),stdout);
+		if(ferror(stdout))
+			writeerr();
+    }
+#endif /* COMPATIBLE */
+
+    offset = 0;
+    bytes_out = 3;		/* includes 3-byte header mojo */
+    out_count = 0;
+    clear_flg = 0;
+    ratio = 0;
+    in_count = 1;
+    checkpoint = CHECK_GAP;
+    maxcode = MAXCODE(n_bits = INIT_BITS);
+    free_ent = ((block_compress) ? FIRST : 256 );
+
+    ent = getc(stdin);
+
+    hshift = 0;
+    for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
+    	hshift++;
+    hshift = 8 - hshift;		/* set hash code range bound */
+
+    hsize_reg = hsize;
+    cl_hash( (count_int) hsize_reg);		/* clear hash table */
+
+#ifdef SIGNED_COMPARE_SLOW
+    while ( (c = getc(stdin)) != (unsigned) EOF )
+#else
+    while ( (c = getc(stdin)) != EOF )
+#endif
+	{
+		in_count++;
+		fcode = (long) (((long) c << maxbits) + ent);
+	 	i = ((c << hshift) ^ ent);	/* xor hashing */
+
+		if ( htabof (i) == fcode ) 
+		{
+		    ent = codetabof (i);
+		    continue;
+		} else if ( (long)htabof (i) < 0 )	/* empty slot */
+		    goto nomatch;
+	 	disp = hsize_reg - i;		/* secondary hash (after G. Knott) */
+		if ( i == 0 )
+		    disp = 1;
+probe:
+		if ( (i -= disp) < 0 )
+		    i += hsize_reg;
+
+		if ( htabof (i) == fcode ) 
+		{
+		    ent = codetabof (i);
+		    continue;
+		}
+		if ( (long)htabof (i) > 0 ) 
+		    goto probe;
+nomatch:
+		output ( (code_int) ent );
+		out_count++;
+	 	ent = c;
+#ifdef SIGNED_COMPARE_SLOW
+		if ( (unsigned) free_ent < (unsigned) maxmaxcode)
+#else
+		if ( free_ent < maxmaxcode )
+#endif
+		{
+	 	    codetabof (i) = free_ent++;	/* code -> hashtable */
+		    htabof (i) = fcode;
+		}
+		else if ( (count_int)in_count >= checkpoint && block_compress )
+		    cl_block ();
+    }
+    /*
+     * Put out the final code.
+     */
+    output( (code_int)ent );
+    out_count++;
+    output( (code_int)-1 );
+
+    /*
+     * Print out stats on stderr
+     */
+    if(zcat_flg == 0 && !quiet) 
+	{
+#ifdef DEBUG
+		fprintf( stderr,
+		"%ld chars in, %ld codes (%ld bytes) out, compression factor: ",
+		in_count, out_count, bytes_out );
+		prratio( stderr, in_count, bytes_out );
+		fprintf( stderr, "\n");
+		fprintf( stderr, "\tCompression as in compact: " );
+		prratio( stderr, in_count-bytes_out, in_count );
+		fprintf( stderr, "\n");
+		fprintf( stderr, "\tLargest code (of last block) was %d (%d bits)\n",
+		free_ent - 1, n_bits );
+#else /* !DEBUG */
+		fprintf( stderr, "Compression: " );
+		prratio( stderr, in_count-bytes_out, in_count );
+#endif /* DEBUG */
+    }
+    if(bytes_out > in_count)	/* exit(2) if no savings */
+		exit_stat = 2;
+    return;
+}
+
+/*****************************************************************
+ * TAG( output )
+ *
+ * Output the given code.
+ * Inputs:
+ * 	code:	A n_bits-bit integer.  If == -1, then EOF.  This assumes
+ *		that n_bits =< (long)wordsize - 1.
+ * Outputs:
+ * 	Outputs code to the file.
+ * Assumptions:
+ *	Chars are 8 bits long.
+ * Algorithm:
+ * 	Maintain a BITS character long buffer (so that 8 codes will
+ * fit in it exactly).  Use the VAX insv instruction to insert each
+ * code in turn.  When the buffer fills up empty it and start over.
+ */
+
+static char buf[BITS];
+
+#ifndef vax
+char_type lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
+char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+#endif /* vax */
+void output( code )
+code_int  code;
+{
+#ifdef DEBUG
+    static int col = 0;
+#endif /* DEBUG */
+
+    /*
+     * On the VAX, it is important to have the REGISTER declarations
+     * in exactly the order given, or the asm will break.
+     */
+    REGISTER int r_off = offset, bits= n_bits;
+    REGISTER char * bp = buf;
+#ifndef BREAKHIGHC
+#ifdef METAWARE
+	int temp;
+#endif
+#endif
+#ifdef DEBUG
+	if ( verbose )
+	    fprintf( stderr, "%5d%c", code,
+		    (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
+#endif /* DEBUG */
+    if ( code >= 0 ) 
+	{
+#ifdef vax
+	/* VAX DEPENDENT!! Implementation on other machines is below.
+	 *
+	 * Translation: Insert BITS bits from the argument starting at
+	 * offset bits from the beginning of buf.
+	 */
+	0;	/* Work around for pcc -O bug with asm and if stmt */
+	asm( "insv	4(ap),r11,r10,(r9)" );
+#else /* not a vax */
+/* 
+ * byte/bit numbering on the VAX is simulated by the following code
+ */
+	/*
+	 * Get to the first byte.
+	 */
+	bp += (r_off >> 3);
+	r_off &= 7;
+	/*
+	 * Since code is always >= 8 bits, only need to mask the first
+	 * hunk on the left.
+	 */
+#ifndef BREAKHIGHC
+#ifdef METAWARE
+	*bp &= rmask[r_off];
+	temp = (code << r_off) & lmask[r_off];
+	*bp |= temp;
+#else
+	*bp = (*bp & rmask[r_off]) | ((code << r_off) & lmask[r_off]);
+#endif
+#else
+	*bp = (*bp & rmask[r_off]) | ((code << r_off) & lmask[r_off]);
+#endif
+	bp++;
+	bits -= (8 - r_off);
+	code >>= (8 - r_off);
+	/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
+	if ( bits >= 8 ) 
+	{
+	    *bp++ = code;
+	    code >>= 8;
+	    bits -= 8;
+	}
+	/* Last bits. */
+	if(bits)
+	    *bp = code;
+#endif /* vax */
+	offset += n_bits;
+	if ( offset == (n_bits << 3) ) 
+	{
+	    bp = buf;
+	    bits = n_bits;
+	    bytes_out += bits;
+	    do
+		putc(*bp++,stdout);
+	    while(--bits);
+	    offset = 0;
+	}
+
+	/*
+	 * If the next entry is going to be too big for the code size,
+	 * then increase it, if possible.
+	 */
+	if ( free_ent > maxcode || (clear_flg > 0))
+	{
+	    /*
+	     * Write the whole buffer, because the input side won't
+	     * discover the size increase until after it has read it.
+	     */
+	    if ( offset > 0 ) 
+		{
+			if( fwrite( buf, (size_t)1, (size_t)n_bits, stdout ) != n_bits)
+				writeerr();
+			bytes_out += n_bits;
+	    }
+	    offset = 0;
+
+	    if ( clear_flg ) 
+		{
+    	        maxcode = MAXCODE (n_bits = INIT_BITS);
+		        clear_flg = 0;
+	    }
+	    else 
+		{
+	    	n_bits++;
+	    	if ( n_bits == maxbits )
+			    maxcode = maxmaxcode;
+	    	else
+			    maxcode = MAXCODE(n_bits);
+	    }
+#ifdef DEBUG
+	    if ( debug ) 
+		{
+			fprintf( stderr, "\nChange to %d bits\n", n_bits );
+			col = 0;
+	    }
+#endif /* DEBUG */
+	}
+    } else 
+	{
+	/*
+	 * At EOF, write the rest of the buffer.
+	 */
+	if ( offset > 0 )
+	    fwrite( buf, (size_t)1, (size_t)(offset + 7) / 8, stdout );
+	bytes_out += (offset + 7) / 8;
+	offset = 0;
+	fflush( stdout );
+#ifdef DEBUG
+	if ( verbose )
+	    fprintf( stderr, "\n" );
+#endif /* DEBUG */
+	if( ferror( stdout ) )
+		writeerr();
+    }
+}
+/*
+ * Decompress stdin to stdout.  This routine adapts to the codes in the
+ * file building the "string" table on-the-fly; requiring no table to
+ * be stored in the compressed file.  The tables used herein are shared
+ * with those of the compress() routine.  See the definitions above.
+ */
+
+void decompress() {
+    REGISTER char_type *stackp;
+    REGISTER int finchar;
+    REGISTER code_int code, oldcode, incode;
+
+    /*
+     * As above, initialize the first 256 entries in the table.
+     */
+    maxcode = MAXCODE(n_bits = INIT_BITS);
+    for ( code = 255; code >= 0; code-- ) {
+	tab_prefixof(code) = 0;
+	tab_suffixof(code) = (char_type)code;
+    }
+    free_ent = ((block_compress) ? FIRST : 256 );
+
+    finchar = oldcode = getcode();
+    if(oldcode == -1)	/* EOF already? */
+	return;			/* Get out of here */
+    putc( (char)finchar,stdout );		/* first code must be 8 bits = char */
+    if(ferror(stdout))		/* Crash if can't write */
+	writeerr();
+    stackp = de_stack;
+
+    while ( (code = getcode()) > -1 ) {
+
+	if ( (code == CLEAR) && block_compress ) {
+	    for ( code = 255; code >= 0; code-- )
+		tab_prefixof(code) = 0;
+	    clear_flg = 1;
+	    free_ent = FIRST - 1;
+	    if ( (code = getcode ()) == -1 )	/* O, untimely death! */
+		break;
+	}
+	incode = code;
+	/*
+	 * Special case for KwKwK string.
+	 */
+	if ( code >= free_ent ) {
+            *stackp++ = finchar;
+	    code = oldcode;
+	}
+
+	/*
+	 * Generate output characters in reverse order
+	 */
+#ifdef SIGNED_COMPARE_SLOW
+	while ( ((unsigned long)code) >= ((unsigned long)256) ) {
+#else
+	while ( code >= 256 ) {
+#endif
+	    *stackp++ = tab_suffixof(code);
+	    code = tab_prefixof(code);
+	}
+	*stackp++ = finchar = tab_suffixof(code);
+
+	/*
+	 * And put them out in forward order
+	 */
+	do
+	    putc ( *--stackp ,stdout);
+	while ( stackp > de_stack );
+
+	/*
+	 * Generate the new entry.
+	 */
+	if ( (code=free_ent) < maxmaxcode ) 
+	{
+	    tab_prefixof(code) = (unsigned short)oldcode;
+	    tab_suffixof(code) = finchar;
+	    free_ent = code+1;
+	} 
+	/*
+	 * Remember previous code.
+	 */
+	oldcode = incode;
+    }
+    fflush( stdout );
+    if(ferror(stdout))
+	writeerr();
+}
+
+/*****************************************************************
+ * TAG( getcode )
+ *
+ * Read one code from the standard input.  If EOF, return -1.
+ * Inputs:
+ * 	stdin
+ * Outputs:
+ * 	code or -1 is returned.
+ */
+
+code_int
+getcode() 
+{
+    /*
+     * On the VAX, it is important to have the REGISTER declarations
+     * in exactly the order given, or the asm will break.
+     */
+    REGISTER code_int code;
+    static int offset = 0, size = 0;
+    static char_type buf[BITS];
+    REGISTER int r_off, bits;
+    REGISTER char_type *bp = buf;
+
+    if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) 
+	{
+		/*
+		 * If the next entry will be too big for the current code
+		 * size, then we must increase the size.  This implies reading
+		 * a new buffer full, too.
+		 */
+		if ( free_ent > maxcode ) 
+		{
+		    n_bits++;
+		    if ( n_bits == maxbits )
+				maxcode = maxmaxcode;	/* won't get any bigger now */
+		    else
+				maxcode = MAXCODE(n_bits);
+		}
+		if ( clear_flg > 0) 
+		{
+    	    maxcode = MAXCODE (n_bits = INIT_BITS);
+		    clear_flg = 0;
+		}
+		size = fread( buf, (size_t)1, (size_t)n_bits, stdin );
+		if ( size <= 0 )
+		    return -1;			/* end of file */
+		offset = 0;
+		/* Round size down to integral number of codes */
+		size = (size << 3) - (n_bits - 1);
+    }
+    r_off = offset;
+    bits = n_bits;
+#ifdef vax
+    asm( "extzv   r10,r9,(r8),r11" );
+#else /* not a vax */
+	/*
+	 * Get to the first byte.
+	 */
+	bp += (r_off >> 3);
+	r_off &= 7;
+	/* Get first part (low order bits) */
+#ifdef NO_UCHAR
+	code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
+#else
+	code = (*bp++ >> r_off);
+#endif /* NO_UCHAR */
+	bits -= (8 - r_off);
+	r_off = 8 - r_off;		/* now, offset into code word */
+	/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
+	if ( bits >= 8 ) 
+	{
+#ifdef NO_UCHAR
+	    code |= (*bp++ & 0xff) << r_off;
+#else
+	    code |= *bp++ << r_off;
+#endif /* NO_UCHAR */
+	    r_off += 8;
+	    bits -= 8;
+	}
+	/* high order bits. */
+	code |= (*bp & rmask[bits]) << r_off;
+#endif /* vax */
+    offset += n_bits;
+
+    return code;
+}
+
+#ifndef AZTEC86
+char *
+strrchr(s, c)		/* For those who don't have it in libc.a */
+REGISTER char *s, c;
+{
+	char *p;
+	for (p = NULL; *s; s++)
+	    if (*s == c)
+		p = s;
+	return(p);
+}
+#endif
+
+
+#ifndef METAWARE
+#ifdef DEBUG
+printcodes()
+{
+    /*
+     * Just print out codes from input file.  For debugging.
+     */
+    code_int code;
+    int col = 0, bits;
+
+    bits = n_bits = INIT_BITS;
+    maxcode = MAXCODE(n_bits);
+    free_ent = ((block_compress) ? FIRST : 256 );
+    while ( ( code = getcode() ) >= 0 ) {
+	if ( (code == CLEAR) && block_compress ) {
+   	    free_ent = FIRST - 1;
+   	    clear_flg = 1;
+	}
+	else if ( free_ent < maxmaxcode )
+	    free_ent++;
+	if ( bits != n_bits ) {
+	    fprintf(stderr, "\nChange to %d bits\n", n_bits );
+	    bits = n_bits;
+	    col = 0;
+	}
+	fprintf(stderr, "%5d%c", code, (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
+    }
+    putc( '\n', stderr );
+    exit( 0 );
+}
+#ifdef DEBUG2
+code_int sorttab[1<<BITS];	/* sorted pointers into htab */
+#define STACK_SIZE	500
+static char stack[STACK_SIZE];
+/* dumptab doesn't use main stack now -prevents distressing crashes */
+dump_tab()	/* dump string table */
+{
+    REGISTER int i, first;
+    REGISTER ent;
+    int stack_top = STACK_SIZE;
+    REGISTER c;
+
+    if(do_decomp == 0) {	/* compressing */
+	REGISTER int flag = 1;
+
+	for(i=0; i<hsize; i++) {	/* build sort pointers */
+		if((long)htabof(i) >= 0) {
+			sorttab[codetabof(i)] = i;
+		}
+	}
+	first = block_compress ? FIRST : 256;
+	for(i = first; i < free_ent; i++) {
+		fprintf(stderr, "%5d: \"", i);
+		stack[--stack_top] = '\n';
+		stack[--stack_top] = '"'; /* " */
+		stack_top = in_stack((int)(htabof(sorttab[i])>>maxbits)&0xff, 
+                                     stack_top);
+		for(ent=htabof(sorttab[i]) & ((1<<maxbits)-1);
+		    ent > 256;
+		    ent=htabof(sorttab[ent]) & ((1<<maxbits)-1)) {
+			stack_top = in_stack((int)(htabof(sorttab[ent]) >> maxbits),
+						stack_top);
+		}
+		stack_top = in_stack(ent, stack_top);
+		fwrite( &stack[stack_top], (size_t)1, (size_t)(STACK_SIZE-stack_top), stderr);
+	   	stack_top = STACK_SIZE;
+	}
+   } else if(!debug) {	/* decompressing */
+
+       for ( i = 0; i < free_ent; i++ ) {
+	   ent = i;
+	   c = tab_suffixof(ent);
+	   if ( isascii(c) && isprint(c) )
+	       fprintf( stderr, "%5d: %5d/'%c'  \"",
+			   ent, tab_prefixof(ent), c );
+	   else
+	       fprintf( stderr, "%5d: %5d/\\%03o \"",
+			   ent, tab_prefixof(ent), c );
+	   stack[--stack_top] = '\n';
+	   stack[--stack_top] = '"'; /* " */
+	   for ( ; ent != NULL;
+		   ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) {
+	       stack_top = in_stack(tab_suffixof(ent), stack_top);
+	   }
+	   fwrite( &stack[stack_top], (size_t)1, (size_t)(STACK_SIZE - stack_top), stderr );
+	   stack_top = STACK_SIZE;
+       }
+    }
+}
+
+int
+in_stack(c, stack_top)
+	REGISTER int c, stack_top;
+{
+	if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) {
+	    stack[--stack_top] = c;
+	} else {
+	    switch( c ) {
+	    case '\n': stack[--stack_top] = 'n'; break;
+	    case '\t': stack[--stack_top] = 't'; break;
+	    case '\b': stack[--stack_top] = 'b'; break;
+	    case '\f': stack[--stack_top] = 'f'; break;
+	    case '\r': stack[--stack_top] = 'r'; break;
+	    case '\\': stack[--stack_top] = '\\'; break;
+	    default:
+	 	stack[--stack_top] = '0' + c % 8;
+	 	stack[--stack_top] = '0' + (c / 8) % 8;
+	 	stack[--stack_top] = '0' + c / 64;
+	 	break;
+	    }
+	    stack[--stack_top] = '\\';
+	}
+	if (stack_top<0) {
+	    fprintf(stderr,"dump_tab stack overflow!!!\n");
+	    exit(1);
+	}
+	return stack_top;
+}
+#else
+dump_tab() {}
+#endif /* DEBUG2 */
+#endif /* DEBUG */
+#endif /* METAWARE */
+
+void writeerr()
+{
+    perror ( ofname );
+    unlink ( ofname );
+    exit ( 1 );
+}
+
+void copystat(ifname, ofname)
+char *ifname, *ofname;
+{
+    struct stat statbuf;
+    int mode;
+#ifndef AZTEC86
+    time_t timep[2];
+#else
+	unsigned long timep[2];
+#endif
+    fflush(stdout);
+    close(fileno(stdout));
+    if (stat(ifname, &statbuf)) 
+	{		/* Get stat on input file */
+		perror(ifname);
+		return;
+    }
+#ifndef PCDOS
+    /* meddling with UNIX-style file modes */
+    if ((statbuf.st_mode & S_IFMT/*0170000*/) != S_IFREG/*0100000*/) 
+	{
+		if(quiet)
+	    	fprintf(stderr, "%s: ", ifname);
+		fprintf(stderr, " -- not a regular file: unchanged");
+		exit_stat = 1;
+    } else if (statbuf.st_nlink > 1) 
+	{
+		if(quiet)
+	    	fprintf(stderr, "%s: ", ifname);
+		fprintf(stderr, " -- has %d other links: unchanged",
+		statbuf.st_nlink - 1);
+		exit_stat = 1;
+    } else 
+#endif
+	if (exit_stat == 2 && (!force)) 
+	{ /* No compression: remove file.Z */
+		if(!quiet)
+			fprintf(stderr, " -- file unchanged");
+    } else 
+	{			/* ***** Successful Compression ***** */
+		exit_stat = 0;
+#ifndef PCDOS
+		mode = statbuf.st_mode & 07777;
+#else
+		mode = statbuf.st_attr & 07777;
+#endif
+		if (chmod(ofname, mode))		/* Copy modes */
+		    perror(ofname);
+#ifndef PCDOS
+		chown(ofname, statbuf.st_uid, statbuf.st_gid);	/* Copy ownership */
+		timep[0] = statbuf.st_atime;
+		timep[1] = statbuf.st_mtime;
+#else
+		timep[0] = statbuf.st_mtime;
+		timep[1] = statbuf.st_mtime;
+#endif
+		utime(ofname, (struct utimbuf *)timep);	/* Update last accessed and modified times */
+/*
+		if (unlink(ifname))
+		    perror(ifname);
+*/
+		if(!quiet)
+		    if(do_decomp == 0)
+			fprintf(stderr, " -- compressed to %s", ofname);
+		    else
+			fprintf(stderr, " -- decompressed to %s", ofname);
+		return;		/* Successful return */
+    }
+
+    /* Unsuccessful return -- one of the tests failed */
+    if (unlink(ofname))
+		perror(ofname);
+}
+/*
+ * This routine returns 1 if we are running in the foreground and stderr
+ * is a tty.
+ */
+int foreground()
+{
+#ifndef METAWARE
+	if(bgnd_flag) {	/* background? */
+		return(0);
+	} else {			/* foreground */
+#endif
+		if(isatty(2)) {		/* and stderr is a tty */
+			return(1);
+		} else {
+			return(0);
+		}
+#ifndef METAWARE
+	}
+#endif
+}
+#ifndef METAWARE
+void onintr (dummy)
+int dummy; /* to keep the compiler happy */
+{
+	(void)signal(SIGINT,SIG_IGN);
+    unlink ( ofname );
+    exit ( 1 );
+}
+
+void oops (dummy)	/* wild pointer -- assume bad input */
+int dummy; /* to keep the compiler happy */
+{
+	(void)signal(SIGSEGV,SIG_IGN);
+    if ( do_decomp == 1 ) 
+    	fprintf ( stderr, "uncompress: corrupt input\n" );
+    unlink ( ofname );
+    exit ( 1 );
+}
+#endif
+void cl_block ()		/* table clear for block compress */
+{
+    REGISTER long int rat;
+
+    checkpoint = in_count + CHECK_GAP;
+#ifdef DEBUG
+	if ( debug ) {
+    		fprintf ( stderr, "count: %ld, ratio: ", in_count );
+     		prratio ( stderr, in_count, bytes_out );
+		fprintf ( stderr, "\n");
+	}
+#endif /* DEBUG */
+
+    if(in_count > 0x007fffff) {	/* shift will overflow */
+	rat = bytes_out >> 8;
+	if(rat == 0) {		/* Don't divide by zero */
+	    rat = 0x7fffffff;
+	} else {
+	    rat = in_count / rat;
+	}
+    } else {
+	rat = (in_count << 8) / bytes_out;	/* 8 fractional bits */
+    }
+    if ( rat > ratio ) {
+	ratio = rat;
+    } else {
+	ratio = 0;
+#ifdef DEBUG
+	if(verbose)
+		dump_tab();	/* dump string table */
+#endif
+ 	cl_hash ( (count_int) hsize );
+	free_ent = FIRST;
+	clear_flg = 1;
+	output ( (code_int) CLEAR );
+#ifdef DEBUG
+	if(debug)
+    		fprintf ( stderr, "clear\n" );
+#endif /* DEBUG */
+    }
+}
+
+void cl_hash(hsize)		/* reset code table */
+	REGISTER count_int hsize;
+{
+#ifdef AZTEC86
+#ifdef PCDOS
+	/* This function only in PC-DOS lib, not in MINIX lib */
+	memset(htab,-1, hsize * sizeof(count_int));
+#else
+/* MINIX and all non-PC machines do it this way */	
+#ifndef XENIX_16	/* Normal machine */
+	REGISTER count_int *htab_p = htab+hsize;
+#else
+	REGISTER j;
+	REGISTER long k = hsize;
+	REGISTER count_int *htab_p;
+#endif
+	REGISTER long i;
+	REGISTER long m1 = -1;
+
+#ifdef XENIX_16
+    for(j=0; j<=8 && k>=0; j++,k-=8192) 
+	{
+		i = 8192;
+		if(k < 8192) 
+		{
+			i = k;
+		}
+		htab_p = &(htab[j][i]);
+		i -= 16;
+		if(i > 0) 
+		{
+#else
+	i = hsize - 16;
+#endif
+	 	do 
+		{				/* might use Sys V memset(3) here */
+			*(htab_p-16) = m1;
+			*(htab_p-15) = m1;
+			*(htab_p-14) = m1;
+			*(htab_p-13) = m1;
+			*(htab_p-12) = m1;
+			*(htab_p-11) = m1;
+			*(htab_p-10) = m1;
+			*(htab_p-9) = m1;
+			*(htab_p-8) = m1;
+			*(htab_p-7) = m1;
+			*(htab_p-6) = m1;
+			*(htab_p-5) = m1;
+			*(htab_p-4) = m1;
+			*(htab_p-3) = m1;
+			*(htab_p-2) = m1;
+			*(htab_p-1) = m1;
+			htab_p -= 16;
+		} while ((i -= 16) >= 0);
+#ifdef XENIX_16
+		}
+    }
+#endif
+	for ( i += 16; i > 0; i-- )
+		*--htab_p = m1;
+#endif
+#endif
+}
+
+void prratio(stream, num, den)
+FILE *stream;
+long int num;
+long int den;
+{
+	REGISTER int q;			/* Doesn't need to be long */
+	if(num > 214748L) 
+	{		/* 2147483647/10000 */
+		q = (int)(num / (den / 10000L));
+	} else 
+	{
+		q = (int)(10000L * num / den);		/* Long calculations, though */
+	}
+	if (q < 0) 
+	{
+		putc('-', stream);
+		q = -q;
+	}
+	fprintf(stream, "%d.%02d%c", q / 100, q % 100, '%');
+}
+
+void version()
+{
+	fprintf(stderr, "compress 4.1\n");
+	fprintf(stderr, "Options: ");
+#ifdef vax
+	fprintf(stderr, "vax, ");
+#endif
+#ifdef _MINIX
+	fprintf(stderr, "MINIX, ");
+#endif
+#ifdef NO_UCHAR
+	fprintf(stderr, "NO_UCHAR, ");
+#endif
+#ifdef SIGNED_COMPARE_SLOW
+	fprintf(stderr, "SIGNED_COMPARE_SLOW, ");
+#endif
+#ifdef XENIX_16
+	fprintf(stderr, "XENIX_16, ");
+#endif
+#ifdef COMPATIBLE
+	fprintf(stderr, "COMPATIBLE, ");
+#endif
+#ifdef DEBUG
+	fprintf(stderr, "DEBUG, ");
+#endif
+#ifdef BSD4_2
+	fprintf(stderr, "BSD4_2, ");
+#endif
+	fprintf(stderr, "BITS = %d\n", BITS);
+}
+/* End of text from uok.UUCP:net.sources */
+
Index: /trunk/minix/commands/simple/cp.c
===================================================================
--- /trunk/minix/commands/simple/cp.c	(revision 9)
+++ /trunk/minix/commands/simple/cp.c	(revision 9)
@@ -0,0 +1,1380 @@
+/*	cp 1.12 - copy files				Author: Kees J. Bot
+ *	mv      - move files					20 Jul 1993
+ *	rm      - remove files
+ *	ln      - make a link
+ *	cpdir   - copy a directory tree (cp -psmr)
+ *	clone   - make a link farm (ln -fmr)
+ */
+#define nil 0
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <utime.h>
+#include <dirent.h>
+#include <errno.h>
+#ifndef DEBUG
+#define DEBUG	0
+#define NDEBUG	1
+#endif
+#include <assert.h>
+
+#include <sys/dir.h>
+
+/* Copy files in this size chunks: */
+#if __minix && !__minix_vmd
+#define CHUNK	(8192 * sizeof(char *))
+#else
+#define CHUNK	(1024 << (sizeof(int) + sizeof(char *)))
+#endif
+
+
+#ifndef CONFORMING
+#define CONFORMING	1	/* Precisely POSIX conforming. */
+#endif
+
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+
+char *prog_name;		/* Call name of this program. */
+int ex_code= 0;			/* Final exit code. */
+
+typedef enum identity { CP, MV, RM, LN, CPDIR, CLONE } identity_t;
+typedef enum action { COPY, MOVE, REMOVE, LINK } action_t;
+
+identity_t identity;		/* How did the user call me? */
+action_t action;		/* Copying, moving, or linking. */
+int pflag= 0;			/* -p/-s: Make orginal and copy the same. */
+int iflag= 0;			/* -i: Interactive overwriting/deleting. */
+int fflag= 0;			/* -f: Force. */
+int sflag= 0;			/* -s: Make a symbolic link (ln/clone). */
+int Sflag= 0;			/* -S: Make a symlink if across devices. */
+int mflag= 0;			/* -m: Merge trees, no target dir trickery. */
+int rflag= 0;			/* -r/-R: Recursively copy a tree. */
+int vflag= 0;			/* -v: Verbose. */
+int xflag= 0;			/* -x: Don't traverse past mount points. */
+int xdev= 0;			/* Set when moving or linking cross-device. */
+int expand= 0;			/* Expand symlinks, ignore links. */
+int conforming= CONFORMING;	/* Sometimes standards are a pain. */
+
+int fc_mask;			/* File creation mask. */
+int uid, gid;			/* Effective uid & gid. */
+int istty;			/* Can have terminal input. */
+
+#ifndef S_ISLNK
+/* There were no symlinks in medieval times. */
+#define S_ISLNK(mode)			(0)
+#define lstat				stat
+#define symlink(path1, path2)		(errno= ENOSYS, -1)
+#define readlink(path, buf, len)	(errno= ENOSYS, -1)
+#endif
+
+void report(const char *label)
+{
+    if (action == REMOVE && fflag) return;
+    fprintf(stderr, "%s: %s: %s\n", prog_name, label, strerror(errno));
+    ex_code= 1;
+}
+
+void fatal(const char *label)
+{
+    report(label);
+    exit(1);
+}
+
+void report2(const char *src, const char *dst)
+{
+    fprintf(stderr, "%s %s %s: %s\n", prog_name, src, dst, strerror(errno));
+    ex_code= 1;
+}
+
+#if DEBUG
+size_t nchunks= 0;	/* Number of allocated cells. */
+#endif
+
+void *allocate(void *mem, size_t size)
+/* Like realloc, but with checking of the return value. */
+{
+#if DEBUG
+    if (mem == nil) nchunks++;
+#endif
+    if ((mem= mem == nil ? malloc(size) : realloc(mem, size)) == nil)
+	fatal("malloc()");
+    return mem;
+}
+
+void deallocate(void *mem)
+/* Release a chunk of memory. */
+{
+    if (mem != nil) {
+#if DEBUG
+	nchunks--;
+#endif
+	free(mem);
+    }
+}
+
+typedef struct pathname {
+    char		*path;	/* The actual pathname. */
+    size_t		idx;	/* Index for the terminating null byte. */
+    size_t		lim;	/* Actual length of the path array. */
+} pathname_t;
+
+void path_init(pathname_t *pp)
+/* Initialize a pathname to the null string. */
+{
+    pp->path= allocate(nil, pp->lim= DIRSIZ + 2);
+    pp->path[pp->idx= 0]= 0;
+}
+
+void path_add(pathname_t *pp, const char *name)
+/* Add a component to a pathname. */
+{
+    size_t lim;
+    char *p;
+
+    lim= pp->idx + strlen(name) + 2;
+
+    if (lim > pp->lim) {
+	pp->lim= lim += lim/2;	/* add an extra 50% growing space. */
+
+	pp->path= allocate(pp->path, lim);
+    }
+
+    p= pp->path + pp->idx;
+    if (p > pp->path && p[-1] != '/') *p++ = '/';
+
+    while (*name != 0) {
+	if (*name != '/' || p == pp->path || p[-1] != '/') *p++ = *name;
+	name++;
+    }
+    *p = 0;
+    pp->idx= p - pp->path;
+}
+
+void path_trunc(pathname_t *pp, size_t didx)
+/* Delete part of a pathname to a remembered length. */
+{
+    pp->path[pp->idx= didx]= 0;
+}
+
+#if DEBUG
+const char *path_name(const pathname_t *pp)
+/* Return the actual name as a C string. */
+{
+    return pp->path;
+}
+
+size_t path_length(const pathname_t *pp)
+/* The length of the pathname. */
+{
+    return pp->idx;
+}
+
+void path_drop(pathname_t *pp)
+/* Release the storage occupied by the pathname. */
+{
+    deallocate(pp->path);
+}
+
+#else /* !DEBUG */
+#define path_name(pp)		((const char *) (pp)->path)
+#define path_length(pp)		((pp)->idx)
+#define path_drop(pp)		deallocate((void *) (pp)->path)
+#endif /* !DEBUG */
+
+char *basename(const char *path)
+/* Return the last component of a pathname.  (Note: declassifies a const
+ * char * just like strchr.
+ */
+{
+    const char *p= path;
+
+    for (;;) {
+	while (*p == '/') p++;			/* Trailing slashes? */
+
+	if (*p == 0) break;
+
+	path= p;
+	while (*p != 0 && *p != '/') p++;	/* Skip component. */
+    }
+    return (char *) path;
+}
+
+int affirmative(void)
+/* Get a yes/no answer from the suspecting user. */
+{
+    int c;
+    int ok;
+
+    fflush(stdout);
+    fflush(stderr);
+
+    while ((c= getchar()) == ' ') {}
+    ok= (c == 'y' || c == 'Y');
+    while (c != EOF && c != '\n') c= getchar();
+
+    return ok;
+}
+
+int writable(const struct stat *stp)
+/* True iff the file with the given attributes allows writing.  (And we have
+ * a terminal to ask if ok to overwrite.)
+ */
+{
+    if (!istty || uid == 0) return 1;
+    if (stp->st_uid == uid) return stp->st_mode & S_IWUSR;
+    if (stp->st_gid == gid) return stp->st_mode & S_IWGRP;
+    return stp->st_mode & S_IWOTH;
+}
+
+#ifndef PATH_MAX
+#define PATH_MAX	1024
+#endif
+
+static char *link_islink(struct stat *stp, const char *file)
+{
+    /* Tell if a file, which stat(2) information in '*stp', has been seen
+     * earlier by this function under a different name.  If not return a
+     * null pointer with errno set to ENOENT, otherwise return the name of
+     * the link.  Return a null pointer with an error code in errno for any
+     * error, using E2BIG for a too long file name.
+     *
+     * Use link_islink(nil, nil) to reset all bookkeeping.
+     *
+     * Call for a file twice to delete it from the store.
+     */
+
+    typedef struct link {	/* In-memory link store. */
+	struct link	*next;		/* Hash chain on inode number. */
+	ino_t		ino;		/* File's inode number. */
+	off_t		off;		/* Offset to more info in temp file. */
+    } link_t;
+    typedef struct dlink {	/* On-disk link store. */
+	dev_t		dev;		/* Device number. */
+	char		file[PATH_MAX];	/* Name of earlier seen link. */
+    } dlink_t;
+    static link_t *links[256];		/* Hash list of known links. */
+    static int tfd= -1;			/* Temp file for file name storage. */
+    static dlink_t dlink;
+    link_t *lp, **plp;
+    size_t len;
+    off_t off;
+
+    if (file == nil) {
+	/* Reset everything. */
+	for (plp= links; plp < arraylimit(links); plp++) {
+	    while ((lp= *plp) != nil) {
+		*plp= lp->next;
+		free(lp);
+	    }
+	}
+	if (tfd != -1) close(tfd);
+	tfd= -1;
+	return nil;
+    }
+
+    /* The file must be a non-directory with more than one link. */
+    if (S_ISDIR(stp->st_mode) || stp->st_nlink <= 1) {
+	errno= ENOENT;
+	return nil;
+    }
+
+    plp= &links[stp->st_ino % arraysize(links)];
+
+    while ((lp= *plp) != nil) {
+	if (lp->ino == stp->st_ino) {
+	    /* May have seen this link before.  Get it and check. */
+	    if (lseek(tfd, lp->off, SEEK_SET) == -1) return nil;
+	    if (read(tfd, &dlink, sizeof(dlink)) < 0) return nil;
+
+	    /* Only need to check the device number. */
+	    if (dlink.dev == stp->st_dev) {
+		if (strcmp(file, dlink.file) == 0) {
+		    /* Called twice.  Forget about this link. */
+		    *plp= lp->next;
+		    free(lp);
+		    errno= ENOENT;
+		    return nil;
+		}
+
+		/* Return the name of the earlier link. */
+		return dlink.file;
+	    }
+	}
+	plp= &lp->next;
+    }
+
+    /* First time I see this link.  Add it to the store. */
+    if (tfd == -1) {
+	for (;;) {
+	    char *tmp;
+
+	    tmp= tmpnam(nil);
+	    tfd= open(tmp, O_RDWR|O_CREAT|O_EXCL, 0600);
+	    if (tfd < 0) {
+		if (errno != EEXIST) return nil;
+	    } else {
+		(void) unlink(tmp);
+		break;
+	    }
+	}
+    }
+    if ((len= strlen(file)) >= PATH_MAX) {
+	errno= E2BIG;
+	return nil;
+    }
+
+    dlink.dev= stp->st_dev;
+    strcpy(dlink.file, file);
+    len += offsetof(dlink_t, file) + 1;
+    if ((off= lseek(tfd, 0, SEEK_END)) == -1) return nil;
+    if (write(tfd, &dlink, len) != len) return nil;
+
+    if ((lp= malloc(sizeof(*lp))) == nil) return nil;
+    lp->next= nil;
+    lp->ino= stp->st_ino;
+    lp->off= off;
+    *plp= lp;
+    errno= ENOENT;
+    return nil;
+}
+
+int trylink(const char *src, const char *dst, struct stat *srcst,
+			struct stat *dstst)
+/* Keep the link structure intact if src has been seen before. */
+{
+    char *olddst;
+    int linked;
+
+    if (action == COPY && expand) return 0;
+
+    if ((olddst= link_islink(srcst, dst)) == nil) {
+	/* if (errno != ENOENT) ... */
+	return 0;
+    }
+
+    /* Try to link the file copied earlier to the new file. */
+    if (dstst->st_ino != 0) (void) unlink(dst);
+
+    if ((linked= (link(olddst, dst) == 0)) && vflag)
+	printf("ln %s ..\n", olddst);
+
+    return linked;
+}
+
+int copy(const char *src, const char *dst, struct stat *srcst,
+			struct stat *dstst)
+/* Copy one file to another and copy (some of) the attributes. */
+{
+    char buf[CHUNK];
+    int srcfd, dstfd;
+    ssize_t n;
+
+    assert(srcst->st_ino != 0);
+
+    if (dstst->st_ino == 0) {
+	/* The file doesn't exist yet. */
+
+	if (!S_ISREG(srcst->st_mode)) {
+	    /* Making a new mode 666 regular file. */
+	    srcst->st_mode= (S_IFREG | 0666) & fc_mask;
+	} else
+	if (!pflag && conforming) {
+	    /* Making a new file copying mode with umask applied. */
+	    srcst->st_mode &= fc_mask;
+	}
+    } else {
+	/* File exists, ask if ok to overwrite if '-i'. */
+
+	if (iflag || (action == MOVE && !fflag && !writable(dstst))) {
+	    fprintf(stderr, "Overwrite %s? (mode = %03o) ",
+			dst, dstst->st_mode & 07777);
+	    if (!affirmative()) return 0;
+	}
+
+	if (action == MOVE) {
+	    /* Don't overwrite, remove first. */
+	    if (unlink(dst) < 0 && errno != ENOENT) {
+		report(dst);
+		return 0;
+	    }
+	} else {
+	    /* Overwrite. */
+	    if (!pflag) {
+		/* Keep the existing mode and ownership. */
+		srcst->st_mode= dstst->st_mode;
+		srcst->st_uid= dstst->st_uid;
+		srcst->st_gid= dstst->st_gid;
+	    }
+	}
+    }
+
+    /* Keep the link structure if possible. */
+    if (trylink(src, dst, srcst, dstst)) return 1;
+
+    if ((srcfd= open(src, O_RDONLY)) < 0) {
+	report(src);
+	return 0;
+    }
+
+    dstfd= open(dst, O_WRONLY|O_CREAT|O_TRUNC, srcst->st_mode & 0777);
+    if (dstfd < 0 && fflag && errno == EACCES) {
+	/* Retry adding a "w" bit. */
+	(void) chmod(dst, dstst->st_mode | S_IWUSR);
+	dstfd= open(dst, O_WRONLY|O_CREAT|O_TRUNC, 0);
+    }
+    if (dstfd < 0 && fflag && errno == EACCES) {
+	/* Retry after trying to delete. */
+	(void) unlink(dst);
+	dstfd= open(dst, O_WRONLY|O_CREAT|O_TRUNC, 0);
+    }
+    if (dstfd < 0) {
+	report(dst);
+	close(srcfd);
+	return 0;
+    }
+
+    /* Get current parameters. */
+    if (fstat(dstfd, dstst) < 0) {
+	report(dst);
+	close(srcfd);
+	close(dstfd);
+	return 0;
+    }
+
+    /* Copy the little bytes themselves. */
+    while ((n= read(srcfd, buf, sizeof(buf))) > 0) {
+	char *bp = buf;
+	ssize_t r;
+
+	while (n > 0 && (r= write(dstfd, bp, n)) > 0) {
+	    bp += r;
+	    n -= r;
+	}
+	if (r <= 0) {
+	    if (r == 0) {
+		fprintf(stderr,
+		    "%s: Warning: EOF writing to %s\n",
+		    prog_name, dst);
+		break;
+	    }
+	    fatal(dst);
+	}
+    }
+
+    if (n < 0) {
+	report(src);
+	close(srcfd);
+	close(dstfd);
+	return 0;
+    }
+
+    close(srcfd);
+    close(dstfd);
+
+    /* Copy the ownership. */
+    if ((pflag || !conforming)
+	&& S_ISREG(dstst->st_mode)
+	&& (dstst->st_uid != srcst->st_uid
+		|| dstst->st_gid != srcst->st_gid)
+    ) {
+	if (chmod(dst, 0) == 0) dstst->st_mode&= ~07777;
+	if (chown(dst, srcst->st_uid, srcst->st_gid) < 0) {
+	    if (errno != EPERM) {
+		report(dst);
+		return 0;
+	    }
+	} else {
+	    dstst->st_uid= srcst->st_uid;
+	    dstst->st_gid= srcst->st_gid;
+	}
+    }
+
+    if (conforming && S_ISREG(dstst->st_mode)
+	&& (dstst->st_uid != srcst->st_uid
+		|| dstst->st_gid != srcst->st_gid)
+    ) {
+	/* Suid bits must be cleared in the holy name of
+	 * security (and the assumed user stupidity).
+	 */
+	srcst->st_mode&= ~06000;
+    }
+
+    /* Copy the mode. */
+    if (S_ISREG(dstst->st_mode) && dstst->st_mode != srcst->st_mode) {
+	if (chmod(dst, srcst->st_mode) < 0) {
+	    if (errno != EPERM) {
+		report(dst);
+		return 0;
+	    }
+	    fprintf(stderr, "%s: Can't change the mode of %s\n",
+		prog_name, dst);
+	}
+    }
+
+    /* Copy the file modification time. */
+    if ((pflag || !conforming) && S_ISREG(dstst->st_mode)) {
+	struct utimbuf ut;
+
+	ut.actime= action == MOVE ? srcst->st_atime : time(nil);
+	ut.modtime= srcst->st_mtime;
+	if (utime(dst, &ut) < 0) {
+	    if (errno != EPERM) {
+		report(dst);
+		return 0;
+	    }
+	    if (pflag) {
+		fprintf(stderr,
+		    "%s: Can't set the time of %s\n",
+		    prog_name, dst);
+	    }
+	}
+    }
+    if (vflag) {
+	printf(action == COPY ? "cp %s ..\n" : "mv %s ..\n", src);
+    }
+    return 1;
+}
+
+void copy1(const char *src, const char *dst, struct stat *srcst,
+			    struct stat *dstst)
+/* Inspect the source file and then copy it.  Treatment of symlinks and
+ * special files is a bit complicated.  The filetype and link-structure are
+ * ignored if (expand && !rflag), symlinks and link-structure are ignored
+ * if (expand && rflag), everything is copied precisely if !expand.
+ */
+{
+    int r, linked;
+
+    assert(srcst->st_ino != 0);
+
+    if (srcst->st_ino == dstst->st_ino && srcst->st_dev == dstst->st_dev) {
+	fprintf(stderr, "%s: can't copy %s onto itself\n",
+	    prog_name, src);
+	ex_code= 1;
+	return;
+    }
+
+    /* You can forget it if the destination is a directory. */
+    if (dstst->st_ino != 0 && S_ISDIR(dstst->st_mode)) {
+	errno= EISDIR;
+	report(dst);
+	return;
+    }
+
+    if (S_ISREG(srcst->st_mode) || (expand && !rflag)) {
+	if (!copy(src, dst, srcst, dstst)) return;
+
+	if (action == MOVE && unlink(src) < 0) {
+	    report(src);
+	    return;
+	}
+	return;
+    }
+
+    if (dstst->st_ino != 0) {
+	if (iflag || (action == MOVE && !fflag && !writable(dstst))) {
+	    fprintf(stderr, "Replace %s? (mode = %03o) ",
+		dst, dstst->st_mode & 07777);
+	    if (!affirmative()) return;
+	}
+	if (unlink(dst) < 0) {
+	    report(dst);
+	    return;
+	}
+	dstst->st_ino= 0;
+    }
+
+    /* Apply the file creation mask if so required. */
+    if (!pflag && conforming) srcst->st_mode &= fc_mask;
+
+    linked= 0;
+
+    if (S_ISLNK(srcst->st_mode)) {
+	char buf[1024+1];
+
+	if ((r= readlink(src, buf, sizeof(buf)-1)) < 0) {
+	    report(src);
+	    return;
+	}
+	buf[r]= 0;
+	r= symlink(buf, dst);
+	if (vflag && r == 0)
+	    printf("ln -s %s %s\n", buf, dst);
+    } else
+    if (trylink(src, dst, srcst, dstst)) {
+	linked= 1;
+	r= 0;
+    } else
+    if (S_ISFIFO(srcst->st_mode)) {
+	r= mkfifo(dst, srcst->st_mode);
+	if (vflag && r == 0)
+	    printf("mkfifo %s\n", dst);
+    } else
+    if (S_ISBLK(srcst->st_mode) || S_ISCHR(srcst->st_mode)) {
+	r= mknod(dst, srcst->st_mode, srcst->st_rdev);
+	if (vflag && r == 0) {
+	    printf("mknod %s %c %d %d\n",
+		dst,
+		S_ISBLK(srcst->st_mode) ? 'b' : 'c',
+		(srcst->st_rdev >> 8) & 0xFF,
+		(srcst->st_rdev >> 0) & 0xFF);
+	}
+    } else {
+	fprintf(stderr, "%s: %s: odd filetype %5o (not copied)\n",
+	    prog_name, src, srcst->st_mode);
+	ex_code= 1;
+	return;
+    }
+
+    if (r < 0 || lstat(dst, dstst) < 0) {
+	report(dst);
+	return;
+    }
+
+    if (action == MOVE && unlink(src) < 0) {
+	report(src);
+	(void) unlink(dst);	/* Don't want it twice. */
+	return;
+    }
+
+    if (linked) return;
+
+    if (S_ISLNK(srcst->st_mode)) return;
+
+    /* Copy the ownership. */
+    if ((pflag || !conforming)
+	&& (dstst->st_uid != srcst->st_uid
+		|| dstst->st_gid != srcst->st_gid)
+    ) {
+	if (chown(dst, srcst->st_uid, srcst->st_gid) < 0) {
+	    if (errno != EPERM) {
+		report(dst);
+		return;
+	    }
+	}
+    }
+
+    /* Copy the file modification time. */
+    if (pflag || !conforming) {
+	struct utimbuf ut;
+
+	ut.actime= action == MOVE ? srcst->st_atime : time(nil);
+	ut.modtime= srcst->st_mtime;
+	if (utime(dst, &ut) < 0) {
+	    if (errno != EPERM) {
+		report(dst);
+		return;
+	    }
+	    fprintf(stderr, "%s: Can't set the time of %s\n",
+		prog_name, dst);
+	}
+    }
+}
+
+void remove1(const char *src, struct stat *srcst)
+{
+    if (iflag || (!fflag && !writable(srcst))) {
+	fprintf(stderr, "Remove %s? (mode = %03o) ", src,
+			srcst->st_mode & 07777);
+	if (!affirmative()) return;
+    }
+    if (unlink(src) < 0) {
+	report(src);
+    } else {
+	if (vflag) printf("rm %s\n", src);
+    }
+}
+
+void link1(const char *src, const char *dst, struct stat *srcst,
+			    struct stat *dstst)
+{
+    pathname_t sym;
+    const char *p;
+
+    if (dstst->st_ino != 0 && (iflag || fflag)) {
+	if (srcst->st_ino == dstst->st_ino) {
+	    if (fflag) return;
+	    fprintf(stderr, "%s: Can't link %s onto itself\n",
+		prog_name, src);
+	    ex_code= 1;
+	    return;
+	}
+	if (iflag) {
+	    fprintf(stderr, "Remove %s? ", dst);
+	    if (!affirmative()) return;
+	}
+	errno= EISDIR;
+	if (S_ISDIR(dstst->st_mode) || unlink(dst) < 0) {
+	    report(dst);
+	    return;
+	}
+    }
+
+    if (!sflag && !(rflag && S_ISLNK(srcst->st_mode)) && !(Sflag && xdev)) {
+	/* A normal link. */
+	if (link(src, dst) < 0) {
+	    if (!Sflag || errno != EXDEV) {
+		report2(src, dst);
+		return;
+	    }
+	    /* Can't do a cross-device link, we have to symlink. */
+	    xdev= 1;
+	} else {
+	    if (vflag) printf("ln %s..\n", src);
+	    return;
+	}
+    }
+
+    /* Do a symlink. */
+    if (!rflag && !Sflag) {
+	/* We can get away with a "don't care if it works" symlink. */
+	if (symlink(src, dst) < 0) {
+	    report(dst);
+	    return;
+	}
+	if (vflag) printf("ln -s %s %s\n", src, dst);
+	return;
+    }
+
+    /* If the source is a symlink then it is simply copied. */
+    if (S_ISLNK(srcst->st_mode)) {
+	int r;
+	char buf[1024+1];
+
+	if ((r= readlink(src, buf, sizeof(buf)-1)) < 0) {
+	    report(src);
+	    return;
+	}
+	buf[r]= 0;
+	if (symlink(buf, dst) < 0) {
+	    report(dst);
+	    return;
+	}
+	if (vflag) printf("ln -s %s %s\n", buf, dst);
+	return;
+    }
+
+    /* Make a symlink that has to work, i.e. we must be able to access the
+     * source now, and the link must work.
+     */
+    if (dst[0] == '/' && src[0] != '/') {
+	/* ln -[rsS] relative/path /full/path. */
+	fprintf(stderr,
+	    "%s: Symlinking %s to %s is too difficult for me to figure out\n",
+	    prog_name, src, dst);
+	exit(1);
+    }
+
+    /* Count the number of subdirectories in the destination file and
+     * add one '..' for each.
+     */
+    path_init(&sym);
+    if (src[0] != '/') {
+	p= dst;
+	while (*p != 0) {
+	    if (p[0] == '.') {
+		if (p[1] == '/' || p[1] == 0) {
+		    /* A "." component; skip. */
+		    do p++; while (*p == '/');
+		    continue;
+		} else
+		if (p[1] == '.' && (p[2] == '/' || p[2] == 0)) {
+		    /* A ".." component; oops. */
+		    switch (path_length(&sym)) {
+		    case 0:
+			fprintf(stderr,
+	    "%s: Symlinking %s to %s is too difficult for me to figure out\n",
+			    prog_name, src, dst);
+			exit(1);
+		    case 2:
+			path_trunc(&sym, 0);
+			break;
+		    default:
+			path_trunc(&sym, path_length(&sym) - 3);
+		    }
+		    p++;
+		    do p++; while (*p == '/');
+		    continue;
+		}
+	    }
+	    while (*p != 0 && *p != '/') p++;
+	    while (*p == '/') p++;
+	    if (*p == 0) break;
+	    path_add(&sym, "..");
+	}
+    }
+    path_add(&sym, src);
+
+    if (symlink(path_name(&sym), dst) < 0) {
+	report(dst);
+    } else {
+	if (vflag) printf("ln -s %s %s\n", path_name(&sym), dst);
+    }
+    path_drop(&sym);
+}
+
+typedef struct entrylist {
+    struct entrylist	*next;
+    char			*name;
+} entrylist_t;
+
+int eat_dir(const char *dir, entrylist_t **dlist)
+/* Make a linked list of all the names in a directory. */
+{
+    DIR *dp;
+    struct dirent *entry;
+
+    if ((dp= opendir(dir)) == nil) return 0;
+
+    while ((entry= readdir(dp)) != nil) {
+	if (strcmp(entry->d_name, ".") == 0) continue;
+	if (strcmp(entry->d_name, "..") == 0) continue;
+
+	*dlist= allocate(nil, sizeof(**dlist));
+	(*dlist)->name= allocate(nil, strlen(entry->d_name)+1);
+	strcpy((*dlist)->name, entry->d_name);
+	dlist= &(*dlist)->next;
+    }
+    closedir(dp);
+    *dlist= nil;
+    return 1;
+}
+
+void chop_dlist(entrylist_t **dlist)
+/* Chop an entry of a name list. */
+{
+    entrylist_t *junk= *dlist;
+
+    *dlist= junk->next;
+    deallocate(junk->name);
+    deallocate(junk);
+}
+
+void drop_dlist(entrylist_t *dlist)
+/* Get rid of a whole list. */
+{
+    while (dlist != nil) chop_dlist(&dlist);
+}
+
+void do1(pathname_t *src, pathname_t *dst, int depth)
+/* Perform the appropriate action on a source and destination file. */
+{
+    size_t slashsrc, slashdst;
+    struct stat srcst, dstst;
+    entrylist_t *dlist;
+    static ino_t topdst_ino;
+    static dev_t topdst_dev;
+    static dev_t topsrc_dev;
+
+#if DEBUG
+    if (vflag && depth == 0) {
+	char flags[100], *pf= flags;
+
+	if (pflag) *pf++= 'p';
+	if (iflag) *pf++= 'i';
+	if (fflag) *pf++= 'f';
+	if (sflag) *pf++= 's';
+	if (Sflag) *pf++= 'S';
+	if (mflag) *pf++= 'm';
+	if (rflag) *pf++= 'r';
+	if (vflag) *pf++= 'v';
+	if (xflag) *pf++= 'x';
+	if (expand) *pf++= 'L';
+	if (conforming) *pf++= 'C';
+	*pf= 0;
+	printf(": %s -%s %s %s\n", prog_name, flags,
+		    path_name(src), path_name(dst));
+    }
+#endif
+
+    /* st_ino == 0 if not stat()'ed yet, or nonexistent. */
+    srcst.st_ino= 0;
+    dstst.st_ino= 0;
+
+    if (action != LINK || !sflag || rflag) {
+	/* Source must exist unless symlinking. */
+	if ((expand ? stat : lstat)(path_name(src), &srcst) < 0) {
+	    report(path_name(src));
+	    return;
+	}
+    }
+
+    if (depth == 0) {
+	/* First call: Not cross-device yet, first dst not seen yet,
+	 * remember top device number.
+	 */
+	xdev= 0;
+	topdst_ino= 0;
+	topsrc_dev= srcst.st_dev;
+    }
+
+    /* Inspect the intended destination unless removing. */
+    if (action != REMOVE) {
+	if ((expand ? stat : lstat)(path_name(dst), &dstst) < 0) {
+	    if (errno != ENOENT) {
+		report(path_name(dst));
+		return;
+	    }
+	}
+    }
+
+    if (action == MOVE && !xdev) {
+	if (dstst.st_ino != 0 && srcst.st_dev != dstst.st_dev) {
+	    /* It's a cross-device rename, i.e. copy and remove. */
+	    xdev= 1;
+	} else
+	if (!mflag || dstst.st_ino == 0 || !S_ISDIR(dstst.st_mode)) {
+	    /* Try to simply rename the file (not merging trees). */
+
+	    if (srcst.st_ino == dstst.st_ino) {
+		fprintf(stderr,
+		    "%s: Can't move %s onto itself\n",
+		    prog_name, path_name(src));
+		ex_code= 1;
+		return;
+	    }
+
+	    if (dstst.st_ino != 0) {
+		if (iflag || (!fflag && !writable(&dstst))) {
+		    fprintf(stderr,
+			"Replace %s? (mode = %03o) ",
+			path_name(dst),
+			dstst.st_mode & 07777);
+		    if (!affirmative()) return;
+		}
+		if (!S_ISDIR(dstst.st_mode))
+		    (void) unlink(path_name(dst));
+	    }
+
+	    if (rename(path_name(src), path_name(dst)) == 0) {
+		/* Success. */
+		if (vflag) {
+		    printf("mv %s %s\n", path_name(src),
+			    path_name(dst));
+		}
+		return;
+	    }
+	    if (errno == EXDEV) {
+		xdev= 1;
+	    } else {
+		report2(path_name(src), path_name(dst));
+		return;
+	    }
+	}
+    }
+
+    if (srcst.st_ino == 0 || !S_ISDIR(srcst.st_mode)) {
+	/* Copy/move/remove/link a single file. */
+	switch (action) {
+	case COPY:
+	case MOVE:
+	    copy1(path_name(src), path_name(dst), &srcst, &dstst);
+	    break;
+	case REMOVE:
+	    remove1(path_name(src), &srcst);
+	    break;
+	case LINK:
+	    link1(path_name(src), path_name(dst), &srcst, &dstst);
+	    break;
+	}
+	return;
+    }
+
+    /* Recursively copy/move/remove/link a directory if -r or -R. */
+    if (!rflag) {
+	errno= EISDIR;
+	report(path_name(src));
+	return;
+    }
+
+    /* Ok to remove contents of dir? */
+    if (action == REMOVE) {
+	if (xflag && topsrc_dev != srcst.st_dev) {
+	    /* Don't recurse past a mount point. */
+	    return;
+	}
+	if (iflag) {
+	    fprintf(stderr, "Remove contents of %s? ", path_name(src));
+	    if (!affirmative()) return;
+	}
+    }
+
+    /* Gather the names in the source directory. */
+    if (!eat_dir(path_name(src), &dlist)) {
+	report(path_name(src));
+	return;
+    }
+
+    /* Check/create the target directory. */
+    if (action != REMOVE && dstst.st_ino != 0 && !S_ISDIR(dstst.st_mode)) {
+	if (action != MOVE && !fflag) {
+	    errno= ENOTDIR;
+	    report(path_name(dst));
+	    return;
+	}
+	if (iflag) {
+	    fprintf(stderr, "Replace %s? ", path_name(dst));
+	    if (!affirmative()) {
+		drop_dlist(dlist);
+		return;
+	    }
+	}
+	if (unlink(path_name(dst)) < 0) {
+	    report(path_name(dst));
+	    drop_dlist(dlist);
+	    return;
+	}
+	dstst.st_ino= 0;
+    }
+
+    if (action != REMOVE) {
+	if (dstst.st_ino == 0) {
+	    /* Create a new target directory. */
+	    if (!pflag && conforming) srcst.st_mode&= fc_mask;
+
+	    if (mkdir(path_name(dst), srcst.st_mode | S_IRWXU) < 0
+		    || stat(path_name(dst), &dstst) < 0) {
+		report(path_name(dst));
+		drop_dlist(dlist);
+		return;
+	    }
+	    if (vflag) printf("mkdir %s\n", path_name(dst));
+	} else {
+	    /* Target directory already exists. */
+	    if (action == MOVE && !mflag) {
+		errno= EEXIST;
+		report(path_name(dst));
+		drop_dlist(dlist);
+		return;
+	    }
+	    if (!pflag) {
+		/* Keep the existing attributes. */
+		srcst.st_mode= dstst.st_mode;
+		srcst.st_uid= dstst.st_uid;
+		srcst.st_gid= dstst.st_gid;
+		srcst.st_mtime= dstst.st_mtime;
+	    }
+	}
+
+	if (topdst_ino == 0) {
+	    /* Remember the top destination. */
+	    topdst_dev= dstst.st_dev;
+	    topdst_ino= dstst.st_ino;
+	}
+
+	if (srcst.st_ino == topdst_ino && srcst.st_dev == topdst_dev) {
+	    /* E.g. cp -r /shallow /shallow/deep. */
+	    fprintf(stderr,
+		"%s%s %s/ %s/: infinite recursion avoided\n",
+		prog_name, action != MOVE ? " -r" : "",
+		path_name(src), path_name(dst));
+	    drop_dlist(dlist);
+	    return;
+	}
+
+	if (xflag && topsrc_dev != srcst.st_dev) {
+	    /* Don't recurse past a mount point. */
+	    drop_dlist(dlist);
+	    return;
+	}
+    }
+
+    /* Go down. */
+    slashsrc= path_length(src);
+    slashdst= path_length(dst);
+
+    while (dlist != nil) {
+	path_add(src, dlist->name);
+	if (action != REMOVE) path_add(dst, dlist->name);
+
+	do1(src, dst, depth+1);
+
+	path_trunc(src, slashsrc);
+	path_trunc(dst, slashdst);
+	chop_dlist(&dlist);
+    }
+
+    if (action == MOVE || action == REMOVE) {
+	/* The contents of the source directory should have
+	 * been (re)moved above.  Get rid of the empty dir.
+	 */
+	if (action == REMOVE && iflag) {
+	    fprintf(stderr, "Remove directory %s? ",
+			    path_name(src));
+	    if (!affirmative()) return;
+	}
+	if (rmdir(path_name(src)) < 0) {
+	    if (errno != ENOTEMPTY) report(path_name(src));
+	    return;
+	}
+	if (vflag) printf("rmdir %s\n", path_name(src));
+    }
+
+    if (action != REMOVE) {
+	/* Set the attributes of a new directory. */
+	struct utimbuf ut;
+
+	/* Copy the ownership. */
+	if ((pflag || !conforming)
+	    && (dstst.st_uid != srcst.st_uid
+		|| dstst.st_gid != srcst.st_gid)
+	) {
+	    if (chown(path_name(dst), srcst.st_uid,
+			    srcst.st_gid) < 0) {
+		if (errno != EPERM) {
+		    report(path_name(dst));
+		    return;
+		}
+	    }
+	}
+
+	/* Copy the mode. */
+	if (dstst.st_mode != srcst.st_mode) {
+	    if (chmod(path_name(dst), srcst.st_mode) < 0) {
+		report(path_name(dst));
+		return;
+	    }
+	}
+
+	/* Copy the file modification time. */
+	if (dstst.st_mtime != srcst.st_mtime) {
+	    ut.actime= action == MOVE ? srcst.st_atime : time(nil);
+	    ut.modtime= srcst.st_mtime;
+	    if (utime(path_name(dst), &ut) < 0) {
+		if (errno != EPERM) {
+		    report(path_name(dst));
+		    return;
+		}
+		fprintf(stderr,
+		    "%s: Can't set the time of %s\n",
+		    prog_name, path_name(dst));
+	    }
+	}
+    }
+}
+
+void usage(void)
+{
+    char *flags1, *flags2;
+
+    switch (identity) {
+    case CP:
+	flags1= "pifsmrRvx";
+	flags2= "pifsrRvx";
+	break;
+    case MV:
+	flags1= "ifsmvx";
+	flags2= "ifsvx";
+	break;
+    case RM:
+	fprintf(stderr, "Usage: rm [-ifrRvx] file ...\n");
+	exit(1);
+    case LN:
+	flags1= "ifsSmrRvx";
+	flags2= "ifsSrRvx";
+	break;
+    case CPDIR:
+	flags1= "ifvx";
+	flags2= nil;
+	break;
+    case CLONE:
+	flags1= "ifsSvx";
+	flags2= nil;
+	break;
+    }
+    fprintf(stderr, "Usage: %s [-%s] file1 file2\n", prog_name, flags1);
+  if (flags2 != nil)
+    fprintf(stderr, "       %s [-%s] file ... dir\n", prog_name, flags2);
+    exit(1);
+}
+
+void main(int argc, char **argv)
+{
+    int i;
+    char *flags;
+    struct stat st;
+    pathname_t src, dst;
+    size_t slash;
+
+#if DEBUG >= 3
+    /* The first argument is the call name while debugging. */
+    if (argc < 2) exit(-1);
+    argv++;
+    argc--;
+#endif
+#if DEBUG
+    vflag= isatty(1);
+#endif
+
+    /* Call name of this program. */
+    prog_name= basename(argv[0]);
+
+    /* Required action. */
+    if (strcmp(prog_name, "cp") == 0) {
+	identity= CP;
+	action= COPY;
+	flags= "pifsmrRvx";
+	expand= 1;
+    } else
+    if (strcmp(prog_name, "mv") == 0) {
+	identity= MV;
+	action= MOVE;
+	flags= "ifsmvx";
+	rflag= pflag= 1;
+    } else
+    if (strcmp(prog_name, "rm") == 0) {
+	identity= RM;
+	action= REMOVE;
+	flags= "ifrRvx";
+    } else
+    if (strcmp(prog_name, "ln") == 0) {
+	identity= LN;
+	action= LINK;
+	flags= "ifsSmrRvx";
+    } else
+    if (strcmp(prog_name, "cpdir") == 0) {
+	identity= CPDIR;
+	action= COPY;
+	flags= "pifsmrRvx";
+	rflag= mflag= pflag= 1;
+	conforming= 0;
+    } else
+    if (strcmp(prog_name, "clone") == 0) {
+	identity= CLONE;
+	action= LINK;
+	flags= "ifsSmrRvx";
+	rflag= mflag= fflag= 1;
+    } else {
+	fprintf(stderr,
+	    "%s: Identity crisis, not called cp, mv, rm, ln, cpdir, or clone\n",
+	    prog_name);
+	exit(1);
+    }
+
+    /* Who am I?, where am I?, how protective am I? */
+    uid= geteuid();
+    gid= getegid();
+    istty= isatty(0);
+    fc_mask= ~umask(0);
+
+    /* Gather flags. */
+    i= 1;
+    while (i < argc && argv[i][0] == '-') {
+	char *opt= argv[i++] + 1;
+
+	if (opt[0] == '-' && opt[1] == 0) break;	/* -- */
+
+	while (*opt != 0) {
+	    /* Flag supported? */
+	    if (strchr(flags, *opt) == nil) usage();
+
+	    switch (*opt++) {
+	    case 'p':
+		pflag= 1;
+		break;
+	    case 'i':
+		iflag= 1;
+		if (action == MOVE) fflag= 0;
+		break;
+	    case 'f':
+		fflag= 1;
+		if (action == MOVE) iflag= 0;
+		break;
+	    case 's':
+		if (action == LINK) {
+		    sflag= 1;
+		} else {
+		    /* Forget about POSIX, do it right. */
+		    conforming= 0;
+		}
+		break;
+	    case 'S':
+		Sflag= 1;
+		break;
+	    case 'm':
+		mflag= 1;
+		break;
+	    case 'r':
+		expand= 0;
+		/*FALL THROUGH*/
+	    case 'R':
+		rflag= 1;
+		break;
+	    case 'v':
+		vflag= 1;
+		break;
+	    case 'x':
+		xflag= 1;
+		break;
+	    default:
+		assert(0);
+	    }
+	}
+    }
+
+    switch (action) {
+    case REMOVE:
+	if (i == argc) usage();
+	break;
+    case LINK:
+	/* 'ln dir/file' is to be read as 'ln dir/file .'. */
+	if ((argc - i) == 1 && action == LINK) argv[argc++]= ".";
+	/*FALL THROUGH*/
+    default:
+	if ((argc - i) < 2) usage();
+    }
+
+    path_init(&src);
+    path_init(&dst);
+
+    if (action != REMOVE && !mflag
+	&& stat(argv[argc-1], &st) >= 0 && S_ISDIR(st.st_mode)
+    ) {
+	/* The last argument is a directory, this means we have to
+	 * throw the whole lot into this directory.  This is the
+	 * Right Thing unless you use -r.
+	 */
+	path_add(&dst, argv[argc-1]);
+	slash= path_length(&dst);
+
+	do {
+	    path_add(&src, argv[i]);
+	    path_add(&dst, basename(argv[i]));
+
+	    do1(&src, &dst, 0);
+
+	    path_trunc(&src, 0);
+	    path_trunc(&dst, slash);
+	} while (++i < argc-1);
+    } else
+    if (action == REMOVE || (argc - i) == 2) {
+	/* Just two files (or many files for rm). */
+	do {
+	    path_add(&src, argv[i]);
+	    if (action != REMOVE) path_add(&dst, argv[i+1]);
+
+	    do1(&src, &dst, 0);
+	    path_trunc(&src, 0);
+	} while (action == REMOVE && ++i < argc);
+    } else {
+	usage();
+    }
+    path_drop(&src);
+    path_drop(&dst);
+
+#if DEBUG
+    if (nchunks != 0) {
+	fprintf(stderr, "(%ld chunks of memory not freed)\n",
+	    (long) nchunks);
+    }
+#endif
+    exit(ex_code);
+}
Index: /trunk/minix/commands/simple/crc.c
===================================================================
--- /trunk/minix/commands/simple/crc.c	(revision 9)
+++ /trunk/minix/commands/simple/crc.c	(revision 9)
@@ -0,0 +1,117 @@
+/* Compute checksum			Author: Johan W. Stevenson */
+
+/* Copyright 1988 by Johan W. Stevenson */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+int errs;
+
+#if __STDC__
+int main(int argc, char **argv);
+void crc(char *fname);
+#else
+void crc();
+#endif
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  char line[256];
+
+  if (argc <= 1)
+	crc((char *) 0);
+  else if (argc == 2 && strcmp(argv[1], "-") == 0)
+	while (fgets(line, sizeof line, stdin) != NULL) {
+		if (line[strlen(line) - 1] == '\n')
+			line[strlen(line) - 1] = '\0';
+		crc(line);
+	}
+  else
+	do {
+		crc(argv[1]);
+		argv++;
+		argc--;
+	} while (argc > 1);
+  return(errs != 0);
+}
+
+/* Crctab calculated by Mark G. Mendel, Network Systems Corporation */
+static unsigned short crctab[256] = {
+       0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+       0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+       0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+       0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+       0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+       0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+       0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+       0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+       0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+       0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+       0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+       0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+       0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+       0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+       0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+       0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+       0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+       0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+       0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+       0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+       0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+       0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+       0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+       0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+       0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+       0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+       0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+       0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+       0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+       0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+       0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+        0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+};
+
+/* Updcrc macro derived from article Copyright (C) 1986 Stephen Satchell.
+ *  NOTE: First argument must be in range 0 to 255.
+ *        Second argument is referenced twice.
+ *
+ * Programmers may incorporate any or all code into their programs,
+ * giving proper credit within the source. Publication of the
+ * source routines is permitted so long as proper credit is given
+ * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg,
+ * Omen Technology.
+ */
+
+#define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
+
+void crc(fname)
+char *fname;
+{
+  register int c;
+  register long len = 0;
+  register unsigned short crc = 0;
+  register FILE *fp;
+
+  if (fname == NULL)
+	fp = stdin;
+  else if ((fp = fopen(fname, "r")) == NULL) {
+	fprintf(stderr, "crc: Can't open %s: %s\n", fname, strerror(errno));
+	errs++;
+	return;
+  }
+  while ((c = getc(fp)) != EOF) {
+	len++;
+	crc = updcrc(c, crc);
+  }
+  printf("%05u %6ld", crc, len);
+  if (fname) {
+	printf(" %s", fname);
+	fclose(fp);
+  }
+  printf("\n");
+}
Index: /trunk/minix/commands/simple/cut.c
===================================================================
--- /trunk/minix/commands/simple/cut.c	(revision 9)
+++ /trunk/minix/commands/simple/cut.c	(revision 9)
@@ -0,0 +1,310 @@
+/* cut - extract columns from a file or stdin. 	Author: Michael J. Holme
+ *
+ *	Copyright 1989, Michael John Holme, All rights reserved.
+ *	This code may be freely distributed, provided that this notice
+ *	remains intact.
+ *
+ *	V1.1: 6th September 1989
+ *
+ *	Bugs, criticisms, etc,
+ *      c/o Mark Powell
+ *          JANET sq79@uk.ac.liv
+ *          ARPA  sq79%liv.ac.uk@nsfnet-relay.ac.uk
+ *          UUCP  ...!mcvax!ukc!liv.ac.uk!sq79
+ *-------------------------------------------------------------------------
+ *	Changed for POSIX1003.2/Draft10 conformance
+ *	Thomas Brupbacher (tobr@mw.lpc.ethz.ch), September 1990.
+ *	Changes:
+ *	    - separation of error messages ( stderr) and output (stdout).
+ *	    - support for -b and -n (no effect, -b acts as -c)
+ *	    - support for -s
+ *-------------------------------------------------------------------------
+ */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define MAX_FIELD	80	/* Pointers to the beginning of each field
+			 * are stored in columns[], if a line holds
+			 * more than MAX_FIELD columns the array
+			 * boundary is exceed. But unlikely at 80 */
+
+#define MAX_ARGS	32	/* Maximum number of fields following -f or
+			 * -c switches												  	  */
+int args[MAX_ARGS * 2];
+int num_args;
+
+/* Lots of new defines, should easen maintainance...			*/
+#define DUMP_STDIN	0	/* define for mode: no options	 */
+#define OPTIONF		1	/* define for mode: option -f 	 */
+#define OPTIONC		2	/* define for mode: option -c	 */
+#define OPTIONB		3	/* define for mode: option -b	 */
+#define NOTSET		0	/* option not selected		 */
+#define SET		1	/* option selected		 */
+
+/* Defines for the warnings						*/
+#define DELIMITER_NOT_APPLICABLE	0
+#define OVERRIDING_PREVIOUS_MODE	1
+#define OPTION_NOT_APPLICABLE		2
+#define UNKNOWN_OPTION			3
+#define FILE_NOT_READABLE		4
+
+/* Defines for the fatal errors						*/
+#define SYNTAX_ERROR			101
+#define POSITION_ERROR			102
+#define USAGE				103
+#define LINE_TO_LONG_ERROR		104
+#define RANGE_ERROR			105
+#define MAX_FIELDS_EXEEDED_ERROR	106
+#define MAX_ARGS_EXEEDED_ERROR		107
+
+
+int mode;			/* 0 = dump stdin to stdout, 1=-f, 2=-c   */
+int flag_i;			/* SET = -i set on command line	 */
+int flag_s;			/* SET = -s set on command line	 */
+char delim = '\t';		/* default delimiting character	  */
+FILE *fd;
+char *name;
+char line[BUFSIZ];
+int exit_status;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void warn, (int warn_number, char *option));
+_PROTOTYPE(void cuterror, (int err));
+_PROTOTYPE(void get_args, (void));
+_PROTOTYPE(void cut, (void));
+
+void warn(warn_number, option)
+int warn_number;
+char *option;
+{
+  static char *warn_msg[] = {
+			   "%s: Option -d allowed only with -f\n",
+			   "%s: -%s overrides earlier option\n",
+			   "%s: -%s not allowed in current mode\n",
+			   "%s: Cannot open %s\n"
+  };
+
+  fprintf(stderr, warn_msg[warn_number], name, option);
+  exit_status = warn_number + 1;
+
+}
+
+void cuterror(err)
+int err;
+{
+  static char *err_mes[] = {
+			  "%s: syntax error\n",
+			  "%s: position must be >0\n",
+  "%s: usage: cut [-f args [-i] [-d x]]|[-c args] [filename [...]]\n",
+			  "%s: line longer than BUFSIZ\n",
+		 "%s: range must not decrease from left to right\n",
+			  "%s: MAX_FIELD exceeded\n",
+			  "%s: MAX_ARGS exceeded\n"
+  };
+
+  fprintf(stderr, err_mes[err - 101], name);
+  exit(err);
+}
+
+
+void get_args()
+{
+  int i = 0;
+  int arg_ptr = 0;
+  int flag;
+
+  num_args = 0;
+  do {
+	if (num_args == MAX_ARGS) cuterror(MAX_ARGS_EXEEDED_ERROR);
+	if (!isdigit(line[i]) && line[i] != '-') cuterror(SYNTAX_ERROR);
+
+	args[arg_ptr] = 1;
+	args[arg_ptr + 1] = BUFSIZ;
+	flag = 1;
+
+	while (line[i] != ',' && line[i] != 0) {
+		if (isdigit(line[i])) {
+			args[arg_ptr] = 0;
+			while (isdigit(line[i]))
+				args[arg_ptr] = 10 * args[arg_ptr] + line[i++] - '0';
+			if (!args[arg_ptr]) cuterror(POSITION_ERROR);
+			arg_ptr++;
+		}
+		if (line[i] == '-') {
+			arg_ptr |= 1;
+			i++;
+			flag = 0;
+		}
+	}
+	if (flag && arg_ptr & 1) args[arg_ptr] = args[arg_ptr - 1];
+	if (args[num_args * 2] > args[num_args * 2 + 1])
+		cuterror(RANGE_ERROR);
+	num_args++;
+	arg_ptr = num_args * 2;
+  }
+  while (line[i++]);
+}
+
+
+void cut()
+{
+  int i, j, length, maxcol;
+  char *columns[MAX_FIELD];
+
+  while (fgets(line, BUFSIZ, fd)) {
+	length = strlen(line) - 1;
+	*(line + length) = 0;
+	switch (mode) {
+	    case DUMP_STDIN:	printf("%s", line);	break;
+	    case OPTIONF:
+		maxcol = 0;
+		columns[maxcol++] = line;
+		for (i = 0; i < length; i++) {
+			if (*(line + i) == delim) {
+				*(line + i) = 0;
+				if (maxcol == MAX_FIELD)
+					cuterror(MAX_FIELDS_EXEEDED_ERROR);
+				columns[maxcol] = line + i + 1;
+				while (*(line + i + 1) == delim && flag_i) {
+					columns[maxcol]++;
+					i++;
+				}
+				maxcol++;
+			}
+		}
+		if (maxcol == 1) {
+			if (flag_s != SET) printf("%s", line);
+		} else {
+			for (i = 0; i < num_args; i++) {
+				for (j = args[i * 2]; j <= args[i * 2 + 1]; j++)
+					if (j <= maxcol) {
+						printf("%s", columns[j - 1]);
+						if (i != num_args - 1 || j != args[i * 2 + 1])
+							putchar(delim);
+					}
+			}
+		}
+		break;
+	    case OPTIONC:
+		for (i = 0; i < num_args; i++) {
+			for (j = args[i * 2]; j <= (args[i * 2 + 1] > length ? length :
+					      args[i * 2 + 1]); j++)
+				putchar(*(line + j - 1));
+		}
+	}
+	if (maxcol == 1 && flag_s == SET);
+	else
+		putchar('\n');
+  }
+}
+
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i = 1;
+  int numberFilenames = 0;
+  name = argv[0];
+
+  if (argc == 1) cuterror(USAGE);
+
+  while (i < argc) {
+	if (argv[i][0] == '-') {
+		switch (argv[i++][1]) {
+		    case 'd':
+			if (mode == OPTIONC || mode == OPTIONB)
+				warn(DELIMITER_NOT_APPLICABLE, "d");
+			delim = argv[i++][0];
+			break;
+		    case 'f':
+			sprintf(line, "%s", argv[i++]);
+			if (mode == OPTIONC || mode == OPTIONB)
+				warn(OVERRIDING_PREVIOUS_MODE, "f");
+			mode = OPTIONF;
+			break;
+		    case 'b':
+			sprintf(line, "%s", argv[i++]);
+			if (mode == OPTIONF || mode == OPTIONC)
+				warn(OVERRIDING_PREVIOUS_MODE, "b");
+			mode = OPTIONB;
+			break;
+		    case 'c':
+			sprintf(line, "%s", argv[i++]);
+			if (mode == OPTIONF || mode == OPTIONB)
+				warn(OVERRIDING_PREVIOUS_MODE, "c");
+			mode = OPTIONC;
+			break;
+		    case 'i':	flag_i = SET;	break;
+		    case 's':	flag_s = SET;	break;
+		    case '\0':	/* - means: read from stdin		 */
+			numberFilenames++;
+			break;
+		    case 'n':	/* needed for Posix, but no effect here	 */
+			if (mode != OPTIONB)
+				warn(OPTION_NOT_APPLICABLE, "n");
+			break;
+		    default:
+			warn(UNKNOWN_OPTION, &(argv[i - 1][1]));
+		}
+	} else {
+		i++;
+		numberFilenames++;
+	}
+  }
+
+/* Here follow the checks, if the selected options are reasonable.	*/
+  if (mode == OPTIONB)		/* since in Minix char := byte		 */
+	mode = OPTIONC;
+/* Flag -s is only allowed with -f, otherwise warn and reset flag_s	*/
+  if (flag_s == SET && (mode == OPTIONB || mode == OPTIONC)) {
+	warn(OPTION_NOT_APPLICABLE, "s");
+	flag_s = NOTSET;
+  }
+
+/* Flag -i is only allowed with -f, otherwise warn and reset flag_i	*/
+  if (flag_i == SET && mode == OPTIONF) {
+	warn(OPTION_NOT_APPLICABLE, "s");
+	flag_i = NOTSET;
+  }
+  get_args();
+  if (numberFilenames != 0) {
+	i = 1;
+	while (i < argc) {
+		if (argv[i][0] == '-') {
+			switch (argv[i][1]) {
+			    case 'f':
+			    case 'c':
+			    case 'b':
+			    case 'd':	i += 2;	break;
+			    case 'n':
+			    case 'i':
+			    case 's':	i++;	break;
+			    case '\0':
+				fd = stdin;
+				i++;
+				cut();
+				break;
+			    default:	i++;
+			}
+		} else {
+			if ((fd = fopen(argv[i++], "r")) == NULL) {
+				warn(FILE_NOT_READABLE, argv[i - 1]);
+			} else {
+				cut();
+				fclose(fd);
+			}
+		}
+	}
+  } else {
+	fd = stdin;
+	cut();
+  }
+
+  return(exit_status);
+}
Index: /trunk/minix/commands/simple/date.c
===================================================================
--- /trunk/minix/commands/simple/date.c	(revision 9)
+++ /trunk/minix/commands/simple/date.c	(revision 9)
@@ -0,0 +1,443 @@
+/* date - Display (or set) the date and time		Author: V. Archer */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <unistd.h>
+
+#define	MIN	60L		/* # seconds in a minute */
+#define	HOUR	(60 * MIN)	/* # seconds in an hour */
+#define	DAY	(24 * HOUR)	/* # seconds in a day */
+#define	YEAR	(365 * DAY)	/* # seconds in a (non-leap) year */
+
+int qflag, uflag, sflag, Sflag;
+
+/* Default output file descriptor.
+ */
+int outfd = 1;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void putchar, (int c));
+_PROTOTYPE(void pstring, (char *s, int len));
+_PROTOTYPE(void pldecimal, (unsigned long d, int digits));
+_PROTOTYPE(void pdecimal, (int d, int digits));
+_PROTOTYPE(void fmtdate, (char *format, time_t t, struct tm *p));
+_PROTOTYPE(time_t make_time, (char *t));
+_PROTOTYPE(struct tm *september, (time_t *tp));
+_PROTOTYPE(void usage, (void));
+
+/* Main module. Handles P1003.2 date and system administrator's date. The
+ * date entered should be given GMT, regardless of the system's TZ!
+ */
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  time_t t;
+  struct tm *tm;
+  char *format;
+  char time_buf[40];
+  int n;
+  int i;
+
+  time(&t);
+
+  i = 1;
+  while (i < argc && argv[i][0] == '-') {
+	char *opt = argv[i++] + 1, *end;
+
+	if (opt[0] == '-' && opt[1] == 0) break;
+
+	while (*opt != 0) switch (*opt++) {
+	case 'q':
+		qflag = 1;
+		break;
+	case 's':
+		sflag = 1;
+		break;
+	case 'u':
+		uflag = 1;
+		break;
+	case 'S':
+		Sflag = 1;
+		break;
+	case 't':
+		/* (obsolete, now -r) */
+	case 'r':
+		if (*opt == 0) {
+			if (i == argc) usage();
+			opt = argv[i++];
+		}
+		t = strtoul(opt, &end, 10);
+		if (*end != 0) usage();
+		opt = "";
+		break;
+	default:
+		usage();
+	}
+  }
+
+  if (!qflag && i < argc && ('0' <= argv[i][0] && argv[i][0] <= '9')) {
+	t = make_time(argv[i++]);
+	sflag = 1;
+  }
+
+  format = "%c";
+  if (i < argc && argv[i][0] == '+') format = argv[i++] + 1;
+
+  if (i != argc) usage();
+
+  if (qflag) {
+	pstring("\nPlease enter date: MMDDYYhhmmss. Then hit the RETURN key.\n", -1);
+	n = read(0, time_buf, sizeof(time_buf));
+	if (n > 0 && time_buf[n-1] == '\n') n--;
+	if (n >= 0) time_buf[n] = 0;
+	t = make_time(time_buf);
+	sflag = 1;
+  }
+
+  if (sflag && stime(&t) != 0) {
+	outfd = 2;
+	pstring("No permission to set time\n", -1);
+	return(1);
+  }
+
+  tm = Sflag ? september(&t) : uflag ? gmtime(&t) : localtime(&t);
+
+  fmtdate(format, t, tm);
+  putchar('\n');
+  return(0);
+}
+
+/* Replacement for stdio putchar().
+ */
+void putchar(c)
+int c;
+{
+  static char buf[1024];
+  static char *bp = buf;
+
+  if (c != 0) *bp++ = c;
+  if (c == 0 || c == '\n' || bp == buf + sizeof(buf)) {
+	write(outfd, buf, bp - buf);
+	bp = buf;
+  }
+}
+
+/* Internal function that prints a n-digits number. Replaces stdio in our
+ * specific case.
+ */
+void pldecimal(d, digits)
+unsigned long d;
+int digits;
+{
+  digits--;
+  if (d > 9 || digits > 0) pldecimal(d / 10, digits);
+  putchar('0' + (d % 10));
+}
+
+void pdecimal(d, digits)
+int d, digits;
+{
+  pldecimal((unsigned long) d, digits);
+}
+
+/* Internal function that prints a fixed-size string. Replaces stdio in our
+ * specific case.
+ */
+void pstring(s, len)
+char *s;
+int len;
+{
+  while (*s)
+	if (len--)
+		putchar(*s++);
+	else
+		break;
+}
+
+/* Format the date, using the given locale string. A special case is the
+ * TZ which might be a sign followed by four digits (New format time zone).
+ */
+void fmtdate(format, t, p)
+char *format;
+time_t t;
+struct tm *p;
+{
+  int i;
+  char *s;
+  static char *wday[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
+		       "Thursday", "Friday", "Saturday"};
+  static char *month[] = {"January", "February", "March", "April",
+			"May", "June", "July", "August",
+		    "September", "October", "November", "December"};
+
+  while (*format)
+	if (*format == '%') {
+		switch (*++format) {
+		    case 'A':
+			pstring(wday[p->tm_wday], -1);
+			break;
+		    case 'B':
+			pstring(month[p->tm_mon], -1);
+			break;
+		    case 'D':
+			pdecimal(p->tm_mon + 1, 2);
+			putchar('/');
+			pdecimal(p->tm_mday, 2);
+			putchar('/');
+		    case 'y':
+			pdecimal(p->tm_year % 100, 2);
+			break;
+		    case 'H':
+			pdecimal(p->tm_hour, 2);
+			break;
+		    case 'I':
+			i = p->tm_hour % 12;
+			pdecimal(i ? i : 12, 2);
+			break;
+		    case 'M':
+			pdecimal(p->tm_min, 2);
+			break;
+		    case 'X':
+		    case 'T':
+			pdecimal(p->tm_hour, 2);
+			putchar(':');
+			pdecimal(p->tm_min, 2);
+			putchar(':');
+		    case 'S':
+			pdecimal(p->tm_sec, 2);
+			break;
+		    case 'U':
+			pdecimal((p->tm_yday - p->tm_wday + 13) / 7, 2);
+			break;
+		    case 'W':
+			if (--(p->tm_wday) < 0) p->tm_wday = 6;
+			pdecimal((p->tm_yday - p->tm_wday + 13) / 7, 2);
+			if (++(p->tm_wday) > 6) p->tm_wday = 0;
+			break;
+		    case 'Y':
+			pdecimal(p->tm_year + 1900, 4);
+			break;
+		    case 'Z':
+			if (uflag) {
+				s = "GMT";
+			} else {
+				s = (p->tm_isdst == 1) ? tzname[1] : tzname[0];
+			}
+			pstring(s, strlen(s));
+			break;
+		    case 'a':
+			pstring(wday[p->tm_wday], 3);
+			break;
+		    case 'b':
+		    case 'h':
+			pstring(month[p->tm_mon], 3);
+			break;
+		    case 'c':
+			if (!(s = getenv("LC_TIME")))
+				s = "%a %b %e %T %Z %Y";
+			fmtdate(s, t, p);
+			break;
+		    case 'd':
+			pdecimal(p->tm_mday, 2);
+			break;
+		    case 'e':
+			if (p->tm_mday < 10) putchar(' ');
+			pdecimal(p->tm_mday, 1);
+			break;
+		    case 'j':
+			pdecimal(p->tm_yday + 1, 3);
+			break;
+		    case 'm':
+			pdecimal(p->tm_mon + 1, 2);
+			break;
+		    case 'n':	putchar('\n');	break;
+		    case 'p':
+			if (p->tm_hour < 12)
+				putchar('A');
+			else
+				putchar('P');
+			putchar('M');
+			break;
+		    case 'r':
+			fmtdate("%I:%M:%S %p", t, p);
+			break;
+		    case 's':
+			pldecimal((unsigned long) t, 0);
+			break;
+		    case 't':	putchar('\t');	break;
+		    case 'w':
+			putchar('0' + p->tm_wday);
+			break;
+		    case 'x':
+			fmtdate("%B %e %Y", t, p);
+			break;
+		    case '%':	putchar('%');	break;
+		    case '\0':	format--;
+		}
+		format++;
+	} else
+		putchar(*format++);
+}
+
+/* Convert a local date string into GMT time in seconds. */
+time_t make_time(t)
+char *t;
+{
+  struct tm tm;				/* user specified time */
+  time_t now;				/* current time */
+  int leap;				/* current year is leap year */
+  int i;				/* general index */
+  int fld;				/* number of fields */
+  int f[6];				/* time fields */
+  static int days_per_month[2][12] = {
+  { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+  { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }};
+
+/* Get current time just in case */
+  now = time((time_t *) 0);
+  tm  = *localtime(&now);
+  tm.tm_sec   = 0;
+  tm.tm_mon++;
+  tm.tm_year %= 100;
+
+/* Parse the time */
+#if '0'+1 != '1' || '1'+1 != '2' || '2'+1 != '3' || '3'+1 != '4' || \
+    '4'+1 != '5' || '5'+1 != '6' || '6'+1 != '7' || '7'+1 != '8' || '8'+1 != '9'
+  << Code unsuitable for character collating sequence >>
+#endif
+
+  for (fld = 0; fld < sizeof(f)/sizeof(f[0]); fld++) {
+	if (*t == 0) break;
+	f[fld] = 0;
+	for (i = 0; i < 2; i++, t++) {
+		if (*t < '0' || *t > '9') usage();
+		f[fld] = f[fld] * 10 + *t - '0';
+	}
+  }
+
+  switch (fld) {
+  case 2:
+	tm.tm_hour = f[0]; tm.tm_min  = f[1]; break;
+
+  case 3:
+	tm.tm_hour = f[0]; tm.tm_min  = f[1]; tm.tm_sec  = f[2];
+	break;
+
+  case 5:
+  	tm.tm_mon  = f[0]; tm.tm_mday = f[1]; tm.tm_year = f[2];
+	tm.tm_hour = f[3]; tm.tm_min  = f[4];
+	break;
+
+  case 6:
+	tm.tm_mon  = f[0]; tm.tm_mday = f[1]; tm.tm_year = f[2];
+	tm.tm_hour = f[3]; tm.tm_min  = f[4]; tm.tm_sec  = f[5];
+	break;
+
+  default:
+	usage();
+  }
+
+/* Convert the time into seconds since 1 January 1970 */
+  if (tm.tm_year < 70)
+    tm.tm_year += 100;
+  leap = (tm.tm_year % 4 == 0 && tm.tm_year % 400 != 0);
+  if (tm.tm_mon  < 1  || tm.tm_mon  > 12 ||
+      tm.tm_mday < 1  || tm.tm_mday > days_per_month[leap][tm.tm_mon-1] ||
+      tm.tm_hour > 23 || tm.tm_min  > 59) {
+    outfd = 2;
+    pstring("Illegal date format\n", -1);
+    exit(1);
+  }
+
+/* Convert the time into Minix time - zone independent code */
+  {
+    time_t utctime;			/* guess at unix time */
+    time_t nextbit;			/* next bit to try */
+    int rv;				/* result of try */
+    struct tm *tmp;			/* local time conversion */
+
+#define COMPARE(a,b)	((a) != (b)) ? ((a) - (b)) :
+
+    utctime = 1;
+    do {
+      nextbit = utctime;
+      utctime = nextbit << 1;
+    } while (utctime >= 1);
+
+    for (utctime = 0; ; nextbit >>= 1) {
+
+      utctime |= nextbit;
+      tmp = localtime(&utctime);
+      if (tmp == 0) continue;
+
+      rv = COMPARE(tmp->tm_year,    tm.tm_year)
+           COMPARE(tmp->tm_mon + 1, tm.tm_mon)
+	   COMPARE(tmp->tm_mday,    tm.tm_mday)
+	   COMPARE(tmp->tm_hour,    tm.tm_hour)
+	   COMPARE(tmp->tm_min,     tm.tm_min)
+	   COMPARE(tmp->tm_sec,     tm.tm_sec)
+	   0;
+
+      if (rv > 0)
+        utctime &= ~nextbit;
+      else if (rv == 0)
+        break;
+
+      if (nextbit == 0) {
+	uflag = 1;
+        outfd = 2;
+        pstring("Inexact conversion to UTC from ", -1);
+        fmtdate("%c\n", utctime, localtime(&utctime) );
+	exit(1);
+      }
+    }
+    return utctime;
+  }
+}
+
+/* Correct the time to the reckoning of Eternal September. */
+struct tm *september(tp)
+time_t *tp;
+{
+  time_t t;
+  int days;
+  struct tm *tm;
+
+  tm = localtime(tp);
+
+  t = *tp - (tm->tm_hour - 12) * 3600L;  /* No zone troubles around noon. */
+  days = 0;
+
+  while (tm->tm_year > 93 || (tm->tm_year == 93 && tm->tm_mon >= 8)) {
+	/* Step back a year or a month. */
+	days += tm->tm_year > 93 ? tm->tm_yday+1 : tm->tm_mday;
+	t = *tp - days * (24 * 3600L);
+
+	tm = localtime(&t);
+  }
+
+  if (days > 0) {
+	tm = localtime(tp);
+	tm->tm_mday = days;
+	tm->tm_year = 93;
+	tm->tm_mon = 8;
+#if SANITY
+	t = mktime(tm);
+	tm = localtime(&t);
+#endif
+  }
+  return tm;
+}
+
+/* (Extended) Posix prototype of date. */
+void usage()
+{
+  outfd = 2;
+  pstring("Usage: date [-qsuS] [-r seconds] [[MMDDYY]hhmm[ss]] [+format]\n", -1);
+  exit(1);
+}
Index: /trunk/minix/commands/simple/dd.c
===================================================================
--- /trunk/minix/commands/simple/dd.c	(revision 9)
+++ /trunk/minix/commands/simple/dd.c	(revision 9)
@@ -0,0 +1,394 @@
+/* dd - disk dumper */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#define EOS '\0'
+#define BOOLEAN int
+#define TRUE 1
+#define FALSE 0
+
+char *pch, *errorp;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(BOOLEAN is, (char *pc));
+_PROTOTYPE(int num, (void));
+_PROTOTYPE(void puto, (void));
+_PROTOTYPE(void statistics, (void));
+_PROTOTYPE(int ulcase, (int c));
+_PROTOTYPE(void cnull, (int c));
+_PROTOTYPE(void null, (int c));
+_PROTOTYPE(void extra, (void));
+_PROTOTYPE(void over, (int dummy));
+
+BOOLEAN is(pc)
+char *pc;
+{
+  register char *ps = pch;
+
+  while (*ps++ == *pc++)
+	if (*pc == EOS) {
+		pch = ps;
+		return(TRUE);
+	}
+  return(FALSE);
+}
+
+#define BIGNUM  2147483647
+
+int num()
+{
+  long ans;
+  register char *pc;
+
+  pc = pch;
+  ans = 0L;
+  while ((*pc >= '0') && (*pc <= '9'))
+	ans = (long) ((*pc++ - '0') + (ans * 10));
+  while (TRUE) switch (*pc++) {
+	    case 'w':
+		ans *= 2L;
+		continue;
+	    case 'b':
+		ans *= 512L;
+		continue;
+	    case 'k':
+		ans *= 1024L;
+		continue;
+	    case 'x':
+		pch = pc;
+		ans *= (long) num();
+	    case EOS:
+		if ((ans >= BIGNUM) || (ans < 0)) {
+			fprintf(stderr, "dd: argument %s out of range\n",
+				errorp);
+			exit(1);
+		}
+		return((int) ans);
+	}
+}
+
+#define SWAB 0x0001
+#define LCASE 0x0002
+#define UCASE 0x0004
+#define NOERROR 0x0008
+#define SYNC 0x0010
+#define SILENT 0x0020
+#define BLANK ' '
+#define DEFAULT 512
+
+unsigned cbs, bs, skip, nseek, count;
+int seekseen = FALSE;
+unsigned ibs = DEFAULT;
+unsigned obs = DEFAULT;
+unsigned files = 1;
+char *ifilename = NULL;
+char *ofilename = NULL;
+
+int convflag = 0;
+int flag = 0;
+int ifd, ofd, ibc;
+char *ibuf, *obuf, *op;
+unsigned nifull, nipartial, nofull, nopartial;
+int cbc;
+unsigned ntr, obc;
+int ns;
+char mlen[] = {64, 45, 82, 45, 83, 96, 109, 100, 109, 97, 96, 116, 108, 9};
+
+void puto()
+{
+  int n;
+
+  if (obc == 0) return;
+  if (obc == obs)
+	nofull++;
+  else
+	nopartial++;
+  if ((n = write(ofd, obuf, obc)) != obc) {
+	if (n == -1) {
+		fprintf(stderr, "dd: Write error: %s\n", strerror(errno));
+	} else {
+		fprintf(stderr, "dd: Short write, %d instead of %d\n", n, obc);
+	}
+	exit(1);
+  }
+  obc = 0;
+}
+
+void statistics()
+{
+  if (convflag & SILENT) return;
+  fprintf(stderr, "%u+%u records in\n", nifull, nipartial);
+  fprintf(stderr, "%u+%u records out\n", nofull, nopartial);
+  if (ntr) fprintf(stderr, "%d truncated records\n", ntr);
+}
+
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+#ifdef __STDC__
+  void (*convert) (int);
+#else
+  void (*convert) ();
+#endif
+  char *iptr;
+  int i, j;
+
+  convert = null;
+  argc--;
+  argv++;
+  while (argc-- > 0) {
+	pch = *(argv++);
+	if (is("ibs=")) {
+		errorp = pch;
+		ibs = num();
+		continue;
+	}
+	if (is("obs=")) {
+		errorp = pch;
+		obs = num();
+		continue;
+	}
+	if (is("bs=")) {
+		errorp = pch;
+		bs = num();
+		continue;
+	}
+	if (is("if=")) {
+		ifilename = pch;
+		continue;
+	}
+	if (is("of=")) {
+		ofilename = pch;
+		continue;
+	}
+	if (is("skip=")) {
+		errorp = pch;
+		skip = num();
+		continue;
+	}
+	if (is("seek=")) {
+		errorp = pch;
+		nseek = num();
+		seekseen = TRUE;
+		continue;
+	}
+	if (is("count=")) {
+		errorp = pch;
+		count = num();
+		continue;
+	}
+	if (is("files=")) {
+		errorp = pch;
+		files = num();
+		continue;
+	}
+	if (is("length=")) {
+		errorp = pch;
+		for (j = 0; j < 13; j++) mlen[j]++;
+		write(2, mlen, 14);
+		continue;
+	}
+	if (is("conv=")) {
+		while (*pch != EOS) {
+			if (is("lcase")) {
+				convflag |= LCASE;
+				continue;
+			}
+			if (is("ucase")) {
+				convflag |= UCASE;
+				continue;
+			}
+			if (is("noerror")) {
+				convflag |= NOERROR;
+				continue;
+			}
+			if (is("sync")) {
+				convflag |= SYNC;
+				continue;
+			}
+			if (is("swab")) {
+				convflag |= SWAB;
+				continue;
+			}
+			if (is("silent")) {
+				convflag |= SILENT;
+				continue;
+			}
+			if (is(",")) continue;
+			fprintf(stderr, "dd: bad argument: %s\n",
+				pch);
+			exit(1);
+		}
+		if (*pch == EOS) continue;
+	}
+	fprintf(stderr, "dd: bad argument: %s\n", pch);
+	exit(1);
+  }
+  if ((convert == null) && (convflag & (UCASE | LCASE))) convert = cnull;
+  if ((ifd = ((ifilename) ? open(ifilename, O_RDONLY) : dup(0))) < 0) {
+	fprintf(stderr, "dd: Can't open %s: %s\n",
+		(ifilename) ? ifilename : "stdin", strerror(errno));
+	exit(1);
+  }
+  if ((ofd = ((ofilename) ? open(ofilename, seekseen ? O_WRONLY | O_CREAT
+					: O_WRONLY | O_CREAT | O_TRUNC, 0666)
+			: dup(1))) < 0) {
+	fprintf(stderr, "dd: Can't open %s: %s\n",
+		(ofilename) ? ofilename : "stdout", strerror(errno));
+	exit(1);
+  }
+  if (bs) {
+	ibs = obs = bs;
+	if (convert == null) flag++;
+  }
+  if (ibs == 0) {
+	fprintf(stderr, "dd: ibs cannot be zero\n");
+	exit(1);
+  }
+  if (obs == 0) {
+	fprintf(stderr, "dd: obs cannot be zero\n");
+	exit(1);
+  }
+  if ((ibuf = sbrk(ibs)) == (char *) -1) {
+	fprintf(stderr, "dd: not enough memory\n");
+	exit(1);
+  }
+  if ((obuf = (flag) ? ibuf : sbrk(obs)) == (char *) -1) {
+	fprintf(stderr, "dd: not enough memory\n");
+	exit(1);
+  }
+  ibc = obc = cbc = 0;
+  op = obuf;
+  if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, over);
+  if (skip != 0) {
+	struct stat st;
+	if (fstat(ifd,&st) < 0 || !(S_ISREG(st.st_mode) || S_ISBLK(st.st_mode))
+	   || lseek(ifd, (off_t) ibs * (off_t) skip, SEEK_SET) == (off_t) -1) {
+		do {
+			if (read(ifd, ibuf, ibs) == -1) {
+				fprintf(stderr,
+					"dd: Error skipping input: %s\n",
+					strerror(errno));
+				exit(1);
+			}
+		} while (--skip != 0);
+	}
+  }
+  if (nseek != 0) {
+	if (lseek(ofd, (off_t) obs * (off_t) nseek, SEEK_SET) == (off_t) -1) {
+		fprintf(stderr, "dd: Seeking on output failed: %s\n",
+			strerror(errno));
+		exit(1);
+	}
+  }
+
+outputall:
+  if (ibc-- == 0) {
+	ibc = 0;
+	if ((count == 0) || ((nifull + nipartial) != count)) {
+		if (convflag & (NOERROR | SYNC))
+			for (iptr = ibuf + ibs; iptr > ibuf;) *--iptr = 0;
+		ibc = read(ifd, ibuf, ibs);
+	}
+	if (ibc == -1) {
+		fprintf(stderr, "dd: Read error: %s\n", strerror(errno));
+		if ((convflag & NOERROR) == 0) {
+			puto();
+			over(0);
+		}
+		ibc = 0;
+		for (i = 0; i < ibs; i++)
+			if (ibuf[i] != 0) ibc = i;
+		statistics();
+	}
+	if ((ibc == 0) && (--files <= 0)) {
+		puto();
+		over(0);
+	}
+	if (ibc != ibs) {
+		nipartial++;
+		if (convflag & SYNC) ibc = ibs;
+	} else
+		nifull++;
+	iptr = ibuf;
+	i = ibc >> 1;
+	if ((convflag & SWAB) && i) do {
+			int temp;
+			temp = *iptr++;
+			iptr[-1] = *iptr;
+			*iptr++ = temp;
+		} while (--i);
+	iptr = ibuf;
+	if (flag) {
+		obc = ibc;
+		puto();
+		ibc = 0;
+	}
+	goto outputall;
+  }
+  i = *iptr++ & 0377;
+  (*convert) (i);
+  goto outputall;
+}
+
+int ulcase(c)
+int c;
+{
+  int ans = c;
+
+  if ((convflag & UCASE) && (c >= 'a') &&
+      (c <= 'z'))
+	ans += 'A' - 'a';
+  if ((convflag & LCASE) && (c >= 'A') &&
+      (c <= 'Z'))
+	ans += 'a' - 'A';
+  return(ans);
+}
+
+void cnull(c)
+int c;
+{
+  c = ulcase(c);
+  null(c);
+}
+
+void null(c)
+int c;
+{
+  *op++ = c;
+  if (++obc >= obs) {
+	puto();
+	op = obuf;
+  }
+}
+
+void extra()
+{
+  if (++cbc >= cbs) {
+	null('\n');
+	cbc = 0;
+	ns = 0;
+  }
+}
+
+void over(sig)
+int sig;
+{
+  statistics();
+  if (sig != 0) {
+	signal(sig, SIG_DFL);
+	raise(sig);
+  }
+  exit(0);
+}
Index: /trunk/minix/commands/simple/decomp16.c
===================================================================
--- /trunk/minix/commands/simple/decomp16.c	(revision 9)
+++ /trunk/minix/commands/simple/decomp16.c	(revision 9)
@@ -0,0 +1,444 @@
+/* decomp16: decompress 16bit compressed files on a 16bit Intel processor
+ *
+ * Version 1.3 of 25 Mar 92.
+ *
+ * This was written by John N. White on 6/30/91 and is Public Domain.
+ * Patched to run under news by Will Rose, Feb 92.
+ * J N White's (earlier) patches added by Will Rose, 20 Feb 92.
+ * Unsigned int increment/wrap bug fixed by Will Rose, 24 Mar 92.
+ * Argument bug fixed, stdio generalised by Will Rose, 25 Mar 92.
+ *
+ * decomp16 can use as as little as 512 bytes of stack; since it forks
+ * four additional copies, it's probably worth using minimum stack rather
+ * than the 8192 byte Minix default.  To reduce memory still further,
+ * change BUFSZ below to 256; it is currently set to 1024 for speed.  The
+ * minimal decomp16 needs about 280k to run in pipe mode (56k per copy).
+ *
+ * This program acts as a filter:
+ *    decomp16 < compressed_file > decompressed_file
+ * The arguments -0 to -4 run only the corresponding pass.
+ * Thus:
+ *    decomp16 -4 < compressed_file > 3;
+ *    decomp16 -3 < 3 > 2;
+ *    decomp16 -2 < 2 > 1;
+ *    decomp16 -1 < 1 > 0;
+ *    decomp16 -0 < 0 > decompressed_file
+ * will also work, as will connecting the passes by explicit pipes if
+ * there is enough memory to do so.  File name arguments can also be
+ * given directly on the command line.
+ *
+ * Compress uses a modified LZW compression algorithm. A compressed file
+ * is a set of indices into a dictionary of strings. The number of bits
+ * used to store each index depends on the number of entries currently
+ * in the dictionary. If there are between 257 and 512 entries, 9 bits
+ * are used. With 513 entries, 10 bits are used, etc. The initial dictionary
+ * consists of 0-255 (which are the corresponding chars) and 256 (which
+ * is a special CLEAR code). As each index in the compressed file is read,
+ * a new entry is added to the dictionary consisting of the current string
+ * with the first char of the next string appended. When the dictionary
+ * is full, no further entries are added. If a CLEAR code is received,
+ * the dictionary will be completely reset. The first two bytes of the
+ * compressed file are a magic number, and the third byte indicates the
+ * maximum number of bits, and whether the CLEAR code is used (older versions
+ * of compress didn't have CLEAR).
+ *
+ * This program works by forking four more copies of itself. The five
+ * programs form a pipeline. Copy 0 writes to stdout, and forks copy 1
+ * to supply its input, which in turn forks and reads from copy 2, etc.
+ * This sequence is used so that when the program exits, all writes
+ * are completed and a program that has exec'd uncompress (such as news)
+ * can immediately use the uncompressed data when the wait() call returns.
+ *
+ * If given a switch -#, where # is a digit from 0 to 4 (example: -2), the
+ * program will run as that copy, reading from stdin and writing to stdout.
+ * This allows decompressing with very limited RAM because only one of the
+ * five passes is in memory at a time.
+ *
+ * The compressed data is a series of string indices (and a header at
+ * the beginning and an occasional CLEAR code). As these indices flow
+ * through the pipes, each program decodes the ones it can. The result
+ * of each decoding will be indices that the following programs can handle.
+ *
+ * Each of the 65536 strings in the dictionary is an earlier string with
+ * some character added to the end (except for the the 256 predefined
+ * single char strings). When new entries are made to the dictionary,
+ * the string index part will just be the last index to pass through.
+ * But the char part is the first char of the next string, which isn't
+ * known yet. So the string can be stored as a pair of indices. When
+ * this string is specified, it is converted to this pair of indices,
+ * which are flagged so that the first will be decoded in full while
+ * the second will be decoded to its first char. The dictionary takes
+ * 256k to store (64k strings of 2 indices of 2 bytes each). This is
+ * too big for a 64k data segment, so it is divided into 5 equal parts.
+ * Copy 4 of the program maintains the high part and copy 0 holds the
+ * low part.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define BUFSZ		1024	/* size of i/o buffers */
+#define BUFSZ_2		(BUFSZ/2)	/* # of unsigned shorts in i/o bufs */
+#define DICTSZ		(unsigned)13056	/* # of local dictionary entries */
+#define EOF_INDEX	(unsigned short)0xFFFF	/* EOF flag for pipeline */
+#define FALSE		0
+#define TRUE		~FALSE
+
+int fdin, fdout, fderr;		/* input, output, and error file descriptors */
+int ibufstart, obufind, ibufend;/* i/o buffer indices */
+int ipbufind = BUFSZ_2;		/* pipe buffer indices */
+int opbufind = 0;
+int pnum = -1;			/* ID of this copy */
+unsigned short ipbuf[BUFSZ_2];	/* for buffering input */
+unsigned short opbuf[BUFSZ_2];	/* for buffering output */
+unsigned char *ibuf = (unsigned char *) ipbuf;
+unsigned char *obuf = (unsigned char *) opbuf;
+
+unsigned short dindex[DICTSZ];	/* dictionary: index to substring */
+unsigned short dchar[DICTSZ];	/* dictionary: last char of string */
+unsigned iindex, tindex, tindex2;	/* holds index being processed */
+unsigned base;			/* where in global dict local dict starts */
+unsigned tbase;
+unsigned locend;		/* where in global dict local dict ends */
+unsigned curend = 256;		/* current end of global dict */
+unsigned maxend;		/* max end of global dict */
+int dcharp;			/* ptr to dchar that needs next index entry */
+int curbits;			/* number of bits for getbits() to read */
+int maxbits;			/* limit on number of bits */
+int clearflg;			/* if set, allow CLEAR */
+int inmod;			/* mod 8 for getbits() */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void ffork, (void));
+_PROTOTYPE(void die, (char *s));
+_PROTOTYPE(void myputc, (unsigned c));
+_PROTOTYPE(unsigned mygetc, (void));
+_PROTOTYPE(void getbits, (void));
+_PROTOTYPE(void getpipe, (void));
+_PROTOTYPE(void putpipe, (unsigned u, int flag));
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  char c, *cp;
+  int j, k, fdtmp;
+  unsigned int len;
+
+  /* Find the program name */
+  j = 0;
+  while (argv[0][j] != '\0') j++;
+  len = (unsigned int) j;
+  while (j--)
+	if (argv[0][j] == '/') break;
+  if (argv[0][j] == '/') j++;
+  cp = argv[0] + j;
+  len -= j;
+
+  /* Sort out the flags */
+  for (k = 1; k < argc; k++) {
+	if (argv[k][0] == '-') {
+		c = argv[k][1];
+		switch (c) {
+		    case '0':	/* pass numbers */
+		    case '1':
+		    case '2':
+		    case '3':
+		    case '4':	pnum = c - '0';	break;
+		    case 'd':	/* used by news */
+			break;
+		    default:
+			(void) write(1, "Usage: ", 7);
+			(void) write(1, cp, len);
+			(void) write(1, " [-#] [in] [out]\n", 17);
+			exit(0);
+			break;
+		}
+
+		/* Once it's checked, lose it anyway */
+		for (j = k; j < argc; j++) argv[j] = argv[j + 1];
+		argc--;
+		k--;
+	}
+  }
+
+  /* Default i/o settings */
+  fdin = 0;
+  fdout = 1;
+  fderr = 2;
+
+  /* Try to open specific files and connect them to stdin/stdout */
+  if (argc > 1) {
+	if ((fdtmp = open(argv[1], 0)) == -1) die("input open failed");
+	(void) close(0);
+	if ((fdin = dup(fdtmp)) == -1) die("input dup failed\n");
+	(void) close(fdtmp);
+  }
+  if (argc > 2) {
+	(void) unlink(argv[2]);
+	if ((fdtmp = creat(argv[2], 0666)) == -1) die("output creat failed");
+	(void) close(1);
+	if ((fdout = dup(fdtmp)) == -1) die("output dup failed\n");
+	(void) close(fdtmp);
+  }
+
+  /* Sort out type of compression */
+  if (pnum == -1 || pnum == 4) {/* if this is pass 4 */
+	/* Check header of compressed file */
+	if (mygetc() != 0x1F || mygetc() != 0x9D)      /* check magic number */
+		die("not a compressed file\n");
+	iindex = mygetc();	/* get compression style */
+  } else
+	getpipe();		/* get compression style */
+
+  maxbits = iindex & 0x1F;
+  clearflg = ((iindex & 0x80) != 0) ? TRUE : FALSE;
+  if (maxbits < 9 || maxbits > 16)	/* check for valid maxbits */
+	die("can't decompress\n");
+  if (pnum != -1 && pnum != 0)
+	putpipe(iindex, 0);	/* pass style to next copy */
+
+  /* Fork off an ancestor if necessary - ffork() increments pnum */
+  if (pnum == -1) {
+	pnum = 0;
+	if (pnum == 0) ffork();
+	if (pnum == 1) ffork();
+	if (pnum == 2) ffork();
+	if (pnum == 3) ffork();
+  }
+
+  /* Preliminary inits. Note: end/maxend/curend are highest, not
+   * highest + 1 */
+  base = DICTSZ * pnum + 256;
+  locend = base + DICTSZ - 1;
+  maxend = (1 << maxbits) - 1;
+  if (maxend > locend) maxend = locend;
+
+  while (TRUE) {
+	curend = 255 + (clearflg ? 1 : 0);	/* init dictionary */
+	dcharp = DICTSZ;	/* flag for none needed */
+	curbits = 9;		/* init curbits (for copy 0) */
+	while (TRUE) {		/* for each index in input */
+		if (pnum == 4) {/* get index using getbits() */
+			if (curbits < maxbits && (1 << curbits) <= curend) {
+				/* Curbits needs to be increased */
+				/* Due to uglyness in compress, these
+				 * indices in the compressed file are
+				 * wasted */
+				while (inmod) getbits();
+				curbits++;
+			}
+			getbits();
+		} else
+			getpipe();	/* get next index */
+
+		if (iindex == 256 && clearflg) {
+			if (pnum > 0) putpipe(iindex, 0);
+			/* Due to uglyness in compress, these indices
+			 * in the compressed file are wasted */
+			while (inmod) getbits();
+			break;
+		}
+		tindex = iindex;
+		/* Convert the index part, ignoring spawned chars */
+		while (tindex >= base) tindex = dindex[tindex - base];
+		/* Pass on the index */
+		putpipe(tindex, 0);
+		/* Save the char of the last added entry, if any */
+		if (dcharp < DICTSZ) dchar[dcharp++] = tindex;
+		if (curend < maxend && ++curend > (base - 1))
+			dindex[dcharp = (curend - base)] = iindex;
+
+		/* Do spawned chars. They are naturally produced in
+		 * the wrong order. To get them in the right order
+		 * without using memory, a series of passes,
+		 * progressively less deep, are used */
+		tbase = base;
+		while ((tindex = iindex) >= tbase) {/* for each char to spawn*/
+			while ((tindex2 = dindex[tindex - base]) >= tbase)
+				tindex = tindex2;    /* scan to desired char */
+			putpipe(dchar[tindex-base], 1); /* put it to the pipe*/
+			tbase = tindex + 1;
+			if (tbase == 0) break;	/* it's a wrap */
+		}
+	}
+  }
+}
+
+
+/* F f o r k
+ *
+ * Fork off the previous pass - the parent reads from the child.
+ */
+void ffork()
+{
+  int j, pfd[2];
+
+  if (pipe(pfd) == -1) die("pipe() error\n");
+  if ((j = fork()) == -1) die("fork() error\n");
+  if (j == 0) {			/* this is the child */
+	if (close(1) == -1) die("close(1) error\n");
+	if (dup(pfd[1]) != 1) die("dup(1) error\n");
+	(void) close(pfd[0]);
+	pnum++;
+  } else {			/* this is the parent */
+	if (close(0) == -1) die("close(0) error\n");
+	if (dup(pfd[0]) != 0) die("dup(0) error\n");
+	(void) close(pfd[1]);
+  }
+}
+
+
+/* D i e
+ *
+ * If s is a message, write it to stderr. Flush buffers if needed. Then exit.
+ */
+void die(s)
+char *s;
+{
+  /* Flush stdout buffer if needed */
+  if (obufind != 0) {
+	if (write(fdout, (char *) obuf, (unsigned) obufind) != obufind)
+		s = "bad stdout write\n";
+	obufind = 0;
+  }
+
+  /* Flush pipe if needed */
+  do
+	putpipe(EOF_INDEX, 0);
+  while (opbufind);
+  /* Write any error message */
+  if (s != (char *) NULL) {
+	while (*s) (void) write(fderr, s++, 1);
+  }
+  exit((s == (char *) NULL) ? 0 : 1);
+}
+
+
+/* M p u t c
+ *
+ * Put a char to stdout.
+ */
+void myputc(c)
+unsigned c;
+{
+  obuf[obufind++] = c;
+  if (obufind >= BUFSZ) {	/* if stdout buffer full */
+	if (write(fdout, (char *) obuf, BUFSZ) != BUFSZ)	/* flush to stdout */
+		die("bad stdout write\n");
+	obufind = 0;
+  }
+}
+
+
+/* M y g e t c
+ *
+ * Get a char from stdin. If EOF, then die() and exit.
+ */
+unsigned mygetc()
+{
+  if (ibufstart >= ibufend) {	/* if stdin buffer empty */
+	if ((ibufend = read(fdin, (char *) ibuf, BUFSZ)) <= 0)
+		die((char *) NULL);	/* if EOF, do normal exit */
+	ibufstart = 0;
+  }
+  return(ibuf[ibufstart++] & 0xff);
+}
+
+
+/* G e t b i t s
+ *
+ * Put curbits bits into index from stdin. Note: only copy 4 uses this.
+ * The bits within a byte are in the correct order. But when the bits
+ * cross a byte boundry, the lowest bits will be in the higher part of
+ * the current byte, and the higher bits will be in the lower part of
+ * the next byte.
+ */
+void getbits()
+{
+  int have;
+  static unsigned curbyte;	/* byte having bits extracted from it */
+  static int left;		/* how many bits are left in curbyte */
+
+  inmod = (inmod + 1) & 7;	/* count input mod 8 */
+  iindex = curbyte;
+  have = left;
+  if (curbits - have > 8) {
+	iindex |= mygetc() << have;
+	have += 8;
+  }
+  iindex |= ((curbyte = mygetc()) << have) & ~((unsigned) 0xFFFF << curbits);
+  curbyte >>= curbits - have;
+  left = 8 - (curbits - have);
+}
+
+
+/* G e t p i p e
+ *
+ * Get an index from the pipeline. If flagged firstonly, handle it here.
+ */
+void getpipe()
+{
+  static short flags;
+  static int n = 0;		/* number of flags in flags */
+
+  while (TRUE) {		/* while index with firstonly flag set */
+	if (n <= 0) {
+		if (ipbufind >= BUFSZ_2) {	/* if pipe input buffer
+						 * empty */
+			if (read(fdin, (char *) ipbuf, BUFSZ) != BUFSZ)
+				die("bad pipe read\n");
+			ipbufind = 0;
+		}
+		flags = ipbuf[ipbufind++];
+		n = 15;
+	}
+	iindex = ipbuf[ipbufind++];
+	if (iindex > curend)
+		die((iindex == EOF_INDEX) ? (char *) NULL : "invalid data\n");
+	flags <<= 1;
+	n--;
+	/* Assume flags < 0 if highest remaining flag is set */
+	if (flags < 0) {	/* if firstonly flag for index is not set */
+		while (iindex >= base) iindex = dindex[iindex - base];
+		putpipe(iindex, 1);
+	} else
+		return;		/* return with valid non-firstonly index */
+  }
+}
+
+
+/* P u t p i p e
+ *
+ * put an index into the pipeline.
+ */
+void putpipe(u, flag)
+unsigned u;
+int flag;
+{
+  static unsigned short flags, *flagp;
+  static int n = 0;		/* number of flags in flags */
+
+  if (pnum == 0) {		/* if we should write to stdout */
+	myputc(u);		/* index will be the char value */
+	return;
+  }
+  if (n == 0) {			/* if we need to reserve a flag entry */
+	flags = 0;
+	flagp = opbuf + opbufind;
+	opbufind++;
+  }
+  opbuf[opbufind++] = u;	/* add index to buffer */
+  flags = (flags << 1) | flag;	/* add firstonly flag */
+  if (++n >= 15) {		/* if block of 15 indices */
+	n = 0;
+	*flagp = flags;		/* insert flags entry */
+	if (opbufind >= BUFSZ_2) {	/* if pipe out buffer full */
+		opbufind = 0;
+		if (write(fdout, (char *) opbuf, BUFSZ) != BUFSZ)
+			die("bad pipe write\n");
+	}
+  }
+}
Index: /trunk/minix/commands/simple/dev2name.c
===================================================================
--- /trunk/minix/commands/simple/dev2name.c	(revision 9)
+++ /trunk/minix/commands/simple/dev2name.c	(revision 9)
@@ -0,0 +1,54 @@
+
+/* Translate internal FS device number to a /dev/ name. */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <minix/config.h>
+#include <minix/const.h>
+
+#define PATH_DEV "/dev"
+
+int
+main(int argc, char *argv[])
+{
+	DIR *dev;
+	struct dirent *e;
+	int dev_n;
+	if(argc <= 1 || argc > 3) {
+		fprintf(stderr, "Usage: \n"
+			"%s <major> <minor>\n"
+			"%s <devicenumber>\n", argv[0], argv[0]);
+		return 1;
+	} else if(argc == 2) dev_n = atoi(argv[1]);
+	else if(argc == 3) dev_n = (atoi(argv[1]) << MAJOR) | atoi(argv[2]);
+
+	if(chdir(PATH_DEV) < 0) {
+		perror(PATH_DEV " chdir");
+		return 1;
+	}
+
+	if(!(dev=opendir("."))) {
+		perror(". in " PATH_DEV);
+		return 1;
+	}
+
+	while((e=readdir(dev))) {
+		struct stat st;
+		if(stat(e->d_name, &st) < 0) {
+			continue;
+		}
+		if((st.st_mode & (S_IFBLK | S_IFCHR)) && dev_n == st.st_rdev) {
+			printf("%s/%s\n", PATH_DEV, e->d_name);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
Index: /trunk/minix/commands/simple/devsize.c
===================================================================
--- /trunk/minix/commands/simple/devsize.c	(revision 9)
+++ /trunk/minix/commands/simple/devsize.c	(revision 9)
@@ -0,0 +1,57 @@
+/* Ben Gras
+ *
+ * Based on sizeup() in mkfs.c.
+ */
+
+#include <sys/types.h>
+#include <sys/dir.h>
+#include <sys/stat.h>
+#include <ibm/partition.h>
+#include <minix/partition.h>
+#include <minix/u64.h>
+#include <sys/ioc_disk.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+unsigned long sizeup(char *);
+
+int main(int argc, char *argv[])
+{
+  int sec;
+
+  if(argc != 2) {
+	fprintf(stderr, "Usage: %s <device>\n", argv[0]);
+	return 1;
+  }
+
+  printf("%lu\n", sizeup(argv[1]));
+  return 0;
+}	
+
+
+unsigned long sizeup(device)
+char *device;
+{
+  int fd;
+  struct partition entry;
+  unsigned long d;
+  struct stat st;
+
+  if ((fd = open(device, O_RDONLY)) == -1) {
+  	perror("sizeup open");
+  	exit(1);
+  }
+  if (ioctl(fd, DIOCGETP, &entry) == -1) {
+  	perror("sizeup ioctl");
+  	exit(1);
+  }
+  close(fd);
+  d = div64u(entry.size, 512);
+  return d;
+}
Index: /trunk/minix/commands/simple/df.c
===================================================================
--- /trunk/minix/commands/simple/df.c	(revision 9)
+++ /trunk/minix/commands/simple/df.c	(revision 9)
@@ -0,0 +1,442 @@
+/* df - disk free block printout	Author: Andy Tanenbaum
+ *
+ * 91/04/30 Kees J. Bot (kjb@cs.vu.nl)
+ *	Map filename arguments to the devices they live on.
+ *	Changed output to show percentages.
+ *
+ * 92/12/12 Kees J. Bot
+ *	Posixized.  (Almost, the normal output is in kilobytes, it should
+ *	be 512-byte units.  'df -P' and 'df -kP' are as it should be.)
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#if __minix_vmd
+#include <sys/mnttab.h>
+#else
+#include <minix/minlib.h>
+#endif
+
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include <servers/fs/const.h>
+#include <servers/fs/type.h>
+#include <servers/fs/super.h>
+#undef printf
+
+#if !__minix_vmd
+/* Map Minix-vmd names to Minix names. */
+#define v12_super_block		super_block
+#define SUPER_V1		SUPER_MAGIC
+
+#endif
+
+#define ISDISK(mode)	S_ISBLK(mode)	/* || S_ISCHR for raw device??? */
+
+extern int errno;
+char MTAB[] = "/etc/mtab";
+
+struct mtab {	/* List of mounted devices from /etc/mtab. */
+	struct mtab	*next;
+	dev_t		device;
+	char		*devname;
+	char		*mountpoint;
+} *mtab= NULL;
+
+struct mtab *searchtab(char *name);
+void readmtab(char *type);
+int df(const struct mtab *mt);
+bit_t bit_count(unsigned blocks, bit_t bits, int fd, int bs);
+
+int iflag= 0;	/* Focus on inodes instead of blocks. */
+int Pflag= 0;	/* Posix standard output. */
+int kflag= 0;	/* Output in kilobytes instead of 512 byte units for -P. */
+int istty;	/* isatty(1) */
+uid_t ruid, euid;	/* To sometimes change identities. */
+gid_t rgid, egid;
+
+void usage(void)
+{
+	fprintf(stderr, "Usage: df [-ikP] [-t type] [device]...\n");
+	exit(1);
+}
+
+int unitsize;
+
+int main(int argc, char *argv[])
+{
+  int i;
+  struct mtab *mt;
+  char *type= "dev";
+  int ex= 0;
+
+  while (argc > 1 && argv[1][0] == '-') {
+  	char *opt= argv[1]+1;
+
+  	while (*opt != 0) {
+  		switch (*opt++) {
+  		case 'i':	iflag= 1;	break;
+  		case 'k':	kflag= 1;	break;
+  		case 'P':	Pflag= 1;	break;
+  		case 't':
+			if (argc < 3) usage();
+			type= argv[2];
+			argv++;
+			argc--;
+			break;
+		default:
+			usage();
+		}
+	}
+	argc--;
+	argv++;
+  }
+
+  istty= isatty(1);
+  ruid= getuid(); euid= geteuid();
+  rgid= getgid(); egid= getegid();
+
+  readmtab(type);
+ 
+  if(!Pflag || (Pflag && kflag)) unitsize = 1024;
+  else unitsize = 512;
+
+  if (Pflag) {
+	printf(!iflag ? "\
+Filesystem    %4d-blocks      Used    Available  Capacity  Mounted on\n" : "\
+Filesystem         Inodes       IUsed      IFree    %%IUsed    Mounted on\n",
+		unitsize);
+  } else {
+	printf("%s\n", !iflag ? "\
+Filesystem      Size (kB)       Free       Used    % Files%   Mounted on" : "\
+Filesystem          Files       Free       Used    % BUsed%   Mounted on"
+	);
+  }
+
+  if (argc == 1) {
+	for (mt= mtab; mt != NULL; mt= mt->next) ex |= df(mt);
+  } else {
+	for (i = 1; i < argc; i++) ex |= df(searchtab(argv[i]));
+  }
+  exit(ex);
+}
+
+void readmtab(char *type)
+/* Turn the mounted file table into a list. */
+{
+  struct mtab **amt= &mtab, *new;
+  struct stat st;
+
+#if __minix_vmd
+  char *devname, *mountpoint;
+  FILE *mtf;
+  struct mnttab mte, look;
+
+  if ((mtf= fopen(MTAB, "r")) == NULL) {
+	fprintf(stderr, "df: can't open %s\n", MTAB);
+	return;
+  }
+
+  look.mnt_special= NULL;
+  look.mnt_mountp= NULL;
+  look.mnt_fstype= type;
+  look.mnt_mntopts= NULL;
+
+  while (getmntany(mtf, &mte, &look) >= 0) {
+  	devname= mte.mnt_special;
+  	mountpoint= mte.mnt_mountp;
+
+		/* Skip bad entries, can't complain about everything. */
+	if (stat(devname, &st) < 0 || !ISDISK(st.st_mode)) continue;
+
+		/* Make new list cell. */
+	if ((new= (struct mtab *) malloc(sizeof(*new))) == NULL
+	  || (new->devname= (char *) malloc(strlen(devname) + 1)) == NULL
+	  || (new->mountpoint= (char *) malloc(strlen(mountpoint) + 1)) == NULL
+	) break;
+
+	new->device= st.st_rdev;
+	strcpy(new->devname, devname);
+	strcpy(new->mountpoint, mountpoint);
+
+	*amt= new;		/* Add the cell to the end. */
+	amt= &new->next;
+	*amt= NULL;
+  }
+  fclose(mtf);
+
+#else /* __minix */
+  char devname[128], mountpoint[128], version[10], rw_flag[10];
+
+  if (load_mtab("df") < 0) exit(1);
+
+  while (get_mtab_entry(devname, mountpoint, version, rw_flag),
+							  devname[0] != 0) {
+	if (strcmp(type, "dev") == 0) {
+		if (strcmp(version, "1") != 0 && strcmp(version, "2") != 0 &&
+		 	strcmp(version, "3"))
+			continue;
+	} else {
+		if (strcmp(type, version) != 0) continue;
+	}
+
+		/* Skip bad entries, can't complain about everything. */
+	if (stat(devname, &st) < 0 || !ISDISK(st.st_mode)) continue;
+
+		/* Make new list cell. */
+	if ((new= (struct mtab *) malloc(sizeof(*new))) == NULL
+	  || (new->devname= (char *) malloc(strlen(devname) + 1)) == NULL
+	  || (new->mountpoint= (char *) malloc(strlen(mountpoint) + 1)) == NULL
+	) break;
+
+	new->device= st.st_rdev;
+	strcpy(new->devname, devname);
+	strcpy(new->mountpoint, mountpoint);
+
+	*amt= new;		/* Add the cell to the end. */
+	amt= &new->next;
+	*amt= NULL;
+  }
+#endif
+}
+
+struct mtab *searchtab(char *name)
+/* See what we can do with a user supplied name, there are five possibilities:
+ * 1. It's a device and it is in the mtab: Return mtab entry.
+ * 2. It's a device and it is not in the mtab: Return device mounted on "".
+ * 3. It's a file and lives on a device in the mtab: Return mtab entry.
+ * 4. It's a file and it's not on an mtab device: Search /dev for the device
+ *    and return this device as mounted on "???".
+ * 5. It's junk: Return something df() will choke on.
+ */
+{
+  static struct mtab unknown;
+  static char devname[5 + NAME_MAX + 1]= "/dev/";
+  struct mtab *mt;
+  struct stat st;
+  DIR *dp;
+  struct dirent *ent;
+
+  unknown.devname= name;
+  unknown.mountpoint= "";
+
+  if (stat(name, &st) < 0) return &unknown;	/* Case 5. */
+
+  unknown.device= ISDISK(st.st_mode) ? st.st_rdev : st.st_dev;
+
+  for (mt= mtab; mt != NULL; mt= mt->next) {
+	if (unknown.device == mt->device)
+		return mt;			/* Case 1 & 3. */
+  }
+
+  if (ISDISK(st.st_mode)) {
+	return &unknown;			/* Case 2. */
+  }
+
+  if ((dp= opendir("/dev")) == NULL) return &unknown;	/* Disaster. */
+
+  while ((ent= readdir(dp)) != NULL) {
+	if (ent->d_name[0] == '.') continue;
+	strcpy(devname + 5, ent->d_name);
+	if (stat(devname, &st) >= 0 && ISDISK(st.st_mode)
+		&& unknown.device == st.st_rdev
+	) {
+		unknown.devname= devname;
+		unknown.mountpoint= "???";
+		break;
+	}
+  }
+  closedir(dp);
+  return &unknown;				/* Case 4. */
+}
+
+/* (num / tot) in percentages rounded up. */
+#define percent(num, tot)  ((int) ((100L * (num) + ((tot) - 1)) / (tot)))
+
+/* One must be careful printing all these _t types. */
+#define L(n)	((long) (n))
+
+int df(const struct mtab *mt)
+{
+  int fd;
+  bit_t i_count, z_count;
+  block_t totblocks, busyblocks;
+  int n, block_size;
+  struct v12_super_block super, *sp;
+
+  /* Don't allow Joe User to df just any device. */
+  seteuid(*mt->mountpoint == 0 ? ruid : euid);
+  setegid(*mt->mountpoint == 0 ? rgid : egid);
+
+  if ((fd = open(mt->devname, O_RDONLY)) < 0) {
+	fprintf(stderr, "df: %s: %s\n", mt->devname, strerror(errno));
+	return(1);
+  }
+  lseek(fd, (off_t) SUPER_BLOCK_BYTES, SEEK_SET);	/* skip boot block */
+
+  if (read(fd, (char *) &super, sizeof(super)) != (int) sizeof(super)) {
+	fprintf(stderr, "df: Can't read super block of %s\n", mt->devname);
+	close(fd);
+	return(1);
+  }
+
+  sp = &super;
+  if (sp->s_magic != SUPER_V1 && sp->s_magic != SUPER_V2
+      && sp->s_magic != SUPER_V3) {
+	fprintf(stderr, "df: %s: Not a valid file system\n", mt->devname);
+	close(fd);
+	return(1);
+  }
+
+  if(sp->s_magic != SUPER_V3) block_size = _STATIC_BLOCK_SIZE;
+  else block_size = super.s_block_size;
+
+  if(block_size < _MIN_BLOCK_SIZE || block_size > _MAX_BLOCK_SIZE) {
+	fprintf(stderr, "df: %s: funny block size (%d)\n",
+		mt->devname, block_size);
+	close(fd);
+	return(1);
+  }
+
+  if (sp->s_magic == SUPER_V1) sp->s_zones= sp->s_nzones;
+
+  lseek(fd, (off_t) block_size * 2L, SEEK_SET);	/* skip rest of super block */
+
+  i_count = bit_count(sp->s_imap_blocks, (bit_t) (sp->s_ninodes+1),
+  	fd, block_size);
+
+  if (i_count == -1) {
+	fprintf(stderr, "df: Can't find bit maps of %s\n", mt->devname);
+	close(fd);
+	return(1);
+  }
+  i_count--;	/* There is no inode 0. */
+
+  /* The first bit in the zone map corresponds with zone s_firstdatazone - 1
+   * This means that there are s_zones - (s_firstdatazone - 1) bits in the map
+   */
+  z_count = bit_count(sp->s_zmap_blocks,
+	(bit_t) (sp->s_zones - (sp->s_firstdatazone - 1)), fd, block_size);
+
+  if (z_count == -1) {
+	fprintf(stderr, "df: Can't find bit maps of %s\n", mt->devname);
+	close(fd);
+	return(1);
+  }
+  /* Don't forget those zones before sp->s_firstdatazone - 1 */
+  z_count += sp->s_firstdatazone - 1;
+
+#ifdef __minix_vmd
+  totblocks = sp->s_zones;
+  busyblocks = z_count;
+#else
+  totblocks = (block_t) sp->s_zones << sp->s_log_zone_size;
+  busyblocks = (block_t) z_count << sp->s_log_zone_size;
+#endif
+
+  busyblocks = busyblocks * (block_size/512) / (unitsize/512);
+  totblocks = totblocks * (block_size/512) / (unitsize/512);
+
+  /* Print results. */
+  printf("%s", mt->devname);
+  n= strlen(mt->devname);
+  if (n > 15 && istty) { putchar('\n'); n= 0; }
+  while (n < 15) { putchar(' '); n++; }
+
+  if (!Pflag && !iflag) {
+	printf(" %9ld  %9ld  %9ld %3d%%   %3d%%   %s\n",
+		L(totblocks),				/* Blocks */
+		L(totblocks - busyblocks),		/* free */
+		L(busyblocks),				/* used */
+		percent(busyblocks, totblocks),		/* % */
+		percent(i_count, sp->s_ninodes),	/* FUsed% */
+		mt->mountpoint				/* Mounted on */
+	);
+  }
+  if (!Pflag && iflag) {
+	printf(" %9ld  %9ld  %9ld %3d%%   %3d%%   %s\n",
+		L(sp->s_ninodes),			/* Files */
+		L(sp->s_ninodes - i_count),		/* free */
+		L(i_count),				/* used */
+		percent(i_count, sp->s_ninodes),	/* % */
+		percent(busyblocks, totblocks),		/* BUsed% */
+		mt->mountpoint				/* Mounted on */
+	);
+  }
+  if (Pflag && !iflag) {
+	printf(" %9ld   %9ld  %9ld     %4d%%    %s\n",
+		L(totblocks),				/* Blocks */
+		L(busyblocks),				/* Used */
+		totblocks - busyblocks,			/* Available */
+		percent(busyblocks, totblocks),		/* Capacity */
+		mt->mountpoint				/* Mounted on */
+	);
+  }
+  if (Pflag && iflag) {
+	printf(" %9ld   %9ld  %9ld     %4d%%    %s\n",
+		L(sp->s_ninodes),			/* Inodes */
+		L(i_count),				/* IUsed */
+		L(sp->s_ninodes - i_count),		/* IAvail */
+		percent(i_count, sp->s_ninodes),	/* Capacity */
+		mt->mountpoint				/* Mounted on */
+	);
+  }
+  close(fd);
+  return(0);
+}
+
+bit_t bit_count(unsigned blocks, bit_t bits, int fd, int block_size)
+{
+  char *wptr;
+  int i, b;
+  bit_t busy;
+  char *wlim;
+  static char buf[_MAX_BLOCK_SIZE];
+  static char bits_in_char[1 << CHAR_BIT];
+
+  /* Precalculate bitcount for each char. */
+  if (bits_in_char[1] != 1) {
+	for (b = (1 << 0); b < (1 << CHAR_BIT); b <<= 1)
+		for (i = 0; i < (1 << CHAR_BIT); i++)
+			if (i & b) bits_in_char[i]++;
+  }
+
+  /* Loop on blocks, reading one at a time and counting bits. */
+  busy = 0;
+  for (i = 0; i < blocks && bits != 0; i++) {
+	if (read(fd, buf, block_size) != block_size) return(-1);
+
+	wptr = &buf[0];
+	if (bits >= CHAR_BIT * block_size) {
+		wlim = &buf[block_size];
+		bits -= CHAR_BIT * block_size;
+	} else {
+		b = bits / CHAR_BIT;	/* whole chars in map */
+		wlim = &buf[b];
+		bits -= b * CHAR_BIT;	/* bits in last char, if any */
+		b = *wlim & ((1 << bits) - 1);	/* bit pattern from last ch */
+		busy += bits_in_char[b];
+		bits = 0;
+	}
+
+	/* Loop on the chars of a block. */
+	while (wptr != wlim)
+		busy += bits_in_char[*wptr++ & ((1 << CHAR_BIT) - 1)];
+  }
+  return(busy);
+}
+
+/*
+ * $PchId: df.c,v 1.7 1998/07/27 18:42:17 philip Exp $
+ */
Index: /trunk/minix/commands/simple/dhrystone.c
===================================================================
--- /trunk/minix/commands/simple/dhrystone.c	(revision 9)
+++ /trunk/minix/commands/simple/dhrystone.c	(revision 9)
@@ -0,0 +1,585 @@
+/* dhrystone - benchmark program */
+
+#define REGISTER
+/*
+ *
+ *	"DHRYSTONE" Benchmark Program
+ *
+ *	Version:	C/1.1, 12/01/84
+ *
+ *	Date:		PROGRAM updated 01/06/86, COMMENTS changed 01/31/87
+ *
+ *	Author:		Reinhold P. Weicker,  CACM Vol 27, No 10, 10/84 pg.1013
+ *			Translated from ADA by Rick Richardson
+ *			Every method to preserve ADA-likeness has been used,
+ *			at the expense of C-ness.
+ *
+ *	Compile:	cc -O dry.c -o drynr			: No registers
+ *			cc -O -DREG=register dry.c -o dryr	: Registers
+ *
+ *	Defines:	Defines are provided for old C compiler's
+ *			which don't have enums, and can't assign structures.
+ *			The time(2) function is library dependant; Most
+ *			return the time in seconds, but beware of some, like
+ *			Aztec C, which return other units.
+ *			The LOOPS define is initially set for 50000 loops.
+ *			If you have a machine with large integers and is
+ *			very fast, please change this number to 500000 to
+ *			get better accuracy.  Please select the way to
+ *			measure the execution time using the TIME define.
+ *			For single user machines, time(2) is adequate. For
+ *			multi-user machines where you cannot get single-user
+ *			access, use the times(2) function.  Be careful to
+ *			adjust the HZ parameter below for the units which
+ *			are returned by your times(2) function.  You can
+ *			sometimes find this in <sys/param.h>.  If you have
+ *			neither time(2) nor times(2), use a stopwatch in
+ *			the dead of the night.
+ *			Use a "printf" at the point marked "start timer"
+ *			to begin your timings. DO NOT use the UNIX "time(1)"
+ *			command, as this will measure the total time to
+ *			run this program, which will (erroneously) include
+ *			the time to malloc(3) storage and to compute the
+ *			time it takes to do nothing.
+ *
+ *	Run:		drynr; dryr
+ *
+ *	Results:	If you get any new machine/OS results, please send to:
+ *
+ *				ihnp4!castor!pcrat!rick
+ *
+ *			and thanks to all that do.
+ *
+ *	Note:		I order the list in increasing performance of the
+ *			"with registers" benchmark.  If the compiler doesn't
+ *			provide register variables, then the benchmark
+ *			is the same for both REG and NOREG.
+ *
+ *	PLEASE:		Send complete information about the machine type,
+ *			clock speed, OS and C manufacturer/version.  If
+ *			the machine is modified, tell me what was done.
+ *			On UNIX, execute uname -a and cc -V to get this info.
+ *
+ *	80x8x NOTE:	80x8x benchers: please try to do all memory models
+ *			for a particular compiler.
+ *
+ *
+ *	The following program contains statements of a high-level programming
+ *	language (C) in a distribution considered representative:
+ *
+ *	assignments			53%
+ *	control statements		32%
+ *	procedure, function calls	15%
+ *
+ *	100 statements are dynamically executed.  The program is balanced with
+ *	respect to the three aspects:
+ *		- statement type
+ *		- operand type (for simple data types)
+ *		- operand access
+ *			operand global, local, parameter, or constant.
+ *
+ *	The combination of these three aspects is balanced only approximately.
+ *
+ *	The program does not compute anything meaningfull, but it is
+ *	syntactically and semantically correct.
+ *
+ */
+
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+
+/* Accuracy of timings and human fatigue controlled by next two lines */
+/*#define LOOPS	50000	*/	/* Use this for slow or 16 bit machines */
+/*#define LOOPS	500000 */	/* Use this for faster machines */
+/*#define LOOPS	(sizeof(int) == 2 ? 50000 : 1000000)*/
+
+/* Seconds to run */
+#define SECONDS	15
+
+/* Compiler dependent options */
+#define	NOENUM			/* Define if compiler has no enum's */
+/* #define NOSTRUCTASSIGN */	/* Define if compiler can't assign structures*/
+
+
+/* Define only one of the next two defines */
+#define TIMES			/* Use times(2) time function */
+/*#define TIME	*/		/* Use time(2) time function */
+
+
+#ifdef TIME
+/* Ganularity of time(2) is of course 1 second */
+#define HZ	1
+#endif
+
+#ifdef TIMES
+/* Define the granularity of your times(2) function */
+/*#define HZ	50	*/	/* times(2) returns 1/50 second (europe?) */
+/*#define HZ	60	*/	/* times(2) returns 1/60 second (most) */
+/*#define HZ	100 	*/	/* times(2) returns 1/100 second (WECo) */
+#endif
+
+/* For compatibility with goofed up version */
+/*#undef GOOF		*/	/* Define if you want the goofed up version */
+
+
+#ifdef GOOF
+char Version[] = "1.0";
+#else
+char Version[] = "1.1";
+#endif
+
+
+#ifdef	NOSTRUCTASSIGN
+#define	structassign(d, s)	memcpy(&(d), &(s), sizeof(d))
+#else
+#define	structassign(d, s)	d = s
+#endif
+
+
+#ifdef	NOENUM
+#define	Ident1	1
+#define	Ident2	2
+#define	Ident3	3
+#define	Ident4	4
+#define	Ident5	5
+typedef int Enumeration;
+#else
+typedef enum {
+  Ident1, Ident2, Ident3, Ident4, Ident5
+} Enumeration;
+#endif
+
+typedef int OneToThirty;
+typedef int OneToFifty;
+typedef char CapitalLetter;
+typedef char String30[31];
+typedef int Array1Dim[51];
+typedef int Array2Dim[51][51];
+
+struct Record {
+  struct Record *PtrComp;
+  Enumeration Discr;
+  Enumeration EnumComp;
+  OneToFifty IntComp;
+  String30 StringComp;
+};
+
+typedef struct Record RecordType;
+typedef RecordType *RecordPtr;
+typedef int boolean;
+
+#ifdef NULL
+#undef NULL
+#endif
+
+#define	NULL		0
+#define	TRUE		1
+#define	FALSE		0
+
+#ifndef REG
+#define	REG
+#endif
+
+
+#ifdef TIMES
+#include <sys/times.h>
+#endif
+
+#ifndef _PROTOTYPE
+#define _PROTOTYPE(fun, args)	fun args
+#endif
+
+_PROTOTYPE(int main, (void));
+_PROTOTYPE(void prep_timer, (void));
+_PROTOTYPE(void timeout, (int sig));
+_PROTOTYPE(void Proc0, (void));
+_PROTOTYPE(void Proc1, (RecordPtr PtrParIn));
+_PROTOTYPE(void Proc2, (OneToFifty *IntParIO));
+_PROTOTYPE(void Proc3, (RecordPtr *PtrParOut));
+_PROTOTYPE(void Proc4, (void));
+_PROTOTYPE(void Proc5, (void));
+_PROTOTYPE(void Proc6, (Enumeration EnumParIn, Enumeration *EnumParOut));
+_PROTOTYPE(void Proc7, (OneToFifty IntParI1, OneToFifty IntParI2, 
+						OneToFifty *IntParOut));
+_PROTOTYPE(void Proc8, (Array1Dim Array1Par, Array2Dim Array2Par, 
+				OneToFifty IntParI1, OneToFifty IntParI2));
+/*_PROTOTYPE(Enumeration Func1,(CapitalLetter CharPar1, CapitalLetter CharPar2));*/
+_PROTOTYPE(boolean Func2, (String30 StrParI1, String30 StrParI2));
+_PROTOTYPE(boolean Func3, (Enumeration EnumParIn));
+
+_PROTOTYPE(Enumeration Func1, (int CharPar1, int CharPar2));
+
+
+int main()
+{
+  Proc0();
+  return(0);
+}
+
+
+#if __STDC__
+volatile int done;
+#else
+int done;
+#endif
+
+void prep_timer()
+{
+  signal(SIGALRM, timeout);
+  done = 0;
+}
+
+void timeout(sig)
+int sig;
+{
+  done = 1;
+}
+
+/* Package 1  */
+int IntGlob;
+boolean BoolGlob;
+char Char1Glob;
+char Char2Glob;
+Array1Dim Array1Glob;
+Array2Dim Array2Glob;
+RecordPtr PtrGlb;
+RecordPtr PtrGlbNext;
+
+
+void Proc0()
+{
+  OneToFifty IntLoc1;
+  REG OneToFifty IntLoc2;
+  OneToFifty IntLoc3;
+  REG char CharIndex;
+  Enumeration EnumLoc;
+  String30 String1Loc;
+  String30 String2Loc;
+  register unsigned long i;
+  unsigned long starttime;
+  unsigned long benchtime;
+  unsigned long nulltime;
+  unsigned long nullloops;
+  unsigned long benchloops;
+  unsigned long ticks_per_sec;
+#ifdef TIMES
+  struct tms tms;
+#endif
+
+#ifdef HZ
+#define ticks_per_sec	HZ
+#else
+  ticks_per_sec = sysconf(_SC_CLK_TCK);
+#endif
+
+  i = 0;
+  prep_timer();
+
+#ifdef TIME
+  starttime = time((long *) 0);
+#endif
+
+#ifdef TIMES
+  times(&tms);
+  starttime = tms.tms_utime;
+#endif
+
+  alarm(1);
+  while (!done) i++;
+
+#ifdef TIME
+  nulltime = time((long *) 0) - starttime;	/* Computes o'head of loop */
+#endif
+
+#ifdef TIMES
+  times(&tms);
+  nulltime = tms.tms_utime - starttime;	/* Computes overhead of looping */
+#endif
+
+  nullloops = i;
+
+
+  PtrGlbNext = (RecordPtr) malloc(sizeof(RecordType));
+  PtrGlb = (RecordPtr) malloc(sizeof(RecordType));
+  PtrGlb->PtrComp = PtrGlbNext;
+  PtrGlb->Discr = Ident1;
+  PtrGlb->EnumComp = Ident3;
+  PtrGlb->IntComp = 40;
+  strcpy(PtrGlb->StringComp, "DHRYSTONE PROGRAM, SOME STRING");
+#ifndef	GOOF
+  strcpy(String1Loc, "DHRYSTONE PROGRAM, 1'ST STRING");	/* GOOF */
+#endif
+
+  Array2Glob[8][7] = 10;	/* Was missing in published program */
+
+
+/*****************
+-- Start Timer --
+*****************/
+  i = 0;
+  prep_timer();
+
+#ifdef TIME
+  starttime = time((long *) 0);
+#endif
+
+#ifdef TIMES
+  times(&tms);
+  starttime = tms.tms_utime;
+#endif
+
+  alarm(SECONDS);
+  while (!done) {
+	i++;
+	Proc5();
+	Proc4();
+	IntLoc1 = 2;
+	IntLoc2 = 3;
+	strcpy(String2Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
+	EnumLoc = Ident2;
+	BoolGlob = !Func2(String1Loc, String2Loc);
+	while (IntLoc1 < IntLoc2) {
+		IntLoc3 = 5 * IntLoc1 - IntLoc2;
+		Proc7(IntLoc1, IntLoc2, &IntLoc3);
+		++IntLoc1;
+	}
+	Proc8(Array1Glob, Array2Glob, IntLoc1, IntLoc3);
+	Proc1(PtrGlb);
+	for (CharIndex = 'A'; CharIndex <= Char2Glob; ++CharIndex)
+		if (EnumLoc == Func1(CharIndex, 'C'))
+			Proc6(Ident1, &EnumLoc);
+	IntLoc3 = IntLoc2 * IntLoc1;
+	IntLoc2 = IntLoc3 / IntLoc1;
+	IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1;
+	Proc2(&IntLoc1);
+  }
+
+
+/*****************
+-- Stop Timer --
+*****************/
+
+
+#ifdef TIME
+  benchtime = time((long *) 0) - starttime;
+#endif
+
+#ifdef TIMES
+  times(&tms);
+  benchtime = tms.tms_utime - starttime;
+#endif
+  benchloops = i;
+
+  /* Approximately correct benchtime to the nulltime. */
+  benchtime -= nulltime / (nullloops / benchloops);
+
+  printf("Dhrystone(%s) time for %lu passes = %lu.%02lu\n",
+	Version,
+	benchloops, benchtime / ticks_per_sec,
+	benchtime % ticks_per_sec * 100 / ticks_per_sec);
+  printf("This machine benchmarks at %lu dhrystones/second\n",
+	benchloops * ticks_per_sec / benchtime);
+}
+
+
+void Proc1(PtrParIn)
+REG RecordPtr PtrParIn;
+{
+#define	NextRecord	(*(PtrParIn->PtrComp))
+
+
+  structassign(NextRecord, *PtrGlb);
+  PtrParIn->IntComp = 5;
+  NextRecord.IntComp = PtrParIn->IntComp;
+  NextRecord.PtrComp = PtrParIn->PtrComp;
+  Proc3((RecordPtr *)NextRecord.PtrComp);
+  if (NextRecord.Discr == Ident1) {
+	NextRecord.IntComp = 6;
+	Proc6(PtrParIn->EnumComp, &NextRecord.EnumComp);
+	NextRecord.PtrComp = PtrGlb->PtrComp;
+	Proc7(NextRecord.IntComp, 10, &NextRecord.IntComp);
+  } else
+	structassign(*PtrParIn, NextRecord);
+
+
+#undef	NextRecord
+}
+
+
+void Proc2(IntParIO)
+OneToFifty *IntParIO;
+{
+  REG OneToFifty IntLoc;
+  REG Enumeration EnumLoc;
+
+
+  IntLoc = *IntParIO + 10;
+  for (;;) {
+	if (Char1Glob == 'A') {
+		--IntLoc;
+		*IntParIO = IntLoc - IntGlob;
+		EnumLoc = Ident1;
+	}
+	if (EnumLoc == Ident1) break;
+  }
+}
+
+
+void Proc3(PtrParOut)
+RecordPtr *PtrParOut;
+{
+  if (PtrGlb != NULL)
+	*PtrParOut = PtrGlb->PtrComp;
+  else
+	IntGlob = 100;
+  Proc7(10, IntGlob, &PtrGlb->IntComp);
+}
+
+
+void Proc4()
+{
+  REG boolean BoolLoc;
+
+
+  BoolLoc = Char1Glob == 'A';
+  BoolLoc |= BoolGlob;
+  Char2Glob = 'B';
+}
+
+
+void Proc5()
+{
+  Char1Glob = 'A';
+  BoolGlob = FALSE;
+}
+
+
+void Proc6(EnumParIn, EnumParOut)
+REG Enumeration EnumParIn;
+REG Enumeration *EnumParOut;
+{
+  *EnumParOut = EnumParIn;
+  if (!Func3(EnumParIn)) *EnumParOut = Ident4;
+  switch (EnumParIn) {
+      case Ident1:	*EnumParOut = Ident1;	break;
+      case Ident2:
+	if (IntGlob > 100)
+		*EnumParOut = Ident1;
+	else
+		*EnumParOut = Ident4;
+	break;
+      case Ident3:	*EnumParOut = Ident2;	break;
+      case Ident4:
+	break;
+      case Ident5:	*EnumParOut = Ident3;
+}
+}
+
+
+void Proc7(IntParI1, IntParI2, IntParOut)
+OneToFifty IntParI1;
+OneToFifty IntParI2;
+OneToFifty *IntParOut;
+{
+  REG OneToFifty IntLoc;
+
+
+  IntLoc = IntParI1 + 2;
+  *IntParOut = IntParI2 + IntLoc;
+}
+
+
+void Proc8(Array1Par, Array2Par, IntParI1, IntParI2)
+Array1Dim Array1Par;
+Array2Dim Array2Par;
+OneToFifty IntParI1;
+OneToFifty IntParI2;
+{
+  REG OneToFifty IntLoc;
+  REG OneToFifty IntIndex;
+
+
+  IntLoc = IntParI1 + 5;
+  Array1Par[IntLoc] = IntParI2;
+  Array1Par[IntLoc + 1] = Array1Par[IntLoc];
+  Array1Par[IntLoc + 30] = IntLoc;
+  for (IntIndex = IntLoc; IntIndex <= (IntLoc + 1); ++IntIndex)
+	Array2Par[IntLoc][IntIndex] = IntLoc;
+  ++Array2Par[IntLoc][IntLoc - 1];
+  Array2Par[IntLoc + 20][IntLoc] = Array1Par[IntLoc];
+  IntGlob = 5;
+}
+
+
+Enumeration Func1(CharPar1, CharPar2)
+CapitalLetter CharPar1;
+CapitalLetter CharPar2;
+{
+  REG CapitalLetter CharLoc1;
+  REG CapitalLetter CharLoc2;
+
+
+  CharLoc1 = CharPar1;
+  CharLoc2 = CharLoc1;
+  if (CharLoc2 != CharPar2)
+	return(Ident1);
+  else
+	return(Ident2);
+}
+
+
+boolean Func2(StrParI1, StrParI2)
+String30 StrParI1;
+String30 StrParI2;
+{
+  REG OneToThirty IntLoc;
+  REG CapitalLetter CharLoc;
+
+
+  IntLoc = 1;
+  while (IntLoc <= 1)
+	if (Func1(StrParI1[IntLoc], StrParI2[IntLoc + 1]) == Ident1) {
+		CharLoc = 'A';
+		++IntLoc;
+	}
+  if (CharLoc >= 'W' && CharLoc <= 'Z') IntLoc = 7;
+  if (CharLoc == 'X')
+	return(TRUE);
+  else {
+	if (strcmp(StrParI1, StrParI2) > 0) {
+		IntLoc += 7;
+		return(TRUE);
+	} else
+		return(FALSE);
+  }
+}
+
+
+boolean Func3(EnumParIn)
+REG Enumeration EnumParIn;
+{
+  REG Enumeration EnumLoc;
+
+
+  EnumLoc = EnumParIn;
+  if (EnumLoc == Ident3) return(TRUE);
+  return(FALSE);
+}
+
+
+#ifdef	NOSTRUCTASSIGN
+memcpy(d, s, l)
+register char *d;
+register char *s;
+register int l;
+{
+  while (l--) *d++ = *s++;
+}
+
+#endif
Index: /trunk/minix/commands/simple/diff.c
===================================================================
--- /trunk/minix/commands/simple/diff.c	(revision 9)
+++ /trunk/minix/commands/simple/diff.c	(revision 9)
@@ -0,0 +1,1254 @@
+/* diff  - print differences between 2 files	  Author: Erik Baalbergen */
+
+/* Poor man's implementation of diff(1) 	- no options available
+* 	- may give more output than other diffs,
+*	  due to the straight-forward algorithm
+* 	- runs out of memory if the differing chunks become too large
+* 	- input line length should not exceed LINELEN; longer lines are
+*	  truncated, while only the first LINELEN characters are compared
+*
+* 	- Bug fixes by Rick Thomas Sept. 1989
+*
+* Please report bugs and suggestions to erikb@cs.vu.nl
+*------------------------------------------------------------------------------
+* Changed diff to conform to POSIX 1003.2 ( Draft 11) by Thomas Brupbacher
+* ( tobr@mw.lpc.ethz.ch).
+*
+* To incorporate the context diff option -c in the program, the source code
+* for the program cdiff has been copied to the end of this program. Only
+* slight modifications for the cdiff code to work within the program diff
+* were made( e.g. main() -> context_diff()).
+*
+* New options:
+* -c, -C n where n=0,1,...:
+*  	produces a context diff as the program cdiff. The default is to
+*  	print 3 lines of context, this value can be changed with -C
+*	( e.g. -C 5 prints five lines of context.)
+* -e :	Prints an ed script, so you can convert <file1> to <file2> with
+*  	the command ed <file1> < `diff -e <file1> <file2>`.
+* -b :	Causes trailing blanks to be ignored and spaces of multiple blanks
+*  	to be reduced to one blank before comparison.
+*-----------------------------------------------------------------------------
+*/
+
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>		/* NAME_MAX for maximal filename length	 */
+#include <string.h>		/* string manipulation			 */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <time.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdio.h>
+
+/* These definitions are needed only to suppress warning messages. */
+#define Nullfp 		((FILE*)0)
+#define Nullch 		((char*)0)
+#define NullStructLine	((struct line *)0)
+
+#define LINELEN 128		/* max line length included in diff	 */
+
+
+#define NOT_SET 0		/* Defines to characterise if a flag 	 */
+#define SET	1		/* is set				 */
+
+ /* Indexes of the warning-message array	 */
+#define EXCLUSIVE_OPTIONS	0
+#define CANNOT_OPEN_FILE	1
+
+ /* Used to define the mode 		 */
+typedef enum {
+  undefined, context, ed_mode
+} MODE;
+
+ /* Global variables for the 'normal' diff part	 */
+char *progname;			/* program name	(on command line)	 */
+int diffs = 0;			/* number of differences		 */
+MODE mode;			/* which mode is used			 */
+int severe_error;		/* nonzero after severe, non-fatal error */
+
+/* The following global variables are used with the -r option:
+ * for every pair of files that are different, a "command line" of the
+ * form "diff <options> <oldfile> <newfile>" is printed before the real
+ * output starts.							 */
+int firstoutput = 1;		/* flag to print one time		 */
+char options_string[10];	/* string to hold command line options 	 */
+char oldfile[PATH_MAX];		/* first file				 */
+char newfile[PATH_MAX];		/* second file				 */
+
+
+ /* Global variables for the command-line options */
+int trim_blanks = NOT_SET;	/* SET if -b specified	 		 */
+int recursive_dir = NOT_SET;	/* SET if -r specified	 		 */
+int context_lines = 3;		/* numbers of lines in a context	 */
+static int offset;		/* offset of the actual line number for -e */
+
+ /* Function prototypes for the functions in this file	 */
+struct f;
+_PROTOTYPE(int main, (int argc, char **argv ));
+_PROTOTYPE(void process_command_line, (int argc, char **argv ));
+_PROTOTYPE(void analyse_input_files, (char *arg1, char *arg2, char *input1, 
+							char *input2 ));
+_PROTOTYPE(void diff, (char *filename1, char *filename2 ));
+_PROTOTYPE(FILE *check_file, (char *name ));
+_PROTOTYPE(void build_option_string, (void ));
+_PROTOTYPE(void fatal_error, (char *fmt, char *s ));
+_PROTOTYPE(void warn, (int number, char *string ));
+_PROTOTYPE(void trimming_blanks, (char *l_text ));
+_PROTOTYPE(char *filename, (char *path_string));
+_PROTOTYPE(struct line *new_line, (int size ));
+_PROTOTYPE(void free_line, (struct line *l ));
+_PROTOTYPE(int equal_line, (struct line *l1, struct line *l2 ));
+_PROTOTYPE(int equal_3, (struct line *l1, struct line *l2 ));
+_PROTOTYPE(struct line *read_line, (FILE *fp ));
+_PROTOTYPE(void advance, (struct f *f ));
+_PROTOTYPE(void aside, (struct f *f, struct line *l ));
+_PROTOTYPE(struct line *next, (struct f *f ));
+_PROTOTYPE(void init_f, (struct f *f, FILE *fp ));
+_PROTOTYPE(void update, (struct f *f, char *s ));
+_PROTOTYPE(void __diff, (FILE *fp1, FILE *fp2 ));
+_PROTOTYPE(void differ, (struct f *f1, struct f *f2 ));
+_PROTOTYPE(int wlen, (struct f *f ));
+_PROTOTYPE(void range, (int a, int b ));
+_PROTOTYPE(void cdiff, (char *old, char *new, FILE *file1, FILE *file2 ));
+_PROTOTYPE(void dumphunk, (void ));
+_PROTOTYPE(char *getold, (int targ ));
+_PROTOTYPE(char *getnew, (int targ ));
+_PROTOTYPE(int isdir, (char *path ));
+_PROTOTYPE(void diff_recursive, (char *dir1, char *dir2 ));
+_PROTOTYPE(void file_type_error, (char *filename1, char *filename2, 
+			struct stat *statbuf1, struct stat *statbuf2 ));
+_PROTOTYPE(void *xmalloc, (size_t size));
+_PROTOTYPE(void *xrealloc, (void *ptr, size_t size));
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  char file1[PATH_MAX], file2[PATH_MAX];
+  extern int optind;		/* index of the current string in argv	 */
+
+  progname = argv[0];
+  process_command_line(argc, argv);
+
+  analyse_input_files(argv[optind], argv[optind + 1], file1, file2);
+  optind++;
+
+  if (recursive_dir == SET) {
+	build_option_string();
+	diff_recursive(file1, file2);
+  } else {
+	diff(file1, file2);
+  }
+
+  return(severe_error ? 2 : diffs > 0 ? 1 : 0);
+}
+
+/* Process the command line and set the flags for the different
+ * options. the processing of the command line is done with the
+ * getopt() library function. a minimal error processing is done
+ * for the number of command line arguments.				 */
+void process_command_line(argc, argv)
+int argc;			/* number of arguments on command line	 */
+char **argv;			/* ** to arguments on command line	 */
+{
+  int c;
+  extern char *optarg;		/* points to string with options	 */
+  extern int optind;		/* index of the current string in argv	 */
+
+  /* Are there enough arguments?		 */
+  if (argc < 3) {
+	fatal_error("Usage: %s [-c|-e|-C n][-br] file1 file2\n", progname);
+  }
+
+  /* Process all options using getopt()	 */
+  while ((c = getopt(argc, argv, "ceC:br")) != -1) {
+	switch (c) {
+	    case 'c':
+		if (mode != undefined) warn(EXCLUSIVE_OPTIONS, "c");
+		mode = context;
+		context_lines = 3;
+		break;
+	    case 'e':
+		if (mode != undefined) warn(EXCLUSIVE_OPTIONS, "e");
+		mode = ed_mode;
+		break;
+	    case 'C':
+		if (mode != undefined) warn(EXCLUSIVE_OPTIONS, "C");
+		mode = context;
+		context_lines = atoi(optarg);
+		break;
+	    case 'b':	trim_blanks = SET;	break;
+	    case 'r':	recursive_dir = SET;	break;
+	    case '?':
+		exit(2);
+	}
+  }
+
+  /* We should have two arguments left	 */
+  if ((argc - optind) != 2)
+	fatal_error("Need exactly two input file-names!\n", "");
+}
+
+/* Analyse_input_files takes the two input files on the command line
+ * and decides what to do. returns the (corrected) filenames that
+ * can be used to call diff().
+ * if two directories are given, then a recursive diff is done.
+ * one directory and one filename compares the file with <filename>
+ * in the directory <directory> with <filename>.
+ * if two filenames are specified, no special action takes place.
+ */
+void analyse_input_files(arg1, arg2, input1, input2)
+char *arg1, *arg2;		/* filenames on the command line	 */
+char *input1, *input2;		/* filenames to be used with diff()	 */
+{
+  int stat1 = 0, stat2 = 0;
+
+  if (strcmp(arg1, "-") != 0)
+	stat1 = isdir(arg1);	/* != 0 <-> arg1 is directory		 */
+  if (strcmp(arg2, "-") != 0) stat2 = isdir(arg2);
+#ifdef DEBUG
+  fprintf(stderr, "%s, stat = %d\n", arg1, stat1);
+  fprintf(stderr, "%s, stat = %d\n", arg2, stat2);
+#endif
+  if (stat1 && stat2) {		/* both arg1 and arg2 are directories */
+	recursive_dir = SET;
+	strcpy(input1, arg1);
+	strcpy(input2, arg2);
+	return;
+  }
+  if (stat1 != 0) {		/* arg1 is a dir, arg2 not		 */
+	if (strcmp(arg2, "-") != 0) {	/* arg2 != stdin	 */
+		strcpy(input1, arg1);
+		strcat(input1, "/");
+		strcat(input1, arg2);
+		strcpy(input2, arg2);
+		return;
+	} else {
+		fatal_error("cannot compare stdin (-) with a directory!", "");
+	}
+  }
+  if (stat2 != 0) {		/* arg2 is a dir, arg1 not		 */
+	if (strcmp(arg1, "-") != 0) {	/* arg1 != stdin	 */
+		strcpy(input1, arg1);
+		strcpy(input2, arg2);
+		strcat(input2, "/");
+		strcat(input2, arg1);
+		return;
+	} else {		/* arg1 == stdin			 */
+		fatal_error("cannot compare stdin (-) with a directory!", "");
+	}
+  }
+
+  /* Both arg1 and arg2 are normal  files	 */
+  strcpy(input1, arg1);
+  strcpy(input2, arg2);
+}
+
+/* Diff() is the front end for all modes of the program diff, execpt
+ * the recursive_dir option.
+ * diff() expects the filenames of the two files to be compared as
+ * arguments. the mode is determined from the global variable mode.
+ */
+void diff(filename1, filename2)
+char *filename1, *filename2;
+{
+  FILE *file1 = check_file(filename1);
+  FILE *file2 = check_file(filename2);
+  struct stat statbuf1, statbuf2;
+
+  if ((file1 != Nullfp) && (file2 != Nullfp)) {
+	/* If we do a recursive diff, then we don't compare block
+	 * special, character special or FIFO special files to any
+	 * file.			  */
+	fstat(fileno(file1), &statbuf1);
+	fstat(fileno(file2), &statbuf2);
+	if ((((statbuf1.st_mode & S_IFREG) != S_IFREG) ||
+	     ((statbuf2.st_mode & S_IFREG) != S_IFREG)) &&
+	    (recursive_dir == SET)) {
+		file_type_error(filename1, filename2, &statbuf1, &statbuf2);
+	} else {
+		switch (mode) {
+		    case context:
+			cdiff(filename1, filename2, file1, file2);
+			break;
+		    case ed_mode:
+		    case undefined:
+			__diff(file1, file2);
+			if (mode == ed_mode) printf("w\n");
+			break;
+		}
+	}
+  } else
+	severe_error = 1;
+  if (file1 != Nullfp) fclose(file1);
+  if (file2 != Nullfp) fclose(file2);
+}
+
+/* Check_file() opens the fileptr with name <filename>. if <filename>
+ * equals "-" stdin is associated with the return value.
+ */
+FILE *check_file(name)
+char *name;
+{
+  FILE *temp;
+
+  if (strcmp(name, "-") == 0) {
+	return(stdin);
+  } else {
+	temp = fopen(name, "r");
+	if (temp == Nullfp) warn(CANNOT_OPEN_FILE, name);
+	return(temp);
+  }
+}
+
+/* Build_option_string() is called before recursive_dir() is called
+ * from the main() function. its purpose is to build the string that
+ * is used on the command line to get the current operation mode.
+ * e.g. "-C 6 -b".
+ */
+void build_option_string()
+{
+  switch (mode) {
+	    case ed_mode:sprintf(options_string, "-e");
+	break;
+      case context:
+	if (context_lines == 3)
+		sprintf(options_string, "-c");
+	else
+		sprintf(options_string, "-C %d", context_lines);
+	break;
+  }
+
+}
+
+
+/* The fatal error handler.
+ * Expects a format string and a string as arguments. The arguments
+ * are printed to stderr and the program exits with an error code 2.
+ */
+void fatal_error(fmt, s)
+char *fmt;			/* the format sttring to be printed	 */
+char *s;			/* string to be inserted into the format
+				 * string				 */
+{
+  fprintf(stderr, "%s: ", progname);
+  fprintf(stderr, fmt, s);
+  fprintf(stderr, "\n");
+  exit(2);
+}
+
+/* This function prints non fatal error messages to stderr.
+ * Expects the index of the message to be printed and a pointer
+ * to the (optional) string to be printed.
+ * Returns no value.
+ */
+void warn(number, string)
+int number;			/* index of the warning			 */
+char *string;			/* string to be inserted to the warning	 */
+{
+  static char *warning[] = {
+    "%s: The options -c, -e, -C n are mutually exclusive! Assuming -%c\n",
+    "%s: cannot open file %s for reading\n",
+  };
+  fprintf(stderr, warning[number], progname, string);
+}
+
+/* Function used with the optione -b, trims the blanks in a input line:
+ * - blanks between words are reduced to one
+ * - trailing blanks are eliminated.
+ */
+void trimming_blanks(l_text)
+char *l_text;			/* begin of the char array		 */
+{
+  char *line = l_text;
+  char *copy_to, *copy_from;
+
+  do {
+	if (*line == ' ') {
+		copy_from = line;
+		copy_to = line;
+		while (*(++copy_from) == ' ');
+		if (*copy_from != '\n') copy_to++;
+		while (*copy_from != '\0') *(copy_to++) = *(copy_from++);
+		*copy_to = '\0';
+	}
+  } while (*(++line) != '\0');
+}
+
+
+/* Filename separates the filename and the relative path in path_string.
+ * Returns the filename with a leading /
+ */
+char *filename(path_string)
+char *path_string;
+{
+  char name[NAME_MAX + 2];	/* filename plus /		 	 */
+  char *ptr;
+
+  name[0] = '/';
+  ptr = strrchr(path_string, '/');
+
+  if (ptr == 0) {		/* no / in path_string, only a filename	 */
+	strcat(name, path_string);
+  } else {
+	strcat(name, ptr);
+  }
+
+  return(name);
+}
+
+/* The line module: one member in a linked list of lines. */
+struct line {
+  struct line *l_next;		/* pointer to the next line	 */
+  char l_eof;			/* == 0 if last line in file	 */
+  char *l_text;			/* array with the text		 */
+};
+
+struct line *freelist = 0;
+#define stepup(ll) ( ((ll) && ((ll)->l_eof==0)) ? (ll)->l_next : (ll) )
+
+/* Function to allocate space for a new line containing SIZE chars	*/
+struct line *new_line(size)
+int size;
+{
+  register struct line *l;
+
+  if ((l = freelist) != NullStructLine)
+	freelist = freelist->l_next;
+  else {
+	l = (struct line *) xmalloc(3 * sizeof(void *));
+	l->l_text = (char *) xmalloc((size + 2) * sizeof(char));
+	if ((l == 0) || (l->l_text == 0)) fatal_error("Out of memory", "");
+  }
+  return l;
+}
+
+
+/* Free_line() releases storage allocated for <l>. */
+void free_line(l)
+register struct line *l;
+{
+  l->l_next = freelist;
+  freelist = l;
+}
+
+/* Equal_line() compares two lines, <l1> and <l2>.
+ * the returned value is the result of the strcmp() function.
+ */
+int equal_line(l1, l2)
+struct line *l1, *l2;
+{
+  if (l1 == 0 || l2 == 0)
+	return(0);
+  else if (l1->l_eof || l2->l_eof)
+	return(l1->l_eof == l2->l_eof);
+  else
+	return(strcmp(l1->l_text, l2->l_text) == 0);
+}
+
+int equal_3(l1, l2)
+struct line *l1, *l2;
+{
+  register int i, ansr;
+
+  ansr = 1;
+#ifdef DEBUG
+  if (l1 == 0)
+	fprintf(stderr, "\t(null)\n");
+  else if (l1->l_eof)
+	fprintf(stderr, "\t(eof)\n");
+  else
+	fprintf(stderr, "\t%s", l1->l_text);
+  if (l2 == 0)
+	fprintf(stderr, "\t(null)\n");
+  else if (l2->l_eof)
+	fprintf(stderr, "\t(eof)\n");
+  else
+	fprintf(stderr, "\t%s", l2->l_text);
+#endif
+  for (i = 0; i < 3; ++i) {
+	if (!equal_line(l1, l2)) {
+		ansr = 0;
+		break;
+	}
+	l1 = stepup(l1);
+	l2 = stepup(l2);
+  }
+#ifdef DEBUG
+  fprintf(stderr, "\t%d\n", ansr);
+#endif
+  return(ansr);
+}
+
+struct line *
+ read_line(fp)
+FILE *fp;
+{
+  register struct line *l = new_line(LINELEN);
+  register char *p;
+  register int c;
+
+  (p = &(l->l_text[LINELEN]))[1] = '\377';
+  l->l_eof = 0;
+  if (fgets(l->l_text, LINELEN + 2, fp) == 0) {
+	l->l_eof = 1;
+	l->l_text[0] = 0;
+  } else if ((p[1] & 0377) != 0377 && *p != '\n') {
+	while ((c = fgetc(fp)) != '\n' && c != EOF) {
+	}
+	*p++ = '\n';
+	*p = '\0';
+  }
+  l->l_next = 0;
+  if (trim_blanks == SET) {
+#ifdef DEBUG
+	printf("xxx %s xxx\n", l->l_text);
+#endif
+	trimming_blanks(l->l_text);
+#ifdef DEBUG
+	printf("xxx %s xxx\n", l->l_text);
+#endif
+  }
+  return l;
+}
+
+/* File window handler */
+struct f {
+  struct line *f_bwin, *f_ewin;
+  struct line *f_aside;
+  int f_linecnt;		/* line number in file of last advanced line */
+  FILE *f_fp;
+};
+
+void advance(f)
+register struct f *f;
+{
+  register struct line *l;
+
+  if ((l = f->f_bwin) != NullStructLine) {
+	if (f->f_ewin == l)
+		f->f_bwin = f->f_ewin = 0;
+	else
+		f->f_bwin = l->l_next;
+	free_line(l);
+	(f->f_linecnt)++;
+  }
+}
+
+void aside(f, l)
+struct f *f;
+struct line *l;
+{
+  register struct line *ll;
+
+  if (l == 0) return;
+  if ((ll = l->l_next) != NullStructLine) {
+	while (ll->l_next) ll = ll->l_next;
+	ll->l_next = f->f_aside;
+	f->f_aside = l->l_next;
+	l->l_next = 0;
+	f->f_ewin = l;
+  }
+}
+
+
+struct line *next(f)
+register struct f *f;
+{
+  register struct line *l;
+
+  if ((l = f->f_aside) != NullStructLine) {
+	f->f_aside = l->l_next;
+	l->l_next = 0;
+  } else
+	l = read_line(f->f_fp);
+  if (l) {
+	if (f->f_bwin == 0)
+		f->f_bwin = f->f_ewin = l;
+	else {
+		if (f->f_ewin->l_eof && l->l_eof) {
+			free_line(l);
+			return(f->f_ewin);
+		}
+		f->f_ewin->l_next = l;
+		f->f_ewin = l;
+	}
+  }
+  return l;
+}
+
+
+/* Init_f() initialises a window structure (struct f). <fp> is the
+ * file associated with <f>.
+ */
+void init_f(f, fp)
+register struct f *f;
+FILE *fp;
+{
+  f->f_bwin = f->f_ewin = f->f_aside = 0;
+  f->f_linecnt = 0;
+  f->f_fp = fp;
+}
+
+
+/* Update() prints a window. <f> is a pointer to the window, <s> is the
+ * string containing the "prefix" to the printout( either "<" or ">").
+ * after completion of update(), the window is empty.
+ */
+void update(f, s)
+register struct f *f;
+char *s;
+{
+  char *help;
+  int only_dot = 0;
+
+  if (firstoutput && (recursive_dir == SET)) {
+	printf("diff %s %s %s\n", options_string, oldfile, newfile);
+	firstoutput = 0;
+  }
+  while (f->f_bwin && f->f_bwin != f->f_ewin) {
+	if (mode != ed_mode) {
+		printf("%s%s", s, f->f_bwin->l_text);
+	} else {
+#ifdef DEBUG
+		printf("ed_mode: test for only dot");
+		printf("%s", f->f_bwin->l_text);
+#endif
+		help = f->f_bwin->l_text;
+		while ((*help == ' ') ||
+		       (*help == '.') ||
+		       (*help == '\t')) {
+			if (*(help++) == '.') only_dot++;
+			if (only_dot > 1) break;
+		}
+
+		/* If only_dot is equal 1, there is only one dot on
+		 * the line, so we have to take special actions.
+		 * f the line with only one dot is found, we output
+		 * two dots (".."), terminate the append modus and
+		 * substitute "." for "..". Afterwards we restart
+		 * with the append command.			 */
+		if (*help == '\n' && only_dot == 1) {
+			help = f->f_bwin->l_text;
+			while (*help != '\0') {
+				if (*help == '.') printf(".");
+				putchar((int) *(help++));
+			}
+			printf(".\n");
+			printf(".s/\\.\\././\n");
+			printf("a\n");
+		} else {
+			printf("%s%s", s, f->f_bwin->l_text);
+		}
+	}
+	advance(f);
+  }
+}
+
+/* __Diff(), performs the "core operation" of the program.
+ * Expects two file-pointers as arguments. This functions does
+ * *not* check if the file-pointers are valid.
+ */
+
+void __diff(fp1, fp2)
+FILE *fp1, *fp2;
+{
+  struct f f1, f2;
+  struct line *l1, *s1, *b1, *l2, *s2, *b2;
+  register struct line *ll;
+
+  init_f(&f1, fp1);
+  init_f(&f2, fp2);
+  l1 = next(&f1);
+  l2 = next(&f2);
+  while ((l1->l_eof == 0) || (l2->l_eof == 0)) {
+	if (equal_line(l1, l2)) {
+  equal:
+		advance(&f1);
+		advance(&f2);
+		l1 = next(&f1);
+		l2 = next(&f2);
+		continue;
+	}
+	s1 = b1 = l1;
+	s2 = b2 = l2;
+	/* Read several more lines */
+	next(&f1);
+	next(&f1);
+	next(&f2);
+	next(&f2);
+	/* Start searching */
+search:
+	next(&f2);
+	ll = s1;
+	do {
+		if (equal_3(ll, b2)) {
+			l1 = ll;
+			l2 = b2;
+			aside(&f1, ll);
+			aside(&f2, b2);
+			differ(&f1, &f2);
+			goto equal;
+		}
+		if (ll->l_eof) break;
+		ll = stepup(ll);
+	} while (ll);
+	b2 = stepup(b2);
+
+	next(&f1);
+	ll = s2;
+	do {
+		if (equal_3(b1, ll)) {
+			l1 = b1;
+			l2 = ll;
+			aside(&f2, ll);
+			aside(&f1, b1);
+			differ(&f1, &f2);
+			goto equal;
+		}
+		if (ll->l_eof != 0) break;
+		ll = stepup(ll);
+	} while (ll);
+	b1 = stepup(b1);
+
+	goto search;
+  }
+
+  /* Both of the files reached EOF */
+}
+
+/* Differ() prints the differences between files. the arguments <f1> and
+ * <f2> are pointers to the two windows, where the differences are.
+ */
+void differ(f1, f2)
+register struct f *f1, *f2;
+{
+  int cnt1 = f1->f_linecnt, len1 = wlen(f1);
+  int cnt2 = f2->f_linecnt, len2 = wlen(f2);
+  if ((len1 != 0) || (len2 != 0)) {
+	if (len1 == 0) {
+		if (mode == ed_mode) {
+			cnt1 += offset;
+			printf("%d a\n", cnt1);
+			update(f2, "");
+			printf(".\n");
+			offset += len2;
+		} else {
+			printf("%da", cnt1);
+			range(cnt2 + 1, cnt2 + len2);
+		}
+	} else if (len2 == 0) {
+		if (mode == ed_mode) {
+			cnt1 += offset;
+			range(cnt1 + 1, cnt1 + len1);
+			printf("d\n");
+			offset -= len1;
+			while (f1->f_bwin && f1->f_bwin != f1->f_ewin)
+				advance(f1);
+		} else {
+			range(cnt1 + 1, cnt1 + len1);
+			printf("d%d", cnt2);
+		}
+	} else {
+		if (mode != ed_mode) {
+			range(cnt1 + 1, cnt1 + len1);
+			putchar('c');
+			range(cnt2 + 1, cnt2 + len2);
+		} else {
+			cnt1 += offset;
+			if (len1 == len2) {
+				range(cnt1 + 1, cnt1 + len1);
+				printf("c\n");
+				update(f2, "");
+				printf(".\n");
+			} else {
+				range(cnt1 + 1, cnt1 + len1);
+				printf("d\n");
+				printf("%d a\n", cnt1);
+				update(f2, "");
+				printf(".\n");
+				offset -= len1 - len2;
+			}
+			while (f1->f_bwin && f1->f_bwin != f1->f_ewin)
+				advance(f1);
+		}
+	}
+	if (mode != ed_mode) {
+		putchar('\n');
+		if (len1 != 0) update(f1, "< ");
+		if ((len1 != 0) && (len2 != 0)) printf("---\n");
+		if (len2 != 0) update(f2, "> ");
+	}
+	diffs++;
+  }
+}
+
+
+/* Function wlen() calculates the number of lines in a window. */
+int wlen(f)
+struct f *f;
+{
+  register cnt = 0;
+  register struct line *l = f->f_bwin, *e = f->f_ewin;
+
+  while (l && l != e) {
+	cnt++;
+	l = l->l_next;
+  }
+  return cnt;
+}
+
+
+/* Range() prints the line numbers of a range. the arguments <a> and <b>
+ * are the beginning and the ending line number of the range. if
+ * <a> == <b>, only one line number is printed. otherwise <a> and <b> are
+ * separated by a ",".
+ */
+void range(a, b)
+int a, b;
+{
+  printf(((a == b) ? "%d" : "%d,%d"), a, b);
+}
+
+/* Here follows the code for option -c.
+ * This code is from the cdiff program by Larry Wall. I changed it only
+ * slightly to reflect the POSIX standard and to call the main routine
+ * as function context_diff().
+ */
+
+/* Cdiff - context diff			Author: Larry Wall */
+
+/* These global variables are still here from the original cdiff program...
+ * I was to lazy just to sort them out...
+ */
+char buff[512];
+FILE *oldfp, *newfp;
+
+int oldmin, oldmax, newmin, newmax;
+int oldbeg, oldend, newbeg, newend;
+int preoldmax, prenewmax;
+int preoldbeg, preoldend, prenewbeg, prenewend;
+int oldwanted, newwanted;
+
+char *oldhunk, *newhunk;
+size_t oldsize, oldalloc, newsize, newalloc;
+
+int oldline, newline; /* Jose */
+
+void cdiff(old, new, file1, file2)
+char *old, *new;		/* The names of the two files to be compared */
+FILE *file1, *file2;		/* The corresponding file-pointers	 */
+{
+  FILE *inputfp;
+  struct stat statbuf;
+  register char *s;
+  char op;
+  char *newmark, *oldmark;
+  int len;
+  char *line;
+  int i, status;
+
+  oldfp = file1;
+  newfp = file2;
+
+  oldalloc = 512;
+  oldhunk = (char *) xmalloc(oldalloc);
+  newalloc = 512;
+  newhunk = (char *) xmalloc(newalloc);
+
+
+/* The context diff spawns a new process that executes a normal diff
+ * and parses the output.
+ */
+  if (trim_blanks == SET)
+	sprintf(buff, "diff -b %s %s", old, new);
+  else
+	sprintf(buff, "diff %s %s", old, new);
+
+  inputfp = popen(buff, "r");
+  if (!inputfp) {
+	fprintf(stderr, "Can't execute diff %s %s, popen failed with %s\n",
+		old, new, strerror(errno));
+	exit(2);
+  }
+  preoldend = -1000;
+  firstoutput = 1;
+  oldline = newline = 0;
+  while (fgets(buff, sizeof buff, inputfp) != Nullch) {
+	if (firstoutput) {
+		if (recursive_dir == SET) {
+			printf("diff %s %s %s\n", options_string,
+			       oldfile, newfile);
+		}
+		fstat(fileno(oldfp), &statbuf);
+		printf("*** %s %s", old, ctime(&statbuf.st_mtime));
+		fstat(fileno(newfp), &statbuf);
+		printf("--- %s %s", new, ctime(&statbuf.st_mtime));
+		firstoutput = 0;
+	}
+	if (isdigit(*buff)) {
+		oldmin = atoi(buff);
+		for (s = buff; isdigit(*s); s++);
+		if (*s == ',') {
+			s++;
+			oldmax = atoi(s);
+			for (; isdigit(*s); s++);
+		} else {
+			oldmax = oldmin;
+		}
+		if (*s != 'a' && *s != 'd' && *s != 'c') {
+			fprintf(stderr, "Unparseable input: %s", s);
+			exit(2);
+		}
+		op = *s;
+		s++;
+		newmin = atoi(s);
+		for (; isdigit(*s); s++);
+		if (*s == ',') {
+			s++;
+			newmax = atoi(s);
+			for (; isdigit(*s); s++);
+		} else {
+			newmax = newmin;
+		}
+		if (*s != '\n' && *s != ' ') {
+			fprintf(stderr, "Unparseable input: %s", s);
+			exit(2);
+		}
+		newmark = oldmark = "! ";
+		if (op == 'a') {
+			oldmin++;
+			newmark = "+ ";
+		}
+		if (op == 'd') {
+			newmin++;
+			oldmark = "- ";
+		}
+		oldbeg = oldmin - context_lines;
+		oldend = oldmax + context_lines;
+		if (oldbeg < 1) oldbeg = 1;
+		newbeg = newmin - context_lines;
+		newend = newmax + context_lines;
+		if (newbeg < 1) newbeg = 1;
+
+		if (preoldend < oldbeg - 1) {
+			if (preoldend >= 0) {
+				dumphunk();
+			}
+			preoldbeg = oldbeg;
+			prenewbeg = newbeg;
+			oldwanted = newwanted = 0;
+			oldsize = newsize = 0;
+		} else {	/* we want to append to previous hunk */
+			oldbeg = preoldmax + 1;
+			newbeg = prenewmax + 1;
+		}
+
+		for (i = oldbeg; i <= oldmax; i++) {
+			line = getold(i);
+			if (!line) {
+				oldend = oldmax = i - 1;
+				break;
+			}
+			len = strlen(line) + 2;
+			if (oldsize + len + 1 >= oldalloc) {
+				oldalloc *= 2;
+				oldhunk = (char *) xrealloc(oldhunk, oldalloc);
+			}
+			if (i >= oldmin) {
+				strcpy(oldhunk + oldsize, oldmark);
+				oldwanted++;
+			} else {
+				strcpy(oldhunk + oldsize, "  ");
+			}
+			strcpy(oldhunk + oldsize + 2, line);
+			oldsize += len;
+		}
+		preoldmax = oldmax;
+		preoldend = oldend;
+
+		for (i = newbeg; i <= newmax; i++) {
+			line = getnew(i);
+			if (!line) {
+				newend = newmax = i - 1;
+				break;
+			}
+			len = strlen(line) + 2;
+			if (newsize + len + 1 >= newalloc) {
+				newalloc *= 2;
+				newhunk = (char *) xrealloc(newhunk, newalloc);
+			}
+			if (i >= newmin) {
+				strcpy(newhunk + newsize, newmark);
+				newwanted++;
+			} else {
+				strcpy(newhunk + newsize, "  ");
+			}
+			strcpy(newhunk + newsize + 2, line);
+			newsize += len;
+		}
+		prenewmax = newmax;
+		prenewend = newend;
+	}
+  }
+  status = pclose(inputfp);
+  if (status != 0) diffs++;
+  if (!WIFEXITED(status) || WEXITSTATUS(status) > 1) severe_error = 1;
+
+  if (preoldend >= 0) {
+	dumphunk();
+  }
+}
+
+void dumphunk()
+{
+  int i;
+  char *line;
+  int len;
+
+  for (i = preoldmax + 1; i <= preoldend; i++) {
+	line = getold(i);
+	if (!line) {
+		preoldend = i - 1;
+		break;
+	}
+	len = strlen(line) + 2;
+	if (oldsize + len + 1 >= oldalloc) {
+		oldalloc *= 2;
+		oldhunk = (char *) xrealloc(oldhunk, oldalloc);
+	}
+	strcpy(oldhunk + oldsize, "  ");
+	strcpy(oldhunk + oldsize + 2, line);
+	oldsize += len;
+  }
+  for (i = prenewmax + 1; i <= prenewend; i++) {
+	line = getnew(i);
+	if (!line) {
+		prenewend = i - 1;
+		break;
+	}
+	len = strlen(line) + 2;
+	if (newsize + len + 1 >= newalloc) {
+		newalloc *= 2;
+		newhunk = (char *) xrealloc(newhunk, newalloc);
+	}
+	strcpy(newhunk + newsize, "  ");
+	strcpy(newhunk + newsize + 2, line);
+	newsize += len;
+  }
+  fputs("***************\n", stdout);
+  if (preoldbeg >= preoldend) {
+	printf("*** %d ****\n", preoldend);
+  } else {
+	printf("*** %d,%d ****\n", preoldbeg, preoldend);
+  }
+  if (oldwanted) {
+	fputs(oldhunk, stdout);
+  }
+  oldsize = 0;
+  *oldhunk = '\0';
+  if (prenewbeg >= prenewend) {
+	printf("--- %d ----\n", prenewend);
+  } else {
+	printf("--- %d,%d ----\n", prenewbeg, prenewend);
+  }
+  if (newwanted) {
+	fputs(newhunk, stdout);
+  }
+  newsize = 0;
+  *newhunk = '\0';
+}
+
+char *getold(targ)
+int targ;
+{
+  while (fgets(buff, sizeof buff, oldfp) != Nullch) {
+	oldline++;
+	if (oldline == targ) return buff;
+  }
+  return Nullch;
+}
+
+char *getnew(targ)
+int targ;
+{
+  while (fgets(buff, sizeof buff, newfp) != Nullch) {
+	newline++;
+	if (newline == targ) return buff;
+  }
+  return Nullch;
+}
+
+
+/* Isdir() checks, if <path> is the name of a directory. a return value
+ * is 0, <path> is a normal file. otherwise the <path> is a directory.
+ */
+int isdir(path)
+char *path;
+{
+  struct stat buf;
+  stat(path, &buf);
+  if (buf.st_mode & S_IFDIR) {	/* path is a directory		 */
+	return(~0);
+  } else {
+	return(0);
+  }
+}
+
+
+
+/* This is the "main" function if a diff of two directories has to be
+ * done. diff_recursive() expects the names of the two directories to
+ * be compared. 							 */
+void diff_recursive(dir1, dir2)
+char *dir1, *dir2;
+{
+  FILE *ls1, *ls2;
+  char file1[PATH_MAX], file2[PATH_MAX];
+  char jointfile1[PATH_MAX], jointfile2[PATH_MAX];
+  char command[PATH_MAX];
+  int difference, eof1, eof2;
+
+  sprintf(command, "ls %s", dir1);
+  ls1 = popen(command, "r");
+  sprintf(command, "ls %s", dir2);
+  ls2 = popen(command, "r");
+
+  if ((ls1 == NULL) || (ls2 == NULL))
+	fatal_error("cannot execute ls!", "");
+
+  file1[0] = '\0';
+  eof1 = fscanf(ls1, "%s\n", file1);
+  file2[0] = '\0';
+  eof2 = fscanf(ls2, "%s\n", file2);
+
+  while ((file1[0] != '\0') && (file2[0] != '\0')) {
+	difference = strcmp(file1, file2);
+	while (difference != 0) {
+		if (difference < 0) {
+			printf("Only in %s: %s\n", dir1, file1);
+			file1[0] = '\0';
+			eof1 = fscanf(ls1, "%s\n", file1);
+			if (file1[0] == '\0') break;
+		} else {
+			printf("Only in %s: %s\n", dir2, file2);
+			file2[0] = '\0';
+			eof2 = fscanf(ls2, "%s\n", file2);
+			if (file2[0] == '\0') break;
+		}
+		difference = strcmp(file1, file2);
+	}
+	if (eof1 != EOF && eof2 != EOF) {
+		strcpy(jointfile1, dir1);
+		strcat(jointfile1, "/");
+		strcat(jointfile1, file1);
+		strcpy(jointfile2, dir2);
+		strcat(jointfile2, "/");
+		strcat(jointfile2, file2);
+
+		if ((isdir(jointfile1) != 0) && (isdir(jointfile2) != 0)) {
+			printf("Common subdirectories: %s and %s\n",
+			       jointfile1, jointfile2);
+			diff_recursive(jointfile1, jointfile2);
+		} else {
+			firstoutput = 1;
+			strcpy(oldfile, jointfile1);
+			strcpy(newfile, jointfile2);
+			diff(jointfile1, jointfile2);
+		}
+		file1[0] = '\0';
+		eof1 = fscanf(ls1, "%s\n", file1);
+		file2[0] = '\0';
+		eof2 = fscanf(ls2, "%s\n", file2);
+	}
+  }
+
+  if (file1[0] != '\0') {	/* first arg still has files 		 */
+	do {
+		printf("Only in %s: %s\n", dir1, file1);
+		eof1 = fscanf(ls1, " %s\n", file1);
+	} while (eof1 != EOF);
+  }
+  if (file2[0] != '\0') {
+	do {
+		printf("Only in %s: %s\n", dir2, file2);
+		eof2 = fscanf(ls2, " %s\n", file2);
+	} while (eof2 != EOF);
+  }
+  if (pclose(ls1) != 0) severe_error = 1;
+  if (pclose(ls2) != 0) severe_error = 1;
+}
+
+
+/* File_type_error is called, if in a recursive diff ( -r) one of the two
+ * files a block special, a character special or a FIFO special file is.
+ * The corresponding error message is printed here.			  */
+void file_type_error(filename1, filename2, statbuf1, statbuf2)
+char *filename1, *filename2;
+struct stat *statbuf1, *statbuf2;
+{
+  char type1[25], type2[25];
+
+  switch (statbuf1->st_mode & S_IFMT) {	/* select only file mode */
+      case S_IFREG:
+	sprintf(type1, "regular file ");
+	break;
+      case S_IFBLK:
+	sprintf(type1, "block special file ");
+	break;
+      case S_IFDIR:	sprintf(type1, "directory ");	break;
+      case S_IFCHR:
+	sprintf(type1, "character special file ");
+	break;
+      case S_IFIFO:
+	sprintf(type1, "FIFO special file ");
+	break;
+  }
+
+  switch (statbuf2->st_mode & S_IFMT) {	/* select only file mode */
+      case S_IFREG:
+	sprintf(type2, "regular file ");
+	break;
+      case S_IFBLK:
+	sprintf(type2, "block special file ");
+	break;
+      case S_IFDIR:	sprintf(type2, "directory ");	break;
+      case S_IFCHR:
+	sprintf(type2, "character special file ");
+	break;
+      case S_IFIFO:
+	sprintf(type2, "FIFO special file ");
+	break;
+  }
+  printf("File %s is a %s while file %s is a %s\n",
+         filename1, type1, filename2, type2);
+}
+
+void *xmalloc(size)
+size_t size;
+{
+  void *ptr;
+
+  ptr = malloc(size);
+  if (ptr == NULL) {
+	fprintf(stderr, "%s: out of memory\n", progname);
+	exit(2);
+  }
+  return(ptr);
+}
+
+void *xrealloc(ptr, size)
+void *ptr;
+size_t size;
+{
+  ptr = realloc(ptr, size);
+  if (ptr == NULL) {
+	fprintf(stderr, "%s: out of memory\n", progname);
+	exit(2);
+  }
+  return(ptr);
+}
Index: /trunk/minix/commands/simple/dirname.c
===================================================================
--- /trunk/minix/commands/simple/dirname.c	(revision 9)
+++ /trunk/minix/commands/simple/dirname.c	(revision 9)
@@ -0,0 +1,42 @@
+/* dirname - extract the directory name from a path	Author: Peter Holzer */
+
+/* Dirname -- extract directory part from a path name
+ *
+ * Peter Holzer (hp@vmars.tuwien.ac.at)
+ *
+ * $Log: dirname.c,v $
+ * Revision 1.1.1.1  2005/04/21 14:55:21  beng
+ * Initial import of pre-3.0.1
+ *
+ * Revision 1.1.1.1  2005/04/20 13:33:30  beng
+ * Initial import of minix 2.0.4
+ *
+ * Revision 1.1  1994/02/12  16:15:02  hjp
+ * Initial revision
+ *
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+  char *p;
+  char *path;
+
+  if (argc != 2) {
+	fprintf(stderr, "Usage: %s path\n", argv[0]);
+	return(1);
+  }
+  path = argv[1];
+  p = path + strlen(path);
+  while (p > path && p[-1] == '/') p--;	/* trailing slashes */
+  while (p > path && p[-1] != '/') p--;	/* last component */
+  while (p > path && p[-1] == '/') p--;	/* trailing slashes */
+  if (p == path) {
+	printf(path[0] == '/' ? "/\n" : ".\n");
+  } else {
+	printf("%.*s\n", (int) (p - path), path);
+  }
+  return(0);
+}
Index: /trunk/minix/commands/simple/du.c
===================================================================
--- /trunk/minix/commands/simple/du.c	(revision 9)
+++ /trunk/minix/commands/simple/du.c	(revision 9)
@@ -0,0 +1,254 @@
+/* du - report on disk usage		Author: Alistair G. Crooks */
+
+/*
+ *	du.c		1.1	27/5/87		agc	Joypace Ltd.
+ *			1.2	24 Mar 89	nick@nswitgould.oz
+ *			1.3	31 Mar 89	nick@nswitgould.oz
+ *			1.4	22 Feb 90	meulenbr@cst.prl.philips.nl
+ *			1.5	09 Jul 91	hp@vmars.tuwien.ac.at
+ *			1.6	01 Oct 92	kjb@cs.vu.nl
+ *			1.7	04 Jan 93	bde
+ *			1.8	19 Sep 94	kjb
+ *			1.9	28 Oct 99	kjb
+ *
+ *	Copyright 1987, Joypace Ltd., London UK. All rights reserved.
+ *	This code may be freely distributed, provided that this notice
+ *	remains attached.
+ *
+ *	du - a public domain interpretation of du(1).
+ *
+ *  1.2: 	Fixed bug involving 14 character long filenames
+ *  1.3:	Add [-l levels] option to restrict printing.
+ *  1.4:	Added processing of multiple arguments
+ *  1.5:	Fixed processing of multiple arguments. General cleanup.
+ *  1.6:	Use readdir
+ *  1.7:	Merged 1.5 and 1.6.
+ *		Print totals even for non-dirs at top level.
+ *		Count blocks for each dir before printing total for the dir.
+ *		Count blocks for all non-special files.
+ *		Don't clutter link buffer with directories.
+ *  1.8:	Remember all links.
+ *  1.9:	Added -x flag to not cross device boundaries.  Type fixes.
+ */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <minix/config.h>
+#include <minix/const.h>
+
+extern char *optarg;
+extern int optind;
+
+#define	LINELEN		256
+#define	NR_ALREADY	512
+
+#ifdef S_IFLNK
+#define	LSTAT lstat
+#else
+#define	LSTAT stat
+#endif
+
+typedef struct already {
+  struct already *al_next;
+  int al_dev;
+  ino_t al_inum;
+  nlink_t al_nlink;
+} ALREADY;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(int makedname, (char *d, char *f, char *out, int outlen));
+_PROTOTYPE(int done, (Dev_t dev, Ino_t inum, Nlink_t nlink));
+_PROTOTYPE(long dodir, (char *d, int thislev, Dev_t dev));
+
+char *prog;			/* program name */
+char *optstr = "asxdl:";	/* options */
+int silent = 0;			/* silent mode */
+int all = 0;			/* all directory entries mode */
+int crosschk = 0;		/* do not cross device boundaries mode */
+char *startdir = ".";		/* starting from here */
+int levels = 20000;		/* # of directory levels to print */
+ALREADY *already[NR_ALREADY];
+int alc;
+
+
+/*
+ *	makedname - make the pathname from the directory name, and the
+ *	directory entry, placing it in out. If this would overflow,
+ *	return 0, otherwise 1.
+ */
+int makedname(d, f, out, outlen)
+char *d;
+char *f;
+char *out;
+int outlen;
+{
+  char *cp;
+  int length;
+
+  length = strlen(f);
+  if (strlen(d) + length + 2 > outlen) return(0);
+  for (cp = out; *d; *cp++ = *d++);
+  if (*(cp - 1) != '/') *cp++ = '/';
+  while (length--) *cp++ = *f++;
+  *cp = '\0';
+  return(1);
+}
+
+/*
+ *	done - have we encountered (dev, inum) before? Returns 1 for yes,
+ *	0 for no, and remembers (dev, inum, nlink).
+ */
+int done(dev, inum, nlink)
+dev_t dev;
+ino_t inum;
+nlink_t nlink;
+{
+  register ALREADY **pap, *ap;
+
+  pap = &already[(unsigned) inum % NR_ALREADY];
+  while ((ap = *pap) != NULL) {
+	if (ap->al_inum == inum && ap->al_dev == dev) {
+		if (--ap->al_nlink == 0) {
+			*pap = ap->al_next;
+			free(ap);
+		}
+		return(1);
+	}
+	pap = &ap->al_next;
+  }
+  if ((ap = malloc(sizeof(*ap))) == NULL) {
+	fprintf(stderr, "du: Out of memory\n");
+	exit(1);
+  }
+  ap->al_next = NULL;
+  ap->al_inum = inum;
+  ap->al_dev = dev;
+  ap->al_nlink = nlink - 1;
+  *pap = ap;
+  return(0);
+}
+
+int get_block_size(char *dir, struct stat *st)
+{
+  struct statfs stfs;
+  static int fs_block_size = -1, fs_dev = -1;
+  int d;
+
+  if(st->st_dev == fs_dev)
+  	return fs_block_size;
+
+  if((d = open(dir, O_RDONLY)) < 0) {
+  	perror(dir);
+  	return 0;
+  }
+
+  if(fstatfs(d, &stfs) < 0) {
+  	perror(dir);
+  	return 0;
+  }
+
+  fs_block_size = stfs.f_bsize;
+  fs_dev = st->st_dev;
+
+  return fs_block_size;
+}
+
+
+/*
+ *	dodir - process the directory d. Return the long size (in blocks)
+ *	of d and its descendants.
+ */
+long dodir(d, thislev, dev)
+char *d;
+int thislev;
+dev_t dev;
+{
+  int maybe_print;
+  struct stat s;
+  long total_kb;
+  char dent[LINELEN];
+  DIR *dp;
+  struct dirent *entry;
+  int block_size;
+
+  if (LSTAT(d, &s) < 0) {
+	fprintf(stderr,
+		"%s: %s: %s\n", prog, d, strerror(errno));
+    	return 0L;
+  }
+  if (s.st_dev != dev && dev != 0 && crosschk) return 0;
+  block_size = get_block_size(d, &s);
+  if(block_size < 1) {
+	fprintf(stderr,
+		"%s: %s: funny block size found (%d)\n", 
+			prog, d, block_size);
+    	return 0L;
+  }
+  total_kb = ((s.st_size + (block_size - 1)) / block_size) * block_size / 1024;
+  switch (s.st_mode & S_IFMT) {
+    case S_IFDIR:
+	/* Directories should not be linked except to "." and "..", so this
+	 * directory should not already have been done.
+	 */
+	maybe_print = !silent;
+	if ((dp = opendir(d)) == NULL) break;
+	while ((entry = readdir(dp)) != NULL) {
+		if (strcmp(entry->d_name, ".") == 0 ||
+		    strcmp(entry->d_name, "..") == 0)
+			continue;
+		if (!makedname(d, entry->d_name, dent, sizeof(dent))) continue;
+		total_kb += dodir(dent, thislev - 1, s.st_dev);
+	}
+	closedir(dp);
+	break;
+    case S_IFBLK:
+    case S_IFCHR:
+	/* st_size for special files is not related to blocks used. */
+	total_kb = 0;
+	/* Fall through. */
+    default:
+	if (s.st_nlink > 1 && done(s.st_dev, s.st_ino, s.st_nlink)) return 0L;
+	maybe_print = all;
+	break;
+  }
+  if (thislev >= levels || (maybe_print && thislev >= 0)) {
+	printf("%ld\t%s\n", total_kb, d);
+  }
+  return(total_kb);
+}
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  int c;
+
+  prog = argv[0];
+  while ((c = getopt(argc, argv, optstr)) != EOF) switch (c) {
+	    case 'a':	all = 1;	break;
+	    case 's':	silent = 1;	break;
+	    case 'x':
+	    case 'd':	crosschk = 1;	break;
+	    case 'l':	levels = atoi(optarg);	break;
+	    default:
+		fprintf(stderr,
+			"Usage: %s [-asx] [-l levels] [startdir]\n", prog);
+		exit(1);
+	}
+  do {
+	if (optind < argc) startdir = argv[optind++];
+	alc = 0;
+	(void) dodir(startdir, levels, 0);
+  } while (optind < argc);
+  return(0);
+}
Index: /trunk/minix/commands/simple/ed.c
===================================================================
--- /trunk/minix/commands/simple/ed.c	(revision 9)
+++ /trunk/minix/commands/simple/ed.c	(revision 9)
@@ -0,0 +1,2198 @@
+/* Copyright 1987 Brian Beattie Rights Reserved.
+ *
+ * Permission to copy and/or distribute granted under the
+ * following conditions:
+ *
+ * 1). No charge may be made other than resonable charges
+ *	for reproduction.
+ *
+ * 2). This notice must remain intact.
+ *
+ * 3). No further restrictions may be added.
+ *
+ */
+
+/*	This program used to be in many little pieces, with this makefile:
+.SUFFIXES:	.c .s
+
+CFLAGS = -F
+
+OBJS =	append.s catsub.s ckglob.s deflt.s del.s docmd.s doglob.s\
+  doprnt.s doread.s dowrite.s ed.s egets.s find.s getfn.s getlst.s\
+  getnum.s getone.s getptr.s getrhs.s gettxt.s ins.s join.s maksub.s\
+  move.s optpat.s set.s setbuf.s subst.s getpat.s matchs.s amatch.s\
+  unmkpat.s omatch.s makepat.s bitmap.s dodash.s esc.s System.s
+
+ed:	$(OBJS)
+  cc -T. -i -o ed $(OBJS)
+*/
+
+#include <sys/types.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <stdio.h>
+
+/****************************/
+
+/*	tools.h	*/
+/*
+ *	#defines for non-printing ASCII characters
+ */
+
+#define NUL	0x00		/* ^@ */
+#define EOS	0x00		/* end of string */
+#define SOH	0x01		/* ^A */
+#define STX	0x02		/* ^B */
+#define ETX	0x03		/* ^C */
+#define EOT	0x04		/* ^D */
+#define ENQ	0x05		/* ^E */
+#define ACK	0x06		/* ^F */
+#define BEL	0x07		/* ^G */
+#define BS	0x08		/* ^H */
+#define HT	0x09		/* ^I */
+#define LF	0x0a		/* ^J */
+#define NL	'\n'
+#define VT	0x0b		/* ^K */
+#define FF	0x0c		/* ^L */
+#define CR	0x0d		/* ^M */
+#define SO	0x0e		/* ^N */
+#define SI	0x0f		/* ^O */
+#define DLE	0x10		/* ^P */
+#define DC1	0x11		/* ^Q */
+#define DC2	0x12		/* ^R */
+#define DC3	0x13		/* ^S */
+#define DC4	0x14		/* ^T */
+#define NAK	0x15		/* ^U */
+#define SYN	0x16		/* ^V */
+#define ETB	0x17		/* ^W */
+#define CAN	0x18		/* ^X */
+#define EM	0x19		/* ^Y */
+#define SUB	0x1a		/* ^Z */
+#define ESC	0x1b		/* ^[ */
+#define FS	0x1c		/* ^\ */
+#define GS	0x1d		/* ^] */
+#define RS	0x1e		/* ^^ */
+#define US	0x1f		/* ^_ */
+#define SP	0x20		/* space */
+#define DEL	0x7f		/* DEL */
+
+
+#define TRUE	1
+#define FALSE	0
+#define ERR	-2
+
+
+/*	Definitions of meta-characters used in pattern matching
+ *	routines.  LITCHAR & NCCL are only used as token identifiers;
+ *	all the others are also both token identifier and actual symbol
+ *	used in the regular expression.
+ */
+
+
+#define BOL	'^'
+#define EOL	'$'
+#define ANY	'.'
+#define LITCHAR	'L'
+#define	ESCAPE	'\\'
+#define CCL	'['		/* Character class: [...] */
+#define CCLEND	']'
+#define NEGATE	'^'
+#define NCCL	'!'		/* Negative character class [^...] */
+#define CLOSURE	'*'
+#define OR_SYM	'|'
+#define DITTO	'&'
+#define OPEN	'('
+#define CLOSE	')'
+
+/* Largest permitted size for an expanded character class.  (i.e. the class
+ * [a-z] will expand into 26 symbols; [a-z0-9] will expand into 36.)
+ */
+#define CLS_SIZE	128
+
+/*
+ *	Tokens are used to hold pattern templates. (see makepat())
+ */
+typedef char BITMAP;
+
+typedef struct token {
+  char tok;
+  char lchar;
+  BITMAP *bitmap;
+  struct token *next;
+} TOKEN;
+
+#define TOKSIZE sizeof (TOKEN)
+
+/*
+ *	An absolute maximun for strings.
+ */
+
+#define MAXSTR	132		/* Maximum numbers of characters in a line */
+
+
+/* Macros */
+#define max(a,b)	((a>b)?a:b)
+#define min(a,b)	((a<b)?a:b)
+#define toupper(c)	(c>='a'&&c<='z'?c-32:c)
+
+/*	ed.h	*/
+#define FATAL	(ERR-1)
+struct line {
+  int l_stat;			/* empty, mark */
+  struct line *l_prev;
+  struct line *l_next;
+  char l_buff[1];
+};
+
+typedef struct line LINE;
+
+#define LINFREE	1		/* entry not in use */
+#define LGLOB	2		/* line marked global */
+
+				/* max number of chars per line */
+#define MAXLINE	(sizeof(int) == 2 ? 256 : 8192)
+#define MAXPAT	256		/* max number of chars per replacement
+				 * pattern */
+				/* max file name size */
+#define MAXFNAME (sizeof(int) == 2 ? 256 : 1024)
+
+extern LINE line0;
+extern int curln, lastln, line1, line2, nlines;
+extern int nflg;		/* print line number flag */
+extern int lflg;		/* print line in verbose mode */
+extern char *inptr;		/* tty input buffer */
+extern char linbuf[], *linptr;	/* current line */
+extern int truncflg;		/* truncate long line flag */
+extern int eightbit;		/* save eighth bit */
+extern int nonascii;		/* count of non-ascii chars read */
+extern int nullchar;		/* count of null chars read */
+extern int truncated;		/* count of lines truncated */
+extern int fchanged;		/* file changed */
+
+#define nextln(l)	((l)+1 > lastln ? 0 : (l)+1)
+#define prevln(l)	((l)-1 < 0 ? lastln : (l)-1)
+
+/*	amatch.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(static char *match, (char *lin, TOKEN *pat, char *boln));
+_PROTOTYPE(char *amatch, (char *lin, TOKEN *pat, char *boln));
+_PROTOTYPE(int append, (int line, int glob));
+_PROTOTYPE(BITMAP *makebitmap, (unsigned size));
+_PROTOTYPE(int setbit, (unsigned c, char *map, unsigned val));
+_PROTOTYPE(int testbit, (unsigned c, char *map));
+_PROTOTYPE(char *catsub, (char *from, char *to, char *sub, char *new, char *newend));
+_PROTOTYPE(int ckglob, (void));
+_PROTOTYPE(int deflt, (int def1, int def2));
+_PROTOTYPE(int del, (int from, int to));
+_PROTOTYPE(int docmd, (int glob));
+_PROTOTYPE(int dolst, (int line1, int line2));
+_PROTOTYPE(char *dodash, (int delim, char *src, char *map));
+_PROTOTYPE(int doglob, (void));
+_PROTOTYPE(int doprnt, (int from, int to));
+_PROTOTYPE(void prntln, (char *str, int vflg, int lin));
+_PROTOTYPE(void putcntl, (int c, FILE *stream));
+_PROTOTYPE(int doread, (int lin, char *fname));
+_PROTOTYPE(int dowrite, (int from, int to, char *fname, int apflg));
+_PROTOTYPE(void intr, (int sig));
+_PROTOTYPE(int egets, (char *str, int size, FILE *stream));
+_PROTOTYPE(int esc, (char **s));
+_PROTOTYPE(int find, (TOKEN *pat, int dir));
+_PROTOTYPE(char *getfn, (void));
+_PROTOTYPE(int getlst, (void));
+_PROTOTYPE(int getnum, (int first));
+_PROTOTYPE(int getone, (void));
+_PROTOTYPE(TOKEN *getpat, (char *arg));
+_PROTOTYPE(LINE *getptr, (int num));
+_PROTOTYPE(int getrhs, (char *sub));
+_PROTOTYPE(char *gettxt, (int num));
+_PROTOTYPE(int ins, (char *str));
+_PROTOTYPE(int System, (char *c));
+_PROTOTYPE(int join, (int first, int last));
+_PROTOTYPE(TOKEN *makepat, (char *arg, int delim));
+_PROTOTYPE(char *maksub, (char *sub, int subsz));
+_PROTOTYPE(char *matchs, (char *line, TOKEN *pat, int ret_endp));
+_PROTOTYPE(int move, (int num));
+_PROTOTYPE(int transfer, (int num));
+_PROTOTYPE(int omatch, (char **linp, TOKEN *pat, char *boln));
+_PROTOTYPE(TOKEN *optpat, (void));
+_PROTOTYPE(int set, (void));
+_PROTOTYPE(int show, (void));
+_PROTOTYPE(void relink, (LINE *a, LINE *x, LINE *y, LINE *b));
+_PROTOTYPE(void clrbuf, (void));
+_PROTOTYPE(void set_buf, (void));
+_PROTOTYPE(int subst, (TOKEN *pat, char *sub, int gflg, int pflag));
+_PROTOTYPE(void unmakepat, (TOKEN *head));
+
+/*     Scans throught the pattern template looking for a match
+ * with lin.  Each element of lin is compared with the template
+ * until either a mis-match is found or the end of the template
+ * is reached.  In the former case a 0 is returned; in the latter,
+ * a pointer into lin (pointing to the character following the
+ * matched pattern) is returned.
+ *
+ *	"lin"	is a pointer to the line being searched.
+ *	"pat"	is a pointer to a template made by makepat().
+ *	"boln"	is a pointer into "lin" which points at the
+ *			character at the beginning of the line.
+ */
+
+char *paropen[9], *parclose[9];
+int between, parnum;
+
+char *amatch(lin, pat, boln)
+char *lin;
+TOKEN *pat;
+char *boln;
+{
+  between = 0;
+  parnum = 0;
+
+  lin = match(lin, pat, boln);
+
+  if (between) return 0;
+
+  while (parnum < 9) {
+	paropen[parnum] = parclose[parnum] = "";
+	parnum++;
+  }
+  return lin;
+}
+
+static char *match(lin, pat, boln)
+char *lin;
+TOKEN *pat;
+char *boln;
+{
+  register char *bocl, *rval, *strstart;
+
+  if (pat == 0) return 0;
+
+  strstart = lin;
+
+  while (pat) {
+	if (pat->tok == CLOSURE && pat->next) {
+		/* Process a closure: first skip over the closure
+		 * token to the object to be repeated.  This object
+		 * can be a character class. */
+
+		pat = pat->next;
+
+		/* Now match as many occurrences of the closure
+		 * pattern as possible. */
+		bocl = lin;
+
+		while (*lin && omatch(&lin, pat, boln));
+
+		/* 'Lin' now points to the character that made made
+		 * us fail.  Now go on to process the rest of the
+		 * string.  A problem here is a character following
+		 * the closure which could have been in the closure.
+		 * For example, in the pattern "[a-z]*t" (which
+		 * matches any lower-case word ending in a t), the
+		 * final 't' will be sucked up in the while loop.
+		 * So, if the match fails, we back up a notch and try
+		 * to match the rest of the string again, repeating
+		 * this process recursively until we get back to the
+		 * beginning of the closure.  The recursion goes, at
+		 * most two levels deep. */
+
+		if (pat = pat->next) {
+			int savbtwn = between;
+			int savprnm = parnum;
+
+			while (bocl <= lin) {
+				if (rval = match(lin, pat, boln)) {
+					/* Success */
+					return(rval);
+				} else {
+					--lin;
+					between = savbtwn;
+					parnum = savprnm;
+				}
+			}
+			return(0);	/* match failed */
+		}
+	} else if (pat->tok == OPEN) {
+		if (between || parnum >= 9) return 0;
+		paropen[parnum] = lin;
+		between = 1;
+		pat = pat->next;
+	} else if (pat->tok == CLOSE) {
+		if (!between) return 0;
+		parclose[parnum++] = lin;
+		between = 0;
+		pat = pat->next;
+	} else if (omatch(&lin, pat, boln)) {
+		pat = pat->next;
+	} else {
+		return(0);
+	}
+  }
+
+  /* Note that omatch() advances lin to point at the next character to
+   * be matched.  Consequently, when we reach the end of the template,
+   * lin will be pointing at the character following the last character
+   * matched.  The exceptions are templates containing only a BOLN or
+   * EOLN token.  In these cases omatch doesn't advance.
+   * 
+   * A philosophical point should be mentioned here.  Is $ a position or a
+   * character? (i.e. does $ mean the EOL character itself or does it
+   * mean the character at the end of the line.)  I decided here to
+   * make it mean the former, in order to make the behavior of match()
+   * consistent.  If you give match the pattern ^$ (match all lines
+   * consisting only of an end of line) then, since something has to be
+   * returned, a pointer to the end of line character itself is
+   * returned. */
+
+  return((char *) max(strstart, lin));
+}
+
+/*	append.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+int append(line, glob)
+int line, glob;
+{
+  int stat;
+  char lin[MAXLINE];
+
+  if (glob) return(ERR);
+  curln = line;
+  while (1) {
+	if (nflg) printf("%6d. ", curln + 1);
+
+	if (fgets(lin, MAXLINE, stdin) == NULL) return(EOF);
+	if (lin[0] == '.' && lin[1] == '\n') return (0);
+	stat = ins(lin);
+	if (stat < 0) return(ERR);
+
+  }
+}
+
+/*	bitmap.c	*/
+/*
+ *	BITMAP.C -	makebitmap, setbit, testbit
+ *			bit-map manipulation routines.
+ *
+ *	Copyright (c) Allen I. Holub, all rights reserved.  This program may
+ *		for copied for personal, non-profit use only.
+ *
+ */
+
+#ifdef DEBUG
+/* #include <stdio.h> */
+#endif
+
+/* #include "tools.h" */
+
+
+BITMAP *makebitmap(size)
+unsigned size;
+{
+  /* Make a bit map with "size" bits.  The first entry in the map is an
+   * "unsigned int" representing the maximum bit.  The map itself is
+   * concatenated to this integer. Return a pointer to a map on
+   * success, 0 if there's not enough memory. */
+
+  unsigned *map, numbytes;
+
+  numbytes = (size >> 3) + ((size & 0x07) ? 1 : 0);
+
+#ifdef DEBUG
+  printf("Making a %d bit map (%d bytes required)\n", size, numbytes);
+#endif
+
+  if (map = (unsigned *) malloc(numbytes + sizeof(unsigned))) {
+	*map = size;
+	memset(map + 1, 0, numbytes);
+  }
+
+  return((BITMAP *) map);
+}
+
+int setbit(c, map, val)
+unsigned c, val;
+char *map;
+{
+  /* Set bit c in the map to val. If c > map-size, 0 is returned, else
+   * 1 is returned. */
+
+  if (c >= *(unsigned *) map)	/* if c >= map size */
+	return 0;
+
+  map += sizeof(unsigned);	/* skip past size */
+
+  if (val)
+	map[c >> 3] |= 1 << (c & 0x07);
+  else
+	map[c >> 3] &= ~(1 << (c & 0x07));
+
+  return 1;
+}
+
+int testbit(c, map)
+unsigned c;
+char *map;
+{
+  /* Return 1 if the bit corresponding to c in map is set. 0 if it is not. */
+
+  if (c >= *(unsigned *) map) return 0;
+
+  map += sizeof(unsigned);
+
+  return(map[c >> 3] & (1 << (c & 0x07)));
+}
+
+/*	catsub.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+extern char *paropen[9], *parclose[9];
+
+char *catsub(from, to, sub, new, newend)
+char *from, *to, *sub, *new, *newend;
+{
+  char *cp, *cp2;
+
+  for (cp = new; *sub != EOS && cp < newend;) {
+	if (*sub == DITTO) for (cp2 = from; cp2 < to;) {
+			*cp++ = *cp2++;
+			if (cp >= newend) break;
+		}
+	else if (*sub == ESCAPE) {
+		sub++;
+		if ('1' <= *sub && *sub <= '9') {
+			char *parcl = parclose[*sub - '1'];
+
+			for (cp2 = paropen[*sub - '1']; cp2 < parcl;) {
+				*cp++ = *cp2++;
+				if (cp >= newend) break;
+			}
+		} else
+			*cp++ = *sub;
+	} else
+		*cp++ = *sub;
+
+	sub++;
+  }
+
+  return(cp);
+}
+
+/*	ckglob.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+int ckglob()
+{
+  TOKEN *glbpat;
+  char c, delim;
+  char lin[MAXLINE];
+  int num;
+  LINE *ptr;
+
+  c = *inptr;
+
+  if (c != 'g' && c != 'v') return(0);
+
+  if (deflt(1, lastln) < 0) return(ERR);
+
+  delim = *++inptr;
+  if (delim <= ' ') return(ERR);
+
+  glbpat = optpat();
+
+  if (*inptr == delim) inptr++;
+
+  ptr = getptr(1);
+  for (num = 1; num <= lastln; num++) {
+	ptr->l_stat &= ~LGLOB;
+	if (line1 <= num && num <= line2) {
+		strcpy(lin, ptr->l_buff);
+		strcat(lin, "\n");
+		if (matchs(lin, glbpat, 0)) {
+			if (c == 'g') ptr->l_stat |= LGLOB;
+		} else {
+			if (c == 'v') ptr->l_stat |= LGLOB;
+		}
+	}
+	ptr = ptr->l_next;
+  }
+  return(1);
+}
+
+/*	deflt.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+int deflt(def1, def2)
+int def1, def2;
+{
+  if (nlines == 0) {
+	line1 = def1;
+	line2 = def2;
+  }
+  if (line1 > line2 || line1 <= 0) return(ERR);
+  return(0);
+}
+
+/*	del.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+int del(from, to)
+int from, to;
+{
+  LINE *first, *last, *next, *tmp;
+
+  if (from < 1) from = 1;
+  first = getptr(prevln(from));
+  last = getptr(nextln(to));
+  next = first->l_next;
+  while (next != last && next != &line0) {
+	tmp = next->l_next;
+	free((char *) next);
+	next = tmp;
+  }
+  relink(first, last, first, last);
+  lastln -= (to - from) + 1;
+  curln = prevln(from);
+  return(0);
+}
+
+/*	docmd.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+char fname[MAXFNAME];
+int fchanged;
+extern int nofname;
+
+extern int mark[];
+
+int docmd(glob)
+int glob;
+{
+  static char rhs[MAXPAT];
+  TOKEN *subpat;
+  int c, err, line3;
+  int apflg, pflag, gflag;
+  int nchng;
+  char *fptr;
+
+  pflag = FALSE;
+  while (*inptr == SP && *inptr == HT) inptr++;
+
+  c = *inptr++;
+
+  switch (c) {
+      case NL:
+	if (nlines == 0) {
+		if ((line2 = nextln(curln)) == 0) return(ERR);
+	}
+	curln = line2;
+	return(1);
+	break;
+
+      case '=':	printf("%d\n", line2);	break;
+
+      case 'a':
+	if (*inptr != NL || nlines > 1) return(ERR);
+
+	if (append(line1, glob) < 0) return(ERR);;
+	fchanged = TRUE;
+	break;
+
+      case 'c':
+	if (*inptr != NL) return(ERR);
+
+	if (deflt(curln, curln) < 0) return(ERR);
+
+	if (del(line1, line2) < 0) return(ERR);
+	if (append(curln, glob) < 0) return (ERR);
+	fchanged = TRUE;
+	break;
+
+      case 'd':
+	if (*inptr != NL) return(ERR);
+
+	if (deflt(curln, curln) < 0) return(ERR);
+
+	if (del(line1, line2) < 0) return(ERR);
+	if (nextln(curln) != 0) curln = nextln(curln);
+	fchanged = TRUE;
+	break;
+
+      case 'e':
+	if (nlines > 0) return(ERR);
+	if (fchanged) {
+		fchanged = FALSE;
+		return(ERR);
+	}
+
+	/* FALL THROUGH */
+      case 'E':
+	if (nlines > 0) return(ERR);
+
+	if (*inptr != ' ' && *inptr != HT && *inptr != NL) return(ERR);
+
+	if ((fptr = getfn()) == NULL) return(ERR);
+
+	clrbuf();
+	if ((err = doread(0, fptr)) < 0) return(err);
+
+	strcpy(fname, fptr);
+	fchanged = FALSE;
+	break;
+
+      case 'f':
+	if (nlines > 0) return(ERR);
+
+	if (*inptr != ' ' && *inptr != HT && *inptr != NL) return(ERR);
+
+	if ((fptr = getfn()) == NULL) return(ERR);
+
+	if (nofname)
+		printf("%s\n", fname);
+	else
+		strcpy(fname, fptr);
+	break;
+
+      case 'i':
+	if (*inptr != NL || nlines > 1) return(ERR);
+
+	if (append(prevln(line1), glob) < 0) return(ERR);
+	fchanged = TRUE;
+	break;
+
+      case 'j':
+	if (*inptr != NL || deflt(curln, curln + 1) < 0) return(ERR);
+
+	if (join(line1, line2) < 0) return(ERR);
+	break;
+
+      case 'k':
+	while (*inptr == ' ' || *inptr == HT) inptr++;
+
+	if (*inptr < 'a' || *inptr > 'z') return ERR;
+	c = *inptr++;
+
+	if (*inptr != ' ' && *inptr != HT && *inptr != NL) return(ERR);
+
+	mark[c - 'a'] = line1;
+	break;
+
+      case 'l':
+	if (*inptr != NL) return(ERR);
+	if (deflt(curln, curln) < 0) return (ERR);
+	if (dolst(line1, line2) < 0) return (ERR);
+	break;
+
+      case 'm':
+	if ((line3 = getone()) < 0) return(ERR);
+	if (deflt(curln, curln) < 0) return (ERR);
+	if (move(line3) < 0) return (ERR);
+	fchanged = TRUE;
+	break;
+
+      case 'P':
+      case 'p':
+	if (*inptr != NL) return(ERR);
+	if (deflt(curln, curln) < 0) return (ERR);
+	if (doprnt(line1, line2) < 0) return (ERR);
+	break;
+
+      case 'q':
+	if (fchanged) {
+		fchanged = FALSE;
+		return(ERR);
+	}
+
+	/* FALL THROUGH */
+      case 'Q':
+	if (*inptr == NL && nlines == 0 && !glob)
+		return(EOF);
+	else
+		return(ERR);
+
+      case 'r':
+	if (nlines > 1) return(ERR);
+
+	if (nlines == 0) line2 = lastln;
+
+	if (*inptr != ' ' && *inptr != HT && *inptr != NL) return(ERR);
+
+	if ((fptr = getfn()) == NULL) return(ERR);
+
+	if ((err = doread(line2, fptr)) < 0) return(err);
+	fchanged = TRUE;
+	break;
+
+      case 's':
+	if (*inptr == 'e') return(set());
+	while (*inptr == SP || *inptr == HT) inptr++;
+	if ((subpat = optpat()) == NULL) return (ERR);
+	if ((gflag = getrhs(rhs)) < 0) return (ERR);
+	if (*inptr == 'p') pflag++;
+	if (deflt(curln, curln) < 0) return (ERR);
+	if ((nchng = subst(subpat, rhs, gflag, pflag)) < 0) return (ERR);
+	if (nchng) fchanged = TRUE;
+	break;
+
+      case 't':
+	if ((line3 = getone()) < 0) return(ERR);
+	if (deflt(curln, curln) < 0) return (ERR);
+	if (transfer(line3) < 0) return (ERR);
+	fchanged = TRUE;
+	break;
+
+      case 'W':
+      case 'w':
+	apflg = (c == 'W');
+
+	if (*inptr != ' ' && *inptr != HT && *inptr != NL) return(ERR);
+
+	if ((fptr = getfn()) == NULL) return(ERR);
+
+	if (deflt(1, lastln) < 0) return(ERR);
+	if (dowrite(line1, line2, fptr, apflg) < 0) return (ERR);
+	fchanged = FALSE;
+	break;
+
+      case 'x':
+	if (*inptr == NL && nlines == 0 && !glob) {
+		if ((fptr = getfn()) == NULL) return(ERR);
+		if (dowrite(1, lastln, fptr, 0) >= 0) return (EOF);
+	}
+	return(ERR);
+
+      case 'z':
+	if (deflt(curln, curln) < 0) return(ERR);
+
+	switch (*inptr) {
+	    case '-':
+		if (doprnt(line1 - 21, line1) < 0) return(ERR);
+		break;
+
+	    case '.':
+		if (doprnt(line1 - 11, line1 + 10) < 0) return(ERR);
+		break;
+
+	    case '+':
+	    case '\n':
+		if (doprnt(line1, line1 + 21) < 0) return(ERR);
+		break;
+	}
+	break;
+
+      default:	return(ERR);
+}
+  return(0);
+}
+
+int dolst(line1, line2)
+int line1, line2;
+{
+  int oldlflg = lflg, p;
+
+  lflg = 1;
+  p = doprnt(line1, line2);
+  lflg = oldlflg;
+
+  return p;
+}
+
+/*	dodash.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+
+/*	Expand the set pointed to by *src into dest.
+ *	Stop at delim.  Return 0 on error or size of
+ *	character class on success.  Update *src to
+ *	point at delim.  A set can have one element
+ *	{x} or several elements ( {abcdefghijklmnopqrstuvwxyz}
+ *	and {a-z} are equivalent ).  Note that the dash
+ *	notation is expanded as sequential numbers.
+ *	This means (since we are using the ASCII character
+ *	set) that a-Z will contain the entire alphabet
+ *	plus the symbols: [\]^_`.  The maximum number of
+ *	characters in a character class is defined by maxccl.
+ */
+char *dodash(delim, src, map)
+int delim;
+char *src, *map;
+{
+
+  register int first, last;
+  char *start;
+
+  start = src;
+
+  while (*src && *src != delim) {
+	if (*src != '-') setbit(esc(&src), map, 1);
+
+	else if (src == start || *(src + 1) == delim)
+		setbit('-', map, 1);
+	else {
+		src++;
+
+		if (*src < *(src - 2)) {
+			first = *src;
+			last = *(src - 2);
+		} else {
+			first = *(src - 2);
+			last = *src;
+		}
+
+		while (++first <= last) setbit(first, map, 1);
+
+	}
+	src++;
+  }
+  return(src);
+}
+
+/*	doglob.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+int doglob()
+{
+  int lin, stat;
+  char *cmd;
+  LINE *ptr;
+
+  cmd = inptr;
+
+  while (1) {
+	ptr = getptr(1);
+	for (lin = 1; lin <= lastln; lin++) {
+		if (ptr->l_stat & LGLOB) break;
+		ptr = ptr->l_next;
+	}
+	if (lin > lastln) break;
+
+	ptr->l_stat &= ~LGLOB;
+	curln = lin;
+	inptr = cmd;
+	if ((stat = getlst()) < 0) return(stat);
+	if ((stat = docmd(1)) < 0) return (stat);
+  }
+  return(curln);
+}
+
+/*	doprnt.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+int doprnt(from, to)
+int from, to;
+{
+  int i;
+  LINE *lptr;
+
+  from = from < 1 ? 1 : from;
+  to = to > lastln ? lastln : to;
+
+  if (to != 0) {
+	lptr = getptr(from);
+	for (i = from; i <= to; i++) {
+		prntln(lptr->l_buff, lflg, (nflg ? i : 0));
+		lptr = lptr->l_next;
+	}
+	curln = to;
+  }
+  return(0);
+}
+
+void prntln(str, vflg, lin)
+char *str;
+int vflg, lin;
+{
+  if (lin) printf("%7d ", lin);
+  while (*str && *str != NL) {
+	if (*str < ' ' || *str >= 0x7f) {
+		switch (*str) {
+		    case '\t':
+			if (vflg)
+				putcntl(*str, stdout);
+			else
+				putc(*str, stdout);
+			break;
+
+		    case DEL:
+			putc('^', stdout);
+			putc('?', stdout);
+			break;
+
+		    default:
+			putcntl(*str, stdout);
+			break;
+		}
+	} else
+		putc(*str, stdout);
+	str++;
+  }
+  if (vflg) putc('$', stdout);
+  putc('\n', stdout);
+}
+
+void putcntl(c, stream)
+char c;
+FILE *stream;
+{
+  putc('^', stream);
+  putc((c & 31) | '@', stream);
+}
+
+/*	doread.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+extern int diag;
+
+int doread(lin, fname)
+int lin;
+char *fname;
+{
+  FILE *fp;
+  int err;
+  long bytes;
+  int lines;
+  static char str[MAXLINE];
+
+  err = 0;
+  nonascii = nullchar = truncated = 0;
+
+  if (diag) printf("\"%s\" ", fname);
+  if ((fp = fopen(fname, "r")) == NULL) {
+	printf("file open err\n");
+	return(ERR);
+  }
+  curln = lin;
+  for (lines = 0, bytes = 0; (err = egets(str, MAXLINE, fp)) > 0;) {
+	bytes += strlen(str);
+	if (ins(str) < 0) {
+		printf("file insert error\n");
+		err++;
+		break;
+	}
+	lines++;
+  }
+  fclose(fp);
+  if (err < 0) return(err);
+  if (diag) {
+	printf("%d lines %ld bytes", lines, bytes);
+	if (nonascii) printf(" [%d non-ascii]", nonascii);
+	if (nullchar) printf(" [%d nul]", nullchar);
+	if (truncated) printf(" [%d lines truncated]", truncated);
+	printf("\n");
+  }
+  return(err);
+}
+
+/*	dowrite.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+int dowrite(from, to, fname, apflg)
+int from, to;
+char *fname;
+int apflg;
+{
+  FILE *fp;
+  int lin, err;
+  int lines;
+  long bytes;
+  char *str;
+  LINE *lptr;
+
+  err = 0;
+
+  lines = bytes = 0;
+  if (diag) printf("\"%s\" ", fname);
+  if ((fp = fopen(fname, (apflg ? "a" : "w"))) == NULL) {
+	printf("file open error\n");
+	return(ERR);
+  }
+  lptr = getptr(from);
+  for (lin = from; lin <= to; lin++) {
+	str = lptr->l_buff;
+	lines++;
+	bytes += strlen(str) + 1;
+	if (fputs(str, fp) == EOF) {
+		printf("file write error\n");
+		err++;
+		break;
+	}
+	fputc('\n', fp);
+	lptr = lptr->l_next;
+  }
+  if (diag) printf("%d lines %ld bytes\n", lines, bytes);
+  fclose(fp);
+  return(err);
+}
+
+/*	ed.c	*/
+/* Copyright 1987 Brian Beattie Rights Reserved.
+ *
+ * Permission to copy and/or distribute granted under the
+ * following conditions:
+ *
+ * 1). No charge may be made other than resonable charges
+ *	for reproduction.
+ *
+ * 2). This notice must remain intact.
+ *
+ * 3). No further restrictions may be added.
+ *
+ */
+/* #include <stdio.h> */
+/* #include <signal.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+#include <setjmp.h>
+jmp_buf env;
+
+LINE line0;
+int curln = 0;
+int lastln = 0;
+char *inptr;
+static char inlin[MAXLINE];
+int nflg, lflg;
+int line1, line2, nlines;
+extern char fname[];
+int version = 1;
+int diag = 1;
+
+void intr(sig)
+int sig;
+{
+  printf("?\n");
+  longjmp(env, 1);
+}
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  int stat, i, doflush;
+
+  set_buf();
+  doflush = isatty(1);
+
+  if (argc > 1 && (strcmp(argv[1], "-") == 0 || strcmp(argv[1], "-s") == 0)) {
+	diag = 0;
+	argc--;
+	argv++;
+  }
+  if (argc > 1) {
+	for (i = 1; i < argc; i++) {
+		if (doread(0, argv[i]) == 0) {
+			curln = 1;
+			strcpy(fname, argv[i]);
+			break;
+		}
+	}
+  }
+  while (1) {
+	setjmp(env);
+	if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, intr);
+
+	if (doflush) fflush(stdout);
+
+	if (fgets(inlin, sizeof(inlin), stdin) == NULL) {
+		break;
+	}
+	for (;;) {
+		inptr = strchr(inlin, EOS);
+		if (inptr >= inlin+2 && inptr[-2] == '\\' && inptr[-1] == NL) {
+			inptr[-1] = 'n';
+			if (fgets(inptr, sizeof(inlin) - (inptr - inlin),
+						stdin) == NULL) break;
+		} else {
+			break;
+		}
+	}
+	if (*inlin == '!') {
+		if ((inptr = strchr(inlin, NL)) != NULL) *inptr = EOS;
+		System(inlin + 1);
+		continue;
+	}
+	inptr = inlin;
+	if (getlst() >= 0)
+		if ((stat = ckglob()) != 0) {
+			if (stat >= 0 && (stat = doglob()) >= 0) {
+				curln = stat;
+				continue;
+			}
+		} else {
+			if ((stat = docmd(0)) >= 0) {
+				if (stat == 1) doprnt(curln, curln);
+				continue;
+			}
+		}
+	if (stat == EOF) {
+		exit(0);
+	}
+	if (stat == FATAL) {
+		fputs("FATAL ERROR\n", stderr);
+		exit(1);
+	}
+	printf("?\n");
+  }
+  return(0);
+}
+
+/*	egets.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+int eightbit = 1;		/* save eight bit */
+int nonascii, nullchar, truncated;
+int egets(str, size, stream)
+char *str;
+int size;
+FILE *stream;
+{
+  int c, count;
+  char *cp;
+
+  for (count = 0, cp = str; size > count;) {
+	c = getc(stream);
+	if (c == EOF) {
+		*cp++ = '\n';
+		*cp = EOS;
+		if (count) {
+			printf("[Incomplete last line]\n");
+		}
+		return(count);
+	}
+	if (c == NL) {
+		*cp++ = c;
+		*cp = EOS;
+		return(++count);
+	}
+	if (c > 127) {
+		if (!eightbit)	/* if not saving eighth bit */
+			c = c & 127;	/* strip eigth bit */
+		nonascii++;	/* count it */
+	}
+	if (c) {
+		*cp++ = c;	/* not null, keep it */
+		count++;
+	} else
+		nullchar++;	/* count nulls */
+  }
+  str[count - 1] = EOS;
+  if (c != NL) {
+	printf("truncating line\n");
+	truncated++;
+	while ((c = getc(stream)) != EOF)
+		if (c == NL) break;
+  }
+  return(count);
+}
+
+/*	esc.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+
+/* Map escape sequences into their equivalent symbols.  Returns the
+ * correct ASCII character.  If no escape prefix is present then s
+ * is untouched and *s is returned, otherwise **s is advanced to point
+ * at the escaped character and the translated character is returned.
+ */
+int esc(s)
+char **s;
+{
+  register int rval;
+
+
+  if (**s != ESCAPE) {
+	rval = **s;
+  } else {
+	(*s)++;
+
+	switch (toupper(**s)) {
+	    case '\000':	rval = ESCAPE;	break;
+	    case 'S':	rval = ' ';	break;
+	    case 'N':	rval = '\n';	break;
+	    case 'T':	rval = '\t';	break;
+	    case 'B':	rval = '\b';	break;
+	    case 'R':	rval = '\r';	break;
+	    default:	rval = **s;	break;
+	}
+  }
+
+  return(rval);
+}
+
+/*	find.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+int find(pat, dir)
+TOKEN *pat;
+int dir;
+{
+  int i, num;
+  char lin[MAXLINE];
+  LINE *ptr;
+
+  num = curln;
+  ptr = getptr(curln);
+  num = (dir ? nextln(num) : prevln(num));
+  ptr = (dir ? ptr->l_next : ptr->l_prev);
+  for (i = 0; i < lastln; i++) {
+	if (num == 0) {
+		num = (dir ? nextln(num) : prevln(num));
+		ptr = (dir ? ptr->l_next : ptr->l_prev);
+	}
+	strcpy(lin, ptr->l_buff);
+	strcat(lin, "\n");
+	if (matchs(lin, pat, 0)) {
+		return(num);
+	}
+	num = (dir ? nextln(num) : prevln(num));
+	ptr = (dir ? ptr->l_next : ptr->l_prev);
+  }
+  return(ERR);
+}
+
+/*	getfn.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+extern char fname[MAXFNAME];
+int nofname;
+
+char *getfn()
+{
+  static char file[256];
+  char *cp;
+
+  if (*inptr == NL) {
+	nofname = TRUE;
+	strcpy(file, fname);
+  } else {
+	nofname = FALSE;
+	while (*inptr == SP || *inptr == HT) inptr++;
+
+	cp = file;
+	while (*inptr && *inptr != NL && *inptr != SP && *inptr != HT) {
+		*cp++ = *inptr++;
+	}
+	*cp = '\0';
+
+	if (strlen(file) == 0) {
+		printf("bad file name\n");
+		return(NULL);
+	}
+  }
+
+  if (strlen(file) == 0) {
+	printf("no file name\n");
+	return(NULL);
+  }
+  return(file);
+}
+
+/*	getlst.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+int getlst()
+{
+  int num;
+
+  line2 = 0;
+  for (nlines = 0; (num = getone()) >= 0;) {
+	line1 = line2;
+	line2 = num;
+	nlines++;
+	if (*inptr != ',' && *inptr != ';') break;
+	if (*inptr == ';') curln = num;
+	inptr++;
+  }
+  nlines = min(nlines, 2);
+  if (nlines == 0) line2 = curln;
+  if (nlines <= 1) line1 = line2;
+
+  if (num == ERR)
+	return(num);
+  else
+	return(nlines);
+}
+
+/*	getnum.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+int mark['z' - 'a' + 1];
+
+int getnum(first)
+int first;
+{
+  TOKEN *srchpat;
+  int num;
+  char c;
+
+  while (*inptr == SP || *inptr == HT) inptr++;
+
+  if (*inptr >= '0' && *inptr <= '9') {	/* line number */
+	for (num = 0; *inptr >= '0' && *inptr <= '9';) {
+		num = (num * 10) + *inptr - '0';
+		inptr++;
+	}
+	return num;
+  }
+  switch (c = *inptr) {
+      case '.':
+	inptr++;
+	return(curln);
+
+      case '$':
+	inptr++;
+	return(lastln);
+
+      case '/':
+      case '?':
+	srchpat = optpat();
+	if (*inptr == c) inptr++;
+	return(find(srchpat, c == '/' ? 1 : 0));
+
+      case '-':
+      case '+':
+	return(first ? curln : 1);
+
+      case '\'':
+	inptr++;
+	if (*inptr < 'a' || *inptr > 'z') return(EOF);
+
+	return mark[*inptr++ - 'a'];
+
+      default:
+	return(first ? EOF : 1);/* unknown address */
+  }
+}
+
+/*	getone.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+#define FIRST 1
+#define NOTFIRST 0
+
+int getone()
+{
+  int c, i, num;
+
+  if ((num = getnum(FIRST)) >= 0) {
+	while (1) {
+		while (*inptr == SP || *inptr == HT) inptr++;
+
+		if (*inptr != '+' && *inptr != '-') break;
+		c = *inptr++;
+
+		if ((i = getnum(NOTFIRST)) < 0) return(i);
+
+		if (c == '+') {
+			num += i;
+		} else {
+			num -= i;
+		}
+	}
+  }
+  return(num > lastln ? ERR : num);
+}
+
+/*	getpat.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+
+/* Translate arg into a TOKEN string */
+TOKEN *
+ getpat(arg)
+char *arg;
+{
+
+  return(makepat(arg, '\000'));
+}
+
+/*	getptr.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+LINE *
+ getptr(num)
+int num;
+{
+  LINE *ptr;
+  int j;
+
+  if (2 * num > lastln && num <= lastln) {	/* high line numbers */
+	ptr = line0.l_prev;
+	for (j = lastln; j > num; j--) ptr = ptr->l_prev;
+  } else {			/* low line numbers */
+	ptr = &line0;
+	for (j = 0; j < num; j++) ptr = ptr->l_next;
+  }
+  return(ptr);
+}
+
+/*	getrhs.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+int getrhs(sub)
+char *sub;
+{
+  if (inptr[0] == NL || inptr[1] == NL)	/* check for eol */
+	return(ERR);
+
+  if (maksub(sub, MAXPAT) == NULL) return(ERR);
+
+  inptr++;			/* skip over delimter */
+  while (*inptr == SP || *inptr == HT) inptr++;
+  if (*inptr == 'g') {
+	inptr++;
+	return(1);
+  }
+  return(0);
+}
+
+/*	gettxt.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+char *
+ gettxt(num)
+int num;
+{
+  LINE *lin;
+  static char txtbuf[MAXLINE];
+
+  lin = getptr(num);
+  strcpy(txtbuf, lin->l_buff);
+  strcat(txtbuf, "\n");
+  return(txtbuf);
+}
+
+/*	ins.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+int ins(str)
+char *str;
+{
+  char buf[MAXLINE], *cp;
+  LINE *new, *cur, *nxt;
+
+  cp = buf;
+  while (1) {
+	if ((*cp = *str++) == NL) *cp = EOS;
+	if (*cp) {
+		cp++;
+		continue;
+	}
+	if ((new = (LINE *) malloc(sizeof(LINE) + strlen(buf))) == NULL)
+		return(ERR);	/* no memory */
+
+	new->l_stat = 0;
+	strcpy(new->l_buff, buf);	/* build new line */
+	cur = getptr(curln);	/* get current line */
+	nxt = cur->l_next;	/* get next line */
+	relink(cur, new, new, nxt);	/* add to linked list */
+	relink(new, nxt, cur, new);
+	lastln++;
+	curln++;
+
+	if (*str == EOS)	/* end of line ? */
+		return(1);
+
+	cp = buf;
+  }
+}
+
+/*	join.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+extern int fchanged;
+
+int join(first, last)
+int first, last;
+{
+  char buf[MAXLINE];
+  char *cp = buf, *str;
+  int num;
+
+  if (first <= 0 || first > last || last > lastln) return(ERR);
+  if (first == last) {
+	curln = first;
+	return 0;
+  }
+  for (num = first; num <= last; num++) {
+	str = gettxt(num);
+
+	while (*str != NL && cp < buf + MAXLINE - 1) *cp++ = *str++;
+
+	if (cp == buf + MAXLINE - 1) {
+		printf("line too long\n");
+		return(ERR);
+	}
+  }
+  *cp++ = NL;
+  *cp = EOS;
+  del(first, last);
+  curln = first - 1;
+  ins(buf);
+  fchanged = TRUE;
+  return 0;
+}
+
+/*	makepat.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+
+/* Make a pattern template from the strinng pointed to by arg.  Stop
+ * when delim or '\000' or '\n' is found in arg.  Return a pointer to
+ * the pattern template.
+ *
+ * The pattern template used here are somewhat different than those
+ * used in the "Software Tools" book; each token is a structure of
+ * the form TOKEN (see tools.h).  A token consists of an identifier,
+ * a pointer to a string, a literal character and a pointer to another
+ * token.  This last is 0 if there is no subsequent token.
+ *
+ * The one strangeness here is caused (again) by CLOSURE which has
+ * to be put in front of the previous token.  To make this insertion a
+ * little easier, the 'next' field of the last to point at the chain
+ * (the one pointed to by 'tail) is made to point at the previous node.
+ * When we are finished, tail->next is set to 0.
+ */
+TOKEN *
+ makepat(arg, delim)
+char *arg;
+int delim;
+{
+  TOKEN *head, *tail, *ntok;
+  int error;
+
+  /* Check for characters that aren't legal at the beginning of a template. */
+
+  if (*arg == '\0' || *arg == delim || *arg == '\n' || *arg == CLOSURE)
+	return(0);
+
+  error = 0;
+  tail = head = NULL;
+
+  while (*arg && *arg != delim && *arg != '\n' && !error) {
+	ntok = (TOKEN *) malloc(TOKSIZE);
+	ntok->lchar = '\000';
+	ntok->next = 0;
+
+	switch (*arg) {
+	    case ANY:	ntok->tok = ANY;	break;
+
+	    case BOL:
+		if (head == 0)	/* then this is the first symbol */
+			ntok->tok = BOL;
+		else
+			ntok->tok = LITCHAR;
+		ntok->lchar = BOL;
+		break;
+
+	    case EOL:
+		if (*(arg + 1) == delim || *(arg + 1) == '\000' ||
+		    *(arg + 1) == '\n') {
+			ntok->tok = EOL;
+		} else {
+			ntok->tok = LITCHAR;
+			ntok->lchar = EOL;
+		}
+		break;
+
+	    case CLOSURE:
+		if (head != 0) {
+			switch (tail->tok) {
+			    case BOL:
+			    case EOL:
+			    case CLOSURE:
+				return(0);
+
+			    default:
+				ntok->tok = CLOSURE;
+			}
+		}
+		break;
+
+	    case CCL:
+
+		if (*(arg + 1) == NEGATE) {
+			ntok->tok = NCCL;
+			arg += 2;
+		} else {
+			ntok->tok = CCL;
+			arg++;
+		}
+
+		if (ntok->bitmap = makebitmap(CLS_SIZE))
+			arg = dodash(CCLEND, arg, ntok->bitmap);
+		else {
+			fprintf(stderr, "Not enough memory for pat\n");
+			error = 1;
+		}
+		break;
+
+	    default:
+		if (*arg == ESCAPE && *(arg + 1) == OPEN) {
+			ntok->tok = OPEN;
+			arg++;
+		} else if (*arg == ESCAPE && *(arg + 1) == CLOSE) {
+			ntok->tok = CLOSE;
+			arg++;
+		} else {
+			ntok->tok = LITCHAR;
+			ntok->lchar = esc(&arg);
+		}
+	}
+
+	if (error || ntok == 0) {
+		unmakepat(head);
+		return(0);
+	} else if (head == 0) {
+		/* This is the first node in the chain. */
+
+		ntok->next = 0;
+		head = tail = ntok;
+	} else if (ntok->tok != CLOSURE) {
+		/* Insert at end of list (after tail) */
+
+		tail->next = ntok;
+		ntok->next = tail;
+		tail = ntok;
+	} else if (head != tail) {
+		/* More than one node in the chain.  Insert the
+		 * CLOSURE node immediately in front of tail. */
+
+		(tail->next)->next = ntok;
+		ntok->next = tail;
+	} else {
+		/* Only one node in the chain,  Insert the CLOSURE
+		 * node at the head of the linked list. */
+
+		ntok->next = head;
+		tail->next = ntok;
+		head = ntok;
+	}
+	arg++;
+  }
+
+  tail->next = 0;
+  return(head);
+}
+
+/*	maksub.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+char *
+ maksub(sub, subsz)
+char *sub;
+int subsz;
+{
+  int size;
+  char delim, *cp;
+
+  size = 0;
+  cp = sub;
+
+  delim = *inptr++;
+  for (size = 0; *inptr != delim && *inptr != NL && size < subsz; size++) {
+	if (*inptr == '&') {
+		*cp++ = DITTO;
+		inptr++;
+	} else if ((*cp++ = *inptr++) == ESCAPE) {
+		if (size >= subsz) return(NULL);
+
+		switch (toupper(*inptr)) {
+		    case NL:	*cp++ = ESCAPE;		break;
+			break;
+		    case 'S':
+			*cp++ = SP;
+			inptr++;
+			break;
+		    case 'N':
+			*cp++ = NL;
+			inptr++;
+			break;
+		    case 'T':
+			*cp++ = HT;
+			inptr++;
+			break;
+		    case 'B':
+			*cp++ = BS;
+			inptr++;
+			break;
+		    case 'R':
+			*cp++ = CR;
+			inptr++;
+			break;
+		    case '0':{
+				int i = 3;
+				*cp = 0;
+				do {
+					if (*++inptr < '0' || *inptr > '7')
+						break;
+
+					*cp = (*cp << 3) | (*inptr - '0');
+				} while (--i != 0);
+				cp++;
+			} break;
+		    default:	*cp++ = *inptr++;	break;
+		}
+	}
+  }
+  if (size >= subsz) return(NULL);
+
+  *cp = EOS;
+  return(sub);
+}
+
+/*	matchs.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+
+/* Compares line and pattern.  Line is a character string while pat
+ * is a pattern template made by getpat().
+ * Returns:
+ *	1. A zero if no match was found.
+ *
+ *	2. A pointer to the last character satisfing the match
+ *	   if ret_endp is non-zero.
+ *
+ *	3. A pointer to the beginning of the matched string if
+ *	   ret_endp is zero.
+ *
+ * e.g.:
+ *
+ *	matchs ("1234567890", getpat("4[0-9]*7), 0);
+ * will return a pointer to the '4', while:
+ *
+ *	matchs ("1234567890", getpat("4[0-9]*7), 1);
+ * will return a pointer to the '7'.
+ */
+char *
+ matchs(line, pat, ret_endp)
+char *line;
+TOKEN *pat;
+int ret_endp;
+{
+
+  char *rval, *bptr;
+  char *line2;
+  TOKEN *pat2;
+  char c;
+  short ok;
+
+  bptr = line;
+
+  while (*line) {
+
+	if (pat && pat->tok == LITCHAR) {
+		while (*line) {
+			pat2 = pat;
+			line2 = line;
+			if (*line2 != pat2->lchar) {
+				c = pat2->lchar;
+				while (*line2 && *line2 != c) ++line2;
+				line = line2;
+				if (*line2 == '\0') break;
+			}
+			ok = 1;
+			++line2;
+			pat2 = pat2->next;
+			while (pat2 && pat2->tok == LITCHAR) {
+				if (*line2 != pat2->lchar) {
+					ok = 0;
+					break;
+				}
+				++line2;
+				pat2 = pat2->next;
+			}
+			if (!pat2) {
+				if (ret_endp)
+					return(--line2);
+				else
+					return(line);
+			} else if (ok)
+				break;
+			++line;
+		}
+		if (*line == '\0') return(0);
+	} else {
+		line2 = line;
+		pat2 = pat;
+	}
+	if ((rval = amatch(line2, pat2, bptr)) == 0) {
+		if (pat && pat->tok == BOL) break;
+		line++;
+	} else {
+		if (rval > bptr && rval > line)
+			rval--;	/* point to last char matched */
+		rval = ret_endp ? rval : line;
+		break;
+	}
+  }
+  return(rval);
+}
+
+/*	move.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+int move(num)
+int num;
+{
+  LINE *k0, *k1, *k2, *k3;
+
+  if (line1 <= 0 || line2 < line1 || (line1 <= num && num <= line2))
+	return(ERR);
+  k0 = getptr(prevln(line1));
+  k1 = getptr(line1);
+  k2 = getptr(line2);
+  k3 = getptr(nextln(line2));
+
+  relink(k0, k3, k0, k3);
+  lastln -= line2 - line1 + 1;
+
+  if (num > line1) num -= line2 - line1 + 1;
+
+  curln = num + (line2 - line1 + 1);
+
+  k0 = getptr(num);
+  k3 = getptr(nextln(num));
+
+  relink(k0, k1, k2, k3);
+  relink(k2, k3, k0, k1);
+  lastln += line2 - line1 + 1;
+
+  return(1);
+}
+
+int transfer(num)
+int num;
+{
+  int mid, lin, ntrans;
+
+  if (line1 <= 0 || line1 > line2) return(ERR);
+
+  mid = num < line2 ? num : line2;
+
+  curln = num;
+  ntrans = 0;
+
+  for (lin = line1; lin <= mid; lin++) {
+	ins(gettxt(lin));
+	ntrans++;
+  }
+  lin += ntrans;
+  line2 += ntrans;
+
+  for (; lin <= line2; lin += 2) {
+	ins(gettxt(lin));
+	line2++;
+  }
+  return(1);
+}
+
+/*	omatch.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+
+/* Match one pattern element, pointed at by pat, with the character at
+ * **linp.  Return non-zero on match.  Otherwise, return 0.  *Linp is
+ * advanced to skip over the matched character; it is not advanced on
+ * failure.  The amount of advance is 0 for patterns that match null
+ * strings, 1 otherwise.  "boln" should point at the position that will
+ * match a BOL token.
+ */
+int omatch(linp, pat, boln)
+char **linp;
+TOKEN *pat;
+char *boln;
+{
+
+  register int advance;
+
+  advance = -1;
+
+  if (**linp) {
+	switch (pat->tok) {
+	    case LITCHAR:
+		if (**linp == pat->lchar) advance = 1;
+		break;
+
+	    case BOL:
+		if (*linp == boln) advance = 0;
+		break;
+
+	    case ANY:
+		if (**linp != '\n') advance = 1;
+		break;
+
+	    case EOL:
+		if (**linp == '\n') advance = 0;
+		break;
+
+	    case CCL:
+		if (testbit(**linp, pat->bitmap)) advance = 1;
+		break;
+
+	    case NCCL:
+		if (!testbit(**linp, pat->bitmap)) advance = 1;
+		break;
+	}
+  }
+  if (advance >= 0) *linp += advance;
+
+  return(++advance);
+}
+
+/*	optpat.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+TOKEN *oldpat;
+
+TOKEN *
+ optpat()
+{
+  char delim, str[MAXPAT], *cp;
+
+  delim = *inptr++;
+  cp = str;
+  while (*inptr != delim && *inptr != NL) {
+	if (*inptr == ESCAPE && inptr[1] != NL) *cp++ = *inptr++;
+	*cp++ = *inptr++;
+  }
+
+  *cp = EOS;
+  if (*str == EOS) return(oldpat);
+  if (oldpat) unmakepat(oldpat);
+  oldpat = getpat(str);
+  return(oldpat);
+}
+
+/*	set.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+struct tbl {
+  char *t_str;
+  int *t_ptr;
+  int t_val;
+} *t, tbl[] = {
+
+  "number", &nflg, TRUE,
+  "nonumber", &nflg, FALSE,
+  "list", &lflg, TRUE,
+  "nolist", &lflg, FALSE,
+  "eightbit", &eightbit, TRUE,
+  "noeightbit", &eightbit, FALSE,
+  0
+};
+
+int set()
+{
+  char word[16];
+  int i;
+
+  inptr++;
+  if (*inptr != 't') {
+	if (*inptr != SP && *inptr != HT && *inptr != NL) return(ERR);
+  } else
+	inptr++;
+
+  if (*inptr == NL) return(show());
+  /* Skip white space */
+  while (*inptr == SP || *inptr == HT) inptr++;
+
+  for (i = 0; *inptr != SP && *inptr != HT && *inptr != NL;)
+	word[i++] = *inptr++;
+  word[i] = EOS;
+  for (t = tbl; t->t_str; t++) {
+	if (strcmp(word, t->t_str) == 0) {
+		*t->t_ptr = t->t_val;
+		return(0);
+	}
+  }
+  return(0);
+}
+
+int show()
+{
+  extern int version;
+
+  printf("ed version %d.%d\n", version / 100, version % 100);
+  printf("number %s, list %s\n", nflg ? "ON" : "OFF", lflg ? "ON" : "OFF");
+  return(0);
+}
+
+/*	setbuf.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+void relink(a, x, y, b)
+LINE *a, *x, *y, *b;
+{
+  x->l_prev = a;
+  y->l_next = b;
+}
+
+void clrbuf()
+{
+  del(1, lastln);
+}
+
+void set_buf()
+{
+  relink(&line0, &line0, &line0, &line0);
+  curln = lastln = 0;
+}
+
+/*	subst.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+/* #include "ed.h" */
+
+int subst(pat, sub, gflg, pflag)
+TOKEN *pat;
+char *sub;
+int gflg, pflag;
+{
+  int lin, chngd, nchngd;
+  char *txtptr, *txt;
+  char *lastm, *m, *new, buf[MAXLINE];
+
+  if (line1 <= 0) return(ERR);
+  nchngd = 0;			/* reset count of lines changed */
+  for (lin = line1; lin <= line2; lin++) {
+	txt = txtptr = gettxt(lin);
+	new = buf;
+	chngd = 0;
+	lastm = NULL;
+	while (*txtptr) {
+		if (gflg || !chngd)
+			m = amatch(txtptr, pat, txt);
+		else
+			m = NULL;
+		if (m != NULL && lastm != m) {
+			chngd++;
+			new = catsub(txtptr, m, sub, new,
+				     buf + MAXLINE);
+			lastm = m;
+		}
+		if (m == NULL || m == txtptr) {
+			*new++ = *txtptr++;
+		} else {
+			txtptr = m;
+		}
+	}
+	if (chngd) {
+		if (new >= buf + MAXLINE) return(ERR);
+		*new++ = EOS;
+		del(lin, lin);
+		ins(buf);
+		nchngd++;
+		if (pflag) doprnt(curln, curln);
+	}
+  }
+  if (nchngd == 0 && !gflg) {
+	return(ERR);
+  }
+  return(nchngd);
+}
+
+/*	System.c	*/
+#define SHELL	"/bin/sh"
+#define SHELL2	"/usr/bin/sh"
+
+int System(c)
+char *c;
+{
+  int pid, status;
+
+  switch (pid = fork()) {
+      case -1:
+	return -1;
+      case 0:
+	execl(SHELL, "sh", "-c", c, (char *) 0);
+	execl(SHELL2, "sh", "-c", c, (char *) 0);
+	exit(-1);
+      default:	while (wait(&status) != pid);
+}
+  return status;
+}
+
+/*	unmkpat.c	*/
+/* #include <stdio.h> */
+/* #include "tools.h" */
+
+/* Free up the memory usde for token string */
+void unmakepat(head)
+TOKEN *head;
+{
+
+  register TOKEN *old_head;
+
+  while (head) {
+	switch (head->tok) {
+	    case CCL:
+	    case NCCL:
+		free(head->bitmap);
+		/* Fall through to default */
+
+	    default:
+		old_head = head;
+		head = head->next;
+		free((char *) old_head);
+		break;
+	}
+  }
+}
Index: /trunk/minix/commands/simple/eject.c
===================================================================
--- /trunk/minix/commands/simple/eject.c	(revision 9)
+++ /trunk/minix/commands/simple/eject.c	(revision 9)
@@ -0,0 +1,39 @@
+/*	eject 1.3 - Eject removable media		Author: Kees J. Bot
+ *								11 Dec 1993
+ */
+#define nil 0
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+void fatal(char *label)
+{
+	fprintf(stderr, "eject: %s: %s\n", label, strerror(errno));
+	exit(1);
+}
+
+void main(int argc, char **argv)
+{
+	char *device;
+	int fd;
+
+	if (argc != 2) {
+		fprintf(stderr, "Usage: eject <device>\n");
+		exit(1);
+	}
+
+	device= argv[1];
+
+	/* Try to open it in whatever mode. */
+	fd= open(device, O_RDONLY);
+	if (fd < 0 && errno == EACCES) fd= open(device, O_WRONLY);
+	if (fd < 0) fatal(device);
+
+	/* Tell it to eject. */
+	if (ioctl(fd, DIOCEJECT, nil) < 0) fatal(device);
+	exit(0);
+}
Index: /trunk/minix/commands/simple/env.c
===================================================================
--- /trunk/minix/commands/simple/env.c	(revision 9)
+++ /trunk/minix/commands/simple/env.c	(revision 9)
@@ -0,0 +1,83 @@
+/*	env 1.1 - Set environment for command		Author: Kees J. Bot
+ *								17 Dec 1997
+ */
+#define nil 0
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+int main(int argc, char **argv)
+{
+	int i;
+	int iflag= 0;
+	int aflag= 0;
+	extern char **environ;
+
+	i= 1;
+	while (i < argc && argv[i][0] == '-') {
+		char *opt= argv[i++] + 1;
+
+		if (opt[0] == '-' && opt[1] == 0) break;	/* -- */
+
+		if (opt[0] == 0) iflag= 1;			/* - */
+
+		while (*opt != 0) switch (*opt++) {
+		case 'i':
+			iflag= 1;	/* Clear environment. */
+			break;
+		case 'a':		/* Specify arg 0 separately. */
+			aflag= 1;
+			break;
+		default:
+			fprintf(stderr,
+		"Usage: env [-ia] [name=value] ... [utility [argument ...]]\n");
+			exit(1);
+		}
+	}
+
+	/* Clear the environment if -i. */
+	if (iflag) *environ= nil;
+
+	/* Set the new environment strings. */
+	while (i < argc && strchr(argv[i], '=') != nil) {
+		if (putenv(argv[i]) != 0) {
+			fprintf(stderr, "env: Setting '%s' failed: %s\n",
+				argv[i], strerror(errno));
+			exit(1);
+		}
+		i++;
+	}
+
+	/* Environment settings and command may be separated with '--'.
+	 * This is for compatibility with other envs, we don't advertise it.
+	 */
+	if (i < argc && strcmp(argv[i], "--") == 0) i++;
+
+	if (i >= argc) {
+		/* No utility given; print environment. */
+		char **ep;
+
+		for (ep= environ; *ep != nil; ep++) {
+			if (puts(*ep) == EOF) {
+				fprintf(stderr, "env: %s\n", strerror(errno));
+				exit(1);
+			}
+		}
+		return 0;
+	} else {
+		char *util, **args;
+		int err;
+
+		util= argv[i];
+		args= argv + i;
+		if (aflag) args++;
+		(void) execvp(util, args);
+		err= errno;
+		fprintf(stderr, "env: Can't execute %s: %s\n",
+			util, strerror(err));
+		return err == ENOENT ? 127 : 126;
+	}
+}
Index: /trunk/minix/commands/simple/expand.c
===================================================================
--- /trunk/minix/commands/simple/expand.c	(revision 9)
+++ /trunk/minix/commands/simple/expand.c	(revision 9)
@@ -0,0 +1,99 @@
+/*  expand - expand tabs to spaces	Author: Terrence W. Holm */
+
+/*  Usage:  expand  [ -tab1,tab2,tab3,... ]  [ file ... ]  */
+
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define MAX_TABS 32
+
+int column = 0;			/* Current column, retained between files  */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void Expand, (FILE *f, int tab_index, int tabs []));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int tabs[MAX_TABS];
+  int tab_index = 0;		/* Default one tab   */
+  int i;
+  FILE *f;
+
+  tabs[0] = 8;			/* Default tab stop  */
+
+  if (argc > 1 && argv[1][0] == '-') {
+	char *p = argv[1];
+	int last_tab_stop = 0;
+
+	for (tab_index = 0; tab_index < MAX_TABS; ++tab_index) {
+		if ((tabs[tab_index] = atoi(p + 1)) <= last_tab_stop) {
+			fprintf(stderr, "Bad tab stop spec\n");
+			exit(1);
+		}
+		last_tab_stop = tabs[tab_index];
+
+		if ((p = strchr(p + 1, ',')) == NULL) break;
+	}
+
+	--argc;
+	++argv;
+  }
+  if (argc == 1)
+	Expand(stdin, tab_index, tabs);
+  else
+	for (i = 1; i < argc; ++i) {
+		if ((f = fopen(argv[i], "r")) == NULL) {
+			perror(argv[i]);
+			exit(1);
+		}
+		Expand(f, tab_index, tabs);
+		fclose(f);
+	}
+
+  return(0);
+}
+
+
+void Expand(f, tab_index, tabs)
+FILE *f;
+int tab_index;
+int tabs[];
+{
+  int next;
+  int c;
+  int i;
+
+  while ((c = getc(f)) != EOF) {
+	if (c == '\t') {
+		if (tab_index == 0)
+			next = (column / tabs[0] + 1) * tabs[0];
+		else {
+			for (i = 0; i <= tab_index && tabs[i] <= column; ++i);
+
+			if (i > tab_index)
+				next = column + 1;
+			else
+				next = tabs[i];
+		}
+
+		do {
+			++column;
+			putchar(' ');
+		} while (column < next);
+
+		continue;
+	}
+	if (c == '\b')
+		column = column > 0 ? column - 1 : 0;
+	else if (c == '\n' || c == '\r')
+		column = 0;
+	else
+		++column;
+
+	putchar(c);
+  }
+}
Index: /trunk/minix/commands/simple/factor.c
===================================================================
--- /trunk/minix/commands/simple/factor.c	(revision 9)
+++ /trunk/minix/commands/simple/factor.c	(revision 9)
@@ -0,0 +1,53 @@
+/* factor - print the prime factors of a number      Author: Andy Tanenbaum */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(long first, (long k));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+/* Factor a number */
+
+  long i, n, flag = 0;
+
+  if (argc != 2 || (n = atol(argv[1])) < 2) {
+	printf("Usage: factor n   (2 <= n < 2**31)\n");
+	exit(1);
+  }
+  if (n == 2) {
+	printf("2 is a prime\n");
+	exit(0);
+  }
+  while (1) {
+	i = first(n);
+	if (i == 0) {
+		if (flag == 0)
+			printf("%ld is a prime\n", n);
+		else
+			printf("%ld\n", n);
+		exit(0);
+	}
+	printf("%ld ", i);
+	n = n / i;
+	flag = 1;
+  }
+}
+
+
+long first(k)
+long k;
+{
+/* Return the first factor of k.  If it is a prime, return 0; */
+
+  long i;
+
+  if (k == 2) return(0);
+  if (k % 2 == 0) return (2);
+  for (i = 3; i <= k / 3; i += 2)
+	if (k % i == 0) return(i);
+  return(0);
+}
Index: /trunk/minix/commands/simple/fgrep.c
===================================================================
--- /trunk/minix/commands/simple/fgrep.c	(revision 9)
+++ /trunk/minix/commands/simple/fgrep.c	(revision 9)
@@ -0,0 +1,354 @@
+/* fgrep - fast grep			Author: Bert Gijsbers */
+
+/* Copyright (c) 1991 by Bert Gijsbers.  All rights reserved.
+ * Permission to use and redistribute this software is hereby granted provided
+ * that this copyright notice remains intact and that any modifications are
+ * clearly marked as such.
+ *
+ * syntax:
+ *	fgrep -chlnsv <[-e string] ... [-f file] ... | string> [file] ...
+ * options:
+ *	-c : print the number of matching lines
+ *	-h : don't print file name headers if more than one file
+ *	-l : print only the file names of the files containing a match
+ *	-n : print line numbers
+ *	-s : don't print, return status only
+ *	-v : reverse, lines not containing one of the strings match
+ *	-e string : search for this string
+ *	-f file : file contains strings to search for
+ * notes:
+ *	Options are processed by getopt(3).
+ *	Multiple strings per command line are supported, eg.
+ *		fgrep -e str1 -e str2 *.c
+ *	Instead of a filename - is allowed, meaning standard input.
+ */
+
+/* #include <ansi.h> */
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#define MAX_STR_LEN	 256	/* maximum length of strings to search for */
+#define BYTE		0xFF	/* convert from char to int */
+#define READ_SIZE	4096	/* read() request size */
+#define BUF_SIZE (2*READ_SIZE)	/* size of buffer */
+
+typedef struct test_str {
+  struct test_str *next;	/* linked list */
+  char *str;			/* string to be found */
+  char *str_end;		/* points to last character */
+  int len;			/* string length */
+  char *bufp;			/* pointer into input buffer */
+  unsigned char table[256];	/* table for Boyer-Moore algorithm */
+} test_str;
+
+test_str *strings;
+char *prog_name;
+int cflag, hflag, lflag, nflag, sflag, vflag;
+unsigned line_num;		/* line number in current file */
+
+int fd_in, eof_seen;		/* file descriptor for input and eof status */
+char input_buffer[BUF_SIZE + 2];/* buffer + sentinel margin */
+#define buffer	(&input_buffer[2])
+
+/* Pointers into the input buffer */
+char *input;			/* points to current input char */
+char *max_input;		/* points to first invalid char */
+char *buf_end;			/* points to first char not read */
+
+/* Error messages */
+char no_mem[] = "not enough memory";
+char no_arg[] = "argument missing";
+
+extern char *optarg;
+extern int optind;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(char *search_str, (test_str * ts));
+_PROTOTYPE(int fill_buffer, (void));
+_PROTOTYPE(void failure, (char *mesg));
+_PROTOTYPE(void file_open, (void));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(char *get_line, (void));
+_PROTOTYPE(void string_file, (void));
+_PROTOTYPE(void add_string, (char *str));
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  char *line;
+  int c;
+  unsigned count;		/* number of matching lines in current file */
+  unsigned found_one = 0;	/* was there any match in any file at all ? */
+
+#ifdef noperprintf
+  noperprintf(stdout);
+#else
+  static char outbuf[BUFSIZ];
+
+  setvbuf(stdout, outbuf, _IOFBF, sizeof outbuf);
+#endif
+
+  prog_name = argv[0];
+  if (argc == 1) usage();
+  while ((c = getopt(argc, argv, "ce:f:hlnsv")) != EOF) {
+	switch (c) {
+	    case 'c':	cflag++;	break;
+	    case 'e':	add_string(optarg);	break;
+	    case 'f':	string_file();	break;
+	    case 'h':	hflag++;	break;
+	    case 'l':	lflag++;	break;
+	    case 'n':	nflag++;	break;
+	    case 's':	sflag++;	break;
+	    case 'v':	vflag++;	break;
+	    default:	usage();	break;
+	}
+  }
+
+  /* If no -e or -f option is used take a string from the command line. */
+  if (strings == (test_str *) NULL) {
+	if (optind == argc) failure(no_arg);
+	add_string(argv[optind++]);
+  }
+  if (argc - optind < 2)
+	hflag++;		/* don't print filenames if less than two
+			 * files */
+
+  /* Handle every matching line according to the flags. */
+  do {
+	optarg = argv[optind];
+	file_open();
+	count = 0;
+	while ((line = get_line()) != (char *) NULL) {
+		count++;
+		if (sflag) return 0;
+		if (lflag) {
+			printf("%s\n", optarg);
+			fflush(stdout);
+			break;
+		}
+		if (cflag) continue;
+		if (hflag == 0) printf("%s:", optarg);
+		if (nflag) printf("%u:", line_num);
+		do {
+			putchar(*line);
+		} while (++line < input);
+		fflush(stdout);
+	}
+	found_one |= count;
+	if (cflag) {
+		if (hflag == 0) printf("%s: ", optarg);
+		printf("%u\n", count);
+		fflush(stdout);
+	}
+	close(fd_in);
+  } while (++optind < argc);
+
+  /* Exit nonzero if no match is found. */
+  return found_one ? 0 : 1;
+}
+
+void usage()
+{
+  fprintf(stderr,
+	"Usage: %s -chlnsv <[-e string] ... [-f file] ... | string> [file] ...\n",
+	prog_name);
+  exit(2);
+}
+
+void failure(mesg)
+char *mesg;
+{
+  fprintf(stderr, "%s: %s\n", prog_name, mesg);
+  exit(1);
+}
+
+/* Add a string to search for to the global linked list `strings'. */
+void add_string(str)
+char *str;
+{
+  test_str *ts;
+  int len;
+
+  if (str == (char *) NULL || (len = strlen(str)) == 0) return;
+  if (len > MAX_STR_LEN) failure("string too long");
+  if ((ts = (test_str *) malloc(sizeof(*ts))) == (test_str *) NULL)
+	failure(no_mem);
+
+  /* Initialize Boyer-Moore table. */
+  memset(ts->table, len, sizeof(ts->table));
+  ts->len = len;
+  ts->str = str;
+  ts->str_end = str + len - 1;
+  for (; --len >= 0; str++) ts->table[*str & BYTE] = len;
+
+  /* Put it on the list */
+  ts->next = strings;
+  strings = ts;
+}
+
+/* Open a file for reading.  Initialize input buffer pointers. */
+void file_open()
+{
+  /* Use stdin if no file arguments are given on the command line. */
+  if (optarg == (char *) NULL || strcmp(optarg, "-") == 0) {
+	fd_in = 0;
+	optarg = "stdin";
+  } else if ((fd_in = open(optarg, O_RDONLY)) == -1) {
+	fprintf(stderr, "%s: can't open %s\n", prog_name, optarg);
+	exit(1);
+  }
+  input = max_input = buf_end = buffer;
+  buffer[-1] = '\n';		/* sentinel */
+  eof_seen = 0;
+  line_num = 0;
+}
+
+/* Move any leftover characters to the head of the buffer.
+ * Read characters into the rest of the buffer.
+ * Round off the available input to whole lines.
+ * Return the number of valid input characters.
+ */
+int fill_buffer()
+{
+  char *bufp;
+  int size;
+
+  if (eof_seen) return 0;
+
+  size = buf_end - max_input;
+  memmove(buffer, max_input, size);
+  bufp = &buffer[size];
+
+  do {
+	if ((size = read(fd_in, bufp, READ_SIZE)) <= 0) {
+		if (size != 0) failure("read error");
+		eof_seen++;
+		if (bufp == buffer)	/* no input left */
+			return 0;
+		/* Make sure the last char of a file is '\n'. */
+		*bufp++ = '\n';
+		break;
+	}
+	bufp += size;
+  } while (bufp - buffer < READ_SIZE && bufp[-1] != '\n');
+
+  buf_end = bufp;
+  while (*--bufp != '\n');
+  if (++bufp == buffer) {
+	/* Line too long. */
+	*buf_end++ = '\n';
+	bufp = buf_end;
+  }
+  max_input = bufp;
+  input = buffer;
+
+  return max_input - buffer;
+}
+
+/* Read strings from a file.  Give duplicates to add_string(). */
+void string_file()
+{
+  char *str, *p;
+
+  file_open();
+  while (input < max_input || fill_buffer() > 0) {
+	p = (char *) memchr(input, '\n', BUF_SIZE);
+	*p++ = '\0';
+	if ((str = (char *) malloc(p - input)) == (char *) NULL)
+		failure(no_mem);
+	memcpy(str, input, p - input);
+	add_string(str);
+	input = p;
+  }
+  close(fd_in);
+}
+
+/* Scan the rest of the available input for a string using Boyer-Moore.
+ * Return a pointer to the match or a pointer beyond end of input if no match.
+ * Record how far the input is scanned.
+ */
+char *search_str(ts)
+test_str *ts;
+{
+  char *bufp, *prevbufp, *s;
+
+  bufp = input + ts->len - 1;
+  while (bufp < max_input) {
+	prevbufp = bufp;
+	bufp += ts->table[*bufp & BYTE];
+	if (bufp > prevbufp) continue;
+	s = ts->str_end;
+	do {
+		if (s == ts->str) {	/* match found */
+			ts->bufp = bufp;
+			return bufp;
+		}
+	} while (*--bufp == *--s);
+	bufp = prevbufp + 1;
+  }
+  ts->bufp = bufp;
+
+  return bufp;
+}
+
+/* Return the next line in which one of the strings occurs.
+ * Or, if the -v option is used, the next line without a match.
+ * Or NULL on EOF.
+ */
+char *get_line()
+{
+  test_str *ts;
+  char *match, *line;
+
+  /* Loop until a line is found. */
+  while (1) {
+	if (input >= max_input && fill_buffer() == 0) {	/* EOF */
+		line = (char *) NULL;
+		break;
+	}
+
+	/* If match is still equal to max_input after the next loop
+	 * then no match is found. */
+	match = max_input;
+	ts = strings;
+	do {
+		if (input == buffer) {
+			if (search_str(ts) < match) match = ts->bufp;
+		} else if (ts->bufp < match) {
+			if (ts->bufp >= input || search_str(ts) < match)
+				match = ts->bufp;
+		}
+	} while ((ts = ts->next) != (test_str *) NULL);
+
+	/* Determine if and in what line a match is found. Only do
+	 * line number counting if it is necessary or very easy. */
+	if (vflag) {
+		line_num++;
+		line = input;
+		input = 1 + (char *) memchr(line, '\n', BUF_SIZE);
+		if (input <= match) break;	/* no match in current line */
+	} else if (nflag) {
+		do {
+			line_num++;
+			line = input;
+			input = 1 + (char *) memchr(line, '\n', BUF_SIZE);
+		} while (input < match ||
+			 (input == match && match < max_input));
+		if (match < max_input) break;	/* match found */
+	} else if (match < max_input) {
+		/* Match found. */
+		for (line = match; *--line != '\n';);
+		line++;
+		input = 1 + (char *) memchr(match, '\n', BUF_SIZE);
+		break;
+	} else
+		input = max_input;
+  }
+
+  return line;
+}
Index: /trunk/minix/commands/simple/file.c
===================================================================
--- /trunk/minix/commands/simple/file.c	(revision 9)
+++ /trunk/minix/commands/simple/file.c	(revision 9)
@@ -0,0 +1,278 @@
+/* file - report on file type.		Author: Andy Tanenbaum */
+/* Magic number detection changed to look-up table 08-Jan-91 - ajm */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define BLOCK_SIZE	1024
+
+#define XBITS 00111		/* rwXrwXrwX (x bits in the mode) */
+#define ENGLISH 25		/* cutoff for determining if text is Eng. */
+unsigned char buf[BLOCK_SIZE];
+
+struct info {
+  int execflag;			/* 1 == ack executable, 2 == gnu executable,
+				 * 3 == core */
+  unsigned char magic[4];	/* First four bytes of the magic number */
+  unsigned char mask[4];	/* Mask to apply when matching */
+  char *description;		/* What it means */
+} table[] = {
+  0x00, 0x1f, 0x9d, 0x8d, 0x00,		0xff, 0xff, 0xff, 0x00,
+	"13-bit compressed file",
+  0x00, 0x1f, 0x9d, 0x90, 0x00,		0xff, 0xff, 0xff, 0x00,
+	"16-bit compressed file",
+  0x00, 0x65, 0xff, 0x00, 0x00,		0xff, 0xff, 0x00, 0x00,
+	"MINIX-PC bcc archive",
+  0x00, 0x2c, 0xff, 0x00, 0x00,		0xff, 0xff, 0x00, 0x00,
+	"ACK object archive",
+  0x00, 0x65, 0xff, 0x00, 0x00,		0xff, 0xff, 0x00, 0x00,
+	"MINIX-PC ack archive",
+  0x00, 0x47, 0x6e, 0x75, 0x20,		0xff, 0xff, 0xff, 0xff,
+	"MINIX-68k gnu archive",
+  0x00, 0x21, 0x3c, 0x61, 0x72,		0xff, 0xff, 0xff, 0xff,
+	"MINIX-PC gnu archive",
+  0x00, 0x01, 0x02, 0x00, 0x00,		0xff, 0xff, 0x00, 0x00,
+	"ACK object file",
+  0x00, 0xa3, 0x86, 0x00, 0x00, 	0xff, 0xff, 0x00, 0x00,
+	"MINIX-PC bcc object file",
+  0x00, 0x00, 0x00, 0x01, 0x07, 	0xff, 0xff, 0xff, 0xff,
+	"MINIX-68k gnu object file",
+  0x00, 0x07, 0x01, 0x00, 0x00, 	0xff, 0xff, 0xff, 0xff,
+	"MINIX-PC gnu object file",
+  0x01, 0x01, 0x03, 0x00, 0x04, 	0xff, 0xff, 0x00, 0xff,
+	"MINIX-PC 16-bit executable",
+  0x01, 0x01, 0x03, 0x00, 0x10, 	0xff, 0xff, 0x00, 0xff,
+	"MINIX-PC 32-bit executable",
+  0x01, 0x04, 0x10, 0x03, 0x01, 	0xff, 0xff, 0xff, 0xff,
+	"MINIX-68k old style executable",
+  0x01, 0x01, 0x03, 0x10, 0x0b, 	0xff, 0xff, 0xff, 0xff,
+	"MINIX-68k new style executable",
+  0x02, 0x0b, 0x01, 0x00, 0x00, 	0xff, 0xff, 0xff, 0xff,
+	"MINIX-PC 32-bit gnu executable combined I & D space",
+  0x02, 0x00, 0x00, 0x0b, 0x01, 	0xff, 0xff, 0xff, 0xff,
+	"MINIX-68k gnu executable",
+  0x03, 0x82, 0x12, 0xC4, 0xC0,		0xff, 0xff, 0xff, 0xff,
+	"core file",
+};
+
+int tabsize = sizeof(table) / sizeof(struct info);
+int L_flag;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void file, (char *name));
+_PROTOTYPE(void do_strip, (int type));
+_PROTOTYPE(void usage, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+/* This program uses some heuristics to try to guess about a file type by
+ * looking at its contents.
+ */
+  int c, i;
+
+  L_flag= 0;
+  while ((c= getopt(argc, argv, "L?")) != -1)
+  {
+	switch(c)
+	{
+	case 'L':
+		L_flag= 1;
+		break;
+	case '?':
+		usage();
+	default:
+		fprintf(stderr, "file: panic getopt failed\n");
+		exit(1);
+	}
+  }
+  if (optind >= argc) usage();
+  for (i = optind; i < argc; i++) file(argv[i]);
+  return(0);
+}
+
+void file(name)
+char *name;
+{
+  int i, fd, n, mode, nonascii, special, funnypct, etaoins;
+  int j;
+  long engpct;
+  int c;
+  struct stat st_buf;
+
+  printf("%s: ", name);
+
+#ifdef S_IFLNK
+  if (!L_flag)
+	n = lstat(name, &st_buf);
+  else
+	n = stat(name, &st_buf);
+#else
+  n = stat(name, &st_buf);
+#endif
+  if (n < 0) {
+	printf("cannot stat\n");
+	return;
+  }
+  mode = st_buf.st_mode;
+
+  /* Check for directories and special files. */
+  if (S_ISDIR(mode)) {
+	printf("directory\n");
+	return;
+  }
+  if (S_ISCHR(mode)) {
+	printf("character special file\n");
+	return;
+  }
+  if (S_ISBLK(mode)) {
+	printf("block special file\n");
+	return;
+  }
+  if (S_ISFIFO(mode)) {
+	printf("named pipe\n");
+	return;
+  }
+#ifdef S_IFLNK
+  if (S_ISLNK(mode)) {
+	n= readlink(name, (char *)buf, BLOCK_SIZE);
+	if (n == -1)
+		printf("cannot readlink\n");
+	else
+		printf("symbolic link to %.*s\n", n, buf);
+	return;
+  }
+#endif
+  if (!S_ISREG(mode)) {
+	printf("strange file type %5o\n", mode);
+	return;
+  }
+
+  /* Open the file, stat it, and read in 1 block. */
+  fd = open(name, O_RDONLY);
+  if (fd < 0) {
+	printf("cannot open\n");
+	return;
+  }
+  n = read(fd, (char *)buf, BLOCK_SIZE);
+  if (n < 0) {
+	printf("cannot read\n");
+	close(fd);
+	return;
+  }
+  if (n == 0) {       /* must check this, for loop will fail otherwise !! */
+      printf("empty file\n");
+      close(fd);
+      return;
+  }
+
+  for (i = 0; i < tabsize; i++) {
+	for (j = 0; j < 4; j++)
+		if ((buf[j] & table[i].mask[j]) != table[i].magic[j])
+			break;
+	if (j == 4) {
+		printf("%s", table[i].description);
+		do_strip(table[i].execflag);
+		close(fd);
+		return;
+	}
+  }
+
+
+  /* Check to see if file is a shell script. */
+  if (mode & XBITS) {
+	/* Not a binary, but executable.  Probably a shell script. */
+	printf("shell script\n");
+	close(fd);
+	return;
+  }
+
+  /* Check for ASCII data and certain punctuation. */
+  nonascii = 0;
+  special = 0;
+  etaoins = 0;
+  for (i = 0; i < n; i++) {
+	c = buf[i];
+	if (c & 0200) nonascii++;
+	if (c == ';' || c == '{' || c == '}' || c == '#') special++;
+	if (c == '*' || c == '<' || c == '>' || c == '/') special++;
+	if (c >= 'A' && c <= 'Z') c = c - 'A' + 'a';
+	if (c == 'e' || c == 't' || c == 'a' || c == 'o') etaoins++;
+	if (c == 'i' || c == 'n' || c == 's') etaoins++;
+  }
+
+  if (nonascii == 0) {
+	/* File only contains ASCII characters.  Continue processing. */
+	funnypct = 100 * special / n;
+	engpct = 100L * (long) etaoins / n;
+	if (funnypct > 1) {
+		printf("C program\n");
+	} else {
+		if (engpct > (long) ENGLISH)
+			printf("English text\n");
+		else
+			printf("ASCII text\n");
+	}
+	close(fd);
+	return;
+  }
+
+  /* Give up.  Call it data. */
+  printf("data\n");
+  close(fd);
+  return;
+}
+
+void do_strip(type)
+int type;
+{
+  if (type == 1) {	/* Non-GNU executable */
+	if (buf[2] & 1)
+		printf(", UZP");
+	if (buf[2] & 2)
+		printf(", PAL");
+	if (buf[2] & 4)
+		printf(", NSYM");
+	if (buf[2] & 0x20)
+		printf(", sep I&D");
+	else
+		printf(", comm I&D");
+	if (( buf[28] | buf[29] | buf[30] | buf[31]) != 0)
+		printf(" not stripped\n");
+	else
+		printf(" stripped\n");
+	return;
+  }
+
+  if (type == 2) {	/* GNU format executable */
+     if ((buf[16] | buf[17] | buf[18] | buf[19]) != 0)
+	 printf(" not stripped\n");
+     else
+	 printf(" stripped\n");
+     return;
+  }
+
+  if (type == 3) {	/* Core file in <sys/core.h> format */
+	switch(buf[36] & 0xff)
+	{
+		case 1:	printf(" of i86 executable"); break;
+		case 2:	printf(" of i386 executable"); break;
+		default:printf(" of unknown executable"); break;
+	}
+	printf(" '%.32s'\n", buf+4);
+	return;
+  }
+
+  printf("\n");		/* Not an executable file */
+ }
+
+void usage()
+{
+  printf("Usage: file [-L] name ...\n");
+  exit(1);
+}
Index: /trunk/minix/commands/simple/find.c
===================================================================
--- /trunk/minix/commands/simple/find.c	(revision 9)
+++ /trunk/minix/commands/simple/find.c	(revision 9)
@@ -0,0 +1,927 @@
+/* find - look for files satisfying a predicate       Author: E. Baalbergen */
+
+/* Original author: Erik Baalbergen; POSIX compliant version: Bert Laverman */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <pwd.h>
+#include <grp.h>
+#include <dirent.h>
+#include <limits.h>
+#include <stdio.h>
+
+/*######################## DEFINITIONS ##############################*/
+
+#ifdef S_IFLNK
+#define LSTAT lstat
+#else
+#define LSTAT stat
+#endif
+
+#define SHELL "/bin/sh"
+#define MAXARG          256	/* maximum length for an argv for -exec  */
+#define BSIZE           512	/* POSIX wants 512 byte blocks           */
+#define SECS_PER_DAY    (24L*60L*60L)	/* check your planet             */
+
+#define OP_NAME          1	/* match name                            */
+#define OP_PERM          2	/* check file permission bits            */
+#define OP_TYPE          3	/* check file type bits                  */
+#define OP_LINKS         4	/* check link count                      */
+#define OP_USER          5	/* check owner                           */
+#define OP_GROUP         6	/* check group ownership                 */
+#define OP_SIZE          7	/* check size, blocks or bytes           */
+#define OP_SIZEC         8	/* this is a fake for -size with 'c'     */
+#define OP_INUM          9	/* compare inode number                  */
+#define OP_ATIME        10	/* check last access time                */
+#define OP_CTIME        11	/* check creation time                   */
+#define OP_MTIME        12	/* check last modification time          */
+#define OP_EXEC         13	/* execute command                       */
+#define OP_OK           14	/* execute with confirmation             */
+#define OP_PRINT        15	/* print name                            */
+#define OP_PRINT0       16	/* print name null terminated            */
+#define OP_NEWER        17	/* compare modification times            */
+#define OP_CNEWER       18	/* compare modification times            */
+#define OP_AND          19	/* logical and (short circuit)           */
+#define OP_OR           20	/* logical or (short circuit)            */
+#define OP_XDEV         21	/* do not cross file-system boundaries   */
+#define OP_DEPTH        22	/* descend directory before testing      */
+#define OP_PRUNE        23	/* don't descend into current directory  */
+#define OP_NOUSER       24	/* check validity of user id             */
+#define OP_NOGROUP      25	/* check validity of group id            */
+#define LPAR            26	/* left parenthesis                      */
+#define RPAR            27	/* right parenthesis                     */
+#define NOT             28	/* logical not                           */
+
+/* Some return values: */
+#define EOI             -1	/* end of expression                     */
+#define NONE             0	/* not a valid predicate                 */
+
+/* For -perm with symbolic modes: */
+#define ISWHO(c)        ((c == 'u') || (c == 'g') || (c == 'o') || (c == 'a'))
+#define ISOPER(c)       ((c == '-') || (c == '=') || (c == '+'))
+#define ISMODE(c)       ((c == 'r') || (c == 'w') || (c == 'x') || \
+			 (c == 's') || (c == 't'))
+#define MUSER           1
+#define MGROUP          2
+#define MOTHERS         4
+
+
+struct exec {
+  int e_cnt;
+  char *e_vec[MAXARG];
+};
+
+struct node {
+  int n_type;			/* any OP_ or NOT */
+  union {
+	char *n_str;
+	struct {
+		long n_val;
+		int n_sign;
+	} n_int;
+	struct exec *n_exec;
+	struct {
+		struct node *n_left, *n_right;
+	} n_opnd;
+  } n_info;
+};
+
+struct oper {
+  char *op_str;
+  int op_val;
+} ops[] = {
+
+  {
+	"name", OP_NAME
+  },
+  {
+	"perm", OP_PERM
+  },
+  {
+	"type", OP_TYPE
+  },
+  {
+	"links", OP_LINKS
+  },
+  {
+	"user", OP_USER
+  },
+  {
+	"group", OP_GROUP
+  },
+  {
+	"size", OP_SIZE
+  },
+  {
+	"inum", OP_INUM
+  },
+  {
+	"atime", OP_ATIME
+  },
+  {
+	"ctime", OP_CTIME
+  },
+  {
+	"mtime", OP_MTIME
+  },
+  {
+	"exec", OP_EXEC
+  },
+  {
+	"ok", OP_OK
+  },
+  {
+	"print", OP_PRINT
+  },
+  {
+	"print0", OP_PRINT0
+  },
+  {
+	"newer", OP_NEWER
+  },
+  {
+	"cnewer", OP_CNEWER
+  },
+  {
+	"a", OP_AND
+  },
+  {
+	"o", OP_OR
+  },
+  {
+	"xdev", OP_XDEV
+  },
+  {
+	"depth", OP_DEPTH
+  },
+  {
+	"prune", OP_PRUNE
+  },
+  {
+	"nouser", OP_NOUSER
+  },
+  {
+	"nogroup", OP_NOGROUP
+  },
+  {
+	0, 0
+  }
+};
+
+
+char **ipp;			/* pointer to next argument during parsing       */
+char *prog;			/* program name (== argv [0])                    */
+char *epath;			/* value of PATH environment string              */
+long current_time;		/* for computing age                             */
+int tty;			/* fd for /dev/tty when using -ok                */
+int xdev_flag = 0;		/* cross device boundaries?                      */
+int devnr;			/* device nr of first inode                      */
+int depth_flag = 0;		/* descend before check?                         */
+int prune_here;			/* This is Baaaad! Don't ever do this again!     */
+int um;				/* current umask()                               */
+int needprint = 1;		/* implicit -print needed?                       */
+
+
+/* The prototypes: */
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(char *Malloc, (int n));
+_PROTOTYPE(char *Salloc, (char *s));
+_PROTOTYPE(void find, (char *path, struct node * pred, char *last));
+_PROTOTYPE(int check, (char *path, struct stat * st, struct node * n, char *last));
+_PROTOTYPE(int ichk, (long val, struct node * n));
+_PROTOTYPE(int lex, (char *str));
+_PROTOTYPE(struct node * newnode, (int t));
+_PROTOTYPE(int isnumber, (char *str, int base, int sign));
+_PROTOTYPE(void number, (char *str, int base, long *pl, int *ps));
+_PROTOTYPE(void fmode, (char *str, long *pl, int *ps));
+_PROTOTYPE(struct node * expr, (int t));
+_PROTOTYPE(struct node * primary, (int t));
+_PROTOTYPE(struct node * secondary, (int t));
+_PROTOTYPE(void checkarg, (char *arg));
+_PROTOTYPE(struct node * simple, (int t));
+_PROTOTYPE(void nonfatal, (char *s1, char *s2));
+_PROTOTYPE(void fatal, (char *s1, char *s2));
+_PROTOTYPE(int smatch, (char *s, char *t));
+_PROTOTYPE(char *find_bin, (char *s));
+_PROTOTYPE(int execute, (int op, struct exec * e, char *path));
+_PROTOTYPE(void domode, (int op, int *mode, int bits));
+
+
+/* Malloc: a certified malloc */
+char *Malloc(n)
+int n;
+{
+  char *m;
+
+  if ((m = (char *) malloc(n)) == (char *) NULL) fatal("out of memory", "");
+  return m;
+}
+
+/* Salloc: allocate space for a string */
+char *Salloc(s)
+char *s;
+{
+  return strcpy(Malloc(strlen(s) + 1), s);
+}
+
+
+/* Main: the main body */
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  char **pathlist, *path, *last;
+  int pathcnt = 0, i;
+  struct node *pred;
+
+  prog = *argv++;		/* set program name (for diagnostics)    */
+  if ((epath = getenv("PATH")) == (char *) NULL)
+	fatal("Can't get path from environment", "");
+  (void) umask(um = umask(0));	/* non-destructive get-umask :-)         */
+  time(&current_time);		/* get current time                      */
+
+  pathlist= argv;
+  while (--argc > 0 && lex(*argv) == NONE) {	/* find paths            */
+	pathcnt++;
+	argv++;
+  }
+  if (pathcnt == 0)		/* there must be at least one path       */
+	fatal("Usage: path-list [predicate-list]", "");
+
+  ipp = argv;			/* prepare for parsing                   */
+  if (argc != 0) {		/* If there is anything to parse,        */
+	pred = expr(lex(*ipp));	/* then do so                            */
+	if (lex(*++ipp) != EOI)	/* Make sure there's nothing left        */
+		fatal("syntax error: garbage at end of predicate", "");
+  } else			/* No predicate list                     */
+	pred = (struct node *) NULL;
+
+  for (i = 0; i < pathcnt; i++) {
+	if (xdev_flag) xdev_flag = 2;
+	path = pathlist[i];
+	if ((last = strrchr(path, '/')) == NULL) last = path; else last++;
+	find(path, pred, last);
+  }
+  return 0;
+}
+
+void find(path, pred, last)
+char *path, *last;
+struct node *pred;
+{
+  char spath[PATH_MAX];
+  register char *send = spath, *p;
+  struct stat st;
+  DIR *dp;
+  struct dirent *de;
+
+  if (path[1] == '\0' && *path == '/') {
+	*send++ = '/';
+	*send = '\0';
+  } else
+	while (*send++ = *path++) {
+	}
+
+  if (LSTAT(spath, &st) == -1)
+	nonfatal("can't get status of ", spath);
+  else {
+	switch (xdev_flag) {
+	  case 0:
+		break;
+	  case 1:
+		if (st.st_dev != devnr) return;
+		break;
+	  case 2:		/* set current device number */
+		xdev_flag = 1;
+		devnr = st.st_dev;
+		break;
+	}
+
+	prune_here = 0;
+	if (!depth_flag && check(spath, &st, pred, last) && needprint)
+		printf("%s\n", spath);
+	if (!prune_here && (st.st_mode & S_IFMT) == S_IFDIR) {
+		if ((dp = opendir(spath)) == NULL) {
+			nonfatal("can't read directory ", spath);
+			perror( "Error" );
+			return;
+		}
+		send[-1] = '/';
+		while ((de = readdir(dp)) != NULL) {
+			p = de->d_name;
+			if ((de->d_name[0] != '.') || ((de->d_name[1])
+					  && ((de->d_name[1] != '.')
+					      || (de->d_name[2])))) {
+				strcpy(send, de->d_name);
+				find(spath, pred, send);
+			}
+		}
+		closedir(dp);
+	}
+	if (depth_flag) {
+		send[-1] = '\0';
+		if (check(spath, &st, pred, last) && needprint)
+			printf("%s\n", spath);
+	}
+  }
+}
+
+int check(path, st, n, last)
+char *path, *last;
+register struct stat *st;
+register struct node *n;
+{
+  if (n == (struct node *) NULL) return 1;
+  switch (n->n_type) {
+    case OP_AND:
+	return check(path, st, n->n_info.n_opnd.n_left, last) &&
+		check(path, st, n->n_info.n_opnd.n_right, last);
+    case OP_OR:
+	return check(path, st, n->n_info.n_opnd.n_left, last) ||
+		check(path, st, n->n_info.n_opnd.n_right, last);
+    case NOT:
+	return !check(path, st, n->n_info.n_opnd.n_left, last);
+    case OP_NAME:
+	return smatch(last, n->n_info.n_str);
+    case OP_PERM:
+	if (n->n_info.n_int.n_sign < 0)
+		return(st->st_mode & (int) n->n_info.n_int.n_val) ==
+			(int) n->n_info.n_int.n_val;
+	return(st->st_mode & 07777) == (int) n->n_info.n_int.n_val;
+    case OP_NEWER:
+	return st->st_mtime > n->n_info.n_int.n_val;
+    case OP_CNEWER:
+	return st->st_ctime > n->n_info.n_int.n_val;
+    case OP_TYPE:
+	return(st->st_mode & S_IFMT) == (mode_t) n->n_info.n_int.n_val;
+    case OP_LINKS:
+	return ichk((long) (st->st_nlink), n);
+    case OP_USER:
+	return st->st_uid == n->n_info.n_int.n_val;
+    case OP_GROUP:
+	return st->st_gid == n->n_info.n_int.n_val;
+    case OP_SIZE:
+	return ichk((st->st_size == 0) ? 0L :
+		    (long) ((st->st_size - 1) / BSIZE + 1), n);
+    case OP_SIZEC:
+	return ichk((long) st->st_size, n);
+    case OP_INUM:
+	return ichk((long) (st->st_ino), n);
+    case OP_ATIME:
+	return ichk(st->st_atime, n);
+    case OP_CTIME:
+	return ichk(st->st_ctime, n);
+    case OP_MTIME:
+	return ichk(st->st_mtime, n);
+    case OP_EXEC:
+    case OP_OK:
+	return execute(n->n_type, n->n_info.n_exec, path);
+    case OP_PRINT:
+	printf("%s\n", path);
+	return 1;
+    case OP_PRINT0:
+	printf("%s", path); putchar(0);
+	return 1;
+    case OP_XDEV:
+    case OP_DEPTH:
+	return 1;
+    case OP_PRUNE:
+	prune_here = 1;
+	return 1;
+    case OP_NOUSER:
+	return(getpwuid(st->st_uid) == (struct passwd *) NULL);
+    case OP_NOGROUP:
+	return(getgrgid(st->st_gid) == (struct group *) NULL);
+  }
+  fatal("ILLEGAL NODE", "");
+  return 0;			/* Never reached */
+}
+
+int ichk(val, n)
+long val;
+struct node *n;
+{
+  switch (n->n_info.n_int.n_sign) {
+    case 0:
+	return val == n->n_info.n_int.n_val;
+    case 1:
+	return val > n->n_info.n_int.n_val;
+    case -1:	return val < n->n_info.n_int.n_val;
+}
+  fatal("internal: bad n_sign", "");
+  return 0;			/* Never reached */
+}
+
+int lex(str)
+char *str;
+{
+  if (str == (char *) NULL) return EOI;
+  if (*str == '-') {
+	register struct oper *op;
+
+	str++;
+	for (op = ops; op->op_str; op++)
+		if (strcmp(str, op->op_str) == 0) break;
+	return op->op_val;
+  }
+  if (str[1] == 0) {
+	switch (*str) {
+	  case '(':
+		return LPAR;
+	  case ')':
+		return RPAR;
+	  case '!':	return NOT;
+	}
+  }
+  return NONE;
+}
+
+struct node *
+ newnode(t)
+int t;
+{
+  struct node *n = (struct node *) Malloc(sizeof(struct node));
+
+  n->n_type = t;
+  return n;
+}
+
+/*########################### PARSER ###################################*/
+/* Grammar:
+ * expr        : primary | primary OR expr;
+ * primary     : secondary | secondary AND primary | secondary primary;
+ * secondary   : NOT secondary | LPAR expr RPAR | simple;
+ * simple      : -OP args...
+ */
+
+/* Isnumber checks correct number syntax. A sign is allowed, but the '+'
+ * only if the number is to be in decimal.
+ */
+int isnumber(str, base, sign)
+register char *str;
+int base;
+int sign;
+{
+  if (sign && ((*str == '-') || ((base == 8) && (*str == '+')))) str++;
+  while ((*str >= '0') && (*str < ('0' + base))) str++;
+  return(*str == '\0' ? 1 : 0);
+}
+
+/* Convert a string to an integer, storing sign info in *ps. */
+void number(str, base, pl, ps)
+char *str;
+int base;
+long *pl;
+int *ps;
+{
+  int up = '0' + base - 1;
+  long val = 0;
+
+  *ps = ((*str == '-' || *str == '+') ? ((*str++ == '-') ? -1 : 1) : 0);
+  while (*str >= '0' && *str <= up) val = base * val + *str++ - '0';
+  if (*str) fatal("syntax error: illegal numeric value", "");
+  *pl = val;
+}
+
+
+void domode(op, mode, bits)
+int op;
+int *mode;
+int bits;
+{
+  switch (op) {
+    case '-':
+	*mode &= ~bits;
+	break;			/* clear bits */
+    case '=':
+	*mode |= bits;
+	break;			/* set bits */
+    case '+':
+	*mode |= (bits & ~um);	/* set, but take umask in account */
+  }
+}
+
+void fmode(str, pl, ps)
+char *str;
+long *pl;
+int *ps;
+{
+  int m = 0, w, op;
+  char *p = str;
+
+  if (*p == '-') {
+	*ps = -1;
+	p++;
+  } else
+	*ps = 0;
+
+  while (*p) {
+	w = 0;
+	if (ISOPER(*p))
+		w = MUSER | MGROUP | MOTHERS;
+	else if (!ISWHO(*p))
+		fatal("u, g, o, or a expected: ", p);
+	else {
+		while (ISWHO(*p)) {
+			switch (*p) {
+			  case 'u':
+				w |= MUSER;
+				break;
+			  case 'g':
+				w |= MGROUP;
+				break;
+			  case 'o':
+				w |= MOTHERS;
+				break;
+			  case 'a':
+				w = MUSER | MGROUP | MOTHERS;
+			}
+			p++;
+		}
+		if (!ISOPER(*p)) fatal("-, + or = expected: ", p);
+	}
+	op = *p++;
+	while (ISMODE(*p)) {
+		switch (*p) {
+		  case 'r':
+			if (w & MUSER) domode(op, &m, S_IRUSR);
+			if (w & MGROUP) domode(op, &m, S_IRGRP);
+			if (w & MOTHERS) domode(op, &m, S_IROTH);
+			break;
+		  case 'w':
+			if (w & MUSER) domode(op, &m, S_IWUSR);
+			if (w & MGROUP) domode(op, &m, S_IWGRP);
+			if (w & MOTHERS) domode(op, &m, S_IWOTH);
+			break;
+		  case 'x':
+			if (w & MUSER) domode(op, &m, S_IXUSR);
+			if (w & MGROUP) domode(op, &m, S_IXGRP);
+			if (w & MOTHERS) domode(op, &m, S_IXOTH);
+			break;
+		  case 's':
+			if (w & MUSER) domode(op, &m, S_ISUID);
+			if (w & MGROUP) domode(op, &m, S_ISGID);
+			break;
+		  case 't':
+			domode(op, &m, S_ISVTX);
+		}
+		p++;
+	}
+	if (*p) {
+		if (*p == ',')
+			p++;
+		else
+			fatal("garbage at end of mode string: ", p);
+	}
+  }
+  *pl = m;
+}
+
+struct node *
+ expr(t)
+int t;
+{
+  struct node *nd, *p, *nd2;
+
+  nd = primary(t);
+  if ((t = lex(*++ipp)) == OP_OR) {
+	nd2 = expr(lex(*++ipp));
+	p = newnode(OP_OR);
+	p->n_info.n_opnd.n_left = nd;
+	p->n_info.n_opnd.n_right = nd2;
+	return p;
+  }
+  ipp--;
+  return nd;
+}
+
+struct node *
+ primary(t)
+int t;
+{
+  struct node *nd, *p, *nd2;
+
+  nd = secondary(t);
+  if ((t = lex(*++ipp)) != OP_AND) {
+	ipp--;
+	if (t == EOI || t == RPAR || t == OP_OR) return nd;
+  }
+  nd2 = primary(lex(*++ipp));
+  p = newnode(OP_AND);
+  p->n_info.n_opnd.n_left = nd;
+  p->n_info.n_opnd.n_right = nd2;
+  return p;
+}
+
+struct node *
+ secondary(t)
+int t;
+{
+  struct node *n, *p;
+
+  if (t == LPAR) {
+	n = expr(lex(*++ipp));
+	if (lex(*++ipp) != RPAR) fatal("syntax error, ) expected", "");
+	return n;
+  }
+  if (t == NOT) {
+	n = secondary(lex(*++ipp));
+	p = newnode(NOT);
+	p->n_info.n_opnd.n_left = n;
+	return p;
+  }
+  return simple(t);
+}
+
+void checkarg(arg)
+char *arg;
+{
+  if (arg == 0) fatal("syntax error, argument expected", "");
+}
+
+struct node *
+ simple(t)
+int t;
+{
+  struct node *p = newnode(t);
+  struct exec *e;
+  struct stat est;
+  struct passwd *pw;
+  struct group *gr;
+  long l;
+  int i;
+
+  switch (t) {
+    case OP_TYPE:
+	checkarg(*++ipp);
+	switch (**ipp) {
+	  case 'b':
+		p->n_info.n_int.n_val = S_IFBLK;
+		break;
+	  case 'c':
+		p->n_info.n_int.n_val = S_IFCHR;
+		break;
+	  case 'd':
+		p->n_info.n_int.n_val = S_IFDIR;
+		break;
+	  case 'f':
+		p->n_info.n_int.n_val = S_IFREG;
+		break;
+	  case 'p':
+		p->n_info.n_int.n_val = S_IFIFO;
+		break;
+	  case 's':
+		p->n_info.n_int.n_val = ~0;
+		break;
+	  case 'l':
+#ifdef S_IFLNK
+		p->n_info.n_int.n_val = S_IFLNK;
+#else
+		p->n_info.n_int.n_val = ~0;	/* Always unequal. */
+#endif
+		break;
+	  default:
+		fatal("-type needs b, c, d, f, p, s or l", "");
+	}
+	break;
+    case OP_USER:
+	checkarg(*++ipp);
+	if (((pw = getpwnam(*ipp)) == NULL)
+	    && isnumber(*ipp, 10, 0))
+		number(*ipp, 10, &(p->n_info.n_int.n_val),
+		       &(p->n_info.n_int.n_sign));
+	else {
+		if (pw == NULL)
+			fatal("unknown user: ", *ipp);
+		p->n_info.n_int.n_val = pw->pw_uid;
+		p->n_info.n_int.n_sign = 0;
+	}
+	break;
+    case OP_GROUP:
+	checkarg(*++ipp);
+	if (((gr = getgrnam(*ipp)) == NULL)
+	    && isnumber(*ipp, 10, 0))
+		number(*ipp, 10, &(p->n_info.n_int.n_val),
+		       &(p->n_info.n_int.n_sign));
+	else {
+		if (gr == NULL)
+			fatal("unknown group: ", *ipp);
+		p->n_info.n_int.n_val = gr->gr_gid;
+		p->n_info.n_int.n_sign = 0;
+	}
+	break;
+    case OP_SIZE:
+	checkarg(*++ipp);
+	i = strlen(*ipp) - 1;
+	if ((*ipp)[i] == 'c') {
+		p->n_type = OP_SIZEC;	/* Count in bytes i.s.o. blocks */
+		(*ipp)[i] = '\0';
+	}
+	number(*ipp, 10, &(p->n_info.n_int.n_val),
+	       &(p->n_info.n_int.n_sign));
+	break;
+    case OP_LINKS:
+    case OP_INUM:
+	checkarg(*++ipp);
+	number(*ipp, 10, &(p->n_info.n_int.n_val),
+	       &(p->n_info.n_int.n_sign));
+	break;
+    case OP_PERM:
+	checkarg(*++ipp);
+	if (isnumber(*ipp, 8, 1)) number(*ipp, 8, &(p->n_info.n_int.n_val),
+		       &(p->n_info.n_int.n_sign));
+	else
+		fmode(*ipp, &(p->n_info.n_int.n_val),
+		      &(p->n_info.n_int.n_sign));
+	break;
+    case OP_ATIME:
+    case OP_CTIME:
+    case OP_MTIME:
+	checkarg(*++ipp);
+	number(*ipp, 10, &l, &(p->n_info.n_int.n_sign));
+	p->n_info.n_int.n_val = current_time - l * SECS_PER_DAY;
+	/* More than n days old means less than the absolute time */
+	p->n_info.n_int.n_sign *= -1;
+	break;
+    case OP_EXEC:
+    case OP_OK:
+	checkarg(*++ipp);
+	e = (struct exec *) Malloc(sizeof(struct exec));
+	e->e_cnt = 2;
+	e->e_vec[0] = SHELL;
+	p->n_info.n_exec = e;
+	while (*ipp) {
+		if (**ipp == ';' && (*ipp)[1] == '\0') {
+			e->e_vec[e->e_cnt] = 0;
+			break;
+		}
+		e->e_vec[(e->e_cnt)++] =
+			(**ipp == '{' && (*ipp)[1] == '}'
+		       && (*ipp)[2] == '\0') ? (char *) (-1) : *ipp;
+		ipp++;
+	}
+	if (*ipp == 0) fatal("-exec/-ok: ; missing", "");
+	if ((e->e_vec[1] = find_bin(e->e_vec[2])) == 0)
+		fatal("can't find program ", e->e_vec[2]);
+	if (t == OP_OK)
+		if ((tty = open("/dev/tty", O_RDWR)) < 0)
+			fatal("can't open /dev/tty", "");
+	break;
+    case OP_CNEWER:
+    case OP_NEWER:
+	checkarg(*++ipp);
+	if (LSTAT(*ipp, &est) == -1)
+		fatal("-newer: can't get status of ", *ipp);
+	p->n_info.n_int.n_val = est.st_mtime;
+	break;
+    case OP_NAME:
+	checkarg(*++ipp);
+	p->n_info.n_str = *ipp;
+	break;
+    case OP_XDEV:	xdev_flag = 1;	break;
+    case OP_DEPTH:	depth_flag = 1;	break;
+    case OP_PRUNE:
+    case OP_PRINT:
+    case OP_PRINT0:
+    case OP_NOUSER:	case OP_NOGROUP:	break;
+          default:
+	fatal("syntax error, operator expected", "");
+  }
+  if ((t == OP_PRINT) || (t == OP_PRINT0) || (t == OP_EXEC) || (t == OP_OK))
+	needprint = 0;
+
+  return p;
+}
+
+/*######################## DIAGNOSTICS ##############################*/
+
+void nonfatal(s1, s2)
+char *s1, *s2;
+{
+  fprintf(stderr, "%s: %s%s\n", prog, s1, s2);
+}
+
+void fatal(s1, s2)
+char *s1, *s2;
+{
+  nonfatal(s1, s2);
+  exit(1);
+}
+
+/*################### SMATCH #########################*/
+/* Don't try to understand the following one... */
+int smatch(s, t)		/* shell-like matching */
+char *s, *t;
+{
+  register n;
+
+  if (*t == '\0') return *s == '\0';
+  if (*t == '*') {
+	++t;
+	do
+		if (smatch(s, t)) return 1;
+	while (*s++ != '\0');
+	return 0;
+  }
+  if (*s == '\0') return 0;
+  if (*t == '\\') return (*s == *++t) ? smatch(++s, ++t) : 0;
+  if (*t == '?') return smatch(++s, ++t);
+  if (*t == '[') {
+	while (*++t != ']') {
+		if (*t == '\\') ++t;
+		if (*(t + 1) != '-')
+			if (*t == *s) {
+				while (*++t != ']')
+					if (*t == '\\') ++t;
+				return smatch(++s, ++t);
+			} else
+				continue;
+		if (*(t + 2) == ']') return(*s == *t || *s == '-');
+		n = (*(t + 2) == '\\') ? 3 : 2;
+		if (*s >= *t && *s <= *(t + n)) {
+			while (*++t != ']')
+				if (*t == '\\') ++t;
+			return smatch(++s, ++t);
+		}
+		t += n;
+	}
+	return 0;
+  }
+  return(*s == *t) ? smatch(++s, ++t) : 0;
+}
+
+/*####################### EXECUTE ###########################*/
+/* Do -exec or -ok */
+
+char *
+ find_bin(s)
+char *s;
+{
+  char *f, *l, buf[PATH_MAX];
+
+  if (*s == '/')		/* absolute path name */
+	return(access(s, 1) == 0) ? s : 0;
+  l = f = epath;
+  for (;;) {
+	if (*l == ':' || *l == 0) {
+		if (l == f) {
+			if (access(s, 1) == 0) return Salloc(s);
+			f++;
+		} else {
+			register char *p = buf, *q = s;
+
+			while (f != l) *p++ = *f++;
+			f++;
+			*p++ = '/';
+			while (*p++ = *q++) {
+			}
+			if (access(buf, 1) == 0) return Salloc(buf);
+		}
+		if (*l == 0) break;
+	}
+	l++;
+  }
+  return 0;
+}
+
+int execute(op, e, path)
+int op;
+struct exec *e;
+char *path;
+{
+  int s, pid;
+  char *argv[MAXARG];
+  register char **p, **q;
+
+  for (p = e->e_vec, q = argv; *p;)	/* replace the {}s */
+	if ((*q++ = *p++) == (char *) -1) q[-1] = path;
+  *q = '\0';
+  if (op == OP_OK) {
+	char answer[10];
+
+	for (p = &argv[2]; *p; p++) {
+		write(tty, *p, strlen(*p));
+		write(tty, " ", 1);
+	}
+	write(tty, "? ", 2);
+	if (read(tty, answer, 10) < 2 || *answer != 'y') return 0;
+  }
+  if ((pid = fork()) == -1) fatal("can't fork", "");
+  if (pid == 0) {
+	register i = 3;
+
+	while (close(i++) == 0) {
+	}			/* wow!!! */
+	execv(argv[1], &argv[2]);	/* binary itself? */
+	execv(argv[0], &argv[1]);	/* shell command? */
+	fatal("exec failure: ", argv[1]);	/* none of them! */
+	exit(127);
+  }
+  return wait(&s) == pid && s == 0;
+}
Index: /trunk/minix/commands/simple/finger.c
===================================================================
--- /trunk/minix/commands/simple/finger.c	(revision 9)
+++ /trunk/minix/commands/simple/finger.c	(revision 9)
@@ -0,0 +1,1093 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)finger.c 1.1 87/12/21 SMI"; /* from 5.8 3/13/86 */
+#endif /* not lint */
+
+/*
+ * This is a finger program.  It prints out useful information about users
+ * by digging it up from various system files.
+ *
+ * There are three output formats, all of which give login name, teletype
+ * line number, and login time.  The short output format is reminiscent
+ * of finger on ITS, and gives one line of information per user containing
+ * in addition to the minimum basic requirements (MBR), the full name of
+ * the user, his idle time and location.  The
+ * quick style output is UNIX who-like, giving only name, teletype and
+ * login time.  Finally, the long style output give the same information
+ * as the short (in more legible format), the home directory and shell
+ * of the user, and, if it exits, a copy of the file .plan in the users
+ * home directory.  Finger may be called with or without a list of people
+ * to finger -- if no list is given, all the people currently logged in
+ * are fingered.
+ *
+ * The program is validly called by one of the following:
+ *
+ *	finger			{short form list of users}
+ *	finger -l		{long form list of users}
+ *	finger -b		{briefer long form list of users}
+ *	finger -q		{quick list of users}
+ *	finger -i		{quick list of users with idle times}
+ *	finger namelist		{long format list of specified users}
+ *	finger -s namelist	{short format list of specified users}
+ *	finger -w namelist	{narrow short format list of specified users}
+ *
+ * where 'namelist' is a list of users login names.
+ * The other options can all be given after one '-', or each can have its
+ * own '-'.  The -f option disables the printing of headers for short and
+ * quick outputs.  The -b option briefens long format outputs.  The -p
+ * option turns off plans for long format outputs.
+ */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/netdb.h>
+#include <net/gen/socket.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_hdr.h>
+#include <net/gen/tcp_io.h>
+#include <net/hton.h>
+#include <net/netlib.h>
+
+#define NONOTHING	1		/* don't say "No plan", or "No mail" */
+
+#define NONET	0
+
+#define ASTERISK	'*'		/* ignore this in real name */
+#define COMMA		','		/* separator in pw_gecos field */
+#define COMMAND		'-'		/* command line flag char */
+#define SAMENAME	'&'		/* repeat login name in real name */
+#define TALKABLE	0220		/* tty is writable if this mode */
+
+struct utmp user;
+#define NMAX sizeof(user.ut_name)
+#define LMAX sizeof(user.ut_line)
+#define HMAX sizeof(user.ut_host)
+
+struct person {			/* one for each person fingered */
+	char *name;			/* name */
+	char tty[LMAX+1];		/* null terminated tty line */
+	char host[HMAX+1];		/* null terminated remote host name */
+	long loginat;			/* time of (last) login */
+	long idletime;			/* how long idle (if logged in) */
+	char *realname;			/* pointer to full name */
+	struct passwd *pwd;		/* structure of /etc/passwd stuff */
+	char loggedin;			/* person is logged in */
+	char writable;			/* tty is writable */
+	char original;			/* this is not a duplicate entry */
+	struct person *link;		/* link to next person */
+	char *where;			/* terminal location */
+	char hostt[HMAX+1];		/* login host */
+};
+
+#include <minix/paths.h>
+
+char LASTLOG[] = _PATH_LASTLOG;	/* last login info */
+char USERLOG[] = _PATH_UTMP;		/* who is logged in */
+char PLAN[] = "/.plan";			/* what plan file is */
+char PROJ[] = "/.project";		/* what project file */
+	
+int unbrief = 1;			/* -b option default */
+int header = 1;				/* -f option default */
+int hack = 1;				/* -h option default */
+int idle = 0;				/* -i option default */
+int large = 0;				/* -l option default */
+int match = 1;				/* -m option default */
+int plan = 1;				/* -p option default */
+int unquick = 1;			/* -q option default */
+int small = 0;				/* -s option default */
+int wide = 1;				/* -w option default */
+
+int unshort;
+int lf;					/* LASTLOG file descriptor */
+struct person *person1;			/* list of people */
+long tloc;				/* current time */
+
+#if !_MINIX
+char *strcpy();
+char *ctime();
+#endif
+
+char *prog_name;
+
+int main (int argc, char *argv[]);
+static void doall(void);
+static void donames(char **args);
+static void print(void);
+static void fwopen(void);
+static void decode(struct person *pers);
+static void fwclose(void);
+static int netfinger (char *name);
+static int matchcmp (char *gname, char *login, char *given);
+static void quickprint (struct person *pers);
+static void shortprint (struct person *pers);
+static void personprint (struct person *pers);
+static int AlreadyPrinted(int uid);
+static int AnyMail (char *name);
+static struct passwd *pwdcopy(struct passwd *pfrom);
+static void findidle (struct person *pers);
+static int ltimeprint (char *dt, long *before, char *after);
+static void stimeprint (long *dt);
+static void findwhen (struct person *pers);
+static int namecmp (char *name1, char *name2);
+
+main(argc, argv)
+	int argc;
+	register char **argv;
+{
+	FILE *fp;
+	register char *s;
+
+	prog_name= argv[0];
+
+	/* parse command line for (optional) arguments */
+	while (*++argv && **argv == COMMAND)
+		for (s = *argv + 1; *s; s++)
+			switch (*s) {
+			case 'b':
+				unbrief = 0;
+				break;
+			case 'f':
+				header = 0;
+				break;
+			case 'h':
+				hack = 0;
+				break;
+			case 'i':
+				idle = 1;
+				unquick = 0;
+				break;
+			case 'l':
+				large = 1;
+				break;
+			case 'm':
+				match = 0;
+				break;
+			case 'p':
+				plan = 0;
+				break;
+			case 'q':
+				unquick = 0;
+				break;
+			case 's':
+				small = 1;
+				break;
+			case 'w':
+				wide = 0;
+				break;
+			default:
+				fprintf(stderr, "Usage: finger [-bfhilmpqsw] [login1 [login2 ...] ]\n");
+				exit(1);
+			}
+	if (unquick || idle)
+		time(&tloc);
+	/*
+	 * *argv == 0 means no names given
+	 */
+	if (*argv == 0)
+		doall();
+	else
+		donames(argv);
+	if (person1)
+		print();
+	exit(0);
+}
+
+static void doall()
+{
+	register struct person *p;
+	register struct passwd *pw;
+	int uf;
+	char name[NMAX + 1];
+
+	unshort = large;
+	if ((uf = open(USERLOG, 0)) < 0) {
+		fprintf(stderr, "finger: error opening %s\n", USERLOG);
+		exit(2);
+	}
+	if (unquick) {
+		setpwent();
+		fwopen();
+	}
+	while (read(uf, (char *)&user, sizeof user) == sizeof user) {
+		if (user.ut_name[0] == 0)
+			continue;
+		if (person1 == 0)
+			p = person1 = (struct person *) malloc(sizeof *p);
+		else {
+			p->link = (struct person *) malloc(sizeof *p);
+			p = p->link;
+		}
+		bcopy(user.ut_name, name, NMAX);
+		name[NMAX] = 0;
+		bcopy(user.ut_line, p->tty, LMAX);
+		p->tty[LMAX] = 0;
+		bcopy(user.ut_host, p->host, HMAX);
+		p->host[HMAX] = 0;
+		p->loginat = user.ut_time;
+		p->pwd = 0;
+		p->loggedin = 1;
+		p->where = NULL;
+		if (unquick && (pw = getpwnam(name))) {
+			p->pwd = pwdcopy(pw);
+			decode(p);
+			p->name = p->pwd->pw_name;
+		} else
+			p->name = strcpy(malloc(strlen(name) + 1), name);
+	}
+	if (unquick) {
+		fwclose();
+		endpwent();
+	}
+	close(uf);
+	if (person1 == 0) {
+		printf("No one logged on\n");
+		return;
+	}
+	p->link = 0;
+}
+
+static void donames(argv)
+	char **argv;
+{
+	register struct person *p;
+	register struct passwd *pw;
+	int uf;
+
+	/*
+	 * get names from command line and check to see if they're
+	 * logged in
+	 */
+	unshort = !small;
+	for (; *argv != 0; argv++) {
+		if (netfinger(*argv))
+			continue;
+		if (person1 == 0)
+			p = person1 = (struct person *) malloc(sizeof *p);
+		else {
+			p->link = (struct person *) malloc(sizeof *p);
+			p = p->link;
+		}
+		p->name = *argv;
+		p->loggedin = 0;
+		p->original = 1;
+		p->pwd = 0;
+	}
+	if (person1 == 0)
+		return;
+	p->link = 0;
+	/*
+	 * if we are doing it, read /etc/passwd for the useful info
+	 */
+	if (unquick) {
+		setpwent();
+		if (!match) {
+			for (p = person1; p != 0; p = p->link)
+				if (pw = getpwnam(p->name))
+					p->pwd = pwdcopy(pw);
+		} else while ((pw = getpwent()) != 0) {
+			for (p = person1; p != 0; p = p->link) {
+				if (!p->original)
+					continue;
+				if (strcmp(p->name, pw->pw_name) != 0 &&
+				    !matchcmp(pw->pw_gecos, pw->pw_name, p->name))
+					continue;
+				if (p->pwd == 0)
+					p->pwd = pwdcopy(pw);
+				else {
+					struct person *new;
+					/*
+					 * handle multiple login names, insert
+					 * new "duplicate" entry behind
+					 */
+					new = (struct person *)
+						malloc(sizeof *new);
+					new->pwd = pwdcopy(pw);
+					new->name = p->name;
+					new->original = 1;
+					new->loggedin = 0;
+					new->link = p->link;
+					p->original = 0;
+					p->link = new;
+					p = new;
+				}
+			}
+		}
+		endpwent();
+	}
+	/* Now get login information */
+	if ((uf = open(USERLOG, 0)) < 0) {
+		fprintf(stderr, "finger: error opening %s\n", USERLOG);
+		exit(2);
+	}
+	while (read(uf, (char *)&user, sizeof user) == sizeof user) {
+		if (*user.ut_name == 0)
+			continue;
+		for (p = person1; p != 0; p = p->link) {
+			if (p->loggedin == 2)
+				continue;
+			if (strncmp(p->pwd ? p->pwd->pw_name : p->name,
+				    user.ut_name, NMAX) != 0)
+				continue;
+			if (p->loggedin == 0) {
+				bcopy(user.ut_line, p->tty, LMAX);
+				p->tty[LMAX] = 0;
+				bcopy(user.ut_host, p->host, HMAX);
+				p->host[HMAX] = 0;
+				p->loginat = user.ut_time;
+				p->loggedin = 1;
+			} else {	/* p->loggedin == 1 */
+				struct person *new;
+				new = (struct person *) malloc(sizeof *new);
+				new->name = p->name;
+				bcopy(user.ut_line, new->tty, LMAX);
+				new->tty[LMAX] = 0;
+				bcopy(user.ut_host, new->host, HMAX);
+				new->host[HMAX] = 0;
+				new->loginat = user.ut_time;
+				new->pwd = p->pwd;
+				new->loggedin = 1;
+				new->original = 0;
+				new->link = p->link;
+				p->loggedin = 2;
+				p->link = new;
+				p = new;
+			}
+		}
+	}
+	close(uf);
+	if (unquick) {
+		fwopen();
+		for (p = person1; p != 0; p = p->link)
+			decode(p);
+		fwclose();
+	}
+}
+
+static void print()
+{
+	register FILE *fp;
+	register struct person *p;
+	register char *s;
+	register c;
+
+	/*
+	 * print out what we got
+	 */
+	if (header) {
+		if (unquick) {
+			if (!unshort)
+				if (wide)
+					printf("Login       Name              TTY Idle    When            Where\n");
+				else
+					printf("Login    TTY Idle    When            Where\n");
+		} else {
+			printf("Login      TTY            When");
+			if (idle)
+				printf("             Idle");
+			putchar('\n');
+		}
+	}
+	for (p = person1; p != 0; p = p->link) {
+		if (!unquick) {
+			quickprint(p);
+			continue;
+		}
+		if (!unshort) {
+			shortprint(p);
+			continue;
+		}
+		personprint(p);
+		if (p->pwd != 0 && !AlreadyPrinted(p->pwd->pw_uid)) {
+			AnyMail(p->pwd->pw_name);
+			if (hack) {
+				s = malloc(strlen(p->pwd->pw_dir) +
+					sizeof PROJ);
+				strcpy(s, p->pwd->pw_dir);
+				strcat(s, PROJ);
+				if ((fp = fopen(s, "r")) != 0) {
+					printf("Project: ");
+					while ((c = getc(fp)) != EOF) {
+						if (c == '\n')
+							break;
+						if (isprint(c) || isspace(c))
+							putchar(c);
+						else
+							putchar(c ^ 100);
+					}
+					fclose(fp);
+					putchar('\n');
+				}
+				free(s);
+			}
+			if (plan) {
+				s = malloc(strlen(p->pwd->pw_dir) +
+					sizeof PLAN);
+				strcpy(s, p->pwd->pw_dir);
+				strcat(s, PLAN);
+				if ((fp = fopen(s, "r")) == 0) {
+					if (!NONOTHING) printf("No Plan.\n");
+				} else {
+					printf("Plan:\n");
+					while ((c = getc(fp)) != EOF)
+						if (isprint(c) || isspace(c))
+							putchar(c);
+						else
+							putchar(c ^ 100);
+					fclose(fp);
+				}
+				free(s);
+			}
+		}
+		if (p->link != 0)
+			putchar('\n');
+	}
+}
+
+/*
+ * Duplicate a pwd entry.
+ * Note: Only the useful things (what the program currently uses) are copied.
+ */
+static struct passwd *
+pwdcopy(pfrom)
+	register struct passwd *pfrom;
+{
+	register struct passwd *pto;
+
+	pto = (struct passwd *) malloc(sizeof *pto);
+#define savestr(s) strcpy(malloc(strlen(s) + 1), s)
+	pto->pw_name = savestr(pfrom->pw_name);
+	pto->pw_uid = pfrom->pw_uid;
+	pto->pw_gecos = savestr(pfrom->pw_gecos);
+	pto->pw_dir = savestr(pfrom->pw_dir);
+	pto->pw_shell = savestr(pfrom->pw_shell);
+#undef savestr
+	return pto;
+}
+
+/*
+ * print out information on quick format giving just name, tty, login time
+ * and idle time if idle is set.
+ */
+static void quickprint(pers)
+	register struct person *pers;
+{
+	printf("%-*.*s  ", NMAX, NMAX, pers->name);
+	if (pers->loggedin) {
+		if (idle) {
+			findidle(pers);
+			printf("%c%-*s %-16.16s", pers->writable ? ' ' : '*',
+				LMAX, pers->tty, ctime(&pers->loginat));
+			ltimeprint("   ", &pers->idletime, "");
+		} else
+			printf(" %-*s %-16.16s", LMAX,
+				pers->tty, ctime(&pers->loginat));
+		putchar('\n');
+	} else
+		printf("          Not Logged In\n");
+}
+
+/*
+ * print out information in short format, giving login name, full name,
+ * tty, idle time, login time, and host.
+ */
+static void shortprint(pers)
+	register struct person *pers;
+{
+	char *p;
+	char dialup;
+
+	if (pers->pwd == 0) {
+		printf("%-15s       ???\n", pers->name);
+		return;
+	}
+	printf("%-*s", NMAX, pers->pwd->pw_name);
+	dialup = 0;
+	if (wide) {
+		if (pers->realname)
+			printf(" %-20.20s", pers->realname);
+		else
+			printf("        ???          ");
+	}
+	putchar(' ');
+	if (pers->loggedin && !pers->writable)
+		putchar('*');
+	else
+		putchar(' ');
+	if (*pers->tty) {
+		if (pers->tty[0] == 't' && pers->tty[1] == 't' &&
+		    pers->tty[2] == 'y') {
+			if (pers->tty[3] == 'd' && pers->loggedin)
+				dialup = 1;
+			printf("%-2.2s ", pers->tty + 3);
+		} else
+			printf("%-2.2s ", pers->tty);
+	} else
+		printf("   ");
+	p = ctime(&pers->loginat);
+	if (pers->loggedin) {
+		stimeprint(&pers->idletime);
+		printf(" %3.3s %-5.5s ", p, p + 11);
+	} else if (pers->loginat == 0)
+		printf(" < .  .  .  . >");
+	else if (tloc - pers->loginat >= 180L * 24 * 60 * 60)
+		printf(" <%-6.6s, %-4.4s>", p + 4, p + 20);
+	else
+		printf(" <%-12.12s>", p + 4);
+	if (pers->host[0])
+		printf(" %-20.20s", pers->host);
+	putchar('\n');
+}
+
+
+/*
+ * print out a person in long format giving all possible information.
+ * directory and shell are inhibited if unbrief is clear.
+ */
+static void
+personprint(pers)
+	register struct person *pers;
+{
+	if (pers->pwd == 0) {
+		printf("Login name: %-10s\t\t\tIn real life: ???\n",
+			pers->name);
+		return;
+	}
+	printf("Login name: %-10s", pers->pwd->pw_name);
+	if (pers->loggedin && !pers->writable)
+		printf("	(messages off)	");
+	else
+		printf("			");
+	if (pers->realname)
+		printf("In real life: %s", pers->realname);
+	if (unbrief) {
+		printf("\nDirectory: %-25s", pers->pwd->pw_dir);
+		if (*pers->pwd->pw_shell)
+			printf("\tShell: %-s", pers->pwd->pw_shell);
+	}
+	if (pers->loggedin) {
+		register char *ep = ctime(&pers->loginat);
+		if (*pers->host) {
+			printf("\nOn since %15.15s on %s from %s",
+				&ep[4], pers->tty, pers->host);
+			ltimeprint("\n", &pers->idletime, " Idle Time");
+		} else {
+			printf("\nOn since %15.15s on %-*s",
+				&ep[4], LMAX, pers->tty);
+			ltimeprint("\t", &pers->idletime, " Idle Time");
+		}
+	} else if (pers->loginat == 0) {
+		if (lf >= 0) printf("\nNever logged in.");
+	} else if (tloc - pers->loginat > 180L * 24 * 60 * 60) {
+		register char *ep = ctime(&pers->loginat);
+		printf("\nLast login %10.10s, %4.4s on %s",
+			ep, ep+20, pers->tty);
+		if (*pers->host)
+			printf(" from %s", pers->host);
+	} else {
+		register char *ep = ctime(&pers->loginat);
+		printf("\nLast login %16.16s on %s", ep, pers->tty);
+		if (*pers->host)
+			printf(" from %s", pers->host);
+	}
+	putchar('\n');
+}
+
+
+/*
+ * decode the information in the gecos field of /etc/passwd
+ */
+static void
+decode(pers)
+	register struct person *pers;
+{
+	char buffer[256];
+	register char *bp, *gp, *lp;
+	int alldigits;
+	int hasspace;
+	int len;
+
+	pers->realname = 0;
+	if (pers->pwd == 0)
+		return;
+	gp = pers->pwd->pw_gecos;
+	bp = buffer;
+	if (*gp == ASTERISK)
+		gp++;
+	while (*gp && *gp != COMMA) 			/* name */
+		if (*gp == SAMENAME) {
+			lp = pers->pwd->pw_name;
+			if (islower(*lp))
+				*bp++ = toupper(*lp++);
+			while (*bp++ = *lp++)
+				;
+			bp--;
+			gp++;
+		} else
+			*bp++ = *gp++;
+	*bp++ = 0;
+	if ((len = bp - buffer) > 1)
+		pers->realname = strcpy(malloc(len), buffer);
+	if (pers->loggedin)
+		findidle(pers);
+	else
+		findwhen(pers);
+}
+
+/*
+ * find the last log in of a user by checking the LASTLOG file.
+ * the entry is indexed by the uid, so this can only be done if
+ * the uid is known (which it isn't in quick mode)
+ */
+
+static void
+fwopen()
+{
+	if ((lf = open(LASTLOG, 0)) < 0) {
+		if (errno == ENOENT) return;
+		fprintf(stderr, "finger: %s open error\n", LASTLOG);
+	}
+}
+
+static void
+findwhen(pers)
+	register struct person *pers;
+{
+	struct utmp ll;
+#define ll_line ut_line
+#define ll_host ut_host
+#define ll_time ut_time
+
+	int i;
+
+	if (lf >= 0) {
+		lseek(lf, (long)pers->pwd->pw_uid * sizeof ll, 0);
+		if ((i = read(lf, (char *)&ll, sizeof ll)) == sizeof ll) {
+			bcopy(ll.ll_line, pers->tty, LMAX);
+			pers->tty[LMAX] = 0;
+			bcopy(ll.ll_host, pers->host, HMAX);
+			pers->host[HMAX] = 0;
+			pers->loginat = ll.ll_time;
+		} else {
+			if (i != 0)
+				fprintf(stderr, "finger: %s read error\n",
+					LASTLOG);
+			pers->tty[0] = 0;
+			pers->host[0] = 0;
+			pers->loginat = 0L;
+		}
+	} else {
+		pers->tty[0] = 0;
+		pers->host[0] = 0;
+		pers->loginat = 0L;
+	}
+}
+
+static void fwclose()
+{
+	if (lf >= 0)
+		close(lf);
+}
+
+/*
+ * find the idle time of a user by doing a stat on /dev/tty??,
+ * where tty?? has been gotten from USERLOG, supposedly.
+ */
+static void
+findidle(pers)
+	register struct person *pers;
+{
+	struct stat ttystatus;
+	static char buffer[20] = "/dev/";
+	long t;
+#define TTYLEN 5
+
+	strcpy(buffer + TTYLEN, pers->tty);
+	buffer[TTYLEN+LMAX] = 0;
+	if (stat(buffer, &ttystatus) < 0) {
+		fprintf(stderr, "finger: Can't stat %s\n", buffer);
+		exit(4);
+	}
+	time(&t);
+	if (t < ttystatus.st_atime)
+		pers->idletime = 0L;
+	else
+		pers->idletime = t - ttystatus.st_atime;
+	pers->writable = (ttystatus.st_mode & TALKABLE) == TALKABLE;
+}
+
+/*
+ * print idle time in short format; this program always prints 4 characters;
+ * if the idle time is zero, it prints 4 blanks.
+ */
+static void
+stimeprint(dt)
+	long *dt;
+{
+	register struct tm *delta;
+
+	delta = gmtime(dt);
+	if (delta->tm_yday == 0)
+		if (delta->tm_hour == 0)
+			if (delta->tm_min == 0)
+				printf("    ");
+			else
+				printf("  %2d", delta->tm_min);
+		else
+			if (delta->tm_hour >= 10)
+				printf("%3d:", delta->tm_hour);
+			else
+				printf("%1d:%02d",
+					delta->tm_hour, delta->tm_min);
+	else
+		printf("%3dd", delta->tm_yday);
+}
+
+/*
+ * print idle time in long format with care being taken not to pluralize
+ * 1 minutes or 1 hours or 1 days.
+ * print "prefix" first.
+ */
+static int
+ltimeprint(before, dt, after)
+	long *dt;
+	char *before, *after;
+{
+	register struct tm *delta;
+
+	delta = gmtime(dt);
+	if (delta->tm_yday == 0 && delta->tm_hour == 0 && delta->tm_min == 0 &&
+	    delta->tm_sec <= 10)
+		return (0);
+	printf("%s", before);
+	if (delta->tm_yday >= 10)
+		printf("%d days", delta->tm_yday);
+	else if (delta->tm_yday > 0)
+		printf("%d day%s %d hour%s",
+			delta->tm_yday, delta->tm_yday == 1 ? "" : "s",
+			delta->tm_hour, delta->tm_hour == 1 ? "" : "s");
+	else
+		if (delta->tm_hour >= 10)
+			printf("%d hours", delta->tm_hour);
+		else if (delta->tm_hour > 0)
+			printf("%d hour%s %d minute%s",
+				delta->tm_hour, delta->tm_hour == 1 ? "" : "s",
+				delta->tm_min, delta->tm_min == 1 ? "" : "s");
+		else
+			if (delta->tm_min >= 10)
+				printf("%2d minutes", delta->tm_min);
+			else if (delta->tm_min == 0)
+				printf("%2d seconds", delta->tm_sec);
+			else
+				printf("%d minute%s %d second%s",
+					delta->tm_min,
+					delta->tm_min == 1 ? "" : "s",
+					delta->tm_sec,
+					delta->tm_sec == 1 ? "" : "s");
+	printf("%s", after);
+}
+
+static int
+matchcmp(gname, login, given)
+	register char *gname;
+	char *login;
+	char *given;
+{
+	char buffer[100];
+	register char *bp, *lp;
+	register c;
+
+	if (*gname == ASTERISK)
+		gname++;
+	lp = 0;
+	bp = buffer;
+	for (;;)
+		switch (c = *gname++) {
+		case SAMENAME:
+			for (lp = login; bp < buffer + sizeof buffer
+					 && (*bp++ = *lp++);)
+				;
+			bp--;
+			break;
+		case ' ':
+		case COMMA:
+		case '\0':
+			*bp = 0;
+			if (namecmp(buffer, given))
+				return (1);
+			if (c == COMMA || c == 0)
+				return (0);
+			bp = buffer;
+			break;
+		default:
+			if (bp < buffer + sizeof buffer)
+				*bp++ = c;
+		}
+	/*NOTREACHED*/
+}
+
+static int
+namecmp(name1, name2)
+	register char *name1, *name2;
+{
+	register c1, c2;
+
+	for (;;) {
+		c1 = *name1++;
+		if (islower(c1))
+			c1 = toupper(c1);
+		c2 = *name2++;
+		if (islower(c2))
+			c2 = toupper(c2);
+		if (c1 != c2)
+			break;
+		if (c1 == 0)
+			return (1);
+	}
+	if (!c1) {
+		for (name2--; isdigit(*name2); name2++)
+			;
+		if (*name2 == 0)
+			return (1);
+	} else if (!c2) {
+		for (name1--; isdigit(*name1); name1++)
+			;
+		if (*name2 == 0)
+			return (1);
+	}
+	return (0);
+}
+
+#if NONET
+static int
+netfinger(name)
+char *name;
+{
+	return 0;
+}
+#else
+static int
+netfinger(name)
+	char *name;
+{
+	char *host;
+	char fname[100];
+	struct hostent *hp;
+	struct servent *sp;
+	int s, result;
+#if !_MINIX
+	char *rindex();
+#endif
+	register FILE *f;
+	register int c;
+	register int lastc;
+	nwio_tcpconf_t tcpconf;
+	nwio_tcpcl_t tcpconnopt;
+	char *tcp_device;
+
+	if (name == NULL)
+		return (0);
+	host = rindex(name, '@');
+	if (host == NULL)
+		return (0);
+	*host++ = 0;
+	hp = gethostbyname(host);
+	if (hp == NULL) {
+		static struct hostent def;
+		static ipaddr_t defaddr;
+		static char namebuf[128];
+
+		defaddr = inet_addr(host);
+		if (defaddr == -1) {
+			printf("unknown host: %s\n", host);
+			return (1);
+		}
+		strcpy(namebuf, host);
+		def.h_name = namebuf;
+		def.h_addr = (char *)&defaddr;
+		def.h_length = sizeof (ipaddr_t);
+		def.h_addrtype = AF_INET;
+		def.h_aliases = 0;
+		hp = &def;
+	}
+	printf("[%s] ", hp->h_name);
+	fflush(stdout);
+
+	tcp_device= getenv("TCP_DEVICE");
+	if (tcp_device == NULL)
+		tcp_device= TCP_DEVICE;
+	s= open (tcp_device, O_RDWR);
+	if (s == -1)
+	{
+		fprintf(stderr, "%s: unable to open %s (%s)\n",
+			prog_name, tcp_device, strerror(errno));
+		exit(1);
+	}
+	tcpconf.nwtc_flags= NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
+	tcpconf.nwtc_remaddr= *(ipaddr_t *)hp->h_addr;
+	tcpconf.nwtc_remport= htons(TCPPORT_FINGER);
+
+	result= ioctl (s, NWIOSTCPCONF, &tcpconf);
+	if (result<0)
+	{
+		fprintf(stderr, "%s\n", strerror(errno));
+		exit(1);
+	}
+
+	tcpconnopt.nwtcl_flags= 0;
+
+	do
+	{
+		result= ioctl (s, NWIOTCPCONN, &tcpconnopt);
+		if (result<0 && errno== EAGAIN)
+		{
+			fprintf(stderr, "got EAGAIN error, sleeping 2s\n");
+			sleep(2);
+		}
+	} while (result<0 && errno == EAGAIN);
+	if (result<0)
+	{
+		fprintf(stderr, "%s\n", strerror(errno));
+		exit(1);
+	}
+	printf("\r\n");
+	if (large) write(s, "/W ", 3);
+	write(s, name, strlen(name));
+	write(s, "\r\n", 2);
+	f = fdopen(s, "r");
+	while ((c = getc(f)) != EOF) {
+/*
+		switch(c) {
+		case 0210:
+		case 0211:
+		case 0212:
+		case 0214:
+			c -= 0200;
+			break;
+		case 0215:
+			c = '\n';
+			break;
+		}
+*/
+		c &= ~0200;
+		if (c == '\r')
+		{
+			c= getc(f) & ~0200;
+			if (c == '\012')
+			{
+				lastc= c;
+				putchar('\n');
+				continue;
+			}
+			else
+				putchar('\r');
+		}
+		lastc = c;
+		if (isprint(c) || isspace(c))
+			putchar(c);
+		else
+			putchar(c ^ 100);
+	}
+	if (lastc != '\n')
+		putchar('\n');
+	(void)fclose(f);
+	return (1);
+}
+#endif
+
+/*
+ *	AnyMail - takes a username (string pointer thereto), and
+ *	prints on standard output whether there is any unread mail,
+ *	and if so, how old it is.	(JCM@Shasta 15 March 80)
+ */
+#define preamble "/usr/spool/mail/"	/* mailboxes are there */
+static int
+AnyMail(name)
+char *name;
+{
+	struct stat buf;		/* space for file status buffer */
+	char *mbxdir = preamble; 	/* string with path preamble */
+	char *mbxpath;			/* space for entire pathname */
+
+#if !_MINIX
+	char *ctime();			/* convert longword time to ascii */
+#endif
+	char *timestr;
+
+	mbxpath = malloc(strlen(name) + strlen(preamble) + 1);
+
+	strcpy(mbxpath, mbxdir);	/* copy preamble into path name */
+	strcat(mbxpath, name);		/* concatenate user name to path */
+
+	if (stat(mbxpath, &buf) == -1 || buf.st_size == 0) {
+	    /* Mailbox is empty or nonexistent */
+	    if (!NONOTHING) printf("No unread mail\n");
+        } else {
+	    if (buf.st_mtime == buf.st_atime) {
+		/* There is something in the mailbox, but we can't really
+		 *   be sure whether it is mail held there by the user
+		 *   or a (single) new message that was placed in a newly
+		 *   recreated mailbox, so we punt and call it "unread mail."
+		 */
+		printf("Unread mail since ");
+	        printf(ctime(&buf.st_mtime));
+	    } else {
+		/* New mail has definitely arrived since the last time
+		 *   mail was read.  mtime is the time the most recent
+		 *   message arrived; atime is either the time the oldest
+		 *   unread message arrived, or the last time the mail
+		 *   was read.
+		 */
+		printf("New mail received ");
+		timestr = ctime(&buf.st_mtime);	/* time last modified */
+		timestr[24] = '\0';		/* suppress newline (ugh) */
+		printf(timestr);
+		printf(";\n  unread since ");
+	        printf(ctime(&buf.st_atime));	/* time last accessed */
+	    }
+	}
+	
+	free(mbxpath);
+}
+
+/*
+ * return true iff we've already printed project/plan for this uid;
+ * if not, enter this uid into table (so this function has a side-effect.)
+ */
+#define	PPMAX	200		/* assume no more than 200 logged-in users */
+int	PlanPrinted[PPMAX+1];
+int	PPIndex = 0;		/* index of next unused table entry */
+
+static int
+AlreadyPrinted(uid)
+int uid;
+{
+	int i = 0;
+	
+	while (i++ < PPIndex) {
+	    if (PlanPrinted[i] == uid)
+		return(1);
+	}
+	if (i < PPMAX) {
+	    PlanPrinted[i] = uid;
+	    PPIndex++;
+	}
+	return(0);
+}
Index: /trunk/minix/commands/simple/fix.c
===================================================================
--- /trunk/minix/commands/simple/fix.c	(revision 9)
+++ /trunk/minix/commands/simple/fix.c	(revision 9)
@@ -0,0 +1,224 @@
+/* fix file difflist - update file from difflist     Author: Erik Baalbergen */
+
+
+/* Notes: files old and old.patch are equal after the following commands
+     diff old new > difflist
+     patch old difflist > old.patch
+   * the diff output is assumed to be produced by my diff program.
+   * the difflist has the following form:
+     difflist ::= chunk*
+     chunk ::= append | delete | change ;
+     append ::= n1 'a' n2 [',' n3]? '\n' ['> ' line '\n'](n3 - n2 + 1)
+     delete ::= n1 [',' n2]? 'd' n3 '\n' ['< ' line '\n'](n2 - n1 + 1)
+     change ::= n1 [',' n2]? 'c' n3 [',' n4]? '\n'
+	      ['< ' line '\n'](n2 - n1 + 1)
+	      '---\n'
+	      ['> ' line '\n'](n4 - n3 + 1)
+     where
+     - n[1234] is an unsigned integer
+     - "[pat](expr)" means "(expr) occurences of pat"
+     - "[pat]?" means "either pat or nothing"
+   * the information in the diff listing is checked against the file to which
+     it is applied; an error is printed if there is a conflict
+*/
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#define IGNORE_WHITE_SPACE	/* This makes it white space insensitive */
+
+#ifdef IGNORE_WHITE_SPACE
+#define strcmp strwcmp
+#endif
+
+#define LINELEN	1024
+
+char *prog = 0, *processing = 0;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(char *getline, (FILE *fp, char *b));
+_PROTOTYPE(char *range, (char *s, int *p1, int *p2));
+_PROTOTYPE(int getcommand, (FILE *fp, int *o1, int *o2, char *pcmd, int *n1, int *n2));
+_PROTOTYPE(void fatal, (char *s, ...));
+_PROTOTYPE(int strwcmp, (char *s1, char *s2));
+_PROTOTYPE(int whitespace, (int ch));
+
+char *
+ getline(fp, b)
+FILE *fp;
+char *b;
+{
+  if (fgets(b, LINELEN, fp) == NULL) fatal("unexpected eof");
+
+  return b;
+}
+
+#define copy(str) printf("%s", str)
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  char cmd, *fl, *fd, obuf[LINELEN], nbuf[LINELEN];
+  int o1, o2, n1, n2, here;
+  FILE *fpf, *fpd;
+
+  prog = argv[0];
+  processing = argv[1];
+  if (argc != 3) fatal("use: %s original-file diff-list-file", prog);
+  if ((fpf = fopen(argv[1], "r")) == NULL) fatal("can't read %s", argv[1]);
+  if ((fpd = fopen(argv[2], "r")) == NULL) fatal("can't read %s", argv[2]);
+  here = 0;
+  while (getcommand(fpd, &o1, &o2, &cmd, &n1, &n2)) {
+	while (here < o1 - 1) {
+		here++;
+		copy(getline(fpf, obuf));
+	}
+	switch (cmd) {
+	    case 'c':
+	    case 'd':
+		if (cmd == 'd' && n1 != n2) fatal("delete count conflict");
+		while (o1 <= o2) {
+			fl = getline(fpf, obuf);
+			here++;
+			fd = getline(fpd, nbuf);
+			if (strncmp(fd, "<", (size_t)1))
+				fatal("illegal delete line");
+			if (strcmp(fl, fd + 2))
+				fatal("delete line conflict");
+			o1++;
+		}
+		if (cmd == 'd') break;
+		if (strcmp(getline(fpd, nbuf), "---\n"))
+			fatal("illegal separator in chunk");
+		/* FALLTHROUGH */
+	    case 'a':
+		if (cmd == 'a') {
+			if (o1 != o2) fatal("append count conflict");
+			copy(getline(fpf, obuf));
+			here++;
+		}
+		while (n1 <= n2) {
+			if (strncmp(getline(fpd, nbuf), ">", (size_t)1))
+				fatal("illegal append line");
+			copy(nbuf + 2);
+			n1++;
+		}
+		break;
+	}
+  }
+  while (fgets(obuf, LINELEN, fpf) != NULL) copy(obuf);
+  return(0);
+}
+
+char *
+ range(s, p1, p2)
+char *s;
+int *p1, *p2;
+{
+  register int v1 = 0, v2;
+
+  while (isdigit(*s)) v1 = 10 * v1 + *s++ - '0';
+  v2 = v1;
+  if (*s == ',') {
+	s++;
+	v2 = 0;
+	while (isdigit(*s)) v2 = 10 * v2 + *s++ - '0';
+  }
+  if (v1 > v2) fatal("illegal range");
+  *p1 = v1;
+  *p2 = v2;
+  return s;
+}
+
+int getcommand(fp, o1, o2, pcmd, n1, n2)
+FILE *fp;
+int *o1, *o2, *n1, *n2;
+char *pcmd;
+{
+  char buf[LINELEN];
+  register char *s;
+  char cmd;
+
+  if ((s = fgets(buf, LINELEN, fp)) == NULL) return 0;
+  s = range(s, o1, o2);
+  if ((cmd = *s++) != 'a' && cmd != 'c' && cmd != 'd')
+	fatal("illegal command");
+  s = range(s, n1, n2);
+  if (*s != '\n' && s[1] != '\0')
+	fatal("extra characters at end of command: %s", s);
+  *pcmd = cmd;
+  return 1;
+}
+
+#ifdef __STDC__
+void fatal(char *s, ...)
+{
+  va_list args;
+
+  va_start (args, s);
+  fprintf(stderr, "%s: processing: %s fatal: ", prog, processing);
+  vfprintf(stderr, s, args);
+  fprintf(stderr, "\n");
+  va_end(args);
+  exit(1);
+}
+#else
+/* the K&R lib does not have vfprintf */
+void fatal(s, a)
+char *s, *a;
+{
+  fprintf(stderr, "%s: processing: %s fatal: ", prog, processing);
+  fprintf(stderr, s, a);
+  fprintf(stderr, "\n");
+  exit(1);
+}
+#endif
+
+#ifdef IGNORE_WHITE_SPACE
+
+/* This routine is a white space insensitive version of strcmp.
+   It is needed for testing things which might have undergone
+   tab conversion or trailing space removal
+   Bret Mckee June, 1988 */
+
+int strwcmp(s1, s2)
+char *s1, *s2;
+{
+  char *x1 = s1, *x2 = s2;
+
+  /* Remove leading white space */
+  while (whitespace(*s1)) s1++;
+  while (whitespace(*s2)) s2++;
+  do {
+	while ((*s1 == *s2) && *s1 && *s2) {
+		s1++;
+		s2++;
+	}
+	;			/* consume identical characters */
+	while (whitespace(*s1)) s1++;
+	while (whitespace(*s2)) s2++;
+  } while (*s1 && *s2 && (*s1 == *s2));
+  if (*s1 - *s2)
+	fprintf(stderr, "Failing for (%x)[%s]\n            (%x)[%s]\n",
+		(int) *s1, x1, (int) *s2, x2);
+  return(*s1 - *s2);
+}
+
+int whitespace(ch)
+char ch;
+{
+  switch (ch) {
+      case ' ':
+      case '\n':
+      case 0x0D:
+      case '\t':
+	return(1);
+      default:	return(0);
+}
+}
+
+#endif
Index: /trunk/minix/commands/simple/fold.c
===================================================================
--- /trunk/minix/commands/simple/fold.c	(revision 9)
+++ /trunk/minix/commands/simple/fold.c	(revision 9)
@@ -0,0 +1,70 @@
+/* fold - folds long lines		Author: Terrence W. Holm */
+
+/*  Usage:  fold  [ -width ]  [ file ... ]  */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#define  TAB		8
+#define  DEFAULT_WIDTH  80
+
+int column = 0;			/* Current column, retained between files  */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void Fold, (FILE *f, int width));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int width = DEFAULT_WIDTH;
+  int i;
+  FILE *f;
+
+  if (argc > 1 && argv[1][0] == '-') {
+	if ((width = atoi(&argv[1][1])) <= 0) {
+		fprintf(stderr, "Bad number for fold\n");
+		exit(1);
+	}
+	--argc;
+	++argv;
+  }
+  if (argc == 1)
+	Fold(stdin, width);
+  else {
+	for (i = 1; i < argc; ++i) {
+		if ((f = fopen(argv[i], "r")) == NULL) {
+			perror(argv[i]);
+			exit(1);
+		}
+		Fold(f, width);
+		fclose(f);
+	}
+  }
+  return(0);
+}
+
+
+void Fold(f, width)
+FILE *f;
+int width;
+{
+  int c;
+
+  while ((c = getc(f)) != EOF) {
+	if (c == '\t')
+		column = (column / TAB + 1) * TAB;
+	else if (c == '\b')
+		column = column > 0 ? column - 1 : 0;
+	else if (c == '\n' || c == '\r')
+		column = 0;
+	else
+		++column;
+
+	if (column > width) {
+		putchar('\n');
+		column = c == '\t' ? TAB : 1;
+	}
+	putchar(c);
+  }
+}
Index: /trunk/minix/commands/simple/fortune.c
===================================================================
--- /trunk/minix/commands/simple/fortune.c	(revision 9)
+++ /trunk/minix/commands/simple/fortune.c	(revision 9)
@@ -0,0 +1,75 @@
+/*  fortune  -  hand out Chinese fortune cookies	Author: Bert Reuling */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define COOKIEJAR "/usr/lib/fortune.dat"
+
+static char *Copyright = "\0Copyright (c) 1990 Bert Reuling";
+static unsigned long seed;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(unsigned long magic, (unsigned long range));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int c1, c2, c3;
+  struct stat cookie_stat;
+  FILE *cookie;
+
+  if ((cookie = fopen(COOKIEJAR, "r")) == NULL) {
+	printf("\nSome things better stay closed.\n  - %s\n", argv[0]);
+	exit (-1);
+  }
+
+  /* Create seed from : date, time, user-id and process-id. we can't get
+   * the position of the moon, unfortunately.
+   */
+  seed = time( (time_t *) 0) ^ (long) getuid() ^ (long) getpid();
+
+  if (stat(COOKIEJAR, &cookie_stat) != 0) {
+	printf("\nIt furthers one to see the super guru.\n  - %s\n", argv[0]);
+	exit (-1);
+  }
+  fseek(cookie, magic((unsigned long) cookie_stat.st_size), 0); /* m ove bu magic... */
+
+  c2 = c3 = '\n';
+  while (((c1 = getc(cookie)) != EOF) && ((c1 != '%') || (c2 != '%') || (c3 != '\n'))) {
+	c3 = c2;
+	c2 = c1;
+  }
+
+  if (c1 == EOF) {
+	printf("\nSomething unexpected has happened.\n  - %s", argv[0]);
+	exit (-1);
+  }
+
+  c2 = c3 = '\n';
+  while (((c1 = getc(cookie)) != '%') || (c2 != '%') || (c3 != '\n')) {
+	if (c1 == EOF) {
+		rewind(cookie);
+		continue;
+	}
+	putc(c2, stdout);
+	c3 = c2;
+	c2 = c1;
+  }
+  putc('\n', stdout);
+  fclose(cookie);
+  return (0);
+}
+
+/*  magic  -  please study carefull: there is more than meets the eye */
+unsigned long magic(range)
+unsigned long range;
+{
+
+  seed = 9065531L * (seed % 9065533L) - 2 * (seed / 9065531L) + 1L;
+  return (seed % range);
+}
Index: /trunk/minix/commands/simple/fsck.c
===================================================================
--- /trunk/minix/commands/simple/fsck.c	(revision 9)
+++ /trunk/minix/commands/simple/fsck.c	(revision 9)
@@ -0,0 +1,1592 @@
+/* Hacks for version 1.6 */					
+
+#define INODES_PER_BLOCK V2_INODES_PER_BLOCK(block_size)
+#define INODE_SIZE ((int) V2_INODE_SIZE)
+#define WORDS_PER_BLOCK (block_size / (int) sizeof(bitchunk_t))
+#define MAX_ZONES (V2_NR_DZONES+V2_INDIRECTS(block_size)+(long)V2_INDIRECTS(block_size)*V2_INDIRECTS(block_size))
+#define NR_DZONE_NUM V2_NR_DZONES
+#define NR_INDIRECTS V2_INDIRECTS(block_size)
+#define NR_ZONE_NUMS V2_NR_TZONES
+#define ZONE_NUM_SIZE V2_ZONE_NUM_SIZE
+#define bit_nr bit_t
+#define block_nr block_t
+#define d_inode d2_inode
+#define d_inum d_ino
+#define dir_struct struct direct
+#define i_mode d2_mode
+#define i_nlinks d2_nlinks
+#define i_size d2_size
+#define i_zone d2_zone
+#define zone_nr zone_t
+
+/* fsck - file system checker		Author: Robbert van Renesse */
+
+/* Modified by Norbert Schlenker
+*   Removed vestiges of standalone/DOS versions:
+*     - various unused variables and buffers removed
+*     - now uses library functions rather than private internal routines
+*     - bytewise structure copies replaced by structure assignment
+*     - fixed one bug with 14 character file names
+*     - other small tweaks for speed
+*
+* Modified by Lars Fredriksen at the request of Andy Tanenbaum, 90-03-10.
+*   Removed -m option, by which fsck could be told to make a file
+*   system on a 360K floppy.  The code had limited utility, was buggy,
+*   and failed due to a bug in the ACK C compiler.  Use mkfs instead!
+*/
+
+#include <sys/types.h>
+#include <sys/dir.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include "../../servers/fs/const.h"
+#include "../../servers/fs/inode.h"
+#include "../../servers/fs/type.h"
+#include <minix/fslib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <a.out.h>
+#include <tools.h>
+#include <dirent.h>
+
+#undef N_DATA
+
+unsigned int fs_version = 2, block_size = 0;
+
+#define BITSHIFT	  4	/* = log2(#bits(int)) */
+
+#define MAXPRINT	  80	/* max. number of error lines in chkmap */
+#define CINDIR		128	/* number of indirect zno's read at a time */
+#define CDIRECT		  1	/* number of dir entries read at a time */
+
+/* Macros for handling bitmaps.  Now bit_t is long, these are bulky and the
+ * type demotions produce a lot of lint.  The explicit demotion in POWEROFBIT
+ * is for efficiency and assumes 2's complement ints.  Lint should be clever
+ * enough not to warn about it since BITMASK is small, but isn't.  (It would
+ * be easier to get right if bit_t was was unsigned (long) since then there
+ * would be no danger from wierd sign representations.  Lint doesn't know
+ * we only use non-negative bit numbers.) There will usually be an implicit
+ * demotion when WORDOFBIT is used as an array index.  This should be safe
+ * since memory for bitmaps will run out first.
+ */
+#define BITMASK		((1 << BITSHIFT) - 1)
+#define WORDOFBIT(b)	((b) >> BITSHIFT)
+#define POWEROFBIT(b)	(1 << ((int) (b) & BITMASK))
+#define setbit(w, b)	(w[WORDOFBIT(b)] |= POWEROFBIT(b))
+#define clrbit(w, b)	(w[WORDOFBIT(b)] &= ~POWEROFBIT(b))
+#define bitset(w, b)	(w[WORDOFBIT(b)] & POWEROFBIT(b))
+
+#define ZONE_CT 	360	/* default zones  (when making file system) */
+#define INODE_CT	 95	/* default inodes (when making file system) */
+
+#include "../../servers/fs/super.h"
+static struct super_block sb;
+
+#define STICKY_BIT	01000	/* not defined anywhere else */
+
+/* Ztob gives the block address of a zone
+ * btoa gives the byte address of a block
+ */
+#define ztob(z)		((block_nr) (z) << sb.s_log_zone_size)
+#define btoa(b)		((long) (b) * block_size)
+#define SCALE		((int) ztob(1))	/* # blocks in a zone */
+#define FIRST		((zone_nr) sb.s_firstdatazone)	/* as the name says */
+
+/* # blocks of each type */
+#define N_IMAP		(sb.s_imap_blocks)
+#define N_ZMAP		(sb.s_zmap_blocks)
+#define N_ILIST		((sb.s_ninodes+INODES_PER_BLOCK-1) / INODES_PER_BLOCK)
+#define N_DATA		(sb.s_zones - FIRST)
+
+/* Block address of each type */
+#define OFFSET_SUPER_BLOCK	SUPER_BLOCK_BYTES
+#define BLK_IMAP	2
+#define BLK_ZMAP	(BLK_IMAP  + N_IMAP)
+#define BLK_ILIST	(BLK_ZMAP  + N_ZMAP)
+#define BLK_FIRST	ztob(FIRST)
+#define ZONE_SIZE	((int) ztob(block_size))
+#define NLEVEL		(NR_ZONE_NUMS - NR_DZONE_NUM + 1)
+
+/* Byte address of a zone/of an inode */
+#define zaddr(z)	btoa(ztob(z))
+#define cinoaddr(i)	((long) (i - 1) * INODE_SIZE + (long) btoa(BLK_ILIST))
+#define INDCHUNK	((int) (CINDIR * ZONE_NUM_SIZE))
+#define DIRCHUNK	((int) (CDIRECT * DIR_ENTRY_SIZE))
+
+char *prog, *fsck_device;		/* program name (fsck), device name */
+int firstcnterr;		/* is this the first inode ref cnt error? */
+bitchunk_t *imap, *spec_imap;	/* inode bit maps */
+bitchunk_t *zmap, *spec_zmap;	/* zone bit maps */
+bitchunk_t *dirmap;		/* directory (inode) bit map */
+char *rwbuf;			/* one block buffer cache */
+block_nr thisblk;		/* block in buffer cache */
+char *nullbuf;	/* null buffer */
+nlink_t *count;			/* inode count */
+int changed;			/* has the diskette been written to? */
+struct stack {
+  dir_struct *st_dir;
+  struct stack *st_next;
+  char st_presence;
+} *ftop;
+
+int dev;			/* file descriptor of the device */
+
+#define DOT	1
+#define DOTDOT	2
+
+/* Counters for each type of inode/zone. */
+int nfreeinode, nregular, ndirectory, nblkspec, ncharspec, nbadinode;
+int npipe, nsyml, ztype[NLEVEL];
+long nfreezone;
+
+int repair, automatic, listing, listsuper;	/* flags */
+int firstlist;			/* has the listing header been printed? */
+unsigned part_offset;		/* sector offset for this partition */
+char answer[] = "Answer questions with y or n.  Then hit RETURN";
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void initvars, (void));
+_PROTOTYPE(void fatal, (char *s));
+_PROTOTYPE(int eoln, (int c));
+_PROTOTYPE(int yes, (char *question));
+_PROTOTYPE(int atoo, (char *s));
+_PROTOTYPE(int input, (char *buf, int size));
+_PROTOTYPE(char *alloc, (unsigned nelem, unsigned elsize));
+_PROTOTYPE(void printname, (char *s));
+_PROTOTYPE(void printrec, (struct stack *sp));
+_PROTOTYPE(void printpath, (int mode, int nlcr));
+_PROTOTYPE(void devopen, (void));
+_PROTOTYPE(void devclose, (void));
+_PROTOTYPE(void devio, (block_nr bno, int dir));
+_PROTOTYPE(void devread, (long offset, char *buf, int size));
+_PROTOTYPE(void devwrite, (long offset, char *buf, int size));
+_PROTOTYPE(void pr, (char *fmt, int cnt, char *s, char *p));
+_PROTOTYPE(void lpr, (char *fmt, long cnt, char *s, char *p));
+_PROTOTYPE(bit_nr getnumber, (char *s));
+_PROTOTYPE(char **getlist, (char ***argv, char *type));
+_PROTOTYPE(void lsuper, (void));
+_PROTOTYPE(void getsuper, (void));
+_PROTOTYPE(void chksuper, (void));
+_PROTOTYPE(void lsi, (char **clist));
+_PROTOTYPE(bitchunk_t *allocbitmap, (int nblk));
+_PROTOTYPE(void loadbitmap, (bitchunk_t *bitmap, block_nr bno, int nblk));
+_PROTOTYPE(void dumpbitmap, (bitchunk_t *bitmap, block_nr bno, int nblk));
+_PROTOTYPE(void fillbitmap, (bitchunk_t *bitmap, bit_nr lwb, bit_nr upb, char **list));
+_PROTOTYPE(void freebitmap, (bitchunk_t *p));
+_PROTOTYPE(void getbitmaps, (void));
+_PROTOTYPE(void putbitmaps, (void));
+_PROTOTYPE(void chkword, (unsigned w1, unsigned w2, bit_nr bit, char *type, int *n, int *report, bit_t));
+_PROTOTYPE(void chkmap, (bitchunk_t *cmap, bitchunk_t *dmap, bit_nr bit, block_nr blkno, int nblk, char *type));
+_PROTOTYPE(void chkilist, (void));
+_PROTOTYPE(void getcount, (void));
+_PROTOTYPE(void counterror, (Ino_t ino));
+_PROTOTYPE(void chkcount, (void));
+_PROTOTYPE(void freecount, (void));
+_PROTOTYPE(void printperm, (mode_t mode, int shift, int special, int overlay));
+_PROTOTYPE(void list, (Ino_t ino, d_inode *ip));
+_PROTOTYPE(int Remove, (dir_struct *dp));
+_PROTOTYPE(void make_printable_name, (char *dst, char *src, int n));
+_PROTOTYPE(int chkdots, (Ino_t ino, off_t pos, dir_struct *dp, Ino_t exp));
+_PROTOTYPE(int chkname, (Ino_t ino, dir_struct *dp));
+_PROTOTYPE(int chkentry, (Ino_t ino, off_t pos, dir_struct *dp));
+_PROTOTYPE(int chkdirzone, (Ino_t ino, d_inode *ip, off_t pos, zone_nr zno));
+_PROTOTYPE(int chksymlinkzone, (Ino_t ino, d_inode *ip, off_t pos,
+								zone_nr zno));
+_PROTOTYPE(void errzone, (char *mess, zone_nr zno, int level, off_t pos));
+_PROTOTYPE(int markzone, (zone_nr zno, int level, off_t pos));
+_PROTOTYPE(int chkindzone, (Ino_t ino, d_inode *ip, off_t *pos, zone_nr zno, int level));
+_PROTOTYPE(off_t jump, (int level));
+_PROTOTYPE(int zonechk, (Ino_t ino, d_inode *ip, off_t *pos, zone_nr zno, int level));
+_PROTOTYPE(int chkzones, (Ino_t ino, d_inode *ip, off_t *pos, zone_nr *zlist, int len, int level));
+_PROTOTYPE(int chkfile, (Ino_t ino, d_inode *ip));
+_PROTOTYPE(int chkdirectory, (Ino_t ino, d_inode *ip));
+_PROTOTYPE(int chklink, (Ino_t ino, d_inode *ip));
+_PROTOTYPE(int chkspecial, (Ino_t ino, d_inode *ip));
+_PROTOTYPE(int chkmode, (Ino_t ino, d_inode *ip));
+_PROTOTYPE(int chkinode, (Ino_t ino, d_inode *ip));
+_PROTOTYPE(int descendtree, (dir_struct *dp));
+_PROTOTYPE(void chktree, (void));
+_PROTOTYPE(void printtotal, (void));
+_PROTOTYPE(void chkdev, (char *f, char **clist, char **ilist, char **zlist));
+
+/* Initialize the variables used by this program. */
+void initvars()
+{
+  register level;
+
+  nregular = ndirectory = nblkspec = ncharspec = nbadinode = npipe = nsyml = 0;
+  for (level = 0; level < NLEVEL; level++) ztype[level] = 0;
+  changed = 0;
+  thisblk = NO_BLOCK;
+  firstlist = 1;
+  firstcnterr = 1;
+}
+
+/* Print the string `s' and exit. */
+void fatal(s)
+char *s;
+{
+  printf("%s\nfatal\n", s);
+  exit(-1);
+}
+
+/* Test for end of line. */
+int eoln(c)
+int c;
+{
+  return(c == EOF || c == '\n' || c == '\r');
+}
+
+/* Ask a question and get the answer unless automatic is set. */
+int yes(question)
+char *question;
+{
+  register int c, answerchar;
+  static int note = 0;
+
+  if (!repair) {
+	printf("\n");
+	return(0);
+  }
+  printf("%s? ", question);
+  if(!note) { printf("(y=yes, n=no, q=quit, A=for yes to all) "); note = 1; }
+  if (automatic) {
+	printf("yes\n");
+	return(1);
+  }
+  fflush(stdout);
+  if ((c = answerchar = getchar()) == 'q' || c == 'Q') exit(1);
+  if(c == 'A') { automatic = 1; c = 'y'; }
+  while (!eoln(c)) c = getchar();
+  return !(answerchar == 'n' || answerchar == 'N');
+}
+
+/* Convert string to integer.  Representation is octal. */
+int atoo(s)
+register char *s;
+{
+  register int n = 0;
+
+  while ('0' <= *s && *s < '8') {
+	n <<= 3;
+	n += *s++ - '0';
+  }
+  return n;
+}
+
+/* If repairing the file system, print a prompt and get a string from user. */
+int input(buf, size)
+char *buf;
+int size;
+{
+  register char *p = buf;
+
+  printf("\n");
+  if (repair) {
+	printf("--> ");
+	fflush(stdout);
+	while (--size) {
+		*p = getchar();
+		if (eoln(*p)) {
+			*p = 0;
+			return(p > buf);
+		}
+		p++;
+	}
+	*p = 0;
+	while (!eoln(getchar()));
+	return(1);
+  }
+  return(0);
+}
+
+/* Allocate some memory and zero it. */
+char *alloc(nelem, elsize)
+unsigned nelem, elsize;
+{
+  char *p;
+
+  if ((p = (char *)malloc((size_t)nelem * elsize)) == 0) {
+  	fprintf(stderr, "Tried to allocate %dkB\n",
+  		nelem*elsize/1024);
+  	fatal("out of memory");
+  }
+  memset((void *) p, 0, (size_t)nelem * elsize);
+  return(p);
+}
+
+/* Print the name in a directory entry. */
+void printname(s)
+char *s;
+{
+  register n = NAME_MAX;
+  int c;
+
+  do {
+	if ((c = *s) == 0) break;
+	if (!isprint(c)) c = '?';
+	putchar(c);
+	s++;
+  } while (--n);
+}
+
+/* Print the pathname given by a linked list pointed to by `sp'.  The
+ * names are in reverse order.
+ */
+void printrec(sp)
+struct stack *sp;
+{
+  if (sp->st_next != 0) {
+	printrec(sp->st_next);
+	putchar('/');
+	printname(sp->st_dir->d_name);
+  }
+}
+
+/* Print the current pathname.  */
+void printpath(mode, nlcr)
+int mode;
+int nlcr;
+{
+  if (ftop->st_next == 0)
+	putchar('/');
+  else
+	printrec(ftop);
+  switch (mode) {
+      case 1:
+	printf(" (ino = %u, ", ftop->st_dir->d_inum);
+	break;
+      case 2:
+	printf(" (ino = %u)", ftop->st_dir->d_inum);
+	break;
+  }
+  if (nlcr) printf("\n");
+}
+
+/* Open the device.  */
+void devopen()
+{
+  if ((dev = open(fsck_device, repair ? O_RDWR : O_RDONLY)) < 0) {
+	perror(fsck_device);
+	fatal("couldn't open device to fsck");
+  }
+}
+
+/* Close the device. */
+void devclose()
+{
+  if (close(dev) != 0) {
+	perror("close");
+	fatal("");
+  }
+}
+
+/* Read or write a block. */
+void devio(bno, dir)
+block_nr bno;
+int dir;
+{
+  if(!block_size) fatal("devio() with unknown block size");
+  if (dir == READING && bno == thisblk) return;
+  thisblk = bno;
+
+#if 0
+printf("%s at block %5d\n", dir == READING ? "reading " : "writing", bno);
+#endif
+  lseek(dev, (off_t) btoa(bno), SEEK_SET);
+  if (dir == READING) {
+	if (read(dev, rwbuf, block_size) == block_size)
+		return;
+  } else {
+	if (write(dev, rwbuf, block_size) == block_size)
+		return;
+  }
+
+  printf("%s: can't %s block %ld (error = 0x%x)\n", prog,
+         dir == READING ? "read" : "write", (long) bno, errno);
+  if (dir == READING) {
+	printf("Continuing with a zero-filled block.\n");
+	memset(rwbuf, 0, block_size);
+	return;
+  }
+  fatal("");
+}
+
+/* Read `size' bytes from the disk starting at byte `offset'. */
+void devread(offset, buf, size)
+long offset;
+char *buf;
+int size;
+{
+  if(!block_size) fatal("devread() with unknown block size");
+  devio((block_nr) (offset / block_size), READING);
+  memmove(buf, &rwbuf[(int) (offset % block_size)], (size_t)size);  /* lint but OK */
+}
+
+/* Write `size' bytes to the disk starting at byte `offset'. */
+void devwrite(offset, buf, size)
+long offset;
+char *buf;
+int size;
+{
+  if(!block_size) fatal("devwrite() with unknown block size");
+  if (!repair) fatal("internal error (devwrite)");
+  if (size != block_size) devio((block_nr) (offset / block_size), READING);
+  memmove(&rwbuf[(int) (offset % block_size)], buf, (size_t)size);  /* lint but OK */
+  devio((block_nr) (offset / block_size), WRITING);
+  changed = 1;
+}
+
+/* Print a string with either a singular or a plural pronoun. */
+void pr(fmt, cnt, s, p)
+char *fmt, *s, *p;
+int cnt;
+{
+  printf(fmt, cnt, cnt == 1 ? s : p);
+}
+
+/* Same as above, but with a long argument */
+void lpr(fmt, cnt, s, p)
+char *fmt, *s, *p;
+long cnt;
+{
+  printf(fmt, cnt, cnt == 1 ? s : p);
+}
+
+/* Convert string to number. */
+bit_nr getnumber(s)
+register char *s;
+{
+  register bit_nr n = 0;
+
+  if (s == NULL)
+	return NO_BIT;
+  while (isdigit(*s))
+	n = (n << 1) + (n << 3) + *s++ - '0';
+  return (*s == '\0') ? n : NO_BIT;
+}
+
+/* See if the list pointed to by `argv' contains numbers. */
+char **getlist(argv, type)
+char ***argv, *type;
+{
+  register char **list = *argv;
+  register empty = 1;
+
+  while (getnumber(**argv) != NO_BIT) {
+	(*argv)++;
+	empty = 0;
+  }
+  if (empty) {
+	printf("warning: no %s numbers given\n", type);
+	return(NULL);
+  }
+  return(list);
+}
+
+/* Make a listing of the super block.  If `repair' is set, ask the user
+ * for changes.
+ */
+void lsuper()
+{
+  char buf[80];
+
+  do {
+	/* Most of the following atol's enrage lint, for good reason. */  
+	printf("ninodes       = %u", sb.s_ninodes);
+	if (input(buf, 80)) sb.s_ninodes = atol(buf);
+	printf("nzones        = %ld", sb.s_zones);
+	if (input(buf, 80)) sb.s_zones = atol(buf);
+	printf("imap_blocks   = %u", sb.s_imap_blocks);
+	if (input(buf, 80)) sb.s_imap_blocks = atol(buf);
+	printf("zmap_blocks   = %u", sb.s_zmap_blocks);
+	if (input(buf, 80)) sb.s_zmap_blocks = atol(buf);
+	printf("firstdatazone = %u", sb.s_firstdatazone);
+	if (input(buf, 80)) sb.s_firstdatazone = atol(buf);
+	printf("log_zone_size = %u", sb.s_log_zone_size);
+	if (input(buf, 80)) sb.s_log_zone_size = atol(buf);
+	printf("maxsize       = %ld", sb.s_max_size);
+	if (input(buf, 80)) sb.s_max_size = atol(buf);
+	printf("block size    = %ld", sb.s_block_size);
+	if (input(buf, 80)) sb.s_block_size = atol(buf);
+	if (yes("ok now")) {
+		devwrite(OFFSET_SUPER_BLOCK, (char *) &sb, sizeof(sb));
+		return;
+	}
+  } while (yes("Do you want to try again"));
+  if (repair) exit(0);
+}
+
+/* Get the super block from either disk or user.  Do some initial checks. */
+void getsuper()
+{
+  if(lseek(dev, OFFSET_SUPER_BLOCK, SEEK_SET) < 0) {
+  	perror("lseek");
+  	fatal("couldn't seek to super block.");
+  }
+  if(read(dev, &sb, sizeof(sb)) != sizeof(sb)) {
+  	fatal("couldn't read super block.");
+  }
+  if (listsuper) lsuper();
+  if (sb.s_magic == SUPER_MAGIC) fatal("Cannot handle V1 file systems");
+  if (sb.s_magic == SUPER_V2) {
+  	fs_version = 2;
+  	block_size = /* STATIC_BLOCK_SIZE */ 8192;
+  } else if(sb.s_magic == SUPER_V3) {
+  	fs_version = 3;
+  	block_size = sb.s_block_size;
+  } else {
+  	fatal("bad magic number in super block");
+  }
+  if (sb.s_ninodes <= 0) fatal("no inodes");
+  if (sb.s_zones <= 0) fatal("no zones");
+  if (sb.s_imap_blocks <= 0) fatal("no imap");
+  if (sb.s_zmap_blocks <= 0) fatal("no zmap");
+  if (sb.s_firstdatazone <= 4) fatal("first data zone too small");
+  if (sb.s_log_zone_size < 0) fatal("zone size < block size");
+  if (sb.s_max_size <= 0) fatal("max. file size <= 0");
+
+}
+
+/* Check the super block for reasonable contents. */
+void chksuper()
+{
+  register n;
+  register off_t maxsize;
+
+  n = bitmapsize((bit_t) sb.s_ninodes + 1, block_size);
+  if (sb.s_magic != SUPER_V2 && sb.s_magic != SUPER_V3)
+  	fatal("bad magic number in super block");
+  if (sb.s_imap_blocks < n) {
+  	printf("need %d bocks for inode bitmap; only have %d\n",
+  		n, sb.s_imap_blocks);
+  	fatal("too few imap blocks");
+  }
+  if (sb.s_imap_blocks != n) {
+	pr("warning: expected %d imap_block%s", n, "", "s");
+	printf(" instead of %d\n", sb.s_imap_blocks);
+  }
+  n = bitmapsize((bit_t) sb.s_zones, block_size);
+  if (sb.s_zmap_blocks < n) fatal("too few zmap blocks");
+  if (sb.s_zmap_blocks != n) {
+	pr("warning: expected %d zmap_block%s", n, "", "s");
+	printf(" instead of %d\n", sb.s_zmap_blocks);
+  }
+  if (sb.s_firstdatazone >= sb.s_zones)
+	fatal("first data zone too large");
+  if (sb.s_log_zone_size >= 8 * sizeof(block_nr))
+	fatal("log_zone_size too large");
+  if (sb.s_log_zone_size > 8) printf("warning: large log_zone_size (%d)\n",
+	       sb.s_log_zone_size);
+  n = (BLK_ILIST + N_ILIST + SCALE - 1) >> sb.s_log_zone_size;
+  if (sb.s_firstdatazone < n) fatal("first data zone too small");
+  if (sb.s_firstdatazone != n) {
+	printf("warning: expected first data zone to be %d ", n);
+	printf("instead of %u\n", sb.s_firstdatazone);
+  }
+  maxsize = MAX_FILE_POS;
+  if (((maxsize - 1) >> sb.s_log_zone_size) / block_size >= MAX_ZONES)
+	maxsize = ((long) MAX_ZONES * block_size) << sb.s_log_zone_size;
+  if (sb.s_max_size != maxsize) {
+	printf("warning: expected max size to be %ld ", maxsize);
+	printf("instead of %ld\n", sb.s_max_size);
+  }
+}
+
+int inoaddr(int inn)
+{
+	int a;
+	a = cinoaddr(inn);
+	return a;
+}
+
+/* Make a listing of the inodes given by `clist'.  If `repair' is set, ask
+ * the user for changes.
+ */
+void lsi(clist)
+char **clist;
+{
+  register bit_nr bit;
+  register ino_t ino;
+  d_inode inode, *ip = &inode;
+  char buf[80];
+
+  if (clist == 0) return;
+  while ((bit = getnumber(*clist++)) != NO_BIT) {
+	setbit(spec_imap, bit);
+	ino = bit;
+	do {
+		devread(inoaddr(ino), (char *) ip, INODE_SIZE);
+		printf("inode %u:\n", ino);
+		printf("    mode   = %6o", ip->i_mode);
+		if (input(buf, 80)) ip->i_mode = atoo(buf);
+		printf("    nlinks = %6u", ip->i_nlinks);
+		if (input(buf, 80)) ip->i_nlinks = atol(buf);
+		printf("    size   = %6ld", ip->i_size);
+		if (input(buf, 80)) ip->i_size = atol(buf);
+		if (yes("Write this back")) {
+			devwrite(inoaddr(ino), (char *) ip, INODE_SIZE);
+			break;
+		}
+	} while (yes("Do you want to change it again"));
+  }
+}
+
+/* Allocate `nblk' blocks worth of bitmap. */
+bitchunk_t *allocbitmap(nblk)
+int nblk;
+{
+  register bitchunk_t *bitmap;
+
+  bitmap = (bitchunk_t *) alloc((unsigned) nblk, block_size);
+  *bitmap |= 1;
+  return(bitmap);
+}
+
+/* Load the bitmap starting at block `bno' from disk. */
+void loadbitmap(bitmap, bno, nblk)
+bitchunk_t *bitmap;
+block_nr bno;
+int nblk;
+{
+  register i;
+  register bitchunk_t *p;
+
+  p = bitmap;
+  for (i = 0; i < nblk; i++, bno++, p += WORDS_PER_BLOCK)
+	devread(btoa(bno), (char *) p, block_size);
+  *bitmap |= 1;
+}
+
+/* Write the bitmap starting at block `bno' to disk. */
+void dumpbitmap(bitmap, bno, nblk)
+bitchunk_t *bitmap;
+block_nr bno;
+int nblk;
+{
+  register i;
+  register bitchunk_t *p = bitmap;
+
+  for (i = 0; i < nblk; i++, bno++, p += WORDS_PER_BLOCK)
+	devwrite(btoa(bno), (char *) p, block_size);
+}
+
+/* Set the bits given by `list' in the bitmap. */
+void fillbitmap(bitmap, lwb, upb, list)
+bitchunk_t *bitmap;
+bit_nr lwb, upb;
+char **list;
+{
+  register bit_nr bit;
+
+  if (list == 0) return;
+  while ((bit = getnumber(*list++)) != NO_BIT)
+	if (bit < lwb || bit >= upb) {
+		if (bitmap == spec_imap)
+			printf("inode number %ld ", bit);
+		else
+			printf("zone number %ld ", bit);
+		printf("out of range (ignored)\n");
+	} else
+		setbit(bitmap, bit - lwb + 1);
+}
+
+/* Deallocate the bitmap `p'. */
+void freebitmap(p)
+bitchunk_t *p;
+{
+  free((char *) p);
+}
+
+/* Get all the bitmaps used by this program. */
+void getbitmaps()
+{
+  imap = allocbitmap(N_IMAP);
+  zmap = allocbitmap(N_ZMAP);
+  spec_imap = allocbitmap(N_IMAP);
+  spec_zmap = allocbitmap(N_ZMAP);
+  dirmap = allocbitmap(N_IMAP);
+}
+
+/* Release all the space taken by the bitmaps. */
+void putbitmaps()
+{
+  freebitmap(imap);
+  freebitmap(zmap);
+  freebitmap(spec_imap);
+  freebitmap(spec_zmap);
+  freebitmap(dirmap);
+}
+
+/* `w1' and `w2' are differing words from two bitmaps that should be
+ * identical.  Print what's the matter with them.
+ */
+void chkword(w1, w2, bit, type, n, report, phys)
+unsigned w1, w2;
+char *type;
+bit_nr bit;
+int *n, *report;
+bit_nr phys;
+{
+  for (; (w1 | w2); w1 >>= 1, w2 >>= 1, bit++, phys++)
+	if ((w1 ^ w2) & 1 && ++(*n) % MAXPRINT == 0 && *report &&
+	    (!repair || automatic || yes("stop this listing")))
+		*report = 0;
+	else if (*report)
+		if ((w1 & 1) && !(w2 & 1))
+			printf("%s %ld (%ld) is missing\n", type, bit, phys);
+		else if (!(w1 & 1) && (w2 & 1))
+			printf("%s %ld (%ld) is not free\n", type, bit, phys);
+}
+
+/* Check if the given (correct) bitmap is identical with the one that is
+ * on the disk.  If not, ask if the disk should be repaired.
+ */
+void chkmap(cmap, dmap, bit, blkno, nblk, type)
+bitchunk_t *cmap, *dmap;
+bit_nr bit;
+block_nr blkno;
+int nblk;
+char *type;
+{
+  register bitchunk_t *p = dmap, *q = cmap;
+  int report = 1, nerr = 0;
+  int w = nblk * WORDS_PER_BLOCK;
+  bit_nr phys = 0;
+
+  printf("Checking %s map\n", type);
+  loadbitmap(dmap, blkno, nblk);
+  do {
+	if (*p != *q) chkword(*p, *q, bit, type, &nerr, &report, phys);
+	p++;
+	q++;
+	bit += 8 * sizeof(bitchunk_t);
+	phys += 8 * sizeof(bitchunk_t);
+  } while (--w > 0);
+
+  if ((!repair || automatic) && !report) printf("etc. ");
+  if (nerr > MAXPRINT || nerr > 10) printf("%d errors found. ", nerr);
+  if (nerr != 0 && yes("install a new map")) dumpbitmap(cmap, blkno, nblk);
+  if (nerr > 0) printf("\n");
+}
+
+/* See if the inodes that aren't allocated are cleared. */
+void chkilist()
+{
+  register ino_t ino = 1;
+  mode_t mode;
+
+  printf("Checking inode list\n");
+  do
+	if (!bitset(imap, (bit_nr) ino)) {
+		devread(inoaddr(ino), (char *) &mode, sizeof(mode));
+		if (mode != I_NOT_ALLOC) {
+			printf("mode inode %u not cleared", ino);
+			if (yes(". clear")) devwrite(inoaddr(ino), nullbuf,
+					 INODE_SIZE);
+		}
+	}
+  while (++ino <= sb.s_ninodes && ino != 0);
+  printf("\n");
+}
+
+/* Allocate an array to maintain the inode reference counts in. */
+void getcount()
+{
+  count = (nlink_t *) alloc((unsigned) (sb.s_ninodes + 1), sizeof(nlink_t));
+}
+
+/* The reference count for inode `ino' is wrong.  Ask if it should be adjusted. */
+void counterror(ino)
+ino_t ino;
+{
+  d_inode inode;
+
+  if (firstcnterr) {
+	printf("INODE NLINK COUNT\n");
+	firstcnterr = 0;
+  }
+  devread(inoaddr(ino), (char *) &inode, INODE_SIZE);
+  count[ino] += inode.i_nlinks;	/* it was already subtracted; add it back */
+  printf("%5u %5u %5u", ino, (unsigned) inode.i_nlinks, count[ino]);
+  if (yes(" adjust")) {
+	if ((inode.i_nlinks = count[ino]) == 0) {
+		fatal("internal error (counterror)");
+		inode.i_mode = I_NOT_ALLOC;
+		clrbit(imap, (bit_nr) ino);
+	}
+	devwrite(inoaddr(ino), (char *) &inode, INODE_SIZE);
+  }
+}
+
+/* Check if the reference count of the inodes are correct.  The array `count'
+ * is maintained as follows:  an entry indexed by the inode number is
+ * incremented each time a link is found; when the inode is read the link
+ * count in there is substracted from the corresponding entry in `count'.
+ * Thus, when the whole file system has been traversed, all the entries
+ * should be zero.
+ */
+void chkcount()
+{
+  register ino_t ino;
+
+  for (ino = 1; ino <= sb.s_ninodes && ino != 0; ino++)
+	if (count[ino] != 0) counterror(ino);
+  if (!firstcnterr) printf("\n");
+}
+
+/* Deallocate the `count' array. */
+void freecount()
+{
+  free((char *) count);
+}
+
+/* Print the inode permission bits given by mode and shift. */
+void printperm(mode_t mode, int shift, int special, int overlay)
+{
+  if (mode >> shift & R_BIT)
+	putchar('r');
+  else
+	putchar('-');
+  if (mode >> shift & W_BIT)
+	putchar('w');
+  else
+	putchar('-');
+  if (mode & special)
+	putchar(overlay);
+  else
+	if (mode >> shift & X_BIT)
+		putchar('x');
+	else
+		putchar('-');
+}
+
+/* List the given inode. */
+void list(ino, ip)
+ino_t ino;
+d_inode *ip;
+{
+  if (firstlist) {
+	firstlist = 0;
+	printf(" inode permission link   size name\n");
+  }
+  printf("%6u ", ino);
+  switch (ip->i_mode & I_TYPE) {
+      case I_REGULAR:		putchar('-');	break;
+      case I_DIRECTORY:		putchar('d');	break;
+      case I_CHAR_SPECIAL:	putchar('c');	break;
+      case I_BLOCK_SPECIAL:	putchar('b');	break;
+      case I_NAMED_PIPE:	putchar('p');	break;
+#ifdef I_SYMBOLIC_LINK
+      case I_SYMBOLIC_LINK:	putchar('l');	break;
+#endif
+      default:			putchar('?');
+}
+  printperm(ip->i_mode, 6, I_SET_UID_BIT, 's');
+  printperm(ip->i_mode, 3, I_SET_GID_BIT, 's');
+  printperm(ip->i_mode, 0, STICKY_BIT, 't');
+  printf(" %3u ", ip->i_nlinks);
+  switch (ip->i_mode & I_TYPE) {
+      case I_CHAR_SPECIAL:
+      case I_BLOCK_SPECIAL:
+	printf("  %2x,%2x ", (dev_t) ip->i_zone[0] >> MAJOR & 0xFF,
+	       (dev_t) ip->i_zone[0] >> MINOR & 0xFF);
+	break;
+      default:	printf("%7ld ", ip->i_size);
+  }
+  printpath(0, 1);
+}
+
+/* Remove an entry from a directory if ok with the user.
+ * Don't name the function remove() - that is owned by ANSI, and chaos results
+ * when it is a macro.
+ */
+int Remove(dp)
+dir_struct *dp;
+{
+  setbit(spec_imap, (bit_nr) dp->d_inum);
+  if (yes(". remove entry")) {
+	count[dp->d_inum]--;
+	memset((void *) dp, 0, sizeof(dir_struct));
+	return(1);
+  }
+  return(0);
+}
+
+/* Convert string so that embedded control characters are printable. */
+void make_printable_name(dst, src, n)
+register char *dst;
+register char *src;
+register int n;
+{
+  register int c;
+
+  while (--n >= 0 && (c = *src++) != '\0') {
+	if (isprint(c) && c != '\\')
+		*dst++ = c;
+	else {
+		*dst++ = '\\';
+		switch (c) {
+		      case '\\':
+			*dst++ = '\\'; break;
+		      case '\b':
+			*dst++ = 'b'; break;
+		      case '\f':
+			*dst++ = 'f'; break;
+		      case '\n':
+			*dst++ = 'n'; break;
+		      case '\r':
+			*dst++ = 'r'; break;
+		      case '\t':
+			*dst++ = 't'; break;
+		      default:
+			*dst++ = '0' + ((c >> 6) & 03);
+			*dst++ = '0' + ((c >> 3) & 07);
+			*dst++ = '0' + (c & 07);
+		}
+	}
+  }
+  *dst = '\0';
+}
+
+/* See if the `.' or `..' entry is as expected. */
+int chkdots(ino, pos, dp, exp)
+ino_t ino, exp;
+off_t pos;
+dir_struct *dp;
+{
+  char printable_name[4 * NAME_MAX + 1];
+
+  if (dp->d_inum != exp) {
+	make_printable_name(printable_name, dp->d_name, sizeof(dp->d_name));
+	printf("bad %s in ", printable_name);
+	printpath(1, 0);
+	printf("%s is linked to %u ", printable_name, dp->d_inum);
+	printf("instead of %u)", exp);
+	setbit(spec_imap, (bit_nr) ino);
+	setbit(spec_imap, (bit_nr) dp->d_inum);
+	setbit(spec_imap, (bit_nr) exp);
+	if (yes(". repair")) {
+		count[dp->d_inum]--;
+		dp->d_inum = exp;
+		count[exp]++;
+		return(0);
+	}
+  } else if (pos != (dp->d_name[1] ? DIR_ENTRY_SIZE : 0)) {
+	make_printable_name(printable_name, dp->d_name, sizeof(dp->d_name));
+	printf("warning: %s has offset %ld in ", printable_name, pos);
+	printpath(1, 0);
+	printf("%s is linked to %u)\n", printable_name, dp->d_inum);
+	setbit(spec_imap, (bit_nr) ino);
+	setbit(spec_imap, (bit_nr) dp->d_inum);
+	setbit(spec_imap, (bit_nr) exp);
+  }
+  return(1);
+}
+
+/* Check the name in a directory entry. */
+int chkname(ino, dp)
+ino_t ino;
+dir_struct *dp;
+{
+  register n = NAME_MAX + 1;
+  register char *p = dp->d_name;
+
+  if (*p == '\0') {
+	printf("null name found in ");
+	printpath(0, 0);
+	setbit(spec_imap, (bit_nr) ino);
+	if (Remove(dp)) return(0);
+  }
+  while (*p != '\0' && --n != 0)
+	if (*p++ == '/') {
+		printf("found a '/' in entry of directory ");
+		printpath(1, 0);
+		setbit(spec_imap, (bit_nr) ino);
+		printf("entry = '");
+		printname(dp->d_name);
+		printf("')");
+		if (Remove(dp)) return(0);
+		break;
+	}
+  return(1);
+}
+
+/* Check a directory entry.  Here the routine `descendtree' is called
+ * recursively to check the file or directory pointed to by the entry.
+ */
+int chkentry(ino, pos, dp)
+ino_t ino;
+off_t pos;
+dir_struct *dp;
+{
+  if (dp->d_inum < ROOT_INODE || dp->d_inum > sb.s_ninodes) {
+	printf("bad inode found in directory ");
+	printpath(1, 0);
+	printf("ino found = %u, ", dp->d_inum);
+	printf("name = '");
+	printname(dp->d_name);
+	printf("')");
+	if (yes(". remove entry")) {
+		memset((void *) dp, 0, sizeof(dir_struct));
+		return(0);
+	}
+	return(1);
+  }
+  if ((unsigned) count[dp->d_inum] == SHRT_MAX) {
+	printf("too many links to ino %u\n", dp->d_inum);
+	printf("discovered at entry '");
+	printname(dp->d_name);
+	printf("' in directory ");
+	printpath(0, 1);
+	if (Remove(dp)) return(0);
+  }
+  count[dp->d_inum]++;
+  if (strcmp(dp->d_name, ".") == 0) {
+	ftop->st_presence |= DOT;
+	return(chkdots(ino, pos, dp, ino));
+  }
+  if (strcmp(dp->d_name, "..") == 0) {
+	ftop->st_presence |= DOTDOT;
+	return(chkdots(ino, pos, dp, ino == ROOT_INODE ? ino :
+			ftop->st_next->st_dir->d_inum));
+  }
+  if (!chkname(ino, dp)) return(0);
+  if (bitset(dirmap, (bit_nr) dp->d_inum)) {
+	printf("link to directory discovered in ");
+	printpath(1, 0);
+	printf("name = '");
+	printname(dp->d_name);
+	printf("', dir ino = %u)", dp->d_inum);
+	return !Remove(dp);
+  }
+  return(descendtree(dp));
+}
+
+/* Check a zone of a directory by checking all the entries in the zone.
+ * The zone is split up into chunks to not allocate too much stack.
+ */
+int chkdirzone(ino, ip, pos, zno)
+ino_t ino;
+d_inode *ip;
+off_t pos;
+zone_nr zno;
+{
+  dir_struct dirblk[CDIRECT];
+  register dir_struct *dp;
+  register n, dirty;
+  register long offset = zaddr(zno);
+  register off_t size = 0;
+  n = SCALE * (NR_DIR_ENTRIES(block_size) / CDIRECT);
+
+  do {
+	devread(offset, (char *) dirblk, DIRCHUNK);
+	dirty = 0;
+	for (dp = dirblk; dp < &dirblk[CDIRECT]; dp++) {
+		if (dp->d_inum != NO_ENTRY && !chkentry(ino, pos, dp))
+			dirty = 1;
+		pos += DIR_ENTRY_SIZE;
+		if (dp->d_inum != NO_ENTRY) size = pos;
+	}
+	if (dirty) devwrite(offset, (char *) dirblk, DIRCHUNK);
+	offset += DIRCHUNK;
+	n--;
+  } while (n > 0);
+
+  if (size > ip->i_size) {
+	printf("size not updated of directory ");
+	printpath(2, 0);
+	if (yes(". extend")) {
+		setbit(spec_imap, (bit_nr) ino);
+		ip->i_size = size;
+		devwrite(inoaddr(ino), (char *) ip, INODE_SIZE);
+	}
+  }
+  return(1);
+}
+
+
+int chksymlinkzone(ino, ip, pos, zno)
+ino_t ino;
+d_inode *ip;
+off_t pos;
+zone_nr zno;
+{
+	long offset;
+	size_t len;
+	char target[PATH_MAX+1];
+
+	if (ip->i_size > PATH_MAX)
+		fatal("chksymlinkzone: fsck program inconsistency\n");
+	offset = zaddr(zno);
+	devread(offset, target, ip->i_size);
+	target[ip->i_size]= '\0';
+	len= strlen(target);
+	if (len != ip->i_size)
+	{
+		printf("bad size in symbolic link (%d instead of %d) ",
+			ip->i_size, len);
+		printpath(2, 0);
+		if (yes(". update")) {
+			setbit(spec_imap, (bit_nr) ino);
+			ip->i_size = len;
+			devwrite(inoaddr(ino), (char *) ip, INODE_SIZE);
+		}
+	}
+	return 1;
+}
+
+/* There is something wrong with the given zone.  Print some details. */
+void errzone(mess, zno, level, pos)
+char *mess;
+zone_nr zno;
+int level;
+off_t pos;
+{
+  printf("%s zone in ", mess);
+  printpath(1, 0);
+  printf("zno = %ld, type = ", zno);
+  switch (level) {
+      case 0:	printf("DATA");	break;
+      case 1:	printf("SINGLE INDIRECT");	break;
+      case 2:	printf("DOUBLE INDIRECT");	break;
+      default:	printf("VERY INDIRECT");
+  }
+  printf(", pos = %ld)\n", pos);
+}
+
+/* Found the given zone in the given inode.  Check it, and if ok, mark it
+ * in the zone bitmap.
+ */
+int markzone(zno, level, pos)
+zone_nr zno;
+int level;
+off_t pos;
+{
+  register bit_nr bit = (bit_nr) zno - FIRST + 1;
+
+  ztype[level]++;
+  if (zno < FIRST || zno >= sb.s_zones) {
+	errzone("out-of-range", zno, level, pos);
+	return(0);
+  }
+  if (bitset(zmap, bit)) {
+	setbit(spec_zmap, bit);
+	errzone("duplicate", zno, level, pos);
+	return(0);
+  }
+  nfreezone--;
+  if (bitset(spec_zmap, bit)) errzone("found", zno, level, pos);
+  setbit(zmap, bit);
+  return(1);
+}
+
+/* Check an indirect zone by checking all of its entries.
+ * The zone is split up into chunks to not allocate too much stack.
+ */
+int chkindzone(ino, ip, pos, zno, level)
+ino_t ino;
+d_inode *ip;
+off_t *pos;
+zone_nr zno;
+int level;
+{
+  zone_nr indirect[CINDIR];
+  register n = NR_INDIRECTS / CINDIR;
+  register long offset = zaddr(zno);
+
+  do {
+	devread(offset, (char *) indirect, INDCHUNK);
+	if (!chkzones(ino, ip, pos, indirect, CINDIR, level - 1)) return(0);
+	offset += INDCHUNK;
+  } while (--n && *pos < ip->i_size);
+  return(1);
+}
+
+/* Return the size of a gap in the file, represented by a null zone number
+ * at some level of indirection.
+ */
+off_t jump(level)
+int level;
+{
+  off_t power = ZONE_SIZE;
+
+  if (level != 0) do
+		power *= NR_INDIRECTS;
+	while (--level);
+  return(power);
+}
+
+/* Check a zone, which may be either a normal data zone, a directory zone,
+ * or an indirect zone.
+ */
+int zonechk(ino, ip, pos, zno, level)
+ino_t ino;
+d_inode *ip;
+off_t *pos;
+zone_nr zno;
+int level;
+{
+  if (level == 0) {
+	if ((ip->i_mode & I_TYPE) == I_DIRECTORY &&
+	    !chkdirzone(ino, ip, *pos, zno))
+		return(0);
+	if ((ip->i_mode & I_TYPE) == I_SYMBOLIC_LINK &&
+	    !chksymlinkzone(ino, ip, *pos, zno))
+		return(0);
+	*pos += ZONE_SIZE;
+	return(1);
+  } else
+	return chkindzone(ino, ip, pos, zno, level);
+}
+
+/* Check a list of zones given by `zlist'. */
+int chkzones(ino, ip, pos, zlist, len, level)
+ino_t ino;
+d_inode *ip;
+off_t *pos;
+zone_nr *zlist;
+int len;
+int level;
+{
+  register ok = 1, i;
+
+  /* The check on the position in the next loop is commented out, since FS
+   * now requires valid zone numbers in each level that is necessary and FS
+   * always deleted all the zones in the double indirect block.
+   */
+  for (i = 0; i < len /* && *pos < ip->i_size */ ; i++)
+	if (zlist[i] == NO_ZONE)
+		*pos += jump(level);
+	else if (!markzone(zlist[i], level, *pos)) {
+		*pos += jump(level);
+		ok = 0;
+	} else if (!zonechk(ino, ip, pos, zlist[i], level))
+		ok = 0;
+  return(ok);
+}
+
+/* Check a file or a directory. */
+int chkfile(ino, ip)
+ino_t ino;
+d_inode *ip;
+{
+  register ok, i, level;
+  off_t pos = 0;
+
+  ok = chkzones(ino, ip, &pos, &ip->i_zone[0], NR_DZONE_NUM, 0);
+  for (i = NR_DZONE_NUM, level = 1; i < NR_ZONE_NUMS; i++, level++)
+	ok &= chkzones(ino, ip, &pos, &ip->i_zone[i], 1, level);
+  return(ok);
+}
+
+/* Check a directory by checking the contents.  Check if . and .. are present. */
+int chkdirectory(ino, ip)
+ino_t ino;
+d_inode *ip;
+{
+  register ok;
+
+  setbit(dirmap, (bit_nr) ino);
+  ok = chkfile(ino, ip);
+  if (!(ftop->st_presence & DOT)) {
+	printf(". missing in ");
+	printpath(2, 1);
+	ok = 0;
+  }
+  if (!(ftop->st_presence & DOTDOT)) {
+	printf(".. missing in ");
+	printpath(2, 1);
+	ok = 0;
+  }
+  return(ok);
+}
+
+#ifdef I_SYMBOLIC_LINK
+
+/* Check the validity of a symbolic link. */
+int chklink(ino, ip)
+ino_t ino;
+d_inode *ip;
+{
+  int ok;
+
+  ok = chkfile(ino, ip);
+  if (ip->i_size <= 0 || ip->i_size > block_size) {
+	if (ip->i_size == 0)
+		printf("empty symbolic link ");
+	else
+		printf("symbolic link too large (size %ld) ", ip->i_size);
+	printpath(2, 1);
+	ok = 0;
+  }
+  return(ok);
+}
+
+#endif
+
+/* Check the validity of a special file. */
+int chkspecial(ino, ip)
+ino_t ino;
+d_inode *ip;
+{
+  int i, ok;
+
+  ok = 1;
+  if ((dev_t) ip->i_zone[0] == NO_DEV) {
+	printf("illegal device number %ld for special file ", ip->i_zone[0]);
+	printpath(2, 1);
+	ok = 0;
+  }
+
+  /* FS will not use the remaining "zone numbers" but 1.6.11++ will panic if
+   * they are nonzero, since this should not happen.
+   */
+  for (i = 1; i < NR_ZONE_NUMS; i++)
+	if (ip->i_zone[i] != NO_ZONE) {
+		printf("nonzero zone number %ld for special file ",
+		       ip->i_zone[i]);
+		printpath(2, 1);
+		ok = 0;
+	}
+  return(ok);
+}
+
+/* Check the mode and contents of an inode. */
+int chkmode(ino, ip)
+ino_t ino;
+d_inode *ip;
+{
+  switch (ip->i_mode & I_TYPE) {
+      case I_REGULAR:
+	nregular++;
+	return chkfile(ino, ip);
+      case I_DIRECTORY:
+	ndirectory++;
+	return chkdirectory(ino, ip);
+      case I_BLOCK_SPECIAL:
+	nblkspec++;
+	return chkspecial(ino, ip);
+      case I_CHAR_SPECIAL:
+	ncharspec++;
+	return chkspecial(ino, ip);
+      case I_NAMED_PIPE:
+	npipe++;
+	return chkfile(ino, ip);
+#ifdef I_SYMBOLIC_LINK
+      case I_SYMBOLIC_LINK:
+	nsyml++;
+	return chklink(ino, ip);
+#endif
+      default:
+	nbadinode++;
+	printf("bad mode of ");
+	printpath(1, 0);
+	printf("mode = %o)", ip->i_mode);
+	return(0);
+  }
+}
+
+/* Check an inode. */
+int chkinode(ino, ip)
+ino_t ino;
+d_inode *ip;
+{
+  if (ino == ROOT_INODE && (ip->i_mode & I_TYPE) != I_DIRECTORY) {
+	printf("root inode is not a directory ");
+	printf("(ino = %u, mode = %o)\n", ino, ip->i_mode);
+	fatal("");
+  }
+  if (ip->i_nlinks == 0) {
+	printf("link count zero of ");
+	printpath(2, 0);
+	return(0);
+  }
+  nfreeinode--;
+  setbit(imap, (bit_nr) ino);
+  if ((unsigned) ip->i_nlinks > SHRT_MAX) {
+	printf("link count too big in ");
+	printpath(1, 0);
+	printf("cnt = %u)\n", (unsigned) ip->i_nlinks);
+	count[ino] -= SHRT_MAX;
+	setbit(spec_imap, (bit_nr) ino);
+  } else {
+	count[ino] -= (unsigned) ip->i_nlinks;
+  }
+  return chkmode(ino, ip);
+}
+
+/* Check the directory entry pointed to by dp, by checking the inode. */
+int descendtree(dp)
+dir_struct *dp;
+{
+  d_inode inode;
+  register ino_t ino = dp->d_inum;
+  register visited;
+  struct stack stk;
+
+  stk.st_dir = dp;
+  stk.st_next = ftop;
+  ftop = &stk;
+  if (bitset(spec_imap, (bit_nr) ino)) {
+	printf("found inode %u: ", ino);
+	printpath(0, 1);
+  }
+  visited = bitset(imap, (bit_nr) ino);
+  if (!visited || listing) {
+	devread(inoaddr(ino), (char *) &inode, INODE_SIZE);
+	if (listing) list(ino, &inode);
+	if (!visited && !chkinode(ino, &inode)) {
+		setbit(spec_imap, (bit_nr) ino);
+		if (yes("remove")) {
+			count[ino] += inode.i_nlinks - 1;
+			clrbit(imap, (bit_nr) ino);
+			devwrite(inoaddr(ino), nullbuf, INODE_SIZE);
+			memset((void *) dp, 0, sizeof(dir_struct));
+			ftop = ftop->st_next;
+			return(0);
+		}
+	}
+  }
+  ftop = ftop->st_next;
+  return(1);
+}
+
+/* Check the file system tree. */
+void chktree()
+{
+  dir_struct dir;
+
+  nfreeinode = sb.s_ninodes;
+  nfreezone = N_DATA;
+  dir.d_inum = ROOT_INODE;
+  dir.d_name[0] = 0;
+  if (!descendtree(&dir)) fatal("bad root inode");
+  putchar('\n');
+}
+
+/* Print the totals of all the objects found. */
+void printtotal()
+{
+  printf("blocksize = %5d        ", block_size);
+  printf("zonesize  = %5d\n", ZONE_SIZE);
+  printf("\n");
+  pr("%8u    Regular file%s\n", nregular, "", "s");
+  pr("%8u    Director%s\n", ndirectory, "y", "ies");
+  pr("%8u    Block special file%s\n", nblkspec, "", "s");
+  pr("%8u    Character special file%s\n", ncharspec, "", "s");
+  if (nbadinode != 0) pr("%6u    Bad inode%s\n", nbadinode, "", "s");
+  pr("%8u    Free inode%s\n", nfreeinode, "", "s");
+  pr("%8u    Named pipe%s\n", npipe, "", "s");
+  pr("%8u    Symbolic link%s\n", nsyml, "", "s");
+/* Don't print some fields.
+  printf("\n");
+  pr("%8u    Data zone%s\n",		  ztype[0],	 "",   "s");
+  pr("%8u    Single indirect zone%s\n",	  ztype[1],	 "",   "s");
+  pr("%8u    Double indirect zone%s\n",	  ztype[2],	 "",   "s");
+*/
+  lpr("%8ld    Free zone%s\n", nfreezone, "", "s");
+}
+
+/* Check the device which name is given by `f'.  The inodes listed by `clist'
+ * should be listed separately, and the inodes listed by `ilist' and the zones
+ * listed by `zlist' should be watched for while checking the file system.
+ */
+
+void chkdev(f, clist, ilist, zlist)
+char *f, **clist, **ilist, **zlist;
+{
+  if (automatic) repair = 1;
+  fsck_device = f;
+  initvars();
+
+  devopen();
+
+  getsuper();
+
+  if(block_size < _MIN_BLOCK_SIZE || block_size > _MAX_BLOCK_SIZE)
+  	fatal("funny block size");
+
+  if(!(rwbuf = malloc(block_size))) fatal("couldn't allocate fs buf (1)");
+  if(!(nullbuf = malloc(block_size))) fatal("couldn't allocate fs buf (2)");
+  memset(nullbuf, 0, block_size);
+
+  chksuper();
+
+  lsi(clist);
+
+  getbitmaps();
+
+  fillbitmap(spec_imap, (bit_nr) 1, (bit_nr) sb.s_ninodes + 1, ilist);
+  fillbitmap(spec_zmap, (bit_nr) FIRST, (bit_nr) sb.s_zones, zlist);
+
+  getcount();
+  chktree();
+  chkmap(zmap, spec_zmap, (bit_nr) FIRST - 1, BLK_ZMAP, N_ZMAP, "zone");
+  chkcount();
+  chkmap(imap, spec_imap, (bit_nr) 0, BLK_IMAP, N_IMAP, "inode");
+  chkilist();
+  printtotal();
+
+  putbitmaps();
+  freecount();
+  devclose();
+
+  if (changed) printf("----- FILE SYSTEM HAS BEEN MODIFIED -----\n\n");
+}
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  register char **clist = 0, **ilist = 0, **zlist = 0;
+
+  register devgiven = 0;
+  register char *arg;
+
+  if ((1 << BITSHIFT) != 8 * sizeof(bitchunk_t)) {
+	printf("Fsck was compiled with the wrong BITSHIFT!\n");
+	exit(1);
+  }
+
+  sync();
+  prog = *argv++;
+  while ((arg = *argv++) != 0)
+	if (arg[0] == '-' && arg[1] != 0 && arg[2] == 0) switch (arg[1]) {
+		    case 'a':	automatic ^= 1;	break;
+		    case 'c':
+			clist = getlist(&argv, "inode");
+			break;
+		    case 'i':
+			ilist = getlist(&argv, "inode");
+			break;
+		    case 'z':
+			zlist = getlist(&argv, "zone");
+			break;
+		    case 'r':	repair ^= 1;	break;
+		    case 'l':	listing ^= 1;	break;
+		    case 's':	listsuper ^= 1;	break;
+		    default:
+			printf("%s: unknown flag '%s'\n", prog, arg);
+		}
+	else {
+		chkdev(arg, clist, ilist, zlist);
+		clist = 0;
+		ilist = 0;
+		zlist = 0;
+		devgiven = 1;
+	}
+  if (!devgiven) {
+	printf("Usage: fsck [-acilrsz] file\n");
+	exit(1);
+  }
+  return(0);
+}
Index: /trunk/minix/commands/simple/fsck1.c
===================================================================
--- /trunk/minix/commands/simple/fsck1.c	(revision 9)
+++ /trunk/minix/commands/simple/fsck1.c	(revision 9)
@@ -0,0 +1,1477 @@
+/* Hacks for version 1.6 */					
+
+#define INODES_PER_BLOCK V1_INODES_PER_BLOCK
+#define INODE_SIZE V1_INODE_SIZE
+#define WORDS_PER_BLOCK (BLOCK_SIZE / (int) sizeof(bitchunk_t))
+#define MAX_ZONES (V1_NR_DZONES+V1_INDIRECTS+(long)V1_INDIRECTS*V1_INDIRECTS)
+#define NR_DZONE_NUM V1_NR_DZONES
+#define NR_INDIRECTS V1_INDIRECTS
+#define NR_ZONE_NUMS V1_NR_TZONES
+#define ZONE_NUM_SIZE V1_ZONE_NUM_SIZE
+#define bit_nr u16_t	/* perhaps bit_t should be used, although slower */
+#define Bit_nr U16_t
+#define block_nr block_t
+#define d_inode d1_inode
+#define d_inum d_ino
+#define dir_struct struct direct
+#define i_mode d1_mode
+#define i_nlinks d1_nlinks
+#define i_size d1_size
+#define i_zone d1_zone
+#define zone_nr zone1_t
+#define Zone_nr Zone1_t
+
+/* fsck - file system checker		Author: Robbert van Renesse */
+
+/* Modified by Norbert Schlenker
+*   Removed vestiges of standalone/DOS versions:
+*     - various unused variables and buffers removed
+*     - now uses library functions rather than private internal routines
+*     - bytewise structure copies replaced by structure assignment
+*     - fixed one bug with 14 character file names
+*     - other small tweaks for speed
+*
+* Modified by Lars Fredriksen at the request of Andy Tanenbaum, 90-03-10.
+*   Removed -m option, by which fsck could be told to make a file
+*   system on a 360K floppy.  The code had limited utility, was buggy,
+*   and failed due to a bug in the ACK C compiler.  Use mkfs instead!
+*/
+
+#include <sys/types.h>
+#include <sys/dir.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include "../../servers/fs/const.h"
+#include "../../servers/fs/inode.h"
+#include "../../servers/fs/type.h"
+#include <minix/fslib.h>
+#include <stdio.h>
+#include <dirent.h>
+
+#define BLOCK_SIZE _STATIC_BLOCK_SIZE
+
+#define BITSHIFT	  4	/* = log2(#bits(int)) */
+
+#define MAXPRINT	  8	/* max. number of error lines in chkmap */
+#define CINDIR		128	/* number of indirect zno's read at a time */
+#define CDIRECT		 16	/* number of dir entries read at a time */
+#define BITMASK		((1 << BITSHIFT) - 1)
+#define setbit(w, b)	(w[(b) >> BITSHIFT] |= 1 << ((b) & BITMASK))
+#define clrbit(w, b)	(w[(b) >> BITSHIFT] &= ~(1 << ((b) & BITMASK)))
+#define bitset(w, b)	(w[(b) >> BITSHIFT] & (1 << ((b) & BITMASK)))
+
+#define ZONE_CT 	360	/* default zones  (when making file system) */
+#define INODE_CT	 95	/* default inodes (when making file system) */
+
+#include "../../servers/fs/super.h"
+struct super_block sb;
+
+#define STICKY_BIT	01000	/* not defined anywhere else */
+
+/* Ztob gives the block address of a zone
+ * btoa gives the byte address of a block
+ */
+#define ztob(z)		((block_nr) (z) << sb.s_log_zone_size)
+#define btoa(b)		((long) (b) * BLOCK_SIZE)
+#define SCALE		((int) ztob(1))	/* # blocks in a zone */
+#define FIRST		((zone_nr) sb.s_firstdatazone)	/* as the name says */
+
+/* # blocks of each type */
+#define N_SUPER		1
+#define N_IMAP		(sb.s_imap_blocks)
+#define N_ZMAP		(sb.s_zmap_blocks)
+#define N_ILIST		((sb.s_ninodes+INODES_PER_BLOCK-1) / INODES_PER_BLOCK)
+#define N_DATA		(sb.s_nzones - FIRST)
+
+/* Block address of each type */
+#define BLK_SUPER	(1)
+#define BLK_IMAP	(BLK_SUPER + N_SUPER)
+#define BLK_ZMAP	(BLK_IMAP  + N_IMAP)
+#define BLK_ILIST	(BLK_ZMAP  + N_ZMAP)
+#define BLK_FIRST	ztob(FIRST)
+#define ZONE_SIZE	((int) ztob(BLOCK_SIZE))
+#define NLEVEL		(NR_ZONE_NUMS - NR_DZONE_NUM + 1)
+
+/* Byte address of a zone/of an inode */
+#define zaddr(z)	btoa(ztob(z))
+#define inoaddr(i)	((long) (i - 1) * INODE_SIZE + btoa(BLK_ILIST))
+#define INDCHUNK	(CINDIR * ZONE_NUM_SIZE)
+#define DIRCHUNK	(CDIRECT * DIR_ENTRY_SIZE)
+
+char *prog, *device;		/* program name (fsck), device name */
+int firstcnterr;		/* is this the first inode ref cnt error? */
+bitchunk_t *imap, *spec_imap;	/* inode bit maps */
+bitchunk_t *zmap, *spec_zmap;	/* zone bit maps */
+bitchunk_t *dirmap;		/* directory (inode) bit map */
+char rwbuf[BLOCK_SIZE];		/* one block buffer cache */
+block_nr thisblk;		/* block in buffer cache */
+char nullbuf[BLOCK_SIZE];	/* null buffer */
+nlink_t *count;			/* inode count */
+int changed;			/* has the diskette been written to? */
+struct stack {
+  dir_struct *st_dir;
+  struct stack *st_next;
+  char st_presence;
+} *ftop;
+
+int dev;			/* file descriptor of the device */
+
+#define DOT	1
+#define DOTDOT	2
+
+/* Counters for each type of inode/zone. */
+int nfreeinode, nregular, ndirectory, nblkspec, ncharspec, nbadinode;
+int npipe, nsyml, nfreezone, ztype[NLEVEL];
+
+int repair, automatic, listing, listsuper;	/* flags */
+int firstlist;			/* has the listing header been printed? */
+unsigned part_offset;		/* sector offset for this partition */
+char answer[] = "Answer questions with y or n.  Then hit RETURN";
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void initvars, (void));
+_PROTOTYPE(void fatal, (char *s));
+_PROTOTYPE(int eoln, (int c));
+_PROTOTYPE(int yes, (char *question));
+_PROTOTYPE(int atoo, (char *s));
+_PROTOTYPE(int input, (char *buf, int size));
+_PROTOTYPE(char *alloc, (unsigned nelem, unsigned elsize));
+_PROTOTYPE(void printname, (char *s));
+_PROTOTYPE(void printrec, (struct stack *sp));
+_PROTOTYPE(void printpath, (int mode, int nlcr));
+_PROTOTYPE(void devopen, (void));
+_PROTOTYPE(void devclose, (void));
+_PROTOTYPE(void devio, (block_nr bno, int dir));
+_PROTOTYPE(void devread, (long offset, char *buf, int size));
+_PROTOTYPE(void devwrite, (long offset, char *buf, int size));
+_PROTOTYPE(void pr, (char *fmt, int cnt, char *s, char *p));
+_PROTOTYPE(bit_nr getnumber, (char *s));
+_PROTOTYPE(char **getlist, (char ***argv, char *type));
+_PROTOTYPE(void lsuper, (void));
+_PROTOTYPE(void getsuper, (void));
+_PROTOTYPE(void chksuper, (void));
+_PROTOTYPE(void lsi, (char **clist));
+_PROTOTYPE(bitchunk_t *allocbitmap, (int nblk));
+_PROTOTYPE(void loadbitmap, (bitchunk_t *bitmap, block_nr bno, int nblk));
+_PROTOTYPE(void dumpbitmap, (bitchunk_t *bitmap, block_nr bno, int nblk));
+_PROTOTYPE(void fillbitmap, (bitchunk_t *bitmap, Bit_nr lwb, Bit_nr upb, char **list));
+_PROTOTYPE(void freebitmap, (bitchunk_t *p));
+_PROTOTYPE(void getbitmaps, (void));
+_PROTOTYPE(void putbitmaps, (void));
+_PROTOTYPE(void chkword, (unsigned w1, unsigned w2, Bit_nr bit, char *type, int *n, int *report));
+_PROTOTYPE(void chkmap, (bitchunk_t *cmap, bitchunk_t *dmap, Bit_nr bit, block_nr blkno, int nblk, char *type));
+_PROTOTYPE(void chkilist, (void));
+_PROTOTYPE(void getcount, (void));
+_PROTOTYPE(void counterror, (Ino_t ino));
+_PROTOTYPE(void chkcount, (void));
+_PROTOTYPE(void freecount, (void));
+_PROTOTYPE(void printperm, (mode_t mode, int shift, int special, int overlay));
+_PROTOTYPE(void list, (Ino_t ino, d_inode *ip));
+_PROTOTYPE(int Remove, (dir_struct *dp));
+_PROTOTYPE(void make_printable_name, (char *dst, char *src, int n));
+_PROTOTYPE(int chkdots, (Ino_t ino, off_t pos, dir_struct *dp, Ino_t exp));
+_PROTOTYPE(int chkname, (Ino_t ino, dir_struct *dp));
+_PROTOTYPE(int chkentry, (Ino_t ino, off_t pos, dir_struct *dp));
+_PROTOTYPE(int chkdirzone, (Ino_t ino, d_inode *ip, off_t pos, Zone_nr zno));
+_PROTOTYPE(void errzone, (char *mess, Zone_nr zno, int level, off_t pos));
+_PROTOTYPE(int markzone, (Ino_t ino, Zone_nr zno, int level, off_t pos));
+_PROTOTYPE(int chkindzone, (Ino_t ino, d_inode *ip, off_t *pos, Zone_nr zno, int level));
+_PROTOTYPE(off_t jump, (int level));
+_PROTOTYPE(int zonechk, (Ino_t ino, d_inode *ip, off_t *pos, Zone_nr zno, int level));
+_PROTOTYPE(int chkzones, (Ino_t ino, d_inode *ip, off_t *pos, zone_nr *zlist, int len, int level));
+_PROTOTYPE(int chkfile, (Ino_t ino, d_inode *ip));
+_PROTOTYPE(int chkdirectory, (Ino_t ino, d_inode *ip));
+_PROTOTYPE(int chklink, (Ino_t ino, d_inode *ip));
+_PROTOTYPE(int chkmode, (Ino_t ino, d_inode *ip));
+_PROTOTYPE(int chkinode, (Ino_t ino, d_inode *ip));
+_PROTOTYPE(int chkspecial, (Ino_t ino, d_inode *ip) );
+_PROTOTYPE(int descendtree, (dir_struct *dp));
+_PROTOTYPE(void chktree, (void));
+_PROTOTYPE(void printtotal, (void));
+_PROTOTYPE(void chkdev, (char *f, char **clist, char **ilist, char **zlist));
+
+/* Initialize the variables used by this program. */
+void initvars()
+{
+  register level;
+
+  nregular = ndirectory = nblkspec = ncharspec = nbadinode = npipe = nsyml = 0;
+  for (level = 0; level < NLEVEL; level++) ztype[level] = 0;
+  changed = 0;
+  thisblk = NO_BLOCK;
+  firstlist = 1;
+  firstcnterr = 1;
+}
+
+/* Print the string `s' and exit. */
+void fatal(s)
+char *s;
+{
+  printf("%s\nfatal\n", s);
+  exit(-1);
+}
+
+/* Test for end of line. */
+int eoln(c)
+int c;
+{
+  return(c == EOF || c == '\n' || c == '\r');
+}
+
+/* Ask a question and get the answer unless automatic is set. */
+int yes(question)
+char *question;
+{
+  register c, answer;
+
+  if (!repair) {
+	printf("\n");
+	return(0);
+  }
+  printf("%s? ", question);
+  if (automatic) {
+	printf("yes\n");
+	return(1);
+  }
+  fflush(stdout);
+  if ((c = answer = getchar()) == 'q' || c == 'Q') exit(1);
+  while (!eoln(c)) c = getchar();
+  return !(answer == 'n' || answer == 'N');
+}
+
+/* Convert string to integer.  Representation is octal. */
+int atoo(s)
+register char *s;
+{
+  register int n = 0;
+
+  while ('0' <= *s && *s < '8') {
+	n <<= 3;
+	n += *s++ - '0';
+  }
+  return n;
+}
+
+/* If repairing the file system, print a prompt and get a string from user. */
+int input(buf, size)
+char *buf;
+int size;
+{
+  register char *p = buf;
+
+  printf("\n");
+  if (repair) {
+	printf("--> ");
+	fflush(stdout);
+	while (--size) {
+		*p = getchar();
+		if (eoln(*p)) {
+			*p = 0;
+			return(p > buf);
+		}
+		p++;
+	}
+	*p = 0;
+	while (!eoln(getchar()));
+	return(1);
+  }
+  return(0);
+}
+
+/* Allocate some memory and zero it. */
+char *alloc(nelem, elsize)
+unsigned nelem, elsize;
+{
+  char *p;
+
+  if ((p = (char *) malloc((size_t)nelem * elsize)) == 0) fatal("out of memory");
+  memset(p, 0, (size_t)nelem * elsize);
+  return(p);
+}
+
+/* Print the name in a directory entry. */
+void printname(s)
+char *s;
+{
+  register n = NAME_MAX;
+  int c;
+
+  do {
+	if ((c = *s) == 0) break;
+	if (!isprint(c)) c = '?';
+	putchar(c);
+	s++;
+  } while (--n);
+}
+
+/* Print the pathname given by a linked list pointed to by `sp'.  The
+ * names are in reverse order.
+ */
+void printrec(sp)
+struct stack *sp;
+{
+  if (sp->st_next != 0) {
+	printrec(sp->st_next);
+	putchar('/');
+	printname(sp->st_dir->d_name);
+  }
+}
+
+/* Print the current pathname.  */
+void printpath(mode, nlcr)
+int mode;
+int nlcr;
+{
+  if (ftop->st_next == 0)
+	putchar('/');
+  else
+	printrec(ftop);
+  switch (mode) {
+      case 1:
+	printf(" (ino = %u, ", ftop->st_dir->d_inum);
+	break;
+      case 2:
+	printf(" (ino = %u)", ftop->st_dir->d_inum);
+	break;
+  }
+  if (nlcr) printf("\n");
+}
+
+/* Open the device.  */
+void devopen()
+{
+  if ((dev = open(device, repair ? O_RDWR : O_RDONLY)) < 0) {
+	perror(device);
+	fatal("");
+  }
+}
+
+/* Close the device. */
+void devclose()
+{
+  if (close(dev) != 0) {
+	perror("close");
+	fatal("");
+  }
+}
+
+/* Read or write a block. */
+void devio(bno, dir)
+block_nr bno;
+int dir;
+{
+  if (dir == READING && bno == thisblk) return;
+  thisblk = bno;
+
+  lseek(dev, (off_t) btoa(bno), SEEK_SET);
+  if (dir == READING) {
+	if (read(dev, rwbuf, BLOCK_SIZE) == BLOCK_SIZE)
+		return;
+  } else {
+	if (write(dev, rwbuf, BLOCK_SIZE) == BLOCK_SIZE)
+		return;
+  }
+
+  printf("%s: can't %s block %ld (error = 0x%x)\n", prog,
+         dir == READING ? "read" : "write", (long) bno, errno);
+  if (dir == READING) {
+	printf("Continuing with a zero-filled block.\n");
+	memset(rwbuf, 0, BLOCK_SIZE);
+	return;
+  }
+  fatal("");
+}
+
+/* Read `size' bytes from the disk starting at byte `offset'. */
+void devread(offset, buf, size)
+long offset;
+char *buf;
+int size;
+{
+  devio((block_nr) (offset / BLOCK_SIZE), READING);
+  memmove(buf, &rwbuf[(int) (offset % BLOCK_SIZE)], (size_t)size);
+}
+
+/* Write `size' bytes to the disk starting at byte `offset'. */
+void devwrite(offset, buf, size)
+long offset;
+char *buf;
+int size;
+{
+  if (!repair) fatal("internal error (devwrite)");
+  if (size != BLOCK_SIZE) devio((block_nr) (offset / BLOCK_SIZE), READING);
+  memmove(&rwbuf[(int) (offset % BLOCK_SIZE)], buf, (size_t)size);
+  devio((block_nr) (offset / BLOCK_SIZE), WRITING);
+  changed = 1;
+}
+
+/* Print a string with either a singular or a plural pronoun. */
+void pr(fmt, cnt, s, p)
+char *fmt, *s, *p;
+int cnt;
+{
+  printf(fmt, cnt, cnt == 1 ? s : p);
+}
+
+/* Convert string to number. */
+bit_nr getnumber(s)
+register char *s;
+{
+  register bit_nr n = 0;
+
+  if (s == NULL)
+	return NO_BIT;
+  while (isdigit(*s))
+	n = (n << 1) + (n << 3) + *s++ - '0';
+  return (*s == '\0') ? n : NO_BIT;
+}
+
+/* See if the list pointed to by `argv' contains numbers. */
+char **getlist(argv, type)
+char ***argv, *type;
+{
+  register char **list = *argv;
+  register empty = 1;
+
+  while (getnumber(**argv) != NO_BIT) {
+	(*argv)++;
+	empty = 0;
+  }
+  if (empty) {
+	printf("warning: no %s numbers given\n", type);
+	return(NULL);
+  }
+  return(list);
+}
+
+/* Make a listing of the super block.  If `repair' is set, ask the user
+ * for changes.
+ */
+void lsuper()
+{
+  char buf[80];
+
+  do {
+	printf("ninodes       = %u", sb.s_ninodes);
+	if (input(buf, 80)) sb.s_ninodes = atol(buf);
+	printf("nzones        = %u", sb.s_nzones);
+	if (input(buf, 80)) sb.s_nzones = atol(buf);
+	printf("imap_blocks   = %u", sb.s_imap_blocks);
+	if (input(buf, 80)) sb.s_imap_blocks = atol(buf);
+	printf("zmap_blocks   = %u", sb.s_zmap_blocks);
+	if (input(buf, 80)) sb.s_zmap_blocks = atol(buf);
+	printf("firstdatazone = %u", sb.s_firstdatazone);
+	if (input(buf, 80)) sb.s_firstdatazone = atol(buf);
+	printf("log_zone_size = %u", sb.s_log_zone_size);
+	if (input(buf, 80)) sb.s_log_zone_size = atol(buf);
+	printf("maxsize       = %lu", sb.s_max_size);
+	if (input(buf, 80)) sb.s_max_size = atol(buf);
+	if (yes("ok now")) {
+		devwrite(btoa(BLK_SUPER), (char *) &sb, sizeof(sb));
+		return;
+	}
+  } while (yes("Do you want to try again"));
+  if (repair) exit(0);
+}
+
+/* Get the super block from either disk or user.  Do some initial checks. */
+void getsuper()
+{
+  devread(btoa(BLK_SUPER), (char *) &sb, sizeof(sb));
+  if (listsuper) lsuper();
+  if (sb.s_magic == SUPER_V2) fatal("Cannot handle V2 file systems");
+  if (sb.s_magic != SUPER_MAGIC) fatal("bad magic number in super block");
+  if ((short) sb.s_ninodes <= 0) fatal("no inodes");
+  if (sb.s_nzones <= 2) fatal("no zones");
+  if ((short) sb.s_imap_blocks <= 0) fatal("no imap");
+  if ((short) sb.s_zmap_blocks <= 0) fatal("no zmap");
+  if ((short) sb.s_firstdatazone <= 1) fatal("first data zone too small");
+  if ((short) sb.s_log_zone_size < 0) fatal("zone size < block size");
+  if (sb.s_max_size <= 0) fatal("max. file size <= 0");
+}
+
+/* Check the super block for reasonable contents. */
+void chksuper()
+{
+  register n;
+  register off_t maxsize;
+
+  n = bitmapsize((bit_t) sb.s_ninodes + 1, BLOCK_SIZE);
+  if (sb.s_magic != SUPER_MAGIC) fatal("bad magic number in super block");
+  if ((short) sb.s_imap_blocks < n) fatal("too few imap blocks");
+  if (sb.s_imap_blocks != n) {
+	pr("warning: expected %d imap_block%s", n, "", "s");
+	printf(" instead of %d\n", sb.s_imap_blocks);
+  }
+  n = bitmapsize((bit_t) sb.s_nzones, BLOCK_SIZE);
+  if ((short) sb.s_zmap_blocks < n) fatal("too few zmap blocks");
+  if (sb.s_zmap_blocks != n) {
+	pr("warning: expected %d zmap_block%s", n, "", "s");
+	printf(" instead of %d\n", sb.s_zmap_blocks);
+  }
+  if (sb.s_firstdatazone >= sb.s_nzones)
+	fatal("first data zone too large");
+  if ((unsigned short) sb.s_log_zone_size >= 8 * sizeof(block_nr))
+	fatal("log_zone_size too large");
+  if (sb.s_log_zone_size > 8) printf("warning: large log_zone_size (%d)\n",
+	       sb.s_log_zone_size);
+  n = (BLK_ILIST + N_ILIST + SCALE - 1) >> sb.s_log_zone_size;
+  if ((short) sb.s_firstdatazone < n) fatal("first data zone too small");
+  if (sb.s_firstdatazone != n) {
+	printf("warning: expected first data zone to be %d ", n);
+	printf("instead of %u\n", sb.s_firstdatazone);
+  }
+  maxsize = MAX_FILE_POS;
+  if (((maxsize - 1) >> sb.s_log_zone_size) / BLOCK_SIZE >= MAX_ZONES)
+	maxsize = ((long) MAX_ZONES * BLOCK_SIZE) << sb.s_log_zone_size;
+  if (sb.s_max_size != maxsize) {
+	printf("warning: expected max size to be %ld ", maxsize);
+	printf("instead of %ld\n", sb.s_max_size);
+  }
+}
+
+/* Make a listing of the inodes given by `clist'.  If `repair' is set, ask
+ * the user for changes.
+ */
+void lsi(clist)
+char **clist;
+{
+  register bit_nr bit;
+  register ino_t ino;
+  d_inode inode, *ip = &inode;
+  char buf[80];
+
+  if (clist == 0) return;
+  while ((bit = getnumber(*clist++)) != NO_BIT) {
+	setbit(spec_imap, bit);
+	ino = bit;
+	do {
+		devread(inoaddr(ino), (char *) ip, INODE_SIZE);
+		printf("inode %u:\n", ino);
+		printf("    mode   = %06o", ip->i_mode);
+		if (input(buf, 80)) ip->i_mode = atoo(buf);
+		printf("    nlinks = %6u", ip->i_nlinks);
+		if (input(buf, 80)) ip->i_nlinks = atol(buf);
+		printf("    size   = %6ld", ip->i_size);
+		if (input(buf, 80)) ip->i_size = atol(buf);
+		if (yes("Write this back")) {
+			devwrite(inoaddr(ino), (char *) ip, INODE_SIZE);
+			break;
+		}
+	} while (yes("Do you want to change it again"));
+  }
+}
+
+/* Allocate `nblk' blocks worth of bitmap. */
+bitchunk_t *allocbitmap(nblk)
+int nblk;
+{
+  register bitchunk_t *bitmap;
+
+  bitmap = (bitchunk_t *) alloc(nblk, BLOCK_SIZE);
+  *bitmap |= 1;
+  return(bitmap);
+}
+
+/* Load the bitmap starting at block `bno' from disk. */
+void loadbitmap(bitmap, bno, nblk)
+bitchunk_t *bitmap;
+block_nr bno;
+int nblk;
+{
+  register i;
+  register bitchunk_t *p;
+
+  p = bitmap;
+  for (i = 0; i < nblk; i++, bno++, p += WORDS_PER_BLOCK)
+	devread(btoa(bno), (char *) p, BLOCK_SIZE);
+  *bitmap |= 1;
+}
+
+/* Write the bitmap starting at block `bno' to disk. */
+void dumpbitmap(bitmap, bno, nblk)
+bitchunk_t *bitmap;
+block_nr bno;
+int nblk;
+{
+  register i;
+  register bitchunk_t *p = bitmap;
+
+  for (i = 0; i < nblk; i++, bno++, p += WORDS_PER_BLOCK)
+	devwrite(btoa(bno), (char *) p, BLOCK_SIZE);
+}
+
+/* Set the bits given by `list' in the bitmap. */
+void fillbitmap(bitmap, lwb, upb, list)
+bitchunk_t *bitmap;
+bit_nr lwb, upb;
+char **list;
+{
+  register bit_nr bit;
+
+  if (list == 0) return;
+  while ((bit = getnumber(*list++)) != NO_BIT)
+	if (bit < lwb || bit >= upb) {
+		if (bitmap == spec_imap)
+			printf("inode number %u ", bit);
+		else
+			printf("zone number %u ", bit);
+		printf("out of range (ignored)\n");
+	} else
+		setbit(bitmap, bit - lwb + 1);
+}
+
+/* Deallocate the bitmap `p'. */
+void freebitmap(p)
+bitchunk_t *p;
+{
+  free((char *) p);
+}
+
+/* Get all the bitmaps used by this program. */
+void getbitmaps()
+{
+  imap = allocbitmap(N_IMAP);
+  zmap = allocbitmap(N_ZMAP);
+  spec_imap = allocbitmap(N_IMAP);
+  spec_zmap = allocbitmap(N_ZMAP);
+  dirmap = allocbitmap(N_IMAP);
+}
+
+/* Release all the space taken by the bitmaps. */
+void putbitmaps()
+{
+  freebitmap(imap);
+  freebitmap(zmap);
+  freebitmap(spec_imap);
+  freebitmap(spec_zmap);
+  freebitmap(dirmap);
+}
+
+/* `w1' and `w2' are differing words from two bitmaps that should be
+ * identical.  Print what's the matter with them.
+ */
+void chkword(w1, w2, bit, type, n, report)
+unsigned w1, w2;
+char *type;
+bit_nr bit;
+int *n, *report;
+{
+  for (; (w1 | w2); w1 >>= 1, w2 >>= 1, bit++)
+	if ((w1 ^ w2) & 1 && ++(*n) % MAXPRINT == 0 && *report &&
+	    (!repair || automatic || yes("stop this listing")))
+		*report = 0;
+	else if (*report)
+		if ((w1 & 1) && !(w2 & 1))
+			printf("%s %u is missing\n", type, bit);
+		else if (!(w1 & 1) && (w2 & 1))
+			printf("%s %u is not free\n", type, bit);
+}
+
+/* Check if the given (correct) bitmap is identical with the one that is
+ * on the disk.  If not, ask if the disk should be repaired.
+ */
+void chkmap(cmap, dmap, bit, blkno, nblk, type)
+bitchunk_t *cmap, *dmap;
+bit_nr bit;
+block_nr blkno;
+int nblk;
+char *type;
+{
+  register bitchunk_t *p = dmap, *q = cmap;
+  int report = 1, nerr = 0;
+  int w = nblk * WORDS_PER_BLOCK;
+
+  printf("Checking %s map\n", type);
+  loadbitmap(dmap, blkno, nblk);
+  do {
+	if (*p != *q) chkword(*p, *q, bit, type, &nerr, &report);
+	p++;
+	q++;
+	bit += 8 * sizeof(bitchunk_t);
+  } while (--w > 0);
+
+  if ((!repair || automatic) && !report) printf("etc. ");
+  if (nerr > MAXPRINT || nerr > 10) printf("%d errors found. ", nerr);
+  if (nerr != 0 && yes("install a new map")) dumpbitmap(cmap, blkno, nblk);
+  if (nerr > 0) printf("\n");
+}
+
+/* See if the inodes that aren't allocated are cleared. */
+void chkilist()
+{
+  register ino_t ino = 1;
+  mode_t mode;
+
+  printf("Checking inode list\n");
+  do
+	if (!bitset(imap, (bit_nr) ino)) {
+		devread(inoaddr(ino), (char *) &mode, sizeof(mode));
+		if (mode != I_NOT_ALLOC) {
+			printf("mode inode %u not cleared", ino);
+			if (yes(". clear")) devwrite(inoaddr(ino), nullbuf,
+					 INODE_SIZE);
+		}
+	}
+  while (++ino <= sb.s_ninodes);
+  printf("\n");
+}
+
+/* Allocate an array to maintain the inode reference counts in. */
+void getcount()
+{
+  count = (nlink_t *) alloc(sb.s_ninodes + 1, sizeof(nlink_t));
+}
+
+/* The reference count for inode `ino' is wrong.  Ask if it should be adjusted. */
+void counterror(ino)
+ino_t ino;
+{
+  d_inode inode;
+
+  if (firstcnterr) {
+	printf("INODE NLINK COUNT\n");
+	firstcnterr = 0;
+  }
+  devread(inoaddr(ino), (char *) &inode, INODE_SIZE);
+  count[ino] += inode.i_nlinks;
+  printf("%5u %5u %5u", ino, (unsigned) inode.i_nlinks, count[ino]);
+  if (yes(" adjust")) {
+	if ((inode.i_nlinks = count[ino]) == 0) {
+		fatal("internal error (counterror)");
+/* This would be a patch
+		inode.i_mode = I_NOT_ALLOC;
+		clrbit(imap, (bit_nr) ino);
+*/
+	}
+	devwrite(inoaddr(ino), (char *) &inode, INODE_SIZE);
+  }
+}
+
+/* Check if the reference count of the inodes are correct.  The array `count'
+ * is maintained as follows:  an entry indexed by the inode number is
+ * incremented each time a link is found; when the inode is read the link
+ * count in there is substracted from the corresponding entry in `count'.
+ * Thus, when the whole file system has been traversed, all the entries
+ * should be zero.
+ */
+void chkcount()
+{
+  register ino_t ino;
+
+  for (ino = 1; ino <= sb.s_ninodes; ino++)
+	if (count[ino] != 0) counterror(ino);
+  if (!firstcnterr) printf("\n");
+}
+
+/* Deallocate the `count' array. */
+void freecount()
+{
+  free((char *) count);
+}
+
+/* Print the inode permission bits given by mode and shift. */
+void printperm(mode_t mode, int shift, int special, int overlay)
+{
+  if (mode >> shift & R_BIT)
+	putchar('r');
+  else
+	putchar('-');
+  if (mode >> shift & W_BIT)
+	putchar('w');
+  else
+	putchar('-');
+  if (mode & special)
+	putchar(overlay);
+  else
+	if (mode >> shift & X_BIT)
+		putchar('x');
+	else
+		putchar('-');
+}
+
+/* List the given inode. */
+void list(ino, ip)
+ino_t ino;
+d_inode *ip;
+{
+  if (firstlist) {
+	firstlist = 0;
+	printf(" inode permission link   size name\n");
+  }
+  printf("%6u ", ino);
+  switch (ip->i_mode & I_TYPE) {
+      case I_REGULAR:		putchar('-');	break;
+      case I_DIRECTORY:		putchar('d');	break;
+      case I_CHAR_SPECIAL:	putchar('c');	break;
+      case I_BLOCK_SPECIAL:	putchar('b');	break;
+      case I_NAMED_PIPE:	putchar('p');	break;
+#ifdef I_SYMBOLIC_LINK
+      case I_SYMBOLIC_LINK:	putchar('l');	break;
+#endif
+      default:			putchar('?');
+}
+  printperm(ip->i_mode, 6, I_SET_UID_BIT, 's');
+  printperm(ip->i_mode, 3, I_SET_GID_BIT, 's');
+  printperm(ip->i_mode, 0, STICKY_BIT, 't');
+  printf(" %3u ", ip->i_nlinks);
+  switch (ip->i_mode & I_TYPE) {
+      case I_CHAR_SPECIAL:
+      case I_BLOCK_SPECIAL:
+	printf("  %2x,%2x ", (dev_t) ip->i_zone[0] >> MAJOR & 0xFF,
+	       (dev_t) ip->i_zone[0] >> MINOR & 0xFF);
+	break;
+      default:	printf("%7ld ", ip->i_size);
+  }
+  printpath(0, 1);
+}
+
+/* Remove an entry from a directory if ok with the user.
+ * Don't name the function remove() - that is owned by ANSI, and chaos results
+ * when it is a macro.
+ */
+int Remove(dp)
+dir_struct *dp;
+{
+  setbit(spec_imap, (bit_nr) dp->d_inum);
+  if (yes(". remove entry")) {
+	count[dp->d_inum]--;
+	memset((void *) dp, 0, sizeof(dir_struct));
+	return(1);
+  }
+  return(0);
+}
+
+/* Convert string so that embedded control characters are printable. */
+void make_printable_name(dst, src, n)
+register char *dst;
+register char *src;
+register int n;
+{
+  register int c;
+
+  while (--n >= 0 && (c = *src++) != '\0') {
+	if (isprint(c) && c != '\\')
+		*dst++ = c;
+	else {
+		*dst++ = '\\';
+		switch (c) {
+		      case '\\':
+			*dst++ = '\\'; break;
+		      case '\b':
+			*dst++ = 'b'; break;
+		      case '\f':
+			*dst++ = 'f'; break;
+		      case '\n':
+			*dst++ = 'n'; break;
+		      case '\r':
+			*dst++ = 'r'; break;
+		      case '\t':
+			*dst++ = 't'; break;
+		      default:
+			*dst++ = '0' + ((c >> 6) & 03);
+			*dst++ = '0' + ((c >> 3) & 07);
+			*dst++ = '0' + (c & 07);
+		}
+	}
+  }
+  *dst = '\0';
+}
+
+/* See if the `.' or `..' entry is as expected. */
+int chkdots(ino, pos, dp, exp)
+ino_t ino, exp;
+off_t pos;
+dir_struct *dp;
+{
+  char printable_name[4 * NAME_MAX + 1];
+
+  if (dp->d_inum != exp) {
+	make_printable_name(printable_name, dp->d_name, sizeof(dp->d_name));
+	printf("bad %s in ", printable_name);
+	printpath(1, 0);
+	printf("%s is linked to %u ", printable_name, dp->d_inum);
+	printf("instead of %u)", exp);
+	setbit(spec_imap, (bit_nr) ino);
+	setbit(spec_imap, (bit_nr) dp->d_inum);
+	setbit(spec_imap, (bit_nr) exp);
+	if (yes(". repair")) {
+		count[dp->d_inum]--;
+		dp->d_inum = exp;
+		count[exp]++;
+		return(0);
+	}
+  } else if (pos != (dp->d_name[1] ? DIR_ENTRY_SIZE : 0)) {
+	make_printable_name(printable_name, dp->d_name, sizeof(dp->d_name));
+	printf("warning: %s has offset %ld in ", printable_name, pos);
+	printpath(1, 0);
+	printf("%s is linked to %u)\n", printable_name, dp->d_inum);
+	setbit(spec_imap, (bit_nr) ino);
+	setbit(spec_imap, (bit_nr) dp->d_inum);
+	setbit(spec_imap, (bit_nr) exp);
+  }
+  return(1);
+}
+
+/* Check the name in a directory entry. */
+int chkname(ino, dp)
+ino_t ino;
+dir_struct *dp;
+{
+  register n = NAME_MAX + 1;
+  register char *p = dp->d_name;
+
+  if (*p == '\0') {
+	printf("null name found in ");
+	printpath(0, 0);
+	setbit(spec_imap, (bit_nr) ino);
+	if (Remove(dp)) return(0);
+  }
+  while (*p != '\0' && --n != 0)
+	if (*p++ == '/') {
+		printf("found a '/' in entry of directory ");
+		printpath(1, 0);
+		setbit(spec_imap, (bit_nr) ino);
+		printf("entry = '");
+		printname(dp->d_name);
+		printf("')");
+		if (Remove(dp)) return(0);
+		break;
+	}
+  return(1);
+}
+
+/* Check a directory entry.  Here the routine `descendtree' is called
+ * recursively to check the file or directory pointed to by the entry.
+ */
+int chkentry(ino, pos, dp)
+ino_t ino;
+off_t pos;
+dir_struct *dp;
+{
+  if (dp->d_inum < ROOT_INODE || dp->d_inum > sb.s_ninodes) {
+	printf("bad inode found in directory ");
+	printpath(1, 0);
+	printf("ino found = %u, ", dp->d_inum);
+	printf("name = '");
+	printname(dp->d_name);
+	printf("')");
+	if (yes(". remove entry")) {
+		memset((void *) dp, 0, sizeof(dir_struct));
+		return(0);
+	}
+	return(1);
+  }
+  if ((unsigned) count[dp->d_inum] == CHAR_MAX) {
+	printf("too many links to ino %u\n", dp->d_inum);
+	printf("discovered at entry '");
+	printname(dp->d_name);
+	printf("' in directory ");
+	printpath(0, 1);
+	if (Remove(dp)) return(0);
+  }
+  count[dp->d_inum]++;
+  if (strcmp(dp->d_name, ".") == 0) {
+	ftop->st_presence |= DOT;
+	return(chkdots(ino, pos, dp, ino));
+  }
+  if (strcmp(dp->d_name, "..") == 0) {
+	ftop->st_presence |= DOTDOT;
+	return(chkdots(ino, pos, dp, ino == ROOT_INODE ? ino :
+			ftop->st_next->st_dir->d_inum));
+  }
+  if (!chkname(ino, dp)) return(0);
+  if (bitset(dirmap, (bit_nr) dp->d_inum)) {
+	printf("link to directory discovered in ");
+	printpath(1, 0);
+	printf("name = '");
+	printname(dp->d_name);
+	printf("', dir ino = %u)", dp->d_inum);
+	return !Remove(dp);
+  }
+  return(descendtree(dp));
+}
+
+/* Check a zone of a directory by checking all the entries in the zone.
+ * The zone is split up into chunks to not allocate too much stack.
+ */
+int chkdirzone(ino, ip, pos, zno)
+ino_t ino;
+d_inode *ip;
+off_t pos;
+zone_nr zno;
+{
+  dir_struct dirblk[CDIRECT];
+  register dir_struct *dp;
+  register n = SCALE * (NR_DIR_ENTRIES(BLOCK_SIZE) / CDIRECT), dirty;
+  register long offset = zaddr(zno);
+  register off_t size = 0;
+
+  do {
+	devread(offset, (char *) dirblk, DIRCHUNK);
+	dirty = 0;
+	for (dp = dirblk; dp < &dirblk[CDIRECT]; dp++) {
+		if (dp->d_inum != NO_ENTRY && !chkentry(ino, pos, dp))
+			dirty = 1;
+		pos += DIR_ENTRY_SIZE;
+		if (dp->d_inum != NO_ENTRY) size = pos;
+	}
+	if (dirty) devwrite(offset, (char *) dirblk, DIRCHUNK);
+	offset += DIRCHUNK;
+  } while (--n);
+
+  if (size > ip->i_size) {
+	printf("size not updated of directory ");
+	printpath(2, 0);
+	if (yes(". extend")) {
+		setbit(spec_imap, (bit_nr) ino);
+		ip->i_size = size;
+		devwrite(inoaddr(ino), (char *) ip, INODE_SIZE);
+	}
+  }
+  return(1);
+}
+
+/* There is something wrong with the given zone.  Print some details. */
+void errzone(mess, zno, level, pos)
+char *mess;
+zone_nr zno;
+int level;
+off_t pos;
+{
+  printf("%s zone in ", mess);
+  printpath(1, 0);
+  printf("zno = %u, type = ", zno);
+  switch (level) {
+      case 0:	printf("DATA");	break;
+      case 1:	printf("SINGLE INDIRECT");	break;
+      case 2:	printf("DOUBLE INDIRECT");	break;
+      default:	printf("VERY INDIRECT");
+  }
+  printf(", pos = %ld)\n", pos);
+}
+
+/* Found the given zone in the given inode.  Check it, and if ok, mark it
+ * in the zone bitmap.
+ */
+int markzone(ino, zno, level, pos)
+ino_t ino;
+zone_nr zno;
+int level;
+off_t pos;
+{
+  register bit_nr bit = (bit_nr) zno - FIRST + 1;
+
+  ztype[level]++;
+  if (zno < FIRST || zno >= sb.s_nzones) {
+	errzone("out-of-range", zno, level, pos);
+	return(0);
+  }
+  if (bitset(zmap, bit)) {
+	setbit(spec_zmap, bit);
+	errzone("duplicate", zno, level, pos);
+	return(0);
+  }
+  nfreezone--;
+  if (bitset(spec_zmap, bit)) errzone("found", zno, level, pos);
+  setbit(zmap, bit);
+  return(1);
+}
+
+/* Check an indirect zone by checking all of its entries.
+ * The zone is split up into chunks to not allocate too much stack.
+ */
+int chkindzone(ino, ip, pos, zno, level)
+ino_t ino;
+d_inode *ip;
+off_t *pos;
+zone_nr zno;
+int level;
+{
+  zone_nr indirect[CINDIR];
+  register n = NR_INDIRECTS / CINDIR;
+  register long offset = zaddr(zno);
+
+  do {
+	devread(offset, (char *) indirect, INDCHUNK);
+	if (!chkzones(ino, ip, pos, indirect, CINDIR, level - 1)) return(0);
+	offset += INDCHUNK;
+  } while (--n && *pos < ip->i_size);
+  return(1);
+}
+
+/* Return the size of a gap in the file, represented by a null zone number
+ * at some level of indirection.
+ */
+off_t jump(level)
+int level;
+{
+  off_t power = ZONE_SIZE;
+
+  if (level != 0) do
+		power *= NR_INDIRECTS;
+	while (--level);
+  return(power);
+}
+
+/* Check a zone, which may be either a normal data zone, a directory zone,
+ * or an indirect zone.
+ */
+int zonechk(ino, ip, pos, zno, level)
+ino_t ino;
+d_inode *ip;
+off_t *pos;
+zone_nr zno;
+int level;
+{
+  if (level == 0) {
+	if ((ip->i_mode & I_TYPE) == I_DIRECTORY &&
+	    !chkdirzone(ino, ip, *pos, zno))
+		return(0);
+	*pos += ZONE_SIZE;
+	return(1);
+  } else
+	return chkindzone(ino, ip, pos, zno, level);
+}
+
+/* Check a list of zones given by `zlist'. */
+int chkzones(ino, ip, pos, zlist, len, level)
+ino_t ino;
+d_inode *ip;
+off_t *pos;
+zone_nr *zlist;
+int len;
+int level;
+{
+  register ok = 1, i;
+
+  /* The check on the position in the next loop is commented out, since FS
+   * now requires valid zone numbers in each level that is necessary and FS
+   * always deleted all the zones in the double indirect block.
+   */
+  for (i = 0; i < len /* && *pos < ip->i_size */ ; i++)
+	if (zlist[i] == NO_ZONE)
+		*pos += jump(level);
+	else if (!markzone(ino, zlist[i], level, *pos)) {
+		*pos += jump(level);
+		ok = 0;
+	} else if (!zonechk(ino, ip, pos, zlist[i], level))
+		ok = 0;
+  return(ok);
+}
+
+/* Check a file or a directory. */
+int chkfile(ino, ip)
+ino_t ino;
+d_inode *ip;
+{
+  register ok, i, level;
+  off_t pos = 0;
+
+  ok = chkzones(ino, ip, &pos, (zone_nr *)&ip->i_zone[0], NR_DZONE_NUM, 0);
+  for (i = NR_DZONE_NUM, level = 1; i < NR_ZONE_NUMS; i++, level++)
+	ok &= chkzones(ino, ip, &pos, (zone_nr *)&ip->i_zone[i], 1, level);
+  return(ok);
+}
+
+/* Check a directory by checking the contents.  Check if . and .. are present. */
+int chkdirectory(ino, ip)
+ino_t ino;
+d_inode *ip;
+{
+  register ok;
+
+  setbit(dirmap, (bit_nr) ino);
+  ok = chkfile(ino, ip);
+  if (!(ftop->st_presence & DOT)) {
+	printf(". missing in ");
+	printpath(2, 1);
+	ok = 0;
+  }
+  if (!(ftop->st_presence & DOTDOT)) {
+	printf(".. missing in ");
+	printpath(2, 1);
+	ok = 0;
+  }
+  return(ok);
+}
+
+#ifdef I_SYMBOLIC_LINK
+
+/* Check the validity of a symbolic link. */
+int chklink(ino, ip)
+ino_t ino;
+d_inode *ip;
+{
+  int ok;
+
+  ok = chkfile(ino, ip);
+  if (ip->i_size <= 0 || ip->i_size > BLOCK_SIZE) {
+	if (ip->i_size == 0)
+		printf("empty symbolic link ");
+	else
+		printf("symbolic link too large (size %ld) ", ip->i_size);
+	printpath(2, 1);
+	ok = 0;
+  }
+  return(ok);
+}
+
+#endif
+
+/* Check the validity of a special file. */
+int chkspecial(ino, ip)
+ino_t ino;
+d_inode *ip;
+{
+  int i, ok;
+
+  ok = 1;
+  if ((dev_t) ip->i_zone[0] == NO_DEV) {
+	printf("illegal device number %u for special file ", ip->i_zone[0]);
+	printpath(2, 1);
+	ok = 0;
+  }
+
+  /* FS will not use the remaining "zone numbers" but 1.6.11++ will panic if
+   * they are nonzero, since this should not happen.
+   */
+  for (i = 1; i < NR_ZONE_NUMS; i++)
+	if (ip->i_zone[i] != NO_ZONE) {
+		printf("nonzero zone number %u for special file ",
+		       ip->i_zone[i]);
+		printpath(2, 1);
+		ok = 0;
+	}
+  return(ok);
+}
+
+/* Check the mode and contents of an inode. */
+int chkmode(ino, ip)
+ino_t ino;
+d_inode *ip;
+{
+  switch (ip->i_mode & I_TYPE) {
+      case I_REGULAR:
+	nregular++;
+	return chkfile(ino, ip);
+      case I_DIRECTORY:
+	ndirectory++;
+	return chkdirectory(ino, ip);
+      case I_BLOCK_SPECIAL:
+	nblkspec++;
+	return chkspecial(ino, ip);
+      case I_CHAR_SPECIAL:
+	ncharspec++;
+	return chkspecial(ino, ip);
+      case I_NAMED_PIPE:
+	npipe++;
+	return chkfile(ino, ip);
+#ifdef I_SYMBOLIC_LINK
+      case I_SYMBOLIC_LINK:
+	nsyml++;
+	return chklink(ino, ip);
+#endif
+      default:
+	nbadinode++;
+	printf("bad mode of ");
+	printpath(1, 0);
+	printf("mode = %o)", ip->i_mode);
+	return(0);
+  }
+}
+
+/* Check an inode. */
+int chkinode(ino, ip)
+ino_t ino;
+d_inode *ip;
+{
+  if (ino == ROOT_INODE && (ip->i_mode & I_TYPE) != I_DIRECTORY) {
+	printf("root inode is not a directory ");
+	printf("(ino = %u, mode = %o)\n", ino, ip->i_mode);
+	fatal("");
+  }
+  if (ip->i_nlinks == 0) {
+	printf("link count zero of ");
+	printpath(2, 0);
+	return(0);
+  }
+  nfreeinode--;
+  setbit(imap, (bit_nr) ino);
+  if ((unsigned) ip->i_nlinks > CHAR_MAX) {
+	printf("link count too big in ");
+	printpath(1, 0);
+	printf("cnt = %u)\n", (unsigned) ip->i_nlinks);
+	count[ino] -= CHAR_MAX;
+	setbit(spec_imap, (bit_nr) ino);
+  } else
+	count[ino] -= (unsigned) ip->i_nlinks;
+  return chkmode(ino, ip);
+}
+
+/* Check the directory entry pointed to by dp, by checking the inode. */
+int descendtree(dp)
+dir_struct *dp;
+{
+  d_inode inode;
+  register ino_t ino = dp->d_inum;
+  register visited;
+  struct stack stk;
+
+  stk.st_dir = dp;
+  stk.st_next = ftop;
+  ftop = &stk;
+  if (bitset(spec_imap, (bit_nr) ino)) {
+	printf("found inode %u: ", ino);
+	printpath(0, 1);
+  }
+  visited = bitset(imap, (bit_nr) ino);
+  if (!visited || listing) {
+	devread(inoaddr(ino), (char *) &inode, INODE_SIZE);
+	if (listing) list(ino, &inode);
+	if (!visited && !chkinode(ino, &inode)) {
+		setbit(spec_imap, (bit_nr) ino);
+		if (yes("remove")) {
+			count[ino] += inode.i_nlinks - 1;
+			clrbit(imap, (bit_nr) ino);
+			devwrite(inoaddr(ino), nullbuf, INODE_SIZE);
+			memset((void *) dp, 0, sizeof(dir_struct));
+			ftop = ftop->st_next;
+			return(0);
+		}
+	}
+  }
+  ftop = ftop->st_next;
+  return(1);
+}
+
+/* Check the file system tree. */
+void chktree()
+{
+  dir_struct dir;
+
+  nfreeinode = sb.s_ninodes;
+  nfreezone = N_DATA;
+  dir.d_inum = ROOT_INODE;
+  dir.d_name[0] = 0;
+  if (!descendtree(&dir)) fatal("bad root inode");
+  putchar('\n');
+}
+
+/* Print the totals of all the objects found. */
+void printtotal()
+{
+  printf("blocksize = %5d        ", BLOCK_SIZE);
+  printf("zonesize  = %5d\n", ZONE_SIZE);
+  printf("\n");
+  pr("%6u    Regular file%s\n", nregular, "", "s");
+  pr("%6u    Director%s\n", ndirectory, "y", "ies");
+  pr("%6u    Block special file%s\n", nblkspec, "", "s");
+  pr("%6u    Character special file%s\n", ncharspec, "", "s");
+  if (nbadinode != 0) pr("%6u    Bad inode%s\n", nbadinode, "", "s");
+  pr("%6u    Free inode%s\n", nfreeinode, "", "s");
+  pr("%6u    Named pipe%s\n", npipe, "", "s");
+  pr("%6u    Symbolic link%s\n", nsyml, "", "s");
+/* Don't print some fields.
+  printf("\n");
+  pr("%6u    Data zone%s\n",		  ztype[0],	 "",   "s");
+  pr("%6u    Single indirect zone%s\n",	  ztype[1],	 "",   "s");
+  pr("%6u    Double indirect zone%s\n",	  ztype[2],	 "",   "s");
+*/
+  pr("%6u    Free zone%s\n", nfreezone, "", "s");
+}
+
+/* Check the device which name is given by `f'.  The inodes listed by `clist'
+ * should be listed separately, and the inodes listed by `ilist' and the zones
+ * listed by `zlist' should be watched for while checking the file system.
+ */
+
+void chkdev(f, clist, ilist, zlist)
+char *f, **clist, **ilist, **zlist;
+{
+  if (automatic) repair = 1;
+  device = f;
+  initvars();
+
+  devopen();
+
+  getsuper();
+  chksuper();
+
+  lsi(clist);
+
+  getbitmaps();
+
+  fillbitmap(spec_imap, (bit_nr) 1, (bit_nr) sb.s_ninodes + 1, ilist);
+  fillbitmap(spec_zmap, (bit_nr) FIRST, (bit_nr) sb.s_nzones, zlist);
+
+  getcount();
+  chktree();
+  chkmap(zmap, spec_zmap, (bit_nr) FIRST - 1, BLK_ZMAP, N_ZMAP, "zone");
+  chkcount();
+  chkmap(imap, spec_imap, (bit_nr) 0, BLK_IMAP, N_IMAP, "inode");
+  chkilist();
+  printtotal();
+
+  putbitmaps();
+  freecount();
+  devclose();
+
+  if (changed) printf("----- FILE SYSTEM HAS BEEN MODIFIED -----\n\n");
+}
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  register char **clist = 0, **ilist = 0, **zlist = 0;
+
+  register devgiven = 0;
+  register char *arg;
+
+  if ((1 << BITSHIFT) != 8 * sizeof(bitchunk_t)) {
+	printf("Fsck was compiled with the wrong BITSHIFT!\n");
+	exit(1);
+  }
+
+  sync();
+  prog = *argv++;
+  while ((arg = *argv++) != 0)
+	if (arg[0] == '-' && arg[1] != 0 && arg[2] == 0) switch (arg[1]) {
+		    case 'a':	automatic ^= 1;	break;
+		    case 'c':
+			clist = getlist(&argv, "inode");
+			break;
+		    case 'i':
+			ilist = getlist(&argv, "inode");
+			break;
+		    case 'z':
+			zlist = getlist(&argv, "zone");
+			break;
+		    case 'r':	repair ^= 1;	break;
+		    case 'l':	listing ^= 1;	break;
+		    case 's':	listsuper ^= 1;	break;
+		    default:
+			printf("%s: unknown flag '%s'\n", prog, arg);
+		}
+	else {
+		chkdev(arg, clist, ilist, zlist);
+		clist = 0;
+		ilist = 0;
+		zlist = 0;
+		devgiven = 1;
+	}
+  if (!devgiven) {
+	printf("Usage: fsck1 [-acilrsz] file\n");
+	exit(1);
+  }
+  return(0);
+}
Index: /trunk/minix/commands/simple/getty.c
===================================================================
--- /trunk/minix/commands/simple/getty.c	(revision 9)
+++ /trunk/minix/commands/simple/getty.c	(revision 9)
@@ -0,0 +1,201 @@
+/* getty - get tty speed			Author: Fred van Kempen */
+
+/*
+ * GETTY  -     Initialize and serve a login-terminal for INIT.
+ *		Also, select the correct speed. The STTY() code
+ *		was taken from stty(1).c; which was written by
+ *		Andrew S. Tanenbaum.
+ *
+ * Usage:	getty [-c filename] [-h] [-k] [-t] line [speed]
+ *
+ * Version:	3.4	02/17/90
+ *
+ * Author:	F. van Kempen, MicroWalt Corporation
+ *
+ * Modifications:
+ *		All the good stuff removed to get a minimal getty, because
+ *		many modems don't like all that fancy speed detection stuff.
+ *		03/03/91	Kees J. Bot (kjb@cs.vu.nl)
+ *
+ *		Uname(), termios.  More nonsense removed.  (The result has
+ *		only 10% of the original functionality, but a 10x chance of
+ *		working.)
+ *		12/12/92	Kees J. Bot
+ *
+ *		Customizable login banner.
+ *		11/13/95	Kees J. Bot
+ *
+ *		Suspend/resume signals removed.
+ *		2001-04-04	Kees J. Bot
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/utsname.h>
+
+char LOGIN[] =		"/usr/bin/login";
+char SHELL[] =		"/bin/sh";
+
+char *tty_name;			/* name of the line */
+
+/* Crude indication of a tty being physically secure: */
+#define securetty(dev)		((unsigned) ((dev) - 0x0400) < (unsigned) 8)
+
+void std_out(char *s)
+{
+  write(1, s, strlen(s));
+}
+
+/* Read one character from stdin.
+ */
+int readch(void)
+{
+  int st;
+  char ch1;
+
+  /* read character from TTY */
+  st = read(0, &ch1, 1);
+  if (st == 0) {
+	std_out("\n");
+	exit(0);
+  }
+  if (st < 0) {
+	std_out("getty: ");
+	std_out(tty_name);
+	std_out(": read error\n");
+	exit(1);
+  }
+  return(ch1 & 0xFF);
+}
+
+
+/* Handle the process of a GETTY.
+ */
+void do_getty(char *name, size_t len, char **args, char *ttyname)
+{
+  register char *np, *s, *s0;
+  int ch;
+  struct utsname utsname;
+  char **banner, *t;
+  static char *def_banner[] = { "%s  Release %r Version %v  (%t)\n\n%n login: ", 0 };
+
+  /* Clean up tty name. */
+  if((t = strrchr(ttyname, '/'))) ttyname = t + 1;
+
+  /* Default banner? */
+  if (args[0] == NULL) args = def_banner;
+
+  /* Display prompt. */
+  ch = ' ';
+  *name = '\0';
+  while (ch != '\n') {
+	/* Get data about this machine. */
+	uname(&utsname);
+
+	/* Print the banner. */
+	for (banner = args; *banner != NULL; banner++) {
+		std_out(banner == args ? "\n" : " ");
+		s0 = *banner;
+		for (s = *banner; *s != 0; s++) {
+			if (*s == '\\') {
+				write(1, s0, s-s0);
+				s0 = s+2;
+				switch (*++s) {
+				case 'n':  std_out("\n"); break;
+				case 's':  std_out(" "); break;
+				case 't':  std_out("\t"); break;
+				case 0:	   goto leave;
+				default:   s0 = s;
+				}
+			} else
+			if (*s == '%') {
+				write(1, s0, s-s0);
+				s0 = s+2;
+				switch (*++s) {
+				case 's':  std_out(utsname.sysname); break;
+				case 'n':  std_out(utsname.nodename); break;
+				case 'r':  std_out(utsname.release); break;
+				case 'v':  std_out(utsname.version); break;
+				case 'm':  std_out(utsname.machine); break;
+				case 'p':  std_out(utsname.arch); break;
+				case 't':  std_out(ttyname); break;
+#if __minix_vmd
+				case 'k':  std_out(utsname.kernel); break;
+				case 'h':  std_out(utsname.hostname); break;
+				case 'b':  std_out(utsname.bus); break;
+#endif
+				case 0:	   goto leave;
+				default:   s0 = s-1;
+				}
+			}
+		}
+	    leave:
+		write(1, s0, s-s0);
+	}
+
+	np = name;
+	while ((ch = readch()) != '\n') {
+		if (np < name + len) *np++ = ch;
+	}
+	*np = '\0';
+	if (*name == '\0') ch = ' ';	/* blank line typed! */
+  }
+}
+
+
+/* Execute the login(1) command with the current
+ * username as its argument. It will reply to the
+ * calling user by typing "Password: "...
+ */
+void do_login(char *name)
+{ 
+  struct stat st;
+
+  execl(LOGIN, LOGIN, name, (char *) NULL);
+  /* Failed to exec login.  Impossible, but true.  Try a shell, but only if
+   * the terminal is more or less secure, because it will be a root shell.
+   */
+  std_out("getty: can't exec ");
+  std_out(LOGIN);
+  std_out("\n");
+  if (fstat(0, &st) == 0 && S_ISCHR(st.st_mode) && securetty(st.st_rdev)) {
+	execl(SHELL, SHELL, (char *) NULL);
+  }
+}
+
+
+int main(int argc, char **argv)
+{
+  register char *s;
+  char name[30];
+  struct sigaction sa;
+
+  /* Don't let QUIT dump core. */
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = 0;
+  sa.sa_handler = exit;
+  sigaction(SIGQUIT, &sa, NULL);
+
+  tty_name = ttyname(0);
+  if (tty_name == NULL) {
+	std_out("getty: tty name unknown\n");
+	pause();
+	return(1);
+  }
+
+  chown(tty_name, 0, 0);	/* set owner of TTY to root */
+  chmod(tty_name, 0600);	/* mode to max secure */
+
+  do_getty(name, sizeof(name), argv+1, tty_name);	/* handle getty() */
+  name[29] = '\0';		/* make sure the name fits! */
+
+  do_login(name);		/* and call login(1) if OK */
+
+  return(1);			/* never executed */
+}
Index: /trunk/minix/commands/simple/gomoku.c
===================================================================
--- /trunk/minix/commands/simple/gomoku.c	(revision 9)
+++ /trunk/minix/commands/simple/gomoku.c	(revision 9)
@@ -0,0 +1,739 @@
+/* gomoku - 5 in a row game		Author: ? */
+
+/* This program plays a very old Japanese game called GO-MOKU,
+   perhaps better known as  5-in-line.   The game is played on
+   a board with 19 x 19 squares, and the object of the game is
+   to get 5 stones in a row.
+*/
+
+#include <sys/types.h>
+#include <curses.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Size of the board */
+#define SIZE 19
+
+/* Importance of attack (1..16) */
+#define AttackFactor 4
+
+/* Value of having 0, 1,2,3,4 or 5 pieces in line */
+int Weight[7] = {0, 0, 4, 20, 100, 500, 0};
+
+#define Null 0
+#define Horiz 1
+#define DownLeft 2
+#define DownRight 3
+#define Vert 4
+
+/* The two players */
+#define Empty 0
+#define Cross 1
+#define Nought 2
+
+char PieceChar[Nought + 1] = {' ', 'X', '0'};
+
+int Board[SIZE + 1][SIZE + 1];/* The board */
+int Player;			/* The player whose move is next */
+int TotalLines;			/* The number of Empty lines left */
+int GameWon;			/* Set if one of the players has won */
+
+int Line[4][SIZE + 1][SIZE + 1][Nought + 1];
+
+/* Value of each square for each player */
+int Value[SIZE + 1][SIZE + 1][Nought + 1];
+
+int X, Y;			/* Move coordinates */
+char Command;			/* Command from keyboard */
+int AutoPlay = FALSE;		/* The program plays against itself */
+
+_PROTOTYPE(void Initialize, (void));
+_PROTOTYPE(int Abort, (char *s));
+_PROTOTYPE(void WriteLetters, (void));
+_PROTOTYPE(void WriteLine, (int j, int *s));
+_PROTOTYPE(void WriteBoard, (int N, int *Top, int *Middle, int *Bottom));
+_PROTOTYPE(void SetUpScreen, (void));
+_PROTOTYPE(void GotoSquare, (int x, int y));
+_PROTOTYPE(void PrintMove, (int Piece, int X, int Y));
+_PROTOTYPE(void ClearMove, (void));
+_PROTOTYPE(void PrintMsg, (char *Str));
+_PROTOTYPE(void ClearMsg, (void));
+_PROTOTYPE(void WriteCommand, (char *S));
+_PROTOTYPE(void ResetGame, (int FirstGame));
+_PROTOTYPE(int OpponentColor, (int Player));
+_PROTOTYPE(void BlinkRow, (int X, int Y, int Dx, int Dy, int Piece));
+_PROTOTYPE(void BlinkWinner, (int Piece, int X, int Y, int WinningLine));
+_PROTOTYPE(int Random, (int x));
+_PROTOTYPE(void Add, (int *Num));
+_PROTOTYPE(void Update, (int Lin[], int Valu[], int Opponent));
+_PROTOTYPE(void MakeMove, (int X, int Y));
+_PROTOTYPE(int GameOver, (void));
+_PROTOTYPE(void FindMove, (int *X, int *Y));
+_PROTOTYPE(char GetChar, (void));
+_PROTOTYPE(void ReadCommand, (int X, int Y, char *Command));
+_PROTOTYPE(void InterpretCommand, (int Command));
+_PROTOTYPE(void PlayerMove, (void));
+_PROTOTYPE(void ProgramMove, (void));
+_PROTOTYPE(int main, (void));
+
+/* Set terminal to raw mode. */
+void Initialize()
+{
+  srand(getpid() + 13);		/* Initialize the random seed with our pid */
+  initscr();
+  raw();
+  noecho();
+  clear();
+}
+
+/* Reset terminal and exit from the program. */
+int Abort(s)
+char *s;
+{
+  move(LINES - 1, 0);
+  refresh();
+  endwin();
+  exit(0);
+}
+
+/* Set up the screen ----------------------------------------------- */
+
+/* Write the letters */
+void WriteLetters()
+{
+  int i;
+
+  addch(' ');
+  addch(' ');
+  for (i = 1; i <= SIZE; i++) printw(" %c", 'A' + i - 1);
+  addch('\n');
+}
+
+/* Write one line of the board */
+void WriteLine(j, s)
+int j;
+int *s;
+{
+  int i;
+
+  printw("%2d ", j);
+  addch(s[0]);
+  for (i = 2; i <= SIZE - 1; i++) {
+	addch(s[1]);
+	addch(s[2]);
+  }
+  addch(s[1]);
+  addch(s[3]);
+  printw(" %-2d\n", j);
+}
+
+/* Print the Empty board and the border */
+void WriteBoard(N, Top, Middle, Bottom)
+int N;
+int *Top, *Middle, *Bottom;
+{
+  int j;
+
+  move(1, 0);
+  WriteLetters();
+  WriteLine(N, Top);
+  for (j = N - 1; j >= 2; j--) WriteLine(j, Middle);
+  WriteLine(1, Bottom);
+  WriteLetters();
+}
+
+/* Sets up the screen with an Empty board */
+void SetUpScreen()
+{
+  int top[4], middle[4], bottom[4];
+
+  top[0] = ACS_ULCORNER;
+  top[1] = ACS_HLINE;
+  top[2] = ACS_TTEE;
+  top[3] = ACS_URCORNER;
+
+  middle[0] = ACS_LTEE;
+  middle[1] = ACS_HLINE;
+  middle[2] = ACS_PLUS;
+  middle[3] = ACS_RTEE;
+
+  bottom[0] = ACS_LLCORNER;
+  bottom[1] = ACS_HLINE;
+  bottom[2] = ACS_BTEE;
+  bottom[3] = ACS_LRCORNER;
+
+  WriteBoard(SIZE, top, middle, bottom);
+}
+
+/* Show moves ----------------------------------------------- */
+
+void GotoSquare(x, y)
+int x, y;
+{
+  move(SIZE + 2 - y, 1 + x * 2);
+}
+
+/* Prints a move */
+void PrintMove(Piece, X, Y)
+int Piece;
+int X, Y;
+{
+  move(22, 49);
+  printw("%c %c %d", PieceChar[Piece], 'A' + X - 1, Y);
+  clrtoeol();
+  GotoSquare(X, Y);
+  addch(PieceChar[Piece]);
+  GotoSquare(X, Y);
+  refresh();
+}
+
+/* Clears the line where a move is displayed */
+void ClearMove()
+{
+  move(22, 49);
+  clrtoeol();
+}
+
+/* Message handling ---------------------------------------------- */
+
+/* Prints a message */
+void PrintMsg(Str)
+char *Str;
+{
+  mvprintw(23, 1, "%s", Str);
+}
+
+/* Clears the message about the winner */
+void ClearMsg()
+{
+  move(23, 1);
+  clrtoeol();
+}
+
+/* Highlights the first letter of S */
+void WriteCommand(S)
+char *S;
+{
+  standout();
+  addch(*S);
+  standend();
+  printw("%s", S + 1);
+}
+
+/* Display the board ----------------------------------------------- */
+
+/* Resets global variables to start a new game */
+void ResetGame(FirstGame)
+int FirstGame;
+{
+  int I, J;
+  int C, D;
+
+  SetUpScreen();
+  if (FirstGame) {
+	move(1, 49);
+	addstr("G O M O K U");
+	move(3, 49);
+	WriteCommand("Newgame    ");
+	WriteCommand("Quit ");
+	move(5, 49);
+	WriteCommand("Auto");
+	move(7, 49);
+	WriteCommand("Play");
+	move(9, 49);
+	WriteCommand("Hint");
+	move(14, 60);
+	WriteCommand("Left, ");
+	WriteCommand("Right, ");
+	move(16, 60);
+	WriteCommand("Up, ");
+	WriteCommand("Down");
+	move(18, 60);
+	standout();
+	addstr("SPACE");
+	move(20, 49);
+	WriteCommand(" NOTE: Use Num Lock & arrows");
+	standend();
+	mvaddstr(14, 49, "7  8  9");
+	mvaddch(15, 52, ACS_UARROW);
+	mvaddch(16, 49, '4');
+	addch(ACS_LARROW);
+	mvaddch(16, 54, ACS_RARROW);
+	addch('6');
+	mvaddch(17, 52, ACS_DARROW);
+	mvaddstr(18, 49, "1  2  3");
+	FirstGame = FALSE;
+  } else {
+	ClearMsg();
+	ClearMove();
+  }
+
+  /* Clear tables */
+  for (I = 1; I <= SIZE; I++) for (J = 1; J <= SIZE; J++) {
+		Board[I][J] = Empty;
+		for (C = Cross; C <= Nought; C++) {
+			Value[I][J][C] = 0;
+			for (D = 0; D <= 3; D++) Line[D][I][J][C] = 0;
+		}
+	}
+
+  /* Cross starts */
+  Player = Cross;
+  /* Total number of lines */
+  TotalLines = 2 * 2 * (SIZE * (SIZE - 4) + (SIZE - 4) * (SIZE - 4));
+  GameWon = FALSE;
+}
+
+int OpponentColor(Player)
+int Player;
+{
+  if (Player == Cross)
+	return Nought;
+  else
+	return Cross;
+}
+
+/* Blink the row of 5 stones */
+void BlinkRow(X, Y, Dx, Dy, Piece)
+int X, Y, Dx, Dy, Piece;
+{
+  int I;
+
+  attron(A_BLINK);
+  for (I = 1; I <= 5; I++) {
+	GotoSquare(X, Y);
+	addch(PieceChar[Piece]);
+	X = X - Dx;
+	Y = Y - Dy;
+  }
+  attroff(A_BLINK);
+}
+
+/* Prints the 5 winning stones in blinking color */
+void BlinkWinner(Piece, X, Y, WinningLine)
+int Piece, X, Y, WinningLine;
+{
+  /* Used to store the position of the winning move */
+  int XHold, YHold;
+  /* Change in X and Y */
+  int Dx, Dy;
+
+  /* Display winning move */
+  PrintMove(Piece, X, Y);
+  /* Preserve winning position */
+  XHold = X;
+  YHold = Y;
+  switch (WinningLine) {
+      case Horiz:
+	{
+		Dx = 1;
+		Dy = 0;
+		break;
+	}
+
+      case DownLeft:
+	{
+		Dx = 1;
+		Dy = 1;
+		break;
+	}
+
+      case Vert:
+	{
+		Dx = 0;
+		Dy = 1;
+		break;
+	}
+
+      case DownRight:
+	{
+		Dx = -1;
+		Dy = 1;
+		break;
+	}
+  }
+
+  /* Go to topmost, leftmost */
+  while (Board[X + Dx][Y + Dy] != Empty && Board[X + Dx][Y + Dy] == Piece) {
+	X = X + Dx;
+	Y = Y + Dy;
+  }
+  BlinkRow(X, Y, Dx, Dy, Piece);
+  /* Restore winning position */
+  X = XHold;
+  Y = YHold;
+  /* Go back to winning square */
+  GotoSquare(X, Y);
+}
+
+/* Functions for playing a game -------------------------------- */
+
+int Random(x)
+int x;
+{
+  return((rand() / 19) % x);
+}
+
+/* Adds one to the number of pieces in a line */
+void Add(Num)
+int *Num;
+{
+  /* Adds one to the number.     */
+  *Num = *Num + 1;
+  /* If it is the first piece in the line, then the opponent cannot use
+   * it any more.  */
+  if (*Num == 1) TotalLines = TotalLines - 1;
+  /* The game is won if there are 5 in line. */
+  if (*Num == 5) GameWon = TRUE;
+}
+
+/* Updates the value of a square for each player, taking into
+   account that player has placed an extra piece in the square.
+   The value of a square in a usable line is Weight[Lin[Player]+1]
+   where Lin[Player] is the number of pieces already placed
+in the line */
+void Update(Lin, Valu, Opponent)
+int Lin[];
+int Valu[];
+int Opponent;
+{
+  /* If the opponent has no pieces in the line, then simply update the
+   * value for player */
+  if (Lin[Opponent] == 0)
+	Valu[Player] += Weight[Lin[Player] + 1] - Weight[Lin[Player]];
+  else
+	/* If it is the first piece in the line, then the line is
+	 * spoiled for the opponent */
+  if (Lin[Player] == 1) Valu[Opponent] -= Weight[Lin[Opponent] + 1];
+}
+
+/* Performs the move X,Y for player, and updates the global variables
+(Board, Line, Value, Player, GameWon, TotalLines and the screen) */
+void MakeMove(X, Y)
+int X, Y;
+{
+  int Opponent;
+  int X1, Y1;
+  int K, L, WinningLine;
+
+  WinningLine = Null;
+  Opponent = OpponentColor(Player);
+  GameWon = FALSE;
+
+  /* Each square of the board is part of 20 different lines. The adds
+   * one to the number of pieces in each of these lines. Then it
+   * updates the value for each of the 5 squares in each of the 20
+   * lines. Finally Board is updated, and the move is printed on the
+   * screen. */
+
+  /* Horizontal lines, from left to right */
+  for (K = 0; K <= 4; K++) {
+	X1 = X - K;		/* Calculate starting point */
+	Y1 = Y;
+	if ((1 <= X1) && (X1 <= SIZE - 4)) {	/* Check starting point */
+		Add(&Line[0][X1][Y1][Player]);	/* Add one to line */
+		if (GameWon && (WinningLine == Null))	/* Save winning line */
+			WinningLine = Horiz;
+		for (L = 0; L <= 4; L++)	/* Update value for the
+						 * 5 squares in the line */
+			Update(Line[0][X1][Y1], Value[X1 + L][Y1], Opponent);
+	}
+  }
+
+  for (K = 0; K <= 4; K++) {	/* Diagonal lines, from lower left to
+				 * upper right */
+	X1 = X - K;
+	Y1 = Y - K;
+	if ((1 <= X1) && (X1 <= SIZE - 4) &&
+	    (1 <= Y1) && (Y1 <= SIZE - 4)) {
+		Add(&Line[1][X1][Y1][Player]);
+		if (GameWon && (WinningLine == Null))	/* Save winning line */
+			WinningLine = DownLeft;
+		for (L = 0; L <= 4; L++)
+			Update(Line[1][X1][Y1], Value[X1 + L][Y1 + L], Opponent);
+	}
+  }				/* for */
+
+  for (K = 0; K <= 4; K++) {	/* Diagonal lines, down right to upper left */
+	X1 = X + K;
+	Y1 = Y - K;
+	if ((5 <= X1) && (X1 <= SIZE) &&
+	    (1 <= Y1) && (Y1 <= SIZE - 4)) {
+		Add(&Line[3][X1][Y1][Player]);
+		if (GameWon && (WinningLine == Null))	/* Save winning line */
+			WinningLine = DownRight;
+		for (L = 0; L <= 4; L++)
+			Update(Line[3][X1][Y1], Value[X1 - L][Y1 + L], Opponent);
+	}
+  }				/* for */
+
+  for (K = 0; K <= 4; K++) {	/* Vertical lines, from down to up */
+	X1 = X;
+	Y1 = Y - K;
+	if ((1 <= Y1) && (Y1 <= SIZE - 4)) {
+		Add(&Line[2][X1][Y1][Player]);
+		if (GameWon && (WinningLine == Null))	/* Save winning line */
+			WinningLine = Vert;
+		for (L = 0; L <= 4; L++)
+			Update(Line[2][X1][Y1], Value[X1][Y1 + L], Opponent);
+	}
+  }
+
+  Board[X][Y] = Player;		/* Place piece in board */
+  if (GameWon)
+	BlinkWinner(Player, X, Y, WinningLine);
+  else
+	PrintMove(Player, X, Y);/* Print move on screen */
+  Player = Opponent;		/* The opponent is next to move */
+}
+
+int GameOver()
+/* A game is over if one of the players have
+won, or if there are no more Empty lines */
+{
+  return(GameWon || (TotalLines <= 0));
+}
+
+/* Finds a move X,Y for player, simply by picking the one with the
+highest value */
+void FindMove(X, Y)
+int *X, *Y;
+{
+  int Opponent;
+  int I, J;
+  int Max, Valu;
+
+  Opponent = OpponentColor(Player);
+  Max = -10000;
+  /* If no square has a high value then pick the one in the middle */
+  *X = (SIZE + 1) / 2;
+  *Y = (SIZE + 1) / 2;
+  if (Board[*X][*Y] == Empty) Max = 4;
+  /* The evaluation for a square is simply the value of the square for
+   * the player (attack points) plus the value for the opponent
+   * (defense points). Attack is more important than defense, since it
+   * is better to get 5 in line yourself than to prevent the op- ponent
+   * from getting it. */
+
+  /* For all Empty squares */
+  for (I = 1; I <= SIZE; I++) for (J = 1; J <= SIZE; J++)
+		if (Board[I][J] == Empty) {
+			/* Calculate evaluation */
+			Valu = Value[I][J][Player] * (16 + AttackFactor) / 16 + Value[I][J][Opponent] + Random(4);
+			/* Pick move with highest value */
+			if (Valu > Max) {
+				*X = I;
+				*Y = J;
+				Max = Valu;
+			}
+		}
+}
+
+char GetChar()
+/* Get a character from the keyboard */
+{
+  int c;
+
+  c = getch();
+  if (c < 0) abort();
+  if (c == '\033') {	/* arrow key */
+	if ((c = getch()) == '[') {
+		c = getch();
+		switch (c) {
+		case 'A': c = 'U'; break;
+		case 'B': c = 'D'; break;
+		case 'C': c = 'R'; break;
+		case 'D': c = 'L'; break;
+		default:
+			c = '?';
+			break;
+		}
+	}
+	else
+		c = '?';
+  }
+  if (islower(c))
+	return toupper(c);
+  else
+	return c;
+}
+
+/* Reads in a valid command character */
+void ReadCommand(X, Y, Command)
+int X, Y;
+char *Command;
+{
+  int ValidCommand;
+
+  do {
+	ValidCommand = TRUE;
+	GotoSquare(X, Y);	/* Goto square */
+	refresh();
+	*Command = GetChar();	/* Read from keyboard */
+	switch (*Command) {
+	    case '\n':		/* '\n', '\r' or space means place a */
+	    case '\r':
+	    case ' ':
+		*Command = 'E';
+		break;		/* stone at the cursor position  */
+
+	    case 'L':
+	    case 'R':
+	    case 'U':
+	    case 'D':
+	    case '7':
+	    case '9':
+	    case '1':
+	    case '3':
+	    case 'N':
+	    case 'Q':
+	    case 'A':
+	    case 'P':
+	    case 'H':
+		break;
+
+	    case '8':	*Command = 'U';	break;
+	    case '2':	*Command = 'D';	break;
+	    case '4':	*Command = 'L';	break;
+	    case '6':	*Command = 'R';	break;
+	    default:
+		{
+			if (GameOver())
+				*Command = 'P';
+			else
+				ValidCommand = FALSE;
+			break;
+		}
+	}
+  } while (!ValidCommand);
+}
+
+void InterpretCommand(Command)
+char Command;
+{
+  int Temp;
+
+  switch (Command) {
+      case 'N':{		/* Start new game */
+		ResetGame(FALSE);	/* ResetGame but only redraw
+					 * the board */
+		X = (SIZE + 1) / 2;
+		Y = X;
+		break;
+	}
+      case 'H':
+	FindMove(&X, &Y);
+	break;			/* Give the user a hint */
+      case 'L':
+	X = (X + SIZE - 2) % SIZE + 1;
+	break;			/* Left  */
+      case 'R':
+	X = X % SIZE + 1;
+	break;			/* Right */
+      case 'D':
+	Y = (Y + SIZE - 2) % SIZE + 1;
+	break;			/* Down  */
+      case 'U':
+	Y = Y % SIZE + 1;
+	break;			/* Up    */
+      case '7':{
+		if ((X == 1) || (Y == SIZE)) {	/* Move diagonally    *//* t
+						 * owards upper left */
+			Temp = X;
+			X = Y;
+			Y = Temp;
+		} else {
+			X = X - 1;
+			Y = Y + 1;
+		}
+		break;
+	}
+      case '9':{		/* Move diagonally    */
+		if (X == SIZE) {/* toward upper right */
+			X = (SIZE - Y) + 1;
+			Y = 1;
+		} else if (Y == SIZE) {
+			Y = (SIZE - X) + 1;
+			X = 1;
+		} else {
+			X = X + 1;
+			Y = Y + 1;
+		}
+		break;
+	}
+      case '1':{		/* Move diagonally   */
+		if (Y == 1) {	/* toward lower left */
+			Y = (SIZE - X) + 1;
+			X = SIZE;
+		} else if (X == 1) {
+			X = (SIZE - Y) + 1;
+			Y = SIZE;
+		} else {
+			X = X - 1;
+			Y = Y - 1;
+		}
+		break;
+	}
+      case '3':{		/* Move diagonally    */
+		if ((X == SIZE) || (Y == 1)) {	/* toward lower right */
+			Temp = X;
+			X = Y;
+			Y = Temp;
+		} else {
+			X = X + 1;
+			Y = Y - 1;
+		}
+		break;
+	}
+      case 'A':
+	AutoPlay = TRUE;
+	break;			/* Auto play mode */
+  }				/* case */
+}				/* InterpretCommand */
+
+void PlayerMove()
+/* Enter and make a move */
+{
+  if (Board[X][Y] == Empty) {
+	MakeMove(X, Y);
+	if (GameWon) PrintMsg("Congratulations, You won!");
+	Command = 'P';
+  }
+  refresh();
+}				/* PlayerMove */
+
+void ProgramMove()
+/* Find and perform programs move */
+{
+  do {
+	if (GameOver()) {
+		AutoPlay = FALSE;
+		if ((Command != 'Q') && (!GameWon)) PrintMsg("Tie game!");
+	} else {
+		FindMove(&X, &Y);
+		MakeMove(X, Y);
+		if (GameWon) PrintMsg("I won!");
+	}
+	refresh();
+  } while (AutoPlay);
+}
+
+int main()
+{
+  Initialize();
+  ResetGame(TRUE);		/* ResetGame and draw the entire screen */
+  refresh();
+  X = (SIZE + 1) / 2;		/* Set starting position to */
+  Y = X;			/* the middle of the board  */
+  do {
+	ReadCommand(X, Y, &Command);
+	if (GameOver())
+		if (Command != 'Q') Command = 'N';
+	InterpretCommand(Command);
+	if (Command == 'E') PlayerMove();
+	if (Command == 'P' || Command == 'A') ProgramMove();
+  } while (Command != 'Q');
+  Abort("Good bye!");
+  return(0);
+}
Index: /trunk/minix/commands/simple/grep.c
===================================================================
--- /trunk/minix/commands/simple/grep.c	(revision 9)
+++ /trunk/minix/commands/simple/grep.c	(revision 9)
@@ -0,0 +1,379 @@
+/* grep - search a file for a pattern	Author: Norbert Schlenker */
+
+/* Norbert Schlenker (nfs@princeton.edu)  1990-02-08
+ * Released into the public domain.
+ *
+ * Grep searches files for lines containing a pattern, as specified by
+ * a regular expression, and prints those lines.  It is invoked by:
+ *	grep [flags] [pattern] [file ...]
+ *
+ * Flags:
+ *	-e pattern	useful when pattern begins with '-'
+ *	-c		print a count of lines matched
+ *	-i		ignore case
+ *	-l		prints just file names, no lines (quietly overrides -n)
+ *	-n		printed lines are preceded by relative line numbers
+ *	-s		prints errors only (quietly overrides -l and -n)
+ *	-v		prints lines which don't contain the pattern
+ *
+ * Semantic note:
+ * 	If both -l and -v are specified, grep prints the names of those
+ *	files which do not contain the pattern *anywhere*.
+ *
+ * Exit:
+ *	Grep sets an exit status which can be tested by the caller.
+ *	Note that these settings are not necessarily compatible with
+ *	any other version of grep, especially when -v is specified.
+ *	Possible status values are:
+ *	  0	if any matches are found
+ *	  1	if no matches are found
+ *	  2	if syntax errors are detected or any file cannot be opened
+ */
+
+
+/* External interfaces */
+#include <sys/types.h>
+#include <regexp.h>		/* Thanks to Henry Spencer */
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+/* Internal constants */
+#define MATCH		0	/* exit code: some match somewhere */
+#define NO_MATCH	1	/* exit code: no match on any line */
+#define FAILURE		2	/* exit code: syntax error or bad file name */
+
+/* Macros */
+#define SET_FLAG(c)	(flags[(c)-'a'] = 1)
+#define FLAG(c)		(flags[(c)-'a'] != 0)
+
+#define uppercase(c)	(((unsigned) ((c) - 'A')) <= ('Z' - 'A'))
+#define downcase(c)	((c) - 'A' + 'a')
+
+/* Private storage */
+static char *program;		/* program name */
+static char flags[26];		/* invocation flags */
+static regexp *expression;	/* compiled search pattern */
+static const char *rerr;              /* error message */
+
+/* External variables. */
+extern int optind;
+extern char *optarg;
+
+/* Internal interfaces */
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(static int match, (FILE *input, char *label, char *filename));
+_PROTOTYPE(static char *get_line, (FILE *input));
+_PROTOTYPE(static char *map_nocase, (char *line));
+_PROTOTYPE(void regerror , (const char *s ) );
+_PROTOTYPE(static void tov8, (char *v8pattern, char *pattern));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int opt;			/* option letter from getopt() */
+  int egrep=0;			/* using extended regexp operators */
+  char *pattern;		/* search pattern */
+  char *v8pattern;		/* v8 regexp search pattern */
+  int exit_status = NO_MATCH;	/* exit status for our caller */
+  int file_status;		/* status of search in one file */
+  FILE *input;			/* input file (if not stdin) */
+
+  program = argv[0];
+  if (strlen(program)>=5 && strcmp(program+strlen(program)-5,"egrep")==0) egrep=1;
+  memset(flags, 0, sizeof(flags));
+  pattern = NULL;
+
+/* Process any command line flags. */
+  while ((opt = getopt(argc, argv, "e:cilnsv")) != EOF) {
+	if (opt == '?')
+		exit_status = FAILURE;
+	else
+	if (opt == 'e')
+		pattern = optarg;
+	else
+		SET_FLAG(opt);
+  }
+
+/* Detect a few problems. */
+  if ((exit_status == FAILURE) || (optind == argc && pattern == NULL)) {
+	fprintf(stderr,"Usage: %s [-cilnsv] [-e] expression [file ...]\n",program);
+	exit(FAILURE);
+  }
+
+/* Ensure we have a usable pattern. */
+  if (pattern == NULL)
+	pattern = argv[optind++];
+
+/* Map pattern to lowercase if -i given. */
+  if (FLAG('i')) {
+	char *p;
+	for (p = pattern; *p != '\0'; p++) {
+		if (uppercase(*p))
+			*p = downcase(*p);
+	}
+  }
+
+  if (!egrep) {
+	  if ((v8pattern=malloc(2*strlen(pattern)))==(char*)0) {
+		fprintf(stderr,"%s: out of memory\n");
+		exit(FAILURE);
+	  }
+	  tov8(v8pattern,pattern);
+  } else v8pattern=pattern;
+
+  rerr=(char*)0;
+  if ((expression = regcomp(v8pattern)) == NULL) {
+	fprintf(stderr,"%s: bad regular expression",program);
+	if (rerr) fprintf(stderr," (%s)",rerr);
+	fprintf(stderr,"\n");
+	exit(FAILURE);
+  }
+
+/* Process the files appropriately. */
+  if (optind == argc) {		/* no file names - find pattern in stdin */
+	exit_status = match(stdin, (char *) NULL, "<stdin>");
+  }
+  else 
+  if (optind + 1 == argc) {	/* one file name - find pattern in it */
+	if (strcmp(argv[optind], "-") == 0) {
+		exit_status = match(stdin, (char *) NULL, "-");
+	} else {
+		if ((input = fopen(argv[optind], "r")) == NULL) {
+			fprintf(stderr, "%s: couldn't open %s\n",
+							program, argv[optind]);
+			exit_status = FAILURE;
+		}
+		else {
+			exit_status = match(input, (char *) NULL, argv[optind]);
+		}
+	}
+  }
+  else
+  while (optind < argc) {	/* lots of file names - find pattern in all */
+	if (strcmp(argv[optind], "-") == 0) {
+		file_status = match(stdin, "-", "-");
+	} else {
+		if ((input = fopen(argv[optind], "r")) == NULL) {
+			fprintf(stderr, "%s: couldn't open %s\n",
+							program, argv[optind]);
+			exit_status = FAILURE;
+		} else {
+			file_status = match(input, argv[optind], argv[optind]);
+			fclose(input);
+		}
+	}
+	if (exit_status != FAILURE)
+		exit_status &= file_status;
+	++optind;
+  }
+  return(exit_status);
+}
+
+
+/* match - matches the lines of a file with the regular expression.
+ * To improve performance when either -s or -l is specified, this
+ * function handles those cases specially.
+ */
+
+static int match(input, label, filename)
+FILE *input;
+char *label;
+char *filename;
+{
+  char *line, *testline;	/* pointers to input line */
+  long int lineno = 0;		/* line number */
+  long int matchcount = 0;	/* lines matched */
+  int status = NO_MATCH;	/* summary of what was found in this file */
+
+  if (FLAG('s') || FLAG('l')) {
+	while ((line = get_line(input)) != NULL) {
+		testline = FLAG('i') ? map_nocase(line) : line;
+		if (regexec(expression, testline, 1)) {
+			status = MATCH;
+			break;
+		}
+	}
+	if (FLAG('l'))
+		if ((!FLAG('v') && status == MATCH) ||
+		    ( FLAG('v') && status == NO_MATCH))
+			puts(filename);
+	return status;
+  }
+
+  while ((line = get_line(input)) != NULL) {
+	++lineno;
+	testline = FLAG('i') ? map_nocase(line) : line;
+	if (regexec(expression, testline, 1)) {
+		status = MATCH;
+		if (!FLAG('v')) {
+			if (label != NULL)
+				printf("%s:", label);
+			if (FLAG('n'))
+				printf("%ld:", lineno);
+			if (!FLAG('c')) puts(line);
+			matchcount++;
+		}
+	} else {
+		if (FLAG('v')) {
+			if (label != NULL)
+				printf("%s:", label);
+			if (FLAG('n'))
+				printf("%ld:", lineno);
+			if (!FLAG('c')) puts(line);
+			matchcount++;
+		}
+	}
+  }
+  if (FLAG('c')) printf("%ld\n", matchcount);
+  return status;
+}
+
+
+/* get_line - fetch a line from the input file
+ * This function reads a line from the input file into a dynamically
+ * allocated buffer.  If the line is too long for the current buffer,
+ * attempts will be made to increase its size to accomodate the line.
+ * The trailing newline is stripped before returning to the caller.
+ */
+
+#define FIRST_BUFFER (size_t)256		/* first buffer size */
+
+static char *buf = NULL;	/* input buffer */
+static size_t buf_size = 0;		/* input buffer size */
+
+static char *get_line(input)
+FILE *input;
+{
+  int n;
+  register char *bp;
+  register int c;
+  char *new_buf;
+  size_t new_size;
+
+  if (buf_size == 0) {
+	if ((buf = (char *) malloc(FIRST_BUFFER)) == NULL) {
+		fprintf(stderr,"%s: not enough memory\n",program);
+		exit(FAILURE);
+	}
+	buf_size = FIRST_BUFFER;
+  }
+
+  bp = buf;
+  n = buf_size;
+  while (1) {
+	while (--n > 0 && (c = getc(input)) != EOF) {
+		if (c == '\n') {
+			*bp = '\0';
+			return buf;
+		}
+		*bp++ = c;
+	}
+	if (c == EOF)
+		return (ferror(input) || bp == buf) ? NULL : buf;
+	new_size = buf_size << 1;
+	if ((new_buf = (char *) realloc(buf, new_size)) == NULL) {
+		fprintf(stderr, "%s: line too long - truncated\n", program);
+		while ((c = getc(input)) != EOF && c != '\n') ;
+		*bp = '\0';
+		return buf;
+	} else {
+		bp = new_buf + (buf_size - 1);
+		n = buf_size + 1;
+		buf = new_buf;
+		buf_size = new_size;
+	}
+  }
+}
+
+
+/* map_nocase - map a line down to lowercase letters only.
+ * bad points:	assumes line gotten from get_line.
+ *		there is more than A-Z you say?
+ */
+
+static char *map_nocase(line)
+char *line;
+{
+  static char *mapped=(char*)0;
+  static size_t map_size = 0;
+  char *mp;
+
+  if (map_size < buf_size) {
+	if ((mapped=realloc(mapped,map_size=buf_size)) == NULL) {
+		fprintf(stderr,"%s: not enough memory\n",program);
+		exit(FAILURE);
+	}
+  }
+
+  mp = mapped;
+  do {
+	*mp++ = uppercase(*line) ? downcase(*line) : *line;
+  } while (*line++ != '\0');
+
+  return mapped;
+}
+
+/* In basic regular expressions, the characters ?, +, |, (, and )
+   are taken literally; use the backslashed versions for RE operators.
+   In v8 regular expressions, things are the other way round, so
+   we have to swap those characters and their backslashed versions.
+*/
+static void tov8(char *v8, char *basic)
+{
+  while (*basic) switch (*basic)
+  {
+    case '?':
+    case '+':
+    case '|':
+    case '(':
+    case ')':        
+    {        
+      *v8++='\\';
+      *v8++=*basic++;
+      break;
+    }                    
+    case '\\':
+    {
+      switch (*(basic+1))
+      {
+        case '?':
+        case '+':
+        case '|':
+        case '(': 
+        case ')':
+        {
+          *v8++=*++basic;
+          ++basic;
+          break;
+        }
+        case '\0':
+        {
+          *v8++=*basic++;
+          break;
+        }
+        default:
+        {       
+          *v8++=*basic++;
+          *v8++=*basic++;
+        }                
+      }     
+      break;
+    }       
+    default:
+    {
+      *v8++=*basic++;
+    }                
+  }   
+  *v8++='\0';
+}
+
+/* Regular expression code calls this routine to print errors. */
+
+void regerror(s)
+const char *s;
+{
+  rerr=s;
+}
Index: /trunk/minix/commands/simple/head.c
===================================================================
--- /trunk/minix/commands/simple/head.c	(revision 9)
+++ /trunk/minix/commands/simple/head.c	(revision 9)
@@ -0,0 +1,78 @@
+/* head - print the first few lines of a file	Author: Andy Tanenbaum */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define DEFAULT 10
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void do_file, (int n, FILE *f));
+_PROTOTYPE(void usage, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  FILE *f;
+  int n, k, nfiles;
+  char *ptr;
+
+  /* Check for flag.  Only flag is -n, to say how many lines to print. */
+  k = 1;
+  ptr = argv[1];
+  n = DEFAULT;
+  if (argc > 1 && *ptr++ == '-') {
+	k++;
+	n = atoi(ptr);
+	if (n <= 0) usage();
+  }
+  nfiles = argc - k;
+
+  if (nfiles == 0) {
+	/* Print standard input only. */
+	do_file(n, stdin);
+	exit(0);
+  }
+
+  /* One or more files have been listed explicitly. */
+  while (k < argc) {
+	if (nfiles > 1) printf("==> %s <==\n", argv[k]);
+	if ((f = fopen(argv[k], "r")) == NULL)
+		fprintf(stderr, "%s: cannot open %s: %s\n",
+			argv[0], argv[k], strerror(errno));
+	else {
+		do_file(n, f);
+		fclose(f);
+	}
+	k++;
+	if (k < argc) printf("\n");
+  }
+  return(0);
+}
+
+
+
+void do_file(n, f)
+int n;
+FILE *f;
+{
+  int c;
+
+  /* Print the first 'n' lines of a file. */
+  while (n) switch (c = getc(f)) {
+	    case EOF:
+		return;
+	    case '\n':
+		--n;
+	    default:	putc((char) c, stdout);
+	}
+}
+
+
+void usage()
+{
+  fprintf(stderr, "Usage: head [-n] [file ...]\n");
+  exit(1);
+}
Index: /trunk/minix/commands/simple/host.c
===================================================================
--- /trunk/minix/commands/simple/host.c	(revision 9)
+++ /trunk/minix/commands/simple/host.c	(revision 9)
@@ -0,0 +1,1410 @@
+/*
+ * Copyright (c) 1986 Regents of the University of California
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of California at Berkeley. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+/*
+ * Actually, this program is from Rutgers University, however it is 
+ * based on nslookup and other pieces of named tools, so it needs
+ * that copyright notice.
+ */
+
+#if _MINIX
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <net/hton.h>
+#include <net/netlib.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/netdb.h>
+#include <net/gen/nameser.h>
+#include <net/gen/resolv.h>
+#include <net/gen/socket.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+
+#undef ERROR
+#else
+#include <stdio.h>
+#include <sys/types.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <resolv.h>
+#include <sys/param.h>
+#include <strings.h>
+#include <ctype.h>
+#endif
+
+extern int h_errno;
+
+#define NUMMX 50
+
+#define  SUCCESS		0
+#define  TIME_OUT		-1
+#define  NO_INFO 		-2
+#define  ERROR 			-3
+#define  NONAUTH 		-4
+
+#define NAME_LEN 256
+
+#ifndef T_TXT
+#define T_TXT 16
+#endif
+#ifndef NO_DATA
+#define NO_DATA NO_ADDRESS
+#endif
+#ifndef C_HS
+#define C_HS 4
+#endif
+
+FILE *filePtr;
+
+struct state orig;
+extern struct state _res;
+static u8_t *cname = NULL;
+int getclass = C_IN;
+int gettype, getdeftype = T_A;
+int verbose = 0;
+int list = 0;
+int server_specified = 0;
+
+union querybuf;
+
+int main _ARGS(( int c, char *v[] ));
+
+static int parsetype _ARGS(( char *s ));
+static int parseclass _ARGS(( char *s ));
+static void hperror _ARGS(( int errno ));
+static void printanswer _ARGS(( struct hostent *hp ));
+static int ListHosts _ARGS(( char *namePtr, int queryType ));
+static int gethostinfo _ARGS(( char *name ));
+static int getdomaininfo _ARGS(( char *name, char *domain ));
+static int getinfo _ARGS(( char *name, char *domain, int type ));
+static int printinfo _ARGS(( union querybuf *answer, u8_t *eom, int filter, 
+								int isls ));
+static char *DecodeError _ARGS(( int result ));
+static u8_t *pr_rr _ARGS(( u8_t *cp, u8_t *msg, FILE *file, int filter ));
+static u8_t * pr_cdname _ARGS(( u8_t *cp, u8_t *msg, u8_t *name, int namelen ));
+static char *pr_class _ARGS(( int class ));
+static char *pr_type _ARGS(( int type ));
+static int tcpip_writeall _ARGS(( int fd, char *buf, unsigned siz ));
+
+int
+main(c, v)
+	char **v;
+{
+	char *domain;
+	ipaddr_t addr;
+	register struct hostent *hp;
+	register char *s, *p;
+	register inverse = 0;
+	register waitmode = 0;
+	u8_t *oldcname;
+	int ncnames;
+	int isaddr;
+
+	res_init();
+	_res.retrans = 5;
+
+	if (c < 2) {
+		fprintf(stderr, "Usage: host [-w] [-v] [-r] [-d] [-V] [-t querytype] [-c class] [-a] host [server]\n  -w to wait forever until reply\n  -v for verbose output\n  -r to disable recursive processing\n  -d to turn on debugging output\n  -t querytype to look for a specific type of information\n  -c class to look for non-Internet data\n  -a is equivalent to '-v -t *'\n  -V to always use a virtual circuit\n");
+		exit(1);
+	}
+	while (c > 2 && v[1][0] == '-') {
+		if (strcmp (v[1], "-w") == 0) {
+			_res.retry = 1;
+			_res.retrans = 15;
+			waitmode = 1;
+			v++;
+			c--;
+		}
+		else if (strcmp (v[1], "-r") == 0) {
+			_res.options &= ~RES_RECURSE;
+			v++;
+			c--;
+		}
+		else if (strcmp (v[1], "-d") == 0) {
+			_res.options |= RES_DEBUG;
+			v++;
+			c--;
+		}
+		else if (strcmp (v[1], "-v") == 0) {
+			verbose = 1;
+			v++;
+			c--;
+		}
+		else if (strcmp (v[1], "-l") == 0) {
+			list = 1;
+			v++;
+			c--;
+		}
+		else if (strncmp (v[1], "-t", 2) == 0) {
+			v++;
+			c--;
+			gettype = parsetype(v[1]);
+			v++;
+			c--;
+		}
+		else if (strncmp (v[1], "-c", 2) == 0) {
+			v++;
+			c--;
+			getclass = parseclass(v[1]);
+			v++;
+			c--;
+		}
+		else if (strcmp (v[1], "-a") == 0) {
+			verbose = 1;
+			gettype = T_ANY;
+			v++;
+			c--;
+		}		
+		else if (strcmp (v[1], "-V") == 0) {
+			_res.options |= RES_USEVC;
+			v++;
+			c--;
+		}
+        }
+	if (c > 2) {
+		s = v[2];
+		server_specified++;
+		
+		if ((p = strchr(s, ':')) != NULL) *p++ = 0;
+		isaddr = inet_aton(s, &addr);
+		if (p != NULL) p[-1] = ':';
+		if (!isaddr) {
+		  hp = gethostbyname(s);
+		  if (hp == NULL) {
+		    fprintf(stderr,"Error in looking up server name:\n");
+		    hperror(h_errno);
+		    exit(1);
+		  }
+		  _res.nsaddr= *(ipaddr_t *)hp->h_addr;
+		  printf("Using domain server:\n");
+		  printanswer(hp);
+		}
+		else {
+		  _res.nsaddr_list[0]= addr;
+		  _res.nsport_list[0]= htons(NAMESERVER_PORT);
+		  printf("Using domain server %s",
+			 inet_ntoa(_res.nsaddr));
+		  if (p != NULL) {
+		    printf(" on port %d", atoi(p));
+		    _res.nsport_list[0]= htons(atoi(p));
+		  }
+		  printf(":\n");
+		}
+	      }
+	domain = v[1];
+	if (strcmp (domain, ".") != 0 && inet_aton(domain, &addr)) {
+	  static char ipname[sizeof("255.255.255.255.in-addr.arpa.")];
+	  sprintf(ipname, "%d.%d.%d.%d.in-addr.arpa.",
+	    ((unsigned char *) &addr)[3],
+	    ((unsigned char *) &addr)[2],
+	    ((unsigned char *) &addr)[1],
+	    ((unsigned char *) &addr)[0]);
+	  domain = ipname;
+	  getdeftype = T_PTR;
+	}
+
+	hp = NULL;
+	h_errno = TRY_AGAIN;
+/*
+ * we handle default domains ourselves, thank you
+ */
+	_res.options &= ~RES_DEFNAMES;
+
+        if (list)
+	  exit(ListHosts(domain, gettype ? gettype : getdeftype));
+	oldcname = NULL;
+	ncnames = 5;
+	while (hp == NULL && h_errno == TRY_AGAIN) {
+	  cname = NULL;
+	  if (oldcname == NULL)
+	    hp = (struct hostent *)gethostinfo(domain);
+	  else
+	    hp = (struct hostent *)gethostinfo((char *)oldcname);
+	  if (cname) {
+	    if (ncnames-- == 0) {
+	      printf("Too many cnames.  Possible loop.\n");
+	      exit(1);
+	    }
+	    oldcname = cname;
+	    hp = NULL;
+	    h_errno = TRY_AGAIN;
+	    continue;
+	  }
+	  if (!waitmode)
+	    break;
+	}
+
+	if (hp == NULL) {
+	  hperror(h_errno);
+	  exit(1);
+	}
+
+	exit(0);
+
+}
+
+static int
+parsetype(s)
+	char *s;
+{
+if (strcmp(s,"a") == 0)
+  return(1);
+if (strcmp(s,"ns") == 0)
+  return(2);
+if (strcmp(s,"md") == 0)
+  return(3);
+if (strcmp(s,"mf") == 0)
+  return(4);
+if (strcmp(s,"cname") == 0)
+  return(5);
+if (strcmp(s,"soa") == 0)
+  return(6);
+if (strcmp(s,"mb") == 0)
+  return(7);
+if (strcmp(s,"mg") == 0)
+  return(8);
+if (strcmp(s,"mr") == 0)
+  return(9);
+if (strcmp(s,"null") == 0)
+  return(10);
+if (strcmp(s,"wks") == 0)
+  return(11);
+if (strcmp(s,"ptr") == 0)
+  return(12);
+if (strcmp(s,"hinfo") == 0)
+  return(13);
+if (strcmp(s,"minfo") == 0)
+  return(14);
+if (strcmp(s,"mx") == 0)
+  return(15);
+if (strcmp(s,"txt") == 0)	/* Roy */
+  return(T_TXT);		/* Roy */
+if (strcmp(s,"uinfo") == 0)
+  return(100);
+if (strcmp(s,"uid") == 0)
+  return(101);
+if (strcmp(s,"gid") == 0)
+  return(102);
+if (strcmp(s,"unspec") == 0)
+  return(103);
+if (strcmp(s,"any") == 0)
+  return(255);
+if (strcmp(s,"*") == 0)
+  return(255);
+if (atoi(s))
+  return(atoi(s));
+fprintf(stderr, "Invalid query type: %s\n", s);
+exit(2);
+}
+
+static int
+parseclass(s)
+	char *s;
+{
+if (strcmp(s,"in") == 0)
+  return(C_IN);
+if (strcmp(s,"chaos") == 0)
+  return(C_CHAOS);
+if (strcmp(s,"hs") == 0)
+  return(C_HS);
+if (strcmp(s,"any") == 0)
+  return(C_ANY);
+if (atoi(s))
+  return(atoi(s));
+fprintf(stderr, "Invalid query class: %s\n", s);
+exit(2);
+}
+
+static void
+printanswer(hp)
+	register struct hostent *hp;
+{
+	register char **cp;
+	register ipaddr_t **hptr;
+
+	printf("Name: %s\n", hp->h_name);
+	printf("Address:");
+	for (hptr = (ipaddr_t **)hp->h_addr_list; *hptr; hptr++)
+	  printf(" %s", inet_ntoa(*(ipaddr_t *)*hptr));
+	printf("\nAliases:");
+	for (cp = hp->h_aliases; cp && *cp && **cp; cp++)
+		printf(" %s", *cp);
+	printf("\n\n");
+}
+
+static void
+hperror(errno) 
+int errno;
+{
+switch(errno) {
+	case HOST_NOT_FOUND:
+		fprintf(stderr,"Host not found.\n");
+		break;
+	case TRY_AGAIN:
+		fprintf(stderr,"Host not found, try again.\n");
+		break;
+	case NO_RECOVERY:
+		fprintf(stderr,"No recovery, Host not found.\n");
+		break;
+	case NO_ADDRESS:
+		fprintf(stderr,"There is an entry for this host, but it doesn't have what you requested.\n");
+		break;
+	}
+}
+
+
+typedef union querybuf {
+	dns_hdr_t qb1;
+	u8_t qb2[PACKETSZ];
+} querybuf_t;
+
+static u8_t hostbuf[BUFSIZ+1];
+
+
+static int
+gethostinfo(name)
+	char *name;
+{
+	register char *cp, **domain;
+	int n;
+	int hp;
+	int nDomain;
+
+	if (strcmp(name, ".") == 0)
+		return(getdomaininfo(name, NULL));
+	for (cp = name, n = 0; *cp; cp++)
+		if (*cp == '.')
+			n++;
+	if (n && cp[-1] == '.') {
+		if (cp[-1] == '.')
+			cp[-1] = 0;
+		hp = getdomaininfo(name, (char *)NULL);
+		if (cp[-1] == 0)
+			cp[-1] = '.';
+		return (hp);
+	}
+	if (n == 0 && (cp = __hostalias(name))) {
+	        if (verbose)
+		    printf("Aliased to \"%s\"\n", cp);
+		_res.options |= RES_DEFNAMES;	  
+		return (getdomaininfo(cp, (char *)NULL));
+	}
+#ifdef MAXDS
+	for (nDomain = 0;
+	     _res.defdname_list[nDomain][0] != 0;
+	     nDomain++) {
+	    for (domain = _res.dnsrch_list[nDomain]; *domain; domain++) {
+	        if (verbose)
+		    printf("Trying domain \"%s\"\n", *domain);
+		hp = getdomaininfo(name, *domain);
+		if (hp)
+			return (hp);
+	    }
+	}
+#else
+	for (domain = _res.dnsrch; *domain; domain++) {
+	  if (verbose)
+	    printf("Trying domain \"%s\"\n", *domain);
+	  hp = getdomaininfo(name, *domain);
+	  if (hp)
+	    return (hp);
+	}
+#endif
+	if (h_errno != HOST_NOT_FOUND ||
+	   (_res.options & RES_DNSRCH) == 0)
+		return (0);
+	if (verbose)
+	    printf("Trying null domain\n");
+	return (getdomaininfo(name, (char *)NULL));
+}
+
+static int
+getdomaininfo(name, domain)
+	char *name, *domain;
+{
+  return getinfo(name, domain, gettype ? gettype : getdeftype);
+}
+
+static int
+getinfo(name, domain, type)
+	char *name, *domain;
+{
+
+	dns_hdr_t *hp;
+	u8_t *eom, *bp, *cp;
+	querybuf_t buf, answer;
+	int n, n1, i, j, nmx, ancount, nscount, arcount, qdcount, buflen;
+	u_short pref, class;
+	char host[2*MAXDNAME+2];
+
+	if (domain == NULL)
+		(void)sprintf(host, "%.*s", MAXDNAME, name);
+	else
+		(void)sprintf(host, "%.*s.%.*s", MAXDNAME, name, MAXDNAME, domain);
+
+	n = res_mkquery(QUERY, host, getclass, type, (char *)NULL, 0, NULL,
+		(char *)&buf, sizeof(buf));
+	if (n < 0) {
+		if (_res.options & RES_DEBUG)
+			printf("res_mkquery failed\n");
+		h_errno = NO_RECOVERY;
+		return(0);
+	}
+	n = res_send((char *)&buf, n, (char *)&answer, sizeof(answer));
+	if (n < 0) {
+		if (_res.options & RES_DEBUG)
+			printf("res_send failed\n");
+		h_errno = TRY_AGAIN;
+		return (0);
+	}
+	eom = (u8_t *)&answer + n;
+	return(printinfo(&answer, eom, T_ANY, 0));
+}
+
+static int
+printinfo(answer, eom, filter, isls)
+	querybuf_t *answer;
+	u8_t *eom;
+        int filter;
+        int isls;
+{
+	dns_hdr_t *hp;
+	u8_t *bp, *cp;
+	int n, n1, i, j, nmx, ancount, nscount, arcount, qdcount, buflen;
+	u_short pref, class;
+
+	/*
+	 * find first satisfactory answer
+	 */
+	hp = (dns_hdr_t *) answer;
+	ancount = ntohs(hp->dh_ancount);
+	qdcount = ntohs(hp->dh_qdcount);
+	nscount = ntohs(hp->dh_nscount);
+	arcount = ntohs(hp->dh_arcount);
+	if (_res.options & RES_DEBUG || (verbose && isls == 0))
+		printf("rcode = %d (%s), ancount=%d\n", 
+		       hp->dh_flag2 & DHF_RCODE,
+		       DecodeError(hp->dh_flag2 & DHF_RCODE), ancount);
+	if (hp->dh_flag2 & DHF_RCODE != NOERROR || 
+		(ancount+nscount+arcount) == 0) {
+		switch (hp->dh_flag2 & DHF_RCODE) {
+			case NXDOMAIN:
+				/* Check if it's an authoritive answer */
+				if (hp->dh_flag1 & DHF_AA) {
+					h_errno = HOST_NOT_FOUND;
+					return(0);
+				} else {
+					h_errno = TRY_AGAIN;
+					return(0);
+				}
+			case SERVFAIL:
+				h_errno = TRY_AGAIN;
+				return(0);
+#ifdef OLDJEEVES
+			/*
+			 * Jeeves (TOPS-20 server) still does not
+			 * support MX records.  For the time being,
+			 * we must accept FORMERRs as the same as
+			 * NOERROR.
+			 */
+			case FORMERR:
+#endif /* OLDJEEVES */
+			case NOERROR:
+/* TpB - set a return error for this case. NO_DATA */
+				h_errno = NO_DATA;
+				return(0); /* was 1,but now indicates exception */
+#ifndef OLDJEEVES
+			case FORMERR:
+#endif /* OLDJEEVES */
+			case NOTIMP:
+			case REFUSED:
+				h_errno = NO_RECOVERY;
+				return(0);
+		}
+		return (0);
+	}
+	bp = hostbuf;
+	nmx = 0;
+	buflen = sizeof(hostbuf);
+	cp = (u8_t *)answer + sizeof(dns_hdr_t);
+	if (qdcount) {
+		cp += dn_skipname((u8_t *)cp,(u8_t *)eom) + QFIXEDSZ;
+		while (--qdcount > 0)
+			cp += dn_skipname((u8_t *)cp,(u8_t *)eom) + QFIXEDSZ;
+	}
+	if (ancount) {
+	  if (!(hp->dh_flag1 & DHF_AA))
+	    if (verbose && isls == 0)
+	      printf("The following answer is not authoritative:\n");
+	  while (--ancount >= 0 && cp && cp < eom) {
+	    cp = pr_rr(cp, (u8_t *)answer, stdout, filter);
+/*
+ * When we ask for address and there is a CNAME, it seems to return
+ * both the CNAME and the address.  Since we trace down the CNAME
+ * chain ourselves, we don't really want to print the address at
+ * this point.
+ */
+	    if (cname && ! verbose)
+	      return (1);
+	  }
+	}
+	if (! verbose)
+	  return (1);
+	if (nscount) {
+	  printf("For authoritative answers, see:\n");
+	  while (--nscount >= 0 && cp && cp < eom) {
+	    cp = pr_rr(cp, (u8_t *)answer, stdout, filter);
+	  }
+	}
+	if (arcount) {
+	  printf("Additional information:\n");
+	  while (--arcount >= 0 && cp && cp < eom) {
+	    cp = pr_rr(cp, (u8_t *)answer, stdout, filter);
+	  }
+	}
+	return(1);
+ }
+
+static u8_t cnamebuf[MAXDNAME];
+
+/*
+ * Print resource record fields in human readable form.
+ */
+static u8_t *
+pr_rr(cp, msg, file, filter)
+	u8_t *cp, *msg;
+	FILE *file;
+        int filter;
+{
+	int type, class, dlen, n, c, proto, ttl;
+	ipaddr_t inaddr;
+	u8_t *cp1;
+	struct protoent *protop;
+	struct servent *servp;
+	char punc;
+	int doprint;
+	u8_t name[MAXDNAME];
+
+	if ((cp = pr_cdname(cp, msg, name, sizeof(name))) == NULL)
+		return (NULL);			/* compression error */
+
+	type = _getshort(cp);
+	cp += sizeof(u_short);
+
+	class = _getshort(cp);
+	cp += sizeof(u_short);
+
+	ttl = _getlong(cp);
+	cp += sizeof(u_long);
+
+	if (filter == type || filter == T_ANY ||
+	    (filter == T_A && (type == T_PTR || type == T_NS)))
+	  doprint = 1;
+	else
+	  doprint = 0;
+
+	if (doprint)
+	  if (verbose)
+	    fprintf(file,"%s\t%d%s\t%s",
+		    name, ttl, pr_class(class), pr_type(type));
+	  else
+	    fprintf(file,"%s%s %s",name, pr_class(class), pr_type(type));
+	if (verbose)
+	  punc = '\t';
+	else
+	  punc = ' ';
+
+	dlen = _getshort(cp);
+	cp += sizeof(u_short);
+	cp1 = cp;
+	/*
+	 * Print type specific data, if appropriate
+	 */
+	switch (type) {
+	case T_A:
+		switch (class) {
+		case C_IN:
+			bcopy((char *)cp, (char *)&inaddr, sizeof(inaddr));
+			if (dlen == 4) {
+			        if (doprint)
+				  fprintf(file,"%c%s", punc,
+					inet_ntoa(inaddr));
+				cp += dlen;
+			} else if (dlen == 7) {
+			        if (doprint) {
+				  fprintf(file,"%c%s", punc,
+					  inet_ntoa(inaddr));
+				  fprintf(file,", protocol = %d", cp[4]);
+				  fprintf(file,", port = %d",
+					  (cp[5] << 8) + cp[6]);
+				}
+				cp += dlen;
+			}
+			break;
+		}
+		break;
+	case T_CNAME:
+		if (dn_expand(msg, msg + 512, cp, cnamebuf, 
+			      sizeof(cnamebuf)-1) >= 0) {
+			strcat((char *) cnamebuf, ".");
+			if (gettype != T_CNAME && gettype != T_ANY)
+				cname = cnamebuf;				
+		}
+	case T_MB:
+#ifdef OLDRR
+	case T_MD:
+	case T_MF:
+#endif /* OLDRR */
+	case T_MG:
+	case T_MR:
+	case T_NS:
+	case T_PTR:
+		cp = pr_cdname(cp, msg, name, sizeof(name));
+		if (doprint)
+		  fprintf(file,"%c%s",punc, name);
+		break;
+
+	case T_HINFO:
+		if (n = *cp++) {
+			if (doprint)
+			  fprintf(file,"%c%.*s", punc, n, cp);
+			cp += n;
+		}
+		if (n = *cp++) {
+			if (doprint)
+			  fprintf(file,"%c%.*s", punc, n, cp);
+			cp += n;
+		}
+		break;
+
+	case T_SOA:
+		cp = pr_cdname(cp, msg, name, sizeof(name));
+		if (doprint)
+		  fprintf(file,"\t%s", name);
+		cp = pr_cdname(cp, msg, name, sizeof(name));
+		if (doprint)
+		  fprintf(file," %s", name);
+		if (doprint)
+		  fprintf(file,"(\n\t\t\t%ld\t;serial (version)", _getlong(cp));
+		cp += sizeof(u_long);
+		if (doprint)
+		  fprintf(file,"\n\t\t\t%ld\t;refresh period", _getlong(cp));
+		cp += sizeof(u_long);
+		if (doprint)
+		  fprintf(file,"\n\t\t\t%ld\t;retry refresh this often", _getlong(cp));
+		cp += sizeof(u_long);
+		if (doprint)
+		  fprintf(file,"\n\t\t\t%ld\t;expiration period", _getlong(cp));
+		cp += sizeof(u_long);
+		if (doprint)
+		  fprintf(file,"\n\t\t\t%ld\t;minimum TTL\n\t\t\t)", _getlong(cp));
+		cp += sizeof(u_long);
+		break;
+
+	case T_MX:
+		if (doprint)
+		  if (verbose)
+		    fprintf(file,"\t%d ",_getshort(cp));
+		  else
+		    fprintf(file," (pri=%d) by ",_getshort(cp));
+		cp += sizeof(u_short);
+		cp = pr_cdname(cp, msg, name, sizeof(name));
+		if (doprint)
+		  fprintf(file, "%s", name);
+		break;
+
+	case T_MINFO:
+		cp = pr_cdname(cp, msg, name, sizeof(name));
+		if (doprint)
+		  fprintf(file,"%c%s",punc, name);
+		cp = pr_cdname(cp, msg, name, sizeof(name));
+		if (doprint)
+		  fprintf(file," %s", name);
+		break;
+
+		/* Roy start */
+	case T_TXT:
+		if (n = *cp++) {
+			if (doprint)
+			  fprintf(file,"%c%.*s", punc, n, cp);
+			cp += n;
+		}
+		break;
+		/* Roy end */
+
+	case T_UINFO:
+		if (doprint)
+		  fprintf(file,"%c%s", punc, cp);
+		cp += dlen;
+		break;
+
+	case T_UID:
+	case T_GID:
+		if (dlen == 4) {
+			if (doprint)
+			  fprintf(file,"%c%ld", punc, _getlong(cp));
+			cp += sizeof(int);
+		}
+		break;
+
+	case T_WKS:
+		if (dlen < sizeof(u_long) + 1)
+			break;
+		bcopy((char *)cp, (char *)&inaddr, sizeof(inaddr));
+		cp += sizeof(u_long);
+		proto = *cp++;
+		protop = getprotobynumber(proto);
+		if (doprint)
+		  if (protop)
+		    fprintf(file,"%c%s %s", punc,
+			    inet_ntoa(inaddr), protop->p_name);
+		  else
+		    fprintf(file,"%c%s %d", punc,
+			    inet_ntoa(inaddr), proto);
+
+		n = 0;
+		while (cp < cp1 + dlen) {
+			c = *cp++;
+			do {
+ 				if (c & 0200) {
+				  servp = NULL;
+				  if (protop)
+				    servp = getservbyport (htons(n),
+							   protop->p_name);
+				  if (doprint)
+				    if (servp)
+				      fprintf(file, " %s", servp->s_name);
+				    else
+				      fprintf(file, " %d", n);
+				}
+ 				c <<= 1;
+			} while (++n & 07);
+		}
+		break;
+
+	default:
+		if (doprint)
+		  fprintf(file,"%c???", punc);
+		cp += dlen;
+	}
+	if (cp != cp1 + dlen)
+		fprintf(file,"packet size error (%#x != %#x)\n", cp, cp1+dlen);
+	if (doprint)
+	  fprintf(file,"\n");
+	return (cp);
+}
+
+static	char nbuf[20];
+
+/*
+ * Return a string for the type
+ */
+static char *
+pr_type(type)
+	int type;
+{
+	switch (type) {
+	case T_A:
+		return(verbose? "A" : "has address");
+	case T_NS:		/* authoritative server */
+		return("NS");
+#ifdef OLDRR
+	case T_MD:		/* mail destination */
+		return("MD");
+	case T_MF:		/* mail forwarder */
+		return("MF");
+#endif /* OLDRR */
+	case T_CNAME:		/* connonical name */
+		return(verbose? "CNAME" : "is a nickname for");
+	case T_SOA:		/* start of authority zone */
+		return("SOA");
+	case T_MB:		/* mailbox domain name */
+		return("MB");
+	case T_MG:		/* mail group member */
+		return("MG");
+	case T_MX:		/* mail routing info */
+		return(verbose? "MX" : "mail is handled");
+	/* Roy start */
+	case T_TXT:		/* TXT - descriptive info */
+		return(verbose? "TXT" : "descriptive text");
+	/* Roy end */
+	case T_MR:		/* mail rename name */
+		return("MR");
+	case T_NULL:		/* null resource record */
+		return("NULL");
+	case T_WKS:		/* well known service */
+		return("WKS");
+	case T_PTR:		/* domain name pointer */
+		return("PTR");
+	case T_HINFO:		/* host information */
+		return("HINFO");
+	case T_MINFO:		/* mailbox information */
+		return("MINFO");
+	case T_AXFR:		/* zone transfer */
+		return("AXFR");
+	case T_MAILB:		/* mail box */
+		return("MAILB");
+	case T_MAILA:		/* mail address */
+		return("MAILA");
+	case T_ANY:		/* matches any type */
+		return("ANY");
+	case T_UINFO:
+		return("UINFO");
+	case T_UID:
+		return("UID");
+	case T_GID:
+		return("GID");
+	default:
+		return (sprintf(nbuf, "%d", type) == EOF ? NULL : nbuf);
+	}
+}
+
+/*
+ * Return a mnemonic for class
+ */
+static char *
+pr_class(class)
+	int class;
+{
+
+	switch (class) {
+	case C_IN:		/* internet class */
+		return(verbose? " IN" : "");
+	case C_CHAOS:		/* chaos class */
+		return(verbose? " CHAOS" : "");
+	case C_HS:		/* Hesiod class */
+		return(verbose? " HS" : "");
+	case C_ANY:		/* matches any class */
+		return(" ANY");
+	default:
+		return (sprintf(nbuf," %d", class) == EOF ? NULL : nbuf);
+	}
+}
+
+static u8_t *
+pr_cdname(cp, msg, name, namelen)
+	u8_t *cp, *msg;
+        u8_t *name;
+        int namelen;
+{
+	int n;
+
+	if ((n = dn_expand(msg, msg + 512, cp, name, namelen - 2)) < 0)
+		return (NULL);
+	if (name[0] == '\0') {
+		name[0] = '.';
+		name[1] = '\0';
+	}
+	return (cp + n);
+}
+
+char *resultcodes[] = {
+	"NOERROR",
+	"FORMERR",
+	"SERVFAIL",
+	"NXDOMAIN",
+	"NOTIMP",
+	"REFUSED",
+	"6",
+	"7",
+	"8",
+	"9",
+	"10",
+	"11",
+	"12",
+	"13",
+	"14",
+	"NOCHANGE",
+};
+
+
+
+
+/*
+ ******************************************************************************
+ *
+ *  ListHosts --
+ *
+ *	Requests the name server to do a zone transfer so we
+ *	find out what hosts it knows about.
+ *
+ *  Results:
+ *	SUCCESS		the listing was successful.
+ *	ERROR		the server could not be contacted because 
+ *			a socket could not be obtained or an error
+ *			occured while receiving, or the output file
+ *			could not be opened.
+ *
+ ******************************************************************************
+ */
+
+static int
+ListHosts(namePtr, queryType)
+    char *namePtr;
+    int  queryType;  /* e.g. T_A */
+{
+	querybuf_t 		buf, answer;
+	dns_hdr_t		*headerPtr;
+
+	int 			msglen;
+	int 			amtToRead;
+	int 			numRead;
+	int 			i;
+	int 			numAnswers = 0;
+	int 			result;
+	int 			soacnt = 0;
+	u_short 		len;
+	int			dlen;
+	int			type;
+	int			nscount;
+	u8_t 			*cp, *nmp;
+	u8_t 			name[NAME_LEN];
+	char 			dname[2][NAME_LEN];
+	u8_t 			domain[NAME_LEN];
+/* names and addresses of name servers to try */
+#define NUMNS 8
+	char			nsname[NUMNS][NAME_LEN];
+	int			nshaveaddr[NUMNS];
+#define IPADDRSIZE 4
+#define NUMNSADDR 16
+	char	 		nsipaddr[NUMNSADDR][IPADDRSIZE];
+	int			numns;
+	int			numnsaddr;
+	int			thisns;
+	struct hostent		*hp;
+	enum {
+	    NO_ERRORS, 
+	    ERR_READING_LEN, 
+	    ERR_READING_MSG,
+	    ERR_PRINTING
+	} error = NO_ERRORS;
+	char *tcp_serv_name;
+	int tcp_fd;
+	nwio_tcpconf_t tcpconf;
+	nwio_tcpcl_t clopt;
+	int terrno;
+
+/*
+ * normalize to not have trailing dot.  We do string compares below
+ * of info from name server, and it won't have trailing dots.
+ */
+	i = strlen(namePtr);
+	if (namePtr[i-1] == '.')
+	  namePtr[i-1] = 0;
+
+	if (server_specified) {
+	  bcopy((char *)&_res.nsaddr, nsipaddr[0], IPADDRSIZE);
+	  numnsaddr = 1;
+	}
+	else {
+
+/*
+ * First we have to find out where to look.  This needs a NS query,
+ * possibly followed by looking up addresses for some of the names.
+ */
+
+	msglen = res_mkquery(QUERY, namePtr, C_IN, T_NS,
+				(char *)0, 0, (struct rrec *)0, 
+				(char *)&buf, sizeof(buf));
+
+	if (msglen < 0) {
+		printf("res_mkquery failed\n");
+		return (ERROR);
+	}
+
+	msglen = res_send((char *)&buf,msglen,(char *)&answer, sizeof(answer));
+	
+	if (msglen < 0) {
+		printf("Unable to get to nameserver -- try again later\n");
+		return (ERROR);
+	}
+	if (_res.options & RES_DEBUG || verbose)
+		printf("rcode = %d (%s), ancount=%d\n", 
+		       answer.qb1.dh_flag2 & DHF_RCODE,
+		       DecodeError(answer.qb1.dh_flag2 & DHF_RCODE),
+		       ntohs(answer.qb1.dh_ancount));
+
+/*
+ * Analyze response to our NS lookup
+ */
+
+	nscount = ntohs(answer.qb1.dh_ancount) + ntohs(answer.qb1.dh_nscount) +
+		  ntohs(answer.qb1.dh_arcount);
+
+	if (answer.qb1.dh_flag2 & DHF_RCODE != NOERROR || nscount == 0) {
+		switch (answer.qb1.dh_flag2 & DHF_RCODE) {
+			case NXDOMAIN:
+				/* Check if it's an authoritive answer */
+				if (answer.qb1.dh_flag1 & DHF_AA) {
+					printf("No such domain\n");
+				} else {
+					printf("Unable to get information about domain -- try again later.\n");
+				}
+				break;
+			case SERVFAIL:
+				printf("Unable to get information about that domain -- try again later.\n");
+				break;
+			case NOERROR:
+				printf("That domain exists, but seems to be a leaf node.\n");
+				break;
+			case FORMERR:
+			case NOTIMP:
+			case REFUSED:
+				printf("Unrecoverable error looking up domain name.\n");
+				break;
+		}
+		return (0);
+	}
+
+	cp = answer.qb2 + sizeof(dns_hdr_t);
+	if (ntohs(answer.qb1.dh_qdcount) > 0)
+	  cp += dn_skipname(cp, answer.qb2 + msglen) + QFIXEDSZ;
+
+	numns = 0;
+	numnsaddr = 0;
+
+/*
+ * Look at response from NS lookup for NS and A records.
+ */
+
+	for (;nscount; nscount--) {
+	  cp += dn_expand(answer.qb2, answer.qb2 + msglen, cp,
+			  domain, sizeof(domain));
+	  type = _getshort(cp);
+	  cp += sizeof(u_short) + sizeof(u_short) + sizeof(u_long);
+	  dlen = _getshort(cp);
+	  cp += sizeof(u_short);
+	  if (type == T_NS) {
+	    if (dn_expand(answer.qb2, answer.qb2 + msglen, cp, 
+			  name, sizeof(name)) >= 0) {
+	      if (numns < NUMNS && strcasecmp((char *)domain, namePtr) == 0) {
+		for (i = 0; i < numns; i++)
+		  if (strcasecmp(nsname[i], (char *)name) == 0)
+		    break;  /* duplicate */
+		if (i >= numns) {
+		  strncpy(nsname[numns], (char *)name, sizeof(name));
+		  nshaveaddr[numns] = 0;
+		  numns++;
+		}
+	      }
+	    }
+	  }
+	  else if (type == T_A) {
+	    if (numnsaddr < NUMNSADDR)
+	      for (i = 0; i < numns; i++) {
+		if (strcasecmp(nsname[i], (char *)domain) == 0) {
+		  nshaveaddr[i]++;
+		  bcopy((char *)cp, nsipaddr[numnsaddr],IPADDRSIZE);
+		  numnsaddr++;
+		  break;
+		}
+	      }
+	  }
+	  cp += dlen;
+	}
+
+/*
+ * Usually we'll get addresses for all the servers in the additional
+ * info section.  But in case we don't, look up their addresses.
+ */
+
+	for (i = 0; i < numns; i++) {
+	  if (! nshaveaddr[i]) {
+	    register long **hptr;
+	    int numaddrs = 0;
+
+	    hp = gethostbyname(nsname[i]);
+	    if (hp) {
+	      for (hptr = (long **)hp->h_addr_list; *hptr; hptr++)
+		if (numnsaddr < NUMNSADDR) {
+		  bcopy((char *)*hptr, nsipaddr[numnsaddr],IPADDRSIZE);
+		  numnsaddr++;
+		  numaddrs++;
+		}
+	    }
+	    if (_res.options & RES_DEBUG || verbose)
+	      printf("Found %d addresses for %s by extra query\n",
+		     numaddrs, nsname[i]);
+	  }
+	  else
+	    if (_res.options & RES_DEBUG || verbose)
+	      printf("Found %d addresses for %s\n",
+		     nshaveaddr[i], nsname[i]);
+	}
+        }
+/*
+ * Now nsipaddr has numnsaddr addresses for name servers that
+ * serve the requested domain.  Now try to find one that will
+ * accept a zone transfer.
+ */
+
+	thisns = 0;
+
+again:
+
+	numAnswers = 0;
+	soacnt = 0;
+
+	/*
+	 *  Create a query packet for the requested domain name.
+	 *
+	 */
+	msglen = res_mkquery(QUERY, namePtr, getclass, T_AXFR,
+				(char *)0, 0, (struct rrec *)0, 
+				(char *) &buf, sizeof(buf));
+	if (msglen < 0) {
+	    if (_res.options & RES_DEBUG) {
+		fprintf(stderr, "ListHosts: Res_mkquery failed\n");
+	    }
+	    return (ERROR);
+	}
+
+	/*
+	 *  Set up a virtual circuit to the server.
+	 */
+
+	tcp_serv_name= getenv("TCP_DEVICE");
+	if (!tcp_serv_name)
+		tcp_serv_name= TCP_DEVICE;
+	for (;thisns < numnsaddr; thisns++) 
+	{
+		tcp_fd= open(tcp_serv_name, O_RDWR);
+		if (tcp_fd == -1)
+		{
+			fprintf(stderr, "unable to open '%s': %s\n", tcp_serv_name,
+				strerror(errno));
+			return ERROR;
+		}
+
+		tcpconf.nwtc_flags= NWTC_EXCL | NWTC_LP_SEL | NWTC_SET_RA | 
+								NWTC_SET_RP;
+		tcpconf.nwtc_remaddr= *(ipaddr_t *)nsipaddr[thisns];
+		tcpconf.nwtc_remport= _res.nsport_list[0];
+		result= ioctl(tcp_fd, NWIOSTCPCONF, &tcpconf);
+		if (result == -1)
+		{
+			fprintf(stderr, "tcp_ioc_setconf failed: %s\n", 
+				strerror(errno));
+			close(tcp_fd);
+			return ERROR;
+		}
+		if (_res.options & RES_DEBUG || verbose)
+			printf("Trying %s\n", inet_ntoa(tcpconf.nwtc_remaddr));
+		clopt.nwtcl_flags= 0;
+		result= ioctl(tcp_fd, NWIOTCPCONN, &clopt);
+		if (result == 0)
+			break;
+		terrno= errno;
+		if (verbose)
+			fprintf(stderr, 
+				"Connection failed, trying next server: %s\n",
+				strerror(errno));
+		close(tcp_fd);
+	}	
+	if (thisns >= numnsaddr) {
+	  printf("No server for that domain responded\n");
+	  if (!verbose)
+	    fprintf(stderr, "Error from the last server was: %s\n", 
+						strerror(terrno));
+	  return(ERROR);
+	}
+
+	/*
+	 * Send length & message for zone transfer 
+	 */
+
+        len = htons(msglen);
+
+	result= tcpip_writeall(tcp_fd, (char *)&len, sizeof(len));
+	if (result != sizeof(len))
+	{
+		fprintf(stderr, "write failed: %s\n", strerror(errno));
+		close(tcp_fd);
+		return ERROR;
+	}
+	result= tcpip_writeall(tcp_fd, (char *)&buf, msglen);
+	if (result != msglen)
+	{
+		fprintf(stderr, "write failed: %s\n",
+			strerror(errno));
+		close(tcp_fd);
+		return ERROR;
+	}
+	filePtr = stdout;
+
+	while (1) {
+
+	    /*
+	     * Read the length of the response.
+	     */
+
+	    cp = (u8_t *) &buf;
+	    amtToRead = sizeof(u_short);
+	    while(amtToRead > 0)
+	    {
+		result = read(tcp_fd, (char *)cp, amtToRead);
+		if (result <= 0)
+			break;
+		cp 	  += result;
+		amtToRead -= result;
+	    }
+	    if (amtToRead) {
+		error = ERR_READING_LEN;
+		break;
+	    }	
+
+	    if ((len = htons(*(u_short *)&buf)) == 0) {
+		break;	/* nothing left to read */
+	    }
+
+	    /*
+	     * Read the response.
+	     */
+
+	    amtToRead = len;
+	    cp = (u8_t *) &buf;
+	    while(amtToRead > 0)
+	    {
+		result = read(tcp_fd, (char *)cp, amtToRead);
+		if (result<= 0)
+			break;
+		cp 	  += result;
+		amtToRead -= result;
+	    }
+	    if (amtToRead) {
+		error = ERR_READING_MSG;
+		break;
+	    }
+
+	    i = buf.qb1.dh_flag2 & DHF_RCODE;
+	    if (i != NOERROR || ntohs(buf.qb1.dh_ancount) == 0) {
+	      if ((thisns+1) < numnsaddr &&
+		  (i == SERVFAIL || i == NOTIMP || i == REFUSED)) {
+		if (_res.options & RES_DEBUG || verbose)
+		  printf("Server failed, trying next server: %s\n",
+			 i != NOERROR ? 
+			 DecodeError(i) : "Premature end of data");
+		close(tcp_fd);
+		thisns++;
+		goto again;
+	      }
+	      printf("Server failed: %s\n",
+		     i != NOERROR ? DecodeError(i) : "Premature end of data");
+	      break;
+	    }
+
+
+	    result = printinfo(&buf, cp, queryType, 1);
+	    if (! result) {
+		error = ERR_PRINTING;
+		break;
+	    }
+	    numAnswers++;
+	    cp = buf.qb2 + sizeof(dns_hdr_t);
+	    if (ntohs(buf.qb1.dh_qdcount) > 0)
+		cp += dn_skipname(cp, buf.qb2 + len) + QFIXEDSZ;
+
+	    nmp = cp;
+	    cp += dn_skipname(cp, (u_char *)&buf + len);
+	    if ((_getshort(cp) == T_SOA)) {
+		dn_expand(buf.qb2, buf.qb2 + len, nmp, (u8_t *)dname[soacnt],
+			sizeof(dname[0]));
+	        if (soacnt) {
+		    if (strcmp(dname[0], dname[1]) == 0)
+			break;
+		} else
+		    soacnt++;
+	    }
+        }
+
+	close(tcp_fd);
+
+	switch (error) {
+	    case NO_ERRORS:
+		return (SUCCESS);
+
+	    case ERR_READING_LEN:
+		return(ERROR);
+
+	    case ERR_PRINTING:
+		fprintf(stderr,"*** Error during listing of %s: %s\n", 
+				namePtr, DecodeError(result));
+		return(result);
+
+	    case ERR_READING_MSG:
+		headerPtr = (dns_hdr_t *) &buf;
+		fprintf(stderr,"ListHosts: error receiving zone transfer:\n");
+		fprintf(stderr,
+	       "  result: %s, answers = %d, authority = %d, additional = %d\n", 
+		    	resultcodes[headerPtr->dh_flag2 & DHF_RCODE], 
+		    	ntohs(headerPtr->dh_ancount), 
+			ntohs(headerPtr->dh_nscount), 
+			ntohs(headerPtr->dh_arcount));
+		return(ERROR);
+	    default:
+		return(ERROR);
+	}
+}
+
+static char *
+DecodeError(result)
+    int result;
+{
+	switch(result) {
+	    case NOERROR: 	return("Success"); break;
+	    case FORMERR:	return("Format error"); break;
+	    case SERVFAIL:	return("Server failed"); break;
+	    case NXDOMAIN:	return("Non-existent domain"); break;
+	    case NOTIMP:	return("Not implemented"); break;
+	    case REFUSED:	return("Query refused"); break;
+	    case NOCHANGE:	return("No change"); break;
+	    case NO_INFO: 	return("No information"); break;
+	    case ERROR: 	return("Unspecified error"); break;
+	    case TIME_OUT: 	return("Timed out"); break;
+	    case NONAUTH: 	return("Non-authoritative answer"); break;
+	    default: 		break;
+	}
+	return("BAD ERROR VALUE"); 
+}
+
+static int tcpip_writeall(fd, buf, siz)
+int fd;
+char *buf;
+unsigned siz;
+{
+	unsigned siz_org;
+	int nbytes;
+
+	siz_org= siz;
+
+	while (siz)
+	{
+		nbytes= write(fd, buf, siz);
+		if (nbytes == -1)
+			return nbytes;
+		assert(siz >= nbytes);
+		buf += nbytes;
+		siz -= nbytes;
+	}
+	return siz_org;
+}
Index: /trunk/minix/commands/simple/hostaddr.c
===================================================================
--- /trunk/minix/commands/simple/hostaddr.c	(revision 9)
+++ /trunk/minix/commands/simple/hostaddr.c	(revision 9)
@@ -0,0 +1,313 @@
+/*
+hostaddr.c
+
+Fetch an ip and/or ethernet address and print it on one line.
+
+Created:	Jan 27, 1992 by Philip Homburg
+*/
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/utsname.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include <net/gen/if_ether.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/ip_io.h>
+#include <net/gen/netdb.h>
+#include <net/gen/socket.h>
+#include <net/gen/nameser.h>
+#include <net/gen/resolv.h>
+#include <net/gen/dhcp.h>
+
+#include <minix/paths.h>
+
+char *prog_name;
+
+char DHCPCACHE[]=_PATH_DHCPCACHE;
+
+void main _ARGS(( int argc, char *argv[] ));
+void usage _ARGS(( void ));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+	int c;
+	int first_print;
+	int a_flag, e_flag, i_flag, h_flag;
+	char *E_arg, *I_arg;
+	int do_ether, do_ip, do_asc_ip, do_hostname;
+	char *eth_device, *ip_device;
+	int eth_fd, ip_fd;
+	int result;
+	nwio_ethstat_t nwio_ethstat;
+	nwio_ipconf_t nwio_ipconf;
+	struct hostent *hostent;
+	char *hostname, *domain;
+	char nodename[2*256];
+	dhcp_t dhcp;
+
+	first_print= 1;
+	prog_name= argv[0];
+
+	a_flag= e_flag= h_flag = i_flag= 0;
+	E_arg= I_arg= NULL;
+
+	while((c= getopt(argc, argv, "?aheE:iI:")) != -1)
+	{
+		switch(c)
+		{
+		case '?':
+			usage();
+		case 'a':
+			if (a_flag)
+				usage();
+			a_flag= 1;
+			break;
+		case 'h':
+			if (h_flag)
+				usage();
+			h_flag= 1;
+			break;
+		case 'e':
+			if (e_flag)
+				usage();
+			e_flag= 1;
+			break;
+		case 'E':
+			if (E_arg)
+				usage();
+			E_arg= optarg;
+			break;
+		case 'i':
+			if (i_flag)
+				usage();
+			i_flag= 1;
+			break;
+		case 'I':
+			if (I_arg)
+				usage();
+			I_arg= optarg;
+			break;
+		default:
+			usage();
+		}
+	}
+	if(optind != argc)
+		usage();
+
+	do_ether= e_flag;
+	if (E_arg)
+		eth_device= E_arg;
+	else
+	{
+		eth_device= getenv("ETH_DEVICE");
+		if (!eth_device)
+			eth_device= ETH_DEVICE;
+	}
+
+	do_ip= i_flag;
+	do_asc_ip= a_flag;
+	do_hostname= h_flag;
+	if (I_arg)
+		ip_device= I_arg;
+	else
+	{
+		ip_device= getenv("IP_DEVICE");
+		if (!ip_device)
+			ip_device= IP_DEVICE;
+	}
+
+	if (!do_ether && !do_ip && !do_asc_ip && !do_hostname)
+		do_ether= do_ip= do_asc_ip= 1;
+
+	if (do_ether)
+	{
+		eth_fd= open(eth_device, O_RDWR);
+		if (eth_fd == -1)
+		{
+			fprintf(stderr, "%s: Unable to open '%s': %s\n",
+				prog_name, eth_device, strerror(errno));
+			exit(1);
+		}
+		result= ioctl(eth_fd, NWIOGETHSTAT, &nwio_ethstat);
+		if (result == -1)
+		{
+			fprintf(stderr, 
+			"%s: Unable to fetch ethernet address: %s\n",
+				prog_name, strerror(errno));
+			exit(1);
+		}
+		printf("%s%s", first_print ? "" : " ",
+					ether_ntoa(&nwio_ethstat.nwes_addr));
+		first_print= 0;
+	}
+	if (do_ip || do_asc_ip || do_hostname)
+	{
+		ip_fd= open(ip_device, O_RDWR);
+		if (ip_fd == -1)
+		{
+			fprintf(stderr, "%s: Unable to open '%s': %s\n",
+				prog_name, ip_device, strerror(errno));
+			exit(1);
+		}
+		result= ioctl(ip_fd, NWIOGIPCONF, &nwio_ipconf);
+		if (result == -1)
+		{
+			fprintf(stderr, 
+				"%s: Unable to fetch IP address: %s\n",
+				prog_name,
+				strerror(errno));
+			exit(1);
+		}
+	}
+
+	setuid(getuid());
+
+	if (do_ip)
+	{
+		printf("%s%s", first_print ? "" : " ",
+					inet_ntoa(nwio_ipconf.nwic_ipaddr));
+		first_print= 0;
+	}
+	if (do_asc_ip || do_hostname)
+	{
+		int fd;
+		int r;
+		dhcp_t d;
+		u8_t *data;
+		size_t hlen, dlen;
+
+		hostname= NULL;
+		domain= NULL;
+
+		/* Use a reverse DNS lookup to get the host name.  This is
+		 * the preferred method, but often fails due to lazy admins.
+		 */
+		hostent= gethostbyaddr((char *)&nwio_ipconf.nwic_ipaddr,
+			sizeof(nwio_ipconf.nwic_ipaddr), AF_INET);
+		if (hostent != NULL) hostname= hostent->h_name;
+
+		if (hostname != NULL)
+		{
+			/* Reverse DNS works.  */
+		}
+		else if ((fd= open(DHCPCACHE, O_RDONLY)) == -1)
+		{
+			if (errno != ENOENT)
+			{
+				fprintf(stderr, "%s: %s: %s\n",
+					prog_name, DHCPCACHE, strerror(errno));
+				exit(1);
+			}
+		}
+		else
+		{
+			/* Try to get the hostname from the DHCP data. */
+			while ((r= read(fd, &d, sizeof(d))) == sizeof(d))
+			{
+				if (d.yiaddr == nwio_ipconf.nwic_ipaddr) break;
+			}
+			if (r < 0)
+			{
+				fprintf(stderr, "%s: %s: %s\n",
+					prog_name, DHCPCACHE, strerror(errno));
+				exit(1);
+			}
+			close(fd);
+
+			if (r == sizeof(d))
+			{
+				if (dhcp_gettag(&d, DHCP_TAG_HOSTNAME,
+							&data, &hlen))
+					hostname= (char *) data;
+
+				if (dhcp_gettag(&d, DHCP_TAG_DOMAIN,
+							&data, &dlen))
+					domain= (char *) data;
+
+				if (hostname != NULL) hostname[hlen] = 0;
+				if (domain != NULL) domain[dlen] = 0;
+			}
+		}
+
+		if (hostname != NULL)
+		{
+			if (strchr(hostname, '.') != NULL)
+			{
+				domain= strchr(hostname, '.');
+				*domain++ = 0;
+			}
+		}
+		else
+		{
+			/* No host name anywhere.  Use the IP address. */
+			hostname= inet_ntoa(nwio_ipconf.nwic_ipaddr);
+			domain= NULL;
+		}
+
+		strcpy(nodename, hostname);
+		if (domain != NULL)
+		{
+			strcat(nodename, ".");
+			strcat(nodename, domain);
+		}
+	}
+	if (do_asc_ip)
+	{
+		printf("%s%s", first_print ? "" : " ", nodename);
+		first_print= 0;
+	}
+	if (do_hostname)
+	{
+#if __minix_vmd
+		if (sysuname(_UTS_SET, _UTS_NODENAME,
+					nodename, strlen(nodename)+1) == -1)
+		{
+			fprintf(stderr, "%s: Unable to set nodename: %s\n",
+				prog_name, strerror(errno));
+			exit(1);
+		}
+
+		if (sysuname(_UTS_SET, _UTS_HOSTNAME,
+					hostname, strlen(hostname)+1) == -1)
+		{
+			fprintf(stderr, "%s: Unable to set hostname: %s\n",
+				prog_name, strerror(errno));
+			exit(1);
+		}
+#else
+		FILE *fp;
+
+		if ((fp= fopen("/etc/hostname.file", "w")) == NULL
+		    || fprintf(fp, "%s\n", nodename) == EOF
+		    || fclose(fp) == EOF)
+		{
+			fprintf(stderr, "%s: /etc/hostname.file: %s\n",
+				prog_name, strerror(errno));
+			exit(1);
+		}
+#endif
+	}
+	if (!first_print) printf("\n");
+	exit(0);
+}
+
+void usage()
+{
+	fprintf(stderr,
+		"Usage: %s -[eiah] [-E <eth-device>] [-I <ip-device>]\n", 
+								prog_name);
+	exit(1);
+}
Index: /trunk/minix/commands/simple/id.c
===================================================================
--- /trunk/minix/commands/simple/id.c	(revision 9)
+++ /trunk/minix/commands/simple/id.c	(revision 9)
@@ -0,0 +1,122 @@
+/* id - return uid and gid		Author: John J. Marco */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
+/* 		----- id.c -----					*/
+/* Id - get real and effective user id and group id			*/
+/* Author: John J. Marco						*/
+/*	   pa1343@sdcc15.ucsd.edu					*/
+/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <limits.h>
+
+int main(int argc, char *argv[])
+{
+  struct passwd *pwd;
+  struct group *grp;
+  uid_t ruid, euid;
+  gid_t rgid, egid;
+#if __minix_vmd
+  uid_t suid;
+  gid_t sgid;
+#else
+# define suid ruid
+# define sgid rgid
+#endif
+#if NGROUPS_MAX > 0
+  gid_t groups[NGROUPS_MAX];
+  int ngroups;
+#else
+# define groups (&rgid)
+# define ngroups 0
+#endif
+  int g;
+  int isug;
+  int c, uopt = 0;
+
+#if __minix_vmd
+  get6id(&ruid, &euid, &suid, &rgid, &egid, &sgid);
+  isug = issetugid();
+#else
+  ruid = getuid();
+  euid = geteuid();
+  rgid = getgid();
+  egid = getegid();
+  isug = 0;
+#endif
+#if NGROUPS_MAX > 0
+  ngroups = getgroups(NGROUPS_MAX, groups);
+#endif
+
+  while((c = getopt(argc, argv, "u")) != EOF) {
+	switch(c) {
+		case 'u':
+			uopt = 1;
+			break;
+		default:
+			fprintf(stderr, "%s: unrecognized option\n", argv[0]);
+			return(1);
+	}
+  }
+
+  if(uopt) {
+	printf("%d\n", euid);
+	return 0;
+  }
+
+  if ((pwd = getpwuid(ruid)) == NULL)
+	printf("uid=%d", ruid);
+  else
+	printf("uid=%d(%s)", ruid, pwd->pw_name);
+
+  if ((grp = getgrgid(rgid)) == NULL)
+	printf(" gid=%d", rgid);
+  else
+	printf(" gid=%d(%s)", rgid, grp->gr_name);
+
+  if (euid != ruid)
+	if ((pwd = getpwuid(euid)) != NULL)
+		printf(" euid=%d(%s)", euid, pwd->pw_name);
+	else
+		printf(" euid=%d", euid);
+
+  if (egid != rgid)
+	if ((grp = getgrgid(egid)) != NULL)
+		printf(" egid=%d(%s)", egid, grp->gr_name);
+	else
+		printf(" egid=%d", egid);
+
+  if (suid != euid)
+	if ((pwd = getpwuid(suid)) != NULL)
+		printf(" suid=%d(%s)", suid, pwd->pw_name);
+	else
+		printf(" suid=%d", suid);
+
+  if (sgid != egid)
+	if ((grp = getgrgid(sgid)) != NULL)
+		printf(" sgid=%d(%s)", sgid, grp->gr_name);
+	else
+		printf(" sgid=%d", sgid);
+
+  if (isug) {
+	printf(" issetugid");
+  }
+
+  if (ngroups > 0) {
+	printf(" groups=");
+	for (g = 0; g < ngroups; g++) {
+		if (g > 0) fputc(',', stdout);
+		if ((grp = getgrgid(groups[g])) == NULL)
+			printf("%d", groups[g]);
+		else
+			printf("%d(%s)", groups[g], grp->gr_name);
+	}
+  }
+
+  printf("\n");
+  return(0);
+}
Index: /trunk/minix/commands/simple/ifconfig.c
===================================================================
--- /trunk/minix/commands/simple/ifconfig.c	(revision 9)
+++ /trunk/minix/commands/simple/ifconfig.c	(revision 9)
@@ -0,0 +1,352 @@
+/*
+ifconfig.c
+*/
+
+#define _POSIX_C_SOURCE	2
+
+#include <sys/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <net/netlib.h>
+#include <net/gen/in.h>
+#include <net/gen/ip_io.h>
+#include <net/gen/inet.h>
+
+#if __STDC__
+#define PROTO(x,y) x y
+#else
+#define PROTO(x,y) x()
+#endif
+
+static PROTO (void usage, (void) );
+static PROTO (void set_hostaddr, (int ip_fd, char *host_s, int ins) );
+static PROTO (void set_netmask, (int ip_fd, char *net_s, int ins) );
+static PROTO (void set_mtu, (int ip_fd, char *mtu_s) );
+static PROTO (int check_ipaddrset, (int ip_fd) );
+static PROTO (int check_netmaskset, (int ip_fd) );
+static PROTO (int get_ipconf, (int ip_fd,
+	struct nwio_ipconf *ref_ipconf) );
+PROTO (int main, (int argc, char *argv[]) );
+
+char *prog_name;
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+	char *device_s, *hostaddr_s, *mtu_s, *netmask_s, **arg_s;
+	int ins;
+	int c, ip_fd, ifno;
+	struct nwio_ipconf ipconf;
+	int i_flag, v_flag, a_flag, modify;
+	char *d_arg, *h_arg, *m_arg, *n_arg;
+
+	prog_name= argv[0];
+
+	d_arg= NULL;
+	h_arg= NULL;
+	m_arg= NULL;
+	n_arg= NULL;
+	i_flag= 0;
+	v_flag= 0;
+	a_flag= 0;
+	while ((c= getopt(argc, argv, "?I:h:m:n:iva")) != -1)
+	{
+		switch(c)
+		{
+		case '?':
+			usage();
+		case 'I':
+			if (d_arg)
+				usage();
+			d_arg= optarg;
+			break;
+		case 'h':
+			if (h_arg)
+				usage();
+			h_arg= optarg;
+			break;
+		case 'm':
+			if (m_arg)
+				usage();
+			m_arg= optarg;
+			break;
+		case 'n':
+			if (n_arg)
+				usage();
+			n_arg= optarg;
+			break;
+		case 'i':
+			if (i_flag)
+				usage();
+			i_flag= 1;
+			break;
+		case 'v':
+			if (v_flag)
+				usage();
+			v_flag= 1;
+			break;
+		case 'a':
+			if (a_flag)
+				usage();
+			a_flag= 1;
+			break;
+		default:
+			fprintf(stderr, "%s: getopt failed: '%c'\n", 
+				prog_name, c);
+			exit(1);
+		}
+	}
+	modify = (h_arg != NULL || n_arg != NULL || m_arg != NULL);
+	if (a_flag && modify) usage();
+	if (!modify) v_flag= 1;
+
+	if (modify) setuid(getuid());
+
+	if (optind != argc)
+		usage();
+
+	hostaddr_s= h_arg;
+	mtu_s= m_arg;
+	netmask_s= n_arg;
+	ins= i_flag;
+
+	ifno= 0;
+	do
+	{
+		if (!a_flag) {
+			device_s= d_arg;
+			if (device_s == NULL)
+				device_s= getenv("IP_DEVICE");
+			if (device_s == NULL)
+				device_s= IP_DEVICE;
+		} else {
+			static char device[sizeof("/dev/ip99")];
+
+			sprintf(device, "/dev/ip%d", ifno);
+			device_s= device;
+		}
+
+		ip_fd= open (device_s, O_RDWR);
+		if (ip_fd<0)
+		{
+			if (a_flag && (errno == ENOENT || errno == ENXIO))
+				continue;
+
+			fprintf(stderr, "%s: Unable to open '%s': %s\n", 
+				prog_name, device_s, strerror(errno));
+			exit(1);
+		}
+
+		if (hostaddr_s)
+			set_hostaddr(ip_fd, hostaddr_s, ins);
+
+		if (netmask_s)
+			set_netmask(ip_fd, netmask_s, ins);
+
+		if (mtu_s)
+			set_mtu(ip_fd, mtu_s);
+
+		if (v_flag) {
+			if (!get_ipconf(ip_fd, &ipconf))
+			{
+				if (!a_flag)
+				{
+					fprintf(stderr,
+					"%s: %s: Host address not set\n",
+						prog_name, device_s);
+					exit(1);
+				}
+			}
+			else
+			{
+				printf("%s: address %s", device_s,
+					inet_ntoa(ipconf.nwic_ipaddr));
+
+				if (ipconf.nwic_flags & NWIC_NETMASK_SET)
+				{
+					printf(" netmask %s",
+						inet_ntoa(ipconf.nwic_netmask));
+				}
+#ifdef NWIC_MTU_SET
+				if (ipconf.nwic_mtu)
+					printf(" mtu %u", ipconf.nwic_mtu);
+#endif
+				fputc('\n', stdout);
+			}
+		}
+		close(ip_fd);
+	} while (a_flag && ++ifno < 32);
+	exit(0);
+}
+
+static void set_hostaddr (ip_fd, hostaddr_s, ins)
+int ip_fd;
+char *hostaddr_s;
+int ins;
+{
+	ipaddr_t ipaddr;
+	struct nwio_ipconf ipconf;
+	int result;
+
+	ipaddr= inet_addr (hostaddr_s);
+	if (ipaddr == (ipaddr_t)(-1))
+	{
+		fprintf(stderr, "%s: Invalid host address (%s)\n",
+			prog_name, hostaddr_s);
+		exit(1);
+	}
+	if (ins && check_ipaddrset(ip_fd))
+		return;
+
+	ipconf.nwic_flags= NWIC_IPADDR_SET;
+	ipconf.nwic_ipaddr= ipaddr;
+
+	result= ioctl(ip_fd, NWIOSIPCONF, &ipconf);
+	if (result<0)
+	{
+		fprintf(stderr, "%s: Unable to set IP configuration: %s\n",
+			prog_name, strerror(errno));
+		exit(1);
+	}
+}
+
+static int check_ipaddrset (ip_fd)
+int ip_fd;
+{
+	struct nwio_ipconf ipconf;
+
+	if (!get_ipconf(ip_fd, &ipconf))
+		return 0;
+
+	assert (ipconf.nwic_flags & NWIC_IPADDR_SET);
+
+	return 1;
+}
+
+static int get_ipconf (ip_fd, ref_ipaddr)
+int ip_fd;
+struct nwio_ipconf *ref_ipaddr;
+{
+	int flags;
+	int error, result;
+	nwio_ipconf_t ipconf;
+
+	flags= fcntl(ip_fd, F_GETFL);
+	fcntl(ip_fd, F_SETFL, flags | O_NONBLOCK);
+
+	result= ioctl (ip_fd, NWIOGIPCONF, &ipconf);
+	error= errno;
+
+	fcntl(ip_fd, F_SETFL, flags);
+
+	if (result <0 && error != EAGAIN)
+	{
+		errno= error;
+		fprintf(stderr, "%s: Unable to get IP configuration: %s\n",
+			prog_name, strerror(errno));
+		exit(1);
+	}
+	if (result == 0)
+	{
+		*ref_ipaddr = ipconf;
+	}
+	return result>=0;
+}
+
+static void usage()
+{
+	fprintf(stderr,
+	"Usage: %s [-I ip-device] [-h ipaddr] [-n netmask] [-m mtu] [-iva]\n",
+		prog_name);
+	exit(1);
+}
+
+static void set_netmask (ip_fd, netmask_s, ins)
+int ip_fd;
+char *netmask_s;
+int ins;
+{
+	ipaddr_t netmask;
+	struct nwio_ipconf ipconf;
+	int result;
+
+	netmask= inet_addr (netmask_s);
+	if (netmask == (ipaddr_t)(-1))
+	{
+		fprintf(stderr, "%s: Invalid netmask (%s)\n",
+			prog_name, netmask_s);
+		exit(1);
+	}
+	if (ins && check_netmaskset(ip_fd))
+		return;
+
+	ipconf.nwic_flags= NWIC_NETMASK_SET;
+	ipconf.nwic_netmask= netmask;
+
+	result= ioctl(ip_fd, NWIOSIPCONF, &ipconf);
+	if (result<0)
+	{
+		fprintf(stderr, "%s: Unable to set IP configuration: %s\n",
+			prog_name, strerror(errno));
+		exit(1);
+	}
+}
+
+static void set_mtu (ip_fd, mtu_s)
+int ip_fd;
+char *mtu_s;
+{
+	ipaddr_t netmask;
+	int result;
+	long mtu;
+	char *check;
+	struct nwio_ipconf ipconf;
+
+	mtu= strtol (mtu_s, &check, 0);
+	if (check[0] != '\0')
+	{
+		fprintf(stderr, "%s: Invalid mtu (%s)\n",
+			prog_name, mtu_s);
+		exit(1);
+	}
+
+#ifdef NWIC_MTU_SET
+	ipconf.nwic_flags= NWIC_MTU_SET;
+	ipconf.nwic_mtu= mtu;
+
+	result= ioctl(ip_fd, NWIOSIPCONF, &ipconf);
+	if (result<0)
+	{
+		fprintf(stderr, "%s: Unable to set IP configuration: %s\n",
+			prog_name, strerror(errno));
+		exit(1);
+	}
+#endif
+}
+
+static int check_netmaskset (ip_fd)
+int ip_fd;
+{
+	struct nwio_ipconf ipconf;
+
+	if (!get_ipconf(ip_fd, &ipconf))
+	{
+		fprintf(stderr,
+"%s: Unable to determine if netmask is set, please set IP address first\n",
+			prog_name);
+		exit(1);
+	}
+
+	return (ipconf.nwic_flags & NWIC_NETMASK_SET);
+}
+
+/*
+ * $PchId: ifconfig.c,v 1.7 2001/02/21 09:19:52 philip Exp $
+ */
Index: /trunk/minix/commands/simple/ifdef.c
===================================================================
--- /trunk/minix/commands/simple/ifdef.c	(revision 9)
+++ /trunk/minix/commands/simple/ifdef.c	(revision 9)
@@ -0,0 +1,504 @@
+/* ifdef - remove #ifdefs		Author: Warren Toomey */
+
+/* Copyright 1989 by Warren Toomey	wkt@cs.adfa.oz.au[@uunet.uu.net]
+ *
+ * You may freely copy or distribute this code as long as this notice
+ * remains intact.
+ *
+ * You may modify this code, as long as this notice remains intact, and
+ * you add another notice indicating that the code has been modified.
+ *
+ * You may NOT sell this code or in any way profit from this code without
+ * prior agreement from the author.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+/* Definition of structures and constants used in ifdef.c  */
+
+/* Types of symbols */
+#define DEF	  1		/* Symbol is defined    */
+#define UNDEF	  2		/* Symbol isn't defined */
+#define IGN	  3		/* Ignore this symbol unless defined */
+
+/* Redef mode values */
+#define MUTABLE   1		/* Symbol can change defined <-> undefined */
+#define IMMUTABLE 2		/* Symbol can't change as above            */
+
+/* Processing modes */
+#define NO	0		/* Don't process */
+#define YES	1		/* Process */
+
+/* Ignore (IGN), ignore but process */
+struct DEFINE {
+  char *symbol;			/* SLL of defined symbols. The redef  */
+  char type;			/* field indicates if this symbol can */
+  char redef;			/* change from defined <-> undefined. */
+  struct DEFINE *next;		/* Type is DEF or UNDEF.	      */
+};
+
+/* Global variables & structures */
+FILE *zin;			/* Input file for processing  */
+struct DEFINE *defptr;		/* Defined symbols SLL        */
+struct DEFINE *defend;		/* Ptr to last node in defptr */
+struct DEFINE *deftemp;		/* Ptr to last found node     */
+int line = 1;			/* Current line number        */
+int table = 0;			/* Don't normally want a table */
+
+extern int optind;
+extern char *optarg;
+
+/* Prototypes. */
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(char fgetarg, (FILE *stream, char *cbuf));
+_PROTOTYPE(int find, (char *symd));
+_PROTOTYPE(void defit, (char *sym, int redef, int typed));
+_PROTOTYPE(void stop, (void));
+_PROTOTYPE(void gotoeoln, (void));
+_PROTOTYPE(void prteoln, (void));
+_PROTOTYPE(void printtable, (void));
+_PROTOTYPE(char getendif, (void));
+_PROTOTYPE(void gettable, (void));
+_PROTOTYPE(void parse, (void));
+_PROTOTYPE(void usage, (void));
+
+#ifdef __STDC__
+char fgetarg ( FILE *stream , char *cbuf )
+#else
+char fgetarg(stream, cbuf)	/* Get next arg from file into cbuf, */
+FILE *stream;			/* returning the character that      */
+char *cbuf;			/* terminated it. Cbuf returns 0     */
+#endif
+{				/* if no arg. EOF is returned if no  */
+  int ch;			/* args left in file.                */
+  int i;
+
+  i = 0;
+  cbuf[i] = 0;
+
+  while (((ch = fgetc(stream)) == ' ') || (ch == '\t') || (ch == '\n'))
+	if (ch == '\n') return(ch);	/* Bypass leading */
+					/* Whitespace     */
+  if (feof(stream)) return(EOF);
+
+  cbuf[i++] = ch;
+
+  while (((ch = fgetc(stream)) != ' ') && (ch != '\t') && (ch != '\n'))
+	cbuf[i++] = ch;			/* Get the argument */
+
+  cbuf[i] = 0;
+  return(ch);
+}
+
+
+#ifdef __STDC__
+int find ( char *sym )
+#else
+int find(sym)
+char *sym;
+#endif
+{				/* Return DEF if defined else UNDEF */
+
+  deftemp = defptr;
+  while (deftemp) {			/* Search for the symbol */
+	if (!strcmp(deftemp->symbol, sym))
+		return(deftemp->type);	/* Setting up the type */
+	deftemp = deftemp->next;
+  }
+  return(0);
+}
+
+
+
+#define Define(x,y)	defit(x,y,DEF)
+#define Undefine(x,y)	defit(x,y,UNDEF)
+#define Ignore(x,y)	defit(x,y,IGN)
+
+#ifdef __STDC__
+void defit ( char *sym , int redef , int type )
+#else
+void defit(sym, redef, type)	/* Add symbol to the define list */
+char *sym;
+char redef;			/* Mode: MUTABLE etc      */
+char type;			/* Type: DEF, UNDEF, IGN  */
+#endif
+{
+  struct DEFINE *temp;
+  char c;
+
+  c = find(sym);		/* First try finding the symbol */
+  if (type == c) return;	/* Return if already declared */
+  if (c) {			/* We have to move if from DEF <-> UNDEF */
+	if (deftemp->redef == IMMUTABLE)
+		return;
+	else {
+		deftemp->type = type;
+		deftemp->redef = redef;
+	}
+  } else {			/* We must create a struct & add it */
+				/* Malloc room for the struct */
+	if ((temp = (struct DEFINE *)malloc(sizeof(struct DEFINE))) == NULL) {
+		(void)fprintf(stderr, "ifdef: could not malloc\n");
+		exit(1);
+	}
+
+					/* Malloc room for symbol */
+	if ((temp->symbol = (char *)malloc(strlen(sym) + 1)) == NULL) {
+		(void)fprintf(stderr, "ifdef: could not malloc\n");
+		exit(1);
+	}
+	(void)strcpy(temp->symbol, sym); /* Copy symbol into struct      */
+	temp->redef = redef;		/* and set its redef mode too   */
+	temp->type = type;		/* as well as making it defined */
+
+
+					/* Now add to the SLL */
+	if (defptr == NULL)		/* If first node set  */
+		defptr = temp;		/* the pointers to it */
+	else
+		defend->next = temp;	/* else add it to the */
+	defend = temp;			/* end of the list.   */
+  }
+}
+
+
+
+#ifdef __STDC__
+void stop ( void )
+#else
+void stop()
+#endif
+{				/* Stop: Tidy up at EOF */
+  if (table) printtable();
+  (void)fclose(zin);
+  exit(0);
+}
+
+#define Goto	{ line++; if (ch!='\n') gotoeoln(); }
+#define Print	{ line++; if (ch!='\n') prteoln();  }
+
+#ifdef __STDC__
+void gotoeoln ( void )
+#else
+void gotoeoln()			/* Go to the end of the line */
+#endif
+{
+  int ch;
+  while ((ch = fgetc(zin)) != '\n')
+	if (ch == EOF) stop();
+}
+
+
+#ifdef __STDC__
+void prteoln ( void )
+#else
+void prteoln()			/* Print to the end of the line */
+#endif
+{
+  int ch;
+  while ((ch = fgetc(zin)) != '\n')
+	if (ch == EOF)
+		stop();
+	else
+		(void)putchar(ch);
+  (void)putchar('\n');
+}
+
+
+#ifdef __STDC__
+void printtable ( void )
+#else
+void printtable()		/* Print the defines in the SLL */
+#endif
+{
+  struct DEFINE *temp;
+
+  (void)printf("Defined\n\n");
+
+  temp = defptr;
+  while (temp) {
+	if (temp->type == DEF) (void)printf("%s\n", temp->symbol);
+	temp = temp->next;
+  }
+
+  (void)printf("\n\nUndefined\n\n");
+
+  temp = defptr;
+  while (temp) {
+	if (temp->type == UNDEF) (void)printf("%s\n", temp->symbol);
+	temp = temp->next;
+  }
+}
+
+#ifdef __STDC__
+char getendif ( void )
+#else
+char getendif()
+#endif
+{				/* Find matching endif when ignoring */
+  char word[80];		/* Buffer for symbols */
+  int ch;
+  int skip;			/* Number of skipped #ifdefs */
+
+  skip = 1;
+
+  while (1) {
+			/* Scan through the file looking for starting lines */
+	if ((ch = fgetc(zin)) == EOF)
+		stop();		/* Get first char on the line */
+	if (ch != '#') {	/* If not a # ignore line     */
+		(void)putchar(ch);
+		Print;
+		continue;
+	}
+	ch = fgetarg(zin, word);	/* Get the word after the # */
+
+	if (!strcmp(word, "ifdef") || !strcmp(word, "ifndef")) skip++;
+						/* Keep track of ifdefs & */
+	if (!strcmp(word, "endif")) skip--;	/* endifs		  */
+
+	(void)printf("#%s%c", word, ch);	/* Print the line out 	  */
+	Print;
+	if (!skip) return('\n');	/* If matching endif, return */
+  }
+}
+
+
+#ifdef __STDC__
+void gettable ( void )
+#else
+void gettable()			/* Get & print a table of defines etc.  */
+#endif
+{
+
+  char word[80];		/* Buffer for symbols */
+  int ch;
+
+  while (1) {
+			/* Scan through the file looking for starting lines */
+	if ((ch = fgetc(zin)) == EOF)
+		stop();		/* Get first char on the line */
+	if (ch != '#') {	/* If not a # ignore line     */
+		Goto;
+		continue;
+	}
+	ch = fgetarg(zin, word);	/* Get the word after the # */
+
+	if (!strcmp(word, "define")) {		/* Define: Define the */
+		ch = fgetarg(zin, word);	/* symbol, and goto   */
+		Define(word, MUTABLE);		/* the end of line    */
+		Goto;
+		continue;
+	}
+	if (!strcmp(word, "undef")) {		/* Undef: Undefine the */
+		ch = fgetarg(zin, word);	/* symbol, and goto    */
+		Undefine(word, MUTABLE);	/* the end of line     */
+		Goto;
+		continue;
+	}					/* Ifdef:            */
+	if (!strcmp(word, "ifdef") || !strcmp(word, "ifndef")) {
+		ch = fgetarg(zin, word);	/* Get the symbol */
+		if (find(word) != DEF)
+			Undefine(word, MUTABLE);	/* undefine it */
+		Goto;
+		continue;
+	}
+	Goto;				/* else ignore the line */
+  }
+}
+
+
+
+#ifdef __STDC__
+void parse ( void )
+#else
+void parse()
+#endif
+{				/* Parse & remove ifdefs from C source */
+  char word[80];		/* Buffer for symbols */
+  int ch;
+  int proc;			/* Should we be processing this bit?    */
+  int skip;			/* Number of skipped #ifdefs		 */
+
+  proc = 1;
+  skip = 0;
+
+  while (1) {
+			/* Scan through the file looking for starting lines */
+	if ((ch = fgetc(zin)) == EOF)
+		stop();		/* Get first char on the line */
+	if (ch != '#')
+		if (proc) {	/* If not # and  we're processing */
+			(void)putchar(ch); /* then print the line */
+			Print;
+			continue;
+		} else {
+			Goto;	/* else just skip the line  */
+			continue;
+		}
+
+	ch = fgetarg(zin, word);	/* Get the word after the # */
+
+	if (!strcmp(word, "define") && proc) {	/* Define: Define the */
+		ch = fgetarg(zin, word);	/* symbol, and goto   */
+		Define(word, MUTABLE);		/* the end of line    */
+		(void)printf("#define %s%c", word, ch);
+		Print;
+		continue;
+	}
+	if (!strcmp(word, "undef") && proc) {	/* Undef: Undefine the */
+		ch = fgetarg(zin, word);	/* symbol, and goto    */
+		Undefine(word, MUTABLE);	/* the end of line     */
+		(void)printf("#undef %s%c", word, ch);
+		Print;
+		continue;
+	}
+	if (!strcmp(word, "if")) {	/* If: we cannot handle these */
+		if (!proc)		/* at the moment, so just */
+			skip++;		/* treat them as an ignored */
+		else {			/* definition */
+			(void)printf("#%s%c",word,ch);
+			Print;
+			ch = getendif();	/* Get matching endif */
+			continue;
+		     	}
+	}
+	if (!strcmp(word, "ifdef")) {	/* Ifdef:	     */
+		if (!proc)		/* If not processing */
+			skip++;		/* skip it           */
+		else {
+			ch = fgetarg(zin, word); /* Get the symbol */
+			switch (find(word)) {
+			    case DEF:
+				break;
+			    case IGN:
+				(void)printf("#ifdef %s%c", word, ch);
+				Print;
+				ch = getendif(); /* Get matching endif */
+				break;
+						/* If symbol undefined */
+			    default:
+				Undefine(word, MUTABLE); /* undefine it */
+				proc = 0;	/* & stop processing */
+			}
+		}
+		Goto;
+		continue;
+	}
+	if (!strcmp(word, "ifndef")) {
+		/* Ifndef: */
+		if (!proc)	/* If not processing */
+			skip++;	/* skip the line     */
+		else {
+			ch = fgetarg(zin, word); /* Get the symbol */
+			switch (find(word)) {	/* If defined, stop */
+			    case DEF:
+				proc = 0;	/* processing       */
+				break;
+			    case IGN:
+				(void)printf("#ifdef %s%c", word, ch);
+				Print;
+				ch = getendif(); /* Get matching endif */
+				break;
+			}
+		}
+		Goto;
+		continue;
+	}
+	if (!strcmp(word, "else") && !skip) {	/* Else: Flip processing */
+		proc = !proc;
+		Goto;
+		continue;
+	}
+	if (!strcmp(word, "endif")) {	/* Endif: If no skipped   */
+					/* ifdefs turn processing */
+		if (!skip)		/* on, else decrement the */
+			proc = 1;	/* number of skips        */
+		else
+			skip--;
+		Goto;
+		continue;
+	}
+		/* The word fails all of the above tests, so if we're */
+		/* processing, print the line. */
+	if (proc) {
+		(void)printf("#%s%c", word, ch);
+		Print;
+	} else
+		Goto;
+  }
+}
+
+
+#ifdef __STDC__
+void usage ( void )
+#else
+void usage()
+#endif
+{
+  (void)fprintf(stderr, "Usage: ifdef [-t] [-Dsymbol] [-dsymbol] [-Usymbol] [-Isymbol] <file>\n");
+  exit(0);
+}
+
+
+#ifdef __STDC__
+int main(int argc , char *argv [])
+#else
+int main(argc, argv)
+int argc;
+char *argv[];
+#endif
+{
+  char sym[80];			/* Temp symbol storage */
+  int c;
+
+  if (argc == 1) usage();	/* Catch the curious user	 */
+  while ((c = getopt(argc, argv, "tD:d:U:I:")) != EOF) {
+	switch (c) {
+	    case 't':
+		table = 1;	/* Get the various options */
+		break;
+
+	    case 'd':
+		(void)strcpy(sym, optarg);
+		Define(sym, MUTABLE);
+		break;
+
+	    case 'D':
+		(void)strcpy(sym, optarg);
+		Define(sym, IMMUTABLE);
+		break;
+
+	    case 'U':
+		(void)strcpy(sym, optarg);
+		Undefine(sym, IMMUTABLE);
+		break;
+
+	    case 'I':
+		(void)strcpy(sym, optarg);
+		Ignore(sym, IMMUTABLE);
+		break;
+
+	    default:	usage();
+	}
+  }
+
+  zin = stdin;		/* If a C file is named */
+			/* Open stdin with it */
+  if (*argv[argc - 1] != '-') {
+	(void)fclose(zin);
+	if ((zin = fopen(argv[argc - 1], "r")) == NULL) {
+		perror("ifdef");
+		exit(1);
+	}
+  }
+  if (table)
+	gettable();		/* Either generate a table or    */
+  else
+	parse();		/* parse & replace with the file */
+  return(0);
+}
Index: /trunk/minix/commands/simple/in.fingerd.c
===================================================================
--- /trunk/minix/commands/simple/in.fingerd.c	(revision 9)
+++ /trunk/minix/commands/simple/in.fingerd.c	(revision 9)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)in.fingerd.c 1.1 87/12/21 SMI"; /* from UCB 5.1 6/6/85 */
+#endif /* not lint */
+
+/*
+ * Finger server.
+ */
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main _ARGS(( int argc, char *argv[] ));
+void fatal _ARGS(( char *prog, char *s ));
+
+int main(argc, argv)
+	char *argv[];
+{
+	register char *sp;
+	char line[512];
+	int i, p[2], pid, status;
+	FILE *fp;
+	char *av[4];
+
+	line[0] = '\0';
+	fgets(line, sizeof(line), stdin);
+	sp = line + strlen(line);
+	if (sp > line && *--sp == '\n') *sp = '\0';
+	sp = line;
+	av[0] = "finger";
+	i = 1;
+	while (1) {
+		while (isspace(*sp))
+			sp++;
+		if (!*sp)
+			break;
+		if (*sp == '/' && (sp[1] == 'W' || sp[1] == 'w')) {
+			sp += 2;
+			av[i++] = "-l";
+		}
+		if (*sp && !isspace(*sp)) {
+			av[i++] = sp;
+			while (*sp && !isspace(*sp))
+				sp++;
+			*sp = '\0';
+		}
+	}
+	av[i] = 0;
+	if (pipe(p) < 0)
+		fatal(argv[0], "pipe");
+	if ((pid = fork()) == 0) {
+		close(p[0]);
+		if (p[1] != 1) {
+			dup2(p[1], 1);
+			close(p[1]);
+		}
+		execv("/usr/bin/finger", av);
+		printf("No finger program found\n");
+		fflush(stdout);
+		_exit(1);
+	}
+	if (pid == -1)
+		fatal(argv[0], "fork");
+	close(p[1]);
+	if ((fp = fdopen(p[0], "r")) == NULL)
+		fatal(argv[0], "fdopen");
+	while ((i = getc(fp)) != EOF) {
+		if (i == '\n')
+			putchar('\r');
+		putchar(i);
+	}
+	fclose(fp);
+	while ((i = wait(&status)) != pid && i != -1)
+		;
+	return(0);
+}
+
+void fatal(prog, s)
+	char *prog, *s;
+{
+
+	fprintf(stderr, "%s: ", prog);
+	perror(s);
+	exit(1);
+}
Index: /trunk/minix/commands/simple/in.rshd.c
===================================================================
--- /trunk/minix/commands/simple/in.rshd.c	(revision 9)
+++ /trunk/minix/commands/simple/in.rshd.c	(revision 9)
@@ -0,0 +1,445 @@
+/*
+in.rshd.c
+*/
+
+/*
+	main channel:
+
+	back channel\0
+	remuser\0
+	locuser\0
+	command\0
+	data
+
+	back channel:
+	signal\0
+
+*/
+
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pwd.h>
+#include <grp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/netdb.h>
+#include <net/gen/socket.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/hton.h>
+#include <net/netlib.h>
+
+#define DEBUG 0
+
+#if DEBUG
+#define where() fprintf(stderr, "%s, %d: ", __FILE__, __LINE__)
+#endif
+
+char cmdbuf[_POSIX_ARG_MAX+1], locuser[16], remuser[16];
+extern char **environ;
+char username[20]="USER=";
+char homedir[64]="HOME=";
+char shell[64]="SHELL=";
+char tz[1024]="TZ=";
+char *envinit[]= {homedir, shell, username, tz, "PATH=:/bin:/usr/bin", 0};
+char *prog_name;
+char buffer[PIPE_BUF];
+
+#if __STDC__
+#define PROTO(func, args) func args
+#else
+#define PROTO(func, args) func ()
+#endif
+
+PROTO (int main, (int argc, char *argv[]));
+PROTO (void getstr, (char*buf, int cnt, char *err));
+PROTO (void close_on_exec, (int fd));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+	int result, result1;
+	nwio_tcpconf_t tcpconf, err_tcpconf;
+	nwio_tcpcl_t tcpconnopt;
+	nwio_tcpatt_t tcpattachopt;
+	tcpport_t tcpport;
+	tcpport_t err_port;
+	int err_fd, pds[2];
+	pid_t pid, pid1, new_pg;
+#if USEATTACH
+	int err2_fd;
+#endif
+	struct passwd *pwent;
+	char *cp, *buff_ptr, *TZ;
+	char sig;
+
+	prog_name= argv[0];
+	if (argc != 1)
+	{
+		fprintf(stderr, "%s: wrong number of arguments (%d)\n",
+			prog_name, argc);
+		exit(1);
+	}
+
+	signal(SIGINT, SIG_DFL);
+	signal(SIGQUIT, SIG_DFL);
+	signal(SIGTERM, SIG_DFL);
+
+#if DEBUG
+ { where(); fprintf(stderr, "\n"); }
+#endif
+	result= ioctl (0, NWIOGTCPCONF, &tcpconf);
+	if (result<0)
+	{
+		fprintf(stderr, "%s: ioctl(NWIOGTCPCONF)= %d : %s\n", 
+			prog_name, errno, strerror(errno));
+		exit(1);
+	}
+#if DEBUG
+ { where(); fprintf(stderr, "\n"); }
+#endif
+
+	tcpport= ntohs(tcpconf.nwtc_remport);
+	if (tcpport >= TCPPORT_RESERVED || tcpport < TCPPORT_RESERVED/2)
+	{
+		printf("\1%s: unprotected port (%d)\n", prog_name, tcpport);
+		exit(1);
+	}
+	alarm(60);
+	err_port= 0;
+	for (;;)
+	{
+		char c;
+		result= read(0, &c, 1);
+		if (result <0)
+		{
+			fprintf(stderr, "%s: read= %d : %s\n", prog_name, 
+				errno, strerror(errno));
+		}
+		if (result<1)
+			exit(1);
+		if (c == 0)
+			break;
+		err_port= err_port*10 + c - '0';
+	}
+	alarm(0);
+	if (err_port != 0)
+	{
+		int n, pid, lport;
+
+		pid= getpid();
+		lport= 1;
+		do {
+			lport= (lport << 1) | (pid & 1);
+			pid >>= 1;
+		} while (lport < TCPPORT_RESERVED/2);
+
+		n= TCPPORT_RESERVED/2;
+		do
+		{
+			if (--lport < TCPPORT_RESERVED/2)
+				lport= TCPPORT_RESERVED-1;
+			err_fd= open ("/dev/tcp", O_RDWR);
+			if (err_fd<0)
+			{
+				fprintf(stderr, "%s: open= %d : %s\n", 
+					prog_name, errno, strerror(errno));
+				exit(1);
+			}
+			close_on_exec(err_fd);
+			err_tcpconf.nwtc_flags= NWTC_LP_SET | NWTC_SET_RA |
+				NWTC_SET_RP | NWTC_EXCL;
+			err_tcpconf.nwtc_locport= htons(lport);
+			err_tcpconf.nwtc_remport= htons(err_port);
+			err_tcpconf.nwtc_remaddr= tcpconf.nwtc_remaddr;
+
+#if DEBUG
+ { where(); fprintf(stderr, "\n"); }
+#endif
+			result= ioctl (err_fd, NWIOSTCPCONF, &err_tcpconf);
+			if (result == 0) break;
+			if (errno != EADDRINUSE)
+			{
+				fprintf(stderr, 
+					"%s: ioctl(NWIOSTCPCONF)= %d : %s\n",
+					prog_name, errno, strerror(errno));
+				exit(1);
+			}
+			close(err_fd);
+		} while (--n > 0);
+		if (n == 0)
+		{
+			printf("\1can't get stderr port\n");
+			exit(1);
+		}
+
+		err_tcpconf.nwtc_flags= NWTC_SHARED;
+#if DEBUG
+{ where(); fprintf(stderr, "\n"); }
+#endif
+		result= ioctl (err_fd, NWIOSTCPCONF, &err_tcpconf);
+		if (result<0)
+		{
+			fprintf(stderr, 
+				"%s: ioctl(NWIOSTCPCONF)= %d : %s\n",
+				prog_name, errno, strerror(errno));
+			exit(1);
+		}
+#if DEBUG
+{ where(); fprintf(stderr, "\n"); }
+#endif
+		tcpconnopt.nwtcl_flags= 0;
+
+		n= 20;
+		for (;;)
+		{
+#if DEBUG
+{ where(); fprintf(stderr, "\n"); }
+#endif
+			result= ioctl (err_fd, NWIOTCPCONN, &tcpconnopt);
+			if (result == 0) break;
+			if (errno != EAGAIN && errno != ECONNREFUSED)
+			{
+				fprintf(stderr,
+					"%s: ioctl(NWIOTCPCONN)= %d : %s\n",
+					prog_name, errno, strerror(errno));
+				exit(1);
+			}
+			if (--n == 0) break;
+			sleep(1);
+#if DEBUG
+{ where(); fprintf(stderr, "\n"); }
+#endif
+		}
+#if USEATTACH
+		err2_fd= open ("/dev/tcp", O_RDWR);
+		close_on_exec(err2_fd);
+		if (err2_fd<0)
+		{
+			fprintf(stderr, "%s: open= %d : %s\n", errno,
+				prog_name, strerror(errno));
+			exit(1);
+		}
+#if DEBUG
+ { where(); fprintf(stderr, "\n"); }
+#endif
+		result= ioctl (err2_fd, NWIOSTCPCONF, &err_tcpconf);
+		if (result<0)
+		{
+			fprintf(stderr, "%s: ioctl(NWIOSTCPCONF)= %d : %s\n",
+				prog_name, errno, strerror(errno));
+			exit(1);
+		}
+#if DEBUG
+ { where(); fprintf(stderr, "\n"); }
+#endif
+		tcpattachopt.nwta_flags= 0;
+#if DEBUG
+ { where(); fprintf(stderr, "\n"); }
+#endif
+		result= ioctl (err2_fd, NWIOTCPATTACH, &tcpattachopt);
+		if (result<0)
+		{
+			fprintf(stderr, "%s: ioctl(NWIOTCPATTACH)= %d : %s\n",
+				prog_name, errno, strerror(errno));
+			exit(1);
+		}
+#if DEBUG
+ { where(); fprintf(stderr, "\n"); }
+#endif
+#endif
+	}
+	getstr(remuser, sizeof(remuser), "remuser");
+	getstr(locuser, sizeof(locuser), "locuser");
+	getstr(cmdbuf, sizeof(cmdbuf), "cmdbuf");
+	setpwent();
+	pwent= getpwnam(locuser);
+	if (!pwent)
+	{
+		printf("\1Login incorrect.\n");
+		exit(1);
+	}
+	endpwent();
+	if (chdir(pwent->pw_dir) < 0)
+	{
+		chdir("/");
+	}
+#if DEBUG
+ { where(); fprintf(stderr, "calling iruserok(%s, %d, %s, %s)\n", 
+	inet_ntoa(tcpconf.nwtc_remaddr), 0, remuser, locuser); }
+#endif
+	if (iruserok(tcpconf.nwtc_remaddr, 0, remuser, locuser) < 0)
+	{
+		printf("\1Permission denied.\n");
+		exit(1);
+	}
+	if (err_port)
+	{
+		/* Let's go to a different process group. */
+		new_pg= setsid();
+		pid= fork();
+		if (pid<0)
+		{
+			if (errno != EAGAIN)
+			{
+				fprintf(stderr, "%s: fork()= %d : %s\n",
+					prog_name, errno, strerror(errno));
+			}
+			printf("\1Try again.\n");
+			exit(1);
+		}
+		if (pid)
+		{
+			close(0);	/* stdin */
+			close(1);	/* stdout */
+#if USEATTACH
+			close(err_fd);	/* stderr for shell */
+#endif
+			dup2(2,0);
+			dup2(2,1);
+			for (;;)
+			{
+#if !USEATTACH
+				if (read(err_fd, &sig, 1) <= 0)
+#else
+				if (read(err2_fd, &sig, 1) <= 0)
+#endif
+				{
+#if 0
+					printf("read failed: %d\n", errno);
+#endif
+					exit(0);
+				}
+				pid= 0;
+#if 0
+				printf("killing %d with %d\n", -new_pg, sig);
+#endif
+				kill(-new_pg, sig);
+			}
+		}
+#if USEATTACH
+		close(err2_fd);	/* signal channel for parent */
+#endif
+		result= pipe(pds);
+		if (result<0)
+		{
+			printf("\1Can't make pipe\n");
+			kill(getppid(), SIGTERM);
+			exit(1);
+		}
+		pid1= fork();
+		if (pid1<0)
+		{
+			if (errno != EAGAIN)
+			{
+				fprintf(stderr, "%s: fork()= %d : %s\n",
+					prog_name, errno, strerror(errno));
+			}
+			printf("\1Try again.\n");
+			kill(-new_pg, SIGTERM);
+			exit(1);
+		}
+		if (pid1)
+		{
+			close(pds[1]);	/* write side of pipe */
+			for (;;)
+			{
+				result= read(pds[0], buffer, sizeof(buffer));
+				if (result<=0)
+				{
+					kill(pid, SIGTERM);
+					exit(0);
+				}
+				buff_ptr= buffer;
+				while (result>0)
+				{
+					result1= write (err_fd, buff_ptr,
+						result);
+					if (result1 <= 0)
+					{
+						fprintf(stderr, 
+						"%s: write()= %d : %s\n",
+							prog_name, errno,
+							strerror(errno));
+						kill(-new_pg, SIGTERM);
+						exit(1);
+					}
+					result -= result1;
+				}
+			}
+		}
+		close(err_fd);	/* file descriptor for error channel */
+		close (pds[0]);	/* read side of pipe */
+		dup2(pds[1], 2);
+		close (pds[1]);	/* write side of pipe */
+	}
+	if (*pwent->pw_shell == '\0')
+		pwent->pw_shell= "/bin/sh";
+#if __minix_vmd
+	initgroups(pwent->pw_name, pwent->pw_gid);
+#endif
+	setgid(pwent->pw_gid);
+	setuid(pwent->pw_uid);
+	TZ=getenv("TZ");
+	environ= envinit;
+	strncat(homedir, pwent->pw_dir, sizeof(homedir)-6);
+	strncat(shell, pwent->pw_shell, sizeof(shell)-7);
+	strncat(username, pwent->pw_name, sizeof(username)-6);
+	if (TZ)
+		strncat(tz, TZ, sizeof(tz)-4);
+	else
+		envinit[3]= NULL;
+
+	cp= strrchr(pwent->pw_shell, '/');
+	if (cp)
+		cp++;
+	else
+		cp= pwent->pw_shell;
+
+	if (!err_port)
+		dup2(1, 2);
+	write(1, "\0", 1);
+
+	execl(pwent->pw_shell, cp, "-c", cmdbuf, 0);
+	close(2);
+	open("/dev/tty", O_RDWR);
+	fprintf(stderr, "%s: execl(%s, %s, .., %s)= %d : %s\n", prog_name,
+		pwent->pw_shell, cp, cmdbuf, errno, strerror(errno));
+	kill(getppid(), SIGTERM);
+	exit(1);
+}
+
+void getstr(buf, cnt, err)
+char *buf;
+int cnt;
+char *err;
+{
+	char c;
+
+	do
+	{
+		if (read(0, &c, 1) != 1)
+			exit(1);
+		*buf++ = c;
+		if (--cnt == 0)
+		{
+			printf("\1%s too long", err);
+			exit(1);
+		}
+	} while (c != 0);
+}
+
+void close_on_exec(fd)
+int fd;
+{
+	(void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+}
Index: /trunk/minix/commands/simple/install.c
===================================================================
--- /trunk/minix/commands/simple/install.c	(revision 9)
+++ /trunk/minix/commands/simple/install.c	(revision 9)
@@ -0,0 +1,599 @@
+/*	install 1.11 - install files.			Author: Kees J. Bot
+ *								21 Feb 1993
+ */
+#define nil 0
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <a.out.h>
+#include <limits.h>
+#include <pwd.h>
+#include <grp.h>
+#include <utime.h>
+#include <signal.h>
+
+/* First line used on a self-decompressing executable. */
+char ZCAT[]=	"#!/usr/bin/zexec /usr/bin/zcat\n";
+char GZCAT[]=	"#!/usr/bin/zexec /usr/bin/gzcat\n";
+
+/* Compression filters. */
+char *COMPRESS[]=	{ "compress", nil };
+char *GZIP[]=		{ "gzip", "-#", nil };
+
+int excode= 0;		/* Exit code. */
+
+void report(char *label)
+{
+	if (label == nil || label[0] == 0)
+		fprintf(stderr, "install: %s\n", strerror(errno));
+	else
+		fprintf(stderr, "install: %s: %s\n", label, strerror(errno));
+	excode= 1;
+}
+
+void fatal(char *label)
+{
+	report(label);
+	exit(1);
+}
+
+void *allocate(void *mem, size_t size)
+/* Safe malloc/realloc. */
+{
+	mem= mem == nil ? malloc(size) : realloc(mem, size);
+
+	if (mem == nil) fatal(nil);
+	return mem;
+}
+
+void deallocate(void *mem)
+{
+	if (mem != nil) free(mem);
+}
+
+int lflag= 0;		/* Make a hard link if possible. */
+int cflag= 0;		/* Copy if you can't link, otherwise symlink. */
+int dflag= 0;		/* Create a directory. */
+int strip= 0;		/* Strip the copy. */
+char **compress= nil;	/* Compress utility to make a compressed executable. */
+char *zcat= nil;	/* Line one to decompress. */
+
+long stack= -1;		/* Amount of heap + stack. */
+int wordpow= 1;		/* Must be multiplied with wordsize ** wordpow */
+			/* So 8kb for an 8086 and 16kb for the rest. */
+
+pid_t filter(int fd, char **command)
+/* Let a command filter the output to fd. */
+{
+	pid_t pid;
+	int pfd[2];
+
+	if (pipe(pfd) < 0) {
+		report("pipe()");
+		return -1;
+	}
+
+	switch ((pid= fork())) {
+	case -1:
+		report("fork()");
+		return -1;
+	case 0:
+		/* Run the filter. */
+		dup2(pfd[0], 0);
+		dup2(fd, 1);
+		close(pfd[0]);
+		close(pfd[1]);
+		close(fd);
+		signal(SIGPIPE, SIG_DFL);
+		execvp(command[0], command);
+		fatal(command[0]);
+	}
+	/* Connect fd to the pipe. */
+	dup2(pfd[1], fd);
+	close(pfd[0]);
+	close(pfd[1]);
+	return pid;
+}
+
+int mkdirp(char *dir, int mode, int owner, int group)
+/* mkdir -p dir */
+{
+	int keep;
+	char *sep, *pref;
+
+	sep= dir;
+	while (*sep == '/') sep++;
+	
+	if (*sep == 0) {
+		errno= EINVAL;
+		return -1;
+	}
+
+	do {
+		while (*sep != '/' && *sep != 0) sep++;
+		pref= sep;
+		while (*sep == '/') sep++;
+
+		keep= *pref; *pref= 0;
+
+		if (strcmp(dir, ".") == 0 || strcmp(dir, "..") == 0) continue;
+
+		if (mkdir(dir, mode) < 0) {
+			if (errno != EEXIST || *sep == 0) {
+				/* On purpose not doing: *pref= keep; */
+				return -1;
+			}
+		} else {
+			if (chown(dir, owner, group) < 0 && errno != EPERM)
+				return -1;
+		}
+	} while (*pref= keep, *sep != 0);
+	return 0;
+}
+
+void makedir(char *dir, int mode, int owner, int group)
+/* Install a directory, and set it's modes. */
+{
+	struct stat st;
+
+	if (stat(dir, &st) < 0) {
+		if (errno != ENOENT) { report(dir); return; }
+
+		/* The target doesn't exist, make it. */
+		if (mode == -1) mode= 0755;
+		if (owner == -1) owner= getuid();
+		if (group == -1) group= getgid();
+
+		if (mkdirp(dir, mode, owner, group) < 0) {
+			report(dir); return;
+		}
+	} else {
+		/* The target does exist, change mode and ownership. */
+		if (mode == -1) mode= (st.st_mode & 07777) | 0555;
+
+		if ((st.st_mode & 07777) != mode) {
+			if (chmod(dir, mode) < 0) { report(dir); return; }
+		}
+		if (owner == -1) owner= st.st_uid;
+		if (group == -1) group= st.st_gid;
+		if (st.st_uid != owner || st.st_gid != group) {
+			if (chown(dir, owner, group) < 0 && errno != EPERM) {
+				report(dir); return;
+			}
+			/* Set the mode again, chown may have wrecked it. */
+			(void) chmod(dir, mode);
+		}
+	}
+}
+
+int setstack(struct exec *hdr)
+/* Set the stack size in a header.  Return true if something changed. */
+{
+	long total;
+
+	total= stack;
+	while (wordpow > 0) {
+		total *= hdr->a_cpu == A_I8086 ? 2 : 4;
+		wordpow--;
+	}
+	total+= hdr->a_data + hdr->a_bss;
+
+	if (!(hdr->a_flags & A_SEP)) {
+		total+= hdr->a_text;
+#ifdef A_PAL
+		if (hdr->a_flags & A_PAL) total+= hdr->a_hdrlen;
+#endif
+	}
+	if (hdr->a_cpu == A_I8086 && total > 0x10000L)
+		total= 0x10000L;
+
+	if (hdr->a_total != total) {
+		/* Need to change stack allocation. */
+		hdr->a_total= total;
+
+		return 1;
+	}
+	return 0;
+}
+
+void copylink(char *source, char *dest, int mode, int owner, int group)
+{
+	struct stat sst, dst;
+	int sfd, dfd, n;
+	int r, same= 0, change= 0, docopy= 1;
+	char buf[4096];
+#	define hdr ((struct exec *) buf)
+	pid_t pid = 0;
+	int status = 0;
+
+	/* Source must exist as a plain file, dest may exist as a plain file. */
+
+	if (stat(source, &sst) < 0) { report(source); return; }
+
+	if (mode == -1) {
+		mode= sst.st_mode & 07777;
+		if (!lflag || cflag) {
+			mode|= 0444;
+			if (mode & 0111) mode|= 0111;
+		}
+	}
+	if (owner == -1) owner= sst.st_uid;
+	if (group == -1) group= sst.st_gid;
+
+	if (!S_ISREG(sst.st_mode)) {
+		fprintf(stderr, "install: %s is not a regular file\n", source);
+		excode= 1;
+		return;
+	}
+	r= stat(dest, &dst);
+	if (r < 0) {
+		if (errno != ENOENT) { report(dest); return; }
+	} else {
+		if (!S_ISREG(dst.st_mode)) {
+			fprintf(stderr, "install: %s is not a regular file\n",
+									dest);
+			excode= 1;
+			return;
+		}
+
+		/* Are the files the same? */
+		if (sst.st_dev == dst.st_dev && sst.st_ino == dst.st_ino) {
+			if (!lflag && cflag) {
+				fprintf(stderr,
+				"install: %s and %s are the same, can't copy\n",
+					source, dest);
+				excode= 1;
+				return;
+			}
+			same= 1;
+		}
+	}
+
+	if (lflag && !same) {
+		/* Try to link the files. */
+
+		if (r >= 0 && unlink(dest) < 0) {
+			report(dest); return;
+		}
+
+		if (link(source, dest) >= 0) {
+			docopy= 0;
+		} else {
+			if (!cflag || errno != EXDEV) {
+				fprintf(stderr,
+					"install: can't link %s to %s: %s\n",
+					source, dest, strerror(errno));
+				excode= 1;
+				return;
+			}
+		}
+	}
+
+	if (docopy && !same) {
+		/* Copy the files, stripping if necessary. */
+		long count= LONG_MAX;
+		int first= 1;
+
+		if ((sfd= open(source, O_RDONLY)) < 0) {
+			report(source); return;
+		}
+
+		/* Open for write is less simple, its mode may be 444. */
+		dfd= open(dest, O_WRONLY|O_CREAT|O_TRUNC, mode | 0600);
+		if (dfd < 0 && errno == EACCES) {
+			(void) chmod(dest, mode | 0600);
+			dfd= open(dest, O_WRONLY|O_TRUNC);
+		}
+		if (dfd < 0) {
+			report(dest);
+			close(sfd);
+			return;
+		}
+
+		pid= 0;
+		while (count > 0 && (n= read(sfd, buf, sizeof(buf))) > 0) {
+			if (first && n >= A_MINHDR && !BADMAG(*hdr)) {
+				if (strip) {
+					count= hdr->a_hdrlen
+						+ hdr->a_text + hdr->a_data;
+#ifdef A_NSYM
+					hdr->a_flags &= ~A_NSYM;
+#endif
+					hdr->a_syms= 0;
+				}
+				if (stack != -1 && setstack(hdr)) change= 1;
+
+				if (compress != nil) {
+					/* Write first #! line. */
+					(void) write(dfd, zcat, strlen(zcat));
+
+					/* Put a compressor in between. */
+					if ((pid= filter(dfd, compress)) < 0) {
+						close(sfd);
+						close(dfd);
+						return;
+					}
+					change= 1;
+				}
+			}
+			if (count < n) n= count;
+
+			if (write(dfd, buf, n) < 0) {
+				report(dest);
+				close(sfd);
+				close(dfd);
+				if (pid != 0) (void) waitpid(pid, nil, 0);
+				return;
+			}
+			count-= n;
+			first= 0;
+		}
+		if (n < 0) report(source);
+		close(sfd);
+		close(dfd);
+		if (pid != 0 && waitpid(pid, &status, 0) < 0 || status != 0) {
+			excode= 1;
+			return;
+		}
+		if (n < 0) return;
+	} else {
+		if (stack != -1) {
+			/* The file has been linked into place.  Set the
+			 * stack size.
+			 */
+			if ((dfd= open(dest, O_RDWR)) < 0) {
+				report(dest);
+				return;
+			}
+
+			if ((n= read(dfd, buf, sizeof(*hdr))) < 0) {
+				report(dest); return;
+			}
+
+			if (n >= A_MINHDR && !BADMAG(*hdr) && setstack(hdr)) {
+				if (lseek(dfd, (off_t) 0, SEEK_SET) == -1
+					|| write(dfd, buf, n) < 0
+				) {
+					report(dest);
+					close(dfd);
+					return;
+				}
+				change= 1;
+			}
+			close(dfd);
+		}
+	}
+
+	if (stat(dest, &dst) < 0) { report(dest); return; }
+
+	if ((dst.st_mode & 07777) != mode) {
+		if (chmod(dest, mode) < 0) { report(dest); return; }
+	}
+	if (dst.st_uid != owner || dst.st_gid != group) {
+		if (chown(dest, owner, group) < 0 && errno != EPERM) {
+			report(dest); return;
+		}
+		/* Set the mode again, chown may have wrecked it. */
+		(void) chmod(dest, mode);
+	}
+	if (!change) {
+		struct utimbuf ubuf;
+
+		ubuf.actime= dst.st_atime;
+		ubuf.modtime= sst.st_mtime;
+
+		if (utime(dest, &ubuf) < 0 && errno != EPERM) {
+			report(dest); return;
+		}
+	}
+}
+
+void usage(void)
+{
+	fprintf(stderr, "\
+Usage:\n\
+  install [-lcsz#] [-o owner] [-g group] [-m mode] [-S stack] [file1] file2\n\
+  install [-lcsz#] [-o owner] [-g group] [-m mode] [-S stack] file ... dir\n\
+  install -d [-o owner] [-g group] [-m mode] directory\n");
+	exit(1);
+}
+
+void main(int argc, char **argv)
+{
+	int i= 1;
+	int mode= -1;		/* Mode of target. */
+	int owner= -1;		/* Owner. */
+	int group= -1;		/* Group. */
+	int super = 0;
+#if NGROUPS_MAX > 0
+	gid_t groups[NGROUPS_MAX];
+	int ngroups;
+	int g;
+#endif
+
+	/* Only those in group 0 are allowed to set owner and group. */
+	if (getgid() == 0) super = 1;
+#if NGROUPS_MAX > 0
+	ngroups= getgroups(NGROUPS_MAX, groups);
+	for (g= 0; g < ngroups; g++) if (groups[g] == 0) super= 1;
+#endif
+	if (!super) {
+		setgid(getgid());
+		setuid(getuid());
+	}
+
+	/* May use a filter. */
+	signal(SIGPIPE, SIG_IGN);
+
+	while (i < argc && argv[i][0] == '-') {
+		char *p= argv[i++]+1;
+		char *end;
+		unsigned long num;
+		int wp;
+		struct passwd *pw;
+		struct group *gr;
+
+		if (strcmp(p, "-") == 0) break;
+
+		while (*p != 0) {
+			switch (*p++) {
+			case 'l':	lflag= 1;	break;
+			case 'c':	cflag= 1;	break;
+			case 's':	strip= 1;	break;
+			case 'd':	dflag= 1;	break;
+			case 'z':
+				if (compress == nil) {
+					compress= COMPRESS;
+					zcat= ZCAT;
+				}
+				break;
+			case 'o':
+				if (*p == 0) {
+					if (i == argc) usage();
+					p= argv[i++];
+					if (*p == 0) usage();
+				}
+				num= strtoul(p, &end, 10);
+				if (*end == 0) {
+					if ((uid_t) num != num) usage();
+					owner= num;
+				} else {
+					if ((pw= getpwnam(p)) == nil) {
+						fprintf(stderr,
+						"install: %s: unknown user\n",
+							p);
+						exit(1);
+					}
+					owner= pw->pw_uid;
+				}
+				p= "";
+				break;
+			case 'g':
+				if (*p == 0) {
+					if (i == argc) usage();
+					p= argv[i++];
+					if (*p == 0) usage();
+				}
+				num= strtoul(p, &end, 10);
+				if (*end == 0) {
+					if ((gid_t) num != num) usage();
+					group= num;
+				} else {
+					if ((gr= getgrnam(p)) == nil) {
+						fprintf(stderr,
+						"install: %s: unknown user\n",
+							p);
+						exit(1);
+					}
+					group= gr->gr_gid;
+				}
+				p= "";
+				break;
+			case 'm':
+				if (*p == 0) {
+					if (i == argc) usage();
+					p= argv[i++];
+					if (*p == 0) usage();
+				}
+				num= strtoul(p, &end, 010);
+				if (*end != 0 || (num & 07777) != num) usage();
+				mode= num;
+				if ((mode & S_ISUID) && super && owner == -1) {
+					/* Setuid what?  Root most likely. */
+					owner= 0;
+				}
+				if ((mode & S_ISGID) && super && group == -1) {
+					group= 0;
+				}
+				p= "";
+				break;
+			case 'S':
+				if (*p == 0) {
+					if (i == argc) usage();
+					p= argv[i++];
+					if (*p == 0) usage();
+				}
+				stack= strtol(p, &end, 0);
+				wp= 0;
+				if (end == p || stack < 0) usage();
+				p= end;
+				while (*p != 0) {
+					switch (*p++) {
+					case 'm':
+					case 'M': num= 1024 * 1024L; break;
+					case 'k':
+					case 'K': num= 1024; break;
+					case 'w':
+					case 'W': num= 4; wp++; break;
+					case 'b':
+					case 'B': num= 1; break;
+					default: usage();
+					}
+					if (stack > LONG_MAX / num) usage();
+					stack*= num;
+				}
+				wordpow= 0;
+				while (wp > 0) { stack /= 4; wordpow++; wp--; }
+				break;
+			default:
+				if ((unsigned) (p[-1] - '1') <= ('9' - '1')) {
+					compress= GZIP;
+					GZIP[1][1]= p[-1];
+					zcat= GZCAT;
+					break;
+				}
+				usage();
+			}
+		}
+	}
+	/* Some options don't mix. */
+	if (dflag && (cflag || lflag || strip)) usage();
+
+	/* Don't let the user umask interfere. */
+	umask(000);
+
+	if (dflag) {
+		/* install directory */
+		if ((argc - i) != 1) usage();
+
+		makedir(argv[i], mode, owner, group);
+	} else {
+		struct stat st;
+
+		if ((argc - i) < 1) usage();
+		if ((lflag || cflag) && (argc - i) == 1) usage();
+
+		if (stat(argv[argc-1], &st) >= 0 && S_ISDIR(st.st_mode)) {
+			/* install file ... dir */
+			char *target= nil;
+			char *base;
+
+			if ((argc - i) == 1) usage();
+
+			while (i < argc-1) {
+				if ((base= strrchr(argv[i], '/')) == nil)
+					base= argv[i];
+				else
+					base++;
+				target= allocate(target, strlen(argv[argc-1])
+						+ 1 + strlen(base) + 1);
+				strcpy(target, argv[argc-1]);
+				strcat(target, "/");
+				strcat(target, base);
+
+				copylink(argv[i++], target, mode, owner, group);
+			}
+		} else {
+			/* install [file1] file2 */
+
+			copylink(argv[i], argv[argc-1], mode, owner, group);
+		}
+	}
+	exit(excode);
+}
Index: /trunk/minix/commands/simple/intr.c
===================================================================
--- /trunk/minix/commands/simple/intr.c	(revision 9)
+++ /trunk/minix/commands/simple/intr.c	(revision 9)
@@ -0,0 +1,148 @@
+/*	intr 1.4 - run a command with interrupts enabled
+ *							Author: Kees J. Bot
+ *								17 Dec 1992
+ */
+#define nil 0
+#ifndef _POSIX_SOURCE
+#define _POSIX_SOURCE 1
+#endif
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#if __minix
+static char DEV_LOG[]= "/dev/log";
+#else
+static char DEV_LOG[]= "/dev/console";
+#endif
+
+static void say(const char *s)
+{
+	write(2, s, strlen(s));
+}
+
+static void fatal(const char *label)
+{
+	int err= errno;
+
+	say("intr: ");
+	say(label);
+	say(": ");
+	say(strerror(err));
+	say("\n");
+	exit(1);
+}
+
+static void usage(void)
+{
+	say("Usage: intr [-d] [-t seconds] command [arg ...]\n");
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	int fd;
+	unsigned n= 0;
+	int daemonize= 0;
+	int i;
+
+	i= 1;
+	while (i < argc && argv[i][0] == '-') {
+		char *opt= argv[i++]+1, *end;
+		unsigned long sec;
+
+		if (opt[0] == '-' && opt[1] == 0) break;
+
+		while (*opt != 0) switch (*opt++) {
+		case 'd':
+			/* -d */
+			daemonize= 1;
+			break;
+		case 't':
+			/* -t n: alarm in n seconds. */
+			if (*opt == 0) {
+				if (i == argc) usage();
+				opt= argv[i++];
+			}
+			sec= strtoul(opt, &end, 10);
+			if (end == opt || *end != 0 || (n= sec) != sec)
+				usage();
+			opt= "";
+			break;
+		default:
+			usage();
+		}
+	}
+
+	if ((argc - i) < 1) usage();
+
+	/* Try to open the controlling tty. */
+	if ((fd= open("/dev/tty", O_RDWR)) < 0) {
+		if (errno != ENXIO) fatal("/dev/tty");
+	}
+
+	if (!daemonize) {
+		/* Bring to the foreground.  If we already have a controlling
+		 * tty then use it.  Otherwise try to allocate the console as
+		 * controlling tty and begin a process group.
+		 */
+		if (fd < 0) {
+			if (setsid() < 0) fatal("setsid()");
+
+			fd= open("/dev/console", O_RDWR);
+		}
+
+		if (fd >= 0) {
+			if (fd != 0) {
+				dup2(fd, 0);
+				close(fd);
+			}
+			dup2(0, 1);
+			dup2(0, 2);
+		}
+
+		/* Set the usual signals back to the default. */
+		signal(SIGHUP, SIG_DFL);
+		signal(SIGINT, SIG_DFL);
+		signal(SIGQUIT, SIG_DFL);
+		signal(SIGTERM, SIG_DFL);
+	} else {
+		/* Send to the background.  Redirect input to /dev/null, and
+		 * output to the log device.  Detach from the process group.
+		 */
+		if (fd >= 0) {
+			close(fd);
+
+			if (setsid() < 0) fatal("setsid()");
+		}
+		if ((fd= open("/dev/null", O_RDWR)) < 0) fatal("/dev/null");
+		if (fd != 0) {
+			dup2(fd, 0);
+			close(fd);
+		}
+		if ((fd= open(DEV_LOG, O_WRONLY)) < 0) fatal(DEV_LOG);
+		if (fd != 1) {
+			dup2(fd, 1);
+			close(fd);
+		}
+		dup2(1, 2);
+
+		/* Move to the root directory. */
+		(void) chdir("/");
+	}
+
+	/* Schedule the alarm.  (It is inherited over execve.) */
+	if (n != 0) alarm(n);
+
+	/* Call program. */
+	execvp(argv[i], argv + i);
+
+	/* Complain. */
+	fatal(argv[i]);
+	return 0;
+}
Index: /trunk/minix/commands/simple/irdpd.c
===================================================================
--- /trunk/minix/commands/simple/irdpd.c	(revision 9)
+++ /trunk/minix/commands/simple/irdpd.c	(revision 9)
@@ -0,0 +1,624 @@
+/*	irdpd 1.10 - Internet router discovery protocol daemon.
+ *							Author: Kees J. Bot
+ *								28 May 1994
+ * Activily solicitate or passively look for routers.
+ * Based heavily on its forerunners, the irdp_sol and rip2icmp daemons by
+ * Philip Homburg.
+ */
+#define nil 0
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <limits.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/asynchio.h>
+#include <net/hton.h>
+#include <net/netlib.h>
+#include <net/gen/in.h>
+#include <net/gen/ip_hdr.h>
+#include <net/gen/icmp.h>
+#include <net/gen/icmp_hdr.h>
+#include <net/gen/ip_io.h>
+#include <net/gen/inet.h>
+#include <net/gen/netdb.h>
+#include <net/gen/oneCsum.h>
+#include <net/gen/socket.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/udp_io.h>
+
+#define MAX_SOLICITATIONS	    3	/* # router solicitations. */
+#define SOLICITATION_INTERVAL	    3	/* Secs between solicitate retries. */
+#define DEST_TO 	      (10*60)	/* 10 minutes */
+#define NEW_ROUTE	       (5*60)	/* 5 minutes */
+#define DANGER		       (2*60)	/* Nearing a advert timeout? */
+#define DEAD_TO		    (24L*60*60)	/* 24 hours */
+#define DEAD_PREF	    0x80000000L	/* From RFC 1256 */
+#define MaxAdvertisementInterval (DEST_TO/2)	/* Chosen to jive with RIP */
+#define AdvertisementLifetime	 DEST_TO
+#define PRIO_OFF_DEF		-1024
+#define RIP_REPLY		    2
+
+/* It's now or never. */
+#define IMMEDIATELY	((time_t) ((time_t) -1 < 0 ? LONG_MIN : 0))
+#define NEVER		((time_t) ((time_t) -1 < 0 ? LONG_MAX : ULONG_MAX))
+
+#if !__minix_vmd
+/* Standard Minix needs to choose between router discovery and RIP info. */
+int do_rdisc= 1;
+int do_rip= 0;
+#else
+/* VMD Minix can do both at once. */
+#define do_rdisc 1
+#define do_rip 1
+#endif
+
+int rip_fd;			/* For incoming RIP packet. */
+int irdp_fd;			/* Receive or transmit IRDP packets. */
+
+char *udp_device;		/* UDP device to use. */
+char *ip_device;		/* IP device to use. */
+
+int priority_offset;		/* Offset to make my routes less preferred. */
+
+int bcast= 0;			/* Broadcast adverts to all. */
+int debug= 0;
+
+char rip_buf[8192];		/* Incoming RIP packet buffer. */
+char irdp_buf[1024];		/* IRDP buffer. */
+
+typedef struct routeinfo
+{
+	u8_t		command;
+	u8_t		version;
+	u16_t		zero1;
+	struct routedata {
+		u16_t	family;
+		u16_t	zero2;
+		u32_t	ip_addr;
+		u32_t	zero3, zero4;
+		u32_t	metric;
+	} data[1];
+} routeinfo_t;
+
+typedef struct table
+{
+	ipaddr_t	tab_gw;
+	i32_t		tab_pref;
+	time_t		tab_time;
+} table_t;
+
+table_t *table;			/* Collected table of routing info. */
+size_t table_size;
+
+int sol_retries= MAX_SOLICITATIONS;
+time_t next_sol= IMMEDIATELY;
+time_t next_advert= NEVER;
+time_t router_advert_valid= IMMEDIATELY;
+time_t now;
+
+void report(const char *label)
+/* irdpd: /dev/hd0: Device went up in flames */
+{
+	fprintf(stderr, "irdpd: %s: %s\n", label, strerror(errno));
+}
+
+void fatal(const char *label)
+/* irdpd: /dev/house: Taking this with it */
+{
+	report(label);
+	exit(1);
+}
+
+#if DEBUG
+char *addr2name(ipaddr_t host)
+/* Translate an IP address to a printable name. */
+{
+	struct hostent *hostent;
+
+	hostent= gethostbyaddr((char *) &host, sizeof(host), AF_INET);
+	return hostent == nil ? inet_ntoa(host) : hostent->h_name;
+}
+#else
+#define addr2name(host)	inet_ntoa(host)
+#endif
+
+void print_table(void)
+/* Show the collected routing table. */
+{
+	int i;
+	table_t *ptab;
+	struct tm *tm;
+
+	for (i= 0, ptab= table; i < table_size; i++, ptab++) {
+		if (ptab->tab_time < now - DEAD_TO) continue;
+
+		tm= localtime(&ptab->tab_time);
+		printf("%-40s %6ld %02d:%02d:%02d\n",
+			addr2name(ptab->tab_gw),
+			(long) ptab->tab_pref,
+			tm->tm_hour, tm->tm_min, tm->tm_sec);
+	}
+}
+
+void advertize(ipaddr_t host)
+/* Send a router advert to a host. */
+{
+	char *buf, *data;
+	ip_hdr_t *ip_hdr;
+	icmp_hdr_t *icmp_hdr;
+	int i;
+	table_t *ptab;
+
+	buf= malloc(sizeof(*ip_hdr) + offsetof(icmp_hdr_t, ih_dun.uhd_data)
+			+ table_size * (sizeof(ipaddr_t) + sizeof(u32_t)));
+	if (buf == nil) fatal("heap error");
+
+	ip_hdr= (ip_hdr_t *) buf;
+	icmp_hdr= (icmp_hdr_t *) (ip_hdr + 1);
+
+	ip_hdr->ih_vers_ihl= 0x45;
+	ip_hdr->ih_dst= host;
+
+	icmp_hdr->ih_type= ICMP_TYPE_ROUTER_ADVER;
+	icmp_hdr->ih_code= 0;
+	icmp_hdr->ih_hun.ihh_ram.iram_na= 0;
+	icmp_hdr->ih_hun.ihh_ram.iram_aes= 2;
+	icmp_hdr->ih_hun.ihh_ram.iram_lt= htons(AdvertisementLifetime);
+	data= (char *) icmp_hdr->ih_dun.uhd_data;
+
+	/* Collect gateway entries from the table. */
+	for (i= 0, ptab= table; i < table_size; i++, ptab++) {
+		if (ptab->tab_time < now - DEAD_TO) continue;
+
+		icmp_hdr->ih_hun.ihh_ram.iram_na++;
+		if (ptab->tab_time < now - DEST_TO) ptab->tab_pref= DEAD_PREF;
+		* (ipaddr_t *) data= ptab->tab_gw;
+		data+= sizeof(ipaddr_t);
+		* (i32_t *) data= htonl(ptab->tab_pref);
+		data+= sizeof(i32_t);
+	}
+	icmp_hdr->ih_chksum= 0;
+	icmp_hdr->ih_chksum= ~oneC_sum(0, icmp_hdr, data - (char *) icmp_hdr);
+
+	if (icmp_hdr->ih_hun.ihh_ram.iram_na > 0) {
+		/* Send routing info. */
+
+		if (debug) {
+			printf("Routing table send to %s:\n", addr2name(host));
+			print_table();
+		}
+
+		if (write(irdp_fd, buf, data - buf) < 0) {
+			(errno == EIO ? fatal : report)(ip_device);
+		}
+	}
+	free(buf);
+}
+
+void time_functions(void)
+/* Perform time dependend functions: router solicitation, router advert. */
+{
+	if (now >= next_sol) {
+		char buf[sizeof(ip_hdr_t) + 8];
+		ip_hdr_t *ip_hdr;
+		icmp_hdr_t *icmp_hdr;
+
+		if (sol_retries == 0) {
+			/* Stop soliciting. */
+			next_sol= NEVER;
+#if !__minix_vmd
+			/* Switch to RIP if no router responded. */
+			if (table_size == 0) {
+				do_rip= 1;
+				do_rdisc= 0;
+			}
+#endif
+			return;
+		}
+
+		/* Broadcast a router solicitation to find a router. */
+		ip_hdr= (ip_hdr_t *) buf;
+		icmp_hdr= (icmp_hdr_t *) (ip_hdr + 1);
+
+		ip_hdr->ih_vers_ihl= 0x45;
+		ip_hdr->ih_dst= HTONL(0xFFFFFFFFL);
+
+		icmp_hdr->ih_type= ICMP_TYPE_ROUTE_SOL;
+		icmp_hdr->ih_code= 0;
+		icmp_hdr->ih_chksum= 0;
+		icmp_hdr->ih_hun.ihh_unused= 0;
+		icmp_hdr->ih_chksum= ~oneC_sum(0, icmp_hdr, 8);
+
+		if (debug) printf("Broadcasting router solicitation\n");
+
+		if (write(irdp_fd, buf, sizeof(buf)) < 0)
+			fatal("sending router solicitation failed");
+
+		/* Schedule the next packet. */
+		next_sol= now + SOLICITATION_INTERVAL;
+
+		sol_retries--;
+	}
+
+	if (now >= next_advert) {
+		/* Advertize routes to the local host (normally), or
+		 * broadcast them (to keep bad hosts up.)
+		 */
+
+		advertize(bcast ? HTONL(0xFFFFFFFFL) : HTONL(0x7F000001L));
+		next_advert= now + MaxAdvertisementInterval;
+#if !__minix_vmd
+		/* Make sure we are listening to RIP now. */
+		do_rip= 1;
+		do_rdisc= 0;
+#endif
+	}
+}
+
+void add_gateway(ipaddr_t host, i32_t pref)
+/* Add a router with given address and preference to the routing table. */
+{
+	table_t *oldest, *ptab;
+	int i;
+
+	/* Look for the host, or select the oldest entry. */
+	oldest= nil;
+	for (i= 0, ptab= table; i < table_size; i++, ptab++) {
+		if (ptab->tab_gw == host) break;
+
+		if (oldest == nil || ptab->tab_time < oldest->tab_time)
+			oldest= ptab;
+	}
+
+	/* Don't evict the oldest if it is still valid. */
+	if (oldest != nil && oldest->tab_time >= now - DEST_TO) oldest= nil;
+
+	/* Expand the table? */
+	if (i == table_size && oldest == nil) {
+		table_size++;
+		table= realloc(table, table_size * sizeof(*table));
+		if (table == nil) fatal("heap error");
+		oldest= &table[table_size - 1];
+	}
+
+	if (oldest != nil) {
+		ptab= oldest;
+		ptab->tab_gw= host;
+		ptab->tab_pref= DEAD_PREF;
+	}
+
+	/* Replace an entry if the new one looks more promising. */
+	if (pref >= ptab->tab_pref || ptab->tab_time <= now - NEW_ROUTE) {
+		ptab->tab_pref= pref;
+		ptab->tab_time= now;
+	}
+}
+
+void rip_incoming(ssize_t n)
+/* Use a RIP packet to add to the router table.  (RIP packets are really for
+ * between routers, but often it is the only information around.)
+ */
+{
+	udp_io_hdr_t *udp_io_hdr;
+	u32_t default_dist;
+	i32_t pref;
+	routeinfo_t *routeinfo;
+	struct routedata *data, *end;
+
+	/* We don't care about RIP packets when there are router adverts. */
+	if (now + MaxAdvertisementInterval < router_advert_valid) return;
+
+	udp_io_hdr= (udp_io_hdr_t *) rip_buf;
+	if (udp_io_hdr->uih_data_len != n - sizeof(*udp_io_hdr)) {
+		if (debug) printf("Bad sized route packet (discarded)\n");
+		return;
+	}
+	routeinfo= (routeinfo_t *) (rip_buf + sizeof(*udp_io_hdr)
+			+ udp_io_hdr->uih_ip_opt_len);
+
+	if (routeinfo->command != RIP_REPLY) {
+		if (debug) {
+			printf("RIP-%d packet command %d ignored\n",
+				routeinfo->version, routeinfo->command);
+		}
+		return;
+	}
+
+	/* Look for a default route, the route to the gateway. */
+	end= (struct routedata *) (rip_buf + n);
+	default_dist= (u32_t) -1;
+	for (data= routeinfo->data; data < end; data++) {
+		if (ntohs(data->family) != AF_INET || data->ip_addr != 0)
+			continue;
+		default_dist= ntohl(data->metric);
+		if (default_dist >= 256) {
+			if (debug) {
+				printf("Strange metric %lu\n",
+					(unsigned long) default_dist);
+			}
+		}
+	}
+	pref= default_dist >= 256 ? 1 : 512 - default_dist;
+	pref+= priority_offset;
+
+	/* Add the gateway to the table with the calculated preference. */
+	add_gateway(udp_io_hdr->uih_src_addr, pref);
+
+	if (debug) {
+		printf("Routing table after RIP-%d packet from %s:\n",
+			routeinfo->version,
+			addr2name(udp_io_hdr->uih_src_addr));
+		print_table();
+	}
+
+	/* Start advertizing. */
+	if (next_advert == NEVER) next_advert= IMMEDIATELY;
+}
+
+void irdp_incoming(ssize_t n)
+/* Look for router solicitations and router advertisements.  The solicitations
+ * are probably from other irdpd daemons, we answer them if we do not expect
+ * a real router to answer.  The advertisements cause this daemon to shut up.
+ */
+{
+	ip_hdr_t *ip_hdr;
+	icmp_hdr_t *icmp_hdr;
+	int ip_hdr_len;
+	char *data;
+	int i;
+	int router;
+	ipaddr_t addr;
+	i32_t pref;
+	time_t valid;
+
+	ip_hdr= (ip_hdr_t *) irdp_buf;
+	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
+	if (n < ip_hdr_len + 8) {
+		if (debug) printf("Bad sized ICMP (discarded)\n");
+		return;
+	}
+
+	icmp_hdr= (icmp_hdr_t *)(irdp_buf + ip_hdr_len);
+
+	/* Did I send this myself? */
+	if (ip_hdr->ih_src == ip_hdr->ih_dst) return;
+	if ((htonl(ip_hdr->ih_src) & 0xFF000000L) == 0x7F000000L) return;
+
+	if (icmp_hdr->ih_type != ICMP_TYPE_ROUTER_ADVER) return;
+
+	/* Incoming router advertisement, the kind of packet the TCP/IP task
+	 * is very happy with.  No need to solicit further.
+	 */
+	sol_retries= 0;
+
+	/* Add router info to our table.  Also see if the packet really came
+	 * from a router.  If so then we can go dormant for the lifetime of
+	 * the ICMP.
+	 */
+	router= 0;
+	data= (char *) icmp_hdr->ih_dun.uhd_data;
+	for (i= 0; i < icmp_hdr->ih_hun.ihh_ram.iram_na; i++) {
+		addr= * (ipaddr_t *) data;
+		data+= sizeof(ipaddr_t);
+		pref= htonl(* (i32_t *) data);
+		data+= sizeof(i32_t);
+
+		if (addr == ip_hdr->ih_src) {
+			/* The sender is in the routing table! */
+			router= 1;
+		}
+		add_gateway(addr, pref);
+	}
+
+	valid= now + ntohs(icmp_hdr->ih_hun.ihh_ram.iram_lt);
+	if (router) router_advert_valid= valid;
+
+	/* Restart advertizing close to the timeout of the advert.  (No more
+	 * irdpd adverts if the router stays alive.)
+	 */
+	if (router || next_advert > valid - DANGER)
+		next_advert= valid - DANGER;
+
+	if (debug) {
+		printf("Routing table after advert received from %s:\n",
+			addr2name(ip_hdr->ih_src));
+		print_table();
+		if (router) {
+			struct tm *tm= localtime(&router_advert_valid);
+			printf(
+			"This router advert is valid until %02d:%02d:%02d\n",
+				tm->tm_hour, tm->tm_min, tm->tm_sec);
+		}
+	}
+}
+
+void sig_handler(int sig)
+/* A signal changes the debug level. */
+{
+	switch (sig) {
+	case SIGUSR1:	debug++;		break;
+	case SIGUSR2:	debug= 0;		break;
+	}
+}
+
+void usage(void)
+{
+	fprintf(stderr,
+"Usage: irdpd [-bd] [-U udp-device] [-I ip-device] [-o priority-offset]\n");
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	int i;
+	struct servent *service;
+	udpport_t route_port;
+	nwio_udpopt_t udpopt;
+	nwio_ipopt_t ipopt;
+	asynchio_t asyn;
+	time_t timeout;
+	struct timeval tv;
+	struct sigaction sa;
+	char *offset_arg, *offset_end;
+	long arg;
+
+	udp_device= ip_device= nil;
+	offset_arg= nil;
+
+	for (i = 1; i < argc && argv[i][0] == '-'; i++) {
+		char *p= argv[i] + 1;
+
+		if (p[0] == '-' && p[1] == 0) { i++; break; }
+
+		while (*p != 0) {
+			switch (*p++) {
+			case 'U':
+				if (udp_device != nil) usage();
+				if (*p == 0) {
+					if (++i == argc) usage();
+					p= argv[i];
+				}
+				udp_device= p;
+				p= "";
+				break;
+			case 'I':
+				if (ip_device != nil) usage();
+				if (*p == 0) {
+					if (++i == argc) usage();
+					p= argv[i];
+				}
+				ip_device= p;
+				p= "";
+				break;
+			case 'o':
+				if (offset_arg != nil) usage();
+				if (*p == 0) {
+					if (++i == argc) usage();
+					p= argv[i];
+				}
+				offset_arg= p;
+				p= "";
+				break;
+			case 'b':
+				bcast= 1;
+				break;
+			case 's':
+				/*obsolete*/
+				break;
+			case 'd':
+				debug= 1;
+				break;
+			default:
+				usage();
+			}
+		}
+	}
+	if (i != argc) usage();
+
+	/* Debug level signals. */
+	sa.sa_handler= sig_handler;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags= 0;
+	sigaction(SIGUSR1, &sa, nil);
+	sigaction(SIGUSR2, &sa, nil);
+
+	if (udp_device == nil && (udp_device= getenv("UDP_DEVICE")) == nil)
+		udp_device= UDP_DEVICE;
+
+	if (ip_device == nil && (ip_device= getenv("IP_DEVICE")) == nil)
+		ip_device= IP_DEVICE;
+
+	if (offset_arg == nil) {
+		priority_offset= PRIO_OFF_DEF;
+	} else {
+		arg= strtol(offset_arg, &offset_end, 0);
+		if (*offset_end != 0 || (priority_offset= arg) != arg) usage();
+	}
+
+	if ((service= getservbyname("route", "udp")) == nil) {
+		fprintf(stderr,
+	"irdpd: unable to look up the port number for the 'route' service\n");
+		exit(1);
+	}
+
+	route_port= (udpport_t) service->s_port;
+
+	if ((rip_fd= open(udp_device, O_RDWR)) < 0) fatal(udp_device);
+
+	udpopt.nwuo_flags= NWUO_COPY | NWUO_LP_SET | NWUO_DI_LOC
+		| NWUO_EN_BROAD | NWUO_RP_SET | NWUO_RA_ANY | NWUO_RWDATALL
+		| NWUO_DI_IPOPT;
+	udpopt.nwuo_locport= route_port;
+	udpopt.nwuo_remport= route_port;
+	if (ioctl(rip_fd, NWIOSUDPOPT, &udpopt) < 0)
+		fatal("setting UDP options failed");
+
+	if ((irdp_fd= open(ip_device, O_RDWR)) < 0) fatal(ip_device);
+
+	ipopt.nwio_flags= NWIO_COPY | NWIO_EN_LOC | NWIO_EN_BROAD
+			| NWIO_REMANY | NWIO_PROTOSPEC
+			| NWIO_HDR_O_SPEC | NWIO_RWDATALL;
+	ipopt.nwio_tos= 0;
+	ipopt.nwio_ttl= 1;
+	ipopt.nwio_df= 0;
+	ipopt.nwio_hdropt.iho_opt_siz= 0;
+	ipopt.nwio_rem= HTONL(0xFFFFFFFFL);
+	ipopt.nwio_proto= IPPROTO_ICMP;
+
+	if (ioctl(irdp_fd, NWIOSIPOPT, &ipopt) < 0)
+		fatal("can't configure ICMP channel");
+
+	asyn_init(&asyn);
+
+	while (1) {
+		ssize_t r;
+
+		if (do_rip) {
+			/* Try a RIP read. */
+			r= asyn_read(&asyn, rip_fd, rip_buf, sizeof(rip_buf));
+			if (r < 0) {
+				if (errno == EIO) fatal(udp_device);
+				if (errno != EINPROGRESS) report(udp_device);
+			} else {
+				now= time(nil);
+				rip_incoming(r);
+			}
+		}
+
+		if (do_rdisc) {
+			/* Try an IRDP read. */
+			r= asyn_read(&asyn, irdp_fd, irdp_buf,
+							sizeof(irdp_buf));
+			if (r < 0) {
+				if (errno == EIO) fatal(ip_device);
+				if (errno != EINPROGRESS) report(ip_device);
+			} else {
+				now= time(nil);
+				irdp_incoming(r);
+			}
+		}
+		fflush(stdout);
+
+		/* Compute the next wakeup call. */
+		timeout= next_sol < next_advert ? next_sol : next_advert;
+
+		/* Wait for a RIP or IRDP packet or a timeout. */
+		tv.tv_sec= timeout;
+		tv.tv_usec= 0;
+		if (asyn_wait(&asyn, 0, timeout == NEVER ? nil : &tv) < 0) {
+			/* Timeout? */
+			if (errno != EINTR && errno != EAGAIN)
+				fatal("asyn_wait()");
+			now= time(nil);
+			time_functions();
+		}
+	}
+}
Index: /trunk/minix/commands/simple/isoread.c
===================================================================
--- /trunk/minix/commands/simple/isoread.c	(revision 9)
+++ /trunk/minix/commands/simple/isoread.c	(revision 9)
@@ -0,0 +1,865 @@
+/*
+ * isoread.c
+ *
+ * isoread reads a file system in ISO9660 or HIGH SIERRA format from
+ * a given device.
+ *
+ * Apr  5 1995    Michel R. Prevenier 
+ * Nov 16 1996    Kees J. Bot        -- bug fix: isoread filename matching 
+ * Dec  7 1997    Albert S. Woodhull -- bug fix: return values
+ *                                       "   " : isodir filename handling
+ *                                   -- added  : isoread -a option  
+ * Mar 21 2000    Michael A. Temari  -- bug fix: look_up only searched first
+ *                                             : block of directory
+ *                                             : stack overflow in recurse_dir
+ *                                             : and various other bugs
+ * Apr 14 2002    Michael A. Temari  -- bug fix: fixed recursing directories
+ *                                             : and printing dates 2000 and 
+ *                                             : later
+ * May 14 2002    Kees J. Bot        -- bug fix: fixed error messages
+ * Mar 14 2003    Kees J. Bot        -- added  : iso{dir,read} -B option
+ * Jul 24 2003    Michael A. Temari  -- bug fix: bytes to blocks roundup fix
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <sys/times.h>
+#include <unistd.h>
+
+/*             
+ *  definitions used by the ISO9660 and HIGH SIERRA file system
+ */
+
+#define ISO9660_ID	"CD001"
+#define HIGH_SIERRA_ID	"CDROM"
+#define BLOCK_SIZE	2048
+#define BLOCK_SHIFT	11
+
+
+/* Fields in a ISO9660 volume descriptor */
+struct iso9660_descriptor
+{
+  char type[1];		
+  char id[5];			
+  char version[1];		
+  char reserved1[1];		
+  char system_id[32];		
+  char volume_id[32];		
+  char reserved2[8];		
+  char volume_size[8];	
+  char reserved3[32];		
+  char volume_set_size[4];	
+  char volume_seq_nr[4];
+  char block_size[4];	
+  char path_table_size[8];	
+  char type_l_path_table[4];	
+  char opt_type_l_path_table[4];	
+  char type_m_path_table[4];	
+  char opt_type_m_path_table[4];	
+  char root_dir_entry[34];
+  char vol_set_id[128];	
+  char publ_id[128];
+  char prep_id[128];	
+  char appl_id[128];	
+  char copyright_file_id[37];	
+  char abstract_file_id[37];	
+  char bibl_file_id[37];
+  char creation_date[17];	
+  char mod_date[17];	
+  char exp_date[17];	
+  char eff_date[17];	
+  char file_struc_version[1];
+  char reserved4[1];		
+  char appl_data[512];	
+  char reserved5[653];			
+};
+
+
+/* Fields in a High Sierra volume descriptor */
+struct high_sierra_descriptor
+{
+  char reserved1[8];
+  char type[1];	
+  char id[5];		
+  char version[1];	
+  char reserved2[1];	
+  char system_id[32];
+  char volume_id[32];
+  char reserved3[8];	
+  char volume_size[8];	
+  char reserved4[32];
+  char vol_set_size[4];
+  char volume_seq_nr[4];	
+  char block_size[4];	
+  char path_table_size[8];
+  char type_l_path_table[4];
+  char reserved5[28];		
+  char root_dir_entry[34];
+};
+
+
+/* Fields in a directory entry */
+struct dir_entry 
+{
+  char length[1];	
+  char ext_attr_length[1];
+  char first_block[8];
+  char size[8];	
+  char date[7];
+  char flags[1];	
+  char file_unit_size[1];
+  char interleave[1];
+  char volume_seq_nr[4];	
+  char name_length[1];
+  char name[1];
+};
+
+
+#define STDOUT		stdout
+#define STDERR		stderr
+#define NULL_DIR	(struct dir_entry *) 0
+#define MAX_NAME_LENGTH	255
+#define MAX_PATH_LENGTH	1024
+
+#define NR_OF_CHARS	13 
+#define NR_OF_BLANKS	2
+#define NR_OF_COLS	(80 / (NR_OF_CHARS + NR_OF_BLANKS))
+
+/* This macro always returns a lower case character */
+#define LOWER_CASE(CHR) (CHR >= 'A' && CHR <= 'Z' ? CHR | 0x20 : CHR) 
+
+/* Macro's for determining . , .. and normal directory entries */
+#define IS_DOT(PTR) (PTR->name_length[0] == 1 && PTR->name[0] == 0 ? 1 : 0)
+#define IS_DOT_DOT(PTR) (PTR->name_length[0] == 1 && PTR->name[0] == 1 ? 1 : 0)
+#define IS_DIR(PTR) (PTR->flags[-High_Sierra] & 2 ? 1 : 0)
+
+
+_PROTOTYPE (int main, (int argc, char **argv));
+_PROTOTYPE (int iso_cmp, (char *name, struct dir_entry *dir_ptr, int dir_flag));
+_PROTOTYPE (void list_dir, (struct dir_entry *dir_ptr));
+_PROTOTYPE (void list_file, (struct dir_entry *dir_ptr));
+_PROTOTYPE (struct dir_entry *look_up, (char *name));
+_PROTOTYPE (void recurse_dir, (char *path, struct dir_entry *dir_ptr));
+_PROTOTYPE (void read_device, (long offset, int nr_of_bytes, char *buffer));
+_PROTOTYPE (int valid_fs, (void) );               
+_PROTOTYPE (void usage, (void) );               
+_PROTOTYPE (void print_date, (char *date));
+_PROTOTYPE (void print_dir_date, (char *date));
+_PROTOTYPE (void iso_info, (struct iso9660_descriptor *vol_desc));
+_PROTOTYPE (void hs_info, (struct high_sierra_descriptor *vol_desc));
+_PROTOTYPE (int iso_711, (char *c));
+_PROTOTYPE (int iso_712, (char *c));
+_PROTOTYPE (int iso_721, (char *c));
+_PROTOTYPE (int iso_722, (char *c));
+_PROTOTYPE (int iso_723, (char *c));
+_PROTOTYPE (long iso_731, (char *c));
+_PROTOTYPE (long iso_732, (char *c));
+_PROTOTYPE (long iso_733, (char *c));
+
+
+char Buffer[BLOCK_SIZE];	            /* buffer to hold read data */
+int Device;				    /* global file descriptor */
+struct iso9660_descriptor *Iso_Vol_Desc;    /* iso9660 volume descriptor */
+struct high_sierra_descriptor *Hs_Vol_Desc; /* high sierra volume descriptor */
+int High_Sierra = 0;                        /* 1 = high sierra format */
+int Iso9660 = 0;                            /* 1 = iso9660 format */
+
+/* This comes in handy when printing the date */
+char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
+
+/* Flags displaying what to do  */
+int Read_File = 0;      /* 1 = Read file */
+int Read_Dir = 0;	/* 1 = Read directory entry */
+int Read_Info = 0;      /* 1 = Read volume descriptor */
+int Recurse = 0;        /* 1 = Recursively descend directories */
+int Verbose = 0;        /* 1 = Print all info on directories */
+int ByteOffset = 0;     /* 1 = Print byte offset and length of files */
+int Aflag = 0;          /* 1 = Suppress output of \r  */
+
+int iso_cmp(name, dir_ptr, dir_flag)
+char *name;
+struct dir_entry *dir_ptr;
+int dir_flag;
+{
+/* Compare name with directory entries, looking for match with a dirname.
+ * An iso9660 filename is terminated by ";n", where n will probably 
+ * be 1. A directory name is not terminated by anything special, it may be
+ * followed by a \0 if padding is needed to put the following directory 
+ * entry on an even address.
+ */
+  int i;
+  int len;
+
+  /* First match the filename */
+  len = strlen(name);
+  if (len > iso_711(dir_ptr->name_length)) return 1;
+  for (i = 0; i < len; i++)
+  {
+    if (dir_ptr->name[i] == ';') return 1;	/* found end of a filename */ 
+    if (name[i] != LOWER_CASE(dir_ptr->name[i])) return 1; /* match failed */
+  }
+  if (dir_ptr->name[i] != ';' && i != len) return 1; /* incomplete match */
+
+  /* The filename is ok, now look at the file type */
+  if (dir_flag && !IS_DIR(dir_ptr)) return 1;  /* File type not correct */
+
+  return 0; 
+}
+
+
+void usage()
+{
+  if (Read_Dir)
+   fprintf (STDERR, "Usage: isodir [-lrB] inputfile [dir]\n");
+  else if (Read_Info)
+   fprintf (STDERR, "Usage: isoinfo inputfile\n");
+  else
+   fprintf (STDERR, "Usage: isoread [-a] inputfile file\n");
+  exit(1);
+}
+
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  struct dir_entry *entry;
+  char path[MAX_PATH_LENGTH];
+  char *input_file;
+  char *basename;
+  char *file_name;
+  int i,j;
+
+  /* Read arguments */
+  basename = argv[0];
+  while (*argv[0] != '\0') 
+    if (*argv[0]++ == '/') basename = argv[0];
+
+  if (strcmp(basename,"isodir") == 0) Read_Dir = 1;
+  else if (strcmp(basename,"isoinfo") == 0) Read_Info = 1;
+  else Read_File = 1;
+
+  if ((argc > 5 && Read_Dir) || (argc != 2 && Read_Info) ||
+     (argc > 4 && Read_File)) usage();
+
+  i = 1;
+
+  while (i < argc && argv[i][0] == '-')
+  {
+    char *opt = argv[i++] + 1;
+
+    if (opt[0] == '-' && opt[1] == '\0') break;
+
+    while (*opt != '\0')
+    {
+      if (Read_Info) usage();
+      if (Read_Dir)
+      switch (*opt++)
+      {
+	case 'r':	Recurse = 1; break;  
+	case 'l':	Verbose = 1; break;
+	case 'B':	ByteOffset = 1; break;
+	default:	usage();
+      }
+      if (Read_File)
+      switch (*opt++)
+      {
+	case 'a':	Aflag = 1; break;    
+	case 'B':	ByteOffset = 1; break;
+	default:	usage();
+      }
+    }
+  }
+
+  if (i >= argc) usage();
+  input_file = argv[i++];
+
+  if (Read_File)
+  {
+    if (i >= argc) usage();
+    file_name = argv[i++];
+  }
+
+  if (Read_Dir)
+  {
+    file_name = "/";
+    if (i < argc)
+    {
+      file_name = argv[i++];
+    }
+  }
+
+  if (i < argc) usage();
+  
+  if (Read_File || Read_Dir)
+  {
+    for (i=0; file_name[i] != '\0'; i++) 
+      path[i] = LOWER_CASE(file_name[i]);
+    path[i] = '\0';
+  }
+ 
+  /* Open file system (file or device) */
+  if ((Device = open(input_file, O_RDONLY)) < 0) 
+  {
+    fprintf (STDERR, "cannot open %s: %s\n", input_file, strerror(errno));
+    exit(-1);
+  }
+
+  
+  if (!valid_fs())
+  {
+    fprintf (STDERR, "File system not in ISO9660 or HIGH SIERRA format \n");
+    exit(-1);
+  }
+
+  
+  if (Read_Info)
+  {
+    if (Iso9660) 
+      iso_info(Iso_Vol_Desc);
+    else 
+      hs_info(Hs_Vol_Desc);
+    exit(0);
+  }
+
+  /* Lookup file */
+  if ((entry = look_up(path)) != NULL_DIR)
+  {
+    if (Read_Dir)
+      if (Recurse) recurse_dir(path,entry);
+      else list_dir(entry);
+    else
+      list_file(entry);
+  }
+  else
+  {
+    if (Read_Dir)
+      fprintf (STDERR, "Directory");
+    else
+      fprintf (STDERR, "File");
+    fprintf (STDERR, " %s not found\n", path);
+    exit(-1);
+  }
+  return 0;
+}
+
+
+struct dir_entry *look_up(path)
+char *path;
+{
+  /* Lookup a file name */
+
+  struct dir_entry *dir_ptr;
+  long block;
+  int nr_of_blocks;
+  int offset;
+  char name[MAX_NAME_LENGTH + 1];
+  int name_index = 0;
+  int last_in_path = 0;
+  int found;
+  int i,j;
+
+  /* Get the right dir entry structure */
+  if (Iso9660)
+    dir_ptr = (struct dir_entry *) Iso_Vol_Desc->root_dir_entry;  
+  else
+    dir_ptr = (struct dir_entry *) Hs_Vol_Desc->root_dir_entry;  
+
+  /* If we look for the root we already have the right entry */
+  if (path[0] == '/')
+    if (strlen(path) == 1) return dir_ptr;
+    else name_index = 1; /* first name in path */
+
+  /* Keep searching for the path elements until all are found */
+  while (!last_in_path)
+  {
+    /* Get next name in path */ 
+    for (i = name_index; i < strlen(path); i++)
+    {
+      if (path[i] == '/') break;
+      name[i - name_index] = path[i];
+    }
+    last_in_path = 
+           (i == strlen(path) || (i == strlen(path) - 1 && path[i] == '/'));
+    name[i-name_index] = '\0';
+    name_index = i + 1;
+   
+    /* Get block of next directory */
+    block = iso_733(dir_ptr->first_block) + iso_711(dir_ptr->ext_attr_length);
+    nr_of_blocks = (iso_733(dir_ptr->size) + (BLOCK_SIZE-1)) >> BLOCK_SHIFT;
+
+    /* Search for file in dir entry */
+    found = 0;
+    for (j=0; j < nr_of_blocks && !found; j++) 
+    {
+      /* Read a directory block */
+      read_device(block*BLOCK_SIZE, BLOCK_SIZE, Buffer);
+      block++;
+
+      dir_ptr = (struct dir_entry *) Buffer;
+
+      offset = 0;
+      /* Compare with all entries in this block */
+      while (iso_711(dir_ptr->length) > 0 && offset < BLOCK_SIZE)
+      {
+        if (iso_cmp(name, dir_ptr,
+            (Read_Dir || (!Read_Dir && !last_in_path))) == 0) 
+        {
+          found = 1;
+          break;
+        }
+        /* Next entry */
+        offset += iso_711(dir_ptr->length);
+        dir_ptr = (struct dir_entry *) (Buffer + offset);
+      }
+    }
+    if (!found) return NULL_DIR;   /* path element not found */ 
+  }
+  return dir_ptr;
+}
+  
+
+void recurse_dir(path, dir_ptr)
+char *path;
+struct dir_entry *dir_ptr;
+{
+  /* Recursively descend all directories starting with dir_ptr */
+
+  char tmp_path[MAX_PATH_LENGTH];
+  int i,j, path_length;
+  long block, saveblock, dblock;
+  int nr_of_blocks;
+  int offset = 0; 
+
+  
+  /* Save block number and nr of blocks of current dir entry because 
+   * list_dir changes dir_ptr 
+   */
+  block = iso_733(dir_ptr->first_block) + iso_711(dir_ptr->ext_attr_length);
+  nr_of_blocks = (iso_733(dir_ptr->size) + (BLOCK_SIZE-1)) >> BLOCK_SHIFT;
+
+  /* Add a trailing / to path if necessary */
+  path_length = strlen(path);
+  if (path[path_length-1] != '/')
+  {
+    path[path_length++] = '/';
+    path[path_length] = '\0';
+  }
+
+  /* Print current path of directory, and list contents of directory */
+  fprintf(STDOUT,"directory %s:\n\n", path);
+  list_dir(dir_ptr);
+  fprintf(STDOUT,"\n\n");
+  
+  for (j=0; j < nr_of_blocks; j++) 
+  {
+    read_device(block*BLOCK_SIZE, BLOCK_SIZE, Buffer);
+    saveblock = block++;
+
+    /* Save buffer, because the next recursive call destroys 
+     * the global Buffer 
+     */
+    dir_ptr = (struct dir_entry *) Buffer;
+
+    /* Search this dir entry for directories */
+    offset = 0;
+    while (iso_711(dir_ptr->length) != 0 && offset < BLOCK_SIZE)
+    {
+      /* Is current file a directory and not the . or .. entries */
+      if (IS_DIR(dir_ptr)  && !IS_DOT(dir_ptr) && !IS_DOT_DOT(dir_ptr))
+      {
+        /* setup path for next recursive call */
+        for (i=0; i<path_length; i++) tmp_path[i] = path[i]; 
+        for (i=0;i<iso_711(dir_ptr->name_length) && dir_ptr->name[i] != ';';i++)
+          tmp_path[i+path_length] = LOWER_CASE(dir_ptr->name[i]);
+        tmp_path[i+path_length] = '/';
+        tmp_path[i+1+path_length] = '\0';
+  
+        /* Read block of directory we found */
+        dblock = iso_733(dir_ptr->first_block);
+        read_device(dblock*BLOCK_SIZE, BLOCK_SIZE, Buffer);
+  
+        /* And start all over again with this entry */
+        recurse_dir(tmp_path, (struct dir_entry *) Buffer);
+
+        /* get the block we were looking at */
+        read_device(saveblock*BLOCK_SIZE, BLOCK_SIZE, Buffer);
+      }
+
+      /* Go to the next file in this directory */
+      offset += iso_711(dir_ptr->length);
+      dir_ptr = (struct dir_entry *) (Buffer + offset);
+    }
+  }
+}
+    
+
+void list_dir(dir_ptr)
+struct dir_entry *dir_ptr;
+{
+  /* List all entries in a directory */
+  int tty;
+  long block;
+  int nr_of_blocks;
+  int i,j;
+  int offset = 0;
+  char name[NR_OF_CHARS+NR_OF_BLANKS+1];
+  int name_len;
+  int column = 0;
+  int skip = 0;
+
+  tty = isatty(STDOUT_FILENO);
+  /* Get first block of directory */
+  block = iso_733(dir_ptr->first_block) + iso_711(dir_ptr->ext_attr_length);
+  nr_of_blocks = (iso_733(dir_ptr->size) + (BLOCK_SIZE-1)) >> BLOCK_SHIFT;
+
+  /* Read all directory blocks and display their contents */
+  for (j=0; j < nr_of_blocks; j++) 
+  {
+    read_device(block*BLOCK_SIZE, BLOCK_SIZE, Buffer);
+    block++;
+
+    dir_ptr = (struct dir_entry *) (Buffer);
+    offset = 0;
+    while (iso_711(dir_ptr->length) != 0 && offset < BLOCK_SIZE)
+    {
+      name_len = 0;
+      if (IS_DOT(dir_ptr))
+      {
+        name[name_len++] =  '.';
+        if (!Verbose) skip = 1;
+      }
+      else
+      {
+        if (IS_DOT_DOT(dir_ptr))
+        { 
+          name[name_len++] =  '.';
+          name[name_len++] =  '.';
+          if (!Verbose) skip = 1;
+        }
+        else
+        {
+          for (i=0; i<iso_711(dir_ptr->name_length) &&
+                    i<NR_OF_CHARS; i++) 
+          {
+            if (dir_ptr->name[i] == ';') break;
+            name[name_len++] = LOWER_CASE(dir_ptr->name[i]);
+          }
+          if (IS_DIR(dir_ptr) && tty) name[name_len++] = '/';
+        }
+      }
+      if (!skip)
+      {
+        if (ByteOffset)
+        {
+          fprintf (STDOUT, "%10ld ",
+            (iso_733(dir_ptr->first_block) + iso_711(dir_ptr->ext_attr_length))
+              * BLOCK_SIZE);
+        }
+        if (Verbose || ByteOffset)
+        {
+          fprintf (STDOUT, "%10ld ",  iso_733(dir_ptr->size));
+        }
+        if (Verbose)
+        {
+          print_dir_date(dir_ptr->date);
+          fprintf (STDOUT, " ");
+        }
+	if(!tty)
+		name[name_len] = '\0';
+	else {
+	        for(i=name_len; i<(NR_OF_CHARS+NR_OF_BLANKS); i++) name[i] = ' ';
+	        name[NR_OF_CHARS+NR_OF_BLANKS] = '\0';
+	}
+        fprintf(STDOUT, "%s", name);
+        if (!(Verbose || ByteOffset))
+        {
+          column++;
+          if (column >= NR_OF_COLS || !tty) 
+          {
+            column = 0;
+            fprintf(STDOUT,"\n");
+          }
+        }
+        else fprintf(STDOUT,"\n");
+      }
+      skip = 0;
+      offset += iso_711(dir_ptr->length);
+      dir_ptr = (struct dir_entry *) (Buffer+offset);
+    }
+  }
+  if (!Verbose && column) fprintf(STDOUT,"\n");
+}
+
+
+void print_dir_date(date)
+char *date;
+{
+  /* Print date in a directory entry */
+
+  int m;
+
+  m = iso_711(&date[1]) - 1;
+  if(m < 0 || m > 11)
+  	fprintf(STDOUT, "   ");
+  else
+	fprintf(STDOUT,"%.3s",&months[m*3]);
+
+  fprintf (STDOUT, " %02d %04d %02d:%02d:%02d",
+           date[2],
+           1900+date[0],
+           date[3],
+           date[4],
+           date[5]);
+}
+
+
+void list_file(dir_ptr)
+struct dir_entry *dir_ptr;
+{
+  /* List contents of a file */
+
+  int i;
+  long block;
+  long size;
+  char c;
+
+  block = iso_733(dir_ptr->first_block);
+  size = iso_733(dir_ptr->size);
+
+  if (ByteOffset) {
+    fprintf(STDOUT, "%ld %ld\n", block*BLOCK_SIZE, size);
+    return;
+  }
+
+  while (size > 0)
+  if (Aflag == 1) {
+    read_device(block*BLOCK_SIZE, BLOCK_SIZE, Buffer);
+      for (i=0; ((i < size) && (i < BLOCK_SIZE)); i++)
+        if (Buffer[i] != '\r') fprintf(STDOUT, "%c", Buffer[i]);
+    size-= BLOCK_SIZE;
+    block++;
+  } else {
+    read_device(block*BLOCK_SIZE, BLOCK_SIZE, Buffer);
+      for (i=0; ((i < size) && (i < BLOCK_SIZE)); i++)
+        fprintf(STDOUT, "%c", Buffer[i]);
+    size-= BLOCK_SIZE;
+    block++;
+  }
+}
+
+
+void print_date(date)
+char *date;
+{
+  /* Print the date in a volume descriptor */
+
+  fprintf (STDOUT, "%c%c-%c%c-%c%c%c%c %c%c:%c%c:%c%c",
+           date[4],
+           date[5],
+           date[6],
+           date[7],
+           date[0],
+           date[1],
+           date[2],
+           date[3],
+           date[8],
+           date[9],
+           date[10],
+           date[11],
+           date[12],
+           date[13]);
+}
+
+void iso_info(vol_desc)
+struct iso9660_descriptor *vol_desc;
+{
+  int i;
+
+  fprintf (STDOUT, "Format: ISO9660 \n");
+  fprintf (STDOUT, "System id: ");
+  for (i=0; i< sizeof(vol_desc->system_id); i++) 
+    fprintf(STDOUT, "%c", vol_desc->system_id[i]);
+  fprintf (STDOUT, "\n");
+  fprintf (STDOUT, "Volume id: ");
+  for (i=0; i< sizeof(vol_desc->volume_id); i++) 
+    fprintf(STDOUT, "%c", vol_desc->volume_id[i]);
+  fprintf (STDOUT, "\n");
+  fprintf (STDOUT, "Volume size: %ld Kb\n", iso_733(vol_desc->volume_size)*2);
+  fprintf (STDOUT, "Block size: %d bytes \n", iso_723(vol_desc->block_size));
+  fprintf (STDOUT, "Creation date: ");
+  print_date(vol_desc->creation_date); 
+  fprintf(STDOUT, "\n");
+  fprintf (STDOUT, "Modification date: ");
+  print_date(vol_desc->mod_date); 
+  fprintf (STDOUT, "\n");
+  fprintf (STDOUT, "Expiration date: ");
+  print_date(vol_desc->exp_date); 
+  fprintf (STDOUT, "\n");
+  fprintf (STDOUT, "Effective date: ");
+  print_date(vol_desc->eff_date); 
+  fprintf (STDOUT, "\n");
+}
+
+
+void hs_info(vol_desc)
+struct high_sierra_descriptor *vol_desc;
+{
+  int i;
+
+  fprintf (STDOUT, "Format: HIGH SIERRA \n");
+  fprintf (STDOUT, "System id: ");
+  for (i=0; i< sizeof(vol_desc->system_id); i++) 
+    fprintf(STDOUT, "%c", vol_desc->system_id[i]);
+  fprintf (STDOUT, "\n");
+  fprintf (STDOUT, "Volume id: ");
+  for (i=0; i< sizeof(vol_desc->volume_id); i++) 
+    fprintf(STDOUT, "%c", vol_desc->volume_id[i]);
+  fprintf (STDOUT, "\n");
+  fprintf (STDOUT, "Volume size: %ld Kb\n", (iso_733(vol_desc->volume_size)*2));
+  fprintf (STDOUT, "Block size: %d bytes \n", iso_723(vol_desc->block_size));
+}
+  
+
+int valid_fs()               
+{
+
+  int i;
+
+  /* search for a volume descriptor */
+  for (i=16; i<100; i++)
+  {
+  
+    read_device((long)(i)*BLOCK_SIZE, BLOCK_SIZE, Buffer);
+
+    Iso_Vol_Desc = (struct iso9660_descriptor *) Buffer; 
+    Hs_Vol_Desc = (struct high_sierra_descriptor *) Buffer; 
+    
+    if (strncmp(Iso_Vol_Desc->id, ISO9660_ID, sizeof Iso_Vol_Desc->id) == 0)
+    {
+      /* iso_info(Iso_Vol_Desc); */
+      Iso9660 = 1;
+      break;  
+    }
+
+    if (strncmp(Hs_Vol_Desc->id, HIGH_SIERRA_ID, sizeof Hs_Vol_Desc->id) == 0)
+    {
+      /* hs_info(Hs_Vol_Desc); */
+      High_Sierra = 1; 
+      break;  
+    }
+  }
+
+  if (i >= 100) return 0;
+  return 1;
+}
+
+
+void read_device(offset, nr_of_bytes, buffer)
+long offset;
+int nr_of_bytes;
+char *buffer;
+{
+  int bytes_read;
+
+  if (lseek(Device, offset, SEEK_SET) == -1) 
+  {
+	fflush (stdout);
+	fprintf (STDERR, "seek error: %s\n", strerror(errno));
+	exit(1);
+  }
+
+  bytes_read = read(Device, buffer, nr_of_bytes);
+  if (bytes_read != nr_of_bytes) 
+  {
+  	fprintf (STDERR, "read error: %s\n",
+	    bytes_read >= 0 ? "Short read" : strerror(errno));
+  	exit (1);
+  }
+}
+
+
+/* The ISO9660 functions */
+
+int iso_711 (c)
+char *c;
+{
+  return (*c & 0xff);
+}
+
+
+int iso_712 (c)
+char *c;
+{
+  int n;
+	
+  n = *c;
+  if (n & 0x80) n |= 0xffffff00;
+  return n;
+}
+
+int iso_721 (c)
+char *c;
+{
+  return ((c[0] & 0xff) | ((c[1] & 0xff) << 8));
+}
+
+int iso_722 (c)
+char *c;
+{
+  return (((c[0] & 0xff) << 8) | (c[1] & 0xff));
+}
+
+int iso_723 (c)
+char *c;
+{
+  if (c[0] != c[3] || c[1] != c[2]) 
+  {
+    fprintf (STDERR, "Invalid ISO 7.2.3 number\n");
+    exit (1);
+  }
+  return (iso_721 (c));
+}
+
+long iso_731 (c)
+char *c;
+{
+  return ((long)(c[0] & 0xff)
+       | ((long)(c[1] & 0xff) << 8)
+       | ((long)(c[2] & 0xff) << 16)
+       | ((long)(c[3] & 0xff) << 24));
+}
+
+
+long iso_732 (c)
+char *c;
+{
+  return (((long)(c[0] & 0xff) << 24)
+        | (((long)c[1] & 0xff) << 16)
+        | (((long)c[2] & 0xff) << 8)
+        | ((long)c[3] & 0xff));
+}
+
+long iso_733 (c)
+char *c;
+{
+int i;
+
+  for (i = 0; i < 4; i++) 
+  {
+    if (c[i] != c[7-i]) 
+    {
+      fprintf (STDERR, "Invalid ISO 7.3.3 number\n");
+      exit (1);
+    }
+  }
+  return (iso_731(c));
+}
Index: /trunk/minix/commands/simple/join.c
===================================================================
--- /trunk/minix/commands/simple/join.c	(revision 9)
+++ /trunk/minix/commands/simple/join.c	(revision 9)
@@ -0,0 +1,360 @@
+/* join - relation data base operator	Author:  Saeko Hirabayashi */
+
+/* Written by Saeko Hirabayashi, 1989.
+ * 1992-01-28 Modified by Kouichi Hirabayashi to add some POSIX1003.2 options.
+ *
+ * This a free program.
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#define MAXFLD	200		/* maximum # of fields to accept */
+
+_PROTOTYPE(void main, (int argc, char **argv));
+_PROTOTYPE(void error, (char *s, char *t));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(void match, (void));
+_PROTOTYPE(void f1_only, (void));
+_PROTOTYPE(void f2_only, (void));
+_PROTOTYPE(void output, (int flag));
+_PROTOTYPE(void outfld, (int file));
+_PROTOTYPE(void outputf, (int flag));
+_PROTOTYPE(int compare, (void));
+_PROTOTYPE(int get1, (void));
+_PROTOTYPE(int get2, (int back));
+_PROTOTYPE(int getrec, (int file));
+_PROTOTYPE(int split, (int file));
+_PROTOTYPE(int atoi, (char *str));
+_PROTOTYPE(int exit, (int val));
+_PROTOTYPE(FILE * efopen, (char *file, char *mode));
+_PROTOTYPE(void (*outfun), (int file));	/* output func: output() or outputf()*/
+
+#define F1	1
+#define F2	2
+#define SEP	(sep ? sep : ' ')
+
+FILE *fp[2];			/* file pointer for file1 and file2 */
+long head;			/* head of the current (same)key group of the
+				 * file2 */
+
+char buf[2][BUFSIZ];		/* input buffer for file1 and file2 */
+char *fld[2][MAXFLD];		/* field vector for file1 and file2 */
+int nfld[2];			/* # of fields for file1 and file2 */
+
+int kpos[2];			/* key field position for file1 and file2
+				 * (from 0) */
+char oldkey[BUFSIZ];		/* previous key of the file1 */
+
+struct {			/* output list by -o option */
+  int o_file;			/* file #: 0 or 1 */
+  int o_field;			/* field #: 0, 1, 2, .. */
+} olist[MAXFLD];
+int nout;			/* # of output filed */
+
+int aflag;			/* n for '-an': F1 or F2 or both */
+int vflag;			/* n for '-vn': F1 or F2 or both */
+char *es;			/* s for '-e s' */
+char sep;			/* c for -tc: filed separator */
+char *cmd;			/* name of this program */
+
+void main(argc, argv)
+int argc;
+char **argv;
+{
+  register char *s;
+  int c, i, j;
+
+  cmd = argv[0];
+  outfun = output;		/* default output form */
+
+  while (--argc > 0 && (*++argv)[0] == '-' && (*argv)[1]) {
+	/* "-" is a file name (stdin) */
+	s = argv[0] + 1;
+	if ((c = *s) == '-' && !s[1]) {
+		++argv;
+		--argc;
+		break;		/* -- */
+	}
+	if (*++s == '\0') {
+		s = *++argv;
+		--argc;
+	}
+	switch (c) {
+	    case 'a':		/* add unpairable line to output */
+		vflag = 0;
+		switch (*s) {
+		    case '1':	aflag |= F1;	break;
+		    case '2':	aflag |= F2;	break;
+		    default:	aflag |= (F1 | F2);	break;
+		}
+		break;
+
+	    case 'e':		/* replace empty field by es */
+		es = s;
+		break;
+
+	    case 'j':		/* key field (obsolute) */
+		c = *s++;
+		if (*s == '\0') {
+			s = *++argv;
+			--argc;
+		}
+
+	    case '1':		/* key field of file1 */
+	    case '2':		/* key field of file2 */
+		i = atoi(s) - 1;
+
+		switch (c) {
+		    case '1':	kpos[0] = i;	break;
+		    case '2':	kpos[1] = i;	break;
+	            default:	kpos[0] = kpos[1] = i;
+				break;
+		}
+		break;
+
+	    case 'o':		/* specify output format */
+		do {
+			i = j = 0;
+			sscanf(s, "%d.%d", &i, &j);
+			if (i < 1 || j < 1 || i > 2) usage();
+			olist[nout].o_file = i - 1;
+			olist[nout].o_field = j - 1;
+			nout++;
+			if ((s = strchr(s, ',')) != (char *) 0)
+				s++;
+			else {
+				s = *++argv;
+				--argc;
+			}
+		} while (argc > 2 && *s != '-');
+		++argc;
+		--argv;		/* compensation */
+		outfun = outputf;
+		break;
+
+	    case 't':		/* tab char */
+		sep = *s;
+		break;
+
+	    case 'v':		/* output unpairable line only */
+		aflag = 0;
+		switch (*s) {
+		    case '1':	vflag |= F1;	break;
+		    case '2':	vflag |= F2;	break;
+		    default:	vflag |= (F1 | F2);	break;
+		}
+		break;
+
+	    default:	usage();
+	}
+  }
+  if (argc != 2) usage();
+
+  fp[0] = strcmp(argv[0], "-") ? efopen(argv[0], "r") : stdin;
+  fp[1] = efopen(argv[1], "r");
+
+  nfld[0] = get1();		/* read file1 */
+  nfld[1] = get2(0);		/* read file2 */
+
+  while (nfld[0] || nfld[1]) {
+	if ((i = compare()) == 0)
+		match();
+	else if (i < 0)
+		f1_only();
+	else
+		f2_only();
+  }
+  fflush(stdout);
+
+  exit(0);
+}
+
+void usage()
+{
+  fprintf(stderr,
+    "Usage: %s [-an|-vn] [-e str] [-o list] [-tc] [-1 f] [-2 f] file1 file2\n",
+    cmd);
+  exit(1);
+}
+
+int compare()
+{				/* compare key field */
+  register int r;
+
+  if (nfld[1] == 0)		/* file2 EOF */
+	r = -1;
+  else if (nfld[0] == 0)	/* file1 EOF */
+	r = 1;
+  else {
+	if (nfld[0] <= kpos[0])
+		error("missing key field in file1", (char *) 0);
+	if (nfld[1] <= kpos[1])
+		error("missing key field in file2", (char *) 0);
+
+	r = strcmp(fld[0][kpos[0]], fld[1][kpos[1]]);
+  }
+  return r;
+}
+
+void match()
+{
+  long p;
+
+  if (!vflag) (*outfun) (F1 | F2);
+
+  p = ftell(fp[1]);
+  nfld[1] = get2(0);		/* check key order */
+  if (nfld[1] == 0 || strcmp(fld[0][kpos[0]], fld[1][kpos[1]])) {
+	nfld[0] = get1();
+	if (strcmp(fld[0][kpos[0]], oldkey) == 0) {
+		fseek(fp[1], head, 0);	/* re-do from head */
+		nfld[1] = get2(1);	/* don't check key order */
+	} else
+		head = p;	/* mark here */
+  }
+}
+
+void f1_only()
+{
+  if ((aflag & F1) || (vflag & F1)) (*outfun) (F1);
+  nfld[0] = get1();
+}
+
+void f2_only()
+{
+  if ((aflag & F2) || (vflag & F2)) (*outfun) (F2);
+  head = ftell(fp[1]);		/* mark */
+  nfld[1] = get2(0);		/* check key order */
+}
+
+void output(f)
+{				/* default output form */
+  if (f & F1)
+	fputs(fld[0][kpos[0]], stdout);
+  else
+	fputs(fld[1][kpos[1]], stdout);
+  if (f & F1) outfld(0);
+  if (f & F2) outfld(1);
+  fputc('\n', stdout);
+}
+
+void outfld(file)
+{				/* output all fields except key_field */
+  register int i;
+  int k, n;
+
+  k = kpos[file];
+  n = nfld[file];
+  for (i = 0; i < n; i++)
+	if (i != k) {
+		fputc(SEP, stdout);
+		fputs(fld[file][i], stdout);
+	}
+}
+
+void outputf(f)
+{				/* output by '-o list' */
+  int i, j, k;
+  register char *s;
+
+  for (i = k = 0; i < nout; i++) {
+	j = olist[i].o_file;
+	if ((f & (j + 1)) && (olist[i].o_field < nfld[j]))
+		s = fld[j][olist[i].o_field];
+	else
+		s = es;
+	if (s) {
+		if (k++) fputc(SEP, stdout);
+		fputs(s, stdout);
+	}
+  }
+  fputc('\n', stdout);
+}
+
+int get1()
+{				/* read file1 */
+  int r;
+  static char oldkey1[BUFSIZ];
+
+  if (fld[0][kpos[0]]) {
+        strcpy(oldkey, fld[0][kpos[0]]);  /* save previous key for control */
+  }
+  r = getrec(0);
+
+  if (r) {
+        if (strcmp(oldkey1, fld[0][kpos[0]]) > 0)
+	      error("file1 is not sorted", (char *) 0);
+        strcpy(oldkey1, fld[0][kpos[0]]);  /* save prev key for sort check */
+  }
+  return r;
+}
+
+int get2(back)
+{				/* read file2 */
+  static char oldkey2[BUFSIZ];
+  int r;
+
+  r = getrec(1);
+
+  if (r) {
+        if (!back && strcmp(oldkey2, fld[1][kpos[1]]) > 0)
+	      error("file2 is not sorted", (char *) 0);
+        strcpy(oldkey2, fld[1][kpos[1]]);  /* save prev key for sort check */
+  }
+  return r;
+}
+
+int getrec(file)
+{				/* read one line to split it */
+  if (fgets(buf[file], BUFSIZ, fp[file]) == (char *) 0)
+	*buf[file] = '\0';
+  else if (*buf[file] == '\n' || *buf[file] == '\r')
+	error("null line in file%s", file ? "1" : "0");
+
+  return split(file);
+}
+
+int split(file)
+{				/* setup fields */
+  register int n;
+  register char *s, *t;
+
+  for (n = 0, s = buf[file]; *s && *s != '\n' && *s != '\r';) {
+	if (sep) {
+		for (t = s; *s && *s != sep && *s != '\n' && *s != '\r'; s++);
+	} else {
+		while (*s == ' ' || *s == '\t')
+			s++;	/* skip leading white space */
+		for (t = s; *s && *s != ' ' && *s != '\t'
+		     && *s != '\n' && *s != '\r'; s++);
+		/* We will treat trailing white space as NULL field */
+	}
+	if (*s) *s++ = '\0';
+	fld[file][n++] = t;
+	if (n == MAXFLD) error("too many filed in file%s", file ? "1" : "0");
+  }
+  fld[file][n] = (char *) 0;
+
+  return n;
+}
+
+FILE *efopen(file, mode)
+char *file, *mode;
+{
+  FILE *fp;
+
+  if ((fp = fopen(file, mode)) == (FILE *) 0) error("can't open %s", file);
+
+  return fp;
+}
+
+void error(s, t)
+char *s, *t;
+{
+  fprintf(stderr, "%s: ", cmd);
+  fprintf(stderr, s, t);
+  fprintf(stderr, "\n");
+
+  exit(1);
+}
Index: /trunk/minix/commands/simple/kill.c
===================================================================
--- /trunk/minix/commands/simple/kill.c	(revision 9)
+++ /trunk/minix/commands/simple/kill.c	(revision 9)
@@ -0,0 +1,100 @@
+/* kill - send a signal to a process	Author: Adri Koppes  */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void usage, (void));
+
+/* Table of signal names. */
+struct signames {
+	char *name;
+	int sig;
+} signames[] = {
+	{ "HUP",	SIGHUP		},
+	{ "INT",	SIGINT		},
+	{ "QUIT",	SIGQUIT		},
+	{ "ILL",	SIGILL		},
+	{ "TRAP",	SIGTRAP		},
+	{ "ABRT",	SIGABRT		},
+	{ "IOT",	SIGIOT		},
+	{ "FPE",	SIGFPE		},
+	{ "KILL",	SIGKILL		},
+	{ "USR1",	SIGUSR1		},
+	{ "SEGV",	SIGSEGV		},
+	{ "USR2",	SIGUSR2		},
+	{ "PIPE",	SIGPIPE		},
+	{ "ALRM",	SIGALRM		},
+	{ "TERM",	SIGTERM		},
+	{ "EMT",	SIGEMT		},
+	{ "BUS",	SIGBUS		},
+	{ "CHLD",	SIGCHLD		},
+	{ "CONT",	SIGCONT		},
+	{ "STOP",	SIGSTOP		},
+	{ "TSTP",	SIGTSTP		},
+	{ "TTIN",	SIGTTIN		},
+	{ "TTOU",	SIGTTOU		},
+#ifdef SIGWINCH
+	{ "WINCH",	SIGWINCH	},
+#endif
+	{ NULL,		0		}
+};
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  pid_t proc;
+  int ex = 0, sig = SIGTERM;
+  char *end;
+  long l;
+  unsigned long ul;
+  struct sigaction sa;
+  int i, doit;
+  struct signames *snp;
+
+  if (argc > 1 && argv[1][0] == '-') {
+	sig = -1;
+	for (snp = signames; snp->name != NULL; snp++) {	/* symbolic? */
+		if (strcmp(snp->name, argv[1] + 1) == 0) {
+			sig = snp->sig;
+			break;
+		}
+	}
+	if (sig < 0) {						/* numeric? */
+		ul = strtoul(argv[1] + 1, &end, 10);
+		if (end == argv[1] + 1 || *end != 0 || ul > _NSIG) usage();
+		sig = ul;
+	}
+	argv++;
+	argc--;
+  }
+  sa.sa_flags = 0;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_handler = SIG_IGN;		/* try not to kill yourself */
+  (void) sigaction(sig, &sa, (struct sigaction *) NULL);
+
+  for (doit = 0; doit <= 1; doit++) {
+	for (i = 1; i < argc; i++) {
+		l = strtoul(argv[i], &end, 10);
+		if (end == argv[i] || *end != 0 || (pid_t) l != l) usage();
+		proc = l;
+		if (doit && kill(proc, sig) < 0) {
+			fprintf(stderr, "kill: %d: %s\n",
+				proc, strerror(errno));
+			ex = 1;
+		}
+	}
+  }
+  return(ex);
+}
+
+void usage()
+{
+  fprintf(stderr, "Usage: kill [-sig] pid\n");
+  exit(1);
+}
Index: /trunk/minix/commands/simple/last.c
===================================================================
--- /trunk/minix/commands/simple/last.c	(revision 9)
+++ /trunk/minix/commands/simple/last.c	(revision 9)
@@ -0,0 +1,481 @@
+/* last - display login history			Author: Terrence W. Holm */
+
+/* last-	Display the user log-in history.
+ *		Last(1) searches backwards through the file of log-in
+ *		records (/usr/adm/wtmp), displaying the length of
+ *		log-in sessions as requested by the options:
+ *
+ * Usage:	last [-r] [-count] [-f file] [name] [tty] ...
+ *
+ *		-r	Search backwards only until the last reboot
+ *			record.
+ *
+ *		-count	Only print out <count> records. Last(1) stops
+ *			when either -r or -count is satisfied, or at
+ *			the end of the file if neither is given.
+ *
+ *		-f file	Use "file" instead of "/usr/adm/wtmp".
+ *
+ *		name	Print records for the user "name".
+ *
+ *		tty	Print records for the terminal "tty". Actually,
+ *			a list of names may be given and all records
+ *			that match either the user or tty name are
+ *			printed. If no names are given then all records
+ *			are displayed.
+ *
+ *		A sigquit (^\) causes last(1) to display how far it
+ *		has gone back in the log-in record file, it then
+ *		continues. This is used to check on the progress of
+ *		long running searches. A sigint will stop last(1).
+ *
+ * Author:	Terrence W. Holm	May 1988
+ *
+ * Revision:
+ *		Fred van Kempen, October 1989
+ *		 -Adapted to MSS.
+ *		 -Adapted to new utmp database.
+ *
+ *		Fred van Kempen, December 1989
+ *		 -Adapted to POSIX (MINIX 1.5)
+ *
+ *		Fred van Kempen, January 1990
+ *		 -Final edit for 1.5
+ *
+ *		Philip Homburg, March 1992
+ *		 -Include host in output
+ *
+ *		Kees J. Bot, July 1997
+ *		 -Approximate system uptime from last reboot record
+ */
+#include <sys/types.h>
+#include <signal.h>
+#include <string.h>
+#include <utmp.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <minix/paths.h>
+
+#define  FALSE	0
+#define  TRUE	1
+#define  RLOGIN	1
+
+#define  BUFFER_SIZE     4096	/* Room for wtmp records */
+#define  MAX_WTMP_COUNT  ( BUFFER_SIZE / sizeof(struct utmp) )
+
+#define  min( a, b )     ( (a < b) ? a : b )
+#define  max( a, b )	 ( (a > b) ? a : b )
+
+
+typedef struct logout {		/* A logout time record */
+  char line[12];		/* The terminal name */
+  long time;			/* The logout time */
+  struct logout *next;		/* Next in linked list */
+} logout;
+
+
+static char *Version = "@(#) LAST 1.7 (10/24/92)";
+
+
+/* command-line option flags */
+char boot_limit = FALSE;	/* stop on latest reboot */
+char count_limit = FALSE;	/* stop after print_count */
+char tell_uptime = FALSE;	/* tell uptime since last reboot */
+int print_count;
+char *prog;			/* name of this program */
+int arg_count;			/* used to select specific */
+char **args;			/* users and ttys */
+
+/* global variables */
+long boot_time = 0;		/* Zero means no reboot yet */
+char *boot_down;		/* "crash" or "down " flag */
+logout *first_link = NULL;	/* List of logout times */
+int interrupt = FALSE;		/* If sigint or sigquit occurs */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void Sigint, (int sig));
+_PROTOTYPE(void Sigquit, (int sig));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(void Process, (struct utmp *wtmp));
+_PROTOTYPE(int Print_Record, (struct utmp *wtmp));
+_PROTOTYPE(void Print_Duration, (long from, long to));
+_PROTOTYPE(void Print_Uptime, (void));
+_PROTOTYPE(void Record_Logout_Time, (struct utmp *wtmp));
+
+/* Sigint() and Sigquit() Flag occurrence of an interrupt. */
+void Sigint(sig)
+int sig;
+{
+  interrupt = SIGINT;
+}
+
+
+void Sigquit(sig)
+int sig;
+{
+  interrupt = SIGQUIT;
+}
+
+
+void usage()
+{
+  fprintf(stderr,
+	"Usage: last [-r] [-u] [-count] [-f file] [name] [tty] ...\n");
+  exit(-1);
+}
+
+
+/* A log-in record format file contains four types of records.
+ *
+ *  [1] generated on a system reboot:
+ *
+ *	line="~", name="reboot", host="", time=date()
+ *
+ *
+ *  [2] generated after a shutdown:
+ *
+ *	line="~", name="shutdown", host="", time=date()
+ *
+ *
+ *  [3] generated on a successful login(1)
+ *
+ *	line=ttyname(), name=cuserid(), host=, time=date()
+ *
+ *
+ *  [4] generated by init(8) on a logout
+ *
+ *	line=ttyname(), name="", host="", time=date()
+ *
+ *
+ * Note: This version of last(1) does not recognize the '|' and '}' time
+ *	 change records. Last(1) pairs up line login's and logout's to
+ *	 generate four types of output lines:
+ *
+ *	  [1] a system reboot or shutdown
+ *
+ *	   reboot    ~       Mon May 16 14:16
+ *	   shutdown  ~       Mon May 16 14:15
+ *
+ *	  [2] a login with a matching logout
+ *
+ *	   edwin     tty1    Thu May 26 20:05 - 20:32  (00:27)
+ *
+ *	  [3] a login followed by a reboot or shutdown
+ *
+ *	   root      tty0    Mon May 16 13:57 - crash  (00:19)
+ *	   root      tty1    Mon May 16 13:45 - down   (00:30)
+ *
+ *	  [4] a login not followed by a logout or reboot
+ *
+ *	   terry     tty0    Thu May 26 21:19   still logged in
+ */
+void Process(wtmp)
+struct utmp *wtmp;
+{
+  logout *link;
+  logout *next_link;
+  char is_reboot;
+
+  /* suppress the job number on an "ftp" line */
+  if (!strncmp(wtmp->ut_line, "ftp", (size_t)3)) strncpy(wtmp->ut_line, "ftp", (size_t)8);
+
+  if (!strcmp(wtmp->ut_line, "~")) {
+	/* A reboot or shutdown record  */
+	if (boot_limit) exit(0);
+
+	if (Print_Record(wtmp)) putchar('\n');
+	boot_time = wtmp->ut_time;
+
+	is_reboot = !strcmp(wtmp->ut_name, "reboot");
+	if (is_reboot)
+		boot_down = "crash";
+	else
+		boot_down = "down ";
+
+	if (tell_uptime) {
+		if (!is_reboot) {
+			fprintf(stderr,
+		"%s: no reboot record added to wtmp file on system boot!\n",
+				prog);
+			exit(1);
+		}
+		Print_Uptime();
+		exit(0);
+	}
+
+	/* remove any logout records */
+	for (link = first_link; link != NULL; link = next_link) {
+		next_link = link->next;
+		free(link);
+	}
+	first_link = NULL;
+  } else if (wtmp->ut_name[0] == '\0') {
+	/* A logout record */
+	Record_Logout_Time(wtmp);
+  } else {
+	/* A login record */
+	for (link = first_link; link != NULL; link = link->next)
+		if (!strncmp(link->line, wtmp->ut_line, (size_t)8)) {
+			/* found corresponding logout record */
+			if (Print_Record(wtmp)) {
+				printf("- %.5s ", ctime(&link->time) + 11);
+				Print_Duration(wtmp->ut_time, link->time);
+			}
+			/* record login time */
+			link->time = wtmp->ut_time;
+			return;
+		}
+	/* could not find a logout record for this login tty */
+	if (Print_Record(wtmp))
+		if (boot_time == 0)	/* still on */
+			printf("  still logged in\n");
+		else {		/* system crashed while on */
+			printf("- %s ", boot_down);
+			Print_Duration(wtmp->ut_time, boot_time);
+		}
+	Record_Logout_Time(wtmp);	/* Needed in case of 2
+					 * consecutive logins  */
+  }
+}
+
+
+/* Print_Record(wtmp) If the record was requested, then print out
+ * the user name, terminal, host and time.
+ */
+int Print_Record(wtmp)
+struct utmp *wtmp;
+{
+  int i;
+  char print_flag = FALSE;
+
+  /* just interested in the uptime? */
+  if (tell_uptime) return(FALSE);
+
+  /* check if we have already printed the requested number of records */
+  if (count_limit && print_count == 0) exit(0);
+
+  for (i = 0; i < arg_count; ++i)
+	if (!strncmp(args[i], wtmp->ut_name, sizeof(wtmp->ut_name)) ||
+	    !strncmp(args[i], wtmp->ut_line, sizeof(wtmp->ut_line)))
+		print_flag = TRUE;
+
+  if (arg_count == 0 || print_flag) {
+#ifdef RLOGIN
+	printf("%-8.8s  %-8.8s %-16.16s %.16s ",
+	       wtmp->ut_name, wtmp->ut_line, wtmp->ut_host,
+	       ctime(&wtmp->ut_time));
+#else
+	printf("%-8.8s  %-8.8s  %.16s ",
+	       wtmp->ut_name, wtmp->ut_line, ctime(&wtmp->ut_time));
+#endif
+	--print_count;
+	return(TRUE);
+  }
+  return(FALSE);
+}
+
+
+/* Print_Duration(from, to) Calculate and print the days and hh:mm between
+ * the log-in and the log-out.
+ */
+void Print_Duration(from, to)
+long from;
+long to;
+{
+  long delta, days, hours, minutes;
+
+  delta = max(to - from, 0);
+  days = delta / (24L * 60L * 60L);
+  delta = delta % (24L * 60L * 60L);
+  hours = delta / (60L * 60L);
+  delta = delta % (60L * 60L);
+  minutes = delta / 60L;
+
+  if (days > 0)
+	printf("(%ld+", days);
+  else
+	printf(" (");
+
+  printf("%02ld:%02ld)\n", hours, minutes);
+}
+
+
+/* Print_Uptime() Calculate and print the "uptime" between the last recorded
+ * boot and the current time.
+ */
+void Print_Uptime()
+{
+#define NLOADS 3
+  int nloads;
+  double loads[NLOADS];
+  char *utmp_file = _PATH_UTMP;
+  unsigned nusers;
+  struct utmp ut;
+  FILE *uf;
+  time_t now;
+  struct tm *tm;
+  unsigned long up;
+
+  /* Count the number of active users in the utmp file. */
+  if ((uf = fopen(utmp_file, "r")) == NULL) {
+	fprintf(stderr, "%s: %s: %s\n", prog, utmp_file, strerror(errno));
+	exit(1);
+  }
+
+  nusers = 0;
+  while (fread(&ut, sizeof(ut), 1, uf) == 1) {
+#ifdef USER_PROCESS
+	if (ut.ut_type == USER_PROCESS) nusers++;
+#else
+	if (ut.ut_name[0] != 0 && ut.ut_line[0] != 0) nusers++;
+#endif
+  }
+  fclose(uf);
+
+  /* Current time. */
+  now = time((time_t *) NULL);
+  tm = localtime(&now);
+
+  /* Uptime. */
+  up = now - boot_time;
+
+  printf(" %d:%02d  up", tm->tm_hour, tm->tm_min);
+  if (up >= 24 * 3600L) {
+	unsigned long days = up / (24 * 3600L);
+	printf(" %lu day%s,", days, days == 1 ? "" : "s");
+  }
+  printf(" %lu:%02lu,", (up % (24 * 3600L)) / 3600, (up % 3600) / 60);
+  printf("  %u user%s", nusers, nusers == 1 ? "" : "s");
+  if((nloads = getloadavg(loads, NLOADS)) > 0) {
+	int i;
+	printf(", load averages:");
+	for(i = 0; i < nloads; i++)
+		printf("%s %.2f", (i > 0) ? "," : "", loads[i]);
+  }
+  printf("\n");
+}
+
+
+/* Record_Logout_Time(wtmp) A linked list of "last logout time" is kept.
+ * Each element of the list is for one terminal.
+ */
+void Record_Logout_Time(wtmp)
+struct utmp *wtmp;
+{
+  logout *link;
+
+  /* see if the terminal is already in the list */
+  for (link = first_link; link != NULL; link = link->next)
+	if (!strncmp(link->line, wtmp->ut_line, (size_t)8)) {
+		link->time = wtmp->ut_time;
+		return;
+	}
+  /* allocate a new logout record, for a tty not previously encountered */
+  link = (logout *) malloc(sizeof(logout));
+  if (link == NULL) {
+	fprintf(stderr, "%s: malloc failure\n", prog);
+	exit(1);
+  }
+  strncpy(link->line, wtmp->ut_line, (size_t)8);
+  link->time = wtmp->ut_time;
+  link->next = first_link;
+
+  first_link = link;
+}
+
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  char *wtmp_file = _PATH_WTMP;
+  FILE *f;
+  long size;			/* Number of wtmp records in the file	 */
+  int wtmp_count;		/* How many to read into wtmp_buffer	 */
+  struct utmp wtmp_buffer[MAX_WTMP_COUNT];
+
+  if ((prog = strrchr(argv[0], '/')) == NULL) prog = argv[0]; else prog++;
+
+  --argc;
+  ++argv;
+
+  while (argc > 0 && *argv[0] == '-') {
+	if (!strcmp(argv[0], "-r"))
+		boot_limit = TRUE;
+	else
+	if (!strcmp(argv[0], "-u"))
+		tell_uptime = TRUE;
+	else if (argc > 1 && !strcmp(argv[0], "-f")) {
+		wtmp_file = argv[1];
+		--argc;
+		++argv;
+	} else if ((print_count = atoi(argv[0] + 1)) > 0)
+		count_limit = TRUE;
+	else
+		usage();
+
+	--argc;
+	++argv;
+  }
+
+  arg_count = argc;
+  args = argv;
+
+  if (!strcmp(prog, "uptime")) tell_uptime = TRUE;
+
+  if ((f = fopen(wtmp_file, "r")) == NULL) {
+	perror(wtmp_file);
+	exit(1);
+  }
+  if (fseek(f, 0L, 2) != 0 || (size = ftell(f)) % sizeof(struct utmp) != 0) {
+	fprintf(stderr, "%s: invalid wtmp file\n", prog);
+	exit(1);
+  }
+  if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
+	signal(SIGINT, Sigint);
+	signal(SIGQUIT, Sigquit);
+  }
+  size /= sizeof(struct utmp);	/* Number of records in wtmp	 */
+
+  if (size == 0) wtmp_buffer[0].ut_time = time((time_t *)0);
+
+  while (size > 0) {
+	wtmp_count = (int) min(size, MAX_WTMP_COUNT);
+	size -= (long) wtmp_count;
+
+	fseek(f, size * sizeof(struct utmp), 0);
+
+
+	if (fread(&wtmp_buffer[0], sizeof(struct utmp), (size_t)wtmp_count, f)
+	    != wtmp_count) {
+		fprintf(stderr, "%s: read error on wtmp file\n", prog);
+		exit(1);
+	}
+	while (--wtmp_count >= 0) {
+		Process(&wtmp_buffer[wtmp_count]);
+		if (interrupt) {
+			printf("\ninterrupted %.16s \n",
+			   ctime(&wtmp_buffer[wtmp_count].ut_time));
+
+			if (interrupt == SIGINT) exit(2);
+
+			interrupt = FALSE;
+			signal(SIGQUIT, Sigquit);
+		}
+	}
+
+  }				/* end while(size > 0) */
+
+  if (tell_uptime) {
+	fprintf(stderr,
+		"%s: no reboot record in wtmp file to compute uptime from\n",
+		prog);
+	return(1);
+  }
+
+  printf("\nwtmp begins %.16s \n", ctime(&wtmp_buffer[0].ut_time));
+  return(0);
+}
Index: /trunk/minix/commands/simple/leave.c
===================================================================
--- /trunk/minix/commands/simple/leave.c	(revision 9)
+++ /trunk/minix/commands/simple/leave.c	(revision 9)
@@ -0,0 +1,210 @@
+/* Usage:	leave [ [+] hh[:]mm ]
+ *
+ * Author:	Terrence W. Holm
+ *
+ * Revision:
+ *		Fred van Kempen, MINIX User Group Holland
+ *		 -adapted to MSS
+ *		 -adapted to new utmp database
+ *		 -adapted to POSIX (MINIX 1.5)
+ *		Michael Temari, <temari@ix.netcom.com>
+ *		 -use localtime/mktime to fix bug with DST
+ */
+
+#include <sys/types.h>
+#include <signal.h>
+#include <time.h>
+#include <utmp.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+
+#define Min(a,b)  ((a<b) ? a : b)
+
+#define STRING	   80		/* lots of room for an argument */
+#define MIN	   60L		/* seconds per minute */
+#define HOUR      (60L*60L)	/* seconds per hour */
+
+/* Set the following to your personal preferences for the
+ * time and contents of warnings.
+ */
+#define INTERVALS 13		/* size of intervals[] */
+#define WARNINGS  4		/* size of warnings[] */
+
+
+static char *Version = "@(#) LEAVE 1.4 (01/09/90)";
+static int intervals[INTERVALS] = {
+  -5 * MIN,
+  -1 * MIN,
+  0,
+  MIN,
+  2 * MIN,
+  3 * MIN,
+  4 * MIN,
+  5 * MIN,
+  6 * MIN,
+  7 * MIN,
+  8 * MIN,
+  9 * MIN,
+  10 * MIN
+};
+static char *warnings[WARNINGS] = {
+  "You have to leave within 5 minutes",
+  "Just one more minute!",
+  "Time to leave!",
+  "You're going to be late!"	/* for all subsequent warnings */
+};
+
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void Usage, (void));
+_PROTOTYPE(void Get_Hour_Min, (char *when, int *hour, int *min));
+_PROTOTYPE(int Still_Logged_On, (char *user, char *tty));
+
+void Usage()
+{
+   fprintf(stderr, "Usage: leave [[+]hh[:]mm]\n");
+  exit(1);
+}
+
+
+void Get_Hour_Min(when, hour, min)
+char *when;
+int *hour;
+int *min;
+{
+  int hour_min;
+  int just_min = 0;
+
+  switch (sscanf(when, "%d:%d", &hour_min, &just_min)) {
+      case 1:
+	*hour = hour_min / 100;
+	*min = hour_min % 100;
+	break;
+      case 2:
+	*hour = hour_min;
+	*min = just_min;
+	break;
+      default:
+	Usage();
+  }
+
+  if (hour_min < 0 || just_min < 0 || *min > 59) Usage();
+}
+
+
+int Still_Logged_On(user, tty)
+char *user;
+char *tty;
+{
+  FILE *f;
+  struct utmp login;
+
+  if ((f = fopen(UTMP, "r")) == NULL)
+	/* no login/logout records kept */
+	return(1);
+
+  while (fread(&login, sizeof(struct utmp), (size_t)1, f) == 1) {
+	if (!strncmp(login.ut_line, tty, (size_t)8))
+		if (!strncmp(login.ut_name, user, (size_t)8)) {
+			fclose(f);
+			return(1);
+		} else {
+			fclose(f);
+			return(0);
+		}
+  }
+  fclose(f);
+  return(0);
+}
+
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  char when[STRING];
+  time_t now = time((time_t *)0);
+  time_t leave, delta;
+  struct tm *tm;
+  int hour, min;
+  int pid, i;
+  char *user = cuserid( (char *)NULL);
+  char *tty = ttyname(0) + 5;
+
+  /* get the argument string "when" either from stdin, or argv */
+  if (argc <= 1) {
+	printf("When do you have to leave? ");
+	fflush(stdout);
+	if (fgets(when, STRING, stdin) == NULL || when[0] == '\n') exit(0);
+  } else {
+	strcpy(when, argv[1]);
+	if (argc > 2) strcat(when, argv[2]);
+  }
+
+  /* determine the leave time from the current time and "when" */
+  tm = localtime(&now);
+  if (when[0] == '+') {
+	Get_Hour_Min(&when[1], &hour, &min);
+	tm->tm_hour += hour;
+	tm->tm_min += min;
+	leave = mktime(tm);
+  } else {
+	/* user entered an absolute time */
+	Get_Hour_Min(&when[0], &hour, &min);
+	tm->tm_hour = hour;
+	tm->tm_min = min;
+	leave = mktime(tm);
+	if (leave < now) {
+		printf("That time has already passed!\n");
+		exit(1);
+	}
+  }
+
+  printf("Alarm set for %s", ctime(&leave));
+
+  if ((pid = fork()) == -1) {
+	fprintf(stderr, "leave: can not fork\n");
+	exit(1);
+  }
+  if (pid != 0) exit(0);
+
+  /* only the child continues on */
+  if (user == NULL || tty == NULL) {
+	fprintf(stderr, "leave: Can not determine user and terminal name\n");
+	exit(1);
+  }
+  signal(SIGINT, SIG_IGN);
+  signal(SIGQUIT, SIG_IGN);
+  signal(SIGTERM, SIG_IGN);
+
+  for (;;) {
+	if (!Still_Logged_On(user, tty)) exit(0);
+
+	/* how much longer until the leave time? */
+	/* XXX - use difftime all over. */
+	delta = leave - time((time_t *)0);
+
+	/* which interval are we currently in? */
+	for (i = 0; i < INTERVALS; ++i)
+		if (delta + intervals[i] > 0) break;
+
+	/* if we are within intervals[0] then print a warning If
+	 * there are more intervals than messages, then use/
+	 * warnings[WARNINGS-1] for all subsequent messages. */
+	if (i > 0)
+		printf("\007\r%s\r\n",
+			warnings[i > WARNINGS ? WARNINGS - 1 : i - 1]);
+
+	if (i == INTERVALS) {
+		printf("That was the last time I'll tell you. Bye.\r\n");
+		exit(0);
+	}
+	/* Sleep until the next interval. For long periods, wake up
+	 * every hour to check if the user is still on (also required
+	 * because 16 bit ints don't allow long waits). */
+	sleep((unsigned) Min(delta + intervals[i], HOUR));
+  }
+}
Index: /trunk/minix/commands/simple/life.c
===================================================================
--- /trunk/minix/commands/simple/life.c	(revision 9)
+++ /trunk/minix/commands/simple/life.c	(revision 9)
@@ -0,0 +1,241 @@
+/* life - Conway's game of life		Author: Jim King */
+
+/* clife.c - curses life simulator.  Translated from Pascal to C implementing
+ *           curses Oct 1988 by pulsar@lsrhs, not jek5036@ritvax.isc.rit.edu
+ *           life needs about 18kb stack space on MINIX.
+ *
+ * Flags:	-d  draw your own screen using arrows and space bar
+ *		-p  print statistics on the bottom line during the game
+ */
+
+#include <sys/types.h>
+#include <signal.h>
+#include <time.h>
+#include <curses.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#if __minix_vmd		/* Use a more random rand(). */
+#define srand(seed)	srandom(seed)
+#define rand()		random()
+#endif
+
+/* A value of -1 will make it go forever */
+/* A value of 0 will make it exit immediately */
+#define	REPSTOP		-1	/* number of repetitions before stop */
+
+int present[23][80];		/* screen 1 cycle ago */
+int past[23][80];		/* screen this cycle */
+int total;			/* total # of changes */
+int icnt;			/* counter to check for repetition */
+int maxrow = 22;		/* some defines to represent the screen */
+int maxcol = 79;
+int minrow = 0;
+int mincol = 0; 
+int pri = 0;			/* flag for printing stats on bottom line */
+int draw = 0;			/* flag for drawing your own screen */
+int i, j, k;			/* loop counters */
+int cycle;			/* current cycle # */
+int changes;			/* # of changes this cycle (live + die) */
+int die;			/* number of deaths this cycle */
+int live;			/* number of births this cycle */
+
+WINDOW *mns;			/* Main Screen */
+WINDOW *info;			/* Bottom line */
+
+_PROTOTYPE(void cleanup, (int s));
+_PROTOTYPE(void initialize, (void));
+_PROTOTYPE(void makscr, (void));
+_PROTOTYPE(void update, (void));
+_PROTOTYPE(void print, (void));
+_PROTOTYPE(int main, (int ac, char *av[]));
+
+/* Cleanup - cleanup then exit */
+void cleanup(s)
+int s;
+{
+  move(23, 0);			/* go to bottom of screen */
+  refresh();			/* update cursor */
+
+  endwin();			/* shutdown curses */
+  exit(1);			/* exit */
+}
+
+/* Initialize - init windows, variables, and signals */
+
+void initialize()
+{
+  srand(getpid());		/* init random seed */
+  initscr();			/* init curses */
+  noecho();
+  curs_set(0);
+  signal(SIGINT, cleanup);	/* catch ^C */
+  mns = newwin(maxrow, maxcol, 0, 0);	/* new window */
+  scrollok(mns, FALSE);
+  info = newwin(1, 80, 23, 0);
+  scrollok(info, FALSE);
+  wclear(mns);
+  wclear(info);
+  wmove(info, 0, 0);
+  wrefresh(info);
+  if (!draw) {			/* if no draw, make random pattern */
+	for (j = 0; j < maxrow; j++) {
+		for (k = 0; k < maxcol; k++) {
+			present[j][k] = rand() % 2;
+			if (present[j][k] == 1) changes++, live++;
+		}
+	}
+  }
+}
+
+/* Makscr - make your own screen using arrow keys and space bar */
+void makscr()
+{
+  int curx, cury;		/* current point on screen */
+  char c;			/* input char */
+
+  wclear(info);
+  wmove(info, 0, 0);
+  wprintw(info, "Use arrow keys to move, space to place / erase, ^D to start", NULL);
+  wrefresh(info);
+  curx = cury = 1;
+  wmove(mns, cury - 1, curx - 1);
+  wrefresh(mns);
+  noecho();
+  for (;;) {
+	c = wgetch(mns);
+	if (c == '\004')
+		break;
+	else if (c == ' ') {
+		if (present[cury][curx]) {
+			--present[cury][curx];
+			changes++;
+			die++;
+			mvwaddch(mns, cury, curx, ' ');
+		} else {
+			++present[cury][curx];
+			changes++;
+			live++;
+			mvwaddch(mns, cury, curx, '*');
+		}
+	} else if (c == '\033') {
+		wgetch(mns);
+		switch (wgetch(mns)) {
+		    case 'A':	--cury;	break;
+		    case 'B':	++cury;	break;
+		    case 'C':	++curx;	break;
+		    case 'D':	--curx;	break;
+		    default:	break;
+		}
+	}
+	if (cury > maxrow) cury = minrow;
+	if (cury < minrow) cury = maxrow;
+	if (curx > maxcol) curx = mincol;
+	if (curx < mincol) curx = maxcol;
+	wmove(mns, cury, curx);
+	wrefresh(mns);
+  }
+  wclear(info);
+}
+
+/* Update rules:  2 or 3 adjacent alive --- stay alive
+ *                3 adjacent alive -- dead to live
+ *                all else die or stay dead
+ */
+void update()
+{				/* Does all mathmatical calculations */
+  int howmany, w, x, y, z;
+  changes = die = live = 0;
+  for (j = 0; j < maxrow; j++) {
+	for (k = 0; k < maxcol; k++) {
+		w = j - 1;
+		x = j + 1;
+		y = k - 1;
+		z = k + 1;
+
+		howmany = (past[w][y] + past[w][k] + past[w][z] +
+			   past[j][y] + past[j][z] + past[x][y] +
+			   past[x][k] + past[x][z]);
+
+		switch (howmany) {
+		    case 0:
+		    case 1:
+		    case 4:
+		    case 5:
+		    case 6:
+		    case 7:
+		    case 8:
+			present[j][k] = 0;
+			if (past[j][k]) changes++, die++;
+			break;
+		    case 3:
+			present[j][k] = 1;
+			if (!past[j][k]) changes++, live++;
+			break;
+		    default:	break;
+		}
+	}
+  }
+  if (live == die)
+	++icnt;
+  else
+	icnt = 0;
+
+  if (icnt == REPSTOP) cleanup(0);
+}
+
+/* Print - updates the screen according to changes from past to present */
+void print()
+{	
+/* Updates the screen, greatly improved using curses */
+  if (pri) {
+	wmove(info, 0, 0);
+	total += changes;
+	cycle++;
+	wprintw(info, "Cycle %5d | %5d changes: %5d died + %5d born = %5u total changes", (char *) cycle, changes, die, live, total);
+	wclrtoeol(info);
+  }
+  for (j = 1; j < maxrow; j++) {
+	for (k = 1; k < maxcol; k++) {
+		if (present[j][k] != past[j][k] && present[j][k] == 1) {
+			wmove(mns, j, k);
+			wprintw(mns, "*", NULL);
+		} else if (present[j][k] != past[j][k] && present[j][k] == 0) {
+			wmove(mns, j, k);
+			wprintw(mns, " ", NULL);
+		}
+	}
+  }
+  if (pri) wrefresh(info);
+  wrefresh(mns);
+}
+
+/* Main - main procedure */
+int main(ac, av)
+int ac;
+char *av[];
+{
+  if (ac > 1) {
+	for (j = 1; j < ac; j++) {
+		switch (av[j][1]) {
+		    case 'd':	++draw;	break;
+		    case 'p':	++pri;	break;
+		    default:
+			fprintf(stderr, "%s: usage: %s [-d] [-p]\n", av[0], av[0]);
+			exit(1);
+		}
+	}
+  }
+
+  initialize();
+  if (draw) makscr();
+
+  for (;;) {
+	print();
+	for (j = 0; j < maxrow; j++) {
+		for (k = 0; k < maxcol; k++) past[j][k] = present[j][k];
+	}
+	update();
+  }
+}
Index: /trunk/minix/commands/simple/loadramdisk.c
===================================================================
--- /trunk/minix/commands/simple/loadramdisk.c	(revision 9)
+++ /trunk/minix/commands/simple/loadramdisk.c	(revision 9)
@@ -0,0 +1,126 @@
+/*
+loadramdisk.c
+
+Copy a device or file specified as argument to /dev/ram
+*/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+#define RAM	"/dev/ram"
+
+char buf[10240];
+
+static unsigned long size_device(int fd);
+
+int main(int argc, char *argv[])
+{
+	unsigned long off, size;
+	int r, s, fd, ramfd;
+	char *src;
+
+	if (argc != 2)
+	{
+		fprintf(stderr, "Usage: loadramdisk <file>\n");
+		exit(1);
+	}
+	src= argv[1];
+	fd= open(src, O_RDONLY);
+	if (fd < 0)
+	{
+		fprintf(stderr, "Unable to open '%s': %s\n",
+			src, strerror(errno));
+		exit(1);
+	}
+
+	/* Get the size of the device */
+	errno= 0;
+	size= size_device(fd);
+	if (errno != 0)
+	{
+		fprintf(stderr, "Lseek(end) failed on '%s': %s\n",
+			src, strerror(errno));
+		exit(1);
+	}
+	if (lseek(fd, 0, SEEK_SET) != 0)
+	{
+		fprintf(stderr, "Lseek(0) failed on '%s': %s\n",
+			src, strerror(errno));
+		exit(1);
+	}
+
+	ramfd= open(RAM, O_RDWR);
+	if (ramfd < 0)
+	{
+		fprintf(stderr, "Unable to open '%s': %s\n",
+			RAM, strerror(errno));
+		exit(1);
+	}
+	r= ioctl(ramfd, MIOCRAMSIZE, &size);
+	if (r != 0)
+	{
+		fprintf(stderr, "MIOCRAMSIZE %lu failed on '%s': %s\n",
+			size, RAM, strerror(errno));
+		exit(1);
+	}
+
+	off= 0;
+	while (off < size)
+	{
+		r= read(fd, buf, sizeof(buf));
+		if (r <= 0)
+		{
+			fprintf(stderr, "error reading '%s': %s\n",
+				src, r == 0 ? "unexpected EOF" :
+				strerror(errno));
+			exit(1);
+		}
+		s= write(ramfd, buf, r);
+		if (s != r)
+		{
+			fprintf(stderr, "error writing to '%s': %s\n",
+				s >= 0 ? "short write" : strerror(errno));
+			exit(1);
+		}
+		off += r;
+	}
+	exit(0);
+}
+
+static unsigned long size_device(int fd)
+{
+	char b;
+	int r;
+	unsigned long low, mid, high;
+
+	/* Try to find the size of a device using binary search */
+	low= 0;
+	high= -1;
+
+	while (mid= low+(high-low)/2, mid > low)
+	{
+		if (lseek(fd, mid, SEEK_SET) != mid)
+		{
+			fprintf(stderr, "lseek to %lu failed: %s\n",
+				mid, strerror(errno));
+			exit(1);
+		}
+		r= read(fd, &b, 1);
+		if (r < 0)
+		{
+			fprintf(stderr, "read failed at position %lu: %s\n",
+				mid, strerror(errno));
+			exit(1);
+		}
+		if (r > 0)
+			low= mid;
+		else
+			high= mid;
+	}
+	return high;
+}
Index: /trunk/minix/commands/simple/login.c
===================================================================
--- /trunk/minix/commands/simple/login.c	(revision 9)
+++ /trunk/minix/commands/simple/login.c	(revision 9)
@@ -0,0 +1,508 @@
+/* login - log into the system			Author: Patrick van Kleef */
+
+/* Original version by Patrick van Kleef.  History of modifications:
+ *
+ * Peter S. Housel   Jan. 1988
+ *  - Set up $USER, $HOME and $TERM.
+ *  - Set signals to SIG_DFL.
+ *
+ * Terrence W. Holm   June 1988
+ *  - Allow a username as an optional argument.
+ *  - Time out if a password is not typed within 60 seconds.
+ *  - Perform a dummy delay after a bad username is entered.
+ *  - Don't allow a login if "/etc/nologin" exists.
+ *  - Cause a failure on bad "pw_shell" fields.
+ *  - Record the login in "/usr/adm/wtmp".
+ *
+ * Peter S. Housel   Dec. 1988
+ *  - Record the login in "/etc/utmp" also.
+ *
+ * F. van Kempen     June 1989
+ *  - various patches for Minix V1.4a.
+ *
+ * F. van Kempen     September 1989
+ *  - added login-failure administration (new utmp.h needed!).
+ *  - support arguments in pw_shell field
+ *  - adapted source text to MINIX Style Sheet
+ *
+ * F. van Kempen     October 1989
+ *  - adapted to new utmp database.
+ * F. van Kempen,    December 1989
+ *  - fixed 'slot' assumption in wtmp()
+ *  - fixed all MSS-stuff
+ *  - adapted to POSIX (MINIX 1.5)
+ * F. van Kempen,    January 1990
+ *  - made all 'bad login accounting' optional by "#ifdef BADLOG".
+ * F. van Kempen,    Februari 1990
+ *  - fixed 'first argument' bug and added some casts.
+ *
+ * Andy Tanenbaum April 1990
+ * - if /bin/sh cannot be located, try /usr/bin/sh
+ *
+ * Michael A. Temari	October 1990
+ *  - handle more than single digit tty devices
+ *
+ * Philip Homburg - Feb 28 1992
+ *  - use ttyname to get the name of a tty.
+ *
+ * Kees J. Bot - Feb 13 1993
+ *  - putting out garbage.
+ *  - added lastlog.
+ *
+ * Kees J. Bot - Feb 13 1993
+ *  - supplementary groups.
+ *
+ * Kees J. Bot - Jan 3 1996
+ *  - ported back to standard Minix.
+ */
+
+#define _MINIX_SOURCE
+#define _POSIX_C_SOURCE	2
+
+#include <sys/types.h>
+#include <ttyent.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <time.h>
+#include <sys/utsname.h>
+#include <minix/minlib.h>
+#include <minix/paths.h>
+
+char PATH_UTMP[] = _PATH_UTMP;			/* current logins */
+char PATH_WTMP[] = _PATH_WTMP;		/* login/logout history */
+char PATH_LASTLOG[] = _PATH_LASTLOG;	/* last login history */
+char PATH_MOTD[] = _PATH_MOTD;			/* message of the day */
+
+#define TTY_GID		4			/* group ID of ttys */
+
+#define EXTRA_ENV	6
+
+/* Crude indication of a tty being physically secure: */
+#define securetty(dev)		((unsigned) ((dev) - 0x0400) < (unsigned) 8)
+
+int time_out;
+char *hostname;
+char user[32];
+char logname[35];
+char home[128];
+char shell[128];
+char term[128];
+char **env;
+extern char **environ;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void wtmp, (char *user, int uid));
+_PROTOTYPE(void show_file, (char *nam));
+_PROTOTYPE(void Time_out, (int dummy));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(void add2env, (char **env, char *entry, int replace));
+
+void wtmp(user, uid)
+char *user;			/* user name */
+int uid;			/* user id */
+{
+  /* Make entries in /usr/adm/wtmp and /etc/utmp. */
+  struct utmp entry;
+  register int fd= -1;
+  int lineno;
+  int err = 0;
+  char *what;
+
+  /* First, read the current UTMP entry. we need some of its
+   * parameters! (like PID, ID etc...).
+   */
+  what= "ttyslot()";
+  lineno= ttyslot();
+  if (lineno == 0) err= errno;	/* ttyslot failed */
+
+  if (err == 0 && (fd = open(what = PATH_UTMP, O_RDONLY)) < 0) {
+  	if (errno == ENOENT) return;
+  	err= errno;
+  }
+  if (err == 0 && lseek(fd, (off_t) lineno * sizeof(entry), SEEK_SET) < 0)
+  	err= errno;
+  if (err == 0 && read(fd, (char *) &entry, sizeof(entry)) != sizeof(entry))
+  	err= errno;
+  if (fd >= 0) close(fd);
+
+  /* Enter new fields. */
+  strncpy(entry.ut_user, user, sizeof(entry.ut_user));
+  if (hostname) strncpy(entry.ut_host, hostname, sizeof(entry.ut_host));
+
+  if (entry.ut_pid == 0) entry.ut_pid = getpid();
+
+  entry.ut_type = USER_PROCESS;		/* we are past login... */
+  time(&entry.ut_time);
+
+  /* Write a WTMP record. */
+  if (err == 0) {
+  	if ((fd = open(what = PATH_WTMP, O_WRONLY|O_APPEND)) < 0) {
+  		if (errno != ENOENT) err= errno;
+	} else {
+		if (write(fd, (char *) &entry, sizeof(entry)) < 0) err= errno;
+		close(fd);
+	}
+  }
+
+  /* Rewrite the UTMP entry. */
+  if (err == 0 && (fd = open(what = PATH_UTMP, O_WRONLY)) < 0)
+	err= errno;
+  if (err == 0 && lseek(fd, (off_t) lineno * sizeof(entry), SEEK_SET) < 0)
+	err= errno;
+  if (err == 0 && write(fd, (char *) &entry, sizeof(entry)) < 0)
+	err= errno;
+  if (fd >= 0) close(fd);
+
+  /* Write the LASTLOG entry. */
+  if (err == 0 && (fd = open(what = PATH_LASTLOG, O_WRONLY)) < 0) {
+	if (errno == ENOENT) return;
+	err= errno;
+  }
+  if (err == 0 && lseek(fd, (off_t) uid * sizeof(entry), SEEK_SET) < 0)
+	err= errno;
+  if (err == 0 && write(fd, (char *) &entry, sizeof(entry)) < 0)
+	err= errno;
+  if (fd >= 0) close(fd);
+
+  if (err != 0) {
+  	fprintf(stderr, "login: %s: %s\n", what, strerror(err));
+  	return;
+  }
+}
+
+
+void show_file(nam)
+char *nam;
+{
+/* Read a textfile and show it on the desired terminal. */
+  register int fd, len;
+  char buf[80];
+
+  if ((fd = open(nam, O_RDONLY)) > 0) {
+	len = 1;
+	while (len > 0) {
+		len = read(fd, buf, 80);
+		write(1, buf, len);
+	}
+	close(fd);
+  }
+}
+
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  char name[30];
+  char *password, *cryptedpwd;
+  char *tty_name, *p;
+  int n, ap, check_pw, bad, secure, i, envsiz, do_banner;
+  struct passwd *pwd;
+  char *bp, *argx[8], **ep;	/* pw_shell arguments */
+  char argx0[64];		/* argv[0] of the shell */
+  char *sh = "/bin/sh";		/* sh/pw_shell field value */
+  char *initialname;
+  int c, b_flag, f_flag, p_flag;
+  char *h_arg;
+  int authorized, preserv_env;
+  struct ttyent *ttyp;
+  struct stat ttystat;
+  struct sigaction sa;
+  struct utsname uts;
+
+  /* Don't let QUIT dump core. */
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = 0;
+  sa.sa_handler = exit;
+  sigaction(SIGQUIT, &sa, NULL);
+
+  /* Parse options.  */
+  b_flag= 0;
+  f_flag= 0;
+  p_flag= 0;
+  h_arg= NULL;
+  while ((c= getopt(argc, argv, "?bfh:p")) != -1)
+  {
+	switch(c)
+	{
+	case 'b': b_flag= 1;	break;
+	case 'f': f_flag= 1;	break;
+	case 'h':
+		if (h_arg)
+			usage();
+		if (getuid() == 0)
+			h_arg= optarg;
+		break;
+	case 'p': p_flag= 1;	break;
+	case '?':
+		usage();
+	default:
+		fprintf(stderr, "login: getopt failed: '%c'\n", c);
+		exit(1);
+	}
+  }
+  if (optind < argc)
+	initialname= argv[optind++];
+  else
+	initialname= NULL;
+  if (optind != argc)
+	usage();
+
+  authorized= f_flag;
+  hostname= h_arg;
+  preserv_env= p_flag;
+  do_banner= b_flag;
+
+  /* Look up /dev/tty number. */
+  tty_name= ttyname(0);
+  if (tty_name == NULL)
+  {
+	write(1, "Unable to lookup tty name\n", 26);
+	exit(1);
+  }
+
+  if (do_banner)
+  {
+	uname(&uts);
+	write(1, "\n", 1);
+	write(1, uts.sysname, strlen(uts.sysname));
+	write(1, "/", 1);
+	write(1, uts.machine, strlen(uts.machine));
+	write(1, " Release ", 9);
+	write(1, uts.release, strlen(uts.release));
+	write(1, " Version ", 9);
+	write(1, uts.version, strlen(uts.version));
+	write(1, " (", 2);
+	p= strrchr(tty_name, '/');
+	if (!p)
+		p= tty_name;
+	else
+		p++;
+	write(1, p, strlen(p));
+	write(1, ")\n\n", 3);
+	write(1, uts.nodename, strlen(uts.nodename));
+	write(1, " ", 1);
+  }
+
+  /* Get login name and passwd. */
+  for (;;initialname= NULL) {
+	if (initialname)
+		strcpy(name, initialname);
+	else {
+		do {
+			write(1, "login: ", 7);
+			n = read(0, name, 30);
+			if (n == 0) exit(1);
+			if (n < 0)
+			{
+				if (errno != EINTR)
+					fprintf(stderr,
+						"login: read failed: %s\n",
+							strerror(errno));
+				exit(1);
+			}
+		} while (n < 2);
+		name[n - 1] = 0;
+	}
+
+	/* Start timer running. */
+	time_out = 0;
+	sa.sa_handler = Time_out;
+	sigaction(SIGALRM, &sa, NULL);
+	alarm(60);
+
+
+	/* Look up login/passwd. */
+	pwd = getpwnam(name);
+
+	check_pw = 1;			/* default is check password. */
+
+	/* For now, only console is secure. */
+	secure = fstat(0, &ttystat) == 0 && securetty(ttystat.st_rdev);
+
+	if (pwd && authorized && initialname
+			&& (pwd->pw_uid == getuid() || getuid() == 0)) {
+		check_pw= 0;		/* Don't ask a password for
+					 * pre-authorized users.
+					 */
+	} else
+	if (pwd && secure && strcmp(crypt("", pwd->pw_passwd),
+						pwd->pw_passwd) == 0) {
+		check_pw= 0;		/* empty password */
+	}
+
+	if (check_pw) {
+		password = getpass("Password:");
+
+		if (time_out) exit(1);
+
+		bad = 0;
+		if (!pwd) bad = 1;
+		if (!password) { password = ""; bad = 1; }
+		if (!secure && pwd && strcmp(crypt("", pwd->pw_passwd),
+					pwd->pw_passwd) == 0) bad = 1;
+
+		cryptedpwd = bad ? "*" : pwd->pw_passwd;
+
+		if (strcmp(crypt(password, cryptedpwd), cryptedpwd) != 0) {
+			write(1, "Login incorrect\n", 16);
+			continue;
+		}
+	}
+	/* Check if the system is going down  */
+	if (access("/etc/nologin", 0) == 0 && strcmp(name, "root") != 0) {
+		write(1, "System going down\n\n", 19);
+		continue;
+	}
+
+	/* Stop timer. */
+	alarm(0);
+
+	/* Write login record to /usr/adm/wtmp and /etc/utmp */
+	wtmp(name, pwd->pw_uid);
+
+	/* Create the argv[] array from the pw_shell field. */
+	ap = 0;
+	argx[ap++] = argx0;	/* "-sh" most likely */
+	if (pwd->pw_shell[0]) {
+		sh = pwd->pw_shell;
+		bp = sh;
+		while (*bp) {
+			while (*bp && *bp != ' ' && *bp != '\t') bp++;
+			if (*bp == ' ' || *bp == '\t') {
+				*bp++ = '\0';	/* mark end of string */
+				argx[ap++] = bp;
+			}
+		}
+	} else
+	argx[ap] = NULL;
+	strcpy(argx0, "-");	/* most shells need it for their .profile */
+	if ((bp= strrchr(sh, '/')) == NULL) bp = sh; else bp++;
+	strncat(argx0, bp, sizeof(argx0) - 2);
+
+	/* Set the environment */
+	if (p_flag)
+	{
+		for (ep= environ; *ep; ep++)
+			;
+	}
+	else
+		ep= environ;
+
+	envsiz= ep-environ;
+	env= calloc(envsiz + EXTRA_ENV, sizeof(*env));
+	if (env == NULL)
+	{
+		fprintf(stderr, "login: out of memory\n");
+		exit(1);
+	}
+	for (i= 0; i<envsiz; i++)
+		env[i]= environ[i];
+
+	strcpy(user, "USER=");
+	strcat(user, name);
+	add2env(env, user, 1);
+	strcpy(logname, "LOGNAME=");
+	strcat(logname, name);
+	add2env(env, logname, 1);
+	strcpy(home, "HOME=");
+	strcat(home, pwd->pw_dir);
+	add2env(env, home, 1);
+	strcpy(shell, "SHELL=");
+	strcat(shell, sh);
+	add2env(env, shell, 1);
+	if ((ttyp = getttynam(tty_name + 5)) != NULL) {
+		strcpy(term, "TERM=");
+		strcat(term, ttyp->ty_type);
+		add2env(env, term, 0);
+	}
+
+	/* Show the message-of-the-day. */
+	show_file(PATH_MOTD);
+
+	/* Assign the terminal to this user. */
+	chown(tty_name, pwd->pw_uid, TTY_GID);
+	chmod(tty_name, 0620);
+
+	/* Change id. */
+#if __minix_vmd
+	initgroups(pwd->pw_name, pwd->pw_gid);
+#endif
+	setgid(pwd->pw_gid);
+	setuid(pwd->pw_uid);
+
+	/* cd $HOME */
+	chdir(pwd->pw_dir);
+
+	/* Reset signals to default values. */
+	sa.sa_handler = SIG_DFL;
+	for (n = 1; n <= _NSIG; ++n) sigaction(n, &sa, NULL);
+
+	/* Execute the user's shell. */
+	execve(sh, argx, env);
+
+	if (pwd->pw_gid == 0) {
+		/* Privileged user gets /bin/sh in times of crisis. */
+		sh= "/bin/sh";
+		argx[0]= "-sh";
+		strcpy(shell, "SHELL=");
+		strcat(shell, sh);
+		execve(sh, argx, env);
+	}
+	fprintf(stderr, "login: can't execute %s: %s\n", sh, strerror(errno));
+	exit(1);
+  }
+  return(0);
+}
+
+
+void Time_out(dummy)
+int dummy; /* to keep the compiler happy */
+{
+   write(2, "\r\nLogin timed out after 60 seconds\r\n", 36);
+   time_out = 1;
+}
+
+void usage()
+{
+	fprintf(stderr,
+		"Usage: login [-h hostname] [-b] [-f] [-p] [username]\n");
+	exit(1);
+}
+
+void add2env(env, entry, replace)
+char **env;
+char *entry;
+int replace;
+{
+/* Replace an environment variable with entry or add entry if the environment
+ * variable doesn't exit yet. 
+ */
+	char *cp;
+	int keylen;
+
+	cp= strchr(entry, '=');
+	keylen= cp-entry+1;
+
+	for(; *env; env++)
+	{
+		if (strncmp(*env, entry, keylen) == 0) {
+			if (!replace) return;		/* Don't replace */
+			break;
+		}
+	}
+	*env= entry;
+}
+
+/*
+ * $PchId: login.c,v 1.6 2001/07/31 14:23:28 philip Exp $
+ */
Index: /trunk/minix/commands/simple/look.c
===================================================================
--- /trunk/minix/commands/simple/look.c	(revision 9)
+++ /trunk/minix/commands/simple/look.c	(revision 9)
@@ -0,0 +1,158 @@
+/*	look 1.3 - Find lines in a sorted list.		Author: Kees J. Bot
+ */
+#define nil 0
+#include <sys/types.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+char DEFAULT[] = "/usr/lib/dict/words";
+
+char *string, *wordlist= DEFAULT;
+
+#define MAXLEN	1024	/* Maximum word length. */
+
+int dflg= 0, fflg= 0;
+
+void nonascii(char *what)
+{
+	fprintf(stderr, "look: %s contains non-ASCII characters.\n", what);
+	exit(1);
+}
+
+int compare(char *prefix, char *word)
+{
+	char *p= prefix, *w= word;
+	int cp, cw;
+
+	do {
+		do {
+			if ((cp= *p++) == 0) return 0;
+			if (!isascii(cp)) nonascii("prefix string");
+		} while (dflg && !isspace(cp) && !isalnum(cp));
+
+		if (dflg) {
+			if (isspace(cp)) {
+				while (isspace(*p)) p++;
+				cp= ' ';
+			}
+		}
+		if (fflg && isupper(cp)) cp= tolower(cp);
+
+		do {
+			if ((cw= *w++) == 0) return 1;
+			if (!isascii(cw)) nonascii(wordlist);
+		} while (dflg && !isspace(cw) && !isalnum(cw));
+
+		if (dflg) {
+			if (isspace(cw)) {
+				while (isspace(*w)) w++;
+				cw= ' ';
+			}
+		}
+		if (fflg && isupper(cw)) cw= tolower(cw);
+	} while (cp == cw);
+
+	return cp - cw;
+}
+
+char *readword(FILE *f)
+{
+	static char word[MAXLEN + 2];
+	int n;
+
+	if (fgets(word, sizeof(word), f) == nil) {
+		if (ferror(f)) {
+			fprintf(stderr, "look: read error on %s",
+				wordlist);
+			exit(1);
+		}
+		return nil;
+	}
+
+	n= strlen(word);
+
+	if (word[n-1] != '\n') {
+		fprintf(stderr, "look: word from %s is too long\n", wordlist);
+		exit(1);
+	}
+	word[n-1] = 0;
+
+	return word;
+}
+
+void look(void)
+{
+	off_t low, mid, high;
+	FILE *f;
+	char *word;
+	int c;
+
+	if ((f= fopen(wordlist, "r")) == nil) {
+		fprintf(stderr, "look: Can't open %s\n", wordlist);
+		exit(1);
+	}
+
+	low= 0;
+
+	fseek(f, (off_t) 0, 2);
+
+	high= ftell(f);
+
+	while (low <= high) {
+		mid= (low + high) / 2;
+
+		fseek(f, mid, 0);
+
+		if (mid != 0) readword(f);
+
+		if ((word= readword(f)) == nil)
+			c= -1;
+		else
+			c= compare(string, word);
+
+		if (c <= 0) high= mid - 1; else low= mid + 1;
+	}
+	fseek(f, low, 0);
+	if (low != 0) readword(f);
+
+	c=0;
+	while (c >= 0 && (word= readword(f)) != nil) {
+		c= compare(string, word);
+
+		if (c == 0) puts(word);
+	}
+}
+
+int main(int argc, char **argv)
+{
+	if (argc == 2) dflg= fflg= 1;
+
+	while (argc > 1 && argv[1][0] == '-') {
+		char *p= argv[1] + 1;
+
+		while (*p != 0) {
+			switch (*p++) {
+			case 'd':	dflg= 1; break;
+			case 'f':	fflg= 1; break;
+			default:
+				fprintf(stderr, "look: Bad flag: %c\n", p[-1]);
+				exit(1);
+			}
+		}
+		argc--;
+		argv++;
+	}
+	if (argc == 3)
+		wordlist= argv[2];
+	else
+	if (argc != 2) {
+		fprintf(stderr, "Usage: look [-df] string [file]\n");
+		exit(1);
+	}
+	string= argv[1];
+	look();
+	exit(0);
+}
+/* Kees J. Bot 24-5-89. */
Index: /trunk/minix/commands/simple/lp.c
===================================================================
--- /trunk/minix/commands/simple/lp.c	(revision 9)
+++ /trunk/minix/commands/simple/lp.c	(revision 9)
@@ -0,0 +1,91 @@
+/*	lp 1.4 - Send file to the lineprinter		Author: Kees J. Bot
+ *								3 Dec 1989
+ */
+#define nil 0
+#include <sys/types.h>
+#include <stdio.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/wait.h>
+
+char LPD1[] = "/usr/sbin/lpd";		/* Proper place of lpd */
+char LPD2[] = "/usr/bin/lpd";		/* Minix has no sbin directories. */
+
+void report(char *mess)
+{
+	fprintf(stderr, "lp: %s: %s\n", mess, strerror(errno));
+}
+
+void fatal(char *mess)
+{
+	report(mess);
+	exit(1);
+}
+
+void lp(char *file)
+/* Start the lpd daemon giving it the file to spool and print. */
+{
+	int pid, status;
+
+	if (file[0] != '/' || (pid= fork()) == 0) {
+		execl(LPD1, LPD1, file, (char *) nil);
+		if (errno != ENOENT) fatal(LPD1);
+		execl(LPD2, LPD2, file, (char *) nil);
+		fatal(LPD2);
+	}
+
+	if (pid < 0) fatal("can't fork");
+
+	if (waitpid(pid, &status, 0) < 0) fatal("wait");
+
+	if (status != 0) exit(1);
+}
+
+char path[PATH_MAX+1];
+int cwdsize;
+
+int main(int argc, char **argp)
+{
+	int e=0;
+	char *file;
+
+	if (argc <= 1) lp("stdin");
+
+	/* Lpd requires full path names, so find out where we are. */
+	if (getcwd(path, sizeof(path)) == nil)
+		fatal("Can't determine current directory");
+
+	cwdsize= strlen(path);
+
+	/* Hand each file to lpd. */
+	while ((file= *++argp) != nil) {
+
+		close(0);
+
+		if (open(file, O_RDONLY) != 0) {
+			report(file);
+			e=1;
+			continue;
+		}
+		if (file[0] == '/') {
+			lp(file);
+			continue;
+		}
+		if (cwdsize + 1 + strlen(file) + 1 > sizeof(path)) {
+			fprintf(stderr,
+				"lp: full pathname of %s is too long\n",
+				file);
+			e=1;
+			continue;
+		}
+		path[cwdsize] = '/';
+		strcpy(path + cwdsize + 1, file);
+
+		lp(path);
+	}
+	exit(e);
+}
Index: /trunk/minix/commands/simple/lpd.c
===================================================================
--- /trunk/minix/commands/simple/lpd.c	(revision 9)
+++ /trunk/minix/commands/simple/lpd.c	(revision 9)
@@ -0,0 +1,368 @@
+/*	lpd 1.6 - Printer daemon			Author: Kees J. Bot
+ *								3 Dec 1989
+ */
+#define nil 0
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <termcap.h>
+
+char PRINTER[] =	"/dev/lp";
+char SPOOL[] =		"/usr/spool/lpd";
+char LOG[] =		"/dev/log";
+
+void report(char *mess)
+{
+	fprintf(stderr, "lpd: %s: %s\n", mess, strerror(errno));
+}
+
+void fatal(char *mess)
+{
+	report(mess);
+	exit(1);
+}
+
+char jobX[] = "jobXXXXXX";
+char tmpX[] = "tmpXXXXXX";
+
+void spoolerr(char *file)
+{
+	int e= errno;
+
+	unlink(jobX);
+	unlink(tmpX);
+	fatal(file);
+}
+
+void spool(char *path)
+/* Place a file into the spool directory, either by copying it, or by leaving
+ * a reference.
+ */
+{
+	char *file;
+	int j, u;
+
+	mktemp(jobX);
+	file= mktemp(tmpX);
+
+	if (path[0] == '/') {
+		int f;
+
+		if ((f= open(path, O_RDONLY)) >= 0) {
+			close(f);
+			file= path;
+		}
+	}
+	if (file != path) {
+		int c;
+		FILE *t;
+
+		if ((t= fopen(tmpX, "w")) == nil) spoolerr(tmpX);
+
+		while ((c= getchar()) != EOF && putc(c, t) != EOF) {}
+
+		if (ferror(stdin)) spoolerr(path);
+
+		if (ferror(t) || fclose(t) == EOF) spoolerr(tmpX);
+
+		fclose(stdin);
+	}
+
+	if ((j= open(jobX, O_WRONLY|O_CREAT|O_EXCL, 0000)) < 0) spoolerr(jobX);
+
+	u= getuid();
+	if (write(j, file, strlen(file)+1) < 0
+		|| write(j, &u, sizeof(u)) < 0
+		|| write(j, path, strlen(path)+1) < 0
+		|| close(j) < 0
+		|| chmod(jobX, 0600) < 0
+	) spoolerr(jobX);
+}
+
+struct job {
+	struct job *next;
+	time_t age;
+	char name[sizeof(jobX)];
+} *jobs = nil;
+
+int job(void)
+/* Look for print jobs in the spool directory.  Make a list of them sorted
+ * by age.  Return true iff the list is nonempty.
+ */
+{
+	DIR *spool;
+	struct dirent *entry;
+	struct job *newjob, **ajob;
+	struct stat st;
+
+	if (jobs != nil) return 1;
+
+	if ((spool= opendir(".")) == nil) fatal(SPOOL);
+
+	while ((entry= readdir(spool)) != nil) {
+		if (strncmp(entry->d_name, "job", 3) != 0) continue;
+
+		if (stat(entry->d_name, &st) < 0
+			|| (st.st_mode & 0777) == 0000) continue;
+
+		if ((newjob= malloc(sizeof(*newjob))) == nil) fatal("malloc()");
+		newjob->age = st.st_mtime;
+		strcpy(newjob->name, entry->d_name);
+
+		ajob= &jobs;
+		while (*ajob != nil && (*ajob)->age < newjob->age)
+			ajob= &(*ajob)->next;
+
+		newjob->next= *ajob;
+		*ajob= newjob;
+	}
+	closedir(spool);
+
+	return jobs != nil;
+}
+
+/* What to do with control-X:
+ * 0 ignore,
+ * 1 give up on controlling the printer, assume user knows how printer works,
+ * 2 print.
+ */
+char control[] = {
+	0, 1, 1, 1, 1, 1, 1, 0,		/* \0, \a  don't show.	*/
+	2, 2, 2, 1, 2, 2, 1, 1,		/* \b, \t, \n, \f, \r	*/
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1
+};
+
+int lp;
+char buf[BUFSIZ];
+int count, column, line, ncols = 80, nlines = 66;
+
+int flush(void)
+/* Copy the characters in the output buffer to the printer, with retries if
+ * out of paper.
+ */
+{
+	char *bp= buf;
+
+	while (count > 0) {
+		int retry = 0, complain = 0;
+		int r;
+
+		while ((r= write(lp, bp, count)) < 0) {
+			if (errno != EAGAIN) fatal(PRINTER);
+			if (retry == complain) {
+				fprintf(stderr,
+					"lpd: %s: Printer out of paper\n",
+					PRINTER);
+				complain= retry + 60;
+			}
+			sleep(1);
+			retry++;
+		}
+		bp+= r;
+		count-= r;
+	}
+	count = 0;
+}
+
+int put(int c)
+/* Send characters to the output buffer to be printed and do so if the buffer
+ * is full.  Track the position of the write-head in `column' and `line'.
+ */
+{
+	buf[count++] = c;
+
+	switch (c) {
+	case '\f':
+		column = 0;
+		line = 0;
+		break;
+	case '\r':
+		column = 0;
+		break;
+	case '\n':
+		line++;
+		break;
+	case '\b':
+		column--;
+		break;
+	default:
+		if (++column > ncols) { line++; column= 1; }
+	}
+	if (line == nlines) line= 0;
+
+	if (count == BUFSIZ) flush();
+}
+
+void print(FILE *f)
+/* Send the contents of an open file to the printer.  Expand tabs and change
+ * linefeed to a carriage-return linefeed sequence.  Print a formfeed at the
+ * end if needed to reach the top of the next page.  If a control character
+ * is printed that we do not know about, then the user is assumed to know
+ * what they are doing, so output processing is disabled.
+ */
+{
+	int c;
+
+	count= column= line= 0;
+
+	while ((c= getc(f)) != EOF) {
+		if (c < ' ') {
+			switch (control[c]) {
+			case 0:	continue;	/* Ignore this one. */
+			case 1:
+				/* Can't handle this junk, assume smart user. */
+				do {
+					buf[count++] = c;
+					if (count == BUFSIZ) flush();
+				} while ((c= getc(f)) != EOF);
+
+				flush();
+				return;
+			case 2: /* fine */;
+			}
+		}
+
+		switch (c) {
+		case '\n':
+			put('\r');
+			put('\n');
+			break;
+		case '\t':
+			do {
+				put(' ');
+			} while (column & 07);
+			break;
+		case '\b':
+			if (column > 0) put(c);
+			break;
+		default:
+			put(c);
+		}
+	}
+	if (column > 0) { put('\r'); put('\n'); }
+	if (line > 0) put('\f');
+	flush();
+	return;
+}
+
+void joberr(char *job)
+{
+	fprintf(stderr, "lpd: something is wrong with %s\n", job);
+
+	if (unlink(job) < 0) fatal("can't remove it");
+}
+
+void work(void)
+/* Print all the jobs in the job list. */
+{
+	FILE *j, *f;
+	char file[PATH_MAX+1], *pf=file;
+	int c;
+	struct job *job;
+
+	job= jobs;
+	jobs= jobs->next;
+
+	if ((j= fopen(job->name, "r")) == nil) {
+		joberr(job->name);
+		return;
+	}
+
+	do {
+		if (pf == file + sizeof(file) || (c= getc(j)) == EOF) {
+			fclose(j);
+			joberr(job->name);
+			return;
+		}
+		*pf++ = c;
+	} while (c != 0);
+
+	fclose(j);
+
+	if ((f= fopen(file, "r")) == nil)
+		fprintf(stderr, "lpd: can't read %s\n", file);
+	else {
+		print(f);
+		fclose(f);
+	}
+	if (file[0] != '/' && unlink(file) < 0) report(file);
+
+	if (unlink(job->name) < 0) fatal(job->name);
+	free(job);
+}
+
+void getcap(void)
+/* Find the line printer dimensions in the termcap database under "lp". */
+{
+	char printcap[1024];
+	int n;
+
+	if (tgetent(printcap, "lp") == 1) {
+		if ((n= tgetnum("co")) > 0) ncols= n;
+		if ((n= tgetnum("li")) > 0) nlines= n;
+	}
+}
+
+void haunt(void)
+/* Become a daemon, print jobs while there are any, exit. */
+{
+	int fd;
+
+	if ((fd= open("/dev/tty", O_RDONLY)) != -1) {
+		/* We have a controlling tty!  Disconnect. */
+		close(fd);
+
+		switch(fork()) {
+		case -1:	fatal("can't fork");
+		case  0:	break;
+		default:	exit(0);
+		}
+
+		if ((fd= open("/dev/null", O_RDONLY)) < 0) fatal("/dev/null");
+		dup2(fd, 0);
+		close(fd);
+		if ((fd= open(LOG, O_WRONLY)) < 0) fatal(LOG);
+		dup2(fd, 1);
+		dup2(fd, 2);
+		close(fd);
+		setsid();
+	}
+
+	getcap();
+
+	do {
+		if ((lp= open(PRINTER, O_WRONLY)) < 0) {
+			/* Another lpd? */
+			if (errno == EBUSY) exit(0);
+			fatal(PRINTER);
+		}
+
+		while (job()) work();
+
+		close(lp);
+	} while (job());
+}
+
+int main(int argc, char **argv)
+{
+	if (argc > 2) {
+		fprintf(stderr, "Usage: %s [path | stdin < path]\n", argv[0]);
+		exit(1);
+	}
+
+	umask(0077);
+
+	if (chdir(SPOOL) < 0) fatal(SPOOL);
+
+	if (argc == 2) spool(argv[1]);
+
+	haunt();
+}
Index: /trunk/minix/commands/simple/ls.c
===================================================================
--- /trunk/minix/commands/simple/ls.c	(revision 9)
+++ /trunk/minix/commands/simple/ls.c	(revision 9)
@@ -0,0 +1,1150 @@
+/*	ls 5.4 - List files.				Author: Kees J. Bot
+ *								25 Apr 1989
+ *
+ * About the amount of bytes for heap + stack under Minix:
+ * Ls needs a average amount of 42 bytes per unserviced directory entry, so
+ * scanning 10 directory levels deep in an ls -R with 100 entries per directory
+ * takes 42000 bytes of heap.  So giving ls 10000 bytes is tight, 20000 is
+ * usually enough, 40000 is pessimistic.
+ */
+
+/* The array l_ifmt[] is used in an 'ls -l' to map the type of a file to a
+ * letter.  This is done so that ls can list any future file or device type
+ * other than symlinks, without recompilation.  (Yes it's dirty.)
+ */
+char l_ifmt[] = "0pcCd?bB-?l?s???";
+
+#define ifmt(mode)	l_ifmt[((mode) >> 12) & 0xF]
+
+#define nil 0
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <time.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#ifndef major
+#define major(dev)	((int) (((dev) >> 8) & 0xFF))
+#define minor(dev)	((int) (((dev) >> 0) & 0xFF))
+#endif
+
+#if !__minix
+#define SUPER_ID	uid	/* Let -A flag be default for SUPER_ID == 0. */
+#else
+#define SUPER_ID	gid
+#endif
+
+#ifdef S_IFLNK
+int (*status)(const char *file, struct stat *stp);
+#else
+#define status	stat
+#endif
+
+/* Basic disk block size is 512 except for one niche O.S. */
+#if __minix
+#define BLOCK	1024
+#else
+#define BLOCK	 512
+#endif
+
+/* Assume other systems have st_blocks. */
+#if !__minix
+#define ST_BLOCKS 1
+#endif
+
+/* Some terminals ignore more than 80 characters on a line.  Dumb ones wrap
+ * when the cursor hits the side.  Nice terminals don't wrap until they have
+ * to print the 81st character.  Whether we like it or not, no column 80.
+ */
+int ncols= 79;
+
+#define NSEP	3	/* # spaces between columns. */
+
+#define MAXCOLS	128	/* Max # of files per line. */
+
+char *arg0;	/* Last component of argv[0]. */
+int uid, gid;	/* callers id. */
+int ex= 0;	/* Exit status to be. */
+int istty;	/* Output is on a terminal. */
+
+/* Safer versions of malloc and realloc: */
+
+void heaperr(void)
+{
+	fprintf(stderr, "%s: Out of memory\n", arg0);
+	exit(-1);
+}
+
+void *allocate(size_t n)
+/* Deliver or die. */
+{
+	void *a;
+
+	if ((a= malloc(n)) == nil) heaperr();
+	return a;
+}
+
+void *reallocate(void *a, size_t n)
+{
+	if ((a= realloc(a, n)) == nil) heaperr();
+	return a;
+}
+
+char allowed[] = "acdfghilnpqrstu1ACDFLMRTX";
+char flags[sizeof(allowed)];
+
+char arg0flag[] = "cdfmrtx";	/* These in argv[0] go to upper case. */
+
+void setflags(char *flgs)
+{
+	int c;
+
+	while ((c= *flgs++) != 0) {
+		if (strchr(allowed, c) == nil) {
+			fprintf(stderr, "Usage: %s [-%s] [file ...]\n",
+				arg0, allowed);
+			exit(1);
+		} else
+		if (strchr(flags, c) == nil) {
+			flags[strlen(flags)] = c;
+		}
+	}
+}
+
+int present(int f)
+{
+	return f == 0 || strchr(flags, f) != nil;
+}
+
+void report(char *f)
+/* Like perror(3), but in the style: "ls: junk: No such file or directory. */
+{
+	fprintf(stderr, "%s: %s: %s\n", arg0, f, strerror(errno));
+	ex= 1;
+}
+
+/* Two functions, uidname and gidname, translate id's to readable names.
+ * All names are remembered to avoid searching the password file.
+ */
+#define NNAMES	(1 << (sizeof(int) + sizeof(char *)))
+enum whatmap { PASSWD, GROUP };
+
+struct idname {		/* Hash list of names. */
+	struct idname	*next;
+	char		*name;
+	uid_t		id;
+} *uids[NNAMES], *gids[NNAMES];
+
+char *idname(unsigned id, enum whatmap map)
+/* Return name for a given user/group id. */
+{
+	struct idname *i;
+	struct idname **ids= &(map == PASSWD ? uids : gids)[id % NNAMES];
+
+	while ((i= *ids) != nil && id < i->id) ids= &i->next;
+
+	if (i == nil || id != i->id) {
+		/* Not found, go look in the password or group map. */
+		char *name= nil;
+		char noname[3 * sizeof(uid_t)];
+
+		if (!present('n')) {
+			if (map == PASSWD) {
+				struct passwd *pw= getpwuid(id);
+
+				if (pw != nil) name= pw->pw_name;
+			} else {
+				struct group *gr= getgrgid(id);
+
+				if (gr != nil) name= gr->gr_name;
+			}
+		}
+		if (name == nil) {
+			/* Can't find it, weird.  Use numerical "name." */
+			sprintf(noname, "%u", id);
+			name= noname;
+		}
+
+		/* Add a new id-to-name cell. */
+		i= allocate(sizeof(*i));
+		i->id= id;
+		i->name= allocate(strlen(name) + 1);
+		strcpy(i->name, name);
+		i->next= *ids;
+		*ids= i;
+	}
+	return i->name;
+}
+
+#define uidname(uid)	idname((uid), PASSWD)
+#define gidname(gid)	idname((gid), GROUP)
+
+/* Path name construction, addpath adds a component, delpath removes it.
+ * The string path is used throughout the program as the file under examination.
+ */
+
+char *path;	/* Path name constructed in path[]. */
+int plen= 0, pidx= 0;	/* Lenght/index for path[]. */
+
+void addpath(int *didx, char *name)
+/* Add a component to path. (name may also be a full path at the first call)
+ * The index where the current path ends is stored in *pdi.
+ */
+{
+	if (plen == 0) path= (char *) allocate((plen= 32) * sizeof(path[0]));
+
+	if (pidx == 1 && path[0] == '.') pidx= 0;	/* Remove "." */
+
+	*didx= pidx;	/* Record point to go back to for delpath. */
+
+	if (pidx > 0 && path[pidx-1] != '/') path[pidx++]= '/';
+
+	do {
+		if (*name != '/' || pidx == 0 || path[pidx-1] != '/') {
+			if (pidx == plen) {
+				path= (char *) reallocate((void *) path,
+						(plen*= 2) * sizeof(path[0]));
+			}
+			path[pidx++]= *name;
+		}
+	} while (*name++ != 0);
+
+	--pidx;		/* Put pidx back at the null.  The path[pidx++]= '/'
+			 * statement will overwrite it at the next call.
+			 */
+}
+
+#define delpath(didx)	(path[pidx= didx]= 0)	/* Remove component. */
+
+int field = 0;	/* (used to be) Fields that must be printed. */
+		/* (now) Effects triggered by certain flags. */
+
+#define L_INODE		0x0001	/* -i */
+#define L_BLOCKS	0x0002	/* -s */
+#define L_EXTRA		0x0004	/* -X */
+#define L_MODE		0x0008	/* -lMX */
+#define L_LONG		0x0010	/* -l */
+#define L_GROUP		0x0020	/* -g */
+#define L_BYTIME	0x0040	/* -tuc */
+#define L_ATIME		0x0080	/* -u */
+#define L_CTIME		0x0100	/* -c */
+#define L_MARK		0x0200	/* -F */
+#define L_MARKDIR	0x0400	/* -p */
+#define L_TYPE		0x0800	/* -D */
+#define L_LONGTIME	0x1000	/* -T */
+#define L_DIR		0x2000	/* -d */
+#define L_KMG		0x4000	/* -h */
+
+struct file {		/* A file plus stat(2) information. */
+	struct file	*next;	/* Lists are made of them. */
+	char		*name;	/* Null terminated name. */
+	ino_t		ino;
+	mode_t		mode;
+	uid_t		uid;
+	gid_t		gid;
+	nlink_t		nlink;
+	dev_t		rdev;
+	off_t		size;
+	time_t		mtime;
+	time_t		atime;
+	time_t		ctime;
+#if ST_BLOCKS
+	long		blocks;
+#endif
+};
+
+void setstat(struct file *f, struct stat *stp)
+{
+	f->ino=		stp->st_ino;
+	f->mode=	stp->st_mode;
+	f->nlink=	stp->st_nlink;
+	f->uid=		stp->st_uid;
+	f->gid=		stp->st_gid;
+	f->rdev=	stp->st_rdev;
+	f->size=	stp->st_size;
+	f->mtime=	stp->st_mtime;
+	f->atime=	stp->st_atime;
+	f->ctime=	stp->st_ctime;
+#if ST_BLOCKS
+	f->blocks=	stp->st_blocks;
+#endif
+}
+
+#define	PAST	(26*7*24*3600L)	/* Half a year ago. */
+/* Between PAST and FUTURE from now a time is printed, otherwise a year. */
+#define FUTURE	( 1*7*24*3600L)	/* One week. */
+
+static char *timestamp(struct file *f)
+/* Transform the right time field into something readable. */
+{
+	struct tm *tm;
+	time_t t;
+	static time_t now;
+	static int drift= 0;
+	static char date[] = "Jan 19 03:14:07 2038";
+	static char month[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
+
+	t= f->mtime;
+	if (field & L_ATIME) t= f->atime;
+	if (field & L_CTIME) t= f->ctime;
+
+	tm= localtime(&t);
+	if (--drift < 0) { time(&now); drift= 50; }	/* limit time() calls */
+
+	if (field & L_LONGTIME) {
+		sprintf(date, "%.3s %2d %02d:%02d:%02d %d",
+			month + 3*tm->tm_mon,
+			tm->tm_mday,
+			tm->tm_hour, tm->tm_min, tm->tm_sec,
+			1900 + tm->tm_year);
+	} else
+	if (t < now - PAST || t > now + FUTURE) {
+		sprintf(date, "%.3s %2d  %d",
+			month + 3*tm->tm_mon,
+			tm->tm_mday,
+			1900 + tm->tm_year);
+	} else {
+		sprintf(date, "%.3s %2d %02d:%02d",
+			month + 3*tm->tm_mon,
+			tm->tm_mday,
+			tm->tm_hour, tm->tm_min);
+	}
+	return date;
+}
+
+char *permissions(struct file *f)
+/* Compute long or short rwx bits. */
+{
+	static char rwx[] = "drwxr-x--x";
+
+	rwx[0] = ifmt(f->mode);
+	/* Note that rwx[0] is a guess for the more alien file types.  It is
+	 * correct for BSD4.3 and derived systems.  I just don't know how
+	 * "standardized" these numbers are.
+	 */
+
+	if (field & L_EXTRA) {		/* Short style */
+		int mode = f->mode, ucase= 0;
+
+		if (uid == f->uid) {	/* What group of bits to use. */
+			/* mode<<= 0, */
+			ucase= (mode<<3) | (mode<<6);
+			/* Remember if group or others have permissions. */
+		} else
+		if (gid == f->gid) {
+			mode<<= 3;
+		} else {
+			mode<<= 6;
+		}
+		rwx[1]= mode&S_IRUSR ? (ucase&S_IRUSR ? 'R' : 'r') : '-';
+		rwx[2]= mode&S_IWUSR ? (ucase&S_IWUSR ? 'W' : 'w') : '-';
+
+		if (mode&S_IXUSR) {
+			static char sbit[]= { 'x', 'g', 'u', 's' };
+
+			rwx[3]= sbit[(f->mode&(S_ISUID|S_ISGID))>>10];
+			if (ucase&S_IXUSR) rwx[3] += 'A'-'a';
+		} else {
+			rwx[3]= f->mode&(S_ISUID|S_ISGID) ? '=' : '-';
+		}
+		rwx[4]= 0;
+	} else {		/* Long form. */
+		char *p= rwx+1;
+		int mode= f->mode;
+
+		do {
+			p[0] = (mode & S_IRUSR) ? 'r' : '-';
+			p[1] = (mode & S_IWUSR) ? 'w' : '-';
+			p[2] = (mode & S_IXUSR) ? 'x' : '-';
+			mode<<= 3;
+		} while ((p+=3) <= rwx+7);
+
+		if (f->mode&S_ISUID) rwx[3]= f->mode&(S_IXUSR>>0) ? 's' : '=';
+		if (f->mode&S_ISGID) rwx[6]= f->mode&(S_IXUSR>>3) ? 's' : '=';
+		if (f->mode&S_ISVTX) rwx[9]= f->mode&(S_IXUSR>>6) ? 't' : '=';
+	}
+	return rwx;
+}
+
+void numeral(int i, char **pp)
+{
+	char itoa[3*sizeof(int)], *a=itoa;
+
+	do *a++ = i%10 + '0'; while ((i/=10) > 0);
+
+	do *(*pp)++ = *--a; while (a>itoa);
+}
+
+#define K	1024L		/* A kilobyte counts in multiples of K */
+#define T	1000L		/* A megabyte in T*K, a gigabyte in T*T*K */
+
+char *cxsize(struct file *f)
+/* Try and fail to turn a 32 bit size into 4 readable characters. */
+{
+	static char siz[] = "1.2m";
+	char *p= siz;
+	off_t z;
+
+	siz[1]= siz[2]= siz[3]= 0;
+
+	if (f->size <= 5*K) {	/* <= 5K prints as is. */
+		numeral((int) f->size, &p);
+		return siz;
+	}
+	z= (f->size + K-1) / K;
+
+	if (z <= 999) {		/* Print as 123k. */
+		numeral((int) z, &p);
+		*p = 'k';	/* Can't use 'K', looks bad */
+	} else
+	if (z*10 <= 99*T) {	/* 1.2m (Try ls -X /dev/at0) */
+		z= (z*10 + T-1) / T;	/* Force roundup */
+		numeral((int) z / 10, &p);
+		*p++ = '.';
+		numeral((int) z % 10, &p);
+		*p = 'm';
+	} else
+	if (z <= 999*T) {	/* 123m */
+		numeral((int) ((z + T-1) / T), &p);
+		*p = 'm';
+	} else {		/* 1.2g */
+		z= (z*10 + T*T-1) / (T*T);
+		numeral((int) z / 10, &p);
+		*p++ = '.';
+		numeral((int) z % 10, &p);
+		*p = 'g';
+	}
+	return siz;
+}
+
+/* Transform size of file to number of blocks.  This was once a function that
+ * guessed the number of indirect blocks, but that nonsense has been removed.
+ */
+#if ST_BLOCKS
+#define nblocks(f)	((f)->blocks)
+#else
+#define nblocks(f)	(((f)->size + BLOCK-1) / BLOCK)
+#endif
+
+/* From number of blocks to kilobytes. */
+#if BLOCK < 1024
+#define nblk2k(nb)	(((nb) + (1024 / BLOCK - 1)) / (1024 / BLOCK))
+#else
+#define nblk2k(nb)	((nb) * (BLOCK / 1024))
+#endif
+
+static int (*CMP)(struct file *f1, struct file *f2);
+static int (*rCMP)(struct file *f1, struct file *f2);
+
+static void mergesort(struct file **al)
+/* This is either a stable mergesort, or thermal noise, I'm no longer sure.
+ * It must be called like this: if (L != nil && L->next != nil) mergesort(&L);
+ */
+{
+	/* static */ struct file *l1, **mid;  /* Need not be local */
+	struct file *l2;
+
+	l1= *(mid= &(*al)->next);
+	do {
+		if ((l1= l1->next) == nil) break;
+		mid= &(*mid)->next;
+	} while ((l1= l1->next) != nil);
+
+	l2= *mid;
+	*mid= nil;
+
+	if ((*al)->next != nil) mergesort(al);
+	if (l2->next != nil) mergesort(&l2);
+
+	l1= *al;
+	for (;;) {
+		if ((*CMP)(l1, l2) <= 0) {
+			if ((l1= *(al= &l1->next)) == nil) {
+				*al= l2;
+				break;
+			}
+		} else {
+			*al= l2;
+			l2= *(al= &l2->next);
+			*al= l1;
+			if (l2 == nil) break;
+		}
+	}
+}
+
+int namecmp(struct file *f1, struct file *f2)
+{
+	return strcmp(f1->name, f2->name);
+}
+
+int mtimecmp(struct file *f1, struct file *f2)
+{
+	return f1->mtime == f2->mtime ? 0 : f1->mtime > f2->mtime ? -1 : 1;
+}
+
+int atimecmp(struct file *f1, struct file *f2)
+{
+	return f1->atime == f2->atime ? 0 : f1->atime > f2->atime ? -1 : 1;
+}
+
+int ctimecmp(struct file *f1, struct file *f2)
+{
+	return f1->ctime == f2->ctime ? 0 : f1->ctime > f2->ctime ? -1 : 1;
+}
+
+int typecmp(struct file *f1, struct file *f2)
+{
+	return ifmt(f1->mode) - ifmt(f2->mode);
+}
+
+int revcmp(struct file *f1, struct file *f2) { return (*rCMP)(f2, f1); }
+
+static void sort(struct file **al)
+/* Sort the files according to the flags. */
+{
+	if (!present('f') && *al != nil && (*al)->next != nil) {
+		CMP= namecmp;
+
+		if (!(field & L_BYTIME)) {
+			/* Sort on name */
+
+			if (present('r')) { rCMP= CMP; CMP= revcmp; }
+			mergesort(al);
+		} else {
+			/* Sort on name first, then sort on time. */
+
+			mergesort(al);
+			if (field & L_CTIME) {
+				CMP= ctimecmp;
+			} else
+			if (field & L_ATIME) {
+				CMP= atimecmp;
+			} else {
+				CMP= mtimecmp;
+			}
+
+			if (present('r')) { rCMP= CMP; CMP= revcmp; }
+			mergesort(al);
+		}
+		/* Separate by file type if so desired. */
+
+		if (field & L_TYPE) {
+			CMP= typecmp;
+			mergesort(al);
+		}
+	}
+}
+
+struct file *newfile(char *name)
+/* Create file structure for given name. */
+{
+	struct file *new;
+
+	new= (struct file *) allocate(sizeof(*new));
+	new->name= strcpy((char *) allocate(strlen(name)+1), name);
+	return new;
+}
+
+void pushfile(struct file **flist, struct file *new)
+/* Add file to the head of a list. */
+{
+	new->next= *flist;
+	*flist= new;
+}
+
+void delfile(struct file *old)
+/* Release old file structure. */
+{
+	free((void *) old->name);
+	free((void *) old);
+}
+
+struct file *popfile(struct file **flist)
+/* Pop file off top of file list. */
+{
+	struct file *f;
+
+	f= *flist;
+	*flist= f->next;
+	return f;
+}
+
+int dotflag(char *name)
+/* Return flag that would make ls list this name: -a or -A. */
+{
+	if (*name++ != '.') return 0;
+
+	switch (*name++) {
+	case 0:		return 'a';			/* "." */
+	case '.':	if (*name == 0) return 'a';	/* ".." */
+	default:	return 'A';			/* ".*" */
+	}
+}
+
+int adddir(struct file **aflist, char *name)
+/* Add directory entries of directory name to a file list. */
+{
+	DIR *d;
+	struct dirent *e;
+
+	if (access(name, 0) < 0) {
+		report(name);
+		return 0;
+	}
+
+	if ((d= opendir(name)) == nil) {
+		report(name);
+		return 0;
+	}
+	while ((e= readdir(d)) != nil) {
+		if (e->d_ino != 0 && present(dotflag(e->d_name))) {
+			pushfile(aflist, newfile(e->d_name));
+			aflist= &(*aflist)->next;
+		}
+	}
+	closedir(d);
+	return 1;
+}
+
+off_t countblocks(struct file *flist)
+/* Compute total block count for a list of files. */
+{
+	off_t cb = 0;
+
+	while (flist != nil) {
+		switch (flist->mode & S_IFMT) {
+		case S_IFDIR:
+		case S_IFREG:
+#ifdef S_IFLNK
+		case S_IFLNK:
+#endif
+			cb += nblocks(flist);
+		}
+		flist= flist->next;
+	}
+	return cb;
+}
+
+void printname(char *name)
+/* Print a name with control characters as '?' (unless -q).  The terminal is
+ * assumed to be eight bit clean.
+ */
+{
+	int c, q= present('q');
+
+	while ((c= (unsigned char) *name++) != 0) {
+		if (q && (c < ' ' || c == 0177)) c= '?';
+		putchar(c);
+	}
+}
+
+int mark(struct file *f, int doit)
+{
+	int c;
+
+	c= 0;
+
+	if (field & L_MARK) {
+		switch (f->mode & S_IFMT) {
+		case S_IFDIR:	c= '/'; break;
+#ifdef S_IFIFO
+		case S_IFIFO:	c= '|'; break;
+#endif
+#ifdef S_IFLNK
+		case S_IFLNK:	c= '@'; break;
+#endif
+#ifdef S_IFSOCK
+		case S_IFSOCK:	c= '='; break;
+#endif
+		case S_IFREG:
+			if (f->mode & (S_IXUSR | S_IXGRP | S_IXOTH)) c= '*';
+			break;
+		}
+	} else
+	if (field & L_MARKDIR) {
+		if (S_ISDIR(f->mode)) c= '/';
+	}
+
+	if (doit && c != 0) putchar(c);
+	return c;
+}
+
+/* Width of entire column, and of several fields. */
+enum { W_COL, W_INO, W_BLK, W_NLINK, W_UID, W_GID, W_SIZE, W_NAME, MAXFLDS };
+
+unsigned char fieldwidth[MAXCOLS][MAXFLDS];
+
+void maxise(unsigned char *aw, int w)
+/* Set *aw to the larger of it and w. */
+{
+	if (w > *aw) {
+		if (w > UCHAR_MAX) w= UCHAR_MAX;
+		*aw= w;
+	}
+}
+
+int numwidth(unsigned long n)
+/* Compute width of 'n' when printed. */
+{
+	int width= 0;
+
+	do { width++; } while ((n /= 10) > 0);
+	return width;
+}
+
+#if !__minix
+int numxwidth(unsigned long n)
+/* Compute width of 'n' when printed in hex. */
+{
+	int width= 0;
+
+	do { width++; } while ((n /= 16) > 0);
+	return width;
+}
+#endif
+
+static int nsp= 0;	/* This many spaces have not been printed yet. */
+#define spaces(n)	(nsp= (n))
+#define terpri()	(nsp= 0, putchar('\n'))		/* No trailing spaces */
+
+void print1(struct file *f, int col, int doit)
+/* Either compute the number of spaces needed to print file f (doit == 0) or
+ * really print it (doit == 1).
+ */
+{
+	int width= 0, n;
+	char *p;
+	unsigned char *f1width = fieldwidth[col];
+
+	while (nsp>0) { putchar(' '); nsp--; }/* Fill gap between two columns */
+
+	if (field & L_INODE) {
+		if (doit) {
+			printf("%*d ", f1width[W_INO], f->ino);
+		} else {
+			maxise(&f1width[W_INO], numwidth(f->ino));
+			width++;
+		}
+	}
+	if (field & L_BLOCKS) {
+		unsigned long nb= nblk2k(nblocks(f));
+		if (doit) {
+			printf("%*lu ", f1width[W_BLK], nb);
+		} else {
+			maxise(&f1width[W_BLK], numwidth(nb));
+			width++;
+		}
+	}
+	if (field & L_MODE) {
+		if (doit) {
+			printf("%s ", permissions(f));
+		} else {
+			width+= (field & L_EXTRA) ? 5 : 11;
+		}
+	}
+	if (field & L_EXTRA) {
+		p= cxsize(f);
+		n= strlen(p)+1;
+
+		if (doit) {
+			n= f1width[W_SIZE] - n;
+			while (n > 0) { putchar(' '); --n; }
+			printf("%s ", p);
+		} else {
+			maxise(&f1width[W_SIZE], n);
+		}
+	}
+	if (field & L_LONG) {
+		if (doit) {
+			printf("%*u ", f1width[W_NLINK], (unsigned) f->nlink);
+		} else {
+			maxise(&f1width[W_NLINK], numwidth(f->nlink));
+			width++;
+		}
+		if (!(field & L_GROUP)) {
+			if (doit) {
+				printf("%-*s  ", f1width[W_UID],
+							uidname(f->uid));
+			} else {
+				maxise(&f1width[W_UID],
+						strlen(uidname(f->uid)));
+				width+= 2;
+			}
+		}
+		if (doit) {
+			printf("%-*s  ", f1width[W_GID], gidname(f->gid));
+		} else {
+			maxise(&f1width[W_GID], strlen(gidname(f->gid)));
+			width+= 2;
+		}
+
+		switch (f->mode & S_IFMT) {
+		case S_IFBLK:
+		case S_IFCHR:
+#ifdef S_IFMPB
+		case S_IFMPB:
+#endif
+#ifdef S_IFMPC
+		case S_IFMPC:
+#endif
+#if __minix
+			if (doit) {
+				printf("%*d, %3d ", f1width[W_SIZE] - 5,
+					major(f->rdev), minor(f->rdev));
+			} else {
+				maxise(&f1width[W_SIZE],
+						numwidth(major(f->rdev)) + 5);
+				width++;
+			}
+#else /* !__minix */
+			if (doit) {
+				printf("%*lX ", f1width[W_SIZE],
+					(unsigned long) f->rdev);
+			} else {
+				maxise(&f1width[W_SIZE], numwidth(f->rdev));
+				width++;
+			}
+#endif /* !__minix */
+			break;
+		default:
+			if (field & L_KMG) {
+				p= cxsize(f);
+				n= strlen(p)+1;
+
+				if (doit) {
+					n= f1width[W_SIZE] - n;
+					while (n > 0) { putchar(' '); --n; }
+					printf("%s ", p);
+				} else {
+					maxise(&f1width[W_SIZE], n);
+				}
+			} else {
+				if (doit) {
+					printf("%*lu ", f1width[W_SIZE],
+						(unsigned long) f->size);
+				} else {
+					maxise(&f1width[W_SIZE],
+						numwidth(f->size));
+					width++;
+				}
+			}
+		}
+
+		if (doit) {
+			printf("%s ", timestamp(f));
+		} else {
+			width+= (field & L_LONGTIME) ? 21 : 13;
+		}
+	}
+
+	n= strlen(f->name);
+	if (doit) {
+		printname(f->name);
+		if (mark(f, 1) != 0) n++;
+#ifdef S_IFLNK
+		if ((field & L_LONG) && (f->mode & S_IFMT) == S_IFLNK) {
+			char *buf;
+			int r, didx;
+
+			buf= (char *) allocate(((size_t) f->size + 1)
+							* sizeof(buf[0]));
+			addpath(&didx, f->name);
+			r= readlink(path, buf, (int) f->size);
+			delpath(didx);
+			if (r > 0) buf[r] = 0; else r=1, strcpy(buf, "?");
+			printf(" -> ");
+			printname(buf);
+			free((void *) buf);
+			n+= 4 + r;
+		}
+#endif
+		spaces(f1width[W_NAME] - n);
+	} else {
+		if (mark(f, 0) != 0) n++;
+#ifdef S_IFLNK
+		if ((field & L_LONG) && (f->mode & S_IFMT) == S_IFLNK) {
+			n+= 4 + (int) f->size;
+		}
+#endif
+		maxise(&f1width[W_NAME], n + NSEP);
+
+		for (n= 1; n < MAXFLDS; n++) width+= f1width[n];
+		maxise(&f1width[W_COL], width);
+	}
+}
+
+int countfiles(struct file *flist)
+/* Return number of files in the list. */
+{
+	int n= 0;
+
+	while (flist != nil) { n++; flist= flist->next; }
+
+	return n;
+}
+
+struct file *filecol[MAXCOLS];	/* filecol[i] is list of files for column i. */
+int nfiles, nlines;	/* # files to print, # of lines needed. */
+
+void columnise(struct file *flist, int nplin)
+/* Chop list of files up in columns.  Note that 3 columns are used for 5 files
+ * even though nplin may be 4, filecol[3] will simply be nil.
+ */
+{
+	int i, j;
+
+	nlines= (nfiles + nplin - 1) / nplin;	/* nlines needed for nfiles */
+
+	filecol[0]= flist;
+
+	for (i=1; i<nplin; i++) {	/* Give nlines files to each column. */
+		for (j=0; j<nlines && flist != nil; j++) flist= flist->next;
+
+		filecol[i]= flist;
+	}
+}
+
+int print(struct file *flist, int nplin, int doit)
+/* Try (doit == 0), or really print the list of files over nplin columns.
+ * Return true if it can be done in nplin columns or if nplin == 1.
+ */
+{
+	register struct file *f;
+	register int col, fld, totlen;
+
+	columnise(flist, nplin);
+
+	if (!doit) {
+		for (col= 0; col < nplin; col++) {
+			for (fld= 0; fld < MAXFLDS; fld++) {
+				fieldwidth[col][fld]= 0;
+			}
+		}
+	}
+
+	while (--nlines >= 0) {
+		totlen= 0;
+
+		for (col= 0; col < nplin; col++) {
+			if ((f= filecol[col]) != nil) {
+				filecol[col]= f->next;
+				print1(f, col, doit);
+			}
+			if (!doit && nplin > 1) {
+				/* See if this line is not too long. */
+				if (fieldwidth[col][W_COL] == UCHAR_MAX) {
+					return 0;
+				}
+				totlen+= fieldwidth[col][W_COL];
+				if (totlen > ncols+NSEP) return 0;
+			}
+		}
+		if (doit) terpri();
+	}
+	return 1;
+}
+
+enum depth { SURFACE, SURFACE1, SUBMERGED };
+enum state { BOTTOM, SINKING, FLOATING };
+
+void listfiles(struct file *flist, enum depth depth, enum state state)
+/* Main workhorse of ls, it sorts and prints the list of files.  Flags:
+ * depth: working with the command line / just one file / listing dir.
+ * state: How "recursive" do we have to be.
+ */
+{
+	struct file *dlist= nil, **afl= &flist, **adl= &dlist;
+	int nplin;
+	static int white = 1;	/* Nothing printed yet. */
+
+	/* Flush everything previously printed, so new error output will
+	 * not intermix with files listed earlier.
+	 */
+	fflush(stdout);
+
+	if (field != 0 || state != BOTTOM) {	/* Need stat(2) info. */
+		while (*afl != nil) {
+			static struct stat st;
+			int r, didx;
+
+			addpath(&didx, (*afl)->name);
+
+			if ((r= status(path, &st)) < 0
+#ifdef S_IFLNK
+				&& (status == lstat || lstat(path, &st) < 0)
+#endif
+			) {
+				if (depth != SUBMERGED || errno != ENOENT)
+					report((*afl)->name);
+				delfile(popfile(afl));
+			} else {
+				setstat(*afl, &st);
+				afl= &(*afl)->next;
+			}
+			delpath(didx);
+		}
+	}
+	sort(&flist);
+
+	if (depth == SUBMERGED && (field & (L_BLOCKS | L_LONG))) {
+		printf("total %ld\n", nblk2k(countblocks(flist)));
+	}
+
+	if (state == SINKING || depth == SURFACE1) {
+	/* Don't list directories themselves, list their contents later. */
+		afl= &flist;
+		while (*afl != nil) {
+			if (((*afl)->mode & S_IFMT) == S_IFDIR) {
+				pushfile(adl, popfile(afl));
+				adl= &(*adl)->next;
+			} else {
+				afl= &(*afl)->next;
+			}
+		}
+	}
+
+	if ((nfiles= countfiles(flist)) > 0) {
+		/* Print files in how many columns? */
+		nplin= !present('C') ? 1 : nfiles < MAXCOLS ? nfiles : MAXCOLS;
+
+		while (!print(flist, nplin, 0)) nplin--;	/* Try first */
+
+		print(flist, nplin, 1);		/* Then do it! */
+		white = 0;
+	}
+
+	while (flist != nil) {	/* Destroy file list */
+		if (state == FLOATING && (flist->mode & S_IFMT) == S_IFDIR) {
+			/* But keep these directories for ls -R. */
+			pushfile(adl, popfile(&flist));
+			adl= &(*adl)->next;
+		} else {
+			delfile(popfile(&flist));
+		}
+	}
+
+	while (dlist != nil) {	/* List directories */
+		if (dotflag(dlist->name) != 'a' || depth != SUBMERGED) {
+			int didx;
+
+			addpath(&didx, dlist->name);
+
+			flist= nil;
+			if (adddir(&flist, path)) {
+				if (depth != SURFACE1) {
+					if (!white) putchar('\n');
+					printf("%s:\n", path);
+					white = 0;
+				}
+				listfiles(flist, SUBMERGED,
+					state == FLOATING ? FLOATING : BOTTOM);
+			}
+			delpath(didx);
+		}
+		delfile(popfile(&dlist));
+	}
+}
+
+int main(int argc, char **argv)
+{
+	struct file *flist= nil, **aflist= &flist;
+	enum depth depth;
+	char *lsflags;
+	struct winsize ws;
+
+	uid= geteuid();
+	gid= getegid();
+
+	if ((arg0= strrchr(argv[0], '/')) == nil) arg0= argv[0]; else arg0++;
+	argv++;
+
+	if (strcmp(arg0, "ls") != 0) {
+		char *p= arg0+1;
+
+		while (*p != 0) {
+			if (strchr(arg0flag, *p) != nil) *p += 'A' - 'a';
+			p++;
+		}
+		setflags(arg0+1);
+	}
+	while (*argv != nil && (*argv)[0] == '-') {
+		if ((*argv)[1] == '-' && (*argv)[2] == 0) {
+			argv++;
+			break;
+		}
+		setflags(*argv++ + 1);
+	}
+
+	istty= isatty(1);
+
+	if (istty && (lsflags= getenv("LSOPTS")) != nil) {
+		if (*lsflags == '-') lsflags++;
+		setflags(lsflags);
+	}
+
+	if (!present('1') && !present('C') && !present('l')
+		&& (istty || present('M') || present('X') || present('F'))
+	) setflags("C");
+
+	if (istty) setflags("q");
+
+	if (SUPER_ID == 0 || present('a')) setflags("A");
+
+	if (present('i')) field|= L_INODE;
+	if (present('s')) field|= L_BLOCKS;
+	if (present('M')) field|= L_MODE;
+	if (present('X')) field|= L_EXTRA | L_MODE;
+	if (present('t')) field|= L_BYTIME;
+	if (present('u')) field|= L_ATIME;
+	if (present('c')) field|= L_CTIME;
+	if (present('l')) field|= L_MODE | L_LONG;
+	if (present('g')) field|= L_MODE | L_LONG | L_GROUP;
+	if (present('F')) field|= L_MARK;
+	if (present('p')) field|= L_MARKDIR;
+	if (present('D')) field|= L_TYPE;
+	if (present('T')) field|= L_MODE | L_LONG | L_LONGTIME;
+	if (present('d')) field|= L_DIR;
+	if (present('h')) field|= L_KMG;
+	if (field & L_LONG) field&= ~L_EXTRA;
+
+#ifdef S_IFLNK
+	status= present('L') ? stat : lstat;
+#endif
+
+	if (present('C')) {
+		int t= istty ? 1 : open("/dev/tty", O_WRONLY);
+
+		if (t >= 0 && ioctl(t, TIOCGWINSZ, &ws) == 0 && ws.ws_col > 0)
+			ncols= ws.ws_col - 1;
+
+		if (t != 1 && t != -1) close(t);
+	}
+
+	depth= SURFACE;
+
+	if (*argv == nil) {
+		if (!(field & L_DIR)) depth= SURFACE1;
+		pushfile(aflist, newfile("."));
+	} else {
+		if (argv[1] == nil && !(field & L_DIR)) depth= SURFACE1;
+
+		do {
+			pushfile(aflist, newfile(*argv++));
+			aflist= &(*aflist)->next;
+		} while (*argv!=nil);
+	}
+	listfiles(flist, depth,
+		(field & L_DIR) ? BOTTOM : present('R') ? FLOATING : SINKING);
+	return ex;
+}
Index: /trunk/minix/commands/simple/mail.c
===================================================================
--- /trunk/minix/commands/simple/mail.c	(revision 9)
+++ /trunk/minix/commands/simple/mail.c	(revision 9)
@@ -0,0 +1,776 @@
+/*  mail - send/receive mail 		 Author: Peter S. Housel */
+/* Version 0.2 of September 1990: added -e, -t, * options - cwr */
+
+/* 2003-07-18: added -s option - ASW */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#undef EOF			/* temporary hack */
+#include <signal.h>
+#include <pwd.h>
+#include <time.h>
+#include <setjmp.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <stdio.h>
+
+#ifdef DEBUG
+#define D(Q) (Q)
+#else
+#define D(Q)
+#endif
+
+#define SHELL		"/bin/sh"
+
+#define DROPNAME 	"/usr/spool/mail/%s"
+#define LOCKNAME	"/usr/spool/mail/%s.lock"
+#define LOCKWAIT	5	/* seconds to wait after collision */
+#define LOCKTRIES	4	/* maximum number of collisions */
+
+#define MBOX		"mbox"
+
+#define HELPFILE	"/usr/lib/mail.help"
+#define PROMPT		"? "
+#define PATHLEN		80
+#define MAXRCPT		100	/* maximum number of recipients */
+#define LINELEN		512
+
+/* #define MAILER		"/usr/bin/smail"	*/ /* smart mailer */
+#define MAILERARGS		/* (unused) */
+
+#define UNREAD		1	/* 'not read yet' status */
+#define DELETED		2	/* 'deleted' status */
+#define READ		3	/* 'has been read' status */
+
+struct letter {
+  struct letter *prev, *next;	/* linked letter list */
+  int status;			/* letter status */
+  off_t location;		/* location within mailbox file */
+};
+
+struct letter *firstlet, *lastlet;
+
+int usemailer = 1;		/* use MAILER to deliver (if any) */
+int printmode = 0;		/* print-and-exit mode */
+int quitmode = 0;		/* take interrupts */
+int reversemode = 0;		/* print mailbox in reverse order */
+int usedrop = 1;		/* read the maildrop (no -f given) */
+int verbose = 0;		/* pass "-v" flag on to mailer */
+int needupdate = 0;		/* need to update mailbox */
+int msgstatus = 0;		/* return the mail status */
+int distlist = 0;		/* include distribution list */
+char mailbox[PATHLEN];		/* user's mailbox/maildrop */
+char tempname[PATHLEN] = "/tmp/mailXXXXXX";	/* temporary file */
+char *subject = NULL;
+FILE *boxfp = NULL;		/* mailbox file */
+jmp_buf printjump;		/* for quitting out of letters */
+unsigned oldmask;		/* saved umask() */
+
+extern int optind;
+extern char *optarg;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(int deliver, (int count, char *vec []));
+_PROTOTYPE(FILE *makerewindable, (void));
+_PROTOTYPE(int copy, (FILE *fromfp, FILE *tofp));
+_PROTOTYPE(void readbox, (void));
+_PROTOTYPE(void printall, (void));
+_PROTOTYPE(void interact, (void));
+_PROTOTYPE(void onint, (int dummy));
+_PROTOTYPE(void savelet, (struct letter *let, char *savefile));
+_PROTOTYPE(void updatebox, (void));
+_PROTOTYPE(void printlet, (struct letter *let, FILE *tofp));
+_PROTOTYPE(void doshell, (char *command));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(char *basename, (char *name));
+_PROTOTYPE(char *whoami, (void));
+_PROTOTYPE(void dohelp, (void));
+_PROTOTYPE(int filesize, (char *name));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int c;
+
+  if ('l' == (basename(argv[0]))[0])	/* 'lmail' link? */
+	usemailer = 0;		/* yes, let's deliver it */
+
+  (void) mktemp(tempname);	/* name the temp file */
+
+  oldmask = umask(022);		/* change umask for security */
+
+  while (EOF != (c = getopt(argc, argv, "epqrf:tdvs:"))) switch (c) {
+	    case 'e':	++msgstatus;	break;	
+
+	    case 't':	++distlist;	break;
+
+	    case 'p':	++printmode;	break;
+
+	    case 'q':	++quitmode;	break;
+
+	    case 'r':	++reversemode;	break;
+
+	    case 'f':
+		setuid(getuid());	/* won't need to lock */
+		usedrop = 0;
+		strncpy(mailbox, optarg, (size_t)(PATHLEN - 1));
+		break;
+
+	    case 'd':	usemailer = 0;	break;
+
+	    case 'v':	++verbose;	break;
+
+	    case 's':	subject = optarg; break;
+
+	    default:
+		usage();
+		exit(1);
+	}
+
+  if (optind < argc) {
+	if (deliver(argc - optind, argv + optind) < 0)
+		exit(1);
+	else
+		exit(0);
+  }
+  if (usedrop) sprintf(mailbox, DROPNAME, whoami());
+
+  D(printf("mailbox=%s\n", mailbox));
+
+  if (msgstatus) {
+	if (filesize(mailbox))
+		exit(0);
+	else
+		exit(1);
+  }
+
+  readbox();
+
+  if (printmode)
+	printall();
+  else
+	interact();
+
+  if (needupdate) updatebox();
+
+  return(0);
+}
+
+int deliver(count, vec)
+int count;
+char *vec[];
+{
+  int i, j;
+  int errs = 0;			/* count of errors */
+  int dropfd;			/* file descriptor for user's drop */
+  int created = 0;		/* true if we created the maildrop */
+  FILE *mailfp;			/* fp for mail */
+  struct stat stb;		/* for checking drop modes, owners */
+#ifdef __STDC__
+  void (*sigint)(int), (*sighup)(int), (*sigquit)(int);/* saving signal state */
+#else
+  void (*sigint) (), (*sighup) (), (*sigquit) ();      /* saving signal state */
+#endif
+  time_t now;			/* for datestamping the postmark */
+  char sender[32];		/* sender's login name */
+  char lockname[PATHLEN];	/* maildrop lock */
+  int locktries;		/* tries when box is locked */
+  struct passwd *pw;		/* sender and recipent */
+  int to_console;		/* deliver to console if everything fails */
+
+  if (count > MAXRCPT) {
+	fprintf(stderr, "mail: too many recipients\n");
+	return -1;
+  }
+#ifdef MAILER
+  if (usemailer) {
+	char *argvec[MAXRCPT + 3];
+	char **argp;
+
+	setuid(getuid());
+
+	argp = argvec;
+	*argp++ = "send-mail";
+	if (verbose) *argp++ = "-v";
+
+	for (i = 0; i < count; ++i) *argp++ = vec[i];
+
+	*argp = NULL;
+	execv(MAILER, argvec);
+	fprintf(stderr, "mail: couldn't exec %s\n", MAILER);
+	return -1;
+  }
+#endif /* MAILER */
+
+  if (NULL == (pw = getpwuid(getuid()))) {
+	fprintf(stderr, "mail: unknown sender\n");
+	return -1;
+  }
+  strcpy(sender, pw->pw_name);
+
+  /* If we need to rewind stdin and it isn't rewindable, make a copy */
+  if (isatty(0) || (count > 1 && lseek(0, 0L, 0) == (off_t) -1)) {
+	mailfp = makerewindable();
+  } else
+	mailfp = stdin;
+
+  /* Shut off signals during the delivery */
+  sigint = signal(SIGINT, SIG_IGN);
+  sighup = signal(SIGHUP, SIG_IGN);
+  sigquit = signal(SIGQUIT, SIG_IGN);
+
+  for (i = 0; i < count; ++i) {
+	if (count > 1) rewind(mailfp);
+
+	D(printf("deliver to %s\n", vec[i]));
+
+	if (NULL == (pw = getpwnam(vec[i]))) {
+		fprintf(stderr, "mail: user %s not known\n", vec[i]);
+		++errs;
+		continue;
+	}
+	sprintf(mailbox, DROPNAME, pw->pw_name);
+	sprintf(lockname, LOCKNAME, pw->pw_name);
+
+	D(printf("maildrop='%s', lock='%s'\n", mailbox, lockname));
+
+	/* Lock the maildrop while we're messing with it. Races are
+	 * possible (though not very likely) when we have to create
+	 * the maildrop, but not otherwise. If the box is already
+	 * locked, wait awhile and try again. */
+	locktries = created = to_console = 0;
+trylock:
+	if (link(mailbox, lockname) != 0) {
+		if (ENOENT == errno) {	/* user doesn't have a drop yet */
+			dropfd = creat(mailbox, 0600);
+			if (dropfd < 0 && errno == ENOENT) {
+				/* Probably missing spool dir; to console. */
+				boxfp = fopen("/dev/console", "w");
+				if (boxfp != NULL) {
+					to_console = 1;
+					goto nobox;
+				}
+			}
+			if (dropfd < 0) {
+				fprintf(stderr, "mail: couln't create a maildrop for user %s\n",
+					vec[i]);
+				++errs;
+				continue;
+			}
+			++created;
+			goto trylock;
+		} else {	/* somebody else has it locked, it seems -
+			 * wait */
+			if (++locktries >= LOCKTRIES) {
+				fprintf(stderr, "mail: couldn't lock maildrop for user %s\n",
+					vec[i]);
+				++errs;
+				continue;
+			}
+			sleep(LOCKWAIT);
+			goto trylock;
+		}
+	}
+	if (created) {
+		(void) chown(mailbox, pw->pw_uid, pw->pw_gid);
+		boxfp = fdopen(dropfd, "a");
+	} else
+		boxfp = fopen(mailbox, "a");
+
+	if (NULL == boxfp || stat(mailbox, &stb) < 0) {
+		fprintf(stderr, "mail: serious maildrop problems for %s\n", vec[i]);
+		unlink(lockname);
+		++errs;
+		continue;
+	}
+	if (stb.st_uid != pw->pw_uid || (stb.st_mode & S_IFMT) != S_IFREG) {
+		fprintf(stderr, "mail: mailbox for user %s is illegal\n", vec[i]);
+		unlink(lockname);
+		++errs;
+		continue;
+	}
+nobox:
+	if (to_console) {
+		fprintf(boxfp,
+			"-------------\n| Mail from %s to %s\n-------------\n",
+			sender, vec[i]);
+	} else {
+		(void) time(&now);
+		fprintf(boxfp, "From %s %24.24s\n", sender, ctime(&now));
+	}
+
+	/* Add the To: header line */
+	fprintf(boxfp, "To: %s\n", vec[i]);
+
+	if (distlist) {
+		fprintf(boxfp, "Dist: ");
+		for (j = 0; j < count; ++j)
+			if (getpwnam(vec[j]) != NULL && j != i)
+				fprintf(boxfp, "%s ", vec[j]) ;
+		fprintf(boxfp, "\n");
+	}
+
+	/* Add the Subject: header line */
+	if (subject != NULL) fprintf(boxfp, "Subject: %s\n", subject);
+
+	fprintf(boxfp, "\n");
+ 
+	if ((copy(mailfp, boxfp) < 0) || (fclose(boxfp) != 0)) {
+		fprintf(stderr, "mail: error delivering to user %s", vec[i]);
+		perror(" ");
+		++errs;
+	}
+	unlink(lockname);
+  }
+
+  fclose(mailfp);
+
+  /* Put signals back the way they were */
+  signal(SIGINT, sigint);
+  signal(SIGHUP, sighup);
+  signal(SIGQUIT, sigquit);
+
+  return(0 == errs) ? 0 : -1;
+}
+
+/* 'stdin' isn't rewindable. Make a temp file that is.
+ * Note that if one wanted to catch SIGINT and write a '~/dead.letter'
+ * for interactive mails, this might be the place to do it (though the
+ * case where a MAILER is being used would also need to be handled).
+ */
+FILE *makerewindable()
+{
+  FILE *tempfp;			/* temp file used for copy */
+  int c;			/* character being copied */
+  int state;			/* ".\n" detection state */
+
+  if (NULL == (tempfp = fopen(tempname, "w"))) {
+	fprintf(stderr, "mail: can't create temporary file\n");
+	return NULL;
+  }
+
+  /* Here we copy until we reach the end of the letter (end of file or
+   * a line containing only a '.'), painstakingly avoiding setting a
+   * line length limit. */
+  state = '\n';
+  while (EOF != (c = getc(stdin))) switch (state) {
+	    case '\n':
+		if ('.' == c)
+			state = '.';
+		else {
+			if ('\n' != c) state = '\0';
+			putc(c, tempfp);
+		}
+		break;
+	    case '.':
+		if ('\n' == c) goto done;
+		state = '\0';
+		putc('.', tempfp);
+		putc(c, tempfp);
+		break;
+	    default:
+		state = ('\n' == c) ? '\n' : '\0';
+		putc(c, tempfp);
+	}
+done:
+  if (ferror(tempfp) || fclose(tempfp)) {
+	fprintf(stderr, "mail: couldn't copy letter to temporary file\n");
+	return NULL;
+  }
+  tempfp = freopen(tempname, "r", stdin);
+  unlink(tempname);		/* unlink name; file lingers on in limbo */
+  return tempfp;
+}
+
+int copy(fromfp, tofp)
+FILE *fromfp, *tofp;
+{
+  int c;			/* character being copied */
+  int state;			/* ".\n" and postmark detection state */
+  int blankline = 0;		/* was most recent line completely blank? */
+  static char postmark[] = "From ";
+  char *p, *q;
+
+  /* Here we copy until we reach the end of the letter (end of file or
+   * a line containing only a '.'). Postmarks (lines beginning with
+   * "From ") are copied with a ">" prepended. Here we also complicate
+   * things by not setting a line limit. */
+  state = '\n';
+  p = postmark;
+  while (EOF != (c = getc(fromfp))) {
+	switch (state) {
+	    case '\n':
+		if ('.' == c)	/* '.' at BOL */
+			state = '.';
+		else if (*p == c) {	/* start of postmark */
+			++p;
+			state = 'P';
+		} else {	/* anything else */
+			if ('\n' == c)
+				blankline = 1;
+			else {
+				state = '\0';
+				blankline = 0;
+			}
+			putc(c, tofp);
+		}
+		break;
+	    case '.':
+		if ('\n' == c) goto done;
+		state = '\0';
+		putc('.', tofp);
+		putc(c, tofp);
+		break;
+	    case 'P':
+		if (*p == c) {
+			if (*++p == '\0') {	/* successfully reached end */
+				p = postmark;
+				putc('>', tofp);
+				fputs(postmark, tofp);
+				state = '\0';
+				break;
+			}
+			break;	/* not there yet */
+		}
+		state = ('\n' == c) ? '\n' : '\0';
+		for (q = postmark; q < p; ++q) putc(*q, tofp);
+		putc(c, tofp);
+		blankline = 0;
+		p = postmark;
+		break;
+	    default:
+		state = ('\n' == c) ? '\n' : '\0';
+		putc(c, tofp);
+	}
+  }
+  if ('\n' != state) putc('\n', tofp);
+done:
+  if (!blankline) putc('\n', tofp);
+  if (ferror(tofp)) return -1;
+  return 0;
+}
+
+void readbox()
+{
+  char linebuf[512];
+  struct letter *let;
+  off_t current;
+
+  firstlet = lastlet = NULL;
+
+  if (access(mailbox, 4) < 0 || NULL == (boxfp = fopen(mailbox, "r"))) {
+	if (usedrop && ENOENT == errno) return;
+	fprintf(stderr, "can't access mailbox ");
+	perror(mailbox);
+	exit(1);
+  }
+  current = 0L;
+  while (1) {
+	if (NULL == fgets(linebuf, sizeof linebuf, boxfp)) break;
+
+	if (!strncmp(linebuf, "From ", (size_t)5)) {
+		if (NULL == (let = (struct letter *) malloc(sizeof(struct letter)))) {
+			fprintf(stderr, "Out of memory.\n");
+			exit(1);
+		}
+		if (NULL == lastlet) {
+			firstlet = let;
+			let->prev = NULL;
+		} else {
+			let->prev = lastlet;
+			lastlet->next = let;
+		}
+		lastlet = let;
+		let->next = NULL;
+
+		let->status = UNREAD;
+		let->location = current;
+		D(printf("letter at %ld\n", current));
+	}
+	current += strlen(linebuf);
+  }
+}
+
+void printall()
+{
+  struct letter *let;
+
+  let = reversemode ? firstlet : lastlet;
+
+  if (NULL == let) {
+	printf("No mail.\n");
+	return;
+  }
+  while (NULL != let) {
+	printlet(let, stdout);
+	let = reversemode ? let->next : let->prev;
+  }
+}
+
+void interact()
+{
+  char linebuf[512];		/* user input line */
+  struct letter *let, *next;	/* current and next letter */
+  int interrupted = 0;		/* SIGINT hit during letter print */
+  int needprint = 1;		/* need to print this letter */
+  char *savefile;		/* filename to save into */
+
+  if (NULL == firstlet) {
+	printf("No mail.\n");
+	return;
+  }
+  let = reversemode ? firstlet : lastlet;
+
+  while (1) {
+	next = reversemode ? let->next : let->prev;
+	if (NULL == next) next = let;
+
+	if (!quitmode) {
+		interrupted = setjmp(printjump);
+		signal(SIGINT, onint);
+	}
+	if (!interrupted && needprint) {
+		if (DELETED != let->status) let->status = READ;
+		printlet(let, stdout);
+	}
+	if (interrupted) putchar('\n');
+	needprint = 0;
+	fputs(PROMPT, stdout);
+	fflush(stdout);
+
+	if (fgets(linebuf, sizeof linebuf, stdin) == NULL) break;
+
+	if (!quitmode) signal(SIGINT, SIG_IGN);
+
+	switch (linebuf[0]) {
+	    case '\n':
+		let = next;
+		needprint = 1;
+		continue;
+	    case 'd':
+		let->status = DELETED;
+		if (next != let)/* look into this */
+			needprint = 1;
+		needupdate = 1;
+		let = next;
+		continue;
+	    case 'p':
+		needprint = 1;
+		continue;
+	    case '-':
+		next = reversemode ? let->prev : let->next;
+		if (NULL == next) next = let;
+		let = next;
+		needprint = 1;
+		continue;
+	    case 's':
+		for (savefile = strtok(linebuf + 1, " \t\n");
+		     savefile != NULL;
+		     savefile = strtok((char *) NULL, " \t\n")) {
+			savelet(let, savefile);
+		}
+		continue;
+	    case '!':
+		doshell(linebuf + 1);
+		continue;
+	    case '*':
+		dohelp();
+		continue;
+	    case 'q':
+		return;
+	    case 'x':
+		exit(0);
+	    default:
+		fprintf(stderr, "Illegal command\n");
+		continue;
+	}
+  }
+}
+
+void onint(dummy)
+int dummy;	/* to satisfy ANSI compilers */
+{
+  longjmp(printjump, 1);
+}
+
+void savelet(let, savefile)
+struct letter *let;
+char *savefile;
+{
+  int waitstat, pid;
+  FILE *savefp;
+
+  if ((pid = fork()) < 0) {
+	perror("mail: couldn't fork");
+	return;
+  } else if (pid != 0) {	/* parent */
+	wait(&waitstat);
+	return;
+  }
+
+  /* Child */
+  setgid(getgid());
+  setuid(getuid());
+  if ((savefp = fopen(savefile, "a")) == NULL) {
+	perror(savefile);
+	exit(0);
+  }
+  printlet(let, savefp);
+  if ((ferror(savefp) != 0) | (fclose(savefp) != 0)) {
+	fprintf(stderr, "savefile write error:");
+	perror(savefile);
+  }
+  exit(0);
+}
+
+void updatebox()
+{
+  FILE *tempfp;			/* fp for tempfile */
+  char lockname[PATHLEN];	/* maildrop lock */
+  int locktries = 0;		/* tries when box is locked */
+  struct letter *let;		/* current letter */
+  int c;
+
+  sprintf(lockname, LOCKNAME, whoami());
+
+  if (NULL == (tempfp = fopen(tempname, "w"))) {
+	perror("mail: can't create temporary file");
+	return;
+  }
+  for (let = firstlet; let != NULL; let = let->next) {
+	if (let->status != DELETED) {
+		printlet(let, tempfp);
+		D(printf("printed letter at %ld\n", let->location));
+	}
+  }
+
+  if (ferror(tempfp) || NULL == (tempfp = freopen(tempname, "r", tempfp))) {
+	perror("mail: temporary file write error");
+	unlink(tempname);
+	return;
+  }
+
+  /* Shut off signals during the update */
+  signal(SIGINT, SIG_IGN);
+  signal(SIGHUP, SIG_IGN);
+  signal(SIGQUIT, SIG_IGN);
+
+  if (usedrop) while (link(mailbox, lockname) != 0) {
+		if (++locktries >= LOCKTRIES) {
+			fprintf(stderr, "mail: couldn't lock maildrop for update\n");
+			return;
+		}
+		sleep(LOCKWAIT);
+	}
+
+  if (NULL == (boxfp = freopen(mailbox, "w", boxfp))) {
+	perror("mail: couldn't reopen maildrop");
+	fprintf(stderr, "mail may have been lost; look in %s\n", tempname);
+	if (usedrop) unlink(lockname);
+	return;
+  }
+  unlink(tempname);
+
+  while ((c = getc(tempfp)) != EOF) putc(c, boxfp);
+
+  fclose(boxfp);
+
+  if (usedrop) unlink(lockname);
+}
+
+void printlet(let, tofp)
+struct letter *let;
+FILE *tofp;
+{
+  off_t current, limit;
+  int c;
+
+  fseek(boxfp, (current = let->location), 0);
+  limit = (NULL != let->next) ? let->next->location : -1;
+
+  while (current != limit && (c = getc(boxfp)) != EOF) {
+	putc(c, tofp);
+	++current;
+  }
+}
+
+void doshell(command)
+char *command;
+{
+  int waitstat, pid;
+  char *shell;
+
+  if (NULL == (shell = getenv("SHELL"))) shell = SHELL;
+
+  if ((pid = fork()) < 0) {
+	perror("mail: couldn't fork");
+	return;
+  } else if (pid != 0) {	/* parent */
+	wait(&waitstat);
+	return;
+  }
+
+  /* Child */
+  setgid(getgid());
+  setuid(getuid());
+  umask(oldmask);
+
+  execl(shell, shell, "-c", command, (char *) NULL);
+  fprintf(stderr, "can't exec shell\n");
+  exit(127);
+}
+
+void usage()
+{
+  fprintf(stderr, "usage: mail [-epqr] [-f file]\n");
+  fprintf(stderr, "       mail [-dtv] [-s subject] user [...]\n");
+}
+
+char *basename(name)
+char *name;
+{
+  char *p;
+
+  if (NULL == (p = rindex(name, '/')))
+	return name;
+  else
+	return p + 1;
+}
+
+char *whoami()
+{
+  struct passwd *pw;
+
+  if (NULL != (pw = getpwuid(getuid())))
+	return pw->pw_name;
+  else
+	return "nobody";
+}
+
+void dohelp()
+{
+  FILE *fp;
+  char buffer[80];
+
+  if ( (fp = fopen(HELPFILE, "r")) == NULL)
+	fprintf(stdout, "can't open helpfile %s\n", HELPFILE);
+  else
+	while (fgets(buffer, 80, fp))
+		fputs(buffer, stdout);
+}
+
+int filesize(name)
+char *name ;
+{
+  struct stat buf;
+ 
+  if (stat(name, &buf) == -1)
+	buf.st_size = 0L;
+
+  return (buf.st_size ? 1 : 0);
+}
Index: /trunk/minix/commands/simple/man.c
===================================================================
--- /trunk/minix/commands/simple/man.c	(revision 9)
+++ /trunk/minix/commands/simple/man.c	(revision 9)
@@ -0,0 +1,695 @@
+/*	man 2.4 - display online manual pages		Author: Kees J. Bot
+ *								17 Mar 1993
+ */
+#define nil NULL
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+/* Defaults: */
+char MANPATH[]=	"/usr/local/man:/usr/man:/usr/gnu/man";
+char PAGER[]=	"more";
+
+/* Comment at the start to let tbl(1) be run before n/troff. */
+char TBL_MAGIC[] = ".\\\"t\n";
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+#define between(a, c, z) ((unsigned) ((c) - (a)) <= (unsigned) ((z) - (a)))
+
+/* Section 9 uses special macros under Minix. */
+#if __minix
+#define SEC9SPECIAL	1
+#else
+#define SEC9SPECIAL	0
+#endif
+
+int searchwhatis(FILE *wf, char *title, char **ppage, char **psection)
+/* Search a whatis file for the next occurence of "title".  Return the basename
+ * of the page to read and the section it is in.  Return 0 on failure, 1 on
+ * success, -1 on EOF or error.
+ */
+{
+    static char page[256], section[32];
+    char alias[256];
+    int found= 0;
+    int c;
+
+    /* Each whatis line should have the format:
+     *	page, title, title (section) - descriptive text
+     */
+
+    /* Search the file for a line with the title. */
+    do {
+	int first= 1;
+	char *pc= section;
+
+	c= fgetc(wf);
+
+	/* Search the line for the title. */
+	do {
+	    char *pa= alias;
+
+	    while (c == ' ' || c == '\t' || c == ',') c= fgetc(wf);
+
+	    while (c != ' ' && c != '\t' && c != ','
+		    && c != '(' && c != '\n' && c != EOF
+	    ) {
+		if (pa < arraylimit(alias)-1) *pa++= c;
+		c= getc(wf);
+	    }
+	    *pa= 0;
+	    if (first) { strcpy(page, alias); first= 0; }
+
+	    if (strcmp(alias, title) == 0) found= 1;
+	} while (c != '(' && c != '\n' && c != EOF);
+
+	if (c != '(') {
+	    found= 0;
+	} else {
+	    while ((c= fgetc(wf)) != ')' && c != '\n' && c != EOF) {
+		if ('A' <= c && c <= 'Z') c= c - 'A' + 'a';
+		if (pc < arraylimit(section)-1) *pc++= c;
+	    }
+	    *pc= 0;
+	    if (c != ')' || pc == section) found= 0;
+	}
+	while (c != EOF && c != '\n') c= getc(wf);
+    } while (!found && c != EOF);
+
+    if (found) {
+	*ppage= page;
+	*psection= section;
+    }
+    return c == EOF ? -1 : found;
+}
+
+int searchwindex(FILE *wf, char *title, char **ppage, char **psection)
+/* Search a windex file for the next occurence of "title".  Return the basename
+ * of the page to read and the section it is in.  Return 0 on failure, 1 on
+ * success, -1 on EOF or error.
+ */
+{
+    static char page[256], section[32];
+    static long low, high;
+    long mid0, mid1;
+    int c;
+    unsigned char *pt;
+    char *pc;
+
+    /* Each windex line should have the format:
+     *	title page (section) - descriptive text
+     * The file is sorted.
+     */
+
+    if (ftell(wf) == 0) {
+	/* First read of this file, initialize. */
+	low= 0;
+	fseek(wf, (off_t) 0, SEEK_END);
+	high= ftell(wf);
+    }
+
+    /* Binary search for the title. */
+    while (low <= high) {
+	pt= (unsigned char *) title;
+
+	mid0= mid1= (low + high) >> 1;
+	if (mid0 == 0) {
+	    if (fseek(wf, (off_t) 0, SEEK_SET) != 0)
+		return -1;
+	} else {
+	    if (fseek(wf, (off_t) mid0 - 1, SEEK_SET) != 0)
+		return -1;
+
+	    /* Find the start of a line. */
+	    while ((c= getc(wf)) != EOF && c != '\n')
+		mid1++;
+	    if (ferror(wf)) return -1;
+	}
+
+	/* See if the line has the title we seek. */
+	for (;;) {
+	    if ((c= getc(wf)) == ' ' || c == '\t') c= 0;
+	    if (c == 0 || c != *pt) break;
+	    pt++;
+	}
+
+	/* Halve the search range. */
+	if (c == EOF || *pt <= c) {
+	    high= mid0 - 1;
+	} else {
+	    low= mid1 + 1;
+	}
+    }
+
+    /* Look for the title from 'low' onwards. */
+    if (fseek(wf, (off_t) low, SEEK_SET) != 0)
+	return -1;
+
+    do {
+	if (low != 0) {
+	    /* Find the start of a line. */
+	    while ((c= getc(wf)) != EOF && c != '\n')
+		low++;
+	    if (ferror(wf)) return -1;
+	}
+
+	/* See if the line has the title we seek. */
+	pt= (unsigned char *) title;
+
+	for (;;) {
+	    if ((c= getc(wf)) == EOF) return 0;
+	    low++;
+	    if (c == ' ' || c == '\t') c= 0;
+	    if (c == 0 || c != *pt) break;
+	    pt++;
+	}
+    } while (c < *pt);
+
+    if (*pt != c) return 0;		/* Not found. */
+
+    /* Get page and section. */
+    while ((c= fgetc(wf)) == ' ' || c == '\t') {}
+
+    pc= page;
+    while (c != ' ' && c != '\t' && c != '(' && c != '\n' && c != EOF) {
+	if (pc < arraylimit(page)-1) *pc++= c;
+	c= getc(wf);
+    }
+    if (pc == page) return 0;
+    *pc= 0;
+
+    while (c == ' ' || c == '\t') c= fgetc(wf);
+
+    if (c != '(') return 0;
+
+    pc= section;
+    while ((c= fgetc(wf)) != ')' && c != '\n' && c != EOF) {
+	if ('A' <= c && c <= 'Z') c= c - 'A' + 'a';
+	if (pc < arraylimit(section)-1) *pc++= c;
+    }
+    *pc= 0;
+    if (c != ')' || pc == section) return 0;
+
+    while (c != EOF && c != '\n') c= getc(wf);
+    if (c != '\n') return 0;
+
+    *ppage= page;
+    *psection= section;
+    return 1;
+}
+
+char ALL[]= "";		/* Magic sequence of all sections. */
+
+int all= 0;		/* Show all pages with a given title. */
+int whatis= 0;		/* man -f word == whatis word. */
+int apropos= 0;		/* man -k word == apropos word. */
+int quiet= 0;		/* man -q == quietly check. */
+enum ROFF { NROFF, TROFF } rofftype= NROFF;
+char *roff[] = { "nroff", "troff" };
+
+int shown;		/* True if something has been shown. */
+int tty;		/* True if displaying on a terminal. */
+char *manpath;		/* The manual directory path. */
+char *pager;		/* The pager to use. */
+
+char *pipeline[8][8];	/* An 8 command pipeline of 7 arguments each. */
+char *(*plast)[8] = pipeline;
+
+void putinline(char *arg1, ...)
+/* Add a command to the pipeline. */
+{
+    va_list ap;
+    char **argv;
+
+    argv= *plast++;
+    *argv++= arg1;
+
+    va_start(ap, arg1);
+    while ((*argv++= va_arg(ap, char *)) != nil) {}
+    va_end(ap);
+}
+
+void execute(int set_mp, char *file)
+/* Execute the pipeline build with putinline().  (This is a lot of work to
+ * avoid a call to system(), but it so much fun to do it right!)
+ */
+{
+    char *(*plp)[8], **argv;
+    char *mp;
+    int fd0, pfd[2], err[2];
+    pid_t pid;
+    int r, status;
+    int last;
+    void (*isav)(int sig), (*qsav)(int sig), (*tsav)(int sig);
+
+    if (tty) {
+	/* Must run this through a pager. */
+	putinline(pager, (char *) nil);
+    }
+    if (plast == pipeline) {
+	/* No commands at all? */
+	putinline("cat", (char *) nil);
+    }
+
+    /* Add the file as argument to the first command. */
+    argv= pipeline[0];
+    while (*argv != nil) argv++;
+    *argv++= file;
+    *argv= nil;
+
+    /* Start the commands. */
+    fd0= 0;
+    for (plp= pipeline; plp < plast; plp++) {
+	argv= *plp;
+	last= (plp+1 == plast);
+
+	/* Create an error pipe and pipe between this command and the next. */
+	if (pipe(err) < 0 || (!last && pipe(pfd) < 0)) {
+	    fprintf(stderr, "man: can't create a pipe: %s\n", strerror(errno));
+	    exit(1);
+	}
+
+	(void) fcntl(err[1], F_SETFD, fcntl(err[1], F_GETFD) | FD_CLOEXEC);
+
+	if ((pid = fork()) < 0) {
+	    fprintf(stderr, "man: cannot fork: %s\n", strerror(errno));
+	    exit(1);
+	}
+	if (pid == 0) {
+	    /* Child. */
+	    if (set_mp) {
+		mp= malloc((8 + strlen(manpath) + 1) * sizeof(*mp));
+		if (mp != nil) {
+		    strcpy(mp, "MANPATH=");
+		    strcat(mp, manpath);
+		    (void) putenv(mp);
+		}
+	    }
+
+	    if (fd0 != 0) {
+		dup2(fd0, 0);
+		close(fd0);
+	    }
+	    if (!last) {
+		close(pfd[0]);
+		if (pfd[1] != 1) {
+		    dup2(pfd[1], 1);
+		    close(pfd[1]);
+		}
+	    }
+	    close(err[0]);
+	    execvp(argv[0], argv);
+	    (void) write(err[1], &errno, sizeof(errno));
+	    _exit(1);
+	}
+
+	close(err[1]);
+	if (read(err[0], &errno, sizeof(errno)) != 0) {
+	    fprintf(stderr, "man: %s: %s\n", argv[0],
+			    strerror(errno));
+	    exit(1);
+	}
+	close(err[0]);
+
+	if (!last) {
+	    close(pfd[1]);
+	    fd0= pfd[0];
+	}
+	set_mp= 0;
+    }
+
+    /* Wait for the last command to finish. */
+    isav= signal(SIGINT, SIG_IGN);
+    qsav= signal(SIGQUIT, SIG_IGN);
+    tsav= signal(SIGTERM, SIG_IGN);
+    while ((r= wait(&status)) != pid) {
+	if (r < 0) {
+	    fprintf(stderr, "man: wait(): %s\n", strerror(errno));
+	    exit(1);
+	}
+    }
+    (void) signal(SIGINT, isav);
+    (void) signal(SIGQUIT, qsav);
+    (void) signal(SIGTERM, tsav);
+    if (status != 0) exit(1);
+    plast= pipeline;
+}
+
+void keyword(char *keyword)
+/* Make an apropos(1) or whatis(1) call. */
+{
+    putinline(apropos ? "apropos" : "whatis",
+		all ? "-a" : (char *) nil,
+		(char *) nil);
+
+    if (tty) {
+	printf("Looking for keyword '%s'\n", keyword);
+	fflush(stdout);
+    }
+
+    execute(1, keyword);
+}
+
+enum pagetype { CAT, CATZ, MAN, MANZ, SMAN, SMANZ };
+
+int showpage(char *page, enum pagetype ptype, char *macros)
+/* Show a manual page if it exists using the proper decompression and
+ * formatting tools.
+ */
+{
+    struct stat st;
+
+    /* We want a normal file without X bits if not a full path. */
+    if (stat(page, &st) < 0) return 0;
+
+    if (!S_ISREG(st.st_mode)) return 0;
+    if ((st.st_mode & 0111) && page[0] != '/') return 0;
+
+    /* Do we only care if it exists? */
+    if (quiet) { shown= 1; return 1; }
+
+    if (ptype == CATZ || ptype == MANZ || ptype == SMANZ) {
+	putinline("zcat", (char *) nil);
+    }
+
+    if (ptype == SMAN || ptype == SMANZ) {
+	/* Change SGML into regular *roff. */
+	putinline("/usr/lib/sgml/sgml2roff", (char *) nil);
+	putinline("tbl", (char *) nil);
+	putinline("eqn", (char *) nil);
+    }
+
+    if (ptype == MAN) {
+	/* Do we need tbl? */
+	FILE *fp;
+	int c;
+	char *tp = TBL_MAGIC;
+
+	if ((fp = fopen(page, "r")) == nil) {
+	    fprintf(stderr, "man: %s: %s\n", page, strerror(errno));
+	    exit(1);
+	}
+	c= fgetc(fp);
+	for (;;) {
+	    if (c == *tp || (c == '\'' && *tp == '.')) {
+		if (*++tp == 0) {
+		    /* A match, add tbl. */
+		    putinline("tbl", (char *) nil);
+		    break;
+		}
+	    } else {
+		/* No match. */
+		break;
+	    }
+	    while ((c = fgetc(fp)) == ' ' || c == '\t') {}
+	}
+	fclose(fp);
+    }
+
+    if (ptype == MAN || ptype == MANZ || ptype == SMAN || ptype == SMANZ) {
+	putinline(roff[rofftype], macros, (char *) nil);
+    }
+
+    if (tty) {
+	printf("%s %s\n",
+	    ptype == CAT || ptype == CATZ ? "Showing" : "Formatting", page);
+	fflush(stdout);
+    }
+    execute(0, page);
+
+    shown= 1;
+    return 1;
+}
+
+int member(char *word, char *list)
+/* True if word is a member of a comma separated list. */
+{
+    size_t len= strlen(word);
+
+    if (list == ALL) return 1;
+
+    while (*list != 0) {
+	if (strncmp(word, list, len) == 0
+		&& (list[len] == 0 || list[len] == ','))
+	    return 1;
+	while (*list != 0 && *list != ',') list++;
+	if (*list == ',') list++;
+    }
+    return 0;
+}
+
+int trymandir(char *mandir, char *title, char *section)
+/* Search the whatis file of the manual directory for a page of the given
+ * section and display it.
+ */
+{
+    FILE *wf;
+    char whatis[1024], pagename[1024], *wpage, *wsection;
+    int rsw, rsp;
+    int ntries;
+    int (*searchidx)(FILE *, char *, char **, char **);
+    struct searchnames {
+	enum pagetype	ptype;
+	char		*pathfmt;
+    } *sp;
+    static struct searchnames searchN[] = {
+	{ CAT,	"%s/cat%s/%s.%s"	},	/* SysV */
+	{ CATZ,	"%s/cat%s/%s.%s.Z"	},
+	{ MAN,	"%s/man%s/%s.%s"	},
+	{ MANZ,	"%s/man%s/%s.%s.Z"	},
+	{ SMAN,	"%s/sman%s/%s.%s"	},	/* Solaris */
+	{ SMANZ,"%s/sman%s/%s.%s.Z"	},
+	{ CAT,	"%s/cat%.1s/%s.%s"	},	/* BSD */
+	{ CATZ,	"%s/cat%.1s/%s.%s.Z"	},
+	{ MAN,	"%s/man%.1s/%s.%s"	},
+	{ MANZ,	"%s/man%.1s/%s.%s.Z"	},
+    };
+
+    if (strlen(mandir) + 1 + 6 + 1 > arraysize(whatis)) return 0;
+
+    /* Prefer a fast windex database if available. */
+    sprintf(whatis, "%s/windex", mandir);
+
+    if ((wf= fopen(whatis, "r")) != nil) {
+	searchidx= searchwindex;
+    } else {
+	/* Use a classic whatis database. */
+	sprintf(whatis, "%s/whatis", mandir);
+
+	if ((wf= fopen(whatis, "r")) == nil) return 0;
+	searchidx= searchwhatis;
+    }
+
+    rsp= 0;
+    while (!rsp && (rsw= (*searchidx)(wf, title, &wpage, &wsection)) == 1) {
+	if (!member(wsection, section)) continue;
+
+	/* When looking for getc(1S) we try:
+	 *	cat1s/getc.1s
+	 *	cat1s/getc.1s.Z
+	 *	man1s/getc.1s
+	 *	man1s/getc.1s.Z
+	 *	sman1s/getc.1s
+	 *	sman1s/getc.1s.Z
+	 *	cat1/getc.1s
+	 *	cat1/getc.1s.Z
+	 *	man1/getc.1s
+	 *	man1/getc.1s.Z
+	 */
+
+	if (strlen(mandir) + 2 * strlen(wsection) + strlen(wpage)
+		    + 10 > arraysize(pagename))
+	    continue;
+
+	sp= searchN;
+	ntries= arraysize(searchN);
+	do {
+	    if (sp->ptype <= CATZ && rofftype != NROFF)
+		continue;
+
+	    sprintf(pagename, sp->pathfmt,
+		mandir, wsection, wpage, wsection);
+
+	    rsp= showpage(pagename, sp->ptype,
+		(SEC9SPECIAL && strcmp(wsection, "9") == 0) ? "-mnx" : "-man");
+	} while (sp++, !rsp && --ntries != 0);
+
+	if (all) rsp= 0;
+    }
+    if (rsw < 0 && ferror(wf)) {
+	fprintf(stderr, "man: %s: %s\n", whatis, strerror(errno));
+	exit(1);
+    }
+    fclose(wf);
+    return rsp;
+}
+
+int trysubmandir(char *mandir, char *title, char *section)
+/* Search the subdirectories of this manual directory for whatis files, they
+ * may have manual pages that override the ones in the major directory.
+ */
+{
+    char submandir[1024];
+    DIR *md;
+    struct dirent *entry;
+
+    if ((md= opendir(mandir)) == nil) return 0;
+
+    while ((entry= readdir(md)) != nil) {
+	if (strcmp(entry->d_name, ".") == 0
+	    || strcmp(entry->d_name, "..") == 0) continue;
+	if ((strncmp(entry->d_name, "man", 3) == 0
+	    || strncmp(entry->d_name, "cat", 3) == 0)
+	    && between('0', entry->d_name[3], '9')) continue;
+
+	if (strlen(mandir) + 1 + strlen(entry->d_name) + 1
+		    > arraysize(submandir)) continue;
+
+	sprintf(submandir, "%s/%s", mandir, entry->d_name);
+
+	if (trymandir(submandir, title, section) && !all) {
+	    closedir(md);
+	    return 1;
+	}
+    }
+    closedir(md);
+
+    return 0;
+}
+
+void searchmanpath(char *title, char *section)
+/* Search the manual path for a manual page describing "title." */
+{
+    char mandir[1024];
+    char *pp= manpath, *pd;
+
+    for (;;) {
+	while (*pp != 0 && *pp == ':') pp++;
+
+	if (*pp == 0) break;
+
+	pd= mandir;
+	while (*pp != 0 && *pp != ':') {
+	    if (pd < arraylimit(mandir)) *pd++= *pp;
+	    pp++;
+	}
+	if (pd == arraylimit(mandir)) continue;		/* forget it */
+
+	*pd= 0;
+	if (trysubmandir(mandir, title, section) && !all) break;
+	if (trymandir(mandir, title, section) && !all) break;
+    }
+}
+
+void usage(void)
+{
+    fprintf(stderr, "Usage: man -[antfkq] [-M path] [-s section] title ...\n");
+    exit(1);
+}
+
+int main(int argc, char **argv)
+{
+    char *title, *section= ALL;
+    int i;
+    int nomoreopt= 0;
+    char *opt;
+
+    if ((pager= getenv("PAGER")) == nil) pager= PAGER;
+    if ((manpath= getenv("MANPATH")) == nil) manpath= MANPATH;
+    tty= isatty(1);
+
+    i= 1;
+    do {
+	while (i < argc && argv[i][0] == '-' && !nomoreopt) {
+	    opt= argv[i++]+1;
+	    if (opt[0] == '-' && opt[1] == 0) {
+		nomoreopt= 1;
+		break;
+	    }
+	    while (*opt != 0) {
+		switch (*opt++) {
+		case 'a':
+		    all= 1;
+		    break;
+		case 'f':
+		    whatis= 1;
+		    break;
+		case 'k':
+		    apropos= 1;
+		    break;
+		case 'q':
+		    quiet= 1;
+		    break;
+		case 'n':
+		    rofftype= NROFF;
+		    apropos= whatis= 0;
+		    break;
+		case 't':
+		    rofftype= TROFF;
+		    apropos= whatis= 0;
+		    break;
+		case 's':
+		    if (*opt == 0) {
+			if (i == argc) usage();
+			section= argv[i++];
+		    } else {
+			section= opt;
+			opt= "";
+		    }
+		    break;
+		case 'M':
+		    if (*opt == 0) {
+			if (i == argc) usage();
+			manpath= argv[i++];
+		    } else {
+			manpath= opt;
+			opt= "";
+		    }
+		    break;
+		default:
+		    usage();
+		}
+	    }
+	}
+
+	if (i >= argc) usage();
+
+	if (between('0', argv[i][0], '9') && argv[i][1] == 0) {
+	    /* Allow single digit section designations. */
+	    section= argv[i++];
+	}
+	if (i == argc) usage();
+
+	title= argv[i++];
+
+	if (whatis || apropos) {
+	    keyword(title);
+	} else {
+	    shown= 0;
+	    searchmanpath(title, section);
+
+	    if (!shown) (void) showpage(title, MAN, "-man");
+
+	    if (!shown) {
+		if (!quiet) {
+		    fprintf(stderr,
+			"man: no manual on %s\n",
+			title);
+		}
+		exit(1);
+	    }
+	}
+    } while (i < argc);
+
+    return 0;
+}
Index: /trunk/minix/commands/simple/mesg.c
===================================================================
--- /trunk/minix/commands/simple/mesg.c	(revision 9)
+++ /trunk/minix/commands/simple/mesg.c	(revision 9)
@@ -0,0 +1,48 @@
+/* mesg - enable or disable communications. Author: John J. Ribera */
+
+/*
+ * mesg -	enable or disable communications.
+ *
+ * Usage:	mesg [ y | n ]
+ *
+ *		'mesg n' will turn off group and world permissions of the
+ *			 user's terminal.
+ *		'mesg y' will enable group and world to write to the user's
+ *			 tty.
+ *		mesg	 with no parameters will put the writeable status
+ *			 onto stdout.
+ *
+ * Author:	John J. Ribera, Jr. 09/09/90
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+_PROTOTYPE( int main, (int argc, char *argv []) );
+
+int main(argc, argv)
+int  argc;
+char *argv[];
+{
+  struct stat statb;
+  char *tty_name;
+
+  if ((tty_name = ttyname(0)) == NULL) exit(2);
+  if (stat(tty_name, &statb) == -1) exit(2);
+  if (--argc) {
+	if (*argv[1] == 'n') statb.st_mode = 0600;
+	  else if (*argv[1] == 'y') statb.st_mode = 0620;
+	  else {
+		fprintf(stderr, "mesg: usage: mesg [n|y]\n");
+		exit(2);
+	}
+	if (chmod(tty_name, statb.st_mode) == -1) exit(2);
+  } else printf((statb.st_mode & 020) ? "is y\n" : "is n\n");
+
+  if (statb.st_mode & 020) exit(0);
+
+  exit(1);
+}
+
Index: /trunk/minix/commands/simple/mkdir.c
===================================================================
--- /trunk/minix/commands/simple/mkdir.c	(revision 9)
+++ /trunk/minix/commands/simple/mkdir.c	(revision 9)
@@ -0,0 +1,265 @@
+/* mkdir - Make directories		Author: V. Archer */
+
+/* Copyright 1991 by Vincent Archer
+ *	You may freely redistribute this software, in source or binary
+ *	form, provided that you do not alter this copyright mention in any
+ *	way.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <minix/minlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+extern int optind, opterr;
+extern char *optarg;
+
+#define USR_MODES (S_ISUID|S_IRWXU)
+#define GRP_MODES (S_ISGID|S_IRWXG)
+#define EXE_MODES (S_IXUSR|S_IXGRP|S_IXOTH)
+#ifdef S_ISVTX
+#define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO|S_ISVTX)
+#else
+#define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO)
+#endif
+#define DEFAULT_MODE (S_IRWXU|S_IRWXG|S_IRWXO)
+#define USER_WX (S_IWUSR|S_IXUSR)
+
+
+/* Global variables */
+int pflag;
+char *symbolic;
+mode_t u_mask;
+struct stat st;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(mode_t parsemode, (char *symbolic, mode_t oldmode));
+_PROTOTYPE(int makepath, (char *fordir));
+_PROTOTYPE(int makedir, (char *dirname));
+_PROTOTYPE(void usage, (void));
+
+/* Parse a P1003.2 4.7.7-conformant symbolic mode. */
+mode_t parsemode(char *symbolic, mode_t oldmode)
+{
+  mode_t who, mask, newmode, tmpmask;
+  char action;
+  char *end;
+  unsigned long octalmode;
+
+  octalmode = strtoul(symbolic, &end, 010);
+  if (octalmode < ALL_MODES && *end == 0 && end != symbolic) return octalmode;
+
+  newmode = oldmode & ALL_MODES;
+  while (*symbolic) {
+	who = 0;
+	for (; *symbolic; symbolic++) {
+		if (*symbolic == 'a') {
+			who |= ALL_MODES;
+			continue;
+		}
+		if (*symbolic == 'u') {
+			who |= USR_MODES;
+			continue;
+		}
+		if (*symbolic == 'g') {
+			who |= GRP_MODES;
+			continue;
+		}
+		if (*symbolic == 'o') {
+			who |= S_IRWXO;
+			continue;
+		}
+		break;
+	}
+	if (!*symbolic || *symbolic == ',') usage();
+	while (*symbolic) {
+		if (*symbolic == ',') break;
+		switch (*symbolic) {
+		    default:
+			usage();
+		    case '+':
+		    case '-':
+		    case '=':	action = *symbolic++;
+		}
+		mask = 0;
+		for (; *symbolic; symbolic++) {
+			if (*symbolic == 'u') {
+				tmpmask = newmode & S_IRWXU;
+				mask |= tmpmask | (tmpmask << 3) | (tmpmask << 6);
+				symbolic++;
+				break;
+			}
+			if (*symbolic == 'g') {
+				tmpmask = newmode & S_IRWXG;
+				mask |= tmpmask | (tmpmask >> 3) | (tmpmask << 3);
+				symbolic++;
+				break;
+			}
+			if (*symbolic == 'o') {
+				tmpmask = newmode & S_IRWXO;
+				mask |= tmpmask | (tmpmask >> 3) | (tmpmask >> 6);
+				symbolic++;
+				break;
+			}
+			if (*symbolic == 'r') {
+				mask |= S_IRUSR | S_IRGRP | S_IROTH;
+				continue;
+			}
+			if (*symbolic == 'w') {
+				mask |= S_IWUSR | S_IWGRP | S_IWOTH;
+				continue;
+			}
+			if (*symbolic == 'x') {
+				mask |= EXE_MODES;
+				continue;
+			}
+			if (*symbolic == 's') {
+				mask |= S_ISUID | S_ISGID;
+				continue;
+			}
+			if (*symbolic == 'X') {
+				if (S_ISDIR(oldmode) || (oldmode & EXE_MODES))
+					mask |= EXE_MODES;
+				continue;
+			}
+#ifdef S_ISVTX
+			if (*symbolic == 't') {
+				mask |= S_ISVTX;
+				who |= S_ISVTX;
+				continue;
+			}
+#endif
+			break;
+		}
+		switch (action) {
+		    case '=':
+			if (who)
+				newmode &= ~who;
+			else
+				newmode = 0;
+		    case '+':
+			if (who)
+				newmode |= who & mask;
+			else
+				newmode |= mask & (~u_mask);
+			break;
+		    case '-':
+			if (who)
+				newmode &= ~(who & mask);
+			else
+				newmode &= ~mask | u_mask;
+		}
+	}
+	if (*symbolic) symbolic++;
+  }
+  return(newmode);
+}
+
+
+/* Main module. */
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  int error, c;
+
+  opterr = 0;
+  pflag = 0;
+  symbolic = (char *) 0;
+  u_mask = umask(0);
+  umask(u_mask);
+  while ((c = getopt(argc, argv, "m:p")) != EOF) switch (c) {
+	    case 'm':	symbolic = optarg;	break;
+	    case 'p':	pflag = 1;	break;
+	    default:	usage();
+	}
+  if (optind >= argc) usage();
+
+  error = 0;
+  while (optind < argc) error |= makedir(argv[optind++]);
+  return(error);
+}
+
+
+/* P1003.2 requires that missing intermediate pathname components should be
+ *	created if the -p option is specified (4.40.3).
+ */
+int makepath(fordir)
+char *fordir;
+{
+  char parent[PATH_MAX + 1], *end, *last;
+
+  strcpy(parent, fordir);
+  do {
+	  if (!(end = strrchr(parent, '/'))) return(0);
+	  *end = '\0';
+	  if (!parent[0] || !strcmp(parent, ".")) return(0);
+  } while((last = strrchr(parent, '/')) && !strcmp(last+1, "."));
+
+  if (!stat(parent, &st)) {
+	if (S_ISDIR(st.st_mode)) return(0);
+	errno = ENOTDIR;
+	perror(parent);
+	return(1);
+  }
+  if (mkdir(parent, DEFAULT_MODE)) {
+	if (makepath(parent)) return(1);
+	if (mkdir(parent, DEFAULT_MODE)) {
+		perror(parent);
+		return(1);
+	}
+  }
+
+/* P1003.2 states that, regardless of umask() value, intermediate paths
+ *	should have at least write and search (x) permissions (4.40.10).
+ */
+  if ((u_mask & USER_WX) &&
+      chmod(parent, ((~u_mask) | USER_WX)) & DEFAULT_MODE) {
+	perror(parent);
+	return(1);
+  }
+  return(0);
+}
+
+
+/* Actual directory creation, using a mkdir() system call. */
+int makedir(dirname)
+char *dirname;
+{
+  if (mkdir(dirname, DEFAULT_MODE)) {
+	if (!pflag) {
+		perror(dirname);
+		return(1);
+	}
+	if (!stat(dirname, &st)) {
+		if (S_ISDIR(st.st_mode)) return(0);
+		errno = ENOTDIR;
+		perror(dirname);
+		return(1);
+	}
+	if (makepath(dirname)) return(1);
+	if (mkdir(dirname, DEFAULT_MODE)) {
+		perror(dirname);
+		return(1);
+	}
+  }
+  if (symbolic && (stat(dirname, &st) ||
+		 chmod(dirname, parsemode(symbolic, st.st_mode)))) {
+	perror(dirname);
+	return(1);
+  }
+  return(0);
+}
+
+
+/* Posix command prototype. */
+void usage()
+{
+  std_err("Usage: mkdir [-p] [-m mode] dir...\n");
+  exit(1);
+}
Index: /trunk/minix/commands/simple/mkfifo.c
===================================================================
--- /trunk/minix/commands/simple/mkfifo.c	(revision 9)
+++ /trunk/minix/commands/simple/mkfifo.c	(revision 9)
@@ -0,0 +1,194 @@
+/* mkfifo - Make FIFO special files		Author: V. Archer */
+
+/* Copyright 1991 by Vincent Archer
+ *	You may freely redistribute this software, in source or binary
+ *	form, provided that you do not alter this copyright mention in any
+ *	way.
+ */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <unistd.h>
+#include <minix/minlib.h>
+#include <stdio.h>
+
+#define USR_MODES (S_ISUID|S_IRWXU)
+#define GRP_MODES (S_ISGID|S_IRWXG)
+#define EXE_MODES (S_IXUSR|S_IXGRP|S_IXOTH)
+#ifdef S_ISVTX
+#define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO|S_ISVTX)
+#else
+#define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO)
+#endif
+#define DEFAULT_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
+
+
+/* Global u_mask needed in changemode.h */
+mode_t u_mask;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(mode_t parsemode, (char *symbolic, mode_t oldmode));
+_PROTOTYPE(void usage, (void));
+
+/* Parse a P1003.2 4.7.7-conformant symbolic mode. */
+mode_t parsemode(char *symbolic, mode_t oldmode)
+{
+  mode_t who, mask, newmode, tmpmask;
+  char action;
+
+  newmode = oldmode & ALL_MODES;
+  while (*symbolic) {
+	who = 0;
+	for (; *symbolic; symbolic++) {
+		if (*symbolic == 'a') {
+			who |= ALL_MODES;
+			continue;
+		}
+		if (*symbolic == 'u') {
+			who |= USR_MODES;
+			continue;
+		}
+		if (*symbolic == 'g') {
+			who |= GRP_MODES;
+			continue;
+		}
+		if (*symbolic == 'o') {
+			who |= S_IRWXO;
+			continue;
+		}
+		break;
+	}
+	if (!*symbolic || *symbolic == ',') usage();
+	while (*symbolic) {
+		if (*symbolic == ',') break;
+		switch (*symbolic) {
+		    default:
+			usage();
+		    case '+':
+		    case '-':
+		    case '=':	action = *symbolic++;
+		}
+		mask = 0;
+		for (; *symbolic; symbolic++) {
+			if (*symbolic == 'u') {
+				tmpmask = newmode & S_IRWXU;
+				mask |= tmpmask | (tmpmask << 3) | (tmpmask << 6);
+				symbolic++;
+				break;
+			}
+			if (*symbolic == 'g') {
+				tmpmask = newmode & S_IRWXG;
+				mask |= tmpmask | (tmpmask >> 3) | (tmpmask << 3);
+				symbolic++;
+				break;
+			}
+			if (*symbolic == 'o') {
+				tmpmask = newmode & S_IRWXO;
+				mask |= tmpmask | (tmpmask >> 3) | (tmpmask >> 6);
+				symbolic++;
+				break;
+			}
+			if (*symbolic == 'r') {
+				mask |= S_IRUSR | S_IRGRP | S_IROTH;
+				continue;
+			}
+			if (*symbolic == 'w') {
+				mask |= S_IWUSR | S_IWGRP | S_IWOTH;
+				continue;
+			}
+			if (*symbolic == 'x') {
+				mask |= EXE_MODES;
+				continue;
+			}
+			if (*symbolic == 's') {
+				mask |= S_ISUID | S_ISGID;
+				continue;
+			}
+			if (*symbolic == 'X') {
+				if (S_ISDIR(oldmode) || (oldmode & EXE_MODES))
+					mask |= EXE_MODES;
+				continue;
+			}
+#ifdef S_ISVTX
+			if (*symbolic == 't') {
+				mask |= S_ISVTX;
+				who |= S_ISVTX;
+				continue;
+			}
+#endif
+			break;
+		}
+		switch (action) {
+		    case '=':
+			if (who)
+				newmode &= ~who;
+			else
+				newmode = 0;
+		    case '+':
+			if (who)
+				newmode |= who & mask;
+			else
+				newmode |= mask & (~u_mask);
+			break;
+		    case '-':
+			if (who)
+				newmode &= ~(who & mask);
+			else
+				newmode &= ~mask | u_mask;
+		}
+	}
+	if (*symbolic) symbolic++;
+  }
+  return(newmode);
+}
+
+
+/* Main module. Since only one option (-m mode) is allowed, there's no need
+ * to include the whole getopt() stuff.
+ */
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int errors = 0;
+  char *symbolic;
+
+  if (argc > 2 && *argv[1] == '-' && strcmp(argv[1], "-m") != 0) usage();
+  argc--;
+  argv++;
+  if (argc && strncmp(*argv, "-m", (size_t) 2) == 0) {
+	argc--;
+	if ((argv[0])[2])
+		symbolic = (*argv++) + 2;
+	else {
+		if (!argc--) usage();
+		argv++;
+		symbolic = *argv++;
+	}
+	u_mask = umask(0);
+	umask(u_mask);
+  } else
+	symbolic = (char *) 0;
+
+  if (!argc) usage();
+  for (; argc--; argv++)
+	if (mkfifo(*argv, DEFAULT_MODE)) {
+		perror(*argv);
+		errors = 1;
+	} else if (symbolic && chmod(*argv, parsemode(symbolic, DEFAULT_MODE))) {
+		unlink(*argv);
+		perror(*argv);
+		errors = 1;
+	}
+  return(errors);
+}
+
+
+/* Posix command prototype. */
+void usage()
+{
+  std_err("Usage: mkfifo [-m mode] file...\n");
+  exit(1);
+}
Index: /trunk/minix/commands/simple/mkfs.c
===================================================================
--- /trunk/minix/commands/simple/mkfs.c	(revision 9)
+++ /trunk/minix/commands/simple/mkfs.c	(revision 9)
@@ -0,0 +1,1593 @@
+/* mkfs  -  make the MINIX filesystem	Authors: Tanenbaum et al. */
+
+/*	Authors: Andy Tanenbaum, Paul Ogilvie, Frans Meulenbroeks, Bruce Evans
+ *
+ * This program can make both version 1 and version 2 file systems, as follows:
+ *	mkfs /dev/fd0 1200	# Version 2 (default)
+ *	mkfs -1 /dev/fd0 360	# Version 1
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/dir.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include <minix/minlib.h>
+#include "../../servers/fs/const.h"
+#if (MACHINE == IBM_PC)
+#include <minix/partition.h>
+#include <minix/u64.h>
+#include <sys/ioctl.h>
+#endif
+#include <a.out.h>
+#include <tools.h>
+#include <dirent.h>
+
+#undef EXTERN
+#define EXTERN			/* get rid of EXTERN by making it null */
+#include "../../servers/fs/type.h"
+#include "../../servers/fs/super.h"
+#include <minix/fslib.h>
+
+#ifndef max
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef DOS
+#ifndef UNIX
+#define UNIX
+#endif
+#endif
+
+#define INODE_MAP            2
+#define MAX_TOKENS          10
+#define LINE_LEN           200
+#define BIN                  2
+#define BINGRP               2
+#define BIT_MAP_SHIFT       13
+#define N_BLOCKS         MAX_BLOCK_NR
+#define N_BLOCKS16	  (128L * 1024)
+#define INODE_MAX       ((unsigned) 65535)
+
+/* You can make a really large file system on a 16-bit system, but the array
+ * of bits that get_block()/putblock() needs gets a bit big, so we can only
+ * prefill MAX_INIT blocks.  (16-bit fsck can't check a file system larger
+ * than N_BLOCKS16 anyway.)
+ */
+#define MAX_INIT	 (sizeof(char *) == 2 ? N_BLOCKS16 : N_BLOCKS)
+
+
+#ifdef DOS
+maybedefine O_RDONLY 4		/* O_RDONLY | BINARY_BIT */
+ maybedefine BWRITE 5		/* O_WRONLY | BINARY_BIT */
+#endif
+
+#if (MACHINE == ATARI)
+int isdev;
+#endif
+
+extern char *optarg;
+extern int optind;
+
+int next_zone, next_inode, zone_size, zone_shift = 0, zoff;
+block_t nrblocks;
+int inode_offset, lct = 0, disk, fd, print = 0, file = 0;
+unsigned int nrinodes;
+int override = 0, simple = 0, dflag;
+int donttest;			/* skip test if it fits on medium */
+char *progname;
+
+long current_time, bin_time;
+char *zero, *lastp;
+char umap[MAX_INIT / 8];	/* bit map tells if block read yet */
+block_t zone_map;		/* where is zone map? (depends on # inodes) */
+int inodes_per_block;
+int fs_version;
+unsigned int block_size;
+block_t max_nrblocks;
+
+FILE *proto;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(block_t sizeup, (char *device));
+_PROTOTYPE(void super, (zone_t zones, Ino_t inodes));
+_PROTOTYPE(void rootdir, (Ino_t inode));
+_PROTOTYPE(void eat_dir, (Ino_t parent));
+_PROTOTYPE(void eat_file, (Ino_t inode, int f));
+_PROTOTYPE(void enter_dir, (Ino_t parent, char *name, Ino_t child));
+_PROTOTYPE(void incr_size, (Ino_t n, long count));
+_PROTOTYPE(PRIVATE ino_t alloc_inode, (int mode, int usrid, int grpid));
+_PROTOTYPE(PRIVATE zone_t alloc_zone, (void));
+_PROTOTYPE(void add_zone, (Ino_t n, zone_t z, long bytes, long cur_time));
+_PROTOTYPE(void add_z_1, (Ino_t n, zone_t z, long bytes, long cur_time));
+_PROTOTYPE(void add_z_2, (Ino_t n, zone_t z, long bytes, long cur_time));
+_PROTOTYPE(void incr_link, (Ino_t n));
+_PROTOTYPE(void insert_bit, (block_t block, int bit));
+_PROTOTYPE(int mode_con, (char *p));
+_PROTOTYPE(void getline, (char line[LINE_LEN], char *parse[MAX_TOKENS]));
+_PROTOTYPE(void check_mtab, (char *devname));
+_PROTOTYPE(long file_time, (int f));
+_PROTOTYPE(void pexit, (char *s));
+_PROTOTYPE(void copy, (char *from, char *to, int count));
+_PROTOTYPE(void print_fs, (void));
+_PROTOTYPE(int read_and_set, (block_t n));
+_PROTOTYPE(void special, (char *string));
+_PROTOTYPE(void get_block, (block_t n, char *buf));
+_PROTOTYPE(void get_super_block, (char *buf));
+_PROTOTYPE(void put_block, (block_t n, char *buf));
+_PROTOTYPE(void cache_init, (void));
+_PROTOTYPE(void flush, (void));
+_PROTOTYPE(void mx_read, (int blocknr, char *buf));
+_PROTOTYPE(void mx_write, (int blocknr, char *buf));
+_PROTOTYPE(void dexit, (char *s, int sectnum, int err));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(char *alloc_block, (void));
+
+/*================================================================
+ *                    mkfs  -  make filesystem
+ *===============================================================*/
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int nread, mode, usrid, grpid, ch;
+  block_t blocks, maxblocks;
+  block_t i;
+  ino_t root_inum;
+  ino_t inodes;
+  zone_t zones;
+  char *token[MAX_TOKENS], line[LINE_LEN];
+  struct stat statbuf;
+
+  /* Get two times, the current time and the mod time of the binary of
+   * mkfs itself.  When the -d flag is used, the later time is put into
+   * the i_mtimes of all the files.  This feature is useful when
+   * producing a set of file systems, and one wants all the times to be
+   * identical. First you set the time of the mkfs binary to what you
+   * want, then go.
+   */
+  current_time = time((time_t *) 0);	/* time mkfs is being run */
+  stat(argv[0], &statbuf);
+  bin_time = statbuf.st_mtime;	/* time when mkfs binary was last modified */
+
+  /* Process switches. */
+  progname = argv[0];
+  blocks = 0;
+  i = 0;
+  fs_version = 3;
+  inodes_per_block = 0;
+  max_nrblocks = N_BLOCKS;
+  block_size = 0;
+  while ((ch = getopt(argc, argv, "12b:di:lotB:")) != EOF)
+	switch (ch) {
+	    case '1':
+		fs_version = 1;
+		inodes_per_block = V1_INODES_PER_BLOCK;
+		max_nrblocks = 0xFFFF;
+		break;
+	    case '2':
+	    	fs_version = 2;
+	    	break;
+	    case 'b':
+		blocks = strtoul(optarg, (char **) NULL, 0);
+		break;
+	    case 'd':
+		dflag = 1;
+		current_time = bin_time;
+		break;
+	    case 'i':
+		i = strtoul(optarg, (char **) NULL, 0);
+		break;
+	    case 'l':	print = 1;	break;
+	    case 'o':	override = 1;	break;
+	    case 't':	donttest = 1;	break;
+	    case 'B':	block_size = atoi(optarg);	break;
+	    default:	usage();
+	}
+
+  if(fs_version == 3) {
+  	if(!block_size) block_size = _MAX_BLOCK_SIZE; /* V3 default block size */
+  	if(block_size%SECTOR_SIZE || block_size < _MIN_BLOCK_SIZE) {
+  		fprintf(stderr, "block size must be multiple of sector (%d) "
+  			"and at least %d bytes\n",
+  			SECTOR_SIZE, _MIN_BLOCK_SIZE);
+  		pexit("specified block size illegal");
+  	}
+  	if(block_size%V2_INODE_SIZE) {
+  		fprintf(stderr, "block size must be a multiple of inode size (%d bytes)\n",
+  			V2_INODE_SIZE);
+  		pexit("specified block size illegal");
+  	}
+  } else {
+  	if(block_size) {
+	  	pexit("Can't specify a block size if FS version is <3");
+  	}
+ 	block_size = _STATIC_BLOCK_SIZE;	/* V1/V2 block size */
+  }
+
+  if(!inodes_per_block)
+  	inodes_per_block = V2_INODES_PER_BLOCK(block_size);
+
+  /* now that the block size is known, do buffer allocations where
+   * possible.
+   */
+  zero = alloc_block();
+  bzero(zero, block_size);
+
+  /* Determine the size of the device if not specified as -b or proto. */
+  maxblocks = sizeup(argv[optind]);
+  if (argc - optind == 1 && blocks == 0) {
+  	blocks = maxblocks;
+  	/* blocks == 0 is checked later, but leads to a funny way of
+  	 * reporting a 0-sized device (displays usage).
+  	 */
+  	if(blocks < 1) {
+  		fprintf(stderr, "%s: this device can't hold a filesystem.\n",
+  			progname);
+  		return 1;
+  	}
+  }
+
+  /* The remaining args must be 'special proto', or just 'special' if the
+   * no. of blocks has already been specified.
+   */
+  if (argc - optind != 2 && (argc - optind != 1 || blocks == 0)) usage();
+
+  if (blocks > maxblocks) {
+ 	fprintf(stderr, "%s: %s: number of blocks too large for device.\n",
+  		progname, argv[optind]);
+  	return 1;
+  }
+
+  /* Check special. */
+  check_mtab(argv[optind]);
+
+  /* Check and start processing proto. */
+  optarg = argv[++optind];
+  if (optind < argc && (proto = fopen(optarg, "r")) != NULL) {
+	/* Prototype file is readable. */
+	lct = 1;
+	getline(line, token);	/* skip boot block info */
+
+	/* Read the line with the block and inode counts. */
+	getline(line, token);
+	blocks = atol(token[0]);
+	if (blocks > max_nrblocks) pexit("Block count too large");
+	if (sizeof(char *) == 2 && blocks > N_BLOCKS16) {
+		fprintf(stderr,
+		"%s: warning: FS is larger than the %dM that fsck can check!\n",
+			progname, (int) (N_BLOCKS16 / (1024L * 1024)));
+	}
+	inodes = atoi(token[1]);
+
+	/* Process mode line for root directory. */
+	getline(line, token);
+	mode = mode_con(token[0]);
+	usrid = atoi(token[1]);
+	grpid = atoi(token[2]);
+  } else {
+	lct = 0;
+	if (optind < argc) {
+		/* Maybe the prototype file is just a size.  Check. */
+		blocks = strtoul(optarg, (char **) NULL, 0);
+		if (blocks == 0) pexit("Can't open prototype file");
+	}
+	if (i == 0) {
+		int kb;
+		kb = blocks * (max(block_size,1024) / 1024);
+		/* The default for inodes is 2 blocks per kb, rounded up
+		 * to fill an inode block.  Above 20M, the average files are
+		 * sure to be larger because it is hard to fill up 20M with
+		 * tiny files, so reduce the default number of inodes.  This
+		 * default can always be overridden by using the '-i option.
+		 */
+		i = kb / 2;
+		if (kb >= 20000) i = kb / 3;
+		if (kb >= 40000) i = kb / 4;
+		if (kb >= 60000) i = kb / 5;
+		if (kb >= 80000) i = kb / 6;
+		if (kb >= 100000) i = kb / 7;
+
+		/* round up to fill inode block */
+		i += inodes_per_block - 1;
+		i = i / inodes_per_block * inodes_per_block;
+		if (i > INODE_MAX && fs_version < 3) i = INODE_MAX;
+
+	}
+	if (blocks < 5) pexit("Block count too small");
+	if (blocks > max_nrblocks) pexit("Block count too large");
+	if (i < 1) pexit("Inode count too small");
+	if (i > INODE_MAX && fs_version < 3) pexit("Inode count too large");
+	inodes = (ino_t) i;
+
+	/* Make simple file system of the given size, using defaults. */
+	mode = 040777;
+	usrid = BIN;
+	grpid = BINGRP;
+	simple = 1;
+  }
+
+  if(ULONG_MAX / block_size <= blocks-1) {
+  	fprintf(stderr, "Warning: too big for filesystem to currently\n");
+  	fprintf(stderr, "run on (max 4GB), truncating.\n");
+  	blocks = ULONG_MAX / block_size;
+  }
+
+  nrblocks = blocks;
+  nrinodes = inodes;
+
+  /* Open special. */
+  special(argv[--optind]);
+
+#ifdef UNIX
+  if (!donttest) {
+	short *testb;
+	ssize_t w;
+
+	testb = (short *) alloc_block();
+
+	/* Try writing the last block of partition or diskette. */
+	if(lseek(fd, (off_t) (blocks - 1) * block_size, SEEK_SET) < 0) {
+		pexit("couldn't seek to last block to test size (1)");
+	}
+	testb[0] = 0x3245;
+	testb[1] = 0x11FF;
+	testb[block_size-1] = 0x1F2F;
+	if ((w=write(fd, (char *) testb, block_size)) != block_size) {
+		if(w < 0) perror("write");
+		printf("%d/%d\n", w, block_size);
+		pexit("File system is too big for minor device (write)");
+	}
+	sync();			/* flush write, so if error next read fails */
+	if(lseek(fd, (off_t) (blocks - 1) * block_size, SEEK_SET) < 0) {
+		pexit("couldn't seek to last block to test size (2)");
+	}
+	testb[0] = 0;
+	testb[1] = 0;
+	nread = read(fd, (char *) testb, block_size);
+	if (nread != block_size || testb[0] != 0x3245 || testb[1] != 0x11FF ||
+		testb[block_size-1] != 0x1F2F) {
+		if(nread < 0) perror("read");
+		pexit("File system is too big for minor device (read)");
+	}
+	lseek(fd, (off_t) (blocks - 1) * block_size, SEEK_SET);
+	testb[0] = 0;
+	testb[1] = 0;
+	if (write(fd, (char *) testb, block_size) != block_size)
+		pexit("File system is too big for minor device (write2)");
+	lseek(fd, 0L, SEEK_SET);
+	free(testb);
+  }
+#endif
+
+  /* Make the file-system */
+
+  cache_init();
+
+#if (MACHINE == ATARI)
+  if (isdev) {
+	char block0[BLOCK_SIZE];
+	get_block((block_t) 0, block0);
+	/* Need to read twice; first time gets an empty block */
+	get_block((block_t) 0, block0);
+	/* Zero parts of the boot block so the disk won't be
+	 * recognized as a tos disk any more. */
+	block0[0] = block0[1] = 0;	/* branch code to boot code    */
+	strncpy(&block0[2], "MINIX ", (size_t) 6);
+	block0[16] = 0;		/* number of FATS              */
+	block0[17] = block0[18] = 0;	/* number of dir entries       */
+	block0[22] = block0[23] = 0;	/* sectors/FAT                 */
+	bzero(&block0[30], 480);/* boot code                   */
+	put_block((block_t) 0, block0);
+  } else
+#endif
+
+	put_block((block_t) 0, zero);	/* Write a null boot block. */
+
+  zone_shift = 0;		/* for future use */
+  zones = nrblocks >> zone_shift;
+
+  super(zones, inodes);
+
+  root_inum = alloc_inode(mode, usrid, grpid);
+  rootdir(root_inum);
+  if (simple == 0) eat_dir(root_inum);
+
+  if (print) print_fs();
+  flush();
+  return(0);
+
+  /* NOTREACHED */
+}				/* end main */
+
+
+/*================================================================
+ *                    sizeup  -  determine device size
+ *===============================================================*/
+block_t sizeup(device)
+char *device;
+{
+  int fd;
+  struct partition entry;
+  block_t d;
+  struct stat st;
+
+  if ((fd = open(device, O_RDONLY)) == -1) {
+	if (errno != ENOENT)
+		perror("sizeup open");
+  	return 0;
+  }
+  if (ioctl(fd, DIOCGETP, &entry) == -1) {
+  	perror("sizeup ioctl");
+  	if(fstat(fd, &st) < 0) {
+  		perror("fstat");
+	  	entry.size = cvu64(0);
+  	} else {
+  		fprintf(stderr, "used fstat instead\n");
+	  	entry.size = cvu64(st.st_size);
+  	}
+  }
+  close(fd);
+  d = div64u(entry.size, block_size);
+  return d;
+}
+
+
+/*================================================================
+ *                 super  -  construct a superblock
+ *===============================================================*/
+
+void super(zones, inodes)
+zone_t zones;
+ino_t inodes;
+{
+  unsigned int i;
+  int inodeblks;
+  int initblks;
+
+  zone_t initzones, nrzones, v1sq, v2sq;
+  zone_t zo;
+  struct super_block *sup;
+  char *buf, *cp;
+
+  buf = alloc_block();
+
+  for (cp = buf; cp < &buf[block_size]; cp++) *cp = 0;
+  sup = (struct super_block *) buf;	/* lint - might use a union */
+
+  sup->s_ninodes = inodes;
+  if (fs_version == 1) {
+	sup->s_nzones = zones;
+  } else {
+	sup->s_nzones = 0;	/* not used in V2 - 0 forces errors early */
+	sup->s_zones = zones;
+  }
+  sup->s_imap_blocks = bitmapsize((bit_t) (1 + inodes), block_size);
+  sup->s_zmap_blocks = bitmapsize((bit_t) zones, block_size);
+  inode_offset = sup->s_imap_blocks + sup->s_zmap_blocks + 2;
+  inodeblks = (inodes + inodes_per_block - 1) / inodes_per_block;
+  initblks = inode_offset + inodeblks;
+  initzones = (initblks + (1 << zone_shift) - 1) >> zone_shift;
+  nrzones = nrblocks >> zone_shift;
+  sup->s_firstdatazone = (initblks + (1 << zone_shift) - 1) >> zone_shift;
+  zoff = sup->s_firstdatazone - 1;
+  sup->s_log_zone_size = zone_shift;
+  if (fs_version == 1) {
+	sup->s_magic = SUPER_MAGIC;	/* identify super blocks */
+	v1sq = (zone_t) V1_INDIRECTS * V1_INDIRECTS;
+	zo = V1_NR_DZONES + (long) V1_INDIRECTS + v1sq;
+  	sup->s_max_size = zo * block_size;
+  } else {
+	v2sq = (zone_t) V2_INDIRECTS(block_size) * V2_INDIRECTS(block_size);
+	zo = V2_NR_DZONES + (zone_t) V2_INDIRECTS(block_size) + v2sq;
+  	if(fs_version == 2) {
+		sup->s_magic = SUPER_V2;/* identify super blocks */
+  		sup->s_max_size = zo * block_size;
+	} else {
+		sup->s_magic = SUPER_V3;
+  		sup->s_block_size = block_size;
+  		sup->s_disk_version = 0;
+#define MAX_MAX_SIZE 	((unsigned long) 0xffffffff)
+  		if(MAX_MAX_SIZE/block_size < zo) {
+	  		sup->s_max_size = MAX_MAX_SIZE;
+  		}
+	  	else {
+	  		sup->s_max_size = zo * block_size;
+	  	}
+	}
+  }
+
+  zone_size = 1 << zone_shift;	/* nr of blocks per zone */
+
+  if (lseek(fd, (off_t) _STATIC_BLOCK_SIZE, SEEK_SET) == (off_t) -1) {
+	pexit("super() couldn't seek");
+  }
+  if (write(fd, buf, _STATIC_BLOCK_SIZE) != _STATIC_BLOCK_SIZE) {
+	pexit("super() couldn't write");
+  }
+
+  /* Clear maps and inodes. */
+  for (i = 2; i < initblks; i++) put_block((block_t) i, zero);
+
+  next_zone = sup->s_firstdatazone;
+  next_inode = 1;
+
+  zone_map = INODE_MAP + sup->s_imap_blocks;
+
+  insert_bit(zone_map, 0);	/* bit zero must always be allocated */
+  insert_bit((block_t) INODE_MAP, 0);	/* inode zero not used but
+					 * must be allocated */
+
+  free(buf);
+}
+
+
+/*================================================================
+ *              rootdir  -  install the root directory
+ *===============================================================*/
+void rootdir(inode)
+ino_t inode;
+{
+  zone_t z;
+
+  z = alloc_zone();
+  add_zone(inode, z, 2 * sizeof(struct direct), current_time);
+  enter_dir(inode, ".", inode);
+  enter_dir(inode, "..", inode);
+  incr_link(inode);
+  incr_link(inode);
+}
+
+
+/*================================================================
+ *	    eat_dir  -  recursively install directory
+ *===============================================================*/
+void eat_dir(parent)
+ino_t parent;
+{
+  /* Read prototype lines and set up directory. Recurse if need be. */
+  char *token[MAX_TOKENS], *p;
+  char line[LINE_LEN];
+  int mode, usrid, grpid, maj, min, f;
+  ino_t n;
+  zone_t z;
+  long size;
+
+  while (1) {
+	getline(line, token);
+	p = token[0];
+	if (*p == '$') return;
+	p = token[1];
+	mode = mode_con(p);
+	usrid = atoi(token[2]);
+	grpid = atoi(token[3]);
+	if (grpid & 0200) fprintf(stderr, "A.S.Tanenbaum\n");
+	n = alloc_inode(mode, usrid, grpid);
+
+	/* Enter name in directory and update directory's size. */
+	enter_dir(parent, token[0], n);
+	incr_size(parent, sizeof(struct direct));
+
+	/* Check to see if file is directory or special. */
+	incr_link(n);
+	if (*p == 'd') {
+		/* This is a directory. */
+		z = alloc_zone();	/* zone for new directory */
+		add_zone(n, z, 2 * sizeof(struct direct), current_time);
+		enter_dir(n, ".", n);
+		enter_dir(n, "..", parent);
+		incr_link(parent);
+		incr_link(n);
+		eat_dir(n);
+	} else if (*p == 'b' || *p == 'c') {
+		/* Special file. */
+		maj = atoi(token[4]);
+		min = atoi(token[5]);
+		size = 0;
+		if (token[6]) size = atoi(token[6]);
+		size = block_size * size;
+		add_zone(n, (zone_t) ((maj << 8) | min), size, current_time);
+	} else {
+		/* Regular file. Go read it. */
+		if ((f = open(token[4], O_RDONLY)) < 0) {
+			fprintf(stderr, "%s: Can't open %s: %s\n",
+				progname, token[4], strerror(errno));
+		} else {
+			eat_file(n, f);
+		}
+	}
+  }
+
+}
+
+/*================================================================
+ * 		eat_file  -  copy file to MINIX
+ *===============================================================*/
+/* Zonesize >= blocksize */
+void eat_file(inode, f)
+ino_t inode;
+int f;
+{
+  int ct, i, j, k;
+  zone_t z;
+  char *buf;
+  long timeval;
+
+  buf = alloc_block();
+
+  do {
+	for (i = 0, j = 0; i < zone_size; i++, j += ct) {
+		for (k = 0; k < block_size; k++) buf[k] = 0;
+		if ((ct = read(f, buf, block_size)) > 0) {
+			if (i == 0) z = alloc_zone();
+			put_block((z << zone_shift) + i, buf);
+		}
+	}
+	timeval = (dflag ? current_time : file_time(f));
+	if (ct) add_zone(inode, z, (long) j, timeval);
+  } while (ct == block_size);
+  close(f);
+}
+
+
+
+/*================================================================
+ *	    directory & inode management assist group
+ *===============================================================*/
+void enter_dir(parent, name, child)
+ino_t parent, child;
+char *name;
+{
+  /* Enter child in parent directory */
+  /* Works for dir > 1 block and zone > block */
+  int i, j, k, l, off;
+  block_t b;
+  zone_t z;
+  char *p1, *p2;
+  struct direct *dir_entry;
+  d1_inode ino1[V1_INODES_PER_BLOCK];
+  d2_inode *ino2;
+  int nr_dzones;
+
+  b = ((parent - 1) / inodes_per_block) + inode_offset;
+  off = (parent - 1) % inodes_per_block;
+
+  if(!(dir_entry = malloc(NR_DIR_ENTRIES(block_size) * sizeof(*dir_entry))))
+  	pexit("couldn't allocate directory entry");
+
+  if(!(ino2 = malloc(V2_INODES_PER_BLOCK(block_size) * sizeof(*ino2))))
+  	pexit("couldn't allocate block of inodes entry");
+
+  if (fs_version == 1) {
+	get_block(b, (char *) ino1);
+	nr_dzones = V1_NR_DZONES;
+  } else {
+	get_block(b, (char *) ino2);
+	nr_dzones = V2_NR_DZONES;
+  }
+  for (k = 0; k < nr_dzones; k++) {
+	if (fs_version == 1) {
+		z = ino1[off].d1_zone[k];
+		if (z == 0) {
+			z = alloc_zone();
+			ino1[off].d1_zone[k] = z;
+		}
+	} else {
+		z = ino2[off].d2_zone[k];
+		if (z == 0) {
+			z = alloc_zone();
+			ino2[off].d2_zone[k] = z;
+		}
+	}
+	for (l = 0; l < zone_size; l++) {
+		get_block((z << zone_shift) + l, (char *) dir_entry);
+		for (i = 0; i < NR_DIR_ENTRIES(block_size); i++) {
+			if (dir_entry[i].d_ino == 0) {
+				dir_entry[i].d_ino = child;
+				p1 = name;
+				p2 = dir_entry[i].d_name;
+				j = sizeof(dir_entry[i].d_name);
+				while (j--) {
+					*p2++ = *p1;
+					if (*p1 != 0) p1++;
+				}
+				put_block((z << zone_shift) + l, (char *) dir_entry);
+				if (fs_version == 1) {
+					put_block(b, (char *) ino1);
+				} else {
+					put_block(b, (char *) ino2);
+				}
+				free(dir_entry);
+				free(ino2);
+				return;
+			}
+		}
+	}
+  }
+
+  printf("Directory-inode %d beyond direct blocks.  Could not enter %s\n",
+         parent, name);
+  pexit("Halt");
+}
+
+
+void add_zone(n, z, bytes, cur_time)
+ino_t n;
+zone_t z;
+long bytes, cur_time;
+{
+  if (fs_version == 1) {
+	add_z_1(n, z, bytes, cur_time);
+  } else {
+	add_z_2(n, z, bytes, cur_time);
+  }
+}
+
+void add_z_1(n, z, bytes, cur_time)
+ino_t n;
+zone_t z;
+long bytes, cur_time;
+{
+  /* Add zone z to inode n. The file has grown by 'bytes' bytes. */
+
+  int off, i;
+  block_t b;
+  zone_t indir;
+  zone1_t blk[V1_INDIRECTS];
+  d1_inode *p;
+  d1_inode inode[V1_INODES_PER_BLOCK];
+
+  b = ((n - 1) / V1_INODES_PER_BLOCK) + inode_offset;
+  off = (n - 1) % V1_INODES_PER_BLOCK;
+  get_block(b, (char *) inode);
+  p = &inode[off];
+  p->d1_size += bytes;
+  p->d1_mtime = cur_time;
+  for (i = 0; i < V1_NR_DZONES; i++)
+	if (p->d1_zone[i] == 0) {
+		p->d1_zone[i] = (zone1_t) z;
+		put_block(b, (char *) inode);
+		return;
+	}
+  put_block(b, (char *) inode);
+
+  /* File has grown beyond a small file. */
+  if (p->d1_zone[V1_NR_DZONES] == 0)
+	p->d1_zone[V1_NR_DZONES] = (zone1_t) alloc_zone();
+  indir = p->d1_zone[V1_NR_DZONES];
+  put_block(b, (char *) inode);
+  b = indir << zone_shift;
+  get_block(b, (char *) blk);
+  for (i = 0; i < V1_INDIRECTS; i++)
+	if (blk[i] == 0) {
+		blk[i] = (zone1_t) z;
+		put_block(b, (char *) blk);
+		return;
+	}
+  pexit("File has grown beyond single indirect");
+}
+
+void add_z_2(n, z, bytes, cur_time)
+ino_t n;
+zone_t z;
+long bytes, cur_time;
+{
+  /* Add zone z to inode n. The file has grown by 'bytes' bytes. */
+
+  int off, i;
+  block_t b;
+  zone_t indir;
+  zone_t *blk;
+  d2_inode *p;
+  d2_inode *inode;
+
+  if(!(blk = malloc(V2_INDIRECTS(block_size)*sizeof(*blk))))
+  	pexit("Couldn't allocate indirect block");
+
+  if(!(inode = malloc(V2_INODES_PER_BLOCK(block_size)*sizeof(*inode))))
+  	pexit("Couldn't allocate block of inodes");
+
+  b = ((n - 1) / V2_INODES_PER_BLOCK(block_size)) + inode_offset;
+  off = (n - 1) % V2_INODES_PER_BLOCK(block_size);
+  get_block(b, (char *) inode);
+  p = &inode[off];
+  p->d2_size += bytes;
+  p->d2_mtime = cur_time;
+  for (i = 0; i < V2_NR_DZONES; i++)
+	if (p->d2_zone[i] == 0) {
+		p->d2_zone[i] = z;
+		put_block(b, (char *) inode);
+  		free(blk);
+  		free(inode);
+		return;
+	}
+  put_block(b, (char *) inode);
+
+  /* File has grown beyond a small file. */
+  if (p->d2_zone[V2_NR_DZONES] == 0) p->d2_zone[V2_NR_DZONES] = alloc_zone();
+  indir = p->d2_zone[V2_NR_DZONES];
+  put_block(b, (char *) inode);
+  b = indir << zone_shift;
+  get_block(b, (char *) blk);
+  for (i = 0; i < V2_INDIRECTS(block_size); i++)
+	if (blk[i] == 0) {
+		blk[i] = z;
+		put_block(b, (char *) blk);
+  		free(blk);
+  		free(inode);
+		return;
+	}
+  pexit("File has grown beyond single indirect");
+}
+
+
+void incr_link(n)
+ino_t n;
+{
+  /* Increment the link count to inode n */
+  int off;
+  static int enter = 0;
+  block_t b;
+
+  if(enter) exit(1);
+
+  b = ((n - 1) / inodes_per_block) + inode_offset;
+  off = (n - 1) % inodes_per_block;
+  if (fs_version == 1) {
+	d1_inode inode1[V1_INODES_PER_BLOCK];
+
+	get_block(b, (char *) inode1);
+	inode1[off].d1_nlinks++;
+	put_block(b, (char *) inode1);
+  } else {
+	static d2_inode *inode2 = NULL;
+	int n;
+
+	n = sizeof(*inode2) * V2_INODES_PER_BLOCK(block_size);
+	if(!inode2 && !(inode2 = malloc(n)))
+		pexit("couldn't allocate a block of inodes");
+
+	get_block(b, (char *) inode2);
+	inode2[off].d2_nlinks++;
+	put_block(b, (char *) inode2);
+  }
+  enter = 0;
+}
+
+
+void incr_size(n, count)
+ino_t n;
+long count;
+{
+  /* Increment the file-size in inode n */
+  block_t b;
+  int off;
+
+  b = ((n - 1) / inodes_per_block) + inode_offset;
+  off = (n - 1) % inodes_per_block;
+  if (fs_version == 1) {
+	d1_inode inode1[V1_INODES_PER_BLOCK];
+
+	get_block(b, (char *) inode1);
+	inode1[off].d1_size += count;
+	put_block(b, (char *) inode1);
+  } else {
+	d2_inode *inode2;
+	if(!(inode2 = malloc(V2_INODES_PER_BLOCK(block_size) * sizeof(*inode2))))
+		pexit("couldn't allocate a block of inodes");
+
+	get_block(b, (char *) inode2);
+	inode2[off].d2_size += count;
+	put_block(b, (char *) inode2);
+	free(inode2);
+  }
+}
+
+
+/*================================================================
+ * 	 	     allocation assist group
+ *===============================================================*/
+PRIVATE ino_t alloc_inode(mode, usrid, grpid)
+int mode, usrid, grpid;
+{
+  ino_t num;
+  int off;
+  block_t b;
+
+  num = next_inode++;
+  if (num > nrinodes) {
+  	fprintf(stderr, "have %d inodoes\n", nrinodes);
+  	pexit("File system does not have enough inodes");
+  }
+  b = ((num - 1) / inodes_per_block) + inode_offset;
+  off = (num - 1) % inodes_per_block;
+  if (fs_version == 1) {
+	d1_inode inode1[V1_INODES_PER_BLOCK];
+
+	get_block(b, (char *) inode1);
+	inode1[off].d1_mode = mode;
+	inode1[off].d1_uid = usrid;
+	inode1[off].d1_gid = grpid;
+	put_block(b, (char *) inode1);
+  } else {
+	d2_inode *inode2;
+
+	if(!(inode2 = malloc(V2_INODES_PER_BLOCK(block_size) * sizeof(*inode2))))
+		pexit("couldn't allocate a block of inodes");
+
+	get_block(b, (char *) inode2);
+	inode2[off].d2_mode = mode;
+	inode2[off].d2_uid = usrid;
+	inode2[off].d2_gid = grpid;
+	put_block(b, (char *) inode2);
+
+	free(inode2);
+  }
+
+  /* Set the bit in the bit map. */
+  /* DEBUG FIXME.  This assumes the bit is in the first inode map block. */
+  insert_bit((block_t) INODE_MAP, (int) num);
+  return(num);
+}
+
+
+PRIVATE zone_t alloc_zone()
+{
+  /* Allocate a new zone */
+  /* Works for zone > block */
+  block_t b;
+  int i;
+  zone_t z;
+
+  z = next_zone++;
+  b = z << zone_shift;
+  if ((b + zone_size) > nrblocks)
+	pexit("File system not big enough for all the files");
+  for (i = 0; i < zone_size; i++)
+	put_block(b + i, zero);	/* give an empty zone */
+  /* DEBUG FIXME.  This assumes the bit is in the first zone map block. */
+  insert_bit(zone_map, (int) (z - zoff));	/* lint, NOT OK because
+						 * z hasn't been broken
+						 * up into block +
+						 * offset yet. */
+  return(z);
+}
+
+
+void insert_bit(block, bit)
+block_t block;
+int bit;
+{
+  /* Insert 'count' bits in the bitmap */
+  int w, s;
+  short *buf;
+
+  buf = (short *) alloc_block();
+
+  if (block < 0) pexit("insert_bit called with negative argument");
+  get_block(block, (char *) buf);
+  w = bit / (8 * sizeof(short));
+  s = bit % (8 * sizeof(short));
+  buf[w] |= (1 << s);
+  put_block(block, (char *) buf);
+
+  free(buf);
+}
+
+
+/*================================================================
+ * 		proto-file processing assist group
+ *===============================================================*/
+int mode_con(p)
+char *p;
+{
+  /* Convert string to mode */
+  int o1, o2, o3, mode;
+  char c1, c2, c3;
+
+  c1 = *p++;
+  c2 = *p++;
+  c3 = *p++;
+  o1 = *p++ - '0';
+  o2 = *p++ - '0';
+  o3 = *p++ - '0';
+  mode = (o1 << 6) | (o2 << 3) | o3;
+  if (c1 == 'd') mode += I_DIRECTORY;
+  if (c1 == 'b') mode += I_BLOCK_SPECIAL;
+  if (c1 == 'c') mode += I_CHAR_SPECIAL;
+  if (c1 == '-') mode += I_REGULAR;
+  if (c2 == 'u') mode += I_SET_UID_BIT;
+  if (c3 == 'g') mode += I_SET_GID_BIT;
+  return(mode);
+}
+
+void getline(line, parse)
+char *parse[MAX_TOKENS];
+char line[LINE_LEN];
+{
+  /* Read a line and break it up in tokens */
+  int k;
+  char c, *p;
+  int d;
+
+  for (k = 0; k < MAX_TOKENS; k++) parse[k] = 0;
+  for (k = 0; k < LINE_LEN; k++) line[k] = 0;
+  k = 0;
+  parse[0] = 0;
+  p = line;
+  while (1) {
+	if (++k > LINE_LEN) pexit("Line too long");
+	d = fgetc(proto);
+	if (d == EOF) pexit("Unexpected end-of-file");
+	*p = d;
+	if (*p == '\n') lct++;
+	if (*p == ' ' || *p == '\t') *p = 0;
+	if (*p == '\n') {
+		*p++ = 0;
+		*p = '\n';
+		break;
+	}
+	p++;
+  }
+
+  k = 0;
+  p = line;
+  lastp = line;
+  while (1) {
+	c = *p++;
+	if (c == '\n') return;
+	if (c == 0) continue;
+	parse[k++] = p - 1;
+	do {
+		c = *p++;
+	} while (c != 0 && c != '\n');
+  }
+}
+
+
+/*================================================================
+ *			other stuff
+ *===============================================================*/
+void check_mtab(devname)
+char *devname;			/* /dev/hd1 or whatever */
+{
+/* Check to see if the special file named in s is mounted. */
+
+  int n, r;
+  struct stat sb;
+  char special[PATH_MAX + 1], mounted_on[PATH_MAX + 1], version[10], rw_flag[10];
+
+  r= stat(devname, &sb);
+  if (r == -1)
+  {
+	if (errno == ENOENT)
+		return;	/* Does not exist, and therefore not mounted. */
+	fprintf(stderr, "%s: stat %s failed: %s\n",
+		progname, devname, strerror(errno));
+	exit(1);
+  }
+  if (!S_ISBLK(sb.st_mode))
+  {
+	/* Not a block device and therefore not mounted. */
+	return;
+  }
+
+  if (load_mtab("mkfs") < 0) return;
+  while (1) {
+	n = get_mtab_entry(special, mounted_on, version, rw_flag);
+	if (n < 0) return;
+	if (strcmp(devname, special) == 0) {
+		/* Can't mkfs on top of a mounted file system. */
+		fprintf(stderr, "%s: %s is mounted on %s\n",
+			progname, devname, mounted_on);
+		exit(1);
+	}
+  }
+}
+
+
+long file_time(f)
+int f;
+{
+#ifdef UNIX
+  struct stat statbuf;
+  fstat(f, &statbuf);
+  return(statbuf.st_mtime);
+#else				/* fstat not supported by DOS */
+  return(0L);
+#endif
+}
+
+
+void pexit(s)
+char *s;
+{
+  fprintf(stderr, "%s: %s\n", progname, s);
+  if (lct != 0)
+	fprintf(stderr, "Line %d being processed when error detected.\n", lct);
+  flush();
+  exit(2);
+}
+
+
+void copy(from, to, count)
+char *from, *to;
+int count;
+{
+  while (count--) *to++ = *from++;
+}
+
+char *alloc_block()
+{
+	char *buf;
+
+	if(!(buf = malloc(block_size))) {
+		pexit("couldn't allocate filesystem buffer");
+	}
+  	bzero(buf, block_size);
+
+	return buf;
+}
+
+void print_fs()
+{
+  int i, j;
+  ino_t k;
+  d1_inode inode1[V1_INODES_PER_BLOCK];
+  d2_inode *inode2;
+  unsigned short *usbuf;
+  block_t b, inode_limit;
+  struct direct *dir;
+
+  if(!(inode2 = malloc(V2_INODES_PER_BLOCK(block_size) * sizeof(*inode2))))
+	pexit("couldn't allocate a block of inodes");
+
+  if(!(dir = malloc(NR_DIR_ENTRIES(block_size)*sizeof(*dir))))
+  	pexit("malloc of directory entry failed");
+
+  usbuf = (unsigned short *) alloc_block();
+
+  get_super_block((char *) usbuf);
+  printf("\nSuperblock: ");
+  for (i = 0; i < 8; i++) printf("%06o ", usbuf[i]);
+  get_block((block_t) 2, (char *) usbuf);
+  printf("...\nInode map:  ");
+  for (i = 0; i < 9; i++) printf("%06o ", usbuf[i]);
+  get_block((block_t) 3, (char *) usbuf);
+  printf("...\nZone  map:  ");
+  for (i = 0; i < 9; i++) printf("%06o ", usbuf[i]);
+  printf("...\n");
+
+  free(usbuf);
+  usbuf = NULL;
+
+  k = 0;
+  for (b = inode_offset; k < nrinodes; b++) {
+	if (fs_version == 1) {
+		get_block(b, (char *) inode1);
+	} else {
+		get_block(b, (char *) inode2);
+	}
+	for (i = 0; i < inodes_per_block; i++) {
+		k = inodes_per_block * (int) (b - inode_offset) + i + 1;
+		/* Lint but OK */
+		if (k > nrinodes) break;
+		if (fs_version == 1) {
+			if (inode1[i].d1_mode != 0) {
+				printf("Inode %2d:  mode=", k);
+				printf("%06o", inode1[i].d1_mode);
+				printf("  uid=%2d  gid=%2d  size=",
+				inode1[i].d1_uid, inode1[i].d1_gid);
+				printf("%6ld", inode1[i].d1_size);
+				printf("  zone[0]=%d\n", inode1[i].d1_zone[0]);
+			}
+			if ((inode1[i].d1_mode & I_TYPE) == I_DIRECTORY) {
+				/* This is a directory */
+				get_block(inode1[i].d1_zone[0], (char *) dir);
+				for (j = 0; j < NR_DIR_ENTRIES(block_size); j++)
+					if (dir[j].d_ino)
+						printf("\tInode %2d: %s\n", dir[j].d_ino, dir[j].d_name);
+			}
+		} else {
+			if (inode2[i].d2_mode != 0) {
+				printf("Inode %2d:  mode=", k);
+				printf("%06o", inode2[i].d2_mode);
+				printf("  uid=%2d  gid=%2d  size=",
+				inode2[i].d2_uid, inode2[i].d2_gid);
+				printf("%6ld", inode2[i].d2_size);
+				printf("  zone[0]=%ld\n", inode2[i].d2_zone[0]);
+			}
+			if ((inode2[i].d2_mode & I_TYPE) == I_DIRECTORY) {
+				/* This is a directory */
+				get_block(inode2[i].d2_zone[0], (char *) dir);
+				for (j = 0; j < NR_DIR_ENTRIES(block_size); j++)
+					if (dir[j].d_ino)
+						printf("\tInode %2d: %s\n", dir[j].d_ino, dir[j].d_name);
+			}
+		}
+	}
+  }
+
+  printf("%d inodes used.     %d zones used.\n", next_inode - 1, next_zone);
+  free(dir);
+  free(inode2);
+}
+
+
+int read_and_set(n)
+block_t n;
+{
+/* The first time a block is read, it returns all 0s, unless there has
+ * been a write.  This routine checks to see if a block has been accessed.
+ */
+
+  int w, s, mask, r;
+
+  if (sizeof(char *) == 2 && n >= MAX_INIT) pexit("can't initialize past 128M");
+  w = n / 8;
+  s = n % 8;
+  mask = 1 << s;
+  r = (umap[w] & mask ? 1 : 0);
+  umap[w] |= mask;
+  return(r);
+}
+
+void usage()
+{
+  fprintf(stderr,
+	  "Usage: %s [-12dlot] [-b blocks] [-i inodes] [-B blocksize] special [proto]\n",
+	  progname);
+  exit(1);
+}
+
+/*================================================================
+ *		      get_block & put_block for MS-DOS
+ *===============================================================*/
+#ifdef DOS
+
+/*
+ *	These are the get_block and put_block routines
+ *	when compiling & running mkfs.c under MS-DOS.
+ *
+ *	It requires the (asembler) routines absread & abswrite
+ *	from the file diskio.asm. Since these routines just do
+ *	as they are told (read & write the sector specified),
+ *	a local cache is used to minimize the i/o-overhead for
+ *	frequently used blocks.
+ *
+ *	The global variable "file" determines whether the output
+ *	is to a disk-device or to a binary file.
+ */
+
+
+#define PH_SECTSIZE	   512	/* size of a physical disk-sector */
+
+
+char *derrtab[14] = {
+	     "no error",
+	     "disk is read-only",
+	     "unknown unit",
+	     "device not ready",
+	     "bad command",
+	     "data error",
+	     "internal error: bad request structure length",
+	     "seek error",
+	     "unknown media type",
+	     "sector not found",
+	     "printer out of paper (?)",
+	     "write fault",
+	     "read error",
+	     "general error"
+};
+
+#define	CACHE_SIZE	20	/* 20 block-buffers */
+
+
+struct cache {
+  char blockbuf[BLOCK_SIZE];
+  block_t blocknum;
+  int dirty;
+  int usecnt;
+} cache[CACHE_SIZE];
+
+
+void special(string)
+char *string;
+{
+
+  if (string[1] == ':' && string[2] == 0) {
+	/* Format: d: or d:fname */
+	disk = (string[0] & ~32) - 'A';
+	if (disk > 1 && !override)	/* safety precaution */
+		pexit("Bad drive specifier for special");
+  } else {
+	file = 1;
+	if ((fd = creat(string, BWRITE)) == 0)
+		pexit("Can't open special file");
+  }
+}
+
+void get_block(n, buf)
+block_t n;
+char *buf;
+{
+  /* Get a block to the user */
+  struct cache *bp, *fp;
+
+  /* First access returns a zero block */
+  if (read_and_set(n) == 0) {
+	copy(zero, buf, block_size);
+	return;
+  }
+
+  /* Look for block in cache */
+  fp = 0;
+  for (bp = cache; bp < &cache[CACHE_SIZE]; bp++) {
+	if (bp->blocknum == n) {
+		copy(bp, buf, block_size);
+		bp->usecnt++;
+		return;
+	}
+
+	/* Remember clean block */
+	if (bp->dirty == 0)
+		if (fp) {
+			if (fp->usecnt > bp->usecnt) fp = bp;
+		} else
+			fp = bp;
+  }
+
+  /* Block not in cache, get it */
+  if (!fp) {
+	/* No clean buf, flush one */
+	for (bp = cache, fp = cache; bp < &cache[CACHE_SIZE]; bp++)
+		if (fp->usecnt > bp->usecnt) fp = bp;
+	mx_write(fp->blocknum, fp);
+  }
+  mx_read(n, fp);
+  fp->dirty = 0;
+  fp->usecnt = 0;
+  fp->blocknum = n;
+  copy(fp, buf, block_size);
+}
+
+void put_block(n, buf)
+block_t n;
+char *buf;
+{   
+  /* Accept block from user */
+  struct cache *fp, *bp;
+
+  (void) read_and_set(n);
+
+  /* Look for block in cache */
+  fp = 0;
+  for (bp = cache; bp < &cache[CACHE_SIZE]; bp++) {
+	if (bp->blocknum == n) {
+		copy(buf, bp, block_size);
+		bp->dirty = 1;
+		return;
+	}
+
+	/* Remember clean block */
+	if (bp->dirty == 0)
+		if (fp) {
+			if (fp->usecnt > bp->usecnt) fp = bp;
+		} else
+			fp = bp;
+  }
+
+  /* Block not in cache */
+  if (!fp) {
+	/* No clean buf, flush one */
+	for (bp = cache, fp = cache; bp < &cache[CACHE_SIZE]; bp++)
+		if (fp->usecnt > bp->usecnt) fp = bp;
+	mx_write(fp->blocknum, fp);
+  }
+  fp->dirty = 1;
+  fp->usecnt = 1;
+  fp->blocknum = n;
+  copy(buf, fp, block_size);
+}
+
+void cache_init()
+{
+  struct cache *bp;
+  for (bp = cache; bp < &cache[CACHE_SIZE]; bp++) bp->blocknum = -1;
+}
+
+void flush()
+{
+  /* Flush all dirty blocks to disk */
+  struct cache *bp;
+
+  for (bp = cache; bp < &cache[CACHE_SIZE]; bp++)
+	if (bp->dirty) {
+		mx_write(bp->blocknum, bp);
+		bp->dirty = 0;
+	}
+}
+
+/*==================================================================
+ *			hard read & write etc.
+ *=================================================================*/
+#define MAX_RETRIES	5
+
+
+void mx_read(blocknr, buf)
+int blocknr;
+char *buf;
+{
+
+  /* Read the requested MINIX-block in core */
+  char (*bp)[PH_SECTSIZE];
+  int sectnum, retries, err;
+
+  if (file) {
+	lseek(fd, (off_t) blocknr * block_size, 0);
+	if (read(fd, buf, block_size) != block_size)
+		pexit("mx_read: error reading file");
+  } else {
+	sectnum = blocknr * (block_size / PH_SECTSIZE);
+	for (bp = buf; bp < &buf[block_size]; bp++) {
+		retries = MAX_RETRIES;
+		do
+			err = absread(disk, sectnum, bp);
+		while (err && --retries);
+
+		if (retries) {
+			sectnum++;
+		} else {
+			dexit("mx_read", sectnum, err);
+		}
+	}
+  }
+}
+
+void mx_write(blocknr, buf)
+int blocknr;
+char *buf;
+{
+  /* Write the MINIX-block to disk */
+  char (*bp)[PH_SECTSIZE];
+  int retries, sectnum, err;
+
+  if (file) {
+	lseek(fd, blocknr * block_size, 0);
+	if (write(fd, buf, block_size) != block_size) {
+		pexit("mx_write: error writing file");
+	}
+  } else {
+	sectnum = blocknr * (block_size / PH_SECTSIZE);
+	for (bp = buf; bp < &buf[block_size]; bp++) {
+		retries = MAX_RETRIES;
+		do {
+			err = abswrite(disk, sectnum, bp);
+		} while (err && --retries);
+
+		if (retries) {
+			sectnum++;
+		} else {
+			dexit("mx_write", sectnum, err);
+		}
+	}
+  }
+}
+
+
+void dexit(s, sectnum, err)
+int sectnum, err;
+char *s;
+{
+  printf("Error: %s, sector: %d, code: %d, meaning: %s\n",
+         s, sectnum, err, derrtab[err]);
+  exit(2);
+}
+
+#endif
+
+/*================================================================
+ *		      get_block & put_block for UNIX
+ *===============================================================*/
+#ifdef UNIX
+
+void special(string)
+char *string;
+{
+  fd = creat(string, 0777);
+  close(fd);
+  fd = open(string, O_RDWR);
+  if (fd < 0) pexit("Can't open special file");
+#if (MACHINE == ATARI)
+  {
+	struct stat statbuf;
+
+	if (fstat(fd, &statbuf) < 0) return;
+	isdev = (statbuf.st_mode & S_IFMT) == S_IFCHR
+		||
+		(statbuf.st_mode & S_IFMT) == S_IFBLK
+		;
+  }
+#endif
+}
+
+
+
+void get_block(n, buf)
+block_t n;
+char *buf;
+{
+/* Read a block. */
+
+  int k;
+
+  /* First access returns a zero block */
+  if (read_and_set(n) == 0) {
+	copy(zero, buf, block_size);
+	return;
+  }
+  lseek(fd, (off_t) n * block_size, SEEK_SET);
+  k = read(fd, buf, block_size);
+  if (k != block_size) {
+	pexit("get_block couldn't read");
+  }
+}
+
+void get_super_block(buf)
+char *buf;
+{
+/* Read a block. */
+
+  int k;
+
+  if(lseek(fd, (off_t) SUPER_BLOCK_BYTES, SEEK_SET) < 0) {
+  	perror("lseek");
+  	pexit("seek failed");
+  }
+  k = read(fd, buf, _STATIC_BLOCK_SIZE);
+  if (k != _STATIC_BLOCK_SIZE) {
+	pexit("get_super_block couldn't read");
+  }
+}
+
+void put_block(n, buf)
+block_t n;
+char *buf;
+{
+/* Write a block. */
+
+  (void) read_and_set(n);
+
+  /* XXX - check other lseeks too. */
+  if (lseek(fd, (off_t) n * block_size, SEEK_SET) == (off_t) -1) {
+	pexit("put_block couldn't seek");
+  }
+  if (write(fd, buf, block_size) != block_size) {
+	pexit("put_block couldn't write");
+  }
+}
+
+
+/* Dummy routines to keep source file clean from #ifdefs */
+
+void flush()
+{
+  return;
+}
+
+void cache_init()
+{
+  return;
+}
+
+#endif
Index: /trunk/minix/commands/simple/mknod.c
===================================================================
--- /trunk/minix/commands/simple/mknod.c	(revision 9)
+++ /trunk/minix/commands/simple/mknod.c	(revision 9)
@@ -0,0 +1,70 @@
+/* mknod - build a special file		Author: Andy Tanenbaum */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <minix/minlib.h>
+#include <errno.h>
+#include <stdio.h>
+
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(void badcomm, (void));
+_PROTOTYPE(void badfifo, (void));
+_PROTOTYPE(void badchar, (void));
+_PROTOTYPE(void badblock, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+/* Mknod name b/c major minor makes a node. */
+
+  int mode, major, minor, dev;
+
+  if (argc < 3) badcomm();
+  if (*argv[2] != 'b' && *argv[2] != 'c' && *argv[2] != 'p') badcomm();
+  if (*argv[2] == 'p' && argc != 3) badfifo();
+  if (*argv[2] == 'c' && argc != 5) badchar();
+  if (*argv[2] == 'b' && argc != 5) badblock();
+  if (*argv[2] == 'p') {
+	mode = 010666;
+	dev = 0;
+  } else {
+	mode = (*argv[2] == 'b' ? 060666 : 020666);
+	major = atoi(argv[3]);
+	minor = atoi(argv[4]);
+	if (major - 1 > 0xFE || minor > 0xFF) badcomm();
+	dev = (major << 8) | minor;
+  }
+  if (mknod(argv[1], mode, dev) < 0) {
+	int err = errno;
+	std_err("mknod: ");
+	errno = err;
+	perror(argv[1]);
+  }
+  return(0);
+}
+
+void badcomm()
+{
+  std_err("Usage: mknod name b/c/p [major minor]\n");
+  exit(1);
+}
+
+void badfifo()
+{
+  std_err("Usage: mknod name p\n");
+  exit(1);
+}
+
+void badchar()
+{
+  std_err("Usage: mknod name c major minor\n");
+  exit(1);
+}
+
+void badblock()
+{
+  std_err("Usage: mknod name b major minor\n");
+  exit(1);
+}
Index: /trunk/minix/commands/simple/mkproto.c
===================================================================
--- /trunk/minix/commands/simple/mkproto.c	(revision 9)
+++ /trunk/minix/commands/simple/mkproto.c	(revision 9)
@@ -0,0 +1,250 @@
+/* mkproto - make an mkfs prototype	Author: Andrew Cagney */
+
+/* Submitted by: cagney@chook.ua.oz (Andrew Cagney - aka Noid) */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+/* The default values for the prototype file */
+#define DEF_UID		2	/* bin */
+#define DEF_GID		1	/* daemon group */
+#define DEF_PROT	0555	/* a=re */
+#define DEF_BLOCKS	360
+#define DEF_INODES	63
+#define DEF_INDENTSTR	"\t"
+
+#ifndef major
+#define major(x) ( (x>>8) & 0377)
+#define minor(x) (x & 0377)
+#endif
+
+/* Globals. */
+int count, origlen, tabs;
+int gid, uid, prot, same_uid, same_gid, same_prot, blocks, inodes;
+int block_given, inode_given, dprot;
+char *indentstr;
+char *proto_file, *top;
+FILE *outfile;
+
+extern int optind;
+extern char *optarg;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void descend, (char *dirname));
+_PROTOTYPE(void display_attrib, (char *name, struct stat *st));
+_PROTOTYPE(void usage, (char *binname));
+_PROTOTYPE(void open_outfile, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  char *dir;
+  struct stat st;
+  int op;
+
+  gid = DEF_GID;
+  uid = DEF_UID;
+  prot = DEF_PROT;
+  blocks = DEF_BLOCKS;
+  inodes = DEF_INODES;
+  indentstr = DEF_INDENTSTR;
+  inode_given = 0;
+  block_given = 0;
+  top = 0;
+  same_uid = 0;
+  same_gid = 0;
+  same_prot = 0;
+  while ((op = getopt(argc, argv, "b:g:i:p:t:u:d:s")) != EOF) {
+	switch (op) {
+	    case 'b':
+		blocks = atoi(optarg);
+		block_given = 1;
+		break;
+	    case 'g':
+		gid = atoi(optarg);
+		if (gid == 0) usage(argv[0]);
+		same_gid = 0;
+		break;
+	    case 'i':
+		inodes = atoi(optarg);
+		inode_given = 1;
+		break;
+	    case 'p':
+		sscanf(optarg, "%o", &prot);
+		if (prot == 0) usage(argv[0]);
+		same_prot = 0;
+		break;
+	    case 's':
+		same_prot = 1;
+		same_uid = 1;
+		same_gid = 1;
+		break;
+	    case 't':	top = optarg;	break;
+	    case 'u':
+		uid = atoi(optarg);
+		if (uid == 0) usage(argv[0]);
+		same_uid = 0;
+		break;
+	    case 'd':	indentstr = optarg;	break;
+	    default:		/* Illegal options */
+		usage(argv[0]);
+	}
+  }
+
+  if (optind >= argc) {
+	usage(argv[0]);
+  } else {
+	dir = argv[optind];
+	optind++;
+	proto_file = argv[optind];
+  }
+  if (!top) top = dir;
+  open_outfile();
+  if (block_given && !inode_given) inodes = (blocks / 3) + 8;
+  if (!block_given && inode_given) usage(argv[0]);
+  count = 1;
+  tabs = 0;
+  origlen = strlen(dir);
+
+  /* Check that it really is a directory */
+  stat(dir, &st);
+  if ((st.st_mode & S_IFMT) != S_IFDIR) {
+	fprintf(stderr, "mkproto: %s must be a directory\n", dir);
+	usage(argv[0]);
+  }
+  fprintf(outfile, "boot\n%d %d\n", blocks, inodes);
+  display_attrib("", &st);
+  fprintf(outfile, "\n");
+  descend(dir);
+  fprintf(outfile, "$\n");
+  return(0);
+}
+
+/* Output the prototype spec for this directory. */
+void descend(dirname)
+char *dirname;
+{
+  struct dirent *dp;
+  DIR *dirp;
+  char *name, *temp, *tempend;
+  int i;
+  struct stat st;
+  mode_t mode;
+
+  dirp = opendir(dirname);
+  if (dirp == NULL) {
+	fprintf(stderr, "unable to open directory %s\n", dirname);
+	return;
+  }
+  tabs++;
+  temp = (char *) malloc(sizeof(char) * strlen(dirname) +1 + PATH_MAX);
+  strcpy(temp, dirname);
+  strcat(temp, "/");
+  tempend = &temp[strlen(temp)];
+
+  for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
+	name = dp->d_name;
+
+	count++;
+	strcpy(tempend, name);
+
+	if (stat(temp, &st) == -1) {
+		fprintf(stderr, "cant get status of '%s' \n", temp);
+		continue;
+	}
+	if (name[0] == '.' && (name[1] == 0 ||
+	    (name[1] == '.' && name[2] == 0)))
+		continue;
+
+	display_attrib(name, &st);
+
+	mode = st.st_mode & S_IFMT;
+	if (mode == S_IFDIR) {
+		fprintf(outfile, "\n");
+		descend(temp);
+		for (i = 0; i < tabs; i++) {
+			fprintf(outfile, indentstr);
+		}
+		fprintf(outfile, "$\n");
+		continue;
+	}
+	if (mode == S_IFBLK || mode == S_IFCHR) {
+		fprintf(outfile, " %d %d\n", major(st.st_rdev), minor(st.st_rdev));
+		continue;
+	}
+	if (mode == S_IFREG) {
+		i = origlen;
+		fprintf(outfile, "%s%s", indentstr, top);
+		while (temp[i] != '\0') {
+			fputc(temp[i], outfile);
+			i++;
+		}
+		fprintf(outfile, "\n");
+		continue;
+	}
+	fprintf(outfile, " /dev/null");
+	fprintf(stderr,"File\n\t%s\n has an invalid mode, made empty.\n",temp);
+  }
+  closedir(dirp);
+  free(temp);
+  tabs--;
+}
+
+
+void display_attrib(name, st)
+char *name;
+struct stat *st;
+{
+/* Output the specification for a single file */
+
+  int i;
+
+  if (same_uid) uid = st->st_uid;
+  if (same_gid) gid = st->st_gid;
+  if (same_prot)
+	prot = st->st_mode & 0777;	/***** This one is a bit shady *****/
+  for (i = 0; i < tabs; i++) fprintf(outfile, indentstr);
+  fprintf(outfile, "%s%s%c%c%c%3o %d %d",
+	name,
+	*name == '\0' ? "" : indentstr,	/* stop the tab for a null name */
+	(st->st_mode & S_IFMT) == S_IFDIR ? 'd' :
+	(st->st_mode & S_IFMT) == S_IFCHR ? 'c' :
+	(st->st_mode & S_IFMT) == S_IFBLK ? 'b' :
+	'-',			/* file type */
+	(st->st_mode & S_ISUID) ? 'u' : '-',	/* set uid */
+	(st->st_mode & S_ISGID) ? 'g' : '-',	/* set gid */
+	prot,
+	uid,
+	gid);
+}
+
+void usage(binname)
+char *binname;
+{
+  fprintf(stderr, "Usage: %s [options] source_directory [prototype_file]\n", binname);
+  fprintf(stderr, "options:\n");
+  fprintf(stderr, "   -b n\t\t file system size is n blocks (default %d)\n", DEF_BLOCKS);
+  fprintf(stderr, "   -d STRING\t define the indentation characters (default %s)\n", "(none)");
+  fprintf(stderr, "   -g n\t\t use n as the gid on all files (default %d)\n", DEF_GID);
+  fprintf(stderr, "   -i n\t\t file system gets n i-nodes (default %d)\n", DEF_INODES);
+  fprintf(stderr, "   -p nnn\t use nnn (octal) as mode on all files (default %o)\n", DEF_PROT);
+  fprintf(stderr, "   -s  \t\t use the same uid, gid and mode as originals have\n");
+  fprintf(stderr, "   -t ROOT\t inital path prefix for each entry\n");
+  fprintf(stderr, "   -u n\t\t use nnn as the uid on all files (default %d)\n", DEF_UID);
+  exit(1);
+}
+
+void open_outfile()
+{
+  if (proto_file == NULL)
+	outfile = stdout;
+  else if ((outfile = fopen(proto_file, "w")) == NULL)
+	fprintf(stderr, "Cannot create %s\n ", proto_file);
+}
Index: /trunk/minix/commands/simple/mkswap.c
===================================================================
--- /trunk/minix/commands/simple/mkswap.c	(revision 9)
+++ /trunk/minix/commands/simple/mkswap.c	(revision 9)
@@ -0,0 +1,197 @@
+/*	mkswap 1.0 - Initialize a swap partition or file
+ *							Author: Kees J. Bot
+ *								6 Jan 2001
+ */
+#define nil ((void*)0)
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include <minix/u64.h>
+#include <minix/partition.h>
+#include <minix/swap.h>
+#include <servers/fs/const.h>
+#include <servers/fs/type.h>
+#include <servers/fs/super.h>
+
+static void usage(void)
+{
+    fprintf(stderr, "Usage: mkswap [-f] device-or-file [size[km]]\n");
+    exit(1);
+}
+
+int main(int argc, char **argv)
+{
+    int first;
+    int i;
+    char *file;
+    unsigned long offset, size, devsize;
+    int fd;
+    struct stat st;
+    ssize_t r;
+    struct super_block super;
+    swap_hdr_t swap_hdr;
+    static u8_t block[_MAX_BLOCK_SIZE];
+
+    first= 0;
+    i= 1;
+    while (i < argc && argv[i][0] == '-') {
+	char *opt= argv[i++]+1;
+
+	if (opt[0] == '-' && opt[1] == 0) break;	/* -- */
+
+	while (*opt != 0) switch (*opt++) {
+	case 'f':	first= 1;	break;
+	default:	usage();
+	}
+    }
+    if (i == argc) usage();
+    file= argv[i++];
+
+    size= 0;
+    if (i < argc) {
+	char *end;
+	unsigned long m;
+
+	size= strtoul(argv[i], &end, 10);
+	if (end == argv[i]) usage();
+	m= 1024;
+	if (*end != 0) {
+	    switch (*end) {
+	    case 'm':	case 'M':	m *= 1024;	/*FALL THROUGH*/
+	    case 'k':	case 'K':	end++;		break;
+	    }
+	}
+	if (*end != 0 || size == -1
+	    || (size * m) / m != size || (size *= m) <= SWAP_OFFSET
+	) {
+	    fprintf(stderr, "mkswap: %s: Bad size\n", argv[i]);
+	    exit(1);
+	}
+	i++;
+    }
+    if (i != argc) usage();
+
+    /* Open the device or file. */
+    if ((fd= open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) {
+	fprintf(stderr, "mkswap: Can't open %s: %s\n", file, strerror(errno));
+	exit(1);
+    }
+
+    /* File or device? */
+    (void) fstat(fd, &st);
+    if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
+	struct partition part;
+
+	/* How big is the partition? */
+	if (ioctl(fd, DIOCGETP, &part) < 0) {
+	    fprintf(stderr, "mkswap: Can't determine the size of %s: %s\n",
+		file, strerror(errno));
+	    exit(1);
+	}
+	devsize= cv64ul(part.size);
+	offset= 0;
+
+	if (!first) {
+	    /* Is there a file system? */
+	    r= -1;
+	    if (lseek(fd, SUPER_BLOCK_BYTES, SEEK_SET) == -1
+		|| (r= read(fd, block, _STATIC_BLOCK_SIZE)) < _STATIC_BLOCK_SIZE
+	    ) {
+		fprintf(stderr, "mkswap: %s: %s\n",
+		    file, r >= 0 ? "End of file" : strerror(errno));
+		exit(1);
+	    }
+	    memcpy(&super, block, sizeof(super));
+	    if (super.s_magic == SUPER_MAGIC) {
+		offset= (unsigned long) super.s_nzones * _STATIC_BLOCK_SIZE;
+	    } else
+	    if (super.s_magic == SUPER_V2) {
+		offset= (unsigned long) super.s_zones * _STATIC_BLOCK_SIZE;
+	    } else if (super.s_magic == SUPER_V3) {
+		offset= (unsigned long) super.s_zones * super.s_block_size;
+	    } else {
+		first= 1;
+	    }
+	}
+	if (size == 0) size= devsize - offset;
+	if (size == 0 || offset + size > devsize) {
+	    fprintf(stderr, "mkswap: There is no room on %s for ", file);
+	    if (size > 0) fprintf(stderr, "%lu kilobytes of ", size/1024);
+	    fprintf(stderr, "swapspace\n");
+	    if (offset > 0) {
+		fprintf(stderr, "(Use the -f flag to wipe the file system)\n");
+	    }
+	    exit(1);
+	}
+    } else
+    if (S_ISREG(st.st_mode)) {
+	/* Write to the swap file to guarantee space for MM. */
+	unsigned long n;
+
+	if (size == 0) {
+	    fprintf(stderr, "mkswap: No size specified for %s\n", file);
+	    usage();
+	}
+
+	memset(block, 0, sizeof(block));
+	for (n= 0; n < size; n += r) {
+	    r= size > sizeof(block) ? sizeof(block) : size;
+	    if ((r= write(fd, block, r)) <= 0) {
+		fprintf(stderr, "mkswap: %s: %s\n",
+		    file, r == 0 ? "End of file" : strerror(errno));
+		exit(1);
+	    }
+	}
+	first= 1;
+    } else {
+	fprintf(stderr, "mkswap: %s is not a device or a file\n", file);
+	exit(1);
+    }
+
+    if (offset < SWAP_OFFSET) {
+	offset += SWAP_OFFSET;
+	if (size < SWAP_OFFSET) size= 0; else size -= SWAP_OFFSET;
+    }
+    swap_hdr.sh_magic[0]= SWAP_MAGIC0;
+    swap_hdr.sh_magic[1]= SWAP_MAGIC1;
+    swap_hdr.sh_magic[2]= SWAP_MAGIC2;
+    swap_hdr.sh_magic[3]= SWAP_MAGIC3;
+    swap_hdr.sh_version= SH_VERSION;
+    swap_hdr.sh_priority= 0;
+    swap_hdr.sh_offset= offset;
+    swap_hdr.sh_swapsize= size;
+
+    r= -1;
+    if (lseek(fd, SWAP_BOOTOFF, SEEK_SET) == -1
+	|| (r= read(fd, block, sizeof(block))) < sizeof(block)
+    ) {
+	fprintf(stderr, "mkswap: %s: %s\n", file,
+	    file, r >= 0 ? "End of file" : strerror(errno));
+	exit(1);
+    }
+
+    r= (first ? SWAP_BOOTOFF : OPTSWAP_BOOTOFF) - SWAP_BOOTOFF;
+    memcpy(block + r, &swap_hdr, sizeof(swap_hdr));
+
+    r= -1;
+    if (lseek(fd, SWAP_BOOTOFF, SEEK_SET) == -1
+	|| (r= write(fd, block, sizeof(block))) < sizeof(block)
+    ) {
+	fprintf(stderr, "mkswap: %s: %s\n", file,
+	    file, r >= 0 ? "End of file" : strerror(errno));
+	exit(1);
+    }
+    printf("%s: swapspace at offset %lu, size %lu kilobytes\n",
+	file, offset / 1024, size / 1024);
+    return 0;
+}
Index: /trunk/minix/commands/simple/modem.c
===================================================================
--- /trunk/minix/commands/simple/modem.c	(revision 9)
+++ /trunk/minix/commands/simple/modem.c	(revision 9)
@@ -0,0 +1,253 @@
+/* modem - Put modem into DIALIN or DIALOUT mode.	Author: F. van Kempen */
+
+/* Exit:	0	OK, suspended/restarted GETTY
+ *		1	UNIX error
+ *		2	Process busy
+ * Version:	1.3 	12/30/89
+ *
+ * Author:	F. van Kempen, MicroWalt Corporation
+ *
+ * All fancy stuff removed, see getty.c.	Kees J. Bot.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <errno.h>
+
+#include <minix/paths.h>
+
+char PATH_UTMP[] = _PATH_UTMP;			/* current logins */
+
+_PROTOTYPE(void usage , (void));
+_PROTOTYPE(int main , (int argc , char *argv []));
+_PROTOTYPE(void sendcodes , (char *tty, char *codes));
+
+
+void usage()
+{
+  fprintf(stderr,
+"Usage: modem [-sio] [-I in-codes] [-O out-codes] line [command args ...]\n");
+  exit(1);
+}
+
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+  struct utmp entry;
+  char devtty[1024], *tty;
+  char **command;
+  int ex_code = 0;
+  int fd, i, slot, getty;
+  struct stat st;
+  enum { TOGGLE, DIALIN, DIALOUT } mode= TOGGLE;
+  int silent = 0;
+  _PROTOTYPE(void (*hsig), (int));
+  _PROTOTYPE(void (*isig), (int));
+  _PROTOTYPE(void (*qsig), (int));
+  _PROTOTYPE(void (*tsig), (int));
+  pid_t pid;
+  int r, status;
+  uid_t uid = getuid();
+  gid_t gid = getgid();
+  char *in_codes, *out_codes;
+
+  i = 1;
+  while (i < argc && argv[i][0] == '-') {
+	char *opt = argv[i++] + 1;
+
+	if (opt[0] == '-' && opt[1] == 0) break;
+
+	while (*opt != 0) {
+		switch (*opt++) {
+		    case 's':	/* silent mode */
+			silent = 1;
+			break;
+		    case 'i':	/* DIAL-IN mode: suspend GETTY */
+			mode = DIALIN;
+			break;
+		    case 'o':	/* DIAL-OUT mode: restart GETTY */
+			mode = DIALOUT;
+			break;
+		    case 'I':	/* code to switch modem to dial-in */
+			if (*opt == 0) {
+				if (i == argc) usage();
+				opt = argv[i++];
+			}
+			in_codes = opt;
+			opt = "";
+			break;
+		    case 'O':	/* code to switch modem to dial-out */
+			if (*opt == 0) {
+				if (i == argc) usage();
+				opt = argv[i++];
+			}
+			out_codes = opt;
+			opt = "";
+			break;
+		    default:
+			usage();
+		}
+	}
+  }
+
+  if (i == argc) usage();
+  tty = argv[i++];		/* Modem line */
+
+  if (mode != TOGGLE && i != argc) usage();
+  command = argv + i;		/* Command to execute (if any). */
+
+  if (strchr(tty, '/') == NULL) {
+	strcpy(devtty, "/dev/");
+	strncat(devtty, tty, 1024 - 6);
+	tty = devtty;
+  }
+
+  if (stat(tty, &st) < 0) {
+	fprintf(stderr, "modem: %s: %s\n", tty, strerror(errno));
+	exit(1);
+  }
+
+  if (!S_ISCHR(st.st_mode)) {
+	fprintf(stderr, "%s is not a tty\n", tty);
+	exit(1);
+  }
+
+  /* Find the utmp slot number for the line. */
+  if ((fd= open(tty, O_RDONLY)) < 0 || (slot= fttyslot(fd)) == 0) {
+	fprintf(stderr, "modem: %s: %s\n", tty, strerror(errno));
+	exit(1);
+  }
+  close(fd);
+
+  /* Read the UTMP file to find out the PID and STATUS of the GETTY. */
+  entry.ut_type= 0;
+  if ((fd = open(PATH_UTMP, O_RDONLY)) < 0
+	|| lseek(fd, (off_t) slot * sizeof(entry), SEEK_SET) < 0
+	|| read(fd, &entry, sizeof(entry)) < 0
+  ) {
+	fprintf(stderr, "modem: cannot read UTMP !\n");
+	exit(1);
+  }
+  close(fd);
+
+  hsig= signal(SIGHUP, SIG_IGN);
+  isig= signal(SIGINT, SIG_IGN);
+  qsig= signal(SIGQUIT, SIG_IGN);
+  tsig= signal(SIGTERM, SIG_IGN);
+
+  /* Process the terminal entry if we got one. */
+  switch (entry.ut_type) {
+  case LOGIN_PROCESS:		/* getty waiting for a call */
+	getty = 1;
+	break;
+  case USER_PROCESS:		/* login or user-shell */
+	if (!silent) fprintf(stderr, "modem: line is busy.\n");
+	exit(2);
+	break;
+  default:
+	getty = 0;
+  }
+
+  for (i = (mode == TOGGLE) ? 0 : 1; i < 2; i++) {
+	/* Now perform the desired action (DIALIN or DIALOUT). */
+	switch (mode) {
+	case DIALOUT:
+	case TOGGLE:
+		if (getty) kill(entry.ut_pid, SIGUSR1);  /* suspend getty */
+		chown(tty, uid, st.st_gid);	/* give line to user */
+		chmod(tty, 0600);
+		if (out_codes != NULL) sendcodes(tty, out_codes);
+		if (!silent) printf("modem on %s set for dialout.\n", tty);
+		break;
+	case DIALIN:
+		if (in_codes != NULL) sendcodes(tty, in_codes);
+		chown(tty, 0, st.st_gid);		/* revoke access */
+		chmod(tty, 0600);
+		if (getty) kill(entry.ut_pid, SIGUSR2);	/* restart getty */
+		if (!silent) printf("modem on %s set for dialin.\n", tty);
+	}
+	if (mode == TOGGLE) {
+		/* Start the command to run */
+		pid_t pid;
+		int status;
+
+		switch ((pid = fork())) {
+		case -1:
+			fprintf(stderr, "modem: fork(): %s\n", strerror(errno));
+			ex_code= 1;
+			break;
+		case 0:
+			setgid(gid);
+			setuid(uid);
+			(void) signal(SIGHUP, hsig);
+			(void) signal(SIGINT, isig);
+			(void) signal(SIGQUIT, qsig);
+			(void) signal(SIGTERM, tsig);
+			execvp(command[0], command);
+			fprintf(stderr, "modem: %s: %s\n",
+					command[0], strerror(errno));
+			_exit(127);
+		default:
+			while ((r= wait(&status)) != pid) {
+				if (r == -1 && errno != EINTR) break;
+			}
+			if (r == -1 || status != 0) ex_code = 1;
+		}
+		mode = DIALIN;
+	}
+  }
+  exit(ex_code);
+}
+
+void sendcodes(tty, codes)
+char *tty, *codes;
+{
+	int fd;
+	int c;
+	char buf[1024], *bp = buf;
+
+	if ((fd = open(tty, O_RDWR|O_NONBLOCK)) < 0) {
+		fprintf(stderr, "modem: can't send codes to %s: %s\n",
+			tty, strerror(errno));
+		return;
+	}
+	while ((c = *codes++) != 0) {
+fprintf(stderr, "%d\n", __LINE__);
+		if (c == '\\') {
+			if ((c = *codes++) == 0) break;
+			if (c == 'r') c= '\r';
+			if (c == 'n') c= '\n';
+		}
+		*bp++ = c;
+		if (bp == buf + sizeof(buf) || c == '\r' || c == '\n') {
+fprintf(stderr, "%d\n", __LINE__);
+			write(fd, buf, bp - buf);
+fprintf(stderr, "%d\n", __LINE__);
+			do {sleep(1);
+fprintf(stderr, "%d\n", __LINE__);
+			fprintf(stderr, "%d\n", read(fd, buf, sizeof(buf)));
+			}while (read(fd, buf, sizeof(buf)) > 0);
+fprintf(stderr, "%d\n", __LINE__);
+			bp = buf;
+		}
+	}
+	if (bp > buf) {
+fprintf(stderr, "%d\n", __LINE__);
+		write(fd, buf, bp - buf);
+fprintf(stderr, "%d\n", __LINE__);
+		do sleep(1); while (read(fd, buf, sizeof(buf)) > 0);
+fprintf(stderr, "%d\n", __LINE__);
+	}
+	close(fd);
+}
Index: /trunk/minix/commands/simple/mount.c
===================================================================
--- /trunk/minix/commands/simple/mount.c	(revision 9)
+++ /trunk/minix/commands/simple/mount.c	(revision 9)
@@ -0,0 +1,206 @@
+/* mount - mount a file system		Author: Andy Tanenbaum */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/minlib.h>
+#include <minix/swap.h>
+#include <sys/svrctl.h>
+#include <stdio.h>
+#include "../../servers/fs/const.h"
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void list, (void));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(void tell, (char *this));
+_PROTOTYPE(void swapon, (char *file));
+
+static u8_t MAGIC[] = { SWAP_MAGIC0, SWAP_MAGIC1, SWAP_MAGIC2, SWAP_MAGIC3 };
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, ro, swap, n, v;
+  char **ap, *vs, *opt, *err;
+  char special[PATH_MAX+1], mounted_on[PATH_MAX+1], version[10], rw_flag[10];
+
+  if (argc == 1) list();	/* just list /etc/mtab */
+  ro = 0;
+  swap = 0;
+  ap = argv+1;
+  for (i = 1; i < argc; i++) {
+	if (argv[i][0] == '-') {
+		opt = argv[i]+1;
+		while (*opt != 0) switch (*opt++) {
+		case 'r':	ro = 1;		break;
+		case 's':	swap = 1;	break;
+		default:	usage();
+		}
+	} else {
+		*ap++ = argv[i];
+	}
+  }
+  *ap = NULL;
+  argc = (ap - argv);
+
+  if (ro && swap) usage();
+
+  if (swap) {
+	if (argc != 2) usage();
+	swapon(argv[1]);
+	tell(argv[1]);
+	tell(" is swapspace\n");
+  } else {
+	if (argc != 3) usage();
+	if (mount(argv[1], argv[2], ro) < 0) {
+		err = strerror(errno);
+		std_err("mount: Can't mount ");
+		std_err(argv[1]);
+		std_err(" on ");
+		std_err(argv[2]);
+		std_err(": ");
+		std_err(err);
+		std_err("\n");
+		exit(1);
+	}
+	/* The mount has completed successfully. Tell the user. */
+	tell(argv[1]);
+	tell(" is read-");
+	tell(ro ? "only" : "write");
+	tell(" mounted on ");
+	tell(argv[2]);
+	tell("\n");
+  }
+
+  /* Update /etc/mtab. */
+  n = load_mtab("mount");
+  if (n < 0) exit(1);		/* something is wrong. */
+
+  /* Loop on all the /etc/mtab entries, copying each one to the output buf. */
+  while (1) {
+	n = get_mtab_entry(special, mounted_on, version, rw_flag);
+	if (n < 0) break;
+	n = put_mtab_entry(special, mounted_on, version, rw_flag);
+	if (n < 0) {
+		std_err("mount: /etc/mtab has grown too large\n");
+		exit(1);
+	}
+  }
+  if (swap) {
+	vs = "swap";
+  } else {
+	v = fsversion(argv[1], "mount");
+	if (v == 1)
+		vs = "1";
+	else if (v == 2)
+		vs = "2";
+	else if (v == 3)
+		vs = "3";
+	else
+		vs = "0";
+  }
+  n = put_mtab_entry(argv[1], swap ? "swap" : argv[2], vs, (ro ? "ro" : "rw") );
+  if (n < 0) {
+	std_err("mount: /etc/mtab has grown too large\n");
+	exit(1);
+  }
+
+  n = rewrite_mtab("mount");
+  return(0);
+}
+
+
+void list()
+{
+  int n;
+  char special[PATH_MAX+1], mounted_on[PATH_MAX+1], version[10], rw_flag[10];
+
+  /* Read and print /etc/mtab. */
+  n = load_mtab("mount");
+  if (n < 0) exit(1);
+
+  while (1) {
+	n = get_mtab_entry(special, mounted_on, version, rw_flag);
+	if  (n < 0) break;
+	write(1, special, strlen(special));
+	if (strcmp(version, "swap") == 0) {
+		tell(" is swapspace\n");
+	} else {
+		tell(" is read-");
+		tell(strcmp(rw_flag, "rw") == 0 ? "write" : "only");
+		tell(" mounted on ");
+		tell(mounted_on);
+		tell("\n");
+	}
+  }
+  exit(0);
+}
+
+
+void usage()
+{
+  std_err("Usage: mount [-r] special name\n       mount -s special\n");
+  exit(1);
+}
+
+
+void tell(this)
+char *this;
+{
+  write(1, this, strlen(this));
+}
+
+void swapon(file)
+char *file;
+{
+  u32_t super[2][_MAX_BLOCK_SIZE / 2 / sizeof(u32_t)];
+  swap_hdr_t *sp;
+  struct mmswapon mmswapon;
+  int fd, r;
+  char *err;
+  
+  if ((fd = open(file, O_RDWR)) < 0
+	|| lseek(fd, SUPER_BLOCK_BYTES, SEEK_SET) == -1
+	|| (r = read(fd, super, _STATIC_BLOCK_SIZE)) < 0
+  ) {
+	err = strerror(errno);
+	std_err("mount: ");
+	std_err(file);
+	std_err(": ");
+	std_err(err);
+	std_err("\n");
+	exit(1);
+  }
+  sp = (swap_hdr_t *) &super[0];
+  if (memcmp(sp->sh_magic, MAGIC, sizeof(MAGIC)) != 0)
+	sp = (swap_hdr_t *) &super[1];
+  if (r == _STATIC_BLOCK_SIZE && memcmp(sp->sh_magic, MAGIC, sizeof(MAGIC)) != 0
+			|| sp->sh_version > SH_VERSION) {
+	std_err("mount: ");
+	std_err(file);
+	std_err(" is not swapspace\n");
+	exit(1);
+  }
+  close(fd);
+  mmswapon.offset = sp->sh_offset;
+  mmswapon.size = sp->sh_swapsize;
+  strncpy(mmswapon.file, file, sizeof(mmswapon.file));
+  mmswapon.file[sizeof(mmswapon.file)-1] = 0;
+  if (svrctl(MMSWAPON, &mmswapon) < 0) {
+	err = strerror(errno);
+	std_err("mount: ");
+	std_err(file);
+	std_err(": ");
+	std_err(err);
+	std_err("\n");
+	exit(1);
+  }
+}
Index: /trunk/minix/commands/simple/mt.c
===================================================================
--- /trunk/minix/commands/simple/mt.c	(revision 9)
+++ /trunk/minix/commands/simple/mt.c	(revision 9)
@@ -0,0 +1,216 @@
+/*	mt 1.3 - magnetic tape control			Author: Kees J. Bot
+ *								4 Apr 1993
+ */
+#define nil	NULL
+#ifndef _POSIX_SOURCE
+#define _POSIX_SOURCE	1
+#endif
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mtio.h>
+
+/* Device status. */
+#define DS_OK		0
+#define DS_ERR		1
+#define DS_EOF		2
+
+/* SCSI Sense key bits. */
+#define SENSE_KEY	0x0F	/* The key part. */
+#define SENSE_ILI	0x20	/* Illegal block size. */
+#define SENSE_EOM	0x40	/* End-of-media. */
+#define SENSE_EOF	0x80	/* Filemark reached. */
+
+/* Supported operations: */
+
+typedef struct tape_operation {
+	int	op;		/* Opcode for MTIOCTOP ioctl (if any). */
+	char	*cmd;		/* Command name. */
+	int	lim;		/* Limits on count. */
+} tape_operation_t;
+
+#define SELF	-1	/* Not a simple command, have to interpret. */
+#define IGN	-1	/* Ignore count field (or accept anything.) */
+#define NNG	 0	/* Nonnegative count field. */
+#define POS	 1	/* Positive count field. */
+
+tape_operation_t tapeops[] = {
+	{ MTWEOF,  "eof",      POS },	/* Write EOF mark */
+	{ MTWEOF,  "weof",     POS },	/* Same */
+	{ MTFSF,   "fsf",      POS },	/* Forward Space File */
+	{ MTFSR,   "fsr",      POS },	/* Forward Space Record */
+	{ MTBSF,   "bsf",      NNG },	/* Backward Space File */
+	{ MTBSR,   "bsr",      POS },	/* Backward Space Record */
+	{ MTEOM,   "eom",      IGN },	/* To End-Of-Media */
+	{ MTREW,   "rewind",   IGN },	/* Rewind */
+	{ MTOFFL,  "offline",  IGN },	/* Rewind and take offline */
+	{ MTOFFL,  "rewoffl",  IGN },	/* Same */
+	{ SELF,	   "status",   IGN },	/* Tape Status */
+	{ MTRETEN, "retension",IGN },	/* Retension the tape */
+	{ MTERASE, "erase",    IGN },	/* Erase the tape */
+	{ MTMODE,  "density",  NNG },	/* Select density */
+	{ MTBLKZ,  "blksize",  NNG },	/* Select block size */
+	{ MTBLKZ,  "blocksize",NNG },	/* Same */
+};
+
+#define arraysize(a)	(sizeof(a)/sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+
+/* From aha_scsi.c: */
+char *dev_state[] = {
+	"OK", "ERR", "EOF"
+};
+
+char *scsi_sense[] = {
+	"NO SENSE INFO", "RECOVERED ERROR", "NOT READY", "MEDIUM ERROR",
+	"HARDWARE ERROR", "ILLEGAL REQUEST", "UNIT ATTENTION", "DATA PROTECT",
+	"BLANK CHECK", "VENDOR UNIQUE ERROR", "COPY ABORTED", "ABORTED COMMAND",
+	"EQUAL", "VOLUME OVERFLOW", "MISCOMPARE", "SENSE RESERVED"
+};
+
+void usage(void)
+{
+	fprintf(stderr, "Usage: mt [-f device] command [count]\n");
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	char *tape;
+	char *cmd;
+	int count= 1;
+	int fd, r;
+	tape_operation_t *op, *found;
+	struct mtop mtop;
+	struct mtget mtget;
+
+	tape= getenv("TAPE");
+
+	/* -f tape? */
+	if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'f') {
+		tape= argv[1] + 2;
+
+		if (*tape == 0) {
+			if (--argc < 2) usage();
+			argv++;
+			tape= argv[1];
+		}
+		argc--;
+		argv++;
+	}
+
+	if (argc != 2 && argc != 3) usage();
+
+	if (argc == 3) {
+		/* Check and convert the 'count' argument. */
+		char *end;
+
+		errno= 0;
+		count= strtol(argv[2], &end, 0);
+		if (*end != 0) usage();
+		if (errno == ERANGE || (mtop.mt_count= count) != count) {
+			fprintf(stderr, "mt: %s: count too large, overflow\n",
+				argv[2]);
+			exit(1);
+		}
+	}
+
+	if (tape == nil) {
+		fprintf(stderr,
+			"mt: tape device not specified by -f or $TAPE\n");
+		exit(1);
+	}
+
+	cmd= argv[1];
+	if (strcmp(cmd, "rew") == 0) cmd= "rewind";	/* aha! */
+	found= nil;
+
+	/* Search for an operation that is unambiguously named. */
+	for (op= tapeops; op < arraylimit(tapeops); op++) {
+		if (strncmp(op->cmd, cmd, strlen(cmd)) == 0) {
+			if (found != nil) {
+				fprintf(stderr, "mt: %s: ambiguous\n", cmd);
+				exit(1);
+			}
+			found= op;
+		}
+	}
+
+	if ((op= found) == nil) {
+		fprintf(stderr, "mt: unknown command '%s'\n", cmd);
+		exit(1);
+	}
+
+	/* Check count. */
+	switch (op->lim) {
+	case NNG:
+		if (count < 0) {
+			fprintf(stderr, "mt %s: count may not be negative\n",
+				op->cmd);
+			exit(1);
+		}
+		break;
+	case POS:
+		if (count <= 0) {
+			fprintf(stderr,
+				"mt %s: count must be greater than zero\n",
+				op->cmd);
+			exit(1);
+		}
+		break;
+	}
+
+	if (strcmp(tape, "-") == 0) {
+		fd= 0;
+	} else
+	if ((fd= open(tape, O_RDONLY)) < 0) {
+		fprintf(stderr, "mt: %s: %s\n", tape, strerror(errno));
+		exit(1);
+	}
+
+	if (op->op != SELF) {
+		/* A simple tape operation. */
+
+		mtop.mt_op= op->op;
+		mtop.mt_count= count;
+		r= ioctl(fd, MTIOCTOP, &mtop);
+	} else
+	if (strcmp(op->cmd, "status") == 0) {
+		/* Get status information. */
+
+		if ((r= ioctl(fd, MTIOCGET, &mtget)) == 0) {
+			printf("\
+SCSI tape drive %s:\n\
+   drive status = 0x%02x (%s), sense key = 0x%02x (%s%s%s%s)\n\
+   file no = %ld, block no = %ld, residual = %ld, block size = ",
+   				tape, mtget.mt_dsreg,
+   				mtget.mt_dsreg > 2 ? "?" :
+   						dev_state[mtget.mt_dsreg],
+				mtget.mt_erreg,
+				mtget.mt_erreg & SENSE_EOF ? "EOF + " : "",
+				mtget.mt_erreg & SENSE_EOM ? "EOM + " : "",
+				mtget.mt_erreg & SENSE_ILI ? "ILI + " : "",
+				scsi_sense[mtget.mt_erreg & SENSE_KEY],
+				(long) mtget.mt_fileno,
+				(long) mtget.mt_blkno,
+				(long) mtget.mt_resid);
+			printf(mtget.mt_blksize == 0 ? "variable\n" : "%ld\n",
+				mtget.mt_blksize);
+		}
+	}
+	if (r < 0) {
+		if (errno == ENOTTY) {
+			fprintf(stderr, "mt: %s: command '%s' not supported\n",
+				tape, op->cmd);
+			exit(2);
+		}
+		fprintf(stderr, "mt: %s: %s\n", tape, strerror(errno));
+		exit(1);
+	}
+	exit(0);
+}
Index: /trunk/minix/commands/simple/newroot.c
===================================================================
--- /trunk/minix/commands/simple/newroot.c	(revision 9)
+++ /trunk/minix/commands/simple/newroot.c	(revision 9)
@@ -0,0 +1,31 @@
+/*
+newroot.c
+
+Replace the current root with a new one
+*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+	int r;
+	char *dev;
+
+	if (argc != 2)
+	{
+		fprintf(stderr, "Usage: newroot <block-special>\n");
+		exit(1);
+	}
+	dev= argv[1];
+	r= mount(dev, "/", 0 /* !ro */);
+	if (r != 0)
+	{
+		fprintf(stderr, "newroot: mount failed: %s\n", strerror(errno));
+		exit(1);
+	}
+	return 0;
+}
Index: /trunk/minix/commands/simple/nice.c
===================================================================
--- /trunk/minix/commands/simple/nice.c	(revision 9)
+++ /trunk/minix/commands/simple/nice.c	(revision 9)
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 1989, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#define	DEFNICE	10
+
+void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+	long niceness = DEFNICE;
+	int ch;
+	char *ep;
+	char arg1[10];
+
+	/* Obsolescent syntax: -number, --number */
+	if (argc >= 2 && argv[1][0] == '-' && (argv[1][1] == '-' ||
+	    isdigit((unsigned char)argv[1][1])) && strcmp(argv[1], "--") != 0) {
+		snprintf(arg1, sizeof(arg1), "-n%s", argv[1] + 1);
+		argv[1] = arg1;
+	}
+
+	while ((ch = getopt(argc, argv, "n:")) != -1) {
+		switch (ch) {
+		case 'n':
+			errno = 0;
+			niceness = strtol(optarg, &ep, 10);
+			if (ep == optarg || *ep != '\0' || errno ||
+			    niceness < INT_MIN || niceness > INT_MAX) {
+				fprintf(stderr, "%s: invalid nice value", optarg);
+				return 1;
+			}
+			break;
+		default:
+			usage();
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc == 0)
+		usage();
+
+	errno = 0;
+	niceness += getpriority(PRIO_PROCESS, 0);
+	if (errno) {
+		perror("getpriority");
+		return 1;
+	}
+	if (setpriority(PRIO_PROCESS, 0, (int)niceness)) {
+		perror("setpriority");
+		return 1;
+	}
+	errno = 0;
+	execvp(*argv, argv);
+	perror("execvp");
+	return 1;
+}
+
+void
+usage(void)
+{
+
+	(void)fprintf(stderr, "usage: nice [-n incr] utility [arguments]\n");
+	exit(1);
+}
Index: /trunk/minix/commands/simple/nm.c
===================================================================
--- /trunk/minix/commands/simple/nm.c	(revision 9)
+++ /trunk/minix/commands/simple/nm.c	(revision 9)
@@ -0,0 +1,226 @@
+/* nm - print name list.		Author: Dick van Veen */
+
+/* Dick van Veen: veench@cs.vu.nl */
+
+#include <sys/types.h>
+#include <a.out.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+/* Read the name list in memory, sort it, and print it.  */
+
+/* Nm [-gnopru] [file] ...
+ *
+ * flags:
+ *	-d	address in decimal
+ *	-g	print only external symbols.
+ *	-n	sort numerically rather than alphabetically.
+ *	-o	prepend file name to each line rather than only once.
+ *	-p	don't sort, pint n symbol-table order.
+ *	-r	sort in reverse order.
+ *	-u	print only undefined symbols.
+ *
+ *	-	when no file name is present, a.out is assumed.
+ *
+ *	NOTE:	no archives are supported because assembly files don't
+ *		have symbol tables.
+ *
+ */
+
+#define A_OUT		"a.out"
+
+int d_flag;
+int g_flag;
+int n_flag;
+int o_flag;
+int p_flag;
+int r_flag;
+int u_flag;
+
+char io_buf[BUFSIZ];		/* io buffer */
+struct exec header;		/* header of a.out file */
+int stbl_elems;			/* #elements in symbol table */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(int nm_sort, (const void *tmp_stbl1, const void *tmp_stbl2));
+_PROTOTYPE(void nm, (char *file));
+_PROTOTYPE(int read_header, (int fd));
+_PROTOTYPE(void nm_print, (char *file, struct nlist *stbl));
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  argv++;
+  while (*argv != 0 && **argv == '-') {
+	*argv += 1;
+	while (**argv != '\0') {
+		switch (**argv) {
+		    case 'd':	d_flag = 1;	break;
+		    case 'g':	g_flag = 1;	break;
+		    case 'n':	n_flag = 1;	break;
+		    case 'o':	o_flag = 1;	break;
+		    case 'p':	p_flag = 1;	break;
+		    case 'r':	r_flag = 1;	break;
+		    case 'u':	u_flag = 1;	break;
+		    default:
+			fprintf(stderr, "illegal flag: -%c\n", **argv);
+			exit(-1);
+		}
+		*argv += 1;
+	}
+	argv++;
+  }
+  setbuf(stdin, io_buf);
+  if (*argv == 0)
+	nm(A_OUT);
+  else
+	while (*argv != 0) {
+		nm(*argv);
+		argv++;
+	}
+  return(0);
+}
+
+int nm_sort(tmp_stbl1, tmp_stbl2)
+_CONST void *tmp_stbl1, *tmp_stbl2;
+{
+
+  struct nlist *stbl1 = (struct nlist *)tmp_stbl1;
+  struct nlist *stbl2 = (struct nlist *)tmp_stbl2;
+  int cmp;
+
+  if (n_flag) {			/* sort numerically */
+	if ((stbl1->n_sclass & N_SECT) <
+	    (stbl2->n_sclass & N_SECT))
+		cmp = -1;
+	else if ((stbl1->n_sclass & N_SECT) >
+		 (stbl2->n_sclass & N_SECT))
+		cmp = 1;
+	else if (stbl1->n_value < stbl2->n_value)
+		cmp = -1;
+	else if (stbl1->n_value > stbl2->n_value)
+		cmp = 1;
+	else
+		cmp = strncmp(stbl1->n_name, stbl2->n_name, (size_t)8);
+  } else {
+	cmp = strncmp(stbl1->n_name, stbl2->n_name, (size_t)8);
+	if (cmp == 0) {
+		if (stbl1->n_value < stbl2->n_value)
+			cmp = -1;
+		else if (stbl1->n_value > stbl2->n_value)
+			cmp = 1;
+	}
+  }
+
+  if (r_flag) cmp = -cmp;	/* reverse sort */
+  return(cmp);
+}
+
+void nm(file)
+char *file;
+{
+  struct nlist *stbl;
+  int fd;
+
+  fd = open(file, O_RDONLY);
+  if (fd == -1) {
+	fprintf(stderr, "can't open %s\n", file);
+	return;
+  }
+  if (read_header(fd)) {
+	fprintf(stderr, "%s: no executable file\n", file);
+	close(fd);
+	return;
+  }
+  if (header.a_syms == 0) {
+	close(fd);
+	return;
+  }
+  if ((size_t) header.a_syms != header.a_syms) {
+	fprintf(stderr, "%s: symbol table too large to allocate\n", file);
+	close(fd);
+	return;
+  }
+  if ((int) header.a_syms != header.a_syms) {
+	/* This is necessary because we are too lazy to iterate the read. */
+	fprintf(stderr, "%s: symbol table too large to read\n", file);
+	close(fd);
+	return;
+  }
+  stbl = (struct nlist *) malloc((size_t) header.a_syms);
+  if (stbl == NULL) {
+	fprintf(stderr, "%s: can't allocate symbol table\n", file);
+	close(fd);
+	return;
+  }
+  if (read(fd, (char *) stbl, (unsigned) header.a_syms) != header.a_syms) {
+	fprintf(stderr, "%s: can't read symbol table\n", file);
+	free(stbl);
+	close(fd);
+	return;
+  }
+  stbl_elems = (int) header.a_syms / sizeof(struct nlist);
+  if (!p_flag) qsort(stbl, (size_t)stbl_elems, sizeof(struct nlist), nm_sort);
+  nm_print(file, stbl);
+  free(stbl);
+  close(fd);
+}
+
+int read_header(fd)
+int fd;
+{
+  if (read(fd, (char *) &header, sizeof(struct exec)) != sizeof(struct exec))
+	return(1);
+  if (BADMAG(header)) return(1);
+  lseek(fd, A_SYMPOS(header), SEEK_SET);
+
+  return(0);
+}
+
+void nm_print(file, stbl)
+char *file;
+register struct nlist *stbl;
+{
+  struct nlist *last;
+  char name[9];
+  int n_sclass;
+  char type;
+
+  name[8] = '\0';
+  if (!o_flag) printf("%s:\n", file);
+  for (last = &stbl[stbl_elems]; stbl != last; stbl++) {
+	if (g_flag && (stbl->n_sclass & N_CLASS) != C_EXT) continue;
+	if (u_flag && (stbl->n_sclass & N_SECT) != N_UNDF) continue;
+
+	n_sclass = stbl->n_sclass & N_SECT;
+	if (n_sclass == N_ABS)
+		type = 'a';
+	else if (n_sclass == N_TEXT)
+		type = 't';
+	else if (n_sclass == N_DATA)
+		type = 'd';
+	else if (n_sclass == N_BSS)
+		type = 'b';
+	else
+		type = 'u';
+	if ((stbl->n_sclass & N_CLASS) == C_EXT) type += 'A' - 'a';
+	strncpy(name, stbl->n_name, (size_t)8);
+	if (d_flag) {
+		/* Offsets in decimal. */
+		if (o_flag) 
+		       printf("%s:%08ld %c %s\n",file,stbl->n_value,type,name);
+		else
+		       printf("%08ld %c %s\n", stbl->n_value, type, name);
+	} else {
+		/* Offsets in hex. */
+		if (o_flag) 
+		       printf("%s:%08lx %c %s\n",file,stbl->n_value,type,name);
+		else
+		       printf("%08lx %c %s\n", stbl->n_value, type, name);
+	}
+  }
+}
Index: /trunk/minix/commands/simple/nonamed.c
===================================================================
--- /trunk/minix/commands/simple/nonamed.c	(revision 9)
+++ /trunk/minix/commands/simple/nonamed.c	(revision 9)
@@ -0,0 +1,2173 @@
+/*	nonamed - Not a name daemon, but plays one on TV.
+ *							Author: Kees J. Bot
+ *								29 Nov 1994
+ */
+static const char version[] = "2.7";
+
+/* Use the file reading gethostent() family of functions. */
+#define sethostent	_sethostent
+#define gethostent	_gethostent
+#define endhostent	_endhostent
+
+#define nil ((void*)0)
+#include <sys/types.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <limits.h>
+#include <signal.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/asynchio.h>
+#include <net/hton.h>
+#include <net/netlib.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/nameser.h>
+#include <net/gen/resolv.h>
+#include <net/gen/netdb.h>
+#include <net/gen/socket.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/udp_io.h>
+#include <net/gen/dhcp.h>
+
+#include <minix/paths.h>
+
+#define HTTL	  	3600L	/* Default time to live for /etc/hosts data. */
+#define SHORT_TIMEOUT	   2	/* If you expect an answer soon. */
+#define MEDIUM_TIMEOUT	   4	/* Soon, but not that soon. */
+#define LONG_TIMEOUT	 300	/* For stream connections to a real named. */
+#define N_IDS		 256	/* Keep track of this many queries. */
+#define N_DATAMAX (4096*sizeof(char *))	/* Default response cache size. */
+#define N_NAMEDS	   8	/* Max # name daemons we can keep track of. */
+#define NO_FD		(-1)	/* No name daemon channel here. */
+#define T_NXD	((u16_t) -1)	/* A "type" signalling a nonexistent domain. */
+
+/* Can't do async I/O under standard Minix, so forget about TCP. */
+#define DO_TCP (__minix_vmd || !__minix)
+
+/* Host data, file to store our process id in, our cache, DHCP's cache. */
+static char HOSTS[]=	_PATH_HOSTS;
+static char PIDFILE[]=	"/usr/run/nonamed.pid";
+static char NNCACHE[]=	"/usr/adm/nonamed.cache";
+static char DHCPCACHE[]= _PATH_DHCPCACHE;
+
+/* Magic string to head the cache file. */
+static char MAGIC[4]=	"NND\2";
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+#define between(a, c, z) ((unsigned) ((c) - (a)) <= (unsigned) ((z) - (a)))
+
+/* The start of time and the far future. */
+#define IMMEDIATE	((time_t) 0)
+#define NEVER		((time_t) ((time_t) -1 < 0 ? LONG_MAX : ULONG_MAX))
+
+static unsigned debug;		/* Debug level. */
+static time_t now;		/* Current time. */
+static u32_t stale;		/* Extension time for stale data. */
+static u32_t httl;		/* TTL for /etc/hosts data. */
+static int reinit, done;	/* Reinit config / program is done. */
+static int single;		/* Run single on a nondefault interface. */
+static int localonly;		/* Only accept local queries. */
+#define LOCALHOST	0x7F000001
+
+static void report(const char *label)
+{
+    fprintf(stderr, "nonamed: %s: %s\n", label, strerror(errno));
+}
+
+static void fatal(const char *label)
+{
+    report(label);
+    if (debug >= 3) { fflush(nil); abort(); }
+    exit(1);
+}
+
+static void *allocate(void *mem, size_t size)
+{
+    if ((mem= realloc(mem, size)) == nil) fatal("malloc()");
+    return mem;
+}
+
+static void deallocate(void *mem)
+{
+    free(mem);
+}
+
+static char *timegmt(time_t t)
+/* Simple "time in seconds to GMT time today" converter. */
+{
+    unsigned h, m, s;
+    static char asctime[sizeof("00:00:00")];
+
+    s= t % 60;
+    t /= 60;
+    m= t % 60;
+    t /= 60;
+    h= t % 24;
+    sprintf(asctime, "%02u:%02u:%02u", h, m, s);
+    return asctime;
+}
+
+static char *nowgmt(void)
+{
+    return timegmt(now);
+}
+
+#define PC(n)	((void) sizeof(char [sizeof(*(n)) == 1]), (char *) (n))
+#define namecpy(n1, n2)		strcpy(PC(n1), PC(n2))
+#define namecat(n1, n2)		strcat(PC(n1), PC(n2))
+#define namechr(n, c)		((u8_t *) strchr(PC(n), (c)))
+#define namecmp(n1, n2)		strcasecmp(PC(n1), PC(n2))
+#define namencmp(n1, n2, len)	strncasecmp(PC(n1), PC(n2), len)
+
+typedef struct dns {		/* A DNS packet. */
+	dns_hdr_t	hdr;		/* DNS header. */
+	u8_t		data[PACKETSZ - sizeof(dns_hdr_t)];	/* DNS data. */
+} dns_t;
+
+/* Addres of DNS packet to octet address, or vv. */
+#define dns2oct(dp)		((u8_t *) (dp))
+#define oct2dns(dp)		((dns_t *) (dp))
+
+typedef struct query {		/* One cached answer to a query. */
+	struct query	*less;		/* Less recently used. */
+	struct query	*more;		/* More recently used. */
+	time_t		age;		/* Time it was added. */
+	time_t		stale;		/* Time it goes stale by TTL. */
+	u16_t		usage;		/* Counts of queries answered. */
+	u8_t		flags;		/* QF_REFRESH. */
+	size_t		size;		/* Size of DNS packet. */
+	dns_t		dns;		/* Answer to query as a DNS packet. */
+} query_t;
+
+#define QF_REFRESH	0x01		/* This stale data must be refreshed. */
+#define QU_SHIFT	1		/* To shift usage by when evicting. */
+
+/* Size of new query_t or existing query_t. */
+#define query_allocsize(dnssize)	(offsetof(query_t, dns) + (dnssize))
+#define query_size(qp)			query_allocsize((qp)->size)
+
+static query_t *mru, *lru;	/* Most and least recently used answers. */
+static int q_refresh;		/* Set when an entry needs refreshing. */
+
+static void pack16(u8_t *buf, u16_t s)
+/* Pack a 16 bit value into a byte array. */
+{
+    buf[0]= ((u8_t *) &s)[0];
+    buf[1]= ((u8_t *) &s)[1];
+}
+
+static void pack32(u8_t *buf, u32_t l)
+/* Pack a 32 bit value into a byte array. */
+{
+    buf[0]= ((u8_t *) &l)[0];
+    buf[1]= ((u8_t *) &l)[1];
+    buf[2]= ((u8_t *) &l)[2];
+    buf[3]= ((u8_t *) &l)[3];
+}
+
+static u16_t upack16(u8_t *buf)
+/* Unpack a 16 bit value from a byte array. */
+{
+    u16_t s;
+
+    ((u8_t *) &s)[0]= buf[0];
+    ((u8_t *) &s)[1]= buf[1];
+    return s;
+}
+
+static u32_t upack32(u8_t *buf)
+/* Unpack a 32 bit value from a byte array. */
+{
+    u32_t l;
+
+    ((u8_t *) &l)[0]= buf[0];
+    ((u8_t *) &l)[1]= buf[1];
+    ((u8_t *) &l)[2]= buf[2];
+    ((u8_t *) &l)[3]= buf[3];
+    return l;
+}
+
+/* Encoding of RRs: i(paddr), d(omain), l(ong), c(har), s(tring), (s)h(ort). */
+static char *encoding[] = {
+	"c*",		/* anything unknown is c* */
+	"i",		/* A */
+	"d",		/* NS */
+	"d",		/* MD */
+	"d",		/* MF */
+	"d",		/* CNAME */
+	"ddlllll",	/* SOA */
+	"d",		/* MB */
+	"d",		/* MG */
+	"d",		/* MR */
+	"c*",		/* NULL */
+	"icc*",		/* WKS */
+	"d",		/* PTR */
+	"ss",		/* HINFO */
+	"dd",		/* MINFO */
+	"hd",		/* MX */
+	"s*",		/* TXT */
+};
+
+static char *itoa(char *fmt, u32_t i)
+{
+    static char output[32 + 3 * sizeof(i)];
+
+    sprintf(output, fmt, (unsigned long) i);
+    return output;
+}
+
+static char *classname(unsigned class)
+/* Class name of a resource record, for debug purposes. */
+{
+    static char *classes[] = { "IN", "CS", "CHAOS", "HS" };
+
+    if ((class - C_IN) < arraysize(classes)) return classes[class - C_IN];
+    return itoa("C_%u", class);
+}
+
+static char *typename(unsigned type)
+/* Type name of a resource record, for debug purposes. */
+{
+    static char type_A[][6] = {
+	"A", "NS", "MD", "MF", "CNAME", "SOA", "MB", "MG", "MR", "NULL",
+	"WKS", "PTR", "HINFO", "MINFO", "MX", "TXT",
+    };
+    static char type_AXFR[][6] = {
+	"AXFR", "MAILB", "MAILA", "ANY",
+    };
+    if ((type - T_A) < arraysize(type_A)) return type_A[type - T_A];
+    if ((type - T_AXFR) < arraysize(type_AXFR)) return type_AXFR[type - T_AXFR];
+    return itoa("T_%u", type);
+}
+
+static int print_qrr(dns_t *dp, size_t size, u8_t *cp0, int q)
+/* Print a query (q) or resource record (!q) from 'cp0' in a DNS packet for
+ * debug purposes.  Return number of bytes skipped or -1 on error.
+ */
+{
+    u8_t name[MAXDNAME+1];
+    u8_t *cp;
+    char *ep;
+    u8_t *dlim, *rlim;
+    u16_t type, class, rdlength;
+    u32_t ttl;
+    int r;
+
+    cp= cp0;
+    dlim= dns2oct(dp) + size;
+    r= dn_expand(dns2oct(dp), dlim, cp, name, MAXDNAME);
+    if (r == -1) return -1;
+    cp += r;
+    if (cp + 2 * sizeof(u16_t) > dlim) return -1;
+    type= ntohs(upack16(cp));
+    cp += sizeof(u16_t);
+    class= ntohs(upack16(cp));
+    cp += sizeof(u16_t);
+    printf("%-25s", (char *) name);
+    if (q) {
+	/* We're just printing a query segment, stop right here. */
+	printf(" %8s", classname(class));
+	printf(" %-5s", typename(type));
+	return cp - cp0;
+    }
+    if (cp + sizeof(u32_t) + sizeof(u16_t) > dlim) return -1;
+    ttl= ntohl(upack32(cp));
+    cp += sizeof(u32_t);
+    rdlength= ntohs(upack16(cp));
+    cp += sizeof(u16_t);
+    if (cp + rdlength > dlim) return -1;
+    rlim = cp + rdlength;
+    printf(" %5lu", (unsigned long) ttl);
+    printf(" %s", classname(class));
+    printf(" %-5s", typename(type));
+    ep= type < arraysize(encoding) ? encoding[type] : encoding[0];
+    while (*ep != 0) {
+	switch (*ep++) {
+	case 'i':
+	    if (cp + sizeof(u32_t) > rlim) return -1;
+	    printf(" %s", inet_ntoa(upack32(cp)));
+	    cp += sizeof(u32_t);
+	    break;
+	case 'l':
+	    if (cp + sizeof(u32_t) > rlim) return -1;
+	    printf(" %ld", (long)(i32_t) ntohl(upack32(cp)));
+	    cp += sizeof(u32_t);
+	    break;
+	case 'd':
+	    r= dn_expand(dns2oct(dp), dlim, cp, name, MAXDNAME);
+	    if (r == -1) return -1;
+	    printf(" %s", (char *) name);
+	    cp += r;
+	    break;
+	case 'c':
+	    if (cp >= rlim) return -1;
+	    printf(" %02X", *cp++);
+	    break;
+	case 's':
+	    r= *cp + 1;
+	    if (cp + r > rlim) return -1;
+	    printf(" \"%.*s\"", *cp, (char *) (cp + 1));
+	    cp += r;
+	    break;
+	case 'h':
+	    if (cp + sizeof(u16_t) > rlim) return -1;
+	    printf(" %u", ntohs(upack16(cp)));
+	    cp += sizeof(u16_t);
+	    break;
+	}
+	if (*ep == '*') ep= cp < rlim ? ep-1 : ep+1;
+    }
+    return cp - cp0;
+}
+
+static void dns_tell(int indent, dns_t *dp, size_t size)
+/* Explain a DNS packet, for debug purposes. */
+{
+    u8_t *cp;
+    int r, i;
+    unsigned count[4];
+    static char label[4][4]= { "QD:", "AN:", "NS:", "AR:" };
+    static char rcodes[][9] = {
+	"NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN", "NOTIMP", "REFUSED"
+    };
+
+    if (size < sizeof(dns_hdr_t)) return;
+
+    printf("%*s", indent, "");
+    printf("DNS %s:", (dp->hdr.dh_flag1 & DHF_QR) ? "reply" : "query");
+    r= dp->hdr.dh_flag2 & DHF_RCODE;
+    printf(" %s", r < arraysize(rcodes) ? rcodes[r] : itoa("ERR_%lu", r));
+    if (dp->hdr.dh_flag1 & DHF_AA) printf(" AA");
+    if (dp->hdr.dh_flag1 & DHF_TC) printf(" TC");
+    if (dp->hdr.dh_flag1 & DHF_RD) printf(" RD");
+    if (dp->hdr.dh_flag2 & DHF_RA) printf(" RA");
+#ifdef DHF_AD
+    if (dp->hdr.dh_flag2 & DHF_AD) printf(" AD");
+    if (dp->hdr.dh_flag2 & DHF_CD) printf(" CD");
+#endif
+    fputc('\n', stdout);
+
+    count[0]= ntohs(dp->hdr.dh_qdcount);
+    count[1]= ntohs(dp->hdr.dh_ancount);
+    count[2]= ntohs(dp->hdr.dh_nscount);
+    count[3]= ntohs(dp->hdr.dh_arcount);
+    cp = dp->data;
+    for (i= 0; i < 4; i++) {
+	while (count[i] > 0) {
+	    printf("%*s", indent, "");
+	    printf(" %s ", label[i]);
+	    r= print_qrr(dp, size, cp, (i == 0));
+	    fputc('\n', stdout);
+	    if (r == -1) return;
+	    cp += r;
+	    count[i]--;
+	}
+    }
+}
+
+static u32_t dns_ttl(dns_t *dp, size_t size, u32_t delta)
+/* Compute the minimum TTL of all RRs in a DNS packet and subtract delta from
+ * all TTLs.  (We are actually only interested in the minimum (delta = 0) or
+ * the subtraction (delta > 0).  It was easier to roll this into one routine.)
+ */
+{
+    u8_t *cp, *rdp, *dlim;
+    int r, i, hasttl, hassoa;
+    unsigned type, count[4];
+    u32_t ttl, minimum, minttl;
+    unsigned rcode;
+    u8_t name[MAXDNAME+1];
+
+    hasttl= hassoa= 0;
+    minttl= 365*24*3600L;
+    dlim= dns2oct(dp) + size;
+    if (size < sizeof(dns_hdr_t)) return 0;
+
+    rcode= dp->hdr.dh_flag2 & DHF_RCODE;
+    count[0]= ntohs(dp->hdr.dh_qdcount);
+    count[1]= ntohs(dp->hdr.dh_ancount);
+    count[2]= ntohs(dp->hdr.dh_nscount);
+    count[3]= ntohs(dp->hdr.dh_arcount);
+    cp = dp->data;
+    for (i= 0; i < 4 && cp < dlim; i++) {
+	while (count[i] > 0) {
+	    r= dn_expand(dns2oct(dp), dlim, cp, name, MAXDNAME);
+	    if (r == -1) break;
+	    cp += r + 2 * sizeof(u16_t);
+	    if (i != 0) {
+		if (cp + sizeof(u32_t) + sizeof(u16_t) > dlim) break;
+		type= upack16(cp - 2 * sizeof(u16_t));
+		ttl= ntohl(upack32(cp));
+		ttl= ttl < delta ? 0 : ttl - delta;
+		if (rcode == NXDOMAIN && i == 2 && type == HTONS(T_SOA)) {
+		    rdp= cp + sizeof(u32_t) + sizeof(u16_t);
+		    r= dn_expand(dns2oct(dp), dlim, rdp, name, MAXDNAME);
+		    if (r == -1) break;
+		    rdp += r;
+		    r= dn_expand(dns2oct(dp), dlim, rdp, name, MAXDNAME);
+		    if (r == -1) break;
+		    rdp += r + 4 * sizeof(u32_t);
+		    if (rdp + sizeof(u32_t) > dlim) break;
+		    minimum= ntohl(upack32(rdp));
+		    if (ttl > minimum) ttl= minimum;
+		    hassoa= 1;
+		}
+		if (delta != 0) pack32(cp, htonl(ttl));
+		if (ttl < minttl) minttl= ttl;
+		hasttl= 1;
+		cp += sizeof(u32_t);
+		cp += sizeof(u16_t) + ntohs(upack16(cp));
+	    }
+	    count[i]--;
+	}
+    }
+    return ((rcode == NOERROR && hasttl) || (rcode == NXDOMAIN && hassoa))
+		? minttl : 0;
+}
+
+/* Total cached query data. */
+static size_t n_datamax= N_DATAMAX;
+static size_t n_data;
+
+static query_t *extract_query(query_t *qp)
+/* Take a query out of the query cache. */
+{
+    assert(qp != nil);
+    *(qp->less != nil ? &qp->less->more : &lru) = qp->more;
+    *(qp->more != nil ? &qp->more->less : &mru) = qp->less;
+    n_data -= query_size(qp);
+    return qp;
+}
+
+static query_t *get_query(u8_t *name, unsigned type)
+/* Find a query and if so remove it from the cache and return it. */
+{
+    query_t *qp, *less;
+    u8_t qname[MAXDNAME+1];
+    int r;
+
+    for (qp= mru; qp != nil; qp= less) {
+	less= qp->less;
+	if (qp->stale <= now - stale) {
+	    /* This answer has expired. */
+	    deallocate(extract_query(qp));
+	} else {
+	    r= dn_expand(dns2oct(&qp->dns), dns2oct(&qp->dns) + qp->size,
+		qp->dns.data, qname, MAXDNAME);
+	    if (r == -1) continue;
+	    if (namecmp(qname, name) == 0 && upack16(qp->dns.data+r) == type) {
+		/* Found an answer to the query. */
+		return extract_query(qp);
+	    }
+	}
+    }
+    return nil;
+}
+
+static void insert_query(query_t *qp)
+/* (Re)insert a query into the cache. */
+{
+    *(qp->less != nil ? &qp->less->more : &lru) = qp;
+    *(qp->more != nil ? &qp->more->less : &mru) = qp;
+    n_data += query_size(qp);
+
+    /* Try to delete the LRU while there is too much memory in use.  If
+     * its usage count is too high then it gets a second chance.
+     */
+    while (n_data > n_datamax && lru != nil) {
+	if ((lru->usage >>= QU_SHIFT) == 0 || lru->stale <= now - stale) {
+	    deallocate(extract_query(lru));
+	} else {
+	    lru->less= mru;	/* Make list circular. */
+	    mru->more= lru;
+	    mru= lru;		/* Move one over, making LRU the MRU. */
+	    lru= lru->more;
+	    lru->less= nil;	/* Break the circle. */
+	    mru->more= nil;
+	}
+    }
+
+    if (debug >= 2) {
+	unsigned n= 0;
+	for (qp= mru; qp != nil; qp= qp->less) n++;
+	printf("%u cached repl%s, %u bytes, sbrk(0) = %u\n",
+	    n, n == 1 ? "y" : "ies",
+	    (unsigned) n_data,
+	    (unsigned) sbrk(0));
+    }
+}
+
+static void put_query(query_t *qp)
+/* Add a new query to the cache as the MRU. */
+{
+    qp->less= mru;
+    qp->more= nil;
+    insert_query(qp);
+}
+
+static void cache2file(void)
+/* Store the cached data into the cache file. */
+{
+    FILE *fp;
+    query_t *qp;
+    u8_t data[4+1+2+2];
+    u16_t usage;
+    char newcache[sizeof(NNCACHE) + sizeof(".new")];
+
+    if (single) return;
+
+    strcpy(newcache, NNCACHE);
+    strcat(newcache, ".new");
+
+    if ((fp= fopen(newcache, "w")) == nil) {
+	if ((errno != ENOENT && errno != EROFS) || debug >= 2) report(newcache);
+	return;
+    }
+    if (debug >= 2) printf("Writing %s:\n", newcache);
+
+    /* Magic number: */
+    fwrite(MAGIC, 1, sizeof(MAGIC), fp);
+
+    for (qp= lru; qp != nil; qp= qp->more) {
+	if (qp->stale <= now - stale) continue;
+	if (debug >= 2) {
+	    printf("Usage = %u, Age = %ld, Flags = %02X:\n",
+		qp->usage, (long) (now - qp->age), qp->flags);
+	    dns_tell(2, &qp->dns, qp->size);
+	}
+	pack32(data+0, htonl(qp->age));
+	data[4]= qp->flags;
+	pack16(data+5, htons(qp->size));
+	pack16(data+7, htons(qp->usage));
+	fwrite(data, 1, sizeof(data), fp);
+	fwrite(&qp->dns, 1, qp->size, fp);
+	if (ferror(fp)) break;
+    }
+
+    if (ferror(fp) || fclose(fp) == EOF) {
+	report(newcache);
+	(void) unlink(newcache);
+	return;
+    }
+
+    if (debug >= 2) printf("mv %s %s\n", newcache, NNCACHE);
+    if (rename(newcache, NNCACHE) < 0) {
+	fprintf(stderr, "nonamed: mv %s %s: %s\n",
+	    newcache, NNCACHE, strerror(errno));
+	(void) unlink(newcache);
+    }
+}
+
+static void file2cache(void)
+/* Read cached data from the cache file. */
+{
+    query_t *qp;
+    FILE *fp;
+    u8_t data[4+1+2+2];
+    size_t dlen;
+
+    if (single) return;
+
+    if ((fp= fopen(NNCACHE, "r")) == nil) {
+	if (errno != ENOENT || debug >= 2) report(NNCACHE);
+	return;
+    }
+    if (debug >= 2) printf("Reading %s:\n", NNCACHE);
+
+    /* Magic number? */
+    fread(data, 1, sizeof(MAGIC), fp);
+    if (ferror(fp) || memcmp(MAGIC, data, sizeof(MAGIC)) != 0) goto err;
+
+    for (;;) {
+	fread(data, 1, sizeof(data), fp);
+	if (feof(fp) || ferror(fp)) break;
+	dlen= ntohs(upack16(data+5));
+	qp= allocate(nil, query_allocsize(dlen));
+	qp->age= htonl(upack32(data+0));
+	qp->flags= data[4];
+	if (qp->flags & QF_REFRESH) q_refresh= 1;
+	qp->size= dlen;
+	qp->usage= htons(upack16(data+7));
+	fread(&qp->dns, 1, qp->size, fp);
+	if (feof(fp) || ferror(fp)) {
+	    deallocate(qp);
+	    goto err;
+	}
+	qp->stale= qp->age + dns_ttl(&qp->dns, dlen, 0);
+	if (debug >= 2) {
+	    printf("Usage = %u, Age = %ld, Flags = %02X:\n",
+		qp->usage, (long) (now - qp->age), qp->flags);
+	    dns_tell(2, &qp->dns, dlen);
+	}
+	put_query(qp);
+    }
+    if (ferror(fp)) {
+    err:
+	/* The cache file did not end at EOF or is otherwise a mess. */
+	fprintf(stderr, "nonamed: %s: %s\n", NNCACHE,
+		ferror(fp) ? strerror(errno) : "Corrupt");
+	while (lru != nil) deallocate(extract_query(lru));
+    }
+    fclose(fp);
+}
+
+typedef int handler_t(void *data, int expired);
+
+/* All actions are in the form of "jobs". */
+typedef struct job {
+	struct job	*next, **prev;	/* To make a job queue. */
+	handler_t	*handler;	/* Function to handle this job. */
+	time_t		timeout;	/* Moment it times out. */
+	void		*data;		/* Data associated with the job. */
+} job_t;
+
+static job_t *queue;		/* Main job queue. */
+
+static void newjob(handler_t *handler, time_t timeout, void *data)
+/* Create a new job with the given handler, timeout time and data. */
+{
+    job_t *job, **prev;
+
+    job= allocate(nil, sizeof(*job));
+    job->handler= handler;
+    job->timeout= timeout;
+    job->data= data;
+
+    for (prev= &queue; *prev != nil; prev= &(*prev)->next) {
+	if (job->timeout < (*prev)->timeout) break;
+    }
+    job->next= *prev;
+    job->prev= prev;
+    *prev= job;
+    if (job->next != nil) job->next->prev= &job->next;
+}
+
+static int execjob(job_t *job, int expired)
+/* Execute a job by calling the handler.  Remove the job if it returns true,
+ * indicating that it is done.  Expired is set if the job timed out.  It is
+ * otherwise called to check for I/O.
+ */
+{
+    if ((*job->handler)(job->data, expired)) {
+	*job->prev= job->next;
+	if (job->next != nil) job->next->prev= job->prev;
+	deallocate(job);
+	return 1;
+    }
+    return 0;
+}
+
+static void force_expire(handler_t *handler)
+/* Force jobs to expire immediately, the named searcher for instance. */
+{
+    job_t *job, **prev= &queue;
+
+    while ((job= *prev) != nil) {
+	if (job->handler == handler && job->timeout != IMMEDIATE) {
+	    *prev= job->next;
+	    if (job->next != nil) job->next->prev= prev;
+	    newjob(job->handler, IMMEDIATE, job->data);
+	    deallocate(job);
+	} else {
+	    prev= &job->next;
+	}
+    }
+}
+
+static int nxdomain(u8_t *name)
+/* True iff the two top level components in a name are repeated in the name,
+ * or if in-addr.arpa is found within a name.  Such things happen often in a
+ * search for an already fully qualified local name.  For instance:
+ * flotsam.cs.vu.nl.cs.vu.nl.  (We don't want this at boot time.)
+ */
+{
+    u8_t *end, *top, *p;
+    size_t n;
+
+    end= namechr(name, 0);
+    top= end;
+    while (top > name && *--top != '.') {}
+    while (top > name && *--top != '.') {}
+    n= end - top;
+    p= top;
+    for (;;) {
+	if (p == name) return 0;
+	if (*--p == '.') {
+	    if (namencmp(p, top, n) == 0 && p[n] == '.') return 1;
+	    if (namencmp(p, ".in-addr.arpa.", 14) == 0) return 1;
+	}
+    }
+}
+
+typedef struct id2id {
+	u16_t		id;		/* ID of old query. */
+	u16_t		port;		/* Reply port. */
+	ipaddr_t	ip;		/* Reply address. */
+} id2id_t;
+
+static id2id_t id2id[N_IDS];
+static u16_t id_counter;
+
+static u16_t new_id(u16_t in_id, u16_t in_port, ipaddr_t in_ip)
+/* An incoming UDP query must be relabeled with a new ID before it can be
+ * send on to a real name daemon.
+ */
+{
+    id2id_t *idp;
+    u16_t id;
+
+    id= id_counter++;
+    idp= &id2id[id % N_IDS];
+    idp->id= in_id;
+    idp->port= in_port;
+    idp->ip= in_ip;
+    return htons(id);
+}
+
+static int old_id(u16_t id, u16_t *out_id, u16_t *out_port, ipaddr_t *out_ip)
+/* Translate a reply id back to the id, port, and address used in the query.
+ * Return true if the translation is possible.
+ */
+{
+    id= ntohs(id);
+    if ((u16_t) (id_counter - id) > N_IDS) {
+	/* Too old. */
+	return 0;
+    } else {
+	/* We know this one. */
+	id2id_t *idp= &id2id[id % N_IDS];
+
+	if (idp->port == 0) return 0;	/* Named is trying to fool us? */
+	*out_id= idp->id;
+	*out_port= idp->port;
+	*out_ip= idp->ip;
+	idp->port= 0;
+	return 1;
+    }
+}
+
+/* IDs used to mark my own queries to name servers, must be new_id translated
+ * to make them unique "on the wire".
+ */
+#define ID_IPSELF	HTONL(0)	/* "I did it myself" address. */
+#define ID_PROBE	HTONS(0)	/* Name server probe. */
+#define ID_REFRESH	HTONS(1)	/* Query to refresh a cache entry. */
+
+static char *tcp_device, *udp_device;	/* TCP and UDP device names. */
+static int udp_fd;			/* To send or receive UDP packets. */
+static asynchio_t asyn;			/* For I/O in progress. */
+static ipaddr_t my_ip;			/* My IP address. */
+static u16_t my_port, named_port;	/* Port numbers, normally "domain". */
+
+static ipaddr_t named[N_NAMEDS];	/* Addresses of all name servers. */
+static unsigned n_nameds;		/* Number of configured name daemons. */
+static unsigned i_named;		/* Index to current name server. */
+static int expect;			/* Set when we expect an answer. */
+static int search_ct= -1;		/* Named search count and state. */
+static int dirty;			/* True when new entry put in cache. */
+
+#define current_named()		(+named[i_named])
+#define searching()		(search_ct > 0)
+#define start_searching()	((void) (search_ct= -1))
+#define stop_searching()	((void) (search_ct= 0))
+#define expecting()		(+expect)
+#define start_expecting()	((void) (expect= 1))
+#define stop_expecting()	((void) (expect= 0))
+
+static time_t filetime(const char *file)
+/* Get the modified time of a file. */
+{
+    struct stat st;
+
+    return stat(file, &st) == 0 ? st.st_mtime : 0;
+}
+
+static void init_config(ipaddr_t ifip)
+/* Read name daemon list and other special stuff from the hosts file. */
+{
+    struct hostent *he;
+    u32_t nip, hip;
+    static time_t hosts_time, dhcp_time;
+    time_t ht, dt;
+
+    /* See if anything really changed. */
+    if (((ifip ^ HTONL(LOCALHOST)) & HTONL(0xFF000000)) == 0) ifip= my_ip;
+    ht= filetime(HOSTS);
+    dt= filetime(DHCPCACHE);
+    if (ifip == my_ip && ht == hosts_time && dt == dhcp_time) return;
+    my_ip= ifip;
+    hosts_time= ht;
+    dhcp_time= dt;
+
+    if (debug >= 2) {
+	printf("%s: I am nonamed %s at %s:%u\n",
+	    nowgmt(), version, inet_ntoa(my_ip), ntohs(my_port));
+    }
+
+    httl= HTONL(HTTL);
+    stale= 0;
+    n_nameds= 0;
+
+    if (!single) {
+	sethostent(0);
+	while ((he= gethostent()) != nil) {
+	    memcpy(&nip, he->h_addr, sizeof(u32_t));
+	    hip= ntohl(nip);
+	    if (namecmp(he->h_name, "%ttl") == 0) httl= nip;
+	    if (namecmp(he->h_name, "%stale") == 0) stale= hip;
+	    if (namecmp(he->h_name, "%memory") == 0) n_datamax= hip;
+	    if (namecmp(he->h_name, "%nameserver") == 0) {
+		if (nip != my_ip || named_port != my_port) {
+		    if (n_nameds < N_NAMEDS) named[n_nameds++]= nip;
+		}
+	    }
+	}
+	endhostent();
+    }
+
+    if (n_nameds == 0) {
+	/* No name daemons found in the host file.  What about DHCP? */
+	int fd;
+	dhcp_t d;
+	ssize_t r;
+	u8_t *data;
+	size_t len;
+
+	if ((fd= open(DHCPCACHE, O_RDONLY)) < 0) {
+	    if (errno != ENOENT) fatal(DHCPCACHE);
+	} else {
+	    while ((r= read(fd, &d, sizeof(d))) == sizeof(d)) {
+		if (d.yiaddr == my_ip) break;
+	    }
+	    if (r < 0) fatal(DHCPCACHE);
+	    close(fd);
+
+	    if (r == sizeof(d) && dhcp_gettag(&d, DHCP_TAG_DNS, &data, &len)) {
+		while (len >= sizeof(nip)) {
+		    memcpy(&nip, data, sizeof(nip));
+		    data += sizeof(nip);
+		    len -= sizeof(nip);
+		    if (nip != my_ip || named_port != my_port) {
+			if (n_nameds < N_NAMEDS) named[n_nameds++]= nip;
+		    }
+		}
+	    }
+	}
+    }
+    i_named= 0;
+}
+
+static handler_t job_save_cache, job_read_udp, job_find_named, job_expect_named;
+#if DO_TCP
+static handler_t job_setup_listen, job_listen, job_setup_connect, job_connect;
+static handler_t job_read_query, job_write_query;
+static handler_t job_read_reply, job_write_reply;
+#endif
+
+static int query_hosts(u8_t *qname, unsigned type, dns_t *dp, size_t *pdlen)
+/* Read the /etc/hosts file to try and answer an A or PTR query.  Return
+ * true iff an answer can be found, with the answer copied to *dp.
+ */
+{
+    struct hostent *he;
+    int i, r;
+    dns_t dns;
+    u8_t *domain;
+    u8_t *cp;
+    u8_t name[MAXDNAME+1];
+    u8_t *dnvec[40];
+    unsigned ancount;
+    struct hostent localhost;
+    static char *noaliases[]= { nil };
+    static ipaddr_t localaddr= HTONL(LOCALHOST);
+    static char *localaddrlist[]= { (char *) &localaddr, nil };
+
+    if (single) return 0;
+
+    /* Assume we can answer. */
+    dns.hdr.dh_flag1= DHF_QR | DHF_AA;
+    dns.hdr.dh_flag2= DHF_RA;
+    dns.hdr.dh_qdcount= HTONS(1);
+    ancount= 0;
+    dns.hdr.dh_nscount= HTONS(0);
+    dns.hdr.dh_arcount= HTONS(0);
+
+    dnvec[0]= dns2oct(&dns);
+    dnvec[1]= nil;
+    cp= dns.data;
+    r= dn_comp(qname, cp, arraysize(dns.data), dnvec, arraylimit(dnvec));
+    if (r == -1) return 0;
+    cp += r;
+    pack16(cp, type);
+    cp += sizeof(u16_t);
+    pack16(cp, HTONS(C_IN));
+    cp += sizeof(u16_t);
+
+    /* Localhost is fixed to 127.0.0.1. */
+    localhost.h_name=
+	namencmp(qname, "localhost.", 10) == 0 ? (char *) qname : "localhost";
+    localhost.h_aliases= noaliases;
+    localhost.h_addr_list= localaddrlist;
+    he= &localhost;
+
+    sethostent(0);
+    do {
+	switch (type) {
+	case HTONS(T_A):
+	    if (namecmp(qname, he->h_name) == 0) {
+	      addA:
+		r= dn_comp((u8_t *) he->h_name, cp, arraylimit(dns.data) - cp,
+		    dnvec, arraylimit(dnvec));
+		if (r == -1) return 0;
+		cp += r;
+		if (cp + 3 * sizeof(u16_t) + 2 * sizeof(u32_t)
+		    > arraylimit(dns.data)) { r= -1; break; }
+		pack16(cp, HTONS(T_A));
+		cp += sizeof(u16_t);
+		pack16(cp, HTONS(C_IN));
+		cp += sizeof(u16_t);
+		pack32(cp, httl);
+		cp += sizeof(u32_t);
+		pack16(cp, HTONS(sizeof(u32_t)));
+		cp += sizeof(u16_t);
+		memcpy(cp, he->h_addr, sizeof(u32_t));
+		cp += sizeof(u32_t);
+		ancount++;
+		break;
+	    }
+	    /*FALL THROUGH*/
+	case HTONS(T_CNAME):
+	    domain= namechr(he->h_name, '.');
+	    for (i= 0; he->h_aliases[i] != nil; i++) {
+		namecpy(name, he->h_aliases[i]);
+		if (domain != nil && namechr(name, '.') == nil) {
+		    namecat(name, domain);
+		}
+		if (namecmp(qname, name) == 0) {
+		    r= dn_comp(name, cp, arraylimit(dns.data) - cp,
+			dnvec, arraylimit(dnvec));
+		    if (r == -1) break;
+		    cp += r;
+		    if (cp + 3 * sizeof(u16_t)
+			+ 1 * sizeof(u32_t) > arraylimit(dns.data)) return 0;
+		    pack16(cp, HTONS(T_CNAME));
+		    cp += sizeof(u16_t);
+		    pack16(cp, HTONS(C_IN));
+		    cp += sizeof(u16_t);
+		    pack32(cp, httl);
+		    cp += sizeof(u32_t);
+		    /* pack16(cp, htonl(RDLENGTH)) */
+		    cp += sizeof(u16_t);
+		    r= dn_comp((u8_t *) he->h_name, cp,
+			arraylimit(dns.data) - cp,
+			dnvec, arraylimit(dnvec));
+		    if (r == -1) break;
+		    pack16(cp - sizeof(u16_t), htons(r));
+		    cp += r;
+		    ancount++;
+		    if (type == HTONS(T_A)) goto addA;	/* really wants A */
+		    break;
+		}
+	    }
+	    break;
+	case HTONS(T_PTR):
+	    if (ancount > 0) break;
+	    if (he->h_name[0] == '%') break;
+	    sprintf((char *) name, "%d.%d.%d.%d.in-addr.arpa",
+		    ((u8_t *) he->h_addr)[3],
+		    ((u8_t *) he->h_addr)[2],
+		    ((u8_t *) he->h_addr)[1],
+		    ((u8_t *) he->h_addr)[0]);
+	    if (namecmp(qname, name) == 0) {
+		r= dn_comp(name, cp, arraylimit(dns.data) - cp,
+		    dnvec, arraylimit(dnvec));
+		if (r == -1) break;
+		cp += r;
+		if (cp + 3 * sizeof(u16_t) + 1 * sizeof(u32_t)
+		    > arraylimit(dns.data)) { r= -1; break; }
+		pack16(cp, HTONS(T_PTR));
+		cp += sizeof(u16_t);
+		pack16(cp, HTONS(C_IN));
+		cp += sizeof(u16_t);
+		pack32(cp, httl);
+		cp += sizeof(u32_t);
+		/* pack16(cp, htonl(RDLENGTH)) */
+		cp += sizeof(u16_t);
+		r= dn_comp((u8_t *) he->h_name, cp,
+		    arraylimit(dns.data) - cp, dnvec, arraylimit(dnvec));
+		if (r == -1) return 0;
+		pack16(cp - sizeof(u16_t), htons(r));
+		cp += r;
+		ancount++;
+	    }
+	    break;
+	}
+    } while (r != -1 && (he= gethostent()) != nil);
+    endhostent();
+
+    if (r == -1 || ancount == 0) return 0;
+
+    dns.hdr.dh_ancount= htons(ancount);
+    memcpy(dp, &dns, *pdlen= cp - dns2oct(&dns));
+    return 1;
+}
+
+static int query_chaos(u8_t *qname, unsigned type, dns_t *dp, size_t *pdlen)
+/* Report my version.  Can't let BIND take all the credit. :-) */
+{
+    int i, n, r;
+    dns_t dns;
+    u8_t *cp;
+    u8_t *dnvec[40];
+
+    if (type != HTONS(T_TXT) || namecmp(qname, "version.bind") != 0) return 0;
+
+    dns.hdr.dh_flag1= DHF_QR | DHF_AA;
+    dns.hdr.dh_flag2= DHF_RA;
+    dns.hdr.dh_qdcount= HTONS(1);
+    dns.hdr.dh_ancount= HTONS(1);
+    dns.hdr.dh_nscount= HTONS(0);
+    dns.hdr.dh_arcount= htons(n_nameds);
+
+    dnvec[0]= dns2oct(&dns);
+    dnvec[1]= nil;
+    cp= dns.data;
+    r= dn_comp(qname, cp, arraysize(dns.data), dnvec, arraylimit(dnvec));
+    if (r == -1) return 0;
+    cp += r;
+    pack16(cp, type);
+    cp += sizeof(u16_t);
+    pack16(cp, HTONS(C_CHAOS));
+    cp += sizeof(u16_t);
+
+    r= dn_comp(qname, cp, arraylimit(dns.data) - cp, dnvec, arraylimit(dnvec));
+    if (r == -1) return 0;
+    cp += r;
+    pack16(cp, HTONS(T_TXT));
+    cp += sizeof(u16_t);
+    pack16(cp, HTONS(C_CHAOS));
+    cp += sizeof(u16_t);
+    pack32(cp, HTONL(0));
+    cp += sizeof(u32_t);
+    /* pack16(cp, htonl(RDLENGTH)) */
+    cp += sizeof(u16_t);
+    sprintf((char *) cp + 1, "nonamed %s at %s:%u",
+	    version, inet_ntoa(my_ip), ntohs(my_port));
+    r= strlen((char *) cp + 1) + 1;
+    pack16(cp - sizeof(u16_t), htons(r));
+    *cp= r-1;
+    cp += r;
+    for (n= 0, i= i_named; n < n_nameds; n++, i= (i+1) % n_nameds) {
+	r= dn_comp((u8_t *) "%nameserver", cp, arraylimit(dns.data) - cp,
+	    dnvec, arraylimit(dnvec));
+	if (r == -1) return 0;
+	cp += r;
+	if (cp + 3 * sizeof(u16_t)
+	    + 2 * sizeof(u32_t) > arraylimit(dns.data)) return 0;
+	pack16(cp, HTONS(T_A));
+	cp += sizeof(u16_t);
+	pack16(cp, HTONS(C_IN));
+	cp += sizeof(u16_t);
+	pack32(cp, HTONL(0));
+	cp += sizeof(u32_t);
+	pack16(cp, HTONS(sizeof(u32_t)));
+	cp += sizeof(u16_t);
+	memcpy(cp, &named[i], sizeof(u32_t));
+	cp += sizeof(u32_t);
+    }
+
+    memcpy(dp, &dns, *pdlen= cp - dns2oct(&dns));
+    return 1;
+}
+
+static void cache_reply(dns_t *dp, size_t dlen)
+/* Store a DNS packet in the cache. */
+{
+    int r;
+    query_t *qp, *less, *more;
+    unsigned usage;
+    u16_t type;
+    u8_t *cp;
+    u8_t name[MAXDNAME];
+    u32_t minttl;
+
+    if ((dp->hdr.dh_flag1 & (DHF_RD | DHF_TC)) != DHF_RD) return;
+    if (dp->hdr.dh_qdcount != HTONS(1)) return;
+    cp= dp->data;
+    r= dn_expand(dns2oct(dp), dns2oct(dp) + dlen, cp, name, MAXDNAME);
+    if (r == -1) return;
+    cp += r;
+    type= upack16(cp);
+    cp += sizeof(u16_t);
+    if (upack16(cp) != HTONS(C_IN)) return;
+
+    /* Delete old cached data, if any.  Note where it is in the LRU. */
+    if ((qp= get_query(name, type)) != nil) {
+	less= qp->less;
+	more= qp->more;
+	usage= qp->usage;
+	deallocate(qp);
+    } else {
+	/* Not yet in the cache. */
+	less= mru;
+	more= nil;
+	usage= 1;
+    }
+
+    /* Determine minimum TTL.  Discard if zero, never cache zero TTLs. */
+    if ((minttl= dns_ttl(dp, dlen, 0)) == 0) return;
+
+    /* Enter new reply in cache. */
+    qp= allocate(nil, query_allocsize(dlen));
+    qp->less= less;
+    qp->more= more;
+    qp->age= now;
+    qp->flags= 0;
+    qp->usage= usage;
+    qp->size= dlen;
+    memcpy(&qp->dns, dp, dlen);
+    qp->stale= qp->age + minttl;
+    insert_query(qp);
+    if (debug >= 1) printf("Answer cached\n");
+
+    /* Save the cache soon. */
+    if (!dirty) {
+	dirty= 1;
+	newjob(job_save_cache, now + LONG_TIMEOUT, nil);
+    }
+}
+
+static int job_save_cache(void *data, int expired)
+/* Some time after the cache is changed it is written back to disk. */
+{
+    if (!expired) return 0;
+    cache2file();
+    dirty= 0;
+}
+
+static int compose_reply(dns_t *dp, size_t *pdlen)
+/* Try to compose a reply to a request in *dp using the hosts file or
+ * cached data.  Return answer in *dp with its size in *pdlen.  Return true
+ * iff an answer is given.
+ */
+{
+    size_t dlen= *pdlen;
+    int r, rd;
+    query_t *qp;
+    unsigned id, type, class;
+    u8_t *cp;
+    u8_t name[MAXDNAME];
+
+    cp= dp->data;
+    r= dn_expand(dns2oct(dp), dns2oct(dp) + dlen, cp, name, MAXDNAME);
+    if (r != -1) {
+	cp += r;
+	if (cp + 2 * sizeof(u16_t) > dns2oct(dp) + dlen) {
+	    r= -1;
+	} else {
+	    type= upack16(cp);
+	    cp += sizeof(u16_t);
+	    class= upack16(cp);
+	    cp += sizeof(u16_t);
+	}
+    }
+
+    /* Remember ID and RD. */
+    id= dp->hdr.dh_id;
+    rd= dp->hdr.dh_flag1 & DHF_RD;
+
+    if (r == -1) {
+	/* Malformed query, reply "FORMERR". */
+	dp->hdr.dh_flag1 &= ~(DHF_TC);
+	dp->hdr.dh_flag1 |= DHF_QR | DHF_AA;
+	dp->hdr.dh_flag2 &= ~(DHF_UNUSED | DHF_RCODE);
+	dp->hdr.dh_flag2 |= DHF_RA | FORMERR;
+    } else
+    if (class == HTONS(C_IN) && query_hosts(name, type, dp, pdlen)) {
+	/* Answer to this query is in the hosts file. */
+	dlen= *pdlen;
+    } else
+    if (class == HTONS(C_IN) && (qp= get_query(name, type)) != nil) {
+	/* Answer to this query is present in the cache. */
+	memcpy(dp, &qp->dns, dlen= qp->size);
+	dp->hdr.dh_flag1 &= ~DHF_AA;
+	(void) dns_ttl(dp, dlen, now - qp->age);
+	if (rd) {
+	    if (qp->stale <= now) {
+		qp->flags |= QF_REFRESH;
+		q_refresh= 1;
+	    }
+	    qp->usage++;
+	}
+	put_query(qp);
+    } else
+    if (class == HTONS(C_CHAOS) && query_chaos(name, type, dp, pdlen)) {
+	/* Return our version numbers. */
+	dlen= *pdlen;
+    } else
+    if (n_nameds == 0 || nxdomain(name)) {
+	/* No real name daemon present, or this name has a repeated top level
+	 * domain sequence.  Reply "no such domain".
+	 */
+	dp->hdr.dh_flag1 &= ~(DHF_TC);
+	dp->hdr.dh_flag1 |= DHF_QR | DHF_AA;
+	dp->hdr.dh_flag2 &= ~(DHF_UNUSED | DHF_RCODE);
+	dp->hdr.dh_flag2 |= DHF_RA | NXDOMAIN;
+    } else
+    if (!rd) {
+	/* "Recursion Desired" is off, so don't bother to relay. */
+	dp->hdr.dh_flag1 &= ~(DHF_TC);
+	dp->hdr.dh_flag1 |= DHF_QR;
+	dp->hdr.dh_flag2 &= ~(DHF_UNUSED | DHF_RCODE);
+	dp->hdr.dh_flag2 |= DHF_RA | NOERROR;
+    } else {
+	/* Caller needs to consult with a real name daemon. */
+	return 0;
+    }
+
+    /* Copy ID and RD back to answer. */
+    dp->hdr.dh_id= id;
+    dp->hdr.dh_flag1 &= ~DHF_RD;
+    dp->hdr.dh_flag1 |= rd;
+    *pdlen= dlen;
+    return 1;
+}
+
+typedef struct udp_dns {	/* One DNS packet over UDP. */
+	udp_io_hdr_t	hdr;		/* UDP header (source/destination). */
+	dns_t		dns;		/* DNS packet. */
+} udp_dns_t;
+
+static void refresh_cache(void)
+/* Find a stale entry in the cache that was used to answer a query, and send
+ * a request to a name server that should refresh this entry.
+ */
+{
+    query_t *qp;
+    unsigned type;
+    int r;
+    u8_t *cp;
+    size_t dlen, ulen;
+    u8_t qname[MAXDNAME+1];
+    u8_t *dnvec[40];
+    udp_dns_t udp;
+
+    if (!q_refresh) return;
+    for (qp= lru; qp != nil; qp= qp->more) {
+	if ((qp->flags & QF_REFRESH) && qp->stale > now - stale) break;
+    }
+    if (qp == nil) {
+	q_refresh= 0;
+	return;
+    }
+
+    /* Found one to refresh. */
+    qp->flags &= ~QF_REFRESH;
+    r= dn_expand(dns2oct(&qp->dns), dns2oct(&qp->dns) + qp->size,
+	qp->dns.data, qname, MAXDNAME);
+    if (r == -1) return;
+    type= upack16(qp->dns.data+r);
+
+    dnvec[0]= dns2oct(&udp.dns);
+    dnvec[1]= nil;
+    cp= udp.dns.data;
+    r= dn_comp(qname, cp, arraysize(udp.dns.data), dnvec, arraylimit(dnvec));
+    if (r == -1) return;
+    cp += r;
+    pack16(cp, type);
+    cp += sizeof(u16_t);
+    pack16(cp, HTONS(C_IN));
+    cp += sizeof(u16_t);
+    dlen= cp - dns2oct(&udp.dns);
+
+    udp.dns.hdr.dh_id= new_id(ID_REFRESH, my_port, ID_IPSELF);
+    udp.dns.hdr.dh_flag1= DHF_RD;
+    udp.dns.hdr.dh_flag2= 0;
+    udp.dns.hdr.dh_qdcount= HTONS(1);
+    udp.dns.hdr.dh_ancount= HTONS(0);
+    udp.dns.hdr.dh_nscount= HTONS(0);
+    udp.dns.hdr.dh_arcount= HTONS(0);
+
+    udp.hdr.uih_dst_addr= current_named();
+    udp.hdr.uih_dst_port= named_port;
+    udp.hdr.uih_ip_opt_len= 0;
+    udp.hdr.uih_data_len= dlen;
+
+    if (debug >= 1) {
+	printf("Refresh to %s:%u:\n",
+	    inet_ntoa(current_named()), ntohs(named_port));
+	dns_tell(0, &udp.dns, dlen);
+    }
+    ulen= offsetof(udp_dns_t, dns) + dlen;
+    if (write(udp_fd, &udp, ulen) < 0) fatal(udp_device);
+}
+
+static int job_read_udp(void *data, int expired)
+/* Read UDP queries and replies. */
+{
+    size_t ulen, dlen;
+    static udp_dns_t udp;
+    u16_t id, port;
+    ipaddr_t ip;
+    time_t dtime;
+
+    assert(!expired);
+
+    /* Try to read a packet. */
+    ulen= asyn_read(&asyn, udp_fd, &udp, sizeof(udp));
+    dlen= ulen - offsetof(udp_dns_t, dns);
+
+    if (ulen == -1) {
+	if (errno == EINPROGRESS && !expired) return 0;
+	if (errno == EIO) fatal(udp_device);
+
+	if (debug >= 2) {
+	    printf("%s: UDP read: %s\n", nowgmt(), strerror(errno));
+	}
+    } else {
+	if (debug >= 2) {
+	    printf("%s: UDP read, %d bytes\n", nowgmt(), (int) ulen);
+	}
+    }
+
+    /* Restart this job no matter what. */
+    newjob(job_read_udp, NEVER, nil);
+
+    if (ulen < (ssize_t) (sizeof(udp_io_hdr_t) + sizeof(dns_hdr_t))) return 1;
+
+    if (debug >= 1) {
+	printf("%s:%u UDP ", inet_ntoa(udp.hdr.uih_src_addr),
+				ntohs(udp.hdr.uih_src_port));
+	dns_tell(0, &udp.dns, dlen);
+    }
+
+    /* Check, and if necessary reinitialize my configuration. */
+    init_config(udp.hdr.uih_dst_addr);
+
+    if (udp.dns.hdr.dh_flag1 & DHF_QR) {
+	/* This is a remote named reply, not a query. */
+
+	/* Response to a query previously relayed? */
+	if (!old_id(udp.dns.hdr.dh_id, &id, &port, &ip)) return 1;
+
+	if (ip == ID_IPSELF && id == ID_PROBE) {
+	    if (searching()) {
+		/* We have found a name server! */
+		int i;
+
+		/* In my list? */
+		for (i= 0; i < n_nameds; i++) {
+		    if (named[i] == udp.hdr.uih_src_addr) {
+			i_named= i;
+			if (debug >= 1) {
+			    printf("Current named = %s\n",
+				inet_ntoa(current_named()));
+			}
+			stop_searching();
+			force_expire(job_find_named);
+		    }
+		}
+	    }
+	}
+
+	/* We got an answer, so stop worrying. */
+	if (expecting()) {
+	    stop_expecting();
+	    force_expire(job_expect_named);
+	}
+
+	/* Put the information in the cache. */
+	cache_reply(&udp.dns, dlen);
+
+	/* Refresh a cached entry that was used when stale. */
+	refresh_cache();
+
+	/* Discard reply to myself. */
+	if (ip == ID_IPSELF) return 1;
+
+	/* Send the reply to the process that asked for it. */
+	udp.dns.hdr.dh_id= id;
+	udp.hdr.uih_dst_addr= ip;
+	udp.hdr.uih_dst_port= port;
+	if (debug >= 1) printf("To client %s:%u\n", inet_ntoa(ip), ntohs(port));
+    } else {
+	/* A query. */
+	if (udp.dns.hdr.dh_qdcount != HTONS(1)) return 1;
+
+	if(localonly) {
+		/* Check if it's a local query. */
+		if(ntohl(udp.hdr.uih_src_addr) != LOCALHOST) {
+		   	syslog(LOG_WARNING, "nonamed: dropped query from %s",
+		   		inet_ntoa(udp.hdr.uih_src_addr));
+		   	return 1;
+		}
+	}
+
+	/* Try to compose a reply from local data. */
+	if (compose_reply(&udp.dns, &dlen)) {
+	    udp.hdr.uih_dst_addr= udp.hdr.uih_src_addr;
+	    udp.hdr.uih_dst_port= udp.hdr.uih_src_port;
+	    udp.hdr.uih_ip_opt_len= 0;
+	    udp.hdr.uih_data_len= dlen;
+	    ulen= offsetof(udp_dns_t, dns) + dlen;
+
+	    /* Send an UDP DNS reply. */
+	    if (debug >= 1) {
+		printf("%s:%u UDP ", inet_ntoa(udp.hdr.uih_dst_addr),
+					    ntohs(udp.hdr.uih_dst_port));
+		dns_tell(0, &udp.dns, dlen);
+	    }
+	} else {
+	    /* Let a real name daemon handle the query. */
+	    udp.dns.hdr.dh_id= new_id(udp.dns.hdr.dh_id,
+				udp.hdr.uih_src_port, udp.hdr.uih_src_addr);
+	    udp.hdr.uih_dst_addr= current_named();
+	    udp.hdr.uih_dst_port= named_port;
+	    if (!expecting()) {
+		start_expecting();
+		newjob(job_expect_named, now + MEDIUM_TIMEOUT, nil);
+	    }
+	    if (debug >= 1) {
+		printf("To named %s:%u\n",
+		    inet_ntoa(current_named()), ntohs(named_port));
+	    }
+	}
+    }
+    if (write(udp_fd, &udp, ulen) < 0) fatal(udp_device);
+    return 1;
+}
+
+#if DO_TCP
+
+typedef struct data_cl {	/* Data for connect or listen jobs. */
+	int		fd;		/* Open TCP channel. */
+	int		dn_fd;		/* TCP channel to the name daemon. */
+	int		retry;		/* Retrying a connect? */
+	nwio_tcpcl_t	tcpcl;		/* Flags. */
+} data_cl_t;
+
+typedef struct data_rw {	/* Data for TCP read or write jobs. */
+	int		r_fd;		/* Read from this TCP channel. */
+	int		w_fd;		/* And write to this TCP channel. */
+	struct data_rw	*rev;		/* Optional reverse TCP channel. */
+	u8_t		*buf;		/* Buffer for bytes to transfer. */
+	ssize_t		offset;		/* Offset in buf to r/w at. */
+	size_t		size;		/* Size of buf. */
+} data_rw_t;
+
+static int job_setup_listen(void *data, int expired)
+/* Set up a listening channel for TCP DNS queries. */
+{
+    data_cl_t *data_cl= data;
+    nwio_tcpconf_t tcpconf;
+    nwio_tcpopt_t tcpopt;
+    int fd;
+
+    if (!expired) return 0;
+    if (debug >= 2) printf("%s: Setup listen\n", nowgmt());
+
+    if (data_cl == nil) {
+	if ((fd= open(tcp_device, O_RDWR)) < 0) {
+	    if (errno != EMFILE) report(tcp_device);
+	    newjob(job_setup_listen, now + SHORT_TIMEOUT, nil);
+	    return 1;
+	}
+
+	tcpconf.nwtc_flags= NWTC_SHARED | NWTC_LP_SET | NWTC_UNSET_RA
+							| NWTC_UNSET_RP;
+	tcpconf.nwtc_locport= my_port;
+	if (ioctl(fd, NWIOSTCPCONF, &tcpconf) == -1) fatal(tcp_device);
+
+	tcpopt.nwto_flags= NWTO_DEL_RST;
+	if (ioctl(fd, NWIOSTCPOPT, &tcpopt) == -1) fatal(tcp_device);
+
+	data_cl= allocate(nil, sizeof(*data_cl));
+	data_cl->fd= fd;
+	data_cl->tcpcl.nwtcl_flags= 0;
+    }
+    /* And listen. */
+    newjob(job_listen, NEVER, data_cl);
+    return 1;
+}
+
+static int job_listen(void *data, int expired)
+/* A connection on the TCP DNS query channel. */
+{
+    data_cl_t *data_cl= data;
+
+    /* Wait for a client. */
+    if (asyn_ioctl(&asyn, data_cl->fd, NWIOTCPLISTEN, &data_cl->tcpcl) < 0) {
+	if (errno == EINPROGRESS) return 0;
+	report(tcp_device);
+
+	/* Try again after a short time. */
+	newjob(job_setup_listen, now + SHORT_TIMEOUT, data_cl);
+	return 1;
+    }
+    if (debug >= 2) printf("%s: Listen\n", nowgmt());
+
+    /* Immediately resume listening. */
+    newjob(job_setup_listen, IMMEDIATE, nil);
+
+    /* Set up a connect to the real name daemon. */
+    data_cl->retry= 0;
+    newjob(job_setup_connect, IMMEDIATE, data_cl);
+    return 1;
+}
+
+static void start_relay(int fd, int dn_fd)
+/* Start one or two read jobs after job_setup_connect() or job_connect(). */
+{
+    data_rw_t *query;	/* Client to DNS daemon relay. */
+    data_rw_t *reply;	/* DNS daemon to client relay. */
+
+    query= allocate(nil, sizeof(*query));
+    query->r_fd= fd;
+    query->buf= allocate(nil, sizeof(u16_t));
+    query->offset= 0;
+    query->size= sizeof(u16_t);
+    if (dn_fd == NO_FD) {
+	/* Answer mode. */
+	query->w_fd= fd;
+	query->rev= nil;
+    } else {
+	/* Relay mode. */
+	reply= allocate(nil, sizeof(*reply));
+	reply->r_fd= dn_fd;
+	reply->w_fd= fd;
+	reply->buf= allocate(nil, sizeof(u16_t));
+	reply->offset= 0;
+	reply->size= sizeof(u16_t);
+	reply->rev= query;
+	query->w_fd= dn_fd;
+	query->rev= reply;
+	newjob(job_read_reply, now + LONG_TIMEOUT, reply);
+    }
+    newjob(job_read_query, now + LONG_TIMEOUT, query);
+}
+
+static void close_relay(data_rw_t *data_rw)
+/* Close a relay channel. */
+{
+    if (data_rw->rev != nil) {
+	/* Other end still active, signal EOF. */
+	(void) ioctl(data_rw->w_fd, NWIOTCPSHUTDOWN, nil);
+	data_rw->rev->rev= nil;
+    } else {
+	/* Close both ends down. */
+	asyn_close(&asyn, data_rw->r_fd);
+	close(data_rw->r_fd);
+	if (data_rw->w_fd != data_rw->r_fd) {
+	    asyn_close(&asyn, data_rw->w_fd);
+	    close(data_rw->w_fd);
+	}
+    }
+    deallocate(data_rw->buf);
+    deallocate(data_rw);
+}
+
+static int job_setup_connect(void *data, int expired)
+/* Set up a connect for a TCP channel to the real name daemon. */
+{
+    nwio_tcpconf_t tcpconf;
+    int dn_fd;
+    data_cl_t *data_cl= data;
+
+    if (!expired) return 0;
+    if (debug >= 2) printf("%s: Setup connect\n", nowgmt());
+
+    if (n_nameds == 0) {
+	/* No name daemons to relay to, answer myself. */
+	start_relay(data_cl->fd, NO_FD);
+	deallocate(data_cl);
+	return 1;
+    }
+
+    if ((dn_fd= open(tcp_device, O_RDWR)) < 0) {
+	if (errno != EMFILE) report(tcp_device);
+	if (++data_cl->retry < 5) {
+	    /* Retry. */
+	    newjob(job_setup_connect, now + SHORT_TIMEOUT, data_cl);
+	} else {
+	    /* Reply myself (bound to fail). */
+	    start_relay(data_cl->fd, NO_FD);
+	    deallocate(data_cl);
+	}
+	return 1;
+    }
+
+    tcpconf.nwtc_flags= NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
+    tcpconf.nwtc_remaddr= current_named();
+    tcpconf.nwtc_remport= named_port;
+    if (ioctl(dn_fd, NWIOSTCPCONF, &tcpconf) == -1) fatal(tcp_device);
+
+    /* And connect. */
+    data_cl->dn_fd= dn_fd;
+    data_cl->tcpcl.nwtcl_flags= 0;
+    newjob(job_connect, NEVER, data_cl);
+    return 1;
+}
+
+static int job_connect(void *data, int expired)
+/* Connect to a TCP DNS query channel. */
+{
+    data_cl_t *data_cl= data;
+
+    /* Try to connect. */
+    if (asyn_ioctl(&asyn, data_cl->dn_fd, NWIOTCPCONN, &data_cl->tcpcl) < 0) {
+	if (errno == EINPROGRESS) return 0;
+	if (errno == EIO) fatal(tcp_device);
+
+	/* Connection refused. */
+	if (debug >= 2) printf("%s: Connect: %s\n", nowgmt(), strerror(errno));
+	asyn_close(&asyn, data_cl->dn_fd);
+	close(data_cl->dn_fd);
+	data_cl->dn_fd= NO_FD;
+	if (++data_cl->retry < 5) {
+	    /* Search a new name daemon. */
+	    if (!searching()) {
+		start_searching();
+		force_expire(job_find_named);
+	    }
+	    newjob(job_setup_connect, NEVER, data_cl);
+	    return 1;
+	}
+	/* Reply with a failure eventually. */
+    }
+    if (debug >= 2) printf("%s: Connect\n", nowgmt());
+
+    /* Read the query from the user, send on to the name daemon, etc. */
+    start_relay(data_cl->fd, data_cl->dn_fd);
+    deallocate(data_cl);
+    return 1;
+}
+
+static void tcp_dns_tell(int fd, u8_t *buf)
+/* Tell about a DNS packet on a TCP channel. */
+{
+    nwio_tcpconf_t tcpconf;
+
+    if (ioctl(fd, NWIOGTCPCONF, &tcpconf) < 0) {
+	printf("??\?:?? TCP ");
+    } else {
+	printf("%s:%u TCP ", inet_ntoa(tcpconf.nwtc_remaddr),
+				ntohs(tcpconf.nwtc_remport));
+    }
+    dns_tell(0, oct2dns(buf + sizeof(u16_t)), ntohs(upack16(buf)));
+}
+
+static int job_read_query(void *data, int expired)
+/* Read TCP queries from the client. */
+{
+    data_rw_t *data_rw= data;
+    ssize_t count;
+
+    /* Try to read count bytes. */
+    count= asyn_read(&asyn, data_rw->r_fd,
+				data_rw->buf + data_rw->offset,
+				data_rw->size - data_rw->offset);
+
+    if (count < 0) {
+	if (errno == EINPROGRESS && !expired) return 0;
+	if (errno == EIO) fatal(tcp_device);
+
+	/* Remote end is late, or an error occurred. */
+	if (debug >= 2) {
+	    printf("%s: TCP read query: %s\n", nowgmt(), strerror(errno));
+	}
+	close_relay(data_rw);
+	return 1;
+    }
+
+    if (debug >= 2) {
+	printf("%s: TCP read query, %d/%u bytes\n",
+	    nowgmt(), data_rw->offset + count, data_rw->size);
+    }
+    if (count == 0) {
+	/* EOF. */
+	close_relay(data_rw);
+	return 1;
+    }
+    data_rw->offset += count;
+    if (data_rw->offset == data_rw->size) {
+	data_rw->size= sizeof(u16_t) + ntohs(upack16(data_rw->buf));
+	if (data_rw->size < sizeof(u16_t)) {
+	    /* Malformed. */
+	    close_relay(data_rw);
+	    return 1;
+	}
+	if (data_rw->offset < data_rw->size) {
+	    /* Query not complete, read more. */
+	    data_rw->buf= allocate(data_rw->buf, data_rw->size);
+	    newjob(job_read_query, now + LONG_TIMEOUT, data_rw);
+	    return 1;
+	}
+    }
+
+    if (data_rw->size < sizeof(u16_t) + sizeof(dns_hdr_t)) {
+	close_relay(data_rw);
+	return 1;
+    }
+    if (debug >= 1) tcp_dns_tell(data_rw->r_fd, data_rw->buf);
+
+    /* Relay or reply. */
+    if (data_rw->w_fd != data_rw->r_fd) {
+	/* We have a real name daemon to do the work. */
+	data_rw->offset= 0;
+	newjob(job_write_query, now + LONG_TIMEOUT, data_rw);
+    } else {
+	/* No real name daemons or none reachable, so use the hosts file. */
+	dns_t *dp;
+	size_t dlen;
+
+	if (data_rw->size < sizeof(u16_t) + PACKETSZ) {
+	    data_rw->buf= allocate(data_rw->buf, sizeof(u16_t) + PACKETSZ);
+	}
+
+	/* Build a reply packet. */
+	dp= oct2dns(data_rw->buf + sizeof(u16_t));
+	dlen= data_rw->size - sizeof(u16_t);
+	if (!compose_reply(dp, &dlen)) {
+	    /* We're told to ask a name daemon, but that won't work. */
+	    close_relay(data_rw);
+	    return 1;
+	}
+
+	/* Start a reply write. */
+	pack16(data_rw->buf, htons(dlen));
+	data_rw->size= sizeof(u16_t) + dlen;
+	data_rw->buf= allocate(data_rw->buf, data_rw->size);
+	data_rw->offset= 0;
+	newjob(job_write_reply, now + LONG_TIMEOUT, data_rw);
+    }
+    return 1;
+}
+
+static int job_write_query(void *data, int expired)
+/* Relay a TCP query to the name daemon. */
+{
+    data_rw_t *data_rw= data;
+    ssize_t count;
+
+    /* Try to write count bytes to the name daemon. */
+    count= asyn_write(&asyn, data_rw->w_fd,
+				data_rw->buf + data_rw->offset,
+				data_rw->size - data_rw->offset);
+
+    if (count <= 0) {
+	if (errno == EINPROGRESS && !expired) return 0;
+	if (errno == EIO) fatal(tcp_device);
+
+	/* A write expired or failed (usually a broken connection.) */
+	if (debug >= 2) {
+	    printf("%s: TCP write query: %s\n", nowgmt(), strerror(errno));
+	}
+	close_relay(data_rw);
+	return 1;
+    }
+
+    if (debug >= 2) {
+	printf("%s: TCP write query, %d/%u bytes\n",
+	    nowgmt(), data_rw->offset + count, data_rw->size);
+    }
+    data_rw->offset += count;
+    if (data_rw->offset < data_rw->size) {
+	/* Partial write, continue. */
+	newjob(job_write_query, now + LONG_TIMEOUT, data_rw);
+	return 1;
+    }
+    if (debug >= 1) tcp_dns_tell(data_rw->w_fd, data_rw->buf);
+
+    /* Query fully send on, go read more queries. */
+    data_rw->offset= 0;
+    data_rw->size= sizeof(u16_t);
+    newjob(job_read_query, now + LONG_TIMEOUT, data_rw);
+    return 1;
+}
+
+static int job_read_reply(void *data, int expired)
+/* Read a TCP reply from the real name daemon. */
+{
+    data_rw_t *data_rw= data;
+    ssize_t count;
+
+    /* Try to read count bytes. */
+    count= asyn_read(&asyn, data_rw->r_fd,
+				data_rw->buf + data_rw->offset,
+				data_rw->size - data_rw->offset);
+
+    if (count < 0) {
+	if (errno == EINPROGRESS && !expired) return 0;
+	if (errno == EIO) fatal(tcp_device);
+
+	/* Remote end is late, or an error occurred. */
+	if (debug >= 2) {
+	    printf("%s: TCP read reply: %s\n", nowgmt(), strerror(errno));
+	}
+	close_relay(data_rw);
+	return 1;
+    }
+
+    if (debug >= 2) {
+	printf("%s: TCP read reply, %d/%u bytes\n",
+	    nowgmt(), data_rw->offset + count, data_rw->size);
+    }
+    if (count == 0) {
+	/* EOF. */
+	close_relay(data_rw);
+	return 1;
+    }
+    data_rw->offset += count;
+    if (data_rw->offset == data_rw->size) {
+	data_rw->size= sizeof(u16_t) + ntohs(upack16(data_rw->buf));
+	if (data_rw->size < sizeof(u16_t)) {
+	    /* Malformed. */
+	    close_relay(data_rw);
+	    return 1;
+	}
+	if (data_rw->offset < data_rw->size) {
+	    /* Reply not complete, read more. */
+	    data_rw->buf= allocate(data_rw->buf, data_rw->size);
+	    newjob(job_read_reply, now + LONG_TIMEOUT, data_rw);
+	    return 1;
+	}
+    }
+    if (debug >= 1) tcp_dns_tell(data_rw->r_fd, data_rw->buf);
+
+    /* Reply fully read, send it on. */
+    data_rw->offset= 0;
+    newjob(job_write_reply, now + LONG_TIMEOUT, data_rw);
+    return 1;
+}
+
+static int job_write_reply(void *data, int expired)
+/* Send a TCP reply to the client. */
+{
+    data_rw_t *data_rw= data;
+    ssize_t count;
+
+    /* Try to write count bytes to the client. */
+    count= asyn_write(&asyn, data_rw->w_fd,
+				data_rw->buf + data_rw->offset,
+				data_rw->size - data_rw->offset);
+
+    if (count <= 0) {
+	if (errno == EINPROGRESS && !expired) return 0;
+	if (errno == EIO) fatal(tcp_device);
+
+	/* A write expired or failed (usually a broken connection.) */
+	if (debug >= 2) {
+	    printf("%s: TCP write reply: %s\n", nowgmt(), strerror(errno));
+	}
+	close_relay(data_rw);
+	return 1;
+    }
+
+    if (debug >= 2) {
+	printf("%s: TCP write reply, %d/%u bytes\n",
+	    nowgmt(), data_rw->offset + count, data_rw->size);
+    }
+    data_rw->offset += count;
+    if (data_rw->offset < data_rw->size) {
+	/* Partial write, continue. */
+	newjob(job_write_reply, now + LONG_TIMEOUT, data_rw);
+	return 1;
+    }
+    if (debug >= 1) tcp_dns_tell(data_rw->w_fd, data_rw->buf);
+
+    /* Reply fully send on, go read more replies (or queries). */
+    data_rw->offset= 0;
+    data_rw->size= sizeof(u16_t);
+    newjob(data_rw->w_fd != data_rw->r_fd ? job_read_reply : job_read_query,
+		now + LONG_TIMEOUT, data_rw);
+    return 1;
+}
+#else /* !DO_TCP */
+
+static int job_dummy(void *data, int expired)
+{
+    return 1;
+}
+#define job_setup_listen	job_dummy
+#define job_setup_connect	job_dummy
+#endif /* !DO_TCP */
+
+static void named_probe(ipaddr_t ip)
+/* Send a probe to a name daemon, like 'host -r -t ns . <ip>'. */
+{
+    udp_dns_t udp;
+#   define dlen (offsetof(dns_t, data) + 5)
+#   define ulen (offsetof(udp_dns_t, dns) + dlen)
+
+    /* Send a simple DNS query that all name servers can answer easily:
+     * "What are the name servers for the root domain?"
+     */
+    udp.dns.hdr.dh_id= new_id(ID_PROBE, my_port, ID_IPSELF);
+    udp.dns.hdr.dh_flag1= 0;
+    udp.dns.hdr.dh_flag2= 0;
+    udp.dns.hdr.dh_qdcount= HTONS(1);
+    udp.dns.hdr.dh_ancount= HTONS(0);
+    udp.dns.hdr.dh_nscount= HTONS(0);
+    udp.dns.hdr.dh_arcount= HTONS(0);
+
+    udp.dns.data[0] = 0;	/* Null name. */
+    pack16(udp.dns.data+1, HTONS(T_NS));
+    pack16(udp.dns.data+3, HTONS(C_IN));
+    if (debug >= 1) {
+	printf("PROBE %s ", inet_ntoa(ip));
+	dns_tell(0, &udp.dns, dlen);
+    }
+
+    udp.hdr.uih_dst_addr= ip;
+    udp.hdr.uih_dst_port= named_port;
+    udp.hdr.uih_ip_opt_len= 0;
+    udp.hdr.uih_data_len= dlen;
+
+    if (write(udp_fd, &udp, ulen) < 0) fatal(udp_device);
+#undef dlen
+#undef ulen
+}
+
+static int job_find_named(void *data, int expired)
+/* Look for a real name daemon to answer real DNS queries. */
+{
+    if (!expired) return 0;
+    if (debug >= 2) printf("%s: Find named\n", nowgmt());
+
+    /* New search? */
+    if (search_ct < 0) {
+	search_ct= n_nameds;
+	i_named= -1;
+    }
+
+    if (--search_ct < 0) {
+	/* Forced end of search (named response!), or end of search with
+	 * nothing found.  Search again after a long time.
+	 */
+	newjob(job_find_named,
+	    (stale > 0 || i_named > 0) ? now + LONG_TIMEOUT : NEVER, nil);
+	force_expire(job_setup_connect);
+	return 1;
+    }
+
+    /* Send a named probe. */
+    i_named= (i_named+1) % n_nameds;
+    named_probe(current_named());
+
+    /* Schedule the next call. */
+    newjob(job_find_named, now + SHORT_TIMEOUT, nil);
+    return 1;
+}
+
+static int job_expect_named(void *data, int expired)
+/* The real name server is expected to answer by now. */
+{
+    if (!expired) return 0;
+    if (debug >= 2) printf("%s: Expect named\n", nowgmt());
+
+    if (expecting() && !searching()) {
+	/* No answer yet, start searching. */
+	start_searching();
+	force_expire(job_find_named);
+    }
+    return 1;
+}
+
+static void sig_handler(int sig)
+/* A signal forces a search for a real name daemon, etc. */
+{
+    switch (sig) {
+    case SIGINT:
+    case SIGTERM:	done= 1;		break;
+    case SIGHUP:	reinit= 1;		break;
+    case SIGUSR1:	debug++;		break;
+    case SIGUSR2:	debug= 0;		break;
+    }
+}
+
+static void usage(void)
+{
+    fprintf(stderr, "Usage: nonamed [-qs] [-d[level]] [-p port]\n");
+    exit(1);
+}
+
+int main(int argc, char **argv)
+{
+    job_t *job;
+    nwio_udpopt_t udpopt;
+    int i;
+    struct servent *servent;
+    struct sigaction sa;
+    FILE *fp;
+    int quit= 0;
+
+    /* Debug output must be line buffered. */
+    setvbuf(stdout, nil, _IOLBF, 0);
+
+    /* DNS service port number? */
+    if ((servent= getservbyname("domain", nil)) == nil) {
+	fprintf(stderr, "nonamed: \"domain\": unknown service\n");
+	exit(1);
+    }
+    my_port= servent->s_port;
+    named_port= servent->s_port;
+
+    i= 1;
+    while (i < argc && argv[i][0] == '-') {
+	char *opt= argv[i++] + 1, *end;
+
+	if (opt[0] == '-' && opt[1] == 0) break;
+
+	switch (*opt++) {
+	case 'd':		/* Debug level. */
+	    debug= 1;
+	    if (between('0', *opt, '9')) debug= strtoul(opt, &opt, 10);
+	    break;
+	case 'p':		/* Port to listen to (for testing.) */
+	    if (*opt == 0) {
+		if (i == argc) usage();
+		opt= argv[i++];
+	    }
+	    my_port= htons(strtoul(opt, &end, 0));
+	    if (opt == end || *end != 0) usage();
+	    opt= end;
+	    break;
+	case 's':
+	    single= 1;
+	    break;
+	case 'q':		/* Quit after printing cache contents. */
+	    quit= 1;
+	    break;
+	case 'L':
+	    localonly= 1;
+	    break;
+	default:
+	    usage();
+	}
+    }
+    if (i != argc) usage();
+
+    if (quit) {
+	/* Oops, just having a look at the cache. */
+	debug= 2;
+	now= time(nil);
+	n_datamax= -1;
+	file2cache();
+	return 0;
+    }
+
+    /* Don't die on broken pipes, reinitialize on hangup, etc. */
+    sa.sa_handler= SIG_IGN;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags= 0;
+    sigaction(SIGPIPE, &sa, nil);
+    sa.sa_handler= sig_handler;
+    sigaction(SIGINT, &sa, nil);
+    sigaction(SIGHUP, &sa, nil);
+    sigaction(SIGUSR1, &sa, nil);
+    sigaction(SIGUSR2, &sa, nil);
+    sigaction(SIGTERM, &sa, nil);
+
+    /* TCP and UDP device names. */
+    if ((tcp_device= getenv("TCP_DEVICE")) == nil) tcp_device= TCP_DEVICE;
+    if ((udp_device= getenv("UDP_DEVICE")) == nil) udp_device= UDP_DEVICE;
+
+    /* Open an UDP channel for incoming DNS queries. */
+    if ((udp_fd= open(udp_device, O_RDWR)) < 0) fatal(udp_device);
+
+    udpopt.nwuo_flags= NWUO_EXCL | NWUO_LP_SET | NWUO_EN_LOC | NWUO_DI_BROAD
+		| NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL | NWUO_DI_IPOPT;
+    udpopt.nwuo_locport= my_port;
+    if (ioctl(udp_fd, NWIOSUDPOPT, &udpopt) == -1
+	|| ioctl(udp_fd, NWIOGUDPOPT, &udpopt) == -1
+    ) {
+	fatal(udp_device);
+    }
+
+    /* The current time is... */
+    now= time(nil);
+
+    /* Read configuration and data cached by the previous nonamed. */
+    init_config(udpopt.nwuo_locaddr);
+    file2cache();
+
+    if (!single) {
+	/* Save process id. */
+	if ((fp= fopen(PIDFILE, "w")) != nil) {
+	    fprintf(fp, "%u\n", (unsigned) getpid());
+	    fclose(fp);
+	}
+    }
+
+    /* Jobs that start the ball rolling. */
+    newjob(job_read_udp, NEVER, nil);
+    newjob(job_setup_listen, IMMEDIATE, nil);
+    newjob(job_find_named, IMMEDIATE, nil);
+
+    /* Open syslog. */
+    openlog("nonamed", LOG_PID, LOG_DAEMON);
+
+    while (!done) {
+	/* There is always something in the queue. */
+	assert(queue != nil);
+
+	/* Any expired jobs? */
+	while (queue->timeout <= now) {
+	    (void) execjob(queue, 1);
+	    assert(queue != nil);
+	}
+
+	/* Check I/O jobs. */
+	for (job= queue; job != nil; job= job->next) {
+	    if (execjob(job, 0)) break;
+	}
+
+	if (queue->timeout != IMMEDIATE) {
+	    struct timeval tv, *tvp;
+
+	    if (debug >= 2) printf("%s: I/O wait", nowgmt());
+
+	    if (queue->timeout != NEVER) {
+		tv.tv_sec= queue->timeout;
+		tv.tv_usec= 0;
+		tvp= &tv;
+		if (debug >= 2) printf(" (expires %s)\n", timegmt(tv.tv_sec));
+	    } else {
+		tvp= nil;
+		if (debug >= 2) fputc('\n', stdout);
+	    }
+	    fflush(stdout);
+
+	    if (asyn_wait(&asyn, 0, tvp) < 0) {
+		if (errno != EINTR && errno != EAGAIN) fatal("fwait()");
+	    }
+	    now= time(nil);
+	}
+
+	if (reinit) {
+	    /* A hangup makes us go back to square one. */
+	    reinit= 0;
+	    if (ioctl(udp_fd, NWIOGUDPOPT, &udpopt) == -1) fatal(udp_device);
+	    init_config(udpopt.nwuo_locaddr);
+	    start_searching();
+	    force_expire(job_find_named);
+	}
+    }
+    cache2file();
+    (void) unlink(PIDFILE);
+    if (debug >= 2) printf("sbrk(0) = %u\n", (unsigned) sbrk(0));
+    return 0;
+}
Index: /trunk/minix/commands/simple/od.c
===================================================================
--- /trunk/minix/commands/simple/od.c	(revision 9)
+++ /trunk/minix/commands/simple/od.c	(revision 9)
@@ -0,0 +1,314 @@
+/* od - octal dump		   Author: Andy Tanenbaum */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+
+int bflag, cflag, dflag, oflag, xflag, hflag, vflag;
+int linenr, width, state, ever;
+int prevwds[8];
+long off;
+char buf[512], buffer[BUFSIZ];
+int next;
+int bytespresent;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(long offset, (int argc, char *argv [], int k));
+_PROTOTYPE(void dumpfile, (void));
+_PROTOTYPE(void wdump, (short *words, int k, int radix));
+_PROTOTYPE(void bdump, (char bytes [16 ], int k, int c));
+_PROTOTYPE(void byte, (int val, int c));
+_PROTOTYPE(int getwords, (short **words));
+_PROTOTYPE(int same, (short *w1, int *w2));
+_PROTOTYPE(void outword, (int val, int radix));
+_PROTOTYPE(void outnum, (int num, int radix));
+_PROTOTYPE(void addrout, (long l));
+_PROTOTYPE(char hexit, (int k));
+_PROTOTYPE(void usage, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int k, flags;
+  char *p;
+
+  /* Process flags */
+  setbuf(stdout, buffer);
+  flags = 0;
+  p = argv[1];
+  if (argc > 1 && *p == '-') {
+	/* Flags present. */
+	flags++;
+	p++;
+	while (*p) {
+		switch (*p) {
+		    case 'b':	bflag++;	break;
+		    case 'c':	cflag++;	break;
+		    case 'd':	dflag++;	break;
+		    case 'h':	hflag++;	break;
+		    case 'o':	oflag++;	break;
+		    case 'v':	vflag++;	break;	
+		    case 'x':	xflag++;	break;
+		    default:	usage();
+		}
+		p++;
+	}
+  } else {
+	oflag = 1;
+  }
+  if ((bflag | cflag | dflag | oflag | xflag) == 0) oflag = 1;
+  k = (flags ? 2 : 1);
+  if (bflag | cflag) {
+	width = 8;
+  } else if (oflag) {
+	width = 7;
+  } else if (dflag) {
+	width = 6;
+  } else {
+	width = 5;
+  }
+
+  /* Process file name, if any. */
+  p = argv[k];
+  if (k < argc && *p != '+') {
+	/* Explicit file name given. */
+	close(0);
+	if (open(argv[k], O_RDONLY) != 0) {
+		fprintf(stderr, "od: cannot open %s\n", argv[k]);
+		exit(1);
+	}
+	k++;
+  }
+
+  /* Process offset, if any. */
+  if (k < argc) {
+	/* Offset present. */
+	off = offset(argc, argv, k);
+	off = (off / 16L) * 16L;
+	lseek(0, off, SEEK_SET);
+  }
+  dumpfile();
+  addrout(off);
+  printf("\n");
+  return(0);
+}
+
+
+long offset(argc, argv, k)
+int argc;
+char *argv[];
+int k;
+{
+  int dot, radix;
+  char *p, c;
+  long val;
+
+  /* See if the offset is decimal. */
+  dot = 0;
+  p = argv[k];
+  while (*p)
+	if (*p++ == '.') dot = 1;
+
+  /* Convert offset to binary. */
+  radix = (dot ? 10 : 8);
+  val = 0;
+  p = argv[k];
+  if (*p == '+') p++;
+  while (*p != 0 && *p != '.') {
+	c = *p++;
+	if (c < '0' || c > '9') {
+		printf("Bad character in offset: %c\n", c);
+		exit(1);
+	}
+	val = radix * val + c - '0';
+  }
+
+  p = argv[k + 1];
+  if (k + 1 == argc - 1 && *p == 'b') val = 512L * val;
+  return(val);
+}
+
+
+void dumpfile()
+{
+  int k;
+  short *words;
+
+  while ((k = getwords(&words))) {	/* 'k' is # bytes read */
+	if (!vflag) {		/* ensure 'lazy' evaluation */
+		if (k == 16 && ever == 1 && same(words, prevwds)) {
+			if (state == 0) {
+				printf("*\n");
+				state = 1;
+				off += 16;
+				continue;
+			} else if (state == 1) {
+				off += 16;
+				continue;
+			}
+		}
+	}
+	addrout(off);
+	off += k;
+	state = 0;
+	ever = 1;
+	linenr = 1;
+	if (oflag) wdump(words, k, 8);
+	if (dflag) wdump(words, k, 10);
+	if (xflag) wdump(words, k, 16);
+	if (cflag) bdump((char *)words, k, (int)'c');
+	if (bflag) bdump((char *)words, k, (int)'b');
+	for (k = 0; k < 8; k++) prevwds[k] = words[k];
+	for (k = 0; k < 8; k++) words[k] = 0;
+  }
+}
+
+
+void wdump(words, k, radix)
+short *words;
+int k, radix;
+{
+  int i;
+
+  if (linenr++ != 1) printf("       ");
+  for (i = 0; i < (k + 1) / 2; i++) outword(words[i] & 0xFFFF, radix);
+  printf("\n");
+}
+
+
+void bdump(bytes, k, c)
+char bytes[16];
+int k;
+char c;
+{
+  int i;
+
+  if (linenr++ != 1) printf("       ");
+  for (i = 0; i < k; i++) byte(bytes[i] & 0377, c);
+  printf("\n");
+}
+
+void byte(val, c)
+int val;
+char c;
+{
+  if (c == 'b') {
+	printf(" ");
+	outnum(val, 7);
+	return;
+  }
+  if (val == 0)
+	printf("  \\0");
+  else if (val == '\b')
+	printf("  \\b");
+  else if (val == '\f')
+	printf("  \\f");
+  else if (val == '\n')
+	printf("  \\n");
+  else if (val == '\r')
+	printf("  \\r");
+  else if (val == '\t')
+	printf("  \\t");
+  else if (val >= ' ' && val < 0177)
+	printf("   %c", val);
+  else {
+	printf(" ");
+	outnum(val, 7);
+  }
+}
+
+
+int getwords(words)
+short **words;
+{
+  int count;
+
+  if (next >= bytespresent) {
+	bytespresent = read(0, buf, 512);
+	next = 0;
+  }
+  if (next >= bytespresent) return(0);
+  *words = (short *) &buf[next];
+  if (next + 16 <= bytespresent)
+	count = 16;
+  else
+	count = bytespresent - next;
+
+  next += count;
+  return(count);
+}
+
+int same(w1, w2)
+short *w1;
+int *w2;
+{
+  int i;
+  i = 8;
+  while (i--)
+	if (*w1++ != *w2++) return(0);
+  return(1);
+}
+
+void outword(val, radix)
+int val, radix;
+{
+/* Output 'val' in 'radix' in a field of total size 'width'. */
+
+  int i;
+
+  if (radix == 16) i = width - 4;
+  if (radix == 10) i = width - 5;
+  if (radix == 8) i = width - 6;
+  if (i == 1)
+	printf(" ");
+  else if (i == 2)
+	printf("  ");
+  else if (i == 3)
+	printf("   ");
+  else if (i == 4)
+	printf("    ");
+  outnum(val, radix);
+}
+
+
+void outnum(num, radix)
+int num, radix;
+{
+/* Output a number with all leading 0s present.  Octal is 6 places,
+ * decimal is 5 places, hex is 4 places.
+ */
+  unsigned val;
+
+  val = (unsigned) num;
+  if (radix == 8)
+	printf ("%06o", val);
+  else if (radix == 10)
+	printf ("%05u", val);
+  else if (radix == 16)
+	printf ("%04x", val);
+  else if (radix == 7) {
+  	/* special case */
+	printf ("%03o", val);
+  }
+}
+
+
+void addrout(l)
+long l;
+{
+  if (hflag == 0) {
+	printf("%07lo", l);
+  } else {
+	printf("%07lx", l);
+  }
+}
+
+
+void usage()
+{
+  fprintf(stderr, "Usage: od [-bcdhovx] [file] [ [+] offset [.] [b] ]\n");
+}
Index: /trunk/minix/commands/simple/origmkfs.c
===================================================================
--- /trunk/minix/commands/simple/origmkfs.c	(revision 9)
+++ /trunk/minix/commands/simple/origmkfs.c	(revision 9)
@@ -0,0 +1,1374 @@
+/* mkfs  -  make the MINIX filesystem	Authors: Tanenbaum et al. */
+
+/*	Authors: Andy Tanenbaum, Paul Ogilvie, Frans Meulenbroeks, Bruce Evans
+ *
+ * This program can make both version 1 and version 2 file systems, as follows:
+ *	mkfs /dev/fd0 1200	# Version 2 (default)
+ *	mkfs -1 /dev/fd0 360	# Version 1
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/dir.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include <minix/minlib.h>
+#include "../../servers/fs/const.h"
+#if (MACHINE == IBM_PC)
+#include <minix/partition.h>
+#include <minix/u64.h>
+#include <sys/ioctl.h>
+#endif
+
+#undef EXTERN
+#define EXTERN			/* get rid of EXTERN by making it null */
+#include "../../servers/fs/type.h"
+#include "../../servers/fs/super.h"
+#include <minix/fslib.h>
+
+#ifndef DOS
+#ifndef UNIX
+#define UNIX
+#endif
+#endif
+
+#undef BLOCK_SIZE
+#define BLOCK_SIZE 1024
+
+#define INODE_MAP            2
+#define MAX_TOKENS          10
+#define LINE_LEN           200
+#define BIN                  2
+#define BINGRP               2
+#define BIT_MAP_SHIFT       13
+#define N_BLOCKS         (1024L * 1024)
+#define N_BLOCKS16	  (128L * 1024)
+#define INODE_MAX       ((unsigned) 65535)
+
+/* You can make a really large file system on a 16-bit system, but the array
+ * of bits that get_block()/putblock() needs gets a bit big, so we can only
+ * prefill MAX_INIT blocks.  (16-bit fsck can't check a file system larger
+ * than N_BLOCKS16 anyway.)
+ */
+#define MAX_INIT	 (sizeof(char *) == 2 ? N_BLOCKS16 : N_BLOCKS)
+
+
+#ifdef DOS
+maybedefine O_RDONLY 4		/* O_RDONLY | BINARY_BIT */
+ maybedefine BWRITE 5		/* O_WRONLY | BINARY_BIT */
+#endif
+
+#if (MACHINE == ATARI)
+int isdev;
+#endif
+
+extern char *optarg;
+extern int optind;
+
+int next_zone, next_inode, zone_size, zone_shift = 0, zoff;
+block_t nrblocks;
+int inode_offset, lct = 0, disk, fd, print = 0, file = 0;
+unsigned int nrinodes;
+int override = 0, simple = 0, dflag;
+int donttest;			/* skip test if it fits on medium */
+char *progname;
+
+long current_time, bin_time;
+char zero[BLOCK_SIZE], *lastp;
+char umap[MAX_INIT / 8];	/* bit map tells if block read yet */
+block_t zone_map;		/* where is zone map? (depends on # inodes) */
+int inodes_per_block;
+int fs_version;
+block_t max_nrblocks;
+
+FILE *proto;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(block_t sizeup, (char *device));
+_PROTOTYPE(void super, (zone_t zones, Ino_t inodes));
+_PROTOTYPE(void rootdir, (Ino_t inode));
+_PROTOTYPE(void eat_dir, (Ino_t parent));
+_PROTOTYPE(void eat_file, (Ino_t inode, int f));
+_PROTOTYPE(void enter_dir, (Ino_t parent, char *name, Ino_t child));
+_PROTOTYPE(void incr_size, (Ino_t n, long count));
+_PROTOTYPE(PRIVATE ino_t alloc_inode, (int mode, int usrid, int grpid));
+_PROTOTYPE(PRIVATE zone_t alloc_zone, (void));
+_PROTOTYPE(void add_zone, (Ino_t n, zone_t z, long bytes, long cur_time));
+_PROTOTYPE(void add_z_1, (Ino_t n, zone_t z, long bytes, long cur_time));
+_PROTOTYPE(void add_z_2, (Ino_t n, zone_t z, long bytes, long cur_time));
+_PROTOTYPE(void incr_link, (Ino_t n));
+_PROTOTYPE(void insert_bit, (block_t block, int bit));
+_PROTOTYPE(int mode_con, (char *p));
+_PROTOTYPE(void getline, (char line[LINE_LEN], char *parse[MAX_TOKENS]));
+_PROTOTYPE(void check_mtab, (char *devname));
+_PROTOTYPE(long file_time, (int f));
+_PROTOTYPE(void pexit, (char *s));
+_PROTOTYPE(void copy, (char *from, char *to, int count));
+_PROTOTYPE(void print_fs, (void));
+_PROTOTYPE(int read_and_set, (block_t n));
+_PROTOTYPE(void special, (char *string));
+_PROTOTYPE(void get_block, (block_t n, char buf[BLOCK_SIZE]));
+_PROTOTYPE(void put_block, (block_t n, char buf[BLOCK_SIZE]));
+_PROTOTYPE(void cache_init, (void));
+_PROTOTYPE(void flush, (void));
+_PROTOTYPE(void mx_read, (int blocknr, char buf[BLOCK_SIZE]));
+_PROTOTYPE(void mx_write, (int blocknr, char buf[BLOCK_SIZE]));
+_PROTOTYPE(void dexit, (char *s, int sectnum, int err));
+_PROTOTYPE(void usage, (void));
+
+/*================================================================
+ *                    mkfs  -  make filesystem
+ *===============================================================*/
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int nread, mode, usrid, grpid, ch;
+  block_t blocks;
+  block_t i;
+  ino_t root_inum;
+  ino_t inodes;
+  zone_t zones;
+  char *token[MAX_TOKENS], line[LINE_LEN];
+  struct stat statbuf;
+
+  /* Get two times, the current time and the mod time of the binary of
+   * mkfs itself.  When the -d flag is used, the later time is put into
+   * the i_mtimes of all the files.  This feature is useful when
+   * producing a set of file systems, and one wants all the times to be
+   * identical. First you set the time of the mkfs binary to what you
+   * want, then go.
+   */
+  current_time = time((time_t *) 0);	/* time mkfs is being run */
+  stat(argv[0], &statbuf);
+  bin_time = statbuf.st_mtime;	/* time when mkfs binary was last modified */
+
+  /* Process switches. */
+  progname = argv[0];
+  blocks = 0;
+  i = 0;
+  fs_version = 2;
+  inodes_per_block = V2_INODES_PER_BLOCK(BLOCK_SIZE);
+  max_nrblocks = N_BLOCKS;
+  while ((ch = getopt(argc, argv, "1b:di:lot")) != EOF)
+	switch (ch) {
+	    case '1':
+		fs_version = 1;
+		inodes_per_block = V1_INODES_PER_BLOCK;
+		max_nrblocks = 0xFFFF;
+		break;
+	    case 'b':
+		blocks = strtoul(optarg, (char **) NULL, 0);
+		break;
+	    case 'd':
+		dflag = 1;
+		current_time = bin_time;
+		break;
+	    case 'i':
+		i = strtoul(optarg, (char **) NULL, 0);
+		break;
+	    case 'l':	print = 1;	break;
+	    case 'o':	override = 1;	break;
+	    case 't':	donttest = 1;	break;
+	    default:	usage();
+	}
+
+  /* Determine the size of the device if not specified as -b or proto. */
+  if (argc - optind == 1 && blocks == 0) blocks = sizeup(argv[optind]);
+  printf("%lu blocks\n", blocks);
+
+  /* The remaining args must be 'special proto', or just 'special' if the
+   * block size has already been specified.
+   */
+  if (argc - optind != 2 && (argc - optind != 1 || blocks == 0)) usage();
+
+  /* Check special. */
+  check_mtab(argv[optind]);
+
+  /* Check and start processing proto. */
+  optarg = argv[++optind];
+  if (optind < argc && (proto = fopen(optarg, "r")) != NULL) {
+	/* Prototype file is readable. */
+	lct = 1;
+	getline(line, token);	/* skip boot block info */
+
+	/* Read the line with the block and inode counts. */
+	getline(line, token);
+	blocks = atol(token[0]);
+	if (blocks > max_nrblocks) {
+		printf("%d > %d\n",  blocks, max_nrblocks);
+		pexit("Block count too large");
+	}
+	if (sizeof(char *) == 2 && blocks > N_BLOCKS16) {
+		fprintf(stderr,
+		"%s: warning: FS is larger than the %dM that fsck can check!\n",
+			progname, (int) (N_BLOCKS16 / (1024L * 1024)));
+	}
+	inodes = atoi(token[1]);
+
+	/* Process mode line for root directory. */
+	getline(line, token);
+	mode = mode_con(token[0]);
+	usrid = atoi(token[1]);
+	grpid = atoi(token[2]);
+  } else {
+	lct = 0;
+	if (optind < argc) {
+		/* Maybe the prototype file is just a size.  Check. */
+		blocks = strtoul(optarg, (char **) NULL, 0);
+		if (blocks == 0) pexit("Can't open prototype file");
+	}
+	if (i == 0) {
+		/* The default for inodes is 3 blocks per inode, rounded up
+		 * to fill an inode block.  Above 20M, the average files are
+		 * sure to be larger because it is hard to fill up 20M with
+		 * tiny files, so reduce the default number of inodes.  This
+		 * default can always be overridden by using the -i option.
+		 */
+		i = blocks / 3;
+		if (blocks >= 20000) i = blocks / 4;
+		if (blocks >= 40000) i = blocks / 5;
+		if (blocks >= 60000) i = blocks / 6;
+		if (blocks >= 80000) i = blocks / 7;
+		if (blocks >= 100000) i = blocks / 8;
+		i += inodes_per_block - 1;
+		i = i / inodes_per_block * inodes_per_block;
+		if (i > INODE_MAX) i = INODE_MAX;
+	}
+	if (blocks < 5) pexit("Block count too small");
+	if (blocks > max_nrblocks)  {
+		printf("%d > %d\n",  blocks, max_nrblocks);
+		pexit("Block count too large");
+	}
+	if (i < 1) pexit("Inode count too small");
+	if (i > INODE_MAX) pexit("Inode count too large");
+	inodes = (ino_t) i;
+
+	/* Make simple file system of the given size, using defaults. */
+	mode = 040777;
+	usrid = BIN;
+	grpid = BINGRP;
+	simple = 1;
+  }
+  nrblocks = blocks;
+  nrinodes = inodes;
+
+  /* Open special. */
+  special(argv[--optind]);
+
+#ifdef UNIX
+  if (!donttest) {
+	static short testb[BLOCK_SIZE / sizeof(short)];
+
+	/* Try writing the last block of partition or diskette. */
+	lseek(fd, (off_t) (blocks - 1) * BLOCK_SIZE, SEEK_SET);
+	testb[0] = 0x3245;
+	testb[1] = 0x11FF;
+	if (write(fd, (char *) testb, BLOCK_SIZE) != BLOCK_SIZE)
+		pexit("File system is too big for minor device");
+	sync();			/* flush write, so if error next read fails */
+	lseek(fd, (off_t) (blocks - 1) * BLOCK_SIZE, SEEK_SET);
+	testb[0] = 0;
+	testb[1] = 0;
+	nread = read(fd, (char *) testb, BLOCK_SIZE);
+	if (nread != BLOCK_SIZE || testb[0] != 0x3245 || testb[1] != 0x11FF)
+		pexit("File system is too big for minor device");
+	lseek(fd, (off_t) (blocks - 1) * BLOCK_SIZE, SEEK_SET);
+	testb[0] = 0;
+	testb[1] = 0;
+	if (write(fd, (char *) testb, BLOCK_SIZE) != BLOCK_SIZE)
+		pexit("File system is too big for minor device");
+	lseek(fd, 0L, SEEK_SET);
+  }
+#endif
+
+  /* Make the file-system */
+
+  cache_init();
+
+#if (MACHINE == ATARI)
+  if (isdev) {
+	char block0[BLOCK_SIZE];
+	get_block((block_t) 0, block0);
+	/* Need to read twice; first time gets an empty block */
+	get_block((block_t) 0, block0);
+	/* Zero parts of the boot block so the disk won't be
+	 * recognized as a tos disk any more. */
+	block0[0] = block0[1] = 0;	/* branch code to boot code    */
+	strncpy(&block0[2], "MINIX ", (size_t) 6);
+	block0[16] = 0;		/* number of FATS              */
+	block0[17] = block0[18] = 0;	/* number of dir entries       */
+	block0[22] = block0[23] = 0;	/* sectors/FAT                 */
+	bzero(&block0[30], 480);/* boot code                   */
+	put_block((block_t) 0, block0);
+  } else
+#endif
+
+	put_block((block_t) 0, zero);	/* Write a null boot block. */
+
+  zone_shift = 0;		/* for future use */
+  zones = nrblocks >> zone_shift;
+
+  super(zones, inodes);
+
+  root_inum = alloc_inode(mode, usrid, grpid);
+  rootdir(root_inum);
+  if (simple == 0) eat_dir(root_inum);
+
+  if (print) print_fs();
+  flush();
+  return(0);
+
+  /* NOTREACHED */
+}				/* end main */
+
+
+/*================================================================
+ *                    sizeup  -  determine device size
+ *===============================================================*/
+block_t sizeup(device)
+char *device;
+{
+  int fd;
+  struct partition entry;
+
+  if ((fd = open(device, O_RDONLY)) == -1) return 0;
+  if (ioctl(fd, DIOCGETP, &entry) == -1) entry.size = cvu64(0);
+  close(fd);
+  return div64u(entry.size, BLOCK_SIZE);
+}
+
+
+/*================================================================
+ *                 super  -  construct a superblock
+ *===============================================================*/
+
+void super(zones, inodes)
+zone_t zones;
+ino_t inodes;
+{
+  unsigned int i;
+  int inodeblks;
+  int initblks;
+
+  zone_t initzones, nrzones, v1sq, v2sq;
+  zone_t zo;
+  struct super_block *sup;
+  char buf[BLOCK_SIZE], *cp;
+
+  for (cp = buf; cp < &buf[BLOCK_SIZE]; cp++) *cp = 0;
+  sup = (struct super_block *) buf;	/* lint - might use a union */
+
+  sup->s_ninodes = inodes;
+  if (fs_version == 1) {
+	sup->s_nzones = zones;
+  } else {
+	sup->s_nzones = 0;	/* not used in V2 - 0 forces errors early */
+	sup->s_zones = zones;
+  }
+  sup->s_imap_blocks = bitmapsize((bit_t) (1 + inodes), BLOCK_SIZE);
+  sup->s_zmap_blocks = bitmapsize((bit_t) zones, BLOCK_SIZE);
+  inode_offset = sup->s_imap_blocks + sup->s_zmap_blocks + 2;
+  inodeblks = (inodes + inodes_per_block - 1) / inodes_per_block;
+  initblks = inode_offset + inodeblks;
+  initzones = (initblks + (1 << zone_shift) - 1) >> zone_shift;
+  nrzones = nrblocks >> zone_shift;
+  sup->s_firstdatazone = (initblks + (1 << zone_shift) - 1) >> zone_shift;
+  zoff = sup->s_firstdatazone - 1;
+  sup->s_log_zone_size = zone_shift;
+  if (fs_version == 1) {
+	sup->s_magic = SUPER_MAGIC;	/* identify super blocks */
+	v1sq = (zone_t) V1_INDIRECTS * V1_INDIRECTS;
+	zo = V1_NR_DZONES + (long) V1_INDIRECTS + v1sq;
+  } else {
+	sup->s_magic = SUPER_V2;/* identify super blocks */
+	v2sq = (zone_t) V2_INDIRECTS(BLOCK_SIZE) * V2_INDIRECTS(BLOCK_SIZE);
+	zo = V2_NR_DZONES + (zone_t) V2_INDIRECTS(BLOCK_SIZE) + v2sq;
+  }
+  sup->s_max_size = zo * BLOCK_SIZE;
+  zone_size = 1 << zone_shift;	/* nr of blocks per zone */
+
+  put_block((block_t) 1, buf);
+
+  /* Clear maps and inodes. */
+  for (i = 2; i < initblks; i++) put_block((block_t) i, zero);
+
+  next_zone = sup->s_firstdatazone;
+  next_inode = 1;
+
+  zone_map = INODE_MAP + sup->s_imap_blocks;
+
+  insert_bit(zone_map, 0);	/* bit zero must always be allocated */
+  insert_bit((block_t) INODE_MAP, 0);	/* inode zero not used but
+					 * must be allocated */
+}
+
+
+/*================================================================
+ *              rootdir  -  install the root directory
+ *===============================================================*/
+void rootdir(inode)
+ino_t inode;
+{
+  zone_t z;
+
+  z = alloc_zone();
+  add_zone(inode, z, 32L, current_time);
+  enter_dir(inode, ".", inode);
+  enter_dir(inode, "..", inode);
+  incr_link(inode);
+  incr_link(inode);
+}
+
+
+/*================================================================
+ *	    eat_dir  -  recursively install directory
+ *===============================================================*/
+void eat_dir(parent)
+ino_t parent;
+{
+  /* Read prototype lines and set up directory. Recurse if need be. */
+  char *token[MAX_TOKENS], *p;
+  char line[LINE_LEN];
+  int mode, usrid, grpid, maj, min, f;
+  ino_t n;
+  zone_t z;
+  long size;
+
+  while (1) {
+	getline(line, token);
+	p = token[0];
+	if (*p == '$') return;
+	p = token[1];
+	mode = mode_con(p);
+	usrid = atoi(token[2]);
+	grpid = atoi(token[3]);
+	if (grpid & 0200) fprintf(stderr, "A.S.Tanenbaum\n");
+	n = alloc_inode(mode, usrid, grpid);
+
+	/* Enter name in directory and update directory's size. */
+	enter_dir(parent, token[0], n);
+	incr_size(parent, 16L);
+
+	/* Check to see if file is directory or special. */
+	incr_link(n);
+	if (*p == 'd') {
+		/* This is a directory. */
+		z = alloc_zone();	/* zone for new directory */
+		add_zone(n, z, 32L, current_time);
+		enter_dir(n, ".", n);
+		enter_dir(n, "..", parent);
+		incr_link(parent);
+		incr_link(n);
+		eat_dir(n);
+	} else if (*p == 'b' || *p == 'c') {
+		/* Special file. */
+		maj = atoi(token[4]);
+		min = atoi(token[5]);
+		size = 0;
+		if (token[6]) size = atoi(token[6]);
+		size = BLOCK_SIZE * size;
+		add_zone(n, (zone_t) ((maj << 8) | min), size, current_time);
+	} else {
+		/* Regular file. Go read it. */
+		if ((f = open(token[4], O_RDONLY)) < 0) {
+			fprintf(stderr, "%s: Can't open %s: %s\n",
+				progname, token[4], strerror(errno));
+		} else
+			eat_file(n, f);
+	}
+  }
+
+}
+
+/*================================================================
+ * 		eat_file  -  copy file to MINIX
+ *===============================================================*/
+/* Zonesize >= blocksize */
+void eat_file(inode, f)
+ino_t inode;
+int f;
+{
+  int ct, i, j, k;
+  zone_t z;
+  char buf[BLOCK_SIZE];
+  long timeval;
+
+  do {
+	for (i = 0, j = 0; i < zone_size; i++, j += ct) {
+		for (k = 0; k < BLOCK_SIZE; k++) buf[k] = 0;
+		if ((ct = read(f, buf, BLOCK_SIZE)) > 0) {
+			if (i == 0) z = alloc_zone();
+			put_block((z << zone_shift) + i, buf);
+		}
+	}
+	timeval = (dflag ? current_time : file_time(f));
+	if (ct) add_zone(inode, z, (long) j, timeval);
+  } while (ct == BLOCK_SIZE);
+  close(f);
+}
+
+
+
+/*================================================================
+ *	    directory & inode management assist group
+ *===============================================================*/
+void enter_dir(parent, name, child)
+ino_t parent, child;
+char *name;
+{
+  /* Enter child in parent directory */
+  /* Works for dir > 1 block and zone > block */
+  int i, j, k, l, off;
+  block_t b;
+  zone_t z;
+  char *p1, *p2;
+  struct direct dir_entry[NR_DIR_ENTRIES(BLOCK_SIZE)];
+  d1_inode ino1[V1_INODES_PER_BLOCK];
+  d2_inode ino2[V2_INODES_PER_BLOCK(BLOCK_SIZE)];
+  int nr_dzones;
+
+  b = ((parent - 1) / inodes_per_block) + inode_offset;
+  off = (parent - 1) % inodes_per_block;
+
+  if (fs_version == 1) {
+	get_block(b, (char *) ino1);
+	nr_dzones = V1_NR_DZONES;
+  } else {
+	get_block(b, (char *) ino2);
+	nr_dzones = V2_NR_DZONES;
+  }
+  for (k = 0; k < nr_dzones; k++) {
+	if (fs_version == 1) {
+		z = ino1[off].d1_zone[k];
+		if (z == 0) {
+			z = alloc_zone();
+			ino1[off].d1_zone[k] = z;
+		}
+	} else {
+		z = ino2[off].d2_zone[k];
+		if (z == 0) {
+			z = alloc_zone();
+			ino2[off].d2_zone[k] = z;
+		}
+	}
+	for (l = 0; l < zone_size; l++) {
+		get_block((z << zone_shift) + l, (char *) dir_entry);
+		for (i = 0; i < NR_DIR_ENTRIES(BLOCK_SIZE); i++) {
+			if (dir_entry[i].d_ino == 0) {
+				dir_entry[i].d_ino = child;
+				p1 = name;
+				p2 = dir_entry[i].d_name;
+				j = 14;
+				while (j--) {
+					*p2++ = *p1;
+					if (*p1 != 0) p1++;
+				}
+				put_block((z << zone_shift) + l, (char *) dir_entry);
+				if (fs_version == 1) {
+					put_block(b, (char *) ino1);
+				} else {
+					put_block(b, (char *) ino2);
+				}
+				return;
+			}
+		}
+	}
+  }
+
+  printf("Directory-inode %d beyond direct blocks.  Could not enter %s\n",
+         parent, name);
+  pexit("Halt");
+}
+
+
+void add_zone(n, z, bytes, cur_time)
+ino_t n;
+zone_t z;
+long bytes, cur_time;
+{
+  if (fs_version == 1) {
+	add_z_1(n, z, bytes, cur_time);
+  } else {
+	add_z_2(n, z, bytes, cur_time);
+  }
+}
+
+void add_z_1(n, z, bytes, cur_time)
+ino_t n;
+zone_t z;
+long bytes, cur_time;
+{
+  /* Add zone z to inode n. The file has grown by 'bytes' bytes. */
+
+  int off, i;
+  block_t b;
+  zone_t indir;
+  zone1_t blk[V1_INDIRECTS];
+  d1_inode *p;
+  d1_inode inode[V1_INODES_PER_BLOCK];
+
+  b = ((n - 1) / V1_INODES_PER_BLOCK) + inode_offset;
+  off = (n - 1) % V1_INODES_PER_BLOCK;
+  get_block(b, (char *) inode);
+  p = &inode[off];
+  p->d1_size += bytes;
+  p->d1_mtime = cur_time;
+  for (i = 0; i < V1_NR_DZONES; i++)
+	if (p->d1_zone[i] == 0) {
+		p->d1_zone[i] = (zone1_t) z;
+		put_block(b, (char *) inode);
+		return;
+	}
+  put_block(b, (char *) inode);
+
+  /* File has grown beyond a small file. */
+  if (p->d1_zone[V1_NR_DZONES] == 0)
+	p->d1_zone[V1_NR_DZONES] = (zone1_t) alloc_zone();
+  indir = p->d1_zone[V1_NR_DZONES];
+  put_block(b, (char *) inode);
+  b = indir << zone_shift;
+  get_block(b, (char *) blk);
+  for (i = 0; i < V1_INDIRECTS; i++)
+	if (blk[i] == 0) {
+		blk[i] = (zone1_t) z;
+		put_block(b, (char *) blk);
+		return;
+	}
+  pexit("File has grown beyond single indirect");
+}
+
+void add_z_2(n, z, bytes, cur_time)
+ino_t n;
+zone_t z;
+long bytes, cur_time;
+{
+  /* Add zone z to inode n. The file has grown by 'bytes' bytes. */
+
+  int off, i;
+  block_t b;
+  zone_t indir;
+  zone_t blk[V2_INDIRECTS(BLOCK_SIZE)];
+  d2_inode *p;
+  d2_inode inode[V2_INODES_PER_BLOCK(BLOCK_SIZE)];
+
+  b = ((n - 1) / V2_INODES_PER_BLOCK(BLOCK_SIZE)) + inode_offset;
+  off = (n - 1) % V2_INODES_PER_BLOCK(BLOCK_SIZE);
+  get_block(b, (char *) inode);
+  p = &inode[off];
+  p->d2_size += bytes;
+  p->d2_mtime = cur_time;
+  for (i = 0; i < V2_NR_DZONES; i++)
+	if (p->d2_zone[i] == 0) {
+		p->d2_zone[i] = z;
+		put_block(b, (char *) inode);
+		return;
+	}
+  put_block(b, (char *) inode);
+
+  /* File has grown beyond a small file. */
+  if (p->d2_zone[V2_NR_DZONES] == 0) p->d2_zone[V2_NR_DZONES] = alloc_zone();
+  indir = p->d2_zone[V2_NR_DZONES];
+  put_block(b, (char *) inode);
+  b = indir << zone_shift;
+  get_block(b, (char *) blk);
+  for (i = 0; i < V2_INDIRECTS(BLOCK_SIZE); i++)
+	if (blk[i] == 0) {
+		blk[i] = z;
+		put_block(b, (char *) blk);
+		return;
+	}
+  pexit("File has grown beyond single indirect");
+}
+
+
+void incr_link(n)
+ino_t n;
+{
+  /* Increment the link count to inode n */
+  int off;
+  block_t b;
+
+  b = ((n - 1) / inodes_per_block) + inode_offset;
+  off = (n - 1) % inodes_per_block;
+  if (fs_version == 1) {
+	d1_inode inode1[V1_INODES_PER_BLOCK];
+
+	get_block(b, (char *) inode1);
+	inode1[off].d1_nlinks++;
+	put_block(b, (char *) inode1);
+  } else {
+	d2_inode inode2[V2_INODES_PER_BLOCK(BLOCK_SIZE)];
+
+	get_block(b, (char *) inode2);
+	inode2[off].d2_nlinks++;
+	put_block(b, (char *) inode2);
+  }
+}
+
+
+void incr_size(n, count)
+ino_t n;
+long count;
+{
+  /* Increment the file-size in inode n */
+  block_t b;
+  int off;
+
+  b = ((n - 1) / inodes_per_block) + inode_offset;
+  off = (n - 1) % inodes_per_block;
+  if (fs_version == 1) {
+	d1_inode inode1[V1_INODES_PER_BLOCK];
+
+	get_block(b, (char *) inode1);
+	inode1[off].d1_size += count;
+	put_block(b, (char *) inode1);
+  } else {
+	d2_inode inode2[V2_INODES_PER_BLOCK(BLOCK_SIZE)];
+
+	get_block(b, (char *) inode2);
+	inode2[off].d2_size += count;
+	put_block(b, (char *) inode2);
+  }
+}
+
+
+/*================================================================
+ * 	 	     allocation assist group
+ *===============================================================*/
+PRIVATE ino_t alloc_inode(mode, usrid, grpid)
+int mode, usrid, grpid;
+{
+  ino_t num;
+  int off;
+  block_t b;
+
+  num = next_inode++;
+  if (num > nrinodes) pexit("File system does not have enough inodes");
+  b = ((num - 1) / inodes_per_block) + inode_offset;
+  off = (num - 1) % inodes_per_block;
+  if (fs_version == 1) {
+	d1_inode inode1[V1_INODES_PER_BLOCK];
+
+	get_block(b, (char *) inode1);
+	inode1[off].d1_mode = mode;
+	inode1[off].d1_uid = usrid;
+	inode1[off].d1_gid = grpid;
+	put_block(b, (char *) inode1);
+  } else {
+	d2_inode inode2[V2_INODES_PER_BLOCK(BLOCK_SIZE)];
+
+	get_block(b, (char *) inode2);
+	inode2[off].d2_mode = mode;
+	inode2[off].d2_uid = usrid;
+	inode2[off].d2_gid = grpid;
+	put_block(b, (char *) inode2);
+  }
+
+  /* Set the bit in the bit map. */
+  /* DEBUG FIXME.  This assumes the bit is in the first inode map block. */
+  insert_bit((block_t) INODE_MAP, (int) num);
+  return(num);
+}
+
+
+PRIVATE zone_t alloc_zone()
+{
+  /* Allocate a new zone */
+  /* Works for zone > block */
+  block_t b;
+  int i;
+  zone_t z;
+
+  z = next_zone++;
+  b = z << zone_shift;
+  if ((b + zone_size) > nrblocks)
+	pexit("File system not big enough for all the files");
+  for (i = 0; i < zone_size; i++)
+	put_block(b + i, zero);	/* give an empty zone */
+  /* DEBUG FIXME.  This assumes the bit is in the first zone map block. */
+  insert_bit(zone_map, (int) (z - zoff));	/* lint, NOT OK because
+						 * z hasn't been broken
+						 * up into block +
+						 * offset yet. */
+  return(z);
+}
+
+
+void insert_bit(block, bit)
+block_t block;
+int bit;
+{
+  /* Insert 'count' bits in the bitmap */
+  int w, s;
+  short buf[BLOCK_SIZE / sizeof(short)];
+
+  if (block < 0) pexit("insert_bit called with negative argument");
+  get_block(block, (char *) buf);
+  w = bit / (8 * sizeof(short));
+  s = bit % (8 * sizeof(short));
+  buf[w] |= (1 << s);
+  put_block(block, (char *) buf);
+}
+
+
+/*================================================================
+ * 		proto-file processing assist group
+ *===============================================================*/
+int mode_con(p)
+char *p;
+{
+  /* Convert string to mode */
+  int o1, o2, o3, mode;
+  char c1, c2, c3;
+
+  c1 = *p++;
+  c2 = *p++;
+  c3 = *p++;
+  o1 = *p++ - '0';
+  o2 = *p++ - '0';
+  o3 = *p++ - '0';
+  mode = (o1 << 6) | (o2 << 3) | o3;
+  if (c1 == 'd') mode += I_DIRECTORY;
+  if (c1 == 'b') mode += I_BLOCK_SPECIAL;
+  if (c1 == 'c') mode += I_CHAR_SPECIAL;
+  if (c1 == '-') mode += I_REGULAR;
+  if (c2 == 'u') mode += I_SET_UID_BIT;
+  if (c3 == 'g') mode += I_SET_GID_BIT;
+  return(mode);
+}
+
+void getline(line, parse)
+char *parse[MAX_TOKENS];
+char line[LINE_LEN];
+{
+  /* Read a line and break it up in tokens */
+  int k;
+  char c, *p;
+  int d;
+
+  for (k = 0; k < MAX_TOKENS; k++) parse[k] = 0;
+  for (k = 0; k < LINE_LEN; k++) line[k] = 0;
+  k = 0;
+  parse[0] = 0;
+  p = line;
+  while (1) {
+	if (++k > LINE_LEN) pexit("Line too long");
+	d = fgetc(proto);
+	if (d == EOF) pexit("Unexpected end-of-file");
+	*p = d;
+	if (*p == '\n') lct++;
+	if (*p == ' ' || *p == '\t') *p = 0;
+	if (*p == '\n') {
+		*p++ = 0;
+		*p = '\n';
+		break;
+	}
+	p++;
+  }
+
+  k = 0;
+  p = line;
+  lastp = line;
+  while (1) {
+	c = *p++;
+	if (c == '\n') return;
+	if (c == 0) continue;
+	parse[k++] = p - 1;
+	do {
+		c = *p++;
+	} while (c != 0 && c != '\n');
+  }
+}
+
+
+/*================================================================
+ *			other stuff
+ *===============================================================*/
+void check_mtab(devname)
+char *devname;			/* /dev/hd1 or whatever */
+{
+/* Check to see if the special file named in s is mounted. */
+
+  int n;
+  char special[PATH_MAX + 1], mounted_on[PATH_MAX + 1], version[10], rw_flag[10];
+
+  if (load_mtab("mkfs") < 0) return;
+  while (1) {
+	n = get_mtab_entry(special, mounted_on, version, rw_flag);
+	if (n < 0) return;
+	if (strcmp(devname, special) == 0) {
+		/* Can't mkfs on top of a mounted file system. */
+		fprintf(stderr, "%s: %s is mounted on %s\n",
+			progname, devname, mounted_on);
+		exit(1);
+	}
+  }
+}
+
+
+long file_time(f)
+int f;
+{
+#ifdef UNIX
+  struct stat statbuf;
+  fstat(f, &statbuf);
+  return(statbuf.st_mtime);
+#else				/* fstat not supported by DOS */
+  return(0L);
+#endif
+}
+
+
+void pexit(s)
+char *s;
+{
+  fprintf(stderr, "%s: %s\n", progname, s);
+  if (lct != 0)
+	fprintf(stderr, "Line %d being processed when error detected.\n", lct);
+  flush();
+  exit(2);
+}
+
+
+void copy(from, to, count)
+char *from, *to;
+int count;
+{
+  while (count--) *to++ = *from++;
+}
+
+
+void print_fs()
+{
+  int i, j;
+  ino_t k;
+  d1_inode inode1[V1_INODES_PER_BLOCK];
+  d2_inode inode2[V2_INODES_PER_BLOCK(BLOCK_SIZE)];
+  unsigned short usbuf[BLOCK_SIZE / sizeof(unsigned short)];
+  block_t b, inode_limit;
+  struct direct dir[NR_DIR_ENTRIES(BLOCK_SIZE)];
+
+  get_block((block_t) 1, (char *) usbuf);
+  printf("\nSuperblock: ");
+  for (i = 0; i < 8; i++) printf("%06o ", usbuf[i]);
+  get_block((block_t) 2, (char *) usbuf);
+  printf("...\nInode map:  ");
+  for (i = 0; i < 9; i++) printf("%06o ", usbuf[i]);
+  get_block((block_t) 3, (char *) usbuf);
+  printf("...\nZone  map:  ");
+  for (i = 0; i < 9; i++) printf("%06o ", usbuf[i]);
+  printf("...\n");
+
+  k = 0;
+  for (b = inode_offset; k < nrinodes; b++) {
+	if (fs_version == 1) {
+		get_block(b, (char *) inode1);
+	} else {
+		get_block(b, (char *) inode2);
+	}
+	for (i = 0; i < inodes_per_block; i++) {
+		k = inodes_per_block * (int) (b - inode_offset) + i + 1;
+		/* Lint but OK */
+		if (k > nrinodes) break;
+		if (fs_version == 1) {
+			if (inode1[i].d1_mode != 0) {
+				printf("Inode %2d:  mode=", k);
+				printf("%06o", inode1[i].d1_mode);
+				printf("  uid=%2d  gid=%2d  size=",
+				inode1[i].d1_uid, inode1[i].d1_gid);
+				printf("%6ld", inode1[i].d1_size);
+				printf("  zone[0]=%d\n", inode1[i].d1_zone[0]);
+			}
+			if ((inode1[i].d1_mode & I_TYPE) == I_DIRECTORY) {
+				/* This is a directory */
+				get_block(inode1[i].d1_zone[0], (char *) dir);
+				for (j = 0; j < NR_DIR_ENTRIES(BLOCK_SIZE); j++)
+					if (dir[j].d_ino)
+						printf("\tInode %2d: %s\n", dir[j].d_ino, dir[j].d_name);
+			}
+		} else {
+			if (inode2[i].d2_mode != 0) {
+				printf("Inode %2d:  mode=", k);
+				printf("%06o", inode2[i].d2_mode);
+				printf("  uid=%2d  gid=%2d  size=",
+				inode2[i].d2_uid, inode2[i].d2_gid);
+				printf("%6ld", inode2[i].d2_size);
+				printf("  zone[0]=%ld\n", inode2[i].d2_zone[0]);
+			}
+			if ((inode2[i].d2_mode & I_TYPE) == I_DIRECTORY) {
+				/* This is a directory */
+				get_block(inode2[i].d2_zone[0], (char *) dir);
+				for (j = 0; j < NR_DIR_ENTRIES(BLOCK_SIZE); j++)
+					if (dir[j].d_ino)
+						printf("\tInode %2d: %s\n", dir[j].d_ino, dir[j].d_name);
+			}
+		}
+	}
+  }
+
+  printf("%d inodes used.     %d zones used.\n", next_inode - 1, next_zone);
+}
+
+
+int read_and_set(n)
+block_t n;
+{
+/* The first time a block is read, it returns all 0s, unless there has
+ * been a write.  This routine checks to see if a block has been accessed.
+ */
+
+  int w, s, mask, r;
+
+  if (sizeof(char *) == 2 && n >= MAX_INIT) pexit("can't initialize past 128M");
+  w = n / 8;
+  s = n % 8;
+  mask = 1 << s;
+  r = (umap[w] & mask ? 1 : 0);
+  umap[w] |= mask;
+  return(r);
+}
+
+void usage()
+{
+  fprintf(stderr,
+	  "Usage: %s [-1dlot] [-b blocks] [-i inodes] special [proto]\n",
+	  progname);
+  exit(1);
+}
+
+/*================================================================
+ *		      get_block & put_block for MS-DOS
+ *===============================================================*/
+#ifdef DOS
+
+/*
+ *	These are the get_block and put_block routines
+ *	when compiling & running mkfs.c under MS-DOS.
+ *
+ *	It requires the (asembler) routines absread & abswrite
+ *	from the file diskio.asm. Since these routines just do
+ *	as they are told (read & write the sector specified),
+ *	a local cache is used to minimize the i/o-overhead for
+ *	frequently used blocks.
+ *
+ *	The global variable "file" determines whether the output
+ *	is to a disk-device or to a binary file.
+ */
+
+
+#define PH_SECTSIZE	   512	/* size of a physical disk-sector */
+
+
+char *derrtab[14] = {
+	     "no error",
+	     "disk is read-only",
+	     "unknown unit",
+	     "device not ready",
+	     "bad command",
+	     "data error",
+	     "internal error: bad request structure length",
+	     "seek error",
+	     "unknown media type",
+	     "sector not found",
+	     "printer out of paper (?)",
+	     "write fault",
+	     "read error",
+	     "general error"
+};
+
+#define	CACHE_SIZE	20	/* 20 block-buffers */
+
+
+struct cache {
+  char blockbuf[BLOCK_SIZE];
+  block_t blocknum;
+  int dirty;
+  int usecnt;
+} cache[CACHE_SIZE];
+
+
+void special(string)
+char *string;
+{
+
+  if (string[1] == ':' && string[2] == 0) {
+	/* Format: d: or d:fname */
+	disk = (string[0] & ~32) - 'A';
+	if (disk > 1 && !override)	/* safety precaution */
+		pexit("Bad drive specifier for special");
+  } else {
+	file = 1;
+	if ((fd = creat(string, BWRITE)) == 0)
+		pexit("Can't open special file");
+  }
+}
+
+void get_block(n, buf)
+block_t n;
+char buf[BLOCK_SIZE];
+{
+  /* Get a block to the user */
+  struct cache *bp, *fp;
+
+  /* First access returns a zero block */
+  if (read_and_set(n) == 0) {
+	copy(zero, buf, BLOCK_SIZE);
+	return;
+  }
+
+  /* Look for block in cache */
+  fp = 0;
+  for (bp = cache; bp < &cache[CACHE_SIZE]; bp++) {
+	if (bp->blocknum == n) {
+		copy(bp, buf, BLOCK_SIZE);
+		bp->usecnt++;
+		return;
+	}
+
+	/* Remember clean block */
+	if (bp->dirty == 0)
+		if (fp) {
+			if (fp->usecnt > bp->usecnt) fp = bp;
+		} else
+			fp = bp;
+  }
+
+  /* Block not in cache, get it */
+  if (!fp) {
+	/* No clean buf, flush one */
+	for (bp = cache, fp = cache; bp < &cache[CACHE_SIZE]; bp++)
+		if (fp->usecnt > bp->usecnt) fp = bp;
+	mx_write(fp->blocknum, fp);
+  }
+  mx_read(n, fp);
+  fp->dirty = 0;
+  fp->usecnt = 0;
+  fp->blocknum = n;
+  copy(fp, buf, BLOCK_SIZE);
+}
+
+void put_block(n, buf)
+block_t n;
+char buf[BLOCK_SIZE];
+{
+  /* Accept block from user */
+  struct cache *fp, *bp;
+
+  (void) read_and_set(n);
+
+  /* Look for block in cache */
+  fp = 0;
+  for (bp = cache; bp < &cache[CACHE_SIZE]; bp++) {
+	if (bp->blocknum == n) {
+		copy(buf, bp, BLOCK_SIZE);
+		bp->dirty = 1;
+		return;
+	}
+
+	/* Remember clean block */
+	if (bp->dirty == 0)
+		if (fp) {
+			if (fp->usecnt > bp->usecnt) fp = bp;
+		} else
+			fp = bp;
+  }
+
+  /* Block not in cache */
+  if (!fp) {
+	/* No clean buf, flush one */
+	for (bp = cache, fp = cache; bp < &cache[CACHE_SIZE]; bp++)
+		if (fp->usecnt > bp->usecnt) fp = bp;
+	mx_write(fp->blocknum, fp);
+  }
+  fp->dirty = 1;
+  fp->usecnt = 1;
+  fp->blocknum = n;
+  copy(buf, fp, BLOCK_SIZE);
+}
+
+void cache_init()
+{
+  struct cache *bp;
+  for (bp = cache; bp < &cache[CACHE_SIZE]; bp++) bp->blocknum = -1;
+}
+
+void flush()
+{
+  /* Flush all dirty blocks to disk */
+  struct cache *bp;
+
+  for (bp = cache; bp < &cache[CACHE_SIZE]; bp++)
+	if (bp->dirty) {
+		mx_write(bp->blocknum, bp);
+		bp->dirty = 0;
+	}
+}
+
+/*==================================================================
+ *			hard read & write etc.
+ *=================================================================*/
+#define MAX_RETRIES	5
+
+
+void mx_read(blocknr, buf)
+int blocknr;
+char buf[BLOCK_SIZE];
+{
+
+  /* Read the requested MINIX-block in core */
+  char (*bp)[PH_SECTSIZE];
+  int sectnum, retries, err;
+
+  if (file) {
+	lseek(fd, (off_t) blocknr * BLOCK_SIZE, 0);
+	if (read(fd, buf, BLOCK_SIZE) != BLOCK_SIZE)
+		pexit("mx_read: error reading file");
+  } else {
+	sectnum = blocknr * (BLOCK_SIZE / PH_SECTSIZE);
+	for (bp = buf; bp < &buf[BLOCK_SIZE]; bp++) {
+		retries = MAX_RETRIES;
+		do
+			err = absread(disk, sectnum, bp);
+		while (err && --retries);
+
+		if (retries) {
+			sectnum++;
+		} else {
+			dexit("mx_read", sectnum, err);
+		}
+	}
+  }
+}
+
+void mx_write(blocknr, buf)
+int blocknr;
+char buf[BLOCK_SIZE];
+{
+  /* Write the MINIX-block to disk */
+  char (*bp)[PH_SECTSIZE];
+  int retries, sectnum, err;
+
+  if (file) {
+	lseek(fd, blocknr * BLOCK_SIZE, 0);
+	if (write(fd, buf, BLOCK_SIZE) != BLOCK_SIZE) {
+		pexit("mx_write: error writing file");
+	}
+  } else {
+	sectnum = blocknr * (BLOCK_SIZE / PH_SECTSIZE);
+	for (bp = buf; bp < &buf[BLOCK_SIZE]; bp++) {
+		retries = MAX_RETRIES;
+		do {
+			err = abswrite(disk, sectnum, bp);
+		} while (err && --retries);
+
+		if (retries) {
+			sectnum++;
+		} else {
+			dexit("mx_write", sectnum, err);
+		}
+	}
+  }
+}
+
+
+void dexit(s, sectnum, err)
+int sectnum, err;
+char *s;
+{
+  printf("Error: %s, sector: %d, code: %d, meaning: %s\n",
+         s, sectnum, err, derrtab[err]);
+  exit(2);
+}
+
+#endif
+
+/*================================================================
+ *		      get_block & put_block for UNIX
+ *===============================================================*/
+#ifdef UNIX
+
+void special(string)
+char *string;
+{
+  fd = creat(string, 0777);
+  close(fd);
+  fd = open(string, O_RDWR);
+  if (fd < 0) pexit("Can't open special file");
+#if (MACHINE == ATARI)
+  {
+	struct stat statbuf;
+
+	if (fstat(fd, &statbuf) < 0) return;
+	isdev = (statbuf.st_mode & S_IFMT) == S_IFCHR
+		||
+		(statbuf.st_mode & S_IFMT) == S_IFBLK
+		;
+  }
+#endif
+}
+
+
+
+void get_block(n, buf)
+block_t n;
+char buf[BLOCK_SIZE];
+{
+/* Read a block. */
+
+  int k;
+
+  /* First access returns a zero block */
+  if (read_and_set(n) == 0) {
+	copy(zero, buf, BLOCK_SIZE);
+	return;
+  }
+  lseek(fd, (off_t) n * BLOCK_SIZE, SEEK_SET);
+  k = read(fd, buf, BLOCK_SIZE);
+  if (k != BLOCK_SIZE) {
+	pexit("get_block couldn't read");
+  }
+}
+
+void put_block(n, buf)
+block_t n;
+char buf[BLOCK_SIZE];
+{
+/* Write a block. */
+
+  (void) read_and_set(n);
+
+  /* XXX - check other lseeks too. */
+  if (lseek(fd, (off_t) n * BLOCK_SIZE, SEEK_SET) == (off_t) -1) {
+	pexit("put_block couldn't seek");
+  }
+  if (write(fd, buf, BLOCK_SIZE) != BLOCK_SIZE) {
+	pexit("put_block couldn't write");
+  }
+}
+
+
+/* Dummy routines to keep source file clean from #ifdefs */
+
+void flush()
+{
+  return;
+}
+
+void cache_init()
+{
+  return;
+}
+
+#endif
Index: /trunk/minix/commands/simple/passwd.c
===================================================================
--- /trunk/minix/commands/simple/passwd.c	(revision 9)
+++ /trunk/minix/commands/simple/passwd.c	(revision 9)
@@ -0,0 +1,260 @@
+/* passwd - change a passwd			Author: Adri Koppes */
+
+/* chfn, chsh - change full name, shell		Added by: Kees J. Bot */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <signal.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <minix/minlib.h>
+#include <stdio.h>
+
+_PROTOTYPE(void report, (char *label));
+_PROTOTYPE(void quit, (int ex_stat));
+_PROTOTYPE(void fatal, (char *label));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(int goodchars, (char *s));
+_PROTOTYPE(int main, (int argc, char **argv));
+
+char pw_file[] = "/etc/passwd";
+char sh_file[] = "/etc/shadow";
+char pw_tmp[] = "/etc/ptmp";
+char bad[] = "Permission denied\n";
+char buf[1024];
+
+enum action {
+  PASSWD, CHFN, CHSH
+} action = PASSWD;
+
+char *arg0;
+
+void report(label)
+char *label;
+{
+  int e = errno;
+  fprintf(stderr, "%s: ", arg0);
+  fflush(stderr);
+  errno = e;
+  perror(label);
+}
+
+void quit(ex_stat)
+int ex_stat;
+{
+  if (unlink(pw_tmp) < 0 && errno != ENOENT) {
+	report(pw_tmp);
+	ex_stat = 1;
+  }
+  exit(ex_stat);
+}
+
+void fatal(label)
+char *label;
+{
+  report(label);
+  quit(1);
+}
+
+void usage()
+{
+  static char *usages[] = {
+	"passwd [user]\n",
+	"chfn [user] fullname\n",
+	"chsh [user] shell\n"
+  };
+  std_err(usages[(int) action]);
+  exit(1);
+}
+
+int goodchars(s)
+char *s;
+{
+  int c;
+
+  while ((c = *s++) != 0) {
+	if (c == ':' || c < ' ' || c >= 127) return(0);
+  }
+  return(1);
+}
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int uid, cn, n;
+  int fd_pwd, fd_tmp;
+  FILE *fp_tmp;
+  time_t salt;
+  struct passwd *pwd;
+  char *name, pwname[9], oldpwd[9], newpwd[9], newcrypted[14], sl[2];
+  char *argn;
+  int shadow = 0;
+
+  if ((arg0 = strrchr(argv[0], '/')) != 0)
+	arg0++;
+  else
+	arg0 = argv[0];
+
+  if (strcmp(arg0, "chfn") == 0)
+	action = CHFN;
+  else if (strcmp(arg0, "chsh") == 0)
+	action = CHSH;
+
+  uid = getuid();
+
+  n = action == PASSWD ? 1 : 2;
+
+  if (argc != n && argc != n + 1) usage();
+
+  if (argc == n) {
+	pwd = getpwuid(uid);
+	strcpy(pwname, pwd->pw_name);
+	name = pwname;
+  } else {
+	name = argv[1];
+	pwd = getpwnam(name);
+  }
+  if (pwd == NULL || ((uid != pwd->pw_uid) && uid != 0)) {
+	std_err(bad);
+	exit(1);
+  }
+
+  switch (action) {
+      case PASSWD:
+	if (pwd->pw_passwd[0] == '#' && pwd->pw_passwd[1] == '#') {
+		/* The password is found in the shadow password file. */
+		shadow = 1;
+		strncpy(pwname, pwd->pw_passwd + 2, 8);
+		pwname[8] = 0;
+		name = pwname;
+		setpwfile(sh_file);
+		if ((pwd= getpwnam(name)) == NULL) {
+			std_err(bad);
+			exit(1);
+		}
+		printf("Changing the shadow password of %s\n", name);
+	} else {
+		printf("Changing the password of %s\n", name);
+	}
+
+	oldpwd[0] = 0;
+	if (pwd->pw_passwd[0] != '\0' && uid != 0) {
+		strcpy(oldpwd, getpass("Old password:"));
+		if (strcmp(pwd->pw_passwd, crypt(oldpwd, pwd->pw_passwd)) != 0)
+		{
+			std_err(bad);
+			exit(1);
+		}
+	}
+	for (;;) {
+		strcpy(newpwd, getpass("New password:"));
+
+		if (newpwd[0] == '\0')
+			std_err("Password cannot be null");
+		else if (strcmp(newpwd, getpass("Retype password:")) != 0)
+			std_err("Passwords don't match");
+		else
+			break;
+
+		std_err(", try again\n");
+	}
+	time(&salt);
+	sl[0] = (salt & 077) + '.';
+	sl[1] = ((salt >> 6) & 077) + '.';
+	for (cn = 0; cn < 2; cn++) {
+		if (sl[cn] > '9') sl[cn] += 7;
+		if (sl[cn] > 'Z') sl[cn] += 6;
+	}
+	strcpy(newcrypted, crypt(newpwd, sl));
+	break;
+
+      case CHFN:
+      case CHSH:
+	argn = argv[argc - 1];
+
+	if (strlen(argn) > (action == CHFN ? 80 : 60) || !goodchars(argn)) {
+		std_err(bad);
+		exit(1);
+	}
+  }
+
+  signal(SIGHUP, SIG_IGN);
+  signal(SIGINT, SIG_IGN);
+  signal(SIGQUIT, SIG_IGN);
+  signal(SIGTERM, SIG_IGN);
+
+  umask(0);
+  n = 10;
+  while ((fd_tmp = open(pw_tmp, O_RDWR | O_CREAT | O_EXCL, 0400)) < 0) {
+	if (errno != EEXIST) fatal("Can't create temporary file");
+
+	if (n-- > 0) {
+		sleep(2);
+	} else {
+		fprintf(stderr, "Password file busy, try again later.\n");
+		exit(1);
+	}
+  }
+
+  if ((fp_tmp = fdopen(fd_tmp, "w+")) == NULL) fatal(pw_tmp);
+
+  setpwent();
+  while ((pwd = getpwent()) != 0) {
+	if (strcmp(name, pwd->pw_name) == 0) {
+		switch (action) {
+		    case PASSWD:
+			pwd->pw_passwd = newcrypted;
+			break;
+		    case CHFN:
+			pwd->pw_gecos = argn;
+			break;
+		    case CHSH:
+		    	pwd->pw_shell = argn;
+		    	break;
+		}
+	}
+	if (strcmp(pwd->pw_shell, "/bin/sh") == 0
+		|| strcmp(pwd->pw_shell, "/usr/bin/sh") == 0
+	)
+		pwd->pw_shell = "";
+
+	fprintf(fp_tmp, "%s:%s:%s:",
+		pwd->pw_name,
+		pwd->pw_passwd,
+		itoa(pwd->pw_uid)
+	);
+	if (ferror(fp_tmp)) fatal(pw_tmp);
+
+	fprintf(fp_tmp, "%s:%s:%s:%s\n",
+		itoa(pwd->pw_gid),
+		pwd->pw_gecos,
+		pwd->pw_dir,
+		pwd->pw_shell
+	);
+	if (ferror(fp_tmp)) fatal(pw_tmp);
+  }
+  endpwent();
+  if (fflush(fp_tmp) == EOF) fatal(pw_tmp);
+
+  if (lseek(fd_tmp, (off_t) 0, SEEK_SET) != 0)
+	fatal("Can't reread temp file");
+
+  if ((fd_pwd = open(shadow ? sh_file : pw_file, O_WRONLY | O_TRUNC)) < 0)
+	fatal("Can't recreate password file");
+
+  while ((n = read(fd_tmp, buf, sizeof(buf))) != 0) {
+	if (n < 0 || write(fd_pwd, buf, n) != n) {
+		report("Error rewriting password file, tell root!");
+		exit(1);
+	}
+  }
+  close(fd_tmp);
+  close(fd_pwd);
+  quit(0);
+}
Index: /trunk/minix/commands/simple/paste.c
===================================================================
--- /trunk/minix/commands/simple/paste.c	(revision 9)
+++ /trunk/minix/commands/simple/paste.c	(revision 9)
@@ -0,0 +1,456 @@
+/* paste - laminate files		Author: David Ihnat */
+
+/* Paste - a recreation of the Unix(Tm) paste(1) command.
+ *
+ * syntax: paste file1 file2 ... paste -dLIST file1 file2 ... paste -s [-dLIST]
+ * file1 file2 ...
+ *
+ * Copyright (C) 1984 by David M. Ihnat
+ *
+ * This program is a total rewrite of the Bell Laboratories Unix(Tm) command of
+ * the same name, as of System V.  It contains no proprietary code, and
+ * therefore may be used without violation of any proprietary agreements
+ * whatsoever.  However, you will notice that the program is copyrighted by
+ * me.  This is to assure the program does *not* fall into the public domain.
+ * Thus, I may specify just what I am now: This program may be freely copied
+ * and distributed, provided this notice remains; it may not be sold for
+ * profit without express written consent of the author. Please note that I
+ * recreated the behavior of the Unix(Tm) 'paste' command as faithfully as
+ * possible, with minor exceptions (noted below); however, I haven't run a
+ * full set of regression * tests.  Thus, the user of this program accepts
+ * full responsibility for any effects or loss; in particular, the author is
+ * not responsible for any losses, explicit or incidental, that may be
+ * incurred through use of this program.
+ *
+ * The changes to the program, with one exception, are transparent to a user
+ * familiar with the Unix command of the same name.  These changes are:
+ *
+ * 1) The '-s' option had a bug in the Unix version when used with multiple
+ *    files.  (It would repeat each file in a list, i.e., for 
+ *
+ *		paste -s file1 file2 file3
+ *
+ * it would list
+ *
+ *	 <file1\n><file1\n><file2\n><file1\n><file2\n><file3\n>
+ *
+ * I fixed this, and reported the bug to the providers of the command in Unix.
+ *
+ * 2) The list of valid escape sequences has been expanded to include \b,\f, 
+ *    and \r.  (Just because *I* can't imagine why you'd want to use them 
+ *    doesn't mean I should keep them from you.)
+ *
+ * 3) There is no longer any restriction on line length.
+ *
+ * I ask that any bugs (and, if possible, fixes) be reported to me when
+ * possible.  -David Ihnat (312) 784-4544 ihuxx!ignatz
+ */
+
+/* Modified to run under MINIX 1.1 by David O. Tinker  (416) 978-3636
+ * (utgpu!dtinker) Sept. 19, 1987
+ */
+
+/* Modified to conform to POSIX 1003.2/Draft10 standard 23rd Sept. 1990
+ * Changes:
+ * 	- the arguments can be in any order
+ *	- removed the ToUpper function
+ * by Thomas Brupbacher (tobr@mw.lpc.ethz.ch)
+ */
+
+#include <errno.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+/* I'd love to use enums, but not everyone has them.  Portability, y'know. */
+#define NODELIM		1
+#define USAGE		2
+#define BADFILE		3
+#define TOOMANY		4
+
+#define	TAB		'\t'
+#define	NL		'\n'
+#define	BS		'\b'
+#define	FF		'\f'
+#define	CR		'\r'
+#define DEL             '\177'
+#define SPACE		' '
+#define BACKSLASH	'\\'
+
+#define	_MAXSZ		512
+#define _MAXFILES	12
+#define	CLOSED		((FILE *)-1)
+#define ENDLIST		((FILE *)-2)
+
+char *cmdnam;
+
+short int sflag;
+static char default_delims[] = {TAB};	/* default delimiter string	 */
+char *delims;			/* the pointer to the delimiters        */
+int number_of_delims = 1;	/* number of delimiters to use	 	 */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void docol, (int nfiles, char **fnamptr));
+_PROTOTYPE(void doserial, (int nfiles, char **fnamptr));
+_PROTOTYPE(void delimbuild, (char *strptr));
+_PROTOTYPE(void prerr, (int etype, char *estring));
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  char **arg_ptr;		/* used to save argv, needed for docol() etc */
+  int num_files = 0;		/* Number of filenames specified on cmd line */
+  sflag = 0;
+  delims = default_delims;	/* use default delimiters */
+
+  cmdnam = *argv;
+
+  if (argc >= 2) {
+
+	/* Skip invocation name */
+	argv++;
+	argc--;
+
+	/* Save argv */
+	arg_ptr = argv;
+	/* First, parse input options */
+
+	while (argc-- > 0) {
+		if (argv[0][0] == '-' && argv[0][1] != '\0') {
+			switch (argv[0][1]) {
+			    case 'd':
+				/* Delimiter character(s) */
+				if (*(++argv) == '\0')
+					prerr(NODELIM, "");
+				else
+					delimbuild(*(argv));
+				argc--;
+				break;
+
+			    case 's':	sflag++;	break;
+
+			    default:	prerr(USAGE, "");
+			}
+			argv++;
+		} else {
+			num_files++;
+			argv++;
+		}
+	}
+
+	/* If there are more than MAX_FILES files on the command
+	 * line, exit with error message.						 */
+	if (num_files > _MAXFILES) prerr(TOOMANY, "");
+
+	/* If no files specified, simply exit.  Otherwise, if not the
+	 * old '-s' option, process all files. If '-s', then process
+	 * files one-at-a-time. */
+
+	if (!sflag)
+		docol(num_files, arg_ptr);	/* Column paste */
+	else
+		doserial(num_files, arg_ptr);	/* Serial paste */
+
+	exit(0);
+  } else
+	prerr(USAGE, "");
+  return(0);
+}
+
+void docol(nfiles, fnamptr)
+int nfiles;
+char **fnamptr;
+{
+  char iobuff[_MAXSZ];		/* i/o buffer for the fgets */
+  short int somedone;		/* flag for blank field handling */
+
+  /* There is a strange case where all files are just ready to be
+   * closed, or will on this round.  In that case, the string of
+   * delimiters must be preserved.  delbuf[1] ->delbuf[MAXFILES+1]
+   * provides intermediate storage for closed files, if needed;
+   * delbuf[0] is the current index.
+   */
+  char delbuf[_MAXFILES + 2];
+
+  FILE *fileptr[_MAXFILES + 1];
+
+  int filecnt;			/* Set to number of files to process */
+  register char *delimptr;	/* Cycling delimiter pointer */
+  int index;			/* Working variable */
+  int strend;			/* End of string in buffer */
+
+  /* Perform column paste.  First, attempt to open all files. (This
+   * could be expanded to an infinite number of files, but at the
+   * (considerable) expense of remembering the file and its current
+   * offset, then opening/reading/closing.  The commands' utility
+   * doesn't warrant the effort; at least, to me...) 
+   */
+
+  for (filecnt = 0; (nfiles > 0); fnamptr++) {
+	if ((fnamptr[0][0] == '-') && (fnamptr[0][1] != '\0')) {
+		if (fnamptr[0][1] == 'd') fnamptr++;
+	} else {
+		nfiles--;
+		if (fnamptr[0][0] == '-') {
+			fileptr[filecnt++] = stdin;
+		} else {
+			fileptr[filecnt] = fopen(fnamptr[0], "r");
+			if (fileptr[filecnt++] == NULL)
+				prerr(BADFILE, *fnamptr);
+		}
+	}
+  }
+
+  fileptr[filecnt] = ENDLIST;	/* End of list. */
+
+  /* Have all files.  Now, read a line from each file, and output to
+   * stdout.  Notice that the old 511 character limitation on the line
+   * length no longer applies, since this program doesn't do the
+   * buffering.  Do this until you go through the loop and don't
+   * successfully read from any of the files.
+   */
+  for (; filecnt;) {
+	somedone = 0;		/* Blank field handling flag */
+	delimptr = delims;	/* Start at beginning of delim list */
+	delbuf[0] = 0;		/* No squirreled delims */
+
+	for (index = 0; (fileptr[index] != ENDLIST) && filecnt; index++) {
+		/* Read a line and immediately output. If it's too
+		 * big for the buffer, then dump what was read and go
+		 * back for more.
+		 * 
+		 * Otherwise, if it is from the last file, then leave
+		 * the carriage return in place; if not, replace with
+		 * a delimiter (if any) 
+ 		 */
+
+		strend = 0;	/* Set so can easily detect EOF */
+
+		if (fileptr[index] != CLOSED)
+			while (fgets(iobuff, (_MAXSZ - 1), 
+					fileptr[index]) != NULL) {
+				strend = strlen(iobuff);/* Did the buf fill? */
+
+				if (strend == (_MAXSZ - 1)) {
+					/* Gosh, what a long line. */
+					fputs(iobuff, stdout);
+					strend = 0;
+					continue;
+				}
+
+				/* Ok got whole line in buffer. */
+				break;	/* Out of loop for this file */
+			}
+
+		/* Ended either on an EOF (well, actually NULL
+		 * return-- it *could* be some sort of file error,
+		 * but but if the file was opened successfully, this
+		 * is unlikely. Besides, error checking on streams
+		 * doesn't allow us to decide exactly what went
+		 * wrong, so I'm going to be very Unix-like and
+		 * ignore it!), or a closed file, or a received line.
+		 * If an EOF, close the file and mark it in the list.
+		 * In any case, output the delimiter of choice. 
+		 */
+
+		if (!strend) {
+			if (fileptr[index] != CLOSED) {
+				fclose(fileptr[index]);
+				fileptr[index] = CLOSED;
+				filecnt--;
+			}
+
+			/* Is this the end of the whole thing? */
+			if ((fileptr[index + 1] == ENDLIST) && !somedone)
+				continue;	/* EXITS */
+
+			/* Ok, some files not closed this line. Last file? */
+			if (fileptr[index + 1] == ENDLIST) {
+				if (delbuf[0]) {
+					fputs(&delbuf[1], stdout);
+					delbuf[0] = 0;
+				}
+				putc((int) NL, stdout);
+				continue;	/* Next read of files */
+			} else {
+				/* Closed file; setup delim */
+				if (*delimptr != DEL) {
+					delbuf[0]++;
+					delbuf[delbuf[0]] = *delimptr++;
+					delbuf[delbuf[0] + 1] = '\0';
+				} else
+					delimptr++;
+			}
+
+			/* Reset end of delimiter string if necessary */
+			if (*delimptr == '\0') delimptr = delims;
+		} else {
+			/* Some data read. */
+			somedone++;
+
+			/* Any saved delims? */
+			if (delbuf[0]) {
+				fputs(&delbuf[1], stdout);
+				delbuf[0] = 0;
+			}
+
+			/* If last file, last char will be NL. */
+			if (fileptr[index + 1] != ENDLIST) {
+				if (*delimptr == DEL) {
+					delimptr++;
+					iobuff[strend - 1] = '\0';/* No delim*/
+				} else
+					iobuff[strend - 1] = *delimptr++;
+			}
+			if (*delimptr == '\0') delimptr = delims;
+
+			/* Now dump the buffer */
+			fputs(iobuff, stdout);
+			fflush(stdout);
+		}
+	}
+  }
+}
+
+void doserial(nfiles, fnamptr)
+int nfiles;
+char **fnamptr;
+{
+  /* Do serial paste.  Simply scarf characters, performing
+   * one-character buffering to facilitate delim processing. 
+   */
+
+  register int charnew, charold;
+  register char *delimptr;
+
+  register FILE *fileptr;
+
+  for (; nfiles != 0; fnamptr++) {
+	if ((fnamptr[0][0] == '-') && (fnamptr[0][1] != '\0')) {
+		if (fnamptr[0][1] == 'd') fnamptr++;
+	} else {
+		if (fnamptr[0][0] == '-') {
+			fileptr = stdin;
+		} else {
+			fileptr = fopen(*fnamptr, "r");
+
+			if (fileptr == NULL) prerr(BADFILE, *fnamptr);
+		}
+
+		/* The file is open; just keep taking characters,
+		 * stashing them in charnew; output charold,
+		 * converting to the appropriate delimiter character
+		 * if needful.  After the EOF, simply output
+		 * 'charold' if it's a newline; otherwise, output it
+		 * and then a newline. 
+		 */
+
+		delimptr = delims;	/* Set up for delimiter string */
+
+		if ((charold = getc(fileptr)) == EOF) {
+			/* Empty file! */
+			putc(NL, stdout);
+			fflush(stdout);
+			continue;	/* Go on to the next file */
+		}
+
+		/* Ok, 'charold' is set up.  Hit it! */
+
+		while ((charnew = getc(fileptr)) != EOF) {
+			/* Ok, process the old character */
+			if (charold == NL) {
+				if (*delimptr != DEL)
+					putc((int) *delimptr++, stdout);
+
+				/* Reset pointer at end of delimiter string */
+				if (*delimptr == '\0') delimptr = delims;
+			} else
+				putc(charold, stdout);
+
+			charold = charnew;
+		}
+
+		/* Ok, hit EOF.  Process that last character */
+
+		putc(charold, stdout);
+		if ((char) charold != NL) putc(NL, stdout);
+		fflush(stdout);
+		nfiles--;
+	}
+  }
+}
+
+void delimbuild(strptr)
+char *strptr;
+{
+  /* Process the delimiter string into something that can be used by
+   * the routines.  This involves, primarily, collapsing the backslash
+   * representations of special characters into their actual values,
+   * and terminating the string in a manner that the routines can
+   * recognize.  The set of possible backslash characters has been
+   * expanded beyond that recognized by the vanilla Unix(Tm) version. 
+   */
+
+  register char *strout;
+
+  delims = strptr;		/* delims now points to argv[...]	 */
+  strout = strptr;		/* Start at the same place, anyway */
+
+  while (*strptr) {
+	if (*strptr != '\\')	/* Is it an escape character? */
+		*strout++ = *strptr++;	/* No, just transfer it */
+	else {
+		strptr++;	/* Get past escape character */
+
+		switch (*strptr) {
+		    case '0':	*strout++ = DEL;	break;
+
+		    case 't':	*strout++ = TAB;	break;
+
+		    case 'n':	*strout++ = NL;	break;
+
+		    case 'b':	*strout++ = BS;	break;
+
+		    case 'f':	*strout++ = FF;	break;
+
+		    case 'r':	*strout++ = CR;	break;
+
+		    case '\\':
+			*strout++ = BACKSLASH;
+			break;
+
+		    default:	*strout++ = *strptr;
+		}
+
+		strptr++;
+	}
+
+  }
+  *strout = '\0';		/* Heaven forfend that we forget this! */
+}
+
+void prerr(etype, estring)
+int etype;
+char *estring;
+{
+  switch (etype) {
+      case USAGE:
+	fprintf(stderr, "%s : Usage: %s [-s] [-d <delimiters>] file1 file2 ...\n", cmdnam, cmdnam);
+	break;
+
+      case NODELIM:
+	fprintf(stderr, "%s : no delimiters\n", cmdnam);
+	break;
+
+      case BADFILE:
+	fprintf(stderr, "%s : %s : cannot open\n", cmdnam, estring);
+	break;
+
+      case TOOMANY:
+	fprintf(stderr, "%s : too many files\n", cmdnam);
+	break;
+  }
+  exit(1);
+}
Index: /trunk/minix/commands/simple/ping.c
===================================================================
--- /trunk/minix/commands/simple/ping.c	(revision 9)
+++ /trunk/minix/commands/simple/ping.c	(revision 9)
@@ -0,0 +1,151 @@
+/*
+ping.c
+*/
+
+#define DEBUG	1
+
+#include <sys/types.h>
+#include <errno.h>
+#include <signal.h>
+#include <net/gen/netdb.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <net/gen/oneCsum.h>
+#include <fcntl.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/ip_hdr.h>
+#include <net/gen/icmp_hdr.h>
+#include <net/gen/ip_io.h>
+
+#define WRITE_SIZE 30
+char buffer[16*1024];
+
+int main(int argc, char *argv[]);
+
+#if DEBUG
+#define where() fprintf(stderr, "%s %d:", __FILE__, __LINE__);
+#endif
+
+#if __STDC__
+#define PROTO(x,y) x y
+#else
+#define PROTO(x,y) X ()
+#endif
+
+PROTO (int main, (int argc, char *argv[]) );
+static PROTO (void sig_hand, (int signal) );
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+	int fd, i;
+	int result, result1;
+	nwio_ipopt_t ipopt;
+	ip_hdr_t *ip_hdr;
+	int ihl;
+	icmp_hdr_t *icmp_hdr;
+	ipaddr_t dst_addr;
+	struct hostent *hostent;
+	int length;
+
+	if (argc<2 || argc>3)
+	{
+		fprintf(stderr, "Usage: %s hostname [-l length] [-t timeout]\n",
+			argv[0]);
+		exit(1);
+	}
+	hostent= gethostbyname(argv[1]);
+	if (!hostent)
+	{
+		dst_addr= inet_addr(argv[1]);
+		if (dst_addr == -1)
+		{
+			fprintf(stderr, "%s: unknown host (%s)\n",
+				argv[0], argv[1]);
+			exit(1);
+		}
+	}
+	else
+		dst_addr= *(ipaddr_t *)(hostent->h_addr);
+	if (argc == 3)
+	{
+		length= strtol (argv[2], (char **)0, 0);
+		if (length< sizeof(icmp_hdr_t) + IP_MIN_HDR_SIZE)
+		{
+			fprintf(stderr, "%s: length too small (%s)\n",
+				argv[0], argv[2]);
+			exit(1);
+		}
+	}
+	else
+		length= WRITE_SIZE;
+
+	fd= open ("/dev/ip", O_RDWR);
+	if (fd<0)
+		perror("open"), exit(1);
+
+	ipopt.nwio_flags= NWIO_COPY | NWIO_PROTOSPEC;
+	ipopt.nwio_proto= 1;
+
+	result= ioctl (fd, NWIOSIPOPT, &ipopt);
+	if (result<0)
+		perror("ioctl (NWIOSIPOPT)"), exit(1);
+
+	result= ioctl (fd, NWIOGIPOPT, &ipopt);
+	if (result<0)
+		perror("ioctl (NWIOGIPOPT)"), exit(1);
+
+	for (i= 0; i< 20; i++)
+	{
+		ip_hdr= (ip_hdr_t *)buffer;
+		ip_hdr->ih_dst= dst_addr;
+
+		icmp_hdr= (icmp_hdr_t *)(buffer+20);
+		icmp_hdr->ih_type= 8;
+		icmp_hdr->ih_code= 0;
+		icmp_hdr->ih_chksum= 0;
+		icmp_hdr->ih_chksum= ~oneC_sum(0, (u16_t *)icmp_hdr,
+			WRITE_SIZE-20);
+		result= write(fd, buffer, length);
+		if (result<0)
+		{
+			perror("write");
+			exit(1);
+		}
+		if (result != length)
+		{
+			where();
+			fprintf(stderr, "result= %d\n", result);
+			exit(1);
+		}
+
+		alarm(0);
+		signal (SIGALRM, sig_hand);
+		alarm(1);
+
+		result= read(fd, buffer, sizeof(buffer));
+		if (result>= 0 || errno != EINTR)
+			break;
+	}
+	if (i >= 20)
+	{
+		printf("no answer from %s\n", argv[1]);
+		exit(1);
+	}
+	if (result<0)
+	{
+		perror ("read");
+		exit(1);
+	}
+	printf("%s is alive\n", argv[1]);
+	exit(0);
+}
+
+static void sig_hand(signal)
+int signal;
+{
+}
Index: /trunk/minix/commands/simple/pr.c
===================================================================
--- /trunk/minix/commands/simple/pr.c	(revision 9)
+++ /trunk/minix/commands/simple/pr.c	(revision 9)
@@ -0,0 +1,504 @@
+/* pr - print files			Author: Michiel Huisjes */
+
+/* Pr - print files
+ *
+ * Author: Michiel Huisjes.
+ * Modified: Jacob P. Bunschoten.	(30 nov 87)
+ *	When "columns" is not given and numbering is on:
+ *		line numbers are correlated with input lines.
+ *	(try pr [-1] -n file )
+ *	tabs are accounted for.
+ *	When numbering is turned on, width know this.
+ *	automatic line-folding. -f to get the original program.
+ *	backspaces are accounted for. -b to disable this.
+ *	multi-column mode changed.
+ *	header can be given and used.
+ *	format changed may occur between printing of several files:
+ *		pr -l30 file1 -w75 file2
+ *
+ * Modified: Rick Thomas.		(Sept 12, 1988)
+ *	added "-M" option to cover functionality of old "-n" option,
+ *	and made "-n" option behavior compatible with system V.
+ *
+ * Usage: pr [+page] [-columns] [-h header] [-wwidth] [-llength] [-ntm] [files]
+ *        -t : Do not print the 5 line header and trailer at the page.
+ *        -n : Turn on line numbering.
+ *        -M : Use "Minix" style line numbering -- Each page begins at
+ *             a line number that is an even multiple of the page length.
+ *             Like the listings in Appendix E of the book.
+ *        +page    : Start printing at page n.
+ *        -columns : Print files in n-columns.
+ *        -l length: Take the length of the page to be n instead of 66
+ *        -h header: Take next argument as page header.
+ *        -w width  : Take the width of the page to be n instead of default 79
+ *	  -f : do not fold lines.
+ *
+ * Modified: Lars Fredriksen		(Jan 19, 1990)
+ *	fixed the program so that
+ *		pr -n *.c
+ *	would work. The clobal variable 'width' was decremented
+ *	by NUM_WIDTH, for each file, resulting in width finally
+ *	being so small that nothing was printed. Used the local
+ *	variable 'w' for the width adjustment (in print())
+ *
+ * Modified: Kenneth J. Hendrickson	(10 April 1991)
+ *	date in header should be last modification date for files,
+ *	and the current time for stdin.
+ *
+ * Modified: Kees J. Bot		(5 October 1992)
+ *	Use localtime(3) to get the date, it knows TZ.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+
+#define DEF_LENGTH	66
+#define DEF_WIDTH	79
+#define NUM_WIDTH	8
+#define TAB_WIDTH	8	/* fixed tab_width */
+
+/* Used to compute next (fixed) tabstop */
+#define TO_TAB(x)	(( (x) + TAB_WIDTH ) & ~07 )
+
+typedef char BOOL;
+
+#define FALSE		0
+#define TRUE		1
+
+/* EAT:	eat rest of input line */
+#define EAT(fp)		while((c=getc(fp))!='\n' && c!=EOF)
+
+/* L_BUF: calculate address of pointer to char (string) used in format */
+#define L_BUF(i,j)	* (char **) (line_buf + (i + j*length)*sizeof(char *))
+
+char *header;
+BOOL no_header;
+BOOL number = FALSE;
+BOOL minix_number = FALSE;
+BOOL ext_header_set = FALSE;	/* external header given */
+BOOL back_space = TRUE;		/* back space correction in line width */
+BOOL dont_fold = FALSE;		/* original. If the line does not fit eat it. */
+short columns;
+short cwidth;
+short start_page = 1;
+short width = DEF_WIDTH;
+short length = DEF_LENGTH;
+short linenr;
+char *line_buf;			/* used in format for multi-column output */
+
+char output[1024];
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(static char *myalloc, (size_t size));
+_PROTOTYPE(char skip_page, (int lines, int width, FILE * filep));
+_PROTOTYPE(void format, (FILE * filep));
+_PROTOTYPE(void print_page, (int pagenr, int maxcol));
+_PROTOTYPE(void print, (FILE * filep));
+_PROTOTYPE(void out_header, (int page));
+_PROTOTYPE(void print_time, (time_t t));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  FILE *file;
+  char *ptr;
+  int index = 1;		/* index is one ahead of argc */
+  int line, col;
+
+  setbuf(stdout, output);
+  do {
+	if (argc == index)	/* No arguments (left) */
+		goto pr_files;
+
+	ptr = argv[index++];
+	if (*ptr == '+') {
+		start_page = atoi(++ptr);
+		continue;
+	}
+	if (*ptr != '-') {	/* no flags */
+		index--;
+		goto pr_files;
+	}
+	if (*++ptr >= '0' && *ptr <= '9') {
+		columns = atoi(ptr);
+		if (columns <= 0) columns = 1;
+		continue;	/* Fetch next flag */
+	}
+	while (*ptr) switch (*ptr++) {
+		    case 't':	no_header = TRUE;	break;
+		    case 'n':
+			number = TRUE;
+			minix_number = FALSE;
+			break;
+		    case 'M':
+			number = TRUE;
+			minix_number = TRUE;
+			break;
+		    case 'h':
+			header = argv[index++];
+			ext_header_set = TRUE;
+			break;
+		    case 'w':
+			if ((width = atoi(ptr)) <= 0) width = DEF_WIDTH;
+			*ptr = '\0';
+			break;
+		    case 'l':
+			if ((length = atoi(ptr)) <= 0) length = DEF_LENGTH;
+			*ptr = '\0';
+			break;
+		    case 'b':	/* back_space correction off */
+			back_space = FALSE;
+			break;
+		    case 'f':	/* do not fold lines */
+			dont_fold = TRUE;
+			break;
+		    default:
+			fprintf(stderr, "Usage: %s [+page] [-columns] [-h header] [-w<width>] [-l<length>] [-nMt] [files]\n", argv[0]);
+			exit(1);
+		}
+	continue;		/* Scan for next flags */
+
+
+	/* ==============  flags are read. Print the file(s) ========= */
+
+pr_files:
+
+	if (!no_header) length -= 10;
+
+	if (columns) {
+		cwidth = width / columns + 1;
+		if (columns > width) {
+			fprintf(stderr, "Too many columns for page width.\n");
+			exit(1);
+		}
+
+		/* Allocate piece of mem to hold some pointers */
+		line_buf = myalloc(length * columns * sizeof(char *));
+	}
+	for (line = 0; line < length; line++)
+		for (col = 0; col < columns; col++)
+			L_BUF(line, col) = NULL;
+
+	if (length <= 0) {
+		fprintf(stderr, "Minimal length should be %d\n", no_header ?
+			1 : 11);
+		exit(1);
+	}
+	while (index <= argc) {	/* print all files, including stdin */
+		if (index < argc && (*argv[index] == '-' || *argv[index] == '+'))
+			break;	/* Format change */
+
+		if (argc == index) {	/* no file specified, so stdin */
+			if (!ext_header_set) header = "";
+			file = stdin;
+		} else {
+			if ((file = fopen(argv[index], "r")) == (FILE *) 0) {
+				fprintf(stderr, "Cannot open %s\n", argv[index++]);
+				continue;
+			}
+			if (!ext_header_set) header = argv[index];
+		}
+		if (columns)
+			format(file);
+		else
+			print(file);
+		fclose(file);
+		if (++index >= argc)
+			break;	/* all files (including stdin) done */
+	}
+	if (index >= argc) break;
+	/* When control comes here. format changes are to be done.
+	 * reinitialize some variables */
+	if (!no_header) length += 10;
+
+	start_page = 1;
+	ext_header_set = FALSE;
+	if (columns) free(line_buf);
+  } while (index <= argc);	/* "pr -l60" should work too */
+
+  (void) fflush(stdout);
+  return(0);
+}
+
+char skip_page(lines, width, filep)
+int lines, width;
+FILE *filep;
+{
+  short c;
+  int char_cnt;
+  int w;
+
+  do {
+	w = width;
+	if (number)		/* first lines are shorter */
+		if (!columns ||	/* called from print(file)  */
+		    !(lines % columns))	/* called from format(file) */
+			w -= NUM_WIDTH;
+
+	char_cnt = 0;
+	while ((c = getc(filep)) != '\n' && c != EOF && char_cnt < w) {
+		/* Calculate if this line is longer than "width (w)"
+		 * characters */
+		if (c == '\b' && back_space) {
+			if (--char_cnt < 0) char_cnt = 0;
+		} else if (c == '\t')
+			char_cnt = TO_TAB(char_cnt);
+		else
+			char_cnt++;
+	}
+	if (dont_fold && c != '\n' && c != EOF) EAT(filep);
+	lines--;
+	if (c == '\n') linenr++;
+  } while (lines > 0 && c != EOF);
+
+  return c;			/* last char read */
+}
+
+void format(filep)
+FILE *filep;
+{
+  char buf[512];
+  short c = '\0';
+  short index, lines, i;
+  short page_number = 0;
+  short maxcol = columns;
+  short wdth;
+  short line, col;
+
+  do {
+	/* Check printing of page */
+	page_number++;
+
+	if (page_number < start_page && c != EOF) {
+		c = (char) skip_page(columns * length, cwidth, filep);
+		continue;
+	}
+	if (c == EOF) return;
+
+	lines = columns * length;
+	for (line = 0; line < length; line++)
+		for (col = 0; col < columns; col++) {
+			if (L_BUF(line, col) != NULL)
+				free(L_BUF(line, col));
+			L_BUF(line, col) = (char *) NULL;
+		}
+	line = 0;
+	col = 0;
+	do {
+		index = 0;
+		wdth = cwidth - 1;
+		if (number && !col)	/* need room for numbers */
+			wdth -= NUM_WIDTH;
+
+		/* Intermidiate colums are shortened by 1 char */
+		/* Last column not */
+		if (col + 1 == columns) wdth++;
+		for (i = 0; i < wdth - 1; i++) {
+			c = getc(filep);
+			if (c == '\n' || c == EOF) break;
+
+			if (c == '\b' && back_space) {
+				buf[index++] = '\b';
+				if (--i < 0) {	/* just in case ... */
+					i = 0;
+					index = 0;
+				}
+			} else if (c == '\t') {
+				int cnt, max;
+
+				max = TO_TAB(i);
+				for (cnt = i; cnt < max; cnt++)
+					buf[index++] = ' ';
+				i = max - 1;
+			} else
+				buf[index++] = (char) c;
+		}
+		buf[index++] = '\0';
+		/* Collected enough chars (or eoln, or EOF) */
+
+		/* First char is EOF */
+		if (i == 0 && lines == columns * length && c == EOF) return;
+
+		/* Alloc mem to hold this (sub) string */
+		L_BUF(line, col) = myalloc(index * sizeof(char));
+		strcpy(L_BUF(line, col), buf);
+
+		line++;
+		line %= length;
+		if (line == 0) {
+			col++;
+			col %= columns;
+		}
+		if (dont_fold && c != '\n' && c != EOF) EAT(filep);
+		lines--;	/* line ready for output */
+		if (c == EOF) {
+			maxcol = columns - lines / length;
+		}
+	} while (c != EOF && lines);
+	print_page(page_number, maxcol);
+  } while (c != EOF);
+}
+
+void print_page(pagenr, maxcol)
+short pagenr, maxcol;
+{
+  short pad, i, j;
+  short width;
+  char *p;
+
+  if (minix_number)
+	linenr = (pagenr - 1) * length + 1;
+  else
+	linenr = 1;
+
+  if (!no_header) out_header(pagenr);
+
+  for (i = 0; i < length; i++) {
+	for (j = 0; j < maxcol; j++) {
+		width = cwidth;
+		if (number && j == 0) {	/* first columns */
+			printf("%7.7d ", linenr++);	/* 7 == NUM_WIDTH-1 */
+			width -= NUM_WIDTH;
+		}
+		pad = 0;
+		if (p = (char *) L_BUF(i, j))
+			for (; pad < width - 1 && *p; pad++) putchar(*p++);
+		if (j < maxcol - 1) while (pad++ < width - 1)
+				putchar(' ');
+	}
+	putchar('\n');
+  }
+  if (!no_header) printf("\n\n\n\n\n");
+}
+
+void print(filep)
+FILE *filep;
+{
+  short c = '\0';
+  short page_number = 0;
+  short lines;
+  short cnt;
+  short w = width;
+  BOOL pr_number = TRUE;	/* only real lines are numbered, not folded
+			 * parts */
+
+  linenr = 1;
+  if (number) w -= NUM_WIDTH;
+
+  do {
+	/* Check printing of page */
+	page_number++;
+
+	if (page_number < start_page && c != EOF) {
+		pr_number = FALSE;
+		c = skip_page(length, w, filep);
+		if (c == '\n') pr_number = TRUE;
+		continue;
+	}
+	if (c == EOF) return;
+
+	if (minix_number) linenr = (page_number - 1) * length + 1;
+
+	if (page_number == start_page) c = getc(filep);
+
+	/* Print the page */
+	lines = length;
+	while (lines && c != EOF) {
+		if (lines == length && !no_header) out_header(page_number);
+		if (number)
+			if (pr_number)
+				printf("%7.7d ", linenr++);	/* 7 == NUM_WIDTH-1 */
+			else
+				printf("%7c ", ' ');	/* 7 == NUM_WIDTH-1 */
+		pr_number = FALSE;
+		cnt = 0;
+		while (c != '\n' && c != EOF && cnt < w) {
+			if (c == '\t') {
+				int i, max;
+				max = TO_TAB(cnt);
+				for (i = cnt; i < max; i++) putchar(' ');
+				cnt = max - 1;
+			} else if (c == '\b' && back_space) {
+				putchar('\b');
+				cnt--;
+			} else
+				putchar(c);
+			c = getc(filep);
+			cnt++;
+		}
+		putchar('\n');
+		if (dont_fold && c != '\n' && c != EOF) EAT(filep);
+		lines--;
+		if (c == '\n') {
+			c = getc(filep);
+			pr_number = TRUE;
+		}
+	}
+	if (lines == length)	/* We never printed anything on this
+				 * page --  */
+		return;		/* even the header, so dont try to fill it up */
+	if (!no_header)		/* print the trailer -- 5 blank lines */
+		printf("\n\n\n\n\n");
+  } while (c != EOF);
+
+  /* Fill last page */
+  if (page_number >= start_page) {
+	while (lines--) putchar('\n');
+  }
+}
+
+static char *myalloc(size)
+size_t size;			/* How many bytes */
+{
+  void *ptr;
+
+  ptr = malloc(size);
+  if (ptr == NULL) {
+	fprintf(stderr, "malloc returned NULL\n");
+	exit(1);
+  }
+  return(char *) ptr;
+}
+
+void out_header(page)
+short page;
+{
+  time_t t;
+  struct stat buf;
+
+  if (strlen(header)) {
+	stat(header, &buf);	/* use last modify time for file */
+	t = buf.st_mtime;
+  } else
+	(void) time(&t);	/* use current time for stdin */
+  print_time(t);
+  printf("  %s   Page %d\n\n\n", header, page);
+}
+
+char *moname[] = {
+	  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+/* Print the date. */
+void print_time(t)
+time_t t;
+{
+  struct tm *tm;
+
+  tm = localtime(&t);
+
+  printf("\n\n%s %2d %2d:%02d %d",
+         moname[tm->tm_mon],
+         tm->tm_mday,
+         tm->tm_hour,
+         tm->tm_min,
+         1900 + tm->tm_year
+	);
+}
Index: /trunk/minix/commands/simple/pr_routes.c
===================================================================
--- /trunk/minix/commands/simple/pr_routes.c	(revision 9)
+++ /trunk/minix/commands/simple/pr_routes.c	(revision 9)
@@ -0,0 +1,307 @@
+/*
+vmd/cmd/simple/pr_routes.c
+*/
+
+#define _POSIX_C_SOURCE 2
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/ip_io.h>
+#include <net/gen/route.h>
+#include <net/gen/netdb.h>
+#include <net/gen/inet.h>
+
+#define N_IF	64	/* More than enough? */
+
+char *prog_name;
+int all_devices;
+char *ifname;
+ipaddr_t iftab[N_IF];
+
+static void print_header(void);
+static void print_route(nwio_route_t *route);
+static void fill_iftab(void);
+static char *get_ifname(ipaddr_t addr);
+static void fatal(char *fmt, ...);
+static void usage(void);
+
+int main(int argc, char *argv[])
+{
+	int nr_routes, i;
+	nwio_route_t route;
+	nwio_ipconf_t ip_conf;
+	unsigned long ioctl_cmd;
+	int ip_fd;
+	int result;
+	int c;
+	char *ip_device, *cp;
+	int a_flag, i_flag, o_flag;
+	char *I_arg;
+
+	prog_name= argv[0];
+
+	a_flag= 0;
+	i_flag= 0;
+	o_flag= 0;
+	I_arg= NULL;
+	while ((c =getopt(argc, argv, "?aI:io")) != -1)
+	{
+		switch(c)
+		{
+		case '?':
+			usage();
+		case 'a':
+			if (a_flag)
+				usage();
+			a_flag= 1;
+			break;
+		case 'I':
+			if (I_arg)
+				usage();
+			I_arg= optarg;
+			break;
+		case 'i':
+			if (i_flag || o_flag)
+				usage();
+			i_flag= 1;
+			break;
+		case 'o':
+			if (i_flag || o_flag)
+				usage();
+			o_flag= 1;
+			break;
+		default:
+			fprintf(stderr, "%s: getopt failed: '%c'\n",
+				prog_name, c);
+			exit(1);
+		}
+	}
+	if (optind != argc)
+		usage();
+
+	ip_device= I_arg;
+	all_devices= a_flag;
+
+	if (i_flag)
+		ioctl_cmd= NWIOGIPIROUTE;
+	else
+		ioctl_cmd= NWIOGIPOROUTE;
+
+	if (ip_device == NULL)
+		ip_device= getenv("IP_DEVICE");
+	ifname= ip_device;
+	if (ip_device == NULL)
+		ip_device= IP_DEVICE;
+		
+	ip_fd= open(ip_device, O_RDONLY);
+	if (ip_fd == -1)
+	{
+		fprintf(stderr, "%s: unable to open %s: %s\n", prog_name,
+			ip_device, strerror(errno));
+		exit(1);
+	}
+
+	if (!all_devices && ifname)
+	{
+		cp= strrchr(ip_device, '/');
+		if (cp)
+			ifname= cp+1;
+	}
+	else
+	{
+		ifname= NULL;
+		fill_iftab();
+	}
+
+	result= ioctl(ip_fd, NWIOGIPCONF, &ip_conf);
+	if (result == -1)
+	{
+		fprintf(stderr, "%s: unable to NWIOIPGCONF: %s\n",
+			prog_name, strerror(errno));
+		exit(1);
+	}
+
+	route.nwr_ent_no= 0;
+	result= ioctl(ip_fd, ioctl_cmd, &route);
+	if (result == -1)
+	{
+		fprintf(stderr, "%s: unable to NWIOGIPxROUTE: %s\n",
+			prog_name, strerror(errno));
+		exit(1);
+	}
+	print_header();
+	nr_routes= route.nwr_ent_count;
+	for (i= 0; i<nr_routes; i++)
+	{
+		route.nwr_ent_no= i;
+		result= ioctl(ip_fd, ioctl_cmd, &route);
+		if (result == -1)
+		{
+			fprintf(stderr, "%s: unable to NWIOGIPxROUTE: %s\n",
+				prog_name, strerror(errno));
+			exit(1);
+		}
+		if (all_devices || route.nwr_ifaddr == ip_conf.nwic_ipaddr)
+			print_route(&route);
+	}
+	exit(0);
+}
+
+int ent_width= 5;
+int if_width= 4;
+int dest_width= 18;
+int gateway_width= 15;
+int dist_width= 4;
+int pref_width= 5;
+int mtu_width= 4;
+
+static void print_header(void)
+{
+	printf("%*s ", ent_width, "ent #");
+	printf("%*s ", if_width, "if");
+	printf("%*s ", dest_width, "dest");
+	printf("%*s ", gateway_width, "gateway");
+	printf("%*s ", dist_width, "dist");
+	printf("%*s ", pref_width, "pref");
+	printf("%*s ", mtu_width, "mtu");
+	printf("%s", "flags");
+	printf("\n");
+}
+
+static char *cidr2a(ipaddr_t addr, ipaddr_t mask)
+{
+	ipaddr_t testmask= 0xFFFFFFFF;
+	int n;
+	static char result[sizeof("255.255.255.255/255.255.255.255")];
+
+	for (n= 32; n >= 0; n--)
+	{
+		if (mask == htonl(testmask))
+			break;
+		testmask= (testmask << 1) & 0xFFFFFFFF;
+	}
+
+	sprintf(result, "%s/%-2d", inet_ntoa(addr), n);
+	if (n == -1)
+		strcpy(strchr(result, '/')+1, inet_ntoa(mask));
+	return result;
+}
+
+static void print_route(nwio_route_t *route)
+{
+	if (!(route->nwr_flags & NWRF_INUSE))
+		return;
+
+	printf("%*lu ", ent_width, (unsigned long) route->nwr_ent_no);
+	printf("%*s ", if_width,
+		ifname ?  ifname : get_ifname(route->nwr_ifaddr));
+	printf("%*s ", dest_width, cidr2a(route->nwr_dest, route->nwr_netmask));
+	printf("%*s ", gateway_width, inet_ntoa(route->nwr_gateway));
+	printf("%*lu ", dist_width, (unsigned long) route->nwr_dist);
+	printf("%*ld ", pref_width, (long) route->nwr_pref);
+	printf("%*lu", mtu_width, (long) route->nwr_mtu);
+	if (route->nwr_flags & NWRF_STATIC)
+		printf(" static");
+	if (route->nwr_flags & NWRF_UNREACHABLE)
+		printf(" dead");
+	printf("\n");
+}
+
+static void fill_iftab(void)
+{
+	int i, j, r, fd;
+	nwio_ipconf_t ip_conf;
+	char dev_name[12];	/* /dev/ipXXXX */
+
+	for (i= 0; i<N_IF; i++)
+	{
+		iftab[i]= 0;
+
+		sprintf(dev_name, "/dev/ip%d", i);
+		fd= open(dev_name, O_RDWR);
+		if (fd == -1)
+		{
+			if (errno == EACCES || errno == ENOENT || errno == ENXIO)
+				continue;
+			fatal("unable to open '%s': %s",
+				dev_name, strerror(errno));
+		}
+		fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
+		r= ioctl(fd, NWIOGIPCONF, &ip_conf);
+		if (r == -1 && errno == EAGAIN)
+		{
+			/* interface is down */
+			close(fd);
+			continue;
+		}
+		if (r == -1)
+		{
+			fatal("NWIOGIPCONF failed on %s: %s",
+				dev_name, strerror(errno));
+		}
+
+		iftab[i]= ip_conf.nwic_ipaddr;
+		close(fd);
+
+		for (j= 0; j<i; j++)
+		{
+			if (iftab[j] == iftab[i])
+			{
+				fatal("duplicate address in ip%d and ip%d: %s",
+					i, j, inet_ntoa(iftab[i]));
+			}
+		}
+
+	}
+}
+
+static char *get_ifname(ipaddr_t addr)
+{
+	static char name[7];	/* ipXXXX */
+
+	int i;
+
+	for (i= 0; i<N_IF; i++)
+	{
+		if (iftab[i] != addr)
+			continue;
+		sprintf(name, "ip%d", i);
+		return name;
+	}
+
+	return inet_ntoa(addr);
+}
+
+static void fatal(char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	fprintf(stderr, "%s: ", prog_name);
+	vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+	va_end(ap);
+	exit(1);
+}
+
+static void usage(void)
+{
+	fprintf(stderr, "Usage: %s [-i|-o] [ -a ] [ -I <ip-device> ]\n",
+		prog_name);
+	exit(1);
+}
+
+/*
+ * $PchId: pr_routes.c,v 1.8 2002/04/11 10:58:58 philip Exp $
+ */
Index: /trunk/minix/commands/simple/prep.c
===================================================================
--- /trunk/minix/commands/simple/prep.c	(revision 9)
+++ /trunk/minix/commands/simple/prep.c	(revision 9)
@@ -0,0 +1,136 @@
+/* prep - prepare file for statistics 	Author: Andy Tanenbaum */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define TROFF_CHAR	'.'	/* troff commands begin with this char */
+#define EOL		'\n'	/* end of line char */
+#define APOSTROPHE	047	/* single quote */
+#define BACKSLASH       '\\'	/* troff code */
+
+int lfread;			/* set when last char read was lf */
+int lfwritten = 1;		/* set when last char written was lf */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void skipline, (void));
+_PROTOTYPE(int backslash, (void));
+_PROTOTYPE(void usage, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+
+  int c;
+
+  if (argc > 2) usage();
+  if (argc == 2) {
+	if (freopen(argv[1], "r", stdin) == NULL) {
+		printf("prep: cannot open %s\n", argv[1]);
+		exit(1);
+	}
+  }
+  while ((c = getchar()) != EOF) {
+	/* Lines beginning with "." are troff commands -- skip them. */
+	if (lfread && c == TROFF_CHAR) {
+		skipline();
+		continue;
+	}
+	while (c == BACKSLASH) c = backslash();	/* eat troff stuff */
+
+	if (isupper(c)) {
+		putchar(tolower(c));
+		lfwritten = 0;
+		lfread = 0;
+		continue;
+	}
+	if (islower(c)) {
+		putchar(c);
+		lfwritten = 0;
+		lfread = 0;
+		continue;
+	}
+	if (c == APOSTROPHE) {
+		putchar(c);
+		lfwritten = 0;
+		lfread = 0;
+		continue;
+	}
+	lfread = (c == EOL ? 1 : 0);
+	if (lfwritten) continue;
+	putchar(EOL);
+	lfwritten = 1;
+  }
+  return(0);
+}
+
+
+void skipline()
+{
+  char c;
+
+  while ((c = getchar()) != EOL);
+}
+
+
+int backslash()
+{
+/* A backslash has been seen.  Eat troff stuff. */
+
+  int c, c1, c2;
+
+  c = getchar();
+  switch (c) {
+      case 'f':
+	c = getchar();
+	c = getchar();
+	return(c);
+
+      case 's':			/* \s7  or \s14 */
+	c = getchar();
+	c = getchar();
+	if (isdigit(c)) c = getchar();
+	return(c);
+
+      case 'n':			/* \na or \n(xx  */
+	c = getchar();
+	if (c == '(') {
+		c = getchar();
+		c = getchar();
+	}
+	c = getchar();
+	return(c);
+
+      case '*':			/* / * (XX */
+	c = getchar();
+	if (c == '(') {
+		c = getchar();
+		c = getchar();
+		c = getchar();
+		return(c);
+	}
+
+      case '(':			/* troff 4-character escape sequence */
+	c1 = getchar();
+	c2 = getchar();
+	if (c1 == 'e' && c2 == 'm') return(' ');
+	if (c1 == 'e' && c2 == 'n') return(' ');
+	c = getchar();
+	return(c);
+
+      case '%':			/* soft hyphen: \% */
+	c = getchar();
+	return(c);
+
+      default:
+	return(c);
+
+  }
+}
+
+void usage()
+{
+  printf("Usage: prep [file]\n");
+  exit(1);
+}
Index: /trunk/minix/commands/simple/printenv.c
===================================================================
--- /trunk/minix/commands/simple/printenv.c	(revision 9)
+++ /trunk/minix/commands/simple/printenv.c	(revision 9)
@@ -0,0 +1,12 @@
+
+#include <stdio.h>
+
+int main(int argc, char *argv[], char *envp[])
+{
+	int p;
+	for(p = 0; envp[p] && *envp[p]; p++) {
+		printf("%s\n", envp[p]);
+	}
+	return 0;
+}
+
Index: /trunk/minix/commands/simple/printf.c
===================================================================
--- /trunk/minix/commands/simple/printf.c	(revision 9)
+++ /trunk/minix/commands/simple/printf.c	(revision 9)
@@ -0,0 +1,471 @@
+#if ever
+static char sccsid[] = "@(#)printf.c	(U of Maryland) FLB 6-Jan-1987";
+static char RCSid[] = "@(#)$Header: /cvsup/minix/src/commands/simple/printf.c,v 1.1.1.1 2005/04/21 14:55:31 beng Exp $";
+#endif
+
+/*
+ * Printf - Duplicate the C library routine of the same name, but from
+ *	    the shell command level.
+ *
+ * Fred Blonder <fred@Mimsy.umd.edu>
+ *
+ * To Compile:
+ %	cc -s -O printf.c -o printf
+ *
+ * $Log: printf.c,v $
+ * Revision 1.1.1.1  2005/04/21 14:55:31  beng
+ * Initial import of pre-3.0.1
+ *
+ * Revision 1.1.1.1  2005/04/20 13:33:30  beng
+ * Initial import of minix 2.0.4
+ *
+ * Revision 1.4  87/01/29  20:52:30  fred
+ * Re-installed backslash-notation conversion for string & char arguments.
+ * 
+ * Revision 1.3  87/01/29  20:44:23  fred
+ * Converted to portable algorithm.
+ * Added Roman format for integers.
+ * 	29-Jan-87  FLB
+ * 
+ * Revision 1.2  87/01/09  19:10:57  fred
+ * Fixed bug in argument-count error-checking.
+ * Changed backslash escapes within strings to correspond to ANSII C
+ * 	draft standard.  (9-Jan-87 FLB)
+ * 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define EX_OK		0
+#define EX_USAGE	1
+
+int ctrl(char *s);
+
+#define atoi(a)		strtoul((a), NULL, 0)
+
+/****************************************************************************/
+
+int main(int argc, char *argv[])
+{
+register char *cp, *conv_spec, **argp, **ep;
+char *ctor(int x);
+
+if (argc < 2) {
+	fprintf(stderr,
+		"printf: Usage: printf <format-string> [ arg1 . . . ]\n");
+	exit(EX_USAGE);
+	}
+
+argp = &argv[2];	/* Point at first arg (if any) beyond format string. */
+ep = &argv[argc];	/* Point beyond last arg. */
+
+ctrl(argv[1]);	/* Change backslash notation to control chars in fmt string. */
+
+/* Scan format string for conversion specifications, and do appropriate
+   conversion on the corresponding argument. */
+for (cp = argv[1]; *cp; cp++) {
+register int dynamic_count;
+
+	/* Look for next conversion spec. */
+	while (*cp && *cp != '%') {
+		putchar(*cp++);
+		}
+
+	if (!*cp)	/* End of format string */
+		break;
+		
+	dynamic_count = 0;	/* Begin counting dynamic field width specs. */
+	conv_spec = cp++;	/* Remember where this conversion begins. */
+
+	for (;*cp; cp++) {	/* Scan until conversion character. */
+		char conv_buf[BUFSIZ];	/* Save conversion string here. */
+		register int conv_len;	/* Length of ``conv_buf''. */
+
+		switch (*cp) {	/* Field-width spec.: Keep scanning. */
+			case '.': case '0': case '1': case '2': case '3':
+			case '4': case '5': case '6': case '7': case '8':
+			case '9':
+				continue;
+
+			case '*':	/* Dynamic field-width spec */
+				dynamic_count++;
+				continue;
+
+			case 's':	/* String */
+				if (&argp[dynamic_count] >= ep) {
+					fprintf(stderr,
+					"printf: Not enough args for format.\n"
+						);
+					exit(EX_USAGE);
+					}
+
+				(void) strncpy(conv_buf, conv_spec,
+					conv_len = cp - conv_spec + 1);
+				conv_buf[conv_len] = '\0';
+
+				switch (dynamic_count) {
+					case 0:
+						ctrl(*argp);
+						printf(conv_buf, *argp++);
+						break;
+
+					case 1:
+						{
+						register int a1;
+
+						a1 = atoi(*argp++);
+						ctrl(*argp);
+						printf(conv_buf, a1, *argp++);
+						}
+						break;
+
+					case 2:
+						{
+						register int a1, a2;
+
+						a1 = atoi(*argp++);
+						a2 = atoi(*argp++);
+						ctrl(*argp);
+						printf(conv_buf, a1, a2, *argp++);
+						}
+						break;
+
+					}
+				goto out;
+
+			case 'c':	/* Char */
+				if (&argp[dynamic_count] >= ep) {
+					fprintf(stderr,
+					"printf: Not enough args for format.\n"
+						);
+					exit(EX_USAGE);
+					}
+
+				(void) strncpy(conv_buf, conv_spec,
+					conv_len = cp - conv_spec + 1);
+				conv_buf[conv_len] = '\0';
+
+				switch (dynamic_count) {
+					case 0:
+						ctrl(*argp);
+						printf(conv_buf, **argp++);
+						break;
+
+					case 1:
+						{
+						register int a1;
+
+						a1 = atoi(*argp++);
+						ctrl(*argp);
+						printf(conv_buf, a1, **argp++);
+						}
+						break;
+
+					case 2:
+						{
+						register int a1, a2;
+
+						a1 = atoi(*argp++);
+						a2 = atoi(*argp++);
+						ctrl(*argp);
+						printf(conv_buf, a1, a2, **argp++);
+						}
+						break;
+					}
+				goto out;
+
+			case 'd':	/* Integer */
+			case 'o':
+			case 'x':
+			case 'X':
+			case 'u':
+				if (&argp[dynamic_count] >= ep) {
+					fprintf(stderr,
+					"printf: Not enough args for format.\n"
+						);
+					exit(EX_USAGE);
+					}
+
+				(void) strncpy(conv_buf, conv_spec,
+					conv_len = cp - conv_spec + 1);
+				conv_buf[conv_len] = '\0';
+
+				switch (dynamic_count) {
+					case 0:
+						printf(conv_buf, atoi(*argp++));
+						break;
+
+					case 1:
+						{
+						register int a1;
+
+						a1 = atoi(*argp++);
+						printf(conv_buf, a1, atoi(*argp++));
+						}
+						break;
+
+					case 2:
+						{
+						register int a1, a2;
+
+						a1 = atoi(*argp++);
+						a2 = atoi(*argp++);
+						printf(conv_buf, a1, a2, atoi(*argp++));
+						}
+						break;
+
+					}
+				goto out;
+
+			case 'f':	/* Real */
+			case 'e':
+			case 'g':
+				if (&argp[dynamic_count] >= ep) {
+					fprintf(stderr,
+					"printf: Not enough args for format.\n"
+						);
+					exit(EX_USAGE);
+					}
+
+				(void) strncpy(conv_buf, conv_spec,
+					conv_len = cp - conv_spec + 1);
+				conv_buf[conv_len] = '\0';
+
+				switch (dynamic_count) {
+					case 0:
+						printf(conv_buf, atof(*argp++));
+						break;
+
+					case 1:
+						{
+						register int a1;
+
+						a1 = atoi(*argp++);
+						printf(conv_buf, a1, atof(*argp++));
+						}
+						break;
+
+					case 2:
+						{
+						register int a1, a2;
+
+						a1 = atoi(*argp++);
+						a2 = atoi(*argp++);
+						printf(conv_buf, a1, a2, atof(*argp++));
+						}
+						break;
+
+					}
+				goto out;
+
+			case 'r':	/* Roman (Well, why not?) */
+				if (&argp[dynamic_count] >= ep) {
+					fprintf(stderr,
+					"printf: Not enough args for format.\n"
+						);
+					exit(EX_USAGE);
+					}
+
+				(void) strncpy(conv_buf, conv_spec,
+					conv_len = cp - conv_spec + 1);
+				conv_buf[conv_len] = '\0';
+				conv_buf[conv_len - 1] = 's';
+
+				switch (dynamic_count) {
+					case 0:
+						printf(conv_buf,
+							ctor(atoi(*argp++)));
+						break;
+
+					case 1:
+						{
+						register int a1;
+
+						a1 = atoi(*argp++);
+						printf(conv_buf, a1,
+							ctor(atoi(*argp++)));
+						}
+						break;
+
+					case 2:
+						{
+						register int a1, a2;
+
+						a1 = atoi(*argp++);
+						a2 = atoi(*argp++);
+						printf(conv_buf, a1, a2,
+							ctor(atoi(*argp++)));
+						}
+						break;
+
+					}
+				goto out;
+
+			case '%':	/* Boring */
+				putchar('%');
+				break;
+
+			default:	/* Probably an error, but let user
+					   have his way. */
+				continue;
+			}
+		}
+	out: ;
+	}
+
+exit(EX_OK);
+}
+
+/****************************************************************************/
+
+/* Convert backslash notation to control characters, in place. */
+
+int ctrl(char *s)
+{
+register char *op;
+static int val;
+
+for (op = s; *s; s++)
+	if (*s == '\\')
+		switch (*++s) {
+			case '\0':	/* End-of-string: user goofed */
+				goto out;
+
+			case '\\':	/* Backslash */
+				*op++ = '\\';
+				break;
+
+			case 'n':	/* newline */
+				*op++ = '\n';
+				break;
+
+			case 't':	/* horizontal tab */
+				*op++ = '\t';
+				break;
+
+			case 'r':	/* carriage-return */
+				*op++ = '\r';
+				break;
+
+			case 'f':	/* form-feed */
+				*op++ = '\f';
+				break;
+
+			case 'b':	/* backspace */
+				*op++ = '\b';
+				break;
+
+			case 'v':	/* vertical tab */
+				*op++ = '\13';
+				break;
+
+			case 'a':	/* WARNING! DANGER! DANGER! DANGER! */
+				*op++ = '\7';
+				break;
+
+			case '0': case '1': case '2': case '3':
+			case '4': case '5': case '6': case '7':
+				{	/* octal constant */
+				register int digits;
+
+				val = 0;
+				(void) sscanf(s, "%3o", &val);
+				*op++ = val;
+				for (digits = 3; s[1] &&
+					strchr("01234567", s[1])
+					&& --digits > 0;
+						s++);
+				}
+				break;
+
+			case 'x':	/* hex constant */
+			case 'X':
+				s++;
+				{
+				register int digits;
+
+				val = 0;
+				(void) sscanf(s, "%3x", &val);
+				*op++ = val;
+				for (digits = 3; *s && s[1] &&
+					strchr("0123456789abcdefABCDEF",
+									s[1])
+					&& --digits > 0;
+						s++);
+				}
+				break;
+
+			}
+	else
+		*op++ = *s;
+
+out:
+
+*op = '\0';
+}
+
+/****************************************************************************/
+
+/* Convert integer to Roman Numerals. (Have have you survived without it?) */
+
+struct roman {
+	unsigned r_mag;
+	char r_units, r_fives;
+	} roman[] = {
+		{ 1000, 'M', '\0', },
+		{  100, 'C', 'D',  },
+		{   10, 'X', 'L',  },
+		{    1, 'I', 'V',  },
+		};
+
+char *ctor(int x)
+{
+register struct roman *mp;
+static char buf[BUFSIZ];
+register char *cp = buf;
+
+/* I've never actually seen a roman numeral with a minus-sign.
+   Probably ought to print out some appropriate latin phrase instead. */
+if (x < 0) {
+	*cp++ = '-';
+	x = -x;
+	}
+
+for (mp = roman; x; mp++) {
+	register unsigned units;
+
+	units = x / mp->r_mag;
+	x = x % mp->r_mag;
+
+	if (cp > &buf[BUFSIZ-2])
+		return "???";
+
+	if (units == 9 && mp > roman) {	/* Do inverse notation: Eg: ``IX''. */
+		*cp++ = mp->r_units;
+		*cp++ = mp[-1].r_units;
+		}
+	else if (units == 4 && mp->r_fives) {
+		/* Inverse notation for half-decades: Eg: ``IV'' */
+		*cp++ = mp->r_units;
+		*cp++ = mp->r_fives;
+		}
+	else {	/* Additive notation */
+		if (units >= 5 && mp->r_fives) {
+			*cp++ = mp->r_fives;
+			units -= 5;
+			}
+		while (units--) {
+			*cp++ = mp->r_units;
+			if (cp > &buf[BUFSIZ-5])
+				return "???";
+			}
+		}
+	}
+
+*cp = '\0';
+
+return buf;
+}
+
+/****************************************************************************/
Index: /trunk/minix/commands/simple/printroot.c
===================================================================
--- /trunk/minix/commands/simple/printroot.c	(revision 9)
+++ /trunk/minix/commands/simple/printroot.c	(revision 9)
@@ -0,0 +1,85 @@
+/* printroot - print root device on stdout	Author: Bruce Evans */
+
+/* This program figures out what the root device is by doing a stat on it, and
+ * then searching /dev until it finds an entry with the same device number.
+ * A typical use (probably the only use) is in /etc/rc for initializing
+ * /etc/mtab, as follows:
+ *
+ *	/usr/bin/printroot >/etc/mtab
+ *
+ *  9 Dec 1989	- clean up for 1.5 - full prototypes (BDE)
+ * 15 Oct 1989	- avoid ACK cc bugs (BDE):
+ *		- sizeof "foo" is 2 (from wrong type char *) instead of 4
+ *		- char foo[10] = "bar"; allocates 4 bytes instead of 10
+ *  1 Oct 1989	- Minor changes by Andy Tanenbaum
+ *  5 Oct 1992	- Use readdir (kjb)
+ * 26 Nov 1994	- Flag -r: print just the root device (kjb)
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <minix/minlib.h>
+#include <dirent.h>
+
+static char DEV_PATH[] = "/dev/";	/* #define would step on sizeof bug */
+static char MESSAGE[] = " / ";	/* ditto */
+#define UNKNOWN_DEV	"/dev/unknown"
+#define ROOT		"/"
+int rflag;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void done, (char *name, int status));
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  DIR *dp;
+  struct dirent *entry;
+  struct stat filestat, rootstat;
+  static char namebuf[sizeof DEV_PATH + NAME_MAX];
+
+  rflag = (argc > 1 && strcmp(argv[1], "-r") == 0);
+
+  if (stat(ROOT, &rootstat) == 0 && (dp = opendir(DEV_PATH)) != (DIR *) NULL) {
+	while ((entry = readdir(dp)) != (struct dirent *) NULL) {
+		strcpy(namebuf, DEV_PATH);
+		strcat(namebuf, entry->d_name);
+		if (stat(namebuf, &filestat) != 0) continue;
+		if ((filestat.st_mode & S_IFMT) != S_IFBLK) continue;
+		if (filestat.st_rdev != rootstat.st_dev) continue;
+		done(namebuf, 0);
+	}
+  }
+  done(UNKNOWN_DEV, 1);
+  return(0);			/* not reached */
+}
+
+void done(name, status)
+char *name;
+int status;
+{
+  int v;
+
+  write(1, name, strlen(name));
+  if (rflag) {
+	write(1, "\n", 1);
+	exit(status);
+  }
+  write(1, MESSAGE, sizeof MESSAGE - 1);
+  v = fsversion(name, "printroot");	/* determine file system version */
+  if (v == 1)
+	write(1, "1 rw\n", 5);
+  else if (v == 2)
+	write(1, "2 rw\n", 5);
+  else if (v == 3)
+	write(1, "3 rw\n", 5);
+  else
+	write(1, "0 rw\n", 5);
+  exit(status);
+}
Index: /trunk/minix/commands/simple/progressbar.c
===================================================================
--- /trunk/minix/commands/simple/progressbar.c	(revision 9)
+++ /trunk/minix/commands/simple/progressbar.c	(revision 9)
@@ -0,0 +1,79 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <string.h>
+
+_PROTOTYPE(int main, (int argc, char **argv));
+
+void
+prettyprogress(long b, long maxb, time_t starttime)
+{
+  /* print progress indication */
+  time_t spent, now;
+  double bpsec;
+  time(&now);
+  spent = now - starttime;
+  printf("\r");	/* Make sure progress bar starts at beginning of line */
+  if(spent > 0 && (bpsec = (double)b / spent) > 0) {
+  	int len, i;
+  	long secremain, minremain, hremain;
+	  secremain = (maxb - b) / bpsec;
+	  minremain = (secremain / 60) % 60;
+	  hremain = secremain / 3600;
+  	len = printf("Remaining: %ld files. ", maxb-b);
+
+#if 0
+  	len += printf("ETA: %d:%02d:%02d ",
+  		hremain, minremain, secremain % 60);
+#endif
+
+	len += printf(" [");
+
+#define WIDTH 77
+  	len = WIDTH - len;
+  	for(i = 0; i < (b * (len-1) / maxb); i++) 
+  		printf("=");
+ 	printf("|");
+  	for(; i < len-2; i++) 
+  		printf("-");
+  	printf("][K\n");
+  } else printf("\n");
+
+  return;
+}
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+	long i = 0, count = 0;
+	int l;
+	char line[2000];
+	time_t start;
+	if(argc < 2) return 1;
+	count = atol(argv[1]);
+	if(count < 0) return 1;
+	time(&start);
+	printf("\n");
+#define LINES 5
+	for(l = 1; l <= LINES+1; l++) printf("\n");
+	printf("[A");
+	while(fgets(line, sizeof(line), stdin)) {
+		char *nl;
+		i++;
+		for(l = 0; l <= LINES; l++)  printf("[A");
+		if(i <= count) prettyprogress(i, count, start);
+		else printf("\n");
+		printf("[M");
+		for(l = 0; l < LINES; l++)  printf("[B");
+		if((nl = strchr(line, '\n'))) *nl = '\0';
+		line[78] = '\0';
+		printf("\r%s\r", line);
+	}
+
+  	printf("\nDone.[K\n");
+
+	return 0;
+}
Index: /trunk/minix/commands/simple/proto.c
===================================================================
--- /trunk/minix/commands/simple/proto.c	(revision 9)
+++ /trunk/minix/commands/simple/proto.c	(revision 9)
@@ -0,0 +1,688 @@
+/* proto - Generate ANSI C prototypes.	Author:	Eric R. Smith */
+
+/* Program to extract function declarations from C source code
+ * Written by Eric R. Smith and placed in the public domain
+ * Thanks are due to Jwahar R. Bammi for fixing several bugs
+ * And providing the Unix makefiles.
+ */
+#define EXIT_SUCCESS  0
+#define EXIT_FAILURE  1
+
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define ISCSYM(x) ((x) > 0 && (isalnum(x) || (x) == '_' ))
+#define ABORTED ( (Word *) -1 )
+#define MAXPARAM 20		/* max. number of parameters to a function */
+
+typedef struct word {
+  struct word *next;
+  char string[1];
+} Word;
+
+int inquote = 0;		/* in a quote? */
+int newline_seen = 1;		/* are we at the start of a line */
+long linenum = 1L;		/* line number in current file */
+long endline = 0L;		/* the last line before the { of a f'n */
+long symline = 0L;		/* Line that symbol was on, set by getsym() */
+int dostatic = 0;		/* do static functions? */
+int donum = 0;			/* print line numbers? */
+int dohead = 1;			/* do file headers? */
+int docond = 1;			/* conditionalize for non-ANSI compilers? */
+int dodiff = 0;			/* Output a diff file to prototype original */
+int doold = 0;			/* do old style: P() */
+int glastc = ' ';		/* last char. seen by getsym() */
+Word *endlist;			/* Parentheses after the parameters */
+char *progname;			/* name of program (for error messages) */
+
+
+_PROTOTYPE(Word * word_alloc, (char *s));
+_PROTOTYPE(void word_free, (Word * w));
+_PROTOTYPE(int List_len, (Word * w));
+_PROTOTYPE(Word * word_append, (Word * w1, Word * w2));
+_PROTOTYPE(int foundin, (Word * w1, Word * w2));
+_PROTOTYPE(void addword, (Word * w, char *s));
+_PROTOTYPE(void printlist, (Word * p));
+_PROTOTYPE(Word * typelist, (Word * p));
+_PROTOTYPE(void typefixhack, (Word * w));
+_PROTOTYPE(int ngetc, (FILE * f));
+_PROTOTYPE(int fnextch, (FILE * f));
+_PROTOTYPE(int nextch, (FILE * f));
+_PROTOTYPE(int getsym, (char *buf, FILE * f));
+_PROTOTYPE(int skipit, (char *buf, FILE * f));
+_PROTOTYPE(Word * getparamlist, (FILE * f));
+_PROTOTYPE(void emit, (Word * wlist, Word * plist, long startline));
+_PROTOTYPE(void getdecl, (FILE * f));
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void Usage, (void));
+
+/* Routines for manipulating lists of words. */
+
+Word *word_alloc(s)
+char *s;
+{
+  Word *w;
+
+  w = (Word *) malloc(sizeof(Word) + strlen(s) + 1);
+  if (w == NULL) {
+	fprintf(stderr, "%s: out of memory\n", progname);
+	exit(1);
+  }
+  (void) strcpy(w->string, s);
+  w->next = NULL;
+  return w;
+}
+
+void word_free(w)
+Word *w;
+{
+  Word *oldw;
+  while (w) {
+	oldw = w;
+	w = w->next;
+	free((char *) oldw);
+  }
+}
+
+/* Return the length of a list; empty words are not counted */
+int List_len(w)
+Word *w;
+{
+  int count = 0;
+
+  while (w) {
+	if (*w->string) count++;
+	w = w->next;
+  }
+  return count;
+}
+
+/* Append two lists, and return the result */
+Word *word_append(w1, w2)
+Word *w1, *w2;
+{
+  Word *r, *w;
+
+  r = w = word_alloc("");
+
+  while (w1) {
+	w->next = word_alloc(w1->string);
+	w = w->next;
+	w1 = w1->next;
+  }
+  while (w2) {
+	w->next = word_alloc(w2->string);
+	w = w->next;
+	w2 = w2->next;
+  }
+
+  return r;
+}
+
+/* See if the last entry in w2 is in w1 */
+int foundin(w1, w2)
+Word *w1, *w2;
+{
+  while (w2->next) w2 = w2->next;
+
+  while (w1) {
+	if (!strcmp(w1->string, w2->string)) return 1;
+	w1 = w1->next;
+  }
+  return 0;
+}
+
+/* Add the string s to the given list of words */
+void addword(w, s)
+Word *w;
+char *s;
+{
+  while (w->next) w = w->next;
+  w->next = word_alloc(s);
+}
+
+/* Printlist: print out a list */
+void printlist(p)
+Word *p;
+{
+  Word *w;
+  int i = 0;
+
+  for (w = p; w; w = w->next) {
+	printf("%s", w->string);
+	if (ISCSYM(w->string[0]) && i > 0
+			&& w->next && w->next->string[0] != ',') printf(" ");
+	i++;
+  }
+}
+
+/* Given a list representing a type and a variable name, extract just
+ * the base type, e.g. "struct word *x" would yield "struct word".
+ * Similarly, "unsigned char x[]" would yield "unsigned char".
+ */
+Word *typelist(p)
+Word *p;
+{
+  Word *w, *r, *last;
+
+  last = r = w = word_alloc("");
+  while (p && p->next) {
+	if (p->string[0] == '[') {
+		word_free(w);
+		last->next = NULL;
+		break;
+	}
+	if (p->string[0] && !ISCSYM(p->string[0])) break;
+	w->next = word_alloc(p->string);
+	last = w;
+	w = w->next;
+	p = p->next;
+  }
+  return r;
+}
+
+/* Typefixhack: promote formal parameters of type "char", "unsigned char",
+ * "short", or "unsigned short" to "int".
+ */
+void typefixhack(w)
+Word *w;
+{
+  Word *oldw = 0;
+
+  while (w) {
+	if (*w->string) {
+		if ((!strcmp(w->string, "char") ||
+		     !strcmp(w->string, "short"))
+		    && (List_len(w->next) < 2)) {
+			if (oldw && !strcmp(oldw->string, "unsigned")) {
+				oldw->next = w->next;
+				free((char *) w);
+				w = oldw;
+			}
+			(void) strcpy(w->string, "int");
+		}
+	}
+	w = w->next;
+  }
+}
+
+/* Read a character: if it's a newline, increment the line count */
+int ngetc(f)
+FILE *f;
+{
+  int c;
+
+  c = getc(f);
+  if (c == '\n') linenum++;
+
+  return c;
+}
+
+/* Read the next character from the file. If the character is '\' then
+ * read and skip the next character. Any comment sequence is converted
+ * to a blank.
+ */
+int fnextch(f)
+FILE *f;
+{
+  int c, lastc, incomment;
+
+  c = ngetc(f);
+  while (c == '\\') {
+	c = ngetc(f);		/* skip a character */
+	c = ngetc(f);
+  }
+  if (c == '/' && !inquote) {
+	c = ngetc(f);
+	if (c == '*') {
+		incomment = 1;
+		c = ' ';
+		while (incomment) {
+			lastc = c;
+			c = ngetc(f);
+			if (lastc == '*' && c == '/')
+				incomment = 0;
+			else if (c < 0)
+				return c;
+		}
+		return fnextch(f);
+	} else {
+		if (c == '\n') linenum--;
+		(void) ungetc(c, f);
+		return '/';
+	}
+  }
+  return c;
+}
+
+
+/* Get the next "interesting" character. Comments are skipped, and strings
+ * are converted to "0". Also, if a line starts with "#" it is skipped.
+ */
+int nextch(f)
+FILE *f;
+{
+  int c;
+
+  c = fnextch(f);
+  if (newline_seen && c == '#') {
+	do {
+		c = fnextch(f);
+	} while (c >= 0 && c != '\n');
+	if (c < 0) return c;
+  }
+  newline_seen = (c == '\n');
+
+  if (c == '\'' || c == '\"') {
+	inquote = c;
+	while ((c = fnextch(f)) >= 0) {
+		if (c == inquote) {
+			inquote = 0;
+			return '0';
+		}
+	}
+  }
+  return c;
+}
+
+/* Get the next symbol from the file, skipping blanks.
+ * Return 0 if OK, -1 for EOF.
+ * Also collapses everything between { and }
+ */
+int getsym(buf, f)
+char *buf;
+FILE *f;
+{
+  register int c;
+  int inbrack = 0;
+
+  c = glastc;
+  while ((c > 0) && isspace(c)) c = nextch(f);
+  if (c < 0) return -1;
+  if (c == '{') {
+	inbrack = 1;
+	endline = linenum;
+	while (inbrack) {
+		c = nextch(f);
+		if (c < 0) {
+			glastc = c;
+			return c;
+		}
+		if (c == '{')
+			inbrack++;
+		else if (c == '}')
+			inbrack--;
+	}
+	(void) strcpy(buf, "{}");
+	glastc = nextch(f);
+	return 0;
+  }
+  if (!ISCSYM(c)) {
+	*buf++ = c;
+	glastc = nextch(f);
+	if (c == '(' && glastc == '*') {	/* Look for a 'f'n pointer */
+		*buf++ = glastc;
+		glastc = nextch(f);
+	}
+	*buf = 0;
+	return 0;
+  }
+  symline = linenum;
+  while (ISCSYM(c)) {
+	*buf++ = c;
+	c = nextch(f);
+  }
+  *buf = 0;
+  glastc = c;
+  return 0;
+}
+
+
+/* Skipit: skip until a ";" or the end of a function declaration is seen */
+int skipit(buf, f)
+char *buf;
+FILE *f;
+{
+  int i;
+
+  do {
+	i = getsym(buf, f);
+	if (i < 0) return i;
+  } while (*buf != ';' && *buf != '{');
+
+  return 0;
+}
+
+/* Get a parameter list; when this is called the next symbol in line
+ * should be the first thing in the list.
+ */
+Word *getparamlist(f)
+FILE *f;
+{
+  static Word *pname[MAXPARAM];	/* parameter names */
+  Word *tlist,			/* type name */
+  *plist;			/* temporary */
+  int np = 0;			/* number of parameters */
+  int typed[MAXPARAM];		/* parameter has been given a type */
+  int tlistdone;		/* finished finding the type name */
+  int sawsomething;
+  int i;
+  int inparen = 0;
+  char buf[80];
+
+  for (i = 0; i < MAXPARAM; i++) typed[i] = 0;
+
+  plist = word_alloc("");
+  endlist = word_alloc("");
+
+  /* First, get the stuff inside brackets (if anything) */
+
+  sawsomething = 0;		/* gets set nonzero when we see an arg */
+  for (;;) {
+	if (getsym(buf, f) < 0) return(NULL);
+	if (*buf == ')' && (--inparen < 0)) {
+		if (sawsomething) {	/* if we've seen an arg */
+			pname[np] = plist;
+			plist = word_alloc("");
+			np++;
+		}
+		break;
+	}
+	if (*buf == ';') {	/* something weird */
+		return ABORTED;
+	}
+	sawsomething = 1;	/* there's something in the arg. list */
+	if (*buf == ',' && inparen == 0) {
+		pname[np] = plist;
+		plist = word_alloc("");
+		np++;
+	} else {
+		addword(plist, buf);
+		if (*buf == '(') inparen++;
+	}
+  }
+
+  /* Next, get the declarations after the function header */
+  inparen = 0;
+  tlist = word_alloc("");
+  plist = word_alloc("");
+  tlistdone = 0;
+  sawsomething = 0;
+  for (;;) {
+	if (getsym(buf, f) < 0) return(NULL);
+
+	/* Handle parentheses, which should indicate func pointer rtn values */
+	if (*buf == '(') {
+		addword(endlist, buf);
+		addword(endlist, " void ");
+		inparen++;
+	} else if (*buf == ')') {
+		if (symline == linenum) {
+			addword(endlist, buf);
+			addword(endlist, buf);
+		}
+		inparen--;
+	} else if (*buf == ',' && !inparen) {
+		/* Handle a list like "int x,y,z" */
+		if (!sawsomething) return(NULL);
+		for (i = 0; i < np; i++) {
+			if (!typed[i] && foundin(plist, pname[i])) {
+				typed[i] = 1;
+				word_free(pname[i]);
+				pname[i] = word_append(tlist, plist);
+				/* Promote types */
+				typefixhack(pname[i]);
+				break;
+			}
+		}
+		if (!tlistdone) {
+			tlist = typelist(plist);
+			tlistdone = 1;
+		}
+		word_free(plist);
+		plist = word_alloc("");
+	} else if (*buf == ';') {
+		/* Handle the end of a list */
+		if (!sawsomething) return ABORTED;
+		for (i = 0; i < np; i++) {
+			if (!typed[i] && foundin(plist, pname[i])) {
+				typed[i] = 1;
+				word_free(pname[i]);
+				pname[i] = word_append(tlist, plist);
+				typefixhack(pname[i]);
+				break;
+			}
+		}
+		tlistdone = 0;
+		word_free(tlist);
+		word_free(plist);
+		tlist = word_alloc("");
+		plist = word_alloc("");
+	} else if (!strcmp(buf, "{}"))
+		break;	/* Handle the  beginning of the function */
+		/* Otherwise, throw word into list (except for "register") */
+	else if (strcmp(buf, "register")) {
+		sawsomething = 1;
+		addword(plist, buf);
+		if (*buf == '(') inparen++;
+		if (*buf == ')') inparen--;
+	}
+  }
+
+  /* Now take the info we have and build a prototype list */
+
+  /* Empty parameter list means "void" */
+  if (np == 0) return word_alloc("void");
+
+  plist = tlist = word_alloc("");
+  for (i = 0; i < np; i++) {
+
+  /* If no type provided, make it an "int" */
+	if (!(pname[i]->next) ||
+	    (!(pname[i]->next->next)&&strcmp(pname[i]->next->string,"void"))) {
+		addword(tlist, "int");
+	}
+	while (tlist->next) tlist = tlist->next;
+	tlist->next = pname[i];
+	if (i < np - 1) addword(tlist, ", ");
+  }
+  return plist;
+}
+
+/* Emit a function declaration. The attributes and name of the function
+ * are in wlist; the parameters are in plist.
+ */
+void emit(wlist, plist, startline)
+Word *wlist, *plist;
+long startline;
+{
+  Word *w;
+  int count = 0;
+
+  if (doold == 0) printf("_PROTOTYPE( ");
+  if (dodiff) {
+	printf("%lda%ld,%ld\n", startline - 1, startline, startline +2);
+	printf("> #ifdef __STDC__\n> ");
+  }
+  if (donum) printf("/*%8ld */ ", startline);
+  for (w = wlist; w; w = w->next) {
+	if (w->string[0]) count++;
+  }
+  if (count < 2) printf("int ");
+  printlist(wlist);
+  if (docond) {
+	if (doold)
+		printf(" P((");
+	else
+		printf(", (");
+  } else {
+	printf("(");
+  }
+
+  printlist(plist);
+  printlist(endlist);
+
+  if (docond) {
+	if (doold)
+		printf("))");
+	else
+		printf(") )");
+  } else {
+	printf(")");
+  }
+
+  if (!dodiff)
+	printf(";\n");
+  else
+	printf("\n");
+
+  if (dodiff) {
+	printf("> #else\n");
+	printf("%lda%ld\n", endline - 1, endline);
+	printf("> #endif\n");
+  }
+}
+
+/* Get all the function declarations */
+void getdecl(f)
+FILE *f;
+{
+  Word *plist, *wlist = NULL;
+  char buf[80];
+  int sawsomething;
+  long startline = 0L;		/* line where declaration started */
+  int oktoprint;
+
+again:				/* SHAME SHAME */
+  word_free(wlist);
+  wlist = word_alloc("");
+  sawsomething = 0;
+  oktoprint = 1;
+
+  for (;;) {
+	if (getsym(buf, f) < 0) return;
+
+	/* Guess when a declaration is not an external function definition */
+	if (!strcmp(buf, ",") || !strcmp(buf, "{}") ||
+	    !strcmp(buf, "=") || !strcmp(buf, "typedef") ||
+	    !strcmp(buf, "extern")) {
+		(void) skipit(buf, f);
+		goto again;
+	}
+	if (!dostatic && !strcmp(buf, "static")) oktoprint = 0;
+
+	/* For the benefit of compilers that allow "inline" declarations */
+	if (!strcmp(buf, "inline") && !sawsomething) continue;
+	if (!strcmp(buf, ";")) goto again;
+
+	/* A left parenthesis *might* indicate a function definition */
+	if (!strcmp(buf, "(")) {
+		if (!sawsomething || !(plist = getparamlist(f))) {
+			(void) skipit(buf, f);
+			goto again;
+		}
+		if (plist == ABORTED) goto again;
+
+		/* It seems to have been what we wanted */
+		if (oktoprint) emit(wlist, plist, startline);
+		word_free(plist);
+		goto again;
+	}
+	addword(wlist, buf);
+	if (!sawsomething) startline = symline;
+	sawsomething = 1;
+  }
+}
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  FILE *f, *g;
+  char *t;
+  char newname[40];
+
+  progname = argv[0];
+  argv++;
+  argc--;
+  g = stdout;
+
+  while (*argv && **argv == '-') {
+	t = *argv++;
+	--argc;
+	t++;
+	while (*t) {
+		if (*t == 's')
+			dostatic = 1;
+		else if (*t == 'n')
+			donum = 1;
+		else if (*t == 'p')
+			docond = 0;
+		else if (*t == 'P')
+			doold =1;
+		else if (*t == 'd') {
+			dodiff = 1;
+			doold = 1;
+			docond = 0;
+			donum = 0;
+			dostatic = 1;
+		} else
+			Usage();
+		t++;
+	}
+  }
+
+  if (docond && doold) {
+	printf("#ifdef __STDC__\n");
+	printf("# define P(args)\targs\n");
+	printf("#else\n");
+	printf("# define P(args)\t()\n");
+	printf("#endif\n\n");
+  }
+  if (argc == 0)
+	getdecl(stdin);
+  else
+	while (argc > 0 && *argv) {
+		if (!(f = fopen(*argv, "r"))) {
+			perror(*argv);
+			exit(EXIT_FAILURE);
+		}
+#if 0
+		if (dodiff) {
+			(void) sprintf(newname, "%sdif", *argv);
+			(void) fclose(g);
+			if (!(g = fopen(newname, "w"))) {
+				perror(newname);
+				exit(EXIT_FAILURE);
+			}
+		}
+#endif
+		if (doold && dohead && !dodiff) printf("\n/* %s */\n", *argv);
+		linenum = 1;
+		newline_seen = 1;
+		glastc = ' ';
+		getdecl(f);
+		argc--;
+		argv++;
+		(void) fclose(f);
+	}
+  if (docond && doold) printf("\n#undef P\n");	/* clean up namespace */
+  (void) fclose(g);
+  return(EXIT_SUCCESS);
+}
+
+
+void Usage()
+{
+  fputs("Usage: ", stderr);
+  fputs(progname, stderr);
+  fputs(" [-d][-n][-p][-s] [files ...]\n", stderr);
+  fputs("   -P: use P() style instead of _PROTOTYPE\n", stderr);
+  fputs("   -d: produce a diff file to prototype original source\n", stderr);
+  fputs("   -n: put line numbers of declarations as comments\n", stderr);
+  fputs("   -p: don't make header files readable by K&R compilers\n", stderr);
+  fputs("   -s: include declarations for static functions\n", stderr);
+  exit(EXIT_FAILURE);
+}
Index: /trunk/minix/commands/simple/pwd.c
===================================================================
--- /trunk/minix/commands/simple/pwd.c	(revision 9)
+++ /trunk/minix/commands/simple/pwd.c	(revision 9)
@@ -0,0 +1,49 @@
+/* pwd - print working directory	Author: Norbert Schlenker */
+
+/*
+ * pwd - print working directory
+ *   Syntax:	pwd
+ *   Flags:	None.
+ *   Author:	Norbert Schlenker
+ *   Copyright:	None.  Released to the public domain.
+ *   Reference:	IEEE P1003.2 Section 4.50 (draft 10)
+ *   Bugs:	No internationalization support; all messages are in English.
+ */
+
+/* Force visible Posix names */
+#ifndef _POSIX_SOURCE
+#define _POSIX_SOURCE 1
+#endif
+
+/* External interfaces */
+#include <sys/types.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+/* Magic numbers suggested or required by Posix specification */
+#define SUCCESS	0		/* exit code in case of success */
+#define FAILURE 1		/*                   or failure */
+
+_PROTOTYPE(int main, (void));
+
+static char dir[PATH_MAX + 1];
+static char *errmsg = "pwd: cannot search some directory on the path\n";
+
+int main()
+{
+  char *p;
+  size_t n;
+
+  p = getcwd(dir, PATH_MAX);
+  if (p == NULL) {
+	write(STDERR_FILENO, errmsg, strlen(errmsg));
+	exit(FAILURE);
+  }
+  n = strlen(p);
+  p[n] = '\n';
+  if (write(STDOUT_FILENO, p, n + 1) != n + 1) 	exit(FAILURE);
+  return(SUCCESS);
+}
Index: /trunk/minix/commands/simple/pwdauth.c
===================================================================
--- /trunk/minix/commands/simple/pwdauth.c	(revision 9)
+++ /trunk/minix/commands/simple/pwdauth.c	(revision 9)
@@ -0,0 +1,357 @@
+/*	pwdauth 2.0 - check a shadow password		Author: Kees J. Bot
+ *								7 Feb 1994
+ *
+ * This program gets as input the key and salt arguments of the crypt(3)
+ * function as two null terminated strings.  The crypt result is output as
+ * one null terminated string.  Input and output must be <= 1024 characters.
+ * The exit code will be 1 on any error.
+ *
+ * If the key has the form '##name' then the key will be encrypted and the
+ * result checked to be equal to the encrypted password in the shadow password
+ * file.  If equal than '##name' will be returned, otherwise exit code 2.
+ *
+ * Otherwise the key will be encrypted normally and the result returned.
+ *
+ * As a special case, anything matches a null encrypted password to allow
+ * a no-password login.
+ */
+#define nil 0
+#define crypt	CRYPT	/* The true crypt is included here. */
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define LEN	1024
+char SHADOW[] = "/etc/shadow";
+
+int main(int argc, char **argv)
+{
+	char key[LEN];
+	char *salt;
+	struct passwd *pw;
+	int n;
+
+	/* Read input data.  Check if there are exactly two null terminated
+	 * strings.
+	 */
+	n= read(0, key, LEN);
+	if (n < 0) return 1;
+	salt = key + n;
+	n = 0;
+	while (salt > key) if (*--salt == 0) n++;
+	if (n != 2) return 1;
+	salt = key + strlen(key) + 1;
+
+	if (salt[0] == '#' && salt[1] == '#') {
+		/* Get the encrypted password from the shadow password file,
+		 * encrypt key and compare.
+		 */
+		setpwfile(SHADOW);
+
+		if ((pw= getpwnam(salt + 2)) == nil) return 2;
+
+		/* A null encrypted password matches a null key, otherwise
+		 * do the normal crypt(3) authentication check.
+		 */
+		if (*pw->pw_passwd == 0 && *key == 0) {
+			/* fine */
+		} else
+		if (strcmp(crypt(key, pw->pw_passwd), pw->pw_passwd) != 0) {
+			return 2;
+		}
+	} else {
+		/* Normal encryption. */
+		if (*salt == 0 && *key == 0) {
+			/* fine */
+		} else {
+			salt= crypt(key, salt);
+		}
+	}
+
+	/* Return the (possibly new) salt to the caller. */
+	if (write(1, salt, strlen(salt) + 1) < 0) return 1;
+	return 0;
+}
+
+/* The one and only crypt(3) function. */
+
+/*	From Andy Tanenbaum's book "Computer Networks",
+	rewritten in C
+*/
+
+struct block {
+	unsigned char b_data[64];
+};
+
+struct ordering {
+	unsigned char o_data[64];
+};
+
+static struct block key;
+
+static struct ordering InitialTr = {
+	58,50,42,34,26,18,10, 2,60,52,44,36,28,20,12, 4,
+	62,54,46,38,30,22,14, 6,64,56,48,40,32,24,16, 8,
+	57,49,41,33,25,17, 9, 1,59,51,43,35,27,19,11, 3,
+	61,53,45,37,29,21,13, 5,63,55,47,39,31,23,15, 7,
+};
+
+static struct ordering FinalTr = {
+	40, 8,48,16,56,24,64,32,39, 7,47,15,55,23,63,31,
+	38, 6,46,14,54,22,62,30,37, 5,45,13,53,21,61,29,
+	36, 4,44,12,52,20,60,28,35, 3,43,11,51,19,59,27,
+	34, 2,42,10,50,18,58,26,33, 1,41, 9,49,17,57,25,
+};
+
+static struct ordering swap = {
+	33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
+	49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,
+	 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,
+	17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,
+};
+
+static struct ordering KeyTr1 = {
+	57,49,41,33,25,17, 9, 1,58,50,42,34,26,18,
+	10, 2,59,51,43,35,27,19,11, 3,60,52,44,36,
+	63,55,47,39,31,23,15, 7,62,54,46,38,30,22,
+	14, 6,61,53,45,37,29,21,13, 5,28,20,12, 4,
+};
+
+static struct ordering KeyTr2 = {
+	14,17,11,24, 1, 5, 3,28,15, 6,21,10,
+	23,19,12, 4,26, 8,16, 7,27,20,13, 2,
+	41,52,31,37,47,55,30,40,51,45,33,48,
+	44,49,39,56,34,53,46,42,50,36,29,32,
+};
+
+static struct ordering etr = {
+	32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,
+	 8, 9,10,11,12,13,12,13,14,15,16,17,
+	16,17,18,19,20,21,20,21,22,23,24,25,
+	24,25,26,27,28,29,28,29,30,31,32, 1,
+};
+
+static struct ordering ptr = {
+	16, 7,20,21,29,12,28,17, 1,15,23,26, 5,18,31,10,
+	 2, 8,24,14,32,27, 3, 9,19,13,30, 6,22,11, 4,25,
+};
+
+static unsigned char s_boxes[8][64] = {
+{	14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
+	 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
+	 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
+	15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,
+},
+
+{	15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
+	 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
+	 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
+	13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,
+},
+
+{	10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
+	13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
+	13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
+	 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,
+},
+
+{	 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
+	13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
+	10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
+	 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,
+},
+
+{	 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
+	14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
+	 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
+	11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,
+},
+
+{	12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
+	10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
+	 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
+	 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,
+},
+
+{	 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
+	13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
+	 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
+	 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,
+},
+
+{	13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
+	 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
+	 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
+	 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
+},
+};
+
+static int rots[] = {
+	1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
+};
+
+static void transpose(struct block *data, struct ordering *t, int n)
+{
+	struct block x;
+
+	x = *data;
+
+	while (n-- > 0) {
+		data->b_data[n] = x.b_data[t->o_data[n] - 1];
+	}
+}
+
+static void rotate(struct block *key)
+{
+	unsigned char *p = key->b_data;
+	unsigned char *ep = &(key->b_data[55]);
+	int data0 = key->b_data[0], data28 = key->b_data[28];
+
+	while (p++ < ep) *(p-1) = *p;
+	key->b_data[27] = data0;
+	key->b_data[55] = data28;
+}
+
+static struct ordering *EP = &etr;
+
+static void f(int i, struct block *key, struct block *a, struct block *x)
+{
+	struct block e, ikey, y;
+	int k;
+	unsigned char *p, *q, *r;
+
+	e = *a;
+	transpose(&e, EP, 48);
+	for (k = rots[i]; k; k--) rotate(key);
+	ikey = *key;
+	transpose(&ikey, &KeyTr2, 48);
+	p = &(y.b_data[48]);
+	q = &(e.b_data[48]);
+	r = &(ikey.b_data[48]);
+	while (p > y.b_data) {
+		*--p = *--q ^ *--r;
+	}
+	q = x->b_data;
+	for (k = 0; k < 8; k++) {
+		int xb, r;
+
+		r = *p++ << 5;
+		r += *p++ << 3;
+		r += *p++ << 2;
+		r += *p++ << 1;
+		r += *p++;
+		r += *p++ << 4;
+
+		xb = s_boxes[k][r];
+
+		*q++ = (xb >> 3) & 1;
+		*q++ = (xb>>2) & 1;
+		*q++ = (xb>>1) & 1;
+		*q++ = (xb & 1);
+	}
+	transpose(x, &ptr, 32);
+}
+
+static void setkey(char *k)
+{
+
+	key = *((struct block *) k);
+	transpose(&key, &KeyTr1, 56);
+}
+
+static void encrypt(char *blck, int edflag)
+{
+	struct block *p = (struct block *) blck;
+	int i;
+
+	transpose(p, &InitialTr, 64);
+	for (i = 15; i>= 0; i--) {
+		int j = edflag ? i : 15 - i;
+		int k;
+		struct block b, x;
+
+		b = *p;
+		for (k = 31; k >= 0; k--) {
+			p->b_data[k] = b.b_data[k + 32];
+		}
+		f(j, &key, p, &x);
+		for (k = 31; k >= 0; k--) {
+			p->b_data[k+32] = b.b_data[k] ^ x.b_data[k];
+		}
+	}
+	transpose(p, &swap, 64);
+	transpose(p, &FinalTr, 64);
+}
+
+char *crypt(const char *pw, const char *salt)
+{
+	char pwb[66];
+	char *cp;
+	static char result[16];
+	char *p = pwb;
+	struct ordering new_etr;
+	int i;
+
+	while (*pw && p < &pwb[64]) {
+		int j = 7;
+
+		while (j--) {
+			*p++ = (*pw >> j) & 01;
+		}
+		pw++;
+		*p++ = 0;
+	}
+	while (p < &pwb[64]) *p++ = 0;
+
+	setkey(p = pwb);
+
+	while (p < &pwb[66]) *p++ = 0;
+
+	new_etr = etr;
+	EP = &new_etr;
+	if (salt[0] == 0 || salt[1] == 0) salt = "**";
+	for (i = 0; i < 2; i++) {
+		char c = *salt++;
+		int j;
+
+		result[i] = c;
+		if ( c > 'Z') c -= 6 + 7 + '.';	/* c was a lower case letter */
+		else if ( c > '9') c -= 7 + '.';/* c was upper case letter */
+		else c -= '.';			/* c was digit, '.' or '/'. */
+						/* now, 0 <= c <= 63 */
+		for (j = 0; j < 6; j++) {
+			if ((c >> j) & 01) {
+				int t = 6*i + j;
+				int temp = new_etr.o_data[t];
+				new_etr.o_data[t] = new_etr.o_data[t+24];
+				new_etr.o_data[t+24] = temp;
+			}
+		}
+	}
+
+	if (result[1] == 0) result[1] = result[0];
+
+	for (i = 0; i < 25; i++) encrypt(pwb,0);
+	EP = &etr;
+
+	p = pwb;
+	cp = result+2;
+	while (p < &pwb[66]) {
+		int c = 0;
+		int j = 6;
+
+		while (j--) {
+			c <<= 1;
+			c |= *p++;
+		}
+		c += '.';		/* becomes >= '.' */
+		if (c > '9') c += 7;	/* not in [./0-9], becomes upper */
+		if (c > 'Z') c += 6;	/* not in [A-Z], becomes lower */
+		*cp++ = c;
+	}
+	*cp = 0;
+	return result;
+}
Index: /trunk/minix/commands/simple/ramdisk.c
===================================================================
--- /trunk/minix/commands/simple/ramdisk.c	(revision 9)
+++ /trunk/minix/commands/simple/ramdisk.c	(revision 9)
@@ -0,0 +1,38 @@
+
+#include <minix/paths.h>
+
+#include <sys/ioc_memory.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+int
+main(int argc, char *argv[])
+{
+	int fd;
+	signed long size;
+	if((fd=open(_PATH_RAMDISK, O_RDONLY)) < 0) {
+		perror(_PATH_RAMDISK);
+		return 1;
+	}
+
+	if(argc != 2) {
+		fprintf(stderr, "usage: %s <size in bytes>\n", argv[0]);
+		return 1;
+	}
+
+	size = atol(argv[1]);
+
+	if(size <= 0) {
+		fprintf(stderr, "size should be positive.\n");
+		return 1;
+	}
+
+	if(ioctl(fd, MIOCRAMSIZE, &size) < 0) {
+		perror("MIOCRAMSIZE");
+		return 1;
+	}
+
+	return 0;
+}
+
Index: /trunk/minix/commands/simple/rarpd.c
===================================================================
--- /trunk/minix/commands/simple/rarpd.c	(revision 9)
+++ /trunk/minix/commands/simple/rarpd.c	(revision 9)
@@ -0,0 +1,365 @@
+/*
+rarpd.c
+
+Created:	Nov 12, 1992 by Philip Homburg
+
+Changed:	May 13, 1995 by Kees J. Bot
+		Rewrite to handle multiple ethernets.
+
+Changed:	Jul 18, 1995 by Kees J. Bot
+		Do RARP requests (formerly inet's job)
+
+Changed:	Dec 14, 1996 by Kees J. Bot
+		Query the netmask
+
+Changed:	Dec 11, 2000 by Kees J. Bot
+		Dressed down to be only a RARP server, giving the floor to DHCP
+*/
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/asynchio.h>
+#include <net/hton.h>
+#include <net/gen/socket.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include <net/gen/if_ether.h>
+#include <net/gen/ip_io.h>
+#include <net/gen/nameser.h>
+
+#define MAX_RARP_RETRIES	5
+#define RARP_TIMEOUT		5
+
+typedef struct rarp46
+{
+	ether_addr_t a46_dstaddr;
+	ether_addr_t a46_srcaddr;
+	ether_type_t a46_ethtype;
+	u16_t a46_hdr, a46_pro;
+	u8_t a46_hln, a46_pln;
+	u16_t a46_op;
+	ether_addr_t a46_sha;
+	u8_t a46_spa[4];
+	ether_addr_t a46_tha;
+	u8_t a46_tpa[4];
+	char a46_padding[ETH_MIN_PACK_SIZE - (4*6 + 2*4 + 4*2 + 2*1)];
+} rarp46_t;
+
+#define ETH_RARP_PROTO	0x8035
+
+#define RARP_ETHERNET	1
+
+#define RARP_REQUEST	3
+#define RARP_REPLY	4
+
+static char *program;
+static unsigned debug;
+
+#define between(a, c, z)	((unsigned) (c) - (a) <= (unsigned) (z) - (a))
+
+static void report(const char *label)
+{
+    fprintf(stderr, "%s: %s: %s\n", program, label, strerror(errno));
+}
+
+static void fatal(const char *label)
+{
+    report(label);
+    exit(1);
+}
+
+static void *allocate(size_t size)
+{
+    void *mem;
+
+    if ((mem= malloc(size)) == NULL) fatal("Can't allocate memory");
+    return mem;
+}
+
+static char *ethdev(int n)
+{
+    static char an_ethdev[]= "/dev/ethNNN";
+
+    sprintf(an_ethdev + sizeof(an_ethdev)-4, "%d", n);
+    return an_ethdev;
+}
+
+static char *ipdev(int n)
+{
+    static char an_ipdev[]= "/dev/ipNNN";
+
+    sprintf(an_ipdev + sizeof(an_ipdev)-4, "%d", n);
+    return an_ipdev;
+}
+
+typedef struct ethernet {
+	int		n;		/* Network number. */
+	int		eth_fd;		/* Open low level ethernet device. */
+	ether_addr_t	eth_addr;	/* Ethernet address of this net. */
+	char		packet[ETH_MAX_PACK_SIZE];	/* Incoming packet. */
+	ipaddr_t	ip_addr;	/* IP address of this net. */
+	ipaddr_t	ip_mask;	/* Associated netmask. */
+} ethernet_t;
+
+static ethernet_t *ethernets;
+
+static void onsig(int sig)
+{
+    switch (sig) {
+    case SIGUSR1:	debug++;	break;
+    case SIGUSR2:	debug= 0;	break;
+    }
+}
+
+static void rarp_reply(ethernet_t *ep, char *hostname, ipaddr_t ip_addr,
+						ether_addr_t eth_addr)
+{
+    rarp46_t rarp46;
+
+    /* Construct a RARP reply packet and send it. */
+    rarp46.a46_dstaddr= eth_addr;
+    rarp46.a46_hdr= HTONS(RARP_ETHERNET);
+    rarp46.a46_pro= HTONS(ETH_IP_PROTO);
+    rarp46.a46_hln= 6;
+    rarp46.a46_pln= 4;
+    rarp46.a46_op= HTONS(RARP_REPLY);
+    rarp46.a46_sha= ep->eth_addr;
+    memcpy(rarp46.a46_spa, &ep->ip_addr, sizeof(ipaddr_t));
+    rarp46.a46_tha= eth_addr;
+    memcpy(rarp46.a46_tpa, &ip_addr, sizeof(ipaddr_t));
+
+    if (debug >= 1) {
+	printf("%s: Replying %s (%s) to %s\n",
+	    ethdev(ep->n), inet_ntoa(ip_addr), hostname, ether_ntoa(&eth_addr));
+    }
+    (void) write(ep->eth_fd, &rarp46, sizeof(rarp46));
+}
+
+static int addhostname(char *addname, char *hostname, int n)
+{
+    /* Create an additional hostname for a given hostname by adding "-n" to
+     * the first part.  E.g. given "wombat.cs.vu.nl" and n=2 return
+     * "wombat-2.cs.vu.nl".  This is useful for VU practical work where
+     * people get a few extra ethernet addresses on a machine and are asked
+     * to build a TCP/IP stack on it.
+     */
+    char *dot;
+
+    if (strlen(hostname) + 4 >= 1024) return 0;
+    if ((dot= strchr(hostname, '.')) == NULL) dot= strchr(hostname, 0);
+    sprintf(addname, "%.*s-%d%s", (dot - hostname), hostname, n, dot);
+    return 1;
+}
+
+static void usage(void)
+{
+    fprintf(stderr, "Usage: %s [-d[level]] network-name ...\n", program);
+    exit(1);
+}
+
+static int ifname2n(const char *name)
+{
+    /* Translate an interface name, ip0, ip1, etc, to a number. */
+    const char *np;
+    char *end;
+    unsigned long n;
+
+    np= name;
+    if (*np++ != 'i' || *np++ != 'p') usage();
+    n= strtoul(np, &end, 10);
+    if (end == np || *end != 0) usage();
+    if (n >= 1000) {
+	fprintf(stderr, "%s: Network number of \"%s\" is a bit large\n",
+	    program, name);
+	exit(1);
+    }
+    return n;
+}
+
+int main(int argc, char **argv)
+{
+    int i;
+    ethernet_t *ep;
+    nwio_ethopt_t ethopt;
+    nwio_ethstat_t ethstat;
+    char hostname[1024];
+    struct hostent *hostent;
+    struct sigaction sa;
+    nwio_ipconf_t ipconf;
+    asynchio_t asyn;
+    ssize_t n;
+    ipaddr_t ip_addr;
+    rarp46_t rarp46;
+    int fd;
+    int n_eths;
+
+    program= argv[0];
+    asyn_init(&asyn);
+
+    debug= 0;
+    i= 1;
+    while (i < argc && argv[i][0] == '-') {
+	char *opt= argv[i++]+1;
+
+	if (opt[0] == '-' && opt[1] == 0) break;	/* -- */
+
+	while (*opt != 0) switch (*opt++) {
+	case 'd':
+	    debug= 1;
+	    if (between('0', *opt, '9')) debug= strtoul(opt, &opt, 10);
+	    break;
+	default:
+	    usage();
+	}
+    }
+
+    if ((n_eths= (argc - i)) == 0) usage();
+
+#if __minix_vmd
+    /* Minix-vmd can handle all nets at once using async I/O. */
+    ethernets= allocate(n_eths * sizeof(ethernets[0]));
+    for (i= 0; i < n_eths; i++) {
+	ethernets[i].n= ifname2n(argv[argc - n_eths + i]);
+    }
+#else
+    /* Minix forks n-1 times to handle each net in a process each. */
+    for (i= 0; i < n_eths; i++) {
+	if (i+1 < n_eths) {
+	    switch (fork()) {
+	    case -1:	fatal("fork()");
+	    case 0:		break;
+	    default:	continue;
+	    }
+	}
+	ethernets= allocate(1 * sizeof(ethernets[0]));
+	ethernets[0].n= ifname2n(argv[argc - n_eths + i]);
+    }
+    n_eths= 1;
+#endif
+
+    sa.sa_handler= onsig;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags= 0;
+    sigaction(SIGUSR1, &sa, NULL);
+    sigaction(SIGUSR2, &sa, NULL);
+
+    for (i= 0; i < n_eths; i++) {
+	ep= &ethernets[i];
+	if ((ep->eth_fd= open(ethdev(ep->n), O_RDWR)) < 0) fatal(ethdev(ep->n));
+
+	if (ioctl(ep->eth_fd, NWIOGETHSTAT, &ethstat) < 0) {
+	    fprintf(stderr, "%s: %s: Unable to get eth statistics: %s\n",
+		program, ethdev(ep->n), strerror(errno));
+	    exit(1);
+	}
+	ep->eth_addr= ethstat.nwes_addr;
+	if (debug >= 1) {
+	    printf("%s: Ethernet address is %s\n",
+		ethdev(ep->n), ether_ntoa(&ep->eth_addr));
+	}
+
+	ethopt.nweo_flags= NWEO_COPY | NWEO_EN_LOC | NWEO_EN_BROAD |
+		NWEO_TYPESPEC;
+	ethopt.nweo_type= HTONS(ETH_RARP_PROTO);
+
+	if (ioctl(ep->eth_fd, NWIOSETHOPT, &ethopt) < 0) {
+	    fprintf(stderr, "%s: %s: Unable to set eth options: %s\n",
+		program, ethdev(ep->n), strerror(errno));
+	    exit(1);
+	}
+
+	/* What are my address and netmask? */
+	if ((fd= open(ipdev(ep->n), O_RDWR)) < 0) fatal(ipdev(ep->n));
+	if (ioctl(fd, NWIOGIPCONF, &ipconf) < 0) fatal(ipdev(ep->n));
+
+	ep->ip_addr= ipconf.nwic_ipaddr;
+	ep->ip_mask= ipconf.nwic_netmask;
+	close(fd);
+	if (debug >= 1) {
+	    printf("%s: IP address is %s / ",
+		ipdev(ep->n), inet_ntoa(ep->ip_addr));
+	    printf("%s\n", inet_ntoa(ep->ip_mask));
+	}
+    }
+
+    /* Wait for RARP requests, reply, repeat. */
+    for(;;) {
+	fflush(NULL);
+
+	/* Wait for a RARP request. */
+	for (i= 0; i < n_eths; i++) {
+	    ep= &ethernets[i];
+
+	    n= asyn_read(&asyn, ep->eth_fd, ep->packet, sizeof(ep->packet));
+	    if (n != -1) break;
+	    if (errno != EINPROGRESS) {
+		report(ethdev(ep->n));
+		sleep(10);
+	    }
+	}
+
+	/* RARP request? */
+	if (i < n_eths
+	    && n >= sizeof(rarp46)
+	    && (memcpy(&rarp46, ep->packet, sizeof(rarp46)), 1)
+	    && rarp46.a46_hdr == HTONS(RARP_ETHERNET)
+	    && rarp46.a46_pro == HTONS(ETH_IP_PROTO)
+	    && rarp46.a46_hln == 6
+	    && rarp46.a46_pln == 4
+	    && rarp46.a46_op == HTONS(RARP_REQUEST)
+	) {
+	    if ((ether_ntohost(hostname, &rarp46.a46_tha) == 0
+		  || (rarp46.a46_tha.ea_addr[0] == 'v'
+		    && (memcpy(&ip_addr, rarp46.a46_tha.ea_addr+2, 4), 1)
+		    && (hostent= gethostbyaddr((char*) &ip_addr,
+						4, AF_INET)) != NULL
+		    && addhostname(hostname, hostent->h_name,
+						rarp46.a46_tha.ea_addr[1])))
+		&& (hostent= gethostbyname(hostname)) != NULL
+		&& hostent->h_addrtype == AF_INET
+	    ) {
+		/* Host is found in the ethers file and the DNS, or the
+		 * ethernet address denotes a special additional address
+		 * used for implementing a TCP/IP stack in user space.
+		 */
+		for (i= 0; hostent->h_addr_list[i] != NULL; i++) {
+		    memcpy(&ip_addr, hostent->h_addr_list[i], sizeof(ipaddr_t));
+
+		    /* Check if the address is on this network. */
+		    if (((ip_addr ^ ep->ip_addr) & ep->ip_mask) == 0) break;
+		}
+
+		if (hostent->h_addr_list[i] != NULL) {
+		    rarp_reply(ep, hostname, ip_addr, rarp46.a46_tha);
+		} else {
+		    if (debug >= 2) {
+			printf("%s: Host '%s' (%s) is on the wrong net\n",
+			    ethdev(ep->n),
+			    hostname, ether_ntoa(&rarp46.a46_tha));
+		    }
+		}
+	    } else {
+		if (debug >= 2) {
+		    printf("%s: RARP request from unknown host '%s'\n",
+			ethdev(ep->n), ether_ntoa(&rarp46.a46_tha));
+		}
+	    }
+	}
+
+	/* Wait for another request. */
+	if (asyn_wait(&asyn, 0, NULL) < 0) {
+	    report("asyn_wait()");
+	    sleep(10);
+	}
+    }
+}
Index: /trunk/minix/commands/simple/rawspeed.c
===================================================================
--- /trunk/minix/commands/simple/rawspeed.c	(revision 9)
+++ /trunk/minix/commands/simple/rawspeed.c	(revision 9)
@@ -0,0 +1,273 @@
+/*	rawspeed 1.15 - Measure speed of a device.	Author: Kees J. Bot
+ *								26 Apr 1992
+ */
+#define nil 0
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#if !__minix
+#include <sys/time.h>
+#endif
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/stat.h>
+
+#define SECTOR_SIZE		512
+#define BLK_MAX_SECTORS		(sizeof(int) == 2 ? 32 : 64)
+#define CHR_MAX_SECTORS		(sizeof(int) == 2 ? 63 : 512)
+#define ABS_MAX_SECTORS		(INT_MAX / SECTOR_SIZE)
+
+#define USEC	(!__minix || __minix_vmd)
+
+/* Any good random number generator around? */
+#if __minix_vmd || __linux
+#define	rand	random
+#define srand	srandom
+#endif
+
+#if __sun && __svr4__
+#define rand	lrand48
+#define srand	srand48
+#endif
+
+void report(const char *label)
+{
+	fprintf(stderr, "rawspeed: %s: %s\n", label, strerror(errno));
+}
+
+void fatal(const char *label)
+{
+	report(label);
+	exit(1);
+}
+
+void usage(void)
+{
+	fprintf(stderr,
+"Usage: rawspeed [-u unit] [-m max] [-t seconds] [-c] [-r limit] device\n");
+	fprintf(stderr,
+"       -u unit = best sector multiple (default 2)\n");
+	fprintf(stderr,
+"       -m max = read multiples of unit upto 'max' (default %d raw, %d file)\n",
+					CHR_MAX_SECTORS, BLK_MAX_SECTORS);
+	fprintf(stderr,
+"       -t seconds = time to run test (default 10)\n");
+	fprintf(stderr,
+"       -c = cache test: rewind after each read or write of max size\n");
+	fprintf(stderr,
+"       -r limit = random seeks upto sector 'limit' before reading or writing\n");
+	exit(1);
+}
+
+int done= 0;
+
+void timeout(int sig)
+{
+	done= 1;
+}
+
+int main(int argc, char **argv)
+{
+	int i, fd, n= 0, unit= -1, max= -1, cache= 0;
+	int size, seconds= 10;
+	long tenthsec;
+#if USEC
+	struct timeval start_time, end_time;
+	struct timezone dummy;
+#else
+	time_t start_time;
+#endif
+	off_t nbytes= 0, wbytes= 0, randlimit= 0;
+	char *device, *chunk;
+	struct stat st;
+	off_t nseeks= 0;
+
+	for (i= 1; i < argc && argv[i][0] == '-' && argv[i][1] != 0; i++) {
+		char *opt;
+
+		if (argv[i][1] == '-' && argv[i][2] == 0) { i++; break; }
+
+		for (opt= argv[i]+1; *opt != 0; opt++) {
+			switch (*opt) {
+			case 'w':
+				if (i == argc) usage();
+				wbytes= atol(argv[++i]) * 1024;
+				if (wbytes <= 0) usage();
+				break;
+			case 'm':
+				if (i == argc) usage();
+				max= atoi(argv[++i]);
+				if (max <= 0 || max > ABS_MAX_SECTORS)
+					usage();
+				break;
+			case 'u':
+				if (i == argc) usage();
+				unit= atoi(argv[++i]);
+				if (unit <= 0 || unit > ABS_MAX_SECTORS)
+					usage();
+				break;
+			case 't':
+				if (i == argc) usage();
+				seconds= atoi(argv[++i]);
+				if (seconds <= 0) usage();
+				break;
+			case 'c':
+				cache= 1;
+				break;
+			case 'r':
+				if (i == argc) usage();
+				randlimit= atol(argv[++i]);
+				if (randlimit <= 0) usage();
+				break;
+			default:
+				usage();
+			}
+		}
+	}
+
+	if (i != argc - 1) usage();
+
+	if (strcmp(argv[i], "-") == 0) {
+		fd= wbytes == 0 ? 0 : 1;
+		device= "";
+	} else {
+		device= argv[i];
+		if ((fd= open(device,
+			wbytes == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666)) < 0)
+				fatal(device);
+	}
+	if (max < 0) {
+		if (fstat(fd, &st) >= 0 && S_ISCHR(st.st_mode))
+			max= CHR_MAX_SECTORS;
+		else
+			max= BLK_MAX_SECTORS;
+	}
+
+	if (unit < 0) unit= max > 1 ? 2 : 1;
+	unit*= max / unit;
+	if (unit == 0) usage();
+	size= unit * SECTOR_SIZE;
+	randlimit/= unit;
+
+	if ((chunk= malloc((size_t) size)) == nil) {
+		fprintf(stderr, "rawspeed: can't grab %d bytes: %s\n",
+			size, strerror(errno));
+		exit(1);
+	}
+
+	/* Touch the pages to get real memory sending other processes to swap.
+	 */
+	memset((void *) chunk, 0, (size_t) size);
+
+	/* Clean the cache. */
+	sync();
+
+	signal(SIGALRM, timeout);
+	signal(SIGINT, timeout);
+#if USEC
+	gettimeofday(&start_time, &dummy);
+	if (randlimit != 0) srand((int) (start_time.tv_sec & INT_MAX));
+#else
+	start_time= time((time_t *) nil);
+	if (randlimit != 0) srand((int) (start_time & INT_MAX));
+#endif
+	alarm(seconds);
+
+	if (wbytes > 0) {
+		while (!done && (n= write(fd, chunk, size)) > 0
+						&& (nbytes+= n) < wbytes) {
+			if (cache && lseek(fd, (off_t) 0, SEEK_SET) == -1)
+				fatal(device);
+			if (randlimit != 0) {
+				if (lseek(fd, (off_t)
+					(rand() % randlimit * size),
+							SEEK_SET) == -1)
+					fatal(device);
+				nseeks++;
+			}
+		}
+		sync();
+	} else {
+		while (!done && (n= read(fd, chunk, size)) > 0) {
+			nbytes+= n;
+			if (cache && lseek(fd, (off_t) 0, SEEK_SET) == -1)
+				fatal(device);
+			if (randlimit != 0) {
+				if (lseek(fd, (off_t)
+					(rand() % randlimit * size),
+							SEEK_SET) == -1)
+					fatal(device);
+				nseeks++;
+			}
+		}
+	}
+
+#if USEC
+	gettimeofday(&end_time, &dummy);
+	tenthsec= (end_time.tv_sec - start_time.tv_sec) * 10
+		+ (end_time.tv_usec - start_time.tv_usec) / 100000;
+#else
+	tenthsec= (time((time_t *) 0) - start_time) * 10;
+#endif
+	if (n < 0 && errno == EINTR) n= 0;
+	if (n < 0) report(device);
+
+	if (nbytes > 0) {
+		off_t kBpts;
+
+		fprintf(stderr, "%ld kB / %d.%d s = ",
+			(nbytes + 512) / 1024,
+			tenthsec / 10, tenthsec % 10);
+		if (tenthsec < 5)
+			fprintf(stderr, "infinite\n");
+		else {
+			if (nbytes > LONG_MAX / 100) {
+				seconds = (tenthsec + 5) / 10;
+				kBpts= (nbytes + 512L * seconds)
+							/ (1024L * seconds);
+				fprintf(stderr, "%ld kB/s\n", kBpts);
+			} else {
+				kBpts= (100 * nbytes + 512L * tenthsec)
+							/ (1024L * tenthsec);
+				fprintf(stderr, "%ld.%ld kB/s\n",
+					kBpts/10, kBpts%10);
+			}
+		}
+	}
+	if (randlimit != 0 && tenthsec >= 5) {
+		int rpm, disc= 0;
+		off_t tenthms;
+
+		tenthms= (tenthsec * 1000 + nseeks/2) / nseeks;
+
+		fprintf(stderr,
+			"%ld seeks / %d.%d s = %ld seeks/s = %ld.%ld ms/seek\n",
+			nseeks, tenthsec / 10, tenthsec % 10,
+			(nseeks * 10 + tenthsec/2) / tenthsec,
+			tenthms / 10, tenthms % 10);
+
+		for (rpm= 3600; rpm <= 7200; rpm+= 1800) {
+			int rotms = (10000L / 2 * 60 + rpm/2) / rpm;
+
+			if (tenthms <= rotms) continue;
+
+			if (!disc) {
+				fprintf(stderr,
+					"discarding av. rotational delay:\n  ");
+				disc= 1;
+			} else {
+				fprintf(stderr, ", ");
+			}
+			fprintf(stderr, "%ld.%ld ms (%d rpm)",
+				(tenthms - rotms) / 10, (tenthms - rotms) % 10,
+				rpm);
+		}
+		if (disc) fputc('\n', stdout);
+	}
+	return n < 0 ? 1 : 0;
+}
Index: /trunk/minix/commands/simple/rcp.c
===================================================================
--- /trunk/minix/commands/simple/rcp.c	(revision 9)
+++ /trunk/minix/commands/simple/rcp.c	(revision 9)
@@ -0,0 +1,848 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1983 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rcp.c 1.1 87/12/21 SMI"; /* from UCB 5.3 6/8/85"*/
+#endif /* not lint */
+
+/*
+ * rcp
+ */
+
+#undef _MINIX
+#define NAMESERVER
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <utime.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <net/gen/netdb.h>
+#include <net/netlib.h>
+
+#if __STDC__
+#define PROTO(func, args)	func args
+#else
+#define PROTO(func, args)	func ()
+#endif /* __STDC__ */
+
+PROTO (int main, (int argc, char *argv[]));
+PROTO (void lostconn, (int sig));
+PROTO (void error, (char *fmt, ...) );
+PROTO (int response, (void) );
+PROTO (void source, (int argc, char *argv[]) );
+PROTO (void sink, (int argc, char *argv[]) );
+PROTO (void usage, (void) );
+PROTO (char *colon, (char *cp) );
+PROTO (int okname, (char *cp0) );
+PROTO (int susystem, (char *s) );
+PROTO (void verifydir, (char *cp) );
+PROTO (void rsource, (char *name, struct stat *statp) );
+PROTO (struct buffer *allocbuf, (struct buffer *bp, int fd, int blksize) );
+
+#define vfork	fork
+
+int	rem;
+int	errs;
+int	errno;
+int	iamremote, targetshouldbedirectory;
+int	iamrecursive;
+int	myuid;		/* uid of invoker */
+int	pflag;
+struct	passwd *pwd;
+int	userid;
+int	port;
+
+struct buffer {
+	int	cnt;
+	char	*buf;
+};
+
+
+#define	ga()	 	(void) write(rem, "", 1)
+
+main(argc, argv)
+	int argc;
+	char **argv;
+{
+	char *targ, *host, *src;
+#ifndef NAMESERVER
+	char *suser, *tuser;
+#else /* NAMESERVER */
+	char *suser, *tuser, *thost;
+#endif /* NAMESERVER */
+	int i;
+	char buf[BUFSIZ], cmd[16];
+	struct servent *sp;
+
+	sp = getservbyname("shell", "tcp");
+	if (sp == NULL) {
+		fprintf(stderr, "rcp: shell/tcp: unknown service\n");
+		exit(1);
+	}
+	port = sp->s_port;
+	pwd = getpwuid(userid = getuid());
+	if (pwd == 0) {
+		fprintf(stderr, "who are you?\n");
+		exit(1);
+	}
+
+#ifdef NOT_DEF
+	/*
+	 * This is a kludge to allow seteuid to user before touching
+	 * files and seteuid root before doing rcmd so we can open
+	 * the socket.
+	 */
+	myuid = getuid();
+	if (setruid(0) < 0) {
+		perror("setruid root");
+		exit(1);
+	}
+	seteuid(myuid);
+#endif
+
+	for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
+		(*argv)++;
+		while (**argv) switch (*(*argv)++) {
+
+		    case 'r':
+			iamrecursive++;
+			break;
+
+		    case 'p':		/* preserve mtimes and atimes */
+			pflag++;
+			break;
+
+		    /* The rest of these are not for users. */
+		    case 'd':
+			targetshouldbedirectory = 1;
+			break;
+
+		    case 'f':		/* "from" */
+			iamremote = 1;
+			(void) response();
+			source(--argc, ++argv);
+			exit(errs);
+
+		    case 't':		/* "to" */
+			iamremote = 1;
+			sink(--argc, ++argv);
+			exit(errs);
+
+		    default:
+			usage();
+			exit(1);
+		}
+	}
+if (iamremote)
+{
+	close(2);
+	open("/dev/tty", 2);
+}
+
+	if (argc < 2) {
+		usage();
+		exit(1);
+	}
+	rem = -1;
+	if (argc > 2)
+		targetshouldbedirectory = 1;
+	(void) sprintf(cmd, "rcp%s%s%s",
+	    iamrecursive ? " -r" : "", pflag ? " -p" : "", 
+	    targetshouldbedirectory ? " -d" : "");
+	(void) signal(SIGPIPE, lostconn);
+	targ = colon(argv[argc - 1]);
+	if (targ) {				/* ... to remote */
+		*targ++ = 0;
+		if (*targ == 0)
+			targ = ".";
+#ifndef NAMESERVER
+		tuser = strrchr(argv[argc - 1], '.');
+		if (tuser) {
+			*tuser++ = 0;
+			if (!okname(tuser))
+				exit(1);
+		} else
+			tuser = pwd->pw_name;
+#else /* NAMESERVER */
+		thost = strchr(argv[argc - 1], '@');
+		if (thost) {
+			*thost++ = 0;
+			tuser = argv[argc - 1];
+			if (*tuser == '\0')
+				tuser = pwd->pw_name;
+			else if (!okname(tuser))
+				exit(1);
+		} else {
+			thost = argv[argc - 1];
+			tuser = pwd->pw_name;
+		}
+#endif /* NAMESERVER */
+		for (i = 0; i < argc - 1; i++) {
+			src = colon(argv[i]);
+			if (src) {		/* remote to remote */
+				*src++ = 0;
+				if (*src == 0)
+					src = ".";
+#ifndef NAMESERVER
+				suser = strrchr(argv[i], '.');
+				if (suser) {
+					*suser++ = 0;
+					if (!okname(suser))
+#else /* NAMESERVER */
+				host = strchr(argv[i], '@');
+				if (host) {
+					*host++ = 0;
+					suser = argv[i];
+					if (*suser == '\0')
+						suser = pwd->pw_name;
+					else if (!okname(suser))
+#endif /* NAMESERVER */
+						continue;
+#ifndef NAMESERVER
+		(void) sprintf(buf, "rsh %s -l %s -n %s %s '%s.%s:%s'",
+					    argv[i], suser, cmd, src,
+					    argv[argc - 1], tuser, targ);
+				} else
+		(void) sprintf(buf, "rsh %s -n %s %s '%s.%s:%s'",
+					    argv[i], cmd, src,
+					    argv[argc - 1], tuser, targ);
+#else /* NAMESERVER */
+		(void) sprintf(buf, "rsh %s -l %s -n %s %s '%s@%s:%s'",
+					    host, suser, cmd, src,
+					    tuser, thost, targ);
+				} else
+		(void) sprintf(buf, "rsh %s -n %s %s '%s@%s:%s'",
+					    argv[i], cmd, src,
+					    tuser, thost, targ);
+#endif /* NAMESERVER */
+				(void) susystem(buf);
+			} else {		/* local to remote */
+				if (rem == -1) {
+					(void) sprintf(buf, "%s -t %s",
+					    cmd, targ);
+#ifndef NAMESERVER
+					host = argv[argc - 1];
+#else /* NAMESERVER */
+					host = thost;
+#endif /* NAMESERVER */
+#ifdef NOT_DEF
+					if (seteuid(0) < 0) {
+						perror("seteuid root");
+						exit(1);
+					}
+#endif
+					rem = rcmd(&host, port, pwd->pw_name,
+					    tuser, buf, 0);
+#ifdef NO_DEF
+					seteuid(myuid);
+#endif
+					if (rem < 0)
+						exit(1);
+					if (response() < 0)
+						exit(1);
+				}
+				source(1, argv+i);
+			}
+		}
+	} else {				/* ... to local */
+		if (targetshouldbedirectory)
+			verifydir(argv[argc - 1]);
+		for (i = 0; i < argc - 1; i++) {
+			src = colon(argv[i]);
+			if (src == 0) {		/* local to local */
+				(void) sprintf(buf, "cp%s%s %s %s",
+				    iamrecursive ? " -r" : "",
+				    pflag ? " -p" : "",
+				    argv[i], argv[argc - 1]);
+				(void) susystem(buf);
+			} else {		/* remote to local */
+				*src++ = 0;
+				if (*src == 0)
+					src = ".";
+#ifndef NAMESERVER
+				suser = strrchr(argv[i], '.');
+				if (suser) {
+					*suser++ = 0;
+					if (!okname(suser))
+#else /* NAMESERVER */
+				host = strchr(argv[i], '@');
+				if (host) {
+					*host++ = 0;
+					suser = argv[i];
+					if (*suser == '\0')
+						suser = pwd->pw_name;
+					else if (!okname(suser))
+#endif /* NAMESERVER */
+						continue;
+#ifndef NAMESERVER
+				} else
+#else /* NAMESERVER */
+				} else {
+					host = argv[i];
+#endif /* NAMESERVER */
+					suser = pwd->pw_name;
+#ifdef NAMESERVER
+				}
+#endif /* NAMESERVER */
+				(void) sprintf(buf, "%s -f %s", cmd, src);
+#ifndef NAMESERVER
+				host = argv[i];
+#endif /* NAMESERVER */
+#ifdef NOT_DEF
+				if (seteuid(0) < 0) {
+					perror("seteuid root");
+					exit(1);
+				}
+#endif
+				rem = rcmd(&host, port, pwd->pw_name, suser,
+				    buf, 0);
+#ifdef NOT_DEF
+				seteuid(myuid);
+#endif
+				if (rem < 0) {
+					errs++;
+					continue;
+				}
+				sink(1, argv+argc-1);
+				(void) close(rem);
+				rem = -1;
+			}
+		}
+	}
+	exit(errs);
+}
+
+void
+verifydir(cp)
+	char *cp;
+{
+	struct stat stb;
+
+	if (stat(cp, &stb) >= 0) {
+		if ((stb.st_mode & S_IFMT) == S_IFDIR)
+			return;
+		errno = ENOTDIR;
+	}
+	error("rcp: %s: %s.\n", cp, strerror(errno));
+	exit(1);
+}
+
+char *
+colon(cp)
+	char *cp;
+{
+
+	while (*cp) {
+		if (*cp == ':')
+			return (cp);
+		if (*cp == '/')
+			return (0);
+		cp++;
+	}
+	return (0);
+}
+
+
+int
+okname(cp0)
+	char *cp0;
+{
+	register char *cp = cp0;
+	register int c;
+
+	do {
+		c = *cp;
+		if (c & 0200)
+			goto bad;
+		if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
+			goto bad;
+		cp++;
+	} while (*cp);
+	return (1);
+bad:
+	fprintf(stderr, "rcp: invalid user name %s\n", cp0);
+	return (0);
+}
+
+int
+susystem(s)
+	char *s;
+{
+	int status, pid, w;
+	register void PROTO ((*istat), (int) ), PROTO ((*qstat), (int) );
+
+	if ((pid = vfork()) == 0) {
+#ifdef NOT_DEF
+		(void) setruid(myuid);
+#endif
+		execl("/bin/sh", "sh", "-c", s, (char *)0);
+		_exit(127);
+	}
+	istat = signal(SIGINT, SIG_IGN);
+	qstat = signal(SIGQUIT, SIG_IGN);
+	while ((w = wait(&status)) != pid && w != -1)
+		;
+	if (w == -1)
+		status = -1;
+	(void) signal(SIGINT, istat);
+	(void) signal(SIGQUIT, qstat);
+	return (status);
+}
+
+void
+source(argc, argv)
+	int argc;
+	char **argv;
+{
+	char *last, *name;
+	struct stat stb;
+	static struct buffer buffer;
+	struct buffer *bp;
+	int x, sizerr, f, amt;
+	off_t i;
+	char buf[BUFSIZ];
+
+	for (x = 0; x < argc; x++) {
+		name = argv[x];
+		if ((f = open(name, 0)) < 0) {
+			error("rcp: %s: %s\n", name, strerror(errno));
+			continue;
+		}
+		if (fstat(f, &stb) < 0)
+			goto notreg;
+		switch (stb.st_mode&S_IFMT) {
+
+		case S_IFREG:
+			break;
+
+		case S_IFDIR:
+			if (iamrecursive) {
+				(void) close(f);
+				rsource(name, &stb);
+				continue;
+			}
+			/* fall into ... */
+		default:
+notreg:
+			(void) close(f);
+			error("rcp: %s: not a plain file\n", name);
+			continue;
+		}
+		last = strrchr(name, '/');
+		if (last == 0)
+			last = name;
+		else
+			last++;
+		if (pflag) {
+			/*
+			 * Make it compatible with possible future
+			 * versions expecting microseconds.
+			 */
+			(void) sprintf(buf, "T%ld 0 %ld 0\n",
+			    stb.st_mtime, stb.st_atime);
+			(void) write(rem, buf, strlen(buf));
+			if (response() < 0) {
+				(void) close(f);
+				continue;
+			}
+		}
+		(void) sprintf(buf, "C%04o %ld %s\n",
+		    stb.st_mode&07777, stb.st_size, last);
+		(void) write(rem, buf, strlen(buf));
+		if (response() < 0) {
+			(void) close(f);
+			continue;
+		}
+		if ((bp = allocbuf(&buffer, f, BUFSIZ)) == 0) {
+			(void) close(f);
+			continue;
+		}
+		sizerr = 0;
+		for (i = 0; i < stb.st_size; i += bp->cnt) {
+			amt = bp->cnt;
+			if (i + amt > stb.st_size)
+				amt = stb.st_size - i;
+			if (sizerr == 0 && read(f, bp->buf, amt) != amt)
+				sizerr = 1;
+			(void) write(rem, bp->buf, amt);
+		}
+		(void) close(f);
+		if (sizerr == 0)
+			ga();
+		else
+			error("rcp: %s: file changed size\n", name);
+		(void) response();
+	}
+}
+
+
+void
+rsource(name, statp)
+	char *name;
+	struct stat *statp;
+{
+	DIR *d = opendir(name);
+	char *last;
+	struct dirent *dp;
+	char buf[BUFSIZ];
+	char *bufv[1];
+
+	if (d == 0) {
+		error("rcp: %s: %s\n", name, strerror(errno));
+		return;
+	}
+	last = strrchr(name, '/');
+	if (last == 0)
+		last = name;
+	else
+		last++;
+	if (pflag) {
+		(void) sprintf(buf, "T%ld 0 %ld 0\n",
+		    statp->st_mtime, statp->st_atime);
+		(void) write(rem, buf, strlen(buf));
+		if (response() < 0) {
+			closedir(d);
+			return;
+		}
+	}
+	(void) sprintf(buf, "D%04o %d %s\n", statp->st_mode&07777, 0, last);
+	(void) write(rem, buf, strlen(buf));
+	if (response() < 0) {
+		closedir(d);
+		return;
+	}
+	while (dp = readdir(d)) {
+		if (dp->d_ino == 0)
+			continue;
+		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
+			continue;
+		if (strlen(name) + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
+			error("%s/%s: Name too long.\n", name, dp->d_name);
+			continue;
+		}
+		(void) sprintf(buf, "%s/%s", name, dp->d_name);
+		bufv[0] = buf;
+		source(1, bufv);
+	}
+	closedir(d);
+	(void) write(rem, "E\n", 2);
+	(void) response();
+}
+
+int
+response()
+{
+	char resp, c, rbuf[BUFSIZ], *cp = rbuf;
+
+	if (read(rem, &resp, 1) != 1)
+		lostconn(0);
+	switch (resp) {
+
+	case 0:				/* ok */
+		return (0);
+
+	default:
+		*cp++ = resp;
+		/* fall into... */
+	case 1:				/* error, followed by err msg */
+	case 2:				/* fatal error, "" */
+		do {
+			if (read(rem, &c, 1) != 1)
+				lostconn(0);
+			*cp++ = c;
+		} while (cp < &rbuf[BUFSIZ] && c != '\n');
+		if (iamremote == 0)
+			(void) write(2, rbuf, cp - rbuf);
+		errs++;
+		if (resp == 1)
+			return (-1);
+		exit(1);
+	}
+	/*NOTREACHED*/
+}
+
+void
+lostconn(sig)
+int sig;
+{
+
+	if (iamremote == 0)
+		fprintf(stderr, "rcp: lost connection\n");
+	exit(1);
+}
+
+void
+sink(argc, argv)
+	int argc;
+	char **argv;
+{
+	off_t i, j, size;
+	char *targ, *whopp, *cp;
+	int of, mode, wrerr, exists, first, count, amt;
+	struct buffer *bp;
+	static struct buffer buffer;
+	struct stat stb;
+	int targisdir = 0;
+	int mask = umask(0);
+	char *myargv[1];
+	char cmdbuf[BUFSIZ], nambuf[BUFSIZ];
+	int setimes = 0;
+	struct utimbuf utimbuf;
+#define atime	utimbuf.actime
+#define mtime	utimbuf.modtime
+	time_t dummy;
+#define	SCREWUP(str)	{ whopp = str; goto screwup; }
+
+#ifdef NOT_DEF
+	seteuid(pwd->pw_uid);
+#endif
+	if (!pflag)
+		(void) umask(mask);
+	if (argc != 1) {
+		error("rcp: ambiguous target\n");
+		exit(1);
+	}
+	targ = *argv;
+	if (targetshouldbedirectory)
+		verifydir(targ);
+	ga();
+	if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR)
+		targisdir = 1;
+	for (first = 1; ; first = 0) {
+		cp = cmdbuf;
+		if (read(rem, cp, 1) <= 0)
+			return;
+		if (*cp++ == '\n')
+			SCREWUP("unexpected '\\n'");
+		do {
+			if (read(rem, cp, 1) != 1)
+				SCREWUP("lost connection");
+		} while (*cp++ != '\n');
+		*cp = 0;
+		if (cmdbuf[0] == '\01' || cmdbuf[0] == '\02') {
+			if (iamremote == 0)
+				(void) write(2, cmdbuf+1, strlen(cmdbuf+1));
+			if (cmdbuf[0] == '\02')
+				exit(1);
+			errs++;
+			continue;
+		}
+		*--cp = 0;
+		cp = cmdbuf;
+		if (*cp == 'E') {
+			ga();
+			return;
+		}
+
+#define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0');
+		if (*cp == 'T') {
+			setimes++;
+			cp++;
+			getnum(mtime);
+			if (*cp++ != ' ')
+				SCREWUP("mtime.sec not delimited");
+			getnum(dummy);
+			if (*cp++ != ' ')
+				SCREWUP("mtime.usec not delimited");
+			getnum(atime);
+			if (*cp++ != ' ')
+				SCREWUP("atime.sec not delimited");
+			getnum(dummy);
+			if (*cp++ != '\0')
+				SCREWUP("atime.usec not delimited");
+			ga();
+			continue;
+		}
+		if (*cp != 'C' && *cp != 'D') {
+			/*
+			 * Check for the case "rcp remote:foo\* local:bar".
+			 * In this case, the line "No match." can be returned
+			 * by the shell before the rcp command on the remote is
+			 * executed so the ^Aerror_message convention isn't
+			 * followed.
+			 */
+			if (first) {
+				error("%s\n", cp);
+				exit(1);
+			}
+			SCREWUP("expected control record");
+		}
+		cp++;
+		mode = 0;
+		for (; cp < cmdbuf+5; cp++) {
+			if (*cp < '0' || *cp > '7')
+				SCREWUP("bad mode");
+			mode = (mode << 3) | (*cp - '0');
+		}
+		if (*cp++ != ' ')
+			SCREWUP("mode not delimited");
+		size = 0;
+		while (isdigit(*cp))
+			size = size * 10 + (*cp++ - '0');
+		if (*cp++ != ' ')
+			SCREWUP("size not delimited");
+		if (targisdir)
+			(void) sprintf(nambuf, "%s%s%s", targ,
+			    *targ ? "/" : "", cp);
+		else
+			(void) strcpy(nambuf, targ);
+		exists = stat(nambuf, &stb) == 0;
+		if (cmdbuf[0] == 'D') {
+			if (exists) {
+				if ((stb.st_mode&S_IFMT) != S_IFDIR) {
+					errno = ENOTDIR;
+					goto bad;
+				}
+				if (pflag)
+					(void) chmod(nambuf, mode);
+			} else if (mkdir(nambuf, mode) < 0)
+				goto bad;
+			myargv[0] = nambuf;
+			sink(1, myargv);
+			if (setimes) {
+				setimes = 0;
+				if (utime(nambuf, &utimbuf) < 0)
+					error("rcp: can't set times on %s: %s\n",
+					    nambuf, strerror(errno));
+			}
+			continue;
+		}
+		if ((of = creat(nambuf, mode)) < 0) {
+	bad:
+			error("rcp: %s: %s\n", nambuf, strerror(errno));
+			continue;
+		}
+		if (exists && pflag)
+			(void) chmod(nambuf, mode);
+		ga();
+		if ((bp = allocbuf(&buffer, of, BUFSIZ)) == 0) {
+			(void) close(of);
+			continue;
+		}
+		cp = bp->buf;
+		count = 0;
+		wrerr = 0;
+		for (i = 0; i < size; i += BUFSIZ) {
+			amt = BUFSIZ;
+			if (i + amt > size)
+				amt = size - i;
+			count += amt;
+			do {
+				j = read(rem, cp, amt);
+				if (j <= 0)
+					exit(1);
+				amt -= j;
+				cp += j;
+			} while (amt > 0);
+			if (count == bp->cnt) {
+				if (wrerr == 0 &&
+				    write(of, bp->buf, count) != count)
+					wrerr++;
+				count = 0;
+				cp = bp->buf;
+			}
+		}
+		if (count != 0 && wrerr == 0 &&
+		    write(of, bp->buf, count) != count)
+			wrerr++;
+		(void) close(of);
+		(void) response();
+		if (setimes) {
+			setimes = 0;
+			if (utime(nambuf, &utimbuf) < 0)
+				error("rcp: can't set times on %s: %s\n",
+				    nambuf, strerror(errno));
+		}				   
+		if (wrerr)
+			error("rcp: %s: %s\n", nambuf, strerror(errno));
+		else
+			ga();
+	}
+screwup:
+	error("rcp: protocol screwup: %s\n", whopp);
+	exit(1);
+}
+
+struct buffer *
+allocbuf(bp, fd, blksize)
+	struct buffer *bp;
+	int fd, blksize;
+{
+	struct stat stb;
+	int size;
+
+	if (fstat(fd, &stb) < 0) {
+		error("rcp: fstat: %s\n", strerror(errno));
+		return ((struct buffer *)0);
+	}
+	size= 0;
+#if NOT_DEF
+	size = roundup(stb.st_blksize, blksize);
+#endif
+	if (size == 0)
+		size = blksize;
+	if (bp->cnt < size) {
+		if (bp->buf != 0)
+			free(bp->buf);
+		bp->buf = (char *)malloc((unsigned) size);
+		if (bp->buf == 0) {
+			error("rcp: malloc: out of memory\n");
+			return ((struct buffer *)0);
+		}
+	}
+	bp->cnt = size;
+	return (bp);
+}
+
+/*VARARGS1*/
+#if __STDC__
+void
+error (char *fmt, ...)
+#else
+error(fmt)
+char *fmt;
+#endif
+{
+	char buf[BUFSIZ], *cp = buf;
+	va_list ap;
+
+	va_start(ap, fmt);
+
+	errs++;
+	*cp++ = 1;
+	(void) vsprintf(cp, fmt, ap);
+	va_end(ap);
+	(void) write(rem, buf, strlen(buf));
+	if (iamremote == 0)
+		(void) write(2, buf+1, strlen(buf+1));
+}
+
+void
+usage()
+{
+	fprintf(stderr, "Usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn d2\n");
+}
Index: /trunk/minix/commands/simple/rdate.c
===================================================================
--- /trunk/minix/commands/simple/rdate.c	(revision 9)
+++ /trunk/minix/commands/simple/rdate.c	(revision 9)
@@ -0,0 +1,109 @@
+/*	rdate 1.0 - Set time&date from remote host	Author: Kees J. Bot
+ *								12 Oct 1995
+ */
+#define nil 0
+#include <sys/types.h>
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <net/hton.h>
+#include <net/netlib.h>
+#include <net/gen/in.h>
+#include <net/gen/netdb.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+
+void report(const char *label)
+{
+	fprintf(stderr, "rdate: %s: %s\n", label, strerror(errno));
+}
+
+void fatal(const char *label)
+{
+	report(label);
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	char *tcp_device;
+	int fd;
+	int i;
+	struct servent *servent;
+	struct hostent *hostent;
+	u16_t time_port;
+	nwio_tcpconf_t tcpconf;
+	nwio_tcpcl_t tcpcl;
+	u32_t net_time;
+	time_t unix_time;
+
+	if (argc <= 1) {
+		fprintf(stderr, "Usage: rdate host ...\n");
+		exit(1);
+	}
+
+	/* Look up the port number of the TCP service "time". */
+	if ((servent= getservbyname("time", "tcp")) == nil) {
+		fprintf(stderr, "rdate: \"time\": unknown service\n");
+		exit(1);
+	}
+	time_port= servent->s_port;
+
+	if ((tcp_device= getenv("TCP_DEVICE")) == nil) tcp_device= TCP_DEVICE;
+
+	if ((fd= open(tcp_device, O_RDWR)) < 0) fatal(tcp_device);
+
+	/* Try each host on the command line. */
+	for (i= 1; i < argc; i++) {
+		if ((hostent= gethostbyname(argv[i])) == nil) {
+			fprintf(stderr, "rdate: %s: unknown host\n", argv[i]);
+			continue;
+		}
+
+		/* Configure a TCP channel and connect to the remote host. */
+
+		tcpconf.nwtc_flags= NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
+		memcpy(&tcpconf.nwtc_remaddr, hostent->h_addr, 4);
+		tcpconf.nwtc_remport= time_port;
+		if (ioctl(fd, NWIOSTCPCONF, &tcpconf) == -1) fatal(tcp_device);
+
+		tcpcl.nwtcl_flags= 0;
+		if (ioctl(fd, NWIOTCPCONN, &tcpcl) < 0) {
+			report(argv[i]);
+			continue;
+		}
+
+		/* Read four bytes to obtain the time. */
+		switch (read(fd, &net_time, sizeof(net_time))) {
+		case -1:
+			report(argv[i]);
+			continue;
+		default:
+			fprintf(stderr, "rdate: %s: short read\n", argv[i]);
+			continue;
+		case sizeof(net_time):
+			break;
+		}
+		break;
+	}
+	if (i == argc) exit(1);
+
+	/* Internet time is in seconds since 1900, UNIX time is in seconds
+	 * since 1970.
+	 */
+	unix_time= ntohl(net_time) - 2208988800;
+
+	/* Try to set the time and tell us about it. */
+	if (stime(&unix_time) < 0) {
+		printf("time on ");
+	} else {
+		printf("time set to ");
+	}
+	printf("%s: %s", argv[i], ctime(&unix_time));
+	exit(0);
+}
Index: /trunk/minix/commands/simple/readall.c
===================================================================
--- /trunk/minix/commands/simple/readall.c	(revision 9)
+++ /trunk/minix/commands/simple/readall.c	(revision 9)
@@ -0,0 +1,194 @@
+/* readall - read a whole device fast		Author: Andy Tanenbaum */
+
+/* Readall reads all the blocks on a device as fast as it can.  If it hits
+ * an error, it stops reading in large units and reads one block at a time.
+ * It reports on all errors it finds.
+ *
+ * If the -b flag is given, the output is a shell script that can be run
+ * to mark all the bad blocks.
+ *
+ * If the -t flag is given, only the total numbers of blocks is reported.
+ *
+ * Examples of usage:
+ *	readall /dev/hd1		# read /dev/hd1
+ *	readall -b /dev/hd2		# prepare bad block list on stdout
+ *	readall -t /dev/ram		# report size of ram disk
+ */
+
+#include <sys/types.h>
+#include <sys/ioc_disk.h>
+#include <minix/partition.h>
+#include <minix/u64.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define CHUNK    25		/* max number of blocks read at once */
+#define BLOCK_SIZE	1024	/* size of a block */
+#define RESUME  200		/* # good reads before going back to CHUNK */
+#define DIVISOR	 1000		/* how often to print statistics */
+#define STORE  4096		/* save this many bad blocks for summary */
+
+int chunk = CHUNK;		/* current number of blocks being read */
+long goodies;			/* incremented on good reads */
+long errors;			/* number of errors so far */
+int normal = 1;			/* set unless -b flag is given */
+int total = 0;			/* unset unless -t flag is given */
+char *name;			/* name of special file being read */
+
+char a[CHUNK * BLOCK_SIZE];	/* read buffer */
+long rotten[STORE];		/* list of bad blocks */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+static _PROTOTYPE(void output, (long blocks_read));
+
+/* print pretty progress meter with remaining no. of blocks and ETA on
+ * stderr
+ */
+void
+prettyprogress(long b, long nblocks, time_t starttime)
+{
+  /* print progress indication */
+  time_t spent, now;
+  long bpsec;
+  time(&now);
+  spent = now - starttime;
+  if(spent > 0 && (bpsec = b / spent) > 0) {
+  	int len, i;
+  	long secremain, minremain, hremain;
+	  secremain = (nblocks - b) / bpsec;
+	  minremain = (secremain / 60) % 60;
+	  hremain = secremain / 3600;
+  	len = fprintf(stderr, "Remain %ld blocks. ETA: %d:%02d:%02d  [",
+  		nblocks - b,
+  		hremain, minremain, secremain % 60);
+#define WIDTH 77
+  	len = WIDTH - len;
+  	for(i = 0; i < (b * (len-1) / nblocks); i++) 
+  		fprintf(stderr, "=");
+ 	fprintf(stderr, "|");
+  	for(; i < len-2; i++) 
+  		fprintf(stderr, "-");
+  	fprintf(stderr, "]\r");
+  	fflush(stderr);
+  }
+
+  return;
+}
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  struct partition entry;
+  int fd, s, i, badprinted;
+  long b = 0, nblocks;
+  char *p;
+  time_t starttime;
+
+  if (argc != 2 && argc != 3) {
+	fprintf(stderr, "Usage: readall [-b | -t] file\n");
+	exit(1);
+  }
+  i = 1;
+
+  p = argv[1];
+  if (*p == '-' && *(p + 1) == 'b' && *(p + 2) == '\0') {
+	normal = 0;
+	i++;
+	name = argv[i];
+  }
+  if (*p == '-' && *(p + 1) == 't' && *(p + 2) == '\0') {
+	normal = 0;
+	total = 1;
+	i++;
+	name = argv[i];
+  }
+  fd = open(argv[i], O_RDONLY);
+  if (fd < 0) {
+  	perror(argv[i]);
+	fprintf(stderr, "%s is not readable\n", argv[i]);
+	exit(1);
+  }
+
+  /* Get size of file */
+  if(ioctl(fd, DIOCGETP, &entry) < 0) {
+  	perror("ioctl DIOCGETP");
+  	return 1;
+  }
+  nblocks = div64u(entry.size, BLOCK_SIZE);
+
+  time(&starttime);
+  /* Read the entire file. Try it in large chunks, but if an error
+   * occurs, go to single reads for a while. */
+  while (1) {
+	if(lseek(fd, BLOCK_SIZE * b, SEEK_SET) < 0) {
+		perror("lseek");
+		return 1;
+	}
+	s = read(fd, a, BLOCK_SIZE * chunk);
+	if (s == BLOCK_SIZE * chunk) {
+		/* Normal read, no errors. */
+		b += chunk;
+		goodies++;
+		if (chunk == 1) {
+			if (goodies >= RESUME && b % DIVISOR == 0)
+				chunk = CHUNK;
+		}
+  		if(b % DIVISOR == 0 && !normal) {
+  			prettyprogress(b, nblocks, starttime);
+  		}
+	} else if (s < 0) {
+		/* I/O error. */
+		if (chunk != 1) {
+			chunk = 1;	/* regress to single block mode */
+			continue;
+		}
+		if (errors == STORE) {
+			fprintf(stderr,
+			 "\n%ld Bad blocks is too many.  Exiting\n",
+				errors);
+			exit(1);
+		}
+		rotten[(int) errors] = b;	/* log the error */
+		b += chunk;
+		errors++;
+	} else {
+		/* End of file. */
+		b += s / BLOCK_SIZE;
+		if (normal) {
+			output(b);
+			fprintf(stderr, "\n");
+		} else fprintf(stderr, "\r%*s\n", -WIDTH, "Done scanning.");
+		if (total) printf("%8ld\n", b);
+		if ((errors == 0) || total) exit(0);
+		badprinted = 0;
+		if (normal) printf("Summary of bad blocks\n");
+
+		/* Print summary of bad blocks, possibly as shell script. */
+		for (i = 0; i < errors; i++) {
+			if (normal == 0 && badprinted == 0) {
+				printf("badblocks %s ", name);
+				badprinted = 1;
+			}
+			printf("%6ld ", rotten[i]);
+			if ((i + 1) % 7 == 0) {
+				printf("\n");
+				badprinted = 0;
+			}
+		}
+		printf("\n");
+		exit(0);
+	}
+	if (normal && b % DIVISOR == 0) output(b);
+  }
+}
+
+static void output(blocks_read)
+long blocks_read;
+{
+  fprintf(stderr, "%8ld blocks read, %5ld errors\r", blocks_read, errors);
+  fflush(stderr);
+}
Index: /trunk/minix/commands/simple/readfs.c
===================================================================
--- /trunk/minix/commands/simple/readfs.c	(revision 9)
+++ /trunk/minix/commands/simple/readfs.c	(revision 9)
@@ -0,0 +1,601 @@
+/* readfs - read a MINIX file system	Author: Paul Polderman */
+
+/* Command: readfs - read and extract a MINIX filesystem.
+ *
+ * Syntax:  readfs [-li] block-special [directory]
+ *
+ * Flags: -l:	Extract files and dirs and produce a mkfs-listing on stdout
+ * 	  -i:	Information only: give the listing, but do not extract files.
+ *	  -d:	Don't extract regular files, just the skeleton please.
+ *
+ * Examples: readfs /dev/fd1		# extract all files from /dev/fd1.
+ * 	     readfs -i /dev/hd2		# see what's on /dev/hd2.
+ * 	     readfs -l /dev/at0 rootfs	# extract and list the filesystem
+ * 					# of /dev/at0 and put the tree
+ * 					# in the directory `rootfs'.
+ *
+ *   Readfs reads a MINIX filesystem and extracts recursively all directories
+ * and files, and (optionally) produces a mkfs-listing of them on stdout.
+ * The root directory contents are placed in the current directory, unless
+ * a directory is given as argument, in which case the contents are put there.
+ * Readfs tries to restore the attributes (mode/uid/gid/time) of the files
+ * extracted to those of the original files.
+ * Special files are created as ordinary files, but the mkfs-listing
+ * enables mkfs to restore them to original.
+ */
+
+#include <sys/types.h>
+#include <sys/dir.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <utime.h>
+#include <dirent.h>
+
+#define BLOCK_SIZE _STATIC_BLOCK_SIZE
+
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include "../../servers/fs/const.h"
+#include "../../servers/fs/type.h"
+#include "../../servers/fs/buf.h"
+#include "../../servers/fs/super.h"
+
+#undef printf			/* Definition used only in the kernel */
+#include <stdio.h>
+
+/* Compile with -I/user0/ast/minix
+ * (i.e. the directory containing the MINIX system sources)
+ *
+ *	Author: Paul Polderman (polder@cs.vu.nl) April 1987
+ */
+
+char verbose = 0;		/* give a mkfs-listing of the filesystem */
+ /* And extracts its contents. */
+char noaction = 0;		/* just give a mkfs-listing, do not extract
+			 * files. */
+char nofiles = 0;		/* only extract the skeleton FS structure */
+
+struct super_block sb;
+char pathname[1024];
+int inodes_per_block;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void get_flags, (char *flags));
+_PROTOTYPE(void readfs, (char *special_file, char *directory));
+_PROTOTYPE(int get_inode, (int fd, Ino_t inum, d1_inode * ip));
+_PROTOTYPE(void dump_dir, (int special, d1_inode * ip, char *directory));
+_PROTOTYPE(int dump_file, (int special, d1_inode * ip, char *filename));
+_PROTOTYPE(int get_fileblock, (int special, d1_inode * ip, block_t b, struct buf * bp));
+_PROTOTYPE(int get_block, (int fd, block_t block, struct buf * bp, int type));
+_PROTOTYPE(int get_rawblock, (int special, block_t blockno, char *bufp));
+_PROTOTYPE(void restore, (char *name, d1_inode * ip));
+_PROTOTYPE(void show_info, (char *name, d1_inode * ip, char *path));
+_PROTOTYPE(void do_indent, (int i));
+_PROTOTYPE(int Mkdir, (char *directory));
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  switch (argc) {
+      case 2:
+	pathname[0] = '\0';
+	readfs(argv[1], pathname);
+	break;
+      case 3:
+	if (argv[1][0] == '-') {
+		get_flags(&argv[1][1]);
+		pathname[0] = '\0';
+		readfs(argv[2], pathname);
+	} else {
+		strcpy(pathname, argv[2]);
+		readfs(argv[1], pathname);
+	}
+	break;
+      case 4:
+	if (argv[1][0] == '-') {
+		get_flags(&argv[1][1]);
+		strcpy(pathname, argv[3]);
+		readfs(argv[2], pathname);
+		break;
+	}			/* else fall through .. */
+      default:
+	fprintf(stderr, "Usage: %s [-li] <special> [dirname]\n", argv[0]);
+	exit(1);
+  }
+  return(0);
+}
+
+void get_flags(flags)
+register char *flags;
+{
+  while (*flags) {
+	switch (*flags) {
+	    case 'L':
+	    case 'l':	verbose = 1;	break;
+	    case 'I':
+	    case 'i':
+		noaction = 1;
+		verbose = 1;
+		break;
+	    case 'D':
+	    case 'd':	nofiles = 1;	break;
+	    default:
+		fprintf(stderr, "Bad flag: %c\n", *flags);
+		break;
+	}
+	flags++;
+  }
+}
+
+#define	zone_shift	(sb.s_log_zone_size)	/* zone to block ratio */
+
+void readfs(special_file, directory)
+char *special_file, *directory;
+/* Readfs: opens the given special file (with MINIX filesystem),
+ * and extracts its contents into the given directory.
+ */
+{
+  d1_inode root_inode;
+  int special, magic;
+  off_t super_b;
+
+  umask(0);
+
+  /* Open the special file */
+  if ((special = open(special_file, O_RDONLY)) < 0) {
+	fprintf(stderr, "cannot open %s\n", special_file);
+	return;
+  }
+
+  /* Read the superblock */
+  super_b = (off_t) 1 *(off_t) BLOCK_SIZE;
+  if (lseek(special, super_b, SEEK_SET) != super_b) {
+	fprintf(stderr, "cannot seek to superblock\n");
+	return;
+  }
+  if (read(special, (char *) &sb, sizeof(struct super_block))
+      != sizeof(struct super_block)) {
+	fprintf(stderr, "cannot read superblock\n");
+	return;
+  }
+
+  /* The number of inodes in a block differs in V1 and V2. */
+  magic = sb.s_magic;
+  if (magic == SUPER_MAGIC || magic == SUPER_REV) {
+	inodes_per_block = V1_INODES_PER_BLOCK;
+  } else {
+	inodes_per_block = V2_INODES_PER_BLOCK(BLOCK_SIZE);
+  }
+
+  /* Is it really a MINIX filesystem ? */
+  if (magic != SUPER_MAGIC && magic != SUPER_V2) {
+	fprintf(stderr, "%s is not a valid MINIX filesystem\n", special_file);
+	return;
+  }
+
+  /* Fetch the inode of the root directory */
+  if (get_inode(special, (ino_t) ROOT_INODE, &root_inode) < 0) {
+	fprintf(stderr, "cannot get inode of root directory\n");
+	return;
+  }
+
+  /* Print number of blocks and inodes */
+  if (verbose) printf("boot\n%ld %d\n",
+	       (block_t) sb.s_nzones << zone_shift, sb.s_ninodes);
+
+  /* Extract (recursively) the root directory */
+  dump_dir(special, &root_inode, directory);
+}
+
+/* Different type of blocks:	(used in routine get_block for caching) */
+
+#define	B_INODE		0	/* Cache #0 is the inode cache */
+#define	B_INDIRECT	1	/* Cache #1 is the (dbl) indirect block cache */
+#define	B_DATA		2	/* No cache for data blocks (only read once) */
+
+int get_inode(fd, inum, ip)
+int fd;
+ino_t inum;
+d1_inode *ip;
+
+/* Get inode `inum' from the MINIX filesystem. (Uses the inode-cache) */
+{
+  struct buf bp;
+  block_t block;
+  block_t ino_block;
+  unsigned short ino_offset;
+
+  /* Calculate start of i-list */
+  block = 1 + 1 + sb.s_imap_blocks + sb.s_zmap_blocks;
+
+  /* Calculate block with inode inum */
+  ino_block = ((inum - 1) / inodes_per_block);
+  ino_offset = ((inum - 1) % inodes_per_block);
+  block += ino_block;
+
+  /* Fetch the block */
+  if (get_block(fd, block, &bp, B_INODE) == 0) {
+	memcpy((void *) ip, (void *) &bp.b_v1_ino[ino_offset], sizeof(d1_inode));
+	return(0);
+  }
+
+  /* Oeps, foutje .. */
+  fprintf(stderr, "cannot find inode %d\n", inum);
+  return(-1);
+}
+
+static int indent = 0;		/* current indent (used for mkfs-listing) */
+
+void dump_dir(special, ip, directory)
+int special;
+d1_inode *ip;
+char *directory;
+/* Make the given directory (if non-NULL),
+ * and recursively extract its contents.
+ */
+{
+  register struct direct *dp;
+  register int n_entries;
+  register char *name;
+  block_t b = 0;
+  d1_inode dip;
+  struct buf bp;
+
+  if (verbose) {
+	show_info(directory, ip, "");
+	indent++;
+  }
+  if (!noaction && *directory) {
+	/* Try to make the directory if not already there */
+	if (Mkdir(directory) != 0 || chdir(directory) < 0) {
+		fprintf(stderr, "Mkdir %s failed\n", directory);
+		return;
+	}
+  }
+  for (name = directory; *name; name++)	/* Find end of pathname */
+	;
+  *name++ = '/';		/* Add trailing slash */
+
+  n_entries = (int) (ip->d1_size / (off_t) sizeof(struct direct));
+  while (n_entries > 0) {
+
+	/* Read next block of the directory */
+	if (get_fileblock(special, ip, b, &bp) < 0) return;
+	dp = &bp.b_dir[0];
+	if (b++ == (block_t) 0) {
+		dp += 2;	/* Skip "." and ".." */
+		n_entries -= 2;
+	}
+
+	/* Extract the files/directories listed in the block */
+	while (n_entries-- > 0 && dp < &bp.b_dir[NR_DIR_ENTRIES(BLOCK_SIZE)]) {
+		if (dp->d_ino != (ino_t) 0) {
+			if (get_inode(special, dp->d_ino, &dip) < 0) {
+				/* Bad luck */
+				dp++;
+				continue;
+			}
+
+			/* Add new pathname-component to `pathname'. */
+			strncpy(name, dp->d_name, (size_t) NAME_MAX);
+			name[NAME_MAX] = '\0';
+
+			/* Call the right routine */
+			if ((dip.d1_mode & I_TYPE) == I_DIRECTORY)
+				dump_dir(special, &dip, name);
+			else
+				dump_file(special, &dip, name);
+		}
+		dp++;		/* Next entry, please. */
+	}
+  }
+  *--name = '\0';		/* Restore `pathname' to what it was. */
+  if (!noaction && *directory) {
+	chdir("..");		/* Go back up. */
+	restore(directory, ip);	/* Restore mode/owner/accesstime */
+  }
+  if (verbose) {
+	do_indent(--indent);	/* Let mkfs know we are done */
+	printf("$\n");		/* with this directory. */
+  }
+}
+
+int dump_file(special, ip, filename)
+int special;
+d1_inode *ip;
+char *filename;
+/* Extract given filename from the MINIX-filesystem,
+ * and store it on the local filesystem.
+ */
+{
+  int file;
+  block_t b = 0;
+  struct buf bp;
+  off_t size;
+
+  if (nofiles && (ip->d1_mode & I_TYPE) == I_REGULAR) return(0);
+
+  if (verbose) show_info(filename, ip, pathname);
+
+  if (noaction) return(0);
+
+  if (access(filename, 0) == 0) {
+	/* Should not happen, but just in case .. */
+	fprintf(stderr, "Will not create %s: file exists\n", filename);
+	return(-1);
+  }
+  if ((file = creat(filename, (ip->d1_mode & ALL_MODES))) < 0) {
+	fprintf(stderr, "cannot create %s\n", filename);
+	return(-1);
+  }
+
+  /* Don't try to extract /dev/hd0 */
+  if ((ip->d1_mode & I_TYPE) == I_REGULAR) {
+	size = ip->d1_size;
+	while (size > (off_t) 0) {
+		/* Get next block of file */
+		if (get_fileblock(special, ip, b++, &bp) < 0) {
+			close(file);
+			return(-1);
+		}
+
+		/* Write it to the file */
+		if (size > (off_t) BLOCK_SIZE)
+			write(file, bp.b_data, BLOCK_SIZE);
+		else
+			write(file, bp.b_data, (int) size);
+
+		size -= (off_t) BLOCK_SIZE;
+	}
+  }
+  close(file);
+  restore(filename, ip);	/* Restore mode/owner/filetimes */
+  return(0);
+}
+
+int get_fileblock(special, ip, b, bp)
+int special;
+d1_inode *ip;
+block_t b;
+struct buf *bp;
+/* Read the `b'-th block from the file whose inode is `ip'. */
+{
+  zone_t zone, ind_zone;
+  block_t z, zone_index;
+  int r;
+
+  /* Calculate zone in which the datablock number is contained */
+  zone = (zone_t) (b >> zone_shift);
+
+  /* Calculate index of the block number in the zone */
+  zone_index = b - ((block_t) zone << zone_shift);
+
+  /* Go get the zone */
+  if (zone < (zone_t) V1_NR_DZONES) {	/* direct block */
+	zone = ip->d1_zone[(int) zone];
+	z = ((block_t) zone << zone_shift) + zone_index;
+	r = get_block(special, z, bp, B_DATA);
+	return(r);
+  }
+
+  /* The zone is not a direct one */
+  zone -= (zone_t) V1_NR_DZONES;
+
+  /* Is it single indirect ? */
+  if (zone < (zone_t) V1_INDIRECTS) {	/* single indirect block */
+	ind_zone = ip->d1_zone[V1_NR_DZONES];
+  } else {			/* double indirect block */
+	/* Fetch the double indirect block */
+	ind_zone = ip->d1_zone[V1_NR_DZONES + 1];
+	z = (block_t) ind_zone << zone_shift;
+	r = get_block(special, z, bp, B_INDIRECT);
+	if (r < 0) return(r);
+
+	/* Extract the indirect zone number from it */
+	zone -= (zone_t) V1_INDIRECTS;
+
+	/* The next line assumes a V1 file system only! */
+	ind_zone = bp->b_v1_ind[(int) (zone / V1_INDIRECTS)];
+	zone %= (zone_t) V1_INDIRECTS;
+  }
+
+  /* Extract the datablock number from the indirect zone */
+  z = (block_t) ind_zone << zone_shift;
+  r = get_block(special, z, bp, B_INDIRECT);
+  if (r < 0) return(r);
+
+  /* The next line assumes a V1 file system only! */
+  zone = bp->b_v1_ind[(int) zone];
+
+  /* Calculate datablock number to be fetched */
+  z = ((block_t) zone << zone_shift) + zone_index;
+  r = get_block(special, z, bp, B_DATA);
+  return(r);
+}
+
+/* The following routines simulate a LRU block cache.
+ *
+ * Definition of a cache block:
+ */
+
+struct cache_block {
+  block_t b_block;		/* block number of block */
+  long b_access;		/* counter value of last access */
+  char b_buf[BLOCK_SIZE];	/* buffer for block */
+};
+
+#define	NR_CACHES	2	/* total number of caches */
+#define	NR_CBLOCKS	5	/* number of blocks in a cache */
+
+static struct cache_block cache[NR_CACHES][NR_CBLOCKS];
+static long counter = 0L;	/* Counter used as a sense of time. */
+ /* Incremented after each cache operation. */
+
+int get_block(fd, block, bp, type)
+int fd;
+block_t block;
+struct buf *bp;
+int type;
+/* Get the requested block from the device with filedescriptor fd.
+ * If it is in the cache, no (floppy-) disk access is needed,
+ * if not, allocate a cache block and read the block into it.
+ */
+{
+  register int i;
+  register struct cache_block *cache_p, *cp;
+
+  if (block == (block_t) NO_ZONE) {
+	/* Should never happen in a good filesystem. */
+	fprintf(stderr, "get_block: NO_ZONE requested !\n");
+	return(-1);
+  }
+  if (type < 0 || type >= NR_CACHES)	/* No cache for this type */
+	return(get_rawblock(fd, block, (char *) bp));
+
+  cache_p = cache[type];
+  cp = (struct cache_block *) 0;
+
+  /* First find out if block requested is in the cache */
+  for (i = 0; i < NR_CBLOCKS; i++) {
+	if (cache_p[i].b_block == block) {	/* found right block */
+		cp = &cache_p[i];
+		break;
+	}
+  }
+
+  if (cp == (struct cache_block *) 0) {	/* block is not in cache */
+	cp = cache_p;		/* go find oldest buffer */
+	for (i = 0; i < NR_CBLOCKS; i++) {
+		if (cache_p[i].b_access < cp->b_access) cp = &cache_p[i];
+	}
+
+	/* Fill the buffer with the right block */
+	if (get_rawblock(fd, block, cp->b_buf) < 0) return(-1);
+  }
+
+  /* Update/store last access counter */
+  cp->b_access = ++counter;
+  cp->b_block = block;
+  memcpy((void *) bp, (void *) cp->b_buf, BLOCK_SIZE);
+  return(0);
+}
+
+int get_rawblock(special, blockno, bufp)
+int special;
+block_t blockno;
+char *bufp;
+/* Read a block from the disk. */
+{
+  off_t pos;
+
+  /* Calculate the position of the block on the disk */
+  pos = (off_t) blockno *(off_t) BLOCK_SIZE;
+
+  /* Read the block from the disk */
+  if (lseek(special, pos, SEEK_SET) == pos
+      && read(special, bufp, BLOCK_SIZE) == BLOCK_SIZE)
+	return(0);
+
+  /* Should never get here .. */
+  fprintf(stderr, "read block %d failed\n", blockno);
+  return(-1);
+}
+
+void restore(name, ip)
+char *name;
+d1_inode *ip;
+/* Restores given file's attributes.
+ * `ip' contains the attributes of the file on the MINIX filesystem,
+ * `name' is the filename of the extracted file on the local filesystem.
+ */
+{
+  long ttime[2];
+
+  chown(name, ip->d1_uid, ip->d1_gid);	/* Fails if not superuser */
+  chmod(name, (ip->d1_mode & ALL_MODES));
+  ttime[0] = ttime[1] = ip->d1_mtime;
+  utime(name, (struct utimbuf *) ttime);
+}
+
+/* Characters to use as prefix to `mkfs' mode field */
+
+static char special_chars[] = {
+		       '-',	/* I_REGULAR */
+		       'c',	/* I_CHAR_SPECIAL */
+		       'd',	/* I_DIRECTORY */
+		       'b'	/* I_BLOCK_SPECIAL */
+};
+
+void show_info(name, ip, path)
+char *name;
+d1_inode *ip;
+char *path;
+/* Show information about the given file/dir in `mkfs'-format */
+{
+  char c1, c2, c3;
+
+  c1 = special_chars[(ip->d1_mode >> 13) & 03];
+  c2 = ((ip->d1_mode & ALL_MODES & ~RWX_MODES) == I_SET_UID_BIT) ? 'u' : '-';
+  c3 = ((ip->d1_mode & ALL_MODES & ~RWX_MODES) == I_SET_GID_BIT) ? 'g' : '-';
+
+  if (*name) {
+	do_indent(indent);
+	printf("%-14s ", name);
+  }
+  printf("%c%c%c%03o %d %d", c1, c2, c3,
+         (ip->d1_mode & RWX_MODES), ip->d1_uid, ip->d1_gid);
+
+  switch (ip->d1_mode & I_TYPE) {
+      case I_DIRECTORY:
+	break;
+      case I_CHAR_SPECIAL:	/* Print major and minor dev numbers */
+	printf(" %d %d", (ip->d1_zone[0] >> MAJOR) & 0377,
+	       (ip->d1_zone[0] >> MINOR) & 0377);
+	break;
+      case I_BLOCK_SPECIAL:	/* Print major and minor dev numbers */
+	printf(" %d %d", (ip->d1_zone[0] >> MAJOR) & 0377,
+	       (ip->d1_zone[0] >> MINOR) & 0377);
+	/* Also print the number of blocks on the device */
+	printf(" %ld", (ip->d1_size / (off_t) BLOCK_SIZE));
+	break;
+      default:			/* Just print the pathname */
+	printf(" %s", path);
+	break;
+  }
+  putchar('\n');
+}
+
+#define	INDENT_SIZE	4
+
+void do_indent(i)
+int i;
+{
+  i *= INDENT_SIZE;
+  while (i-- > 0) putchar(' ');
+}
+
+int Mkdir(directory)
+char *directory;
+/* Make a directory, return exit status.
+ * This routine is not necessary on systems that
+ * have a system call to make directories.
+ */
+{
+  int pid, status;
+
+  if ((pid = fork()) == 0) {
+	execl("/bin/Mkdir", "Mkdir", directory, (char *) 0);
+	execl("/usr/bin/Mkdir", "Mkdir", directory, (char *) 0);
+	exit(1);
+  } else if (pid < 0)
+	return(-1);
+  while (wait(&status) != pid);
+  return(status);
+}
Index: /trunk/minix/commands/simple/remsync.c
===================================================================
--- /trunk/minix/commands/simple/remsync.c	(revision 9)
+++ /trunk/minix/commands/simple/remsync.c	(revision 9)
@@ -0,0 +1,1551 @@
+/*	remsync 1.5 - remotely synchronize file trees	Author: Kees J. Bot
+ *								10 Jun 1994
+ */
+#define nil 0
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <time.h>
+#include <utime.h>
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+
+#ifndef major
+#define major(dev)	((int) ((dev) >> 8))
+#define minor(dev)	((int) ((dev) & 0xFF))
+#endif
+
+#ifndef S_ISLNK
+/* There were no symlinks in medieval times. */
+#define S_ISLNK(mode)			(0)
+#define lstat				stat
+#define symlink(path1, path2)		(errno= ENOSYS, -1)
+#define readlink(path, buf, len)	(errno= ENOSYS, -1)
+#endif
+
+int sflag;		/* Make state file. */
+int dflag;		/* Make list of differences. */
+int uflag;		/* Only update files with newer versions. */
+int xflag;		/* Do not cross device boundaries. */
+int Dflag;		/* Debug: Readable differences, no file contents. */
+int vflag;		/* Verbose. */
+
+#define NO_DEVICE	(-1)
+dev_t xdev= NO_DEVICE;	/* The device that you should stay within. */
+
+int excode= 0;		/* Exit(excode); */
+
+#define BASE_INDENT	2	/* State file basic indent. */
+
+void report(const char *label)
+{
+	fprintf(stderr, "remsync: %s: %s\n", label, strerror(errno));
+	excode= 1;
+}
+
+void fatal(const char *label)
+{
+	report(label);
+	exit(1);
+}
+
+void *allocate(void *mem, size_t size)
+{
+	if ((mem= mem == nil ? malloc(size) : realloc(mem, size)) == nil) {
+		fprintf(stderr, "remsync: Out of memory: %s\n",
+			strerror(errno));
+		exit(1);
+	}
+	return mem;
+}
+
+void deallocate(void *mem)
+{
+	if (mem != nil) free(mem);
+}
+
+/* One needs to slowly forget two sets of objects: for the code that reads
+ * the state file, and for the code that traverses trees.
+ */
+int keep;
+#define KEEP_STATE	0
+#define KEEP_TRAVERSE	1
+
+void forget(void *mem)
+/* Some objects must be deleted in time, but not just yet. */
+{
+	static void *death_row[2][50];
+	static void **dp[2]= { death_row[0], death_row[1] };
+
+	deallocate(*dp[keep]);
+	*dp[keep]++= mem;
+	if (dp[keep] == arraylimit(death_row[keep])) dp[keep]= death_row[keep];
+}
+
+char *copystr(const char *s)
+{
+	char *c= allocate(nil, (strlen(s) + 1) * sizeof(c[0]));
+	strcpy(c, s);
+	return c;
+}
+
+typedef struct pathname {
+	char		*path;	/* The actual pathname. */
+	size_t		idx;	/* Index for the terminating null byte. */
+	size_t		lim;	/* Actual length of the path array. */
+} pathname_t;
+
+void path_init(pathname_t *pp)
+/* Initialize a pathname to the null string. */
+{
+	pp->path= allocate(nil, (pp->lim= 16) * sizeof(pp->path[0]));
+	pp->path[pp->idx= 0]= 0;
+}
+
+void path_add(pathname_t *pp, const char *name)
+/* Add a component to a pathname. */
+{
+	size_t lim;
+	char *p;
+	int slash;
+
+	lim= pp->idx + strlen(name) + 2;
+
+	if (lim > pp->lim) {
+		pp->lim= lim + lim/2;	/* add an extra 50% growing space. */
+		pp->path= allocate(pp->path, pp->lim * sizeof(pp->path[0]));
+	}
+
+	p= pp->path + pp->idx;
+	slash= (pp->idx > 0);
+	if (pp->idx == 1 && p[-1] == '/') p--;
+
+	while (*name != 0) {
+		if (*name == '/') {
+			slash= 1;
+		} else {
+			if (slash) { *p++ = '/'; slash= 0; }
+			*p++= *name;
+		}
+		name++;
+	}
+	if (slash && p == pp->path) *p++= '/';
+	*p = 0;
+	pp->idx= p - pp->path;
+}
+
+void path_trunc(pathname_t *pp, size_t didx)
+/* Delete part of a pathname to a remembered length. */
+{
+	pp->path[pp->idx= didx]= 0;
+}
+
+#if kept_for_comments_only
+
+const char *path_name(const pathname_t *pp)
+/* Return the actual name as a char array. */
+{
+	return pp->path;
+}
+
+size_t path_length(const pathname_t *pp)
+/* The length of the pathname. */
+{
+	return pp->idx;
+}
+
+void path_drop(pathname_t *pp)
+/* Release the storage occupied by the pathname. */
+{
+	free(pp->path);
+}
+#endif
+
+#define path_name(pp)		((const char *) (pp)->path)
+#define path_length(pp)		((pp)->idx)
+#define path_drop(pp)		free((void *) (pp)->path)
+
+typedef struct namelist {	/* Obviously a list of names. */
+	struct namelist	*next;
+	char		*name;
+} namelist_t;
+
+char *rdlink(const char *link, off_t size)
+/* Look where "link" points. */
+{
+	static char *path= nil;
+	static size_t len= 0;
+	size_t n;
+
+	if (len <= size) {
+		path= allocate(path, (len= size * 2) * sizeof(path[0]));
+	}
+	if ((n= readlink(link, path, len)) == -1) return nil;
+	path[n]= 0;
+	return path;
+}
+
+void sort(namelist_t **anl)
+/* A stable mergesort disguised as line noise.  Must be called like this:
+ *	if (L!=nil && L->next!=nil) sort(&L);
+ */
+{
+	/* static */ namelist_t *nl1, **mid;  /* Need not be local */
+	namelist_t *nl2;
+
+	nl1= *(mid= &(*anl)->next);
+	do {
+		if ((nl1= nl1->next) == nil) break;
+		mid= &(*mid)->next;
+	} while ((nl1= nl1->next) != nil);
+
+	nl2= *mid;
+	*mid= nil;
+
+	if ((*anl)->next != nil) sort(anl);
+	if (nl2->next != nil) sort(&nl2);
+
+	nl1= *anl;
+	for (;;) {
+		if (strcmp(nl1->name, nl2->name)<=0) {
+			if ((nl1= *(anl= &nl1->next)) == nil) {
+				*anl= nl2;
+				break;
+			}
+		} else {
+			*anl= nl2;
+			nl2= *(anl= &nl2->next);
+			*anl= nl1;
+			if (nl2 == nil) break;
+		}
+	}
+}
+
+namelist_t *collect(const char *dir)
+/* Return a sorted list of directory entries.  Returns null with errno != 0
+ * on error.
+ */
+{
+	namelist_t *names, **pn= &names;
+	DIR *dp;
+	struct dirent *entry;
+
+	if ((dp= opendir(dir)) == nil) return nil;
+
+	while ((entry= readdir(dp)) != nil) {
+		if (entry->d_name[0] == '.'
+			&& (entry->d_name[1] == 0
+				|| (entry->d_name[1] == '.'
+					&& entry->d_name[2] == 0))) {
+			continue;
+		}
+		*pn= allocate(nil, sizeof(**pn));
+		(*pn)->name= copystr(entry->d_name);
+		pn= &(*pn)->next;
+	}
+	closedir(dp);
+	*pn= nil;
+	errno= 0;
+	if (names != nil && names->next != nil) sort(&names);
+	return names;
+}
+
+char *pop_name(namelist_t **names)
+/* Return one name of a name list. */
+{
+	char *name;
+	namelist_t *junk;
+
+	junk= *names;
+	*names= junk->next;
+	name= junk->name;
+	deallocate(junk);
+	forget(name);
+	return name;
+}
+
+typedef enum filetype {		/* The files we know about. */
+	F_DIR,
+	F_FILE,
+	F_BLK,
+	F_CHR,
+	F_PIPE,
+	F_LINK
+} filetype_t;
+
+typedef struct entry {		/* One file. */
+	int		depth;		/* Depth in directory tree. */
+	const char	*name;		/* Name of entry. */
+	const char	*path;		/* Path name. */
+	int		ignore;		/* Ignore this entry (errno number.) */
+	unsigned long	fake_ino;	/* Fake inode number for hard links. */
+	int		linked;		/* Is the file hard linked? */
+	int		lastlink;	/* Is it the last link? */
+	char		*link;		/* Where a (sym)link points to. */
+	filetype_t	type;
+	mode_t		mode;		/* Not unlike those in struct stat. */
+	uid_t		uid;
+	gid_t		gid;
+	off_t		size;
+	time_t		mtime;
+	dev_t		rdev;
+} entry_t;
+
+void linked(entry_t *entry, struct stat *stp)
+/* Return an "inode number" if a file could have links (link count > 1).
+ * Also return a path to the first link if you see the file again.
+ */
+{
+	static unsigned long new_fake_ino= 0;
+	static struct links {
+		struct links	*next;
+		char		*path;
+		ino_t		ino;
+		dev_t		dev;
+		nlink_t		nlink;
+		unsigned long	fake_ino;
+	} *links[1024];
+	struct links **plp, *lp;
+
+	entry->linked= entry->lastlink= 0;
+	entry->fake_ino= 0;
+	entry->link= nil;
+
+	if (S_ISDIR(stp->st_mode) || stp->st_nlink < 2) return;
+
+	plp= &links[stp->st_ino % arraysize(links)];
+	while ((lp= *plp) != nil && (lp->ino != stp->st_ino
+				|| lp->dev != stp->st_dev)) plp= &lp->next;
+
+	if (lp == nil) {
+		/* New file, store it with a new fake inode number. */
+		*plp= lp= allocate(nil, sizeof(*lp));
+		lp->next= nil;
+		lp->path= copystr(entry->path);
+		lp->ino= stp->st_ino;
+		lp->dev= stp->st_dev;
+		lp->nlink= stp->st_nlink;
+		lp->fake_ino= ++new_fake_ino;
+	} else {
+		entry->link= lp->path;
+		entry->linked= 1;
+	}
+	entry->fake_ino= lp->fake_ino;
+
+	if (--lp->nlink == 0) {
+		/* No need to remember this one, no more links coming. */
+		*plp= lp->next;
+		forget(lp->path);
+		deallocate(lp);
+		entry->lastlink= 1;
+	}
+}
+
+char *tree;		/* Tree to work on. */
+FILE *statefp;		/* State file. */
+char *state_file;
+FILE *difffp;		/* File of differences. */
+char *diff_file;
+
+entry_t *traverse(void)
+/* Get one name from the directory tree. */
+{
+	static int depth;
+	static pathname_t path;
+	static entry_t entry;
+	static namelist_t **entries;
+	static size_t *trunc;
+	static size_t deep;
+	static namelist_t *newentries;
+	struct stat st;
+
+recurse:
+	keep= KEEP_TRAVERSE;
+
+	if (deep == 0) {
+		/* Initialize for the root of the tree. */
+		path_init(&path);
+		path_add(&path, tree);
+		entries= allocate(nil, 1 * sizeof(entries[0]));
+		entries[0]= allocate(nil, sizeof(*entries[0]));
+		entries[0]->next= nil;
+		entries[0]->name= copystr("/");
+		trunc= allocate(nil, 1 * sizeof(trunc[0]));
+		trunc[0]= path_length(&path);
+		deep= 1;
+	} else
+	if (newentries != nil) {
+		/* Last entry was a directory, need to go down. */
+		if (entry.ignore) {
+			/* Ouch, it is to be ignored! */
+			while (newentries != nil) (void) pop_name(&newentries);
+			goto recurse;
+		}
+		if (++depth == deep) {
+			deep++;
+			entries= allocate(entries, deep * sizeof(entries[0]));
+			trunc= allocate(trunc, deep * sizeof(trunc[0]));
+		}
+		entries[depth]= newentries;
+		newentries= nil;
+		trunc[depth]= path_length(&path);
+	} else {
+		/* Pop up out of emptied directories. */
+		while (entries[depth] == nil) {
+			if (depth == 0) return nil;	/* Back at the root. */
+
+			/* Go up one level. */
+			depth--;
+		}
+	}
+	entry.name= pop_name(&entries[depth]);
+	path_trunc(&path, trunc[depth]);
+	path_add(&path, entry.name);
+	if (depth == 0) {
+		entry.path= "/";
+	} else {
+		entry.path= path_name(&path) + trunc[0];
+		if (entry.path[0] == '/') entry.path++;
+	}
+	entry.depth= depth;
+	entry.ignore= 0;
+
+	if (lstat(path_name(&path), &st) < 0) {
+		if (depth == 0 || errno != ENOENT) {
+			/* Something wrong with this entry, complain about
+			 * it and ignore it further.
+			 */
+			entry.ignore= errno;
+			report(path_name(&path));
+			return &entry;
+		} else {
+			/* Entry strangely nonexistent; simply continue. */
+			goto recurse;
+		}
+	}
+
+	/* Don't cross mountpoints if -x is set. */
+	if (xflag) {
+		if (xdev == NO_DEVICE) xdev= st.st_dev;
+		if (st.st_dev != xdev) {
+			/* Ignore the mountpoint. */
+			entry.ignore= EXDEV;
+			return &entry;
+		}
+	}
+
+	entry.mode= st.st_mode & 07777;
+	entry.uid= st.st_uid;
+	entry.gid= st.st_gid;
+	entry.size= st.st_size;
+	entry.mtime= st.st_mtime;
+	entry.rdev= st.st_rdev;
+
+	linked(&entry, &st);
+
+	if (S_ISDIR(st.st_mode)) {
+		/* A directory. */
+		entry.type= F_DIR;
+
+		/* Gather directory entries for the next traverse. */
+		if ((newentries= collect(path_name(&path))) == nil
+							&& errno != 0) {
+			entry.ignore= errno;
+			report(path_name(&path));
+		}
+	} else
+	if (S_ISREG(st.st_mode)) {
+		/* A plain file. */
+		entry.type= F_FILE;
+	} else
+	if (S_ISBLK(st.st_mode)) {
+		/* A block special file. */
+		entry.type= F_BLK;
+	} else
+	if (S_ISCHR(st.st_mode)) {
+		/* A character special file. */
+		entry.type= F_CHR;
+	} else
+	if (S_ISFIFO(st.st_mode)) {
+		/* A named pipe. */
+		entry.type= F_PIPE;
+	} else
+	if (S_ISLNK(st.st_mode)) {
+		/* A symbolic link. */
+		entry.type= F_LINK;
+		if ((entry.link= rdlink(path_name(&path), st.st_size)) == nil) {
+			entry.ignore= errno;
+			report(path_name(&path));
+		}
+	} else {
+		/* Unknown type of file. */
+		entry.ignore= EINVAL;
+	}
+	return &entry;
+}
+
+void checkstate(void)
+{
+	if (ferror(statefp)) fatal(state_file);
+}
+
+void indent(int depth)
+/* Provide indentation to show directory depth. */
+{
+	int n= BASE_INDENT * (depth - 1);
+
+	while (n >= 8) {
+		if (putc('\t', statefp) == EOF) checkstate();
+		n-= 8;
+	}
+	while (n > 0) {
+		if (putc(' ', statefp) == EOF) checkstate();
+		n--;
+	}
+}
+
+int print_name(FILE *fp, const char *name)
+/* Encode a name. */
+{
+	const char *p;
+	int c;
+
+	for (p= name; (c= (unsigned char) *p) != 0; p++) {
+		if (c <= ' ' || c == '\\') {
+			fprintf(fp, "\\%03o", c);
+			if (ferror(fp)) return 0;
+		} else {
+			if (putc(c, fp) == EOF) return 0;
+		}
+	}
+	return 1;
+}
+
+void mkstatefile(void)
+/* Make a state file out of the directory tree. */
+{
+	entry_t *entry;
+
+	while ((entry= traverse()) != nil) {
+		indent(entry->depth);
+		if (!print_name(statefp, entry->name)) checkstate();
+
+		if (entry->ignore) {
+			fprintf(statefp, "\tignore (%s)\n",
+				strerror(entry->ignore));
+			checkstate();
+			continue;
+		}
+
+		switch (entry->type) {
+		case F_DIR:
+			fprintf(statefp, "\td%03o %u %u",
+				(unsigned) entry->mode,
+				(unsigned) entry->uid, (unsigned) entry->gid);
+			break;
+		case F_FILE:
+			fprintf(statefp, "\t%03o %u %u %lu %lu",
+				(unsigned) entry->mode,
+				(unsigned) entry->uid, (unsigned) entry->gid,
+				(unsigned long) entry->size,
+				(unsigned long) entry->mtime);
+			break;
+		case F_BLK:
+		case F_CHR:
+			fprintf(statefp, "\t%c%03o %u %u %x",
+				entry->type == F_BLK ? 'b' : 'c',
+				(unsigned) entry->mode,
+				(unsigned) entry->uid, (unsigned) entry->gid,
+				(unsigned) entry->rdev);
+			break;
+		case F_PIPE:
+			fprintf(statefp, "\tp%03o %u %u",
+				(unsigned) entry->mode,
+				(unsigned) entry->uid, (unsigned) entry->gid);
+			break;
+		case F_LINK:
+			fprintf(statefp, "\t-> ");
+			checkstate();
+			(void) print_name(statefp, entry->link);
+			break;
+		}
+		checkstate();
+		if (entry->fake_ino != 0)
+			fprintf(statefp, " %lu", entry->fake_ino);
+		if (entry->lastlink)
+			fprintf(statefp, " last");
+		if (fputc('\n', statefp) == EOF) checkstate();
+	}
+	fflush(statefp);
+	checkstate();
+}
+
+char *read1line(FILE *fp)
+/* Read one line from a file.  Return null on EOF or error. */
+{
+	static char *line;
+	static size_t len;
+	size_t idx;
+	int c;
+
+	if (len == 0) line= allocate(nil, (len= 16) * sizeof(line[0]));
+
+	idx= 0;
+	while ((c= getc(fp)) != EOF && c != '\n') {
+		if (c < '\t') {
+			/* Control characters are not possible. */
+			fprintf(stderr,
+				"remsync: control character in data file!\n");
+			exit(1);
+		}
+		line[idx++]= c;
+		if (idx == len) {
+			line= allocate(line, (len*= 2) * sizeof(line[0]));
+		}
+	}
+	if (c == EOF) {
+		if (ferror(fp)) return nil;
+		if (idx == 0) return nil;
+	}
+	line[idx]= 0;
+	return line;
+}
+
+void getword(char **pline, char **parg, size_t *plen)
+/* Get one word from a line, interpret octal escapes. */
+{
+	char *line= *pline;
+	char *arg= *parg;
+	size_t len= *plen;
+	int i;
+	int c;
+	size_t idx;
+
+	idx= 0;
+	while ((c= *line) != 0 && c != ' ' && c != '\t') {
+		line++;
+		if (c == '\\') {
+			c= 0;
+			for (i= 0; i < 3; i++) {
+				if ((unsigned) (*line - '0') >= 010) break;
+				c= (c << 3) | (*line - '0');
+				line++;
+			}
+		}
+		arg[idx++]= c;
+		if (idx == len) arg= allocate(arg, (len*= 2) * sizeof(arg[0]));
+	}
+	arg[idx]= 0;
+	*pline= line;
+	*parg= arg;
+	*plen= len;
+}
+
+void splitline(char *line, char ***pargv, size_t *pargc)
+/* Split a line into an array of words. */
+{
+	static char **argv;
+	static size_t *lenv;
+	static size_t len;
+	size_t idx;
+
+	idx= 0;
+	for (;;) {
+		while (*line == ' ' || *line == '\t') line++;
+
+		if (*line == 0) break;
+
+		if (idx == len) {
+			len++;
+			argv= allocate(argv, len * sizeof(argv[0]));
+			lenv= allocate(lenv, len * sizeof(lenv[0]));
+			argv[idx]= allocate(nil, 16 * sizeof(argv[idx][0]));
+			lenv[idx]= 16;
+		}
+		getword(&line, &argv[idx], &lenv[idx]);
+		idx++;
+	}
+	*pargv= argv;
+	*pargc= idx;
+}
+
+int getattributes(entry_t *entry, int argc, char **argv)
+/* Convert state or difference file info into file attributes. */
+{
+	int i;
+	int attr;
+#define A_MODE1		0x01	/* Some of these attributes follow the name */
+#define A_MODE		0x02
+#define	A_OWNER		0x04
+#define A_SIZETIME	0x08
+#define A_DEV		0x10
+#define A_LINK		0x20
+
+	switch (argv[0][0]) {
+	case 'd':
+		/* Directory. */
+		entry->type= F_DIR;
+		attr= A_MODE1 | A_OWNER;
+		break;
+	case 'b':
+		/* Block device. */
+		entry->type= F_BLK;
+		attr= A_MODE1 | A_OWNER | A_DEV;
+		break;
+	case 'c':
+		/* Character device. */
+		entry->type= F_CHR;
+		attr= A_MODE1 | A_OWNER | A_DEV;
+		break;
+	case 'p':
+		/* Named pipe. */
+		entry->type= F_PIPE;
+		attr= A_MODE1 | A_OWNER;
+		break;
+	case '-':
+		/* Symlink. */
+		entry->type= F_LINK;
+		attr= A_LINK;
+		break;
+	default:
+		/* Normal file. */
+		entry->type= F_FILE;
+		attr= A_MODE | A_OWNER | A_SIZETIME;
+	}
+
+	if (attr & (A_MODE | A_MODE1)) {
+		entry->mode= strtoul(argv[0] + (attr & A_MODE1), nil, 010);
+	}
+	i= 1;
+	if (attr & A_OWNER) {
+		if (i + 2 > argc) return 0;
+		entry->uid= strtoul(argv[i++], nil, 10);
+		entry->gid= strtoul(argv[i++], nil, 10);
+	}
+	if (attr & A_SIZETIME) {
+		if (i + 2 > argc) return 0;
+		entry->size= strtoul(argv[i++], nil, 10);
+		entry->mtime= strtoul(argv[i++], nil, 10);
+	}
+	if (attr & A_DEV) {
+		if (i + 1 > argc) return 0;
+		entry->rdev= strtoul(argv[i++], nil, 0x10);
+	}
+	if (attr & A_LINK) {
+		if (i + 1 > argc) return 0;
+		entry->link= argv[i++];
+	}
+	entry->linked= entry->lastlink= 0;
+	if (i < argc) {
+		/* It has a fake inode number, so it is a hard link. */
+		static struct links {	/* List of hard links. */
+			struct links	*next;
+			unsigned long	fake_ino;
+			char		*path;
+		} *links[1024];
+		struct links **plp, *lp;
+		unsigned long fake_ino;
+
+		fake_ino= strtoul(argv[i++], nil, 10);
+
+		plp= &links[fake_ino % arraysize(links)];
+		while ((lp= *plp) != nil && lp->fake_ino != fake_ino)
+			plp= &lp->next;
+
+		if (lp == nil) {
+			/* New link. */
+			*plp= lp= allocate(nil, sizeof(*lp));
+			lp->next= nil;
+			lp->fake_ino= fake_ino;
+			lp->path= copystr(entry->path);
+		} else {
+			/* Linked to. */
+			entry->link= lp->path;
+			entry->linked= 1;
+		}
+
+		if (i < argc) {
+			if (strcmp(argv[i++], "last") != 0) return 0;
+
+			/* Last hard link of a file. */
+			forget(lp->path);
+			*plp= lp->next;
+			deallocate(lp);
+			entry->lastlink= 1;
+		}
+	}
+	if (i != argc) return 0;
+	return 1;
+}
+
+void state_syntax(off_t line)
+{
+	fprintf(stderr, "remsync: %s: syntax error on line %lu\n",
+		state_file, (unsigned long) line);
+	exit(1);
+}
+
+entry_t *readstate(void)
+/* Read one entry from the state file. */
+{
+	static entry_t entry;
+	static pathname_t path;
+	static size_t *trunc;
+	static size_t trunc_len;
+	static base_indent;
+	char *line;
+	char **argv;
+	size_t argc;
+	static off_t lineno;
+	int indent, depth;
+
+recurse:
+	keep= KEEP_STATE;
+
+	if (feof(statefp) || (line= read1line(statefp)) == nil) {
+		checkstate();
+		return nil;
+	}
+	lineno++;
+
+	/* How far is this entry indented? */
+	indent= 0;
+	while (*line != 0) {
+		if (*line == ' ') indent++;
+		else
+		if (*line == '\t') indent= (indent + 8) & ~7;
+		else
+			break;
+		line++;
+	}
+	if (indent > 0 && base_indent == 0) base_indent= indent;
+	depth= (base_indent == 0 ? 0 : indent / base_indent) + 1;
+
+	if (entry.ignore && depth > entry.depth) {
+		/* If the old directory is ignored, then so are its entries. */
+		goto recurse;
+	}
+	entry.depth= depth;
+
+	splitline(line, &argv, &argc);
+	if (argc < 2) state_syntax(lineno);
+
+	if (trunc == nil) {
+		/* The root of the tree, initialize path. */
+		if (argv[0][0] != '/') state_syntax(lineno);
+		path_init(&path);
+		path_add(&path, "/");
+		trunc= allocate(nil, (trunc_len= 16) * sizeof(trunc[0]));
+
+		/* The root has depth 0. */
+		entry.depth= 0;
+		trunc[0]= 0;
+	} else {
+		if (entry.depth > trunc_len) {
+			trunc= allocate(trunc,
+					(trunc_len*= 2) * sizeof(trunc[0]));
+		}
+		path_trunc(&path, trunc[entry.depth - 1]);
+		path_add(&path, argv[0]);
+		trunc[entry.depth]= path_length(&path);
+	}
+
+	entry.path= path_name(&path);
+	entry.name= argv[0];
+	entry.link= nil;
+	if ((entry.ignore= strcmp(argv[1], "ignore") == 0)) {
+		return &entry;
+	}
+	if (!getattributes(&entry, argc - 1, argv + 1)) state_syntax(lineno);
+	return &entry;
+}
+
+void checkdiff(void)
+{
+	if (ferror(difffp)) fatal(diff_file);
+}
+
+enum { DELETE, REPLACE, COPY, SIMILAR, EQUAL, ADD }
+compare(entry_t *remote, entry_t *local)
+/* Compare the local and remote entries and tell what need to be done. */
+{
+	int cmp;
+
+	/* Surplus entries? */
+	if (local == nil) return DELETE;
+	if (remote == nil) return ADD;
+
+	/* Extra directory entries? */
+	if (remote->depth > local->depth) return DELETE;
+	if (local->depth > remote->depth) return ADD;
+
+	/* Compare names. */
+	cmp= strcmp(remote->name, local->name);
+	if (cmp < 0) return DELETE;
+	if (cmp > 0) return ADD;
+
+	/* The files have the same name.  Ignore one, ignore the other. */
+	if (remote->ignore || local->ignore) {
+		remote->ignore= local->ignore= 1;
+		return EQUAL;
+	}
+
+	/* Reasons for replacement? */
+	if (remote->type != local->type) return REPLACE;
+
+	/* Should be hard linked to the same file. */
+	if (remote->linked || local->linked) {
+		if (!remote->linked || !local->linked) return REPLACE;
+		if (strcmp(remote->link, local->link) != 0) return REPLACE;
+	}
+
+	switch (remote->type) {
+	case F_FILE:
+		if (uflag) {
+			if (remote->mtime < local->mtime) return COPY;
+		} else {
+			if (remote->size != local->size
+					|| remote->mtime != local->mtime)
+				return COPY;
+		}
+		goto check_modes;
+	case F_BLK:
+	case F_CHR:
+		if (remote->rdev != local->rdev) return REPLACE;
+		goto check_modes;
+	case F_DIR:
+	case F_PIPE:
+	check_modes:
+		if (remote->mode != local->mode
+			|| remote->uid != local->uid
+			|| remote->gid != local->gid) return SIMILAR;
+		break;
+	case F_LINK:
+		if (strcmp(remote->link, local->link) != 0) return REPLACE;
+		break;
+	}
+	return EQUAL;
+}
+
+void delete(entry_t *old)
+/* Emit an instruction to remove an entry. */
+{
+	if (old->ignore) return;
+	if (uflag) return;
+
+	fprintf(difffp, "rm ");
+	checkdiff();
+	if (!print_name(difffp, old->path)) checkdiff();
+	if (putc('\n', difffp) == EOF) checkdiff();
+	if (vflag) fprintf(stderr, "rm %s\n", old->path);
+}
+
+void change_modes(entry_t *old, entry_t *new)
+/* Emit an instruction to change the attributes of an entry. */
+{
+	if (new->ignore) return;
+
+	fprintf(difffp, "chmod ");
+	checkdiff();
+	if (!print_name(difffp, new->path)) checkdiff();
+	fprintf(difffp, " %03o %u %u\n",
+		(unsigned) new->mode,
+		(unsigned) new->uid, (unsigned) new->gid);
+	checkdiff();
+	if (vflag && old->mode != new->mode) {
+		fprintf(stderr, "chmod %s %03o %u %u\n",
+			new->path,
+			(unsigned) new->mode,
+			(unsigned) new->uid, (unsigned) new->gid);
+	}
+}
+
+int cat(int f, off_t size)
+/* Include the contents of a file in the differences file. */
+{
+	ssize_t n;
+	unsigned char buf[1024 << sizeof(int)];
+	unsigned char *p;
+	int c;
+
+	if (Dflag) return 1;	/* Debug: Don't need the file contents. */
+
+	while ((n= read(f, buf, sizeof(buf))) > 0) {
+		p= buf;
+		do {
+			if (size == 0) {
+				/* File suddenly larger. */
+				errno= EINVAL;
+				return 0;
+			}
+			c= *p++;
+			if (putc(c, difffp) == EOF) checkdiff();
+			size--;
+		} while (--n != 0);
+	}
+	if (size > 0) {
+		int err= errno;
+
+		/* File somehow shrunk, pad it out. */
+		do {
+			if (putc(0, difffp) == EOF) checkdiff();
+		} while (--size != 0);
+		errno= n == 0 ? EINVAL : err;
+		n= -1;
+	}
+	return n == 0;
+}
+
+void add(entry_t *old, entry_t *new)
+/* Emit an instruction to add an entry. */
+{
+	pathname_t file;
+	int f;
+
+	if (new->ignore) return;
+
+	if (new->linked) {
+		/* This file is to be a hard link to an existing file. */
+		fprintf(difffp, "ln ");
+		checkdiff();
+		if (!print_name(difffp, new->link)) checkdiff();
+		if (fputc(' ', difffp) == EOF) checkdiff();
+		if (!print_name(difffp, new->path)) checkdiff();
+		if (fputc('\n', difffp) == EOF) checkdiff();
+		if (vflag) {
+			fprintf(stderr, "ln %s %s\n", new->link, new->path);
+		}
+		return;
+	}
+
+	/* Add some other type of file. */
+	fprintf(difffp, "add ");
+	checkdiff();
+	if (!print_name(difffp, new->path)) checkdiff();
+
+	switch (new->type) {
+	case F_DIR:
+		fprintf(difffp, " d%03o %u %u\n",
+			(unsigned) new->mode,
+			(unsigned) new->uid, (unsigned) new->gid);
+		if (vflag) fprintf(stderr, "mkdir %s\n", new->path);
+		break;
+	case F_FILE:
+		path_init(&file);
+		path_add(&file, tree);
+		path_add(&file, new->path);
+		if ((f= open(path_name(&file), O_RDONLY)) < 0) {
+			report(path_name(&file));
+			path_drop(&file);
+			fprintf(difffp, " ignore\n");
+			break;
+		}
+		fprintf(difffp, " %03o %u %u %lu %lu\n",
+			(unsigned) new->mode,
+			(unsigned) new->uid, (unsigned) new->gid,
+			(unsigned long) new->size,
+			(unsigned long) new->mtime);
+		checkdiff();
+		if (!cat(f, new->size)) {
+			int err= errno;
+			report(path_name(&file));
+			fprintf(difffp, "old ");
+			checkdiff();
+			print_name(difffp, err == EINVAL
+				? "File changed when copied" : strerror(err));
+			fputc('\n', difffp);
+			checkdiff();
+		} else {
+			if (vflag) {
+				fprintf(stderr, "%s %s\n",
+					old == nil ? "add" :
+						old->mtime > new->mtime ?
+							"restore" : "update",
+					new->path);
+			}
+		}
+		close(f);
+		path_drop(&file);
+		break;
+	case F_BLK:
+	case F_CHR:
+		fprintf(difffp, " %c%03o %u %u %lx\n",
+			new->type == F_BLK ? 'b' : 'c',
+			(unsigned) new->mode,
+			(unsigned) new->uid, (unsigned) new->gid,
+			(unsigned long) new->rdev);
+		if (vflag) fprintf(stderr, "mknod %s\n", new->path);
+		break;
+	case F_PIPE:
+		fprintf(difffp, " p%03o %u %u\n",
+			(unsigned) new->mode,
+			(unsigned) new->uid, (unsigned) new->gid);
+		if (vflag) fprintf(stderr, "mkfifo %s\n", new->path);
+		break;
+	case F_LINK:
+		fprintf(difffp, " -> ");
+		checkdiff();
+		(void) print_name(difffp, new->link);
+		checkdiff();
+		fputc('\n', difffp);
+		if (vflag) {
+			fprintf(stderr, "ln -s %s %s\n", new->link, new->path);
+		}
+		break;
+	}
+	checkdiff();
+}
+
+void mkdifferences(void)
+{
+	entry_t *remote;
+	entry_t *local;
+
+	remote= readstate();
+	local= traverse();
+
+	while (remote != nil || local != nil) {
+		switch (compare(remote, local)) {
+		case DELETE:
+			/* Remove the remote file. */
+			delete(remote);
+			remote->ignore= 1;
+			remote= readstate();
+			break;
+		case REPLACE:
+			/* Replace the remote file with the local one. */
+			if (remote->type == F_FILE && local->type == F_FILE
+							&& !local->linked) {
+				/* Don't overwrite, remove first. */
+				delete(remote);
+			}
+			/*FALL THROUGH*/
+		case COPY:
+			/* Overwrite the remote file with the local one. */
+			add(remote, local);
+			remote->ignore= 1;
+			goto skip2;
+		case SIMILAR:
+			/* About the same, but the attributes need changing. */
+			change_modes(remote, local);
+			goto skip2;
+		case EQUAL:
+		skip2:
+			/* Skip two files. */
+			remote= readstate();
+			local= traverse();
+			break;
+		case ADD:
+			/* Add the local file. */
+			add(nil, local);
+			local= traverse();
+			break;
+		}
+	}
+	fprintf(difffp, "end\n");
+	fflush(difffp);
+	checkdiff();
+}
+
+void apply_remove(pathname_t *pp)
+/* Remove an obsolete file. */
+{
+	struct stat st;
+
+	if (lstat(path_name(pp), &st) < 0) {
+		if (errno != ENOENT) report(path_name(pp));
+		return;
+	}
+
+	if (S_ISDIR(st.st_mode)) {
+		/* Recursively delete directories. */
+		size_t len;
+		namelist_t *entries;
+
+		if ((entries= collect(path_name(pp))) == nil && errno != 0) {
+			report(path_name(pp));
+			return;
+		}
+		len= path_length(pp);
+
+		while (entries != nil) {
+			path_add(pp, pop_name(&entries));
+			apply_remove(pp);
+			path_trunc(pp, len);
+		}
+		if (rmdir(path_name(pp)) < 0) {
+			report(path_name(pp));
+			return;
+		}
+		if (vflag) fprintf(stderr, "rmdir %s\n", path_name(pp));
+	} else {
+		/* Some other type of file. */
+		if (unlink(path_name(pp)) < 0) {
+			report(path_name(pp));
+			return;
+		}
+		if (vflag) fprintf(stderr, "rm %s\n", path_name(pp));
+	}
+}
+
+void apply_mkold(const char *file, const char *err)
+/* Make a file very old.  (An error occurred when it was added.) */
+{
+	struct utimbuf utb;
+
+	utb.actime= utb.modtime= 0;
+	if (utime(file, &utb) < 0) {
+		report(file);
+		return;
+	}
+	fprintf(stderr, "made %s look old", file);
+	fprintf(stderr, err == nil ? "\n" : " due to a remote problem: %s\n",
+								err);
+}
+
+void apply_chmod(const char *file, mode_t mode, uid_t uid, gid_t gid, int talk)
+/* Change mode and ownership. */
+{
+	struct stat st;
+
+	if (lstat(file, &st) < 0) {
+		report(file);
+		return;
+	}
+	if ((st.st_mode & 07777) != mode) {
+		if (chmod(file, mode) < 0) {
+			report(file);
+			return;
+		}
+		if (vflag && talk) {
+			fprintf(stderr, "chmod %03o %s\n",
+						(unsigned) mode, file);
+		}
+	}
+	if (st.st_uid != uid || st.st_gid != gid) {
+		if (chown(file, uid, gid) < 0) {
+			if (errno != EPERM) report(file);
+			return;
+		}
+		if (vflag && talk) {
+			fprintf(stderr, "chown %u:%u %s\n",
+				(unsigned) uid, (unsigned) gid, file);
+		}
+	}
+}
+
+void apply_add(pathname_t *pp, entry_t *entry)
+/* Add or replace a file. */
+{
+	const char *file;
+	off_t size;
+	int f;
+	unsigned char buf[1024 << sizeof(int)];
+	unsigned char *p;
+	int c;
+	int dirty;
+	struct stat st;
+	struct utimbuf utb;
+
+	if (entry->ignore) return;
+
+	if (lstat(path_name(pp), &st) >= 0 && (entry->type != F_FILE
+					|| !S_ISREG(st.st_mode))) {
+		apply_remove(pp);
+	}
+
+	file= path_name(pp);
+
+	switch (entry->type) {
+	case F_DIR:
+		if (mkdir(file, entry->mode) < 0) {
+			report(file);
+			return;
+		}
+		if (vflag) fprintf(stderr, "mkdir %s\n", file);
+		break;
+	case F_FILE:
+		size= entry->size;
+
+		f= -1;
+		st.st_mode= 0;
+		if (lstat(file, &st) < 0 || S_ISREG(st.st_mode)) {
+			f= open(file, O_WRONLY | O_CREAT | O_TRUNC,
+						entry->mode);
+			if (f < 0) {
+				(void) chmod(file, entry->mode | 0200);
+				f= open(file, O_WRONLY | O_CREAT | O_TRUNC,
+						entry->mode);
+			}
+			if (f < 0) {
+				(void) unlink(file);
+				f= open(file, O_WRONLY | O_CREAT | O_TRUNC,
+						entry->mode);
+			}
+			if (f < 0) report(file);
+		}
+		dirty= (f >= 0);
+		p= buf;
+		while (size > 0 && (c= getc(difffp)) != EOF) {
+			size--;
+			*p++= c;
+			if (p == arraylimit(buf) || size == 0) {
+				if (f >= 0 && write(f, buf, p - buf) < 0) {
+					report(file);
+					close(f);
+					f= -1;
+				}
+				p= buf;
+			}
+		}
+		if (size > 0) {
+			if (ferror(difffp)) report(diff_file);
+			if (feof(difffp)) {
+				fprintf(stderr, "remspec: %s: premature EOF\n",
+					diff_file);
+			}
+			if (dirty) apply_mkold(file, nil);
+			exit(1);
+		}
+		if (f < 0) {
+			if (dirty) apply_mkold(file, nil);
+			return;
+		}
+		close(f);
+		if (vflag) {
+			fprintf(stderr, st.st_mode == 0 ? "add %s\n"
+				: entry->mtime >= st.st_mtime
+					? "update %s\n" : "restore %s\n", file);
+		}
+		utb.actime= time(nil);
+		utb.modtime= entry->mtime;
+		if (utime(file, &utb) < 0) report(file);
+		break;
+	case F_BLK:
+		if (mknod(file, S_IFBLK | entry->mode, entry->rdev) < 0) {
+			report(file);
+			return;
+		}
+		if (vflag) {
+			fprintf(stderr, "mknod %s b %d %d\n", file,
+				major(entry->rdev), minor(entry->rdev));
+		}
+		break;
+	case F_CHR:
+		if (mknod(file, S_IFCHR | entry->mode, entry->rdev) < 0) {
+			report(file);
+			return;
+		}
+		if (vflag) {
+			fprintf(stderr, "mknod %s c %d %d\n", file,
+				major(entry->rdev), minor(entry->rdev));
+		}
+		break;
+	case F_PIPE:
+		if (mknod(file, S_IFIFO | entry->mode, 0) < 0) {
+			report(file);
+			return;
+		}
+		if (vflag) fprintf(stderr, "mknod %s p\n", file);
+		break;
+	case F_LINK:
+		if (symlink(entry->link, file) < 0) {
+			report(file);
+			return;
+		}
+		if (vflag) fprintf(stderr, "ln -s %s %s\n", entry->link, file);
+		return;
+	}
+	apply_chmod(file, entry->mode, entry->uid, entry->gid, 0);
+}
+
+void apply_link(const char *file, pathname_t *pp)
+/* Hard link *pp to file. */
+{
+	struct stat st1, st2;
+
+	if (lstat(file, &st1) < 0) {
+		report(file);
+		return;
+	}
+	if (lstat(path_name(pp), &st2) >= 0) {
+		if (st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev)
+			return;
+		apply_remove(pp);
+		if (lstat(path_name(pp), &st2) >= 0) return;
+	}
+	if (link(file, path_name(pp)) < 0) {
+		fprintf(stderr, "remsync: ln %s %s: %s\n", file, path_name(pp),
+			strerror(errno));
+		excode= 1;
+		return;
+	}
+	if (vflag) fprintf(stderr, "ln %s %s\n", file, path_name(pp));
+}
+
+void diff_syntax(const char *line)
+{
+	fprintf(stderr, "remsync: %s: syntax error on this line: %s\n",
+		diff_file, line);
+	exit(1);
+}
+
+void apply_differences(void)
+/* Update a tree to a list of differences derived from a remote tree. */
+{
+	char *line;
+	char **argv;
+	size_t argc;
+	pathname_t path, link;
+	size_t trunc;
+
+	path_init(&path);
+	path_init(&link);
+	path_add(&path, tree);
+	path_add(&link, tree);
+	trunc= path_length(&path);
+
+	while (!feof(difffp) && (line= read1line(difffp)) != nil) {
+		splitline(line, &argv, &argc);
+		if (argc == 0) diff_syntax(line);
+
+		path_trunc(&path, trunc);
+
+		if (strcmp(argv[0], "add") == 0) {
+			entry_t entry;
+
+			if (argc < 3) diff_syntax(line);
+			path_add(&path, argv[1]);
+			entry.ignore= (strcmp(argv[2], "ignore") == 0);
+			if (!entry.ignore && !getattributes(&entry,
+							argc - 2, argv + 2))
+				diff_syntax(line);
+			apply_add(&path, &entry);
+		} else
+		if (strcmp(argv[0], "rm") == 0) {
+			if (argc != 2) diff_syntax(line);
+			path_add(&path, argv[1]);
+			apply_remove(&path);
+		} else
+		if (strcmp(argv[0], "ln") == 0) {
+			if (argc != 3) diff_syntax(line);
+			path_trunc(&link, trunc);
+			path_add(&link, argv[1]);
+			path_add(&path, argv[2]);
+			apply_link(path_name(&link), &path);
+		} else
+		if (strcmp(argv[0], "chmod") == 0) {
+			if (argc != 5) diff_syntax(line);
+			path_add(&path, argv[1]);
+			apply_chmod(path_name(&path),
+				strtoul(argv[2], nil, 010),
+				strtoul(argv[3], nil, 10),
+				strtoul(argv[4], nil, 10),
+				1);
+		} else
+		if (strcmp(argv[0], "old") == 0) {
+			if (argc != 3) diff_syntax(line);
+			path_add(&path, argv[1]);
+			apply_mkold(path_name(&path), argv[2]);
+		} else
+		if (strcmp(argv[0], "end") == 0) {
+			if (argc != 1) diff_syntax(line);
+			break;
+		} else {
+			diff_syntax(line);
+		}
+	}
+	checkdiff();
+}
+
+void usage(void)
+{
+    fprintf(stderr, "Usage: remsync -sxv tree [state-file]\n");
+    fprintf(stderr, "       remsync -duxvD tree [state-file [diff-file]]\n");
+    fprintf(stderr, "       remsync [-xv] tree [diff-file]\n");
+    exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	int i;
+
+	for (i= 1; i < argc && argv[i][0] == '-'; i++) {
+		char *p= argv[i] + 1;
+
+		if (p[0] == '-' && p[1] == 0) { i++; break; }
+
+		while (*p != 0) {
+			switch (*p++) {
+			case 's':	sflag= 1; break;
+			case 'd':	dflag= 1; break;
+			case 'u':	uflag= 1; break;
+			case 'x':	xflag= 1; break;
+			case 'D':	Dflag= 1; break;
+			case 'v':	vflag= 1; break;
+			default:	usage();
+			}
+		}
+	}
+	if (sflag && dflag) usage();
+	if (sflag && uflag) usage();
+	if (!sflag && !dflag && uflag) usage();
+	if (!dflag && Dflag) usage();
+
+	if (i == argc) usage();
+	tree= argv[i++];
+
+	if (sflag) {
+		/* Make a state file. */
+		state_file= i < argc ? argv[i++] : "-";
+		if (i != argc) usage();
+
+		statefp= stdout;
+		if (strcmp(state_file, "-") != 0) {
+			if ((statefp= fopen(state_file, "w")) == nil)
+				fatal(state_file);
+		}
+		mkstatefile();
+	} else
+	if (dflag) {
+		/* Make a file of differences. */
+		state_file= i < argc ? argv[i++] : "-";
+
+		diff_file= i < argc ? argv[i++] : "-";
+		if (i != argc) usage();
+
+		statefp= stdin;
+		if (strcmp(state_file, "-") != 0) {
+			if ((statefp= fopen(state_file, "r")) == nil)
+				fatal(state_file);
+		}
+
+		difffp= stdout;
+		if (strcmp(diff_file, "-") != 0) {
+			if ((difffp= fopen(diff_file, "w")) == nil)
+				fatal(diff_file);
+		}
+		mkdifferences();
+	} else {
+		/* Apply a file of differences. */
+		diff_file= i < argc ? argv[i++] : "-";
+		if (i != argc) usage();
+
+		difffp= stdin;
+		if (strcmp(diff_file, "-") != 0) {
+			if ((difffp= fopen(diff_file, "r")) == nil)
+				fatal(diff_file);
+		}
+		apply_differences();
+	}
+	exit(excode);
+}
Index: /trunk/minix/commands/simple/rev.c
===================================================================
--- /trunk/minix/commands/simple/rev.c	(revision 9)
+++ /trunk/minix/commands/simple/rev.c	(revision 9)
@@ -0,0 +1,108 @@
+/*-
+ * Copyright (c) 1987, 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1987, 1992, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+	const char *filename;
+	char p[2000], *t;
+	FILE *fp;
+	size_t len;
+	int ch, rval;
+
+	setlocale(LC_ALL, "");
+
+	while ((ch = getopt(argc, argv, "")) != -1)
+		switch(ch) {
+		case '?':
+		default:
+			usage();
+		}
+
+	argc -= optind;
+	argv += optind;
+
+	fp = stdin;
+	filename = "stdin";
+	rval = 0;
+	do {
+		if (*argv) {
+			if ((fp = fopen(*argv, "r")) == NULL) {
+				perror(*argv);
+				rval = 1;
+				++argv;
+				continue;
+			}
+			filename = *argv++;
+		}
+		while ((fgets(p, sizeof(p)-1, fp)) != NULL) {
+			len = strlen(p);
+			if (p[len - 1] == '\n')
+				--len;
+			t = p + len - 1;
+			for (t = p + len - 1; t >= p; --t)
+				putchar(*t);
+			putchar('\n');
+		}
+		if (ferror(fp)) {
+			perror(filename);
+			rval = 1;
+		}
+		(void)fclose(fp);
+	} while(*argv);
+	exit(rval);
+}
+
+void
+usage(void)
+{
+	(void)fprintf(stderr, "usage: rev [file ...]\n");
+	exit(1);
+}
Index: /trunk/minix/commands/simple/rget.c
===================================================================
--- /trunk/minix/commands/simple/rget.c	(revision 9)
+++ /trunk/minix/commands/simple/rget.c	(revision 9)
@@ -0,0 +1,290 @@
+/*	rget 2.6 - remote pipe				Author: Kees J. Bot
+ *								20 Mar 1989
+ *
+ * here$ ... | rput key			there$ rget -h here key | ...
+ * here$ rput key command ...		there$ rget -h here key command ...
+ *
+ * (Once my first try at network programming, completely reworked by now.)
+ */
+#define nil ((void*)0)
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#if __minix
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/netdb.h>
+#include <net/gen/socket.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_hdr.h>
+#include <net/gen/tcp_io.h>
+#include <net/hton.h>
+#include <net/netlib.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#endif
+
+static char *name;
+static int iflag, oflag, hflag, lflag, cflag;	/* -iolch? */
+static char *host;				/* Argument to -h. */
+static struct hostent *hent;			/* gethostbyname(host) */
+static char *key;				/* key (port) */
+static char **cmdv;				/* command [arg ...] */
+
+static void fatal(const char *label)
+{
+    int err= errno;
+
+    fprintf(stderr, "%s: %s: %s\n", name, label, strerror(err));
+    exit(1);
+}
+
+static unsigned name2port(char *n)
+{
+    char *end;
+    unsigned port;
+
+    port= strtoul(n, &end, 0);
+    if (end == n || *end != 0) {
+	port= 1;
+	while (*n != 0) port *= (*n++ & 0xFF);
+	port |= 0x8000;
+    }
+    return htons(port & 0xFFFF);
+}
+
+static void usage(void)
+{
+    fprintf(stderr,
+	"Usage: %s [-lcio] [-h host] key [command [arg ...]]\n"
+	"\t-l: Open TCP socket and listen (default for rput)\n"
+	"\t-c: Connect to a remote TCP socket (default for rget)\n"
+	"\t-i: Tie standard input to the TCP stream (default for rget)\n"
+	"\t-o: Tie standard output to the TCP stream (default for rput)\n"
+	"\t-io: Bidirectional!\n"
+	"\tkey: A word to hash into a port number, or simply a port number\n",
+	name);
+    exit(1);
+}
+
+int main(int argc, char **argv)
+{
+    int i, s;
+
+    if ((name= strrchr(argv[0], '/')) == nil) name= argv[0]; else name++;
+
+    if (strcmp(name, "rget") != 0 && strcmp(name, "rput") != 0) {
+	fprintf(stderr, "Don't know what to do if you call me '%s'\n", name);
+	exit(1);
+    }
+
+    i= 1;
+    while (i < argc && argv[i][0] == '-') {
+	char *opt= argv[i++]+1;
+
+	if (opt[0] == '-' && opt[1] == 0) break;	/* -- */
+
+	while (*opt != 0) switch (*opt++) {
+	case 'l':	lflag= 1;	break;
+	case 'c':	cflag= 1;	break;
+	case 'i':	iflag= 1;	break;
+	case 'o':	oflag= 1;	break;
+	case 'h':
+	    hflag= 1;
+	    if (*opt == 0) {
+		if (i == argc) usage();
+		opt= argv[i++];
+	    }
+	    host= opt;
+	    opt= "";
+	    break;
+	default:	usage();	break;
+	}
+    }
+
+    if (i == argc) usage();
+    key= argv[i++];
+    cmdv= argv + i;
+
+    /* Defaults. */
+    if (!lflag && !cflag) {
+	if (name[1] == 'p') lflag= 1;
+	if (name[1] == 'g') cflag= 1;
+    }
+    if (!iflag && !oflag) {
+	if (name[1] == 'g') iflag= 1;
+	if (name[1] == 'p') oflag= 1;
+    }
+
+    /* Constraints. */
+    if (lflag && cflag) {
+	fprintf(stderr, "%s: -c and -l don't mix\n", name);
+	usage();
+    }
+    if (cflag && !hflag) {
+	fprintf(stderr, "%s: -c requires a host name given with -h\n", name);
+	usage();
+    }
+    if (lflag && hflag) {
+	fprintf(stderr, "%s: -l does not require a host name given with -h\n",
+	    name);
+	usage();
+    }
+    if (iflag && oflag && cmdv[0] == nil) {
+	fprintf(stderr, "%s: -io requires that a command is given\n", name);
+	usage();
+    }
+
+    if (hflag) {
+	if ((hent= gethostbyname(host)) == nil) {
+	    fprintf(stderr, "%s: %s: Name lookup failed\n", name, host);
+	    exit(1);
+	}
+    }
+
+    s= -1;
+    if (lflag) {
+	/* We need to listen and wait.  (We're "rput", most likely.) */
+#if __minix
+	char *tcp_device;
+	struct nwio_tcpconf tcpconf;
+	struct nwio_tcpcl tcplistenopt;
+
+	if ((tcp_device= getenv("TCP_DEVICE")) == nil) tcp_device= "/dev/tcp";
+	if ((s= open(tcp_device, O_RDWR)) < 0) fatal(tcp_device);
+
+	tcpconf.nwtc_flags=
+	    NWTC_EXCL | NWTC_LP_SET | NWTC_UNSET_RA | NWTC_UNSET_RP;
+	tcpconf.nwtc_locport= name2port(key);
+	if (ioctl(s, NWIOSTCPCONF, &tcpconf) < 0) fatal("NWIOSTCPCONF");
+
+	tcplistenopt.nwtcl_flags= 0;
+	if (ioctl(s, NWIOTCPLISTEN, &tcplistenopt) < 0) fatal("NWIOTCPLISTEN");
+#else
+	int sa;
+	struct sockaddr_in channel;
+	static int on= 1;
+
+	if ((s= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))<0) fatal("socket()");
+
+	(void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
+								sizeof(on));
+	memset(&channel, 0, sizeof(channel));
+	channel.sin_family= AF_INET;
+	channel.sin_addr.s_addr= htonl(INADDR_ANY);
+	channel.sin_port= name2port(key);
+	if (bind(s, (struct sockaddr *) &channel, sizeof(channel)) < 0)
+	    fatal("bind()");
+
+	if (listen(s, 0) < 0) fatal("listen()");
+
+	if ((sa= accept(s, nil, nil)) < 0) fatal("accept()");
+	close(s);
+	s= sa;
+#endif
+    }
+
+    if (cflag) {
+	/* Connect to the remote end.  (We're "rget", most likely.) */
+#if __minix
+	int n;
+	char *tcp_device;
+	nwio_tcpconf_t tcpconf;
+	nwio_tcpcl_t tcpconnopt;
+
+	if ((tcp_device= getenv("TCP_DEVICE")) == nil) tcp_device= "/dev/tcp";
+
+	n=60;
+	for (;;) {
+	    if ((s= open(tcp_device, O_RDWR)) < 0) fatal(tcp_device);
+
+	    tcpconf.nwtc_flags= NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
+	    memcpy(&tcpconf.nwtc_remaddr, hent->h_addr,
+		sizeof(tcpconf.nwtc_remaddr));
+	    tcpconf.nwtc_remport= name2port(key);
+	    if (ioctl(s, NWIOSTCPCONF, &tcpconf) < 0) fatal("NWIOSTCPCONF");
+
+	    tcpconnopt.nwtcl_flags= 0;
+	    if (ioctl(s, NWIOTCPCONN, &tcpconnopt) == 0) break;
+
+	    if (--n > 0) sleep(2); else fatal("NWIOTCPCONN");
+	    close(s);
+	}
+#else
+	int n;
+	struct sockaddr_in channel;
+
+	n=60;
+	for (;;) {
+	    if ((s= socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+		fatal("socket()");
+
+	    memset(&channel, 0, sizeof(channel));
+	    channel.sin_family= AF_INET;
+	    memcpy(&channel.sin_addr.s_addr, hent->h_addr,
+		sizeof(channel.sin_addr.s_addr));
+	    channel.sin_port= name2port(key);
+	    if (connect(s, (struct sockaddr *) &channel,
+			    sizeof(channel)) >= 0) break;
+
+	    if (--n > 0) sleep(2); else fatal("connect()");
+	    close(s);
+	}
+#endif
+    }
+
+    if (cmdv[0] != nil) {
+	/* A command is given, so execute it with standard input (rget),
+	 * standard output (rput) or both (-io) tied to the TCP stream.
+	 */
+	if (iflag) dup2(s, 0);
+	if (oflag) dup2(s, 1);
+	close(s);
+
+	execvp(cmdv[0], cmdv);
+	fatal(cmdv[0]);
+    } else {
+	/* Without a command we have to copy bytes ourselves, probably to or
+	 * from a command that is connected to us with a pipe.  (The original
+	 * function of rput/rget, a remote pipe.)
+	 */
+	int fi, fo;
+	int n;
+	char buf[8192];
+
+	if (iflag) {
+	    fi= s;
+	    fo= 1;
+	} else {
+	    fi= 0;
+	    fo= s;
+	}
+
+	while ((n= read(fi, buf, sizeof(buf))) > 0) {
+	    char *bp= buf;
+
+	    while (n > 0) {
+		int r;
+
+		if ((r= write(fo, bp, n)) <= 0) {
+		    if (r == 0) {
+			fprintf(stderr, "%s: write(): Unexpected EOF\n", name);
+			exit(1);
+		    }
+		    fatal("write()");
+		}
+		bp+= r;
+		n-= r;
+	    }
+	}
+	if (n < 0) fatal("read()");
+    }
+    return 0;
+}
Index: /trunk/minix/commands/simple/rlogin.c
===================================================================
--- /trunk/minix/commands/simple/rlogin.c	(revision 9)
+++ /trunk/minix/commands/simple/rlogin.c	(revision 9)
@@ -0,0 +1,1775 @@
+/*
+ * Copyright (c) 1983, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#ifdef ID
+static char sccsid[] = "@(#)rlogin.c	5.33 (Berkeley) 3/1/91";
+#endif
+#endif /* not lint */
+
+/*
+ * $Source: /cvsup/minix/src/commands/simple/rlogin.c,v $
+ * $Header: mit/rlogin/RCS/rlogin.c,v 5.2 89/07/26 12:11:21 kfall
+ *	Exp Locker: kfall $
+ */
+
+/*
+ * rlogin - remote login
+ */
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/netdb.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+
+#include <termios.h>
+#include <setjmp.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+
+#ifdef KERBEROS
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+
+CREDENTIALS cred;
+Key_schedule schedule;
+int use_kerberos = 1, doencrypt;
+char dst_realm_buf[REALM_SZ], *dest_realm = NULL;
+extern char *krb_realmofhost();
+#endif
+
+#ifndef TIOCPKT_WINDOW
+#define	TIOCPKT_WINDOW	0x80
+#endif
+
+/* concession to Sun */
+#ifndef SIGUSR1
+#define	SIGUSR1	30
+#endif
+
+extern int errno;
+int eight, litout, rem;
+
+int noescape;
+u_char escapechar = '~';
+
+struct speed
+{
+	speed_t speed;
+	char *name;
+} speeds[] = {
+	{ B0, "0" }, { B50, "50" }, { B75, "75" }, { B110, "110" }, 
+	{ B134, "134" }, { B150, "150" }, { B200, "200" }, { B300, "300" }, 
+	{ B600, "600" }, { B1200, "1200" }, { B1800, "1800" }, 
+	{ B2400, "2400" }, { B4800, "4800" }, { B9600, "9600" }, 
+	{ B19200, "19200" }, { B38400, "38400" }, { B57600, "57600" },
+	{ B115200, "115200" },
+	{ -1, NULL },
+};
+
+#if __minix_vmd
+/* flow control variables */
+int more2read_0;
+int inprogress_0;
+int more2write_1;
+int inprogress_1;
+int more2read_rem;
+int inprogress_rd_rem;
+int more2write_rem;
+int inprogress_wr_rem;
+
+/* write to remote */
+size_t wr_rem_size;
+size_t wr_rem_offset;
+size_t extra_wr_rem_size;
+size_t extra_wr_rem_offset;
+char *extra_wr_rem;
+size_t extra_wr_rem_new_size;
+char *extra_wr_rem_new;
+
+#endif /* __minix_vmd */
+
+struct	winsize winsize;
+
+#define	get_window_size(fd, wp)	ioctl(fd, TIOCGWINSZ, wp)
+
+extern int main _ARGS(( int argc, char **argv ));
+static void usage _ARGS(( void ));
+static u_char getescape _ARGS(( char *p ));
+static char *speeds2str _ARGS(( speed_t speed ));
+static void lostpeer _ARGS(( int sig ));
+static void doit _ARGS(( void ));
+static void setsignal _ARGS(( int sig, void (*act)(int sig) ));
+static void msg _ARGS(( char *str ));
+static void done _ARGS(( int status ));
+#if !__minix_vmd
+static int reader _ARGS(( void ));
+#endif
+static void mode _ARGS(( int f ));
+#if __minix_vmd
+static void mark_async _ARGS(( int fd ));
+static void init_0 _ARGS(( void ));
+static void init_1 _ARGS(( void ));
+static void init_rd_rem _ARGS(( void ));
+static void init_wr_rem _ARGS(( void ));
+static void restart_0 _ARGS(( void ));
+static void restart_1 _ARGS(( void ));
+static void restart_rd_rem _ARGS(( void ));
+static void restart_wr_rem _ARGS(( void ));
+static void completed_0 _ARGS(( int result, int error ));
+static void completed_1 _ARGS(( int result, int error ));
+static void completed_rd_rem _ARGS(( int result, int error ));
+static void completed_wr_rem _ARGS(( int result, int error ));
+static void do_urg _ARGS(( int urg_byte ));
+#endif
+#if !__minix_vmd
+static void catch_child _ARGS(( int sig ));
+static void writer _ARGS(( void ));
+#endif
+static void echo _ARGS(( int c ));
+#if __minix_vmd
+static void finish _ARGS(( void ));
+static void sendwindow _ARGS(( void ));
+static void sigwinch _ARGS(( int sig ));
+static void subshell _ARGS(( void ));
+#endif
+
+int main(argc, argv)
+	int argc;
+	char **argv;
+{
+	extern char *optarg;
+	extern int optind;
+	struct passwd *pw;
+	struct servent *sp;
+	struct termios ttyb;
+	nwio_tcpopt_t tcpopt;
+	int error;
+	int argoff, ch, dflag, one, uid;
+	char *host, *p, *user, term[1024];
+
+	argoff = dflag = 0;
+	one = 1;
+	host = user = NULL;
+
+	if (p = rindex(argv[0], '/'))
+		++p;
+	else
+		p = argv[0];
+
+	if (strcmp(p, "rlogin"))
+		host = p;
+
+	/* handle "rlogin host flags" */
+	if (!host && argc > 2 && argv[1][0] != '-') {
+		host = argv[1];
+		argoff = 1;
+	}
+
+#ifdef KERBEROS
+#define	OPTIONS	"8EKLde:k:l:x"
+#else
+#define	OPTIONS	"8EKLde:l:"
+#endif
+	while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
+		switch(ch) {
+		case '8':
+			eight = 1;
+			break;
+		case 'E':
+			noescape = 1;
+			break;
+		case 'K':
+#ifdef KERBEROS
+			use_kerberos = 0;
+#endif
+			break;
+		case 'L':
+			litout = 1;
+			break;
+		case 'd':
+			dflag = 1;
+			break;
+		case 'e':
+			escapechar = getescape(optarg);
+			break;
+#ifdef KERBEROS
+		case 'k':
+			dest_realm = dst_realm_buf;
+			(void)strncpy(dest_realm, optarg, REALM_SZ);
+			break;
+#endif
+		case 'l':
+			user = optarg;
+			break;
+#ifdef CRYPT
+#ifdef KERBEROS
+		case 'x':
+			doencrypt = 1;
+			des_set_key(cred.session, schedule);
+			break;
+#endif
+#endif
+		case '?':
+		default:
+			usage();
+		}
+	optind += argoff;
+	argc -= optind;
+	argv += optind;
+
+	/* if haven't gotten a host yet, do so */
+	if (!host && !(host = *argv++))
+		usage();
+
+	if (*argv)
+		usage();
+
+	if (!(pw = getpwuid(uid = getuid()))) {
+		(void)fprintf(stderr, "rlogin: unknown user id.\n");
+		exit(1);
+	}
+	if (!user)
+		user = pw->pw_name;
+
+	sp = NULL;
+#ifdef KERBEROS
+	if (use_kerberos) {
+		sp = getservbyname((doencrypt ? "eklogin" : "klogin"), "tcp");
+		if (sp == NULL) {
+			use_kerberos = 0;
+			warning("can't get entry for %s/tcp service",
+			    doencrypt ? "eklogin" : "klogin");
+		}
+	}
+#endif
+	if (sp == NULL)
+		sp = getservbyname("login", "tcp");
+	if (sp == NULL) {
+		(void)fprintf(stderr, "rlogin: login/tcp: unknown service.\n");
+		exit(1);
+	}
+
+	(void)strncpy(term, (p = getenv("TERM")) ? p : "network", sizeof(term));
+	term[sizeof(term)-1]= 0;
+
+	if (tcgetattr(0, &ttyb) == 0) {
+		(void)strcat(term, "/");
+		(void)strcat(term, speeds2str(cfgetospeed(&ttyb)));
+	}
+
+	(void)get_window_size(0, &winsize);
+
+	(void)signal(SIGPIPE, lostpeer);
+
+#ifdef KERBEROS
+try_connect:
+	if (use_kerberos) {
+		rem = KSUCCESS;
+		errno = 0;
+		if (dest_realm == NULL)
+			dest_realm = krb_realmofhost(host);
+
+#ifdef CRYPT
+		if (doencrypt)
+			rem = krcmd_mutual(&host, sp->s_port, user, term, 0,
+			    dest_realm, &cred, schedule);
+		else
+#endif /* CRYPT */
+			rem = krcmd(&host, sp->s_port, user, term, 0,
+			    dest_realm);
+		if (rem < 0) {
+			use_kerberos = 0;
+			sp = getservbyname("login", "tcp");
+			if (sp == NULL) {
+				(void)fprintf(stderr,
+				    "rlogin: unknown service login/tcp.\n");
+				exit(1);
+			}
+			if (errno == ECONNREFUSED)
+				warning("remote host doesn't support Kerberos");
+			if (errno == ENOENT)
+				warning("can't provide Kerberos auth data");
+			goto try_connect;
+		}
+	} else {
+#ifdef CRYPT
+		if (doencrypt) {
+			(void)fprintf(stderr,
+			    "rlogin: the -x flag requires Kerberos authentication.\n");
+			exit(1);
+		}
+#endif /* CRYPT */
+		rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0);
+	}
+#else
+	rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0);
+#endif /* KERBEROS */
+
+	if (rem < 0)
+		exit(1);
+
+	/* Enable BSD compatibility for urgent data. */
+	tcpopt.nwto_flags= NWTO_BSD_URG;
+	error= ioctl(rem, NWIOSTCPOPT, &tcpopt);
+	if (error == -1)
+	{
+		fprintf(stderr, "rlogin: NWIOSTCPOPT failed: %s\n",
+			strerror(errno));
+	}
+
+	(void)setuid(uid);
+	doit();
+	/*NOTREACHED*/
+}
+
+struct termios defattr, rawattr;
+#if __minix_vmd
+int mustsendwindow;
+#else
+int child;
+#endif
+
+static void
+doit()
+{
+	struct termios sb;
+#if !__minix_vmd
+	int r;
+#else
+	asio_fd_set_t fd_set;
+	struct fwait fw;
+	int result;
+#endif
+
+	(void)tcgetattr(0, &sb);
+	defattr = sb;
+	rawattr = sb;
+
+	rawattr.c_iflag &= ~(ICRNL | IGNCR | INLCR | ISTRIP | IXOFF | IXON | 
+							PARMRK | IXANY);
+	rawattr.c_oflag &= ~(OPOST);
+	rawattr.c_lflag &= ~(ECHONL | ECHO | ICANON | IEXTEN | ISIG);
+
+	(void)signal(SIGINT, SIG_IGN);
+	setsignal(SIGHUP, exit);
+	setsignal(SIGQUIT, exit);
+
+#if !__minix_vmd
+	child = fork();
+	if (child == -1) {
+		(void)fprintf(stderr, "rlogin: fork: %s.\n", strerror(errno));
+		done(1);
+	}
+	if (child == 0) {
+		mode(1);
+		r = reader();
+		if (r == 0) {
+			msg("connection closed.");
+			exit(0);
+		}
+		sleep(1);
+		msg("\007connection closed.");
+		exit(1);
+	}
+
+	(void)signal(SIGCHLD, catch_child);
+	writer();
+
+#else /* __minix_vmd */
+
+	mode(1);
+	/* mark the file descriptors 0, 1, and rem as asynchronous. */
+	mark_async(0);
+	mark_async(1);
+	mark_async(rem);
+	init_0();
+	init_1();
+	init_rd_rem();
+	init_wr_rem();
+
+	for (;;)
+	{
+		ASIO_FD_ZERO(&fd_set);
+		fw.fw_flags= 0;
+		fw.fw_bits= fd_set.afds_bits;
+		fw.fw_maxfd= ASIO_FD_SETSIZE;
+
+		if (more2read_0 && !inprogress_0)
+		{
+			restart_0();
+			fw.fw_flags |= FWF_NONBLOCK;
+		}
+
+		if (more2write_1 && !inprogress_1)
+		{
+			restart_1();
+			fw.fw_flags |= FWF_NONBLOCK;
+		}
+
+		if (more2read_rem && !inprogress_rd_rem)
+		{
+			restart_rd_rem();
+			fw.fw_flags |= FWF_NONBLOCK;
+		}
+
+		if (more2write_rem && !inprogress_wr_rem)
+		{
+			restart_wr_rem();
+			fw.fw_flags |= FWF_NONBLOCK;
+		}
+
+		if (more2read_0 && inprogress_0)
+			ASIO_FD_SET(0, ASIO_READ, &fd_set);
+		if (more2write_1 && inprogress_1)
+			ASIO_FD_SET(1, ASIO_WRITE, &fd_set);
+		if (more2read_rem && inprogress_rd_rem)
+			ASIO_FD_SET(rem, ASIO_READ, &fd_set);
+		if (more2write_rem && inprogress_wr_rem)
+			ASIO_FD_SET(rem, ASIO_WRITE, &fd_set);
+
+		for (;;)
+		{
+			result= fwait(&fw);
+			if (result == -1 && (errno == EAGAIN || 
+							errno == EINTR))
+			{
+				break;
+			}
+			if (result == -1)
+			{
+				fprintf(stderr, "fwait failed (%s)\n", 
+							strerror(errno));
+				exit(1);
+			}
+			assert(result == 0);
+#if 0
+printf("fwait: fw_fw= %d, fw_operation= %d, fw_result= %d, fw.fw_errno= %d\n",
+	fw.fw_fd, fw.fw_operation, fw.fw_result, fw.fw_errno);
+#endif
+			if (fw.fw_fd == 0 && fw.fw_operation == ASIO_READ)
+			{
+				completed_0(fw.fw_result, fw.fw_errno);
+			}
+			else if (fw.fw_fd == 1 && 
+					fw.fw_operation == ASIO_WRITE)
+			{
+				completed_1(fw.fw_result, fw.fw_errno);
+			}
+			else if (fw.fw_fd == rem && 
+					fw.fw_operation == ASIO_READ)
+			{
+				completed_rd_rem(fw.fw_result, fw.fw_errno);
+			}
+			else if (fw.fw_fd == rem && 
+					fw.fw_operation == ASIO_WRITE)
+			{
+				completed_wr_rem(fw.fw_result, fw.fw_errno);
+			}
+			else
+			{
+				fprintf(stderr,
+			"strange result from fwait: fd= %d, operation= %d\n",
+					fw.fw_fd, fw.fw_operation);
+				exit(1);
+			}
+			if (!(fw.fw_flags & FWF_MORE))
+				break;
+		}
+		if (mustsendwindow)
+		{
+			mustsendwindow= 0;
+			sendwindow();
+		}
+	}
+#endif /* __minix_vmd */
+	msg("connection closed.");
+	done(0);
+}
+
+/* trap a signal, unless it is being ignored. */
+static void
+setsignal(sig, act)
+	int sig;
+	void (*act) _ARGS(( int sig ));
+{
+	if (signal(sig, act) == SIG_IGN)
+		(void)signal(sig, SIG_IGN);
+}
+
+static void
+done(status)
+	int status;
+{
+	int w, wstatus;
+
+	mode(0);
+#if !__minix_vmd
+	if (child > 0) {
+		/* make sure catch_child does not snap it up */
+		(void)signal(SIGCHLD, SIG_DFL);
+		if (kill(child, SIGKILL) >= 0)
+			while ((w = wait(&wstatus)) > 0 && w != child);
+	}
+#endif
+	exit(status);
+}
+
+int dosigwinch;
+#if !__minix
+void sigwinch();
+#endif
+
+#if !__minix_vmd
+static void
+catch_child(sig)
+	int sig;
+{
+	int status;
+	int pid;
+
+	for (;;) {
+		pid = waitpid(-1, &status, WNOHANG|WUNTRACED);
+		if (pid == 0)
+			return;
+		/* if the child (reader) dies, just quit */
+		if (pid < 0 || pid == child && !WIFSTOPPED(status))
+			done(WTERMSIG(status) | WEXITSTATUS(status));
+	}
+	/* NOTREACHED */
+}
+#endif
+
+#if !__minix_vmd
+/*
+ * writer: write to remote: 0 -> line.
+ * ~.				terminate
+ * ~^Z				suspend rlogin process.
+ * ~<delayed-suspend char>	suspend rlogin process, but leave reader alone.
+ */
+static void
+writer()
+{
+	register int bol, local, n;
+	u_char ch;
+	int c;
+
+	bol = 1;			/* beginning of line */
+	local = 0;
+	for (;;) {
+		n = read(STDIN_FILENO, &ch, 1);
+		if (n <= 0) {
+			if (n < 0 && errno == EINTR)
+				continue;
+			break;
+		}
+		c = ch;
+		/*
+		 * If we're at the beginning of the line and recognize a
+		 * command character, then we echo locally.  Otherwise,
+		 * characters are echo'd remotely.  If the command character
+		 * is doubled, this acts as a force and local echo is
+		 * suppressed.
+		 */
+		if (bol) {
+			bol = 0;
+			if (!noescape && c == escapechar) {
+				local = 1;
+				continue;
+			}
+		} else if (local) {
+			local = 0;
+			if (c == '.' || c == defattr.c_cc[VEOF]) {
+				echo(c);
+				break;
+			}
+#if !__minix
+			if (c == defattr.c_cc[VSUSP]) {
+				bol = 1;
+				echo(c);
+				stop(c);
+				continue;
+			}
+#endif
+			if (c != escapechar)
+#ifdef CRYPT
+#ifdef KERBEROS
+				if (doencrypt)
+					(void)des_write(rem, &escapechar, 1);
+				else
+#endif
+#endif
+					(void)write(rem, &escapechar, 1);
+		}
+
+		ch = c;
+#ifdef CRYPT
+#ifdef KERBEROS
+		if (doencrypt) {
+			if (des_write(rem, &ch, 1) == 0) {
+				msg("line gone");
+				break;
+			}
+		} else
+#endif
+#endif
+			if (write(rem, &ch, 1) == 0) {
+				msg("line gone");
+				break;
+			}
+		bol = c == defattr.c_cc[VKILL] ||
+		    c == defattr.c_cc[VEOF] ||
+		    c == defattr.c_cc[VINTR] ||
+		    c == defattr.c_cc[VSUSP] ||
+		    c == '\r' || c == '\n';
+	}
+}
+#endif
+
+#if !__minix_vmd
+static void
+echo(c)
+int c;
+{
+	register char *p;
+	char buf[8];
+
+	p = buf;
+	c &= 0177;
+	*p++ = escapechar;
+	if (c < ' ') {
+		*p++ = '^';
+		*p++ = c + '@';
+	} else if (c == 0177) {
+		*p++ = '^';
+		*p++ = '?';
+	} else
+		*p++ = c;
+	*p++ = '\r';
+	*p++ = '\n';
+	(void)write(STDOUT_FILENO, buf, p - buf);
+}
+#endif
+
+#if !__minix
+stop(cmdc)
+	char cmdc;
+{
+	mode(0);
+	(void)signal(SIGCHLD, SIG_IGN);
+	(void)kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
+	(void)signal(SIGCHLD, catch_child);
+	mode(1);
+	sigwinch();			/* check for size changes */
+}
+#endif
+
+#if __minix_vmd
+#ifdef SIGWINCH
+static void
+sigwinch(sig)
+	int sig;
+{
+	struct winsize ws;
+
+#if __minix
+	signal(SIGWINCH, sigwinch);
+#endif
+
+	if (dosigwinch && get_window_size(0, &ws) == 0 &&
+	    memcmp(&ws, &winsize, sizeof(ws))) {
+		winsize = ws;
+		mustsendwindow= 1;
+	}
+}
+
+/*
+ * Send the window size to the server via the magic escape
+ */
+static void
+sendwindow()
+{
+	struct winsize *wp;
+	char *obuf, *new_buf;
+
+	new_buf= realloc(extra_wr_rem_new, 
+					extra_wr_rem_new_size+4+sizeof(*wp));
+	if (new_buf == 0)
+		return;
+	extra_wr_rem_new= new_buf;
+	obuf= new_buf+extra_wr_rem_new_size;
+	extra_wr_rem_new_size += 4+sizeof(*wp);
+
+	more2read_0= 0;
+	more2write_rem= 1;
+
+	wp = (struct winsize *)(obuf+4);
+	obuf[0] = 0377;
+	obuf[1] = 0377;
+	obuf[2] = 's';
+	obuf[3] = 's';
+	wp->ws_row = htons(winsize.ws_row);
+	wp->ws_col = htons(winsize.ws_col);
+	wp->ws_xpixel = htons(winsize.ws_xpixel);
+	wp->ws_ypixel = htons(winsize.ws_ypixel);
+}
+#endif /* SIGWINCH */
+#endif
+
+#if !__minix_vmd
+/*
+ * reader: read from remote: line -> 1
+ */
+#define	READING	1
+#define	WRITING	2
+
+int rcvcnt, rcvstate;
+char rcvbuf[8 * 1024];
+
+static int
+reader()
+{
+	int pid = -getpid();
+	int n, remaining;
+	char *bufp = rcvbuf;
+
+	for (;;) {
+		while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
+			rcvstate = WRITING;
+			n = write(STDOUT_FILENO, bufp, remaining);
+			if (n < 0) {
+				if (errno != EINTR)
+					return(-1);
+				continue;
+			}
+			bufp += n;
+		}
+		bufp = rcvbuf;
+		rcvcnt = 0;
+		rcvstate = READING;
+
+#ifdef CRYPT
+#ifdef KERBEROS
+		if (doencrypt)
+			rcvcnt = des_read(rem, rcvbuf, sizeof(rcvbuf));
+		else
+#endif
+#endif
+			rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf));
+		if (rcvcnt == 0)
+			return (0);
+		if (rcvcnt < 0) {
+			if (errno == EINTR)
+				continue;
+			if (errno == EURG) {
+				nwio_tcpopt_t tcpopt;
+#if DEBUG
+fprintf(stderr, "\n\rEURG\n\r");
+#endif
+				tcpopt.nwto_flags= NWTO_RCV_URG;
+				if (ioctl(rem, NWIOSTCPOPT, &tcpopt) == -1) {
+					fprintf(stderr,
+				"rlogin: trouble with urgent data: %s\n",
+						strerror(errno));
+					return(-1);
+				}
+				continue;
+			}
+			if (errno == ENOURG) {
+				nwio_tcpopt_t tcpopt;
+#if DEBUG
+fprintf(stderr, "\n\rENOURG\n\r");
+#endif
+				tcpopt.nwto_flags= NWTO_RCV_NOTURG;
+				if (ioctl(rem, NWIOSTCPOPT, &tcpopt) == -1) {
+					fprintf(stderr,
+				"rlogin: trouble with not-urgent data: %s\n",
+						strerror(errno));
+					return(-1);
+				}
+				continue;
+			}
+			(void)fprintf(stderr, "rlogin: read: %s\n",
+				strerror(errno));
+			return(-1);
+		}
+	}
+}
+#endif  /* !__minix_vmd */
+
+static void
+mode(f)
+	int f;
+{
+	struct termios *sb;
+
+	switch(f) {
+	case 0:
+		sb= &defattr;
+		break;
+	case 1:
+		sb= &rawattr;
+		break;
+	default:
+		return;
+	}
+	(void)tcsetattr(0, TCSAFLUSH, sb);
+}
+
+static void
+lostpeer(sig)
+int sig;
+{
+	(void)signal(SIGPIPE, SIG_IGN);
+	msg("\007connection closed.");
+	done(1);
+}
+
+static void
+msg(str)
+	char *str;
+{
+	(void)fprintf(stderr, "rlogin: %s\r\n", str);
+}
+
+#ifdef KERBEROS
+/* VARARGS */
+warning(va_alist)
+va_dcl
+{
+	va_list ap;
+	char *fmt;
+
+	(void)fprintf(stderr, "rlogin: warning, using standard rlogin: ");
+	va_start(ap);
+	fmt = va_arg(ap, char *);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	(void)fprintf(stderr, ".\n");
+}
+#endif
+
+static void
+usage()
+{
+	(void)fprintf(stderr,
+	    "Usage: rlogin [-%s]%s[-e char] [-l username] host\n",
+#ifdef KERBEROS
+#ifdef CRYPT
+	    "8ELx", " [-k realm] ");
+#else
+	    "8EL", " [-k realm] ");
+#endif
+#else
+	    "8EL", " ");
+#endif
+	exit(1);
+}
+
+/*
+ * The following routine provides compatibility (such as it is) between 4.2BSD
+ * Suns and others.  Suns have only a `ttysize', so we convert it to a winsize.
+ */
+#ifdef sun
+get_window_size(fd, wp)
+	int fd;
+	struct winsize *wp;
+{
+	struct ttysize ts;
+	int error;
+
+	if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0)
+		return(error);
+	wp->ws_row = ts.ts_lines;
+	wp->ws_col = ts.ts_cols;
+	wp->ws_xpixel = 0;
+	wp->ws_ypixel = 0;
+	return(0);
+}
+#endif
+
+static u_char
+getescape(p)
+	register char *p;
+{
+	long val;
+	int len;
+
+	if ((len = strlen(p)) == 1)	/* use any single char, including '\' */
+		return((u_char)*p);
+					/* otherwise, \nnn */
+	if (*p == '\\' && len >= 2 && len <= 4) {
+		val = strtol(++p, (char **)NULL, 8);
+		for (;;) {
+			if (!*++p)
+				return((u_char)val);
+			if (*p < '0' || *p > '8')
+				break;
+		}
+	}
+	msg("illegal option value -- e");
+	usage();
+	/* NOTREACHED */
+}
+
+static char *
+speeds2str(speed)
+	speed_t speed;
+{
+	int i;
+	for (i= 0; speeds[i].name != NULL && speeds[i].speed != speed; i++) {
+		if (speeds[i].speed == speed) return speeds[i].name;
+	}
+	return "unknown";
+}
+
+#if __minix_vmd
+static void 
+mark_async(fd)
+	int fd;
+{
+	int result;
+	int v;
+
+	result= fcntl(fd, F_GETFD);
+	if (result == -1)
+	{
+		fprintf(stderr,
+			"rlogin: mark_async: fcntl(%d, GETFD) failed (%s)\n",
+			fd, strerror(errno));
+		exit(1);
+	}
+	v= result | FD_ASYNCHIO;
+	result= fcntl(fd, F_SETFD, v);
+	if (result == -1)
+	{
+		fprintf(stderr, 
+		"rlogin: mark_async: fcntl(%d, SETFD, %d) failed (%s)\n",
+			fd, v, strerror(errno));
+		exit(1);
+	}
+}
+
+#define RD_0_BUFSIZE	256
+char rd_0_buf[RD_0_BUFSIZE];
+size_t rd_0_offset;
+
+static void
+init_0()
+{
+	more2read_0= 1;
+	inprogress_0= 0;
+	rd_0_offset= 0;
+}
+
+size_t wr_1_size;
+size_t wr_1_offset;
+char *urg_1;
+size_t urg_1_size;
+char *extra_1;
+size_t extra_1_size;
+size_t extra_1_offset;
+char *extra_1_new;
+size_t extra_1_new_size;
+#define MAX_EXTRA_1_NEW_SIZE	(16*1024)
+
+static void
+init_1()
+{
+	more2write_1= 0;
+	inprogress_1= 0;
+	wr_1_size= 0;
+	wr_1_offset= 0;
+	urg_1= NULL;
+	urg_1_size= 0;
+	extra_1= NULL;
+	extra_1_size= 0;
+	extra_1_offset= 0;
+	extra_1_new= NULL;
+	extra_1_new_size= 0;
+}
+
+#define RD_REM_BUFSIZE	(8*1024)
+char rd_rem_buf[RD_REM_BUFSIZE];
+size_t rd_rem_offset;
+int rd_rem_urg;
+
+static void 
+init_rd_rem()
+{
+	more2read_rem= 1;
+	inprogress_rd_rem= 0;
+	rd_rem_offset= 0;
+	rd_rem_urg= 0;
+}
+
+static void 
+init_wr_rem()
+{
+	more2write_rem= 0;
+	inprogress_wr_rem= 0;
+	wr_rem_size= 0;
+	wr_rem_offset= 0;
+	extra_wr_rem_size= 0;
+	extra_wr_rem_offset= 0;
+	extra_wr_rem= NULL;
+	extra_wr_rem_new_size= 0;
+	extra_wr_rem_new= NULL;
+}
+
+static void
+restart_0()
+{
+	size_t offset;
+	int result, error;
+
+	assert(!inprogress_0);
+	rd_0_offset= 1;
+	offset= 0;
+	while (offset < RD_0_BUFSIZE)
+	{
+		result= read(0, rd_0_buf+rd_0_offset+offset,
+					RD_0_BUFSIZE-rd_0_offset-offset);
+		if (result > 0)
+		{
+			offset += result;
+			assert(rd_0_offset+offset <= RD_0_BUFSIZE);
+			continue;
+		}
+		error= errno;
+
+		if (offset != 0)
+			completed_0(offset, 0);
+		rd_0_offset += offset;
+		if (result == -1 && error == EINPROGRESS)
+		{
+			inprogress_0= 1;
+			return;
+		}
+		completed_0(result, error);
+		return;
+	}
+	completed_0(offset, 0);
+}
+
+static void 
+restart_1()
+{
+	size_t offset;
+	int result, error;
+
+	assert(!inprogress_1);
+
+	while (extra_1 != NULL || extra_1_new != NULL)
+	{
+		if (extra_1 == NULL)
+		{
+			extra_1= extra_1_new;
+			extra_1_new= NULL;
+			extra_1_size= extra_1_new_size;
+			extra_1_new_size= 0;
+			extra_1_offset= 0;
+		}
+		offset= 0;
+#if DEBUG
+		if (extra_1_size == 0)
+			fprintf(stderr, "restart_1: extra_1_size= 0\n");
+#endif
+		while (offset < extra_1_size)
+		{
+			result= write(1, extra_1+extra_1_offset+offset, 
+							extra_1_size-offset);
+			if (result > 0)
+			{
+				assert (result <= extra_1_size-offset);
+				offset += result;
+				continue;
+			}
+			error= errno;
+			if (offset != 0)
+				completed_1(offset, 0);
+
+			if (result == -1 && errno == EINPROGRESS)
+			{
+				inprogress_1= 1;
+				return;
+			}
+			completed_1(result, errno);
+			return;
+		}
+		completed_1(offset, 0);
+	}
+
+	offset= 0;
+
+	if (wr_1_size == 0)
+	{
+		more2write_1= 0;
+		more2read_rem= 1;
+		return;
+	}
+
+	while (offset < wr_1_size)
+	{
+		result= write(1, rd_rem_buf+wr_1_offset+offset, 
+							wr_1_size-offset);
+		if (result > 0)
+		{
+			assert (result <= wr_1_size-offset);
+			offset += result;
+			continue;
+		}
+		error= errno;
+		if (offset != 0)
+			completed_1(offset, 0);
+
+		if (result == -1 && errno == EINPROGRESS)
+		{
+			inprogress_1= 1;
+			return;
+		}
+		completed_1(result, errno);
+		return;
+	}
+	completed_1(offset, 0);
+}
+
+static void
+restart_rd_rem()
+{
+	size_t offset;
+	int result, error;
+
+	assert(!inprogress_rd_rem);
+	rd_rem_offset= 0;
+	offset= 0;
+	while (offset < RD_REM_BUFSIZE)
+	{
+		result= read(rem, rd_rem_buf+offset, RD_REM_BUFSIZE-offset);
+		if (result > 0)
+		{
+			offset += result;
+			assert(offset <= RD_REM_BUFSIZE);
+			continue;
+		}
+		error= errno;
+
+		if (offset != 0)
+			completed_rd_rem(offset, 0);
+		rd_rem_offset= offset;
+		if (result == -1 && error == EINPROGRESS)
+		{
+			inprogress_rd_rem= 1;
+			return;
+		}
+		completed_rd_rem(result, error);
+		return;
+	}
+	completed_rd_rem(offset, 0);
+}
+
+static void
+restart_wr_rem()
+{
+	size_t offset;
+	int result, error;
+
+	assert(!inprogress_wr_rem);
+
+	if (extra_wr_rem_new != NULL && extra_wr_rem == NULL)
+	{
+		extra_wr_rem= extra_wr_rem_new;
+		extra_wr_rem_size= extra_wr_rem_new_size;
+		extra_wr_rem_offset= 0;
+		extra_wr_rem_new= NULL;
+		extra_wr_rem_new_size= 0;
+	}
+	if (extra_wr_rem != NULL)
+	{
+		offset= 0;
+		while (offset < extra_wr_rem_size)
+		{
+			result= write(rem, 
+				extra_wr_rem+extra_wr_rem_offset+offset, 
+						extra_wr_rem_size-offset);
+			if (result > 0)
+			{
+				assert (result <= extra_wr_rem_size-offset);
+				offset += result;
+				continue;
+			}
+			error= errno;
+			if (offset != 0)
+				completed_wr_rem(offset, 0);
+
+			if (result == -1 && errno == EINPROGRESS)
+			{
+				inprogress_wr_rem= 1;
+				return;
+			}
+			completed_wr_rem(result, errno);
+			return;
+		}
+		completed_wr_rem(offset, 0);
+	}
+	if (wr_rem_size == 0)
+		return;
+
+	offset= 0;
+	while (offset < wr_rem_size)
+	{
+		result= write(rem, rd_0_buf+wr_rem_offset+offset, 
+							wr_rem_size-offset);
+		if (result > 0)
+		{
+			assert (result <= wr_rem_size-offset);
+			offset += result;
+			continue;
+		}
+		error= errno;
+		if (offset != 0)
+			completed_wr_rem(offset, 0);
+
+		if (result == -1 && errno == EINPROGRESS)
+		{
+			inprogress_wr_rem= 1;
+			return;
+		}
+		completed_wr_rem(result, errno);
+		return;
+	}
+	completed_wr_rem(offset, 0);
+}
+
+static void
+completed_0(result, error)
+	int result;
+	int error;
+{
+	static int bol= 0, local= 0;
+
+	char *iptr, *optr;
+	int i;
+	u_char c;
+
+	inprogress_0= 0;
+
+	if (result > 0)
+	{
+		assert(rd_0_offset > 0);
+		wr_rem_offset= 1;
+
+		iptr= rd_0_buf+rd_0_offset;
+		optr= rd_0_buf+wr_rem_offset;
+		for (i= 0; i<result; iptr++, i++)
+		{
+			c= *iptr;
+			if (bol)
+			{
+				bol= 0;
+				if (!noescape && c == escapechar)
+				{
+					local= 1;
+					continue;
+				}
+			}
+			else if (local)
+			{
+				local= 0;
+				if (c == '.' || (c != _POSIX_VDISABLE &&
+					c == defattr.c_cc[VEOF]))
+				{
+					echo(c);
+					finish();
+					/* NOTREACHED */
+				}
+				if (c == '!')
+				{
+					subshell();
+					continue;
+				}
+				if (c != escapechar)
+				{
+					if (optr < iptr)
+					{
+						*(optr++)= escapechar;
+					}
+					else
+					{
+						assert(optr == iptr);
+						assert(iptr == rd_0_buf+
+								rd_0_offset);
+						assert(rd_0_offset > 0);
+						wr_rem_offset--;
+						optr[-1]= escapechar;
+					}
+				}
+			}
+			*(optr++)= c;
+			bol= (c != _POSIX_VDISABLE) && 
+				(c == defattr.c_cc[VKILL] ||
+				c == defattr.c_cc[VEOF] ||
+				c == defattr.c_cc[VINTR] ||
+				c == defattr.c_cc[VSUSP] ||
+				c == '\r' || c == '\n');
+		}
+		wr_rem_size += optr-rd_0_buf-wr_rem_offset;
+		if (wr_rem_size != 0)
+		{
+			more2read_0= 0;
+			more2write_rem= 1;
+		}
+		return;
+	} else
+	if (result < 0) {
+		fprintf(stderr, "rlogin: %s\n", strerror(error));
+	}
+	done(1);
+}
+
+static void
+completed_1(result, error)
+	int result;
+	int error;
+{
+	inprogress_1= 0;
+
+	if (result > 0)
+	{
+		if (extra_1 != NULL)
+		{
+			assert (result <= extra_1_size);
+			extra_1_size -= result;
+			extra_1_offset += result;
+			if (extra_1_size == 0)
+			{
+				more2write_1= 0;
+				more2read_rem= 1;
+				free(extra_1);
+				extra_1= NULL;
+			}
+			return;
+		}
+		assert (result <= wr_1_size);
+		wr_1_size -= result;
+		wr_1_offset += result;
+		if (wr_1_size == 0)
+		{
+			more2write_1= 0;
+			more2read_rem= 1;
+		}
+		return;
+	} else
+	if (result < 0) {
+		fprintf(stderr, "rlogin: %s\n", strerror(error));
+	}
+	done(1);
+}
+
+static void
+completed_rd_rem(result, error)
+	int result;
+	int error;
+{
+	nwio_tcpopt_t tcpopt;
+	char *new_buf;
+	size_t keep_size;
+	u_char urg_byte;
+	int i;
+
+	inprogress_rd_rem= 0;
+
+	if (result > 0)
+	{
+		if (rd_rem_urg)
+		{
+#if DEBUG
+fprintf(stderr, "\n\r%d urg bytes\n\r", result);
+#endif
+			if (urg_1_size > MAX_EXTRA_1_NEW_SIZE)
+			{
+				keep_size= MAX_EXTRA_1_NEW_SIZE/2;
+				memmove(urg_1, urg_1+urg_1_size-keep_size, 
+					keep_size);
+				urg_1_size= keep_size;
+			}
+			new_buf= realloc(urg_1, urg_1_size+result);
+			if (new_buf == NULL)
+			{
+				fprintf(stderr, 
+					"rlogin: warning realloc %d failed\n",
+					urg_1_size+result);
+				return;
+			}
+			memcpy(new_buf+urg_1_size, 
+				rd_rem_buf+rd_rem_offset, result);
+			urg_1= new_buf;
+			urg_1_size += result;
+			return;
+		}
+		more2read_rem= 0;
+		more2write_1= 1;
+		wr_1_size= result;
+		wr_1_offset= rd_rem_offset;
+		return;
+	}
+	if (result == -1 && error == EURG)
+	{
+#if DEBUG
+fprintf(stderr, "\n\rEURG\n\r");
+#endif
+		rd_rem_urg= 1;
+		tcpopt.nwto_flags= NWTO_RCV_URG;
+		result= ioctl(rem, NWIOSTCPOPT, &tcpopt);
+		if (result == -1)
+		{
+			fprintf(stderr, 
+				"rlogin: NWIOSTCPOPT on %d failed (%s)\n",
+				rem, strerror(errno));
+			exit(1);
+		}
+		return;
+	}
+	if (result == -1 && error == ENOURG)
+	{
+#if DEBUG
+fprintf(stderr, "\n\rENOURG\n\r");
+#endif
+		rd_rem_urg= 0;
+		tcpopt.nwto_flags= NWTO_RCV_NOTURG;
+		result= ioctl(rem, NWIOSTCPOPT, &tcpopt);
+		if (result == -1)
+		{
+			fprintf(stderr, 
+				"rlogin: NWIOSTCPOPT on %d failed (%s)\n",
+				rem, strerror(errno));
+			exit(1);
+		}
+		if (urg_1_size != 0)
+		{
+			urg_byte= urg_1[urg_1_size-1];
+			urg_1_size--;
+			do_urg(urg_byte);
+			if (urg_1_size == 0)
+				return;
+			if (extra_1_new_size + urg_1_size > MAX_EXTRA_1_NEW_SIZE)
+			{
+				extra_1_new_size= 0;
+				free(extra_1_new);
+				extra_1_new= NULL;
+			}
+			if (extra_1_new_size != 0)
+			{
+				new_buf= realloc(extra_1_new, 
+					extra_1_new_size+urg_1_size);
+				if (new_buf == 0)
+				{
+					extra_1_new_size= 0;
+					free(extra_1_new);
+					extra_1_new= NULL;
+				}
+				else
+				{
+					extra_1_new= new_buf;
+					memcpy(extra_1_new+extra_1_new_size,
+						urg_1, urg_1_size);
+					extra_1_new_size += urg_1_size;
+					urg_1_size= 0;
+					free(urg_1);
+					urg_1= NULL;
+				}
+			}
+			if (extra_1_new_size == 0)
+			{
+				extra_1_new_size= urg_1_size;
+				extra_1_new= urg_1;
+				urg_1_size= 0;
+				urg_1= NULL;
+			}
+			more2read_rem= 0;
+			more2write_1= 1;
+		}
+		return;
+	}
+	if (result == -1 && error == EINTR)
+	{
+		/* Never mind. */
+		return;
+	}
+	if (result == 0)
+	{
+		msg("connection closed.");
+		done(0);
+	}
+	if (result < 0) {
+		fprintf(stderr, "rlogin: %s\n", strerror(error));
+	}
+	done(1);
+}
+
+static void
+completed_wr_rem(result, error)
+	int result;
+	int error;
+{
+	inprogress_wr_rem= 0;
+
+	if (result > 0)
+	{
+		if (extra_wr_rem != NULL)
+		{
+			assert (result <= extra_wr_rem_size);
+			extra_wr_rem_size -= result;
+			extra_wr_rem_offset += result;
+			if (extra_wr_rem_size == 0)
+			{
+				free(extra_wr_rem);
+				extra_wr_rem= NULL;
+				if (wr_rem_size == 0)
+				{
+					more2write_rem= 0;
+					more2read_0= 1;
+				}
+			}
+			return;
+		}
+
+		assert (result <= wr_rem_size);
+		wr_rem_size -= result;
+		wr_rem_offset += result;
+		if (wr_rem_size == 0)
+		{
+			more2write_rem= 0;
+			more2read_0= 1;
+		}
+		return;
+	}
+	if (result < 0) {
+		fprintf(stderr, "rlogin: %s\n", strerror(error));
+	}
+	done(1);
+}
+
+static void
+do_urg(urg_byte)
+	int urg_byte;
+{
+#if DEBUG
+	fprintf(stderr, "rlogin: warning got urg_byte 0x%x\r\n", urg_byte);
+#endif
+	if (urg_byte & TIOCPKT_WINDOW)
+	{
+		if (dosigwinch == 0)
+		{
+			sendwindow();
+			signal(SIGWINCH, sigwinch);
+		}
+		dosigwinch= 1;
+	}
+}
+
+static void
+echo(c)
+	int c;
+{
+	u_char c1;
+	char *new_buf;
+
+	new_buf= realloc(extra_1_new, extra_1_new_size+6);
+	if (new_buf == NULL)
+		return;
+	extra_1_new= new_buf;
+	new_buf= extra_1_new+extra_1_new_size;
+
+	c1= escapechar;
+	if (c1 < ' ')
+	{
+		*new_buf++= '^';
+		*new_buf++= c1 + '@';
+	}
+	else if (c1 == 0x7f)
+	{
+		*new_buf++= '^';
+		*new_buf++= '?';
+	}
+	else
+		*new_buf++= c1;
+
+	if (c < ' ')
+	{
+		*new_buf++= '^';
+		*new_buf++= c + '@';
+	}
+	else if (c == 0x7f)
+	{
+		*new_buf++= '^';
+		*new_buf++= '?';
+	}
+	else
+		*new_buf++= c;
+
+	*new_buf++= '\r';
+	*new_buf++= '\n';
+	extra_1_new_size= new_buf-extra_1_new;
+	more2write_1= 1;
+}
+
+static void
+finish()
+{
+	done(0);
+}
+
+static char cmdbuf[256];
+
+static void
+subshell()
+{
+	/* Start a subshell. Based on the first character of the command,
+	 * the tcp connection will be present at fd 3 ('+'), or at
+	 * fd 0 and fd 1 ('=')
+	 */
+	int r, pid, stat, len;
+	char *shell, *cmd;
+
+	/* cancel the reads and writes that are in progress. */
+	if (inprogress_0)
+	{
+		r= fcancel(0, ASIO_READ);
+		if (r != 0) abort();
+	}
+	if (inprogress_1)
+	{
+		r= fcancel(1, ASIO_WRITE);
+		if (r != 0) abort();
+	}
+	if (inprogress_rd_rem)
+	{
+		r= fcancel(rem, ASIO_READ);
+		if (r != 0) abort();
+	}
+	if (inprogress_wr_rem)
+	{
+		r= fcancel(rem, ASIO_WRITE);
+		if (r != 0) abort();
+	}
+
+	mode(0);
+
+	pid= fork();
+	if (pid == -1) abort();
+	if (pid != 0)
+	{
+		r= waitpid(pid, &stat, 0);
+		if (r != pid) abort();
+
+#if DEBUG
+		fprintf(stderr, "stat: 0x%x\n", stat);
+#endif
+		mode(1);
+		return;
+	}
+
+	(void)signal(SIGINT, SIG_DFL);
+
+	shell= getenv("SHELL");
+	if (shell == NULL)
+		shell= "/bin/sh";
+	printf("~!\ncommand [%s]: ", shell);
+	cmd= fgets(cmdbuf, sizeof(cmdbuf), stdin);
+	if (cmd == NULL)
+		exit(0);
+#if DEBUG
+	printf("got command '%s'\n", cmd);
+#endif
+
+	/* Strip the trailing newline */
+	len= strlen(cmd);
+	if (len > 0 && cmd[len-1] == '\n')
+		cmd[len-1]= '\0';
+	else
+		printf("\n");
+
+	/* Skip leading white space */
+	while (*cmd != '\0' && isspace(*cmd))
+		cmd++;
+
+	if (*cmd == '+')
+	{
+		if (rem != 3)
+		{
+			dup2(rem, 3);
+			close(rem);
+		}
+		cmd++;
+	}
+	else if (*cmd == '=')
+	{
+		dup2(rem, 0);
+		dup2(rem, 1);
+		close(rem);
+		cmd++;
+	}
+	else
+		close(rem);
+	if (*cmd == '\0')
+	{
+		r= execl(shell, shell, NULL);
+	}
+	else
+	{
+		r= execl("/bin/sh", "sh", "-c", cmd, NULL);
+	}
+	printf("exec failed: %d, %d\n", r, errno);
+	exit(0);
+}
+#endif /* __minix_vmd */
Index: /trunk/minix/commands/simple/rmdir.c
===================================================================
--- /trunk/minix/commands/simple/rmdir.c	(revision 9)
+++ /trunk/minix/commands/simple/rmdir.c	(revision 9)
@@ -0,0 +1,46 @@
+/*	rmdir - remove directory.		Author:  Kees J. Bot
+ */
+#define nil 0
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+void tell(char *what)
+{
+	write(2, what, strlen(what));
+}
+
+void report(char *label)
+{
+	char *err= strerror(errno);
+
+	tell("rmdir: ");
+	tell(label);
+	tell(": ");
+	tell(err);
+	tell("\n");
+}
+
+int main(int argc, char **argv)
+{
+	int i, ex= 0;
+
+	if (argc < 2) {
+		tell("Usage: rmdir directory ...\n");
+		exit(1);
+	}
+
+	i=1;
+	do {
+		if (rmdir(argv[i]) < 0) {
+			report(argv[i]);
+			ex= 1;
+		}
+	} while (++i < argc);
+
+	exit(ex);
+}
+/* Kees J. Bot  27-12-90. */
Index: /trunk/minix/commands/simple/rsh.c
===================================================================
--- /trunk/minix/commands/simple/rsh.c	(revision 9)
+++ /trunk/minix/commands/simple/rsh.c	(revision 9)
@@ -0,0 +1,567 @@
+/*-
+ * Copyright (c) 1983, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rsh.c	5.24 (Berkeley) 7/1/91";
+#endif /* not lint */
+
+/*
+ * $Source: /cvsup/minix/src/commands/simple/rsh.c,v $
+ * $Header: /cvsup/minix/src/commands/simple/rsh.c,v 1.2 2005/06/17 13:42:53 beng Exp $
+ */
+
+#if _MINIX
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <net/netlib.h>
+#include <net/gen/netdb.h>
+void main _ARGS(( int argc, char *argv[] ));
+void usage _ARGS(( void ));
+char *copyargs _ARGS(( char **argv ));
+void sendsig _ARGS(( int signo ));
+void talk _ARGS(( int nflag, long omask, int pid, int rem ));
+
+#define _PATH_RLOGIN1	"/bin/rlogin"
+#define _PATH_RLOGIN2	"/usr/bin/rlogin"
+
+#else
+#include <sys/types.h>
+#include <sys/signal.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <pwd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <varargs.h>
+#include "pathnames.h"
+#endif
+
+#ifdef KERBEROS
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+
+CREDENTIALS cred;
+Key_schedule schedule;
+int use_kerberos = 1, doencrypt;
+char dst_realm_buf[REALM_SZ], *dest_realm;
+extern char *krb_realmofhost();
+#endif
+
+/*
+ * rsh - remote shell
+ */
+extern int errno;
+int rfd2;
+
+void
+main(argc, argv)
+	int argc;
+	char **argv;
+{
+	extern char *optarg;
+	extern int optind;
+	struct passwd *pw;
+	struct servent *sp;
+	long omask;
+	int argoff, asrsh, ch, dflag, nflag, one, pid, rem, uid;
+	register char *p;
+	char *args, *host, *user;
+#if !_MINIX
+	char *copyargs();
+	void sendsig();
+#endif
+
+	argoff = asrsh = dflag = nflag = 0;
+	one = 1;
+	host = user = NULL;
+
+	/* if called as something other than "rsh", use it as the host name */
+	if (p = rindex(argv[0], '/'))
+		++p;
+	else
+		p = argv[0];
+	if (strcmp(p, "rsh"))
+		host = p;
+	else
+		asrsh = 1;
+
+	/* handle "rsh host flags" */
+	if (!host && argc > 2 && argv[1][0] != '-') {
+		host = argv[1];
+		argoff = 1;
+	}
+
+#ifdef KERBEROS
+#ifdef CRYPT
+#define	OPTIONS	"8KLdek:l:nwx"
+#else
+#define	OPTIONS	"8KLdek:l:nw"
+#endif
+#else
+#define	OPTIONS	"8KLdel:nw"
+#endif
+	while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
+		switch(ch) {
+		case 'K':
+#ifdef KERBEROS
+			use_kerberos = 0;
+#endif
+			break;
+		case 'L':	/* -8Lew are ignored to allow rlogin aliases */
+		case 'e':
+		case 'w':
+		case '8':
+			break;
+		case 'd':
+			dflag = 1;
+			break;
+		case 'l':
+			user = optarg;
+			break;
+#ifdef KERBEROS
+		case 'k':
+			dest_realm = dst_realm_buf;
+			strncpy(dest_realm, optarg, REALM_SZ);
+			break;
+#endif
+		case 'n':
+			nflag = 1;
+			break;
+#ifdef KERBEROS
+#ifdef CRYPT
+		case 'x':
+			doencrypt = 1;
+			des_set_key(cred.session, schedule);
+			break;
+#endif
+#endif
+		case '?':
+		default:
+			usage();
+		}
+	optind += argoff;
+
+	/* if haven't gotten a host yet, do so */
+	if (!host && !(host = argv[optind++]))
+		usage();
+
+	/* if no further arguments, must have been called as rlogin. */
+	if (!argv[optind]) {
+		if (asrsh)
+			*argv = "rlogin";
+		execv(_PATH_RLOGIN1, argv);
+		execv(_PATH_RLOGIN2, argv);
+		(void)fprintf(stderr, "rsh: can't exec rlogin\n");
+		exit(1);
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	if (!(pw = getpwuid(uid = getuid()))) {
+		(void)fprintf(stderr, "rsh: unknown user id.\n");
+		exit(1);
+	}
+	if (!user)
+		user = pw->pw_name;
+
+#ifdef KERBEROS
+#ifdef CRYPT
+	/* -x turns off -n */
+	if (doencrypt)
+		nflag = 0;
+#endif
+#endif
+
+	args = copyargs(argv);
+
+	sp = NULL;
+#ifdef KERBEROS
+	if (use_kerberos) {
+		sp = getservbyname((doencrypt ? "ekshell" : "kshell"), "tcp");
+		if (sp == NULL) {
+			use_kerberos = 0;
+			warning("can't get entry for %s/tcp service",
+			    doencrypt ? "ekshell" : "kshell");
+		}
+	}
+#endif
+	if (sp == NULL)
+		sp = getservbyname("shell", "tcp");
+	if (sp == NULL) {
+		(void)fprintf(stderr, "rsh: shell/tcp: unknown service.\n");
+		exit(1);
+	}
+
+#ifdef KERBEROS
+try_connect:
+	if (use_kerberos) {
+		rem = KSUCCESS;
+		errno = 0;
+		if (dest_realm == NULL)
+			dest_realm = krb_realmofhost(host);
+
+#ifdef CRYPT
+		if (doencrypt)
+			rem = krcmd_mutual(&host, sp->s_port, user, args,
+			    &rfd2, dest_realm, &cred, schedule);
+		else
+#endif
+			rem = krcmd(&host, sp->s_port, user, args, &rfd2,
+			    dest_realm);
+		if (rem < 0) {
+			use_kerberos = 0;
+			sp = getservbyname("shell", "tcp");
+			if (sp == NULL) {
+				(void)fprintf(stderr,
+				    "rsh: unknown service shell/tcp.\n");
+				exit(1);
+			}
+			if (errno == ECONNREFUSED)
+				warning("remote host doesn't support Kerberos");
+			if (errno == ENOENT)
+				warning("can't provide Kerberos auth data");
+			goto try_connect;
+		}
+	} else {
+		if (doencrypt) {
+			(void)fprintf(stderr,
+			    "rsh: the -x flag requires Kerberos authentication.\n");
+			exit(1);
+		}
+		rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
+	}
+#else
+	rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
+#endif
+
+	if (rem < 0)
+		exit(1);
+
+	if (rfd2 < 0) {
+		(void)fprintf(stderr, "rsh: can't establish stderr.\n");
+		exit(1);
+	}
+#if !_MINIX
+	if (dflag) {
+		if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one,
+		    sizeof(one)) < 0)
+			(void)fprintf(stderr, "rsh: setsockopt: %s.\n",
+			    strerror(errno));
+		if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one,
+		    sizeof(one)) < 0)
+			(void)fprintf(stderr, "rsh: setsockopt: %s.\n",
+			    strerror(errno));
+	}
+#endif
+
+	(void)setuid(uid);
+#if !_MINIX
+	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM));
+#endif
+	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+		(void)signal(SIGINT, sendsig);
+	if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+		(void)signal(SIGQUIT, sendsig);
+	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
+		(void)signal(SIGTERM, sendsig);
+
+	if (!nflag) {
+		pid = fork();
+		if (pid < 0) {
+			(void)fprintf(stderr,
+			    "rsh: fork: %s.\n", strerror(errno));
+			exit(1);
+		}
+	}
+
+#ifdef KERBEROS
+#ifdef CRYPT
+	if (!doencrypt)
+#endif
+#endif
+	{
+#if _MINIX
+		;
+#else
+		(void)ioctl(rfd2, FIONBIO, &one);
+		(void)ioctl(rem, FIONBIO, &one);
+#endif
+	}
+
+	talk(nflag, omask, pid, rem);
+
+	if (!nflag && pid)
+	{
+#if DEBUG
+		printf("killing %d with %d\n", pid, SIGKILL);
+#endif
+		(void)kill(pid, SIGKILL);
+	}
+	exit(0);
+}
+
+void
+talk(nflag, omask, pid, rem)
+	int nflag, pid;
+	long omask;
+	register int rem;
+{
+	register int cc, wc;
+	register char *bp;
+	int readfrom, ready, rembits;
+	char buf[BUFSIZ];
+#if _MINIX
+	int pid1;
+#endif
+
+	if (!nflag && pid == 0) {
+		(void)close(rfd2);
+
+reread:		errno = 0;
+		if ((cc = read(0, buf, sizeof buf)) <= 0)
+			goto done;
+		bp = buf;
+
+rewrite:
+#if !_MINIX
+		rembits = 1 << rem;
+		if (select(16, 0, &rembits, 0, 0) < 0) {
+			if (errno != EINTR) {
+				(void)fprintf(stderr,
+				    "rsh: select: %s.\n", strerror(errno));
+				exit(1);
+			}
+			goto rewrite;
+		}
+		if ((rembits & (1 << rem)) == 0)
+			goto rewrite;
+#endif
+#ifdef KERBEROS
+#ifdef CRYPT
+		if (doencrypt)
+			wc = des_write(rem, bp, cc);
+		else
+#endif
+#endif
+			wc = write(rem, bp, cc);
+		if (wc < 0) {
+#if !_MINIX
+			if (errno == EWOULDBLOCK)
+				goto rewrite;
+#endif
+			goto done;
+		}
+		bp += wc;
+		cc -= wc;
+		if (cc == 0)
+			goto reread;
+		goto rewrite;
+done:
+#if _MINIX
+		ioctl(rem, NWIOTCPSHUTDOWN, NULL);
+#else
+		(void)shutdown(rem, 1);
+#endif
+		exit(0);
+	}
+
+#if _MINIX
+	pid1= fork();
+	if (pid1 == -1)
+	{
+		(void)fprintf(stderr, "rsh: fork: %s.\n", strerror(errno));
+		exit(1);
+	}
+	close (pid1 ? rfd2 : rem);
+	for(;;)
+	{
+		errno = 0;
+		cc = read(pid1 ? rem : rfd2, buf, sizeof buf);
+		if (cc <= 0)
+		{
+			if (pid1)
+			{
+#if DEBUG
+				printf("killing %d with %d\n", pid1, SIGKILL);
+#endif
+				kill(pid1, SIGKILL);
+				return;
+			}
+			exit(0);
+		}
+		(void)write(pid1 ? 1 : 2, buf, cc);
+	}
+#else
+	(void)sigsetmask(omask);
+	readfrom = (1 << rfd2) | (1 << rem);
+	do {
+		ready = readfrom;
+		if (select(16, &ready, 0, 0, 0) < 0) {
+			if (errno != EINTR) {
+				(void)fprintf(stderr,
+				    "rsh: select: %s.\n", strerror(errno));
+				exit(1);
+			}
+			continue;
+		}
+		if (ready & (1 << rfd2)) {
+			errno = 0;
+#ifdef KERBEROS
+#ifdef CRYPT
+			if (doencrypt)
+				cc = des_read(rfd2, buf, sizeof buf);
+			else
+#endif
+#endif
+				cc = read(rfd2, buf, sizeof buf);
+			if (cc <= 0) {
+				if (errno != EWOULDBLOCK)
+					readfrom &= ~(1 << rfd2);
+			} else
+				(void)write(2, buf, cc);
+		}
+		if (ready & (1 << rem)) {
+			errno = 0;
+#ifdef KERBEROS
+#ifdef CRYPT
+			if (doencrypt)
+				cc = des_read(rem, buf, sizeof buf);
+			else
+#endif
+#endif
+				cc = read(rem, buf, sizeof buf);
+			if (cc <= 0) {
+				if (errno != EWOULDBLOCK)
+					readfrom &= ~(1 << rem);
+			} else
+				(void)write(1, buf, cc);
+		}
+	} while (readfrom);
+#endif
+}
+
+void
+sendsig(signo)
+	char signo;
+{
+#ifdef KERBEROS
+#ifdef CRYPT
+	if (doencrypt)
+		(void)des_write(rfd2, &signo, 1);
+	else
+#endif
+#endif
+		(void)write(rfd2, &signo, 1);
+}
+
+#ifdef KERBEROS
+/* VARARGS */
+warning(va_alist)
+va_dcl
+{
+	va_list ap;
+	char *fmt;
+
+	(void)fprintf(stderr, "rsh: warning, using standard rsh: ");
+	va_start(ap);
+	fmt = va_arg(ap, char *);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	(void)fprintf(stderr, ".\n");
+}
+#endif
+
+char *
+copyargs(argv)
+	char **argv;
+{
+	register int cc;
+	register char **ap, *p;
+	char *args;
+#if !_MINIX
+	char *malloc();
+#endif
+
+	cc = 0;
+	for (ap = argv; *ap; ++ap)
+		cc += strlen(*ap) + 1;
+	if (!(args = malloc((u_int)cc))) {
+		(void)fprintf(stderr, "rsh: %s.\n", strerror(ENOMEM));
+		exit(1);
+	}
+	for (p = args, ap = argv; *ap; ++ap) {
+		(void)strcpy(p, *ap);
+		for (p = strcpy(p, *ap); *p; ++p);
+		if (ap[1])
+			*p++ = ' ';
+	}
+	return(args);
+}
+
+void
+usage()
+{
+	(void)fprintf(stderr,
+	    "usage: rsh [-nd%s]%s[-l login] host [command]\n",
+#ifdef KERBEROS
+#ifdef CRYPT
+	    "x", " [-k realm] ");
+#else
+	    "", " [-k realm] ");
+#endif
+#else
+	    "", " ");
+#endif
+	exit(1);
+}
Index: /trunk/minix/commands/simple/sed.c
===================================================================
--- /trunk/minix/commands/simple/sed.c	(revision 9)
+++ /trunk/minix/commands/simple/sed.c	(revision 9)
@@ -0,0 +1,1613 @@
+/* sed - stream editor		Author: Eric S. Raymond */
+
+/* This used to be three different files with the following makefile:
+ * (Note the chmem).
+
+CFLAGS=	-F -T.
+
+OBJS=   sedcomp.s sedexec.s
+
+sed: 	$(OBJS)
+        cc -T. -o sed $(OBJS)
+  @chmem =13312 sed
+
+$(OBJS):	sed.h
+
+ * If you want longer lines: increase MAXBUF.
+ * If you want scripts with more text: increase POOLSIZE.
+ * If you want more commands per script: increase MAXCMDS.
+ */
+
+#include <ctype.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+/*+++++++++++++++*/
+
+/* Sed.h -- types and constants for the stream editor */
+
+/* Data area sizes used by both modules */
+#define MAXBUF		4000	/* current line buffer size */
+#define MAXAPPENDS	20	/* maximum number of appends */
+#define MAXTAGS		9	/* tagged patterns are \1 to \9 */
+
+/* Constants for compiled-command representation */
+#define EQCMD	0x01		/* = -- print current line number	 */
+#define ACMD	0x02		/* a -- append text after current line	 */
+#define BCMD	0x03		/* b -- branch to label			 */
+#define CCMD	0x04		/* c -- change current line		 */
+#define DCMD	0x05		/* d -- delete all of pattern space */
+#define CDCMD	0x06		/* D -- delete first line of pattern space */
+#define GCMD	0x07		/* g -- copy hold space to pattern space */
+#define CGCMD	0x08		/* G -- append hold space to pattern space */
+#define HCMD	0x09		/* h -- copy pattern space to hold space */
+#define CHCMD	0x0A		/* H -- append pattern space to hold space */
+#define ICMD	0x0B		/* i -- insert text before current line	 */
+#define LCMD	0x0C		/* l -- print pattern space in escaped form */
+#define NCMD	0x0D		/* n -- get next line into pattern space */
+#define CNCMD	0x0E		/* N -- append next line to pattern space */
+#define PCMD	0x0F		/* p -- print pattern space to output	 */
+#define CPCMD	0x10		/* P -- print first line of pattern space */
+#define QCMD	0x11		/* q -- exit the stream editor		 */
+#define RCMD	0x12		/* r -- read in a file after current line */
+#define SCMD	0x13		/* s -- regular-expression substitute	 */
+#define TCMD	0x14		/* t -- branch on any substitute successful */
+#define CTCMD	0x15		/* T -- branch on any substitute failed	 */
+#define WCMD	0x16		/* w -- write pattern space to file	 */
+#define CWCMD	0x17		/* W -- write first line of pattern space */
+#define XCMD	0x18		/* x -- exhange pattern and hold spaces	 */
+#define YCMD	0x19		/* y -- transliterate text		 */
+
+struct cmd_t {			/* compiled-command representation */
+  char *addr1;			/* first address for command */
+  char *addr2;			/* second address for command */
+  union {
+	char *lhs;		/* s command lhs */
+	struct cmd_t *link;	/* label link */
+  } u;
+  char command;			/* command code */
+  char *rhs;			/* s command replacement string */
+  FILE *fout;			/* associated output file descriptor */
+  struct {
+	char allbut;		/* was negation specified? */
+	char global;		/* was g postfix specified? */
+	char print;		/* was p postfix specified? */
+	char inrange;		/* in an address range? */
+  } flags;
+};
+typedef struct cmd_t sedcmd;	/* use this name for declarations */
+
+#define BAD	((char *) -1)	/* guaranteed not a string ptr */
+
+
+
+/* Address and regular expression compiled-form markers */
+#define STAR	1		/* marker for Kleene star */
+#define CCHR	2		/* non-newline character to be matched
+			 * follows */
+#define CDOT	4		/* dot wild-card marker */
+#define CCL	6		/* character class follows */
+#define CNL	8		/* match line start */
+#define CDOL	10		/* match line end */
+#define CBRA	12		/* tagged pattern start marker */
+#define CKET	14		/* tagged pattern end marker */
+#define CBACK	16		/* backslash-digit pair marker */
+#define CLNUM	18		/* numeric-address index follows */
+#define CEND	20		/* symbol for end-of-source */
+#define CEOF	22		/* end-of-field mark */
+
+/* Sed.h ends here */
+
+#ifndef CMASK
+#define CMASK  0xFF		/* some char type should have been unsigned
+			 * char? */
+#endif
+
+/*+++++++++++++++*/
+
+/* Sed - stream editor		Author: Eric S. Raymond */
+
+/*
+   The stream editor compiles its command input	 (from files or -e options)
+   into an internal form using compile() then executes the compiled form using
+   execute(). Main() just initializes data structures, interprets command line
+   options, and calls compile() and execute() in appropriate sequence.
+
+   The data structure produced by compile() is an array of compiled-command
+   structures (type sedcmd).  These contain several pointers into pool[], the
+   regular-expression and text-data pool, plus a command code and g & p flags.
+   In the special case that the command is a label the struct  will hold a ptr
+   into the labels array labels[] during most of the compile,  until resolve()
+   resolves references at the end.
+
+   The operation of execute() is described in its source module.
+*/
+
+/* #include <stdio.h> */
+/* #include "sed.h"   */
+
+/* Imported functions */
+
+/***** public stuff ******/
+
+#define MAXCMDS		500	/* maximum number of compiled commands */
+#define MAXLINES	256	/* max # numeric addresses to compile */
+
+/* Main data areas */
+char linebuf[MAXBUF + 1];	/* current-line buffer */
+sedcmd cmds[MAXCMDS + 1];	/* hold compiled commands */
+long linenum[MAXLINES];		/* numeric-addresses table */
+
+/* Miscellaneous shared variables */
+int nflag;			/* -n option flag */
+int eargc;			/* scratch copy of argument count */
+char **eargv;			/* scratch copy of argument list */
+char bits[] = {1, 2, 4, 8, 16, 32, 64, 128};
+
+/***** module common stuff *****/
+
+#define POOLSIZE	20000	/* size of string-pool space */
+#define WFILES		10	/* max # w output files that can be compiled */
+#define RELIMIT		256	/* max chars in compiled RE */
+#define MAXDEPTH	20	/* maximum {}-nesting level */
+#define MAXLABS		50	/* max # of labels that can be handled */
+
+#define SKIPWS(pc)	while ((*pc==' ') || (*pc=='\t')) pc++
+#define ABORT(msg)	(fprintf(stderr, msg, linebuf), quit(2))
+#define IFEQ(x, v)	if (*x == v) x++ ,	/* do expression */
+
+/* Error messages */
+static char AGMSG[] = "sed: garbled address %s\n";
+static char CGMSG[] = "sed: garbled command %s\n";
+static char TMTXT[] = "sed: too much text: %s\n";
+static char AD1NG[] = "sed: no addresses allowed for %s\n";
+static char AD2NG[] = "sed: only one address allowed for %s\n";
+static char TMCDS[] = "sed: too many commands, last was %s\n";
+static char COCFI[] = "sed: cannot open command-file %s\n";
+static char UFLAG[] = "sed: unknown flag %c\n";
+static char CCOFI[] = "sed: cannot create %s\n";
+static char ULABL[] = "sed: undefined label %s\n";
+static char TMLBR[] = "sed: too many {'s\n";
+static char FRENL[] = "sed: first RE must be non-null\n";
+static char NSCAX[] = "sed: no such command as %s\n";
+static char TMRBR[] = "sed: too many }'s\n";
+static char DLABL[] = "sed: duplicate label %s\n";
+static char TMLAB[] = "sed: too many labels: %s\n";
+static char TMWFI[] = "sed: too many w files\n";
+static char REITL[] = "sed: RE too long: %s\n";
+static char TMLNR[] = "sed: too many line numbers\n";
+static char TRAIL[] = "sed: command \"%s\" has trailing garbage\n";
+
+typedef struct {		/* represent a command label */
+  char *name;			/* the label name */
+  sedcmd *last;			/* it's on the label search list */
+  sedcmd *address;		/* pointer to the cmd it labels */
+}
+
+ label;
+
+/* Label handling */
+static label labels[MAXLABS];	/* here's the label table */
+static label *lab = labels + 1;	/* pointer to current label */
+static label *lablst = labels;	/* header for search list */
+
+/* String pool for regular expressions, append text, etc. etc. */
+static char pool[POOLSIZE];	/* the pool */
+static char *fp = pool;		/* current pool pointer */
+static char *poolend = pool + POOLSIZE;	/* pointer past pool end */
+
+/* Compilation state */
+static FILE *cmdf = NULL;	/* current command source */
+static char *cp = linebuf;	/* compile pointer */
+static sedcmd *cmdp = cmds;	/* current compiled-cmd ptr */
+static char *lastre = NULL;	/* old RE pointer */
+static int bdepth = 0;		/* current {}-nesting level */
+static int bcount = 0;		/* # tagged patterns in current RE */
+
+/* Compilation flags */
+static int eflag;		/* -e option flag */
+static int gflag;		/* -g option flag */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(static void compile, (void));
+_PROTOTYPE(static int cmdcomp, (int cchar));
+_PROTOTYPE(static char *rhscomp, (char *rhsp, int delim));
+_PROTOTYPE(static char *recomp, (char *expbuf, int redelim));
+_PROTOTYPE(static int cmdline, (char *cbuf));
+_PROTOTYPE(static char *address, (char *expbuf));
+_PROTOTYPE(static char *gettext, (char *txp));
+_PROTOTYPE(static label *search, (label *ptr));
+_PROTOTYPE(static void resolve, (void));
+_PROTOTYPE(static char *ycomp, (char *ep, int delim));
+_PROTOTYPE(void quit, (int n));
+_PROTOTYPE(void execute, (void));
+_PROTOTYPE(static int selected, (sedcmd *ipc));
+_PROTOTYPE(static int match, (char *expbuf, int gf));
+_PROTOTYPE(static int advance, (char *lp, char *ep));
+_PROTOTYPE(static int substitute, (sedcmd *ipc));
+_PROTOTYPE(static void dosub, (char *rhsbuf));
+_PROTOTYPE(static char *place, (char *asp, char *al1, char *al2));
+_PROTOTYPE(static void listto, (char *p1, FILE *fp));
+_PROTOTYPE(static void truncated, (int h));
+_PROTOTYPE(static void command, (sedcmd *ipc));
+_PROTOTYPE(static void openfile, (char *file));
+_PROTOTYPE(static void get, (void));
+_PROTOTYPE(static void initget, (void));
+_PROTOTYPE(static char *getline, (char *buf));
+_PROTOTYPE(static int Memcmp, (char *a, char *b, int count));
+_PROTOTYPE(static void readout, (void));
+
+int main(argc, argv)
+/* Main sequence of the stream editor */
+int argc;
+char *argv[];
+{
+  eargc = argc;			/* set local copy of argument count */
+  eargv = argv;			/* set local copy of argument list */
+  cmdp->addr1 = pool;		/* 1st addr expand will be at pool start */
+  if (eargc == 1) quit(0);	/* exit immediately if no arguments */
+  /* Scan through the arguments, interpreting each one */
+  while ((--eargc > 0) && (**++eargv == '-')) switch (eargv[0][1]) {
+	    case 'e':
+		eflag++;
+		compile();	/* compile with e flag on */
+		eflag = 0;
+		continue;	/* get another argument */
+	    case 'f':
+		if (eargc-- <= 0)	/* barf if no -f file */
+			quit(2);
+		if ((cmdf = fopen(*++eargv, "r")) == NULL) {
+			fprintf(stderr, COCFI, *eargv);
+			quit(2);
+		}
+		compile();	/* file is O.K., compile it */
+		fclose(cmdf);
+		continue;	/* go back for another argument */
+	    case 'g':
+		gflag++;	/* set global flag on all s cmds */
+		continue;
+	    case 'n':
+		nflag++;	/* no print except on p flag or w */
+		continue;
+	    default:
+		fprintf(stdout, UFLAG, eargv[0][1]);
+		continue;
+	}
+
+
+  if (cmdp == cmds) {		/* no commands have been compiled */
+	eargv--;
+	eargc++;
+	eflag++;
+	compile();
+	eflag = 0;
+	eargv++;
+	eargc--;
+  }
+  if (bdepth)			/* we have unbalanced squigglies */
+	ABORT(TMLBR);
+
+  lablst->address = cmdp;	/* set up header of label linked list */
+  resolve();			/* resolve label table indirections */
+  execute();			/* execute commands */
+  quit(0);			/* everything was O.K. if we got here */
+  return(0);
+}
+
+
+#define H	0x80		/* 128 bit, on if there's really code for
+			 * command */
+#define LOWCMD	56		/* = '8', lowest char indexed in cmdmask */
+
+/* Indirect through this to get command internal code, if it exists */
+static char cmdmask[] =
+{
+ 0, 0, H, 0, 0, H + EQCMD, 0, 0,
+ 0, 0, 0, 0, H + CDCMD, 0, 0, CGCMD,
+ CHCMD, 0, 0, 0, 0, 0, CNCMD, 0,
+ CPCMD, 0, 0, 0, H + CTCMD, 0, 0, H + CWCMD,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, H + ACMD, H + BCMD, H + CCMD, DCMD, 0, 0, GCMD,
+ HCMD, H + ICMD, 0, 0, H + LCMD, 0, NCMD, 0,
+ PCMD, H + QCMD, H + RCMD, H + SCMD, H + TCMD, 0, 0, H + WCMD,
+ XCMD, H + YCMD, 0, H + BCMD, 0, H, 0, 0,
+};
+
+static void compile()
+/* Precompile sed commands out of a file */
+{
+  char ccode;
+
+
+  for (;;) {			/* main compilation loop */
+	if (*cp == '\0') {	/* get a new command line */
+		*linebuf = '\0';	/* K.H */
+		if (cmdline(cp = linebuf) < 0) break;
+	}
+	SKIPWS(cp);
+	if (*cp == '\0')	/* empty */
+		continue;
+	if (*cp == '#') {	/* comment */
+		while (*cp) ++cp;
+		continue;
+	}
+	if (*cp == ';') {	/* ; separates cmds */
+		cp++;
+		continue;
+	}
+
+	/* Compile first address */
+	if (fp > poolend)
+		ABORT(TMTXT);
+	else if ((fp = address(cmdp->addr1 = fp)) == BAD)
+		ABORT(AGMSG);
+
+	if (fp == cmdp->addr1) {/* if empty RE was found */
+		if (lastre)	/* if there was previous RE */
+			cmdp->addr1 = lastre;	/* use it */
+		else
+			ABORT(FRENL);
+	} else if (fp == NULL) {/* if fp was NULL */
+		fp = cmdp->addr1;	/* use current pool location */
+		cmdp->addr1 = NULL;
+	} else {
+		lastre = cmdp->addr1;
+		if (*cp == ',' || *cp == ';') {	/* there's 2nd addr */
+			cp++;
+			if (fp > poolend) ABORT(TMTXT);
+			fp = address(cmdp->addr2 = fp);
+			if (fp == BAD || fp == NULL) ABORT(AGMSG);
+			if (fp == cmdp->addr2)
+				cmdp->addr2 = lastre;
+			else
+				lastre = cmdp->addr2;
+		} else
+			cmdp->addr2 = NULL;	/* no 2nd address */
+	}
+	if (fp > poolend) ABORT(TMTXT);
+
+	SKIPWS(cp);		/* discard whitespace after address */
+	IFEQ(cp, '!') cmdp->flags.allbut = 1;
+
+	SKIPWS(cp);		/* get cmd char, range-check it */
+	if ((*cp < LOWCMD) || (*cp > '~')
+	    || ((ccode = cmdmask[*cp - LOWCMD]) == 0))
+		ABORT(NSCAX);
+
+	cmdp->command = ccode & ~H;	/* fill in command value */
+	if ((ccode & H) == 0)	/* if no compile-time code */
+		cp++;		/* discard command char */
+	else if (cmdcomp(*cp++))/* execute it; if ret = 1 */
+		continue;	/* skip next line read */
+
+	if (++cmdp >= cmds + MAXCMDS) ABORT(TMCDS);
+
+	SKIPWS(cp);		/* look for trailing stuff */
+	if (*cp != '\0' && *cp != ';' && *cp != '#') ABORT(TRAIL);
+  }
+}
+
+static int cmdcomp(cchar)
+/* Compile a single command */
+register char cchar;		/* character name of command */
+{
+  static sedcmd **cmpstk[MAXDEPTH];	/* current cmd stack for {} */
+  static char *fname[WFILES];	/* w file name pointers */
+  static FILE *fout[WFILES];	/* w file file ptrs */
+  static int nwfiles = 1;	/* count of open w files */
+  int i;			/* indexing dummy used in w */
+  sedcmd *sp1, *sp2;		/* temps for label searches */
+  label *lpt;
+  char redelim;			/* current RE delimiter */
+
+  fout[0] = stdout;
+  switch (cchar) {
+      case '{':			/* start command group */
+	cmdp->flags.allbut = !cmdp->flags.allbut;
+	cmpstk[bdepth++] = &(cmdp->u.link);
+	if (++cmdp >= cmds + MAXCMDS) ABORT(TMCDS);
+	return(1);
+
+      case '}':			/* end command group */
+	if (cmdp->addr1) ABORT(AD1NG);	/* no addresses allowed */
+	if (--bdepth < 0) ABORT(TMRBR);	/* too many right braces */
+	*cmpstk[bdepth] = cmdp;	/* set the jump address */
+	return(1);
+
+      case '=':			/* print current source line number */
+      case 'q':			/* exit the stream editor */
+	if (cmdp->addr2) ABORT(AD2NG);
+	break;
+
+      case ':':			/* label declaration */
+	if (cmdp->addr1) ABORT(AD1NG);	/* no addresses allowed */
+	fp = gettext(lab->name = fp);	/* get the label name */
+	if (lpt = search(lab)) {/* does it have a double? */
+		if (lpt->address) ABORT(DLABL);	/* yes, abort */
+	} else {		/* check that it doesn't overflow label table */
+		lab->last = NULL;
+		lpt = lab;
+		if (++lab >= labels + MAXLABS) ABORT(TMLAB);
+	}
+	lpt->address = cmdp;
+	return(1);
+
+      case 'b':			/* branch command */
+      case 't':			/* branch-on-succeed command */
+      case 'T':			/* branch-on-fail command */
+	SKIPWS(cp);
+	if (*cp == '\0') {	/* if branch is to start of cmds... */
+		/* Add current command to end of label last */
+		if (sp1 = lablst->last) {
+			while (sp2 = sp1->u.link) sp1 = sp2;
+			sp1->u.link = cmdp;
+		} else		/* lablst->last == NULL */
+			lablst->last = cmdp;
+		break;
+	}
+	fp = gettext(lab->name = fp);	/* else get label into pool */
+	if (lpt = search(lab)) {/* enter branch to it */
+		if (lpt->address)
+			cmdp->u.link = lpt->address;
+		else {
+			sp1 = lpt->last;
+			while (sp2 = sp1->u.link) sp1 = sp2;
+			sp1->u.link = cmdp;
+		}
+	} else {		/* matching named label not found */
+		lab->last = cmdp;	/* add the new label */
+		lab->address = NULL;	/* it's forward of here */
+		if (++lab >= labels + MAXLABS)	/* overflow if last */
+			ABORT(TMLAB);
+	}
+	break;
+
+      case 'a':			/* append text */
+      case 'i':			/* insert text */
+      case 'r':			/* read file into stream */
+	if (cmdp->addr2) ABORT(AD2NG);
+      case 'c':			/* change text */
+	if ((*cp == '\\') && (*++cp == '\n')) cp++;
+	fp = gettext(cmdp->u.lhs = fp);
+	break;
+
+      case 'D':			/* delete current line in hold space */
+	cmdp->u.link = cmds;
+	break;
+
+      case 's':			/* substitute regular expression */
+	redelim = *cp++;	/* get delimiter from 1st ch */
+	if ((fp = recomp(cmdp->u.lhs = fp, redelim)) == BAD) ABORT(CGMSG);
+	if (fp == cmdp->u.lhs)	/* if compiled RE zero len */
+		cmdp->u.lhs = lastre;	/* use the previous one */
+	else			/* otherwise */
+		lastre = cmdp->u.lhs;	/* save the one just found */
+	if ((cmdp->rhs = fp) > poolend) ABORT(TMTXT);
+	if ((fp = rhscomp(cmdp->rhs, redelim)) == BAD) ABORT(CGMSG);
+	if (gflag) cmdp->flags.global ++;
+	while (*cp == 'g' || *cp == 'p' || *cp == 'P') {
+		IFEQ(cp, 'g') cmdp->flags.global ++;
+		IFEQ(cp, 'p') cmdp->flags.print = 1;
+		IFEQ(cp, 'P') cmdp->flags.print = 2;
+	}
+
+      case 'l':			/* list pattern space */
+	if (*cp == 'w')
+		cp++;		/* and execute a w command! */
+	else
+		break;		/* s or l is done */
+
+      case 'w':			/* write-pattern-space command */
+      case 'W':			/* write-first-line command */
+	if (nwfiles >= WFILES) ABORT(TMWFI);
+	fp = gettext(fname[nwfiles] = fp);	/* filename will be in pool */
+	for (i = nwfiles - 1; i >= 0; i--)	/* match it in table */
+		if ((fname[i] != NULL) &&
+		    (strcmp(fname[nwfiles], fname[i]) == 0)) {
+			cmdp->fout = fout[i];
+			return(0);
+		}
+
+	/* If didn't find one, open new out file */
+	if ((cmdp->fout = fopen(fname[nwfiles], "w")) == NULL) {
+		fprintf(stderr, CCOFI, fname[nwfiles]);
+		quit(2);
+	}
+	fout[nwfiles++] = cmdp->fout;
+	break;
+
+      case 'y':			/* transliterate text */
+	fp = ycomp(cmdp->u.lhs = fp, *cp++);	/* compile translit */
+	if (fp == BAD) ABORT(CGMSG);	/* fail on bad form */
+	if (fp > poolend) ABORT(TMTXT);	/* fail on overflow */
+	break;
+  }
+  return(0);			/* succeeded in interpreting one command */
+}
+
+static char *rhscomp(rhsp, delim)	/* uses bcount */
+ /* Generate replacement string for substitute command right hand side */
+register char *rhsp;		/* place to compile expression to */
+register char delim;		/* regular-expression end-mark to look for */
+{
+  register char *p = cp;	/* strictly for speed */
+
+  for (;;)
+	if ((*rhsp = *p++) == '\\') {	/* copy; if it's a \, */
+		*rhsp = *p++;	/* copy escaped char */
+		/* Check validity of pattern tag */
+		if (*rhsp > bcount + '0' && *rhsp <= '9') return(BAD);
+		*rhsp++ |= 0x80;/* mark the good ones */
+		continue;
+	} else if (*rhsp == delim) {	/* found RE end, hooray... */
+		*rhsp++ = '\0';	/* cap the expression string */
+		cp = p;
+		return(rhsp);	/* pt at 1 past the RE */
+	} else if (*rhsp++ == '\0')	/* last ch not RE end, help! */
+		return(BAD);
+}
+
+static char *recomp(expbuf, redelim)	/* uses cp, bcount */
+ /* Compile a regular expression to internal form */
+char *expbuf;			/* place to compile it to */
+char redelim;			/* RE end-marker to look for */
+{
+  register char *ep = expbuf;	/* current-compiled-char pointer */
+  register char *sp = cp;	/* source-character ptr */
+  register int c;		/* current-character pointer */
+  char negclass;		/* all-but flag */
+  char *lastep;			/* ptr to last expr compiled */
+  char *svclass;		/* start of current char class */
+  char brnest[MAXTAGS];		/* bracket-nesting array */
+  char *brnestp;		/* ptr to current bracket-nest */
+  int classct;			/* class element count */
+  int tags;			/* # of closed tags */
+
+  if (*cp == redelim)		/* if first char is RE endmarker */
+	return(cp++, expbuf);	/* leave existing RE unchanged */
+
+  lastep = NULL;		/* there's no previous RE */
+  brnestp = brnest;		/* initialize ptr to brnest array */
+  tags = bcount = 0;		/* initialize counters */
+
+  if (*ep++ = (*sp == '^'))	/* check for start-of-line syntax */
+	sp++;
+
+  for (;;) {
+	if (ep >= expbuf + RELIMIT)	/* match is too large */
+		return(cp = sp, BAD);
+	if ((c = *sp++) == redelim) {	/* found the end of the RE */
+		cp = sp;
+		if (brnestp != brnest)	/* \(, \) unbalanced */
+			return(BAD);
+		*ep++ = CEOF;	/* write end-of-pattern mark */
+		return(ep);	/* return ptr to compiled RE */
+	}
+	if (c != '*')		/* if we're a postfix op */
+		lastep = ep;	/* get ready to match last */
+
+	switch (c) {
+	    case '\\':
+		if ((c = *sp++) == '(') {	/* start tagged section */
+			if (bcount >= MAXTAGS) return(cp = sp, BAD);
+			*brnestp++ = bcount;	/* update tag stack */
+			*ep++ = CBRA;	/* enter tag-start */
+			*ep++ = bcount++;	/* bump tag count */
+			continue;
+		} else if (c == ')') {	/* end tagged section */
+			if (brnestp <= brnest)	/* extra \) */
+				return(cp = sp, BAD);
+			*ep++ = CKET;	/* enter end-of-tag */
+			*ep++ = *--brnestp;	/* pop tag stack */
+			tags++;	/* count closed tags */
+			continue;
+		} else if (c >= '1' && c <= '9') {	/* tag use */
+			if ((c -= '1') >= tags)	/* too few */
+				return(BAD);
+			*ep++ = CBACK;	/* enter tag mark */
+			*ep++ = c;	/* and the number */
+			continue;
+		} else if (c == '\n')	/* escaped newline no good */
+			return(cp = sp, BAD);
+		else if (c == 'n')	/* match a newline */
+			c = '\n';
+		else if (c == 't')	/* match a tab */
+			c = '\t';
+		else if (c == 'r')	/* match a return */
+			c = '\r';
+		goto defchar;
+
+	    case '\0':		/* ignore nuls */
+		continue;
+
+	    case '\n':		/* trailing pattern delimiter is missing */
+		return(cp = sp, BAD);
+
+	    case '.':		/* match any char except newline */
+		*ep++ = CDOT;
+		continue;
+	    case '*':		/* 0..n repeats of previous pattern */
+		if (lastep == NULL)	/* if * isn't first on line */
+			goto defchar;	/* match a literal * */
+		if (*lastep == CKET)	/* can't iterate a tag */
+			return(cp = sp, BAD);
+		*lastep |= STAR;/* flag previous pattern */
+		continue;
+
+	    case '$':		/* match only end-of-line */
+		if (*sp != redelim)	/* if we're not at end of RE */
+			goto defchar;	/* match a literal $ */
+		*ep++ = CDOL;	/* insert end-symbol mark */
+		continue;
+
+	    case '[':		/* begin character set pattern */
+		if (ep + 17 >= expbuf + RELIMIT) ABORT(REITL);
+		*ep++ = CCL;	/* insert class mark */
+		if (negclass = ((c = *sp++) == '^')) c = *sp++;
+		svclass = sp;	/* save ptr to class start */
+		do {
+			if (c == '\0') ABORT(CGMSG);
+
+			/* Handle character ranges */
+			if (c == '-' && sp > svclass && *sp != ']')
+				for (c = sp[-2]; c < *sp; c++)
+					ep[c >> 3] |= bits[c & 7];
+
+			/* Handle escape sequences in sets */
+			if (c == '\\')
+				if ((c = *sp++) == 'n')
+					c = '\n';
+				else if (c == 't')
+					c = '\t';
+				else if (c == 'r')
+					c = '\r';
+
+			/* Enter (possibly translated) char in set */
+			ep[c >> 3] |= bits[c & 7];
+		} while
+			((c = *sp++) != ']');
+
+		/* Invert the bitmask if all-but was specified */
+		if (negclass) for (classct = 0; classct < 16; classct++)
+				ep[classct] ^= 0xFF;
+		ep[0] &= 0xFE;	/* never match ASCII 0 */
+		ep += 16;	/* advance ep past set mask */
+		continue;
+
+  defchar:			/* match literal character */
+	    default:		/* which is what we'd do by default */
+		*ep++ = CCHR;	/* insert character mark */
+		*ep++ = c;
+	}
+  }
+}
+
+static int cmdline(cbuf)	/* uses eflag, eargc, cmdf */
+ /* Read next command from -e argument or command file */
+register char *cbuf;
+{
+  register int inc;		/* not char because must hold EOF */
+
+  *cbuf-- = 0;			/* so pre-increment points us at cbuf */
+
+  /* E command flag is on */
+  if (eflag) {
+	register char *p;	/* ptr to current -e argument */
+	static char *savep;	/* saves previous value of p */
+
+	if (eflag > 0) {	/* there are pending -e arguments */
+		eflag = -1;
+		if (eargc-- <= 0) quit(2);	/* if no arguments, barf */
+
+		/* Else transcribe next e argument into cbuf */
+		p = *++eargv;
+		while (*++cbuf = *p++)
+			if (*cbuf == '\\') {
+				if ((*++cbuf = *p++) == '\0')
+					return(savep = NULL, -1);
+				else
+					continue;
+			} else if (*cbuf == '\n') {	/* end of 1 cmd line */
+				*cbuf = '\0';
+				return(savep = p, 1);
+				/* We'll be back for the rest... */
+			}
+
+		/* Found end-of-string; can advance to next argument */
+		return(savep = NULL, 1);
+	}
+	if ((p = savep) == NULL) return(-1);
+
+	while (*++cbuf = *p++)
+		if (*cbuf == '\\') {
+			if ((*++cbuf = *p++) == '0')
+				return(savep = NULL, -1);
+			else
+				continue;
+		} else if (*cbuf == '\n') {
+			*cbuf = '\0';
+			return(savep = p, 1);
+		}
+	return(savep = NULL, 1);
+  }
+
+  /* If no -e flag read from command file descriptor */
+  while ((inc = getc(cmdf)) != EOF)	/* get next char */
+	if ((*++cbuf = inc) == '\\')	/* if it's escape */
+		*++cbuf = inc = getc(cmdf);	/* get next char */
+	else if (*cbuf == '\n')	/* end on newline */
+		return(*cbuf = '\0', 1);	/* cap the string */
+
+  return(*++cbuf = '\0', -1);	/* end-of-file, no more chars */
+}
+
+static char *address(expbuf)	/* uses cp, linenum */
+ /* Expand an address at *cp... into expbuf, return ptr at following char */
+register char *expbuf;
+{
+  static int numl = 0;		/* current ind in addr-number table */
+  register char *rcp;		/* temp compile ptr for forwd look */
+  long lno;			/* computed value of numeric address */
+
+  if (*cp == '$') {		/* end-of-source address */
+	*expbuf++ = CEND;	/* write symbolic end address */
+	*expbuf++ = CEOF;	/* and the end-of-address mark (!) */
+	cp++;			/* go to next source character */
+	return(expbuf);	/* we're done */
+  }
+  if (*cp == '/' || *cp == '\\') { /* start of regular-expression match */
+	if (*cp == '\\') cp++;
+	return(recomp(expbuf, *cp++));	/* compile the RE */
+  }
+
+  rcp = cp;
+  lno = 0;			/* now handle a numeric address */
+  while (*rcp >= '0' && *rcp <= '9')	/* collect digits */
+	lno = lno * 10 + *rcp++ - '0';	/* compute their value */
+
+  if (rcp > cp) {		/* if we caught a number... */
+	*expbuf++ = CLNUM;	/* put a numeric-address marker */
+	*expbuf++ = numl;	/* and the address table index */
+	linenum[numl++] = lno;	/* and set the table entry */
+	if (numl >= MAXLINES)	/* oh-oh, address table overflow */
+		ABORT(TMLNR);	/* abort with error message */
+	*expbuf++ = CEOF;	/* write the end-of-address marker */
+	cp = rcp;		/* point compile past the address */
+	return(expbuf);	/* we're done */
+  }
+  return(NULL);			/* no legal address was found */
+}
+
+static char *gettext(txp)	/* uses global cp */
+ /* Accept multiline input from *cp..., discarding leading whitespace */
+register char *txp;		/* where to put the text */
+{
+  register char *p = cp;	/* this is for speed */
+
+  SKIPWS(p);			/* discard whitespace */
+  do {
+	if ((*txp = *p++) == '\\')	/* handle escapes */
+		*txp = *p++;
+	if (*txp == '\0')	/* we're at end of input */
+		return(cp = --p, ++txp);
+	else if (*txp == '\n')	/* also SKIPWS after newline */
+		SKIPWS(p);
+  } while
+	(txp++);		/* keep going till we find that nul */
+  return(txp);
+}
+
+static label *search(ptr)	/* uses global lablst */
+ /* Find the label matching *ptr, return NULL if none */
+register label *ptr;
+{
+  register label *rp;
+  for (rp = lablst; rp < ptr; rp++)
+	if ((rp->name != NULL) && (strcmp(rp->name, ptr->name) == 0))
+		return(rp);
+  return(NULL);
+}
+
+static void resolve()
+{				/* uses global lablst */
+  /* Write label links into the compiled-command space */
+  register label *lptr;
+  register sedcmd *rptr, *trptr;
+
+  /* Loop through the label table */
+  for (lptr = lablst; lptr < lab; lptr++)
+	if (lptr->address == NULL) {	/* barf if not defined */
+		fprintf(stderr, ULABL, lptr->name);
+		quit(2);
+	} else if (lptr->last) {/* if last is non-null */
+		rptr = lptr->last;	/* chase it */
+		while (trptr = rptr->u.link) {	/* resolve refs */
+			rptr->u.link = lptr->address;
+			rptr = trptr;
+		}
+		rptr->u.link = lptr->address;
+	}
+}
+
+static char *ycomp(ep, delim)
+/* Compile a y (transliterate) command */
+register char *ep;		/* where to compile to */
+char delim;			/* end delimiter to look for */
+{
+  register char *tp, *sp;
+  register int c;
+
+  /* Scan the 'from' section for invalid chars */
+  for (sp = tp = cp; *tp != delim; tp++) {
+	if (*tp == '\\') tp++;
+	if ((*tp == '\n') || (*tp == '\0')) return (BAD);
+  }
+  tp++;				/* tp now points at first char of 'to'
+			 * section */
+
+  /* Now rescan the 'from' section */
+  while ((c = *sp++ & 0x7F) != delim) {
+	if (c == '\\' && *sp == 'n') {
+		sp++;
+		c = '\n';
+	}
+	if ((ep[c] = *tp++) == '\\' && *tp == 'n') {
+		ep[c] = '\n';
+		tp++;
+	}
+	if ((ep[c] == delim) || (ep[c] == '\0')) return(BAD);
+  }
+
+  if (*tp != delim)		/* 'to', 'from' parts have unequal lengths */
+	return(BAD);
+
+  cp = ++tp;			/* point compile ptr past translit */
+
+  for (c = 0; c < 128; c++)	/* fill in self-map entries in table */
+	if (ep[c] == 0) ep[c] = c;
+
+  return(ep + 0x80);		/* return first free location past table end */
+}
+
+void quit(n)
+int n;
+{
+/* Flush buffers and exit.  Now a historical relic.  Rely on exit to flush
+ * the buffers.
+ */
+  exit(n);
+}
+
+/*+++++++++++++++*/
+
+/*
+   sedexec.c -- execute compiled form of stream editor commands
+
+   The single entry point of this module is the function execute(). It
+   may take a string argument (the name of a file to be used as text)  or
+   the argument NULL which tells it to filter standard input. It executes
+   the compiled commands in cmds[] on each line in turn.
+
+   The function command() does most of the work. Match() and advance()
+   are used for matching text against precompiled regular expressions and
+   dosub() does right-hand-side substitution.  Getline() does text input;
+   readout() and Memcmp() are output and string-comparison utilities.
+*/
+
+/* #include <stdio.h>	*/
+/* #include <ctype.h>	*/
+/* #include "sed.h"	*/
+
+/***** shared variables imported from the main ******/
+
+/* Main data areas */
+extern char linebuf[];		/* current-line buffer */
+extern sedcmd cmds[];		/* hold compiled commands */
+extern long linenum[];		/* numeric-addresses table */
+
+/* Miscellaneous shared variables */
+extern int nflag;		/* -n option flag */
+extern int eargc;		/* scratch copy of argument count */
+extern char **eargv;		/* scratch copy of argument list */
+extern char bits[];		/* the bits table */
+
+/***** end of imported stuff *****/
+
+#define MAXHOLD	 MAXBUF		/* size of the hold space */
+#define GENSIZ	 MAXBUF		/* maximum genbuf size */
+
+#define TRUE	 1
+#define FALSE	 0
+
+static char LTLMSG[] = "sed: line too long\n";
+
+static char *spend;		/* current end-of-line-buffer pointer */
+static long lnum = 0L;		/* current source line number */
+
+/* Append buffer maintenance */
+static sedcmd *appends[MAXAPPENDS];	/* array of ptrs to a,i,c commands */
+static sedcmd **aptr = appends;	/* ptr to current append */
+
+/* Genbuf and its pointers */
+static char genbuf[GENSIZ];
+static char *loc1;
+static char *loc2;
+static char *locs;
+
+/* Command-logic flags */
+static int lastline;		/* do-line flag */
+static int jump;		/* jump to cmd's link address if set */
+static int delete;		/* delete command flag */
+
+/* Tagged-pattern tracking */
+static char *bracend[MAXTAGS];	/* tagged pattern start pointers */
+static char *brastart[MAXTAGS];	/* tagged pattern end pointers */
+
+static int anysub;		/* true if any s on current line succeeded */
+
+
+void execute()
+/* Execute the compiled commands in cmds[] */
+{
+  register char *p1;		/* dummy copy ptrs */
+  register sedcmd *ipc;		/* ptr to current command */
+  char *execp;			/* ptr to source */
+
+
+  initget();
+
+  /* Here's the main command-execution loop */
+  for (;;) {
+
+	/* Get next line to filter */
+	if ((execp = getline(linebuf)) == BAD) return;
+	spend = execp;
+	anysub = FALSE;
+
+	/* Loop through compiled commands, executing them */
+	for (ipc = cmds; ipc->command;) {
+		if (!selected(ipc)) {
+			ipc++;
+			continue;
+		}
+		command(ipc);	/* execute the command pointed at */
+
+		if (delete)	/* if delete flag is set */
+			break;	/* don't exec rest of compiled cmds */
+
+		if (jump) {	/* if jump set, follow cmd's link */
+			jump = FALSE;
+			if ((ipc = ipc->u.link) == 0) {
+				ipc = cmds;
+				break;
+			}
+		} else		/* normal goto next command */
+			ipc++;
+	}
+
+	/* We've now done all modification commands on the line */
+
+	/* Here's where the transformed line is output */
+	if (!nflag && !delete) {
+		for (p1 = linebuf; p1 < spend; p1++) putc(*p1, stdout);
+		putc('\n', stdout);
+	}
+
+	/* If we've been set up for append, emit the text from it */
+	if (aptr > appends) readout();
+
+	delete = FALSE;		/* clear delete flag; about to get next cmd */
+  }
+}
+
+static int selected(ipc)
+/* Is current command selected */
+sedcmd *ipc;
+{
+  register char *p1 = ipc->addr1;	/* point p1 at first address */
+  register char *p2 = ipc->addr2;	/* and p2 at second */
+  int c;
+  int sel = TRUE;		/* select by default */
+
+  if (!p1)			/* No addresses: always selected */
+	;
+  else if (ipc->flags.inrange) {
+	if (*p2 == CEND);
+	else if (*p2 == CLNUM) {
+		c = p2[1] & CMASK;
+		if (lnum >= linenum[c]) {
+			ipc->flags.inrange = FALSE;
+			if (lnum > linenum[c]) sel = FALSE;
+		}
+	} else if (match(p2, 0))
+		ipc->flags.inrange = FALSE;
+  } else if (*p1 == CEND) {
+	if (!lastline) sel = FALSE;
+  } else if (*p1 == CLNUM) {
+	c = p1[1] & CMASK;
+	if (lnum != linenum[c])
+		sel = FALSE;
+	else if (p2)
+		ipc->flags.inrange = TRUE;
+  } else if (match(p1, 0)) {
+	if (p2) ipc->flags.inrange = TRUE;
+  } else
+	sel = FALSE;
+
+  return ipc->flags.allbut ? !sel : sel;
+}
+
+static int match(expbuf, gf)	/* uses genbuf */
+ /* Match RE at expbuf against linebuf; if gf set, copy linebuf from genbuf */
+char *expbuf;
+int gf;
+{
+  register char *p1, *p2, c;
+
+  if (gf) {
+	if (*expbuf) return(FALSE);
+	p1 = linebuf;
+	p2 = genbuf;
+	while (*p1++ = *p2++);
+	locs = p1 = loc2;
+  } else {
+	p1 = linebuf;
+	locs = FALSE;
+  }
+
+  p2 = expbuf;
+  if (*p2++) {
+	loc1 = p1;
+	if (*p2 == CCHR && p2[1] != *p1)	/* 1st char is wrong */
+		return(FALSE);	/* so fail */
+	return(advance(p1, p2));/* else try to match rest */
+  }
+
+  /* Quick check for 1st character if it's literal */
+  if (*p2 == CCHR) {
+	c = p2[1];		/* pull out character to search for */
+	do {
+		if (*p1 != c) continue;	/* scan the source string */
+		if (advance(p1, p2))	/* found it, match the rest */
+			return(loc1 = p1, 1);
+	} while
+		(*p1++);
+	return(FALSE);		/* didn't find that first char */
+  }
+
+  /* Else try for unanchored match of the pattern */
+  do {
+	if (advance(p1, p2)) return(loc1 = p1, 1);
+  } while
+	(*p1++);
+
+  /* If got here, didn't match either way */
+  return(FALSE);
+}
+
+static int advance(lp, ep)
+/* Attempt to advance match pointer by one pattern element */
+register char *lp;		/* source (linebuf) ptr */
+register char *ep;		/* regular expression element ptr */
+{
+  register char *curlp;		/* save ptr for closures */
+  char c;			/* scratch character holder */
+  char *bbeg;
+  int ct;
+
+  for (;;) switch (*ep++) {
+	    case CCHR:		/* literal character */
+		if (*ep++ == *lp++)	/* if chars are equal */
+			continue;	/* matched */
+		return(FALSE);	/* else return false */
+
+	    case CDOT:		/* anything but newline */
+		if (*lp++)	/* first NUL is at EOL */
+			continue;	/* keep going if didn't find */
+		return(FALSE);	/* else return false */
+
+	    case CNL:		/* start-of-line */
+	    case CDOL:		/* end-of-line */
+		if (*lp == 0)	/* found that first NUL? */
+			continue;	/* yes, keep going */
+		return(FALSE);	/* else return false */
+
+	    case CEOF:		/* end-of-address mark */
+		loc2 = lp;	/* set second loc */
+		return(TRUE);	/* return true */
+
+	    case CCL:		/* a closure */
+		c = *lp++ & 0177;
+		if (ep[c >> 3] & bits[c & 07]) {	/* is char in set? */
+			ep += 16;	/* then skip rest of bitmask */
+			continue;	/* and keep going */
+		}
+		return(FALSE);	/* else return false */
+
+	    case CBRA:		/* start of tagged pattern */
+		brastart[*ep++] = lp;	/* mark it */
+		continue;	/* and go */
+
+	    case CKET:		/* end of tagged pattern */
+		bracend[*ep++] = lp;	/* mark it */
+		continue;	/* and go */
+
+	    case CBACK:
+		bbeg = brastart[*ep];
+		ct = bracend[*ep++] - bbeg;
+
+		if (Memcmp(bbeg, lp, ct)) {
+			lp += ct;
+			continue;
+		}
+		return(FALSE);
+
+	    case CBACK | STAR:
+		bbeg = brastart[*ep];
+		ct = bracend[*ep++] - bbeg;
+		curlp = lp;
+		while (Memcmp(bbeg, lp, ct)) lp += ct;
+
+		while (lp >= curlp) {
+			if (advance(lp, ep)) return(TRUE);
+			lp -= ct;
+		}
+		return(FALSE);
+
+
+	    case CDOT | STAR:	/* match .* */
+		curlp = lp;	/* save closure start loc */
+		while (*lp++);	/* match anything */
+		goto star;	/* now look for followers */
+
+	    case CCHR | STAR:	/* match <literal char>* */
+		curlp = lp;	/* save closure start loc */
+		while (*lp++ == *ep);	/* match many of that char */
+		ep++;		/* to start of next element */
+		goto star;	/* match it and followers */
+
+	    case CCL | STAR:	/* match [...]* */
+		curlp = lp;	/* save closure start loc */
+		do {
+			c = *lp++ & 0x7F;	/* match any in set */
+		} while
+			(ep[c >> 3] & bits[c & 07]);
+		ep += 16;	/* skip past the set */
+		goto star;	/* match followers */
+
+  star:				/* the recursion part of a * or + match */
+		if (--lp == curlp)	/* 0 matches */
+			continue;
+
+		if (*ep == CCHR) {
+			c = ep[1];
+			do {
+				if (*lp != c) continue;
+				if (advance(lp, ep)) return (TRUE);
+			} while
+				(lp-- > curlp);
+			return(FALSE);
+		}
+		if (*ep == CBACK) {
+			c = *(brastart[ep[1]]);
+			do {
+				if (*lp != c) continue;
+				if (advance(lp, ep)) return (TRUE);
+			} while
+				(lp-- > curlp);
+			return(FALSE);
+		}
+		do {
+			if (lp == locs) break;
+			if (advance(lp, ep)) return (TRUE);
+		} while
+			(lp-- > curlp);
+		return(FALSE);
+
+	    default:
+		fprintf(stderr, "sed: RE error, %o\n", *--ep);
+		quit(2);
+	}
+}
+
+static int substitute(ipc)
+/* Perform s command */
+sedcmd *ipc;			/* ptr to s command struct */
+{
+  int nullmatch;
+
+  if (match(ipc->u.lhs, 0)) {	/* if no match */
+	nullmatch = (loc1 == loc2);
+	dosub(ipc->rhs);	/* perform it once */
+  } else
+	return(FALSE);		/* command fails */
+
+  if (ipc->flags.global)	/* if global flag enabled */
+	while (*loc2) {		/* cycle through possibles */
+		if (nullmatch) loc2++;
+		if (match(ipc->u.lhs, 1)) {	/* found another */
+			nullmatch = (loc1 == loc2);
+			dosub(ipc->rhs);	/* so substitute */
+		} else		/* otherwise, */
+			break;	/* we're done */
+	}
+  return(TRUE);			/* we succeeded */
+}
+
+static void dosub(rhsbuf)	/* uses linebuf, genbuf, spend */
+ /* Generate substituted right-hand side (of s command) */
+char *rhsbuf;			/* where to put the result */
+{
+  register char *lp, *sp, *rp;
+  int c;
+
+  /* Copy linebuf to genbuf up to location  1 */
+  lp = linebuf;
+  sp = genbuf;
+  while (lp < loc1) *sp++ = *lp++;
+
+  for (rp = rhsbuf; c = *rp++;) {
+	if (c == '&') {
+		sp = place(sp, loc1, loc2);
+		continue;
+	} else if (c & 0200 && (c &= 0177) >= '1' && c < MAXTAGS + '1') {
+		sp = place(sp, brastart[c - '1'], bracend[c - '1']);
+		continue;
+	}
+	*sp++ = c & 0177;
+	if (sp >= genbuf + MAXBUF) fprintf(stderr, LTLMSG);
+  }
+  lp = loc2;
+  loc2 = sp - genbuf + linebuf;
+  while (*sp++ = *lp++)
+	if (sp >= genbuf + MAXBUF) fprintf(stderr, LTLMSG);
+  lp = linebuf;
+  sp = genbuf;
+  while (*lp++ = *sp++);
+  spend = lp - 1;
+}
+
+static char *place(asp, al1, al2)	/* uses genbuf */
+ /* Place chars at *al1...*(al1 - 1) at asp... in genbuf[] */
+register char *asp, *al1, *al2;
+{
+  while (al1 < al2) {
+	*asp++ = *al1++;
+	if (asp >= genbuf + MAXBUF) fprintf(stderr, LTLMSG);
+  }
+  return(asp);
+}
+
+static void listto(p1, fp)
+/* Write a hex dump expansion of *p1... to fp */
+register char *p1;		/* the source */
+FILE *fp;			/* output stream to write to */
+{
+  p1--;
+  while (*p1++)
+	if (isprint(*p1))
+		putc(*p1, fp);	/* pass it through */
+	else {
+		putc('\\', fp);	/* emit a backslash */
+		switch (*p1) {
+		    case '\b':
+			putc('b', fp);
+			break;	/* BS */
+		    case '\t':
+			putc('t', fp);
+			break;	/* TAB */
+		    case '\n':
+			putc('n', fp);
+			break;	/* NL */
+		    case '\r':
+			putc('r', fp);
+			break;	/* CR */
+		    case '\33':
+			putc('e', fp);
+			break;	/* ESC */
+		    default:
+			fprintf(fp, "%02x", *p1 & 0xFF);
+		}
+	}
+  putc('\n', fp);
+}
+
+static void truncated(h)
+int h;
+{
+  static long last = 0L;
+
+  if (lnum == last) return;
+  last = lnum;
+
+  fprintf(stderr, "sed: ");
+  fprintf(stderr, h ? "hold space" : "line %ld", lnum);
+  fprintf(stderr, " truncated to %d characters\n", MAXBUF);
+}
+
+static void command(ipc)
+/* Execute compiled command pointed at by ipc */
+sedcmd *ipc;
+{
+  static char holdsp[MAXHOLD + 1];	/* the hold space */
+  static char *hspend = holdsp;	/* hold space end pointer */
+  register char *p1, *p2;
+  char *execp;
+  int didsub;			/* true if last s succeeded */
+
+  switch (ipc->command) {
+      case ACMD:		/* append */
+	*aptr++ = ipc;
+	if (aptr >= appends + MAXAPPENDS) fprintf(stderr,
+			"sed: too many appends after line %ld\n",
+			lnum);
+	*aptr = 0;
+	break;
+
+      case CCMD:		/* change pattern space */
+	delete = TRUE;
+	if (!ipc->flags.inrange || lastline) printf("%s\n", ipc->u.lhs);
+	break;
+
+      case DCMD:		/* delete pattern space */
+	delete++;
+	break;
+
+      case CDCMD:		/* delete a line in hold space */
+	p1 = p2 = linebuf;
+	while (*p1 != '\n')
+		if (delete = (*p1++ == 0)) return;
+	p1++;
+	while (*p2++ = *p1++) continue;
+	spend = p2 - 1;
+	jump++;
+	break;
+
+      case EQCMD:		/* show current line number */
+	fprintf(stdout, "%ld\n", lnum);
+	break;
+
+      case GCMD:		/* copy hold space to pattern space */
+	p1 = linebuf;
+	p2 = holdsp;
+	while (*p1++ = *p2++);
+	spend = p1 - 1;
+	break;
+
+      case CGCMD:		/* append hold space to pattern space */
+	*spend++ = '\n';
+	p1 = spend;
+	p2 = holdsp;
+	do
+		if (p1 > linebuf + MAXBUF) {
+			truncated(0);
+			p1[-1] = 0;
+			break;
+		}
+	while (*p1++ = *p2++);
+
+	spend = p1 - 1;
+	break;
+
+      case HCMD:		/* copy pattern space to hold space */
+	p1 = holdsp;
+	p2 = linebuf;
+	while (*p1++ = *p2++);
+	hspend = p1 - 1;
+	break;
+
+      case CHCMD:		/* append pattern space to hold space */
+	*hspend++ = '\n';
+	p1 = hspend;
+	p2 = linebuf;
+	do
+		if (p1 > holdsp + MAXBUF) {
+			truncated(1);
+			p1[-1] = 0;
+			break;
+		}
+	while (*p1++ = *p2++);
+
+	hspend = p1 - 1;
+	break;
+
+      case ICMD:		/* insert text */
+	printf("%s\n", ipc->u.lhs);
+	break;
+
+      case BCMD:		/* branch to label */
+	jump = TRUE;
+	break;
+
+      case LCMD:		/* list text */
+	listto(linebuf, (ipc->fout != NULL) ? ipc->fout : stdout);
+	break;
+
+      case NCMD:		/* read next line into pattern space */
+	if (!nflag) puts(linebuf);	/* flush out the current line */
+	if (aptr > appends) readout();	/* do pending a, r commands */
+	if ((execp = getline(linebuf)) == BAD) {
+		delete = TRUE;
+		break;
+	}
+	spend = execp;
+	anysub = FALSE;
+	break;
+
+      case CNCMD:		/* append next line to pattern space */
+	if (aptr > appends) readout();
+	*spend++ = '\n';
+	if ((execp = getline(spend)) == BAD) {
+		*--spend = 0;
+		break;
+	}
+	spend = execp;
+	anysub = FALSE;
+	break;
+
+      case PCMD:		/* print pattern space */
+	puts(linebuf);
+	break;
+
+      case CPCMD:		/* print one line from pattern space */
+cpcom:				/* so s command can jump here */
+	for (p1 = linebuf; *p1 != '\n' && *p1 != '\0';) putc(*p1++, stdout);
+	putc('\n', stdout);
+	break;
+
+      case QCMD:		/* quit the stream editor */
+	if (!nflag) puts(linebuf);	/* flush out the current line */
+	if (aptr > appends)
+		readout();	/* do any pending a and r commands */
+	quit(0);
+
+      case RCMD:		/* read a file into the stream */
+	*aptr++ = ipc;
+	if (aptr >= appends + MAXAPPENDS) fprintf(stderr,
+			"sed: too many reads after line %ld\n",
+			lnum);
+	*aptr = 0;
+	break;
+
+      case SCMD:		/* substitute RE */
+	didsub = substitute(ipc);
+	if (didsub) anysub = TRUE;
+	if (ipc->flags.print && didsub)
+		if (ipc->flags.print == TRUE)
+			puts(linebuf);
+		else
+			goto cpcom;
+	if (didsub && ipc->fout) fprintf(ipc->fout, "%s\n", linebuf);
+	break;
+
+      case TCMD:		/* branch on any s successful */
+      case CTCMD:		/* branch on any s failed */
+	if (anysub == (ipc->command == CTCMD))
+		break;		/* no branch if any s failed, else */
+	anysub = FALSE;
+	jump = TRUE;		/* set up to jump to assoc'd label */
+	break;
+
+      case CWCMD:		/* write one line from pattern space */
+	for (p1 = linebuf; *p1 != '\n' && *p1 != '\0';)
+		putc(*p1++, ipc->fout);
+	putc('\n', ipc->fout);
+	break;
+
+      case WCMD:		/* write pattern space to file */
+	fprintf(ipc->fout, "%s\n", linebuf);
+	break;
+
+      case XCMD:		/* exchange pattern and hold spaces */
+	p1 = linebuf;
+	p2 = genbuf;
+	while (*p2++ = *p1++) continue;
+	p1 = holdsp;
+	p2 = linebuf;
+	while (*p2++ = *p1++) continue;
+	spend = p2 - 1;
+	p1 = genbuf;
+	p2 = holdsp;
+	while (*p2++ = *p1++) continue;
+	hspend = p2 - 1;
+	break;
+
+      case YCMD:
+	p1 = linebuf;
+	p2 = ipc->u.lhs;
+	while (*p1 = p2[*p1]) p1++;
+	break;
+  }
+}
+
+static void openfile(file)
+char *file;
+/* Replace stdin by given file */
+{
+  if (freopen(file, "r", stdin) == NULL) {
+	fprintf(stderr, "sed: can't open %s\n", file);
+	quit(1);
+  }
+}
+
+static int c;			/* Will be the next char to read, a kind of
+			 * lookahead */
+
+static void get()
+/* Read next character into c treating all argument files as run through cat */
+{
+  while ((c = getchar()) == EOF && --eargc >= 0) openfile(*eargv++);
+}
+
+static void initget()
+/* Initialise character input */
+{
+  if (--eargc >= 0) openfile(*eargv++);	/* else input == stdin */
+  get();
+}
+
+static char *getline(buf)
+/* Get next line of text to be edited, return pointer to end */
+register char *buf;		/* where to send the input */
+{
+  if (c == EOF) return BAD;
+
+  lnum++;			/* we can read a new line */
+
+  do {
+	if (c == '\n') {
+		get();
+		break;
+	}
+	if (buf <= linebuf + MAXBUF) *buf++ = c;
+	get();
+  } while (c != EOF);
+
+  if (c == EOF) lastline = TRUE;
+
+  if (buf > linebuf + MAXBUF) {
+	truncated(0);
+	--buf;
+  }
+  *buf = 0;
+  return buf;
+}
+
+static int Memcmp(a, b, count)
+/* Return TRUE if *a... == *b... for count chars, FALSE otherwise */
+register char *a, *b;
+int count;
+{
+  while (count--)		/* look at count characters */
+	if (*a++ != *b++)	/* if any are nonequal	 */
+		return(FALSE);	/* return FALSE for false */
+  return(TRUE);			/* compare succeeded */
+}
+
+static void readout()
+/* Write file indicated by r command to output */
+{
+  register int t;		/* hold input char or EOF */
+  FILE *fi;			/* ptr to file to be read */
+
+  aptr = appends - 1;		/* arrange for pre-increment to work right */
+  while (*++aptr)
+	if ((*aptr)->command == ACMD)	/* process "a" cmd */
+		printf("%s\n", (*aptr)->u.lhs);
+	else {			/* process "r" cmd */
+		if ((fi = fopen((*aptr)->u.lhs, "r")) == NULL) {
+			fprintf(stderr, "sed: can't open %s\n",
+				(*aptr)->u.lhs);
+			continue;
+		}
+		while ((t = getc(fi)) != EOF) putc((char) t, stdout);
+		fclose(fi);
+	}
+  aptr = appends;		/* reset the append ptr */
+  *aptr = 0;
+}
+
+/* Sedexec.c ends here */
Index: /trunk/minix/commands/simple/shar.c
===================================================================
--- /trunk/minix/commands/simple/shar.c	(revision 9)
+++ /trunk/minix/commands/simple/shar.c	(revision 9)
@@ -0,0 +1,71 @@
+/* shar - make a shell archive		Author: Michiel Husijes */
+
+#include <stdlib.h>		/* for the nonstd :-( _PROTOTYPE */
+#include <stdio.h>
+
+static _PROTOTYPE( void error, (char *progname, char *operation,
+				char *filename) );
+_PROTOTYPE( int main, (int argc, char **argv) );
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int argn;
+  register int ch;
+  register FILE *fp;
+  int exitstatus;
+  char *filename;
+
+  exitstatus = 0;
+  for (argn = 1; argn < argc; argn++) {
+	filename = argv[argn];
+	if ((fp = fopen(filename, "r")) == NULL) {
+		error(argv[0], "opening ", filename);
+		exitstatus = 1;
+	} else {
+		fputs("echo x - ", stdout);
+		fputs(filename, stdout);
+		fputs("\nsed '/^X/s///' > ", stdout);
+		fputs(filename, stdout);
+		fputs(" << '/'\n", stdout);
+		while ((ch = getc(fp)) != EOF) {
+			putchar('X');
+			putchar(ch);
+			while (ch != '\n') {
+				ch = getc(fp);
+				if (ch == EOF) break;
+				putchar(ch);
+			}
+			if (ch == EOF) break;
+		}
+		fputs("/\n", stdout);
+		if (ferror(fp)) {
+			error(argv[0], "reading ", filename);
+			exitstatus = 1;
+		}
+		if (fclose(fp) != 0) {
+			error(argv[0], "closing ", filename);
+			exitstatus = 1;
+		}
+		if (ferror(stdout)) break;	/* lost already */
+	}
+  }
+  fflush(stdout);
+  if (ferror(stdout)) {
+	error(argv[0], "writing ", "stdout");
+	exitstatus = 1;
+  }
+  return(exitstatus);
+}
+
+static void error(progname, operation, filename)
+char *progname;
+char *operation;
+char *filename;
+{
+  fputs(progname, stderr);
+  fputs(": error ", stderr);
+  fputs(operation, stderr);
+  perror(filename);
+}
Index: /trunk/minix/commands/simple/size.c
===================================================================
--- /trunk/minix/commands/simple/size.c	(revision 9)
+++ /trunk/minix/commands/simple/size.c	(revision 9)
@@ -0,0 +1,64 @@
+/* size - tell size of an object file		Author: Andy Tanenbaum */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <a.out.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+int heading;			/* set when heading printed */
+int error;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void size, (char *name));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i;
+
+  if (argc == 1) {
+	size("a.out");
+	exit(error);
+  }
+  for (i = 1; i < argc; i++) size(argv[i]);
+  return(error);
+}
+
+
+
+void size(name)
+char *name;
+{
+  int fd, separate;
+  long dynam, allmem;
+  struct exec exec;
+
+  if ((fd = open(name, O_RDONLY)) < 0) {
+	fprintf(stderr, "size: can't open %s\n", name);
+	error = 1;
+	return;
+  }
+  if (read(fd, (char *)&exec, sizeof(struct exec)) != sizeof(struct exec)) {
+	fprintf(stderr, "size: %s: header too short\n", name);
+	error = 1;
+	close(fd);
+	return;
+  }
+  if (BADMAG(exec)) {
+	fprintf(stderr, "size: %s not an object file\n", name);
+	error = 1;
+	close(fd);
+	return;
+  }
+  separate = (exec.a_flags & A_SEP ? 1 : 0);
+  dynam = exec.a_total - exec.a_text - exec.a_data - exec.a_bss;
+  if (separate) dynam += exec.a_text;
+  allmem = (separate ? exec.a_total + exec.a_text : exec.a_total);
+  if (heading++ == 0) printf("   text    data     bss    stack   memory\n");
+  printf("%7ld %7ld %7ld %8ld %8ld  %s\n",
+         exec.a_text, exec.a_data, exec.a_bss, dynam, allmem, name);
+  close(fd);
+}
Index: /trunk/minix/commands/simple/sleep.c
===================================================================
--- /trunk/minix/commands/simple/sleep.c	(revision 9)
+++ /trunk/minix/commands/simple/sleep.c	(revision 9)
@@ -0,0 +1,34 @@
+/* sleep - suspend a process for x sec		Author: Andy Tanenbaum */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <minix/minlib.h>
+
+_PROTOTYPE(int main, (int argc, char **argv));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  register seconds;
+  register char c;
+
+  seconds = 0;
+
+  if (argc != 2) {
+	std_err("Usage: sleep time\n");
+	exit(1);
+  }
+  while (c = *(argv[1])++) {
+	if (c < '0' || c > '9') {
+		std_err("sleep: bad arg\n");
+		exit(1);
+	}
+	seconds = 10 * seconds + (c - '0');
+  }
+
+  /* Now sleep. */
+  sleep(seconds);
+  return(0);
+}
Index: /trunk/minix/commands/simple/slip.c
===================================================================
--- /trunk/minix/commands/simple/slip.c	(revision 9)
+++ /trunk/minix/commands/simple/slip.c	(revision 9)
@@ -0,0 +1,323 @@
+/*	slip 1.1 - Serial line IP			Author: Kees J. Bot
+ *								19 Jul 1997
+ */
+#define nil 0
+#include <sys/types.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/asynchio.h>
+
+#if __minix && !__minix_vmd
+#define HAS_ASYN	0	/* Standard Minix doesn't have async I/O. */
+#else
+#define HAS_ASYN	1	/* Everyone else does in some way. */
+#endif
+
+#if !HAS_ASYN
+#include <signal.h>
+#endif
+
+#define END		0300		/* End of packet. */
+#define ESC		0333		/* Byte stuffing escape. */
+#define ESC_END		0334		/* END -> ESC ESC_END -> END. */
+#define ESC_ESC		0335		/* ESC -> ESC ESC_ESC -> ESC. */
+
+#define PACKLEN		2048		/* Max datagram size. */
+#define SLIPLEN   (1 + 2*PACKLEN + 1)	/* Max serial size when all escaped. */
+
+/* Pathetic fprintf() clone to avoid dragging in the stdio library. */
+static int fprintf(int fd, const char *format, ...);
+#define stderr	2
+
+int main(int argc, char **argv)
+{
+    char *ps_device;
+    int ps_fd;
+    int doing[2], discard;
+    ssize_t r;
+#if !HAS_ASYN
+    pid_t other_pid;
+#endif
+    size_t ps_len[2], sl_len[2];
+    unsigned char *sl_end;
+    unsigned char ps_buf[2][PACKLEN];
+    unsigned char sl_buf[2][SLIPLEN];
+    asynchio_t asyn;
+
+    if (argc != 2) {
+	fprintf(stderr, "Usage: slip psip-device\n");
+	exit(1);
+    }
+    ps_device= argv[1];
+
+    if ((ps_fd= open(ps_device, O_RDWR)) < 0) {
+	fprintf(stderr, "slip: can't open %s: %s\n",
+	    ps_device, strerror(errno));
+	exit(1);
+    }
+
+    doing[0]= 1;	/* We're doing serial -> psip. */
+    discard= 0;		/* No input error. */
+    sl_len[0]= 0;	/* Nothing read from serial line yet. */
+    sl_end= nil;	/* No END marker seen. */
+    ps_len[0]= 0;	/* Nothing to write to pseudo IP device. */
+
+    doing[1]= 1;	/* We're doing psip -> serial. */
+    sl_len[1]= 0;	/* Nothing read from pseudo IP device yet. */
+    ps_len[1]= 0;	/* Nothing to write to serial line. */
+
+#if !HAS_ASYN
+    /* Oops, standard Minix can't do asynchronous I/O.  Fork and let the parent
+     * do serial -> psip, and the child do psip -> serial.  (Note that we have
+     * to make sure that we're not reading and writing at the same time even
+     * for standard Minix.  For Minix-vmd we do fill an input buffer while an
+     * output buffer is waiting to be drained to improve performance a bit.)
+     */
+    switch ((other_pid= fork())) {
+    case -1:
+	fprintf(stderr, "slip: can't fork: %s\n", strerror(errno));
+	exit(1);
+    case 0:
+	/* Child. */
+	doing[0]= 0;	/* *Not* doing serial -> psip. */
+	other_pid= getppid();
+	break;
+    default:
+	/* Parent. */
+	doing[1]= 0;	/* *Not* doing psip -> serial. */
+    }
+#endif
+
+    asyn_init(&asyn);
+
+    for (;;) {
+	if (doing[0]) {
+	    /* If there is an END marker in the serial input then create
+	     * an IP packet to be send to the TCP/IP task.
+	     */
+	    while (sl_end != nil && ps_len[0] == 0) {
+		unsigned char *sp= sl_buf[0];
+		unsigned char *pp= ps_buf[0];
+
+		while (sp < sl_end) {
+		    int c= *sp++;
+
+		    if (c == ESC) {
+			switch (*sp++) {
+			case ESC_ESC:	/* ESC ESC_ESC -> ESC. */
+			    c= ESC;
+			    break;
+			case ESC_END:	/* ESC ESC_END -> END. */
+			    c= END;
+			    break;
+			default:
+			    /* Protocol error. */
+			    discard= 1;
+			}
+		    }
+		    if (pp < ps_buf[0] + PACKLEN) {
+			*pp++ = c;
+		    } else {
+			/* Packet too big, discard. */
+			discard= 1;
+		    }
+		}
+		if (discard) {
+		    discard= 0;
+		} else {
+		    /* A new packet can be send to the TCP/IP server. */
+		    ps_len[0]= (pp - ps_buf[0]);
+		}
+		/* Move what's beyond END to the front. */
+		sl_end++;
+		sl_len[0] -= (sl_end - sl_buf[0]);
+		memmove(sl_buf[0], sl_end, sl_len[0]);
+		sl_end= memchr(sl_buf[0], END, sl_len[0]);
+	    }
+
+	    /* Reading from serial input. */
+	    if (sl_end == nil && (HAS_ASYN || ps_len[0] == 0)) {
+		r= asyn_read(&asyn, 0, sl_buf[0] + sl_len[0],
+							SLIPLEN - sl_len[0]);
+		if (r > 0) {
+		    sl_end= memchr(sl_buf[0] + sl_len[0], END, r);
+		    sl_len[0]+= r;
+		    if (sl_end == nil && sl_len[0] == SLIPLEN) {
+			/* Packet is idiotically big and no END in sight. */
+			sl_len[0]= 0;
+			discard= 1;
+		    }
+		} else
+		if (r == 0) {
+		    fprintf(stderr, "slip: EOF on serial input\n");
+		    break;
+		} else
+		if (errno != ASYN_INPROGRESS) {
+		    fprintf(stderr, "slip: serial input error: %s\n",
+			strerror(errno));
+		    break;
+		}
+	    }
+
+	    /* Writing to the psip device. */
+	    if (ps_len[0] > 0) {
+		r= asyn_write(&asyn, ps_fd, ps_buf[0], ps_len[0]);
+		if (r == ps_len[0]) {
+		    /* Packet written. */
+		    ps_len[0]= 0;
+		} else
+		if (r >= 0) {
+		    fprintf(stderr,
+			"slip: odd write to %s, tried %u, wrote %d\n",
+			ps_device, (unsigned) ps_len[0], (int) r);
+		    break;
+		} else
+		if (errno != ASYN_INPROGRESS) {
+		    fprintf(stderr, "slip: error writing %s: %s\n",
+			ps_device, strerror(errno));
+		    break;
+		}
+	    }
+	}
+
+	if (doing[1]) {
+	    /* Transform an IP packet to a "byte stuffed" serial packet. */
+	    if (ps_len[1] > 0 && sl_len[1] == 0) {
+		unsigned char *pp= ps_buf[1];
+		unsigned char *sp= sl_buf[1];
+
+		*sp++ = END;
+		while (ps_len[1] > 0) {
+		    int c= *pp++;
+		    ps_len[1]--;
+		    switch (c) {
+		    case ESC:		/* ESC -> ESC ESC_ESC. */
+			*sp++ = ESC;
+			c= ESC_ESC;
+			break;
+		    case END:		/* END -> ESC ESC_END. */
+			*sp++ = ESC;
+			c= ESC_END;
+			break;
+		    }
+		    *sp++ = c;
+		}
+		*sp++ = END;
+		sl_len[1]= (sp - sl_buf[1]);
+	    }
+
+	    /* Reading from the psip device. */
+	    if (ps_len[1] == 0 && (HAS_ASYN || sl_len[1] == 0)) {
+		r= asyn_read(&asyn, ps_fd, ps_buf[1], PACKLEN);
+		if (r > 0) {
+		    /* One packet read. */
+		    ps_len[1]= r;
+		} else
+		if (r == 0) {
+		    fprintf(stderr, "slip: EOF on %s\n", ps_device);
+		    break;
+		} else
+		if (errno != ASYN_INPROGRESS) {
+		    fprintf(stderr, "slip: error reading %s: %s\n",
+			ps_device, strerror(errno));
+		    break;
+		}
+	    }
+
+	    /* Writing to serial output. */
+	    if (sl_len[1] > 0) {
+		r= asyn_write(&asyn, 1, sl_buf[1], sl_len[1]);
+		if (r > 0) {
+		    if ((sl_len[1]-= r) > 0) {
+			memmove(sl_buf[1], sl_buf[1] + r, sl_len[1]);
+		    }
+		} else
+		if (r == 0) {
+		    fprintf(stderr, "slip: EOF on serial output\n");
+		    break;
+		} else
+		if (errno != ASYN_INPROGRESS) {
+		    fprintf(stderr, "slip: serial output error: %s\n",
+			strerror(errno));
+		    break;
+		}
+	    }
+	}
+
+	/* Wait for something to happen. */
+	if (asyn_wait(&asyn, 0, nil) < 0) {
+	    fprintf(stderr,
+		"slip: error while waiting for I/O to happen: %s\n",
+		strerror(errno));
+	    break;
+	}
+    }
+#if !HAS_ASYN
+    /* Tell my alter ego that the game is over. */
+    kill(other_pid, SIGKILL);
+#endif
+    return 1;
+}
+
+static int fprintf(int fd, const char *format, ...)
+/* Simple fprintf() to save a few bytes by not using the stdio library. */
+{
+    int len;
+    ssize_t r;
+    const char *fp0, *fp;
+    va_list ap;
+
+    len= 0;
+    fp= fp0= format;
+    va_start(ap, format);
+
+    while (*fp != 0) {
+	if (*fp == '%' && memchr("sdu", fp[1], 3) != nil) {
+	    if (fp > fp0) {
+		if ((r= write(fd, fp0, (fp - fp0))) < 0) return -1;
+		len+= r;
+	    }
+	    fp++;
+	    fp0= fp+1;
+
+	    if (*fp == 's') {
+		char *s= va_arg(ap, char *);
+
+		if ((r= write(fd, s, strlen(s))) < 0) return -1;
+		len+= r;
+	    } else {
+		int d;
+		unsigned u;
+		char a[3 * sizeof(u) + 2];
+		char *p;
+
+		if (*fp == 'd') {
+		    u= d= va_arg(ap, int);
+		    if (d < 0) u= -u;
+		} else {
+		    u= va_arg(ap, unsigned);
+		    d= 0;
+		}
+
+		p= a + sizeof(a);
+		*--p= 0;
+		do *--p= '0' + (u % 10); while ((u /= 10) > 0);
+
+		if (d < 0) *--p= '-';
+		if ((r= write(fd, p, (a + sizeof(a)) - p)) < 0) return -1;
+		len+= r;
+	    }
+	}
+	fp++;
+    }
+    if (fp > fp0) {
+	if ((r= write(fd, fp0, (fp - fp0))) < 0) return -1;
+	len+= r;
+    }
+    va_end(ap);
+    return len;
+}
Index: /trunk/minix/commands/simple/sort.c
===================================================================
--- /trunk/minix/commands/simple/sort.c	(revision 9)
+++ /trunk/minix/commands/simple/sort.c	(revision 9)
@@ -0,0 +1,1193 @@
+/* sort - sort a file of lines		Author: Michiel Huisjes */
+
+/* SYNOPSIS:
+ * 	sort [-funbirdcmt'x'] [+beg_pos[opts] [-end_pos]] [-o outfile] [file]..
+ *
+ * 	[opts] can be any of
+ * 	-f : Fold upper case to lower.
+ * 	-n : Sort to numeric value (optional decimal point) implies -b
+ * 	-b : Skip leading blanks
+ * 	-i : Ignore chars outside ASCII range (040 - 0176)
+ * 	-r : Reverse the sense of comparisons.
+ * 	-d : Sort to dictionary order. Only letters, digits, comma's and points
+ * 	     are compared.
+ * 	If any of these flags are used in [opts], then they override all global
+ * 	ordering for this field.
+ *
+ * 	I/O control flags are:
+ * 	-u : Print uniq lines only once.
+ * 	-c : Check if files are sorted in order.
+ * 	-m : Merge already sorted files.
+ * 	-o outfile : Name of output file. (Can be one of the input files).
+ * 		     Default is stdout.
+ * 	- : Take stdin as input.
+ *
+ * 	Fields:
+ * 	-t'x' : Field separating character is 'x'
+ * 	+a.b : Start comparing at field 'a' with offset 'b'. A missing 'b' is
+ * 	       taken to be 0.
+ * 	-a.b : Stop comparing at field 'a' with offset 'b'. A missing 'b' is
+ * 	       taken to be 0.
+ * 	A missing -a.b means the rest of the line.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <limits.h>
+
+#define OPEN_FILES	(OPEN_MAX-4)	/* Nr of open files per process */
+#if __minix_vmd
+#define MEMORY_SIZE	(1024 * 1024)
+#else
+#define MEMORY_SIZE	((10 * sizeof(int)) * 1024)
+#endif
+					/* Total mem_size */
+#define LINE_SIZE	(1024 >> 1)	/* Max length of a line */
+#define IO_SIZE		(2 * 1024)	/* Size of buffered output */
+#define STD_OUT		 1	/* Fd of terminal */
+
+/* Return status of functions */
+#define OK		 0
+#define ERROR		-1
+#define NIL_PTR		((char *) 0)
+
+/* Compare return values */
+#define LOWER		-1
+#define SAME		 0
+#define HIGHER		 1
+
+/* Table definitions. */
+#define DICT		0x001	/* Alpha, numeric, letters and . */
+#define ASCII		0x002	/* All between ' ' and '~' */
+#define BLANK		0x004	/* ' ' and '\t' */
+#define DIGIT		0x008	/* 0-9 */
+#define UPPER		0x010	/* A-Z */
+
+typedef int BOOL;
+
+#define	FALSE	0
+#define	TRUE	1
+
+typedef struct {
+  int fd;			/* Fd of file */
+  char *buffer;			/* Buffer for reads */
+  int read_chars;		/* Nr of chars actually read in buffer */
+  int cnt;			/* Nr of chars taken out of buffer */
+  char *line;			/* Contains line currently used */
+} MERGE;
+
+#define NIL_MERGE	((MERGE *) 0)
+MERGE merge_f[OPEN_FILES];	/* Merge structs */
+int buf_size;			/* Size of core available for each struct */
+
+#define FIELDS_LIMIT	10	/* 1 global + 9 user */
+#define GLOBAL		 0
+
+typedef struct {
+  int beg_field, beg_pos;	/* Begin field + offset */
+  int end_field, end_pos;	/* End field + offset. ERROR == EOLN */
+  BOOL reverse;			/* TRUE if rev. flag set on this field */
+  BOOL blanks;
+  BOOL dictionary;
+  BOOL fold_case;
+  BOOL ascii;
+  BOOL numeric;
+} FIELD;
+
+/* Field declarations. A total of FILEDS_LIMIT is allowed */
+FIELD fields[FIELDS_LIMIT];
+int field_cnt;			/* Nr of field actually assigned */
+
+/* Various output control flags */
+BOOL check = FALSE;
+BOOL only_merge = FALSE;
+BOOL uniq = FALSE;
+
+char *mem_top;			/* Mem_top points to lowest pos of memory. */
+char *cur_pos;			/* First free position in mem */
+char **line_table;		/* Pointer to the internal line table */
+BOOL in_core = TRUE;		/* Set if input cannot all be sorted in core */
+
+ /* Place where temp_files should be made */
+char temp_files[] = "/tmp/sort.XXXXX.XX";
+char *output_file;		/* Name of output file */
+int out_fd;			/* Fd to output file (could be STD_OUT) */
+char out_buffer[IO_SIZE];	/* For buffered output */
+
+char **argptr;			/* Pointer to argv structure */
+int args_offset;		/* Nr of args spilled on options */
+int args_limit;			/* Nr of args given */
+
+char separator;			/* Char that separates fields */
+int nr_of_files = 0;		/* Nr_of_files to be merged */
+int disabled;			/* Nr of files done */
+
+char USAGE[] = "Usage: sort [-funbirdcmt'x'] [+beg_pos [-end_pos]] [-o outfile] [file] ..";
+
+/* Forward declarations */
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void get_opts, (char *ptr, FIELD * field));
+_PROTOTYPE(void new_field, (FIELD * field, int *offset, BOOL beg_fl));
+_PROTOTYPE(void adjust_options, (FIELD * field));
+_PROTOTYPE(void error, (BOOL quit, char *message, char *arg));
+_PROTOTYPE(void open_outfile, (void));
+_PROTOTYPE(void get_file, (int fd, off_t size));
+_PROTOTYPE(int last_line, (void));
+_PROTOTYPE(void print_table, (int fd));
+_PROTOTYPE(char *file_name, (int nr));
+_PROTOTYPE(void mread, (int fd, char *address, int bytes));
+_PROTOTYPE(void mwrite, (int fd, char *address, int bytes));
+_PROTOTYPE(void sort, (void));
+_PROTOTYPE(void sort_table, (int nel));
+_PROTOTYPE(void incr, (int si, int ei));
+_PROTOTYPE(int cmp_fields, (char *el1, char *el2));
+_PROTOTYPE(void build_field, (char *dest, FIELD * field, char *src));
+_PROTOTYPE(char *skip_fields, (char *str, int nf));
+_PROTOTYPE(int compare, (char *el1, char *el2));
+_PROTOTYPE(int cmp, (unsigned char *el1, unsigned char *el2, FIELD * field));
+_PROTOTYPE(int digits, (char *str1, char *str2, BOOL check_sign));
+_PROTOTYPE(void files_merge, (int file_cnt));
+_PROTOTYPE(void merge, (int start_file, int limit_file));
+_PROTOTYPE(void put_line, (char *line));
+_PROTOTYPE(MERGE * print, (MERGE * merg, int file_cnt));
+_PROTOTYPE(int read_line, (MERGE * merg));
+_PROTOTYPE(MERGE * skip_lines, (MERGE * smallest, int file_cnt));
+_PROTOTYPE(void uniq_lines, (MERGE * merg));
+_PROTOTYPE(void check_file, (int fd, char *file));
+_PROTOTYPE(int length, (char *line));
+_PROTOTYPE(void copy, (char *dest, char *src));
+_PROTOTYPE(char *msbrk, (int size));
+_PROTOTYPE(void mbrk, (char *address));
+_PROTOTYPE(void catch, (int dummy));
+
+/* Table of all chars. 0 means no special meaning. */
+char table[256] = {
+/* '^@' to space */
+	   0, 0, 0, 0, 0, 0, 0, 0,
+	   0, BLANK | DICT, 0, 0, 0, 0, 0, 0,
+	   0, 0, 0, 0, 0, 0, 0, 0,
+	   0, 0, 0, 0, 0, 0, 0, 0,
+
+/* Space to '0' */
+       BLANK | DICT | ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,
+	   ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,
+	   ASCII, ASCII,
+
+/* '0' until '9' */
+     DIGIT | DICT | ASCII, DIGIT | DICT | ASCII, DIGIT | DICT | ASCII,
+     DIGIT | DICT | ASCII, DIGIT | DICT | ASCII, DIGIT | DICT | ASCII,
+     DIGIT | DICT | ASCII, DIGIT | DICT | ASCII, DIGIT | DICT | ASCII,
+	   DIGIT | DICT | ASCII,
+
+/* ASCII from ':' to '@' */
+	   ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,
+
+/* Upper case letters 'A' to 'Z' */
+     UPPER | DICT | ASCII, UPPER | DICT | ASCII, UPPER | DICT | ASCII,
+     UPPER | DICT | ASCII, UPPER | DICT | ASCII, UPPER | DICT | ASCII,
+     UPPER | DICT | ASCII, UPPER | DICT | ASCII, UPPER | DICT | ASCII,
+     UPPER | DICT | ASCII, UPPER | DICT | ASCII, UPPER | DICT | ASCII,
+     UPPER | DICT | ASCII, UPPER | DICT | ASCII, UPPER | DICT | ASCII,
+     UPPER | DICT | ASCII, UPPER | DICT | ASCII, UPPER | DICT | ASCII,
+     UPPER | DICT | ASCII, UPPER | DICT | ASCII, UPPER | DICT | ASCII,
+     UPPER | DICT | ASCII, UPPER | DICT | ASCII, UPPER | DICT | ASCII,
+	   UPPER | DICT | ASCII, UPPER | DICT | ASCII,
+
+/* ASCII from '[' to '`' */
+	   ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,
+
+/* Lower case letters from 'a' to 'z' */
+	   DICT | ASCII, DICT | ASCII, DICT | ASCII, DICT | ASCII,
+	   DICT | ASCII, DICT | ASCII, DICT | ASCII, DICT | ASCII,
+	   DICT | ASCII, DICT | ASCII, DICT | ASCII, DICT | ASCII,
+	   DICT | ASCII, DICT | ASCII, DICT | ASCII, DICT | ASCII,
+	   DICT | ASCII, DICT | ASCII, DICT | ASCII, DICT | ASCII,
+	   DICT | ASCII, DICT | ASCII, DICT | ASCII, DICT | ASCII,
+	   DICT | ASCII, DICT | ASCII,
+
+/* ASCII from '{' to '~' */
+	   ASCII, ASCII, ASCII, ASCII,
+
+/* Stuff from -1 to -177 */
+	   0, 0, 0, 0, 0, 0, 0, 0, 0,
+	   0, 0, 0, 0, 0, 0, 0, 0, 0,
+	   0, 0, 0, 0, 0, 0, 0, 0, 0,
+	   0, 0, 0, 0, 0, 0, 0, 0, 0,
+	   0, 0, 0, 0, 0, 0, 0, 0, 0,
+	   0, 0, 0, 0, 0, 0, 0, 0, 0,
+	   0, 0, 0, 0, 0, 0, 0, 0, 0,
+	   0, 0, 0, 0, 0, 0, 0, 0, 0,
+	   0, 0, 0, 0, 0, 0, 0
+};
+
+
+/*
+ * Get_opts () assigns the options into the field structure as described in ptr.
+ * This field structure could be the GLOBAL one.
+ */
+void get_opts(ptr, field)
+register char *ptr;
+register FIELD *field;
+{
+  switch (*ptr) {
+      case 'b':			/* Skip leading blanks */
+	field->blanks = TRUE;
+	break;
+      case 'd':			/* Dictionary order */
+	field->dictionary = TRUE;
+	break;
+      case 'f':			/* Fold upper case to lower */
+	field->fold_case = TRUE;
+	break;
+      case 'i':			/* Skip chars outside ' ' '~' */
+	field->ascii = TRUE;
+	break;
+      case 'n':			/* Sort on numeric */
+	field->numeric = TRUE;
+	field->blanks = TRUE;
+	break;
+      case 'r':			/* Reverse comparisons */
+	field->reverse = TRUE;
+	break;
+      default:			/* Illegal options */
+	error(TRUE, USAGE, NIL_PTR);
+  }
+}
+
+/* New_field () assigns a new field as described by the arguments.
+ * A field description is of the form: +a.b[opts] -c.d, where b and d, as well
+ * as -c.d and [opts] are optional. Nr before digit is field nr. Nr after digit
+ * is offset from field.
+ */
+void new_field(field, offset, beg_fl)
+register FIELD *field;		/* Field to assign */
+int *offset;			/* Offset in argv structure */
+BOOL beg_fl;			/* Assign beg or end of field */
+{
+  register char *ptr;
+
+  ptr = argptr[*offset];
+  *offset += 1;			/* Incr offset to next arg */
+  ptr++;
+
+  if (beg_fl)
+	field->beg_field = atoi(ptr);	/* Assign int of first field */
+  else
+	field->end_field = atoi(ptr);
+
+  while (table[*ptr] & DIGIT)	/* Skip all digits */
+	ptr++;
+
+  if (*ptr == '.') {		/* Check for offset */
+	ptr++;
+	if (beg_fl)
+		field->beg_pos = atoi(ptr);
+	else
+		field->end_pos = atoi(ptr);
+	while (table[*ptr] & DIGIT)	/* Skip digits */
+		ptr++;
+  }
+  if (beg_fl) {
+	while (*ptr != '\0')	/* Check options after field */
+		get_opts(ptr++, field);
+  }
+  if (beg_fl) {			/* Check for end pos */
+	ptr = argptr[*offset];
+	if (ptr && *ptr == '-' && ((table[*(ptr + 1)] & DIGIT) || *(ptr + 1) == '.')) {
+		new_field(field, offset, FALSE);
+		if (field->beg_field > field->end_field)
+			error(TRUE, "End field is before start field!", NIL_PTR);
+	} else			/* No end pos. */
+		field->end_field = ERROR;
+  }
+}
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int arg_count = 1;		/* Offset in argv */
+  struct stat st;
+  register char *ptr;		/* Ptr to *argv in use */
+  register int fd;
+  int pid, pow;
+
+  argptr = argv;
+  cur_pos = mem_top = msbrk(MEMORY_SIZE);	/* Find lowest mem. location */
+
+  while (arg_count < argc && ((ptr = argv[arg_count])[0] == '-' || *ptr == '+')) {
+	if (*ptr == '-' && *(ptr + 1) == '\0')	/* "-" means stdin */
+		break;
+	if (*ptr == '+') {	/* Assign field. */
+		if (++field_cnt == FIELDS_LIMIT)
+			error(TRUE, "Too many fields", NIL_PTR);
+		new_field(&fields[field_cnt], &arg_count, TRUE);
+	} else {		/* Get output options */
+		while (*++ptr) {
+			switch (*ptr) {
+			    case 'c':	/* Only check file */
+				check = TRUE;
+				break;
+			    case 'm':	/* Merge (sorted) files */
+				only_merge = TRUE;
+				break;
+			    case 'u':	/* Only give uniq lines */
+				uniq = TRUE;
+				break;
+			    case 'o':	/* Name of output file */
+				output_file = argv[++arg_count];
+				break;
+			    case 't':	/* Field separator */
+				ptr++;
+				separator = *ptr;
+				break;
+			    default:	/* Sort options */
+				get_opts(ptr, &fields[GLOBAL]);
+			}
+		}
+		arg_count++;
+	}
+  }
+
+  for (fd = 1; fd <= field_cnt; fd++) adjust_options(&fields[fd]);
+
+/* Create name of tem_files 'sort.pid.aa' */
+  ptr = &temp_files[10];
+  pid = getpid();
+  pow = 10000;
+  while (pow != 0) {
+	*ptr++ = pid / pow + '0';
+	pid %= pow;
+	pow /= 10;
+  }
+
+  signal(SIGINT, catch);
+
+/* Only merge files. Set up */
+  if (only_merge) {
+	args_limit = args_offset = arg_count;
+	while (argv[args_limit] != NIL_PTR)
+		args_limit++;	/* Find nr of args */
+	files_merge(args_limit - arg_count);
+	exit(0);
+  }
+  if (arg_count == argc) {	/* No args left. Use stdin */
+	if (check)
+		check_file(0, NIL_PTR);
+	else
+		get_file(0, (off_t) 0);
+  } else
+	while (arg_count < argc) {	/* Sort or check args */
+		if (strcmp(argv[arg_count], "-") == 0)
+			fd = 0;
+		else if (stat(argv[arg_count], &st) < 0) {
+			error(FALSE, "Cannot find ", argv[arg_count++]);
+			continue;
+		}
+
+		/* Open files */
+		else if ((fd = open(argv[arg_count], O_RDONLY)) < 0) {
+			error(FALSE, "Cannot open ", argv[arg_count++]);
+			continue;
+		}
+		if (check)
+			check_file(fd, argv[arg_count]);
+		else		/* Get_file reads whole file */
+			get_file(fd, st.st_size);
+		arg_count++;
+	}
+
+  if (check) exit(0);
+
+  sort();			/* Sort whatever is left */
+
+  if (nr_of_files == 1)		/* Only one file sorted -> don't merge */
+	exit(0);
+
+  files_merge(nr_of_files);
+  return(0);
+}
+
+/* Adjust_options() assigns all global variables set also in the fields
+ * assigned.
+ */
+void adjust_options(field)
+register FIELD *field;
+{
+  register FIELD *gfield = &fields[GLOBAL];
+
+  if (gfield->reverse) field->reverse = TRUE;
+  if (gfield->blanks) field->blanks = TRUE;
+  if (gfield->dictionary) field->dictionary = TRUE;
+  if (gfield->fold_case) field->fold_case = TRUE;
+  if (gfield->ascii) field->ascii = TRUE;
+  if (gfield->numeric) field->numeric = TRUE;
+}
+
+/* Error () prints the error message on stderr and exits if quit == TRUE. */
+void error(quit, message, arg)
+register BOOL quit;
+register char *message, *arg;
+{
+  write(2, message, strlen(message));
+  if (arg != NIL_PTR) write(2, arg, strlen(arg));
+  perror(" ");
+  if (quit) exit(1);
+}
+
+/* Open_outfile () assigns to out_fd the fd where the output must go when all
+ * the sorting is done.
+ */
+void open_outfile()
+{
+  if (output_file == NIL_PTR)
+	out_fd = STD_OUT;
+  else if ((out_fd = creat(output_file, 0644)) < 0)
+	error(TRUE, "Cannot creat ", output_file);
+}
+
+/* Get_file reads the whole file of filedescriptor fd. If the file is too big
+ * to keep in core, a partial sort is done, and the output is stashed somewhere.
+ */
+void get_file(fd, size)
+int fd;				/* Fd of file to read */
+register off_t size;		/* Size of file */
+{
+  register int i;
+  int rest;			/* Rest in memory */
+  char save_ch;			/* Used in stdin readings */
+
+  rest = MEMORY_SIZE - (cur_pos - mem_top);
+  if (fd == 0) {		/* We're reding stdin */
+	while ((i = read(0, cur_pos, rest)) > 0) {
+		if ((cur_pos - mem_top) + i == MEMORY_SIZE) {
+			in_core = FALSE;
+			i = last_line();	/* End of last line */
+			save_ch = mem_top[i];
+			mem_top[i] = '\0';
+			sort();	/* Sort core */
+			mem_top[i] = save_ch;	/* Restore erased char */
+			/* Restore last (half read) line */
+			for (rest = 0; i + rest != MEMORY_SIZE; rest++)
+				mem_top[rest] = mem_top[i + rest];
+			/* Assign current pos. in memory */
+			cur_pos = &mem_top[rest];
+		} else {	/* Fits, just assign position in mem. */
+			cur_pos = cur_pos + i;
+			*cur_pos = '\0';
+		}
+
+		/* Calculate rest of mem */
+		rest = MEMORY_SIZE - (cur_pos - mem_top);
+	}
+  }
+
+  /* Reading file. Check size */
+  else if (size > rest) {	/* Won't fit */
+	mread(fd, cur_pos, rest);
+	in_core = FALSE;
+	i = last_line();	/* Get pos. of last line */
+	mem_top[i] = '\0';	/* Truncate */
+	(void) lseek(fd, (off_t) (i - MEMORY_SIZE), SEEK_CUR);	/* Do this next time */
+	size = size - rest - i + MEMORY_SIZE;	/* Calculate rest */
+	cur_pos = mem_top;	/* Reset mem */
+	sort();			/* Sort core */
+	get_file(fd, size);	/* Get rest of file */
+  } else {			/* Fits. Just read in */
+	rest = size;
+	mread(fd, cur_pos, rest);
+	cur_pos = cur_pos + rest;	/* Reassign cur_pos */
+	*cur_pos = '\0';
+	(void) close(fd);	/* File completed */
+  }
+}
+
+/* Last_line () find the last line in core and retuns the offset from the top
+ * of the memory.
+ */
+int last_line()
+{
+  register int i;
+
+  for (i = MEMORY_SIZE - 2; i > 0; i--)
+	if (mem_top[i] == '\n') break;
+  return i + 1;
+}
+
+/* Print_table prints the line table in the given file_descriptor. If the fd
+ * equals ERROR, it opens a temp_file itself.
+ */
+void print_table(fd)
+int fd;
+{
+  register char **line_ptr;	/* Ptr in line_table */
+  register char *ptr;		/* Ptr to line */
+  int index = 0;		/* Index in output buffer */
+
+  if (fd == ERROR) {
+	if ((fd = creat(file_name(nr_of_files), 0644)) < 0)
+		error(TRUE, "Cannot creat ", file_name(nr_of_files));
+  }
+  for (line_ptr = line_table; *line_ptr != NIL_PTR; line_ptr++) {
+	ptr = *line_ptr;
+	/* Skip all same lines if uniq is set */
+	if (uniq && *(line_ptr + 1) != NIL_PTR) {
+		if (compare(ptr, *(line_ptr + 1)) == SAME) continue;
+	}
+	do {			/* Print line in a buffered way */
+		out_buffer[index++] = *ptr;
+		if (index == IO_SIZE) {
+			mwrite(fd, out_buffer, IO_SIZE);
+			index = 0;
+		}
+	} while (*ptr++ != '\n');
+  }
+  mwrite(fd, out_buffer, index);/* Flush buffer */
+  (void) close(fd);		/* Close file */
+  nr_of_files++;		/* Increment nr_of_files to merge */
+}
+
+/* File_name () returns the nr argument from the argument list, or a uniq
+ * filename if the nr is too high, or the arguments were not merge files.
+ */
+char *file_name(nr)
+register int nr;
+{
+  if (only_merge) {
+	if (args_offset + nr < args_limit) return argptr[args_offset + nr];
+  }
+  temp_files[16] = nr / 26 + 'a';
+  temp_files[17] = nr % 26 + 'a';
+
+  return temp_files;
+}
+
+/* Mread () performs a normal read (), but checks the return value. */
+void mread(fd, address, bytes)
+int fd;
+char *address;
+register int bytes;
+{
+  if (read(fd, address, bytes) < 0 && bytes != 0)
+	error(TRUE, "Read error", NIL_PTR);
+}
+
+/* Mwrite () performs a normal write (), but checks the return value. */
+void mwrite(fd, address, bytes)
+int fd;
+char *address;
+register int bytes;
+{
+  if (write(fd, address, bytes) != bytes && bytes != 0)
+	error(TRUE, "Write error", NIL_PTR);
+}
+
+/* Sort () sorts the input in memory starting at mem_top. */
+void sort()
+{
+  register char *ptr = mem_top;
+  register int count = 0;
+
+/* Count number of lines in memory */
+  while (*ptr) {
+	if (*ptr++ == '\n') count++;
+  }
+
+/* Set up the line table */
+  line_table = (char **) msbrk(count * sizeof(char *) + sizeof(char *));
+
+  count = 1;
+  ptr = line_table[0] = mem_top;
+  while (*ptr) {
+	if (*ptr++ == '\n') line_table[count++] = ptr;
+  }
+
+  line_table[count - 1] = NIL_PTR;
+
+/* Sort the line table */
+  sort_table(count - 1);
+
+/* Stash output somewhere */
+  if (in_core) {
+	open_outfile();
+	print_table(out_fd);
+  } else
+	print_table(ERROR);
+
+/* Free line table */
+  mbrk((char *) line_table);
+}
+
+/* Sort_table () sorts the line table consisting of nel elements. */
+void sort_table(nel)
+register int nel;
+{
+  char *tmp;
+  register int i;
+
+  /* Make heap */
+  for (i = (nel >> 1); i >= 1; i--) incr(i, nel);
+
+  /* Sort from heap */
+  for (i = nel; i > 1; i--) {
+	tmp = line_table[0];
+	line_table[0] = line_table[i - 1];
+	line_table[i - 1] = tmp;
+	incr(1, i - 1);
+  }
+}
+
+/* Incr () increments the heap. */
+void incr(si, ei)
+register int si, ei;
+{
+  char *tmp;
+
+  while (si <= (ei >> 1)) {
+	si <<= 1;
+	if (si + 1 <= ei && compare(line_table[si - 1], line_table[si]) <= 0)
+		si++;
+	if (compare(line_table[(si >> 1) - 1], line_table[si - 1]) >= 0)
+		return;
+	tmp = line_table[(si >> 1) - 1];
+	line_table[(si >> 1) - 1] = line_table[si - 1];
+	line_table[si - 1] = tmp;
+  }
+}
+
+/* Cmp_fields builds new lines out of the lines pointed to by el1 and el2 and
+ * puts it into the line1 and line2 arrays. It then calls the cmp () routine
+ * with the field describing the arguments.
+ */
+int cmp_fields(el1, el2)
+register char *el1, *el2;
+{
+  int i, ret;
+  char line1[LINE_SIZE], line2[LINE_SIZE];
+
+  for (i = 0; i < field_cnt; i++) {	/* Setup line parts */
+	build_field(line1, &fields[i + 1], el1);
+	build_field(line2, &fields[i + 1], el2);
+	if ((ret = cmp((unsigned char *) line1, (unsigned char *) line2,
+		       &fields[i + 1])) != SAME)
+		break;		/* If equal, try next field */
+  }
+
+/* Check for reverse flag */
+  if (i != field_cnt && fields[i + 1].reverse) return -ret;
+
+/* Else return the last return value of cmp () */
+  return ret;
+}
+
+/* Build_field builds a new line from the src as described by the field.
+ * The result is put in dest.
+ */
+void build_field(dest, field, src)
+char *dest;			/* Holds result */
+register FIELD *field;		/* Field description */
+register char *src;		/* Source line */
+{
+  char *begin = src;		/* Remember start location */
+  char *last;			/* Pointer to end location */
+  int i;
+
+/* Skip begin fields */
+  src = skip_fields(src, field->beg_field);
+
+/* Skip begin positions */
+  for (i = 0; i < field->beg_pos && *src != '\n'; i++) src++;
+
+/* Copy whatever is left */
+  copy(dest, src);
+
+/* If end field is assigned truncate (perhaps) the part copied */
+  if (field->end_field != ERROR) {	/* Find last field */
+	last = skip_fields(begin, field->end_field);
+/* Skip positions as given by end fields description */
+	for (i = 0; i < field->end_pos && *last != '\n'; i++) last++;
+	dest[last - src] = '\n';/* Truncate line */
+  }
+}
+
+/* Skip_fields () skips nf fields of the line pointed to by str. */
+char *skip_fields(str, nf)
+register char *str;
+int nf;
+{
+  while (nf-- > 0) {
+	if (separator == '\0') {/* Means ' ' or '\t' */
+		while (*str != ' ' && *str != '\t' && *str != '\n') str++;
+		while (table[*str] & BLANK) str++;
+	} else {
+		while (*str != separator && *str != '\n') str++;
+		if (*str == separator) str++;
+	}
+  }
+  return str;			/* Return pointer to indicated field */
+}
+
+/* Compare is called by all sorting routines. It checks if fields assignments
+ * has been made. if so, it calls cmp_fields (). If not, it calls cmp () and
+ * reversed the return value if the (global) reverse flag is set.
+ */
+int compare(el1, el2)
+register char *el1, *el2;
+{
+  int ret;
+
+  if (field_cnt > GLOBAL) return cmp_fields(el1, el2);
+
+  ret = cmp((unsigned char *) el1, (unsigned char *) el2, &fields[GLOBAL]);
+  return(fields[GLOBAL].reverse) ? -ret : ret;
+}
+
+/* Cmp () is the actual compare routine. It compares according to the
+ * description given in the field pointer.
+ */
+int cmp(el1, el2, field)
+register unsigned char *el1, *el2;
+FIELD *field;
+{
+  int c1, c2;
+
+  if (field->blanks) {		/* Skip leading blanks */
+	while (table[*el1] & BLANK) el1++;
+	while (table[*el2] & BLANK) el2++;
+  }
+  if (field->numeric)		/* Compare numeric */
+	return digits((char *) el1, (char *) el2, TRUE);
+
+  for (;;) {
+	while (*el1 == *el2) {
+		if (*el1++ == '\n')	/* EOLN on both strings */
+			return SAME;
+		el2++;
+	}
+	if (*el1 == '\n')	/* EOLN on string one */
+		return LOWER;
+	if (*el2 == '\n') return HIGHER;
+	if (field->ascii) {	/* Skip chars outside 040 - 0177 */
+		if ((table[*el1] & ASCII) == 0) {
+			do {
+				el1++;
+			} while ((table[*el1] & ASCII) == 0);
+			continue;
+		}
+		if ((table[*el2] & ASCII) == 0) {
+			do {
+				el2++;
+			} while ((table[*el2] & ASCII) == 0);
+			continue;
+		}
+	}
+	if (field->dictionary) {/* Skip non-dict chars */
+		if ((table[*el1] & DICT) == 0) {
+			do {
+				el1++;
+			} while ((table[*el1] & DICT) == 0);
+			continue;
+		}
+		if ((table[*el2] & DICT) == 0) {
+			do {
+				el2++;
+			} while ((table[*el2] & DICT) == 0);
+			continue;
+		}
+	}
+	if (field->fold_case) {	/* Fold upper case to lower */
+		if (table[c1 = *el1++] & UPPER) c1 += 'a' - 'A';
+		if (table[c2 = *el2++] & UPPER) c2 += 'a' - 'A';
+		if (c1 == c2) continue;
+		return c1 - c2;
+	}
+	return *el1 - *el2;
+  }
+
+  /* NOTREACHED */
+}
+
+/*
+ * Digits compares () the two strings that point to a number of digits followed
+ * by an optional decimal point.
+ */
+int digits(str1, str2, check_sign)
+register char *str1, *str2;
+BOOL check_sign;		/* True if sign must be checked */
+{
+  BOOL negative = FALSE;	/* True if negative numbers */
+  int diff, pow, ret;
+
+/* Check for optional minus or plus sign */
+  if (check_sign) {
+	if (*str1 == '-') {
+		negative = TRUE;
+		str1++;
+	} else if (*str1 == '+')
+		str1++;
+
+	if (*str2 == '-') {
+		if (negative == FALSE) return HIGHER;
+		str2++;
+	} else if (negative)
+		return LOWER;
+	else if (*str2 == '+')
+		str2++;
+  }
+
+/* Keep incrementing as long as digits are available and equal */
+  while ((table[*str1] & DIGIT) && table[*str2] & DIGIT) {
+	if (*str1 != *str2) break;
+	str1++;
+	str2++;
+  }
+
+/* First check for the decimal point. */
+  if (*str1 == '.' || *str2 == '.') {
+	if (*str1 == '.') {
+		if (*str2 == '.')	/* Both. Check decimal part */
+			ret = digits(str1 + 1, str2 + 1, FALSE);
+		else
+			ret = (table[*str2] & DIGIT) ? LOWER : HIGHER;
+	} else
+		ret = (table[*str1] & DIGIT) ? HIGHER : LOWER;
+  }
+
+/* Now either two digits differ, or unknown char is seen (e.g. end of string) */
+  else if ((table[*str1] & DIGIT) && (table[*str2] & DIGIT)) {
+	diff = *str1 - *str2;	/* Basic difference */
+	pow = 0;		/* Check power of numbers */
+	while (table[*str1++] & DIGIT) pow++;
+	while (table[*str2++] & DIGIT) pow--;
+	ret = (pow == 0) ? diff : pow;
+  }
+
+/* Unknown char. Check on which string it occurred */
+  else {
+	if ((table[*str1] & DIGIT) == 0)
+		ret = (table[*str2] & DIGIT) ? LOWER : SAME;
+	else
+		ret = HIGHER;
+  }
+
+/* Reverse sense of comparisons if negative is true. (-1000 < -1) */
+  return(negative) ? -ret : ret;
+}
+
+/* Files_merge () merges all files as indicated by nr_of_files. Merging goes
+ * in numbers of files that can be opened at the same time. (OPEN_FILES)
+ */
+void files_merge(file_cnt)
+register int file_cnt;		/* Nr_of_files to merge */
+{
+  register int i;
+  int limit;
+
+  for (i = 0; i < file_cnt; i += OPEN_FILES) {
+	/* Merge last files and store in output file */
+	if ((limit = i + OPEN_FILES) >= file_cnt) {
+		open_outfile();
+		limit = file_cnt;
+	} else {		/* Merge OPEN_FILES files and store in temp
+			 * file */
+		temp_files[16] = file_cnt / 26 + 'a';
+		temp_files[17] = file_cnt % 26 + 'a';
+		if ((out_fd = creat(temp_files, 0644)) < 0)
+			error(TRUE, "Cannot creat ", temp_files);
+		file_cnt++;
+	}
+	merge(i, limit);
+  }
+
+/* Cleanup mess */
+  i = (only_merge) ? args_limit - args_offset : 0;
+  while (i < file_cnt) (void) unlink(file_name(i++));
+}
+
+/* Merge () merges the files between start_file and limit_file. */
+void merge(start_file, limit_file)
+int start_file, limit_file;
+{
+  register MERGE *smallest;	/* Keeps track of smallest line */
+  register int i;
+  int file_cnt = limit_file - start_file;	/* Nr of files to merge */
+
+/* Calculate size in core available for file_cnt merge structs */
+  buf_size = MEMORY_SIZE / file_cnt - LINE_SIZE;
+
+  mbrk(mem_top);		/* First reset mem to lowest loc. */
+  disabled = 0;			/* All files not done yet */
+
+/* Set up merge structures. */
+  for (i = start_file; i < limit_file; i++) {
+	smallest = &merge_f[i - start_file];
+	if (!strcmp(file_name(i), "-"))	/* File is stdin */
+		smallest->fd = 0;
+	else if ((smallest->fd = open(file_name(i), O_RDONLY)) < 0) {
+		smallest->fd = ERROR;
+		error(FALSE, "Cannot open ", file_name(i));
+		disabled++;	/* Done this file */
+		continue;
+	}
+	smallest->buffer = msbrk(buf_size);
+	smallest->line = msbrk(LINE_SIZE);
+	smallest->cnt = smallest->read_chars = 0;
+	(void) read_line(smallest);	/* Read first line */
+  }
+
+  if (disabled == file_cnt) {	/* Couldn't open files */
+	(void) close(out_fd);
+	return;
+  }
+
+/* Find a merg struct to assign smallest. */
+  for (i = 0; i < file_cnt; i++) {
+	if (merge_f[i].fd != ERROR) {
+		smallest = &merge_f[i];
+		break;
+	}
+  }
+
+/* Loop until all files minus one are done */
+  while (disabled < file_cnt - 1) {
+	if (uniq)		/* Skip all same lines */
+		smallest = skip_lines(smallest, file_cnt);
+	else {			/* Find smallest line */
+		for (i = 0; i < file_cnt; i++) {
+			if (merge_f[i].fd == ERROR)
+				continue;	/* We've had this one */
+			if (compare(merge_f[i].line, smallest->line) < 0)
+				smallest = &merge_f[i];
+		}
+	}			/* Print line and read next */
+	smallest = print(smallest, file_cnt);
+  }
+
+  if (only_merge && uniq)
+	uniq_lines(smallest);	/* Print only uniq lines */
+  else				/* Print rest of file */
+	while (print(smallest, file_cnt) != NIL_MERGE);
+
+  put_line(NIL_PTR);		/* Flush output buffer */
+}
+
+/* Put_line () prints the line into the out_fd filedescriptor. If line equals
+ * NIL_PTR, the out_fd is flushed and closed.
+ */
+void put_line(line)
+register char *line;
+{
+  static int index = 0;		/* Index in out_buffer */
+
+  if (line == NIL_PTR) {	/* Flush and close */
+	mwrite(out_fd, out_buffer, index);
+	index = 0;
+	(void) close(out_fd);
+	return;
+  }
+  do {				/* Fill out_buffer with line */
+	out_buffer[index++] = *line;
+	if (index == IO_SIZE) {
+		mwrite(out_fd, out_buffer, IO_SIZE);
+		index = 0;
+	}
+  } while (*line++ != '\n');
+}
+
+/*
+ * Print () prints the line of the merg structure and tries to read another one.
+ * If this fails, it returns the next merg structure which file_descriptor is
+ * still open. If none could be found, a NIL structure is returned.
+ */
+MERGE *print(merg, file_cnt)
+register MERGE *merg;
+int file_cnt;			/* Nr of files that are being merged */
+{
+  register int i;
+
+  put_line(merg->line);		/* Print the line */
+
+  if (read_line(merg) == ERROR) {	/* Read next line */
+	for (i = 0; i < file_cnt; i++) {
+		if (merge_f[i].fd != ERROR) {
+			merg = &merge_f[i];
+			break;
+		}
+	}
+	if (i == file_cnt)	/* No more files left */
+		return NIL_MERGE;
+  }
+  return merg;
+}
+
+/* Read_line () reads a line from the fd from the merg struct. If the read
+ * failed, disabled is incremented and the file is closed. Readings are
+ * done in buf_size bytes.
+ * Lines longer than LINE_SIZE are silently truncated.
+ */
+int read_line(merg)
+register MERGE *merg;
+{
+  register char *ptr = merg->line - 1;	/* Ptr buf that will hold line */
+
+  do {
+	ptr++;
+	if (merg->cnt == merg->read_chars) {	/* Read new buffer */
+		if ((merg->read_chars =
+		     read(merg->fd, merg->buffer, buf_size)) <= 0) {
+			(void) close(merg->fd);	/* OOPS */
+			merg->fd = ERROR;
+			disabled++;
+			return ERROR;
+		}
+		merg->cnt = 0;
+	}
+	*ptr = merg->buffer[merg->cnt++];	/* Assign next char of line */
+	if (ptr - merg->line == LINE_SIZE - 1)
+		*ptr = '\n';	/* Truncate very long lines */
+  } while (*ptr != '\n' && *ptr != '\0');
+
+  if (*ptr == '\0')		/* Add '\n' to last line */
+	*ptr = '\n';
+  *++ptr = '\0';		/* Add '\0' */
+  return OK;
+}
+
+/* Skip_lines () skips all same lines in all the files currently being merged.
+ * It returns a pointer to the merge struct containing the smallest line.
+ */
+MERGE *skip_lines(smallest, file_cnt)
+register MERGE *smallest;
+int file_cnt;
+{
+  register int i;
+  int ret;
+
+  if (disabled == file_cnt - 1)	/* We've had all */
+	return smallest;
+
+  for (i = 0; i < file_cnt; i++) {
+	if (merge_f[i].fd == ERROR || smallest == &merge_f[i])
+		continue;	/* Don't check same file */
+	while ((ret = compare(merge_f[i].line, smallest->line)) == 0) {
+		if (read_line(&merge_f[i]) == ERROR) break;	/* EOF */
+	}
+	if (ret < 0)		/* Line wasn't smallest. Try again */
+		return skip_lines(&merge_f[i], file_cnt);
+  }
+  return smallest;
+}
+
+/* Uniq_lines () prints only the uniq lines out of the fd of the merg struct. */
+void uniq_lines(merg)
+register MERGE *merg;
+{
+  char lastline[LINE_SIZE];	/* Buffer to hold last line */
+
+  for (;;) {
+	put_line(merg->line);	/* Print this line */
+	copy(lastline, merg->line);	/* and save it */
+	if (read_line(merg) == ERROR)	/* Read the next */
+		return;
+	/* Keep reading until lines duffer */
+	while (compare(lastline, merg->line) == SAME)
+		if (read_line(merg) == ERROR) return;
+  }
+
+  /* NOTREACHED */
+}
+
+/*
+ * Check_file () checks if a file is sorted in order according to the arguments
+ * given in main ().
+ */
+void check_file(fd, file)
+int fd;
+char *file;
+{
+  register MERGE *merg;		/* 1 file only */
+  char lastline[LINE_SIZE];	/* Save last line */
+  register int ret;		/* ret status of compare */
+
+  if (fd == 0) file = "stdin";
+  merg = (MERGE *) mem_top;	/* Assign MERGE structure */
+  merg->buffer = mem_top + sizeof(MERGE);
+  merg->line = msbrk(LINE_SIZE);
+  merg->cnt = merg->read_chars = 0;
+  merg->fd = fd;
+  buf_size = MEMORY_SIZE - sizeof(MERGE);
+
+  if (read_line(merg) == ERROR)	/* Read first line */
+	return;
+  copy(lastline, merg->line);	/* and save it */
+
+  for (;;) {
+	if (read_line(merg) == ERROR)	/* EOF reached */
+		break;
+	if ((ret = compare(lastline, merg->line)) > 0) {
+		error(FALSE, "Disorder in file ", file);
+		write(2, merg->line, length(merg->line));
+		break;
+	} else if (ret < 0)	/* Copy if lines not equal */
+		copy(lastline, merg->line);
+	else if (uniq) {
+		error(FALSE, "Non uniq line in file ", file);
+		write(2, merg->line, length(merg->line));
+		break;
+	}
+  }
+
+  mbrk(mem_top);		/* Reset mem */
+}
+
+/* Length () returns the length of the argument line including the linefeed. */
+int length(line)
+register char *line;
+{
+  register int i = 1;		/* Add linefeed */
+
+  while (*line++ != '\n') i++;
+  return i;
+}
+
+/* Copy () copies the src line into the dest line including linefeed. */
+void copy(dest, src)
+register char *dest, *src;
+{
+  while ((*dest++ = *src++) != '\n');
+}
+
+/* Msbrk() does a sbrk() and checks the return value. */
+char *msbrk(size)
+register int size;
+{
+  register char *address;
+
+  if ((address = sbrk(size)) == (char *) -1)
+	error(TRUE, "Not enough memory. Use chmem to allocate more", NIL_PTR);
+  return address;
+}
+
+/* Mbrk() does a brk() and checks the return value. */
+void mbrk(address)
+char *address;
+{
+  if (brk(address) == -1) error(TRUE, "Cannot reset memory", NIL_PTR);
+}
+
+void catch(dummy)
+int dummy;			/* to satisfy the prototype */
+{
+  register int i;
+
+  signal(SIGINT, SIG_IGN);
+  only_merge = FALSE;
+  for (i = 0; i < 26; i++) (void) unlink(file_name(i));
+  exit(2);
+}
Index: /trunk/minix/commands/simple/split.c
===================================================================
--- /trunk/minix/commands/simple/split.c	(revision 9)
+++ /trunk/minix/commands/simple/split.c	(revision 9)
@@ -0,0 +1,117 @@
+/* split - split a file			Author: Michiel Huisjes */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <minix/minlib.h>
+
+#define CHUNK_SIZE	1024
+
+int cut_line = 1000;
+int infile;
+char out_file[100];
+char *suffix;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void split, (void));
+_PROTOTYPE(int newfile, (void));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(void quit, (void));
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  unsigned short i;
+
+  out_file[0] = 'x';
+  infile = -1;
+
+  if (argc > 4) usage();
+  for (i = 1; i < argc; i++) {
+	if (argv[i][0] == '-') {
+		if (argv[i][1] >= '0' && argv[i][1] <= '9'
+		    && cut_line == 1000)
+			cut_line = atoi(argv[i]);
+		else if (argv[i][1] == '\0' && infile == -1)
+			infile = 0;
+		else
+			usage();
+	} else if (infile == -1) {
+		if ((infile = open(argv[i], O_RDONLY)) < 0) {
+			std_err("Cannot open input file.\n");
+			exit(1);
+		}
+	} else
+		strcpy(out_file, argv[i]);
+  }
+  if (infile == -1) infile = 0;
+  strcat(out_file, "aa");
+  for (suffix = out_file; *suffix; suffix++);
+  suffix--;
+
+/* Appendix now points to last `a' of "aa". We have to decrement it by one */
+  *suffix = 'a' - 1;
+  split();
+  return(0);
+}
+
+void split()
+{
+  char buf[CHUNK_SIZE];
+  register char *index, *base;
+  register int n;
+  int fd;
+  long lines = 0L;
+
+  fd = -1;
+  while ((n = read(infile, buf, CHUNK_SIZE)) > 0) {
+	base = index = buf;
+	while (--n >= 0) {
+		if (*index++ == '\n')
+			if (++lines % cut_line == 0) {
+				if (fd == -1) fd = newfile();
+				if (write(fd, base, (int) (index - base)) != (int) (index - base))
+					quit();
+				base = index;
+				close(fd);
+				fd = -1;
+			}
+	}
+	if (index == base) continue;
+	if (fd == -1) fd = newfile();
+	if (write(fd, base, (int) (index - base)) != (int) (index - base))
+		quit();
+  }
+}
+
+int newfile()
+{
+  int fd;
+
+  if (++*suffix > 'z') {	/* Increment letter */
+	*suffix = 'a';		/* Reset last letter */
+	++*(suffix - 1);	/* Previous letter must be incremented */
+	/* E.g. was `filename.az' */
+	/* Now `filename.ba' */
+  }
+  if ((fd = creat(out_file, 0644)) < 0) {
+	std_err("Cannot create new file.\n");
+	exit(2);
+  }
+  return fd;
+}
+
+void usage()
+{
+  std_err("Usage: split [-n] [file [name]].\n");
+  exit(1);
+}
+
+void quit()
+{
+  std_err("split: write error\n");
+  exit(1);
+}
Index: /trunk/minix/commands/simple/stat.c
===================================================================
--- /trunk/minix/commands/simple/stat.c	(revision 9)
+++ /trunk/minix/commands/simple/stat.c	(revision 9)
@@ -0,0 +1,391 @@
+/* stat.c Feb 1987 - main, printit, statit
+ *
+ * stat - a program to perform what the stat(2) call does.  
+ *
+ * usage: stat [-] [-all] -<field> [-<field> ...] [file1 file2 file3 ...]
+ *
+ * where   <field> is one of the struct stat fields without the leading "st_".
+ *	   The three times can be printed out as human times by requesting
+ *	   -Ctime instead of -ctime (upper case 1st letter).
+ *	   - means take the file names from stdin.
+ *	   -0.. means fd0..
+ *	   no files means all fds.
+ *
+ * output: if only one field is specified, that fields' contents are printed.
+ *         if more than one field is specified, the output is
+ *	   file	filed1: f1val, field2: f2val, etc
+ *
+ * written: Larry McVoy, (mcvoy@rsch.wisc.edu)  
+ */
+
+# define	ALLDEF		/* Make -all default. (kjb) */
+
+# include	<sys/types.h>
+# include	<errno.h>
+# include	<limits.h>
+# include	<stdio.h>
+# include	<stdlib.h>
+# include	<unistd.h>
+# include 	<string.h>
+# include	<time.h>
+# include	<sys/stat.h>
+# define	addr(x)		((void*) &sbuf.x)
+# define	size(x)		sizeof(sbuf.x)
+# define	equal(s, t)	(strcmp(s, t) == 0)
+# ifndef PATH_MAX
+#  define	PATH_MAX	1024
+# endif
+# undef		LS_ADDS_SPACE	/* AT&T Unix PC, ls prints "file[* /]" */
+				/* This makes stat fail. */
+
+# ifndef _MINIX			/* All but Minix have u_* and st_blocks */
+#  define BSD
+# endif
+
+# ifndef S_IREAD
+#  define S_IREAD	S_IRUSR
+#  define S_IWRITE	S_IWUSR
+#  define S_IEXEC	S_IXUSR
+# endif
+
+char *      arg0;
+struct stat sbuf;
+extern int  errno;
+int	    first_file= 1;
+#ifndef S_IFLNK
+#define lstat	stat
+#endif
+
+struct field {
+    char* f_name;	/* field name in stat */
+    u_char* f_addr;	/* address of the field in sbuf */
+    u_short f_size;	/* size of the object, needed for pointer arith */
+    u_short f_print;	/* show this field? */
+} fields[] = {
+    { "dev",		addr(st_dev),		size(st_dev),		0 },
+    { "ino",		addr(st_ino),		size(st_ino),		0 },
+    { "mode",		addr(st_mode),		size(st_mode),		0 },
+    { "nlink",		addr(st_nlink),		size(st_nlink),		0 },
+    { "uid",		addr(st_uid),		size(st_uid),		0 },
+    { "gid",		addr(st_gid),		size(st_gid),		0 },
+    { "rdev",		addr(st_rdev),		size(st_rdev),		0 },
+    { "size",		addr(st_size),		size(st_size),		0 },
+    { "Atime",		addr(st_atime),		size(st_atime),		0 },
+    { "atime",		addr(st_atime),		size(st_atime),		0 },
+    { "Mtime",		addr(st_mtime),		size(st_mtime),		0 },
+    { "mtime",		addr(st_mtime),		size(st_mtime),		0 },
+    { "Ctime",		addr(st_ctime),		size(st_ctime),		0 },
+    { "ctime",		addr(st_ctime),		size(st_ctime),		0 },
+# ifdef BSD
+    { "blksize", 	addr(st_blksize),	size(st_blksize),	0 },
+    { "blocks",		addr(st_blocks),	size(st_blocks),	0 },
+# endif
+    { NULL,		0,			0,			0 },
+};
+    
+void printstat(struct stat *sbuf, int nprint);
+void printit(struct stat* sb, struct field* f, int n);
+void rwx(mode_t mode, char *bit);
+void usage(void);
+
+int do_readlink=0;
+
+int main(int ac, char** av)
+{
+    int      i, j, nprint = 0, files = 0;
+    char     buf[PATH_MAX], *check;
+    int      sym=0, ret=0, from_stdin = 0;
+    int      err;
+    u_long   fd;
+
+    if ((arg0 = strrchr(av[0], '/')) == NULL) arg0 = av[0]; else arg0++;
+#ifdef S_IFLNK
+    if (equal(arg0, "lstat")) sym = 1;
+    if (equal(arg0, "readlink")) do_readlink = 1;
+#endif
+
+    if (ac > 1 && equal(av[i = 1], "-"))
+	i++, from_stdin++;
+
+    for (i= 1; i<ac; i++)  {
+	if (av[i][0] == '-')  {
+	    if (equal(av[i], "-")) {
+		from_stdin= 1;
+		files++;
+		continue;
+	    }
+	    if (equal("-all", av[i])) {
+		for (j=0; fields[j].f_name; j++)
+		    nprint++, fields[j].f_print++;
+		continue;
+	    }
+	    if (equal("-s", av[i])) {
+#ifdef S_IFLNK
+		sym=1;
+#endif
+		continue;
+	    }
+	    fd = strtoul(av[i]+1, &check, 0);
+	    if (check != av[i]+1 && *check == '\0')
+	    {
+		files++;
+		continue;
+	    }
+	    for (j=0; fields[j].f_name; j++) 
+		if (equal(fields[j].f_name, &av[i][1])) {
+		    nprint++, fields[j].f_print++;
+		    break;
+		}
+	    if (!fields[j].f_name) {
+		if (!equal("-?", av[i])) {
+		    fprintf(stderr, "stat: %s: bad field\n", av[i]);
+		}
+		usage();
+	    }
+	}
+	else 
+	    files++;
+    }
+    if (!nprint) {
+# ifndef ALLDEF
+	usage();
+# else
+	for (j=0; fields[j].f_name; j++)
+	    nprint++, fields[j].f_print++;
+# endif
+    }
+
+    if (from_stdin)
+	files++;	/* We don't know how many files come from stdin. */
+
+    if (files == 0) {	/* Stat all file descriptors. */
+	if(do_readlink) return 0;
+	for (i= 0; i<OPEN_MAX; i++) {
+	    err= fstat(i, &sbuf);
+	    if (err == -1 && errno == EBADF)
+		continue;
+	    if (err == 0) {
+		if (!first_file) fputc('\n', stdout);
+		printf("fd %d:\n", i);
+		printstat(&sbuf, nprint);
+	    }
+	    else {
+		fprintf(stderr, "%s: fd %d: %s\n", arg0, i, strerror(errno));
+		ret= 1;
+	    }
+	}
+	exit(ret);
+    }
+		
+    for (i=1; i<ac; i++) {
+	if (equal(av[i], "-")) {
+	    while (fgets(buf, sizeof(buf), stdin)) {
+	    	char *p= strchr(buf, '\n');
+	    	if (p) *p= 0;
+#ifdef S_IFLNK
+		if(do_readlink) {
+			char sbuf[300];
+			int n;
+			if((n=readlink(buf, sbuf, sizeof(sbuf)-1)) < 0) {
+				perror(buf);
+				continue;
+			}
+			sbuf[n] = '\0';
+			printf("%s: %s\n", buf, sbuf);
+			continue;
+		}
+#endif
+		if (!sym) err= stat(av[i], &sbuf);
+		if (sym || (err != 0 && errno == ENOENT)) {
+		    err= lstat(av[i], &sbuf);
+		}
+		if (err == -1) {
+		    fprintf(stderr, "%s: %s: %s\n",
+			arg0, av[i], strerror(errno));
+		    ret= 1;
+		}
+		else {
+		    if (!first_file) fputc('\n', stdout);
+		    printf("%s:\n", buf);
+		    printstat(&sbuf, nprint);
+		}
+	    }
+	    continue;
+	}
+	if (av[i][0] == '-') {
+	    fd= strtoul(av[i]+1, &check, 10);
+	    if (check == av[i]+1 || *check != '\0') continue;
+	    if (fd >= INT_MAX) {
+		err= -1;
+		errno= EBADF;
+	    }
+	    else {
+		err= fstat((int) fd, &sbuf);
+	    }
+	    if (err != -1) {
+		if (!first_file) fputc('\n', stdout);
+		if (files != 1) printf("fd %lu:\n", fd);
+		printstat(&sbuf, nprint);
+	    }
+	    else {
+		fprintf(stderr, "fd %lu: %s\n", fd, strerror(errno));
+		ret= 1;
+	    }
+	    continue;
+	}
+	if(do_readlink) {
+		char sbuf[300];
+		int n;
+		if((n=err=readlink(av[i], sbuf, sizeof(sbuf)-1)) < 0) {
+			perror(av[i]);
+			continue;
+		}
+		sbuf[n] = '\0';
+		printf("%s: %s\n", av[i], sbuf);
+		continue;
+	}
+	if (!sym) err= stat(av[i], &sbuf);
+	if (sym || (err != 0 && errno == ENOENT)) err= lstat(av[i], &sbuf);
+	if (err != -1) {
+	    if (!first_file) fputc('\n', stdout);
+	    if (files != 1) printf("%s:\n", av[i]);
+	    printstat(&sbuf, nprint);
+	}
+	else {
+	    fprintf(stderr, "%s: %s: %s\n", arg0, av[i], strerror(errno));
+	    ret= 1;
+	}
+    }
+    exit(ret);
+}
+
+/*------------------------------------------------------------------30/Jan/87-*
+ * printstat(file, nprint) - do the work
+ *----------------------------------------------------------------larry mcvoy-*/
+void printstat(struct stat *sbuf, int nprint)
+{
+    int      j;
+    int      first_field= 1;
+
+    for (j=0; fields[j].f_name; j++) {
+	if (fields[j].f_print) {
+	    if (!first_field) fputc('\n', stdout);
+	    printit(sbuf, &fields[j], nprint);
+	    first_field= 0;
+	}
+    }
+    fputc('\n', stdout);
+    first_file= 0;
+}
+
+/*------------------------------------------------------------------30/Jan/87-*
+ * printit(sb, f, n) - print the field
+ *
+ * Inputs    -> (struct stat*), (struct field*), (int)
+ *
+ * Results   -> Displays the field, with special handling of weird fields like
+ *		mode and mtime.  The mode field is dumped in octal, followed
+ *		by one or more of the S_IF<X> and/or S_I<X> values.
+ *----------------------------------------------------------------larry mcvoy-*/
+void printit(struct stat* sb, struct field* f, int n)
+{
+    if (n > 1)
+	printf("%s: ", f->f_name);
+    if (equal(f->f_name, "mode")) {
+		/* This lot changed to my personal liking. (kjb) */
+	char bit[11];
+
+	printf("%07lo, ", (u_long) sb->st_mode);
+
+	strcpy(bit, "----------");
+
+	switch (sb->st_mode&S_IFMT) {
+	case S_IFDIR:	bit[0]='d';	break;
+# ifdef S_IFFIFO
+	case S_IFFIFO:	bit[0]='p';	break;
+# endif
+	case S_IFCHR:	bit[0]='c';	break;
+	case S_IFBLK:	bit[0]='b';	break;
+# ifdef S_IFSOCK
+	case S_IFSOCK:	bit[0]='S';	break;
+# endif
+# ifdef S_IFMPC
+	case S_IFMPC:	bit[0]='C';	break;
+# endif
+# ifdef S_IFMPB
+	case S_IFMPB:	bit[0]='B';	break;
+# endif
+# ifdef S_IFLNK
+	case S_IFLNK:	bit[0]='l';	break;
+# endif
+	}
+	rwx(sb->st_mode, bit+1);
+	rwx(sb->st_mode<<3, bit+4);
+	rwx(sb->st_mode<<6, bit+7);
+	if (sb->st_mode&S_ISUID)	bit[3]='s';
+	if (sb->st_mode&S_ISGID)	bit[6]='s';
+	if (sb->st_mode&S_ISVTX)	bit[9]='t';
+	printf("\"%s\"", bit);
+    }
+    /* times in human form, uppercase first letter */
+    else if (equal("Ctime", f->f_name)) {
+	printf("%.24s (%lu)", ctime(&sb->st_ctime), (u_long) sb->st_ctime);
+	f[1].f_print= 0;
+    }
+    else if (equal("Mtime", f->f_name)) {
+	printf("%.24s (%lu)", ctime(&sb->st_mtime), (u_long) sb->st_mtime);
+	f[1].f_print= 0;
+    }
+    else if (equal("Atime", f->f_name)) {
+	printf("%.24s (%lu)", ctime(&sb->st_atime), (u_long) sb->st_atime);
+	f[1].f_print= 0;
+    }
+    else if (equal("ctime", f->f_name)) {
+	printf("%lu", (u_long) sb->st_ctime);
+    }
+    else if (equal("mtime", f->f_name)) {
+	printf("%lu", (u_long) sb->st_mtime);
+    }
+    else if (equal("atime", f->f_name)) {
+	printf("%lu", (u_long) sb->st_atime);
+    }
+    else {
+	switch (f->f_size) {
+	case sizeof(char):
+	    printf("%d", * (u_char *) f->f_addr);
+	    break;
+	case sizeof(short):
+	    printf("%u", (u_int) * (u_short *) f->f_addr);
+	    break;
+#if INT_MAX != SHRT_MAX
+	case sizeof(int):
+	    printf("%u", * (u_int *) f->f_addr);
+	    break;
+#endif
+#if LONG_MAX != INT_MAX && LONG_MAX != SHRT_MAX
+	case sizeof(long):
+	    printf("%lu", * (u_long *) f->f_addr);
+	    break;
+#endif
+	default:
+	    fprintf(stderr, "\nProgram error: bad '%s' field size %d\n", 
+			    f->f_name, f->f_size);
+	    break;
+	}
+    }
+}
+
+void rwx(mode_t mode, char *bit)
+{
+	if (mode&S_IREAD)	bit[0]='r';
+	if (mode&S_IWRITE)	bit[1]='w';
+	if (mode&S_IEXEC)	bit[2]='x';
+}
+
+void usage(void)
+{
+    fprintf(stderr,
+	"Usage: %s [-] [-fd] [-all] [-s] [-field ...] [file1 ...]\n", 
+	arg0);
+    exit(1);
+}
Index: /trunk/minix/commands/simple/strings.c
===================================================================
--- /trunk/minix/commands/simple/strings.c	(revision 9)
+++ /trunk/minix/commands/simple/strings.c	(revision 9)
@@ -0,0 +1,139 @@
+/* strings - print ASCII strings in a file	Author: Peter S. Housel */
+
+/*
+  This is a version of the BSD "strings" program for Minix. It is used
+  to search a file for printable strings. To install,
+
+  cc -o strings strings.c
+  chmem =8000 strings
+
+Command:  strings - search file for printable strings
+Syntax:	  strings [-] [-o] [-len] file ...
+Flags:	  -	Search the entire file. If this option is not given, only
+	 	the initialized data segment of files that appear to be
+		"a.out" format is searched.
+    	  -o	Print the offset (in octal) with each string.
+          -len	Use "len" as the minimum string length. The default is 4.
+
+Examples: strings core
+	  strings -o a.out > str
+
+Strings searches the specified file(s) for printable ASCII strings (four
+or more printable characters followed by a newline or a null) and writes
+them to the standard output. This can be used to find out, for example, to
+find out what program a "core" file came from, what kinds of error messages
+are in an executable, or to see ASCII data hidden in a "binary" data file.
+
+P.S. The program doesn't use the "a.out.h" file posted last week by
+Dick van Veen, both because it was written before then, and because
+not everybody has a.out.h yet. Future revisions probably ought to, though.
+
+*/
+
+
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+/* Minix (8086 version) dependant definitions */
+#define SMALLMAGIC	0x04100301L	/* small model a.out magic number */
+#define SEPARATEMAGIC	0x04200301L	/* separate instruction/data a.out */
+
+#define HDR_MAGIC	0	/* 0'th long  magic number */
+#define HDR_HSIZE	1	/* 1'st long  size of header */
+#define HDR_TSIZE	2	/* 2'nd long  size of text */
+#define HDR_DSIZE	3	/* 3'rd long  size of init'ed data */
+#define HDR_BSIZE	4	/* 4'th long  size of bss */
+#define HDR_TOTMEM	6	/* 6'th long  total memory */
+
+#define HDR_LEN		8	/* total length of header */
+
+/* Miscellaneous definitions */
+#define	STRLEN		4	/* default minimum string length */
+#define STRBUF		512	/* buffer length for strings */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void strings, (char *filename));
+_PROTOTYPE(void usage, (void));
+
+int strmin = STRLEN;		/* minimum string length */
+int printoff = 0;		/* print octal offset of each str */
+int objall = 0;			/* search entire a.out file, not */
+
+/* Just initialized data segment */
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  while ((++argv, --argc) && '-' == (*argv)[0]) {
+	if (!strcmp(*argv, "-"))
+		++objall;
+	else if (!strcmp(*argv, "-o"))
+		++printoff;
+	else if (isdigit((*argv)[1]))
+		strmin = atoi(&(*argv)[1]);
+	else
+		usage();
+  }
+
+  if (0 == argc) usage();
+  while (argc--) strings(*argv++);
+  return(0);
+}
+
+void strings(filename)
+char *filename;
+{
+  char buf[STRBUF];		/* the strings buffer */
+  char *bufptr;			/* pointer into the strings buffer */
+  FILE *input;			/* input file */
+  long header[HDR_LEN];		/* buffer for reading the header */
+  long offset;			/* file offset */
+  long limit;			/* limit, if doing data segment only */
+  int c;			/* input character */
+
+  if (NULL == (input = fopen(filename, "r"))) {
+	fprintf(stderr, "strings: ");
+	perror(filename);
+	exit(1);
+  }
+  if (HDR_LEN == fread(header, sizeof(long), (size_t)HDR_LEN, input)
+      && (SMALLMAGIC == header[HDR_MAGIC]
+	||SEPARATEMAGIC == header[HDR_MAGIC]) && !objall) {
+	offset = header[HDR_HSIZE] + header[HDR_TSIZE];	/* object file */
+	limit = offset + header[HDR_DSIZE];
+  } else {
+	offset = 0L;
+	limit = 0L;
+  }
+
+  fseek(input, offset, 0);
+  bufptr = buf;
+
+  while (!limit || offset < limit) {
+	if (EOF == (c = getc(input))) break;
+	if ((('\0' == c || '\n' == c) && bufptr - buf >= strmin)
+	    || (bufptr - buf == STRBUF - 1)) {
+		*bufptr = '\0';
+		if (printoff) printf("%lo:", offset - (bufptr - buf));
+		puts(buf);
+		bufptr = buf;
+	} else if ((' ' <= c && c < 0177) || '\t' == c)
+		*bufptr++ = c;
+	else
+		bufptr = buf;
+
+	++offset;
+  }
+
+  fclose(input);
+}
+
+void usage()
+{
+  fprintf(stderr, "usage: strings [-] [-o] [-num] file ...\n");
+  exit(1);
+}
Index: /trunk/minix/commands/simple/strip.c
===================================================================
--- /trunk/minix/commands/simple/strip.c	(revision 9)
+++ /trunk/minix/commands/simple/strip.c	(revision 9)
@@ -0,0 +1,169 @@
+/* strip - remove symbols.		Author: Dick van Veen */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <a.out.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* Strip [file] ...
+ *
+ *	-	when no file is present, a.out is assumed.
+ *
+ */
+
+#define A_OUT		"a.out"
+#define NAME_LENGTH	128	/* max file path name */
+
+char buffer[BUFSIZ];		/* used to copy executable */
+char new_file[NAME_LENGTH];	/* contains name of temporary */
+struct exec header;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void strip, (char *file));
+_PROTOTYPE(int read_header, (int fd));
+_PROTOTYPE(int write_header, (int fd));
+_PROTOTYPE(int make_tmp, (char *new_name, char *name));
+_PROTOTYPE(int copy_file, (int fd1, int fd2, long size));
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  argv++;
+  if (*argv == NULL)
+	strip(A_OUT);
+  else
+	while (*argv != NULL) {
+		strip(*argv);
+		argv++;
+	}
+  return(0);
+}
+
+void strip(file)
+char *file;
+{
+  int fd, new_fd;
+  struct stat buf;
+  long symb_size, relo_size;
+
+  fd = open(file, O_RDONLY);
+  if (fd == -1) {
+	fprintf(stderr, "can't open %s\n", file);
+	close(fd);
+	return;
+  }
+  if (read_header(fd)) {
+	fprintf(stderr, "%s: not an executable file\n", file);
+	close(fd);
+	return;
+  }
+  if (header.a_syms == 0L) {
+	close(fd);		/* no symbol table present */
+	return;
+  }
+  symb_size = header.a_syms;
+  header.a_syms = 0L;		/* remove table size */
+  fstat(fd, &buf);
+  relo_size = buf.st_size - (A_MINHDR + header.a_text + header.a_data + symb_size);
+  new_fd = make_tmp(new_file, file);
+  if (new_fd == -1) {
+	fprintf(stderr, "can't create temporary file\n");
+	close(fd);
+	return;
+  }
+  if (write_header(new_fd)) {
+	fprintf(stderr, "can't write temporary file\n");
+	unlink(new_file);
+	close(fd);
+	close(new_fd);
+	return;
+  }
+  if (copy_file(fd, new_fd, header.a_text + header.a_data)) {
+	fprintf(stderr, "can't copy %s\n", file);
+	unlink(new_file);
+	close(fd);
+	close(new_fd);
+	return;
+  }
+  if (relo_size != 0) {
+	lseek(fd, symb_size, 1);
+	if (copy_file(fd, new_fd, relo_size)) {
+	    fprintf(stderr, "can't copy %s\n", file);
+	    unlink(new_file);
+	    close(fd);
+	    close(new_fd);
+	    return;
+	}
+  }
+  close(fd);
+  close(new_fd);
+  if (unlink(file) == -1) {
+	fprintf(stderr, "can't unlink %s\n", file);
+	unlink(new_file);
+	return;
+  }
+  link(new_file, file);
+  unlink(new_file);
+  chmod(file, buf.st_mode);
+}
+
+int read_header(fd)
+int fd;
+{
+  if (read(fd, (char *) &header, A_MINHDR) != A_MINHDR) return(1);
+  if (BADMAG(header)) return (1);
+  if (header.a_hdrlen > sizeof(struct exec)) return (1);
+  lseek(fd, 0L, SEEK_SET);	/* variable size header */
+  if (read(fd, (char *)&header, (int)header.a_hdrlen) != (int) header.a_hdrlen)
+	return(1);
+  return(0);
+}
+
+int write_header(fd)
+int fd;
+{
+  lseek(fd, 0L, SEEK_SET);
+  if (write(fd, (char *)&header, (int)header.a_hdrlen) != (int)header.a_hdrlen)
+	return(1);
+  return(0);
+}
+
+int make_tmp(new_name, name)
+char *new_name, *name;
+{
+  int len;
+  char *nameptr;
+
+  len = strlen(name);
+  if (len + 1 > NAME_LENGTH) return(-1);
+  strcpy(new_name, name);
+  nameptr = strrchr(new_name, '/');
+  if (nameptr == NULL) nameptr = new_name - 1;
+  if (nameptr - new_name + 6 + 1 > NAME_LENGTH) return (-1);
+  strcpy(nameptr + 1, "XXXXXX");
+  mktemp(new_name);
+  return(creat(new_name, 0777));
+}
+
+int copy_file(fd1, fd2, size)
+int fd1, fd2;
+long size;
+{
+  int length;
+
+  while (size > 0) {
+	if (size < sizeof(buffer))
+		length = size;
+	else
+		length = sizeof(buffer);
+	if (read(fd1, buffer, length) != length) return(1);
+	if (write(fd2, buffer, length) != length) return (1);
+	size -= length;
+  }
+  return(0);
+}
Index: /trunk/minix/commands/simple/stty.c
===================================================================
--- /trunk/minix/commands/simple/stty.c	(revision 9)
+++ /trunk/minix/commands/simple/stty.c	(revision 9)
@@ -0,0 +1,1277 @@
+/* stty - set terminal mode	  	Author: Andy Tanenbaum */
+
+/*
+	Adapted to POSIX 1003.2 by Philip Homburg.
+ */
+
+#ifdef __minix_vmd
+#define _MINIX_SOURCE
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#ifdef __minix
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#endif
+
+/* Default settings, the Minix ones are defined in <termios.h> */
+
+#ifndef TCTRL_DEF
+#define TCTRL_DEF	(PARENB | CREAD | CS7)
+#endif
+
+#ifndef TSPEED_DEF
+#define TSPEED_DEF	B1200
+#endif
+
+#ifndef TINPUT_DEF
+#define TINPUT_DEF	(BRKINT | IGNPAR | ISTRIP | ICRNL)
+#endif
+
+#ifndef TOUTPUT_DEF
+#define TOUTPUT_DEF	OPOST
+#endif
+
+#ifndef TLOCAL_DEF
+#define TLOCAL_DEF	(ISIG | IEXTEN | ICANON | ECHO | ECHOE)
+#endif
+
+#ifndef TEOF_DEF
+#define TEOF_DEF	'\4'	/* ^D */
+#endif
+#ifndef TEOL_DEF
+#ifdef _POSIX_VDISABLE
+#define TEOL_DEF	_POSIX_VDISABLE
+#else
+#define TEOL_DEF	'\n'
+#endif
+#endif
+#ifndef TERASE_DEF
+#define TERASE_DEF	'\10'	/* ^H */
+#endif
+#ifndef TINTR_DEF
+#define TINTR_DEF	'\177'	/* ^? */
+#endif
+#ifndef TKILL_DEF
+#define TKILL_DEF	'\25'	/* ^U */
+#endif
+#ifndef TQUIT_DEF
+#define TQUIT_DEF	'\34'	/* ^\ */
+#endif
+#ifndef TSUSP_DEF
+#define TSUSP_DEF	'\32'	/* ^Z */
+#endif
+#ifndef TSTART_DEF
+#define TSTART_DEF	'\21'	/* ^Q */
+#endif
+#ifndef TSTOP_DEF
+#define TSTOP_DEF	'\23'	/* ^S */
+#endif
+#ifndef TMIN_DEF
+#define TMIN_DEF	1
+#endif
+#ifndef TTIME_DEF
+#define TTIME_DEF	0
+#endif
+
+
+
+char *prog_name;
+struct termios termios;
+int column= 0, max_column=80;		/* Assume 80 character terminals. */
+#ifdef __minix
+struct winsize winsize;
+#endif
+
+#if __minix
+#define PROTO(a) _ARGS(a)
+#else
+#define PROTO(a) ()
+#endif
+
+void main PROTO(( int argc, char **argv ));
+void report PROTO(( int flags ));
+int option PROTO(( char *opt, char *next ));
+int match PROTO(( char *s1, char *s2 ));
+void prctl PROTO(( int c ));
+speed_t long2speed PROTO(( long num ));
+long speed2long PROTO(( unsigned long speed ));
+void print_flags PROTO(( unsigned long flags, unsigned long flag,
+				unsigned long def, char *string, int all ));
+void output PROTO(( char *s ));
+void do_print_char PROTO(( unsigned chr, unsigned def, char *name, int all ));
+void do_print_num PROTO(( unsigned num, unsigned def, char *name, int all ));
+void set_saved_settings PROTO(( char *opt ));
+void set_control PROTO(( int option, char *value ));
+void set_min_tim PROTO(( int option, char *value ));
+
+#define print_char(c,d,n,a) (do_print_char((unsigned)(c),(unsigned)(d),(n),(a)))
+#define print_num(m,d,n,a) (do_print_num((unsigned)(m),(unsigned)(d),(n),(a)))
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int flags, k;
+
+  prog_name= argv[0];
+  flags= 0;
+
+  /* Stty with no arguments just reports on current status. */
+  if (tcgetattr(0, &termios) == -1)
+  {
+	fprintf(stderr, "%s: can't read ioctl parameters from stdin: %s\n",
+		prog_name, strerror(errno));
+	exit(1);
+  }
+#ifdef __minix
+  if (ioctl(0, TIOCGWINSZ, &winsize) == -1)
+  {
+	fprintf(stderr, "%s: can't get screen size from stdin: %s\n",
+		prog_name, strerror(errno));
+	exit(1);
+  }
+  if (winsize.ws_col != 0)
+	max_column= winsize.ws_col;
+#endif
+
+  if (argc == 2)
+  {
+	if (!strcmp(argv[1], "-a"))
+		flags |= 1;
+	else if (!strcmp(argv[1], "-g"))
+		flags |= 2;
+  }
+  if (argc == 1 || flags) {
+	report(flags);
+	exit(0);
+  }
+
+  /* Process the options specified. */
+  for (k= 1; k < argc; k++)
+	k += option(argv[k], k+1 < argc ? argv[k+1] : "");
+
+#ifdef __minix
+  if (ioctl(0, TIOCSWINSZ, &winsize) == -1)
+  {
+	fprintf(stderr, "%s: can't set screen size to stdin: %s\n",
+		prog_name, strerror(errno));
+	exit(1);
+  }
+#endif
+  if (tcsetattr(0, TCSANOW, &termios) == -1)
+  {
+	fprintf(stderr, "%s: can't set terminal parameters to stdin: %s\n",
+		prog_name, strerror(errno));
+	exit(1);
+  }
+  exit(0);
+}
+
+
+
+void report(flags)
+int flags;
+{
+	int i, all;
+	tcflag_t c_cflag, c_iflag, c_oflag, c_lflag;
+	char line[80];
+	speed_t ispeed, ospeed;
+
+	if (flags & 2)
+	{	/* We have to write the termios structure in a encoded form
+		 * to stdout.
+		 */
+		printf(":%x:%x:%x:%x:%x:%x", termios.c_iflag, termios.c_oflag,
+			termios.c_cflag, termios.c_lflag, cfgetispeed(&termios),
+			cfgetospeed(&termios));
+		for (i= 0; i<NCCS; i++)
+			printf(":%x", termios.c_cc[i]);
+		printf(":\n");
+		return;
+	}
+
+	all= !!flags;
+
+	/* Start with the baud rate. */
+	ispeed= cfgetispeed(&termios);
+	ospeed= cfgetospeed(&termios);
+	if (ispeed != ospeed)
+	{
+		sprintf(line, "ispeed %lu baud; ospeed %lu baud;", 
+			speed2long(ispeed), speed2long(ospeed));
+		output(line);
+	}
+	else if (all || ospeed != TSPEED_DEF)
+	{
+		sprintf(line, "speed %lu baud;", speed2long(ospeed));
+		output(line);
+	}
+
+	/* The control modes. */
+
+	c_cflag= termios.c_cflag;
+	if (all || (c_cflag & CSIZE) != (TCTRL_DEF & CSIZE))
+	{
+		switch (c_cflag & CSIZE)
+		{
+		case CS5: output("cs5"); break;
+		case CS6: output("cs6"); break;
+		case CS7: output("cs7"); break;
+		case CS8: output("cs8"); break;
+		default: output("cs??"); break;
+		}
+	}
+	print_flags(c_cflag, PARENB, TCTRL_DEF, "-parenb", all);
+	print_flags(c_cflag, PARODD, TCTRL_DEF, "-parodd", all);
+	print_flags(c_cflag, HUPCL, TCTRL_DEF, "-hupcl", all);
+	print_flags(c_cflag, CSTOPB, TCTRL_DEF, "-cstopb", all);
+	print_flags(c_cflag, CREAD, TCTRL_DEF, "-cread", all);
+	print_flags(c_cflag, CLOCAL, TCTRL_DEF, "-clocal", all);
+		
+	if (all)
+	{
+		printf("\n");
+		column= 0;
+	}
+
+	/* The input flags. */
+
+	c_iflag= termios.c_iflag;
+
+	print_flags(c_iflag, IGNBRK, TINPUT_DEF, "-ignbrk", all);
+	print_flags(c_iflag, BRKINT, TINPUT_DEF, "-brkint", all);
+	print_flags(c_iflag, IGNPAR, TINPUT_DEF, "-ignpar", all);
+	print_flags(c_iflag, PARMRK, TINPUT_DEF, "-parmrk", all);
+	print_flags(c_iflag, INPCK, TINPUT_DEF, "-inpck", all);
+	print_flags(c_iflag, ISTRIP, TINPUT_DEF, "-istrip", all);
+	print_flags(c_iflag, INLCR, TINPUT_DEF, "-inlcr", all);
+	print_flags(c_iflag, IGNCR, TINPUT_DEF, "-igncr", all);
+	print_flags(c_iflag, ICRNL, TINPUT_DEF, "-icrnl", all);
+	print_flags(c_iflag, IXON, TINPUT_DEF, "-ixon", all);
+	print_flags(c_iflag, IXOFF, TINPUT_DEF, "-ixoff", all);
+	print_flags(c_iflag, IXANY, TINPUT_DEF, "-ixany", all);
+	
+	if (all)
+	{
+		printf("\n");
+		column= 0;
+	}
+
+	/* The output flags. */
+
+	c_oflag= termios.c_oflag;
+
+	print_flags(c_oflag, OPOST, TOUTPUT_DEF, "-opost", all);
+#ifdef __minix
+	print_flags(c_oflag, ONLCR, TOUTPUT_DEF, "-onlcr", all);
+	print_flags(c_oflag, XTABS, TOUTPUT_DEF, "-xtabs", all);
+	print_flags(c_oflag, ONOEOT, TOUTPUT_DEF, "-onoeot", all);
+#endif
+	if (all)
+	{
+		printf("\n");
+		column= 0;
+	}
+
+	/* The local flags. */
+
+	c_lflag= termios.c_lflag;
+
+	print_flags(c_lflag, ISIG, TLOCAL_DEF, "-isig", all);
+	print_flags(c_lflag, ICANON, TLOCAL_DEF, "-icanon", all);
+	print_flags(c_lflag, IEXTEN, TLOCAL_DEF, "-iexten", all);
+	print_flags(c_lflag, ECHO, TLOCAL_DEF, "-echo", all);
+	print_flags(c_lflag, ECHOE, TLOCAL_DEF, "-echoe", all);
+	print_flags(c_lflag, ECHOK, TLOCAL_DEF, "-echok", all);
+	print_flags(c_lflag, ECHONL, TLOCAL_DEF, "-echonl", all);
+	print_flags(c_lflag, NOFLSH, TLOCAL_DEF, "-noflsh", all);
+#ifdef TOSTOP
+	print_flags(c_lflag, TOSTOP, TLOCAL_DEF, "-tostop", all);
+#endif
+#ifdef __minix
+	print_flags(c_lflag, LFLUSHO, TLOCAL_DEF, "-lflusho", all);
+#endif
+
+	if (all)
+	{
+		printf("\n");
+		column= 0;
+	}
+
+	/* The special control characters. */
+
+	print_char(termios.c_cc[VEOF], TEOF_DEF, "eof", all);
+	print_char(termios.c_cc[VEOL], TEOL_DEF, "eol", all);
+	print_char(termios.c_cc[VERASE], TERASE_DEF, "erase", all);
+	print_char(termios.c_cc[VINTR], TINTR_DEF, "intr", all);
+	print_char(termios.c_cc[VKILL], TKILL_DEF, "kill", all);
+	print_char(termios.c_cc[VQUIT], TQUIT_DEF, "quit", all);
+	print_char(termios.c_cc[VSUSP], TSUSP_DEF, "susp", all);
+	print_char(termios.c_cc[VSTART], TSTART_DEF, "start", all);
+	print_char(termios.c_cc[VSTOP], TSTOP_DEF, "stop", all);
+#ifdef __minix
+	print_char(termios.c_cc[VREPRINT], TREPRINT_DEF, "rprnt", all);
+	print_char(termios.c_cc[VLNEXT], TLNEXT_DEF, "lnext", all);
+	print_char(termios.c_cc[VDISCARD], TDISCARD_DEF, "flush", all);
+#endif
+	print_num(termios.c_cc[VMIN], TMIN_DEF, "min", all);
+	print_num(termios.c_cc[VTIME], TTIME_DEF, "time", all);
+	if (all)
+	{
+		printf("\n");
+		column= 0;
+	}
+
+#ifdef __minix
+	/* Screen size */
+	if (all || winsize.ws_row != 0 || winsize.ws_col != 0)
+	{
+		sprintf(line, "%d rows %d columns", winsize.ws_row, 
+			winsize.ws_col);
+		output(line);
+	}
+
+	if (all || winsize.ws_ypixel != 0 || winsize.ws_xpixel != 0)
+	{
+		sprintf(line, "%d ypixels %d xpixels", winsize.ws_ypixel, 
+			winsize.ws_xpixel);
+		output(line);
+	}
+
+	if (all)
+	{
+		printf("\n");
+		column= 0;
+	}
+#endif
+
+	if (column != 0)
+	{
+		printf("\n");
+		column= 0;
+	}
+}
+
+int option(opt, next)
+char *opt, *next;
+{
+  char *check;
+  speed_t speed;
+  long num;
+
+  /* The control options. */
+
+  if (match(opt, "clocal")) {
+	termios.c_cflag |= CLOCAL;
+	return 0;
+  }
+  if (match(opt, "-clocal")) {
+	termios.c_cflag &= ~CLOCAL;
+	return 0;
+  }
+
+  if (match(opt, "cread")) {
+	termios.c_cflag |= CREAD;
+	return 0;
+  }
+  if (match(opt, "-cread")) {
+	termios.c_cflag &= ~CREAD;
+	return 0;
+  }
+
+  if (match(opt, "cs5")) {
+	termios.c_cflag &= ~CSIZE;
+	termios.c_cflag |= CS5;
+	return 0;
+  }
+  if (match(opt, "cs6")) {
+	termios.c_cflag &= ~CSIZE;
+	termios.c_cflag |= CS6;
+	return 0;
+  }
+  if (match(opt, "cs7")) {
+	termios.c_cflag &= ~CSIZE;
+	termios.c_cflag |= CS7;
+	return 0;
+  }
+  if (match(opt, "cs8")) {
+	termios.c_cflag &= ~CSIZE;
+	termios.c_cflag |= CS8;
+	return 0;
+  }
+
+  if (match(opt, "cstopb")) {
+	termios.c_cflag |= CSTOPB;
+	return 0;
+  }
+  if (match(opt, "-cstopb")) {
+	termios.c_cflag &= ~CSTOPB;
+	return 0;
+  }
+
+  if (match(opt, "hupcl") || match(opt, "hup")) {
+	termios.c_cflag |= HUPCL;
+	return 0;
+  }
+  if (match(opt, "-hupcl") || match(opt, "-hup")) {
+	termios.c_cflag &= ~HUPCL;
+	return 0;
+  }
+
+  if (match(opt, "parenb")) {
+	termios.c_cflag |= PARENB;
+	return 0;
+  }
+  if (match(opt, "-parenb")) {
+	termios.c_cflag &= ~PARENB;
+	return 0;
+  }
+
+  if (match(opt, "parodd")) {
+	termios.c_cflag |= PARODD;
+	return 0;
+  }
+  if (match(opt, "-parodd")) {
+	termios.c_cflag &= ~PARODD;
+	return 0;
+  }
+
+  num= strtol(opt, &check, 10);
+  if (check[0] == '\0')
+  {
+	speed= long2speed(num);
+	if (speed == (speed_t)-1)
+	{
+		fprintf(stderr, "%s: illegal speed: '%s'\n", prog_name, opt);
+		return 0;
+	}
+	/* Speed OK */
+	cfsetispeed(&termios, speed);
+	cfsetospeed(&termios, speed);
+	return 0;
+  }
+
+  if (match(opt, "ispeed")) {
+	num= strtol(next, &check, 10);
+	if (check != '\0')
+	{
+		speed= long2speed(num);
+		if (speed == (speed_t)-1)
+		{
+			fprintf(stderr, "%s: illegal speed: '%s'\n", prog_name, 
+									opt);
+			return 1;
+		}
+		cfsetispeed(&termios, speed);
+		return 1;
+	}
+	else
+	{
+		fprintf(stderr, "%s: invalid argument to ispeed: '%s'\n", 
+			prog_name, next);
+		return 1;
+	}
+  }
+
+  if (match(opt, "ospeed")) {
+	num= strtol(next, &check, 10);
+	if (check != '\0')
+	{
+		speed= long2speed(num);
+		if (speed == (speed_t)-1)
+		{
+			fprintf(stderr, "%s: illegal speed: '%s'\n", prog_name, 
+									opt);
+			return 1;
+		}
+		cfsetospeed(&termios, speed);
+		return 1;
+	}
+	else
+	{
+		fprintf(stderr, "%s: invalid argument to ospeed: %s\n", 
+			prog_name, next);
+		return 1;
+	}
+  }
+
+  /* Input modes. */
+
+  if (match(opt, "brkint")) {
+	termios.c_iflag |= BRKINT;
+	return 0;
+  }
+  if (match(opt, "-brkint")) {
+	termios.c_iflag &= ~BRKINT;
+	return 0;
+  }
+
+  if (match(opt, "icrnl")) {
+	termios.c_iflag |= ICRNL;
+	return 0;
+  }
+  if (match(opt, "-icrnl")) {
+	termios.c_iflag &= ~ICRNL;
+	return 0;
+  }
+
+  if (match(opt, "ignbrk")) {
+	termios.c_iflag |= IGNBRK;
+	return 0;
+  }
+  if (match(opt, "-ignbrk")) {
+	termios.c_iflag &= ~IGNBRK;
+	return 0;
+  }
+
+  if (match(opt, "igncr")) {
+	termios.c_iflag |= IGNCR;
+	return 0;
+  }
+  if (match(opt, "-igncr")) {
+	termios.c_iflag &= ~IGNCR;
+	return 0;
+  }
+
+  if (match(opt, "ignpar")) {
+	termios.c_iflag |= IGNPAR;
+	return 0;
+  }
+  if (match(opt, "-ignpar")) {
+	termios.c_iflag &= ~IGNPAR;
+	return 0;
+  }
+
+  if (match(opt, "inlcr")) {
+	termios.c_iflag |= INLCR;
+	return 0;
+  }
+  if (match(opt, "-inlcr")) {
+	termios.c_iflag &= ~INLCR;
+	return 0;
+  }
+
+  if (match(opt, "inpck")) {
+	termios.c_iflag |= INPCK;
+	return 0;
+  }
+  if (match(opt, "-inpck")) {
+	termios.c_iflag &= ~INPCK;
+	return 0;
+  }
+
+  if (match(opt, "istrip")) {
+	termios.c_iflag |= ISTRIP;
+	return 0;
+  }
+  if (match(opt, "-istrip")) {
+	termios.c_iflag &= ~ISTRIP;
+	return 0;
+  }
+
+  if (match(opt, "ixoff")) {
+	termios.c_iflag |= IXOFF;
+	return 0;
+  }
+  if (match(opt, "-ixoff")) {
+	termios.c_iflag &= ~IXOFF;
+	return 0;
+  }
+
+  if (match(opt, "ixon")) {
+	termios.c_iflag |= IXON;
+	return 0;
+  }
+  if (match(opt, "-ixon")) {
+	termios.c_iflag &= ~IXON;
+	return 0;
+  }
+
+  if (match(opt, "parmrk")) {
+	termios.c_iflag |= PARMRK;
+	return 0;
+  }
+  if (match(opt, "-parmrk")) {
+	termios.c_iflag &= ~PARMRK;
+	return 0;
+  }
+
+  if (match(opt, "ixany")) {
+	termios.c_iflag |= IXANY;
+	return 0;
+  }
+  if (match(opt, "-ixany")) {
+	termios.c_iflag &= ~IXANY;
+	return 0;
+  }
+
+  /* Output modes. */
+
+  if (match(opt, "opost")) {
+	termios.c_oflag |= OPOST;
+	return 0;
+  }
+  if (match(opt, "-opost")) {
+	termios.c_oflag &= ~OPOST;
+	return 0;
+  }
+#ifdef __minix
+  if (match(opt, "onlcr")) {
+	termios.c_oflag |= ONLCR;
+	return 0;
+  }
+  if (match(opt, "-onlcr")) {
+	termios.c_oflag &= ~ONLCR;
+	return 0;
+  }
+
+  if (match(opt, "xtabs")) {
+	termios.c_oflag |= XTABS;
+	return 0;
+  }
+  if (match(opt, "-xtabs")) {
+	termios.c_oflag &= ~XTABS;
+	return 0;
+  }
+
+  if (match(opt, "onoeot")) {
+	termios.c_oflag |= ONOEOT;
+	return 0;
+  }
+  if (match(opt, "-onoeot")) {
+	termios.c_oflag &= ~ONOEOT;
+	return 0;
+  }
+#endif
+
+  /* Local modes. */
+
+  if (match(opt, "echo")) {
+	termios.c_lflag |= ECHO;
+	return 0;
+  }
+  if (match(opt, "-echo")) {
+	termios.c_lflag &= ~ECHO;
+	return 0;
+  }
+
+  if (match(opt, "echoe")) {
+	termios.c_lflag |= ECHOE;
+	return 0;
+  }
+  if (match(opt, "-echoe")) {
+	termios.c_lflag &= ~ECHOE;
+	return 0;
+  }
+
+  if (match(opt, "echok")) {
+	termios.c_lflag |= ECHOK;
+	return 0;
+  }
+  if (match(opt, "-echok")) {
+	termios.c_lflag &= ~ECHOK;
+	return 0;
+  }
+
+  if (match(opt, "echonl")) {
+	termios.c_lflag |= ECHONL;
+	return 0;
+  }
+  if (match(opt, "-echonl")) {
+	termios.c_lflag &= ~ECHONL;
+	return 0;
+  }
+
+  if (match(opt, "icanon")) {
+	termios.c_lflag |= ICANON;
+	return 0;
+  }
+  if (match(opt, "-icanon")) {
+	termios.c_lflag &= ~ICANON;
+	return 0;
+  }
+
+  if (match(opt, "iexten")) {
+	termios.c_lflag |= IEXTEN;
+	return 0;
+  }
+  if (match(opt, "-iexten")) {
+	termios.c_lflag &= ~IEXTEN;
+	return 0;
+  }
+
+  if (match(opt, "isig")) {
+	termios.c_lflag |= ISIG;
+	return 0;
+  }
+  if (match(opt, "-isig")) {
+	termios.c_lflag &= ~ISIG;
+	return 0;
+  }
+
+  if (match(opt, "noflsh")) {
+	termios.c_lflag |= NOFLSH;
+	return 0;
+  }
+  if (match(opt, "-noflsh")) {
+	termios.c_lflag &= ~NOFLSH;
+	return 0;
+  }
+
+  if (match(opt, "tostop")) {
+	termios.c_lflag |= TOSTOP;
+	return 0;
+  }
+  if (match(opt, "-tostop")) {
+	termios.c_lflag &= ~TOSTOP;
+	return 0;
+  }
+
+#ifdef __minix
+  if (match(opt, "lflusho")) {
+	termios.c_lflag |= LFLUSHO;
+	return 0;
+  }
+  if (match(opt, "-lflusho")) {
+	termios.c_lflag &= ~LFLUSHO;
+	return 0;
+  }
+#endif
+
+  /* The special control characters. */
+  if (match(opt, "eof")) {
+	set_control(VEOF, next);
+	return 1;
+  }
+
+  if (match(opt, "eol")) {
+	set_control(VEOL, next);
+	return 1;
+  }
+
+  if (match(opt, "erase")) {
+	set_control(VERASE, next);
+	return 1;
+  }
+
+  if (match(opt, "intr")) {
+	set_control(VINTR, next);
+	return 1;
+  }
+
+  if (match(opt, "kill")) {
+	set_control(VKILL, next);
+	return 1;
+  }
+
+  if (match(opt, "quit")) {
+	set_control(VQUIT, next);
+	return 1;
+  }
+
+  if (match(opt, "susp")) {
+	set_control(VSUSP, next);
+	return 1;
+  }
+
+  if (match(opt, "start")) {
+	set_control(VSTART, next);
+	return 1;
+  }
+
+  if (match(opt, "stop")) {
+	set_control(VSTOP, next);
+	return 1;
+  }
+#ifdef __minix
+  if (match(opt, "rprnt")) {
+	set_control(VREPRINT, next);
+	return 1;
+  }
+
+  if (match(opt, "lnext")) {
+	set_control(VLNEXT, next);
+	return 1;
+  }
+
+  if (match(opt, "flush")) {
+	set_control(VDISCARD, next);
+	return 1;
+  }
+#endif
+ 
+  if (match(opt, "min")) {
+	set_min_tim(VMIN, next);
+	return 1;
+  }
+
+  if (match(opt, "time")) {
+	set_min_tim(VTIME, next);
+	return 1;
+  }
+
+  /* Special modes. */
+  if (opt[0] == ':')
+  {
+	set_saved_settings(opt);
+	return 0;
+  }
+
+  if (match(opt, "cooked") || match(opt, "raw")) {
+	int x = opt[0] == 'c' ? 1 : 0;
+
+	option(x + "-icrnl", "");	/* off in raw mode, on in cooked mode */
+	option(x + "-ixon", "");
+	option(x + "-opost", "");
+	option(x + "-onlcr", "");
+	option(x + "-isig", "");
+	option(x + "-icanon", "");
+	option(x + "-iexten", "");
+	option(x + "-echo", "");
+	return 0;
+  }
+
+  if (match(opt, "evenp") || match(opt, "parity")) {
+	option("parenb", "");
+	option("cs7", "");
+	option("-parodd", "");
+	return 0;
+  }
+
+  if (match(opt, "oddp")) {
+	option("parenb", "");
+	option("cs7", "");
+	option("parodd", "");
+	return 0;
+  }
+
+  if (match(opt, "-parity") || match(opt, "-evenp") || match(opt, "-oddp")) {
+	option("-parenb", "");
+	option("cs8", "");
+	return 0;
+  }
+
+  if (match(opt, "nl")) {
+	option("icrnl", "");
+	return 0;
+  }
+
+  if (match(opt, "-nl")) {
+	option("-icrnl", "");
+	option("-inlcr", "");
+	option("-igncr", "");
+	return 0;
+  }
+
+  if (match(opt, "ek")) {
+	termios.c_cc[VERASE]= TERASE_DEF;;
+	termios.c_cc[VKILL]= TKILL_DEF;;
+	return 0;
+  }
+
+  if (match(opt, "sane"))
+  {
+	/* Reset all terminal attributes to a sane state, except things like
+	 * line speed and parity, because it can't be known what their sane
+	 * values are.
+	 */
+	termios.c_iflag= (TINPUT_DEF & ~(IGNPAR|ISTRIP|INPCK))
+		| (termios.c_iflag & (IGNPAR|ISTRIP|INPCK));
+	termios.c_oflag= (TOUTPUT_DEF & ~(XTABS))
+		| (termios.c_oflag & (XTABS));
+	termios.c_cflag= (TCTRL_DEF & ~(CLOCAL|CSIZE|CSTOPB|PARENB|PARODD))
+		| (termios.c_cflag & (CLOCAL|CSIZE|CSTOPB|PARENB|PARODD));
+	termios.c_lflag= (TLOCAL_DEF & ~(ECHOE|ECHOK))
+		| (termios.c_lflag & (ECHOE|ECHOK));
+	if (termios.c_lflag & ICANON) {
+		termios.c_cc[VMIN]= TMIN_DEF;
+		termios.c_cc[VTIME]= TTIME_DEF;
+	}
+	termios.c_cc[VEOF]= TEOF_DEF;
+	termios.c_cc[VEOL]= TEOL_DEF;
+	termios.c_cc[VERASE]= TERASE_DEF;
+	termios.c_cc[VINTR]= TINTR_DEF;
+	termios.c_cc[VKILL]= TKILL_DEF;
+	termios.c_cc[VQUIT]= TQUIT_DEF;
+	termios.c_cc[VSUSP]= TSUSP_DEF;
+#ifdef __minix
+	termios.c_cc[VREPRINT]= TREPRINT_DEF;
+	termios.c_cc[VLNEXT]= TLNEXT_DEF;
+	termios.c_cc[VDISCARD]= TDISCARD_DEF;
+#endif
+	termios.c_cc[VSTART]= TSTART_DEF;
+	termios.c_cc[VSTOP]= TSTOP_DEF;
+	if (!(termios.c_lflag & ICANON)) {
+		termios.c_cc[VMIN]= TMIN_DEF;
+		termios.c_cc[VTIME]= TTIME_DEF;
+	}
+	return 0;
+  }
+
+#ifdef __minix
+  if (match(opt, "cols"))
+  {
+  	num= strtol(next, &check, 0);
+  	if (check[0] != '\0')
+  	{
+  		fprintf(stderr, "%s: illegal parameter to cols: '%s'\n", 
+  							prog_name, next);
+  		return 1;
+  	}
+  	winsize.ws_col= num;
+	return 1;
+  }
+
+  if (match(opt, "rows"))
+  {
+  	num= strtol(next, &check, 0);
+  	if (check[0] != '\0')
+  	{
+  		fprintf(stderr, "%s: illegal parameter to rows: '%s'\n", 
+  							prog_name, next);
+  		return 1;
+  	}
+  	winsize.ws_row= num;
+	return 1;
+  }
+
+  if (match(opt, "xpixels"))
+  {
+  	num= strtol(next, &check, 0);
+  	if (check[0] != '\0')
+  	{
+  		fprintf(stderr, "%s: illegal parameter to xpixels: '%s'\n", 
+  							prog_name, next);
+  		return 1;
+  	}
+  	winsize.ws_xpixel= num;
+	return 1;
+  }
+
+  if (match(opt, "ypixels"))
+  {
+  	num= strtol(next, &check, 0);
+  	if (check[0] != '\0')
+  	{
+  		fprintf(stderr, "%s: illegal parameter to ypixels: '%s'\n", 
+  							prog_name, next);
+  		return 1;
+  	}
+  	winsize.ws_ypixel= num;
+	return 1;
+  }
+#endif /* __minix */
+
+  fprintf(stderr, "%s: unknown mode: %s\n", prog_name, opt);
+  return 0;
+}
+
+int match(s1, s2)
+char *s1, *s2;
+{
+
+  while (1) {
+	if (*s1 == 0 && *s2 == 0) return(1);
+	if (*s1 == 0 || *s2 == 0) return (0);
+	if (*s1 != *s2) return (0);
+	s1++;
+	s2++;
+  }
+}
+
+void prctl(c)
+char c;
+{
+  if (c < ' ')
+	printf("^%c", 'A' + c - 1);
+  else if (c == 0177)
+	printf("^?");
+  else
+	printf("%c", c);
+}
+
+struct s2s {
+	speed_t ts;
+	long ns;
+} s2s[] = {
+	{ B0,		     0 },
+	{ B50,		    50 },
+	{ B75,		    75 },
+	{ B110,		   110 },
+	{ B134,		   134 },
+	{ B150,		   150 },
+	{ B200,		   200 },
+	{ B300,		   300 },
+	{ B600,		   600 },
+	{ B1200,	  1200 },
+	{ B1800,	  1800 },
+	{ B2400,	  2400 },
+	{ B4800,	  4800 },
+	{ B9600,	  9600 },
+	{ B19200,	 19200 },
+	{ B38400,	 38400 },
+#ifdef __minix
+	{ B57600,	 57600 },
+	{ B115200,	115200 },
+#ifdef B230400
+	{ B230400,	230400 },
+#endif
+#ifdef B460800
+	{ B460800,	460800 },
+#endif
+#ifdef B921600
+	{ B921600,	921600 },
+#endif
+#endif
+};
+
+speed_t long2speed(num)
+long num;
+{
+	struct s2s *sp;
+
+	for (sp = s2s; sp < s2s + (sizeof(s2s) / sizeof(s2s[0])); sp++) {
+		if (sp->ns == num) return sp->ts;
+	}
+	return -1;
+}
+
+long speed2long(speed)
+unsigned long speed;
+{
+	struct s2s *sp;
+
+	for (sp = s2s; sp < s2s + (sizeof(s2s) / sizeof(s2s[0])); sp++) {
+		if (sp->ts == speed) return sp->ns;
+	}
+	return -1;
+}
+		
+void print_flags(flags, flag, def, string, all)
+unsigned long flags;
+unsigned long flag;
+unsigned long def;
+char *string;
+int all;
+{
+	if (!(flags & flag))
+	{
+		if (all || (def & flag))
+			output(string);
+		return;
+	}
+	string++;
+	if (all || !(def & flag))
+		output(string);
+}
+
+void output(s)
+char *s;
+{
+	int len;
+
+	len= strlen(s);
+	if (column + len + 3 >= max_column)
+	{
+		printf("\n");
+		column= 0;
+	}
+	if (column)
+	{
+		putchar(' ');
+		column++;
+	}
+	fputs(s, stdout);
+	column += len;
+}
+
+void do_print_char(chr, def, name, all)
+unsigned chr;
+unsigned def;
+char *name;
+int all;
+{
+	char line[20];
+
+	if (!all && chr == def)
+		return;
+	
+#ifdef _POSIX_VDISABLE
+	if (chr == _POSIX_VDISABLE)
+		sprintf(line, "%s = <undef>", name);
+	else
+#endif
+	if (chr < ' ')
+		sprintf(line, "%s = ^%c", name, chr + '@');
+	else if (chr == 127)
+		sprintf(line, "%s = ^?", name);
+	else
+		sprintf(line, "%s = %c", name, chr);
+	output(line);
+}
+
+void do_print_num(num, def, name, all)
+unsigned num;
+unsigned def;
+char *name;
+int all;
+{
+	char line[20];
+		
+	if (!all && num == def)
+		return;
+	sprintf(line, "%s = %u", name, num);
+	output(line);
+}
+
+void set_saved_settings(opt)
+char *opt;
+{
+	long num;
+	char *check;
+	tcflag_t c_oflag, c_cflag, c_lflag, c_iflag;
+	cc_t c_cc[NCCS];
+	speed_t ispeed, ospeed;
+	int i;
+
+	check= opt;
+	num= strtol(check+1, &check, 16);
+	if (check[0] != ':')
+	{
+		fprintf(stderr, "error in saved settings '%s'\n", opt);
+		return;
+	}
+	c_iflag= num;
+
+	num= strtol(check+1, &check, 16);
+	if (check[0] != ':')
+	{
+		fprintf(stderr, "error in saved settings '%s'\n", opt);
+		return;
+	}
+	c_oflag= num;
+
+	num= strtol(check+1, &check, 16);
+	if (check[0] != ':')
+	{
+		fprintf(stderr, "error in saved settings '%s'\n", opt);
+		return;
+	}
+	c_cflag= num;
+
+	num= strtol(check+1, &check, 16);
+	if (check[0] != ':')
+	{
+		fprintf(stderr, "error in saved settings '%s'\n", opt);
+		return;
+	}
+	c_lflag= num;
+
+	num= strtol(check+1, &check, 16);
+	if (check[0] != ':')
+	{
+		fprintf(stderr, "error in saved settings '%s'\n", opt);
+		return;
+	}
+	ispeed= num;
+
+	num= strtol(check+1, &check, 16);
+	if (check[0] != ':')
+	{
+		fprintf(stderr, "error in saved settings '%s'\n", opt);
+		return;
+	}
+	ospeed= num;
+
+	for(i=0; i<NCCS; i++)
+	{
+		num= strtol(check+1, &check, 16);
+		if (check[0] != ':')
+		{
+			fprintf(stderr, "error in saved settings '%s'\n", opt);
+			return;
+		}
+		c_cc[i]= num;
+	}
+	if (check[1] != '\0')
+	{
+		fprintf(stderr, "error in saved settings '%s'\n", opt);
+		return;
+	}
+	termios.c_iflag= c_iflag;
+	termios.c_oflag= c_oflag;
+	termios.c_cflag= c_cflag;
+	termios.c_lflag= c_lflag;
+
+	cfsetispeed(&termios, ispeed);
+	cfsetospeed(&termios, ospeed);
+
+	for(i=0; i<NCCS; i++)
+		termios.c_cc[i]= c_cc[i];
+}
+
+void set_control(option, value)
+int option;
+char *value;
+{
+	int chr;
+
+	if (match(value, "undef") || match(value, "^-")) {
+#ifdef _POSIX_VDISABLE
+		chr= _POSIX_VDISABLE;
+#else
+		fprintf(stderr, 
+			"stty: unable to set option to _POSIX_VDISABLE\n");
+		return;
+#endif
+	} else if (match(value, "^?"))
+		chr= '\177';
+	else if (strlen(value) == 2 && value[0] == '^') {
+		chr= toupper(value[1]) - '@';
+		if (chr < 0 || chr >= 32) {
+			fprintf(stderr, "stty: illegal option value: '%s'\n",
+				value);
+			return;
+		}
+	} else if (strlen(value) == 1)
+		chr= value[0];
+	else {
+		fprintf(stderr, "stty: illegal option value: '%s'\n", value);
+		return;
+	}
+
+	assert(option >= 0 && option < NCCS);
+	termios.c_cc[option]= chr;
+}
+		
+void set_min_tim(option, value)
+int option;
+char *value;
+{
+	long num;
+	char *check;
+
+	num= strtol(value, &check, 0);
+	if (check[0] != '\0') {
+		fprintf(stderr, "stty: illegal option value: '%s'\n", value);
+		return;
+	}
+
+	if ((cc_t)num != num) {
+		fprintf(stderr, "stty: illegal option value: '%s'\n", value);
+		return;
+	}
+	assert(option >= 0 && option < NCCS);
+	termios.c_cc[option]= num;
+}
+
+/*
+ * $PchId: stty.c,v 1.7 2001/05/02 15:04:42 philip Exp $
+ */
Index: /trunk/minix/commands/simple/su.c
===================================================================
--- /trunk/minix/commands/simple/su.c	(revision 9)
+++ /trunk/minix/commands/simple/su.c	(revision 9)
@@ -0,0 +1,155 @@
+/* su - become super-user		Author: Patrick van Kleef */
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <time.h>
+#if __minix_vmd
+#include <sys/syslog.h>
+#endif
+#include <minix/minlib.h>
+
+_PROTOTYPE(int main, (int argc, char **argv));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  register char *name, *password;
+  char *shell, sh0[100];
+  char from_user[8+1], from_shell[100];
+  register struct passwd *pwd;
+  char USER[20], LOGNAME[25], HOME[100], SHELL[100];
+  char *envv[20], **envp;
+  int smallenv;
+  char *p;
+  int super;
+  int loginshell;
+#if __minix_vmd
+  gid_t groups[NGROUPS_MAX];
+  int ngroups;
+  int g;
+#endif
+
+  smallenv = 0;
+  loginshell = 0;
+  if (argc > 1 && (strcmp(argv[1], "-") == 0 || strcmp(argv[1], "-e") == 0)) {
+	if (argv[1][1] == 0)
+		loginshell= 1;		/* 'su -' reads .profile */
+	argv[1] = argv[0];
+	argv++;
+	argc--;
+	smallenv = 1;	/* Use small environment. */
+  }
+  if (argc > 1) {
+	if (argv[1][0] == '-') {
+		fprintf(stderr,
+			"Usage: su [-[e]] [user [shell-arguments ...]]\n");
+		exit(1);
+	}
+	name = argv[1];
+	argv[1] = argv[0];
+	argv++;
+  } else {
+	name = "root";
+  }
+
+  if ((pwd = getpwuid(getuid())) == 0) {
+	fprintf(stderr, "You do not exist\n");
+	exit(1);
+  }
+  strncpy(from_user, pwd->pw_name, 8);
+  from_user[8]= 0;
+  strncpy(from_shell, pwd->pw_shell[0] == '\0' ? "/bin/sh" : pwd->pw_shell,
+						sizeof(from_shell)-1);
+  from_shell[sizeof(from_shell)-1]= 0;
+
+  if ((pwd = getpwnam(name)) == 0) {
+	fprintf(stderr, "Unknown id: %s\n", name);
+	exit(1);
+  }
+  super = 0;
+  if (getgid() == 0) super = 1;
+#if __minix_vmd
+  ngroups = getgroups(NGROUPS_MAX, groups);
+  for (g = 0; g < ngroups; g++) if (groups[g] == 0) super = 1;
+#endif
+
+  if (!super && strcmp(pwd->pw_passwd, crypt("", pwd->pw_passwd)) != 0) {
+#if __minix_vmd
+	openlog("su", 0, LOG_AUTH);
+#endif
+	password = getpass("Password:");
+	if (password == 0
+	  || strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) {
+		if (password != 0 && *password != 0) {
+#if __minix_vmd
+			syslog(LOG_WARNING, "su %s failed for %s",
+							name, from_user);
+#endif
+		}
+		fprintf(stderr, "Sorry\n");
+		exit(2);
+	}
+#if __minix_vmd
+	syslog(LOG_NOTICE, "su %s succeeded for %s", name, from_user);
+	closelog();
+#endif
+  }
+
+#if __minix_vmd
+  initgroups(pwd->pw_name, pwd->pw_gid);
+#endif
+  setgid(pwd->pw_gid);
+  setuid(pwd->pw_uid);
+  if (loginshell) {
+	shell = pwd->pw_shell[0] == '\0' ? "/bin/sh" : pwd->pw_shell;
+  } else {
+	if ((shell = getenv("SHELL")) == NULL) shell = from_shell;
+  }
+  if ((p= strrchr(shell, '/')) == 0) p= shell; else p++;
+  sh0[0]= '-';
+  strcpy(loginshell ? sh0+1 : sh0, p);
+  argv[0]= sh0;
+
+  if (smallenv) {
+	envp = envv;
+	*envp++ = "PATH=:/bin:/usr/bin",
+	strcpy(USER, "USER=");
+	strcpy(USER + 5, name);
+	*envp++ = USER;
+	strcpy(LOGNAME, "LOGNAME=");
+	strcpy(LOGNAME + 8, name);
+	*envp++ = LOGNAME;
+	strcpy(SHELL, "SHELL=");
+	strcpy(SHELL + 6, shell);
+	*envp++ = SHELL;
+	strcpy(HOME, "HOME=");
+	strcpy(HOME + 5, pwd->pw_dir);
+	*envp++ = HOME;
+	if ((p = getenv("TERM")) != NULL) {
+		*envp++ = p - 5;
+	}
+	if ((p = getenv("TERMCAP")) != NULL) {
+		*envp++ = p - 8;
+	}
+	if ((p = getenv("TZ")) != NULL) {
+		*envp++ = p - 3;
+	}
+	*envp = NULL;
+	(void) chdir(pwd->pw_dir);
+	execve(shell, argv, envv);
+	perror(shell);
+  } else {
+	execv(shell, argv);
+	perror(shell);
+  }
+  fprintf(stderr, "No shell\n");
+  return(3);
+}
Index: /trunk/minix/commands/simple/sum.c
===================================================================
--- /trunk/minix/commands/simple/sum.c	(revision 9)
+++ /trunk/minix/commands/simple/sum.c	(revision 9)
@@ -0,0 +1,121 @@
+/* sum - checksum a file		Author: Martin C. Atkins */
+
+/*
+ *	This program was written by:
+ *		Martin C. Atkins,
+ *		University of York,
+ *		Heslington,
+ *		York. Y01 5DD
+ *		England
+ *	and is released into the public domain, on the condition
+ *	that this comment is always included without alteration.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <minix/minlib.h>
+#include <stdio.h>
+
+#define BUFFER_SIZE (512)
+
+int rc = 0;
+
+char *defargv[] = {"-", 0};
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void error, (char *s, char *f));
+_PROTOTYPE(void sum, (int fd, char *fname));
+_PROTOTYPE(void putd, (int number, int fw, int zeros));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  register int fd;
+
+  if (*++argv == 0) argv = defargv;
+  for (; *argv; argv++) {
+	if (argv[0][0] == '-' && argv[0][1] == '\0')
+		fd = 0;
+	else
+		fd = open(*argv, O_RDONLY);
+
+	if (fd == -1) {
+		error("can't open ", *argv);
+		rc = 1;
+		continue;
+	}
+	sum(fd, (argc > 2) ? *argv : (char *) 0);
+	if (fd != 0) close(fd);
+  }
+  return(rc);
+}
+
+void error(s, f)
+char *s, *f;
+{
+
+  std_err("sum: ");
+  std_err(s);
+
+  if (f) std_err(f);
+  std_err("\n");
+}
+
+void sum(fd, fname)
+int fd;
+char *fname;
+{
+  char buf[BUFFER_SIZE];
+  register int i, n;
+  long size = 0;
+  unsigned crc = 0;
+  unsigned tmp, blks;
+
+  while ((n = read(fd, buf, BUFFER_SIZE)) > 0) {
+	for (i = 0; i < n; i++) {
+		crc = (crc >> 1) + ((crc & 1) ? 0x8000 : 0);
+		tmp = buf[i] & 0377;
+		crc += tmp;
+		crc &= 0xffff;
+		size++;
+	}
+  }
+
+  if (n < 0) {
+	if (fname)
+		error("read error on ", fname);
+	else
+		error("read error", (char *) 0);
+	rc = 1;
+	return;
+  }
+  putd(crc, 5, 1);
+  blks = (size + (long) BUFFER_SIZE - 1L) / (long) BUFFER_SIZE;
+  putd(blks, 6, 0);
+  if (fname) printf(" %s", fname);
+  printf("\n");
+}
+
+void putd(number, fw, zeros)
+int number, fw, zeros;
+{
+/* Put a decimal number, in a field width, to stdout. */
+
+  char buf[10];
+  int n;
+  unsigned num;
+
+  num = (unsigned) number;
+  for (n = 0; n < fw; n++) {
+	if (num || n == 0) {
+		buf[fw - n - 1] = '0' + num % 10;
+		num /= 10;
+	} else
+		buf[fw - n - 1] = zeros ? '0' : ' ';
+  }
+  buf[fw] = 0;
+  printf("%s", buf);
+}
Index: /trunk/minix/commands/simple/swapfs.c
===================================================================
--- /trunk/minix/commands/simple/swapfs.c	(revision 9)
+++ /trunk/minix/commands/simple/swapfs.c	(revision 9)
@@ -0,0 +1,1048 @@
+/* swapfs - swap a Minix file system	    Author: Niels C. Willems */
+
+
+/* $Id: swapfs.c,v 1.1.1.1 2005/04/21 14:55:33 beng Exp $ */
+
+/* Swapfs, a program to convert V1 or V2 Minix file systems from big endian
+   byte order to little endian and vv.
+
+   Some examples:
+   swapfs -v disk.01			! only show verbose information.
+   swapfs /dev/fd0 | compress > fd0r.Z	! convert and compress filesystem.
+   swapfs -v fileA fileA	! read, convert and write the same filesystem.
+
+  This program uses one byte of heap memory for each data block (1Kbytes)
+  in the file system, so with Minix-PC 16-bit you can't swap file systems
+  bigger than about 32 Mbytes
+
+  Be careful with 'swapfs fileA fileA'. If the program aborts e.g. by
+  user interrupt, power failure or an inconsistent file system, you
+  better have a backup of fileA
+
+  This program only converts directories and indirect blocks of files
+  that are in use. Converting indirect blocks or directories of deleted
+  files is hard and not yet done.
+
+  If you have a (1.6.xx, xx < 18) version of Minix that supports the
+  mounting of reversed file systems always mount them read-only and
+  avoid any attemp to modify them (mkdir, open, creat) too!
+  These problems have been fixed in Minix 1.6.18.
+
+  In this version you can get some more information about the
+  file system with the -d (debug) flag.
+
+      Please send your bug reports or ideas to ncwille@cs.vu.nl
+ */
+
+
+#define _POSIX_SOURCE	1
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include <assert.h>
+
+#if __STDC__ == 1
+#define	_PROTOTYPE(function, params)	function params
+#else
+#define	_PROTOTYPE(function, params)	function()
+#endif
+
+#define BLOCK_SIZE	1024
+
+#define BOOT_BLOCK_OFF	   (blockn_t) 0
+#define SUPER_BLOCK_OFF    (blockn_t) 1
+
+#define V1_MAGIC		0x137F
+#define V2_MAGIC		0x2468
+#define NINODES_OFFSET		     0
+#define V1_ZONES_OFFSET		     2
+#define IMAP_BLOCKS_OFFSET	     4
+#define ZMAP_BLOCKS_OFFSET	     6
+#define FIRSTDATAZONE_OFFSET	     8
+#define LOG_ZONE_SIZE_OFFSET        10
+#define MAGIC_OFFSET		    16
+#define V2_ZONES_OFFSET		    20
+
+
+#define NR_DIRECT_ZONES	 7
+#define V1_NR_TZONES	 9
+#define V2_NR_TZONES	10
+#define V1_INODE_SIZE	32
+#define V2_INODE_SIZE	64
+
+#define INODE1_MODE_OFF		 0
+#define INODE1_SIZE_OFF		 4
+#define INODE1_DIRECT_OFF	14
+#define INODE1_IND1_OFF		28
+#define INODE1_IND2_OFF		30
+
+#define INODE2_MODE_OFF		 0
+#define INODE2_SIZE_OFF		 8
+#define INODE2_DIRECT_OFF	24
+#define INODE2_IND1_OFF		52
+#define INODE2_IND2_OFF		56
+#define INODE2_IND3_OFF		60
+
+#define INODE_MODE_MASK		0xf000	/* file type mask    */
+#define INODE_DIR_MODE		0x4000	/* directory         */
+#define INODE_BLK_SPECIAL_MODE	0x6000	/* block special     */
+#define INODE_CHR_SPECIAL_MODE  0x2000	/* character special */
+
+#define T_MASK		0x1c
+#define T_UNKNOWN	0x00
+#define T_MAYBE_OLD_DIR	0x04
+#define T_OLD_NON_DIR	0x08
+#define T_DIR		0x0c
+#define T_NON_DIR	0x10
+
+#define INDIRECT_MASK	0x03
+
+#define IND_PROCESSED_BIT 0x20	/* set when all blocks in ind block are
+			 * marked */
+#define IND_CONFLICT_BIT  0x40
+#define TYPE_CONFLICT_BIT 0x80
+
+#define DIR_ENTRY_SIZE    16
+
+typedef enum {
+  Unused_zone, Old_zone, In_use_zone
+} class_t;
+
+typedef unsigned long blockn_t;
+typedef unsigned int inodesn_t;
+
+typedef struct {
+  inodesn_t ninodes;		/* # usable inodes on the minor device */
+  blockn_t imap_blocks;		/* # of blocks used by inode bit map */
+  blockn_t zmap_blocks;		/* # of blocks used by zone bit map */
+  blockn_t firstdatazone;	/* number of first data zone */
+  int log_zone_size;		/* log2 of blocks/zone */
+  blockn_t zones;		/* number of zones */
+
+  int version;			/* file system version */
+  inodesn_t inodes_per_block;
+  blockn_t first_imap_block;
+  blockn_t first_zmap_block;
+  blockn_t first_inode_block;	/* number of first block with inodes */
+  size_t dzmap_size;		/* # of data zone blocks */
+} super_t;
+
+
+typedef struct {		/* summary of inode */
+  long size;			/* current file size in bytes */
+  blockn_t direct[NR_DIRECT_ZONES];	/* block numbers for direct,
+					 * ind, ... */
+  blockn_t ind1;		/* single indirect block number */
+  blockn_t ind2;		/* double indirect block number */
+  blockn_t ind3;		/* triple indirect block number */
+  int ztype;			/* type of zones that belong to this inode */
+} inode_t;
+
+static char rcsid[] = "$Id: swapfs.c,v 1.1.1.1 2005/04/21 14:55:33 beng Exp $";
+
+static int super_format[] = {2, 2, 2, 2, 2, 2, 4, 2, 2, 4, 0};
+static int inode1_format[] = {2, 2, 4, 4, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0};
+static int inode2_format[] = {2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+		      4, 4, 0};
+
+static char *ind_str[4] = {"direct", "single indirect",
+		   "double indirect", "triple indirect"};
+
+static int big_endian_fs;	/* set in init_super(), 1 iff file system has
+			 * big endian byte order */
+static int verbose_flag;
+static int debug_flag;
+static int test_flag;
+
+typedef unsigned char *dzmap_t;
+
+
+int _PROTOTYPE(main, (int argc, char *argv[]));
+static void _PROTOTYPE(parse_args_init_io, (int argc, char *argv[]));
+static void _PROTOTYPE(rw_boot, (void));
+static void _PROTOTYPE(rw_init_super, (super_t * sp));
+static void _PROTOTYPE(init_dzmap, (dzmap_t * dzmap_ptr, size_t dzmap_size));
+static void _PROTOTYPE(rw_ibmap, (super_t super));
+static void _PROTOTYPE(rw_zbmap, (super_t super));
+static void _PROTOTYPE(print_stat, (dzmap_t dzmap, super_t super));
+static void _PROTOTYPE(p1_rw_inodes, (dzmap_t dzmap, super_t super));
+static void _PROTOTYPE(rd_indirects, (dzmap_t dzmap, super_t super, int ind,
+			       class_t required_class));
+static void _PROTOTYPE(rw_data_zones, (dzmap_t dzmap, super_t super));
+
+static int _PROTOTYPE(read_block, (char *buf, blockn_t offset));
+static void _PROTOTYPE(write_block, (char *buf));
+static int _PROTOTYPE(convcpy, (char *dst, char *src, int *format));
+static void _PROTOTYPE(conv2_blkcpy, (char *dst, char *src));
+static void _PROTOTYPE(conv4_blkcpy, (char *dst, char *src));
+static void _PROTOTYPE(conv2cpy, (char *dst, char *src));
+static int _PROTOTYPE(inode_size, (int version));
+
+static void _PROTOTYPE(init_super, (super_t * sp, char *buf));
+static void _PROTOTYPE(get_inode, (inode_t * ip, char *buf, int version));
+static int _PROTOTYPE(check_inode, (inode_t inode, super_t super));
+static int _PROTOTYPE(was_blk_special, (inode_t inode));
+static int _PROTOTYPE(check_blk_number, (blockn_t num, super_t super));
+static void _PROTOTYPE(cw_inode_block, (char *buf, inodesn_t ninodes,
+				 int version));
+static void _PROTOTYPE(proc_ind, (dzmap_t dzmap, size_t curr_ind,
+			   char *buf, super_t super));
+static void _PROTOTYPE(cw_dir_block, (char *buf));
+static void _PROTOTYPE(dzmap_add_inode, (dzmap_t dzmap, inode_t inode,
+				  super_t super));
+static void _PROTOTYPE(dz_update, (dzmap_t dzmap, blockn_t blknum,
+		     int new_indnum, int new_ztype, super_t super));
+static class_t _PROTOTYPE(ztype_class, (int ztype));
+
+static unsigned int _PROTOTYPE(two_bytes, (char buf[2]));
+static long _PROTOTYPE(four_bytes, (char buf[4]));
+
+static void _PROTOTYPE(fail, (char *string));
+static void _PROTOTYPE(usage, (char *arg0));
+
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  super_t super;
+  dzmap_t dzmap;
+
+  parse_args_init_io(argc, argv);
+  rw_boot();
+  rw_init_super(&super);
+  init_dzmap(&dzmap, super.dzmap_size);
+  rw_ibmap(super);
+  rw_zbmap(super);
+  p1_rw_inodes(dzmap, super);
+
+  rd_indirects(dzmap, super, 3, In_use_zone);
+  rd_indirects(dzmap, super, 2, In_use_zone);
+  rd_indirects(dzmap, super, 1, In_use_zone);
+  if (verbose_flag) putc('\n', stderr);
+
+  print_stat(dzmap, super);
+  rw_data_zones(dzmap, super);
+  return 0;
+}
+
+
+static void parse_args_init_io(argc, argv)
+int argc;
+char *argv[];
+{
+  char *str;
+  struct stat buf;
+  ino_t src_ino;
+  int i;
+
+  debug_flag = 0;
+  verbose_flag = 0;
+  test_flag = 0;
+
+  for (i = 1; i < argc; i++) {
+	str = argv[i];
+	if (*str != '-') break;
+	switch (*++str) {
+	    case 'v':	verbose_flag = 1;	break;
+	    case 'd':
+		debug_flag = 1;
+		verbose_flag = 1;
+		break;
+	    case 't':	test_flag = 1;	break;
+	    default:	usage(argv[0]);
+	}
+  }
+  if ((argc - i == 0 && isatty(0)) || (argc - i) > 2) usage(argv[0]);
+
+  if (argc - i > 0) {
+	(void) close(0);
+	if (open(argv[i], O_RDONLY) != 0) {
+		fprintf(stderr, "Can't open input file %s", argv[i]);
+		fail("");
+	}
+  }
+  if (isatty(1) || argc - i == 2) {
+	if (argc - i < 2)
+		test_flag = 1;
+	else {
+		i++;
+		(void) close(1);
+		(void) fstat(0, &buf);
+		src_ino = buf.st_ino;
+		if (stat(argv[i], &buf) == 0 && src_ino == buf.st_ino) {
+			/* Src and dest are the same */
+			if (open(argv[i], O_WRONLY) != 1) {
+				fprintf(stderr, "Can't open output file %s", argv[i]);
+				fail("");
+			}
+		} else if (creat(argv[i], 0644) != 1) {
+			fprintf(stderr, "Can't creat output file %s", argv[i]);
+			fail("");
+		}
+	}
+  }
+}
+
+
+static void rw_boot()
+{
+  char buf[BLOCK_SIZE];
+
+  if (read_block(buf, BOOT_BLOCK_OFF) != BLOCK_SIZE)
+	fail("Can't read bootblock");
+  write_block(buf);
+}
+
+
+static void rw_init_super(sp)
+super_t *sp;
+{
+  char ibuf[BLOCK_SIZE], obuf[BLOCK_SIZE];
+
+  if (read_block(ibuf, SUPER_BLOCK_OFF) != BLOCK_SIZE)
+	fail("Can't read superblock");
+
+  init_super(sp, ibuf);
+
+  memcpy(obuf, ibuf, (size_t) BLOCK_SIZE);	/* preserve 'unused' data */
+  (void) convcpy(obuf, ibuf, super_format);
+
+  write_block(obuf);
+}
+
+
+static void init_dzmap(dzmap_ptr, dzmap_size)
+dzmap_t *dzmap_ptr;
+size_t dzmap_size;
+{
+  if ((*dzmap_ptr = (dzmap_t) malloc(dzmap_size)) == (dzmap_t) NULL)
+	fail("Not enough space for data zone map");
+  memset(*dzmap_ptr, '\0', (size_t) dzmap_size);
+}
+
+
+static void rw_ibmap(super)
+super_t super;
+{
+  char ibuf[BLOCK_SIZE], obuf[BLOCK_SIZE];
+  blockn_t i;
+
+  for (i = 0; i < super.imap_blocks; i++) {
+	if (read_block(ibuf, super.first_imap_block + i) != BLOCK_SIZE)
+		fail("Can't read inode bit map");
+	conv2_blkcpy(obuf, ibuf);
+	write_block(obuf);
+  }
+}
+
+
+static void rw_zbmap(super)
+super_t super;
+{
+  char ibuf[BLOCK_SIZE], obuf[BLOCK_SIZE];
+  blockn_t i;
+
+  for (i = 0; i < super.zmap_blocks; i++) {
+	if (read_block(ibuf, super.first_zmap_block + i) != BLOCK_SIZE)
+		fail("Can't read zone bit map");
+	conv2_blkcpy(obuf, ibuf);
+	write_block(obuf);
+  }
+}
+
+
+static void p1_rw_inodes(dzmap, super)
+dzmap_t dzmap;
+super_t super;
+{
+  char buf[BLOCK_SIZE], *buf_ptr;
+  inodesn_t i, num_inodes;
+  blockn_t next_block;
+  inode_t inode;
+
+
+  next_block = super.first_inode_block;
+
+  for (i = 1; i <= super.ninodes; i++) {
+	if ((i - 1) % super.inodes_per_block == 0) {
+		if (read_block(buf, next_block) != BLOCK_SIZE)
+			fail("read failed in inode block");
+		buf_ptr = buf;
+		next_block++;
+		num_inodes = super.ninodes + 1 - i;
+		if (num_inodes > super.inodes_per_block)
+			num_inodes = super.inodes_per_block;
+		cw_inode_block(buf, num_inodes, super.version);
+	}
+	get_inode(&inode, buf_ptr, super.version);
+	dzmap_add_inode(dzmap, inode, super);
+	buf_ptr += inode_size(super.version);
+  }
+}
+
+
+static void print_stat(dzmap, super)
+dzmap_t dzmap;
+super_t super;
+{
+  size_t i;
+  register unsigned char dz;
+  int both_conflict = 0, ind_conflict = 0, type_conflict = 0, unreferenced = 0;
+  int not_in_use = 0;
+
+  if (!verbose_flag) return;
+
+  for (i = 0; i < super.dzmap_size; i++) {
+	dz = dzmap[i];
+	if (dz & IND_CONFLICT_BIT && dz & TYPE_CONFLICT_BIT)
+		both_conflict++;
+	else if (dz & IND_CONFLICT_BIT)
+		ind_conflict++;
+	else if (dz & TYPE_CONFLICT_BIT)
+		type_conflict++;
+
+	if (dz == 0) unreferenced++;
+	if (ztype_class(dz & T_MASK) < In_use_zone) not_in_use++;
+
+  }
+  if (debug_flag) {
+	fprintf(stderr, "%5d zone blocks with conflicting indir.\n",
+		ind_conflict);
+	fprintf(stderr, "%5d zone blocks with conflicting types.\n",
+		type_conflict);
+	fprintf(stderr, "%5d zone blocks with conflicting types and indir.\n",
+		both_conflict);
+	fprintf(stderr, "%5d zone blocks never referenced.\n", unreferenced);
+  }
+  fprintf(stderr, "%5d zone blocks not in use.\n", not_in_use);
+  putc('\n', stderr);
+}
+
+
+static void rd_indirects(dzmap, super, ind, required_class)
+dzmap_t dzmap;
+super_t super;
+int ind;
+class_t required_class;
+{
+  size_t i;
+  int ind_cnt;
+  off_t dz_offset;
+  char buf[BLOCK_SIZE];
+
+  dz_offset = super.firstdatazone;
+  ind_cnt = 0;
+  for (i = 0; i < super.dzmap_size; i++) {
+	if (ztype_class(dzmap[i] & T_MASK) != required_class ||
+	    (dzmap[i] & INDIRECT_MASK) != ind ||
+	    (dzmap[i] & IND_PROCESSED_BIT))
+		continue;
+
+	ind_cnt++;
+	if (read_block(buf, dz_offset + i) != BLOCK_SIZE) {
+		fprintf(stderr, "Can't read %s block", ind_str[ind]);
+		fail("");
+	}
+	proc_ind(dzmap, i, buf, super);
+  }
+  if ((verbose_flag && ind_cnt > 0) || debug_flag)
+	fprintf(stderr, "%5d %s zone blocks.\n", ind_cnt, ind_str[ind]);
+}
+
+
+static void rw_data_zones(dzmap, super)
+dzmap_t dzmap;
+super_t super;
+{
+  char ibuf[BLOCK_SIZE], obuf[BLOCK_SIZE];
+  size_t i;
+  int ztype, ind, last_read;
+  off_t dz_offset;
+
+  dz_offset = super.firstdatazone;
+  for (i = 0; i < super.dzmap_size; i++) {
+	last_read = read_block(ibuf, dz_offset + i);
+	if (last_read != BLOCK_SIZE) break;
+
+	ind = dzmap[i] & INDIRECT_MASK;
+	if (ind == 0) {
+		ztype = dzmap[i] & T_MASK;
+		if (ztype == T_DIR)
+			cw_dir_block(ibuf);
+		else
+			write_block(ibuf);
+	} else {
+		if (super.version == 1)
+			conv2_blkcpy(obuf, ibuf);
+		else
+			conv4_blkcpy(obuf, ibuf);
+		write_block(obuf);
+	}
+	if (verbose_flag && i && i % 1024 == 0) {
+		fprintf(stderr, ".");
+		fflush(stderr);
+	}
+  }
+  if (verbose_flag && i > 1024) putc('\n', stderr);
+
+  if (last_read != BLOCK_SIZE) for (; i < super.dzmap_size; i++)
+		if (ztype_class(dzmap[i] & T_MASK) == In_use_zone)
+			fail("Can't read data zone");
+}
+
+
+static int read_block(buf, offset)
+char *buf;
+blockn_t offset;
+{
+  static blockn_t curr_offset = 0;
+  int bytes;
+
+  if (offset != curr_offset) {
+	if (lseek(0, (off_t) offset * BLOCK_SIZE, 0) == -1)
+		fail("lseek failed on input file");
+	curr_offset = offset;
+  }
+  bytes = read(0, buf, BLOCK_SIZE);
+  if (bytes < 0) fail("read failed on input file");
+
+  curr_offset += bytes;
+
+  return bytes;
+}
+
+
+static void write_block(buf)
+char *buf;
+{
+  if (test_flag) return;
+
+  if (write(1, buf, BLOCK_SIZE) != BLOCK_SIZE)
+	fail("write failed on output file");
+}
+
+
+static int convcpy(dst, src, format)
+char *dst;
+char *src;
+int *format;
+{
+  char *old_src = src;
+  register char tmp;
+  int i;
+
+  for (i = 0; format[i] > 0; i++) {
+	switch (format[i]) {
+	    case 1:	*dst++ = *src++;	break;
+	    case 2:
+		tmp = *src++;
+		*dst++ = *src++;
+		*dst++ = tmp;
+		break;
+	    case 4:
+		tmp = src[0];
+		dst[0] = src[3];
+		dst[3] = tmp;
+		tmp = src[1];
+		dst[1] = src[2];
+		dst[2] = tmp;
+		src += 4;
+		dst += 4;
+		break;
+	    default:
+		fail("wrong format array for convcpy");
+	}
+  }
+  return(src - old_src);
+}
+
+
+static void conv2_blkcpy(dst, src)
+char *dst;
+char *src;
+{
+  int i;
+  register char tmp;
+
+  for (i = 0; i < BLOCK_SIZE; i += 2) {
+	tmp = *src++;
+	*dst++ = *src++;
+	*dst++ = tmp;
+  }
+}
+
+
+static void conv4_blkcpy(dst, src)
+char *dst;
+char *src;
+{
+  int i;
+  register char tmp;
+
+  for (i = 0; i < BLOCK_SIZE; i += 4) {
+	tmp = src[0];
+	dst[0] = src[3];
+	dst[3] = tmp;
+
+	tmp = src[1];
+	dst[1] = src[2];
+	dst[2] = tmp;
+
+	src += 4;
+	dst += 4;
+  }
+}
+
+
+static void conv2cpy(dst, src)
+char *dst;
+char *src;
+{
+  register char tmp;
+  tmp = *src++;
+  *dst++ = *src++;
+  *dst++ = tmp;
+}
+
+
+static int inode_size(version)
+int version;
+{
+  return(version == 1) ? V1_INODE_SIZE : V2_INODE_SIZE;
+}
+
+
+static void init_super(sp, buf)
+super_t *sp;
+char *buf;
+{
+  int magic;
+  long imapblks, zmapblks;
+
+  big_endian_fs = 0;		/* guess the file system is little endian */
+  magic = two_bytes(buf + MAGIC_OFFSET);
+
+  if (magic != V1_MAGIC && magic != V2_MAGIC) {
+	big_endian_fs = 1;
+	magic = two_bytes(buf + MAGIC_OFFSET);
+  }
+  switch (magic) {
+      case V1_MAGIC:	sp->version = 1;	break;
+      case V2_MAGIC:	sp->version = 2;	break;
+      default:	fail("Not a Minix file system");
+}
+
+  if (verbose_flag) fprintf(stderr, "\nVersion = V%d, %s endian.\n",
+		sp->version, big_endian_fs ? "big" : "little");
+
+  sp->ninodes = two_bytes(buf + NINODES_OFFSET);
+  imapblks = two_bytes(buf + IMAP_BLOCKS_OFFSET);
+  sp->imap_blocks = imapblks;
+  zmapblks = two_bytes(buf + ZMAP_BLOCKS_OFFSET);
+  sp->zmap_blocks = zmapblks;
+  sp->firstdatazone = two_bytes(buf + FIRSTDATAZONE_OFFSET);
+  sp->log_zone_size = two_bytes(buf + LOG_ZONE_SIZE_OFFSET);
+
+  if (sp->version == 1)
+	sp->zones = two_bytes(buf + V1_ZONES_OFFSET);
+  else
+	sp->zones = four_bytes(buf + V2_ZONES_OFFSET);
+
+  sp->inodes_per_block = BLOCK_SIZE / inode_size(sp->version);
+
+  if (imapblks < 0 || zmapblks < 0 || sp->ninodes < 1 || sp->zones < 1)
+	fail("Bad superblock");
+
+
+  if (sp->log_zone_size != 0)
+	fail("Can't swap file systems with different zone and block sizes");
+
+  sp->first_imap_block = SUPER_BLOCK_OFF + 1;
+  sp->first_zmap_block = sp->first_imap_block + sp->imap_blocks;
+  sp->first_inode_block = sp->first_zmap_block + sp->zmap_blocks;
+
+  sp->dzmap_size = sp->zones - sp->firstdatazone;
+  if (verbose_flag) {
+	fprintf(stderr, "nzones = %ld, ", sp->zones);
+	fprintf(stderr, "ninodes = %u, ", sp->ninodes);
+	fprintf(stderr, "first data zone = %ld.\n\n", sp->firstdatazone);
+  }
+}
+
+
+static void get_inode(ip, buf, version)
+inode_t *ip;
+char *buf;
+int version;
+{
+  int i;
+  int mode;
+
+  if (version == 1) {
+	mode = two_bytes(buf + INODE1_MODE_OFF);
+	ip->size = four_bytes(buf + INODE1_SIZE_OFF);
+	ip->ind1 = two_bytes(buf + INODE1_IND1_OFF);
+	ip->ind2 = two_bytes(buf + INODE1_IND2_OFF);
+	ip->ind3 = 0;
+	for (i = 0; i < NR_DIRECT_ZONES; i++)
+		ip->direct[i] = two_bytes(buf + INODE1_DIRECT_OFF + 2 * i);
+  } else {
+	mode = two_bytes(buf + INODE2_MODE_OFF);
+	ip->size = four_bytes(buf + INODE2_SIZE_OFF);
+	ip->ind1 = four_bytes(buf + INODE2_IND1_OFF);
+	ip->ind2 = four_bytes(buf + INODE2_IND2_OFF);
+	ip->ind3 = four_bytes(buf + INODE2_IND3_OFF);
+	for (i = 0; i < NR_DIRECT_ZONES; i++)
+		ip->direct[i] = four_bytes(buf + INODE2_DIRECT_OFF + 4 * i);
+  }
+
+  if (mode == 0) {
+	if (ip->size % DIR_ENTRY_SIZE == 0)
+		ip->ztype = T_MAYBE_OLD_DIR;
+	else
+		ip->ztype = T_OLD_NON_DIR;
+	if (was_blk_special(*ip)) ip->size = 0;
+  } else {
+	mode = mode & INODE_MODE_MASK;
+	if (mode == INODE_BLK_SPECIAL_MODE || mode == INODE_CHR_SPECIAL_MODE)
+		ip->size = 0;	/* prevent the use of the block numbers. */
+	ip->ztype = (mode == INODE_DIR_MODE) ? T_DIR : T_NON_DIR;
+  }
+}
+
+
+static int check_inode(inode, super)
+inode_t inode;
+super_t super;
+{
+  int i;
+
+  for (i = 0; i < NR_DIRECT_ZONES; i++)
+	if (!check_blk_number(inode.direct[i], super)) return 0;
+
+  return(check_blk_number(inode.ind1, super) &&
+	check_blk_number(inode.ind2, super) &&
+	check_blk_number(inode.ind3, super));
+}
+
+
+static int check_blk_number(num, super)
+blockn_t num;
+super_t super;
+{
+  if (num == 0 || (num >= super.firstdatazone && num < super.zones))
+	return 1;
+
+  fprintf(stderr, "warning bad block number %ld in inode.\n", num);
+  return 0;
+}
+
+
+static int was_blk_special(inode)
+inode_t inode;
+{
+  int i, result;
+  blockn_t block_size;
+
+  if (inode.size % BLOCK_SIZE || inode.ind1) return 0;
+  block_size = inode.size / BLOCK_SIZE;
+
+  for (i = NR_DIRECT_ZONES - 1; i >= 0; i--)
+	if (inode.direct[i] != 0) break;
+
+  result = (i < 1 && block_size > i + 1);
+
+  if (debug_flag && result) {
+	fprintf(stderr, "old block special file detected (slot = %d).\n", i);
+  }
+  return result;
+}
+
+
+static void cw_inode_block(buf, ninodes, version)
+char *buf;
+inodesn_t ninodes;
+int version;
+{
+  char output_buf[BLOCK_SIZE];
+  char *src, *dst;
+  inodesn_t i;
+  int cnt, free_bytes;
+  int *format;
+
+  src = buf;
+  dst = output_buf;
+
+  format = (version == 1) ? inode1_format : inode2_format;
+  for (i = 0; i < ninodes; i++) {
+	cnt = convcpy(dst, src, format);
+	src += cnt;
+	dst += cnt;
+  }
+
+  assert(cnt == inode_size(version));
+
+  free_bytes = BLOCK_SIZE - (src - buf);
+  assert(free_bytes >= 0);
+  if (verbose_flag && free_bytes > 0) {
+	/* There is a small change that the last free inode has no
+	 * matching bit in the last inode bit map block: e.g. if
+	 * sp->ninodes == 8191. */
+	fprintf(stderr, "%5d bytes (%d inodes) free in last inode block.\n",
+		free_bytes, free_bytes / inode_size(version));
+	memcpy(dst, src, (size_t) free_bytes);
+  }
+  write_block(output_buf);
+}
+
+
+static void proc_ind(dzmap, curr_ind, buf, super)
+dzmap_t dzmap;
+size_t curr_ind;
+char *buf;
+super_t super;
+{
+  int indnum, i, ztype;
+  int word_size;		/* size of zone block number in ind. block in
+			 * bytes */
+  unsigned char dz, tmp_dz;
+  blockn_t blk, ind_blk;
+  int bad_range = 0, hidden_zero = 0, zero_flag = 0, expired = 0;
+  size_t blk_index;
+
+  dz = dzmap[curr_ind];
+  indnum = dz & INDIRECT_MASK;
+  ztype = dz & T_MASK;
+  ind_blk = curr_ind + super.firstdatazone;
+
+  word_size = (super.version == 1) ? 2 : 4;
+  assert(indnum > 0);
+
+  for (i = 0; i < BLOCK_SIZE; i += word_size) {
+	if (word_size == 2)
+		blk = two_bytes(buf + i);
+	else
+		blk = four_bytes(buf + i);
+
+	if (blk == 0)
+		zero_flag = 1;
+	else if (blk < super.firstdatazone || blk >= super.zones)
+		bad_range = 1;
+	else {
+		if (zero_flag) hidden_zero = 1;
+		blk_index = blk - super.firstdatazone;
+		tmp_dz = dzmap[blk_index];
+		if (ztype_class(tmp_dz & T_MASK) == In_use_zone) expired = 1;
+	}
+
+  }
+
+  if (ztype_class(ztype) == In_use_zone) {
+	if (bad_range) {
+		fprintf(stderr, "%s zone block contains ", ind_str[indnum]);
+		fail("illegal value");
+	}
+	if ((ztype == T_DIR || indnum > 1) && hidden_zero) {
+		fprintf(stderr, "WARNING: %s zone block %ld contains ",
+			ind_str[indnum], ind_blk);
+		fprintf(stderr, "unexpected zero block numbers\n");
+	}
+  } else {
+	if (expired) {
+		dzmap[curr_ind] &= ~(INDIRECT_MASK & IND_CONFLICT_BIT);
+		return;
+	}
+
+	/* Not yet implemented. :-( if (bad_range || (indnum > 1 &&
+	 * hidden_zero) || equal_values(buf, super.version ) { } */
+  }
+
+  for (i = 0; i < BLOCK_SIZE; i += word_size) {
+	if (word_size == 2)
+		blk = two_bytes(buf + i);
+	else
+		blk = four_bytes(buf + i);
+
+	if (blk == 0) continue;
+	blk_index = blk - super.firstdatazone;
+	tmp_dz = dzmap[blk_index];
+	if (ztype_class(tmp_dz & T_MASK) == In_use_zone) {	/* trouble */
+		if ((tmp_dz & INDIRECT_MASK) == indnum - 1 &&
+		    (tmp_dz & T_MASK) == ztype)
+			fprintf(stderr, "WARNING: %s zone block %ld used more \
+than once\n", ind_str[indnum - 1], blk);
+		else {
+			fprintf(stderr, "Block %ld used more than ", blk);
+			fail("once with different types");
+		}
+	}
+	dzmap[blk_index] = (dz & ~INDIRECT_MASK) | (indnum - 1);
+  }
+  dzmap[curr_ind] |= IND_PROCESSED_BIT;
+}
+
+
+static void cw_dir_block(buf)
+char *buf;
+{
+  char output_buf[BLOCK_SIZE];
+  int ino, i, old_ino_offset;
+
+  memcpy(output_buf, buf, BLOCK_SIZE);
+
+  for (i = 0; i < BLOCK_SIZE; i += DIR_ENTRY_SIZE) {
+	ino = two_bytes(buf + i);
+	if (ino == 0) {
+		old_ino_offset = i + DIR_ENTRY_SIZE - 2;
+		conv2cpy(output_buf + old_ino_offset, buf + old_ino_offset);
+	} else
+		conv2cpy(output_buf + i, buf + i);
+  }
+  write_block(output_buf);
+}
+
+
+static void dzmap_add_inode(dzmap, inode, super)
+dzmap_t dzmap;
+inode_t inode;
+super_t super;
+{
+  int i;
+
+  if (inode.size == 0 || !check_inode(inode, super)) return;
+
+  for (i = 0; i < NR_DIRECT_ZONES; i++)
+	dz_update(dzmap, inode.direct[i], 0, inode.ztype, super);
+
+  dz_update(dzmap, inode.ind1, 1, inode.ztype, super);
+  dz_update(dzmap, inode.ind2, 2, inode.ztype, super);
+  dz_update(dzmap, inode.ind3, 3, inode.ztype, super);
+}
+
+
+static void dz_update(dzmap, blknum, new_indnum, new_ztype, super)
+dzmap_t dzmap;
+blockn_t blknum;
+int new_indnum;
+int new_ztype;
+super_t super;
+{
+  size_t dznum;
+  int old_indnum;
+  int old_ztype;
+  unsigned char *dz;
+  char new_dz;
+
+
+  if (blknum == 0) return;
+
+  dznum = (size_t) (blknum - super.firstdatazone);
+
+  dz = &dzmap[dznum];
+  old_indnum = *dz & INDIRECT_MASK;
+  old_ztype = *dz & T_MASK;
+
+  new_dz = new_ztype | new_indnum;
+
+  if (ztype_class(new_ztype) > ztype_class(old_ztype)) {
+	*dz = new_dz;
+	return;
+  } else if (ztype_class(new_ztype) < ztype_class(old_ztype))
+	return;
+
+  /* Collision: old and new have the same class */
+
+  if (ztype_class(old_ztype) == In_use_zone) {	/* trouble */
+	if (new_indnum == old_indnum && new_ztype == old_ztype) {
+		fprintf(stderr, "WARNING: file system corrupt, zone block %ld \
+is used more than once.\n", blknum);
+		return;
+	}
+	fprintf(stderr, "ERROR: file system corrupt, zone block %ld is used \
+more than once.\n", blknum);
+	fail("Can't determine its type");
+  }
+  assert(ztype_class(old_ztype) == Old_zone);
+
+
+  if (new_indnum != old_indnum) {
+	*dz |= IND_CONFLICT_BIT;
+	if (new_indnum > old_indnum) {
+		*dz &= ~INDIRECT_MASK;
+		*dz |= new_indnum;
+	}
+  }
+  if (new_ztype == T_MAYBE_OLD_DIR || old_ztype == T_MAYBE_OLD_DIR) {
+	*dz |= TYPE_CONFLICT_BIT;
+	*dz &= ~T_MASK;
+	*dz |= T_MAYBE_OLD_DIR;
+  }
+}
+
+
+static class_t ztype_class(ztype)
+int ztype;
+{
+  class_t class;
+
+  if (ztype == T_MAYBE_OLD_DIR || ztype == T_OLD_NON_DIR)
+	class = Old_zone;
+  else if (ztype == T_DIR || ztype == T_NON_DIR)
+	class = In_use_zone;
+  else
+	class = Unused_zone;
+
+  return class;
+}
+
+
+static void fail(str)
+char *str;
+{
+  fprintf(stderr, "%s\n", str);
+  exit(1);
+}
+
+
+static unsigned int two_bytes(buf)
+char buf[2];
+{
+  unsigned char *ubuf = (unsigned char *) buf;
+
+  if (big_endian_fs)
+	return(ubuf[0] << 8) | ubuf[1];
+  else
+	return(ubuf[1] << 8) | ubuf[0];
+}
+
+
+static long four_bytes(buf)
+char buf[4];
+{
+  unsigned char *ubuf = (unsigned char *) buf;
+  register int r1, r2;
+
+  if (big_endian_fs) {
+	r1 = (ubuf[0] << 8) | ubuf[1];
+	r2 = (ubuf[2] << 8) | ubuf[3];
+  } else {
+	r2 = (ubuf[1] << 8) | ubuf[0];
+	r1 = (ubuf[3] << 8) | ubuf[2];
+  }
+  return((long) r1 << 16) | r2;
+}
+
+
+static void usage(arg0)
+char *arg0;
+{
+  fprintf(stderr, "usage: %s [-v] srcfs [destfs]\n", arg0);
+  exit(2);
+}
Index: /trunk/minix/commands/simple/sync.c
===================================================================
--- /trunk/minix/commands/simple/sync.c	(revision 9)
+++ /trunk/minix/commands/simple/sync.c	(revision 9)
@@ -0,0 +1,14 @@
+/* sync - flush the file system buffers.  Author: Andy Tanenbaum */
+
+#include <sys/types.h>
+#include <unistd.h>
+
+_PROTOTYPE(int main, (void));
+
+int main()
+{
+/* First prize in shortest useful program contest. */
+/* Highest comment/code ratio */
+  sync();
+  return(0);
+}
Index: /trunk/minix/commands/simple/synctree.c
===================================================================
--- /trunk/minix/commands/simple/synctree.c	(revision 9)
+++ /trunk/minix/commands/simple/synctree.c	(revision 9)
@@ -0,0 +1,1481 @@
+/*	synctree 4.16 - Synchronise file tree.		Author: Kees J. Bot
+ *								5 Apr 1989
+ * SYNOPSYS
+ *	synctree [-iuf] [[user1@machine1:]dir1 [[user2@]machine2:]dir2
+ *
+ * Dir2 will then be synchronized to dir1 with respect to the flags.
+ * The flags mean:
+ *	-i  Be interactive on files other than directories too.
+ *	-u  Only install files that are newer, i.e. that need an update.
+ *	-f  Force.  Don't ask for confirmation, all answers are 'yes'.
+ *
+ * Hitting return lets synctree use its proposed answer.  Hitting CTRL-D is
+ * like typing return to all questions that follow.
+ *
+ * If either of the directories to be synchronized contains the file ".backup"
+ * then it is a backup directory.  The file ".backup" in this directory is
+ * an array of mode information indexed on inode number.
+ *
+ * 89/04/05, Kees J. Bot - Birth of tree synchronizing program.
+ * 92/02/02		 - General overhaul, rcp(1) like syntax.
+ */
+
+#define nil 0
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <utime.h>
+#include <string.h>
+#include <signal.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/wait.h>
+
+#if _MINIX
+#include "limits.h"
+#include "minix/config.h"
+
+/*#define BLOCK_SIZE	1024*/
+#define LITTLE_ENDIAN	(CHIP == INTEL)
+#define USE_SHADOWING	(CHIP == M68000)
+#else
+#define LITTLE_ENDIAN	0
+#define USE_SHADOWING	0
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX	1024
+#endif
+
+#ifndef S_ISLNK
+/* There were no symlinks in medieval times. */
+#define S_ISLNK(mode)			(0)
+#define lstat				stat
+#define symlink(path1, path2)		(errno= ENOSYS, -1)
+#define readlink(path, buf, len)	(errno= ENOSYS, -1)
+#endif
+
+#define NUMBYTES     4	/* Any number fits in this many bytes. */
+#define CHUNK     4096	/* Transfer files in this size chunks. */
+
+static int install= 0;	/* Install files, do not delete, update if newer. */
+static int interact= 0;	/* Ask permission to install too. */
+static int force= 0;	/* Force trees to be completely equal. */
+static int backup= 0;	/* This tree is for backup. */
+
+static char SYNCNAME[]	= "synctree";
+static char SLAVENAME[]	= "==SLAVE==";
+static char MASTERNAME[]= "==MASTER==";
+
+
+static char BACKUP[] = ".backup";	/* Backup filemodes. */
+static int filemodes;			/* Filemodes fildes. */
+
+static int chan[2]= { 0, 1 };	/* In and output channel to opposite side. */
+
+#define BUCKSIZE (1+NUMBYTES+CHUNK)
+static char bucket[BUCKSIZE];	/* Put a lot of things here before sending. */
+static char *buckp= bucket;	/* Fill pointer. */
+static int buckn= 0;		/* # bytes in bucket. */
+
+enum orders {	/* What back breaking labour should the slave perform? */
+	ENTER= 128,	/* Make ready to process contents of directory. */
+	ADVANCE,	/* Determine next pathname and report it back. */
+	CAT,		/* Send contents of file. */
+	MORE,		/* Send more file contents. */
+	CANCEL,		/* Current pathname is not installed, remove as link. */
+	DIE,		/* Die with exit(0); */
+	DIE_BAD,	/* exit(1); */
+	POSITIVE,	/* Ask a yes/no question expecting yes. */
+	NEGATIVE,	/* Same expecting no. */
+	PASS_YES,	/* Pass this to the master will you. */
+	PASS_NO		/* Same here. */
+};
+
+#ifdef DEBUG
+char *ORDERS[]= {
+	"ENTER", "ADVANCE", "CAT", "MORE", "CANCEL", "DIE", "DIE_BAD",
+	"POSITIVE", "NEGATIVE", "PASS_YES", "PASS_NO"
+};
+#endif
+
+enum answers {
+	PATH= 128,	/* Report pathname, and stat(2) info. */
+	LINK,		/* Report linkname, pathname, and stat(2) info. */
+	DATA,		/* Contents of file follow. */
+	NODATA,		/* Can't read file. */
+	DONE,		/* Nothing more to advance to. */
+	SYMLINK,	/* Report symlinkname, pathname, and stat(2) info. */
+	YES, NO		/* Result of an ASK. */
+};
+
+#ifdef DEBUG
+char *ANSWERS[]= {
+	"PATH", "LINK", "DATA", "NODATA", "DONE", "SYMLINK", "YES", "NO"
+};
+
+#define DPRINTF(format, arg)	fprintf(stderr, format, arg0, arg)
+#else
+#define DPRINTF(format, arg)
+#endif
+
+struct mode {
+	unsigned short	md_mode;
+	unsigned short	md_uid;
+	unsigned short	md_gid;
+	unsigned short	md_rdev;
+	unsigned short	md_devsiz;
+};
+
+static char *arg0;	/* basename(argv[0]) */
+static int ex= 0;	/* exit status. */
+
+static void because()
+{
+	fprintf(stderr, ": %s\n", strerror(errno));
+	ex= 1;
+}
+
+static void perr(label) char *label;
+{
+	fprintf(stderr, "%s: %s: %s\n", arg0, label, strerror(errno));
+	ex= 1;
+}
+
+static void perrx(label) char *label;
+{
+	perr(label);
+	exit(1);
+}
+
+#if S_HIDDEN
+/* Support for per achitecture hidden files. */
+static int transparent= 0;
+
+static void isvisible(name) char *name;
+{
+	char *p= name + strlen(name);
+
+	while (p > name && *--p == '/') {}
+
+	if (p > name && *p == '@' && p[-1] != '/') transparent= 1;
+}
+#else
+#define transparent	0
+#define isvisible(name)	((void) 0)
+#endif
+
+static void isbackup(slave) int slave;
+{
+	if ((filemodes= open(BACKUP, slave ? O_RDONLY : O_RDWR)) >= 0)
+		backup= 1;
+	else {
+		if (errno != ENOENT) perrx(BACKUP);
+	}
+}
+
+static char path[PATH_MAX+1];	/* Holds pathname of file being worked on. */
+static char lnkpth[PATH_MAX+1];	/* (Sym)link to path. */
+static char *linkpath;		/* What path is, or should be linked to. */
+static struct stat st;		/* Corresponding stat(2) info. */
+static char Spath[PATH_MAX+1];	/* Slave is looking at this. */
+static char Slnkpth[PATH_MAX+1];/* (Sym)link to Spath. */
+static char *Slinkpath=nil;	/* Either nil or Slnkpth. */
+static struct stat Sst;		/* Slave's stat(2). */
+
+static char *addpath(p, n) char *p, *n;
+/* Add a name to the path, return pointer to end. */
+{
+	if (p - path + 1 + strlen(n) > PATH_MAX) {
+		*p= 0;
+		fprintf(stderr, "%s: %s/%s is too long.\n", arg0, path, n);
+		fprintf(stderr, "%s: Unable to continue.\n", arg0);
+		exit(1);
+	}
+	if (p == path+1 && path[0] == '.') p= path;
+
+	if (p > path) *p++ = '/';
+
+	while (*n != 0) *p++ = *n++;
+	*p= 0;
+	return p;
+}
+
+struct entry {	/* A directory entry. */
+	struct entry	*next;	/* Next entry in same directory */
+	struct entry	*dir;	/* It is part of this directory */
+	struct entry	*con;	/* If a dir, its contents */
+	char		*name;	/* Name of this dir entry */
+};
+
+static struct entry *E= nil;		/* File being processed. */
+
+static void setpath(e) struct entry *e;
+/* Set path leading to e. */
+{
+	static char *pend;
+
+	if (e == nil)
+		pend= path;
+	else {
+		setpath(e->dir);
+		pend= addpath(pend, e->name);
+	}
+}
+
+static void sort(ae) struct entry **ae;
+/* This is either a stable mergesort, or thermal noise, I'm no longer sure.
+ * It must be called like this: if (L!=nil && L->next!=nil) sort(&L);
+ */
+{
+	/* static */ struct entry *e1, **mid;  /* Need not be local */
+	struct entry *e2;
+
+	e1= *(mid= &(*ae)->next);
+	do {
+		if ((e1= e1->next) == nil) break;
+		mid= &(*mid)->next;
+	} while ((e1= e1->next) != nil);
+
+	e2= *mid;
+	*mid= nil;
+
+	if ((*ae)->next != nil) sort(ae);
+	if (e2->next != nil) sort(&e2);
+
+	e1= *ae;
+	for (;;) {
+		if (strcmp(e1->name, e2->name)<=0) {
+			if ((e1= *(ae= &e1->next)) == nil) {
+				*ae= e2;
+				break;
+			}
+		} else {
+			*ae= e2;
+			e2= *(ae= &e2->next);
+			*ae= e1;
+			if (e2 == nil) break;
+		}
+	}
+}
+
+static void enter()
+/* Collect directory entries of E. */
+{
+	struct entry **last= &E->con, *new;
+	struct dirent *e;
+	DIR *d;
+
+	if ((d= opendir(path)) == nil) {
+		fprintf(stderr, "%s: Can't read dir %s\n", arg0, path);
+		return;
+	}
+
+	while ((e= readdir(d)) != nil) {
+		if (e->d_name[0] == '.' && (e->d_name[1] == 0
+			|| (e->d_name[1] == '.' && e->d_name[2] == 0)
+		)) continue;
+
+		new= (struct entry *) malloc(sizeof(*new));
+
+		new->next= nil;
+		new->dir= E;
+		new->con= nil;
+		new->name= (char *) malloc(strlen(e->d_name) + 1);
+		strcpy(new->name, e->d_name);
+		*last= new;
+		last= &new->next;
+	}
+	closedir(d);
+	if (E->con != nil && E->con->next != nil) sort(&E->con);
+}
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+
+static char *link_islink(struct stat *stp, const char *file)
+{
+    /* Tell if a file, which stat(2) information in '*stp', has been seen
+     * earlier by this function under a different name.  If not return a
+     * null pointer with errno set to ENOENT, otherwise return the name of
+     * the link.  Return a null pointer with an error code in errno for any
+     * error, using E2BIG for a too long file name.
+     *
+     * Use link_islink(nil, nil) to reset all bookkeeping.
+     *
+     * Call for a file twice to delete it from the store.
+     */
+
+    typedef struct link {	/* In-memory link store. */
+	struct link	*next;		/* Hash chain on inode number. */
+	ino_t		ino;		/* File's inode number. */
+	off_t		off;		/* Offset to more info in temp file. */
+    } link_t;
+    typedef struct dlink {	/* On-disk link store. */
+	dev_t		dev;		/* Device number. */
+	char		file[PATH_MAX];	/* Name of earlier seen link. */
+    } dlink_t;
+    static link_t *links[256];		/* Hash list of known links. */
+    static int tfd= -1;			/* Temp file for file name storage. */
+    static dlink_t dlink;
+    link_t *lp, **plp;
+    size_t len;
+    off_t off;
+
+    if (file == nil) {
+	/* Reset everything. */
+	for (plp= links; plp < arraylimit(links); plp++) {
+	    while ((lp= *plp) != nil) {
+		*plp= lp->next;
+		free(lp);
+	    }
+	}
+	if (tfd != -1) close(tfd);
+	tfd= -1;
+	return nil;
+    }
+
+    /* The file must be a non-directory with more than one link. */
+    if (S_ISDIR(stp->st_mode) || stp->st_nlink <= 1) {
+	errno= ENOENT;
+	return nil;
+    }
+
+    plp= &links[stp->st_ino % arraysize(links)];
+
+    while ((lp= *plp) != nil) {
+	if (lp->ino == stp->st_ino) {
+	    /* May have seen this link before.  Get it and check. */
+	    if (lseek(tfd, lp->off, SEEK_SET) == -1) return nil;
+	    if (read(tfd, &dlink, sizeof(dlink)) < 0) return nil;
+
+	    /* Only need to check the device number. */
+	    if (dlink.dev == stp->st_dev) {
+		if (strcmp(file, dlink.file) == 0) {
+		    /* Called twice.  Forget about this link. */
+		    *plp= lp->next;
+		    free(lp);
+		    errno= ENOENT;
+		    return nil;
+		}
+
+		/* Return the name of the earlier link. */
+		return dlink.file;
+	    }
+	}
+	plp= &lp->next;
+    }
+
+    /* First time I see this link.  Add it to the store. */
+    if (tfd == -1) {
+	for (;;) {
+	    char *tmp;
+
+	    tmp= tmpnam(nil);
+	    tfd= open(tmp, O_RDWR|O_CREAT|O_EXCL, 0600);
+	    if (tfd < 0) {
+		if (errno != EEXIST) return nil;
+	    } else {
+		(void) unlink(tmp);
+		break;
+	    }
+	}
+    }
+    if ((len= strlen(file)) >= PATH_MAX) {
+	errno= E2BIG;
+	return nil;
+    }
+
+    dlink.dev= stp->st_dev;
+    strcpy(dlink.file, file);
+    len += offsetof(dlink_t, file) + 1;
+    if ((off= lseek(tfd, 0, SEEK_END)) == -1) return nil;
+    if (write(tfd, &dlink, len) != len) return nil;
+
+    if ((lp= malloc(sizeof(*lp))) == nil) return nil;
+    lp->next= nil;
+    lp->ino= stp->st_ino;
+    lp->off= off;
+    *plp= lp;
+    errno= ENOENT;
+    return nil;
+}
+
+#define cancellink()	((void) islink())
+
+static char *islink()
+/* Returns the name of the file path is linked to.  If no such link can be
+ * found, then path is added to the list and nil is returned.  If all the
+ * links of a file have been seen, then it is removed from the list.
+ * Directories are not seen as linkable.
+ */
+{
+	char *name;
+
+	name= link_islink(&st, path);
+	if (name == nil && errno != ENOENT) perrx(path);
+	return name;
+}
+
+static void setstat(ino, stp) ino_t ino; struct stat *stp;
+/* Set backup status info, we know that backup is true. */
+{
+	struct mode md;
+
+	md.md_mode = stp->st_mode;
+	md.md_uid = stp->st_uid;
+	md.md_gid = stp->st_gid;
+	md.md_rdev = stp->st_rdev;
+	md.md_devsiz = stp->st_size / 1024;
+
+	if (lseek(filemodes, (off_t) sizeof(md) * (off_t) ino, 0) == -1
+		|| write(filemodes, (char *) &md, sizeof(md)) != sizeof(md)
+	) perrx(BACKUP);
+}
+
+static int getstat(name, stp) char *name; struct stat *stp;
+/* Get status information of file name, skipping some files.  Backup info
+ * is inserted as needed.
+ */
+{
+	errno= 0;
+
+	if (strcmp(name, BACKUP) == 0) return -1;
+
+	if (lstat(name, stp) < 0) return -1;
+
+	if (stp->st_mode == S_IFREG && stp->st_mtime == 0) return -1;
+
+	if (backup) {
+		struct mode md;
+
+		if (lseek(filemodes,
+			(off_t) sizeof(md) * (off_t) stp->st_ino, 0) == -1
+		    || read(filemodes, (char *) &md, sizeof(md)) != sizeof(md)
+		    || md.md_mode == 0
+		) {
+			errno= 0;
+			setstat(stp->st_ino, stp);
+		} else {
+			stp->st_mode = md.md_mode;
+			stp->st_uid = md.md_uid;
+			stp->st_gid = md.md_gid;
+			stp->st_rdev = md.md_rdev;
+			if (S_ISBLK(stp->st_mode))
+				stp->st_size= (off_t) md.md_devsiz * 1024;
+		}
+	}
+	return 0;
+}
+
+static int advance()
+/* Determine next pathname, return true on success. */
+{
+	for (;;) {
+		if (E==nil) {	/* First call, enter root dir. */
+			E= (struct entry *) malloc(sizeof(*E));
+			E->dir= nil;
+			E->con= nil;
+			E->next= nil;
+			E->name= (char *) malloc(3);
+			strcpy(E->name, transparent ? ".@" : ".");
+		} else
+		if (E->con != nil)	/* Dir's files must be processed. */
+			E= E->con;
+		else {
+			for (;;) {
+				/* Remove E from it's parents list, then
+				 * try next entry, if none, go to parent dir.
+				 */
+				struct entry *junk= E, *parent= E->dir;
+
+				if (parent != nil) parent->con= E->next;
+				E= E->next;
+				free(junk->name);
+				free(junk);
+
+				if (E != nil) break;
+
+				if ((E= parent) == nil) return 0;
+			}
+		}
+		setpath(E);
+		if (getstat(path, &st) == 0) {
+			if (S_ISLNK(st.st_mode)) {
+				int n;
+
+				if ((n= readlink(path, lnkpth, PATH_MAX)) >= 0)
+				{
+					lnkpth[n]= 0;
+					break;
+				}
+			} else {
+				break;
+			}
+		}
+		if (errno != 0 && errno != ENOENT) perr(path);
+	}
+
+	linkpath= islink();
+	DPRINTF("%s: path = %s\n", path);
+	return 1;
+}
+
+static enum orders request()
+/* Slave reads command sent by master. */
+{
+	static char buf[64], *bp;
+	static int n= 0;
+	int req;
+
+	for (;;) {
+		if (n == 0) {
+			if ((n= read(chan[0], buf, (int) sizeof(buf))) <= 0) {
+				if (n < 0) perrx("request()");
+				/* Master died, try to report it then follow. */
+				fprintf(stderr,
+					"%s: Master died prematurely.\n", arg0);
+				exit(1);
+			}
+			bp= buf;
+		}
+		req= *bp++ & 0xFF;
+		n--;
+		if (req >= (int) ENTER) break;
+
+		/* Master using slave to print to stdout: */
+		putchar(req);
+	}
+	DPRINTF("%s: request() == %s\n", ORDERS[req - (int) ENTER]);
+
+	return (enum orders) req;
+}
+
+static void report()
+{
+	int r;
+
+	DPRINTF("%s: reporting now!\n", 0);
+
+	buckp= bucket;
+
+	while (buckn > 0) {
+		r = buckn;
+		if (r > (512 << sizeof(char*))) r= (512 << sizeof(char*));
+
+		if ((r= write(chan[1], buckp, r)) < 0) perrx("report()");
+
+		buckp += r;
+		buckn -= r;
+	}
+	buckp= bucket;
+	buckn= 0;
+}
+
+static void inform(a) enum answers a;
+/* Slave replies to master. */
+{
+	DPRINTF("%s: inform(%s)\n", ANSWERS[(int) a - (int) PATH]);
+
+	*buckp++ = (int) a;
+	buckn++;
+}
+
+#define wwrite(buf, n)	(memcpy(buckp, (buf), (n)), buckp+= (n), buckn+= (n))
+
+static void sendnum(n) long n;
+/* Send number from least to most significant byte. */
+{
+#if LITTLE_ENDIAN
+	wwrite((char *) &n, sizeof(n));
+#else
+	char buf[NUMBYTES];
+
+	buf[0]= (char) (n >>  0);
+	buf[1]= (char) (n >>  8);
+	buf[2]= (char) (n >> 16);
+	buf[3]= (char) (n >> 24);
+	wwrite(buf, sizeof(buf));
+#endif
+}
+
+static void send(buf, n) char *buf; int n;
+/* Slave sends size and contents of buf. */
+{
+	sendnum((long) n);
+	if (n > 0) wwrite(buf, (size_t) n);
+}
+
+static void sendstat(stp) struct stat *stp;
+{
+	sendnum((long) stp->st_mode);
+	sendnum((long) stp->st_uid);
+	sendnum((long) stp->st_gid);
+	sendnum((long) stp->st_rdev);
+	sendnum((long) stp->st_size);
+	sendnum((long) stp->st_mtime);
+}
+
+static int ask();
+
+static void slave()
+/* Carry out orders from the master, such as transmitting path names.
+ * Note that the slave uses path, not Spath, the master uses Spath.
+ */
+{
+	int f, n;
+	char buf[CHUNK];
+	enum { run, done, die } state= run;
+
+	do {
+		switch (request()) {
+		case ENTER:
+			enter();
+			break;
+		case ADVANCE:
+			if (!advance() || state == done) {
+				inform(DONE);
+				state= done;
+			} else {
+				if (linkpath!=nil) {
+					inform(LINK);
+					send(linkpath, strlen(linkpath) + 1);
+				} else
+				if (S_ISLNK(st.st_mode)) {
+					inform(SYMLINK);
+					send(lnkpth, strlen(lnkpth) + 1);
+				} else {
+					inform(PATH);
+				}
+				send(path, strlen(path) + 1);
+				sendstat(&st);
+			}
+			break;
+		case CAT:
+			if ((f= open(path, O_RDONLY))<0) {
+				fprintf(stderr, "%s: Can't open %s",
+					arg0, path);
+				because();
+				inform(NODATA);
+				break;
+			}
+			inform(DATA);
+			do {
+				n= read(f, buf, sizeof(buf));
+				if (n < 0) perr(path);
+				send(buf, n);
+				if (n > 0) report();
+			} while (n > 0);
+			close(f);
+			break;
+		case CANCEL:
+			cancellink();
+			break;
+		case DIE_BAD:
+			ex= 1;
+			/*FALL THROUGH*/
+		case DIE:
+			state= die;
+			break;
+		case POSITIVE:
+			inform(ask('y') ? YES : NO);
+			break;
+		case NEGATIVE:
+			inform(ask('n') ? YES : NO);
+			break;
+		case PASS_YES:
+			inform(YES);
+			break;
+		case PASS_NO:
+			inform(NO);
+			break;
+		default:
+			fprintf(stderr, "%s: strange request\n", arg0);
+			exit(1);
+		}
+		report();
+	} while (state != die);
+}
+
+static int execute(argv) char **argv;
+/* Execute a command and return its success or failure. */
+{
+	int pid, r, status;
+
+	if ((pid= fork())<0) {
+		perr("fork()");
+		return 0;
+	}
+	if (pid == 0) {
+		execvp(argv[0], argv);
+		perrx(argv[0]);
+	}
+	while ((r= wait(&status)) != pid) {
+		if (r < 0) {
+			perr(argv[0]);
+			return 0;
+		}
+	}
+	return status == 0;
+}
+
+static int removedir(dir) char *dir;
+/* Remove a directory and its contents. */
+{
+	static char *argv[] = { "rm", "-r", nil, nil };
+
+	printf("(rm -r %s)\n", dir);
+
+	argv[2]= dir;
+	return execute(argv);
+}
+
+static void order(o) enum orders o;
+/* Master tells slave what to do. */
+{
+	char c= (char) o;
+
+	DPRINTF("%s: order(%s)\n", ORDERS[o - (int) ENTER]);
+
+	if (write(chan[1], &c, 1) != 1) perrx("order()");
+}
+
+static void rread(buf, n) char *buf; int n;
+/* Master gets buf of size n from slave, doing multiple reads if needed. */
+{
+	int r;
+
+	while (n > 0) {
+		if (buckn == 0) {
+			switch (buckn= read(chan[0], bucket, BUCKSIZE)) {
+			case -1:
+				perrx("reply channel from slave");
+			case  0:
+				fprintf(stderr,
+					"%s: slave died prematurely.\n",
+					arg0);
+				exit(1);
+			}
+			buckp= bucket;
+		}
+		r= n < buckn ? n : buckn;
+		memcpy(buf, buckp, r);
+		buckp+= r;
+		buckn-= r;
+		buf+= r;
+		n-= r;
+	}
+}
+
+static enum answers answer()
+/* Master reads slave's reply. */
+{
+	char c;
+	int a;
+
+	rread(&c, 1);
+	a= c & 0xFF;
+
+	DPRINTF("%s: answer() == %s\n", ANSWERS[a - (int) PATH]);
+
+	return (enum answers) a;
+}
+
+static long recnum()
+/* Read number as pack of bytes from least to most significant.  The data
+ * is on the wire in little-endian format.  (Mostly run on PC's).
+ */
+{
+#if LITTLE_ENDIAN
+	long n;
+
+	rread((char *) &n, (int) sizeof(n));
+	return n;
+#else
+	unsigned char buf[NUMBYTES];
+
+	rread(buf, sizeof(buf));
+	return	buf[0]
+		| ((unsigned) buf[1] << 8)
+		| ((unsigned long) buf[2] << 16)
+		| ((unsigned long) buf[3] << 24);
+#endif
+}
+
+static int receive(buf, max) char *buf; int max;
+/* Master get's data from slave, by first reading size, then data. */
+{
+	int n;
+
+	n= recnum();
+	if (n > max) {
+		fprintf(stderr, "%s: panic: Can't read %d bytes\n", arg0, n);
+		exit(1);
+	}
+	if (n > 0) rread(buf, n);
+	return n;
+}
+
+static void recstat(stp) struct stat *stp;
+{
+	stp->st_mode= recnum();
+	stp->st_uid= recnum();
+	stp->st_gid= recnum();
+	stp->st_rdev= recnum();
+	stp->st_size= recnum();
+	stp->st_mtime= recnum();
+}
+
+static int key()
+{
+	int c;
+	static int tty= -1;
+
+	if (tty < 0) tty= isatty(0);
+
+	if (feof(stdin) || (c= getchar()) == EOF) {
+		c= '\n';
+		if (tty) putchar('\n');
+	}
+
+	if (!tty) putchar(c);
+
+	return c;
+}
+
+static int ask(def) int def;
+/* Ask for a yes or no, anything else means choose def. */
+{
+	int y, c;
+
+	if (chan[0] == 0) {
+		/* I'm running remote, tell the slave to ask. */
+		fflush(stdout);
+		order(def == 'y' ? POSITIVE : NEGATIVE);
+		return answer() == YES;
+	}
+
+	printf("? (%c) ", def);
+	fflush(stdout);
+
+	do c= key(); while (c == ' ' || c == '\t');
+
+	y= c;
+
+	while (c != '\n') c= key();
+
+	if (y != 'y' && y != 'Y' && y != 'n' && y != 'N') y= def;
+
+	return y == 'y' || y == 'Y';
+}
+
+static void setmodes(silent) int silent;
+{
+	struct stat st;
+	int change= 0;
+	struct utimbuf tms;
+
+	errno= 0;
+	getstat(Spath, &st);
+	if (backup && silent) {
+		setstat(st.st_ino, &Sst);
+		getstat(Spath, &st);
+	}
+
+	if (S_ISLNK(st.st_mode)) return;
+
+	if (errno == 0 && st.st_mode != Sst.st_mode) {
+		if (!backup) chmod(Spath, Sst.st_mode & 07777);
+		change= 1;
+	}
+	if (errno == 0
+		&& (st.st_uid != Sst.st_uid || st.st_gid != Sst.st_gid)
+		&& (backup || geteuid() == 0)
+	) {
+		errno= 0;
+		if (!backup) chown(Spath, Sst.st_uid, Sst.st_gid);
+		change= 1;
+	}
+
+	if (backup && !silent) setstat(st.st_ino, &Sst);
+
+	if (errno == 0 && S_ISREG(Sst.st_mode) && st.st_mtime != Sst.st_mtime) {
+		time(&tms.actime);
+		tms.modtime= Sst.st_mtime;
+		errno= 0;
+		utime(Spath, &tms);
+		change= 1;
+	}
+	if (errno != 0) {
+		fprintf(stderr, "%s: Can't set modes of %s", arg0, Spath);
+		because();
+	} else
+	if (change && !silent) {
+		printf("Mode changed of %s\n", Spath);
+	}
+}
+
+static void makeold()
+{
+	static struct utimbuf tms= { 0, 0 };
+
+	if (utime(Spath, &tms) < 0) {
+		if (errno != ENOENT) {
+			fprintf(stderr,
+				"%s: can't make %s look old", arg0, Spath);
+			because();
+		}
+	} else {
+		fprintf(stderr, "%s: made %s look old.\n", arg0, Spath);
+	}
+}
+
+static int busy= 0;
+
+static void bail_out(sig) int sig;
+{
+	signal(sig, SIG_IGN);
+
+	fprintf(stderr, "%s: Exiting after signal %d\n", arg0, sig);
+
+	if (busy) {
+		fprintf(stderr, "%s: was installing %s\n", arg0, Spath);
+		makeold();
+	}
+	order(DIE_BAD);
+
+	exit(sig);
+}
+
+static int makenode(name, mode, addr, size)
+	char *name; int mode; dev_t addr; off_t size;
+{
+	int r;
+
+	if (!backup) {
+		r= mknod(name, mode, addr);
+	} else {
+		if ((r= creat(name, 0644)) >= 0) close(r);
+	}
+	return r;
+}
+
+static void add(update) int update;
+/* Add Spath to the filesystem. */
+{
+	int f, n;
+	char buf[CHUNK];
+	int forced_update= force && update;
+
+	if (Slinkpath != nil && !S_ISLNK(Sst.st_mode)) {
+		if (interact && !update) {
+			printf("Link %s to %s", Spath, Slinkpath);
+			if (!ask('n')) return;
+		}
+		if (link(Slinkpath, Spath) >= 0) {
+			printf("Linked %s to %s\n", Spath, Slinkpath);
+			return;
+		} else {
+			fprintf(stderr,
+				"%s: Can't link %s to %s",
+				arg0, Slinkpath, Spath);
+			because();
+			/* Try to install instead. */
+		}
+	}
+	switch (Sst.st_mode & S_IFMT) {
+	case S_IFDIR:
+		if (!force) {
+			printf("Add dir %s", Spath);
+			if (!ask('n')) return;
+		}
+		if (mkdir(Spath, backup ? 0755 : Sst.st_mode) < 0) {
+			perr(Spath);
+			return;
+		}
+		printf("Directory %s created.\n", Spath);
+		order(ENTER);
+		break;
+	case S_IFBLK:
+	case S_IFCHR:
+	case S_IFIFO:
+		if (interact && !update) {
+			printf("Create special file %s", Spath);
+			if (!ask('n')) { order(CANCEL); return; }
+		}
+		if (makenode(Spath, Sst.st_mode, Sst.st_rdev, Sst.st_size)<0) {
+			fprintf(stderr,
+				"%s: Can't create special file %s",
+				arg0, Spath);
+			because();
+			return;
+		}
+		printf("Special file %s created\n", Spath);
+		break;
+#ifdef S_IFLNK
+	case S_IFLNK:
+		if (interact && !update) {
+			printf("Install %s -> %s", Spath, Slnkpth);
+			if (!ask('n')) { order(CANCEL); return; }
+		}
+		if (symlink(Slnkpth, Spath) < 0) {
+			fprintf(stderr, "%s: Can't create symlink %s",
+				arg0, Spath);
+			because();
+			return;
+		}
+		printf("%s %s -> %s\n",
+			forced_update ? "Updated:  " : "Installed:",
+			Spath, Slnkpth);
+		break;
+#endif
+	case S_IFREG:
+		if (interact && !update) {
+			printf("Install %s", Spath);
+			if (!ask('n')) { order(CANCEL); return; }
+		}
+		order(CAT);
+		if (answer() != DATA) return;
+
+		busy= 1;
+		if ((f= creat(Spath, backup ? 0644 : Sst.st_mode&07777)) < 0) {
+			busy= 0;
+			fprintf(stderr, "%s: Can't create %s", arg0, Spath);
+			because();
+		}
+
+		while ((n= receive(buf, sizeof(buf)))>0) {
+			if (f >= 0 && write(f, buf, n) != n) {
+				fprintf(stderr, "%s: Write error on %s",
+					arg0, Spath);
+				because();
+				close(f); f= -1;
+			}
+		}
+		if (n < 0) {
+			fprintf(stderr, "%s: Slave read err on %s\n",
+				arg0, Spath);
+		}
+		if (f >= 0) close(f);
+		if (n < 0 || f < 0) { makeold(); busy= 0; return; }
+		busy= 0;
+		printf("%s %s\n",
+			forced_update ?
+				Sst.st_mtime < st.st_mtime ? "Restored: " :
+					"Updated:  " :
+				"Installed:",
+			Spath
+		);
+		break;
+	default:
+		fprintf(stderr,
+			"%s: Won't add file with strange mode %05o: %s\n",
+			arg0, Sst.st_mode, Spath);
+		order(CANCEL);
+		return;
+	}
+	setmodes(1);
+}
+
+static int delete(update) int update;
+/* Delete path. */
+{
+	int forced_update= force && update;
+
+	if (S_ISDIR(st.st_mode)) {
+		if (install) return 0;
+		if (!force) {
+			printf("Delete dir %s", path);
+			if (!ask('n')) return 0;
+		}
+		if (!removedir(path)) { ex= 1; return 0; }
+		if (!forced_update) printf("Directory %s deleted.\n", path);
+		return 1;
+	}
+
+	if (install && !update) return 0;
+
+	if (!force) {
+		printf("Delete %s", path);
+		if (!ask((interact && !update) ? 'n' : 'y')) return 0;
+	}
+
+	if (unlink(path)<0) {
+		fprintf(stderr, "Can't delete %s", path);
+		because();
+		return 0;
+	}
+	cancellink();
+	if (!forced_update) printf("Deleted:   %s\n", path);
+	return 1;
+}
+
+static int different()
+/* Return true iff path and Spath are different. */
+{
+	if (! ( (linkpath == nil && Slinkpath == nil)
+		|| (linkpath != nil && Slinkpath != nil
+			&& strcmp(linkpath, Slinkpath) == 0)
+	)) {
+		linkpath= Slinkpath;
+		return 1;
+	}
+
+	if ((st.st_mode & S_IFMT) != (Sst.st_mode & S_IFMT)) return 1;
+
+	switch (st.st_mode & S_IFMT) {
+	case S_IFDIR:
+		return 0;
+	case S_IFBLK:
+	case S_IFCHR:
+		return st.st_rdev != Sst.st_rdev;
+	case S_IFREG:
+		if (install) return Sst.st_mtime > st.st_mtime;
+		return st.st_size != Sst.st_size
+			|| st.st_mtime != Sst.st_mtime;
+	case S_IFIFO:	return 0;
+#ifdef S_IFLNK
+	case S_IFLNK:	return strcmp(lnkpth, Slnkpth) != 0;
+#endif
+	default:	return 1;
+	}
+}
+
+static void compare()
+/* See if path and Spath are same. */
+{
+	if (different()) {
+		if (!force) {
+			printf("%sing %s (delete + add)\n",
+				Sst.st_mtime < st.st_mtime ? "Restor" : "Updat",
+				path);
+		}
+		if (delete(1)) add(1);
+	} else {
+		if (!install) setmodes(0);
+
+		if (S_ISDIR(st.st_mode)) {
+			order(ENTER);
+			enter();
+		}
+	}
+}
+
+static int done= 0, Sdone= 0;
+
+static enum action { ADD, COMPARE, DELETE } action()
+/* Look at path's of master and slave, compare them alphabetically to see
+ * who is ahead of who, then tell what is to be done.
+ */
+{
+	int c;
+	char *Sp, *p;
+
+	if (done) return ADD;		/* Slave still has names. */
+	if (Sdone) return DELETE;	/* Master has too many names. */
+
+	/* Compare paths.  Let "a/a" come before "a.a". */
+	Sp= Spath;
+	p= path;
+	while (*Sp == *p && *Sp != 0) { Sp++; p++; }
+	if (*Sp == '/') return ADD;
+	if (*p == '/') return DELETE;
+	return (c= strcmp(Sp, p)) == 0 ? COMPARE : c < 0 ? ADD : DELETE;
+}
+
+static void master()
+/* Synchronise file tree to that of its slave. */
+{
+	enum action a= COMPARE;	/* Trick first advances. */
+
+	umask(backup ? 0022 : 0000);
+
+	signal(SIGPIPE, SIG_IGN);
+	signal(SIGHUP, bail_out);
+	signal(SIGINT, bail_out);
+	signal(SIGTERM, bail_out);
+
+	while (!done || !Sdone) {
+		if (!Sdone && (a == ADD || a == COMPARE)) {
+			/* Slave advances. */
+			order(ADVANCE);
+			switch (answer()) {
+			case PATH:
+				Slinkpath= nil;
+				receive(Spath, sizeof(Spath));
+				recstat(&Sst);
+				break;
+			case LINK:
+				receive(Slnkpth, sizeof(Slnkpth));
+				Slinkpath= Slnkpth;
+				receive(Spath, sizeof(Spath));
+				recstat(&Sst);
+				break;
+			case SYMLINK:
+				Slinkpath= nil;
+				receive(Slnkpth, sizeof(Slnkpth));
+				receive(Spath, sizeof(Spath));
+				recstat(&Sst);
+				break;
+			case DONE:
+				Sdone= 1;
+				break;
+			default:
+				fprintf(stderr,
+					"%s: Strange answer from slave.\n",
+					arg0);
+				exit(1);
+			}
+		}
+		if (!done && (a == COMPARE || a == DELETE)) {
+			/* Master advances. */
+			if (!advance()) done= 1;
+		}
+
+		if (done && Sdone) break;
+
+		switch (a= action()) {
+		case ADD:	/* Spath exists, path doesn't, add? */
+			add(0);
+			break;
+		case COMPARE:	/* They both exist, are they the same? */
+			compare();
+			break;
+		case DELETE:	/* path exists, Spath doesn't, delete? */
+			delete(0);
+		}
+		fflush(stdout);	/* Don't keep user in suspense. */
+	}
+	order(ex == 0 ? DIE : DIE_BAD);
+}
+
+static void mediator()
+/* Sits at the local machine and passes orders from master to slave, both
+ * on remote machines.  Only diagnostics and questions are handled.
+ */
+{
+	enum orders req;
+
+	for (;;) {
+		switch (req= request()) {
+		case DIE_BAD:
+			ex= 1;
+			/*FALL THROUGH*/
+		case DIE:
+			order(DIE);
+			return;
+		case POSITIVE:
+			order(ask('y') ? PASS_YES : PASS_NO);
+			break;
+		case NEGATIVE:
+			order(ask('n') ? PASS_YES : PASS_NO);
+			break;
+		default:
+			order(req);
+		}
+	}
+}
+
+#define P_EXIT		1	/* Make sure process doesn't return. */
+#define P_SHADOW	2	/* Always use exec on 68000. */
+
+static void startprocess(proc, machine, path, p_flags)
+	void (*proc)(); char *machine, *path; int p_flags;
+{
+	char *argv[10], **argp= argv;
+	char flags[10], *pfl= flags;
+
+	if (machine != nil) {
+		char *u= machine, *m;
+
+		*argp++ = "rsh";
+		if ((m= strchr(machine, '@')) != nil) {
+			*m++ = 0;
+			*argp++ = "-l";
+			*argp++ = u;
+			machine= m;
+		}
+		*argp++ = machine;
+	} else
+	/* Without this check it would run like a pig on an non MMU 68000: */
+	if (!(USE_SHADOWING && p_flags & P_SHADOW)) {
+		if (chdir(path) < 0) {
+			if (proc != master || errno != ENOENT
+						|| mkdir(path, 0700) < 0)
+				perrx(path);
+			if (chdir(path) < 0) perrx(path);
+			printf("Destination directory %s created\n", path);
+		}
+		isvisible(path);
+		isbackup(proc == slave);
+		(*proc)();
+		if (p_flags & P_EXIT) exit(ex);
+		return;
+	}
+	*argp++ = SYNCNAME;
+	*pfl++ = '-';
+	if (interact) *pfl++ = 'i';
+	if (install) *pfl++ = 'u';
+	if (force) *pfl++ = 'f';
+	*pfl= 0;
+	*argp++ = flags;
+	*argp++ = proc == slave ? SLAVENAME : MASTERNAME;
+	*argp++ = path;
+	*argp++ = nil;
+#ifdef DEBUG
+	fprintf(stderr, "execlp(");
+	for (argp= argv; *argp != nil; argp++) fprintf(stderr, "%s, ", *argp);
+	fprintf(stderr, "nil);\n");
+#endif
+	execvp(argv[0], argv);
+	perrx(argv[0]);
+}
+
+void splitcolon(path, amach, adir) char *path, **amach, **adir;
+{
+	char *dir= path;
+
+	for (;;) {
+		if (*dir == ':') {
+			*dir++ = 0;
+			*amach= path;
+			*adir= dir;
+			break;
+		}
+		if (*dir == 0 || *dir == '/') {
+			*amach= nil;
+			*adir= path;
+			break;
+		}
+		dir++;
+	}
+}
+
+static void Usage()
+{
+	fprintf(stderr,
+	    "Usage: %s [-iuf] [[user@]machine:]dir1 [[user@]machine:]dir2\n",
+		arg0);
+	exit(1);
+}
+
+main(argc, argv) int argc; char **argv;
+{
+	char *s_mach, *s_dir;
+	char *m_mach, *m_dir;
+	int m2s[2], s2m[2], m2m[2];
+	int s_pid= 0, m_pid= 0;
+	int r;
+
+	if ((arg0= strrchr(argv[0], '/')) == nil) arg0= argv[0]; else arg0++;
+
+	while (argc>1 && argv[1][0] == '-') {
+		char *f= argv[1]+1;
+
+		while (*f != 0) {
+			switch (*f++) {
+			case 'i':	interact= 1; break;
+			case 'u':	install= 1; break;
+			case 'f':	force= 1; break;
+			default:	Usage();
+			}
+		}
+		argc--;
+		argv++;
+	}
+
+	if (argc != 3) Usage();
+
+	if (strcmp(argv[1], SLAVENAME) == 0) {
+		arg0= "Slave";
+		splitcolon(argv[2], &s_mach, &s_dir);
+		startprocess(slave, s_mach, s_dir, P_EXIT);
+	} else
+	if (strcmp(argv[1], MASTERNAME) == 0) {
+		arg0= "Master";
+		splitcolon(argv[2], &m_mach, &m_dir);
+		startprocess(master, m_mach, m_dir, P_EXIT);
+	}
+
+	splitcolon(argv[1], &s_mach, &s_dir);
+	splitcolon(argv[2], &m_mach, &m_dir);
+
+	/* How difficult can plumbing be? */
+	if (pipe(m2s) < 0 || pipe(s2m) < 0) perrx("pipe()");
+
+	if (m_mach == nil) {
+		/* synctree [machine:]dir1 dir2 */
+		switch (s_pid= fork()) {
+		case -1:
+			perrx("fork()");
+		case 0:
+			dup2(m2s[0], 0); close(m2s[0]); close(m2s[1]);
+			dup2(s2m[1], 1); close(s2m[0]); close(s2m[1]);
+			arg0= "Slave";
+			startprocess(slave, s_mach, s_dir, P_EXIT|P_SHADOW);
+		}
+		chan[0]= s2m[0]; close(s2m[1]);
+		chan[1]= m2s[1]; close(m2s[0]);
+		startprocess(master, m_mach, m_dir, 0);
+	} else
+	if (s_mach == nil) {
+		/* synctree dir1 machine:dir2 */
+		switch (m_pid= fork()) {
+		case -1:
+			perrx("fork()");
+		case 0:
+			dup2(s2m[0], 0); close(s2m[0]); close(s2m[1]);
+			dup2(m2s[1], 1); close(m2s[0]); close(m2s[1]);
+			arg0= "Master";
+			startprocess(master, m_mach, m_dir, P_EXIT|P_SHADOW);
+		}
+		chan[0]= m2s[0]; close(m2s[1]);
+		chan[1]= s2m[1]; close(s2m[0]);
+		startprocess(slave, s_mach, s_dir, 0);
+	} else {
+		/* synctree machine1:dir1 machine2:dir2 */
+		if (pipe(m2m) < 0) perrx(pipe);
+
+		switch (s_pid= fork()) {
+		case -1:
+			perrx("fork()");
+		case 0:
+			dup2(m2s[0], 0); close(m2s[0]); close(m2s[1]);
+			dup2(s2m[1], 1); close(s2m[0]); close(s2m[1]);
+			close(m2m[0]); close(m2m[1]);
+			arg0= "Slave";
+			startprocess(slave, s_mach, s_dir, P_EXIT|P_SHADOW);
+		}
+
+		switch (m_pid= fork()) {
+		case -1:
+			perrx("fork()");
+		case 0:
+			dup2(s2m[0], 0); close(s2m[0]); close(s2m[1]);
+			close(m2s[0]); close(m2s[1]);
+			dup2(m2m[1], 1); close(m2m[0]); close(m2m[1]);
+			arg0= "Master";
+			startprocess(master, m_mach, m_dir, P_EXIT|P_SHADOW);
+		}
+		close(s2m[0]); close(s2m[1]);
+		chan[0]= m2m[0]; close(m2m[1]);
+		chan[1]= m2s[1]; close(m2s[0]);
+		mediator();
+	}
+	close(chan[0]);
+	close(chan[1]);
+
+	alarm(15); /* Don't wait(2) forever. */
+
+	while (s_pid != 0 || m_pid != 0) {
+		if ((r= wait((int *) nil)) < 0) perrx("wait()");
+		if (r == s_pid) s_pid= 0;
+		if (r == m_pid) m_pid= 0;
+	}
+	exit(ex);
+}
Index: /trunk/minix/commands/simple/sysenv.c
===================================================================
--- /trunk/minix/commands/simple/sysenv.c	(revision 9)
+++ /trunk/minix/commands/simple/sysenv.c	(revision 9)
@@ -0,0 +1,80 @@
+/*	sysenv 1.0 - request system boot parameter	Author: Kees J. Bot
+ *								23 Dec 2000
+ */
+#define nil ((void*)0)
+#include <sys/types.h>
+#include <sys/svrctl.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#define NIL ((char*)0)
+
+static void tell(int fd, ...)
+{
+    va_list ap;
+    char *s;
+
+    va_start(ap, fd);
+    while ((s= va_arg(ap, char *)) != NIL) {
+	(void) write(fd, s, strlen(s));
+    }
+    va_end(ap);
+}
+
+int main(int argc, char **argv)
+{
+    struct sysgetenv sysgetenv;
+    int i;
+    int ex= 0;
+    char *e;
+    char val[1024];
+
+    i= 1;
+    while (i < argc && argv[i][0] == '-') {
+	char *opt= argv[i++]+1;
+
+	if (opt[0] == '-' && opt[1] == 0) break;	/* -- */
+
+	if (*opt != 0) {
+	    tell(2, "Usage: sysenv [name ...]\n", NIL);
+	    exit(1);
+	}
+    }
+
+    do {
+	if (i < argc) {
+	    sysgetenv.key= argv[i];
+	    sysgetenv.keylen= strlen(sysgetenv.key) + 1;
+	} else {
+	    sysgetenv.key= nil;
+	    sysgetenv.keylen= 0;
+	}
+	sysgetenv.val= val;
+	sysgetenv.vallen= sizeof(val);
+
+	if (svrctl(MMGETPARAM, &sysgetenv) == -1) {
+	    if (errno == ESRCH) {
+		ex |= 2;
+	    } else {
+		ex |= 1;
+		tell(2, "sysenv: ", strerror(errno), "\n", NIL);
+	    }
+	    continue;
+	}
+
+	e= sysgetenv.val;
+	do {
+	    e += strlen(e);
+	    *e++ = '\n';
+	} while (i == argc && *e != 0);
+
+	if (write(1, sysgetenv.val, e - sysgetenv.val) < 0) {
+	    ex |= 1;
+	    tell(2, "sysenv: ", strerror(errno), "\n", NIL);
+	}
+    } while (++i < argc);
+    return ex;
+}
Index: /trunk/minix/commands/simple/tail.c
===================================================================
--- /trunk/minix/commands/simple/tail.c	(revision 9)
+++ /trunk/minix/commands/simple/tail.c	(revision 9)
@@ -0,0 +1,359 @@
+/* tail - copy the end of a file	Author: Norbert Schlenker */
+
+/*   Syntax:	tail [-f] [-c number | -n number] [file]
+ *		tail -[number][c|l][f] [file]		(obsolescent)
+ *		tail +[number][c|l][f] [file]		(obsolescent)
+ *   Flags:
+ *	-c number	Measure starting point in bytes.  If number begins
+ *			with '+', the starting point is relative to the
+ *			the file's beginning.  If number begins with '-'
+ *			or has no sign, the starting point is relative to
+ *			the end of the file.
+ *	-f		Keep trying to read after EOF on files and FIFOs.
+ *	-n number	Measure starting point in lines.  The number
+ *			following the flag has significance similar to
+ *			that described for the -c flag.
+ *
+ *   If neither -c nor -n are specified, the default is tail -n 10.
+ *
+ *   In the obsolescent syntax, an argument with a 'c' following the
+ *   (optional) number is equivalent to "-c number" in the standard
+ *   syntax, with number including the leading sign ('+' or '-') of the
+ *   argument.  An argument with 'l' following the number is equivalent
+ *   to "-n number" in the standard syntax.  If the number is not
+ *   specified, 10 is used as the default.  If neither 'c' nor 'l' are
+ *   specified, 'l' is assumed.  The character 'f' may be suffixed to
+ *   the argument and is equivalent to specifying "-f" in the standard
+ *   syntax.  Look for lines marked "OBSOLESCENT".
+ *
+ *   If no file is specified, standard input is assumed. 
+ *
+ *   P1003.2 does not specify tail's behavior when a count of 0 is given.
+ *   It also does not specify clearly whether the first byte (line) of a
+ *   file should be numbered 0 or 1.  Historical behavior is that the
+ *   first byte is actually number 1 (contrary to all Unix standards).
+ *   Historically, a count of 0 (or -0) results in no output whatsoever,
+ *   while a count of +0 results in the entire file being copied (just like
+ *   +1).  The implementor does not agree with these behaviors, but has
+ *   copied them slavishly.  Look for lines marked "HISTORICAL".
+ *   
+ *   Author:    Norbert Schlenker
+ *   Copyright: None.  Released to the public domain.
+ *   Reference: P1003.2 section 4.59 (draft 10)
+ *   Notes:	Under Minix, this program requires chmem =30000.
+ *   Bugs:	No internationalization support; all messages are in English.
+ */
+
+/* Force visible Posix names */
+#ifndef _POSIX_SOURCE
+#define _POSIX_SOURCE 1
+#endif
+
+/* External interfaces */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* External interfaces that should have been standardized into <getopt.h> */
+extern char *optarg;
+extern int optind;
+
+/* We expect this constant to be defined in <limits.h> in a Posix program,
+ * but we'll specify it here just in case it's been left out.
+ */
+#ifndef LINE_MAX
+#define LINE_MAX 2048		/* minimum acceptable lower bound */
+#endif
+
+/* Magic numbers suggested or required by Posix specification */
+#define SUCCESS	0		/* exit code in case of success */
+#define FAILURE 1		/*                   or failure */
+#define DEFAULT_COUNT 10	/* default number of lines or bytes */
+#define MIN_BUFSIZE (LINE_MAX * DEFAULT_COUNT)
+#define SLEEP_INTERVAL	1	/* sleep for one second intervals with -f */
+
+#define FALSE 0
+#define TRUE 1
+
+/* Internal functions - prototyped under Minix */
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(int tail, (int count, int bytes, int read_until_killed));
+_PROTOTYPE(int keep_reading, (void));
+_PROTOTYPE(void usage, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int cflag = FALSE;
+  int nflag = FALSE;
+  int fflag = FALSE;
+  int number = -DEFAULT_COUNT;
+  char *suffix;
+  int opt;
+  struct stat stat_buf;
+
+/* Determining whether this invocation is via the standard syntax or
+ * via an obsolescent one is a nasty kludge.  Here it is, but there is
+ * no pretense at elegance.
+ */
+  if (argc == 1) {		/* simple:  default read of a pipe */
+	exit(tail(-DEFAULT_COUNT, 0, fflag));
+  }
+  if ((argv[1][0] == '+') ||	/* OBSOLESCENT */
+      (argv[1][0] == '-' && ((isdigit(argv[1][1])) ||
+			     (argv[1][1] == 'l') ||
+			     (argv[1][1] == 'c' && argv[1][2] == 'f')))) {
+	--argc; ++argv;
+	if (isdigit(argv[0][1])) {
+		number = (int)strtol(argv[0], &suffix, 10);
+		if (number == 0) {		/* HISTORICAL */
+			if (argv[0][0] == '+')
+				number = 1;
+			else
+				exit(SUCCESS);
+		}
+	} else {
+		number = (argv[0][0] == '+') ? DEFAULT_COUNT : -DEFAULT_COUNT;
+		suffix = &(argv[0][1]);
+	}
+	if (*suffix != '\0') {
+		if (*suffix == 'c') {
+			cflag = TRUE;
+			++suffix;
+		}
+		else
+		if (*suffix == 'l') {
+			nflag = TRUE;
+			++suffix;
+		}
+	}
+	if (*suffix != '\0') {
+		if (*suffix == 'f') {
+			fflag = TRUE;
+			++suffix;
+		}
+	}
+	if (*suffix != '\0') {	/* bad form: assume to be a file name */
+		number = -DEFAULT_COUNT;
+		cflag = nflag = FALSE;
+		fflag = FALSE;
+	} else {
+		--argc; ++argv;
+	}
+  } else {			/* new standard syntax */
+	while ((opt = getopt(argc, argv, "c:fn:")) != EOF) {
+		switch (opt) {
+		      case 'c':
+			cflag = TRUE;
+			if (*optarg == '+' || *optarg == '-')
+				number = atoi(optarg);
+			else
+			if (isdigit(*optarg))
+				number = -atoi(optarg);
+			else
+				usage();
+			if (number == 0) {		/* HISTORICAL */
+				if (*optarg == '+')
+					number = 1;
+				else
+					exit(SUCCESS);
+			}
+			break;
+		      case 'f':
+			fflag = TRUE;
+			break;
+		      case 'n':
+			nflag = TRUE;
+			if (*optarg == '+' || *optarg == '-')
+				number = atoi(optarg);
+			else
+			if (isdigit(*optarg))
+				number = -atoi(optarg);
+			else
+				usage();
+			if (number == 0) {		/* HISTORICAL */
+				if (*optarg == '+')
+					number = 1;
+				else
+					exit(SUCCESS);
+			}
+			break;
+		      default:
+			usage();
+			/* NOTREACHED */
+		}
+	}
+	argc -= optind;
+	argv += optind;
+  }
+
+  if (argc > 1 ||		/* too many arguments */
+      (cflag && nflag)) {	/* both bytes and lines specified */
+	usage();
+  }
+
+  if (argc > 0) {		/* an actual file */
+	if (freopen(argv[0], "r", stdin) != stdin) {
+		fputs("tail: could not open ", stderr);
+		fputs(argv[0], stderr);
+		fputs("\n", stderr);
+		exit(FAILURE);
+	}
+	/* There is an optimization possibility here.  If a file is being
+	 * read, we need not look at the front of it.  If we seek backwards
+         * from the end, we can (potentially) avoid looking at most of the
+	 * file.  Some systems fail when asked to seek backwards to a point
+	 * before the start of the file, so we avoid that possibility.
+	 */
+	if (number < 0 && fstat(fileno(stdin), &stat_buf) == 0) {
+		long offset = cflag ? (long)number : (long)number * LINE_MAX;
+
+		if (-offset < stat_buf.st_size)
+			fseek(stdin, offset, SEEK_END);
+	}
+  } else {
+	fflag = FALSE;		/* force -f off when reading a pipe */
+  }
+  exit(tail(number, cflag, fflag));
+  /* NOTREACHED */
+}
+
+int tail(count, bytes, read_until_killed)
+int count;			/* lines or bytes desired */
+int bytes;			/* TRUE if we want bytes */
+int read_until_killed;		/* keep reading at EOF */
+{
+  int c;
+  char *buf;			/* pointer to input buffer */
+  char *buf_end;		/* and one past its end */
+  char *start;			/* pointer to first desired character in buf */
+  char *finish;			/* pointer past last desired character */
+  int wrapped_once = FALSE;	/* TRUE after buf has been filled once */
+
+/* This is magic.  If count is positive, it means start at the count'th
+ * line or byte, with the first line or byte considered number 1.  Thus,
+ * we want to SKIP one less line or byte than the number specified.  In
+ * the negative case, we look backward from the end of the file for the
+ * (count + 1)'th newline or byte, so we really want the count to be one
+ * LARGER than was specified (in absolute value).  In either case, the
+ * right thing to do is:
+ */
+  --count;
+
+/* Count is positive:  skip the desired lines or bytes and then copy. */
+  if (count >= 0) {
+	while (count > 0 && (c = getchar()) != EOF) {
+		if (bytes || c == '\n')
+			--count;
+	}
+	while ((c = getchar()) != EOF) {
+		if (putchar(c) == EOF)
+			return FAILURE;
+	}
+	if (read_until_killed)
+		return keep_reading();
+	return ferror(stdin) ? FAILURE : SUCCESS;
+  }
+
+/* Count is negative:  allocate a reasonably large buffer. */
+  if ((buf = (char *)malloc(MIN_BUFSIZE + 1)) == (char *)NULL) {
+	fputs("tail: out of memory\n", stderr);
+	return FAILURE;
+  }
+  buf_end = buf + (MIN_BUFSIZE + 1);
+
+/* Read the entire file into the buffer. */
+  finish = buf;
+  while ((c = getchar()) != EOF) {
+	*finish++ = c;
+	if (finish == buf_end) {
+		finish = buf;
+		wrapped_once = TRUE;
+	}
+  }
+  if (ferror(stdin))
+	return FAILURE;
+
+/* Back up inside the buffer.  The count has already been adjusted to
+ * back up exactly one character too far, so we will bump the buffer
+ * pointer once after we're done.
+ * 
+ * BUG: For large line counts, the buffer may not be large enough to
+ *	hold all the lines.  The specification allows the program to
+ *	fail in such a case - this program will simply dump the entire
+ *	buffer's contents as its best attempt at the desired behavior.
+ */
+  if (finish != buf || wrapped_once) {		/* file was not empty */
+	start = (finish == buf) ? buf_end - 1 : finish - 1;
+	while (start != finish) {
+		if ((bytes || *start == '\n') && ++count == 0)
+			break;
+		if (start == buf) {
+			start = buf_end - 1;
+			if (!wrapped_once)	/* never wrapped: stop now */
+				break;
+		} else {
+			--start;
+		}
+	}
+	if (++start == buf_end) {		/* bump after going too far */
+		start = buf;
+	}
+	if (finish > start) {
+		fwrite(start, 1, finish - start, stdout);
+	} else {
+		fwrite(start, 1, buf_end - start, stdout);
+		fwrite(buf, 1, finish - buf, stdout);
+	}
+  }
+  if (read_until_killed)
+	return keep_reading();
+  return ferror(stdout) ? FAILURE : SUCCESS;
+}
+
+/* Wake at intervals to reread standard input.  Copy anything read to
+ * standard output and then go to sleep again.
+ */
+int keep_reading()
+{
+  char buf[1024];
+  int n;
+  int i;
+  off_t pos;
+  struct stat st;
+
+  pos = lseek(0, (off_t) 0, SEEK_CUR);
+  for (;;) {
+  	for (i = 0; i < 60; i++) {
+  		while ((n = read(0, buf, sizeof(buf))) > 0) {
+  			if (write(1, buf, n) < 0) return FAILURE;
+  		}
+  		if (n < 0) return FAILURE;
+
+		sleep(SLEEP_INTERVAL);
+	}
+
+	/* Rewind if suddenly truncated. */
+	if (pos != -1) {
+		if (fstat(0, &st) == -1) {
+			pos = -1;
+		} else
+		if (st.st_size < pos) {
+			pos = lseek(0, (off_t) 0, SEEK_SET);
+		} else {
+			pos = st.st_size;
+		}
+	}
+  }
+}
+
+/* Tell the user the standard syntax. */
+void usage()
+{
+  fputs("Usage: tail [-f] [-c number | -n number] [file]\n", stderr);
+  exit(FAILURE);
+}
Index: /trunk/minix/commands/simple/tar.c
===================================================================
--- /trunk/minix/commands/simple/tar.c	(revision 9)
+++ /trunk/minix/commands/simple/tar.c	(revision 9)
@@ -0,0 +1,1108 @@
+/* tar - tape archiver			Author: Michiel Huisjes */
+
+/* Usage: tar [cxt][vo][F][f] tapefile [files]
+ *
+ * attempt to make tar to conform to POSIX 1003.1
+ * disclaimer: based on an old (1986) POSIX draft.
+ * Klamer Schutte, 20/9/89
+ *
+ * Changes:
+ *  Changed to handle the original minix-tar format.	KS 22/9/89
+ *  Changed to handle BSD4.3 tar format.		KS 22/9/89
+ *  Conform to current umask if not super-user.		KS 22/9/89
+ *  Update usage message to show f option		KS 22/9/89
+ *
+ *
+ * 1)	tar will back itself up, should check archive inode num(&dev) and
+  then check the target inode number. In verbose mode, issue
+  warning, in all cases ignore target.
+  marks@mgse		Mon Sep 25 10:38:58 CDT 1989
+  	added global varaibles, made changes to main() and add_file();
+  maks@mgse Mon Sep 25 12:09:20 CDT 1989
+
+   2)	tar will not notice that a file has changed size while it was being
+  backed up. should issue warning.
+  marks@mgse		Mon Sep 25 10:38:58 CDT 1989
+
+   3)	the 'f' option was not documented in usage[].
+  marks@mgse		Mon Sep 25 12:03:20 CDT 1989
+  	changed both usage[] defines. Why are there two (one is commented out)?
+  	( deleted by me (was done twice) -- KS, 2/10/89 )
+ *
+ *  changed stat on tar_fd to an fstat				KS 2/10/89
+ *  deleted mkfifo() code -- belongs in libc.a			KS 2/10/89
+ *  made ar_dev default to -1 : an illegal device		KS 2/10/89
+ *  made impossible to chown if normal user			KS 2/10/89
+ *  if names in owner fields not known use numirical values	KS 2/10/89
+ *  creat with mask 666 -- use umask if to liberal		KS 2/10/89
+ *  allow to make directories as ../directory			KS 2/10/89
+ *  allow tmagic field to end with a space (instead of \0)	KS 2/10/89
+ *  correct usage of tmagic field 				KS 3/10/89
+ *  made mkdir() to return a value if directory == "."  	KS 3/10/89
+ *  made lint complains less (On a BSD 4.3 system)		KS 3/10/89
+ *  use of directory(3) routines				KS 3/10/89
+ *  deleted use of d_namlen selector of struct dirent		KS 18/10/89
+ *  support mknod4(2)						EC 7/7/90
+ *  forget inodes when link count expires			EC 6/4/91
+ *  don't remember directories *twice*!
+ *  added 'p' flag to ignore umask for normal user		KJB 6/10/92
+ *  mknod4(2) out						KJB 30/10/94
+ *  added 'D' flag to not recurse into directories		KJB 19/12/94
+ *  status output to stdout unless 'tar cvf -'			KJB 3/5/97
+ *
+ * Bugs:
+ *  verbose mode is not reporting consistent
+ *  code needs cleanup
+ *  prefix field is not used
+ *  timestamp of a directory will not be correct if there are files to be
+ *  unpacked in the directory
+ *	(add you favorite bug here (or two (or three (or ...))))
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
+#include <tar.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utime.h>
+#include <sys/wait.h>
+#include <stdio.h>		/* need NULL */
+#include <errno.h>
+
+#define	POSIX_COMP		/* POSIX compatible */
+#define DIRECT_3		/* use directory(3) routines */
+
+#ifdef DIRECT_3
+#ifndef BSD
+/* To all minix users: i am sorry, developed this piece of code on a
+ * BSD system. KS 18/10/89 */
+#include <dirent.h>
+#define	direct	dirent		/* stupid BSD non-POSIX compatible name! */
+#else				/* BSD */
+#include <sys/dir.h>
+#include <dir.h>
+#endif				/* BSD */
+#endif				/* DIRECT_3 */
+
+#ifdef S_IFIFO
+#define	HAVE_FIFO		/* have incorporated Simon Pooles' changes */
+#endif
+#ifdef S_IFLNK
+#define HAVE_SYMLINK
+#endif
+
+typedef char BOOL;
+#define TRUE	1
+#define FALSE	0
+
+#define STRING_SIZE	256	/* string buffer size */
+#define HEADER_SIZE	TBLOCK
+#define NAME_SIZE	NAMSIZ
+/* #define BLOCK_BOUNDARY	 20 -- not in POSIX ! */
+
+typedef union hblock HEADER;
+
+/* Make the MINIX member names overlap to the POSIX names */
+#define	m_name		name
+#define m_mode		mode
+#define m_uid		uid
+#define m_gid		gid
+#define m_size		size
+#define	m_time		mtime
+#define	m_checksum	chksum
+#define	m_linked	typeflag
+#define	m_link		linkname
+#define	hdr_block	dummy
+#define	m		header
+#define	member		dbuf
+
+#if 0				/* original structure -- see tar.h for new
+			 * structure */
+typedef union {
+  char hdr_block[HEADER_SIZE];
+  struct m {
+	char m_name[NAME_SIZE];
+	char m_mode[8];
+	char m_uid[8];
+	char m_gid[8];
+	char m_size[12];
+	char m_time[12];
+	char m_checksum[8];
+	char m_linked;
+	char m_link[NAME_SIZE];
+  } member;
+} HEADER;
+
+#endif
+
+/* Structure used to note links */
+struct link {
+  ino_t ino;
+  dev_t dev;
+  nlink_t nlink;
+  struct link *next;
+  char name[1];
+} *link_top = NULL;
+
+HEADER header;
+
+#define INT_TYPE	(sizeof(header.member.m_uid))
+#define LONG_TYPE	(sizeof(header.member.m_size))
+
+#define NIL_HEADER	((HEADER *) 0)
+#define NIL_PTR		((char *) 0)
+#define TBLOCK_SIZE	TBLOCK
+
+#define flush()		print(NIL_PTR)
+
+BOOL show_fl, creat_fl, ext_fl;
+
+int tar_fd;
+/* Char usage[] = "Usage: tar [cxt] tarfile [files]."; */
+char usage[] = "Usage: tar [cxt][vo][F][f] tarfile [files].";
+char io_buffer[TBLOCK_SIZE];
+char path[NAME_SIZE];
+char pathname[NAME_SIZE];
+int force_flag = 0;
+#ifdef ORIGINAL_DEFAULTS
+int chown_flag = 1;
+int verbose_flag = 1;
+#else
+int chown_flag = 0;
+int verbose_flag = 0;
+#endif
+int norec_flag = 0;
+
+/* Make sure we don't tar ourselves. marks@mgse Mon Sep 25 12:06:28 CDT 1989 */
+ino_t ar_inode;			/* archive inode number	 */
+dev_t ar_dev;			/* archive device number */
+
+int total_blocks;
+int u_mask;			/* one's complement of current umask */
+
+#define block_size()	(int) ((convert(header.member.m_size, LONG_TYPE) \
+  + (long) TBLOCK_SIZE - 1) / (long) TBLOCK_SIZE)
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void error, (char *s1, char *s2));
+_PROTOTYPE(BOOL get_header, (void));
+_PROTOTYPE(void tarfile, (void));
+_PROTOTYPE(void skip_entry, (void));
+_PROTOTYPE(void extract, (char *file));
+_PROTOTYPE(void delete, (char *file));
+_PROTOTYPE(void do_chown, (char *file));
+_PROTOTYPE(void timestamp, (char *file));
+_PROTOTYPE(void copy, (char *file, int from, int to, long bytes));
+_PROTOTYPE(long convert, (char str[], int type));
+_PROTOTYPE(int checksum, (void));
+_PROTOTYPE(int is_dir, (char *file));
+_PROTOTYPE(char *path_name, (char *file));
+_PROTOTYPE(void add_path, (char *name));
+_PROTOTYPE(void add_file, (char *file));
+_PROTOTYPE(void verb_print, (char *s1, char *s2));
+_PROTOTYPE(void add_close, (int fd));
+_PROTOTYPE(int add_open, (char *file, struct stat * st));
+_PROTOTYPE(void make_header, (char *file, struct stat * st));
+_PROTOTYPE(void is_added, (struct stat * st, char *file));
+_PROTOTYPE(void is_deleted, (struct stat * st));
+_PROTOTYPE(char *is_linked, (struct stat * st));
+_PROTOTYPE(void clear_header, (void));
+_PROTOTYPE(void adjust_boundary, (void));
+_PROTOTYPE(void mread, (int fd, char *address, int bytes));
+_PROTOTYPE(void mwrite, (int fd, char *address, int bytes));
+_PROTOTYPE(int bread, (int fd, char *address, int bytes));
+_PROTOTYPE(int bwrite, (int fd, char *address, int bytes));
+_PROTOTYPE(void print, (char *str));
+_PROTOTYPE(char *num_out, (long number));
+_PROTOTYPE(void string_print, (char *buffer, char *fmt,...));
+
+void error(s1, s2)
+char *s1, *s2;
+{
+  string_print(NIL_PTR, "%s %s\n", s1, s2 ? s2 : "");
+  flush();
+  exit(1);
+}
+
+int main(argc, argv)
+int argc;
+register char *argv[];
+{
+  register char *mem_name;
+  register char *ptr;
+  struct stat st;
+  int i;
+
+  if (argc < 3) error(usage, NIL_PTR);
+
+  for (ptr = argv[1]; *ptr; ptr++) {
+  	/* Ignore - as first char */
+  	if(*ptr == '-' && ptr == argv[1]) continue;
+	switch (*ptr) {
+	    case 'c':	creat_fl = TRUE;	break;
+	    case 'x':	ext_fl = TRUE;	break;
+	    case 't':	show_fl = TRUE;	break;
+	    case 'v':		/* verbose output  -Dal */
+		verbose_flag = !verbose_flag;
+		break;
+	    case 'o':		/* chown/chgrp files  -Dal */
+		chown_flag = TRUE;
+		break;
+	    case 'F':		/* IGNORE ERRORS  -Dal */
+		force_flag = TRUE;
+		break;
+	    case 'f':		/* standard U*IX usage -KS */
+		break;
+	    case 'p':		/* restore file modes right, ignore umask. */
+		(void) umask(0);
+		break;
+	    case 'D':		/* do not recursively add directories. */
+		norec_flag = TRUE;
+		break;
+	    default:	error(usage, NIL_PTR);
+	}
+  }
+
+  if (creat_fl + ext_fl + show_fl != 1) error(usage, NIL_PTR);
+
+  if (strcmp(argv[2], "-") == 0)/* only - means stdin/stdout - KS */
+	tar_fd = creat_fl ? 1 : 0;	/* '-' means used
+					 * stdin/stdout  -Dal */
+  else
+	tar_fd = creat_fl ? creat(argv[2], 0666) : open(argv[2], O_RDONLY);
+
+  if (tar_fd < 0) error("Cannot open ", argv[2]);
+
+  if (geteuid()) {		/* check if super-user */
+	int save_umask;
+	save_umask = umask(0);
+	u_mask = ~save_umask;
+	umask(save_umask);
+	chown_flag = TRUE;	/* normal user can't chown */
+  } else
+	u_mask = ~0;		/* don't restrict if 'privileged utility' */
+
+  ar_dev = -1;			/* impossible device nr */
+  if (creat_fl) {
+	if (tar_fd > 1 && fstat(tar_fd, &st) < 0)
+		error("Can't stat ", argv[2]);	/* will never be here,
+						 * right? */
+	else {			/* get archive inode & device	 */
+		ar_inode = st.st_ino;	/* save files inode	 */
+		ar_dev = st.st_dev;	/* save files device	 */
+	}			/* marks@mgse Mon Sep 25 11:30:45 CDT 1989 */
+
+	for (i = 3; i < argc; i++) {
+		add_file(argv[i]);
+		path[0] = '\0';
+	}
+	adjust_boundary();
+  } else if (ext_fl) {
+	/* Extraction code moved here from tarfile() MSP */
+	while (get_header()) {
+		mem_name = header.member.m_name;
+		if (is_dir(mem_name)) {
+			for (ptr = mem_name; *ptr; ptr++);
+			*(ptr - 1) = '\0';
+			header.dbuf.typeflag = '5';
+		}
+		for (i = 3; i < argc; i++)
+			if (!strncmp(argv[i], mem_name, strlen(argv[i])))
+				break;
+		if (argc == 3 || (i < argc)) {
+			extract(mem_name);
+		} else if (header.dbuf.typeflag == '0' ||
+			   header.dbuf.typeflag == 0 ||
+			   header.dbuf.typeflag == ' ')
+			skip_entry();
+		flush();
+	}
+  } else
+	tarfile();		/* tarfile() justs prints info. now MSP */
+
+  flush();
+  return(0);
+}
+
+BOOL get_header()
+{
+  register int check;
+
+  mread(tar_fd, (char *) &header, sizeof(header));
+  if (header.member.m_name[0] == '\0') return FALSE;
+
+  if (force_flag)		/* skip checksum verification  -Dal */
+	return TRUE;
+
+  check = (int) convert(header.member.m_checksum, INT_TYPE);
+
+  if (check != checksum()) error("Tar: header checksum error.", NIL_PTR);
+
+  return TRUE;
+}
+
+/* Tarfile() just lists info about archive now; as of the t flag. */
+/* Extraction has been moved into main() as that needs access to argv[] */
+
+void tarfile()
+{
+  register char *mem_name;
+
+  while (get_header()) {
+	mem_name = header.member.m_name;
+	string_print(NIL_PTR, "%s%s", mem_name,
+		     (verbose_flag ? " " : "\n"));
+	switch (header.dbuf.typeflag) {
+	    case '1':
+		verb_print("linked to", header.dbuf.linkname);
+		break;
+	    case '2':
+		verb_print("symbolic link to", header.dbuf.linkname);
+		break;
+	    case '6':	verb_print("", "fifo");	break;
+	    case '3':
+	    case '4':
+		if (verbose_flag) {
+			char sizebuf[TSIZLEN + 1];
+
+			strncpy(sizebuf, header.dbuf.size, (size_t) TSIZLEN);
+			sizebuf[TSIZLEN] = 0;
+			string_print(NIL_PTR,
+			      "%s special file major %s minor %s\n",
+				     (header.dbuf.typeflag == '3' ?
+				      "character" : "block"),
+				     header.dbuf.devmajor,
+				     header.dbuf.devminor,
+				     sizebuf);
+		}
+		break;
+	    case '0':		/* official POSIX */
+	    case 0:		/* also mentioned in POSIX */
+	    case ' ':		/* ofetn used */
+		if (!is_dir(mem_name)) {
+			if (verbose_flag)
+				string_print(NIL_PTR, "%d tape blocks\n",
+					     block_size());
+			skip_entry();
+			break;
+		} else		/* FALL TROUGH */
+	    case '5':
+			verb_print("", "directory");
+		break;
+	    default:
+		string_print(NIL_PTR, "not recogised item %d\n",
+			     header.dbuf.typeflag);
+	}
+	flush();
+  }
+}
+
+void skip_entry()
+{
+  register int blocks = block_size();
+
+  while (blocks--) (void) bread(tar_fd, io_buffer, TBLOCK_SIZE);
+}
+
+void extract(file)
+register char *file;
+{
+  register int fd, r;
+  char *pd1, *pd2;		/* walk thru failed directory path */
+
+  switch (header.dbuf.typeflag) {
+      case '1':			/* Link */
+	delete(file);
+	if (link(header.member.m_link, file) < 0)
+		string_print(NIL_PTR, "Cannot link %s to %s: %s\n",
+			     header.member.m_link, file, strerror(errno));
+	else if (verbose_flag)
+		string_print(NIL_PTR, "Linked %s to %s\n",
+			     header.member.m_link, file);
+	return;
+      case '5':			/* directory */
+	if (!(file[0] == '.' && file[1] == '\0')) delete(file);
+	if ((file[0] == '.' && file[1] == '\0') || mkdir(file, 0700) == 0) {
+		do_chown(file);
+		verb_print("created directory", file);
+	} else {
+		string_print(NIL_PTR, "Can't make directory %s: %s\n",
+				file, strerror(errno));
+	}
+	return;
+      case '3':			/* character special */
+      case '4':			/* block special */
+	{
+		int dmajor, dminor, mode;
+
+		dmajor = (int) convert(header.dbuf.devmajor, INT_TYPE);
+		dminor = (int) convert(header.dbuf.devminor, INT_TYPE);
+		mode = (header.dbuf.typeflag == '3' ? S_IFCHR : S_IFBLK);
+		delete(file);
+		if (mknod(file, mode, (dmajor << 8 | dminor)) == 0) {
+			if (verbose_flag) string_print(NIL_PTR,
+				     "made %s special file major %s minor %s\n",
+				      (header.dbuf.typeflag == '3' ?
+				       "character" : "block"),
+					     header.dbuf.devmajor,
+					     header.dbuf.devminor);
+			do_chown(file);
+		}
+		else 
+		{
+			string_print(NIL_PTR,
+				     "cannot make %s special file major %s minor %s: %s\n",
+				      (header.dbuf.typeflag == '3' ?
+				       "character" : "block"),
+					     header.dbuf.devmajor,
+					     header.dbuf.devminor,
+					     strerror(errno));
+		}
+		return;
+	}
+      case '2':			/* symbolic link */
+#ifdef HAVE_SYMLINK
+	delete(file);
+	if (symlink(header.member.m_link, file) < 0)
+		string_print(NIL_PTR, "Cannot make symbolic link %s to %s: %s\n",
+			     header.member.m_link, file, strerror(errno));
+	else if (verbose_flag)
+		string_print(NIL_PTR, "Symbolic link %s to %s\n",
+			     header.member.m_link, file);
+	return;
+#endif
+      case '7':			/* contiguous file -- what is this (KS) */
+	print("Not implemented file type\n");
+	return;			/* not implemented, but break out */
+#ifdef HAVE_FIFO
+      case '6':			/* fifo */
+	delete(file);
+	if (mkfifo(file, 0) == 0) {	/* is chmod'ed in do_chown */
+		do_chown(file);
+		verb_print("made fifo", file);
+	} else
+		string_print(NIL_PTR, "Can't make fifo %s: %s\n",
+			file, strerror(errno));
+	return;
+#endif
+  }
+
+  /* Create regular file.  If failure, try to make missing directories. */
+  if ((fd = creat(file, 0600)) < 0) {
+	pd1 = file;
+	while ((pd2 = index(pd1, '/')) > (char *) 0) {
+		*pd2 = '\0';
+		if (access(file, 1) < 0)
+			if (mkdir(file, 0777) < 0) {
+				string_print(NIL_PTR, "Cannot mkdir %s: %s\n",
+					file, strerror(errno));
+				return;
+			} else
+				string_print(NIL_PTR, "Made directory %s\n", file);
+		*pd2 = '/';
+		pd1 = ++pd2;
+	}
+	if ((fd = creat(file, 0600)) < 0) {
+		string_print(NIL_PTR, "Cannot create %s: %s\n",
+			file, strerror(errno));
+		return;
+	}
+  }
+  copy(file, tar_fd, fd, convert(header.member.m_size, LONG_TYPE));
+  (void) close(fd);
+
+  do_chown(file);
+}
+
+void delete(file)
+char *file;
+{
+  /* remove a file or an empty directory */
+  struct stat stbuf;
+
+  if (stat(file, &stbuf) < 0) return;
+
+  if (S_ISDIR(stbuf.st_mode)) (void) rmdir(file); else (void) unlink(file);
+  /* leave error reporting to the create following soon. */
+}
+
+void do_chown(file)
+char *file;
+{
+  int uid = -1, gid = -1;	/* these are illegal ??? -- KS */
+
+  if (!chown_flag) {		/* set correct owner and group  -Dal */
+	if (header.dbuf.magic[TMAGLEN] == ' ')
+		header.dbuf.magic[TMAGLEN] = '\0';	/* some tars out there
+							 * ... */
+	if (strncmp(TMAGIC, header.dbuf.magic, (size_t) TMAGLEN)) {
+		struct passwd *pwd;
+		struct group *grp;
+
+		pwd = getpwnam(header.dbuf.uname);
+		if (pwd != NULL) uid = pwd->pw_uid;
+		grp = getgrnam(header.dbuf.gname);
+		if (grp != NULL) gid = grp->gr_gid;
+	}
+	if (uid == -1) uid = (int) convert(header.member.m_uid, INT_TYPE);
+	if (gid == -1) gid = (int) convert(header.member.m_gid, INT_TYPE);
+	chown(file, uid, gid);
+  }
+  chmod(file, u_mask & (int) convert(header.member.m_mode, INT_TYPE));
+
+  /* Should there be a timestamp if the chown failes? -- KS */
+  timestamp(file);
+
+}
+
+void timestamp(file)
+char *file;
+{
+  struct utimbuf buf;
+
+  buf.modtime = buf.actime = convert(header.dbuf.mtime, LONG_TYPE);
+  utime(file, &buf);
+}
+
+void copy(file, from, to, bytes)
+char *file;
+int from, to;
+register long bytes;
+{
+  register int rest;
+  int blocks = (int) ((bytes + (long) TBLOCK_SIZE - 1) / (long) TBLOCK_SIZE);
+
+  if (verbose_flag)
+	string_print(NIL_PTR, "%s, %d tape blocks\n", file, blocks);
+
+  while (blocks--) {
+	(void) bread(from, io_buffer, TBLOCK_SIZE);
+	rest = (bytes > (long) TBLOCK_SIZE) ? TBLOCK_SIZE : (int) bytes;
+	mwrite(to, io_buffer, (to == tar_fd) ? TBLOCK_SIZE : rest);
+	bytes -= (long) rest;
+  }
+}
+
+long convert(str, type)
+char str[];
+int type;
+{
+  register long ac = 0L;
+  register int i;
+
+  for (i = 0; i < type; i++) {
+	if (str[i] >= '0' && str[i] <= '7') {
+		ac <<= 3;
+		ac += (long) (str[i] - '0');
+	}
+  }
+
+  return ac;
+}
+
+int checksum()
+{
+  register char *ptr = header.member.m_checksum;
+  register int ac = 0;
+
+  while (ptr < &header.member.m_checksum[INT_TYPE]) *ptr++ = ' ';
+
+  ptr = header.hdr_block;
+  while (ptr < &header.hdr_block[TBLOCK_SIZE]) ac += *ptr++;
+
+  return ac;
+}
+
+int is_dir(file)
+register char *file;
+{
+  while (*file++ != '\0');
+
+  return(*(file - 2) == '/');
+}
+
+
+char *path_name(file)
+register char *file;
+{
+
+  string_print(pathname, "%s%s", path, file);
+  return pathname;
+}
+
+void add_path(name)
+register char *name;
+{
+  register char *path_ptr = path;
+
+  while (*path_ptr) path_ptr++;
+
+  if (name == NIL_PTR) {
+	while (*path_ptr-- != '/');
+	while (*path_ptr != '/' && path_ptr != path) path_ptr--;
+	if (*path_ptr == '/') path_ptr++;
+	*path_ptr = '\0';
+  } else {
+	while (*name) {
+		if (path_ptr == &path[NAME_SIZE])
+			error("Pathname too long", NIL_PTR);
+		*path_ptr++ = *name++;
+	}
+	*path_ptr++ = '/';
+	*path_ptr = '\0';
+  }
+}
+
+/*
+ *	add a file to the archive
+*/
+void add_file(file)
+register char *file;
+{
+  struct stat st;
+  char *linkname;
+  register int fd = -1;
+  char namebuf[16];		/* -Dal */
+  char cwd[129];		/* -KS */
+
+#ifdef HAVE_SYMLINK
+  if (lstat(file, &st) < 0) {
+#else
+  if (stat(file, &st) < 0) {
+#endif
+	string_print(NIL_PTR, "%s: %s\n", file, strerror(errno));
+	return;
+  }
+  if (st.st_dev == ar_dev && st.st_ino == ar_inode) {
+	string_print(NIL_PTR, "Cannot tar current archive file (%s)\n", file);
+	return;
+  }				/* marks@mgse Mon Sep 25 12:06:28 CDT 1989 */
+  if ((fd = add_open(file, &st)) < 0) {
+	string_print(NIL_PTR, "Cannot open %s\n", file);
+	return;
+  }
+  make_header(path_name(file), &st);
+  if ((linkname = is_linked(&st)) != NULL) {
+	strncpy(header.dbuf.linkname, linkname, (size_t) NAMSIZ);
+	header.dbuf.typeflag = '1';
+	if (verbose_flag) string_print(NIL_PTR, "linked %s to %s\n",
+			     header.dbuf.linkname, file);
+	string_print(header.member.m_checksum, "%I ", checksum());
+	mwrite(tar_fd, (char *) &header, sizeof(header));
+  } else {
+	is_added(&st, file);
+	switch (st.st_mode & S_IFMT) {
+	    case S_IFREG:
+		header.dbuf.typeflag = '0';
+		string_print(header.member.m_checksum, "%I ", checksum());
+		mwrite(tar_fd, (char *) &header, sizeof(header));
+		copy(path_name(file), fd, tar_fd, (long) st.st_size);
+		break;
+	    case S_IFDIR:
+		header.dbuf.typeflag = '5';
+		string_print(header.member.m_checksum, "%I ", checksum());
+		mwrite(tar_fd, (char *) &header, sizeof(header));
+		verb_print("read directory", file);
+		if (norec_flag) break;
+		if (NULL == getcwd(cwd, (int) sizeof cwd))
+			string_print(NIL_PTR, "Error: cannot getcwd()\n");
+		else if (chdir(file) < 0)
+			string_print(NIL_PTR, "Cannot chdir to %s: %s\n",
+				file, strerror(errno));
+		else {
+			add_path(file);
+#ifdef	DIRECT_3
+			{
+				DIR *dirp;
+				struct direct *dp;
+				struct stat dst;
+
+				add_close(fd);
+				fd= 0;
+				dirp = opendir(".");
+				while (NULL != (dp = readdir(dirp)))
+					if (strcmp(dp->d_name, ".") == 0)
+						is_linked(&st);
+					else if (strcmp(dp->d_name, "..") == 0) {
+						if (stat("..", &dst) == 0)
+							is_linked(&dst);
+					} else {
+						strcpy(namebuf, dp->d_name);
+						add_file(namebuf);
+					}
+				closedir(dirp);
+			}
+#else
+			{
+				int i;
+				struct direct dir;
+				struct stat dst;
+
+				for (i = 0; i < 2; i++) {	/* . and .. */
+					mread(fd, &dir, sizeof(dir));
+					if (strcmp(dir.d_name, ".") == 0)
+						is_linked(&st);
+					else if (strcmp(dir.d_name, "..") == 0) {
+						if (stat("..", &dst) == 0)
+							is_linked(&dst);
+					} else
+						break;
+				}
+				while (bread(fd, &dir, sizeof(dir)) == sizeof(dir))
+					if (dir.d_ino) {
+						strncpy(namebuf, dir.d_name,
+						   (size_t) DIRSIZ);
+						namebuf[DIRSIZ] = '\0';
+						add_file(namebuf);
+					}
+			}
+#endif
+			chdir(cwd);
+			add_path(NIL_PTR);
+			*file = 0;
+		}
+		break;
+#ifdef HAVE_SYMLINK
+	    case S_IFLNK:
+		{
+			int i;
+
+			header.dbuf.typeflag = '2';
+			verb_print("read symlink", file);
+			i = readlink(file,
+				     header.dbuf.linkname,
+				  sizeof(header.dbuf.linkname) - 1);
+			if (i < 0) {
+				string_print(NIL_PTR,
+					"Cannot read symbolic link %s: %s\n",
+					file, strerror(errno));
+				return;
+			}
+			header.dbuf.linkname[i] = 0;
+			string_print(header.member.m_checksum, "%I ", checksum());
+			mwrite(tar_fd, (char *) &header, sizeof(header));
+			break;
+		}
+#endif
+#ifdef HAVE_FIFO
+	    case S_IFIFO:
+		header.dbuf.typeflag = '6';
+		verb_print("read fifo", file);
+		string_print(header.member.m_checksum, "%I ", checksum());
+		mwrite(tar_fd, (char *) &header, sizeof(header));
+		break;
+#endif
+	    case S_IFBLK:
+		header.dbuf.typeflag = '4';
+		if (verbose_flag) {
+			char sizebuf[TSIZLEN + 1];
+
+			strncpy(sizebuf, header.dbuf.size, (size_t) TSIZLEN);
+			sizebuf[TSIZLEN] = 0;
+			string_print(NIL_PTR,
+			 "read block device %s major %s minor %s\n",
+				     file, header.dbuf.devmajor, header.dbuf.devminor, sizebuf);
+		}
+		string_print(header.member.m_checksum, "%I ", checksum());
+		mwrite(tar_fd, (char *) &header, sizeof(header));
+		break;
+	    case S_IFCHR:
+		header.dbuf.typeflag = '3';
+		if (verbose_flag) string_print(NIL_PTR,
+				     "read character device %s major %s minor %s\n",
+				     file, header.dbuf.devmajor, header.dbuf.devminor);
+		string_print(header.member.m_checksum, "%I ", checksum());
+		mwrite(tar_fd, (char *) &header, sizeof(header));
+		break;
+	    default:
+		is_deleted(&st);
+		string_print(NIL_PTR, "Tar: %s unknown file type. Not added.\n", file);
+		*file = 0;
+	}
+  }
+
+  flush();
+  add_close(fd);
+}
+
+void verb_print(s1, s2)
+char *s1, *s2;
+{
+  if (verbose_flag) string_print(NIL_PTR, "%s: %s\n", s1, s2);
+}
+
+void add_close(fd)
+int fd;
+{
+  if (fd != 0) close(fd);
+}
+
+/*
+ *	open file 'file' to be added to archive, return file descriptor
+*/
+int add_open(file, st)
+char *file;
+struct stat *st;
+{
+  int fd;
+  if (((st->st_mode & S_IFMT) != S_IFREG) &&
+      ((st->st_mode & S_IFMT) != S_IFDIR))
+	return 0;
+  fd = open(file, O_RDONLY);
+  if (fd == -1)
+  	fprintf(stderr, "open failed: %s\n", strerror(errno));
+  return fd;
+}
+
+void make_header(file, st)
+char *file;
+register struct stat *st;
+{
+  register char *ptr = header.member.m_name;
+  struct passwd *pwd;
+  struct group *grp;
+
+  clear_header();
+
+  while (*ptr++ = *file++);
+
+  if ((st->st_mode & S_IFMT) == S_IFDIR) {	/* fixed test  -Dal */
+	*(ptr - 1) = '/';
+  }
+  string_print(header.member.m_mode, "%I ", st->st_mode & 07777);
+  string_print(header.member.m_uid, "%I ", st->st_uid);
+  string_print(header.member.m_gid, "%I ", st->st_gid);
+  if ((st->st_mode & S_IFMT) == S_IFREG)
+	string_print(header.member.m_size, "%L ", st->st_size);
+  else
+	strncpy(header.dbuf.size, "0", (size_t) TSIZLEN);
+  string_print(header.member.m_time, "%L ", st->st_mtime);
+  strncpy(header.dbuf.magic, TMAGIC, (size_t) TMAGLEN);
+  header.dbuf.version[0] = 0;
+  header.dbuf.version[1] = 0;
+  pwd = getpwuid(st->st_uid);
+  strncpy(header.dbuf.uname,
+	(pwd != NULL ? pwd->pw_name : "nobody"), TUNMLEN);
+  grp = getgrgid(st->st_gid);
+  strncpy(header.dbuf.gname,
+	(grp != NULL ? grp->gr_name : "nobody"), TGNMLEN);
+  if (st->st_mode & (S_IFBLK | S_IFCHR)) {
+	string_print(header.dbuf.devmajor, "%I ", (st->st_rdev >> 8));
+	string_print(header.dbuf.devminor, "%I ", (st->st_rdev & 0xFF));
+  }
+  header.dbuf.prefix[0] = 0;
+}
+
+void is_added(st, file)
+struct stat *st;
+char *file;
+{
+  struct link *new;
+  char *name;
+
+  if ((*file == 0) || (st->st_nlink == 1)) return;
+  name = path_name(file);
+  new = (struct link *) malloc(sizeof(struct link) + strlen(name));
+  if (new == NULL) {
+	print("Out of memory\n");
+	return;
+  }
+  new->next = link_top;
+  new->dev = st->st_dev;
+  new->ino = st->st_ino;
+  new->nlink = st->st_nlink - 1;
+  strcpy(new->name, name);
+  link_top = new;
+}
+
+void is_deleted(st)
+struct stat *st;
+{
+  struct link *old;
+
+  if ((old = link_top) != NULL) {
+	link_top = old->next;
+	free(old);
+  }
+}
+
+char *is_linked(st)
+struct stat *st;
+{
+  struct link *cur = link_top;
+  struct link **pre = &link_top;
+  static char name[NAMSIZ];
+
+  while (cur != NULL)
+	if ((cur->dev != st->st_dev) || (cur->ino != st->st_ino)) {
+		pre = &cur->next;
+		cur = cur->next;
+	} else {
+		if (--cur->nlink == 0) {
+			*pre = cur->next;
+			strncpy(name, cur->name, NAMSIZ);
+			return name;
+		}
+		return cur->name;
+	}
+  return NULL;
+}
+
+void clear_header()
+{
+  register char *ptr = header.hdr_block;
+
+  while (ptr < &header.hdr_block[TBLOCK_SIZE]) *ptr++ = '\0';
+}
+
+void adjust_boundary()
+{
+  clear_header();
+  mwrite(tar_fd, (char *) &header, sizeof(header));
+#ifndef POSIX_COMP
+  while (total_blocks++ < BLOCK_BOUNDARY)
+	mwrite(tar_fd, (char *) &header, sizeof(header));
+#else
+  mwrite(tar_fd, (char *) &header, sizeof(header));
+#endif
+  (void) close(tar_fd);
+}
+
+void mread(fd, address, bytes)
+int fd, bytes;
+char *address;
+{
+  if (bread(fd, address, bytes) != bytes) error("Tar: read error.", NIL_PTR);
+}
+
+void mwrite(fd, address, bytes)
+int fd, bytes;
+char *address;
+{
+  if (bwrite(fd, address, bytes) != bytes) error("Tar: write error.", NIL_PTR);
+
+  total_blocks++;
+}
+
+int bread(fd, address, bytes)
+int fd, bytes;
+char *address;
+{
+  int n = 0, r;
+
+  while (n < bytes) {
+	if ((r = read(fd, address + n, bytes - n)) <= 0) {
+		if (r < 0) return r;
+		break;
+	}
+	n += r;
+  }
+  return n;
+}
+
+int bwrite(fd, address, bytes)
+int fd, bytes;
+char *address;
+{
+  int n = 0, r;
+
+  while (n < bytes) {
+	if ((r = write(fd, address + n, bytes - n)) <= 0) {
+		if (r < 0) return r;
+		break;
+	}
+	n += r;
+  }
+  return n;
+}
+
+char output[TBLOCK_SIZE];
+void print(str)
+register char *str;
+{
+  int fd = (tar_fd == 1 ? 2 : 1);
+  static int indx = 0;
+
+  if (str == NIL_PTR) {
+	write(fd, output, indx);
+	indx = 0;
+	return;
+  }
+  while (*str) {
+	output[indx++] = *str++;
+	if (indx == TBLOCK_SIZE) {
+		write(fd, output, TBLOCK_SIZE);
+		indx = 0;
+	}
+  }
+}
+
+char *num_out(number)
+register long number;
+{
+  static char num_buf[12];
+  register int i;
+
+  for (i = 11; i--;) {
+	num_buf[i] = (number & 07) + '0';
+	number >>= 3;
+  }
+
+  return num_buf;
+}
+
+/*VARARGS2*/
+#if __STDC__
+void string_print(char *buffer, char *fmt,...)
+#else
+void string_print(buffer, fmt)
+char *buffer;
+char *fmt;
+#endif
+{
+  va_list args;
+  register char *buf_ptr;
+  char *scan_ptr;
+  char buf[STRING_SIZE];
+  BOOL pr_fl, i;
+
+  if (pr_fl = (buffer == NIL_PTR)) buffer = buf;
+
+  va_start(args, fmt);
+  buf_ptr = buffer;
+  while (*fmt) {
+	if (*fmt == '%') {
+		fmt++;
+		switch (*fmt++) {
+		    case 's':
+			scan_ptr = (char *) (va_arg(args, char *));
+			break;
+		    case 'I':
+			scan_ptr = num_out((long) (va_arg(args, int)));
+			for (i = 0; i < 5; i++) scan_ptr++;
+			break;
+		    case 'L':
+			scan_ptr = num_out((long) va_arg(args, long));
+			break;
+		    case 'd':
+			scan_ptr = num_out((long) va_arg(args, int));
+			while (*scan_ptr == '0') scan_ptr++;
+			scan_ptr--;
+			break;
+		    default:	scan_ptr = "";
+		}
+		while (*buf_ptr++ = *scan_ptr++);
+		buf_ptr--;
+	} else
+		*buf_ptr++ = *fmt++;
+  }
+  *buf_ptr = '\0';
+
+  if (pr_fl) print(buffer);
+  va_end(args);
+}
Index: /trunk/minix/commands/simple/tcpd.c
===================================================================
--- /trunk/minix/commands/simple/tcpd.c	(revision 9)
+++ /trunk/minix/commands/simple/tcpd.c	(revision 9)
@@ -0,0 +1,311 @@
+/*
+tcpd.c
+*/
+
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <minix/config.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <net/hton.h>
+#include <net/netlib.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/netdb.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+
+/* This program can be compiled to be paranoid, i.e. check incoming connection
+ * according to an access file, or to trust anyone.  The much smaller "trust
+ * 'em" binary will call the paranoid version if the access file exists.
+ */
+
+static char *arg0, *service;
+static unsigned nchildren;
+
+static void report(const char *label)
+{
+    int err= errno;
+
+    fprintf(stderr, "%s %s: %s: %s\n", arg0, service, label, strerror(err));
+    errno= err;
+}
+
+static void sigchld(int sig)
+{
+    while (waitpid(0, NULL, WNOHANG) > 0) {
+	if (nchildren > 0) nchildren--;
+    }
+}
+
+static void release(int *fd)
+{
+    if (*fd != -1) {
+	close(*fd);
+	*fd= -1;
+    }
+}
+
+static void usage(void)
+{
+    fprintf(stderr,
+	"Usage: %s [-d] [-m maxclients] service program [arg ...]\n",
+	arg0);
+    exit(1);
+}
+
+int main(int argc, char **argv)
+{
+    tcpport_t port;
+    int last_failed = 0;
+    struct nwio_tcpcl tcplistenopt;
+    struct nwio_tcpconf tcpconf;
+    struct nwio_tcpopt tcpopt;
+    char *tcp_device;
+    struct servent *servent;
+    int tcp_fd, client_fd, count, r;
+    int pfd[2];
+    unsigned stall= 0;
+    struct sigaction sa;
+    sigset_t chldmask, chldunmask, oldmask;
+    char **progv;
+
+#if !PARANOID
+#   define debug 0
+#   define max_children ((unsigned) -1)
+    arg0= argv[0];
+
+    /* Switch to the paranoid version of me if there are flags, or if
+     * there is an access file.
+     */
+    if (argv[1][0] == '-' || access(_PATH_SERVACCES, F_OK) == 0) {
+	execv("/usr/bin/tcpdp", argv);
+	report("tcpdp");
+	exit(1);
+    }
+    if (argc < 3) usage();
+    service= argv[1];
+    progv= argv+2;
+
+#else /* PARANOID */
+    int debug, i;
+    unsigned max_children;
+
+    arg0= argv[0];
+    debug= 0;
+    max_children= -1;
+    i= 1;
+    while (i < argc && argv[i][0] == '-') {
+	char *opt= argv[i++] + 1;
+	unsigned long m;
+	char *end;
+
+	if (*opt == '-' && opt[1] == 0) break;	/* -- */
+
+	while (*opt != 0) switch (*opt++) {
+	case 'd':
+	    debug= 1;
+	    break;
+	case 'm':
+	    if (*opt == 0) {
+		if (i == argc) usage();
+		opt= argv[i++];
+	    }
+	    m= strtoul(opt, &end, 10);
+	    if (m <= 0 || m > UINT_MAX || *end != 0) usage();
+	    max_children= m;
+	    opt= "";
+	    break;
+	default:
+	    usage();
+	}
+    }
+    service= argv[i++];
+    progv= argv+i;
+    if (i >= argc) usage();
+#endif
+
+    /* The interface to start the service on. */
+    if ((tcp_device= getenv("TCP_DEVICE")) == NULL) tcp_device= TCP_DEVICE;
+
+    /* Let SIGCHLD interrupt whatever I'm doing. */
+    sigemptyset(&chldmask);
+    sigaddset(&chldmask, SIGCHLD);
+    sigprocmask(SIG_BLOCK, &chldmask, &oldmask);
+    chldunmask= oldmask;
+    sigdelset(&chldunmask, SIGCHLD);
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = sigchld;
+    sigaction(SIGCHLD, &sa, NULL);
+
+    /* Open a socket to the service I'm to serve. */
+    if ((servent= getservbyname(service, "tcp")) == NULL) {
+	unsigned long p;
+	char *end;
+
+	p= strtoul(service, &end, 0);
+	if (p <= 0 || p > 0xFFFF || *end != 0) {
+	    fprintf(stderr, "%s: %s: Unknown service\n",
+		arg0, service);
+	    exit(1);
+	}
+	port= htons((tcpport_t) p);
+    } else {
+	port= servent->s_port;
+
+	if (debug)
+	{
+	    fprintf(stderr, "%s %s: listening to port %u\n",
+		arg0, service, ntohs(port));
+	}
+    }
+
+    /* No client yet. */
+    client_fd= -1;
+
+    while (1) {
+	if ((tcp_fd= open(tcp_device, O_RDWR)) < 0) {
+	    report(tcp_device);
+#if 0
+	    if (errno == ENOENT || errno == ENODEV
+			    || errno == ENXIO) {
+		exit(1);
+	    }
+#endif
+	    last_failed = 1;
+	    goto bad;
+	}
+	if(last_failed)
+		fprintf(stderr, "%s %s: %s: Ok\n",
+			arg0, service, tcp_device);
+	last_failed = 0;
+
+	tcpconf.nwtc_flags= NWTC_LP_SET | NWTC_UNSET_RA | NWTC_UNSET_RP;
+	tcpconf.nwtc_locport= port;
+
+	if (ioctl(tcp_fd, NWIOSTCPCONF, &tcpconf) < 0) {
+	    report("Can't configure TCP channel");
+	    exit(1);
+	}
+
+	tcpopt.nwto_flags= NWTO_DEL_RST;
+
+	if (ioctl(tcp_fd, NWIOSTCPOPT, &tcpopt) < 0) {
+	    report("Can't set TCP options");
+	    exit(1);
+	}
+
+	if (client_fd != -1) {
+	    /* We have a client, so start a server for it. */
+
+	    tcpopt.nwto_flags= 0;
+	    (void) ioctl(client_fd, NWIOSTCPOPT, &tcpopt);
+
+	    fflush(NULL);
+
+	    /* Create a pipe to serve as an error indicator. */
+	    if (pipe(pfd) < 0) {
+		report("pipe");
+		goto bad;
+	    }
+	    (void) fcntl(pfd[1], F_SETFD,
+		    fcntl(pfd[1], F_GETFD) | FD_CLOEXEC);
+
+	    /* Fork and exec. */
+	    switch (fork()) {
+	    case -1:
+		report("fork");
+		close(pfd[0]);
+		close(pfd[1]);
+		goto bad;
+	    case 0:
+		close(tcp_fd);
+		close(pfd[0]);
+#if PARANOID
+		/* Check if access to this service allowed. */
+		if (ioctl(client_fd, NWIOGTCPCONF, &tcpconf) == 0
+		    && tcpconf.nwtc_remaddr != tcpconf.nwtc_locaddr
+		    && !servxcheck(tcpconf.nwtc_remaddr, argv[1], NULL)
+		) {
+		    exit(1);
+		}
+#endif
+		sigprocmask(SIG_SETMASK, &oldmask, NULL);
+		dup2(client_fd, 0);
+		dup2(client_fd, 1);
+		close(client_fd);
+		execvp(progv[0], progv);
+		report(progv[0]);
+		write(pfd[1], &errno, sizeof(errno));
+		exit(1);
+	    default:
+		nchildren++;
+		release(&client_fd);
+		close(pfd[1]);
+		r= read(pfd[0], &errno, sizeof(errno));
+		close(pfd[0]);
+		if (r != 0) goto bad;
+		break;
+	    }
+	}
+
+	while (nchildren >= max_children) {
+	    /* Too many clients, wait for one to die off. */
+	    sigsuspend(&chldunmask);
+	}
+
+	/* Wait for a new connection. */
+	sigprocmask(SIG_UNBLOCK, &chldmask, NULL);
+
+	tcplistenopt.nwtcl_flags= 0;
+	while (ioctl(tcp_fd, NWIOTCPLISTEN, &tcplistenopt) < 0) {
+	    if (errno != EINTR) {
+		if (errno != EAGAIN || debug) {
+		    report("Unable to listen");
+		}
+		goto bad;
+	    }
+	}
+	sigprocmask(SIG_BLOCK, &chldmask, NULL);
+
+	/* We got a connection. */
+	client_fd= tcp_fd;
+	tcp_fd= -1;
+
+	if (debug && ioctl(client_fd, NWIOGTCPCONF, &tcpconf) == 0) {
+	    fprintf(stderr, "%s %s: Connection from %s:%u\n",
+		arg0, service,
+		inet_ntoa(tcpconf.nwtc_remaddr),
+		ntohs(tcpconf.nwtc_remport));
+	}
+	/* All is well, no need to stall. */
+	stall= 0;
+	continue;
+
+    bad:
+	/* All is not well, release resources. */
+	release(&tcp_fd);
+	release(&client_fd);
+
+	/* Wait a bit if this happens more than once. */
+	if (stall != 0) {
+	    if (debug) {
+		fprintf(stderr, "%s %s: stalling %u second%s\n",
+		    arg0, service,
+		    stall, stall == 1 ? "" : "s");
+	    }
+	    sleep(stall);
+	    stall <<= 1;
+	} else {
+	    stall= 1;
+	}
+    }
+}
Index: /trunk/minix/commands/simple/tcpstat.c
===================================================================
--- /trunk/minix/commands/simple/tcpstat.c	(revision 9)
+++ /trunk/minix/commands/simple/tcpstat.c	(revision 9)
@@ -0,0 +1,327 @@
+/*
+tcpstat.c
+
+Created:	June 1995 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+#define _MINIX_SOURCE
+#define _POSIX_C_SOURCE 2
+
+#include <inet/inet.h>
+#undef printf
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/svrctl.h>
+#ifndef __minix_vmd
+#include <sys/times.h>
+#endif
+#include <net/netlib.h>
+#include <net/gen/inet.h>
+#include <net/gen/netdb.h>
+#include <net/gen/socket.h>
+#include <minix/queryparam.h>
+
+#include <inet/generic/buf.h>
+#include <inet/generic/clock.h>
+#include <inet/generic/event.h>
+#include <inet/generic/type.h>
+#include <inet/generic/tcp.h>
+#include <inet/generic/tcp_int.h>
+
+char *prog_name;
+tcp_conn_t tcp_conn_table[TCP_CONN_NR];
+char values[2 * sizeof(tcp_conn_table) + 1];
+int inclListen, numerical, verbose;
+
+void print_conn(int i, clock_t now);
+void usage(void);
+
+int main(int argc, char*argv[])
+{
+	char *tcp_device;
+	int fd, i;
+	struct svrqueryparam qpar;
+	char *pval;
+	struct timeval uptime;
+	clock_t now;
+	int fl;
+	int a_flag, n_flag, v_flag;
+
+	(prog_name=strrchr(argv[0], '/')) ? prog_name++ : (prog_name=argv[0]);
+
+	a_flag= 0;
+	n_flag= 0;
+	v_flag= 0;
+	while ((fl= getopt(argc, argv, "?anv")) != -1)
+	{
+		switch(fl)
+		{
+		case '?':
+			usage();
+		case 'a':
+			a_flag= 1;
+			break;
+		case 'n':
+			n_flag= 1;
+			break;
+		case 'v':
+			v_flag= 1;
+			break;
+		default:
+			fprintf(stderr, "%s: getopt failed: '%c'\n", 
+				prog_name, fl);
+			exit(1);
+		}
+	}
+	inclListen= !!a_flag;
+	numerical= !!n_flag;
+	verbose= !!v_flag;
+
+	tcp_device= TCP_DEVICE;
+	if ((fd= open(tcp_device, O_RDWR)) == -1)
+	{
+		fprintf(stderr, "%s: unable to open '%s': %s\n", prog_name,
+			tcp_device, strerror(errno));
+		exit(1);
+	}
+
+	qpar.param = "tcp_conn_table";
+	qpar.psize = strlen(qpar.param);
+	qpar.value = values;
+	qpar.vsize = sizeof(values);
+	if (ioctl(fd, NWIOQUERYPARAM, &qpar) == -1)
+	{
+		fprintf(stderr, "%s: queryparam failed: %s\n", prog_name,
+			strerror(errno));
+		exit(1);
+	}
+	pval= values;
+	if (paramvalue(&pval, tcp_conn_table, sizeof(tcp_conn_table)) !=
+		sizeof(tcp_conn_table))
+	{
+		fprintf(stderr,
+			"%s: unable to decode the results from queryparam\n",
+			prog_name);
+		exit(1);
+	}
+
+#ifdef __minix_vmd
+	/* Get the uptime in clock ticks. */
+	if (sysutime(UTIME_UPTIME, &uptime) == -1)
+	{
+		fprintf(stderr, "%s: sysutime failed: %s\n", prog_name,
+			strerror(errno));
+		exit(1);
+	}
+	now= uptime.tv_sec * HZ + (uptime.tv_usec*HZ/1000000);
+#else	/* Minix 3 */
+	now= times(NULL);
+#endif
+
+	for (i= 0; i<TCP_CONN_NR; i++)
+		print_conn(i, now);
+	exit(0);
+}
+
+void print_conn(int i, clock_t now)
+{
+	tcp_conn_t *tcp_conn;
+	char *addr_str;
+	struct hostent *hostent;
+	struct servent *servent;
+	ipaddr_t a1, a2;
+	tcpport_t p1, p2;
+	unsigned flags;
+	int no_verbose;
+	clock_t rtt, artt, drtt;
+
+	tcp_conn= &tcp_conn_table[i];
+	if (!(tcp_conn->tc_flags & TCF_INUSE))
+		return;
+	if (tcp_conn->tc_state == TCS_LISTEN && !inclListen)
+		return;
+	if (tcp_conn->tc_state == TCS_CLOSED && tcp_conn->tc_fd == NULL &&
+		tcp_conn->tc_senddis < now)
+	{
+		return;
+	}
+	
+	printf("%3d", i);
+
+	a1= tcp_conn->tc_locaddr;
+	p1= tcp_conn->tc_locport;
+	a2= tcp_conn->tc_remaddr;
+	p2= tcp_conn->tc_remport;
+
+	if (a1 == 0)
+		addr_str= "*";
+	else if (!numerical &&
+		(hostent= gethostbyaddr((char *)&a1,
+		sizeof(a1), AF_INET)) != NULL)
+	{
+		addr_str= hostent->h_name;
+	}
+	else
+		addr_str= inet_ntoa(a1);
+	printf(" %s:", addr_str);
+
+	if (p1 == 0)
+		printf("*");
+	else if ((servent= getservbyport(p1, "tcp")) != NULL)
+	{
+		printf("%s", servent->s_name);
+	}
+	else
+		printf("%u", ntohs(p1));
+
+	if (tcp_conn->tc_orglisten)
+		printf(" <- ");
+	else
+		printf(" -> ");
+
+	if (a2 == 0)
+		addr_str= "*";
+	else if (!numerical &&
+		(hostent= gethostbyaddr((char *)&a2,
+		sizeof(a2), AF_INET)) != NULL)
+	{
+		addr_str= hostent->h_name;
+	}
+	else
+		addr_str= inet_ntoa(a2);
+	printf("%s:", addr_str);
+
+	if (p2 == 0)
+		printf("*");
+	else if ((servent= getservbyport(p2, "tcp")) !=
+		NULL)
+	{
+		printf("%s", servent->s_name);
+	}
+	else
+		printf("%u", ntohs(p2));
+
+	printf(" ");
+	no_verbose= 0;
+	switch(tcp_conn->tc_state)
+	{
+	case TCS_CLOSED:	printf("CLOSED");
+				if (tcp_conn->tc_senddis >= now)
+				{
+					printf("(time wait %ld s)",
+						(tcp_conn->tc_senddis-now)/HZ);
+				}
+				no_verbose= 1;
+				break;
+	case TCS_LISTEN:	printf("LISTEN"); no_verbose= 1; break;
+	case TCS_SYN_RECEIVED:	printf("SYN_RECEIVED"); break;
+	case TCS_SYN_SENT:	printf("SYN_SENT"); break;
+	case TCS_ESTABLISHED:	printf("ESTABLISHED"); break;
+	case TCS_CLOSING:	printf("CLOSING"); break;
+	default:		printf("state(%d)", tcp_conn->tc_state);
+				break;
+	}
+
+	if (tcp_conn->tc_flags & TCF_FIN_RECV)
+		printf(" F<");
+	if (tcp_conn->tc_flags & TCF_FIN_SENT)
+	{
+		printf(" F>");
+		if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
+			printf("+");
+	}
+	if (tcp_conn->tc_state != TCS_CLOSED &&
+		tcp_conn->tc_state != TCS_LISTEN)
+	{
+		printf("\n\t");
+		printf("RQ: %lu, SQ: %lu, RWnd: %u, SWnd: %lu, SWThresh: %lu",
+			tcp_conn->tc_RCV_NXT - tcp_conn->tc_RCV_LO,
+			tcp_conn->tc_SND_NXT - tcp_conn->tc_SND_UNA,
+			tcp_conn->tc_rcv_wnd,
+			tcp_conn->tc_snd_cwnd - tcp_conn->tc_SND_UNA,
+			tcp_conn->tc_snd_cthresh);
+	}
+
+	printf("\n");
+
+	if (!verbose || no_verbose)
+		return;
+	rtt= tcp_conn->tc_rtt;
+	artt= tcp_conn->tc_artt;
+	drtt= tcp_conn->tc_drtt;
+	printf("\tmss %u, mtu %u%s, rtt %.3f (%.3f+%d*%.3f) s\n",
+		tcp_conn->tc_max_mtu-IP_TCP_MIN_HDR_SIZE,
+		tcp_conn->tc_mtu,
+		(tcp_conn->tc_flags & TCF_PMTU) ? "" : " (no PMTU)",
+		rtt/(HZ+0.0),
+		artt/(HZ+0.0)/TCP_RTT_SCALE, TCP_DRTT_MULT,
+		drtt/(HZ+0.0)/TCP_RTT_SCALE);
+	flags= tcp_conn->tc_flags;
+	printf("\tflags:");
+	if (!flags)
+		printf(" TCF_EMPTY");
+	if (flags & TCF_INUSE)
+		flags &= ~TCF_INUSE;
+	if (flags & TCF_FIN_RECV)
+	{
+		printf(" TCF_FIN_RECV");
+		flags &= ~TCF_FIN_RECV;
+	}
+	if (flags & TCF_RCV_PUSH)
+	{
+		printf(" TCF_RCV_PUSH");
+		flags &= ~TCF_RCV_PUSH;
+	}
+	if (flags & TCF_MORE2WRITE)
+	{
+		printf(" TCF_MORE2WRITE");
+		flags &= ~TCF_MORE2WRITE;
+	}
+	if (flags & TCF_SEND_ACK)
+	{
+		printf(" TCF_SEND_ACK");
+		flags &= ~TCF_SEND_ACK;
+	}
+	if (flags & TCF_FIN_SENT)
+	{
+		printf(" TCF_FIN_SENT");
+		flags &= ~TCF_FIN_SENT;
+	}
+	if (flags & TCF_BSD_URG)
+	{
+		printf(" TCF_BSD_URG");
+		flags &= ~TCF_BSD_URG;
+	}
+	if (flags & TCF_NO_PUSH)
+	{
+		printf(" TCF_NO_PUSH");
+		flags &= ~TCF_NO_PUSH;
+	}
+	if (flags & TCF_PUSH_NOW)
+	{
+		printf(" TCF_PUSH_NOW");
+		flags &= ~TCF_PUSH_NOW;
+	}
+	if (flags & TCF_PMTU)
+		flags &= ~TCF_PMTU;
+	if (flags)
+		printf(" 0x%x", flags);
+	printf("\n");
+	printf("\ttimer: ref %d, time %f, active %d\n",
+		tcp_conn->tc_transmit_timer.tim_ref,
+		(0.0+tcp_conn->tc_transmit_timer.tim_time-now)/HZ,
+		tcp_conn->tc_transmit_timer.tim_active);
+}
+
+void usage(void)
+{
+	fprintf(stderr, "Usage: %s [-anv]\n", prog_name);
+	exit(1);
+}
+
+/*
+ * $PchId: tcpstat.c,v 1.8 2005/01/30 01:04:38 philip Exp $
+ */
Index: /trunk/minix/commands/simple/tee.c
===================================================================
--- /trunk/minix/commands/simple/tee.c	(revision 9)
+++ /trunk/minix/commands/simple/tee.c	(revision 9)
@@ -0,0 +1,66 @@
+/* tee - pipe fitting			Author: Paul Polderman */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <minix/minlib.h>
+
+#define	MAXFD	18
+#define CHUNK_SIZE	4096
+
+int fd[MAXFD];
+
+_PROTOTYPE(int main, (int argc, char **argv));
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  char iflag = 0, aflag = 0;
+  char buf[CHUNK_SIZE];
+  int i, s, n;
+
+  argv++;
+  --argc;
+  while (argc > 0 && argv[0][0] == '-') {
+	switch (argv[0][1]) {
+	    case 'i':		/* Interrupt turned off. */
+		iflag++;
+		break;
+	    case 'a':		/* Append to outputfile(s), instead of
+			 * overwriting them. */
+		aflag++;
+		break;
+	    default:
+		std_err("Usage: tee [-i] [-a] [files].\n");
+		exit(1);
+	}
+	argv++;
+	--argc;
+  }
+  fd[0] = 1;			/* Always output to stdout. */
+  for (s = 1; s < MAXFD && argc > 0; --argc, argv++, s++) {
+	if (aflag && (fd[s] = open(*argv, O_RDWR)) >= 0) {
+		lseek(fd[s], 0L, SEEK_END);
+		continue;
+	} else {
+		if ((fd[s] = creat(*argv, 0666)) >= 0) continue;
+	}
+	std_err("Cannot open output file: ");
+	std_err(*argv);
+	std_err("\n");
+	exit(2);
+  }
+
+  if (iflag) signal(SIGINT, SIG_IGN);
+
+  while ((n = read(0, buf, CHUNK_SIZE)) > 0) {
+	for (i = 0; i < s; i++) write(fd[i], buf, n);
+  }
+
+  for (i = 0; i < s; i++)	/* Close all fd's */
+	close(fd[i]);
+  return(0);
+}
Index: /trunk/minix/commands/simple/term.c
===================================================================
--- /trunk/minix/commands/simple/term.c	(revision 9)
+++ /trunk/minix/commands/simple/term.c	(revision 9)
@@ -0,0 +1,539 @@
+/* term - terminal simulator		Author: Andy Tanenbaum */
+
+/* This program allows the user to turn a MINIX system into a dumb
+ * terminal to communicate with a remote computer through one of the ttys.
+ * It forks into two processes.  The parent sits in a tight loop copying
+ * from stdin to the tty.  The child sits in a tight loop copying from
+ * the tty to stdout.
+ *
+ * 2 Sept 88 BDE (Bruce D. Evans): Massive changes to make current settings the
+ * default, allow any file as the "tty", support fancy baud rates and remove
+ * references to and dependencies on modems and keyboards, so (e.g.)
+ * a local login on /dev/tty1 can do an external login on /dev/tty2.
+ *
+ * 3 Sept 88 BDE: Split parent again to main process copies from stdin to a
+ * pipe which is copied to the tty.  This stops a blocked write to the
+ * tty from hanging the program.
+ *
+ * 11 Oct 88 BDE: Cleaned up baud rates and parity stripping.
+ *
+ * 09 Oct 90 MAT (Michael A. Temari): Fixed bug where terminal isn't reset
+ * if an error occurs.
+ *
+ * Nov 90 BDE: Don't broadcast kill(0, SIGINT) since two or more of these
+ * in a row will kill the parent shell.
+ *
+ * 19 Oct 89 RW (Ralf Wenk): Adapted to MINIX ST 1.1 + RS232 driver. Split
+ * error into error_n and error. Added resetting of the terminal settings
+ * in error.
+ *
+ * 24 Nov 90 RW: Adapted to MINIX ST 1.5.10.2. Forked processes are now
+ * doing an exec to get a better performance. This idea is stolen from
+ * a terminal program written by Felix Croes.
+ *
+ * 01 May 91 RW: Merged the MINIX ST patches with Andys current version.
+ * Most of the 19 Oct 89 patches are deleted because they are already there.
+ *
+ * 10 Mar 96 KJB: Termios adaption, cleanup, command key interface.
+ *
+ * 27 Nov 96 KJB: Add -c flag that binds commands to keys.
+ *
+ * Example usage:
+ *	term			: baud, bits/char, parity from /dev/tty1
+ *	term 9600 7 even	: 9600 baud, 7 bits/char, even parity
+ *	term odd 300 7		:  300 baud, 7 bits/char, odd parity
+ *	term /dev/tty2		: use /dev/tty2 rather than /dev/tty1
+ *				: Any argument starting with "/" is
+ *				: taken as the communication device.
+ *	term 8 57600 /dev/tty2 -atdt4441234	: if an argument begins with
+ *						: - , the rest of that arg is
+ *						: sent to the modem as a
+ *						: dial string
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+
+#define CHUNK 1024		/* how much to read at once */
+
+char TERM_LINE[] = "/dev/modem";/* default serial port to use */
+
+				/* device lock file */
+char lockfile[] = "/usr/spool/locks/LK.iii.jjj.kkk";
+
+char *commdev;			/* communications device a.k.a. "modem". */
+int commfd;			/* open file no. for comm device */
+struct termios tccomm;		/* terminal parameters for commfd */
+struct termios tcstdin;		/* terminal parameters for stdin */
+struct termios tcsavestdin;	/* saved terminal parameters for stdin */
+
+/* Special key to get term's attention. */
+#define HOTKEY	'\035'		/* CTRL-] */
+
+struct param_s {
+  char *pattern;
+  unsigned value;
+  enum { BAD, BITS, PARITY, SPEED } type;
+} params[] = {
+  { "5",	CS5,		BITS	},
+  { "6",	CS6,		BITS	},
+  { "7",	CS7,		BITS	},
+  { "8",	CS8,		BITS	},
+
+  { "even",	PARENB,		PARITY	},
+  { "odd",	PARENB|PARODD,	PARITY	},
+
+  { "50",	B50,		SPEED	},
+  { "75",	B75,		SPEED	},
+  { "110",	B110,		SPEED	},
+  { "134",	B134,		SPEED	},
+  { "200",	B200,		SPEED	},
+  { "300",	B300,		SPEED	},
+  { "600",	B600,		SPEED	},
+  { "1200",	B1200,		SPEED	},
+  { "1800",	B1800,		SPEED	},
+  { "2400",	B2400,		SPEED	},
+  { "4800",	B4800,		SPEED	},
+  { "9600",	B9600,		SPEED	},
+  { "19200",	B19200,		SPEED	},
+  { "38400",	B38400,		SPEED	},
+  { "57600",	B57600,		SPEED	},
+  { "115200",	B115200,	SPEED	},
+  { "",		0,		BAD	},	/* BAD type to end list */
+};
+
+#define NIL ((char *) NULL)		/* tell(fd, ..., NIL) */
+
+_PROTOTYPE(int main, (int argc, char *argv[]));
+_PROTOTYPE(int isdialstr, (char *arg));
+_PROTOTYPE(void tell, (int fd, ...));
+_PROTOTYPE(void reader, (int on));
+_PROTOTYPE(void shell, (char *cmd));
+_PROTOTYPE(void lock_device, (char *device));
+_PROTOTYPE(void fatal, (char *label));
+_PROTOTYPE(void setnum, (char *s, int n));
+_PROTOTYPE(void set_uart, (int argc, char *argv[], struct termios *tcp));
+_PROTOTYPE(void set_raw, (struct termios *tcp));
+_PROTOTYPE(void quit, (int code));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i;
+  unsigned char key;
+  int candial;
+
+  for (i = 1; i < argc; ++i) {
+	if (argv[i][0] == '/') {
+		if (commdev != NULL) {
+			tell(2, "term: too many communication devices\n", NIL);
+			exit(1);
+		}
+		commdev = argv[i];
+	}
+  }
+  if (commdev == NULL) commdev = TERM_LINE;
+
+  /* Save tty attributes of the terminal. */
+  if (tcgetattr(0, &tcsavestdin) < 0) {
+	tell(2, "term: standard input is not a terminal\n", NIL);
+	exit(1);
+  }
+
+  lock_device(commdev);
+
+  commfd = open(commdev, O_RDWR);
+  if (commfd < 0) {
+	tell(2, "term: can't open ", commdev, ": ", strerror(errno), "\n", NIL);
+	quit(1);
+  }
+
+  /* Compute RAW modes of terminal and modem. */
+  if (tcgetattr(commfd, &tccomm) < 0) {
+	tell(2, "term: ", commdev, " is not a terminal\n", NIL);
+	quit(1);
+  }
+  signal(SIGINT, quit);
+  signal(SIGTERM, quit);
+  tcstdin = tcsavestdin;
+  set_raw(&tcstdin);
+  set_raw(&tccomm);
+  set_uart(argc, argv, &tccomm);
+  tcsetattr(0, TCSANOW, &tcstdin);
+  tcsetattr(commfd, TCSANOW, &tccomm);
+
+  /* Start a reader process to copy modem output to the screen. */
+  reader(1);
+
+  /* Welcome message. */
+  tell(1, "Connected to ", commdev,
+			", command key is CTRL-], type ^]? for help\r\n", NIL);
+
+  /* Dial. */
+  candial = 0;
+  for (i = 1; i < argc; ++i) {
+	if (!isdialstr(argv[i])) continue;
+	tell(commfd, argv[i] + 1, "\r", NIL);
+	candial = 1;
+  }
+
+  /* Main loop of the terminal simulator. */
+  while (read(0, &key, 1) == 1) {
+	if (key == HOTKEY) {
+		/* Command key typed. */
+		if (read(0, &key, 1) != 1) continue;
+
+		switch (key) {
+		default:
+			/* Added command? */
+			for (i = 1; i < argc; ++i) {
+				char *arg = argv[i];
+
+				if (arg[0] == '-' && arg[1] == 'c'
+							&& arg[2] == key) {
+					reader(0);
+					tcsetattr(0, TCSANOW, &tcsavestdin);
+					shell(arg+3);
+					tcsetattr(0, TCSANOW, &tcstdin);
+					reader(1);
+					break;
+				}
+			}
+			if (i < argc) break;
+
+			/* Unrecognized command, print list. */
+			tell(1, "\r\nTerm commands:\r\n",
+				" ? - this help\r\n",
+				candial ? " d - redial\r\n" : "",
+				" s - subshell (e.g. for file transfer)\r\n",
+				" h - hangup (+++ ATH)\r\n",
+				" b - send a break\r\n",
+				" q - exit term\r\n",
+				NIL);
+			for (i = 1; i < argc; ++i) {
+				char *arg = argv[i];
+				static char cmd[] = " x - ";
+
+				if (arg[0] == '-' && arg[1] == 'c'
+							&& arg[2] != 0) {
+					cmd[1] = arg[2];
+					tell(1, cmd, arg+3, "\r\n", NIL);
+				}
+			}
+			tell(1, "^] - send a CTRL-]\r\n\n",
+				NIL);
+			break;
+		case 'd':
+			/* Redial by sending the dial commands again. */
+			for (i = 1; i < argc; ++i) {
+				if (!isdialstr(argv[i])) continue;
+				tell(commfd, argv[i] + 1, "\r", NIL);
+			}
+			break;
+		case 's':
+			/* Subshell. */
+			reader(0);
+			tcsetattr(0, TCSANOW, &tcsavestdin);
+			shell(NULL);
+			tcsetattr(0, TCSANOW, &tcstdin);
+			reader(1);
+			break;
+		case 'h':
+			/* Hangup by using the +++ escape and ATH command. */
+			sleep(2);
+			tell(commfd, "+++", NIL);
+			sleep(2);
+			tell(commfd, "ATH\r", NIL);
+			break;
+		case 'b':
+			/* Send a break. */
+			tcsendbreak(commfd, 0);
+			break;
+		case 'q':
+			/* Exit term. */
+			quit(0);
+		case HOTKEY:
+			(void) write(commfd, &key, 1);
+			break;
+		}
+	} else {
+		/* Send keyboard input down the serial line. */
+		if (write(commfd, &key, 1) != 1) break;
+	}
+  }
+  tell(2, "term: nothing to copy from input to ", commdev, "?\r\n", NIL);
+  quit(1);
+}
+
+
+int isdialstr(char *arg)
+{
+/* True iff arg is the start of a dial string, i.e. "-at...". */
+
+  return (arg[0] == '-'
+  	&& (arg[1] == 'a' || arg[1] == 'A')
+  	&& (arg[2] == 't' || arg[2] == 'T'));
+}
+
+
+void tell(int fd, ...)
+{
+/* Write strings to file descriptor 'fd'. */
+  va_list ap;
+  char *s;
+
+  va_start(ap, fd);
+  while ((s = va_arg(ap, char *)) != NIL) write(fd, s, strlen(s));
+  va_end(ap);
+}
+
+
+void reader(on)
+int on;
+{
+/* Start or end a process that copies from the modem to the screen. */
+
+  static pid_t pid;
+  char buf[CHUNK];
+  ssize_t n, m, r;
+
+  if (!on) {
+	/* End the reader process (if any). */
+	if (pid == 0) return;
+	kill(pid, SIGKILL);
+	(void) waitpid(pid, (int *) NULL, 0);
+	pid = 0;
+	return;
+  }
+
+  /* Start a reader */
+  pid = fork();
+  if (pid < 0) {
+	tell(2, "term: fork() failed: ", strerror(errno), "\r\n", NIL);
+	quit(1);
+  }
+  if (pid == 0) {
+	/* Child: Copy from the modem to the screen. */
+
+	while ((n = read(commfd, buf, sizeof(buf))) > 0) {
+		m = 0;
+		while (m < n && (r = write(1, buf + m, n - m)) > 0) m += r;
+	}
+	tell(2, "term: nothing to copy from ", commdev, " to output?\r\n", NIL);
+	kill(getppid(), SIGTERM);
+	_exit(1);
+  }
+  /* One reader on the loose. */
+}
+
+
+void shell(char *cmd)
+{
+/* Invoke a subshell to allow one to run zmodem for instance.  Run sh -c 'cmd'
+ * instead if 'cmd' non-null.
+ */
+
+  pid_t pid;
+  char *shell, *sh0;
+  _PROTOTYPE(void (*isav), (int));
+  _PROTOTYPE(void (*qsav), (int));
+  _PROTOTYPE(void (*tsav), (int));
+
+  if (cmd == NULL) {
+	tell(1, "\nExit the shell to return to term, ",
+		commdev, " is open on file descriptor 9.\n", NIL);
+  }
+
+  if (cmd != NULL || (shell = getenv("SHELL")) == NULL) shell = "/bin/sh";
+  if ((sh0 = strrchr(shell, '/')) == NULL) sh0 = shell; else sh0++;
+
+  /* Start a shell */
+  pid = fork();
+  if (pid < 0) {
+	tell(2, "term: fork() failed: ", strerror(errno), "\n", NIL);
+	return;
+  }
+  if (pid == 0) {
+	/* Child: Exec the shell. */
+	setgid(getgid());
+	setuid(getuid());
+
+	if (commfd != 9) { dup2(commfd, 9); close(commfd); }
+
+	if (cmd == NULL) {
+		execl(shell, sh0, (char *) NULL);
+	} else {
+		execl(shell, sh0, "-c", cmd, (char *) NULL);
+	}
+	tell(2, "term: can't execute ", shell, ": ", strerror(errno), "\n",NIL);
+	_exit(1);
+  }
+  /* Wait for the shell to exit. */
+  isav = signal(SIGINT, SIG_IGN);
+  qsav = signal(SIGQUIT, SIG_IGN);
+  tsav = signal(SIGTERM, SIG_IGN);
+  (void) waitpid(pid, (int *) 0, 0);
+  (void) signal(SIGINT, isav);
+  (void) signal(SIGQUIT, qsav);
+  (void) signal(SIGTERM, tsav);
+  tell(1, "\n[back to term]\n", NIL);
+}
+
+
+void lock_device(device)
+char *device;
+{
+/* Lock a device by creating a lock file using SYSV style locking. */
+
+  struct stat stbuf;
+  unsigned int pid;
+  int fd;
+  int n;
+  int u;
+
+  if (stat(device, &stbuf) < 0) fatal(device);
+
+  if (!S_ISCHR(stbuf.st_mode)) {
+	tell(2, "term: ", device, " is not a character device\n", NIL);
+	exit(1);
+  }
+
+  /* Compute the lock file name. */
+  setnum(lockfile + 23, (stbuf.st_dev >> 8) & 0xFF);	/* FS major (why?) */
+  setnum(lockfile + 27, (stbuf.st_rdev >> 8) & 0xFF);	/* device major */
+  setnum(lockfile + 31, (stbuf.st_rdev >> 0) & 0xFF);	/* device minor */
+
+  /* Try to make a lock file and put my pid in it. */
+  u = umask(0);
+  for (;;) {
+	if ((fd = open(lockfile, O_RDONLY)) < 0) {
+		/* No lock file, try to lock it myself. */
+		if (errno != ENOENT) fatal(device);
+		if ((fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL, 0444)) < 0) {
+			if (errno == EEXIST) continue;
+			fatal(lockfile);
+		}
+		pid = getpid();
+		n = write(fd, &pid, sizeof(pid));
+		if (n < 0) {
+			n = errno;
+			(void) unlink(lockfile);
+			errno = n;
+			fatal(lockfile);
+		}
+		close(fd);
+		break;
+	} else {
+		/* Already there, but who owns it? */
+		n = read(fd, &pid, sizeof(pid));
+		if (n < 0) fatal(device);
+		close(fd);
+		if (n == sizeof(pid) && !(kill(pid, 0) < 0 && errno == ESRCH)) {
+			/* It is locked by a running process. */
+			tell(2, "term: ", device,
+				" is in use by another program\n", NIL);
+			if (getpgrp() == getpid()) sleep(3);
+			exit(1);
+		}
+		/* Stale lock. */
+		tell(1, "Removing stale lock ", lockfile, "\n", NIL);
+		if (unlink(lockfile) < 0 && errno != ENOENT) fatal(lockfile);
+	}
+  }
+  /* Lock achieved, but what if two terms encounters a stale lock at the same
+   * time?
+   */
+  umask(u);
+}
+
+
+void fatal(char *label)
+{
+  tell(2, "term: ", label, ": ", strerror(errno), "\n", NIL);
+  exit(1);
+}
+
+
+void setnum(char *s, int n)
+{
+/* Poke 'n' into string 's' backwards as three decimal digits. */
+  int i;
+
+  for (i = 0; i < 3; i++) { *--s = '0' + (n % 10); n /= 10; }
+}
+
+
+void set_uart(argc, argv, tcp)
+int argc;
+char *argv[];
+struct termios *tcp;
+{
+/* Set up the UART parameters. */
+
+  int i;
+  char *arg;
+  struct param_s *param;
+
+  /* Examine all the parameters and check for validity. */
+  for (i = 1; i < argc; ++i) {
+	arg = argv[i];
+	if (arg[0] == '/' || arg[0] == '-') continue;
+
+	/* Check parameter for legality. */
+	for (param = &params[0];
+	     param->type != BAD && strcmp(arg, param->pattern) != 0;
+	     ++param);
+	switch (param->type) {
+	    case BAD:
+		tell(2, "Invalid parameter: ", arg, "\n", NIL);
+		quit(1);
+		break;
+	    case BITS:
+		tcp->c_cflag &= ~CSIZE;
+		tcp->c_cflag |= param->value;
+		break;
+	    case PARITY:
+		tcp->c_cflag &= PARENB | PARODD;
+		tcp->c_cflag |= param->value;
+		break;
+	    case SPEED:
+		cfsetispeed(tcp, (speed_t) param->value);
+		cfsetospeed(tcp, (speed_t) param->value);
+		break;
+	}
+  }
+}
+
+
+void set_raw(tcp)
+struct termios *tcp;
+{
+  /* Set termios attributes for RAW mode. */
+
+  tcp->c_iflag &= ~(ICRNL|IGNCR|INLCR|IXON|IXOFF);
+  tcp->c_lflag &= ~(ICANON|IEXTEN|ISIG|ECHO|ECHONL);
+  tcp->c_oflag &= ~(OPOST);
+  tcp->c_cc[VMIN] = 1;
+  tcp->c_cc[VTIME] = 0;
+}
+
+
+void quit(code)
+int code;
+{
+/* Stop the reader process, reset the terminal, and exit. */
+  reader(0);
+  tcsetattr(0, TCSANOW, &tcsavestdin);
+  (void) unlink(lockfile);
+  exit(code);
+}
Index: /trunk/minix/commands/simple/termcap.c
===================================================================
--- /trunk/minix/commands/simple/termcap.c	(revision 9)
+++ /trunk/minix/commands/simple/termcap.c	(revision 9)
@@ -0,0 +1,163 @@
+/* termcap - print termcap settings	Author: Terrence Holm */
+
+#include <stdlib.h>
+#include <termcap.h>
+#include <stdio.h>
+
+#define  TC_BUFFER  1024	/* Size of termcap(3) buffer	*/
+
+/****************************************************************/
+/*								*/
+/*    termcap  [ type ]						*/
+/*								*/
+/*    Prints out all of the termcap capabilities as described	*/
+/*    in termcap(4). If "type" is not supplied then $TERM is	*/
+/*    used.							*/
+/*								*/
+/****************************************************************/
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void Print, (char *comment, char *name));
+_PROTOTYPE(void Error, (char *message, char *arg));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+
+  {
+  char *term;
+  char  buffer[ TC_BUFFER ];
+
+
+  /*  Check for an argument  */
+
+  if ( argc > 2 )
+    Error( "Usage:  %s  [ type ]\n", argv[0] );
+
+  if ( argc == 2 )
+    term = argv[1];
+  else
+    term = getenv( "TERM" );
+
+  if ( term == NULL )
+    Error( "termcap:  $TERM is not defined\n", "" );
+
+
+  /*  Read in the termcap entry  */
+
+  if ( tgetent( buffer, term ) != 1 )
+    Error( "termcap:  No termcap entry for %s\n", term );
+
+
+  /*  Print out the entry's contents  */
+
+  printf( "TERM = %s\n\n", term );
+
+  if ( tgetflag( "am" ) == 1 )
+    printf( "End of line wraps to next line   (am)\n" );
+
+  if ( tgetflag( "bs" ) == 1 )
+    printf( "Ctrl/H performs a backspace      (bs)\n" );
+
+  printf( "Number of columns                (co) = %d\n", tgetnum( "co" ) );
+  printf( "Number of lines                  (li) = %d\n", tgetnum( "li" ) );
+
+  Print( "Clear to end of line", 	  "ce" );
+  Print( "Clear to end of screen", 	  "cd" );
+  Print( "Clear the whole screen",	  "cl" );
+
+  Print( "Start \"stand out\" mode",	  "so" );
+  Print( "End \"stand out\" mode",	  "se" );
+  Print( "Start underscore mode",	  "us" );
+  Print( "End underscore mode",		  "ue" );
+  Print( "Start blinking mode",		  "mb" );
+  Print( "Start bold mode",		  "md" );
+  Print( "Start reverse mode",		  "mr" );
+  Print( "Return to normal mode",	  "me" );
+
+  Print( "Scroll backwards",		  "sr" );
+  Print( "Cursor motion",		  "cm" );
+
+  Print( "Up one line",			  "up" );
+  Print( "Down one line",		  "do" );
+  Print( "Left one space",		  "le" );
+  Print( "Right one space",		  "nd" );
+  Print( "Move to top left corner",	  "ho" );
+
+  Print( "Generated by \"UP\"",		  "ku" );
+  Print( "Generated by \"DOWN\"",	  "kd" );
+  Print( "Generated by \"LEFT\"",	  "kl" );
+  Print( "Generated by \"RIGHT\"",	  "kr" );
+  Print( "Generated by \"HOME\"",	  "kh" );
+  Print( "Generated by \"END\"",	  "k0" );
+  Print( "Generated by \"PGUP\"",	  "k1" );
+  Print( "Generated by \"PGDN\"",	  "k2" );
+  Print( "Generated by numeric \"+\"",	  "k3" );
+  Print( "Generated by numeric \"-\"",	  "k4" );
+  Print( "Generated by numeric \"5\"",	  "k5" );
+
+  return( 0 );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*    	Print( comment, name )					*/
+/*								*/
+/*    		If a termcap entry exists for "name", then	*/
+/*		print out "comment" and the entry. Control	*/
+/*		characters are printed as ^x.			*/
+/*								*/
+/****************************************************************/
+
+
+void Print( comment, name )
+  char *comment;
+  char *name;
+
+  {
+  char  entry[ 50 ];
+  char *p = entry;
+
+  if ( tgetstr( name, &p ) == NULL )
+    return;
+    
+  printf( "%-32s (%s) = ", comment, name );
+
+  for ( p = entry;  *p != '\0';  ++p )
+    if ( *p < ' ' )
+      printf( "^%c", *p + '@' );
+    else if ( *p == '\177' )
+      printf( "^?" );
+    else
+      putchar( *p );
+
+  putchar( '\n' );
+  }
+
+
+
+
+
+
+/****************************************************************/
+/*								*/
+/*    	Error( message, arg )					*/
+/*								*/
+/*    		Printf the "message" and abort.			*/
+/*								*/
+/****************************************************************/
+
+
+void Error( message, arg )
+  char *message;
+  char *arg;
+
+  {
+  fprintf( stderr, message, arg );
+  exit( 1 );
+  }
Index: /trunk/minix/commands/simple/tget.c
===================================================================
--- /trunk/minix/commands/simple/tget.c	(revision 9)
+++ /trunk/minix/commands/simple/tget.c	(revision 9)
@@ -0,0 +1,98 @@
+/*	tget 1.0 - get termcap values			Author: Kees J. Bot
+ *								6 Mar 1994
+ */
+#define nil 0
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termcap.h>
+
+void fputchar(int c)
+{
+	putchar(c);
+}
+
+void usage(void)
+{
+	fprintf(stderr,
+"Usage: tget [-flag id] [-num id] [-str id] [-goto col line] [[-echo] string]\n"
+		);
+	exit(-1);
+}
+
+void main(int argc, char **argv)
+{
+	char termbuf[1024];
+	char string[256], *pstr;
+	char *term;
+	int i;
+	int excode= 0;
+
+	if ((term= getenv("TERM")) == nil) {
+		fprintf(stderr, "tget: $TERM is not set\n");
+		exit(-1);
+	}
+
+	if (tgetent(termbuf, term) != 1) {
+		fprintf(stderr, "tget: no termcap entry for '%s'\n", term);
+		exit(-1);
+	}
+
+	for (i= 1; i < argc; i++) {
+		char *option= argv[i];
+		char *id;
+
+		if (option[0] != '-') {
+			fputs(option, stdout);
+			continue;
+		}
+
+		if (++i == argc) usage();
+		id= argv[i];
+
+		if (strcmp(option, "-flag") == 0) {
+			excode= tgetflag(id) ? 0 : 1;
+		} else
+		if (strcmp(option, "-num") == 0) {
+			int num;
+
+			if ((num= tgetnum(id)) == -1) {
+				excode= 1;
+			} else {
+				excode= 0;
+				printf("%d", num);
+			}
+		} else
+		if (strcmp(option, "-str") == 0) {
+			char *str;
+
+			if ((str= tgetstr(id, (pstr= string, &pstr))) == nil) {
+				excode= 1;
+			} else {
+				excode= 0;
+				tputs(str, 0, fputchar);
+			}
+		} else
+		if (strcmp(option, "-goto") == 0) {
+			char *cm;
+			int col, line;
+
+			col= atoi(id);
+			if (++i == argc) usage();
+			line= atoi(argv[i]);
+
+			if ((cm= tgetstr("cm", (pstr= string, &pstr))) == nil) {
+				excode= 1;
+			} else {
+				excode= 0;
+				tputs(tgoto(cm, col, line), 0, fputchar);
+			}
+		} else
+		if (strcmp(option, "-echo") == 0) {
+			fputs(id, stdout);
+		} else {
+			usage();
+		}
+	}
+	exit(excode);
+}
Index: /trunk/minix/commands/simple/time.c
===================================================================
--- /trunk/minix/commands/simple/time.c	(revision 9)
+++ /trunk/minix/commands/simple/time.c	(revision 9)
@@ -0,0 +1,161 @@
+/* time - time a command	Authors: Andy Tanenbaum & Michiel Huisjes */
+
+#define NEW	1
+
+#include <sys/types.h>
+#include <sys/times.h>
+#include <limits.h>
+#include <time.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <minix/minlib.h>
+#include <stdio.h>
+
+/* -DNEW prints time to 0.01 sec. */
+#ifdef NEW		
+#define HUNDREDTHS 1
+#endif
+
+char **args;
+char *name;
+
+int digit_seen;
+char a[] = "        . \0";
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void print_time, (clock_t t));
+_PROTOTYPE(void twin, (int n, char *p));
+_PROTOTYPE(void execute, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+
+  struct tms pre_buf, post_buf;
+  int status, pid;
+#if _VMD_EXT
+  struct timeval start_time, end_time;
+#else
+  struct tms dummy;
+  int start_time, end_time;
+#endif
+  clock_t real_time;
+
+  if (argc == 1) exit(0);
+
+  args = &argv[1];
+  name = argv[1];
+
+  /* Get real time at start of run. */
+#if _VMD_EXT
+  (void) sysutime(UTIME_TIMEOFDAY, &start_time);
+#else
+  start_time = times(&dummy);
+#endif
+
+  /* Fork off child. */
+  if ((pid = fork()) < 0) {
+	std_err("Cannot fork\n");
+	exit(1);
+  }
+  if (pid == 0) execute();
+
+  /* Parent is the time program.  Disable interrupts and wait. */
+  signal(SIGINT, SIG_IGN);
+  signal(SIGQUIT, SIG_IGN);
+
+  do {
+	times(&pre_buf);
+  } while (wait(&status) != pid);
+#if _VMD_EXT
+  (void) sysutime(UTIME_TIMEOFDAY, &end_time);
+  real_time = (end_time.tv_sec - start_time.tv_sec) * CLOCKS_PER_SEC
+	+ (end_time.tv_usec - start_time.tv_usec) * CLOCKS_PER_SEC / 1000000;
+#else
+  end_time = times(&dummy);
+  real_time = (end_time - start_time);
+#endif
+
+  if ((status & 0377) != 0) std_err("Command terminated abnormally.\n");
+  times(&post_buf);
+
+  /* Print results. -DNEW enables time on one line to 0.01 sec */
+#ifndef NEW
+  std_err("real ");
+  print_time(real_time);
+  std_err("\nuser ");
+  print_time(post_buf.tms_cutime - pre_buf.tms_cutime);
+  std_err("\nsys  ");
+  print_time(post_buf.tms_cstime - pre_buf.tms_cstime);
+  std_err("\n");
+#else
+  print_time(real_time);
+  std_err(" real");
+  print_time(post_buf.tms_cutime - pre_buf.tms_cutime);
+  std_err(" user");
+  print_time(post_buf.tms_cstime - pre_buf.tms_cstime);
+  std_err(" sys\n");
+#endif
+  return((status & 0377) ? -1 : (status >> 8));
+}
+
+void print_time(t)
+register clock_t t;
+{
+/* Print the time 't' in hours: minutes: seconds.  't' is in ticks. */
+
+  int hours, minutes, seconds, hundredths, i;
+
+  digit_seen = 0;
+  for (i = 0; i < 8; i++) a[i] = ' ';
+  hours = (int) (t / ((clock_t) 3600 * CLOCKS_PER_SEC));
+  t -= (clock_t) hours * 3600 * CLOCKS_PER_SEC;
+  minutes = (int) (t / ((clock_t) 60 * CLOCKS_PER_SEC));
+  t -= (clock_t) minutes * 60 * CLOCKS_PER_SEC;
+  seconds = (int) (t / CLOCKS_PER_SEC);
+  t -= (clock_t) seconds * CLOCKS_PER_SEC;
+  hundredths = (int) (t * 100 / CLOCKS_PER_SEC);
+
+  if (hours) {
+	twin(hours, &a[0]);
+	a[2] = ':';
+  }
+  if (minutes || digit_seen) {
+	twin(minutes, &a[3]);
+	a[5] = ':';
+  }
+  if (seconds || digit_seen)
+	twin(seconds, &a[6]);
+  else
+	a[7] = '0';
+  a[9] = hundredths / 10 + '0';
+#ifdef HUNDREDTHS		/* tenths used to be enough */
+  a[10] = hundredths % 10 + '0';
+#endif
+  std_err(a);
+}
+
+void twin(n, p)
+int n;
+char *p;
+{
+  char c1, c2;
+  c1 = (n / 10) + '0';
+  c2 = (n % 10) + '0';
+  if (digit_seen == 0 && c1 == '0') c1 = ' ';
+  *p++ = c1;
+  *p++ = c2;
+  if (n > 0) digit_seen = 1;
+}
+
+void execute()
+{
+  execvp(name, args);
+  std_err("Cannot execute ");
+  std_err(name);
+  std_err("\n");
+  exit(-1);
+}
Index: /trunk/minix/commands/simple/top.c
===================================================================
--- /trunk/minix/commands/simple/top.c	(revision 9)
+++ /trunk/minix/commands/simple/top.c	(revision 9)
@@ -0,0 +1,348 @@
+
+/* Author: Ben Gras <beng@few.vu.nl>  17 march 2006 */
+
+#define _MINIX 1
+#define _POSIX_SOURCE 1
+
+#include <stdio.h>
+#include <pwd.h>
+#include <curses.h>
+#include <timers.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <termcap.h>
+#include <termios.h>
+#include <time.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/ioc_tty.h>
+#include <sys/times.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/select.h>
+
+#include <minix/ipc.h>
+#include <minix/config.h>
+#include <minix/type.h>
+#include <minix/const.h>
+
+#include "../../servers/pm/mproc.h"
+#include "../../kernel/const.h"
+#include "../../kernel/proc.h"
+
+#define  TC_BUFFER  1024        /* Size of termcap(3) buffer    */
+#define  TC_STRINGS  200        /* Enough room for cm,cl,so,se  */
+
+char *Tclr_all;
+
+int print_memory(struct pm_mem_info *pmi)
+{
+        int h;
+        int largest_bytes = 0, total_bytes = 0; 
+        for(h = 0; h < _NR_HOLES; h++) {
+                if(pmi->pmi_holes[h].h_base && pmi->pmi_holes[h].h_len) {
+                        int bytes;
+                        bytes = pmi->pmi_holes[h].h_len << CLICK_SHIFT;
+                        if(bytes > largest_bytes) largest_bytes = bytes;
+                        total_bytes += bytes;
+                }
+        }
+
+	printf("Mem: %dK Free, %dK Contiguous Free\n",
+		total_bytes/1024, largest_bytes/1024);
+
+	return 1;
+}
+
+int print_load(double *loads, int nloads)
+{
+	int i;
+	printf("load averages: ");
+	for(i = 0; i < nloads; i++)
+		printf("%s %.2f", (i > 0) ? "," : "", loads[i]);
+	printf("\n");
+	return 1;
+}
+
+#define PROCS (NR_PROCS+NR_TASKS)
+
+int print_proc_summary(struct proc *proc)
+{
+	int p, alive, running, sleeping;
+
+	alive = running = sleeping = 0;
+
+	for(p = 0; p < PROCS; p++) {
+		if(p - NR_TASKS == IDLE)
+			continue;
+		if(proc[p].p_rts_flags & SLOT_FREE)
+			continue;
+		alive++;
+		if(proc[p].p_rts_flags & ~SLOT_FREE)
+			sleeping++;
+		else
+			running++;
+	}
+	printf("%d processes: %d running, %d sleeping\n",
+		alive, running, sleeping);
+	return 1;
+}
+
+static struct tp {
+	struct proc *p;
+	int ticks;
+} tick_procs[PROCS];
+
+int cmp_ticks(const void *v1, const void *v2)
+{
+	struct tp *p1 = (struct tp *) v1, *p2 = (struct tp *) v2;
+	if(p1->ticks < p2->ticks)
+		return 1;
+	if(p1->ticks > p2->ticks)
+		return -1;
+	if(p1->p->p_nr < p2->p->p_nr)
+		return -1;
+	if(p1->p->p_nr > p2->p->p_nr)
+		return 1;
+	return 0;
+}
+
+void print_procs(int maxlines,
+	struct proc *proc1, struct proc *proc2, int dt,
+	struct mproc *mproc)
+{
+	int p, nprocs, tot=0;
+	int idleticks = 0, kernelticks = 0, systemticks = 0;
+
+	if(dt < 1) return;
+
+	for(p = nprocs = 0; p < PROCS; p++) {
+		if(proc2[p].p_rts_flags & SLOT_FREE)
+			continue;
+		tick_procs[nprocs].p = proc2 + p;
+		if(proc1[p].p_endpoint == proc2[p].p_endpoint) {
+			tick_procs[nprocs].ticks =
+				proc2[p].p_user_time-proc1[p].p_user_time;
+		} else {
+			tick_procs[nprocs].ticks =
+				proc2[p].p_user_time;
+		}
+		if(p-NR_TASKS == IDLE) {
+			idleticks = tick_procs[nprocs].ticks;
+			continue;
+		}
+
+		/* Kernel task time, not counting IDLE */
+		if(proc2[p].p_nr < 0)
+			kernelticks += tick_procs[nprocs].ticks;
+		else if(mproc[proc2[p].p_nr].mp_procgrp == 0)
+			systemticks += tick_procs[nprocs].ticks;
+		nprocs++;
+	}
+
+	qsort(tick_procs, nprocs, sizeof(tick_procs[0]), cmp_ticks);
+
+	printf("CPU states: %6.2f%% user, %6.2f%% system, %6.2f%% kernel, %6.2f%% idle",
+		100.0*(dt-systemticks-kernelticks-idleticks)/dt,
+		100.0*systemticks/dt,
+		100.0*kernelticks/dt,
+		100.0*idleticks/dt);
+	printf("\n\n");
+	maxlines -= 2;
+
+	printf("  PID USERNAME PRI NICE   SIZE STATE   TIME     CPU COMMAND\n");
+	maxlines--;
+	for(p = 0; p < nprocs; p++) {
+		int euid = 0;
+		struct proc *pr;
+		int pnr, ticks;
+		char *name = "";
+		static struct passwd *who = NULL;
+		static int last_who = -1;
+
+		if(maxlines-- <= 0) break;
+
+		pnr = tick_procs[p].p->p_nr;
+		pr = tick_procs[p].p;
+		ticks = pr->p_user_time;
+		if(pnr >= 0) {
+			printf("%5d ", mproc[pnr].mp_pid);
+			euid = mproc[pnr].mp_effuid;
+			name = mproc[pnr].mp_name;
+		} else	{
+			printf("[%3d] ", pnr);
+			name = pr->p_name;
+		}
+		if(last_who != euid || !who) {
+			who = getpwuid(euid);
+			last_who = euid;
+		}
+
+		if(who && who->pw_name) printf("%-8s ", who->pw_name);
+		else if(pnr >= 0) printf("%8d ", mproc[pnr].mp_effuid);
+		else printf("         ");
+
+		printf(" %2d ", pr->p_priority);
+		if(pnr >= 0) {
+			printf(" %3d ", mproc[pnr].mp_nice);
+		} else printf("     ");
+		printf("%5dK",
+			((pr->p_memmap[T].mem_len + 
+			pr->p_memmap[D].mem_len) << CLICK_SHIFT)/1024);
+		printf("%6s", pr->p_rts_flags ? "" : "RUN");
+		printf(" %3d:%02d ", (ticks/HZ/60), (ticks/HZ)%60);
+
+		printf("%6.2f%% %s\n",
+			100.0*tick_procs[p].ticks/dt, name);
+	}
+}
+
+void showtop(int r)
+{
+#define NLOADS 3
+	double loads[NLOADS];
+	int nloads, i, p, lines = 0;
+	static struct proc prev_proc[PROCS], proc[PROCS];
+	struct winsize winsize;
+        static struct pm_mem_info pmi;
+	static int prev_uptime, uptime;
+	static struct mproc mproc[NR_PROCS];
+	struct tms tms;
+
+	uptime = times(&tms);
+
+	if(ioctl(STDIN_FILENO, TIOCGWINSZ, &winsize) != 0) {
+		perror("TIOCGWINSZ");
+		fprintf(stderr, "TIOCGWINSZ failed\n");
+		exit(1);
+	}
+
+        if(getsysinfo(PM_PROC_NR, SI_MEM_ALLOC, &pmi) < 0) {
+		fprintf(stderr, "getsysinfo() for SI_MEM_ALLOC failed.\n");
+		exit(1);;
+	}
+
+	if(getsysinfo(PM_PROC_NR, SI_KPROC_TAB, proc) < 0) {
+		fprintf(stderr, "getsysinfo() for SI_KPROC_TAB failed.\n");
+		exit(1);
+	}
+
+	if(getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc) < 0) {
+		fprintf(stderr, "getsysinfo() for SI_PROC_TAB failed.\n");
+		exit(1);
+	}
+
+	if((nloads = getloadavg(loads, NLOADS)) != NLOADS) {
+		fprintf(stderr, "getloadavg() failed - %d loads\n", nloads);
+		exit(1);
+	}
+
+
+	printf("%s", Tclr_all);
+
+	lines += print_load(loads, NLOADS);
+	lines += print_proc_summary(proc);
+	lines += print_memory(&pmi);
+
+	if(winsize.ws_row > 0) r = winsize.ws_row;
+
+	print_procs(r - lines - 2, prev_proc,
+		proc, uptime-prev_uptime, mproc);
+
+	memcpy(prev_proc, proc, sizeof(prev_proc));
+	prev_uptime = uptime;
+}
+
+void init(int *rows)
+{
+	char  *term;
+	static char   buffer[TC_BUFFER], strings[TC_STRINGS];
+	char *s = strings, *v;
+
+	*rows = 0;
+
+	if(!(term = getenv("TERM"))) {
+		fprintf(stderr, "No TERM set\n");
+		exit(1);
+	}
+
+	if ( tgetent( buffer, term ) != 1 ) {
+		fprintf(stderr, "tgetent failed for term %s\n", term);
+		exit(1);
+	}
+
+	if ( (Tclr_all = tgetstr( "cl", &s )) == NULL )
+		Tclr_all = "\f";
+
+	if((v = tgetstr ("li", &s)) != NULL)
+		sscanf(v, "%d", rows);
+	if(*rows < 1) *rows = 24;
+	if(!initscr()) {
+		fprintf(stderr, "initscr() failed\n");
+		exit(1);
+	}
+	cbreak();
+	nl();
+}
+
+void sigwinch(int sig) { }
+
+int main(int argc, char *argv[])
+{
+	int r, c, s = 0, orig;
+
+	init(&r);
+
+	while((c=getopt(argc, argv, "s:")) != EOF) {
+		switch(c) {
+			case 's':
+				s = atoi(optarg);
+				break;
+			default:
+				fprintf(stderr,
+					"Usage: %s [-s<secdelay>]\n", argv[0]);
+				return 1;
+		}
+	}
+
+	if(s < 1) 
+		s = 2;
+
+	/* Catch window size changes so display is updated properly right away. */
+	signal(SIGWINCH, sigwinch);
+
+	while(1) {
+		fd_set fds;
+		int ns;
+		struct timeval tv;
+		showtop(r);
+		tv.tv_sec = s;
+		tv.tv_usec = 0;
+
+		FD_ZERO(&fds);
+		FD_SET(STDIN_FILENO, &fds);
+		if((ns=select(STDIN_FILENO+1, &fds, NULL, NULL, &tv)) < 0
+			&& errno != EINTR) {
+			perror("select");
+			sleep(1);
+		}
+
+		if(ns > 0 && FD_ISSET(STDIN_FILENO, &fds)) {
+			char c;
+			if(read(STDIN_FILENO, &c, 1) == 1) {
+				switch(c) {
+					case 'q':
+						return 0;
+						break;
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
Index: /trunk/minix/commands/simple/touch.c
===================================================================
--- /trunk/minix/commands/simple/touch.c	(revision 9)
+++ /trunk/minix/commands/simple/touch.c	(revision 9)
@@ -0,0 +1,248 @@
+/* Touch - change file access and modification times.
+ *
+ * Usage: see end of file
+ *
+ * Conforms to P1003.2 draft 10, sec. 4.62, except that time values
+ * are not checked for validity, but passed on to mktime, so that
+ * 9301990000 will refer to Apr. 9th 1993. As a side effect, leap
+ * seconds are not handled correctly.
+ *
+ * Authors: Original author unknown. Rewritten for POSIX by 
+ *	Peter Holzer (hp@vmars.tuwien.ac.at).
+ *
+ * $Id: touch.c,v 1.1.1.1 2005/04/21 14:55:35 beng Exp $
+ * $Log: touch.c,v $
+ * Revision 1.1.1.1  2005/04/21 14:55:35  beng
+ * Initial import of pre-3.0.1
+ *
+ * Revision 1.1.1.1  2005/04/20 13:33:47  beng
+ * Initial import of minix 2.0.4
+ *
+ * Revision 1.8  1994/03/17  21:39:19  hjp
+ * fixed bug with 4-digit years
+ *
+ * Revision 1.7  1994/03/15  00:43:27  hjp
+ * Changes from kjb (vmd 1.6.25.1):
+ * fixed exit code
+ * nonstandard flag 0 to make file very old
+ *
+ * Revision 1.6  1994/02/12  17:26:33  hjp
+ * fixed -a and -m flags
+ *
+ * Revision 1.5  1994/02/12  16:04:13  hjp
+ * fixed bug when -t argument was not given
+ * removed debugging code
+ * run through pretty to get Minix layout
+ *
+ * Revision 1.4  1994/02/07  21:23:11  hjp
+ * POSIXified.
+ *
+ */
+
+#define _POSIX_C_SOURCE 2	/* getopt */
+#include <assert.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <utime.h>
+
+#define val2(string) ((string)[0] * 10 + (string)[1] - '0' * 11)
+#define val4(string) (val2(string) * 100 + val2(string + 2))
+
+typedef enum {
+  OLD, NEW
+} formatT;
+
+char *cmnd;
+int no_creat = 0;
+unsigned int to_change = 0;
+#	define ATIME	1
+#	define MTIME	2
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(int doit, (char *name, struct utimbuf tvp));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(time_t parsetime, (const char *string, formatT format));
+
+time_t parsetime(string, format)
+const char *string;
+formatT format;
+{
+  struct tm tm;
+  time_t touchtime;
+  size_t l;
+
+  l = strspn(string, "0123456789");
+  if (l % 2 == 1) return -1;
+  if (string[l] != '\0' && (string[l] != '.' || format == OLD)) {
+	return -1;
+  }
+  if (format == OLD) {
+	if (l == 10) {
+		/* Last two digits are year */
+		tm.tm_year = val2(string + 8);
+		if (tm.tm_year <= 68) tm.tm_year += 100;
+	} else if (l == 8) {
+		time(&touchtime);
+		tm = *localtime(&touchtime);
+	} else {
+		return -1;
+	}
+  } else {
+	if (l == 12) {
+		/* First four digits are year */
+		tm.tm_year = val4(string) - 1900;
+		string += 4;
+	} else if (l == 10) {
+		/* First two digits are year */
+		tm.tm_year = val2(string);
+		if (tm.tm_year <= 68) tm.tm_year += 100;
+		string += 2;
+	} else if (l == 8) {
+		time(&touchtime);
+		tm = *localtime(&touchtime);
+	} else {
+		return -1;
+	}
+  }
+  tm.tm_mon = val2(string) - 1;
+  string += 2;
+  tm.tm_mday = val2(string);
+  string += 2;
+  tm.tm_hour = val2(string);
+  string += 2;
+  tm.tm_min = val2(string);
+  string += 2;
+  if (format == NEW && string[0] == '.') {
+	if (isdigit(string[1]) && isdigit(string[2]) &&
+	    string[3] == '\0') {
+		tm.tm_sec = val2(string + 1);
+	} else {
+		return -1;
+	}
+  } else {
+	tm.tm_sec = 0;
+  }
+  tm.tm_isdst = -1;
+  touchtime = mktime(&tm);
+  return touchtime;
+}
+
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  time_t auxtime;
+  struct stat sb;
+  int c;
+  struct utimbuf touchtimes;
+  int fail = 0;
+
+  cmnd = argv[0];
+  auxtime = time((time_t *) NULL);
+  touchtimes.modtime = auxtime;
+  touchtimes.actime = auxtime;
+
+  while ((c = getopt(argc, argv, "r:t:acm0")) != EOF) {
+	switch (c) {
+	    case 'r':
+		if (stat(optarg, &sb) == -1) {
+			fprintf(stderr, "%s: cannot stat %s: %s\n",
+				cmnd, optarg, strerror(errno));
+			exit(1);
+		}
+		touchtimes.modtime = sb.st_mtime;
+		touchtimes.actime = sb.st_atime;
+		break;
+	    case 't':
+		auxtime = parsetime(optarg, NEW);
+		if (auxtime == (time_t) - 1) usage();
+		touchtimes.modtime = auxtime;
+		touchtimes.actime = auxtime;
+		break;
+	    case 'a':	to_change |= ATIME;	break;
+	    case 'm':	to_change |= MTIME;	break;
+	    case 'c':	no_creat = 1;	break;
+	    case '0':
+		touchtimes.modtime = touchtimes.actime = 0;
+		break;
+	    case '?':	usage();	break;
+	    default:	assert(0);
+	}
+  }
+  if (to_change == 0) {
+	to_change = ATIME | MTIME;
+  }
+  if (optind == argc) usage();
+
+  /* Now check for old style time argument */
+  if (strcmp(argv[optind - 1], "--") != 0 &&
+      (auxtime = parsetime(argv[optind], OLD)) != (time_t) - 1) {
+	touchtimes.modtime = auxtime;
+	touchtimes.actime = auxtime;
+	optind++;
+	if (optind == argc) usage();
+  }
+  while (optind < argc) {
+	if (doit(argv[optind], touchtimes) > 0) {
+		fprintf(stderr, "%s: cannot touch %s: %s\n",
+			cmnd, argv[optind], strerror(errno));
+		fail = 1;
+	}
+	optind++;
+  }
+  return fail ? 1 : 0;
+}
+
+
+int doit(name, tvp)
+char *name;
+struct utimbuf tvp;
+{
+  int fd;
+  struct stat sb;
+
+  if (to_change != (ATIME | MTIME)) {
+
+	if (stat(name, &sb) != -1) {
+		if (!(to_change & ATIME)) {
+			tvp.actime = sb.st_atime;
+		} else {
+			tvp.modtime = sb.st_mtime;
+		}
+	}
+  }
+  if (utime(name, &tvp) == 0) return 0;
+  if (errno != ENOENT) return 1;
+  if (no_creat == 1) return 0;
+  if ((fd = creat(name, 0666)) >= 0) {
+	if (fstat(fd, &sb) != -1) {
+		if (!(to_change & ATIME)) {
+			tvp.actime = sb.st_atime;
+		} else {
+			tvp.modtime = sb.st_mtime;
+		}
+	} else {
+		assert(0);
+	}
+	close(fd);
+	if (utime(name, &tvp) == 0) return 0;
+  }
+  return 1;
+}
+
+
+void usage()
+{
+  fprintf(stderr, "Usage: %s [-c] [-a] [-m] [-r file] [-t [CC[YY]]MMDDhhmm[.ss]] "
+	"[MMDDhhmm[YY]] file...\n", cmnd);
+  exit(1);
+}
Index: /trunk/minix/commands/simple/tr.c
===================================================================
--- /trunk/minix/commands/simple/tr.c	(revision 9)
+++ /trunk/minix/commands/simple/tr.c	(revision 9)
@@ -0,0 +1,169 @@
+/* tr - translate characters		Author: Michiel Huisjes */
+/* Usage: tr [-cds] [string1 [string2]]
+ *	c: take complement of string1
+ *	d: delete input characters coded string1
+ *	s: squeeze multiple output characters of string2 into one character
+ */
+
+#define BUFFER_SIZE	1024
+#define ASCII		0377
+
+typedef char BOOL;
+#define TRUE	1
+#define FALSE	0
+
+#define NIL_PTR		((char *) 0)
+
+BOOL com_fl, del_fl, sq_fl;
+
+unsigned char output[BUFFER_SIZE], input[BUFFER_SIZE];
+unsigned char vector[ASCII + 1];
+BOOL invec[ASCII + 1], outvec[ASCII + 1];
+
+short in_index, out_index;
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void convert, (void));
+_PROTOTYPE(void map, (unsigned char *string1, unsigned char *string2));
+_PROTOTYPE(void expand, (char *arg, unsigned char *buffer));
+_PROTOTYPE(void complement, (unsigned char *buffer));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  register unsigned char *ptr;
+  int index = 1;
+  short i;
+
+  if (argc > 1 && argv[index][0] == '-') {
+	for (ptr = (unsigned char *) &argv[index][1]; *ptr; ptr++) {
+		switch (*ptr) {
+		    case 'c':	com_fl = TRUE;	break;
+		    case 'd':	del_fl = TRUE;	break;
+		    case 's':	sq_fl = TRUE;	break;
+		    default:
+			write(2,"Usage: tr [-cds] [string1 [string2]].\n", 38);
+			exit(1);
+		}
+	}
+	index++;
+  }
+  for (i = 0; i <= ASCII; i++) {
+	vector[i] = i;
+	invec[i] = outvec[i] = FALSE;
+  }
+
+  if (argv[index] != NIL_PTR) {
+	expand(argv[index++], input);
+	if (com_fl) complement(input);
+	if (argv[index] != NIL_PTR) expand(argv[index], output);
+	if (argv[index] != NIL_PTR) map(input, output);
+	for (ptr = input; *ptr; ptr++) invec[*ptr] = TRUE;
+	for (ptr = output; *ptr; ptr++) outvec[*ptr] = TRUE;
+  }
+  convert();
+  return(0);
+}
+
+void convert()
+{
+  short read_chars = 0;
+  short c, coded;
+  short last = -1;
+
+  for (;;) {
+	if (in_index == read_chars) {
+		if ((read_chars = read(0, (char *)input, BUFFER_SIZE)) <= 0) {
+			if (write(1, (char *)output, out_index) != out_index)
+				write(2, "Bad write\n", 10);
+			exit(0);
+		}
+		in_index = 0;
+	}
+	c = input[in_index++];
+	coded = vector[c];
+	if (del_fl && invec[c]) continue;
+	if (sq_fl && last == coded && outvec[coded]) continue;
+	output[out_index++] = last = coded;
+	if (out_index == BUFFER_SIZE) {
+		if (write(1, (char *)output, out_index) != out_index) {
+			write(2, "Bad write\n", 10);
+			exit(1);
+		}
+		out_index = 0;
+	}
+  }
+
+  /* NOTREACHED */
+}
+
+void map(string1, string2)
+register unsigned char *string1, *string2;
+{
+  unsigned char last;
+
+  while (*string1) {
+	if (*string2 == '\0')
+		vector[*string1] = last;
+	else
+		vector[*string1] = last = *string2++;
+	string1++;
+  }
+}
+
+void expand(arg, buffer)
+register char *arg;
+register unsigned char *buffer;
+{
+  int i, ac;
+
+  while (*arg) {
+	if (*arg == '\\') {
+		arg++;
+		i = ac = 0;
+		if (*arg >= '0' && *arg <= '7') {
+			do {
+				ac = (ac << 3) + *arg++ - '0';
+				i++;
+			} while (i < 4 && *arg >= '0' && *arg <= '7');
+			*buffer++ = ac;
+		} else if (*arg != '\0')
+			*buffer++ = *arg++;
+	} else if (*arg == '[') {
+		arg++;
+		i = *arg++;
+		if (*arg++ != '-') {
+			*buffer++ = '[';
+			arg -= 2;
+			continue;
+		}
+		ac = *arg++;
+		while (i <= ac) *buffer++ = i++;
+		arg++;		/* Skip ']' */
+	} else
+		*buffer++ = *arg++;
+  }
+}
+
+void complement(buffer)
+unsigned char *buffer;
+{
+  register unsigned char *ptr;
+  register short i, index;
+  unsigned char conv[ASCII + 2];
+
+  index = 0;
+  for (i = 1; i <= ASCII; i++) {
+	for (ptr = buffer; *ptr; ptr++)
+		if (*ptr == i) break;
+	if (*ptr == '\0') conv[index++] = i & ASCII;
+  }
+  conv[index] = '\0';
+  strcpy((char *)buffer, (char *)conv);
+}
Index: /trunk/minix/commands/simple/treecmp.c
===================================================================
--- /trunk/minix/commands/simple/treecmp.c	(revision 9)
+++ /trunk/minix/commands/simple/treecmp.c	(revision 9)
@@ -0,0 +1,327 @@
+/* treecmp - compare two trees		Author: Andy Tanenbaum */
+
+/* This program recursively compares two trees and reports on differences.
+ * It can be used, for example, when a project consists of a large number
+ * of files and directories.  When a new release (i.e., a new tree) has been
+ * prepared, the old and new tree can be compared to give a list of what has
+ * changed.  The algorithm used is that the second tree is recursively
+ * descended and for each file or directory found, the corresponding one in
+ * the other tree checked.  The two arguments are not completely symmetric
+ * because the second tree is descended, not the first one, but reversing
+ * the arguments will still detect all the differences, only they will be
+ * printed in a different order.  The program needs lots of stack space
+ * because routines with local arrays are called recursively. The call is
+ *    treecmp [-cv] old_dir new_dir
+ * The -v flag (verbose) prints the directory names as they are processed.
+ * The -c flag (changes) just prints the names of changed and new files.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define BUFSIZE 4096		/* size of file buffers */
+#define MAXPATH 128		/* longest acceptable path */
+#define DIRENTLEN 14		/* number of characters in a file name */
+
+struct dirstruct {		/* layout of a directory entry */
+  ino_t inum;
+  char fname[DIRENTLEN];
+};
+
+struct stat stat1, stat2;	/* stat buffers */
+
+char buf1[BUFSIZE];		/* used for comparing bufs */
+char buf2[BUFSIZE];		/* used for comparing bufs */
+
+int changes;			/* set on -c flag */
+int verbose;			/* set on -v flag */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void compare, (char *old, char *new));
+_PROTOTYPE(void regular, (char *old, char *new));
+_PROTOTYPE(void directory, (char *old, char *new));
+_PROTOTYPE(void check, (char *s, struct dirstruct *dp1, int ent1, char *new));
+_PROTOTYPE(void usage, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  char *p;
+
+  if (argc < 3 || argc > 4) usage();
+  p = argv[1];
+  if (argc == 4) {
+	if (*p != '-') usage();
+	p++;
+	if (*p == '\0') usage();
+	while (*p) {
+		if (*p == 'c') changes++;
+		if (*p == 'v') verbose++;
+		if (*p != 'c' && *p != 'v') usage();
+		p++;
+	}
+  }
+  if (argc == 3)
+	compare(argv[1], argv[2]);
+  else
+	compare(argv[2], argv[3]);
+
+  return(0);
+}
+
+void compare(old, new)
+char *old, *new;
+{
+/* This is the main comparision routine.  It gets two path names as arguments
+ * and stats them both.  Depending on the results, it calls other routines
+ * to compare directories or files.
+ */
+
+  int type1, type2;
+
+  if (stat(new, &stat1) < 0) {
+	/* The new file does not exist. */
+	if (changes == 0)
+		fprintf(stderr, "Cannot stat: %s\n", new);
+	else
+		printf("%s\n", new);
+	return;
+  }
+  if (stat(old, &stat2) < 0) {
+	/* The old file does not exist. */
+	if (changes == 0) 
+		fprintf(stderr, "Missing file: %s\n", old);
+	else
+		printf("%s\n", new);
+	return;
+  }
+
+  /* Examine the types of the files. */
+  type1 = stat1.st_mode & S_IFMT;
+  type2 = stat2.st_mode & S_IFMT;
+  if (type1 != type2) {
+	fprintf(stderr, "Type diff: %s and %s\n", new, old);
+	return;
+  }
+
+  /* The types are the same. */
+  switch (type1) {
+      case S_IFREG:	regular(old, new);	break;
+      case S_IFDIR:	directory(old, new);	break;
+      case S_IFCHR:	break;
+      case S_IFBLK:	break;
+      default:		fprintf(stderr, "Unknown file type %o\n", type1);
+  }
+  return;
+}
+
+void regular(old, new)
+char *old, *new;
+{
+/* Compare to regular files.  If they are different, complain. */
+
+  int fd1, fd2, n1, n2;
+  unsigned bytes;
+  long count;
+
+  if (stat1.st_size != stat2.st_size) {
+	if (changes == 0)
+		printf("Size diff: %s and %s\n", new, old);
+	else
+		printf("%s\n", new);
+	return;
+  }
+
+  /* The sizes are the same.  We actually have to read the files now. */
+  fd1 = open(new, O_RDONLY);
+  if (fd1 < 0) {
+	fprintf(stderr, "Cannot open %s for reading\n", new);
+	return;
+  }
+  fd2 = open(old, O_RDONLY);
+  if (fd2 < 0) {
+	fprintf(stderr, "Cannot open %s for reading\n", old);
+	return;
+  }
+  count = stat1.st_size;
+  while (count > 0L) {
+	bytes = (unsigned) (count > BUFSIZE ? BUFSIZE : count);	/* rd count */
+	n1 = read(fd1, buf1, bytes);
+	n2 = read(fd2, buf2, bytes);
+	if (n1 != n2) {
+		if (changes == 0)
+			printf("Length diff: %s and %s\n", new, old);
+		else
+			printf("%s\n", new);
+		close(fd1);
+		close(fd2);
+		return;
+	}
+
+	/* Compare the buffers. */
+	if (memcmp((void *) buf1, (void *) buf2, (size_t) n1) != 0) {
+		if (changes == 0)
+			printf("File diff: %s and %s\n", new, old);
+		else
+			printf("%s\n", new);
+		close(fd1);
+		close(fd2);
+		return;
+	}
+	count -= n1;
+  }
+  close(fd1);
+  close(fd2);
+}
+
+void directory(old, new)
+char *old, *new;
+{
+/* Recursively compare two directories by reading them and comparing their
+ * contents.  The order of the entries need not be the same.
+ */
+
+  int fd1, fd2, n1, n2, ent1, ent2, i, used1 = 0, used2 = 0;
+  char *dir1buf, *dir2buf;
+  char name1buf[MAXPATH], name2buf[MAXPATH];
+  struct dirstruct *dp1, *dp2;
+  unsigned dir1bytes, dir2bytes;
+
+  /* Allocate space to read in the directories */
+  dir1bytes = (unsigned) stat1.st_size;
+  dir1buf = (char *)malloc((size_t)dir1bytes);
+  if (dir1buf == 0) {
+	fprintf(stderr, "Cannot process directory %s: out of memory\n", new);
+	return;
+  }
+  dir2bytes = (unsigned) stat2.st_size;
+  dir2buf = (char *)malloc((size_t)dir2bytes);
+  if (dir2buf == 0) {
+	fprintf(stderr, "Cannot process directory %s: out of memory\n", old);
+	free(dir1buf);
+	return;
+  }
+
+  /* Read in the directories. */
+  fd1 = open(new, O_RDONLY);
+  if (fd1 > 0) n1 = read(fd1, dir1buf, dir1bytes);
+  if (fd1 < 0 || n1 != dir1bytes) {
+	fprintf(stderr, "Cannot read directory %s\n", new);
+	free(dir1buf);
+	free(dir2buf);
+	if (fd1 > 0) close(fd1);
+	return;
+  }
+  close(fd1);
+
+  fd2 = open(old, O_RDONLY);
+  if (fd2 > 0) n2 = read(fd2, dir2buf, dir2bytes);
+  if (fd2 < 0 || n2 != dir2bytes) {
+	fprintf(stderr, "Cannot read directory %s\n", old);
+	free(dir1buf);
+	free(dir2buf);
+	close(fd1);
+	if (fd2 > 0) close(fd2);
+	return;
+  }
+  close(fd2);
+
+  /* Linearly search directories */
+  ent1 = dir1bytes / sizeof(struct dirstruct);
+  dp1 = (struct dirstruct *) dir1buf;
+  for (i = 0; i < ent1; i++) {
+	if (dp1->inum != 0) used1++;
+	dp1++;
+  }
+
+  ent2 = dir2bytes / sizeof(struct dirstruct);
+  dp2 = (struct dirstruct *) dir2buf;
+  for (i = 0; i < ent2; i++) {
+	if (dp2->inum != 0) used2++;
+	dp2++;
+  }
+
+  if (verbose) printf("Directory %s: %d entries\n", new, used1);
+
+  /* Check to see if any entries in dir2 are missing from dir1. */
+  dp1 = (struct dirstruct *) dir1buf;
+  dp2 = (struct dirstruct *) dir2buf;
+  for (i = 0; i < ent2; i++) {
+	if (dp2->inum == 0 || strcmp(dp2->fname, ".") == 0 ||
+					    strcmp(dp2->fname, "..") == 0) {
+		dp2++;
+		continue;
+	}
+	check(dp2->fname, dp1, ent1, new);
+	dp2++;
+  }
+
+  /* Recursively process all the entries in dir1. */
+  dp1 = (struct dirstruct *) dir1buf;
+  for (i = 0; i < ent1; i++) {
+	if (dp1->inum == 0 || strcmp(dp1->fname, ".") == 0 ||
+	    strcmp(dp1->fname, "..") == 0) {
+		dp1++;
+		continue;
+	}
+	if (strlen(new) + DIRENTLEN >= MAXPATH) {
+		fprintf(stderr, "Path too long: %s\n", new);
+		free(dir1buf);
+		free(dir2buf);
+		return;
+	}
+	if (strlen(old) + DIRENTLEN >= MAXPATH) {
+		fprintf(stderr, "Path too long: %s\n", old);
+		free(dir1buf);
+		free(dir2buf);
+		return;
+	}
+	strcpy(name1buf, old);
+	strcat(name1buf, "/");
+	strncat(name1buf, dp1->fname, (size_t)DIRENTLEN);
+	strcpy(name2buf, new);
+	strcat(name2buf, "/");
+	strncat(name2buf, dp1->fname, (size_t)DIRENTLEN);
+
+	/* Here is the recursive call to process an entry. */
+	compare(name1buf, name2buf);	/* recursive call */
+	dp1++;
+  }
+
+  free(dir1buf);
+  free(dir2buf);
+}
+
+void check(s, dp1, ent1, new)
+char *s;
+struct dirstruct *dp1;
+int ent1;
+char *new;
+{
+/* See if the file name 's' is present in the directory 'dirbuf'. */
+  int i;
+  char file[DIRENTLEN+1];
+
+  for (i = 0; i < ent1; i++) {
+	if (strncmp(dp1->fname, s, (size_t)DIRENTLEN) == 0) return;
+	dp1++;
+  }
+  if (changes == 0) {
+	strncpy(file, s, DIRENTLEN);
+	file[DIRENTLEN] = '\0';
+	printf("Missing file: %s/%s\n", new, file);
+  }
+	
+}
+
+void usage()
+{
+  printf("Usage: treecmp [-cv] old_dir new_dir\n");
+  exit(1);
+}
Index: /trunk/minix/commands/simple/truncate.c
===================================================================
--- /trunk/minix/commands/simple/truncate.c	(revision 9)
+++ /trunk/minix/commands/simple/truncate.c	(revision 9)
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2000 Sheldon Hearn <sheldonh@FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static off_t	parselength(char *, off_t *);
+static void	usage(void);
+
+static int	no_create;
+static int	do_relative;
+static int	do_refer;
+static int	got_size;
+
+int
+main(int argc, char **argv)
+{
+	struct stat	sb;
+	mode_t	omode;
+	off_t	oflow, rsize, sz, tsize;
+	int	ch, error, fd, oflags;
+	char   *fname, *rname;
+
+	rsize = tsize = 0;
+	error = 0;
+	rname = NULL;
+	while ((ch = getopt(argc, argv, "cr:s:")) != -1)
+		switch (ch) {
+		case 'c':
+			no_create = 1;
+			break;
+		case 'r':
+			do_refer = 1;
+			rname = optarg;
+			break;
+		case 's':
+			if (parselength(optarg, &sz) == -1) {
+				fprintf(stderr,
+				    "invalid size argument `%s'", optarg);
+				   exit(EXIT_FAILURE);
+				  }
+			if (*optarg == '+' || *optarg == '-')
+				do_relative = 1;
+			got_size = 1;
+			break;
+		default:
+			usage();
+			/* NOTREACHED */
+		}
+
+	argv += optind;
+	argc -= optind;
+
+	/*
+	 * Exactly one of do_refer or got_size must be specified.  Since
+	 * do_relative implies got_size, do_relative and do_refer are
+	 * also mutually exclusive.  See usage() for allowed invocations.
+	 */
+	if (do_refer + got_size != 1 || argc < 1)
+		usage();
+	if (do_refer) {
+		if (stat(rname, &sb) == -1) {
+			fprintf(stderr, "%s", rname);
+			exit(EXIT_FAILURE);
+		}
+		tsize = sb.st_size;
+	} else if (do_relative)
+		rsize = sz;
+	else
+		tsize = sz;
+
+	if (no_create)
+		oflags = O_WRONLY;
+	else
+		oflags = O_WRONLY | O_CREAT;
+	omode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+
+	while ((fname = *argv++) != NULL) {
+		if ((fd = open(fname, oflags, omode)) == -1) {
+			if (errno != ENOENT) {
+				perror(fname);
+				error++;
+			}
+			continue;
+		}
+		if (do_relative) {
+			if (fstat(fd, &sb) == -1) {
+				perror(fname);
+				error++;
+				continue;
+			}
+			oflow = sb.st_size + rsize;
+			if (oflow < (sb.st_size + rsize)) {
+				errno = EFBIG;
+				perror(fname);
+				error++;
+				continue;
+			}
+			tsize = oflow;
+		}
+		if (tsize < 0)
+			tsize = 0;
+
+		if (ftruncate(fd, tsize) == -1) {
+			perror(fname);
+			error++;
+			continue;
+		}
+
+		close(fd);
+	}
+
+	return error ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+/*
+ * Return the numeric value of a string given in the form [+-][0-9]+[GMK]
+ * or -1 on format error or overflow.
+ */
+static off_t
+parselength(char *ls, off_t *sz)
+{
+	off_t	length, oflow;
+	int	lsign;
+
+	length = 0;
+	lsign = 1;
+
+	switch (*ls) {
+	case '-':
+		lsign = -1;
+	case '+':
+		ls++;
+	}
+
+#define	ASSIGN_CHK_OFLOW(x, y)	if (x < y) return -1; y = x
+	/*
+	 * Calculate the value of the decimal digit string, failing
+	 * on overflow.
+	 */
+	while (isdigit(*ls)) {
+		oflow = length * 10 + *ls++ - '0';
+		ASSIGN_CHK_OFLOW(oflow, length);
+	}
+
+	switch (*ls) {
+	case 'G':
+	case 'g':
+		oflow = length * 1024;
+		ASSIGN_CHK_OFLOW(oflow, length);
+	case 'M':
+	case 'm':
+		oflow = length * 1024;
+		ASSIGN_CHK_OFLOW(oflow, length);
+	case 'K':
+	case 'k':
+		if (ls[1] != '\0')
+			return -1;
+		oflow = length * 1024;
+		ASSIGN_CHK_OFLOW(oflow, length);
+	case '\0':
+		break;
+	default:
+		return -1;
+	}
+
+	*sz = length * lsign;
+	return 0;
+}
+
+static void
+usage(void)
+{
+	fprintf(stderr, "%s\n%s\n",
+	    "usage: truncate [-c] -s [+|-]size[K|k|M|m|G|g] file ...",
+	    "       truncate [-c] -r rfile file ...");
+	exit(EXIT_FAILURE);
+}
Index: /trunk/minix/commands/simple/tsort.c
===================================================================
--- /trunk/minix/commands/simple/tsort.c	(revision 9)
+++ /trunk/minix/commands/simple/tsort.c	(revision 9)
@@ -0,0 +1,356 @@
+/* topo - topological sort		Author: Kent Williams */
+
+/*
+** topo - perform a topological sort of the output of lorder.
+**
+** Usage : topo [infile] [outfile]
+**
+** Author: Kent Williams (williams@umaxc.weeg.uiowa.edu)
+*/
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+typedef struct __v {
+    struct __v *next;   /* link list node                   */
+    int indegree,       /* number of edges into this vertex */
+        visited,        /* depth-first search visited flag  */
+        on_the_path,    /* used to find cycles              */
+        has_a_cycle;    /* true if a cycle at this vertex   */
+    struct __e *out;    /* outgoing edges from this vertex  */
+    char key[1];        /* name of this vertex              */
+} vertex;
+
+typedef struct __e {
+    struct __e *next;   /* link list node                   */
+    vertex *v;          /* vertex to which this edge goes   */
+} edge;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void *xmalloc, (size_t siz));
+_PROTOTYPE(edge *new_edge, (vertex *v));
+_PROTOTYPE(char *copyupto, (char *name, char *buf, int stop));
+_PROTOTYPE(int child_of, (vertex *parent, vertex *child));
+_PROTOTYPE(vertex *add_v, (char *s));
+_PROTOTYPE(void readin, (void));
+_PROTOTYPE(void pushname, (char *s));
+_PROTOTYPE(char *popname, (void));
+_PROTOTYPE(void topo, (void));
+_PROTOTYPE(void print_cycle, (vertex *parent, vertex *child));
+_PROTOTYPE(void dfs, (vertex *v));
+_PROTOTYPE(void check_cycles, (void));
+
+/*
+** xmalloc -- standard do or die malloc front end.
+*/
+void *
+xmalloc(siz)
+size_t siz;
+{
+    void *rval = (void *)malloc(siz);
+    if(rval == NULL) {
+        fputs("Out of memory.\n",stderr);
+        exit(1);
+    }
+    return rval;
+}
+
+/*
+** edge allocater.
+*/
+edge *
+new_edge(v)
+vertex *v;
+{
+    edge *rval;
+    rval = (edge *)xmalloc(sizeof(edge));
+    rval->v = v; return rval;
+}
+
+/*
+** copyupto - copy until you see the stop character.
+*/
+char *
+copyupto(name,buf,stop)
+char *name,*buf,stop;
+{
+    while(*buf != '\0' && *buf != stop)
+        *name++ = *buf++;
+    *name = '\0';
+    while(*buf != '\0' && isspace(*buf))
+        buf++;
+    return buf;
+}
+
+/*
+** find out if the vertex child is a child of the vertex parent.
+*/
+int
+child_of(parent,child)
+vertex *parent,*child;
+{
+    edge *e;
+    for(e = parent->out; e != NULL && e->v != child; e = e->next)
+        ;
+    return e == NULL ? 0 : 1;
+}
+
+/*
+** the vertex set.
+**
+** add_v adds a vertex to the set if it's not already there.
+*/
+vertex *vset = NULL;
+
+vertex *
+add_v(s)
+char *s;
+{
+    vertex *v,*last;
+    /*
+    ** go looking for this key in the vertex set.
+    */
+    for(last = v = vset; v != NULL && strcmp(v->key,s) != 0;
+        last = v, v = v->next)
+        ;
+    if(v != NULL) {
+        /*
+        ** use the move-to-front heuristic to keep this from being
+        ** an O(N^2) algorithm.
+        */
+        if(last != vset) {
+            last->next = v->next;
+            v->next = vset;
+            vset = v;
+        }
+        return v;
+    }
+
+    v = (vertex *)xmalloc(sizeof(vertex) + strlen(s));
+
+    v->out = NULL;
+    strcpy(v->key,s);
+    v->indegree =
+    v->on_the_path =
+    v->has_a_cycle =
+    v->visited = 0;
+    v->next = vset;
+    vset = v;
+    return v;
+}
+
+/*
+** readin -- read in the dependency pairs.
+*/
+void
+readin()
+{
+    static char buf[128];
+    static char name[64];
+    char *bp;
+    vertex *child,*parent;
+    edge *e;
+    while(fgets(buf,sizeof(buf),stdin) != NULL) {
+	bp = buf + strlen(buf);
+	if (bp > buf && bp[-1] == '\n') *--bp = 0;
+        bp = copyupto(name,buf,' ');
+        child = add_v(name);
+        parent = add_v(bp);
+        if(child != parent && !child_of(parent,child)) {
+            e = new_edge(child);
+            e->next = parent->out;
+            parent->out = e;
+            child->indegree++;
+        }
+    }
+}
+
+/*
+** the topological sort produces names of modules in reverse of
+** the order we want them in, so use a stack to hold the names
+** until we get them all, then pop them off to print them.
+*/
+struct name { struct name *next; char *s; }
+*namelist = NULL;
+
+void
+pushname(s)
+char *s;
+{
+    struct name *x = (struct name *)xmalloc(sizeof(struct name));
+    x->s = s;
+    x->next = namelist;
+    namelist = x;
+}
+
+char *
+popname() {
+    char *rval;
+    struct name *tmp;
+    if(namelist == NULL)
+        return NULL;
+    tmp = namelist;
+    rval = namelist->s;
+    namelist = namelist->next;
+    free(tmp);
+    return rval;
+}
+
+/*
+** topo - do a topological sort of the dependency graph.
+*/
+void topo() {
+    vertex *x = vset,*n;
+    edge *e;
+    vertex *outq = NULL,*tmp;
+#define insq(x) ((x->next = outq),(outq = x))
+#define deq() ((tmp = outq),(outq = outq->next),tmp)
+
+    /*
+    ** find all vertices that don't depend on any other vertices
+    ** Since it breaks the "next" links to insert x into the queue,
+    ** x->next is saved before insq, to resume the list traversal.
+    */
+    while (x != NULL) {
+	n = x->next;
+        if(x->indegree == 0) {
+            insq(x);
+            pushname(x->key);       
+        }
+	x = n;
+    }
+
+    /*
+    ** for each vertex V with indegree of zero,
+    **     for each edge E from vertex V
+    **        subtract one from the indegree of the vertex V'
+    **        pointed to by E.  If V' now has an indegree of zero,
+    **        add it to the set of vertices with indegree zero, and
+    **        push its name on the output stack.
+    */
+    while(outq != NULL) {
+        x = deq();
+        e = x->out;
+        while(e != NULL) {
+            if(--(e->v->indegree) == 0) {
+                insq(e->v);
+                pushname(e->v->key);
+            }
+            e = e->next;
+        }
+    }
+    
+    /*
+    ** print the vertex names in opposite of the order they were
+    ** encountered.
+    */
+    while(namelist != NULL)
+        puts(popname());
+}
+
+/*
+** print_cycle --
+** A cycle has been detected between parent and child.
+** Start with the child, and look at each of its edges for
+** the parent.
+**
+** We know a vertex is on the path from the child to the parent
+** because the depth-first search sets on_the_path true for each
+** vertex it visits.
+*/
+void
+print_cycle(parent,child)
+vertex *parent, *child;
+{
+    char *s;
+    vertex *x;
+    edge *e;
+    for(x = child; x != parent; ) {
+        pushname(x->key);
+        for(e = x->out; e != NULL; e = e->next) {
+            /*
+            ** stop looking for the path at the first node found
+            ** that's on the path.  Watch out for cycles already
+            ** detected, because if you follow an edge into a cycle,
+            ** you're stuck in an infinite loop!
+            */
+            if(e->v->on_the_path && !e->v->has_a_cycle) {
+                x = e->v;
+                break;
+            }
+        }
+    }
+    /*
+    ** print the name of the parent, and then names of each of the
+    ** vertices on the path from the child to the parent.
+    */
+    fprintf(stderr,"%s\n",x->key);
+    while((s = popname()) != NULL)
+        fprintf(stderr,"%s\n",s);
+}
+
+/*
+** depth first search for cycles in the dependency graph.
+** See "Introduction to Algorithms" by Udi Manber Addison-Wesley 1989
+*/
+void
+dfs(v)
+vertex *v;
+{
+    edge *e;
+
+    if(v->visited)      /* If you've been here before, don't go again! */
+        return;
+    v->visited++;
+    v->on_the_path++;   /* this node is on the path from the root. */
+
+    /*
+    ** depth-first search all outgoing edges.
+    */
+    for(e = v->out; e != NULL; e = e->next) {
+        if(!e->v->visited)
+            dfs(e->v);
+        if(e->v->on_the_path) {
+            fprintf(stderr,"cycle found between %s and %s\n",
+                v->key,e->v->key);
+            print_cycle(v,e->v);
+            v->has_a_cycle++;
+        }
+    }
+    v->on_the_path = 0;
+}
+
+/*
+** check cycles starts the recursive depth-first search from
+** each vertex in vset.
+*/
+void
+check_cycles()
+{
+    vertex *v;
+    for(v = vset; v != NULL; v = v->next)
+        dfs(v);
+}
+
+/*
+** main program.
+*/
+int main(argc,argv)
+int argc;
+char **argv;
+{
+    if(argc > 1 && freopen(argv[1],"r",stdin) == NULL) {
+        perror(argv[1]);
+        exit(0);
+    }
+    if(argc > 2 && freopen(argv[2],"w",stdout) == NULL) {
+        perror(argv[2]);
+        exit(0);
+    }
+    readin();
+    check_cycles();
+    topo();
+    return(0);
+}
Index: /trunk/minix/commands/simple/ttt.c
===================================================================
--- /trunk/minix/commands/simple/ttt.c	(revision 9)
+++ /trunk/minix/commands/simple/ttt.c	(revision 9)
@@ -0,0 +1,299 @@
+/* tic tac toe (noughts and crosses)		Author: Warren Toomey */
+
+/* Copyright 1988 by Warren Toomey	wkt@cs.adfa.oz.au[@uunet.uu.net]
+ *
+ * You may freely copy or distribute this code as long as this notice
+ * remains intact.
+ *
+ * You may modify this code, as long as this notice remains intact, and
+ * you add another notice indicating that the code has been modified.
+ *
+ * You may NOT sell this code or in any way profit from this code without
+ * prior agreement from the author.
+ */
+
+/* Compile with cc -o tic tic.c -lcurses -ltermcap */
+
+#include <stdlib.h>
+#include <time.h>
+
+#ifdef CURSES
+#include <curses.h>
+#endif
+
+#include <stdio.h>
+
+#ifndef CURSES
+#define printw printf
+#endif
+
+
+typedef struct {
+  int value;			/* The move returned by the    */
+  int path;			/* alphabeta consists of a value */
+} MOVE;				/* and an actual move (path)   */
+
+_PROTOTYPE(int main, (void));
+_PROTOTYPE(int stateval, (int board [], int whosemove));
+_PROTOTYPE(MOVE alphabeta, (int board [], int whosemove, int alpha, int beta));
+_PROTOTYPE(void draw, (int board []));
+_PROTOTYPE(void getmove, (int board []));
+_PROTOTYPE(int endofgame, (int board []));
+_PROTOTYPE(int randommove, (void));
+
+ /* Static evaluator. Returns 100 if we have 3 in a row -100 if they have 3
+  * in a row
+  * 
+  * Board is array of 9 ints, where 0=empty square 1=our move 4= their move
+  * 
+  * and board is indices	0 1 2 3 4 5 6 7 8 */
+
+
+int stateval(board, whosemove)
+int board[];
+int whosemove;
+{
+  static int row[8][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8},	/* Indices of 3in-a-rows */
+			{0, 3, 6}, {1, 4, 7}, {2, 5, 8},
+			{0, 4, 8}, {2, 4, 6}};
+
+  int temp;			/* Temp row results */
+  int i, j;			/* Loop counters */
+  int side;			/* Depth multiplier */
+  int win, lose;
+
+  if (whosemove == 1) {
+	win = 100;
+	lose = -100;
+	side = 1;
+  } else {
+	/* Multiply by -1 if */
+	win = -100;
+	lose = 100;
+	side = -1;
+  }				/* not out move */
+  for (i = 0; i < 8; i++) {	/* For every 3-in-a-row */
+	temp = 0;
+	for (j = 0; j < 3; j++)	/* Add up the board values */
+		temp += board[row[i][j]];
+
+	if (temp == 3) return(win);	/* We've got 3 in a row */
+	if (temp == 12) return (lose);	/* They've got 3 in a row */
+  }
+  return(0);			/* Finally return sum */
+}
+
+
+MOVE alphabeta(board, whosemove, alpha, beta)	/* Alphabeta: takes a board, */
+int board[];			/* whose move, alpha & beta cutoffs, */
+int whosemove;			/* and returns a move to make and */
+int alpha;			/* the value that the move has */
+int beta;
+{
+  MOVE result, successor;
+  int best_score, i, best_path, mademove;
+
+  result.value = stateval(board, whosemove);	/* Work out the board's */
+  /* Static value */
+  if ((result.value == 100) ||	/* If a win or loss already */
+      (result.value == -100))
+	return(result);	/* return the result */
+
+  best_score = beta;		/* Ok, set worst score */
+  mademove = 0;			/* to the beta cutoff */
+  for (i = 0; i < 9; i++) {
+	if (board[i] == 0) {	/* For all valid moves */
+		mademove = 1;
+		board[i] = whosemove;	/* make the move on board */
+		successor = alphabeta(board, 5 - whosemove, -best_score - 1, -alpha - 1);
+		/* Get value of the move */
+		board[i] = 0;	/* Take move back */
+		if (-successor.value > best_score) {	/* If a better score */
+			best_score = -successor.value;	/* update our score */
+			best_path = i;	/* and move */
+			if (best_score > alpha)
+				break;	/* If we've beaten alpha */
+		}		/* return immediately */
+	}
+  }
+  if (mademove) {
+	result.value = best_score;	/* Finally return best score */
+	result.path = best_path;/* and best move */
+  }
+  return(result);		/* If no move, return static result */
+}
+
+
+void draw(board)			/* Draw the board */
+int board[];
+{
+  int i, j, row;
+  static char out[] = " X  O";	/* Lookup table for character */
+
+  row = 6;
+#ifdef CURSES
+  move(row, 0);
+#endif
+  for (j = 0; j < 9; j += 3) {
+	printw(" %d | %d | %d     ", j, j + 1, j + 2);
+	for (i = 0; i < 3; i++) {
+		printw("%c ", out[board[j + i]]);
+		if (i < 2) printw("| ");
+	}
+	if (j < 4) {
+#ifdef CURSES
+		move(++row, 0);
+#else
+		printw("\n");
+#endif
+		printw("---+---+---   ---+---+---");
+	}
+#ifdef CURSES
+	move(++row, 0);
+#else
+	printw("\n");
+#endif
+  }
+#ifdef CURSES
+  refresh();
+#else
+  printw("\n");
+#endif
+}
+
+
+void getmove(board)			/* Get a player's move */
+int board[];
+{
+  int Move;
+  int ItemsRead;
+  char dumc;
+
+  do {
+	do {
+#ifdef CURSES
+		move(9, 40);
+		printw("Your move: ");	/* Prompt for move */
+		refresh();
+#else
+		printw("Your move: ");	/* Prompt for move */
+#endif
+		ItemsRead = scanf("%d", &Move);	/* Input the move */
+		if (ItemsRead == 0) scanf("%c", &dumc);	/* Remove the offending character */
+	}
+	while (ItemsRead != 1);
+  }
+  while (board[Move]);
+  board[Move] = 4;		/* If legal, add to board */
+  draw(board);			/* Draw the board */
+}
+
+
+int endofgame(board)		/* Determine end of the game */
+int board[];
+{
+  int eval;
+  int count;
+
+  eval = stateval(board, 1);
+#ifdef CURSES
+  move(20, 25);
+#endif
+  if (eval == 100) {
+	printw("I have beaten you.\n");
+	return(1);
+  }
+  if (eval == -100) {
+	printw("Bus error (core dumped)\n");
+	return(1);
+  }
+  count = 0;
+  for (eval = 0; eval < 9; eval++)
+	if (board[eval] != 0) count++;
+  if (count == 9) {
+	printw("A draw!\n");
+	return(1);
+  }
+#ifdef CURSES
+  refresh();
+#endif
+  return(0);
+}
+
+
+int randommove()
+{				/* Make an initial random move */
+  int i;
+
+  i = abs((int) time((long *) 0));
+  return(i % 9);
+}
+
+
+int main()
+{				/* The actual game */
+  int i, board[9];
+  char ch;
+  MOVE ourmove;
+
+  for (i = 0; i < 9; i++) board[i] = 0;	/* Initialise the board */
+#ifdef CURSES
+  initscr();
+  clear();
+  refresh();
+#endif
+  printw("                           TIC TAC TOE   \n\n");
+  printw("                        Your moves are 'O'\n");
+  printw("                         My moves are 'X'\n\n");
+#ifdef CURSES
+  move(5, 0);
+  printw("Do you wish to move first: ");
+  refresh();
+  while (scanf("%c", &ch) != 1);
+  move(5, 0);
+  printw("                         .......");	/* Kludge to get rid */
+  refresh();
+  move(5, 0);
+  printw("                                ");	/* of input letter */
+  refresh();
+#else
+  do
+	printw("Do you wish to move first: ");
+  while (scanf("%c", &ch) != 1);
+#endif
+  if ((ch != 'y') && (ch != 'Y')) {
+	i = randommove();	/* If we move first */
+	board[i] = 1;		/* make it random */
+#ifdef CURSES
+	move(7, 42);
+	printw("My move: %d\n", i);
+	refresh();
+#else
+	printw("My move: %d\n", i);
+#endif
+  }
+  draw(board);
+  getmove(board);
+
+  while (1) {
+	ourmove = alphabeta(board, 1, 99, -99);	/* Get a move for us;
+						 * return wins */
+	/* Immediately & ignore losses */
+	board[ourmove.path] = 1;/* and make it */
+#ifdef CURSES
+	move(7, 42);
+	printw("My move: %d\n", ourmove.path);
+	refresh();
+#else
+	printw("My move: %d\n", ourmove.path);
+#endif
+	draw(board);
+	if (endofgame(board)) break;	/* If end of game, exit */
+	getmove(board);		/* Get opponent's move */
+	if (endofgame(board)) break;	/* If end of game, exit */
+  }
+#ifdef CURSES
+  endwin();
+#endif
+  return(0);
+}
Index: /trunk/minix/commands/simple/tty.c
===================================================================
--- /trunk/minix/commands/simple/tty.c	(revision 9)
+++ /trunk/minix/commands/simple/tty.c	(revision 9)
@@ -0,0 +1,30 @@
+/* tty.c - Return tty name		Author: Freeman P. Pascal IV */
+
+/* Minor changes to make tty conform to POSIX1003.2 Draft10
+   Thomas Brupbacher (tobr@mw.lpc.ethz.ch)			*/
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+_PROTOTYPE(int main, (int argc, char **argv));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  char *tty_name;
+
+  tty_name = ttyname(STDIN_FILENO);
+  if ((argc == 2) && (!strcmp(argv[1], "-s")))
+	 /* Do nothing - shhh! we're in silent mode */ ;
+  else
+	puts((tty_name != NULL) ? tty_name : "not a tty");
+
+  if (isatty(STDIN_FILENO) == 0)
+	return(1);
+  else
+	return(0);
+}
Index: /trunk/minix/commands/simple/udpstat.c
===================================================================
--- /trunk/minix/commands/simple/udpstat.c	(revision 9)
+++ /trunk/minix/commands/simple/udpstat.c	(revision 9)
@@ -0,0 +1,300 @@
+/*
+udpstat.c
+
+Created:	March 2001 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+#define _MINIX_SOURCE
+#define _POSIX_C_SOURCE 2
+
+#include <inet/inet.h>
+#undef printf
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/svrctl.h>
+#ifndef __minix_vmd
+#include <sys/times.h>
+#endif
+#include <net/netlib.h>
+#include <net/gen/inet.h>
+#include <net/gen/netdb.h>
+#include <net/gen/socket.h>
+#include <minix/queryparam.h>
+
+#include <inet/generic/buf.h>
+#include <inet/generic/clock.h>
+#include <inet/generic/event.h>
+#include <inet/generic/type.h>
+#include <inet/generic/udp_int.h>
+
+char *prog_name;
+udp_fd_t udp_fd_table[UDP_FD_NR];
+udp_port_t *udp_port_table;
+udp_port_t *udp_port_tablep;
+size_t udp_port_table_s;
+size_t udp_port_table_rs;
+int udp_port_nr;
+char values[6 * sizeof(void *) + 3];
+char *valuesl= NULL;
+size_t v_size;
+int inclSel, numerical;
+
+void print_fd(int i, clock_t now);
+void usage(void);
+
+int main(int argc, char*argv[])
+{
+	char *udp_device;
+	int fd, i;
+	struct svrqueryparam qpar;
+	char *pval;
+	struct timeval uptime;
+	clock_t now;
+	int fl;
+	int a_flag, n_flag;
+
+	(prog_name=strrchr(argv[0], '/')) ? prog_name++ : (prog_name=argv[0]);
+
+	a_flag= 0;
+	n_flag= 0;
+	while ((fl= getopt(argc, argv, "?an")) != -1)
+	{
+		switch(fl)
+		{
+		case '?':
+			usage();
+		case 'a':
+			a_flag= 1;
+			break;
+		case 'n':
+			n_flag= 1;
+			break;
+		default:
+			fprintf(stderr, "%s: getopt failed: '%c'\n", 
+				prog_name, fl);
+			exit(1);
+		}
+	}
+	inclSel= !!a_flag;
+	numerical= !!n_flag;
+
+	udp_device= UDP_DEVICE;
+	if ((fd= open(udp_device, O_RDWR)) == -1)
+	{
+		fprintf(stderr, "%s: unable to open '%s': %s\n", prog_name,
+			udp_device, strerror(errno));
+		exit(1);
+	}
+
+	v_size= 2*sizeof(udp_fd_table)+1;
+	valuesl= realloc(valuesl, v_size);
+	if (!valuesl)
+	{
+		fprintf(stderr, "%s: unable to malloc %u bytes for valuesl\n",
+			prog_name, v_size);
+		exit(1);
+	}
+
+	qpar.param = "udp_fd_table";
+	qpar.psize = strlen(qpar.param);
+	qpar.value = valuesl;
+	qpar.vsize = v_size;
+	if (ioctl(fd, NWIOQUERYPARAM, &qpar) == -1)
+	{
+		fprintf(stderr, "%s: queryparam failed: %s\n", prog_name,
+			strerror(errno));
+		exit(1);
+	}
+	pval= valuesl;
+	if (paramvalue(&pval, udp_fd_table, sizeof(udp_fd_table)) !=
+		sizeof(udp_fd_table))
+	{
+		fprintf(stderr,
+	"%s: unable to decode the results from queryparam (udp_fd_table)\n",
+			prog_name);
+		exit(1);
+	}
+
+	/* Get address, size, and element size of the UDP port table */
+	qpar.param = "&udp_port_table,$udp_port_table,$udp_port_table[0]";
+	qpar.psize = strlen(qpar.param);
+	qpar.value = values;
+	qpar.vsize = sizeof(values);
+	if (ioctl(fd, NWIOQUERYPARAM, &qpar) == -1)
+	{
+		fprintf(stderr, "%s: queryparam failed: %s\n", prog_name,
+			strerror(errno));
+		exit(1);
+	}
+	pval= values;
+	if (paramvalue(&pval, &udp_port_tablep, sizeof(udp_port_tablep)) !=
+		sizeof(udp_port_tablep) ||
+		paramvalue(&pval, &udp_port_table_s, sizeof(udp_port_table_s))
+			!= sizeof(udp_port_table_s) ||
+		paramvalue(&pval, &udp_port_table_rs, sizeof(udp_port_table_rs))
+			!= sizeof(udp_port_table_rs))
+	{
+		fprintf(stderr,
+"%s: unable to decode the results from queryparam (&udp_port_table, ...)\n",
+			prog_name);
+		exit(1);
+	}
+
+	if (udp_port_table_rs != sizeof(udp_port_table[0]))
+	{
+		fprintf(stderr,
+	"%s: size mismatch in udp_port_table (different version of inet?)\n",
+			prog_name);
+		exit(1);
+	}
+	udp_port_nr= udp_port_table_s/udp_port_table_rs;
+	assert(udp_port_table_s == udp_port_nr*udp_port_table_rs);
+	udp_port_table= malloc(udp_port_table_s);
+	if (!udp_port_table)
+	{
+		fprintf(stderr,
+	"%s: unable to malloc %u bytes for udp_port_table\n",
+			prog_name, udp_port_table_s);
+		exit(1);
+	}
+	v_size= 2*udp_port_table_s+1;
+	valuesl= realloc(valuesl, v_size);
+	if (!valuesl)
+	{
+		fprintf(stderr, "%s: unable to malloc %u bytes for valuesl\n",
+			prog_name, v_size);
+		exit(1);
+	}
+
+	qpar.param = "udp_port_table";
+	qpar.psize = strlen(qpar.param);
+	qpar.value = valuesl;
+	qpar.vsize = v_size;
+	if (ioctl(fd, NWIOQUERYPARAM, &qpar) == -1)
+	{
+		fprintf(stderr, "%s: queryparam failed: %s\n", prog_name,
+			strerror(errno));
+		exit(1);
+	}
+	pval= valuesl;
+	if (paramvalue(&pval, udp_port_table, udp_port_table_s) !=
+		udp_port_table_s)
+	{
+		fprintf(stderr,
+	"%s: unable to decode the results from queryparam (udp_port_table)\n",
+			prog_name);
+		exit(1);
+	}
+
+	/* Get the uptime in clock ticks. */
+#ifdef __minix_vmd
+	if (sysutime(UTIME_UPTIME, &uptime) == -1)
+	{
+		fprintf(stderr, "%s: sysutime failed: %s\n", prog_name,
+			strerror(errno));
+		exit(1);
+	}
+	now= uptime.tv_sec * HZ + (uptime.tv_usec*HZ/1000000);
+#else	/* Minix 3 */
+	now= times(NULL);
+#endif
+
+	for (i= 0; i<UDP_FD_NR; i++)
+		print_fd(i, now);
+	exit(0);
+}
+
+void print_fd(int i, clock_t now)
+{
+	unsigned long nwuo_flags;
+	int port_nr;
+	udp_fd_t *udp_fd;
+	udp_port_t *udp_port;
+	char *locaddr_str, *remaddr_str;
+	struct hostent *hostent;
+	struct servent *servent;
+	nwio_udpopt_t uf_udpopt;
+
+	udp_fd= &udp_fd_table[i];
+	if (!(udp_fd->uf_flags & UFF_INUSE))
+		return;
+	uf_udpopt= udp_fd->uf_udpopt;
+	nwuo_flags= uf_udpopt.nwuo_flags;
+	if (((nwuo_flags & NWUO_LOCPORT_MASK) != NWUO_LP_SET) && !inclSel)
+		return;
+
+	port_nr= udp_fd->uf_port-udp_port_tablep;
+	udp_port= &udp_port_table[port_nr];
+	
+	printf("%3d", i);
+
+	if (nwuo_flags & NWUO_EN_LOC)
+	{
+		if (!numerical && (hostent=
+			gethostbyaddr((char *)&udp_port->up_ipaddr,
+			sizeof(ipaddr_t), AF_INET)) != NULL)
+		{
+			locaddr_str= hostent->h_name;
+		}
+		else
+			locaddr_str= inet_ntoa(udp_port->up_ipaddr);
+	}
+	else if (nwuo_flags & NWUO_EN_BROAD)
+		locaddr_str= "255.255.255.255";
+	else
+		locaddr_str= "0.0.0.0";
+
+	printf(" %s:", locaddr_str);
+
+	if ((nwuo_flags & NWUO_LOCPORT_MASK) != NWUO_LP_SEL &&
+		(nwuo_flags & NWUO_LOCPORT_MASK) != NWUO_LP_SET)
+	{
+		printf("*");
+	}
+	else if ((servent= getservbyport(uf_udpopt.nwuo_locport, "udp")) !=
+		NULL)
+	{
+		printf("%s", servent->s_name);
+	}
+	else
+		printf("%u", ntohs(uf_udpopt.nwuo_locport));
+
+	printf(" -> ");
+
+	if (!(nwuo_flags & NWUO_RA_SET))
+		remaddr_str= "*";
+	else if (!numerical &&
+		(hostent= gethostbyaddr((char *)&uf_udpopt.nwuo_remaddr,
+		sizeof(ipaddr_t), AF_INET)) != NULL)
+	{
+		remaddr_str= hostent->h_name;
+	}
+	else
+		remaddr_str= inet_ntoa(uf_udpopt.nwuo_remaddr);
+	printf("%s:", remaddr_str);
+
+	if (!(nwuo_flags & NWUO_RP_SET))
+		printf("*");
+	else if ((servent= getservbyport(uf_udpopt.nwuo_remport, "udp")) !=
+		NULL)
+	{
+		printf("%s", servent->s_name);
+	}
+	else
+		printf("%u", ntohs(uf_udpopt.nwuo_remport));
+	printf("\n");
+}
+
+void usage(void)
+{
+	fprintf(stderr, "Usage: %s [-a] [-n]\n", prog_name);
+	exit(1);
+}
+
+/*
+ * $PchId: udpstat.c,v 1.4 2005/01/30 01:04:57 philip Exp $
+ */
Index: /trunk/minix/commands/simple/umount.c
===================================================================
--- /trunk/minix/commands/simple/umount.c	(revision 9)
+++ /trunk/minix/commands/simple/umount.c	(revision 9)
@@ -0,0 +1,92 @@
+/* umount - unmount a file system		Author: Andy Tanenbaum */
+
+#define _MINIX 1		/* for proto of the non-POSIX umount() */
+#define _POSIX_SOURCE 1		/* for PATH_MAX from limits.h */
+
+#include <sys/types.h>
+#include <sys/svrctl.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <minix/minlib.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void update_mtab, (char *devname));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(void tell, (char *this));
+
+static char mountpoint[PATH_MAX+1];
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int sflag = 0;
+
+  while (argc > 1 && argv[1][0] == '-') {
+	char *opt = argv[1]+1;
+	while (*opt) if (*opt++ == 's') sflag = 1; else usage();
+	argc--;
+	argv++;
+  }
+  if (argc != 2) usage();
+  if ((sflag ? svrctl(MMSWAPOFF, NULL) : umount(argv[1])) < 0) {
+	if (errno == EINVAL)
+		std_err("Device not mounted\n");
+	else
+		perror("umount");
+	exit(1);
+  }
+  update_mtab(argv[1]);
+  tell(argv[1]);
+  tell(" unmounted");
+  if (*mountpoint != '\0') {
+	tell(" from ");
+	tell(mountpoint);
+  }
+  tell("\n");
+  return(0);
+}
+
+void update_mtab(devname)
+char *devname;
+{
+/* Remove an entry from /etc/mtab. */
+  int n;
+  char special[PATH_MAX+1], mounted_on[PATH_MAX+1], version[10], rw_flag[10];
+
+  if (load_mtab("umount") < 0) {
+	std_err("/etc/mtab not updated.\n");
+	exit(1);
+  }
+  while (1) {
+	n = get_mtab_entry(special, mounted_on, version, rw_flag);
+	if (n < 0) break;
+	if (strcmp(devname, special) == 0) {
+		strcpy(mountpoint, mounted_on);
+		continue;
+	}
+	(void) put_mtab_entry(special, mounted_on, version, rw_flag);
+  }
+  n = rewrite_mtab("umount");
+  if (n < 0) {
+	std_err("/etc/mtab not updated.\n");
+	exit(1);
+  }
+}
+
+void usage()
+{
+  std_err("Usage: umount [-s] special\n");
+  exit(1);
+}
+
+void tell(this)
+char *this;
+{
+  write(1, this, strlen(this));
+}
Index: /trunk/minix/commands/simple/uname.c
===================================================================
--- /trunk/minix/commands/simple/uname.c	(revision 9)
+++ /trunk/minix/commands/simple/uname.c	(revision 9)
@@ -0,0 +1,128 @@
+/*  uname - print system name			Author: Earl Chew */
+
+/* Print the following system information as returned by the uname()
+ * function:
+ *
+ *	system name		Minix
+ *	node name		waddles
+ *	release name		1.5
+ *	version			10
+ *	machine name		i86
+ *	arch			i86	(Minix specific)
+ */
+
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Define the uname components. */
+#define ALL	 ((unsigned) 0x1F)
+#define SYSNAME  ((unsigned) 0x01)
+#define NODENAME ((unsigned) 0x02)
+#define RELEASE  ((unsigned) 0x04)
+#define VERSION  ((unsigned) 0x08)
+#define U_MACHINE  ((unsigned) 0x10)
+#define ARCH     ((unsigned) 0x20)
+
+_PROTOTYPE(int main, (int argc, char **argv ));
+_PROTOTYPE(void print, (int fd, ... ));
+_PROTOTYPE(void usage, (void ));
+
+#ifdef __STDC__
+void print(int fd, ...)
+#else
+void print(fd)
+int fd;
+#endif
+{
+/* Print a sequence of strings onto the named channel. */
+  va_list argp;
+  char *p;
+
+  va_start(argp, fd);
+  while (1) {
+	p = va_arg(argp, char *);
+	if (p == (char *) NULL) break;
+	write(fd, p, strlen(p));
+  }
+  va_end(argp);
+}
+
+char *name;
+
+void usage()
+{
+  print(STDERR_FILENO, "Usage: ", name, " -snrvmpa\n", (char *) NULL);
+  exit(EXIT_FAILURE);
+}
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+  int info;
+  char *p;
+  struct utsname un;
+
+  name = strrchr(argv[0], '/');
+  if (name == NULL) name = argv[0]; else name++;
+
+  for (info = 0; argc > 1; argc--, argv++) {
+  	if (argv[1][0] == '-') {
+  		for (p = &argv[1][1]; *p; p++) {
+  			switch (*p) {
+				case 'a': info |= ALL;      break;
+				case 'm': info |= U_MACHINE;  break;
+				case 'n': info |= NODENAME; break;
+				case 'r': info |= RELEASE;  break;
+				case 's': info |= SYSNAME;  break;
+				case 'v': info |= VERSION;  break;
+				case 'p': info |= ARCH;     break;
+				default: usage();
+  			}
+		}
+	} else {
+		usage();
+	}
+  }
+
+  if (info == 0) info = strcmp(name, "arch") == 0 ? ARCH : SYSNAME;
+
+  if (uname(&un) != 0) {
+	print(STDERR_FILENO, "unable to determine uname values\n", (char *) NULL);
+	exit(EXIT_FAILURE);
+  }
+
+  if ((info & SYSNAME) != 0)
+	print(STDOUT_FILENO, un.sysname, (char *) NULL);
+  if ((info & NODENAME) != 0) {
+	if ((info & (SYSNAME)) != 0)
+		print(STDOUT_FILENO, " ", (char *) NULL);
+	print(STDOUT_FILENO, un.nodename, (char *) NULL);
+  }
+  if ((info & RELEASE) != 0) {
+	if ((info & (SYSNAME|NODENAME)) != 0)
+		print(STDOUT_FILENO, " ", (char *) NULL);
+	print(STDOUT_FILENO, un.release, (char *) NULL);
+  }
+  if ((info & VERSION) != 0) {
+	if ((info & (SYSNAME|NODENAME|RELEASE)) != 0)
+		print(STDOUT_FILENO, " ", (char *) NULL);
+	print(STDOUT_FILENO, un.version, (char *) NULL);
+  }
+  if ((info & U_MACHINE) != 0) {
+	if ((info & (SYSNAME|NODENAME|RELEASE|VERSION)) != 0)
+		print(STDOUT_FILENO, " ", (char *) NULL);
+	print(STDOUT_FILENO, un.machine, (char *) NULL);
+  }
+  if ((info & ARCH) != 0) {
+	if ((info & (SYSNAME|NODENAME|RELEASE|VERSION|U_MACHINE)) != 0)
+		print(STDOUT_FILENO, " ", (char *) NULL);
+	print(STDOUT_FILENO, un.arch, (char *) NULL);
+  }
+  print(STDOUT_FILENO, "\n", (char *) NULL);
+  return EXIT_SUCCESS;
+}
Index: /trunk/minix/commands/simple/unexpand.c
===================================================================
--- /trunk/minix/commands/simple/unexpand.c	(revision 9)
+++ /trunk/minix/commands/simple/unexpand.c	(revision 9)
@@ -0,0 +1,121 @@
+/*  unexpand - convert spaces to tabs	Author: Terrence W. Holm */
+
+/*  Usage:  unexpand  [ -a ]  [ file ... ]  */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#define  TAB   8
+
+
+int column = 0;			/* Current column, retained between files  */
+int spaces = 0;			/* Spaces since last tab stop  	    */
+int leading_blank = 1;		/* Only unexpand leading blanks,	    */
+/* Overruled by -a option	            */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void Unexpand, (FILE *f, int all));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+
+{
+  int all = 0;			/* -a flag means unexpand all spaces  */
+  int i;
+  FILE *f;
+
+  if (argc > 1 && argv[1][0] == '-') {
+	if (strcmp(argv[1], "-a") == 0)
+		all = 1;
+	else {
+		fprintf(stderr, "Usage:  unexpand  [ -a ]  [ file ... ]\n");
+		exit(1);
+	}
+
+	--argc;
+	++argv;
+  }
+  if (argc == 1)
+	Unexpand(stdin, all);
+  else
+	for (i = 1; i < argc; ++i) {
+		if ((f = fopen(argv[i], "r")) == NULL) {
+			perror(argv[i]);
+			exit(1);
+		}
+		Unexpand(f, all);
+		fclose(f);
+	}
+
+
+  /* If there are pending spaces print them.  */
+
+  while (spaces > 0) {
+	putchar(' ');
+	--spaces;
+  }
+
+  return(0);
+}
+
+void Unexpand(f, all)
+FILE *f;
+int all;
+
+{
+  int c;
+
+  while ((c = getc(f)) != EOF) {
+	if (c == ' ' && (all || leading_blank)) {
+		++column;
+		++spaces;
+
+		/* If we have white space up to a tab stop, then output	 */
+		/* A tab. If only one space is required, use a ' '.	 */
+
+		if (column % TAB == 0) {
+			if (spaces == 1)
+				putchar(' ');
+			else
+				putchar('\t');
+
+			spaces = 0;
+		}
+		continue;
+	}
+
+	/* If a tab character is encountered in the input then		*/
+	/* Simply echo it. Any accumulated spaces can only be 		*/
+	/* Since the last tab stop, so ignore them.			*/
+	if (c == '\t') {
+		column = (column / TAB + 1) * TAB;
+		spaces = 0;
+		putchar('\t');
+		continue;
+	}
+
+	/* A non-space character is to be printed. If there   */
+	/* Are pending spaces, then print them. There will be */
+	/* At most TAB-1 spaces to print.		      */
+	while (spaces > 0) {
+		putchar(' ');
+		--spaces;
+	}
+
+	if (c == '\n' || c == '\r') {
+		column = 0;
+		leading_blank = 1;
+		putchar(c);
+		continue;
+	}
+	if (c == '\b')
+		column = column > 0 ? column - 1 : 0;
+	else
+		++column;
+
+	leading_blank = 0;
+	putchar(c);
+  }
+}
Index: /trunk/minix/commands/simple/uniq.c
===================================================================
--- /trunk/minix/commands/simple/uniq.c	(revision 9)
+++ /trunk/minix/commands/simple/uniq.c	(revision 9)
@@ -0,0 +1,195 @@
+/* uniq - compact repeated lines		Author: John Woods */
+/* Uniq [-udc] [-n] [+n] [infile [outfile]]
+ *
+ *	Written 02/08/86 by John Woods, placed into public domain.  Enjoy.
+ *
+ */
+
+/* If the symbol WRITE_ERROR is defined, uniq will exit(1) if it gets a
+ * write error on the output.  This is not (of course) how V7 uniq does it,
+ * so undefine the symbol if you want to lose your output to a full disk
+ */
+
+#define WRITE_ERROR 1
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+char buffer[BUFSIZ];
+int uflag = 1;			/* default is union of -d and -u outputs */
+int dflag = 1;			/* flags are mutually exclusive */
+int cflag = 0;
+int fields = 0;
+int chars = 0;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(FILE *xfopen, (char *fn, char *mode));
+_PROTOTYPE(char *skip, (char *s));
+_PROTOTYPE(int equal, (char *s1, char *s2));
+_PROTOTYPE(void show, (char *line, int count));
+_PROTOTYPE(int uniq, (void));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(int getline, (char *buf, int count));
+
+FILE *xfopen(fn, mode)
+char *fn, *mode;
+{
+  FILE *p;
+
+  if ((p = fopen(fn, mode)) == NULL) {
+	perror("uniq");
+	fflush(stdout);
+	exit(1);
+  }
+  return(p);
+}
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  char *p;
+  int inf = -1, outf;
+
+  setbuf(stdout, buffer);
+  for (--argc, ++argv; argc > 0 && (**argv == '-' || **argv == '+');
+       --argc, ++argv) {
+	if (**argv == '+')
+		chars = atoi(*argv + 1);
+	else if (isdigit(argv[0][1]))
+		fields = atoi(*argv + 1);
+	else if (argv[0][1] == '\0')
+		inf = 0;	/* - is stdin */
+	else
+		for (p = *argv + 1; *p; p++) {
+			switch (*p) {
+			    case 'd':
+				dflag = 1;
+				uflag = 0;
+				break;
+			    case 'u':
+				uflag = 1;
+				dflag = 0;
+				break;
+			    case 'c':	cflag = 1;	break;
+			    default:	usage();
+			}
+		}
+  }
+
+  /* Input file */
+  if (argc == 0)
+	inf = 0;
+  else if (inf == -1) {		/* if - was not given */
+	fclose(stdin);
+	xfopen(*argv++, "r");
+	argc--;
+  }
+  if (argc == 0)
+	outf = 1;
+  else {
+	fclose(stdout);
+	xfopen(*argv++, "w");
+	argc--;
+  }
+
+  uniq();
+  fflush(stdout);
+  return(0);
+}
+
+char *skip(s)
+char *s;
+{
+  int n;
+
+  /* Skip fields */
+  for (n = fields; n > 0; --n) {
+	/* Skip blanks */
+	while (*s && (*s == ' ' || *s == '\t')) s++;
+	if (!*s) return s;
+	while (*s && (*s != ' ' && *s != '\t')) s++;
+	if (!*s) return s;
+  }
+
+  /* Skip characters */
+  for (n = chars; n > 0; --n) {
+	if (!*s) return s;
+	s++;
+  }
+  return s;
+}
+
+int equal(s1, s2)
+char *s1, *s2;
+{
+  return !strcmp(skip(s1), skip(s2));
+}
+
+void show(line, count)
+char *line;
+int count;
+{
+  if (cflag)
+	printf("%4d %s", count, line);
+  else {
+	if ((uflag && count == 1) || (dflag && count != 1))
+		printf("%s", line);
+  }
+}
+
+/* The meat of the whole affair */
+char *nowline, *prevline, buf1[1024], buf2[1024];
+
+int uniq()
+{
+  char *p;
+  int seen;
+
+  /* Setup */
+  prevline = buf1;
+  if (getline(prevline, 1024) < 0) return(0);
+  seen = 1;
+  nowline = buf2;
+
+  /* Get nowline and compare if not equal, dump prevline and swap
+   * pointers else continue, bumping seen count */
+  while (getline(nowline, 1024) > 0) {
+	if (!equal(prevline, nowline)) {
+		show(prevline, seen);
+		seen = 1;
+		p = nowline;
+		nowline = prevline;
+		prevline = p;
+	} else
+		seen += 1;
+  }
+  show(prevline, seen);
+  return 0;
+}
+
+void usage()
+{
+  fprintf(stderr, "Usage: uniq [-udc] [+n] [-n] [input [output]]\n");
+}
+
+int getline(buf, count)
+char *buf;
+int count;
+{
+  int c;
+  int ct = 0;
+
+  while (ct++ < count) {
+	c = getc(stdin);
+	if (c < 0) return(-1);
+	*buf++ = c;
+	if (c == '\n') {
+		*buf++ = 0;
+		return(ct);
+	}
+  }
+  return(ct);
+}
Index: /trunk/minix/commands/simple/update.c
===================================================================
--- /trunk/minix/commands/simple/update.c	(revision 9)
+++ /trunk/minix/commands/simple/update.c	(revision 9)
@@ -0,0 +1,24 @@
+/* update - do sync periodically		Author: Andy Tanenbaum */
+
+#include <sys/types.h>
+#include <signal.h>
+#include <unistd.h>
+
+_PROTOTYPE(int main, (void));
+
+int main()
+{
+  /* Release all (?) open file descriptors. */
+  close(0);
+  close(1);
+  close(2);
+
+  /* Release current directory to avoid locking current device. */
+  chdir("/");
+
+  /* Flush the cache every 30 seconds. */
+  while (1) {
+	sync();
+	sleep(30);
+  }
+}
Index: /trunk/minix/commands/simple/uud.c
===================================================================
--- /trunk/minix/commands/simple/uud.c	(revision 9)
+++ /trunk/minix/commands/simple/uud.c	(revision 9)
@@ -0,0 +1,562 @@
+/* uud - bulletproof version of uudecode */
+
+/*
+ * Uud -- decode a uuencoded file back to binary form.
+ *
+ * From the Berkeley original, modified by MSD, RDR, JPHD & WLS.
+ * The Atari GEMDOS version compiled with MWC 2.x.
+ * The MSDOS version with TurboC.
+ * The Unix version with cc.
+ * this version is made: 25 Nov 1988.
+ * Jan 2 1990: Change system definition and change MSDOS to open the output
+ *             file for write binary do cr/lf replacement.
+ */
+
+#define UNIX  1		/* define one of: UNIX (Minix too!), MSDOS, or GEMDOS */ 
+
+#ifdef GEMDOS
+#define SYSNAME "gemdos"
+#define SMALL 1
+#endif
+#ifdef MSDOS
+#define SYSNAME "msdos"
+#define SMALL 1
+#endif
+#ifdef UNIX
+#define SYSNAME "unix"
+#endif
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <stdio.h>
+
+#ifdef GEMDOS
+#include <osbind.h>
+#define Error(n)  { Bconin(2); exit(n); }
+#else
+#define Error(n)  exit(n)
+#endif
+#ifdef UNIX
+#define WRITE	  "w"
+#else
+#define WRITE	  "wb"		/* for both MSDOS and GEMDOS!	*/
+#endif
+
+#define loop	while (1)
+
+#define NCHARS  256
+#define LINELEN 256
+#define FILELEN 64
+#define NORMLEN 60	/* allows for 80 encoded chars per line */
+
+#define SEQMAX 'z'
+#define SEQMIN 'a'
+char seqc;
+int first, secnd, check, numl;
+
+FILE *in, *out;
+char *pos;
+char ifname[FILELEN], ofname[FILELEN];
+char *source = NULL, *target = NULL;
+char blank, part = '\0';
+int partn, lens;
+int debug = 0, nochk = 0, onedone = 0;
+int chtbl[NCHARS], cdlen[NORMLEN + 3];
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(char *getnword, (char *str, int n));
+_PROTOTYPE(void gettable, (void));
+_PROTOTYPE(void decode, (void));
+_PROTOTYPE(void getfile, (char *buf));
+_PROTOTYPE(void format, (char *fp, ...));
+_PROTOTYPE(void doprnt, (char *fp, char *ap));
+_PROTOTYPE(void puti, (unsigned int i, unsigned int r));
+_PROTOTYPE(void outc, (int c));
+
+int main(argc, argv) int argc; char *argv[];
+{
+	int mode;
+	register int i, j;
+	char *curarg;
+	char dest[FILELEN], buf[LINELEN];
+
+	while ((curarg = argv[1]) != NULL && curarg[0] == '-') {
+		if (((curarg[1] == 'd') || (curarg[1] == 'D')) &&
+		    (curarg[2] == '\0')) {
+			debug = 1;
+		} else if (((curarg[1] == 'n') || (curarg[1] == 'N')) &&
+			   (curarg[2] == '\0')) {
+			nochk = 1;
+		} else if (((curarg[1] == 't') || (curarg[1] == 'T')) &&
+			   (curarg[2] == '\0')) {
+			argv++;
+			argc--;
+			if (argc < 2) {
+				format("uud: Missing target directory.\n");
+				Error(15);
+			}
+			target = argv[1];
+			if (debug)
+				format("Target dir = %s\n",target);
+		} else if (((curarg[1] == 's') || (curarg[1] == 'S')) &&
+			   (curarg[2] == '\0')) {
+			argv++;
+			argc--;
+			if (argc < 2) {
+				format("uud: Missing source directory.\n");
+				Error(15);
+			}
+			source = argv[1];
+			if (debug)
+				format("Source dir = %s\n",source);
+		} else if (curarg[1] != '\0') {
+			format("Usage: uud [-n] [-d] [-s dir] [-t dir] [input-file]\n");
+			Error(1);
+		} else
+			break;
+		argv++;
+		argc--;
+	}
+
+	if (curarg == NULL || ((curarg[0] == '-') && (curarg[1] == '\0'))) {
+		in = stdin;
+		strcpy(ifname, "<stdin>");
+	} else {
+		if (source != NULL) {
+			strcpy(ifname, source);
+			strcat(ifname, curarg);
+		} else
+			strcpy(ifname, curarg);
+		if ((in = fopen(ifname, "r")) == NULL) {
+			format("uud: Can't open %s\n", ifname);
+			Error(2);
+		}
+		numl = 0;
+	}
+
+/*
+ * Set up the default translation table.
+ */
+	for (i = 0; i < ' '; i++) chtbl[i] = -1;
+	for (i = ' ', j = 0; i < ' ' + 64; i++, j++) chtbl[i] = j;
+	for (i = ' ' + 64; i < NCHARS; i++) chtbl[i] = -1;
+	chtbl['`'] = chtbl[' '];	/* common mutation */
+	chtbl['~'] = chtbl['^'];	/* an other common mutation */
+	blank = ' ';
+/*
+ * set up the line length table, to avoid computing lotsa * and / ...
+ */
+	cdlen[0] = 1;
+	for (i = 1, j = 5; i <= NORMLEN; i += 3, j += 4)
+		cdlen[i] = (cdlen[i + 1] = (cdlen[i + 2] = j));
+/*
+ * search for header or translation table line.
+ */
+	loop {	/* master loop for multiple decodes in one file */
+		partn = 'a';
+		loop {
+			if (fgets(buf, sizeof buf, in) == NULL) {
+				if (onedone) {
+					if (debug) format("End of file.\n");
+					exit(0);
+				} else {
+					format("uud: No begin line.\n");
+					Error(3);
+				}
+			}
+			numl++;
+			if (strncmp(buf, "table", (size_t)5) == 0) {
+				gettable();
+				continue;
+			}
+			if (strncmp(buf, "begin", (size_t)5) == 0) {
+				break;
+			}
+		}
+		lens = strlen(buf);
+		if (lens) buf[--lens] = '\0';
+#ifdef SMALL
+		if ((pos = getnword(buf, 3))) {
+			strcpy(dest, pos);
+		} else
+#else
+		if(sscanf(buf,"begin%o%s", &mode, dest) != 2)
+#endif
+		{
+			format("uud: Missing filename in begin line.\n");
+			Error(10);
+		}
+
+		if (target != NULL) {
+			strcpy(ofname, target);
+			strcat(ofname, dest);
+		} else
+			strcpy(ofname, dest);
+
+		if((out = fopen(ofname, WRITE)) == NULL) {
+			format("uud: Cannot open output file: %s\n", ofname);
+			Error(4);
+		}
+		if (debug) format("Begin uudecoding: %s\n", ofname);
+		seqc = SEQMAX;
+		check = nochk ? 0 : 1;
+		first = 1;
+		secnd = 0;
+		decode();
+		fclose(out);
+#ifdef UNIX
+		chmod(ofname, mode);
+#endif
+		onedone = 1;
+		if (debug) format("End uudecoding: %s\n", ofname);
+	}	/* master loop for multiple decodes in one file */
+}
+
+/*
+ * Bring back a pointer to the start of the nth word.
+ */
+char *getnword(str, n) register char *str; register int n;
+{
+	while((*str == '\t') || (*str == ' ')) str++;
+	if (! *str) return NULL;
+	while(--n) {
+		while ((*str != '\t') && (*str != ' ') && (*str)) str++;
+		if (! *str) return NULL;
+		while((*str == '\t') || (*str == ' ')) str++;
+		if (! *str) return NULL;
+	}
+	return str;
+}
+
+/*
+ * Install the table in memory for later use.
+ */
+void gettable()
+{
+	char buf[LINELEN];
+	register int c, n = 0;
+	register char *cpt;
+
+	for (c = 0; c < NCHARS; c++) chtbl[c] = -1;
+
+again:	if (fgets(buf, sizeof buf, in) == NULL) {
+		format("uud: EOF while in translation table.\n");
+		Error(5);
+	}
+	numl++;
+	if (strncmp(buf, "begin", (size_t)5) == 0) {
+		format("uud: Incomplete translation table.\n");
+		Error(6);
+	}
+	cpt = buf + strlen(buf) - 1;
+	*cpt = ' ';
+	while (*(cpt) == ' ') {
+		*cpt = 0;
+		cpt--;
+	}
+	cpt = buf;
+	while (c = *cpt) {
+		if (chtbl[c] != -1) {
+			format("uud: Duplicate char in translation table.\n");
+			Error(7);
+		}
+		if (n == 0) blank = c;
+		chtbl[c] = n++;
+		if (n >= 64) return;
+		cpt++;
+	}
+	goto again;
+}
+
+/*
+ * copy from in to out, decoding as you go along.
+ */
+
+void decode()
+{
+	char buf[LINELEN], outl[LINELEN];
+	register char *bp, *ut;
+	register int *trtbl = chtbl;
+	register int n, c, rlen;
+	register unsigned int len;
+
+	loop {
+		if (fgets(buf, sizeof buf, in) == NULL) {
+			format("uud: EOF before end.\n");
+			fclose(out);
+			Error(8);
+		}
+		numl++;
+		len = strlen(buf);
+		if (len) buf[--len] = '\0';
+/*
+ * Is it an unprotected empty line before the end line ?
+ */
+		if (len == 0) continue;
+/*
+ * Get the binary line length.
+ */
+		n = trtbl[*buf];
+		if (n >= 0) goto decod;
+/*
+ * end of uuencoded file ?
+ */
+		if (strncmp(buf, "end", (size_t)3) == 0) return;
+/*
+ * end of current file ? : get next one.
+ */
+		if (strncmp(buf, "include", (size_t)7) == 0) {
+			getfile(buf);
+			continue;
+		}
+		format("uud: Bad prefix line %d in file: %s\n",numl, ifname);
+		if (debug) format("Bad line =%s\n",buf);
+		Error(11);
+/*
+ * Sequence checking ?
+ */
+decod:		rlen = cdlen[n];
+/*
+ * Is it the empty line before the end line ?
+ */
+		if (n == 0) continue;
+/*
+ * Pad with blanks.
+ */
+		for (bp = &buf[c = len];
+			c < rlen; c++, bp++) *bp = blank;
+/*
+ * Verify if asked for.
+ */
+		if (debug) {
+			for (len = 0, bp = buf; len < rlen; len++) {
+				if (trtbl[*bp] < 0) {
+					format(
+	"Non uuencoded char <%c>, line %d in file: %s\n", *bp, numl, ifname);
+					format("Bad line =%s\n",buf);
+					Error(16);
+				}
+				bp++;
+			}
+		}
+/*
+ * All this just to check for uuencodes that append a 'z' to each line....
+ */
+		if (secnd && check) {
+			secnd = 0;
+			if (buf[rlen] == SEQMAX) {
+				check = 0;
+				if (debug) format("Sequence check turned off (2).\n");
+			} else
+				if (debug) format("Sequence check on (2).\n");
+		} else if (first && check) {
+			first = 0;
+			secnd = 1;
+			if (buf[rlen] != SEQMAX) {
+				check = 0;
+				if (debug) format("No sequence check (1).\n");
+			} else
+				if (debug) format("Sequence check on (1).\n");
+		}
+/*
+ * There we check.
+ */
+		if (check) {
+			if (buf[rlen] != seqc) {
+				format("uud: Wrong sequence line %d in %s\n",
+					numl, ifname);
+				if (debug)
+					format(
+	"Sequence char is <%c> instead of <%c>.\n", buf[rlen], seqc);
+				Error(18);
+			}
+			seqc--;
+			if (seqc < SEQMIN) seqc = SEQMAX;
+		}
+/*
+ * output a group of 3 bytes (4 input characters).
+ * the input chars are pointed to by p, they are to
+ * be output to file f.n is used to tell us not to
+ * output all of them at the end of the file.
+ */
+		ut = outl;
+		len = n;
+		bp = &buf[1];
+		while (n > 0) {
+			*(ut++) = trtbl[*bp] << 2 | trtbl[bp[1]] >> 4;
+			n--;
+			if (n) {
+				*(ut++) = (trtbl[bp[1]] << 4) |
+					  (trtbl[bp[2]] >> 2);
+				n--;
+			}
+			if (n) {
+				*(ut++) = trtbl[bp[2]] << 6 | trtbl[bp[3]];
+				n--;
+			}
+			bp += 4;
+		}
+		if ((n = fwrite(outl, (size_t)1, (size_t)len, out)) <= 0) {
+			format("uud: Error on writing decoded file.\n");
+			Error(18);
+		}
+	}
+}
+
+/*
+ * Find the next needed file, if existing, otherwise try further
+ * on next file.
+ */
+void getfile(buf) register char *buf;
+{
+	if ((pos = getnword(buf, 2)) == NULL) {
+		format("uud: Missing include file name.\n");
+		Error(17);
+	} else
+		if (source != NULL) {
+			strcpy(ifname, source);
+			strcat(ifname, pos);
+		} else
+			strcpy(ifname, pos);
+#ifdef GEMDOS
+	if (Fattrib(ifname, 0, 0) < 0)
+#else
+	if (access(ifname, 04))
+#endif
+	{
+		if (debug) {
+			format("Cant find: %s\n", ifname);
+			format("Continuing to read same file.\n");
+		}
+	}
+	else {
+		if (freopen(ifname, "r", in) == in) {
+			numl = 0;
+			if (debug) 
+				format("Reading next section from: %s\n", ifname);
+		} else {
+			format("uud: Freopen abort: %s\n", ifname);
+			Error(9);
+		}
+	}
+	loop {
+		if (fgets(buf, LINELEN, in) == NULL) {
+			format("uud: No begin line after include: %s\n", ifname);
+			Error(12);
+		}
+		numl++;
+		if (strncmp(buf, "table", (size_t)5) == 0) {
+			gettable();
+			continue;
+		}
+		if (strncmp(buf, "begin", (size_t)5) == 0) break;
+	}
+	lens = strlen(buf);
+	if (lens) buf[--lens] = '\0';
+/*
+ * Check the part suffix.
+ */
+	if ((pos = getnword(buf, 3)) == NULL ) {
+		format("uud: Missing part name, in included file: %s\n", ifname);
+		Error(13);
+	} else {
+		part = *pos;
+		partn++;
+		if (partn > 'z') partn = 'a';
+		if (part != partn) {
+			format("uud: Part suffix mismatch: <%c> instead of <%c>.\n",
+				part, partn);
+			Error(14);
+		}
+		if (debug) format("Reading part %c\n", *pos);
+	}
+}
+
+/*
+ * Printf style formatting. (Borrowed from MicroEmacs by Dave Conroy.) 
+ * A lot smaller than the full fledged printf.
+ */
+#ifdef __STDC__
+void format(char *fp, ...)
+{
+  va_list args;
+
+  va_start (args, fp);
+  doprnt(fp, (char *)&args);
+  va_end(args);
+}
+#else
+/* VARARGS1 */
+void format(fp, args) char *fp;
+{
+	doprnt(fp, (char *)&args);
+}
+#endif
+
+void doprnt(fp, ap)
+register char	*fp;
+register char	*ap;
+{
+	register int	c, k;
+	register char	*s;
+
+	while ((c = *fp++) != '\0') {
+		if (c != '%')
+			outc(c);
+		else {
+			c = *fp++;
+			switch (c) {
+			case 'd':
+				puti(*(int *)ap, 10);
+				ap += sizeof(int);
+				break;
+
+			case 's':
+				s = *(char **)ap;
+				while ((k = *s++) != '\0')
+					outc(k);
+				ap += sizeof(char *);
+				break;
+
+			case 'c':
+				outc(*(int *)ap);
+				ap += sizeof(int);
+				break;
+
+			default:
+				outc(c);
+			}
+		}
+	}
+}
+
+/*
+ * Put integer, in radix "r".
+ */
+void puti(i, r)
+register unsigned int	i;
+register unsigned int	r;
+{
+	register unsigned int	q, s;
+
+	if ((q = i / r) != 0)
+		puti(q, r);
+	s = i % r;
+	if (s <= 9)
+		outc(s + '0');
+	else
+		outc(s - 10 + 'A');
+}
+void outc(c) register char c;
+{
+#ifdef GEMDOS
+	if (c == '\n') Bconout(2, '\r');
+	Bconout(2, c);
+#else
+	putchar(c);
+#endif
+}
Index: /trunk/minix/commands/simple/uue.c
===================================================================
--- /trunk/minix/commands/simple/uue.c	(revision 9)
+++ /trunk/minix/commands/simple/uue.c	(revision 9)
@@ -0,0 +1,217 @@
+/* uue - bulletproof version of uuencode */
+
+/* Uue -- encode a file so that it's printable ascii, short lines
+ *
+ * Slightly modified from a version posted to net.sources a while back,
+ * and suitable for compilation on the IBM PC
+ *
+ * modified for Lattice C on the ST - 11.05.85 by MSD
+ * modified for ALCYON on the ST -    10-24-86 by RDR
+ * modified a little more for MWC...  02/09/87 by JPHD
+ * (An optional first argument of the form: -nnumber (e.g. -500), will
+ * produce a serie of files that long, linked by the include statement,
+ * such files are automatically uudecoded by the companion program.)
+ * More mods, - ...		   05/06/87 by jphd
+ * Mods for TOPS 20, and more.     08/06/87 by jphd
+ *     (remove freopen and rindex...change filename generation...)
+ * (A lot more to do about I/O speed, avoiding completely the stdio.h...)
+ * May be called as uuencode.       Oct 2 1993 by Kees J. Bot
+ *
+ */
+
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#define USAGE
+#define FILE_NAME 10		/* affects how long names are truncated */
+
+/* ENC is the basic 1 character encoding function to make a char printing */
+#define ENC(c) (((c) & 077) + ' ')
+
+FILE *fp, *outp;
+char ofname[80];
+int lenofname;
+int stdo = 0;
+
+#ifdef ST
+#define READ "rb"
+#else
+#define READ "r"
+#endif
+
+int part = 'a', chap = 'a';
+#define SEQMAX 'z'
+#define SEQMIN 'a'
+char seqc = SEQMAX;
+
+int split = 0;
+int fileln = 32000;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void maketable, (void));
+_PROTOTYPE(void makename, (void));
+_PROTOTYPE(void encode, (void));
+_PROTOTYPE(void outdec, (char *p));
+_PROTOTYPE(int fr, (char *buf, int cnt));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  char *prog_name;
+  char *fname;
+  int filter;
+
+  prog_name = argv[0] + strlen(argv[0]);
+  while (prog_name > argv[0] && prog_name[-1] != '/') prog_name--;
+  filter = strcmp(prog_name, "uuencode") == 0;
+
+  if (argc < 2) {
+	fprintf(stderr, "Usage: %s [-n] inputfile [-]\n", prog_name);
+	exit(2);
+  }
+  if (argv[1][0] == '-') {
+	fileln = -atoi(argv[1]);
+	if (fileln <= 0) {
+		fprintf(stderr, "Wrong file length arg.\n");
+		exit(3);
+	}
+	split = 1;
+	argv++;
+	argc--;
+  }
+  if (filter) {		/* old uuencode reads from standard input */
+	fp = stdin;
+  } else {
+	if ((fp = fopen(argv[1], READ)) == NULL) {	/* binary input !!! */
+		fprintf(stderr, "Cannot open %s\n", argv[1]);
+		exit(1);
+	}
+  }
+  fname = argv[1] + strlen(argv[1]);
+  while (fname > argv[1] && fname[-1] != '/') fname--;
+  strcpy(ofname, fname);
+  fname = ofname;
+  do {
+	if (*fname == '.') *fname = '\0';
+  } while (*fname++);
+  /* 10 char prefix + .uue -> 14 chars MAX */
+  lenofname = strlen(ofname);
+  if (lenofname > FILE_NAME) ofname[FILE_NAME] = '\0';
+  strcat(ofname, ".uue");
+  lenofname = strlen(ofname);
+  if (!split && (filter || (argc > 2) && (argv[2][0] == '-'))) {
+	stdo = 1;
+	outp = stdout;
+  } else {
+	makename();
+	if ((outp = fopen(ofname, "w")) == NULL) {
+		fprintf(stderr, "Cannot open %s\n", ofname);
+		exit(1);
+	}
+  }
+  maketable();
+  fprintf(outp, "begin %o %s\n", 0644, argv[1]);
+  encode();
+  fprintf(outp, "end\n");
+  fclose(outp);
+  return(0);
+}
+
+/* Create ASCII table so a mailer can screw it up and the decode
+ * program can restore the error.
+ */
+void maketable()
+{
+  register int i, j;
+
+  fputs("table\n", outp);
+  for (i = ' ', j = 0; i < '`'; j++) {
+	if (j == 32) putc('\n', outp);
+	fputc(i++, outp);
+  }
+  putc('\n', outp);
+}
+
+/* Generate the names needed for single and multiple part encoding.  */
+void makename()
+{
+  if (split) {
+	ofname[lenofname - 1] = part;
+	ofname[lenofname - 2] = chap;
+  }
+}
+
+/* Copy from in to out, encoding as you go along.  */
+void encode()
+{
+  char buf[80];
+  register int i, n;
+  register int lines;
+  lines = 6;
+
+  for (;;) {
+	n = fr(buf, 45);
+	putc(ENC(n), outp);
+	for (i = 0; i < n; i += 3) outdec(&buf[i]);
+	putc(seqc, outp);
+	seqc--;
+	if (seqc < SEQMIN) seqc = SEQMAX;
+	putc('\n', outp);
+	++lines;
+	if (split && (lines > fileln)) {
+		part++;
+		if (part > 'z') {
+			part = 'a';
+			if (chap == 'z')
+				chap = 'a';	/* loop ... */
+			else
+				chap++;
+		}
+		makename();
+		fprintf(outp, "include %s\n", ofname);
+		fclose(outp);
+		if ((outp = fopen(ofname, "w")) == NULL) {
+			fprintf(stderr, "Cannot open %s\n", ofname);
+			exit(1);
+		}
+		maketable();
+		fprintf(outp, "begin part %c %s\n", part, ofname);
+		lines = 6;
+	}
+	if (n <= 0) break;
+  }
+}
+
+/* Output one group of 3 bytes, pointed at by p, on file f.  */
+void outdec(p)
+register char *p;
+{
+  register int c1, c2, c3, c4;
+
+  c1 = *p >> 2;
+  c2 = ((*p << 4) & 060) | ((p[1] >> 4) & 017);
+  c3 = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03);
+  c4 = p[2] & 077;
+  putc(ENC(c1), outp);
+  putc(ENC(c2), outp);
+  putc(ENC(c3), outp);
+  putc(ENC(c4), outp);
+}
+
+/* Fr: like read but stdio */
+int fr(buf, cnt)
+register char *buf;
+register int cnt;
+{
+  register int c, i;
+  for (i = 0; i < cnt; i++) {
+	c = fgetc(fp);
+	if (feof(fp)) return(i);
+	buf[i] = c;
+  }
+  return(cnt);
+}
Index: /trunk/minix/commands/simple/vol.c
===================================================================
--- /trunk/minix/commands/simple/vol.c	(revision 9)
+++ /trunk/minix/commands/simple/vol.c	(revision 9)
@@ -0,0 +1,371 @@
+/* vol - break stdin into volumes	Author: Andy Tanenbaum */
+
+/* This program reads standard input and writes it onto diskettes, pausing
+ * at the start of each one.  It's main use is for saving files that are
+ * larger than a single diskette.  Vol just writes its standard input onto
+ * a diskette, and prompts for a new one when it is full.  This mechanism
+ * is transparent to the process producing vol's standard input. For example,
+ *	tar cf - . | vol -w 360 /dev/fd0
+ * puts the tar output as as many diskettes as needed.  To read them back in,
+ * use
+ *	vol -r 360 /dev/fd0 | tar xf -
+ *
+ * Changed 17 Nov 1993 by Kees J. Bot to handle buffering to slow devices.
+ * Changed 27 Jul 1994 by Kees J. Bot to auto discover data direction + -rw.
+ * Changed 19 Sep 1995 by Kees J. Bot to do better buffering to tapes.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mtio.h>
+#include <minix/partition.h>
+#include <minix/u64.h>
+
+/* Preferred block size to variable block length tapes, block devices or files.
+ */
+#define VAR_BLKSIZ	   8192
+
+/* Required block size multiple of fixed block size tapes (usually updated by
+ * 'mt status' data) and character devices.
+ */
+#define FIX_BLKSIZ	    512
+
+/* Maximum multiple block size. */
+#if __minix_vmd
+#define MULT_MAX	1048576
+#else
+#define MULT_MAX	((ssize_t) (SSIZE_MAX < 65536L ? SSIZE_MAX : 65536L))
+#endif
+
+char *buffer = NULL;
+size_t block_size = 0, mult_max = 0;
+size_t buffer_size;
+long volume_size;
+char *str_vol_size;
+int rflag = 0, wflag = 0, oneflag = 0, variable = 0;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(long str2size, (char *name, char *str, long min, long max,
+							int assume_kb));
+_PROTOTYPE(void tape_inquire, (char *name, int fd));
+_PROTOTYPE(void allocate_buffer, (void));
+_PROTOTYPE(void diskio, (int fd1, int fd2, char *file1, char *file2));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int volume = 1, fd, tty, i, init, autovolsize;
+  char *p, *name;
+  struct stat stb;
+  struct partition part;
+  char key;
+
+  /* Fetch and verify the arguments. */
+  i = 1;
+  while (i < argc && argv[i][0] == '-') {
+	p = argv[i++] + 1;
+	if (p[0] == '-' && p[1] == 0) {
+		/* -- */
+		i++;
+		break;
+	}
+	while (*p != '\0') {
+		switch (*p++) {
+		case 'r':
+		case 'u':
+			rflag = 1;
+			break;
+		case 'w':
+			wflag = 1;
+			break;
+		case '1':
+			oneflag = 1;
+			break;
+		case 'b':
+			if (*p == 0) {
+				if (i == argc) usage();
+				p = argv[i++];
+			}
+			block_size = str2size("block", p,
+						1L, (long) SSIZE_MAX, 0);
+			p= "";
+			break;
+		case 'm':
+			if (*p == 0) {
+				if (i == argc) usage();
+				p = argv[i++];
+			}
+			mult_max = str2size("maximum", p,
+						1L, (long) SSIZE_MAX, 0);
+			p= "";
+			break;
+		default:
+			usage();
+		}
+	}
+  }
+  if (i < argc - 1) {
+	str_vol_size = argv[i++];
+	volume_size = str2size("volume", str_vol_size, 1L, LONG_MAX, 1);
+	autovolsize = 0;
+  } else {
+	volume_size = 0;	/* unlimited (long tape) or use DIOCGETP */
+	autovolsize = 1;
+  }
+
+  if (i >= argc) usage();
+  name = argv[i];
+
+  if (!rflag && !wflag) {
+	/* Auto direction.  If there is a terminal at one side then data is
+	 * to go out at the other side.
+	 */
+	if (isatty(0)) rflag = 1;
+	if (isatty(1)) wflag = 1;
+  }
+
+  if (rflag == wflag) {
+	fprintf(stderr, "vol: should %s be read or written?\n", name);
+	usage();
+  }
+
+  if (stat(name, &stb) < 0) {
+	fprintf(stderr, "vol: %s: %s\n", name, strerror(errno));
+	exit(1);
+  }
+  if (!S_ISBLK(stb.st_mode) && !S_ISCHR(stb.st_mode)) {
+	fprintf(stderr, "vol: %s is not a device\n", name);
+	exit(1);
+  }
+  variable = !S_ISCHR(stb.st_mode);
+
+  if (!oneflag) {
+	tty = open("/dev/tty", O_RDONLY);
+	if (tty < 0) {
+		fprintf(stderr, "vol: cannot open /dev/tty\n");
+		exit(1);
+	}
+  }
+
+  /* Buffer initializations are yet to be done. */
+  init = 0;
+
+  while (1) {
+	sleep(1);
+	if (oneflag) {
+		if (volume != 1) {
+			if (rflag) exit(0);
+			fprintf(stderr,
+				"vol: can't continue, volume is full\n");
+			exit(1);
+		}
+	} else {
+		fprintf(stderr,
+			"\007Please insert %sput volume %d and hit return\n",
+			rflag ? "in" : "out", volume);
+		while (read(tty, &key, sizeof(key)) == 1 && key != '\n') {}
+	}
+
+	/* Open the special file. */
+	fd = open(name, rflag ? O_RDONLY : O_WRONLY);
+	if (fd < 0) {
+		fprintf(stderr, "vol: %s: %s\n", name, strerror(errno));
+		exit(1);
+	}
+
+	if (!init) {
+		/* Ask for the tape block size and allocate a buffer. */
+		if (S_ISCHR(stb.st_mode)) tape_inquire(name, fd);
+		allocate_buffer();
+		init = 1;
+	}
+
+	if (autovolsize) {
+		/* Ask the driver how big the volume is. */
+		if (ioctl(fd, DIOCGETP, &part) < 0) {
+			autovolsize = 0;
+		} else {
+			volume_size = cv64ul(part.size);
+		}
+	}
+
+	/* Read or write the requisite number of blocks. */
+	if (rflag) {
+		diskio(fd, 1, name, "stdout");	/* vol -r | tar xf - */
+	} else {
+		diskio(0, fd, "stdin", name);	/* tar cf - | vol -w */
+	}
+	close(fd);
+	volume++;
+  }
+}
+
+void usage()
+{
+  fprintf(stderr,
+	"Usage: vol [-rw1] [-b blocksize] [-m max] [size] block-special\n");
+  exit(1);
+}
+
+long str2size(name, str, min, max, assume_kb)
+char *name;
+char *str;
+long min, max;
+int assume_kb;
+{
+  /* Convert a string to a size.  The number may be followed by 'm', 'k', 'b'
+   * or 'w' to multiply the size as shown below.  If 'assume_kb' is set then
+   * kilobytes is the default.
+   */
+  long size, factor;
+  char *ptr;
+  int bad;
+
+  errno = 0;
+  size = strtol(str, &ptr, 10);
+  bad = (errno != 0 || ptr == str || size < min || size > max);
+  if (*ptr == 0 && assume_kb) ptr = "k";
+  while (!bad && *ptr != 0) {
+	switch (*ptr++) {
+	case 'm':
+	case 'M':
+		factor = 1024*1024L; break;
+	case 'k':
+	case 'K':
+		factor = 1024; break;
+	case 'b':
+	case 'B':
+		factor = 512; break;
+	case 'w':
+	case 'W':
+		factor = 2; break;
+	default:
+		factor = 1; bad = 1;
+	}
+	if (size <= max / factor) size *= factor; else bad = 1;
+  }
+  if (bad) {
+	fprintf(stderr, "vol: bad %s size '%s'\n", name, str);
+	exit(1);
+  }
+  return size;
+}
+
+void tape_inquire(name, fd)
+char *name;
+int fd;
+{
+  /* If the device happens to be a tape, then what is its block size? */
+  struct mtget mtget;
+
+  if (ioctl(fd, MTIOCGET, &mtget) < 0) {
+	if (errno != ENOTTY) {
+		fprintf(stderr, "vol: %s: %s\n", name,
+					strerror(errno));
+		exit(1);
+	}
+  } else {
+	if (mtget.mt_blksize > SSIZE_MAX) {
+		fprintf(stderr,
+		"vol: %s: tape block size (%lu) is too large to handle\n",
+			name, (unsigned long) mtget.mt_blksize);
+		exit(1);
+	}
+	if (mtget.mt_blksize == 0) {
+		variable = 1;
+	} else {
+		/* fixed */
+		block_size = mtget.mt_blksize;
+	}
+  }
+}
+
+void allocate_buffer()
+{
+  /* Set block size and maximum multiple. */
+  if (block_size == 0) block_size = variable ? 1 : FIX_BLKSIZ;
+  if (mult_max == 0) mult_max = variable ? VAR_BLKSIZ : MULT_MAX;
+
+  /* Stretch the buffer size to the max. */
+  buffer_size = mult_max / block_size * block_size;
+  if (buffer_size == 0) buffer_size = block_size;
+
+  if (volume_size % block_size != 0) {
+	fprintf(stderr,
+	"vol: volume size (%s) is not a multiple of the block size (%lu)\n",
+		str_vol_size, (unsigned long) block_size);
+	exit(1);
+  }
+
+  buffer = (char *) malloc(buffer_size);
+  if (buffer == NULL) {
+	fprintf(stderr, "vol: cannot allocate a %luk buffer\n",
+		(unsigned long) buffer_size / 1024);
+	exit(1);
+  }
+}
+
+void diskio(fd1, fd2, file1, file2)
+int fd1, fd2;
+char *file1, *file2;
+{
+/* Read 'volume_size' bytes from 'fd1' and write them on 'fd2'.  Watch out for
+ * the fact that reads on pipes can return less than the desired data.
+ */
+
+  ssize_t n, in_needed, in_count, out_count;
+  long needed = volume_size;
+  int eof = 0;
+
+  for (;;) {
+	if (volume_size == 0) needed = buffer_size;
+
+	if (needed == 0) break;
+
+	in_count = 0;
+	in_needed = needed > buffer_size ? buffer_size : needed;
+	while (in_count < in_needed) {
+		n = in_needed - in_count;
+		n = eof ? 0 : read(fd1, buffer + in_count, n);
+		if (n == 0) {
+			eof = 1;
+			if ((n = in_count % block_size) > 0) {
+				n = block_size - n;
+				memset(buffer + in_count, '\0', n);
+				if ((in_count += n) > in_needed)
+					in_count = in_needed;
+			}
+			break;
+		}
+		if (n < 0) {
+			fprintf(stderr, "vol: %s: %s\n",
+						file1, strerror(errno));
+			exit(1);
+		}
+		in_count += n;
+	}
+	if (in_count == 0) exit(0);	/* EOF */
+	out_count = 0;
+	while (out_count < in_count) {
+		n = in_count - out_count;
+		n = write(fd2, buffer + out_count, n);
+		if (n < 0) {
+			fprintf(stderr, "vol: %s: %s\n",
+						file2, strerror(errno));
+			exit(1);
+		}
+		out_count += n;
+	}
+	needed -= in_count;
+  }
+}
Index: /trunk/minix/commands/simple/wc.c
===================================================================
--- /trunk/minix/commands/simple/wc.c	(revision 9)
+++ /trunk/minix/commands/simple/wc.c	(revision 9)
@@ -0,0 +1,151 @@
+/* wc - count lines, words and characters	Author: David Messer */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/*
+ *
+ *	Usage:  wc [-lwc] [names]
+ *
+ *		Flags:
+ *			l - count lines.
+ *			w - count words.
+ *			c - count characters.
+ *
+ *		Flags l, w, and c are default.
+ *		Words are delimited by any non-alphabetic character.
+ *
+ *  Released into the PUBLIC-DOMAIN 02/10/86
+ *
+ *	If you find this program to be of use to you, a donation of
+ *	whatever you think it is worth will be cheerfully accepted.
+ *
+ *	Written by: David L. Messer
+ *				P.O. Box 19130, Mpls, MN,  55119
+ *      Program (heavily) modified by Andy Tanenbaum
+ */
+
+
+int lflag;			/* Count lines */
+int wflag;			/* Count words */
+int cflag;			/* Count characters */
+
+long lcount;			/* Count of lines */
+long wcount;			/* Count of words */
+long ccount;			/* Count of characters */
+
+long ltotal;			/* Total count of lines */
+long wtotal;			/* Total count of words */
+long ctotal;			/* Total count of characters */
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(void count, (FILE *f));
+_PROTOTYPE(void usage, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int k;
+  char *cp;
+  int tflag, files;
+
+  /* Get flags. */
+  files = argc - 1;
+  k = 1;
+  cp = argv[1];
+  if (argc > 1 && *cp++ == '-') {
+	files--;
+	k++;			/* points to first file */
+	while (*cp != 0) {
+		switch (*cp) {
+		    case 'l':	lflag++;	break;
+		    case 'w':	wflag++;	break;
+		    case 'c':	cflag++;	break;
+		    default:	usage();
+		}
+		cp++;
+	}
+  }
+
+  /* If no flags are set, treat as wc -lwc. */
+  if (!lflag && !wflag && !cflag) {
+	lflag = 1;
+	wflag = 1;
+	cflag = 1;
+  }
+
+  /* Process files. */
+  tflag = files >= 2;		/* set if # files > 1 */
+
+  /* Check to see if input comes from std input. */
+  if (k >= argc) {
+	count(stdin);
+	if (lflag) printf(" %6ld", lcount);
+	if (wflag) printf(" %6ld", wcount);
+	if (cflag) printf(" %6ld", ccount);
+	printf(" \n");
+	fflush(stdout);
+	exit(0);
+  }
+
+  /* There is an explicit list of files.  Loop on files. */
+  while (k < argc) {
+	FILE *f;
+
+	if ((f = fopen(argv[k], "r")) == NULL) {
+		fprintf(stderr, "wc: cannot open %s\n", argv[k]);
+	} else {
+		count(f);
+		if (lflag) printf(" %6ld", lcount);
+		if (wflag) printf(" %6ld", wcount);
+		if (cflag) printf(" %6ld", ccount);
+		printf(" %s\n", argv[k]);
+		fclose(f);
+	}
+	k++;
+  }
+
+  if (tflag) {
+	if (lflag) printf(" %6ld", ltotal);
+	if (wflag) printf(" %6ld", wtotal);
+	if (cflag) printf(" %6ld", ctotal);
+	printf(" total\n");
+  }
+  fflush(stdout);
+  return(0);
+}
+
+void count(f)
+FILE *f;
+{
+  register int c;
+  register int word = 0;
+
+  lcount = 0;
+  wcount = 0;
+  ccount = 0L;
+
+  while ((c = getc(f)) != EOF) {
+	ccount++;
+
+	if (isspace(c)) {
+		if (word) wcount++;
+		word = 0;
+	} else {
+		word = 1;
+	}
+
+	if (c == '\n' || c == '\f') lcount++;
+  }
+  ltotal += lcount;
+  wtotal += wcount;
+  ctotal += ccount;
+}
+
+void usage()
+{
+  fprintf(stderr, "Usage: wc [-lwc] [name ...]\n");
+  exit(1);
+}
Index: /trunk/minix/commands/simple/which.c
===================================================================
--- /trunk/minix/commands/simple/which.c	(revision 9)
+++ /trunk/minix/commands/simple/which.c	(revision 9)
@@ -0,0 +1,86 @@
+/* which - search paths for executable */
+
+#define DELIMITER ':'
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+_PROTOTYPE(int main, (int argc, char **argv));
+
+int main(ac, av)
+int ac;
+char **av;
+{
+  char *path, *cp;
+  char buf[400];
+  char prog[400];
+  char patbuf[512];
+  int quit, none;
+  int excode = 0;
+
+  if (ac < 2) {
+	fprintf(stderr, "Usage: %s cmd [cmd, ..]\n", *av);
+	exit(1);
+  }
+  av[ac] = 0;
+  for (av++; *av; av++) {
+
+	quit = 0;
+	none = 1;
+	if ((path = getenv("PATH")) == NULL) {
+		fprintf(stderr, "Null path.\n");
+		exit(0);
+	}
+	strcpy(patbuf, path);
+	path = patbuf;
+	cp = path;
+
+	while (1) {
+		cp = strchr(path, DELIMITER);
+		if (cp == NULL)
+			quit++;
+		else
+			*cp = '\0';
+
+		if (strcmp(path, "") == 0 && quit == 0) {
+			sprintf(buf, "%s./%s", path, *av);
+		} else
+			sprintf(buf, "%s/%s", path, *av);
+
+		/* Fprintf(stderr,"Trying %s, path %s\n",buf,path); */
+
+		path = ++cp;
+
+		if (access(buf, 1) == 0) {
+			printf("%s\n", buf);
+			none = 0;
+		}
+		sprintf(prog, "%s.%s", buf, "prg");
+		if (access(prog, 1) == 0) {
+			printf("%s\n", prog);
+			none = 0;
+		}
+		sprintf(prog, "%s.%s", buf, "ttp");
+		if (access(prog, 1) == 0) {
+			printf("%s\n", prog);
+			none = 0;
+		}
+		sprintf(prog, "%s.%s", buf, "tos");
+		if (access(prog, 1) == 0) {
+			printf("%s\n", prog);
+			none = 0;
+		}
+		if (quit) {
+			if (none) {
+				fprintf(stderr, "No %s in %s\n", *av, getenv("PATH"));
+				excode = 1;
+			}
+			break;
+		}
+	}
+  }
+  return(excode);
+}
Index: /trunk/minix/commands/simple/who.c
===================================================================
--- /trunk/minix/commands/simple/who.c	(revision 9)
+++ /trunk/minix/commands/simple/who.c	(revision 9)
@@ -0,0 +1,72 @@
+/*	who 1.5 - tell who is currently logged in	Author: Kees J. Bot
+ *								9 Jul 1989
+ */
+#define nil 0
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <utmp.h>
+#include <time.h>
+#include <string.h>
+#include <minix/paths.h>
+
+char PATH_UTMP[] = _PATH_UTMP;
+
+char day[] = "SunMonTueWedThuFriSat";
+char month[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
+
+int main(int argc, char **argv)
+{
+	char *tmp= PATH_UTMP;
+	FILE *f;
+	struct utmp ut;
+	struct tm *tm;
+	int slot, wtmp= 0, once= 0;
+
+	if (argc > 3) {
+		fprintf(stderr, "Usage: who <account-file>  |  who am i\n");
+		exit(1);
+	}
+	if (argc == 2) {
+		tmp= argv[1];
+		wtmp= 1;
+	}
+
+	if ((f= fopen(tmp, "r")) == nil) {
+		fprintf(stderr, "who: can't open %s\n", tmp);
+		exit(1);
+	}
+	if (argc == 3) {
+		if ((slot= ttyslot()) < 0) {
+			fprintf(stderr, "who: no access to terminal.\n");
+			exit(1);
+		}
+		fseek(f, (off_t) sizeof(ut) * slot, 0);
+		once= 1;
+	}
+
+	while (fread((char *) &ut, sizeof(ut), 1, f) == 1) {
+		if (!wtmp && ut.ut_name[0] == 0) continue;
+
+		tm= localtime(&ut.ut_time);
+
+		printf("%-9.8s %-9.8s %.3s %.3s %2d %02d:%02d",
+			ut.ut_name,
+			ut.ut_line,
+			day + (3 * tm->tm_wday),
+			month + (3 * tm->tm_mon),
+			tm->tm_mday,
+			tm->tm_hour,
+			tm->tm_min
+		);
+
+		if (ut.ut_host[0] != 0) printf("  (%.*s)",
+				(int) sizeof(ut.ut_host), ut.ut_host);
+
+		printf("\n");
+		if (once) break;
+	}
+	exit(0);
+}
Index: /trunk/minix/commands/simple/whoami.c
===================================================================
--- /trunk/minix/commands/simple/whoami.c	(revision 9)
+++ /trunk/minix/commands/simple/whoami.c	(revision 9)
@@ -0,0 +1,19 @@
+/* whoami - print the current user name 	Author: Terrence W. Holm */
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+_PROTOTYPE(int main, (void));
+
+int main()
+{
+  struct passwd *pw_entry;
+
+  pw_entry = getpwuid(geteuid());
+  if (pw_entry == NULL) exit(1);
+  puts(pw_entry->pw_name);
+  return(0);
+}
Index: /trunk/minix/commands/simple/write.c
===================================================================
--- /trunk/minix/commands/simple/write.c	(revision 9)
+++ /trunk/minix/commands/simple/write.c	(revision 9)
@@ -0,0 +1,269 @@
+/* write - write to a logged in user	Authors: N. Andrew and F. van Kempen */
+
+/*
+ * Usage:	write [-c] [-v] user [tty]
+ *  			-c Read & write one character at a time (cbreak mode)
+ *			-v Verbose
+ *
+ * Version:	1.6	10/24/92
+ *
+ * NOTES:	Write requires 1.4a (or higher) libraries,
+ *		for getopt(), strchr().
+ *
+ * Authors:	Nick Andrew  (nick@nswitgould.oz)  - Public Domain
+ *		Fred van Kempen (minixug!waltje@kyber.uucp)
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <termios.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <time.h>
+#include <stdio.h>
+#include <minix/paths.h>
+
+static char *Version = "@(#) WRITE 1.6 (10/24/92)";
+
+int otty;			/* file desc of callee's terminal */
+short int cbreak = 0;		/* are we in CBREAK (-c) mode? */
+short int verbose = 0;		/* are we in VERBOSE (-v) mode? */
+short int writing = 0;		/* is there a connection? */
+char *user = NULL;	/* callee's user name */
+char *tty = NULL;	/* callee's terminal if given */
+char *ourtty = NULL;	/* our terminal name */
+struct termios ttyold, ttynew;	/* our tty controlling structs */
+
+extern int optind;
+
+_PROTOTYPE(int main, (int argc, char **argv));
+_PROTOTYPE(char *finduser, (void));
+_PROTOTYPE(void settty, (char *utty));
+_PROTOTYPE(void sayhello, (void));
+_PROTOTYPE(void escape, (char *cmd));
+_PROTOTYPE(void writetty, (void));
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(void intr, (int dummy));
+
+char *finduser()
+{
+/* Search the UTMP database for the user we want. */
+
+  static char utmptty[16];
+  struct utmp utmp;
+  struct passwd *userptr;
+  int utmpfd;
+
+  ourtty = ttyname(0);
+  if (ourtty == NULL) ourtty = "/dev/console";
+
+  if (user == NULL) exit(-1);
+  if ((userptr = getpwnam(user)) == NULL) {
+	fprintf(stderr, "No such user: %s\n", user);
+	return(NULL);
+  }
+  if (verbose) fprintf(stderr, "Trying to write to %s\n",
+		userptr->pw_gecos);
+
+  if ((utmpfd = open(_PATH_UTMP, O_RDONLY)) < 0) {
+	fprintf(stderr, "Cannot open utmp file\n");
+	return(NULL);
+  }
+  utmptty[0] = '\0';
+
+  /* We want to find if 'user' is logged on, and return in utmptty[]
+   * 'user' `s terminal, and if 'user' is logged onto the tty the
+   * caller specified, return that tty name. */
+  while (read(utmpfd, (char *) &utmp, sizeof(utmp)) == sizeof(utmp)) {
+	/* is this the user we are looking for? */
+	if (strncmp(utmp.ut_name, user, sizeof(utmp.ut_name))) continue;
+
+	strcpy(utmptty, utmp.ut_line);
+	/* is he on the terminal we want to write to? */
+	if (tty == NULL || !strcmp(utmptty, tty)) {
+		break;
+	}
+  }
+
+  if (utmptty[0] == '\0') {
+	fprintf(stderr, "%s is not logged on\n", user);
+	return( NULL);
+  }
+  if (tty != NULL && strcmp(utmptty, tty)) {
+	fprintf(stderr, "%s is logged onto %s, not %s\n", user, utmptty, tty);
+	return( NULL);
+  }
+  close(utmpfd);
+
+  if (verbose) fprintf(stderr, "Writing to %s on %s\n", user, utmptty);
+  return(utmptty);
+}
+
+
+void settty(utty)
+char *utty;			/* name of terminal found in utmp */
+{
+/* Open other person's terminal and setup our own terminal. */
+
+  char buff[48];
+
+  sprintf(buff, "/dev/%s", utty);
+  if ((otty = open(buff, O_WRONLY)) < 0) {
+	fprintf(stderr, "Cannot open %s to write to %s\n", utty, user);
+	fprintf(stderr, "It may have write permission turned off\n");
+	exit(-1);
+  }
+  tcgetattr(0, &ttyold);
+  tcgetattr(0, &ttynew);
+  ttynew.c_lflag &= ~(ICANON|ECHO);
+  signal(SIGINT, intr);
+  if (cbreak) tcsetattr(0, TCSANOW, &ttynew);
+}
+
+
+void sayhello()
+{
+  struct passwd *pw;
+  char buff[128];
+  long now;
+  char *sp;
+
+  time(&now);
+
+  pw = getpwuid(getuid());
+  if (pw == NULL) {
+	fprintf(stderr, "unknown user\n");
+	exit(-1);
+  }
+  if ((sp = strrchr(ourtty, '/')) != NULL)
+	++sp;
+  else
+	sp = ourtty;
+
+  sprintf(buff, "\nMessage from %s (%s) %-24.24s...\n",
+	pw->pw_name, sp, ctime(&now));
+
+  write(otty, buff, strlen(buff));
+  printf("\007\007");
+  fflush(stdout);
+}
+
+
+void escape(cmd)
+char *cmd;
+{
+/* Shell escape. */
+
+  register char *x;
+
+  write(1, "!\n", 2);
+  for (x = cmd; *x; ++x)
+	if (*x == '\n') *x = '\0';
+
+  system(cmd);
+  write(1, "!\n", 2);
+}
+
+
+void writetty()
+{
+/* The write loop. */
+
+  char line[80];
+  int n, cb_esc;
+
+  writing = 1;
+  cb_esc = 0;
+
+  while ((n = read(0, line, 79)) > 0) {
+	if (line[0] == '\004') break;	/* EOT */
+
+	if (cbreak && line[0] == '\n') cb_esc = 1;
+
+	if (cbreak) write(1, line, n);
+
+	if (line[0] == '!') {
+		if (cbreak && cb_esc) {
+			cb_esc = 0;
+			tcsetattr(0, TCSANOW, &ttyold);
+			read(0, line, 79);
+			escape(line);
+			tcsetattr(0, TCSANOW, &ttynew);
+		} else if (cbreak)
+			write(otty, line, n);
+		else
+			escape(&line[1]);
+		continue;
+	}
+	write(otty, line, n);
+  }
+  write(1, "\nEOT\n", 5);
+  write(otty, "\nEOT\n", 5);
+}
+
+
+void usage()
+{
+  fprintf(stderr, "usage: write [-c] [-v] user [tty]\n");
+  fprintf(stderr, "\t-c : cbreak mode\n\t-v : verbose\n");
+  exit(-1);
+}
+
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  register int c;
+  char *sp;
+
+  setbuf(stdout, (char *) NULL);
+
+  /* Parse options. */
+  while ((c = getopt(argc, argv, "cv")) != EOF) switch (c) {
+	        case 'c':	cbreak = 1;	break;
+	        case 'v':	verbose = 1;	break;
+	    default:
+		usage();
+	}
+
+  /* Parse user and tty arguments */
+  if (optind < argc) {
+	user = argv[optind++];
+
+	/* WTMP usernames are 1-8 chars */
+	if (strlen(user) > 8) *(user + 8) = '\0';
+
+	if (optind < argc) {
+		tty = argv[optind++];
+		if (optind < argc) usage();
+	}
+  } else
+	usage();
+
+  sp = finduser();		/* find which tty to write onto */
+  if (sp != NULL) {	/* did we find one? */
+	settty(sp);		/* setup our terminal */
+	sayhello();		/* print the initial message */
+	writetty();		/* the write loop */
+	tcsetattr(0, TCSANOW, &ttyold);
+	exit(0);
+  }
+  return(-1);
+}
+
+void intr(dummy)
+int dummy;			/* to satisfy the prototype */
+{
+/* The interrupt key has been hit. exit cleanly. */
+
+  signal(SIGINT, SIG_IGN);
+  fprintf(stderr, "\nInterrupt. Exiting write\n");
+  tcsetattr(0, TCSANOW, &ttyold);
+  if (writing) write(otty, "\nEOT\n", 5);
+  exit(0);
+}
Index: /trunk/minix/commands/simple/writeisofs.c
===================================================================
--- /trunk/minix/commands/simple/writeisofs.c	(revision 9)
+++ /trunk/minix/commands/simple/writeisofs.c	(revision 9)
@@ -0,0 +1,1111 @@
+
+/* writeisofs - simple ISO9660-format-image writing utility */
+
+#include <errno.h>
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <ibm/partition.h>
+
+#include <sys/stat.h>
+
+#define Writefield(fd, f) Write(fd, &(f), sizeof(f))
+
+extern char *optarg;
+extern int optind;
+
+typedef unsigned char u_int8_t;
+typedef unsigned short int u_int16_t;
+typedef unsigned long int u_int32_t;
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#define FLAG_DIR	2
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define NAMELEN		(DIRSIZ+5)
+#define ISONAMELEN	12
+#define PLATFORM_80X86	0
+
+#define ISO_SECTOR 2048
+#define VIRTUAL_SECTOR	512
+
+#define CURRENTDIR	"."
+#define PARENTDIR	".."
+
+/*  *** CD (disk) data structures ********************* */
+
+/* primary volume descriptor */
+
+struct pvd {
+	u_int8_t one;
+	char set[6];
+	u_int8_t zero;
+	char system[32];
+	char volume[32];
+	u_int8_t zeroes1[8];
+	u_int32_t sectors[2];
+	u_int8_t zeroes2[32];
+	u_int16_t setsize[2];
+	u_int16_t seq[2];
+	u_int16_t sectorsize[2];
+	u_int32_t pathtable[2];
+	u_int32_t first_little_pathtable_start;
+	u_int32_t second_little_pathtable_start;
+	u_int32_t first_big_pathtable_start;
+	u_int32_t second_big_pathtable_start;
+	u_int8_t rootrecord[34];
+	u_int8_t volumeset[128];
+	u_int8_t publisher[128];
+	u_int8_t preparer[128];
+	u_int8_t application[128];
+	u_int8_t copyrightfile[37];
+	u_int8_t abstractfile[37];
+	u_int8_t bibliofile[37];
+	u_int8_t create[17];
+	u_int8_t modified[17];
+	char expiry[17];
+	u_int8_t effective[17];
+	u_int8_t one2;
+	u_int8_t zero2;
+	u_int8_t zeroes3[512];
+	u_int8_t zeroes4[653];
+};
+
+/* boot record volume descriptor */
+
+struct bootrecord {
+	u_int8_t	indicator;	/* 0 */
+	char		set[5];		/* "CD001" */
+	u_int8_t	version;	/* 1 */
+	char		ident[32];	/* "EL TORITO SPECIFICATION" */
+	u_int8_t	zero[32];	/* unused, must be 0 */
+	u_int32_t	bootcatalog;	/* starting sector of boot catalog */
+	u_int8_t	zero2[1973];	/* unused, must be 0 */
+};
+
+/* boot catalog validation entry */
+
+struct bc_validation {
+	u_int8_t	headerid;	/* 1 */
+	u_int8_t	platform;	/* 0: 80x86; 1: powerpc; 2: mac */
+	u_int8_t	zero[2];	/* unused, must be 0 */
+	char		idstring[24];	/* id string */
+	u_int16_t	checksum;
+	u_int8_t	keys[2];	/* 0x55AA */
+};
+
+/* boot catalog initial/default entry */
+
+#define INDICATE_BOOTABLE	0x88
+
+#define BOOTMEDIA_NONE		0
+#define BOOTMEDIA_120M		1
+#define BOOTMEDIA_144M		2
+#define BOOTMEDIA_288M		3
+#define BOOTMEDIA_HARDDISK	4
+
+struct bc_initial {
+	u_int8_t	indicator;	/* INDICATE_BOOTABLE */
+	u_int8_t	media;		/* BOOTMEDIA_* */
+	u_int16_t	seg;		/* load segment or 0 for default */
+	u_int8_t	type;		/* system type (from part. table) */
+	u_int8_t	zero;
+	u_int16_t	sectors;
+	u_int32_t	startsector;
+	u_int8_t	zero2[20];
+};
+
+/* directory entry */
+
+struct dir {
+	u_int8_t	recordsize;
+	u_int8_t	extended;
+	u_int32_t	datasector[2];
+	u_int32_t	filesize[2];
+	u_int8_t	year;
+	u_int8_t	month;
+	u_int8_t	day;
+	u_int8_t	hour;
+	u_int8_t	minute;
+	u_int8_t	second;
+	u_int8_t	offset;
+	u_int8_t	flags;
+	u_int8_t	interleaved;
+	u_int8_t	interleavegap;
+	u_int16_t	sequence[2];
+	u_int8_t	namelen;
+	char		name[NAMELEN];
+};
+
+/*  *** program (memory) data structures ********************* */
+
+struct node {
+	char name[NAMELEN];
+	int isdir;
+	int pathtablerecord;
+	struct node *firstchild, *nextchild;
+
+	/* filled out at i/o time */
+	u_int32_t startsector, bytesize;
+};
+
+int n_reserved_pathtableentries = 0, n_used_pathtableentries = 0;
+int harddisk_emulation = 0;
+int system_type = 0;
+
+int get_system_type(int fd);
+
+ssize_t
+Write(int fd, void *buf, ssize_t len)
+{
+	ssize_t r;
+	if((r=write(fd, buf, len)) != len) {
+		if(r < 0) { perror("write"); }
+		fprintf(stderr, "failed or short write - aborting.\n");
+		exit(1);
+	}
+	return len;
+}
+
+off_t
+Lseek(int fd, off_t pos, int rel)
+{
+	off_t r;
+
+	if((r=lseek(fd, pos, rel)) < 0) {
+		perror("lseek");
+		fprintf(stderr, "lseek failed - aborting.\n");
+		exit(1);
+	}
+
+	return r;
+}
+
+void
+writesector(int fd, char *block, int *currentsector)
+{
+	Write(fd, block, ISO_SECTOR);
+	(*currentsector)++;
+	return;
+}
+
+void
+seeksector(int fd, int sector, int *currentsector)
+{
+	Lseek(fd, sector*ISO_SECTOR, SEEK_SET);
+	*currentsector = sector;
+}
+
+void
+seekwritesector(int fd, int sector, char *block, int *currentsector)
+{
+	seeksector(fd, sector, currentsector);
+	writesector(fd, block, currentsector);
+}
+
+ssize_t
+Read(int fd, void *buf, ssize_t len)
+{
+	ssize_t r;
+	if((r=read(fd, buf, len)) != len) {
+		if(r < 0) { perror("read"); }
+		fprintf(stderr, "failed or short read.\n");
+		exit(1);
+	}
+
+	return len;
+}
+
+void both16(unsigned char *both, unsigned short i16)
+{
+	unsigned char *little, *big;
+
+	little = both;
+	big = both + 2;
+
+	little[0] = big[1] = i16        & 0xFF;
+	little[1] = big[0] = (i16 >> 8) & 0xFF;
+}
+
+void both32(unsigned char *both, unsigned long i32)
+{
+	unsigned char *little, *big;
+
+	little = both;
+	big = both + 4;
+
+	little[0] = big[3] = i32         & 0xFF;
+	little[1] = big[2] = (i32 >>  8) & 0xFF;
+	little[2] = big[1] = (i32 >> 16) & 0xFF;
+	little[3] = big[0] = (i32 >> 24) & 0xFF;
+}
+
+#define MINDIRLEN	 1
+#define MAXDIRLEN	31
+
+#define MAXLEVEL 8
+
+static int cmpf(const void *v1, const void *v2)
+{
+	struct node *n1, *n2;
+	int i;
+	char f1[NAMELEN], f2[NAMELEN];
+
+	n1 = (struct node *) v1;
+	n2 = (struct node *) v2;
+	strcpy(f1, n1->name);
+	strcpy(f2, n2->name);
+	for(i = 0; i < strlen(f1); i++) f1[i] = toupper(f1[i]);
+	for(i = 0; i < strlen(f2); i++) f2[i] = toupper(f2[i]);
+
+
+	return -strcmp(f1, f2);
+}
+
+void
+maketree(struct node *thisdir, char *name, int level)
+{
+	DIR *dir;
+	struct dirent *e;
+	struct node *dirnodes = NULL;
+	int reserved_dirnodes = 0, used_dirnodes = 0;
+	struct node *child;
+
+	thisdir->firstchild = NULL;
+	thisdir->isdir = 1;
+	thisdir->startsector = 0xdeadbeef;
+
+	if(level >= MAXLEVEL) {
+		fprintf(stderr, "ignoring entries in %s (too deep for iso9660)\n",
+			name);
+		return;
+	}
+
+	if(!(dir = opendir(CURRENTDIR))) {
+		perror("opendir");
+		return;
+	}
+
+	/* how many entries do we need to allocate? */
+	while(readdir(dir)) reserved_dirnodes++;
+	if(!reserved_dirnodes) {
+		closedir(dir);
+		return;
+	}
+
+	if(!(dirnodes = malloc(sizeof(*dirnodes)*reserved_dirnodes))) {
+		fprintf(stderr, "couldn't allocate dirnodes (%d bytes)\n",
+			sizeof(*dirnodes)*reserved_dirnodes);
+		exit(1);
+	}
+
+
+	/* remember all entries in this dir */
+	rewinddir(dir);
+
+	child = dirnodes;
+	while((e=readdir(dir))) {
+		struct stat st;
+		mode_t type;
+		if(!strcmp(e->d_name, CURRENTDIR) || !strcmp(e->d_name, PARENTDIR))
+			continue;
+		if(stat(e->d_name, &st) < 0) {
+			perror(e->d_name);
+			fprintf(stderr, "failed to stat file/dir\n");
+			exit(1);
+		}
+
+		type = st.st_mode & S_IFMT;
+
+/*
+		printf("%s type: %x dir: %x file: %x\n",
+			e->d_name, type, S_IFDIR, S_IFREG);
+			*/
+		if(type != S_IFDIR && type != S_IFREG)
+			continue;
+
+		used_dirnodes++;
+		if(used_dirnodes > reserved_dirnodes) {
+			fprintf(stderr, "huh, directory entries appeared "
+	"(not enough pre-allocated nodes; this can't happen) ?\n");
+			exit(1);
+		}
+
+		if(type == S_IFDIR) {
+			child->isdir = 1;
+		} else {
+			child->isdir = 0;
+			child->firstchild = NULL;
+		}
+		strncpy(child->name, e->d_name, sizeof(child->name));
+
+		child++;
+	}
+
+	closedir(dir);
+
+	if(!used_dirnodes)
+		return;
+
+	if(!(dirnodes=realloc(dirnodes, used_dirnodes*sizeof(*dirnodes)))) {
+		fprintf(stderr, "realloc() of dirnodes failed - aborting\n");
+		exit(1);
+	}
+
+	qsort(dirnodes, used_dirnodes, sizeof(*dirnodes), cmpf);
+
+	child = dirnodes;
+
+	while(used_dirnodes--) {
+		child->nextchild = thisdir->firstchild;
+		thisdir->firstchild = child;
+		if(child->isdir) {
+			if(chdir(child->name) < 0) {
+				perror(child->name);
+			} else {
+				maketree(child, child->name, level+1);
+				if(chdir(PARENTDIR) < 0) {
+					perror("chdir() failed");
+					fprintf(stderr, "couldn't chdir() to parent, aborting\n");
+					exit(1);
+				}
+			}
+		}
+
+		child++;
+	}
+
+}
+
+void
+little32(unsigned char *dest, u_int32_t src)
+{
+	dest[0] = ((src >>  0) & 0xFF);
+	dest[1] = ((src >>  8) & 0xFF);
+	dest[2] = ((src >> 16) & 0xFF);
+	dest[3] = ((src >> 24) & 0xFF);
+
+	return;
+}
+
+void
+little16(unsigned char *dest, u_int16_t src)
+{
+	dest[0] = ((src >>  0) & 0xFF);
+	dest[1] = ((src >>  8) & 0xFF);
+
+	return;
+}
+
+void
+big32(unsigned char *dest, u_int32_t src)
+{
+	dest[3] = ((src >>  0) & 0xFF);
+	dest[2] = ((src >>  8) & 0xFF);
+	dest[1] = ((src >> 16) & 0xFF);
+	dest[0] = ((src >> 24) & 0xFF);
+	return;
+}
+
+void
+big16(unsigned char *dest, u_int16_t src)
+{
+	dest[1] = ((src >>  0) & 0xFF);
+	dest[0] = ((src >>  8) & 0xFF);
+	return;
+}
+
+
+void
+traversetree(struct node *root, int level, int littleendian,
+	int maxlevel, int *bytes, int fd, int parentrecord, int *recordno)
+{
+	struct node *child;
+	struct pte {
+		u_int8_t len;
+		u_int8_t zero;
+		u_int32_t startsector;
+		u_int16_t parent;
+	} pte;
+
+	if(level == maxlevel) {
+		int i;
+		char newname[NAMELEN];
+		if(!root->isdir)
+			return;
+		pte.zero = 0;
+		if(level == 1) {
+			/* root */
+			pte.len = 1;
+			pte.parent = 1;
+			root->name[0] = root->name[1] = '\0';
+		} else {
+			pte.len = strlen(root->name);
+			pte.parent = parentrecord;
+		}
+		pte.startsector = root->startsector;
+		root->pathtablerecord = (*recordno)++;
+
+		if(littleendian) {
+			little32((unsigned char *) &pte.startsector, pte.startsector);
+			little16((unsigned char *) &pte.parent, pte.parent);
+		} else {
+			big32((unsigned char *) &pte.startsector, pte.startsector);
+			big16((unsigned char *) &pte.parent, pte.parent);
+		}
+
+		*bytes += Write(fd, &pte.len, sizeof(pte.len));
+		*bytes += Write(fd, &pte.zero, sizeof(pte.zero));
+		*bytes += Write(fd, &pte.startsector, sizeof(pte.startsector));
+		*bytes += Write(fd, &pte.parent, sizeof(pte.parent));
+		if(!(pte.len%2))
+			root->name[pte.len++] = '\0';
+		for(i = 0; i < pte.len; i++)
+			newname[i] = toupper(root->name[i]);
+		*bytes += Write(fd, newname, pte.len);
+		return;
+	}
+
+	for(child = root->firstchild; child; child = child->nextchild)
+		if(child->isdir)
+			traversetree(child, level+1, littleendian,
+				maxlevel, bytes, fd, root->pathtablerecord,
+					recordno);
+
+	return;
+}
+
+int
+makepathtables(struct node *root, int littleendian, int *bytes, int fd)
+{
+	int level;
+	static char block[ISO_SECTOR];
+	int recordno;
+
+	recordno = 1;
+
+	*bytes = 0;
+
+	for(level = 1; level <= MAXLEVEL; level++)
+		traversetree(root, 1, littleendian, level, bytes, fd, 1, &recordno);
+
+	if(*bytes % ISO_SECTOR) {
+		ssize_t x;
+		x = ISO_SECTOR-(*bytes % ISO_SECTOR);
+		write(fd, block, x);
+		*bytes += x;
+	}
+
+	return *bytes/ISO_SECTOR;
+}
+
+ssize_t
+write_direntry(char *origname, u_int32_t sector, u_int32_t size, int isdir,
+	int fd)
+{
+	int namelen, total = 0;
+	struct dir entry;
+	char copyname[NAMELEN];
+
+	memset(&entry, 0, sizeof(entry));
+
+	if(!strcmp(origname, CURRENTDIR)) {
+		namelen = 1;
+	} else if(!strcmp(origname, PARENTDIR)) {
+		entry.name[0] = '\001';
+		namelen = 1;
+	} else {
+		int i;
+		strcpy(copyname, origname);
+		namelen = strlen(copyname);
+
+		if(namelen > ISONAMELEN) {
+			fprintf(stderr, "%s: truncated, too long for iso9660\n", copyname);
+			namelen = ISONAMELEN;
+			copyname[namelen] = '\0';
+		}
+
+		strcpy(entry.name, copyname);
+		for(i = 0; i < namelen; i++)
+			entry.name[i] = toupper(entry.name[i]);
+
+		/* padding byte + system field */
+		entry.name[namelen]   = '\0';
+		entry.name[namelen+1] = '\0';
+		entry.name[namelen+2] = '\0';
+	}
+	entry.namelen = namelen;	/* original length */
+	if(!(namelen%2)) namelen++;	/* length with padding byte */
+
+
+	/* XXX 2 extra bytes for 'system use'.. */
+	entry.recordsize = 33 + namelen;
+	both32((unsigned char *) entry.datasector, sector);
+	both32((unsigned char *) entry.filesize, size);
+
+	if(isdir) entry.flags = FLAG_DIR;
+
+	/* XXX node date */
+
+	both16((unsigned char *) entry.sequence, 1);
+	
+	 total = Write(fd, &entry.recordsize, sizeof(entry.recordsize));
+	 total += Write(fd, &entry.extended, sizeof(entry.extended));
+	 total += Write(fd, entry.datasector, sizeof(entry.datasector));
+	 total += Write(fd, entry.filesize, sizeof(entry.filesize));
+	 total += Write(fd, &entry.year, sizeof(entry.year));
+	 total += Write(fd, &entry.month, sizeof(entry.month));
+	 total += Write(fd, &entry.day, sizeof(entry.day));
+	 total += Write(fd, &entry.hour, sizeof(entry.hour));
+	 total += Write(fd, &entry.minute, sizeof(entry.minute));
+	 total += Write(fd, &entry.second, sizeof(entry.second));
+	 total += Write(fd, &entry.offset, sizeof(entry.offset));
+	 total += Write(fd, &entry.flags, sizeof(entry.flags));
+	 total += Write(fd, &entry.interleaved, sizeof(entry.interleaved));
+	 total += Write(fd, &entry.interleavegap, sizeof(entry.interleavegap));
+	 total += Write(fd, entry.sequence, sizeof(entry.sequence));
+	 total += Write(fd, &entry.namelen, sizeof(entry.namelen));
+	 total += Write(fd, entry.name, namelen);
+
+	if(total != entry.recordsize || (total % 2) != 0) {
+		printf("%2d, %2d!  ", total, entry.recordsize);
+		printf("%3d = %3d - %2d + %2d\n",
+		entry.recordsize, sizeof(entry), sizeof(entry.name), namelen);
+	}
+
+	return entry.recordsize;
+}
+
+void
+writedata(struct node *parent, struct node *root,
+	int fd, int *currentsector, int dirs, struct dir *rootentry,
+	int rootsize, int remove_after)
+{
+	static char buf[1024*1024];
+	struct node *c;
+	ssize_t written = 0, rest;
+
+	for(c = root->firstchild; c; c = c->nextchild) {
+		if(c->isdir && chdir(c->name) < 0) {
+			perror(c->name);
+			fprintf(stderr, "couldn't chdir to %s - aborting\n",
+				c->name);
+			exit(1);
+		}
+		writedata(root, c, fd, currentsector, dirs, rootentry, rootsize, remove_after);
+		if(c->isdir && chdir(PARENTDIR) < 0) {
+			perror("chdir to ..");
+			fprintf(stderr, "couldn't chdir to parent - "
+				"aborting\n");
+			exit(1);
+		}
+	}
+
+	/* write nodes depth-first, down-top */
+
+	if(root->isdir && dirs) {
+		/* dir */
+		written = 0;
+		root->startsector = *currentsector;
+		written += write_direntry(CURRENTDIR, root->startsector,
+			root->bytesize, root->isdir, fd);
+		if(parent) {
+			written += write_direntry(PARENTDIR, parent->startsector,
+				root->bytesize, root->isdir, fd);
+		} else {
+			written += write_direntry(PARENTDIR, root->startsector,
+				root->bytesize, root->isdir, fd);
+		}
+		for(c = root->firstchild; c; c = c->nextchild) {
+			off_t cur1, cur2;
+			ssize_t written_before;
+			cur1 = Lseek(fd, 0, SEEK_CUR);
+			written_before = written;
+			written += write_direntry(c->name,
+				c->startsector, c->bytesize, c->isdir, fd);
+			cur2 = Lseek(fd, 0, SEEK_CUR);
+			if(cur1/ISO_SECTOR != (cur2-1)/ISO_SECTOR) {
+				/* passed a sector boundary, argh! */
+				Lseek(fd, cur1, SEEK_SET);
+				written = written_before;
+				rest=(ISO_SECTOR-(written % ISO_SECTOR));
+				memset(buf, 0, rest);
+				Write(fd, buf, rest);
+				written += rest;
+				written += write_direntry(c->name,
+				  c->startsector, c->bytesize, c->isdir, fd);
+			}
+		}
+		root->bytesize = written;
+	} else if(!root->isdir && !dirs) {
+		/* file */
+		struct stat st;
+		ssize_t rem;
+		int filefd;
+		
+		if(stat(root->name, &st) < 0) {
+			perror(root->name);
+			fprintf(stderr, "couldn't stat %s - aborting\n", root->name);
+			exit(1);
+		}
+
+		if((filefd = open(root->name, O_RDONLY)) < 0) {
+			perror(root->name);
+			fprintf(stderr, "couldn't open %s - aborting\n", root->name);
+			exit(1);
+		}
+
+		rem = st.st_size;
+
+		root->startsector = *currentsector;
+
+		while(rem > 0) {
+			ssize_t chunk;
+			chunk = min(sizeof(buf), rem);
+			Read(filefd, buf, chunk);
+			Write(fd, buf, chunk);
+			rem -= chunk;
+		}
+
+		close(filefd);
+
+		root->bytesize = written = st.st_size;
+		if(remove_after && unlink(root->name) < 0) {
+			perror("unlink");
+			fprintf(stderr, "couldn't remove %s\n", root->name);
+		}
+	} else { 
+		/* nothing to be done */
+		return;
+	}
+
+	/* fill out sector with zero bytes */
+
+	if((rest=(ISO_SECTOR-(written % ISO_SECTOR)))) {
+		memset(buf, 0, rest);
+		Write(fd, buf, rest);
+		written += rest;
+	}
+
+	/* update dir size with padded size */
+
+	if(root->isdir) { root->bytesize = written; }
+
+	*currentsector += written/ISO_SECTOR;
+}
+
+void
+writebootcatalog(int fd, int  *currentsector, int imagesector, int imagesectors)
+{
+	static char buf[ISO_SECTOR];
+	struct bc_validation validate;
+	struct bc_initial initial;
+
+	ssize_t written, rest;
+	u_int16_t *v, sum = 0;
+	int i;
+
+	/* write validation entry */
+	
+	memset(&validate, 0, sizeof(validate));
+	validate.headerid = 1;
+	validate.platform = PLATFORM_80X86;
+	strcpy(validate.idstring, "");
+	validate.keys[0] = 0x55;
+	validate.keys[1] = 0xaa;
+
+	v = (u_int16_t *) &validate; 
+	for(i = 0; i < sizeof(validate)/2; i++)
+		sum += v[i];
+	validate.checksum = 65535 - sum + 1; /* sum must be 0 */
+
+	written = Write(fd, &validate, sizeof(validate));
+
+	/* write initial/default entry */
+
+	memset(&initial, 0, sizeof(initial));
+
+	initial.indicator = INDICATE_BOOTABLE;
+	if (harddisk_emulation)
+	{
+		initial.media = BOOTMEDIA_HARDDISK;
+		initial.type = system_type;
+	}
+	else
+		initial.media = BOOTMEDIA_144M;
+	/* initial.sectors = imagesectors; */
+	initial.sectors = 1;
+	initial.startsector = imagesector;
+
+	written += Write(fd, &initial, sizeof(initial));
+
+	/* fill out the rest of the sector with 0's */
+
+	if((rest = ISO_SECTOR - (written % 2048))) {
+		memset(buf, 0, sizeof(buf));
+		written += Write(fd, buf, rest);
+	}
+
+	(*currentsector) += written / ISO_SECTOR;
+
+	return;
+}
+
+int
+writebootimage(char *bootimage, int bootfd, int fd, int *currentsector)
+{
+	static char buf[1024*64];
+	ssize_t chunk, written = 0, rest;
+	int virtuals;
+
+	while((chunk=read(bootfd, buf, sizeof(buf))) > 0)
+		written += Write(fd, buf, chunk);
+
+	if(chunk < 0) {
+		perror("read boot image");
+		exit(1);
+	}
+
+	virtuals = written / VIRTUAL_SECTOR;
+
+	if((rest = ISO_SECTOR - (written % 2048))) {
+		memset(buf, 0, sizeof(buf));
+		written += Write(fd, buf, rest);
+	}
+
+	(*currentsector) += written/ISO_SECTOR;
+
+	return virtuals;
+}
+
+void
+writebootrecord(int fd, int *currentsector, int bootcatalogsector)
+{
+	int i;
+	static struct bootrecord bootrecord;
+	ssize_t w = 0;
+	/* boot record volume descriptor */
+
+	memset(&bootrecord, 0, sizeof(bootrecord));
+	bootrecord.set[0] = 'C';
+	bootrecord.set[1] = 'D';
+	bootrecord.set[2] = '0';
+	bootrecord.set[3] = '0';
+	bootrecord.set[4] = '1';
+	bootrecord.version = 1;
+	bootrecord.bootcatalog = bootcatalogsector;
+	strcpy(bootrecord.ident, "EL TORITO SPECIFICATION");
+	for(i = strlen(bootrecord.ident);
+		i < sizeof(bootrecord.ident); i++)
+		bootrecord.ident[i] = '\0';
+
+	w  = Writefield(fd, bootrecord.indicator);
+	w += Writefield(fd, bootrecord.set);
+	w += Writefield(fd, bootrecord.version);
+	w += Writefield(fd, bootrecord.ident);
+	w += Writefield(fd, bootrecord.zero);
+	w += Writefield(fd, bootrecord.bootcatalog);
+	w += Writefield(fd, bootrecord.zero2);
+
+	if(w != ISO_SECTOR) {
+		fprintf(stderr, "WARNING: something went wrong - boot record (%d) isn't a sector size (%d)\n",
+			w, ISO_SECTOR);
+	}
+
+	(*currentsector)++;
+}
+
+int
+main(int argc, char *argv[])
+{
+	int currentsector = 0;
+	int imagesector, imagesectors;
+	int bootfd, fd, i, ch, nsectors;
+	int remove_after = 0;
+	static char block[ISO_SECTOR];
+	static struct pvd pvd;
+	char *label = "ISO9660";
+	struct tm *now;
+	time_t nowtime;
+	char timestr[20], *prog;
+	char *bootimage = NULL;
+	struct node root;
+	int pvdsector;
+	int bigpath, littlepath, pathbytes = 0, dirsector, filesector, enddir;
+	int bootvolumesector, bootcatalogsector;
+
+	prog = argv[0];
+
+	/* This check is to prevent compiler padding screwing up
+	 * our format.
+	 */
+
+	if(sizeof(struct pvd) != ISO_SECTOR) {
+		fprintf(stderr, "Something confusing happened at\n"
+			"compile-time; pvd should be a sector size. %d != %d\n",
+			sizeof(struct pvd), ISO_SECTOR);
+		return 1;
+	}
+
+	while ((ch = getopt(argc, argv, "Rb:hl:")) != -1) {
+		switch(ch) {
+			case 'h':
+				harddisk_emulation= 1;
+				break;
+			case 'l':
+				label = optarg;
+				break;
+			case 'r':
+				remove_after = 1;
+				break;
+			case 'b':
+				bootimage = optarg;
+				if((bootfd = open(bootimage, O_RDONLY)) < 0) {
+					perror(bootimage);
+					return 1;
+				}
+				break;
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	if(argc != 2) {
+		fprintf(stderr, "usage: %s [-l <label>] [-b <bootfloppyimage>] <dir> <isofile>\n",
+			prog);
+		return 1;
+	}
+
+	/* create .iso file */
+
+	if((fd=open(argv[1], O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0) {
+		perror(argv[1]);
+		return 1;
+	}
+
+	/* go to where the iso has to be made from */
+
+	if(chdir(argv[0]) < 0) {
+		perror(argv[0]);
+		return 1;
+	}
+
+	/* collect dirs and files */
+
+	fprintf(stderr, " * traversing input tree\n");
+
+	maketree(&root, "", 1);
+
+	fprintf(stderr, " * writing initial zeroes and pvd\n");
+
+	/* first sixteen sectors are zero */
+
+	memset(block, 0, sizeof(block));
+
+	for(i = 0; i < 16; i++)
+		writesector(fd, block, &currentsector);
+
+	/* Primary Volume Descriptor */
+	memset(&pvd, 0, sizeof(pvd));
+	pvd.one = 1;
+	pvd.set[0] = 67;
+	pvd.set[1] = 68;
+	pvd.set[2] = 48;
+	pvd.set[3] = 48;
+	pvd.set[4] = 49;
+	pvd.set[5] =  1;
+	pvd.set[5] =  1;
+
+	strncpy(pvd.volume, label, sizeof(pvd.volume)-1);
+	for(i = strlen(pvd.volume); i < sizeof(pvd.volume); i++)
+		pvd.volume[i] = ' ';
+	for(i = 0; i < sizeof(pvd.system); i++)
+		pvd.system[i] = ' ';
+
+	both16((unsigned char *) pvd.setsize, 1);
+	both16((unsigned char *) pvd.seq, 1);
+	both16((unsigned char *) pvd.sectorsize, ISO_SECTOR);
+
+	/* fill time fields */
+	time(&nowtime);
+	now = gmtime(&nowtime);
+	strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S000", now);
+	memcpy(pvd.create, timestr, strlen(timestr));
+	memcpy(pvd.modified, timestr, strlen(timestr));
+	memcpy(pvd.effective, timestr, strlen(timestr));
+	strcpy(pvd.expiry, "0000000000000000");	/* not specified */
+	pvdsector = currentsector;
+
+	writesector(fd, (char *) &pvd, &currentsector);
+
+	if(bootimage) {
+		fprintf(stderr, " * writing boot record volume descriptor\n");
+		bootvolumesector = currentsector;
+		writebootrecord(fd, &currentsector, 0);
+	}
+
+	/* volume descriptor set terminator */
+	memset(block, 0, sizeof(block));
+	block[0] = 255;
+	block[1] =  67;
+	block[2] =  68;
+	block[3] =  48;
+	block[4] =  48;
+	block[5] =  49;
+	block[6] =   1;
+
+	writesector(fd, block, &currentsector);
+
+	if(bootimage) {
+		/* write the boot catalog */
+		fprintf(stderr, " * writing the boot catalog\n");
+		bootcatalogsector = currentsector;
+		if (harddisk_emulation)
+			system_type = get_system_type(bootfd);
+		writebootcatalog(fd, &currentsector, imagesector, imagesectors);
+
+		/* write boot image */
+		fprintf(stderr, " * writing the boot image\n");
+		imagesector = currentsector;
+		imagesectors = writebootimage(bootimage, bootfd,
+			fd, &currentsector);
+		fprintf(stderr, " * image: %d virtual sectors @ sector 0x%x\n",
+			imagesectors, imagesector);
+
+		close(bootfd);
+	}
+
+	/* write out all the file data */
+
+	filesector = currentsector;
+	fprintf(stderr, " * writing file data\n");
+	writedata(NULL, &root, fd, &currentsector, 0,
+		(struct dir *) &pvd.rootrecord, sizeof(pvd.rootrecord),
+		remove_after);
+
+	/* write out all the dir data */
+
+	dirsector = currentsector;
+	fprintf(stderr, " * writing dir data\n");
+	writedata(NULL, &root, fd, &currentsector, 1,
+		(struct dir *) &pvd.rootrecord, sizeof(pvd.rootrecord),
+			remove_after);
+	enddir = currentsector;
+	seeksector(fd, dirsector, &currentsector);
+	fprintf(stderr, " * rewriting dir data\n");
+	fflush(NULL);
+	writedata(NULL, &root, fd, &currentsector, 1,
+		(struct dir *) &pvd.rootrecord, sizeof(pvd.rootrecord),
+			remove_after);
+	if(currentsector != enddir) {
+		fprintf(stderr, "warning: inconsistent directories - "
+			"I have a bug! iso may be broken.\n");
+	}
+
+	/* now write the path table in both formats */
+
+	fprintf(stderr, " * writing big-endian path table\n");
+	bigpath = currentsector;
+	currentsector += makepathtables(&root, 0, &pathbytes, fd);
+
+	fprintf(stderr, " * writing little-endian path table\n");
+	littlepath = currentsector;
+	currentsector += makepathtables(&root, 1, &pathbytes, fd);
+
+	/* this is the size of the iso filesystem for use in the pvd later */
+
+	nsectors = currentsector;
+	both32((unsigned char *) pvd.sectors, nsectors);
+
+	/* *********** Filesystem writing done ************************* */
+
+	/* finish and rewrite the pvd. */
+	fprintf(stderr, " * rewriting pvd\n");
+	seekwritesector(fd, pvdsector, (char *) &pvd, &currentsector);
+
+	both32((unsigned char *) pvd.pathtable, pathbytes);
+	little32((unsigned char *) &pvd.first_little_pathtable_start, littlepath);
+	little32((unsigned char *) &pvd.first_big_pathtable_start, bigpath);
+
+	/* write root dir entry in pvd */
+	seeksector(fd, pvdsector, &currentsector);
+	Lseek(fd, (int)((char *) &pvd.rootrecord - (char *) &pvd), SEEK_CUR);
+	if(write_direntry(CURRENTDIR, root.startsector, root.bytesize,
+		root.isdir, fd) > sizeof(pvd.rootrecord)) {
+		fprintf(stderr, "warning: unexpectedly large root record\n");
+	}
+
+	if(bootimage) {
+		fprintf(stderr, " * rewriting boot catalog\n");
+		seeksector(fd, bootcatalogsector, &currentsector);
+		writebootcatalog(fd, &currentsector, imagesector, imagesectors);
+
+		/* finish and rewrite the boot record volume descriptor */
+		fprintf(stderr, " * rewriting the boot rvd\n");
+		seeksector(fd, bootvolumesector, &currentsector);
+		writebootrecord(fd, &currentsector, bootcatalogsector);
+	}
+
+	fprintf(stderr, " * all ok\n");
+
+	return 0;
+}
+
+int get_system_type(int fd)
+{
+	off_t old_pos;
+	size_t size;
+	ssize_t r;
+	int type;
+	struct part_entry *partp;
+	unsigned char bootsector[512];
+
+	errno= 0;
+	old_pos= lseek(fd, SEEK_SET, 0);
+	if (old_pos == -1 && errno != 0)
+	{
+		fprintf(stderr, "bootimage file is not seekable: %s\n",
+			strerror(errno));
+		exit(1);
+	}
+	size= sizeof(bootsector);
+	r= read(fd, bootsector, size);
+	if (r != size)
+	{
+		fprintf(stderr, "error reading bootimage file: %s\n",
+			r < 0 ? strerror(errno) : "unexpected EOF");
+		exit(1);
+	}
+	if (bootsector[size-2] != 0x55 && bootsector[size-1] != 0xAA)
+	{
+		fprintf(stderr, "bad magic in bootimage file\n");
+		exit(1);
+	}
+
+	partp= (struct part_entry *)&bootsector[PART_TABLE_OFF];
+	type= partp->sysind;
+	if (type == NO_PART)
+	{
+		fprintf(stderr, "first partition table entry is unused\n");
+		exit(1);
+	}
+	if (!(partp->bootind & ACTIVE_FLAG))
+	{
+		fprintf(stderr, "first partition table entry is not active\n");
+		exit(1);
+	}
+
+	lseek(fd, SEEK_SET, old_pos);
+	return type;
+}
Index: /trunk/minix/commands/simple/xargs.c
===================================================================
--- /trunk/minix/commands/simple/xargs.c	(revision 9)
+++ /trunk/minix/commands/simple/xargs.c	(revision 9)
@@ -0,0 +1,424 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * John B. Roll Jr.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1990 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)xargs.c	5.11 (Berkeley) 6/19/91";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#if __minix
+#define _PATH_ECHO	"/bin/echo"
+#else
+#include "pathnames.h"
+#endif
+
+#ifndef ARG_MAX
+#define ARG_MAX		(sizeof(int) == 2 ? 4096 : 128 * 1024)
+#endif
+
+int exit_status = 0;
+int tflag;
+void err(const char *, ...);
+void run(char **argv);
+void usage(void);
+
+int main(int argc, char **argv)
+{
+	extern int optind;
+	extern char *optarg;
+	register int ch;
+	register char *p, *bbp, *ebp, **bxp, **exp, **xp;
+	int cnt, indouble, insingle, nargs, nflag, nline, xflag, zflag;
+	char **av, *argp;
+
+	/*
+	 * POSIX.2 limits the exec line length to ARG_MAX - 2K.  Running that
+	 * caused some E2BIG errors, so it was changed to ARG_MAX - 4K.  Given
+	 * that the smallest argument is 2 bytes in length, this means that
+	 * the number of arguments is limited to:
+	 *
+	 *	 (ARG_MAX - 4K - LENGTH(utility + arguments)) / 2.
+	 *
+	 * We arbitrarily limit the number of arguments to 5000.  This is
+	 * allowed by POSIX.2 as long as the resulting minimum exec line is
+	 * at least LINE_MAX.  Realloc'ing as necessary is possible, but
+	 * probably not worthwhile.
+	 */
+#if !__minix || __minix_vmd
+	nargs = 5000;
+	nline = ARG_MAX - 4 * 1024;
+#else
+	/* Things are more cramped under standard Minix. */
+	nargs = 80 * sizeof(int);
+	nline = ARG_MAX - 512 * sizeof(int);
+#endif
+	nflag = xflag = zflag = 0;
+	while ((ch = getopt(argc, argv, "n:s:tx0")) != EOF)
+		switch(ch) {
+		case 'n':
+			nflag = 1;
+			if ((nargs = atoi(optarg)) <= 0)
+				err("illegal argument count");
+			break;
+		case 's':
+			nline = atoi(optarg);
+			break;
+		case 't':
+			tflag = 1;
+			break;
+		case 'x':
+			xflag = 1;
+			break;
+		case '0':
+			zflag = 1;
+			break;
+		case '?':
+		default:
+			usage();
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (xflag && !nflag)
+		usage();
+
+	/*
+	 * Allocate pointers for the utility name, the utility arguments,
+	 * the maximum arguments to be read from stdin and the trailing
+	 * NULL.
+	 */
+	if (!(av = bxp =
+	    malloc((u_int)(1 + argc + nargs + 1) * sizeof(char **))))
+		err("%s", strerror(errno));
+
+	/*
+	 * Use the user's name for the utility as argv[0], just like the
+	 * shell.  Echo is the default.  Set up pointers for the user's
+	 * arguments.
+	 */
+	if (!*argv)
+		cnt = strlen(*bxp++ = _PATH_ECHO);
+	else {
+		cnt = 0;
+		do {
+			cnt += strlen(*bxp++ = *argv) + 1;
+		} while (*++argv);
+	}
+
+	/*
+	 * Set up begin/end/traversing pointers into the array.  The -n
+	 * count doesn't include the trailing NULL pointer, so the malloc
+	 * added in an extra slot.
+	 */
+	exp = (xp = bxp) + nargs;
+
+	/*
+	 * Allocate buffer space for the arguments read from stdin and the
+	 * trailing NULL.  Buffer space is defined as the default or specified
+	 * space, minus the length of the utility name and arguments.  Set up
+	 * begin/end/traversing pointers into the array.  The -s count does
+	 * include the trailing NULL, so the malloc didn't add in an extra
+	 * slot.
+	 */
+	nline -= cnt;
+	if (nline <= 0)
+		err("insufficient space for command");
+
+	if (!(bbp = malloc((u_int)nline + 1)))
+		err("%s", strerror(errno));
+	ebp = (argp = p = bbp) + nline - 1;
+
+	if (zflag) {
+		/* Read pathnames terminated by null bytes as produced by
+		 * find ... -print0.  No comments in this code, see further
+		 * below.
+		 */
+		for (;;)
+			switch(ch = getchar()) {
+			case EOF:
+				if (p == bbp)
+					exit(exit_status);
+
+				if (argp == p) {
+					*xp = NULL;
+					run(av);
+					exit(exit_status);
+				}
+				/*FALL THROUGH*/
+			case '\0':
+				if (argp == p)
+					continue;
+
+				*p = '\0';
+				*xp++ = argp;
+
+				if (xp == exp || p == ebp || ch == EOF) {
+					if (xflag && xp != exp && p == ebp)
+						err(
+					   "insufficient space for arguments");
+					*xp = NULL;
+					run(av);
+					if (ch == EOF)
+						exit(exit_status);
+					p = bbp;
+					xp = bxp;
+				} else
+					++p;
+				argp = p;
+				break;
+			default:
+				if (p < ebp) {
+					*p++ = ch;
+					break;
+				}
+
+				if (bxp == xp)
+					err("insufficient space for argument");
+				if (xflag)
+					err("insufficient space for arguments");
+
+				*xp = NULL;
+				run(av);
+				xp = bxp;
+				cnt = ebp - argp;
+				bcopy(argp, bbp, cnt);
+				p = (argp = bbp) + cnt;
+				*p++ = ch;
+				break;
+			}
+		/* NOTREACHED */
+	}
+
+	for (insingle = indouble = 0;;)
+		switch(ch = getchar()) {
+		case EOF:
+			/* No arguments since last exec. */
+			if (p == bbp)
+				exit(exit_status);
+
+			/* Nothing since end of last argument. */
+			if (argp == p) {
+				*xp = NULL;
+				run(av);
+				exit(exit_status);
+			}
+			goto arg1;
+		case ' ':
+		case '\t':
+			/* Quotes escape tabs and spaces. */
+			if (insingle || indouble)
+				goto addch;
+			goto arg2;
+		case '\n':
+			/* Empty lines are skipped. */
+			if (argp == p)
+				continue;
+
+			/* Quotes do not escape newlines. */
+arg1:			if (insingle || indouble)
+				 err("unterminated quote");
+
+arg2:			*p = '\0';
+			*xp++ = argp;
+
+			/*
+			 * If max'd out on args or buffer, or reached EOF,
+			 * run the command.  If xflag and max'd out on buffer
+			 * but not on args, object.
+			 */
+			if (xp == exp || p == ebp || ch == EOF) {
+				if (xflag && xp != exp && p == ebp)
+					err("insufficient space for arguments");
+				*xp = NULL;
+				run(av);
+				if (ch == EOF)
+					exit(exit_status);
+				p = bbp;
+				xp = bxp;
+			} else
+				++p;
+			argp = p;
+			break;
+		case '\'':
+			if (indouble)
+				goto addch;
+			insingle = !insingle;
+			break;
+		case '"':
+			if (insingle)
+				goto addch;
+			indouble = !indouble;
+			break;
+		case '\\':
+			/* Backslash escapes anything, is escaped by quotes. */
+			if (!insingle && !indouble && (ch = getchar()) == EOF)
+				err("backslash at EOF");
+			/* FALLTHROUGH */
+		default:
+addch:			if (p < ebp) {
+				*p++ = ch;
+				break;
+			}
+
+			/* If only one argument, not enough buffer space. */
+			if (bxp == xp)
+				err("insufficient space for argument");
+			/* Didn't hit argument limit, so if xflag object. */
+			if (xflag)
+				err("insufficient space for arguments");
+
+			*xp = NULL;
+			run(av);
+			xp = bxp;
+			cnt = ebp - argp;
+			bcopy(argp, bbp, cnt);
+			p = (argp = bbp) + cnt;
+			*p++ = ch;
+			break;
+		}
+	/* NOTREACHED */
+}
+
+void run(char **argv)
+{
+	register char **p;
+	pid_t pid;
+	int noinvoke;
+	int status;
+	int pfd[2];
+
+	if (tflag) {
+		(void)fprintf(stderr, "%s", *argv);
+		for (p = argv + 1; *p; ++p)
+			(void)fprintf(stderr, " %s", *p);
+		(void)fprintf(stderr, "\n");
+		(void)fflush(stderr);
+	}
+	if (pipe(pfd) < 0) err("pipe: %s", strerror(errno));
+
+	switch(pid = fork()) {
+	case -1:
+		err("fork: %s", strerror(errno));
+	case 0:
+		close(pfd[0]);
+		fcntl(pfd[1], F_SETFD, fcntl(pfd[1], F_GETFD) | FD_CLOEXEC);
+
+		execvp(argv[0], argv);
+		noinvoke = (errno == ENOENT) ? 127 : 126;
+		(void)fprintf(stderr,
+		    "xargs: %s exec failed: %s.\n", argv[0], strerror(errno));
+
+		/* Modern way of returning noinvoke instead of a dirty vfork()
+		 * trick:					(kjb)
+		 */
+		write(pfd[1], &noinvoke, sizeof(noinvoke));
+		_exit(-1);
+	}
+	close(pfd[1]);
+	if (read(pfd[0], &noinvoke, sizeof(noinvoke)) < sizeof(noinvoke))
+		noinvoke = 0;
+	close(pfd[0]);
+
+	pid = waitpid(pid, &status, 0);
+	if (pid == -1)
+		err("waitpid: %s", strerror(errno));
+
+	/*
+	 * If we couldn't invoke the utility or the utility didn't exit
+	 * properly, quit with 127 or 126 respectively.
+	 */
+	if (noinvoke)
+		exit(noinvoke);
+
+	/*
+	 * According to POSIX, we have to exit if the utility exits with
+	 * a 255 status, or is interrupted by a signal.   xargs is allowed
+	 * to return any exit status between 1 and 125 in these cases, but
+	 * we'll use 124 and 125, the same values used by GNU xargs.
+	 */
+	if (WIFEXITED(status)) {
+		if (WEXITSTATUS (status) == 255) {
+			fprintf (stderr, "xargs: %s exited with status 255\n",
+				 argv[0]);
+			exit(124);
+		} else if (WEXITSTATUS (status) != 0) {
+			exit_status = 123;
+		}
+	} else if (WIFSTOPPED (status)) {
+		fprintf (stderr, "xargs: %s terminated by signal %d\n",
+			 argv[0], WSTOPSIG (status));
+		exit(125);
+	} else if (WIFSIGNALED (status)) {
+		fprintf (stderr, "xargs: %s terminated by signal %d\n",
+			 argv[0], WTERMSIG (status));
+		exit(125);
+	}
+}
+
+void usage(void)
+{
+	(void)fprintf(stderr,
+"usage: xargs [-t0] [[-x] -n number] [-s size] [utility [argument ...]]\n");
+	exit(1);
+}
+
+void err(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	(void)fprintf(stderr, "xargs: ");
+	(void)vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	(void)fprintf(stderr, "\n");
+	exit(1);
+	/* NOTREACHED */
+}
Index: /trunk/minix/commands/simple/yes.c
===================================================================
--- /trunk/minix/commands/simple/yes.c	(revision 9)
+++ /trunk/minix/commands/simple/yes.c	(revision 9)
@@ -0,0 +1,23 @@
+/*	yes 1.4 - print 'y' or argv[1] continuously.	Author: Kees J. Bot
+ *								15 Apr 1989
+ */
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char **argv)
+{
+	char *yes;
+	static char y[] = "y";
+	int n;
+
+	yes= argc == 1 ? y : argv[1];
+
+	n= strlen(yes);
+		
+	yes[n++]= '\n';
+
+	while (write(1, yes, n) != -1) {}
+	exit(1);
+}
Index: /trunk/minix/commands/syslogd/.depend
===================================================================
--- /trunk/minix/commands/syslogd/.depend	(revision 9)
+++ /trunk/minix/commands/syslogd/.depend	(revision 9)
@@ -0,0 +1,94 @@
+
+logger.o:	/usr/include/ansi.h
+logger.o:	/usr/include/ctype.h
+logger.o:	/usr/include/errno.h
+logger.o:	/usr/include/minix/sys_config.h
+logger.o:	/usr/include/minix/type.h
+logger.o:	/usr/include/stdio.h
+logger.o:	/usr/include/stdlib.h
+logger.o:	/usr/include/string.h
+logger.o:	/usr/include/sys/dir.h
+logger.o:	/usr/include/sys/types.h
+logger.o:	/usr/include/syslog.h
+logger.o:	/usr/include/unistd.h
+logger.o:	logger.c
+
+syslog.o:	/usr/include/ansi.h
+syslog.o:	/usr/include/errno.h
+syslog.o:	/usr/include/fcntl.h
+syslog.o:	/usr/include/minix/ioctl.h
+syslog.o:	/usr/include/minix/sys_config.h
+syslog.o:	/usr/include/minix/type.h
+syslog.o:	/usr/include/net/gen/in.h
+syslog.o:	/usr/include/net/gen/inet.h
+syslog.o:	/usr/include/net/gen/netdb.h
+syslog.o:	/usr/include/net/gen/udp.h
+syslog.o:	/usr/include/net/gen/udp_io.h
+syslog.o:	/usr/include/net/hton.h
+syslog.o:	/usr/include/net/ioctl.h
+syslog.o:	/usr/include/net/netlib.h
+syslog.o:	/usr/include/stdarg.h
+syslog.o:	/usr/include/stdio.h
+syslog.o:	/usr/include/stdlib.h
+syslog.o:	/usr/include/string.h
+syslog.o:	/usr/include/sys/dir.h
+syslog.o:	/usr/include/sys/ioc_cmos.h
+syslog.o:	/usr/include/sys/ioc_disk.h
+syslog.o:	/usr/include/sys/ioc_file.h
+syslog.o:	/usr/include/sys/ioc_memory.h
+syslog.o:	/usr/include/sys/ioc_scsi.h
+syslog.o:	/usr/include/sys/ioc_sound.h
+syslog.o:	/usr/include/sys/ioc_tape.h
+syslog.o:	/usr/include/sys/ioc_tty.h
+syslog.o:	/usr/include/sys/ioctl.h
+syslog.o:	/usr/include/sys/types.h
+syslog.o:	/usr/include/syslog.h
+syslog.o:	/usr/include/time.h
+syslog.o:	/usr/include/unistd.h
+syslog.o:	syslog.c
+
+syslog_test.o:	/usr/include/ansi.h
+syslog_test.o:	/usr/include/minix/sys_config.h
+syslog_test.o:	/usr/include/minix/type.h
+syslog_test.o:	/usr/include/sys/types.h
+syslog_test.o:	/usr/include/syslog.h
+syslog_test.o:	/usr/include/unistd.h
+syslog_test.o:	syslog_test.c
+
+syslogd.o:	/usr/include/ansi.h
+syslogd.o:	/usr/include/ctype.h
+syslogd.o:	/usr/include/errno.h
+syslogd.o:	/usr/include/fcntl.h
+syslogd.o:	/usr/include/limits.h
+syslogd.o:	/usr/include/minix/ioctl.h
+syslogd.o:	/usr/include/minix/sys_config.h
+syslogd.o:	/usr/include/minix/type.h
+syslogd.o:	/usr/include/net/gen/in.h
+syslogd.o:	/usr/include/net/gen/netdb.h
+syslogd.o:	/usr/include/net/gen/udp.h
+syslogd.o:	/usr/include/net/gen/udp_io.h
+syslogd.o:	/usr/include/net/hton.h
+syslogd.o:	/usr/include/net/ioctl.h
+syslogd.o:	/usr/include/net/netlib.h
+syslogd.o:	/usr/include/signal.h
+syslogd.o:	/usr/include/stdio.h
+syslogd.o:	/usr/include/stdlib.h
+syslogd.o:	/usr/include/string.h
+syslogd.o:	/usr/include/sys/dir.h
+syslogd.o:	/usr/include/sys/ioc_cmos.h
+syslogd.o:	/usr/include/sys/ioc_disk.h
+syslogd.o:	/usr/include/sys/ioc_file.h
+syslogd.o:	/usr/include/sys/ioc_memory.h
+syslogd.o:	/usr/include/sys/ioc_scsi.h
+syslogd.o:	/usr/include/sys/ioc_sound.h
+syslogd.o:	/usr/include/sys/ioc_tape.h
+syslogd.o:	/usr/include/sys/ioc_tty.h
+syslogd.o:	/usr/include/sys/ioctl.h
+syslogd.o:	/usr/include/sys/select.h
+syslogd.o:	/usr/include/sys/time.h
+syslogd.o:	/usr/include/sys/types.h
+syslogd.o:	/usr/include/sys/wait.h
+syslogd.o:	/usr/include/syslog.h
+syslogd.o:	/usr/include/time.h
+syslogd.o:	/usr/include/unistd.h
+syslogd.o:	syslogd.c
Index: /trunk/minix/commands/syslogd/CHANGELOG
===================================================================
--- /trunk/minix/commands/syslogd/CHANGELOG	(revision 9)
+++ /trunk/minix/commands/syslogd/CHANGELOG	(revision 9)
@@ -0,0 +1,17 @@
+Version 1.1	Oct. 28, 2000
+  -	first release for testing.
+
+Version 1.2	Jan. 23, 2001
+  -	Changed pidfile directory to '/usr/spool/locks'
+	so at boot old file is deleted.
+  -	Changed the 'debug' variable to 'DbgOpt' so 'debug'
+	can be a preprocessor define from Makefile.
+
+Version 1.3
+  -	Changes for Minix 3.0
+  -	Changed pidfile to /var/run/syslogd.pid and added code
+	for setting pathname from Makefile
+  -	Merged code from usyslogd.c to handle kernel messages.
+  -	Reworked Makefile to make a correct installation
+
+$Id: CHANGELOG,v 1.1 2006/04/03 13:07:42 beng Exp $
Index: /trunk/minix/commands/syslogd/Makefile
===================================================================
--- /trunk/minix/commands/syslogd/Makefile	(revision 9)
+++ /trunk/minix/commands/syslogd/Makefile	(revision 9)
@@ -0,0 +1,44 @@
+##
+##  @(#)Makefile	1.00	Jan. 11, 2000
+##
+##  Makefile for syslogd/klogd
+##  $Id: Makefile,v 1.2 2006/04/04 12:52:22 beng Exp $
+
+BINDIR	= /usr/bin
+
+CC	= exec cc
+RM	= rm -f
+EXTRA	= -DPIDFILE=\"/var/run/syslogd.pid\"
+CPPFLAGS= -D_MINIX -D_POSIX_SOURCE -Ddebug=0 $(EXTRA) -I.
+CFLAGS	= -m -O $(CPPFLAGS)
+MKDEP	= mkdep "$(CC) -E $(CPPFLAGS)"
+LDFLAGS = -i -o $@
+TARGETS = logger syslogd
+
+SRCS =	logger.c syslog.c syslog_test.c syslogd.c
+OBJS =	logger.o syslog.o syslog_test.o syslogd.o
+
+all: $(TARGETS)	
+
+syslogd:	syslogd.o
+	$(CC) $? $(LDFLAGS)
+	@install -S 8kw $@
+
+syslog_test: syslog_test.o syslog.o
+	$(CC) syslog_test.o syslog.o $(LDFLAGS)
+	@install -S 2kw $@
+
+logger: logger.o syslog.o
+	$(CC) logger.o syslog.o $(LDFLAGS)
+	@install -S 2kw $@
+
+clean:
+	$(RM) $(OBJS) $(TARGETS) syslog_test *.BAK core
+
+install:	$(BINDIR)/logger $(BINDIR)/syslog_test $(BINDIR)/syslogd
+$(BINDIR)/logger:	logger
+	install -cs -m 755 -o bin -g operator $? $@
+$(BINDIR)/syslog_test:	syslog_test
+	install -cs -m 755 -o bin -g operator $? $@
+$(BINDIR)/syslogd:	syslogd
+	install -cs -m 700 -o root -g operator $? $@
Index: /trunk/minix/commands/syslogd/README
===================================================================
--- /trunk/minix/commands/syslogd/README	(revision 9)
+++ /trunk/minix/commands/syslogd/README	(revision 9)
@@ -0,0 +1,69 @@
+This is just syslogd and the test programs now. syslog() is in libc 4.2
+syslogd has been changed to use /proc/kmsg for kernel messages. It also
+avoids making any terminal it opens its controlling terminal. Otherwise
+we have a dodgy race condition between processes connecting to terminals
+which can result in the terminal having the wrong group at the wrong time.
+The syslog() in libc 4.2 needs changing to use O_NOCTTY on its opens as
+well.
+
+Mike Jagdis	Internet: jaggy@purplet.demon.co.uk
+		FidoNet:  Mike Jagdis, 2:252/305
+
+---------------------------------------------------------------------------
+
+                           Syslogd and Syslog.o
+
+These are the syslogd and syslog ported from 4.3BSD (that's the new one with
+the *very* flexible config file).  
+
+Syslogd is essentially unchanged from the 4.3BSD, with the exception that
+*nothing* is ever logged to the console (BAD thing to do on a UNIXpc).  You
+can configure it (via /etc/syslog.conf) to log messages in different
+logfiles (depending upon the sender's facility code and the priority), log
+to users' terminals (same dependancies), and if things get real bad, it can
+do a wall (write-all; same dependancies).
+
+Syslog is really only modified in that it uses UDP datagrams because I had
+no luck at all using UNIX domain sockets on the 3B1.  See syslog.h for
+facility codes and priorities that can be used.
+
+
+BUGS:
+Messages from facilities LOG_KERN, LOG_USER, and LOG_PRT never can be
+wall-ed, no matter how high the priority.  I'm still trying to decide if
+this is a bug or a feature. :-)
+
+
+ALSO INCLUDED:
+
+Syslog_test, sendlog (to use from shell scripts) and logger (for use in
+shell script also).
+
+NEEDED:
+
+The resolver routines in libresolv.a are not needed, but allow you to log to
+hosts not present in /etc/hosts and to accept logging from same.
+
+-----------------------------------------------------------------------
+
+Fixed up UNIX domain socket code, added Linux specific code to read messages
+from the kernel.
+
+The #ifdefs are now :-
+
+SYSLOG_INET	listen on a UDP socket (syslogd)
+		log via UDP (syslog library call)
+
+SYSLOG_UNIXAF	listen on a UNIX domain socker (syslogd)
+		log via UNIX domain (syslogd library)
+
+SYSLOG_KERNEL	fork a second copy to read kernel messages using
+		syslog system call.
+
+syslogd should be built with one or more of these flags, libsyslog.a should
+be built with SYSLOG_INET or SYSLOG_UNIXAF, SYSLOG_INET is used in preference
+to SYSLOG_UNIXAF.
+
+readlog is a program which reads from the kernel and records the messages
+it finds in syslogd via the normal library call interface, it can be run
+instead of building syslogd with SYSLOG_KERNEL.
Index: /trunk/minix/commands/syslogd/README.minix
===================================================================
--- /trunk/minix/commands/syslogd/README.minix	(revision 9)
+++ /trunk/minix/commands/syslogd/README.minix	(revision 9)
@@ -0,0 +1,28 @@
+
+
+   This is the porting to Minix of the "syslogd" facility
+   available on many other *nix systems.
+
+   Since I' m still using an old 286 machine for my Minix
+   environment, I choosed to start from an old implementation
+   which has only the basic features. The result is a smaller
+   program, more suitable for 16 bits machines.
+
+   The file syslog.c should be included in C compiler library
+   (libc.a) or directly linked with prorams requiring syslog.
+
+   If you choose the former solution, you must recreate the 
+   library.  After having copied the file syslog.c to the 
+   directory '/usr/src/libs/other' you have to modify the 
+   Makefile in this directory adding syslog.c.
+
+   Then issue a 'make' command in the '/usr/src/libs' and wait 
+   a while.  Then issue 'make install' to install the new object.
+
+   NOTE:   The network must be configured, up and running for
+	   the package to work
+
+   Giovanni Falzoni <gfalzoni@inwind.it>
+
+   $Id: README.minix,v 1.1 2006/04/03 13:07:42 beng Exp $
+
Index: /trunk/minix/commands/syslogd/logger.c
===================================================================
--- /trunk/minix/commands/syslogd/logger.c	(revision 9)
+++ /trunk/minix/commands/syslogd/logger.c	(revision 9)
@@ -0,0 +1,188 @@
+/* Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * #ifndef lint
+ * char copyright[] =
+ * "@(#) Copyright (c) 1983 Regents of the University of California.\n\
+ *  All rights reserved.\n";
+ * #endif
+ *
+ * #ifndef lint
+ * static char sccsid[] = "@(#)logger.c	6.8 (Berkeley) 6/29/88";
+ * #endif
+ *
+ * Porting to Minix by G. Falzoni <gfalzoni@inwind.it>
+ * $Id: logger.c,v 1.1 2006/04/03 13:07:42 beng Exp $
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+** 	LOGGER -- read and log utility
+**
+**	This program reads from an input and arranges to write the
+**	result on the system log, along with a useful tag.
+*/
+
+#define  SYSLOG_NAMES
+#include <syslog.h>
+
+/*
+**	Name:		void bailout(char *msg, char *arg);
+**	Function:	Handles error exit.
+*/
+void bailout(const char *msg, const char *arg)
+{
+
+  fprintf(stderr, "logger: %s %s\n", msg, arg);
+  exit(EXIT_FAILURE);
+}
+
+/*
+**	Name:		int decode(char *name, struct code * codetab);
+**	Function:	Decodes a name to the equivalent priority/facility.
+*/
+int decode(char *name, const struct _code * codetab)
+{
+  const struct _code *c;
+
+  if (isdigit(*name)) return(atoi(name));
+
+  for (c = codetab; c->c_name; c++)
+	if (!strcasecmp(name, c->c_name)) return(c->c_val);
+
+  return(-1);
+}
+
+/*
+**	Name:		int pencode(char *s);
+**	Function:	Decode a symbolic name (facility/priority)
+**			to a numeric value.
+*/
+int pencode(char *s)
+{
+  char *save;
+  int fac, lev;
+
+  for (save = s; *s && *s != '.'; ++s);
+  if (*s) {
+	*s = '\0';
+	fac = decode(save, FacNames);
+	if (fac < 0) bailout("unknown facility name:", save);
+	*s++ = '.';
+  } else {
+	fac = 0;
+	s = save;
+  }
+  lev = decode(s, PriNames);
+  if (lev < 0) bailout("unknown priority name:", save);
+  return((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
+}
+
+/*
+**	Name:		int main(int argc, char **argv);
+**	Function:	Main entry for logger.
+*/
+int main(int argc, char **argv)
+{
+  int pri = LOG_NOTICE;
+  int ch, logflags = 0;
+  char *tag, buf[200];
+  static const char usage[] =
+  "[-i] [-f file] [-p pri] [-t tag] [ message ... ]";
+
+  tag = NULL;
+  while ((ch = getopt(argc, argv, "f:ip:t:")) != EOF) {
+	switch ((char) ch) {
+	    case 'f':		/* file to log */
+		if (freopen(optarg, "r", stdin) == NULL) {
+			bailout(strerror(errno), optarg);
+		}
+		break;
+	    case 'i':		/* log process id also */
+		logflags |= LOG_PID;
+		break;
+	    case 'p':		/* priority */
+		pri = pencode(optarg);
+		break;
+	    case 't':		/* tag */
+		tag = optarg;
+		break;
+	    case '?':
+	    default:	bailout(usage, "");	break;
+	}
+  }
+  argc -= optind;
+  argv += optind;
+
+  /* Setup for logging */
+  openlog(tag ? tag : getlogin(), logflags, 0);
+  fclose(stdout);
+
+  if (argc > 0) {		/* Log input line if appropriate */
+	char *p, *endp;
+	int len;
+
+	for (p = buf, endp = buf + sizeof(buf) - 1;;) {
+		len = strlen(*argv);
+		if (p + len < endp && p > buf) {
+			*--p = '\0';
+			syslog(pri, buf);
+			p = buf;
+		}
+		if (len > sizeof(buf) - 1) {
+			syslog(pri, *argv++);
+			if (!--argc) break;
+		} else {
+			memcpy(p, *argv++, len);
+			p += len;
+			if (!--argc) break;
+			*p++ = ' ';
+			*--p = '\0';
+		}
+	}
+	if (p != buf) {
+		*p = '\0';
+		syslog(pri, buf);
+	}
+  } else			/* Main loop */
+	while (fgets(buf, sizeof(buf), stdin) != NULL) syslog(pri, buf);
+
+  return EXIT_SUCCESS;
+}
+
+/** logger.c **/
Index: /trunk/minix/commands/syslogd/syslog.c
===================================================================
--- /trunk/minix/commands/syslogd/syslog.c	(revision 9)
+++ /trunk/minix/commands/syslogd/syslog.c	(revision 9)
@@ -0,0 +1,167 @@
+/* Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * #if defined(LIBC_SCCS) && !defined(lint)
+ * static char sccsid[] = "@(#)syslog.c    8.4 (Berkeley) 3/18/94";
+ * #endif
+ *
+ * Author: Eric Allman
+ * Modified to use UNIX domain IPC by Ralph Campbell
+ * Patched March 12, 1996 by A. Ian Vogelesang <vogelesang@hdshq.com>
+ * Rewritten by Martin Mares <mj@atrey.karlin.mff.cuni.cz> on May 14, 1997
+ * Rewritten by G. Falzoni <gfalzoni@inwind.it> for porting to Minix
+ *
+ * $Id: syslog.c,v 1.1 2006/04/03 13:07:42 beng Exp $
+ */
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <sys/ioctl.h>
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+#include <net/gen/netdb.h>
+#include <errno.h>
+#include <net/gen/inet.h>
+
+static int LogPid = (-1);
+static int nfd = (-1);
+static int LogFacility = LOG_USER;
+static int LogFlags = 0;
+static char TagBuffer[40] = "syslog";
+
+/*
+** OPENLOG -- open system log
+** 	- establishes a channel to syslogd using UDP device
+**	  (port 514 is used _ syslog/udp)
+**	- stores program tag (if not NULL) and other options
+**	  for use by syslog
+*/
+void openlog(const char *ident, int option, int facility)
+{
+  struct nwio_udpopt udpopt;
+
+  /* Stores logging flags */
+  LogFlags = option & (LOG_PID | LOG_PERROR | LOG_CONS);
+  /* Stores process id. if LOG_PID was specified */
+  if (option & LOG_PID) LogPid = getpid();
+  /* Stores the requested facility */
+  LogFacility = facility;
+  /* Stores log tag if supplied */
+  if (ident != NULL && *ident != '0' && ident != TagBuffer) {
+	strncpy(TagBuffer, ident, sizeof(TagBuffer));
+	TagBuffer[sizeof(TagBuffer) - 1] = '0';
+  }
+
+  /* Opens channel to syslog daemon via UDP device */
+  /* Static values used to minimize code */
+  if (option & LOG_NDELAY) {
+	/* Opens UDP device */
+	if ((nfd = open(UDP_DEVICE, O_RDWR)) < 0) {
+		 /* Report error */ ;
+	}
+	/* Sets options for UDP device */
+	udpopt.nwuo_flags = NWUO_SHARED | NWUO_LP_SET | NWUO_DI_LOC |
+		NWUO_DI_BROAD | NWUO_RP_SET | NWUO_RA_SET |
+		NWUO_RWDATONLY | NWUO_DI_IPOPT;
+	udpopt.nwuo_locaddr = udpopt.nwuo_remaddr = htonl(0x7F000001L);
+	udpopt.nwuo_locport = udpopt.nwuo_remport = htons(514);
+	if (ioctl(nfd, NWIOSUDPOPT, &udpopt) < 0 ||
+	    ioctl(nfd, NWIOGUDPOPT, &udpopt) < 0) {
+		 /* Report error */ ;
+	}
+  }
+  return;
+}
+
+/*
+**  SYSLOG -- print message on log file
+**
+**  This routine looks a lot like printf, except that it outputs to the
+**  log file instead of the standard output.  Also:
+**	- adds a timestamp,
+**	- prints the module name in front of the message,
+**	- has some other formatting types (or will sometime),
+**	- adds a newline on the end of the message.
+**
+** The output of this routine is intended to be read by syslogd(8).
+*/
+void syslog(int lprty, const char *msg,...)
+{
+  time_t now;
+  char buff[512];
+  int len, rc;
+  va_list ap;
+
+  /* First log message open chnnel to syslog */
+  if (nfd < 0) openlog(TagBuffer, LogFlags | LOG_NDELAY, LogFacility);
+  time(&now);
+  len = sprintf(buff, "<%d>%.15s %s: ",
+		LogFacility | lprty, ctime(&now) + 4, TagBuffer);
+  if (LogFlags & LOG_PID) {
+	len -= 2;
+	len += sprintf(buff + len, "[%d]: ", LogPid);
+  }
+  va_start(ap, msg);
+  len += vsprintf(buff + len, msg, ap);
+  va_end(ap);
+  rc = write(nfd, buff, len);
+  if ((rc != len && LogFlags & LOG_CONS) || LogFlags & LOG_PERROR) {
+	write(STDERR_FILENO, buff, len);
+	write(STDERR_FILENO, "\n", 1);
+  }
+  return;
+}
+
+/*
+**  CLOSELOG -- close access to syslogd
+**	- closes UDP channel
+**	- restores default values
+*/
+void closelog(void)
+{
+
+  close(nfd);
+  LogPid = nfd = -1;
+  LogFacility = LOG_USER;
+  LogFlags = 0;
+  return;
+}
+
+/** syslog.c **/
Index: /trunk/minix/commands/syslogd/syslog_test.c
===================================================================
--- /trunk/minix/commands/syslogd/syslog_test.c	(revision 9)
+++ /trunk/minix/commands/syslogd/syslog_test.c	(revision 9)
@@ -0,0 +1,30 @@
+/*
+**	syslog_test
+**
+**	Author:		Giovanni Falzoni <gfalzoni@inwind.it>
+**	$Id: syslog_test.c,v 1.1 2006/04/03 13:07:42 beng Exp $
+*/
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <syslog.h>
+
+/*
+**	SYSLOG TEST
+**	Very simple utility to test syslog facility.
+*/
+void main(void)
+{
+  int ix;
+
+  openlog("syslog_test", LOG_PID | LOG_NDELAY | LOG_PERROR | LOG_CONS, LOG_DAEMON);
+
+  for (ix = LOG_EMERG; ix <= LOG_DEBUG; ix += 1) {
+	sleep(2);
+	syslog(ix, "message from test program - log level %d", ix);
+  }
+  closelog();
+  return;
+}
+
+/** syslog_test.c **/
Index: /trunk/minix/commands/syslogd/syslogd.c
===================================================================
--- /trunk/minix/commands/syslogd/syslogd.c	(revision 9)
+++ /trunk/minix/commands/syslogd/syslogd.c	(revision 9)
@@ -0,0 +1,932 @@
+/*
+**  Copyright (c) 1983, 1988
+**  The Regents of the University of California.  All rights reserved.
+**
+**  Redistribution and use in source and binary forms, with or without
+**  modification, are permitted provided that the following conditions
+**  are met:
+**  1. Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**  2. Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in the
+**     documentation and/or other materials provided with the distribution.
+**  3. All advertising materials mentioning features or use of this software
+**     must display the following acknowledgement:
+**       This product includes software developed by the University of
+**       California, Berkeley and its contributors.
+**  4. Neither the name of the University nor the names of its contributors
+**     may be used to endorse or promote products derived from this software
+**     without specific prior written permission.
+**
+**  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+**  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+**  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+**  ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+**  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+**  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+**  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+**  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+**  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+**  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+**  SUCH DAMAGE.
+**
+**  #ifndef lint
+**  char copyright2[] =
+**  "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
+**   All rights reserved.\n";
+**  #endif
+**
+**  #ifndef lint
+**  static char sccsid[] = "@(#)syslogd.c	5.27 (Berkeley) 10/10/88";
+**  #endif
+**
+**  -----------------------------------------------------------------------
+**
+**  SYSLOGD -- log system messages
+**	This program implements a system log.
+**	It takes a series of lines and outputs them according to the setup
+**	defined in the configuration file.
+**	Each line may have a priority, signified as "<n>" as
+**	the first characters of the line.  If this is
+**	not present, a default priority is used.
+**
+**	To kill syslogd, send a signal 15 (terminate).
+**	A signal 1 (hup) will cause it to reread its configuration file.
+**
+**  Defined Constants:
+**	MAXLINE   -- the maximimum line length that can be handled.
+**	MAXSVLINE -- the length of saved messages (for filtering)
+**	DEFUPRI   -- the default priority for user messages
+**	DEFSPRI   -- the default priority for kernel messages
+**
+**  Author: Eric Allman
+**  extensive changes by Ralph Campbell
+**  more extensive changes by Eric Allman (again)
+**  changes by Steve Lord
+**
+**  Extensive rewriting by G. Falzoni <gfalzoni@inwind.it> for porting to Minix
+** 
+**  $Log: syslogd.c,v $
+**  Revision 1.3  2006/04/04 14:22:40  beng
+**  Fix
+**
+**  Revision 1.2  2006/04/04 14:18:16  beng
+**  Make syslogd work, even if it can only open klog and not udp or vice versa
+**  (but not neither)
+**
+**  Revision 1.1  2006/04/03 13:07:42  beng
+**  Kick out usyslogd in favour of syslogd Giovanni's syslogd port
+**
+**  Revision 1.3  2005/09/16 10:10:12  lsodgf0
+**  Rework for Minix 3.  Adds kernel logs from /dev/klogd
+**
+**  $Id: syslogd.c,v 1.3 2006/04/04 14:22:40 beng Exp $
+*/
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/wait.h>
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+#include <net/gen/netdb.h>
+
+#define SYSLOG_NAMES
+#include <syslog.h>
+#define KLOGD 1
+/** Define following values to your requirements **/
+#define	MAXLINE		512	/* maximum line length */
+#define	MAXSVLINE	256	/* maximum saved line length */
+
+#define DEFUPRI		(LOG_USER|LOG_NOTICE)
+#define DEFSPRI 	(LOG_KERN|LOG_CRIT)
+
+/* Flags to logmsg() */
+#define IGN_CONS	0x001	/* don't print on console */
+#define SYNC_FILE	0x002	/* do fsync on file after printing */
+#define ADDDATE		0x004	/* add a date to the message */
+#define MARK		0x008	/* this message is a mark */
+
+#define	CTTY		"/dev/log"	/* Minix log device (console) */
+
+#define	dprintf	if(DbgOpt!=0)printf
+#if debug == 0
+#define DEBUG(statement)
+#else
+#define DEBUG(statement) statement
+#endif
+#if !defined PIDFILE
+#define PIDFILE	"/var/run/syslogd.pid"
+#endif
+
+#define UNAMESZ		8	/* length of a login name */
+#define MAXUNAMES	20	/* maximum number of user names */
+#define MAXFNAME	200	/* max file pathname length */
+#define MAXHOSTNAMELEN 	64	/* max length of FQDN host name */
+
+/* Intervals at which we flush out "message repeated" messages,
+ * in seconds after previous message is logged.  After each flush,
+ * we move to the next interval until we reach the largest.  */
+#define TIMERINTVL	30	/* interval for checking flush, mark */
+#define INTERVAL1 	30
+#define INTERVAL2 	60
+#define	MAXREPEAT ((sizeof(repeatinterval)/sizeof(repeatinterval[0]))-1)
+#define	REPEATTIME(f) ((f)->f_time+repeatinterval[(f)->f_repeatcount])
+#define	BACKOFF(f) {if(++(f)->f_repeatcount>MAXREPEAT)(f)->f_repeatcount=MAXREPEAT;}
+
+/* Values for f_type */
+#define F_UNUSED 	0	/* unused entry */
+#define F_FILE 		1	/* regular file */
+#define F_TTY 		2	/* terminal */
+#define F_CONSOLE 	3	/* console terminal */
+#define F_FORW 		4	/* remote machine */
+#define F_USERS 	5	/* list of users */
+#define F_WALL 		6	/* everyone logged on */
+
+#define max(a,b) ((a)>=(b)?(a):(b))
+
+/* This structure represents the files that will have log copies printed */
+struct filed {
+  struct filed *f_next;		/* next in linked list */
+  short f_type;			/* entry type, see below */
+  short f_file;			/* file descriptor */
+  time_t f_time;		/* time this was last written */
+  char f_pmask[LOG_NFACILITIES + 1];	/* priority mask */
+  union {
+	char f_uname[MAXUNAMES][UNAMESZ + 1];
+	char f_fname[MAXFNAME];
+  } f_un;
+  char f_prevline[MAXSVLINE];	/* last message logged */
+  char f_lasttime[16];		/* time of last occurrence */
+  char f_prevhost[MAXHOSTNAMELEN + 1];	/* host from which recd. */
+  int f_prevpri;		/* pri of f_prevline */
+  int f_prevlen;		/* length of f_prevline */
+  int f_prevcount;		/* repetition cnt of prevline */
+  int f_repeatcount;		/* number of "repeated" msgs */
+  int f_flags;			/* store some additional flags */
+};
+
+static const char *const TypeNames[] =
+{
+ "UNUSED", "FILE", "TTY", "CONSOLE", "FORW", "USERS", "WALL", NULL,
+};
+
+static struct filed *Files = NULL;
+static struct filed consfile;
+static int DbgOpt = 0;		/* debug flag */
+static char LocalHostName[MAXHOSTNAMELEN + 1];	/* our hostname */
+static int Initialized = 0;	/* set when we have initialized ourselves */
+static int MarkInterval = 20 * 60;	/* interval between marks in seconds */
+static int MarkSeq = 0;		/* mark sequence number */
+static time_t now;
+
+static const char *ConfFile = "/etc/syslog.conf";
+static const char *PidFile = PIDFILE;	/* "/var/run/syslogd.pid" */
+static const char ctty[] = CTTY;
+
+static const char ProgName[] = "syslogd:";
+static const char version[] = "1.3 (Minix)";
+static const char usage[] =
+ /* */ "usage:\tsyslogd [-d] [-m markinterval] [-f conf-file]\n"
+       "\t\t[-p listeningport] [-v] [-?]\n" ;
+static const int repeatinterval[] =
+ /* */ {INTERVAL1, INTERVAL2,};	/* # of secs before flush */
+
+/*
+**  Name:	void wallmsg(struct filed *fLog, char *message);
+**  Function:	Write the specified message to either the entire
+**		world, or a list of approved users.
+*/
+void wallmsg(struct filed * fLog, char *message)
+{
+
+  return;
+}
+
+/*
+**  Name:	void fprintlog(struct filed *fLog, int flags, char *message);
+**  Function:
+*/
+void fprintlog(struct filed * fLog, int flags, char *message)
+{
+  int len;
+  char line[MAXLINE + 1];
+  char repbuf[80];
+
+  if (message == NULL) {
+	if (fLog->f_prevcount > 1) {
+		sprintf(repbuf, "last message repeated %d times", fLog->f_prevcount);
+		message = repbuf;
+	} else
+		message = fLog->f_prevline;
+  }
+  sprintf(line, "%s %s %s", fLog->f_lasttime, fLog->f_prevhost, message);
+  DEBUG(dprintf("Logging to %s", TypeNames[fLog->f_type]);)
+  fLog->f_time = now;
+  switch (fLog->f_type) {
+      case F_UNUSED:		/* */
+	DEBUG(dprintf("\n");)
+	break;
+      case F_CONSOLE:
+	if (flags & IGN_CONS) {
+      case F_FORW:		/* */
+		DEBUG(dprintf(" (ignored)\n");)
+		break;
+	}			/* else Fall Through */
+      case F_TTY:
+      case F_FILE:
+	DEBUG(dprintf(" %s\n", fLog->f_un.f_fname);)
+	strcat(line, fLog->f_type != F_FILE ? "\r\n" : "\n");
+	len = strlen(line);
+	if (write(fLog->f_file, line, len) != len) {
+		 /* Handle errors */ ;
+	} else if (flags & SYNC_FILE)
+		sync();
+	break;
+      case F_USERS:
+      case F_WALL:
+	DEBUG(dprintf("\n");)
+	strcat(line, "\r\n");
+	wallmsg(fLog, line);
+	break;
+  }
+  fLog->f_prevcount = 0;
+  return;
+}
+
+/*
+**  Name:	void logmsg(int pri, char *msg, char *from, int flags);
+**  Function:	Log a message to the appropriate log files, users, etc.
+**		based on the priority.
+*/
+void logmsg(int pri, char *msg, char *from, int flags)
+{
+  struct filed *f;
+  int fac, prilev;
+  int omask, msglen;
+  char *timestamp;
+
+  DEBUG(dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n", pri, flags, from, msg);)
+/*
+  omask = sigblock(__sigmask(SIGHUP) | __sigmask(SIGALRM));
+*/
+  /* Check to see if msg looks non-standard. */
+  msglen = strlen(msg);
+  if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' ||
+      msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')
+	flags |= ADDDATE;
+
+  time(&now);
+  if (flags & ADDDATE)
+	timestamp = ctime(&now) + 4;
+  else {
+	timestamp = msg;
+	msg += 16;
+	msglen -= 16;
+  }
+
+  /* Extract facility and priority level */
+  fac = (flags & MARK) ? LOG_NFACILITIES : LOG_FAC(pri);
+  prilev = LOG_PRI(pri);
+
+  /* Log the message to the particular outputs */
+  if (!Initialized) {
+	/* Not yet initialized. Every message goes to console */
+	f = &consfile;
+	f->f_file = open(ctty, O_WRONLY | O_NOCTTY);
+	if (f->f_file >= 0) {
+		if (!DbgOpt) setsid();
+		fprintlog(f, flags, msg);
+		close(f->f_file);
+	}
+  } else {
+	for (f = Files; f; f = f->f_next) {
+
+		/* Skip messages that are incorrect priority */
+		if (f->f_pmask[fac] < prilev || f->f_pmask[fac] == INTERNAL_NOPRI)
+			continue;
+
+		if (f->f_type == F_CONSOLE && (flags & IGN_CONS)) continue;
+
+		/* Don't output marks to recently written files */
+		if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2)
+			continue;
+
+		/* Suppress duplicate lines to this file */
+		if ((flags & MARK) == 0 && msglen == f->f_prevlen &&
+		    !strcmp(msg, f->f_prevline) &&
+		    !strcmp(from, f->f_prevhost)) {
+			strncpy(f->f_lasttime, timestamp, 15);
+			f->f_prevcount += 1;
+			DEBUG(dprintf("msg repeated %d times, %ld sec of %d\n",
+				f->f_prevcount, now - f->f_time,
+				repeatinterval[f->f_repeatcount]);)
+			/* If domark would have logged this by now,
+			 * flush it now (so we don't hold isolated
+			 * messages), but back off so we'll flush
+			 * less often in the future. */
+			if (now > REPEATTIME(f)) {
+				fprintlog(f, flags, (char *) NULL);
+				BACKOFF(f);
+			}
+		} else {
+			/* New line, save it */
+			if (f->f_prevcount) fprintlog(f, 0, (char *) NULL);
+			f->f_repeatcount = 0;
+			strncpy(f->f_lasttime, timestamp, 15);
+			strncpy(f->f_prevhost, from, sizeof(f->f_prevhost));
+			if (msglen < MAXSVLINE) {
+				f->f_prevlen = msglen;
+				f->f_prevpri = pri;
+				strcpy(f->f_prevline, msg);
+				fprintlog(f, flags, (char *) NULL);
+			} else {
+				f->f_prevline[0] = 0;
+				f->f_prevlen = 0;
+				fprintlog(f, flags, msg);
+			}
+		}
+	}
+  }
+
+/*
+  sigsetmask(omask);
+*/
+  return;
+}
+
+/*
+**  Name:	void logerror(char *type);
+**  Function:	Prints syslogd errors in some place.
+*/
+void logerror(char *type)
+{
+  char buf[100];
+
+  if (errno == 0) sprintf(buf, "%s %s", ProgName, type);
+
+  else if (errno >= _NERROR)
+	sprintf(buf, "%s %s - error %d", ProgName, type, errno);
+
+  else
+	sprintf(buf, "%s %s - %s", ProgName, type, strerror(errno));
+
+  errno = 0;
+  dprintf("%s\n", buf);
+  logmsg(LOG_SYSLOG | LOG_ERR, buf, LocalHostName, ADDDATE);
+  return;
+}
+
+/*
+**  Name:	void die(int sig);
+**  Function:	Signal handler for kill signals.
+*/
+void die(int sig)
+{
+  struct filed *f;
+  char buf[100];
+
+  for (f = Files; f != NULL; f = f->f_next) {
+	/* Flush any pending output */
+	if (f->f_prevcount) fprintlog(f, 0, NULL);
+  }
+  if (sig >= 0) {
+	DEBUG(dprintf("%s exiting on signal %d\n", ProgName, sig);)
+	sprintf(buf, "exiting on signal %d", sig);
+	errno = 0;
+	logerror(buf);
+  }
+  unlink(PidFile);
+  exit(sig == (-1) ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+/*
+**  Name:	void domark(int sig);
+**  Function:	Signal handler for alarm.
+**		Used for messages filtering and mark facility.
+*/
+void domark(int sig)
+{
+  struct filed *f;
+
+  now = time(NULL);
+  MarkSeq += TIMERINTVL;
+  if (MarkSeq >= MarkInterval) {
+	logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE | MARK);
+	MarkSeq = 0;
+  }
+  for (f = Files; f; f = f->f_next) {
+	if (f->f_prevcount && now >= REPEATTIME(f)) {
+		DEBUG(dprintf("flush %s: repeated %d times, %d sec.\n",
+			TypeNames[f->f_type], f->f_prevcount,
+			repeatinterval[f->f_repeatcount]);)
+		fprintlog(f, 0, NULL);
+		BACKOFF(f);
+	}
+  }
+  signal(SIGALRM, domark);
+  alarm(TIMERINTVL);
+  return;
+}
+
+/*
+**  Name:	int decode(char *name, struct _code *codetab);
+**  Function:	Decode a symbolic name to a numeric value
+*/
+int decode(char *name, const struct _code *codetab)
+{
+  const struct _code *c;
+  char *p;
+  char buf[40];
+
+  DEBUG(dprintf("symbolic name: %s", name);)
+  if (isdigit(*name)) return (atoi(name));
+
+  strcpy(buf, name);
+  for (p = buf; *p; p += 1) {
+	if (isupper(*p)) *p = tolower(*p);
+  }
+  for (c = codetab; c->c_name; c += 1) {
+	if (!strcmp(buf, c->c_name)) {
+		DEBUG(dprintf(" ==> %d\n", c->c_val);)
+		return (c->c_val);
+	}
+  }
+  return (-1);
+}
+
+/*
+**  Name:	void cfline(char *line, struct filed *f);
+**  Function:	Parse a configuration file line
+*/
+void cfline(char *line, struct filed * fLog)
+{
+  char *p, *q, *bp;
+  int ix, pri;
+  char buf[MAXLINE];
+  char xbuf[200];
+
+  DEBUG(dprintf("cfline(%s)\n", line);)
+
+  /* Keep sys_errlist stuff out of logerror messages */
+  errno = 0;
+
+  /* Clear out file entry */
+  memset(fLog, 0, sizeof(*fLog));
+  for (ix = 0; ix <= LOG_NFACILITIES; ix += 1)	/* */
+	fLog->f_pmask[ix] = INTERNAL_NOPRI;
+
+  /* Scan through the list of selectors */
+  for (p = line; *p && *p != '\t';) {
+
+	/* Find the end of this facility name list */
+	for (q = p; *q && *q != '\t' && *q++ != '.';) continue;
+
+	/* Collect priority name */
+	for (bp = buf; *q && !strchr("\t,;", *q);) *bp++ = *q++;
+	*bp = '\0';
+
+	/* Skip cruft */
+	while (strchr(", ;", *q)) q++;
+
+	/* Decode priority name */
+	pri = decode(buf, PriNames);
+	if (pri < 0) {
+		sprintf(xbuf, "unknown priority name \"%s\"", buf);
+		logerror(xbuf);
+		return;
+	}
+
+	/* Scan facilities */
+	while (*p && !strchr("\t.;", *p)) {
+		for (bp = buf; *p && !strchr("\t,;.", *p);) *bp++ = *p++;
+		*bp = '\0';
+		if (*buf == '*') {
+			for (ix = 0; ix <= LOG_NFACILITIES; ix += 1)
+				if ((fLog->f_pmask[ix] < pri) ||
+				    (fLog->f_pmask[ix] == INTERNAL_NOPRI)) {
+					fLog->f_pmask[ix] = pri;
+				}
+		} else {
+			ix = decode(buf, FacNames);
+			if (ix < 0) {
+				sprintf(xbuf, "unknown facility name \"%s\"", buf);
+				logerror(xbuf);
+				return;
+			}
+			if ((fLog->f_pmask[ix >> 3] < pri) ||
+			(fLog->f_pmask[ix >> 3] == INTERNAL_NOPRI)) {
+				fLog->f_pmask[ix >> 3] = pri;
+			}
+		}
+		while (*p == ',' || *p == ' ') p++;
+	}
+	p = q;
+  }
+
+  /* Skip to action part */
+  while (*p == '\t' || *p == ' ') p++;
+
+  DEBUG(dprintf("leading char in action: %c\n", *p);)
+  switch (*p) {
+      case '@':			/* Logging to a remote host */
+	break;			/* NOT IMPLEMENTED */
+
+      case '/':			/* Logging to a local file/device */
+	strcpy(fLog->f_un.f_fname, p);
+	DEBUG(dprintf("filename: %s\n", p);	/* ASP */)
+	if ((fLog->f_file = open(p, O_WRONLY | O_APPEND | O_CREAT | O_NOCTTY, 0644)) < 0) {
+		fLog->f_file = F_UNUSED;
+		sprintf(xbuf, "unknown file/device (%s)", p);
+		logerror(xbuf);
+		break;
+	}
+	if (isatty(fLog->f_file)) {
+		if (!DbgOpt) setsid();
+		fLog->f_type = F_TTY;
+	} else
+		fLog->f_type = F_FILE;
+	if (strcmp(p, ctty) == 0) fLog->f_type = F_CONSOLE;
+	break;
+
+      case '*':			/* Logging to all users */
+	DEBUG(dprintf("write-all\n");)
+	fLog->f_type = F_WALL;
+	break;
+
+      default:			/* Logging to selected users */
+	DEBUG(dprintf("users: %s\n", p);	/* ASP */)
+	for (ix = 0; ix < MAXUNAMES && *p; ix += 1) {
+		for (q = p; *q && *q != ',';) q += 1;
+		strncpy(fLog->f_un.f_uname[ix], p, UNAMESZ);
+		if ((q - p) > UNAMESZ)
+			fLog->f_un.f_uname[ix][UNAMESZ] = '\0';
+		else
+			fLog->f_un.f_uname[ix][q - p] = '\0';
+		while (*q == ',' || *q == ' ') q++;
+		p = q;
+	}
+	fLog->f_type = F_USERS;
+	break;
+  }
+}
+
+/*
+**  Name:  	void printline(char *hname, char *msg);
+**  Function:	Takes a raw input line, decodes the message and
+**	  	prints the message on the appropriate log files.
+*/
+void printline(char *hname, char *msg)
+{
+  char line[MAXLINE + 1];
+  char *p = msg, *q = line;
+  int ch, pri = DEFUPRI;
+
+  /* Test for special codes */
+  if (*p == '<') {
+	pri = 0;
+	while (isdigit(*++p)) {
+		if ((*p - '0') < 8) {
+			/* Only 3 bits allocated for pri -- ASP */
+			pri = 10 * pri + (*p - '0');
+		} else
+			pri = 10 * pri + 7;
+	}
+	if (*p == '>') ++p;
+  }
+  if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) pri = DEFUPRI;
+
+  /* Does not allow users to log kernel messages */
+  if (LOG_FAC(pri) == LOG_KERN) pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri));
+
+  /* Copies message to local buffer, translating control characters */
+  while ((ch = *p++ & 0177) != '\0' && q < &line[sizeof(line) - 1]) {
+	if (ch == '\n')		/* Removes newlines */
+		*q++ = ' ';
+	else if (iscntrl(ch)) {	/* Translates control characters */
+		*q++ = '^';
+		*q++ = ch ^ 0100;
+	} else
+		*q++ = ch;
+  }
+  *q = '\0';
+
+  logmsg(pri, line, hname, 0);
+  return;
+}
+
+/*
+**  Name:  	void printkline(char *hname, char *msg);
+**  Function:	Takes a raw input line from kernel and 
+**	  	prints the message on the appropriate log files.
+*/
+void printkline(char *hname, char *msg)
+{
+  char line[MAXLINE + 1];
+  char *p = msg, *q = line;
+  int ch, pri = DEFUPRI;
+
+  /* Copies message to local buffer, adding source program tag */
+  sprintf(line, "kernel: %s", msg);
+
+  logmsg(LOG_KERN | LOG_INFO, line, hname, ADDDATE);
+  return;
+}
+
+/*
+**  Name:	void init(int sig);
+**  Function:	Initialize syslogd from configuration file.
+**		Used at startup or after a SIGHUP signal.
+*/
+void init(int sig)
+{
+  int i;
+  FILE *cf;
+  struct filed *fLog, *next, **nextp;
+  char *p;
+  char cline[BUFSIZ];
+
+  DEBUG(dprintf("init\n");)
+
+  /* Close all open log files. */
+  Initialized = 0;
+  for (fLog = Files; fLog != NULL; fLog = next) {
+
+	/* Flush any pending output */
+	if (fLog->f_prevcount) fprintlog(fLog, 0, NULL);
+
+	switch (fLog->f_type) {
+	    case F_FILE:
+	    case F_TTY:
+	    case F_CONSOLE:	close(fLog->f_file);	break;
+	}
+	next = fLog->f_next;
+	free((char *) fLog);
+  }
+  Files = NULL;
+  nextp = &Files;
+
+  /* Open the configuration file */
+  if ((cf = fopen(ConfFile, "r")) != NULL) {
+	/* Foreach line in the configuration table, open that file. */
+	fLog = NULL;
+	while (fgets(cline, sizeof(cline), cf) != NULL) {
+		/* Check for end-of-section, comments, strip off
+		 * trailing spaces and newline character. */
+		for (p = cline; isspace(*p); p += 1);
+		if (*p == '\0' || *p == '#') continue;
+		for (p = strchr(cline, '\0'); isspace(*--p););
+		*++p = '\0';
+		fLog = (struct filed *) calloc(1, sizeof(*fLog));
+		*nextp = fLog;
+		nextp = &fLog->f_next;
+		cfline(cline, fLog);
+	}
+
+	/* Close the configuration file */
+	fclose(cf);
+	Initialized = 1;
+DEBUG (
+	if (DbgOpt) {
+		for (fLog = Files; fLog; fLog = fLog->f_next) {
+			for (i = 0; i <= LOG_NFACILITIES; i += 1)
+				if (fLog->f_pmask[i] == INTERNAL_NOPRI)
+					printf("X ");
+				else
+					printf("%d ", fLog->f_pmask[i]);
+			printf("%s: ", TypeNames[fLog->f_type]);
+			switch (fLog->f_type) {
+			    case F_FILE:
+			    case F_TTY:
+			    case F_CONSOLE:
+				printf("%s", fLog->f_un.f_fname);
+				break;
+			    case F_FORW:
+				break;
+			    case F_USERS:
+				for (i = 0; i < MAXUNAMES && *fLog->f_un.f_uname[i]; i += 1)
+					printf("%s, ", fLog->f_un.f_uname[i]);
+				break;
+			}
+			printf("\n");
+		}
+	}
+  )
+	logmsg(LOG_SYSLOG | LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE);
+	signal(SIGHUP, init);
+	DEBUG(dprintf("%s restarted\n", ProgName);)
+  } else {
+	DEBUG(dprintf("cannot open %s\n", ConfFile);)
+	*nextp = (struct filed *) calloc(1, sizeof(*fLog));
+	cfline("*.ERR\t" CTTY, *nextp);
+	(*nextp)->f_next = (struct filed *) calloc(1, sizeof(*fLog));
+	cfline("*.PANIC\t*", (*nextp)->f_next);
+	Initialized = 1;
+  }
+  return;
+}
+
+/*
+**  Name:	void daemonize(char *line);
+**  Function:	Clone itself and becomes a daemon releasing unnecessay resources.
+*/
+void daemonize(char *line)
+{
+  int lfd, len, pid;
+
+  if ((lfd = open(PidFile, O_CREAT | O_RDWR, 0600)) > 0) {
+	len = read(lfd, line, 10);
+	line[len] = '\0';
+	close(lfd);
+	if ((kill(len = atoi(line), 0) < 0 && errno == ESRCH) || len == 0) {
+		if (!DbgOpt) {
+			/* Parent ends and child becomes a daemon */
+			if ((pid = fork()) > 0) {
+				/* Write process id. in pid file */
+				lfd = open(PidFile, O_TRUNC | O_WRONLY);
+				len = sprintf(line, "%5d", pid);
+				write(lfd, line, len);
+				close(lfd);
+
+				/* Wait for initialization to complete */
+				exit(EXIT_SUCCESS);
+			}
+			sleep(1);
+			setsid();	/* Set as session leader */
+			chdir("/");	/* Change to the root directory */
+			/* Get rid of all open files */
+			for (lfd = STDERR_FILENO + 1; lfd < OPEN_MAX; lfd += 1)
+				close(lfd);
+		}
+	} else {
+		fprintf(stderr, "\n%s already running\n", ProgName);
+		exit(EXIT_FAILURE);
+	}
+  } else {
+	fprintf(stderr, "\n%s can't open %s (%s)\n", ProgName, PidFile, strerror(errno));
+	exit(EXIT_FAILURE);
+  }
+  return;
+}
+
+/*
+**  Name:	int main(int argc, char **argv);
+**  Function:	Syslog daemon entry point
+*/
+int main(int argc, char **argv)
+{
+  char *p, *udpdev, *eol;
+  int nfd, kfd, len, fdmax;
+  int ch, port = 0;
+  fd_set fdset;
+  struct nwio_udpopt udpopt;
+  struct servent *sp;
+  char line[MAXLINE + 1];
+
+  while ((ch = getopt(argc, argv, "df:m:p:v?")) != EOF) {
+	switch ((char) ch) {
+	    case 'd':		/* Debug */
+		DbgOpt += 1;
+		break;
+	    case 'f':		/* Set configuration file */
+		ConfFile = optarg;
+		break;
+	    case 'm':		/* Set mark interval */
+		MarkInterval = atoi(optarg) * 60;
+		break;
+	    case 'p':		/* Set listening port */
+		port = atoi(optarg);
+		break;
+	    case 'v':		/* Print version */
+		fprintf(stderr, "%s version %s\n", ProgName, version);
+		return EXIT_FAILURE;
+	    case '?':		/* Help */
+	    default:
+		fprintf(stderr, usage);
+		return EXIT_FAILURE;
+	}
+  }
+  if (argc -= optind) {
+	fprintf(stderr, usage);
+	return EXIT_FAILURE;
+  }
+
+  daemonize(line);
+
+  /* Get the official name of local host. */
+  gethostname(LocalHostName, sizeof(LocalHostName) - 1);
+  if ((p = strchr(LocalHostName, '.'))) *p = '\0';
+
+  udpdev = (p = getenv("UDP_DEVICE")) ? p : UDP_DEVICE;
+  sp = getservbyname("syslog", "udp");
+
+  signal(SIGTERM, die);
+  signal(SIGINT, DbgOpt ? die : SIG_IGN);
+  signal(SIGQUIT, DbgOpt ? die : SIG_IGN);
+  signal(SIGALRM, domark);
+
+  alarm(TIMERINTVL);
+
+  /* Open UDP device */
+  nfd = open(udpdev, O_NONBLOCK | O_RDONLY);
+
+  /* Configures the UDP device */
+  udpopt.nwuo_flags = NWUO_SHARED | NWUO_LP_SET | NWUO_EN_LOC |
+	NWUO_DI_BROAD | NWUO_RP_SET | NWUO_RA_SET |
+	NWUO_RWDATONLY | NWUO_DI_IPOPT;
+  udpopt.nwuo_locport = udpopt.nwuo_remport =
+			port == 0 ? sp->s_port : htons(port);
+  udpopt.nwuo_remaddr = udpopt.nwuo_locaddr = htonl(0x7F000001L);
+  
+ if(nfd >= 0) {
+  while (ioctl(nfd, NWIOSUDPOPT, &udpopt) < 0 ||
+      ioctl(nfd, NWIOGUDPOPT, &udpopt) < 0) {
+	if (errno == EAGAIN) {
+		sleep(1);
+		continue;
+	}
+	logerror("Set/Get UDP options failed");
+	return EXIT_FAILURE;
+  }
+ }
+
+  /* Open kernel log device */
+  kfd = open("/dev/klog", O_NONBLOCK | O_RDONLY);
+
+  if(kfd < 0 && nfd < 0) {
+	logerror("open /dev/klog and udp device failed - can't log anything");
+	return EXIT_FAILURE;
+  }
+
+  fdmax = max(nfd, kfd) + 1;
+
+  DEBUG(dprintf("off & running....\n");)
+  
+  init(-1);			/* Initilizes log data structures */
+
+  for (;;) {			/* Main loop */
+
+	FD_ZERO(&fdset);	/* Setup descriptors for select */
+	if(nfd >= 0) FD_SET(nfd, &fdset);
+	if(kfd >= 0) FD_SET(kfd, &fdset);
+
+	if (select(fdmax, &fdset, NULL, NULL, NULL) <= 0) {
+		sleep(1);
+		continue;
+
+	}
+	if (nfd >= 0 && FD_ISSET(nfd, &fdset)) {
+
+		/* Read a message from application programs */
+		len = read(nfd, line, MAXLINE);
+		if (len > 0) {		/* Got a message */
+			line[len] = '\0';
+			dprintf("got a message (%d, %#x)\n", nfd, len);
+			printline(LocalHostName, line);
+
+		} else if (len < 0) {	/* Got an error or signal while reading */
+			if (errno != EINTR)	/* */
+				logerror("Receive error from UDP channel");
+
+		} else {	/* (len == 0) Channel has been closed */
+			logerror("UDP channel has closed");
+			close(nfd);
+			die(-1);
+		}
+	}
+	if (kfd >= 0 && FD_ISSET(kfd, &fdset)) {
+		static char linebuf[5*1024];
+
+		/* Read a message from kernel (klog) */
+		len = read(kfd, linebuf, sizeof(linebuf)-2);
+		dprintf("got a message (%d, %#x)\n", kfd, len);
+		for (ch = 0; ch < len; ch += 1)
+			if (linebuf[ch] == '\0') linebuf[ch] = ' ';
+		if (linebuf[len - 1] == '\n') len -= 1;
+		linebuf[len] = '\n';
+		linebuf[len + 1] = '\0';
+		p = linebuf;
+		while(eol = strchr(p, '\n')) {
+			*eol = '\0';
+			printkline(LocalHostName, p);
+			p = eol+1;
+		}
+	}
+  }
+  /* Control never gets here */
+}
+
+/** syslogd.c **/
Index: /trunk/minix/commands/talk/Makefile
===================================================================
--- /trunk/minix/commands/talk/Makefile	(revision 9)
+++ /trunk/minix/commands/talk/Makefile	(revision 9)
@@ -0,0 +1,31 @@
+# Makefile for talk
+#
+# 08/01/96 			Michael Temari, <temari@ix.netcom.com>
+#
+
+CFLAGS=	-O -D_MINIX -D_POSIX_SOURCE
+LDFLAGS=-i
+BINDIR=	/usr/bin
+PROG=	talk
+CC = exec cc
+
+OBJS=	talk.o screen.o net.o proto.o
+
+all:	$(PROG)
+
+$(PROG):	$(OBJS)
+	$(CC) $(LDFLAGS) -o $@ $(OBJS) -lcurses
+	install -S 16kw $@
+
+clean:
+	rm -f $(PROG) $(OBJS)
+
+install:	$(BINDIR)/$(PROG)
+
+$(BINDIR)/$(PROG):	$(PROG)
+	install -cs -o bin $? $@
+
+talk.o:		talk.c	talk.h	proto.h	net.h	screen.h
+screen.o:	screen.c			screen.h
+net.o:		net.c	talk.h		net.h
+proto.o:	proto.c	talk.h	proto.h	net.h	screen.h
Index: /trunk/minix/commands/talk/build
===================================================================
--- /trunk/minix/commands/talk/build	(revision 9)
+++ /trunk/minix/commands/talk/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/talk/net.c
===================================================================
--- /trunk/minix/commands/talk/net.c	(revision 9)
+++ /trunk/minix/commands/talk/net.c	(revision 9)
@@ -0,0 +1,266 @@
+/* net.c Copyright Michael Temari 08/01/1996 All Rights Reserved */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+#include <net/gen/udp_hdr.h>
+
+#include "talk.h"
+#include "net.h"
+
+_PROTOTYPE(void TimeOut, (int sig));
+
+static unsigned char buffer[8192];
+
+static int udp_ctl;
+int tcp_fd;
+
+static udpport_t ntalk_port;
+
+char luser[USER_SIZE+1], ruser[USER_SIZE+1];
+char lhost[HOST_SIZE+1], rhost[HOST_SIZE+1];
+char ltty[TTY_SIZE+1], rtty[TTY_SIZE+1];
+udpport_t ctlport;
+tcpport_t dataport;
+ipaddr_t laddr, raddr;
+
+int NetInit()
+{
+int s;
+struct servent *servent;
+char *udp_device;
+char *tcp_device;
+nwio_udpopt_t udpopt;
+nwio_tcpconf_t tcpconf;
+
+   if((udp_device = getenv("UDP_DEVICE")) == (char *)NULL)
+   	udp_device = UDP_DEVICE;
+
+   if((udp_ctl = open(udp_device, O_RDWR)) < 0) {
+   	fprintf(stderr, "talk: Could not open %s: %s\n",
+   		udp_device, strerror(errno));
+   	return(-1);
+   }
+
+   if((servent = getservbyname("ntalk", "udp")) == (struct servent *)NULL) {
+   	fprintf(stderr, "talk: Could not find ntalk udp service\n");
+   	close(udp_ctl);
+   	return(-1);
+   }
+
+   ntalk_port = (udpport_t)servent->s_port;
+
+   udpopt.nwuo_flags = NWUO_NOFLAGS;
+   udpopt.nwuo_flags |= NWUO_COPY | NWUO_LP_SEL | NWUO_EN_LOC;
+   udpopt.nwuo_flags |= NWUO_DI_BROAD | NWUO_RP_SET | NWUO_RA_SET;
+   udpopt.nwuo_flags |= NWUO_RWDATONLY | NWUO_DI_IPOPT;
+   udpopt.nwuo_remaddr = raddr;
+   udpopt.nwuo_remport = ntalk_port;
+
+   s = ioctl(udp_ctl, NWIOSUDPOPT, &udpopt);
+   if(s < 0) {
+   	perror("talk: ioctl NWIOSUDPOPT");
+   	close(udp_ctl);
+   	return(-1);
+   }
+
+   s = ioctl(udp_ctl, NWIOGUDPOPT, &udpopt);
+   if(s < 0) {
+   	perror("talk: ioctl NWIOGUDPOPT");
+   	close(udp_ctl);
+   	return(-1);
+   }
+   laddr = udpopt.nwuo_locaddr;
+   ctlport = udpopt.nwuo_locport;
+
+   if((tcp_device = getenv("TCP_DEVICE")) == (char *)NULL)
+   	tcp_device = TCP_DEVICE;
+
+   if((tcp_fd = open(tcp_device, O_RDWR)) < 0) {
+   	fprintf(stderr, "talk: Could not open %s: %s\n",
+   		tcp_device, strerror(errno));
+   	close(udp_ctl);
+   	return(-1);
+   }
+
+   tcpconf.nwtc_flags = NWTC_NOFLAGS;
+   tcpconf.nwtc_flags |= NWTC_LP_SEL | NWTC_SET_RA | NWTC_UNSET_RP;
+   tcpconf.nwtc_remaddr = raddr;
+
+   s = ioctl(tcp_fd, NWIOSTCPCONF, &tcpconf);
+   if(s < 0) {
+   	perror("talk: ioctl NWIOSTCPCONF");
+   	close(udp_ctl);
+   	close(tcp_fd);
+   	return(-1);
+   }
+
+   s = ioctl(tcp_fd, NWIOGTCPCONF, &tcpconf);
+   if(s < 0) {
+   	perror("talk: ioctl NWIOGTCPCONF");
+   	close(udp_ctl);
+   	close(tcp_fd);
+   	return(-1);
+   }
+
+   dataport = tcpconf.nwtc_locport;
+
+   return(0);
+}
+
+int getreply(reply, timeout)
+struct talk_reply *reply;
+int timeout;
+{
+int s;
+int terrno;
+udp_io_hdr_t *udp_io_hdr;
+
+   signal(SIGALRM, TimeOut);
+   alarm(timeout);
+   s = read(udp_ctl, buffer, sizeof(buffer));
+   terrno = errno;
+   alarm(0);
+   errno = terrno;
+   if(s < 0 && errno == EINTR)
+   	return(1);
+   if(s < 0) {
+   	perror("talk: Read error in getreply");
+   	return(-1);
+   }
+
+   if(s == sizeof(struct talk_reply))
+	memcpy((char *)reply, buffer, s);
+
+   return(0);
+}
+
+int sendrequest(request, here)
+struct talk_request *request;
+int here;
+{
+int s;
+nwio_udpopt_t udpopt;
+udp_io_hdr_t *udp_io_hdr;
+
+   udpopt.nwuo_flags = NWUO_NOFLAGS;
+   udpopt.nwuo_flags |= NWUO_COPY | NWUO_LP_SET | NWUO_EN_LOC;
+   udpopt.nwuo_flags |= NWUO_DI_BROAD | NWUO_RP_SET | NWUO_RA_SET;
+   udpopt.nwuo_flags |= NWUO_RWDATONLY | NWUO_DI_IPOPT;
+   udpopt.nwuo_locport = ctlport;
+   if(here)
+	udpopt.nwuo_remaddr = laddr;
+   else
+	udpopt.nwuo_remaddr = raddr;
+   udpopt.nwuo_remport = ntalk_port;
+
+   s = ioctl(udp_ctl, NWIOSUDPOPT, &udpopt);
+   if(s < 0) {
+   	perror("talk: ioctl NWIOSUDPOPT");
+   	return(-1);
+   }
+
+   s = ioctl(udp_ctl, NWIOGUDPOPT, &udpopt);
+   if(s < 0) {
+   	perror("talk: ioctl NWIOGUDPOPT");
+   	return(-1);
+   }
+
+   s = write(udp_ctl, request, sizeof(struct talk_request));
+   if(s < 0) {
+   	perror("talk: write error in sendrequest");
+   	return(-1);
+   }
+
+   if(s != sizeof(struct talk_request)) {
+   	fprintf(stderr, "talk: sendrequest size mismatch %d %d\n", s, sizeof(struct talk_request));
+   	return(-1);
+   }
+
+   return(0);
+}
+
+void TimeOut(sig)
+int sig;
+{
+}
+
+int NetConnect(port)
+u16_t port;
+{
+int s;
+nwio_tcpconf_t tcpconf;
+nwio_tcpcl_t tcpcopt;
+
+   tcpconf.nwtc_flags = NWTC_NOFLAGS;
+   tcpconf.nwtc_flags |= NWTC_LP_SET | NWTC_SET_RA | NWTC_SET_RP;
+   tcpconf.nwtc_locport = dataport;
+   tcpconf.nwtc_remaddr = raddr;
+   tcpconf.nwtc_remport = port;
+
+   s = ioctl(tcp_fd, NWIOSTCPCONF, &tcpconf);
+   if(s < 0) {
+   	perror("talk: ioctl NWIOSTCPCONF");
+   	return(-1);
+   }
+
+   s = ioctl(tcp_fd, NWIOGTCPCONF, &tcpconf);
+   if(s < 0) {
+   	perror("talk: ioctl NWIOGTCPCONF");
+   	return(-1);
+   }
+
+   tcpcopt.nwtcl_flags = 0;
+
+   s = ioctl(tcp_fd, NWIOTCPCONN, &tcpcopt);
+   if(s < 0 && errno == ECONNREFUSED)
+   	return(1);
+   if(s < 0) {
+   	perror("talk: ioctl NWIOTCPCONN");
+   	return(-1);
+   }
+
+   return(0);
+}
+
+int NetListen(timeout)
+int timeout;
+{
+int s;
+nwio_tcpcl_t tcplopt;
+int terrno;
+
+   tcplopt.nwtcl_flags = 0;
+
+   signal(SIGALRM, TimeOut);
+   alarm(timeout);
+   s = ioctl(tcp_fd, NWIOTCPLISTEN, &tcplopt);
+   terrno = errno;
+   alarm(0);
+   errno = terrno;
+
+   if(s < 0 && errno == EINTR)
+   	return(1);
+
+   if(s < 0) {
+   	perror("talk: ioctl NWIOTCPLISTEN");
+   	return(-1);
+   }
+
+   return(0);
+}
Index: /trunk/minix/commands/talk/net.h
===================================================================
--- /trunk/minix/commands/talk/net.h	(revision 9)
+++ /trunk/minix/commands/talk/net.h	(revision 9)
@@ -0,0 +1,15 @@
+/* net.h Copyright Michael Temari 08/01/1996 All Rights Reserved */
+
+extern char luser[], ruser[];
+extern char lhost[], rhost[];
+extern char ltty[], rtty[];
+extern udpport_t ctlport;
+extern tcpport_t dataport;
+extern ipaddr_t laddr, raddr;
+extern int tcp_fd;
+
+_PROTOTYPE(int NetInit, (void));
+_PROTOTYPE(int getreply, (struct talk_reply *reply, int timeout));
+_PROTOTYPE(int sendrequest, (struct talk_request *request, int here));
+_PROTOTYPE(int NetConnect, (U16_t port));
+_PROTOTYPE(int NetListen, (int timeout));
Index: /trunk/minix/commands/talk/proto.c
===================================================================
--- /trunk/minix/commands/talk/proto.c	(revision 9)
+++ /trunk/minix/commands/talk/proto.c	(revision 9)
@@ -0,0 +1,142 @@
+/* proto.c Copyright Michael Temari 08/01/1996 All Rights Reserved */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <net/hton.h>
+#include <net/gen/socket.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/tcp.h>
+#include <net/gen/udp.h>
+
+#include "talk.h"
+#include "proto.h"
+#include "net.h"
+#include "screen.h"
+
+_PROTOTYPE(static int TalkChk, (int gotreply, struct talk_reply *reply, char *msg));
+_PROTOTYPE(static int TalkTrans, (int type, long id, struct talk_reply *reply, int here));
+
+static char *AnswerMsgs[] = {
+	"Success",
+	"User Not Logged In",
+	"Failure",
+	"Remote Does Not Know who we are",
+	"User is not accepting calls",
+	"Are request was not know",
+	"Incorrect Version",
+	"Bad Address",
+	"Bad Control Address"
+};
+
+static int TalkChk(gotreply, reply, msg)
+int gotreply;
+struct talk_reply *reply;
+char *msg;
+{
+   if(!gotreply) {
+	ScreenMsg(msg);
+	return(-1);
+   }
+   if(reply->answer == SUCCESS) return(0);
+   if(reply->answer < (sizeof(AnswerMsgs) / sizeof(AnswerMsgs[0])))
+  	ScreenMsg(AnswerMsgs[reply->answer]);
+   else
+  	ScreenMsg("Bad Answer");
+
+   return(-1);
+}
+
+static int TalkTrans(type, id, reply, here)
+int type;
+long id;
+struct talk_reply *reply;
+int here;
+{
+struct talk_request request;
+int tries;
+int gotreply;
+
+   memset(&request, 0, sizeof(request));
+
+   request.version = TALK_VERSION;
+   request.type = type;
+   request.id = id;
+   request.addr.sa_family = htons(AF_INET);
+   request.addr.sin_port = dataport;
+   request.addr.sin_addr = laddr;
+   request.ctl_addr.sa_family = htons(AF_INET);
+   request.ctl_addr.sin_port = ctlport;
+   request.ctl_addr.sin_addr = laddr;
+   request.pid = getpid();
+   strncpy(request.luser, luser, USER_SIZE);
+   strncpy(request.ruser, ruser, USER_SIZE);
+   strncpy(request.rtty,  rtty,  TTY_SIZE);
+
+   tries = 0;
+   gotreply = 0;
+   while(!ScreenDone && tries++ < 3 && !gotreply) {
+	if(!sendrequest(&request, here))
+		if(!getreply(reply, 5))
+			gotreply = 1;
+	if(!gotreply) continue;
+	if(reply->version != request.version ||
+	   reply->type    != request.type)
+	   	gotreply = 0;
+   }
+   return(gotreply);
+}
+
+int TalkInit()
+{
+struct talk_reply reply;
+long id = 0;
+long rid;
+int s;
+int ring;
+char buff[32];
+
+   /* Check if someone was calling us */
+   ScreenMsg("Initiating Talk Protocol");
+
+   /* Check is someone was calling us */
+   s = TalkTrans(LOOK_UP, ++id, &reply, 0);
+
+   /* Someone was calling us */
+   if(s && reply.answer == SUCCESS) {
+   	s = NetConnect(reply.addr.sin_port);
+   	if(s == 1) {
+   		ScreenMsg("Your party has hung up");
+   		TalkTrans(DELETE, reply.id, &reply, 0);
+   	}
+   	return(s == 0 ? 0 : -1);
+   }
+
+   ScreenMsg("Ringing User");
+
+   ring = 0;
+   while(!ScreenDone && ring++ < 5) {
+   	if(TalkChk(TalkTrans(ANNOUNCE, -1, &reply, 0),
+   			&reply, "No response to are ring"))
+   		return(-1);
+   	rid = reply.id;
+	sprintf(buff, "Ring #%d", ring);
+	ScreenMsg(buff);
+	if(ring == 1) {
+   		if(TalkChk(TalkTrans(LEAVE_INVITE, ++id, &reply, 1),
+   				&reply, "Could not leave are invitaion locally"))
+			return(-1);
+	}
+   	s = NetListen(RING_WAIT);
+   	if(s <= 0) {
+   		TalkTrans(DELETE, reply.id, &reply, 1);
+   		TalkTrans(DELETE, rid, &reply, 0);
+   		return(s);
+   	}
+   }
+
+   return(-1);
+}
Index: /trunk/minix/commands/talk/proto.h
===================================================================
--- /trunk/minix/commands/talk/proto.h	(revision 9)
+++ /trunk/minix/commands/talk/proto.h	(revision 9)
@@ -0,0 +1,3 @@
+/* proto.h Copyright Michael Temari 08/01/1996 All Rights Reserved */
+
+_PROTOTYPE(int TalkInit, (void));
Index: /trunk/minix/commands/talk/screen.c
===================================================================
--- /trunk/minix/commands/talk/screen.c	(revision 9)
+++ /trunk/minix/commands/talk/screen.c	(revision 9)
@@ -0,0 +1,208 @@
+/* screen.c Copyright Michael Temari 08/01/1996 All Rights Reserved */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <signal.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <curses.h>
+
+#include "screen.h"
+
+_PROTOTYPE(void gotsig, (int sig));
+_PROTOTYPE(static char *delword, (WINDOW *w));
+
+struct {
+	WINDOW *win;
+	char erase;
+	char kill;
+	char werase;
+} window[2];
+
+static char line[80+1];
+
+int ScreenDone = 0;
+
+static WINDOW *dwin;
+
+void gotsig(sig)
+int sig;
+{
+   ScreenDone = 1;
+   signal(sig, gotsig);
+}
+
+int ScreenInit()
+{
+int i;
+
+   if(initscr() == (WINDOW *)NULL) {
+   	fprintf(stderr, "talk: Could not initscr\n");
+   	return(-1);
+   }
+   signal(SIGINT, gotsig);
+   signal(SIGQUIT, gotsig);
+   signal(SIGPIPE, gotsig);
+   signal(SIGHUP, gotsig);
+   clear();
+   refresh();
+   noecho();
+   cbreak();
+
+   /* local window */
+   window[LOCALWIN].win = newwin(LINES / 2, COLS, 0, 0);
+   scrollok(window[LOCALWIN].win, TRUE);
+   wclear(window[LOCALWIN].win);
+
+   /* divider between windows */
+   dwin = newwin(1, COLS, LINES / 2, 0);
+   i = COLS;
+   while(i-- > 0)
+   	waddch(dwin, '-');
+   wrefresh(dwin);
+
+   /* remote window */
+   window[REMOTEWIN].win = newwin(LINES - (LINES / 2) - 1, COLS, LINES / 2 + 1, 0);
+   scrollok(window[REMOTEWIN].win, TRUE);
+   wclear(window[REMOTEWIN].win);
+
+   return(0);
+}
+
+void ScreenMsg(msg)
+char *msg;
+{
+WINDOW *w;
+
+   w =window[LOCALWIN].win;
+
+   wmove(w, 0, 0);
+
+   if(*msg != '\0') {
+	wprintw(w, "[%s]", msg);
+	wclrtoeol(w);
+   } else
+   	werase(w);
+
+   wrefresh(w);
+}
+
+void ScreenWho(user, host)
+char *user;
+char *host;
+{
+   if(*host != '\0') {
+   	wmove(dwin, 0, (COLS - (1 + strlen(user) + 1 + strlen(host) + 1)) / 2);
+   	wprintw(dwin, " %s@%s ", user, host);
+   } else {
+   	wmove(dwin, 0, (COLS - (1 + strlen(user) + 1)) / 2);
+   	wprintw(dwin, " %s ", user);
+   }
+   wrefresh(dwin);
+}
+
+void ScreenEdit(lcc, rcc)
+char lcc[];
+char rcc[];
+{
+   window[LOCALWIN].erase   = lcc[0];
+   window[LOCALWIN].kill    = lcc[1];
+   window[LOCALWIN].werase  = lcc[2];
+   window[REMOTEWIN].erase  = rcc[0];
+   window[REMOTEWIN].kill   = rcc[1];
+   window[REMOTEWIN].werase = rcc[2];
+}
+
+void ScreenPut(data, len, win)
+char *data;
+int len;
+int win;
+{
+WINDOW *w;
+unsigned char ch;
+int r, c;
+
+   w = window[win].win;
+
+   while(len-- > 0) {
+   	ch = *data++;
+   	/* new line CR, NL */
+   	if(ch == '\r' || ch == '\n') {
+		waddch(w, '\n');
+	} else
+	/* erase a character, BS, DEL  */
+	if(ch == 0x08 || ch == 0x7f || ch == window[win].erase) {
+		getyx(w, r, c);
+		if(c > 0)
+			c--;
+		wmove(w, r, c);
+		waddch(w, ' ');
+		wmove(w, r, c);
+	} else
+	/* erase line CTL-U */
+	if(ch == 0x15 || ch == window[win].kill) {
+		getyx(w, r, c);
+		wmove(w, r, 0);
+		wclrtoeol(w);
+	} else
+	/* refresh CTL-L */
+	if(ch == 0x0c) {
+		if(win == LOCALWIN) {
+			touchwin(w);
+			wrefresh(w);
+			touchwin(window[REMOTEWIN].win);
+			wrefresh(window[REMOTEWIN].win);
+		}
+	} else
+	/* bell CTL-G */
+	if(ch == 0x07) {
+		putchar(ch);
+	}
+	else
+	/* erase last word CTL-W */
+	if(ch == 0x17 || ch == window[win].werase) {
+		(void) delword(w);
+	} else {
+		getyx(w, r, c);
+		if(1 || isprint(ch)) {
+			if(ch != ' ' && c == (COLS - 1))
+				wprintw(w, "\n%s", delword(w));
+			waddch(w, ch);
+		}
+	}
+   }
+   wrefresh(w);
+}
+
+static char *delword(w)
+WINDOW *w;
+{
+int r, c;
+int i = 0;
+char ch;
+char *p = &line[80];
+
+   *p-- = '\0';
+   getyx(w, r, c);
+   if(c == 0) return;
+   while(c >= 0) {
+   	c--;
+   	ch = mvwinch(w, r, c);
+   	if(ch == ' ') break;
+   	*p-- = ch;
+   	i = 1;
+   	waddch(w, ' ');
+   }
+   c += i;
+   wmove(w, r, c);
+   return(++p);
+}
+
+void ScreenEnd()
+{
+   move(LINES - 1, 0);
+   refresh();
+   endwin();
+}
Index: /trunk/minix/commands/talk/screen.h
===================================================================
--- /trunk/minix/commands/talk/screen.h	(revision 9)
+++ /trunk/minix/commands/talk/screen.h	(revision 9)
@@ -0,0 +1,13 @@
+/* screen.h Copyright Michael Temari 08/01/1996 All Rights Reserved */
+
+_PROTOTYPE(int ScreenInit, (void));
+_PROTOTYPE(void ScreenMsg, (char *msg));
+_PROTOTYPE(void ScreenWho, (char *user, char *host));
+_PROTOTYPE(void ScreenEdit, (char lcc[], char rcc[]));
+_PROTOTYPE(void ScreenPut, (char *data, int len, int mywin));
+_PROTOTYPE(void ScreenEnd, (void));
+
+extern int ScreenDone;
+
+#define	LOCALWIN	0
+#define	REMOTEWIN	1
Index: /trunk/minix/commands/talk/talk.c
===================================================================
--- /trunk/minix/commands/talk/talk.c	(revision 9)
+++ /trunk/minix/commands/talk/talk.c	(revision 9)
@@ -0,0 +1,237 @@
+/* talk.c Copyright Michael Temari 08/01/1996 All Rights Reserved */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <utmp.h>
+#include <termios.h>
+#include <net/gen/netdb.h>
+#include <net/hton.h>
+#include <net/gen/socket.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/tcp.h>
+#include <net/gen/udp.h>
+
+#include "talk.h"
+#include "proto.h"
+#include "net.h"
+#include "screen.h"
+
+_PROTOTYPE(int main, (int argc, char *argv[]));
+_PROTOTYPE(void DoTalk, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+char *p;
+struct hostent *hp;
+struct stat st;
+struct utmp utmp;
+int slot;
+FILE *fp;
+
+   if(argc < 2 || argc > 3) {
+   	fprintf(stderr, "Usage: talk user[@host] [tty]\n");
+   	return(-1);
+   }
+
+   /* get local host name */
+   if(gethostname(lhost, HOST_SIZE) < 0) {
+   	fprintf(stderr, "talk: Error getting local host name\n");
+   	return(-1);
+   }
+
+   /* get local user name and tty */
+   if((slot = ttyslot()) < 0) {
+   	fprintf(stderr, "talk: You are not on a terminal\n");
+   	return(-1);
+   }
+   if((fp = fopen(UTMP, "r")) == (FILE *)NULL) {
+   	fprintf(stderr, "talk: Could not open %s\n", UTMP);
+   	return(-1);
+   }
+   if(fseek(fp, (off_t) sizeof(utmp) * slot, SEEK_SET)) {
+   	fprintf(stderr, "talk: Could not seek %s\n", UTMP);
+   	fclose(fp);
+   	return(-1);
+   }
+   if(fread((char *)&utmp, sizeof(utmp), 1 , fp) != 1) {
+   	fprintf(stderr, "talk: Could not read %s\n", UTMP);
+   	fclose(fp);
+   	return(-1);
+   }
+   fclose(fp);
+   strncpy(luser, utmp.ut_user, USER_SIZE < sizeof(utmp.ut_user) ?
+   				USER_SIZE : sizeof(utmp.ut_user));
+   luser[USER_SIZE] = '\0';
+
+   /* get local tty */
+   if((p = ttyname(0)) == (char *)NULL) {
+   	fprintf(stderr, "talk: You are not on a terminal\n");
+   	return(-1);
+   }
+   strncpy(ltty, p+5, TTY_SIZE);
+   ltty[TTY_SIZE] = '\0';
+
+   /* check if local tty is going to be writable */
+   if(stat(p, &st) < 0) {
+   	perror("talk: Could not stat local tty");
+   	return(-1);
+   }
+   if((st.st_mode & S_IWGRP) == 0) {
+   	fprintf(stderr, "talk: Your terminal is not writable.  Use: mesg y\n");
+   	return(-1);
+   }
+
+   /* get remote user and host name */
+   if((p = strchr(argv[1], '@')) != (char *)NULL)
+   	*p++ = '\0';
+   else
+   	p = lhost;
+   strncpy(ruser, argv[1], USER_SIZE);
+   ruser[USER_SIZE] = '\0';
+   strncpy(rhost, p, HOST_SIZE);
+   rhost[HOST_SIZE] = '\0';
+
+   /* get remote tty */
+   if(argc > 2)
+   	strncpy(rtty, argv[2], TTY_SIZE);
+   else
+   	rtty[0] = '\0';
+   rtty[TTY_SIZE] = '\0';
+
+   if((hp = gethostbyname(rhost)) == (struct hostent *)NULL) {
+   	fprintf(stderr, "talk: Could not determine address of %s\n", rhost);
+   	return(-1);
+   }
+   memcpy((char *)&raddr, (char *)hp->h_addr, hp->h_length);
+
+   if(NetInit()) {
+   	fprintf(stderr, "talk: Error in NetInit\n");
+   	return(-1);
+   }
+
+   if(ScreenInit())
+   	return(-1);
+
+   if(!TalkInit())
+	DoTalk();
+
+   ScreenEnd();
+
+   return(0);
+}
+
+struct pdata {
+	int win;
+	int len;
+	char buffer[64];
+} pdata;
+
+void DoTalk()
+{
+int s;
+int s2;
+int kid;
+int pfd[2];
+int win;
+int len;
+struct termios termios;
+char lcc[3];
+char rcc[3];
+
+   ScreenMsg("");
+   ScreenWho(ruser, rhost);
+
+   /* Get and send edit characters */
+   s = tcgetattr(0, &termios);
+   if(s < 0) {
+   	perror("talk: tcgetattr");
+   	return;
+   }
+   lcc[0] = termios.c_cc[VERASE];
+   lcc[1] = termios.c_cc[VKILL];
+   lcc[2] = 0x17; /* Control - W */
+   s = write(tcp_fd, lcc, sizeof(lcc));
+   if(s != sizeof(lcc)) {
+   	ScreenMsg("Connection Closing due to error");
+   	return;
+   }
+   s = read(tcp_fd, rcc, sizeof(rcc));
+   if(s != sizeof(rcc)) {
+   	ScreenMsg("Connection Closing due to error");
+   	return;
+   }
+   ScreenEdit(lcc, rcc);
+
+   s = pipe(pfd);
+   if(s < 0) {
+   	ScreenMsg("Could not create pipes");
+   	return;
+   }
+
+   if((kid = fork()) < 0) {
+   	ScreenMsg("Could not fork");
+   	close(pfd[0]);
+   	close(pfd[1]);
+   	return;
+   }
+
+   if(kid == 0) {
+   	close(tcp_fd);
+   	close(pfd[1]);
+   	while(1) {
+   		s = read(pfd[0], &pdata, sizeof(pdata));
+   		if(s != sizeof(pdata)) {
+   			close(pfd[0]);
+   			exit(-1);
+   		}
+   		ScreenPut(pdata.buffer, pdata.len, pdata.win);
+   	}
+   }
+
+   close(pfd[0]);
+
+   if((kid = fork()) < 0) {
+   	ScreenMsg("Could not fork");
+   	close(pfd[1]);
+   	return;
+   }
+
+   if(kid == 0) {
+   	pdata.win = REMOTEWIN;
+   	while(!ScreenDone) {
+	   	s = read(tcp_fd, pdata.buffer, sizeof(pdata.buffer));
+   		if(s <= 0)
+   			break;
+   		pdata.len = s;
+		write(pfd[1], &pdata, sizeof(pdata));
+   	}
+   	close(pfd[1]);
+   	close(tcp_fd);
+	kill(getppid(), SIGINT);
+   	exit(-1);
+   }
+
+   pdata.win = LOCALWIN;
+   while(!ScreenDone) {
+	s = read(0, pdata.buffer, sizeof(pdata.buffer));
+	if(s <= 0)
+		break;
+	pdata.len = s;
+	write(pfd[1], &pdata, sizeof(pdata));
+	s2 = write(tcp_fd, pdata.buffer, s);
+	if(s2 != s)
+		break;
+   }
+   kill(kid, SIGINT);
+   close(pfd[1]);
+   close(tcp_fd);
+   return;
+}
Index: /trunk/minix/commands/talk/talk.h
===================================================================
--- /trunk/minix/commands/talk/talk.h	(revision 9)
+++ /trunk/minix/commands/talk/talk.h	(revision 9)
@@ -0,0 +1,57 @@
+/* talk.h Copyright Michael Temari 07/22/1996 All Rights Reserved */
+
+#define	USER_SIZE	12
+#define	TTY_SIZE	16
+#define	HOST_SIZE	255
+
+struct osockaddr {
+	u16_t sa_family;
+	u16_t sin_port;
+	ipaddr_t sin_addr;
+	char junk[8];
+};
+
+struct talk_request {
+	u8_t version;
+	u8_t type;
+	u8_t answer;
+	u8_t junk;
+	u32_t id;
+	struct osockaddr addr;
+	struct osockaddr ctl_addr;
+	long pid;
+	char	luser[USER_SIZE];
+	char	ruser[USER_SIZE];
+	char	rtty[TTY_SIZE];
+};
+
+struct talk_reply {
+	u8_t version;
+	u8_t type;
+	u8_t answer;
+	u8_t junk;
+	u32_t id;
+	struct osockaddr addr;
+};
+
+#define	TALK_VERSION	1
+
+/* message type values */
+#define LEAVE_INVITE	0	/* leave invitation with server */
+#define LOOK_UP		1	/* check for invitation by callee */
+#define DELETE		2	/* delete invitation by caller */
+#define ANNOUNCE	3	/* announce invitation by caller */
+
+/* answer values */
+#define SUCCESS		0	/* operation completed properly */
+#define NOT_HERE	1	/* callee not logged in */
+#define FAILED		2	/* operation failed for unexplained reason */
+#define MACHINE_UNKNOWN	3	/* caller's machine name unknown */
+#define PERMISSION_DENIED 4	/* callee's tty doesn't permit announce */
+#define UNKNOWN_REQUEST	5	/* request has invalid type value */
+#define	BADVERSION	6	/* request has invalid protocol version */
+#define	BADADDR		7	/* request has invalid addr value */
+#define	BADCTLADDR	8	/* request has invalid ctl_addr value */
+
+#define MAX_LIFE	60	/* max time daemon saves invitations */
+#define RING_WAIT	30	/* time to wait before resending invitation */
Index: /trunk/minix/commands/talkd/Makefile
===================================================================
--- /trunk/minix/commands/talkd/Makefile	(revision 9)
+++ /trunk/minix/commands/talkd/Makefile	(revision 9)
@@ -0,0 +1,31 @@
+# Makefile for talkd
+#
+# 07/22/96 			Michael Temari, <temari@ix.netcom.com>
+#
+
+CFLAGS=	-O -D_MINIX -D_POSIX_SOURCE
+LDFLAGS=-i
+BINDIR=	/usr/bin
+PROG=	talkd
+CC = exec cc
+
+OBJS=	talkd.o net.o process.o finduser.o
+
+all:	$(PROG)
+
+$(PROG):	$(OBJS)
+	$(CC) $(LDFLAGS) -o $@ $(OBJS)
+	install -S 8kw $@
+
+clean:
+	rm -f $(PROG) $(OBJS)
+
+install:	$(BINDIR)/$(PROG)
+
+$(BINDIR)/$(PROG):	$(PROG)
+	install -cs -o bin $? $@
+
+talkd.o:	talkd.c		talk.h	talkd.h	process.h net.h
+net.o:		net.c		talk.h	talkd.h	net.h
+process.o:	process.c	talk.h	talkd.h	finduser.h process.h
+finduser.o:	finduser.c	talk.h		finduser.h
Index: /trunk/minix/commands/talkd/build
===================================================================
--- /trunk/minix/commands/talkd/build	(revision 9)
+++ /trunk/minix/commands/talkd/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/talkd/finduser.c
===================================================================
--- /trunk/minix/commands/talkd/finduser.c	(revision 9)
+++ /trunk/minix/commands/talkd/finduser.c	(revision 9)
@@ -0,0 +1,44 @@
+/* finduser.c Copyright Michael Temari 07/22/1996 All Rights Reserved */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <time.h>
+#include <utmp.h>
+#include <net/gen/in.h>
+
+#include "talk.h"
+#include "finduser.h"
+
+int find_user(name, tty)
+char *name;
+char *tty;
+{
+int fd;
+int ret;
+struct utmp utmp;
+
+   /* Now find out if the requested user is logged in. */
+   if((fd = open(UTMP, O_RDONLY)) < 0) {
+	perror("talkd: opening UTMP file");
+	return(FAILED);
+   }
+
+   ret = NOT_HERE;
+
+   while(read(fd, &utmp, sizeof(struct utmp)) == sizeof(struct utmp)) {
+	if(utmp.ut_type != USER_PROCESS) continue;
+	if(strncmp(utmp.ut_user, name, sizeof(utmp.ut_user))) continue;
+	if(*tty && strncmp(utmp.ut_line, tty, sizeof(utmp.ut_line))) continue;
+	strcpy(tty, utmp.ut_line);
+	ret = SUCCESS;
+	break;
+   }
+
+   close(fd);
+
+   return(ret);
+}
Index: /trunk/minix/commands/talkd/finduser.h
===================================================================
--- /trunk/minix/commands/talkd/finduser.h	(revision 9)
+++ /trunk/minix/commands/talkd/finduser.h	(revision 9)
@@ -0,0 +1,3 @@
+/* finduser.h Copyright Michael Temari 07/22/1996 All Rights Reserved */
+
+_PROTOTYPE(int find_user, (char *name, char *tty));
Index: /trunk/minix/commands/talkd/net.c
===================================================================
--- /trunk/minix/commands/talkd/net.c	(revision 9)
+++ /trunk/minix/commands/talkd/net.c	(revision 9)
@@ -0,0 +1,188 @@
+/* net.c Copyright Michael Temari 07/22/1996 All Rights Reserved */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+#include <net/gen/udp_hdr.h>
+
+#include "talk.h"
+#include "talkd.h"
+#include "net.h"
+
+static unsigned char buffer[8192];
+
+static int udp_in;
+static int udp_out;
+
+static udpport_t ntalk_port;
+
+int NetInit()
+{
+int s;
+struct servent *servent;
+char *udp_device;
+nwio_udpopt_t udpopt;
+
+   if((udp_device = getenv("UDP_DEVICE")) == (char *)NULL)
+   	udp_device = UDP_DEVICE;
+
+   if((udp_in = open(udp_device, O_RDWR)) < 0) {
+   	fprintf(stderr, "talkd: Could not open %s: %s\n",
+   		udp_device, strerror(errno));
+   	return(-1);
+   }
+
+   if((udp_out = open(udp_device, O_RDWR)) < 0) {
+   	fprintf(stderr, "talkd: Could not open %s: %s\n",
+   		udp_device, strerror(errno));
+   	close(udp_in);
+   	return(-1);
+   }
+
+   if((servent = getservbyname("ntalk", "udp")) == (struct servent *)NULL) {
+   	fprintf(stderr, "talkd: Could not find ntalk udp service\n");
+   	close(udp_in);
+   	close(udp_out);
+   	return(-1);
+   }
+
+   ntalk_port = (udpport_t)servent->s_port;
+
+   udpopt.nwuo_flags = NWUO_NOFLAGS;
+   udpopt.nwuo_flags |= NWUO_COPY | NWUO_LP_SET | NWUO_EN_LOC;
+   udpopt.nwuo_flags |= NWUO_DI_BROAD | NWUO_RP_ANY | NWUO_RA_ANY;
+   udpopt.nwuo_flags |= NWUO_RWDATALL | NWUO_DI_IPOPT;
+   udpopt.nwuo_locport = ntalk_port;
+
+   s = ioctl(udp_in, NWIOSUDPOPT, &udpopt);
+   if(s < 0) {
+   	perror("talkd: ioctl NWIOSUDPOPT");
+   	close(udp_in);
+   	close(udp_out);
+   	return(-1);
+   }
+
+   s = ioctl(udp_in, NWIOGUDPOPT, &udpopt);
+   if(s < 0) {
+   	perror("talkd: ioctl NWIOGUDPOPT");
+   	close(udp_in);
+   	close(udp_out);
+   	return(-1);
+   }
+
+   return(0);
+}
+
+int getrequest(request)
+struct talk_request *request;
+{
+int s;
+udp_io_hdr_t *udp_io_hdr;
+
+   s = read(udp_in, buffer, sizeof(buffer));
+   if(s < 0) {
+   	perror("talkd: Read error in getrequest");
+   	return(-1);
+   }
+   if(s < sizeof(udp_io_hdr_t)) {
+	fprintf(stderr, "talkd: Packet size read %d is smaller the udp_io_hdr\n", s);
+	return(-1);
+   }
+   udp_io_hdr = (udp_io_hdr_t *)buffer;
+   s = s - sizeof(udp_io_hdr_t);
+
+   /* why is uih_data_len already in host order??? */
+
+   if(udp_io_hdr->uih_data_len != s) {
+	fprintf(stderr, "talkd: Size mismatch Packet %d  Udp Data %d\n",
+		s, udp_io_hdr->uih_data_len);
+	return(-1);
+   }
+
+   if(s != sizeof(struct talk_request)) {
+   	fprintf(stderr, "talkd: Size mismatch in request %d %d\n",
+   			s, sizeof(struct talk_request));
+   	return(-1);
+   }
+
+   memcpy((char *)request, buffer + sizeof(udp_io_hdr_t), s);
+
+   if(opt_d) {
+   	fprintf(stderr, "Request: ");
+	fprintf(stderr, "%02x %02x %02x %02x ",
+	request->version, request->type, request->answer, request->junk);
+	fprintf(stderr, "%08lx ", request->id);
+	fprintf(stderr, "%04x %08lx:%04x\n",
+		request->addr.sa_family, request->addr.sin_addr, request->addr.sin_port);
+	fprintf(stderr, "                     %08lx ", request->pid);
+	fprintf(stderr, "%04x %08lx:%04x\n",
+		request->ctl_addr.sa_family, request->ctl_addr.sin_addr, request->ctl_addr.sin_port);
+	fprintf(stderr, "          %-12.12s %-12.12s %-16.16s\n",
+		request->luser, request->ruser, request->rtty);
+   }
+
+   return(0);
+}
+
+int sendreply(request, reply)
+struct talk_request *request;
+struct talk_reply *reply;
+{
+int s;
+nwio_udpopt_t udpopt;
+udp_io_hdr_t *udp_io_hdr;
+
+   udpopt.nwuo_flags = NWUO_NOFLAGS;
+   udpopt.nwuo_flags |= NWUO_COPY | NWUO_LP_SET | NWUO_EN_LOC;
+   udpopt.nwuo_flags |= NWUO_DI_BROAD | NWUO_RP_SET | NWUO_RA_SET;
+   udpopt.nwuo_flags |= NWUO_RWDATONLY | NWUO_DI_IPOPT;
+   udpopt.nwuo_locport = ntalk_port;
+   udpopt.nwuo_remaddr = request->ctl_addr.sin_addr;
+   udpopt.nwuo_remport = request->ctl_addr.sin_port;
+
+   s = ioctl(udp_out, NWIOSUDPOPT, &udpopt);
+   if(s < 0) {
+   	perror("talkd: ioctl NWIOSUDPOPT");
+   	return(-1);
+   }
+
+   s = ioctl(udp_out, NWIOGUDPOPT, &udpopt);
+   if(s < 0) {
+   	perror("talkd: ioctl NWIOGUDPOPT");
+   	return(-1);
+   }
+
+   if(opt_d) {
+   	fprintf(stderr, "Reply:   ");
+	fprintf(stderr, "%02x %02x %02x %02x ",
+		reply->version, reply->type, reply->answer, reply->junk);
+	fprintf(stderr, "%08lx ", reply->id);
+	fprintf(stderr, "%04x %08lx:%04x",
+		reply->addr.sa_family, reply->addr.sin_addr, reply->addr.sin_port);
+	fprintf(stderr, "\n");
+   }
+
+   s = write(udp_out, reply, sizeof(struct talk_reply));
+   if(s < 0) {
+	perror("talkd: write");
+	return(-1);
+   }
+   if(s != sizeof(struct talk_reply)) {
+	fprintf(stderr, "talkd: write size mismatch %d %d\n",
+		s, sizeof(struct talk_reply));
+	return(-1);
+   }
+	
+   return(0);
+}
Index: /trunk/minix/commands/talkd/net.h
===================================================================
--- /trunk/minix/commands/talkd/net.h	(revision 9)
+++ /trunk/minix/commands/talkd/net.h	(revision 9)
@@ -0,0 +1,5 @@
+/* net.h Copyright Michael Temari 07/22/1996 All Rights Reserved */
+
+_PROTOTYPE(int NetInit, (void));
+_PROTOTYPE(int getrequest, (struct talk_request *request));
+_PROTOTYPE(int sendreply, (struct talk_request *request, struct talk_reply *reply));
Index: /trunk/minix/commands/talkd/process.c
===================================================================
--- /trunk/minix/commands/talkd/process.c	(revision 9)
+++ /trunk/minix/commands/talkd/process.c	(revision 9)
@@ -0,0 +1,269 @@
+/* process.c Copyright Michael Temari 07/22/1996 All Rights Reserved */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#include <net/hton.h>
+#include <net/gen/socket.h>
+#include <net/gen/in.h>
+#include <net/gen/netdb.h>
+
+#include "talk.h"
+#include "talkd.h"
+#include "process.h"
+#include "finduser.h"
+
+struct entry {
+	struct entry *prev;
+	struct talk_request rq;
+	time_t expire;
+	struct entry *next;
+};
+
+_PROTOTYPE(static int announce, (struct talk_request *request, char *rhost));
+_PROTOTYPE(static struct talk_request *lookup, (struct talk_request *request, int type));
+_PROTOTYPE(static int addreq, (struct talk_request *request));
+_PROTOTYPE(static delete_invite, (long id));
+_PROTOTYPE(static long nextid, (void));
+_PROTOTYPE(static void delete, (struct entry *e));
+
+static struct entry *entry = (struct entry *)NULL;
+
+int processrequest(request, reply)
+struct talk_request *request;
+struct talk_reply *reply;
+{
+char *p;
+struct talk_request *rq;
+struct hostent *hp;
+
+   reply->version = TALK_VERSION;
+   reply->type = request->type;
+   reply->answer = 0;
+   reply->junk = 0;
+   reply->id = htonl(0);
+
+
+   /* check version */
+   if(request->version != TALK_VERSION) {
+   	reply->answer = BADVERSION;
+   	return(0);
+   }
+
+   /* check address family */
+   if(ntohs(request->addr.sa_family) != AF_INET) {
+   	reply->answer = BADADDR;
+   	return(0);
+   }
+
+   /* check control address family */
+   if(ntohs(request->ctl_addr.sa_family) != AF_INET) {
+   	reply->answer = BADCTLADDR;
+   	return(0);
+   }
+
+   /* check local name */
+   p = request->luser;
+   while(*p)
+   	if(!isprint(*p)) {
+   		reply->answer = FAILED;
+   		return(0);
+   	} else
+   		p++;
+
+   switch(request->type) {
+   	case ANNOUNCE:
+		reply->answer = find_user(request->ruser, request->rtty);
+		if(reply->answer != SUCCESS) break;
+		hp = gethostbyaddr((char *)&request->ctl_addr.sin_addr, sizeof(ipaddr_t), AF_INET);
+		if(hp == (struct hostent *)NULL) {
+			reply->answer = MACHINE_UNKNOWN;
+			break;
+		}
+		if((rq = lookup(request, 1)) == (struct talk_request *)NULL) {
+			reply->id = addreq(request);
+			reply->answer = announce(request, hp->h_name);
+			break;
+		}
+		if(ntohl(request->id) > ntohl(rq->id)) {
+			rq->id = nextid();
+			reply->id = rq->id;
+			reply->answer = announce(request, hp->h_name);
+		} else {
+			reply->id = rq->id;
+			reply->answer = SUCCESS;
+		}
+   		break;
+   	case LEAVE_INVITE:
+		rq = lookup(request, 1);
+		if(rq == (struct talk_request *)NULL)
+			reply->id = addreq(request);
+		else {
+			reply->id = rq->id;
+			reply->answer = SUCCESS;
+		}
+   		break;
+   	case LOOK_UP:
+		if((rq = lookup(request, 0)) == (struct talk_request *)NULL)
+			reply->answer = NOT_HERE;
+		else {
+			reply->id = rq->id;
+			memcpy((char *)&reply->addr, (char *)&rq->addr, sizeof(reply->addr));
+			reply->answer = SUCCESS;
+		}
+   		break;
+   	case DELETE:
+		reply->answer = delete_invite(request->id);
+   		break;
+   	default:
+   		reply->answer = UNKNOWN_REQUEST;
+   }
+
+   return(0);
+}
+
+static int announce(request, rhost)
+struct talk_request *request;
+char *rhost;
+{
+char tty[5+TTY_SIZE+1];
+struct stat st;
+FILE *fp;
+time_t now;
+struct tm *tm;
+
+   sprintf(tty, "/dev/%s", request->rtty);
+
+   if(stat(tty, &st) < 0)
+   	return(PERMISSION_DENIED);
+
+   if(!(st.st_mode & S_IWGRP))
+   	return(PERMISSION_DENIED);
+
+   if((fp = fopen(tty, "w")) == (FILE *)NULL)
+   	return(PERMISSION_DENIED);
+
+   (void) time(&now);
+
+   tm = localtime(&now);
+
+   fprintf(fp, "\007\007\007\rtalkd: Message from talkd@%s at %d:%02d:%02d\r\n",
+		myhostname, tm->tm_hour, tm->tm_min, tm->tm_sec);
+   fprintf(fp, "talkd: %s@%s would like to talk to you\r\n",
+   		request->luser, rhost);
+   fprintf(fp, "talkd: to answer type:  talk %s@%s\r\n",
+   		request->luser, rhost);
+
+   fclose(fp);
+
+   return(SUCCESS);
+}
+
+static struct talk_request *lookup(request, type)
+struct talk_request *request;
+int type;
+{
+time_t now;
+struct entry *e;
+
+   (void) time(&now);
+
+   for(e = entry; e != (struct entry *)NULL; e = e->next) {
+	if(now > e->expire) {
+		delete(e);
+		continue;
+	}
+	if(type == 0) {
+		if(!strncmp(request->luser, e->rq.ruser, USER_SIZE) &&
+		   !strncmp(request->ruser, e->rq.luser, USER_SIZE) &&
+		   e->rq.type == LEAVE_INVITE)
+			return(&e->rq);
+	} else {
+		if(request->type == e->rq.type &&
+	  	   request->pid == e->rq.pid &&
+		   !strncmp(request->luser, e->rq.luser, USER_SIZE) &&
+		   !strncmp(request->ruser, e->rq.ruser, USER_SIZE)) {
+			e->expire = now + MAX_LIFE;
+			return(&e->rq);
+		}
+	}
+   }
+   return((struct talk_request *)NULL);
+}
+
+static int addreq(request)
+struct talk_request *request;
+{
+time_t now;
+struct entry *e;
+
+   (void) time(&now);
+   request->id = nextid();
+   e = (struct entry *) malloc(sizeof(struct entry));
+   if(e == (struct entry *)NULL) {
+   	fprintf(stderr, "talkd: out of memory in insert table\n");
+   	exit(1);
+   }
+   e->expire = now + MAX_LIFE;
+   memcpy((char *)&e->rq, (char *)request, sizeof(struct talk_request));
+   e->next = entry;
+   if(e->next != (struct entry *)NULL)
+   	e->next->prev = e;
+   e->prev = (struct entry *)NULL;
+   entry = e;
+   return(request->id);
+}
+
+static int delete_invite(id)
+long id;
+{
+time_t now;
+struct entry *e;
+
+   (void) time(&now);
+
+   for(e = entry; e != (struct entry *)NULL; e = e->next) {
+	if(now > e->expire) {
+		delete(e);
+		continue;
+	}
+	if(e->rq.id == id) {
+		delete(e);
+		return(SUCCESS);
+	}
+   }
+   return(NOT_HERE);
+}
+
+static void delete(e)
+struct entry *e;
+{
+   if(e == (struct entry *)NULL) return;
+
+   if(entry == e)
+	entry = e->next;
+   else
+	if(e->prev != (struct entry *)NULL)
+		e->prev->next = e->next;
+
+   if(e->next != (struct entry *)NULL)
+	e->next->prev = e->prev;
+
+   free((char *)e);
+
+   return;
+}
+
+static long nextid()
+{
+static long id = 0;
+
+   id++;
+   if(id <= 0) id = 1;
+   return(htonl(id));
+}
Index: /trunk/minix/commands/talkd/process.h
===================================================================
--- /trunk/minix/commands/talkd/process.h	(revision 9)
+++ /trunk/minix/commands/talkd/process.h	(revision 9)
@@ -0,0 +1,3 @@
+/* process.h Copyright Michael Temari 07/22/1996 All Rights Reserved */
+
+_PROTOTYPE(int processrequest, (struct talk_request *request, struct talk_reply *reply));
Index: /trunk/minix/commands/talkd/talk.h
===================================================================
--- /trunk/minix/commands/talkd/talk.h	(revision 9)
+++ /trunk/minix/commands/talkd/talk.h	(revision 9)
@@ -0,0 +1,57 @@
+/* talk.h Copyright Michael Temari 07/22/1996 All Rights Reserved */
+
+#define	USER_SIZE	12
+#define	TTY_SIZE	16
+#define	HOST_SIZE	255
+
+struct osockaddr {
+	u16_t sa_family;
+	u16_t sin_port;
+	ipaddr_t sin_addr;
+	char junk[8];
+};
+
+struct talk_request {
+	u8_t version;
+	u8_t type;
+	u8_t answer;
+	u8_t junk;
+	u32_t id;
+	struct osockaddr addr;
+	struct osockaddr ctl_addr;
+	long pid;
+	char	luser[USER_SIZE];
+	char	ruser[USER_SIZE];
+	char	rtty[TTY_SIZE];
+};
+
+struct talk_reply {
+	u8_t version;
+	u8_t type;
+	u8_t answer;
+	u8_t junk;
+	u32_t id;
+	struct osockaddr addr;
+};
+
+#define	TALK_VERSION	1
+
+/* message type values */
+#define LEAVE_INVITE	0	/* leave invitation with server */
+#define LOOK_UP		1	/* check for invitation by callee */
+#define DELETE		2	/* delete invitation by caller */
+#define ANNOUNCE	3	/* announce invitation by caller */
+
+/* answer values */
+#define SUCCESS		0	/* operation completed properly */
+#define NOT_HERE	1	/* callee not logged in */
+#define FAILED		2	/* operation failed for unexplained reason */
+#define MACHINE_UNKNOWN	3	/* caller's machine name unknown */
+#define PERMISSION_DENIED 4	/* callee's tty doesn't permit announce */
+#define UNKNOWN_REQUEST	5	/* request has invalid type value */
+#define	BADVERSION	6	/* request has invalid protocol version */
+#define	BADADDR		7	/* request has invalid addr value */
+#define	BADCTLADDR	8	/* request has invalid ctl_addr value */
+
+#define MAX_LIFE	60	/* max time daemon saves invitations */
+#define RING_WAIT	30	/* time to wait before resending invitation */
Index: /trunk/minix/commands/talkd/talkd.c
===================================================================
--- /trunk/minix/commands/talkd/talkd.c	(revision 9)
+++ /trunk/minix/commands/talkd/talkd.c	(revision 9)
@@ -0,0 +1,54 @@
+/* talkd.c Copyright Michael Temari 07/22/1996 All Rights Reserved */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <net/gen/in.h>
+
+#include "talk.h"
+#include "talkd.h"
+#include "net.h"
+#include "process.h"
+
+_PROTOTYPE(int main, (int argc, char *argv[]));
+
+int opt_d = 0;
+char myhostname[HOST_SIZE+1];
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+struct talk_request request;
+struct talk_reply reply;
+
+   if(argc > 1)
+   	if(strcmp(argv[1], "-d") || argc > 2) {
+   		fprintf(stderr, "Usage: talkd [-d]\n");
+   		return(-1);
+   	} else
+		opt_d = 1;
+
+   if(getuid() != 0) {
+	fprintf(stderr, "talkd: Must be run as super user\n");
+	return(-1);
+   }
+
+   if(gethostname(myhostname, HOST_SIZE) < 0) {
+   	fprintf(stderr, "talkd: Error getting hostname\n");
+   	return(-1);
+   }
+
+   if(NetInit()) {
+   	fprintf(stderr, "talkd: Error in NetInit\n");
+   	return(-1);
+   }
+
+   while(getrequest(&request) == 0) {
+   	if(processrequest(&request, &reply)) break;
+   	if(sendreply(&request, &reply)) break;
+   }
+
+   return(-1);
+}
Index: /trunk/minix/commands/talkd/talkd.h
===================================================================
--- /trunk/minix/commands/talkd/talkd.h	(revision 9)
+++ /trunk/minix/commands/talkd/talkd.h	(revision 9)
@@ -0,0 +1,4 @@
+/* talkd.h Copyright Michael Temari 07/22/1996 All Rights Reserved */
+
+extern int opt_d;	/* debug option */
+extern char myhostname[];
Index: /trunk/minix/commands/telnet/Makefile
===================================================================
--- /trunk/minix/commands/telnet/Makefile	(revision 9)
+++ /trunk/minix/commands/telnet/Makefile	(revision 9)
@@ -0,0 +1,21 @@
+# Makefile for telnet
+
+CFLAGS=	-D_MINIX -D_POSIX_SOURCE
+LDFLAGS=-i
+CC = exec cc
+
+SRC=	ttn.c ttn_conf.c
+
+all:	ttn
+
+ttn:	$(SRC)
+	$(CC) $(CFLAGS) $(LDFLAGS) -o ttn $(SRC)
+	install -S 4kw $@
+
+clean:
+	rm -f ttn
+
+install:	/usr/bin/telnet
+
+/usr/bin/telnet:	ttn
+	install -cs -o bin ttn $@
Index: /trunk/minix/commands/telnet/build
===================================================================
--- /trunk/minix/commands/telnet/build	(revision 9)
+++ /trunk/minix/commands/telnet/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/telnet/ttn.c
===================================================================
--- /trunk/minix/commands/telnet/ttn.c	(revision 9)
+++ /trunk/minix/commands/telnet/ttn.c	(revision 9)
@@ -0,0 +1,689 @@
+/*
+ttn.c
+*/
+
+#ifndef _POSIX_SOURCE
+#define _POSIX_SOURCE 1
+#endif
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <net/hton.h>
+#include <net/netlib.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/netdb.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include "ttn.h"
+
+#if __STDC__
+#define PROTOTYPE(func,args) func args
+#else
+#define PROTOTYPE(func,args) func()
+#endif
+
+static int do_read(int fd, char *buf, unsigned len);
+static void screen(void);
+static void keyboard(void);
+static void send_brk(void);
+static int process_opt (char *bp, int count);
+static void do_option (int optsrt);
+static void dont_option (int optsrt);
+static void will_option (int optsrt);
+static void wont_option (int optsrt);
+static int writeall (int fd, char *buffer, int buf_size);
+static int sb_termtype (char *sb, int count);
+static void fatal(char *fmt, ...);
+static void usage(void);
+
+#if DEBUG
+#define where() (fprintf(stderr, "%s %d:", __FILE__, __LINE__))
+#endif
+
+static char *prog_name;
+static tcp_fd;
+static char *term_env;
+static int esc_char= '~';
+static enum { LS_NORM, LS_BOL, LS_ESC } line_state= LS_BOL;
+
+int main(int argc, char *argv[])
+{
+	struct hostent *hostent;
+	struct servent *servent;
+	ipaddr_t host;
+	tcpport_t port;
+	int pid, ppid;
+	nwio_tcpconf_t tcpconf;
+	int c, r;
+	nwio_tcpcl_t tcpconnopt;
+	struct termios termios;
+	char *tcp_device, *remote_name, *port_name;
+	char *e_arg;
+
+	(prog_name=strrchr(argv[0],'/')) ? prog_name++ : (prog_name=argv[0]);
+
+	e_arg= NULL;
+	while (c= getopt(argc, argv, "?e:"), c != -1)
+	{
+		switch(c)
+		{
+		case '?': usage();
+		case 'e': e_arg= optarg; break;
+		default:
+			fatal("Optind failed: '%c'", c);
+		}
+	}
+
+	if (optind >= argc)
+		usage();
+	remote_name= argv[optind++];
+	if (optind < argc)
+		port_name= argv[optind++];
+	else
+		port_name= NULL;
+	if (optind != argc)
+		usage();
+
+	if (e_arg)
+	{
+		switch(strlen(e_arg))
+		{
+		case 0: esc_char= -1; break;
+		case 1: esc_char= e_arg[0]; break;
+		default: fatal("Invalid escape character '%s'", e_arg);
+		}
+	}
+
+	hostent= gethostbyname(remote_name);
+	if (!hostent)
+		fatal("Unknown host %s", remote_name);
+	host= *(ipaddr_t *)(hostent->h_addr);
+
+	if (!port_name)
+		port= htons(TCPPORT_TELNET);
+	else
+	{
+		servent= getservbyname (port_name, "tcp");
+		if (!servent)
+		{
+			port= htons(strtol(port_name, (char **)0, 0));
+			if (!port)
+				fatal("Unknown port %s", port_name);
+		}
+		else
+			port= (tcpport_t)(servent->s_port);
+	}
+
+	fprintf(stderr, "Connecting to %s:%u...\n",
+		inet_ntoa(host), ntohs(port));
+
+	tcp_device= getenv("TCP_DEVICE");
+	if (tcp_device == NULL)
+		tcp_device= TCP_DEVICE;
+	tcp_fd= open (tcp_device, O_RDWR);
+	if (tcp_fd == -1)
+		fatal("Unable to open %s: %s", tcp_device, strerror(errno));
+
+	tcpconf.nwtc_flags= NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
+	tcpconf.nwtc_remaddr= host;
+	tcpconf.nwtc_remport= port;
+
+	r= ioctl (tcp_fd, NWIOSTCPCONF, &tcpconf);
+	if (r == -1)
+		fatal("NWIOSTCPCONF failed: %s", strerror(errno));
+
+	tcpconnopt.nwtcl_flags= 0;
+	do
+	{
+		r= ioctl (tcp_fd, NWIOTCPCONN, &tcpconnopt);
+		if (r == -1 && errno == EAGAIN)
+		{
+			fprintf(stderr, "%s: Got EAGAIN, sleeping(1s)\n",
+				prog_name);
+			sleep(1);
+		}
+	} while (r == -1 && errno == EAGAIN);
+	if (r == -1)
+		fatal("Unable to connect: %s", strerror(errno));
+	printf("Connected\n");
+	ppid= getpid();
+	pid= fork();
+	switch(pid)
+	{
+	case 0:
+		keyboard();
+#if DEBUG
+fprintf(stderr, "killing %d with %d\r\n", ppid, SIGKILL);
+#endif
+		kill(ppid, SIGKILL);
+		break;
+	case -1:
+		fprintf(stderr, "%s: fork failed: %s\r\n", argv[0],
+			strerror(errno));
+		exit(1);
+		break;
+	default:
+		tcgetattr(0, &termios);
+		screen();
+#if DEBUG
+fprintf(stderr, "killing %d with %d\r\n", pid, SIGKILL);
+#endif
+		kill(pid, SIGKILL);
+		tcsetattr(0, TCSANOW, &termios);
+		break;
+	}
+	exit(0);
+}
+
+static int do_read(fd, buf, len)
+int fd;
+char *buf;
+unsigned len;
+{
+	nwio_tcpopt_t tcpopt;
+	int count;
+
+	for (;;)
+	{
+		count= read (fd, buf, len);
+		if (count <0)
+		{
+			if (errno == EURG || errno == ENOURG)
+			{
+				/* Toggle urgent mode. */
+				tcpopt.nwto_flags= errno == EURG ?
+					NWTO_RCV_URG : NWTO_RCV_NOTURG;
+				if (ioctl(tcp_fd, NWIOSTCPOPT, &tcpopt) == -1)
+				{
+					return -1;
+				}
+				continue;
+			}
+			return -1;
+		}
+		return count;
+	}
+}
+
+static void screen()
+{
+	char buffer[1024], *bp, *iacptr;
+	int count, optsize;
+
+	for (;;)
+	{
+		count= do_read (tcp_fd, buffer, sizeof(buffer));
+#if DEBUG && 0
+ { where(); fprintf(stderr, "read %d bytes\r\n", count); }
+#endif
+		if (count <0)
+		{
+			perror ("read");
+			return;
+		}
+		if (!count)
+			return;
+		bp= buffer;
+		do
+		{
+			iacptr= memchr (bp, IAC, count);
+			if (!iacptr)
+			{
+				write(1, bp, count);
+				count= 0;
+			}
+			if (iacptr && iacptr>bp)
+			{
+#if DEBUG 
+ { where(); fprintf(stderr, "iacptr-bp= %d\r\n", iacptr-bp); }
+#endif
+				write(1, bp, iacptr-bp);
+				count -= (iacptr-bp);
+				bp= iacptr;
+				continue;
+			}
+			if (iacptr)
+			{
+assert (iacptr == bp);
+				optsize= process_opt(bp, count);
+#if DEBUG && 0
+ { where(); fprintf(stderr, "process_opt(...)= %d\r\n", optsize); }
+#endif
+				if (optsize<0)
+					return;
+assert (optsize);
+				bp += optsize;
+				count -= optsize;
+			}
+		} while (count);
+	}
+}
+
+static void keyboard()
+{
+	char c, buffer[1024];
+	int count;
+
+	for (;;)
+	{
+		count= read (0, buffer, 1 /* sizeof(buffer) */);
+		if (count == -1)
+			fatal("Read: %s\r\n", strerror(errno));
+		if (!count)
+			return;
+
+		if (line_state != LS_NORM)
+		{
+			c= buffer[0];
+			if (line_state == LS_BOL)
+			{
+				if (c == esc_char)
+				{
+					line_state= LS_ESC;
+					continue;
+				}
+				line_state= LS_NORM;
+			}
+			else if (line_state == LS_ESC)
+			{
+				line_state= LS_NORM;
+				if (c == '.')
+					return;
+				if (c == '#')
+				{
+					send_brk();
+					continue;
+				}
+
+				/* Not a valid command or a repeat of the
+				 * escape char
+				 */
+				if (c != esc_char)
+				{
+					c= esc_char;
+					write(tcp_fd, &c, 1);
+				}
+			}
+		}
+		if (buffer[0] == '\n')
+			write(tcp_fd, "\r", 1);
+		count= write(tcp_fd, buffer, count);
+		if (buffer[0] == '\r')
+		{
+			line_state= LS_BOL;
+			write(tcp_fd, "\0", 1);
+		}
+		if (count<0)
+		{
+			perror("write");
+			fprintf(stderr, "errno= %d\r\n", errno);
+			return;
+		}
+		if (!count)
+			return;
+	}
+}
+
+static void send_brk(void)
+{
+	int r;
+	unsigned char buffer[2];
+
+	buffer[0]= IAC;
+	buffer[1]= IAC_BRK;
+
+	r= writeall(tcp_fd, (char *)buffer, 2);
+	if (r == -1)
+		fatal("Error writing to TCP connection: %s", strerror(errno));
+}
+
+#define next_char(var) \
+	if (offset<count) { (var) = bp[offset++]; } \
+	else if (do_read(tcp_fd, (char *)&(var), 1) <= 0) \
+	{ perror ("read"); return -1; }
+
+static int process_opt (char *bp, int count)
+{
+	unsigned char iac, command, optsrt, sb_command;
+	int offset, result;	;
+#if DEBUG && 0
+ { where(); fprintf(stderr, "process_opt(bp= 0x%x, count= %d)\r\n",
+	bp, count); }
+#endif
+
+	offset= 0;
+assert (count);
+	next_char(iac);
+assert (iac == IAC);
+	next_char(command);
+	switch(command)
+	{
+	case IAC_NOP:
+		break;
+	case IAC_DataMark:
+		/* Ought to flush input queue or something. */
+		break;
+	case IAC_BRK:
+fprintf(stderr, "got a BRK\r\n");
+		break;
+	case IAC_IP:
+fprintf(stderr, "got a IP\r\n");
+		break;
+	case IAC_AO:
+fprintf(stderr, "got a AO\r\n");
+		break;
+	case IAC_AYT:
+fprintf(stderr, "got a AYT\r\n");
+		break;
+	case IAC_EC:
+fprintf(stderr, "got a EC\r\n");
+		break;
+	case IAC_EL:
+fprintf(stderr, "got a EL\r\n");
+		break;
+	case IAC_GA:
+fprintf(stderr, "got a GA\r\n");
+		break;
+	case IAC_SB:
+		next_char(sb_command);
+		switch (sb_command)
+		{
+		case OPT_TERMTYPE:
+#if DEBUG && 0
+fprintf(stderr, "got SB TERMINAL-TYPE\r\n");
+#endif
+			result= sb_termtype(bp+offset, count-offset);
+			if (result<0)
+				return result;
+			else
+				return result+offset;
+		default:
+fprintf(stderr, "got an unknown SB (skiping)\r\n");
+			for (;;)
+			{
+				next_char(iac);
+				if (iac != IAC)
+					continue;
+				next_char(optsrt);
+				if (optsrt == IAC)
+					continue;
+if (optsrt != IAC_SE)
+	fprintf(stderr, "got IAC %d\r\n", optsrt);
+				break;
+			}
+		}
+		break;
+	case IAC_WILL:
+		next_char(optsrt);
+		will_option(optsrt);
+		break;
+	case IAC_WONT:
+		next_char(optsrt);
+		wont_option(optsrt);
+		break;
+	case IAC_DO:
+		next_char(optsrt);
+		do_option(optsrt);
+		break;
+	case IAC_DONT:
+		next_char(optsrt);
+		dont_option(optsrt);
+		break;
+	case IAC:
+fprintf(stderr, "got a IAC\r\n");
+		break;
+	default:
+fprintf(stderr, "got unknown command (%d)\r\n", command);
+	}
+	return offset;
+}
+
+static void do_option (int optsrt)
+{
+	unsigned char reply[3];
+	int result;
+
+	switch (optsrt)
+	{
+	case OPT_TERMTYPE:
+		if (WILL_terminal_type)
+			return;
+		if (!WILL_terminal_type_allowed)
+		{
+			reply[0]= IAC;
+			reply[1]= IAC_WONT;
+			reply[2]= optsrt;
+		}
+		else
+		{
+			WILL_terminal_type= TRUE;
+			term_env= getenv("TERM");
+			if (!term_env)
+				term_env= "unknown";
+			reply[0]= IAC;
+			reply[1]= IAC_WILL;
+			reply[2]= optsrt;
+		}
+		break;
+	default:
+#if DEBUG
+		fprintf(stderr, "got a DO (%d)\r\n", optsrt);
+		fprintf(stderr, "WONT (%d)\r\n", optsrt);
+#endif
+		reply[0]= IAC;
+		reply[1]= IAC_WONT;
+		reply[2]= optsrt;
+		break;
+	}
+	result= writeall(tcp_fd, (char *)reply, 3);
+	if (result<0)
+		perror("write");
+}
+
+static void will_option (int optsrt)
+{
+	unsigned char reply[3];
+	int result;
+
+	switch (optsrt)
+	{
+	case OPT_ECHO:
+		if (DO_echo)
+			break;
+		if (!DO_echo_allowed)
+		{
+			reply[0]= IAC;
+			reply[1]= IAC_DONT;
+			reply[2]= optsrt;
+		}
+		else
+		{
+			struct termios termios;
+
+			tcgetattr(0, &termios);
+			termios.c_iflag &= ~(ICRNL|IGNCR|INLCR|IXON|IXOFF);
+			termios.c_oflag &= ~(OPOST);
+			termios.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG);
+			tcsetattr(0, TCSANOW, &termios);
+
+			DO_echo= TRUE;
+			reply[0]= IAC;
+			reply[1]= IAC_DO;
+			reply[2]= optsrt;
+		}
+		result= writeall(tcp_fd, (char *)reply, 3);
+		if (result<0)
+			perror("write");
+		break;
+	case OPT_SUPP_GA:
+		if (DO_suppress_go_ahead)
+			break;
+		if (!DO_suppress_go_ahead_allowed)
+		{
+			reply[0]= IAC;
+			reply[1]= IAC_DONT;
+			reply[2]= optsrt;
+		}
+		else
+		{
+			DO_suppress_go_ahead= TRUE;
+			reply[0]= IAC;
+			reply[1]= IAC_DO;
+			reply[2]= optsrt;
+		}
+		result= writeall(tcp_fd, (char *)reply, 3);
+		if (result<0)
+			perror("write");
+		break;
+	default:
+#if DEBUG
+		fprintf(stderr, "got a WILL (%d)\r\n", optsrt);
+		fprintf(stderr, "DONT (%d)\r\n", optsrt);
+#endif
+		reply[0]= IAC;
+		reply[1]= IAC_DONT;
+		reply[2]= optsrt;
+		result= writeall(tcp_fd, (char *)reply, 3);
+		if (result<0)
+			perror("write");
+		break;
+	}
+}
+
+static int writeall (fd, buffer, buf_size)
+int fd;
+char *buffer;
+int buf_size;
+{
+	int result;
+
+	while (buf_size)
+	{
+		result= write (fd, buffer, buf_size);
+		if (result <= 0)
+			return -1;
+assert (result <= buf_size);
+		buffer += result;
+		buf_size -= result;
+	}
+	return 0;
+}
+
+static void dont_option (int optsrt)
+{
+	switch (optsrt)
+	{
+	default:
+#if DEBUG
+		fprintf(stderr, "got a DONT (%d)\r\n", optsrt);
+#endif
+		break;
+	}
+}
+
+static void wont_option (int optsrt)
+{
+	switch (optsrt)
+	{
+	default:
+#if DEBUG
+		fprintf(stderr, "got a WONT (%d)\r\n", optsrt);
+#endif
+		break;
+	}
+}
+
+static int sb_termtype (char *bp, int count)
+{
+	unsigned char command, iac, optsrt;
+	unsigned char buffer[4];
+	int offset, result;
+
+	offset= 0;
+	next_char(command);
+	if (command == TERMTYPE_SEND)
+	{
+		buffer[0]= IAC;
+		buffer[1]= IAC_SB;
+		buffer[2]= OPT_TERMTYPE;
+		buffer[3]= TERMTYPE_IS;
+		result= writeall(tcp_fd, (char *)buffer,4);
+		if (result<0)
+			return result;
+		count= strlen(term_env);
+		if (!count)
+		{
+			term_env= "unknown";
+			count= strlen(term_env);
+		}
+		result= writeall(tcp_fd, term_env, count);
+		if (result<0)
+			return result;
+		buffer[0]= IAC;
+		buffer[1]= IAC_SE;
+		result= writeall(tcp_fd, (char *)buffer,2);
+		if (result<0)
+			return result;
+
+	}
+	else
+	{
+#if DEBUG
+ where();
+#endif
+		fprintf(stderr, "got an unknown command (skipping)\r\n");
+	}
+	for (;;)
+	{
+		next_char(iac);
+		if (iac != IAC)
+			continue;
+		next_char(optsrt);
+		if (optsrt == IAC)
+			continue;
+		if (optsrt != IAC_SE)
+		{
+#if DEBUG
+ where();
+#endif
+			fprintf(stderr, "got IAC %d\r\n", optsrt);
+		}
+		break;
+	}
+	return offset;
+}
+
+static void fatal(char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	fprintf(stderr, "%s: ", prog_name);
+	vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+	va_end(ap);
+
+	exit(1);
+}
+
+static void usage(void)
+{
+	fprintf(stderr, "Usage: %s [-e esc-char] host [port]\r\n",
+		prog_name);
+	exit(1);
+}
+
+/*
+ * $PchId: ttn.c,v 1.5 2002/05/07 12:06:41 philip Exp $
+ */
Index: /trunk/minix/commands/telnet/ttn.h
===================================================================
--- /trunk/minix/commands/telnet/ttn.h	(revision 9)
+++ /trunk/minix/commands/telnet/ttn.h	(revision 9)
@@ -0,0 +1,44 @@
+/*
+ttn.h
+*/
+
+#ifndef TTN_H
+#define TTN_H
+
+#define IAC		255
+#define IAC_SE		240
+#define IAC_NOP		241
+#define IAC_DataMark	242
+#define IAC_BRK		243
+#define IAC_IP		244
+#define IAC_AO		245
+#define IAC_AYT		246
+#define IAC_EC		247
+#define IAC_EL		248
+#define IAC_GA		249
+#define IAC_SB		250
+#define IAC_WILL	251
+#define IAC_WONT	252
+#define IAC_DO		253
+#define IAC_DONT	254
+
+#define OPT_ECHO	1
+#define OPT_SUPP_GA	3
+#define OPT_TERMTYPE	24
+
+#define TERMTYPE_SEND	1
+#define TERMTYPE_IS	0
+
+#define FALSE	0
+#define TRUE	(!(FALSE))
+
+extern int DO_echo;
+extern int DO_echo_allowed;
+extern int WILL_terminal_type;
+extern int WILL_terminal_type_allowed;
+extern int DO_suppress_go_ahead;
+extern int DO_suppress_go_ahead_allowed;
+extern int WILL_suppress_go_ahead;
+extern int WILL_suppress_go_ahead_allowed;
+
+#endif /* TTN_H */
Index: /trunk/minix/commands/telnet/ttn_conf.c
===================================================================
--- /trunk/minix/commands/telnet/ttn_conf.c	(revision 9)
+++ /trunk/minix/commands/telnet/ttn_conf.c	(revision 9)
@@ -0,0 +1,12 @@
+/*
+ttn_conf.c
+*/
+
+#include "ttn.h"
+
+int DO_echo= FALSE;
+int DO_echo_allowed= TRUE;
+int WILL_terminal_type= FALSE;
+int WILL_terminal_type_allowed= TRUE;
+int DO_suppress_go_ahead= FALSE;
+int DO_suppress_go_ahead_allowed= TRUE;
Index: /trunk/minix/commands/telnetd/Makefile
===================================================================
--- /trunk/minix/commands/telnetd/Makefile	(revision 9)
+++ /trunk/minix/commands/telnetd/Makefile	(revision 9)
@@ -0,0 +1,32 @@
+# Makefile for telnetd
+#
+# 01/30/96 Initial Release	Michael Temari, <temari@ix.netcom.com>
+#
+
+CFLAGS=	-O -D_MINIX -D_POSIX_SOURCE
+LDFLAGS=-i
+BINDIR=	/usr/bin
+PROG=	in.telnetd
+CC = exec cc
+
+OBJS=	main.o telnet.o term.o pty.o wtmp.o
+
+all:	$(PROG)
+
+$(PROG):	$(OBJS)
+	$(CC) $(LDFLAGS) -o $@ $(OBJS)
+	install -S 8kw $@
+
+clean:
+	rm -f $(PROG) $(OBJS)
+
+install:	$(BINDIR)/$(PROG)
+
+$(BINDIR)/$(PROG):	$(PROG)
+	install -cs -o bin $? $@
+
+main.o:		main.c		telnetd.h
+telnet.o:	telnet.c	telnetd.h	telnet.h
+term.o:		term.c		telnetd.h	telnet.h
+pty.o:		pty.c		telnetd.h
+wtmp.o:				telnetd.h
Index: /trunk/minix/commands/telnetd/build
===================================================================
--- /trunk/minix/commands/telnetd/build	(revision 9)
+++ /trunk/minix/commands/telnetd/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/telnetd/main.c
===================================================================
--- /trunk/minix/commands/telnetd/main.c	(revision 9)
+++ /trunk/minix/commands/telnetd/main.c	(revision 9)
@@ -0,0 +1,158 @@
+/*
+ * TNET		A server program for MINIX which implements the TCP/IP
+ *		suite of networking protocols.  It is based on the
+ *		TCP/IP code written by Phil Karn et al, as found in
+ *		his NET package for Packet Radio communications.
+ *
+ *		This file contains an implementation of the "server"
+ *		for the TELNET protocol.  This protocol can be used to
+ *		remote-login on other systems, just like a normal TTY
+ *		session.
+ *
+ * Usage:	telnetd [-dv]
+ *
+ * Version:	@(#)telnetd.c	1.00	07/26/92
+ *
+ * Author:	Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ *		Michael Temari, <temari@temari.ae.ge.com>
+ */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdio.h>
+#include <ttyent.h>
+#include <utmp.h>
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/socket.h>
+#include <net/gen/netdb.h>
+#include <net/gen/inet.h>
+#include "telnetd.h"
+
+static char *Version = "@(#) telnetd 1.00 (07/26/92)";
+
+int opt_d = 0;				/* debugging output flag	*/
+
+_PROTOTYPE(void usage, (void));
+_PROTOTYPE(int main, (int argc, char *argv[]));
+_PROTOTYPE(void wtmp, (int type, int linenr, char *line, pid_t pid,
+								char *host));
+
+void usage()
+{
+   fprintf(stderr, "Usage: telnetd [-dv]\n");
+
+   exit(-1);
+}
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+char buff[128];
+register int c;
+int pty_fd;
+int tty_fd;
+pid_t pid;
+int lineno;
+char *tty_name;
+struct ttyent *ttyp;
+nwio_tcpconf_t tcpconf;
+struct hostent *hostent;
+char *hostname;
+
+   opterr = 0;
+   while ((c = getopt(argc, argv, "dv")) != EOF) switch(c) {
+	case 'd':
+	case 'v':
+		opt_d = 1;
+		break;
+	default:
+		usage();
+   }
+
+   /* No more arguments allowed. */
+   if (optind != argc) usage();
+
+   /* Obtain the name of the remote host. */
+   if (ioctl(0, NWIOGTCPCONF, &tcpconf) < 0) {
+	sprintf(buff, "Unable to obtain your IP address\r\n");
+	(void) write(1, buff, strlen(buff));
+	return(-1);
+   }
+   if ((hostent = gethostbyaddr((char *) &tcpconf.nwtc_remaddr,
+			sizeof(tcpconf.nwtc_remaddr), AF_INET)) != NULL) {
+	hostname = hostent->h_name;
+   } else {
+	hostname = inet_ntoa(tcpconf.nwtc_remaddr);
+   }
+
+   /* Try allocating a PTY. */
+   if (get_pty(&pty_fd, &tty_name) < 0) {
+	sprintf(buff, "I am sorry, but there is no free PTY left!\r\n");
+	(void) write(1, buff, strlen(buff));
+	return(-1);
+   }
+
+   /* Find the tty in the tty table. */
+   lineno = 0;
+   for (;;) {
+	if ((ttyp = getttyent()) == NULL) {
+		sprintf(buff, "Can't find %s in the tty table\r\n");
+		(void) write(1, buff, strlen(buff));
+	}
+	if (strcmp(ttyp->ty_name, tty_name+5) == 0) break;
+	lineno++;
+   }
+   endttyent();
+
+   /* Initialize the connection to an 8 bit clean channel. */
+   term_init();
+
+   /* Fork off a child process and have it execute a getty(8). */
+   if ((pid = fork()) == 0) {
+	/* Set up a new session. */
+	setsid();
+	if ((tty_fd = open(tty_name, O_RDWR)) < 0) {
+		sprintf(buff, "Can't open %s\r\n", tty_name);
+		(void) write(1, buff, strlen(buff));
+		return(-1);
+	}
+
+	close(pty_fd);
+	dup2(tty_fd, 0);
+	dup2(tty_fd, 1);
+	dup2(tty_fd, 2);
+	close(tty_fd);
+	(void) execl("/usr/sbin/getty", "getty", (char *)NULL);
+	(void) execl("/usr/bin/getty", "getty", (char *)NULL);
+	(void) execl("/usr/bin/login", "login", (char *)NULL);
+	(void) write(1, "EXEC failed!\r\n", 14);
+   } else if (pid < 0) {
+	sprintf(buff, "I am sorry, but the fork(2) call failed!\r\n");
+	(void) write(1, buff, strlen(buff));
+	(void) close(pty_fd);
+	return(-1);
+   }
+
+   wtmp(LOGIN_PROCESS, lineno, tty_name+5, pid, hostname);
+
+   term_inout(pty_fd);
+
+   (void) close(pty_fd);
+
+   wtmp(DEAD_PROCESS, lineno, tty_name+5, pid, hostname);
+
+   chown(tty_name, 0, 0);
+   chmod(tty_name, 0666);
+
+   return(0);
+}
Index: /trunk/minix/commands/telnetd/pty.c
===================================================================
--- /trunk/minix/commands/telnetd/pty.c	(revision 9)
+++ /trunk/minix/commands/telnetd/pty.c	(revision 9)
@@ -0,0 +1,78 @@
+/*
+ * TNET		A server program for MINIX which implements the TCP/IP
+ *		suite of networking protocols.  It is based on the
+ *		TCP/IP code written by Phil Karn et al, as found in
+ *		his NET package for Packet Radio communications.
+ *
+ *		Handle the allocation of a PTY.
+ *
+ * Author:	Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ */
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include "telnetd.h"
+
+
+#define DEV_DIR		"/dev"
+
+/*
+ * Allocate a PTY, by trying to open one repeatedly,
+ * until all PTY channels are done.  If at that point
+ * no PTY is found, go into panic mode :-(
+ */
+int get_pty(pty_fdp, tty_namep)
+int *pty_fdp;
+char **tty_namep;
+{
+  char buff[128], temp[128];
+  register int i, j;
+  int pty_fd;
+  static char tty_name[128];
+
+  for(i = 'p'; i < 'w'; i++) {
+	j = 0;
+	do {
+		sprintf(buff, "%s/pty%c%c",
+			DEV_DIR, i, (j < 10) ? j + '0' : j + 'a' - 10);
+
+		if (opt_d == 1) {
+			(void) write(2, "Testing: ", 9);
+			(void) write(2, buff, strlen(buff));
+			(void) write(2, "...: ", 5);
+		}
+
+		pty_fd = open(buff, O_RDWR);
+		if (opt_d == 1) {
+			if (pty_fd < 0) sprintf(temp, "error %d\r\n", errno);
+			  else sprintf(temp, "OK\r\n");
+			(void) write(2, temp, strlen(temp));
+		}
+
+		if (pty_fd >= 0) break;
+
+		j++;
+		if (j == 16) break;
+	} while(1);
+
+	/* Did we find one? */
+	if (j < 16) break;
+  }
+  if (pty_fd < 0) return(-1);
+
+  if (opt_d == 1) {
+	sprintf(temp, "File %s, desc %d\n", buff, pty_fd);
+	(void) write(1, temp, strlen(temp));
+  }
+
+  sprintf(tty_name, "%s/tty%c%c", DEV_DIR,
+  					i, (j < 10) ? j + '0' : j + 'a' - 10);
+
+  *pty_fdp = pty_fd;
+  *tty_namep = tty_name;
+  return(0);
+}
Index: /trunk/minix/commands/telnetd/telnet.c
===================================================================
--- /trunk/minix/commands/telnetd/telnet.c	(revision 9)
+++ /trunk/minix/commands/telnetd/telnet.c	(revision 9)
@@ -0,0 +1,337 @@
+/*
+ * TNET		A server program for MINIX which implements the TCP/IP
+ *		suite of networking protocols.  It is based on the
+ *		TCP/IP code written by Phil Karn et al, as found in
+ *		his NET package for Packet Radio communications.
+ *
+ *		This module handles telnet option processing.
+ *
+ * Author:	Michael Temari, <temari@temari.ae.ge.com>  01/13/93
+ *
+ */
+#include <sys/types.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <termios.h>
+#include "telnetd.h"
+#include "telnet.h"
+#include <stdio.h>
+#include <sys/ioctl.h>
+
+
+#define	IN_DATA	0
+#define	IN_CR	1
+#define	IN_IAC	2
+#define	IN_IAC2	3
+#define IN_SB	4
+
+_PROTOTYPE(static void dowill, (int c));
+_PROTOTYPE(static void dowont, (int c));
+_PROTOTYPE(static void dodo, (int c));
+_PROTOTYPE(static void dodont, (int c));
+_PROTOTYPE(static void respond, (int ack, int option));
+_PROTOTYPE(static void respond_really, (int ack, int option));
+
+#define	LASTTELOPT	TELOPT_SGA
+
+static int r_winch = 0;
+
+static int TelROpts[LASTTELOPT+1];
+static int TelLOpts[LASTTELOPT+1];
+
+static int telfdout;
+
+void tel_init()
+{
+int i;
+
+   for(i = 0; i <= LASTTELOPT; i++) {
+	TelROpts[i] = 0;
+	TelLOpts[i] = 0;
+   }
+}
+
+void telopt(fdout, what, option)
+int fdout;
+int what;
+int option;
+{
+char buf[3];
+int len;
+
+   buf[0] = IAC;
+   buf[1] = what;
+   buf[2] = option;
+   len = 0;
+
+   switch(what) {
+	case DO:
+		if(option <= LASTTELOPT) {
+			TelROpts[option] = 1;
+			len = 3;
+		} else if(option == TELOPT_WINCH && !r_winch) { r_winch = 1; len = 3; } 
+		break;
+	case DONT:
+		if(option <= LASTTELOPT) {
+			TelROpts[option] = 1;
+			len = 3;
+		}
+		break;
+	case WILL:
+		if(option <= LASTTELOPT) {
+			TelLOpts[option] = 1;
+			len = 3;
+		}
+		break;
+	case WONT:
+		if(option <= LASTTELOPT) {
+			TelLOpts[option] = 1;
+			len = 3;
+		}
+		break;
+   }
+   if(len > 0)
+	(void) write(fdout, buf, len);
+}
+
+int set_winsize(int fd, unsigned int cols, unsigned int rows)
+{
+	struct winsize w;
+	memset(&w, 0, sizeof(w));
+	w.ws_col = cols;
+	w.ws_row = rows;
+	ioctl(fd, TIOCSWINSZ, (char *) &w);
+}
+
+int tel_in(fdout, telout, buffer, len)
+int fdout;
+int telout;
+char *buffer;
+int len;
+{
+static int InState = IN_DATA;
+static int ThisOpt = 0;
+char *p;
+char *p2;
+int size;
+int c;
+
+   telfdout = telout;
+   p = p2 = buffer;
+   size = 0;
+
+   while(len > 0) {
+   	c = (unsigned char)*p++; len--;
+	switch(InState) {
+   		case IN_CR:
+   			InState = IN_DATA;
+   			if(c == 0 || c == '\n')
+   				break;
+   			/* fall through */
+   		case IN_DATA:
+   			if(c == IAC) {
+   				InState = IN_IAC;
+   				break;
+   			}
+   			*p2++ = c; size++;
+   			if(c == '\r') InState = IN_CR;
+   			break;
+   		case IN_IAC:
+   			switch(c) {
+   				case IAC:
+	   				*p2++ = c; size++;
+   					InState = IN_DATA;
+   					break;
+   				case WILL:
+   				case WONT:
+   				case DO:
+   				case DONT:
+   					InState = IN_IAC2;
+   					ThisOpt = c;
+   					break;
+   				case SB:
+   				 	InState = IN_SB; 
+   					break;
+   				case EOR:
+   				case SE:
+   				case NOP:
+   				case BREAK:
+   				case IP:
+   				case AO:
+   				case AYT:
+   				case EC:
+   				case EL:
+   				case GA:
+   					break;
+   				default:
+   					break;
+   			}
+   			break;
+   		case IN_IAC2:
+   			if(size > 0) {
+   				write(fdout, buffer, size);
+   				p2 = buffer;
+   				size = 0;
+   			}
+   			InState = IN_DATA;
+   			switch(ThisOpt) {
+   				case WILL:	dowill(c);	break;
+   				case WONT:	dowont(c);	break;
+   				case DO:	dodo(c);	break;
+   				case DONT:	dodont(c);	break;
+   			}
+   			break;
+   		case IN_SB:
+ 		{
+			static int winchpos = -1;
+   			/* Subnegotiation. */
+   			if(winchpos >= 0) {
+				static unsigned int winchbuf[5], iacs = 0;
+   				winchbuf[winchpos] = c;
+   				/* IAC is escaped - unescape it. */
+   				if(c == IAC) iacs++; else { iacs = 0; winchpos++; }
+   				if(iacs == 2) { winchpos++; iacs = 0; }
+   				if(winchpos >= 4) {
+   					/* End of WINCH data. */
+   					set_winsize(fdout,
+   					(winchbuf[0] << 8) | winchbuf[1],
+   					(winchbuf[2] << 8) | winchbuf[3]);
+   					winchpos = -1;
+   				}
+   			} else {
+				static int lastiac = 0;
+	   			switch(c) {
+   					case TELOPT_WINCH:
+   						/* Start listening. */
+   						winchpos = 0;
+   						break;
+   					case SE:
+   						if(lastiac) InState = IN_DATA;
+   						break;
+   					default:
+   						break;
+   				}
+   				if(c == IAC) lastiac = 1;
+   				else lastiac = 0;
+
+
+   			}
+   			break;
+   		}
+   	}
+   }
+
+   if(size > 0)
+   	write(fdout, buffer, size);
+}
+
+int tel_out(fdout, buf, size)
+int fdout;
+char *buf;
+int size;
+{
+char *p;
+int got_iac, len;
+
+   p = buf;
+   while(size > 0) {
+	buf = p;
+	got_iac = 0;
+	if((p = (char *)memchr(buf, IAC, size)) != (char *)NULL) {
+		got_iac = 1;
+		p++;
+	} else
+		p = buf + size;
+	len = p - buf;
+	if(len > 0)
+		(void) write(fdout, buf, len);
+	if(got_iac)
+		(void) write(fdout, p - 1, 1);
+	size = size - len;
+   }
+}
+
+static void dowill(c)
+int c;
+{
+int ack;
+
+   switch(c) {
+	case TELOPT_BINARY:
+	case TELOPT_ECHO:
+	case TELOPT_SGA:
+		if(TelROpts[c] == 1)
+			return;
+		TelROpts[c] = 1;
+		ack = DO;
+		break;
+	case TELOPT_WINCH:
+		if(r_winch) return;
+		r_winch = 1;
+		ack = DO;
+ 		respond_really(ack, c); 
+		return;
+	default:
+		ack = DONT;
+   }
+
+   respond(ack, c);
+}
+
+static void dowont(c)
+int c;
+{
+   if(c <= LASTTELOPT) {
+	if(TelROpts[c] == 0)
+		return;
+	TelROpts[c] = 0;
+   }
+   respond(DONT, c);
+}
+
+static void dodo(c)
+int c;
+{
+int ack;
+
+   switch(c) {
+	default:
+		ack = WONT;
+   }
+   respond(ack, c);
+}
+
+static void dodont(c)
+int c;
+{
+   if(c <= LASTTELOPT) {
+	if(TelLOpts[c] == 0)
+		return;
+	TelLOpts[c] = 0;
+   }
+   respond(WONT, c);
+}
+
+static void respond(ack, option)
+int ack, option;
+{
+unsigned char c[3];
+
+   c[0] = IAC;
+   c[1] = ack;
+   c[2] = option;
+/*   write(telfdout, c, 3); */
+}
+
+static void respond_really(ack, option)
+int ack, option;
+{
+unsigned char c[3];
+
+   c[0] = IAC;
+   c[1] = ack;
+   c[2] = option;
+   write(telfdout, c, 3); 
+}
Index: /trunk/minix/commands/telnetd/telnet.h
===================================================================
--- /trunk/minix/commands/telnetd/telnet.h	(revision 9)
+++ /trunk/minix/commands/telnetd/telnet.h	(revision 9)
@@ -0,0 +1,71 @@
+/*
+ * TNET		A server program for MINIX which implements the TCP/IP
+ *		suite of networking protocols.  It is based on the
+ *		TCP/IP code written by Phil Karn et al, as found in
+ *		his NET package for Packet Radio communications.
+ *
+ * 		Definitions for the TELNET protocol (see RFC XXX).
+ *
+ * Version:	@(#)arpa/telnet.h	1.00		07/02/92
+ *
+ * Authors:	Original taken from BSD 4.3/TAHOE.
+ *		Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ */
+#ifndef _ARPA_TELNET_H
+#define _ARPA_TELNET_H
+
+#define	IAC		255	/* interpret as command:		*/
+#define	DONT		254	/* you are not to use option		*/
+#define	DO		253	/* please, you use option		*/
+#define	WONT		252	/* I won't use option			*/
+#define	WILL		251	/* I will use option			*/
+#define	SB		250	/* interpret as subnegotiation		*/
+#define	GA		249	/* you may reverse the line		*/
+#define	EL		248	/* erase the current line		*/
+#define	EC		247	/* erase the current character		*/
+#define	AYT		246	/* are you there			*/
+#define	AO		245	/* abort output--but let prog finish	*/
+#define	IP		244	/* interrupt process--permanently	*/
+#define	BREAK		243	/* break				*/
+#define	DM		242	/* data mark--for connect. cleaning	*/
+#define	NOP		241	/* nop					*/
+#define	SE		240	/* end sub negotiation			*/
+#define EOR     	239     /* end of record (transparent mode)	*/
+
+#define SYNCH		242	/* for telfunc calls			*/
+
+/* Telnet options. */
+#define TELOPT_BINARY	0	/* 8-bit data path			*/
+#define TELOPT_ECHO	1	/* echo					*/
+#define	TELOPT_RCP	2	/* prepare to reconnect			*/
+#define	TELOPT_SGA	3	/* suppress go ahead			*/
+#define	TELOPT_NAMS	4	/* approximate message size		*/
+#define	TELOPT_STATUS	5	/* give status				*/
+#define	TELOPT_TM	6	/* timing mark				*/
+#define	TELOPT_RCTE	7	/* remote controlled transmission and echo */
+#define TELOPT_NAOL 	8	/* negotiate about output line width	*/
+#define TELOPT_NAOP 	9	/* negotiate about output page size	*/
+#define TELOPT_NAOCRD	10	/* negotiate about CR disposition	*/
+#define TELOPT_NAOHTS	11	/* negotiate about horizontal tabstops	*/
+#define TELOPT_NAOHTD	12	/* negotiate about horizontal tab disposition */
+#define TELOPT_NAOFFD	13	/* negotiate about formfeed disposition	*/
+#define TELOPT_NAOVTS	14	/* negotiate about vertical tab stops	*/
+#define TELOPT_NAOVTD	15	/* negotiate about vertical tab disposition */
+#define TELOPT_NAOLFD	16	/* negotiate about output LF disposition */
+#define TELOPT_XASCII	17	/* extended ascic character set		*/
+#define	TELOPT_LOGOUT	18	/* force logout				*/
+#define	TELOPT_BM	19	/* byte macro				*/
+#define	TELOPT_DET	20	/* data entry terminal			*/
+#define	TELOPT_SUPDUP	21	/* supdup protocol			*/
+#define	TELOPT_SUPDUPOUTPUT 22	/* supdup output			*/
+#define	TELOPT_SNDLOC	23	/* send location			*/
+#define	TELOPT_TTYPE	24	/* terminal type			*/
+#define	TELOPT_EOR	25	/* end or record			*/
+#define	TELOPT_WINCH	31	/* window size				*/
+#define TELOPT_EXOPL	255	/* extended-options-list		*/
+
+/* Sub-option qualifiers. */
+#define	TELQUAL_IS	0	/* option is...				*/
+#define	TELQUAL_SEND	1	/* send option				*/
+
+#endif /* _ARPA_TELNET_H */
Index: /trunk/minix/commands/telnetd/telnetd.h
===================================================================
--- /trunk/minix/commands/telnetd/telnetd.h	(revision 9)
+++ /trunk/minix/commands/telnetd/telnetd.h	(revision 9)
@@ -0,0 +1,20 @@
+/*
+ * TNET		A server program for MINIX which implements the TCP/IP
+ *		suite of networking protocols.  It is based on the
+ *		TCP/IP code written by Phil Karn et al, as found in
+ *		his NET package for Packet Radio communications.
+ *
+ *		Definitions for the TELNET server.
+ *
+ * Author:	Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ */
+
+extern int opt_d;			/* debugging flag		*/
+
+_PROTOTYPE(int get_pty, (int *, char **));
+_PROTOTYPE(void term_init, (void));
+_PROTOTYPE(void term_inout, (int pty_fd));
+_PROTOTYPE(void tel_init, (void));
+_PROTOTYPE(void telopt, (int fdout, int what, int option));
+_PROTOTYPE(int tel_in, (int fdout, int telout, char *buffer, int len));
+_PROTOTYPE(int tel_out, (int fdout, char *buf, int size));
Index: /trunk/minix/commands/telnetd/term.c
===================================================================
--- /trunk/minix/commands/telnetd/term.c	(revision 9)
+++ /trunk/minix/commands/telnetd/term.c	(revision 9)
@@ -0,0 +1,86 @@
+/*
+ * TNET		A server program for MINIX which implements the TCP/IP
+ *		suite of networking protocols.  It is based on the
+ *		TCP/IP code written by Phil Karn et al, as found in
+ *		his NET package for Packet Radio communications.
+ *
+ *		Handle the TERMINAL module.
+ *
+ * Author:	Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ *              Michael Temari, <temari@temari.ae.ge.com>
+ *
+ * 07/29/92 MT  Telnet options hack which seems to work okay
+ * 01/12/93 MT  Better telnet options processing instead of hack
+ */
+#include <sys/types.h>
+#include <errno.h>
+#if 0
+#include <fcntl.h>
+#endif
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <signal.h>
+#include "telnet.h"
+#include "telnetd.h"
+
+_PROTOTYPE(void sig_done, (int sig));
+
+static char buff[4096];
+
+void term_init()
+{
+  tel_init();
+
+  telopt(1, WILL, TELOPT_SGA);
+  telopt(1, DO,   TELOPT_SGA);
+  telopt(1, WILL, TELOPT_BINARY);
+  telopt(1, DO,   TELOPT_BINARY);
+  telopt(1, WILL, TELOPT_ECHO);
+  telopt(1, DO,   TELOPT_WINCH);
+}
+
+static int io_done = 0;
+
+void term_inout(pty_fd)
+int pty_fd;
+{
+register int i;
+pid_t pid;
+struct sigaction sa;
+
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = 0;
+  sa.sa_handler = sig_done;
+  sigaction(SIGALRM, &sa, (struct sigaction *) NULL);
+
+  if ((pid = fork()) == -1) {
+	sprintf(buff, "telnetd: fork() failed: %s\r\n", strerror(errno));
+	(void) write(1, buff, strlen(buff));
+  }
+
+  if (pid != 0) {
+	/* network -> login process */
+	while (!io_done && (i = read(0, buff, sizeof(buff))) > 0) {
+		tel_in(pty_fd, 1, buff, i);
+	}
+	/* EOF, kill opposite number and exit. */
+	(void) kill(pid, SIGKILL);
+  } else {
+  	/* login process -> network */
+	while ((i = read(pty_fd, buff, sizeof(buff))) > 0) {
+		tel_out(1, buff, i);
+	}
+	/* EOF, alert opposite number and exit. */
+	(void) kill(getppid(), SIGALRM);
+  }
+  /* EOF. */
+}
+
+void sig_done(sig)
+int sig;
+{
+  io_done = 1;
+  alarm(1);			/* there is always a chance... */
+}
Index: /trunk/minix/commands/telnetd/wtmp.c
===================================================================
--- /trunk/minix/commands/telnetd/wtmp.c	(revision 9)
+++ /trunk/minix/commands/telnetd/wtmp.c	(revision 9)
@@ -0,0 +1,113 @@
+/*
+ * TNET		A server program for MINIX which implements the TCP/IP
+ *		suite of networking protocols.  It is based on the
+ *		TCP/IP code written by Phil Karn et al, as found in
+ *		his NET package for Packet Radio communications.
+ *
+ *		This file contains an implementation of the "server"
+ *		for the TELNET protocol.  This protocol can be used to
+ *		remote-login on other systems, just like a normal TTY
+ *		session.
+ *
+ * Usage:	telnetd [-dv]
+ *
+ * Version:	@(#)telnetd.c	1.00	07/26/92
+ *
+ * Author:	Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ *		Michael Temari, <temari@temari.ae.ge.com>
+ */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <time.h>
+#include <stdio.h>
+#include "telnetd.h"
+
+static char PATH_UTMP[] = "/etc/utmp";
+static char PATH_WTMP[] = "/usr/adm/wtmp";
+
+_PROTOTYPE(void wtmp, (int type, int linenr, char *line, pid_t pid,
+								char *host));
+_PROTOTYPE(void report, (char *label));
+
+void wtmp(type, linenr, line, pid, host)
+int type;			/* type of entry */
+int linenr;			/* line number in ttytab */
+char *line;			/* tty name (only good on login) */
+pid_t pid;			/* pid of process */
+char *host;			/* name of the remote host */
+{
+/* Log an event into the UTMP and WTMP files. */
+
+  struct utmp utmp;		/* UTMP/WTMP User Accounting */
+  int fd;
+
+  /* Clear the utmp record. */
+  memset((void *) &utmp, 0, sizeof(utmp));
+
+  /* Fill in utmp. */
+  switch (type) {
+  case LOGIN_PROCESS:
+  	/* A new login, fill in line and host name. */
+	strncpy(utmp.ut_line, line, sizeof(utmp.ut_line));
+	strncpy(utmp.ut_host, host, sizeof(utmp.ut_host));
+	break;
+
+  case DEAD_PROCESS:
+	/* A logout.  Use the current utmp entry, but make sure it is a
+	 * user process exiting, and not getty or login giving up.
+	 */
+	if ((fd = open(PATH_UTMP, O_RDONLY)) < 0) {
+		if (errno != ENOENT) report(PATH_UTMP);
+		return;
+	}
+	if (lseek(fd, (off_t) (linenr+1) * sizeof(utmp), SEEK_SET) == -1
+		|| read(fd, &utmp, sizeof(utmp)) == -1
+	) {
+		report(PATH_UTMP);
+		close(fd);
+		return;
+	}
+	close(fd);
+	if (utmp.ut_type != USER_PROCESS) return;
+	strncpy(utmp.ut_name, "", sizeof(utmp.ut_name));
+	break;
+  }
+
+  /* Finish new utmp entry. */
+  utmp.ut_pid = pid;
+  utmp.ut_type = type;
+  utmp.ut_time = time((time_t *) 0);
+
+  /* Write new entry to utmp. */
+  if ((fd = open(PATH_UTMP, O_WRONLY)) < 0
+	|| lseek(fd, (off_t) (linenr+1) * sizeof(utmp), SEEK_SET) == -1
+	|| write(fd, &utmp, sizeof(utmp)) == -1
+  ) {
+	if (errno != ENOENT) report(PATH_UTMP);
+  }
+  if (fd != -1) close(fd);
+
+  if (type == DEAD_PROCESS) {
+	/* Add new wtmp entry. */
+	if ((fd = open(PATH_WTMP, O_WRONLY | O_APPEND)) < 0
+		  || write(fd, &utmp, sizeof(utmp)) == -1
+	) {
+		if (errno != ENOENT) report(PATH_WTMP);
+	}
+	if (fd != -1) close(fd);
+  }
+}
+
+void report(label)
+char *label;
+{
+  char message[128];
+
+  sprintf(message, "telnetd: %s: %s\r\n", strerror(errno));
+  (void) write(1, message, strlen(message));
+}
Index: /trunk/minix/commands/urlget/Makefile
===================================================================
--- /trunk/minix/commands/urlget/Makefile	(revision 9)
+++ /trunk/minix/commands/urlget/Makefile	(revision 9)
@@ -0,0 +1,36 @@
+# Makefile for urlget
+#
+# 07/02/96 Initial Release	Michael Temari, <temari@ix.netcom.com>
+#
+
+CFLAGS=	-D_MINIX $(OPT)
+LDFLAGS=-fnone
+BINDIR=	/usr/bin
+PROG=	urlget
+LINK1=	httpget
+LINK2=	ftpget
+CC=exec cc
+
+OBJS=	urlget.o net.o
+
+all:	$(PROG)
+
+$(PROG):	$(OBJS)
+	$(CC) $(LDFLAGS) -o $@ $(OBJS)
+	install -S 4kw $@
+
+clean:
+	rm -f $(PROG) $(OBJS)
+
+tar:
+	tar cvf urlget.tar Makefile urlget.c net.c net.h
+
+install:	$(BINDIR)/$(PROG) $(BINDIR)/$(LINK1) $(BINDIR)/$(LINK2)
+
+$(BINDIR)/$(PROG):	$(PROG)
+	install -c $? $@
+
+$(BINDIR)/$(LINK1) $(BINDIR)/$(LINK2):	$(BINDIR)/$(PROG)
+	install -l $? $@
+
+$(OBJS):	net.h
Index: /trunk/minix/commands/urlget/build
===================================================================
--- /trunk/minix/commands/urlget/build	(revision 9)
+++ /trunk/minix/commands/urlget/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/urlget/net.c
===================================================================
--- /trunk/minix/commands/urlget/net.c	(revision 9)
+++ /trunk/minix/commands/urlget/net.c	(revision 9)
@@ -0,0 +1,98 @@
+/* net.c Copyright 2000 by Michael Temari All Rights Reserved */
+/* 04/05/2000 Michael Temari <Michael@TemWare.Com> */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <time.h>
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/socket.h>
+#include <net/gen/netdb.h>
+
+#include "net.h"
+
+int connect(host, port)
+char *host;
+int port;
+{
+nwio_tcpconf_t tcpconf;
+nwio_tcpcl_t tcpcopt;
+char *tcp_device;
+int netfd;
+ipaddr_t nethost;
+tcpport_t netport;
+struct hostent *hp;
+struct servent *sp;
+char *p;
+int s;
+int tries;
+
+   if((hp = gethostbyname(host)) == (struct hostent *)NULL) {
+	fprintf(stderr, "Unknown host %s!\n", host);  
+	return(-1);
+   } else
+	memcpy((char *) &nethost, (char *) hp->h_addr, hp->h_length);
+
+   netport = htons(port);
+
+   /* Connect to the host */
+   if((tcp_device = getenv("TCP_DEVICE")) == NULL)
+	tcp_device = TCP_DEVICE;
+
+   if((netfd = open(tcp_device, O_RDWR)) < 0) {
+	perror("httpget: opening tcp");
+	return(-1);
+   }
+
+   tcpconf.nwtc_flags = NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
+   tcpconf.nwtc_remaddr = nethost;
+   tcpconf.nwtc_remport = netport;
+
+   s = ioctl(netfd, NWIOSTCPCONF, &tcpconf);
+   if(s < 0) {
+	perror("httpget: NWIOSTCPCONF");
+	close(netfd);
+	return(-1);
+   }
+
+   s = ioctl(netfd, NWIOGTCPCONF, &tcpconf);
+   if(s < 0) {
+	perror("httpget: NWIOGTCPCONF");
+	close(netfd);
+	return(-1);
+   }
+
+   tcpcopt.nwtcl_flags = 0;
+
+   tries = 0;
+   do {
+	s = ioctl(netfd, NWIOTCPCONN, &tcpcopt);
+	if(s == -1 && errno == EAGAIN) {
+		if(tries++ >= 10)
+			break;
+		sleep(10);
+	} else
+		break;
+   } while(1);
+
+   if(s < 0) {
+	perror("httpget: NWIOTCPCONN");
+	close(netfd);
+	return(-1);
+   }
+
+   return(netfd);
+}
Index: /trunk/minix/commands/urlget/net.h
===================================================================
--- /trunk/minix/commands/urlget/net.h	(revision 9)
+++ /trunk/minix/commands/urlget/net.h	(revision 9)
@@ -0,0 +1,4 @@
+/* net.h Copyright 2000 by Michael Temari All Rights Reserved */
+/* 04/05/2000 Michael Temari <Michael@TemWare.Com> */
+
+_PROTOTYPE(int connect, (char *host, int port));
Index: /trunk/minix/commands/urlget/urlget.c
===================================================================
--- /trunk/minix/commands/urlget/urlget.c	(revision 9)
+++ /trunk/minix/commands/urlget/urlget.c	(revision 9)
@@ -0,0 +1,629 @@
+/* urlget.c Copyright 2000 by Michael Temari All Rights Reserved */
+/* 04/05/2000 Michael Temari <Michael@TemWare.Com> */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "net.h"
+
+_PROTOTYPE(char *unesc, (char *s));
+_PROTOTYPE(void encode64, (char **pp, char *s));
+_PROTOTYPE(char *auth, (char *user, char *pass));
+_PROTOTYPE(int skipit, (char *buf, int len, int *skip));
+_PROTOTYPE(int httpget, (char *host, int port, char *user, char *pass, char *path, int headers, int discard, int post));
+_PROTOTYPE(void ftppasv, (char *reply));
+_PROTOTYPE(int ftpreply, (FILE *fpr));
+_PROTOTYPE(int ftpcmd, (FILE *fpw, FILE *fpr, char *cmd, char *arg));
+_PROTOTYPE(int ftpget, (char *host, int port, char *user, char *pass, char *path, int type));
+_PROTOTYPE(int tcpget, (char *host, int port, char *user, char *pass, char *path));
+_PROTOTYPE(int main, (int argc, char *argv[]));
+
+char ftpphost[15+1];
+unsigned int ftppport;
+
+#define	SCHEME_HTTP	1
+#define	SCHEME_FTP	2
+#define	SCHEME_TCP	3
+#define	SCHEME_NNTP	4
+
+char buffer[16000];
+
+#if 0
+_PROTOTYPE(int strncasecmp, (const char *s1, const char *s2, size_t len));
+int
+strncasecmp(s1, s2, len)
+const char *s1, *s2;
+size_t len;
+{
+        int c1, c2;
+        do {
+                if (len == 0)
+                        return 0;
+                len--;
+        } while (c1= toupper(*s1++), c2= toupper(*s2++), c1 == c2 && (c1 & c2))
+                ;
+        if (c1 & c2)
+                return c1 < c2 ? -1 : 1;
+        return c1 ? 1 : (c2 ? -1 : 0);
+}
+#endif
+
+char *unesc(s)
+char *s;
+{
+char *p;
+char *p2;
+unsigned char c;
+
+   p = s;
+   p2 = s;
+   while(*p) {
+   	if(*p != '%') {
+   		*p2++ = *p++;
+   		continue;
+   	}
+   	p++;
+   	if(*p == '%') {
+   		*p2++ = *p++;
+   		continue;
+   	}
+   	if(*p >= '0' && *p <= '9') c = *p++ - '0'; else
+   	if(*p >= 'a' && *p <= 'f') c = *p++ - 'a' + 10; else
+   	if(*p >= 'A' && *p <= 'F') c = *p++ - 'A' + 10; else
+   		break;
+   	if(*p >= '0' && *p <= '9') c = c << 4 | (*p++ - '0'); else
+   	if(*p >= 'a' && *p <= 'f') c = c << 4 | (*p++ - 'a') + 10; else
+   	if(*p >= 'A' && *p <= 'F') c = c << 4 | (*p++ - 'A') + 10; else
+   		break;
+   	*p2++ = c;
+   }
+   *p2 = '\0';
+   return(s);
+}
+
+void encode64(pp, s)
+char **pp;
+char *s;
+{
+char *p;
+char c[3];
+int i;
+int len;
+static char e64[64] = {
+	'A','B','C','D','E','F','G','H','I','J','K','L','M',
+	'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
+	'a','b','c','d','e','f','g','h','i','j','k','l','m',
+	'n','o','p','q','r','s','t','u','v','w','x','y','z',
+	'0','1','2','3','4','5','6','7','8','9','+','/' };
+
+   p = *pp;
+   len = strlen(s);
+   for(i=0; i < len; i += 3) {
+   	c[0] = *s++;
+   	c[1] = *s++;
+   	c[2] = *s++;
+   	*p++ = e64[  c[0] >> 2];
+   	*p++ = e64[((c[0] << 4) & 0x30) | ((c[1] >> 4) & 0x0f)];
+   	*p++ = e64[((c[1] << 2) & 0x3c) | ((c[2] >> 6) & 0x03)];
+   	*p++ = e64[  c[2]       & 0x3f];
+   }
+   if(i == len+1)
+   	p[-1] = '=';
+   else
+   if(i == len+2) {
+   	p[-1] = '=';
+   	p[-2] = '=';
+   }
+   *p = '\0';
+   *pp = p;
+   return;
+}
+
+char *auth(user, pass)
+char *user;
+char *pass;
+{
+static char a[128];
+char up[128];
+char *p;
+
+   strcpy(a, "BASIC ");
+   p = a + 6;
+   sprintf(up, "%s:%s", user, pass);
+   encode64(&p, up);
+
+   return(a);
+}
+
+int skipit(buf, len, skip)
+char *buf;
+int len;
+int *skip;
+{
+static int lf = 0;
+static int crlf = 0;
+char *p;
+
+   p = buf;
+
+   while(--len >= 0) {
+   	if((crlf == 0 || crlf == 2) && *p == '\r')
+   		crlf++;
+   	else
+   	if((crlf == 1 || crlf == 3) && *p == '\n')
+   		crlf++;
+   	else
+   		crlf = 0;
+   	if(*p == '\n')
+   		lf++;
+   	else
+   		lf = 0;
+   	if(crlf == 4 || lf == 2) {
+   		*skip = 0;
+   		return(len);
+   	}
+   	p++;
+   }
+
+   return(0);
+}
+
+int httpget(host, port, user, pass, path, headers, discard, post)
+char *host;
+int port;
+char *user;
+char *pass;
+char *path;
+int headers;
+int discard;
+int post;
+{
+int fd;
+int skip;
+int s;
+int s2;
+char *a;
+char *qs;
+int len;
+
+   if(port == 0)
+   	port = 80;
+
+   fd = connect(host, port);
+   if(fd < 0) {
+   	fprintf(stderr, "httpget: Could not connect to %s:%d\n", host, port);
+   	return(-1);
+   }
+
+   if(post) {
+   	qs = strrchr(path, '?');
+   	if(qs != (char *)NULL) {
+   		*qs++ = '\0';
+   		len = strlen(qs);
+   	} else
+   		len = 0;
+   }
+
+   if(post && len > 0)
+	write(fd, "POST ", 5);
+   else
+	write(fd, "GET ", 4);
+   write(fd, path, strlen(path));
+   write(fd, " HTTP/1.0\r\n", 11);
+   write(fd, "User-Agent: urlget\r\n", 20);
+   write(fd, "Connection: Close\r\n", 19);
+   if(*user) {
+   	write(fd, "Authorization: ", 15);
+   	a = auth(user, pass);
+   	write(fd, a, strlen(a));
+   	write(fd, "\r\n", 2);
+   }
+   if(post && len > 0) {
+   	sprintf(buffer, "Content-Length: %u\r\n", len);
+   	write(fd, buffer, strlen(buffer));
+   }
+   write(fd, "Host: ", 6);
+   write(fd, host, strlen(host));
+   write(fd, "\r\n", 2);
+   write(fd, "\r\n", 2);
+   if(post && len > 0)
+   	write(fd, qs, len);
+
+   skip = 1;
+   while((s = read(fd, buffer, sizeof(buffer)-1)) > 0) {
+	buffer[s] = '\0';
+   	if(skip) {
+   		static int firstline = 1;
+		if(firstline) {
+			static char linebuf[1000];
+			int l = 0;
+			int c, v1, v2, e;
+			if(s >= sizeof(linebuf)-l)
+				c = sizeof(linebuf)-1-l;
+			else	c = s;
+			memcpy(linebuf+l, buffer, c);
+			linebuf[l+c] = '\0';
+			if(strchr(buffer, '\n') || strchr(buffer, '\r'))
+				firstline = 0;
+			if(sscanf(linebuf, "HTTP/%d.%d %d ", &v1, &v2, &e) == 3
+				&& e != 200) {
+				fprintf(stderr, "HTTP error %d\n", e);
+				return -1;
+			}
+		}
+
+   		s2 = skipit(buffer, s, &skip);
+   		if(headers)
+   			write(1, buffer, s - s2);
+   	} else
+   		s2 = s;
+   	if(s2 && !discard)
+		if(write(1, &buffer[s - s2], s2) != s2) {
+			perror("write");
+			return(-1);
+		}
+   }
+   if(s < 0) {
+   	fprintf(stderr, "httpget: Read error\n");
+	return(-1);
+   }
+
+   close(fd);
+
+   return(0);
+}
+
+void ftppasv(reply)
+char *reply;
+{
+char *p;
+unsigned char n[6];
+int i;
+
+   ftppport = 0;
+
+   p = reply;
+   while(*p && *p != '(') p++;
+   if(!*p) return;
+   p++;
+   i = 0;
+   while(1) {
+   	n[i++] = atoi(p);
+   	if(i == 6) break;
+   	p = strchr(p, ',');
+   	if(p == (char *)NULL) return;
+   	p++;
+   }
+   sprintf(ftpphost, "%d.%d.%d.%d", n[0], n[1], n[2], n[3]);
+   ftppport = n[4] * 256 + n[5];
+   return;
+}
+
+int ftpreply(fpr)
+FILE *fpr;
+{
+static char reply[256];
+int s;
+char code[4];
+int ft;
+
+   do {
+   	ft = 1;
+   	do {
+   		if(fgets(reply, sizeof(reply), fpr) == (char *)NULL)
+   			return(-1);
+   		if(ft) {
+   			ft = 0;
+   			strncpy(code, reply, 3);
+   			code[3] = '\0';
+   		}
+   	} while(strncmp(reply, code, 3) || reply[3] == '-');
+   	s = atoi(code);
+   } while(s < 200 && s != 125 && s != 150);
+   if(s == 227) ftppasv(reply);
+   return(s);
+}
+
+int ftpcmd(fpw, fpr, cmd, arg)
+FILE *fpw;
+FILE *fpr;
+char *cmd;
+char *arg;
+{
+   fprintf(fpw, "%s%s%s\r\n", cmd, *arg ? " " : "", arg);
+   fflush(fpw);
+   return(ftpreply(fpr));
+}
+
+int ftpget(host, port, user, pass, path, type)
+char *host;
+int port;
+char *user;
+char *pass;
+char *path;
+int type;
+{
+int fd;
+int fd2;
+FILE *fpr;
+FILE *fpw;
+int s;
+int s2;
+char *p;
+char *p2;
+char typec[2];
+
+   if(port == 0)
+   	port = 21;
+
+   if(type == '\0')
+   	type = 'i';
+
+   fd = connect(host, port);
+   if(fd < 0) {
+   	fprintf(stderr, "ftpget: Could not connect to %s:%d\n", host, port);
+   	return(-1);
+   }
+   fpr = fdopen(fd, "r");
+   fpw = fdopen(fd, "w");
+
+   s = ftpreply(fpr);
+   if(s / 100 != 2) goto error;
+   s = ftpcmd(fpw, fpr, "USER", *user ? user : "ftp");
+   if(s / 100 == 3)
+   	s = ftpcmd(fpw, fpr, "PASS", *pass ? pass : "urlget@");
+
+   if(s / 100 != 2) goto error;
+
+   p = path;
+   if(*p == '/') p++;
+   while((p2 = strchr(p, '/')) != (char *)NULL) {
+   	*p2++ = '\0';
+   	s = ftpcmd(fpw, fpr, "CWD", unesc(p));
+   	p = p2;
+   }
+   sprintf(typec, "%c", type == 'd' ? 'A' : type);
+   s = ftpcmd(fpw, fpr, "TYPE", typec);
+   if(s / 100 != 2) goto error;
+   s = ftpcmd(fpw, fpr, "PASV", "");
+   if(s != 227) goto error;
+   fd2 = connect(ftpphost, ftppport);
+   if(fd2 < 0) goto error;
+   s = ftpcmd(fpw, fpr, type == 'd' ? "NLST" : "RETR", unesc(p));
+   if(s / 100 != 1) goto error;
+   while((s = read(fd2, buffer, sizeof(buffer))) > 0) {
+   	s2 = write(1, buffer, s);
+   	if(s2 != s) break;
+   }
+   if(s2 != s && s != 0) s = -1;
+   close(fd2);
+
+   s = ftpreply(fpr);
+   if(s / 100 == 2) s = 0;
+
+error:
+   (void) ftpcmd(fpw, fpr, "QUIT", "");
+
+   fclose(fpr);
+   fclose(fpw);
+   close(fd);
+
+   return(s == 0 ? 0 : -1);
+}
+
+int tcpget(host, port, user, pass, path)
+char *host;
+int port;
+char *user;
+char *pass;
+char *path;
+{
+int fd;
+int s;
+int s2;
+
+   if(port == 0) {
+   	fprintf(stderr, "tcpget: No port specified\n");
+   	return(-1);
+   }
+
+   fd = connect(host, port);
+   if(fd < 0) {
+   	fprintf(stderr, "httpget: Could not connect to %s:%d\n", host, port);
+   	return(-1);
+   }
+   if(*path == '\/')
+   	path++;
+
+   write(fd, path, strlen(path));
+   write(fd, "\n", 1);
+   while((s = read(fd, buffer, sizeof(buffer))) > 0) {
+   	s2 = write(1, buffer, s);
+   	if(s2 != s) break;
+   }
+   close(fd);
+   return(0);
+}
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+char *prog;
+char *url;
+char scheme;
+char user[64];
+char pass[64];
+char host[64];
+int port;
+char *path;
+int type;
+char *ps;
+char *p;
+char *at;
+int s, c;
+int opt_h = 0;
+int opt_d = 0;
+int opt_p = 0;
+
+   prog = strrchr(*argv, '/');
+   if(prog == (char *)NULL)
+   	prog = *argv;
+   argv++;
+   argc--;
+
+   while(argc && argv[0][0] == '-') {
+   	char *opt = *argv++ + 1;
+   	argc--;
+
+	if (opt[0] == '-' && opt[1] == 0) break;
+
+   	while (*opt) switch (*opt++) {
+		case 'h':	opt_h = -1;	break;
+		case 'd':	opt_d = -1;	break;
+		case 'p':	opt_p = -1;	break;
+		default:	argc = 0;	break;
+	}
+   }
+
+   if(strcmp(prog, "ftpget") == 0) {
+   	if(argc < 2 || argc > 4) {
+   		fprintf(stderr, "Usage: %s host path [user [pass]]\n", prog);
+   		return(-1);
+   	}
+   	strncpy(host, *argv++, sizeof(host));
+   	port = 21;
+   	path = *argv++;
+   	if(argc) {
+   		strncpy(user, *argv++, sizeof(user));
+   		argc++;
+   	} else
+   		*user = '\0';
+   	if(argc) {
+   		strncpy(pass, *argv++, sizeof(pass));
+   		argc++;
+   	} else
+   		*pass = '\0';
+	s = ftpget(host, port, user, path, path, 'i');
+	return(s);
+   }
+   if(strcmp(prog, "httpget") == 0) {
+   	if(argc != 2) {
+   		fprintf(stderr, "Usage: %s [-h] [-d] [-p] host path\n", prog);
+   		return(-1);
+   	}
+   	strncpy(host, *argv++, sizeof(host));
+   	port = 80;
+   	path = *argv++;
+	s = httpget(host, port, user, path, path, opt_h, opt_d, opt_p);
+	return(s);
+   }
+
+   if(argc != 1) {
+   usage:
+   	fprintf(stderr, "Usage: %s [-h] [-p] url\n", prog);
+   	return(-1);
+   }
+
+   url = *argv++;
+   argc--;
+
+   if(strncasecmp(url, "http://", 7) == 0) {
+   	scheme = SCHEME_HTTP;
+   	ps = url + 7;
+   } else
+   if(strncasecmp(url, "ftp://", 6) == 0) {
+   	scheme = SCHEME_FTP;
+   	ps = url + 6;
+   } else 
+   if(strncasecmp(url, "tcp://", 6) == 0) {
+   	scheme = SCHEME_TCP;
+   	ps = url + 6;
+   } else {
+	fprintf(stderr, "%s: I do not handle this scheme\n", prog);
+	return(-1);
+   }
+
+   user[0] = '\0';
+   pass[0] = '\0';
+   host[0] = '\0';
+   port = 0;
+
+   p = ps;
+   while(*p && *p != '/') p++;
+   path = p;
+   c = *path;
+   *path = '\0';
+
+   at = strchr(ps, '@');
+   if(at != (char *)NULL) {
+   	*at = '\0';
+   	p = ps;
+   	while(*p && *p != ':') p++;
+   	if(*p)
+   		*p++ = '\0';
+	strcpy(user, ps);
+   	strcpy(pass, p);
+   	ps = at + 1;
+   }
+
+   *path = c;
+   p = ps;
+   while(*p && *p != '/' && *p != ':') p++;
+   strncpy(host, ps, p - ps);
+   host[p - ps] = '\0';
+   if(*p == ':') {
+   	p++;
+   	ps = p;
+   	while(*p && *p != '/')
+   		port = port * 10 + (*p++ - '0');
+   }
+   if(*p == '/')
+	path = p;
+   else
+   	path = "/";
+   if(scheme == SCHEME_FTP) {
+   	p = path;
+   	while(*p && *p != ';') p++;
+   	if(*p) {
+   		*p++ = '\0';
+   		if(strncasecmp(p, "type=", 5) == 0) {
+   			p += 5;
+   			type = tolower(*p);
+   		}
+   	}
+   }
+
+#if 0
+   fprintf(stderr, "Host: %s\n", host);
+   fprintf(stderr, "Port: %d\n", port);
+   fprintf(stderr, "User: %s\n", user);
+   fprintf(stderr, "Pass: %s\n", pass);
+   fprintf(stderr, "Path: %s\n", path);
+   fprintf(stderr, "Type: %c\n", type);
+#endif
+
+   switch(scheme) {
+   	case SCHEME_HTTP:
+		s = httpget(host, port, user, pass, path, opt_h, opt_d, opt_p);
+		break;
+	case SCHEME_FTP:
+		s = ftpget(host, port, user, pass, path, type);
+		break;
+	case SCHEME_TCP:
+		s = tcpget(host, port, user, pass, path);
+		break;
+   }
+
+   return(s);
+}
Index: /trunk/minix/commands/yap/Makefile
===================================================================
--- /trunk/minix/commands/yap/Makefile	(revision 9)
+++ /trunk/minix/commands/yap/Makefile	(revision 9)
@@ -0,0 +1,210 @@
+# $Header: /cvsup/minix/src/commands/yap/Makefile,v 1.2 2005/09/07 08:43:25 beng Exp $
+
+# CFLAGS : options for the C-compiler
+CFLAGS = -O -D_MINIX -D_POSIX_SOURCE -wa
+CC=exec cc
+
+# LDFLAGS : flags for the loader
+#	-i for a PDP-11 with separate I/D (not necessary)
+LDFLAGS = -i
+
+# BINDIR : where the binary will go when you type "make install"
+BINDIR = /usr/bin
+
+# LIBRARIES : -ltermcap or -ltermlib,
+#	-lPW on USG systems (System III, System V),
+# 	-ljobs on Berkeley Unix system (4.1, 2.8?, 2.9)
+LIBRARIES =
+
+HFILES= assert.h\
+	commands.h\
+	display.h\
+	getcomm.h\
+	getline.h\
+	help.h\
+	in_all.h\
+	keys.h\
+	machine.h\
+	main.h\
+	options.h\
+	output.h\
+	pattern.h\
+	process.h\
+	prompt.h\
+	term.h
+
+CFILES=	assert.c\
+	commands.c\
+	display.c\
+	getcomm.c\
+	getline.c\
+	help.c\
+	keys.c\
+	machine.c\
+	main.c\
+	options.c\
+	output.c\
+	pattern.c\
+	process.c\
+	prompt.c\
+	term.c
+
+OFILES=	assert.o\
+	commands.o\
+	display.o\
+	getcomm.o\
+	getline.o\
+	help.o\
+	keys.o\
+	machine.o\
+	main.o\
+	options.o\
+	output.o\
+	pattern.o\
+	process.o\
+	prompt.o\
+	term.o
+
+all:		yap
+
+yap:		$(OFILES)
+		$(CC) $(LDFLAGS) -o yap $(OFILES) $(LIBRARIES)
+		install -S 16kw yap
+
+install:	$(BINDIR)/yap $(BINDIR)/more
+
+$(BINDIR)/yap:	yap
+		install -cs -o bin yap $@
+
+$(BINDIR)/more:	$(BINDIR)/yap
+		install -l $? $@
+
+clean:
+		rm -f yap $(OFILES) a.out core *.bak
+
+pr:
+		pr Makefile $(HFILES) $(CFILES)
+
+lint:
+		lint $(DEFINES) $(CFILES)
+
+#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
+assert.o:	assert.h
+assert.o:	in_all.h
+assert.o:	output.h
+assert.o:	term.h
+commands.o:	assert.h
+commands.o:	commands.h
+commands.o:	display.h
+commands.o:	getcomm.h
+commands.o:	getline.h
+commands.o:	help.h
+commands.o:	in_all.h
+commands.o:	keys.h
+commands.o:	machine.h
+commands.o:	main.h
+commands.o:	options.h
+commands.o:	output.h
+commands.o:	pattern.h
+commands.o:	process.h
+commands.o:	prompt.h
+commands.o:	term.h
+display.o:	assert.h
+display.o:	display.h
+display.o:	getline.h
+display.o:	in_all.h
+display.o:	machine.h
+display.o:	main.h
+display.o:	options.h
+display.o:	output.h
+display.o:	process.h
+display.o:	term.h
+getcomm.o:	assert.h
+getcomm.o:	commands.h
+getcomm.o:	display.h
+getcomm.o:	getcomm.h
+getcomm.o:	getline.h
+getcomm.o:	in_all.h
+getcomm.o:	keys.h
+getcomm.o:	machine.h
+getcomm.o:	main.h
+getcomm.o:	output.h
+getcomm.o:	process.h
+getcomm.o:	prompt.h
+getcomm.o:	term.h
+getline.o:	assert.h
+getline.o:	display.h
+getline.o:	getline.h
+getline.o:	in_all.h
+getline.o:	main.h
+getline.o:	options.h
+getline.o:	output.h
+getline.o:	process.h
+getline.o:	term.h
+help.o:	commands.h
+help.o:	display.h
+help.o:	help.h
+help.o:	in_all.h
+help.o:	keys.h
+help.o:	machine.h
+help.o:	main.h
+help.o:	options.h
+help.o:	output.h
+help.o:	prompt.h
+help.o:	term.h
+keys.o:	assert.h
+keys.o:	commands.h
+keys.o:	in_all.h
+keys.o:	keys.h
+keys.o:	machine.h
+keys.o:	prompt.h
+machine.o:	assert.h
+machine.o:	getline.h
+machine.o:	in_all.h
+machine.o:	machine.h
+main.o:	commands.h
+main.o:	display.h
+main.o:	in_all.h
+main.o:	main.h
+main.o:	options.h
+main.o:	output.h
+main.o:	process.h
+main.o:	prompt.h
+main.o:	term.h
+options.o:	display.h
+options.o:	in_all.h
+options.o:	options.h
+options.o:	output.h
+output.o:	in_all.h
+output.o:	main.h
+output.o:	output.h
+pattern.o:	in_all.h
+pattern.o:	pattern.h
+process.o:	commands.h
+process.o:	display.h
+process.o:	getline.h
+process.o:	in_all.h
+process.o:	main.h
+process.o:	options.h
+process.o:	output.h
+process.o:	process.h
+process.o:	prompt.h
+prompt.o:	display.h
+prompt.o:	getcomm.h
+prompt.o:	getline.h
+prompt.o:	in_all.h
+prompt.o:	main.h
+prompt.o:	options.h
+prompt.o:	output.h
+prompt.o:	process.h
+prompt.o:	prompt.h
+prompt.o:	term.h
+term.o:	display.h
+term.o:	getline.h
+term.o:	in_all.h
+term.o:	keys.h
+term.o:	machine.h
+term.o:	main.h
+term.o:	options.h
+term.o:	output.h
+term.o:	term.h
Index: /trunk/minix/commands/yap/NOTICE
===================================================================
--- /trunk/minix/commands/yap/NOTICE	(revision 9)
+++ /trunk/minix/commands/yap/NOTICE	(revision 9)
@@ -0,0 +1,21 @@
+$Header: /cvsup/minix/src/commands/yap/NOTICE,v 1.1.1.1 2005/04/21 14:55:38 beng Exp $
+
+The software and documentation contained within this
+directory is copyright (c) Ceriel J.H. Jacobs, 1988.
+
+Permission is granted to reproduce and distribute
+this software as long as no fee is charged and
+this notice is included.
+
+Other rights are reserved except as explicitly
+granted by written permission from the author.
+
+		Ceriel J.H. Jacobs
+		Dept. of Maths and Computer Science
+		Vrije Universiteit
+		De Boelelaan 1081
+		1081 HV	 Amsterdam
+		The Netherlands
+    email :
+	ceriel@cs.vu.nl
+
Index: /trunk/minix/commands/yap/READ_ME
===================================================================
--- /trunk/minix/commands/yap/READ_ME	(revision 9)
+++ /trunk/minix/commands/yap/READ_ME	(revision 9)
@@ -0,0 +1,41 @@
+$Header: /cvsup/minix/src/commands/yap/READ_ME,v 1.1.1.1 2005/04/21 14:55:38 beng Exp $
+
+This directory contains the sources of YAP, Yet Another Pager.
+It can do most of the things more(1) can, and much much more.
+
+Yap has been tested on the following systems:
+
+- DEC PDP 11/44 running V7
+- DEC PDP 11/60 running V7
+- DEC VAX 11/750 running 4.1BSD
+- IBM PC/XT running PC/IX
+- NCR Minitower running a System V
+- Several 68k systems
+- SUN-3 and SUN-4
+
+On other systems, you might have some problems getting yap to run, but then
+again, you might not. You can always ask me for help, and maybe even get it.
+If you make any changes, please
+ - tell me about them
+ - mark them clearly, preferably through conditional compilation.
+
+What you need to run yap:
+
+- you need termlib/termcap.
+  It probably is'nt too hard to adapt yap to terminfo.
+  It might even work unchanged, but I don't know about that. We don't have
+  terminfo or the system V curses.
+  If you adapt yap to terminfo, I would sure like to get the changes you made,
+  so please send them to me (email address at the bottom of this note);
+- you also need regex(III) (Either Berkeley style or USG will do).
+  If you do not have it, you should define NOREGEX, which gives you
+  simpleminded searches without meta-characters.
+
+How to install yap:
+
+- edit Makefile (easy)
+- edit in_all.h (easy)
+- type "make install"
+
+			Ceriel Jacobs, Vrije Universiteit Amsterdam
+			ceriel@cs.vu.nl
Index: /trunk/minix/commands/yap/assert.c
===================================================================
--- /trunk/minix/commands/yap/assert.c	(revision 9)
+++ /trunk/minix/commands/yap/assert.c	(revision 9)
@@ -0,0 +1,34 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+# ifndef lint
+static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/assert.c,v 1.1.1.1 2005/04/21 14:55:38 beng Exp $";
+# endif
+
+# define _ASSERT_
+
+# include "in_all.h"
+# include "assert.h"
+# if DO_ASSERT
+# include "output.h"
+# include "term.h"
+
+/*
+ * Assertion fails. Tell me about it.
+ */
+
+VOID
+badassertion(ass,f,l) char *ass, *f; {
+
+	clrbline();
+	putline("Assertion \"");
+	putline(ass);
+	putline("\" failed ");
+	putline(f);
+	putline(", line ");
+	prnum((long) l);
+	putline(".\r\n");
+	flush();
+	resettty();
+	abort();
+}
+# endif
Index: /trunk/minix/commands/yap/assert.h
===================================================================
--- /trunk/minix/commands/yap/assert.h	(revision 9)
+++ /trunk/minix/commands/yap/assert.h	(revision 9)
@@ -0,0 +1,28 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/assert.h,v 1.1.1.1 2005/04/21 14:55:38 beng Exp $ */
+
+/* Assertion macro */
+
+# ifndef _ASSERT_
+# define PUBLIC extern
+# else
+# define PUBLIC
+# endif
+
+#if DO_ASSERT
+#define assert(x) if(!(x)) badassertion("x",__FILE__,__LINE__)
+VOID badassertion();
+/*
+ * void badassertion(ass,fn,lineno)
+ * char *ass,		The assertion in string form,
+ *	*fn;		The filename in which the assertion failed,
+ * int lineno;		The line number of the assertion.
+ *
+ * Reports the assertion on standard output and then aborts with a core dump.
+ */
+#else
+#define assert(x)	/* nothing */
+#endif
+
+# undef PUBLIC
Index: /trunk/minix/commands/yap/build
===================================================================
--- /trunk/minix/commands/yap/build	(revision 9)
+++ /trunk/minix/commands/yap/build	(revision 9)
@@ -0,0 +1,5 @@
+#!/bin/sh
+set -e
+make clean
+make
+make install
Index: /trunk/minix/commands/yap/commands.c
===================================================================
--- /trunk/minix/commands/yap/commands.c	(revision 9)
+++ /trunk/minix/commands/yap/commands.c	(revision 9)
@@ -0,0 +1,706 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+# ifndef lint
+static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/commands.c,v 1.1.1.1 2005/04/21 14:55:38 beng Exp $";
+# endif
+
+# define _COMMANDS_
+
+# include "in_all.h"
+# include "commands.h"
+# include "output.h"
+# include "process.h"
+# include "help.h"
+# include "term.h"
+# include "prompt.h"
+# include "getline.h"
+# include "getcomm.h"
+# include "pattern.h"
+# include "display.h"
+# include "options.h"
+# include "machine.h"
+# include "keys.h"
+# include "main.h"
+# include "assert.h"
+# if USG_OPEN
+# include <fcntl.h>
+# include <errno.h>
+extern int errno;
+# endif
+# if BSD4_2_OPEN
+# include <sys/file.h>
+# include <errno.h>
+extern int errno;
+# endif
+# if POSIX_OPEN
+# include <sys/types.h>
+# include <fcntl.h>
+# include <errno.h>
+# endif
+
+char	*strcpy(), *strcat();
+
+static long lastcount;		/* Save last count for '.' command */
+static int lastcomm;		/* Save last command for '.' command */
+
+/*ARGSUSED*/
+STATIC int
+do_nocomm(cnt) long cnt; {	/* Do nothing */
+}
+
+/*ARGSUSED*/
+int
+do_chkm(cnt) long cnt; {	/* Change key map */
+	register struct keymap *p;
+
+	if (!(p = othermap)) {
+		error("No other keymap");
+		return;
+	}
+	othermap = currmap;
+	currmap = p;
+}
+
+static int searchdir;		/* Direction of last search */
+
+/*
+ * Perform searches
+ */
+
+STATIC VOID
+do_search(str,cnt,dir) char *str; long cnt; int dir; {
+	register char *p;
+	register long lineno;
+
+	if (str) {
+		/*
+		 * We have to get a pattern, which we have to prompt for
+		 * with the string "str".
+		 */
+		if ((p = readline(str)) == 0) {
+			/*
+			 * User cancelled command
+			 */
+			return;
+		}
+		if ((p = re_comp(p))) {
+			/*
+			 * There was an error in the pattern
+			 */
+			error(p);
+			return;
+		}
+		searchdir = dir;
+	}
+	if (dir < 0) lineno = scr_info.firstline;
+	else lineno = scr_info.lastline;
+	for (;;) {
+		p = 0;
+		if ((lineno += dir) > 0) p = getline(lineno, 0);
+		if (interrupt) return;
+		if (!p) {	/* End of file reached */
+			error("pattern not found");
+			return;
+		}
+		if (re_exec(p) && --cnt <= 0) {
+			/*
+			 * We found the pattern, and we found it often enough.
+			 * Pity that we still don't know where the match is.
+			 * We only know the linenumber. So, we just hope the
+			 * following will at least bring it on the screen ...
+			 */
+			(VOID) display(lineno,0,pagesize,0);
+			(VOID) scrollb(2,0);
+			redraw(0);
+			return;
+		}
+	}
+	/* NOTREACHED */
+}
+
+STATIC int
+do_fsearch(cnt) long cnt; {	/* Forward search */
+
+	do_search("/", cnt, 1);
+}
+
+STATIC int
+do_bsearch(cnt) long cnt; {	/* Backward search */
+
+	do_search("?", cnt, -1);
+}
+
+/*
+ * Repeat last search in direction "dir"
+ */
+
+STATIC int
+n_or_rn_search(cnt,dir) long cnt; int dir; {
+	register char *p;
+
+	if (dir == 1) {
+		p = "/\r";
+	}
+	else if (dir == -1) {
+		p = "?\r";
+	}
+	else {
+		error("No previous pattern");
+		return;
+	}
+	if (!stupid) clrbline();
+	putline(p);
+	flush();
+	do_search((char *) 0, cnt, dir);
+}
+
+STATIC int
+do_nsearch(cnt) long cnt; {	/* Repeat search in same direction */
+	
+	n_or_rn_search(cnt,searchdir);
+}
+
+STATIC int
+do_rnsearch(cnt) long cnt; {	/* Repeat search in opposite direction */
+
+	n_or_rn_search(cnt, -searchdir);
+}
+
+STATIC int shell(esc_ch, cnt) long cnt;
+{
+	register char *p;
+	static char buf[2];
+
+	buf[0] = esc_ch;
+	if (p = readline(buf)) {
+		shellescape(p, esc_ch);
+		if (cnt >= 0 && !hardcopy) {
+			p = startcomm;
+			startcomm = 0;
+			ret_to_continue();
+			putline(TI);
+			if (!p) {
+				/*
+				 * Avoid double redraw.
+				 * After a "startcomm", a redraw will
+				 * take place anyway.
+				 */
+				redraw(1);
+			}
+		}
+	}
+}
+
+STATIC int
+do_shell(cnt) long cnt; {	/* Execute a shell escape */
+	shell('!', cnt);
+}
+
+STATIC int
+do_pipe(cnt) long cnt; {	/* Execute a shell escape */
+	shell('|', cnt);
+}
+
+/*ARGSUSED*/
+STATIC int
+do_writefile(cnt) long cnt; {	/* Write input to a file */
+	register char *p;
+	int fd;
+
+	if ((p = readline("Filename: ")) == 0 || !*p) {
+		/*
+		 * No file name given
+		 */
+		return;
+	}
+# if USG_OPEN || BSD4_2_OPEN || POSIX_OPEN
+	if ((fd = open(p,O_CREAT|O_EXCL|O_WRONLY,0644)) < 0) {
+		if (errno == EEXIST) {
+			error("File exists");
+			return;
+		}
+		error("Could not open file");
+		return;
+	}
+# else
+	if (!access(p,0)) {
+		error("File exists");
+		return;
+	}
+	if ((fd = creat(p,0644)) < 0) {
+		error("Could not open file");
+		return;
+	}
+# endif
+	wrt_fd(fd);
+	(VOID) close(fd);
+}
+
+VOID
+wrt_fd(fd)
+{
+	register long l = 1;
+	register char *p = getline(l,0), *pbuf;
+	char buf[1024];
+
+	while (p) {
+		pbuf = buf;
+		while (p && pbuf < &buf[1024]) {
+			if (!*p) {
+				*pbuf++ = '\n';
+				p = getline(++l,0);
+			}
+			else *pbuf++ = *p++ & 0177;
+		}
+		if (write(fd, buf, pbuf - buf) < 0) {
+			error("Write failed");
+			break;
+		}
+	}
+}
+
+STATIC int
+do_absolute(cnt) long cnt; {	/* Go to linenumber "cnt" */
+
+	if (!getline(cnt,0)) {	/* Not there or interrupt */
+		if (!interrupt) {
+			/*
+			 * User did'nt give an interrupt, so the line number
+			 * was too high. Go to the last line.
+			 */
+			do_lline(cnt);
+		}
+		return;
+	}
+	(VOID) display(cnt,0,pagesize,1);
+}
+
+/*ARGSUSED*/
+STATIC int
+do_visit(cnt) long cnt; {	/* Visit a file */
+	register char *p;
+	static char fn[128];	/* Keep file name */
+
+	if ((p = readline("Filename: ")) == 0) {
+		return;
+	}
+	if (*p) {
+		(VOID) strcpy(fn,p);
+		visitfile(fn);
+	}
+	else {
+		/*
+		 * User typed a return. Visit the current file
+		 */
+		if (!(p = filenames[filecount])) {
+			error("No current file");
+			return;
+		}
+		visitfile(p);
+	}
+	(VOID) display(1L, 0, pagesize, 1);
+}
+
+/*ARGSUSED*/
+STATIC int
+do_error(cnt) long cnt; {	/* Called when user types wrong key sequence */
+
+	error(currmap->k_help);
+}
+
+/*
+ * Interface routine for displaying previous screen,
+ * depending on cflag.
+ */
+
+STATIC int
+prev_screen(sz,really) int sz, really; {
+	register int retval;
+
+	retval = scrollb(sz - 1, really && cflag);
+	if (really && !cflag) {
+		/*
+		 * The previous call did not display anything, but at least we
+		 * know where to start
+		 */
+		return display(scr_info.firstline, scr_info.nf, sz, 1);
+	}
+	return retval;
+}
+
+/*
+ * Interface routine for displaying the next screen,
+ * dependent on cflag.
+ */
+
+STATIC int
+next_screen(sz,really) int sz, really; {
+
+	register int t;
+	register struct scr_info *p = &scr_info;
+
+	if (cflag) {
+		return scrollf(sz-1,really);
+	}
+	t = p->tail->cnt - 1;
+	if (p->lastline == p->firstline) {
+		t += p->nf;
+	}
+	return display(p->lastline, t, sz, really);
+}
+
+/*ARGSUSED*/
+STATIC int
+do_redraw(cnt) long cnt; {
+
+	redraw(1);
+}
+
+STATIC int
+page_size(cnt) unsigned cnt; {
+
+	if (cnt) {
+		if (cnt > maxpagesize) return maxpagesize;
+		if (cnt < MINPAGESIZE) return MINPAGESIZE;
+		return (int) cnt;
+	}
+	return pagesize;
+}
+
+STATIC int
+do_forward(cnt) long cnt; {	/* Display next page */
+	register int i;
+
+	i = page_size((unsigned) cnt);
+	if (status & EOFILE) {
+		/*
+		 * May seem strange, but actually a visit to the next file
+		 * has already been done here
+		 */
+		(VOID) display(1L,0,i,1);
+		return;
+	}
+	(VOID) next_screen(i,1);
+}
+
+STATIC int
+do_backward(cnt) long cnt; {
+	register int i, temp;
+
+	i = page_size((unsigned) cnt);
+	if (!(status & START)) {
+		(VOID) prev_screen(i,1);
+		return;
+	}
+	if (stdf < 0) {
+		(VOID) display(1L,0,i,1);
+		return;
+	}
+	/*
+	 * The next part is a bit clumsy.
+	 * We want to display the last page of the previous file (for which
+	 * a visit has already been done), but the pagesize may temporarily
+	 * be different because the command had a count
+	 */
+	temp = pagesize;
+	pagesize = i;
+	do_lline(cnt);
+	pagesize = temp;
+}
+
+/*ARGSUSED*/
+STATIC int
+do_firstline(cnt) long cnt; {	/* Go to start of input */
+
+	do_absolute(1L);
+}
+
+STATIC int
+do_lline(cnt) long cnt; {	/* Go to end of input */
+	register int i = 0;
+	register int j = pagesize - 1;
+
+	if ((cnt = to_lastline()) < 0) {
+		/*
+		 * Interrupted by the user
+		 */
+		return;
+	}
+	/*
+	 * Display the page such that only the last line of the page is
+	 * a "~", independant of the pagesize
+	 */
+	while (!(display(cnt,i,j,0) & EOFILE)) {
+		/*
+		 * The last line could of course be very long ...
+		 */
+		i+= j;
+	}
+	(VOID) scrollb(j - scr_info.tail->cnt, 0);
+	redraw(0);
+}
+
+STATIC int
+do_lf(cnt) long cnt; {		/* Display next line, or go to line */
+
+	if (cnt) {		/* Go to line */
+		do_absolute(cnt);
+		return;
+	}
+	(VOID) scrollf(1,1);
+}
+
+STATIC int
+do_upline(cnt) long cnt; {	/* Display previous line, or go to line */
+
+	if (cnt) {		/* Go to line */
+		do_absolute(cnt);
+		return;
+	}
+	(VOID) scrollb(1,1);
+}
+
+STATIC int
+do_skiplines(cnt) long cnt; {	/* Skip lines forwards */
+
+	/* Should be interruptable ... */
+	(VOID) scrollf((int) (cnt + maxpagesize - 1), 0);
+	redraw(0);
+}
+
+STATIC int
+do_bskiplines(cnt) long cnt; {	/* Skip lines backwards */
+
+	/* Should be interruptable ... */
+	(VOID) scrollb((int) (cnt + pagesize - 1), 0);
+	redraw(0);
+}
+
+STATIC int
+do_fscreens(cnt) long cnt; {	/* Skip screens forwards */
+
+	do {
+		if ((next_screen(pagesize,0) & EOFILE) || interrupt) break;
+	} while (--cnt >= 0);
+	redraw(0);
+}
+
+STATIC int
+do_bscreens(cnt) long cnt; {	/* Skip screens backwards */
+
+	do {
+		if ((prev_screen(pagesize,0) & START) || interrupt) break;
+	} while (--cnt >= 0);
+	redraw(0);
+}
+
+STATIC int
+scro_size(cnt) unsigned cnt; {
+
+	if (cnt >= maxpagesize) return maxpagesize;
+	if (cnt) return (int) cnt;
+	return scrollsize;
+}
+
+STATIC int
+do_f_scroll(cnt) long cnt; {	/* Scroll forwards */
+
+	(VOID) scrollf(scro_size((unsigned) cnt),1);
+}
+
+STATIC int
+do_b_scroll(cnt) long cnt; {	/* Scroll backwards */
+
+	(VOID) scrollb(scro_size((unsigned) cnt),1);
+}
+
+STATIC int
+do_previousfile(cnt) long cnt; {/* Visit previous file */
+
+	if (nextfile(- (int) cnt)) {
+		error("No (Nth) previous file");
+		return;
+	}
+	redraw(0);
+}
+
+STATIC int
+do_nextfile(cnt) long cnt; {	/* Visit next file */
+
+	if (nextfile((int) cnt)) {
+		error("No (Nth) next file");
+		return;
+	}
+	redraw(0);
+}
+
+STATIC int do_lcomm();
+
+/*
+ * The next array is initialized, sorted on the first element of the structs,
+ * so that we can perform binary search
+ */
+struct commands commands[] = {
+{"",	    0,	    do_error,	    ""},
+{"",	    0,	    do_nocomm,	    ""},
+{"bf",	    STICKY|NEEDS_COUNT,
+		    do_previousfile,"Visit previous file"},
+{"bl",	    NEEDS_SCREEN|STICKY,
+		    do_upline,	    "Scroll one line up, or go to line"},
+{"bot",	    STICKY,
+		    do_lline,	    "Go to last line of the input"},
+{"bp",	    BACK|NEEDS_SCREEN|TOPREVFILE|STICKY,
+		    do_backward,    "display previous page"},
+{"bps",	    SCREENSIZE_ADAPT|BACK|NEEDS_SCREEN|TOPREVFILE|STICKY,
+		    do_backward,    "Display previous page, set pagesize"},
+{"bs",	    BACK|NEEDS_SCREEN|STICKY,
+		    do_b_scroll,    "Scroll backwards"},
+{"bse",	    0,	    do_bsearch,	    "Search backwards for pattern"},
+{"bsl",	    BACK|NEEDS_SCREEN|STICKY|NEEDS_COUNT,
+		    do_bskiplines,  "Skip lines backwards"},
+{"bsp",	    BACK|NEEDS_SCREEN|STICKY|NEEDS_COUNT,
+		    do_bscreens,    "Skip screens backwards"},
+{"bss",	    SCROLLSIZE_ADAPT|BACK|NEEDS_SCREEN|STICKY,
+		    do_b_scroll,    "Scroll backwards, set scrollsize"},
+{"chm",	    0,	    do_chkm,	    "Switch to other keymap"},
+{"exg",	    STICKY, exgmark,	    "Exchange current page with mark"},
+{"ff",	    STICKY|NEEDS_COUNT,
+		    do_nextfile,    "Visit next file"},
+{"fl",	    NEEDS_SCREEN|STICKY,
+		    do_lf,	    "Scroll one line down, or go to line"},
+{"fp",	    TONEXTFILE|AHEAD|STICKY,
+		    do_forward,	    "Display next page"},
+{"fps",	    SCREENSIZE_ADAPT|TONEXTFILE|AHEAD|STICKY,
+		    do_forward,	    "Display next page, set pagesize"},
+{"fs",	    AHEAD|NEEDS_SCREEN|STICKY,
+		    do_f_scroll,    "Scroll forwards"},
+{"fse",	    0,	    do_fsearch,	    "Search forwards for pattern"},
+{"fsl",	    AHEAD|NEEDS_SCREEN|STICKY|NEEDS_COUNT,
+		    do_skiplines,   "Skip lines forwards"},
+{"fsp",	    AHEAD|NEEDS_SCREEN|STICKY|NEEDS_COUNT,
+		    do_fscreens,    "Skip screens forwards"},
+{"fss",	    SCROLLSIZE_ADAPT|AHEAD|NEEDS_SCREEN|STICKY,
+		    do_f_scroll,    "Scroll forwards, set scrollsize"},
+{"hlp",	    0,	    do_help,	    "Give description of all commands"},
+{"mar",	    0,	    setmark,	    "Set a mark on the current page"},
+{"nse",	    STICKY, do_nsearch,	    "Repeat the last search"},
+{"nsr",	    STICKY, do_rnsearch, "Repeat last search in other direction"},
+{"pip",     ESC,    do_pipe,	    "pipe input into shell command"},
+{"qui",	    0,	    quit,	    "Exit from yap"},
+{"red",	    0,	    do_redraw,	    "Redraw screen"},
+{"rep",	    0,	    do_lcomm,	    "Repeat last command"},
+{"shl",	    ESC,    do_shell,	    "Execute a shell escape"},
+{"tom",	    0,	    tomark,	    "Go to mark"},
+{"top",	    STICKY, do_firstline,   "Go to the first line of the input"},
+{"vis",	    0,	    do_visit,	    "Visit a file"},
+{"wrf",	    0,	    do_writefile,   "Write input to a file"},
+};
+
+/*
+ * Lookup string "s" in the commands array, and return index.
+ * return 0 if not found.
+ */
+
+int
+lookup(s) char *s; {
+	register struct commands *l, *u, *m;
+
+	l = &commands[2];
+	u = &commands[sizeof(commands) / sizeof(*u) - 1];
+	do {
+		/*
+		 * Perform binary search
+		 */
+		m = l + (u - l) / 2;
+		if (strcmp(s, m->c_cmd) > 0) l = m + 1;
+		else u = m;
+	} while (l < u);
+	if (!strcmp(s, u->c_cmd)) return u - commands;
+	return 0;
+}
+
+/*ARGSUSED*/
+STATIC int
+do_lcomm(cnt) long cnt; {	/* Repeat last command */
+
+	if (!lastcomm) {
+		error("No previous command");
+		return;
+	}
+	do_comm(lastcomm, lastcount);
+}
+
+/*
+ * Execute a command, with optional count "count".
+ */
+
+VOID
+do_comm(comm, count) register int comm; register long count; {
+
+	register struct commands *pcomm;
+	register int temp;
+	register int flags;
+
+	pcomm = &commands[comm];
+	flags = pcomm->c_flags;
+
+	/*
+	 * Check the command.
+	 * If the last line of the file is displayed and the command goes
+	 * forwards and does'nt have the ability to go to the next file, it
+	 * is an error.
+	 * If the first line of the file is displayed and the command goes
+	 * backwards and does'nt have the ability to go to the previous file,
+	 * it is an error.
+	 * Also check wether we need the next or previous file. If so, get it.
+	 */
+	if ((status & EOFILE) && (flags & AHEAD)) {
+		if (qflag || !(flags & TONEXTFILE)) return;
+		if (nextfile(1)) quit();
+	}
+	if ((status & START) && (flags & BACK)) {
+		if (qflag || !(flags & TOPREVFILE)) return;
+		if (nextfile(-1)) quit();
+	}
+	/*
+	 * Does the command stick around for LASTCOMM?
+	 */
+	if (flags & STICKY) {
+		lastcomm = comm;
+		lastcount = count;
+	}
+	if (!count) {
+		if (flags & NEEDS_COUNT) count = 1;
+	}
+	else {
+		/*
+		 * Does the command adapt the screensize?
+		 */
+		if (flags & SCREENSIZE_ADAPT) {
+			temp = maxpagesize;
+			if ((unsigned) count < temp) {
+				temp = count;
+			}
+			if (temp < MINPAGESIZE) {
+				temp = MINPAGESIZE;
+			}
+			count = 0;
+			pagesize = temp;
+		}
+		/*
+		 * Does the command adapt the scrollsize?
+		 */
+		if (flags & SCROLLSIZE_ADAPT) {
+			temp = maxpagesize - 1;
+			if ((unsigned) count < temp) {
+				temp = (int) count;
+			}
+			scrollsize = temp;
+			count = 0;
+		}
+	}
+	/*
+	 * Now execute the command.
+	 */
+	(*(pcomm->c_func))(count);
+}
Index: /trunk/minix/commands/yap/commands.h
===================================================================
--- /trunk/minix/commands/yap/commands.h	(revision 9)
+++ /trunk/minix/commands/yap/commands.h	(revision 9)
@@ -0,0 +1,64 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/commands.h,v 1.1.1.1 2005/04/21 14:55:39 beng Exp $ */
+
+# ifndef _COMMANDS_
+# define PUBLIC extern
+# else
+# define PUBLIC
+# endif
+
+/* Flags, describing properties of commands */
+
+# define SCREENSIZE_ADAPT	01	/* Can change screen size */
+# define SCROLLSIZE_ADAPT	02	/* Can change scrollsize */
+# define TONEXTFILE		04	/* to next file */
+# define AHEAD			010	/* goes ahead in the file */
+# define BACK			020	/* goes back in the file */
+# define NEEDS_SCREEN		040	/* needs screen info */
+# define TOPREVFILE		0100	/* to previous file */
+# define STICKY			0200	/* remember for lastcomm */
+# define NEEDS_COUNT		0400	/* command needs a count */
+# define ESC			01000	/* shell or pipe escape */
+
+extern struct commands {
+    char *c_cmd;		/* Short mnemonic for a command */
+    int c_flags;		/* describes command properties */
+    int (*c_func)();		/* Function executing the command */
+    char *c_descr;		/* Short command description */
+} commands[];
+
+int	do_chkm();
+/*
+ * int	do_chkm(cnt)
+ * long cnt;			Ignored
+ *
+ * Switch to other keymap
+ */
+
+VOID	do_comm();
+/*
+ * void do_comm(command, count)
+ * int command;			Index in the commands array
+ * long count;			Some commands possibly take a count
+ *
+ * Checks and executes commands.
+ */
+
+int	lookup();
+/*
+ * int lookup(str)
+ * char *str;
+ *
+ * Searches the string "str" in the command list.
+ * It returns its index if it exists, otherwise it returns 0.
+ */
+
+VOID	wrt_fd();
+/*
+ * void wrt_fd(fd)
+ * int fd;			File descriptor
+ *
+ * Write input to file descriptor fd
+ */
+# undef PUBLIC
Index: /trunk/minix/commands/yap/display.c
===================================================================
--- /trunk/minix/commands/yap/display.c	(revision 9)
+++ /trunk/minix/commands/yap/display.c	(revision 9)
@@ -0,0 +1,547 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+# ifndef lint
+static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/display.c,v 1.1.1.1 2005/04/21 14:55:39 beng Exp $";
+# endif
+
+# define _DISPLAY_
+
+# include "in_all.h"
+# include "display.h"
+# include "assert.h"
+# include "machine.h"
+# include "term.h"
+# include "output.h"
+# include "options.h"
+# include "process.h"
+# include "getline.h"
+# include "main.h"
+
+STATIC char * do_line();
+
+/*
+ * Fill n lines of the screen, each with "str".
+ */
+
+STATIC VOID
+fillscr(n,str) char *str; int n; {
+
+	while (n-- > 0) {
+		putline(str);
+	}
+}
+
+/*
+ * Skip "n" screenlines of line "p", and return what's left of it.
+ */
+
+STATIC char *
+skiplines(p,n) char *p; int n; {
+
+	while (n-- > 0) {
+		p = do_line(p,0);
+		scr_info.currentpos--;
+	}
+	return p;
+}
+
+/*
+ * Redraw screen.
+ * "n" = 1 if it is a real redraw, 0 if one page must be displayed.
+ * It is also called when yap receives a stop signal.
+ */
+
+VOID
+redraw(n) int n; {
+	register struct scr_info *p = &scr_info;
+	register int i;
+
+	i = pagesize;
+	if (n && p->currentpos) {
+		i = p->currentpos;
+	}
+	(VOID) display(p->firstline,p->nf,i,1);
+}
+
+/*
+ * Compute return value for the routines "display" and "scrollf".
+ * This return value indicates wether we are at the end of file
+ * or at the start, or both.
+ * "s" contains that part of the last line that was not displayed.
+ */
+
+STATIC int
+compretval(s) char *s; {
+	register int i;
+	register struct scr_info *p = &scr_info;
+
+	i = 0;
+	if (!s || (!*s && !getline(p->lastline+1, 1))) {
+		i = EOFILE;
+	}
+	if (p->firstline == 1 && !p->nf) {
+		i |= START;
+	}
+	status = i;
+	return i;
+}
+
+/*
+ * Display nlines, starting at line n, not displaying the first
+ * nd screenlines of n.
+ * If reallydispl = 0, the actual displaying is not performed,
+ * only the computing associated with it is done.
+ */
+
+int
+display(n,nd,nlines,reallydispl)
+  long n; int nd; register int nlines; int reallydispl; {
+
+	register struct scr_info *s = &scr_info;
+	register char *p;	/* pointer to line to be displayed */
+
+	if (startcomm)	{	/* No displaying on a command from the
+				 * yap command line. In this case, displaying
+				 * will be done after executing the command,
+				 * by a redraw.
+				 */
+		reallydispl = 0;
+	}
+	if (!n) {
+		n = 1L;
+		nd = 0;
+	}
+	if (reallydispl) {	/* move cursor to starting point */
+		if (stupid) {
+			putline(currentfile);
+			putline(", line ");
+			prnum(n);
+			nlines--;
+		}
+		if (cflag) {
+			putline("\r\n");
+		}
+		else {
+			home();
+			clrscreen();
+		}
+	}
+	/*
+	 * Now, do computations and display
+	 */
+	s->currentpos = 0;
+	s->nf = nd;
+	s->head = s->tail;
+	s->tail->cnt = 0;
+	s->tail->line = n;
+	p = skiplines(getline(n,1),nd);
+	while (nlines && p) {
+		/*
+		 * While there is room,
+		 * and there is something left to display ...
+		 */
+		(s->tail->cnt)++;
+		nlines--;
+		if (*(p = do_line(p,reallydispl)) == '\0') {
+			/*
+			 * File-line finished, get next one ...
+			 */
+			p = getline(++n,1);
+			if (nlines && p) {
+				s->tail = s->tail->next;
+				s->tail->cnt = 0;
+				s->tail->line = n;
+			}
+		}
+	}
+	if (!stupid) {
+		s->currentpos += nlines;
+		if (reallydispl) {
+			fillscr(nlines, "~\r\n");
+			fillscr(maxpagesize - s->currentpos, "\r\n");
+		}
+	}
+	return compretval(p);
+}
+
+/*
+ * Scroll forwards n lines.
+ */
+
+int
+scrollf(n,reallydispl) int n; int reallydispl; {
+
+	register struct scr_info *s = &scr_info;
+	register char *p;
+	register long ll;
+	register int i;
+
+	/*
+	 * First, find out how many screenlines of the last line were already
+	 * on the screen, and possibly above it.
+	 */
+
+	if (n <= 0 || (status & EOFILE)) return status;
+	if (startcomm) reallydispl = 0;
+	/*
+	 * Find out where to begin displaying
+	 */
+	i = s->tail->cnt;
+	if ((ll = s->lastline) == s->firstline) i += s->nf;
+	p = skiplines(getline(ll, 1), i);
+	/*
+	 * Now, place the cursor at the first free line
+	 */
+	if (reallydispl && !stupid) {
+		clrbline();
+		mgoto(s->currentpos);
+	}
+	/*
+	 * Now display lines, keeping track of which lines are on the screen.
+	 */
+	while (n-- > 0) {	/* There are still rows to be displayed */
+		if (!*p) {	/* End of line, get next one */
+			if (!(p = getline(++ll, 1))) {
+				/*
+				 * No lines left. At end of file
+				 */
+				break;
+			}
+			s->tail = s->tail->next;
+			s->tail->cnt = 0;
+			s->tail->line = ll;
+		}
+		if (s->currentpos >= maxpagesize) {
+			/*
+			 * No room, delete first screen-line
+			 */
+			s->currentpos--;
+			s->nf++;
+			if (--(s->head->cnt) == 0) {
+				/*
+				 * The first file-line on the screen is wiped
+				 * out completely; update administration
+				 * accordingly.
+				 */
+				s->nf = 0;
+				s->head = s->head->next;
+				assert(s->head->cnt > 0);
+			}
+		}
+		s->tail->cnt++;
+		p = do_line(p, reallydispl);
+	}
+	return compretval(p);
+}
+
+/*
+ * Scroll back n lines
+ */
+
+int
+scrollb(n, reallydispl) int n, reallydispl; {
+
+	register struct scr_info *s = &scr_info;
+	register char *p;	/* Holds string to be displayed */
+	register int i;
+	register int count;
+	register long ln;	/* a line number */
+	register int nodispl;
+	int cannotscroll;	/* stupid or no insert-line */
+
+	/*
+	 * First, find out where to start
+	 */
+	if ((count = n) <= 0 || (status & START)) return status;
+	if (startcomm) reallydispl = 0;
+	cannotscroll = stupid || (!*AL && !*SR);
+	ln = s->firstline;
+	nodispl = s->nf;
+	while (count) { /* While scrolling back ... */
+		if (i = nodispl) {
+			/*
+			 * There were screen-lines of s->firstline that were not
+			 * displayed.
+			 * We can use them now, but only "count" of them.
+			 */
+			if (i > count) i = count;
+			s->currentpos += i;
+			nodispl -= i;
+			count -= i;
+		}
+		else {	/* Get previous line */
+			if (ln == 1) break; /* isn't there ... */
+			p = getline(--ln, 1);
+			/*
+			 * Make it the first line of the screen and compute
+			 * how many screenlines it takes. These lines are not
+			 * displayed, but nodispl is set to this count, so
+			 * that it will be nonzero next time around
+			 */
+			nodispl = 0;
+			do {	/* Find out how many screenlines */
+				nodispl++;
+				p = skiplines(p, 1);
+			} while (*p);
+		}
+	}
+	n -= count;
+	if ((i = s->currentpos) > maxpagesize) i = maxpagesize;
+	if (reallydispl && hardcopy) i = n;
+	/*
+	 * Now that we know where to start, we can use "display" to do the
+	 * rest of the computing for us, and maybe even the displaying ...
+	 */
+	i = display(ln,
+		    nodispl,
+		    i,
+		    reallydispl && cannotscroll);
+	if (cannotscroll || !reallydispl) {
+		/*
+		 * Yes, "display" did the displaying, or we did'nt have to
+		 * display at all.
+		 * I like it, but the user obviously does not.
+		 * Let him buy another (smarter) terminal ...
+		 */
+		return i;
+	}
+	/*
+	 * Now, all we have to do is the displaying. And we are dealing with
+	 * a smart terminal (it can insert lines or scroll back).
+	 */
+	home();
+	/*
+	 * Insert lines all at once
+	 */
+	for (i = n; i; i--) {
+		if (DB && *CE) {
+			/*
+			 * Grumble..., terminal retains lines below, so we have
+			 * to clear the lines that we push off the screen
+			 */
+			clrbline();
+			home();
+		}
+		if (*SR) {
+			scrollreverse();
+		}
+		else {
+# ifdef VT100_PATCH
+			insert_line(0);
+# else
+			insert_line();
+# endif
+		}
+	}
+	p = skiplines(getline(ln = s->firstline, 1), s->nf);
+	for (i = 0; i < n; i++) {
+		p = do_line(p,1);
+		s->currentpos--;
+		if (!*p) {
+			p = getline(++ln, 1);
+		}
+	}
+	return count;
+}
+
+/*
+ * Process a line.
+ * If reallydispl > 0 then display it.
+ */
+
+STATIC char *
+do_line(str, reallydispl) register char *str; int reallydispl; {
+
+	char buf[1024];
+	register char *p = buf;
+	register int pos = COLS;
+	register int c;
+	register int c1;
+	register int do_ul = 0, do_hl = 0;
+	int lastmode = 0, lasthlmode = 0;
+	int c2;
+
+	while (*str && pos > 0) {
+		if (*str < ' ' && (c1 = match(str,&c2,sppat)) > 0) {
+			/*
+			 * We found a string that matches, and thus must be
+			 * echoed literally
+			 */
+			if ((pos - c2) <= 0) {
+				/*
+				 * It did not fit
+				 */
+				break;
+			}
+			pos -= c2;
+			str += c1;
+			if (reallydispl) {
+				c = *str;
+				*p = *str = 0;
+				cputline(p = buf);
+				putline(str - c1);
+				*str = c;
+			}
+			continue;
+		}
+		c = *str++;
+		do_hl = 0;
+		if (*str == '\b' && *(str+1) != 0
+					&& (c != '_' || *(str+2) == '\b')) {
+			while (*str == '\b' && *(str+1) != 0) {
+				str++;
+				c = *str++;
+				do_hl = 1;
+			}
+		}
+		do_ul = 1;
+		/*
+		 * Find underline sequences ...
+		 */
+		if (c == '_' && *str == '\b') {
+			str++;
+			c = *str++;
+		}
+		else {
+			if (*str == '\b' && *(str+1) == '_') {
+				str += 2;
+			}
+			else	do_ul = 0;
+		}
+		if (reallydispl && do_hl != lasthlmode) {
+			*p = 0;
+			cputline(p = buf);
+			if (do_hl) bold();
+			else end_bold();
+		}
+		lasthlmode = do_hl;
+		if (reallydispl && do_ul != lastmode) {
+			*p = 0;
+			cputline(p = buf);
+			if (do_ul) underline();
+			else end_underline();
+		}
+		lastmode = do_ul;
+		*p++ = c;
+		if (c >= ' ' && c < 0177) {
+			pos--;
+			if (reallydispl && do_ul && *UC && pos > 0) {
+				/*
+				 * Underlining apparently is done one
+				 * character at a time.
+				 */
+				*p = 0;
+				cputline(p = buf);
+				backspace();
+				underchar();
+			}
+			continue;
+		}
+		if (c == '\t') {
+			p--;
+			c1 = 8 - ((COLS - pos) & 07);
+			/*
+			 * Actually, if COLS is a multiple of 8, this can be
+			 * simplified to
+			 *     c1 = pos & 07;
+			 * But of course, we don't know that for sure.
+			 */
+			if (pos - c1 < 0) break;
+			pos -= c1;
+			if (reallydispl) {
+				if (expandtabs) {
+					/*
+					 * Expand tabs. We cannot let the
+					 * kernel take care of this
+					 * for two reasons:
+					 * 1. There can be tabs in cursor
+					 *    addressing strings,
+					 * 2. We probably do it better.
+					 */
+					while (c1-- > 0) {
+						*p++ = ' ';
+					}
+				}
+				else {
+					*p = 0;
+					cputline(p = buf);
+					givetab();
+				}
+			}
+			continue;
+		}
+		/*
+		 * Now we have a control character, which takes two positions
+		 */
+		if (pos <= 1) {
+			p--;
+			break;
+		}
+		pos -= 2;
+	}
+	if (reallydispl) {
+		*p = 0;
+		cputline(buf);
+		if (pos > 0 || (pos <= 0 && (!AM || XN))) {
+			putline("\r\n");
+		}
+		/*
+		 * The next should be here! I.e. it may not be before printing
+		 * the newline. This has to do with XN. We don't know exactly
+		 * WHEN the terminal will stop ignoring the newline.
+		 * I have for example a terminal (Ampex a230) that will
+		 * continue to ignore the newline after a clear to end of line
+		 * sequence, but not after an end_underline sequence.
+		 */
+		if (do_ul) {
+			end_underline();
+		}
+		if (do_hl) {
+			standend();
+		}
+	}
+	scr_info.currentpos++;
+	return str;
+}
+
+/* ARGSUSED */
+int
+setmark(cnt) long cnt; {	/* Set a mark on the current page */
+	register struct scr_info *p = &scr_info;
+
+	p->savfirst = p->firstline;
+	p->savnf = p->nf;
+}
+
+/* ARGSUSED */
+int
+tomark(cnt) long cnt; {		/* Go to the mark */
+	register struct scr_info *p = &scr_info;
+
+	(VOID) display(p->savfirst,p->savnf,pagesize,1);
+}
+
+/* ARGSUSED */
+int
+exgmark(cnt) long cnt; {	/* Exchange mark and current page */
+	register struct scr_info *p = &scr_info;
+	register long svfirst;
+	register int svnf;
+
+	svfirst = p->firstline;
+	svnf = p->nf;
+	tomark(0L);
+	p->savfirst = svfirst;
+	p->savnf = svnf;
+}
+
+VOID
+d_clean() {			/* Clean up */
+	register struct scr_info *p = &scr_info;
+
+	p->savnf = 0;
+	p->savfirst = 0;
+	p->head = p->tail;
+	p->head->line = 0;
+	p->currentpos = 0;
+}
Index: /trunk/minix/commands/yap/display.h
===================================================================
--- /trunk/minix/commands/yap/display.h	(revision 9)
+++ /trunk/minix/commands/yap/display.h	(revision 9)
@@ -0,0 +1,124 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/display.h,v 1.1.1.1 2005/04/21 14:55:39 beng Exp $ */
+
+# ifndef _DISPLAY_
+# define PUBLIC extern
+# else
+# define PUBLIC
+# endif
+
+# define MINPAGESIZE 5
+
+PUBLIC int	pagesize;	/* How many lines on a page */
+PUBLIC int	maxpagesize;	/* Maximum # of lines on a page */
+PUBLIC int	scrollsize;	/* number of lines in a scroll */
+struct scr_info {
+	struct linelist {
+	    int cnt;		/* # of screenlines for this line */
+	    long line;		/* lineno of this line */
+# define firstline head->line
+# define lastline tail->line
+	    struct linelist *next;
+	    struct linelist *prev;
+	} *tail, *head;		/* Of all lines of the input file that are
+				 * on the screen, remember how many
+				 * screenlines they occupy. Keep this
+				 * info in a doubly linked list.
+				 */
+	int	nf;		/* How many screenlines of the first line
+				 * on the screen are not on the screen?
+				 */
+	int	currentpos;	/* Y coordinate of first free line */
+	struct linelist ssaavv; /* Mark */
+# define savfirst ssaavv.line
+# define savnf ssaavv.cnt
+};
+
+PUBLIC struct scr_info scr_info;
+PUBLIC int	status;		/* EOFILE on end of file
+				 * START on start of file
+				 * logical "or" if both
+				 */
+/* Flags for status field */
+
+# define EOFILE 01
+# define START 02
+
+VOID	redraw();
+/*
+ * void redraw(flag)
+ * int flag;			Either 0 or 1
+ *
+ * Redraws the screen. If flag = 1, the screen is redrawn as precisely
+ * as possible, otherwise one page is displayed (which possibly does not
+ * take a whole screen.
+ */
+
+int	display();
+/*
+ * int display(firstline, nodispl, nlines, really)
+ * long firstline;		Line with which to start
+ * int nodispl;			Do not display nodispl lines of it
+ * int nlines;			Number of screen lines that must be displayed
+ * int really;			Either 0 or 1
+ *
+ * Displays nlines as a page. if "really" = 0, the actual displaying is not
+ * performed. Only the computing associated with it is done.
+ */
+
+int	scrollf();
+/*
+ * int scrollf(nlines,really)
+ * int nlines;			Number of lines to scroll
+ * int really;			Either 0 or 1, see explanation above
+ *
+ * Scroll forwards "nlines" (screen)lines.
+ */
+
+int	scrollb();
+/*
+ * int scrollb(nlines,really)
+ * int nlines;			Number of lines to scroll
+ * int really;			Either 0 or 1, see explanation above
+ *
+ * Scroll backwards "nlines" (screen)lines.
+ */
+
+int	tomark();
+/*
+ * int tomark(cnt)
+ * long cnt;			(Argument ignored)
+ *
+ * Display a page starting at the mark. If there was no
+ * mark, display the first page of the file.
+ * (There is always assumed to be a mark, the initial one is on the first page
+ * of the file).
+ */
+
+int	setmark();
+/*
+ * int setmark(cnt)
+ * long cnt;			(Argument ignored)
+ *
+ * Sets a mark on the current page.
+ * It returns nothing (but the address is taken ...)
+ */
+
+int	exgmark();
+/*
+ * int exgmark(cnt)
+ * long cnt;			(Argumewnt ignored)
+ *
+ * Sets the mark on the current page and displays the
+ * previously marked page.
+ */
+
+VOID	d_clean();
+/*
+ * void d_clean()
+ *
+ * Clean up and initialize. To be called before displaying a new file
+ */
+
+# undef PUBLIC
Index: /trunk/minix/commands/yap/getcomm.c
===================================================================
--- /trunk/minix/commands/yap/getcomm.c	(revision 9)
+++ /trunk/minix/commands/yap/getcomm.c	(revision 9)
@@ -0,0 +1,313 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/*
+ * Command reader, also executes shell escapes
+ */
+
+# ifndef lint
+static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/getcomm.c,v 1.1.1.1 2005/04/21 14:55:39 beng Exp $";
+# endif
+
+# define _GETCOMM_
+
+# include <ctype.h>
+# include "in_all.h"
+# include "term.h"
+# include "process.h"
+# include "getcomm.h"
+# include "commands.h"
+# include "prompt.h"
+# include "main.h"
+# include "output.h"
+# include "getline.h"
+# include "machine.h"
+# include "keys.h"
+# include "display.h"
+# include "assert.h"
+
+#if USG_OPEN
+#include <fcntl.h>
+#endif
+#if POSIX_OPEN
+#include <sys/types.h>
+#include <fcntl.h>
+#endif
+
+char	*strcpy(),
+	*getenv();
+
+STATIC int	killchar();
+
+/*
+ * Read a line from the terminal, doing line editing.
+ * The parameter s contains the prompt for the line.
+ */
+
+char *
+readline(s) char *s; {
+
+	static char buf[80];
+	register char *p = buf;
+	register int ch;
+	register int pos;
+
+	clrbline();
+	putline(s);
+	pos = strlen(s);
+	while ((ch = getch()) != '\n' && ch != '\r') {
+		if (ch == -1) {
+			/*
+			 * Can only occur because of an interrupted read.
+			 */
+			ch = erasech;
+			interrupt = 0;
+		}
+		if (ch == erasech) {
+			/*
+			 * Erase last char
+			 */
+			if (p == buf) {
+				/*
+				 * There was none, so return
+				 */
+				return (char *) 0;
+			}
+			pos -= killchar(*--p);
+			if (*p != '\\') continue;
+		}
+		if (ch == killch) {
+			/*
+			 * Erase the whole line
+			 */
+			if (!(p > buf && *(p-1) == '\\')) {
+				while (p > buf) {
+					pos -= killchar(*--p);
+				}
+				continue;
+			}
+			pos -= killchar(*--p);
+		}
+		if (p > &buf[78] || pos >= COLS - 2) {
+			/*
+			 * Line does not fit.
+			 * Simply refuse to make it any longer
+			 */
+			pos -= killchar(*--p);
+		}
+		*p++ = ch;
+		if (ch < ' ' || ch >= 0177) {
+			fputch('^');
+			pos++;
+			ch ^= 0100;
+		}
+		fputch(ch);
+		pos++;
+	}
+	fputch('\r');
+	*p++ = '\0';
+	flush();
+	return buf;
+}
+
+/*
+ * Erase a character from the command line.
+ */
+
+STATIC int
+killchar(c) {
+
+	backspace();
+	putch(' ');
+	backspace();
+	if (c < ' ' || c >= 0177) {
+		(VOID) killchar(' ');
+		return 2;
+	}
+	return 1;
+}
+
+/*
+ * Do a shell escape, after expanding '%' and '!'.
+ */
+
+VOID
+shellescape(p, esc_char) register char *p; {
+
+	register char *p2;	/* walks through command */
+	register int id;	/* procid of child */
+	register int cnt;	/* prevent array bound errors */
+	register int lastc = 0;	/* will contain the previous char */
+# ifdef SIGTSTP
+	VOID (*savetstp)();
+# endif
+	static char previous[256];	/* previous command */
+	char comm[256];			/* space for command */
+	int piped[2];
+
+	p2 = comm;
+	*p2++ = esc_char;
+	cnt = 253;
+	while (*p) {
+		/*
+		 * expand command
+		 */
+		switch(*p++) {
+		  case '!':
+			/*
+			 * An unescaped ! expands to the previous
+			 * command, but disappears if there is none
+			 */
+			if (lastc != '\\') {
+				if (*previous) {
+					id = strlen(previous);
+					if ((cnt -= id) <= 0) break;
+					(VOID) strcpy(p2,previous);
+					p2 += id;
+				}
+			}
+			else {
+				*(p2-1) = '!';
+			}
+			continue;
+		  case '%':
+			/*
+			 * An unescaped % will expand to the current
+			 * filename, but disappears is there is none
+			 */
+			if (lastc != '\\') {
+				if (nopipe) {
+					id = strlen(currentfile);
+					if ((cnt -= id) <= 0) break;
+					(VOID) strcpy(p2,currentfile);
+					p2 += id;
+				}
+			}
+			else {
+				*(p2-1) = '%';
+			}
+			continue;
+		  default:
+			lastc = *(p-1);
+			if (cnt-- <= 0) break;
+			*p2++ = lastc;
+			continue;
+		}
+		break;
+	}
+	clrbline();
+	*p2 = '\0';
+	if (!stupid) {
+		/*
+		 * Display expanded command
+		 */
+		cputline(comm);
+		putline("\r\n");
+	}
+	flush();
+	(VOID) strcpy(previous,comm + 1);
+	resettty();
+	if (esc_char == '|' && pipe(piped) < 0) {
+		error("Cannot create pipe");
+		return;
+	}
+	if ((id = fork()) < 0) {
+		error("Cannot fork");
+		return;
+	}
+	if (id == 0) {
+		/*
+		 * Close files, as child might need the file descriptors
+		 */
+		cls_files();
+		if (esc_char == '|') {
+			close(piped[1]);
+#if USG_OPEN || POSIX_OPEN
+			close(0);
+			fcntl(piped[0], F_DUPFD, 0);
+#else
+			dup2(piped[0], 0);
+#endif
+			close(piped[0]);
+		}
+		execl("/bin/sh", "sh", "-c", comm + 1, (char *) 0);
+		exit(1);
+	}
+	(VOID) signal(SIGINT,SIG_IGN);
+	(VOID) signal(SIGQUIT,SIG_IGN);
+# ifdef SIGTSTP
+	if ((savetstp = signal(SIGTSTP,SIG_IGN)) != SIG_IGN) {
+		(VOID) signal(SIGTSTP,SIG_DFL);
+	}
+# endif
+	if (esc_char == '|') {
+		(VOID) close(piped[0]);
+		(VOID) signal(SIGPIPE, SIG_IGN);
+		wrt_fd(piped[1]);
+		(VOID) close(piped[1]);
+	}
+	while ((lastc = wait((int *) 0)) != id && lastc >= 0)  {
+		/*
+		 * Wait for child, making sure it is the one we expected ...
+		 */
+	}
+	(VOID) signal(SIGINT,catchdel);
+	(VOID) signal(SIGQUIT,quit);
+# ifdef SIGTSTP
+	(VOID) signal(SIGTSTP, savetstp);
+# endif
+	inittty();
+}
+
+/*
+ * Get all those commands ...
+ */
+
+int
+getcomm (plong) long   *plong; {
+	int	c;
+	long	count;
+	char	*p;
+	int	i;
+	int	j;
+	char	buf[10];
+
+	for (;;) {
+		count = 0;
+		give_prompt();
+		while (isdigit((c = getch()))) {
+			count = count * 10 + (c - '0');
+		}
+		*plong = count;
+		p = buf;
+		for (;;) {
+			if (c == -1) {
+				/*
+				 * This should never happen, but it does,
+				 * when the user gives a TSTP signal (^Z) or
+				 * an interrupt while the program is trying
+				 * to read a character from the terminal.
+				 * In this case, the read is interrupted, so
+				 * we end up here.
+				 * Right, we will have to read again.
+				 */
+				if (interrupt) return 1;
+				break;
+			}
+			*p++ = c;
+			*p = 0;
+			if ((i = match(buf, &j, currmap->k_mach)) > 0) {
+				/*
+				 * The key sequence matched. We have a command
+				 */
+				return j;
+			}
+			if (i == 0) return 0;
+			/*
+			 * We have a prefix of a command.
+			 */
+			assert(i == FSM_ISPREFIX);
+			c = getch();
+		}
+	}
+	/* NOTREACHED */
+}
Index: /trunk/minix/commands/yap/getcomm.h
===================================================================
--- /trunk/minix/commands/yap/getcomm.h	(revision 9)
+++ /trunk/minix/commands/yap/getcomm.h	(revision 9)
@@ -0,0 +1,36 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/getcomm.h,v 1.1.1.1 2005/04/21 14:55:39 beng Exp $ */
+
+# ifndef _GETCOMM_
+# define PUBLIC extern
+# else
+# define PUBLIC
+# endif
+
+int	getcomm();
+/*
+ * int getcomm()
+ *
+ * Reads commands given by the user. The command is returned.
+ */
+
+VOID	shellescape();
+/*
+ * void shellescape(command)
+ * char *command;		The shell command to be executed
+ *
+ * Expands '%' and '!' in the command "command" to the current filename
+ * and the previous command respectively, and then executes "command".
+ */
+
+char *	readline();
+/*
+ * char * readline(prompt)
+ * char *prompt;		Prompt given to the user
+ *
+ * Gives a prompt "prompt" and reads a line to be typed in by the user.
+ * A pointer to this line is returned. Space for this line is static.
+ */
+
+# undef PUBLIC
Index: /trunk/minix/commands/yap/getline.c
===================================================================
--- /trunk/minix/commands/yap/getline.c	(revision 9)
+++ /trunk/minix/commands/yap/getline.c	(revision 9)
@@ -0,0 +1,722 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+# ifndef lint
+static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/getline.c,v 1.1.1.1 2005/04/21 14:55:39 beng Exp $";
+# endif
+
+# define _GETLINE_
+
+# include <errno.h>
+# include "in_all.h"
+# include "getline.h"
+# include "options.h"
+# include "process.h"
+# include "term.h"
+# include "main.h"
+# include "display.h"
+# include "output.h"
+# include "assert.h"
+
+extern int errno;
+
+# define BLOCKSIZE 2048		/* size of blocks */
+# define CHUNK 50		/* # of blockheaders allocated at a time */
+
+/*
+ * The blockheaders of the blocks that are in core are kept in a linked list.
+ * The last added block is indicated by b_head,
+ * the tail of the list is indicated by b_tail.
+ * The links go from b_tail to b_head.
+ * The blockheaders are all in an array, in the order of the line numbers.
+ * Also, the blockheaders must always be in core, so they have to be rather
+ * small. On systems with a small address space, yap can run out of core,
+ * and panic. However, this should only happen with very large files (>> 1M).
+ */
+
+struct block {
+	int		b_flags;	/* Contains the following flags: */
+# define DUMPED		01		/* block dumped on temporary file */
+# define PARTLY		02		/* block not filled completely (eof) */
+	int		b_next;		/* ptr in linked list */
+	long		b_end;		/* line number of last line in block */
+	char	 *	b_info;		/* the block */
+	int      *	b_offs;		/* line offsets within the block */
+	long		b_foff;		/* offset of block in file */
+};
+
+static struct block *	blocklist,	/* beginning of the list of blocks */
+		    *	maxblocklist,	/* first free entry in the list */
+		    *	topblocklist;	/* end of allocated core for the list */
+static int	b_head,
+		b_tail;
+static int	tfdes, ifdes;		/* File descriptors for temporary's */
+static long	lastreadline;		/* lineno of last line read */
+static int	ENDseen;
+
+STATIC VOID readblock();
+STATIC VOID nextblock();
+STATIC char *re_alloc();
+
+STATIC struct block *
+new_block()
+{
+	register struct block *pblock = maxblocklist - 1;
+
+	if (!maxblocklist || !(pblock->b_flags & PARTLY)) {
+		/*
+		 * There is no last block, or it was filled completely,
+		 * so allocate a new blockheader.
+		 */
+		register int siz;
+
+		pblock = blocklist;
+		if (maxblocklist == topblocklist) {
+			/*
+			 * No blockheaders left. Allocate new ones
+			 */
+			siz = topblocklist - pblock;
+			blocklist = pblock = (struct block *)
+			re_alloc((char *) pblock,
+			(unsigned) (siz * sizeof(*pblock)),
+			(unsigned) ((siz + CHUNK) * sizeof(*pblock)));
+			pblock += siz;
+			topblocklist = pblock + CHUNK;
+			maxblocklist = pblock;
+			for (; pblock < topblocklist; pblock++) {
+				pblock->b_end = 0;
+				pblock->b_info = 0;
+				pblock->b_flags = 0;
+			}
+			if (!siz) {
+				/*
+				 * Create dummy header cell.
+				 */
+				maxblocklist++;
+			}
+		}
+		pblock = maxblocklist++;
+	}
+	nextblock(pblock);
+	return pblock;
+}
+
+/*
+ * Return the block in which line 'n' of the current file can be found.
+ * If "disable_interrupt" = 0, the call may be interrupted, in which
+ * case it returns 0.
+ */
+
+STATIC struct block *
+getblock(n, disable_interrupt) register long n; {
+	register struct block * pblock;
+
+	if (stdf < 0) {
+		/*
+		 * Not file descriptor, so return end of file
+		 */
+		return 0;
+	}
+	pblock = maxblocklist - 1;
+	if (n < lastreadline ||
+	    (n == lastreadline && !(pblock->b_flags & PARTLY))) {
+		/*
+		 * The line asked for has been read already.
+		 * Perform binary search in the blocklist to find the block
+		 * where it's in.
+		 */
+		register struct block *min, *mid;
+
+		min = blocklist + 1;
+		do {
+			mid = min + (pblock - min) / 2;
+			if (n > mid->b_end) {
+				min = mid + 1;
+			}
+			else pblock = mid;
+		} while (min < pblock);
+		/* Found, pblock is now a reference to the block wanted */
+		if (!pblock->b_info) readblock(pblock);
+		return pblock;
+	}
+
+	/*
+	 * The line was'nt read yet, so read blocks until found
+	 */
+	for (;;) {
+		if (interrupt && !disable_interrupt) return 0;
+		pblock = new_block();
+		if (pblock->b_end >= n) {
+			return pblock;
+		}
+		if (pblock->b_flags & PARTLY) {
+			/*
+			 * We did not find it, and the last block could not be
+			 * read completely, so return 0;
+			 */
+			return	0;
+		}
+	}
+	/* NOTREACHED */
+}
+
+char *
+getline(n, disable_interrupt) long n; {
+	register struct block *pblock;
+
+	if (!(pblock = getblock(n, disable_interrupt))) {
+		return (char *) 0;
+	}
+	return pblock->b_info + pblock->b_offs[n - ((pblock-1)->b_end + 1)];
+}
+
+/*
+ * Find the last line of the input, and return its number
+ */
+
+long
+to_lastline() {
+
+	for (;;) {
+		if (!getline(lastreadline + 1, 0)) {
+			/*
+			 * "lastreadline" always contains the linenumber of
+			 * the last line read. So, if the call to getline
+			 * succeeds, "lastreadline" is affected
+			 */
+			if (interrupt) return -1L;
+			return lastreadline;
+		}
+	}
+	/* NOTREACHED */
+}
+
+#if MAXNBLOCKS
+int nblocks;		/* Count number of large blocks */
+#endif
+
+/*
+ * Allocate some memory. If unavailable, free some and try again.
+ * If all fails, panic.
+ */
+
+char *
+alloc(size, isblock) unsigned size; {
+
+	register char *pmem;
+	register struct block *pblock, *bllist;
+	char *malloc();
+	long lseek();
+	register long i;
+
+	bllist = blocklist;
+	while (
+#if MAXNBLOCKS
+	   (isblock && nblocks >= MAXNBLOCKS) ||
+#endif
+	   !(pmem = malloc(size))   /* No space */
+	) {
+		if (b_tail == 0) {
+			/*
+			 * Also, no blocks in core. Pity
+			 */
+			panic("No core");
+		}
+#if MAXNBLOCKS
+		nblocks--;
+#endif
+		pblock = bllist + b_tail;
+		b_tail = pblock->b_next;
+		if (!nopipe && !(pblock->b_flags & DUMPED)) {
+			/*
+			 * Dump the block on a temporary file
+			 */
+			if (!tfdes) {
+				/*
+				 * create and open temporary files
+				 */
+				tfdes = opentemp(0);
+				ifdes = opentemp(1);
+			}
+			pblock->b_flags |= DUMPED;
+			/*
+			 * Find out where to dump the block, and dump it
+			 */
+			i = (pblock-1)->b_end * sizeof(int);
+			(VOID) lseek(tfdes,
+				((long) BLOCKSIZE * (pblock - bllist)), 0);
+			if (write(tfdes, pblock->b_info, BLOCKSIZE)
+			    != BLOCKSIZE) {
+				panic("write failed");
+			}
+			/*
+			 * Also dump the offsets of the lines in the block
+			 */
+			(VOID) lseek(ifdes, i, 0);
+			i = pblock->b_end * sizeof(int) - i;
+			if (write(ifdes, (char *) pblock->b_offs, (int) i)
+			    != (int) i) {
+				panic("Write failed");
+			}
+		}
+		/*
+		 * Now that the block is dumped, the space taken by it can
+		 * be freed
+		 */
+		free((char *) pblock->b_offs);
+		free(pblock->b_info);
+		pblock->b_info = (char *) 0;
+	}
+#if MAXNBLOCKS
+	if (isblock) nblocks++;
+#endif
+	return pmem;
+}
+
+/*
+ * Re-allocate the memorychunk pointed to by ptr, to let it
+ * grow or shrink.
+ * realloc of the standard C library is useless, as it is destructive
+ * if the malloc fails.
+ */
+
+STATIC char *
+re_alloc(ptr,oldsize, newsize)
+char *ptr; unsigned oldsize; unsigned newsize; {
+	register char *pmem;
+	register char *c1, *c2;
+
+	/*
+	 * We could be smarter here, by checking if newsize < oldsize, and in
+	 * that case using realloc, but this depends on realloc using the
+	 * same block if the block shrinks. The question is, wether all
+	 * reallocs in the world do this.
+	 */
+	pmem = alloc(newsize, 0);
+	if (oldsize) {
+		/*
+		 * This test makes re_alloc also work if there was no old block
+		 */
+		c1 = pmem;
+		c2 = ptr;
+		if (newsize > oldsize) {
+			newsize = oldsize;
+		}
+		while (newsize--) {
+			*c1++ = *c2++;
+		}
+		free(ptr);
+	}
+	return pmem;
+}
+
+/*
+ * Append a block to the linked list of blockheaders of blocks that are
+ * in core.
+ */
+
+STATIC VOID
+addtolist(pblock) register struct block *pblock; {
+	register struct block *bllist = blocklist;
+
+	pblock->b_next = 0;
+	(bllist + b_head)->b_next = pblock - bllist;
+	b_head = pblock - bllist;
+	if (!b_tail) {
+		/*
+		 * The list was empty, initialize
+		 */
+		b_tail = b_head;
+	}
+}
+
+static char *saved;
+static long filldegree;
+
+/*
+ * Try to read the block indicated by pblock
+ */
+
+STATIC VOID
+nextblock(pblock) register struct block *pblock; {
+	register char *c,	/* Run through pblock->b_info */
+		      *c1;	/* indicate end of pblock->b_info */
+	register int *poff;	/* pointer in line-offset list */
+	register int cnt;	/* # of characters read */
+	register unsigned siz;	/* Size of allocated line-offset list */
+	static unsigned savedsiz;	/* saved "siz" */
+	static int *savedpoff;		/* saved "poff" */
+	static char *savedc1;		/* saved "c1" */
+
+	if (pblock->b_flags & PARTLY) {
+		/*
+		 * The block was already partly filled. Initialize locals
+		 * accordingly
+		 */
+		poff = savedpoff;
+		siz = savedsiz;
+		pblock->b_flags = 0;
+		c1 = savedc1;
+		if (c1 == pblock->b_info || *(c1 - 1)) {
+			/*
+			 * We had incremented "lastreadline" temporarily,
+			 * because the last line could not be completely read
+			 * last time we tried. Undo this increment
+			 */
+			poff--;
+			--lastreadline;
+		}
+	}
+	else {
+		if (nopipe) pblock->b_foff = lseek(stdf, 0L, 1);
+		if (saved) {
+			/*
+			 * There were leftovers from the previous block
+			 */
+			pblock->b_info = saved;
+			if (nopipe) pblock->b_foff -= savedc1 - saved;
+			c1 = savedc1;
+			saved = 0;
+		}
+		else {	/* Allocate new block */
+			pblock->b_info = c1 = alloc(BLOCKSIZE + 1, 1);
+		}
+		/*
+		 * Allocate some space for line-offsets
+		 */
+		pblock->b_offs = poff = (int *)
+			alloc((unsigned) (100 * sizeof(int)), 0);
+		siz = 99;
+		*poff++ = 0;
+	}
+	c = c1;
+	for (;;) {
+		/*
+		 * Read loop
+		 */
+		cnt = read(stdf, c1, BLOCKSIZE - (c1 - pblock->b_info));
+		if (cnt < 0) {
+			/*
+			 * Interrupted read
+			 */
+			if (errno == EINTR) continue;
+			error("Could not read input file");
+			cnt = 0;
+		}
+		c1 += cnt;
+		if (c1 != pblock->b_info + BLOCKSIZE) {
+			ENDseen = 1;
+			pblock->b_flags |= PARTLY;
+		}
+		break;
+	}
+	assert(c <= c1);
+	while (c < c1) {
+		/*
+		 * Now process the block
+		 */
+		*c &= 0177;	/* Most significant bit ignored */
+		if (*c == '\n') {
+			/*
+			 * Newlines are replaced by '\0', so that "getline"
+			 * can deliver one line at a time
+			 */
+			*c = 0;
+			lastreadline++;
+			/*
+			 * Remember the line-offset
+			 */
+			if (poff == pblock->b_offs + siz) {
+				/*
+				 * No space for it, allocate some more
+				 */
+				pblock->b_offs = (int *)
+					re_alloc((char *) pblock->b_offs,
+						 (siz+1) * sizeof(int),
+						 (siz + 51) * sizeof(int));
+				poff = pblock->b_offs + siz;
+				siz += 50;
+			}
+			*poff++ = c - pblock->b_info + 1;
+		}
+		else if (*c == '\0') {
+			/*
+			 * 0-bytes are replaced by 0200, because newlines are
+			 * replaced by 0, and 0200 & 0177 gives again 0 ...
+			 */
+			*c = 0200;
+		}
+		c++;
+	}
+	assert(c==c1);
+	*c = 0;
+	if (c != pblock->b_info && *(c-1) != 0) {
+		/*
+		 * The last line read does not end with a newline, so add one
+		 */
+		lastreadline++;
+		*poff++ = c - pblock->b_info + 1;
+		if (!(pblock->b_flags & PARTLY) && *(poff - 2) != 0) {
+			/*
+			 * Save the started line; it will be in the next block.
+			 * Remove the newline we added just now.
+			 */
+			saved = c1 = alloc(BLOCKSIZE + 1, 1);
+			c = pblock->b_info + *(--poff - 1);
+			while (*c) *c1++ = *c++;
+			c = pblock->b_info + *(poff - 1);
+			savedc1 = c1;
+			--lastreadline;
+		}
+	}
+	pblock->b_end = lastreadline;
+	if (pblock->b_flags & PARTLY) {
+		/*
+		 * Take care, that we can call "nextblock" again, to fill in
+		 * the rest of this block
+		 */
+		savedsiz = siz;
+		savedpoff = poff;
+		savedc1 = c;
+		if (c == pblock->b_info) {
+			lastreadline++;
+			pblock->b_end = 0;
+		}
+	}
+	else {
+		/*
+		 * Not completely read blocks are not in the linked list,
+		 * so can never be "swapped out".
+		 */
+		addtolist(pblock);
+		cnt = pblock - blocklist;
+		filldegree = ((c-pblock->b_info) + (cnt-1) * filldegree) / cnt;
+	}
+	assert(pblock->b_end - (pblock-1)->b_end <= poff - pblock->b_offs);
+}
+
+/*
+ * Allocate core for the block, and read it back from
+ * the temporary file.
+ */
+
+STATIC VOID
+readblock(pblock) register struct block *pblock; {
+
+	register int size;
+	register long i;
+
+	/*
+	 * Find out where the block is, and read it
+	 */
+	pblock->b_info = alloc(BLOCKSIZE + 1, 1);
+	i = (pblock - 1)->b_end * sizeof(int);
+	size = (int) (pblock->b_end * sizeof(int) - i);
+	pblock->b_offs	= (int *) alloc((unsigned) size, 0);
+	if (nopipe) {
+		register char *c;
+		register int line_index;
+		int cnt;
+		long l = lseek(stdf, 0L, 1);
+
+		(VOID) lseek(stdf, pblock->b_foff, 0);
+		cnt = read(stdf, pblock->b_info, BLOCKSIZE);
+		(VOID) lseek(stdf, l, 0);
+		c = pblock->b_info;
+		pblock->b_offs[0] = 0;
+		line_index = 1;
+		size /= sizeof(int);
+		while (c < pblock->b_info + cnt) {
+			*c &= 0177;
+			if (*c == '\n') {
+				*c = '\0';
+				if (line_index < size)
+					pblock->b_offs[line_index++] =
+						(c - pblock->b_info) + 1;
+			}
+			else if (*c == '\0') *c = 0200;
+			c++;
+		}
+		*c = '\0';
+	}
+	else {
+		(VOID) lseek(tfdes, (long) ((long) BLOCKSIZE * (pblock - blocklist)),0);
+		if (read(tfdes, pblock->b_info,BLOCKSIZE) != BLOCKSIZE) {
+			panic("read error");
+		}
+		/*
+		 * Find out where the line-offset list is, and read it
+		 */
+		(VOID) lseek(ifdes, i, 0);
+		if (read(ifdes, (char *) pblock->b_offs, size) != size) {
+			panic("read error");
+		}
+		pblock->b_info[BLOCKSIZE] = '\0';
+	}
+	/*
+	 * Add this block to the list of incore blocks
+	 */
+	addtolist(pblock);
+}
+
+/*
+ * Called after processing a file.
+ * Free all core.
+ */
+
+VOID
+do_clean() {
+
+	register struct block *pblock;
+	register char *p;
+
+	for (pblock = blocklist; pblock < maxblocklist; pblock++) {
+		if (p = pblock->b_info) {
+			free(p);
+			free((char *) pblock->b_offs);
+		}
+	}
+	if (p = (char *) blocklist) {
+		free(p);
+	}
+	blocklist = 0;
+	maxblocklist = 0;
+	topblocklist = 0;
+	lastreadline = 0;
+	filldegree = 0;
+	ENDseen = 0;
+	if (p = saved) free(p);
+	saved = 0;
+	b_head = 0;
+	b_tail = 0;
+# if MAXNBLOCKS
+	nblocks = 0;
+# endif
+}
+
+/*
+ * Close a file with file-descriptor "file", if it indeed is one
+ */
+
+STATIC VOID
+cls(file) {
+	if (file) (VOID) close(file);
+}
+
+/*
+ * Close all files
+ */
+
+VOID
+cls_files() {
+
+	cls(tfdes);
+	cls(ifdes);
+	cls(stdf);
+}
+
+/*
+ * Get a character. If possible, do some workahead.
+ */
+
+int
+getch() {
+# if USG_OPEN
+# include <fcntl.h>
+# include <sys/stat.h>
+
+	register int i,j;
+	struct stat buf;
+# else
+# ifdef FIONREAD
+# include <sys/stat.h>
+
+	struct stat buf;
+	long i;
+# endif
+# endif
+
+	char c;
+	int retval;
+
+	flush();
+	if (startcomm) {
+		/*
+		 * Command line option command
+		 */
+		if (*startcomm) return *startcomm++;
+		return '\n';
+	}
+# if USG_OPEN
+	if (stdf >= 0) {
+		/*
+		 * Make reads from the terminal non-blocking, so that
+		 * we can see if the user typed something
+		 */
+		i = fcntl(0,F_GETFL,0);
+		if (i != -1 && fcntl(0, F_SETFL, i|O_NDELAY) != -1) {
+			j = 0;
+			while (! ENDseen && 
+			       ((j = read(0,&c,1)) == 0
+#ifdef EWOULDBLOCK
+			        || (j < 0 && errno == EWOULDBLOCK)
+#endif
+			       )
+			       &&
+			       (nopipe || 
+				(fstat(stdf,&buf) >= 0 && buf.st_size > 0))) {
+				/*
+				 * Do some read ahead, after making sure there
+				 * is input and the user did not type a command
+				 */
+				new_block();
+			}
+			(VOID) fcntl(0,F_SETFL,i);
+			if (j < 0) {
+				/*
+				 * Could this have happened?
+				 * I'm not sure, because the read is
+				 * nonblocking. Can it be interrupted then?
+				 */
+				return -1;
+			}
+			if (j > 0) return c;
+		}
+	}
+# else
+# ifdef FIONREAD
+	if (stdf >= 0) {
+		/*
+		 * See if there are any characters waiting in the terminal input
+		 * queue. If there are not, read ahead.
+		 */
+		while (! ENDseen &&
+		       ( ioctl(0, FIONREAD, (char *) &i) >= 0 && i == 0) &&
+		       ( nopipe || fstat(stdf,&buf) >= 0 && buf.st_size > 0)) {
+			/*
+			 * While the user does'nt type anything, and there is
+			 * input to be processed, work ahead
+			 */
+			if (interrupt) return -1;
+			new_block();
+		}
+	}
+# endif
+# endif
+	if (read(0,&c,1) <= 0) retval = -1; else retval = c & 0177;
+	return retval;
+}
+
+/*
+ * Get the position of line "ln" in the file.
+ */
+
+long
+getpos(ln) long ln; {
+	register struct block *pblock;
+	register long i;
+
+	pblock = getblock(ln,1);
+	assert(pblock != 0);
+	i = filldegree * (pblock - blocklist);
+	return i - (filldegree - pblock->b_offs[ln - (pblock-1)->b_end]);
+}
Index: /trunk/minix/commands/yap/getline.h
===================================================================
--- /trunk/minix/commands/yap/getline.h	(revision 9)
+++ /trunk/minix/commands/yap/getline.h	(revision 9)
@@ -0,0 +1,71 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/getline.h,v 1.1.1.1 2005/04/21 14:55:39 beng Exp $ */
+
+# ifndef _GETLINE_
+# define PUBLIC extern
+# else
+# define PUBLIC
+# endif
+
+char *	getline();
+/*
+ * char * getline(ln,disable_interrupt)
+ * long ln;			The line number of the line to be returned
+ * int disable_interrupt;	1 if interrupts must be ignored, 0 otherwise
+ *
+ * Returns a pointer to the line with linenumber "ln".
+ * It returns 0 if
+ * - there was an interrupt, and interrupts were not disabled, or
+ * - there is no line with linenumber "ln".
+ */
+
+char *	alloc();
+/*
+ * char * alloc(size, isblock)
+ * unsigned size;		The size in bytes
+ * int isblock;			Flag indicating whether this is a file-text
+ *				block
+ *
+ * Return a pointer to a block of "size" bytes.
+ * Panics if no core can be found.
+ */
+
+VOID	do_clean();
+/*
+ * void do_clean()
+ *
+ * Cleans up and initializes.
+ */
+
+VOID	cls_files();
+/*
+ * void cls_files()
+ *
+ * Closes files. Useful for shell escapes.
+ */
+
+int	getch();
+/*
+ * int getch()
+ *
+ * Get a character from input or command option line (only at start up).
+ * Some systems allow us to do some workahead while the user is
+ * thinking/reading. Use this to get parts of the input file in core.
+ */
+
+long	to_lastline();
+/*
+ * long to_lastline()
+ *
+ * Finds the last line of the file, and returns its number.
+ * This command can be interrupted, in which case it returns 0.
+ */
+
+long	getpos();
+/*
+ * long getpos(line);
+ *
+ * get offset of line "line" in the input
+ */
+# undef PUBLIC
Index: /trunk/minix/commands/yap/help.c
===================================================================
--- /trunk/minix/commands/yap/help.c	(revision 9)
+++ /trunk/minix/commands/yap/help.c	(revision 9)
@@ -0,0 +1,107 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+#ifndef lint
+static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/help.c,v 1.1.1.1 2005/04/21 14:55:39 beng Exp $";
+#endif
+
+#define _HELP_
+#include "in_all.h"
+#include "help.h"
+#include "machine.h"
+#include "commands.h"
+#include "keys.h"
+#include "output.h"
+#include "prompt.h"
+#include "main.h"
+#include "display.h"
+#include "term.h"
+#include "options.h"
+
+static int h_cnt;		/* Count # of lines */
+static struct state *origin;	/* Keep track of startstate */
+
+/*
+ * Print a key sequence.
+ * We arrived at an endstate. The s_next link in the state structure now
+ * leads us from "origin" to the current state, so that we can print the key
+ * sequence easily.
+ */
+
+STATIC VOID
+pr_comm() {
+	register struct state *p = origin;
+	register char *pb;
+	register int c;
+	char buf[30];
+	register int i = 0;	/* How many characters printed? */
+
+	pb = buf;
+	for (;;) {
+		c = p->s_char & 0177;
+		if (c < ' ' || c == 0177) {
+			/*
+			 * Will take an extra position
+			 */
+			i++;
+		}
+		*pb++ = c;
+		i++;
+		if (!p->s_match) break;
+		p = p->s_next;
+	}
+	do {
+		*pb++ = ' ';
+	} while (++i < 12);
+	*pb = 0;
+	cputline(buf);
+}
+
+/*
+ * Print out a description of the keymap. This is done, by temporarily using
+ * the s_next field in the state structure indicate the state matching the
+ * next character, so that we can walk from "origin" to an endstate.
+ */
+
+STATIC VOID
+pr_mach(currstate, back) register struct state *currstate, *back; {
+	struct state *save;
+
+	while (currstate) {
+		if (interrupt) break;
+		if (back) {
+			save = back->s_next;	/* Save original link */
+			back->s_next = currstate;
+		}
+		if (!currstate->s_match) {
+			/*
+			 * End state, print command
+			 */
+			pr_comm();
+			putline(commands[currstate->s_cnt].c_descr);
+			putline("\r\n");
+			if (++h_cnt >= maxpagesize) {
+				ret_to_continue();
+				h_cnt = 0;
+			}
+		}
+		else pr_mach(currstate->s_match, currstate);
+		currstate = currstate->s_next;
+		if (back) back->s_next = save;	/* restore */
+		else origin = currstate;
+	}
+}
+
+/*ARGSUSED*/
+int
+do_help(i) long i; {	/* The help command */
+
+	startcomm = 0;
+	h_cnt = 2;
+	putline("\r\nSummary of yap commands:\r\n");
+	origin = currmap->k_mach;
+	pr_mach(currmap->k_mach, (struct state *) 0);
+	if (h_cnt) {
+		ret_to_continue();
+	}
+	if (!hardcopy && scr_info.currentpos) redraw(1);
+}
Index: /trunk/minix/commands/yap/help.h
===================================================================
--- /trunk/minix/commands/yap/help.h	(revision 9)
+++ /trunk/minix/commands/yap/help.h	(revision 9)
@@ -0,0 +1,20 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/help.h,v 1.1.1.1 2005/04/21 14:55:39 beng Exp $ */
+
+# ifndef _HELP_
+# define PUBLIC extern
+# else
+# define PUBLIC
+# endif
+
+int	do_help();
+/*
+ * int do_help(cnt);
+ * long cnt;			This is ignored, but a count is given
+ *				to any command
+ *
+ * Give a summary of commands
+ */
+
+# undef PUBLIC
Index: /trunk/minix/commands/yap/in_all.h
===================================================================
--- /trunk/minix/commands/yap/in_all.h	(revision 9)
+++ /trunk/minix/commands/yap/in_all.h	(revision 9)
@@ -0,0 +1,89 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/in_all.h,v 1.1.1.1 2005/04/21 14:55:40 beng Exp $ */
+
+#define DO_ASSERT 0	/* define when debugging */
+# ifdef DO_ASSERT
+# define STATIC
+# else
+# define STATIC static
+# endif
+
+#define VOID void	/* preferably void, but int if your compiler does
+			   not recognize void
+			*/
+
+#if _POSIX_SOURCE
+#define POSIX_OPEN 1	/* POSIX "open" system call */
+#else
+#define USG_OPEN 0	/* USG "open" system call (include <fcntl.h>) */
+#define BSD4_2_OPEN 0 /* BSD 4.2 "open" system call (include <sys/file.h>)*/
+#endif
+
+/* Sanity check 1 */
+# if (!!USG_OPEN) + (!!BSD4_2_OPEN) + (!!POSIX_OPEN) > 1
+Oops, now why did you do that?
+O, never mind, just try it again with
+USG_OPEN = 1 or		for System III, System V etc.
+BSD4_2_OPEN = 1 or	for Berkeley 4.2, Ultrix etc.
+POSIX_OPEN = 1 or	for POSIX compliant systems.
+USG_OPEN = 0 and BSD4_2_OPEN = 0 and POSIX_OOPEN
+	for Berkeley 4.1, v7 and whatever else
+# endif
+
+#define BSD_REGEX 0	/* Berkeley style re_comp/re_exec */
+#define V8_REGEX  1	/* V8 style regexec/regcomp */
+#define USG_REGEX 0	/* USG style regex/regcmp */
+
+/* Sanity check 2 */
+# if USG_REGEX + BSD_REGEX + V8_REGEX > 1
+Select one style for the regular expressions please!
+# endif
+
+#define USG_TTY 0	/* define if you have an USG tty driver (termio) */
+			/* If you do not define this, you get either the
+			 * V7 tty driver or the BSD one.
+			 */
+#if _POSIX_SOURCE
+#define POSIX_TTY 1
+#endif
+
+#if __minix && !__minix_vmd
+#define MAXNBLOCKS 10	/* Limit the number of blocks that yap will use to keep
+			 * the input in core.
+			 * This was needed to let yap run on an IBM XT
+			 * running PC/IX. The problem is that malloc can
+			 * allocate almost all available space, leaving no
+			 * space for the stack, which causes a memory fault.
+			 * Internal yap blocks are 2K, but there is a lot of
+			 * additional information that yap keeps around. You
+			 * can also use it if you want to limit yap's maximum
+			 * size. If defined, it should be at least 3.
+			 * 10 is probably a reasonable number.
+			 */
+#endif
+/* Sanity check 3 */
+# ifdef MAXNBLOCKS
+# if MAXNBLOCKS < 3
+Read the above comment!
+# endif
+# endif
+
+#define VT100_PATCH	/* This involves a patch that will insert lines
+			 * correctly on a VT100 terminal. The termcap entry
+			 * for it contains an "al" with %-escapes. According
+			 * to the termcap-documentation this is not allowed,
+			 * but ...
+			 * If VT100_PATCH is defined, the "al" capability will
+			 * be offered to "tgoto", before "tputs"-ing it.
+			 * I don't know if there are any terminals out there
+			 * that have a % in their "al" capability. If there
+			 * are, yap will not work properly when compiled with
+			 * VT100_PATCH defined.
+			 * Also, escape sequences for standout and underline
+			 * will be tputs-ed if VT100_PATCH is defined.
+			 */
+
+#if _MINIX
+#define	LCASE	0	/* Minix doesn;t have LCASE */
+#endif
Index: /trunk/minix/commands/yap/keys.c
===================================================================
--- /trunk/minix/commands/yap/keys.c	(revision 9)
+++ /trunk/minix/commands/yap/keys.c	(revision 9)
@@ -0,0 +1,188 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+# ifndef lint
+static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/keys.c,v 1.1.1.1 2005/04/21 14:55:40 beng Exp $";
+# endif
+
+# define _KEYS_
+
+# include <ctype.h>
+# include "in_all.h"
+# include "machine.h"
+# include "keys.h"
+# include "commands.h"
+# include "prompt.h"
+# include "assert.h"
+
+char defaultmap[] = "\
+bf=P:bl=k:bl=^K:bl=^[[A:bot=l:bot=$:bot=^[[Y:bp=-:bp=^[[V:bs=^B:bse=?:bsl=S:\
+bsp=F:chm=X:exg=x:ff=N:fl=^J:fl=^M:fl=j:fl=^[[B:fp= :fp=^[[U:fs=^D:fse=/:\
+fsl=s:fsp=f:hlp=h:nse=n:nsr=r:red=^L:rep=.:bps=Z:bss=b:fps=z:fss=d:shl=!:\
+tom=':top=\\^:top=^[[H:vis=e:wrf=w:qui=q:qui=Q:mar=m:pip=|";
+
+char *strcpy();
+char *strcat();
+char *getenv();
+
+/*
+ * Construct an error message and return it
+ */
+
+STATIC char *
+kerror(key, emess) char *key, *emess; {
+	static char ebuf[80];	/* Room for the error message */
+
+	(VOID) strcpy(ebuf, key);
+	(VOID) strcat(ebuf, emess);
+	return ebuf;
+}
+
+/*
+ * Compile a keymap into commtable. Returns an error message if there
+ * is one
+ */
+
+STATIC char *
+compile(map, commtable)
+  register char *map; register struct keymap *commtable; {
+	register char *mark;	/* Indicates start of mnemonic */
+	register char *c;	/* Runs through buf */
+	register int temp;
+	char *escapes = commtable->k_esc;
+	char buf[10];		/* Will hold key sequence */
+
+	(VOID) strcpy(commtable->k_help,"Illegal command");
+	while (*map) {
+		c = buf;
+		mark = map;	/* Start of mnemonic */
+		while (*map && *map != '=') {
+			map++;
+		}
+		if (!*map) {
+			/*
+			 * Mnemonic should end with '='
+			 */
+			return kerror(mark, ": Syntax error");
+		}
+		*map++ = 0;
+		while (*map) {
+			/*
+			 * Get key sequence
+			 */
+			if (*map == ':') {
+				/*
+				 * end of key sequence
+				 */
+				map++;
+				break;
+			}
+			*c = *map++ & 0177;
+			if (*c == '^' || *c == '\\') {
+				if (!(temp = *map++)) {
+					/*
+					 * Escape not followed by a character
+					 */
+					return kerror(mark, ": Syntax error");
+				}
+				if (*c == '^') {
+					if (temp == '?') *c = 0177;
+					else *c = temp & 037;
+				}
+				else *c = temp & 0177;
+			}
+			setused(*c);
+			c++;
+			if (c >= &buf[9]) {
+				return kerror(mark,": Key sequence too long");
+			}
+		}
+		*c = 0;
+		if (!(temp = lookup(mark))) {
+			return kerror(mark,": Nonexistent function");
+		}
+		if (c == &buf[1] && (commands[temp].c_flags & ESC) &&
+		    escapes < &(commtable->k_esc[sizeof(commtable->k_esc)-1])) {
+			*escapes++ = buf[0] & 0177;
+		}
+		temp = addstring(buf, temp, &(commtable->k_mach));
+		if (temp == FSM_ISPREFIX) {
+			return kerror(mark,": Prefix of other key sequence");
+		}
+		if (temp == FSM_HASPREFIX) {
+			return kerror(mark,": Other key sequence is prefix");
+		}
+		assert(temp == FSM_OKE);
+		if (!strcmp(mark, "hlp")) {
+			/*
+			 * Create an error message to be given when the user
+			 * types an illegal command
+			 */
+			(VOID) strcpy(commtable->k_help, "Type ");
+			(VOID) strcat(commtable->k_help, buf);
+			(VOID) strcat(commtable->k_help, " for help");
+		}
+	}
+	*escapes = 0;
+	return (char *) 0;
+}
+
+/*
+ * Initialize the keymaps
+ */
+
+VOID
+initkeys() {
+	register char *p;
+	static struct keymap xx[2];
+
+	currmap = &xx[0];
+	othermap = &xx[1];
+	p = compile(defaultmap, currmap);	/* Compile default map */
+	assert(p == (char *) 0);
+	p = getenv("YAPKEYS");
+	if (p) {
+		if (!(p = compile(p, othermap))) {
+			/*
+			 * No errors in user defined keymap. So, use it
+			 */
+			do_chkm(0L);
+			return;
+		}
+		error(p);
+	}
+	othermap = 0;		       /* No other keymap */
+}
+
+int
+is_escape(c)
+{
+	register char *p = currmap->k_esc;
+
+	while (*p) {
+		if (c == *p++) return 1;
+	}
+	return 0;
+}
+
+static char keyset[16];		/* bitset indicating which keys are
+				 * used
+				 */
+/*
+ * Mark key "key" as used
+ */
+
+VOID
+setused(key) int key; {
+
+	keyset[(key & 0177) >> 3] |= (1 << (key & 07));
+}
+
+/*
+ * return non-zero if key "key" is used in a keymap
+ */
+
+int
+isused(key) int key; {
+
+	return keyset[(key & 0177) >> 3] & (1 << (key & 07));
+}
Index: /trunk/minix/commands/yap/keys.h
===================================================================
--- /trunk/minix/commands/yap/keys.h	(revision 9)
+++ /trunk/minix/commands/yap/keys.h	(revision 9)
@@ -0,0 +1,50 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/keys.h,v 1.1.1.1 2005/04/21 14:55:40 beng Exp $ */
+
+# ifndef _KEYS_
+# define PUBLIC extern
+# else
+# define PUBLIC
+# endif
+
+PUBLIC struct keymap {
+    char k_help[80];		/* To be printed on illegal command */
+    struct state *k_mach;	/* Finite state machine */
+    char k_esc[10];		/* escape chars */
+} *currmap,			/* pointer to current key map */
+  *othermap;			/* pointer to other keymap */
+
+VOID initkeys();
+/*
+ * void initkeys();
+ *
+ * Initializes the keymap(s).
+ */
+
+VOID setused();
+/*
+ * void setused(key);
+ * int key;
+ *
+ * Marks the key "key" as used.
+ */
+
+int isused();
+/*
+ * int isused(key);
+ * int key;
+ *
+ * returns 0 if the key "key" is not used.
+ * Otherwise it returns non-zero.
+ */
+
+int is_escape();
+/*
+ * int is_escape(c);
+ * int c;
+ *
+ * Returns 1 if "c" is an escape char (shell or pipe) in the current
+ * keymap.
+ */
+# undef PUBLIC
Index: /trunk/minix/commands/yap/machine.c
===================================================================
--- /trunk/minix/commands/yap/machine.c	(revision 9)
+++ /trunk/minix/commands/yap/machine.c	(revision 9)
@@ -0,0 +1,137 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+# ifndef lint
+static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/machine.c,v 1.1.1.1 2005/04/21 14:55:40 beng Exp $";
+# endif
+
+# define _MACHINE_
+
+# include <ctype.h>
+# include "in_all.h"
+# include "machine.h"
+# include "getline.h"
+# include "assert.h"
+
+/*
+ * Add part of finite state machine to recognize the string s.
+ */
+
+STATIC int
+addtomach(s, cnt, list) char *s; struct state **list; {
+
+	register struct state *l;
+	register int i = FSM_OKE;	/* Return value */
+	register int j;
+
+	for (;;) {
+		l = *list;
+		if (!l) {
+			/*
+			 * Create new list element
+			 */
+			*list = l = (struct state *) alloc(sizeof(*l), 0);
+			l->s_char = *s;
+			l->s_endstate = 0;
+			l->s_match = 0;
+			l->s_next = 0;
+		}
+		if (l->s_char == *s) {
+			/*
+			 * Continue with next character
+			 */
+			if (!*++s) {
+				/*
+				 * No next character
+				 */
+				j = l->s_endstate;
+				l->s_endstate = 1;
+				if (l->s_match || j) {
+					/*
+					 * If the state already was an endstate,
+					 * or has a successor, the currently
+					 * added string is a prefix of an
+					 * already recognized string
+					 */
+					return FSM_ISPREFIX;
+				}
+				l->s_cnt = cnt;
+				return i;
+			}
+			if (l->s_endstate) {
+				/*
+				 * In this case, the currently added string has
+				 * a prefix that is an already recognized
+				 * string.
+				 */
+				i = FSM_HASPREFIX;
+			}
+			list = &(l->s_match);
+			continue;
+		}
+		list = &(l->s_next);
+	}
+	/* NOTREACHED */
+}
+
+/*
+ * Add a string to the FSM.
+ */
+
+int
+addstring(s,cnt,machine) register char *s; struct state **machine; {
+
+	if (!s || !*s) {
+		return FSM_ISPREFIX;
+	}
+	return addtomach(s,cnt,machine);
+}
+
+/*
+ * Match string s with the finite state machine.
+ * If it matches, the number of characters actually matched is returned,
+ * and the count is put in the word pointed to by i.
+ * If the string is a prefix of a string that could be matched,
+ * FSM_ISPREFIX is returned. Otherwise, 0 is returned.
+ */
+
+int
+match(s,i,mach) char *s; int *i; register struct state *mach; {
+
+	register char *s1 = s;	/* Walk through string */
+	register struct state *mach1 = 0;
+				/* Keep track of previous state */
+
+	while (mach && *s1) {
+		if (mach->s_char == *s1) {
+			/*
+			 * Current character matches. Carry on with next
+			 * character and next state
+			 */
+			mach1 = mach;
+			mach = mach->s_match;
+			s1++;
+			continue;
+		}
+		mach = mach->s_next;
+	}
+	if (!mach1) {
+		/*
+		 * No characters matched
+		 */
+		return 0;
+	}
+	if (mach1->s_endstate) {
+		/*
+		 * The string matched
+		 */
+		*i = mach1->s_cnt;
+		return s1 - s;
+	}
+	if (!*s1) {
+		/*
+		 * The string matched a prefix
+		 */
+		return FSM_ISPREFIX;
+	}
+	return 0;
+}
Index: /trunk/minix/commands/yap/machine.h
===================================================================
--- /trunk/minix/commands/yap/machine.h	(revision 9)
+++ /trunk/minix/commands/yap/machine.h	(revision 9)
@@ -0,0 +1,60 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/machine.h,v 1.1.1.1 2005/04/21 14:55:40 beng Exp $ */
+
+# ifndef _MACHINE_
+# define PUBLIC extern
+# else
+# define PUBLIC
+# endif
+
+/*
+ * Simple minded finite state machine implementation to recognize
+ * strings.
+ */
+
+struct state {
+    char s_char;		/* character to match with */
+    char s_endstate;		/* flag, 1 if this state is an endstate */
+    struct state *s_match;	/* new state if matched */
+    struct state *s_next;	/* other characters to match with */
+    short s_cnt;		/* if an endstate, this field is filled with
+				 * some info, dependant on the machine.
+				 */
+};
+
+# define FSM_OKE	0
+# define FSM_ISPREFIX	-1	/* Must be < 0 */
+# define FSM_HASPREFIX	1
+
+int	addstring();
+/*
+ * int addstring(str,cnt,mach)
+ * char *str;			The string to be recognized
+ * int cnt;			Attribute of the string.
+ * struct state **mach;		The finite state machine
+ *
+ * This routine adds a string to a finite state automaton.
+ * It returns FSM_ISPREFIX if the added string is a prefix of a string already
+ * in the automaton, FSM_HASPREFIX if a string, already recognized by the
+ * automaton, is a prefix of the added string.
+ * Otherwise it returns FSM_OKE.
+ */
+
+int	match();
+/*
+ * int match(str,p_int,mach)
+ * char *str;			pointer to string
+ * int *p_int;			Pointer to an integer
+ * struct state *mach;		The finite state machine
+ *
+ * A match of the string indicated by "str" is tried. If a head of "str"
+ * is recognized by the finite state automaton, a machine dependant number
+ * is put in the integer pointed to by "p_int".
+ * The number of characters that match is returned, so a return value of 0
+ * means no match.
+ * A return value of FSM_PREFIX means that the string "str" was a prefix of a
+ * matched string.
+ */
+
+# undef PUBLIC
Index: /trunk/minix/commands/yap/main.c
===================================================================
--- /trunk/minix/commands/yap/main.c	(revision 9)
+++ /trunk/minix/commands/yap/main.c	(revision 9)
@@ -0,0 +1,220 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+# ifndef lint
+static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/main.c,v 1.1.1.1 2005/04/21 14:55:40 beng Exp $";
+# endif
+
+# define _MAIN_
+
+# include "in_all.h"
+# if USG_OPEN
+# include <fcntl.h>
+# endif
+# if BSD4_2_OPEN
+# include <sys/file.h>
+# endif
+# if POSIX_OPEN
+# include <sys/types.h>
+# include <fcntl.h>
+# endif
+# include "main.h"
+# include "term.h"
+# include "options.h"
+# include "output.h"
+# include "process.h"
+# include "commands.h"
+# include "display.h"
+# include "prompt.h"
+
+char	*strcpy();
+
+STATIC int initialize();
+# ifdef SIGTSTP
+STATIC int suspsig();
+# endif
+
+int
+main(argc,argv) register char ** argv; {
+
+	register char ** av;
+
+	if (! isatty(1)) {
+		no_tty = 1;
+	}
+	argv[argc] = 0;
+	progname = argv[0];
+	if ((av = readoptions(argv)) == (char **) 0 ||
+		initialize(*av ? 1 : 0)) {
+		if (no_tty) {
+			close(1);
+			(VOID) dup(2);
+		}
+		putline("Usage: ");
+		putline(argv[0]);
+		putline(
+" [-c] [-u] [-n] [-q] [-number] [+command] [file ... ]\n");
+		flush();
+		exit(1);
+	}
+	if (no_tty) {
+		*--av = "cat";
+		execve("/bin/cat", av, (char *) 0);
+	}
+	else	processfiles(argc-(av-argv), av);
+	(VOID) quit();
+	/* NOTREACHED */
+}
+
+char *mktemp();
+
+/*
+ * Open temporary file for reading and writing.
+ * Panic if it fails
+ */
+
+static char indexfile[30], tempfile[30];
+
+int
+opentemp(i) {
+
+	register fildes;
+	register char *f;
+
+	f = i ? mktemp(indexfile) : mktemp(tempfile);
+# if BSD4_2_OPEN || USG_OPEN || POSIX_OPEN
+	if ((fildes = open(f,O_RDWR|O_TRUNC|O_CREAT,0600)) < 0) {
+# else
+	if ((fildes = creat(f,0600)) <= 0 || close(fildes) < 0 ||
+	    (fildes = open(f,2)) < 0) {
+# endif
+		panic("Couldn't open temporary file");
+	}
+	(VOID) unlink(f);
+	return fildes;
+}
+
+/*
+ * Collect initializing stuff here.
+ */
+
+STATIC int
+initialize(x) {
+
+	if (!(nopipe = x)) {
+		/*
+		 * Reading from pipe
+		 */
+		if (isatty(0)) {
+			return 1;
+		}
+		stdf = dup(0);	/* Duplicate file descriptor of input */
+		if (no_tty) return 0;
+		/*
+		 * Make sure standard input is from the terminal.
+		 */
+		(VOID) close(0);
+# if BSD4_2_OPEN || USG_OPEN || POSIX_OPEN
+		if (open("/dev/tty",O_RDONLY,0) != 0) {
+# else
+		if (open("/dev/tty",0) != 0) {
+# endif
+			putline("Couldn't open terminal\n");
+			flush();
+			exit(1);
+		}
+	}
+	if (no_tty) return 0;
+	(VOID) strcpy(tempfile,"/usr/tmp/yap_XXXXXX");
+	(VOID) strcpy(indexfile,"/usr/tmp/yap-XXXXXX");
+	/*
+	 * Handle signals.
+	 * Catch QUIT, DELETE and ^Z
+	 */
+	(VOID) signal(SIGQUIT,SIG_IGN);
+	(VOID) signal(SIGINT, catchdel);
+	ini_terminal();
+# ifdef SIGTSTP
+	if (signal(SIGTSTP,SIG_IGN) == SIG_DFL) {
+		(VOID) signal(SIGTSTP,suspsig);
+	}
+# endif
+	(VOID) signal(SIGQUIT,quit);
+	return 0;
+}
+
+int
+catchdel() {
+	(VOID) signal(SIGINT, catchdel);
+	interrupt = 1;
+}
+
+# ifdef SIGTSTP
+
+/*
+ * We had a SIGTSTP signal.
+ * Suspend, by a call to this routine.
+ */
+
+VOID
+suspend() {
+
+	nflush();
+	resettty();
+	(VOID) signal(SIGTSTP,SIG_DFL);
+#if BSD4_2_OPEN
+	sigsetmask(sigblock(0)&~(1 << (SIGTSTP - 1)));
+#endif
+	(VOID) kill(0, SIGTSTP);
+	/*
+	 * We are not here anymore ...
+	 *
+
+	 *
+	 * But we arive here ...
+	 */
+	inittty();
+	putline(TI);
+	flush();
+	(VOID) signal(SIGTSTP,suspsig);
+}
+
+/*
+ * SIGTSTP signal handler.
+ * Just indicate that we had one, ignore further ones and return.
+ */
+
+STATIC int
+suspsig() {
+
+	suspend();
+	if (DoneSetJmp) longjmp(SetJmpBuf, 1);
+}
+# endif
+
+/*
+ * quit : called on exit.
+ * I bet you guessed that much.
+ */
+
+int
+quit() {
+
+	clrbline();
+	resettty();
+	flush();
+	exit(0);
+}
+
+/*
+ * Exit, but nonvoluntarily.
+ * At least tell the user why.
+ */
+
+VOID
+panic(s) char *s; {
+
+	putline("\007\007\007\r\n");
+	putline(s);
+	putline("\r\n");
+	quit();
+}
Index: /trunk/minix/commands/yap/main.h
===================================================================
--- /trunk/minix/commands/yap/main.h	(revision 9)
+++ /trunk/minix/commands/yap/main.h	(revision 9)
@@ -0,0 +1,68 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/main.h,v 1.1.1.1 2005/04/21 14:55:40 beng Exp $ */
+
+# ifndef _MAIN_
+# define PUBLIC extern
+# else
+# define PUBLIC
+# endif
+
+PUBLIC int	nopipe;		/* Not reading from pipe? */
+PUBLIC char *	progname;	/* Name of this program */
+PUBLIC int	interrupt;	/* Interrupt given? */
+PUBLIC int	no_tty;		/* output not to a terminal, behave like cat */
+
+int	main();
+/*
+ * int main(argc,argv)
+ * int argc;		Argument count
+ * char *argv[];	The arguments
+ *
+ * Main program.
+ */
+
+int	opentemp();
+/*
+ * int opentemp(i)
+ * int i;		Either 0 or 1, indicates which temporary to open
+ *
+ * Returns a file descriptor for the temporary file, or panics if
+ * it couldn't open one.
+ */
+
+int	catchdel();
+/*
+ * int catchdel();
+ *
+ * interrupt handler. Does not return a value, but PCC has some
+ * difficulty with the type pointer to function returning void.
+ * This routine only sets a flag indicating that there was an interrupt.
+ */
+
+int	quit();
+/*
+ * int quit();
+ *
+ * Quit signal handler. Also used for normal exits.
+ * It resets the terminal and exits
+ */
+
+VOID	panic();
+/*
+ * void panic(str)
+ * char *str;		Reason for panic
+ *
+ * Panic, but at least tell the user why.
+ */
+
+# ifdef SIGTSTP
+VOID	suspend();
+/*
+ * void suspend()
+ *
+ * Suspends this process
+ */
+# endif
+
+# undef PUBLIC
Index: /trunk/minix/commands/yap/options.c
===================================================================
--- /trunk/minix/commands/yap/options.c	(revision 9)
+++ /trunk/minix/commands/yap/options.c	(revision 9)
@@ -0,0 +1,88 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+# ifndef lint
+static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/options.c,v 1.1.1.1 2005/04/21 14:55:40 beng Exp $";
+# endif
+
+# define _OPTIONS_
+
+# include "in_all.h"
+# include "options.h"
+# include "output.h"
+# include "display.h"
+# include <ctype.h>
+
+STATIC int parsopt();
+char *getenv();
+
+/*
+ * Read the options. Return the argv pointer following them if there were
+ * no errors, otherwise return 0.
+ */
+
+char **
+readoptions(argv) char ** argv; {
+
+	register char ** av = argv+1;
+	register char *p;
+
+	if (p = getenv("YAP")) {
+		(VOID) parsopt(p);
+	}
+	while (*av && **av == '-') {
+		if (parsopt(*av)) {
+			/*
+			 * Error in option
+			 */
+			putline(*av);
+			putline(": illegal option\n");
+			return (char **) 0;
+		}
+		av++;
+	}
+	if (*av && **av == '+') {
+		/*
+		 * Command in command line
+		 */
+		startcomm = *av + 1;
+		av++;
+	}
+	return av;
+}
+
+STATIC int
+parsopt(s) register char *s; {
+	register i;
+
+	if (*s == '-') s++;
+	if (isdigit(*s)) {
+		/*
+		 * pagesize option
+		 */
+		i = 0;
+		do {
+			i = i * 10 + *s++ - '0';
+		} while (isdigit(*s));
+		if (i < MINPAGESIZE) i = MINPAGESIZE;
+		pagesize = i;
+	}
+	while (*s) {
+		switch(*s++) {
+		  case 'c' :
+			cflag++;
+			break;
+		  case 'n' :
+			nflag++;
+			break;
+		  case 'u' :
+			uflag++;
+			break;
+		  case 'q' :
+			qflag++;
+			break;
+		  default :
+			return 1;
+		}
+	}
+	return 0;
+}
Index: /trunk/minix/commands/yap/options.h
===================================================================
--- /trunk/minix/commands/yap/options.h	(revision 9)
+++ /trunk/minix/commands/yap/options.h	(revision 9)
@@ -0,0 +1,26 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/options.h,v 1.1.1.1 2005/04/21 14:55:40 beng Exp $ */
+
+# ifndef _OPTIONS_
+# define PUBLIC extern
+# else
+# define PUBLIC
+# endif
+
+PUBLIC int	cflag;		/* no home before each page */
+PUBLIC int	uflag;		/* no underlining */
+PUBLIC int	nflag;		/* no pattern matching on input */
+PUBLIC int	qflag;		/* no exit on the next page command */
+PUBLIC char *	startcomm;	/* There was a command option */
+
+char ** readoptions();
+/*
+ * char ** readoptions(argv)
+ * char **argv;			Arguments given to yap.
+ *
+ * process the options from the arguments. Return 0 if there was an error,
+ * otherwise return a pointer to where the filenames start.
+ */
+
+# undef PUBLIC
Index: /trunk/minix/commands/yap/output.c
===================================================================
--- /trunk/minix/commands/yap/output.c	(revision 9)
+++ /trunk/minix/commands/yap/output.c	(revision 9)
@@ -0,0 +1,100 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/*
+ * Handle output to screen
+ */
+
+# ifndef lint
+static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/output.c,v 1.1.1.1 2005/04/21 14:55:40 beng Exp $";
+# endif
+
+# define _OUTPUT_
+
+# include "in_all.h"
+# include "output.h"
+# include "main.h"
+
+# define OBUFSIZ 64*128
+
+static char _outbuf[OBUFSIZ];
+
+VOID
+flush() {			/* Flush output buffer, by writing it */
+	register char *p = _outbuf;
+
+	_ocnt = OBUFSIZ;
+	if (_optr) (VOID) write(1, p, _optr - p);
+	_optr = p;
+}
+
+VOID
+nflush() {			/* Flush output buffer, ignoring it */
+
+	_ocnt = OBUFSIZ;
+	_optr = _outbuf;
+}
+
+int
+fputch(ch) char ch; {		/* print a character */
+	putch(ch);
+}
+
+VOID
+putline(s) register char *s; {	/* Print string s */
+
+	if (!s) return;
+	while (*s) {
+		putch(*s++);
+	}
+}
+
+/*
+ * A safe version of putline. All control characters are echoed as ^X
+ */
+
+VOID
+cputline(s) char *s; {
+	register c;
+
+	while (c = *s++) {
+		if ((unsigned) c > 0177) c &= 0177;
+		if (c < ' ' || c == 0177) {
+			putch('^');
+			c ^= 0100;
+		}
+		putch(c);
+	}
+}
+
+/*
+ * Simple minded routine to print a number
+ */
+
+VOID
+prnum(n) long n; {
+
+	putline(getnum(n));
+}
+
+static char *
+fillnum(n, p)
+	long n;
+	char *p;
+{
+	if (n >= 10) {
+		p = fillnum(n / 10, p);
+	}
+	*p++ = (int) (n % 10) + '0';
+	*p = '\0';
+	return p;
+}
+
+char *
+getnum(n)
+	long n;
+{
+	static char buf[20];
+
+	fillnum(n, buf);
+	return buf;
+}
Index: /trunk/minix/commands/yap/output.h
===================================================================
--- /trunk/minix/commands/yap/output.h	(revision 9)
+++ /trunk/minix/commands/yap/output.h	(revision 9)
@@ -0,0 +1,69 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/output.h,v 1.1.1.1 2005/04/21 14:55:40 beng Exp $ */
+
+# ifndef _OUTPUT_
+# define PUBLIC extern
+# else
+# define PUBLIC
+# endif
+
+PUBLIC int _ocnt;
+PUBLIC char *_optr;
+
+#define putch(ch)	if (1) {if (--_ocnt <= 0) flush(); *_optr++ = (ch);} else
+
+VOID	flush();
+/*
+ * void flush()
+ *
+ * Write the output buffer to the screen
+ */
+
+VOID	nflush();
+/*
+ * void nflush()
+ *
+ * Clear output buffer, but do not write it
+ */
+
+int	fputch();
+/*
+ * int fputch(c)
+ * int c;		The character to be printed
+ *
+ * Put character "c" in output buffer and flush if necessary.
+ */
+
+VOID	putline();
+/*
+ * void putline(s)
+ * char *s;		The string to be printed
+ *
+ * Put string "s" in output buffer  etc...
+ */
+
+VOID	cputline();
+/*
+ * void cputline(s)
+ * char *s;		The string to be handled
+ *
+ * Put string "s" in the output buffer, expanding control characters
+ */
+
+VOID	prnum();
+/*
+ * void prnum(n)
+ * long n;		The number to be printed
+ *
+ * print the number "n", using putch.
+ */
+
+char	*getnum();
+/*
+ * char *getnum(n)
+ * long n;		The number to be converted to a string
+ *
+ * Convert a number to a string and return a pointer to it.
+ */
+# undef PUBLIC
Index: /trunk/minix/commands/yap/pattern.c
===================================================================
--- /trunk/minix/commands/yap/pattern.c	(revision 9)
+++ /trunk/minix/commands/yap/pattern.c	(revision 9)
@@ -0,0 +1,160 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+# ifndef lint
+static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/pattern.c,v 1.1.1.1 2005/04/21 14:55:41 beng Exp $";
+# endif not lint
+
+# define _PATTERN_
+
+# include "in_all.h"
+# include "pattern.h"
+# include "getline.h"
+
+# if V8_REGEX
+# include <regexp.h>
+# endif V8_REGEX
+
+/*
+ * Interface to regular expression routines.
+ * Also: simple minded patterns without meta-characters.
+ */
+
+# if USG_REGEX
+static char *pattern;		/* Pointer to compiled pattern */
+char *regcmp(), *regex();
+# endif USG_REGEX
+# if V8_REGEX
+static struct regexp *pattern;
+static char *rc_error;
+struct regexp *regcomp();
+# endif V8_REGEX
+
+# if USG_REGEX || V8_REGEX
+/*
+ * Compile a new pattern, but first free previous result.
+ */
+
+char *
+re_comp(s) char *s; {
+
+	if (!*s) {
+		/*
+		 * user wants previous pattern
+		 */
+		return (char *) 0;
+	}
+	if (pattern) {
+		/*
+		 * there was a compiled pattern
+		 */
+		free(pattern);
+		pattern = 0;
+	}
+# if USG_REGEX
+	return (pattern = regcmp(s, (char *) 0)) ?
+		(char *) 0 :
+		"Error in pattern";
+# endif USG_REGEX
+# if V8_REGEX
+	pattern = regcomp(s);
+	if (pattern) return (char *) 0;
+	if (rc_error) return rc_error;
+	return "Error in pattern";
+# endif V8_REGEX
+}
+
+# if V8_REGEX
+VOID
+regerror(str) char *str; {
+	rc_error = str;
+}
+# endif V8_REGEX
+
+/*
+ * Search for compiled pattern in string "s". Return 0 if not found.
+ */
+
+re_exec(s) char *s; {
+
+# if USG_REGEX
+	return !(regex(pattern,s) == 0);
+# endif USG_REGEX
+# if V8_REGEX
+#  if _MINIX
+	return regexec(pattern,s,1);
+#  else
+	return regexec(pattern,s);
+#  endif
+# endif V8_REGEX
+}
+# else
+# ifndef BSD_REGEX
+/*
+ * In this case, simple minded pattern search without meta-characters
+ */
+
+char	*strcpy();
+
+static char *pattern;
+
+/*
+ * re_comp : Just remember pattern.
+ */
+
+char *
+re_comp(s) char *s; {
+
+	if (!*s) {
+		/*
+		 * User wants previous pattern
+		 */
+		if (!pattern) {
+			return "No previous regular expression";
+		}
+		return (char *) 0;
+	}
+	if (pattern) {
+		/*
+		 * Free old pattern
+		 */
+		free(pattern);
+	}
+	pattern = alloc((unsigned) (strlen(s) + 1), 0);
+	(VOID) strcpy(pattern,s);
+	return (char *) 0;
+}
+
+/*
+ * re-exec : Simple minded pattern matcher
+ */
+
+re_exec(s) register char *s; {
+
+	register char *ppat, *pstr;
+
+	for (; *s; s++) {
+		/*
+		 * As long as there are characters ...
+		 */
+		ppat = pattern; /* Try the pattern again */
+		pstr = s;
+		while (*ppat == *pstr) {
+			if (*++ppat == '\0') {
+				/*
+				 * The pattern matched! Report success
+				 */
+				return 1;
+			}
+			if (*++pstr == '\0') {
+				/*
+				 * Not enough characters left in the string.
+				 * Report failure
+				 */
+				return 0;
+			}
+		}
+	}
+	return 0;		/* Failure */
+}
+# endif not BSD_REGEX
+# endif
Index: /trunk/minix/commands/yap/pattern.h
===================================================================
--- /trunk/minix/commands/yap/pattern.h	(revision 9)
+++ /trunk/minix/commands/yap/pattern.h	(revision 9)
@@ -0,0 +1,14 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/pattern.h,v 1.1.1.1 2005/04/21 14:55:41 beng Exp $ */
+
+# ifndef _PATTERN_
+# define PUBLIC extern
+# else
+# define PUBLIC
+# endif
+
+char *	re_comp();
+int	re_exec();
+
+# undef PUBLIC
Index: /trunk/minix/commands/yap/process.c
===================================================================
--- /trunk/minix/commands/yap/process.c	(revision 9)
+++ /trunk/minix/commands/yap/process.c	(revision 9)
@@ -0,0 +1,127 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+# ifndef lint
+static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/process.c,v 1.1.1.1 2005/04/21 14:55:41 beng Exp $";
+# endif
+
+# define _PROCESS_
+
+# include "in_all.h"
+# if USG_OPEN
+# include <fcntl.h>
+# endif
+# if BSD4_2_OPEN
+# include <sys/file.h>
+# endif
+# if POSIX_OPEN
+# include <sys/types.h>
+# include <fcntl.h>
+# endif
+# include <sys/types.h>
+# include <sys/stat.h>
+# include "process.h"
+# include "commands.h"
+# include "display.h"
+# include "prompt.h"
+# include "getline.h"
+# include "main.h"
+# include "options.h"
+# include "output.h"
+
+static int nfiles;		/* Number of filenames on command line */
+
+/*
+ * Visit a file, file name is "fn".
+ */
+
+VOID
+visitfile(fn) char *fn; {
+	struct stat statbuf;
+
+	if (stdf > 0) {
+		/*
+		 * Close old input file
+		 */
+		(VOID) close(stdf);
+	}
+	currentfile = fn;
+# if USG_OPEN || BSD4_2_OPEN || POSIX_OPEN
+	if ((stdf = open(fn,O_RDONLY,0)) < 0) {
+# else
+	if ((stdf = open(fn,0)) < 0) {
+# endif
+		error(": could not open");
+		maxpos = 0;
+	}
+	else {	/* Get size for percentage in prompt */
+		(VOID) fstat(stdf, &statbuf);
+		maxpos = statbuf.st_size;
+	}
+	do_clean();
+	d_clean();
+}
+
+/*
+ * process the input files, one by one.
+ * If there is none, input is from a pipe.
+ */
+
+VOID
+processfiles(n,argv) char ** argv; {
+
+	static char *dummies[3];
+	long arg;
+
+	if (!(nfiles = n)) {
+		/*
+		 * Input from pipe
+		 */
+		currentfile = "standard-input";
+		/*
+		 * Take care that *(filenames - 1) and *(filenames + 1) are 0
+		 */
+		filenames = &dummies[1];
+		d_clean();
+		do_clean();
+	}
+	else {
+		filenames = argv;
+		(VOID) nextfile(0);
+	}
+	*--argv = 0;
+	if (startcomm) {
+		n = getcomm(&arg);
+		if (commands[n].c_flags & NEEDS_SCREEN) {
+			redraw(0);
+		}
+		do_comm(n,arg);
+		startcomm = 0;
+	}
+	redraw(1);
+	if (setjmp(SetJmpBuf)) {
+		nflush();
+		redraw(1);
+	}
+	DoneSetJmp = 1;
+	for (;;) {
+		interrupt = 0;
+		n = getcomm(&arg);
+		do_comm(n, arg);
+	}
+}
+
+/*
+ * Get the next file the user asks for.
+ */
+
+int
+nextfile(n) {
+	register i;
+
+	if ((i = filecount + n) >= nfiles || i < 0) {
+		return 1;
+	}
+	filecount = i;
+	visitfile(filenames[i]);
+	return 0;
+}
Index: /trunk/minix/commands/yap/process.h
===================================================================
--- /trunk/minix/commands/yap/process.h	(revision 9)
+++ /trunk/minix/commands/yap/process.h	(revision 9)
@@ -0,0 +1,48 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/process.h,v 1.1.1.1 2005/04/21 14:55:41 beng Exp $ */
+
+# ifndef _PROCESS_
+# define PUBLIC extern
+# else
+# define PUBLIC
+# endif
+
+# include <setjmp.h>
+
+PUBLIC	jmp_buf	SetJmpBuf;
+PUBLIC	int DoneSetJmp;
+
+PUBLIC int	stdf;		/* input file descriptor */
+PUBLIC int	filecount;	/* index in filename table */
+PUBLIC char **	filenames;	/* the filenametable */
+PUBLIC char *	currentfile;	/* Name of current file */
+PUBLIC long	maxpos;		/* Size of file */
+
+VOID	visitfile();
+/*
+ * void visitfile(fn)
+ * char *fn;			name of file to be visited
+ *
+ * Opens the file "fn" and gives an error message if this fails.
+ */
+
+VOID	processfiles();
+/*
+ * void processfiles(n,argv)
+ * int n;			number of files to be handled
+ * char ** argv;		names of the files
+ *
+ * Does all the work according to the divide and conquer method
+ */
+
+int	nextfile();
+/*
+ * int nextfile(n)
+ * int n;
+ *
+ * Visits n'th next file. If not there in argument list, return 1.
+ * Otherwise return 0.
+ */
+
+# undef PUBLIC
Index: /trunk/minix/commands/yap/prompt.c
===================================================================
--- /trunk/minix/commands/yap/prompt.c	(revision 9)
+++ /trunk/minix/commands/yap/prompt.c	(revision 9)
@@ -0,0 +1,193 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+# ifndef lint
+static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/prompt.c,v 1.1.1.1 2005/04/21 14:55:41 beng Exp $";
+# endif
+
+# define _PROMPT_
+
+# include "in_all.h"
+# include "prompt.h"
+# include "term.h"
+# include "output.h"
+# include "options.h"
+# include "display.h"
+# include "process.h"
+# include "getline.h"
+# include "main.h"
+# include "getcomm.h"
+# include "keys.h"
+# include "assert.h"
+# include "commands.h"
+
+#define basename(x) x
+
+#ifndef basename
+STATIC char *	basename();
+#endif
+
+static char *errorgiven;	/* Set to error message, if there is one */
+
+char *
+copy(p, ep, s)
+	register char *p, *s;
+	char *ep;
+{
+	while (p < ep && *s) {
+		*p++ = *s++;
+	}
+	return p;
+}
+
+/*
+ * display the prompt and refresh the screen.
+ */
+
+VOID
+give_prompt() {
+
+	register char **name;
+	register struct scr_info *p = &scr_info;
+	char buf[256];
+	register char *pb = buf;
+
+	if (startcomm) return;
+	flush();
+	if (window()) {
+		redraw(0);
+		flush();
+	}
+	if (!stupid) {
+		/*
+		 * fancy prompt
+		 */
+		clrbline();
+		standout();
+		pb = copy(pb, &buf[255], basename(currentfile));
+		if (stdf >= 0) {
+			pb = copy(pb, &buf[255], ", ");
+			pb = copy(pb, &buf[255], getnum(p->firstline));
+			pb = copy(pb, &buf[255], "-");
+			pb = copy(pb, &buf[255], getnum(p->lastline));
+		}
+	}
+	else {
+		*pb++ = '\007';	/* Stupid terminal, stupid prompt */
+	}
+	if (errorgiven) {
+		/*
+		 * display error message
+		 */
+		pb = copy(pb, &buf[255], " ");
+		pb = copy(pb, &buf[255], errorgiven);
+		if (stupid) {
+			pb = copy(pb, &buf[255], "\r\n");
+		}
+		errorgiven = 0;
+	}
+	else if (!stupid && (status || maxpos)) {
+		pb = copy(pb, &buf[255], " (");
+		name = &filenames[filecount];
+		if (status) {
+			/*
+			 * indicate top and/or bottom
+			 */
+			if (status & START) {
+				if (!*(name - 1)) {
+					pb = copy(pb, &buf[255], "Top");
+				}
+				else {
+					pb = copy(pb, &buf[255], "Previous: ");
+					pb = copy(pb, &buf[255], basename(*(name - 1)));
+				}
+				if (status & EOFILE) {
+					pb = copy(pb, &buf[255], ", ");
+				}
+			}
+			if (status & EOFILE) {
+				if (!*(name+1)) {
+					pb = copy(pb, &buf[255], "Bottom");
+				}
+				else {
+					pb = copy(pb, &buf[255], "Next: ");
+					pb = copy(pb, &buf[255], basename(*(name + 1)));
+				}
+			}
+		}
+		else {	/* display percentage */
+			pb = copy(pb, &buf[255], getnum((100 * getpos(p->lastline))/maxpos));
+			pb = copy(pb, &buf[255], "%");
+		}
+		pb = copy(pb, &buf[255], ")");
+	}
+	*pb = '\0';
+	if (!stupid) {
+		buf[COLS-1] = 0;
+		putline(buf);
+		standend();
+	}
+	else	putline(buf);
+}
+
+/*
+ * Remember error message
+ */
+
+VOID
+error(str) char *str; {
+
+	errorgiven = str;
+}
+
+#ifndef basename
+STATIC char *
+basename(fn) char *fn; {	/* Return name without path */
+
+	register char *s;
+
+	s = fn;
+	while (*s++) ;		/* Search end of name */
+	for (;;) {
+		if (*--s == '/') {
+			/*
+			 * Backwards to first '/'
+			 */
+			if (*(s+1)) {
+				/*
+				 * There is a name after the '/'
+				 */
+				return s + 1;
+			}
+			*s = 0; /* No name after the '/' */
+		}
+		if (s == fn) return s;
+	}
+	/* NOTREACHED */
+}
+#endif
+
+VOID
+ret_to_continue() {		/* Obvious */
+	int c;
+	static char buf[2];
+
+	for (;;) {
+		clrbline();
+		standout();
+		if (errorgiven) {
+			putline(errorgiven);
+			putline(" ");
+			errorgiven = 0;
+		}
+		putline("[Type anything to continue]");
+		standend();
+		if (is_escape(c = getch())) {
+			buf[0] = c;
+			(VOID) match(buf, &c, currmap->k_mach);
+			assert(c > 0);
+			do_comm(c, -1L);
+		}
+		else	break;
+	}
+	clrbline();
+}
Index: /trunk/minix/commands/yap/prompt.h
===================================================================
--- /trunk/minix/commands/yap/prompt.h	(revision 9)
+++ /trunk/minix/commands/yap/prompt.h	(revision 9)
@@ -0,0 +1,33 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/prompt.h,v 1.1.1.1 2005/04/21 14:55:41 beng Exp $ */
+
+# ifndef _PROMPT_
+# define PUBLIC extern
+# else
+# define PUBLIC
+# endif
+
+VOID	give_prompt();
+/*
+ * void give_prompt()
+ *
+ * Displays a prompt, with possibly an error message
+ */
+
+VOID	error();
+/*
+ * void error(s)
+ * char *s;		The error
+ *
+ * Takes care that there will be an error message in the next prompt.
+ */
+
+VOID	ret_to_continue();
+/*
+ * void ret_to_continue();
+ *
+ * Asks the user to type something before continuing.
+ */
+
+# undef PUBLIC
Index: /trunk/minix/commands/yap/term.c
===================================================================
--- /trunk/minix/commands/yap/term.c	(revision 9)
+++ /trunk/minix/commands/yap/term.c	(revision 9)
@@ -0,0 +1,487 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/*
+ * Terminal handling routines, mostly initializing.
+ */
+
+# ifndef lint
+static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/term.c,v 1.1.1.1 2005/04/21 14:55:41 beng Exp $";
+# endif
+
+# define _TERM_
+
+#include "in_all.h"
+#include "term.h"
+#include "machine.h"
+#include "output.h"
+#include "display.h"
+#include "options.h"
+#include "getline.h"
+#include "keys.h"
+#include "main.h"
+
+#ifdef TIOCGWINSZ
+static struct winsize w;
+#endif
+
+char	*strcpy(),
+	*strcat(),
+	*tgoto(),
+	*tgetstr(),
+	*getenv();
+
+static char	tcbuf1[1024];	/* Holds terminal capability strings */
+static char *	ptc;		/* Pointer in it */
+static char	tcbuf[1024];	/* Another termcap buffer */
+short	ospeed;		/* Needed for tputs() */
+char	PC;		/* Needed for tputs() */
+char *	UP;		/* Needed for tgoto() */
+static char	*ll;
+
+struct linelist _X[100];	/* 100 is enough ? */
+
+# if USG_TTY
+static struct termio _tty,_svtty;
+# elif POSIX_TTY
+static struct termios _tty, _svtty;
+# else
+# ifdef TIOCSPGRP
+static int proc_id, saved_pgrpid;
+# endif
+static struct sgttyb _tty,_svtty;
+# ifdef TIOCGETC
+static struct tchars _ttyc, _svttyc;
+# endif
+# ifdef TIOCGLTC
+static int line_discipline;
+static struct ltchars _lttyc, _svlttyc;
+# endif
+# endif
+
+static VOID
+handle(c) char *c; {	/* if character *c is used, set it to undefined */
+
+	if (isused(*c)) *c = 0377;
+}
+
+/*
+ * Set terminal in cbreak mode.
+ * Also check if tabs need expanding.
+ */
+
+VOID
+inittty() {
+# if USG_TTY
+	register struct termio *p = &_tty;
+
+	ioctl(0,TCGETA,(char *) p);
+	_svtty = *p;
+	if (p->c_oflag & TAB3) {
+		/*
+		 * We do tab expansion ourselves
+		 */
+		expandtabs = 1;
+	}
+	p->c_oflag &= ~(TAB3|OCRNL|ONLRET|ONLCR);
+	p->c_oflag |= (/*ONOCR|*/OPOST);	/* ONOCR does not seem to work
+						   very well in combination with
+						   ~ONLCR
+						*/
+	p->c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON);
+	if (isused('S'&037) || isused('Q'&037)) p->c_iflag &= ~IXON;
+	handle(&(p->c_cc[0]));	/* INTR and QUIT (mnemonics not defined ??) */
+	handle(&(p->c_cc[1]));
+	erasech = p->c_cc[VERASE];
+	killch = p->c_cc[VKILL];
+	p->c_cc[VMIN] = 1;	/* Just wait for one character */
+	p->c_cc[VTIME] = 0;
+	ospeed = p->c_cflag & CBAUD;
+	ioctl(0,TCSETAW,(char *) p);
+#elif POSIX_TTY
+	register struct termios *p = &_tty;
+
+	tcgetattr(0, p);
+	_svtty = *p;
+#ifdef _MINIX	/* Should be XTABS */
+	if (p->c_oflag & XTABS) {
+		/*
+		 * We do tab expansion ourselves
+		 */
+		expandtabs = 1;
+	}
+	p->c_oflag &= (OPOST|XTABS);
+#else
+	p->c_oflag &= ~OPOST;
+#endif
+	p->c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON);
+	if (isused('S'&037) || isused('Q'&037)) p->c_iflag &= ~IXON;
+	handle(&(p->c_cc[VINTR]));	
+	handle(&(p->c_cc[VQUIT]));
+	erasech = p->c_cc[VERASE];
+	killch = p->c_cc[VKILL];
+	p->c_cc[VMIN] = 1;	/* Just wait for one character */
+	p->c_cc[VTIME] = 0;
+	ospeed = cfgetospeed(p);
+	tcsetattr(0, TCSANOW, p);
+# else
+	register struct sgttyb *p = &_tty;
+
+# ifdef TIOCSPGRP
+	/*
+	 * If we can, we put yap in another process group, and the terminal
+	 * with it. This is done, so that interrupts given by the user
+	 * will only affect yap and not it's children (processes writing
+	 * on a pipe to yap)
+	 */
+	if (ioctl(0, TIOCSPGRP, (char *) &proc_id) != -1) {
+		setpgrp(0, proc_id);
+	}
+# endif
+	ioctl(0,TIOCGETP,(char *) p);
+	_svtty = *p;
+	erasech = p->sg_erase;
+	killch = p->sg_kill;
+	ospeed = p->sg_ospeed;
+	if (p->sg_flags & XTABS) {
+		/*
+		 * We do tab expansion ourselves
+		 */
+		expandtabs = 1;
+	}
+	p->sg_flags |= (CBREAK);
+	p->sg_flags &= ~(ECHO|XTABS|RAW|LCASE|CRMOD);
+#ifdef TIOCSETN
+	ioctl(0, TIOCSETN, (char *) p);
+#else
+	ioctl(0,TIOCSETP,(char *) p);
+#endif
+/* Bloody Sun ... */
+#undef t_startc
+#undef t_stopc
+#undef t_intrc
+#undef t_quitc
+#undef t_suspc
+#undef t_dsuspc
+#undef t_flushc
+#undef t_lnextc
+# ifdef TIOCGETC
+	{   register struct tchars *q = &_ttyc;
+
+		ioctl(0,TIOCGETC,(char *) q);
+		_svttyc = *q;
+		handle(&(q->t_intrc));
+		handle(&(q->t_quitc));
+		if (isused(q->t_startc) || isused(q->t_stopc)) {
+			q->t_startc = q->t_stopc = 0377;
+		}
+		ioctl(0,TIOCSETC, (char *) q);
+	}
+# endif
+# ifdef TIOCGLTC
+	{   register struct ltchars *q = &_lttyc;
+
+		ioctl(0,TIOCGETD,(char *) &line_discipline);
+		if (line_discipline == NTTYDISC) {
+			ioctl(0, TIOCGLTC,(char *) q);
+			_svlttyc = *q;
+			handle(&(q->t_suspc));
+			handle(&(q->t_dsuspc));
+			q->t_flushc = q->t_lnextc = 0377;
+			ioctl(0,TIOCSLTC, (char *) q);
+		}
+	}
+# endif
+# endif
+}
+
+/*
+ * Reset the terminal to its original state
+ */
+
+VOID
+resettty() {
+
+# if USG_TTY
+	ioctl(0,TCSETAW,(char *) &_svtty);
+# elif POSIX_TTY
+	tcsetattr(0, TCSANOW, &_svtty);
+# else
+# ifdef TIOCSPGRP
+	ioctl(0, TIOCSPGRP, (char *) &saved_pgrpid);
+	setpgrp(0, saved_pgrpid);
+# endif
+	ioctl(0,TIOCSETP,(char *) &_svtty);
+# ifdef TIOCGETC
+	ioctl(0,TIOCSETC, (char *) &_svttyc);
+# endif
+# ifdef TIOCGLTC
+	if (line_discipline == NTTYDISC) ioctl(0,TIOCSLTC, (char *) &_svlttyc);
+# endif
+# endif
+	putline(TE);
+	flush();
+}
+
+/*
+ * Get terminal capability "cap".
+ * If not present, return an empty string.
+ */
+
+STATIC char *
+getcap(cap) char *cap; {
+	register char *s;
+
+	s = tgetstr(cap, &ptc);
+	if (!s) return "";
+	return s;
+}
+
+/*
+ * Initialize some terminal-dependent stuff.
+ */
+
+VOID
+ini_terminal() {
+
+	register char * s;
+	register struct linelist *lp, *lp1;
+	register i;
+	register UG, SG;
+	char tempbuf[20];
+	char *mb, *mh, *mr;	/* attributes */
+
+	initkeys();
+#if !_MINIX
+# ifdef TIOCSPGRP
+	proc_id = getpid();
+	ioctl(0,TIOCGPGRP, (char *) &saved_pgrpid);
+# endif
+#endif
+	inittty();
+	stupid = 1;
+	ptc = tcbuf1;
+	BC = "\b";
+	TA = "\t";
+	if (!(s = getenv("TERM"))) s = "dumb";
+	if (tgetent(tcbuf, s) <= 0) {
+		panic("No termcap entry");
+	}
+	stupid = 0;
+	hardcopy = tgetflag("hc");	/* Hard copy terminal?*/
+	PC = *(getcap("pc"));
+	if (*(s = getcap("bc"))) {
+		/*
+		 * Backspace if not ^H
+		 */
+		BC = s;
+	}
+	UP = getcap("up");		/* move up a line */
+	CE = getcap("ce");		/* clear to end of line */
+	CL = getcap("cl");		/* clear screen */
+	if (!*CL) cflag = 1;
+	TI = getcap("ti");		/* Initialization for CM */
+	TE = getcap("te");		/* end for CM */
+	CM = getcap("cm");		/* cursor addressing */
+	SR = getcap("sr");		/* scroll reverse */
+	AL = getcap("al");		/* Insert line */
+	SO = getcap("so");		/* standout */
+	SE = getcap("se");		/* standend */
+	SG = tgetnum("sg");		/* blanks left by SO, SE */
+	if (SG < 0) SG = 0;
+	US = getcap("us");		/* underline */
+	UE = getcap("ue");		/* end underline */
+	UG = tgetnum("ug");		/* blanks left by US, UE */
+	if (UG < 0) UG = 0;
+	UC = getcap("uc");		/* underline a character */
+	mb = getcap("mb");		/* blinking attribute */
+	MD = getcap("md");		/* bold attribute */
+	ME = getcap("me");		/* turn off attributes */
+	mh = getcap("mh");		/* half bright attribute */
+	mr = getcap("mr");		/* reversed video attribute */
+	if (!nflag) {
+		/*
+		 * Recognize special strings
+		 */
+		(VOID) addstring(SO,SG,&sppat);
+		(VOID) addstring(SE,SG,&sppat);
+		(VOID) addstring(US,UG,&sppat);
+		(VOID) addstring(UE,UG,&sppat);
+		(VOID) addstring(mb,0,&sppat);
+		(VOID) addstring(MD,0,&sppat);
+		(VOID) addstring(ME,0,&sppat);
+		(VOID) addstring(mh,0,&sppat);
+		(VOID) addstring(mr,0,&sppat);
+		if (*UC) {
+			(VOID) strcpy(tempbuf,BC);
+			(VOID) strcat(tempbuf,UC);
+			(VOID) addstring(tempbuf,0,&sppat);
+		}
+	}
+	if (UG > 0 || uflag) {
+		US = "";
+		UE = "";
+	}
+	if (*US || uflag) UC = "";
+	COLS = tgetnum("co");		/* columns on page */
+	i = tgetnum("li");		/* Lines on page */
+	AM = tgetflag("am");		/* terminal wraps automatically? */
+	XN = tgetflag("xn");		/* and then ignores next newline? */
+	DB = tgetflag("db");		/* terminal retains lines below */
+	if (!*(s = getcap("ho")) && *CM) {
+		s = tgoto(CM,0,0);	/* Another way of getting home */
+	}
+	if ((!*CE && !*AL) || !*s || hardcopy) {
+		cflag = stupid = 1;
+	}
+	(VOID) strcpy(HO,s);
+	if (*(s = getcap("ta"))) {
+		/*
+		 * Tab (other than ^I or padding)
+		 */
+		TA = s;
+	}
+       if (!*(ll = getcap("ll")) && *CM && i > 0) {
+		/*
+		 * Lower left hand corner
+		 */
+               (VOID) strcpy(BO, tgoto(CM,0,i-1));
+	}
+       else    (VOID) strcpy(BO, ll);
+	if (COLS <= 0 || COLS > 256) {
+		if ((unsigned) COLS >= 65409) {
+			/* SUN bug */
+			COLS &= 0xffff;
+			COLS -= (65409 - 128);
+		}
+		if (COLS <= 0 || COLS > 256) COLS = 80;
+	}
+	if (i <= 0) {
+		i = 24;
+		cflag = stupid = 1;
+	}
+	LINES = i;
+	maxpagesize = i - 1;
+	scrollsize = maxpagesize / 2;
+	if (scrollsize <= 0) scrollsize = 1;
+	if (!pagesize || pagesize >= i) {
+		pagesize = maxpagesize;
+	}
+
+	/*
+	 * The next part does not really belong here, but there it is ...
+	 * Initialize a circular list for the screenlines.
+	 */
+
+       scr_info.tail = lp = _X;
+       lp1 = lp + (100 - 1);
+	for (; lp <= lp1; lp++) {
+		/*
+		 * Circular doubly linked list
+		 */
+		lp->next = lp + 1;
+		lp->prev = lp - 1;
+	}
+       lp1->next = scr_info.tail;
+	lp1->next->prev = lp1;
+	if (stupid) {
+		(VOID) strcpy(BO,"\r\n");
+	}
+	putline(TI);
+	window();
+}
+
+/*
+ * Place cursor at start of line n.
+ */
+
+VOID
+mgoto(n) register n; {
+
+	if (n == 0) home();
+	else if (n == maxpagesize && *BO) bottom();
+	else if (*CM) {
+		/*
+		 * Cursor addressing
+		 */
+		tputs(tgoto(CM,0,n),1,fputch);
+	}
+	else if (*BO && *UP && n >= (maxpagesize >> 1)) {
+		/*
+		 * Bottom and then up
+		 */
+		bottom();
+		while (n++ < maxpagesize) putline(UP);
+	}
+	else {	/* Home, and then down */
+		home();
+		while (n--) putline("\r\n");
+	}
+}
+
+/*
+ * Clear bottom line
+ */
+
+VOID
+clrbline() {
+
+	if (stupid) {
+		putline("\r\n");
+		return;
+	}
+	bottom();
+	if (*CE) {
+		/*
+		 * We can clear to end of line
+		 */
+		clrtoeol();
+		return;
+	}
+# ifdef VT100_PATCH
+	insert_line(maxpagesize);
+# else
+	insert_line();
+# endif
+}
+
+# ifdef VT100_PATCH
+ins_line(l) {
+	tputs(tgoto(AL, l, 0), maxpagesize - l, fputch);
+}
+# endif
+
+VOID
+home() {
+
+	tputs(HO,1,fputch);
+}
+
+VOID
+bottom() {
+
+	tputs(BO,1,fputch);
+	if (!*BO) mgoto(maxpagesize);
+}
+
+int
+window()
+{
+#ifdef TIOCGWINSZ
+        if (ioctl(1, TIOCGWINSZ, &w) < 0) return 0;
+
+        if (w.ws_col == 0) w.ws_col = COLS;
+        if (w.ws_row == 0) w.ws_row = LINES;
+        if (w.ws_col != COLS || w.ws_row != LINES) {
+		COLS = w.ws_col;
+		LINES = w.ws_row;
+		maxpagesize = LINES - 1;
+		pagesize = maxpagesize;
+		if (! *ll) (VOID) strcpy(BO, tgoto(CM,0,maxpagesize));
+		scr_info.currentpos = 0;
+		scrollsize = maxpagesize / 2; 
+		if (scrollsize <= 0) scrollsize = 1;
+		return 1;
+        }
+#endif
+        return 0;
+}
Index: /trunk/minix/commands/yap/term.h
===================================================================
--- /trunk/minix/commands/yap/term.h	(revision 9)
+++ /trunk/minix/commands/yap/term.h	(revision 9)
@@ -0,0 +1,137 @@
+/* Copyright (c) 1985 Ceriel J.H. Jacobs */
+
+/* $Header: /cvsup/minix/src/commands/yap/term.h,v 1.1.1.1 2005/04/21 14:55:41 beng Exp $ */
+
+/* All terminal and terminal dependent stuff */
+
+# ifndef _TERM_
+# define PUBLIC extern
+# else
+# define PUBLIC
+# endif
+
+# if USG_TTY
+# include <termio.h>
+# elif POSIX_TTY
+# include <termios.h>
+# else
+# include <sgtty.h>
+# endif
+
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+
+/* Terminal setting */
+
+PUBLIC int expandtabs;		/* Tabs need expanding? */
+PUBLIC int stupid;		/* Stupid terminal */
+PUBLIC int hardcopy;		/* Hardcopy terminal */
+
+/* termcap stuff */
+PUBLIC
+char	*CE,			/* clear to end of line */
+	*CL,			/* clear screen */
+	*SO,			/* stand out */
+	*SE,			/* stand end */
+	*US,			/* underline start */
+	*UE,			/* underline end */
+	*UC,			/* underline character */
+	*MD,			/* bold start */
+	*ME,			/* attributes (like bold) off */
+	*TI,			/* initialize for CM */
+	*TE,			/* End of CM */
+	*CM,			/* Cursor addressing */
+	*TA,			/* Tab */
+	*SR,			/* Scroll reverse */
+	*AL;			/* insert line */
+PUBLIC
+int	LINES,			/* # of lines on screen */
+	COLS,			/* # of colums */
+	AM,			/* Automatic margins */
+	XN,			/* newline ignored after wrap */
+	DB;			/* terminal retains lines below */
+PUBLIC
+char	HO[20],			/* Sequence to get to home position */
+	BO[20];			/* sequence to get to lower left hand corner */
+PUBLIC
+int	erasech,		/* users erase character */
+	killch;			/* users kill character */
+PUBLIC struct state *sppat;	/* Special patterns to be recognized */
+PUBLIC char
+	*BC;			/* Back space */
+
+#define backspace()	putline(BC)
+#define clrscreen()	tputs(CL,LINES,fputch)
+#define clrtoeol()	tputs(CE,1,fputch)
+#define scrollreverse()	tputs(SR,LINES,fputch)
+#ifdef VT100_PATCH
+#define insert_line(l)	ins_line(l)
+#define standout()	tputs(SO,1,fputch)
+#define standend()	tputs(SE,1,fputch)
+#define underline()	tputs(US,1,fputch)
+#define end_underline() tputs(UE,1,fputch)
+#define bold()		tputs(MD,1,fputch)
+#define end_bold()	tputs(ME,1,fputch)
+#define underchar()	tputs(UC,1,fputch)
+# else
+#define insert_line()	tputs(AL,LINES,fputch)
+#define standout()	putline(SO)
+#define standend()	putline(SE)
+#define underline()	putline(US)
+#define end_underline() putline(UE)
+#define bold()		putline(MD)
+#define end_bold()	putline(ME)
+#define underchar()	putline(UC)
+# endif
+#define givetab()	tputs(TA,1,fputch)
+
+VOID	inittty();
+/*
+ * void inittty()
+ *
+ * Initialises the terminal (sets it in cbreak mode, etc)
+ */
+
+VOID	resettty();
+/*
+ * void resettty()
+ *
+ * resets the terminal to the mode in which it was before yap was invoked
+ */
+
+VOID	ini_terminal();
+/*
+ * void ini_terminal()
+ *
+ * Handles the termcap entry for your terminal. In some cases, the terminal
+ * will be considered stupid.
+ */
+
+VOID	mgoto();
+/*
+ * void mgoto(n)
+ * int n;		Line to go to
+ *
+ * Put the cursor at the start of the n'th screen line.
+ * This can be done in several ways (of course).
+ */
+
+VOID	clrbline();
+/*
+ * void clrbline()
+ *
+ * clears the bottom line, by either clearing it to end of line,
+ * or pushing it of the screen by inserting a line before it.
+ */
+
+VOID	home();
+VOID	bottom();
+/*
+ * Obvious
+ */
+
+#ifdef WINDOW
+int	window();
+#endif
+# undef PUBLIC
Index: /trunk/minix/commands/zmodem/Makefile
===================================================================
--- /trunk/minix/commands/zmodem/Makefile	(revision 9)
+++ /trunk/minix/commands/zmodem/Makefile	(revision 9)
@@ -0,0 +1,25 @@
+# Makefile for zmodem
+
+all: rz sz
+
+CC = exec cc
+CFLAGS= -DPOSIX -D_MINIX -D_POSIX_SOURCE -O -wo
+
+rz: rz.c rbsb.c zm.c zmodem.h
+	$(CC) $(CFLAGS) -i -o rz rz.c
+	install -S 5kw $@
+
+sz: sz.c rbsb.c zm.c zmodem.h
+	$(CC) $(CFLAGS) -i -o sz sz.c
+	install -S 5kw $@
+
+install:	/usr/bin/rz /usr/bin/sz
+
+/usr/bin/rz:	rz
+	install -cs -o bin rz $@
+
+/usr/bin/sz:	sz
+	install -cs -o bin sz $@
+
+clean:	
+	rm -f *.bak *.o core rz sz
Index: /trunk/minix/commands/zmodem/build
===================================================================
--- /trunk/minix/commands/zmodem/build	(revision 9)
+++ /trunk/minix/commands/zmodem/build	(revision 9)
@@ -0,0 +1,3 @@
+#!/bin/sh
+make clean
+make && make install
Index: /trunk/minix/commands/zmodem/crctab.c
===================================================================
--- /trunk/minix/commands/zmodem/crctab.c	(revision 9)
+++ /trunk/minix/commands/zmodem/crctab.c	(revision 9)
@@ -0,0 +1,140 @@
+/*
+ *  Crc calculation stuff
+ */
+
+/* crctab calculated by Mark G. Mendel, Network Systems Corporation */
+static unsigned short crctab[256] = {
+    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
+    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
+    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
+    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
+    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
+    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
+    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
+    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
+    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
+    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
+    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
+    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
+    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
+    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
+    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
+    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
+    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
+    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
+    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
+    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
+    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
+    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
+    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
+    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
+    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
+    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
+    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
+    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
+    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
+    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
+    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
+    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
+};
+
+/*
+ * updcrc macro derived from article Copyright (C) 1986 Stephen Satchell. 
+ *  NOTE: First srgument must be in range 0 to 255.
+ *        Second argument is referenced twice.
+ * 
+ * Programmers may incorporate any or all code into their programs, 
+ * giving proper credit within the source. Publication of the 
+ * source routines is permitted so long as proper credit is given 
+ * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg, 
+ * Omen Technology.
+ */
+
+#define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
+
+/*
+ * Copyright (C) 1986 Gary S. Brown.  You may use this program, or
+ * code or tables extracted from it, as desired without restriction.
+ */
+
+/* First, the polynomial itself and its table of feedback terms.  The  */
+/* polynomial is                                                       */
+/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
+/* Note that we take it "backwards" and put the highest-order term in  */
+/* the lowest-order bit.  The X^32 term is "implied"; the LSB is the   */
+/* X^31 term, etc.  The X^0 term (usually shown as "+1") results in    */
+/* the MSB being 1.                                                    */
+
+/* Note that the usual hardware shift register implementation, which   */
+/* is what we're using (we're merely optimizing it by doing eight-bit  */
+/* chunks at a time) shifts bits into the lowest-order term.  In our   */
+/* implementation, that means shifting towards the right.  Why do we   */
+/* do it this way?  Because the calculated CRC must be transmitted in  */
+/* order from highest-order term to lowest-order term.  UARTs transmit */
+/* characters in order from LSB to MSB.  By storing the CRC this way,  */
+/* we hand it to the UART in the order low-byte to high-byte; the UART */
+/* sends each low-bit to hight-bit; and the result is transmission bit */
+/* by bit from highest- to lowest-order term without requiring any bit */
+/* shuffling on our part.  Reception works similarly.                  */
+
+/* The feedback terms table consists of 256, 32-bit entries.  Notes:   */
+/*                                                                     */
+/*     The table can be generated at runtime if desired; code to do so */
+/*     is shown later.  It might not be obvious, but the feedback      */
+/*     terms simply represent the results of eight shift/xor opera-    */
+/*     tions for all combinations of data and CRC register values.     */
+/*                                                                     */
+/*     The values must be right-shifted by eight bits by the "updcrc"  */
+/*     logic; the shift must be unsigned (bring in zeroes).  On some   */
+/*     hardware you could probably optimize the shift in assembler by  */
+/*     using byte-swap instructions.                                   */
+
+static long cr3tab[] = { /* CRC polynomial 0xedb88320 */
+0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+#ifdef NFGM
+long
+UPDC32(b, c)
+long c;
+{
+	return (cr3tab[((int)c ^ b) & 0xff] ^ ((c >> 8) & 0x00FFFFFF));
+}
+
+#else
+
+#define UPDC32(b, c) (cr3tab[((int)c ^ b) & 0xff] ^ ((c >> 8) & 0x00FFFFFF))
+#endif
+
+/* End of crctab.c */
Index: /trunk/minix/commands/zmodem/rbsb.c
===================================================================
--- /trunk/minix/commands/zmodem/rbsb.c	(revision 9)
+++ /trunk/minix/commands/zmodem/rbsb.c	(revision 9)
@@ -0,0 +1,421 @@
+/*
+ *
+ *  Rev 05-05-1988
+ *  This file contains Unix specific code for setting terminal modes,
+ *  very little is specific to ZMODEM or YMODEM per se (that code is in
+ *  sz.c and rz.c).  The CRC-16 routines used by XMODEM, YMODEM, and ZMODEM
+ *  are also in this file, a fast table driven macro version
+ *
+ *	V7/BSD HACKERS:  SEE NOTES UNDER mode(2) !!!
+ *
+ *   This file is #included so the main file can set parameters such as HOWMANY.
+ *   See the main files (rz.c/sz.c) for compile instructions.
+ */
+
+#ifdef V7
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sgtty.h>
+#define OS "V7/BSD"
+#ifdef LLITOUT
+long Locmode;		/* Saved "local mode" for 4.x BSD "new driver" */
+long Locbit = LLITOUT;	/* Bit SUPPOSED to disable output translations */
+#include <strings.h>
+#endif
+#endif
+
+#ifdef POSIX
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <termios.h>
+#define OS "POSIX"
+#endif
+
+#ifndef OS
+#ifndef USG
+#define USG
+#endif
+#endif
+
+#ifdef USG
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <termio.h>
+#include <sys/ioctl.h>
+#define OS "SYS III/V"
+#define MODE2OK
+#include <string.h>
+#endif
+
+#include "zmodem.h"
+
+_PROTOTYPE(static unsigned getspeed , (int code ));
+
+#if HOWMANY  > 255
+Howmany must be 255 or less
+#endif
+
+/*
+ * return 1 iff stdout and stderr are different devices
+ *  indicating this program operating with a modem on a
+ *  different line
+ */
+int Fromcu;		/* Were called from cu or yam */
+
+void from_cu()
+{
+	struct stat a, b;
+
+	fstat(1, &a); fstat(2, &b);
+	Fromcu = a.st_rdev != b.st_rdev;
+	return;
+}
+
+void cucheck()
+{
+	if (Fromcu)
+		fprintf(stderr,"Please read the manual page BUGS chapter!\r\n");
+}
+
+
+struct {
+	unsigned baudr;
+	int speedcode;
+} speeds[] = {
+	110,	B110,
+	300,	B300,
+#ifdef B600
+	600,	B600,
+#endif
+	1200,	B1200,
+	2400,	B2400,
+	4800,	B4800,
+	9600,	B9600,
+#ifdef EXTA
+	19200,	EXTA,
+	38400,	EXTB,
+#endif
+	0,
+};
+
+int Twostop;		/* Use two stop bits */
+
+
+#ifndef READCHECK
+#ifdef FIONREAD
+#define READCHECK
+/*
+ *  Return non 0 iff something to read from io descriptor f
+ */
+int rdchk(f)
+{
+	static long lf;
+
+	ioctl(f, FIONREAD, &lf);
+	return ((int) lf);
+}
+#endif
+#ifdef SV
+#define READCHECK
+#include <fcntl.h>
+
+char checked = '\0' ;
+/*
+ * Nonblocking I/O is a bit different in System V, Release 2
+ */
+int rdchk(f)
+{
+	int lf, savestat;
+
+	savestat = fcntl(f, F_GETFL) ;
+	fcntl(f, F_SETFL, savestat | O_NDELAY) ;
+	lf = read(f, &checked, 1) ;
+	fcntl(f, F_SETFL, savestat) ;
+	return(lf) ;
+}
+#endif
+#endif
+
+
+static unsigned
+getspeed(code)
+int code;
+{
+	register n;
+
+	for (n=0; speeds[n].baudr; ++n)
+		if (speeds[n].speedcode == code)
+			return speeds[n].baudr;
+	return 38400;	/* Assume fifo if ioctl failed */
+}
+
+
+
+#ifdef POSIX
+struct termios oldtty, tty;
+#else
+#ifdef ICANON
+struct termio oldtty, tty;
+#else
+struct sgttyb oldtty, tty;
+struct tchars oldtch, tch;
+#endif
+#endif
+
+int iofd = 0;		/* File descriptor for ioctls & reads */
+
+/*
+ * mode(n)
+ *  3: save old tty stat, set raw mode with flow control
+ *  2: set XON/XOFF for sb/sz with ZMODEM or YMODEM-g
+ *  1: save old tty stat, set raw mode 
+ *  0: restore original tty mode
+ */
+int mode(n)
+int n;
+{
+	static did0 = FALSE;
+
+	vfile("mode:%d", n);
+	switch(n) {
+#ifdef POSIX
+	case 2:		/* Un-raw mode used by sz, sb when -g detected */
+		if(!did0)
+			(void) tcgetattr(iofd, &oldtty);
+		tty = oldtty;
+
+		tty.c_iflag = BRKINT|IXON;
+
+		tty.c_oflag = 0;	/* Transparent output */
+
+		tty.c_cflag &= ~PARENB;	/* Disable parity */
+		tty.c_cflag |= CS8;	/* Set character size = 8 */
+		if (Twostop)
+			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
+
+
+		tty.c_lflag = ISIG;
+		tty.c_cc[VINTR] = Zmodem ? 03:030;	/* Interrupt char */
+		tty.c_cc[VQUIT] = -1;			/* Quit char */
+		tty.c_cc[VMIN] = 3;	 /* This many chars satisfies reads */
+		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
+
+		(void) tcsetattr(iofd, TCSANOW, &tty);
+		did0 = TRUE;
+		return OK;
+	case 1:
+	case 3:
+		if(!did0)
+			(void) tcgetattr(iofd, &oldtty);
+		tty = oldtty;
+
+		tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK;
+
+		 /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */
+		tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+
+		tty.c_oflag = 0;	/* Transparent output */
+
+		tty.c_cflag &= ~PARENB;	/* Same baud rate, disable parity */
+		tty.c_cflag |= CS8;	/* Set character size = 8 */
+		if (Twostop)
+			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
+		tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
+		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
+		(void) tcsetattr(iofd, TCSANOW, &tty);
+		did0 = TRUE;
+		Baudrate = cfgetospeed(&tty);
+		return OK;
+#endif
+#ifdef USG
+	case 2:		/* Un-raw mode used by sz, sb when -g detected */
+		if(!did0)
+			(void) ioctl(iofd, TCGETA, &oldtty);
+		tty = oldtty;
+
+		tty.c_iflag = BRKINT|IXON;
+
+		tty.c_oflag = 0;	/* Transparent output */
+
+		tty.c_cflag &= ~PARENB;	/* Disable parity */
+		tty.c_cflag |= CS8;	/* Set character size = 8 */
+		if (Twostop)
+			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
+
+
+#ifdef READCHECK
+		tty.c_lflag = Zmodem ? 0 : ISIG;
+		tty.c_cc[VINTR] = Zmodem ? -1:030;	/* Interrupt char */
+#else
+		tty.c_lflag = ISIG;
+		tty.c_cc[VINTR] = Zmodem ? 03:030;	/* Interrupt char */
+#endif
+		tty.c_cc[VQUIT] = -1;			/* Quit char */
+#ifdef NFGVMIN
+		tty.c_cc[VMIN] = 1;
+#else
+		tty.c_cc[VMIN] = 3;	 /* This many chars satisfies reads */
+#endif
+		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
+
+		(void) ioctl(iofd, TCSETAW, &tty);
+		did0 = TRUE;
+		return OK;
+	case 1:
+	case 3:
+		if(!did0)
+			(void) ioctl(iofd, TCGETA, &oldtty);
+		tty = oldtty;
+
+		tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK;
+
+		 /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */
+		tty.c_lflag &= ~(ECHO | ICANON | ISIG);
+
+		tty.c_oflag = 0;	/* Transparent output */
+
+		tty.c_cflag &= ~PARENB;	/* Same baud rate, disable parity */
+		tty.c_cflag |= CS8;	/* Set character size = 8 */
+		if (Twostop)
+			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
+#ifdef NFGVMIN
+		tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */
+#else
+		tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
+#endif
+		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
+		(void) ioctl(iofd, TCSETAW, &tty);
+		did0 = TRUE;
+		Baudrate = getspeed(tty.c_cflag & CBAUD);
+		return OK;
+#endif
+#ifdef V7
+	/*
+	 *  NOTE: this should transmit all 8 bits and at the same time
+	 *   respond to XOFF/XON flow control.  If no FIONREAD or other
+	 *   READCHECK alternative, also must respond to INTRRUPT char
+	 *   This doesn't work with V7.  It should work with LLITOUT,
+	 *   but LLITOUT was broken on the machine I tried it on.
+	 */
+	case 2:		/* Un-raw mode used by sz, sb when -g detected */
+		if(!did0) {
+#ifdef TIOCEXCL
+			ioctl(iofd, TIOCEXCL, 0);
+#endif
+			ioctl(iofd, TIOCGETP, &oldtty);
+			ioctl(iofd, TIOCGETC, (struct sgttyb *) &oldtch);
+#ifdef LLITOUT
+			ioctl(iofd, TIOCLGET, &Locmode);
+#endif
+		}
+		tty = oldtty;
+		tch = oldtch;
+#ifdef READCHECK
+		tch.t_intrc = Zmodem ? -1:030;	/* Interrupt char */
+#else
+		tch.t_intrc = Zmodem ? 03:030;	/* Interrupt char */
+#endif
+#ifdef ODDP
+		tty.sg_flags |= ODDP;
+#endif
+#ifdef EVENP
+		tty.sg_flags |= EVENP;
+#endif
+#ifdef CBREAK
+		tty.sg_flags |= CBREAK;
+#endif
+#ifdef ALLDELAY
+		tty.sg_flags &= ~ALLDELAY;
+#endif
+#ifdef CRMOD
+		tty.sg_flags &= ~CRMOD;
+#endif
+#ifdef ECHO
+		tty.sg_flags &= ~ECHO;
+#endif
+#ifdef LCASE
+		tty.sg_flags &= ~LCASE;
+#endif
+
+		ioctl(iofd, TIOCSETP, &tty);
+		ioctl(iofd, TIOCSETC, (struct sgttyb *) &tch);
+#ifdef LLITOUT
+		ioctl(iofd, TIOCLBIS, &Locbit);
+#endif
+		bibi(99);	/* un-raw doesn't work w/o lit out */
+		did0 = TRUE;
+		return OK;
+	case 1:
+	case 3:
+		if(!did0) {
+#ifdef TIOCEXCL
+			ioctl(iofd, TIOCEXCL, 0);
+#endif
+			ioctl(iofd, TIOCGETP, &oldtty);
+			ioctl(iofd, TIOCGETC, (struct sgttyb *) &oldtch);
+#ifdef LLITOUT
+			ioctl(iofd, TIOCLGET, &Locmode);
+#endif
+		}
+		tty = oldtty;
+		tty.sg_flags |= RAW;
+		tty.sg_flags &= ~ECHO;
+		ioctl(iofd, TIOCSETP, &tty);
+		did0 = TRUE;
+		Baudrate = getspeed(tty.sg_ospeed);
+		return OK;
+#endif
+	case 0:
+		if(!did0)
+			return ERROR;
+#ifdef POSIX
+		/* Wait for output to drain, flush input queue, restore
+		 * modes and restart output.
+		 */
+		(void) tcsetattr(iofd, TCSAFLUSH, &oldtty);
+		(void) tcflow(iofd, TCOON);
+#endif
+#ifdef USG
+		(void) ioctl(iofd, TCSBRK, 1);	/* Wait for output to drain */
+		(void) ioctl(iofd, TCFLSH, 1);	/* Flush input queue */
+		(void) ioctl(iofd, TCSETAW, &oldtty);	/* Restore modes */
+		(void) ioctl(iofd, TCXONC,1);	/* Restart output */
+#endif
+#ifdef V7
+		ioctl(iofd, TIOCSETP, &oldtty);
+		ioctl(iofd, TIOCSETC, (struct sgttyb *) &oldtch);
+#ifdef TIOCNXCL
+		ioctl(iofd, TIOCNXCL, 0);
+#endif
+#ifdef LLITOUT
+		ioctl(iofd, TIOCLSET, &Locmode);
+#endif
+#endif
+
+		return OK;
+	default:
+		return ERROR;
+	}
+}
+
+void sendbrk()
+{
+#ifdef POSIX
+	tcsendbreak(iofd, 1);
+#endif
+#ifdef V7
+#ifdef TIOCSBRK
+#define CANBREAK
+	sleep(1);
+	ioctl(iofd, TIOCSBRK, 0);
+	sleep(1);
+	ioctl(iofd, TIOCCBRK, 0);
+#endif
+#endif
+#ifdef USG
+#define CANBREAK
+	ioctl(iofd, TCSBRK, 0);
+#endif
+}
+
+/* End of rbsb.c */
Index: /trunk/minix/commands/zmodem/rz.c
===================================================================
--- /trunk/minix/commands/zmodem/rz.c	(revision 9)
+++ /trunk/minix/commands/zmodem/rz.c	(revision 9)
@@ -0,0 +1,1549 @@
+#define VERSION "2.03 05-17-88"
+#define PUBDIR "/usr/spool/uucppublic"
+
+/*% cc -compat -M2 -Ox -K -i -DMD -DOMEN % -o rz; size rz;
+<-xtx-*> cc386 -Ox -DMD -DOMEN -DSEGMENTS=8 rz.c -o $B/rz;  size $B/rz
+ *
+ * rz.c By Chuck Forsberg
+ *
+ *	cc -O rz.c -o rz		USG (3.0) Unix
+ * 	cc -O -DV7  rz.c -o rz		Unix V7, BSD 2.8 - 4.3
+ *
+ *	ln rz rb;  ln rz rx			For either system
+ *
+ *	ln rz /usr/bin/rzrmail		For remote mail.  Make this the
+ *					login shell. rzrmail then calls
+ *					rmail(1) to deliver mail.
+ *
+ * To compile on VMS:
+ *
+ *	define LNK$LIBRARY   SYS$LIBRARY:VAXCRTL.OLB
+ *	cc rz.c
+ *	cc vvmodem.c
+ *	link rz,vvmodem
+ *	rz :== $disk:[username.subdir]rz.exe
+ *
+ *
+ *  Unix is a trademark of Western Electric Company
+ *
+ * A program for Unix to receive files and commands from computers running
+ *  Professional-YAM, PowerCom, YAM, IMP, or programs supporting XMODEM.
+ *  rz uses Unix buffered input to reduce wasted CPU time.
+ *
+ * Iff the program is invoked by rzCOMMAND, output is piped to 
+ * "COMMAND filename"  (Unix only)
+ *
+ *  Some systems (Venix, Coherent, Regulus) may not support tty raw mode
+ *  read(2) the same way as Unix. ONEREAD must be defined to force one
+ *  character reads for these systems. Added 7-01-84 CAF
+ *
+ *  Alarm signal handling changed to work with 4.2 BSD 7-15-84 CAF 
+ *
+ *  BIX added 6-30-87 to support BIX(TM) upload protocol used by the
+ *  Byte Information Exchange.
+ *
+ *  NFGVMIN Updated 2-18-87 CAF for Xenix systems where c_cc[VMIN]
+ *  doesn't work properly (even though it compiles without error!),
+ *
+ *  SEGMENTS=n added 2-21-88 as a model for CP/M programs
+ *    for CP/M-80 systems that cannot overlap modem and disk I/O.
+ *
+ *  VMS flavor hacks begin with rz version 2.00
+ *
+ *  -DMD may be added to compiler command line to compile in
+ *    Directory-creating routines from Public Domain TAR by John Gilmore
+ *
+ *  HOWMANY may be tuned for best performance
+ *
+ *  USG UNIX (3.0) ioctl conventions courtesy  Jeff Martin
+ */
+
+#include <sys/types.h>
+
+#ifdef vax11c
+#include <types.h>
+#include <stat.h>
+#define LOGFILE "rzlog.tmp"
+#define OS "VMS"
+#define BUFREAD
+extern int errno;
+#define SS_NORMAL SS$_NORMAL
+#else
+/* Not vax11c */
+#define SS_NORMAL 0
+#define LOGFILE "/tmp/rzlog"
+#endif
+
+#include <time.h>
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utime.h>
+#include <stdio.h>
+
+#define OK 0
+#define FALSE 0
+#define TRUE 1
+#undef ERROR
+#define ERROR (-1)
+
+
+_PROTOTYPE(long getfree , (void));
+_PROTOTYPE(void alrm , (int sig ));
+_PROTOTYPE(int main , (int argc , char *argv []));
+_PROTOTYPE(int usage , (void));
+_PROTOTYPE(int wcreceive , (int argc , char **argp ));
+_PROTOTYPE(int wcrxpn , (char *rpn ));
+_PROTOTYPE(int wcrx , (void));
+_PROTOTYPE(int wcgetsec , (char *rxbuf , int maxtime ));
+_PROTOTYPE(int readline , (int timeout ));
+_PROTOTYPE(void purgeline , (void));
+_PROTOTYPE(int procheader , (char *name ));
+_PROTOTYPE(int make_dirs , (char *pathname ));
+_PROTOTYPE(int makedir , (char *dpath , int dmode ));
+_PROTOTYPE(int putsec , (char *buf , int n ));
+_PROTOTYPE(void sendline , (int c ));
+_PROTOTYPE(void flushmo , (void));
+_PROTOTYPE(void uncaps , (char *s ));
+_PROTOTYPE(int IsAnyLower , (char *s ));
+_PROTOTYPE(char *substr , (char *s , char *t ));
+void zperr();
+_PROTOTYPE(void canit , (void));
+_PROTOTYPE(void report , (int sct ));
+_PROTOTYPE(void chkinvok , (char *s ));
+_PROTOTYPE(void checkpath , (char *name ));
+_PROTOTYPE(int tryz , (void));
+_PROTOTYPE(int rzfiles , (void));
+_PROTOTYPE(int rzfile , (void));
+_PROTOTYPE(void zmputs , (char *s ));
+_PROTOTYPE(int closeit , (void));
+_PROTOTYPE(void ackbibi , (void));
+_PROTOTYPE(void bttyout , (int c ));
+_PROTOTYPE(int sys2 , (char *s ));
+_PROTOTYPE(void exec2 , (char *s ));
+
+/*
+ * Max value for HOWMANY is 255.
+ *   A larger value reduces system overhead but may evoke kernel bugs.
+ *   133 corresponds to an XMODEM/CRC sector
+ */
+#ifndef HOWMANY
+#define HOWMANY 133
+#endif
+
+/* Ward Christensen / CP/M parameters - Don't change these! */
+#define ENQ 005
+#define CAN ('X'&037)
+#define XOFF ('s'&037)
+#define XON ('q'&037)
+#define SOH 1
+#define STX 2
+#define EOT 4
+#define ACK 6
+#define NAK 025
+#define CPMEOF 032
+#define WANTCRC 0103	/* send C not NAK to get crc not checksum */
+#define TIMEOUT (-2)
+#define RCDO (-3)
+#define ERRORMAX 5
+#define RETRYMAX 5
+#define WCEOT (-10)
+#define PATHLEN 257	/* ready for 4.2 bsd ? */
+#define UNIXFILE 0xF000	/* The S_IFMT file mask bit for stat */
+
+int Zmodem=0;		/* ZMODEM protocol requested */
+int Nozmodem = 0;	/* If invoked as "rb" */
+unsigned Baudrate = 2400;
+
+#ifdef vax11c
+#include "vrzsz.c"	/* most of the system dependent stuff here */
+#else
+#include "rbsb.c"	/* most of the system dependent stuff here */
+#endif
+
+#include "crctab.c"
+
+FILE *fout;
+
+/*
+ * Routine to calculate the free bytes on the current file system
+ *  ~0 means many free bytes (unknown)
+ */
+long getfree()
+{
+	return(~0L);	/* many free bytes ... */
+}
+
+int Lastrx;
+int Crcflg;
+int Firstsec;
+int Eofseen;		/* indicates cpm eof (^Z) has been received */
+int errors;
+int Restricted=0;	/* restricted; no /.. or ../ in filenames */
+#ifdef ONEREAD
+/* Sorry, Regulus and some others don't work right in raw mode! */
+int Readnum = 1;	/* Number of bytes to ask for in read() from modem */
+#else
+int Readnum = HOWMANY;	/* Number of bytes to ask for in read() from modem */
+#endif
+
+#define DEFBYTL 2000000000L	/* default rx file size */
+long Bytesleft;		/* number of bytes of incoming file left */
+long Modtime;		/* Unix style mod time for incoming file */
+int Filemode;		/* Unix style mode for incoming file */
+char Pathname[PATHLEN];
+char *Progname;		/* the name by which we were called */
+
+int Batch=0;
+int Topipe=0;
+int MakeLCPathname=TRUE;	/* make received pathname lower case */
+int Verbose=0;
+int Quiet=0;		/* overrides logic that would otherwise set verbose */
+int Nflag = 0;		/* Don't really transfer files */
+int Rxclob=FALSE;	/* Clobber existing file */
+int Rxbinary=FALSE;	/* receive all files in bin mode */
+int Rxascii=FALSE;	/* receive files in ascii (translate) mode */
+int Thisbinary;		/* current file is to be received in bin mode */
+int Blklen;		/* record length of received packets */
+
+#ifdef SEGMENTS
+int chinseg = 0;	/* Number of characters received in this data seg */
+char secbuf[1+(SEGMENTS+1)*1024];
+#else
+char secbuf[1025];
+#endif
+
+
+char linbuf[HOWMANY];
+int Lleft=0;		/* number of characters in linbuf */
+time_t timep[2];
+char Lzmanag;		/* Local file management request */
+char zconv;		/* ZMODEM file conversion request */
+char zmanag;		/* ZMODEM file management request */
+char ztrans;		/* ZMODEM file transport request */
+int Zctlesc;		/* Encode control characters */
+int Zrwindow = 1400;	/* RX window size (controls garbage count) */
+
+jmp_buf tohere;		/* For the interrupt on RX timeout */
+
+#define xsendline(c) sendline(c)
+#include "zm.c"
+
+int tryzhdrtype=ZRINIT;	/* Header type to send corresponding to Last rx close */
+
+void alrm(sig)
+int sig;
+{
+	longjmp(tohere, -1);
+}
+
+/* called by signal interrupt or terminate to clean things up */
+void bibi(n)
+int n;
+{
+	if (Zmodem)
+		zmputs(Attn);
+	canit(); mode(0);
+	fprintf(stderr, "rz: caught signal %d; exiting\n", n);
+	cucheck();
+	exit(128+n);
+}
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+	register char *cp;
+	register npats;
+	char *virgin, **patts;
+	int exitcode = 0;
+
+	Rxtimeout = 100;
+	setbuf(stderr, (char *)NULL);
+	if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
+		Restricted=TRUE;
+
+	from_cu();
+#ifdef vax11c
+	Progname = virgin = "rz";
+#else
+	chkinvok(virgin=argv[0]);	/* if called as [-]rzCOMMAND set flag */
+#endif
+	npats = 0;
+	while (--argc) {
+		cp = *++argv;
+		if (*cp == '-') {
+			while( *++cp) {
+				switch(*cp) {
+				case '\\':
+					 cp[1] = toupper(cp[1]);  continue;
+				case '+':
+					Lzmanag = ZMAPND; break;
+				case 'a':
+					Rxascii=TRUE;  break;
+				case 'b':
+					Rxbinary=TRUE; break;
+				case 'c':
+					Crcflg=TRUE; break;
+#ifndef vax11c
+				case 'D':
+					Nflag = TRUE; break;
+#endif
+				case 'e':
+					Zctlesc = 1; break;
+				case 'p':
+					Lzmanag = ZMPROT;  break;
+				case 'q':
+					Quiet=TRUE; Verbose=0; break;
+				case 't':
+					if (--argc < 1) {
+						usage();
+					}
+					Rxtimeout = atoi(*++argv);
+					if (Rxtimeout<10 || Rxtimeout>1000)
+						usage();
+					break;
+				case 'w':
+					if (--argc < 1) {
+						usage();
+					}
+					Zrwindow = atoi(*++argv);
+					break;
+				case 'u':
+					MakeLCPathname=FALSE; break;
+				case 'v':
+					++Verbose; break;
+				case 'y':
+					Rxclob=TRUE; break;
+				default:
+					usage();
+				}
+			}
+		}
+		else if ( !npats && argc>0) {
+			if (argv[0][0]) {
+				npats=argc;
+				patts=argv;
+			}
+		}
+	}
+	if (npats > 1)
+		usage();
+	if (Batch && npats)
+		usage();
+	if (Verbose) {
+		if (freopen(LOGFILE, "a", stderr)==NULL) {
+			printf("Can't open log file %s\n",LOGFILE);
+			exit(0200);
+		}
+		setbuf(stderr, (char *)NULL);
+		fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname);
+	}
+	if (Fromcu && !Quiet) {
+		if (Verbose == 0)
+			Verbose = 2;
+	}
+	vfile("%s %s for %s\n", Progname, VERSION, OS);
+	mode(1);
+	if (signal(SIGINT, bibi) == SIG_IGN) {
+		signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
+	}
+	else {
+		signal(SIGINT, bibi); signal(SIGKILL, bibi);
+	}
+	signal(SIGTERM, bibi);
+	if (wcreceive(npats, patts)==ERROR) {
+		exitcode=0200;
+		canit();
+	}
+	mode(0);
+	vfile("exitcode = %d\n",exitcode);
+	if (exitcode && !Zmodem)	/* bellow again with all thy might. */
+		canit();
+	if (exitcode)
+		cucheck();
+	if (Verbose) putc('\n', stderr);
+	exit(exitcode ? exitcode:SS_NORMAL);
+}
+
+
+int usage()
+{
+	cucheck();
+#ifdef vax11c
+	fprintf(stderr,"Usage:	rz [-abeuvy]\n");
+#else
+	fprintf(stderr,"Usage:	rz [-abeuvy]		(ZMODEM)\n");
+	fprintf(stderr,"or	rb [-abuvy]		(YMODEM)\n");
+	fprintf(stderr,"or	rx [-abcv] file	(XMODEM or XMODEM-1k)\n");
+#endif
+	fprintf(stderr,"	  -a ASCII transfer (strip CR)\n");
+	fprintf(stderr,"	  -b Binary transfer for all files\n");
+#ifndef vax11c
+	fprintf(stderr,"	  -c Use 16 bit CRC	(XMODEM)\n");
+#endif
+	fprintf(stderr,"	  -e Escape control characters	(ZMODEM)\n");
+	fprintf(stderr,"	  -v Verbose more v's give more info\n");
+	fprintf(stderr,"	  -y Yes, clobber existing file if any\n");
+	fprintf(stderr,"%s %s for %s by Chuck Forsberg, Omen Technology INC\n",
+	  Progname, VERSION, OS);
+	fprintf(stderr, "\t\t\042The High Reliability Software\042\n");
+	exit(SS_NORMAL);
+}
+/*
+ *  Debugging information output interface routine
+ */
+/* VARARGS1 */
+void vfile(f, a, b, c)
+register char *f,*a,*b,*c;
+
+{
+	if (Verbose > 2) {
+		fprintf(stderr, f, a, b, c);
+		fprintf(stderr, "\n");
+	}
+}
+
+/*
+ * Let's receive something already.
+ */
+
+char *rbmsg =
+"%s ready. To begin transfer, type \"%s file ...\" to your modem program\r\n\n";
+
+int wcreceive(argc, argp)
+int argc;
+char **argp;
+{
+	register c;
+
+	if (Batch || argc==0) {
+		Crcflg=1;
+		if ( !Quiet)
+			fprintf(stderr, rbmsg, Progname, Nozmodem?"sb":"sz");
+		if (c=tryz()) {
+			if (c == ZCOMPL)
+				return OK;
+			if (c == ERROR)
+				goto fubar;
+			c = rzfiles();
+			if (c)
+				goto fubar;
+		} else {
+			for (;;) {
+				if (wcrxpn(secbuf)== ERROR)
+					goto fubar;
+				if (secbuf[0]==0)
+					return OK;
+				if (procheader(secbuf) == ERROR)
+					goto fubar;
+				if (wcrx()==ERROR)
+					goto fubar;
+			}
+		}
+	} else {
+		Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
+
+		procheader(""); strcpy(Pathname, *argp); checkpath(Pathname);
+		fprintf(stderr, "\nrz: ready to receive %s\r\n", Pathname);
+		if ((fout=fopen(Pathname, "w")) == NULL)
+			return ERROR;
+		if (wcrx()==ERROR)
+			goto fubar;
+	}
+	return OK;
+fubar:
+	canit();
+#ifndef vax11c
+	if (Topipe && fout) {
+		pclose(fout);  return ERROR;
+	}
+#endif
+	if (fout)
+		fclose(fout);
+#ifndef vax11c
+	if (Restricted) {
+		unlink(Pathname);
+		fprintf(stderr, "\r\nrz: %s removed.\r\n", Pathname);
+	}
+#endif
+	return ERROR;
+}
+
+
+/*
+ * Fetch a pathname from the other end as a C ctyle ASCIZ string.
+ * Length is indeterminate as long as less than Blklen
+ * A null string represents no more files (YMODEM)
+ */
+int wcrxpn(rpn)
+char *rpn;	/* receive a pathname */
+{
+	register c;
+
+#ifdef NFGVMIN
+	readline(1);
+#else
+	purgeline();
+#endif
+
+et_tu:
+	Firstsec=TRUE;  Eofseen=FALSE;
+	sendline(Crcflg?WANTCRC:NAK);
+	Lleft=0;	/* Do read next time ... */
+	while ((c = wcgetsec(rpn, 100)) != 0) {
+		if (c == WCEOT) {
+			zperr( "Pathname fetch returned %d", c);
+			sendline(ACK);
+			Lleft=0;	/* Do read next time ... */
+			readline(1);
+			goto et_tu;
+		}
+		return ERROR;
+	}
+	sendline(ACK);
+	return OK;
+}
+
+/*
+ * Adapted from CMODEM13.C, written by
+ * Jack M. Wierda and Roderick W. Hart
+ */
+
+int wcrx()
+{
+	register int sectnum, sectcurr;
+	register char sendchar;
+	int cblklen;			/* bytes to dump this block */
+
+	Firstsec=TRUE;sectnum=0; Eofseen=FALSE;
+	sendchar=Crcflg?WANTCRC:NAK;
+
+	for (;;) {
+		sendline(sendchar);	/* send it now, we're ready! */
+		Lleft=0;	/* Do read next time ... */
+		sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130);
+		report(sectcurr);
+		if (sectcurr==((sectnum+1) &0377)) {
+			sectnum++;
+			cblklen = Bytesleft>Blklen ? Blklen:Bytesleft;
+			if (putsec(secbuf, cblklen)==ERROR)
+				return ERROR;
+			if ((Bytesleft-=cblklen) < 0)
+				Bytesleft = 0;
+			sendchar=ACK;
+		}
+		else if (sectcurr==(sectnum&0377)) {
+			zperr( "Received dup Sector");
+			sendchar=ACK;
+		}
+		else if (sectcurr==WCEOT) {
+			if (closeit())
+				return ERROR;
+			sendline(ACK);
+			Lleft=0;	/* Do read next time ... */
+			return OK;
+		}
+		else if (sectcurr==ERROR)
+			return ERROR;
+		else {
+			zperr( "Sync Error");
+			return ERROR;
+		}
+	}
+}
+
+/*
+ * Wcgetsec fetches a Ward Christensen type sector.
+ * Returns sector number encountered or ERROR if valid sector not received,
+ * or CAN CAN received
+ * or WCEOT if eot sector
+ * time is timeout for first char, set to 4 seconds thereafter
+ ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
+ *    (Caller must do that when he is good and ready to get next sector)
+ */
+
+int wcgetsec(rxbuf, maxtime)
+char *rxbuf;
+int maxtime;
+{
+	register checksum, wcj, firstch;
+	register unsigned short oldcrc;
+	register char *p;
+	int sectcurr;
+
+	for (Lastrx=errors=0; errors<RETRYMAX; errors++) {
+
+		if ((firstch=readline(maxtime))==STX) {
+			Blklen=1024; goto get2;
+		}
+		if (firstch==SOH) {
+			Blklen=128;
+get2:
+			sectcurr=readline(1);
+			if ((sectcurr+(oldcrc=readline(1)))==0377) {
+				oldcrc=checksum=0;
+				for (p=rxbuf,wcj=Blklen; --wcj>=0; ) {
+					if ((firstch=readline(1)) < 0)
+						goto bilge;
+					oldcrc=updcrc(firstch, oldcrc);
+					checksum += (*p++ = firstch);
+				}
+				if ((firstch=readline(1)) < 0)
+					goto bilge;
+				if (Crcflg) {
+					oldcrc=updcrc(firstch, oldcrc);
+					if ((firstch=readline(1)) < 0)
+						goto bilge;
+					oldcrc=updcrc(firstch, oldcrc);
+					if (oldcrc & 0xFFFF)
+						zperr( "CRC");
+					else {
+						Firstsec=FALSE;
+						return sectcurr;
+					}
+				}
+				else if (((checksum-firstch)&0377)==0) {
+					Firstsec=FALSE;
+					return sectcurr;
+				}
+				else
+					zperr( "Checksum");
+			}
+			else
+				zperr("Sector number garbled");
+		}
+		/* make sure eot really is eot and not just mixmash */
+#ifdef NFGVMIN
+		else if (firstch==EOT && readline(1)==TIMEOUT)
+			return WCEOT;
+#else
+		else if (firstch==EOT && Lleft==0)
+			return WCEOT;
+#endif
+		else if (firstch==CAN) {
+			if (Lastrx==CAN) {
+				zperr( "Sender CANcelled");
+				return ERROR;
+			} else {
+				Lastrx=CAN;
+				continue;
+			}
+		}
+		else if (firstch==TIMEOUT) {
+			if (Firstsec)
+				goto humbug;
+bilge:
+			zperr( "TIMEOUT");
+		}
+		else
+			zperr( "Got 0%o sector header", firstch);
+
+humbug:
+		Lastrx=0;
+		while(readline(1)!=TIMEOUT)
+			;
+		if (Firstsec) {
+			sendline(Crcflg?WANTCRC:NAK);
+			Lleft=0;	/* Do read next time ... */
+		} else {
+			maxtime=40; sendline(NAK);
+			Lleft=0;	/* Do read next time ... */
+		}
+	}
+	/* try to stop the bubble machine. */
+	canit();
+	return ERROR;
+}
+
+#ifndef vax11c
+/*
+ * This version of readline is reasoably well suited for
+ * reading many characters.
+ *  (except, currently, for the Regulus version!)
+ *
+ * timeout is in tenths of seconds
+ */
+int readline(timeout)
+int timeout;
+{
+	register n;
+	static char *cdq;	/* pointer for removing chars from linbuf */
+
+	if (--Lleft >= 0) {
+		if (Verbose > 8) {
+			fprintf(stderr, "%02x ", *cdq&0377);
+		}
+		return (*cdq++ & 0377);
+	}
+	n = timeout/10;
+	if (n < 2)
+		n = 3;
+	if (Verbose > 5)
+		fprintf(stderr, "Calling read: alarm=%d  Readnum=%d ",
+		  n, Readnum);
+	if (setjmp(tohere)) {
+#ifdef TIOCFLUSH
+/*		ioctl(iofd, TIOCFLUSH, 0); */
+#endif
+		Lleft = 0;
+		if (Verbose>1)
+			fprintf(stderr, "Readline:TIMEOUT\n");
+		return TIMEOUT;
+	}
+	signal(SIGALRM, alrm); alarm(n);
+	Lleft=read(iofd, cdq=linbuf, Readnum);
+	alarm(0);
+	if (Verbose > 5) {
+		fprintf(stderr, "Read returned %d bytes\n", Lleft);
+	}
+	if (Lleft < 1)
+		return TIMEOUT;
+	--Lleft;
+	if (Verbose > 8) {
+		fprintf(stderr, "%02x ", *cdq&0377);
+	}
+	return (*cdq++ & 0377);
+}
+
+
+
+/*
+ * Purge the modem input queue of all characters
+ */
+void purgeline()
+{
+	Lleft = 0;
+#ifdef USG
+	ioctl(iofd, TCFLSH, 0);
+#else
+	lseek(iofd, 0L, 2);
+#endif
+}
+#endif
+
+
+/*
+ * Process incoming file information header
+ */
+int procheader(name)
+char *name;
+{
+	register char *openmode, *p;
+
+	/* set default parameters and overrides */
+	openmode = "w";
+	Thisbinary = (!Rxascii) || Rxbinary;
+	if (Lzmanag)
+		zmanag = Lzmanag;
+
+	/*
+	 *  Process ZMODEM remote file management requests
+	 */
+	if (!Rxbinary && zconv == ZCNL)	/* Remote ASCII override */
+		Thisbinary = 0;
+	if (zconv == ZCBIN)	/* Remote Binary override */
+		Thisbinary = TRUE;
+	else if (zmanag == ZMAPND)
+		openmode = "a";
+
+#ifndef BIX
+	/* Check for existing file */
+	if (!Rxclob && (zmanag&ZMMASK) != ZMCLOB && (fout=fopen(name, "r"))) {
+		fclose(fout);  return ERROR;
+	}
+#endif
+
+	Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
+
+	p = name + 1 + strlen(name);
+	if (*p) {	/* file coming from Unix or DOS system */
+		sscanf(p, "%ld%lo%o", &Bytesleft, &Modtime, &Filemode);
+#ifndef vax11c
+		if (Filemode & UNIXFILE)
+			++Thisbinary;
+#endif
+		if (Verbose) {
+			fprintf(stderr,  "\nIncoming: %s %ld %lo %o\n",
+			  name, Bytesleft, Modtime, Filemode);
+		}
+	}
+
+#ifdef BIX
+	if ((fout=fopen("scratchpad", openmode)) == NULL)
+		return ERROR;
+	return OK;
+#else
+
+	else {		/* File coming from CP/M system */
+		for (p=name; *p; ++p)		/* change / to _ */
+			if ( *p == '/')
+				*p = '_';
+
+		if ( *--p == '.')		/* zap trailing period */
+			*p = 0;
+	}
+
+#ifndef vax11c
+	if (!Zmodem && MakeLCPathname && !IsAnyLower(name)
+	  && !(Filemode&UNIXFILE))
+		uncaps(name);
+#endif
+	if (Topipe > 0) {
+		sprintf(Pathname, "%s %s", Progname+2, name);
+		if (Verbose)
+			fprintf(stderr,  "Topipe: %s %s\n",
+			  Pathname, Thisbinary?"BIN":"ASCII");
+#ifndef vax11c
+		if ((fout=popen(Pathname, "w")) == NULL)
+			return ERROR;
+#endif
+	} else {
+		strcpy(Pathname, name);
+		if (Verbose) {
+			fprintf(stderr,  "Receiving %s %s %s\n",
+			  name, Thisbinary?"BIN":"ASCII", openmode);
+		}
+		checkpath(name);
+		if (Nflag)
+			name = "/dev/null";
+#ifndef vax11c
+#ifdef OMEN
+		if (name[0] == '!' || name[0] == '|') {
+			if ( !(fout = popen(name+1, "w"))) {
+				return ERROR;
+			}
+			Topipe = -1;  return(OK);
+		}
+#endif
+#endif
+#ifdef MD
+		fout = fopen(name, openmode);
+		if ( !fout)
+			if (make_dirs(name))
+				fout = fopen(name, openmode);
+#else
+		fout = fopen(name, openmode);
+#endif
+		if ( !fout)
+			return ERROR;
+	}
+	return OK;
+#endif /* BIX */
+}
+
+#ifdef MD
+/*
+ *  Directory-creating routines from Public Domain TAR by John Gilmore
+ */
+
+/*
+ * After a file/link/symlink/dir creation has failed, see if
+ * it's because some required directory was not present, and if
+ * so, create all required dirs.
+ */
+int make_dirs(pathname)
+register char *pathname;
+{
+	register char *p;		/* Points into path */
+	int madeone = 0;		/* Did we do anything yet? */
+	int save_errno = errno;		/* Remember caller's errno */
+	char *strchr();
+
+	if (errno != ENOENT)
+		return 0;		/* Not our problem */
+
+	for (p = strchr(pathname, '/'); p != NULL; p = strchr(p+1, '/')) {
+		/* Avoid mkdir of empty string, if leading or double '/' */
+		if (p == pathname || p[-1] == '/')
+			continue;
+		/* Avoid mkdir where last part of path is '.' */
+		if (p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))
+			continue;
+		*p = 0;				/* Truncate the path there */
+		if ( !makedir(pathname, 0777)) {	/* Try to create it as a dir */
+			vfile("Made directory %s\n", pathname);
+			madeone++;		/* Remember if we made one */
+			*p = '/';
+			continue;
+		}
+		*p = '/';
+		if (errno == EEXIST)		/* Directory already exists */
+			continue;
+		/*
+		 * Some other error in the makedir.  We return to the caller.
+		 */
+		break;
+	}
+	errno = save_errno;		/* Restore caller's errno */
+	return madeone;			/* Tell them to retry if we made one */
+}
+
+#if (MD != 2)
+#define	TERM_SIGNAL(status)	((status) & 0x7F)
+#define TERM_COREDUMP(status)	(((status) & 0x80) != 0)
+#define TERM_VALUE(status)	((status) >> 8)
+/*
+ * Make a directory.  Compatible with the mkdir() system call on 4.2BSD.
+ */
+int makedir(dpath, dmode)
+char *dpath;
+int dmode;
+{
+	int cpid, status;
+	struct stat statbuf;
+
+	if (stat(dpath,&statbuf) == 0) {
+		errno = EEXIST;		/* Stat worked, so it already exists */
+		return -1;
+	}
+
+	/* If stat fails for a reason other than non-existence, return error */
+	if (errno != ENOENT) return -1; 
+
+	switch (cpid = fork()) {
+
+	case -1:			/* Error in fork() */
+		return(-1);		/* Errno is set already */
+
+	case 0:				/* Child process */
+		/*
+		 * Cheap hack to set mode of new directory.  Since this
+		 * child process is going away anyway, we zap its umask.
+		 * FIXME, this won't suffice to set SUID, SGID, etc. on this
+		 * directory.  Does anybody care?
+		 */
+		status = umask(0);	/* Get current umask */
+		status = umask(status | (0777 & ~dmode)); /* Set for mkdir */
+		execl("/bin/mkdir", "mkdir", dpath, (char *)0);
+		_exit(-1);		/* Can't exec /bin/mkdir */
+	
+	default:			/* Parent process */
+		while (cpid != wait(&status)) ;	/* Wait for kid to finish */
+	}
+
+	if (TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0) {
+		errno = EIO;		/* We don't know why, but */
+		return -1;		/* /bin/mkdir failed */
+	}
+
+	return 0;
+}
+#endif /* MD != 2 */
+#endif /* MD */
+
+/*
+ * Putsec writes the n characters of buf to receive file fout.
+ *  If not in binary mode, carriage returns, and all characters
+ *  starting with CPMEOF are discarded.
+ */
+int putsec(buf, n)
+char *buf;
+register int n;
+{
+	register char *p;
+
+	if (n == 0)
+		return OK;
+	if (Thisbinary) {
+		for (p=buf; --n>=0; )
+			putc( *p++, fout);
+	}
+	else {
+		if (Eofseen)
+			return OK;
+		for (p=buf; --n>=0; ++p ) {
+			if ( *p == '\r')
+				continue;
+			if (*p == CPMEOF) {
+				Eofseen=TRUE; return OK;
+			}
+			putc(*p ,fout);
+		}
+	}
+	return OK;
+}
+
+#ifndef vax11c
+/*
+ *  Send a character to modem.  Small is beautiful.
+ */
+void sendline(c)
+int c;
+{
+	char d;
+
+	d = c;
+	if (Verbose>6)
+		fprintf(stderr, "Sendline: %x\n", c);
+	write(1, &d, 1);
+}
+
+void flushmo() {}
+#endif
+
+
+
+
+
+/* make string s lower case */
+void uncaps(s)
+register char *s;
+{
+	for ( ; *s; ++s)
+		if (isupper(*s))
+			*s = tolower(*s);
+}
+/*
+ * IsAnyLower returns TRUE if string s has lower case letters.
+ */
+int IsAnyLower(s)
+register char *s;
+{
+	for ( ; *s; ++s)
+		if (islower(*s))
+			return TRUE;
+	return FALSE;
+}
+
+/*
+ * substr(string, token) searches for token in string s
+ * returns pointer to token within string if found, NULL otherwise
+ */
+char *
+substr(s, t)
+register char *s,*t;
+{
+	register char *ss,*tt;
+	/* search for first char of token */
+	for (ss=s; *s; s++)
+		if (*s == *t)
+			/* compare token with substring */
+			for (ss=s,tt=t; ;) {
+				if (*tt == 0)
+					return s;
+				if (*ss++ != *tt++)
+					break;
+			}
+	return (char *)NULL;
+}
+
+/*
+ * Log an error
+ */
+/*VARARGS1*/
+void zperr(s,p,u)
+char *s, *p, *u;
+{
+	if (Verbose <= 0)
+		return;
+	fprintf(stderr, "Retry %d: ", errors);
+	fprintf(stderr, s, p, u);
+	fprintf(stderr, "\n");
+}
+
+/* send cancel string to get the other end to shut up */
+void canit()
+{
+	static char canistr[] = {
+	 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
+	};
+
+#ifdef vax11c
+	raw_wbuf(strlen(canistr), canistr);
+	purgeline();
+#else
+	printf(canistr);
+	Lleft=0;	/* Do read next time ... */
+	fflush(stdout);
+#endif
+}
+
+
+void report(sct)
+int sct;
+{
+	if (Verbose>1)
+		fprintf(stderr,"%03d%c",sct,sct%10? ' ' : '\r');
+}
+
+#ifndef vax11c
+/*
+ * If called as [-][dir/../]vrzCOMMAND set Verbose to 1
+ * If called as [-][dir/../]rzCOMMAND set the pipe flag
+ * If called as rb use YMODEM protocol
+ */
+void chkinvok(s)
+char *s;
+{
+	register char *p;
+
+	p = s;
+	while (*p == '-')
+		s = ++p;
+	while (*p)
+		if (*p++ == '/')
+			s = p;
+	if (*s == 'v') {
+		Verbose=1; ++s;
+	}
+	Progname = s;
+	if (s[0]=='r' && s[1]=='z')
+		Batch = TRUE;
+	if (s[0]=='r' && s[1]=='b')
+		Batch = Nozmodem = TRUE;
+	if (s[2] && s[0]=='r' && s[1]=='b')
+		Topipe = 1;
+	if (s[2] && s[0]=='r' && s[1]=='z')
+		Topipe = 1;
+}
+#endif
+
+/*
+ * Totalitarian Communist pathname processing
+ */
+void checkpath(name)
+char *name;
+{
+	if (Restricted) {
+		if (fopen(name, "r") != NULL) {
+			canit();
+			fprintf(stderr, "\r\nrz: %s exists\n", name);
+			bibi(-1);
+		}
+		/* restrict pathnames to current tree or uucppublic */
+		if ( substr(name, "../")
+		 || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {
+			canit();
+			fprintf(stderr,"\r\nrz:\tSecurity Violation\r\n");
+			bibi(-1);
+		}
+	}
+}
+
+/*
+ * Initialize for Zmodem receive attempt, try to activate Zmodem sender
+ *  Handles ZSINIT frame
+ *  Return ZFILE if Zmodem filename received, -1 on error,
+ *   ZCOMPL if transaction finished,  else 0
+ */
+int tryz()
+{
+	register c, n;
+	register cmdzack1flg;
+
+	if (Nozmodem)		/* Check for "rb" program name */
+		return 0;
+
+
+	for (n=Zmodem?15:5; --n>=0; ) {
+		/* Set buffer length (0) and capability flags */
+#ifdef SEGMENTS
+		stohdr(SEGMENTS*1024L);
+#else
+		stohdr(0L);
+#endif
+#ifdef CANBREAK
+		Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
+#else
+		Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;
+#endif
+		if (Zctlesc)
+			Txhdr[ZF0] |= TESCCTL;
+		zshhdr(tryzhdrtype, Txhdr);
+		if (tryzhdrtype == ZSKIP)	/* Don't skip too far */
+			tryzhdrtype = ZRINIT;	/* CAF 8-21-87 */
+again:
+		switch (zgethdr(Rxhdr, 0)) {
+		case ZRQINIT:
+			continue;
+		case ZEOF:
+			continue;
+		case TIMEOUT:
+			continue;
+		case ZFILE:
+			zconv = Rxhdr[ZF0];
+			zmanag = Rxhdr[ZF1];
+			ztrans = Rxhdr[ZF2];
+			tryzhdrtype = ZRINIT;
+			c = zrdata(secbuf, 1024);
+			mode(3);
+			if (c == GOTCRCW)
+				return ZFILE;
+			zshhdr(ZNAK, Txhdr);
+			goto again;
+		case ZSINIT:
+			Zctlesc = TESCCTL & Rxhdr[ZF0];
+			if (zrdata(Attn, ZATTNLEN) == GOTCRCW) {
+				stohdr(1L);
+				zshhdr(ZACK, Txhdr);
+				goto again;
+			}
+			zshhdr(ZNAK, Txhdr);
+			goto again;
+		case ZFREECNT:
+			stohdr(getfree());
+			zshhdr(ZACK, Txhdr);
+			goto again;
+		case ZCOMMAND:
+#ifdef vax11c
+			return ERROR;
+#else
+			cmdzack1flg = Rxhdr[ZF0];
+			if (zrdata(secbuf, 1024) == GOTCRCW) {
+				if (cmdzack1flg & ZCACK1)
+					stohdr(0L);
+				else
+					stohdr((long)sys2(secbuf));
+				purgeline();	/* dump impatient questions */
+				do {
+					zshhdr(ZCOMPL, Txhdr);
+				}
+				while (++errors<20 && zgethdr(Rxhdr,1) != ZFIN);
+				ackbibi();
+				if (cmdzack1flg & ZCACK1)
+					exec2(secbuf);
+				return ZCOMPL;
+			}
+			zshhdr(ZNAK, Txhdr); goto again;
+#endif
+		case ZCOMPL:
+			goto again;
+		default:
+			continue;
+		case ZFIN:
+			ackbibi(); return ZCOMPL;
+		case ZCAN:
+			return ERROR;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Receive 1 or more files with ZMODEM protocol
+ */
+int rzfiles()
+{
+	register c;
+
+	for (;;) {
+		switch (c = rzfile()) {
+		case ZEOF:
+		case ZSKIP:
+			switch (tryz()) {
+			case ZCOMPL:
+				return OK;
+			default:
+				return ERROR;
+			case ZFILE:
+				break;
+			}
+			continue;
+		default:
+			return c;
+		case ERROR:
+			return ERROR;
+		}
+	}
+}
+
+/*
+ * Receive a file with ZMODEM protocol
+ *  Assumes file name frame is in secbuf
+ */
+int rzfile()
+{
+	register c, n;
+	long rxbytes;
+
+	Eofseen=FALSE;
+	if (procheader(secbuf) == ERROR) {
+		return (tryzhdrtype = ZSKIP);
+	}
+
+	n = 20; rxbytes = 0l;
+
+	for (;;) {
+#ifdef SEGMENTS
+		chinseg = 0;
+#endif
+		stohdr(rxbytes);
+		zshhdr(ZRPOS, Txhdr);
+nxthdr:
+		switch (c = zgethdr(Rxhdr, 0)) {
+		default:
+			vfile("rzfile: zgethdr returned %d", c);
+			return ERROR;
+		case ZNAK:
+		case TIMEOUT:
+#ifdef SEGMENTS
+			putsec(secbuf, chinseg);
+			chinseg = 0;
+#endif
+			if ( --n < 0) {
+				vfile("rzfile: zgethdr returned %d", c);
+				return ERROR;
+			}
+		case ZFILE:
+			zrdata(secbuf, 1024);
+			continue;
+		case ZEOF:
+#ifdef SEGMENTS
+			putsec(secbuf, chinseg);
+			chinseg = 0;
+#endif
+			if (rclhdr(Rxhdr) != rxbytes) {
+				/*
+				 * Ignore eof if it's at wrong place - force
+				 *  a timeout because the eof might have gone
+				 *  out before we sent our zrpos.
+				 */
+				errors = 0;  goto nxthdr;
+			}
+			if (closeit()) {
+				tryzhdrtype = ZFERR;
+				vfile("rzfile: closeit returned <> 0");
+				return ERROR;
+			}
+			vfile("rzfile: normal EOF");
+			return c;
+		case ERROR:	/* Too much garbage in header search error */
+#ifdef SEGMENTS
+			putsec(secbuf, chinseg);
+			chinseg = 0;
+#endif
+			if ( --n < 0) {
+				vfile("rzfile: zgethdr returned %d", c);
+				return ERROR;
+			}
+			zmputs(Attn);
+			continue;
+		case ZSKIP:
+#ifdef SEGMENTS
+			putsec(secbuf, chinseg);
+			chinseg = 0;
+#endif
+			closeit();
+			vfile("rzfile: Sender SKIPPED file");
+			return c;
+		case ZDATA:
+			if (rclhdr(Rxhdr) != rxbytes) {
+				if ( --n < 0) {
+					return ERROR;
+				}
+#ifdef SEGMENTS
+				putsec(secbuf, chinseg);
+				chinseg = 0;
+#endif
+				zmputs(Attn);  continue;
+			}
+moredata:
+			if (Verbose>1)
+				fprintf(stderr, "\r%7ld ZMODEM%s    ",
+				  rxbytes, Crc32?" CRC-32":"");
+#ifdef SEGMENTS
+			if (chinseg >= (1024 * SEGMENTS)) {
+				putsec(secbuf, chinseg);
+				chinseg = 0;
+			}
+			switch (c = zrdata(secbuf+chinseg, 1024))
+#else
+			switch (c = zrdata(secbuf, 1024))
+#endif
+			{
+			case ZCAN:
+#ifdef SEGMENTS
+				putsec(secbuf, chinseg);
+				chinseg = 0;
+#endif
+				vfile("rzfile: zgethdr returned %d", c);
+				return ERROR;
+			case ERROR:	/* CRC error */
+#ifdef SEGMENTS
+				putsec(secbuf, chinseg);
+				chinseg = 0;
+#endif
+				if ( --n < 0) {
+					vfile("rzfile: zgethdr returned %d", c);
+					return ERROR;
+				}
+				zmputs(Attn);
+				continue;
+			case TIMEOUT:
+#ifdef SEGMENTS
+				putsec(secbuf, chinseg);
+				chinseg = 0;
+#endif
+				if ( --n < 0) {
+					vfile("rzfile: zgethdr returned %d", c);
+					return ERROR;
+				}
+				continue;
+			case GOTCRCW:
+				n = 20;
+#ifdef SEGMENTS
+				chinseg += Rxcount;
+				putsec(secbuf, chinseg);
+				chinseg = 0;
+#else
+				putsec(secbuf, Rxcount);
+#endif
+				rxbytes += Rxcount;
+				stohdr(rxbytes);
+				zshhdr(ZACK, Txhdr);
+				sendline(XON);
+				goto nxthdr;
+			case GOTCRCQ:
+				n = 20;
+#ifdef SEGMENTS
+				chinseg += Rxcount;
+#else
+				putsec(secbuf, Rxcount);
+#endif
+				rxbytes += Rxcount;
+				stohdr(rxbytes);
+				zshhdr(ZACK, Txhdr);
+				goto moredata;
+			case GOTCRCG:
+				n = 20;
+#ifdef SEGMENTS
+				chinseg += Rxcount;
+#else
+				putsec(secbuf, Rxcount);
+#endif
+				rxbytes += Rxcount;
+				goto moredata;
+			case GOTCRCE:
+				n = 20;
+#ifdef SEGMENTS
+				chinseg += Rxcount;
+#else
+				putsec(secbuf, Rxcount);
+#endif
+				rxbytes += Rxcount;
+				goto nxthdr;
+			}
+		}
+	}
+}
+
+/*
+ * Send a string to the modem, processing for \336 (sleep 1 sec)
+ *   and \335 (break signal)
+ */
+void zmputs(s)
+char *s;
+{
+	register c;
+
+	while (*s) {
+		switch (c = *s++) {
+		case '\336':
+			sleep(1); continue;
+		case '\335':
+			sendbrk(); continue;
+		default:
+			sendline(c);
+		}
+	}
+}
+
+/*
+ * Close the receive dataset, return OK or ERROR
+ */
+int closeit()
+{
+	time_t q;
+
+#ifndef vax11c
+	if (Topipe) {
+		if (pclose(fout)) {
+			return ERROR;
+		}
+		return OK;
+	}
+#endif
+	if (fclose(fout)==ERROR) {
+		fprintf(stderr, "file close ERROR\n");
+		return ERROR;
+	}
+#ifndef vax11c
+	if (Modtime) {
+		timep[0] = time(&q);
+		timep[1] = Modtime;
+		utime(Pathname, (struct utimbuf *) timep);
+	}
+#endif
+	if ((Filemode&S_IFMT) == S_IFREG)
+		chmod(Pathname, (07777 & Filemode));
+	return OK;
+}
+
+/*
+ * Ack a ZFIN packet, let byegones be byegones
+ */
+void ackbibi()
+{
+	register n;
+
+	vfile("ackbibi:");
+	Readnum = 1;
+	stohdr(0L);
+	for (n=3; --n>=0; ) {
+		purgeline();
+		zshhdr(ZFIN, Txhdr);
+		switch (readline(100)) {
+		case 'O':
+			readline(1);	/* Discard 2nd 'O' */
+			vfile("ackbibi complete");
+			return;
+		case RCDO:
+			return;
+		case TIMEOUT:
+		default:
+			break;
+		}
+	}
+}
+
+
+
+/*
+ * Local console output simulation
+ */
+void bttyout(c)
+int c;
+{
+	if (Verbose || Fromcu)
+		putc(c, stderr);
+}
+
+#ifndef vax11c
+/*
+ * Strip leading ! if present, do shell escape. 
+ */
+int sys2(s)
+register char *s;
+{
+	if (*s == '!')
+		++s;
+	return system(s);
+}
+/*
+ * Strip leading ! if present, do exec.
+ */
+void exec2(s)
+register char *s;
+{
+	if (*s == '!')
+		++s;
+	mode(0);
+	execl("/bin/sh", "sh", "-c", s);
+}
+#endif
+/* End of rz.c */
Index: /trunk/minix/commands/zmodem/sz.c
===================================================================
--- /trunk/minix/commands/zmodem/sz.c	(revision 9)
+++ /trunk/minix/commands/zmodem/sz.c	(revision 9)
@@ -0,0 +1,1755 @@
+#define VERSION "sz 2.12 05-29-88"
+#define PUBDIR "/usr/spool/uucppublic"
+
+/*% cc -compat -M2 -Ox -K -i -DTXBSIZE=16384  -DNFGVMIN -DREADCHECK sz.c -lx -o sz; size sz
+
+	Following is used for testing, might not be reasonable for production
+<-xtx-*> cc -Osal -DTXBSIZE=32768  -DSV sz.c -lx -o $B/sz; size $B/sz
+
+ ****************************************************************************
+ *
+ * sz.c By Chuck Forsberg,  Omen Technology INC
+ *
+ ****************************************************************************
+ *
+ * Typical Unix/Xenix/Clone compiles:
+ *
+ *	cc -O sz.c -o sz		USG (SYS III/V) Unix
+ *	cc -O -DSV sz.c -o sz		Sys V Release 2 with non-blocking input
+ *					Define to allow reverse channel checking
+ *	cc -O -DV7  sz.c -o sz		Unix Version 7, 2.8 - 4.3 BSD
+ *
+ *	cc -O -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz	Classic Xenix
+ *
+ *	ln sz sb			**** All versions ****
+ *	ln sz sx			**** All versions ****
+ *
+ ****************************************************************************
+ *
+ * Typical VMS compile and install sequence:
+ *
+ *		define LNK$LIBRARY   SYS$LIBRARY:VAXCRTL.OLB
+ *		cc sz.c
+ *		cc vvmodem.c
+ *		link sz,vvmodem
+ *	sz :== $disk$user2:[username.subdir]sz.exe
+ *
+ *  If you feel adventureous, remove the #define BADSYNC line
+ *  immediately following the #ifdef vax11c line!  Some VMS
+ *  systems know how to fseek, some don't.
+ *
+ ****************************************************************************
+ *
+ *
+ * A program for Unix to send files and commands to computers running
+ *  Professional-YAM, PowerCom, YAM, IMP, or programs supporting Y/XMODEM.
+ *
+ *  Sz uses buffered I/O to greatly reduce CPU time compared to UMODEM.
+ *
+ *  USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
+ *
+ *  2.1x hacks to avoid VMS fseek() bogosity, allow input from pipe
+ *     -DBADSEEK -DTXBSIZE=32768  
+ *  2.x has mods for VMS flavor
+ *
+ * 1.34 implements tx backchannel garbage count and ZCRCW after ZRPOS
+ * in accordance with the 7-31-87 ZMODEM Protocol Description
+ */
+
+
+#include <sys/types.h>
+
+#ifdef vax11c
+#define BADSEEK
+#define TXBSIZE 32768		/* Must be power of two, < MAXINT */
+#include <types.h>
+#include <stat.h>
+#define LOGFILE "szlog.tmp"
+#define OS "VMS"
+#define READCHECK
+#define BUFWRITE
+#define iofd
+extern int errno;
+#define SS_NORMAL SS$_NORMAL
+#define xsendline(c) sendline(c)
+
+
+#else	/* vax11c */
+
+
+#define SS_NORMAL 0
+#define LOGFILE "/tmp/szlog"
+
+#define sendline(c) putchar((c) & 0377)
+#define xsendline(c) putchar(c)
+
+#endif
+
+#include <signal.h>
+#include <setjmp.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utime.h>
+#include <stdio.h>
+
+#define PATHLEN 256
+#define OK 0
+#define FALSE 0
+#define TRUE 1
+#undef ERROR
+#define ERROR (-1)
+/* Ward Christensen / CP/M parameters - Don't change these! */
+#define ENQ 005
+#define CAN ('X'&037)
+#define XOFF ('s'&037)
+#define XON ('q'&037)
+#define SOH 1
+#define STX 2
+#define EOT 4
+#define ACK 6
+#define NAK 025
+#define CPMEOF 032
+#define WANTCRC 0103	/* send C not NAK to get crc not checksum */
+#define WANTG 0107	/* Send G not NAK to get nonstop batch xmsn */
+#define TIMEOUT (-2)
+#define RCDO (-3)
+#define RETRYMAX 10
+
+
+#define HOWMANY 2
+int Zmodem=0;		/* ZMODEM protocol requested by receiver */
+unsigned Baudrate=2400;	/* Default, should be set by first mode() call */
+unsigned Txwindow;	/* Control the size of the transmitted window */
+unsigned Txwspac;	/* Spacing between zcrcq requests */
+unsigned Txwcnt;	/* Counter used to space ack requests */
+long Lrxpos;		/* Receiver's last reported offset */
+int errors;
+
+#ifdef vax11c
+#include "vrzsz.c"	/* most of the system dependent stuff here */
+#else
+#include "rbsb.c"	/* most of the system dependent stuff here */
+#endif
+#include "crctab.c"
+
+int Filesleft;
+long Totalleft;
+
+/*
+ * Attention string to be executed by receiver to interrupt streaming data
+ *  when an error is detected.  A pause (0336) may be needed before the
+ *  ^C (03) or after it.
+ */
+#ifdef READCHECK
+char Myattn[] = { 0 };
+#else
+#ifdef USG
+char Myattn[] = { 03, 0336, 0 };
+#else
+char Myattn[] = { 0 };
+#endif
+#endif
+
+FILE *in;
+
+#ifdef BADSEEK
+int Canseek = 0;	/* 1: Can seek 0: only rewind -1: neither (pipe) */
+#ifndef TXBSIZE
+#define TXBSIZE 16384		/* Must be power of two, < MAXINT */
+#endif
+#else
+int Canseek = 1;	/* 1: Can seek 0: only rewind -1: neither (pipe) */
+#endif
+
+#ifdef TXBSIZE
+#define TXBMASK (TXBSIZE-1)
+char Txb[TXBSIZE];		/* Circular buffer for file reads */
+char *txbuf = Txb;		/* Pointer to current file segment */
+#else
+char txbuf[1024];
+#endif
+long vpos = 0;			/* Number of bytes read from file */
+
+char Lastrx;
+char Crcflg;
+int Verbose=0;
+int Modem2=0;		/* XMODEM Protocol - don't send pathnames */
+int Restricted=0;	/* restricted; no /.. or ../ in filenames */
+int Quiet=0;		/* overrides logic that would otherwise set verbose */
+int Ascii=0;		/* Add CR's for brain damaged programs */
+int Fullname=0;		/* transmit full pathname */
+int Unlinkafter=0;	/* Unlink file after it is sent */
+int Dottoslash=0;	/* Change foo.bar.baz to foo/bar/baz */
+int firstsec;
+int errcnt=0;		/* number of files unreadable */
+int blklen=128;		/* length of transmitted records */
+int Optiong;		/* Let it rip no wait for sector ACK's */
+int Eofseen;		/* EOF seen on input set by zfilbuf */
+int BEofseen;		/* EOF seen on input set by fooseek */
+int Totsecs;		/* total number of sectors this file */
+int Filcnt=0;		/* count of number of files opened */
+int Lfseen=0;
+unsigned Rxbuflen = 16384;	/* Receiver's max buffer length */
+int Tframlen = 0;	/* Override for tx frame length */
+int blkopt=0;		/* Override value for zmodem blklen */
+int Rxflags = 0;
+long bytcnt;
+int Wantfcs32 = TRUE;	/* want to send 32 bit FCS */
+char Lzconv;	/* Local ZMODEM file conversion request */
+char Lzmanag;	/* Local ZMODEM file management request */
+int Lskipnocor;
+char Lztrans;
+char zconv;		/* ZMODEM file conversion request */
+char zmanag;		/* ZMODEM file management request */
+char ztrans;		/* ZMODEM file transport request */
+int Command;		/* Send a command, then exit. */
+char *Cmdstr;		/* Pointer to the command string */
+int Cmdtries = 11;
+int Cmdack1;		/* Rx ACKs command, then do it */
+int Exitcode = 0;
+int Test;		/* 1= Force receiver to send Attn, etc with qbf. */
+			/* 2= Character transparency test */
+char *qbf="The quick brown fox jumped over the lazy dog's back 1234567890\r\n";
+long Lastsync;		/* Last offset to which we got a ZRPOS */
+int Beenhereb4;		/* How many times we've been ZRPOS'd same place */
+
+jmp_buf tohere;		/* For the interrupt on RX timeout */
+jmp_buf intrjmp;	/* For the interrupt on RX CAN */
+
+_PROTOTYPE(void onintr , (int sig ));
+_PROTOTYPE(int main , (int argc , char *argv []));
+_PROTOTYPE(int wcsend , (int argc , char *argp []));
+_PROTOTYPE(int wcs , (char *oname ));
+_PROTOTYPE(int wctxpn , (char *name ));
+_PROTOTYPE(int getnak , (void));
+_PROTOTYPE(int wctx , (long flen ));
+_PROTOTYPE(int wcputsec , (char *buf , int sectnum , int cseclen ));
+_PROTOTYPE(int filbuf , (char *buf , int count ));
+_PROTOTYPE(int zfilbuf , (void));
+_PROTOTYPE(int fooseek , (FILE *fptr , long pos , int whence ));
+_PROTOTYPE(void alrm , (int sig ));
+_PROTOTYPE(int readline , (int timeout ));
+_PROTOTYPE(void flushmo , (void));
+_PROTOTYPE(void purgeline , (void));
+_PROTOTYPE(void canit , (void));
+void zperr();
+_PROTOTYPE(char *substr , (char *s , char *t ));
+_PROTOTYPE(int usage , (void));
+_PROTOTYPE(int getzrxinit , (void));
+_PROTOTYPE(int sendzsinit , (void));
+_PROTOTYPE(int zsendfile , (char *buf , int blen ));
+_PROTOTYPE(int zsendfdata , (void));
+_PROTOTYPE(int getinsync , (int flag ));
+_PROTOTYPE(void saybibi , (void));
+_PROTOTYPE(void bttyout , (int c ));
+_PROTOTYPE(int zsendcmd , (char *buf , int blen ));
+_PROTOTYPE(void chkinvok , (char *s ));
+_PROTOTYPE(void countem , (int argc , char **argv ));
+_PROTOTYPE(void chartest , (int m ));
+
+/* called by signal interrupt or terminate to clean things up */
+void bibi(n)
+int n;
+{
+	canit(); fflush(stdout); mode(0);
+	fprintf(stderr, "sz: caught signal %d; exiting\n", n);
+	if (n == SIGQUIT)
+		abort();
+	if (n == 99)
+		fprintf(stderr, "mode(2) in rbsb.c not implemented!!\n");
+	cucheck();
+	exit(128+n);
+}
+/* Called when ZMODEM gets an interrupt (^X) */
+void onintr(sig)
+int sig;
+{
+	signal(SIGINT, SIG_IGN);
+	longjmp(intrjmp, -1);
+}
+
+int Zctlesc;	/* Encode control characters */
+int Nozmodem = 0;	/* If invoked as "sb" */
+char *Progname = "sz";
+int Zrwindow = 1400;	/* RX window size (controls garbage count) */
+#include "zm.c"
+
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+	register char *cp;
+	register npats;
+	int dm;
+	char **patts;
+	static char xXbuf[BUFSIZ];
+
+	if ((cp = getenv("ZNULLS")) && *cp)
+		Znulls = atoi(cp);
+	if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
+		Restricted=TRUE;
+	from_cu();
+	chkinvok(argv[0]);
+
+	Rxtimeout = 600;
+	npats=0;
+	if (argc<2)
+		usage();
+	setbuf(stdout, xXbuf);		
+	while (--argc) {
+		cp = *++argv;
+		if (*cp++ == '-' && *cp) {
+			while ( *cp) {
+				switch(*cp++) {
+				case '\\':
+					 *cp = toupper(*cp);  continue;
+				case '+':
+					Lzmanag = ZMAPND; break;
+#ifdef CSTOPB
+				case '2':
+					Twostop = TRUE; break;
+#endif
+				case 'a':
+					Lzconv = ZCNL;
+					Ascii = TRUE; break;
+				case 'b':
+					Lzconv = ZCBIN; break;
+				case 'C':
+					if (--argc < 1) {
+						usage();
+					}
+					Cmdtries = atoi(*++argv);
+					break;
+				case 'i':
+					Cmdack1 = ZCACK1;
+					/* **** FALL THROUGH TO **** */
+				case 'c':
+					if (--argc != 1) {
+						usage();
+					}
+					Command = TRUE;
+					Cmdstr = *++argv;
+					break;
+				case 'd':
+					++Dottoslash;
+					/* **** FALL THROUGH TO **** */
+				case 'f':
+					Fullname=TRUE; break;
+				case 'e':
+					Zctlesc = 1; break;
+				case 'k':
+					blklen=1024; break;
+				case 'L':
+					if (--argc < 1) {
+						usage();
+					}
+					blkopt = atoi(*++argv);
+					if (blkopt<24 || blkopt>1024)
+						usage();
+					break;
+				case 'l':
+					if (--argc < 1) {
+						usage();
+					}
+					Tframlen = atoi(*++argv);
+					if (Tframlen<32 || Tframlen>1024)
+						usage();
+					break;
+				case 'N':
+					Lzmanag = ZMNEWL;  break;
+				case 'n':
+					Lzmanag = ZMNEW;  break;
+				case 'o':
+					Wantfcs32 = FALSE; break;
+				case 'p':
+					Lzmanag = ZMPROT;  break;
+				case 'r':
+					Lzconv = ZCRESUM;
+				case 'q':
+					Quiet=TRUE; Verbose=0; break;
+				case 't':
+					if (--argc < 1) {
+						usage();
+					}
+					Rxtimeout = atoi(*++argv);
+					if (Rxtimeout<10 || Rxtimeout>1000)
+						usage();
+					break;
+				case 'T':
+					if (++Test > 1) {
+						chartest(1); chartest(2);
+						mode(0);  exit(0);
+					}
+					break;
+#ifndef vax11c
+				case 'u':
+					++Unlinkafter; break;
+#endif
+				case 'v':
+					++Verbose; break;
+				case 'w':
+					if (--argc < 1) {
+						usage();
+					}
+					Txwindow = atoi(*++argv);
+					if (Txwindow < 256)
+						Txwindow = 256;
+					Txwindow = (Txwindow/64) * 64;
+					Txwspac = Txwindow/4;
+					if (blkopt > Txwspac
+					 || (!blkopt && Txwspac < 1024))
+						blkopt = Txwspac;
+					break;
+				case 'X':
+					++Modem2; break;
+				case 'Y':
+					Lskipnocor = TRUE;
+					/* **** FALLL THROUGH TO **** */
+				case 'y':
+					Lzmanag = ZMCLOB; break;
+				default:
+					usage();
+				}
+			}
+		}
+		else if ( !npats && argc>0) {
+			if (argv[0][0]) {
+				npats=argc;
+				patts=argv;
+#ifndef vax11c
+				if ( !strcmp(*patts, "-"))
+					iofd = 1;
+#endif
+			}
+		}
+	}
+	if (npats < 1 && !Command && !Test) 
+		usage();
+	if (Verbose) {
+		if (freopen(LOGFILE, "a", stderr)==NULL) {
+			printf("Can't open log file %s\n",LOGFILE);
+			exit(0200);
+		}
+		setbuf(stderr, (char *)NULL);
+	}
+	if (Fromcu && !Quiet) {
+		if (Verbose == 0)
+			Verbose = 2;
+	}
+	vfile("%s %s for %s\n", Progname, VERSION, OS);
+
+	mode(1);
+
+	if (signal(SIGINT, bibi) == SIG_IGN) {
+		signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
+	} else {
+		signal(SIGINT, bibi); signal(SIGKILL, bibi);
+	}
+	if ( !Fromcu)
+		signal(SIGQUIT, SIG_IGN);
+	signal(SIGTERM, bibi);
+
+	if ( !Modem2) {
+		if (!Nozmodem) {
+			printf("rz\r");  fflush(stdout);
+		}
+		countem(npats, patts);
+		if (!Nozmodem) {
+			stohdr(0L);
+			if (Command)
+				Txhdr[ZF0] = ZCOMMAND;
+			zshhdr(ZRQINIT, Txhdr);
+		}
+	}
+	fflush(stdout);
+
+	if (Command) {
+		if (getzrxinit()) {
+			Exitcode=0200; canit();
+		}
+		else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
+			Exitcode=0200; canit();
+		}
+	} else if (wcsend(npats, patts)==ERROR) {
+		Exitcode=0200;
+		canit();
+	}
+	fflush(stdout);
+	mode(0);
+	dm = ((errcnt != 0) | Exitcode);
+	if (dm) {
+		cucheck();  exit(dm);
+	}
+	putc('\n',stderr);
+	exit(SS_NORMAL);
+	/*NOTREACHED*/
+}
+
+int wcsend(argc, argp)
+int argc;
+char *argp[];
+{
+	register int n;
+
+	Crcflg=FALSE;
+	firstsec=TRUE;
+	bytcnt = -1;
+	for (n=0; n<argc; ++n) {
+		Totsecs = 0;
+		if (wcs(argp[n])==ERROR)
+			return ERROR;
+	}
+	Totsecs = 0;
+	if (Filcnt==0) {	/* bitch if we couldn't open ANY files */
+		if ( !Modem2) {
+			Command = TRUE;
+			Cmdstr = "echo \"sz: Can't open any requested files\"";
+			if (getnak()) {
+				Exitcode=0200; canit();
+			}
+			if (!Zmodem)
+				canit();
+			else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
+				Exitcode=0200; canit();
+			}
+			Exitcode = 1; return OK;
+		}
+		canit();
+		fprintf(stderr,"\r\nCan't open any requested files.\r\n");
+		return ERROR;
+	}
+	if (Zmodem)
+		saybibi();
+	else if ( !Modem2)
+		wctxpn("");
+	return OK;
+}
+
+int wcs(oname)
+char *oname;
+{
+	register c;
+	register char *p;
+	struct stat f;
+	char name[PATHLEN];
+
+	strcpy(name, oname);
+
+	if (Restricted) {
+		/* restrict pathnames to current tree or uucppublic */
+		if ( substr(name, "../")
+		 || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {
+			canit();
+			fprintf(stderr,"\r\nsz:\tSecurity Violation\r\n");
+			return ERROR;
+		}
+	}
+
+	if ( !strcmp(oname, "-")) {
+		if ((p = getenv("ONAME")) && *p)
+			strcpy(name, p);
+		else
+			sprintf(name, "s%d.sz", getpid());
+		in = stdin;
+	}
+	else if ((in=fopen(oname, "r"))==NULL) {
+		++errcnt;
+		return OK;	/* pass over it, there may be others */
+	}
+	BEofseen = Eofseen = 0;  vpos = 0;
+	/* Check for directory or block special files */
+	fstat(fileno(in), &f);
+	c = f.st_mode & S_IFMT;
+	if (c == S_IFDIR || c == S_IFBLK) {
+		fclose(in);
+		return OK;
+	}
+
+	++Filcnt;
+	switch (wctxpn(name)) {
+	case ERROR:
+		return ERROR;
+	case ZSKIP:
+		return OK;
+	}
+	if (!Zmodem && wctx(f.st_size)==ERROR)
+		return ERROR;
+#ifndef vax11c
+	if (Unlinkafter)
+		unlink(oname);
+#endif
+	return 0;
+}
+
+/*
+ * generate and transmit pathname block consisting of
+ *  pathname (null terminated),
+ *  file length, mode time and file mode in octal
+ *  as provided by the Unix fstat call.
+ *  N.B.: modifies the passed name, may extend it!
+ */
+int wctxpn(name)
+char *name;
+{
+	register char *p, *q;
+	char name2[PATHLEN];
+	struct stat f;
+
+	if (Modem2) {
+		if ((in!=stdin) && *name && fstat(fileno(in), &f)!= -1) {
+			fprintf(stderr, "Sending %s, %ld blocks: ",
+			  name, f.st_size>>7);
+		}
+		fprintf(stderr, "Give your local XMODEM receive command now.\r\n");
+		return OK;
+	}
+	zperr("Awaiting pathname nak for %s", *name?name:"<END>");
+	if ( !Zmodem)
+		if (getnak())
+			return ERROR;
+
+	q = (char *) 0;
+	if (Dottoslash) {		/* change . to . */
+		for (p=name; *p; ++p) {
+			if (*p == '/')
+				q = p;
+			else if (*p == '.')
+				*(q=p) = '/';
+		}
+		if (q && strlen(++q) > 8) {	/* If name>8 chars */
+			q += 8;			/*   make it .ext */
+			strcpy(name2, q);	/* save excess of name */
+			*q = '.';
+			strcpy(++q, name2);	/* add it back */
+		}
+	}
+
+	for (p=name, q=txbuf ; *p; )
+		if ((*q++ = *p++) == '/' && !Fullname)
+			q = txbuf;
+	*q++ = 0;
+	p=q;
+	while (q < (txbuf + 1024))
+		*q++ = 0;
+	if (!Ascii && (in!=stdin) && *name && fstat(fileno(in), &f)!= -1)
+		sprintf(p, "%lu %lo %o 0 %d %ld", f.st_size, f.st_mtime,
+		  f.st_mode, Filesleft, Totalleft);
+	Totalleft -= f.st_size;
+	if (--Filesleft <= 0)
+		Totalleft = 0;
+	if (Totalleft < 0)
+		Totalleft = 0;
+
+	/* force 1k blocks if name won't fit in 128 byte block */
+	if (txbuf[125])
+		blklen=1024;
+	else {		/* A little goodie for IMP/KMD */
+		txbuf[127] = (f.st_size + 127) >>7;
+		txbuf[126] = (f.st_size + 127) >>15;
+	}
+	if (Zmodem)
+		return zsendfile(txbuf, 1+strlen(p)+(p-txbuf));
+	if (wcputsec(txbuf, 0, 128)==ERROR)
+		return ERROR;
+	return OK;
+}
+
+int getnak()
+{
+	register firstch;
+
+	Lastrx = 0;
+	for (;;) {
+		switch (firstch = readline(800)) {
+		case ZPAD:
+			if (getzrxinit())
+				return ERROR;
+			Ascii = 0;	/* Receiver does the conversion */
+			return FALSE;
+		case TIMEOUT:
+			zperr("Timeout on pathname");
+			return TRUE;
+		case WANTG:
+#ifdef MODE2OK
+			mode(2);	/* Set cbreak, XON/XOFF, etc. */
+#endif
+			Optiong = TRUE;
+			blklen=1024;
+		case WANTCRC:
+			Crcflg = TRUE;
+		case NAK:
+			return FALSE;
+		case CAN:
+			if ((firstch = readline(20)) == CAN && Lastrx == CAN)
+				return TRUE;
+		default:
+			break;
+		}
+		Lastrx = firstch;
+	}
+}
+
+
+int wctx(flen)
+long flen;
+{
+	register int thisblklen;
+	register int sectnum, attempts, firstch;
+	long charssent;
+
+	charssent = 0;  firstsec=TRUE;  thisblklen = blklen;
+	vfile("wctx:file length=%ld", flen);
+
+	while ((firstch=readline(Rxtimeout))!=NAK && firstch != WANTCRC
+	  && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN)
+		;
+	if (firstch==CAN) {
+		zperr("Receiver CANcelled");
+		return ERROR;
+	}
+	if (firstch==WANTCRC)
+		Crcflg=TRUE;
+	if (firstch==WANTG)
+		Crcflg=TRUE;
+	sectnum=0;
+	for (;;) {
+		if (flen <= (charssent + 896L))
+			thisblklen = 128;
+		if ( !filbuf(txbuf, thisblklen))
+			break;
+		if (wcputsec(txbuf, ++sectnum, thisblklen)==ERROR)
+			return ERROR;
+		charssent += thisblklen;
+	}
+	fclose(in);
+	attempts=0;
+	do {
+		purgeline();
+		sendline(EOT);
+		fflush(stdout);
+		++attempts;
+	}
+		while ((firstch=(readline(Rxtimeout)) != ACK) && attempts < RETRYMAX);
+	if (attempts == RETRYMAX) {
+		zperr("No ACK on EOT");
+		return ERROR;
+	}
+	else
+		return OK;
+}
+
+int wcputsec(buf, sectnum, cseclen)
+char *buf;
+int sectnum;
+int cseclen;	/* data length of this sector to send */
+{
+	register checksum, wcj;
+	register char *cp;
+	unsigned oldcrc;
+	int firstch;
+	int attempts;
+
+	firstch=0;	/* part of logic to detect CAN CAN */
+
+	if (Verbose>2)
+		fprintf(stderr, "Sector %3d %2dk\n", Totsecs, Totsecs/8 );
+	else if (Verbose>1)
+		fprintf(stderr, "\rSector %3d %2dk ", Totsecs, Totsecs/8 );
+	for (attempts=0; attempts <= RETRYMAX; attempts++) {
+		Lastrx= firstch;
+		sendline(cseclen==1024?STX:SOH);
+		sendline(sectnum);
+		sendline(-sectnum -1);
+		oldcrc=checksum=0;
+		for (wcj=cseclen,cp=buf; --wcj>=0; ) {
+			sendline(*cp);
+			oldcrc=updcrc((0377& *cp), oldcrc);
+			checksum += *cp++;
+		}
+		if (Crcflg) {
+			oldcrc=updcrc(0,updcrc(0,oldcrc));
+			sendline((int)oldcrc>>8);
+			sendline((int)oldcrc);
+		}
+		else
+			sendline(checksum);
+
+		if (Optiong) {
+			firstsec = FALSE; return OK;
+		}
+		firstch = readline(Rxtimeout);
+gotnak:
+		switch (firstch) {
+		case CAN:
+			if(Lastrx == CAN) {
+cancan:
+				zperr("Cancelled");  return ERROR;
+			}
+			break;
+		case TIMEOUT:
+			zperr("Timeout on sector ACK"); continue;
+		case WANTCRC:
+			if (firstsec)
+				Crcflg = TRUE;
+		case NAK:
+			zperr("NAK on sector"); continue;
+		case ACK: 
+			firstsec=FALSE;
+			Totsecs += (cseclen>>7);
+			return OK;
+		case ERROR:
+			zperr("Got burst for sector ACK"); break;
+		default:
+			zperr("Got %02x for sector ACK", firstch); break;
+		}
+		for (;;) {
+			Lastrx = firstch;
+			if ((firstch = readline(Rxtimeout)) == TIMEOUT)
+				break;
+			if (firstch == NAK || firstch == WANTCRC)
+				goto gotnak;
+			if (firstch == CAN && Lastrx == CAN)
+				goto cancan;
+		}
+	}
+	zperr("Retry Count Exceeded");
+	return ERROR;
+}
+
+/* fill buf with count chars padding with ^Z for CPM */
+int filbuf(buf, count)
+register char *buf;
+int count;
+{
+	register c, m;
+
+	if ( !Ascii) {
+		m = read(fileno(in), buf, count);
+		if (m <= 0)
+			return 0;
+		while (m < count)
+			buf[m++] = 032;
+		return count;
+	}
+	m=count;
+	if (Lfseen) {
+		*buf++ = 012; --m; Lfseen = 0;
+	}
+	while ((c=getc(in))!=EOF) {
+		if (c == 012) {
+			*buf++ = 015;
+			if (--m == 0) {
+				Lfseen = TRUE; break;
+			}
+		}
+		*buf++ =c;
+		if (--m == 0)
+			break;
+	}
+	if (m==count)
+		return 0;
+	else
+		while (--m>=0)
+			*buf++ = CPMEOF;
+	return count;
+}
+
+/* Fill buffer with blklen chars */
+int zfilbuf()
+{
+	int n;
+
+#ifdef TXBSIZE
+	/* We assume request is within buffer, or just beyond */
+	txbuf = Txb + (bytcnt & TXBMASK);
+	if (vpos <= bytcnt) {
+		n = fread(txbuf, 1, blklen, in);
+		vpos += n;
+		if (n < blklen)
+			Eofseen = 1;
+		return n;
+	}
+	if (vpos >= (bytcnt+blklen))
+		return blklen;
+	/* May be a short block if crash recovery etc. */
+	Eofseen = BEofseen;
+	return (vpos - bytcnt);
+#else
+	n = fread(txbuf, 1, blklen, in);
+	if (n < blklen)
+		Eofseen = 1;
+	return n;
+#endif
+}
+
+#ifdef TXBSIZE
+int fooseek(fptr, pos, whence)
+FILE *fptr;
+long pos;
+{
+	int m, n;
+
+	vfile("fooseek: pos =%lu vpos=%lu Canseek=%d", pos, vpos, Canseek);
+	/* Seek offset < current buffer */
+	if (pos < (vpos -TXBSIZE +1024)) {
+		BEofseen = 0;
+		if (Canseek > 0) {
+			vpos = pos & ~TXBMASK;
+			if (vpos >= pos)
+				vpos -= TXBSIZE;
+			if (fseek(fptr, vpos, 0))
+				return 1;
+		}
+		else if (Canseek == 0)
+			if (fseek(fptr, vpos = 0L, 0))
+				return 1;
+		else
+			return 1;
+		while (vpos <= pos) {
+			n = fread(Txb, 1, TXBSIZE, fptr);
+			vpos += n;
+			vfile("n=%d vpos=%ld", n, vpos);
+			if (n < TXBSIZE) {
+				BEofseen = 1;
+				break;
+			}
+		}
+		vfile("vpos=%ld", vpos);
+		return 0;
+	}
+	/* Seek offset > current buffer (crash recovery, etc.) */
+	if (pos > vpos) {
+		if (Canseek)
+			if (fseek(fptr, vpos = (pos & ~TXBMASK), 0))
+				return 1;
+		while (vpos <= pos) {
+			txbuf = Txb + (vpos & TXBMASK);
+			m = TXBSIZE - (vpos & TXBMASK);
+			n = fread(txbuf, 1, m, fptr);
+			vpos += n;
+			vfile("bo=%d n=%d vpos=%ld", txbuf-Txb, n, vpos);
+			if (m < n) {
+				BEofseen = 1;
+				break;
+			}
+		}
+		return 0;
+	}
+	/* Seek offset is within current buffer */
+	vfile("vpos=%ld", vpos);
+	return 0;
+}
+#define fseek fooseek
+#endif
+
+
+/* VARARGS1 */
+void vfile(f, a, b, c)
+register char *f,*a,*b,*c;
+{
+	if (Verbose > 2) {
+		fprintf(stderr, f, a, b, c);
+		fprintf(stderr, "\n");
+	}
+}
+
+
+void alrm(sig)
+int sig;
+{
+	longjmp(tohere, -1);
+}
+
+
+#ifndef vax11c
+/*
+ * readline(timeout) reads character(s) from file descriptor 0
+ * timeout is in tenths of seconds
+ */
+int readline(timeout)
+int timeout;
+{
+	register int c;
+	static char byt[1];
+
+	fflush(stdout);
+	if (setjmp(tohere)) {
+		zperr("TIMEOUT");
+		return TIMEOUT;
+	}
+	c = timeout/10;
+	if (c<2)
+		c=2;
+	if (Verbose>5) {
+		fprintf(stderr, "Timeout=%d Calling alarm(%d) ", timeout, c);
+	}
+	signal(SIGALRM, alrm); alarm(c);
+	c=read(iofd, byt, 1);
+	alarm(0);
+	if (Verbose>5)
+		fprintf(stderr, "ret %x\n", byt[0]);
+	if (c<1)
+		return TIMEOUT;
+	return (byt[0]&0377);
+}
+
+void flushmo()
+{
+	fflush(stdout);
+}
+
+
+void purgeline()
+{
+#ifdef USG
+	ioctl(iofd, TCFLSH, 0);
+#else
+	lseek(iofd, 0L, 2);
+#endif
+}
+#endif
+
+/* send cancel string to get the other end to shut up */
+void canit()
+{
+	static char canistr[] = {
+	 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
+	};
+
+#ifdef vax11c
+	raw_wbuf(strlen(canistr), canistr);
+	purgeline();
+#else
+	printf(canistr);
+	fflush(stdout);
+#endif
+}
+
+
+/*
+ * Log an error
+ */
+/*VARARGS1*/
+void zperr(s,p,u)
+char *s, *p, *u;
+{
+	if (Verbose <= 0)
+		return;
+	fprintf(stderr, "\nRetry %d: ", errors);
+	fprintf(stderr, s, p, u);
+	fprintf(stderr, "\n");
+}
+
+/*
+ * substr(string, token) searches for token in string s
+ * returns pointer to token within string if found, NULL otherwise
+ */
+char *
+substr(s, t)
+register char *s,*t;
+{
+	register char *ss,*tt;
+	/* search for first char of token */
+	for (ss=s; *s; s++)
+		if (*s == *t)
+			/* compare token with substring */
+			for (ss=s,tt=t; ;) {
+				if (*tt == 0)
+					return s;
+				if (*ss++ != *tt++)
+					break;
+			}
+	return (char *)NULL;
+}
+
+char *babble[] = {
+#ifdef vax11c
+	"	Send file(s) with ZMODEM Protocol",
+	"Usage:	sz [-2+abdefkLlNnquvwYy] [-] file ...",
+	"	sz [-2Ceqv] -c COMMAND",
+	"	\\ Force next option letter to upper case",
+#else
+	"Send file(s) with ZMODEM/YMODEM/XMODEM Protocol",
+	"	(Y) = Option applies to YMODEM only",
+	"	(Z) = Option applies to ZMODEM only",
+	"Usage:	sz [-2+abdefkLlNnquvwYy] [-] file ...",
+	"	sz [-2Ceqv] -c COMMAND",
+	"	sb [-2adfkquv] [-] file ...",
+	"	sx [-2akquv] [-] file",
+#endif
+#ifdef CSTOPB
+	"	2 Use 2 stop bits",
+#endif
+	"	+ Append to existing destination file (Z)",
+	"	a (ASCII) change NL to CR/LF",
+	"	b Binary file transfer override",
+	"	c send COMMAND (Z)",
+#ifndef vax11c
+	"	d Change '.' to '/' in pathnames (Y/Z)",
+#endif
+	"	e Escape all control characters (Z)",
+	"	f send Full pathname (Y/Z)",
+	"	i send COMMAND, ack Immediately (Z)",
+	"	k Send 1024 byte packets (Y)",
+	"	L N Limit subpacket length to N bytes (Z)",
+	"	l N Limit frame length to N bytes (l>=L) (Z)",
+	"	n send file if source newer (Z)",
+	"	N send file if source newer or longer (Z)",
+	"	o Use 16 bit CRC instead of 32 bit CRC (Z)",
+	"	p Protect existing destination file (Z)",
+	"	r Resume/Recover interrupted file transfer (Z)",
+	"	q Quiet (no progress reports)",
+#ifndef vax11c
+	"	u Unlink file after transmission",
+#endif
+	"	v Verbose - provide debugging information",
+	"	w N Window is N bytes (Z)",
+	"	Y Yes, overwrite existing file, skip if not present at rx (Z)",
+	"	y Yes, overwrite existing file (Z)",
+	"- as pathname sends standard input as sPID.sz or environment ONAME",
+	""
+};
+
+int usage()
+{
+	char **pp;
+
+	for (pp=babble; **pp; ++pp)
+		fprintf(stderr, "%s\n", *pp);
+	fprintf(stderr, "%s for %s by Chuck Forsberg, Omen Technology INC\n",
+	 VERSION, OS);
+	fprintf(stderr, "\t\t\042The High Reliability Software\042\n");
+	cucheck();
+	exit(SS_NORMAL);
+}
+
+/*
+ * Get the receiver's init parameters
+ */
+int getzrxinit()
+{
+	register n;
+	struct stat f;
+
+	for (n=10; --n>=0; ) {
+		
+		switch (zgethdr(Rxhdr, 1)) {
+		case ZCHALLENGE:	/* Echo receiver's challenge numbr */
+			stohdr(Rxpos);
+			zshhdr(ZACK, Txhdr);
+			continue;
+		case ZCOMMAND:		/* They didn't see out ZRQINIT */
+			stohdr(0L);
+			zshhdr(ZRQINIT, Txhdr);
+			continue;
+		case ZRINIT:
+			Rxflags = 0377 & Rxhdr[ZF0];
+			Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
+			Zctlesc |= Rxflags & TESCCTL;
+			Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
+			if ( !(Rxflags & CANFDX))
+				Txwindow = 0;
+			vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen);
+			if ( !Fromcu)
+				signal(SIGINT, SIG_IGN);
+#ifdef MODE2OK
+			mode(2);	/* Set cbreak, XON/XOFF, etc. */
+#endif
+#ifndef READCHECK
+#ifndef USG
+			/* Use 1024 byte frames if no sample/interrupt */
+			if (Rxbuflen < 32 || Rxbuflen > 1024) {
+				Rxbuflen = 1024;
+				vfile("Rxbuflen=%d", Rxbuflen);
+			}
+#endif
+#endif
+			/* Override to force shorter frame length */
+			if (Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32))
+				Rxbuflen = Tframlen;
+			if ( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024))
+				Rxbuflen = Tframlen;
+			vfile("Rxbuflen=%d", Rxbuflen);
+
+#ifndef vax11c
+			/* If using a pipe for testing set lower buf len */
+			fstat(iofd, &f);
+			if ((f.st_mode & S_IFMT) != S_IFCHR) {
+				Rxbuflen = 1024;
+			}
+#endif
+#ifdef BADSEEK
+			Canseek = 0;
+			Txwindow = TXBSIZE - 1024;
+			Txwspac = TXBSIZE/4;
+#endif
+			/*
+			 * If input is not a regular file, force ACK's to
+			 *  prevent running beyond the buffer limits
+			 */
+			if ( !Command) {
+				fstat(fileno(in), &f);
+				if ((f.st_mode & S_IFMT) != S_IFREG) {
+					Canseek = -1;
+#ifdef TXBSIZE
+					Txwindow = TXBSIZE - 1024;
+					Txwspac = TXBSIZE/4;
+#else
+					return ERROR;
+#endif
+				}
+			}
+			/* Set initial subpacket length */
+			if (blklen < 1024) {	/* Command line override? */
+				if (Baudrate > 300)
+					blklen = 256;
+				if (Baudrate > 1200)
+					blklen = 512;
+				if (Baudrate > 2400)
+					blklen = 1024;
+			}
+			if (Rxbuflen && blklen>Rxbuflen)
+				blklen = Rxbuflen;
+			if (blkopt && blklen > blkopt)
+				blklen = blkopt;
+			vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen);
+			vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac);
+
+			return (sendzsinit());
+		case ZCAN:
+		case TIMEOUT:
+			return ERROR;
+		case ZRQINIT:
+			if (Rxhdr[ZF0] == ZCOMMAND)
+				continue;
+		default:
+			zshhdr(ZNAK, Txhdr);
+			continue;
+		}
+	}
+	return ERROR;
+}
+
+/* Send send-init information */
+int sendzsinit()
+{
+	register c;
+
+	if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL)))
+		return OK;
+	errors = 0;
+	for (;;) {
+		stohdr(0L);
+		if (Zctlesc) {
+			Txhdr[ZF0] |= TESCCTL; zshhdr(ZSINIT, Txhdr);
+		}
+		else
+			zsbhdr(ZSINIT, Txhdr);
+		zsdata(Myattn, 1+strlen(Myattn), ZCRCW);
+		c = zgethdr(Rxhdr, 1);
+		switch (c) {
+		case ZCAN:
+			return ERROR;
+		case ZACK:
+			return OK;
+		default:
+			if (++errors > 19)
+				return ERROR;
+			continue;
+		}
+	}
+}
+
+/* Send file name and related info */
+int zsendfile(buf, blen)
+char *buf;
+int blen;
+{
+	register c;
+	register UNSL long crc;
+
+	for (;;) {
+		Txhdr[ZF0] = Lzconv;	/* file conversion request */
+		Txhdr[ZF1] = Lzmanag;	/* file management request */
+		if (Lskipnocor)
+			Txhdr[ZF1] |= ZMSKNOLOC;
+		Txhdr[ZF2] = Lztrans;	/* file transport request */
+		Txhdr[ZF3] = 0;
+		zsbhdr(ZFILE, Txhdr);
+		zsdata(buf, blen, ZCRCW);
+again:
+		c = zgethdr(Rxhdr, 1);
+		switch (c) {
+		case ZRINIT:
+			while ((c = readline(50)) > 0)
+				if (c == ZPAD) {
+					goto again;
+				}
+			/* **** FALL THRU TO **** */
+		default:
+			continue;
+		case ZCAN:
+		case TIMEOUT:
+		case ZABORT:
+		case ZFIN:
+			return ERROR;
+		case ZCRC:
+			crc = 0xFFFFFFFFL;
+			if (Canseek >= 0) {
+				while (((c = getc(in)) != EOF) && --Rxpos)
+					crc = UPDC32(c, crc);
+				crc = ~crc;
+				clearerr(in);	/* Clear EOF */
+				fseek(in, 0L, 0);
+			}
+			stohdr(crc);
+			zsbhdr(ZCRC, Txhdr);
+			goto again;
+		case ZSKIP:
+			fclose(in); return c;
+		case ZRPOS:
+			/*
+			 * Suppress zcrcw request otherwise triggered by
+			 * lastyunc==bytcnt
+			 */
+			if (Rxpos && fseek(in, Rxpos, 0))
+				return ERROR;
+			Lastsync = (bytcnt = Txpos = Rxpos) -1;
+			return zsendfdata();
+		}
+	}
+}
+
+/* Send the data in the file */
+int zsendfdata()
+{
+	register c, e, n;
+	register int newcnt;
+	register long tcount = 0;
+	int junkcount;		/* Counts garbage chars received by TX */
+	static int tleft = 6;	/* Counter for test mode */
+
+	Lrxpos = 0;
+	junkcount = 0;
+	Beenhereb4 = FALSE;
+somemore:
+	if (setjmp(intrjmp)) {
+waitack:
+		junkcount = 0;
+		c = getinsync(0);
+gotack:
+		switch (c) {
+		default:
+		case ZCAN:
+			fclose(in);
+			return ERROR;
+		case ZSKIP:
+			fclose(in);
+			return c;
+		case ZACK:
+		case ZRPOS:
+			break;
+		case ZRINIT:
+			return OK;
+		}
+#ifdef READCHECK
+		/*
+		 * If the reverse channel can be tested for data,
+		 *  this logic may be used to detect error packets
+		 *  sent by the receiver, in place of setjmp/longjmp
+		 *  rdchk(fdes) returns non 0 if a character is available
+		 */
+		while (rdchk(iofd)) {
+#ifdef SV
+			switch (checked)
+#else
+			switch (readline(1))
+#endif
+			{
+			case CAN:
+			case ZPAD:
+				c = getinsync(1);
+				goto gotack;
+			case XOFF:		/* Wait a while for an XON */
+			case XOFF|0200:
+				readline(100);
+			}
+		}
+#endif
+	}
+
+	if ( !Fromcu)
+		signal(SIGINT, onintr);
+	newcnt = Rxbuflen;
+	Txwcnt = 0;
+	stohdr(Txpos);
+	zsbhdr(ZDATA, Txhdr);
+
+	/*
+	 * Special testing mode.  This should force receiver to Attn,ZRPOS
+	 *  many times.  Each time the signal should be caught, causing the
+	 *  file to be started over from the beginning.
+	 */
+	if (Test) {
+		if ( --tleft)
+			while (tcount < 20000) {
+				printf(qbf); fflush(stdout);
+				tcount += strlen(qbf);
+#ifdef READCHECK
+				while (rdchk(iofd)) {
+#ifdef SV
+					switch (checked)
+#else
+					switch (readline(1))
+#endif
+					{
+					case CAN:
+					case ZPAD:
+#ifdef TCFLSH
+						ioctl(iofd, TCFLSH, 1);
+#endif
+						goto waitack;
+					case XOFF:	/* Wait for XON */
+					case XOFF|0200:
+						readline(100);
+					}
+				}
+#endif
+			}
+		signal(SIGINT, SIG_IGN); canit();
+		sleep(3); purgeline(); mode(0);
+		printf("\nsz: Tcount = %ld\n", tcount);
+		if (tleft) {
+			printf("ERROR: Interrupts Not Caught\n");
+			exit(1);
+		}
+		exit(SS_NORMAL);
+	}
+
+	do {
+		n = zfilbuf();
+		if (Eofseen)
+			e = ZCRCE;
+		else if (junkcount > 3)
+			e = ZCRCW;
+		else if (bytcnt == Lastsync)
+			e = ZCRCW;
+		else if (Rxbuflen && (newcnt -= n) <= 0)
+			e = ZCRCW;
+		else if (Txwindow && (Txwcnt += n) >= Txwspac) {
+			Txwcnt = 0;  e = ZCRCQ;
+		}
+		else
+			e = ZCRCG;
+		if (Verbose>1)
+			fprintf(stderr, "\r%7ld ZMODEM%s    ",
+			  Txpos, Crc32t?" CRC-32":"");
+		zsdata(txbuf, n, e);
+		bytcnt = Txpos += n;
+		if (e == ZCRCW)
+			goto waitack;
+#ifdef READCHECK
+		/*
+		 * If the reverse channel can be tested for data,
+		 *  this logic may be used to detect error packets
+		 *  sent by the receiver, in place of setjmp/longjmp
+		 *  rdchk(fdes) returns non 0 if a character is available
+		 */
+		fflush(stdout);
+		while (rdchk(iofd)) {
+#ifdef SV
+			switch (checked)
+#else
+			switch (readline(1))
+#endif
+			{
+			case CAN:
+			case ZPAD:
+				c = getinsync(1);
+				if (c == ZACK)
+					break;
+#ifdef TCFLSH
+				ioctl(iofd, TCFLSH, 1);
+#endif
+				/* zcrce - dinna wanna starta ping-pong game */
+				zsdata(txbuf, 0, ZCRCE);
+				goto gotack;
+			case XOFF:		/* Wait a while for an XON */
+			case XOFF|0200:
+				readline(100);
+			default:
+				++junkcount;
+			}
+		}
+#endif	/* READCHECK */
+		if (Txwindow) {
+			while ((tcount = Txpos - Lrxpos) >= Txwindow) {
+				vfile("%ld window >= %u", tcount, Txwindow);
+				if (e != ZCRCQ)
+					zsdata(txbuf, 0, e = ZCRCQ);
+				c = getinsync(1);
+				if (c != ZACK) {
+#ifdef TCFLSH
+					ioctl(iofd, TCFLSH, 1);
+#endif
+					zsdata(txbuf, 0, ZCRCE);
+					goto gotack;
+				}
+			}
+			vfile("window = %ld", tcount);
+		}
+	} while (!Eofseen);
+	if ( !Fromcu)
+		signal(SIGINT, SIG_IGN);
+
+	for (;;) {
+		stohdr(Txpos);
+		zsbhdr(ZEOF, Txhdr);
+		switch (getinsync(0)) {
+		case ZACK:
+			continue;
+		case ZRPOS:
+			goto somemore;
+		case ZRINIT:
+			return OK;
+		case ZSKIP:
+			fclose(in);
+			return c;
+		default:
+			fclose(in);
+			return ERROR;
+		}
+	}
+}
+
+/*
+ * Respond to receiver's complaint, get back in sync with receiver
+ */
+int getinsync(flag)
+int flag;
+{
+	register int c;
+
+	for (;;) {
+		if (Test) {
+			printf("\r\n\n\n***** Signal Caught *****\r\n");
+			Rxpos = 0; c = ZRPOS;
+		} else
+			c = zgethdr(Rxhdr, 0);
+		switch (c) {
+		case ZCAN:
+		case ZABORT:
+		case ZFIN:
+		case TIMEOUT:
+			return ERROR;
+		case ZRPOS:
+			/* ************************************* */
+			/*  If sending to a buffered modem, you  */
+			/*   might send a break at this point to */
+			/*   dump the modem's buffer.		 */
+			clearerr(in);	/* In case file EOF seen */
+			if (fseek(in, Rxpos, 0))
+				return ERROR;
+			Eofseen = 0;
+			bytcnt = Lrxpos = Txpos = Rxpos;
+			if (Lastsync == Rxpos) {
+				if (++Beenhereb4 > 4)
+					if (blklen > 32)
+						blklen /= 2;
+			}
+			Lastsync = Rxpos;
+			return c;
+		case ZACK:
+			Lrxpos = Rxpos;
+			if (flag || Txpos == Rxpos)
+				return ZACK;
+			continue;
+		case ZRINIT:
+		case ZSKIP:
+			fclose(in);
+			return c;
+		case ERROR:
+		default:
+			zsbhdr(ZNAK, Txhdr);
+			continue;
+		}
+	}
+}
+
+
+/* Say "bibi" to the receiver, try to do it cleanly */
+void saybibi()
+{
+	for (;;) {
+		stohdr(0L);		/* CAF Was zsbhdr - minor change */
+		zshhdr(ZFIN, Txhdr);	/*  to make debugging easier */
+		switch (zgethdr(Rxhdr, 0)) {
+		case ZFIN:
+			sendline('O'); sendline('O'); flushmo();
+		case ZCAN:
+		case TIMEOUT:
+			return;
+		}
+	}
+}
+
+/* Local screen character display function */
+void bttyout(c)
+int c;
+{
+	if (Verbose)
+		putc(c, stderr);
+}
+
+/* Send command and related info */
+int zsendcmd(buf, blen)
+char *buf;
+int blen;
+{
+	register c;
+	long cmdnum;
+
+	cmdnum = getpid();
+	errors = 0;
+	for (;;) {
+		stohdr(cmdnum);
+		Txhdr[ZF0] = Cmdack1;
+		zsbhdr(ZCOMMAND, Txhdr);
+		zsdata(buf, blen, ZCRCW);
+listen:
+		Rxtimeout = 100;		/* Ten second wait for resp. */
+		c = zgethdr(Rxhdr, 1);
+
+		switch (c) {
+		case ZRINIT:
+			goto listen;	/* CAF 8-21-87 */
+		case ERROR:
+		case TIMEOUT:
+			if (++errors > Cmdtries)
+				return ERROR;
+			continue;
+		case ZCAN:
+		case ZABORT:
+		case ZFIN:
+		case ZSKIP:
+		case ZRPOS:
+			return ERROR;
+		default:
+			if (++errors > 20)
+				return ERROR;
+			continue;
+		case ZCOMPL:
+			Exitcode = Rxpos;
+			saybibi();
+			return OK;
+		case ZRQINIT:
+#ifdef vax11c		/* YAMP :== Yet Another Missing Primitive */
+			return ERROR;
+#else
+			vfile("******** RZ *******");
+			system("rz");
+			vfile("******** SZ *******");
+			goto listen;
+#endif
+		}
+	}
+}
+
+/*
+ * If called as sb use YMODEM protocol
+ */
+void chkinvok(s)
+char *s;
+{
+#ifdef vax11c
+	Progname = "sz";
+#else
+	register char *p;
+
+	p = s;
+	while (*p == '-')
+		s = ++p;
+	while (*p)
+		if (*p++ == '/')
+			s = p;
+	if (*s == 'v') {
+		Verbose=1; ++s;
+	}
+	Progname = s;
+	if (s[0]=='s' && s[1]=='b') {
+		Nozmodem = TRUE; blklen=1024;
+	}
+	if (s[0]=='s' && s[1]=='x') {
+		Modem2 = TRUE;
+	}
+#endif
+}
+
+void countem(argc, argv)
+int argc;
+register char **argv;
+{
+	register c;
+	struct stat f;
+
+	for (Totalleft = 0, Filesleft = 0; --argc >=0; ++argv) {
+		f.st_size = -1;
+		if (Verbose>2) {
+			fprintf(stderr, "\nCountem: %03d %s ", argc, *argv);
+			fflush(stderr);
+		}
+		if (access(*argv, 04) >= 0 && stat(*argv, &f) >= 0) {
+			c = f.st_mode & S_IFMT;
+			if (c != S_IFDIR && c != S_IFBLK) {
+				++Filesleft;  Totalleft += f.st_size;
+			}
+		}
+		if (Verbose>2)
+			fprintf(stderr, " %ld", f.st_size);
+	}
+	if (Verbose>2)
+		fprintf(stderr, "\ncountem: Total %d %ld\n",
+		  Filesleft, Totalleft);
+}
+
+void chartest(m)
+int m;
+{
+	register int n;
+
+	mode(m);
+	printf("\r\n\nCharacter Transparency Test Mode %d\r\n", m);
+	printf("If Pro-YAM/ZCOMM is not displaying ^M hit ALT-V NOW.\r\n");
+	printf("Hit Enter.\021");  fflush(stdout);
+	readline(500);
+
+	for (n = 0; n < 256; ++n) {
+		if (!(n%8))
+			printf("\r\n");
+		printf("%02x ", n);  fflush(stdout);
+		sendline(n);	flushmo();
+		printf("  ");  fflush(stdout);
+		if (n == 127) {
+			printf("Hit Enter.\021");  fflush(stdout);
+			readline(500);
+			printf("\r\n");  fflush(stdout);
+		}
+	}
+	printf("\021\r\nEnter Characters, echo is in hex.\r\n");
+	printf("Hit SPACE or pause 40 seconds for exit.\r\n");
+
+	while (n != TIMEOUT && n != ' ') {
+		n = readline(400);
+		printf("%02x\r\n", n);
+		fflush(stdout);
+	}
+	printf("\r\nMode %d character transparency test ends.\r\n", m);
+	fflush(stdout);
+}
+
+/* End of sz.c */
Index: /trunk/minix/commands/zmodem/zm.c
===================================================================
--- /trunk/minix/commands/zmodem/zm.c	(revision 9)
+++ /trunk/minix/commands/zmodem/zm.c	(revision 9)
@@ -0,0 +1,789 @@
+/*
+ *   Z M . C
+ *    ZMODEM protocol primitives
+ *    05-09-88  Chuck Forsberg Omen Technology Inc
+ *
+ * Entry point Functions:
+ *	zsbhdr(type, hdr) send binary header
+ *	zshhdr(type, hdr) send hex header
+ *	zgethdr(hdr, eflag) receive header - binary or hex
+ *	zsdata(buf, len, frameend) send data
+ *	zrdata(buf, len) receive data
+ *	stohdr(pos) store position data in Txhdr
+ *	long rclhdr(hdr) recover position offset from header
+ */
+
+#ifndef CANFDX
+#include "zmodem.h"
+#endif
+int Rxtimeout = 100;		/* Tenths of seconds to wait for something */
+
+#ifndef UNSL
+#define UNSL
+#endif
+
+
+/* Globals used by ZMODEM functions */
+int Rxframeind;		/* ZBIN ZBIN32, or ZHEX type of frame received */
+int Rxtype;		/* Type of header received */
+int Rxcount;		/* Count of data bytes received */
+char Rxhdr[4];		/* Received header */
+char Txhdr[4];		/* Transmitted header */
+long Rxpos;		/* Received file position */
+long Txpos;		/* Transmitted file position */
+int Txfcs32;		/* TURE means send binary frames with 32 bit FCS */
+int Crc32t;		/* Display flag indicating 32 bit CRC being sent */
+int Crc32;		/* Display flag indicating 32 bit CRC being received */
+int Znulls;		/* Number of nulls to send at beginning of ZDATA hdr */
+char Attn[ZATTNLEN+1];	/* Attention string rx sends to tx on err */
+
+static lastsent;	/* Last char we sent */
+static Not8bit;		/* Seven bits seen on header */
+
+static char *frametypes[] = {
+	"Carrier Lost",		/* -3 */
+	"TIMEOUT",		/* -2 */
+	"ERROR",		/* -1 */
+#define FTOFFSET 3
+	"ZRQINIT",
+	"ZRINIT",
+	"ZSINIT",
+	"ZACK",
+	"ZFILE",
+	"ZSKIP",
+	"ZNAK",
+	"ZABORT",
+	"ZFIN",
+	"ZRPOS",
+	"ZDATA",
+	"ZEOF",
+	"ZFERR",
+	"ZCRC",
+	"ZCHALLENGE",
+	"ZCOMPL",
+	"ZCAN",
+	"ZFREECNT",
+	"ZCOMMAND",
+	"ZSTDERR",
+	"xxxxx"
+#define FRTYPES 22	/* Total number of frame types in this array */
+			/*  not including psuedo negative entries */
+};
+
+static char badcrc[] = "Bad CRC";
+
+/* Send ZMODEM binary header hdr of type type */
+void zsbhdr(type, hdr)
+int type;
+register char *hdr;
+{
+	register int n;
+	register unsigned short crc;
+
+	vfile("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
+	if (type == ZDATA)
+		for (n = Znulls; --n >=0; )
+			xsendline(0);
+
+	xsendline(ZPAD); xsendline(ZDLE);
+
+	if (Crc32t=Txfcs32)
+		zsbh32(hdr, type);
+	else {
+		xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0);
+
+		for (n=4; --n >= 0; ++hdr) {
+			zsendline(*hdr);
+			crc = updcrc((0377& *hdr), crc);
+		}
+		crc = updcrc(0,updcrc(0,crc));
+		zsendline(crc>>8);
+		zsendline(crc);
+	}
+	if (type != ZDATA)
+		flushmo();
+}
+
+
+/* Send ZMODEM binary header hdr of type type */
+void zsbh32(hdr, type)
+register char *hdr;
+int type;
+{
+	register int n;
+	register UNSL long crc;
+
+	xsendline(ZBIN32);  zsendline(type);
+	crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
+
+	for (n=4; --n >= 0; ++hdr) {
+		crc = UPDC32((0377 & *hdr), crc);
+		zsendline(*hdr);
+	}
+	crc = ~crc;
+	for (n=4; --n >= 0;) {
+		zsendline((int)crc);
+		crc >>= 8;
+	}
+}
+
+/* Send ZMODEM HEX header hdr of type type */
+void zshhdr(type, hdr)
+int type;
+register char *hdr;
+{
+	register int n;
+	register unsigned short crc;
+
+	vfile("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
+	sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
+	zputhex(type);
+	Crc32t = 0;
+
+	crc = updcrc(type, 0);
+	for (n=4; --n >= 0; ++hdr) {
+		zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
+	}
+	crc = updcrc(0,updcrc(0,crc));
+	zputhex(crc>>8); zputhex(crc);
+
+	/* Make it printable on remote machine */
+	sendline(015); sendline(0212);
+	/*
+	 * Uncork the remote in case a fake XOFF has stopped data flow
+	 */
+	if (type != ZFIN && type != ZACK)
+		sendline(021);
+	flushmo();
+}
+
+/*
+ * Send binary array buf of length length, with ending ZDLE sequence frameend
+ */
+static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
+
+void zsdata(buf, length, frameend)
+register char *buf;
+int length;
+int frameend;
+{
+	register unsigned short crc;
+
+	vfile("zsdata: %d %s", length, Zendnames[(frameend-ZCRCE)&3]);
+	if (Crc32t)
+		zsda32(buf, length, frameend);
+	else {
+		crc = 0;
+		for (;--length >= 0; ++buf) {
+			zsendline(*buf); crc = updcrc((0377 & *buf), crc);
+		}
+		xsendline(ZDLE); xsendline(frameend);
+		crc = updcrc(frameend, crc);
+
+		crc = updcrc(0,updcrc(0,crc));
+		zsendline(crc>>8); zsendline(crc);
+	}
+	if (frameend == ZCRCW) {
+		xsendline(XON);  flushmo();
+	}
+}
+
+void zsda32(buf, length, frameend)
+register char *buf;
+int length;
+int frameend;
+{
+	register int c;
+	register UNSL long crc;
+
+	crc = 0xFFFFFFFFL;
+	for (;--length >= 0; ++buf) {
+		c = *buf & 0377;
+		if (c & 0140)
+			xsendline(lastsent = c);
+		else
+			zsendline(c);
+		crc = UPDC32(c, crc);
+	}
+	xsendline(ZDLE); xsendline(frameend);
+	crc = UPDC32(frameend, crc);
+
+	crc = ~crc;
+	for (length=4; --length >= 0;) {
+		zsendline((int)crc);  crc >>= 8;
+	}
+}
+
+/*
+ * Receive array buf of max length with ending ZDLE sequence
+ *  and CRC.  Returns the ending character or error code.
+ *  NB: On errors may store length+1 bytes!
+ */
+int zrdata(buf, length)
+register char *buf;
+int length;
+{
+	register int c;
+	register unsigned short crc;
+	register char *end;
+	register int d;
+
+	if (Rxframeind == ZBIN32)
+		return zrdat32(buf, length);
+
+	crc = Rxcount = 0;  end = buf + length;
+	while (buf <= end) {
+		if ((c = zdlread()) & ~0377) {
+crcfoo:
+			switch (c) {
+			case GOTCRCE:
+			case GOTCRCG:
+			case GOTCRCQ:
+			case GOTCRCW:
+				crc = updcrc((d=c)&0377, crc);
+				if ((c = zdlread()) & ~0377)
+					goto crcfoo;
+				crc = updcrc(c, crc);
+				if ((c = zdlread()) & ~0377)
+					goto crcfoo;
+				crc = updcrc(c, crc);
+				if (crc & 0xFFFF) {
+					zperr(badcrc);
+					return ERROR;
+				}
+				Rxcount = length - (end - buf);
+				vfile("zrdata: %d  %s", Rxcount,
+				 Zendnames[(d-GOTCRCE)&3]);
+				return d;
+			case GOTCAN:
+				zperr("Sender Canceled");
+				return ZCAN;
+			case TIMEOUT:
+				zperr("TIMEOUT");
+				return c;
+			default:
+				zperr("Bad data subpacket");
+				return c;
+			}
+		}
+		*buf++ = c;
+		crc = updcrc(c, crc);
+	}
+	zperr("Data subpacket too long");
+	return ERROR;
+}
+
+int zrdat32(buf, length)
+register char *buf;
+int length;
+{
+	register int c;
+	register UNSL long crc;
+	register char *end;
+	register int d;
+
+	crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
+	while (buf <= end) {
+		if ((c = zdlread()) & ~0377) {
+crcfoo:
+			switch (c) {
+			case GOTCRCE:
+			case GOTCRCG:
+			case GOTCRCQ:
+			case GOTCRCW:
+				d = c;  c &= 0377;
+				crc = UPDC32(c, crc);
+				if ((c = zdlread()) & ~0377)
+					goto crcfoo;
+				crc = UPDC32(c, crc);
+				if ((c = zdlread()) & ~0377)
+					goto crcfoo;
+				crc = UPDC32(c, crc);
+				if ((c = zdlread()) & ~0377)
+					goto crcfoo;
+				crc = UPDC32(c, crc);
+				if ((c = zdlread()) & ~0377)
+					goto crcfoo;
+				crc = UPDC32(c, crc);
+				if (crc != 0xDEBB20E3) {
+					zperr(badcrc);
+					return ERROR;
+				}
+				Rxcount = length - (end - buf);
+				vfile("zrdat32: %d %s", Rxcount,
+				 Zendnames[(d-GOTCRCE)&3]);
+				return d;
+			case GOTCAN:
+				zperr("Sender Canceled");
+				return ZCAN;
+			case TIMEOUT:
+				zperr("TIMEOUT");
+				return c;
+			default:
+				zperr("Bad data subpacket");
+				return c;
+			}
+		}
+		*buf++ = c;
+		crc = UPDC32(c, crc);
+	}
+	zperr("Data subpacket too long");
+	return ERROR;
+}
+
+
+/*
+ * Read a ZMODEM header to hdr, either binary or hex.
+ *  eflag controls local display of non zmodem characters:
+ *	0:  no display
+ *	1:  display printing characters only
+ *	2:  display all non ZMODEM characters
+ *  On success, set Zmodem to 1, set Rxpos and return type of header.
+ *   Otherwise return negative on error.
+ *   Return ERROR instantly if ZCRCW sequence, for fast error recovery.
+ */
+int zgethdr(hdr, eflag)
+char *hdr;
+int eflag;
+{
+	register int c, n, cancount;
+
+	n = Zrwindow + Baudrate;	/* Max bytes before start of frame */
+	Rxframeind = Rxtype = 0;
+
+startover:
+	cancount = 5;
+again:
+	/* Return immediate ERROR if ZCRCW sequence seen */
+	switch (c = readline(Rxtimeout)) {
+	case RCDO:
+	case TIMEOUT:
+		goto fifi;
+	case CAN:
+gotcan:
+		if (--cancount <= 0) {
+			c = ZCAN; goto fifi;
+		}
+		switch (c = readline(1)) {
+		case TIMEOUT:
+			goto again;
+		case ZCRCW:
+			c = ERROR;
+		/* **** FALL THRU TO **** */
+		case RCDO:
+			goto fifi;
+		default:
+			break;
+		case CAN:
+			if (--cancount <= 0) {
+				c = ZCAN; goto fifi;
+			}
+			goto again;
+		}
+	/* **** FALL THRU TO **** */
+	default:
+agn2:
+		if ( --n == 0) {
+			zperr("Garbage count exceeded");
+			return(ERROR);
+		}
+		if (eflag && ((c &= 0177) & 0140))
+			bttyout(c);
+		else if (eflag > 1)
+			bttyout(c);
+#ifdef UNIX
+		fflush(stderr);
+#endif
+		goto startover;
+	case ZPAD|0200:		/* This is what we want. */
+		Not8bit = c;
+	case ZPAD:		/* This is what we want. */
+		break;
+	}
+	cancount = 5;
+splat:
+	switch (c = noxrd7()) {
+	case ZPAD:
+		goto splat;
+	case RCDO:
+	case TIMEOUT:
+		goto fifi;
+	default:
+		goto agn2;
+	case ZDLE:		/* This is what we want. */
+		break;
+	}
+
+	switch (c = noxrd7()) {
+	case RCDO:
+	case TIMEOUT:
+		goto fifi;
+	case ZBIN:
+		Rxframeind = ZBIN;  Crc32 = FALSE;
+		c =  zrbhdr(hdr);
+		break;
+	case ZBIN32:
+		Crc32 = Rxframeind = ZBIN32;
+		c =  zrbhdr32(hdr);
+		break;
+	case ZHEX:
+		Rxframeind = ZHEX;  Crc32 = FALSE;
+		c =  zrhhdr(hdr);
+		break;
+	case CAN:
+		goto gotcan;
+	default:
+		goto agn2;
+	}
+	Rxpos = hdr[ZP3] & 0377;
+	Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
+	Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
+	Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
+fifi:
+	switch (c) {
+	case GOTCAN:
+		c = ZCAN;
+	/* **** FALL THRU TO **** */
+	case ZNAK:
+	case ZCAN:
+	case ERROR:
+	case TIMEOUT:
+	case RCDO:
+		zperr("Got %s", frametypes[c+FTOFFSET]);
+	/* **** FALL THRU TO **** */
+	default:
+		if (c >= -3 && c <= FRTYPES)
+			vfile("zgethdr: %s %lx", frametypes[c+FTOFFSET], Rxpos);
+		else
+			vfile("zgethdr: %d %lx", c, Rxpos);
+	}
+	return c;
+}
+
+/* Receive a binary style header (type and position) */
+int zrbhdr(hdr)
+register char *hdr;
+{
+	register int c, n;
+	register unsigned short crc;
+
+	if ((c = zdlread()) & ~0377)
+		return c;
+	Rxtype = c;
+	crc = updcrc(c, 0);
+
+	for (n=4; --n >= 0; ++hdr) {
+		if ((c = zdlread()) & ~0377)
+			return c;
+		crc = updcrc(c, crc);
+		*hdr = c;
+	}
+	if ((c = zdlread()) & ~0377)
+		return c;
+	crc = updcrc(c, crc);
+	if ((c = zdlread()) & ~0377)
+		return c;
+	crc = updcrc(c, crc);
+	if (crc & 0xFFFF) {
+		zperr(badcrc);
+		return ERROR;
+	}
+#ifdef ZMODEM
+	Protocol = ZMODEM;
+#endif
+	Zmodem = 1;
+	return Rxtype;
+}
+
+/* Receive a binary style header (type and position) with 32 bit FCS */
+int zrbhdr32(hdr)
+register char *hdr;
+{
+	register int c, n;
+	register UNSL long crc;
+
+	if ((c = zdlread()) & ~0377)
+		return c;
+	Rxtype = c;
+	crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
+#ifdef DEBUGZ
+	vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
+#endif
+
+	for (n=4; --n >= 0; ++hdr) {
+		if ((c = zdlread()) & ~0377)
+			return c;
+		crc = UPDC32(c, crc);
+		*hdr = c;
+#ifdef DEBUGZ
+		vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
+#endif
+	}
+	for (n=4; --n >= 0;) {
+		if ((c = zdlread()) & ~0377)
+			return c;
+		crc = UPDC32(c, crc);
+#ifdef DEBUGZ
+		vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
+#endif
+	}
+	if (crc != 0xDEBB20E3) {
+		zperr(badcrc);
+		return ERROR;
+	}
+#ifdef ZMODEM
+	Protocol = ZMODEM;
+#endif
+	Zmodem = 1;
+	return Rxtype;
+}
+
+
+/* Receive a hex style header (type and position) */
+int zrhhdr(hdr)
+char *hdr;
+{
+	register int c;
+	register unsigned short crc;
+	register int n;
+
+	if ((c = zgethex()) < 0)
+		return c;
+	Rxtype = c;
+	crc = updcrc(c, 0);
+
+	for (n=4; --n >= 0; ++hdr) {
+		if ((c = zgethex()) < 0)
+			return c;
+		crc = updcrc(c, crc);
+		*hdr = c;
+	}
+	if ((c = zgethex()) < 0)
+		return c;
+	crc = updcrc(c, crc);
+	if ((c = zgethex()) < 0)
+		return c;
+	crc = updcrc(c, crc);
+	if (crc & 0xFFFF) {
+		zperr(badcrc); return ERROR;
+	}
+	switch ( c = readline(1)) {
+	case 0215:
+		Not8bit = c;
+		/* **** FALL THRU TO **** */
+	case 015:
+	 	/* Throw away possible cr/lf */
+		switch (c = readline(1)) {
+		case 012:
+			Not8bit |= c;
+		}
+	}
+#ifdef ZMODEM
+	Protocol = ZMODEM;
+#endif
+	Zmodem = 1; return Rxtype;
+}
+
+/* Send a byte as two hex digits */
+void zputhex(c)
+register int c;
+{
+	static char	digits[]	= "0123456789abcdef";
+
+	if (Verbose>8)
+		vfile("zputhex: %02X", c);
+	sendline(digits[(c&0xF0)>>4]);
+	sendline(digits[(c)&0xF]);
+}
+
+/*
+ * Send character c with ZMODEM escape sequence encoding.
+ *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
+ */
+void zsendline(c)
+int c;
+{
+
+	/* Quick check for non control characters */
+	if (c & 0140)
+		xsendline(lastsent = c);
+	else {
+		switch (c &= 0377) {
+		case ZDLE:
+			xsendline(ZDLE);
+			xsendline (lastsent = (c ^= 0100));
+			break;
+		case 015:
+		case 0215:
+			if (!Zctlesc && (lastsent & 0177) != '@')
+				goto sendit;
+		/* **** FALL THRU TO **** */
+		case 020:
+		case 021:
+		case 023:
+		case 0220:
+		case 0221:
+		case 0223:
+			xsendline(ZDLE);
+			c ^= 0100;
+	sendit:
+			xsendline(lastsent = c);
+			break;
+		default:
+			if (Zctlesc && ! (c & 0140)) {
+				xsendline(ZDLE);
+				c ^= 0100;
+			}
+			xsendline(lastsent = c);
+		}
+	}
+}
+
+/* Decode two lower case hex digits into an 8 bit byte value */
+int zgethex()
+{
+	register int c;
+
+	c = zgeth1();
+	if (Verbose>8)
+		vfile("zgethex: %02X", c);
+	return c;
+}
+int zgeth1()
+{
+	register int c, n;
+
+	if ((c = noxrd7()) < 0)
+		return c;
+	n = c - '0';
+	if (n > 9)
+		n -= ('a' - ':');
+	if (n & ~0xF)
+		return ERROR;
+	if ((c = noxrd7()) < 0)
+		return c;
+	c -= '0';
+	if (c > 9)
+		c -= ('a' - ':');
+	if (c & ~0xF)
+		return ERROR;
+	c += (n<<4);
+	return c;
+}
+
+/*
+ * Read a byte, checking for ZMODEM escape encoding
+ *  including CAN*5 which represents a quick abort
+ */
+int zdlread()
+{
+	register int c;
+
+again:
+	/* Quick check for non control characters */
+	if ((c = readline(Rxtimeout)) & 0140)
+		return c;
+	switch (c) {
+	case ZDLE:
+		break;
+	case 023:
+	case 0223:
+	case 021:
+	case 0221:
+		goto again;
+	default:
+		if (Zctlesc && !(c & 0140)) {
+			goto again;
+		}
+		return c;
+	}
+again2:
+	if ((c = readline(Rxtimeout)) < 0)
+		return c;
+	if (c == CAN && (c = readline(Rxtimeout)) < 0)
+		return c;
+	if (c == CAN && (c = readline(Rxtimeout)) < 0)
+		return c;
+	if (c == CAN && (c = readline(Rxtimeout)) < 0)
+		return c;
+	switch (c) {
+	case CAN:
+		return GOTCAN;
+	case ZCRCE:
+	case ZCRCG:
+	case ZCRCQ:
+	case ZCRCW:
+		return (c | GOTOR);
+	case ZRUB0:
+		return 0177;
+	case ZRUB1:
+		return 0377;
+	case 023:
+	case 0223:
+	case 021:
+	case 0221:
+		goto again2;
+	default:
+		if (Zctlesc && ! (c & 0140)) {
+			goto again2;
+		}
+		if ((c & 0140) ==  0100)
+			return (c ^ 0100);
+		break;
+	}
+	if (Verbose>1)
+		zperr("Bad escape sequence %x", c);
+	return ERROR;
+}
+
+/*
+ * Read a character from the modem line with timeout.
+ *  Eat parity, XON and XOFF characters.
+ */
+int noxrd7()
+{
+	register int c;
+
+	for (;;) {
+		if ((c = readline(Rxtimeout)) < 0)
+			return c;
+		switch (c &= 0177) {
+		case XON:
+		case XOFF:
+			continue;
+		default:
+			if (Zctlesc && !(c & 0140))
+				continue;
+		case '\r':
+		case '\n':
+		case ZDLE:
+			return c;
+		}
+	}
+}
+
+/* Store long integer pos in Txhdr */
+void stohdr(pos)
+long pos;
+{
+	Txhdr[ZP0] = pos;
+	Txhdr[ZP1] = pos>>8;
+	Txhdr[ZP2] = pos>>16;
+	Txhdr[ZP3] = pos>>24;
+}
+
+/* Recover a long integer from a header */
+long
+rclhdr(hdr)
+register char *hdr;
+{
+	register long l;
+
+	l = (hdr[ZP3] & 0377);
+	l = (l << 8) | (hdr[ZP2] & 0377);
+	l = (l << 8) | (hdr[ZP1] & 0377);
+	l = (l << 8) | (hdr[ZP0] & 0377);
+	return l;
+}
+
+/* End of zm.c */
Index: /trunk/minix/commands/zmodem/zmodem.h
===================================================================
--- /trunk/minix/commands/zmodem/zmodem.h	(revision 9)
+++ /trunk/minix/commands/zmodem/zmodem.h	(revision 9)
@@ -0,0 +1,161 @@
+/*
+ *   Z M O D E M . H     Manifest constants for ZMODEM
+ *    application to application file transfer protocol
+ *    05-23-87  Chuck Forsberg Omen Technology Inc
+ */
+#define ZPAD '*'	/* 052 Padding character begins frames */
+#define ZDLE 030	/* Ctrl-X Zmodem escape - `ala BISYNC DLE */
+#define ZDLEE (ZDLE^0100)	/* Escaped ZDLE as transmitted */
+#define ZBIN 'A'	/* Binary frame indicator */
+#define ZHEX 'B'	/* HEX frame indicator */
+#define ZBIN32 'C'	/* Binary frame with 32 bit FCS */
+
+/* Frame types (see array "frametypes" in zm.c) */
+#define ZRQINIT	0	/* Request receive init */
+#define ZRINIT	1	/* Receive init */
+#define ZSINIT 2	/* Send init sequence (optional) */
+#define ZACK 3		/* ACK to above */
+#define ZFILE 4		/* File name from sender */
+#define ZSKIP 5		/* To sender: skip this file */
+#define ZNAK 6		/* Last packet was garbled */
+#define ZABORT 7	/* Abort batch transfers */
+#define ZFIN 8		/* Finish session */
+#define ZRPOS 9		/* Resume data trans at this position */
+#define ZDATA 10	/* Data packet(s) follow */
+#define ZEOF 11		/* End of file */
+#define ZFERR 12	/* Fatal Read or Write error Detected */
+#define ZCRC 13		/* Request for file CRC and response */
+#define ZCHALLENGE 14	/* Receiver's Challenge */
+#define ZCOMPL 15	/* Request is complete */
+#define ZCAN 16		/* Other end canned session with CAN*5 */
+#define ZFREECNT 17	/* Request for free bytes on filesystem */
+#define ZCOMMAND 18	/* Command from sending program */
+#define ZSTDERR 19	/* Output to standard error, data follows */
+
+/* ZDLE sequences */
+#define ZCRCE 'h'	/* CRC next, frame ends, header packet follows */
+#define ZCRCG 'i'	/* CRC next, frame continues nonstop */
+#define ZCRCQ 'j'	/* CRC next, frame continues, ZACK expected */
+#define ZCRCW 'k'	/* CRC next, ZACK expected, end of frame */
+#define ZRUB0 'l'	/* Translate to rubout 0177 */
+#define ZRUB1 'm'	/* Translate to rubout 0377 */
+
+/* zdlread return values (internal) */
+/* -1 is general error, -2 is timeout */
+#define GOTOR 0400
+#define GOTCRCE (ZCRCE|GOTOR)	/* ZDLE-ZCRCE received */
+#define GOTCRCG (ZCRCG|GOTOR)	/* ZDLE-ZCRCG received */
+#define GOTCRCQ (ZCRCQ|GOTOR)	/* ZDLE-ZCRCQ received */
+#define GOTCRCW (ZCRCW|GOTOR)	/* ZDLE-ZCRCW received */
+#define GOTCAN	(GOTOR|030)	/* CAN*5 seen */
+
+/* Byte positions within header array */
+#define ZF0	3	/* First flags byte */
+#define ZF1	2
+#define ZF2	1
+#define ZF3	0
+#define ZP0	0	/* Low order 8 bits of position */
+#define ZP1	1
+#define ZP2	2
+#define ZP3	3	/* High order 8 bits of file position */
+
+/* Bit Masks for ZRINIT flags byte ZF0 */
+#define CANFDX	01	/* Rx can send and receive true FDX */
+#define CANOVIO	02	/* Rx can receive data during disk I/O */
+#define CANBRK	04	/* Rx can send a break signal */
+#define CANCRY	010	/* Receiver can decrypt */
+#define CANLZW	020	/* Receiver can uncompress */
+#define CANFC32	040	/* Receiver can use 32 bit Frame Check */
+#define ESCCTL 0100	/* Receiver expects ctl chars to be escaped */
+#define ESC8   0200	/* Receiver expects 8th bit to be escaped */
+
+/* Parameters for ZSINIT frame */
+#define ZATTNLEN 32	/* Max length of attention string */
+/* Bit Masks for ZSINIT flags byte ZF0 */
+#define TESCCTL 0100	/* Transmitter expects ctl chars to be escaped */
+#define TESC8   0200	/* Transmitter expects 8th bit to be escaped */
+
+/* Parameters for ZFILE frame */
+/* Conversion options one of these in ZF0 */
+#define ZCBIN	1	/* Binary transfer - inhibit conversion */
+#define ZCNL	2	/* Convert NL to local end of line convention */
+#define ZCRESUM	3	/* Resume interrupted file transfer */
+/* Management include options, one of these ored in ZF1 */
+#define ZMSKNOLOC	0200	/* Skip file if not present at rx */
+/* Management options, one of these ored in ZF1 */
+#define ZMMASK	037	/* Mask for the choices below */
+#define ZMNEWL	1	/* Transfer if source newer or longer */
+#define ZMCRC	2	/* Transfer if different file CRC or length */
+#define ZMAPND	3	/* Append contents to existing file (if any) */
+#define ZMCLOB	4	/* Replace existing file */
+#define ZMNEW	5	/* Transfer if source newer */
+	/* Number 5 is alive ... */
+#define ZMDIFF	6	/* Transfer if dates or lengths different */
+#define ZMPROT	7	/* Protect destination file */
+/* Transport options, one of these in ZF2 */
+#define ZTLZW	1	/* Lempel-Ziv compression */
+#define ZTCRYPT	2	/* Encryption */
+#define ZTRLE	3	/* Run Length encoding */
+/* Extended options for ZF3, bit encoded */
+#define ZXSPARS	64	/* Encoding for sparse file operations */
+
+/* Parameters for ZCOMMAND frame ZF0 (otherwise 0) */
+#define ZCACK1	1	/* Acknowledge, then do command */
+
+/* Globals used by ZMODEM functions */
+extern Rxframeind;	/* ZBIN ZBIN32, or ZHEX type of frame received */
+extern Rxtype;		/* Type of header received */
+extern Rxcount;		/* Count of data bytes received */
+extern Zrwindow;	/* RX window size (controls garbage count) */
+extern Rxtimeout;	/* Tenths of seconds to wait for something */
+extern char Rxhdr[4];	/* Received header */
+extern char Txhdr[4];	/* Transmitted header */
+extern long Rxpos;	/* Received file position */
+extern long Txpos;	/* Transmitted file position */
+extern Txfcs32;		/* TURE means send binary frames with 32 bit FCS */
+extern Crc32t;		/* Display flag indicating 32 bit CRC being sent */
+extern Crc32;		/* Display flag indicating 32 bit CRC being received */
+extern Znulls;		/* Number of nulls to send at beginning of ZDATA hdr */
+extern char Attn[ZATTNLEN+1];	/* Attention string rx sends to tx on err */
+
+/* crctab.c */
+
+_PROTOTYPE(long UPDC32 , (int b , long c ));
+
+/* rbsb.c */
+
+_PROTOTYPE(void from_cu , (void));
+_PROTOTYPE(void cucheck , (void));
+_PROTOTYPE(int rdchk , (int f ));
+_PROTOTYPE(int rdchk , (int f ));
+_PROTOTYPE(int mode , (int n ));
+_PROTOTYPE(void sendbrk , (void));
+
+/* zm.c */
+
+_PROTOTYPE(void zsbhdr , (int type , char *hdr ));
+_PROTOTYPE(void zsbh32 , (char *hdr , int type ));
+_PROTOTYPE(void zshhdr , (int type , char *hdr ));
+_PROTOTYPE(void zsdata , (char *buf , int length , int frameend ));
+_PROTOTYPE(void zsda32 , (char *buf , int length , int frameend ));
+_PROTOTYPE(int zrdata , (char *buf , int length ));
+_PROTOTYPE(int zrdat32 , (char *buf , int length ));
+_PROTOTYPE(int zgethdr , (char *hdr , int eflag ));
+_PROTOTYPE(int zrbhdr , (char *hdr ));
+_PROTOTYPE(int zrbhdr32 , (char *hdr ));
+_PROTOTYPE(int zrhhdr , (char *hdr ));
+_PROTOTYPE(void zputhex , (int c ));
+_PROTOTYPE(void zsendline , (int c ));
+_PROTOTYPE(int zgethex , (void));
+_PROTOTYPE(int zgeth1 , (void));
+_PROTOTYPE(int zdlread , (void));
+_PROTOTYPE(int noxrd7 , (void));
+_PROTOTYPE(void stohdr , (long pos ));
+_PROTOTYPE(long rclhdr , (char *hdr ));
+
+/* rz.c sz.c */
+
+void vfile();
+_PROTOTYPE(void bibi , (int n ));
+
+/* End of ZMODEM.H */
Index: /trunk/minix/drivers/Makefile
===================================================================
--- /trunk/minix/drivers/Makefile	(revision 9)
+++ /trunk/minix/drivers/Makefile	(revision 9)
@@ -0,0 +1,46 @@
+# Makefile for all device drivers.
+#
+MAKE = exec make -$(MAKEFLAGS)
+
+usage:
+	@echo "" >&2
+	@echo "Makefile for all device drivers." >&2
+	@echo "Usage:" >&2
+	@echo "	make build    # Compile all device drivers locally" >&2
+	@echo "	make image    # Compile drivers in boot image" >&2
+	@echo "	make clean    # Remove local compiler results" >&2
+	@echo "	make install  # Install drivers to /etc/drivers/" >&2
+	@echo "	                (requires root privileges)" >&2
+	@echo "" >&2
+
+build: all
+all install depend clean:
+	cd ./libdriver && $(MAKE) $@
+	cd ./tty && $(MAKE) $@
+	cd ./at_wini && $(MAKE) $@
+	cd ./floppy && $(MAKE) $@
+	cd ./printer && $(MAKE) $@
+	cd ./rtl8139 && $(MAKE) $@
+	cd ./fxp && $(MAKE) $@
+	cd ./dpeth && $(MAKE) $@
+	cd ./log && $(MAKE) $@
+	cd ./bios_wini && $(MAKE) $@
+	cd ./cmos && $(MAKE) $@
+	cd ./random && $(MAKE) $@
+	cd ./rescue && $(MAKE) $@
+	cd ./dp8390 && $(MAKE) $@
+	cd ./sb16 && $(MAKE) $@
+	cd ./lance && $(MAKE) $@
+	cd ./pci && $(MAKE) $@
+	cd ./ti1225 && $(MAKE) $@
+	cd ./memory && $(MAKE) $@	# Must be last for ramdisk image
+
+image:
+	cd ./libdriver && $(MAKE) build
+	cd ./tty && $(MAKE) build
+	cd ./at_wini && $(MAKE) build
+	cd ./floppy && $(MAKE) build
+	cd ./bios_wini && $(MAKE) build
+	cd ./log && $(MAKE) build
+	cd ./pci && $(MAKE) build
+	cd ./memory && $(MAKE) build	# Must be last for ramdisk image
Index: /trunk/minix/drivers/at_wini/.depend
===================================================================
--- /trunk/minix/drivers/at_wini/.depend	(revision 9)
+++ /trunk/minix/drivers/at_wini/.depend	(revision 9)
@@ -0,0 +1,96 @@
+
+at_wini.o:	../drivers.h
+at_wini.o:	../libdriver/driver.h
+at_wini.o:	../libdriver/drvlib.h
+at_wini.o:	/usr/include/ansi.h
+at_wini.o:	/usr/include/errno.h
+at_wini.o:	/usr/include/ibm/bios.h
+at_wini.o:	/usr/include/ibm/interrupt.h
+at_wini.o:	/usr/include/ibm/partition.h
+at_wini.o:	/usr/include/ibm/pci.h
+at_wini.o:	/usr/include/ibm/ports.h
+at_wini.o:	/usr/include/limits.h
+at_wini.o:	/usr/include/minix/bitmap.h
+at_wini.o:	/usr/include/minix/callnr.h
+at_wini.o:	/usr/include/minix/com.h
+at_wini.o:	/usr/include/minix/config.h
+at_wini.o:	/usr/include/minix/const.h
+at_wini.o:	/usr/include/minix/devio.h
+at_wini.o:	/usr/include/minix/dmap.h
+at_wini.o:	/usr/include/minix/ioctl.h
+at_wini.o:	/usr/include/minix/ipc.h
+at_wini.o:	/usr/include/minix/keymap.h
+at_wini.o:	/usr/include/minix/partition.h
+at_wini.o:	/usr/include/minix/sys_config.h
+at_wini.o:	/usr/include/minix/syslib.h
+at_wini.o:	/usr/include/minix/sysutil.h
+at_wini.o:	/usr/include/minix/type.h
+at_wini.o:	/usr/include/minix/u64.h
+at_wini.o:	/usr/include/signal.h
+at_wini.o:	/usr/include/stddef.h
+at_wini.o:	/usr/include/stdlib.h
+at_wini.o:	/usr/include/string.h
+at_wini.o:	/usr/include/sys/dir.h
+at_wini.o:	/usr/include/sys/ioc_disk.h
+at_wini.o:	/usr/include/sys/types.h
+at_wini.o:	/usr/include/unistd.h
+at_wini.o:	at_wini.c
+at_wini.o:	at_wini.h
+
+../libdriver/driver.o:	../libdriver/../drivers.h
+../libdriver/driver.o:	../libdriver/driver.c
+../libdriver/driver.o:	../libdriver/driver.h
+../libdriver/driver.o:	/usr/include/ansi.h
+../libdriver/driver.o:	/usr/include/errno.h
+../libdriver/driver.o:	/usr/include/ibm/bios.h
+../libdriver/driver.o:	/usr/include/ibm/interrupt.h
+../libdriver/driver.o:	/usr/include/ibm/ports.h
+../libdriver/driver.o:	/usr/include/limits.h
+../libdriver/driver.o:	/usr/include/minix/bitmap.h
+../libdriver/driver.o:	/usr/include/minix/callnr.h
+../libdriver/driver.o:	/usr/include/minix/com.h
+../libdriver/driver.o:	/usr/include/minix/config.h
+../libdriver/driver.o:	/usr/include/minix/const.h
+../libdriver/driver.o:	/usr/include/minix/devio.h
+../libdriver/driver.o:	/usr/include/minix/dmap.h
+../libdriver/driver.o:	/usr/include/minix/ioctl.h
+../libdriver/driver.o:	/usr/include/minix/ipc.h
+../libdriver/driver.o:	/usr/include/minix/partition.h
+../libdriver/driver.o:	/usr/include/minix/sys_config.h
+../libdriver/driver.o:	/usr/include/minix/syslib.h
+../libdriver/driver.o:	/usr/include/minix/sysutil.h
+../libdriver/driver.o:	/usr/include/minix/type.h
+../libdriver/driver.o:	/usr/include/minix/u64.h
+../libdriver/driver.o:	/usr/include/signal.h
+../libdriver/driver.o:	/usr/include/stddef.h
+../libdriver/driver.o:	/usr/include/stdlib.h
+../libdriver/driver.o:	/usr/include/string.h
+../libdriver/driver.o:	/usr/include/sys/dir.h
+../libdriver/driver.o:	/usr/include/sys/ioc_disk.h
+../libdriver/driver.o:	/usr/include/sys/types.h
+../libdriver/driver.o:	/usr/include/unistd.h
+
+../libdriver/drvlib.o:	../libdriver/driver.h
+../libdriver/drvlib.o:	../libdriver/drvlib.c
+../libdriver/drvlib.o:	../libdriver/drvlib.h
+../libdriver/drvlib.o:	/usr/include/ansi.h
+../libdriver/drvlib.o:	/usr/include/errno.h
+../libdriver/drvlib.o:	/usr/include/ibm/partition.h
+../libdriver/drvlib.o:	/usr/include/limits.h
+../libdriver/drvlib.o:	/usr/include/minix/callnr.h
+../libdriver/drvlib.o:	/usr/include/minix/com.h
+../libdriver/drvlib.o:	/usr/include/minix/config.h
+../libdriver/drvlib.o:	/usr/include/minix/const.h
+../libdriver/drvlib.o:	/usr/include/minix/devio.h
+../libdriver/drvlib.o:	/usr/include/minix/ipc.h
+../libdriver/drvlib.o:	/usr/include/minix/partition.h
+../libdriver/drvlib.o:	/usr/include/minix/sys_config.h
+../libdriver/drvlib.o:	/usr/include/minix/syslib.h
+../libdriver/drvlib.o:	/usr/include/minix/sysutil.h
+../libdriver/drvlib.o:	/usr/include/minix/type.h
+../libdriver/drvlib.o:	/usr/include/minix/u64.h
+../libdriver/drvlib.o:	/usr/include/stddef.h
+../libdriver/drvlib.o:	/usr/include/string.h
+../libdriver/drvlib.o:	/usr/include/sys/dir.h
+../libdriver/drvlib.o:	/usr/include/sys/types.h
+../libdriver/drvlib.o:	/usr/include/unistd.h
Index: /trunk/minix/drivers/at_wini/Makefile
===================================================================
--- /trunk/minix/drivers/at_wini/Makefile	(revision 9)
+++ /trunk/minix/drivers/at_wini/Makefile	(revision 9)
@@ -0,0 +1,47 @@
+# Makefile for the AT disk driver (AT_WINI)
+DRIVER = at_wini
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+p = ../libpci
+
+# programs, flags, etc.
+MAKE = exec make
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsysutil -lsys -ltimers
+
+OBJ = at_wini.o 
+LIBDRIVER = $d/libdriver/driver.o $d/libdriver/drvlib.o 
+
+
+# build local binary
+all build:	$(DRIVER)
+$(DRIVER):	$(OBJ) $(LIBDRIVER)
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBDRIVER) $(LIBS)
+	install -S 8k $(DRIVER)
+
+$(LIBDRIVER): 
+	cd $d/libdriver && $(MAKE) 
+
+# install with other drivers
+install:	/sbin/$(DRIVER)
+/sbin/$(DRIVER):	$(DRIVER)
+	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f $(DRIVER) *.o *.bak 
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c ../libdriver/*.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/at_wini/at_wini.c
===================================================================
--- /trunk/minix/drivers/at_wini/at_wini.c	(revision 9)
+++ /trunk/minix/drivers/at_wini/at_wini.c	(revision 9)
@@ -0,0 +1,2485 @@
+/* This file contains the device dependent part of a driver for the IBM-AT
+ * winchester controller.  Written by Adri Koppes.
+ *
+ * The file contains one entry point:
+ *
+ *   at_winchester_task:	main entry when system is brought up
+ *
+ * Changes:
+ *   Aug 19, 2005   ATA PCI support, supports SATA  (Ben Gras)
+ *   Nov 18, 2004   moved AT disk driver to user-space  (Jorrit N. Herder)
+ *   Aug 20, 2004   watchdogs replaced by sync alarms  (Jorrit N. Herder)
+ *   Mar 23, 2000   added ATAPI CDROM support  (Michael Temari)
+ *   May 14, 2000   d-d/i rewrite  (Kees J. Bot)
+ *   Apr 13, 1992   device dependent/independent split  (Kees J. Bot)
+ */
+
+#include "at_wini.h"
+
+#include <minix/sysutil.h>
+#include <minix/keymap.h>
+#include <sys/ioc_disk.h>
+#include <ibm/pci.h>
+
+#define ATAPI_DEBUG	    0	/* To debug ATAPI code. */
+
+/* I/O Ports used by winchester disk controllers. */
+
+/* Read and write registers */
+#define REG_CMD_BASE0	0x1F0	/* command base register of controller 0 */
+#define REG_CMD_BASE1	0x170	/* command base register of controller 1 */
+#define REG_CTL_BASE0	0x3F6	/* control base register of controller 0 */
+#define REG_CTL_BASE1	0x376	/* control base register of controller 1 */
+
+#define PCI_CTL_OFF	    2	/* Offset of control registers from BAR2 */
+#define PCI_DMA_2ND_OFF	    8	/* Offset of DMA registers from BAR4 for 
+				 * secondary channel
+				 */
+
+#define REG_DATA	    0	/* data register (offset from the base reg.) */
+#define REG_PRECOMP	    1	/* start of write precompensation */
+#define REG_COUNT	    2	/* sectors to transfer */
+#define REG_SECTOR	    3	/* sector number */
+#define REG_CYL_LO	    4	/* low byte of cylinder number */
+#define REG_CYL_HI	    5	/* high byte of cylinder number */
+#define REG_LDH		    6	/* lba, drive and head */
+#define   LDH_DEFAULT		0xA0	/* ECC enable, 512 bytes per sector */
+#define   LDH_LBA		0x40	/* Use LBA addressing */
+#define	  LDH_DEV		0x10	/* Drive 1 iff set */
+#define   ldh_init(drive)	(LDH_DEFAULT | ((drive) << 4))
+
+/* Read only registers */
+#define REG_STATUS	    7	/* status */
+#define   STATUS_BSY		0x80	/* controller busy */
+#define	  STATUS_RDY		0x40	/* drive ready */
+#define	  STATUS_WF		0x20	/* write fault */
+#define	  STATUS_SC		0x10	/* seek complete (obsolete) */
+#define	  STATUS_DRQ		0x08	/* data transfer request */
+#define	  STATUS_CRD		0x04	/* corrected data */
+#define	  STATUS_IDX		0x02	/* index pulse */
+#define	  STATUS_ERR		0x01	/* error */
+#define	  STATUS_ADMBSY	       0x100	/* administratively busy (software) */
+#define REG_ERROR	    1	/* error code */
+#define	  ERROR_BB		0x80	/* bad block */
+#define	  ERROR_ECC		0x40	/* bad ecc bytes */
+#define	  ERROR_ID		0x10	/* id not found */
+#define	  ERROR_AC		0x04	/* aborted command */
+#define	  ERROR_TK		0x02	/* track zero error */
+#define	  ERROR_DM		0x01	/* no data address mark */
+
+/* Write only registers */
+#define REG_COMMAND	    7	/* command */
+#define   CMD_IDLE		0x00	/* for w_command: drive idle */
+#define   CMD_RECALIBRATE	0x10	/* recalibrate drive */
+#define   CMD_READ		0x20	/* read data */
+#define   CMD_READ_EXT		0x24	/* read data (LBA48 addressed) */
+#define   CMD_READ_DMA_EXT	0x25	/* read data using DMA (w/ LBA48) */
+#define   CMD_WRITE		0x30	/* write data */
+#define	  CMD_WRITE_EXT		0x34	/* write data (LBA48 addressed) */
+#define   CMD_WRITE_DMA_EXT	0x35	/* write data using DMA (w/ LBA48) */
+#define   CMD_READVERIFY	0x40	/* read verify */
+#define   CMD_FORMAT		0x50	/* format track */
+#define   CMD_SEEK		0x70	/* seek cylinder */
+#define   CMD_DIAG		0x90	/* execute device diagnostics */
+#define   CMD_SPECIFY		0x91	/* specify parameters */
+#define   CMD_READ_DMA		0xC8	/* read data using DMA */
+#define   CMD_WRITE_DMA		0xCA	/* write data using DMA */
+#define   ATA_IDENTIFY		0xEC	/* identify drive */
+/* #define REG_CTL		0x206	*/ /* control register */
+#define REG_CTL		0	/* control register */
+#define   CTL_NORETRY		0x80	/* disable access retry */
+#define   CTL_NOECC		0x40	/* disable ecc retry */
+#define   CTL_EIGHTHEADS	0x08	/* more than eight heads */
+#define   CTL_RESET		0x04	/* reset controller */
+#define   CTL_INTDISABLE	0x02	/* disable interrupts */
+#define REG_CTL_ALTSTAT 0	/* alternate status register */
+
+/* Identify words */
+#define ID_GENERAL		0x00	/* General configuration information */
+#define		ID_GEN_NOT_ATA		0x8000	/* Not an ATA device */
+#define ID_CAPABILITIES		0x31	/* Capabilities (49)*/
+#define		ID_CAP_LBA		0x0200	/* LBA supported */
+#define		ID_CAP_DMA		0x0100	/* DMA supported */
+#define ID_FIELD_VALIDITY	0x35	/* Field Validity (53) */
+#define		ID_FV_88		0x04	/* Word 88 is valid (UDMA) */
+#define ID_MULTIWORD_DMA	0x3f	/* Multiword DMA (63) */
+#define		ID_MWDMA_2_SEL		0x0400	/* Mode 2 is selected */
+#define		ID_MWDMA_1_SEL		0x0200	/* Mode 1 is selected */
+#define		ID_MWDMA_0_SEL		0x0100	/* Mode 0 is selected */
+#define		ID_MWDMA_2_SUP		0x0004	/* Mode 2 is supported */
+#define		ID_MWDMA_1_SUP		0x0002	/* Mode 1 is supported */
+#define		ID_MWDMA_0_SUP		0x0001	/* Mode 0 is supported */
+#define ID_CSS			0x53	/* Command Sets Supported (83) */
+#define		ID_CSS_LBA48		0x0400
+#define ID_ULTRA_DMA		0x58	/* Ultra DMA (88) */
+#define		ID_UDMA_5_SEL		0x2000	/* Mode 5 is selected */
+#define		ID_UDMA_4_SEL		0x1000	/* Mode 4 is selected */
+#define		ID_UDMA_3_SEL		0x0800	/* Mode 3 is selected */
+#define		ID_UDMA_2_SEL		0x0400	/* Mode 2 is selected */
+#define		ID_UDMA_1_SEL		0x0200	/* Mode 1 is selected */
+#define		ID_UDMA_0_SEL		0x0100	/* Mode 0 is selected */
+#define		ID_UDMA_5_SUP		0x0020	/* Mode 5 is supported */
+#define		ID_UDMA_4_SUP		0x0010	/* Mode 4 is supported */
+#define		ID_UDMA_3_SUP		0x0008	/* Mode 3 is supported */
+#define		ID_UDMA_2_SUP		0x0004	/* Mode 2 is supported */
+#define		ID_UDMA_1_SUP		0x0002	/* Mode 1 is supported */
+#define		ID_UDMA_0_SUP		0x0001	/* Mode 0 is supported */
+
+/* DMA registers */
+#define DMA_COMMAND		0		/* Command register */
+#define		DMA_CMD_WRITE		0x08	/* PCI bus master writes */
+#define		DMA_CMD_START		0x01	/* Start Bus Master */
+#define DMA_STATUS		2		/* Status register */
+#define		DMA_ST_D1_DMACAP	0x40	/* Drive 1 is DMA capable */
+#define		DMA_ST_D0_DMACAP	0x20	/* Drive 0 is DMA capable */
+#define		DMA_ST_INT		0x04	/* Interrupt */
+#define		DMA_ST_ERROR		0x02	/* Error */
+#define		DMA_ST_BM_ACTIVE	0x01	/* Bus Master IDE Active */
+#define DMA_PRDTP		4		/* PRD Table Pointer */
+
+/* Check for the presence of LBA48 only on drives that are 'big'. */
+#define LBA48_CHECK_SIZE	0x0f000000
+#define LBA_MAX_SIZE		0x0fffffff	/* Highest sector size for
+						 * regular LBA.
+						 */
+
+#if ENABLE_ATAPI
+#define   ERROR_SENSE           0xF0    /* sense key mask */
+#define     SENSE_NONE          0x00    /* no sense key */
+#define     SENSE_RECERR        0x10    /* recovered error */
+#define     SENSE_NOTRDY        0x20    /* not ready */
+#define     SENSE_MEDERR        0x30    /* medium error */
+#define     SENSE_HRDERR        0x40    /* hardware error */
+#define     SENSE_ILRQST        0x50    /* illegal request */
+#define     SENSE_UATTN         0x60    /* unit attention */
+#define     SENSE_DPROT         0x70    /* data protect */
+#define     SENSE_ABRT          0xb0    /* aborted command */
+#define     SENSE_MISCOM        0xe0    /* miscompare */
+#define   ERROR_MCR             0x08    /* media change requested */
+#define   ERROR_ABRT            0x04    /* aborted command */
+#define   ERROR_EOM             0x02    /* end of media detected */
+#define   ERROR_ILI             0x01    /* illegal length indication */
+#define REG_FEAT            1   /* features */
+#define   FEAT_OVERLAP          0x02    /* overlap */
+#define   FEAT_DMA              0x01    /* dma */
+#define REG_IRR             2   /* interrupt reason register */
+#define   IRR_REL               0x04    /* release */
+#define   IRR_IO                0x02    /* direction for xfer */
+#define   IRR_COD               0x01    /* command or data */
+#define REG_SAMTAG          3
+#define REG_CNT_LO          4   /* low byte of cylinder number */
+#define REG_CNT_HI          5   /* high byte of cylinder number */
+#define REG_DRIVE           6   /* drive select */
+#endif
+
+#define REG_STATUS          7   /* status */
+#define   STATUS_BSY            0x80    /* controller busy */
+#define   STATUS_DRDY           0x40    /* drive ready */
+#define   STATUS_DMADF          0x20    /* dma ready/drive fault */
+#define   STATUS_SRVCDSC        0x10    /* service or dsc */
+#define   STATUS_DRQ            0x08    /* data transfer request */
+#define   STATUS_CORR           0x04    /* correctable error occurred */
+#define   STATUS_CHECK          0x01    /* check error */
+
+#ifdef ENABLE_ATAPI
+#define   ATAPI_PACKETCMD       0xA0    /* packet command */
+#define   ATAPI_IDENTIFY        0xA1    /* identify drive */
+#define   SCSI_READ10           0x28    /* read from disk */
+#define   SCSI_SENSE            0x03    /* sense request */
+
+#define CD_SECTOR_SIZE		2048	/* sector size of a CD-ROM */
+#endif /* ATAPI */
+
+/* Interrupt request lines. */
+#define NO_IRQ		 0	/* no IRQ set yet */
+
+#define ATAPI_PACKETSIZE	12
+#define SENSE_PACKETSIZE	18
+
+/* Common command block */
+struct command {
+  u8_t	precomp;	/* REG_PRECOMP, etc. */
+  u8_t	count;
+  u8_t	sector;
+  u8_t	cyl_lo;
+  u8_t	cyl_hi;
+  u8_t	ldh;
+  u8_t	command;
+
+  /* The following at for LBA48 */
+  u8_t	count_prev;
+  u8_t	sector_prev;
+  u8_t	cyl_lo_prev;
+  u8_t	cyl_hi_prev;
+};
+
+/* Error codes */
+#define ERR		 (-1)	/* general error */
+#define ERR_BAD_SECTOR	 (-2)	/* block marked bad detected */
+
+/* Some controllers don't interrupt, the clock will wake us up. */
+#define WAKEUP		(32*HZ)	/* drive may be out for 31 seconds max */
+
+/* Miscellaneous. */
+#define MAX_DRIVES         8
+#define COMPAT_DRIVES      4
+#if _WORD_SIZE > 2
+#define MAX_SECS	 256	/* controller can transfer this many sectors */
+#else
+#define MAX_SECS	 127	/* but not to a 16 bit process */
+#endif
+#define MAX_ERRORS         4	/* how often to try rd/wt before quitting */
+#define NR_MINORS       (MAX_DRIVES * DEV_PER_DRIVE)
+#define SUB_PER_DRIVE	(NR_PARTITIONS * NR_PARTITIONS)
+#define NR_SUBDEVS	(MAX_DRIVES * SUB_PER_DRIVE)
+#define DELAY_USECS     1000	/* controller timeout in microseconds */
+#define DELAY_TICKS 	   1	/* controller timeout in ticks */
+#define DEF_TIMEOUT_TICKS 	300	/* controller timeout in ticks */
+#define RECOVERY_USECS 500000	/* controller recovery time in microseconds */
+#define RECOVERY_TICKS    30	/* controller recovery time in ticks */
+#define INITIALIZED	0x01	/* drive is initialized */
+#define DEAF		0x02	/* controller must be reset */
+#define SMART		0x04	/* drive supports ATA commands */
+#if ENABLE_ATAPI
+#define ATAPI		0x08	/* it is an ATAPI device */
+#else
+#define ATAPI		   0	/* don't bother with ATAPI; optimise out */
+#endif
+#define IDENTIFIED	0x10	/* w_identify done successfully */
+#define IGNORING	0x20	/* w_identify failed once */
+
+/* Timeouts and max retries. */
+int timeout_ticks = DEF_TIMEOUT_TICKS, max_errors = MAX_ERRORS;
+int wakeup_ticks = WAKEUP;
+long w_standard_timeouts = 0, w_pci_debug = 0, w_instance = 0,
+	disable_dma = 0, atapi_debug = 0;
+
+int w_testing = 0, w_silent = 0;
+
+int w_next_drive = 0;
+
+/* Variables. */
+
+/* The struct wini is indexed by controller first, then drive (0-3).
+ * Controller 0 is always the 'compatability' ide controller, at
+ * the fixed locations, whether present or not.
+ */
+PRIVATE struct wini {		/* main drive struct, one entry per drive */
+  unsigned state;		/* drive state: deaf, initialized, dead */
+  unsigned short w_status;	/* device status register */
+  unsigned base_cmd;		/* command base register */
+  unsigned base_ctl;		/* control base register */
+  unsigned base_dma;		/* dma base register */
+  unsigned irq;			/* interrupt request line */
+  unsigned irq_mask;		/* 1 << irq */
+  unsigned irq_need_ack;	/* irq needs to be acknowledged */
+  int irq_hook_id;		/* id of irq hook at the kernel */
+  int lba48;			/* supports lba48 */
+  int dma;			/* supports dma */
+  unsigned lcylinders;		/* logical number of cylinders (BIOS) */
+  unsigned lheads;		/* logical number of heads */
+  unsigned lsectors;		/* logical number of sectors per track */
+  unsigned pcylinders;		/* physical number of cylinders (translated) */
+  unsigned pheads;		/* physical number of heads */
+  unsigned psectors;		/* physical number of sectors per track */
+  unsigned ldhpref;		/* top four bytes of the LDH (head) register */
+  unsigned precomp;		/* write precompensation cylinder / 4 */
+  unsigned max_count;		/* max request for this drive */
+  unsigned open_ct;		/* in-use count */
+  struct device part[DEV_PER_DRIVE];	/* disks and partitions */
+  struct device subpart[SUB_PER_DRIVE];	/* subpartitions */
+} wini[MAX_DRIVES], *w_wn;
+
+PRIVATE int w_device = -1;
+PRIVATE int w_controller = -1;
+PRIVATE int w_major = -1;
+PRIVATE char w_id_string[40];
+
+PRIVATE int win_tasknr;			/* my task number */
+PRIVATE int w_command;			/* current command in execution */
+PRIVATE u8_t w_byteval;			/* used for SYS_IRQCTL */
+PRIVATE int w_drive;			/* selected drive */
+PRIVATE int w_controller;		/* selected controller */
+PRIVATE struct device *w_dv;		/* device's base and size */
+
+/* Unfortunately, DMA_SECTORS and DMA_BUF_SIZE are already defined libdriver
+ * for 'tmp_buf'.
+ */
+#define ATA_DMA_SECTORS	64
+#define ATA_DMA_BUF_SIZE	(ATA_DMA_SECTORS*SECTOR_SIZE)
+
+PRIVATE char dma_buf[ATA_DMA_BUF_SIZE];
+PRIVATE phys_bytes dma_buf_phys;
+
+#define N_PRDTE	1024	/* Should be enough for large requests */
+
+PRIVATE struct prdte
+{
+	u32_t prdte_base;
+	u16_t prdte_count;
+	u8_t prdte_reserved;
+	u8_t prdte_flags;
+} prdt[N_PRDTE];
+PRIVATE phys_bytes prdt_phys;
+
+#define PRDTE_FL_EOT	0x80	/* End of table */
+
+/* Some IDE devices announce themselves as RAID controllers */
+PRIVATE struct
+{
+	u16_t vendor;
+	u16_t device;
+} raid_table[]=
+{
+	{ 0x1106,	0x3149	},	/* VIA VT6420 */
+	{ 0,		0	}	/* end of list */
+};
+
+FORWARD _PROTOTYPE( void init_params, (void) 				);
+FORWARD _PROTOTYPE( void init_drive, (struct wini *w, int base_cmd,
+	int base_ctl, int base_dma, int irq, int ack, int hook,
+							int drive)	);
+FORWARD _PROTOTYPE( void init_params_pci, (int) 			);
+FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) 	);
+FORWARD _PROTOTYPE( struct device *w_prepare, (int dev) 		);
+FORWARD _PROTOTYPE( int w_identify, (void) 				);
+FORWARD _PROTOTYPE( char *w_name, (void) 				);
+FORWARD _PROTOTYPE( int w_specify, (void) 				);
+FORWARD _PROTOTYPE( int w_io_test, (void) 				);
+FORWARD _PROTOTYPE( int w_transfer, (int proc_nr, int opcode, off_t position,
+					iovec_t *iov, unsigned nr_req) 	);
+FORWARD _PROTOTYPE( int com_out, (struct command *cmd) 			);
+FORWARD _PROTOTYPE( int com_out_ext, (struct command *cmd)		);
+FORWARD _PROTOTYPE( void setup_dma, (unsigned *sizep, int proc_nr,
+			iovec_t *iov, int do_write, int *do_copyoutp)	);
+FORWARD _PROTOTYPE( void w_need_reset, (void) 				);
+FORWARD _PROTOTYPE( void ack_irqs, (unsigned int) 			);
+FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
+FORWARD _PROTOTYPE( int w_other, (struct driver *dp, message *m_ptr) 	);
+FORWARD _PROTOTYPE( int w_hw_int, (struct driver *dp, message *m_ptr) 	);
+FORWARD _PROTOTYPE( int com_simple, (struct command *cmd) 		);
+FORWARD _PROTOTYPE( void w_timeout, (void) 				);
+FORWARD _PROTOTYPE( int w_reset, (void) 				);
+FORWARD _PROTOTYPE( void w_intr_wait, (void) 				);
+FORWARD _PROTOTYPE( int at_intr_wait, (void) 				);
+FORWARD _PROTOTYPE( int w_waitfor, (int mask, int value) 		);
+FORWARD _PROTOTYPE( int w_waitfor_dma, (int mask, int value) 		);
+FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry) 		);
+#if ENABLE_ATAPI
+FORWARD _PROTOTYPE( int atapi_sendpacket, (u8_t *packet, unsigned cnt) 	);
+FORWARD _PROTOTYPE( int atapi_intr_wait, (void) 			);
+FORWARD _PROTOTYPE( int atapi_open, (void) 				);
+FORWARD _PROTOTYPE( void atapi_close, (void) 				);
+FORWARD _PROTOTYPE( int atapi_transfer, (int proc_nr, int opcode,
+			off_t position, iovec_t *iov, unsigned nr_req) 	);
+#endif
+
+/* Entry points to this driver. */
+PRIVATE struct driver w_dtab = {
+  w_name,		/* current device's name */
+  w_do_open,		/* open or mount request, initialize device */
+  w_do_close,		/* release device */
+  do_diocntl,		/* get or set a partition's geometry */
+  w_prepare,		/* prepare for I/O on a given minor device */
+  w_transfer,		/* do the I/O */
+  nop_cleanup,		/* nothing to clean up */
+  w_geometry,		/* tell the geometry of the disk */
+  nop_signal,		/* no cleanup needed on shutdown */
+  nop_alarm,		/* ignore leftover alarms */
+  nop_cancel,		/* ignore CANCELs */
+  nop_select,		/* ignore selects */
+  w_other,		/* catch-all for unrecognized commands and ioctls */
+  w_hw_int		/* leftover hardware interrupts */
+};
+
+/*===========================================================================*
+ *				at_winchester_task			     *
+ *===========================================================================*/
+PUBLIC int main()
+{
+/* Install signal handlers. Ask PM to transform signal into message. */
+  struct sigaction sa;
+
+  sa.sa_handler = SIG_MESS;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = 0;
+  if (sigaction(SIGTERM,&sa,NULL)<0) panic("AT","sigaction failed", errno);
+
+  /* Set special disk parameters then call the generic main loop. */
+  init_params();
+  signal(SIGTERM, SIG_IGN);
+  driver_task(&w_dtab);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				init_params				     *
+ *===========================================================================*/
+PRIVATE void init_params()
+{
+/* This routine is called at startup to initialize the drive parameters. */
+
+  u16_t parv[2];
+  unsigned int vector, size;
+  int drive, nr_drives;
+  struct wini *wn;
+  u8_t params[16];
+  int s;
+
+  /* Boot variables. */
+  env_parse("ata_std_timeout", "d", 0, &w_standard_timeouts, 0, 1);
+  env_parse("ata_pci_debug", "d", 0, &w_pci_debug, 0, 1);
+  env_parse("ata_instance", "d", 0, &w_instance, 0, 8);
+  env_parse("ata_no_dma", "d", 0, &disable_dma, 0, 1);
+  env_parse("atapi_debug", "d", 0, &atapi_debug, 0, 1);
+
+  if (disable_dma)
+	printf("DMA for ATA devices is disabled.\n");
+
+  s= sys_umap(SELF, D, (vir_bytes)dma_buf, sizeof(dma_buf), &dma_buf_phys);
+  if (s != 0)
+	panic("at_wini", "can't map dma buffer", s);
+
+  s= sys_umap(SELF, D, (vir_bytes)prdt, sizeof(prdt), &prdt_phys);
+  if (s != 0)
+	panic("at_wini", "can't map prd table", s);
+
+  if (w_instance == 0) {
+	  /* Get the number of drives from the BIOS data area */
+	  if ((s=sys_vircopy(SELF, BIOS_SEG, NR_HD_DRIVES_ADDR, 
+ 		 	SELF, D, (vir_bytes) params, NR_HD_DRIVES_SIZE)) != OK)
+  		panic(w_name(), "Couldn't read BIOS", s);
+	  if ((nr_drives = params[0]) > 2) nr_drives = 2;
+
+	  for (drive = 0, wn = wini; drive < COMPAT_DRIVES; drive++, wn++) {
+		if (drive < nr_drives) {
+		    /* Copy the BIOS parameter vector */
+		    vector = (drive == 0) ? BIOS_HD0_PARAMS_ADDR:BIOS_HD1_PARAMS_ADDR;
+		    size = (drive == 0) ? BIOS_HD0_PARAMS_SIZE:BIOS_HD1_PARAMS_SIZE;
+		    if ((s=sys_vircopy(SELF, BIOS_SEG, vector,
+					SELF, D, (vir_bytes) parv, size)) != OK)
+  				panic(w_name(), "Couldn't read BIOS", s);
+	
+			/* Calculate the address of the parameters and copy them */
+  			if ((s=sys_vircopy(
+  				SELF, BIOS_SEG, hclick_to_physb(parv[1]) + parv[0],
+  				SELF, D, (phys_bytes) params, 16L))!=OK)
+  			    panic(w_name(),"Couldn't copy parameters", s);
+	
+			/* Copy the parameters to the structures of the drive */
+			wn->lcylinders = bp_cylinders(params);
+			wn->lheads = bp_heads(params);
+			wn->lsectors = bp_sectors(params);
+			wn->precomp = bp_precomp(params) >> 2;
+		}
+
+		/* Fill in non-BIOS parameters. */
+		init_drive(wn,
+			drive < 2 ? REG_CMD_BASE0 : REG_CMD_BASE1,
+			drive < 2 ? REG_CTL_BASE0 : REG_CTL_BASE1,
+			0 /* no DMA */, NO_IRQ, 0, 0, drive);
+		w_next_drive++;
+  	}
+  }
+
+  /* Look for controllers on the pci bus. Skip none the first instance,
+   * skip one and then 2 for every instance, for every next instance.
+   */
+  if (w_instance == 0)
+  	init_params_pci(0);
+  else
+  	init_params_pci(w_instance*2-1);
+
+}
+
+#define ATA_IF_NOTCOMPAT1 (1L << 0)
+#define ATA_IF_NOTCOMPAT2 (1L << 2)
+
+/*===========================================================================*
+ *				init_drive				     *
+ *===========================================================================*/
+PRIVATE void init_drive(struct wini *w, int base_cmd, int base_ctl,
+	int base_dma, int irq, int ack, int hook, int drive)
+{
+	w->state = 0;
+	w->w_status = 0;
+	w->base_cmd = base_cmd;
+	w->base_ctl = base_ctl;
+	w->base_dma = base_dma;
+	w->irq = irq;
+	w->irq_mask = 1 << irq;
+	w->irq_need_ack = ack;
+	w->irq_hook_id = hook;
+	w->ldhpref = ldh_init(drive);
+	w->max_count = MAX_SECS << SECTOR_SHIFT;
+	w->lba48 = 0;
+	w->dma = 0;
+}
+
+/*===========================================================================*
+ *				init_params_pci				     *
+ *===========================================================================*/
+PRIVATE void init_params_pci(int skip)
+{
+  int i, r, devind, drive;
+  int irq, irq_hook, raid;
+  u8_t bcr, scr, interface;
+  u16_t vid, did;
+  u32_t base_dma, t3;
+
+  pci_init();
+  for(drive = w_next_drive; drive < MAX_DRIVES; drive++)
+  	wini[drive].state = IGNORING;
+  for(r = pci_first_dev(&devind, &vid, &did); r != 0;
+	r = pci_next_dev(&devind, &vid, &did)) {
+
+	raid= 0;
+
+  	/* Except class 01h (mass storage), subclass be 01h (ATA).
+	 * Also check listed RAID controllers.
+  	 */
+	bcr= pci_attr_r8(devind, PCI_BCR);
+	scr= pci_attr_r8(devind, PCI_SCR);
+	interface= pci_attr_r8(devind, PCI_PIFR);
+	t3= ((bcr << 16) | (scr << 8) | interface);
+  	if (bcr == PCI_BCR_MASS_STORAGE && scr == PCI_MS_IDE)
+		;	/* Okay */
+	else if (t3 == PCI_T3_RAID)
+	{
+		for (i= 0; raid_table[i].vendor != 0; i++)
+		{
+			if (raid_table[i].vendor == vid &&
+				raid_table[i].device == did)
+			{
+				break;
+			}
+		}
+		if (raid_table[i].vendor == 0)
+		{
+		  	printf(
+	"atapci skipping unsupported RAID controller 0x%04x / 0x%04x\n",
+				vid, did);
+			continue;
+		}
+		printf("found supported RAID controller\n");
+		raid= 1;
+	}
+	else
+		continue;	/* Unsupported device class */
+
+  	/* Found a controller.
+  	 * Programming interface register tells us more.
+  	 */
+  	irq = pci_attr_r8(devind, PCI_ILR);
+
+  	/* Any non-compat drives? */
+  	if (raid || (interface & (ATA_IF_NOTCOMPAT1 | ATA_IF_NOTCOMPAT2))) {
+  		int s;
+
+		if (w_next_drive >= MAX_DRIVES)
+		{
+			/* We can't accept more drives, but have to search for
+			 * controllers operating in compatibility mode.
+			 */
+			continue;
+		}
+
+  		irq_hook = irq;
+  		if (skip > 0) {
+  			if (w_pci_debug)
+			{
+				printf(
+				"atapci skipping controller (remain %d)\n",
+					skip);
+			}
+  			skip--;
+  			continue;
+  		}
+  		if ((s=sys_irqsetpolicy(irq, 0, &irq_hook)) != OK) {
+		  	printf("atapci: couldn't set IRQ policy %d\n", irq);
+		  	continue;
+		}
+		if ((s=sys_irqenable(&irq_hook)) != OK) {
+			printf("atapci: couldn't enable IRQ line %d\n", irq);
+		  	continue;
+		}
+  	} 
+
+  	base_dma = pci_attr_r32(devind, PCI_BAR_5) & 0xfffffffc;
+
+  	/* Primary channel not in compatability mode? */
+  	if (raid || (interface & ATA_IF_NOTCOMPAT1)) {
+  		u32_t base_cmd, base_ctl;
+
+  		base_cmd = pci_attr_r32(devind, PCI_BAR) & 0xfffffffc;
+  		base_ctl = pci_attr_r32(devind, PCI_BAR_2) & 0xfffffffc;
+  		if (base_cmd != REG_CMD_BASE0 && base_cmd != REG_CMD_BASE1) {
+	  		init_drive(&wini[w_next_drive],
+	  			base_cmd, base_ctl+PCI_CTL_OFF,
+				base_dma, irq, 1, irq_hook, 0);
+  			init_drive(&wini[w_next_drive+1],
+  				base_cmd, base_ctl+PCI_CTL_OFF,
+				base_dma, irq, 1, irq_hook, 1);
+	  		if (w_pci_debug)
+		  		printf("atapci %d: 0x%x 0x%x irq %d\n", devind, base_cmd, base_ctl, irq);
+			w_next_drive += 2;
+  		} else printf("atapci: ignored drives on primary channel, base %x\n", base_cmd);
+  	}
+	else
+	{
+		/* Update base_dma for compatibility device */
+		for (i= 0; i<MAX_DRIVES; i++)
+		{
+			if (wini[i].base_cmd == REG_CMD_BASE0)
+				wini[i].base_dma= base_dma;
+		}
+	}
+
+  	/* Secondary channel not in compatability mode? */
+  	if (raid || (interface & ATA_IF_NOTCOMPAT2)) {
+  		u32_t base_cmd, base_ctl;
+
+  		base_cmd = pci_attr_r32(devind, PCI_BAR_3) & 0xfffffffc;
+  		base_ctl = pci_attr_r32(devind, PCI_BAR_4) & 0xfffffffc;
+		if (base_dma != 0)
+			base_dma += PCI_DMA_2ND_OFF;
+  		if (base_cmd != REG_CMD_BASE0 && base_cmd != REG_CMD_BASE1) {
+  			init_drive(&wini[w_next_drive],
+  				base_cmd, base_ctl+PCI_CTL_OFF, base_dma,
+				irq, 1, irq_hook, 2);
+	  		init_drive(&wini[w_next_drive+1],
+	  			base_cmd, base_ctl+PCI_CTL_OFF, base_dma,
+				irq, 1, irq_hook, 3);
+	  		if (w_pci_debug)
+  				printf("atapci %d: 0x%x 0x%x irq %d\n", devind, base_cmd, base_ctl, irq);
+			w_next_drive += 2;
+  		} else printf("atapci: ignored drives on secondary channel, base %x\n", base_cmd);
+  	}
+	else
+	{
+		/* Update base_dma for compatibility device */
+		for (i= 0; i<MAX_DRIVES; i++)
+		{
+			if (wini[i].base_cmd == REG_CMD_BASE1 && base_dma != 0)
+				wini[i].base_dma= base_dma+PCI_DMA_2ND_OFF;
+		}
+	}
+  }
+}
+
+/*===========================================================================*
+ *				w_do_open				     *
+ *===========================================================================*/
+PRIVATE int w_do_open(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+/* Device open: Initialize the controller and read the partition table. */
+
+  struct wini *wn;
+
+  if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
+
+  wn = w_wn;
+
+  /* If we've probed it before and it failed, don't probe it again. */
+  if (wn->state & IGNORING) return ENXIO;
+
+  /* If we haven't identified it yet, or it's gone deaf, 
+   * (re-)identify it.
+   */
+  if (!(wn->state & IDENTIFIED) || (wn->state & DEAF)) {
+	/* Try to identify the device. */
+	if (w_identify() != OK) {
+#if VERBOSE
+  		printf("%s: probe failed\n", w_name());
+#endif
+		if (wn->state & DEAF) w_reset();
+		wn->state = IGNORING;
+		return(ENXIO);
+	}
+	  /* Do a test transaction unless it's a CD drive (then
+	   * we can believe the controller, and a test may fail
+	   * due to no CD being in the drive). If it fails, ignore
+	   * the device forever.
+	   */
+	  if (!(wn->state & ATAPI) && w_io_test() != OK) {
+  		wn->state |= IGNORING;
+	  	return(ENXIO);
+	  }
+
+#if VERBOSE
+	  printf("%s: AT driver detected ", w_name());
+	  if (wn->state & (SMART|ATAPI)) {
+		printf("%.40s\n", w_id_string);
+	  } else {
+		printf("%ux%ux%u\n", wn->pcylinders, wn->pheads, wn->psectors);
+	  }
+#endif
+  }
+
+#if ENABLE_ATAPI
+   if ((wn->state & ATAPI) && (m_ptr->COUNT & W_BIT))
+	return(EACCES);
+#endif
+
+  /* Partition the drive if it's being opened for the first time,
+   * or being opened after being closed.
+   */
+  if (wn->open_ct == 0) {
+#if ENABLE_ATAPI
+	if (wn->state & ATAPI) {
+		int r;
+		if ((r = atapi_open()) != OK) return(r);
+	}
+#endif
+
+	/* Partition the disk. */
+	partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY, wn->state & ATAPI);
+  }
+  wn->open_ct++;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				w_prepare				     *
+ *===========================================================================*/
+PRIVATE struct device *w_prepare(int device)
+{
+/* Prepare for I/O on a device. */
+struct wini *prev_wn;
+prev_wn = w_wn;
+  w_device = device;
+
+  if (device < NR_MINORS) {			/* d0, d0p[0-3], d1, ... */
+	w_drive = device / DEV_PER_DRIVE;	/* save drive number */
+	w_wn = &wini[w_drive];
+	w_dv = &w_wn->part[device % DEV_PER_DRIVE];
+  } else
+  if ((unsigned) (device -= MINOR_d0p0s0) < NR_SUBDEVS) {/*d[0-7]p[0-3]s[0-3]*/
+	w_drive = device / SUB_PER_DRIVE;
+	w_wn = &wini[w_drive];
+	w_dv = &w_wn->subpart[device % SUB_PER_DRIVE];
+  } else {
+  	w_device = -1;
+	return(NIL_DEV);
+  }
+  return(w_dv);
+}
+
+/*===========================================================================*
+ *				w_identify				     *
+ *===========================================================================*/
+PRIVATE int w_identify()
+{
+/* Find out if a device exists, if it is an old AT disk, or a newer ATA
+ * drive, a removable media device, etc.
+ */
+
+  struct wini *wn = w_wn;
+  struct command cmd;
+  int i, s;
+  int id_dma, ultra_dma;
+  u32_t dma_base;
+  u16_t w;
+  unsigned long dma_status;
+  unsigned long size;
+#define id_byte(n)	(&tmp_buf[2 * (n)])
+#define id_word(n)	(((u16_t) id_byte(n)[0] <<  0) \
+			|((u16_t) id_byte(n)[1] <<  8))
+#define id_longword(n)	(((u32_t) id_byte(n)[0] <<  0) \
+			|((u32_t) id_byte(n)[1] <<  8) \
+			|((u32_t) id_byte(n)[2] << 16) \
+			|((u32_t) id_byte(n)[3] << 24))
+
+  /* Try to identify the device. */
+  cmd.ldh     = wn->ldhpref;
+  cmd.command = ATA_IDENTIFY;
+  if (com_simple(&cmd) == OK && w_waitfor(STATUS_DRQ, STATUS_DRQ) &&
+	!(wn->w_status & (STATUS_ERR|STATUS_WF))) {
+
+	/* Device information. */
+	if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, SECTOR_SIZE)) != OK)
+		panic(w_name(),"Call to sys_insw() failed", s);
+
+	if (id_word(0) & ID_GEN_NOT_ATA)
+	{
+		printf("%s: not an ATA device?\n", w_name());
+		return ERR;
+	}
+
+	/* This is an ATA device. */
+	wn->state |= SMART;
+
+	/* Why are the strings byte swapped??? */
+	for (i = 0; i < 40; i++) w_id_string[i] = id_byte(27)[i^1];
+
+	/* Preferred CHS translation mode. */
+	wn->pcylinders = id_word(1);
+	wn->pheads = id_word(3);
+	wn->psectors = id_word(6);
+	size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors;
+
+	w= id_word(ID_CAPABILITIES);
+	if ((w & ID_CAP_LBA) && size > 512L*1024*2) {
+		/* Drive is LBA capable and is big enough to trust it to
+		 * not make a mess of it.
+		 */
+		wn->ldhpref |= LDH_LBA;
+		size = id_longword(60);
+
+		w= id_word(ID_CSS);
+		if (size < LBA48_CHECK_SIZE)
+		{
+			/* No need to check for LBA48 */
+		}
+		else if (w & ID_CSS_LBA48) {
+			/* Drive is LBA48 capable (and LBA48 is turned on). */
+			if (id_longword(102)) {
+				/* If no. of sectors doesn't fit in 32 bits,
+				 * trunacte to this. So it's LBA32 for now.
+				 * This can still address devices up to 2TB
+				 * though.
+				 */
+				size = ULONG_MAX;
+			} else {
+				/* Actual number of sectors fits in 32 bits. */
+				size = id_longword(100);
+			}
+			wn->lba48 = 1;
+		}
+
+		/* Check for DMA. Assume that only LBA capable devices can do
+		 * DMA.
+		 */
+		w= id_word(ID_CAPABILITIES);
+		id_dma= !!(w & ID_CAP_DMA);
+		w= id_byte(ID_FIELD_VALIDITY)[0];
+		ultra_dma= !!(w & ID_FV_88);
+		dma_base= wn->base_dma;
+		if (dma_base)
+		{
+			if (sys_inb(dma_base + DMA_STATUS, &dma_status) != OK)
+			{
+				panic(w_name(),
+					"unable to read DMA status register",
+					NO_NUM);
+			}
+		}
+		if (disable_dma)
+			;	/* DMA is disabled */
+		else if (id_dma && dma_base)
+		{
+			w= id_word(ID_MULTIWORD_DMA);
+			if (w & (ID_MWDMA_2_SUP|ID_MWDMA_1_SUP|ID_MWDMA_0_SUP))
+			{
+				printf(
+				"%s: multiword DMA modes supported:%s%s%s\n",
+					w_name(),
+					(w & ID_MWDMA_0_SUP) ? " 0" : "",
+					(w & ID_MWDMA_1_SUP) ? " 1" : "",
+					(w & ID_MWDMA_2_SUP) ? " 2" : "");
+			}
+			if (w & (ID_MWDMA_0_SEL|ID_MWDMA_1_SEL|ID_MWDMA_2_SEL))
+			{
+				printf(
+				"%s: multiword DMA mode selected:%s%s%s\n",
+					w_name(),
+					(w & ID_MWDMA_0_SEL) ? " 0" : "",
+					(w & ID_MWDMA_1_SEL) ? " 1" : "",
+					(w & ID_MWDMA_2_SEL) ? " 2" : "");
+			}
+			if (ultra_dma) 
+			{
+				w= id_word(ID_ULTRA_DMA);
+				if (w & (ID_UDMA_0_SUP|ID_UDMA_1_SUP|
+					ID_UDMA_2_SUP|ID_UDMA_3_SUP|
+					ID_UDMA_4_SUP|ID_UDMA_5_SUP))
+				{
+					printf(
+				"%s: Ultra DMA modes supported:%s%s%s%s%s%s\n",
+					w_name(),
+					(w & ID_UDMA_0_SUP) ? " 0" : "",
+					(w & ID_UDMA_1_SUP) ? " 1" : "",
+					(w & ID_UDMA_2_SUP) ? " 2" : "",
+					(w & ID_UDMA_3_SUP) ? " 3" : "",
+					(w & ID_UDMA_4_SUP) ? " 4" : "",
+					(w & ID_UDMA_5_SUP) ? " 5" : "");
+				}
+				if (w & (ID_UDMA_0_SEL|ID_UDMA_1_SEL|
+					ID_UDMA_2_SEL|ID_UDMA_3_SEL|
+					ID_UDMA_4_SEL|ID_UDMA_5_SEL))
+				{
+					printf(
+				"%s: Ultra DMA mode selected:%s%s%s%s%s%s\n",
+					w_name(),
+					(w & ID_UDMA_0_SEL) ? " 0" : "",
+					(w & ID_UDMA_1_SEL) ? " 1" : "",
+					(w & ID_UDMA_2_SEL) ? " 2" : "",
+					(w & ID_UDMA_3_SEL) ? " 3" : "",
+					(w & ID_UDMA_4_SEL) ? " 4" : "",
+					(w & ID_UDMA_5_SEL) ? " 5" : "");
+				}
+			}
+			wn->dma= 1;
+		}
+		else if (id_dma || dma_base)
+		{
+			printf("id_dma %d, dma_base 0x%x\n", id_dma, dma_base);
+		}
+		else
+			printf("no DMA support\n");
+
+#if 0
+		if (wn->dma && wn == &wini[0])
+		{
+			printf("disabling DMA for drive 0\n");
+			wn->dma= 0;
+		}
+#endif
+	}
+
+	if (wn->lcylinders == 0) {
+		/* No BIOS parameters?  Then make some up. */
+		wn->lcylinders = wn->pcylinders;
+		wn->lheads = wn->pheads;
+		wn->lsectors = wn->psectors;
+		while (wn->lcylinders > 1024) {
+			wn->lheads *= 2;
+			wn->lcylinders /= 2;
+		}
+	}
+#if ENABLE_ATAPI
+  } else
+  if (cmd.command = ATAPI_IDENTIFY,
+	com_simple(&cmd) == OK && w_waitfor(STATUS_DRQ, STATUS_DRQ) &&
+	!(wn->w_status & (STATUS_ERR|STATUS_WF))) {
+	/* An ATAPI device. */
+	wn->state |= ATAPI;
+
+	/* Device information. */
+	if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, 512)) != OK)
+		panic(w_name(),"Call to sys_insw() failed", s);
+
+	/* Why are the strings byte swapped??? */
+	for (i = 0; i < 40; i++) w_id_string[i] = id_byte(27)[i^1];
+
+	size = 0;	/* Size set later. */
+#endif
+  } else {
+	/* Not an ATA device; no translations, no special features.  Don't
+	 * touch it unless the BIOS knows about it.
+	 */
+	if (wn->lcylinders == 0) { return(ERR); }	/* no BIOS parameters */
+	wn->pcylinders = wn->lcylinders;
+	wn->pheads = wn->lheads;
+	wn->psectors = wn->lsectors;
+	size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors;
+  }
+
+  /* Size of the whole drive */
+  wn->part[0].dv_size = mul64u(size, SECTOR_SIZE);
+
+  /* Reset/calibrate (where necessary) */
+  if (w_specify() != OK && w_specify() != OK) {
+  	return(ERR);
+  }
+
+  if (wn->irq == NO_IRQ) {
+	  /* Everything looks OK; register IRQ so we can stop polling. */
+	  wn->irq = w_drive < 2 ? AT_WINI_0_IRQ : AT_WINI_1_IRQ;
+	  wn->irq_hook_id = wn->irq;	/* id to be returned if interrupt occurs */
+	  if ((s=sys_irqsetpolicy(wn->irq, IRQ_REENABLE, &wn->irq_hook_id)) != OK) 
+	  	panic(w_name(), "couldn't set IRQ policy", s);
+	  if ((s=sys_irqenable(&wn->irq_hook_id)) != OK)
+	  	panic(w_name(), "couldn't enable IRQ line", s);
+  }
+  wn->state |= IDENTIFIED;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				w_name					     *
+ *===========================================================================*/
+PRIVATE char *w_name()
+{
+/* Return a name for the current device. */
+  static char name[] = "AT-D0";
+
+  name[4] = '0' + w_drive;
+  return name;
+}
+
+/*===========================================================================*
+ *				w_io_test				     *
+ *===========================================================================*/
+PRIVATE int w_io_test(void)
+{
+	int r, save_dev;
+	int save_timeout, save_errors, save_wakeup;
+	iovec_t iov;
+#ifdef CD_SECTOR_SIZE
+	static char buf[CD_SECTOR_SIZE];
+#else
+	static char buf[SECTOR_SIZE];
+#endif
+
+	iov.iov_addr = (vir_bytes) buf;
+	iov.iov_size = sizeof(buf);
+	save_dev = w_device;
+
+	/* Reduce timeout values for this test transaction. */
+	save_timeout = timeout_ticks;
+	save_errors = max_errors;
+	save_wakeup = wakeup_ticks;
+
+	if (!w_standard_timeouts) {
+		timeout_ticks = HZ * 4;
+		wakeup_ticks = HZ * 6;
+		max_errors = 3;
+	}
+
+	w_testing = 1;
+
+	/* Try I/O on the actual drive (not any (sub)partition). */
+ 	if (w_prepare(w_drive * DEV_PER_DRIVE) == NIL_DEV)
+ 		panic(w_name(), "Couldn't switch devices", NO_NUM);
+
+	r = w_transfer(SELF, DEV_GATHER, 0, &iov, 1);
+
+	/* Switch back. */
+ 	if (w_prepare(save_dev) == NIL_DEV)
+ 		panic(w_name(), "Couldn't switch back devices", NO_NUM);
+
+ 	/* Restore parameters. */
+	timeout_ticks = save_timeout;
+	max_errors = save_errors;
+	wakeup_ticks = save_wakeup;
+	w_testing = 0;
+
+ 	/* Test if everything worked. */
+	if (r != OK || iov.iov_size != 0) {
+		return ERR;
+	}
+
+	/* Everything worked. */
+
+	return OK;
+}
+
+/*===========================================================================*
+ *				w_specify				     *
+ *===========================================================================*/
+PRIVATE int w_specify()
+{
+/* Routine to initialize the drive after boot or when a reset is needed. */
+
+  struct wini *wn = w_wn;
+  struct command cmd;
+
+  if ((wn->state & DEAF) && w_reset() != OK) {
+  	return(ERR);
+  }
+
+  if (!(wn->state & ATAPI)) {
+	/* Specify parameters: precompensation, number of heads and sectors. */
+	cmd.precomp = wn->precomp;
+	cmd.count   = wn->psectors;
+	cmd.ldh     = w_wn->ldhpref | (wn->pheads - 1);
+	cmd.command = CMD_SPECIFY;		/* Specify some parameters */
+
+	/* Output command block and see if controller accepts the parameters. */
+	if (com_simple(&cmd) != OK) return(ERR);
+
+	if (!(wn->state & SMART)) {
+		/* Calibrate an old disk. */
+		cmd.sector  = 0;
+		cmd.cyl_lo  = 0;
+		cmd.cyl_hi  = 0;
+		cmd.ldh     = w_wn->ldhpref;
+		cmd.command = CMD_RECALIBRATE;
+
+		if (com_simple(&cmd) != OK) return(ERR);
+	}
+  }
+  wn->state |= INITIALIZED;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_transfer				     *
+ *===========================================================================*/
+PRIVATE int do_transfer(struct wini *wn, unsigned int precomp,
+	unsigned int count, unsigned int sector,
+	unsigned int opcode, int do_dma)
+{
+  	struct command cmd;
+	unsigned int sector_high;
+	unsigned secspcyl = wn->pheads * wn->psectors;
+	int do_lba48;
+
+	sector_high= 0;	/* For future extensions */
+
+	do_lba48= 0;
+	if (sector >= LBA48_CHECK_SIZE || sector_high != 0)
+	{
+		if (wn->lba48)
+			do_lba48= 1;
+		else if (sector > LBA_MAX_SIZE || sector_high != 0)
+		{
+			/* Strange sector count for LBA device */
+			return EIO;
+		}
+	}
+
+	cmd.precomp = precomp;
+	cmd.count   = count;
+	if (do_dma)
+	{
+		cmd.command = opcode == DEV_SCATTER ? CMD_WRITE_DMA :
+			CMD_READ_DMA;
+	}
+	else
+		cmd.command = opcode == DEV_SCATTER ? CMD_WRITE : CMD_READ;
+
+	if (do_lba48) {
+		if (do_dma)
+		{
+			cmd.command = ((opcode == DEV_SCATTER) ?
+				CMD_WRITE_DMA_EXT : CMD_READ_DMA_EXT);
+		}
+		else
+		{
+			cmd.command = ((opcode == DEV_SCATTER) ?
+				CMD_WRITE_EXT : CMD_READ_EXT);
+		}
+		cmd.count_prev= (count >> 8);
+		cmd.sector  = (sector >>  0) & 0xFF;
+		cmd.cyl_lo  = (sector >>  8) & 0xFF;
+		cmd.cyl_hi  = (sector >> 16) & 0xFF;
+		cmd.sector_prev= (sector >> 24) & 0xFF;
+		cmd.cyl_lo_prev= (sector_high) & 0xFF;
+		cmd.cyl_hi_prev= (sector_high >> 8) & 0xFF;
+		cmd.ldh     = wn->ldhpref;
+
+		return com_out_ext(&cmd);
+	} else if (wn->ldhpref & LDH_LBA) {
+		cmd.sector  = (sector >>  0) & 0xFF;
+		cmd.cyl_lo  = (sector >>  8) & 0xFF;
+		cmd.cyl_hi  = (sector >> 16) & 0xFF;
+		cmd.ldh     = wn->ldhpref | ((sector >> 24) & 0xF);
+	} else {
+  		int cylinder, head, sec;
+		cylinder = sector / secspcyl;
+		head = (sector % secspcyl) / wn->psectors;
+		sec = sector % wn->psectors;
+		cmd.sector  = sec + 1;
+		cmd.cyl_lo  = cylinder & BYTE;
+		cmd.cyl_hi  = (cylinder >> 8) & BYTE;
+		cmd.ldh     = wn->ldhpref | head;
+	}
+
+	return com_out(&cmd);
+}
+
+/*===========================================================================*
+ *				w_transfer				     *
+ *===========================================================================*/
+PRIVATE int w_transfer(proc_nr, opcode, position, iov, nr_req)
+int proc_nr;			/* process doing the request */
+int opcode;			/* DEV_GATHER or DEV_SCATTER */
+off_t position;			/* offset on device to read or write */
+iovec_t *iov;			/* pointer to read or write request vector */
+unsigned nr_req;		/* length of request vector */
+{
+  struct wini *wn = w_wn;
+  iovec_t *iop, *iov_end = iov + nr_req;
+  int n, r, s, errors, do_dma, do_write, do_copyout;
+  unsigned long v, block, w_status;
+  unsigned long dv_size = cv64ul(w_dv->dv_size);
+  unsigned cylinder, head, sector, nbytes;
+  unsigned dma_buf_offset;
+
+#if ENABLE_ATAPI
+  if (w_wn->state & ATAPI) {
+	return atapi_transfer(proc_nr, opcode, position, iov, nr_req);
+  }
+#endif
+
+  
+
+  /* Check disk address. */
+  if ((position & SECTOR_MASK) != 0) return(EINVAL);
+
+  errors = 0;
+
+  while (nr_req > 0) {
+	/* How many bytes to transfer? */
+	nbytes = 0;
+	for (iop = iov; iop < iov_end; iop++) nbytes += iop->iov_size;
+	if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
+
+	/* Which block on disk and how close to EOF? */
+	if (position >= dv_size) return(OK);		/* At EOF */
+	if (position + nbytes > dv_size) nbytes = dv_size - position;
+	block = div64u(add64ul(w_dv->dv_base, position), SECTOR_SIZE);
+
+	do_dma= wn->dma;
+	do_write= (opcode == DEV_SCATTER);
+	
+	if (nbytes >= wn->max_count) {
+		/* The drive can't do more then max_count at once. */
+		nbytes = wn->max_count;
+	}
+
+	/* First check to see if a reinitialization is needed. */
+	if (!(wn->state & INITIALIZED) && w_specify() != OK) return(EIO);
+
+	if (do_dma)
+	{
+		setup_dma(&nbytes, proc_nr, iov, do_write, &do_copyout);
+#if 0
+		printf("nbytes = %d\n", nbytes);
+#endif
+	}
+
+	/* Tell the controller to transfer nbytes bytes. */
+	r = do_transfer(wn, wn->precomp, (nbytes >> SECTOR_SHIFT),
+		block, opcode, do_dma);
+
+	if (opcode == DEV_SCATTER) {
+		/* The specs call for a 400 ns wait after issuing the command.
+		 * Reading the alternate status register is the suggested 
+		 * way to implement this wait.
+		 */
+		if (sys_inb((wn->base_ctl+REG_CTL_ALTSTAT), &w_status) != OK)
+			panic(w_name(), "couldn't get status", NO_NUM);
+	}
+
+	if (do_dma)
+	{
+		/* Wait for the interrupt, check DMA status and optionally
+		 * copy out.
+		 */
+
+		if ((r = at_intr_wait()) != OK) 
+		{
+			/* Don't retry if sector marked bad or too many
+			 * errors.
+			 */
+			if (r == ERR_BAD_SECTOR || ++errors == max_errors) {
+				w_command = CMD_IDLE;
+				return(EIO);
+			}
+			continue;
+		}
+
+		/* Wait for DMA_ST_INT to get set */
+		w_waitfor_dma(DMA_ST_INT, DMA_ST_INT);
+
+		r= sys_inb(wn->base_dma + DMA_STATUS, &v);
+		if (r != 0) panic("at_wini", "w_transfer: sys_inb failed", r);
+
+#if 0
+		printf("dma_status: 0x%x\n", v);
+#endif
+		if (!(v & DMA_ST_INT))
+		{
+			/* DMA did not complete successfully */
+			if (v & DMA_ST_BM_ACTIVE)
+				panic(w_name(), "DMA did not complete", NO_NUM);
+			else if (v & DMA_ST_ERROR)
+			{
+				printf("at_wini: DMA error\n");
+				r= EIO;
+				break;
+			}
+			else
+			{
+#if 0
+				printf("DMA buffer too small\n");
+#endif
+				panic(w_name(), "DMA buffer too small", NO_NUM);
+			}
+		}
+		else if (v & DMA_ST_BM_ACTIVE)
+			panic(w_name(), "DMA buffer too large", NO_NUM);
+
+		dma_buf_offset= 0;
+		while (r == OK && nbytes > 0)
+		{
+			n= iov->iov_size;
+			if (n > nbytes)
+				n= nbytes;
+
+			if (do_copyout)
+			{
+				s= sys_vircopy(SELF, D,
+					(vir_bytes)dma_buf+dma_buf_offset, 
+					proc_nr, D, iov->iov_addr, n);
+				if (s != OK)
+				{
+					panic(w_name(),
+					"w_transfer: sys_vircopy failed",
+						s);
+				}
+			}
+
+			/* Book the bytes successfully transferred. */
+			nbytes -= n;
+			position += n;
+			iov->iov_addr += n;
+			if ((iov->iov_size -= n) == 0)
+				{ iov++; nr_req--; }
+			dma_buf_offset += n;
+		}
+	}
+
+	while (r == OK && nbytes > 0) {
+		/* For each sector, wait for an interrupt and fetch the data
+		 * (read), or supply data to the controller and wait for an
+		 * interrupt (write).
+		 */
+
+		if (opcode == DEV_GATHER) {
+			/* First an interrupt, then data. */
+			if ((r = at_intr_wait()) != OK) {
+				/* An error, send data to the bit bucket. */
+				if (w_wn->w_status & STATUS_DRQ) {
+					if ((s=sys_insw(wn->base_cmd+REG_DATA,
+						SELF, tmp_buf,
+						SECTOR_SIZE)) != OK)
+					{
+						panic(w_name(),
+						"Call to sys_insw() failed",
+							s);
+					}
+				}
+				break;
+			}
+		}
+
+		/* Wait for busy to clear. */
+		if (!w_waitfor(STATUS_BSY, 0)) { r = ERR; break; }
+
+		/* Wait for data transfer requested. */
+		if (!w_waitfor(STATUS_DRQ, STATUS_DRQ)) { r = ERR; break; }
+
+		/* Copy bytes to or from the device's buffer. */
+		if (opcode == DEV_GATHER) {
+			if ((s=sys_insw(wn->base_cmd + REG_DATA, proc_nr, 
+				(void *) iov->iov_addr, SECTOR_SIZE)) != OK)
+			{
+				panic(w_name(),"Call to sys_insw() failed", s);
+			}
+		} else {
+			if ((s=sys_outsw(wn->base_cmd + REG_DATA, proc_nr,
+				(void *) iov->iov_addr, SECTOR_SIZE)) != OK)
+			{
+				panic(w_name(),"Call to sys_outsw() failed",
+					s);
+			}
+
+			/* Data sent, wait for an interrupt. */
+			if ((r = at_intr_wait()) != OK) break;
+		}
+
+		/* Book the bytes successfully transferred. */
+		nbytes -= SECTOR_SIZE;
+		position += SECTOR_SIZE;
+		iov->iov_addr += SECTOR_SIZE;
+		if ((iov->iov_size -= SECTOR_SIZE) == 0) { iov++; nr_req--; }
+	}
+
+	/* Any errors? */
+	if (r != OK) {
+		/* Don't retry if sector marked bad or too many errors. */
+		if (r == ERR_BAD_SECTOR || ++errors == max_errors) {
+			w_command = CMD_IDLE;
+			return(EIO);
+		}
+	}
+  }
+
+  w_command = CMD_IDLE;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				com_out					     *
+ *===========================================================================*/
+PRIVATE int com_out(cmd)
+struct command *cmd;		/* Command block */
+{
+/* Output the command block to the winchester controller and return status */
+
+  struct wini *wn = w_wn;
+  unsigned base_cmd = wn->base_cmd;
+  unsigned base_ctl = wn->base_ctl;
+  pvb_pair_t outbyte[7];		/* vector for sys_voutb() */
+  int s;				/* status for sys_(v)outb() */
+
+  if (w_wn->state & IGNORING) return ERR;
+
+  if (!w_waitfor(STATUS_BSY, 0)) {
+	printf("%s: controller not ready\n", w_name());
+	return(ERR);
+  }
+
+  /* Select drive. */
+  if ((s=sys_outb(base_cmd + REG_LDH, cmd->ldh)) != OK)
+  	panic(w_name(),"Couldn't write register to select drive",s);
+
+  if (!w_waitfor(STATUS_BSY, 0)) {
+	printf("%s: com_out: drive not ready\n", w_name());
+	return(ERR);
+  }
+
+  /* Schedule a wakeup call, some controllers are flaky. This is done with
+   * a synchronous alarm. If a timeout occurs a SYN_ALARM message is sent
+   * from HARDWARE, so that w_intr_wait() can call w_timeout() in case the
+   * controller was not able to execute the command. Leftover timeouts are
+   * simply ignored by the main loop. 
+   */
+  sys_setalarm(wakeup_ticks, 0);
+
+  wn->w_status = STATUS_ADMBSY;
+  w_command = cmd->command;
+  pv_set(outbyte[0], base_ctl + REG_CTL, wn->pheads >= 8 ? CTL_EIGHTHEADS : 0);
+  pv_set(outbyte[1], base_cmd + REG_PRECOMP, cmd->precomp);
+  pv_set(outbyte[2], base_cmd + REG_COUNT, cmd->count);
+  pv_set(outbyte[3], base_cmd + REG_SECTOR, cmd->sector);
+  pv_set(outbyte[4], base_cmd + REG_CYL_LO, cmd->cyl_lo);
+  pv_set(outbyte[5], base_cmd + REG_CYL_HI, cmd->cyl_hi);
+  pv_set(outbyte[6], base_cmd + REG_COMMAND, cmd->command);
+  if ((s=sys_voutb(outbyte,7)) != OK)
+  	panic(w_name(),"Couldn't write registers with sys_voutb()",s);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				com_out_ext				     *
+ *===========================================================================*/
+PRIVATE int com_out_ext(cmd)
+struct command *cmd;		/* Command block */
+{
+/* Output the command block to the winchester controller and return status */
+
+  struct wini *wn = w_wn;
+  unsigned base_cmd = wn->base_cmd;
+  unsigned base_ctl = wn->base_ctl;
+  pvb_pair_t outbyte[11];		/* vector for sys_voutb() */
+  int s;				/* status for sys_(v)outb() */
+  unsigned long w_status;
+
+  if (w_wn->state & IGNORING) return ERR;
+
+  if (!w_waitfor(STATUS_BSY, 0)) {
+	printf("%s: controller not ready\n", w_name());
+	return(ERR);
+  }
+
+  /* Select drive. */
+  if ((s=sys_outb(base_cmd + REG_LDH, cmd->ldh)) != OK)
+  	panic(w_name(),"Couldn't write register to select drive",s);
+
+  if (!w_waitfor(STATUS_BSY, 0)) {
+	printf("%s: com_out: drive not ready\n", w_name());
+	return(ERR);
+  }
+
+  /* Schedule a wakeup call, some controllers are flaky. This is done with
+   * a synchronous alarm. If a timeout occurs a SYN_ALARM message is sent
+   * from HARDWARE, so that w_intr_wait() can call w_timeout() in case the
+   * controller was not able to execute the command. Leftover timeouts are
+   * simply ignored by the main loop. 
+   */
+  sys_setalarm(wakeup_ticks, 0);
+
+  wn->w_status = STATUS_ADMBSY;
+  w_command = cmd->command;
+  pv_set(outbyte[0], base_ctl + REG_CTL, 0);
+  pv_set(outbyte[1], base_cmd + REG_COUNT, cmd->count_prev);
+  pv_set(outbyte[2], base_cmd + REG_SECTOR, cmd->sector_prev);
+  pv_set(outbyte[3], base_cmd + REG_CYL_LO, cmd->cyl_lo_prev);
+  pv_set(outbyte[4], base_cmd + REG_CYL_HI, cmd->cyl_hi_prev);
+  pv_set(outbyte[5], base_cmd + REG_COUNT, cmd->count);
+  pv_set(outbyte[6], base_cmd + REG_SECTOR, cmd->sector);
+  pv_set(outbyte[7], base_cmd + REG_CYL_LO, cmd->cyl_lo);
+  pv_set(outbyte[8], base_cmd + REG_CYL_HI, cmd->cyl_hi);
+
+  pv_set(outbyte[10], base_cmd + REG_COMMAND, cmd->command);
+  if ((s=sys_voutb(outbyte, 11)) != OK)
+  	panic(w_name(),"Couldn't write registers with sys_voutb()",s);
+
+  return(OK);
+}
+
+/*===========================================================================*
+ *				setup_dma				     *
+ *===========================================================================*/
+PRIVATE void setup_dma(sizep, proc_nr, iov, do_write, do_copyoutp)
+unsigned *sizep;
+int proc_nr;
+iovec_t *iov;
+int do_write;
+int *do_copyoutp;
+{
+	phys_bytes phys, user_phys;
+	unsigned n, offset, size;
+	int i, j, r, bad;
+	unsigned long v;
+	struct wini *wn = w_wn;
+
+	/* First try direct scatter/gather to the supplied buffers */
+	size= *sizep;
+	i= 0;	/* iov index */
+	j= 0;	/* prdt index */
+	bad= 0;
+	offset= 0;	/* Offset in current iov */
+
+#if 0
+	printf("setup_dma: proc_nr %d\n", proc_nr);
+#endif
+
+	while (size > 0)
+	{
+#if 0
+		printf(
+		"setup_dma: iov[%d]: addr 0x%x, size %d offset %d, size %d\n",
+			i, iov[i].iov_addr, iov[i].iov_size, offset, size);
+#endif
+			
+		n= iov[i].iov_size-offset;
+		if (n > size)
+			n= size;
+		if (n == 0 || (n & 1))
+			panic("at_wini", "bad size in iov", iov[i].iov_size);
+		r= sys_umap(proc_nr, D, iov[i].iov_addr+offset, n, &user_phys);
+		if (r != 0)
+			panic("at_wini", "can't map user buffer", r);
+		if (user_phys & 1)
+		{
+			/* Buffer is not aligned */
+			printf("setup_dma: user buffer is not aligned\n");
+			bad= 1;
+			break;
+		}
+
+		/* vector is not allowed to cross a 64K boundary */
+		if (user_phys/0x10000 != (user_phys+n-1)/0x10000)
+			n= ((user_phys/0x10000)+1)*0x10000 - user_phys;
+
+		/* vector is not allowed to be bigger than 64K, but we get that
+		 * for free.
+		 */
+
+		if (j >= N_PRDTE)
+		{
+			/* Too many entries */
+			bad= 1;
+			break;
+		}
+
+		prdt[j].prdte_base= user_phys;
+		prdt[j].prdte_count= n;
+		prdt[j].prdte_reserved= 0;
+		prdt[j].prdte_flags= 0;
+		j++;
+
+		offset += n;
+		if (offset >= iov[i].iov_size)
+		{
+			i++;
+			offset= 0;
+		}
+
+		size -= n;
+	}
+
+	if (!bad)
+	{
+		if (j <= 0 || j > N_PRDTE)
+			panic("at_wini", "bad prdt index", j);
+		prdt[j-1].prdte_flags |= PRDTE_FL_EOT;
+
+#if 0
+		for (i= 0; i<j; i++)
+		{
+			printf("prdt[%d]: base 0x%x, size %d, flags 0x%x\n",
+				i, prdt[i].prdte_base, prdt[i].prdte_count,
+				prdt[i].prdte_flags);
+		}
+#endif
+	}
+
+	/* The caller needs to perform a copy-out from the dma buffer if
+	 * this is a read request and we can't DMA directly to the user's
+	 * buffers.
+	 */
+	*do_copyoutp= (!do_write && bad);
+
+	if (bad)
+	{
+		/* Adjust request size */
+		size= *sizep;
+		if (size > ATA_DMA_BUF_SIZE)
+			*sizep= size= ATA_DMA_BUF_SIZE;
+
+		if (do_write)
+		{
+			/* Copy-in */
+			for (offset= 0; offset < size; offset += n)
+			{
+				n= size-offset;
+				if (n > iov->iov_size)
+					n= iov->iov_size;
+			
+				r= sys_vircopy(proc_nr, D, iov->iov_addr,
+					SELF, D, (vir_bytes)dma_buf+offset, 
+					n);
+				if (r != OK)
+				{
+					panic(w_name(),
+					"setup_dma: sys_vircopy failed",
+						r);
+				}
+				iov++;
+			}
+		}
+	
+		/* Fill-in the physical region descriptor table */
+		phys= dma_buf_phys;
+		if (phys & 1)
+		{
+			/* Two byte alignment is required */
+			panic("at_wini", "bad buffer alignment in setup_dma",
+				phys);
+		}
+		for (j= 0; j<N_PRDTE; i++)
+		{
+			if (size == 0)
+			{
+				panic("at_wini", "bad size in setup_dma",
+					size);
+			}
+			if (size & 1)
+			{
+				/* Two byte alignment is required for size */
+				panic("at_wini",
+					"bad size alignment in setup_dma",
+					size);
+			}
+			n= size;
+
+			/* Buffer is not allowed to cross a 64K boundary */
+			if (phys / 0x10000 != (phys+n-1) / 0x10000)
+			{
+				n= ((phys/0x10000)+1)*0x10000 - phys;
+			}
+			prdt[j].prdte_base= phys;
+			prdt[j].prdte_count= n;
+			prdt[j].prdte_reserved= 0;
+			prdt[j].prdte_flags= 0;
+
+			size -= n;
+			if (size == 0)
+			{
+				prdt[j].prdte_flags |= PRDTE_FL_EOT;
+				break;
+			}
+		}
+		if (size != 0)
+			panic("at_wini", "size to large for prdt", NO_NUM);
+
+#if 0
+		for (i= 0; i<=j; i++)
+		{
+			printf("prdt[%d]: base 0x%x, size %d, flags 0x%x\n",
+				i, prdt[i].prdte_base, prdt[i].prdte_count,
+				prdt[i].prdte_flags);
+		}
+#endif
+	}
+
+	/* Stop bus master operation */
+	r= sys_outb(wn->base_dma + DMA_COMMAND, 0);
+	if (r != 0) panic("at_wini", "setup_dma: sys_outb failed", r);
+
+	/* Verify that the bus master is not active */
+	r= sys_inb(wn->base_dma + DMA_STATUS, &v);
+	if (r != 0) panic("at_wini", "setup_dma: sys_inb failed", r);
+	if (v & DMA_ST_BM_ACTIVE)
+		panic("at_wini", "Bus master IDE active", NO_NUM);
+
+	if (prdt_phys & 3)
+		panic("at_wini", "prdt not aligned", prdt_phys);
+	r= sys_outl(wn->base_dma + DMA_PRDTP, prdt_phys);
+	if (r != 0) panic("at_wini", "setup_dma: sys_outl failed", r);
+
+	/* Clear interrupt and error flags */
+	r= sys_outb(wn->base_dma + DMA_STATUS, DMA_ST_INT | DMA_ST_ERROR);
+	if (r != 0) panic("at_wini", "setup_dma: sys_outb failed", r);
+
+	/* Assume disk reads. Start DMA */
+	v= DMA_CMD_START;
+	if (!do_write)
+	{
+		/* Disk reads generate PCI write cycles. */
+		v |= DMA_CMD_WRITE;	
+	}
+	r= sys_outb(wn->base_dma + DMA_COMMAND, v);
+	if (r != 0) panic("at_wini", "setup_dma: sys_outb failed", r);
+
+#if 0
+	r= sys_inb(wn->base_dma + DMA_STATUS, &v);
+	if (r != 0) panic("at_wini", "setup_dma: sys_inb failed", r);
+	printf("dma status: 0x%x\n", v);
+#endif
+}
+
+
+/*===========================================================================*
+ *				w_need_reset				     *
+ *===========================================================================*/
+PRIVATE void w_need_reset()
+{
+/* The controller needs to be reset. */
+  struct wini *wn;
+  int dr = 0;
+
+  for (wn = wini; wn < &wini[MAX_DRIVES]; wn++, dr++) {
+	if (wn->base_cmd == w_wn->base_cmd) {
+		wn->state |= DEAF;
+		wn->state &= ~INITIALIZED;
+	}
+  }
+}
+
+/*===========================================================================*
+ *				w_do_close				     *
+ *===========================================================================*/
+PRIVATE int w_do_close(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+/* Device close: Release a device. */
+  if (w_prepare(m_ptr->DEVICE) == NIL_DEV)
+  	return(ENXIO);
+  w_wn->open_ct--;
+#if ENABLE_ATAPI
+  if (w_wn->open_ct == 0 && (w_wn->state & ATAPI)) atapi_close();
+#endif
+  return(OK);
+}
+
+/*===========================================================================*
+ *				com_simple				     *
+ *===========================================================================*/
+PRIVATE int com_simple(cmd)
+struct command *cmd;		/* Command block */
+{
+/* A simple controller command, only one interrupt and no data-out phase. */
+  int r;
+
+  if (w_wn->state & IGNORING) return ERR;
+
+  if ((r = com_out(cmd)) == OK) r = at_intr_wait();
+  w_command = CMD_IDLE;
+  return(r);
+}
+
+/*===========================================================================*
+ *				w_timeout				     *
+ *===========================================================================*/
+PRIVATE void w_timeout(void)
+{
+  struct wini *wn = w_wn;
+
+  switch (w_command) {
+  case CMD_IDLE:
+	break;		/* fine */
+  case CMD_READ:
+  case CMD_READ_EXT:
+  case CMD_WRITE:
+  case CMD_WRITE_EXT:
+	/* Impossible, but not on PC's:  The controller does not respond. */
+
+	/* Limiting multisector I/O seems to help. */
+	if (wn->max_count > 8 * SECTOR_SIZE) {
+		wn->max_count = 8 * SECTOR_SIZE;
+	} else {
+		wn->max_count = SECTOR_SIZE;
+	}
+	/*FALL THROUGH*/
+  default:
+	/* Some other command. */
+	if (w_testing)  wn->state |= IGNORING;	/* Kick out this drive. */
+	else if (!w_silent) printf("%s: timeout on command 0x%02x\n",
+		w_name(), w_command);
+	w_need_reset();
+	wn->w_status = 0;
+  }
+}
+
+/*===========================================================================*
+ *				w_reset					     *
+ *===========================================================================*/
+PRIVATE int w_reset()
+{
+/* Issue a reset to the controller.  This is done after any catastrophe,
+ * like the controller refusing to respond.
+ */
+  int s;
+  struct wini *wn = w_wn;
+
+  /* Don't bother if this drive is forgotten. */
+  if (w_wn->state & IGNORING) return ERR;
+
+  /* Wait for any internal drive recovery. */
+  tickdelay(RECOVERY_TICKS);
+
+  /* Strobe reset bit */
+  if ((s=sys_outb(wn->base_ctl + REG_CTL, CTL_RESET)) != OK)
+  	panic(w_name(),"Couldn't strobe reset bit",s);
+  tickdelay(DELAY_TICKS);
+  if ((s=sys_outb(wn->base_ctl + REG_CTL, 0)) != OK)
+  	panic(w_name(),"Couldn't strobe reset bit",s);
+  tickdelay(DELAY_TICKS);
+
+  /* Wait for controller ready */
+  if (!w_waitfor(STATUS_BSY, 0)) {
+	printf("%s: reset failed, drive busy\n", w_name());
+	return(ERR);
+  }
+
+  /* The error register should be checked now, but some drives mess it up. */
+
+  for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) {
+	if (wn->base_cmd == w_wn->base_cmd) {
+		wn->state &= ~DEAF;
+  		if (w_wn->irq_need_ack) {
+		    	/* Make sure irq is actually enabled.. */
+	  		sys_irqenable(&w_wn->irq_hook_id);
+		}
+	}
+  }
+		
+
+  return(OK);
+}
+
+/*===========================================================================*
+ *				w_intr_wait				     *
+ *===========================================================================*/
+PRIVATE void w_intr_wait()
+{
+/* Wait for a task completion interrupt. */
+
+  int r;
+  unsigned long w_status;
+  message m;
+
+  if (w_wn->irq != NO_IRQ) {
+	/* Wait for an interrupt that sets w_status to "not busy". */
+	while (w_wn->w_status & (STATUS_ADMBSY|STATUS_BSY)) {
+		int rr;
+		if((rr=receive(ANY, &m)) != OK) { /* expect HARD_INT message */
+			printf("w_intr_wait: receive from ANY failed (%d)\n",
+				r);
+			continue;	/* try again */
+		}
+		if (m.m_type == SYN_ALARM) { 	/* but check for timeout */
+		    w_timeout();		/* a.o. set w_status */
+		} else if (m.m_type == HARD_INT) {
+		    r= sys_inb(w_wn->base_cmd + REG_STATUS, &w_status);
+		    if (r != 0)
+			panic("at_wini", "sys_inb failed", r);
+		    w_wn->w_status= w_status;
+		    ack_irqs(m.NOTIFY_ARG);
+		} else if (m.m_type == DEV_PING) {
+		    notify(m.m_source);
+	        } else {
+	        	printf("AT_WINI got unexpected message %d from %d\n",
+	        		m.m_type, m.m_source);
+	        }
+	}
+  } else {
+	/* Interrupt not yet allocated; use polling. */
+	(void) w_waitfor(STATUS_BSY, 0);
+  }
+}
+
+/*===========================================================================*
+ *				at_intr_wait				     *
+ *===========================================================================*/
+PRIVATE int at_intr_wait()
+{
+/* Wait for an interrupt, study the status bits and return error/success. */
+  int r, s;
+  unsigned long inbval;
+
+  w_intr_wait();
+  if ((w_wn->w_status & (STATUS_BSY | STATUS_WF | STATUS_ERR)) == 0) {
+	r = OK;
+  } else {
+  	if ((s=sys_inb(w_wn->base_cmd + REG_ERROR, &inbval)) != OK)
+  		panic(w_name(),"Couldn't read register",s);
+  	if ((w_wn->w_status & STATUS_ERR) && (inbval & ERROR_BB)) {
+  		r = ERR_BAD_SECTOR;	/* sector marked bad, retries won't help */
+  	} else {
+  		r = ERR;		/* any other error */
+  	}
+  }
+  w_wn->w_status |= STATUS_ADMBSY;	/* assume still busy with I/O */
+  return(r);
+}
+
+/*===========================================================================*
+ *				w_waitfor				     *
+ *===========================================================================*/
+PRIVATE int w_waitfor(mask, value)
+int mask;			/* status mask */
+int value;			/* required status */
+{
+/* Wait until controller is in the required state.  Return zero on timeout.
+ * An alarm that set a timeout flag is used. TIMEOUT is in micros, we need
+ * ticks. Disabling the alarm is not needed, because a static flag is used
+ * and a leftover timeout cannot do any harm.
+ */
+  unsigned long w_status;
+  clock_t t0, t1;
+  int s;
+
+  getuptime(&t0);
+  do {
+	if ((s=sys_inb(w_wn->base_cmd + REG_STATUS, &w_status)) != OK)
+		panic(w_name(),"Couldn't read register",s);
+	w_wn->w_status= w_status;
+	if ((w_wn->w_status & mask) == value) {
+        	return 1;
+	}
+  } while ((s=getuptime(&t1)) == OK && (t1-t0) < timeout_ticks );
+  if (OK != s) printf("AT_WINI: warning, get_uptime failed: %d\n",s);
+
+  w_need_reset();			/* controller gone deaf */
+  return(0);
+}
+
+/*===========================================================================*
+ *				w_waitfor_dma				     *
+ *===========================================================================*/
+PRIVATE int w_waitfor_dma(mask, value)
+int mask;			/* status mask */
+int value;			/* required status */
+{
+/* Wait until controller is in the required state.  Return zero on timeout.
+ * An alarm that set a timeout flag is used. TIMEOUT is in micros, we need
+ * ticks. Disabling the alarm is not needed, because a static flag is used
+ * and a leftover timeout cannot do any harm.
+ */
+  unsigned long w_status;
+  clock_t t0, t1;
+  int s;
+
+  getuptime(&t0);
+  do {
+	if ((s=sys_inb(w_wn->base_dma + DMA_STATUS, &w_status)) != OK)
+		panic(w_name(),"Couldn't read register",s);
+	if ((w_status & mask) == value) {
+        	return 1;
+	}
+  } while ((s=getuptime(&t1)) == OK && (t1-t0) < timeout_ticks );
+  if (OK != s) printf("AT_WINI: warning, get_uptime failed: %d\n",s);
+
+  return(0);
+}
+
+/*===========================================================================*
+ *				w_geometry				     *
+ *===========================================================================*/
+PRIVATE void w_geometry(entry)
+struct partition *entry;
+{
+  struct wini *wn = w_wn;
+
+  if (wn->state & ATAPI) {		/* Make up some numbers. */
+	entry->cylinders = div64u(wn->part[0].dv_size, SECTOR_SIZE) / (64*32);
+	entry->heads = 64;
+	entry->sectors = 32;
+  } else {				/* Return logical geometry. */
+	entry->cylinders = wn->lcylinders;
+	entry->heads = wn->lheads;
+	entry->sectors = wn->lsectors;
+  }
+}
+
+#if ENABLE_ATAPI
+/*===========================================================================*
+ *				atapi_open				     *
+ *===========================================================================*/
+PRIVATE int atapi_open()
+{
+/* Should load and lock the device and obtain its size.  For now just set the
+ * size of the device to something big.  What is really needed is a generic
+ * SCSI layer that does all this stuff for ATAPI and SCSI devices (kjb). (XXX)
+ */
+  w_wn->part[0].dv_size = mul64u(800L*1024, 1024);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				atapi_close				     *
+ *===========================================================================*/
+PRIVATE void atapi_close()
+{
+/* Should unlock the device.  For now do nothing.  (XXX) */
+}
+
+void sense_request(void)
+{
+	int r, i;
+	static u8_t sense[100], packet[ATAPI_PACKETSIZE];
+
+	packet[0] = SCSI_SENSE;
+	packet[1] = 0;
+	packet[2] = 0;
+	packet[3] = 0;
+	packet[4] = SENSE_PACKETSIZE;
+	packet[5] = 0;
+	packet[7] = 0;
+	packet[8] = 0;
+	packet[9] = 0;
+	packet[10] = 0;
+	packet[11] = 0;
+
+	for(i = 0; i < SENSE_PACKETSIZE; i++) sense[i] = 0xff;
+	r = atapi_sendpacket(packet, SENSE_PACKETSIZE);
+	if (r != OK) { printf("request sense command failed\n"); return; }
+	if (atapi_intr_wait() <= 0) { printf("WARNING: request response failed\n"); }
+
+	if (sys_insw(w_wn->base_cmd + REG_DATA, SELF, (void *) sense, SENSE_PACKETSIZE) != OK)
+		printf("WARNING: sense reading failed\n");
+
+	printf("sense data:");
+	for(i = 0; i < SENSE_PACKETSIZE; i++) printf(" %02x", sense[i]);
+	printf("\n");
+}
+
+/*===========================================================================*
+ *				atapi_transfer				     *
+ *===========================================================================*/
+PRIVATE int atapi_transfer(proc_nr, opcode, position, iov, nr_req)
+int proc_nr;			/* process doing the request */
+int opcode;			/* DEV_GATHER or DEV_SCATTER */
+off_t position;			/* offset on device to read or write */
+iovec_t *iov;			/* pointer to read or write request vector */
+unsigned nr_req;		/* length of request vector */
+{
+  struct wini *wn = w_wn;
+  iovec_t *iop, *iov_end = iov + nr_req;
+  int r, s, errors, fresh;
+  u64_t pos;
+  unsigned long block;
+  unsigned long dv_size = cv64ul(w_dv->dv_size);
+  unsigned nbytes, nblocks, count, before, chunk;
+  static u8_t packet[ATAPI_PACKETSIZE];
+
+  errors = fresh = 0;
+
+  while (nr_req > 0 && !fresh) {
+	/* The Minix block size is smaller than the CD block size, so we
+	 * may have to read extra before or after the good data.
+	 */
+	pos = add64ul(w_dv->dv_base, position);
+	block = div64u(pos, CD_SECTOR_SIZE);
+	before = rem64u(pos, CD_SECTOR_SIZE);
+
+	/* How many bytes to transfer? */
+	nbytes = count = 0;
+	for (iop = iov; iop < iov_end; iop++) {
+		nbytes += iop->iov_size;
+		if ((before + nbytes) % CD_SECTOR_SIZE == 0) count = nbytes;
+	}
+
+	/* Does one of the memory chunks end nicely on a CD sector multiple? */
+	if (count != 0) nbytes = count;
+
+	/* Data comes in as words, so we have to enforce even byte counts. */
+	if ((before | nbytes) & 1) return(EINVAL);
+
+	/* Which block on disk and how close to EOF? */
+	if (position >= dv_size) return(OK);		/* At EOF */
+	if (position + nbytes > dv_size) nbytes = dv_size - position;
+
+	nblocks = (before + nbytes + CD_SECTOR_SIZE - 1) / CD_SECTOR_SIZE;
+	if (ATAPI_DEBUG) {
+		printf("block=%lu, before=%u, nbytes=%u, nblocks=%u\n",
+			block, before, nbytes, nblocks);
+	}
+
+	/* First check to see if a reinitialization is needed. */
+	if (!(wn->state & INITIALIZED) && w_specify() != OK) return(EIO);
+
+	/* Build an ATAPI command packet. */
+	packet[0] = SCSI_READ10;
+	packet[1] = 0;
+	packet[2] = (block >> 24) & 0xFF;
+	packet[3] = (block >> 16) & 0xFF;
+	packet[4] = (block >>  8) & 0xFF;
+	packet[5] = (block >>  0) & 0xFF;
+	packet[7] = (nblocks >> 8) & 0xFF;
+	packet[8] = (nblocks >> 0) & 0xFF;
+	packet[9] = 0;
+	packet[10] = 0;
+	packet[11] = 0;
+
+	/* Tell the controller to execute the packet command. */
+	r = atapi_sendpacket(packet, nblocks * CD_SECTOR_SIZE);
+	if (r != OK) goto err;
+
+	/* Read chunks of data. */
+	while ((r = atapi_intr_wait()) > 0) {
+		count = r;
+
+		if (ATAPI_DEBUG) {
+			printf("before=%u, nbytes=%u, count=%u\n",
+				before, nbytes, count);
+		}
+
+		while (before > 0 && count > 0) {	/* Discard before. */
+			chunk = before;
+			if (chunk > count) chunk = count;
+			if (chunk > DMA_BUF_SIZE) chunk = DMA_BUF_SIZE;
+	if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, chunk)) != OK)
+		panic(w_name(),"Call to sys_insw() failed", s);
+			before -= chunk;
+			count -= chunk;
+		}
+
+		while (nbytes > 0 && count > 0) {	/* Requested data. */
+			chunk = nbytes;
+			if (chunk > count) chunk = count;
+			if (chunk > iov->iov_size) chunk = iov->iov_size;
+	if ((s=sys_insw(wn->base_cmd + REG_DATA, proc_nr, (void *) iov->iov_addr, chunk)) != OK)
+		panic(w_name(),"Call to sys_insw() failed", s);
+			position += chunk;
+			nbytes -= chunk;
+			count -= chunk;
+			iov->iov_addr += chunk;
+			fresh = 0;
+			if ((iov->iov_size -= chunk) == 0) {
+				iov++;
+				nr_req--;
+				fresh = 1;	/* new element is optional */
+			}
+		}
+
+		while (count > 0) {		/* Excess data. */
+			chunk = count;
+			if (chunk > DMA_BUF_SIZE) chunk = DMA_BUF_SIZE;
+	if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, chunk)) != OK)
+		panic(w_name(),"Call to sys_insw() failed", s);
+			count -= chunk;
+		}
+	}
+
+	if (r < 0) {
+  err:		/* Don't retry if too many errors. */
+		if (atapi_debug) sense_request();
+		if (++errors == max_errors) {
+			w_command = CMD_IDLE;
+			if (atapi_debug) printf("giving up (%d)\n", errors);
+			return(EIO);
+		}
+		if (atapi_debug) printf("retry (%d)\n", errors);
+	}
+  }
+
+  w_command = CMD_IDLE;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				atapi_sendpacket			     *
+ *===========================================================================*/
+PRIVATE int atapi_sendpacket(packet, cnt)
+u8_t *packet;
+unsigned cnt;
+{
+/* Send an Atapi Packet Command */
+  struct wini *wn = w_wn;
+  pvb_pair_t outbyte[6];		/* vector for sys_voutb() */
+  int s;
+
+  if (wn->state & IGNORING) return ERR;
+
+  /* Select Master/Slave drive */
+  if ((s=sys_outb(wn->base_cmd + REG_DRIVE, wn->ldhpref)) != OK)
+  	panic(w_name(),"Couldn't select master/ slave drive",s);
+
+  if (!w_waitfor(STATUS_BSY | STATUS_DRQ, 0)) {
+	printf("%s: atapi_sendpacket: drive not ready\n", w_name());
+	return(ERR);
+  }
+
+  /* Schedule a wakeup call, some controllers are flaky. This is done with
+   * a synchronous alarm. If a timeout occurs a SYN_ALARM message is sent
+   * from HARDWARE, so that w_intr_wait() can call w_timeout() in case the
+   * controller was not able to execute the command. Leftover timeouts are
+   * simply ignored by the main loop. 
+   */
+  sys_setalarm(wakeup_ticks, 0);
+
+#if _WORD_SIZE > 2
+  if (cnt > 0xFFFE) cnt = 0xFFFE;	/* Max data per interrupt. */
+#endif
+
+  w_command = ATAPI_PACKETCMD;
+  pv_set(outbyte[0], wn->base_cmd + REG_FEAT, 0);
+  pv_set(outbyte[1], wn->base_cmd + REG_IRR, 0);
+  pv_set(outbyte[2], wn->base_cmd + REG_SAMTAG, 0);
+  pv_set(outbyte[3], wn->base_cmd + REG_CNT_LO, (cnt >> 0) & 0xFF);
+  pv_set(outbyte[4], wn->base_cmd + REG_CNT_HI, (cnt >> 8) & 0xFF);
+  pv_set(outbyte[5], wn->base_cmd + REG_COMMAND, w_command);
+  if (atapi_debug) printf("cmd: %x  ", w_command);
+  if ((s=sys_voutb(outbyte,6)) != OK)
+  	panic(w_name(),"Couldn't write registers with sys_voutb()",s);
+
+  if (!w_waitfor(STATUS_BSY | STATUS_DRQ, STATUS_DRQ)) {
+	printf("%s: timeout (BSY|DRQ -> DRQ)\n", w_name());
+	return(ERR);
+  }
+  wn->w_status |= STATUS_ADMBSY;		/* Command not at all done yet. */
+
+  /* Send the command packet to the device. */
+  if ((s=sys_outsw(wn->base_cmd + REG_DATA, SELF, packet, ATAPI_PACKETSIZE)) != OK)
+	panic(w_name(),"sys_outsw() failed", s);
+
+ {
+ int p;
+ if (atapi_debug) {
+ 	printf("sent command:");
+	 for(p = 0; p < ATAPI_PACKETSIZE; p++) { printf(" %02x", packet[p]); }
+	 printf("\n");
+	}
+ }
+  return(OK);
+}
+
+
+#endif /* ENABLE_ATAPI */
+
+/*===========================================================================*
+ *				w_other					     *
+ *===========================================================================*/
+PRIVATE int w_other(dr, m)
+struct driver *dr;
+message *m;
+{
+	int r, timeout, prev;
+
+	if (m->m_type != DEV_IOCTL ) {
+		return EINVAL;
+	}
+
+	if (m->REQUEST == DIOCTIMEOUT) {
+		if ((r=sys_datacopy(m->IO_ENDPT, (vir_bytes)m->ADDRESS,
+			SELF, (vir_bytes)&timeout, sizeof(timeout))) != OK)
+			return r;
+	
+		if (timeout == 0) {
+			/* Restore defaults. */
+			timeout_ticks = DEF_TIMEOUT_TICKS;
+			max_errors = MAX_ERRORS;
+			wakeup_ticks = WAKEUP;
+			w_silent = 0;
+		} else if (timeout < 0) {
+			return EINVAL;
+		} else  {
+			prev = wakeup_ticks;
+	
+			if (!w_standard_timeouts) {
+				/* Set (lower) timeout, lower error
+				 * tolerance and set silent mode.
+				 */
+				wakeup_ticks = timeout;
+				max_errors = 3;
+				w_silent = 1;
+	
+				if (timeout_ticks > timeout)
+					timeout_ticks = timeout;
+			}
+	
+			if ((r=sys_datacopy(SELF, (vir_bytes)&prev, 
+				m->IO_ENDPT, (vir_bytes)m->ADDRESS, sizeof(prev))) != OK)
+				return r;
+		}
+	
+		return OK;
+	} else  if (m->REQUEST == DIOCOPENCT) {
+		int count;
+		if (w_prepare(m->DEVICE) == NIL_DEV) return ENXIO;
+		count = w_wn->open_ct;
+		if ((r=sys_datacopy(SELF, (vir_bytes)&count, 
+			m->IO_ENDPT, (vir_bytes)m->ADDRESS, sizeof(count))) != OK)
+			return r;
+		return OK;
+	}
+	return EINVAL;
+}
+
+/*===========================================================================*
+ *				w_hw_int				     *
+ *===========================================================================*/
+PRIVATE int w_hw_int(dr, m)
+struct driver *dr;
+message *m;
+{
+  /* Leftover interrupt(s) received; ack it/them. */
+  ack_irqs(m->NOTIFY_ARG);
+
+  return OK;
+}
+
+
+/*===========================================================================*
+ *				ack_irqs				     *
+ *===========================================================================*/
+PRIVATE void ack_irqs(unsigned int irqs)
+{
+  unsigned int drive;
+  unsigned long w_status;
+
+  for (drive = 0; drive < MAX_DRIVES && irqs; drive++) {
+  	if (!(wini[drive].state & IGNORING) && wini[drive].irq_need_ack &&
+		(wini[drive].irq_mask & irqs)) {
+		if (sys_inb((wini[drive].base_cmd + REG_STATUS),
+			&w_status) != OK)
+		{
+		  	panic(w_name(), "couldn't ack irq on drive %d\n",
+				drive);
+		}
+		wini[drive].w_status= w_status;
+	 	if (sys_irqenable(&wini[drive].irq_hook_id) != OK)
+		  	printf("couldn't re-enable drive %d\n", drive);
+		irqs &= ~wini[drive].irq_mask;
+	}
+  }
+}
+
+
+#define STSTR(a) if (status & STATUS_ ## a) { strcat(str, #a); strcat(str, " "); }
+#define ERRSTR(a) if (e & ERROR_ ## a) { strcat(str, #a); strcat(str, " "); }
+char *strstatus(int status)
+{
+	static char str[200];
+	str[0] = '\0';
+
+	STSTR(BSY);
+	STSTR(DRDY);
+	STSTR(DMADF);
+	STSTR(SRVCDSC);
+	STSTR(DRQ);
+	STSTR(CORR);
+	STSTR(CHECK);
+	return str;
+}
+
+char *strerr(int e)
+{
+	static char str[200];
+	str[0] = '\0';
+
+	ERRSTR(BB);
+	ERRSTR(ECC);
+	ERRSTR(ID);
+	ERRSTR(AC);
+	ERRSTR(TK);
+	ERRSTR(DM);
+
+	return str;
+}
+
+#if ENABLE_ATAPI
+
+/*===========================================================================*
+ *				atapi_intr_wait				     *
+ *===========================================================================*/
+PRIVATE int atapi_intr_wait()
+{
+/* Wait for an interrupt and study the results.  Returns a number of bytes
+ * that need to be transferred, or an error code.
+ */
+  struct wini *wn = w_wn;
+  pvb_pair_t inbyte[4];		/* vector for sys_vinb() */
+  int s;			/* status for sys_vinb() */
+  int e;
+  int len;
+  int irr;
+  int r;
+  int phase;
+
+  w_intr_wait();
+
+  /* Request series of device I/O. */
+  inbyte[0].port = wn->base_cmd + REG_ERROR;
+  inbyte[1].port = wn->base_cmd + REG_CNT_LO;
+  inbyte[2].port = wn->base_cmd + REG_CNT_HI;
+  inbyte[3].port = wn->base_cmd + REG_IRR;
+  if ((s=sys_vinb(inbyte, 4)) != OK)
+  	panic(w_name(),"ATAPI failed sys_vinb()", s);
+  e = inbyte[0].value;
+  len = inbyte[1].value;
+  len |= inbyte[2].value << 8;
+  irr = inbyte[3].value;
+
+#if ATAPI_DEBUG
+	printf("wn %p  S=%x=%s E=%02x=%s L=%04x I=%02x\n", wn, wn->w_status, strstatus(wn->w_status), e, strerr(e), len, irr);
+#endif
+  if (wn->w_status & (STATUS_BSY | STATUS_CHECK)) {
+	if (atapi_debug) {
+		printf("atapi fail:  S=%x=%s E=%02x=%s L=%04x I=%02x\n", wn->w_status, strstatus(wn->w_status), e, strerr(e), len, irr);
+	}
+  	return ERR;
+  }
+
+  phase = (wn->w_status & STATUS_DRQ) | (irr & (IRR_COD | IRR_IO));
+
+  switch (phase) {
+  case IRR_COD | IRR_IO:
+	if (ATAPI_DEBUG) printf("ACD: Phase Command Complete\n");
+	r = OK;
+	break;
+  case 0:
+	if (ATAPI_DEBUG) printf("ACD: Phase Command Aborted\n");
+	r = ERR;
+	break;
+  case STATUS_DRQ | IRR_COD:
+	if (ATAPI_DEBUG) printf("ACD: Phase Command Out\n");
+	r = ERR;
+	break;
+  case STATUS_DRQ:
+	if (ATAPI_DEBUG) printf("ACD: Phase Data Out %d\n", len);
+	r = len;
+	break;
+  case STATUS_DRQ | IRR_IO:
+	if (ATAPI_DEBUG) printf("ACD: Phase Data In %d\n", len);
+	r = len;
+	break;
+  default:
+	if (ATAPI_DEBUG) printf("ACD: Phase Unknown\n");
+	r = ERR;
+	break;
+  }
+
+#if 0
+  /* retry if the media changed */
+  XXX while (phase == (IRR_IO | IRR_COD) && (wn->w_status & STATUS_CHECK)
+	&& (e & ERROR_SENSE) == SENSE_UATTN && --try > 0);
+#endif
+
+  wn->w_status |= STATUS_ADMBSY;	/* Assume not done yet. */
+  return(r);
+}
+#endif /* ENABLE_ATAPI */
Index: /trunk/minix/drivers/at_wini/at_wini.h
===================================================================
--- /trunk/minix/drivers/at_wini/at_wini.h	(revision 9)
+++ /trunk/minix/drivers/at_wini/at_wini.h	(revision 9)
@@ -0,0 +1,8 @@
+#include "../drivers.h"
+#include "../libdriver/driver.h"
+#include "../libdriver/drvlib.h"
+
+_PROTOTYPE(int main, (void));
+
+#define VERBOSE		   0	/* display identify messages during boot */
+#define ENABLE_ATAPI	   1	/* add ATAPI cd-rom support to driver */
Index: /trunk/minix/drivers/bios_wini/.depend
===================================================================
--- /trunk/minix/drivers/bios_wini/.depend	(revision 9)
+++ /trunk/minix/drivers/bios_wini/.depend	(revision 9)
@@ -0,0 +1,96 @@
+
+bios_wini.o:	../drivers.h
+bios_wini.o:	../libdriver/driver.h
+bios_wini.o:	../libdriver/drvlib.h
+bios_wini.o:	/usr/include/ansi.h
+bios_wini.o:	/usr/include/assert.h
+bios_wini.o:	/usr/include/errno.h
+bios_wini.o:	/usr/include/ibm/bios.h
+bios_wini.o:	/usr/include/ibm/int86.h
+bios_wini.o:	/usr/include/ibm/interrupt.h
+bios_wini.o:	/usr/include/ibm/partition.h
+bios_wini.o:	/usr/include/ibm/ports.h
+bios_wini.o:	/usr/include/limits.h
+bios_wini.o:	/usr/include/minix/bitmap.h
+bios_wini.o:	/usr/include/minix/callnr.h
+bios_wini.o:	/usr/include/minix/com.h
+bios_wini.o:	/usr/include/minix/config.h
+bios_wini.o:	/usr/include/minix/const.h
+bios_wini.o:	/usr/include/minix/devio.h
+bios_wini.o:	/usr/include/minix/dmap.h
+bios_wini.o:	/usr/include/minix/ioctl.h
+bios_wini.o:	/usr/include/minix/ipc.h
+bios_wini.o:	/usr/include/minix/keymap.h
+bios_wini.o:	/usr/include/minix/partition.h
+bios_wini.o:	/usr/include/minix/sys_config.h
+bios_wini.o:	/usr/include/minix/syslib.h
+bios_wini.o:	/usr/include/minix/sysutil.h
+bios_wini.o:	/usr/include/minix/type.h
+bios_wini.o:	/usr/include/minix/u64.h
+bios_wini.o:	/usr/include/signal.h
+bios_wini.o:	/usr/include/stddef.h
+bios_wini.o:	/usr/include/stdlib.h
+bios_wini.o:	/usr/include/string.h
+bios_wini.o:	/usr/include/sys/dir.h
+bios_wini.o:	/usr/include/sys/ioc_disk.h
+bios_wini.o:	/usr/include/sys/types.h
+bios_wini.o:	/usr/include/unistd.h
+bios_wini.o:	bios_wini.c
+
+../libdriver/driver.o:	../libdriver/../drivers.h
+../libdriver/driver.o:	../libdriver/driver.c
+../libdriver/driver.o:	../libdriver/driver.h
+../libdriver/driver.o:	/usr/include/ansi.h
+../libdriver/driver.o:	/usr/include/errno.h
+../libdriver/driver.o:	/usr/include/ibm/bios.h
+../libdriver/driver.o:	/usr/include/ibm/interrupt.h
+../libdriver/driver.o:	/usr/include/ibm/ports.h
+../libdriver/driver.o:	/usr/include/limits.h
+../libdriver/driver.o:	/usr/include/minix/bitmap.h
+../libdriver/driver.o:	/usr/include/minix/callnr.h
+../libdriver/driver.o:	/usr/include/minix/com.h
+../libdriver/driver.o:	/usr/include/minix/config.h
+../libdriver/driver.o:	/usr/include/minix/const.h
+../libdriver/driver.o:	/usr/include/minix/devio.h
+../libdriver/driver.o:	/usr/include/minix/dmap.h
+../libdriver/driver.o:	/usr/include/minix/ioctl.h
+../libdriver/driver.o:	/usr/include/minix/ipc.h
+../libdriver/driver.o:	/usr/include/minix/partition.h
+../libdriver/driver.o:	/usr/include/minix/sys_config.h
+../libdriver/driver.o:	/usr/include/minix/syslib.h
+../libdriver/driver.o:	/usr/include/minix/sysutil.h
+../libdriver/driver.o:	/usr/include/minix/type.h
+../libdriver/driver.o:	/usr/include/minix/u64.h
+../libdriver/driver.o:	/usr/include/signal.h
+../libdriver/driver.o:	/usr/include/stddef.h
+../libdriver/driver.o:	/usr/include/stdlib.h
+../libdriver/driver.o:	/usr/include/string.h
+../libdriver/driver.o:	/usr/include/sys/dir.h
+../libdriver/driver.o:	/usr/include/sys/ioc_disk.h
+../libdriver/driver.o:	/usr/include/sys/types.h
+../libdriver/driver.o:	/usr/include/unistd.h
+
+../libdriver/drvlib.o:	../libdriver/driver.h
+../libdriver/drvlib.o:	../libdriver/drvlib.c
+../libdriver/drvlib.o:	../libdriver/drvlib.h
+../libdriver/drvlib.o:	/usr/include/ansi.h
+../libdriver/drvlib.o:	/usr/include/errno.h
+../libdriver/drvlib.o:	/usr/include/ibm/partition.h
+../libdriver/drvlib.o:	/usr/include/limits.h
+../libdriver/drvlib.o:	/usr/include/minix/callnr.h
+../libdriver/drvlib.o:	/usr/include/minix/com.h
+../libdriver/drvlib.o:	/usr/include/minix/config.h
+../libdriver/drvlib.o:	/usr/include/minix/const.h
+../libdriver/drvlib.o:	/usr/include/minix/devio.h
+../libdriver/drvlib.o:	/usr/include/minix/ipc.h
+../libdriver/drvlib.o:	/usr/include/minix/partition.h
+../libdriver/drvlib.o:	/usr/include/minix/sys_config.h
+../libdriver/drvlib.o:	/usr/include/minix/syslib.h
+../libdriver/drvlib.o:	/usr/include/minix/sysutil.h
+../libdriver/drvlib.o:	/usr/include/minix/type.h
+../libdriver/drvlib.o:	/usr/include/minix/u64.h
+../libdriver/drvlib.o:	/usr/include/stddef.h
+../libdriver/drvlib.o:	/usr/include/string.h
+../libdriver/drvlib.o:	/usr/include/sys/dir.h
+../libdriver/drvlib.o:	/usr/include/sys/types.h
+../libdriver/drvlib.o:	/usr/include/unistd.h
Index: /trunk/minix/drivers/bios_wini/Makefile
===================================================================
--- /trunk/minix/drivers/bios_wini/Makefile	(revision 9)
+++ /trunk/minix/drivers/bios_wini/Makefile	(revision 9)
@@ -0,0 +1,46 @@
+# Makefile for the BIOS disk driver (BIOS_WINI)
+DRIVER = bios_wini
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+MAKE = exec make
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsysutil -lsys -ltimers
+
+OBJ = bios_wini.o 
+LIBDRIVER = $d/libdriver/driver.o $d/libdriver/drvlib.o
+
+
+# build local binary
+all build:	$(DRIVER)
+$(DRIVER):	$(OBJ) $(LIBDRIVER)
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBDRIVER) $(LIBS)
+	install -S 4k $(DRIVER)
+
+$(LIBDRIVER): 
+	cd $d/libdriver && $(MAKE) 
+
+# install with other drivers
+install:	/sbin/$(DRIVER)
+/sbin/$(DRIVER):	$(DRIVER)
+	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f $(DRIVER) *.o *.bak 
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c ../libdriver/*.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/bios_wini/bios_wini.c
===================================================================
--- /trunk/minix/drivers/bios_wini/bios_wini.c	(revision 9)
+++ /trunk/minix/drivers/bios_wini/bios_wini.c	(revision 9)
@@ -0,0 +1,510 @@
+/* This file contains the "device dependent" part of a hard disk driver that
+ * uses the ROM BIOS.  It makes a call and just waits for the transfer to
+ * happen.  It is not interrupt driven and thus will (*) have poor performance.
+ * The advantage is that it should work on virtually any PC, XT, 386, PS/2
+ * or clone.  The demo disk uses this driver.  It is suggested that all
+ * MINIX users try the other drivers, and use this one only as a last resort,
+ * if all else fails.
+ *
+ * (*) The performance is within 10% of the AT driver for reads on any disk
+ *     and writes on a 2:1 interleaved disk, it will be DMA_BUF_SIZE bytes
+ *     per revolution for a minimum of 60 kb/s for writes to 1:1 disks.
+ *
+ * The file contains one entry point:
+ *
+ *	 bios_winchester_task:	main entry when system is brought up
+ *
+ *
+ * Changes:
+ *	30 Apr 1992 by Kees J. Bot: device dependent/independent split.
+ *	14 May 2000 by Kees J. Bot: d-d/i rewrite.
+ */
+
+#include "../drivers.h"
+#include "../libdriver/driver.h"
+#include "../libdriver/drvlib.h"
+#include <minix/sysutil.h>
+#include <minix/keymap.h>
+#include <sys/ioc_disk.h>
+#include <ibm/int86.h>
+#include <assert.h>
+
+#define ME "BIOS_WINI"
+
+/* Error codes */
+#define ERR		 (-1)	/* general error */
+
+/* Parameters for the disk drive. */
+#define MAX_DRIVES         8	/* this driver supports 8 drives (d0 - d7)*/
+#define MAX_SECS	 255	/* bios can transfer this many sectors */
+#define NR_MINORS      (MAX_DRIVES * DEV_PER_DRIVE)
+#define SUB_PER_DRIVE	(NR_PARTITIONS * NR_PARTITIONS)
+#define NR_SUBDEVS	(MAX_DRIVES * SUB_PER_DRIVE)
+
+PRIVATE int pc_at = 1;	/* What about PC XTs? */
+
+/* Variables. */
+PRIVATE struct wini {		/* main drive struct, one entry per drive */
+  unsigned cylinders;		/* number of cylinders */
+  unsigned heads;		/* number of heads */
+  unsigned sectors;		/* number of sectors per track */
+  unsigned open_ct;		/* in-use count */
+  int drive_id;			/* Drive ID at BIOS level */
+  int present;			/* Valid drive */
+  int int13ext;			/* IBM/MS INT 13 extensions supported? */
+  struct device part[DEV_PER_DRIVE];	/* disks and partitions */
+  struct device subpart[SUB_PER_DRIVE]; /* subpartitions */
+} wini[MAX_DRIVES], *w_wn;
+
+PRIVATE int w_drive;			/* selected drive */
+PRIVATE struct device *w_dv;		/* device's base and size */
+PRIVATE vir_bytes bios_buf_vir, bios_buf_size;
+PRIVATE phys_bytes bios_buf_phys;
+PRIVATE int remap_first = 0;		/* Remap drives for CD HD emulation */
+
+_PROTOTYPE(int main, (void) );
+FORWARD _PROTOTYPE( struct device *w_prepare, (int device) );
+FORWARD _PROTOTYPE( char *w_name, (void) );
+FORWARD _PROTOTYPE( int w_transfer, (int proc_nr, int opcode, off_t position,
+					iovec_t *iov, unsigned nr_req) );
+FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) );
+FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
+FORWARD _PROTOTYPE( void w_init, (void) );
+FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry));
+FORWARD _PROTOTYPE( int w_other, (struct driver *dp, message *m_ptr)    );
+
+/* Entry points to this driver. */
+PRIVATE struct driver w_dtab = {
+  w_name,	/* current device's name */
+  w_do_open,	/* open or mount request, initialize device */
+  w_do_close,	/* release device */
+  do_diocntl,	/* get or set a partition's geometry */
+  w_prepare,	/* prepare for I/O on a given minor device */
+  w_transfer,	/* do the I/O */
+  nop_cleanup,	/* no cleanup needed */
+  w_geometry,	/* tell the geometry of the disk */
+  nop_signal,		/* no cleanup needed on shutdown */
+  nop_alarm,		/* ignore leftover alarms */
+  nop_cancel,		/* ignore CANCELs */
+  nop_select,		/* ignore selects */
+  w_other,		/* catch-all for unrecognized commands and ioctls */
+  NULL			/* leftover hardware interrupts */
+};
+
+/*===========================================================================*
+ *				bios_winchester_task			     *
+ *===========================================================================*/
+PUBLIC int main()
+{
+  long v;
+  struct sigaction sa;
+ 
+  sa.sa_handler = SIG_MESS;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = 0;
+  if (sigaction(SIGTERM,&sa,NULL)<0) panic("BIOS","sigaction failed", errno);
+
+  v= 0;
+  env_parse("bios_remap_first", "d", 0, &v, 0, 1);
+  remap_first= v;
+
+/* Set special disk parameters then call the generic main loop. */
+  driver_task(&w_dtab);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				w_prepare				     *
+ *===========================================================================*/
+PRIVATE struct device *w_prepare(device)
+int device;
+{
+/* Prepare for I/O on a device. */
+
+  if (device < NR_MINORS) {			/* d0, d0p[0-3], d1, ... */
+	w_drive = device / DEV_PER_DRIVE;	/* save drive number */
+	w_wn = &wini[w_drive];
+	w_dv = &w_wn->part[device % DEV_PER_DRIVE];
+  } else
+  if ((unsigned) (device -= MINOR_d0p0s0) < NR_SUBDEVS) {/*d[0-7]p[0-3]s[0-3]*/
+	w_drive = device / SUB_PER_DRIVE;
+	w_wn = &wini[w_drive];
+	w_dv = &w_wn->subpart[device % SUB_PER_DRIVE];
+  } else {
+	return(NIL_DEV);
+  }
+  if (w_drive >= MAX_DRIVES || !w_wn->present)
+  	return NIL_DEV;
+  return(w_dv);
+}
+
+/*===========================================================================*
+ *				w_name					     *
+ *===========================================================================*/
+PRIVATE char *w_name()
+{
+/* Return a name for the current device. */
+  static char name[] = "bios-d0";
+
+  name[6] = '0' + w_drive;
+  return name;
+}
+
+/*===========================================================================*
+ *				w_transfer				     *
+ *===========================================================================*/
+PRIVATE int w_transfer(proc_nr, opcode, position, iov, nr_req)
+int proc_nr;			/* process doing the request */
+int opcode;			/* DEV_GATHER or DEV_SCATTER */
+off_t position;			/* offset on device to read or write */
+iovec_t *iov;			/* pointer to read or write request vector */
+unsigned nr_req;		/* length of request vector */
+{
+  struct wini *wn = w_wn;
+  iovec_t *iop, *iov_end = iov + nr_req;
+  int r, errors;
+  unsigned nbytes, count, chunk;
+  unsigned long block;
+  vir_bytes i13e_rw_off, rem_buf_size;
+  unsigned long dv_size = cv64ul(w_dv->dv_size);
+  unsigned secspcyl = wn->heads * wn->sectors;
+  struct int13ext_rw {
+	u8_t	len;
+	u8_t	res1;
+	u16_t	count;
+	u16_t	addr[2];
+	u32_t	block[2];
+  } i13e_rw;
+  struct reg86u reg86;
+
+  /* Check disk address. */
+  if ((position & SECTOR_MASK) != 0) return(EINVAL);
+
+  errors = 0;
+
+  i13e_rw_off= bios_buf_size-sizeof(i13e_rw);
+  rem_buf_size= (i13e_rw_off & ~SECTOR_MASK);
+  assert(rem_buf_size != 0);
+
+  while (nr_req > 0) {
+	/* How many bytes to transfer? */
+	nbytes = 0;
+	for (iop = iov; iop < iov_end; iop++) {
+		if (nbytes + iop->iov_size > rem_buf_size) {
+			/* Don't do half a segment if you can avoid it. */
+			if (nbytes == 0) nbytes = rem_buf_size;
+			break;
+		}
+		nbytes += iop->iov_size;
+	}
+	if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
+
+	/* Which block on disk and how close to EOF? */
+	if (position >= dv_size) return(OK);		/* At EOF */
+	if (position + nbytes > dv_size) nbytes = dv_size - position;
+	block = div64u(add64ul(w_dv->dv_base, position), SECTOR_SIZE);
+
+	/* Degrade to per-sector mode if there were errors. */
+	if (errors > 0) nbytes = SECTOR_SIZE;
+
+	if (opcode == DEV_SCATTER) {
+		/* Copy from user space to the DMA buffer. */
+		count = 0;
+		for (iop = iov; count < nbytes; iop++) {
+			chunk = iov->iov_size;
+			if (count + chunk > nbytes) chunk = nbytes - count;
+			assert(chunk <= rem_buf_size);
+			r= sys_vircopy(proc_nr, D, iop->iov_addr,
+				SYSTEM, D, bios_buf_vir+count, 
+				chunk);
+			if (r != OK)
+				panic(ME, "sys_vircopy failed", r);
+			count += chunk;
+		}
+	}
+
+	/* Do the transfer */
+	if (wn->int13ext) {
+		i13e_rw.len = 0x10;
+		i13e_rw.res1 = 0;
+		i13e_rw.count = nbytes >> SECTOR_SHIFT;
+		i13e_rw.addr[0] = bios_buf_phys % HCLICK_SIZE;
+		i13e_rw.addr[1] = bios_buf_phys / HCLICK_SIZE;
+		i13e_rw.block[0] = block;
+		i13e_rw.block[1] = 0;
+		r= sys_vircopy(SELF, D, (vir_bytes)&i13e_rw,
+			SYSTEM, D, (bios_buf_vir+i13e_rw_off), 
+			sizeof(i13e_rw));
+		if (r != OK)
+			panic(ME, "sys_vircopy failed", r);
+
+		/* Set up an extended read or write BIOS call. */
+		reg86.u.b.intno = 0x13;
+		reg86.u.w.ax = opcode == DEV_SCATTER ? 0x4300 : 0x4200;
+		reg86.u.b.dl = wn->drive_id;
+		reg86.u.w.si = (bios_buf_phys + i13e_rw_off) % HCLICK_SIZE;
+		reg86.u.w.ds = (bios_buf_phys + i13e_rw_off) / HCLICK_SIZE;
+	} else {
+		/* Set up an ordinary read or write BIOS call. */
+		unsigned cylinder = block / secspcyl;
+		unsigned sector = (block % wn->sectors) + 1;
+		unsigned head = (block % secspcyl) / wn->sectors;
+
+		reg86.u.b.intno = 0x13;
+		reg86.u.b.ah = opcode == DEV_SCATTER ? 0x03 : 0x02;
+		reg86.u.b.al = nbytes >> SECTOR_SHIFT;
+		reg86.u.w.bx = bios_buf_phys % HCLICK_SIZE;
+		reg86.u.w.es = bios_buf_phys / HCLICK_SIZE;
+		reg86.u.b.ch = cylinder & 0xFF;
+		reg86.u.b.cl = sector | ((cylinder & 0x300) >> 2);
+		reg86.u.b.dh = head;
+		reg86.u.b.dl = wn->drive_id;
+	}
+
+	r= sys_int86(&reg86);
+	if (r != OK)
+		panic(ME, "BIOS call failed", r);
+
+	if (reg86.u.w.f & 0x0001) {
+		/* An error occurred, try again sector by sector unless */
+		if (++errors == 2) return(EIO);
+		continue;
+	}
+
+	if (opcode == DEV_GATHER) {
+		/* Copy from the DMA buffer to user space. */
+		count = 0;
+		for (iop = iov; count < nbytes; iop++) {
+			chunk = iov->iov_size;
+			if (count + chunk > nbytes) chunk = nbytes - count;
+			assert(chunk <= rem_buf_size);
+			r= sys_vircopy(SYSTEM, D, bios_buf_vir+count, 
+				proc_nr, D, iop->iov_addr,
+				chunk);
+			if (r != OK)
+				panic(ME, "sys_vircopy failed", r);
+			count += chunk;
+		}
+	}
+
+	/* Book the bytes successfully transferred. */
+	position += nbytes;
+	for (;;) {
+		if (nbytes < iov->iov_size) {
+			/* Not done with this one yet. */
+			iov->iov_addr += nbytes;
+			iov->iov_size -= nbytes;
+			break;
+		}
+		nbytes -= iov->iov_size;
+		iov->iov_addr += iov->iov_size;
+		iov->iov_size = 0;
+		if (nbytes == 0) {
+			/* The rest is optional, so we return to give FS a
+			 * chance to think it over.
+			 */
+			return(OK);
+		}
+		iov++;
+		nr_req--;
+	}
+  }
+  return(OK);
+}
+
+/*============================================================================*
+ *				w_do_open				      *
+ *============================================================================*/
+PRIVATE int w_do_open(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+/* Device open: Initialize the controller and read the partition table. */
+
+  static int init_done = FALSE;
+
+  if (!init_done) { w_init(); init_done = TRUE; }
+
+  if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
+
+  if (w_wn->open_ct++ == 0) {
+	/* Partition the disk. */
+	partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY, 0);
+  }
+  return(OK);
+}
+
+/*============================================================================*
+ *				w_do_close				      *
+ *============================================================================*/
+PRIVATE int w_do_close(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+/* Device close: Release a device. */
+
+  if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
+  w_wn->open_ct--;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				w_init					     *
+ *===========================================================================*/
+PRIVATE void w_init()
+{
+/* This routine is called at startup to initialize the drive parameters. */
+
+  int r, drive, drive_id, nr_drives;
+  struct wini *wn;
+  unsigned long capacity;
+  struct int13ext_params {
+	u16_t	len;
+	u16_t	flags;
+	u32_t	cylinders;
+	u32_t	heads;
+	u32_t	sectors;
+	u32_t	capacity[2];
+	u16_t	bts_per_sec;
+	u16_t	config[2];
+  } i13e_par;
+  struct reg86u reg86;
+
+  /* Ask the system task for a suitable buffer */
+  r= sys_getbiosbuffer(&bios_buf_vir, &bios_buf_size);
+  if (r != OK)
+  	panic(ME, "sys_getbiosbuffer failed", r);
+  r= sys_umap(SYSTEM, D, (vir_bytes)bios_buf_vir, (phys_bytes)bios_buf_size,
+  	&bios_buf_phys);
+  if (r != OK)
+  	panic(ME, "sys_umap failed", r);
+  if (bios_buf_phys+bios_buf_size > 0x100000)
+  	panic(ME, "bad BIOS buffer, phys", bios_buf_phys);
+#if 0
+  printf("bios_wini: got buffer size %d, virtual 0x%x, phys 0x%x\n",
+  		bios_buf_size, bios_buf_vir, bios_buf_phys);
+#endif
+
+  /* Get the geometry of the drives */
+  for (drive = 0; drive < MAX_DRIVES; drive++) {
+  	if (remap_first)
+  	{
+  		if (drive == 7)
+			drive_id= 0x80;
+		else
+			drive_id= 0x80 + drive + 1;
+  	}
+  	else
+		drive_id= 0x80 + drive;
+
+	(void) w_prepare(drive * DEV_PER_DRIVE);
+	wn = w_wn;
+	wn->drive_id= drive_id;
+
+	reg86.u.b.intno = 0x13;
+	reg86.u.b.ah = 0x08;	/* Get drive parameters. */
+	reg86.u.b.dl = drive_id;
+	r= sys_int86(&reg86);
+	if (r != OK)
+		panic(ME, "BIOS call failed", r);
+
+	nr_drives = !(reg86.u.w.f & 0x0001) ? reg86.u.b.dl : drive;
+	if (drive_id >= 0x80 + nr_drives) continue;
+	wn->present= 1;
+
+	wn->heads = reg86.u.b.dh + 1;
+	wn->sectors = reg86.u.b.cl & 0x3F;
+	wn->cylinders = (reg86.u.b.ch | ((reg86.u.b.cl & 0xC0) << 2)) + 1;
+
+	capacity = (unsigned long) wn->cylinders * wn->heads * wn->sectors;
+
+	reg86.u.b.intno = 0x13;
+	reg86.u.b.ah = 0x41;	/* INT 13 Extensions - Installation check */
+	reg86.u.w.bx = 0x55AA;
+	reg86.u.b.dl = drive_id;
+
+	if (pc_at) {
+		r= sys_int86(&reg86);
+		if (r != OK)
+			panic(ME, "BIOS call failed", r);
+	}
+
+	if (!(reg86.u.w.f & 0x0001) && reg86.u.w.bx == 0xAA55
+				&& (reg86.u.w.cx & 0x0001)) {
+		/* INT 13 Extensions available. */
+		i13e_par.len = 0x001E;	/* Input size of parameter packet */
+		r= sys_vircopy(SELF, D, (vir_bytes)&i13e_par,
+			SYSTEM, D, bios_buf_vir, 
+			sizeof(i13e_par));
+		if (r != OK)
+			panic(ME, "sys_vircopy failed\n", r);
+		reg86.u.b.intno = 0x13;
+		reg86.u.b.ah = 0x48;	/* Ext. Get drive parameters. */
+		reg86.u.b.dl = drive_id;
+		reg86.u.w.si = bios_buf_phys % HCLICK_SIZE;
+		reg86.u.w.ds = bios_buf_phys / HCLICK_SIZE;
+
+		r= sys_int86(&reg86);
+		if (r != OK)
+			panic(ME, "BIOS call failed", r);
+
+		r= sys_vircopy(SYSTEM, D, bios_buf_vir,
+			 SELF, D, (vir_bytes)&i13e_par,
+			sizeof(i13e_par));
+		if (r != OK)
+			panic(ME, "sys_vircopy failed\n", r);
+
+		if (!(reg86.u.w.f & 0x0001)) {
+			wn->int13ext = 1;	/* Extensions can be used. */
+			capacity = i13e_par.capacity[0];
+			if (i13e_par.capacity[1] != 0) capacity = 0xFFFFFFFF;
+		}
+	}
+
+	if (wn->int13ext) {
+		printf("%s: %lu sectors\n", w_name(), capacity);
+	} else {
+		printf("%s: %d cylinders, %d heads, %d sectors per track\n",
+			w_name(), wn->cylinders, wn->heads, wn->sectors);
+	}
+	wn->part[0].dv_size = mul64u(capacity, SECTOR_SIZE);
+  }
+}
+
+/*============================================================================*
+ *				w_geometry				      *
+ *============================================================================*/
+PRIVATE void w_geometry(entry)
+struct partition *entry;
+{
+  entry->cylinders = w_wn->cylinders;
+  entry->heads = w_wn->heads;
+  entry->sectors = w_wn->sectors;
+}
+
+/*============================================================================*
+ *				w_other				      *
+ *============================================================================*/
+PRIVATE int w_other(dr, m)
+struct driver *dr;
+message *m;
+{
+        int r, timeout, prev;
+
+        if (m->m_type != DEV_IOCTL ) {
+                return EINVAL;
+        }
+
+	if (m->REQUEST == DIOCOPENCT) {
+                int count;
+                if (w_prepare(m->DEVICE) == NIL_DEV) return ENXIO;
+                count = w_wn->open_ct;
+                if ((r=sys_datacopy(SELF, (vir_bytes)&count,
+                        m->IO_ENDPT, (vir_bytes)m->ADDRESS, sizeof(count))) != OK)
+                        return r;
+                return OK;
+        }
+
+        return EINVAL;
+}
+
Index: /trunk/minix/drivers/cmos/.depend
===================================================================
--- /trunk/minix/drivers/cmos/.depend	(revision 9)
+++ /trunk/minix/drivers/cmos/.depend	(revision 9)
@@ -0,0 +1,90 @@
+
+cmos.o:	../drivers.h
+cmos.o:	/usr/include/ansi.h
+cmos.o:	/usr/include/errno.h
+cmos.o:	/usr/include/ibm/bios.h
+cmos.o:	/usr/include/ibm/cmos.h
+cmos.o:	/usr/include/ibm/interrupt.h
+cmos.o:	/usr/include/ibm/ports.h
+cmos.o:	/usr/include/limits.h
+cmos.o:	/usr/include/minix/bitmap.h
+cmos.o:	/usr/include/minix/callnr.h
+cmos.o:	/usr/include/minix/com.h
+cmos.o:	/usr/include/minix/config.h
+cmos.o:	/usr/include/minix/const.h
+cmos.o:	/usr/include/minix/devio.h
+cmos.o:	/usr/include/minix/dmap.h
+cmos.o:	/usr/include/minix/ioctl.h
+cmos.o:	/usr/include/minix/ipc.h
+cmos.o:	/usr/include/minix/sys_config.h
+cmos.o:	/usr/include/minix/syslib.h
+cmos.o:	/usr/include/minix/sysutil.h
+cmos.o:	/usr/include/minix/type.h
+cmos.o:	/usr/include/signal.h
+cmos.o:	/usr/include/stddef.h
+cmos.o:	/usr/include/stdlib.h
+cmos.o:	/usr/include/string.h
+cmos.o:	/usr/include/sys/dir.h
+cmos.o:	/usr/include/sys/ioc_cmos.h
+cmos.o:	/usr/include/sys/types.h
+cmos.o:	/usr/include/time.h
+cmos.o:	/usr/include/unistd.h
+cmos.o:	cmos.c
+
+../libdriver/driver.o:	../libdriver/../drivers.h
+../libdriver/driver.o:	../libdriver/driver.c
+../libdriver/driver.o:	../libdriver/driver.h
+../libdriver/driver.o:	/usr/include/ansi.h
+../libdriver/driver.o:	/usr/include/errno.h
+../libdriver/driver.o:	/usr/include/ibm/bios.h
+../libdriver/driver.o:	/usr/include/ibm/interrupt.h
+../libdriver/driver.o:	/usr/include/ibm/ports.h
+../libdriver/driver.o:	/usr/include/limits.h
+../libdriver/driver.o:	/usr/include/minix/bitmap.h
+../libdriver/driver.o:	/usr/include/minix/callnr.h
+../libdriver/driver.o:	/usr/include/minix/com.h
+../libdriver/driver.o:	/usr/include/minix/config.h
+../libdriver/driver.o:	/usr/include/minix/const.h
+../libdriver/driver.o:	/usr/include/minix/devio.h
+../libdriver/driver.o:	/usr/include/minix/dmap.h
+../libdriver/driver.o:	/usr/include/minix/ioctl.h
+../libdriver/driver.o:	/usr/include/minix/ipc.h
+../libdriver/driver.o:	/usr/include/minix/partition.h
+../libdriver/driver.o:	/usr/include/minix/sys_config.h
+../libdriver/driver.o:	/usr/include/minix/syslib.h
+../libdriver/driver.o:	/usr/include/minix/sysutil.h
+../libdriver/driver.o:	/usr/include/minix/type.h
+../libdriver/driver.o:	/usr/include/minix/u64.h
+../libdriver/driver.o:	/usr/include/signal.h
+../libdriver/driver.o:	/usr/include/stddef.h
+../libdriver/driver.o:	/usr/include/stdlib.h
+../libdriver/driver.o:	/usr/include/string.h
+../libdriver/driver.o:	/usr/include/sys/dir.h
+../libdriver/driver.o:	/usr/include/sys/ioc_disk.h
+../libdriver/driver.o:	/usr/include/sys/types.h
+../libdriver/driver.o:	/usr/include/unistd.h
+
+../libdriver/drvlib.o:	../libdriver/driver.h
+../libdriver/drvlib.o:	../libdriver/drvlib.c
+../libdriver/drvlib.o:	../libdriver/drvlib.h
+../libdriver/drvlib.o:	/usr/include/ansi.h
+../libdriver/drvlib.o:	/usr/include/errno.h
+../libdriver/drvlib.o:	/usr/include/ibm/partition.h
+../libdriver/drvlib.o:	/usr/include/limits.h
+../libdriver/drvlib.o:	/usr/include/minix/callnr.h
+../libdriver/drvlib.o:	/usr/include/minix/com.h
+../libdriver/drvlib.o:	/usr/include/minix/config.h
+../libdriver/drvlib.o:	/usr/include/minix/const.h
+../libdriver/drvlib.o:	/usr/include/minix/devio.h
+../libdriver/drvlib.o:	/usr/include/minix/ipc.h
+../libdriver/drvlib.o:	/usr/include/minix/partition.h
+../libdriver/drvlib.o:	/usr/include/minix/sys_config.h
+../libdriver/drvlib.o:	/usr/include/minix/syslib.h
+../libdriver/drvlib.o:	/usr/include/minix/sysutil.h
+../libdriver/drvlib.o:	/usr/include/minix/type.h
+../libdriver/drvlib.o:	/usr/include/minix/u64.h
+../libdriver/drvlib.o:	/usr/include/stddef.h
+../libdriver/drvlib.o:	/usr/include/string.h
+../libdriver/drvlib.o:	/usr/include/sys/dir.h
+../libdriver/drvlib.o:	/usr/include/sys/types.h
+../libdriver/drvlib.o:	/usr/include/unistd.h
Index: /trunk/minix/drivers/cmos/Makefile
===================================================================
--- /trunk/minix/drivers/cmos/Makefile	(revision 9)
+++ /trunk/minix/drivers/cmos/Makefile	(revision 9)
@@ -0,0 +1,48 @@
+# Makefile for the CMOS driver 
+DRIVER = cmos
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+MAKE = exec make
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsys -lsysutil
+
+OBJ = cmos.o 
+LIBDRIVER = $d/libdriver/driver.o
+
+
+# build local binary
+all build:	$(DRIVER) 
+$(DRIVER):	$(OBJ) $(LIBDRIVER) 
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBDRIVER) $(LIBS)
+	install -S 1024w $(DRIVER)
+
+$(LIBDRIVER): 
+	cd $d/libdriver && $(MAKE) 
+
+
+# install with other drivers
+install:	/sbin/$(DRIVER)
+/sbin/$(DRIVER):	$(DRIVER)
+	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f $(DRIVER) *.o *.bak 
+
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c ../libdriver/*.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/cmos/cmos.c
===================================================================
--- /trunk/minix/drivers/cmos/cmos.c	(revision 9)
+++ /trunk/minix/drivers/cmos/cmos.c	(revision 9)
@@ -0,0 +1,265 @@
+/* This file contains a device driver that can access the CMOS chip to 
+ * get or set the system time. It drives the special file:
+ *
+ *     /dev/cmos	- CMOS chip
+ *
+ * Changes:
+ *     Aug 04, 2005	Created. Read CMOS time.  (Jorrit N. Herder)
+ *
+ * Manufacturers usually use the ID value of the IBM model they emulate.
+ * However some manufacturers, notably HP and COMPAQ, have had different
+ * ideas in the past.
+ *
+ * Machine ID byte information source:
+ *	_The Programmer's PC Sourcebook_ by Thom Hogan,
+ *	published by Microsoft Press
+ */
+
+#include "../drivers.h"
+#include <sys/ioc_cmos.h>
+#include <time.h>
+#include <ibm/cmos.h>
+#include <ibm/bios.h>
+
+extern int errno;			/* error number for PM calls */
+
+FORWARD _PROTOTYPE( int gettime, (int who, int y2kflag, vir_bytes dst_time));
+FORWARD _PROTOTYPE( void reply, (int reply, int replyee, int proc, int s));
+
+FORWARD _PROTOTYPE( int read_register, (int register_address));
+FORWARD _PROTOTYPE( int get_cmostime, (struct tm *tmp, int y2kflag));
+FORWARD _PROTOTYPE( int dec_to_bcd, (int dec));
+FORWARD _PROTOTYPE( int bcd_to_dec, (int bcd));
+
+/*===========================================================================*
+ *				   main 				     *
+ *===========================================================================*/
+PUBLIC void main(void)
+{
+  message m;
+  int y2kflag;
+  int result;
+  int suspended = NONE;
+  int s;
+
+  while(TRUE) {
+
+      /* Get work. */
+      if (OK != (s=receive(ANY, &m)))
+          panic("CMOS", "attempt to receive work failed", s);
+
+      /* Handle request. */
+      switch(m.m_type) {
+
+      case DEV_OPEN:
+      case DEV_CLOSE:
+      case CANCEL:
+          reply(TASK_REPLY, m.m_source, m.IO_ENDPT, OK);
+          break;
+
+      case DEV_PING:
+	  notify(m.m_source);
+	  break;
+      case DEV_IOCTL:				
+
+	  /* Probably best to SUSPEND the caller, CMOS I/O has nasty timeouts. 
+	   * This way we don't block the rest of the system. First check if
+           * another process is already suspended. We cannot handle multiple
+           * requests at a time. 
+           */
+          if (suspended != NONE) {
+              reply(TASK_REPLY, m.m_source, m.IO_ENDPT, EBUSY);
+              break;
+          }
+          suspended = m.IO_ENDPT;
+          reply(TASK_REPLY, m.m_source, m.IO_ENDPT, SUSPEND);
+
+	  switch(m.REQUEST) {
+	  case CIOCGETTIME:			/* get CMOS time */ 
+          case CIOCGETTIMEY2K:
+              y2kflag = (m.REQUEST = CIOCGETTIME) ? 0 : 1;
+              result = gettime(m.IO_ENDPT, y2kflag, (vir_bytes) m.ADDRESS);
+              break;
+          case CIOCSETTIME:
+          case CIOCSETTIMEY2K:
+          default:				/* unsupported ioctl */
+              result = ENOSYS;
+          }
+
+          /* Request completed. Tell the caller to check our status. */
+	  notify(m.m_source);
+          break;
+
+      case DEV_STATUS:
+
+          /* The FS calls back to get our status. Revive the suspended 
+           * processes and return the status of reading the CMOS.
+           */
+	  if (suspended == NONE)
+              reply(DEV_NO_STATUS, m.m_source, NONE, OK);
+          else 
+              reply(DEV_REVIVE, m.m_source, suspended, result);
+          suspended = NONE;
+          break;
+
+      case SYN_ALARM:		/* shouldn't happen */
+      case SYS_SIG:		/* ignore system events */
+          continue;		
+
+      default:
+          reply(TASK_REPLY, m.m_source, m.IO_ENDPT, EINVAL);
+      }	
+  }
+}
+
+/*===========================================================================*
+ *				reply					     *
+ *===========================================================================*/
+PRIVATE void reply(int code, int replyee, int process, int status)
+{
+  message m;
+  int s;
+
+  m.m_type = code;		/* TASK_REPLY or REVIVE */
+  m.REP_STATUS = status;	/* result of device operation */
+  m.REP_ENDPT = process;	/* which user made the request */
+  if (OK != (s=send(replyee, &m)))
+      panic("CMOS", "sending reply failed", s);
+}
+
+/*===========================================================================*
+ *				gettime					     *
+ *===========================================================================*/
+PRIVATE int gettime(int who, int y2kflag, vir_bytes dst_time)
+{
+  unsigned char mach_id, cmos_state;
+  struct tm time1;
+  int i, s;
+
+  /* First obtain the machine ID to see if we can read the CMOS clock. Only
+   * for PS_386 and PC_AT this is possible. Otherwise, return an error.  
+   */
+  sys_vircopy(SELF, BIOS_SEG, (vir_bytes) MACHINE_ID_ADDR, 
+  	SELF, D, (vir_bytes) &mach_id, MACHINE_ID_SIZE);
+  if (mach_id != PS_386_MACHINE && mach_id != PC_AT_MACHINE) {
+	printf("IS: Machine ID unknown. ID byte = %02x.\n", mach_id);
+	return(EFAULT);
+  }
+
+  /* Now check the CMOS' state to see if we can read a proper time from it.
+   * If the state is crappy, return an error.
+   */
+  cmos_state = read_register(CMOS_STATUS);
+  if (cmos_state & (CS_LOST_POWER | CS_BAD_CHKSUM | CS_BAD_TIME)) {
+	printf( "IS: CMOS RAM error(s) found. State = 0x%02x\n", cmos_state );
+	if (cmos_state & CS_LOST_POWER)
+	    printf("IS: RTC lost power. Reset CMOS RAM with SETUP." );
+	if (cmos_state & CS_BAD_CHKSUM)
+	    printf("IS: CMOS RAM checksum is bad. Run SETUP." );
+	if (cmos_state & CS_BAD_TIME)
+	    printf("IS: Time invalid in CMOS RAM. Reset clock." );
+	return(EFAULT);
+  }
+
+  /* Everything seems to be OK. Read the CMOS real time clock and copy the
+   * result back to the caller.
+   */
+  if (get_cmostime(&time1, y2kflag) != 0)
+	return(EFAULT);
+  sys_datacopy(SELF, (vir_bytes) &time1, 
+  	who, dst_time, sizeof(struct tm));
+
+  return(OK);
+}
+
+PRIVATE int get_cmostime(struct tm *t, int y2kflag)
+{
+/* Update the structure pointed to by time with the current time as read
+ * from CMOS RAM of the RTC. If necessary, the time is converted into a
+ * binary format before being stored in the structure.
+ */
+  int osec, n;
+  unsigned long i;
+  clock_t t0,t1;
+
+  /* Start a timer to keep us from getting stuck on a dead clock. */
+  getuptime(&t0);
+  do {
+	osec = -1;
+	n = 0;
+	do {
+	        getuptime(&t1); 
+		if (t1-t0 > 5*HZ) {
+			printf("readclock: CMOS clock appears dead\n");
+			return(1);
+		}
+
+		/* Clock update in progress? */
+		if (read_register(RTC_REG_A) & RTC_A_UIP) continue;
+
+		t->tm_sec = read_register(RTC_SEC);
+		if (t->tm_sec != osec) {
+			/* Seconds changed.  First from -1, then because the
+			 * clock ticked, which is what we're waiting for to
+			 * get a precise reading.
+			 */
+			osec = t->tm_sec;
+			n++;
+		}
+	} while (n < 2);
+
+	/* Read the other registers. */
+	t->tm_min = read_register(RTC_MIN);
+	t->tm_hour = read_register(RTC_HOUR);
+	t->tm_mday = read_register(RTC_MDAY);
+	t->tm_mon = read_register(RTC_MONTH);
+	t->tm_year = read_register(RTC_YEAR);
+
+	/* Time stable? */
+  } while (read_register(RTC_SEC) != t->tm_sec
+	|| read_register(RTC_MIN) != t->tm_min
+	|| read_register(RTC_HOUR) != t->tm_hour
+	|| read_register(RTC_MDAY) != t->tm_mday
+	|| read_register(RTC_MONTH) != t->tm_mon
+	|| read_register(RTC_YEAR) != t->tm_year);
+
+  if ((read_register(RTC_REG_B) & RTC_B_DM_BCD) == 0) {
+	/* Convert BCD to binary (default RTC mode). */
+	t->tm_year = bcd_to_dec(t->tm_year);
+	t->tm_mon = bcd_to_dec(t->tm_mon);
+	t->tm_mday = bcd_to_dec(t->tm_mday);
+	t->tm_hour = bcd_to_dec(t->tm_hour);
+	t->tm_min = bcd_to_dec(t->tm_min);
+	t->tm_sec = bcd_to_dec(t->tm_sec);
+  }
+  t->tm_mon--;	/* Counts from 0. */
+
+  /* Correct the year, good until 2080. */
+  if (t->tm_year < 80) t->tm_year += 100;
+
+  if (y2kflag) {
+	/* Clock with Y2K bug, interpret 1980 as 2000, good until 2020. */
+	if (t->tm_year < 100) t->tm_year += 20;
+  }
+  return 0;
+}
+
+PRIVATE int read_register(int reg_addr)
+{
+/* Read a single CMOS register value. */
+  unsigned long r;
+  sys_outb(RTC_INDEX, reg_addr);
+  sys_inb(RTC_IO, &r);
+  return r;
+}
+
+PRIVATE int bcd_to_dec(int n)
+{
+  return ((n >> 4) & 0x0F) * 10 + (n & 0x0F);
+}
+
+PRIVATE int dec_to_bcd(int n)
+{
+  return ((n / 10) << 4) | (n % 10);
+}
+
Index: /trunk/minix/drivers/dp8390/.depend
===================================================================
--- /trunk/minix/drivers/dp8390/.depend	(revision 9)
+++ /trunk/minix/drivers/dp8390/.depend	(revision 9)
@@ -0,0 +1,169 @@
+
+3c503.o:	../drivers.h
+3c503.o:	/usr/include/ansi.h
+3c503.o:	/usr/include/errno.h
+3c503.o:	/usr/include/ibm/bios.h
+3c503.o:	/usr/include/ibm/interrupt.h
+3c503.o:	/usr/include/ibm/ports.h
+3c503.o:	/usr/include/limits.h
+3c503.o:	/usr/include/minix/bitmap.h
+3c503.o:	/usr/include/minix/callnr.h
+3c503.o:	/usr/include/minix/com.h
+3c503.o:	/usr/include/minix/config.h
+3c503.o:	/usr/include/minix/const.h
+3c503.o:	/usr/include/minix/devio.h
+3c503.o:	/usr/include/minix/dmap.h
+3c503.o:	/usr/include/minix/ipc.h
+3c503.o:	/usr/include/minix/sys_config.h
+3c503.o:	/usr/include/minix/syslib.h
+3c503.o:	/usr/include/minix/sysutil.h
+3c503.o:	/usr/include/minix/type.h
+3c503.o:	/usr/include/net/gen/eth_io.h
+3c503.o:	/usr/include/net/gen/ether.h
+3c503.o:	/usr/include/signal.h
+3c503.o:	/usr/include/stddef.h
+3c503.o:	/usr/include/stdlib.h
+3c503.o:	/usr/include/string.h
+3c503.o:	/usr/include/sys/dir.h
+3c503.o:	/usr/include/sys/types.h
+3c503.o:	/usr/include/unistd.h
+3c503.o:	3c503.c
+3c503.o:	3c503.h
+3c503.o:	dp8390.h
+3c503.o:	local.h
+
+dp8390.o:	../drivers.h
+dp8390.o:	/usr/include/ansi.h
+dp8390.o:	/usr/include/assert.h
+dp8390.o:	/usr/include/errno.h
+dp8390.o:	/usr/include/ibm/bios.h
+dp8390.o:	/usr/include/ibm/interrupt.h
+dp8390.o:	/usr/include/ibm/ports.h
+dp8390.o:	/usr/include/limits.h
+dp8390.o:	/usr/include/minix/bitmap.h
+dp8390.o:	/usr/include/minix/callnr.h
+dp8390.o:	/usr/include/minix/com.h
+dp8390.o:	/usr/include/minix/config.h
+dp8390.o:	/usr/include/minix/const.h
+dp8390.o:	/usr/include/minix/devio.h
+dp8390.o:	/usr/include/minix/dmap.h
+dp8390.o:	/usr/include/minix/ipc.h
+dp8390.o:	/usr/include/minix/sys_config.h
+dp8390.o:	/usr/include/minix/syslib.h
+dp8390.o:	/usr/include/minix/sysutil.h
+dp8390.o:	/usr/include/minix/type.h
+dp8390.o:	/usr/include/net/gen/eth_io.h
+dp8390.o:	/usr/include/net/gen/ether.h
+dp8390.o:	/usr/include/net/hton.h
+dp8390.o:	/usr/include/signal.h
+dp8390.o:	/usr/include/stddef.h
+dp8390.o:	/usr/include/stdlib.h
+dp8390.o:	/usr/include/string.h
+dp8390.o:	/usr/include/sys/dir.h
+dp8390.o:	/usr/include/sys/types.h
+dp8390.o:	/usr/include/unistd.h
+dp8390.o:	dp8390.c
+dp8390.o:	dp8390.h
+dp8390.o:	local.h
+
+ne2000.o:	../drivers.h
+ne2000.o:	/usr/include/ansi.h
+ne2000.o:	/usr/include/errno.h
+ne2000.o:	/usr/include/ibm/bios.h
+ne2000.o:	/usr/include/ibm/interrupt.h
+ne2000.o:	/usr/include/ibm/ports.h
+ne2000.o:	/usr/include/limits.h
+ne2000.o:	/usr/include/minix/bitmap.h
+ne2000.o:	/usr/include/minix/callnr.h
+ne2000.o:	/usr/include/minix/com.h
+ne2000.o:	/usr/include/minix/config.h
+ne2000.o:	/usr/include/minix/const.h
+ne2000.o:	/usr/include/minix/devio.h
+ne2000.o:	/usr/include/minix/dmap.h
+ne2000.o:	/usr/include/minix/ipc.h
+ne2000.o:	/usr/include/minix/sys_config.h
+ne2000.o:	/usr/include/minix/syslib.h
+ne2000.o:	/usr/include/minix/sysutil.h
+ne2000.o:	/usr/include/minix/type.h
+ne2000.o:	/usr/include/net/gen/eth_io.h
+ne2000.o:	/usr/include/net/gen/ether.h
+ne2000.o:	/usr/include/signal.h
+ne2000.o:	/usr/include/stddef.h
+ne2000.o:	/usr/include/stdlib.h
+ne2000.o:	/usr/include/string.h
+ne2000.o:	/usr/include/sys/dir.h
+ne2000.o:	/usr/include/sys/types.h
+ne2000.o:	/usr/include/unistd.h
+ne2000.o:	dp8390.h
+ne2000.o:	local.h
+ne2000.o:	ne2000.c
+ne2000.o:	ne2000.h
+
+rtl8029.o:	../drivers.h
+rtl8029.o:	/usr/include/ansi.h
+rtl8029.o:	/usr/include/assert.h
+rtl8029.o:	/usr/include/errno.h
+rtl8029.o:	/usr/include/ibm/bios.h
+rtl8029.o:	/usr/include/ibm/interrupt.h
+rtl8029.o:	/usr/include/ibm/pci.h
+rtl8029.o:	/usr/include/ibm/ports.h
+rtl8029.o:	/usr/include/limits.h
+rtl8029.o:	/usr/include/minix/bitmap.h
+rtl8029.o:	/usr/include/minix/callnr.h
+rtl8029.o:	/usr/include/minix/com.h
+rtl8029.o:	/usr/include/minix/config.h
+rtl8029.o:	/usr/include/minix/const.h
+rtl8029.o:	/usr/include/minix/devio.h
+rtl8029.o:	/usr/include/minix/dmap.h
+rtl8029.o:	/usr/include/minix/ipc.h
+rtl8029.o:	/usr/include/minix/sys_config.h
+rtl8029.o:	/usr/include/minix/syslib.h
+rtl8029.o:	/usr/include/minix/sysutil.h
+rtl8029.o:	/usr/include/minix/type.h
+rtl8029.o:	/usr/include/net/gen/eth_io.h
+rtl8029.o:	/usr/include/net/gen/ether.h
+rtl8029.o:	/usr/include/signal.h
+rtl8029.o:	/usr/include/stddef.h
+rtl8029.o:	/usr/include/stdlib.h
+rtl8029.o:	/usr/include/string.h
+rtl8029.o:	/usr/include/sys/dir.h
+rtl8029.o:	/usr/include/sys/types.h
+rtl8029.o:	/usr/include/unistd.h
+rtl8029.o:	dp8390.h
+rtl8029.o:	local.h
+rtl8029.o:	rtl8029.c
+rtl8029.o:	rtl8029.h
+
+wdeth.o:	../drivers.h
+wdeth.o:	/usr/include/ansi.h
+wdeth.o:	/usr/include/assert.h
+wdeth.o:	/usr/include/errno.h
+wdeth.o:	/usr/include/ibm/bios.h
+wdeth.o:	/usr/include/ibm/interrupt.h
+wdeth.o:	/usr/include/ibm/ports.h
+wdeth.o:	/usr/include/limits.h
+wdeth.o:	/usr/include/minix/bitmap.h
+wdeth.o:	/usr/include/minix/callnr.h
+wdeth.o:	/usr/include/minix/com.h
+wdeth.o:	/usr/include/minix/config.h
+wdeth.o:	/usr/include/minix/const.h
+wdeth.o:	/usr/include/minix/devio.h
+wdeth.o:	/usr/include/minix/dmap.h
+wdeth.o:	/usr/include/minix/ipc.h
+wdeth.o:	/usr/include/minix/sys_config.h
+wdeth.o:	/usr/include/minix/syslib.h
+wdeth.o:	/usr/include/minix/sysutil.h
+wdeth.o:	/usr/include/minix/type.h
+wdeth.o:	/usr/include/net/gen/eth_io.h
+wdeth.o:	/usr/include/net/gen/ether.h
+wdeth.o:	/usr/include/signal.h
+wdeth.o:	/usr/include/stddef.h
+wdeth.o:	/usr/include/stdlib.h
+wdeth.o:	/usr/include/string.h
+wdeth.o:	/usr/include/sys/dir.h
+wdeth.o:	/usr/include/sys/types.h
+wdeth.o:	/usr/include/unistd.h
+wdeth.o:	dp8390.h
+wdeth.o:	local.h
+wdeth.o:	wdeth.c
+wdeth.o:	wdeth.h
Index: /trunk/minix/drivers/dp8390/3c503.c
===================================================================
--- /trunk/minix/drivers/dp8390/3c503.c	(revision 9)
+++ /trunk/minix/drivers/dp8390/3c503.c	(revision 9)
@@ -0,0 +1,198 @@
+/*
+ *	3c503.c		A shared memory driver for Etherlink II board.
+ *
+ *	Created:	Dec. 20, 1996 by G. Falzoni <falzoni@marina.scn.de>
+ *
+ *	Inspired by the TNET package by M. Ostrowski, the driver for Linux
+ *	by D. Becker, the Crynwr 3c503 packet driver, and the Amoeba driver.
+ *
+ *	It works in shared memory mode and should be used with the
+ *	device driver for NS 8390 based cards of Minix.  Programmed
+ *	I/O could be used as well but would result in poor performance.
+ */
+
+#include "../drivers.h"
+
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+
+#include "local.h"
+#include "dp8390.h"
+#include "3c503.h"
+
+#if ENABLE_3C503
+
+#define MILLIS_TO_TICKS(m)  (((m)*HZ/1000)+1)
+
+_PROTOTYPE(static void el2_init, (dpeth_t *dep));
+_PROTOTYPE(static void el2_stop, (dpeth_t *dep));
+_PROTOTYPE( static void milli_delay, (unsigned long millis)		);
+
+/*===========================================================================*
+ *				el2_init				     *
+ *===========================================================================*/
+static void el2_init(dep)
+dpeth_t * dep;
+{
+  /* Initalize hardware and data structures. */
+  int ix, irq;
+  int sendq_nr;
+  int cntr;
+
+  /* Map the address PROM to lower I/O address range */
+  cntr = inb_el2(dep, EL2_CNTR);
+  outb_el2(dep, EL2_CNTR, cntr | ECNTR_SAPROM);
+
+  /* Read station address from PROM */
+  for (ix = EL2_EA0; ix <= EL2_EA5; ix += 1)
+	dep->de_address.ea_addr[ix] = inb_el2(dep, ix);
+
+  /* Map the 8390 back to lower I/O address range */
+  outb_el2(dep, EL2_CNTR, cntr);
+
+  /* Enable memory, but turn off interrupts until we are ready */
+  outb_el2(dep, EL2_CFGR, ECFGR_IRQOFF);
+
+  dep->de_data_port = dep->de_dp8390_port = dep->de_base_port;
+  dep->de_prog_IO = 0;		/* Programmed I/O not yet available */
+
+  /* Check width of data bus:
+   * 1. Write 0 to WTS bit.  The board will drive it to 1 if it is a
+   *    16-bit card.
+   * 2. Select page 2
+   * 3. See if it is a 16-bit card
+   * 4. Select page 0
+   */
+  outb_el2(dep, DP_CR, CR_PS_P0|CR_DM_ABORT|CR_STP);
+  outb_el2(dep, DP_DCR, 0);
+  outb_el2(dep, DP_CR, CR_PS_P2|CR_DM_ABORT|CR_STP);
+  dep->de_16bit = (inb_el2(dep, DP_DCR) & DCR_WTS) != 0;
+  outb_el2(dep, DP_CR, CR_PS_P0|CR_DM_ABORT|CR_STP);
+
+  /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
+  sendq_nr = (dep->de_ramsize - dep->de_offset_page) / 0x2000;
+  if (sendq_nr < 1)
+	sendq_nr = 1;
+  else if (sendq_nr > SENDQ_NR)
+	sendq_nr = SENDQ_NR;
+
+  dep->de_sendq_nr = sendq_nr;
+  for (ix = 0; ix < sendq_nr; ix++)
+	dep->de_sendq[ix].sq_sendpage = (ix * SENDQ_PAGES) + EL2_SM_START_PG;
+
+  dep->de_startpage = (ix * SENDQ_PAGES) + EL2_SM_START_PG;
+  dep->de_stoppage = EL2_SM_STOP_PG;
+
+  outb_el2(dep, EL2_STARTPG, dep->de_startpage);
+  outb_el2(dep, EL2_STOPPG, dep->de_stoppage);
+
+  /* Point the vector pointer registers somewhere ?harmless?. */
+  outb_el2(dep, EL2_VP2, 0xFF);	/* Point at the ROM restart location    */
+  outb_el2(dep, EL2_VP1, 0xFF);	/* 0xFFFF:0000  (from original sources) */
+  outb_el2(dep, EL2_VP0, 0x00);	/*           - What for protected mode? */
+
+  /* Set interrupt level for 3c503 */
+  irq = (dep->de_irq &= ~DEI_DEFAULT);	/* Strip the default flag. */
+  if (irq == 9) irq = 2;
+  if (irq < 2 || irq > 5) panic("", "bad 3c503 irq configuration", irq);
+  outb_el2(dep, EL2_IDCFG, (0x04 << irq));
+
+  outb_el2(dep, EL2_DRQCNT, 0x08);	/* Set burst size to 8 */
+  outb_el2(dep, EL2_DMAAH, EL2_SM_START_PG);	/* Put start of TX  */
+  outb_el2(dep, EL2_DMAAL, 0x00);	/* buffer in the GA DMA reg */
+
+  outb_el2(dep, EL2_CFGR, ECFGR_NORM);	/* Enable shared memory */
+
+  if (!debug) {
+	printf("%s: 3c503 at %X:%d:%lX\n",
+		dep->de_name, dep->de_base_port, dep->de_irq,
+		dep->de_linmem + dep->de_offset_page);
+  } else {
+	printf("%s: 3Com Etherlink II %sat I/O address 0x%X, "
+			"memory address 0x%lX, irq %d\n",
+		dep->de_name, dep->de_16bit ? "(16-bit) " : "",
+		dep->de_base_port,
+		dep->de_linmem + dep->de_offset_page,
+		dep->de_irq);
+  }
+}
+
+/*===========================================================================*
+ *				el2_stop				     *
+ *===========================================================================*/
+static void el2_stop(dep)
+dpeth_t * dep;
+{
+  /* Stops board by disabling interrupts. */
+
+#if DEBUG
+  printf("%s: stopping Etherlink\n", dep->de_name);
+#endif
+  outb_el2(dep, EL2_CFGR, ECFGR_IRQOFF);
+  return;
+}
+
+/*===========================================================================*
+ *				el2_probe				     *
+ *===========================================================================*/
+int el2_probe(dep)
+dpeth_t * dep;
+{
+  /* Probe for the presence of an EtherLink II card.  Initialize memory
+   * addressing if card detected.
+   */
+  int iobase, membase;
+  int thin;
+
+  /* Thin ethernet or AUI? */
+  thin = (dep->de_linmem & 1) ? ECNTR_AUI : ECNTR_THIN;
+
+  /* Location registers should have 1 bit set */
+  if (!(iobase = inb_el2(dep, EL2_IOBASE))) return 0;
+  if (!((membase = inb_el2(dep, EL2_MEMBASE)) & 0xF0)) return 0;
+  if ((iobase & (iobase - 1)) || (membase & (membase - 1))) return 0;
+
+  /* Resets board */
+  outb_el2(dep, EL2_CNTR, ECNTR_RESET | thin);
+  milli_delay(1);
+  outb_el2(dep, EL2_CNTR, thin);
+  milli_delay(5);
+
+  /* Map the address PROM to lower I/O address range */
+  outb_el2(dep, EL2_CNTR, ECNTR_SAPROM | thin);
+  if (inb_el2(dep, EL2_EA0) != 0x02 ||	/* Etherlink II Station address */
+      inb_el2(dep, EL2_EA1) != 0x60 ||	/* MUST be 02:60:8c:xx:xx:xx */
+      inb_el2(dep, EL2_EA2) != 0x8C)
+	return 0;		/* No Etherlink board at this address */
+
+  /* Map the 8390 back to lower I/O address range */
+  outb_el2(dep, EL2_CNTR, thin);
+
+  /* Setup shared memory addressing for 3c503 */
+  dep->de_linmem = ((membase & 0xC0) ? EL2_BASE_0D8000 : EL2_BASE_0C8000) +
+	((membase & 0xA0) ? (EL2_BASE_0CC000 - EL2_BASE_0C8000) : 0x0000);
+  dep->de_offset_page = (EL2_SM_START_PG * DP_PAGESIZE);
+  dep->de_ramsize = (EL2_SM_STOP_PG - EL2_SM_START_PG) * DP_PAGESIZE;
+
+  /* (Bad kludge, something Philip needs to look into. -- kjb) */
+  dep->de_linmem -= dep->de_offset_page;
+  dep->de_ramsize += dep->de_offset_page;
+
+  /* Board initialization and stop functions */
+  dep->de_initf = el2_init;
+  dep->de_stopf = el2_stop;
+  return 1;
+}
+
+static void milli_delay(unsigned long millis)
+{
+	tickdelay(MILLIS_TO_TICKS(millis));
+}
+
+#endif /* ENABLE_3C503 */
+
+/** 3c503.c **/
+
+/*
+ * $PchId: 3c503.c,v 1.3 2003/09/10 15:33:04 philip Exp $
+ */
Index: /trunk/minix/drivers/dp8390/3c503.h
===================================================================
--- /trunk/minix/drivers/dp8390/3c503.h	(revision 9)
+++ /trunk/minix/drivers/dp8390/3c503.h	(revision 9)
@@ -0,0 +1,64 @@
+/*
+ *	3c503.h		A shared memory driver for Etherlink II board.
+ *
+ *	Created:	Dec. 20, 1996 by G. Falzoni <falzoni@marina.scn.de>
+ */
+
+#define EL2_MEMTEST	0	/* Set to 1 for on board memory test */
+
+#define EL2_GA		0x0400	/* Offset of registers in Gate Array */
+
+/* EtherLink II card */
+
+#define EL2_STARTPG	(EL2_GA+0x00)	/* Start page matching DP_PSTARTPG */
+#define EL2_STOPPG	(EL2_GA+0x01)	/* Stop page matching DP_PSTOPPG   */
+#define EL2_DRQCNT	(EL2_GA+0x02)	/* DMA burst count                 */
+#define EL2_IOBASE	(EL2_GA+0x03)	/* I/O base jumpers (bit coded)    */
+#define EL2_MEMBASE	(EL2_GA+0x04)	/* Memory base jumpers (bit coded) */
+#define EL2_CFGR	(EL2_GA+0x05)	/* Configuration Register  for GA  */
+#define EL2_CNTR	(EL2_GA+0x06)	/* Control(write) and status(read) */
+#define EL2_STATUS	(EL2_GA+0x07)
+#define EL2_IDCFG	(EL2_GA+0x08)	/* Interrupt/DMA configuration reg */
+#define EL2_DMAAH	(EL2_GA+0x09)	/* DMA address register (High byte) */
+#define EL2_DMAAL	(EL2_GA+0x0A)	/* DMA address register (Low byte) */
+#define EL2_VP2		(EL2_GA+0x0B)	/* Vector pointer - set to         */
+#define EL2_VP1		(EL2_GA+0x0C)	/* reset address (0xFFFF:0)  */
+#define EL2_VP0		(EL2_GA+0x0D)	/* */
+#define EL2_FIFOH	(EL2_GA+0x0E)	/* FIFO for progr. I/O (High byte) */
+#define EL2_FIFOL	(EL2_GA+0x0F)	/* FIFO for progr. I/O (Low byte)  */
+
+#define EL2_EA0		0x00	/* Most significant byte of ethernet address */
+#define EL2_EA1		0x01
+#define EL2_EA2		0x02
+#define EL2_EA3		0x03
+#define EL2_EA4		0x04
+#define EL2_EA5		0x05	/* Least significant byte of ethernet address */
+
+/* Bits in EL2_CNTR register */
+#define ECNTR_RESET	0x01	/* Software Reset */
+#define ECNTR_THIN	0x02	/* Onboard transceiver enable */
+#define ECNTR_AUI	0x00	/* Onboard transceiver disable */
+#define ECNTR_SAPROM	0x04	/* Map the station address prom */
+
+/* Bits in EL2_CFGR register */
+#define ECFGR_NORM	0x49	/* Enable 8k shared memory, no DMA, TC int */
+#define ECFGR_IRQOFF	0xC9	/* As above, disable 8390 IRQ */
+
+/* Shared memory management parameters */
+#define EL2_SM_START_PG	0x20	/* First page of TX buffer */
+#define EL2_SM_STOP_PG	0x40	/* Last page +1 of RX ring */
+
+/* Physical addresses where an Etherlink board can be configured */
+#define EL2_BASE_0C8000	0x0C8000
+#define EL2_BASE_0CC000	0x0CC000
+#define EL2_BASE_0D8000	0x0D8000
+#define EL2_BASE_0DC000	0x0DC000
+
+#define inb_el2(dep,reg)	(inb((dep)->de_base_port+(reg)))
+#define outb_el2(dep,reg,data)	(outb((dep)->de_base_port+(reg),(data)))
+
+/** 3c503.h **/
+
+/*
+ * $PchId: 3c503.h,v 1.3 2003/09/10 15:34:29 philip Exp $
+ */
Index: /trunk/minix/drivers/dp8390/Makefile
===================================================================
--- /trunk/minix/drivers/dp8390/Makefile	(revision 9)
+++ /trunk/minix/drivers/dp8390/Makefile	(revision 9)
@@ -0,0 +1,40 @@
+# Makefile for dp8390 driver
+DRIVER = dp8390
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i 
+LIBS = -lsys -lsysutil -ltimers
+
+OBJ = 3c503.o dp8390.o ne2000.o rtl8029.o wdeth.o
+
+# build local binary
+all build:	$(DRIVER)
+$(DRIVER):	$(OBJ) 
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+	install -S 4096 $(DRIVER)
+
+# install with other drivers
+install:	/usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER):	$(DRIVER)
+	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f *.o *.bak $(DRIVER)
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/dp8390/dp8390.c
===================================================================
--- /trunk/minix/drivers/dp8390/dp8390.c	(revision 9)
+++ /trunk/minix/drivers/dp8390/dp8390.c	(revision 9)
@@ -0,0 +1,1982 @@
+/*
+ * dp8390.c
+ *
+ * This file contains a ethernet device driver for NS dp8390 based ethernet
+ * cards.
+ *
+ * The valid messages and their parameters are:
+ *
+ *   m_type	  DL_PORT    DL_PROC   DL_COUNT   DL_MODE   DL_ADDR
+ * |------------+----------+---------+----------+---------+---------|
+ * | HARDINT	|          |         |          |         |         |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_WRITE	| port nr  | proc nr | count    | mode    | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_WRITEV	| port nr  | proc nr | count    | mode    | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_READ	| port nr  | proc nr | count    |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_READV	| port nr  | proc nr | count    |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_INIT	| port nr  | proc nr | mode     |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_GETSTAT	| port nr  | proc nr |          |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_STOP	| port_nr  |         |          |         |	    |
+ * |------------|----------|---------|----------|---------|---------|
+ *
+ * The messages sent are:
+ *
+ *   m-type	   DL_PORT    DL_PROC   DL_COUNT   DL_STAT   DL_CLCK
+ * |-------------+----------+---------+----------+---------+---------|
+ * |DL_TASK_REPLY| port nr  | proc nr | rd-count | err|stat| clock   |
+ * |-------------+----------+---------+----------+---------+---------|
+ *
+ *   m_type	   m3_i1     m3_i2       m3_ca1
+ * |-------------+---------+-----------+---------------|
+ * |DL_INIT_REPLY| port nr | last port | ethernet addr |
+ * |-------------+---------+-----------+---------------|
+ *
+ * Created:	before Dec 28, 1992 by Philip Homburg <philip@f-mnx.phicoh.com>
+ *
+ * Modified Mar 10 1994 by Philip Homburg
+ *	Become a generic dp8390 driver.
+ *
+ * Modified Dec 20 1996 by G. Falzoni <falzoni@marina.scn.de>
+ *	Added support for 3c503 boards.
+ */
+
+#include "../drivers.h"
+
+#include <stdlib.h>
+#include <minix/com.h>
+#include <net/hton.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include "assert.h"
+
+#include "local.h"
+#include "dp8390.h"
+
+#define DE_PORT_NR	3
+
+static dpeth_t de_table[DE_PORT_NR];
+static u16_t eth_ign_proto;
+static char *progname;
+
+/* Configuration */
+typedef struct dp_conf
+{
+	port_t dpc_port;
+	int dpc_irq;
+	phys_bytes dpc_mem;
+	char *dpc_envvar;
+} dp_conf_t;
+
+dp_conf_t dp_conf[]=	/* Card addresses */
+{
+	/* I/O port, IRQ,  Buffer address,  Env. var. */
+	{  0x280,     3,    0xD0000,        "DPETH0"	},
+	{  0x300,     5,    0xC8000,        "DPETH1"	},
+	{  0x380,    10,    0xD8000,        "DPETH2"	},
+};
+
+/* Test if dp_conf has exactly DE_PORT_NR entries.  If not then you will see
+ * the error: "array size is negative".
+ */
+extern int ___dummy[DE_PORT_NR == sizeof(dp_conf)/sizeof(dp_conf[0]) ? 1 : -1];
+
+/* Card inits configured out? */
+#if !ENABLE_WDETH
+#define wdeth_probe(dep)	(0)
+#endif
+#if !ENABLE_NE2000
+#define ne_probe(dep)		(0)
+#endif
+#if !ENABLE_3C503
+#define el2_probe(dep)		(0)
+#endif
+
+/* Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA
+ * on writes to the CR register. Additional CR_STAs do not appear to hurt
+ * genuine dp8390s
+ */
+#define CR_EXTRA	CR_STA
+
+#if ENABLE_PCI
+_PROTOTYPE( static void pci_conf, (void)				);
+#endif
+_PROTOTYPE( static void do_vwrite, (message *mp, int from_int,
+							int vectored)	);
+_PROTOTYPE( static void do_vread, (message *mp, int vectored)		);
+_PROTOTYPE( static void do_init, (message *mp)				);
+_PROTOTYPE( static void do_int, (dpeth_t *dep)				);
+_PROTOTYPE( static void do_getstat, (message *mp)			);
+_PROTOTYPE( static void do_getname, (message *mp)			);
+_PROTOTYPE( static void do_stop, (message *mp)				);
+_PROTOTYPE( static void dp_init, (dpeth_t *dep)				);
+_PROTOTYPE( static void dp_confaddr, (dpeth_t *dep)			);
+_PROTOTYPE( static void dp_reinit, (dpeth_t *dep)			);
+_PROTOTYPE( static void dp_reset, (dpeth_t *dep)			);
+_PROTOTYPE( static void dp_check_ints, (dpeth_t *dep)			);
+_PROTOTYPE( static void dp_recv, (dpeth_t *dep)				);
+_PROTOTYPE( static void dp_send, (dpeth_t *dep)				);
+_PROTOTYPE( static void dp8390_stop, (void)				);
+_PROTOTYPE( static void dp_getblock, (dpeth_t *dep, int page,
+				size_t offset, size_t size, void *dst)	);
+_PROTOTYPE( static void dp_pio8_getblock, (dpeth_t *dep, int page,
+				size_t offset, size_t size, void *dst)	);
+_PROTOTYPE( static void dp_pio16_getblock, (dpeth_t *dep, int page,
+				size_t offset, size_t size, void *dst)	);
+_PROTOTYPE( static int dp_pkt2user, (dpeth_t *dep, int page,
+							int length)	);
+_PROTOTYPE( static void dp_user2nic, (dpeth_t *dep, iovec_dat_t *iovp, 
+		vir_bytes offset, int nic_addr, vir_bytes count)	);
+_PROTOTYPE( static void dp_pio8_user2nic, (dpeth_t *dep,
+				iovec_dat_t *iovp, vir_bytes offset,
+				int nic_addr, vir_bytes count)		);
+_PROTOTYPE( static void dp_pio16_user2nic, (dpeth_t *dep,
+				iovec_dat_t *iovp, vir_bytes offset,
+				int nic_addr, vir_bytes count)		);
+_PROTOTYPE( static void dp_nic2user, (dpeth_t *dep, int nic_addr, 
+		iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)	);
+_PROTOTYPE( static void dp_pio8_nic2user, (dpeth_t *dep, int nic_addr, 
+		iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)	);
+_PROTOTYPE( static void dp_pio16_nic2user, (dpeth_t *dep, int nic_addr, 
+		iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)	);
+_PROTOTYPE( static void dp_next_iovec, (iovec_dat_t *iovp)		);
+_PROTOTYPE( static void conf_hw, (dpeth_t *dep)				);
+_PROTOTYPE( static void update_conf, (dpeth_t *dep, dp_conf_t *dcp)	);
+_PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp)		);
+_PROTOTYPE( static void reply, (dpeth_t *dep, int err, int may_block)	);
+_PROTOTYPE( static void mess_reply, (message *req, message *reply)	);
+_PROTOTYPE( static void get_userdata, (int user_proc,
+		vir_bytes user_addr, vir_bytes count, void *loc_addr)	);
+_PROTOTYPE( static void put_userdata, (int user_proc,
+		vir_bytes user_addr, vir_bytes count, void *loc_addr)	);
+_PROTOTYPE( static void insb, (port_t port, void *buf, size_t size)				);
+_PROTOTYPE( static void insw, (port_t port, void *buf, size_t size)				);
+_PROTOTYPE( static void do_vir_insb, (port_t port, int proc,
+					vir_bytes buf, size_t size)	);
+_PROTOTYPE( static void do_vir_insw, (port_t port, int proc,
+					vir_bytes buf, size_t size)	);
+_PROTOTYPE( static void do_vir_outsb, (port_t port, int proc,
+					vir_bytes buf, size_t size)	);
+_PROTOTYPE( static void do_vir_outsw, (port_t port, int proc,
+					vir_bytes buf, size_t size)	);
+
+/*===========================================================================*
+ *				dpeth_task				     *
+ *===========================================================================*/
+int main(int argc, char *argv[])
+{
+	message m;
+	int i, irq, r, tasknr;
+	dpeth_t *dep;
+	long v;
+
+	if (argc < 1)
+	{
+		panic("DP8390",
+			"A head which at this time has no name", NO_NUM);
+	}
+	(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
+
+	env_setargs(argc, argv);
+
+	for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
+	{
+		strcpy(dep->de_name, "dp8390#0");
+		dep->de_name[7] += i;
+	}
+
+	v= 0;
+	(void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
+	eth_ign_proto= htons((u16_t) v);
+
+	/* Try to notify inet that we are present (again) */
+	r = _pm_findproc("inet", &tasknr);
+	if (r == OK)
+		notify(tasknr);
+
+	while (TRUE)
+	{
+		if ((r= receive(ANY, &m)) != OK)
+			panic("", "dp8390: receive failed", r);
+
+		switch (m.m_type)
+		{
+		case DEV_PING:  notify(m.m_source);		continue;
+		case DL_WRITE:	do_vwrite(&m, FALSE, FALSE);	break;
+		case DL_WRITEV:	do_vwrite(&m, FALSE, TRUE);	break;
+		case DL_READ:	do_vread(&m, FALSE);		break;
+		case DL_READV:	do_vread(&m, TRUE);		break;
+		case DL_INIT:	do_init(&m);			break;
+		case DL_GETSTAT: do_getstat(&m);		break;
+		case DL_GETNAME: do_getname(&m); 		break;
+		case DL_STOP:	do_stop(&m);			break;
+		case HARD_INT:
+			for (i= 0, dep= &de_table[0]; i<DE_PORT_NR; i++, dep++)
+			{
+				if (dep->de_mode != DEM_ENABLED)
+					continue;
+				assert(dep->de_flags & DEF_ENABLED);
+				irq= dep->de_irq;
+				assert(irq >= 0 && irq < NR_IRQ_VECTORS);
+				if (dep->de_int_pending || 1)
+				{
+					dep->de_int_pending= 0;
+					dp_check_ints(dep);
+					do_int(dep);
+					r= sys_irqenable(&dep->de_hook);
+					if (r != OK)
+					{
+						panic("DP8390", 
+						"unable enable interrupts", r);
+					}
+				}
+			}
+			break;
+		case SYS_SIG:	{
+			sigset_t sigset = m.NOTIFY_ARG;
+			if (sigismember(&sigset, SIGKSTOP)) dp8390_stop();
+			break;
+		}
+		case SYN_ALARM:
+			printf("dp8390: strange, got SYN_ALARM\n");
+			break;
+		case PROC_EVENT:
+			break;
+		default:
+			panic("", "dp8390: illegal message", m.m_type);
+		}
+	}
+}
+
+#if 0
+/*===========================================================================*
+ *				dp8390_dump				     *
+ *===========================================================================*/
+void dp8390_dump()
+{
+	dpeth_t *dep;
+	int i, isr;
+
+	printf("\n");
+	for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++)
+	{
+#if XXX
+		if (dep->de_mode == DEM_DISABLED)
+			printf("dp8390 port %d is disabled\n", i);
+		else if (dep->de_mode == DEM_SINK)
+			printf("dp8390 port %d is in sink mode\n", i);
+#endif
+
+		if (dep->de_mode != DEM_ENABLED)
+			continue;
+
+		printf("dp8390 statistics of port %d:\n", i);
+
+		printf("recvErr    :%8ld\t", dep->de_stat.ets_recvErr);
+		printf("sendErr    :%8ld\t", dep->de_stat.ets_sendErr);
+		printf("OVW        :%8ld\n", dep->de_stat.ets_OVW);
+
+		printf("CRCerr     :%8ld\t", dep->de_stat.ets_CRCerr);
+		printf("frameAll   :%8ld\t", dep->de_stat.ets_frameAll);
+		printf("missedP    :%8ld\n", dep->de_stat.ets_missedP);
+
+		printf("packetR    :%8ld\t", dep->de_stat.ets_packetR);
+		printf("packetT    :%8ld\t", dep->de_stat.ets_packetT);
+		printf("transDef   :%8ld\n", dep->de_stat.ets_transDef);
+
+		printf("collision  :%8ld\t", dep->de_stat.ets_collision);
+		printf("transAb    :%8ld\t", dep->de_stat.ets_transAb);
+		printf("carrSense  :%8ld\n", dep->de_stat.ets_carrSense);
+
+		printf("fifoUnder  :%8ld\t", dep->de_stat.ets_fifoUnder);
+		printf("fifoOver   :%8ld\t", dep->de_stat.ets_fifoOver);
+		printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat);
+
+		printf("OWC        :%8ld\t", dep->de_stat.ets_OWC);
+
+		isr= inb_reg0(dep, DP_ISR);
+		printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,
+					inb_reg0(dep, DP_ISR), dep->de_flags);
+	}
+}
+#endif
+
+/*===========================================================================*
+ *				dp8390_stop				     *
+ *===========================================================================*/
+static void dp8390_stop()
+{
+	message mess;
+	int i;
+
+	for (i= 0; i<DE_PORT_NR; i++)
+	{
+		if (de_table[i].de_mode != DEM_ENABLED)
+			continue;
+		mess.m_type= DL_STOP;
+		mess.DL_PORT= i;
+		do_stop(&mess);
+	}
+}
+
+#if ENABLE_PCI
+/*===========================================================================*
+ *				pci_conf				     *
+ *===========================================================================*/
+static void pci_conf()
+{
+	int i, h;
+	char *envvar;
+	struct dpeth *dep;
+	static char envfmt[] = "*:d.d.d";
+	long v;
+	static int first_time= 1;
+
+	if (!first_time)
+		return;
+	first_time= 0;
+
+	for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
+	{
+		envvar= dp_conf[i].dpc_envvar;
+		if (!(dep->de_pci= env_prefix(envvar, "pci")))
+			continue;	/* no PCI config */
+		v= 0;
+		(void) env_parse(envvar, envfmt, 1, &v, 0, 255);
+		dep->de_pcibus= v;
+		v= 0;
+		(void) env_parse(envvar, envfmt, 2, &v, 0, 255);
+		dep->de_pcidev= v;
+		v= 0;
+		(void) env_parse(envvar, envfmt, 3, &v, 0, 255);
+		dep->de_pcifunc= v;
+	}
+
+	for (h= 1; h >= 0; h--) {
+		for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
+		{
+			if (!dep->de_pci)
+				continue;
+			if (((dep->de_pcibus | dep->de_pcidev |
+				dep->de_pcifunc) != 0) != h)
+			{
+				continue;
+			}
+			if (!rtl_probe(dep))
+				dep->de_pci= -1;
+		}
+	}
+}
+#endif /* ENABLE_PCI */
+
+/*===========================================================================*
+ *				do_vwrite				     *
+ *===========================================================================*/
+static void do_vwrite(mp, from_int, vectored)
+message *mp;
+int from_int;
+int vectored;
+{
+	int port, count, size;
+	int sendq_head;
+	dpeth_t *dep;
+
+	port = mp->DL_PORT;
+	count = mp->DL_COUNT;
+	if (port < 0 || port >= DE_PORT_NR)
+		panic("", "dp8390: illegal port", port);
+	dep= &de_table[port];
+	dep->de_client= mp->DL_PROC;
+
+	if (dep->de_mode == DEM_SINK)
+	{
+		assert(!from_int);
+		dep->de_flags |= DEF_PACK_SEND;
+		reply(dep, OK, FALSE);
+		return;
+	}
+	assert(dep->de_mode == DEM_ENABLED);
+	assert(dep->de_flags & DEF_ENABLED);
+	if (dep->de_flags & DEF_SEND_AVAIL)
+		panic("", "dp8390: send already in progress", NO_NUM);
+
+	sendq_head= dep->de_sendq_head;
+	if (dep->de_sendq[sendq_head].sq_filled)
+	{
+		if (from_int)
+			panic("", "dp8390: should not be sending\n", NO_NUM);
+		dep->de_sendmsg= *mp;
+		dep->de_flags |= DEF_SEND_AVAIL;
+		reply(dep, OK, FALSE);
+		return;
+	}
+	assert(!(dep->de_flags & DEF_PACK_SEND));
+
+	if (vectored)
+	{
+		get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+			(count > IOVEC_NR ? IOVEC_NR : count) *
+			sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
+		dep->de_write_iovec.iod_iovec_s = count;
+		dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
+		dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
+
+		dep->de_tmp_iovec = dep->de_write_iovec;
+		size = calc_iovec_size(&dep->de_tmp_iovec);
+	}
+	else
+	{  
+		dep->de_write_iovec.iod_iovec[0].iov_addr =
+			(vir_bytes) mp->DL_ADDR;
+		dep->de_write_iovec.iod_iovec[0].iov_size =
+			mp->DL_COUNT;
+		dep->de_write_iovec.iod_iovec_s = 1;
+		dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
+		dep->de_write_iovec.iod_iovec_addr = 0;
+		size= mp->DL_COUNT;
+	}
+	if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
+	{
+		panic("", "dp8390: invalid packet size", size);
+	}
+	(dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
+		dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
+		size);
+	dep->de_sendq[sendq_head].sq_filled= TRUE;
+	if (dep->de_sendq_tail == sendq_head)
+	{
+		outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
+		outb_reg0(dep, DP_TBCR1, size >> 8);
+		outb_reg0(dep, DP_TBCR0, size & 0xff);
+		outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);/* there it goes.. */
+	}
+	else
+		dep->de_sendq[sendq_head].sq_size= size;
+	
+	if (++sendq_head == dep->de_sendq_nr)
+		sendq_head= 0;
+	assert(sendq_head < SENDQ_NR);
+	dep->de_sendq_head= sendq_head;
+
+	dep->de_flags |= DEF_PACK_SEND;
+
+	/* If the interrupt handler called, don't send a reply. The reply
+	 * will be sent after all interrupts are handled. 
+	 */
+	if (from_int)
+		return;
+	reply(dep, OK, FALSE);
+
+	assert(dep->de_mode == DEM_ENABLED);
+	assert(dep->de_flags & DEF_ENABLED);
+}
+
+/*===========================================================================*
+ *				do_vread				     *
+ *===========================================================================*/
+static void do_vread(mp, vectored)
+message *mp;
+int vectored;
+{
+	int port, count;
+	int size;
+	dpeth_t *dep;
+
+	port = mp->DL_PORT;
+	count = mp->DL_COUNT;
+	if (port < 0 || port >= DE_PORT_NR)
+		panic("", "dp8390: illegal port", port);
+	dep= &de_table[port];
+	dep->de_client= mp->DL_PROC;
+	if (dep->de_mode == DEM_SINK)
+	{
+		reply(dep, OK, FALSE);
+		return;
+	}
+	assert(dep->de_mode == DEM_ENABLED);
+	assert(dep->de_flags & DEF_ENABLED);
+
+	if(dep->de_flags & DEF_READING)
+		panic("", "dp8390: read already in progress", NO_NUM);
+
+	if (vectored)
+	{
+		get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+			(count > IOVEC_NR ? IOVEC_NR : count) *
+			sizeof(iovec_t), dep->de_read_iovec.iod_iovec);
+		dep->de_read_iovec.iod_iovec_s = count;
+		dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
+		dep->de_read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
+
+		dep->de_tmp_iovec = dep->de_read_iovec;
+		size= calc_iovec_size(&dep->de_tmp_iovec);
+	}
+	else
+	{
+		dep->de_read_iovec.iod_iovec[0].iov_addr =
+			(vir_bytes) mp->DL_ADDR;
+		dep->de_read_iovec.iod_iovec[0].iov_size =
+			mp->DL_COUNT;
+		dep->de_read_iovec.iod_iovec_s = 1;
+		dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
+		dep->de_read_iovec.iod_iovec_addr = 0;
+		size= count;
+	}
+	if (size < ETH_MAX_PACK_SIZE_TAGGED)
+		panic("", "dp8390: wrong packet size", size);
+	dep->de_flags |= DEF_READING;
+
+	dp_recv(dep);
+
+	if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==
+		(DEF_READING|DEF_STOPPED))
+	{
+		/* The chip is stopped, and all arrived packets are 
+		 * delivered.
+		 */
+		dp_reset(dep);
+	}
+	reply(dep, OK, FALSE);
+}
+
+/*===========================================================================*
+ *				do_init					     *
+ *===========================================================================*/
+static void do_init(mp)
+message *mp;
+{
+	int port;
+	dpeth_t *dep;
+	message reply_mess;
+
+#if ENABLE_PCI
+	pci_conf(); /* Configure PCI devices. */
+#endif
+
+	port = mp->DL_PORT;
+	if (port < 0 || port >= DE_PORT_NR)
+	{
+		reply_mess.m_type= DL_INIT_REPLY;
+		reply_mess.m3_i1= ENXIO;
+		mess_reply(mp, &reply_mess);
+		return;
+	}
+	dep= &de_table[port];
+	if (dep->de_mode == DEM_DISABLED)
+	{
+		/* This is the default, try to (re)locate the device. */
+		conf_hw(dep);
+		if (dep->de_mode == DEM_DISABLED)
+		{
+			/* Probe failed, or the device is configured off. */
+			reply_mess.m_type= DL_INIT_REPLY;
+			reply_mess.m3_i1= ENXIO;
+			mess_reply(mp, &reply_mess);
+			return;
+		}
+		if (dep->de_mode == DEM_ENABLED)
+			dp_init(dep);
+	}
+
+	if (dep->de_mode == DEM_SINK)
+	{
+		strncpy((char *) dep->de_address.ea_addr, "ZDP", 6);
+		dep->de_address.ea_addr[5] = port;
+		dp_confaddr(dep);
+		reply_mess.m_type = DL_INIT_REPLY;
+		reply_mess.m3_i1 = mp->DL_PORT;
+		reply_mess.m3_i2 = DE_PORT_NR;
+		*(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
+		mess_reply(mp, &reply_mess);
+		return;
+	}
+	assert(dep->de_mode == DEM_ENABLED);
+	assert(dep->de_flags & DEF_ENABLED);
+
+	dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
+
+	if (mp->DL_MODE & DL_PROMISC_REQ)
+		dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
+	if (mp->DL_MODE & DL_MULTI_REQ)
+		dep->de_flags |= DEF_MULTI;
+	if (mp->DL_MODE & DL_BROAD_REQ)
+		dep->de_flags |= DEF_BROAD;
+
+	dep->de_client = mp->m_source;
+	dp_reinit(dep);
+
+	reply_mess.m_type = DL_INIT_REPLY;
+	reply_mess.m3_i1 = mp->DL_PORT;
+	reply_mess.m3_i2 = DE_PORT_NR;
+	*(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
+
+	mess_reply(mp, &reply_mess);
+}
+
+/*===========================================================================*
+ *				do_int					     *
+ *===========================================================================*/
+static void do_int(dep)
+dpeth_t *dep;
+{
+	if (dep->de_flags & (DEF_PACK_SEND | DEF_PACK_RECV))
+		reply(dep, OK, TRUE);
+}
+
+/*===========================================================================*
+ *				do_getstat				     *
+ *===========================================================================*/
+static void do_getstat(mp)
+message *mp;
+{
+	int port;
+	dpeth_t *dep;
+
+	port = mp->DL_PORT;
+	if (port < 0 || port >= DE_PORT_NR)
+		panic("", "dp8390: illegal port", port);
+	dep= &de_table[port];
+	dep->de_client= mp->DL_PROC;
+	if (dep->de_mode == DEM_SINK)
+	{
+		put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+			(vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
+		reply(dep, OK, FALSE);
+		return;
+	}
+	assert(dep->de_mode == DEM_ENABLED);
+	assert(dep->de_flags & DEF_ENABLED);
+
+	dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
+	dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
+	dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
+
+	put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+		(vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
+	reply(dep, OK, FALSE);
+}
+
+/*===========================================================================*
+ *				do_getname				     *
+ *===========================================================================*/
+static void do_getname(mp)
+message *mp;
+{
+	int r;
+
+	strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
+	mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
+	mp->m_type= DL_NAME_REPLY;
+	r= send(mp->m_source, mp);
+	if (r != OK)
+		panic("dp8390", "do_getname: send failed: %d\n", r);
+}
+
+/*===========================================================================*
+ *				do_stop					     *
+ *===========================================================================*/
+static void do_stop(mp)
+message *mp;
+{
+	int port;
+	dpeth_t *dep;
+
+	port = mp->DL_PORT;
+
+	if (port < 0 || port >= DE_PORT_NR)
+		panic("", "dp8390: illegal port", port);
+	dep= &de_table[port];
+	if (dep->de_mode == DEM_SINK)
+		return;
+	assert(dep->de_mode == DEM_ENABLED);
+
+	if (!(dep->de_flags & DEF_ENABLED))
+		return;
+
+	outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
+	(dep->de_stopf)(dep);
+
+	dep->de_flags= DEF_EMPTY;
+}
+
+/*===========================================================================*
+ *				dp_init					     *
+ *===========================================================================*/
+static void dp_init(dep)
+dpeth_t *dep;
+{
+	int dp_rcr_reg;
+	int i, r;
+
+	/* General initialization */
+	dep->de_flags = DEF_EMPTY;
+	(*dep->de_initf)(dep);
+
+	dp_confaddr(dep);
+
+	if (debug)
+	{
+		printf("%s: Ethernet address ", dep->de_name);
+		for (i= 0; i < 6; i++)
+			printf("%x%c", dep->de_address.ea_addr[i],
+							i < 5 ? ':' : '\n');
+	}
+
+	/* Initialization of the dp8390 following the mandatory procedure
+	 * in reference manual ("DP8390D/NS32490D NIC Network Interface
+	 * Controller", National Semiconductor, July 1995, Page 29).
+	 */
+	/* Step 1: */
+	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
+	/* Step 2: */
+	if (dep->de_16bit)
+		outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
+	else
+		outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
+	/* Step 3: */
+	outb_reg0(dep, DP_RBCR0, 0);
+	outb_reg0(dep, DP_RBCR1, 0);
+	/* Step 4: */
+	dp_rcr_reg = 0;
+	if (dep->de_flags & DEF_PROMISC)
+		dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
+	if (dep->de_flags & DEF_BROAD)
+		dp_rcr_reg |= RCR_AB;
+	if (dep->de_flags & DEF_MULTI)
+		dp_rcr_reg |= RCR_AM;
+	outb_reg0(dep, DP_RCR, dp_rcr_reg);
+	/* Step 5: */
+	outb_reg0(dep, DP_TCR, TCR_INTERNAL);
+	/* Step 6: */
+	outb_reg0(dep, DP_BNRY, dep->de_startpage);
+	outb_reg0(dep, DP_PSTART, dep->de_startpage);
+	outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
+	/* Step 7: */
+	outb_reg0(dep, DP_ISR, 0xFF);
+	/* Step 8: */
+	outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
+		IMR_OVWE | IMR_CNTE);
+	/* Step 9: */
+	outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
+
+	outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
+	outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
+	outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
+	outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
+	outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
+	outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
+
+	outb_reg1(dep, DP_MAR0, 0xff);
+	outb_reg1(dep, DP_MAR1, 0xff);
+	outb_reg1(dep, DP_MAR2, 0xff);
+	outb_reg1(dep, DP_MAR3, 0xff);
+	outb_reg1(dep, DP_MAR4, 0xff);
+	outb_reg1(dep, DP_MAR5, 0xff);
+	outb_reg1(dep, DP_MAR6, 0xff);
+	outb_reg1(dep, DP_MAR7, 0xff);
+
+	outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
+	/* Step 10: */
+	outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
+	/* Step 11: */
+	outb_reg0(dep, DP_TCR, TCR_NORMAL);
+
+	inb_reg0(dep, DP_CNTR0);		/* reset counters by reading */
+	inb_reg0(dep, DP_CNTR1);
+	inb_reg0(dep, DP_CNTR2);
+
+	/* Finish the initialization. */
+	dep->de_flags |= DEF_ENABLED;
+	for (i= 0; i<dep->de_sendq_nr; i++)
+		dep->de_sendq[i].sq_filled= 0;
+	dep->de_sendq_head= 0;
+	dep->de_sendq_tail= 0;
+	if (!dep->de_prog_IO)
+	{
+		dep->de_user2nicf= dp_user2nic;
+		dep->de_nic2userf= dp_nic2user;
+		dep->de_getblockf= dp_getblock;
+	}
+	else if (dep->de_16bit)
+	{
+		dep->de_user2nicf= dp_pio16_user2nic;
+		dep->de_nic2userf= dp_pio16_nic2user;
+		dep->de_getblockf= dp_pio16_getblock;
+	}
+	else
+	{
+		dep->de_user2nicf= dp_pio8_user2nic;
+		dep->de_nic2userf= dp_pio8_nic2user;
+		dep->de_getblockf= dp_pio8_getblock;
+	}
+
+	/* Set the interrupt handler and policy. Do not automatically 
+	 * reenable interrupts. Return the IRQ line number on interrupts.
+ 	 */
+ 	dep->de_hook = dep->de_irq;
+	r= sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);
+	if (r != OK)
+		panic("DP8390", "sys_irqsetpolicy failed", r);
+
+	r= sys_irqenable(&dep->de_hook);
+	if (r != OK)
+	{
+		panic("DP8390", "unable enable interrupts", r);
+	}
+}
+
+/*===========================================================================*
+ *				dp_confaddr				     *
+ *===========================================================================*/
+static void dp_confaddr(dep)
+dpeth_t *dep;
+{
+	int i;
+	char eakey[16];
+	static char eafmt[]= "x:x:x:x:x:x";
+	long v;
+
+	/* User defined ethernet address? */
+	strcpy(eakey, dp_conf[dep-de_table].dpc_envvar);
+	strcat(eakey, "_EA");
+
+	for (i= 0; i < 6; i++)
+	{
+		v= dep->de_address.ea_addr[i];
+		if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
+		{
+			break;
+		}
+		dep->de_address.ea_addr[i]= v;
+	}
+
+	if (i != 0 && i != 6) env_panic(eakey);	/* It's all or nothing */
+}
+
+/*===========================================================================*
+ *				dp_reinit				     *
+ *===========================================================================*/
+static void dp_reinit(dep)
+dpeth_t *dep;
+{
+	int dp_rcr_reg;
+
+	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
+
+	dp_rcr_reg = 0;
+	if (dep->de_flags & DEF_PROMISC)
+		dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
+	if (dep->de_flags & DEF_BROAD)
+		dp_rcr_reg |= RCR_AB;
+	if (dep->de_flags & DEF_MULTI)
+		dp_rcr_reg |= RCR_AM;
+	outb_reg0(dep, DP_RCR, dp_rcr_reg);
+}
+
+/*===========================================================================*
+ *				dp_reset				     *
+ *===========================================================================*/
+static void dp_reset(dep)
+dpeth_t *dep;
+{
+	int i;
+
+	/* Stop chip */
+	outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
+	outb_reg0(dep, DP_RBCR0, 0);
+	outb_reg0(dep, DP_RBCR1, 0);
+	for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
+		; /* Do nothing */
+	outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
+	outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
+	outb_reg0(dep, DP_TCR, TCR_NORMAL);
+
+	/* Acknowledge the ISR_RDC (remote dma) interrupt. */
+	for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); i++)
+		; /* Do nothing */
+	outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
+
+	/* Reset the transmit ring. If we were transmitting a packet, we
+	 * pretend that the packet is processed. Higher layers will
+	 * retransmit if the packet wasn't actually sent.
+	 */
+	dep->de_sendq_head= dep->de_sendq_tail= 0;
+	for (i= 0; i<dep->de_sendq_nr; i++)
+		dep->de_sendq[i].sq_filled= 0;
+	dp_send(dep);
+	dep->de_flags &= ~DEF_STOPPED;
+}
+
+/*===========================================================================*
+ *				dp_check_ints				     *
+ *===========================================================================*/
+static void dp_check_ints(dep)
+dpeth_t *dep;
+{
+	int isr, tsr;
+	int size, sendq_tail;
+
+	if (!(dep->de_flags & DEF_ENABLED))
+		panic("", "dp8390: got premature interrupt", NO_NUM);
+
+	for(;;)
+	{
+		isr = inb_reg0(dep, DP_ISR);
+		if (!isr)
+			break;
+		outb_reg0(dep, DP_ISR, isr);
+		if (isr & (ISR_PTX|ISR_TXE))
+		{
+			if (isr & ISR_TXE)
+			{
+#if DEBUG
+ { printf("%s: got send Error\n", dep->de_name); }
+#endif
+				dep->de_stat.ets_sendErr++;
+			}
+			else
+			{
+				tsr = inb_reg0(dep, DP_TSR);
+
+				if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;
+#if 0	/* Reserved in later manuals, should be ignored */
+				if (!(tsr & TSR_DFR))
+				{
+					/* In most (all?) implementations of
+					 * the dp8390, this bit is set
+					 * when the packet is not deferred
+					 */
+					dep->de_stat.ets_transDef++;
+				}
+#endif
+				if (tsr & TSR_COL) dep->de_stat.ets_collision++;
+				if (tsr & TSR_ABT) dep->de_stat.ets_transAb++;
+				if (tsr & TSR_CRS) dep->de_stat.ets_carrSense++;
+				if (tsr & TSR_FU
+					&& ++dep->de_stat.ets_fifoUnder <= 10)
+				{
+					printf("%s: fifo underrun\n",
+						dep->de_name);
+				}
+				if (tsr & TSR_CDH
+					&& ++dep->de_stat.ets_CDheartbeat <= 10)
+				{
+					printf("%s: CD heart beat failure\n",
+						dep->de_name);
+				}
+				if (tsr & TSR_OWC) dep->de_stat.ets_OWC++;
+			}
+			sendq_tail= dep->de_sendq_tail;
+
+			if (!(dep->de_sendq[sendq_tail].sq_filled))
+			{
+				/* Software bug? */
+				assert(!debug);
+
+				/* Or hardware bug? */
+				printf(
+				"%s: transmit interrupt, but not sending\n",
+					dep->de_name);
+				continue;
+			}
+			dep->de_sendq[sendq_tail].sq_filled= 0;
+			if (++sendq_tail == dep->de_sendq_nr)
+				sendq_tail= 0;
+			dep->de_sendq_tail= sendq_tail;
+			if (dep->de_sendq[sendq_tail].sq_filled)
+			{
+				size= dep->de_sendq[sendq_tail].sq_size;
+				outb_reg0(dep, DP_TPSR,
+					dep->de_sendq[sendq_tail].sq_sendpage);
+				outb_reg0(dep, DP_TBCR1, size >> 8);
+				outb_reg0(dep, DP_TBCR0, size & 0xff);
+				outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
+			}
+			if (dep->de_flags & DEF_SEND_AVAIL)
+				dp_send(dep);
+		}
+
+		if (isr & ISR_PRX)
+		{
+			/* Only call dp_recv if there is a read request */
+			if (dep->de_flags & DEF_READING)
+				dp_recv(dep);
+		}
+		
+		if (isr & ISR_RXE) dep->de_stat.ets_recvErr++;
+		if (isr & ISR_CNT)
+		{
+			dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
+			dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
+			dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
+		}
+		if (isr & ISR_OVW)
+		{
+			dep->de_stat.ets_OVW++;
+#if 0
+			{ printW(); printf(
+				"%s: got overwrite warning\n", dep->de_name); }
+#endif
+			if (dep->de_flags & DEF_READING)
+			{
+				printf(
+"dp_check_ints: strange: overwrite warning and pending read request\n");
+				dp_recv(dep);
+			}
+		}
+		if (isr & ISR_RDC)
+		{
+			/* Nothing to do */
+		}
+		if (isr & ISR_RST)
+		{
+			/* this means we got an interrupt but the ethernet 
+			 * chip is shutdown. We set the flag DEF_STOPPED,
+			 * and continue processing arrived packets. When the
+			 * receive buffer is empty, we reset the dp8390.
+			 */
+#if 0
+			 { printW(); printf(
+				"%s: NIC stopped\n", dep->de_name); }
+#endif
+			dep->de_flags |= DEF_STOPPED;
+			break;
+		}
+	}
+	if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) == 
+						(DEF_READING|DEF_STOPPED))
+	{
+		/* The chip is stopped, and all arrived packets are 
+		 * delivered.
+		 */
+		dp_reset(dep);
+	}
+}
+
+/*===========================================================================*
+ *				dp_recv					     *
+ *===========================================================================*/
+static void dp_recv(dep)
+dpeth_t *dep;
+{
+	dp_rcvhdr_t header;
+	unsigned pageno, curr, next;
+	vir_bytes length;
+	int packet_processed, r;
+	u16_t eth_type;
+
+	packet_processed = FALSE;
+	pageno = inb_reg0(dep, DP_BNRY) + 1;
+	if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
+
+	do
+	{
+		outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
+		curr = inb_reg1(dep, DP_CURR);
+		outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
+
+		if (curr == pageno) break;
+
+		(dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),
+			&header);
+		(dep->de_getblockf)(dep, pageno, sizeof(header) +
+			2*sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
+
+		length = (header.dr_rbcl | (header.dr_rbch << 8)) -
+			sizeof(dp_rcvhdr_t);
+		next = header.dr_next;
+		if (length < ETH_MIN_PACK_SIZE ||
+			length > ETH_MAX_PACK_SIZE_TAGGED)
+		{
+			printf("%s: packet with strange length arrived: %d\n",
+				dep->de_name, (int) length);
+			next= curr;
+		}
+		else if (next < dep->de_startpage || next >= dep->de_stoppage)
+		{
+			printf("%s: strange next page\n", dep->de_name);
+			next= curr;
+		}
+		else if (eth_type == eth_ign_proto)
+		{
+			/* Hack: ignore packets of a given protocol, useful
+			 * if you share a net with 80 computers sending
+			 * Amoeba FLIP broadcasts.  (Protocol 0x8146.)
+			 */
+			static int first= 1;
+			if (first)
+			{
+				first= 0;
+				printf("%s: dropping proto 0x%04x packets\n",
+					dep->de_name,
+					ntohs(eth_ign_proto));
+			}
+			dep->de_stat.ets_packetR++;
+		}
+		else if (header.dr_status & RSR_FO)
+		{
+			/* This is very serious, so we issue a warning and
+			 * reset the buffers */
+			printf("%s: fifo overrun, resetting receive buffer\n",
+				dep->de_name);
+			dep->de_stat.ets_fifoOver++;
+			next = curr;
+		}
+		else if ((header.dr_status & RSR_PRX) &&
+					   (dep->de_flags & DEF_ENABLED))
+		{
+			r = dp_pkt2user(dep, pageno, length);
+			if (r != OK)
+				return;
+
+			packet_processed = TRUE;
+			dep->de_stat.ets_packetR++;
+		}
+		if (next == dep->de_startpage)
+			outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
+		else
+			outb_reg0(dep, DP_BNRY, next - 1);
+
+		pageno = next;
+	}
+	while (!packet_processed);
+}
+
+/*===========================================================================*
+ *				dp_send					     *
+ *===========================================================================*/
+static void dp_send(dep)
+dpeth_t *dep;
+{
+	if (!(dep->de_flags & DEF_SEND_AVAIL))
+		return;
+
+	dep->de_flags &= ~DEF_SEND_AVAIL;
+	switch(dep->de_sendmsg.m_type)
+	{
+	case DL_WRITE:	do_vwrite(&dep->de_sendmsg, TRUE, FALSE);	break;
+	case DL_WRITEV:	do_vwrite(&dep->de_sendmsg, TRUE, TRUE);	break;
+	default:
+		panic("", "dp8390: wrong type:", dep->de_sendmsg.m_type);
+		break;
+	}
+}
+
+/*===========================================================================*
+ *				dp_getblock				     *
+ *===========================================================================*/
+static void dp_getblock(dep, page, offset, size, dst)
+dpeth_t *dep;
+int page;
+size_t offset;
+size_t size;
+void *dst;
+{
+	int r;
+
+	offset = page * DP_PAGESIZE + offset;
+
+	r = sys_vircopy(SELF, BIOS_SEG, dep->de_linmem + offset,
+		SELF, D, (vir_bytes)dst, size);
+
+	if (r != OK)
+		panic("DP8390", "dp_getblock: sys_vircopy failed", r);
+}
+
+/*===========================================================================*
+ *				dp_pio8_getblock			     *
+ *===========================================================================*/
+static void dp_pio8_getblock(dep, page, offset, size, dst)
+dpeth_t *dep;
+int page;
+size_t offset;
+size_t size;
+void *dst;
+{
+	offset = page * DP_PAGESIZE + offset;
+	outb_reg0(dep, DP_RBCR0, size & 0xFF);
+	outb_reg0(dep, DP_RBCR1, size >> 8);
+	outb_reg0(dep, DP_RSAR0, offset & 0xFF);
+	outb_reg0(dep, DP_RSAR1, offset >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	insb(dep->de_data_port, dst, size);
+}
+
+/*===========================================================================*
+ *				dp_pio16_getblock			     *
+ *===========================================================================*/
+static void dp_pio16_getblock(dep, page, offset, size, dst)
+dpeth_t *dep;
+int page;
+size_t offset;
+size_t size;
+void *dst;
+{
+	offset = page * DP_PAGESIZE + offset;
+	outb_reg0(dep, DP_RBCR0, size & 0xFF);
+	outb_reg0(dep, DP_RBCR1, size >> 8);
+	outb_reg0(dep, DP_RSAR0, offset & 0xFF);
+	outb_reg0(dep, DP_RSAR1, offset >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	assert (!(size & 1));
+	insw(dep->de_data_port, dst, size);
+}
+
+/*===========================================================================*
+ *				dp_pkt2user				     *
+ *===========================================================================*/
+static int dp_pkt2user(dep, page, length)
+dpeth_t *dep;
+int page, length;
+{
+	int last, count;
+
+	if (!(dep->de_flags & DEF_READING))
+		return EGENERIC;
+
+	last = page + (length - 1) / DP_PAGESIZE;
+	if (last >= dep->de_stoppage)
+	{
+		count = (dep->de_stoppage - page) * DP_PAGESIZE -
+			sizeof(dp_rcvhdr_t);
+
+		/* Save read_iovec since we need it twice. */
+		dep->de_tmp_iovec = dep->de_read_iovec;
+		(dep->de_nic2userf)(dep, page * DP_PAGESIZE +
+			sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);
+		(dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE, 
+				&dep->de_read_iovec, count, length - count);
+	}
+	else
+	{
+		(dep->de_nic2userf)(dep, page * DP_PAGESIZE +
+			sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
+	}
+
+	dep->de_read_s = length;
+	dep->de_flags |= DEF_PACK_RECV;
+	dep->de_flags &= ~DEF_READING;
+
+	return OK;
+}
+
+/*===========================================================================*
+ *				dp_user2nic				     *
+ *===========================================================================*/
+static void dp_user2nic(dep, iovp, offset, nic_addr, count)
+dpeth_t *dep;
+iovec_dat_t *iovp;
+vir_bytes offset;
+int nic_addr;
+vir_bytes count;
+{
+	vir_bytes vir_hw, vir_user;
+	int bytes, i, r;
+
+	vir_hw = dep->de_linmem + nic_addr;
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		r= sys_vircopy(iovp->iod_proc_nr, D,
+			iovp->iod_iovec[i].iov_addr + offset,
+			SELF, BIOS_SEG, vir_hw, bytes);
+		if (r != OK)
+			panic("DP8390", "dp_user2nic: sys_vircopy failed", r);
+
+		count -= bytes;
+		vir_hw += bytes;
+		offset += bytes;
+	}
+	assert(count == 0);
+}
+
+/*===========================================================================*
+ *				dp_pio8_user2nic			     *
+ *===========================================================================*/
+static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
+dpeth_t *dep;
+iovec_dat_t *iovp;
+vir_bytes offset;
+int nic_addr;
+vir_bytes count;
+{
+	phys_bytes phys_user;
+	int bytes, i;
+
+	outb_reg0(dep, DP_ISR, ISR_RDC);
+
+	outb_reg0(dep, DP_RBCR0, count & 0xFF);
+	outb_reg0(dep, DP_RBCR1, count >> 8);
+	outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
+	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		do_vir_outsb(dep->de_data_port, iovp->iod_proc_nr,
+			iovp->iod_iovec[i].iov_addr + offset, bytes);
+		count -= bytes;
+		offset += bytes;
+	}
+	assert(count == 0);
+
+	for (i= 0; i<100; i++)
+	{
+		if (inb_reg0(dep, DP_ISR) & ISR_RDC)
+			break;
+	}
+	if (i == 100)
+	{
+		panic("", "dp8390: remote dma failed to complete", NO_NUM);
+	}
+}
+
+/*===========================================================================*
+ *				dp_pio16_user2nic			     *
+ *===========================================================================*/
+static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
+dpeth_t *dep;
+iovec_dat_t *iovp;
+vir_bytes offset;
+int nic_addr;
+vir_bytes count;
+{
+	vir_bytes vir_user;
+	vir_bytes ecount;
+	int i, r, bytes, user_proc;
+	u8_t two_bytes[2];
+	int odd_byte;
+
+	ecount= (count+1) & ~1;
+	odd_byte= 0;
+
+	outb_reg0(dep, DP_ISR, ISR_RDC);
+	outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
+	outb_reg0(dep, DP_RBCR1, ecount >> 8);
+	outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
+	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		user_proc= iovp->iod_proc_nr;
+		vir_user= iovp->iod_iovec[i].iov_addr + offset;
+		if (odd_byte)
+		{
+			r= sys_vircopy(user_proc, D, vir_user, 
+				SELF, D, (vir_bytes)&two_bytes[1], 1);
+			if (r != OK)
+			{
+				panic("DP8390",
+					"dp_pio16_user2nic: sys_vircopy failed",
+					r);
+			}
+			outw(dep->de_data_port, *(u16_t *)two_bytes);
+			count--;
+			offset++;
+			bytes--;
+			vir_user++;
+			odd_byte= 0;
+			if (!bytes)
+				continue;
+		}
+		ecount= bytes & ~1;
+		if (ecount != 0)
+		{
+			do_vir_outsw(dep->de_data_port, user_proc, vir_user,
+				ecount);
+			count -= ecount;
+			offset += ecount;
+			bytes -= ecount;
+			vir_user += ecount;
+		}
+		if (bytes)
+		{
+			assert(bytes == 1);
+			r= sys_vircopy(user_proc, D, vir_user, 
+				SELF, D, (vir_bytes)&two_bytes[0], 1);
+			if (r != OK)
+			{
+				panic("DP8390",
+					"dp_pio16_user2nic: sys_vircopy failed",
+					r);
+			}
+			count--;
+			offset++;
+			bytes--;
+			vir_user++;
+			odd_byte= 1;
+		}
+	}
+	assert(count == 0);
+
+	if (odd_byte)
+		outw(dep->de_data_port, *(u16_t *)two_bytes);
+
+	for (i= 0; i<100; i++)
+	{
+		if (inb_reg0(dep, DP_ISR) & ISR_RDC)
+			break;
+	}
+	if (i == 100)
+	{
+		panic("", "dp8390: remote dma failed to complete", NO_NUM);
+	}
+}
+
+/*===========================================================================*
+ *				dp_nic2user				     *
+ *===========================================================================*/
+static void dp_nic2user(dep, nic_addr, iovp, offset, count)
+dpeth_t *dep;
+int nic_addr;
+iovec_dat_t *iovp;
+vir_bytes offset;
+vir_bytes count;
+{
+	vir_bytes vir_hw, vir_user;
+	int bytes, i, r;
+
+	vir_hw = dep->de_linmem + nic_addr;
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		r= sys_vircopy(SELF, BIOS_SEG, vir_hw,
+			iovp->iod_proc_nr, D,
+			iovp->iod_iovec[i].iov_addr + offset, bytes);
+		if (r != OK)
+			panic("DP8390", "dp_nic2user: sys_vircopy failed", r);
+
+		count -= bytes;
+		vir_hw += bytes;
+		offset += bytes;
+	}
+	assert(count == 0);
+}
+
+/*===========================================================================*
+ *				dp_pio8_nic2user			     *
+ *===========================================================================*/
+static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
+dpeth_t *dep;
+int nic_addr;
+iovec_dat_t *iovp;
+vir_bytes offset;
+vir_bytes count;
+{
+	phys_bytes phys_user;
+	int bytes, i;
+
+	outb_reg0(dep, DP_RBCR0, count & 0xFF);
+	outb_reg0(dep, DP_RBCR1, count >> 8);
+	outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
+	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		do_vir_insb(dep->de_data_port, iovp->iod_proc_nr,
+			iovp->iod_iovec[i].iov_addr + offset, bytes);
+		count -= bytes;
+		offset += bytes;
+	}
+	assert(count == 0);
+}
+
+/*===========================================================================*
+ *				dp_pio16_nic2user			     *
+ *===========================================================================*/
+static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
+dpeth_t *dep;
+int nic_addr;
+iovec_dat_t *iovp;
+vir_bytes offset;
+vir_bytes count;
+{
+	vir_bytes vir_user;
+	vir_bytes ecount;
+	int i, r, bytes, user_proc;
+	u8_t two_bytes[2];
+	int odd_byte;
+
+	ecount= (count+1) & ~1;
+	odd_byte= 0;
+
+	outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
+	outb_reg0(dep, DP_RBCR1, ecount >> 8);
+	outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
+	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		user_proc= iovp->iod_proc_nr;
+		vir_user= iovp->iod_iovec[i].iov_addr + offset;
+		if (odd_byte)
+		{
+			r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[1],
+				user_proc, D, vir_user,  1);
+			if (r != OK)
+			{
+				panic("DP8390",
+					"dp_pio16_nic2user: sys_vircopy failed",
+					r);
+			}
+			count--;
+			offset++;
+			bytes--;
+			vir_user++;
+			odd_byte= 0;
+			if (!bytes)
+				continue;
+		}
+		ecount= bytes & ~1;
+		if (ecount != 0)
+		{
+			do_vir_insw(dep->de_data_port, user_proc, vir_user,
+				ecount);
+			count -= ecount;
+			offset += ecount;
+			bytes -= ecount;
+			vir_user += ecount;
+		}
+		if (bytes)
+		{
+			assert(bytes == 1);
+			*(u16_t *)two_bytes= inw(dep->de_data_port);
+			r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[0],
+				user_proc, D, vir_user,  1);
+			if (r != OK)
+			{
+				panic("DP8390",
+					"dp_pio16_nic2user: sys_vircopy failed",
+					r);
+			}
+			count--;
+			offset++;
+			bytes--;
+			vir_user++;
+			odd_byte= 1;
+		}
+	}
+	assert(count == 0);
+}
+
+/*===========================================================================*
+ *				dp_next_iovec					     *
+ *===========================================================================*/
+static void dp_next_iovec(iovp)
+iovec_dat_t *iovp;
+{
+	assert(iovp->iod_iovec_s > IOVEC_NR);
+
+	iovp->iod_iovec_s -= IOVEC_NR;
+
+	iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
+
+	get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr, 
+		(iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
+		sizeof(iovec_t), iovp->iod_iovec); 
+}
+
+/*===========================================================================*
+ *				conf_hw					     *
+ *===========================================================================*/
+static void conf_hw(dep)
+dpeth_t *dep;
+{
+	static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 	/* ,... */ };
+
+	int ifnr;
+	dp_conf_t *dcp;
+
+	dep->de_mode= DEM_DISABLED;	/* Superfluous */
+	ifnr= dep-de_table;
+
+	dcp= &dp_conf[ifnr];
+	update_conf(dep, dcp);
+	if (dep->de_mode != DEM_ENABLED)
+		return;
+	if (!wdeth_probe(dep) && !ne_probe(dep) && !el2_probe(dep))
+	{
+		printf("%s: No ethernet card found at 0x%x\n", 
+			dep->de_name, dep->de_base_port);
+		dep->de_mode= DEM_DISABLED;
+		return;
+	}
+
+/* XXX */ if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;
+
+	dep->de_flags = DEF_EMPTY;
+	dep->de_stat = empty_stat;
+}
+
+/*===========================================================================*
+ *				update_conf				     *
+ *===========================================================================*/
+static void update_conf(dep, dcp)
+dpeth_t *dep;
+dp_conf_t *dcp;
+{
+	long v;
+	static char dpc_fmt[] = "x:d:x:x";
+
+#if ENABLE_PCI
+	if (dep->de_pci)
+	{
+		if (dep->de_pci == 1)
+		{
+			/* PCI device is present */
+			dep->de_mode= DEM_ENABLED;
+		}
+		return;		/* Already configured */
+	}
+#endif
+
+	/* Get the default settings and modify them from the environment. */
+	dep->de_mode= DEM_SINK;
+	v= dcp->dpc_port;
+	switch (env_parse(dcp->dpc_envvar, dpc_fmt, 0, &v, 0x0000L, 0xFFFFL)) {
+	case EP_OFF:
+		dep->de_mode= DEM_DISABLED;
+		break;
+	case EP_ON:
+	case EP_SET:
+		dep->de_mode= DEM_ENABLED;	/* Might become disabled if 
+						 * all probes fail */
+		break;
+	}
+	dep->de_base_port= v;
+
+	v= dcp->dpc_irq | DEI_DEFAULT;
+	(void) env_parse(dcp->dpc_envvar, dpc_fmt, 1, &v, 0L,
+						(long) NR_IRQ_VECTORS - 1);
+	dep->de_irq= v;
+
+	v= dcp->dpc_mem;
+	(void) env_parse(dcp->dpc_envvar, dpc_fmt, 2, &v, 0L, 0xFFFFFL);
+	dep->de_linmem= v;
+
+	v= 0;
+	(void) env_parse(dcp->dpc_envvar, dpc_fmt, 3, &v, 0x2000L, 0x8000L);
+	dep->de_ramsize= v;
+}
+
+/*===========================================================================*
+ *				calc_iovec_size				     *
+ *===========================================================================*/
+static int calc_iovec_size(iovp)
+iovec_dat_t *iovp;
+{
+	/* Calculate the size of a request. Note that the iovec_dat
+	 * structure will be unusable after calc_iovec_size.
+	 */
+	int size;
+	int i;
+
+	size= 0;
+	i= 0;
+	while (i < iovp->iod_iovec_s)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		size += iovp->iod_iovec[i].iov_size;
+		i++;
+	}
+	return size;
+}
+
+/*===========================================================================*
+ *				reply					     *
+ *===========================================================================*/
+static void reply(dep, err, may_block)
+dpeth_t *dep;
+int err;
+int may_block;
+{
+	message reply;
+	int status;
+	int r;
+
+	status = 0;
+	if (dep->de_flags & DEF_PACK_SEND)
+		status |= DL_PACK_SEND;
+	if (dep->de_flags & DEF_PACK_RECV)
+		status |= DL_PACK_RECV;
+
+	reply.m_type = DL_TASK_REPLY;
+	reply.DL_PORT = dep - de_table;
+	reply.DL_PROC = dep->de_client;
+	reply.DL_STAT = status | ((u32_t) err << 16);
+	reply.DL_COUNT = dep->de_read_s;
+	reply.DL_CLCK = 0;	/* Don't know */
+	r= send(dep->de_client, &reply);
+
+	if (r == ELOCKED && may_block)
+	{
+#if 0
+		printf("send locked\n");
+#endif
+		return;
+	}
+
+	if (r < 0)
+		panic("", "dp8390: send failed:", r);
+	
+	dep->de_read_s = 0;
+	dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
+}
+
+/*===========================================================================*
+ *				mess_reply				     *
+ *===========================================================================*/
+static void mess_reply(req, reply_mess)
+message *req;
+message *reply_mess;
+{
+	if (send(req->m_source, reply_mess) != OK)
+		panic("", "dp8390: unable to mess_reply", NO_NUM);
+}
+
+/*===========================================================================*
+ *				get_userdata				     *
+ *===========================================================================*/
+static void get_userdata(user_proc, user_addr, count, loc_addr)
+int user_proc;
+vir_bytes user_addr;
+vir_bytes count;
+void *loc_addr;
+{
+	int r;
+
+	r= sys_vircopy(user_proc, D, user_addr,
+		SELF, D, (vir_bytes)loc_addr, count);
+	if (r != OK)
+		panic("DP8390", "get_userdata: sys_vircopy failed", r);
+}
+
+/*===========================================================================*
+ *				put_userdata				     *
+ *===========================================================================*/
+static void put_userdata(user_proc, user_addr, count, loc_addr)
+int user_proc;
+vir_bytes user_addr;
+vir_bytes count;
+void *loc_addr;
+{
+	int r;
+
+	r= sys_vircopy(SELF, D, (vir_bytes)loc_addr, 
+		user_proc, D, user_addr, count);
+	if (r != OK)
+		panic("DP8390", "put_userdata: sys_vircopy failed", r);
+}
+
+u8_t inb(port_t port)
+{
+	int r;
+	u32_t value;
+
+	r= sys_inb(port, &value);
+	if (r != OK)
+		panic("DP8390","sys_inb failed", r);
+	return value;
+}
+
+u16_t inw(port_t port)
+{
+	int r;
+	unsigned long value;
+
+	r= sys_inw(port, &value);
+	if (r != OK)
+		panic("DP8390", "sys_inw failed", r);
+	return (u16_t) value;
+}
+
+void outb(port_t port, u8_t value)
+{
+	int r;
+
+	r= sys_outb(port, value);
+	if (r != OK)
+		panic("DP8390", "sys_outb failed", r);
+}
+
+void outw(port_t port, u16_t value)
+{
+	int r;
+
+	r= sys_outw(port, value);
+	if (r != OK)
+		panic("DP8390", "sys_outw failed", r);
+}
+
+static void insb(port_t port, void *buf, size_t size)
+{
+	do_vir_insb(port, SELF, (vir_bytes)buf, size);
+}
+
+static void insw(port_t port, void *buf, size_t size)
+{
+	do_vir_insw(port, SELF, (vir_bytes)buf, size);
+}
+
+static void do_vir_insb(port_t port, int proc, vir_bytes buf, size_t size)
+{
+	int r;
+
+	r= sys_sdevio(DIO_INPUT, port, DIO_BYTE, proc, (void *)buf, size);
+	if (r != OK)
+		panic("DP8390", "sys_sdevio failed", r);
+}
+
+static void do_vir_insw(port_t port, int proc, vir_bytes buf, size_t size)
+{
+	int r;
+
+	r= sys_sdevio(DIO_INPUT, port, DIO_WORD, proc, (void *)buf, size);
+	if (r != OK)
+		panic("DP8390", "sys_sdevio failed", r);
+}
+
+static void do_vir_outsb(port_t port, int proc, vir_bytes buf, size_t size)
+{
+	int r;
+
+	r= sys_sdevio(DIO_OUTPUT, port, DIO_BYTE, proc, (void *)buf, size);
+	if (r != OK)
+		panic("DP8390", "sys_sdevio failed", r);
+}
+
+static void do_vir_outsw(port_t port, int proc, vir_bytes buf, size_t size)
+{
+	int r;
+
+	r= sys_sdevio(DIO_OUTPUT, port, DIO_WORD, proc, (void *)buf, size);
+	if (r != OK)
+		panic("DP8390", "sys_sdevio failed", r);
+}
+
+/*
+ * $PchId: dp8390.c,v 1.25 2005/02/10 17:32:07 philip Exp $
+ */
Index: /trunk/minix/drivers/dp8390/dp8390.h
===================================================================
--- /trunk/minix/drivers/dp8390/dp8390.h	(revision 9)
+++ /trunk/minix/drivers/dp8390/dp8390.h	(revision 9)
@@ -0,0 +1,297 @@
+/*
+dp8390.h
+
+Created:	before Dec 28, 1992 by Philip Homburg
+*/
+
+/* National Semiconductor DP8390 Network Interface Controller. */
+
+				/* Page 0, for reading ------------- */
+#define	DP_CR		0x0	/* Read side of Command Register     */
+#define	DP_CLDA0	0x1	/* Current Local Dma Address 0       */
+#define	DP_CLDA1	0x2	/* Current Local Dma Address 1       */
+#define	DP_BNRY		0x3	/* Boundary Pointer                  */
+#define	DP_TSR		0x4	/* Transmit Status Register          */
+#define	DP_NCR		0x5	/* Number of Collisions Register     */
+#define	DP_FIFO		0x6	/* Fifo ??                           */
+#define	DP_ISR		0x7	/* Interrupt Status Register         */
+#define	DP_CRDA0	0x8	/* Current Remote Dma Address 0      */
+#define	DP_CRDA1	0x9	/* Current Remote Dma Address 1      */
+#define	DP_DUM1		0xA	/* unused                            */
+#define	DP_DUM2		0xB	/* unused                            */
+#define	DP_RSR		0xC	/* Receive Status Register           */
+#define	DP_CNTR0	0xD	/* Tally Counter 0                   */
+#define	DP_CNTR1	0xE	/* Tally Counter 1                   */
+#define	DP_CNTR2	0xF	/* Tally Counter 2                   */
+
+				/* Page 0, for writing ------------- */
+#define	DP_CR		0x0	/* Write side of Command Register    */
+#define	DP_PSTART	0x1	/* Page Start Register               */
+#define	DP_PSTOP	0x2	/* Page Stop Register                */
+#define	DP_BNRY		0x3	/* Boundary Pointer                  */
+#define	DP_TPSR		0x4	/* Transmit Page Start Register      */
+#define	DP_TBCR0	0x5	/* Transmit Byte Count Register 0    */
+#define	DP_TBCR1	0x6	/* Transmit Byte Count Register 1    */
+#define	DP_ISR		0x7	/* Interrupt Status Register         */
+#define	DP_RSAR0	0x8	/* Remote Start Address Register 0   */
+#define	DP_RSAR1	0x9	/* Remote Start Address Register 1   */
+#define	DP_RBCR0	0xA	/* Remote Byte Count Register 0      */
+#define	DP_RBCR1	0xB	/* Remote Byte Count Register 1      */
+#define	DP_RCR		0xC	/* Receive Configuration Register    */
+#define	DP_TCR		0xD	/* Transmit Configuration Register   */
+#define	DP_DCR		0xE	/* Data Configuration Register       */
+#define	DP_IMR		0xF	/* Interrupt Mask Register           */
+
+				/* Page 1, read/write -------------- */
+#define	DP_CR		0x0	/* Command Register                  */
+#define	DP_PAR0		0x1	/* Physical Address Register 0       */
+#define	DP_PAR1		0x2	/* Physical Address Register 1       */
+#define	DP_PAR2		0x3	/* Physical Address Register 2       */
+#define	DP_PAR3		0x4	/* Physical Address Register 3       */
+#define	DP_PAR4		0x5	/* Physical Address Register 4       */
+#define	DP_PAR5		0x6	/* Physical Address Register 5       */
+#define	DP_CURR		0x7	/* Current Page Register             */
+#define	DP_MAR0		0x8	/* Multicast Address Register 0      */
+#define	DP_MAR1		0x9	/* Multicast Address Register 1      */
+#define	DP_MAR2		0xA	/* Multicast Address Register 2      */
+#define	DP_MAR3		0xB	/* Multicast Address Register 3      */
+#define	DP_MAR4		0xC	/* Multicast Address Register 4      */
+#define	DP_MAR5		0xD	/* Multicast Address Register 5      */
+#define	DP_MAR6		0xE	/* Multicast Address Register 6      */
+#define	DP_MAR7		0xF	/* Multicast Address Register 7      */
+
+/* Bits in dp_cr */
+#define CR_STP		0x01	/* Stop: software reset              */
+#define CR_STA		0x02	/* Start: activate NIC               */
+#define CR_TXP		0x04	/* Transmit Packet                   */
+#define CR_DMA		0x38	/* Mask for DMA control              */
+#define CR_DM_NOP	0x00	/* DMA: No Operation                 */
+#define CR_DM_RR	0x08	/* DMA: Remote Read                  */
+#define CR_DM_RW	0x10	/* DMA: Remote Write                 */
+#define CR_DM_SP	0x18	/* DMA: Send Packet                  */
+#define CR_DM_ABORT	0x20	/* DMA: Abort Remote DMA Operation   */
+#define CR_PS		0xC0	/* Mask for Page Select              */
+#define CR_PS_P0	0x00	/* Register Page 0                   */
+#define CR_PS_P1	0x40	/* Register Page 1                   */
+#define CR_PS_P2	0x80	/* Register Page 2                   */
+#define CR_PS_T1	0xC0	/* Test Mode Register Map            */
+
+/* Bits in dp_isr */
+#define ISR_PRX		0x01	/* Packet Received with no errors    */
+#define ISR_PTX		0x02	/* Packet Transmitted with no errors */
+#define ISR_RXE		0x04	/* Receive Error                     */
+#define ISR_TXE		0x08	/* Transmit Error                    */
+#define ISR_OVW		0x10	/* Overwrite Warning                 */
+#define ISR_CNT		0x20	/* Counter Overflow                  */
+#define ISR_RDC		0x40	/* Remote DMA Complete               */
+#define ISR_RST		0x80	/* Reset Status                      */
+
+/* Bits in dp_imr */
+#define IMR_PRXE	0x01	/* Packet Received iEnable           */
+#define IMR_PTXE	0x02	/* Packet Transmitted iEnable        */
+#define IMR_RXEE	0x04	/* Receive Error iEnable             */
+#define IMR_TXEE	0x08	/* Transmit Error iEnable            */
+#define IMR_OVWE	0x10	/* Overwrite Warning iEnable         */
+#define IMR_CNTE	0x20	/* Counter Overflow iEnable          */
+#define IMR_RDCE	0x40	/* DMA Complete iEnable              */
+
+/* Bits in dp_dcr */
+#define DCR_WTS		0x01	/* Word Transfer Select              */
+#define DCR_BYTEWIDE	0x00	/* WTS: byte wide transfers          */
+#define DCR_WORDWIDE	0x01	/* WTS: word wide transfers          */
+#define DCR_BOS		0x02	/* Byte Order Select                 */
+#define DCR_LTLENDIAN	0x00	/* BOS: Little Endian                */
+#define DCR_BIGENDIAN	0x02	/* BOS: Big Endian                   */
+#define DCR_LAS		0x04	/* Long Address Select               */
+#define DCR_BMS		0x08	/* Burst Mode Select
+				 * Called Loopback Select (LS) in 
+				 * later manuals. Should be set.     */
+#define DCR_AR		0x10	/* Autoinitialize Remote             */
+#define DCR_FTS		0x60	/* Fifo Threshold Select             */
+#define DCR_2BYTES	0x00	/* 2 bytes                           */
+#define DCR_4BYTES	0x40	/* 4 bytes                           */
+#define DCR_8BYTES	0x20	/* 8 bytes                           */
+#define DCR_12BYTES	0x60	/* 12 bytes                          */
+
+/* Bits in dp_tcr */
+#define TCR_CRC		0x01	/* Inhibit CRC                       */
+#define TCR_ELC		0x06	/* Encoded Loopback Control          */
+#define TCR_NORMAL	0x00	/* ELC: Normal Operation             */
+#define TCR_INTERNAL	0x02	/* ELC: Internal Loopback            */
+#define TCR_0EXTERNAL	0x04	/* ELC: External Loopback LPBK=0     */
+#define TCR_1EXTERNAL	0x06	/* ELC: External Loopback LPBK=1     */
+#define TCR_ATD		0x08	/* Auto Transmit Disable             */
+#define TCR_OFST	0x10	/* Collision Offset Enable (be nice) */
+
+/* Bits in dp_tsr */
+#define TSR_PTX		0x01	/* Packet Transmitted (without error)*/
+#define TSR_DFR		0x02	/* Transmit Deferred, reserved in
+				 * later manuals.		     */
+#define TSR_COL		0x04	/* Transmit Collided                 */
+#define TSR_ABT		0x08	/* Transmit Aborted                  */
+#define TSR_CRS		0x10	/* Carrier Sense Lost                */
+#define TSR_FU		0x20	/* FIFO Underrun                     */
+#define TSR_CDH		0x40	/* CD Heartbeat                      */
+#define TSR_OWC		0x80	/* Out of Window Collision           */
+
+/* Bits in tp_rcr */
+#define RCR_SEP		0x01	/* Save Errored Packets              */
+#define RCR_AR		0x02	/* Accept Runt Packets               */
+#define RCR_AB		0x04	/* Accept Broadcast                  */
+#define RCR_AM		0x08	/* Accept Multicast                  */
+#define RCR_PRO		0x10	/* Physical Promiscuous              */
+#define RCR_MON		0x20	/* Monitor Mode                      */
+
+/* Bits in dp_rsr */
+#define RSR_PRX		0x01	/* Packet Received Intact            */
+#define RSR_CRC		0x02	/* CRC Error                         */
+#define RSR_FAE		0x04	/* Frame Alignment Error             */
+#define RSR_FO		0x08	/* FIFO Overrun                      */
+#define RSR_MPA		0x10	/* Missed Packet                     */
+#define RSR_PHY		0x20	/* Multicast Address Match           */
+#define RSR_DIS		0x40	/* Receiver Disabled                 */
+#define RSR_DFR		0x80	/* In later manuals: Deferring       */
+
+typedef struct dp_rcvhdr
+{
+	u8_t dr_status;			/* Copy of rsr                       */
+	u8_t dr_next;			/* Pointer to next packet            */
+	u8_t dr_rbcl;			/* Receive Byte Count Low            */
+	u8_t dr_rbch;			/* Receive Byte Count High           */
+} dp_rcvhdr_t;
+
+#define DP_PAGESIZE	256
+
+/* Some macros to simplify accessing the dp8390 */
+#define inb_reg0(dep, reg)		(inb(dep->de_dp8390_port+reg))
+#define outb_reg0(dep, reg, data)	(outb(dep->de_dp8390_port+reg, data))
+#define inb_reg1(dep, reg)		(inb(dep->de_dp8390_port+reg))
+#define outb_reg1(dep, reg, data)	(outb(dep->de_dp8390_port+reg, data))
+
+/* Software interface to the dp8390 driver */
+
+struct dpeth;
+struct iovec_dat;
+_PROTOTYPE( typedef void (*dp_initf_t), (struct dpeth *dep)		);
+_PROTOTYPE( typedef void (*dp_stopf_t), (struct dpeth *dep)		);
+_PROTOTYPE( typedef void (*dp_user2nicf_t), (struct dpeth *dep,
+			struct iovec_dat *iovp, vir_bytes offset,
+			int nic_addr, vir_bytes count)			);
+_PROTOTYPE( typedef void (*dp_nic2userf_t), (struct dpeth *dep,
+			int nic_addr, struct iovec_dat *iovp,
+			vir_bytes offset, vir_bytes count)		);
+#if 0
+_PROTOTYPE( typedef void (*dp_getheaderf_t), (struct dpeth *dep,
+			int page, struct dp_rcvhdr *h, u16_t *eth_type)	);
+#endif
+_PROTOTYPE( typedef void (*dp_getblock_t), (struct dpeth *dep,
+		int page, size_t offset, size_t size, void *dst)	);
+
+/* iovectors are handled IOVEC_NR entries at a time. */
+#define IOVEC_NR	16
+
+typedef int irq_hook_t;
+
+typedef struct iovec_dat
+{
+  iovec_t iod_iovec[IOVEC_NR];
+  int iod_iovec_s;
+  int iod_proc_nr;
+  vir_bytes iod_iovec_addr;
+} iovec_dat_t;
+
+#define SENDQ_NR	2	/* Maximum size of the send queue */
+#define SENDQ_PAGES	6	/* 6 * DP_PAGESIZE >= 1514 bytes */
+
+typedef struct dpeth
+{
+	/* The de_base_port field is the starting point of the probe.
+	 * The conf routine also fills de_linmem and de_irq. If the probe
+	 * routine knows the irq and/or memory address because they are
+	 * hardwired in the board, the probe should modify these fields.
+	 * Futhermore, the probe routine should also fill in de_initf and
+	 * de_stopf fields with the appropriate function pointers and set
+	 * de_prog_IO iff programmed I/O is to be used.
+	 */
+	port_t de_base_port;
+	phys_bytes de_linmem;
+	int de_irq;
+	int de_int_pending;
+	irq_hook_t de_hook;
+	dp_initf_t de_initf; 
+	dp_stopf_t de_stopf; 
+	int de_prog_IO;
+	char de_name[sizeof("dp8390#n")];
+
+	/* The initf function fills the following fields. Only cards that do
+	 * programmed I/O fill in the de_pata_port field.
+	 * In addition, the init routine has to fill in the sendq data
+	 * structures.
+	 */
+	ether_addr_t de_address;
+	port_t de_dp8390_port;
+	port_t de_data_port;
+	int de_16bit;
+	int de_ramsize;
+	int de_offset_page;
+	int de_startpage;
+	int de_stoppage;
+
+#if ENABLE_PCI
+	/* PCI config */
+	char de_pci;			/* TRUE iff PCI device */
+	u8_t de_pcibus;	
+	u8_t de_pcidev;	
+	u8_t de_pcifunc;	
+#endif
+
+	/* Do it yourself send queue */
+	struct sendq
+	{
+		int sq_filled;		/* this buffer contains a packet */
+		int sq_size;		/* with this size */
+		int sq_sendpage;	/* starting page of the buffer */
+	} de_sendq[SENDQ_NR];
+	int de_sendq_nr;
+	int de_sendq_head;		/* Enqueue at the head */
+	int de_sendq_tail;		/* Dequeue at the tail */
+
+	/* Fields for internal use by the dp8390 driver. */
+	int de_flags;
+	int de_mode;
+	eth_stat_t de_stat;
+	iovec_dat_t de_read_iovec;
+	iovec_dat_t de_write_iovec;
+	iovec_dat_t de_tmp_iovec;
+	vir_bytes de_read_s;
+	int de_client;
+	message de_sendmsg;
+	dp_user2nicf_t de_user2nicf; 
+	dp_nic2userf_t de_nic2userf; 
+	dp_getblock_t de_getblockf; 
+} dpeth_t;
+
+#define DEI_DEFAULT	0x8000
+
+#define DEF_EMPTY	0x000
+#define DEF_PACK_SEND	0x001
+#define DEF_PACK_RECV	0x002
+#define DEF_SEND_AVAIL	0x004
+#define DEF_READING	0x010
+#define DEF_PROMISC	0x040
+#define DEF_MULTI	0x080
+#define DEF_BROAD	0x100
+#define DEF_ENABLED	0x200
+#define DEF_STOPPED	0x400
+
+#define DEM_DISABLED	0x0
+#define DEM_SINK	0x1
+#define DEM_ENABLED	0x2
+
+#if !__minix_vmd
+#define debug		0	/* Standard Minix lacks debug variable */
+#endif
+
+/*
+ * $PchId: dp8390.h,v 1.10 2005/02/10 17:26:06 philip Exp $
+ */
Index: /trunk/minix/drivers/dp8390/local.h
===================================================================
--- /trunk/minix/drivers/dp8390/local.h	(revision 9)
+++ /trunk/minix/drivers/dp8390/local.h	(revision 9)
@@ -0,0 +1,30 @@
+/*
+local.h
+*/
+
+#define ENABLE_WDETH 1
+#define ENABLE_NE2000 1
+#define ENABLE_3C503 1
+#define ENABLE_PCI 1
+
+struct dpeth;
+
+/* 3c503.c */
+_PROTOTYPE( int el2_probe, (struct dpeth* dep)				);
+
+/* dp8390.c */
+_PROTOTYPE( u8_t inb, (port_t port)					);
+_PROTOTYPE( u16_t inw, (port_t port)					);
+_PROTOTYPE( void outb, (port_t port, u8_t v)				);
+_PROTOTYPE( void outw, (port_t port, u16_t v)				);
+
+/* ne2000.c */
+_PROTOTYPE( int ne_probe, (struct dpeth *dep)				);
+_PROTOTYPE( void ne_init, (struct dpeth *dep)				);
+
+/* rtl8029.c */
+_PROTOTYPE( int rtl_probe, (struct dpeth *dep)				);
+
+/* wdeth.c */
+_PROTOTYPE( int wdeth_probe, (struct dpeth* dep)				);
+
Index: /trunk/minix/drivers/dp8390/ne2000.c
===================================================================
--- /trunk/minix/drivers/dp8390/ne2000.c	(revision 9)
+++ /trunk/minix/drivers/dp8390/ne2000.c	(revision 9)
@@ -0,0 +1,330 @@
+/*
+ne2000.c
+
+Driver for the ne2000 ethernet cards. This file contains only the ne2000
+specific code, the rest is in dp8390.c
+
+Created:	March 15, 1994 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+#include "../drivers.h"
+
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#if __minix_vmd
+#include "config.h"
+#endif
+
+#include "local.h"
+#include "dp8390.h"
+#include "ne2000.h"
+
+#if ENABLE_NE2000
+
+#define N 100
+
+#define MILLIS_TO_TICKS(m)  (((m)*HZ/1000)+1)
+
+_PROTOTYPE( typedef int (*testf_t), (dpeth_t *dep, int pos, u8_t *pat)	);
+
+u8_t	pat0[]= { 0x00, 0x00, 0x00, 0x00 };
+u8_t	pat1[]= { 0xFF, 0xFF, 0xFF, 0xFF };
+u8_t	pat2[]= { 0xA5, 0x5A, 0x69, 0x96 };
+u8_t	pat3[]= { 0x96, 0x69, 0x5A, 0xA5 };
+
+_PROTOTYPE( static int test_8, (dpeth_t *dep, int pos, u8_t *pat)	);
+_PROTOTYPE( static int test_16, (dpeth_t *dep, int pos, u8_t *pat)	);
+_PROTOTYPE( static void ne_stop, (dpeth_t *dep)				);
+_PROTOTYPE( static void milli_delay, (unsigned long millis)		);
+
+/*===========================================================================*
+ *				ne_probe				     *
+ *===========================================================================*/
+int ne_probe(dep)
+dpeth_t *dep;
+{
+	int byte;
+	int i;
+	int loc1, loc2;
+	testf_t f;
+
+	dep->de_dp8390_port= dep->de_base_port + NE_DP8390;
+
+	/* We probe for an ne1000 or an ne2000 by testing whether the
+	 * on board is reachable through the dp8390. Note that the
+	 * ne1000 is an 8bit card and has a memory region distict from
+	 * the 16bit ne2000
+	 */
+
+	for (dep->de_16bit= 0; dep->de_16bit < 2; dep->de_16bit++)
+	{
+		/* Reset the ethernet card */
+		byte= inb_ne(dep, NE_RESET);
+		milli_delay(2);
+		outb_ne(dep, NE_RESET, byte);
+		milli_delay(2);
+
+		/* Reset the dp8390 */
+		outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
+		for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
+			; /* Do nothing */
+
+		/* Check if the dp8390 is really there */
+		if ((inb_reg0(dep, DP_CR) & (CR_STP|CR_DM_ABORT)) !=
+			(CR_STP|CR_DM_ABORT))
+		{
+			return 0;
+		}
+
+		/* Disable the receiver and init TCR and DCR. */
+		outb_reg0(dep, DP_RCR, RCR_MON);
+		outb_reg0(dep, DP_TCR, TCR_NORMAL);
+		if (dep->de_16bit)
+		{
+			outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES |
+				DCR_BMS);
+		}
+		else
+		{
+			outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES |
+				DCR_BMS);
+		}
+
+		if (dep->de_16bit)
+		{
+			loc1= NE2000_START;
+			loc2= NE2000_START + NE2000_SIZE - 4;
+			f= test_16;
+		}
+		else
+		{
+			loc1= NE1000_START;
+			loc2= NE1000_START + NE1000_SIZE - 4;
+			f= test_8;
+		}
+		if (f(dep, loc1, pat0) && f(dep, loc1, pat1) &&
+			f(dep, loc1, pat2) && f(dep, loc1, pat3) &&
+			f(dep, loc2, pat0) && f(dep, loc2, pat1) &&
+			f(dep, loc2, pat2) && f(dep, loc2, pat3))
+		{
+			/* We don't need a memory segment */
+			dep->de_linmem= 0;
+			if (!dep->de_pci)
+				dep->de_initf= ne_init;
+			dep->de_stopf= ne_stop;
+			dep->de_prog_IO= 1;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*===========================================================================*
+ *				ne_init					     *
+ *===========================================================================*/
+void ne_init(dep)
+dpeth_t *dep;
+{
+	int i;
+	int word, sendq_nr;
+
+	/* Setup a transfer to get the ethernet address. */
+	if (dep->de_16bit)
+		outb_reg0(dep, DP_RBCR0, 6*2);
+	else
+		outb_reg0(dep, DP_RBCR0, 6);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, 0);
+	outb_reg0(dep, DP_RSAR1, 0);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	for (i= 0; i<6; i++)
+	{
+		if (dep->de_16bit)
+		{
+			word= inw_ne(dep, NE_DATA);
+			dep->de_address.ea_addr[i]= word;
+		}
+		else
+		{
+			dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA);
+		}
+	}
+	dep->de_data_port= dep->de_base_port + NE_DATA;
+	if (dep->de_16bit)
+	{
+		dep->de_ramsize= NE2000_SIZE;
+		dep->de_offset_page= NE2000_START / DP_PAGESIZE;
+	}
+	else
+	{
+		dep->de_ramsize= NE1000_SIZE;
+		dep->de_offset_page= NE1000_START / DP_PAGESIZE;
+	}
+
+	/* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
+	sendq_nr= dep->de_ramsize / 0x2000;
+	if (sendq_nr < 1)
+		sendq_nr= 1;
+	else if (sendq_nr > SENDQ_NR)
+		sendq_nr= SENDQ_NR;
+	dep->de_sendq_nr= sendq_nr;
+	for (i= 0; i<sendq_nr; i++)
+	{
+		dep->de_sendq[i].sq_sendpage= dep->de_offset_page +
+			i*SENDQ_PAGES;	
+	}
+
+	dep->de_startpage= dep->de_offset_page + i*SENDQ_PAGES;
+	dep->de_stoppage= dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE;
+
+	/* Can't override the default IRQ. */
+	dep->de_irq &= ~DEI_DEFAULT;
+
+	if (!debug)
+	{
+		printf("%s: NE%d000 at %X:%d\n",
+			dep->de_name, dep->de_16bit ? 2 : 1,
+			dep->de_base_port, dep->de_irq);
+	}
+	else
+	{
+		printf("%s: Novell NE%d000 ethernet card at I/O address "
+			"0x%X, memory size 0x%X, irq %d\n",
+			dep->de_name, dep->de_16bit ? 2 : 1,
+			dep->de_base_port, dep->de_ramsize, dep->de_irq);
+	}
+}
+
+/*===========================================================================*
+ *				test_8					     *
+ *===========================================================================*/
+static int test_8(dep, pos, pat)
+dpeth_t *dep;
+int pos;
+u8_t *pat;
+{
+	u8_t buf[4];
+	int i;
+	int r;
+
+	outb_reg0(dep, DP_ISR, 0xFF);
+
+	/* Setup a transfer to put the pattern. */
+	outb_reg0(dep, DP_RBCR0, 4);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, pos & 0xFF);
+	outb_reg0(dep, DP_RSAR1, pos >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+	for (i= 0; i<4; i++)
+		outb_ne(dep, NE_DATA, pat[i]);
+
+	for (i= 0; i<N; i++)
+	{
+		if (inb_reg0(dep, DP_ISR) & ISR_RDC)
+			break;
+	}
+	if (i == N)
+	{
+		if (debug)
+		{
+			printf("%s: NE1000 remote DMA test failed\n",
+				dep->de_name);
+		}
+		return 0;
+	}
+
+	outb_reg0(dep, DP_RBCR0, 4);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, pos & 0xFF);
+	outb_reg0(dep, DP_RSAR1, pos >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	for (i= 0; i<4; i++)
+		buf[i]= inb_ne(dep, NE_DATA);
+
+	r= (memcmp(buf, pat, 4) == 0);
+	return r;
+}
+
+/*===========================================================================*
+ *				test_16					     *
+ *===========================================================================*/
+static int test_16(dep, pos, pat)
+dpeth_t *dep;
+int pos;
+u8_t *pat;
+{
+	u8_t buf[4];
+	int i;
+	int r;
+
+	outb_reg0(dep, DP_ISR, 0xFF);
+
+	/* Setup a transfer to put the pattern. */
+	outb_reg0(dep, DP_RBCR0, 4);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, pos & 0xFF);
+	outb_reg0(dep, DP_RSAR1, pos >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+	for (i= 0; i<4; i += 2)
+	{
+		outw_ne(dep, NE_DATA, *(u16_t *)(pat+i));
+	}
+
+	for (i= 0; i<N; i++)
+	{
+		if (inb_reg0(dep, DP_ISR) & ISR_RDC)
+			break;
+	}
+	if (i == N)
+	{
+		if (debug)
+		{
+			printf("%s: NE2000 remote DMA test failed\n",
+				dep->de_name);
+		}
+		return 0;
+	}
+
+	outb_reg0(dep, DP_RBCR0, 4);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, pos & 0xFF);
+	outb_reg0(dep, DP_RSAR1, pos >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	for (i= 0; i<4; i += 2)
+	{
+		*(u16_t *)(buf+i)= inw_ne(dep, NE_DATA);
+	}
+
+	r= (memcmp(buf, pat, 4) == 0);
+	return r;
+}
+
+/*===========================================================================*
+ *				ne_stop					     *
+ *===========================================================================*/
+static void ne_stop(dep)
+dpeth_t *dep;
+{
+	int byte;
+
+	/* Reset the ethernet card */
+	byte= inb_ne(dep, NE_RESET);
+	milli_delay(2);
+	outb_ne(dep, NE_RESET, byte);
+}
+
+static void milli_delay(unsigned long millis)
+{
+	tickdelay(MILLIS_TO_TICKS(millis));
+}
+
+#endif /* ENABLE_NE2000 */
+
+/*
+ * $PchId: ne2000.c,v 1.10 2004/08/03 12:03:00 philip Exp $
+ */
Index: /trunk/minix/drivers/dp8390/ne2000.h
===================================================================
--- /trunk/minix/drivers/dp8390/ne2000.h	(revision 9)
+++ /trunk/minix/drivers/dp8390/ne2000.h	(revision 9)
@@ -0,0 +1,28 @@
+/*
+ne2000.h
+
+Created:	March 15, 1994 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+#ifndef NE2000_H
+#define NE2000_H
+
+#define NE_DP8390	0x00
+#define NE_DATA		0x10
+#define NE_RESET	0x1F
+
+#define NE1000_START	0x2000
+#define NE1000_SIZE	0x2000
+#define NE2000_START	0x4000
+#define NE2000_SIZE	0x4000
+
+#define inb_ne(dep, reg)	(inb(dep->de_base_port+reg))
+#define outb_ne(dep, reg, data)	(outb(dep->de_base_port+reg, data))
+#define inw_ne(dep, reg)	(inw(dep->de_base_port+reg))
+#define outw_ne(dep, reg, data)	(outw(dep->de_base_port+reg, data))
+
+#endif /* NE2000_H */
+
+/*
+ * $PchId: ne2000.h,v 1.4 2004/08/03 12:03:20 philip Exp $
+ */
Index: /trunk/minix/drivers/dp8390/rtl8029.c
===================================================================
--- /trunk/minix/drivers/dp8390/rtl8029.c	(revision 9)
+++ /trunk/minix/drivers/dp8390/rtl8029.c	(revision 9)
@@ -0,0 +1,378 @@
+/*
+rtl8029.c
+
+Initialization of PCI DP8390-based ethernet cards
+
+Created:	April 2000 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+#include "../drivers.h"
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include <ibm/pci.h>
+
+#include "assert.h"
+
+#include "local.h"
+#include "dp8390.h"
+#include "rtl8029.h"
+
+#if ENABLE_PCI
+
+#define MICROS_TO_TICKS(m)  (((m)*HZ/1000000)+1)
+
+PRIVATE struct pcitab
+{
+	u16_t vid;
+	u16_t did;
+	int checkclass;
+} pcitab[]=
+{
+	{ 0x10ec, 0x8029, 0 },		/* Realtek RTL8029 */
+
+	{ 0x0000, 0x0000, 0 }
+};
+
+_PROTOTYPE( static void rtl_init, (struct dpeth *dep)			);
+_PROTOTYPE( static u16_t get_ee_word, (dpeth_t *dep, int a)		);
+_PROTOTYPE( static void ee_wen, (dpeth_t *dep)				);
+_PROTOTYPE( static void set_ee_word, (dpeth_t *dep, int a, U16_t w)	);
+_PROTOTYPE( static void ee_wds, (dpeth_t *dep)				);
+_PROTOTYPE( static void micro_delay, (unsigned long usecs)		);
+
+PUBLIC int rtl_probe(dep)
+struct dpeth *dep;
+{
+	int i, r, devind, just_one;
+	u16_t vid, did;
+	u32_t bar;
+	u8_t ilr;
+	char *dname;
+
+	pci_init();
+
+	if ((dep->de_pcibus | dep->de_pcidev | dep->de_pcifunc) != 0)
+	{
+		/* Look for specific PCI device */
+		r= pci_find_dev(dep->de_pcibus, dep->de_pcidev,
+			dep->de_pcifunc, &devind);
+		if (r == 0)
+		{
+			printf("%s: no PCI found at %d.%d.%d\n",
+				dep->de_name, dep->de_pcibus,
+				dep->de_pcidev, dep->de_pcifunc);
+			return 0;
+		}
+		pci_ids(devind, &vid, &did);
+		just_one= TRUE;
+	}
+	else
+	{
+		r= pci_first_dev(&devind, &vid, &did);
+		if (r == 0)
+			return 0;
+		just_one= FALSE;
+	}
+
+	for(;;)
+	{
+		for (i= 0; pcitab[i].vid != 0; i++)
+		{
+			if (pcitab[i].vid != vid)
+				continue;
+			if (pcitab[i].did != did)
+				continue;
+			if (pcitab[i].checkclass)
+			{
+				panic("",
+				"rtl_probe: class check not implemented",
+					NO_NUM);
+			}
+			break;
+		}
+		if (pcitab[i].vid != 0)
+			break;
+
+		if (just_one)
+		{
+			printf(
+		"%s: wrong PCI device (%04X/%04X) found at %d.%d.%d\n",
+				dep->de_name, vid, did,
+				dep->de_pcibus,
+				dep->de_pcidev, dep->de_pcifunc);
+			return 0;
+		}
+
+		r= pci_next_dev(&devind, &vid, &did);
+		if (!r)
+			return 0;
+	}
+
+	dname= pci_dev_name(vid, did);
+	if (!dname)
+		dname= "unknown device";
+	printf("%s: %s (%04X/%04X) at %s\n",
+		dep->de_name, dname, vid, did, pci_slot_name(devind));
+	pci_reserve(devind);
+	/* printf("cr = 0x%x\n", pci_attr_r16(devind, PCI_CR)); */
+	bar= pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
+
+	if (bar < 0x400)
+		panic("", "base address is not properly configured", NO_NUM);
+
+	dep->de_base_port= bar;
+
+	ilr= pci_attr_r8(devind, PCI_ILR);
+	dep->de_irq= ilr;
+	if (debug)
+	{
+		printf("%s: using I/O address 0x%lx, IRQ %d\n",
+			dep->de_name, (unsigned long)bar, ilr);
+	}
+	dep->de_initf= rtl_init;
+
+	return TRUE;
+}
+
+static void rtl_init(dep)
+dpeth_t *dep;
+{
+	u8_t reg_a, reg_b, cr, config0, config2, config3;
+	int i;
+
+#if DEBUG
+	printf("rtl_init called\n");
+#endif
+	ne_init(dep);
+
+	/* ID */
+	outb_reg0(dep, DP_CR, CR_PS_P0);
+	reg_a = inb_reg0(dep, DP_DUM1);
+	reg_b = inb_reg0(dep, DP_DUM2);
+
+#if DEBUG
+	printf("rtl_init: '%c', '%c'\n", reg_a, reg_b);
+#endif
+
+	outb_reg0(dep, DP_CR, CR_PS_P3);
+	config0 = inb_reg3(dep, 3);
+	config2 = inb_reg3(dep, 5);
+	config3 = inb_reg3(dep, 6);
+	outb_reg0(dep, DP_CR, CR_PS_P0);
+
+#if DEBUG
+	printf("rtl_init: config 0/2/3 = %x/%x/%x\n",
+		config0, config2, config3);
+#endif
+
+	if (getenv("RTL8029FD"))
+	{
+		printf("rtl_init: setting full-duplex mode\n");
+		outb_reg0(dep, DP_CR, CR_PS_P3);
+
+		cr= inb_reg3(dep, 1);
+		outb_reg3(dep, 1, cr | 0xc0);
+
+		outb_reg3(dep, 6, config3 | 0x40);
+		config3 = inb_reg3(dep, 6);
+
+		config2= inb_reg3(dep, 5);
+		outb_reg3(dep, 5, config2 | 0x20);
+		config2= inb_reg3(dep, 5);
+
+		outb_reg3(dep, 1, cr);
+
+		outb_reg0(dep, DP_CR, CR_PS_P0);
+
+#if DEBUG
+		printf("rtl_init: config 2 = %x\n", config2);
+		printf("rtl_init: config 3 = %x\n", config3);
+#endif
+	}
+
+#if DEBUG
+	for (i= 0; i<64; i++)
+		printf("%x ", get_ee_word(dep, i));
+	printf("\n");
+#endif
+
+	if (getenv("RTL8029MN"))
+	{
+		ee_wen(dep);
+
+		set_ee_word(dep, 0x78/2, 0x10ec);
+		set_ee_word(dep, 0x7A/2, 0x8029);
+		set_ee_word(dep, 0x7C/2, 0x10ec);
+		set_ee_word(dep, 0x7E/2, 0x8029);
+
+		ee_wds(dep);
+
+		assert(get_ee_word(dep, 0x78/2) == 0x10ec);
+		assert(get_ee_word(dep, 0x7A/2) == 0x8029);
+		assert(get_ee_word(dep, 0x7C/2) == 0x10ec);
+		assert(get_ee_word(dep, 0x7E/2) == 0x8029);
+	}
+
+	if (getenv("RTL8029XXX"))
+	{
+		ee_wen(dep);
+
+		set_ee_word(dep, 0x76/2, 0x8029);
+
+		ee_wds(dep);
+
+		assert(get_ee_word(dep, 0x76/2) == 0x8029);
+	}
+}
+
+static u16_t get_ee_word(dep, a)
+dpeth_t *dep;
+int a;
+{
+	int b, i, cmd;
+	u16_t w;
+
+	outb_reg0(dep, DP_CR, CR_PS_P3);	/* Bank 3 */
+
+	/* Switch to 9346 mode and enable CS */
+	outb_reg3(dep, 1, 0x80 | 0x8);
+
+	cmd= 0x180 | (a & 0x3f);	/* 1 1 0 a5 a4 a3 a2 a1 a0 */
+	for (i= 8; i >= 0; i--)
+	{
+		b= (cmd & (1 << i));
+		b= (b ? 2 : 0);
+
+		/* Cmd goes out on the rising edge of the clock */
+		outb_reg3(dep, 1, 0x80 | 0x8 | b);
+		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
+	}
+	outb_reg3(dep, 1, 0x80 | 0x8);	/* End of cmd */
+
+	w= 0;
+	for (i= 0; i<16; i++)
+	{
+		w <<= 1;
+
+		/* Data is shifted out on the rising edge. Read at the
+		 * falling edge.
+		 */
+		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4);
+		outb_reg3(dep, 1, 0x80 | 0x8 | b);
+		b= inb_reg3(dep, 1);
+		w |= (b & 1);
+	}
+
+	outb_reg3(dep, 1, 0x80);		/* drop CS */
+	outb_reg3(dep, 1, 0x00);		/* back to normal */
+	outb_reg0(dep, DP_CR, CR_PS_P0);	/* back to bank 0 */
+
+	return w;
+}
+
+static void ee_wen(dep)
+dpeth_t *dep;
+{
+	int b, i, cmd;
+
+	outb_reg0(dep, DP_CR, CR_PS_P3);	/* Bank 3 */
+
+	/* Switch to 9346 mode and enable CS */
+	outb_reg3(dep, 1, 0x80 | 0x8);
+
+	cmd= 0x130;		/* 1 0 0 1 1 x x x x */
+	for (i= 8; i >= 0; i--)
+	{
+		b= (cmd & (1 << i));
+		b= (b ? 2 : 0);
+
+		/* Cmd goes out on the rising edge of the clock */
+		outb_reg3(dep, 1, 0x80 | 0x8 | b);
+		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
+	}
+	outb_reg3(dep, 1, 0x80 | 0x8);	/* End of cmd */
+	outb_reg3(dep, 1, 0x80);	/* Drop CS */
+	micro_delay(1);			/* Is this required? */
+}
+
+static void set_ee_word(dep, a, w)
+dpeth_t *dep;
+int a;
+u16_t w;
+{
+	int b, i, cmd;
+
+	outb_reg3(dep, 1, 0x80 | 0x8);		/* Set CS */
+
+	cmd= 0x140 | (a & 0x3f);		/* 1 0 1 a5 a4 a3 a2 a1 a0 */
+	for (i= 8; i >= 0; i--)
+	{
+		b= (cmd & (1 << i));
+		b= (b ? 2 : 0);
+
+		/* Cmd goes out on the rising edge of the clock */
+		outb_reg3(dep, 1, 0x80 | 0x8 | b);
+		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
+	}
+	for (i= 15; i >= 0; i--)
+	{
+		b= (w & (1 << i));
+		b= (b ? 2 : 0);
+
+		/* Cmd goes out on the rising edge of the clock */
+		outb_reg3(dep, 1, 0x80 | 0x8 | b);
+		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
+	}
+	outb_reg3(dep, 1, 0x80 | 0x8);	/* End of data */
+	outb_reg3(dep, 1, 0x80);	/* Drop CS */
+	micro_delay(1);			/* Is this required? */
+	outb_reg3(dep, 1, 0x80 | 0x8);		/* Set CS */
+	for (i= 0; i<10000; i++)
+	{
+		if (inb_reg3(dep, 1) & 1)
+			break;
+		micro_delay(1);
+	}
+	if (!(inb_reg3(dep, 1) & 1))
+		panic("", "set_ee_word: device remains busy", NO_NUM);
+}
+
+static void ee_wds(dep)
+dpeth_t *dep;
+{
+	int b, i, cmd;
+
+	outb_reg0(dep, DP_CR, CR_PS_P3);	/* Bank 3 */
+
+	/* Switch to 9346 mode and enable CS */
+	outb_reg3(dep, 1, 0x80 | 0x8);
+
+	cmd= 0x100;		/* 1 0 0 0 0 x x x x */
+	for (i= 8; i >= 0; i--)
+	{
+		b= (cmd & (1 << i));
+		b= (b ? 2 : 0);
+
+		/* Cmd goes out on the rising edge of the clock */
+		outb_reg3(dep, 1, 0x80 | 0x8 | b);
+		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
+	}
+	outb_reg3(dep, 1, 0x80 | 0x8);	/* End of cmd */
+	outb_reg3(dep, 1, 0x80);	/* Drop CS */
+	outb_reg3(dep, 1, 0x00);		/* back to normal */
+	outb_reg0(dep, DP_CR, CR_PS_P0);	/* back to bank 0 */
+}
+
+static void micro_delay(unsigned long usecs)
+{
+	tickdelay(MICROS_TO_TICKS(usecs));
+}
+
+#endif /* ENABLE_PCI */
+
+/*
+ * $PchId: rtl8029.c,v 1.7 2004/08/03 12:16:58 philip Exp $
+ */
Index: /trunk/minix/drivers/dp8390/rtl8029.h
===================================================================
--- /trunk/minix/drivers/dp8390/rtl8029.h	(revision 9)
+++ /trunk/minix/drivers/dp8390/rtl8029.h	(revision 9)
@@ -0,0 +1,15 @@
+/*
+rtl8029.h
+
+Created:	Sep 2003 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+/* Bits in dp_cr */
+#define CR_PS_P3	0xC0	/* Register Page 3                   */
+
+#define inb_reg3(dep, reg)	(inb (dep->de_dp8390_port+reg))
+#define outb_reg3(dep, reg, data) (outb(dep->de_dp8390_port+reg, data))
+
+/*
+ * $PchId: rtl8029.h,v 1.3 2004/08/03 15:11:06 philip Exp $
+ */
Index: /trunk/minix/drivers/dp8390/wdeth.c
===================================================================
--- /trunk/minix/drivers/dp8390/wdeth.c	(revision 9)
+++ /trunk/minix/drivers/dp8390/wdeth.c	(revision 9)
@@ -0,0 +1,362 @@
+/*
+wdeth.c
+
+Created:	March 14, 1994 by Philip Homburg
+*/
+
+#include "../drivers.h"
+
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include "assert.h"
+
+#include "local.h"
+#include "dp8390.h"
+#include "wdeth.h"
+
+#if ENABLE_WDETH
+
+#define WET_ETHERNET	0x01		/* Ethernet transceiver */
+#define WET_STARLAN	0x02		/* Starlan transceiver */
+#define WET_INTERF_CHIP	0x04		/* has a WD83C583 interface chip */
+#define WET_BRD_16BIT	0x08		/* 16 bit board */
+#define WET_SLT_16BIT	0x10		/* 16 bit slot */
+#define WET_790		0x20		/* '790 chip */
+
+static int we_int_table[8]= { 9, 3, 5, 7, 10, 11, 15, 4 };
+static int we_790int_table[8]= { 0, 9, 3, 5, 7, 10, 11, 15 };
+
+_PROTOTYPE( static void we_init, (dpeth_t *dep)				);
+_PROTOTYPE( static void we_stop, (dpeth_t *dep)				);
+_PROTOTYPE( static int we_aliasing, (dpeth_t *dep)			);
+_PROTOTYPE( static int we_interface_chip, (dpeth_t *dep)		);
+_PROTOTYPE( static int we_16bitboard, (dpeth_t *dep)			);
+_PROTOTYPE( static int we_16bitslot, (dpeth_t *dep)			);
+_PROTOTYPE( static int we_ultra, (dpeth_t *dep)				);
+
+/*===========================================================================*
+ *				wdeth_probe				     *
+ *===========================================================================*/
+int wdeth_probe(dep)
+dpeth_t *dep;
+{
+	int sum;
+
+	if (dep->de_linmem == 0)
+		return 0;	/* No shared memory, so no WD board */
+
+	sum = inb_we(dep, EPL_EA0) + inb_we(dep, EPL_EA1) +
+		inb_we(dep, EPL_EA2) + inb_we(dep, EPL_EA3) +
+		inb_we(dep, EPL_EA4) + inb_we(dep, EPL_EA5) +
+		inb_we(dep, EPL_TLB) + inb_we(dep, EPL_CHKSUM);
+	if ((sum & 0xFF) != 0xFF)
+		return 0;	/* No ethernet board at this address */
+
+	dep->de_initf= we_init;
+	dep->de_stopf= we_stop;
+	dep->de_prog_IO= 0;
+	return 1;
+}
+
+/*===========================================================================*
+ *				we_init					     *
+ *===========================================================================*/
+static void we_init(dep)
+dpeth_t *dep;
+{
+	int i, int_indx, int_nr;
+	int tlb, rambit, revision;
+	int icr, irr, hwr, b, gcr;
+	int we_type;
+	int sendq_nr;
+
+	assert(dep->de_mode == DEM_ENABLED);
+	assert(!(dep->de_flags & DEF_ENABLED));
+
+	dep->de_address.ea_addr[0] = inb_we(dep, EPL_EA0);
+	dep->de_address.ea_addr[1] = inb_we(dep, EPL_EA1);
+	dep->de_address.ea_addr[2] = inb_we(dep, EPL_EA2);
+	dep->de_address.ea_addr[3] = inb_we(dep, EPL_EA3);
+	dep->de_address.ea_addr[4] = inb_we(dep, EPL_EA4);
+	dep->de_address.ea_addr[5] = inb_we(dep, EPL_EA5);
+
+	dep->de_dp8390_port= dep->de_base_port + EPL_DP8390;
+
+	dep->de_16bit= 0;
+
+	we_type= 0;
+	we_type |= WET_ETHERNET;	/* assume ethernet */
+	if (we_ultra(dep))
+		we_type |= WET_790;
+	if (!we_aliasing(dep))
+	{
+		if (we_interface_chip(dep))
+			we_type |= WET_INTERF_CHIP;
+		if (we_16bitboard(dep))
+		{
+			we_type |= WET_BRD_16BIT;
+			if (we_16bitslot(dep))
+				we_type |= WET_SLT_16BIT;
+		}
+	}
+	if (we_type & WET_SLT_16BIT)
+		dep->de_16bit= 1;
+
+	/* look at the on board ram size. */
+	tlb= inb_we(dep, EPL_TLB);
+	revision= tlb & E_TLB_REV;
+	rambit= tlb & E_TLB_RAM;
+
+	if (dep->de_ramsize != 0)
+	{
+		/* size set from boot environment. */
+	}
+	else if (revision < 2)
+	{
+		dep->de_ramsize= 0x2000;			/* 8K */
+		if (we_type & WET_BRD_16BIT)
+			dep->de_ramsize= 0x4000;		/* 16K */
+		else if ((we_type & WET_INTERF_CHIP) &&
+			inb_we(dep, EPL_ICR) & E_ICR_MEMBIT)
+		{
+			dep->de_ramsize= 0x8000;		/* 32K */
+		}
+	}
+	else
+	{
+		if (we_type & WET_BRD_16BIT)
+		{
+			/* 32K or 16K */
+			dep->de_ramsize= rambit ? 0x8000 : 0x4000;
+		}
+		else
+		{
+			/* 32K or 8K */
+			dep->de_ramsize= rambit ? 0x8000 : 0x2000;
+		}
+	}
+
+	if (we_type & WET_790)
+	{
+		outb_we(dep, EPL_MSR, E_MSR_RESET);
+		if ((we_type & (WET_BRD_16BIT|WET_SLT_16BIT)) ==
+			(WET_BRD_16BIT|WET_SLT_16BIT))
+		{
+			outb_we(dep, EPL_LAAR, E_LAAR_LAN16E | E_LAAR_MEM16E);
+		}
+	}
+	else if (we_type & WET_BRD_16BIT)
+	{
+		if (we_type & WET_SLT_16BIT)
+		{
+			outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_SOFTINT |
+				E_LAAR_LAN16E | E_LAAR_MEM16E);
+		}
+		else
+		{
+			outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_SOFTINT |
+				E_LAAR_LAN16E);
+		}
+	}
+
+	if (we_type & WET_790)
+	{
+		outb_we(dep, EPL_MSR, E_MSR_MENABLE);
+		hwr= inb_we(dep, EPL_790_HWR);
+		outb_we(dep, EPL_790_HWR, hwr | E_790_HWR_SWH);
+		b= inb_we(dep, EPL_790_B);
+		outb_we(dep, EPL_790_B, ((dep->de_linmem >> 13) & 0x0f) |
+			((dep->de_linmem >> 11) & 0x40) | (b & 0xb0));
+		outb_we(dep, EPL_790_HWR, hwr & ~E_790_HWR_SWH);
+	}
+	else
+	{
+		outb_we(dep, EPL_MSR, E_MSR_RESET);
+		outb_we(dep, EPL_MSR, E_MSR_MENABLE |
+			((dep->de_linmem >> 13) & E_MSR_MEMADDR));
+	}
+
+	if ((we_type & WET_INTERF_CHIP) && !(we_type & WET_790))
+	{
+		icr= inb_we(dep, EPL_ICR);
+		irr= inb_we(dep, EPL_IRR);
+		int_indx= (icr & E_ICR_IR2) |
+			((irr & (E_IRR_IR0|E_IRR_IR1)) >> 5);
+		int_nr= we_int_table[int_indx];
+#if DEBUG
+ { printf("%s: encoded irq= %d\n", dep->de_name, int_nr); }
+#endif
+		if (dep->de_irq & DEI_DEFAULT) dep->de_irq= int_nr;
+
+		outb_we(dep, EPL_IRR, irr | E_IRR_IEN);
+	}
+	if (we_type & WET_790)
+	{
+		hwr= inb_we(dep, EPL_790_HWR);
+		outb_we(dep, EPL_790_HWR, hwr | E_790_HWR_SWH);
+
+		gcr= inb_we(dep, EPL_790_GCR);
+
+		outb_we(dep, EPL_790_HWR, hwr & ~E_790_HWR_SWH);
+
+		int_indx= ((gcr & E_790_GCR_IR2) >> 4) |
+			((gcr & (E_790_GCR_IR1|E_790_GCR_IR0)) >> 2);
+		int_nr= we_790int_table[int_indx];
+#if DEBUG
+ { printf("%s: encoded irq= %d\n", dep->de_name, int_nr); }
+#endif
+		if (dep->de_irq & DEI_DEFAULT) dep->de_irq= int_nr;
+
+		icr= inb_we(dep, EPL_790_ICR);
+		outb_we(dep, EPL_790_ICR, icr | E_790_ICR_EIL);
+	}
+
+	/* Strip the "default flag." */
+	dep->de_irq &= ~DEI_DEFAULT;
+
+	if (!debug)
+	{
+		printf("%s: WD80%d3 at %X:%d:%lX\n",
+			dep->de_name, we_type & WET_BRD_16BIT ? 1 : 0,
+			dep->de_base_port, dep->de_irq, dep->de_linmem);
+	}
+	else
+	{
+		printf("%s: Western Digital %s%s card %s%s at I/O "
+			"address 0x%X, memory address 0x%lX, "
+			"memory size 0x%X, irq %d\n",
+			dep->de_name,
+			we_type & WET_BRD_16BIT ? "16-bit " : "", 
+			we_type & WET_ETHERNET ? "Ethernet" : 
+			we_type & WET_STARLAN ? "Starlan" : "Network",
+			we_type & WET_INTERF_CHIP ? "with an interface chip " : "",
+			we_type & WET_SLT_16BIT ? "in a 16-bit slot " : "",
+			dep->de_base_port, dep->de_linmem, dep->de_ramsize,
+			dep->de_irq);
+	}
+
+	dep->de_offset_page= 0;		/* Shared memory starts at 0 */
+
+	/* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
+	sendq_nr= dep->de_ramsize / 0x2000;
+	if (sendq_nr < 1)
+		sendq_nr= 1;
+	else if (sendq_nr > SENDQ_NR)
+		sendq_nr= SENDQ_NR;
+	dep->de_sendq_nr= sendq_nr;
+	for (i= 0; i<sendq_nr; i++)
+		dep->de_sendq[i].sq_sendpage= i*SENDQ_PAGES;	
+
+	dep->de_startpage= i*SENDQ_PAGES;
+	dep->de_stoppage= dep->de_ramsize / DP_PAGESIZE;
+}
+
+/*===========================================================================*
+ *				we_stop					     *
+ *===========================================================================*/
+static void we_stop(dep)
+dpeth_t *dep;
+{
+	if (dep->de_16bit)
+		outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_LAN16E);
+	outb_we(dep, EPL_MSR, E_MSR_RESET);
+	outb_we(dep, EPL_MSR, 0);
+}
+
+/*===========================================================================*
+ *				we_aliasing				     *
+ *===========================================================================*/
+static int we_aliasing(dep)
+dpeth_t *dep;
+{
+/* Determine whether wd8003 hardware performs register aliasing. This implies 
+ * an old WD8003E board. */
+
+	if (inb_we(dep, EPL_REG1) != inb_we(dep, EPL_EA1))
+		return 0;
+	if (inb_we(dep, EPL_REG2) != inb_we(dep, EPL_EA2))
+		return 0;
+	if (inb_we(dep, EPL_REG3) != inb_we(dep, EPL_EA3))
+		return 0;
+	if (inb_we(dep, EPL_REG4) != inb_we(dep, EPL_EA4))
+		return 0;
+	if (inb_we(dep, EPL_REG7) != inb_we(dep, EPL_CHKSUM))
+		return 0;
+	return 1;
+}
+
+/*===========================================================================*
+ *				we_interface_chip			     *
+ *===========================================================================*/
+static int we_interface_chip(dep)
+dpeth_t *dep;
+{
+/* Determine if the board has an interface chip. */
+
+	outb_we(dep, EPL_GP2, 0x35);
+	if (inb_we(dep, EPL_GP2) != 0x35)
+		return 0;
+	outb_we(dep, EPL_GP2, 0x3A);
+	if (inb_we(dep, EPL_GP2) != 0x3A)
+		return 0;
+	return 1;
+}
+
+/*===========================================================================*
+ *				we_16bitboard				     *
+ *===========================================================================*/
+static int we_16bitboard(dep)
+dpeth_t *dep;
+{
+/* Determine whether the board is capable of doing 16 bit memory moves.
+ * If the 16 bit enable bit is unchangable by software we'll assume an 
+ * 8 bit board.
+ */
+	int icr;
+	u8_t tlb;
+
+	icr= inb_we(dep, EPL_ICR);
+
+	outb_we(dep, EPL_ICR, icr ^ E_ICR_16BIT);
+	if (inb_we(dep, EPL_ICR) == icr)
+	{
+		tlb= inb_we(dep, EPL_TLB);
+#if DEBUG
+		printf("%s: tlb= 0x%x\n", dep->de_name, tlb);
+#endif
+		return tlb == E_TLB_EB || tlb == E_TLB_E ||
+			tlb == E_TLB_SMCE || tlb == E_TLB_SMC8216T ||
+			tlb == E_TLB_SMC8216C;
+	}
+	outb_we(dep, EPL_ICR, icr);
+	return (icr & E_ICR_16BIT);
+}
+
+/*===========================================================================*
+ *				we_16bitslot				     *
+ *===========================================================================*/
+static int we_16bitslot(dep)
+dpeth_t *dep;
+{
+/* Determine if the 16 bit board in plugged into a 16 bit slot.  */
+	return !!(inb_we(dep, EPL_ICR) & E_ICR_16BIT);
+}
+
+/*===========================================================================*
+ *				we_ultra				     *
+ *===========================================================================*/
+static int we_ultra(dep)
+dpeth_t *dep;
+{
+/* Determine if we has an '790 chip.  */
+	u8_t tlb;
+
+	tlb= inb_we(dep, EPL_TLB);
+	return tlb == E_TLB_SMC8216T || tlb == E_TLB_SMC8216C;
+}
+
+#endif /* ENABLE_WDETH */
+
+/*
+ * $PchId: wdeth.c,v 1.10 2003/09/10 19:31:50 philip Exp $
+ */
Index: /trunk/minix/drivers/dp8390/wdeth.h
===================================================================
--- /trunk/minix/drivers/dp8390/wdeth.h	(revision 9)
+++ /trunk/minix/drivers/dp8390/wdeth.h	(revision 9)
@@ -0,0 +1,94 @@
+/*
+wdeth.h
+
+Created:	before Dec 28, 1992 by Philip Homburg
+*/
+
+#ifndef WDETH_H
+#define WDETH_H
+
+/* Western Digital Ethercard Plus, or WD8003E card. */
+
+#define EPL_REG0	 0x0		/* Control(write) and status(read) */
+#define EPL_REG1	 0x1
+#define EPL_REG2	 0x2
+#define EPL_REG3	 0x3
+#define EPL_REG4	 0x4
+#define EPL_REG5	 0x5
+#define EPL_REG6	 0x6
+#define EPL_REG7	 0x7
+#define EPL_EA0		 0x8		/* Most significant eaddr byte */
+#define EPL_EA1		 0x9
+#define EPL_EA2		 0xA
+#define EPL_EA3		 0xB
+#define EPL_EA4		 0xC
+#define EPL_EA5		 0xD		/* Least significant eaddr byte */
+#define EPL_TLB		 0xE
+#define EPL_CHKSUM	 0xF		/* sum from epl_ea0 upto here is 0xFF */
+#define EPL_DP8390	0x10		/* NatSemi chip */
+
+#define EPL_MSR		EPL_REG0	/* memory select register */
+#define EPL_ICR 	EPL_REG1	/* interface configuration register */
+#define EPL_IRR		EPL_REG4	/* interrupt request register (IRR) */
+#define EPL_790_HWR	EPL_REG4	/* '790 hardware support register */
+#define EPL_LAAR	EPL_REG5	/* LA address register (write only) */
+#define EPL_790_ICR	EPL_REG6	/* '790 interrupt control register */
+#define EPL_GP2		EPL_REG7	/* general purpose register 2 */
+#define EPL_790_B	EPL_EA3		/* '790 memory register */
+#define EPL_790_GCR	EPL_EA5		/* '790 General Control Register */
+
+/* Bits in EPL_MSR */
+#define E_MSR_MEMADDR	0x3F		/* Bits SA18-SA13, SA19 implicit 1 */
+#define E_MSR_MENABLE	0x40		/* Memory Enable */
+#define E_MSR_RESET	0x80		/* Software Reset */
+
+/* Bits in EPL_ICR */
+#define E_ICR_16BIT	0x01		/* 16 bit bus */
+#define E_ICR_IR2	0x04		/* bit 2 of encoded IRQ */
+#define E_ICR_MEMBIT	0x08		/* 583 mem size mask */
+
+/* Bits in EPL_IRR */
+#define E_IRR_IR0	0x20		/* bit 0 of encoded IRQ */
+#define E_IRR_IR1	0x40		/* bit 1 of encoded IRQ */
+#define E_IRR_IEN	0x80		/* enable interrupts */
+
+/* Bits in EPL_LAAR */
+#define E_LAAR_A19	0x01		/* address lines for above 1M ram */
+#define E_LAAR_A20	0x02		/* address lines for above 1M ram */
+#define E_LAAR_A21	0x04		/* address lines for above 1M ram */
+#define E_LAAR_A22	0x08		/* address lines for above 1M ram */
+#define E_LAAR_A23	0x10		/* address lines for above 1M ram */
+#define E_LAAR_SOFTINT	0x20		/* enable software interrupt */
+#define E_LAAR_LAN16E	0x40		/* enables 16 bit RAM for LAN */
+#define E_LAAR_MEM16E	0x80		/* enables 16 bit RAM for host */
+
+/* Bits and values in EPL_TLB */
+#define E_TLB_EB	0x05		/* WD8013EB */
+#define E_TLB_E		0x27		/* WD8013 Elite */
+#define E_TLB_SMCE	0x29		/* SMC Elite 16 */
+#define E_TLB_SMC8216T	0x2A		/* SMC 8216 T */
+#define E_TLB_SMC8216C	0x2B		/* SMC 8216 C */
+
+#define E_TLB_REV	0x1F		/* revision mask */
+#define E_TLB_SOFT	0x20		/* soft config */
+#define E_TLB_RAM	0x40		/* extra ram bit */
+
+/* Bits in EPL_790_HWR */
+#define E_790_HWR_SWH	0x80		/* switch register set */
+
+/* Bits in EPL_790_ICR */
+#define E_790_ICR_EIL	0x01		/* enable interrupts */
+
+/* Bits in EPL_790_GCR when E_790_HWR_SWH is set in EPL_790_HWR */
+#define E_790_GCR_IR0	0x04		/* bit 0 of encoded IRQ */
+#define E_790_GCR_IR1	0x08		/* bit 1 of encoded IRQ */
+#define E_790_GCR_IR2	0x40		/* bit 2 of encoded IRQ */
+
+#define inb_we(dep, reg)	(inb(dep->de_base_port+reg))
+#define outb_we(dep, reg, data)	(outb(dep->de_base_port+reg, data))
+
+#endif /* WDETH_H */
+
+/*
+ * $PchId: wdeth.h,v 1.6 2003/09/10 19:29:52 philip Exp $
+ */
Index: /trunk/minix/drivers/dpeth/.depend
===================================================================
--- /trunk/minix/drivers/dpeth/.depend	(revision 9)
+++ /trunk/minix/drivers/dpeth/.depend	(revision 9)
@@ -0,0 +1,293 @@
+
+3c501.o:	../drivers.h
+3c501.o:	/usr/include/ansi.h
+3c501.o:	/usr/include/errno.h
+3c501.o:	/usr/include/ibm/bios.h
+3c501.o:	/usr/include/ibm/interrupt.h
+3c501.o:	/usr/include/ibm/ports.h
+3c501.o:	/usr/include/limits.h
+3c501.o:	/usr/include/minix/bitmap.h
+3c501.o:	/usr/include/minix/callnr.h
+3c501.o:	/usr/include/minix/com.h
+3c501.o:	/usr/include/minix/config.h
+3c501.o:	/usr/include/minix/const.h
+3c501.o:	/usr/include/minix/devio.h
+3c501.o:	/usr/include/minix/dmap.h
+3c501.o:	/usr/include/minix/ipc.h
+3c501.o:	/usr/include/minix/sys_config.h
+3c501.o:	/usr/include/minix/syslib.h
+3c501.o:	/usr/include/minix/sysutil.h
+3c501.o:	/usr/include/minix/type.h
+3c501.o:	/usr/include/net/gen/eth_io.h
+3c501.o:	/usr/include/net/gen/ether.h
+3c501.o:	/usr/include/net/hton.h
+3c501.o:	/usr/include/signal.h
+3c501.o:	/usr/include/stddef.h
+3c501.o:	/usr/include/stdlib.h
+3c501.o:	/usr/include/string.h
+3c501.o:	/usr/include/sys/dir.h
+3c501.o:	/usr/include/sys/types.h
+3c501.o:	/usr/include/unistd.h
+3c501.o:	3c501.c
+3c501.o:	3c501.h
+3c501.o:	dp.h
+
+3c503.o:	../drivers.h
+3c503.o:	/usr/include/ansi.h
+3c503.o:	/usr/include/errno.h
+3c503.o:	/usr/include/ibm/bios.h
+3c503.o:	/usr/include/ibm/interrupt.h
+3c503.o:	/usr/include/ibm/ports.h
+3c503.o:	/usr/include/limits.h
+3c503.o:	/usr/include/minix/bitmap.h
+3c503.o:	/usr/include/minix/callnr.h
+3c503.o:	/usr/include/minix/com.h
+3c503.o:	/usr/include/minix/config.h
+3c503.o:	/usr/include/minix/const.h
+3c503.o:	/usr/include/minix/devio.h
+3c503.o:	/usr/include/minix/dmap.h
+3c503.o:	/usr/include/minix/ipc.h
+3c503.o:	/usr/include/minix/sys_config.h
+3c503.o:	/usr/include/minix/syslib.h
+3c503.o:	/usr/include/minix/sysutil.h
+3c503.o:	/usr/include/minix/type.h
+3c503.o:	/usr/include/net/gen/eth_io.h
+3c503.o:	/usr/include/net/gen/ether.h
+3c503.o:	/usr/include/signal.h
+3c503.o:	/usr/include/stddef.h
+3c503.o:	/usr/include/stdlib.h
+3c503.o:	/usr/include/string.h
+3c503.o:	/usr/include/sys/dir.h
+3c503.o:	/usr/include/sys/types.h
+3c503.o:	/usr/include/unistd.h
+3c503.o:	3c503.c
+3c503.o:	3c503.h
+3c503.o:	8390.h
+3c503.o:	dp.h
+
+3c509.o:	../drivers.h
+3c509.o:	/usr/include/ansi.h
+3c509.o:	/usr/include/errno.h
+3c509.o:	/usr/include/ibm/bios.h
+3c509.o:	/usr/include/ibm/interrupt.h
+3c509.o:	/usr/include/ibm/ports.h
+3c509.o:	/usr/include/limits.h
+3c509.o:	/usr/include/minix/bitmap.h
+3c509.o:	/usr/include/minix/callnr.h
+3c509.o:	/usr/include/minix/com.h
+3c509.o:	/usr/include/minix/config.h
+3c509.o:	/usr/include/minix/const.h
+3c509.o:	/usr/include/minix/devio.h
+3c509.o:	/usr/include/minix/dmap.h
+3c509.o:	/usr/include/minix/ipc.h
+3c509.o:	/usr/include/minix/sys_config.h
+3c509.o:	/usr/include/minix/syslib.h
+3c509.o:	/usr/include/minix/sysutil.h
+3c509.o:	/usr/include/minix/type.h
+3c509.o:	/usr/include/net/gen/eth_io.h
+3c509.o:	/usr/include/net/gen/ether.h
+3c509.o:	/usr/include/net/hton.h
+3c509.o:	/usr/include/signal.h
+3c509.o:	/usr/include/stddef.h
+3c509.o:	/usr/include/stdlib.h
+3c509.o:	/usr/include/string.h
+3c509.o:	/usr/include/sys/dir.h
+3c509.o:	/usr/include/sys/types.h
+3c509.o:	/usr/include/unistd.h
+3c509.o:	3c509.c
+3c509.o:	3c509.h
+3c509.o:	dp.h
+
+8390.o:	../drivers.h
+8390.o:	/usr/include/ansi.h
+8390.o:	/usr/include/errno.h
+8390.o:	/usr/include/ibm/bios.h
+8390.o:	/usr/include/ibm/interrupt.h
+8390.o:	/usr/include/ibm/ports.h
+8390.o:	/usr/include/limits.h
+8390.o:	/usr/include/minix/bitmap.h
+8390.o:	/usr/include/minix/callnr.h
+8390.o:	/usr/include/minix/com.h
+8390.o:	/usr/include/minix/config.h
+8390.o:	/usr/include/minix/const.h
+8390.o:	/usr/include/minix/devio.h
+8390.o:	/usr/include/minix/dmap.h
+8390.o:	/usr/include/minix/ipc.h
+8390.o:	/usr/include/minix/sys_config.h
+8390.o:	/usr/include/minix/syslib.h
+8390.o:	/usr/include/minix/sysutil.h
+8390.o:	/usr/include/minix/type.h
+8390.o:	/usr/include/net/gen/eth_io.h
+8390.o:	/usr/include/net/gen/ether.h
+8390.o:	/usr/include/net/hton.h
+8390.o:	/usr/include/signal.h
+8390.o:	/usr/include/stddef.h
+8390.o:	/usr/include/stdlib.h
+8390.o:	/usr/include/string.h
+8390.o:	/usr/include/sys/dir.h
+8390.o:	/usr/include/sys/types.h
+8390.o:	/usr/include/unistd.h
+8390.o:	8390.c
+8390.o:	8390.h
+8390.o:	dp.h
+
+devio.o:	../drivers.h
+devio.o:	/usr/include/ansi.h
+devio.o:	/usr/include/errno.h
+devio.o:	/usr/include/ibm/bios.h
+devio.o:	/usr/include/ibm/interrupt.h
+devio.o:	/usr/include/ibm/ports.h
+devio.o:	/usr/include/limits.h
+devio.o:	/usr/include/minix/bitmap.h
+devio.o:	/usr/include/minix/callnr.h
+devio.o:	/usr/include/minix/com.h
+devio.o:	/usr/include/minix/config.h
+devio.o:	/usr/include/minix/const.h
+devio.o:	/usr/include/minix/devio.h
+devio.o:	/usr/include/minix/dmap.h
+devio.o:	/usr/include/minix/ipc.h
+devio.o:	/usr/include/minix/sys_config.h
+devio.o:	/usr/include/minix/syslib.h
+devio.o:	/usr/include/minix/sysutil.h
+devio.o:	/usr/include/minix/type.h
+devio.o:	/usr/include/net/gen/eth_io.h
+devio.o:	/usr/include/net/gen/ether.h
+devio.o:	/usr/include/signal.h
+devio.o:	/usr/include/stddef.h
+devio.o:	/usr/include/stdlib.h
+devio.o:	/usr/include/string.h
+devio.o:	/usr/include/sys/dir.h
+devio.o:	/usr/include/sys/types.h
+devio.o:	/usr/include/unistd.h
+devio.o:	devio.c
+devio.o:	dp.h
+
+dp.o:	../drivers.h
+dp.o:	/usr/include/ansi.h
+dp.o:	/usr/include/errno.h
+dp.o:	/usr/include/ibm/bios.h
+dp.o:	/usr/include/ibm/interrupt.h
+dp.o:	/usr/include/ibm/ports.h
+dp.o:	/usr/include/limits.h
+dp.o:	/usr/include/minix/bitmap.h
+dp.o:	/usr/include/minix/callnr.h
+dp.o:	/usr/include/minix/com.h
+dp.o:	/usr/include/minix/config.h
+dp.o:	/usr/include/minix/const.h
+dp.o:	/usr/include/minix/devio.h
+dp.o:	/usr/include/minix/dmap.h
+dp.o:	/usr/include/minix/ipc.h
+dp.o:	/usr/include/minix/keymap.h
+dp.o:	/usr/include/minix/sys_config.h
+dp.o:	/usr/include/minix/syslib.h
+dp.o:	/usr/include/minix/sysutil.h
+dp.o:	/usr/include/minix/type.h
+dp.o:	/usr/include/net/gen/eth_io.h
+dp.o:	/usr/include/net/gen/ether.h
+dp.o:	/usr/include/net/hton.h
+dp.o:	/usr/include/signal.h
+dp.o:	/usr/include/stddef.h
+dp.o:	/usr/include/stdlib.h
+dp.o:	/usr/include/string.h
+dp.o:	/usr/include/sys/dir.h
+dp.o:	/usr/include/sys/types.h
+dp.o:	/usr/include/unistd.h
+dp.o:	dp.c
+dp.o:	dp.h
+
+ne.o:	../drivers.h
+ne.o:	/usr/include/ansi.h
+ne.o:	/usr/include/errno.h
+ne.o:	/usr/include/ibm/bios.h
+ne.o:	/usr/include/ibm/interrupt.h
+ne.o:	/usr/include/ibm/ports.h
+ne.o:	/usr/include/limits.h
+ne.o:	/usr/include/minix/bitmap.h
+ne.o:	/usr/include/minix/callnr.h
+ne.o:	/usr/include/minix/com.h
+ne.o:	/usr/include/minix/config.h
+ne.o:	/usr/include/minix/const.h
+ne.o:	/usr/include/minix/devio.h
+ne.o:	/usr/include/minix/dmap.h
+ne.o:	/usr/include/minix/ipc.h
+ne.o:	/usr/include/minix/sys_config.h
+ne.o:	/usr/include/minix/syslib.h
+ne.o:	/usr/include/minix/sysutil.h
+ne.o:	/usr/include/minix/type.h
+ne.o:	/usr/include/net/gen/eth_io.h
+ne.o:	/usr/include/net/gen/ether.h
+ne.o:	/usr/include/signal.h
+ne.o:	/usr/include/stddef.h
+ne.o:	/usr/include/stdlib.h
+ne.o:	/usr/include/string.h
+ne.o:	/usr/include/sys/dir.h
+ne.o:	/usr/include/sys/types.h
+ne.o:	/usr/include/unistd.h
+ne.o:	8390.h
+ne.o:	dp.h
+ne.o:	ne.c
+ne.o:	ne.h
+
+netbuff.o:	../drivers.h
+netbuff.o:	/usr/include/ansi.h
+netbuff.o:	/usr/include/errno.h
+netbuff.o:	/usr/include/ibm/bios.h
+netbuff.o:	/usr/include/ibm/interrupt.h
+netbuff.o:	/usr/include/ibm/ports.h
+netbuff.o:	/usr/include/limits.h
+netbuff.o:	/usr/include/minix/bitmap.h
+netbuff.o:	/usr/include/minix/callnr.h
+netbuff.o:	/usr/include/minix/com.h
+netbuff.o:	/usr/include/minix/config.h
+netbuff.o:	/usr/include/minix/const.h
+netbuff.o:	/usr/include/minix/devio.h
+netbuff.o:	/usr/include/minix/dmap.h
+netbuff.o:	/usr/include/minix/ipc.h
+netbuff.o:	/usr/include/minix/sys_config.h
+netbuff.o:	/usr/include/minix/syslib.h
+netbuff.o:	/usr/include/minix/sysutil.h
+netbuff.o:	/usr/include/minix/type.h
+netbuff.o:	/usr/include/net/gen/eth_io.h
+netbuff.o:	/usr/include/net/gen/ether.h
+netbuff.o:	/usr/include/signal.h
+netbuff.o:	/usr/include/stddef.h
+netbuff.o:	/usr/include/stdlib.h
+netbuff.o:	/usr/include/string.h
+netbuff.o:	/usr/include/sys/dir.h
+netbuff.o:	/usr/include/sys/types.h
+netbuff.o:	/usr/include/unistd.h
+netbuff.o:	dp.h
+netbuff.o:	netbuff.c
+
+wd.o:	../drivers.h
+wd.o:	/usr/include/ansi.h
+wd.o:	/usr/include/errno.h
+wd.o:	/usr/include/ibm/bios.h
+wd.o:	/usr/include/ibm/interrupt.h
+wd.o:	/usr/include/ibm/ports.h
+wd.o:	/usr/include/limits.h
+wd.o:	/usr/include/minix/bitmap.h
+wd.o:	/usr/include/minix/callnr.h
+wd.o:	/usr/include/minix/com.h
+wd.o:	/usr/include/minix/config.h
+wd.o:	/usr/include/minix/const.h
+wd.o:	/usr/include/minix/devio.h
+wd.o:	/usr/include/minix/dmap.h
+wd.o:	/usr/include/minix/ipc.h
+wd.o:	/usr/include/minix/sys_config.h
+wd.o:	/usr/include/minix/syslib.h
+wd.o:	/usr/include/minix/sysutil.h
+wd.o:	/usr/include/minix/type.h
+wd.o:	/usr/include/net/gen/eth_io.h
+wd.o:	/usr/include/net/gen/ether.h
+wd.o:	/usr/include/signal.h
+wd.o:	/usr/include/stddef.h
+wd.o:	/usr/include/stdlib.h
+wd.o:	/usr/include/string.h
+wd.o:	/usr/include/sys/dir.h
+wd.o:	/usr/include/sys/types.h
+wd.o:	/usr/include/unistd.h
+wd.o:	8390.h
+wd.o:	dp.h
+wd.o:	wd.c
+wd.o:	wd.h
Index: /trunk/minix/drivers/dpeth/3c501.c
===================================================================
--- /trunk/minix/drivers/dpeth/3c501.c	(revision 9)
+++ /trunk/minix/drivers/dpeth/3c501.c	(revision 9)
@@ -0,0 +1,420 @@
+/*
+**  File:	3c501.c		Jan. 14, 1997
+**
+**  Author:	Giovanni Falzoni <gfalzoni@inwind.it>
+**
+**  This file contains specific implementation of the ethernet
+**  device driver for 3Com Etherlink (3c501) boards.  This is a
+**  very old board and its performances are very poor for today
+**  network environments.
+**
+**  $Id: 3c501.c,v 1.3 2005/08/05 19:08:43 beng Exp $
+*/
+
+#include "drivers.h"
+#include <minix/com.h>
+#include <net/hton.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include "dp.h"
+
+#if (ENABLE_3C501 == 1)
+
+#include "3c501.h"
+
+static unsigned char StationAddress[SA_ADDR_LEN] = {0, 0, 0, 0, 0, 0,};
+static buff_t *TxBuff = NULL;
+
+/*
+**  Name:	void el1_getstats(dpeth_t *dep)
+**  Function:	Reads statistics counters from board.
+**/
+static void el1_getstats(dpeth_t * dep)
+{
+
+  return;			/* Nothing to do */
+}
+
+/*
+**  Name:	void el1_reset(dpeth_t *dep)
+**  Function:	Reset function specific for Etherlink hardware.
+*/
+static void el1_reset(dpeth_t * dep)
+{
+  int ix;
+
+  for (ix = 0; ix < 8; ix += 1)	/* Resets the board */
+	outb_el1(dep, EL1_CSR, ECSR_RESET);
+  outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
+
+  /* Set Ethernet Address on controller */
+  outb_el1(dep, EL1_CSR, ECSR_LOOP);	/* Loopback mode */
+  for (ix = EL1_ADDRESS; ix < SA_ADDR_LEN; ix += 1)
+	outb_el1(dep, ix, StationAddress[ix]);
+
+  lock();
+  /* Enable DMA/Interrupt, gain control of Buffer */
+  outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
+  /* Clear RX packet area */
+  outw_el1(dep, EL1_RECVPTR, 0);
+  /* Enable transmit/receive configuration and flush pending interrupts */
+  outb_el1(dep, EL1_XMIT, EXSR_IDLE | EXSR_16JAM | EXSR_JAM | EXSR_UNDER);
+  outb_el1(dep, EL1_RECV, dep->de_recv_mode);
+  inb_el1(dep, EL1_RECV);
+  inb_el1(dep, EL1_XMIT);
+  dep->de_flags &= NOT(DEF_XMIT_BUSY);
+  unlock();
+  return;			/* Done */
+}
+
+/*
+**  Name:	void el1_dumpstats(dpeth_t *dep, int port, vir_bytes size)
+**  Function:	Dumps counter on screen (support for console display).
+*/
+static void el1_dumpstats(dpeth_t * dep)
+{
+
+  return;
+}
+
+/*
+**  Name:	void el1_mode_init(dpeth_t *dep)
+**  Function:	Initializes receicer mode
+*/
+static void el1_mode_init(dpeth_t * dep)
+{
+
+  if (dep->de_flags & DEF_BROAD) {
+	dep->de_recv_mode = ERSR_BROAD | ERSR_RMASK;
+
+  } else if (dep->de_flags & DEF_PROMISC) {
+	dep->de_recv_mode = ERSR_ALL | ERSR_RMASK;
+
+  } else if (dep->de_flags & DEF_MULTI) {
+	dep->de_recv_mode = ERSR_MULTI | ERSR_RMASK;
+
+  } else {
+	dep->de_recv_mode = ERSR_NONE | ERSR_RMASK;
+  }
+  outb_el1(dep, EL1_RECV, dep->de_recv_mode);
+  inb_el1(dep, EL1_RECV);
+  return;
+}
+
+/*
+**  Name:	void el1_recv(dpeth_t *dep, int from, int size)
+**  Function:	Receive function.  Called from interrupt handler to
+**  		unload recv. buffer or from main (packet to client)
+*/
+static void el1_recv(dpeth_t * dep, int from, int size)
+{
+  buff_t *rxptr;
+
+  while ((dep->de_flags & DEF_READING) && (rxptr = dep->de_recvq_head)) {
+
+	/* Remove buffer from queue and free buffer */
+	lock();
+	if (dep->de_recvq_tail == dep->de_recvq_head)
+		dep->de_recvq_head = dep->de_recvq_tail = NULL;
+	else
+		dep->de_recvq_head = rxptr->next;
+	unlock();
+
+	/* Copy buffer to user area */
+	mem2user(dep, rxptr);
+
+	/* Reply information */
+	dep->de_read_s = rxptr->size;
+	dep->de_flags |= DEF_ACK_RECV;
+	dep->de_flags &= NOT(DEF_READING);
+
+	/* Return buffer to the idle pool */
+	free_buff(dep, rxptr);
+  }
+  return;
+}
+
+/*
+**  Name:	void el1_send(dpeth_t *dep, int from_int, int pktsize)
+**  Function:	Send function.  Called from main to transit a packet or
+**  		from interrupt handler when a new packet was queued.
+*/
+static void el1_send(dpeth_t * dep, int from_int, int pktsize)
+{
+  buff_t *txbuff;
+  clock_t now;
+
+  if (from_int == FALSE) {
+
+	if ((txbuff = alloc_buff(dep, pktsize + sizeof(buff_t))) != NULL) {
+
+		/*  Fill transmit buffer from user area */
+		txbuff->next = NULL;
+		txbuff->size = pktsize;
+		txbuff->client = dep->de_client;
+		user2mem(dep, txbuff);
+	} else
+		panic(dep->de_name, "out of memory for Tx", NO_NUM);
+
+  } else if ((txbuff = dep->de_xmitq_head) != NULL) {
+
+	/* Get first packet in queue */
+	lock();
+	if (dep->de_xmitq_tail == dep->de_xmitq_head)
+		dep->de_xmitq_head = dep->de_xmitq_tail = NULL;
+	else
+		dep->de_xmitq_head = txbuff->next;
+	unlock();
+	pktsize = txbuff->size;
+
+  } else
+	panic(dep->de_name, "should not be sending ", NO_NUM);
+
+  if ((dep->de_flags & DEF_XMIT_BUSY)) {
+	if (from_int) panic(dep->de_name, "should not be sending ", NO_NUM);
+	getuptime(&now);
+	if ((now - dep->de_xmit_start) > 4) {
+		/* Transmitter timed out */
+		DEBUG(printf("3c501: transmitter timed out ... \n"));
+		dep->de_stat.ets_sendErr += 1;
+		dep->de_flags &= NOT(DEF_XMIT_BUSY);
+		el1_reset(dep);
+	}
+
+	/* Queue packet */
+	lock();			/* Queue packet to receive queue */
+	if (dep->de_xmitq_head == NULL)
+		dep->de_xmitq_head = txbuff;
+	else
+		dep->de_xmitq_tail->next = txbuff;
+	dep->de_xmitq_tail = txbuff;
+	unlock();
+  } else {
+	/* Save for retransmission */
+	TxBuff = txbuff;
+	dep->de_flags |= (DEF_XMIT_BUSY | DEF_ACK_SEND);
+
+	/* Setup board for packet loading */
+	lock();			/* Buffer to processor */
+	outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
+	inb_el1(dep, EL1_RECV);	/* Clears any spurious interrupt */
+	inb_el1(dep, EL1_XMIT);
+	outw_el1(dep, EL1_RECVPTR, 0);	/* Clears RX packet area */
+
+	/* Loads packet */
+	outw_el1(dep, EL1_XMITPTR, (EL1_BFRSIZ - pktsize));
+	outsb(dep->de_data_port, SELF, txbuff->buffer, pktsize);
+	/* Starts transmitter */
+	outw_el1(dep, EL1_XMITPTR, (EL1_BFRSIZ - pktsize));
+	outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_XMIT);	/* There it goes... */
+	unlock();
+
+	getuptime(&dep->de_xmit_start);
+	dep->de_flags &= NOT(DEF_SENDING);
+  }
+  return;
+}
+
+/*
+**  Name:	void el1_stop(dpeth_t *dep)
+**  Function:	Stops board and disable interrupts.
+*/
+static void el1_stop(dpeth_t * dep)
+{
+  int ix;
+
+  DEBUG(printf("%s: stopping Etherlink ....\n", dep->de_name));
+  for (ix = 0; ix < 8; ix += 1)	/* Reset board */
+	outb_el1(dep, EL1_CSR, ECSR_RESET);
+  outb_el1(dep, EL1_CSR, ECSR_SYS);
+  sys_irqdisable(&dep->de_hook);	/* Disable interrupt */
+  return;
+}
+
+/*
+**  Name:	void el1_interrupt(dpeth_t *dep)
+**  Function:	Interrupt handler.  Acknwledges transmit interrupts
+**  		or unloads receive buffer to memory queue.
+*/
+static void el1_interrupt(dpeth_t * dep)
+{
+  u16_t csr, isr;
+  int pktsize;
+  buff_t *rxptr;
+
+  csr = inb_el1(dep, EL1_CSR);
+  if ((csr & ECSR_XMIT) && (dep->de_flags & DEF_XMIT_BUSY)) {
+
+	/* Got a transmit interrupt */
+	isr = inb_el1(dep, EL1_XMIT);
+	if ((isr & (EXSR_16JAM | EXSR_UNDER | EXSR_JAM)) || !(isr & EXSR_IDLE)) {
+	DEBUG(printf("3c501: got xmit interrupt (ASR=0x%02X XSR=0x%02X)\n", csr, isr));
+		if (isr & EXSR_JAM) {
+			/* Sending, packet got a collision */
+			dep->de_stat.ets_collision += 1;
+			/* Put pointer back to beginning of packet */
+			outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
+			outw_el1(dep, EL1_XMITPTR, (EL1_BFRSIZ - TxBuff->size));
+			/* And retrigger transmission */
+			outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_XMIT);
+			return;
+
+		} else if ((isr & EXSR_16JAM) || !(isr & EXSR_IDLE)) {
+			dep->de_stat.ets_sendErr += 1;
+
+		} else if (isr & EXSR_UNDER) {
+			dep->de_stat.ets_fifoUnder += 1;
+		}
+		DEBUG(printf("3c501: got xmit interrupt (0x%02X)\n", isr));
+		el1_reset(dep);
+
+	} else {
+		/** if (inw_el1(dep, EL1_XMITPTR) == EL1_BFRSIZ) **/
+		/* Packet transmitted successfully */
+		dep->de_stat.ets_packetT += 1;
+		dep->bytes_Tx += (long) (TxBuff->size);
+		free_buff(dep, TxBuff);
+		dep->de_flags &= NOT(DEF_XMIT_BUSY);
+		if ((dep->de_flags & DEF_SENDING) && dep->de_xmitq_head) {
+			/* Pending transmit request available in queue */
+			el1_send(dep, TRUE, 0);
+			if (dep->de_flags & (DEF_XMIT_BUSY | DEF_ACK_SEND))
+				return;
+		}
+	}
+
+  } else if ((csr & (ECSR_RECV | ECSR_XMTBSY)) == (ECSR_RECV | ECSR_XMTBSY)) {
+
+	/* Got a receive interrupt */
+	isr = inb_el1(dep, EL1_RECV);
+	pktsize = inw_el1(dep, EL1_RECVPTR);
+	if ((isr & ERSR_RERROR) || (isr & ERSR_STALE)) {
+	DEBUG(printf("Rx0 (ASR=0x%02X RSR=0x%02X size=%d)\n", csr, isr, pktsize));
+		dep->de_stat.ets_recvErr += 1;
+
+	} else if (pktsize < ETH_MIN_PACK_SIZE || pktsize > ETH_MAX_PACK_SIZE) {
+	DEBUG(printf("Rx1 (ASR=0x%02X RSR=0x%02X size=%d)\n", csr, isr, pktsize));
+		dep->de_stat.ets_recvErr += 1;
+
+	} else if ((rxptr = alloc_buff(dep, pktsize + sizeof(buff_t))) == NULL) {
+		/* Memory not available. Drop packet */
+		dep->de_stat.ets_fifoOver += 1;
+
+	} else if (isr & (ERSR_GOOD | ERSR_ANY)) {
+		/* Got a good packet. Read it from buffer */
+		outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
+		outw_el1(dep, EL1_XMITPTR, 0);
+		insb(dep->de_data_port, SELF, rxptr->buffer, pktsize);
+		rxptr->next = NULL;
+		rxptr->size = pktsize;
+		dep->de_stat.ets_packetR += 1;
+		dep->bytes_Rx += (long) pktsize;
+		lock();		/* Queue packet to receive queue */
+		if (dep->de_recvq_head == NULL)
+			dep->de_recvq_head = rxptr;
+		else
+			dep->de_recvq_tail->next = rxptr;
+		dep->de_recvq_tail = rxptr;
+		unlock();
+
+		/* Reply to pending Receive requests, if any */
+		el1_recv(dep, TRUE, 0);
+	}
+  } else {			/* Nasty condition, should never happen */
+	DEBUG(
+	      printf("3c501: got interrupt with status 0x%02X\n"
+		     "       de_flags=0x%04X  XSR=0x%02X RSR=0x%02X \n"
+		     "       xmit buffer = 0x%4X recv buffer = 0x%4X\n",
+			csr, dep->de_flags,
+			inb_el1(dep, EL1_RECV),
+			inb_el1(dep, EL1_XMIT),
+			inw_el1(dep, EL1_XMITPTR),
+			inw_el1(dep, EL1_RECVPTR))
+		);
+	el1_reset(dep);
+  }
+
+  /* Move into receive mode */
+  outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_RECV);
+  outw_el1(dep, EL1_RECVPTR, 0);
+  /* Be sure that interrupts are cleared */
+  inb_el1(dep, EL1_RECV);
+  inb_el1(dep, EL1_XMIT);
+  return;
+}
+
+/*
+**  Name:	void el1_init(dpeth_t *dep)
+**  Function:	Initalizes board hardware and driver data structures.
+*/
+static void el1_init(dpeth_t * dep)
+{
+  int ix;
+
+  dep->de_irq &= NOT(DEI_DEFAULT);	/* Strip the default flag. */
+  dep->de_offset_page = 0;
+  dep->de_data_port = dep->de_base_port + EL1_DATAPORT;
+
+  el1_reset(dep);		/* Reset and initialize board */
+
+  /* Start receiver (default mode) */
+  outw_el1(dep, EL1_RECVPTR, 0);
+  outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_RECV);
+
+  /* Initializes buffer pool */
+  init_buff(dep, NULL);
+  el1_mode_init(dep);
+
+  printf("%s: Etherlink (%s) at %X:%d - ",
+         dep->de_name, "3c501", dep->de_base_port, dep->de_irq);
+  for (ix = 0; ix < SA_ADDR_LEN; ix += 1)
+	printf("%02X%c", (dep->de_address.ea_addr[ix] = StationAddress[ix]),
+	       ix < SA_ADDR_LEN - 1 ? ':' : '\n');
+
+  /* Device specific functions */
+  dep->de_recvf = el1_recv;
+  dep->de_sendf = el1_send;
+  dep->de_flagsf = el1_mode_init;
+  dep->de_resetf = el1_reset;
+  dep->de_getstatsf = el1_getstats;
+  dep->de_dumpstatsf = el1_dumpstats;
+  dep->de_interruptf = el1_interrupt;
+
+  return;			/* Done */
+}
+
+/*
+**  Name:	int el1_probe(dpeth_t *dep)
+**  Function:	Checks for presence of the board.
+*/
+PUBLIC int el1_probe(dpeth_t * dep)
+{
+  int ix;
+
+  for (ix = 0; ix < 8; ix += 1)	/* Reset the board */
+	outb_el1(dep, EL1_CSR, ECSR_RESET);
+  outb_el1(dep, EL1_CSR, ECSR_SYS);	/* Leaves buffer to system */
+
+  /* Check station address */
+  for (ix = 0; ix < SA_ADDR_LEN; ix += 1) {
+	outw_el1(dep, EL1_XMITPTR, ix);
+	StationAddress[ix] = inb_el1(dep, EL1_SAPROM);
+  }
+  if (StationAddress[0] != 0x02 ||	/* Etherlink Station address  */
+      StationAddress[1] != 0x60 ||	/* MUST be 02:60:8c:xx:xx:xx  */
+      StationAddress[2] != 0x8C)
+	return FALSE;		/* No Etherlink board at this address */
+
+  dep->de_ramsize = 0;		/* RAM size is meaningless */
+  dep->de_linmem = 0L;		/* Access is via I/O port  */
+
+  /* Device specific functions */
+  dep->de_initf = el1_init;
+  dep->de_stopf = el1_stop;
+
+  return TRUE;			/* Etherlink board found */
+}
+
+#endif				/* ENABLE_3C501 */
+
+/** 3c501.c **/
Index: /trunk/minix/drivers/dpeth/3c501.h
===================================================================
--- /trunk/minix/drivers/dpeth/3c501.h	(revision 9)
+++ /trunk/minix/drivers/dpeth/3c501.h	(revision 9)
@@ -0,0 +1,71 @@
+/*
+**  File:	3c501.h		Jan. 14, 1997
+**
+**  Author:	Giovanni Falzoni <gfalzoni@inwind.it>
+**
+**  Interface description for 3Com Etherlink boards
+**
+**  $Log: 3c501.h,v $
+**  Revision 1.1  2005/06/29 10:16:46  beng
+**  Import of dpeth 3c501/3c509b/.. ethernet driver by
+**  Giovanni Falzoni <fgalzoni@inwind.it>.
+**
+**  Revision 2.0  2005/06/26 16:16:46  lsodgf0
+**  Initial revision for Minix 3.0.6
+**
+**  $Id: 3c501.h,v 1.1 2005/06/29 10:16:46 beng Exp $
+*/
+
+/* The various board command registers					 */
+#define EL1_ADDRESS	0x00	/* Board station address, 6 bytes	 */
+#define EL1_RECV	0x06	/* Board Receive Config/Status Reg.	 */
+#define EL1_XMIT	0x07	/* Board Transmit Config/Status Reg.	 */
+#define EL1_XMITPTR	0x08	/* Transmit buffer pointer (word access) */
+#define EL1_RECVPTR	0x0A	/* Receive buffer pointer (word access)	 */
+#define EL1_SAPROM	0x0C	/* Window on Station Addr prom		 */
+#define EL1_CSR		0x0E	/* Board Command/Status Register	 */
+#define EL1_DATAPORT	0x0F	/* Window on packet buffer (Data Port)	 */
+
+/* Bits in EL1_RECV, interrupt enable on write, status when read	 */
+#define ERSR_NONE	0x00	/* Match mode in bits 5-6 (wo)		 */
+#define ERSR_ALL	0x40	/* Promiscuous receive (wo)		 */
+#define ERSR_BROAD	0x80	/* Station address plus broadcast (wo)	 */
+#define ERSR_MULTI	0x80	/* Station address plus multicast 0xC0	 */
+#define ERSR_STALE	0x80	/* Receive status previously read (ro)	 */
+#define ERSR_GOOD	0x20	/* Well formed packets only (rw)	 */
+#define ERSR_ANY	0x10	/* Any packet, even with errors (rw)	 */
+#define ERSR_SHORT	0x08	/* Short frame (rw)			 */
+#define ERSR_DRIBBLE	0x04	/* Dribble error (rw)			 */
+#define ERSR_FCS	0x02	/* CRC error (rw)			 */
+#define ERSR_OVER	0x01	/* Data overflow (rw)			 */
+
+#define ERSR_RERROR	(ERSR_SHORT|ERSR_DRIBBLE|ERSR_FCS|ERSR_OVER)
+#define ERSR_RMASK	(ERSR_GOOD|ERSR_RERROR)/*(ERSR_GOOD|ERSR_ANY|ERSR_RERROR)*/
+
+/* Bits in EL1_XMIT, interrupt enable on write, status when read	 */
+#define EXSR_IDLE	0x08	/* Transmit idle (send completed)	 */
+#define EXSR_16JAM	0x04	/* Packet sending got 16 collisions	 */
+#define EXSR_JAM	0x02	/* Packet sending got a collision	 */
+#define EXSR_UNDER	0x01	/* Data underflow in sending		 */
+
+/* Bits in EL1_CSR (Configuration Status Register)			 */
+#define ECSR_RESET	0x80	/* Reset the controller (wo)		 */
+#define ECSR_XMTBSY	0x80	/* Transmitter busy (ro)		 */
+#define ECSR_RIDE	0x01	/* Request interrupt/DMA enable (rw)	 */
+#define ECSR_DMA	0x20	/* DMA request (rw)			 */
+#define ECSR_EDMA	0x10	/* DMA done (ro)			 */
+#define ECSR_CRC	0x02	/* Causes CRC error on transmit (wo)	 */
+#define ECSR_RCVBSY	0x01	/* Receive in progress (ro)		 */
+#define ECSR_LOOP	(3<<2)	/* 2 bit field in bits 2,3, loopback	 */
+#define ECSR_RECV	(2<<2)	/* Gives buffer to receiver (rw)	 */
+#define ECSR_XMIT	(1<<2)	/* Gives buffer to transmit (rw)	 */
+#define ECSR_SYS	(0<<2)	/* Gives buffer to processor (wo)	 */
+
+#define EL1_BFRSIZ	2048	/* Number of bytes in board buffer	 */
+
+#define inb_el1(dep,reg) (inb(dep->de_base_port+(reg)))
+#define inw_el1(dep,reg) (inw(dep->de_base_port+(reg)))
+#define outb_el1(dep,reg,data) (outb(dep->de_base_port+(reg),data))
+#define outw_el1(dep,reg,data) (outw(dep->de_base_port+(reg),data))
+
+/** 3c501.h **/
Index: /trunk/minix/drivers/dpeth/3c503.c
===================================================================
--- /trunk/minix/drivers/dpeth/3c503.c	(revision 9)
+++ /trunk/minix/drivers/dpeth/3c503.c	(revision 9)
@@ -0,0 +1,167 @@
+/*
+**  File:	3c503.c		Dec. 20, 1996
+**
+**  Author:	Giovanni Falzoni <gfalzoni@inwind.it>
+**
+**  Driver for the Etherlink II boards.  Works in shared memory mode.
+**  Programmed I/O could be used as well but would result in poor
+**  performances. This file contains only the board specific code,
+**  the rest is in 8390.c        Code specific for ISA bus only
+**
+**  $Id: 3c503.c,v 1.3 2005/08/05 19:08:43 beng Exp $
+*/
+
+#include "drivers.h"
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include "dp.h"
+
+#if (ENABLE_3C503 == 1)
+
+#include "8390.h"
+#include "3c503.h"
+
+/*
+**  Name:	void el2_init(dpeth_t *dep);
+**  Function:	Initalize hardware and data structures.
+*/
+static void el2_init(dpeth_t * dep)
+{
+  int ix, irq;
+  int sendq_nr;
+  int cntr;
+
+  /* Map the address PROM to lower I/O address range */
+  cntr = inb_el2(dep, EL2_CNTR);
+  outb_el2(dep, EL2_CNTR, cntr | ECNTR_SAPROM);
+
+  /* Read station address from PROM */
+  for (ix = EL2_EA0; ix <= EL2_EA5; ix += 1)
+	dep->de_address.ea_addr[ix] = inb_el2(dep, ix);
+
+  /* Map the 8390 back to lower I/O address range */
+  outb_el2(dep, EL2_CNTR, cntr);
+
+  /* Enable memory, but turn off interrupts until we are ready */
+  outb_el2(dep, EL2_CFGR, ECFGR_IRQOFF);
+
+  dep->de_data_port = dep->de_dp8390_port = dep->de_base_port;
+  dep->de_prog_IO = FALSE;	/* Programmed I/O not yet available */
+
+  /* Check width of data bus */
+  outb_el2(dep, DP_CR, CR_PS_P0 | CR_NO_DMA | CR_STP);
+  outb_el2(dep, DP_DCR, 0);
+  outb_el2(dep, DP_CR, CR_PS_P2 | CR_NO_DMA | CR_STP);
+  dep->de_16bit = (inb_el2(dep, DP_DCR) & DCR_WTS) != 0;
+  outb_el2(dep, DP_CR, CR_PS_P0 | CR_NO_DMA | CR_STP);
+
+  /* Allocate one send buffer (1.5kb) per 8kb of on board memory. */
+  /* Only 8kb of 3c503/16 boards are used to avoid specific routines */
+  sendq_nr = dep->de_ramsize / 0x2000;
+  if (sendq_nr < 1)
+	sendq_nr = 1;
+  else if (sendq_nr > SENDQ_NR)
+	sendq_nr = SENDQ_NR;
+
+  dep->de_sendq_nr = sendq_nr;
+  for (ix = 0; ix < sendq_nr; ix++)
+	dep->de_sendq[ix].sq_sendpage = (ix * SENDQ_PAGES) + EL2_SM_START_PG;
+
+  dep->de_startpage = (ix * SENDQ_PAGES) + EL2_SM_START_PG;
+  dep->de_stoppage = EL2_SM_STOP_PG;
+
+  outb_el2(dep, EL2_STARTPG, dep->de_startpage);
+  outb_el2(dep, EL2_STOPPG, dep->de_stoppage);
+
+  /* Point the vector pointer registers somewhere ?harmless?. */
+  outb_el2(dep, EL2_VP2, 0xFF);	/* Point at the ROM restart location    */
+  outb_el2(dep, EL2_VP1, 0xFF);	/* 0xFFFF:0000  (from original sources) */
+  outb_el2(dep, EL2_VP0, 0x00);	/* - What for protected mode? */
+
+  /* Set interrupt level for 3c503 */
+  irq = (dep->de_irq &= ~DEI_DEFAULT);	/* Strip the default flag. */
+  if (irq == 9) irq = 2;
+  if (irq < 2 || irq > 5) panic(dep->de_name, "bad 3c503 irq configuration", irq);
+  outb_el2(dep, EL2_IDCFG, (0x04 << irq));
+
+  outb_el2(dep, EL2_DRQCNT, 0x08);	/* Set burst size to 8 */
+  outb_el2(dep, EL2_DMAAH, EL2_SM_START_PG);	/* Put start of TX  */
+  outb_el2(dep, EL2_DMAAL, 0x00);	/* buffer in the GA DMA reg */
+
+  outb_el2(dep, EL2_CFGR, ECFGR_NORM);	/* Enable shared memory */
+
+  ns_init(dep);			/* Initialize DP controller */
+
+  printf("%s: Etherlink II%s (%s) at %X:%d:%05lX - ",
+	 dep->de_name, dep->de_16bit ? "/16" : "", "3c503",
+	 dep->de_base_port, dep->de_irq,
+         dep->de_linmem + dep->de_offset_page);
+  for (ix = 0; ix < SA_ADDR_LEN; ix += 1)
+	printf("%02X%c", dep->de_address.ea_addr[ix],
+	       ix < SA_ADDR_LEN - 1 ? ':' : '\n');
+  return;
+}
+
+/*
+**  Name:	void el2_stop(dpeth_t *dep);
+**  Function:	Stops board by disabling interrupts.
+*/
+static void el2_stop(dpeth_t * dep)
+{
+
+  outb_el2(dep, EL2_CFGR, ECFGR_IRQOFF);
+  sys_irqdisable(&dep->de_hook);	/* disable interrupts */
+  return;
+}
+
+/*
+**  Name:	void el2_probe(dpeth_t *dep);
+**  Function:	Probe for the presence of an EtherLink II card.
+**  		Initialize memory addressing if card detected.
+*/
+int el2_probe(dpeth_t * dep)
+{
+  int iobase, membase;
+  int thin;
+
+  /* Thin ethernet or AUI? */
+  thin = (dep->de_linmem & 1) ? ECNTR_AUI : ECNTR_THIN;
+
+  /* Location registers should have 1 bit set */
+  if (!(iobase = inb_el2(dep, EL2_IOBASE))) return FALSE;
+  if (!((membase = inb_el2(dep, EL2_MEMBASE)) & 0xF0)) return FALSE;
+  if ((iobase & (iobase - 1)) || (membase & (membase - 1))) return FALSE;
+
+  /* Resets board */
+  outb_el2(dep, EL2_CNTR, ECNTR_RESET | thin);
+  milli_delay(1);
+  outb_el2(dep, EL2_CNTR, thin);
+  milli_delay(5);
+
+  /* Map the address PROM to lower I/O address range */
+  outb_el2(dep, EL2_CNTR, ECNTR_SAPROM | thin);
+  if (inb_el2(dep, EL2_EA0) != 0x02 ||	/* Etherlink II Station address */
+      inb_el2(dep, EL2_EA1) != 0x60 ||	/* MUST be 02:60:8c:xx:xx:xx */
+      inb_el2(dep, EL2_EA2) != 0x8C)
+	return FALSE;		/* No Etherlink board at this address */
+
+  /* Map the 8390 back to lower I/O address range */
+  outb_el2(dep, EL2_CNTR, thin);
+
+  /* Setup shared memory addressing for 3c503 */
+  dep->de_linmem = ((membase & 0xC0) ? EL2_BASE_0D8000 : EL2_BASE_0C8000) +
+	((membase & 0xA0) ? (EL2_BASE_0CC000 - EL2_BASE_0C8000) : 0x0000);
+
+  /* Shared memory starts at 0x2000 (8kb window) */
+  dep->de_offset_page = (EL2_SM_START_PG * DP_PAGESIZE);
+  dep->de_linmem -= dep->de_offset_page;
+  dep->de_ramsize = (EL2_SM_STOP_PG - EL2_SM_START_PG) * DP_PAGESIZE;
+
+  /* Board initialization and stop functions */
+  dep->de_initf = el2_init;
+  dep->de_stopf = el2_stop;
+  return TRUE;
+}
+#endif				/* ENABLE_3C503 */
+
+/** 3c503.c **/
Index: /trunk/minix/drivers/dpeth/3c503.h
===================================================================
--- /trunk/minix/drivers/dpeth/3c503.h	(revision 9)
+++ /trunk/minix/drivers/dpeth/3c503.h	(revision 9)
@@ -0,0 +1,72 @@
+/*
+**  File:	3c503.h		Dec. 20, 1996
+**
+**  Author:	Giovanni Falzoni <gfalzoni@inwind.it>
+**
+**  Interface description for 3Com Etherlink II boards
+**
+**  $Log: 3c503.h,v $
+**  Revision 1.1  2005/06/29 10:16:46  beng
+**  Import of dpeth 3c501/3c509b/.. ethernet driver by
+**  Giovanni Falzoni <fgalzoni@inwind.it>.
+**
+**  Revision 2.0  2005/06/26 16:16:46  lsodgf0
+**  Initial revision for Minix 3.0.6
+**
+**  $Id: 3c503.h,v 1.1 2005/06/29 10:16:46 beng Exp $
+*/
+
+#define EL2_MEMTEST	0	/* Set to 1 for on board memory test */
+
+#define EL2_GA		0x0400	/* Offset of registers in Gate Array */
+
+/* EtherLink II card */
+
+#define EL2_STARTPG	(EL2_GA+0x00)	/* Start page matching DP_PSTARTPG */
+#define EL2_STOPPG	(EL2_GA+0x01)	/* Stop page matching DP_PSTOPPG   */
+#define EL2_DRQCNT	(EL2_GA+0x02)	/* DMA burst count                 */
+#define EL2_IOBASE	(EL2_GA+0x03)	/* I/O base jumpers (bit coded)    */
+#define EL2_MEMBASE	(EL2_GA+0x04)	/* Memory base jumpers (bit coded) */
+#define EL2_CFGR	(EL2_GA+0x05)	/* Configuration Register  for GA  */
+#define EL2_CNTR	(EL2_GA+0x06)	/* Control(write) and status(read) */
+#define EL2_STATUS	(EL2_GA+0x07)
+#define EL2_IDCFG	(EL2_GA+0x08)	/* Interrupt/DMA configuration reg */
+#define EL2_DMAAH	(EL2_GA+0x09)	/* DMA address register (High byte) */
+#define EL2_DMAAL	(EL2_GA+0x0A)	/* DMA address register (Low byte) */
+#define EL2_VP2		(EL2_GA+0x0B)	/* Vector pointer - set to         */
+#define EL2_VP1		(EL2_GA+0x0C)	/* reset address (0xFFFF:0)  */
+#define EL2_VP0		(EL2_GA+0x0D)	/* */
+#define EL2_FIFOH	(EL2_GA+0x0E)	/* FIFO for progr. I/O (High byte) */
+#define EL2_FIFOL	(EL2_GA+0x0F)	/* FIFO for progr. I/O (Low byte)  */
+
+#define EL2_EA0		0x00	/* Most significant byte of ethernet address */
+#define EL2_EA1		0x01
+#define EL2_EA2		0x02
+#define EL2_EA3		0x03
+#define EL2_EA4		0x04
+#define EL2_EA5		0x05	/* Least significant byte of ethernet address */
+
+/* Bits in EL2_CNTR register */
+#define ECNTR_RESET	0x01	/* Software Reset */
+#define ECNTR_THIN	0x02	/* Onboard transceiver enable */
+#define ECNTR_AUI	0x00	/* Onboard transceiver disable */
+#define ECNTR_SAPROM	0x04	/* Map the station address prom */
+
+/* Bits in EL2_CFGR register */
+#define ECFGR_NORM	0x49	/* Enable 8k shared memory, no DMA, TC int */
+#define ECFGR_IRQOFF	0xC9	/* As above, disable 8390 IRQ */
+
+/* Shared memory management parameters */
+#define EL2_SM_START_PG	0x20	/* First page of TX buffer */
+#define EL2_SM_STOP_PG	0x40	/* Last page +1 of RX ring */
+
+/* Physical addresses where an Etherlink board can be configured */
+#define EL2_BASE_0C8000	0x0C8000
+#define EL2_BASE_0CC000	0x0CC000
+#define EL2_BASE_0D8000	0x0D8000
+#define EL2_BASE_0DC000	0x0DC000
+
+#define inb_el2(dep,reg) (inb((dep)->de_base_port+(reg)))
+#define outb_el2(dep,reg,data) (outb((dep)->de_base_port+(reg),(data)))
+
+/** 3c503.h **/
Index: /trunk/minix/drivers/dpeth/3c509.c
===================================================================
--- /trunk/minix/drivers/dpeth/3c509.c	(revision 9)
+++ /trunk/minix/drivers/dpeth/3c509.c	(revision 9)
@@ -0,0 +1,595 @@
+/*
+**  File:	3c509.c		Jun. 01, 2000
+**
+**  Author:	Giovanni Falzoni <gfalzoni@inwind.it>
+**
+**  This file contains specific implementation of the ethernet
+**  device driver for 3Com Etherlink III (3c509) boards.
+**  NOTE: The board has to be setup to disable PnP and to assign
+**	  I/O base and IRQ.  The driver is for ISA bus only
+**
+**  $Id: 3c509.c,v 1.3 2005/08/05 19:08:43 beng Exp $
+*/
+
+#include "drivers.h"
+#include <minix/com.h>
+#include <net/hton.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+
+#include "dp.h"
+
+#if (ENABLE_3C509 == 1)
+
+#include "3c509.h"
+
+static const char *const IfNamesMsg[] = {
+	"10BaseT", "AUI", "unknown", "BNC",
+};
+
+/*
+**  Name:	void el3_update_stats(dpeth_t *dep)
+**  Function:	Reads statistic counters from board
+**  		and updates local counters.
+*/
+static void el3_update_stats(dpeth_t * dep)
+{
+
+  /* Disables statistics while reading and switches to the correct window */
+  outw_el3(dep, REG_CmdStatus, CMD_StatsDisable);
+  SetWindow(WNO_Statistics);
+
+  /* Reads everything, adding values to the local counters */
+  dep->de_stat.ets_sendErr += inb_el3(dep, REG_TxCarrierLost);	/* Reg. 00 */
+  dep->de_stat.ets_sendErr += inb_el3(dep, REG_TxNoCD);		/* Reg. 01 */
+  dep->de_stat.ets_collision += inb_el3(dep, REG_TxMultColl);	/* Reg. 02 */
+  dep->de_stat.ets_collision += inb_el3(dep, REG_TxSingleColl);	/* Reg. 03 */
+  dep->de_stat.ets_collision += inb_el3(dep, REG_TxLate);	/* Reg. 04 */
+  dep->de_stat.ets_recvErr += inb_el3(dep, REG_RxDiscarded);	/* Reg. 05 */
+  dep->de_stat.ets_packetT += inb_el3(dep, REG_TxFrames);	/* Reg. 06 */
+  dep->de_stat.ets_packetR += inb_el3(dep, REG_RxFrames);	/* Reg. 07 */
+  dep->de_stat.ets_transDef += inb_el3(dep, REG_TxDefer);	/* Reg. 08 */
+  dep->bytes_Rx += (unsigned) inw_el3(dep, REG_RxBytes);	/* Reg. 10 */
+  dep->bytes_Tx += (unsigned) inw_el3(dep, REG_TxBytes);	/* Reg. 12 */
+
+  /* Goes back to operating window and enables statistics */
+  SetWindow(WNO_Operating);
+  outw_el3(dep, REG_CmdStatus, CMD_StatsEnable);
+
+  return;
+}
+
+/*
+**  Name:	void el3_getstats(dpeth_t *dep)
+**  Function:	Reads statistics counters from board.
+*/
+static void el3_getstats(dpeth_t * dep)
+{
+
+  lock();
+  el3_update_stats(dep);
+  unlock();
+  return;
+}
+
+/*
+**  Name:	void el3_dodump(dpeth_t *dep)
+**  Function:	Dumps counter on screen (support for console display).
+*/
+static void el3_dodump(dpeth_t * dep)
+{
+
+  el3_getstats(dep);
+  return;
+}
+
+/*
+**  Name:	void el3_rx_mode(dpeth_t *dep)
+**  Function:	Initializes receiver mode
+*/
+static void el3_rx_mode(dpeth_t * dep)
+{
+
+  dep->de_recv_mode = FilterIndividual;
+  if (dep->de_flags & DEF_BROAD) dep->de_recv_mode |= FilterBroadcast;
+  if (dep->de_flags & DEF_MULTI) dep->de_recv_mode |= FilterMulticast;
+  if (dep->de_flags & DEF_PROMISC) dep->de_recv_mode |= FilterPromiscuous;
+
+  outw_el3(dep, REG_CmdStatus, CMD_RxReset);
+  outw_el3(dep, REG_CmdStatus, CMD_SetRxFilter | dep->de_recv_mode);
+  outw_el3(dep, REG_CmdStatus, CMD_RxEnable);
+
+  return;
+}
+
+/*
+**  Name:	void el3_reset(dpeth_t *dep)
+**  Function:	Reset function specific for Etherlink hardware.
+*/
+static void el3_reset(dpeth_t * dep)
+{
+
+  return;			/* Done */
+}
+
+/*
+**  Name:	void el3_write_fifo(dpeth_t * dep, int pktsize);
+**  Function:	Writes a packet from user area to board.
+**  Remark:	Writing a word/dword at a time may result faster
+**  		but is a lot more complicated. Let's go simpler way.
+*/
+static void el3_write_fifo(dpeth_t * dep, int pktsize)
+{
+  phys_bytes phys_user;
+  int bytes, ix = 0;
+  iovec_dat_t *iovp = &dep->de_write_iovec;
+  int padding = pktsize;
+
+  do {				/* Writes chuncks of packet from user buffers */
+
+	bytes = iovp->iod_iovec[ix].iov_size;	/* Size of buffer */
+	if (bytes > pktsize) bytes = pktsize;
+	/* Writes from user buffer to Tx FIFO */
+        outsb(dep->de_data_port, iovp->iod_proc_nr,
+              (void*)(iovp->iod_iovec[ix].iov_addr), bytes);
+	if (++ix >= IOVEC_NR) {	/* Next buffer of IO vector */
+		dp_next_iovec(iovp);
+		ix = 0;
+	}
+	/* Till packet done */
+  } while ((pktsize -= bytes) > 0);
+  while ((padding++ % sizeof(long)) != 0) outb(dep->de_data_port, 0x00);
+  return;
+}
+
+/*
+**  Name:	void el3_recv(dpeth_t *dep, int fromint, int size)
+**  Function:	Receive function.  Called from interrupt handler or
+**  		from main to unload recv. buffer (packet to client)
+*/
+static void el3_recv(dpeth_t *dep, int fromint, int size)
+{
+  buff_t *rxptr;
+
+  while ((dep->de_flags & DEF_READING) && (rxptr = dep->de_recvq_head)) {
+
+	lock();			/* Remove buffer from queue */
+	if (dep->de_recvq_tail == dep->de_recvq_head)
+		dep->de_recvq_head = dep->de_recvq_tail = NULL;
+	else
+		dep->de_recvq_head = rxptr->next;
+	unlock();
+
+	/* Copy buffer to user area and free it */
+	mem2user(dep, rxptr);
+
+	dep->de_read_s = rxptr->size;
+	dep->de_flags |= DEF_ACK_RECV;
+	dep->de_flags &= NOT(DEF_READING);
+
+	/* Return buffer to the idle pool */
+	free_buff(dep, rxptr);
+  }
+  return;
+}
+
+/*
+**  Name:	void el3_rx_complete(dpeth_t * dep);
+**  Function:	Upon receiving a packet, provides status checks
+**  		and if packet is OK copies it to local buffer.
+*/
+static void el3_rx_complete(dpeth_t * dep)
+{
+  short int RxStatus;
+  int pktsize;
+  buff_t *rxptr;
+
+  RxStatus = inw_el3(dep, REG_RxStatus);
+  pktsize = RxStatus & RXS_Length;	/* Mask off packet length */
+
+  if (RxStatus & RXS_Error) {
+
+	/* First checks for receiving errors */
+	RxStatus &= RXS_ErrType;
+	switch (RxStatus) {	/* Bad packet (see error type) */
+	    case RXS_Dribble:
+	    case RXS_Oversize:
+	    case RXS_Runt:	dep->de_stat.ets_recvErr += 1;	break;
+	    case RXS_Overrun:	dep->de_stat.ets_OVW += 1;	break;
+	    case RXS_Framing:	dep->de_stat.ets_frameAll += 1;	break;
+	    case RXS_CRC:	dep->de_stat.ets_CRCerr += 1;	break;
+	}
+
+  } else if ((rxptr = alloc_buff(dep, pktsize + sizeof(buff_t))) == NULL) {
+	/* Memory not available. Drop packet */
+	dep->de_stat.ets_fifoOver += 1;
+
+  } else {
+	/* Good packet.  Read it from FIFO */
+	insb(dep->de_data_port, SELF, rxptr->buffer, pktsize);
+	rxptr->next = NULL;
+	rxptr->size = pktsize;
+
+	lock();			/* Queue packet to receive queue */
+	if (dep->de_recvq_head == NULL)
+		dep->de_recvq_head = rxptr;
+	else
+		dep->de_recvq_tail->next = rxptr;
+	dep->de_recvq_tail = rxptr;
+	unlock();
+
+	/* Reply to pending Receive requests, if any */
+	el3_recv(dep, TRUE, pktsize);
+  }
+
+  /* Discard top packet from queue */
+  outw_el3(dep, REG_CmdStatus, CMD_RxDiscard);
+
+  return;
+}
+
+/*
+**  Name:	void el3_send(dpeth_t *dep, int count)
+**  Function:	Send function.  Called from main to transit a packet or
+**  		from interrupt handler when Tx FIFO gets available.
+*/
+static void el3_send(dpeth_t * dep, int from_int, int count)
+{
+  clock_t now;
+  int ix;
+  short int TxStatus;
+
+  getuptime(&now);
+  if ((dep->de_flags & DEF_XMIT_BUSY) &&
+      (now - dep->de_xmit_start) > 4) {
+
+	DEBUG(printf("3c509:  Transmitter timed out. Resetting ....\n");)
+	dep->de_stat.ets_sendErr += 1;
+	/* Resets and restars the transmitter */
+	outw_el3(dep, REG_CmdStatus, CMD_TxReset);
+	outw_el3(dep, REG_CmdStatus, CMD_TxEnable);
+	dep->de_flags &= NOT(DEF_XMIT_BUSY);
+  }
+  if (!(dep->de_flags & DEF_XMIT_BUSY)) {
+
+	/* Writes Transmitter preamble 1st Word (packet len, no ints) */
+	outw_el3(dep, REG_TxFIFO, count);
+	/* Writes Transmitter preamble 2nd Word (all zero) */
+	outw_el3(dep, REG_TxFIFO, 0);
+	/* Writes packet */
+	el3_write_fifo(dep, count);
+
+	getuptime(&dep->de_xmit_start);
+	dep->de_flags |= (DEF_XMIT_BUSY | DEF_ACK_SEND);
+	if (inw_el3(dep, REG_TxFree) > ETH_MAX_PACK_SIZE) {
+		/* Tx has enough room for a packet of maximum size */
+		dep->de_flags &= NOT(DEF_XMIT_BUSY | DEF_SENDING);
+	} else {
+		/* Interrupt driver when enough room is available */
+		outw_el3(dep, REG_CmdStatus, CMD_SetTxAvailable | ETH_MAX_PACK_SIZE);
+		dep->de_flags &= NOT(DEF_SENDING);
+	}
+
+	/* Pops Tx status stack */
+	for (ix = 4; --ix && (TxStatus = inb_el3(dep, REG_TxStatus)) > 0;) {
+		if (TxStatus & 0x38) dep->de_stat.ets_sendErr += 1;
+		if (TxStatus & 0x30)
+			outw_el3(dep, REG_CmdStatus, CMD_TxReset);
+		if (TxStatus & 0x3C)
+			outw_el3(dep, REG_CmdStatus, CMD_TxEnable);
+		outb_el3(dep, REG_TxStatus, 0);
+	}
+  }
+  return;
+}
+
+/*
+**  Name:	void el3_close(dpeth_t *dep)
+**  Function:	Stops board and makes it ready to shut down.
+*/
+static void el3_close(dpeth_t * dep)
+{
+
+  /* Disables statistics, Receiver and Transmitter */
+  outw_el3(dep, REG_CmdStatus, CMD_StatsDisable);
+  outw_el3(dep, REG_CmdStatus, CMD_RxDisable);
+  outw_el3(dep, REG_CmdStatus, CMD_TxDisable);
+
+  if (dep->de_if_port == BNC_XCVR) {
+	outw_el3(dep, REG_CmdStatus, CMD_StopIntXcvr);
+	/* milli_delay(5); */
+
+  } else if (dep->de_if_port == TP_XCVR) {
+	SetWindow(WNO_Diagnostics);
+	outw_el3(dep, REG_MediaStatus, inw_el3(dep, REG_MediaStatus) &
+		 NOT((MediaLBeatEnable | MediaJabberEnable)));
+	/* milli_delay(5); */
+  }
+  DEBUG(printf("%s: stopping Etherlink ... \n", dep->de_name));
+  /* Issues a global reset
+  outw_el3(dep, REG_CmdStatus, CMD_GlobalReset); */
+  sys_irqdisable(&dep->de_hook);	/* Disable interrupt */
+ 
+  return;
+}
+
+/*
+**  Name:	void el3_interrupt(dpeth_t *dep)
+**  Function:	Interrupt handler.  Acknwledges transmit interrupts
+**  		or unloads receive buffer to memory queue.
+*/
+static void el3_interrupt(dpeth_t * dep)
+{
+  int loop;
+  unsigned short isr;
+
+  for (loop = 5; loop > 0 && ((isr = inw_el3(dep, REG_CmdStatus)) &
+         (INT_Latch | INT_RxComplete | INT_UpdateStats)); loop -= 1) {
+
+	if (isr & INT_RxComplete)	/* Got a new packet */
+		el3_rx_complete(dep);
+
+	if (isr & INT_TxAvailable) {	/* Tx has room for big packets */
+		DEBUG(printf("3c509: got Tx interrupt, Status=0x%04x\n", isr);)
+		dep->de_flags &= NOT(DEF_XMIT_BUSY);
+		outw_el3(dep, REG_CmdStatus, CMD_Acknowledge | INT_TxAvailable);
+		if (dep->de_flags & DEF_SENDING)	/* Send pending */
+			el3_send(dep, TRUE, dep->de_send_s);
+	}
+	if (isr & (INT_AdapterFail | INT_RxEarly | INT_UpdateStats)) {
+
+		if (isr & INT_UpdateStats)	/* Empties statistics */
+			el3_getstats(dep);
+
+		if (isr & INT_RxEarly)	/* Not really used. Do nothing */
+			outw_el3(dep, REG_CmdStatus, CMD_Acknowledge | (INT_RxEarly));
+
+		if (isr & INT_AdapterFail) {
+			/* Adapter error. Reset and re-enable receiver */
+			DEBUG(printf("3c509: got Rx fail interrupt, Status=0x%04x\n", isr);)
+			el3_rx_mode(dep);
+			outw_el3(dep, REG_CmdStatus, CMD_Acknowledge | INT_AdapterFail);
+		}
+	}
+
+	/* Acknowledge interrupt */
+	outw_el3(dep, REG_CmdStatus, CMD_Acknowledge | (INT_Latch | INT_Requested));
+  }
+  return;
+}
+
+/*
+**  Name:	unsigned el3_read_eeprom(port_t port, unsigned address);
+**  Function:	Reads the EEPROM at specified address
+*/
+static unsigned el3_read_eeprom(port_t port, unsigned address)
+{
+  unsigned int result;
+  int bit;
+
+  address |= EL3_READ_EEPROM;
+  outb(port, address);
+  milli_delay(5);		/* Allows EEPROM reads */
+  for (result = 0, bit = 16; bit > 0; bit -= 1) {
+	result = (result << 1) | (inb(port) & 0x0001);
+  }
+  return result;
+}
+
+/*
+**  Name:	void el3_read_StationAddress(dpeth_t *dep)
+**  Function:	Reads station address from board
+*/
+static void el3_read_StationAddress(dpeth_t * dep)
+{
+  unsigned int ix, rc;
+
+  for (ix = EE_3COM_NODE_ADDR; ix < SA_ADDR_LEN;) {
+	/* Accesses with word No. */
+	rc = el3_read_eeprom(dep->de_id_port, ix / 2);
+	/* Swaps bytes of word */
+	dep->de_address.ea_addr[ix++] = (rc >> 8) & 0xFF;
+	dep->de_address.ea_addr[ix++] = rc & 0xFF;
+  }
+  return;
+}
+
+/*
+**  Name:	void el3_open(dpeth_t *dep)
+**  Function:	Initalizes board hardware and driver data structures.
+*/
+static void el3_open(dpeth_t * dep)
+{
+  unsigned int AddrCfgReg, ResCfgReg;
+  unsigned int ix;
+
+  el3_read_StationAddress(dep);	/* Get ethernet address */
+
+  /* Get address and resource configurations */
+  AddrCfgReg = el3_read_eeprom(dep->de_id_port, EE_ADDR_CFG);
+  ResCfgReg = el3_read_eeprom(dep->de_id_port, EE_RESOURCE_CFG);
+  outb(dep->de_id_port, EL3_ACTIVATE);	/* Activate the board */
+
+  /* Gets xcvr configuration */
+  dep->de_if_port = AddrCfgReg & EL3_CONFIG_XCVR_MASK;
+
+  AddrCfgReg = ((AddrCfgReg & EL3_CONFIG_IOBASE_MASK) << 4) + EL3_IO_BASE_ADDR;
+  if (AddrCfgReg != dep->de_base_port)
+	panic(dep->de_name, "Bad I/O port for Etherlink board", NO_NUM);
+
+  ResCfgReg >>= 12;
+  dep->de_irq &= NOT(DEI_DEFAULT);	/* Strips the default flag */
+  if (ResCfgReg != dep->de_irq) panic(dep->de_name, "Bad IRQ for Etherlink board", NO_NUM);
+
+  SetWindow(WNO_Setup);
+
+  /* Reset transmitter and receiver */
+  outw_el3(dep, REG_CmdStatus, CMD_TxReset);
+  outw_el3(dep, REG_CmdStatus, CMD_RxReset);
+
+  /* Enable the adapter */
+  outb_el3(dep, REG_CfgControl, EL3_EnableAdapter);
+  /* Disable Status bits */
+  outw_el3(dep, REG_CmdStatus, CMD_SetStatusEnab + 0x00);
+
+  /* Set "my own" address */
+  SetWindow(WNO_StationAddress);
+  for (ix = 0; ix < 6; ix += 1)
+	outb_el3(dep, REG_SA0_1 + ix, dep->de_address.ea_addr[ix]);
+
+  /* Start Transceivers as required */
+  if (dep->de_if_port == BNC_XCVR) {
+	/* Start internal transceiver for Coaxial cable */
+	outw_el3(dep, REG_CmdStatus, CMD_StartIntXcvr);
+	milli_delay(5);
+
+  } else if (dep->de_if_port == TP_XCVR) {
+	/* Start internal transceiver for Twisted pair cable */
+	SetWindow(WNO_Diagnostics);
+	outw_el3(dep, REG_MediaStatus,
+		 inw_el3(dep, REG_MediaStatus) | (MediaLBeatEnable | MediaJabberEnable));
+  }
+
+  /* Switch to the statistic window, and clear counts (by reading) */
+  SetWindow(WNO_Statistics);
+  for (ix = REG_TxCarrierLost; ix <= REG_TxDefer; ix += 1) inb_el3(dep, ix);
+  inw_el3(dep, REG_RxBytes);
+  inw_el3(dep, REG_TxBytes);
+
+  /* Switch to operating window for normal use */
+  SetWindow(WNO_Operating);
+
+  /* Receive individual address & broadcast. (Mofified later by rx_mode) */
+  outw_el3(dep, REG_CmdStatus, CMD_SetRxFilter |
+	 (FilterIndividual | FilterBroadcast));
+
+  /* Turn on statistics */
+  outw_el3(dep, REG_CmdStatus, CMD_StatsEnable);
+
+  /* Enable transmitter and receiver */
+  outw_el3(dep, REG_CmdStatus, CMD_TxEnable);
+  outw_el3(dep, REG_CmdStatus, CMD_RxEnable);
+
+  /* Enable all the status bits */
+  outw_el3(dep, REG_CmdStatus, CMD_SetStatusEnab | 0xFF);
+
+  /* Acknowledge all interrupts to clear adapter. Enable interrupts */
+  outw_el3(dep, REG_CmdStatus, CMD_Acknowledge | 0xFF);
+  outw_el3(dep, REG_CmdStatus, CMD_SetIntMask |
+    (INT_Latch | INT_TxAvailable | INT_RxComplete | INT_UpdateStats));
+
+  /* Ready to operate, sets the environment for eth_task */
+  dep->de_data_port = dep->de_base_port;
+  /* Allocates Rx/Tx buffers */
+  init_buff(dep, NULL);
+
+  /* Device specific functions */
+  dep->de_recvf = el3_recv;
+  dep->de_sendf = el3_send;
+  dep->de_flagsf = el3_rx_mode;
+  dep->de_resetf = el3_reset;
+  dep->de_getstatsf = el3_getstats;
+  dep->de_dumpstatsf = el3_dodump;
+  dep->de_interruptf = el3_interrupt;
+
+  printf("%s: Etherlink III (%s) at %X:%d, %s port - ",
+         dep->de_name, "3c509", dep->de_base_port, dep->de_irq,
+         IfNamesMsg[dep->de_if_port >> 14]);
+  for (ix = 0; ix < SA_ADDR_LEN; ix += 1)
+	printf("%02X%c", dep->de_address.ea_addr[ix],
+	       ix < SA_ADDR_LEN - 1 ? ':' : '\n');
+
+  return;			/* Done */
+}
+
+/*
+**  Name:	unsigned int el3_checksum(port_t port);
+**  Function:	Reads EEPROM and computes checksum.
+*/
+static unsigned short el3_checksum(port_t port)
+{
+  unsigned short rc, checksum, address;
+  unsigned char lo, hi;
+
+  for (checksum = address = 0; address < 15; address += 1) {
+	rc = el3_read_eeprom(port, address);
+	lo = rc & 0xFF;
+	hi = (rc >> 8) & 0xFF;
+	if ((address == EE_PROD_ID && (rc & EE_PROD_ID_MASK) != EL3_PRODUCT_ID) ||
+	    (address == EE_3COM_CODE && rc != EL3_3COM_CODE))
+		return address;
+	if (address == EE_ADDR_CFG ||
+	    address == EE_RESOURCE_CFG ||
+	    address == EE_SW_CONFIG_INFO) {
+		lo ^= hi;
+		hi = 0;
+	} else {
+		hi ^= lo;
+		lo = 0;
+	}
+	rc = ((unsigned) hi << 8) + lo;
+	checksum ^= rc;
+  }
+  rc = el3_read_eeprom(port, address);
+  return(checksum ^= rc);	/* If OK checksum is 0 */
+}
+
+/*
+**  Name:	void el3_write_id(port_t port);
+**  Function:	Writes the ID sequence to the board.
+*/
+static void el3_write_id(port_t port)
+{
+  int ix, pattern;
+
+  outb(port, 0);		/* Selects the ID port */
+  outb(port, 0);		/* Resets hardware pattern generator */
+  for (pattern = ix = 0x00FF; ix > 0; ix -= 1) {
+	outb(port, pattern);
+	pattern <<= 1;
+	pattern = (pattern & 0x0100) ? pattern ^ 0xCF : pattern;
+  }
+  return;
+}
+
+/*
+**  Name:	int el3_probe(dpeth_t *dep)
+**  Function:	Checks for presence of the board.
+*/
+PUBLIC int el3_probe(dpeth_t * dep)
+{
+  port_t id_port;
+
+  /* Don't ask me what is this for !! */
+  outb(0x0279, 0x02);	/* Select PnP config control register. */
+  outb(0x0A79, 0x02);	/* Return to WaitForKey state. */
+  /* Tests I/O ports in the 0x1xF range for a valid ID port */
+  for (id_port = 0x110; id_port < 0x200; id_port += 0x10) {
+	outb(id_port, 0x00);
+	outb(id_port, 0xFF);
+	if (inb(id_port) & 0x01) break;
+  }
+  if (id_port == 0x200) return 0;	/* No board responding */
+
+  el3_write_id(id_port);
+  outb(id_port, EL3_ID_GLOBAL_RESET);	/* Reset the board */
+  milli_delay(5);		/* Technical reference says 162 micro sec. */
+  el3_write_id(id_port);
+  outb(id_port, EL3_SET_TAG_REGISTER);
+  milli_delay(5);
+
+  dep->de_id_port = id_port;	/* Stores ID port No. */
+  dep->de_ramsize =		/* RAM size is meaningless */
+	dep->de_offset_page = 0;
+  dep->de_linmem = 0L;		/* Access is via I/O port  */
+
+  /* Device specific functions */
+  dep->de_initf = el3_open;
+  dep->de_stopf = el3_close;
+
+  return(el3_checksum(id_port) == 0);	/* Etherlink board found/not found */
+}
+
+#endif				/* ENABLE_3C509 */
+
+/** 3c509.c **/
Index: /trunk/minix/drivers/dpeth/3c509.h
===================================================================
--- /trunk/minix/drivers/dpeth/3c509.h	(revision 9)
+++ /trunk/minix/drivers/dpeth/3c509.h	(revision 9)
@@ -0,0 +1,164 @@
+/*
+**  File:	3c509.h		Jun. 01, 2000
+**
+**  Author:	Giovanni Falzoni <gfalzoni@inwind.it>
+**
+**  Interface description for 3Com Etherlink III board.
+**
+**  $Log: 3c509.h,v $
+**  Revision 1.1  2005/06/29 10:16:46  beng
+**  Import of dpeth 3c501/3c509b/.. ethernet driver by
+**  Giovanni Falzoni <fgalzoni@inwind.it>.
+**
+**  Revision 2.0  2005/06/26 16:16:46  lsodgf0
+**  Initial revision for Minix 3.0.6
+**
+**  $Id: 3c509.h,v 1.1 2005/06/29 10:16:46 beng Exp $
+*/
+
+/* Command codes */
+#define	CMD_GlobalReset		0x0000	/* resets adapter (power up status) */
+#define	CMD_SelectWindow       (1<<11)	/* select register window */
+#define	CMD_StartIntXcvr       (2<<11)	/* start internal transciver */
+#define	CMD_RxDisable	       (3<<11)	/* rx disable */
+#define	CMD_RxEnable	       (4<<11)	/* rx enable */
+#define	CMD_RxReset	       (5<<11)	/* rx reset */
+#define	CMD_RxDiscard	       (8<<11)	/* rx discard top packet */
+#define	CMD_TxEnable	       (9<<11)	/* tx enable */
+#define	CMD_TxDisable	      (10<<11)	/* tx disable */
+#define	CMD_TxReset	      (11<<11)	/* tx reset */
+#define	CMD_Acknowledge	      (13<<11)	/* acknowledge interrupt */
+#define	CMD_SetIntMask	      (14<<11)	/* set interrupt mask */
+#define	CMD_SetStatusEnab     (15<<11)	/* set read zero mask */
+#define	CMD_SetRxFilter	      (16<<11)	/* set rx filter */
+#define	CMD_SetTxAvailable    (18<<11)	/* set tx available threshold */
+#define	CMD_StatsEnable	      (21<<11)	/* statistics enable */
+#define	CMD_StatsDisable      (22<<11)	/* statistics disable */
+#define	CMD_StopIntXcvr	      (23<<11)	/* start internal transciver */
+
+/* Status register bits (INT for interrupt sources, ST for the rest) */
+#define	INT_Latch		0x0001	/* interrupt latch */
+#define	INT_AdapterFail		0x0002	/* adapter failure */
+#define	INT_TxComplete		0x0004	/* tx complete */
+#define	INT_TxAvailable		0x0008	/* tx available */
+#define	INT_RxComplete	 	0x0010	/* rx complete */
+#define	INT_RxEarly		0x0020	/* rx early */
+#define	INT_Requested		0x0040	/* interrupt requested */
+#define	INT_UpdateStats		0x0080	/* update statistics */
+
+/* Rx Status register bits */
+#define	RXS_Error		0x4000	/* error in packet */
+#define	RXS_Length		0x07FF	/* bytes in RxFIFO */
+#define	RXS_ErrType		0x3800	/* Rx error type, bit 13-11 */
+#define	RXS_Overrun		0x0000	/* overrun error */
+#define	RXS_Oversize		0x0800	/* oversize packet error */
+#define	RXS_Dribble		0x1000	/* dribble bit (not an error) */
+#define	RXS_Runt		0x1800	/* runt packet error */
+#define	RXS_Framing		0x2000	/* framing error */
+#define	RXS_CRC			0x2800	/* CRC error */
+
+/* Tx Status register bits */
+
+/* Window Numbers */
+#define	WNO_Setup		0x0000	/* setup/configuration */
+#define	WNO_Operating		0x0001	/* operating set */
+#define	WNO_StationAddress	0x0002	/* station address setup/read */
+#define	WNO_Diagnostics		0x0004	/* diagnostics */
+#define	WNO_Statistics		0x0006	/* statistics */
+
+/* Register offsets - Window 1 (WNO_Operating) */
+#define	REG_CmdStatus		0x000E	/* command/status */
+#define	REG_TxFree		0x000C	/* free transmit bytes */
+#define	REG_TxStatus		0x000B	/* transmit status (byte) */
+#define	REG_RxStatus		0x0008	/* receive status */
+#define	REG_RxFIFO		0x0000	/* RxFIFO read */
+#define	REG_TxFIFO		0x0000	/* TxFIFO write */
+
+/* Register offsets - Window 0 (WNO_Setup) */
+#define	REG_CfgControl		0x0004	/* configuration control */
+
+/* Register offsets - Window 2 (WNO_StationAddress) */
+#define	REG_SA0_1		0x0000	/* station address bytes 0,1 */
+
+/* Register offsets - Window 3 (WNO_FIFO) */
+
+/* Register offsets - Window 4 (WNO_Diagnostics) */
+#define	REG_MediaStatus		0x000A	/* media type/status */
+
+/* Register offsets - Window 5 (WNO_Readable) */
+
+/* Register offsets - Window 6 (WNO_Statistics) */
+#define	REG_TxBytes		0x000C	/* tx bytes ok */
+#define	REG_RxBytes		0x000A	/* rx bytes ok */
+#define	REG_TxDefer		0x0008	/* tx frames deferred (byte) */
+#define	REG_RxFrames		0x0007	/* rx frames ok (byte) */
+#define	REG_TxFrames		0x0006	/* tx frames ok (byte) */
+#define	REG_RxDiscarded		0x0005	/* rx frames discarded (byte) */
+#define	REG_TxLate		0x0004	/* tx frames late coll. (byte) */
+#define	REG_TxSingleColl	0x0003	/* tx frames one coll. (byte) */
+#define	REG_TxMultColl		0x0002	/* tx frames mult. coll. (byte) */
+#define	REG_TxNoCD		0x0001	/* tx frames no CDheartbt (byte) */
+#define	REG_TxCarrierLost	0x0000	/* tx frames carrier lost (byte) */
+
+/* Various command arguments */
+
+#define	FilterIndividual	0x0001	/* individual address */
+#define	FilterMulticast		0x0002	/* multicast/group addresses */
+#define	FilterBroadcast		0x0004	/* broadcast address */
+#define	FilterPromiscuous	0x0008	/* promiscuous mode */
+
+/* Resource Configuration Register bits */
+#define	EL3_CONFIG_IRQ_MASK	0xF000
+
+/* Address Configuration Register bits */
+#define	EL3_CONFIG_XCVR_MASK	0xC000
+#define	EL3_CONFIG_IOBASE_MASK	0x001F
+
+#define	TP_XCVR			0x0000
+#define	BNC_XCVR		0xC000
+#define	AUI_XCVR		0x4000
+
+#define	EL3_IO_BASE_ADDR	0x200
+
+/* Transmit Preamble */
+
+/* Bits in various diagnostics registers */
+#define	MediaLBeatEnable	0x0080	/* link beat enable (TP) */
+#define	MediaJabberEnable	0x0040	/* jabber enable (TP) */
+
+/* Board identification codes, byte swapped in Rev 0 */
+#define	EL3_3COM_CODE		0x6D50	/* EISA manufacturer code */
+#define	EL3_PRODUCT_ID		0x9050	/* Product ID for ISA board */
+
+/* EEProm access */
+#define	EE_3COM_NODE_ADDR	0x00
+#define	EE_PROD_ID		0x03
+#define	EE_MANUFACTURING_DATA	0x04
+#define	EE_3COM_CODE		0x07
+#define	EE_ADDR_CFG		0x08
+#define	EE_RESOURCE_CFG		0x09
+#define	EE_SW_CONFIG_INFO	0x0D
+#define	EE_PROD_ID_MASK		0xF0FF	/* Mask off revision nibble */
+
+/* Contention logic */
+#define	EL3_READ_EEPROM		0x80
+#define	EL3_ID_GLOBAL_RESET	0xC0
+#define	EL3_SET_TAG_REGISTER	0xD0
+#define	EL3_ACTIVATE_AND_SET_IO	0xE0
+#define	EL3_ACTIVATE		0xFF
+
+/* Software Configuration Register bits */
+
+/* Configuration Control Register bits */
+#define	EL3_EnableAdapter	0x01
+
+/* EL3 access macros */
+#define inb_el3(dep,reg) (inb((dep)->de_base_port+(reg)))
+#define inw_el3(dep,reg) (inw((dep)->de_base_port+(reg)))
+#define outb_el3(dep,reg,data) (outb((dep)->de_base_port+(reg),(data)))
+#define outw_el3(dep,reg,data) (outw((dep)->de_base_port+(reg),(data)))
+
+#define SetWindow(win)  \
+  outw(dep->de_base_port+REG_CmdStatus,CMD_SelectWindow|(win))
+
+/** 3c509.h **/
Index: /trunk/minix/drivers/dpeth/8390.c
===================================================================
--- /trunk/minix/drivers/dpeth/8390.c	(revision 9)
+++ /trunk/minix/drivers/dpeth/8390.c	(revision 9)
@@ -0,0 +1,737 @@
+/*
+**  File:	8390.c		May  02, 2000
+**
+**  Author:	Giovanni Falzoni <gfalzoni@inwind.it>
+**
+**  This file contains an ethernet device driver for NICs
+**  equipped with the National Semiconductor NS 8390 chip.
+**  It has to be associated with the board specific driver.
+**  Rewritten from Minix 2.0.0 ethernet driver dp8390.c
+**  to extract the NS 8390 common functions.
+**
+**  $Id: 8390.c,v 1.4 2005/09/04 18:52:16 beng Exp $
+*/
+
+#include "drivers.h"
+#include <minix/com.h>
+#include <net/hton.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include "dp.h"
+
+#if (ENABLE_DP8390 == 1)
+
+#define PIO16	0	/* NOTE: pio 16 functions missing */
+
+#include "8390.h"
+
+#define	sys_nic2mem(srcOffs,dstProc,dstOffs,length) \
+	sys_vircopy(SELF,dep->de_memsegm,(vir_bytes)(srcOffs),\
+		    (dstProc),D,(vir_bytes)(dstOffs),length)
+#define	sys_user2nic(srcProc,srcOffs,dstOffs,length) \
+	sys_vircopy((srcProc),D,(vir_bytes)(srcOffs),\
+		    SELF,dep->de_memsegm,(vir_bytes)(dstOffs),length)
+
+static const char RdmaErrMsg[] = "remote dma failed to complete";
+
+/*
+**  Name:	void ns_rw_setup(dpeth_t *dep, int mode, int size, u16_t offset);
+**  Function:	Sets the board for reading/writing.
+*/
+static void ns_rw_setup(dpeth_t *dep, int mode, int size, u16_t offset)
+{
+
+  if (mode == CR_DM_RW) outb_reg0(dep, DP_ISR, ISR_RDC);
+  outb_reg0(dep, DP_RBCR0, size & 0xFF);
+  outb_reg0(dep, DP_RBCR1, (size >> 8) & 0xFF);
+  outb_reg0(dep, DP_RSAR0, offset & 0xFF);
+  outb_reg0(dep, DP_RSAR1, (offset >> 8) & 0xFF);
+  mode |= (CR_PS_P0 | CR_STA);
+  outb_reg0(dep, DP_CR, mode);
+  return;
+}
+
+/*
+**  Name:	void ns_start_xmit(dpeth_t *dep, int size, int pageno);
+**  Function:	Sets the board for for transmitting and fires it.
+*/
+static void ns_start_xmit(dpeth_t * dep, int size, int pageno)
+{
+
+  outb_reg0(dep, DP_TPSR, pageno);
+  outb_reg0(dep, DP_TBCR1, size >> 8);
+  outb_reg0(dep, DP_TBCR0, size & 0xFF);
+  outb_reg0(dep, DP_CR, CR_NO_DMA | CR_STA | CR_TXP);	/* Fires transmission */
+  return;
+}
+
+/*
+**  Name:	void mem_getblock(dpeth_t *dep, u16_t offset,
+**  				int size, void *dst)
+**  Function:	Reads a block of packet from board (shared memory).
+*/
+static void mem_getblock(dpeth_t *dep, u16_t offset, int size, void *dst)
+{
+
+  sys_nic2mem(dep->de_linmem + offset, SELF, dst, size);
+  return;
+}
+
+/*
+**  Name:	void mem_nic2user(dpeth_t *dep, int pageno, int pktsize);
+**  Function:	Copies a packet from board to user area (shared memory).
+*/
+static void mem_nic2user(dpeth_t * dep, int pageno, int pktsize)
+{
+  phys_bytes offset, phys_user;
+  iovec_dat_t *iovp = &dep->de_read_iovec;
+  int bytes, ix = 0;
+
+  /* Computes shared memory address (skipping receive header) */
+  offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t);
+
+  do {				/* Reads chuncks of packet into user area */
+
+	bytes = iovp->iod_iovec[ix].iov_size;	/* Size of a chunck */
+	if (bytes > pktsize) bytes = pktsize;
+
+	/* Reads from board to user area */
+	if ((offset + bytes) > (dep->de_stoppage * DP_PAGESIZE)) {
+
+		/* Circular buffer wrap-around */
+		bytes = dep->de_stoppage * DP_PAGESIZE - offset;
+		sys_nic2mem(dep->de_linmem + offset, iovp->iod_proc_nr,
+			    iovp->iod_iovec[ix].iov_addr, bytes);
+		pktsize -= bytes;
+		phys_user += bytes;
+		bytes = iovp->iod_iovec[ix].iov_size - bytes;
+		if (bytes > pktsize) bytes = pktsize;
+		offset = dep->de_startpage * DP_PAGESIZE;
+	}
+	sys_nic2mem(dep->de_linmem + offset, iovp->iod_proc_nr,
+		    iovp->iod_iovec[ix].iov_addr, bytes);
+	offset += bytes;
+
+	if (++ix >= IOVEC_NR) {	/* Next buffer of IO vector */
+		dp_next_iovec(iovp);
+		ix = 0;
+	}
+	/* Till packet done */
+  } while ((pktsize -= bytes) > 0);
+  return;
+}
+
+/*
+**  Name:	void mem_user2nic(dpeth_t *dep, int pageno, int pktsize)
+**  Function:	Copies a packet from user area to board (shared memory).
+*/
+static void mem_user2nic(dpeth_t *dep, int pageno, int pktsize)
+{
+  phys_bytes offset, phys_user;
+  iovec_dat_t *iovp = &dep->de_write_iovec;
+  int bytes, ix = 0;
+
+  /* Computes shared memory address */
+  offset = pageno * DP_PAGESIZE;
+
+  do {				/* Reads chuncks of packet from user area */
+
+	bytes = iovp->iod_iovec[ix].iov_size;	/* Size of chunck */
+	if (bytes > pktsize) bytes = pktsize;
+
+	/* Reads from user area to board (shared memory) */
+	sys_user2nic(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_addr, 
+		     dep->de_linmem + offset, bytes);
+	offset += bytes;
+
+	if (++ix >= IOVEC_NR) {	/* Next buffer of IO vector */
+		dp_next_iovec(iovp);
+		ix = 0;
+	}
+	/* Till packet done */
+  } while ((pktsize -= bytes) > 0);
+  return;
+}
+
+/*
+**  Name:	void pio_getblock(dpeth_t *dep, u16_t offset,
+**  				int size, void *dst)
+**  Function:	Reads a block of packet from board (Prog. I/O).
+*/
+static void pio_getblock(dpeth_t *dep, u16_t offset, int size, void *dst)
+{
+
+  /* Sets up board for reading */
+  ns_rw_setup(dep, CR_DM_RR, size, offset);
+
+#if PIO16 == 0
+  insb(dep->de_data_port, SELF, dst, size);
+#else
+  if (dep->de_16bit == TRUE) {
+	insw(dep->de_data_port, dst, size);
+  } else {
+	insb(dep->de_data_port, dst, size);
+  }
+#endif
+  return;
+}
+
+/*
+**  Name:	void pio_nic2user(dpeth_t *dep, int pageno, int pktsize)
+**  Function:	Copies a packet from board to user area (Prog. I/O).
+*/
+static void pio_nic2user(dpeth_t *dep, int pageno, int pktsize)
+{
+  phys_bytes phys_user;
+  iovec_dat_t *iovp = &dep->de_read_iovec;
+  unsigned offset; int bytes, ix = 0;
+
+  /* Computes memory address (skipping receive header) */
+  offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t);
+  /* Sets up board for reading */
+  ns_rw_setup(dep, CR_DM_RR, ((offset + pktsize) > (dep->de_stoppage * DP_PAGESIZE)) ?
+	(dep->de_stoppage * DP_PAGESIZE) - offset : pktsize, offset);
+
+  do {				/* Reads chuncks of packet into user area */
+
+	bytes = iovp->iod_iovec[ix].iov_size;	/* Size of a chunck */
+	if (bytes > pktsize) bytes = pktsize;
+
+	if ((offset + bytes) > (dep->de_stoppage * DP_PAGESIZE)) {
+
+		/* Circular buffer wrap-around */
+		bytes = dep->de_stoppage * DP_PAGESIZE - offset;
+		insb(dep->de_data_port, iovp->iod_proc_nr, (void*)(iovp->iod_iovec[ix].iov_addr), bytes);
+		pktsize -= bytes;
+		iovp->iod_iovec[ix].iov_addr += bytes;
+		bytes = iovp->iod_iovec[ix].iov_size - bytes;
+		if (bytes > pktsize) bytes = pktsize;
+		offset = dep->de_startpage * DP_PAGESIZE;
+  		ns_rw_setup(dep, CR_DM_RR, pktsize, offset);
+	}
+	insb(dep->de_data_port, iovp->iod_proc_nr, (void*)(iovp->iod_iovec[ix].iov_addr), bytes);
+	offset += bytes;
+
+	if (++ix >= IOVEC_NR) {	/* Next buffer of IO vector */
+		dp_next_iovec(iovp);
+		ix = 0;
+	}
+	/* Till packet done */
+  } while ((pktsize -= bytes) > 0);
+  return;
+}
+
+/*
+**  Name:	void pio_user2nic(dpeth_t *dep, int pageno, int pktsize)
+**  Function:	Copies a packet from user area to board (Prog. I/O).
+*/
+static void pio_user2nic(dpeth_t *dep, int pageno, int pktsize)
+{
+  phys_bytes phys_user;
+  iovec_dat_t *iovp = &dep->de_write_iovec;
+  int bytes, ix = 0;
+
+  /* Sets up board for writing */
+  ns_rw_setup(dep, CR_DM_RW, pktsize, pageno * DP_PAGESIZE);
+  
+  do {				/* Reads chuncks of packet from user area */
+
+	bytes = iovp->iod_iovec[ix].iov_size;	/* Size of chunck */
+	if (bytes > pktsize) bytes = pktsize;
+	outsb(dep->de_data_port, iovp->iod_proc_nr,
+	      (void*)(iovp->iod_iovec[ix].iov_addr), bytes);
+
+	if (++ix >= IOVEC_NR) {	/* Next buffer of I/O vector */
+		dp_next_iovec(iovp);
+		ix = 0;
+	}
+	/* Till packet done */
+  } while ((pktsize -= bytes) > 0);
+
+  for (ix = 0; ix < 100; ix += 1) {
+	if (inb_reg0(dep, DP_ISR) & ISR_RDC) break;
+  }
+  if (ix == 100) {
+	panic(dep->de_name, RdmaErrMsg, NO_NUM);
+  }
+  return;
+}
+
+/*
+**  Name:	void ns_stats(dpeth_t * dep)
+**  Function:	Updates counters reading from device
+*/
+static void ns_stats(dpeth_t * dep)
+{
+
+  dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
+  dep->de_stat.ets_recvErr += inb_reg0(dep, DP_CNTR1);
+  dep->de_stat.ets_fifoOver += inb_reg0(dep, DP_CNTR2);
+  return;
+}
+
+/*
+**  Name:	void ns_dodump(dpeth_t * dep)
+**  Function:	Displays statistics (a request from F5 key).
+*/
+static void ns_dodump(dpeth_t * dep)
+{
+
+  ns_stats(dep);		/* Forces reading fo counters from board */
+  return;
+}
+
+/*
+**  Name:	void ns_reinit(dpeth_t *dep)
+**  Function:	Updates receiver configuration.
+*/
+static void ns_reinit(dpeth_t * dep)
+{
+  int dp_reg = 0;
+
+  if (dep->de_flags & DEF_PROMISC) dp_reg |= RCR_AB | RCR_PRO | RCR_AM;
+  if (dep->de_flags & DEF_BROAD) dp_reg |= RCR_AB;
+  if (dep->de_flags & DEF_MULTI) dp_reg |= RCR_AM;
+  outb_reg0(dep, DP_CR, CR_PS_P0);
+  outb_reg0(dep, DP_RCR, dp_reg);
+  return;
+}
+
+/*
+**  Name:	void ns_send(dpeth_t * dep, int from_int, int size)
+**  Function:	Transfers packet to device and starts sending.
+*/
+static void ns_send(dpeth_t * dep, int from_int, int size)
+{
+  int queue;
+
+  if (queue = dep->de_sendq_head, dep->de_sendq[queue].sq_filled) {
+	if (from_int) panic(dep->de_name, "should not be sending ", NO_NUM);
+	dep->de_send_s = size;
+	return;
+  }
+  (dep->de_user2nicf) (dep, dep->de_sendq[queue].sq_sendpage, size);
+  dep->bytes_Tx += (long) size;
+  dep->de_sendq[queue].sq_filled = TRUE;
+  dep->de_flags |= (DEF_XMIT_BUSY | DEF_ACK_SEND);
+  if (dep->de_sendq_tail == queue) {	/* there it goes.. */
+	ns_start_xmit(dep, size, dep->de_sendq[queue].sq_sendpage);
+  } else
+	dep->de_sendq[queue].sq_size = size;
+
+  if (++queue == dep->de_sendq_nr) queue = 0;
+  dep->de_sendq_head = queue;
+  dep->de_flags &= NOT(DEF_SENDING);
+
+  return;
+}
+
+/*
+**  Name:	void ns_reset(dpeth_t *dep)
+**  Function:	Resets device.
+*/
+static void ns_reset(dpeth_t * dep)
+{
+  int ix;
+
+  /* Stop chip */
+  outb_reg0(dep, DP_CR, CR_STP | CR_NO_DMA);
+  outb_reg0(dep, DP_RBCR0, 0);
+  outb_reg0(dep, DP_RBCR1, 0);
+  for (ix = 0; ix < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); ix += 1)
+	 /* Do nothing */ ;
+  outb_reg0(dep, DP_TCR, TCR_1EXTERNAL | TCR_OFST);
+  outb_reg0(dep, DP_CR, CR_STA | CR_NO_DMA);
+  outb_reg0(dep, DP_TCR, TCR_NORMAL | TCR_OFST);
+
+  /* Acknowledge the ISR_RDC (remote dma) interrupt. */
+  for (ix = 0; ix < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); ix += 1)
+	 /* Do nothing */ ;
+  outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & NOT(ISR_RDC));
+
+  /* Reset the transmit ring. If we were transmitting a packet, we
+   * pretend that the packet is processed. Higher layers will
+   * retransmit if the packet wasn't actually sent. */
+  dep->de_sendq_head = dep->de_sendq_tail = 0;
+  for (ix = 0; ix < dep->de_sendq_nr; ix++)
+	dep->de_sendq[ix].sq_filled = FALSE;
+  ns_send(dep, TRUE, dep->de_send_s);
+  return;
+}
+
+/*
+**  Name:	void ns_recv(dpeth_t *dep, int fromint, int size)
+**  Function:	Gets a packet from device
+*/
+static void ns_recv(dpeth_t *dep, int fromint, int size)
+{
+  dp_rcvhdr_t header;
+  dp_rcvhdr_t dummy;
+  unsigned pageno, curr, next;
+  vir_bytes length;
+  int packet_processed = FALSE;
+#ifdef ETH_IGN_PROTO
+  u16_t eth_type;
+#endif
+
+  pageno = inb_reg0(dep, DP_BNRY) + 1;
+  if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
+
+  do {
+	/* */
+	outb_reg0(dep, DP_CR, CR_PS_P1);
+	curr = inb_reg1(dep, DP_CURR);
+	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_NO_DMA | CR_STA);
+
+	if (curr == pageno) break;
+
+	(dep->de_getblockf) (dep, pageno * DP_PAGESIZE, sizeof(header), &header);
+#ifdef ETH_IGN_PROTO
+	(dep->de_getblockf) (dep, pageno * DP_PAGESIZE + sizeof(header) + 2 * sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
+#endif
+	length = (header.dr_rbcl | (header.dr_rbch << 8)) - sizeof(dp_rcvhdr_t);
+	next = header.dr_next;
+
+	if (length < ETH_MIN_PACK_SIZE || length > ETH_MAX_PACK_SIZE) {
+		printf("%s: packet with strange length arrived: %d\n", dep->de_name, length);
+		dep->de_stat.ets_recvErr += 1;
+		next = curr;
+
+	} else if (next < dep->de_startpage || next >= dep->de_stoppage) {
+		printf("%s: strange next page\n", dep->de_name);
+		dep->de_stat.ets_recvErr += 1;
+		next = curr;
+
+#ifdef ETH_IGN_PROTO
+	} else if (eth_type == eth_ign_proto) {
+		/* Hack: ignore packets of a given protocol */
+		static int first = TRUE;
+		if (first) {
+			first = FALSE;
+			printf("%s: dropping proto %04x packet\n", dep->de_name, ntohs(eth_ign_proto));
+		}
+		next = curr;
+#endif
+	} else if (header.dr_status & RSR_FO) {
+		/* This is very serious, issue a warning and reset buffers */
+		printf("%s: fifo overrun, resetting receive buffer\n", dep->de_name);
+		dep->de_stat.ets_fifoOver += 1;
+		next = curr;
+
+	} else if ((header.dr_status & RSR_PRX) && (dep->de_flags & DEF_ENABLED)) {
+
+		if (!(dep->de_flags & DEF_READING)) break;
+
+		(dep->de_nic2userf) (dep, pageno, length);
+		dep->de_read_s = length;
+		dep->de_flags |= DEF_ACK_RECV;
+		dep->de_flags &= NOT(DEF_READING);
+		packet_processed = TRUE;
+	}
+	dep->bytes_Rx += (long) length;
+	dep->de_stat.ets_packetR += 1;
+	outb_reg0(dep, DP_BNRY, (next == dep->de_startpage ? dep->de_stoppage : next) - 1);
+	pageno = next;
+
+  } while (!packet_processed);
+#if 0
+  if ((dep->de_flags & (DEF_READING | DEF_STOPPED)) == (DEF_READING | DEF_STOPPED))
+	/* The chip is stopped, and all arrived packets delivered */
+	(*dep->de_resetf) (dep);
+  dep->de_flags &= NOT(DEF_STOPPED);
+#endif
+  return;
+}
+
+/*
+**  Name:	void ns_interrupt(dpeth_t * dep)
+**  Function:	Handles interrupt.
+*/
+static void ns_interrupt(dpeth_t * dep)
+{
+  int isr, tsr;
+  int size, queue;
+
+  while ((isr = inb_reg0(dep, DP_ISR)) != 0) {
+
+	outb_reg0(dep, DP_ISR, isr);
+	if (isr & (ISR_PTX | ISR_TXE)) {
+
+		tsr = inb_reg0(dep, DP_TSR);
+		if (tsr & TSR_PTX) {
+			dep->de_stat.ets_packetT++;
+		}
+		if (tsr & TSR_COL) dep->de_stat.ets_collision++;
+		if (tsr & (TSR_ABT | TSR_FU)) {
+			dep->de_stat.ets_fifoUnder++;
+		}
+		if ((isr & ISR_TXE) || (tsr & (TSR_CRS | TSR_CDH | TSR_OWC))) {
+			printf("%s: got send Error (0x%02X)\n", dep->de_name, tsr);
+			dep->de_stat.ets_sendErr++;
+		}
+		queue = dep->de_sendq_tail;
+
+		if (!(dep->de_sendq[queue].sq_filled)) {	/* Hardware bug? */
+			printf("%s: transmit interrupt, but not sending\n", dep->de_name);
+			continue;
+		}
+		dep->de_sendq[queue].sq_filled = FALSE;
+		if (++queue == dep->de_sendq_nr) queue = 0;
+		dep->de_sendq_tail = queue;
+		if (dep->de_sendq[queue].sq_filled) {
+			ns_start_xmit(dep, dep->de_sendq[queue].sq_size,
+				dep->de_sendq[queue].sq_sendpage);
+		}
+		if (dep->de_flags & DEF_SENDING) {
+			ns_send(dep, TRUE, dep->de_send_s);
+		}
+	}
+	if (isr & ISR_PRX) {
+		ns_recv(dep, TRUE, 0);
+	}
+	if (isr & ISR_RXE) {
+		printf("%s: got recv Error (0x%04X)\n", dep->de_name, inb_reg0(dep, DP_RSR));
+		dep->de_stat.ets_recvErr++;
+	}
+	if (isr & ISR_CNT) {
+		dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
+		dep->de_stat.ets_recvErr += inb_reg0(dep, DP_CNTR1);
+		dep->de_stat.ets_fifoOver += inb_reg0(dep, DP_CNTR2);
+	}
+	if (isr & ISR_OVW) {
+		printf("%s: got overwrite warning\n", dep->de_name);
+	}
+	if (isr & ISR_RDC) {
+		/* Nothing to do */
+	}
+	if (isr & ISR_RST) {
+		/* This means we got an interrupt but the ethernet
+		 * chip is shutdown. We set the flag DEF_STOPPED, and
+		 * continue processing arrived packets. When the
+		 * receive buffer is empty, we reset the dp8390. */
+		printf("%s: network interface stopped\n", dep->de_name);
+		dep->de_flags |= DEF_STOPPED;
+		break;
+	}
+  }
+  if ((dep->de_flags & (DEF_READING | DEF_STOPPED)) == (DEF_READING | DEF_STOPPED)) {
+
+	/* The chip is stopped, and all arrived packets delivered */
+	ns_reset(dep);
+	dep->de_flags &= NOT(DEF_STOPPED);
+  }
+  return;
+}
+
+/*
+**  Name:	void ns_init(dpeth_t *dep)
+**  Function:	Initializes the NS 8390
+*/
+void ns_init(dpeth_t * dep)
+{
+  int dp_reg;
+  int ix;
+
+  /* NS8390 initialization (as recommended in National Semiconductor specs) */
+  outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_NO_DMA);	/* 0x21 */
+#if PIO16 == 0
+  outb_reg0(dep, DP_DCR, (DCR_BYTEWIDE | DCR_LTLENDIAN | DCR_8BYTES | DCR_BMS));
+#else
+  outb_reg0(dep, DP_DCR, (((dep->de_16bit) ? DCR_WORDWIDE : DCR_BYTEWIDE) |
+			DCR_LTLENDIAN | DCR_8BYTES | DCR_BMS));
+#endif
+  outb_reg0(dep, DP_RBCR0, 0);
+  outb_reg0(dep, DP_RBCR1, 0);
+  outb_reg0(dep, DP_RCR, RCR_MON);	/* Sets Monitor mode */
+  outb_reg0(dep, DP_TCR, TCR_INTERNAL);	/* Sets Loopback mode 1 */
+  outb_reg0(dep, DP_PSTART, dep->de_startpage);
+  outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
+  outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
+  outb_reg0(dep, DP_ISR, 0xFF);	/* Clears Interrupt Status Register */
+  outb_reg0(dep, DP_IMR, 0);	/* Clears Interrupt Mask Register */
+
+  /* Copies station address in page 1 registers */
+  outb_reg0(dep, DP_CR, CR_PS_P1 | CR_NO_DMA);	/* Selects Page 1 */
+  for (ix = 0; ix < SA_ADDR_LEN; ix += 1)	/* Initializes address */
+	outb_reg1(dep, DP_PAR0 + ix, dep->de_address.ea_addr[ix]);
+  for (ix = DP_MAR0; ix <= DP_MAR7; ix += 1)	/* Initializes address */
+	outb_reg1(dep, ix, 0xFF);
+
+  outb_reg1(dep, DP_CURR, dep->de_startpage);
+  outb_reg1(dep, DP_CR, CR_PS_P0 | CR_NO_DMA);	/* Selects Page 0 */
+
+  inb_reg0(dep, DP_CNTR0);	/* Resets counters by reading them */
+  inb_reg0(dep, DP_CNTR1);
+  inb_reg0(dep, DP_CNTR2);
+
+  dp_reg = IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE;
+  outb_reg0(dep, DP_ISR, 0xFF);	/* Clears Interrupt Status Register */
+  outb_reg0(dep, DP_IMR, dp_reg);	/* Sets Interrupt Mask register */
+
+  dp_reg = 0;
+  if (dep->de_flags & DEF_PROMISC) dp_reg |= RCR_AB | RCR_PRO | RCR_AM;
+  if (dep->de_flags & DEF_BROAD) dp_reg |= RCR_AB;
+  if (dep->de_flags & DEF_MULTI) dp_reg |= RCR_AM;
+  outb_reg0(dep, DP_RCR, dp_reg);	/* Sets receive as requested */
+  outb_reg0(dep, DP_TCR, TCR_NORMAL);	/* Sets transmitter */
+
+  outb_reg0(dep, DP_CR, CR_STA | CR_NO_DMA);	/* Starts board */
+
+  /* Initializes the send queue. */
+  for (ix = 0; ix < dep->de_sendq_nr; ix += 1)
+	dep->de_sendq[ix].sq_filled = 0;
+  dep->de_sendq_head = dep->de_sendq_tail = 0;
+
+  /* Device specific functions */
+  if (!dep->de_prog_IO) {
+	dep->de_user2nicf = mem_user2nic;
+	dep->de_nic2userf = mem_nic2user;
+	dep->de_getblockf = mem_getblock;
+  } else {
+#if PIO16 == 0
+	dep->de_user2nicf = pio_user2nic;
+	dep->de_nic2userf = pio_nic2user;
+	dep->de_getblockf = pio_getblock;
+#else
+#error	Missing I/O functions for pio 16 bits
+#endif
+  }
+  dep->de_recvf = ns_recv;
+  dep->de_sendf = ns_send;
+  dep->de_flagsf = ns_reinit;
+  dep->de_resetf = ns_reset;
+  dep->de_getstatsf = ns_stats;
+  dep->de_dumpstatsf = ns_dodump;
+  dep->de_interruptf = ns_interrupt;
+
+  return;			/* Done */
+}
+
+#if PIO16 == 1
+
+/*
+**  Name:	void dp_pio16_user2nic(dpeth_t *dep, int pageno, int pktsize)
+**  Function:	Copies a packet from user area to board (Prog. I/O, 16bits).
+*/
+static void dp_pio16_user2nic(dpeth_t *dep, int pageno, int pktsize)
+{
+  u8_t two_bytes[2];
+  phys_bytes phys_user, phys_2bytes = vir2phys(two_bytes);
+  vir_bytes ecount = (pktsize + 1) & NOT(0x0001);
+  int bytes, ix = 0, odd_byte = 0;
+  iovec_dat_t *iovp = &dep->de_write_iovec;
+
+  outb_reg0(dep, DP_ISR, ISR_RDC);
+  dp_read_setup(dep, ecount, pageno * DP_PAGESIZE);
+
+  do {
+	bytes = iovp->iod_iovec[ix].iov_size;
+	if (bytes > pktsize) bytes = pktsize;
+
+	phys_user = numap(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_addr, bytes);
+	if (!phys_user) panic(dep->de_name, UmapErrMsg, NO_NUM);
+
+	if (odd_byte) {
+		phys_copy(phys_user, phys_2bytes + 1, (phys_bytes) 1);
+		out_word(dep->de_data_port, *(u16_t *)two_bytes);
+		pktsize--;
+		bytes--;
+		phys_user++;
+		odd_byte = 0;
+		if (!bytes) continue;
+	}
+	ecount = bytes & NOT(0x0001);
+	if (ecount != 0) {
+		phys_outsw(dep->de_data_port, phys_user, ecount);
+		pktsize -= ecount;
+		bytes -= ecount;
+		phys_user += ecount;
+	}
+	if (bytes) {
+		phys_copy(phys_user, phys_2bytes, (phys_bytes) 1);
+		pktsize--;
+		bytes--;
+		phys_user++;
+		odd_byte = 1;
+	}
+	if (++ix >= IOVEC_NR) {	/* Next buffer of I/O vector */
+		dp_next_iovec(iovp);
+		ix = 0;
+	}
+
+  }  while (bytes > 0);
+
+  if (odd_byte) out_word(dep->de_data_port, *(u16_t *) two_bytes);
+  for (ix = 0; ix < 100; ix++) {
+	if (inb_reg0(dep, DP_ISR) & ISR_RDC) break;
+  }
+  if (ix == 100) {
+	panic(dep->de_name, RdmaErrMsg, NO_NUM);
+  }
+  return;
+}
+
+/*
+**  Name:	void dp_pio16_nic2user(dpeth_t *dep, int pageno, int pktsize)
+**  Function:	Copies a packet from board to user area (Prog. I/O, 16bits).
+*/
+static void dp_pio16_nic2user(dpeth_t * dep, int nic_addr, int count)
+{
+  phys_bytes phys_user;
+  vir_bytes ecount;
+  int bytes, i;
+  u8_t two_bytes[2];
+  phys_bytes phys_2bytes;
+  int odd_byte;
+
+  ecount = (count + 1) & ~1;
+  phys_2bytes = vir2phys(two_bytes);
+  odd_byte = 0;
+
+  dp_read_setup(dep, ecount, nic_addr);
+
+  i = 0;
+  while (count > 0) {
+	if (i >= IOVEC_NR) {
+		dp_next_iovec(iovp);
+		i = 0;
+		continue;
+	}
+	bytes = iovp->iod_iovec[i].iov_size;
+	if (bytes > count) bytes = count;
+
+	phys_user = numap(iovp->iod_proc_nr,
+			  iovp->iod_iovec[i].iov_addr, bytes);
+	if (!phys_user) panic(dep->de_name, UmapErrMsg, NO_NUM);
+	if (odd_byte) {
+		phys_copy(phys_2bytes + 1, phys_user, (phys_bytes) 1);
+		count--;
+		bytes--;
+		phys_user++;
+		odd_byte = 0;
+		if (!bytes) continue;
+	}
+	ecount = bytes & ~1;
+	if (ecount != 0) {
+		phys_insw(dep->de_data_port, phys_user, ecount);
+		count -= ecount;
+		bytes -= ecount;
+		phys_user += ecount;
+	}
+	if (bytes) {
+		*(u16_t *) two_bytes = in_word(dep->de_data_port);
+		phys_copy(phys_2bytes, phys_user, (phys_bytes) 1);
+		count--;
+		bytes--;
+		phys_user++;
+		odd_byte = 1;
+	}
+  }
+  return;
+}
+
+#endif				/* PIO16 == 1 */
+
+#endif				/* ENABLE_DP8390 */
+
+/** end 8390.c **/
Index: /trunk/minix/drivers/dpeth/8390.h
===================================================================
--- /trunk/minix/drivers/dpeth/8390.h	(revision 9)
+++ /trunk/minix/drivers/dpeth/8390.h	(revision 9)
@@ -0,0 +1,174 @@
+/*
+**  File:	8390.h		May  02, 2000
+**
+**  Author:	Giovanni Falzoni <gfalzoni@inwind.it>
+**
+**  National Semiconductor NS 8390 Network Interface Controller
+**
+**  $Log: 8390.h,v $
+**  Revision 1.2  2005/08/22 15:17:40  beng
+**  Remove double-blank lines (Al)
+**
+**  Revision 1.1  2005/06/29 10:16:46  beng
+**  Import of dpeth 3c501/3c509b/.. ethernet driver by
+**  Giovanni Falzoni <fgalzoni@inwind.it>.
+**
+**  Revision 2.0  2005/06/26 16:16:46  lsodgf0
+**  Initial revision for Minix 3.0.6
+**
+**  $Id: 8390.h,v 1.2 2005/08/22 15:17:40 beng Exp $
+*/
+
+#define DP_PAGESIZE	256	/* NS 8390 page size */
+#define SENDQ_PAGES	6	/* SENDQ_PAGES * DP_PAGESIZE >= 1514 bytes */
+
+/* Page 0, read/write ------------- */
+#define	DP_CR		0x00	/* Command Register		RW */
+#define	DP_CLDA0	0x01	/* Current Local Dma Address 0	RO */
+#define	DP_PSTART	0x01	/* Page Start Register		WO */
+#define	DP_CLDA1	0x02	/* Current Local Dma Address 1	RO */
+#define	DP_PSTOP	0x02	/* Page Stop Register		WO */
+#define	DP_BNRY		0x03	/* Boundary Pointer		RW */
+#define	DP_TSR		0x04	/* Transmit Status Register	RO */
+#define	DP_TPSR		0x04	/* Transmit Page Start Register	WO */
+#define	DP_NCR		0x05	/* No. of Collisions Register	RO */
+#define	DP_TBCR0	0x05	/* Transmit Byte Count Reg. 0	WO */
+#define	DP_FIFO		0x06	/* Fifo				RO */
+#define	DP_TBCR1	0x06	/* Transmit Byte Count Reg. 1	WO */
+#define	DP_ISR		0x07	/* Interrupt Status Register	RW */
+#define	DP_CRDA0	0x08	/* Current Remote Dma Addr.Low	RO */
+#define	DP_RSAR0	0x08	/* Remote Start Address Low	WO */
+#define	DP_CRDA1	0x09	/* Current Remote Dma Addr.High	RO */
+#define	DP_RSAR1	0x09	/* Remote Start Address High	WO */
+#define	DP_RBCR0	0x0A	/* Remote Byte Count Low	WO */
+#define	DP_RBCR1	0x0B	/* Remote Byte Count Hihg	WO */
+#define	DP_RSR		0x0C	/* Receive Status Register	RO */
+#define	DP_RCR		0x0C	/* Receive Config. Register	WO */
+#define	DP_CNTR0	0x0D	/* Tally Counter 0		RO */
+#define	DP_TCR		0x0D	/* Transmit Config. Register	WO */
+#define	DP_CNTR1	0x0E	/* Tally Counter 1		RO */
+#define	DP_DCR		0x0E	/* Data Configuration Register	WO */
+#define	DP_CNTR2	0x0F	/* Tally Counter 2		RO */
+#define	DP_IMR		0x0F	/* Interrupt Mask Register	WO */
+
+ /* Page 1, read/write -------------- */
+/*	DP_CR		0x00	   Command Register */
+#define	DP_PAR0		0x01	/* Physical Address Register 0 */
+#define	DP_PAR1		0x02	/* Physical Address Register 1 */
+#define	DP_PAR2		0x03	/* Physical Address Register 2 */
+#define	DP_PAR3		0x04	/* Physical Address Register 3 */
+#define	DP_PAR4		0x05	/* Physical Address Register 4 */
+#define	DP_PAR5		0x06	/* Physical Address Register 5 */
+#define	DP_CURR		0x07	/* Current Page Register */
+#define	DP_MAR0		0x08	/* Multicast Address Register 0 */
+#define	DP_MAR1		0x09	/* Multicast Address Register 1 */
+#define	DP_MAR2		0x0A	/* Multicast Address Register 2 */
+#define	DP_MAR3		0x0B	/* Multicast Address Register 3 */
+#define	DP_MAR4		0x0C	/* Multicast Address Register 4 */
+#define	DP_MAR5		0x0D	/* Multicast Address Register 5 */
+#define	DP_MAR6		0x0E	/* Multicast Address Register 6 */
+#define	DP_MAR7		0x0F	/* Multicast Address Register 7 */
+
+/* Bits in dp_cr */
+#define CR_STP		0x01	/* Stop: software reset */
+#define CR_STA		0x02	/* Start: activate NIC */
+#define CR_TXP		0x04	/* Transmit Packet */
+#define CR_DMA		0x38	/* Mask for DMA control */
+#define CR_DM_RR	0x08	/* DMA: Remote Read */
+#define CR_DM_RW	0x10	/* DMA: Remote Write */
+#define CR_DM_SP	0x18	/* DMA: Send Packet */
+#define CR_NO_DMA	0x20	/* DMA: Stop Remote DMA Operation */
+#define CR_PS		0xC0	/* Mask for Page Select */
+#define CR_PS_P0	0x00	/* Register Page 0 */
+#define CR_PS_P1	0x40	/* Register Page 1 */
+#define CR_PS_P2	0x80	/* Register Page 2 */
+
+/* Bits in dp_isr */
+#define ISR_MASK	0x3F
+#define ISR_PRX		0x01	/* Packet Received with no errors */
+#define ISR_PTX		0x02	/* Packet Transmitted with no errors */
+#define ISR_RXE		0x04	/* Receive Error */
+#define ISR_TXE		0x08	/* Transmit Error */
+#define ISR_OVW		0x10	/* Overwrite Warning */
+#define ISR_CNT		0x20	/* Counter Overflow */
+#define ISR_RDC		0x40	/* Remote DMA Complete */
+#define ISR_RST		0x80	/* Reset Status */
+
+/* Bits in dp_imr */
+#define IMR_PRXE	0x01	/* Packet Received Enable */
+#define IMR_PTXE	0x02	/* Packet Transmitted Enable */
+#define IMR_RXEE	0x04	/* Receive Error Enable */
+#define IMR_TXEE	0x08	/* Transmit Error Enable */
+#define IMR_OVWE	0x10	/* Overwrite Warning Enable */
+#define IMR_CNTE	0x20	/* Counter Overflow Enable */
+#define IMR_RDCE	0x40	/* DMA Complete Enable */
+
+/* Bits in dp_dcr */
+#define DCR_WTS		0x01	/* Word Transfer Select */
+#define DCR_BYTEWIDE	0x00	/* WTS: byte wide transfers */
+#define DCR_WORDWIDE	0x01	/* WTS: word wide transfers */
+#define DCR_BOS		0x02	/* Byte Order Select */
+#define DCR_LTLENDIAN	0x00	/* BOS: Little Endian */
+#define DCR_BIGENDIAN	0x02	/* BOS: Big Endian */
+#define DCR_LAS		0x04	/* Long Address Select */
+#define DCR_BMS		0x08	/* Burst Mode Select */
+#define DCR_AR		0x10	/* Autoinitialize Remote */
+#define DCR_FTS		0x60	/* Fifo Threshold Select */
+#define DCR_2BYTES	0x00	/* Fifo Threshold: 2 bytes */
+#define DCR_4BYTES	0x20	/* Fifo Threshold: 4 bytes */
+#define DCR_8BYTES	0x40	/* Fifo Threshold: 8 bytes */
+#define DCR_12BYTES	0x60	/* Fifo Threshold: 12 bytes */
+
+/* Bits in dp_tcr */
+#define TCR_CRC		0x01	/* Inhibit CRC */
+#define TCR_ELC		0x06	/* Encoded Loopback Control */
+#define TCR_NORMAL	0x00	/* ELC: Normal Operation */
+#define TCR_INTERNAL	0x02	/* ELC: Internal Loopback */
+#define TCR_0EXTERNAL	0x04	/* ELC: External Loopback LPBK=0 */
+#define TCR_1EXTERNAL	0x06	/* ELC: External Loopback LPBK=1 */
+#define TCR_ATD		0x08	/* Auto Transmit */
+#define TCR_OFST	0x10	/* Collision Offset Enable */
+
+/* Bits in dp_tsr */
+#define TSR_PTX		0x01	/* Packet Transmitted (without error) */
+#define TSR_DFR		0x02	/* Transmit Deferred */
+#define TSR_COL		0x04	/* Transmit Collided */
+#define TSR_ABT		0x08	/* Transmit Aborted */
+#define TSR_CRS		0x10	/* Carrier Sense Lost */
+#define TSR_FU		0x20	/* FIFO Underrun */
+#define TSR_CDH		0x40	/* CD Heartbeat */
+#define TSR_OWC		0x80	/* Out of Window Collision */
+
+/* Bits in dp_rcr */
+#define RCR_SEP		0x01	/* Save Errored Packets */
+#define RCR_AR		0x02	/* Accept Runt Packets */
+#define RCR_AB		0x04	/* Accept Broadcast */
+#define RCR_AM		0x08	/* Accept Multicast */
+#define RCR_PRO		0x10	/* Physical Promiscuous */
+#define RCR_MON		0x20	/* Monitor Mode */
+
+/* Bits in dp_rsr */
+#define RSR_PRX		0x01	/* Packet Received Intact */
+#define RSR_CRC		0x02	/* CRC Error */
+#define RSR_FAE		0x04	/* Frame Alignment Error */
+#define RSR_FO		0x08	/* FIFO Overrun */
+#define RSR_MPA		0x10	/* Missed Packet */
+#define RSR_PHY		0x20	/* Multicast Address Match !! */
+#define RSR_DIS		0x40	/* Receiver Disabled */
+
+/* Some macros to simplify accessing the dp8390 */
+#define inb_reg0(dep,reg) (inb(dep->de_dp8390_port+reg))
+#define outb_reg0(dep,reg,data) (outb(dep->de_dp8390_port+reg,data))
+#define inb_reg1(dep,reg) (inb(dep->de_dp8390_port+reg))
+#define outb_reg1(dep,reg,data) (outb(dep->de_dp8390_port+reg,data))
+
+typedef struct dp_rcvhdr {
+  u8_t dr_status;		/* Copy of rsr */
+  u8_t dr_next;			/* Pointer to next packet */
+  u8_t dr_rbcl;			/* Receive Byte Count Low */
+  u8_t dr_rbch;			/* Receive Byte Count High */
+} dp_rcvhdr_t;
+
+void ns_init(dpeth_t *);
+
+/** 8390.h **/
Index: /trunk/minix/drivers/dpeth/Makefile
===================================================================
--- /trunk/minix/drivers/dpeth/Makefile	(revision 9)
+++ /trunk/minix/drivers/dpeth/Makefile	(revision 9)
@@ -0,0 +1,59 @@
+##
+##  Makefile for ISA ethernet drivers	May  02, 2000
+##
+##  $Log: Makefile,v $
+##  Revision 1.3  2005/07/19 13:21:48  jnherder
+##  Renamed src/lib/utils to src/lib/sysutil --- because of new src/lib/util
+##
+##  Revision 1.2  2005/07/19 12:12:47  jnherder
+##  Changed Makefiles: drivers are now installed in /usr/sbin.
+##  TTY now gets SYS_EVENT message with sigset (e.g., SIGKMESS, SIGKSTOP).
+##
+##  Revision 1.1  2005/06/29 10:16:46  beng
+##  Import of dpeth 3c501/3c509b/.. ethernet driver by
+##  Giovanni Falzoni <fgalzoni@inwind.it>.
+##
+##  Revision 2.0  2005/06/26 16:16:46  lsodgf0
+##  Initial revision for Minix 3.0.6
+##
+##  $Id: Makefile,v 1.3 2005/07/19 13:21:48 jnherder Exp $
+
+##  Programs, flags, etc.
+DRIVER	= dpeth
+
+debug	= 0
+
+CC	= exec cc
+LD	= $(CC)
+CPPFLAGS= -I.. -I/usr/include -Ddebug=$(debug)
+CFLAGS	= -ws $(CPPFLAGS)
+LDFLAGS	= -i -o $@
+
+SRCS	= 3c501.c 3c509.c 3c503.c ne.c wd.c 8390.c devio.c netbuff.c dp.c
+OBJS	= 3c501.o 3c509.o 3c503.o ne.o wd.o 8390.o devio.o netbuff.o dp.o
+LIBS	= -lsysutil -lsys # -ltimers
+
+##  Build rules
+all build:	$(DRIVER)
+
+$(DRIVER):	$(OBJS)
+	$(CC) $(OBJS) $(LIBS) $(LDFLAGS)
+	install -S 4kw $(DRIVER)
+
+##  Install with other drivers
+install:	/usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER):	$(DRIVER)
+	install -o root -cs $? $@
+
+##  Generate dependencies
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+##  Clean directory
+clean:
+	@rm -f $(DRIVER) *.o *.BAK
+
+include .depend
+
+##  end
Index: /trunk/minix/drivers/dpeth/README
===================================================================
--- /trunk/minix/drivers/dpeth/README	(revision 9)
+++ /trunk/minix/drivers/dpeth/README	(revision 9)
@@ -0,0 +1,38 @@
+
+This is my implementation of a new network task 
+for the Minix kernel.  I did it initially to handle
+a 3c501 board (Etherlink), but those board are so
+unstable that it is not worth using them except for
+learning how to implement a driver.  When I got a
+3c509b board (Etherlink III) it was easier to
+write the code to handle them.  
+
+The Minix code in 'dp8390.c' is too specific for the
+National chip set, so what I did was to remove as 
+much as I needed of the code dependant from the chip
+and produce a generic task that, I hope, will be able
+to handle many more cards.
+
+$Log: README,v $
+Revision 1.1  2005/06/29 10:16:46  beng
+Import of dpeth 3c501/3c509b/.. ethernet driver by
+Giovanni Falzoni <fgalzoni@inwind.it>.
+
+Revision 1.3  2004/04/14 12:49:07  lsodgf0
+Changes for porting to Minix 2.0.4 run on BOCHS
+
+Revision 1.2  2002/03/25 14:16:09  lsodgf0
+The driver for the NEx000 has been rewritten to be
+operational with the ACCTON 18xx (an NE1000 clone)
+The I/O routines for 16 bit cards are still untested..
+
+Revision 1.1  2002/02/09 09:35:09  lsodgf0
+Initial revision
+The package is not fully tested, i.e. I had only 3Com
+boards (3c501, 3c503, 3c503/16 and 3c509b) and WD8003.
+I got also a NE1000 clone but it was not fully
+operational and I could not appreciate the results.
+For this reason the changes done to the interface
+to I/O for 8 and 16 bits are not tested.
+  
+$Id: README,v 1.1 2005/06/29 10:16:46 beng Exp $
Index: /trunk/minix/drivers/dpeth/devio.c
===================================================================
--- /trunk/minix/drivers/dpeth/devio.c	(revision 9)
+++ /trunk/minix/drivers/dpeth/devio.c	(revision 9)
@@ -0,0 +1,131 @@
+/*
+**  File:	devio.c		Jun. 11, 2005
+**
+**  Author:	Giovanni Falzoni <gfalzoni@inwind.it>
+**
+**  This file contains the routines for readind/writing
+**  from/to the device registers.
+**
+**  $Id: devio.c,v 1.3 2005/08/05 19:08:43 beng Exp $
+*/
+
+#include "drivers.h"
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include "dp.h"
+
+#if (USE_IOPL == 0)
+
+static void warning(const char *type, int err)
+{
+
+  printf("Warning: eth#0 sys_%s failed (%d)\n", type, err);
+  return;
+}
+
+/*
+**  Name:	unsigned int inb(unsigned short int port);
+**  Function:	Reads a byte from specified i/o port.
+*/
+PUBLIC unsigned int inb(unsigned short port)
+{
+  unsigned int value;
+  int rc;
+
+  if ((rc = sys_inb(port, &value)) != OK) warning("inb", rc);
+  return value;
+}
+
+/*
+**  Name:	unsigned int inw(unsigned short int port);
+**  Function:	Reads a word from specified i/o port.
+*/
+PUBLIC unsigned int inw(unsigned short port)
+{
+  unsigned int value;
+  int rc;
+
+  if ((rc = sys_inw(port, &value)) != OK) warning("inw", rc);
+  return value;
+}
+
+/*
+**  Name:	unsigned int insb(unsigned short int port, int proc_nr, void *buffer, int count);
+**  Function:	Reads a sequence of bytes from specified i/o port to user space buffer.
+*/
+PUBLIC void insb(unsigned short int port, int proc_nr, void *buffer, int count)
+{
+  int rc;
+
+  if ((rc = sys_insb(port, proc_nr, buffer, count)) != OK)
+	warning("insb", rc);
+  return;
+}
+
+/*
+**  Name:	unsigned int insw(unsigned short int port, int proc_nr, void *buffer, int count);
+**  Function:	Reads a sequence of words from specified i/o port to user space buffer.
+*/
+PUBLIC void insw(unsigned short int port, int proc_nr, void *buffer, int count)
+{
+  int rc;
+
+  if ((rc = sys_insw(port, proc_nr, buffer, count)) != OK)
+	warning("insw", rc);
+  return;
+}
+
+/*
+**  Name:	void outb(unsigned short int port, unsigned long value);
+**  Function:	Writes a byte to specified i/o port.
+*/
+PUBLIC void outb(unsigned short port, unsigned long value)
+{
+  int rc;
+
+  if ((rc = sys_outb(port, value)) != OK) warning("outb", rc);
+  return;
+}
+
+/*
+**  Name:	void outw(unsigned short int port, unsigned long value);
+**  Function:	Writes a word to specified i/o port.
+*/
+PUBLIC void outw(unsigned short port, unsigned long value)
+{
+  int rc;
+
+  if ((rc = sys_outw(port, value)) != OK) warning("outw", rc);
+  return;
+}
+
+/*
+**  Name:	void outsb(unsigned short int port, int proc_nr, void *buffer, int count);
+**  Function:	Writes a sequence of bytes from user space to specified i/o port.
+*/
+PUBLIC void outsb(unsigned short port, int proc_nr, void *buffer, int count)
+{
+  int rc;
+
+  if ((rc = sys_outsb(port, proc_nr, buffer, count)) != OK)
+	warning("outsb", rc);
+  return;
+}
+
+/*
+**  Name:	void outsw(unsigned short int port, int proc_nr, void *buffer, int count);
+**  Function:	Writes a sequence of bytes from user space to specified i/o port.
+*/
+PUBLIC void outsw(unsigned short port, int proc_nr, void *buffer, int count)
+{
+  int rc;
+
+  if ((rc = sys_outsw(port, proc_nr, buffer, count)) != OK)
+	warning("outsw", rc);
+  return;
+}
+
+#else
+#error To be implemented
+#endif				/* USE_IOPL */
+/**  devio.c  **/
Index: /trunk/minix/drivers/dpeth/dp.c
===================================================================
--- /trunk/minix/drivers/dpeth/dp.c	(revision 9)
+++ /trunk/minix/drivers/dpeth/dp.c	(revision 9)
@@ -0,0 +1,661 @@
+/*
+**  File:	eth.c	Version 1.00,	Jan. 14, 1997
+**
+**  Author:	Giovanni Falzoni <gfalzoni@inwind.it>
+**
+**  This file contains the ethernet device driver main task.
+**  It has to be integrated with the board specific drivers.
+**  It is a rewriting of Minix 2.0.0 ethernet driver (dp8390.c)
+**  to remove bord specific code. It should operate (I hope)
+**  with any board driver.
+**
+**  The valid messages and their parameters are:
+**
+**    m_type       DL_PORT   DL_PROC  DL_COUNT DL_MODE DL_ADDR
+**  +------------+---------+---------+--------+-------+---------+
+**  | HARD_INT   |         |         |        |       |         | 
+**  +------------+---------+---------+--------+-------+---------+
+**  | SYN_ALARM  |         |         |        |       |         | 
+**  +------------+---------+---------+--------+-------+---------+
+**  | HARD_STOP  |         |         |        |       |         | 
+**  +------------+---------+---------+--------+-------+---------+
+**  | FKEY_PRESSED         |         |        |       |         | (99)
+**  +------------+---------+---------+--------+-------+---------+
+**  | DL_WRITE   | port nr | proc nr | count  | mode  | address | (3)
+**  +------------+---------+---------+--------+-------+---------+
+**  | DL_WRITEV  | port nr | proc nr | count  | mode  | address | (4)
+**  +------------+---------+---------+--------+-------+---------+
+**  | DL_READ    | port nr | proc nr | count  |       | address | (5)
+**  +------------+---------+---------+--------+-------+---------+
+**  | DL_READV   | port nr | proc nr | count  |       | address | (6)
+**  +------------+---------+---------+--------+-------+---------+
+**  | DL_INIT    | port nr | proc nr |        | mode  | address | (7)
+**  +------------+---------+---------+--------+-------+---------+
+**  | DL_STOP    | port_nr |         |        |       |         | (8)
+**  +------------+---------+---------+--------+-------+---------+
+**  | DL_GETSTAT | port nr | proc nr |        |       | address | (9)
+**  +------------+---------+---------+--------+-------+---------+
+**
+**  The messages sent are:
+**
+**    m-type       DL_PORT   DL_PROC  DL_COUNT  DL_STAT   DL_CLCK
+**  +------------+---------+---------+--------+---------+---------+
+**  |DL_TASK_REPL| port nr | proc nr |rd-count| err|stat| clock   | (21)
+**  +------------+---------+---------+--------+---------+---------+
+**
+**    m_type       m3_i1     m3_i2      m3_ca1
+**  +------------+---------+---------+---------------+
+**  |DL_INIT_REPL| port nr |last port| ethernet addr | (20)
+**  +------------+---------+---------+---------------+
+**
+**  $Id: dp.c,v 1.13 2006/03/25 04:49:03 beng Exp $
+*/
+
+#include "drivers.h"
+#include <minix/keymap.h>
+#include <net/hton.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+
+#include "dp.h"
+
+/*
+**  Local data
+*/
+extern int errno;
+static dpeth_t de_table[DE_PORT_NR];
+static char *progname;
+
+typedef struct dp_conf {	/* Configuration description structure */
+  port_t dpc_port;
+  int dpc_irq;
+  phys_bytes dpc_mem;
+  char *dpc_envvar;
+} dp_conf_t;
+
+/* Device default configuration */
+static dp_conf_t dp_conf[DE_PORT_NR] = {
+  /* I/O port, IRQ, Buff addr, Env. var, Buf. selector */
+  {     0x300,   5,   0xC8000,	"DPETH0", },
+  {     0x280,  10,   0xCC000,	"DPETH1", },
+};
+
+static const char CopyErrMsg[] = "unable to read/write user data";
+static const char PortErrMsg[] = "illegal port";
+static const char RecvErrMsg[] = "receive failed";
+static const char SendErrMsg[] = "send failed";
+static const char SizeErrMsg[] = "illegal packet size";
+static const char TypeErrMsg[] = "illegal message type";
+static const char DevName[] = "eth#?";
+
+static void do_getname(message *mp);
+
+/*
+**  Name:	void reply(dpeth_t *dep, int err)
+**  Function:	Fills a DL_TASK_REPLY reply message and sends it.
+*/
+static void reply(dpeth_t * dep, int err)
+{
+  message reply;
+  int status = FALSE;
+
+  if (dep->de_flags & DEF_ACK_SEND) status |= DL_PACK_SEND;
+  if (dep->de_flags & DEF_ACK_RECV) status |= DL_PACK_RECV;
+
+  reply.m_type = DL_TASK_REPLY;
+  reply.DL_PORT = dep - de_table;
+  reply.DL_PROC = dep->de_client;
+  reply.DL_STAT = status /* | ((u32_t) err << 16) */;
+  reply.DL_COUNT = dep->de_read_s;
+  getuptime(&reply.DL_CLCK);
+
+  DEBUG(printf("\t reply %d (%ld)\n", reply.m_type, reply.DL_STAT));
+
+  if ((status = send(dep->de_client, &reply)) == OK) {
+	dep->de_read_s = 0;
+	dep->de_flags &= NOT(DEF_ACK_SEND | DEF_ACK_RECV);
+
+  } else if (status != ELOCKED || err == OK)
+	panic(dep->de_name, SendErrMsg, status);
+
+  return;
+}
+
+/*
+**  Name:	void dp_confaddr(dpeth_t *dep)
+**  Function:	Checks environment for a User defined ethernet address.
+*/
+static void dp_confaddr(dpeth_t * dep)
+{
+  static char ea_fmt[] = "x:x:x:x:x:x";
+  char ea_key[16];
+  int ix;
+  long val;
+
+  strcpy(ea_key, dp_conf[dep - de_table].dpc_envvar);
+  strcat(ea_key, "_EA");
+
+  for (ix = 0; ix < SA_ADDR_LEN; ix++) {
+	val = dep->de_address.ea_addr[ix];
+	if (env_parse(ea_key, ea_fmt, ix, &val, 0x00L, 0xFFL) != EP_SET)
+		break;
+	dep->de_address.ea_addr[ix] = val;
+  }
+
+  if (ix != 0 && ix != SA_ADDR_LEN)
+	/* It's all or nothing, force a panic */
+	env_parse(ea_key, "?", 0, &val, 0L, 0L);
+  return;
+}
+
+/*
+**  Name:	void update_conf(dpeth_t *dep, dp_conf_t *dcp)
+**  Function:	Gets the default settings from 'dp_conf' table and
+**  		modifies them from the environment.
+*/
+static void update_conf(dpeth_t * dep, dp_conf_t * dcp)
+{
+  static char dpc_fmt[] = "x:d:x";
+  long val;
+
+  dep->de_mode = DEM_SINK;
+  val = dcp->dpc_port;		/* Get I/O port address */
+  switch (env_parse(dcp->dpc_envvar, dpc_fmt, 0, &val, 0x000L, 0x3FFL)) {
+      case EP_OFF:	dep->de_mode = DEM_DISABLED;	break;
+      case EP_ON:
+      case EP_SET:	dep->de_mode = DEM_ENABLED;	break;
+  }
+  dep->de_base_port = val;
+
+  val = dcp->dpc_irq | DEI_DEFAULT;	/* Get Interrupt line (IRQ) */
+  env_parse(dcp->dpc_envvar, dpc_fmt, 1, &val, 0L, (long) NR_IRQ_VECTORS - 1);
+  dep->de_irq = val;
+
+  val = dcp->dpc_mem;		/* Get shared memory address */
+  env_parse(dcp->dpc_envvar, dpc_fmt, 2, &val, 0L, LONG_MAX);
+  dep->de_linmem = val;
+
+  return;
+}
+
+/*
+**  Name:	void do_dump(message *mp)
+**  Function:	Displays statistics on screen (SFx key from console)
+*/
+static void do_dump(message *mp)
+{
+  dpeth_t *dep;
+  int port;
+
+  printf("\n\n");
+  for (port = 0, dep = de_table; port < DE_PORT_NR; port += 1, dep += 1) {
+
+	if (dep->de_mode == DEM_DISABLED) continue;
+
+	printf("%s statistics:\t\t", dep->de_name);
+
+	/* Network interface status  */
+	printf("Status: 0x%04x (%d)\n\n", dep->de_flags, dep->de_int_pending);
+
+	(*dep->de_dumpstatsf) (dep);
+
+	/* Transmitted/received bytes */
+	printf("Tx bytes:%10ld\t", dep->bytes_Tx);
+	printf("Rx bytes:%10ld\n", dep->bytes_Rx);
+
+	/* Transmitted/received packets */
+	printf("Tx OK:     %8ld\t", dep->de_stat.ets_packetT);
+	printf("Rx OK:     %8ld\n", dep->de_stat.ets_packetR);
+
+	/* Transmit/receive errors */
+	printf("Tx Err:    %8ld\t", dep->de_stat.ets_sendErr);
+	printf("Rx Err:    %8ld\n", dep->de_stat.ets_recvErr);
+
+	/* Transmit unnerruns/receive overrruns */
+	printf("Tx Und:    %8ld\t", dep->de_stat.ets_fifoUnder);
+	printf("Rx Ovr:    %8ld\n", dep->de_stat.ets_fifoOver);
+
+	/* Transmit collisions/receive CRC errors */
+	printf("Tx Coll:   %8ld\t", dep->de_stat.ets_collision);
+	printf("Rx CRC:    %8ld\n", dep->de_stat.ets_CRCerr);
+  }
+  return;
+}
+
+/*
+**  Name:	void get_userdata(int user_proc, vir_bytes user_addr, int count, void *loc_addr)
+**  Function:	Copies data from user area.
+*/
+static void get_userdata(int user_proc, vir_bytes user_addr, int count, void *loc_addr)
+{
+  int rc;
+  vir_bytes len;
+
+  len = (count > IOVEC_NR ? IOVEC_NR : count) * sizeof(iovec_t);
+  if ((rc = sys_datacopy(user_proc, user_addr, SELF, (vir_bytes)loc_addr, len)) != OK)
+	panic(DevName, CopyErrMsg, rc);
+  return;
+}
+
+/*
+**  Name:	void do_first_init(dpeth_t *dep, dp_conf_t *dcp);
+**  Function:	Init action to setup task
+*/
+static void do_first_init(dpeth_t *dep, dp_conf_t *dcp)
+{
+
+  if (dep->de_linmem != 0) {
+	dep->de_memsegm = BIOS_SEG;
+	/* phys2seg(&dep->de_memsegm, &dep->de_memoffs, dep->de_linmem); */
+  } else
+	dep->de_linmem = 0xFFFF0000;
+
+  /* Make sure statisics are cleared */
+  memset((void *) &(dep->de_stat), 0, sizeof(eth_stat_t));
+
+  /* Device specific initialization */
+  (*dep->de_initf) (dep);
+
+  /* Set the interrupt handler policy. Request interrupts not to be reenabled
+   * automatically. Return the IRQ line number when an interrupt occurs.
+   */
+  dep->de_hook = dep->de_irq;
+  sys_irqsetpolicy(dep->de_irq, 0 /*IRQ_REENABLE*/, &dep->de_hook);
+  dep->de_int_pending = FALSE;
+  sys_irqenable(&dep->de_hook);
+
+  return;
+}
+
+/*
+**  Name:	void do_init(message *mp)
+**  Function:	Checks for hardware presence.
+**  		Provides initialization of hardware and data structures
+*/
+static void do_init(message * mp)
+{
+  int port;
+  dpeth_t *dep;
+  dp_conf_t *dcp;
+  message reply_mess;
+
+  port = mp->DL_PORT;
+  if (port >= 0 && port < DE_PORT_NR) {
+
+	dep = &de_table[port];
+	dcp = &dp_conf[port];
+	strcpy(dep->de_name, DevName);
+	dep->de_name[4] = '0' + port;
+
+	if (dep->de_mode == DEM_DISABLED) {
+
+		update_conf(dep, dcp);	/* First time thru */
+		if (dep->de_mode == DEM_ENABLED &&
+		    !el1_probe(dep) &&	/* Probe for 3c501  */
+		    !wdeth_probe(dep) &&	/* Probe for WD80x3 */
+		    !ne_probe(dep) &&	/* Probe for NEx000 */
+		    !el2_probe(dep) &&	/* Probe for 3c503  */
+		    !el3_probe(dep)) {	/* Probe for 3c509  */
+			printf("%s: warning no ethernet card found at 0x%04X\n",
+			       dep->de_name, dep->de_base_port);
+			dep->de_mode = DEM_DISABLED;
+		}
+	}
+
+	/* 'de_mode' may change if probe routines fail, test again */
+	switch (dep->de_mode) {
+
+	    case DEM_DISABLED:
+		/* Device is configured OFF or hardware probe failed */
+		port = ENXIO;
+		break;
+
+	    case DEM_ENABLED:
+		/* Device is present and probed */
+		if (dep->de_flags == DEF_EMPTY) {
+			/* These actions only the first time */
+			do_first_init(dep, dcp);
+			dep->de_flags |= DEF_ENABLED;
+		}
+		dep->de_flags &= NOT(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
+		if (mp->DL_MODE & DL_PROMISC_REQ)
+			dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
+		if (mp->DL_MODE & DL_MULTI_REQ) dep->de_flags |= DEF_MULTI;
+		if (mp->DL_MODE & DL_BROAD_REQ) dep->de_flags |= DEF_BROAD;
+		(*dep->de_flagsf) (dep);
+		dep->de_client = mp->m_source;
+		break;
+
+	    case DEM_SINK:
+		/* Device not present (sink mode) */
+		memset(dep->de_address.ea_addr, 0, sizeof(ether_addr_t));
+		dp_confaddr(dep);	/* Station address from env. */
+		break;
+
+	    default:	break;
+	}
+	*(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
+
+  } else			/* Port number is out of range */
+	port = ENXIO;
+
+  reply_mess.m_type = DL_INIT_REPLY;
+  reply_mess.m3_i1 = port;
+  reply_mess.m3_i2 = DE_PORT_NR;
+  DEBUG(printf("\t reply %d\n", reply_mess.m_type));
+  if (send(mp->m_source, &reply_mess) != OK)	/* Can't send */
+	panic(dep->de_name, SendErrMsg, mp->m_source);
+
+  return;
+}
+
+/*
+**  Name:	void dp_next_iovec(iovec_dat_t *iovp)
+**  Function:	Retrieves data from next iovec element.
+*/
+PUBLIC void dp_next_iovec(iovec_dat_t * iovp)
+{
+
+  iovp->iod_iovec_s -= IOVEC_NR;
+  iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
+  get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,
+	     iovp->iod_iovec_s, iovp->iod_iovec);
+  return;
+}
+
+/*
+**  Name:	int calc_iovec_size(iovec_dat_t *iovp)
+**  Function:	Compute the size of a request.
+*/
+static int calc_iovec_size(iovec_dat_t * iovp)
+{
+  int size, ix;
+
+  size = ix = 0;
+  do {
+	size += iovp->iod_iovec[ix].iov_size;
+	if (++ix >= IOVEC_NR) {
+		dp_next_iovec(iovp);
+		ix = 0;
+	}
+
+	/* Till all vectors added */
+  } while (ix < iovp->iod_iovec_s);
+  return size;
+}
+
+/*
+**  Name:	void do_vwrite(message *mp, int vectored)
+**  Function:
+*/
+static void do_vwrite(message * mp, int vectored)
+{
+  int port, size;
+  dpeth_t *dep;
+
+  port = mp->DL_PORT;
+  if (port < 0 || port >= DE_PORT_NR)	/* Check for illegal port number */
+	panic(dep->de_name, PortErrMsg, port);
+
+  dep = &de_table[port];
+  dep->de_client = mp->DL_PROC;
+
+  if (dep->de_mode == DEM_ENABLED) {
+
+	if (dep->de_flags & DEF_SENDING)	/* Is sending in progress? */
+		panic(dep->de_name, "send already in progress ", NO_NUM);
+
+	dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
+	if (vectored) {
+		get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+		       mp->DL_COUNT, dep->de_write_iovec.iod_iovec);
+		dep->de_write_iovec.iod_iovec_s = mp->DL_COUNT;
+		dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
+		size = calc_iovec_size(&dep->de_write_iovec);
+	} else {
+		dep->de_write_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR;
+		dep->de_write_iovec.iod_iovec[0].iov_size = size = mp->DL_COUNT;
+		dep->de_write_iovec.iod_iovec_s = 1;
+		dep->de_write_iovec.iod_iovec_addr = 0;
+	}
+	if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE)
+		panic(dep->de_name, SizeErrMsg, size);
+
+	dep->de_flags |= DEF_SENDING;
+	(*dep->de_sendf) (dep, FALSE, size);
+
+  } else if (dep->de_mode == DEM_SINK)
+	dep->de_flags |= DEF_ACK_SEND;
+
+  reply(dep, OK);
+  return;
+}
+
+/*
+**  Name:	void do_vread(message *mp, int vectored)
+**  Function:
+*/
+static void do_vread(message * mp, int vectored)
+{
+  int port, size;
+  dpeth_t *dep;
+
+  port = mp->DL_PORT;
+  if (port < 0 || port >= DE_PORT_NR)	/* Check for illegal port number */
+	panic(dep->de_name, PortErrMsg, port);
+
+  dep = &de_table[port];
+  dep->de_client = mp->DL_PROC;
+
+  if (dep->de_mode == DEM_ENABLED) {
+
+	if (dep->de_flags & DEF_READING)	/* Reading in progress */
+		panic(dep->de_name, "read already in progress", NO_NUM);
+
+	dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
+	if (vectored) {
+		get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+			mp->DL_COUNT, dep->de_read_iovec.iod_iovec);
+		dep->de_read_iovec.iod_iovec_s = mp->DL_COUNT;
+		dep->de_read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
+		size = calc_iovec_size(&dep->de_read_iovec);
+	} else {
+		dep->de_read_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR;
+		dep->de_read_iovec.iod_iovec[0].iov_size = size = mp->DL_COUNT;
+		dep->de_read_iovec.iod_iovec_s = 1;
+		dep->de_read_iovec.iod_iovec_addr = 0;
+	}
+	if (size < ETH_MAX_PACK_SIZE) panic(dep->de_name, SizeErrMsg, size);
+
+	dep->de_flags |= DEF_READING;
+	(*dep->de_recvf) (dep, FALSE, size);
+#if 0
+	if ((dep->de_flags & (DEF_READING | DEF_STOPPED)) == (DEF_READING | DEF_STOPPED))
+		/* The chip is stopped, and all arrived packets delivered */
+		(*dep->de_resetf) (dep);
+	dep->de_flags &= NOT(DEF_STOPPED);
+#endif
+  }
+  reply(dep, OK);
+  return;
+}
+
+/*
+**  Name:	void do_getstat(message *mp)
+**  Function:	Reports device statistics.
+*/
+static void do_getstat(message * mp)
+{
+  int port, rc;
+  dpeth_t *dep;
+
+  port = mp->DL_PORT;
+  if (port < 0 || port >= DE_PORT_NR)	/* Check for illegal port number */
+	panic(dep->de_name, PortErrMsg, port);
+
+  dep = &de_table[port];
+  dep->de_client = mp->DL_PROC;
+
+  if (dep->de_mode == DEM_ENABLED) (*dep->de_getstatsf) (dep);
+  if ((rc = sys_datacopy(SELF, (vir_bytes)&dep->de_stat,
+	                 mp->DL_PROC, (vir_bytes)mp->DL_ADDR,
+			 (vir_bytes) sizeof(dep->de_stat))) != OK)
+        panic(DevName, CopyErrMsg, rc);
+  reply(dep, OK);
+  return;
+}
+
+static void do_getname(mp)
+message *mp;
+{
+	int r;
+
+	strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
+	mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
+	mp->m_type= DL_NAME_REPLY;
+	r= send(mp->m_source, mp);
+	if (r != OK)
+		panic("dpeth", "do_getname: send failed: %d\n", r);
+}
+
+/*
+**  Name:	void do_stop(message *mp)
+**  Function:	Stops network interface.
+*/
+static void do_stop(message * mp)
+{
+  int port;
+  dpeth_t *dep;
+
+  port = mp->DL_PORT;
+  if (port < 0 || port >= DE_PORT_NR)	/* Check for illegal port number */
+	panic(dep->de_name, PortErrMsg, port);
+
+  dep = &de_table[port];
+  if (dep->de_mode == DEM_ENABLED && (dep->de_flags & DEF_ENABLED)) {
+
+	/* Stop device */
+	(dep->de_stopf) (dep);
+	dep->de_flags = DEF_EMPTY;
+	dep->de_mode = DEM_DISABLED;
+  }
+  return;
+}
+
+static void do_watchdog(void *message)
+{
+
+  DEBUG(printf("\t no reply"));
+  return;
+}
+
+/*
+**  Name:	int dpeth_task(void)
+**  Function:	Main entry for dp task
+*/
+PUBLIC int main(int argc, char **argv)
+{
+  message m;
+  dpeth_t *dep;
+  int rc, fkeys, sfkeys, tasknr;
+
+  (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
+
+  env_setargs(argc, argv);
+
+  /* Request function key for debug dumps */
+  fkeys = sfkeys = 0; bit_set(sfkeys, 8);
+  if ((fkey_map(&fkeys, &sfkeys)) != OK) 
+	printf("%s: couldn't program Shift+F8 key (%d)\n", DevName, errno);
+
+#ifdef ETH_IGN_PROTO
+  {
+	static u16_t eth_ign_proto = 0;
+	long val;
+	val = 0xFFFF;
+	env_parse("ETH_IGN_PROTO", "x", 0, &val, 0x0000L, 0xFFFFL);
+	eth_ign_proto = htons((u16_t) val);
+  }
+#endif
+
+  /* Try to notify inet that we are present (again) */
+  rc = _pm_findproc("inet", &tasknr);
+  if (rc == OK)
+	notify(tasknr);
+
+  while (TRUE) {
+	if ((rc = receive(ANY, &m)) != OK) panic(dep->de_name, RecvErrMsg, rc);
+
+	DEBUG(printf("eth: got message %d, ", m.m_type));
+
+	switch (m.m_type) {
+	    case DEV_PING:	/* Status request from RS */
+		notify(m.m_source);
+		continue;
+	    case DL_WRITE:	/* Write message to device */
+		do_vwrite(&m, FALSE);
+		break;
+	    case DL_WRITEV:	/* Write message to device */
+		do_vwrite(&m, TRUE);
+		break;
+	    case DL_READ:	/* Read message from device */
+		do_vread(&m, FALSE);
+		break;
+	    case DL_READV:	/* Read message from device */
+		do_vread(&m, TRUE);
+		break;
+	    case DL_INIT:	/* Initialize device */
+		do_init(&m);
+		break;
+	    case DL_GETSTAT:	/* Get device statistics */
+		do_getstat(&m);
+		break;
+	    case DL_GETNAME:
+		do_getname(&m);
+		break;
+	    case SYN_ALARM:	/* to be defined */
+		do_watchdog(&m);
+		break;
+	    case DL_STOP:	/* Stop device */
+		do_stop(&m);
+		break;
+	    case SYS_SIG: {
+	    	sigset_t sigset = m.NOTIFY_ARG;
+	    	if (sigismember(&sigset, SIGKSTOP)) {	/* Shut down */
+		    for (rc = 0; rc < DE_PORT_NR; rc += 1) {
+			if (de_table[rc].de_mode == DEM_ENABLED) {
+				m.m_type = DL_STOP;
+				m.DL_PORT = rc;
+				do_stop(&m);
+			}
+		    }
+		}
+		break;
+	    }
+	    case HARD_INT:	/* Interrupt from device */
+		for (dep = de_table; dep < &de_table[DE_PORT_NR]; dep += 1) {
+			/* If device is enabled and interrupt pending */
+			if (dep->de_mode == DEM_ENABLED) {
+				dep->de_int_pending = TRUE;
+				(*dep->de_interruptf) (dep);
+				if (dep->de_flags & (DEF_ACK_SEND | DEF_ACK_RECV))
+					reply(dep, !OK);
+				dep->de_int_pending = FALSE;
+				sys_irqenable(&dep->de_hook);
+			}
+		}
+		break;
+	    case FKEY_PRESSED:	/* Function key pressed */
+		do_dump(&m);
+		break;
+	    case PROC_EVENT:
+		break;
+	    default:		/* Invalid message type */
+		panic(DevName, TypeErrMsg, m.m_type);
+		break;
+	}
+  }
+  return OK;			/* Never reached, but keeps compiler happy */
+}
+
+/** dp.c **/
Index: /trunk/minix/drivers/dpeth/dp.h
===================================================================
--- /trunk/minix/drivers/dpeth/dp.h	(revision 9)
+++ /trunk/minix/drivers/dpeth/dp.h	(revision 9)
@@ -0,0 +1,281 @@
+/*
+**  File:	eth.h	Version 1.00,	Jan. 14, 1997
+**
+**  Author:	Giovanni Falzoni <gfalzoni@inwind.it>
+**
+**  Interface description for ethernet device driver
+**
+**  $Log: dp.h,v $
+**  Revision 1.4  2005/09/04 18:52:16  beng
+**  Giovanni's fixes to dpeth:
+**  Date: Sat, 03 Sep 2005 11:05:22 +0200
+**  Subject: Minix 3.0.8
+**
+**  Revision 1.3  2005/08/03 11:53:34  jnherder
+**  Miscellaneous cleanups.
+**
+**  Revision 1.2  2005/08/02 15:30:35  jnherder
+**  Various updates to support dynamically starting drivers.
+**  Output during initialization should be suppressed. Unless an error occurs.
+**  Note that main() can now be main(int argc, char **argv) and arguments can
+**  be passed when bringing up the driver.
+**
+**  Revision 1.1  2005/06/29 10:16:46  beng
+**  Import of dpeth 3c501/3c509b/.. ethernet driver by
+**  Giovanni Falzoni <fgalzoni@inwind.it>.
+**
+**  Revision 2.0  2005/06/26 16:16:46  lsodgf0
+**  Initial revision for Minix 3.0.6
+**
+**  $Id: dp.h,v 1.4 2005/09/04 18:52:16 beng Exp $
+*/
+
+#undef  ENABLE_3C501
+#undef  ENABLE_3C503
+#undef  ENABLE_3C509
+#undef  ENABLE_NE2000
+#undef  ENABLE_WDETH
+#undef  ENABLE_DP8390
+
+#define ENABLE_3C501	1	/* enable 3Com Etherlink I board	 */
+#define ENABLE_3C503	1	/* enable 3Com Etherlink II board 	 */
+#define ENABLE_3C509	1	/* enable 3Com Etherlink III board 	 */
+#define ENABLE_NE2000	1	/* enable Novell N2000 board      	 */
+#define ENABLE_WDETH	1	/* enable Western Digital WD80x3  	 */
+
+#define ENABLE_DP8390	(ENABLE_3C503|ENABLE_WDETH|ENABLE_NE2000)
+#define	HAVE_BUFFERS	(ENABLE_3C501|ENABLE_3C509)
+
+#undef  NULL
+#define NULL ((void *)0)
+#define NOT(x) (~(x))
+
+#if debug == 1
+#	define DEBUG(statm) statm
+#else
+#	define DEBUG(statm)
+#endif
+
+typedef struct _m_hdr_t {	/* Buffer handling header */
+  struct _m_hdr_t *next;
+  int size;
+} m_hdr_t;
+
+typedef struct _buff_t {	/* Receive/Transmit buffer header */
+  struct _buff_t *next;
+  int size;
+  int client;
+  char buffer[2];
+} buff_t;
+
+struct dpeth;
+struct iovec_dat;
+typedef void (*dp_eth_t) (struct dpeth *);
+typedef void (*dp_send_recv_t) (struct dpeth *, int, int);
+
+#if ENABLE_DP8390 == 1
+typedef void (*dp_user2nicf_t) (struct dpeth *, int, int);
+typedef void (*dp_nic2userf_t) (struct dpeth *, int, int);
+typedef void (*dp_getblock_t) (struct dpeth *, u16_t, int, void *);
+#endif
+
+#define DE_PORT_NR	2	/* Number of devices supported	 */
+#define SENDQ_NR	2	/* Size of the send queue	 */
+#define IOVEC_NR	16	/* Number of IOVEC entries at a time */
+
+typedef struct iovec_dat {
+  iovec_t iod_iovec[IOVEC_NR];
+  int iod_iovec_s;
+  int iod_proc_nr;
+  vir_bytes iod_iovec_addr;
+} iovec_dat_t;
+
+typedef struct dpeth {
+  /* The de_base_port field is the starting point of the probe. The
+   * conf routine also fills de_linmem and de_irq. If the probe routine
+   * knows the irq and/or memory address because they are hardwired in
+   * the board, the probe should modify these fields. Futhermore, the
+   * probe routine should also fill in de_initf and de_stopf fields
+   * with the appropriate function pointers and set de_prog_IO iff
+   * programmed I/O is to be used.
+   * 
+   * The initf function fills the following fields. Only cards that do
+   * programmed I/O fill in the de_data_port field. In addition, the
+   * init routine has to fill in the sendq data structures. */
+
+  /* Board hardware interface */
+  port_t de_base_port;
+  port_t de_data_port;		/* For boards using Prog. I/O for xmit/recv */
+
+  int de_irq;
+  int de_int_pending;
+  int de_hook;			/* interrupt hook at kernel */
+
+  char de_name[8];
+
+#define DEI_DEFAULT	0x8000
+
+  phys_bytes de_linmem;		/* For boards using shared memory */
+  unsigned short de_memsegm;
+  vir_bytes de_memoffs;
+  int de_ramsize;		/* Size of on board memory	 */
+  int de_offset_page;		/* Offset of shared memory page	 */
+
+  /* Board specific functions */
+  dp_eth_t de_initf;
+  dp_eth_t de_stopf;
+  dp_eth_t de_resetf;
+  dp_eth_t de_flagsf;
+  dp_eth_t de_getstatsf;
+  dp_eth_t de_dumpstatsf;
+  dp_eth_t de_interruptf;
+  dp_send_recv_t de_recvf;
+  dp_send_recv_t de_sendf;
+
+  ether_addr_t de_address;	/* Ethernet Address */
+  eth_stat_t de_stat;		/* Ethernet Statistics */
+  unsigned long bytes_Tx;	/* Total bytes sent/received */
+  unsigned long bytes_Rx;
+
+#define	SA_ADDR_LEN	sizeof(ether_addr_t)
+
+  int de_flags;			/* Send/Receive mode (Configuration) */
+
+#define DEF_EMPTY	0x0000
+#define DEF_READING	0x0001
+#define DEF_RECV_BUSY	0x0002
+#define DEF_ACK_RECV	0x0004
+#define DEF_SENDING	0x0010
+#define DEF_XMIT_BUSY	0x0020
+#define DEF_ACK_SEND	0x0040
+#define DEF_PROMISC	0x0100
+#define DEF_MULTI	0x0200
+#define DEF_BROAD	0x0400
+#define DEF_ENABLED	0x2000
+#define DEF_STOPPED	0x4000
+
+  int de_mode;			/* Status of the Interface */
+
+#define DEM_DISABLED	0x0000
+#define DEM_SINK	0x0001
+#define DEM_ENABLED	0x0002
+
+  /* Temporary storage for RECV/SEND requests */
+  iovec_dat_t de_read_iovec;
+  iovec_dat_t de_write_iovec;
+  vir_bytes de_read_s;
+  vir_bytes de_send_s;
+  int de_client;
+/*
+  message de_sendmsg;
+  iovec_dat_t de_tmp_iovec;
+*/
+#if ENABLE_DP8390 == 1
+  /* For use by NS DP8390 driver */
+  port_t de_dp8390_port;
+  int de_prog_IO;
+  int de_16bit;
+  int de_startpage;
+  int de_stoppage;
+
+  /* Do it yourself send queue */
+  struct sendq {
+	int sq_filled;		/* This buffer contains a packet */
+	int sq_size;		/* with this size */
+	int sq_sendpage;	/* starting page of the buffer */
+  } de_sendq[SENDQ_NR];
+  int de_sendq_nr;
+  int de_sendq_head;		/* Enqueue at the head */
+  int de_sendq_tail;		/* Dequeue at the tail */
+
+  dp_user2nicf_t de_user2nicf;
+  dp_nic2userf_t de_nic2userf;
+  dp_getblock_t de_getblockf;
+#endif
+
+#if ENABLE_3C509 == 1
+  /* For use by 3Com Etherlink III (3c509) driver */
+  port_t de_id_port;
+  port_t de_if_port;
+#endif
+
+#if ENABLE_3C501 == 1 ||  ENABLE_3C509 == 1
+  /* For use by 3Com Etherlink (3c501 and 3c509) driver */
+  buff_t *de_recvq_head;
+  buff_t *de_recvq_tail;
+  buff_t *de_xmitq_head;
+  buff_t *de_xmitq_tail;
+  u16_t de_recv_mode;
+  clock_t de_xmit_start;
+#endif
+
+} dpeth_t;
+
+/*
+ *	Function definitions
+ */
+
+/* dp.c */
+void dp_next_iovec(iovec_dat_t * iovp);
+
+/* devio.c */
+#if defined USE_IOPL
+#include <ibm/portio.h>
+#else
+unsigned int inb(unsigned short int);
+unsigned int inw(unsigned short int);
+void insb(unsigned short int, int, void *, int);
+void insw(unsigned short int, int, void *, int);
+void outb(unsigned short int, unsigned long);
+void outw(unsigned short int, unsigned long);
+void outsb(unsigned short int, int, void *, int);
+void outsw(unsigned short int, int, void *, int);
+#endif
+
+/* netbuff.c */
+void *alloc_buff(dpeth_t *, int);
+void free_buff(dpeth_t *, void *);
+void init_buff(dpeth_t *, buff_t **);
+void mem2user(dpeth_t *, buff_t *);
+void user2mem(dpeth_t *, buff_t *);
+
+/* 3c501.c */
+#if ENABLE_3C501 == 1
+int el1_probe(dpeth_t *);
+#else
+#define el1_probe(x) (0)
+#endif
+
+/* 3c503.c */
+#if ENABLE_3C503 == 1
+int el2_probe(dpeth_t *);
+#else
+#define el2_probe(x) (0)
+#endif
+
+/* 3c509.c */
+#if ENABLE_3C509 == 1
+int el3_probe(dpeth_t *);
+#else
+#define el3_probe(x) (0)
+#endif
+
+/* ne.c */
+#if ENABLE_NE2000 == 1
+int ne_probe(dpeth_t * dep);
+#else
+#define ne_probe(x) (0)
+#endif
+
+/* wd.c */
+#if ENABLE_WDETH == 1
+int wdeth_probe(dpeth_t * dep);
+#else
+#define wdeth_probe(x) (0)
+#endif
+
+#define lock()	 (++dep->de_int_pending,sys_irqdisable(&dep->de_hook))
+#define unlock() do{int i=(--dep->de_int_pending)?0:sys_irqenable(&dep->de_hook);}while(0)
+#define milli_delay(t) tickdelay(1)
+
+/** dp.h **/
Index: /trunk/minix/drivers/dpeth/ne.c
===================================================================
--- /trunk/minix/drivers/dpeth/ne.c	(revision 9)
+++ /trunk/minix/drivers/dpeth/ne.c	(revision 9)
@@ -0,0 +1,193 @@
+/*
+**  File:	ne.c	Jun. 08, 2000
+**
+**  Driver for the NE*000 ethernet cards and derivates.
+**  This file contains only the ne specific code,
+**  the rest is in 8390.c   Code specific for ISA bus only
+**
+**  Created:	March 15, 1994 by Philip Homburg <philip@cs.vu.nl>
+**  PchId: 	ne2000.c,v 1.4 1996/01/19 23:30:34 philip Exp
+**
+**  Modified:	Jun. 08, 2000 by Giovanni Falzoni <gfalzoni@inwind.it>
+**  		Adapted to interface new main network task.
+**
+**  $Id: ne.c,v 1.3 2005/08/05 19:08:43 beng Exp $
+*/
+
+#include "drivers.h"
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include "dp.h"
+
+#if (ENABLE_NE2000 == 1)
+
+#include "8390.h"
+#include "ne.h"
+
+/*
+**  Name:	void ne_reset(dpeth_t * dep);
+**  Function:	Resets the board and checks if reset cycle completes
+*/
+static int ne_reset(dpeth_t * dep)
+{
+  int count = 0;
+
+  /* Reset the ethernet card */
+  outb_ne(dep, NE_RESET, inb_ne(dep, NE_RESET));
+  do {
+	if (++count > 10) return FALSE;	/* 20 mSecs. timeout */
+	milli_delay(2);
+  } while ((inb_ne(dep, DP_ISR) & ISR_RST) == 0);
+  return TRUE;
+}
+
+/*
+**  Name:	void ne_close(dpeth_t * dep);
+**  Function:	Stops the board by resetting it and masking interrupts.
+*/
+static void ne_close(dpeth_t * dep)
+{
+
+  (void)ne_reset(dep);
+  outb_ne(dep, DP_ISR, 0xFF);
+  sys_irqdisable(&dep->de_hook);
+  return;
+}
+
+/* 
+**  Name:	void ne_init(dpeth_t * dep);
+**  Function:	Initialize the board making it ready to work.
+*/
+static void ne_init(dpeth_t * dep)
+{
+  int ix;
+
+  dep->de_data_port = dep->de_base_port + NE_DATA;
+  if (dep->de_16bit) {
+	dep->de_ramsize = NE2000_SIZE;
+	dep->de_offset_page = NE2000_START / DP_PAGESIZE;
+  } else {
+	dep->de_ramsize = NE1000_SIZE;
+	dep->de_offset_page = NE1000_START / DP_PAGESIZE;
+  }
+
+  /* Allocates two send buffers from onboard RAM */
+  dep->de_sendq_nr = SENDQ_NR;
+  for (ix = 0; ix < SENDQ_NR; ix += 1) {
+	dep->de_sendq[ix].sq_sendpage = dep->de_offset_page + ix * SENDQ_PAGES;
+  }
+
+  /* Remaining onboard RAM allocated for receiving */
+  dep->de_startpage = dep->de_offset_page + ix * SENDQ_PAGES;
+  dep->de_stoppage = dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE;
+
+  /* Can't override the default IRQ. */
+  dep->de_irq &= NOT(DEI_DEFAULT);
+
+  ns_init(dep);			/* Initialize DP controller */
+
+  printf("%s: NE%d000 (%dkB RAM) at %X:%d - ",
+         dep->de_name,
+         dep->de_16bit ? 2 : 1,
+         dep->de_ramsize / 1024,
+         dep->de_base_port, dep->de_irq);
+  for (ix = 0; ix < SA_ADDR_LEN; ix += 1)
+	printf("%02X%c", dep->de_address.ea_addr[ix], ix < SA_ADDR_LEN - 1 ? ':' : '\n');
+  return;
+}
+
+/*
+**  Name:	int ne_probe(dpeth_t * dep);
+**  Function:	Probe for the presence of a NE*000 card by testing
+**  		whether the board is reachable through the dp8390.
+**  		Note that the NE1000 is an 8bit card and has a memory
+**  		region distict from the 16bit NE2000.
+*/
+PUBLIC int ne_probe(dpeth_t * dep)
+{
+  int ix, wd, loc1, loc2;
+  char EPROM[32];
+  static const struct {
+	unsigned char offset;
+	unsigned char value;
+  } InitSeq[] =
+  {
+	{	/* Selects page 0. */
+		DP_CR, (CR_NO_DMA | CR_PS_P0 | CR_STP),
+	},
+	{	/* Set byte-wide access and 8 bytes burst mode. */
+		DP_DCR, (DCR_8BYTES | DCR_BMS), 
+	},
+	{	/* Clears the count registers. */
+		DP_RBCR0, 0x00, }, {	DP_RBCR1, 0x00,
+	},
+	{	/* Mask completion irq. */
+		DP_IMR, 0x00, }, {	DP_ISR, 0xFF,
+	},
+	{	/* Set receiver to monitor */
+		DP_RCR, RCR_MON, 
+	},
+	{	/* and transmitter to loopback mode. */
+		DP_TCR, TCR_INTERNAL, 
+	},
+	{	/* Transmit 32 bytes */
+		DP_RBCR0, 32, }, { DP_RBCR1, 0,
+	},
+	{	/* DMA starting at 0x0000. */
+		DP_RSAR0, 0x00, }, { DP_RSAR1, 0x00,
+	},
+	{			/* Start board (reads) */
+		DP_CR, (CR_PS_P0 | CR_DM_RR | CR_STA),
+	},
+  };
+
+  dep->de_dp8390_port = dep->de_base_port + NE_DP8390;
+
+  if ((loc1 = inb_ne(dep, NE_DP8390)) == 0xFF) return FALSE;
+
+  /* Check if the dp8390 is really there */
+  outb_ne(dep, DP_CR, CR_STP | CR_NO_DMA | CR_PS_P1);
+  loc2 = inb_ne(dep, DP_MAR5);	/* Saves one byte of the address */
+  outb_ne(dep, DP_MAR5, 0xFF);	/* Write 0xFF to it (same offset as DP_CNTR0) */
+  outb_ne(dep, DP_CR, CR_NO_DMA | CR_PS_P0);	/* Back to page 0 */
+  inb_ne(dep, DP_CNTR0);	/* Reading counter resets it */
+  if (inb_ne(dep, DP_CNTR0) != 0) {
+	outb_ne(dep, NE_DP8390, loc1);	/* Try to restore modified bytes */
+	outb_ne(dep, DP_TCR, loc2);
+	return FALSE;
+  }
+
+  /* Try to reset the board */
+  if (ne_reset(dep) == FALSE) return FALSE;
+
+  /* Checks whether the board is 8/16bits and a real NE*000 or clone */
+  for (ix = 0; ix < sizeof(InitSeq)/sizeof(InitSeq[0]); ix += 1) {
+	outb_ne(dep, InitSeq[ix].offset, InitSeq[ix].value);
+  }
+  for (ix = 0, wd = 1; ix < 32; ix += 2) {
+	EPROM[ix + 0] = inb_ne(dep, NE_DATA);
+	EPROM[ix + 1] = inb_ne(dep, NE_DATA);
+	/* NE2000s and clones read same value for even and odd addresses */
+	if (EPROM[ix + 0] != EPROM[ix + 1]) wd = 0;
+  }
+  if (wd == 1) {	/* Normalize EPROM contents for NE2000 */
+	for (ix = 0; ix < 16; ix += 1) EPROM[ix] = EPROM[ix * 2];
+  }
+  /* Real NE*000 and good clones have '0x57' at locations 14 and 15 */
+  if (EPROM[14] != 0x57 || EPROM[15] != 0x57) return FALSE;
+
+  /* Setup the ethernet address. */
+  for (ix = 0; ix < SA_ADDR_LEN; ix += 1) {
+	dep->de_address.ea_addr[ix] = EPROM[ix];
+  }
+  dep->de_16bit = wd;
+  dep->de_linmem = 0;		/* Uses Programmed I/O only */
+  dep->de_prog_IO = 1;
+  dep->de_initf = ne_init;
+  dep->de_stopf = ne_close;
+  return TRUE;
+}
+
+#endif				/* ENABLE_NE2000 */
+
+/** ne.c **/
Index: /trunk/minix/drivers/dpeth/ne.h
===================================================================
--- /trunk/minix/drivers/dpeth/ne.h	(revision 9)
+++ /trunk/minix/drivers/dpeth/ne.h	(revision 9)
@@ -0,0 +1,37 @@
+/*
+**  File:	ne.h
+**   
+**  Created:	March 15, 1994 by Philip Homburg <philip@cs.vu.nl>
+**  $PchId: ne2000.h,v 1.2 1995/12/22 08:42:31 philip Exp $
+**
+**  $Log: ne.h,v $
+**  Revision 1.1  2005/06/29 10:16:46  beng
+**  Import of dpeth 3c501/3c509b/.. ethernet driver by
+**  Giovanni Falzoni <fgalzoni@inwind.it>.
+**
+**  Revision 2.0  2005/06/26 16:16:46  lsodgf0
+**  Initial revision for Minix 3.0.6
+**
+**  $Id: ne.h,v 1.1 2005/06/29 10:16:46 beng Exp $
+*/
+
+#ifndef NE2000_H
+#define NE2000_H
+
+#define NE_DP8390	0x00
+#define NE_DATA		0x10
+#define NE_RESET	0x1F
+
+#define NE1000_START	0x2000
+#define NE1000_SIZE	0x2000
+#define NE2000_START	0x4000
+#define NE2000_SIZE	0x4000
+
+#define inb_ne(dep, reg) (inb(dep->de_base_port+reg))
+#define outb_ne(dep, reg, data) (outb(dep->de_base_port+reg, data))
+#define inw_ne(dep, reg) (inw(dep->de_base_port+reg))
+#define outw_ne(dep, reg, data) (outw(dep->de_base_port+reg, data))
+
+#endif				/* NE2000_H */
+
+/** ne.h **/
Index: /trunk/minix/drivers/dpeth/netbuff.c
===================================================================
--- /trunk/minix/drivers/dpeth/netbuff.c	(revision 9)
+++ /trunk/minix/drivers/dpeth/netbuff.c	(revision 9)
@@ -0,0 +1,168 @@
+/*
+**  File:	netbuff.c	Jun. 10, 2000
+**
+**  Author:	Giovanni Falzoni <gfalzoni@inwind.it>
+**
+**  This file contains specific implementation of buffering
+**  for network packets.
+**
+**  $Id: netbuff.c,v 1.3 2005/08/05 19:08:43 beng Exp $
+*/
+
+#include "drivers.h"
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include "dp.h"
+
+#if (HAVE_BUFFERS == 1)
+
+static m_hdr_t *allocptr = NULL;
+static char tx_rx_buff[8192];
+
+/*
+**  Name:	void *alloc_buff(dpeth_t *dep, int size)
+**  Function:	Allocates a buffer from the common pool.
+*/
+PUBLIC void *alloc_buff(dpeth_t *dep, int size)
+{
+  m_hdr_t *ptr, *wrk = allocptr;
+  int units = ((size + sizeof(m_hdr_t) - 1) / sizeof(m_hdr_t)) + 1;
+
+  lock();
+  for (ptr = wrk->next;; wrk = ptr, ptr = ptr->next) {
+	if (ptr->size >= units) {
+		/* Memory is available, carve requested size from pool */
+		if (ptr->size == units) {
+			wrk->next = ptr->next;
+		} else {
+			/* Get memory from top address */
+			ptr->size -= units;
+			ptr += ptr->size;
+			ptr->size = units;
+		}
+		allocptr = wrk;
+		unlock();
+		return ptr + 1;
+	}
+	if (ptr == allocptr) break;
+  }
+  unlock();
+  return NULL;			/* No memory available */
+}
+
+/*
+**  Name:	void free_buff(dpeth_t *dep, void *blk)
+**  Function:	Returns a buffer to the common pool.
+*/
+PUBLIC void free_buff(dpeth_t *dep, void *blk)
+{
+  m_hdr_t *wrk, *ptr = (m_hdr_t *) blk - 1;
+
+  lock();			/* Scan linked list for the correct place */
+  for (wrk = allocptr; !(ptr > wrk && ptr < wrk->next); wrk = wrk->next)
+	if (wrk >= wrk->next && (ptr > wrk || ptr < wrk->next)) break;
+  
+  /* Check if adjacent block is free and join blocks */
+  if (ptr + ptr->size == wrk->next) {
+	ptr->size += wrk->next->size;
+	ptr->next = wrk->next->next;
+  } else
+	ptr->next = wrk->next;
+  if (wrk + wrk->size == ptr) {
+	wrk->size += ptr->size;
+	wrk->next = ptr->next;
+  } else
+	wrk->next = ptr;
+  allocptr = wrk;		/* Point allocptr to block just released */
+  unlock();
+  return;
+}
+
+/*
+**  Name:	void init_buff(dpeth_t *dep, buff_t **tx_buff)
+**  Function:	Initalizes driver data structures.
+*/
+PUBLIC void init_buff(dpeth_t *dep, buff_t **tx_buff)
+{
+
+  /* Initializes buffer pool */
+  if (allocptr == NULL) {
+	m_hdr_t *rx = (m_hdr_t *) tx_rx_buff;
+	rx->next = allocptr = rx;
+	rx->size = 0;
+	rx += 1;
+	rx->next = NULL;
+	rx->size = (sizeof(tx_rx_buff) / sizeof(m_hdr_t)) - 1;
+	free_buff(dep, rx + 1);
+	dep->de_recvq_tail = dep->de_recvq_head = NULL;
+	if (tx_buff != NULL) {
+		*tx_buff = alloc_buff(dep, ETH_MAX_PACK_SIZE + sizeof(buff_t));
+		(*tx_buff)->size = 0;
+	}
+  }
+  return;			/* Done */
+}
+
+/*
+**  Name:	void mem2user(dpeth_t *dep, buff_t *rxbuff);
+**  Function:	Copies a packet from local buffer to user area.
+*/
+PUBLIC void mem2user(dpeth_t *dep, buff_t *rxbuff)
+{
+  phys_bytes phys_user;
+  int bytes, ix = 0;
+  iovec_dat_t *iovp = &dep->de_read_iovec;
+  int pktsize = rxbuff->size;
+  char *buffer = rxbuff->buffer;
+
+  do {				/* Reads chuncks of packet into user buffers */
+
+	bytes = iovp->iod_iovec[ix].iov_size;	/* Size of buffer */
+	if (bytes > pktsize) bytes = pktsize;
+
+	/* Reads from Rx buffer to user area */
+	sys_datacopy(SELF, (vir_bytes)buffer, iovp->iod_proc_nr,
+		     iovp->iod_iovec[ix].iov_addr, bytes);
+	buffer += bytes;
+
+	if (++ix >= IOVEC_NR) {	/* Next buffer of IO vector */
+		dp_next_iovec(iovp);
+		ix = 0;
+	}
+	/* Till packet done */
+  } while ((pktsize -= bytes) > 0);
+  return;
+}
+
+/*
+**  Name:	void user2mem(dpeth_t *dep, buff_t *txbuff)
+**  Function:	Copies a packet from user area to local buffer.
+*/
+PUBLIC void user2mem(dpeth_t *dep, buff_t *txbuff)
+{
+  phys_bytes phys_user;
+  int bytes, ix = 0;
+  iovec_dat_t *iovp = &dep->de_write_iovec;
+  int pktsize = txbuff->size;
+  char *buffer = txbuff->buffer;
+
+  do {				/* Reads chuncks of packet from user buffers */
+
+	bytes = iovp->iod_iovec[ix].iov_size;	/* Size of buffer */
+	if (bytes > pktsize) bytes = pktsize;
+	sys_datacopy(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_addr,
+		     SELF, (vir_bytes)buffer, bytes);
+	buffer += bytes;
+
+	if (++ix >= IOVEC_NR) {	/* Next buffer of IO vector */
+		dp_next_iovec(iovp);
+		ix = 0;
+	}
+	/* Till packet done */
+  } while ((pktsize -= bytes) > 0);
+  return;
+}
+
+#endif				/* HAVE_BUFFERS */
+
+/** netbuff.c **/
Index: /trunk/minix/drivers/dpeth/wd.c
===================================================================
--- /trunk/minix/drivers/dpeth/wd.c	(revision 9)
+++ /trunk/minix/drivers/dpeth/wd.c	(revision 9)
@@ -0,0 +1,314 @@
+/*
+**  File:	wd.c
+**
+**  Driver for the Ethercard (WD80x3) and derivates
+**  This file contains only the wd80x3 specific code,
+**  the rest is in 8390.c
+**
+**  Created:	March 14, 1994 by Philip Homburg
+**  PchId:
+**
+**  Modified: Jun. 08, 2000 by Giovanni Falzoni <gfalzoni@inwind.it>
+**  	Adaptation to interfacing new main network task.
+**
+**  $Id: wd.c,v 1.4 2005/08/22 15:17:40 beng Exp $
+*/
+
+#include "drivers.h"
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include "dp.h"
+
+#if (ENABLE_WDETH == 1)
+
+#include "8390.h"
+#include "wd.h"
+
+#define WET_ETHERNET	0x01	/* Ethernet transceiver */
+#define WET_STARLAN	0x02	/* Starlan transceiver */
+#define WET_INTERF_CHIP	0x04	/* has a WD83C583 interface chip */
+#define WET_BRD_16BIT	0x08	/* 16 bit board */
+#define WET_SLT_16BIT	0x10	/* 16 bit slot */
+#define WET_790		0x20	/* '790 chip */
+
+static const int we_int_table[8] = {9, 3, 5, 7, 10, 11, 15, 4};
+static const int we_790int_table[8] = {0, 9, 3, 5, 7, 10, 11, 15};
+
+_PROTOTYPE(static void we_init, (dpeth_t * dep));
+_PROTOTYPE(static void we_stop, (dpeth_t * dep));
+_PROTOTYPE(static int we_aliasing, (dpeth_t * dep));
+_PROTOTYPE(static int we_interface_chip, (dpeth_t * dep));
+_PROTOTYPE(static int we_16bitboard, (dpeth_t * dep));
+_PROTOTYPE(static int we_16bitslot, (dpeth_t * dep));
+_PROTOTYPE(static int we_ultra, (dpeth_t * dep));
+
+/*===========================================================================*
+ *				wdeth_probe				     *
+ *===========================================================================*/
+int wdeth_probe(dep)
+dpeth_t *dep;
+{
+  int sum;
+
+  if (dep->de_linmem == 0)
+	return FALSE;		/* No shared memory, so no WD board */
+
+  sum = inb_we(dep, EPL_EA0) + inb_we(dep, EPL_EA1) +
+	inb_we(dep, EPL_EA2) + inb_we(dep, EPL_EA3) +
+	inb_we(dep, EPL_EA4) + inb_we(dep, EPL_EA5) +
+	inb_we(dep, EPL_TLB) + inb_we(dep, EPL_CHKSUM);
+  if ((sum & 0xFF) != 0xFF)
+	return FALSE;		/* No ethernet board at this address */
+
+  dep->de_initf = we_init;
+  dep->de_stopf = we_stop;
+  dep->de_prog_IO = 0;
+  return TRUE;
+}
+
+/*===========================================================================*
+ *				we_init					     *
+ *===========================================================================*/
+static void we_init(dep)
+dpeth_t *dep;
+{
+  int i, int_indx, int_nr;
+  int tlb, rambit, revision;
+  int icr, irr, hwr, b, gcr;
+  int we_type;
+  int sendq_nr;
+
+  for (i = 0; i < 6; i += 1) {
+	dep->de_address.ea_addr[i] = inb_we(dep, EPL_EA0 + i);
+  }
+
+  dep->de_dp8390_port = dep->de_base_port + EPL_DP8390;
+
+  dep->de_16bit = 0;
+
+  we_type = 0;
+  we_type |= WET_ETHERNET;	/* assume ethernet */
+  if (we_ultra(dep)) we_type |= WET_790;
+  if (!we_aliasing(dep)) {
+	if (we_interface_chip(dep)) we_type |= WET_INTERF_CHIP;
+	if (we_16bitboard(dep)) {
+		we_type |= WET_BRD_16BIT;
+		if (we_16bitslot(dep)) we_type |= WET_SLT_16BIT;
+	}
+  }
+  if (we_type & WET_SLT_16BIT) dep->de_16bit = 1;
+
+  /* Look at the on board ram size. */
+  tlb = inb_we(dep, EPL_TLB);
+  revision = tlb & E_TLB_REV;
+  rambit = tlb & E_TLB_RAM;
+
+  if (dep->de_ramsize != 0) {
+	/* Size set from boot environment. */
+  } else if (revision < 2) {
+	dep->de_ramsize = 0x2000;	/* 8K */
+	if (we_type & WET_BRD_16BIT)
+		dep->de_ramsize = 0x4000;	/* 16K */
+	else if ((we_type & WET_INTERF_CHIP) &&
+		 inb_we(dep, EPL_ICR) & E_ICR_MEMBIT) {
+		dep->de_ramsize = 0x8000;	/* 32K */
+	}
+  } else {
+	if (we_type & WET_BRD_16BIT) {
+		/* 32K or 16K */
+		dep->de_ramsize = rambit ? 0x8000 : 0x4000;
+	} else {
+		/* 32K or 8K */
+		dep->de_ramsize = rambit ? 0x8000 : 0x2000;
+	}
+  }
+
+  if (we_type & WET_790) {
+	outb_we(dep, EPL_MSR, E_MSR_RESET);
+	if ((we_type & (WET_BRD_16BIT | WET_SLT_16BIT)) ==
+	    (WET_BRD_16BIT | WET_SLT_16BIT)) {
+		outb_we(dep, EPL_LAAR, E_LAAR_LAN16E | E_LAAR_MEM16E);
+	}
+  } else if (we_type & WET_BRD_16BIT) {
+	if (we_type & WET_SLT_16BIT) {
+		outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_SOFTINT |
+			E_LAAR_LAN16E | E_LAAR_MEM16E);
+	} else {
+		outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_SOFTINT |
+			E_LAAR_LAN16E);
+	}
+  }
+  if (we_type & WET_790) {
+	outb_we(dep, EPL_MSR, E_MSR_MENABLE);
+	hwr = inb_we(dep, EPL_790_HWR);
+	outb_we(dep, EPL_790_HWR, hwr | E_790_HWR_SWH);
+	b = inb_we(dep, EPL_790_B);
+	outb_we(dep, EPL_790_B, ((dep->de_linmem >> 13) & 0x0f) |
+		((dep->de_linmem >> 11) & 0x40) | (b & 0xb0));
+	outb_we(dep, EPL_790_HWR, hwr & ~E_790_HWR_SWH);
+  } else {
+	outb_we(dep, EPL_MSR, E_MSR_RESET);
+	outb_we(dep, EPL_MSR, E_MSR_MENABLE |
+		((dep->de_linmem >> 13) & E_MSR_MEMADDR));
+  }
+
+  if ((we_type & WET_INTERF_CHIP) && !(we_type & WET_790)) {
+	icr = inb_we(dep, EPL_ICR);
+	irr = inb_we(dep, EPL_IRR);
+	int_indx = (icr & E_ICR_IR2) | ((irr & (E_IRR_IR0 | E_IRR_IR1)) >> 5);
+	int_nr = we_int_table[int_indx];
+	DEBUG(printf("%s: encoded irq= %d\n", dep->de_name, int_nr));
+	if (dep->de_irq & DEI_DEFAULT) dep->de_irq = int_nr;
+	outb_we(dep, EPL_IRR, irr | E_IRR_IEN);
+  }
+  if (we_type & WET_790) {
+	hwr = inb_we(dep, EPL_790_HWR);
+	outb_we(dep, EPL_790_HWR, hwr | E_790_HWR_SWH);
+
+	gcr = inb_we(dep, EPL_790_GCR);
+
+	outb_we(dep, EPL_790_HWR, hwr & ~E_790_HWR_SWH);
+
+	int_indx = ((gcr & E_790_GCR_IR2) >> 4) |
+		((gcr & (E_790_GCR_IR1 | E_790_GCR_IR0)) >> 2);
+	int_nr = we_790int_table[int_indx];
+	DEBUG(printf("%s: encoded irq= %d\n", dep->de_name, int_nr));
+	if (dep->de_irq & DEI_DEFAULT) dep->de_irq = int_nr;
+	icr = inb_we(dep, EPL_790_ICR);
+	outb_we(dep, EPL_790_ICR, icr | E_790_ICR_EIL);
+  }
+
+  /* Strip the "default flag." */
+  dep->de_irq &= ~DEI_DEFAULT;
+
+  dep->de_offset_page = 0;	/* Shared memory starts at 0 */
+  /* Allocate one send buffer (1.5KB) per 8KB of on board memory.
+  sendq_nr = dep->de_ramsize / 0x2000;
+  if (sendq_nr < 1)
+	sendq_nr = 1;
+  else if (sendq_nr > SENDQ_NR) */
+	sendq_nr = SENDQ_NR;
+  dep->de_sendq_nr = sendq_nr;
+  for (i = 0; i < sendq_nr; i++) {
+	dep->de_sendq[i].sq_sendpage = i * SENDQ_PAGES;
+  }
+  dep->de_startpage = i * SENDQ_PAGES;
+  dep->de_stoppage = dep->de_ramsize / DP_PAGESIZE;
+
+  ns_init(dep);			/* Initialize DP controller */
+
+  printf("%s: WD80%d3 (%dkB RAM) at %X:%d:%lX - ",
+         dep->de_name,
+         we_type & WET_BRD_16BIT ? 1 : 0,
+         dep->de_ramsize / 1024,
+         dep->de_base_port,
+         dep->de_irq,
+         dep->de_linmem);
+  for (i = 0; i < SA_ADDR_LEN; i += 1)
+	printf("%02X%c", dep->de_address.ea_addr[i],
+	       i < SA_ADDR_LEN - 1 ? ':' : '\n');
+
+  return;
+}
+
+/*===========================================================================*
+ *				we_stop					     *
+ *===========================================================================*/
+static void we_stop(dep)
+dpeth_t *dep;
+{
+
+  if (dep->de_16bit) outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_LAN16E);
+  outb_we(dep, EPL_MSR, E_MSR_RESET);
+  outb_we(dep, EPL_MSR, 0);
+  sys_irqdisable(&dep->de_hook);
+  return;
+}
+
+/*===========================================================================*
+ *				we_aliasing				     *
+ *===========================================================================*/
+static int we_aliasing(dep)
+dpeth_t *dep;
+{
+/* Determine whether wd8003 hardware performs register aliasing. This implies
+ * an old WD8003E board. */
+
+  if (inb_we(dep, EPL_REG1) != inb_we(dep, EPL_EA1)) return 0;
+  if (inb_we(dep, EPL_REG2) != inb_we(dep, EPL_EA2)) return 0;
+  if (inb_we(dep, EPL_REG3) != inb_we(dep, EPL_EA3)) return 0;
+  if (inb_we(dep, EPL_REG4) != inb_we(dep, EPL_EA4)) return 0;
+  if (inb_we(dep, EPL_REG7) != inb_we(dep, EPL_CHKSUM)) return 0;
+  return 1;
+}
+
+/*===========================================================================*
+ *				we_interface_chip			     *
+ *===========================================================================*/
+static int we_interface_chip(dep)
+dpeth_t *dep;
+{
+/* Determine if the board has an interface chip. */
+
+  outb_we(dep, EPL_GP2, 0x35);
+  if (inb_we(dep, EPL_GP2) != 0x35) return 0;
+  outb_we(dep, EPL_GP2, 0x3A);
+  if (inb_we(dep, EPL_GP2) != 0x3A) return 0;
+  return 1;
+}
+
+/*===========================================================================*
+ *				we_16bitboard				     *
+ *===========================================================================*/
+static int we_16bitboard(dep)
+dpeth_t *dep;
+{
+/* Determine whether the board is capable of doing 16 bit memory moves.
+ * If the 16 bit enable bit is unchangable by software we'll assume an
+ * 8 bit board.
+ */
+  int icr;
+  u8_t tlb;
+
+  icr = inb_we(dep, EPL_ICR);
+
+  outb_we(dep, EPL_ICR, icr ^ E_ICR_16BIT);
+  if (inb_we(dep, EPL_ICR) == icr) {
+	tlb = inb_we(dep, EPL_TLB);
+
+	DEBUG(printf("%s: tlb= 0x%x\n", dep->de_name, tlb));
+
+	return tlb == E_TLB_EB || tlb == E_TLB_E ||
+		tlb == E_TLB_SMCE || tlb == E_TLB_SMC8216C;
+  }
+  outb_we(dep, EPL_ICR, icr);
+  return 1;
+}
+
+/*===========================================================================*
+ *				we_16bitslot				     *
+ *===========================================================================*/
+static int we_16bitslot(dep)
+dpeth_t *dep;
+{
+/* Determine if the 16 bit board in plugged into a 16 bit slot.  */
+
+  return !!(inb_we(dep, EPL_ICR) & E_ICR_16BIT);
+}
+
+/*===========================================================================*
+ *				we_ultra				     *
+ *===========================================================================*/
+static int we_ultra(dep)
+dpeth_t *dep;
+{
+/* Determine if we has an '790 chip.  */
+  u8_t tlb;
+
+  tlb = inb_we(dep, EPL_TLB);
+  return tlb == E_TLB_SMC8216C;
+}
+
+#endif				/* ENABLE_WDETH */
+
+/** wd.c **/
Index: /trunk/minix/drivers/dpeth/wd.h
===================================================================
--- /trunk/minix/drivers/dpeth/wd.h	(revision 9)
+++ /trunk/minix/drivers/dpeth/wd.h	(revision 9)
@@ -0,0 +1,105 @@
+/*
+**  File: wd.h
+**   
+**  Created:	before Dec 28, 1992 by Philip Homburg
+**  $PchId: wdeth.h,v 1.4 1995/12/22 08:36:57 philip Exp $
+**
+**  $Log: wd.h,v $
+**  Revision 1.2  2005/08/22 15:17:40  beng
+**  Remove double-blank lines (Al)
+**
+**  Revision 1.1  2005/06/29 10:16:46  beng
+**  Import of dpeth 3c501/3c509b/.. ethernet driver by
+**  Giovanni Falzoni <fgalzoni@inwind.it>.
+**
+**  Revision 2.0  2005/06/26 16:16:46  lsodgf0
+**  Initial revision for Minix 3.0.6
+**
+**  $Id: wd.h,v 1.2 2005/08/22 15:17:40 beng Exp $
+*/
+
+#ifndef WDETH_H
+#define WDETH_H
+
+/* Western Digital Ethercard Plus, or WD8003E card. */
+
+#define EPL_REG0	 0x0	/* Control(write) and status(read) */
+#define EPL_REG1	 0x1
+#define EPL_REG2	 0x2
+#define EPL_REG3	 0x3
+#define EPL_REG4	 0x4
+#define EPL_REG5	 0x5
+#define EPL_REG6	 0x6
+#define EPL_REG7	 0x7
+#define EPL_EA0		 0x8	/* Most significant eaddr byte */
+#define EPL_EA1		 0x9
+#define EPL_EA2		 0xA
+#define EPL_EA3		 0xB
+#define EPL_EA4		 0xC
+#define EPL_EA5		 0xD	/* Least significant eaddr byte */
+#define EPL_TLB		 0xE
+#define EPL_CHKSUM	 0xF	/* sum from epl_ea0 upto here is 0xFF */
+#define EPL_DP8390	0x10	/* NatSemi chip */
+
+#define EPL_MSR		EPL_REG0/* memory select register */
+#define EPL_ICR 	EPL_REG1/* interface configuration register */
+#define EPL_IRR		EPL_REG4/* interrupt request register (IRR) */
+#define EPL_790_HWR	EPL_REG4/* '790 hardware support register */
+#define EPL_LAAR	EPL_REG5/* LA address register (write only) */
+#define EPL_790_ICR	EPL_REG6/* '790 interrupt control register */
+#define EPL_GP2		EPL_REG7/* general purpose register 2 */
+#define EPL_790_B	EPL_EA3	/* '790 memory register */
+#define EPL_790_GCR	EPL_EA5	/* '790 General Control Register */
+
+/* Bits in EPL_MSR */
+#define E_MSR_MEMADDR	0x3F	/* Bits SA18-SA13, SA19 implicit 1 */
+#define E_MSR_MENABLE	0x40	/* Memory Enable */
+#define E_MSR_RESET	0x80	/* Software Reset */
+
+/* Bits in EPL_ICR */
+#define E_ICR_16BIT	0x01	/* 16 bit bus */
+#define E_ICR_IR2	0x04	/* bit 2 of encoded IRQ */
+#define E_ICR_MEMBIT	0x08	/* 583 mem size mask */
+
+/* Bits in EPL_IRR */
+#define E_IRR_IR0	0x20	/* bit 0 of encoded IRQ */
+#define E_IRR_IR1	0x40	/* bit 1 of encoded IRQ */
+#define E_IRR_IEN	0x80	/* enable interrupts */
+
+/* Bits in EPL_LAAR */
+#define E_LAAR_A19	0x01	/* address lines for above 1M ram */
+#define E_LAAR_A20	0x02	/* address lines for above 1M ram */
+#define E_LAAR_A21	0x04	/* address lines for above 1M ram */
+#define E_LAAR_A22	0x08	/* address lines for above 1M ram */
+#define E_LAAR_A23	0x10	/* address lines for above 1M ram */
+#define E_LAAR_SOFTINT	0x20	/* enable software interrupt */
+#define E_LAAR_LAN16E	0x40	/* enables 16 bit RAM for LAN */
+#define E_LAAR_MEM16E	0x80	/* enables 16 bit RAM for host */
+
+/* Bits and values in EPL_TLB */
+#define E_TLB_EB	0x05	/* WD8013EB */
+#define E_TLB_E		0x27	/* WD8013 Elite */
+#define E_TLB_SMCE	0x29	/* SMC Elite 16 */
+#define E_TLB_SMC8216C	0x2B	/* SMC 8216 C */
+
+#define E_TLB_REV	0x1F	/* revision mask */
+#define E_TLB_SOFT	0x20	/* soft config */
+#define E_TLB_RAM	0x40	/* extra ram bit */
+
+/* Bits in EPL_790_HWR */
+#define E_790_HWR_SWH	0x80	/* switch register set */
+
+/* Bits in EPL_790_ICR */
+#define E_790_ICR_EIL	0x01	/* enable interrupts */
+
+/* Bits in EPL_790_GCR when E_790_HWR_SWH is set in EPL_790_HWR */
+#define E_790_GCR_IR0	0x04	/* bit 0 of encoded IRQ */
+#define E_790_GCR_IR1	0x08	/* bit 1 of encoded IRQ */
+#define E_790_GCR_IR2	0x40	/* bit 2 of encoded IRQ */
+
+#define inb_we(dep, reg) (inb(dep->de_base_port+reg))
+#define outb_we(dep, reg, data) (outb(dep->de_base_port+reg, data))
+
+#endif				/* WDETH_H */
+
+/** wd.h **/
Index: /trunk/minix/drivers/drivers.h
===================================================================
--- /trunk/minix/drivers/drivers.h	(revision 9)
+++ /trunk/minix/drivers/drivers.h	(revision 9)
@@ -0,0 +1,33 @@
+/* This is the master header for all device drivers. It includes some other
+ * files and defines the principal constants.
+ */
+#define _POSIX_SOURCE      1	/* tell headers to include POSIX stuff */
+#define _MINIX             1	/* tell headers to include MINIX stuff */
+#define _SYSTEM		   1	/* get negative error number in <errno.h> */
+
+/* The following are so basic, all the *.c files get them automatically. */
+#include <minix/config.h>	/* MUST be first */
+#include <ansi.h>		/* MUST be second */
+#include <minix/type.h>
+#include <minix/com.h>
+#include <minix/dmap.h>
+#include <minix/callnr.h>
+#include <sys/types.h>
+#include <minix/const.h>
+#include <minix/devio.h>
+#include <minix/syslib.h>
+#include <minix/sysutil.h>
+#include <minix/bitmap.h>
+
+#include <ibm/interrupt.h>	/* IRQ vectors and miscellaneous ports */
+#include <ibm/bios.h>		/* BIOS index numbers */
+#include <ibm/ports.h>		/* Well-known ports */
+
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stddef.h>
+#include <errno.h>
+#include <unistd.h>
+
Index: /trunk/minix/drivers/floppy/.depend
===================================================================
--- /trunk/minix/drivers/floppy/.depend	(revision 9)
+++ /trunk/minix/drivers/floppy/.depend	(revision 9)
@@ -0,0 +1,94 @@
+
+floppy.o:	../drivers.h
+floppy.o:	../libdriver/driver.h
+floppy.o:	../libdriver/drvlib.h
+floppy.o:	/usr/include/ansi.h
+floppy.o:	/usr/include/errno.h
+floppy.o:	/usr/include/ibm/bios.h
+floppy.o:	/usr/include/ibm/diskparm.h
+floppy.o:	/usr/include/ibm/interrupt.h
+floppy.o:	/usr/include/ibm/partition.h
+floppy.o:	/usr/include/ibm/ports.h
+floppy.o:	/usr/include/limits.h
+floppy.o:	/usr/include/minix/bitmap.h
+floppy.o:	/usr/include/minix/callnr.h
+floppy.o:	/usr/include/minix/com.h
+floppy.o:	/usr/include/minix/config.h
+floppy.o:	/usr/include/minix/const.h
+floppy.o:	/usr/include/minix/devio.h
+floppy.o:	/usr/include/minix/dmap.h
+floppy.o:	/usr/include/minix/ipc.h
+floppy.o:	/usr/include/minix/partition.h
+floppy.o:	/usr/include/minix/sys_config.h
+floppy.o:	/usr/include/minix/syslib.h
+floppy.o:	/usr/include/minix/sysutil.h
+floppy.o:	/usr/include/minix/type.h
+floppy.o:	/usr/include/minix/u64.h
+floppy.o:	/usr/include/signal.h
+floppy.o:	/usr/include/stddef.h
+floppy.o:	/usr/include/stdlib.h
+floppy.o:	/usr/include/string.h
+floppy.o:	/usr/include/sys/dir.h
+floppy.o:	/usr/include/sys/types.h
+floppy.o:	/usr/include/timers.h
+floppy.o:	/usr/include/unistd.h
+floppy.o:	floppy.c
+floppy.o:	floppy.h
+
+../libdriver/driver.o:	../libdriver/../drivers.h
+../libdriver/driver.o:	../libdriver/driver.c
+../libdriver/driver.o:	../libdriver/driver.h
+../libdriver/driver.o:	/usr/include/ansi.h
+../libdriver/driver.o:	/usr/include/errno.h
+../libdriver/driver.o:	/usr/include/ibm/bios.h
+../libdriver/driver.o:	/usr/include/ibm/interrupt.h
+../libdriver/driver.o:	/usr/include/ibm/ports.h
+../libdriver/driver.o:	/usr/include/limits.h
+../libdriver/driver.o:	/usr/include/minix/bitmap.h
+../libdriver/driver.o:	/usr/include/minix/callnr.h
+../libdriver/driver.o:	/usr/include/minix/com.h
+../libdriver/driver.o:	/usr/include/minix/config.h
+../libdriver/driver.o:	/usr/include/minix/const.h
+../libdriver/driver.o:	/usr/include/minix/devio.h
+../libdriver/driver.o:	/usr/include/minix/dmap.h
+../libdriver/driver.o:	/usr/include/minix/ioctl.h
+../libdriver/driver.o:	/usr/include/minix/ipc.h
+../libdriver/driver.o:	/usr/include/minix/partition.h
+../libdriver/driver.o:	/usr/include/minix/sys_config.h
+../libdriver/driver.o:	/usr/include/minix/syslib.h
+../libdriver/driver.o:	/usr/include/minix/sysutil.h
+../libdriver/driver.o:	/usr/include/minix/type.h
+../libdriver/driver.o:	/usr/include/minix/u64.h
+../libdriver/driver.o:	/usr/include/signal.h
+../libdriver/driver.o:	/usr/include/stddef.h
+../libdriver/driver.o:	/usr/include/stdlib.h
+../libdriver/driver.o:	/usr/include/string.h
+../libdriver/driver.o:	/usr/include/sys/dir.h
+../libdriver/driver.o:	/usr/include/sys/ioc_disk.h
+../libdriver/driver.o:	/usr/include/sys/types.h
+../libdriver/driver.o:	/usr/include/unistd.h
+
+../libdriver/drvlib.o:	../libdriver/driver.h
+../libdriver/drvlib.o:	../libdriver/drvlib.c
+../libdriver/drvlib.o:	../libdriver/drvlib.h
+../libdriver/drvlib.o:	/usr/include/ansi.h
+../libdriver/drvlib.o:	/usr/include/errno.h
+../libdriver/drvlib.o:	/usr/include/ibm/partition.h
+../libdriver/drvlib.o:	/usr/include/limits.h
+../libdriver/drvlib.o:	/usr/include/minix/callnr.h
+../libdriver/drvlib.o:	/usr/include/minix/com.h
+../libdriver/drvlib.o:	/usr/include/minix/config.h
+../libdriver/drvlib.o:	/usr/include/minix/const.h
+../libdriver/drvlib.o:	/usr/include/minix/devio.h
+../libdriver/drvlib.o:	/usr/include/minix/ipc.h
+../libdriver/drvlib.o:	/usr/include/minix/partition.h
+../libdriver/drvlib.o:	/usr/include/minix/sys_config.h
+../libdriver/drvlib.o:	/usr/include/minix/syslib.h
+../libdriver/drvlib.o:	/usr/include/minix/sysutil.h
+../libdriver/drvlib.o:	/usr/include/minix/type.h
+../libdriver/drvlib.o:	/usr/include/minix/u64.h
+../libdriver/drvlib.o:	/usr/include/stddef.h
+../libdriver/drvlib.o:	/usr/include/string.h
+../libdriver/drvlib.o:	/usr/include/sys/dir.h
+../libdriver/drvlib.o:	/usr/include/sys/types.h
+../libdriver/drvlib.o:	/usr/include/unistd.h
Index: /trunk/minix/drivers/floppy/Makefile
===================================================================
--- /trunk/minix/drivers/floppy/Makefile	(revision 9)
+++ /trunk/minix/drivers/floppy/Makefile	(revision 9)
@@ -0,0 +1,45 @@
+# Makefile for the floppy disk driver (FLOPPY)
+DRIVER = floppy
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+MAKE = exec make
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsys -lsysutil -ltimers
+
+OBJ = floppy.o 
+LIBDRIVER = $d/libdriver/driver.o $d/libdriver/drvlib.o
+
+# build local binary
+all build:	$(DRIVER)
+$(DRIVER):	$(OBJ) $(LIBDRIVER)
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBDRIVER) $(LIBS)
+	install -S 4096 $(DRIVER)
+
+$(LIBDRIVER): 
+	cd $d/libdriver && $(MAKE) 
+
+# install with other drivers
+install:	/sbin/$(DRIVER)
+/sbin/$(DRIVER):	$(DRIVER)
+	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f $(DRIVER) *.o *.bak 
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c ../libdriver/*.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/floppy/floppy.c
===================================================================
--- /trunk/minix/drivers/floppy/floppy.c	(revision 9)
+++ /trunk/minix/drivers/floppy/floppy.c	(revision 9)
@@ -0,0 +1,1287 @@
+/* This file contains the device dependent part of the driver for the Floppy
+ * Disk Controller (FDC) using the NEC PD765 chip.
+ *
+ * The file contains two entry points:
+ *
+ *   floppy_task:   main entry when system is brought up
+ *
+ * Changes:
+ *   Sep 11, 2005   code cleanup (Andy Tanenbaum)
+ *   Dec 01, 2004   floppy driver moved to user-space (Jorrit N. Herder)
+ *   Sep 15, 2004   sync alarms/ local timer management  (Jorrit N. Herder)
+ *   Aug 12, 2003   null seek no interrupt fix  (Mike Haertel)
+ *   May 14, 2000   d-d/i rewrite  (Kees J. Bot)
+ *   Apr 04, 1992   device dependent/independent split  (Kees J. Bot)
+ *   Mar 27, 1992   last details on density checking  (Kees J. Bot)
+ *   Feb 14, 1992   check drive density on opens only  (Andy Tanenbaum)
+ *	     1991   len[] / motors / reset / step rate / ...  (Bruce Evans)
+ *   May 13, 1991   renovated the errors loop  (Don Chapman)
+ *           1989   I/O vector to keep up with 1-1 interleave  (Bruce Evans)
+ *   Jan 06, 1988   allow 1.44 MB diskettes  (Al Crew)
+ *   Nov 28, 1986   better resetting for 386  (Peter Kay)
+ *   Oct 27, 1986   fdc_results fixed for 8 MHz  (Jakob Schripsema)
+ */
+
+#include "floppy.h"
+#include <timers.h>
+#include <ibm/diskparm.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+
+/* I/O Ports used by floppy disk task. */
+#define DOR            0x3F2	/* motor drive control bits */
+#define FDC_STATUS     0x3F4	/* floppy disk controller status register */
+#define FDC_DATA       0x3F5	/* floppy disk controller data register */
+#define FDC_RATE       0x3F7	/* transfer rate register */
+#define DMA_ADDR       0x004	/* port for low 16 bits of DMA address */
+#define DMA_TOP        0x081	/* port for top 8 bits of 24-bit DMA addr */
+#define DMA_COUNT      0x005	/* port for DMA count (count =  bytes - 1) */
+#define DMA_FLIPFLOP   0x00C	/* DMA byte pointer flip-flop */
+#define DMA_MODE       0x00B	/* DMA mode port */
+#define DMA_INIT       0x00A	/* DMA init port */
+#define DMA_RESET_VAL  0x006
+
+#define DMA_ADDR_MASK  0xFFFFFF	/* mask to verify DMA address is 24-bit */
+
+/* Status registers returned as result of operation. */
+#define ST0             0x00	/* status register 0 */
+#define ST1             0x01	/* status register 1 */
+#define ST2             0x02	/* status register 2 */
+#define ST3             0x00	/* status register 3 (return by DRIVE_SENSE) */
+#define ST_CYL          0x03	/* slot where controller reports cylinder */
+#define ST_HEAD         0x04	/* slot where controller reports head */
+#define ST_SEC          0x05	/* slot where controller reports sector */
+#define ST_PCN          0x01	/* slot where controller reports present cyl */
+
+/* Fields within the I/O ports. */
+/* Main status register. */
+#define CTL_BUSY        0x10	/* bit is set when read or write in progress */
+#define DIRECTION       0x40	/* bit is set when reading data reg is valid */
+#define MASTER          0x80	/* bit is set when data reg can be accessed */
+
+/* Digital output port (DOR). */
+#define MOTOR_SHIFT        4	/* high 4 bits control the motors in DOR */
+#define ENABLE_INT      0x0C	/* used for setting DOR port */
+
+/* ST0. */
+#define ST0_BITS_TRANS  0xD8	/* check 4 bits of status */
+#define TRANS_ST0       0x00	/* 4 bits of ST0 for READ/WRITE */
+#define ST0_BITS_SEEK   0xF8	/* check top 5 bits of seek status */
+#define SEEK_ST0        0x20	/* top 5 bits of ST0 for SEEK */
+
+/* ST1. */
+#define BAD_SECTOR      0x05	/* if these bits are set in ST1, recalibrate */
+#define WRITE_PROTECT   0x02	/* bit is set if diskette is write protected */
+
+/* ST2. */
+#define BAD_CYL         0x1F	/* if any of these bits are set, recalibrate */
+
+/* ST3 (not used). */
+#define ST3_FAULT       0x80	/* if this bit is set, drive is sick */
+#define ST3_WR_PROTECT  0x40	/* set when diskette is write protected */
+#define ST3_READY       0x20	/* set when drive is ready */
+
+/* Floppy disk controller command bytes. */
+#define FDC_SEEK        0x0F	/* command the drive to seek */
+#define FDC_READ        0xE6	/* command the drive to read */
+#define FDC_WRITE       0xC5	/* command the drive to write */
+#define FDC_SENSE       0x08	/* command the controller to tell its status */
+#define FDC_RECALIBRATE 0x07	/* command the drive to go to cyl 0 */
+#define FDC_SPECIFY     0x03	/* command the drive to accept params */
+#define FDC_READ_ID     0x4A	/* command the drive to read sector identity */
+#define FDC_FORMAT      0x4D	/* command the drive to format a track */
+
+/* DMA channel commands. */
+#define DMA_READ        0x46	/* DMA read opcode */
+#define DMA_WRITE       0x4A	/* DMA write opcode */
+
+/* Parameters for the disk drive. */
+#define HC_SIZE         2880	/* # sectors on largest legal disk (1.44MB) */
+#define NR_HEADS        0x02	/* two heads (i.e., two tracks/cylinder) */
+#define MAX_SECTORS	  18	/* largest # sectors per track */
+#define DTL             0xFF	/* determines data length (sector size) */
+#define SPEC2           0x02	/* second parameter to SPECIFY */
+#define MOTOR_OFF      (3*HZ)	/* how long to wait before stopping motor */
+#define WAKEUP	       (2*HZ)	/* timeout on I/O, FDC won't quit. */
+
+/* Error codes */
+#define ERR_SEEK         (-1)	/* bad seek */
+#define ERR_TRANSFER     (-2)	/* bad transfer */
+#define ERR_STATUS       (-3)	/* something wrong when getting status */
+#define ERR_READ_ID      (-4)	/* bad read id */
+#define ERR_RECALIBRATE  (-5)	/* recalibrate didn't work properly */
+#define ERR_DRIVE        (-6)	/* something wrong with a drive */
+#define ERR_WR_PROTECT   (-7)	/* diskette is write protected */
+#define ERR_TIMEOUT      (-8)	/* interrupt timeout */
+
+/* No retries on some errors. */
+#define err_no_retry(err)	((err) <= ERR_WR_PROTECT)
+
+/* Encoding of drive type in minor device number. */
+#define DEV_TYPE_BITS   0x7C	/* drive type + 1, if nonzero */
+#define DEV_TYPE_SHIFT     2	/* right shift to normalize type bits */
+#define FORMAT_DEV_BIT  0x80	/* bit in minor to turn write into format */
+
+/* Miscellaneous. */
+#define MAX_ERRORS         6	/* how often to try rd/wt before quitting */
+#define MAX_RESULTS        7	/* max number of bytes controller returns */
+#define NR_DRIVES          2	/* maximum number of drives */
+#define DIVISOR          128	/* used for sector size encoding */
+#define SECTOR_SIZE_CODE   2	/* code to say "512" to the controller */
+#define TIMEOUT_MICROS   500000L	/* microseconds waiting for FDC */
+#define TIMEOUT_TICKS     30	/* ticks waiting for FDC */
+#define NT                 7	/* number of diskette/drive combinations */
+#define UNCALIBRATED       0	/* drive needs to be calibrated at next use */
+#define CALIBRATED         1	/* no calibration needed */
+#define BASE_SECTOR        1	/* sectors are numbered starting at 1 */
+#define NO_SECTOR        (-1)	/* current sector unknown */
+#define NO_CYL		 (-1)	/* current cylinder unknown, must seek */
+#define NO_DENS		 100	/* current media unknown */
+#define BSY_IDLE	   0	/* busy doing nothing */
+#define BSY_IO		   1	/* busy doing I/O */
+#define BSY_WAKEN	   2	/* got a wakeup call */
+
+/* Seven combinations of diskette/drive are supported.
+ *
+ * # Diskette Drive  Sectors  Tracks   Rotation Data-rate  Comment
+ * 0   360K    360K     9       40     300 RPM  250 kbps   Standard PC DSDD
+ * 1   1.2M    1.2M    15       80     360 RPM  500 kbps   AT disk in AT drive
+ * 2   360K    720K     9       40     300 RPM  250 kbps   Quad density PC
+ * 3   720K    720K     9       80     300 RPM  250 kbps   Toshiba, et al.
+ * 4   360K    1.2M     9       40     360 RPM  300 kbps   PC disk in AT drive
+ * 5   720K    1.2M     9       80     360 RPM  300 kbps   Toshiba in AT drive
+ * 6   1.44M   1.44M   18	80     300 RPM  500 kbps   PS/2, et al.
+ *
+ * In addition, 720K diskettes can be read in 1.44MB drives, but that does
+ * not need a different set of parameters.  This combination uses
+ *
+ * 3   720K    1.44M    9       80     300 RPM  250 kbps   PS/2, et al.
+ */
+PRIVATE struct density {
+	u8_t	secpt;		/* sectors per track */
+	u8_t	cyls;		/* tracks per side */
+	u8_t	steps;		/* steps per cylinder (2 = double step) */
+	u8_t	test;		/* sector to try for density test */
+	u8_t	rate;		/* data rate (2=250, 1=300, 0=500 kbps) */
+	u8_t	start;		/* motor start (clock ticks) */
+	u8_t	gap;		/* gap size */
+	u8_t	spec1;		/* first specify byte (SRT/HUT) */
+} fdensity[NT] = {
+	{  9, 40, 1, 4*9, 2, 4*HZ/8, 0x2A, 0xDF },	/*  360K / 360K  */
+	{ 15, 80, 1,  14, 0, 4*HZ/8, 0x1B, 0xDF },	/*  1.2M / 1.2M  */
+	{  9, 40, 2, 2*9, 2, 4*HZ/8, 0x2A, 0xDF },	/*  360K / 720K  */
+	{  9, 80, 1, 4*9, 2, 6*HZ/8, 0x2A, 0xDF },	/*  720K / 720K  */
+	{  9, 40, 2, 2*9, 1, 4*HZ/8, 0x23, 0xDF },	/*  360K / 1.2M  */
+	{  9, 80, 1, 4*9, 1, 4*HZ/8, 0x23, 0xDF },	/*  720K / 1.2M  */
+	{ 18, 80, 1,  17, 0, 6*HZ/8, 0x1B, 0xCF },	/* 1.44M / 1.44M */
+};
+
+/* The following table is used with the test_sector array to recognize a
+ * drive/floppy combination.  The sector to test has been determined by
+ * looking at the differences in gap size, sectors/track, and double stepping.
+ * This means that types 0 and 3 can't be told apart, only the motor start
+ * time differs.  If a read test succeeds then the drive is limited to the
+ * set of densities it can support to avoid unnecessary tests in the future.
+ */
+
+#define b(d)	(1 << (d))	/* bit for density d. */
+
+PRIVATE struct test_order {
+	u8_t	t_density;	/* floppy/drive type */
+	u8_t	t_class;	/* limit drive to this class of densities */
+} test_order[NT-1] = {
+	{ 6,  b(3) | b(6) },		/* 1.44M  {720K, 1.44M} */
+	{ 1,  b(1) | b(4) | b(5) },	/* 1.2M   {1.2M, 360K, 720K} */
+	{ 3,  b(2) | b(3) | b(6) },	/* 720K   {360K, 720K, 1.44M} */
+	{ 4,  b(1) | b(4) | b(5) },	/* 360K   {1.2M, 360K, 720K} */
+	{ 5,  b(1) | b(4) | b(5) },	/* 720K   {1.2M, 360K, 720K} */
+	{ 2,  b(2) | b(3) },		/* 360K   {360K, 720K} */
+	/* Note that type 0 is missing, type 3 can read/write it too, which is
+	 * why the type 3 parameters have been pessimized to be like type 0.
+	 */
+};
+
+/* Variables. */
+PRIVATE struct floppy {		/* main drive struct, one entry per drive */
+  unsigned fl_curcyl;		/* current cylinder */
+  unsigned fl_hardcyl;		/* hardware cylinder, as opposed to: */
+  unsigned fl_cylinder;		/* cylinder number addressed */
+  unsigned fl_sector;		/* sector addressed */
+  unsigned fl_head;		/* head number addressed */
+  char fl_calibration;		/* CALIBRATED or UNCALIBRATED */
+  u8_t fl_density;		/* NO_DENS = ?, 0 = 360K; 1 = 360K/1.2M; etc.*/
+  u8_t fl_class;		/* bitmap for possible densities */
+  timer_t fl_tmr_stop;		/* timer to stop motor */
+  struct device fl_geom;	/* Geometry of the drive */
+  struct device fl_part[NR_PARTITIONS];  /* partition's base & size */
+} floppy[NR_DRIVES];
+
+PRIVATE int irq_hook_id;	/* id of irq hook at the kernel */
+PRIVATE int motor_status;	/* bitmap of current motor status */
+PRIVATE int need_reset;		/* set to 1 when controller must be reset */
+PRIVATE unsigned f_drive;	/* selected drive */
+PRIVATE unsigned f_device;	/* selected minor device */
+PRIVATE struct floppy *f_fp;	/* current drive */
+PRIVATE struct density *f_dp;	/* current density parameters */
+PRIVATE struct density *prev_dp;/* previous density parameters */
+PRIVATE unsigned f_sectors;	/* equal to f_dp->secpt (needed a lot) */
+PRIVATE u16_t f_busy;		/* BSY_IDLE, BSY_IO, BSY_WAKEN */
+PRIVATE struct device *f_dv;	/* device's base and size */
+PRIVATE struct disk_parameter_s fmt_param; /* parameters for format */
+PRIVATE u8_t f_results[MAX_RESULTS];/* the controller can give lots of output */
+
+/* The floppy uses various timers. These are managed by the floppy driver
+ * itself, because only a single synchronous alarm is available per process.
+ * Besides the 'f_tmr_timeout' timer below, the floppy structure for each
+ * floppy disk drive contains a 'fl_tmr_stop' timer. 
+ */
+PRIVATE timer_t f_tmr_timeout;		/* timer for various timeouts */
+PRIVATE timer_t *f_timers;		/* queue of floppy timers */
+PRIVATE clock_t f_next_timeout; 	/* the next timeout time */
+FORWARD _PROTOTYPE( void f_expire_tmrs, (struct driver *dp, message *m_ptr) );
+FORWARD _PROTOTYPE( void f_set_timer, (timer_t *tp, clock_t delta,
+						 tmr_func_t watchdog) 	);
+FORWARD _PROTOTYPE( void stop_motor, (timer_t *tp) 			);
+FORWARD _PROTOTYPE( void f_timeout, (timer_t *tp) 			);
+
+FORWARD _PROTOTYPE( struct device *f_prepare, (int device) 		);
+FORWARD _PROTOTYPE( char *f_name, (void) 				);
+FORWARD _PROTOTYPE( void f_cleanup, (void) 				);
+FORWARD _PROTOTYPE( int f_transfer, (int proc_nr, int opcode, off_t position,
+					iovec_t *iov, unsigned nr_req) 	);
+FORWARD _PROTOTYPE( int dma_setup, (int opcode) 			);
+FORWARD _PROTOTYPE( void start_motor, (void) 				);
+FORWARD _PROTOTYPE( int seek, (void) 					);
+FORWARD _PROTOTYPE( int fdc_transfer, (int opcode) 			);
+FORWARD _PROTOTYPE( int fdc_results, (void) 				);
+FORWARD _PROTOTYPE( int fdc_command, (u8_t *cmd, int len) 		);
+FORWARD _PROTOTYPE( void fdc_out, (int val) 				);
+FORWARD _PROTOTYPE( int recalibrate, (void) 				);
+FORWARD _PROTOTYPE( void f_reset, (void) 				);
+FORWARD _PROTOTYPE( int f_intr_wait, (void) 				);
+FORWARD _PROTOTYPE( int read_id, (void) 				);
+FORWARD _PROTOTYPE( int f_do_open, (struct driver *dp, message *m_ptr) 	);
+FORWARD _PROTOTYPE( void floppy_stop, (struct driver *dp, message *m_ptr));
+FORWARD _PROTOTYPE( int test_read, (int density)	 		);
+FORWARD _PROTOTYPE( void f_geometry, (struct partition *entry)		);
+
+/* Entry points to this driver. */
+PRIVATE struct driver f_dtab = {
+  f_name,	/* current device's name */
+  f_do_open,	/* open or mount request, sense type of diskette */
+  do_nop,	/* nothing on a close */
+  do_diocntl,	/* get or set a partitions geometry */
+  f_prepare,	/* prepare for I/O on a given minor device */
+  f_transfer,	/* do the I/O */
+  f_cleanup,	/* cleanup before sending reply to user process */
+  f_geometry,	/* tell the geometry of the diskette */
+  floppy_stop,	/* floppy cleanup on shutdown */
+  f_expire_tmrs,/* expire all alarm timers */
+  nop_cancel,
+  nop_select,
+  NULL,
+  NULL
+};
+
+/*===========================================================================*
+ *				floppy_task				     *
+ *===========================================================================*/
+PUBLIC void main()
+{
+/* Initialize the floppy structure and the timers. */
+
+  struct floppy *fp;
+  int s;
+
+  f_next_timeout = TMR_NEVER;
+  tmr_inittimer(&f_tmr_timeout);
+
+  for (fp = &floppy[0]; fp < &floppy[NR_DRIVES]; fp++) {
+	fp->fl_curcyl = NO_CYL;
+	fp->fl_density = NO_DENS;
+	fp->fl_class = ~0;
+	tmr_inittimer(&fp->fl_tmr_stop);
+  }
+
+  /* Set IRQ policy, only request notifications, do not automatically 
+   * reenable interrupts. ID return on interrupt is the IRQ line number. 
+   */
+  irq_hook_id = FLOPPY_IRQ;
+  if ((s=sys_irqsetpolicy(FLOPPY_IRQ, 0, &irq_hook_id )) != OK)
+  	panic("FLOPPY", "Couldn't set IRQ policy", s);
+  if ((s=sys_irqenable(&irq_hook_id)) != OK)
+  	panic("FLOPPY", "Couldn't enable IRQs", s);
+
+  driver_task(&f_dtab);
+}
+
+/*===========================================================================*
+ *				f_expire_tmrs				     *
+ *===========================================================================*/
+PRIVATE void f_expire_tmrs(struct driver *dp, message *m_ptr)
+{
+/* A synchronous alarm message was received. Check if there are any expired 
+ * timers. Possibly reschedule the next alarm.  
+ */
+  clock_t now;				/* current time */
+  timer_t *tp;
+  int s;
+
+  /* Get the current time to compare the timers against. */
+  if ((s=getuptime(&now)) != OK)
+ 	panic("FLOPPY","Couldn't get uptime from clock.", s);
+
+  /* Scan the timers queue for expired timers. Dispatch the watchdog function
+   * for each expired timers. FLOPPY watchdog functions are f_tmr_timeout() 
+   * and stop_motor(). Possibly a new alarm call must be scheduled.
+   */
+  tmrs_exptimers(&f_timers, now, NULL);
+  if (f_timers == NULL) {
+  	f_next_timeout = TMR_NEVER;
+  } else {  					  /* set new sync alarm */
+  	f_next_timeout = f_timers->tmr_exp_time;
+  	if ((s=sys_setalarm(f_next_timeout, 1)) != OK)
+ 		panic("FLOPPY","Couldn't set synchronous alarm.", s);
+  }
+}
+
+/*===========================================================================*
+ *				f_set_timer				     *
+ *===========================================================================*/
+PRIVATE void f_set_timer(tp, delta, watchdog)
+timer_t *tp;				/* timer to be set */
+clock_t delta;				/* in how many ticks */
+tmr_func_t watchdog;			/* watchdog function to be called */
+{
+  clock_t now;				/* current time */
+  int s;
+
+  /* Get the current time. */
+  if ((s=getuptime(&now)) != OK)
+ 	panic("FLOPPY","Couldn't get uptime from clock.", s);
+
+  /* Add the timer to the local timer queue. */
+  tmrs_settimer(&f_timers, tp, now + delta, watchdog, NULL);
+
+  /* Possibly reschedule an alarm call. This happens when the front of the 
+   * timers queue was reinserted at another position, i.e., when a timer was 
+   * reset, or when a new timer was added in front. 
+   */
+  if (f_timers->tmr_exp_time != f_next_timeout) {
+  	f_next_timeout = f_timers->tmr_exp_time; 
+  	if ((s=sys_setalarm(f_next_timeout, 1)) != OK)
+ 		panic("FLOPPY","Couldn't set synchronous alarm.", s);
+  }
+}
+
+/*===========================================================================*
+ *				f_prepare				     *
+ *===========================================================================*/
+PRIVATE struct device *f_prepare(device)
+int device;
+{
+/* Prepare for I/O on a device. */
+
+  f_device = device;
+  f_drive = device & ~(DEV_TYPE_BITS | FORMAT_DEV_BIT);
+  if (f_drive < 0 || f_drive >= NR_DRIVES) return(NIL_DEV);
+
+  f_fp = &floppy[f_drive];
+  f_dv = &f_fp->fl_geom;
+  if (f_fp->fl_density < NT) {
+	f_dp = &fdensity[f_fp->fl_density];
+	f_sectors = f_dp->secpt;
+	f_fp->fl_geom.dv_size = mul64u((long) (NR_HEADS * f_sectors
+					* f_dp->cyls), SECTOR_SIZE);
+  }
+
+  /* A partition? */
+  if ((device &= DEV_TYPE_BITS) >= MINOR_fd0p0)
+	f_dv = &f_fp->fl_part[(device - MINOR_fd0p0) >> DEV_TYPE_SHIFT];
+
+  return f_dv;
+}
+
+/*===========================================================================*
+ *				f_name					     *
+ *===========================================================================*/
+PRIVATE char *f_name()
+{
+/* Return a name for the current device. */
+  static char name[] = "fd0";
+
+  name[2] = '0' + f_drive;
+  return name;
+}
+
+/*===========================================================================*
+ *				f_cleanup				     *
+ *===========================================================================*/
+PRIVATE void f_cleanup()
+{
+  /* Start a timer to turn the motor off in a few seconds. */
+  tmr_arg(&f_fp->fl_tmr_stop)->ta_int = f_drive;
+  f_set_timer(&f_fp->fl_tmr_stop, MOTOR_OFF, stop_motor);
+
+  /* Exiting the floppy driver, so forget where we are. */
+  f_fp->fl_sector = NO_SECTOR;
+}
+
+/*===========================================================================*
+ *				f_transfer				     *
+ *===========================================================================*/
+PRIVATE int f_transfer(proc_nr, opcode, position, iov, nr_req)
+int proc_nr;			/* process doing the request */
+int opcode;			/* DEV_GATHER or DEV_SCATTER */
+off_t position;			/* offset on device to read or write */
+iovec_t *iov;			/* pointer to read or write request vector */
+unsigned nr_req;		/* length of request vector */
+{
+  struct floppy *fp = f_fp;
+  iovec_t *iop, *iov_end = iov + nr_req;
+  int s, r, errors;
+  unsigned block;	/* Seen any 32M floppies lately? */
+  unsigned nbytes, count, chunk, sector;
+  unsigned long dv_size = cv64ul(f_dv->dv_size);
+  vir_bytes user_addr;
+  vir_bytes uaddrs[MAX_SECTORS], *up;
+  u8_t cmd[3];
+
+  /* Check disk address. */
+  if ((position & SECTOR_MASK) != 0) return(EINVAL);
+
+  errors = 0;
+  while (nr_req > 0) {
+	/* How many bytes to transfer? */
+	nbytes = 0;
+	for (iop = iov; iop < iov_end; iop++) nbytes += iop->iov_size;
+
+	/* Which block on disk and how close to EOF? */
+	if (position >= dv_size) return(OK);		/* At EOF */
+	if (position + nbytes > dv_size) nbytes = dv_size - position;
+	block = div64u(add64ul(f_dv->dv_base, position), SECTOR_SIZE);
+
+	if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
+
+	/* Using a formatting device? */
+	if (f_device & FORMAT_DEV_BIT) {
+		if (opcode != DEV_SCATTER) return(EIO);
+		if (iov->iov_size < SECTOR_SIZE + sizeof(fmt_param))
+			return(EINVAL);
+
+		if ((s=sys_datacopy(proc_nr, iov->iov_addr + SECTOR_SIZE,
+			SELF, (vir_bytes) &fmt_param, 
+			(phys_bytes) sizeof(fmt_param))) != OK)
+			panic("FLOPPY", "Sys_vircopy failed", s);
+
+		/* Check that the number of sectors in the data is reasonable,
+		 * to avoid division by 0.  Leave checking of other data to
+		 * the FDC.
+		 */
+		if (fmt_param.sectors_per_cylinder == 0) return(EIO);
+
+		/* Only the first sector of the parameters now needed. */
+		iov->iov_size = nbytes = SECTOR_SIZE;
+	}
+
+	/* Only try one sector if there were errors. */
+	if (errors > 0) nbytes = SECTOR_SIZE;
+
+	/* Compute cylinder and head of the track to access. */
+	fp->fl_cylinder = block / (NR_HEADS * f_sectors);
+	fp->fl_hardcyl = fp->fl_cylinder * f_dp->steps;
+	fp->fl_head = (block % (NR_HEADS * f_sectors)) / f_sectors;
+
+	/* For each sector on this track compute the user address it is to
+	 * go or to come from.
+	 */
+	for (up = uaddrs; up < uaddrs + MAX_SECTORS; up++) *up = 0;
+	count = 0;
+	iop = iov;
+	sector = block % f_sectors;
+	for (;;) {
+		user_addr = iop->iov_addr;
+		chunk = iop->iov_size;
+		if ((chunk & SECTOR_MASK) != 0) return(EINVAL);
+
+		while (chunk > 0) {
+			uaddrs[sector++] = user_addr;
+			chunk -= SECTOR_SIZE;
+			user_addr += SECTOR_SIZE;
+			count += SECTOR_SIZE;
+			if (sector == f_sectors || count == nbytes)
+				goto track_set_up;
+		}
+		iop++;
+	}
+  track_set_up:
+
+	/* First check to see if a reset is needed. */
+	if (need_reset) f_reset();
+
+	/* See if motor is running; if not, turn it on and wait. */
+	start_motor();
+
+	/* Set the stepping rate and data rate */
+	if (f_dp != prev_dp) {
+		cmd[0] = FDC_SPECIFY;
+		cmd[1] = f_dp->spec1;
+		cmd[2] = SPEC2;
+		(void) fdc_command(cmd, 3);
+		if ((s=sys_outb(FDC_RATE, f_dp->rate)) != OK)
+			panic("FLOPPY","Sys_outb failed", s);
+		prev_dp = f_dp;
+	}
+
+	/* If we are going to a new cylinder, perform a seek. */
+	r = seek();
+
+	/* Avoid read_id() if we don't plan to read much. */
+	if (fp->fl_sector == NO_SECTOR && count < (6 * SECTOR_SIZE))
+		fp->fl_sector = 0;
+
+	for (nbytes = 0; nbytes < count; nbytes += SECTOR_SIZE) {
+		if (fp->fl_sector == NO_SECTOR) {
+			/* Find out what the current sector is.  This often
+			 * fails right after a seek, so try it twice.
+			 */
+			if (r == OK && read_id() != OK) r = read_id();
+		}
+
+		/* Look for the next job in uaddrs[] */
+		if (r == OK) {
+			for (;;) {
+				if (fp->fl_sector >= f_sectors)
+					fp->fl_sector = 0;
+
+				up = &uaddrs[fp->fl_sector];
+				if (*up != 0) break;
+				fp->fl_sector++;
+			}
+		}
+
+		if (r == OK && opcode == DEV_SCATTER) {
+			/* Copy the user bytes to the DMA buffer. */
+			if ((s=sys_datacopy(proc_nr, *up,  SELF, 
+				(vir_bytes) tmp_buf,
+				(phys_bytes) SECTOR_SIZE)) != OK)
+			panic("FLOPPY", "Sys_vircopy failed", s);
+		}
+
+		/* Set up the DMA chip and perform the transfer. */
+		if (r == OK) {
+			if (dma_setup(opcode) != OK) {
+				/* This can only fail for addresses above 16MB
+				 * that cannot be handled by the controller, 
+ 				 * because it uses 24-bit addressing.
+				 */
+				return(EIO);
+			}
+			r = fdc_transfer(opcode);
+		}
+
+		if (r == OK && opcode == DEV_GATHER) {
+			/* Copy the DMA buffer to user space. */
+			if ((s=sys_datacopy(SELF, (vir_bytes) tmp_buf, 
+				proc_nr, *up, 
+				(phys_bytes) SECTOR_SIZE)) != OK)
+			panic("FLOPPY", "Sys_vircopy failed", s);
+		}
+
+		if (r != OK) {
+			/* Don't retry if write protected or too many errors. */
+			if (err_no_retry(r) || ++errors == MAX_ERRORS) {
+				return(EIO);
+			}
+
+			/* Recalibrate if halfway. */
+			if (errors == MAX_ERRORS / 2)
+				fp->fl_calibration = UNCALIBRATED;
+
+			nbytes = 0;
+			break;		/* retry */
+		}
+	}
+
+	/* Book the bytes successfully transferred. */
+	position += nbytes;
+	for (;;) {
+		if (nbytes < iov->iov_size) {
+			/* Not done with this one yet. */
+			iov->iov_addr += nbytes;
+			iov->iov_size -= nbytes;
+			break;
+		}
+		nbytes -= iov->iov_size;
+		iov->iov_addr += iov->iov_size;
+		iov->iov_size = 0;
+		if (nbytes == 0) {
+			/* The rest is optional, so we return to give FS a
+			 * chance to think it over.
+			 */
+			return(OK);
+		}
+		iov++;
+		nr_req--;
+	}
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *				dma_setup				     *
+ *===========================================================================*/
+PRIVATE int dma_setup(opcode)
+int opcode;			/* DEV_GATHER or DEV_SCATTER */
+{
+/* The IBM PC can perform DMA operations by using the DMA chip.  To use it,
+ * the DMA (Direct Memory Access) chip is loaded with the 20-bit memory address
+ * to be read from or written to, the byte count minus 1, and a read or write
+ * opcode.  This routine sets up the DMA chip.  Note that the chip is not
+ * capable of doing a DMA across a 64K boundary (e.g., you can't read a
+ * 512-byte block starting at physical address 65520).
+ *
+ * Warning! Also note that it's not possible to do DMA above 16 MB because 
+ * the ISA bus uses 24-bit addresses. Addresses above 16 MB therefore will 
+ * be interpreted modulo 16 MB, dangerously overwriting arbitrary memory. 
+ * A check here denies the I/O if the address is out of range. 
+ */
+  pvb_pair_t byte_out[9];
+  int s;
+
+  /* First check the DMA memory address not to exceed maximum. */
+  if (tmp_phys != (tmp_phys & DMA_ADDR_MASK)) {
+	report("FLOPPY", "DMA denied because address out of range", NO_NUM);
+	return(EIO);
+  }
+
+  /* Set up the DMA registers.  (The comment on the reset is a bit strong,
+   * it probably only resets the floppy channel.)
+   */
+  pv_set(byte_out[0], DMA_INIT, DMA_RESET_VAL);	/* reset the dma controller */
+  pv_set(byte_out[1], DMA_FLIPFLOP, 0);		/* write anything to reset it */
+  pv_set(byte_out[2], DMA_MODE, opcode == DEV_SCATTER ? DMA_WRITE : DMA_READ);
+  pv_set(byte_out[3], DMA_ADDR, (unsigned) tmp_phys >>  0);
+  pv_set(byte_out[4], DMA_ADDR, (unsigned) tmp_phys >>  8);
+  pv_set(byte_out[5], DMA_TOP, (unsigned) (tmp_phys >> 16));
+  pv_set(byte_out[6], DMA_COUNT, (((SECTOR_SIZE - 1) >> 0) & 0xff));
+  pv_set(byte_out[7], DMA_COUNT, (SECTOR_SIZE - 1) >> 8);
+  pv_set(byte_out[8], DMA_INIT, 2);		/* some sort of enable */
+
+  if ((s=sys_voutb(byte_out, 9)) != OK)
+  	panic("FLOPPY","Sys_voutb in dma_setup() failed", s);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				start_motor				     *
+ *===========================================================================*/
+PRIVATE void start_motor()
+{
+/* Control of the floppy disk motors is a big pain.  If a motor is off, you
+ * have to turn it on first, which takes 1/2 second.  You can't leave it on
+ * all the time, since that would wear out the diskette.  However, if you turn
+ * the motor off after each operation, the system performance will be awful.
+ * The compromise used here is to leave it on for a few seconds after each
+ * operation.  If a new operation is started in that interval, it need not be
+ * turned on again.  If no new operation is started, a timer goes off and the
+ * motor is turned off.  I/O port DOR has bits to control each of 4 drives.
+ */
+
+  int s, motor_bit, running;
+  message mess;
+
+  motor_bit = 1 << f_drive;		/* bit mask for this drive */
+  running = motor_status & motor_bit;	/* nonzero if this motor is running */
+  motor_status |= motor_bit;		/* want this drive running too */
+
+  if ((s=sys_outb(DOR,
+  		(motor_status << MOTOR_SHIFT) | ENABLE_INT | f_drive)) != OK)
+	panic("FLOPPY","Sys_outb in start_motor() failed", s);
+
+  /* If the motor was already running, we don't have to wait for it. */
+  if (running) return;			/* motor was already running */
+
+  /* Set an alarm timer to force a timeout if the hardware does not interrupt
+   * in time. Expect HARD_INT message, but check for SYN_ALARM timeout.
+   */ 
+  f_set_timer(&f_tmr_timeout, f_dp->start, f_timeout);
+  f_busy = BSY_IO;
+  do {
+  	receive(ANY, &mess); 
+  	if (mess.m_type == SYN_ALARM) { 
+  		f_expire_tmrs(NULL, NULL);
+	} else if(mess.m_type == DEV_PING) {
+		notify(mess.m_source);
+  	} else {
+  		f_busy = BSY_IDLE;
+  	}
+  } while (f_busy == BSY_IO);
+  f_fp->fl_sector = NO_SECTOR;
+}
+
+/*===========================================================================*
+ *				stop_motor				     *
+ *===========================================================================*/
+PRIVATE void stop_motor(tp)
+timer_t *tp;
+{
+/* This routine is called from an alarm timer after several seconds have
+ * elapsed with no floppy disk activity.  It turns the drive motor off.
+ */
+  int s;
+  motor_status &= ~(1 << tmr_arg(tp)->ta_int);
+  if ((s=sys_outb(DOR, (motor_status << MOTOR_SHIFT) | ENABLE_INT)) != OK)
+	panic("FLOPPY","Sys_outb in stop_motor() failed", s);
+}
+
+/*===========================================================================*
+ *				floppy_stop				     *
+ *===========================================================================*/
+PRIVATE void floppy_stop(struct driver *dp, message *m_ptr)
+{
+/* Stop all activity and cleanly exit with the system. */
+  int s;
+  sigset_t sigset = m_ptr->NOTIFY_ARG;
+  if (sigismember(&sigset, SIGTERM) || sigismember(&sigset, SIGKSTOP)) {
+      if ((s=sys_outb(DOR, ENABLE_INT)) != OK)
+		panic("FLOPPY","Sys_outb in floppy_stop() failed", s);
+      exit(0);	
+  }
+}
+
+/*===========================================================================*
+ *				seek					     *
+ *===========================================================================*/
+PRIVATE int seek()
+{
+/* Issue a SEEK command on the indicated drive unless the arm is already
+ * positioned on the correct cylinder.
+ */
+
+  struct floppy *fp = f_fp;
+  int r;
+  message mess;
+  u8_t cmd[3];
+
+  /* Are we already on the correct cylinder? */
+  if (fp->fl_calibration == UNCALIBRATED)
+	if (recalibrate() != OK) return(ERR_SEEK);
+  if (fp->fl_curcyl == fp->fl_hardcyl) return(OK);
+
+  /* No.  Wrong cylinder.  Issue a SEEK and wait for interrupt. */
+  cmd[0] = FDC_SEEK;
+  cmd[1] = (fp->fl_head << 2) | f_drive;
+  cmd[2] = fp->fl_hardcyl;
+  if (fdc_command(cmd, 3) != OK) return(ERR_SEEK);
+  if (f_intr_wait() != OK) return(ERR_TIMEOUT);
+
+  /* Interrupt has been received.  Check drive status. */
+  fdc_out(FDC_SENSE);		/* probe FDC to make it return status */
+  r = fdc_results();		/* get controller status bytes */
+  if (r != OK || (f_results[ST0] & ST0_BITS_SEEK) != SEEK_ST0
+				|| f_results[ST1] != fp->fl_hardcyl) {
+	/* seek failed, may need a recalibrate */
+	return(ERR_SEEK);
+  }
+  /* Give head time to settle on a format, no retrying here! */
+  if (f_device & FORMAT_DEV_BIT) {
+	/* Set a synchronous alarm to force a timeout if the hardware does
+	 * not interrupt. Expect HARD_INT, but check for SYN_ALARM timeout.
+ 	 */ 
+ 	f_set_timer(&f_tmr_timeout, HZ/30, f_timeout);
+	f_busy = BSY_IO;
+  	do {
+  		receive(ANY, &mess); 
+  		if (mess.m_type == SYN_ALARM) { 
+  			f_expire_tmrs(NULL, NULL);
+		} else if(mess.m_type == DEV_PING) {
+			notify(mess.m_source);
+  		} else {
+  			f_busy = BSY_IDLE;
+  		}
+  	} while (f_busy == BSY_IO);
+  }
+  fp->fl_curcyl = fp->fl_hardcyl;
+  fp->fl_sector = NO_SECTOR;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				fdc_transfer				     *
+ *===========================================================================*/
+PRIVATE int fdc_transfer(opcode)
+int opcode;			/* DEV_GATHER or DEV_SCATTER */
+{
+/* The drive is now on the proper cylinder.  Read, write or format 1 block. */
+
+  struct floppy *fp = f_fp;
+  int r, s;
+  u8_t cmd[9];
+
+  /* Never attempt a transfer if the drive is uncalibrated or motor is off. */
+  if (fp->fl_calibration == UNCALIBRATED) return(ERR_TRANSFER);
+  if ((motor_status & (1 << f_drive)) == 0) return(ERR_TRANSFER);
+
+  /* The command is issued by outputting several bytes to the controller chip.
+   */
+  if (f_device & FORMAT_DEV_BIT) {
+	cmd[0] = FDC_FORMAT;
+	cmd[1] = (fp->fl_head << 2) | f_drive;
+	cmd[2] = fmt_param.sector_size_code;
+	cmd[3] = fmt_param.sectors_per_cylinder;
+	cmd[4] = fmt_param.gap_length_for_format;
+	cmd[5] = fmt_param.fill_byte_for_format;
+	if (fdc_command(cmd, 6) != OK) return(ERR_TRANSFER);
+  } else {
+	cmd[0] = opcode == DEV_SCATTER ? FDC_WRITE : FDC_READ;
+	cmd[1] = (fp->fl_head << 2) | f_drive;
+	cmd[2] = fp->fl_cylinder;
+	cmd[3] = fp->fl_head;
+	cmd[4] = BASE_SECTOR + fp->fl_sector;
+	cmd[5] = SECTOR_SIZE_CODE;
+	cmd[6] = f_sectors;
+	cmd[7] = f_dp->gap;	/* sector gap */
+	cmd[8] = DTL;		/* data length */
+	if (fdc_command(cmd, 9) != OK) return(ERR_TRANSFER);
+  }
+
+  /* Block, waiting for disk interrupt. */
+  if (f_intr_wait() != OK) {
+	printf("%s: disk interrupt timed out.\n", f_name());
+  	return(ERR_TIMEOUT);
+  }
+
+  /* Get controller status and check for errors. */
+  r = fdc_results();
+  if (r != OK) return(r);
+
+  if (f_results[ST1] & WRITE_PROTECT) {
+	printf("%s: diskette is write protected.\n", f_name());
+	return(ERR_WR_PROTECT);
+  }
+
+  if ((f_results[ST0] & ST0_BITS_TRANS) != TRANS_ST0) return(ERR_TRANSFER);
+  if (f_results[ST1] | f_results[ST2]) return(ERR_TRANSFER);
+
+  if (f_device & FORMAT_DEV_BIT) return(OK);
+
+  /* Compare actual numbers of sectors transferred with expected number. */
+  s =  (f_results[ST_CYL] - fp->fl_cylinder) * NR_HEADS * f_sectors;
+  s += (f_results[ST_HEAD] - fp->fl_head) * f_sectors;
+  s += (f_results[ST_SEC] - BASE_SECTOR - fp->fl_sector);
+  if (s != 1) return(ERR_TRANSFER);
+
+  /* This sector is next for I/O: */
+  fp->fl_sector = f_results[ST_SEC] - BASE_SECTOR;
+#if 0
+  if (processor < 386) fp->fl_sector++;		/* Old CPU can't keep up. */
+#endif
+  return(OK);
+}
+
+/*===========================================================================*
+ *				fdc_results				     *
+ *===========================================================================*/
+PRIVATE int fdc_results()
+{
+/* Extract results from the controller after an operation, then allow floppy
+ * interrupts again.
+ */
+
+  int s, result_nr;
+  unsigned long status;
+  clock_t t0,t1;
+
+  /* Extract bytes from FDC until it says it has no more.  The loop is
+   * really an outer loop on result_nr and an inner loop on status. 
+   * A timeout flag alarm is set.
+   */
+  result_nr = 0;
+  getuptime(&t0);
+  do {
+	/* Reading one byte is almost a mirror of fdc_out() - the DIRECTION
+	 * bit must be set instead of clear, but the CTL_BUSY bit destroys
+	 * the perfection of the mirror.
+	 */
+	if ((s=sys_inb(FDC_STATUS, &status)) != OK)
+		panic("FLOPPY","Sys_inb in fdc_results() failed", s);
+	status &= (MASTER | DIRECTION | CTL_BUSY);
+	if (status == (MASTER | DIRECTION | CTL_BUSY)) {
+		unsigned long tmp_r;
+		if (result_nr >= MAX_RESULTS) break;	/* too many results */
+		if ((s=sys_inb(FDC_DATA, &tmp_r)) != OK)
+		   panic("FLOPPY","Sys_inb in fdc_results() failed", s);
+		f_results[result_nr] = tmp_r;
+		result_nr ++;
+		continue;
+	}
+	if (status == MASTER) {			/* all read */
+		if ((s=sys_irqenable(&irq_hook_id)) != OK)
+			panic("FLOPPY", "Couldn't enable IRQs", s);
+
+		return(OK);			/* only good exit */
+	}
+  } while ( (s=getuptime(&t1))==OK && (t1-t0) < TIMEOUT_TICKS );
+  if (OK!=s) printf("FLOPPY: warning, getuptime failed: %d\n", s); 
+  need_reset = TRUE;		/* controller chip must be reset */
+
+  if ((s=sys_irqenable(&irq_hook_id)) != OK)
+	panic("FLOPPY", "Couldn't enable IRQs", s);
+  return(ERR_STATUS);
+}
+
+/*===========================================================================*
+ *				fdc_command				     *
+ *===========================================================================*/
+PRIVATE int fdc_command(cmd, len)
+u8_t *cmd;		/* command bytes */
+int len;		/* command length */
+{
+/* Output a command to the controller. */
+
+  /* Set a synchronous alarm to force a timeout if the hardware does
+   * not interrupt. Expect HARD_INT, but check for SYN_ALARM timeout.
+   * Note that the actual check is done by the code that issued the
+   * fdc_command() call.
+   */ 
+  f_set_timer(&f_tmr_timeout, WAKEUP, f_timeout);
+
+  f_busy = BSY_IO;
+  while (len > 0) {
+	fdc_out(*cmd++);
+	len--;
+  }
+  return(need_reset ? ERR_DRIVE : OK);
+}
+
+/*===========================================================================*
+ *				fdc_out					     *
+ *===========================================================================*/
+PRIVATE void fdc_out(val)
+int val;		/* write this byte to floppy disk controller */
+{
+/* Output a byte to the controller.  This is not entirely trivial, since you
+ * can only write to it when it is listening, and it decides when to listen.
+ * If the controller refuses to listen, the FDC chip is given a hard reset.
+ */
+  clock_t t0, t1;
+  int s;
+  unsigned long status;
+
+  if (need_reset) return;	/* if controller is not listening, return */
+
+  /* It may take several tries to get the FDC to accept a command.  */
+  getuptime(&t0);
+  do {
+  	if ( (s=getuptime(&t1))==OK && (t1-t0) > TIMEOUT_TICKS ) {
+  		if (OK!=s) printf("FLOPPY: warning, getuptime failed: %d\n", s); 
+		need_reset = TRUE;	/* hit it over the head */
+		return;
+	}
+  	if ((s=sys_inb(FDC_STATUS, &status)) != OK)
+  		panic("FLOPPY","Sys_inb in fdc_out() failed", s);
+  }
+  while ((status & (MASTER | DIRECTION)) != (MASTER | 0)); 
+  
+  if ((s=sys_outb(FDC_DATA, val)) != OK)
+	panic("FLOPPY","Sys_outb in fdc_out() failed", s);
+}
+
+/*===========================================================================*
+ *				recalibrate				     *
+ *===========================================================================*/
+PRIVATE int recalibrate()
+{
+/* The floppy disk controller has no way of determining its absolute arm
+ * position (cylinder).  Instead, it steps the arm a cylinder at a time and
+ * keeps track of where it thinks it is (in software).  However, after a
+ * SEEK, the hardware reads information from the diskette telling where the
+ * arm actually is.  If the arm is in the wrong place, a recalibration is done,
+ * which forces the arm to cylinder 0.  This way the controller can get back
+ * into sync with reality.
+ */
+
+  struct floppy *fp = f_fp;
+  int r;
+  u8_t cmd[2];
+
+  /* Issue the RECALIBRATE command and wait for the interrupt. */
+  cmd[0] = FDC_RECALIBRATE;	/* tell drive to recalibrate itself */
+  cmd[1] = f_drive;		/* specify drive */
+  if (fdc_command(cmd, 2) != OK) return(ERR_SEEK);
+  if (f_intr_wait() != OK) return(ERR_TIMEOUT);
+
+  /* Determine if the recalibration succeeded. */
+  fdc_out(FDC_SENSE);		/* issue SENSE command to request results */
+  r = fdc_results();		/* get results of the FDC_RECALIBRATE command*/
+  fp->fl_curcyl = NO_CYL;	/* force a SEEK next time */
+  fp->fl_sector = NO_SECTOR;
+  if (r != OK ||		/* controller would not respond */
+     (f_results[ST0] & ST0_BITS_SEEK) != SEEK_ST0 || f_results[ST_PCN] != 0) {
+	/* Recalibration failed.  FDC must be reset. */
+	need_reset = TRUE;
+	return(ERR_RECALIBRATE);
+  } else {
+	/* Recalibration succeeded. */
+	fp->fl_calibration = CALIBRATED;
+	fp->fl_curcyl = f_results[ST_PCN];
+	return(OK);
+  }
+}
+
+/*===========================================================================*
+ *				f_reset					     *
+ *===========================================================================*/
+PRIVATE void f_reset()
+{
+/* Issue a reset to the controller.  This is done after any catastrophe,
+ * like the controller refusing to respond.
+ */
+  pvb_pair_t byte_out[2];
+  int s,i;
+  message mess;
+
+  /* Disable interrupts and strobe reset bit low. */
+  need_reset = FALSE;
+
+  /* It is not clear why the next lock is needed.  Writing 0 to DOR causes
+   * interrupt, while the PC documentation says turning bit 8 off disables
+   * interrupts.  Without the lock:
+   *   1) the interrupt handler sets the floppy mask bit in the 8259.
+   *   2) writing ENABLE_INT to DOR causes the FDC to assert the interrupt
+   *      line again, but the mask stops the cpu being interrupted.
+   *   3) the sense interrupt clears the interrupt (not clear which one).
+   * and for some reason the reset does not work.
+   */
+  (void) fdc_command((u8_t *) 0, 0);   /* need only the timer */
+  motor_status = 0;
+  pv_set(byte_out[0], DOR, 0);			/* strobe reset bit low */
+  pv_set(byte_out[1], DOR, ENABLE_INT);		/* strobe it high again */
+  if ((s=sys_voutb(byte_out, 2)) != OK)
+  	panic("FLOPPY", "Sys_voutb in f_reset() failed", s); 
+
+  /* A synchronous alarm timer was set in fdc_command. Expect a HARD_INT
+   * message to collect the reset interrupt, but be prepared to handle the 
+   * SYN_ALARM message on a timeout.
+   */
+  do {
+  	receive(ANY, &mess); 
+  	if (mess.m_type == SYN_ALARM) { 
+  		f_expire_tmrs(NULL, NULL);
+	} else if(mess.m_type == DEV_PING) {
+		notify(mess.m_source);
+  	} else {			/* expect HARD_INT */
+  		f_busy = BSY_IDLE;
+  	}
+  } while (f_busy == BSY_IO);
+
+  /* The controller supports 4 drives and returns a result for each of them.
+   * Collect all the results now.  The old version only collected the first
+   * result.  This happens to work for 2 drives, but it doesn't work for 3
+   * or more drives, at least with only drives 0 and 2 actually connected
+   * (the controller generates an extra interrupt for the middle drive when
+   * drive 2 is accessed and the driver panics).
+   *
+   * It would be better to keep collecting results until there are no more.
+   * For this, fdc_results needs to return the number of results (instead
+   * of OK) when it succeeds.
+   */
+  for (i = 0; i < 4; i++) {
+	fdc_out(FDC_SENSE);	/* probe FDC to make it return status */
+	(void) fdc_results();	/* flush controller */
+  }
+  for (i = 0; i < NR_DRIVES; i++)	/* clear each drive */
+	floppy[i].fl_calibration = UNCALIBRATED;
+
+  /* The current timing parameters must be specified again. */
+  prev_dp = NULL;
+}
+
+/*===========================================================================*
+ *				f_intr_wait				     *
+ *===========================================================================*/
+PRIVATE int f_intr_wait()
+{
+/* Wait for an interrupt, but not forever.  The FDC may have all the time of
+ * the world, but we humans do not.
+ */
+  message mess;
+
+  /* We expect a HARD_INT message from the interrupt handler, but if there is
+   * a timeout, a SYN_ALARM notification is received instead. If a timeout 
+   * occurs, report an error.
+   */
+  do {
+  	receive(ANY, &mess); 
+  	if (mess.m_type == SYN_ALARM) {
+  		f_expire_tmrs(NULL, NULL);
+	} else if(mess.m_type == DEV_PING) {
+		notify(mess.m_source);
+  	} else { 
+  		f_busy = BSY_IDLE;
+  	}
+  } while (f_busy == BSY_IO);
+
+  if (f_busy == BSY_WAKEN) {
+
+	/* No interrupt from the FDC, this means that there is probably no
+	 * floppy in the drive.  Get the FDC down to earth and return error.
+	 */
+	need_reset = TRUE;
+	return(ERR_TIMEOUT);
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *				f_timeout				     *
+ *===========================================================================*/
+PRIVATE void f_timeout(tp)
+timer_t *tp;
+{
+/* This routine is called when a timer expires.  Usually to tell that a
+ * motor has spun up, but also to forge an interrupt when it takes too long
+ * for the FDC to interrupt (no floppy in the drive).  It sets a flag to tell
+ * what has happened.
+ */
+  if (f_busy == BSY_IO) {
+	f_busy = BSY_WAKEN;
+  }
+}
+
+/*===========================================================================*
+ *				read_id					     *
+ *===========================================================================*/
+PRIVATE int read_id()
+{
+/* Determine current cylinder and sector. */
+
+  struct floppy *fp = f_fp;
+  int result;
+  u8_t cmd[2];
+
+  /* Never attempt a read id if the drive is uncalibrated or motor is off. */
+  if (fp->fl_calibration == UNCALIBRATED) return(ERR_READ_ID);
+  if ((motor_status & (1 << f_drive)) == 0) return(ERR_READ_ID);
+
+  /* The command is issued by outputting 2 bytes to the controller chip. */
+  cmd[0] = FDC_READ_ID;		/* issue the read id command */
+  cmd[1] = (fp->fl_head << 2) | f_drive;
+  if (fdc_command(cmd, 2) != OK) return(ERR_READ_ID);
+  if (f_intr_wait() != OK) return(ERR_TIMEOUT);
+
+  /* Get controller status and check for errors. */
+  result = fdc_results();
+  if (result != OK) return(result);
+
+  if ((f_results[ST0] & ST0_BITS_TRANS) != TRANS_ST0) return(ERR_READ_ID);
+  if (f_results[ST1] | f_results[ST2]) return(ERR_READ_ID);
+
+  /* The next sector is next for I/O: */
+  fp->fl_sector = f_results[ST_SEC] - BASE_SECTOR + 1;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				f_do_open				     *
+ *===========================================================================*/
+PRIVATE int f_do_open(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;			/* pointer to open message */
+{
+/* Handle an open on a floppy.  Determine diskette type if need be. */
+
+  int dtype;
+  struct test_order *top;
+
+  /* Decode the message parameters. */
+  if (f_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
+
+  dtype = f_device & DEV_TYPE_BITS;	/* get density from minor dev */
+  if (dtype >= MINOR_fd0p0) dtype = 0;
+
+  if (dtype != 0) {
+	/* All types except 0 indicate a specific drive/medium combination.*/
+	dtype = (dtype >> DEV_TYPE_SHIFT) - 1;
+	if (dtype >= NT) return(ENXIO);
+	f_fp->fl_density = dtype;
+	(void) f_prepare(f_device);	/* Recompute parameters. */
+	return(OK);
+  }
+  if (f_device & FORMAT_DEV_BIT) return(EIO);	/* Can't format /dev/fdN */
+
+  /* The device opened is /dev/fdN.  Experimentally determine drive/medium.
+   * First check fl_density.  If it is not NO_DENS, the drive has been used
+   * before and the value of fl_density tells what was found last time. Try
+   * that first.  If the motor is still running then assume nothing changed.
+   */
+  if (f_fp->fl_density != NO_DENS) {
+	if (motor_status & (1 << f_drive)) return(OK);
+	if (test_read(f_fp->fl_density) == OK) return(OK);
+  }
+
+  /* Either drive type is unknown or a different diskette is now present.
+   * Use test_order to try them one by one.
+   */
+  for (top = &test_order[0]; top < &test_order[NT-1]; top++) {
+	dtype = top->t_density;
+
+	/* Skip densities that have been proven to be impossible */
+	if (!(f_fp->fl_class & (1 << dtype))) continue;
+
+	if (test_read(dtype) == OK) {
+		/* The test succeeded, use this knowledge to limit the
+		 * drive class to match the density just read.
+		 */
+		f_fp->fl_class &= top->t_class;
+		return(OK);
+	}
+	/* Test failed, wrong density or did it time out? */
+	if (f_busy == BSY_WAKEN) break;
+  }
+  f_fp->fl_density = NO_DENS;
+  return(EIO);			/* nothing worked */
+}
+
+/*===========================================================================*
+ *				test_read				     *
+ *===========================================================================*/
+PRIVATE int test_read(density)
+int density;
+{
+/* Try to read the highest numbered sector on cylinder 2.  Not all floppy
+ * types have as many sectors per track, and trying cylinder 2 finds the
+ * ones that need double stepping.
+ */
+  int device;
+  off_t position;
+  iovec_t iovec1;
+  int result;
+
+  f_fp->fl_density = density;
+  device = ((density + 1) << DEV_TYPE_SHIFT) + f_drive;
+
+  (void) f_prepare(device);
+  position = (off_t) f_dp->test << SECTOR_SHIFT;
+  iovec1.iov_addr = (vir_bytes) tmp_buf;
+  iovec1.iov_size = SECTOR_SIZE;
+  result = f_transfer(SELF, DEV_GATHER, position, &iovec1, 1);
+
+  if (iovec1.iov_size != 0) return(EIO);
+
+  partition(&f_dtab, f_drive, P_FLOPPY, 0);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				f_geometry				     *
+ *===========================================================================*/
+PRIVATE void f_geometry(entry)
+struct partition *entry;
+{
+  entry->cylinders = f_dp->cyls;
+  entry->heads = NR_HEADS;
+  entry->sectors = f_sectors;
+}
+
Index: /trunk/minix/drivers/floppy/floppy.h
===================================================================
--- /trunk/minix/drivers/floppy/floppy.h	(revision 9)
+++ /trunk/minix/drivers/floppy/floppy.h	(revision 9)
@@ -0,0 +1,6 @@
+#include "../drivers.h"
+#include "../libdriver/driver.h"
+#include "../libdriver/drvlib.h"
+
+_PROTOTYPE(void main, (void));
+
Index: /trunk/minix/drivers/fxp/.depend
===================================================================
--- /trunk/minix/drivers/fxp/.depend	(revision 9)
+++ /trunk/minix/drivers/fxp/.depend	(revision 9)
@@ -0,0 +1,65 @@
+
+fxp.o:	../drivers.h
+fxp.o:	/usr/include/ansi.h
+fxp.o:	/usr/include/assert.h
+fxp.o:	/usr/include/errno.h
+fxp.o:	/usr/include/ibm/bios.h
+fxp.o:	/usr/include/ibm/interrupt.h
+fxp.o:	/usr/include/ibm/pci.h
+fxp.o:	/usr/include/ibm/ports.h
+fxp.o:	/usr/include/limits.h
+fxp.o:	/usr/include/minix/bitmap.h
+fxp.o:	/usr/include/minix/callnr.h
+fxp.o:	/usr/include/minix/com.h
+fxp.o:	/usr/include/minix/config.h
+fxp.o:	/usr/include/minix/const.h
+fxp.o:	/usr/include/minix/devio.h
+fxp.o:	/usr/include/minix/dmap.h
+fxp.o:	/usr/include/minix/ipc.h
+fxp.o:	/usr/include/minix/sys_config.h
+fxp.o:	/usr/include/minix/syslib.h
+fxp.o:	/usr/include/minix/sysutil.h
+fxp.o:	/usr/include/minix/type.h
+fxp.o:	/usr/include/net/gen/eth_io.h
+fxp.o:	/usr/include/net/gen/ether.h
+fxp.o:	/usr/include/net/hton.h
+fxp.o:	/usr/include/signal.h
+fxp.o:	/usr/include/stddef.h
+fxp.o:	/usr/include/stdlib.h
+fxp.o:	/usr/include/string.h
+fxp.o:	/usr/include/sys/dir.h
+fxp.o:	/usr/include/sys/types.h
+fxp.o:	/usr/include/timers.h
+fxp.o:	/usr/include/unistd.h
+fxp.o:	fxp.c
+fxp.o:	fxp.h
+fxp.o:	mii.h
+
+mii.o:	../drivers.h
+mii.o:	/usr/include/ansi.h
+mii.o:	/usr/include/errno.h
+mii.o:	/usr/include/ibm/bios.h
+mii.o:	/usr/include/ibm/interrupt.h
+mii.o:	/usr/include/ibm/ports.h
+mii.o:	/usr/include/limits.h
+mii.o:	/usr/include/minix/bitmap.h
+mii.o:	/usr/include/minix/callnr.h
+mii.o:	/usr/include/minix/com.h
+mii.o:	/usr/include/minix/config.h
+mii.o:	/usr/include/minix/const.h
+mii.o:	/usr/include/minix/devio.h
+mii.o:	/usr/include/minix/dmap.h
+mii.o:	/usr/include/minix/ipc.h
+mii.o:	/usr/include/minix/sys_config.h
+mii.o:	/usr/include/minix/syslib.h
+mii.o:	/usr/include/minix/sysutil.h
+mii.o:	/usr/include/minix/type.h
+mii.o:	/usr/include/signal.h
+mii.o:	/usr/include/stddef.h
+mii.o:	/usr/include/stdlib.h
+mii.o:	/usr/include/string.h
+mii.o:	/usr/include/sys/dir.h
+mii.o:	/usr/include/sys/types.h
+mii.o:	/usr/include/unistd.h
+mii.o:	mii.c
+mii.o:	mii.h
Index: /trunk/minix/drivers/fxp/Makefile
===================================================================
--- /trunk/minix/drivers/fxp/Makefile	(revision 9)
+++ /trunk/minix/drivers/fxp/Makefile	(revision 9)
@@ -0,0 +1,40 @@
+# Makefile for Intel Pro/100 driver (FXP)
+DRIVER = fxp
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i 
+LIBS = -lsys -lsysutil -ltimers
+
+OBJ = fxp.o mii.o
+
+# build local binary
+all build:	$(DRIVER)
+$(DRIVER):	$(OBJ) 
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+	install -S 4096 $(DRIVER)
+
+# install with other drivers
+install:	/usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER):	$(DRIVER)
+	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f *.o *.bak $(DRIVER)
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/fxp/fxp.c
===================================================================
--- /trunk/minix/drivers/fxp/fxp.c	(revision 9)
+++ /trunk/minix/drivers/fxp/fxp.c	(revision 9)
@@ -0,0 +1,2503 @@
+/*
+ * fxp.c
+ *
+ * This file contains an ethernet device driver for Intel 82557, 82558, 
+ * 82559, 82550, and 82562 fast ethernet controllers.
+ *
+ * The valid messages and their parameters are:
+ *
+ *   m_type	  DL_PORT    DL_PROC   DL_COUNT   DL_MODE   DL_ADDR
+ * |------------+----------+---------+----------+---------+---------|
+ * | HARDINT	|          |         |          |         |         |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_WRITE	| port nr  | proc nr | count    | mode    | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_WRITEV	| port nr  | proc nr | count    | mode    | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_READ	| port nr  | proc nr | count    |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_READV	| port nr  | proc nr | count    |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_INIT	| port nr  | proc nr | mode     |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_GETSTAT	| port nr  | proc nr |          |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_STOP	| port_nr  |         |          |         |	    |
+ * |------------|----------|---------|----------|---------|---------|
+ *
+ * The messages sent are:
+ *
+ *   m-type	   DL_PORT    DL_PROC   DL_COUNT   DL_STAT   DL_CLCK
+ * |-------------+----------+---------+----------+---------+---------|
+ * |DL_TASK_REPLY| port nr  | proc nr | rd-count | err|stat| clock   |
+ * |-------------+----------+---------+----------+---------+---------|
+ *
+ *   m_type	   m3_i1     m3_i2       m3_ca1
+ * |-------------+---------+-----------+---------------|
+ * |DL_INIT_REPLY| port nr | last port | ethernet addr |
+ * |-------------+---------+-----------+---------------|
+ *
+ * Created:	Nov 2004 by Philip Homburg <philip@f-mnx.phicoh.com>
+ */
+
+#include "../drivers.h"
+
+#include <stdlib.h>
+#include <net/hton.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include <ibm/pci.h>
+
+#include <timers.h>
+
+#define tmra_ut			timer_t
+#define tmra_inittimer(tp)	tmr_inittimer(tp)
+#define Proc_number(p)		proc_number(p)
+#define debug			0
+#define RAND_UPDATE		/**/
+#define printW()		((void)0)
+#define vm_1phys2bus(p)		(p)
+
+#include "assert.h"
+#include "fxp.h"
+#include "mii.h"
+
+/* Number of receive buffers */
+#define N_RX_BUF	40
+
+/* Number of transmit buffers */
+#define N_TX_BUF	4
+
+/* I/O vectors are handled IOVEC_NR entries at a time. */
+#define IOVEC_NR	16
+
+/* Configuration */
+#define FXP_ENVVAR	"FXPETH"
+
+struct pcitab
+{
+	u16_t vid;
+	u16_t did;
+	int checkclass;
+};
+
+PRIVATE struct pcitab pcitab_fxp[]=
+{
+	{ 0x8086, 0x1229, 0 },		/* Intel 82557, etc. */
+	{ 0x8086, 0x2449, 0 },		/* Intel 82801BA/BAM/CA/CAM */
+
+	{ 0x0000, 0x0000, 0 }
+};
+
+#define FXP_PORT_NR	1		/* Minix */
+
+typedef int irq_hook_t;
+
+/* Translate a pointer to a field in a structure to a pointer to the structure
+ * itself.  So it translates '&struct_ptr->field' back to 'struct_ptr'.
+ */
+#define structof(type, field, ptr) \
+	((type *) (((char *) (ptr)) - offsetof(type, field)))
+
+#define MICROS_TO_TICKS(m)  (((m)*HZ/1000000)+1)
+
+static timer_t *fxp_timers= NULL;
+static clock_t fxp_next_timeout= 0;
+
+static void micro_delay(unsigned long usecs);
+
+/* ignore interrupt for the moment */
+#define interrupt(x)	0
+
+char buffer[70*1024];
+
+typedef struct fxp
+{
+	port_t fxp_base_port;
+	int fxp_mode;
+	int fxp_got_int;
+	int fxp_send_int;
+	int fxp_flags;
+	int fxp_client;
+	int fxp_features;		/* Needed? */
+	int fxp_irq;
+	int fxp_type;			/* What kind of hardware */
+	int fxp_ee_addrlen;		/* #EEPROM address bits */
+	int fxp_tx_alive;
+	int fxp_need_reset;
+
+	/* Rx */
+	vir_bytes fxp_read_s;
+	int fxp_rx_nbuf;
+	int fxp_rx_bufsize;
+	struct rfd *fxp_rx_buf;
+	phys_bytes fxp_rx_busaddr;
+	int fxp_rx_head;
+	int fxp_rx_need_restart;
+	int fxp_need_conf;		/* Re-configure after draining send
+					 * queue
+					 */
+
+	/* Tx */
+	int fxp_tx_nbuf;
+	int fxp_tx_bufsize;
+	struct tx *fxp_tx_buf;
+	phys_bytes fxp_tx_busaddr;
+	int fxp_tx_idle;
+	int fxp_tx_head;
+	int fxp_tx_tail;
+	int fxp_tx_threshold;
+
+	/* Link status */
+	int fxp_report_link;
+	int fxp_link_up;
+	int fxp_mii_busy;
+	u16_t fxp_mii_scr;
+
+	/* PCI related */
+	int fxp_seen;			/* TRUE iff device available */
+	u8_t fxp_pcibus;	
+	u8_t fxp_pcidev;	
+	u8_t fxp_pcifunc;	
+
+	/* 'large' items */
+	irq_hook_t fxp_hook;
+	ether_addr_t fxp_address;
+	message fxp_rx_mess;
+	message fxp_tx_mess;
+	struct sc fxp_stat;
+	u8_t fxp_conf_bytes[CC_BYTES_NR];
+	char fxp_name[sizeof("fxp#n")];
+	iovec_t fxp_iovec[IOVEC_NR];
+}
+fxp_t;
+
+/* fxp_mode */
+#define FM_DISABLED	0x0
+#define FM_ENABLED	0x1
+
+/* fxp_flags */
+#define FF_EMPTY	0x000
+#define FF_PACK_SENT	0x001
+#define FF_PACK_RECV	0x002
+#define FF_SEND_AVAIL	0x004
+#define FF_READING	0x010
+#define FF_PROMISC	0x040
+#define FF_MULTI	0x080
+#define FF_BROAD	0x100
+#define FF_ENABLED	0x200
+
+/* fxp_features */
+#define FFE_NONE	0x0
+
+/* fxp_type */
+#define FT_UNKNOWN	0x0
+#define FT_82557	0x1
+#define FT_82558A	0x2
+#define FT_82559	0x4
+
+static fxp_t fxp_table[FXP_PORT_NR];
+
+static int fxp_tasknr= ANY;
+static u16_t eth_ign_proto;
+static tmra_ut fxp_watchdog;
+static char *progname;
+
+extern int errno;
+
+#define fxp_inb(port, offset)	(do_inb((port) + (offset)))
+#define fxp_inw(port, offset)	(do_inw((port) + (offset)))
+#define fxp_inl(port, offset)	(do_inl((port) + (offset)))
+#define fxp_outb(port, offset, value)	(do_outb((port) + (offset), (value)))
+#define fxp_outw(port, offset, value)	(do_outw((port) + (offset), (value)))
+#define fxp_outl(port, offset, value)	(do_outl((port) + (offset), (value)))
+
+_PROTOTYPE( static void fxp_init, (message *mp)				);
+_PROTOTYPE( static void fxp_pci_conf, (void)				);
+_PROTOTYPE( static int fxp_probe, (fxp_t *fp)				);
+_PROTOTYPE( static void fxp_conf_hw, (fxp_t *fp)			);
+_PROTOTYPE( static void fxp_init_hw, (fxp_t *fp)			);
+_PROTOTYPE( static void fxp_init_buf, (fxp_t *fp)			);
+_PROTOTYPE( static void fxp_reset_hw, (fxp_t *fp)			);
+_PROTOTYPE( static void fxp_confaddr, (fxp_t *fp)			);
+_PROTOTYPE( static void fxp_rec_mode, (fxp_t *fp)			);
+_PROTOTYPE( static void fxp_writev, (message *mp, int from_int,
+							int vectored)	);
+_PROTOTYPE( static void fxp_readv, (message *mp, int from_int, 
+							int vectored)	);
+_PROTOTYPE( static void fxp_do_conf, (fxp_t *fp)			);
+_PROTOTYPE( static void fxp_cu_ptr_cmd, (fxp_t *fp, int cmd,
+				phys_bytes bus_addr, int check_idle)	);
+_PROTOTYPE( static void fxp_ru_ptr_cmd, (fxp_t *fp, int cmd,
+				phys_bytes bus_addr, int check_idle)	);
+_PROTOTYPE( static void fxp_restart_ru, (fxp_t *fp)			);
+_PROTOTYPE( static void fxp_getstat, (message *mp)			);
+_PROTOTYPE( static void fxp_getname, (message *mp)			);
+_PROTOTYPE( static int fxp_handler, (fxp_t *fp)				);
+_PROTOTYPE( static void fxp_check_ints, (fxp_t *fp)			);
+_PROTOTYPE( static void fxp_watchdog_f, (timer_t *tp)			);
+_PROTOTYPE( static int fxp_link_changed, (fxp_t *fp)			);
+_PROTOTYPE( static void fxp_report_link, (fxp_t *fp)			);
+_PROTOTYPE( static void fxp_stop, (void));
+_PROTOTYPE( static void reply, (fxp_t *fp, int err, int may_block)	);
+_PROTOTYPE( static void mess_reply, (message *req, message *reply)	);
+_PROTOTYPE( static void put_userdata, (int user_proc,
+		vir_bytes user_addr, vir_bytes count, void *loc_addr)	);
+_PROTOTYPE( static u16_t eeprom_read, (fxp_t *fp, int reg)		);
+_PROTOTYPE( static void eeprom_addrsize, (fxp_t *fp)			);
+_PROTOTYPE( static u16_t mii_read, (fxp_t *fp, int reg)			);
+_PROTOTYPE( static void fxp_set_timer,(timer_t *tp, clock_t delta,
+						tmr_func_t watchdog)	);
+_PROTOTYPE( static void fxp_expire_timers,(void)			);
+_PROTOTYPE( static u8_t do_inb, (port_t port)				);
+_PROTOTYPE( static u32_t do_inl, (port_t port)				);
+_PROTOTYPE( static void do_outb, (port_t port, u8_t v)			);
+_PROTOTYPE( static void do_outl, (port_t port, u32_t v)			);
+
+/*===========================================================================*
+ *				main					     *
+ *===========================================================================*/
+int main(int argc, char *argv[])
+{
+	message m;
+	int i, r, tasknr;
+	fxp_t *fp;
+	long v;
+
+	if ((fxp_tasknr= getprocnr())<0)
+		panic("FXP", "couldn't get proc nr", errno);
+
+	if (argc < 1)
+		panic("FXP", "A head which at this time has no name", NO_NUM);
+	(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
+
+	v= 0;
+#if 0
+	(void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
+#endif
+	eth_ign_proto= htons((u16_t) v);
+
+#if 0	/* What about memory allocation? */
+	/* Claim buffer memory now under Minix, before MM takes it all. */
+	for (fp= &fxp_table[0]; fp < fxp_table+FXP_PORT_NR; fp++)
+		fxp_init_buf(fp);
+#endif
+
+	/* Try to notify inet that we are present (again) */
+	r = _pm_findproc("inet", &tasknr);
+	if (r == OK)
+		notify(tasknr);
+
+	while (TRUE)
+	{
+		if ((r= receive(ANY, &m)) != OK)
+			panic("FXP","receive failed", r);
+
+		switch (m.m_type)
+		{
+		case DEV_PING:  notify(m.m_source);		continue;
+		case DL_WRITEV:	fxp_writev(&m, FALSE, TRUE);	break;
+		case DL_WRITE:	fxp_writev(&m, FALSE, FALSE);	break;
+#if 0
+		case DL_READ:	fxp_vread(&m, FALSE);		break;
+#endif
+		case DL_READV:	fxp_readv(&m, FALSE, TRUE);	break;
+		case DL_INIT:	fxp_init(&m);			break;
+		case DL_GETSTAT: fxp_getstat(&m);		break;
+		case DL_GETNAME: fxp_getname(&m); 		break;
+		case HARD_INT:
+			for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
+			{
+				if (fp->fxp_mode != FM_ENABLED)
+					continue;
+				fxp_handler(fp);
+
+				r= sys_irqenable(&fp->fxp_hook);
+				if (r != OK)
+					panic("FXP","unable enable interrupts", r);
+
+				if (!fp->fxp_got_int)
+					continue;
+				fp->fxp_got_int= 0;
+				assert(fp->fxp_flags & FF_ENABLED);
+				fxp_check_ints(fp);
+			}
+			break;
+		case SYS_SIG:	{
+			sigset_t sigset = m.NOTIFY_ARG;
+			if (sigismember(&sigset, SIGKSTOP)) fxp_stop();
+			break;
+		}
+		case PROC_EVENT: break;
+		case SYN_ALARM:	fxp_expire_timers();		break;
+		default:
+			panic("FXP"," illegal message", m.m_type);
+		}
+	}
+}
+
+/*===========================================================================*
+ *				fxp_init				     *
+ *===========================================================================*/
+static void fxp_init(mp)
+message *mp;
+{
+	static int first_time= 1;
+
+	int port;
+	fxp_t *fp;
+	message reply_mess;
+
+	if (first_time)
+	{
+		first_time= 0;
+		fxp_pci_conf(); /* Configure PCI devices. */
+
+		tmra_inittimer(&fxp_watchdog);
+		tmr_arg(&fxp_watchdog)->ta_int= 0;
+		fxp_set_timer(&fxp_watchdog, HZ, fxp_watchdog_f);
+	}
+
+	port = mp->DL_PORT;
+	if (port < 0 || port >= FXP_PORT_NR)
+	{
+		reply_mess.m_type= DL_INIT_REPLY;
+		reply_mess.m3_i1= ENXIO;
+		mess_reply(mp, &reply_mess);
+		return;
+	}
+	fp= &fxp_table[port];
+	if (fp->fxp_mode == FM_DISABLED)
+	{
+		/* This is the default, try to (re)locate the device. */
+		fxp_conf_hw(fp);
+		if (fp->fxp_mode == FM_DISABLED)
+		{
+			/* Probe failed, or the device is configured off. */
+			reply_mess.m_type= DL_INIT_REPLY;
+			reply_mess.m3_i1= ENXIO;
+			mess_reply(mp, &reply_mess);
+			return;
+		}
+		if (fp->fxp_mode == FM_ENABLED)
+			fxp_init_hw(fp);
+		fxp_report_link(fp);
+	}
+
+	assert(fp->fxp_mode == FM_ENABLED);
+	assert(fp->fxp_flags & FF_ENABLED);
+
+	fp->fxp_flags &= ~(FF_PROMISC | FF_MULTI | FF_BROAD);
+
+	if (mp->DL_MODE & DL_PROMISC_REQ)
+		fp->fxp_flags |= FF_PROMISC;
+	if (mp->DL_MODE & DL_MULTI_REQ)
+		fp->fxp_flags |= FF_MULTI;
+	if (mp->DL_MODE & DL_BROAD_REQ)
+		fp->fxp_flags |= FF_BROAD;
+
+	fp->fxp_client = mp->m_source;
+	fxp_rec_mode(fp);
+
+	reply_mess.m_type = DL_INIT_REPLY;
+	reply_mess.m3_i1 = mp->DL_PORT;
+	reply_mess.m3_i2 = FXP_PORT_NR;
+	*(ether_addr_t *) reply_mess.m3_ca1 = fp->fxp_address;
+
+	mess_reply(mp, &reply_mess);
+}
+
+/*===========================================================================*
+ *				fxp_pci_conf				     *
+ *===========================================================================*/
+static void fxp_pci_conf()
+{
+	static char envvar[] = FXP_ENVVAR "#";
+	static char envfmt[] = "*:d.d.d";
+
+	int i, h;
+	fxp_t *fp;
+	long v;
+
+	for (i= 0, fp= fxp_table; i<FXP_PORT_NR; i++, fp++)
+	{
+		strcpy(fp->fxp_name, "fxp#0");
+		fp->fxp_name[4] += i;
+		fp->fxp_seen= FALSE;
+		fp->fxp_features= FFE_NONE;
+		envvar[sizeof(FXP_ENVVAR)-1]= '0'+i;
+#if 0
+		if (getenv(envvar) != NULL)
+		{
+			if (strcmp(getenv(envvar), "off") == 0)
+			{
+				fp->fxp_pcibus= 255;
+				continue;
+			}
+			if (!env_prefix(envvar, "pci"))
+				env_panic(envvar);
+		}
+#endif
+
+		v= 0;
+#if 0
+		(void) env_parse(envvar, envfmt, 1, &v, 0, 255);
+#endif
+		fp->fxp_pcibus= v;
+		v= 0;
+#if 0
+		(void) env_parse(envvar, envfmt, 2, &v, 0, 255);
+#endif
+		fp->fxp_pcidev= v;
+		v= 0;
+#if 0
+		(void) env_parse(envvar, envfmt, 3, &v, 0, 255);
+#endif
+		fp->fxp_pcifunc= v;
+	}
+
+	pci_init();
+
+	for (h= 1; h >= 0; h--) {
+		for (i= 0, fp= fxp_table; i<FXP_PORT_NR; i++, fp++)
+		{
+			if (fp->fxp_pcibus == 255)
+				continue;
+			if (((fp->fxp_pcibus | fp->fxp_pcidev |
+				fp->fxp_pcifunc) != 0) != h)
+			{
+				continue;
+			}
+			if (fxp_probe(fp))
+				fp->fxp_seen= TRUE;
+		}
+	}
+}
+
+/*===========================================================================*
+ *				fxp_probe				     *
+ *===========================================================================*/
+static int fxp_probe(fp)
+fxp_t *fp;
+{
+	int i, r, devind, just_one;
+	u16_t vid, did;
+	u32_t bar;
+	u8_t ilr, rev;
+	char *dname, *str;
+
+	if ((fp->fxp_pcibus | fp->fxp_pcidev | fp->fxp_pcifunc) != 0)
+	{
+		/* Look for specific PCI device */
+		r= pci_find_dev(fp->fxp_pcibus, fp->fxp_pcidev,
+			fp->fxp_pcifunc, &devind);
+		if (r == 0)
+		{
+			printf("%s: no PCI device found at %d.%d.%d\n",
+				fp->fxp_name, fp->fxp_pcibus,
+				fp->fxp_pcidev, fp->fxp_pcifunc);
+			return FALSE;
+		}
+		pci_ids(devind, &vid, &did);
+		just_one= TRUE;
+	}
+	else
+	{
+		r= pci_first_dev(&devind, &vid, &did);
+		if (r == 0)
+			return FALSE;
+		just_one= FALSE;
+	}
+
+	for(;;)
+	{
+		for (i= 0; pcitab_fxp[i].vid != 0; i++)
+		{
+			if (pcitab_fxp[i].vid != vid)
+				continue;
+			if (pcitab_fxp[i].did != did)
+				continue;
+			if (pcitab_fxp[i].checkclass)
+			{
+				panic("FXP","fxp_probe: class check not implemented",
+					NO_NUM);
+			}
+			break;
+		}
+		if (pcitab_fxp[i].vid != 0)
+			break;
+
+		if (just_one)
+		{
+			printf(
+		"%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
+				fp->fxp_name, vid, did,
+				fp->fxp_pcibus,
+				fp->fxp_pcidev, fp->fxp_pcifunc);
+			return FALSE;
+		}
+
+		r= pci_next_dev(&devind, &vid, &did);
+		if (!r)
+			return FALSE;
+	}
+
+	dname= pci_dev_name(vid, did);
+#if VERBOSE
+	if (!dname)
+		dname= "unknown device";
+	printf("%s: %s (%04x/%04x) at %s\n",
+		fp->fxp_name, dname, vid, did, pci_slot_name(devind));
+#endif
+	pci_reserve(devind);
+
+	bar= pci_attr_r32(devind, PCI_BAR_2) & 0xffffffe0;
+	if (bar < 0x400)
+	{
+		panic("FXP","fxp_probe: base address is not properly configured",
+			NO_NUM);
+	}
+	fp->fxp_base_port= bar;
+
+	ilr= pci_attr_r8(devind, PCI_ILR);
+	fp->fxp_irq= ilr;
+	if (debug)
+	{
+		printf("%s: using I/O address 0x%lx, IRQ %d\n",
+			fp->fxp_name, (unsigned long)bar, ilr);
+	}
+
+	rev= pci_attr_r8(devind, PCI_REV);
+	str= NULL;
+	fp->fxp_type= FT_UNKNOWN;
+	switch(rev)
+	{
+	case FXP_REV_82557A:	str= "82557A";			/* 0x01 */
+				fp->fxp_type= FT_82557;
+				break;
+	case FXP_REV_82557B:	str= "82557B"; break;		/* 0x02 */
+	case FXP_REV_82557C:	str= "82557C"; break;		/* 0x03 */
+	case FXP_REV_82558A:	str= "82558A"; 			/* 0x04 */
+				fp->fxp_type= FT_82558A;
+				break;
+	case FXP_REV_82558B:	str= "82558B"; break;		/* 0x05 */
+	case FXP_REV_82559A:	str= "82559A"; break;		/* 0x06 */
+	case FXP_REV_82559B:	str= "82559B"; break;		/* 0x07 */
+	case FXP_REV_82559C:	str= "82559C";			/* 0x08 */
+				fp->fxp_type= FT_82559;
+				break;
+	case FXP_REV_82559ERA:	str= "82559ER-A"; 		/* 0x09 */
+				fp->fxp_type= FT_82559;
+				break;
+	case FXP_REV_82550_1:	str= "82550(1)"; 		/* 0x0C */
+				fp->fxp_type= FT_82559;
+				break;
+	case FXP_REV_82550_2:	str= "82550(2)"; 		/* 0x0D */
+				fp->fxp_type= FT_82559;
+				break;
+	case FXP_REV_82550_3:	str= "82550(3)"; 		/* 0x0E */
+				fp->fxp_type= FT_82559;
+				break;
+	case FXP_REV_82551_1:	str= "82551(1)"; 		/* 0x0F */
+				fp->fxp_type= FT_82559;
+				break;
+	case FXP_REV_82551_2:	str= "82551(2)"; 		/* 0x10 */
+				fp->fxp_type= FT_82559;
+				break;
+	}
+
+#if VERBOSE
+	if (str)
+		printf("%s: device revision: %s\n", fp->fxp_name, str);
+	else
+		printf("%s: unknown revision: 0x%x\n", fp->fxp_name, rev);
+#endif
+
+	if (fp->fxp_type == FT_UNKNOWN)
+	{
+		printf("fxp_probe: device is not supported by this driver\n");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+/*===========================================================================*
+ *				fxp_conf_hw				     *
+ *===========================================================================*/
+static void fxp_conf_hw(fp)
+fxp_t *fp;
+{
+	int i;
+	int mwi, ext_stat1, ext_stat2, lim_fifo, i82503, fc;
+
+	fp->fxp_mode= FM_DISABLED;	/* Superfluous */
+
+	if (!fp->fxp_seen)
+		return;
+
+	/* PCI device is present */
+	fp->fxp_mode= FM_ENABLED;
+
+	fp->fxp_flags= FF_EMPTY;
+	fp->fxp_got_int= 0;
+	fp->fxp_send_int= 0;
+	fp->fxp_ee_addrlen= 0;	/* Unknown */
+	fp->fxp_need_reset= 0;
+	fp->fxp_report_link= 0;
+	fp->fxp_link_up= -1;	/* Unknown */
+	fp->fxp_mii_busy= 0;
+	fp->fxp_read_s= 0;
+	fp->fxp_rx_need_restart= 0;
+	fp->fxp_need_conf= 0;
+	fp->fxp_tx_head= 0;
+	fp->fxp_tx_tail= 0;
+	fp->fxp_tx_alive= 0;
+	fp->fxp_tx_threshold= TXTT_MIN;
+
+	/* Try to come up with a sensible configuration for the current
+	 * device. Unfortunately every device is different, defaults are
+	 * not always zero, and some fields are re-used with a completely
+	 * different interpretation. We start out with a sensible default
+	 * for all devices and then add device specific changes.
+	 */
+	fp->fxp_conf_bytes[0]= CC_BYTES_NR;
+	fp->fxp_conf_bytes[1]= CTL_DEFAULT | CRL_DEFAULT;
+	fp->fxp_conf_bytes[2]= CAI_DEFAULT;
+	fp->fxp_conf_bytes[3]= 0;
+	fp->fxp_conf_bytes[4]= 0;
+	fp->fxp_conf_bytes[5]= 0;
+	fp->fxp_conf_bytes[6]= CCB6_ESC | CCB6_ETCB | CCB6_RES;
+	fp->fxp_conf_bytes[7]= CUR_1;
+	fp->fxp_conf_bytes[8]= CCB8_503_MII;
+	fp->fxp_conf_bytes[9]= 0;
+	fp->fxp_conf_bytes[10]= CLB_NORMAL | CPAL_DEFAULT | CCB10_NSAI |
+				CCB10_RES1;
+	fp->fxp_conf_bytes[11]= 0;
+	fp->fxp_conf_bytes[12]= CIS_DEFAULT;
+	fp->fxp_conf_bytes[13]= CCB13_DEFAULT;
+	fp->fxp_conf_bytes[14]= CCB14_DEFAULT;
+	fp->fxp_conf_bytes[15]= CCB15_RES1 | CCB15_RES2;
+	fp->fxp_conf_bytes[16]= CCB16_DEFAULT;
+	fp->fxp_conf_bytes[17]= CCB17_DEFAULT;
+	fp->fxp_conf_bytes[18]= CCB18_RES1 | CCB18_PFCT | CCB18_PE;
+	fp->fxp_conf_bytes[19]= CCB19_FDPE;
+	fp->fxp_conf_bytes[20]= CCB20_PFCL | CCB20_RES1;
+	fp->fxp_conf_bytes[21]= CCB21_RES21;
+
+#if VERBOSE
+	for (i= 0; i<CC_BYTES_NR; i++)
+		printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
+	printf("\n");
+#endif
+
+	mwi= 0;		/* Do we want "Memory Write and Invalidate"? */
+	ext_stat1= 0;	/* Do we want extended statistical counters? */
+	ext_stat2= 0;	/* Do we want even more statistical counters? */
+	lim_fifo= 0;	/* Limit number of frame in TX FIFO */
+	i82503= 0;	/* Older 10 Mbps interface on the 82557 */
+	fc= 0;		/* Flow control */
+
+	switch(fp->fxp_type)
+	{
+	case FT_82557:
+		if (i82503)
+		{
+			fp->fxp_conf_bytes[8] &= ~CCB8_503_MII;
+			fp->fxp_conf_bytes[15] |= CCB15_CRSCDT;
+		}
+		break;
+	case FT_82558A:
+	case FT_82559:
+		if (mwi)
+			fp->fxp_conf_bytes[3] |= CCB3_MWIE;
+		if (ext_stat1)
+			fp->fxp_conf_bytes[6] &= ~CCB6_ESC;
+		if (ext_stat2)
+			fp->fxp_conf_bytes[6] &= ~CCB6_TCOSC;
+		if (lim_fifo)
+			fp->fxp_conf_bytes[7] |= CCB7_2FFIFO;
+		if (fc)
+		{
+			/* From FreeBSD driver */
+			fp->fxp_conf_bytes[16]= 0x1f;
+			fp->fxp_conf_bytes[17]= 0x01;
+
+			fp->fxp_conf_bytes[19] |= CCB19_FDRSTAFC |
+				CCB19_FDRSTOFC;
+		}
+
+		fp->fxp_conf_bytes[18] |= CCB18_LROK;
+		break;
+	default:
+		panic("FXP","fxp_conf_hw: bad device type", fp->fxp_type);
+	}
+
+#if VERBOSE
+	for (i= 0; i<CC_BYTES_NR; i++)
+		printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
+	printf("\n");
+#endif
+}
+
+/*===========================================================================*
+ *				fxp_init_hw				     *
+ *===========================================================================*/
+static void fxp_init_hw(fp)
+fxp_t *fp;
+{
+	int i, r, isr;
+	port_t port;
+	u32_t bus_addr;
+
+	port= fp->fxp_base_port;
+
+	fxp_init_buf(fp);
+
+	fp->fxp_flags = FF_EMPTY;
+	fp->fxp_flags |= FF_ENABLED;
+
+	/* Set the interrupt handler and policy. Do not automatically 
+	 * reenable interrupts. Return the IRQ line number on interrupts.
+ 	 */
+ 	fp->fxp_hook = fp->fxp_irq;
+	r= sys_irqsetpolicy(fp->fxp_irq, 0, &fp->fxp_hook);
+	if (r != OK)
+		panic("FXP","sys_irqsetpolicy failed", r);
+
+	fxp_reset_hw(fp);
+
+	r= sys_irqenable(&fp->fxp_hook);
+	if (r != OK)
+		panic("FXP","sys_irqenable failed", r);
+
+	/* Reset PHY? */
+
+	fxp_do_conf(fp);
+
+	/* Set pointer to statistical counters */
+	r= sys_umap(SELF, D, (vir_bytes)&fp->fxp_stat, sizeof(fp->fxp_stat),
+		&bus_addr);
+	if (r != OK)
+		panic("FXP","sys_umap failed", r);
+	fxp_cu_ptr_cmd(fp, SC_CU_LOAD_DCA, bus_addr, TRUE /* check idle */);
+
+	/* Ack previous interrupts */
+	isr= fxp_inb(port, SCB_INT_STAT);
+	fxp_outb(port, SCB_INT_STAT, isr);
+
+	/* Enable interrupts */
+	fxp_outb(port, SCB_INT_MASK, 0);
+
+	fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
+		TRUE /* check idle */);
+
+	fxp_confaddr(fp);
+	if (debug)
+	{
+		printf("%s: Ethernet address ", fp->fxp_name);
+		for (i= 0; i < 6; i++)
+		{
+			printf("%x%c", fp->fxp_address.ea_addr[i],
+				i < 5 ? ':' : '\n');
+		}
+	}
+}
+
+/*===========================================================================*
+ *				fxp_init_buf				     *
+ *===========================================================================*/
+static void fxp_init_buf(fp)
+fxp_t *fp;
+{
+	size_t rx_totbufsize, tx_totbufsize, tot_bufsize;
+	phys_bytes buf;
+	int i, r;
+	struct rfd *rfdp;
+	struct tx *txp;
+
+	fp->fxp_rx_nbuf= N_RX_BUF;
+	rx_totbufsize= fp->fxp_rx_nbuf * sizeof(struct rfd);
+	fp->fxp_rx_bufsize= rx_totbufsize;
+
+	fp->fxp_tx_nbuf= N_TX_BUF;
+	tx_totbufsize= fp->fxp_tx_nbuf * sizeof(struct tx);
+	fp->fxp_tx_bufsize= tx_totbufsize;
+
+	tot_bufsize= tx_totbufsize + rx_totbufsize;
+
+	/* What about memory allocation? */
+	{
+		static int first_time= 1;
+
+		assert(first_time);
+		first_time= 0;
+
+#define BUFALIGN	4096
+		assert(tot_bufsize <= sizeof(buffer)-BUFALIGN); 
+		buf= (phys_bytes)buffer;
+		buf += BUFALIGN - (buf % BUFALIGN);
+	}
+
+	fp->fxp_rx_buf= (struct rfd *)buf;
+	r= sys_umap(SELF, D, (vir_bytes)buf, rx_totbufsize,
+		&fp->fxp_rx_busaddr);
+	if (r != OK)
+		panic("FXP","sys_umap failed", r);
+	for (i= 0, rfdp= fp->fxp_rx_buf; i<fp->fxp_rx_nbuf; i++, rfdp++)
+	{
+		rfdp->rfd_status= 0;
+		rfdp->rfd_command= 0;
+		if (i != fp->fxp_rx_nbuf-1)
+		{
+			r= sys_umap(SELF, D, (vir_bytes)&rfdp[1],
+				sizeof(rfdp[1]), &rfdp->rfd_linkaddr);
+			if (r != OK)
+				panic("FXP","sys_umap failed", r);
+		}
+		else
+		{
+			rfdp->rfd_linkaddr= fp->fxp_rx_busaddr;
+			rfdp->rfd_command |= RFDC_EL;
+		}
+		rfdp->rfd_reserved= 0;
+		rfdp->rfd_res= 0;
+		rfdp->rfd_size= sizeof(rfdp->rfd_buf);
+
+	}
+	fp->fxp_rx_head= 0;
+
+	fp->fxp_tx_buf= (struct tx *)(buf+rx_totbufsize);
+	r= sys_umap(SELF, D, (vir_bytes)fp->fxp_tx_buf,
+		(phys_bytes)tx_totbufsize, &fp->fxp_tx_busaddr);
+	if (r != OK)
+		panic("FXP","sys_umap failed", r);
+
+	for (i= 0, txp= fp->fxp_tx_buf; i<fp->fxp_tx_nbuf; i++, txp++)
+	{
+		txp->tx_status= 0;
+		txp->tx_command= TXC_EL | CBL_NOP;	/* Just in case */
+		if (i != fp->fxp_tx_nbuf-1)
+		{
+			r= sys_umap(SELF, D, (vir_bytes)&txp[1],
+				(phys_bytes)sizeof(txp[1]),
+				&txp->tx_linkaddr);
+			if (r != OK)
+				panic("FXP","sys_umap failed", r);
+		}
+		else
+		{
+			txp->tx_linkaddr= fp->fxp_tx_busaddr;
+		}
+		txp->tx_tbda= TX_TBDA_NIL;
+		txp->tx_size= 0;
+		txp->tx_tthresh= fp->fxp_tx_threshold;
+		txp->tx_ntbd= 0;
+	}
+	fp->fxp_tx_idle= 1;
+}
+
+/*===========================================================================*
+ *				fxp_reset_hw				     *
+ *===========================================================================*/
+static void fxp_reset_hw(fp)
+fxp_t *fp;
+{
+/* Inline the function in init? */
+	port_t port;
+
+	port= fp->fxp_base_port;
+
+	/* Reset device */
+	fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
+	tickdelay(MICROS_TO_TICKS(CSR_PORT_RESET_DELAY));
+
+	/* Disable interrupts */
+	fxp_outb(port, SCB_INT_MASK, SIM_M);
+
+	/* Set CU base to zero */
+	fxp_cu_ptr_cmd(fp, SC_CU_LOAD_BASE, 0, TRUE /* check idle */);
+
+	/* Set RU base to zero */
+	fxp_ru_ptr_cmd(fp, SC_RU_LOAD_BASE, 0, TRUE /* check idle */);
+}
+
+/*===========================================================================*
+ *				fxp_confaddr				     *
+ *===========================================================================*/
+static void fxp_confaddr(fp)
+fxp_t *fp;
+{
+	static char eakey[]= FXP_ENVVAR "#_EA";
+	static char eafmt[]= "x:x:x:x:x:x";
+	clock_t t0,t1;
+	int i, r;
+	port_t port;
+	u32_t bus_addr;
+	long v;
+	struct ias ias;
+
+	port= fp->fxp_base_port;
+
+	/* User defined ethernet address? */
+	eakey[sizeof(FXP_ENVVAR)-1]= '0' + (fp-fxp_table);
+
+#if 0
+	for (i= 0; i < 6; i++)
+	{
+		if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
+			break;
+		fp->fxp_address.ea_addr[i]= v;
+	}
+#else
+	i= 0;
+#endif
+
+#if 0
+	if (i != 0 && i != 6) env_panic(eakey);	/* It's all or nothing */
+#endif
+
+	if (i == 0)
+	{
+		/* Get ethernet address from EEPROM */
+		for (i= 0; i<3; i++)
+		{
+			v= eeprom_read(fp, i);
+			fp->fxp_address.ea_addr[i*2]= (v & 0xff);
+			fp->fxp_address.ea_addr[i*2+1]= ((v >> 8) & 0xff);
+		}
+	}
+
+	/* Tell NIC about ethernet address */
+	ias.ias_status= 0;
+	ias.ias_command= CBL_C_EL | CBL_AIS;
+	ias.ias_linkaddr= 0;
+	memcpy(ias.ias_ethaddr, fp->fxp_address.ea_addr,
+		sizeof(ias.ias_ethaddr));
+	r= sys_umap(SELF, D, (vir_bytes)&ias, (phys_bytes)sizeof(ias),
+		&bus_addr);
+	if (r != OK)
+		panic("FXP","sys_umap failed", r);
+
+	fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */);
+
+	getuptime(&t0);
+	do {
+		/* Wait for CU command to complete */
+		if (ias.ias_status & CBL_F_C)
+			break;
+	} while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
+
+	if (!(ias.ias_status & CBL_F_C))
+		panic("FXP","fxp_confaddr: CU command failed to complete", NO_NUM);
+	if (!(ias.ias_status & CBL_F_OK))
+		panic("FXP","fxp_confaddr: CU command failed", NO_NUM);
+
+#if VERBOSE
+	printf("%s: hardware ethernet address: ", fp->fxp_name);
+	for (i= 0; i<6; i++)
+	{
+		printf("%02x%s", fp->fxp_address.ea_addr[i], 
+			i < 5 ? ":" : "");
+	}
+	printf("\n");
+#endif
+}
+
+/*===========================================================================*
+ *				fxp_rec_mode				     *
+ *===========================================================================*/
+static void fxp_rec_mode(fp)
+fxp_t *fp;
+{
+	fp->fxp_conf_bytes[0]= CC_BYTES_NR;	/* Just to be sure */
+	fp->fxp_conf_bytes[15] &= ~(CCB15_BD|CCB15_PM);
+	fp->fxp_conf_bytes[21] &= ~CCB21_MA;
+
+	if (fp->fxp_flags & FF_PROMISC)
+		fp->fxp_conf_bytes[15] |= CCB15_PM;
+	if (fp->fxp_flags & FF_MULTI)
+		fp->fxp_conf_bytes[21] |= CCB21_MA;
+
+	if (!(fp->fxp_flags & (FF_BROAD|FF_MULTI|FF_PROMISC)))
+		fp->fxp_conf_bytes[15] |= CCB15_BD;
+
+	/* Queue request if not idle */
+	if (fp->fxp_tx_idle)
+	{
+		fxp_do_conf(fp);
+	}
+	else
+	{
+		printf("fxp_rec_mode: setting fxp_need_conf\n");
+		fp->fxp_need_conf= TRUE;
+	}
+}
+
+/*===========================================================================*
+ *				fxp_writev				     *
+ *===========================================================================*/
+static void fxp_writev(mp, from_int, vectored)
+message *mp;
+int from_int;
+int vectored;
+{
+	vir_bytes iov_src;
+	int i, j, n, o, r, s, dl_port, count, size, prev_head;
+	int fxp_client, fxp_tx_nbuf, fxp_tx_head;
+	u16_t tx_command;
+	fxp_t *fp;
+	iovec_t *iovp;
+	struct tx *txp, *prev_txp;
+
+	dl_port = mp->DL_PORT;
+	count = mp->DL_COUNT;
+	if (dl_port < 0 || dl_port >= FXP_PORT_NR)
+		panic("FXP","fxp_writev: illegal port", dl_port);
+	fp= &fxp_table[dl_port];
+	fxp_client= mp->DL_PROC;
+	fp->fxp_client= fxp_client;
+
+	assert(fp->fxp_mode == FM_ENABLED);
+	assert(fp->fxp_flags & FF_ENABLED);
+
+	if (from_int)
+	{
+		assert(fp->fxp_flags & FF_SEND_AVAIL);
+		fp->fxp_flags &= ~FF_SEND_AVAIL;
+		fp->fxp_tx_alive= TRUE;
+	}
+
+	if (fp->fxp_tx_idle)
+	{
+		txp= fp->fxp_tx_buf;
+		fxp_tx_head= 0;	/* lint */
+		prev_txp= NULL;	/* lint */
+	}
+	else
+	{	
+		fxp_tx_nbuf= fp->fxp_tx_nbuf;
+		prev_head= fp->fxp_tx_head;
+		fxp_tx_head= prev_head+1;
+		if (fxp_tx_head == fxp_tx_nbuf)
+			fxp_tx_head= 0;
+		assert(fxp_tx_head < fxp_tx_nbuf);
+
+		if (fxp_tx_head == fp->fxp_tx_tail)
+		{
+			/* Send queue is full */
+			assert(!(fp->fxp_flags & FF_SEND_AVAIL));
+			fp->fxp_flags |= FF_SEND_AVAIL;
+			goto suspend;
+		}
+
+		prev_txp= &fp->fxp_tx_buf[prev_head];
+		txp= &fp->fxp_tx_buf[fxp_tx_head];
+	}
+
+	assert(!(fp->fxp_flags & FF_SEND_AVAIL));
+	assert(!(fp->fxp_flags & FF_PACK_SENT));
+
+	if (vectored)
+	{
+
+		iov_src = (vir_bytes)mp->DL_ADDR;
+
+		size= 0;
+		o= 0;
+		for (i= 0; i<count; i += IOVEC_NR,
+			iov_src += IOVEC_NR * sizeof(fp->fxp_iovec[0]))
+		{
+			n= IOVEC_NR;
+			if (i+n > count)
+				n= count-i;
+			r= sys_vircopy(fxp_client, D, iov_src, 
+				SELF, D, (vir_bytes)fp->fxp_iovec,
+				n * sizeof(fp->fxp_iovec[0]));
+			if (r != OK)
+				panic("FXP","fxp_writev: sys_vircopy failed", r);
+
+			for (j= 0, iovp= fp->fxp_iovec; j<n; j++, iovp++)
+			{
+				s= iovp->iov_size;
+				if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
+				{
+					panic("FXP","fxp_writev: invalid packet size",
+						NO_NUM);
+				}
+
+				r= sys_vircopy(fxp_client, D, iovp->iov_addr, 
+					SELF, D, (vir_bytes)(txp->tx_buf+o),
+					s);
+				if (r != OK)
+				{
+					panic("FXP","fxp_writev: sys_vircopy failed",
+						r);
+				}
+				size += s;
+				o += s;
+			}
+		}
+		if (size < ETH_MIN_PACK_SIZE)
+			panic("FXP","fxp_writev: invalid packet size", size);
+	}
+	else
+	{  
+		size= mp->DL_COUNT;
+		if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
+			panic("FXP","fxp_writev: invalid packet size", size);
+
+		r= sys_vircopy(fxp_client, D, (vir_bytes)mp->DL_ADDR, 
+			SELF, D, (vir_bytes)txp->tx_buf, size);
+		if (r != OK)
+			panic("FXP","fxp_writev: sys_vircopy failed", r);
+	}
+
+	txp->tx_status= 0;
+	txp->tx_command= TXC_EL | CBL_XMIT;
+	txp->tx_tbda= TX_TBDA_NIL;
+	txp->tx_size= TXSZ_EOF | size;
+	txp->tx_tthresh= fp->fxp_tx_threshold;
+	txp->tx_ntbd= 0;
+	if (fp->fxp_tx_idle)
+	{
+		fp->fxp_tx_idle= 0;
+		fp->fxp_tx_head= fp->fxp_tx_tail= 0;
+
+		fxp_cu_ptr_cmd(fp, SC_CU_START, fp->fxp_tx_busaddr,
+			TRUE /* check idle */);
+	}
+	else
+	{
+		/* Link new request in transmit list */
+		tx_command= prev_txp->tx_command;
+		assert(tx_command == (TXC_EL | CBL_XMIT));
+		prev_txp->tx_command= CBL_XMIT;
+		fp->fxp_tx_head= fxp_tx_head;
+	}
+
+	fp->fxp_flags |= FF_PACK_SENT;
+
+	/* If the interrupt handler called, don't send a reply. The reply
+	 * will be sent after all interrupts are handled. 
+	 */
+	if (from_int)
+		return;
+	reply(fp, OK, FALSE);
+	return;
+
+suspend:
+	if (from_int)
+		panic("FXP","fxp: should not be sending\n", NO_NUM);
+
+	fp->fxp_tx_mess= *mp;
+	reply(fp, OK, FALSE);
+}
+
+/*===========================================================================*
+ *				fxp_readv				     *
+ *===========================================================================*/
+static void fxp_readv(mp, from_int, vectored)
+message *mp;
+int from_int;
+int vectored;
+{
+	int i, j, n, o, r, s, dl_port, fxp_client, count, size,
+		fxp_rx_head, fxp_rx_nbuf;
+	port_t port;
+	unsigned packlen;
+	vir_bytes iov_src;
+	u16_t rfd_status;
+	u16_t rfd_res;
+	u8_t scb_status;
+	fxp_t *fp;
+	iovec_t *iovp;
+	struct rfd *rfdp, *prev_rfdp;
+
+	dl_port = mp->DL_PORT;
+	count = mp->DL_COUNT;
+	if (dl_port < 0 || dl_port >= FXP_PORT_NR)
+		panic("FXP","fxp_readv: illegal port", dl_port);
+	fp= &fxp_table[dl_port];
+	fxp_client= mp->DL_PROC;
+	fp->fxp_client= fxp_client;
+
+	assert(fp->fxp_mode == FM_ENABLED);
+	assert(fp->fxp_flags & FF_ENABLED);
+
+	port= fp->fxp_base_port;
+
+	fxp_rx_head= fp->fxp_rx_head;
+	rfdp= &fp->fxp_rx_buf[fxp_rx_head];
+
+	rfd_status= rfdp->rfd_status;
+	if (!(rfd_status & RFDS_C))
+	{
+		/* Receive buffer is empty, suspend */
+		goto suspend;
+	}
+
+	if (!rfd_status & RFDS_OK)
+	{
+		/* Not OK? What happened? */
+		assert(0);
+	}
+	else
+	{
+		assert(!(rfd_status & (RFDS_CRCERR | RFDS_ALIGNERR |
+			RFDS_OUTOFBUF | RFDS_DMAOVR | RFDS_TOOSHORT | 
+			RFDS_RXERR)));
+	}
+	rfd_res= rfdp->rfd_res;
+	assert(rfd_res & RFDR_EOF);
+	assert(rfd_res & RFDR_F);
+
+	packlen= rfd_res & RFDSZ_SIZE;
+
+	if (vectored)
+	{
+		iov_src = (vir_bytes)mp->DL_ADDR;
+
+		size= 0;
+		o= 0;
+		for (i= 0; i<count; i += IOVEC_NR,
+			iov_src += IOVEC_NR * sizeof(fp->fxp_iovec[0]))
+		{
+			n= IOVEC_NR;
+			if (i+n > count)
+				n= count-i;
+			r= sys_vircopy(fxp_client, D, iov_src, 
+				SELF, D, (vir_bytes)fp->fxp_iovec,
+				n * sizeof(fp->fxp_iovec[0]));
+			if (r != OK)
+				panic("FXP","fxp_readv: sys_vircopy failed", r);
+
+			for (j= 0, iovp= fp->fxp_iovec; j<n; j++, iovp++)
+			{
+				s= iovp->iov_size;
+				if (size + s > packlen)
+				{
+					assert(packlen > size);
+					s= packlen-size;
+				}
+
+				r= sys_vircopy(SELF, D,
+					(vir_bytes)(rfdp->rfd_buf+o),
+					fxp_client, D, iovp->iov_addr, s);
+				if (r != OK)
+				{
+					panic("FXP","fxp_readv: sys_vircopy failed",
+						r);
+				}
+
+				size += s;
+				if (size == packlen)
+					break;
+				o += s;
+			}
+			if (size == packlen)
+				break;
+		}
+		if (size < packlen)
+		{
+			assert(0);
+		}
+	}
+	else
+	{  
+		assert(0);
+	}
+
+	fp->fxp_read_s= packlen;
+	fp->fxp_flags= (fp->fxp_flags & ~FF_READING) | FF_PACK_RECV;
+
+	/* Re-init the current buffer */
+	rfdp->rfd_status= 0;
+	rfdp->rfd_command= RFDC_EL;
+	rfdp->rfd_reserved= 0;
+	rfdp->rfd_res= 0;
+	rfdp->rfd_size= sizeof(rfdp->rfd_buf);
+
+	fxp_rx_nbuf= fp->fxp_rx_nbuf;
+	if (fxp_rx_head == 0)
+	{
+		prev_rfdp= &fp->fxp_rx_buf[fxp_rx_nbuf-1];
+	}
+	else
+		prev_rfdp= &rfdp[-1];
+
+	assert(prev_rfdp->rfd_command & RFDC_EL);
+	prev_rfdp->rfd_command &= ~RFDC_EL;
+
+	fxp_rx_head++;
+	if (fxp_rx_head == fxp_rx_nbuf)
+		fxp_rx_head= 0;
+	assert(fxp_rx_head < fxp_rx_nbuf);
+	fp->fxp_rx_head= fxp_rx_head;
+
+	if (!from_int)
+		reply(fp, OK, FALSE);
+
+	return;
+
+suspend:
+	if (fp->fxp_rx_need_restart)
+	{
+		fp->fxp_rx_need_restart= 0;
+
+		/* Check the status of the RU */
+		scb_status= fxp_inb(port, SCB_STATUS);
+		if ((scb_status & SS_RUS_MASK) != SS_RU_NORES)
+		{
+			/* Race condition? */
+			printf("fxp_readv: restart race: 0x%x\n",
+				scb_status);
+			assert((scb_status & SS_RUS_MASK) == SS_RU_READY);
+		}
+		else
+		{
+			fxp_restart_ru(fp);
+		}
+	}
+	if (from_int)
+	{
+		assert(fp->fxp_flags & FF_READING);
+
+		/* No need to store any state */
+		return;
+	}
+
+	fp->fxp_rx_mess= *mp;
+	assert(!(fp->fxp_flags & FF_READING));
+	fp->fxp_flags |= FF_READING;
+
+	reply(fp, OK, FALSE);
+}
+
+/*===========================================================================*
+ *				fxp_do_conf				     *
+ *===========================================================================*/
+static void fxp_do_conf(fp)
+fxp_t *fp;
+{
+	int r;
+	u32_t bus_addr;
+	struct cbl_conf cc;
+	clock_t t0,t1;
+
+	/* Configure device */
+	cc.cc_status= 0;
+	cc.cc_command= CBL_C_EL | CBL_CONF;
+	cc.cc_linkaddr= 0;
+	memcpy(cc.cc_bytes, fp->fxp_conf_bytes, sizeof(cc.cc_bytes));
+
+	r= sys_umap(SELF, D, (vir_bytes)&cc, (phys_bytes)sizeof(cc),
+		&bus_addr);
+	if (r != OK)
+		panic("FXP","sys_umap failed", r);
+
+	fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */);
+
+	getuptime(&t0);
+	do {
+		/* Wait for CU command to complete */
+		if (cc.cc_status & CBL_F_C)
+			break;
+	} while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
+
+	if (!(cc.cc_status & CBL_F_C))
+		panic("FXP","fxp_do_conf: CU command failed to complete", NO_NUM);
+	if (!(cc.cc_status & CBL_F_OK))
+		panic("FXP","fxp_do_conf: CU command failed", NO_NUM);
+
+}
+
+/*===========================================================================*
+ *				fxp_cu_ptr_cmd				     *
+ *===========================================================================*/
+static void fxp_cu_ptr_cmd(fp, cmd, bus_addr, check_idle)
+fxp_t *fp;
+int cmd;
+phys_bytes bus_addr;
+int check_idle;
+{
+	clock_t t0,t1;
+	port_t port;
+	u8_t scb_cmd;
+
+	port= fp->fxp_base_port;
+
+	if (check_idle)
+	{
+		/* Consistency check. Make sure that CU is idle */
+		if ((fxp_inb(port, SCB_STATUS) & SS_CUS_MASK) != SS_CU_IDLE)
+			panic("FXP","fxp_cu_ptr_cmd: CU is not idle", NO_NUM);
+	}
+
+	fxp_outl(port, SCB_POINTER, bus_addr);
+	fxp_outb(port, SCB_CMD, cmd);
+
+	/* What is a reasonable time-out? There is nothing in the
+	 * documentation. 1 ms should be enough.
+	 */
+	getuptime(&t0);
+	do {
+		/* Wait for CU command to be accepted */
+		scb_cmd= fxp_inb(port, SCB_CMD);
+		if ((scb_cmd & SC_CUC_MASK) == SC_CU_NOP)
+			break;
+	} while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
+
+	if ((scb_cmd & SC_CUC_MASK) != SC_CU_NOP)
+		panic("FXP","fxp_cu_ptr_cmd: CU does not accept command", NO_NUM);
+}
+
+/*===========================================================================*
+ *				fxp_ru_ptr_cmd				     *
+ *===========================================================================*/
+static void fxp_ru_ptr_cmd(fp, cmd, bus_addr, check_idle)
+fxp_t *fp;
+int cmd;
+phys_bytes bus_addr;
+int check_idle;
+{
+	clock_t t0,t1;
+	port_t port;
+	u8_t scb_cmd;
+
+	port= fp->fxp_base_port;
+
+	if (check_idle)
+	{
+		/* Consistency check, make sure that RU is idle */
+		if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_IDLE)
+			panic("FXP","fxp_ru_ptr_cmd: RU is not idle", NO_NUM);
+	}
+
+	fxp_outl(port, SCB_POINTER, bus_addr);
+	fxp_outb(port, SCB_CMD, cmd);
+
+	getuptime(&t0);
+	do {
+		/* Wait for RU command to be accepted */
+		scb_cmd= fxp_inb(port, SCB_CMD);
+		if ((scb_cmd & SC_RUC_MASK) == SC_RU_NOP)
+			break;
+	} while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
+
+	if ((scb_cmd & SC_RUC_MASK) != SC_RU_NOP)
+		panic("FXP","fxp_ru_ptr_cmd: RU does not accept command", NO_NUM);
+}
+
+/*===========================================================================*
+ *				fxp_restart_ru				     *
+ *===========================================================================*/
+static void fxp_restart_ru(fp)
+fxp_t *fp;
+{
+	int i, fxp_rx_nbuf;
+	port_t port;
+	struct rfd *rfdp;
+
+	port= fp->fxp_base_port;
+
+	fxp_rx_nbuf= fp->fxp_rx_nbuf;
+	for (i= 0, rfdp= fp->fxp_rx_buf; i<fxp_rx_nbuf; i++, rfdp++)
+	{
+		rfdp->rfd_status= 0;
+		rfdp->rfd_command= 0;
+		if (i == fp->fxp_rx_nbuf-1)
+			rfdp->rfd_command= RFDC_EL;
+		rfdp->rfd_reserved= 0;
+		rfdp->rfd_res= 0;
+		rfdp->rfd_size= sizeof(rfdp->rfd_buf);
+	}
+	fp->fxp_rx_head= 0;
+
+	/* Make sure that RU is in the 'No resources' state */
+	if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_NORES)
+		panic("FXP","fxp_restart_ru: RU is in an unexpected state", NO_NUM);
+
+	fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
+		FALSE /* do not check idle */);
+}
+
+/*===========================================================================*
+ *				fxp_getstat				     *
+ *===========================================================================*/
+static void fxp_getstat(mp)
+message *mp;
+{
+	clock_t t0,t1;
+	int dl_port;
+	port_t port;
+	fxp_t *fp;
+	u32_t *p;
+	eth_stat_t stats;
+
+	dl_port = mp->DL_PORT;
+	if (dl_port < 0 || dl_port >= FXP_PORT_NR)
+		panic("FXP","fxp_getstat: illegal port", dl_port);
+	fp= &fxp_table[dl_port];
+	fp->fxp_client= mp->DL_PROC;
+
+	assert(fp->fxp_mode == FM_ENABLED);
+	assert(fp->fxp_flags & FF_ENABLED);
+
+	port= fp->fxp_base_port;
+
+	p= &fp->fxp_stat.sc_tx_fcp;
+	*p= 0;
+
+	/* The dump commmand doesn't take a pointer. Setting a pointer
+	 * doesn't hard though.
+	 */
+	fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE /* do not check idle */);
+
+	getuptime(&t0);
+	do {
+		/* Wait for CU command to complete */
+		if (*p != 0)
+			break;
+	} while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
+
+	if (*p == 0)
+		panic("FXP","fxp_getstat: CU command failed to complete", NO_NUM);
+	if (*p != SCM_DSC)
+		panic("FXP","fxp_getstat: bad magic", NO_NUM);
+
+	stats.ets_recvErr=
+		fp->fxp_stat.sc_rx_crc +
+		fp->fxp_stat.sc_rx_align +
+		fp->fxp_stat.sc_rx_resource +
+		fp->fxp_stat.sc_rx_overrun +
+		fp->fxp_stat.sc_rx_cd +
+		fp->fxp_stat.sc_rx_short;
+	stats.ets_sendErr=
+		fp->fxp_stat.sc_tx_maxcol +
+		fp->fxp_stat.sc_tx_latecol +
+		fp->fxp_stat.sc_tx_crs;
+	stats.ets_OVW= fp->fxp_stat.sc_rx_overrun;
+	stats.ets_CRCerr= fp->fxp_stat.sc_rx_crc;
+	stats.ets_frameAll= fp->fxp_stat.sc_rx_align;
+	stats.ets_missedP= fp->fxp_stat.sc_rx_resource;
+	stats.ets_packetR= fp->fxp_stat.sc_rx_good;
+	stats.ets_packetT= fp->fxp_stat.sc_tx_good;
+	stats.ets_transDef= fp->fxp_stat.sc_tx_defered;
+	stats.ets_collision= fp->fxp_stat.sc_tx_totcol;
+	stats.ets_transAb= fp->fxp_stat.sc_tx_maxcol;
+	stats.ets_carrSense= fp->fxp_stat.sc_tx_crs;
+	stats.ets_fifoUnder= fp->fxp_stat.sc_tx_underrun;
+	stats.ets_fifoOver= fp->fxp_stat.sc_rx_overrun;
+	stats.ets_CDheartbeat= 0;
+	stats.ets_OWC= fp->fxp_stat.sc_tx_latecol;
+
+	put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+		(vir_bytes) sizeof(stats), &stats);
+	reply(fp, OK, FALSE);
+}
+
+
+/*===========================================================================*
+ *				fxp_getname				     *
+ *===========================================================================*/
+static void fxp_getname(mp)
+message *mp;
+{
+	int r;
+
+	strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
+	mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
+	mp->m_type= DL_NAME_REPLY;
+	r= send(mp->m_source, mp);
+	if (r != OK)
+		panic("FXP", "fxp_getname: send failed", r);
+}
+
+/*===========================================================================*
+ *				fxp_handler				     *
+ *===========================================================================*/
+static int fxp_handler(fp)
+fxp_t *fp;
+{
+	int port;
+	u16_t isr;
+
+	RAND_UPDATE
+
+	port= fp->fxp_base_port;
+
+	/* Ack interrupt */
+	isr= fxp_inb(port, SCB_INT_STAT);
+	fxp_outb(port, SCB_INT_STAT, isr);
+
+	if (isr & SIS_FR)
+	{
+		isr &= ~SIS_FR;
+
+		if (!fp->fxp_got_int && (fp->fxp_flags & FF_READING))
+		{
+			fp->fxp_got_int= TRUE;
+			interrupt(fxp_tasknr);
+		}
+	}
+	if (isr & SIS_CNA)
+	{
+		isr &= ~SIS_CNA;
+		if (!fp->fxp_tx_idle)
+		{
+			fp->fxp_send_int= TRUE;
+			if (!fp->fxp_got_int)
+			{
+				fp->fxp_got_int= TRUE;
+				interrupt(fxp_tasknr);
+			}
+		}
+	}
+	if (isr & SIS_RNR)
+	{
+		isr &= ~SIS_RNR;
+
+		/* Assume that receive buffer is full of packets. fxp_readv
+		 * will restart the RU.
+		 */
+		fp->fxp_rx_need_restart= 1;
+	}
+	if (isr)
+	{
+		printf("fxp_handler: unhandled interrupt: isr = 0x%02x\n",
+			isr);
+	}
+
+	return 1;
+}
+
+/*===========================================================================*
+ *				fxp_check_ints				     *
+ *===========================================================================*/
+static void fxp_check_ints(fp)
+fxp_t *fp;
+{
+	int n, fxp_flags, prev_tail;
+	int fxp_tx_tail, fxp_tx_nbuf, fxp_tx_threshold;
+	port_t port;
+	u32_t busaddr;
+	u16_t tx_status;
+	u8_t scb_status;
+	struct tx *txp;
+
+	fxp_flags= fp->fxp_flags;
+
+	if (fxp_flags & FF_READING)
+	{
+		if (!(fp->fxp_rx_buf[fp->fxp_rx_head].rfd_status & RFDS_C))
+			; /* Nothing */
+		else if (fp->fxp_rx_mess.m_type == DL_READV)
+		{
+			fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,
+				TRUE /* vectored */);
+		}
+		else
+		{
+			assert(fp->fxp_rx_mess.m_type == DL_READ);
+			fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,
+				FALSE /* !vectored */);
+		}
+	}
+	if (fp->fxp_tx_idle)
+		;	/* Nothing to do */
+	else if (fp->fxp_send_int)
+	{
+		fp->fxp_send_int= FALSE;
+		fxp_tx_tail= fp->fxp_tx_tail;
+		fxp_tx_nbuf= fp->fxp_tx_nbuf;
+		n= 0;
+		for (;;)
+		{
+			txp= &fp->fxp_tx_buf[fxp_tx_tail];
+			tx_status= txp->tx_status;
+			if (!(tx_status & TXS_C))
+				break;
+
+			n++;
+
+			assert(tx_status & TXS_OK);
+			if (tx_status & TXS_U)
+			{
+				fxp_tx_threshold= fp->fxp_tx_threshold;
+				if (fxp_tx_threshold < TXTT_MAX)
+				{
+					fxp_tx_threshold++;
+					fp->fxp_tx_threshold= fxp_tx_threshold;
+				}
+				printf(
+			"fxp_check_ints: fxp_tx_threshold = 0x%x\n",
+					fxp_tx_threshold);
+			}
+
+			if (txp->tx_command & TXC_EL)
+			{
+				fp->fxp_tx_idle= 1;
+				break;
+			}
+
+			fxp_tx_tail++;
+			if (fxp_tx_tail == fxp_tx_nbuf)
+				fxp_tx_tail= 0;
+			assert(fxp_tx_tail < fxp_tx_nbuf);
+		}
+
+		if (fp->fxp_need_conf)
+		{
+			/* Check the status of the CU */
+			port= fp->fxp_base_port;
+			scb_status= fxp_inb(port, SCB_STATUS);
+			if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
+			{
+				/* Nothing to do */
+				printf("scb_status = 0x%x\n", scb_status);
+			}
+			else
+			{
+				printf("fxp_check_ints: fxp_need_conf\n");
+				fp->fxp_need_conf= FALSE;
+				fxp_do_conf(fp);
+			}
+		}
+
+		if (n)
+		{
+			if (!fp->fxp_tx_idle)
+			{
+				fp->fxp_tx_tail= fxp_tx_tail;
+				
+				/* Check the status of the CU */
+				port= fp->fxp_base_port;
+				scb_status= fxp_inb(port, SCB_STATUS);
+				if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
+				{
+					/* Nothing to do */
+					printf("scb_status = 0x%x\n",
+						scb_status);
+
+				}
+				else
+				{
+					if (fxp_tx_tail == 0)
+						prev_tail= fxp_tx_nbuf-1;
+					else
+						prev_tail= fxp_tx_tail-1;
+					busaddr= fp->fxp_tx_buf[prev_tail].
+						tx_linkaddr;
+
+					fxp_cu_ptr_cmd(fp, SC_CU_START,
+						busaddr, 1 /* check idle */);
+				}
+			}
+
+			if (fp->fxp_flags & FF_SEND_AVAIL)
+			{
+				if (fp->fxp_tx_mess.m_type == DL_WRITEV)
+				{
+					fxp_writev(&fp->fxp_tx_mess,
+						TRUE /* from int */,
+						TRUE /* vectored */);
+				}
+				else
+				{
+					assert(fp->fxp_tx_mess.m_type ==
+						DL_WRITE);
+					fxp_writev(&fp->fxp_tx_mess,
+						TRUE /* from int */,
+						FALSE /* !vectored */);
+				}
+			}
+		}
+		
+	}
+	if (fp->fxp_report_link)
+		fxp_report_link(fp);
+
+	if (fp->fxp_flags & (FF_PACK_SENT | FF_PACK_RECV))
+		reply(fp, OK, TRUE);
+}
+
+/*===========================================================================*
+ *				fxp_watchdog_f				     *
+ *===========================================================================*/
+static void fxp_watchdog_f(tp)
+timer_t *tp;
+{
+	int i;
+	fxp_t *fp;
+
+	tmr_arg(&fxp_watchdog)->ta_int= 0;
+	fxp_set_timer(&fxp_watchdog, HZ, fxp_watchdog_f);
+
+	for (i= 0, fp = &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
+	{
+		if (fp->fxp_mode != FM_ENABLED)
+			continue;
+
+		/* Handle race condition, MII interface mgith be busy */
+		if(!fp->fxp_mii_busy)
+		{
+			/* Check the link status. */
+			if (fxp_link_changed(fp))
+			{
+#if VERBOSE
+				printf("fxp_watchdog_f: link changed\n");
+#endif
+				fp->fxp_report_link= TRUE;
+				fp->fxp_got_int= TRUE;
+				interrupt(fxp_tasknr);
+			}
+		}
+		
+		if (!(fp->fxp_flags & FF_SEND_AVAIL))
+		{
+			/* Assume that an idle system is alive */
+			fp->fxp_tx_alive= TRUE;
+			continue;
+		}
+		if (fp->fxp_tx_alive)
+		{
+			fp->fxp_tx_alive= FALSE;
+			continue;
+		}
+
+		fp->fxp_need_reset= TRUE;
+		fp->fxp_got_int= TRUE;
+		interrupt(fxp_tasknr);
+	}
+}
+
+/*===========================================================================*
+ *				fxp_link_changed			     *
+ *===========================================================================*/
+static int fxp_link_changed(fp)
+fxp_t *fp;
+{
+	u16_t scr;
+
+	scr= mii_read(fp, MII_SCR);
+	scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
+
+	return (fp->fxp_mii_scr != scr);
+}
+
+/*===========================================================================*
+ *				fxp_report_link				     *
+ *===========================================================================*/
+static void fxp_report_link(fp)
+fxp_t *fp;
+{
+	port_t port;
+	u16_t mii_ctrl, mii_status, mii_id1, mii_id2, 
+		mii_ana, mii_anlpa, mii_ane, mii_extstat,
+		mii_ms_ctrl, mii_ms_status, scr;
+	u32_t oui;
+	int model, rev;
+	int f, link_up, ms_regs;
+
+	/* Assume an 82555 (compatible) PHY. The should be changed for
+	 * 82557 NICs with different PHYs
+	 */
+	ms_regs= 0;	/* No master/slave registers. */
+
+	fp->fxp_report_link= FALSE;
+	port= fp->fxp_base_port;
+
+	scr= mii_read(fp, MII_SCR);
+	scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
+	fp->fxp_mii_scr= scr;
+
+	mii_ctrl= mii_read(fp, MII_CTRL);
+	mii_read(fp, MII_STATUS); /* Read the status register twice, why? */
+	mii_status= mii_read(fp, MII_STATUS);
+	mii_id1= mii_read(fp, MII_PHYID_H);
+	mii_id2= mii_read(fp, MII_PHYID_L);
+	mii_ana= mii_read(fp, MII_ANA);
+	mii_anlpa= mii_read(fp, MII_ANLPA);
+	mii_ane= mii_read(fp, MII_ANE);
+	if (mii_status & MII_STATUS_EXT_STAT)
+		mii_extstat= mii_read(fp, MII_EXT_STATUS);
+	else
+		mii_extstat= 0;
+	if (ms_regs)
+	{
+		mii_ms_ctrl= mii_read(fp, MII_MS_CTRL);
+		mii_ms_status= mii_read(fp, MII_MS_STATUS);
+	}
+	else
+	{
+		mii_ms_ctrl= 0;
+		mii_ms_status= 0;
+	}
+
+	/* How do we know about the link status? */
+	link_up= !!(mii_status & MII_STATUS_LS);
+
+	fp->fxp_link_up= link_up;
+	if (!link_up)
+	{
+#if VERBOSE
+		printf("%s: link down\n", fp->fxp_name);
+#endif
+		return;
+	}
+
+	oui= (mii_id1 << MII_PH_OUI_H_C_SHIFT) | 
+		((mii_id2 & MII_PL_OUI_L_MASK) >> MII_PL_OUI_L_SHIFT);
+	model= ((mii_id2 & MII_PL_MODEL_MASK) >> MII_PL_MODEL_SHIFT);
+	rev= (mii_id2 & MII_PL_REV_MASK);
+
+#if VERBOSE
+	printf("OUI 0x%06lx, Model 0x%02x, Revision 0x%x\n", oui, model, rev);
+#endif
+
+	if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO))
+	{
+		printf("%s: PHY: ", fp->fxp_name);
+		f= 1;
+		if (mii_ctrl & MII_CTRL_LB)
+		{
+			printf("loopback mode");
+			f= 0;
+		}
+		if (mii_ctrl & MII_CTRL_PD)
+		{
+			if (!f) printf(", ");
+			f= 0;
+			printf("powered down");
+		}
+		if (mii_ctrl & MII_CTRL_ISO)
+		{
+			if (!f) printf(", ");
+			f= 0;
+			printf("isolated");
+		}
+		printf("\n");
+		return;
+	}
+	if (!(mii_ctrl & MII_CTRL_ANE))
+	{
+		printf("%s: manual config: ", fp->fxp_name);
+		switch(mii_ctrl & (MII_CTRL_SP_LSB|MII_CTRL_SP_MSB))
+		{
+		case MII_CTRL_SP_10:	printf("10 Mbps"); break;
+		case MII_CTRL_SP_100:	printf("100 Mbps"); break;
+		case MII_CTRL_SP_1000:	printf("1000 Mbps"); break;
+		case MII_CTRL_SP_RES:	printf("reserved speed"); break;
+		}
+		if (mii_ctrl & MII_CTRL_DM)
+			printf(", full duplex");
+		else
+			printf(", half duplex");
+		printf("\n");
+		return;
+	}
+
+	if (!debug) goto resspeed;
+
+	printf("%s: ", fp->fxp_name);
+	mii_print_stat_speed(mii_status, mii_extstat);
+	printf("\n");
+
+	if (!(mii_status & MII_STATUS_ANC))
+		printf("%s: auto-negotiation not complete\n", fp->fxp_name);
+	if (mii_status & MII_STATUS_RF)
+		printf("%s: remote fault detected\n", fp->fxp_name);
+	if (!(mii_status & MII_STATUS_ANA))
+	{
+		printf("%s: local PHY has no auto-negotiation ability\n",
+			fp->fxp_name);
+	}
+	if (!(mii_status & MII_STATUS_LS))
+		printf("%s: link down\n", fp->fxp_name);
+	if (mii_status & MII_STATUS_JD)
+		printf("%s: jabber condition detected\n", fp->fxp_name);
+	if (!(mii_status & MII_STATUS_EC))
+	{
+		printf("%s: no extended register set\n", fp->fxp_name);
+		goto resspeed;
+	}
+	if (!(mii_status & MII_STATUS_ANC))
+		goto resspeed;
+
+	printf("%s: local cap.: ", fp->fxp_name);
+	if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
+	{
+		printf("1000 Mbps: T-");
+		switch(mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
+		{
+		case MII_MSC_1000T_FD:	printf("FD"); break;
+		case MII_MSC_1000T_HD:	printf("HD"); break;
+		default:		printf("FD/HD"); break;
+		}
+		if (mii_ana)
+			printf(", ");
+	}
+	mii_print_techab(mii_ana);
+	printf("\n");
+
+	if (mii_ane & MII_ANE_PDF)
+		printf("%s: parallel detection fault\n", fp->fxp_name);
+	if (!(mii_ane & MII_ANE_LPANA))
+	{
+		printf("%s: link-partner does not support auto-negotiation\n",
+			fp->fxp_name);
+		goto resspeed;
+	}
+
+	printf("%s: remote cap.: ", fp->fxp_name);
+	if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
+	if (mii_ms_status & (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
+	{
+		printf("1000 Mbps: T-");
+		switch(mii_ms_status &
+			(MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
+		{
+		case MII_MSS_LP1000T_FD:	printf("FD"); break;
+		case MII_MSS_LP1000T_HD:	printf("HD"); break;
+		default:			printf("FD/HD"); break;
+		}
+		if (mii_anlpa)
+			printf(", ");
+	}
+	mii_print_techab(mii_anlpa);
+	printf("\n");
+
+	if (ms_regs)
+	{
+		printf("%s: ", fp->fxp_name);
+		if (mii_ms_ctrl & MII_MSC_MS_MANUAL)
+		{
+			printf("manual %s",
+				(mii_ms_ctrl & MII_MSC_MS_VAL) ?
+				"MASTER" : "SLAVE");
+		}
+		else
+		{
+			printf("%s device",
+				(mii_ms_ctrl & MII_MSC_MULTIPORT) ?
+				"multiport" : "single-port");
+		}
+		if (mii_ms_ctrl & MII_MSC_RES)
+			printf(" reserved<0x%x>", mii_ms_ctrl & MII_MSC_RES);
+		printf(": ");
+		if (mii_ms_status & MII_MSS_FAULT)
+			printf("M/S config fault");
+		else if (mii_ms_status & MII_MSS_MASTER)
+			printf("MASTER");
+		else
+			printf("SLAVE");
+		printf("\n");
+	}
+
+	if (mii_ms_status & (MII_MSS_LP1000T_FD|MII_MSS_LP1000T_HD))
+	{
+		if (!(mii_ms_status & MII_MSS_LOCREC))
+		{
+			printf("%s: local receiver not OK\n",
+				fp->fxp_name);
+		}
+		if (!(mii_ms_status & MII_MSS_REMREC))
+		{
+			printf("%s: remote receiver not OK\n",
+				fp->fxp_name);
+		}
+	}
+	if (mii_ms_status & (MII_MSS_RES|MII_MSS_IDLE_ERR))
+	{
+		printf("%s", fp->fxp_name);
+		if (mii_ms_status & MII_MSS_RES)
+			printf(" reserved<0x%x>", mii_ms_status & MII_MSS_RES);
+		if (mii_ms_status & MII_MSS_IDLE_ERR)
+		{
+			printf(" idle error %d",
+				mii_ms_status & MII_MSS_IDLE_ERR);
+		}
+		printf("\n");
+	}
+
+resspeed:
+#if VERBOSE
+	printf("%s: link up, %d Mbps, %s duplex\n",
+		fp->fxp_name, (scr & MII_SCR_100) ? 100 : 10,
+		(scr & MII_SCR_FD) ? "full" : "half");
+#endif
+	;
+}
+
+/*===========================================================================*
+ *				fxp_stop				     *
+ *===========================================================================*/
+static void fxp_stop()
+{
+	int i;
+	port_t port;
+	fxp_t *fp;
+
+	for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
+	{
+		if (fp->fxp_mode != FM_ENABLED)
+			continue;
+		if (!(fp->fxp_flags & FF_ENABLED))
+			continue;
+		port= fp->fxp_base_port;
+
+		/* Reset device */
+		if (debug)
+			printf("%s: resetting device\n", fp->fxp_name);
+		fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
+	}
+	sys_exit(0);
+}
+
+/*===========================================================================*
+ *				reply					     *
+ *===========================================================================*/
+static void reply(fp, err, may_block)
+fxp_t *fp;
+int err;
+int may_block;
+{
+	message reply;
+	int status;
+	int r;
+
+	status = 0;
+	if (fp->fxp_flags & FF_PACK_SENT)
+		status |= DL_PACK_SEND;
+	if (fp->fxp_flags & FF_PACK_RECV)
+		status |= DL_PACK_RECV;
+
+	reply.m_type = DL_TASK_REPLY;
+	reply.DL_PORT = fp - fxp_table;
+	reply.DL_PROC = fp->fxp_client;
+	reply.DL_STAT = status | ((u32_t) err << 16);
+	reply.DL_COUNT = fp->fxp_read_s;
+#if 0
+	reply.DL_CLCK = get_uptime();
+#else
+	reply.DL_CLCK = 0;
+#endif
+
+	r= send(fp->fxp_client, &reply);
+
+	if (r == ELOCKED && may_block)
+	{
+#if 0
+		printW(); printf("send locked\n");
+#endif
+		return;
+	}
+
+	if (r < 0)
+		panic("FXP","fxp: send failed:", r);
+	
+	fp->fxp_read_s = 0;
+	fp->fxp_flags &= ~(FF_PACK_SENT | FF_PACK_RECV);
+}
+
+/*===========================================================================*
+ *				mess_reply				     *
+ *===========================================================================*/
+static void mess_reply(req, reply_mess)
+message *req;
+message *reply_mess;
+{
+	if (send(req->m_source, reply_mess) != OK)
+		panic("FXP","fxp: unable to mess_reply", NO_NUM);
+}
+
+/*===========================================================================*
+ *				put_userdata				     *
+ *===========================================================================*/
+static void put_userdata(user_proc, user_addr, count, loc_addr)
+int user_proc;
+vir_bytes user_addr;
+vir_bytes count;
+void *loc_addr;
+{
+	int r;
+
+	r= sys_vircopy(SELF, D, (vir_bytes)loc_addr,
+		user_proc, D, user_addr, count);
+	if (r != OK)
+		panic("FXP","put_userdata: sys_vircopy failed", r);
+}
+
+/*===========================================================================*
+ *				eeprom_read				     *
+ *===========================================================================*/
+PRIVATE u16_t eeprom_read(fp, reg)
+fxp_t *fp;
+int reg;
+{
+	port_t port;
+	u16_t v;
+	int b, i, alen;
+
+	alen= fp->fxp_ee_addrlen;
+	if (!alen)
+	{
+		eeprom_addrsize(fp);
+		alen= fp->fxp_ee_addrlen;
+		assert(alen == 6 || alen == 8);
+	}
+
+	port= fp->fxp_base_port;
+
+	fxp_outb(port, CSR_EEPROM, CE_EECS);	/* Enable EEPROM */
+	v= EEPROM_READ_PREFIX;
+	for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
+	{
+		b= ((v & (1 << i)) ? CE_EEDI : 0);
+		fxp_outb(port, CSR_EEPROM, CE_EECS | b);	/* bit */
+		fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
+		micro_delay(EESK_PERIOD/2+1);
+		fxp_outb(port, CSR_EEPROM, CE_EECS | b);		
+		micro_delay(EESK_PERIOD/2+1);
+	}
+	
+	v= reg;
+	for (i= alen-1; i >= 0; i--)
+	{
+		b= ((v & (1 << i)) ? CE_EEDI : 0);
+		fxp_outb(port, CSR_EEPROM, CE_EECS | b);	/* bit */
+		fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
+		micro_delay(EESK_PERIOD/2+1);
+		fxp_outb(port, CSR_EEPROM, CE_EECS | b);		
+		micro_delay(EESK_PERIOD/2+1);
+	}
+
+	v= 0;
+	for (i= 0; i<16; i++)
+	{
+		fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */
+		micro_delay(EESK_PERIOD/2+1);
+		b= !!(fxp_inb(port, CSR_EEPROM) & CE_EEDO);
+		v= (v << 1) | b;
+		fxp_outb(port, CSR_EEPROM, CE_EECS );		
+		micro_delay(EESK_PERIOD/2+1);
+	}
+	fxp_outb(port, CSR_EEPROM, 0);	/* Disable EEPROM */
+	micro_delay(EECS_DELAY);
+
+	return v;
+}
+
+/*===========================================================================*
+ *				eeprom_addrsize				     *
+ *===========================================================================*/
+PRIVATE void eeprom_addrsize(fp)
+fxp_t *fp;
+{
+	port_t port;
+	u16_t v;
+	int b, i;
+
+	port= fp->fxp_base_port;
+
+	/* Try to find out the size of the EEPROM */
+	fxp_outb(port, CSR_EEPROM, CE_EECS);	/* Enable EEPROM */
+	v= EEPROM_READ_PREFIX;
+	for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
+	{
+		b= ((v & (1 << i)) ? CE_EEDI : 0);
+		fxp_outb(port, CSR_EEPROM, CE_EECS | b);	/* bit */
+		fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
+		micro_delay(EESK_PERIOD/2+1);
+		fxp_outb(port, CSR_EEPROM, CE_EECS | b);		
+		micro_delay(EESK_PERIOD/2+1);
+	}
+
+	for (i= 0; i<32; i++)
+	{
+		b= 0;
+		fxp_outb(port, CSR_EEPROM, CE_EECS | b);	/* bit */
+		fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
+		micro_delay(EESK_PERIOD/2+1);
+		fxp_outb(port, CSR_EEPROM, CE_EECS | b);		
+		micro_delay(EESK_PERIOD/2+1);
+		v= fxp_inb(port, CSR_EEPROM);
+		if (!(v & CE_EEDO))
+			break;
+	}
+	if (i >= 32)
+		panic("FXP","eeprom_addrsize: failed", NO_NUM);
+	fp->fxp_ee_addrlen= i+1;
+
+	/* Discard 16 data bits */
+	for (i= 0; i<16; i++)
+	{
+		fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */
+		micro_delay(EESK_PERIOD/2+1);
+		fxp_outb(port, CSR_EEPROM, CE_EECS );		
+		micro_delay(EESK_PERIOD/2+1);
+	}
+	fxp_outb(port, CSR_EEPROM, 0);	/* Disable EEPROM */
+	micro_delay(EECS_DELAY);
+
+#if VERBOSE
+	printf("%s EEPROM address length: %d\n",
+		fp->fxp_name, fp->fxp_ee_addrlen);
+#endif
+}
+
+/*===========================================================================*
+ *				mii_read				     *
+ *===========================================================================*/
+PRIVATE u16_t mii_read(fp, reg)
+fxp_t *fp;
+int reg;
+{
+	clock_t t0,t1;
+	port_t port;
+	u32_t v;
+
+	port= fp->fxp_base_port;
+
+	assert(!fp->fxp_mii_busy);
+	fp->fxp_mii_busy++;
+
+	if (!(fxp_inl(port, CSR_MDI_CTL) & CM_READY))
+		panic("FXP","mii_read: MDI not ready", NO_NUM);
+	fxp_outl(port, CSR_MDI_CTL, CM_READ | (1 << CM_PHYADDR_SHIFT) |
+		(reg << CM_REG_SHIFT));
+
+	getuptime(&t0);
+	do {
+		v= fxp_inl(port, CSR_MDI_CTL);
+		if (v & CM_READY)
+			break;
+	} while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
+
+	if (!(v & CM_READY))
+		panic("FXP","mii_read: MDI not ready after command", NO_NUM);
+
+	fp->fxp_mii_busy--;
+	assert(!fp->fxp_mii_busy);
+
+	return v & CM_DATA_MASK;
+}
+
+/*===========================================================================*
+ *				fxp_set_timer				     *
+ *===========================================================================*/
+PRIVATE void fxp_set_timer(tp, delta, watchdog)
+timer_t *tp;				/* timer to be set */
+clock_t delta;				/* in how many ticks */
+tmr_func_t watchdog;			/* watchdog function to be called */
+{
+	clock_t now;				/* current time */
+	int r;
+
+	/* Get the current time. */
+	r= getuptime(&now);
+	if (r != OK)
+		panic("FXP","unable to get uptime from clock", r);
+
+	/* Add the timer to the local timer queue. */
+	tmrs_settimer(&fxp_timers, tp, now + delta, watchdog, NULL);
+
+	/* Possibly reschedule an alarm call. This happens when a new timer
+	 * is added in front. 
+	 */
+	if (fxp_next_timeout == 0 || 
+		fxp_timers->tmr_exp_time < fxp_next_timeout)
+	{
+		fxp_next_timeout= fxp_timers->tmr_exp_time; 
+#if VERBOSE
+		printf("fxp_set_timer: calling sys_setalarm for %d (now+%d)\n",
+			fxp_next_timeout, fxp_next_timeout-now);
+#endif
+		r= sys_setalarm(fxp_next_timeout, 1);
+		if (r != OK)
+			panic("FXP","unable to set synchronous alarm", r);
+	}
+}
+
+/*===========================================================================*
+ *				fxp_expire_tmrs				     *
+ *===========================================================================*/
+PRIVATE void fxp_expire_timers()
+{
+/* A synchronous alarm message was received. Check if there are any expired 
+ * timers. Possibly reschedule the next alarm.  
+ */
+  clock_t now;				/* current time */
+  timer_t *tp;
+  int r;
+
+  /* Get the current time to compare the timers against. */
+  r= getuptime(&now);
+  if (r != OK)
+ 	panic("FXP","Unable to get uptime from clock.", r);
+
+  /* Scan the timers queue for expired timers. Dispatch the watchdog function
+   * for each expired timers. Possibly a new alarm call must be scheduled.
+   */
+  tmrs_exptimers(&fxp_timers, now, NULL);
+  if (fxp_timers == NULL)
+  	fxp_next_timeout= TMR_NEVER;
+  else
+  {  					  /* set new alarm */
+  	fxp_next_timeout = fxp_timers->tmr_exp_time;
+  	r= sys_setalarm(fxp_next_timeout, 1);
+  	if (r != OK)
+ 		panic("FXP","Unable to set synchronous alarm.", r);
+  }
+}
+
+static void micro_delay(unsigned long usecs)
+{
+	tickdelay(MICROS_TO_TICKS(usecs));
+}
+
+static u8_t do_inb(port_t port)
+{
+	int r;
+	u32_t value;
+
+	r= sys_inb(port, &value);
+	if (r != OK)
+		panic("FXP","sys_inb failed", r);
+	return value;
+}
+
+static u32_t do_inl(port_t port)
+{
+	int r;
+	u32_t value;
+
+	r= sys_inl(port, &value);
+	if (r != OK)
+		panic("FXP","sys_inl failed", r);
+	return value;
+}
+
+static void do_outb(port_t port, u8_t value)
+{
+	int r;
+
+	r= sys_outb(port, value);
+	if (r != OK)
+		panic("FXP","sys_outb failed", r);
+}
+
+static void do_outl(port_t port, u32_t value)
+{
+	int r;
+
+	r= sys_outl(port, value);
+	if (r != OK)
+		panic("FXP","sys_outl failed", r);
+}
+
+/*
+ * $PchId: fxp.c,v 1.4 2005/01/31 22:10:37 philip Exp $
+ */
+
Index: /trunk/minix/drivers/fxp/fxp.h
===================================================================
--- /trunk/minix/drivers/fxp/fxp.h	(revision 9)
+++ /trunk/minix/drivers/fxp/fxp.h	(revision 9)
@@ -0,0 +1,576 @@
+/*
+ibm/fxp.h
+
+Registers and datastructures of the Intel 82557, 82558, 82559, 82550,
+and 82562 fast ethernet controllers.
+
+Created:	Nov 2004 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+#define VERBOSE 	0	/* display output during intialization */
+
+/* Revisions in PCI_REV */
+#define FXP_REV_82557A		0x01
+#define FXP_REV_82557B		0x02
+#define FXP_REV_82557C		0x03
+#define FXP_REV_82558A		0x04
+#define FXP_REV_82558B		0x05
+#define FXP_REV_82559A		0x06
+#define FXP_REV_82559B		0x07
+#define FXP_REV_82559C		0x08
+#define FXP_REV_82559ERA	0x09
+#define FXP_REV_82550_1 	0x0C
+#define FXP_REV_82550_2		0x0D
+#define FXP_REV_82550_3		0x0E
+#define FXP_REV_82551_1		0x0F
+#define FXP_REV_82551_2		0x10
+
+/* Control/Status Registers (CSR). The first 8 bytes are called
+ * System Control Block (SCB)
+ */
+#define SCB_STATUS	0x00	/* Lower half of the SCB status word. CU and
+				 * RU status.
+				 */
+#define	    SS_CUS_MASK		0xC0	/* CU Status */
+#define		SS_CU_IDLE		0x00	/* Idle */
+#define		SS_CU_SUSP		0x40	/* Suspended */
+#define		SS_CU_LPQA		0x80	/* LPQ Active */
+#define		SS_CU_HQPA		0xC0	/* HQP Active */
+#define	    SS_RUS_MASK		0x3C	/* RU Status */
+#define		SS_RU_IDLE		0x00	/* Idle */
+#define		SS_RU_SUSP		0x04	/* Suspended */
+#define		SS_RU_NORES		0x08	/* No Resources */
+#define		SS_RU_READY		0x10	/* Ready */
+						/* Other values are reserved */
+#define	    SS_RESERVED		0x03	/* Reserved */
+#define SCB_INT_STAT	0x01	/* Upper half of the SCB status word.
+				 * Interrupt status. Also used to acknoledge
+				 * interrupts.
+				 */
+#define		SIS_CX	0x80	/* CU command with interrupt bit set. On
+				 * 82557 also TNO Interrupt.
+				 */
+#define		SIS_FR	0x40	/* Frame Received */
+#define		SIS_CNA	0x20	/* CU Not Active */
+#define		SIS_RNR	0x10	/* RU Not Ready */
+#define		SIS_MDI	0x08	/* MDI read/write cycle completed */
+#define		SIS_SWI	0x04	/* Software Interrupt */
+#define		SIS_RES	0x02	/* Reserved */
+#define		SIS_FCP	0x01	/* Flow Control Pause Interrupt (82558 and
+				 * later, reserved on 82557)
+				 */
+#define SCB_CMD		0x02	/* Lower half of the SCB command word. CU and
+				 * RU commands.
+				 */
+#define	    SC_CUC_MASK		0xF0
+#define		SC_CU_NOP		0x00	/* NOP */
+#define		SC_CU_START		0x10	/* Start CU */
+#define		SC_CU_RESUME		0x20	/* Resume CU */
+#define		SC_CU_LOAD_DCA		0x40	/* Load Dump Counters Address */
+#define		SC_CU_DUMP_SC		0x50	/* Dump Statistical Counters */
+#define		SC_CU_LOAD_BASE		0x60	/* Load CU Base */
+#define		SC_CU_DUMP_RSET_SC	0x70	/* Dump and Reset Counters */
+#define		SC_CU_STATIC_RESUME	0xA0	/* Static Resume, 82558 and
+						 * above
+						 */
+#define	    SC_RESERVED		0x08	/* Reserved */
+#define	    SC_RUC_MASK		0x07	/* RU Command Mask */
+#define		SC_RU_NOP		0x00	/* NOP */
+#define		SC_RU_START		0x01	/* Start RU */
+#define		SC_RU_RESUME		0x02	/* Resume RU */
+#define		SC_RU_DMA_REDIR		0x03	/* DMA Redirect */
+#define		SC_RU_ABORT		0x04	/* Abort RU */
+#define		SC_RU_LOAD_HDR		0x05	/* Load Header Data Size */
+#define		SC_RU_LOAD_BASE		0x06	/* Load RU Base */
+#define SCB_INT_MASK	0x03	/* Upper half of the SCB command word. 
+				 * Interrupt mask. Can also be used to
+				 * generate a 'software' interrupt.
+				 */
+				/* The following 6 mask bits are not valid on
+				 * the 82557.
+				 */
+#define	    SIM_CX	0x80	/* Mask CX */
+#define	    SIM_FR	0x40	/* Mask FR */
+#define	    SIM_CNA	0x20	/* Mask CNA */
+#define	    SIM_RNR	0x10	/* Mask RNR */
+#define	    SIM_ER	0x08	/* Mask ER */
+#define	    SIM_FCP	0x04	/* Mask FCP */
+#define	    SIM_SI	0x02	/* Generate Software Interrupt */
+#define	    SIM_M	0x01	/* Mask all interrupts */
+#define SCB_POINTER	0x04	/* A 32-bit (pointer) argument for CU and RU
+				 * commands.
+				 */
+#define CSR_PORT	0x08	/* Control functions that bypass the SCB */
+#define	    CP_PTR_MASK		0xFFFFFFF0	/* Argument pointer */
+#define	    CP_CMD_MASK		0x0000000F	/* Commands bits */
+#define		CP_CMD_SOFT_RESET	0x00000000	/* Software reset */
+#define	    	    CSR_PORT_RESET_DELAY	10	/* Wait for reset to
+							 * complete. In micro
+							 * seconds.
+							 */
+#define		CP_CMD_SELF_TEST	0x00000001	/* Self test */
+#define		CP_CMD_SEL_RESET	0x00000002	/* Selective reset */
+#define		CP_CMD_DUMP		0x00000003	/* Dump */
+#define		CP_CMD_DUMP_WAKEUP	0x00000007	/* Dump and wake-up,
+							 * 82559 and later.
+							 */
+#define	CSR_RESERVED	0x0C	/* reserved, 16-bits */
+#define CSR_EEPROM	0x0E	/* EEPROM Control Register */
+#define	    CE_RESERVED	0xF0	/* Reserved */
+#define	    CE_EEDO	0x08	/* Serial Data Out  (of the EEPROM) */
+#define	    CE_EEDI	0x04	/* Serial Data In (to the EEPROM) */
+#define	    CE_EECS	0x02	/* Chip Select */
+#define	    CE_EESK	0x01	/* Serial Clock */
+#define CSR_RESERVED1	0x0F	/* Reserved */
+#define CSR_MDI_CTL	0x10	/* MDI Control Register, 32-bits */
+#define	    CM_RESERVED		0xC0000000	/* Reserved */
+#define	    CM_IE		0x20000000	/* Enable Interrupt */
+#define	    CM_READY		0x10000000	/* Command completed */
+#define	    CM_OPCODE_MASK	0x0C000000	/* Opcode */
+#define		CM_WRITE		0x04000000	/* Write */
+#define		CM_READ			0x08000000	/* Read */
+#define	    CM_PHYADDR_MASK	0x03E00000	/* Which PHY */
+#define		CM_PHYADDR_SHIFT 21
+#define	    CM_REG_MASK		0x001F0000	/* Which register in the PHY */
+#define	    	CM_REG_SHIFT	16
+#define	    CM_DATA_MASK	0x0000FFFF	/* Data to be read or written */
+
+/* Control Block List (CBL) commands */
+#define CBL_NOP		0	/* No-operation */
+#define CBL_AIS		1	/* Individual Address Setup */
+#define CBL_CONF	2	/* Configure NIC */
+#define CBL_MAS		3	/* Multicast Address Setup */
+#define CBL_XMIT	4	/* Transmit */
+#define CBL_LM		5	/* Load Microcode */
+#define CBL_DUMP	6	/* Dump Internal Registers */
+#define CBL_DIAG	7	/* Diagnose Command */
+
+/* Common command fields */
+#define CBL_C_CMD_MASK	0x0007	/* Command bits */
+#define CBL_C_EL	0x8000	/* End of CBL */
+#define CBL_C_S		0x4000	/* Suspend after the completion of the CB */
+#define CBL_C_I		0x2000	/* Request CX Interrupt */
+#define CBL_C_RES	0x1FF8	/* Reserved */
+
+/* Command flags */
+#define CBL_F_C		0x8000	/* Command has completed */
+#define CBL_F_RES1	0x4000	/* Reserved */
+#define CBL_F_OK	0x2000	/* Command was executed without errors */
+#define CBL_F_RES0	0x1FFF	/* Reserved */
+
+/* Individual Address Setup (1) */
+struct ias
+{
+	u16_t ias_status;
+	u16_t ias_command;
+	u32_t ias_linkaddr;
+	u8_t ias_ethaddr[6];
+	u8_t ias_reserved[2];
+};
+
+/* Configure (2) */
+#define CC_BYTES_NR	22	/* Number of configuration bytes */
+struct cbl_conf
+{
+	u16_t cc_status;
+	u16_t cc_command;
+	u32_t cc_linkaddr;
+	u8_t cc_bytes[CC_BYTES_NR];
+};
+
+/* Byte 0 */
+#define CCB0_RES	0xC0	/* Reserved (0) */
+#define CCB0_BYTECOUNT	0x3F	/* Byte Count (typically either 8 or 22) */
+
+/* Byte 1 */
+#define CCB1_RES	0x80	/* Reserved (0) */
+#define CCB1_TXFIFO_LIM	0x70	/* Transmit FIFO Limit, in DWORDS */
+#define		CTL_DEFAULT	0x00	/* 0 bytes */
+#define CCB1_RXFIFO_LIM	0x0F	/* Receive FIFO Limit */
+#define		CRL_DEFAULT	0x08	/* 32 bytes on 82557, 64 bytes on
+					 * 82558/82559.
+					 */
+
+/* Byte 2 */
+#define CCB2_AIFS	0xFF	/* Adaptive IFS */
+#define		CAI_DEFAULT	0
+
+/* Byte 3 */
+				/* Reserved (must be 0) on 82557 */
+#define CCB3_RES	0xF0	/* Reserved (0) */
+#define	CCB3_TWCL	0x08	/* Terminate Write on Cache Line */
+#define	CCB3_RAE	0x04	/* Read Alignment Enable */
+#define	CCB3_TE		0x02	/* Type Enable??? */
+#define	CCB3_MWIE	0x01	/* Memory Write and Invalidate (MWI) Enable
+				 * Additionally the MWI bit in the PCI
+				 * command register has to be set.
+				 * Recommended by Intel.
+				 */
+
+/* Byte 4 */
+#define CCB4_RES	0x80	/* Reserved (0) */
+#define CCB4_RXDMA_MAX	0x7F	/* Receive DMA Maximum Byte Count */
+
+/* Byte 5 */
+#define CCB5_DMBCE	0x80	/* DMA Maximum Byte Count Enable */
+#define CCB5_TXDMA_MAX	0x7F	/* Transmit DMA Maximum Byte Count */
+
+/* Byte 6 */
+#define CCB6_SBF	0x80	/* Save Bad Frames */
+#define CCB6_DORF	0x40	/* (Do not) Discard Overrun Receive Frame,
+				 * Set this bit to keep them.
+				 */
+#define CCB6_ESC	0x20	/* Extended Statistical Counter. Reserved
+				 * on 82557, must be set to 1.
+				 * Clear this bit to get more counters.
+				 */
+#define CCB6_ETCB	0x10	/* Extended Transmit CB. Reserved on 82557,
+				 * must be set to 1.
+				 * Clear this bit to use Extended TxCBs.
+				 */
+#define CCB6_CI_INT	0x08	/* CPU Idle (CI) Interrupt. Generate a
+				 * CI Int (bit set) or a CNA Int (bit clear)
+				 * when the CU goes to the idle state (or
+				 * to suspended for CNA).
+				 */
+#define CCB6_TNO_INT	0x04	/* Enable TNO Interrupt (82557 only) */
+#define CCB6_TCOSC	0x04	/* TCO Statistical Counter (82559 only) */
+#define CCB6_RES	0x02	/* Reserved, must be set to 1. Called "disable
+				 * direct rcv dma mode" by the FreeBSD
+				 * driver.
+				 */
+#define CCB6_LSCB	0x01	/* Late SCB Update. Only on 82557. */
+
+/* Byte 7 */
+#define CCB7_DTBD	0x80	/* Dynamic TBD. Reserved on 82557, should be
+				 * be set to 0.
+				 */
+#define CCB7_2FFIFO	0x40	/* (At Most) Two Frames in FIFO. Reserved on
+				 * 82557, should be set to 0.
+				 */
+#define CCB7_RES	0x38	/* Reserved (0) */
+#define CCB7_UR		0x06	/* Underrun Retry */
+#define	    CUR_0		0x00	/* No re-transmission */
+#define	    CUR_1		0x02	/* One re-transmission */
+#define	    CUR_2		0x04	/* Two re-transmissions, 1st retry with
+					 * 512 bytes.
+					 */
+#define	    CUR_3		0x06	/* Tree re-transmissions, 1st retry
+					 * with 512 bytes, 2nd retry with 1024.
+					 */
+#define CCB7_DSRF	0x01	/* Discard Short Receive Frames. */
+
+/* Byte 8 */
+#define CCB8_CSMAD	0x80	/* CSMA Disable. Reserved on 82557, should be
+				 * set to zero.
+				 */
+#define CCB8_RES	0x7E	/* Reserved (0) */
+#define CCB8_503_MII	0x01	/* 503 mode or MII mode. Reserved on 82558
+				 * and 82559, should be set to 1.
+				 */
+
+/* Byte 9 */
+#define CCB9_MMWE	0x80	/* Multicast Match Wake Enable. 82558 B-step
+				 * only, should be set to zero on other
+				 * devices.
+				 */
+#define CCB9_AWE	0x40	/* ARP Wake-up Enable. 82558 B-step only,
+				 * should be set to zero on other devices.
+				 */
+#define CCB9_LSCWE	0x20	/* Link Status Change Wake Enable. Available
+				 * on 82558 B-step and 82559. Should be
+				 * set to zero on 82557 and 82558 A-step
+				 */
+#define CCB9_VARP	0x10	/* VLAN ARP (82558 B-step) or VLAN TCO (82559).
+				 * Should be zero on 82557 and 82558 A-step
+				 */
+#define CCB9_RES	0x0E	/* Reserved (0) */
+#define CCB9_TUC	0x01	/* TCP/UDP Checksum. 82559 only, should be
+				 * zero on other devices.
+				 */
+
+/* Byte 10 */
+#define CCB10_LOOPBACK	0xC0	/* Loopback mode */
+#define	    CLB_NORMAL		0x00	/* Normal operation */
+#define	    CLB_INTERNAL	0x40	/* Internal loopback */
+#define	    CLB_RESERVED	0x80	/* Reserved */
+#define	    CLB_EXTERNAL	0xC0	/* External loopback */
+#define CCB10_PAL	0x30	/* Pre-amble length */
+#define	    CPAL_1		0x00	/* 1 byte */
+#define	    CPAL_3		0x10	/* 3 bytes */
+#define	    CPAL_7		0x20	/* 7 bytes */
+#define	    CPAL_15		0x30	/* 15 bytes */
+#define	    CPAL_DEFAULT	CPAL_7
+#define CCB10_NSAI		0x08	/* No Source Address Insertion */
+#define CCB10_RES1		0x06	/* Reserved, should be set to 1 */
+#define CCB10_RES0		0x01	/* Reserved (0) */
+
+/* Byte 11 */
+#define CCB11_RES		0xF8	/* Reserved (0) */
+#define CCB11_LINPRIO		0x07	/* Linear Priority. 82557 only,
+					 * should be zero on other devices.
+					 */
+
+/* Byte 12 */
+#define CCB12_IS		0xF0	/* Interframe spacing in multiples of
+					 * 16 bit times.
+					 */
+#define	    CIS_DEFAULT			0x60	/* 96 (6 in register) */
+#define	CCB12_RES		0x0E	/* Reserved (0) */
+#define	CCB12_LPM		0x01	/* Linear Priority Mode. 82557 only,
+					 * should be zero on other devices.
+					 */
+
+/* Byte 13, 4th byte of IP address for ARP frame filtering. Only valid on
+ * 82558 B-step. Should be 0 on other devices.
+ */
+#define CCB13_DEFAULT		0x00
+/* Byte 14, 3rd byte of IP address for ARP fram efiltering. Only valid on
+ * 82558 B-step. Should be 0xF2 on other devices.
+ */
+#define CCB14_DEFAULT		0xF2
+
+/* Byte 15 */
+#define CCB15_CRSCDT		0x80	/* CRS or CDT. */
+#define CCB15_RES1		0x40	/* Reserved, should be set to one. */
+#define CCB15_CRC16		0x20	/* 16-bit CRC. Only on 82559,
+					 * should be zero on other devices
+					 */
+#define CCB15_IUL		0x10	/* Ignore U/L. Reserved on 82557 and
+					 * should be set to zero.
+					 */
+#define CCB15_RES2		0x08	/* Reserved, should be set to one. */
+#define CCB15_WAW		0x04	/* Wait After Win. Reserved on 82557,
+					 * should be set to zero.
+					 */
+#define CCB15_BD		0x02	/* Broadcast disable */
+#define CCB15_PM		0x01	/* Promiscuous mode */
+
+/* Byte 16. FC Delay Least Significant Byte. Reserved on the 82557 and
+ * should be set to zero.
+ */
+#define CCB16_DEFAULT		0x00
+
+/* Byte 17. FC Delay Most Significant Byte. This byte is reserved on the
+ * 82557 and should be set to 0x40.
+ */
+#define CCB17_DEFAULT		0x40
+
+/* Byte 18 */
+#define CCB18_RES1		0x80	/* Reserved, should be set to 1 */
+#define CCB18_PFCT		0x70	/* Priority Flow Control Threshold.
+					 * Reserved on the 82557 and should
+					 * be set to 1. All bits 1 (disabled)
+					 * is the recommended default.
+					 */
+#define CCB18_LROK		0x08	/* Long Receive OK. Reserved on the
+					 * 82557 and should be set to zero.
+					 * Required for VLANs.
+					 */
+#define CCB18_RCRCT		0x04	/* Receive CRC Transfer */
+#define CCB18_PE		0x02	/* Padding Enable */
+#define CCB18_SE		0x01	/* Stripping Enable */
+
+/* Byte 19 */
+#define CCB19_FDPE		0x80	/* Full Duplex Pin Enable */
+#define CCB19_FFD		0x40	/* Force Full Duplex */
+#define CCB19_RFC		0x20	/* Reject FC. Reserved on the 82557
+					 * and should be set to zero.
+					 */
+#define CCB19_FDRSTAFC		0x10	/* Full Duplex Restart Flow Control.
+					 * Reserved on the 82557 and should be
+					 * set to zero.
+					 */
+#define CCB19_FDRSTOFC		0x08	/* Full Duplex Restop Flow Control.
+					 * Reserved on the 82557 and should be
+					 * set to zero.
+					 */
+#define CCB19_FDTFCD		0x04	/* Full Duplex Transmit Flow Control
+					 * Disable. Reserved on the 82557 and
+					 * should be set to zero.
+					 */
+#define CCB19_MPWD		0x02	/* Magic Packet Wake-up Disable.
+					 * Reserved on the 82557 and 82559ER
+					 * and should be set to zero.
+					 */
+#define CCB19_AW		0x01	/* Address Wake-up (82558 A-step) and
+					 * IA Match Wake Enable (82558 B-step)
+					 * Reserved on the 82557 and 82559 and
+					 * should be set to zero.
+					 */
+
+/* Byte 20 */
+#define CCB20_RES		0x80	/* Reserved (0) */
+#define CCB20_MIA		0x40	/* Multiple IA */
+#define CCB20_PFCL		0x20	/* Priority FC Location. Reserved on
+					 * the 82557 and should be set to 1.
+					 */
+#define CCB20_RES1		0x1F	/* Reserved, should be set to 1 */
+
+/* Byte 21 */
+#define CCB21_RES		0xF0	/* Reserved (0) */
+#define CCB21_MA		0x08	/* Multicast All */
+#define CCB21_RES1_MASK		0x07	/* Reserved, should be set to 5 */
+#define     CCB21_RES21			0x05
+
+/* Transmit (4) */
+struct tx
+{
+	u16_t tx_status;
+	u16_t tx_command;
+	u32_t tx_linkaddr;
+	u32_t tx_tbda;
+	u16_t tx_size;
+	u8_t tx_tthresh;
+	u8_t tx_ntbd;
+	u8_t tx_buf[ETH_MAX_PACK_SIZE_TAGGED];
+};
+
+#define TXS_C		0x8000	/* Transmit DMA has completed */
+#define TXS_RES		0x4000	/* Reserved */
+#define TXS_OK		0x2000	/* Command was executed without error */
+#define TXS_U		0x1000	/* This or previous frame encoutered underrun */
+#define TXS_RES1	0x0FFF	/* Reserved (0) */
+
+#define TXC_EL		0x8000	/* End of List */
+#define TXC_S		0x4000	/* Suspend after this CB */
+#define TXC_I		0x2000	/* Interrupt after this CB */
+#define TXC_CID_MASK	0x1F00	/* CNA Interrupt Delay */
+#define TXC_RES		0x00E0	/* Reserved (0) */
+#define TXC_NC		0x0010	/* No CRC and Source Address Insertion */
+#define TXC_SF		0x0008	/* Not in Simplified Mode */
+#define TXC_CMD		0x0007	/* Command */
+
+#define TXSZ_EOF	0x8000	/* End of Frame */
+#define TXSZ_RES	0x4000	/* Reserved (0) */
+#define TXSZ_COUNT	0x3FFF	/* Transmit Byte Count */
+
+#define TX_TBDA_NIL	0xFFFFFFFF	/* Null Pointer for TBD Array */
+
+#define TXTT_MIN	0x01	/* Minimum for Transmit Threshold */
+#define TXTT_MAX	0xE0	/* Maximum for Transmit Threshold */
+
+/* Statistical Counters */
+struct sc
+{
+	u32_t sc_tx_good;	/* Transmit Good Frames */
+	u32_t sc_tx_maxcol;	/* Transmit Maximum Collisions errors */
+	u32_t sc_tx_latecol;	/* Transmit Late Collisions errors */
+	u32_t sc_tx_underrun;	/* Transmit Underrun errors */
+	u32_t sc_tx_crs;	/* Transmit Lost Carrier Sense */
+	u32_t sc_tx_defered;	/* Transmit Defered */
+	u32_t sc_tx_scol;	/* Transmit Single Collision */
+	u32_t sc_tx_mcol;	/* Transmit Multiple Collisions */
+	u32_t sc_tx_totcol;	/* Transmit Total Collisions */
+	u32_t sc_rx_good;	/* Receive Good Frames */
+	u32_t sc_rx_crc;	/* Receive CRC errors */
+	u32_t sc_rx_align;	/* Receive Alignment errors */
+	u32_t sc_rx_resource;	/* Receive Resource errors */
+	u32_t sc_rx_overrun;	/* Receive Overrun errors */
+	u32_t sc_rx_cd;		/* Receive Collision Detect errors */
+	u32_t sc_rx_short;	/* Receive Short Frame errors */
+
+				/* Short form ends here. The magic number will
+				 * be stored in the next field.
+				 */
+
+	u32_t sc_tx_fcp;	/* Transmit Flow Control Pause */
+	u32_t sc_rx_fcp;	/* Receive Flow Control Pause */
+	u32_t sc_rx_fcu;	/* Receive Flow Control Unsupported */
+
+				/* Longer form (82558 and later) ends here.
+				 * The magic number will be stored in the
+				 * next field.
+				 */
+
+	u32_t sc_tx_tco;	/* Transmit TCO frames */
+	u32_t sc_rx_tco;	/* Receive TCO frames */
+	u32_t sc_magic;		/* Dump of counters completed */
+};
+
+#define SCM_DSC		0x0000A005	/* Magic for SC_CU_DUMP_SC command */
+#define SCM_DRSC	0x0000A007	/* Magic for SC_CU_DUMP_RSET_SC cmd */
+
+/* Receive Frame Descriptor (RFD) */
+struct rfd
+{
+	u16_t rfd_status;
+	u16_t rfd_command;
+	u32_t rfd_linkaddr;
+	u32_t rfd_reserved;
+	u16_t rfd_res;
+	u16_t rfd_size;
+	u8_t rfd_buf[ETH_MAX_PACK_SIZE_TAGGED];
+};
+
+#define RFDS_C		0x8000	/* Frame Reception Completed */
+#define RFDS_RES	0x4000	/* Reserved (0) */
+#define RFDS_OK		0x2000	/* Frame received without any errors */
+#define RFDS_RES1	0x1000	/* Reserved */
+#define RFDS_CRCERR	0x0800	/* CRC error */
+#define RFDS_ALIGNERR	0x0400	/* Alignment error */
+#define RFDS_OUTOFBUF	0x0200	/* Ran out of buffer space (frame is frager
+				 * than supplied buffer).
+				 */
+#define RFDS_DMAOVR	0x0100	/* DMA overrun failure */
+#define RFDS_TOOSHORT	0x0080	/* Frame Too Short */
+#define RFDS_RES2	0x0040	/* Reserved */
+#define RFDS_TYPED	0x0020	/* Frame Is Typed (Type/Length field is 0 or
+				 * >1500)
+				 */
+#define RFDS_RXERR	0x0010	/* Receive Error */
+#define RFDS_RES3	0x0008	/* Reserved */
+#define RFDS_NOAM	0x0004	/* No Address Match */
+#define RFDS_NOAIAM	0x0002	/* No IA Address Match */
+#define RFDS_RXCOL	0x0001	/* Collition Detected During Reception (82557
+				 * and 82558 only)
+				 */
+#define RFDS_TCO	0x0001	/* TCO Packet (82559 and later) */
+
+#define RFDC_EL		0x8000	/* End of List */
+#define RFDC_S		0x4000	/* Suspend */
+#define RFDC_RES	0x3FE0	/* Reserved (0) */
+#define RFDC_H		0x0010	/* Header RFD */
+#define RFDC_SF		0x0008	/* (Not) Simplified Mode */
+#define RFDC_RES1	0x0007	/* Reserved (0) */
+
+#define RFDR_EOF	0x8000	/* End of Frame (all data is in the buffer) */
+#define RFDR_F		0x4000	/* Finished updating the count field */
+#define RFDR_COUNT	0x3FFF	/* Actual Count */
+
+#define RFDSZ_RES	0xC000	/* Reserved (0) */
+#define RFDSZ_SIZE	0x3FFF	/* Buffer Size */
+
+/* EEPROM commands */
+#define EEPROM_READ_PREFIX	0x6	/* Read command */
+#define EEPROM_PREFIX_LEN	3	/* Start bit and two command bits */
+
+/* EEPROM timing parameters */
+#define EECS_DELAY	1	/* Keep EECS low for at least EECS_DELAY
+				 * microseconds
+				 */
+#define EESK_PERIOD	4	/* A cycle of driving EESK high followed by
+				 * driving EESK low should take at least
+				 * EESK_PERIOD microseconds
+				 */
+
+/* Special registers in the 82555 (and compatible) PHYs. Should be moved
+ * to a separate file if other drivers need this too.
+ */
+#define MII_SCR		0x10	/* Status and Control Register */
+#define	    MII_SCR_FC		0x8000	/* Flow Control */
+#define	    MII_SCR_T4E		0x4000	/* Enable T4 unless auto-negotiation */
+#define	    MII_SCR_CRSDC	0x2000	/* RX100 CRS Disconnect */
+#define	    MII_SCR_RES		0x1000	/* Reserved */
+#define	    MII_SCR_RCVSYNC	0x0800	/* RCV De-Serializer in sync */
+#define	    MII_SCR_100DOWN	0x0400	/* 100Base-T Power Down */
+#define	    MII_SCR_10DOWN	0x0200	/* 10Base-T Power Down */
+#define	    MII_SCR_POLARITY	0x0100	/* 10Base-T Polarity */
+#define	    MII_SCR_RES_1	0x00F8	/* Reserved */
+#define	    MII_SCR_T4		0x0004	/* 100Base-T4 negotiated */
+#define	    MII_SCR_100		0x0002	/* 100 Mbps negotiated */
+#define	    MII_SCR_FD		0x0001	/* Full Duplex negotiated */
+
+/*
+ * $PchId: fxp.h,v 1.1 2004/11/23 14:34:03 philip Exp $
+ */
Index: /trunk/minix/drivers/fxp/mii.c
===================================================================
--- /trunk/minix/drivers/fxp/mii.c	(revision 9)
+++ /trunk/minix/drivers/fxp/mii.c	(revision 9)
@@ -0,0 +1,198 @@
+/*
+ibm/mii.c
+
+Created:	Nov 2004 by Philip Homburg <philip@f-mnx.phicoh.com>
+
+Media Independent (Ethernet) Interface functions
+*/
+
+#include "../drivers.h"
+#if __minix_vmd
+#include "config.h"
+#endif
+
+#include "mii.h"
+
+/*===========================================================================*
+ *				mii_print_stat_speed			     *
+ *===========================================================================*/
+PUBLIC void mii_print_stat_speed(stat, extstat)
+u16_t stat;
+u16_t extstat;
+{
+	int fs, ft;
+
+	fs= 1;
+	if (stat & MII_STATUS_EXT_STAT)
+	{
+		if (extstat & (MII_ESTAT_1000XFD | MII_ESTAT_1000XHD |
+			MII_ESTAT_1000TFD | MII_ESTAT_1000THD))
+		{
+			printf("1000 Mbps: ");
+			fs= 0;
+			ft= 1;
+			if (extstat & (MII_ESTAT_1000XFD | MII_ESTAT_1000XHD))
+			{
+				ft= 0;
+				printf("X-");
+				switch(extstat &
+					(MII_ESTAT_1000XFD|MII_ESTAT_1000XHD))
+				{
+				case MII_ESTAT_1000XFD:	printf("FD"); break;
+				case MII_ESTAT_1000XHD:	printf("HD"); break;
+				default:		printf("FD/HD"); break;
+				}
+			}
+			if (extstat & (MII_ESTAT_1000TFD | MII_ESTAT_1000THD))
+			{
+				if (!ft)
+					printf(", ");
+				ft= 0;
+				printf("T-");
+				switch(extstat &
+					(MII_ESTAT_1000TFD|MII_ESTAT_1000THD))
+				{
+				case MII_ESTAT_1000TFD:	printf("FD"); break;
+				case MII_ESTAT_1000THD:	printf("HD"); break;
+				default:		printf("FD/HD"); break;
+				}
+			}
+		}
+	}
+	if (stat & (MII_STATUS_100T4 |
+		MII_STATUS_100XFD | MII_STATUS_100XHD |
+		MII_STATUS_100T2FD | MII_STATUS_100T2HD))
+	{
+		if (!fs)
+			printf(", ");
+		fs= 0;
+		printf("100 Mbps: ");
+		ft= 1;
+		if (stat & MII_STATUS_100T4)
+		{
+			printf("T4");
+			ft= 0;
+		}
+		if (stat & (MII_STATUS_100XFD | MII_STATUS_100XHD))
+		{
+			if (!ft)
+				printf(", ");
+			ft= 0;
+			printf("TX-");
+			switch(stat & (MII_STATUS_100XFD|MII_STATUS_100XHD))
+			{
+			case MII_STATUS_100XFD:	printf("FD"); break;
+			case MII_STATUS_100XHD:	printf("HD"); break;
+			default:		printf("FD/HD"); break;
+			}
+		}
+		if (stat & (MII_STATUS_100T2FD | MII_STATUS_100T2HD))
+		{
+			if (!ft)
+				printf(", ");
+			ft= 0;
+			printf("T2-");
+			switch(stat & (MII_STATUS_100T2FD|MII_STATUS_100T2HD))
+			{
+			case MII_STATUS_100T2FD:	printf("FD"); break;
+			case MII_STATUS_100T2HD:	printf("HD"); break;
+			default:		printf("FD/HD"); break;
+			}
+		}
+	}
+	if (stat & (MII_STATUS_10FD | MII_STATUS_10HD))
+	{
+		if (!fs)
+			printf(", ");
+		printf("10 Mbps: ");
+		fs= 0;
+		printf("T-");
+		switch(stat & (MII_STATUS_10FD|MII_STATUS_10HD))
+		{
+		case MII_STATUS_10FD:	printf("FD"); break;
+		case MII_STATUS_10HD:	printf("HD"); break;
+		default:		printf("FD/HD"); break;
+		}
+	}
+}
+
+/*===========================================================================*
+ *				mii_print_techab			     *
+ *===========================================================================*/
+PUBLIC void mii_print_techab(techab)
+u16_t techab;
+{
+	int fs, ft;
+
+	if ((techab & MII_ANA_SEL_M) != MII_ANA_SEL_802_3)
+	{
+		printf("strange selector 0x%x, value 0x%x",
+			techab & MII_ANA_SEL_M,
+			(techab & MII_ANA_TAF_M) >> MII_ANA_TAF_S);
+		return;
+	}
+	fs= 1;
+	if (techab & (MII_ANA_100T4 | MII_ANA_100TXFD | MII_ANA_100TXHD))
+	{
+		printf("100 Mbps: ");
+		fs= 0;
+		ft= 1;
+		if (techab & MII_ANA_100T4)
+		{
+			printf("T4");
+			ft= 0;
+		}
+		if (techab & (MII_ANA_100TXFD | MII_ANA_100TXHD))
+		{
+			if (!ft)
+				printf(", ");
+			ft= 0;
+			printf("TX-");
+			switch(techab & (MII_ANA_100TXFD|MII_ANA_100TXHD))
+			{
+			case MII_ANA_100TXFD:	printf("FD"); break;
+			case MII_ANA_100TXHD:	printf("HD"); break;
+			default:		printf("FD/HD"); break;
+			}
+		}
+	}
+	if (techab & (MII_ANA_10TFD | MII_ANA_10THD))
+	{
+		if (!fs)
+			printf(", ");
+		printf("10 Mbps: ");
+		fs= 0;
+		printf("T-");
+		switch(techab & (MII_ANA_10TFD|MII_ANA_10THD))
+		{
+		case MII_ANA_10TFD:	printf("FD"); break;
+		case MII_ANA_10THD:	printf("HD"); break;
+		default:		printf("FD/HD"); break;
+		}
+	}
+	if (techab & MII_ANA_PAUSE_SYM)
+	{
+		if (!fs)
+			printf(", ");
+		fs= 0;
+		printf("pause(SYM)");
+	}
+	if (techab & MII_ANA_PAUSE_ASYM)
+	{
+		if (!fs)
+			printf(", ");
+		fs= 0;
+		printf("pause(ASYM)");
+	}
+	if (techab & MII_ANA_TAF_RES)
+	{
+		if (!fs)
+			printf(", ");
+		fs= 0;
+		printf("0x%x", (techab & MII_ANA_TAF_RES) >> MII_ANA_TAF_S);
+	}
+}
+
+/*
+ * $PchId: mii.c,v 1.2 2005/01/31 22:17:26 philip Exp $
+ */
Index: /trunk/minix/drivers/fxp/mii.h
===================================================================
--- /trunk/minix/drivers/fxp/mii.h	(revision 9)
+++ /trunk/minix/drivers/fxp/mii.h	(revision 9)
@@ -0,0 +1,116 @@
+/*
+ibm/mii.h
+
+Created:	Nov 2004 by Philip Homburg <philip@f-mnx.phicoh.com>
+
+Definitions for the Media Independent (Ethernet) Interface
+*/
+
+/* Registers in the Machine Independent Interface (MII) to the PHY.
+ * IEEE 802.3 (2000 Edition) Clause 22.
+ */
+#define MII_CTRL	0x0	/* Control Register (basic) */
+#define		MII_CTRL_RST	0x8000	/* Reset PHY */
+#define		MII_CTRL_LB	0x4000	/* Enable Loopback Mode */
+#define		MII_CTRL_SP_LSB	0x2000	/* Speed Selection (LSB) */
+#define		MII_CTRL_ANE	0x1000	/* Auto Negotiation Enable */
+#define		MII_CTRL_PD	0x0800	/* Power Down */
+#define		MII_CTRL_ISO	0x0400	/* Isolate */
+#define		MII_CTRL_RAN	0x0200	/* Restart Auto-Negotiation Process */
+#define		MII_CTRL_DM	0x0100	/* Full Duplex */
+#define		MII_CTRL_CT	0x0080	/* Enable COL Signal Test */
+#define		MII_CTRL_SP_MSB	0x0040	/* Speed Selection (MSB) */
+#define			MII_CTRL_SP_10		0x0000	/* 10 Mb/s */
+#define			MII_CTRL_SP_100		0x2000	/* 100 Mb/s */
+#define			MII_CTRL_SP_1000	0x0040	/* 1000 Mb/s */
+#define			MII_CTRL_SP_RES		0x2040	/* Reserved */
+#define		MII_CTRL_RES	0x003F	/* Reserved */
+#define MII_STATUS	0x1	/* Status Register (basic) */
+#define		MII_STATUS_100T4	0x8000	/* 100Base-T4 support */
+#define		MII_STATUS_100XFD	0x4000	/* 100Base-X FD support */
+#define		MII_STATUS_100XHD	0x2000	/* 100Base-X HD support */
+#define		MII_STATUS_10FD		0x1000	/* 10 Mb/s FD support */
+#define		MII_STATUS_10HD		0x0800	/* 10 Mb/s HD support */
+#define		MII_STATUS_100T2FD	0x0400	/* 100Base-T2 FD support */
+#define		MII_STATUS_100T2HD	0x0200	/* 100Base-T2 HD support */
+#define		MII_STATUS_EXT_STAT	0x0100	/* Supports MII_EXT_STATUS */
+#define		MII_STATUS_RES		0x0080	/* Reserved */
+#define		MII_STATUS_MFPS		0x0040	/* MF Preamble Suppression */
+#define		MII_STATUS_ANC		0x0020	/* Auto-Negotiation Completed */
+#define		MII_STATUS_RF		0x0010	/* Remote Fault Detected */
+#define		MII_STATUS_ANA		0x0008	/* Auto-Negotiation Ability */
+#define		MII_STATUS_LS		0x0004	/* Link Up */
+#define		MII_STATUS_JD		0x0002	/* Jabber Condition Detected */
+#define		MII_STATUS_EC		0x0001	/* Ext Register Capabilities */
+#define MII_PHYID_H	0x2	/* PHY ID (high) */
+#define		MII_PH_OUI_H_MASK	0xFFFF	/* High part of OUI */
+#define			MII_PH_OUI_H_C_SHIFT	6	/* Shift up in OUI */
+#define MII_PHYID_L	0x3	/* PHY ID (low) */
+#define		MII_PL_OUI_L_MASK	0xFC00	/* Low part of OUI */
+#define			MII_PL_OUI_L_SHIFT	10
+#define		MII_PL_MODEL_MASK	0x03F0	/* Model */
+#define			MII_PL_MODEL_SHIFT	4
+#define		MII_PL_REV_MASK		0x000F	/* Revision */
+#define MII_ANA		0x4	/* Auto-Negotiation Advertisement */
+#define		MII_ANA_NP	0x8000	/* Next PAge */
+#define		MII_ANA_RES	0x4000	/* Reserved */
+#define		MII_ANA_RF	0x2000	/* Remote Fault */
+#define		MII_ANA_TAF_M	0x1FE0	 /* Technology Ability Field */
+#define		MII_ANA_TAF_S	5	 /* Shift */
+#define			MII_ANA_TAF_RES		0x1000	/* Reserved */
+#define			MII_ANA_PAUSE_ASYM	0x0800	/* Asym. Pause */
+#define			MII_ANA_PAUSE_SYM	0x0400	/* Sym. Pause */
+#define			MII_ANA_100T4		0x0200	/* 100Base-T4 */
+#define			MII_ANA_100TXFD		0x0100	/* 100Base-TX FD */
+#define			MII_ANA_100TXHD		0x0080	/* 100Base-TX HD */
+#define			MII_ANA_10TFD		0x0040	/* 10Base-T FD */
+#define			MII_ANA_10THD		0x0020	/* 10Base-T HD */
+#define		MII_ANA_SEL_M	0x001F	 /* Selector Field */
+#define			MII_ANA_SEL_802_3 0x0001 /* 802.3 */
+#define MII_ANLPA	0x5	/* Auto-Neg Link Partner Ability Register */
+#define		MII_ANLPA_NP	0x8000	/* Next Page */
+#define		MII_ANLPA_ACK	0x4000	/* Acknowledge */
+#define		MII_ANLPA_RF	0x2000	/* Remote Fault */
+#define		MII_ANLPA_TAF_M	0x1FC0	 /* Technology Ability Field */
+#define		MII_ANLPA_SEL_M	0x001F	 /* Selector Field */
+#define MII_ANE		0x6	/* Auto-Negotiation Expansion */
+#define		MII_ANE_RES	0xFFE0	/* Reserved */
+#define		MII_ANE_PDF	0x0010	/* Parallel Detection Fault */
+#define		MII_ANE_LPNPA	0x0008	/* Link Partner is Next Page Able */
+#define		MII_ANE_NPA	0x0002	/* Local Device is Next Page Able */
+#define		MII_ANE_PR	0x0002	/* New Page has been received */
+#define		MII_ANE_LPANA	0x0001	/* Link Partner is Auto-Neg.able */
+#define MII_ANNPT	0x7	/* Auto-Negotiation Next Page Transmit */
+#define MII_ANLPRNP	0x8	/* Auto-Neg Link Partner Received Next Page */
+#define MII_MS_CTRL	0x9	/* MASTER-SLAVE Control Register */
+#define		MII_MSC_TEST_MODE	0xE000	/* Test mode */
+#define		MII_MSC_MS_MANUAL	0x1000	/* Master/slave manual config */
+#define		MII_MSC_MS_VAL		0x0800	/* Master/slave value */
+#define		MII_MSC_MULTIPORT	0x0400	/* Multi-port device */
+#define		MII_MSC_1000T_FD	0x0200	/* 1000Base-T Full Duplex */
+#define		MII_MSC_1000T_HD	0x0100	/* 1000Base-T Half Duplex */
+#define		MII_MSC_RES		0x00FF	/* Reserved */
+#define MII_MS_STATUS	0xA	/* MASTER-SLAVE Status Register */
+#define		MII_MSS_FAULT		0x8000	/* Master/slave config fault */
+#define		MII_MSS_MASTER		0x4000	/* Master */
+#define		MII_MSS_LOCREC		0x2000	/* Local Receiver OK */
+#define		MII_MSS_REMREC		0x1000	/* Remote Receiver OK */
+#define		MII_MSS_LP1000T_FD	0x0800	/* Link Partner 1000-T FD */
+#define		MII_MSS_LP1000T_HD	0x0400	/* Link Partner 1000-T HD */
+#define		MII_MSS_RES		0x0300	/* Reserved */
+#define		MII_MSS_IDLE_ERR	0x00FF	/* Idle Error Counter */
+/* 0xB ... 0xE */		/* Reserved */
+#define MII_EXT_STATUS	0xF	/* Extended Status */
+#define		MII_ESTAT_1000XFD	0x8000	/* 1000Base-X Full Duplex */
+#define		MII_ESTAT_1000XHD	0x4000	/* 1000Base-X Half Duplex */
+#define		MII_ESTAT_1000TFD	0x2000	/* 1000Base-T Full Duplex */
+#define		MII_ESTAT_1000THD	0x1000	/* 1000Base-T Half Duplex */
+#define		MII_ESTAT_RES		0x0FFF	/* Reserved */
+/* 0x10 ... 0x1F */		/* Vendor Specific */
+
+_PROTOTYPE( void mii_print_stat_speed, (U16_t stat, U16_t extstat)	);
+_PROTOTYPE( void mii_print_techab, (U16_t techab)			);
+
+/*
+ * $PchId: mii.h,v 1.1 2004/12/27 13:33:30 philip Exp $
+ */
Index: /trunk/minix/drivers/lance/.depend
===================================================================
--- /trunk/minix/drivers/lance/.depend	(revision 9)
+++ /trunk/minix/drivers/lance/.depend	(revision 9)
@@ -0,0 +1,37 @@
+
+lance.o:	../drivers.h
+lance.o:	/usr/include/ansi.h
+lance.o:	/usr/include/assert.h
+lance.o:	/usr/include/errno.h
+lance.o:	/usr/include/ibm/bios.h
+lance.o:	/usr/include/ibm/interrupt.h
+lance.o:	/usr/include/ibm/pci.h
+lance.o:	/usr/include/ibm/ports.h
+lance.o:	/usr/include/limits.h
+lance.o:	/usr/include/minix/bitmap.h
+lance.o:	/usr/include/minix/callnr.h
+lance.o:	/usr/include/minix/com.h
+lance.o:	/usr/include/minix/config.h
+lance.o:	/usr/include/minix/const.h
+lance.o:	/usr/include/minix/devio.h
+lance.o:	/usr/include/minix/dmap.h
+lance.o:	/usr/include/minix/ioctl.h
+lance.o:	/usr/include/minix/ipc.h
+lance.o:	/usr/include/minix/keymap.h
+lance.o:	/usr/include/minix/sys_config.h
+lance.o:	/usr/include/minix/syslib.h
+lance.o:	/usr/include/minix/sysutil.h
+lance.o:	/usr/include/minix/type.h
+lance.o:	/usr/include/net/gen/eth_io.h
+lance.o:	/usr/include/net/gen/ether.h
+lance.o:	/usr/include/net/hton.h
+lance.o:	/usr/include/signal.h
+lance.o:	/usr/include/stddef.h
+lance.o:	/usr/include/stdlib.h
+lance.o:	/usr/include/string.h
+lance.o:	/usr/include/sys/dir.h
+lance.o:	/usr/include/sys/ioc_memory.h
+lance.o:	/usr/include/sys/types.h
+lance.o:	/usr/include/unistd.h
+lance.o:	lance.c
+lance.o:	lance.h
Index: /trunk/minix/drivers/lance/Makefile
===================================================================
--- /trunk/minix/drivers/lance/Makefile	(revision 9)
+++ /trunk/minix/drivers/lance/Makefile	(revision 9)
@@ -0,0 +1,40 @@
+# Makefile for Intel Pro/100 driver (FXP)
+DRIVER = lance
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i 
+LIBS = -lsys -lsysutil
+#-lutils -ltimers
+
+OBJ = lance.o
+
+# build local binary
+all build:	$(DRIVER)
+$(DRIVER):	$(OBJ) 
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+	install -S 4k $(DRIVER)
+
+# install with other drivers
+install:	/usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER):	$(DRIVER)
+	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f *.o *.bak $(DRIVER)
+
+depend:
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
Index: /trunk/minix/drivers/lance/lance.c
===================================================================
--- /trunk/minix/drivers/lance/lance.c	(revision 9)
+++ /trunk/minix/drivers/lance/lance.c	(revision 9)
@@ -0,0 +1,1832 @@
+/*
+ * lance.c
+ *
+ * This file contains a ethernet device driver for AMD LANCE based ethernet
+ * cards.
+ *
+ * The valid messages and their parameters are:
+ *
+ *   m_type       DL_PORT    DL_PROC   DL_COUNT   DL_MODE   DL_ADDR
+ * |------------+----------+---------+----------+---------+---------|
+ * | HARDINT    |          |         |          |         |         |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_WRITE   | port nr  | proc nr | count    | mode    | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_WRITEV  | port nr  | proc nr | count    | mode    | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_READ    | port nr  | proc nr | count    |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_READV   | port nr  | proc nr | count    |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_INIT    | port nr  | proc nr | mode     |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_GETSTAT | port nr  | proc nr |          |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_STOP    | port_nr  |         |          |         |         |
+ * |------------|----------|---------|----------|---------|---------|
+ *
+ * The messages sent are:
+ *
+ *   m-type       DL_POR T   DL_PROC   DL_COUNT   DL_STAT   DL_CLCK
+ * |------------|----------|---------|----------|---------|---------|
+ * |DL_TASK_REPL| port nr  | proc nr | rd-count | err|stat| clock   |
+ * |------------|----------|---------|----------|---------|---------|
+ *
+ *   m_type       m3_i1     m3_i2       m3_ca1
+ * |------------+---------+-----------+---------------|
+ * |DL_INIT_REPL| port nr | last port | ethernet addr |
+ * |------------|---------|-----------|---------------|
+ *
+ * Created: Jul 27, 2002 by Kazuya Kodama <kazuya@nii.ac.jp>
+ * Adapted for Minix 3: Sep 05, 2005 by Joren l'Ami <jwlami@cs.vu.nl>
+ */
+
+#define VERBOSE 0
+
+#include "../drivers.h"
+
+#include <minix/keymap.h>
+#include <net/hton.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include <assert.h>
+
+#include <minix/syslib.h>
+#include <ibm/pci.h>
+
+#include "lance.h"
+/*#include "proc.h"*/
+
+#include <sys/ioc_memory.h>
+
+/* new I/O functions in Minix 3 */
+#define out_byte( x, y ) sys_outb( x, y )
+#define out_word( x, y ) sys_outw( x, y )
+
+static U8_t in_byte(U16_t port)
+{
+	unsigned long value;
+	int s;
+	if ((s=sys_inb(port, &value)) != OK)
+		printf( "lance: warning, sys_inb failed: %d\n", s );
+	return (U8_t) value;
+}
+
+static U16_t in_word( U16_t port)
+{
+	unsigned long value;
+	int s;
+	if ((s=sys_inw(port, &value)) != OK)
+		printf( "lance: warning, sys_inw failed: %d\n", s );
+	return (U16_t) value;
+}
+/*
+#define in_byte( x ) inb( x )
+#define in_word( x ) inw( x )
+*/
+
+static ether_card_t ec_table[EC_PORT_NR_MAX];
+static int eth_tasknr= ANY;
+static u16_t eth_ign_proto;
+
+/* Configuration */
+typedef struct ec_conf
+{
+  port_t ec_port;
+  int ec_irq;
+  phys_bytes ec_mem;
+  char *ec_envvar;
+} ec_conf_t;
+
+/* We hardly use these. Just "LANCE0=on/off" "LANCE1=on/off" mean. */
+ec_conf_t ec_conf[]=    /* Card addresses */
+{
+        /* I/O port, IRQ,  Buffer address,  Env. var,   Buf selector. */
+        {  0x1000,     9,    0x00000,        "LANCE0" },
+        {  0xD000,    15,    0x00000,        "LANCE1" },
+};
+
+/* Actually, we use PCI-BIOS info. */
+PRIVATE struct pcitab
+{
+	u16_t vid;
+	u16_t did;
+	int checkclass;
+} pcitab[]=
+{
+	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, 0 },		/* AMD LANCE */
+
+	{ 0x0000, 0x0000, 0 }
+};
+/*
+struct pci_device pci_dev_list[] = {
+  { PCI_VENDOR_ID_AMD,          PCI_DEVICE_ID_AMD_LANCE,
+    "AMD Lance/PCI",            0, 0, 0, 0, 0, 0}, 
+  { PCI_VENDOR_ID_AMD,          PCI_DEVICE_ID_AMD_LANCE,
+    "AMD Lance/PCI",            0, 0, 0, 0, 0, 0}, 
+  {0, 0, NULL, 0, 0, 0, 0, 0, 0}
+};
+*/
+
+/* General */
+_PROTOTYPE( static void do_init, (message *mp)                          );
+_PROTOTYPE( static void ec_init, (ether_card_t *ec)                     );
+_PROTOTYPE( static void ec_confaddr, (ether_card_t *ec)                 );
+_PROTOTYPE( static void ec_reinit, (ether_card_t *ec)                   );
+_PROTOTYPE( static void ec_check_ints, (ether_card_t *ec)               );
+_PROTOTYPE( static void conf_hw, (ether_card_t *ec)                     );
+/*_PROTOTYPE( static int ec_handler, (irq_hook_t *hook)                   );*/
+_PROTOTYPE( static void update_conf, (ether_card_t *ec, ec_conf_t *ecp) );
+_PROTOTYPE( static void mess_reply, (message *req, message *reply)      );
+_PROTOTYPE( static void do_int, (ether_card_t *ec)                      );
+_PROTOTYPE( static void reply, 
+	    (ether_card_t *ec, int err, int may_block)                  );
+_PROTOTYPE( static void ec_reset, (ether_card_t *ec)                    );
+_PROTOTYPE( static void ec_send, (ether_card_t *ec)                     );
+_PROTOTYPE( static void ec_recv, (ether_card_t *ec)                     );
+_PROTOTYPE( static void do_vwrite, 
+	    (message *mp, int from_int, int vectored)                   );
+_PROTOTYPE( static void do_vread, (message *mp, int vectored)           );
+_PROTOTYPE( static void get_userdata, 
+	    (int user_proc, vir_bytes user_addr, 
+	     vir_bytes count, void *loc_addr)                           );
+_PROTOTYPE( static void ec_user2nic, 
+	    (ether_card_t *dep, iovec_dat_t *iovp, 
+	     vir_bytes offset, int nic_addr, 
+	     vir_bytes count)                                           );
+_PROTOTYPE( static void ec_nic2user, 
+	    (ether_card_t *ec, int nic_addr, 
+	     iovec_dat_t *iovp, vir_bytes offset, 
+	     vir_bytes count)                                           );
+_PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp)             );
+_PROTOTYPE( static void ec_next_iovec, (iovec_dat_t *iovp)              );
+_PROTOTYPE( static void do_getstat, (message *mp)                       );
+_PROTOTYPE( static void put_userdata, 
+	    (int user_proc,
+	     vir_bytes user_addr, vir_bytes count, 
+	     void *loc_addr)                                            );
+_PROTOTYPE( static void do_stop, (message *mp)                          );
+_PROTOTYPE( static void do_getname, (message *mp)                       );
+
+_PROTOTYPE( static void lance_dump, (void)				);
+_PROTOTYPE( static void lance_stop, (void)				);
+_PROTOTYPE( static void getAddressing, (int devind, ether_card_t *ec)	);
+
+/* probe+init LANCE cards */
+_PROTOTYPE( static int lance_probe, (ether_card_t *ec)                  );
+_PROTOTYPE( static void lance_init_card, (ether_card_t *ec)             );
+
+/* --- LANCE --- */
+/* General */
+#define Address                 unsigned long
+
+
+/* Minix 3 */
+#define virt_to_bus(x)          (vir2phys((unsigned long)x))
+unsigned long vir2phys( unsigned long x )
+{
+	int r;
+	unsigned long value;
+	
+	if ( (r=sys_umap( SELF, D, x, 4, &value )) != OK )
+		panic( "lance", "sys_umap failed", r );
+	
+	return value;
+}
+
+/* DMA limitations */
+#define DMA_ADDR_MASK  0xFFFFFF	/* mask to verify DMA address is 24-bit */
+
+#define CORRECT_DMA_MEM() ( (virt_to_bus(lance + sizeof(lance)) & ~DMA_ADDR_MASK) == 0 )
+
+#define ETH_FRAME_LEN           1518
+
+#define LANCE_MUST_PAD          0x00000001
+#define LANCE_ENABLE_AUTOSELECT 0x00000002
+#define LANCE_SELECT_PHONELINE  0x00000004
+#define LANCE_MUST_UNRESET      0x00000008
+
+static const struct lance_chip_type
+{
+  int        id_number;
+  const char *name;
+  int        flags;
+} chip_table[] = {
+  {0x0000, "LANCE 7990",           /* Ancient lance chip.  */
+   LANCE_MUST_PAD + LANCE_MUST_UNRESET},
+  {0x0003, "PCnet/ISA 79C960",     /* 79C960 PCnet/ISA.  */
+   LANCE_ENABLE_AUTOSELECT},
+  {0x2260, "PCnet/ISA+ 79C961",    /* 79C961 PCnet/ISA+, Plug-n-Play.  */
+   LANCE_ENABLE_AUTOSELECT},
+  {0x2420, "PCnet/PCI 79C970",     /* 79C970 or 79C974 PCnet-SCSI, PCI. */
+   LANCE_ENABLE_AUTOSELECT},
+  {0x2430, "PCnet32",              /* 79C965 PCnet for VL bus. */
+   LANCE_ENABLE_AUTOSELECT},
+  {0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II. */
+   LANCE_ENABLE_AUTOSELECT},
+  {0x2625, "PCnet-FAST III 79C973",/* 79C973 PCInet-FAST III. */
+   LANCE_ENABLE_AUTOSELECT},
+  {0x2626, "PCnet/HomePNA 79C978",        
+   LANCE_ENABLE_AUTOSELECT|LANCE_SELECT_PHONELINE},
+  {0x0, "PCnet (unknown)",
+   LANCE_ENABLE_AUTOSELECT},
+};
+
+/* ############## for LANCE device ############## */
+#define LANCE_ETH_ADDR          0x0
+#define LANCE_DATA              0x10
+#define LANCE_ADDR              0x12
+#define LANCE_RESET             0x14
+#define LANCE_BUS_IF            0x16
+#define LANCE_TOTAL_SIZE        0x18
+
+/* Use 2^4=16 {Rx,Tx} buffers */
+#define LANCE_LOG_RX_BUFFERS    4
+#define RX_RING_SIZE            (1 << (LANCE_LOG_RX_BUFFERS))
+#define RX_RING_MOD_MASK        (RX_RING_SIZE - 1)
+#define RX_RING_LEN_BITS        ((LANCE_LOG_RX_BUFFERS) << 29)
+
+#define LANCE_LOG_TX_BUFFERS    4
+#define TX_RING_SIZE            (1 << (LANCE_LOG_TX_BUFFERS))
+#define TX_RING_MOD_MASK        (TX_RING_SIZE - 1)
+#define TX_RING_LEN_BITS        ((LANCE_LOG_TX_BUFFERS) << 29)
+
+/* for lance_interface */
+struct lance_init_block
+{
+  unsigned short  mode;
+  unsigned char   phys_addr[6];
+  unsigned long   filter[2];
+  Address         rx_ring;
+  Address         tx_ring;
+};
+
+struct lance_rx_head
+{
+  union {
+    Address         base;
+    unsigned char   addr[4];
+  } u;
+  short           buf_length;     /* 2s complement */
+  short           msg_length;
+};
+
+struct lance_tx_head
+{
+  union {
+    Address         base;
+    unsigned char   addr[4];
+  } u;
+  short           buf_length;     /* 2s complement */
+  short           misc;
+};
+
+struct lance_interface
+{
+  struct lance_init_block init_block;
+  struct lance_rx_head    rx_ring[RX_RING_SIZE];
+  struct lance_tx_head    tx_ring[TX_RING_SIZE];
+  unsigned char           rbuf[RX_RING_SIZE][ETH_FRAME_LEN];
+  unsigned char           tbuf[TX_RING_SIZE][ETH_FRAME_LEN];
+};
+
+/* =============== global variables =============== */
+static struct lance_interface  *lp;
+static char lance[sizeof(struct lance_interface)+8];
+static int rx_slot_nr = 0;          /* Rx-slot number */
+static int tx_slot_nr = 0;          /* Tx-slot number */
+static int cur_tx_slot_nr = 0;      /* Tx-slot number */
+static char isstored[TX_RING_SIZE]; /* Tx-slot in-use */
+static char *progname;
+
+
+/*===========================================================================*
+ *                            lance_task                                     *
+ *===========================================================================*/
+void main( int argc, char **argv )
+{
+  message m;
+  int i,irq,r, tasknr;
+  ether_card_t *ec;
+  long v;
+	int fkeys, sfkeys;
+	(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
+
+	env_setargs( argc, argv );
+	
+	fkeys = sfkeys = 0; bit_set( sfkeys, 7 );
+ 
+#if 0
+	if ( (r = fkey_map(&fkeys, &sfkeys)) != OK )
+		printf( "Error registering key\n" );
+#endif
+	
+	if((eth_tasknr=getprocnr()) < 0)
+		panic("lance","couldn't get own proc nr", i);
+
+  v= 0;
+  (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
+  eth_ign_proto= htons((u16_t) v);
+
+  /* Try to notify inet that we are present (again) */
+  r = _pm_findproc("inet", &tasknr);
+  if (r == OK)
+	notify(tasknr);
+
+  while (TRUE)
+    {
+      for (i=0;i<EC_PORT_NR_MAX;++i)
+	{
+	  ec= &ec_table[i];
+	  if (ec->ec_irq != 0)
+	    sys_irqenable(&ec->ec_hook);
+	}
+	
+      if ((r= receive(ANY, &m)) != OK)
+        panic( "lance", "receive failed", r);
+        
+      for (i=0;i<EC_PORT_NR_MAX;++i)
+	{
+	  ec= &ec_table[i];
+	  if (ec->ec_irq != 0)
+	    sys_irqdisable(&ec->ec_hook);
+	}
+
+/*printf( "." );*/
+
+      switch (m.m_type){
+      case DEV_PING:   notify(m.m_source);		continue;
+      case DL_WRITE:   do_vwrite(&m, FALSE, FALSE);    break;
+      case DL_WRITEV:  do_vwrite(&m, FALSE, TRUE);     break;
+      case DL_READ:    do_vread(&m, FALSE);            break;
+      case DL_READV:   do_vread(&m, TRUE);             break;
+      case DL_INIT:    do_init(&m);                    break;
+      case DL_GETSTAT: do_getstat(&m);                 break;
+      case DL_STOP:    do_stop(&m);                    break;
+      case DL_GETNAME: do_getname(&m); 			break;
+      case FKEY_PRESSED: lance_dump();                 break;
+      /*case HARD_STOP:  lance_stop();                   break;*/
+      case SYS_SIG:
+      {
+      	sigset_t set = m.NOTIFY_ARG;
+      	if ( sigismember( &set, SIGKSTOP ) )
+      		lance_stop();
+      }
+      	break;
+      case HARD_INT:
+        for (i=0;i<EC_PORT_NR_MAX;++i)
+          {
+            ec= &ec_table[i];
+            if (ec->mode != EC_ENABLED)
+              continue;
+            
+            /*
+            printf( "#.\n" );
+            */
+            
+            irq=ec->ec_irq;
+            /*if (ec->ec_int_pending)*/
+              {
+                ec->ec_int_pending = 0;
+                ec_check_ints(ec);
+                do_int(ec);
+              }
+          }
+        break;
+      case PROC_EVENT:
+	break;
+      default:
+        panic( "lance", "illegal message", m.m_type);
+      }
+    }
+}
+
+/*===========================================================================*
+ *                            lance_dump                                     *
+ *===========================================================================*/
+static void lance_dump()
+{
+  ether_card_t *ec;
+  int i, isr;
+  unsigned short ioaddr;
+  
+  printf("\n");
+  for (i= 0, ec = &ec_table[0]; i<EC_PORT_NR_MAX; i++, ec++)
+    {
+      if (ec->mode == EC_DISABLED)
+	printf("lance port %d is disabled\n", i);
+      else if (ec->mode == EC_SINK)
+	printf("lance port %d is in sink mode\n", i);
+      
+      if (ec->mode != EC_ENABLED)
+	continue;
+      
+      printf("lance statistics of port %d:\n", i);
+      
+      printf("recvErr    :%8ld\t", ec->eth_stat.ets_recvErr);
+      printf("sendErr    :%8ld\t", ec->eth_stat.ets_sendErr);
+      printf("OVW        :%8ld\n", ec->eth_stat.ets_OVW);
+      
+      printf("CRCerr     :%8ld\t", ec->eth_stat.ets_CRCerr);
+      printf("frameAll   :%8ld\t", ec->eth_stat.ets_frameAll);
+      printf("missedP    :%8ld\n", ec->eth_stat.ets_missedP);
+      
+      printf("packetR    :%8ld\t", ec->eth_stat.ets_packetR);
+      printf("packetT    :%8ld\t", ec->eth_stat.ets_packetT);
+      printf("transDef   :%8ld\n", ec->eth_stat.ets_transDef);
+      
+      printf("collision  :%8ld\t", ec->eth_stat.ets_collision);
+      printf("transAb    :%8ld\t", ec->eth_stat.ets_transAb);
+      printf("carrSense  :%8ld\n", ec->eth_stat.ets_carrSense);
+      
+      printf("fifoUnder  :%8ld\t", ec->eth_stat.ets_fifoUnder);
+      printf("fifoOver   :%8ld\t", ec->eth_stat.ets_fifoOver);
+      printf("CDheartbeat:%8ld\n", ec->eth_stat.ets_CDheartbeat);
+      
+      printf("OWC        :%8ld\t", ec->eth_stat.ets_OWC);
+      
+      ioaddr = ec->ec_port;
+      out_word(ioaddr+LANCE_ADDR, 0x00);
+      isr=in_word(ioaddr+LANCE_DATA);
+      printf("isr = 0x%x + 0x%x, flags = 0x%x\n", isr,
+	     in_word(ioaddr+LANCE_DATA), ec->flags);
+      
+      printf("irq = %d\tioadr = %d\n", ec->ec_irq, ec->ec_port);
+    }
+}
+
+/*===========================================================================*
+ *                               lance_stop                                  *
+ *===========================================================================*/
+static void lance_stop()
+{
+  message mess;
+  int i;
+
+  for (i= 0; i<EC_PORT_NR_MAX; i++)
+    {
+      if (ec_table[i].mode != EC_ENABLED)
+	continue;
+      mess.m_type= DL_STOP;
+      mess.DL_PORT= i;
+      do_stop(&mess);
+    }
+    
+  	/*printf("LANCE driver stopped.\n");*/
+  	
+  	sys_exit( 0 );
+}
+
+
+/*===========================================================================*
+ *                              do_init                                      *
+ *===========================================================================*/
+static void do_init(mp)
+message *mp;
+{
+  int port;
+  ether_card_t *ec;
+  message reply_mess;
+
+pci_init();
+
+  port = mp->DL_PORT;
+  if (port < 0 || port >= EC_PORT_NR_MAX)
+    {
+      reply_mess.m_type= DL_INIT_REPLY;
+      reply_mess.m3_i1= ENXIO;
+      mess_reply(mp, &reply_mess);
+      return;
+    }
+  ec= &ec_table[port];
+  strcpy(ec->port_name, "eth_card#0");
+  ec->port_name[9] += port;
+  if (ec->mode == EC_DISABLED)
+    {
+      /* This is the default, try to (re)locate the device. */
+      /* only try to enable if memory is correct for DMA */
+	  if ( CORRECT_DMA_MEM() )
+	  {
+		conf_hw(ec);
+	  }
+	  else
+	  {
+	  	report( "LANCE", "DMA denied because address out of range", NO_NUM );
+	  }
+	  
+      if (ec->mode == EC_DISABLED)
+	{
+	  /* Probe failed, or the device is configured off. */
+	  reply_mess.m_type= DL_INIT_REPLY;
+	  reply_mess.m3_i1= ENXIO;
+	  mess_reply(mp, &reply_mess);
+	  return;
+	}
+      if (ec->mode == EC_ENABLED)
+	ec_init(ec);
+    }
+
+  if (ec->mode == EC_SINK)
+    {
+      ec->mac_address.ea_addr[0] = 
+	ec->mac_address.ea_addr[1] = 
+	ec->mac_address.ea_addr[2] = 
+	ec->mac_address.ea_addr[3] = 
+	ec->mac_address.ea_addr[4] = 
+	ec->mac_address.ea_addr[5] = 0;
+      ec_confaddr(ec);
+      reply_mess.m_type = DL_INIT_REPLY;
+      reply_mess.m3_i1 = mp->DL_PORT;
+      reply_mess.m3_i2 = EC_PORT_NR_MAX;
+      *(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address;
+      mess_reply(mp, &reply_mess);
+      return;
+    }
+  assert(ec->mode == EC_ENABLED);
+  assert(ec->flags & ECF_ENABLED);
+
+  ec->flags &= ~(ECF_PROMISC | ECF_MULTI | ECF_BROAD);
+
+  if (mp->DL_MODE & DL_PROMISC_REQ)
+    ec->flags |= ECF_PROMISC | ECF_MULTI | ECF_BROAD;
+  if (mp->DL_MODE & DL_MULTI_REQ)
+    ec->flags |= ECF_MULTI;
+  if (mp->DL_MODE & DL_BROAD_REQ)
+    ec->flags |= ECF_BROAD;
+
+  ec->client = mp->m_source;
+  ec_reinit(ec);
+
+  reply_mess.m_type = DL_INIT_REPLY;
+  reply_mess.m3_i1 = mp->DL_PORT;
+  reply_mess.m3_i2 = EC_PORT_NR_MAX;
+  *(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address;
+
+  mess_reply(mp, &reply_mess);
+}
+
+
+/*===========================================================================*
+ *                              do_int                                       *
+ *===========================================================================*/
+static void do_int(ec)
+ether_card_t *ec;
+{
+  if (ec->flags & (ECF_PACK_SEND | ECF_PACK_RECV))
+    reply(ec, OK, TRUE);
+}
+
+#if 0
+/*===========================================================================*
+ *                              ec_handler                                   *
+ *===========================================================================*/
+static int ec_handler(hook)
+irq_hook_t *hook;
+{
+  /* LANCE interrupt, send message and reenable interrupts. */
+#if 0
+  printf(">> ec_handler(): \n");
+#endif
+
+  structof(ether_card_t, ec_hook, hook)->ec_int_pending= 1;
+
+  notify(eth_tasknr);
+
+  return 0;
+}
+#endif
+
+/*===========================================================================*
+ *                              conf_hw                                      *
+ *===========================================================================*/
+static void conf_hw(ec)
+ether_card_t *ec;
+{
+  static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0        /* ,... */ };
+
+  int ifnr;
+  ec_conf_t *ecp;
+
+  ec->mode= EC_DISABLED;     /* Superfluous */
+  ifnr= ec-ec_table;
+
+  ecp= &ec_conf[ifnr];
+  update_conf(ec, ecp);
+  if (ec->mode != EC_ENABLED)
+    return;
+
+  if (!lance_probe(ec))
+    {
+      printf("%s: No ethernet card found on PCI-BIOS info.\n", 
+	     ec->port_name);
+      ec->mode= EC_DISABLED;
+      return;
+    }
+
+  /* Allocate a memory segment, programmed I/O should set the
+   * memory segment (linmem) to zero.
+   */
+  if (ec->ec_linmem != 0)
+    {
+    	assert( 0 );
+      	/*phys2seg(&ec->ec_memseg, &ec->ec_memoff, ec->ec_linmem);*/
+    }
+
+/* XXX */ if (ec->ec_linmem == 0) ec->ec_linmem= 0xFFFF0000;
+
+  ec->flags = ECF_EMPTY;
+  ec->eth_stat = empty_stat;
+}
+
+
+/*===========================================================================*
+ *                              update_conf                                  *
+ *===========================================================================*/
+static void update_conf(ec, ecp)
+ether_card_t *ec;
+ec_conf_t *ecp;
+{
+  long v;
+  static char ec_fmt[] = "x:d:x:x";
+
+  /* Get the default settings and modify them from the environment. */
+  ec->mode= EC_SINK;
+  v= ecp->ec_port;
+  switch (env_parse(ecp->ec_envvar, ec_fmt, 0, &v, 0x0000L, 0xFFFFL)) {
+  case EP_OFF:
+    ec->mode= EC_DISABLED;
+    break;
+  case EP_ON:
+  case EP_SET:
+    ec->mode= EC_ENABLED;      /* Might become disabled if 
+				* all probes fail */
+    break;
+  }
+  
+  ec->ec_port= v;
+
+  v= ecp->ec_irq | DEI_DEFAULT;
+  (void) env_parse(ecp->ec_envvar, ec_fmt, 1, &v, 0L,
+		   (long) NR_IRQ_VECTORS - 1);
+  ec->ec_irq= v;
+  
+  v= ecp->ec_mem;
+  (void) env_parse(ecp->ec_envvar, ec_fmt, 2, &v, 0L, 0xFFFFFL);
+  ec->ec_linmem= v;
+  
+  v= 0;
+  (void) env_parse(ecp->ec_envvar, ec_fmt, 3, &v, 0x2000L, 0x8000L);
+  ec->ec_ramsize= v;
+}
+
+
+/*===========================================================================*
+ *                              ec_init                                      *
+ *===========================================================================*/
+static void ec_init(ec)
+ether_card_t *ec;
+{
+  int i, r;
+
+  /* General initialization */
+  ec->flags = ECF_EMPTY;
+  /*disable_irq(ec->ec_irq);*/
+  lance_init_card(ec); /* Get mac_address, etc ...*/
+
+  ec_confaddr(ec);
+
+#if VERBOSE
+  printf("%s: Ethernet address ", ec->port_name);
+  for (i= 0; i < 6; i++)
+    printf("%x%c", ec->mac_address.ea_addr[i],
+	   i < 5 ? ':' : '\n');
+#endif
+
+  /* Finish the initialization */
+  ec->flags |= ECF_ENABLED;
+
+  /* Set the interrupt handler */
+  /*put_irq_handler(&ec->ec_hook, ec->ec_irq, ec_handler);*/
+  ec->ec_hook = ec->ec_irq;
+  	if ((r=sys_irqsetpolicy(ec->ec_irq, 0, &ec->ec_hook)) != OK)
+		printf("lance: error, couldn't set IRQ policy: %d\n", r);
+
+/*  enable_irq(ec->ec_irq); */
+
+/*  enter_kdebug(">> ec_init():"); */
+
+  return;
+}
+
+
+/*===========================================================================*
+ *                              reply                                        *
+ *===========================================================================*/
+static void reply(ec, err, may_block)
+ether_card_t *ec;
+int err;
+int may_block;
+{
+  message reply;
+  int status,r;
+  clock_t now;
+
+  status = 0;
+  if (ec->flags & ECF_PACK_SEND)
+    status |= DL_PACK_SEND;
+  if (ec->flags & ECF_PACK_RECV)
+    status |= DL_PACK_RECV;
+
+  reply.m_type   = DL_TASK_REPLY;
+  reply.DL_PORT  = ec - ec_table;
+  reply.DL_PROC  = ec->client;
+  reply.DL_STAT  = status | ((u32_t) err << 16);
+  reply.DL_COUNT = ec->read_s;
+#if 1
+  if ((r=getuptime(&now)) != OK)
+	panic("lance", "getuptime() failed:", r);
+  reply.DL_CLCK = now; 
+#else
+  reply.DL_CLCK = 0;
+#endif
+
+  r = send(ec->client, &reply);
+#if 1
+  if (r == ELOCKED && may_block)
+    {
+/*     enter_kdebug(">> lance_task: ELOCKED!"); */
+      return;
+    }
+#endif
+  if (r < 0)
+    panic( "lance", "send failed:", r);
+
+  ec->read_s = 0;
+  ec->flags &= ~(ECF_PACK_SEND | ECF_PACK_RECV);
+}
+
+
+/*===========================================================================*
+ *                              mess_reply                                   *
+ *===========================================================================*/
+static void mess_reply(req, reply_mess)
+message *req;
+message *reply_mess;
+{
+  if (send(req->m_source, reply_mess) != OK)
+    panic( "lance", "unable to mess_reply", NO_NUM);
+}
+
+
+/*===========================================================================*
+ *                              ec_confaddr                                  *
+ *===========================================================================*/
+static void ec_confaddr(ec)
+ether_card_t *ec;
+{
+  int i;
+  char eakey[16];
+  static char eafmt[]= "x:x:x:x:x:x";
+  long v;
+
+  /* User defined ethernet address? */
+  strcpy(eakey, ec_conf[ec-ec_table].ec_envvar);
+  strcat(eakey, "_EA");
+
+  for (i= 0; i < 6; i++)
+    {
+      v= ec->mac_address.ea_addr[i];
+      if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
+	break;
+      ec->mac_address.ea_addr[i]= v;
+    }
+  
+  if (i != 0 && i != 6)
+    {
+      /* It's all or nothing; force a panic. */
+      (void) env_parse(eakey, "?", 0, &v, 0L, 0L);
+    }
+}
+
+
+/*===========================================================================*
+ *                              ec_reinit                                    *
+ *===========================================================================*/
+static void ec_reinit(ec)
+ether_card_t *ec;
+{
+  int i;
+  unsigned short ioaddr = ec->ec_port;
+
+  out_word(ioaddr+LANCE_ADDR, 0x0);
+  (void)in_word(ioaddr+LANCE_ADDR);
+  out_word(ioaddr+LANCE_DATA, 0x4);           /* stop */
+
+  /* purge Tx-ring */
+  tx_slot_nr = cur_tx_slot_nr = 0;
+  for (i=0; i<TX_RING_SIZE; i++) {
+    lp->tx_ring[i].u.base = 0;
+    isstored[i]=0;
+  }
+
+  /* re-init Rx-ring */
+  rx_slot_nr = 0;
+  for (i=0; i<RX_RING_SIZE; i++) 
+    {
+      lp->rx_ring[i].buf_length = -ETH_FRAME_LEN;
+      lp->rx_ring[i].u.addr[3] |= 0x80;
+    }
+
+  /* Set 'Receive Mode' */
+  if (ec->flags & ECF_PROMISC)
+    {
+      out_word(ioaddr+LANCE_ADDR, 0xf);
+      out_word(ioaddr+LANCE_DATA, 0x8000);
+    }
+  else
+    {
+      if (ec->flags & (ECF_BROAD | ECF_MULTI))
+        {
+          out_word(ioaddr+LANCE_ADDR, 0xf);
+          out_word(ioaddr+LANCE_DATA, 0x0000);
+        }
+      else
+        {
+          out_word(ioaddr+LANCE_ADDR, 0xf);
+          out_word(ioaddr+LANCE_DATA, 0x4000);
+        }
+    }
+
+  out_word(ioaddr+LANCE_ADDR, 0x0);
+  (void)in_word(ioaddr+LANCE_ADDR);
+  out_word(ioaddr+LANCE_DATA, 0x142);   /* start && enable interrupt */
+
+  return;
+}
+
+/*===========================================================================*
+ *                              ec_check_ints                                *
+ *===========================================================================*/
+static void ec_check_ints(ec)
+ether_card_t *ec;
+{
+  int must_restart=0;
+  int check,status;
+  int isr=0x0000;
+  unsigned short ioaddr = ec->ec_port;
+
+  if (!(ec->flags & ECF_ENABLED))
+    panic( "lance", "got premature interrupt", NO_NUM);
+
+    for (;;)
+      {
+#if 0
+	printf("ETH: Reading ISR...");
+#endif
+	out_word(ioaddr+LANCE_ADDR, 0x00);
+	isr=in_word(ioaddr+LANCE_DATA);
+	if (isr & 0x8600)
+	  out_word( ioaddr+LANCE_DATA, isr & ~0x004f);
+	out_word(ioaddr+LANCE_DATA, 0x7940);
+#if 0
+	printf("ISR=0x%x...",in_word(ioaddr+LANCE_DATA));
+#endif
+#define ISR_WINT 0x0200
+#define ISR_RINT 0x0400
+#define ISR_RERR 0x1000
+#define ISR_WERR 0x4000
+#define ISR_ERR  0x8000
+#define ISR_RST  0x0000
+
+        if ((isr & (ISR_WINT|ISR_RINT|ISR_RERR|ISR_WERR|ISR_ERR)) == 0x0000)
+          {
+#if 0
+	    printf("OK\n");
+#endif
+            break;
+          }
+
+        if (isr & ISR_RERR)
+          {
+#if 0
+	    printf("RERR\n");
+#endif
+            ec->eth_stat.ets_recvErr++;
+          }
+        if ((isr & ISR_WERR) || (isr & ISR_WINT))
+          {
+            if (isr & ISR_WERR)
+              {
+#if 0
+		printf("WERR\n");
+#endif
+                ec->eth_stat.ets_sendErr++;
+              }
+            if (isr & ISR_WINT)
+              {
+#if 0
+		printf("WINT\n");
+#endif
+		/* status check: restart if needed. */
+		status = lp->tx_ring[cur_tx_slot_nr].u.base;
+
+		/* ??? */
+		if (status & 0x40000000)
+		  {
+		    status = lp->tx_ring[cur_tx_slot_nr].misc;
+		    ec->eth_stat.ets_sendErr++;
+		    if (status & 0x0400)
+		      ec->eth_stat.ets_transAb++;
+		    if (status & 0x0800)
+		      ec->eth_stat.ets_carrSense++;
+		    if (status & 0x1000)
+		      ec->eth_stat.ets_OWC++;
+		    if (status & 0x4000)
+		      {
+			ec->eth_stat.ets_fifoUnder++;
+			must_restart=1;
+		      }
+		  }
+		else
+		  {
+		    if (status & 0x18000000)
+		      ec->eth_stat.ets_collision++;
+		    ec->eth_stat.ets_packetT++;
+		  }
+              }
+            /* transmit a packet on the next slot if it exists. */
+	    check = 0;
+	    if (isstored[cur_tx_slot_nr]==1)
+	      {
+		/* free the tx-slot just transmitted */
+		isstored[cur_tx_slot_nr]=0;
+		cur_tx_slot_nr = (++cur_tx_slot_nr) & TX_RING_MOD_MASK;
+		
+		/* next tx-slot is ready? */
+		if (isstored[cur_tx_slot_nr]==1)
+		  check=1;
+		else
+		  check=0;
+	      }
+	    else
+	      {
+		panic( "lance", "got premature WINT...", NO_NUM);
+	      }
+	    if (check==1)
+	      {
+		lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83;
+		out_word(ioaddr+LANCE_ADDR, 0x0000);
+		out_word(ioaddr+LANCE_DATA, 0x0048);
+	      }
+	    else
+	      if (check==-1)
+		continue;
+	    /* we set a buffered message in the slot if it exists. */
+	    /* and transmit it, if needed. */
+	    if (ec->flags & ECF_SEND_AVAIL)
+	      ec_send(ec);
+          }
+        if (isr & ISR_RINT)
+          {
+#if 0
+	    printf("RINT\n");
+#endif
+            ec_recv(ec);
+          }
+
+        if (isr & ISR_RST)
+          {
+            ec->flags = ECF_STOPPED;
+            break;
+          }
+
+        /* ??? cf. lance driver on linux */
+        if (must_restart == 1)
+          {
+#if 0
+	    printf("ETH: restarting...\n");
+#endif
+	    out_word(ioaddr+LANCE_ADDR, 0x0);
+	    (void)in_word(ioaddr+LANCE_ADDR);
+	    out_word(ioaddr+LANCE_DATA, 0x4);  /* stop */
+	    out_word(ioaddr+LANCE_DATA, 0x2);  /* start */
+          }
+      }
+    
+    if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED))
+      {
+#if 0
+	printf("ETH: resetting...\n");
+#endif
+        ec_reset(ec);
+      }
+}
+
+/*===========================================================================*
+ *                              ec_reset                                     *
+ *===========================================================================*/
+static void ec_reset(ec)
+ether_card_t *ec;
+{
+  /* Stop/start the chip, and clear all RX,TX-slots */
+  unsigned short ioaddr = ec->ec_port;
+  int i;
+  
+  out_word(ioaddr+LANCE_ADDR, 0x0);
+  (void)in_word(ioaddr+LANCE_ADDR);
+  out_word(ioaddr+LANCE_DATA, 0x4);                      /* stop */
+  out_word(ioaddr+LANCE_DATA, 0x2);                      /* start */
+  
+  /* purge Tx-ring */
+  tx_slot_nr = cur_tx_slot_nr = 0;
+  for (i=0; i<TX_RING_SIZE; i++) {
+    lp->tx_ring[i].u.base = 0;
+    isstored[i]=0;
+  }
+
+  /* re-init Rx-ring */
+  rx_slot_nr = 0;
+  for (i=0; i<RX_RING_SIZE; i++) 
+    {
+      lp->rx_ring[i].buf_length = -ETH_FRAME_LEN;
+      lp->rx_ring[i].u.addr[3] |= 0x80;
+    }
+
+  /* store a buffered message on the slot if exists */
+  ec_send(ec);
+  ec->flags &= ~ECF_STOPPED;
+}
+
+/*===========================================================================*
+ *                              ec_send                                      *
+ *===========================================================================*/
+static void ec_send(ec)
+ether_card_t *ec;
+{
+  /* from ec_check_ints() or ec_reset(). */
+  /* this function proccesses the buffered message. (slot/transmit) */
+  if (!(ec->flags & ECF_SEND_AVAIL))
+    return;
+  
+  ec->flags &= ~ECF_SEND_AVAIL;
+  switch(ec->sendmsg.m_type)
+    {
+    case DL_WRITE:  do_vwrite(&ec->sendmsg, TRUE, FALSE);       break;
+    case DL_WRITEV: do_vwrite(&ec->sendmsg, TRUE, TRUE);        break;
+    default:
+      panic( "lance", "wrong type:", ec->sendmsg.m_type);
+      break;
+    }
+}
+
+/*===========================================================================*
+ *                              do_vread                                     *
+ *===========================================================================*/
+static void do_vread(mp, vectored)
+message *mp;
+int vectored;
+{
+  int port, count, size;
+  ether_card_t *ec;
+
+  port = mp->DL_PORT;
+  count = mp->DL_COUNT;
+  ec= &ec_table[port];
+  ec->client= mp->DL_PROC;
+
+  if (vectored)
+    {
+      get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+                   (count > IOVEC_NR ? IOVEC_NR : count) *
+                   sizeof(iovec_t), ec->read_iovec.iod_iovec);
+      ec->read_iovec.iod_iovec_s    = count;
+      ec->read_iovec.iod_proc_nr    = mp->DL_PROC;
+      ec->read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
+      
+      ec->tmp_iovec = ec->read_iovec;
+      size= calc_iovec_size(&ec->tmp_iovec);
+    }
+  else
+    {
+      ec->read_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR;
+      ec->read_iovec.iod_iovec[0].iov_size = mp->DL_COUNT;
+      ec->read_iovec.iod_iovec_s           = 1;
+      ec->read_iovec.iod_proc_nr           = mp->DL_PROC;
+      ec->read_iovec.iod_iovec_addr        = 0;
+
+      size= count;
+    }
+  ec->flags |= ECF_READING;
+
+  ec_recv(ec);
+
+  if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED))
+    ec_reset(ec);
+  reply(ec, OK, FALSE);
+}
+
+/*===========================================================================*
+ *                              ec_recv                                      *
+ *===========================================================================*/
+static void ec_recv(ec)
+ether_card_t *ec;
+{
+  vir_bytes length;
+  int packet_processed;
+  int status;
+  unsigned short ioaddr = ec->ec_port;
+
+  if ((ec->flags & ECF_READING)==0)
+    return;
+  if (!(ec->flags & ECF_ENABLED))
+    return;
+
+  /* we check all the received slots until find a properly received packet */
+  packet_processed = FALSE;
+  while (!packet_processed)
+    {
+      status = lp->rx_ring[rx_slot_nr].u.base >> 24;
+      if ( (status & 0x80) == 0x00 )
+        {
+	  status = lp->rx_ring[rx_slot_nr].u.base >> 24;
+
+	  /* ??? */
+	  if (status != 0x03)
+	    {
+	      if (status & 0x01)
+		ec->eth_stat.ets_recvErr++;
+	      if (status & 0x04)
+		ec->eth_stat.ets_fifoOver++;
+	      if (status & 0x08)
+		ec->eth_stat.ets_CRCerr++;
+	      if (status & 0x10)
+		ec->eth_stat.ets_OVW++;
+	      if (status & 0x20)
+		ec->eth_stat.ets_frameAll++;
+	      length = 0;
+	    }
+	  else
+	    {
+	      ec->eth_stat.ets_packetR++;
+	      length = lp->rx_ring[rx_slot_nr].msg_length;
+	    }
+          if (length > 0)
+            {
+	      ec_nic2user(ec, (int)(lp->rbuf[rx_slot_nr]),
+			  &ec->read_iovec, 0, length);
+              
+              ec->read_s = length;
+              ec->flags |= ECF_PACK_RECV;
+              ec->flags &= ~ECF_READING;
+              packet_processed = TRUE;
+            }
+          /* set up this slot again, and we move to the next slot */
+	  lp->rx_ring[rx_slot_nr].buf_length = -ETH_FRAME_LEN;
+	  lp->rx_ring[rx_slot_nr].u.addr[3] |= 0x80;
+
+	  out_word(ioaddr+LANCE_ADDR, 0x00);
+	  out_word(ioaddr+LANCE_DATA, 0x7940);
+
+	  rx_slot_nr = (++rx_slot_nr) & RX_RING_MOD_MASK;
+        }
+      else
+        break;
+    }
+}
+
+/*===========================================================================*
+ *                              do_vwrite                                    *
+ *===========================================================================*/
+static void do_vwrite(mp, from_int, vectored)
+message *mp;
+int from_int;
+int vectored;
+{
+  int port, count, check;
+  ether_card_t *ec;
+  unsigned short ioaddr;
+
+  port = mp->DL_PORT;
+  count = mp->DL_COUNT;
+  ec = &ec_table[port];
+  ec->client= mp->DL_PROC;
+
+  if (isstored[tx_slot_nr]==1)
+    {
+      /* all slots are used, so this message is buffered */
+      ec->sendmsg= *mp;
+      ec->flags |= ECF_SEND_AVAIL;
+      reply(ec, OK, FALSE);
+      return;
+    }
+
+  /* convert the message to write_iovec */
+  if (vectored)
+    {
+      get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+                   (count > IOVEC_NR ? IOVEC_NR : count) *
+                   sizeof(iovec_t), ec->write_iovec.iod_iovec);
+
+      ec->write_iovec.iod_iovec_s    = count;
+      ec->write_iovec.iod_proc_nr    = mp->DL_PROC;
+      ec->write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
+
+      ec->tmp_iovec = ec->write_iovec;
+      ec->write_s = calc_iovec_size(&ec->tmp_iovec);
+    }
+  else
+    {  
+      ec->write_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR;
+      ec->write_iovec.iod_iovec[0].iov_size = mp->DL_COUNT;
+
+      ec->write_iovec.iod_iovec_s    = 1;
+      ec->write_iovec.iod_proc_nr    = mp->DL_PROC;
+      ec->write_iovec.iod_iovec_addr = 0;
+
+      ec->write_s = mp->DL_COUNT;
+    }
+
+  /* copy write_iovec to the slot on DMA address */
+  ec_user2nic(ec, &ec->write_iovec, 0,
+              (int)(lp->tbuf[tx_slot_nr]), ec->write_s);
+  /* set-up for transmitting, and transmit it if needed. */
+  lp->tx_ring[tx_slot_nr].buf_length = -ec->write_s;
+  lp->tx_ring[tx_slot_nr].misc = 0x0;
+  lp->tx_ring[tx_slot_nr].u.base 
+    = virt_to_bus(lp->tbuf[tx_slot_nr]) & 0xffffff;
+  isstored[tx_slot_nr]=1;
+  if (cur_tx_slot_nr == tx_slot_nr)
+    check=1;
+  else
+    check=0;
+  tx_slot_nr = (++tx_slot_nr) & TX_RING_MOD_MASK;
+
+  if (check == 1)
+    {
+      ioaddr = ec->ec_port;
+      lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83;
+      out_word(ioaddr+LANCE_ADDR, 0x0000);
+      out_word(ioaddr+LANCE_DATA, 0x0048);
+    }
+        
+  ec->flags |= ECF_PACK_SEND;
+
+  /* reply by calling do_int() if this function is called from interrupt. */
+  if (from_int)
+    return;
+  reply(ec, OK, FALSE);
+}
+
+
+/*===========================================================================*
+ *                              get_userdata                                 *
+ *===========================================================================*/
+static void get_userdata(user_proc, user_addr, count, loc_addr)
+int user_proc;
+vir_bytes user_addr;
+vir_bytes count;
+void *loc_addr;
+{
+	/*
+  phys_bytes src;
+
+  src = numap_local(user_proc, user_addr, count);
+  if (!src)
+    panic( "lance", "umap failed", NO_NUM);
+
+  phys_copy(src, vir2phys(loc_addr), (phys_bytes) count);
+  */
+	int cps;
+	cps = sys_datacopy(user_proc, user_addr, SELF, (vir_bytes) loc_addr, count);
+	if (cps != OK) printf("lance: warning, scopy failed: %d\n", cps);
+}
+
+/*===========================================================================*
+ *                              ec_user2nic                                  *
+ *===========================================================================*/
+static void ec_user2nic(ec, iovp, offset, nic_addr, count)
+ether_card_t *ec;
+iovec_dat_t *iovp;
+vir_bytes offset;
+int nic_addr;
+vir_bytes count;
+{
+  /*phys_bytes phys_hw, phys_user;*/
+  int bytes, i, r;
+
+  /*
+  phys_hw = vir2phys(nic_addr);
+  */
+  i= 0;
+  while (count > 0)
+    {
+      if (i >= IOVEC_NR)
+        {
+          ec_next_iovec(iovp);
+          i= 0;
+          continue;
+        }
+      if (offset >= iovp->iod_iovec[i].iov_size)
+        {
+          offset -= iovp->iod_iovec[i].iov_size;
+          i++;
+          continue;
+        }
+      bytes = iovp->iod_iovec[i].iov_size - offset;
+      if (bytes > count)
+        bytes = count;
+      
+      /*
+      phys_user = numap_local(iovp->iod_proc_nr,
+                        iovp->iod_iovec[i].iov_addr + offset, bytes);
+      
+      phys_copy(phys_user, phys_hw, (phys_bytes) bytes);
+      */
+      if ( (r=sys_datacopy(iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr + offset,
+      	SELF, nic_addr, count )) != OK )
+      	panic( "lance", "sys_datacopy failed", r );
+      	
+      count -= bytes;
+      nic_addr += bytes;
+      offset += bytes;
+    }
+}
+
+/*===========================================================================*
+ *                              ec_nic2user                                  *
+ *===========================================================================*/
+static void ec_nic2user(ec, nic_addr, iovp, offset, count)
+ether_card_t *ec;
+int nic_addr;
+iovec_dat_t *iovp;
+vir_bytes offset;
+vir_bytes count;
+{
+  /*phys_bytes phys_hw, phys_user;*/
+  int bytes, i, r;
+
+  /*phys_hw = vir2phys(nic_addr);*/
+
+  i= 0;
+  while (count > 0)
+    {
+      if (i >= IOVEC_NR)
+        {
+          ec_next_iovec(iovp);
+          i= 0;
+          continue;
+        }
+      if (offset >= iovp->iod_iovec[i].iov_size)
+        {
+          offset -= iovp->iod_iovec[i].iov_size;
+          i++;
+          continue;
+        }
+      bytes = iovp->iod_iovec[i].iov_size - offset;
+      if (bytes > count)
+        bytes = count;
+      /*
+      phys_user = numap_local(iovp->iod_proc_nr,
+                        iovp->iod_iovec[i].iov_addr + offset, bytes);
+
+      phys_copy(phys_hw, phys_user, (phys_bytes) bytes);
+      */
+      if ( (r=sys_datacopy( SELF, nic_addr, iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr + offset, bytes )) != OK )
+      	panic( "lance", "sys_datacopy failed: ", r );
+      
+      count -= bytes;
+      nic_addr += bytes;
+      offset += bytes;
+    }
+}
+
+
+/*===========================================================================*
+ *                              calc_iovec_size                              *
+ *===========================================================================*/
+static int calc_iovec_size(iovp)
+iovec_dat_t *iovp;
+{
+  int size,i;
+
+  size = i = 0;
+        
+  while (i < iovp->iod_iovec_s)
+    {
+      if (i >= IOVEC_NR)
+        {
+          ec_next_iovec(iovp);
+          i= 0;
+          continue;
+        }
+      size += iovp->iod_iovec[i].iov_size;
+      i++;
+    }
+
+  return size;
+}
+
+/*===========================================================================*
+ *                           ec_next_iovec                                   *
+ *===========================================================================*/
+static void ec_next_iovec(iovp)
+iovec_dat_t *iovp;
+{
+  iovp->iod_iovec_s -= IOVEC_NR;
+  iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
+
+  get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr, 
+               (iovp->iod_iovec_s > IOVEC_NR ? 
+                IOVEC_NR : iovp->iod_iovec_s) * sizeof(iovec_t), 
+               iovp->iod_iovec); 
+}
+
+
+/*===========================================================================*
+ *                              do_getstat                                   *
+ *===========================================================================*/
+static void do_getstat(mp)
+message *mp;
+{
+  int port;
+  ether_card_t *ec;
+
+  port = mp->DL_PORT;
+  if (port < 0 || port >= EC_PORT_NR_MAX)
+    panic( "lance", "illegal port", port);
+
+  ec= &ec_table[port];
+  ec->client= mp->DL_PROC;
+
+  put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+               (vir_bytes) sizeof(ec->eth_stat), &ec->eth_stat);
+  reply(ec, OK, FALSE);
+}
+
+/*===========================================================================*
+ *                              put_userdata                                 *
+ *===========================================================================*/
+static void put_userdata(user_proc, user_addr, count, loc_addr)
+int user_proc;
+vir_bytes user_addr;
+vir_bytes count;
+void *loc_addr;
+{
+  /*phys_bytes dst;
+
+  dst = numap_local(user_proc, user_addr, count);
+  if (!dst)
+    panic( "lance", "umap failed", NO_NUM);
+
+  phys_copy(vir2phys(loc_addr), dst, (phys_bytes) count);
+  */
+	int cps;
+	cps = sys_datacopy(SELF, (vir_bytes) loc_addr, user_proc, user_addr, count);
+	if (cps != OK) printf("lance: warning, scopy failed: %d\n", cps);
+}
+
+/*===========================================================================*
+ *                              do_stop                                      *
+ *===========================================================================*/
+static void do_stop(mp)
+message *mp;
+{
+  int port;
+  ether_card_t *ec;
+  unsigned short ioaddr;
+
+  port = mp->DL_PORT;
+  if (port < 0 || port >= EC_PORT_NR_MAX)
+    panic( "lance", "illegal port", port);
+  ec = &ec_table[port];
+
+  if (!(ec->flags & ECF_ENABLED))
+    return;
+
+  ioaddr = ec->ec_port;
+  
+  out_word(ioaddr+LANCE_ADDR, 0x0);
+  (void)in_word(ioaddr+LANCE_ADDR);
+  out_word(ioaddr+LANCE_DATA, 0x4);                          /* stop */
+  out_word(ioaddr+LANCE_RESET, in_word(ioaddr+LANCE_RESET)); /* reset */
+
+  ec->flags = ECF_EMPTY;
+}
+
+static void getAddressing(devind, ec)
+int devind;
+ether_card_t *ec;
+{
+	unsigned int      membase, ioaddr;
+	int reg, irq;
+
+	for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4)
+	{
+          ioaddr = pci_attr_r32(devind, reg);
+
+          if ((ioaddr & PCI_BASE_ADDRESS_IO_MASK) == 0 
+              || (ioaddr & PCI_BASE_ADDRESS_SPACE_IO) == 0)
+            continue;
+          /* Strip the I/O address out of the returned value */
+          ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
+          /* Get the memory base address */
+          membase = pci_attr_r32(devind, PCI_BASE_ADDRESS_1);
+          /* KK: Get the IRQ number */
+          irq = pci_attr_r8(devind, PCI_INTERRUPT_PIN);
+          if (irq)
+            irq = pci_attr_r8(devind, PCI_INTERRUPT_LINE);
+          /* Get the ROM base address */
+          /*pci_attr_r32(devind, PCI_ROM_ADDRESS, &romaddr);
+          romaddr >>= 10;*/
+          /* Take the first one or the one that matches in boot ROM address */
+          /*if (pci_ioaddr == 0 
+              || romaddr == ((unsigned long) rom.rom_segment << 4)) {*/
+            ec->ec_linmem = membase;
+            ec->ec_port = ioaddr;
+            ec->ec_irq = irq;
+          /*}*/
+	}
+}
+
+/*===========================================================================*
+ *                            lance_probe                                    *
+ *===========================================================================*/
+static int lance_probe(ec)
+ether_card_t *ec;
+{
+  unsigned short    pci_cmd, attached = 0;
+  unsigned short    ioaddr;
+  int               lance_version, chip_version;
+	int devind, just_one, i, r;
+	
+	u16_t vid, did;
+	u32_t bar;
+	u8_t ilr;
+	char *dname;
+
+	if ((ec->ec_pcibus | ec->ec_pcidev | ec->ec_pcifunc) != 0)
+	{
+		/* Look for specific PCI device */
+		r= pci_find_dev(ec->ec_pcibus, ec->ec_pcidev,
+			ec->ec_pcifunc, &devind);
+		if (r == 0)
+		{
+			printf("%s: no PCI found at %d.%d.%d\n",
+				ec->port_name, ec->ec_pcibus,
+				ec->ec_pcidev, ec->ec_pcifunc);
+			return 0;
+		}
+		pci_ids(devind, &vid, &did);
+		just_one= TRUE;
+	}
+	else
+	{
+		r= pci_first_dev(&devind, &vid, &did);
+		if (r == 0)
+			return 0;
+		just_one= FALSE;
+	}
+
+	for(;;)
+	{
+		for (i= 0; pcitab[i].vid != 0; i++)
+		{
+			if (pcitab[i].vid != vid)
+				continue;
+			if (pcitab[i].did != did)
+				continue;
+			if (pcitab[i].checkclass)
+			{
+			  panic("lance",
+			    "class check not implemented", NO_NUM);
+			}
+			break;
+		}
+		if (pcitab[i].vid != 0)
+			break;
+
+		if (just_one)
+		{
+			printf(
+		"%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
+				ec->port_name, vid, did,
+				ec->ec_pcibus,
+				ec->ec_pcidev, ec->ec_pcifunc);
+			return 0;
+		}
+
+		r= pci_next_dev(&devind, &vid, &did);
+		if (!r)
+			return 0;
+	}
+
+	dname= pci_dev_name(vid, did);
+	if (!dname)
+		dname= "unknown device";
+	
+	/*
+	printf("%s: ", ec->port_name);
+	printf("%s ", dname);
+	printf("(%x/", vid);
+	printf("%x) ", did);
+	printf("at %s\n", pci_slot_name(devind));
+	*/
+	pci_reserve(devind);	
+	
+/*  for (i = 0; pci_dev_list[i].vendor != 0; i++) {
+    if (pci_dev_list[i].suffix == 1)
+      {
+	ec->ec_port   = pci_dev_list[i].ioaddr;
+	ec->ec_irq    = pci_dev_list[i].irq;
+	ec->ec_linmem = pci_dev_list[i].membase;
+	ec->ec_bus    = pci_dev_list[i].bus;
+	ec->ec_dev    = pci_dev_list[i].devfn;
+	ec->ec_fnc    =
+	pci_dev_list[i].suffix = -1;
+	attached = 1;
+	break;
+      }
+  }
+  if (attached == 0)
+    return 0; 
+*/
+	getAddressing(devind, ec);
+
+  /* ===== Bus Master ? ===== */
+  /*pcibios_read_config_word(ec->ec_bus, ec->ec_devfn, PCI_COMMAND, &pci_cmd);*/
+  pci_cmd = pci_attr_r32(devind, PCI_CR);
+  if (!(pci_cmd & PCI_COMMAND_MASTER)) {
+    pci_cmd |= PCI_COMMAND_MASTER;
+    /*pcibios_write_config_word(ec->ec_bus, ec->ec_devfn, PCI_COMMAND, pci_cmd);*/
+    pci_attr_w32(devind, PCI_CR, pci_cmd);
+  }
+
+  /* ===== Probe Details ===== */
+  ioaddr = ec->ec_port;
+
+  out_word(ioaddr+LANCE_RESET, in_word(ioaddr+LANCE_RESET)); /* Reset */
+  out_word(ioaddr+LANCE_ADDR, 0x0);                          /* Sw to win 0 */
+  if (in_word(ioaddr+LANCE_DATA) != 0x4)
+    {
+      ec->mode=EC_DISABLED;
+    }
+  /* Probe Chip Version */
+  out_word(ioaddr+LANCE_ADDR, 88);     /* Get the version of the chip */
+  if (in_word(ioaddr+LANCE_ADDR) != 88)
+    lance_version = 0;
+  else
+    {
+      chip_version = in_word(ioaddr+LANCE_DATA);
+      out_word(ioaddr+LANCE_ADDR, 89);
+      chip_version |= in_word(ioaddr+LANCE_DATA) << 16;
+      if ((chip_version & 0xfff) != 0x3)
+        {
+          ec->mode=EC_DISABLED;
+        }
+      chip_version = (chip_version >> 12) & 0xffff;
+      for (lance_version = 1; chip_table[lance_version].id_number != 0;
+           ++lance_version)
+        if (chip_table[lance_version].id_number == chip_version)
+          break;
+    }
+
+#if 0
+  printf("%s: %s at %X:%d\n",
+	 ec->port_name, chip_table[lance_version].name,
+	 ec->ec_port, ec->ec_irq);
+#endif
+
+  return lance_version;
+}
+
+/*===========================================================================*
+ *				do_getname				     *
+ *===========================================================================*/
+static void do_getname(mp)
+message *mp;
+{
+	int r;
+
+	strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
+	mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
+	mp->m_type= DL_NAME_REPLY;
+	r= send(mp->m_source, mp);
+	if (r != OK)
+		panic("LANCE", "do_getname: send failed", r);
+}
+
+/*===========================================================================*
+ *                            lance_init_card                                *
+ *===========================================================================*/
+static void lance_init_card(ec)
+ether_card_t *ec;
+{
+  int i;
+  Address l;
+  unsigned short ioaddr = ec->ec_port;
+
+  /* ============= setup init_block(cf. lance_probe1) ================ */
+  /* make sure data structure is 8-byte aligned */
+  l = ((Address)lance + 7) & ~7;
+  lp = (struct lance_interface *)l;
+  lp->init_block.mode = 0x3;      /* disable Rx and Tx */
+  lp->init_block.filter[0] = lp->init_block.filter[1] = 0x0;
+  /* using multiple Rx/Tx buffer */
+  lp->init_block.rx_ring 
+    = (virt_to_bus(&lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
+  lp->init_block.tx_ring 
+    = (virt_to_bus(&lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;
+
+  l = virt_to_bus(&lp->init_block);
+  out_word(ioaddr+LANCE_ADDR, 0x1); 
+  (void)in_word(ioaddr+LANCE_ADDR);
+  out_word(ioaddr+LANCE_DATA, (unsigned short)l);
+  out_word(ioaddr+LANCE_ADDR, 0x2);
+  (void)in_word(ioaddr+LANCE_ADDR);
+  out_word(ioaddr+LANCE_DATA, (unsigned short)(l >> 16));
+  out_word(ioaddr+LANCE_ADDR, 0x4);
+  (void)in_word(ioaddr+LANCE_ADDR);
+  out_word(ioaddr+LANCE_DATA, 0x915);
+  out_word(ioaddr+LANCE_ADDR, 0x0);
+  (void)in_word(ioaddr+LANCE_ADDR);
+
+  /* ============= Get MAC address (cf. lance_probe1) ================ */
+  for (i = 0; i < 6; ++i)
+    ec->mac_address.ea_addr[i]=in_byte(ioaddr+LANCE_ETH_ADDR+i);
+
+  /* ============ (re)start init_block(cf. lance_reset) =============== */
+  /* Reset the LANCE */
+  (void)in_word(ioaddr+LANCE_RESET);
+
+  /* ----- Re-initialize the LANCE ----- */
+  /* Set station address */
+  for (i = 0; i < 6; ++i)
+    lp->init_block.phys_addr[i] = ec->mac_address.ea_addr[i];
+  /* Preset the receive ring headers */
+  for (i=0; i<RX_RING_SIZE; i++) {
+    lp->rx_ring[i].buf_length = -ETH_FRAME_LEN;
+    /* OWN */
+    lp->rx_ring[i].u.base = virt_to_bus(lp->rbuf[i]) & 0xffffff;
+    /* we set the top byte as the very last thing */
+    lp->rx_ring[i].u.addr[3] = 0x80;
+  }
+  /* Preset the transmitting ring headers */
+  for (i=0; i<TX_RING_SIZE; i++) {
+    lp->tx_ring[i].u.base = 0;
+    isstored[i] = 0;
+  }
+  lp->init_block.mode = 0x0;      /* enable Rx and Tx */
+
+  l = (Address)virt_to_bus(&lp->init_block);
+  out_word(ioaddr+LANCE_ADDR, 0x1);
+  (void)in_word(ioaddr+LANCE_ADDR);
+  out_word(ioaddr+LANCE_DATA, (short)l);
+  out_word(ioaddr+LANCE_ADDR, 0x2);
+  (void)in_word(ioaddr+LANCE_ADDR);
+  out_word(ioaddr+LANCE_DATA, (short)(l >> 16));
+  out_word(ioaddr+LANCE_ADDR, 0x4);
+  (void)in_word(ioaddr+LANCE_ADDR);
+  out_word(ioaddr+LANCE_DATA, 0x915);
+  out_word(ioaddr+LANCE_ADDR, 0x0);
+  (void)in_word(ioaddr+LANCE_ADDR);
+
+  /* ----- start when init done. ----- */
+  out_word(ioaddr+LANCE_DATA, 0x4);           /* stop */
+  out_word(ioaddr+LANCE_DATA, 0x1);           /* init */
+  for (i = 10000; i > 0; --i)
+    if (in_word(ioaddr+LANCE_DATA) & 0x100)
+      break;
+
+  /* Set 'Multicast Table' */
+  for (i=0;i<4;++i)
+    {
+      out_word(ioaddr+LANCE_ADDR, 0x8 + i);
+      out_word(ioaddr+LANCE_DATA, 0xffff);
+    }
+
+  /* Set 'Receive Mode' */
+  if (ec->flags & ECF_PROMISC)
+    {
+      out_word(ioaddr+LANCE_ADDR, 0xf);
+      out_word(ioaddr+LANCE_DATA, 0x8000);
+    }
+  else
+    {
+      if (ec->flags & (ECF_BROAD | ECF_MULTI))
+        {
+          out_word(ioaddr+LANCE_ADDR, 0xf);
+          out_word(ioaddr+LANCE_DATA, 0x0000);
+        }
+      else
+        {
+          out_word(ioaddr+LANCE_ADDR, 0xf);
+          out_word(ioaddr+LANCE_DATA, 0x4000);
+        }
+    }
+  
+  out_word(ioaddr+LANCE_ADDR, 0x0);
+  (void)in_word(ioaddr+LANCE_ADDR);
+  out_word(ioaddr+LANCE_DATA, 0x142);   /* start && enable interrupt */
+
+  return;
+}
Index: /trunk/minix/drivers/lance/lance.h
===================================================================
--- /trunk/minix/drivers/lance/lance.h	(revision 9)
+++ /trunk/minix/drivers/lance/lance.h	(revision 9)
@@ -0,0 +1,103 @@
+/*#include "kernel.h"*/
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+
+/* PCI STUFF */
+#define PCI_BASE_ADDRESS_0		0x10
+#define PCI_BASE_ADDRESS_1		0x14
+#define PCI_BASE_ADDRESS_2		0x18
+#define PCI_BASE_ADDRESS_3		0x1c
+#define PCI_BASE_ADDRESS_4		0x20
+#define PCI_BASE_ADDRESS_5		0x24
+
+#define PCI_BASE_ADDRESS_IO_MASK	(~0x03)
+#define PCI_BASE_ADDRESS_SPACE_IO	0x01
+#define PCI_INTERRUPT_LINE		0x3c
+#define PCI_INTERRUPT_PIN		0x3d
+
+#define PCI_COMMAND_MASTER		0x4
+
+#define PCI_VENDOR_ID_AMD	0x1022
+#define PCI_DEVICE_ID_AMD_LANCE	0x2000
+
+
+/* supported max number of ether cards */
+#define EC_PORT_NR_MAX 2
+
+/* macros for 'mode' */
+#define EC_DISABLED    0x0
+#define EC_SINK        0x1
+#define EC_ENABLED     0x2
+
+/* macros for 'flags' */
+#define ECF_EMPTY       0x000
+#define ECF_PACK_SEND   0x001
+#define ECF_PACK_RECV   0x002
+#define ECF_SEND_AVAIL  0x004
+#define ECF_READING     0x010
+#define ECF_PROMISC     0x040
+#define ECF_MULTI       0x080
+#define ECF_BROAD       0x100
+#define ECF_ENABLED     0x200
+#define ECF_STOPPED     0x400
+
+/* === macros for ether cards (our generalized version) === */
+#define EC_ISR_RINT     0x0001
+#define EC_ISR_WINT     0x0002
+#define EC_ISR_RERR     0x0010
+#define EC_ISR_WERR     0x0020
+#define EC_ISR_ERR      0x0040
+#define EC_ISR_RST      0x0100
+
+/* IOVEC */
+#define IOVEC_NR        16
+typedef struct iovec_dat
+{
+  iovec_t iod_iovec[IOVEC_NR];
+  int iod_iovec_s;
+  int iod_proc_nr;
+  vir_bytes iod_iovec_addr;
+} iovec_dat_t;
+
+#define ETH0_SELECTOR  0x61
+#define ETH1_SELECTOR  0x69
+
+/* ====== ethernet card info. ====== */
+typedef struct ether_card
+{
+  /* ####### MINIX style ####### */
+  char port_name[sizeof("eth_card#n")];
+  int flags;
+  int mode;
+  int transfer_mode;
+  eth_stat_t eth_stat;
+  iovec_dat_t read_iovec;
+  iovec_dat_t write_iovec;
+  iovec_dat_t tmp_iovec;
+  vir_bytes write_s;
+  vir_bytes read_s;
+  int client;
+  message sendmsg;
+
+  /* ######## device info. ####### */
+  port_t ec_port;
+  phys_bytes ec_linmem;
+  int ec_irq;
+  int ec_int_pending;
+  int ec_hook;
+
+  int ec_ramsize;
+  /* PCI */
+  u8_t ec_pcibus;	
+  u8_t ec_pcidev;	
+  u8_t ec_pcifunc;	
+ 
+  /* Addrassing */
+  u16_t ec_memseg;
+  vir_bytes ec_memoff;
+  
+  ether_addr_t mac_address;
+} ether_card_t;
+
+#define DEI_DEFAULT    0x8000
+
Index: /trunk/minix/drivers/libdriver/.depend
===================================================================
--- /trunk/minix/drivers/libdriver/.depend	(revision 9)
+++ /trunk/minix/drivers/libdriver/.depend	(revision 9)
@@ -0,0 +1,58 @@
+
+driver.o:	../drivers.h
+driver.o:	/usr/include/ansi.h
+driver.o:	/usr/include/errno.h
+driver.o:	/usr/include/ibm/bios.h
+driver.o:	/usr/include/ibm/interrupt.h
+driver.o:	/usr/include/ibm/ports.h
+driver.o:	/usr/include/limits.h
+driver.o:	/usr/include/minix/bitmap.h
+driver.o:	/usr/include/minix/callnr.h
+driver.o:	/usr/include/minix/com.h
+driver.o:	/usr/include/minix/config.h
+driver.o:	/usr/include/minix/const.h
+driver.o:	/usr/include/minix/devio.h
+driver.o:	/usr/include/minix/dmap.h
+driver.o:	/usr/include/minix/ioctl.h
+driver.o:	/usr/include/minix/ipc.h
+driver.o:	/usr/include/minix/partition.h
+driver.o:	/usr/include/minix/sys_config.h
+driver.o:	/usr/include/minix/syslib.h
+driver.o:	/usr/include/minix/sysutil.h
+driver.o:	/usr/include/minix/type.h
+driver.o:	/usr/include/minix/u64.h
+driver.o:	/usr/include/signal.h
+driver.o:	/usr/include/stddef.h
+driver.o:	/usr/include/stdlib.h
+driver.o:	/usr/include/string.h
+driver.o:	/usr/include/sys/dir.h
+driver.o:	/usr/include/sys/ioc_disk.h
+driver.o:	/usr/include/sys/types.h
+driver.o:	/usr/include/unistd.h
+driver.o:	driver.c
+driver.o:	driver.h
+
+drvlib.o:	/usr/include/ansi.h
+drvlib.o:	/usr/include/errno.h
+drvlib.o:	/usr/include/ibm/partition.h
+drvlib.o:	/usr/include/limits.h
+drvlib.o:	/usr/include/minix/callnr.h
+drvlib.o:	/usr/include/minix/com.h
+drvlib.o:	/usr/include/minix/config.h
+drvlib.o:	/usr/include/minix/const.h
+drvlib.o:	/usr/include/minix/devio.h
+drvlib.o:	/usr/include/minix/ipc.h
+drvlib.o:	/usr/include/minix/partition.h
+drvlib.o:	/usr/include/minix/sys_config.h
+drvlib.o:	/usr/include/minix/syslib.h
+drvlib.o:	/usr/include/minix/sysutil.h
+drvlib.o:	/usr/include/minix/type.h
+drvlib.o:	/usr/include/minix/u64.h
+drvlib.o:	/usr/include/stddef.h
+drvlib.o:	/usr/include/string.h
+drvlib.o:	/usr/include/sys/dir.h
+drvlib.o:	/usr/include/sys/types.h
+drvlib.o:	/usr/include/unistd.h
+drvlib.o:	driver.h
+drvlib.o:	drvlib.c
+drvlib.o:	drvlib.h
Index: /trunk/minix/drivers/libdriver/Makefile
===================================================================
--- /trunk/minix/drivers/libdriver/Makefile	(revision 9)
+++ /trunk/minix/drivers/libdriver/Makefile	(revision 9)
@@ -0,0 +1,30 @@
+# Makefile for driver library
+
+# Directories
+u = /usr
+i = $u/include
+s = $i/sys
+b = $i/ibm
+m = $i/minix
+
+# Programs, flags, etc.
+CC = exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsysutil -lsys
+
+OBJECTS = driver.o drvlib.o
+
+all build install: $(OBJECTS)	
+
+# $(CC) -c $@ $(LDFLAGS) $(OBJ) $(LIBS)
+
+clean:
+	rm -f *.o *.bak 
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/libdriver/driver.c
===================================================================
--- /trunk/minix/drivers/libdriver/driver.c	(revision 9)
+++ /trunk/minix/drivers/libdriver/driver.c	(revision 9)
@@ -0,0 +1,376 @@
+/* This file contains device independent device driver interface.
+ *
+ * Changes:
+ *   Jul 25, 2005   added SYS_SIG type for signals  (Jorrit N. Herder)
+ *   Sep 15, 2004   added SYN_ALARM type for timeouts  (Jorrit N. Herder)
+ *   Jul 23, 2004   removed kernel dependencies  (Jorrit N. Herder)
+ *   Apr 02, 1992   constructed from AT wini and floppy driver  (Kees J. Bot)
+ *
+ *
+ * The drivers support the following operations (using message format m2):
+ *
+ *    m_type      DEVICE    IO_ENDPT    COUNT    POSITION  ADRRESS
+ * ----------------------------------------------------------------
+ * |  DEV_OPEN  | device  | proc nr |         |         |         |
+ * |------------+---------+---------+---------+---------+---------|
+ * |  DEV_CLOSE | device  | proc nr |         |         |         |
+ * |------------+---------+---------+---------+---------+---------|
+ * |  DEV_READ  | device  | proc nr |  bytes  |  offset | buf ptr |
+ * |------------+---------+---------+---------+---------+---------|
+ * |  DEV_WRITE | device  | proc nr |  bytes  |  offset | buf ptr |
+ * |------------+---------+---------+---------+---------+---------|
+ * | DEV_GATHER | device  | proc nr | iov len |  offset | iov ptr |
+ * |------------+---------+---------+---------+---------+---------|
+ * | DEV_SCATTER| device  | proc nr | iov len |  offset | iov ptr |
+ * |------------+---------+---------+---------+---------+---------|
+ * |  DEV_IOCTL | device  | proc nr |func code|         | buf ptr |
+ * |------------+---------+---------+---------+---------+---------|
+ * |  CANCEL    | device  | proc nr | r/w     |         |         |
+ * |------------+---------+---------+---------+---------+---------|
+ * |  HARD_STOP |         |         |         |         |         |
+ * ----------------------------------------------------------------
+ *
+ * The file contains one entry point:
+ *
+ *   driver_task:	called by the device dependent task entry
+ */
+
+#include "../drivers.h"
+#include <sys/ioc_disk.h>
+#include "driver.h"
+
+#if (CHIP == INTEL)
+
+#if USE_EXTRA_DMA_BUF && DMA_BUF_SIZE < 2048
+/* A bit extra scratch for the Adaptec driver. */
+#define BUF_EXTRA	(2048 - DMA_BUF_SIZE)
+#else
+#define BUF_EXTRA	0
+#endif
+
+/* Claim space for variables. */
+PRIVATE u8_t buffer[(unsigned) 2 * DMA_BUF_SIZE + BUF_EXTRA];
+u8_t *tmp_buf;			/* the DMA buffer eventually */
+phys_bytes tmp_phys;		/* phys address of DMA buffer */
+
+#else /* CHIP != INTEL */
+
+/* Claim space for variables. */
+u8_t tmp_buf[DMA_BUF_SIZE];	/* the DMA buffer */
+phys_bytes tmp_phys;		/* phys address of DMA buffer */
+
+#endif /* CHIP != INTEL */
+
+FORWARD _PROTOTYPE( void init_buffer, (void) );
+FORWARD _PROTOTYPE( int do_rdwt, (struct driver *dr, message *mp) );
+FORWARD _PROTOTYPE( int do_vrdwt, (struct driver *dr, message *mp) );
+
+int device_caller;
+
+/*===========================================================================*
+ *				driver_task				     *
+ *===========================================================================*/
+PUBLIC void driver_task(dp)
+struct driver *dp;	/* Device dependent entry points. */
+{
+/* Main program of any device driver task. */
+
+  int r, proc_nr;
+  message mess;
+
+  /* Get a DMA buffer. */
+  init_buffer();
+
+  /* Here is the main loop of the disk task.  It waits for a message, carries
+   * it out, and sends a reply.
+   */
+  while (TRUE) {
+
+	/* Wait for a request to read or write a disk block. */
+	if (receive(ANY, &mess) != OK) continue;
+
+	device_caller = mess.m_source;
+	proc_nr = mess.IO_ENDPT;
+
+	/* Now carry out the work. */
+	switch(mess.m_type) {
+	case DEV_OPEN:		r = (*dp->dr_open)(dp, &mess);	break;	
+	case DEV_CLOSE:		r = (*dp->dr_close)(dp, &mess);	break;
+	case DEV_IOCTL:		r = (*dp->dr_ioctl)(dp, &mess);	break;
+	case CANCEL:		r = (*dp->dr_cancel)(dp, &mess);break;
+	case DEV_SELECT:	r = (*dp->dr_select)(dp, &mess);break;
+	case DEV_READ:	
+	case DEV_WRITE:	  	r = do_rdwt(dp, &mess);	break;
+	case DEV_GATHER: 
+	case DEV_SCATTER: 	r = do_vrdwt(dp, &mess);	break;
+
+	case HARD_INT:		/* leftover interrupt or expired timer. */
+				if(dp->dr_hw_int) {
+					(*dp->dr_hw_int)(dp, &mess);
+				}
+				continue;
+	case PROC_EVENT:
+	case SYS_SIG:		(*dp->dr_signal)(dp, &mess);
+				continue;	/* don't reply */
+	case SYN_ALARM:		(*dp->dr_alarm)(dp, &mess);	
+				continue;	/* don't reply */
+	case DEV_PING:		notify(mess.m_source);
+				continue;
+	default:		
+		if(dp->dr_other)
+			r = (*dp->dr_other)(dp, &mess);
+		else	
+			r = EINVAL;
+		break;
+	}
+
+	/* Clean up leftover state. */
+	(*dp->dr_cleanup)();
+
+	/* Finally, prepare and send the reply message. */
+	if (r != EDONTREPLY) {
+		mess.m_type = TASK_REPLY;
+		mess.REP_ENDPT = proc_nr;
+		/* Status is # of bytes transferred or error code. */
+		mess.REP_STATUS = r;	
+		send(device_caller, &mess);
+	}
+  }
+}
+
+
+/*===========================================================================*
+ *				init_buffer				     *
+ *===========================================================================*/
+PRIVATE void init_buffer()
+{
+/* Select a buffer that can safely be used for DMA transfers.  It may also
+ * be used to read partition tables and such.  Its absolute address is
+ * 'tmp_phys', the normal address is 'tmp_buf'.
+ */
+
+#if (CHIP == INTEL)
+  unsigned left;
+
+  tmp_buf = buffer;
+  sys_umap(SELF, D, (vir_bytes)buffer, (phys_bytes)sizeof(buffer), &tmp_phys);
+
+  if ((left = dma_bytes_left(tmp_phys)) < DMA_BUF_SIZE) {
+	/* First half of buffer crosses a 64K boundary, can't DMA into that */
+	tmp_buf += left;
+	tmp_phys += left;
+  }
+#endif /* CHIP == INTEL */
+}
+
+/*===========================================================================*
+ *				do_rdwt					     *
+ *===========================================================================*/
+PRIVATE int do_rdwt(dp, mp)
+struct driver *dp;		/* device dependent entry points */
+message *mp;			/* pointer to read or write message */
+{
+/* Carry out a single read or write request. */
+  iovec_t iovec1;
+  int r, opcode;
+  phys_bytes phys_addr;
+
+  /* Disk address?  Address and length of the user buffer? */
+  if (mp->COUNT < 0) return(EINVAL);
+
+  /* Check the user buffer. */
+  sys_umap(mp->IO_ENDPT, D, (vir_bytes) mp->ADDRESS, mp->COUNT, &phys_addr);
+  if (phys_addr == 0) return(EFAULT);
+
+  /* Prepare for I/O. */
+  if ((*dp->dr_prepare)(mp->DEVICE) == NIL_DEV) return(ENXIO);
+
+  /* Create a one element scatter/gather vector for the buffer. */
+  opcode = mp->m_type == DEV_READ ? DEV_GATHER : DEV_SCATTER;
+  iovec1.iov_addr = (vir_bytes) mp->ADDRESS;
+  iovec1.iov_size = mp->COUNT;
+
+  /* Transfer bytes from/to the device. */
+  r = (*dp->dr_transfer)(mp->IO_ENDPT, opcode, mp->POSITION, &iovec1, 1);
+
+  /* Return the number of bytes transferred or an error code. */
+  return(r == OK ? (mp->COUNT - iovec1.iov_size) : r);
+}
+
+/*==========================================================================*
+ *				do_vrdwt				    *
+ *==========================================================================*/
+PRIVATE int do_vrdwt(dp, mp)
+struct driver *dp;	/* device dependent entry points */
+message *mp;		/* pointer to read or write message */
+{
+/* Carry out an device read or write to/from a vector of user addresses.
+ * The "user addresses" are assumed to be safe, i.e. FS transferring to/from
+ * its own buffers, so they are not checked.
+ */
+  static iovec_t iovec[NR_IOREQS];
+  iovec_t *iov;
+  phys_bytes iovec_size;
+  unsigned nr_req;
+  int r;
+
+  nr_req = mp->COUNT;	/* Length of I/O vector */
+
+#if 0
+  if (mp->m_source < 0) {
+    /* Called by a task, no need to copy vector. */
+    iov = (iovec_t *) mp->ADDRESS;
+  } else
+#endif
+  {
+    /* Copy the vector from the caller to kernel space. */
+    if (nr_req > NR_IOREQS) nr_req = NR_IOREQS;
+    iovec_size = (phys_bytes) (nr_req * sizeof(iovec[0]));
+
+    if (OK != sys_datacopy(mp->m_source, (vir_bytes) mp->ADDRESS, 
+    		SELF, (vir_bytes) iovec, iovec_size))
+        panic((*dp->dr_name)(),"bad I/O vector by", mp->m_source);
+    iov = iovec;
+  }
+
+  /* Prepare for I/O. */
+  if ((*dp->dr_prepare)(mp->DEVICE) == NIL_DEV) return(ENXIO);
+
+  /* Transfer bytes from/to the device. */
+  r = (*dp->dr_transfer)(mp->IO_ENDPT, mp->m_type, mp->POSITION, iov, nr_req);
+
+  /* Copy the I/O vector back to the caller. */
+#if 0
+  if (mp->m_source >= 0) {
+#endif
+    sys_datacopy(SELF, (vir_bytes) iovec, 
+    	mp->m_source, (vir_bytes) mp->ADDRESS, iovec_size);
+  return(r);
+}
+
+/*===========================================================================*
+ *				no_name					     *
+ *===========================================================================*/
+PUBLIC char *no_name()
+{
+/* Use this default name if there is no specific name for the device. This was
+ * originally done by fetching the name from the task table for this process: 
+ * "return(tasktab[proc_number(proc_ptr) + NR_TASKS].name);", but currently a
+ * real "noname" is returned. Perhaps, some system information service can be
+ * queried for a name at a later time.
+ */
+  static char name[] = "noname";
+  return name;
+}
+
+/*============================================================================*
+ *				do_nop					      *
+ *============================================================================*/
+PUBLIC int do_nop(dp, mp)
+struct driver *dp;
+message *mp;
+{
+/* Nothing there, or nothing to do. */
+
+  switch (mp->m_type) {
+  case DEV_OPEN:	return(ENODEV);
+  case DEV_CLOSE:	return(OK);
+  case DEV_IOCTL:	return(ENOTTY);
+  default:		return(EIO);
+  }
+}
+
+/*============================================================================*
+ *				nop_signal			  	      *
+ *============================================================================*/
+PUBLIC void nop_signal(dp, mp)
+struct driver *dp;
+message *mp;
+{
+/* Default action for signal is to ignore. */
+}
+
+/*============================================================================*
+ *				nop_alarm				      *
+ *============================================================================*/
+PUBLIC void nop_alarm(dp, mp)
+struct driver *dp;
+message *mp;
+{
+/* Ignore the leftover alarm. */
+}
+
+/*===========================================================================*
+ *				nop_prepare				     *
+ *===========================================================================*/
+PUBLIC struct device *nop_prepare(device)
+{
+/* Nothing to prepare for. */
+  return(NIL_DEV);
+}
+
+/*===========================================================================*
+ *				nop_cleanup				     *
+ *===========================================================================*/
+PUBLIC void nop_cleanup()
+{
+/* Nothing to clean up. */
+}
+
+/*===========================================================================*
+ *				nop_cancel				     *
+ *===========================================================================*/
+PUBLIC int nop_cancel(struct driver *dr, message *m)
+{
+/* Nothing to do for cancel. */
+   return(OK);
+}
+
+/*===========================================================================*
+ *				nop_select				     *
+ *===========================================================================*/
+PUBLIC int nop_select(struct driver *dr, message *m)
+{
+/* Nothing to do for select. */
+   return(OK);
+}
+
+/*============================================================================*
+ *				do_diocntl				      *
+ *============================================================================*/
+PUBLIC int do_diocntl(dp, mp)
+struct driver *dp;
+message *mp;			/* pointer to ioctl request */
+{
+/* Carry out a partition setting/getting request. */
+  struct device *dv;
+  struct partition entry;
+  int s;
+
+  if (mp->REQUEST != DIOCSETP && mp->REQUEST != DIOCGETP) {
+  	if(dp->dr_other) {
+  		return dp->dr_other(dp, mp);
+  	} else return(ENOTTY);
+  }
+
+  /* Decode the message parameters. */
+  if ((dv = (*dp->dr_prepare)(mp->DEVICE)) == NIL_DEV) return(ENXIO);
+
+  if (mp->REQUEST == DIOCSETP) {
+	/* Copy just this one partition table entry. */
+	if (OK != (s=sys_datacopy(mp->IO_ENDPT, (vir_bytes) mp->ADDRESS,
+		SELF, (vir_bytes) &entry, sizeof(entry))))
+	    return s;
+	dv->dv_base = entry.base;
+	dv->dv_size = entry.size;
+  } else {
+	/* Return a partition table entry and the geometry of the drive. */
+	entry.base = dv->dv_base;
+	entry.size = dv->dv_size;
+	(*dp->dr_geometry)(&entry);
+	if (OK != (s=sys_datacopy(SELF, (vir_bytes) &entry,
+		mp->IO_ENDPT, (vir_bytes) mp->ADDRESS, sizeof(entry))))
+	    return s;
+  }
+  return(OK);
+}
Index: /trunk/minix/drivers/libdriver/driver.h
===================================================================
--- /trunk/minix/drivers/libdriver/driver.h	(revision 9)
+++ /trunk/minix/drivers/libdriver/driver.h	(revision 9)
@@ -0,0 +1,91 @@
+/* Types and constants shared between the generic and device dependent
+ * device driver code.
+ */
+
+#define _POSIX_SOURCE      1	/* tell headers to include POSIX stuff */
+#define _MINIX             1	/* tell headers to include MINIX stuff */
+#define _SYSTEM		   1	/* get negative error number in <errno.h> */
+
+/* The following are so basic, all the *.c files get them automatically. */
+#include <minix/config.h>	/* MUST be first */
+#include <ansi.h>		/* MUST be second */
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/com.h>
+#include <minix/callnr.h>
+#include <sys/types.h>
+#include <minix/const.h>
+#include <minix/syslib.h>
+#include <minix/sysutil.h>
+
+#include <string.h>
+#include <limits.h>
+#include <stddef.h>
+#include <errno.h>
+
+#include <minix/partition.h>
+#include <minix/u64.h>
+
+/* Info about and entry points into the device dependent code. */
+struct driver {
+  _PROTOTYPE( char *(*dr_name), (void) );
+  _PROTOTYPE( int (*dr_open), (struct driver *dp, message *m_ptr) );
+  _PROTOTYPE( int (*dr_close), (struct driver *dp, message *m_ptr) );
+  _PROTOTYPE( int (*dr_ioctl), (struct driver *dp, message *m_ptr) );
+  _PROTOTYPE( struct device *(*dr_prepare), (int device) );
+  _PROTOTYPE( int (*dr_transfer), (int proc_nr, int opcode, off_t position,
+					iovec_t *iov, unsigned nr_req) );
+  _PROTOTYPE( void (*dr_cleanup), (void) );
+  _PROTOTYPE( void (*dr_geometry), (struct partition *entry) );
+  _PROTOTYPE( void (*dr_signal), (struct driver *dp, message *m_ptr) );
+  _PROTOTYPE( void (*dr_alarm), (struct driver *dp, message *m_ptr) );
+  _PROTOTYPE( int (*dr_cancel), (struct driver *dp, message *m_ptr) );
+  _PROTOTYPE( int (*dr_select), (struct driver *dp, message *m_ptr) );
+  _PROTOTYPE( int (*dr_other), (struct driver *dp, message *m_ptr) );
+  _PROTOTYPE( int (*dr_hw_int), (struct driver *dp, message *m_ptr) );
+};
+
+#if (CHIP == INTEL)
+
+/* Number of bytes you can DMA before hitting a 64K boundary: */
+#define dma_bytes_left(phys)    \
+   ((unsigned) (sizeof(int) == 2 ? 0 : 0x10000) - (unsigned) ((phys) & 0xFFFF))
+
+#endif /* CHIP == INTEL */
+
+/* Base and size of a partition in bytes. */
+struct device {
+  u64_t dv_base;
+  u64_t dv_size;
+};
+
+#define NIL_DEV		((struct device *) 0)
+
+/* Functions defined by driver.c: */
+_PROTOTYPE( void driver_task, (struct driver *dr) );
+_PROTOTYPE( char *no_name, (void) );
+_PROTOTYPE( int do_nop, (struct driver *dp, message *m_ptr) );
+_PROTOTYPE( struct device *nop_prepare, (int device) );
+_PROTOTYPE( void nop_cleanup, (void) );
+_PROTOTYPE( void nop_task, (void) );
+_PROTOTYPE( void nop_signal, (struct driver *dp, message *m_ptr) );
+_PROTOTYPE( void nop_alarm, (struct driver *dp, message *m_ptr) );
+_PROTOTYPE( int nop_cancel, (struct driver *dp, message *m_ptr) );
+_PROTOTYPE( int nop_select, (struct driver *dp, message *m_ptr) );
+_PROTOTYPE( int do_diocntl, (struct driver *dp, message *m_ptr) );
+
+/* Parameters for the disk drive. */
+#define SECTOR_SIZE      512	/* physical sector size in bytes */
+#define SECTOR_SHIFT       9	/* for division */
+#define SECTOR_MASK      511	/* and remainder */
+
+/* Size of the DMA buffer buffer in bytes. */
+#define USE_EXTRA_DMA_BUF  0	/* usually not needed */
+#define DMA_BUF_SIZE	(DMA_SECTORS * SECTOR_SIZE)
+
+#if (CHIP == INTEL)
+extern u8_t *tmp_buf;			/* the DMA buffer */
+#else
+extern u8_t tmp_buf[];			/* the DMA buffer */
+#endif
+extern phys_bytes tmp_phys;		/* phys address of DMA buffer */
Index: /trunk/minix/drivers/libdriver/drvlib.c
===================================================================
--- /trunk/minix/drivers/libdriver/drvlib.c	(revision 9)
+++ /trunk/minix/drivers/libdriver/drvlib.c	(revision 9)
@@ -0,0 +1,199 @@
+/* IBM device driver utility functions.			Author: Kees J. Bot
+ *								7 Dec 1995
+ * Entry point:
+ *   partition:	partition a disk to the partition table(s) on it.
+ */
+
+#include "driver.h"
+#include "drvlib.h"
+#include <unistd.h>
+
+/* Extended partition? */
+#define ext_part(s)	((s) == 0x05 || (s) == 0x0F)
+
+FORWARD _PROTOTYPE( void extpartition, (struct driver *dp, int extdev,
+						unsigned long extbase) );
+FORWARD _PROTOTYPE( int get_part_table, (struct driver *dp, int device,
+			unsigned long offset, struct part_entry *table));
+FORWARD _PROTOTYPE( void sort, (struct part_entry *table) );
+
+#ifndef CD_SECTOR_SIZE
+#define CD_SECTOR_SIZE 2048
+#endif 
+
+/*============================================================================*
+ *				partition				      *
+ *============================================================================*/
+PUBLIC void partition(dp, device, style, atapi)
+struct driver *dp;	/* device dependent entry points */
+int device;		/* device to partition */
+int style;		/* partitioning style: floppy, primary, sub. */
+int atapi;		/* atapi device */
+{
+/* This routine is called on first open to initialize the partition tables
+ * of a device.  It makes sure that each partition falls safely within the
+ * device's limits.  Depending on the partition style we are either making
+ * floppy partitions, primary partitions or subpartitions.  Only primary
+ * partitions are sorted, because they are shared with other operating
+ * systems that expect this.
+ */
+  struct part_entry table[NR_PARTITIONS], *pe;
+  int disk, par;
+  struct device *dv;
+  unsigned long base, limit, part_limit;
+
+  /* Get the geometry of the device to partition */
+  if ((dv = (*dp->dr_prepare)(device)) == NIL_DEV
+				|| cmp64u(dv->dv_size, 0) == 0) return;
+  base = div64u(dv->dv_base, SECTOR_SIZE);
+  limit = base + div64u(dv->dv_size, SECTOR_SIZE);
+
+  /* Read the partition table for the device. */
+  if(!get_part_table(dp, device, 0L, table)) {
+	  return;
+  }
+
+  /* Compute the device number of the first partition. */
+  switch (style) {
+  case P_FLOPPY:
+	device += MINOR_fd0p0;
+	break;
+  case P_PRIMARY:
+	sort(table);		/* sort a primary partition table */
+	device += 1;
+	break;
+  case P_SUB:
+	disk = device / DEV_PER_DRIVE;
+	par = device % DEV_PER_DRIVE - 1;
+	device = MINOR_d0p0s0 + (disk * NR_PARTITIONS + par) * NR_PARTITIONS;
+  }
+
+  /* Find an array of devices. */
+  if ((dv = (*dp->dr_prepare)(device)) == NIL_DEV) return;
+
+  /* Set the geometry of the partitions from the partition table. */
+  for (par = 0; par < NR_PARTITIONS; par++, dv++) {
+	/* Shrink the partition to fit within the device. */
+	pe = &table[par];
+	part_limit = pe->lowsec + pe->size;
+	if (part_limit < pe->lowsec) part_limit = limit;
+	if (part_limit > limit) part_limit = limit;
+	if (pe->lowsec < base) pe->lowsec = base;
+	if (part_limit < pe->lowsec) part_limit = pe->lowsec;
+
+	dv->dv_base = mul64u(pe->lowsec, SECTOR_SIZE);
+	dv->dv_size = mul64u(part_limit - pe->lowsec, SECTOR_SIZE);
+
+	if (style == P_PRIMARY) {
+		/* Each Minix primary partition can be subpartitioned. */
+		if (pe->sysind == MINIX_PART)
+			partition(dp, device + par, P_SUB, atapi);
+
+		/* An extended partition has logical partitions. */
+		if (ext_part(pe->sysind))
+			extpartition(dp, device + par, pe->lowsec);
+	}
+  }
+}
+
+/*============================================================================*
+ *				extpartition				      *
+ *============================================================================*/
+PRIVATE void extpartition(dp, extdev, extbase)
+struct driver *dp;	/* device dependent entry points */
+int extdev;		/* extended partition to scan */
+unsigned long extbase;	/* sector offset of the base extended partition */
+{
+/* Extended partitions cannot be ignored alas, because people like to move
+ * files to and from DOS partitions.  Avoid reading this code, it's no fun.
+ */
+  struct part_entry table[NR_PARTITIONS], *pe;
+  int subdev, disk, par;
+  struct device *dv;
+  unsigned long offset, nextoffset;
+
+  disk = extdev / DEV_PER_DRIVE;
+  par = extdev % DEV_PER_DRIVE - 1;
+  subdev = MINOR_d0p0s0 + (disk * NR_PARTITIONS + par) * NR_PARTITIONS;
+
+  offset = 0;
+  do {
+	if (!get_part_table(dp, extdev, offset, table)) return;
+	sort(table);
+
+	/* The table should contain one logical partition and optionally
+	 * another extended partition.  (It's a linked list.)
+	 */
+	nextoffset = 0;
+	for (par = 0; par < NR_PARTITIONS; par++) {
+		pe = &table[par];
+		if (ext_part(pe->sysind)) {
+			nextoffset = pe->lowsec;
+		} else
+		if (pe->sysind != NO_PART) {
+			if ((dv = (*dp->dr_prepare)(subdev)) == NIL_DEV) return;
+
+			dv->dv_base = mul64u(extbase + offset + pe->lowsec,
+								SECTOR_SIZE);
+			dv->dv_size = mul64u(pe->size, SECTOR_SIZE);
+
+			/* Out of devices? */
+			if (++subdev % NR_PARTITIONS == 0) return;
+		}
+	}
+  } while ((offset = nextoffset) != 0);
+}
+
+/*============================================================================*
+ *				get_part_table				      *
+ *============================================================================*/
+PRIVATE int get_part_table(dp, device, offset, table)
+struct driver *dp;
+int device;
+unsigned long offset;		/* sector offset to the table */
+struct part_entry *table;	/* four entries */
+{
+/* Read the partition table for the device, return true iff there were no
+ * errors.
+ */
+  iovec_t iovec1;
+  off_t position;
+  static unsigned char partbuf[CD_SECTOR_SIZE];
+
+  position = offset << SECTOR_SHIFT;
+  iovec1.iov_addr = (vir_bytes) partbuf;
+  iovec1.iov_size = CD_SECTOR_SIZE;
+  if ((*dp->dr_prepare)(device) != NIL_DEV) {
+	(void) (*dp->dr_transfer)(SELF, DEV_GATHER, position, &iovec1, 1);
+  }
+  if (iovec1.iov_size != 0) {
+	return 0;
+  }
+  if (partbuf[510] != 0x55 || partbuf[511] != 0xAA) {
+	/* Invalid partition table. */
+	return 0;
+  }
+  memcpy(table, (partbuf + PART_TABLE_OFF), NR_PARTITIONS * sizeof(table[0]));
+  return 1;
+}
+
+/*===========================================================================*
+ *				sort					     *
+ *===========================================================================*/
+PRIVATE void sort(table)
+struct part_entry *table;
+{
+/* Sort a partition table. */
+  struct part_entry *pe, tmp;
+  int n = NR_PARTITIONS;
+
+  do {
+	for (pe = table; pe < table + NR_PARTITIONS-1; pe++) {
+		if (pe[0].sysind == NO_PART
+			|| (pe[0].lowsec > pe[1].lowsec
+					&& pe[1].sysind != NO_PART)) {
+			tmp = pe[0]; pe[0] = pe[1]; pe[1] = tmp;
+		}
+	}
+  } while (--n > 0);
+}
Index: /trunk/minix/drivers/libdriver/drvlib.h
===================================================================
--- /trunk/minix/drivers/libdriver/drvlib.h	(revision 9)
+++ /trunk/minix/drivers/libdriver/drvlib.h	(revision 9)
@@ -0,0 +1,27 @@
+/* IBM device driver definitions			Author: Kees J. Bot
+ *								7 Dec 1995
+ */
+
+#include <ibm/partition.h>
+
+_PROTOTYPE( void partition, (struct driver *dr, int device, int style, int atapi) );
+
+/* BIOS parameter table layout. */
+#define bp_cylinders(t)		(* (u16_t *) (&(t)[0]))
+#define bp_heads(t)		(* (u8_t *)  (&(t)[2]))
+#define bp_reduced_wr(t)	(* (u16_t *) (&(t)[3]))
+#define bp_precomp(t)		(* (u16_t *) (&(t)[5]))
+#define bp_max_ecc(t)		(* (u8_t *)  (&(t)[7]))
+#define bp_ctlbyte(t)		(* (u8_t *)  (&(t)[8]))
+#define bp_landingzone(t)	(* (u16_t *) (&(t)[12]))
+#define bp_sectors(t)		(* (u8_t *)  (&(t)[14]))
+
+/* Miscellaneous. */
+#define DEV_PER_DRIVE	(1 + NR_PARTITIONS)
+#define MINOR_t0	64
+#define MINOR_r0	120
+#define MINOR_d0p0s0	128
+#define MINOR_fd0p0	(28<<2)
+#define P_FLOPPY	0
+#define P_PRIMARY	1
+#define P_SUB		2
Index: /trunk/minix/drivers/log/.depend
===================================================================
--- /trunk/minix/drivers/log/.depend	(revision 9)
+++ /trunk/minix/drivers/log/.depend	(revision 9)
@@ -0,0 +1,166 @@
+
+diag.o:	../../kernel/config.h
+diag.o:	../../kernel/const.h
+diag.o:	../../kernel/type.h
+diag.o:	../drivers.h
+diag.o:	../libdriver/driver.h
+diag.o:	/usr/include/ansi.h
+diag.o:	/usr/include/errno.h
+diag.o:	/usr/include/fcntl.h
+diag.o:	/usr/include/ibm/bios.h
+diag.o:	/usr/include/ibm/cpu.h
+diag.o:	/usr/include/ibm/interrupt.h
+diag.o:	/usr/include/ibm/ports.h
+diag.o:	/usr/include/limits.h
+diag.o:	/usr/include/minix/bitmap.h
+diag.o:	/usr/include/minix/callnr.h
+diag.o:	/usr/include/minix/com.h
+diag.o:	/usr/include/minix/config.h
+diag.o:	/usr/include/minix/const.h
+diag.o:	/usr/include/minix/devio.h
+diag.o:	/usr/include/minix/dmap.h
+diag.o:	/usr/include/minix/ipc.h
+diag.o:	/usr/include/minix/partition.h
+diag.o:	/usr/include/minix/sys_config.h
+diag.o:	/usr/include/minix/syslib.h
+diag.o:	/usr/include/minix/sysutil.h
+diag.o:	/usr/include/minix/type.h
+diag.o:	/usr/include/minix/u64.h
+diag.o:	/usr/include/signal.h
+diag.o:	/usr/include/stddef.h
+diag.o:	/usr/include/stdio.h
+diag.o:	/usr/include/stdlib.h
+diag.o:	/usr/include/string.h
+diag.o:	/usr/include/sys/dir.h
+diag.o:	/usr/include/sys/types.h
+diag.o:	/usr/include/unistd.h
+diag.o:	diag.c
+diag.o:	log.h
+
+kputc.o:	../drivers.h
+kputc.o:	../libdriver/driver.h
+kputc.o:	/usr/include/ansi.h
+kputc.o:	/usr/include/errno.h
+kputc.o:	/usr/include/ibm/bios.h
+kputc.o:	/usr/include/ibm/interrupt.h
+kputc.o:	/usr/include/ibm/ports.h
+kputc.o:	/usr/include/limits.h
+kputc.o:	/usr/include/minix/bitmap.h
+kputc.o:	/usr/include/minix/callnr.h
+kputc.o:	/usr/include/minix/com.h
+kputc.o:	/usr/include/minix/config.h
+kputc.o:	/usr/include/minix/const.h
+kputc.o:	/usr/include/minix/devio.h
+kputc.o:	/usr/include/minix/dmap.h
+kputc.o:	/usr/include/minix/ipc.h
+kputc.o:	/usr/include/minix/partition.h
+kputc.o:	/usr/include/minix/sys_config.h
+kputc.o:	/usr/include/minix/syslib.h
+kputc.o:	/usr/include/minix/sysutil.h
+kputc.o:	/usr/include/minix/type.h
+kputc.o:	/usr/include/minix/u64.h
+kputc.o:	/usr/include/signal.h
+kputc.o:	/usr/include/stddef.h
+kputc.o:	/usr/include/stdlib.h
+kputc.o:	/usr/include/string.h
+kputc.o:	/usr/include/sys/dir.h
+kputc.o:	/usr/include/sys/types.h
+kputc.o:	/usr/include/unistd.h
+kputc.o:	kputc.c
+kputc.o:	log.h
+
+log.o:	../../kernel/config.h
+log.o:	../../kernel/const.h
+log.o:	../../kernel/type.h
+log.o:	../drivers.h
+log.o:	../libdriver/driver.h
+log.o:	/usr/include/ansi.h
+log.o:	/usr/include/errno.h
+log.o:	/usr/include/ibm/bios.h
+log.o:	/usr/include/ibm/cpu.h
+log.o:	/usr/include/ibm/interrupt.h
+log.o:	/usr/include/ibm/ports.h
+log.o:	/usr/include/limits.h
+log.o:	/usr/include/minix/bitmap.h
+log.o:	/usr/include/minix/callnr.h
+log.o:	/usr/include/minix/com.h
+log.o:	/usr/include/minix/config.h
+log.o:	/usr/include/minix/const.h
+log.o:	/usr/include/minix/devio.h
+log.o:	/usr/include/minix/dmap.h
+log.o:	/usr/include/minix/ipc.h
+log.o:	/usr/include/minix/partition.h
+log.o:	/usr/include/minix/sys_config.h
+log.o:	/usr/include/minix/syslib.h
+log.o:	/usr/include/minix/sysutil.h
+log.o:	/usr/include/minix/type.h
+log.o:	/usr/include/minix/u64.h
+log.o:	/usr/include/signal.h
+log.o:	/usr/include/stddef.h
+log.o:	/usr/include/stdlib.h
+log.o:	/usr/include/string.h
+log.o:	/usr/include/sys/dir.h
+log.o:	/usr/include/sys/select.h
+log.o:	/usr/include/sys/time.h
+log.o:	/usr/include/sys/types.h
+log.o:	/usr/include/unistd.h
+log.o:	log.c
+log.o:	log.h
+
+../libdriver/driver.o:	../libdriver/../drivers.h
+../libdriver/driver.o:	../libdriver/driver.c
+../libdriver/driver.o:	../libdriver/driver.h
+../libdriver/driver.o:	/usr/include/ansi.h
+../libdriver/driver.o:	/usr/include/errno.h
+../libdriver/driver.o:	/usr/include/ibm/bios.h
+../libdriver/driver.o:	/usr/include/ibm/interrupt.h
+../libdriver/driver.o:	/usr/include/ibm/ports.h
+../libdriver/driver.o:	/usr/include/limits.h
+../libdriver/driver.o:	/usr/include/minix/bitmap.h
+../libdriver/driver.o:	/usr/include/minix/callnr.h
+../libdriver/driver.o:	/usr/include/minix/com.h
+../libdriver/driver.o:	/usr/include/minix/config.h
+../libdriver/driver.o:	/usr/include/minix/const.h
+../libdriver/driver.o:	/usr/include/minix/devio.h
+../libdriver/driver.o:	/usr/include/minix/dmap.h
+../libdriver/driver.o:	/usr/include/minix/ioctl.h
+../libdriver/driver.o:	/usr/include/minix/ipc.h
+../libdriver/driver.o:	/usr/include/minix/partition.h
+../libdriver/driver.o:	/usr/include/minix/sys_config.h
+../libdriver/driver.o:	/usr/include/minix/syslib.h
+../libdriver/driver.o:	/usr/include/minix/sysutil.h
+../libdriver/driver.o:	/usr/include/minix/type.h
+../libdriver/driver.o:	/usr/include/minix/u64.h
+../libdriver/driver.o:	/usr/include/signal.h
+../libdriver/driver.o:	/usr/include/stddef.h
+../libdriver/driver.o:	/usr/include/stdlib.h
+../libdriver/driver.o:	/usr/include/string.h
+../libdriver/driver.o:	/usr/include/sys/dir.h
+../libdriver/driver.o:	/usr/include/sys/ioc_disk.h
+../libdriver/driver.o:	/usr/include/sys/types.h
+../libdriver/driver.o:	/usr/include/unistd.h
+
+../libdriver/drvlib.o:	../libdriver/driver.h
+../libdriver/drvlib.o:	../libdriver/drvlib.c
+../libdriver/drvlib.o:	../libdriver/drvlib.h
+../libdriver/drvlib.o:	/usr/include/ansi.h
+../libdriver/drvlib.o:	/usr/include/errno.h
+../libdriver/drvlib.o:	/usr/include/ibm/partition.h
+../libdriver/drvlib.o:	/usr/include/limits.h
+../libdriver/drvlib.o:	/usr/include/minix/callnr.h
+../libdriver/drvlib.o:	/usr/include/minix/com.h
+../libdriver/drvlib.o:	/usr/include/minix/config.h
+../libdriver/drvlib.o:	/usr/include/minix/const.h
+../libdriver/drvlib.o:	/usr/include/minix/devio.h
+../libdriver/drvlib.o:	/usr/include/minix/ipc.h
+../libdriver/drvlib.o:	/usr/include/minix/partition.h
+../libdriver/drvlib.o:	/usr/include/minix/sys_config.h
+../libdriver/drvlib.o:	/usr/include/minix/syslib.h
+../libdriver/drvlib.o:	/usr/include/minix/sysutil.h
+../libdriver/drvlib.o:	/usr/include/minix/type.h
+../libdriver/drvlib.o:	/usr/include/minix/u64.h
+../libdriver/drvlib.o:	/usr/include/stddef.h
+../libdriver/drvlib.o:	/usr/include/string.h
+../libdriver/drvlib.o:	/usr/include/sys/dir.h
+../libdriver/drvlib.o:	/usr/include/sys/types.h
+../libdriver/drvlib.o:	/usr/include/unistd.h
Index: /trunk/minix/drivers/log/Makefile
===================================================================
--- /trunk/minix/drivers/log/Makefile	(revision 9)
+++ /trunk/minix/drivers/log/Makefile	(revision 9)
@@ -0,0 +1,45 @@
+# Makefile for log driver
+DRIVER = log
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+d = ..
+
+# programs, flags, etc.
+MAKE = exec make
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsys -lsysutil
+
+OBJ = log.o diag.o kputc.o
+LIBDRIVER = $d/libdriver/driver.o
+
+
+# build local binary
+all build:	$(DRIVER)
+$(DRIVER):	$(OBJ) $(LIBDRIVER)
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBDRIVER) $(LIBS)
+	install -S 4kb $(DRIVER)
+
+$(LIBDRIVER): 
+	cd $d/libdriver && $(MAKE) 
+
+# install with other drivers
+install:	$(DRIVER)
+	install -o root -cs $? /sbin/$(DRIVER) 
+
+# clean up local files
+clean:
+	rm -f $(DRIVER) *.o *.bak 
+
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c ../libdriver/*.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/log/diag.c
===================================================================
--- /trunk/minix/drivers/log/diag.c	(revision 9)
+++ /trunk/minix/drivers/log/diag.c	(revision 9)
@@ -0,0 +1,119 @@
+/* This file handle diagnostic output that is directly sent to the LOG driver.
+ * This output can either be a kernel message (announced through a SYS_EVENT
+ * with a SIGKMESS in the signal set) or output from another system process
+ * (announced through a DIAGNOSTICS message).
+ *
+ * Changes:
+ *	21 July 2005:	Created  (Jorrit N. Herder)
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+
+#include "log.h"
+#include "../../kernel/const.h"
+#include "../../kernel/config.h"
+#include "../../kernel/type.h"
+
+/*==========================================================================*
+ *				do_new_kmess				    *
+ *==========================================================================*/
+PUBLIC int do_new_kmess(m)
+message *m;					/* notification message */
+{
+/* Notification for a new kernel message. */
+  struct kmessages kmess;		/* entire kmess structure */
+  char print_buf[KMESS_BUF_SIZE];	/* copy new message here */
+  static int prev_next = 0;
+  int bytes;
+  int i, r;
+
+  if (m->m_source == TTY_PROC_NR)
+  {
+	message mess;
+
+	/* Ask TTY driver for log output */
+	mess.GETKM_PTR= (char *) &kmess;
+	mess.m_type = GET_KMESS;
+	r= sendrec(TTY_PROC_NR, &mess);
+	if (r == OK) r= mess.m_type;
+	if (r != OK)
+	{
+		report("LOG","couldn't get copy of kmessages from TTY", r);
+		return EDONTREPLY;
+	}
+  }
+  else
+  {
+	/* Try to get a fresh copy of the buffer with kernel messages. */
+	if ((r=sys_getkmessages(&kmess)) != OK) {
+		report("LOG","couldn't get copy of kmessages", r);
+		return EDONTREPLY;
+	}
+  }
+
+  /* Print only the new part. Determine how many new bytes there are with 
+   * help of the current and previous 'next' index. Note that the kernel
+   * buffer is circular. This works fine if less then KMESS_BUF_SIZE bytes
+   * is new data; else we miss % KMESS_BUF_SIZE here.  
+   * Check for size being positive, the buffer might as well be emptied!
+   */
+  if (kmess.km_size > 0) {
+      bytes = ((kmess.km_next + KMESS_BUF_SIZE) - prev_next) % KMESS_BUF_SIZE;
+      r=prev_next;				/* start at previous old */ 
+      i=0;
+      while (bytes > 0) {			
+          print_buf[i] = kmess.km_buf[(r%KMESS_BUF_SIZE)];
+          bytes --;
+          r ++;
+          i ++;
+      }
+      /* Now terminate the new message and save it in the log. */
+      print_buf[i] = 0;
+      log_append(print_buf, i);
+  }
+
+  /* Almost done, store 'next' so that we can determine what part of the
+   * kernel messages buffer to print next time a notification arrives.
+   */
+  prev_next = kmess.km_next;
+  return EDONTREPLY;
+}
+
+/*===========================================================================*
+ *				do_diagnostics				     *
+ *===========================================================================*/
+PUBLIC int do_diagnostics(message *m)
+{
+/* The LOG server handles all diagnostic messages from servers and device 
+ * drivers. It forwards the message to the TTY driver to display it to the
+ * user. It also saves a copy in a local buffer so that messages can be 
+ * reviewed at a later time.
+ */
+  int proc_nr_e; 
+  vir_bytes src;
+  int count;
+  char c;
+  int i = 0;
+  static char diagbuf[10240];
+
+  /* Change SELF to actual process number. */
+  if ((proc_nr_e = m->DIAG_ENDPT) == SELF)
+      m->DIAG_ENDPT = proc_nr_e = m->m_source;
+
+  /* Now also make a copy for the private buffer at the LOG server, so
+   * that the messages can be reviewed at a later time.
+   */
+  src = (vir_bytes) m->DIAG_PRINT_BUF;
+  count = m->DIAG_BUF_COUNT; 
+  while (count > 0 && i < sizeof(diagbuf)-1) {
+      if (sys_datacopy(proc_nr_e, src, SELF, (vir_bytes) &c, 1) != OK) 
+          break;		/* stop copying on error */
+      src ++;
+      count --;
+      diagbuf[i++] = c;
+  }
+  log_append(diagbuf, i);
+
+  return OK;
+}
Index: /trunk/minix/drivers/log/kputc.c
===================================================================
--- /trunk/minix/drivers/log/kputc.c	(revision 9)
+++ /trunk/minix/drivers/log/kputc.c	(revision 9)
@@ -0,0 +1,35 @@
+/* A server must occasionally print some message.  It uses a simple version of 
+ * printf() found in the system library that calls putk() to output characters.
+ * The LOG driver cannot use the regular putk().  Hence, it uses a special
+ * version of putk() that directly sends to the TTY task. 
+ *
+ * Changes:
+ *	21 July 2005:	Created  (Jorrit N. Herder)
+ */
+
+#include "log.h"
+
+/*===========================================================================*
+ *				kputc					     *
+ *===========================================================================*/
+void kputc(c)
+int c;
+{
+/* Accumulate another character.  If 0 or buffer full, print it. */
+  static int buf_count;		/* # characters in the buffer */
+  static char print_buf[80];	/* output is buffered here */
+  message m;
+
+  if ((c == 0 && buf_count > 0) || buf_count == sizeof(print_buf)) {
+	m.DIAG_BUF_COUNT = buf_count;
+	m.DIAG_PRINT_BUF = print_buf;
+	m.DIAG_ENDPT = SELF;
+	m.m_type = DIAGNOSTICS;		/* request TTY to output this buffer */
+	_sendrec(TTY_PROC_NR, &m);	/* if it fails, we give up */ 
+	buf_count = 0;			/* clear buffer for next batch */
+  }
+  if (c != 0) {
+  	print_buf[buf_count++] = c;
+  }
+}
+
Index: /trunk/minix/drivers/log/log.c
===================================================================
--- /trunk/minix/drivers/log/log.c	(revision 9)
+++ /trunk/minix/drivers/log/log.c	(revision 9)
@@ -0,0 +1,480 @@
+/* This file contains a driver for:
+ *     /dev/klog	- system log device
+ *
+ * Changes:
+ *   21 July 2005   - Support for diagnostic messages (Jorrit N. Herder)
+ *    7 July 2005   - Created (Ben Gras)
+ */
+
+#include "log.h"
+#include <sys/time.h>
+#include <sys/select.h>
+#include "../../kernel/const.h"
+#include "../../kernel/type.h"
+
+#define LOG_DEBUG		0	/* enable/ disable debugging */
+
+#define NR_DEVS            	1	/* number of minor devices */
+#define MINOR_KLOG		0	/* /dev/klog */
+
+#define LOGINC(n, i)	do { (n) = (((n) + (i)) % LOG_SIZE); } while(0)
+
+PUBLIC struct logdevice logdevices[NR_DEVS];
+PRIVATE struct device log_geom[NR_DEVS];  	/* base and size of devices */
+PRIVATE int log_device = -1;	 		/* current device */
+
+FORWARD _PROTOTYPE( char *log_name, (void) );
+FORWARD _PROTOTYPE( struct device *log_prepare, (int device) );
+FORWARD _PROTOTYPE( int log_transfer, (int proc_nr, int opcode, off_t position,
+					iovec_t *iov, unsigned nr_req) );
+FORWARD _PROTOTYPE( int log_do_open, (struct driver *dp, message *m_ptr) );
+FORWARD _PROTOTYPE( int log_cancel, (struct driver *dp, message *m_ptr) );
+FORWARD _PROTOTYPE( int log_select, (struct driver *dp, message *m_ptr) );
+FORWARD _PROTOTYPE( void log_signal, (struct driver *dp, message *m_ptr) );
+FORWARD _PROTOTYPE( int log_other, (struct driver *dp, message *m_ptr) );
+FORWARD _PROTOTYPE( void log_geometry, (struct partition *entry) );
+FORWARD _PROTOTYPE( int subread, (struct logdevice *log, int count, int proc_nr, vir_bytes user_vir) );
+
+/* Entry points to this driver. */
+PRIVATE struct driver log_dtab = {
+  log_name,	/* current device's name */
+  log_do_open,	/* open or mount */
+  do_nop,	/* nothing on a close */
+  do_nop,	/* ioctl nop */
+  log_prepare,	/* prepare for I/O on a given minor device */
+  log_transfer,	/* do the I/O */
+  nop_cleanup,	/* no need to clean up */
+  log_geometry,	/* geometry */
+  log_signal,	/* handle system signal */
+  nop_alarm, 	/* no alarm */
+  log_cancel,	/* CANCEL request */
+  log_select,	/* DEV_SELECT request */
+  log_other,	/* Unrecognized messages */
+  NULL		/* HW int */
+};
+
+extern int device_caller;
+
+/*===========================================================================*
+ *				   main 				     *
+ *===========================================================================*/
+PUBLIC int main(void)
+{
+  int i;
+  for(i = 0; i < NR_DEVS; i++) {
+  	log_geom[i].dv_size = cvul64(LOG_SIZE);
+ 	log_geom[i].dv_base = cvul64((long)logdevices[i].log_buffer);
+ 	logdevices[i].log_size = logdevices[i].log_read =
+	 	logdevices[i].log_write =
+	 	logdevices[i].log_select_alerted =
+	 	logdevices[i].log_selected =
+	 	logdevices[i].log_select_ready_ops = 0;
+ 	logdevices[i].log_proc_nr = 0;
+ 	logdevices[i].log_revive_alerted = 0;
+  }
+  driver_task(&log_dtab);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				 log_name					     *
+ *===========================================================================*/
+PRIVATE char *log_name()
+{
+/* Return a name for the current device. */
+  static char name[] = "log";
+  return name;  
+}
+
+/*===========================================================================*
+ *				log_prepare				     *
+ *===========================================================================*/
+PRIVATE struct device *log_prepare(device)
+int device;
+{
+/* Prepare for I/O on a device: check if the minor device number is ok. */
+
+  if (device < 0 || device >= NR_DEVS) return(NIL_DEV);
+  log_device = device;
+
+  return(&log_geom[device]);
+}
+
+/*===========================================================================*
+ *				subwrite					     *
+ *===========================================================================*/
+PRIVATE int
+subwrite(struct logdevice *log, int count, int proc_nr, vir_bytes user_vir)
+{
+	char *buf;
+	int r;
+	if (log->log_write + count > LOG_SIZE)
+		count = LOG_SIZE - log->log_write;
+	buf = log->log_buffer + log->log_write;
+
+	if(proc_nr == SELF) {
+		memcpy(buf, (char *) user_vir, count);
+	}
+	else {
+		if((r=sys_vircopy(proc_nr,D,user_vir, SELF,D,(int)buf, count)) != OK)
+			return r;
+	}
+
+	LOGINC(log->log_write, count);
+	log->log_size += count;
+
+        if(log->log_size > LOG_SIZE) {
+        	int overflow;
+        	overflow = log->log_size - LOG_SIZE;
+        	log->log_size -= overflow;
+        	LOGINC(log->log_read, overflow);
+        }
+
+        if(log->log_size > 0 && log->log_proc_nr && !log->log_revive_alerted) {
+        	/* Someone who was suspended on read can now
+        	 * be revived.
+        	 */
+    		log->log_status = subread(log, log->log_iosize,
+    			log->log_proc_nr, log->log_user_vir);
+    		notify(log->log_source); 
+    		log->log_revive_alerted = 1;
+ 	} 
+
+	if(log->log_size > 0)
+		log->log_select_ready_ops |= SEL_RD;
+
+	if(log->log_size > 0 && log->log_selected &&
+	  !(log->log_select_alerted)) {
+  		/* Someone(s) who was/were select()ing can now
+  		 * be awoken. If there was a blocking read (above),
+  		 * this can only happen if the blocking read didn't
+  		 * swallow all the data (log_size > 0).
+  		 */
+  		if(log->log_selected & SEL_RD) {
+    			notify(log->log_select_proc);
+    			log->log_select_alerted = 1;
+#if LOG_DEBUG
+			printf("log notified %d\n", log->log_select_proc);
+#endif
+  		}
+  	}
+
+        return count;
+}
+
+/*===========================================================================*
+ *				log_append				*
+ *===========================================================================*/
+PUBLIC void
+log_append(char *buf, int count)
+{
+	int w = 0, skip = 0;
+
+	if(count < 1) return;
+	if(count > LOG_SIZE) skip = count - LOG_SIZE;
+	count -= skip;
+	buf += skip;
+	w = subwrite(&logdevices[0], count, SELF, (vir_bytes) buf);
+
+	if(w > 0 && w < count)
+		subwrite(&logdevices[0], count-w, SELF, (vir_bytes) buf+w);
+	return;
+}
+
+/*===========================================================================*
+ *				subread					     *
+ *===========================================================================*/
+PRIVATE int
+subread(struct logdevice *log, int count, int proc_nr, vir_bytes user_vir)
+{
+	char *buf;
+	int r;
+    	if (count > log->log_size)
+    		count = log->log_size;
+        if (log->log_read + count > LOG_SIZE)
+        	count = LOG_SIZE - log->log_read;
+
+    	buf = log->log_buffer + log->log_read;
+        if((r=sys_vircopy(SELF,D,(int)buf,proc_nr,D,user_vir, count)) != OK)
+        	return r;
+
+  	LOGINC(log->log_read, count);
+        log->log_size -= count;
+
+        return count;
+}
+
+/*===========================================================================*
+ *				log_transfer				     *
+ *===========================================================================*/
+PRIVATE int log_transfer(proc_nr, opcode, position, iov, nr_req)
+int proc_nr;			/* process doing the request */
+int opcode;			/* DEV_GATHER or DEV_SCATTER */
+off_t position;			/* offset on device to read or write */
+iovec_t *iov;			/* pointer to read or write request vector */
+unsigned nr_req;		/* length of request vector */
+{
+/* Read or write one the driver's minor devices. */
+  unsigned count;
+  vir_bytes user_vir;
+  struct device *dv;
+  unsigned long dv_size;
+  int accumulated_read = 0;
+  struct logdevice *log;
+  static int f;
+
+  if(log_device < 0 || log_device >= NR_DEVS)
+  	return EIO;
+
+  /* Get minor device number and check for /dev/null. */
+  dv = &log_geom[log_device];
+  dv_size = cv64ul(dv->dv_size);
+  log = &logdevices[log_device];
+
+  while (nr_req > 0) {
+	/* How much to transfer and where to / from. */
+	count = iov->iov_size;
+	user_vir = iov->iov_addr;
+
+	switch (log_device) {
+
+	case MINOR_KLOG:
+	    if (opcode == DEV_GATHER) {
+	    	if (log->log_proc_nr || count < 1) {
+	    		/* There's already someone hanging to read, or
+	    		 * no real I/O requested.
+	    		 */
+	    		return(OK);
+	    	}
+
+	    	if (!log->log_size) {
+	    		if(accumulated_read)
+	    			return OK;
+	    		/* No data available; let caller block. */
+	    		log->log_proc_nr = proc_nr;
+	    		log->log_iosize = count;
+	    		log->log_user_vir = user_vir;
+	    		log->log_revive_alerted = 0;
+
+			/* Device_caller is a global in drivers library. */
+	    		log->log_source = device_caller;
+#if LOG_DEBUG
+	    		printf("blocked %d (%d)\n", 
+	    			log->log_source, log->log_proc_nr);
+#endif
+	    		return(SUSPEND);
+	    	}
+	    	count = subread(log, count, proc_nr, user_vir);
+	    	if(count < 0) {
+	    		return count;
+	    	}
+	    	accumulated_read += count;
+	    } else {
+	    	count = subwrite(log, count, proc_nr, user_vir);
+	    	if(count < 0)
+	    		return count;
+	    }
+	    break;
+	/* Unknown (illegal) minor device. */
+	default:
+	    return(EINVAL);
+	}
+
+	/* Book the number of bytes transferred. */
+	iov->iov_addr += count;
+  	if ((iov->iov_size -= count) == 0) { iov++; nr_req--; }
+  }
+  return(OK);
+}
+
+/*============================================================================*
+ *				log_do_open				      *
+ *============================================================================*/
+PRIVATE int log_do_open(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+  if (log_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
+  return(OK);
+}
+
+/*============================================================================*
+ *				log_geometry				      *
+ *============================================================================*/
+PRIVATE void log_geometry(entry)
+struct partition *entry;
+{
+  /* take a page from the fake memory device geometry */
+  entry->heads = 64;
+  entry->sectors = 32;
+  entry->cylinders = div64u(log_geom[log_device].dv_size, SECTOR_SIZE) /
+  	(entry->heads * entry->sectors);
+}
+
+/*============================================================================*
+ *				log_cancel				      *
+ *============================================================================*/
+PRIVATE int log_cancel(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+  int d;
+  d = m_ptr->TTY_LINE;
+  if(d < 0 || d >= NR_DEVS)
+  	return EINVAL;
+  logdevices[d].log_proc_nr = 0;
+  logdevices[d].log_revive_alerted = 0;
+  return(OK);
+}
+
+/*============================================================================*
+ *				do_status				      *
+ *============================================================================*/
+PRIVATE void do_status(message *m_ptr)
+{
+	int d; 
+	message m;
+
+	/* Caller has requested pending status information, which currently
+	 * can be pending available select()s, or REVIVE events. One message
+	 * is returned for every event, or DEV_NO_STATUS if no (more) events
+	 * are to be returned.
+	 */
+
+	for(d = 0; d < NR_DEVS; d++) {
+		/* Check for revive callback. */
+		if(logdevices[d].log_proc_nr && logdevices[d].log_revive_alerted
+		   && logdevices[d].log_source == m_ptr->m_source) {
+			m.m_type = DEV_REVIVE;
+			m.REP_ENDPT = logdevices[d].log_proc_nr;
+			m.REP_STATUS  = logdevices[d].log_status;
+  			send(m_ptr->m_source, &m);
+			logdevices[d].log_proc_nr = 0;
+			logdevices[d].log_revive_alerted = 0;
+#if LOG_DEBUG
+    		printf("revived %d with %d bytes\n", 
+			m.REP_ENDPT, m.REP_STATUS);
+#endif
+			return;
+		}
+
+		/* Check for select callback. */
+		if(logdevices[d].log_selected && logdevices[d].log_select_proc == m_ptr->m_source 
+			&& logdevices[d].log_select_alerted) {
+			m.m_type = DEV_IO_READY;
+			m.DEV_SEL_OPS = logdevices[d].log_select_ready_ops;
+			m.DEV_MINOR   = d;
+#if LOG_DEBUG
+    		printf("select sending sent\n");
+#endif
+  			send(m_ptr->m_source, &m);
+			logdevices[d].log_selected &= ~logdevices[d].log_select_ready_ops;
+			logdevices[d].log_select_alerted = 0;
+#if LOG_DEBUG
+    		printf("select send sent\n");
+#endif
+			return;
+		}
+	}
+
+	/* No event found. */
+	m.m_type = DEV_NO_STATUS;
+  	send(m_ptr->m_source, &m);
+
+	return;
+}
+
+/*============================================================================*
+ *				log_signal				      *
+ *============================================================================*/
+PRIVATE void log_signal(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+  sigset_t sigset = m_ptr->NOTIFY_ARG;
+  if (sigismember(&sigset, SIGKMESS)) {
+	do_new_kmess(m_ptr);
+  }	
+}
+
+	
+/*============================================================================*
+ *				log_other				      *
+ *============================================================================*/
+PRIVATE int log_other(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+	int r;
+
+	/* This function gets messages that the generic driver doesn't
+	 * understand.
+	 */
+	switch(m_ptr->m_type) {
+	case DIAGNOSTICS: {
+		r = do_diagnostics(m_ptr);
+		break;
+	}
+	case DEV_STATUS: {
+		do_status(m_ptr);
+		r = EDONTREPLY;
+		break;
+	}
+	case NOTIFY_FROM(TTY_PROC_NR):
+		do_new_kmess(m_ptr);
+		r = EDONTREPLY;
+		break;
+	default:
+		r = EINVAL;
+		break;
+	}
+	return r;
+}
+
+/*============================================================================*
+ *				log_select				      *
+ *============================================================================*/
+PRIVATE int log_select(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+  int d, ready_ops = 0, ops = 0;
+  d = m_ptr->TTY_LINE;
+  if(d < 0 || d >= NR_DEVS) {
+#if LOG_DEBUG
+  	printf("line %d? EINVAL\n", d);
+#endif
+  	return EINVAL;
+  }
+
+  ops = m_ptr->IO_ENDPT & (SEL_RD|SEL_WR|SEL_ERR);
+
+  	/* Read blocks when there is no log. */
+  if((m_ptr->IO_ENDPT & SEL_RD) && logdevices[d].log_size > 0) {
+#if LOG_DEBUG
+  	printf("log can read; size %d\n", logdevices[d].log_size);
+#endif
+  	ready_ops |= SEL_RD; /* writes never block */
+ }
+
+  	/* Write never blocks. */
+  if(m_ptr->IO_ENDPT & SEL_WR) ready_ops |= SEL_WR;
+
+	/* Enable select calback if no operations were
+	 * ready to go, but operations were requested,
+	 * and notify was enabled.
+	 */
+  if((m_ptr->IO_ENDPT & SEL_NOTIFY) && ops && !ready_ops) {
+  	logdevices[d].log_selected |= ops;
+  	logdevices[d].log_select_proc = m_ptr->m_source;
+#if LOG_DEBUG
+  	printf("log setting selector.\n");
+#endif
+  }
+
+#if LOG_DEBUG
+  printf("log returning ops %d\n", ready_ops);
+#endif
+
+  return(ready_ops);
+}
Index: /trunk/minix/drivers/log/log.h
===================================================================
--- /trunk/minix/drivers/log/log.h	(revision 9)
+++ /trunk/minix/drivers/log/log.h	(revision 9)
@@ -0,0 +1,37 @@
+/* Includes. */
+#include "../drivers.h"
+#include "../libdriver/driver.h"
+#include <minix/type.h>
+#include <minix/const.h>
+#include <minix/com.h>
+#include <sys/types.h>
+#include <minix/ipc.h>
+
+/* Constants and types. */
+
+#define LOG_SIZE	(50*1024) 
+#define SUSPENDABLE 	      1
+
+struct logdevice {
+	char log_buffer[LOG_SIZE];
+	int	log_size,	/* no. of bytes in log buffer */
+		log_read,	/* read mark */
+		log_write;	/* write mark */
+#if SUSPENDABLE
+	int log_proc_nr,
+		log_source,
+		log_iosize,
+		log_revive_alerted,
+		log_status;	/* proc that is blocking on read */
+	vir_bytes log_user_vir;
+#endif
+	int	log_selected, log_select_proc,
+		log_select_alerted, log_select_ready_ops;
+};
+
+/* Function prototypes. */
+_PROTOTYPE( void kputc, (int c)						);
+_PROTOTYPE( int do_new_kmess, (message *m)				);
+_PROTOTYPE( int do_diagnostics, (message *m)				);
+_PROTOTYPE( void log_append, (char *buf, int len)				);
+
Index: /trunk/minix/drivers/memory/.depend
===================================================================
--- /trunk/minix/drivers/memory/.depend	(revision 9)
+++ /trunk/minix/drivers/memory/.depend	(revision 9)
@@ -0,0 +1,98 @@
+
+memory.o:	../../kernel/config.h
+memory.o:	../../kernel/const.h
+memory.o:	../../kernel/type.h
+memory.o:	../drivers.h
+memory.o:	../libdriver/driver.h
+memory.o:	/usr/include/ansi.h
+memory.o:	/usr/include/assert.h
+memory.o:	/usr/include/errno.h
+memory.o:	/usr/include/ibm/bios.h
+memory.o:	/usr/include/ibm/cpu.h
+memory.o:	/usr/include/ibm/interrupt.h
+memory.o:	/usr/include/ibm/ports.h
+memory.o:	/usr/include/limits.h
+memory.o:	/usr/include/minix/bitmap.h
+memory.o:	/usr/include/minix/callnr.h
+memory.o:	/usr/include/minix/com.h
+memory.o:	/usr/include/minix/config.h
+memory.o:	/usr/include/minix/const.h
+memory.o:	/usr/include/minix/devio.h
+memory.o:	/usr/include/minix/dmap.h
+memory.o:	/usr/include/minix/ioctl.h
+memory.o:	/usr/include/minix/ipc.h
+memory.o:	/usr/include/minix/partition.h
+memory.o:	/usr/include/minix/sys_config.h
+memory.o:	/usr/include/minix/syslib.h
+memory.o:	/usr/include/minix/sysutil.h
+memory.o:	/usr/include/minix/type.h
+memory.o:	/usr/include/minix/u64.h
+memory.o:	/usr/include/signal.h
+memory.o:	/usr/include/stddef.h
+memory.o:	/usr/include/stdlib.h
+memory.o:	/usr/include/string.h
+memory.o:	/usr/include/sys/dir.h
+memory.o:	/usr/include/sys/ioc_memory.h
+memory.o:	/usr/include/sys/types.h
+memory.o:	/usr/include/sys/vm.h
+memory.o:	/usr/include/unistd.h
+memory.o:	local.h
+memory.o:	memory.c
+
+../libdriver/driver.o:	../libdriver/../drivers.h
+../libdriver/driver.o:	../libdriver/driver.c
+../libdriver/driver.o:	../libdriver/driver.h
+../libdriver/driver.o:	/usr/include/ansi.h
+../libdriver/driver.o:	/usr/include/errno.h
+../libdriver/driver.o:	/usr/include/ibm/bios.h
+../libdriver/driver.o:	/usr/include/ibm/interrupt.h
+../libdriver/driver.o:	/usr/include/ibm/ports.h
+../libdriver/driver.o:	/usr/include/limits.h
+../libdriver/driver.o:	/usr/include/minix/bitmap.h
+../libdriver/driver.o:	/usr/include/minix/callnr.h
+../libdriver/driver.o:	/usr/include/minix/com.h
+../libdriver/driver.o:	/usr/include/minix/config.h
+../libdriver/driver.o:	/usr/include/minix/const.h
+../libdriver/driver.o:	/usr/include/minix/devio.h
+../libdriver/driver.o:	/usr/include/minix/dmap.h
+../libdriver/driver.o:	/usr/include/minix/ioctl.h
+../libdriver/driver.o:	/usr/include/minix/ipc.h
+../libdriver/driver.o:	/usr/include/minix/partition.h
+../libdriver/driver.o:	/usr/include/minix/sys_config.h
+../libdriver/driver.o:	/usr/include/minix/syslib.h
+../libdriver/driver.o:	/usr/include/minix/sysutil.h
+../libdriver/driver.o:	/usr/include/minix/type.h
+../libdriver/driver.o:	/usr/include/minix/u64.h
+../libdriver/driver.o:	/usr/include/signal.h
+../libdriver/driver.o:	/usr/include/stddef.h
+../libdriver/driver.o:	/usr/include/stdlib.h
+../libdriver/driver.o:	/usr/include/string.h
+../libdriver/driver.o:	/usr/include/sys/dir.h
+../libdriver/driver.o:	/usr/include/sys/ioc_disk.h
+../libdriver/driver.o:	/usr/include/sys/types.h
+../libdriver/driver.o:	/usr/include/unistd.h
+
+../libdriver/drvlib.o:	../libdriver/driver.h
+../libdriver/drvlib.o:	../libdriver/drvlib.c
+../libdriver/drvlib.o:	../libdriver/drvlib.h
+../libdriver/drvlib.o:	/usr/include/ansi.h
+../libdriver/drvlib.o:	/usr/include/errno.h
+../libdriver/drvlib.o:	/usr/include/ibm/partition.h
+../libdriver/drvlib.o:	/usr/include/limits.h
+../libdriver/drvlib.o:	/usr/include/minix/callnr.h
+../libdriver/drvlib.o:	/usr/include/minix/com.h
+../libdriver/drvlib.o:	/usr/include/minix/config.h
+../libdriver/drvlib.o:	/usr/include/minix/const.h
+../libdriver/drvlib.o:	/usr/include/minix/devio.h
+../libdriver/drvlib.o:	/usr/include/minix/ipc.h
+../libdriver/drvlib.o:	/usr/include/minix/partition.h
+../libdriver/drvlib.o:	/usr/include/minix/sys_config.h
+../libdriver/drvlib.o:	/usr/include/minix/syslib.h
+../libdriver/drvlib.o:	/usr/include/minix/sysutil.h
+../libdriver/drvlib.o:	/usr/include/minix/type.h
+../libdriver/drvlib.o:	/usr/include/minix/u64.h
+../libdriver/drvlib.o:	/usr/include/stddef.h
+../libdriver/drvlib.o:	/usr/include/string.h
+../libdriver/drvlib.o:	/usr/include/sys/dir.h
+../libdriver/drvlib.o:	/usr/include/sys/types.h
+../libdriver/drvlib.o:	/usr/include/unistd.h
Index: /trunk/minix/drivers/memory/Makefile
===================================================================
--- /trunk/minix/drivers/memory/Makefile	(revision 9)
+++ /trunk/minix/drivers/memory/Makefile	(revision 9)
@@ -0,0 +1,61 @@
+# Makefile for memory driver (MEMORY)
+DRIVER = memory
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+MAKE = exec make
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsys -lsysutil
+
+# imgrd_s.s is the ACK assembler version of the ramdisk. For more portability,
+# use the C version imgrd.c. However, the C compiler takes too much memory
+# compiling imgrd.c.
+IMGRD=imgrd_s.o
+#IMGRD=imgrd.c
+
+OBJ = memory.o $(IMGRD)
+LIBDRIVER = $d/libdriver/driver.o
+
+
+# build local binary
+all build:	$(DRIVER)
+
+$(DRIVER):	ramdisk_image $(OBJ) $(LIBDRIVER)
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBDRIVER) $(LIBS)
+	install -S 8k $(DRIVER)
+
+imgrd.o:        ramdisk/image.c
+imgrd_s.o:      ramdisk/image.s
+
+$(LIBDRIVER): 
+	cd $d/libdriver && $(MAKE) 
+
+ramdisk_image:
+	cd ramdisk && make
+
+# install with other drivers
+install: /usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER):	$(DRIVER)
+	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f $(DRIVER) *.o *.bak 
+	cd ramdisk && make clean
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" memory.c ../libdriver/*.c > .depend
+	cd ramdisk && make depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/memory/imgrd.c
===================================================================
--- /trunk/minix/drivers/memory/imgrd.c	(revision 9)
+++ /trunk/minix/drivers/memory/imgrd.c	(revision 9)
@@ -0,0 +1,14 @@
+/*
+Ramdisk that is part of the image
+*/
+
+#include <stddef.h>
+
+#include "local.h"
+
+unsigned char imgrd[]=
+{
+#include "ramdisk/image.c"
+};
+
+size_t imgrd_size= sizeof(imgrd);
Index: /trunk/minix/drivers/memory/imgrd_s.s
===================================================================
--- /trunk/minix/drivers/memory/imgrd_s.s	(revision 9)
+++ /trunk/minix/drivers/memory/imgrd_s.s	(revision 9)
@@ -0,0 +1,15 @@
+#
+.sect .text; .sect .rom; .sect .data
+
+! export symbols
+.define _imgrd, _imgrd_size
+
+.sect .data
+_imgrd:
+0:
+#include "ramdisk/image.s"
+1:
+
+! Use local labels to compute the size of _imgrd.
+_imgrd_size:
+	.data4	[1b] - [0b]
Index: /trunk/minix/drivers/memory/local.h
===================================================================
--- /trunk/minix/drivers/memory/local.h	(revision 9)
+++ /trunk/minix/drivers/memory/local.h	(revision 9)
@@ -0,0 +1,6 @@
+/*
+local defines and declarations 
+*/
+
+extern unsigned char imgrd[];
+extern size_t imgrd_size;
Index: /trunk/minix/drivers/memory/memory.c
===================================================================
--- /trunk/minix/drivers/memory/memory.c	(revision 9)
+++ /trunk/minix/drivers/memory/memory.c	(revision 9)
@@ -0,0 +1,437 @@
+/* This file contains the device dependent part of the drivers for the
+ * following special files:
+ *     /dev/ram		- RAM disk 
+ *     /dev/mem		- absolute memory
+ *     /dev/kmem	- kernel virtual memory
+ *     /dev/null	- null device (data sink)
+ *     /dev/boot	- boot device loaded from boot image 
+ *     /dev/zero	- null byte stream generator
+ *
+ *  Changes:
+ *	Apr 29, 2005	added null byte generator  (Jorrit N. Herder)
+ *	Apr 09, 2005	added support for boot device  (Jorrit N. Herder)
+ *	Jul 26, 2004	moved RAM driver to user-space  (Jorrit N. Herder)
+ *	Apr 20, 1992	device dependent/independent split  (Kees J. Bot)
+ */
+
+#include "../drivers.h"
+#include "../libdriver/driver.h"
+#include <sys/ioc_memory.h>
+#include "../../kernel/const.h"
+#include "../../kernel/config.h"
+#include "../../kernel/type.h"
+
+#include <sys/vm.h>
+
+#include "assert.h"
+
+#include "local.h"
+
+#define NR_DEVS            7		/* number of minor devices */
+
+PRIVATE struct device m_geom[NR_DEVS];  /* base and size of each device */
+PRIVATE int m_seg[NR_DEVS];  		/* segment index of each device */
+PRIVATE int m_device;			/* current device */
+PRIVATE struct kinfo kinfo;		/* kernel information */ 
+PRIVATE struct machine machine;		/* machine information */ 
+
+extern int errno;			/* error number for PM calls */
+
+FORWARD _PROTOTYPE( char *m_name, (void) 				);
+FORWARD _PROTOTYPE( struct device *m_prepare, (int device) 		);
+FORWARD _PROTOTYPE( int m_transfer, (int proc_nr, int opcode, off_t position,
+					iovec_t *iov, unsigned nr_req) 	);
+FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr) 	);
+FORWARD _PROTOTYPE( void m_init, (void) );
+FORWARD _PROTOTYPE( int m_ioctl, (struct driver *dp, message *m_ptr) 	);
+FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) 		);
+
+/* Entry points to this driver. */
+PRIVATE struct driver m_dtab = {
+  m_name,	/* current device's name */
+  m_do_open,	/* open or mount */
+  do_nop,	/* nothing on a close */
+  m_ioctl,	/* specify ram disk geometry */
+  m_prepare,	/* prepare for I/O on a given minor device */
+  m_transfer,	/* do the I/O */
+  nop_cleanup,	/* no need to clean up */
+  m_geometry,	/* memory device "geometry" */
+  nop_signal,	/* system signals */
+  nop_alarm,
+  nop_cancel,
+  nop_select,
+  NULL,
+  NULL
+};
+
+/* Buffer for the /dev/zero null byte feed. */
+#define ZERO_BUF_SIZE 			1024
+PRIVATE char dev_zero[ZERO_BUF_SIZE];
+
+#define click_to_round_k(n) \
+	((unsigned) ((((unsigned long) (n) << CLICK_SHIFT) + 512) / 1024))
+
+/*===========================================================================*
+ *				   main 				     *
+ *===========================================================================*/
+PUBLIC int main(void)
+{
+/* Main program. Initialize the memory driver and start the main loop. */
+  struct sigaction sa;
+
+  sa.sa_handler = SIG_MESS;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = 0;
+  if (sigaction(SIGTERM,&sa,NULL)<0) panic("MEM","sigaction failed", errno);
+
+  m_init();			
+  driver_task(&m_dtab);		
+  return(OK);				
+}
+
+/*===========================================================================*
+ *				 m_name					     *
+ *===========================================================================*/
+PRIVATE char *m_name()
+{
+/* Return a name for the current device. */
+  static char name[] = "memory";
+  return name;  
+}
+
+/*===========================================================================*
+ *				m_prepare				     *
+ *===========================================================================*/
+PRIVATE struct device *m_prepare(device)
+int device;
+{
+/* Prepare for I/O on a device: check if the minor device number is ok. */
+  if (device < 0 || device >= NR_DEVS) return(NIL_DEV);
+  m_device = device;
+
+  return(&m_geom[device]);
+}
+
+/*===========================================================================*
+ *				m_transfer				     *
+ *===========================================================================*/
+PRIVATE int m_transfer(proc_nr, opcode, position, iov, nr_req)
+int proc_nr;			/* process doing the request */
+int opcode;			/* DEV_GATHER or DEV_SCATTER */
+off_t position;			/* offset on device to read or write */
+iovec_t *iov;			/* pointer to read or write request vector */
+unsigned nr_req;		/* length of request vector */
+{
+/* Read or write one the driver's minor devices. */
+  phys_bytes mem_phys;
+  int seg;
+  unsigned count, left, chunk;
+  vir_bytes user_vir;
+  struct device *dv;
+  unsigned long dv_size;
+  int s;
+
+  /* Get minor device number and check for /dev/null. */
+  dv = &m_geom[m_device];
+  dv_size = cv64ul(dv->dv_size);
+
+  while (nr_req > 0) {
+
+	/* How much to transfer and where to / from. */
+	count = iov->iov_size;
+	user_vir = iov->iov_addr;
+
+	switch (m_device) {
+
+	/* No copying; ignore request. */
+	case NULL_DEV:
+	    if (opcode == DEV_GATHER) return(OK);	/* always at EOF */
+	    break;
+
+	/* Virtual copying. For RAM disk, kernel memory and boot device. */
+	case RAM_DEV:
+	case KMEM_DEV:
+	case BOOT_DEV:
+	    if (position >= dv_size) return(OK); 	/* check for EOF */
+	    if (position + count > dv_size) count = dv_size - position;
+	    seg = m_seg[m_device];
+
+	    if (opcode == DEV_GATHER) {			/* copy actual data */
+	        sys_vircopy(SELF,seg,position, proc_nr,D,user_vir, count);
+	    } else {
+	        sys_vircopy(proc_nr,D,user_vir, SELF,seg,position, count);
+	    }
+	    break;
+
+	/* Physical copying. Only used to access entire memory. */
+	case MEM_DEV:
+	    if (position >= dv_size) return(OK); 	/* check for EOF */
+	    if (position + count > dv_size) count = dv_size - position;
+	    mem_phys = cv64ul(dv->dv_base) + position;
+
+	    if (opcode == DEV_GATHER) {			/* copy data */
+	        sys_physcopy(NONE, PHYS_SEG, mem_phys, 
+	        	proc_nr, D, user_vir, count);
+	    } else {
+	        sys_physcopy(proc_nr, D, user_vir, 
+	        	NONE, PHYS_SEG, mem_phys, count);
+	    }
+	    break;
+
+	/* Null byte stream generator. */
+	case ZERO_DEV:
+	    if (opcode == DEV_GATHER) {
+	        left = count;
+	    	while (left > 0) {
+	    	    chunk = (left > ZERO_BUF_SIZE) ? ZERO_BUF_SIZE : left;
+	    	    if (OK != (s=sys_vircopy(SELF, D, (vir_bytes) dev_zero, 
+	    	            proc_nr, D, user_vir, chunk)))
+	    	        report("MEM","sys_vircopy failed", s);
+	    	    left -= chunk;
+ 	            user_vir += chunk;
+	    	}
+	    }
+	    break;
+
+	case IMGRD_DEV:
+	    if (position >= dv_size) return(OK); 	/* check for EOF */
+	    if (position + count > dv_size) count = dv_size - position;
+
+	    if (opcode == DEV_GATHER) {			/* copy actual data */
+	        sys_vircopy(SELF, D, (vir_bytes)&imgrd[position],
+			proc_nr, D, user_vir, count);
+	    } else {
+	        sys_vircopy(proc_nr, D, user_vir,
+			SELF, D, (vir_bytes)&imgrd[position], count);
+	    }
+	    break;
+
+	/* Unknown (illegal) minor device. */
+	default:
+	    return(EINVAL);
+	}
+
+	/* Book the number of bytes transferred. */
+	position += count;
+	iov->iov_addr += count;
+  	if ((iov->iov_size -= count) == 0) { iov++; nr_req--; }
+
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *				m_do_open				     *
+ *===========================================================================*/
+PRIVATE int m_do_open(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+  int r;
+
+/* Check device number on open. */
+  if (m_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
+  if (m_device == MEM_DEV)
+  {
+	r = sys_enable_iop(m_ptr->IO_ENDPT);
+	if (r != OK)
+	{
+		printf("m_do_open: sys_enable_iop failed for %d: %d\n",
+			m_ptr->IO_ENDPT, r);
+		return r;
+	}
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *				m_init					     *
+ *===========================================================================*/
+PRIVATE void m_init()
+{
+  /* Initialize this task. All minor devices are initialized one by one. */
+  phys_bytes ramdev_size;
+  phys_bytes ramdev_base;
+  message m;
+  int i, s;
+
+  if (OK != (s=sys_getkinfo(&kinfo))) {
+      panic("MEM","Couldn't get kernel information.",s);
+  }
+
+  /* Install remote segment for /dev/kmem memory. */
+  m_geom[KMEM_DEV].dv_base = cvul64(kinfo.kmem_base);
+  m_geom[KMEM_DEV].dv_size = cvul64(kinfo.kmem_size);
+  if (OK != (s=sys_segctl(&m_seg[KMEM_DEV], (u16_t *) &s, (vir_bytes *) &s, 
+  		kinfo.kmem_base, kinfo.kmem_size))) {
+      panic("MEM","Couldn't install remote segment.",s);
+  }
+
+  /* Install remote segment for /dev/boot memory, if enabled. */
+  m_geom[BOOT_DEV].dv_base = cvul64(kinfo.bootdev_base);
+  m_geom[BOOT_DEV].dv_size = cvul64(kinfo.bootdev_size);
+  if (kinfo.bootdev_base > 0) {
+      if (OK != (s=sys_segctl(&m_seg[BOOT_DEV], (u16_t *) &s, (vir_bytes *) &s, 
+              kinfo.bootdev_base, kinfo.bootdev_size))) {
+          panic("MEM","Couldn't install remote segment.",s);
+      }
+  }
+
+  /* See if there are already RAM disk details at the Data Store server. */
+  m.DS_KEY = MEMORY_MAJOR;
+  if (OK == (s = _taskcall(DS_PROC_NR, DS_RETRIEVE, &m))) {
+  	ramdev_size = m.DS_VAL_L1;
+ 	ramdev_base = m.DS_VAL_L2;
+  	printf("MEM retrieved size %u and base %u from DS, status %d\n",
+    		ramdev_size, ramdev_base, s);
+  	if (OK != (s=sys_segctl(&m_seg[RAM_DEV], (u16_t *) &s, 
+		(vir_bytes *) &s, ramdev_base, ramdev_size))) {
+      		panic("MEM","Couldn't install remote segment.",s);
+  	}
+  	m_geom[RAM_DEV].dv_base = cvul64(ramdev_base);
+ 	m_geom[RAM_DEV].dv_size = cvul64(ramdev_size);
+	printf("MEM stored retrieved details as new RAM disk\n");
+  }
+
+  /* Ramdisk image built into the memory driver */
+  m_geom[IMGRD_DEV].dv_base= cvul64(0);
+  m_geom[IMGRD_DEV].dv_size= cvul64(imgrd_size);
+
+  /* Initialize /dev/zero. Simply write zeros into the buffer. */
+  for (i=0; i<ZERO_BUF_SIZE; i++) {
+       dev_zero[i] = '\0';
+  }
+
+  /* Set up memory ranges for /dev/mem. */
+#if (CHIP == INTEL)
+  if (OK != (s=sys_getmachine(&machine))) {
+      panic("MEM","Couldn't get machine information.",s);
+  }
+  if (! machine.prot) {
+	m_geom[MEM_DEV].dv_size =   cvul64(0x100000); /* 1M for 8086 systems */
+  } else {
+#if _WORD_SIZE == 2
+	m_geom[MEM_DEV].dv_size =  cvul64(0x1000000); /* 16M for 286 systems */
+#else
+	m_geom[MEM_DEV].dv_size = cvul64(0xFFFFFFFF); /* 4G-1 for 386 systems */
+#endif
+  }
+#else /* !(CHIP == INTEL) */
+#if (CHIP == M68000)
+  m_geom[MEM_DEV].dv_size = cvul64(MEM_BYTES);
+#else /* !(CHIP == M68000) */
+#error /* memory limit not set up */
+#endif /* !(CHIP == M68000) */
+#endif /* !(CHIP == INTEL) */
+}
+
+/*===========================================================================*
+ *				m_ioctl					     *
+ *===========================================================================*/
+PRIVATE int m_ioctl(dp, m_ptr)
+struct driver *dp;			/* pointer to driver structure */
+message *m_ptr;				/* pointer to control message */
+{
+/* I/O controls for the memory driver. Currently there is one I/O control:
+ * - MIOCRAMSIZE: to set the size of the RAM disk.
+ */
+  struct device *dv;
+
+  switch (m_ptr->REQUEST) {
+    case MIOCRAMSIZE: {
+	/* Someone wants to create a new RAM disk with the given size. */
+	static int first_time= 1;
+
+	u32_t ramdev_size;
+	phys_bytes ramdev_base;
+	message m;
+	int s;
+
+	/* A ramdisk can be created only once, and only on RAM disk device. */
+	if (!first_time) return(EPERM);
+	if (m_ptr->DEVICE != RAM_DEV) return(EINVAL);
+        if ((dv = m_prepare(m_ptr->DEVICE)) == NIL_DEV) return(ENXIO);
+
+#if 0
+	ramdev_size= m_ptr->POSITION;
+#else
+	/* Get request structure */
+	s= sys_vircopy(m_ptr->IO_ENDPT, D, (vir_bytes)m_ptr->ADDRESS,
+		SELF, D, (vir_bytes)&ramdev_size, sizeof(ramdev_size));
+	if (s != OK)
+		return s;
+#endif
+
+#if DEBUG
+	printf("allocating ramdisk of size 0x%x\n", ramdev_size);
+#endif
+
+	/* Try to allocate a piece of memory for the RAM disk. */
+        if (allocmem(ramdev_size, &ramdev_base) < 0) {
+            report("MEM", "warning, allocmem failed", errno);
+            return(ENOMEM);
+        }
+
+	/* Store the values we got in the data store so we can retrieve
+	 * them later on, in the unfortunate event of a crash.
+	 */
+	m.DS_KEY = MEMORY_MAJOR;
+	m.DS_VAL_L1 = ramdev_size;
+	m.DS_VAL_L2 = ramdev_base;
+	if (OK != (s = _taskcall(DS_PROC_NR, DS_PUBLISH, &m))) {
+      		panic("MEM","Couldn't store RAM disk details at DS.",s);
+	}
+#if DEBUG
+	printf("MEM stored size %u and base %u at DS, status %d\n",
+	    ramdev_size, ramdev_base, s);
+#endif
+
+  	if (OK != (s=sys_segctl(&m_seg[RAM_DEV], (u16_t *) &s, 
+		(vir_bytes *) &s, ramdev_base, ramdev_size))) {
+      		panic("MEM","Couldn't install remote segment.",s);
+  	}
+
+	dv->dv_base = cvul64(ramdev_base);
+	dv->dv_size = cvul64(ramdev_size);
+	/* first_time= 0; */
+	break;
+    }
+    case MIOCMAP:
+    case MIOCUNMAP: {
+    	int r, do_map;
+    	struct mapreq mapreq;
+
+	if ((*dp->dr_prepare)(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
+    	if (m_device != MEM_DEV)
+    		return ENOTTY;
+
+	do_map= (m_ptr->REQUEST == MIOCMAP);	/* else unmap */
+
+	/* Get request structure */
+	r= sys_vircopy(m_ptr->IO_ENDPT, D, (vir_bytes)m_ptr->ADDRESS,
+		SELF, D, (vir_bytes)&mapreq, sizeof(mapreq));
+	if (r != OK)
+		return r;
+	r= sys_vm_map(m_ptr->IO_ENDPT, do_map,
+		(phys_bytes)mapreq.base, mapreq.size, mapreq.offset);
+	return r;
+    }
+
+    default:
+  	return(do_diocntl(&m_dtab, m_ptr));
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *				m_geometry				     *
+ *===========================================================================*/
+PRIVATE void m_geometry(entry)
+struct partition *entry;
+{
+  /* Memory devices don't have a geometry, but the outside world insists. */
+  entry->cylinders = div64u(m_geom[m_device].dv_size, SECTOR_SIZE) / (64 * 32);
+  entry->heads = 64;
+  entry->sectors = 32;
+}
+
Index: /trunk/minix/drivers/memory/ramdisk/.depend
===================================================================
--- /trunk/minix/drivers/memory/ramdisk/.depend	(revision 9)
+++ /trunk/minix/drivers/memory/ramdisk/.depend	(revision 9)
@@ -0,0 +1,11 @@
+
+bintoc.o:	/usr/include/ansi.h
+bintoc.o:	/usr/include/errno.h
+bintoc.o:	/usr/include/stdarg.h
+bintoc.o:	/usr/include/stdio.h
+bintoc.o:	/usr/include/stdlib.h
+bintoc.o:	/usr/include/string.h
+bintoc.o:	/usr/include/sys/dir.h
+bintoc.o:	/usr/include/sys/types.h
+bintoc.o:	/usr/include/unistd.h
+bintoc.o:	bintoc.c
Index: /trunk/minix/drivers/memory/ramdisk/Makefile
===================================================================
--- /trunk/minix/drivers/memory/ramdisk/Makefile	(revision 9)
+++ /trunk/minix/drivers/memory/ramdisk/Makefile	(revision 9)
@@ -0,0 +1,101 @@
+# Makefile for ramdisk image
+
+PROGRAMS=at_wini bios_wini cdprobe dev2name floppy loadramdisk newroot \
+	pci sh service sysenv
+
+MAKEDEV=/usr/bin/MAKEDEV
+
+all:	image.c image.s
+
+clean:
+	rm -rf $(PROGRAMS) bintoc image image.c t proto.gen
+
+image.c:	bintoc image
+	./bintoc -o $@ image
+
+image.s:	image.c
+	sed < image.c > $@ 's/^/.data1 /;s/,$$//' || { rm -f $@; false; }
+
+# Note for cross compilation: this executable has to be compiled for the
+# host system
+bintoc:	bintoc.c
+	$(CC) -o $@ bintoc.c
+
+image:	proto.gen mtab rc $(PROGRAMS)
+	mkfs -B 2048 image proto.gen || { rm -f image; false; }
+
+at_wini: ../../at_wini/at_wini
+	install -s ../../$@/$@ $@
+
+../../at_wini/at_wini:
+	cd ../../at_wini && make
+
+bios_wini: ../../bios_wini/bios_wini
+	install -s ../../$@/$@ $@
+
+../../bios_wini/bios_wini:
+	cd ../../bios_wini && make
+
+floppy: ../../floppy/floppy
+	install -s ../../$@/$@ $@
+
+../../floppy/floppy:
+	cd ../../floppy && make
+
+pci: ../../pci/pci
+	install -s ../../$@/$@ $@
+
+../../pci/pci:
+	cd ../../pci && make
+
+cdprobe:  ../../../commands/simple/cdprobe
+	install -s ../../../commands/simple/$@ $@
+
+../../../commands/simple/cdprobe: 
+	cd ../../../commands/simple && make cdprobe
+
+dev2name:  ../../../commands/simple/dev2name
+	install -s ../../../commands/simple/$@ $@
+
+../../../commands/simple/dev2name: 
+	cd ../../../commands/simple && make dev2name
+
+loadramdisk:  ../../../commands/simple/loadramdisk
+	install -s ../../../commands/simple/$@ $@
+
+../../../commands/simple/loadramdisk: 
+	cd ../../../commands/simple && make loadramdisk
+
+newroot:  ../../../commands/simple/newroot
+	install -s ../../../commands/simple/$@ $@
+
+../../../commands/simple/newroot: 
+	cd ../../../commands/simple && make newroot
+
+sysenv:  ../../../commands/simple/sysenv
+	install -s ../../../commands/simple/$@ $@
+
+../../../commands/simple/sysenv: 
+	cd ../../../commands/simple && make sysenv
+
+sh:	../../../commands/ash/sh
+	install -s ../../../commands/ash/$@ $@
+
+../../../commands/ash/sh: 
+	cd ../../../commands/ash && make sh
+
+service: ../../../servers/rs/service
+	install -s ../../../servers/rs/$@ $@
+
+../../../servers/rs/service: 
+	cd ../../../servers/rs && make service
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+proto.gen: $(MAKEDEV) proto.sh proto
+	sh -e proto.sh >proto.gen
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/memory/ramdisk/bintoc.c
===================================================================
--- /trunk/minix/drivers/memory/ramdisk/bintoc.c	(revision 9)
+++ /trunk/minix/drivers/memory/ramdisk/bintoc.c	(revision 9)
@@ -0,0 +1,129 @@
+/*
+bintoc.c
+
+Convert a (binary) file to a series of comma separated hex values suitable
+for initializing a character array in C.
+*/
+
+#define _POSIX_C_SOURCE 2
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+char *progname;
+unsigned char buf[1024];
+
+static void fatal(char *fmt, ...);
+static void usage(void);
+
+int main(int argc, char *argv[])
+{
+	int c, i, r, first;
+	FILE *file_in, *file_out;
+	char *in_name;
+	char *o_arg;
+
+	(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
+
+	o_arg= NULL;
+	while (c= getopt(argc, argv, "?o:"), c != -1)
+	{
+		switch(c)
+		{
+		case '?': usage();
+		case 'o': o_arg= optarg; break;
+		default:  fatal("getopt failed: '%c'\n", c);
+		}
+	}
+
+	if (o_arg)
+	{
+		file_out= fopen(o_arg, "w");
+		if (file_out == NULL)
+		{
+			fatal("unable to create '%s': %s\n",
+				o_arg, strerror(errno));
+			exit(1);
+		}
+	}
+	else
+		file_out= stdout;
+
+	if (optind < argc)
+	{
+		in_name= argv[optind];
+		optind++;
+		file_in= fopen(in_name, "r");
+		if (file_in == NULL)
+		{
+			fatal("unable to open '%s': %s",
+				in_name, strerror(errno));
+		}
+	}
+	else
+	{
+		in_name= "(stdin)";
+		file_in= stdin;
+	}
+
+	if (optind != argc)
+		usage();
+
+	first= 1;
+	for (;;)
+	{
+		r= fread(buf, 1, sizeof(buf), file_in);
+		if (r == 0)
+			break;
+		for (i= 0; i<r; i++)
+		{
+			if ((i % 8) == 0)
+			{
+				if (first)
+				{
+					fprintf(file_out, "\t");
+					first= 0;
+				}
+				else
+					fprintf(file_out, ",\n\t");
+			}
+			else
+				fprintf(file_out, ", ");
+			fprintf(file_out, "0x%02x", buf[i]);
+		}
+	}
+
+	if (ferror(file_in))
+	{
+		fatal("read error on %s: %s\n",
+			in_name, strerror(errno));
+	}
+	fprintf(file_out, "\n");
+
+	exit(0);
+}
+
+static void fatal(char *fmt, ...)
+{
+	va_list ap;
+
+	fprintf(stderr, "%s: ", progname);
+
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+
+	fprintf(stderr, "\n");
+
+	exit(1);
+}
+
+static void usage(void)
+{
+	fprintf(stderr, "Usage: bintoc [-o <out-file>] [<in-file>]\n");
+	exit(1);
+}
Index: /trunk/minix/drivers/memory/ramdisk/image.s
===================================================================
--- /trunk/minix/drivers/memory/ramdisk/image.s	(revision 9)
+++ /trunk/minix/drivers/memory/ramdisk/image.s	(revision 9)
@@ -0,0 +1,35840 @@
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x36, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
+.data1 	0x01, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x38, 0x10, 0x20, 0x8c, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x4d, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+.data1 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+.data1 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+.data1 	0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+.data1 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x41, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x41, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x90, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x59, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00
+.data1 	0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00
+.data1 	0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00
+.data1 	0x16, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4c, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x59, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
+.data1 	0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00
+.data1 	0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x54, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x3c, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00
+.data1 	0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00
+.data1 	0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x34, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x3c, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x2a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00
+.data1 	0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x08, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x59, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00
+.data1 	0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00
+.data1 	0x33, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x10, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x3e, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00
+.data1 	0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00
+.data1 	0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x84, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x3f, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00
+.data1 	0x3c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe4, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x59, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x3e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00
+.data1 	0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00
+.data1 	0x42, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00
+.data1 	0x44, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x24, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x34, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4f, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00
+.data1 	0x51, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00
+.data1 	0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00
+.data1 	0x55, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x58, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x75, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00
+.data1 	0x77, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
+.data1 	0x79, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc0, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x40, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x7b, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x41, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x7d, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00
+.data1 	0x7f, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00
+.data1 	0x81, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00
+.data1 	0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x81, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x82, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x83, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x84, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x86, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x88, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x89, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8a, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x05, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x90, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x91, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x92, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x93, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x94, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x95, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x96, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x97, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x98, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x99, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x9a, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x9b, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x09, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x9d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x9e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x9f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0a, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0b, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xaa, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xab, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xac, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xad, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xae, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xaf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x10, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x12, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xba, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xbb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x13, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xbc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xbd, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xbe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xbf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x14, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x16, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x17, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xca, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xcb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x18, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xcc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xcd, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xce, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xcf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x1a, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x1b, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x1c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xda, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xdb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xdc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xdd, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xde, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xdf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x1e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xea, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x22, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xec, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xef, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x23, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x24, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xf1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xf2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xf3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x25, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xf4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xf5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xf6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xf7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xf9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xfa, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xfb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x27, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xfd, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x21, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x21, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb6, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb0, 0x21, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x7f, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb0, 0x21, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x7e, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x21, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa0, 0x21, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x92, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x20, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa0, 0x21, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb6, 0x21, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x61, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa4, 0x21, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa4, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb6, 0x21, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb6, 0x21, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb6, 0x21, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb6, 0x21, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x12, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb6, 0x21, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x13, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x21, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x21, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x21, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa4, 0x21, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x21, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x7d, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa4, 0x21, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x41, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x3f, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa4, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xfc, 0x0d, 0xf3, 0x43, 0x00, 0x00, 0x00, 0x00
+.data1 	0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xed, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x27, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8a, 0x9f, 0x0d, 0x44, 0x00, 0x00, 0x00, 0x00
+.data1 	0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x62, 0x69, 0x6e, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0e, 0x00, 0x00, 0x00, 0x64, 0x65, 0x76, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd1, 0x00, 0x00, 0x00, 0x65, 0x74, 0x63, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x03, 0x00, 0x00, 0x00, 0x61, 0x74, 0x5f, 0x77
+.data1 	0x69, 0x6e, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x04, 0x00, 0x00, 0x00, 0x62, 0x69, 0x6f, 0x73
+.data1 	0x5f, 0x77, 0x69, 0x6e, 0x69, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x05, 0x00, 0x00, 0x00, 0x63, 0x64, 0x70, 0x72
+.data1 	0x6f, 0x62, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x06, 0x00, 0x00, 0x00, 0x64, 0x65, 0x76, 0x32
+.data1 	0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x07, 0x00, 0x00, 0x00, 0x66, 0x6c, 0x6f, 0x70
+.data1 	0x70, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x08, 0x00, 0x00, 0x00, 0x6c, 0x6f, 0x61, 0x64
+.data1 	0x72, 0x61, 0x6d, 0x64, 0x69, 0x73, 0x6b, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x09, 0x00, 0x00, 0x00, 0x6e, 0x65, 0x77, 0x72
+.data1 	0x6f, 0x6f, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x70, 0x63, 0x69, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0b, 0x00, 0x00, 0x00, 0x73, 0x68, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0c, 0x00, 0x00, 0x00, 0x73, 0x65, 0x72, 0x76
+.data1 	0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0d, 0x00, 0x00, 0x00, 0x73, 0x79, 0x73, 0x65
+.data1 	0x6e, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x03, 0x20, 0x10, 0x20, 0x00, 0x00, 0x00
+.data1 	0x50, 0x55, 0x00, 0x00, 0x20, 0x15, 0x00, 0x00
+.data1 	0x80, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa0, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0xed, 0x8b, 0x04, 0x24, 0x8d, 0x54, 0x24
+.data1 	0x04, 0x8d, 0x4c, 0x84, 0x08, 0xbb, 0x0c, 0x14
+.data1 	0x00, 0x00, 0x81, 0xfb, 0x20, 0x15, 0x00, 0x00
+.data1 	0x73, 0x13, 0xf6, 0xc3, 0x03, 0x75, 0x0e, 0x81
+.data1 	0x3b, 0x53, 0x53, 0x53, 0x53, 0x75, 0x06, 0x89
+.data1 	0x1d, 0xac, 0x12, 0x00, 0x00, 0x8b, 0x1d, 0xac
+.data1 	0x12, 0x00, 0x00, 0x89, 0x0b, 0x51, 0x52, 0x50
+.data1 	0x0f, 0x01, 0xe0, 0xa8, 0x04, 0x0f, 0x94, 0x05
+.data1 	0x0c, 0xdd, 0x00, 0x00, 0xe8, 0x07, 0x00, 0x00
+.data1 	0x00, 0x50, 0xe8, 0x86, 0x4c, 0x00, 0x00, 0xf4
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c, 0xc7, 0x45
+.data1 	0xf4, 0x04, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xf8
+.data1 	0x50, 0xe8, 0xc6, 0x4f, 0x00, 0x00, 0x59, 0xc7
+.data1 	0x45, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x00
+.data1 	0x8d, 0x45, 0xf4, 0x50, 0x6a, 0x0f, 0xe8, 0xa9
+.data1 	0x4f, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0
+.data1 	0x79, 0x18, 0xff, 0x35, 0x10, 0x14, 0x00, 0x00
+.data1 	0x68, 0x04, 0x00, 0x00, 0x00, 0x68, 0x18, 0x00
+.data1 	0x00, 0x00, 0xe8, 0x9d, 0x46, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xe8, 0x1a, 0x00, 0x00, 0x00, 0x6a
+.data1 	0x01, 0x6a, 0x0f, 0xe8, 0x50, 0x4c, 0x00, 0x00
+.data1 	0x59, 0x59, 0x68, 0xf0, 0x12, 0x00, 0x00, 0xe8
+.data1 	0xd0, 0x34, 0x00, 0x00, 0x59, 0x31, 0xc0, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x56
+.data1 	0x57, 0x6a, 0x01, 0x6a, 0x00, 0x68, 0xbc, 0x12
+.data1 	0x00, 0x00, 0x6a, 0x00, 0x68, 0x08, 0x01, 0x00
+.data1 	0x00, 0x68, 0x0c, 0x01, 0x00, 0x00, 0xe8, 0x05
+.data1 	0x3d, 0x00, 0x00, 0x83, 0xc4, 0x18, 0x6a, 0x01
+.data1 	0x6a, 0x00, 0x68, 0xc0, 0x12, 0x00, 0x00, 0x6a
+.data1 	0x00, 0x68, 0xf4, 0x00, 0x00, 0x00, 0x68, 0xf8
+.data1 	0x00, 0x00, 0x00, 0xe8, 0xe8, 0x3c, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x18, 0x6a, 0x08, 0x6a, 0x00, 0x68
+.data1 	0xc4, 0x12, 0x00, 0x00, 0x6a, 0x00, 0x68, 0xe0
+.data1 	0x00, 0x00, 0x00, 0x68, 0xe4, 0x00, 0x00, 0x00
+.data1 	0xe8, 0xcb, 0x3c, 0x00, 0x00, 0x83, 0xc4, 0x18
+.data1 	0x6a, 0x01, 0x6a, 0x00, 0x68, 0xc8, 0x12, 0x00
+.data1 	0x00, 0x6a, 0x00, 0x68, 0xd0, 0x00, 0x00, 0x00
+.data1 	0x68, 0xd4, 0x00, 0x00, 0x00, 0xe8, 0xae, 0x3c
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x18, 0x6a, 0x01, 0x6a
+.data1 	0x00, 0x68, 0xcc, 0x12, 0x00, 0x00, 0x6a, 0x00
+.data1 	0x68, 0xc0, 0x00, 0x00, 0x00, 0x68, 0xc4, 0x00
+.data1 	0x00, 0x00, 0xe8, 0x91, 0x3c, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x18, 0x83, 0x3d, 0xc8, 0x12, 0x00, 0x00
+.data1 	0x00, 0x74, 0x0b, 0x68, 0x9c, 0x00, 0x00, 0x00
+.data1 	0xe8, 0x23, 0x3f, 0x00, 0x00, 0x59, 0x68, 0x80
+.data1 	0xa2, 0x00, 0x00, 0x68, 0x00, 0x80, 0x00, 0x00
+.data1 	0x68, 0x80, 0x22, 0x00, 0x00, 0x6a, 0x01, 0x68
+.data1 	0xce, 0x8a, 0x00, 0x00, 0xe8, 0x33, 0x4a, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x14, 0x89, 0xc6, 0x85, 0xf6
+.data1 	0x74, 0x13, 0x56, 0x68, 0x7c, 0x00, 0x00, 0x00
+.data1 	0x68, 0x94, 0x00, 0x00, 0x00, 0xe8, 0x9a, 0x45
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x68, 0x84, 0xc2
+.data1 	0x00, 0x00, 0x68, 0x00, 0x20, 0x00, 0x00, 0x68
+.data1 	0x84, 0xa2, 0x00, 0x00, 0x6a, 0x01, 0x68, 0xce
+.data1 	0x8a, 0x00, 0x00, 0xe8, 0xfc, 0x49, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x14, 0x89, 0xc6, 0x85, 0xf6, 0x74
+.data1 	0x13, 0x56, 0x68, 0x60, 0x00, 0x00, 0x00, 0x68
+.data1 	0x74, 0x00, 0x00, 0x00, 0xe8, 0x63, 0x45, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x83, 0x3d, 0xc4, 0x12
+.data1 	0x00, 0x00, 0x00, 0x0f, 0x85, 0x8a, 0x01, 0x00
+.data1 	0x00, 0x6a, 0x01, 0x8d, 0x45, 0xd8, 0x50, 0x6a
+.data1 	0x01, 0x68, 0xce, 0x8a, 0x00, 0x00, 0x68, 0x75
+.data1 	0x04, 0x00, 0x00, 0x68, 0x00, 0x02, 0x00, 0x00
+.data1 	0x68, 0xce, 0x8a, 0x00, 0x00, 0xe8, 0x2e, 0x4a
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x1c, 0x89, 0xc6, 0x85
+.data1 	0xc0, 0x74, 0x14, 0x56, 0x68, 0x4c, 0x00, 0x00
+.data1 	0x00, 0xe8, 0xa4, 0x0f, 0x00, 0x00, 0x50, 0xe8
+.data1 	0x18, 0x45, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x0f
+.data1 	0xb6, 0x55, 0xd8, 0x89, 0x55, 0xec, 0x83, 0xfa
+.data1 	0x02, 0x7e, 0x07, 0xc7, 0x45, 0xec, 0x02, 0x00
+.data1 	0x00, 0x00, 0x31, 0xff, 0xc7, 0x45, 0xe8, 0x20
+.data1 	0x15, 0x00, 0x00, 0x83, 0xff, 0x04, 0x0f, 0x8d
+.data1 	0x27, 0x01, 0x00, 0x00, 0x39, 0x7d, 0xec, 0x0f
+.data1 	0x8e, 0xd3, 0x00, 0x00, 0x00, 0x85, 0xff, 0x75
+.data1 	0x07, 0xb8, 0x04, 0x01, 0x00, 0x00, 0xeb, 0x05
+.data1 	0xb8, 0x18, 0x01, 0x00, 0x00, 0x89, 0x45, 0xf8
+.data1 	0x85, 0xff, 0x75, 0x07, 0xb8, 0x04, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x05, 0xb8, 0x04, 0x00, 0x00, 0x00
+.data1 	0x89, 0x45, 0xf4, 0x50, 0x8d, 0x45, 0xfc, 0x50
+.data1 	0x6a, 0x01, 0x68, 0xce, 0x8a, 0x00, 0x00, 0xff
+.data1 	0x75, 0xf8, 0x68, 0x00, 0x02, 0x00, 0x00, 0x68
+.data1 	0xce, 0x8a, 0x00, 0x00, 0xe8, 0x9f, 0x49, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x1c, 0x89, 0xc6, 0x85, 0xc0
+.data1 	0x74, 0x14, 0x56, 0x68, 0x38, 0x00, 0x00, 0x00
+.data1 	0xe8, 0x15, 0x0f, 0x00, 0x00, 0x50, 0xe8, 0x89
+.data1 	0x44, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x0f, 0xb7
+.data1 	0x55, 0xfe, 0xc1, 0xe2, 0x04, 0x0f, 0xb7, 0x4d
+.data1 	0xfc, 0x01, 0xd1, 0x6a, 0x10, 0x8d, 0x45, 0xd8
+.data1 	0x50, 0x6a, 0x01, 0x68, 0xce, 0x8a, 0x00, 0x00
+.data1 	0x51, 0x68, 0x00, 0x02, 0x00, 0x00, 0x68, 0xce
+.data1 	0x8a, 0x00, 0x00, 0xe8, 0x58, 0x49, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x1c, 0x89, 0xc6, 0x85, 0xc0, 0x74
+.data1 	0x14, 0x56, 0x68, 0x1c, 0x00, 0x00, 0x00, 0xe8
+.data1 	0xce, 0x0e, 0x00, 0x00, 0x50, 0xe8, 0x42, 0x44
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55, 0xe8
+.data1 	0x0f, 0xb7, 0x4d, 0xd8, 0x89, 0x4a, 0x2c, 0x8b
+.data1 	0x55, 0xe8, 0x0f, 0xb6, 0x4d, 0xda, 0x89, 0x4a
+.data1 	0x30, 0x8b, 0x55, 0xe8, 0x0f, 0xb6, 0x4d, 0xe6
+.data1 	0x89, 0x4a, 0x34, 0x0f, 0xb7, 0x55, 0xdd, 0xc1
+.data1 	0xfa, 0x02, 0x8b, 0x4d, 0xe8, 0x89, 0x51, 0x48
+.data1 	0x57, 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0x6a
+.data1 	0x00, 0x83, 0xff, 0x02, 0x7d, 0x07, 0xb8, 0xf6
+.data1 	0x03, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0x76, 0x03
+.data1 	0x00, 0x00, 0x50, 0x83, 0xff, 0x02, 0x7d, 0x07
+.data1 	0xb8, 0xf0, 0x01, 0x00, 0x00, 0xeb, 0x05, 0xb8
+.data1 	0x70, 0x01, 0x00, 0x00, 0x50, 0xff, 0x75, 0xe8
+.data1 	0xe8, 0x3d, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x20
+.data1 	0xff, 0x05, 0xd8, 0x12, 0x00, 0x00, 0x47, 0x81
+.data1 	0x45, 0xe8, 0xa4, 0x01, 0x00, 0x00, 0xe9, 0xd0
+.data1 	0xfe, 0xff, 0xff, 0x83, 0x3d, 0xc4, 0x12, 0x00
+.data1 	0x00, 0x00, 0x75, 0x0a, 0x6a, 0x00, 0xe8, 0x82
+.data1 	0x00, 0x00, 0x00, 0x59, 0xeb, 0x10, 0x8b, 0x15
+.data1 	0xc4, 0x12, 0x00, 0x00, 0xd1, 0xe2, 0x4a, 0x52
+.data1 	0xe8, 0x70, 0x00, 0x00, 0x00, 0x59, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b, 0x75
+.data1 	0x08, 0xc7, 0x06, 0x00, 0x00, 0x00, 0x00, 0x66
+.data1 	0xc7, 0x46, 0x04, 0x00, 0x00, 0x8b, 0x55, 0x0c
+.data1 	0x89, 0x56, 0x08, 0x8b, 0x55, 0x10, 0x89, 0x56
+.data1 	0x0c, 0x8b, 0x55, 0x14, 0x89, 0x56, 0x10, 0x8b
+.data1 	0x55, 0x18, 0x89, 0x56, 0x14, 0x8b, 0x4d, 0x18
+.data1 	0xba, 0x01, 0x00, 0x00, 0x00, 0xd3, 0xe2, 0x89
+.data1 	0x56, 0x18, 0x8b, 0x55, 0x1c, 0x89, 0x56, 0x1c
+.data1 	0x8b, 0x55, 0x20, 0x89, 0x56, 0x20, 0x8b, 0x55
+.data1 	0x24, 0xc1, 0xe2, 0x04, 0x81, 0xca, 0xa0, 0x00
+.data1 	0x00, 0x00, 0x89, 0x56, 0x44, 0xc7, 0x46, 0x4c
+.data1 	0x00, 0x00, 0x02, 0x00, 0xc7, 0x46, 0x24, 0x00
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x46, 0x28, 0x00, 0x00
+.data1 	0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x34, 0x56, 0x57, 0xe8, 0xf2, 0x44
+.data1 	0x00, 0x00, 0x8b, 0x15, 0xd8, 0x12, 0x00, 0x00
+.data1 	0x89, 0x55, 0xf0, 0x83, 0x7d, 0xf0, 0x08, 0x7d
+.data1 	0x16, 0x69, 0x45, 0xf0, 0xa4, 0x01, 0x00, 0x00
+.data1 	0xc7, 0x80, 0x20, 0x15, 0x00, 0x00, 0x20, 0x00
+.data1 	0x00, 0x00, 0xff, 0x45, 0xf0, 0xeb, 0xe4, 0x8d
+.data1 	0x45, 0xdc, 0x50, 0x8d, 0x45, 0xde, 0x50, 0x8d
+.data1 	0x45, 0xf4, 0x50, 0xe8, 0x30, 0x44, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x45, 0xf8, 0x83, 0x7d
+.data1 	0xf8, 0x00, 0x0f, 0x84, 0xef, 0x03, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x6a
+.data1 	0x0b, 0xff, 0x75, 0xf4, 0xe8, 0xa7, 0x43, 0x00
+.data1 	0x00, 0x59, 0x59, 0x88, 0x45, 0xe3, 0x6a, 0x0a
+.data1 	0xff, 0x75, 0xf4, 0xe8, 0x98, 0x43, 0x00, 0x00
+.data1 	0x59, 0x59, 0x88, 0x45, 0xe2, 0x6a, 0x09, 0xff
+.data1 	0x75, 0xf4, 0xe8, 0x89, 0x43, 0x00, 0x00, 0x59
+.data1 	0x59, 0x88, 0x45, 0xe1, 0x0f, 0xb6, 0x55, 0xe3
+.data1 	0xc1, 0xe2, 0x10, 0x0f, 0xb6, 0x4d, 0xe2, 0xc1
+.data1 	0xe1, 0x08, 0x09, 0xd1, 0x0f, 0xb6, 0x55, 0xe1
+.data1 	0x09, 0xca, 0x89, 0x55, 0xd4, 0x80, 0x7d, 0xe3
+.data1 	0x01, 0x75, 0x0a, 0x80, 0x7d, 0xe2, 0x01, 0x0f
+.data1 	0x84, 0x78, 0x00, 0x00, 0x00, 0x81, 0x7d, 0xd4
+.data1 	0x00, 0x04, 0x01, 0x00, 0x0f, 0x85, 0x69, 0x03
+.data1 	0x00, 0x00, 0x31, 0xf6, 0x0f, 0xb7, 0x14, 0xb5
+.data1 	0xe8, 0x12, 0x00, 0x00, 0x85, 0xd2, 0x74, 0x23
+.data1 	0x0f, 0xb7, 0x55, 0xde, 0x0f, 0xb7, 0x0c, 0xb5
+.data1 	0xe8, 0x12, 0x00, 0x00, 0x39, 0xd1, 0x75, 0x10
+.data1 	0x0f, 0xb7, 0x55, 0xdc, 0x0f, 0xb7, 0x0c, 0xb5
+.data1 	0xea, 0x12, 0x00, 0x00, 0x39, 0xd1, 0x74, 0x03
+.data1 	0x46, 0xeb, 0xd1, 0x0f, 0xb7, 0x14, 0xb5, 0xe8
+.data1 	0x12, 0x00, 0x00, 0x85, 0xd2, 0x75, 0x1c, 0x0f
+.data1 	0xb7, 0x45, 0xdc, 0x50, 0x0f, 0xb7, 0x45, 0xde
+.data1 	0x50, 0x68, 0x60, 0x02, 0x00, 0x00, 0xe8, 0x7d
+.data1 	0x3b, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xe9, 0x10
+.data1 	0x03, 0x00, 0x00, 0x68, 0x3c, 0x02, 0x00, 0x00
+.data1 	0xe8, 0x6b, 0x3b, 0x00, 0x00, 0x59, 0xc7, 0x45
+.data1 	0xe4, 0x01, 0x00, 0x00, 0x00, 0x6a, 0x3c, 0xff
+.data1 	0x75, 0xf4, 0xe8, 0xd9, 0x42, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0x45, 0xec, 0x83, 0x7d, 0xe4, 0x00
+.data1 	0x75, 0x0a, 0xf6, 0x45, 0xe1, 0x05, 0x0f, 0x84
+.data1 	0x92, 0x00, 0x00, 0x00, 0x83, 0x3d, 0xd8, 0x12
+.data1 	0x00, 0x00, 0x08, 0x0f, 0x8d, 0xd2, 0x02, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xec, 0x89, 0x55, 0xe8, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x7e, 0x20, 0x83, 0x3d, 0xc0
+.data1 	0x12, 0x00, 0x00, 0x00, 0x74, 0x0f, 0xff, 0x75
+.data1 	0x08, 0x68, 0x14, 0x02, 0x00, 0x00, 0xe8, 0x15
+.data1 	0x3b, 0x00, 0x00, 0x59, 0x59, 0xff, 0x4d, 0x08
+.data1 	0xe9, 0xa6, 0x02, 0x00, 0x00, 0x8d, 0x45, 0xe8
+.data1 	0x50, 0x6a, 0x00, 0xff, 0x75, 0xec, 0x6a, 0x01
+.data1 	0xe8, 0x0f, 0x45, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x89, 0xc7, 0x85, 0xc0, 0x74, 0x14, 0xff, 0x75
+.data1 	0xec, 0x68, 0xf0, 0x01, 0x00, 0x00, 0xe8, 0xe5
+.data1 	0x3a, 0x00, 0x00, 0x59, 0x59, 0xe9, 0x79, 0x02
+.data1 	0x00, 0x00, 0x8d, 0x45, 0xe8, 0x50, 0x6a, 0x00
+.data1 	0x6a, 0x00, 0x6a, 0x03, 0xe8, 0xe3, 0x44, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x10, 0x89, 0xc7, 0x85, 0xc0
+.data1 	0x74, 0x14, 0xff, 0x75, 0xec, 0x68, 0xc8, 0x01
+.data1 	0x00, 0x00, 0xe8, 0xb9, 0x3a, 0x00, 0x00, 0x59
+.data1 	0x59, 0xe9, 0x4d, 0x02, 0x00, 0x00, 0x6a, 0x20
+.data1 	0xff, 0x75, 0xf4, 0xe8, 0xc0, 0x41, 0x00, 0x00
+.data1 	0x59, 0x59, 0x25, 0xfc, 0xff, 0xff, 0xff, 0x89
+.data1 	0x45, 0xd8, 0x83, 0x7d, 0xe4, 0x00, 0x75, 0x0a
+.data1 	0xf6, 0x45, 0xe1, 0x01, 0x0f, 0x84, 0xd6, 0x00
+.data1 	0x00, 0x00, 0x6a, 0x10, 0xff, 0x75, 0xf4, 0xe8
+.data1 	0x9c, 0x41, 0x00, 0x00, 0x59, 0x59, 0xbf, 0xfc
+.data1 	0xff, 0xff, 0xff, 0x21, 0xc7, 0x6a, 0x14, 0xff
+.data1 	0x75, 0xf4, 0xe8, 0x89, 0x41, 0x00, 0x00, 0x59
+.data1 	0x59, 0x25, 0xfc, 0xff, 0xff, 0xff, 0x89, 0x45
+.data1 	0xcc, 0x81, 0xff, 0xf0, 0x01, 0x00, 0x00, 0x0f
+.data1 	0x84, 0x94, 0x00, 0x00, 0x00, 0x81, 0xff, 0x70
+.data1 	0x01, 0x00, 0x00, 0x0f, 0x84, 0x88, 0x00, 0x00
+.data1 	0x00, 0x05, 0x02, 0x00, 0x00, 0x00, 0x69, 0x1d
+.data1 	0xd8, 0x12, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00
+.data1 	0x6a, 0x00, 0xff, 0x75, 0xe8, 0x6a, 0x01, 0xff
+.data1 	0x75, 0xec, 0xff, 0x75, 0xd8, 0x50, 0x57, 0x81
+.data1 	0xc3, 0x20, 0x15, 0x00, 0x00, 0x53, 0xe8, 0x2f
+.data1 	0xfd, 0xff, 0xff, 0x83, 0xc4, 0x20, 0xba, 0x02
+.data1 	0x00, 0x00, 0x00, 0x03, 0x55, 0xcc, 0x8b, 0x0d
+.data1 	0xd8, 0x12, 0x00, 0x00, 0x41, 0x69, 0xc1, 0xa4
+.data1 	0x01, 0x00, 0x00, 0x6a, 0x01, 0xff, 0x75, 0xe8
+.data1 	0x6a, 0x01, 0xff, 0x75, 0xec, 0xff, 0x75, 0xd8
+.data1 	0x52, 0x57, 0x05, 0x20, 0x15, 0x00, 0x00, 0x50
+.data1 	0xe8, 0xfd, 0xfc, 0xff, 0xff, 0x83, 0xc4, 0x20
+.data1 	0x83, 0x3d, 0xc0, 0x12, 0x00, 0x00, 0x00, 0x74
+.data1 	0x17, 0xff, 0x75, 0xec, 0xff, 0x75, 0xcc, 0x57
+.data1 	0xff, 0x75, 0xf4, 0x68, 0xa8, 0x01, 0x00, 0x00
+.data1 	0xe8, 0xd3, 0x39, 0x00, 0x00, 0x83, 0xc4, 0x14
+.data1 	0x83, 0x05, 0xd8, 0x12, 0x00, 0x00, 0x02, 0xeb
+.data1 	0x3a, 0x57, 0x68, 0x74, 0x01, 0x00, 0x00, 0xe8
+.data1 	0xbc, 0x39, 0x00, 0x00, 0x59, 0x59, 0xeb, 0x2b
+.data1 	0x31, 0xf6, 0x83, 0xfe, 0x08, 0x7d, 0x24, 0x69
+.data1 	0xc6, 0xa4, 0x01, 0x00, 0x00, 0x81, 0xb8, 0x28
+.data1 	0x15, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x75
+.data1 	0x0f, 0x69, 0xc6, 0xa4, 0x01, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xd8, 0x89, 0x90, 0x30, 0x15, 0x00, 0x00
+.data1 	0x46, 0xeb, 0xd7, 0x83, 0x7d, 0xe4, 0x00, 0x75
+.data1 	0x0a, 0xf6, 0x45, 0xe1, 0x04, 0x0f, 0x84, 0xe2
+.data1 	0x00, 0x00, 0x00, 0x6a, 0x18, 0xff, 0x75, 0xf4
+.data1 	0xe8, 0x8b, 0x40, 0x00, 0x00, 0x59, 0x59, 0xbf
+.data1 	0xfc, 0xff, 0xff, 0xff, 0x21, 0xc7, 0x6a, 0x1c
+.data1 	0xff, 0x75, 0xf4, 0xe8, 0x78, 0x40, 0x00, 0x00
+.data1 	0x59, 0x59, 0x25, 0xfc, 0xff, 0xff, 0xff, 0x89
+.data1 	0x45, 0xcc, 0x83, 0x7d, 0xd8, 0x00, 0x74, 0x04
+.data1 	0x83, 0x45, 0xd8, 0x08, 0x81, 0xff, 0xf0, 0x01
+.data1 	0x00, 0x00, 0x0f, 0x84, 0x96, 0x00, 0x00, 0x00
+.data1 	0x81, 0xff, 0x70, 0x01, 0x00, 0x00, 0x0f, 0x84
+.data1 	0x8a, 0x00, 0x00, 0x00, 0xba, 0x02, 0x00, 0x00
+.data1 	0x00, 0x03, 0x55, 0xcc, 0x69, 0x05, 0xd8, 0x12
+.data1 	0x00, 0x00, 0xa4, 0x01, 0x00, 0x00, 0x6a, 0x02
+.data1 	0xff, 0x75, 0xe8, 0x6a, 0x01, 0xff, 0x75, 0xec
+.data1 	0xff, 0x75, 0xd8, 0x52, 0x57, 0x05, 0x20, 0x15
+.data1 	0x00, 0x00, 0x50, 0xe8, 0x12, 0xfc, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x20, 0xba, 0x02, 0x00, 0x00, 0x00
+.data1 	0x03, 0x55, 0xcc, 0x8b, 0x0d, 0xd8, 0x12, 0x00
+.data1 	0x00, 0x41, 0x69, 0xc1, 0xa4, 0x01, 0x00, 0x00
+.data1 	0x6a, 0x03, 0xff, 0x75, 0xe8, 0x6a, 0x01, 0xff
+.data1 	0x75, 0xec, 0xff, 0x75, 0xd8, 0x52, 0x57, 0x05
+.data1 	0x20, 0x15, 0x00, 0x00, 0x50, 0xe8, 0xe0, 0xfb
+.data1 	0xff, 0xff, 0x83, 0xc4, 0x20, 0x83, 0x3d, 0xc0
+.data1 	0x12, 0x00, 0x00, 0x00, 0x74, 0x17, 0xff, 0x75
+.data1 	0xec, 0xff, 0x75, 0xcc, 0x57, 0xff, 0x75, 0xf4
+.data1 	0x68, 0x54, 0x01, 0x00, 0x00, 0xe8, 0xb6, 0x38
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x14, 0x83, 0x05, 0xd8
+.data1 	0x12, 0x00, 0x00, 0x02, 0xeb, 0x45, 0x57, 0x68
+.data1 	0x1c, 0x01, 0x00, 0x00, 0xe8, 0x9f, 0x38, 0x00
+.data1 	0x00, 0x59, 0x59, 0xeb, 0x36, 0x31, 0xf6, 0x83
+.data1 	0xfe, 0x08, 0x7d, 0x2f, 0x69, 0xc6, 0xa4, 0x01
+.data1 	0x00, 0x00, 0x81, 0xb8, 0x28, 0x15, 0x00, 0x00
+.data1 	0x70, 0x01, 0x00, 0x00, 0x75, 0x1a, 0x83, 0x7d
+.data1 	0xd8, 0x00, 0x74, 0x14, 0xba, 0x08, 0x00, 0x00
+.data1 	0x00, 0x03, 0x55, 0xd8, 0x69, 0xc6, 0xa4, 0x01
+.data1 	0x00, 0x00, 0x89, 0x90, 0x30, 0x15, 0x00, 0x00
+.data1 	0x46, 0xeb, 0xcc, 0x8d, 0x45, 0xdc, 0x50, 0x8d
+.data1 	0x45, 0xde, 0x50, 0x8d, 0x45, 0xf4, 0x50, 0xe8
+.data1 	0x98, 0x41, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0x45, 0xf8, 0xe9, 0x07, 0xfc, 0xff, 0xff, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x08, 0x56, 0x8b, 0x55, 0x0c, 0xff, 0x72, 0x08
+.data1 	0xe8, 0xd0, 0x00, 0x00, 0x00, 0x59, 0x85, 0xc0
+.data1 	0x75, 0x0a, 0xb8, 0xfa, 0xff, 0xff, 0xff, 0xe9
+.data1 	0xbe, 0x00, 0x00, 0x00, 0x8b, 0x35, 0x40, 0x22
+.data1 	0x00, 0x00, 0x8b, 0x16, 0xf6, 0xc2, 0x20, 0x74
+.data1 	0x0a, 0xb8, 0xfa, 0xff, 0xff, 0xff, 0xe9, 0xa7
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x16, 0xf6, 0xc2, 0x10
+.data1 	0x74, 0x05, 0xf6, 0xc2, 0x02, 0x74, 0x42, 0xe8
+.data1 	0x51, 0x01, 0x00, 0x00, 0x85, 0xc0, 0x74, 0x1c
+.data1 	0x8b, 0x16, 0xf6, 0xc2, 0x02, 0x74, 0x05, 0xe8
+.data1 	0x49, 0x1b, 0x00, 0x00, 0xc7, 0x06, 0x20, 0x00
+.data1 	0x00, 0x00, 0xb8, 0xfa, 0xff, 0xff, 0xff, 0xe9
+.data1 	0x76, 0x00, 0x00, 0x00, 0x8b, 0x16, 0xf6, 0xc2
+.data1 	0x08, 0x75, 0x16, 0xe8, 0x1d, 0x09, 0x00, 0x00
+.data1 	0x85, 0xc0, 0x74, 0x0d, 0x83, 0x0e, 0x20, 0xb8
+.data1 	0xfa, 0xff, 0xff, 0xff, 0xe9, 0x59, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x16, 0xf6, 0xc2, 0x08, 0x74, 0x12
+.data1 	0x8b, 0x55, 0x0c, 0x8b, 0x52, 0x10, 0xf6, 0xc2
+.data1 	0x02, 0x74, 0x07, 0xb8, 0xf3, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x40, 0x83, 0x7e, 0x50, 0x00, 0x75, 0x34
+.data1 	0x8b, 0x16, 0xf6, 0xc2, 0x08, 0x74, 0x0e, 0xe8
+.data1 	0x2c, 0x1f, 0x00, 0x00, 0x89, 0x45, 0xf8, 0x85
+.data1 	0xc0, 0x74, 0x02, 0xeb, 0x25, 0xba, 0x08, 0x00
+.data1 	0x00, 0x00, 0x23, 0x16, 0x6b, 0x05, 0x78, 0x22
+.data1 	0x00, 0x00, 0x05, 0x52, 0x6a, 0x01, 0x50, 0x68
+.data1 	0xf0, 0x12, 0x00, 0x00, 0xe8, 0xd7, 0x30, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x10, 0x83, 0x46, 0x50, 0x01
+.data1 	0x31, 0xc0, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x04, 0x56, 0x8b, 0x75, 0x08, 0x8b
+.data1 	0x15, 0x40, 0x22, 0x00, 0x00, 0x89, 0x55, 0xfc
+.data1 	0x89, 0x35, 0xdc, 0x12, 0x00, 0x00, 0x83, 0xfe
+.data1 	0x28, 0x7d, 0x39, 0xb9, 0x05, 0x00, 0x00, 0x00
+.data1 	0x89, 0xf0, 0x99, 0xf7, 0xf9, 0xa3, 0x78, 0x22
+.data1 	0x00, 0x00, 0x69, 0x1d, 0x78, 0x22, 0x00, 0x00
+.data1 	0xa4, 0x01, 0x00, 0x00, 0x81, 0xc3, 0x20, 0x15
+.data1 	0x00, 0x00, 0x89, 0x1d, 0x40, 0x22, 0x00, 0x00
+.data1 	0x89, 0xf0, 0x99, 0xf7, 0xf9, 0xc1, 0xe2, 0x04
+.data1 	0x8d, 0x54, 0x13, 0x54, 0x89, 0x15, 0x7c, 0x22
+.data1 	0x00, 0x00, 0xeb, 0x59, 0x81, 0xee, 0x80, 0x00
+.data1 	0x00, 0x00, 0x81, 0xfe, 0x80, 0x00, 0x00, 0x00
+.data1 	0x73, 0x3d, 0xb9, 0x10, 0x00, 0x00, 0x00, 0x89
+.data1 	0xf0, 0x99, 0xf7, 0xf9, 0xa3, 0x78, 0x22, 0x00
+.data1 	0x00, 0x69, 0x1d, 0x78, 0x22, 0x00, 0x00, 0xa4
+.data1 	0x01, 0x00, 0x00, 0x81, 0xc3, 0x20, 0x15, 0x00
+.data1 	0x00, 0x89, 0x1d, 0x40, 0x22, 0x00, 0x00, 0x89
+.data1 	0xf0, 0x99, 0xf7, 0xf9, 0xc1, 0xe2, 0x04, 0x81
+.data1 	0xc3, 0xa4, 0x00, 0x00, 0x00, 0x01, 0xda, 0x89
+.data1 	0x15, 0x7c, 0x22, 0x00, 0x00, 0xeb, 0x0e, 0xc7
+.data1 	0x05, 0xdc, 0x12, 0x00, 0x00, 0xff, 0xff, 0xff
+.data1 	0xff, 0x31, 0xc0, 0xeb, 0x05, 0xa1, 0x7c, 0x22
+.data1 	0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x38, 0x56, 0x57, 0x8b, 0x35, 0x40
+.data1 	0x22, 0x00, 0x00, 0x8b, 0x56, 0x44, 0x88, 0x55
+.data1 	0xf6, 0xc6, 0x45, 0xf7, 0xec, 0x8d, 0x45, 0xf1
+.data1 	0x50, 0xe8, 0x33, 0x19, 0x00, 0x00, 0x59, 0x85
+.data1 	0xc0, 0x0f, 0x85, 0x17, 0x06, 0x00, 0x00, 0x6a
+.data1 	0x08, 0x6a, 0x08, 0xe8, 0x7c, 0x1c, 0x00, 0x00
+.data1 	0x59, 0x59, 0x85, 0xc0, 0x0f, 0x84, 0x04, 0x06
+.data1 	0x00, 0x00, 0x0f, 0xb7, 0x56, 0x04, 0xf6, 0xc2
+.data1 	0x21, 0x0f, 0x85, 0xf7, 0x05, 0x00, 0x00, 0x68
+.data1 	0x00, 0x02, 0x00, 0x00, 0xff, 0x35, 0x14, 0xdd
+.data1 	0x00, 0x00, 0x68, 0xce, 0x8a, 0x00, 0x00, 0x6a
+.data1 	0x77, 0xff, 0x76, 0x08, 0x6a, 0x00, 0xe8, 0x09
+.data1 	0x41, 0x00, 0x00, 0x83, 0xc4, 0x18, 0x89, 0x45
+.data1 	0xe8, 0x85, 0xc0, 0x74, 0x16, 0xff, 0x75, 0xe8
+.data1 	0x68, 0x94, 0x04, 0x00, 0x00, 0xe8, 0x60, 0x07
+.data1 	0x00, 0x00, 0x50, 0xe8, 0xd4, 0x3c, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x8b, 0x15, 0x14, 0xdd, 0x00
+.data1 	0x00, 0x8b, 0x0d, 0x14, 0xdd, 0x00, 0x00, 0x0f
+.data1 	0xb6, 0x59, 0x01, 0xc1, 0xe3, 0x08, 0x0f, 0xb6
+.data1 	0x0a, 0x09, 0xcb, 0xf7, 0xc3, 0x00, 0x80, 0x00
+.data1 	0x00, 0x74, 0x1c, 0xe8, 0x32, 0x07, 0x00, 0x00
+.data1 	0x50, 0x68, 0x7c, 0x04, 0x00, 0x00, 0xe8, 0xf5
+.data1 	0x35, 0x00, 0x00, 0x59, 0x59, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe9, 0x17, 0x07, 0x00, 0x00, 0x83
+.data1 	0x0e, 0x04, 0x31, 0xff, 0x83, 0xff, 0x28, 0x7d
+.data1 	0x1b, 0x8b, 0x15, 0x14, 0xdd, 0x00, 0x00, 0xb9
+.data1 	0x01, 0x00, 0x00, 0x00, 0x31, 0xf9, 0x0f, 0xbe
+.data1 	0x44, 0x0a, 0x36, 0x88, 0x87, 0x44, 0x22, 0x00
+.data1 	0x00, 0x47, 0xeb, 0xe0, 0x8b, 0x15, 0x14, 0xdd
+.data1 	0x00, 0x00, 0x8b, 0x0d, 0x14, 0xdd, 0x00, 0x00
+.data1 	0x0f, 0xb6, 0x59, 0x03, 0xc1, 0xe3, 0x08, 0x0f
+.data1 	0xb6, 0x4a, 0x02, 0x09, 0xcb, 0x89, 0x5e, 0x38
+.data1 	0x8b, 0x15, 0x14, 0xdd, 0x00, 0x00, 0x8b, 0x0d
+.data1 	0x14, 0xdd, 0x00, 0x00, 0x0f, 0xb6, 0x59, 0x07
+.data1 	0xc1, 0xe3, 0x08, 0x0f, 0xb6, 0x4a, 0x06, 0x09
+.data1 	0xcb, 0x89, 0x5e, 0x3c, 0x8b, 0x15, 0x14, 0xdd
+.data1 	0x00, 0x00, 0x8b, 0x0d, 0x14, 0xdd, 0x00, 0x00
+.data1 	0x0f, 0xb6, 0x59, 0x0d, 0xc1, 0xe3, 0x08, 0x0f
+.data1 	0xb6, 0x4a, 0x0c, 0x09, 0xcb, 0x89, 0x5e, 0x40
+.data1 	0x8b, 0x56, 0x38, 0x0f, 0xaf, 0x56, 0x3c, 0x0f
+.data1 	0xaf, 0x56, 0x40, 0x89, 0x55, 0xd0, 0x8b, 0x15
+.data1 	0x14, 0xdd, 0x00, 0x00, 0x8b, 0x0d, 0x14, 0xdd
+.data1 	0x00, 0x00, 0x0f, 0xb6, 0x59, 0x63, 0xc1, 0xe3
+.data1 	0x08, 0x0f, 0xb6, 0x4a, 0x62, 0x09, 0xcb, 0x81
+.data1 	0xe3, 0xff, 0xff, 0x00, 0x00, 0x66, 0x89, 0x5d
+.data1 	0xda, 0x0f, 0xb7, 0x55, 0xda, 0xf7, 0xc2, 0x00
+.data1 	0x02, 0x00, 0x00, 0x0f, 0x84, 0x8b, 0x04, 0x00
+.data1 	0x00, 0x81, 0x7d, 0xd0, 0x00, 0x00, 0x10, 0x00
+.data1 	0x0f, 0x86, 0x7e, 0x04, 0x00, 0x00, 0x83, 0x4e
+.data1 	0x44, 0x40, 0x8b, 0x15, 0x14, 0xdd, 0x00, 0x00
+.data1 	0x8b, 0x0d, 0x14, 0xdd, 0x00, 0x00, 0x0f, 0xb6
+.data1 	0x59, 0x79, 0xc1, 0xe3, 0x08, 0x0f, 0xb6, 0x4a
+.data1 	0x78, 0x09, 0xcb, 0x8b, 0x15, 0x14, 0xdd, 0x00
+.data1 	0x00, 0x0f, 0xb6, 0x4a, 0x7a, 0xc1, 0xe1, 0x10
+.data1 	0x09, 0xd9, 0x8b, 0x15, 0x14, 0xdd, 0x00, 0x00
+.data1 	0x0f, 0xb6, 0x5a, 0x7b, 0xc1, 0xe3, 0x18, 0x09
+.data1 	0xcb, 0x89, 0x5d, 0xd0, 0x8b, 0x15, 0x14, 0xdd
+.data1 	0x00, 0x00, 0x8b, 0x0d, 0x14, 0xdd, 0x00, 0x00
+.data1 	0x0f, 0xb6, 0x99, 0xa7, 0x00, 0x00, 0x00, 0xc1
+.data1 	0xe3, 0x08, 0x0f, 0xb6, 0x8a, 0xa6, 0x00, 0x00
+.data1 	0x00, 0x09, 0xcb, 0x81, 0xe3, 0xff, 0xff, 0x00
+.data1 	0x00, 0x66, 0x89, 0x5d, 0xda, 0x81, 0x7d, 0xd0
+.data1 	0x00, 0x00, 0x00, 0x0f, 0x0f, 0x82, 0xab, 0x00
+.data1 	0x00, 0x00, 0x0f, 0xb7, 0x55, 0xda, 0xf7, 0xc2
+.data1 	0x00, 0x04, 0x00, 0x00, 0x0f, 0x84, 0x9b, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x15, 0x14, 0xdd, 0x00, 0x00
+.data1 	0x8b, 0x0d, 0x14, 0xdd, 0x00, 0x00, 0x0f, 0xb6
+.data1 	0x99, 0xcd, 0x00, 0x00, 0x00, 0xc1, 0xe3, 0x08
+.data1 	0x0f, 0xb6, 0x8a, 0xcc, 0x00, 0x00, 0x00, 0x09
+.data1 	0xcb, 0x8b, 0x15, 0x14, 0xdd, 0x00, 0x00, 0x0f
+.data1 	0xb6, 0x8a, 0xce, 0x00, 0x00, 0x00, 0xc1, 0xe1
+.data1 	0x10, 0x09, 0xd9, 0x8b, 0x15, 0x14, 0xdd, 0x00
+.data1 	0x00, 0x0f, 0xb6, 0x9a, 0xcf, 0x00, 0x00, 0x00
+.data1 	0xc1, 0xe3, 0x18, 0x09, 0xcb, 0x74, 0x09, 0xc7
+.data1 	0x45, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x46
+.data1 	0x8b, 0x15, 0x14, 0xdd, 0x00, 0x00, 0x8b, 0x0d
+.data1 	0x14, 0xdd, 0x00, 0x00, 0x0f, 0xb6, 0x99, 0xc9
+.data1 	0x00, 0x00, 0x00, 0xc1, 0xe3, 0x08, 0x0f, 0xb6
+.data1 	0x8a, 0xc8, 0x00, 0x00, 0x00, 0x09, 0xcb, 0x8b
+.data1 	0x15, 0x14, 0xdd, 0x00, 0x00, 0x0f, 0xb6, 0x8a
+.data1 	0xca, 0x00, 0x00, 0x00, 0xc1, 0xe1, 0x10, 0x09
+.data1 	0xd9, 0x8b, 0x15, 0x14, 0xdd, 0x00, 0x00, 0x0f
+.data1 	0xb6, 0x9a, 0xcb, 0x00, 0x00, 0x00, 0xc1, 0xe3
+.data1 	0x18, 0x09, 0xcb, 0x89, 0x5d, 0xd0, 0xc7, 0x46
+.data1 	0x24, 0x01, 0x00, 0x00, 0x00, 0x8b, 0x15, 0x14
+.data1 	0xdd, 0x00, 0x00, 0x8b, 0x0d, 0x14, 0xdd, 0x00
+.data1 	0x00, 0x0f, 0xb6, 0x59, 0x63, 0xc1, 0xe3, 0x08
+.data1 	0x0f, 0xb6, 0x4a, 0x62, 0x09, 0xcb, 0x81, 0xe3
+.data1 	0xff, 0xff, 0x00, 0x00, 0x66, 0x89, 0x5d, 0xda
+.data1 	0x0f, 0xb7, 0x55, 0xda, 0x81, 0xe2, 0x00, 0x01
+.data1 	0x00, 0x00, 0x31, 0xc0, 0x85, 0xd2, 0x0f, 0x95
+.data1 	0xc0, 0x89, 0x45, 0xe4, 0x8b, 0x15, 0x14, 0xdd
+.data1 	0x00, 0x00, 0x0f, 0xb6, 0x4a, 0x6a, 0x66, 0x89
+.data1 	0x4d, 0xda, 0x0f, 0xb7, 0x55, 0xda, 0x83, 0xe2
+.data1 	0x04, 0x31, 0xdb, 0x85, 0xd2, 0x0f, 0x95, 0xc3
+.data1 	0x89, 0x5d, 0xe0, 0x8b, 0x56, 0x10, 0x89, 0x55
+.data1 	0xdc, 0x85, 0xd2, 0x74, 0x2e, 0x83, 0xc2, 0x02
+.data1 	0x6a, 0x62, 0x8d, 0x45, 0xd4, 0x50, 0x52, 0xe8
+.data1 	0x6c, 0x3d, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85
+.data1 	0xc0, 0x74, 0x18, 0x68, 0x00, 0x80, 0x00, 0x00
+.data1 	0x68, 0x58, 0x04, 0x00, 0x00, 0xe8, 0xb0, 0x04
+.data1 	0x00, 0x00, 0x50, 0xe8, 0x24, 0x3a, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x83, 0x3d, 0xc8, 0x12, 0x00
+.data1 	0x00, 0x00, 0x0f, 0x85, 0xc4, 0x02, 0x00, 0x00
+.data1 	0x83, 0x7d, 0xe4, 0x00, 0x0f, 0x84, 0x8e, 0x02
+.data1 	0x00, 0x00, 0x83, 0x7d, 0xdc, 0x00, 0x0f, 0x84
+.data1 	0x84, 0x02, 0x00, 0x00, 0x8b, 0x15, 0x14, 0xdd
+.data1 	0x00, 0x00, 0x8b, 0x0d, 0x14, 0xdd, 0x00, 0x00
+.data1 	0x0f, 0xb6, 0x59, 0x7f, 0xc1, 0xe3, 0x08, 0x0f
+.data1 	0xb6, 0x4a, 0x7e, 0x09, 0xcb, 0x81, 0xe3, 0xff
+.data1 	0xff, 0x00, 0x00, 0x66, 0x89, 0x5d, 0xda, 0x0f
+.data1 	0xb7, 0x55, 0xda, 0xf6, 0xc2, 0x07, 0x74, 0x55
+.data1 	0x0f, 0xb7, 0x55, 0xda, 0xf6, 0xc2, 0x04, 0x74
+.data1 	0x07, 0xb8, 0x18, 0x04, 0x00, 0x00, 0xeb, 0x05
+.data1 	0xb8, 0x14, 0x04, 0x00, 0x00, 0x0f, 0xb7, 0x55
+.data1 	0xda, 0x50, 0xf6, 0xc2, 0x02, 0x74, 0x07, 0xb8
+.data1 	0x20, 0x04, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0x1c
+.data1 	0x04, 0x00, 0x00, 0x0f, 0xb7, 0x55, 0xda, 0x50
+.data1 	0xf6, 0xc2, 0x01, 0x74, 0x07, 0xb8, 0x28, 0x04
+.data1 	0x00, 0x00, 0xeb, 0x05, 0xb8, 0x24, 0x04, 0x00
+.data1 	0x00, 0x50, 0xe8, 0x13, 0x04, 0x00, 0x00, 0x50
+.data1 	0x68, 0x2c, 0x04, 0x00, 0x00, 0xe8, 0xd6, 0x32
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x14, 0x0f, 0xb7, 0x55
+.data1 	0xda, 0xf7, 0xc2, 0x00, 0x07, 0x00, 0x00, 0x74
+.data1 	0x5e, 0x0f, 0xb7, 0x55, 0xda, 0xf7, 0xc2, 0x00
+.data1 	0x04, 0x00, 0x00, 0x74, 0x07, 0xb8, 0xd8, 0x03
+.data1 	0x00, 0x00, 0xeb, 0x05, 0xb8, 0xd4, 0x03, 0x00
+.data1 	0x00, 0x0f, 0xb7, 0x55, 0xda, 0x50, 0xf7, 0xc2
+.data1 	0x00, 0x02, 0x00, 0x00, 0x74, 0x07, 0xb8, 0xe0
+.data1 	0x03, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0xdc, 0x03
+.data1 	0x00, 0x00, 0x0f, 0xb7, 0x55, 0xda, 0x50, 0xf7
+.data1 	0xc2, 0x00, 0x01, 0x00, 0x00, 0x74, 0x07, 0xb8
+.data1 	0xe8, 0x03, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0xe4
+.data1 	0x03, 0x00, 0x00, 0x50, 0xe8, 0xa9, 0x03, 0x00
+.data1 	0x00, 0x50, 0x68, 0xec, 0x03, 0x00, 0x00, 0xe8
+.data1 	0x6c, 0x32, 0x00, 0x00, 0x83, 0xc4, 0x14, 0x83
+.data1 	0x7d, 0xe0, 0x00, 0x0f, 0x84, 0x86, 0x01, 0x00
+.data1 	0x00, 0x8b, 0x15, 0x14, 0xdd, 0x00, 0x00, 0x8b
+.data1 	0x0d, 0x14, 0xdd, 0x00, 0x00, 0x0f, 0xb6, 0x99
+.data1 	0xb1, 0x00, 0x00, 0x00, 0xc1, 0xe3, 0x08, 0x0f
+.data1 	0xb6, 0x8a, 0xb0, 0x00, 0x00, 0x00, 0x09, 0xcb
+.data1 	0x81, 0xe3, 0xff, 0xff, 0x00, 0x00, 0x66, 0x89
+.data1 	0x5d, 0xda, 0x0f, 0xb7, 0x55, 0xda, 0xf6, 0xc2
+.data1 	0x3f, 0x0f, 0x84, 0x97, 0x00, 0x00, 0x00, 0x0f
+.data1 	0xb7, 0x55, 0xda, 0xf6, 0xc2, 0x20, 0x74, 0x07
+.data1 	0xb8, 0x7c, 0x03, 0x00, 0x00, 0xeb, 0x05, 0xb8
+.data1 	0x78, 0x03, 0x00, 0x00, 0x0f, 0xb7, 0x55, 0xda
+.data1 	0x50, 0xf6, 0xc2, 0x10, 0x74, 0x07, 0xb8, 0x84
+.data1 	0x03, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0x80, 0x03
+.data1 	0x00, 0x00, 0x0f, 0xb7, 0x55, 0xda, 0x50, 0xf6
+.data1 	0xc2, 0x08, 0x74, 0x07, 0xb8, 0x8c, 0x03, 0x00
+.data1 	0x00, 0xeb, 0x05, 0xb8, 0x88, 0x03, 0x00, 0x00
+.data1 	0x0f, 0xb7, 0x55, 0xda, 0x50, 0xf6, 0xc2, 0x04
+.data1 	0x74, 0x07, 0xb8, 0x94, 0x03, 0x00, 0x00, 0xeb
+.data1 	0x05, 0xb8, 0x90, 0x03, 0x00, 0x00, 0x0f, 0xb7
+.data1 	0x55, 0xda, 0x50, 0xf6, 0xc2, 0x02, 0x74, 0x07
+.data1 	0xb8, 0x9c, 0x03, 0x00, 0x00, 0xeb, 0x05, 0xb8
+.data1 	0x98, 0x03, 0x00, 0x00, 0x0f, 0xb7, 0x55, 0xda
+.data1 	0x50, 0xf6, 0xc2, 0x01, 0x74, 0x07, 0xb8, 0xa4
+.data1 	0x03, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0xa0, 0x03
+.data1 	0x00, 0x00, 0x50, 0xe8, 0xd2, 0x02, 0x00, 0x00
+.data1 	0x50, 0x68, 0xa8, 0x03, 0x00, 0x00, 0xe8, 0x95
+.data1 	0x31, 0x00, 0x00, 0x83, 0xc4, 0x20, 0x0f, 0xb7
+.data1 	0x55, 0xda, 0xf7, 0xc2, 0x00, 0x3f, 0x00, 0x00
+.data1 	0x0f, 0x84, 0xa9, 0x00, 0x00, 0x00, 0x0f, 0xb7
+.data1 	0x55, 0xda, 0xf7, 0xc2, 0x00, 0x20, 0x00, 0x00
+.data1 	0x74, 0x07, 0xb8, 0x20, 0x03, 0x00, 0x00, 0xeb
+.data1 	0x05, 0xb8, 0x1c, 0x03, 0x00, 0x00, 0x0f, 0xb7
+.data1 	0x55, 0xda, 0x50, 0xf7, 0xc2, 0x00, 0x10, 0x00
+.data1 	0x00, 0x74, 0x07, 0xb8, 0x28, 0x03, 0x00, 0x00
+.data1 	0xeb, 0x05, 0xb8, 0x24, 0x03, 0x00, 0x00, 0x0f
+.data1 	0xb7, 0x55, 0xda, 0x50, 0xf7, 0xc2, 0x00, 0x08
+.data1 	0x00, 0x00, 0x74, 0x07, 0xb8, 0x30, 0x03, 0x00
+.data1 	0x00, 0xeb, 0x05, 0xb8, 0x2c, 0x03, 0x00, 0x00
+.data1 	0x0f, 0xb7, 0x55, 0xda, 0x50, 0xf7, 0xc2, 0x00
+.data1 	0x04, 0x00, 0x00, 0x74, 0x07, 0xb8, 0x38, 0x03
+.data1 	0x00, 0x00, 0xeb, 0x05, 0xb8, 0x34, 0x03, 0x00
+.data1 	0x00, 0x0f, 0xb7, 0x55, 0xda, 0x50, 0xf7, 0xc2
+.data1 	0x00, 0x02, 0x00, 0x00, 0x74, 0x07, 0xb8, 0x40
+.data1 	0x03, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0x3c, 0x03
+.data1 	0x00, 0x00, 0x0f, 0xb7, 0x55, 0xda, 0x50, 0xf7
+.data1 	0xc2, 0x00, 0x01, 0x00, 0x00, 0x74, 0x07, 0xb8
+.data1 	0x48, 0x03, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0x44
+.data1 	0x03, 0x00, 0x00, 0x50, 0xe8, 0x19, 0x02, 0x00
+.data1 	0x00, 0x50, 0x68, 0x4c, 0x03, 0x00, 0x00, 0xe8
+.data1 	0xdc, 0x30, 0x00, 0x00, 0x83, 0xc4, 0x20, 0xc7
+.data1 	0x46, 0x28, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x2c
+.data1 	0x83, 0x7d, 0xe4, 0x00, 0x75, 0x06, 0x83, 0x7d
+.data1 	0xdc, 0x00, 0x74, 0x15, 0xff, 0x75, 0xdc, 0xff
+.data1 	0x75, 0xe4, 0x68, 0x00, 0x03, 0x00, 0x00, 0xe8
+.data1 	0xb4, 0x30, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xeb
+.data1 	0x0b, 0x68, 0xf0, 0x02, 0x00, 0x00, 0xe8, 0xa5
+.data1 	0x30, 0x00, 0x00, 0x59, 0x83, 0x7e, 0x2c, 0x00
+.data1 	0x0f, 0x85, 0x00, 0x01, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x38, 0x89, 0x56, 0x2c, 0x8b, 0x56, 0x3c, 0x89
+.data1 	0x56, 0x30, 0x8b, 0x56, 0x40, 0x89, 0x56, 0x34
+.data1 	0x81, 0x7e, 0x2c, 0x00, 0x04, 0x00, 0x00, 0x0f
+.data1 	0x86, 0xe1, 0x00, 0x00, 0x00, 0x6b, 0x46, 0x30
+.data1 	0x02, 0x89, 0x46, 0x30, 0x8b, 0x56, 0x2c, 0xd1
+.data1 	0xea, 0x89, 0x56, 0x2c, 0xeb, 0xe2, 0xc6, 0x45
+.data1 	0xf7, 0xa1, 0x8d, 0x45, 0xf1, 0x50, 0xe8, 0x06
+.data1 	0x13, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x0f, 0x85
+.data1 	0x8a, 0x00, 0x00, 0x00, 0x6a, 0x08, 0x6a, 0x08
+.data1 	0xe8, 0x4f, 0x16, 0x00, 0x00, 0x59, 0x59, 0x85
+.data1 	0xc0, 0x0f, 0x84, 0x77, 0x00, 0x00, 0x00, 0x0f
+.data1 	0xb7, 0x56, 0x04, 0xf6, 0xc2, 0x21, 0x0f, 0x85
+.data1 	0x6a, 0x00, 0x00, 0x00, 0x83, 0x0e, 0x08, 0x68
+.data1 	0x00, 0x02, 0x00, 0x00, 0xff, 0x35, 0x14, 0xdd
+.data1 	0x00, 0x00, 0x68, 0xce, 0x8a, 0x00, 0x00, 0x6a
+.data1 	0x77, 0xff, 0x76, 0x08, 0x6a, 0x00, 0xe8, 0xd9
+.data1 	0x3a, 0x00, 0x00, 0x83, 0xc4, 0x18, 0x89, 0x45
+.data1 	0xe8, 0x85, 0xc0, 0x74, 0x16, 0xff, 0x75, 0xe8
+.data1 	0x68, 0xd4, 0x02, 0x00, 0x00, 0xe8, 0x30, 0x01
+.data1 	0x00, 0x00, 0x50, 0xe8, 0xa4, 0x36, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x31, 0xff, 0x83, 0xff, 0x28
+.data1 	0x7d, 0x1b, 0x8b, 0x15, 0x14, 0xdd, 0x00, 0x00
+.data1 	0xb9, 0x01, 0x00, 0x00, 0x00, 0x31, 0xf9, 0x0f
+.data1 	0xbe, 0x44, 0x0a, 0x36, 0x88, 0x87, 0x44, 0x22
+.data1 	0x00, 0x00, 0x47, 0xeb, 0xe0, 0xc7, 0x45, 0xd0
+.data1 	0x00, 0x00, 0x00, 0x00, 0xeb, 0x30, 0x83, 0x7e
+.data1 	0x2c, 0x00, 0x75, 0x0a, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0xe8, 0x00, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x2c, 0x89, 0x56, 0x38, 0x8b, 0x56, 0x30, 0x89
+.data1 	0x56, 0x3c, 0x8b, 0x56, 0x34, 0x89, 0x56, 0x40
+.data1 	0x8b, 0x56, 0x38, 0x0f, 0xaf, 0x56, 0x3c, 0x0f
+.data1 	0xaf, 0x56, 0x40, 0x89, 0x55, 0xd0, 0x68, 0x00
+.data1 	0x02, 0x00, 0x00, 0xff, 0x75, 0xd0, 0x8d, 0x45
+.data1 	0xc8, 0x50, 0xe8, 0xc1, 0x3f, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x50, 0x8d, 0x46, 0x5c, 0x50, 0xb9
+.data1 	0x02, 0x00, 0x00, 0x00, 0xe8, 0xa7, 0x43, 0x00
+.data1 	0x00, 0xe8, 0xd0, 0x01, 0x00, 0x00, 0x85, 0xc0
+.data1 	0x74, 0x13, 0xe8, 0xc7, 0x01, 0x00, 0x00, 0x85
+.data1 	0xc0, 0x74, 0x0a, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x89, 0x00, 0x00, 0x00, 0x83, 0x7e, 0x14
+.data1 	0x00, 0x0f, 0x85, 0x7a, 0x00, 0x00, 0x00, 0x83
+.data1 	0x3d, 0x78, 0x22, 0x00, 0x00, 0x02, 0x7d, 0x07
+.data1 	0xb8, 0x0e, 0x00, 0x00, 0x00, 0xeb, 0x05, 0xb8
+.data1 	0x0f, 0x00, 0x00, 0x00, 0x89, 0x46, 0x14, 0x89
+.data1 	0x46, 0x20, 0x8d, 0x46, 0x20, 0x50, 0x6a, 0x01
+.data1 	0xff, 0x76, 0x14, 0x6a, 0x01, 0xe8, 0x3a, 0x39
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x10, 0x89, 0x45, 0xe8
+.data1 	0x85, 0xc0, 0x74, 0x16, 0xff, 0x75, 0xe8, 0x68
+.data1 	0xbc, 0x02, 0x00, 0x00, 0xe8, 0x41, 0x00, 0x00
+.data1 	0x00, 0x50, 0xe8, 0xb5, 0x35, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x8d, 0x46, 0x20, 0x50, 0x6a, 0x00
+.data1 	0x6a, 0x00, 0x6a, 0x03, 0xe8, 0x0b, 0x39, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x10, 0x89, 0x45, 0xe8, 0x85
+.data1 	0xc0, 0x74, 0x16, 0xff, 0x75, 0xe8, 0x68, 0xa0
+.data1 	0x02, 0x00, 0x00, 0xe8, 0x12, 0x00, 0x00, 0x00
+.data1 	0x50, 0xe8, 0x86, 0x35, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x83, 0x0e, 0x10, 0x31, 0xc0, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0xba, 0x30, 0x00
+.data1 	0x00, 0x00, 0x03, 0x15, 0x78, 0x22, 0x00, 0x00
+.data1 	0x88, 0x15, 0x2c, 0x13, 0x00, 0x00, 0xb8, 0x28
+.data1 	0x13, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x1c, 0xc7, 0x45, 0xe4, 0x94, 0xc4
+.data1 	0x00, 0x00, 0xc7, 0x45, 0xe8, 0x00, 0x08, 0x00
+.data1 	0x00, 0x8b, 0x15, 0xdc, 0x12, 0x00, 0x00, 0x89
+.data1 	0x55, 0xf8, 0x8b, 0x15, 0xb0, 0x12, 0x00, 0x00
+.data1 	0x89, 0x55, 0xf4, 0x8b, 0x15, 0xb4, 0x12, 0x00
+.data1 	0x00, 0x89, 0x55, 0xf0, 0x8b, 0x15, 0xb8, 0x12
+.data1 	0x00, 0x00, 0x89, 0x55, 0xec, 0x83, 0x3d, 0xbc
+.data1 	0x12, 0x00, 0x00, 0x00, 0x75, 0x1e, 0xc7, 0x05
+.data1 	0xb0, 0x12, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x05, 0xb8, 0x12, 0x00, 0x00, 0x68, 0x01
+.data1 	0x00, 0x00, 0xc7, 0x05, 0xb4, 0x12, 0x00, 0x00
+.data1 	0x03, 0x00, 0x00, 0x00, 0xc7, 0x05, 0xd0, 0x12
+.data1 	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6b, 0x05
+.data1 	0x78, 0x22, 0x00, 0x00, 0x05, 0x50, 0xe8, 0xda
+.data1 	0xf6, 0xff, 0xff, 0x59, 0x85, 0xc0, 0x75, 0x18
+.data1 	0x68, 0x00, 0x80, 0x00, 0x00, 0x68, 0xd0, 0x04
+.data1 	0x00, 0x00, 0xe8, 0x5b, 0xff, 0xff, 0xff, 0x50
+.data1 	0xe8, 0xcf, 0x34, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x6a, 0x01, 0x8d, 0x45, 0xe4, 0x50, 0x6a, 0x00
+.data1 	0x68, 0x09, 0x04, 0x00, 0x00, 0x68, 0xce, 0x8a
+.data1 	0x00, 0x00, 0xe8, 0xb8, 0x02, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x14, 0x89, 0x45, 0xfc, 0xff, 0x75, 0xf8
+.data1 	0xe8, 0x98, 0xf6, 0xff, 0xff, 0x59, 0x85, 0xc0
+.data1 	0x75, 0x18, 0x68, 0x00, 0x80, 0x00, 0x00, 0x68
+.data1 	0xb0, 0x04, 0x00, 0x00, 0xe8, 0x19, 0xff, 0xff
+.data1 	0xff, 0x50, 0xe8, 0x8d, 0x34, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x8b, 0x55, 0xf4, 0x89, 0x15, 0xb0
+.data1 	0x12, 0x00, 0x00, 0x8b, 0x55, 0xf0, 0x89, 0x15
+.data1 	0xb4, 0x12, 0x00, 0x00, 0x8b, 0x55, 0xec, 0x89
+.data1 	0x15, 0xb8, 0x12, 0x00, 0x00, 0xc7, 0x05, 0xd0
+.data1 	0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7d, 0xfc, 0x00, 0x75, 0x06, 0x83, 0x7d, 0xe8
+.data1 	0x00, 0x74, 0x07, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x02, 0x31, 0xc0, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x10, 0x56, 0x8b, 0x35, 0x40
+.data1 	0x22, 0x00, 0x00, 0x8b, 0x16, 0xf6, 0xc2, 0x02
+.data1 	0x74, 0x13, 0xe8, 0xe6, 0x10, 0x00, 0x00, 0x85
+.data1 	0xc0, 0x74, 0x0a, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x7f, 0x00, 0x00, 0x00, 0x8b, 0x16, 0xf6
+.data1 	0xc2, 0x08, 0x0f, 0x85, 0x6f, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x56, 0x48, 0x88, 0x55, 0xf1, 0x8b, 0x56
+.data1 	0x40, 0x88, 0x55, 0xf2, 0x8b, 0x56, 0x3c, 0x83
+.data1 	0xea, 0x01, 0x8b, 0x0d, 0x40, 0x22, 0x00, 0x00
+.data1 	0x0b, 0x51, 0x44, 0x88, 0x55, 0xf6, 0xc6, 0x45
+.data1 	0xf7, 0x91, 0x8d, 0x45, 0xf1, 0x50, 0xe8, 0xee
+.data1 	0x0f, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x74, 0x07
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x3d, 0x8b
+.data1 	0x16, 0xf6, 0xc2, 0x04, 0x75, 0x31, 0xc6, 0x45
+.data1 	0xf3, 0x00, 0xc6, 0x45, 0xf4, 0x00, 0xc6, 0x45
+.data1 	0xf5, 0x00, 0x8b, 0x15, 0x40, 0x22, 0x00, 0x00
+.data1 	0x8b, 0x52, 0x44, 0x88, 0x55, 0xf6, 0xc6, 0x45
+.data1 	0xf7, 0x10, 0x8d, 0x45, 0xf1, 0x50, 0xe8, 0xb6
+.data1 	0x0f, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x74, 0x07
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x05, 0x83
+.data1 	0x0e, 0x01, 0x31, 0xc0, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x24, 0x56, 0x57, 0x8b
+.data1 	0x75, 0x14, 0x8b, 0x7d, 0x08, 0x8b, 0x57, 0x3c
+.data1 	0x0f, 0xaf, 0x57, 0x40, 0x89, 0x55, 0xec, 0xc7
+.data1 	0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x45
+.data1 	0xe8, 0x00, 0x00, 0x00, 0x00, 0x81, 0xfe, 0x00
+.data1 	0x00, 0x00, 0x0f, 0x73, 0x06, 0x83, 0x7d, 0xf0
+.data1 	0x00, 0x74, 0x27, 0x83, 0x7f, 0x24, 0x00, 0x74
+.data1 	0x09, 0xc7, 0x45, 0xe8, 0x01, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x18, 0x81, 0xfe, 0xff, 0xff, 0xff, 0x0f
+.data1 	0x77, 0x06, 0x83, 0x7d, 0xf0, 0x00, 0x74, 0x0a
+.data1 	0xb8, 0xfb, 0xff, 0xff, 0xff, 0xe9, 0x49, 0x01
+.data1 	0x00, 0x00, 0x8b, 0x55, 0x0c, 0x88, 0x55, 0xf5
+.data1 	0x8b, 0x55, 0x10, 0x88, 0x55, 0xf6, 0x83, 0x7d
+.data1 	0x1c, 0x00, 0x74, 0x1a, 0x81, 0x7d, 0x18, 0x08
+.data1 	0x04, 0x00, 0x00, 0x75, 0x07, 0xb8, 0xca, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x05, 0xb8, 0xc8, 0x00, 0x00
+.data1 	0x00, 0x88, 0x45, 0xfb, 0xeb, 0x18, 0x81, 0x7d
+.data1 	0x18, 0x08, 0x04, 0x00, 0x00, 0x75, 0x07, 0xb8
+.data1 	0x30, 0x00, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0x20
+.data1 	0x00, 0x00, 0x00, 0x88, 0x45, 0xfb, 0x83, 0x7d
+.data1 	0xe8, 0x00, 0x0f, 0x84, 0x82, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x1c, 0x00, 0x74, 0x1a, 0x81, 0x7d
+.data1 	0x18, 0x08, 0x04, 0x00, 0x00, 0x75, 0x07, 0xb8
+.data1 	0x35, 0x00, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0x25
+.data1 	0x00, 0x00, 0x00, 0x88, 0x45, 0xfb, 0xeb, 0x18
+.data1 	0x81, 0x7d, 0x18, 0x08, 0x04, 0x00, 0x00, 0x75
+.data1 	0x07, 0xb8, 0x34, 0x00, 0x00, 0x00, 0xeb, 0x05
+.data1 	0xb8, 0x24, 0x00, 0x00, 0x00, 0x88, 0x45, 0xfb
+.data1 	0x8b, 0x55, 0x10, 0xc1, 0xea, 0x08, 0x88, 0x55
+.data1 	0xfc, 0x89, 0xf2, 0x88, 0x55, 0xf7, 0x89, 0xf2
+.data1 	0xc1, 0xea, 0x08, 0x88, 0x55, 0xf8, 0x89, 0xf2
+.data1 	0xc1, 0xea, 0x10, 0x88, 0x55, 0xf9, 0x89, 0xf2
+.data1 	0xc1, 0xea, 0x18, 0x88, 0x55, 0xfd, 0x8b, 0x55
+.data1 	0xf0, 0x88, 0x55, 0xfe, 0x8b, 0x55, 0xf0, 0xc1
+.data1 	0xea, 0x08, 0x88, 0x55, 0xff, 0x8b, 0x57, 0x44
+.data1 	0x88, 0x55, 0xfa, 0x8d, 0x45, 0xf5, 0x50, 0xe8
+.data1 	0x43, 0x07, 0x00, 0x00, 0x59, 0xe9, 0x79, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x57, 0x44, 0xf6, 0xc2, 0x40
+.data1 	0x74, 0x25, 0x89, 0xf2, 0x88, 0x55, 0xf7, 0x89
+.data1 	0xf2, 0xc1, 0xea, 0x08, 0x88, 0x55, 0xf8, 0x89
+.data1 	0xf2, 0xc1, 0xea, 0x10, 0x88, 0x55, 0xf9, 0x89
+.data1 	0xf2, 0xc1, 0xea, 0x18, 0x83, 0xe2, 0x0f, 0x0b
+.data1 	0x57, 0x44, 0x88, 0x55, 0xfa, 0xeb, 0x42, 0x89
+.data1 	0xf0, 0x31, 0xd2, 0xf7, 0x75, 0xec, 0x89, 0x45
+.data1 	0xe4, 0x89, 0xf0, 0x31, 0xd2, 0xf7, 0x75, 0xec
+.data1 	0x8b, 0x4f, 0x40, 0x89, 0xd0, 0x31, 0xd2, 0xf7
+.data1 	0xf1, 0x89, 0x45, 0xe0, 0x8b, 0x4f, 0x40, 0x89
+.data1 	0xf0, 0x31, 0xd2, 0xf7, 0xf1, 0x89, 0x55, 0xdc
+.data1 	0x42, 0x88, 0x55, 0xf7, 0x8b, 0x55, 0xe4, 0x88
+.data1 	0x55, 0xf8, 0xc1, 0xfa, 0x08, 0x88, 0x55, 0xf9
+.data1 	0x8b, 0x55, 0xe0, 0x0b, 0x57, 0x44, 0x88, 0x55
+.data1 	0xfa, 0x8d, 0x45, 0xf5, 0x50, 0xe8, 0x21, 0x05
+.data1 	0x00, 0x00, 0x59, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x54, 0x56, 0x57, 0x8b
+.data1 	0x75, 0x14, 0x8b, 0x15, 0x40, 0x22, 0x00, 0x00
+.data1 	0x89, 0x55, 0xfc, 0x8b, 0x55, 0x18, 0xc1, 0xe2
+.data1 	0x03, 0x01, 0xf2, 0x89, 0x55, 0xf4, 0x8b, 0x15
+.data1 	0x7c, 0x22, 0x00, 0x00, 0xff, 0x72, 0x0c, 0xff
+.data1 	0x72, 0x08, 0xe8, 0x25, 0x3b, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0x45, 0xc8, 0x8b, 0x15, 0x40, 0x22
+.data1 	0x00, 0x00, 0x8b, 0x12, 0xf6, 0xc2, 0x08, 0x74
+.data1 	0x1a, 0xff, 0x75, 0x18, 0x56, 0xff, 0x75, 0x10
+.data1 	0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0xe8, 0xd4
+.data1 	0x13, 0x00, 0x00, 0x83, 0xc4, 0x14, 0xe9, 0xbc
+.data1 	0x04, 0x00, 0x00, 0xf7, 0x45, 0x10, 0xff, 0x01
+.data1 	0x00, 0x00, 0x74, 0x0a, 0xb8, 0xea, 0xff, 0xff
+.data1 	0xff, 0xe9, 0xa9, 0x04, 0x00, 0x00, 0xc7, 0x45
+.data1 	0xe4, 0x00, 0x00, 0x00, 0x00, 0x83, 0x7d, 0x18
+.data1 	0x00, 0x0f, 0x84, 0x8c, 0x04, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x89, 0x75
+.data1 	0xf8, 0x8b, 0x55, 0xf4, 0x39, 0x55, 0xf8, 0x73
+.data1 	0x0f, 0x8b, 0x55, 0xf8, 0x8b, 0x52, 0x04, 0x01
+.data1 	0x55, 0xb8, 0x83, 0x45, 0xf8, 0x08, 0xeb, 0xe9
+.data1 	0xf7, 0x45, 0xb8, 0xff, 0x01, 0x00, 0x00, 0x74
+.data1 	0x0a, 0xb8, 0xea, 0xff, 0xff, 0xff, 0xe9, 0x64
+.data1 	0x04, 0x00, 0x00, 0x8b, 0x55, 0xc8, 0x39, 0x55
+.data1 	0x10, 0x72, 0x07, 0x31, 0xc0, 0xe9, 0x55, 0x04
+.data1 	0x00, 0x00, 0x8b, 0x55, 0x10, 0x03, 0x55, 0xb8
+.data1 	0x39, 0x55, 0xc8, 0x73, 0x09, 0x8b, 0x55, 0xc8
+.data1 	0x2b, 0x55, 0x10, 0x89, 0x55, 0xb8, 0x8b, 0x15
+.data1 	0x7c, 0x22, 0x00, 0x00, 0x68, 0x00, 0x02, 0x00
+.data1 	0x00, 0xff, 0x75, 0x10, 0xff, 0x72, 0x04, 0xff
+.data1 	0x32, 0x8d, 0x45, 0xac, 0x50, 0xe8, 0x0a, 0x3a
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x10, 0xff, 0x70, 0x04
+.data1 	0xff, 0x30, 0xe8, 0x69, 0x3a, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0x45, 0xd0, 0x8b, 0x55, 0xfc
+.data1 	0x8b, 0x52, 0x28, 0x89, 0x55, 0xe0, 0x31, 0xdb
+.data1 	0x81, 0x7d, 0x0c, 0x08, 0x04, 0x00, 0x00, 0x75
+.data1 	0x01, 0x43, 0x89, 0x5d, 0xdc, 0x8b, 0x55, 0xfc
+.data1 	0x8b, 0x4d, 0xb8, 0x39, 0x4a, 0x4c, 0x77, 0x06
+.data1 	0x8b, 0x52, 0x4c, 0x89, 0x55, 0xb8, 0x8b, 0x45
+.data1 	0xfc, 0x8b, 0x10, 0xf6, 0xc2, 0x01, 0x75, 0x13
+.data1 	0xe8, 0x71, 0xfc, 0xff, 0xff, 0x85, 0xc0, 0x74
+.data1 	0x0a, 0xb8, 0xfb, 0xff, 0xff, 0xff, 0xe9, 0xcc
+.data1 	0x03, 0x00, 0x00, 0x83, 0x7d, 0xe0, 0x00, 0x74
+.data1 	0x17, 0x8d, 0x45, 0xd8, 0x50, 0xff, 0x75, 0xdc
+.data1 	0x56, 0xff, 0x75, 0x08, 0x8d, 0x45, 0xb8, 0x50
+.data1 	0xe8, 0x27, 0x07, 0x00, 0x00, 0x83, 0xc4, 0x14
+.data1 	0x8b, 0x55, 0xb8, 0xc1, 0xea, 0x09, 0x8b, 0x4d
+.data1 	0xfc, 0xff, 0x75, 0xe0, 0xff, 0x75, 0x0c, 0xff
+.data1 	0x75, 0xd0, 0x52, 0xff, 0x71, 0x48, 0xff, 0x75
+.data1 	0xfc, 0xe8, 0xd1, 0xfc, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x18, 0x89, 0xc7, 0x81, 0x7d, 0x0c, 0x08, 0x04
+.data1 	0x00, 0x00, 0x75, 0x30, 0x8b, 0x55, 0xfc, 0x6a
+.data1 	0x62, 0x8d, 0x45, 0xcc, 0x50, 0xff, 0x72, 0x0c
+.data1 	0xe8, 0x83, 0x33, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x85, 0xc0, 0x74, 0x18, 0x68, 0x00, 0x80, 0x00
+.data1 	0x00, 0x68, 0xdc, 0x05, 0x00, 0x00, 0xe8, 0xc7
+.data1 	0xfa, 0xff, 0xff, 0x50, 0xe8, 0x3b, 0x30, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x83, 0x7d, 0xe0, 0x00
+.data1 	0x0f, 0x84, 0x92, 0x01, 0x00, 0x00, 0xe8, 0xdd
+.data1 	0x0e, 0x00, 0x00, 0x89, 0xc7, 0x85, 0xc0, 0x74
+.data1 	0x2b, 0x83, 0xff, 0xfe, 0x74, 0x12, 0xff, 0x45
+.data1 	0xe4, 0x8b, 0x15, 0xb4, 0x12, 0x00, 0x00, 0x39
+.data1 	0x55, 0xe4, 0x0f, 0x85, 0x85, 0xfe, 0xff, 0xff
+.data1 	0xc7, 0x05, 0x70, 0x22, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0xb8, 0xfb, 0xff, 0xff, 0xff, 0xe9
+.data1 	0x13, 0x03, 0x00, 0x00, 0x6a, 0x04, 0x6a, 0x04
+.data1 	0xe8, 0xf3, 0x0f, 0x00, 0x00, 0x59, 0x59, 0x8b
+.data1 	0x55, 0xfc, 0xb9, 0x02, 0x00, 0x00, 0x00, 0x03
+.data1 	0x4a, 0x10, 0x6a, 0x62, 0x8d, 0x45, 0xd4, 0x50
+.data1 	0x51, 0xe8, 0x02, 0x33, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x89, 0xc7, 0x85, 0xff, 0x74, 0x13, 0x57
+.data1 	0x68, 0xb8, 0x05, 0x00, 0x00, 0x68, 0xd4, 0x05
+.data1 	0x00, 0x00, 0xe8, 0xbd, 0x2f, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x8b, 0x55, 0xd4, 0xf6, 0xc2, 0x04
+.data1 	0x75, 0x56, 0xf6, 0xc2, 0x01, 0x74, 0x1a, 0x68
+.data1 	0x00, 0x80, 0x00, 0x00, 0x68, 0xa0, 0x05, 0x00
+.data1 	0x00, 0xe8, 0x24, 0xfa, 0xff, 0xff, 0x50, 0xe8
+.data1 	0x98, 0x2f, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xeb
+.data1 	0x57, 0x8b, 0x55, 0xd4, 0xf6, 0xc2, 0x02, 0x74
+.data1 	0x15, 0x68, 0x8c, 0x05, 0x00, 0x00, 0xe8, 0xd5
+.data1 	0x28, 0x00, 0x00, 0x59, 0xbf, 0xfb, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x85, 0x02, 0x00, 0x00, 0x68, 0x00
+.data1 	0x80, 0x00, 0x00, 0x68, 0x74, 0x05, 0x00, 0x00
+.data1 	0xe8, 0xed, 0xf9, 0xff, 0xff, 0x50, 0xe8, 0x61
+.data1 	0x2f, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xeb, 0x20
+.data1 	0x8b, 0x55, 0xd4, 0xf6, 0xc2, 0x01, 0x74, 0x18
+.data1 	0x68, 0x00, 0x80, 0x00, 0x00, 0x68, 0x5c, 0x05
+.data1 	0x00, 0x00, 0xe8, 0xcb, 0xf9, 0xff, 0xff, 0x50
+.data1 	0xe8, 0x3f, 0x2f, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xc7, 0x45, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x85
+.data1 	0xff, 0x0f, 0x85, 0x91, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7d, 0xb8, 0x00, 0x0f, 0x84, 0x87, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x56, 0x04, 0x89, 0x55, 0xf0, 0x39
+.data1 	0x55, 0xb8, 0x73, 0x06, 0x8b, 0x55, 0xb8, 0x89
+.data1 	0x55, 0xf0, 0x83, 0x7d, 0xd8, 0x00, 0x74, 0x3f
+.data1 	0x8b, 0x45, 0xb4, 0x05, 0x80, 0x22, 0x00, 0x00
+.data1 	0xff, 0x75, 0xf0, 0xff, 0x36, 0x6a, 0x01, 0xff
+.data1 	0x75, 0x08, 0x50, 0x6a, 0x01, 0x68, 0xce, 0x8a
+.data1 	0x00, 0x00, 0xe8, 0xe9, 0x33, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x1c, 0x89, 0x45, 0xe8, 0x85, 0xc0, 0x74
+.data1 	0x16, 0xff, 0x75, 0xe8, 0x68, 0x3c, 0x05, 0x00
+.data1 	0x00, 0xe8, 0x5c, 0xf9, 0xff, 0xff, 0x50, 0xe8
+.data1 	0xd0, 0x2e, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b
+.data1 	0x55, 0xb8, 0x2b, 0x55, 0xf0, 0x89, 0x55, 0xb8
+.data1 	0x8b, 0x55, 0xf0, 0x01, 0x55, 0x10, 0x01, 0x16
+.data1 	0x8b, 0x56, 0x04, 0x2b, 0x55, 0xf0, 0x89, 0x56
+.data1 	0x04, 0x83, 0x7e, 0x04, 0x00, 0x75, 0x06, 0x83
+.data1 	0xc6, 0x08, 0xff, 0x4d, 0x18, 0x8b, 0x55, 0xf0
+.data1 	0x01, 0x55, 0xb4, 0xe9, 0x67, 0xff, 0xff, 0xff
+.data1 	0x85, 0xff, 0x0f, 0x85, 0x73, 0x01, 0x00, 0x00
+.data1 	0x83, 0x7d, 0xb8, 0x00, 0x0f, 0x84, 0x69, 0x01
+.data1 	0x00, 0x00, 0x81, 0x7d, 0x0c, 0x09, 0x04, 0x00
+.data1 	0x00, 0x0f, 0x85, 0x66, 0x00, 0x00, 0x00, 0xe8
+.data1 	0x2c, 0x0d, 0x00, 0x00, 0x89, 0xc7, 0x85, 0xc0
+.data1 	0x74, 0x5b, 0x8b, 0x15, 0x40, 0x22, 0x00, 0x00
+.data1 	0x0f, 0xb7, 0x4a, 0x04, 0xf6, 0xc1, 0x08, 0x0f
+.data1 	0x84, 0x3e, 0x01, 0x00, 0x00, 0x8b, 0x55, 0xfc
+.data1 	0x68, 0x00, 0x02, 0x00, 0x00, 0xff, 0x35, 0x14
+.data1 	0xdd, 0x00, 0x00, 0x68, 0xce, 0x8a, 0x00, 0x00
+.data1 	0x6a, 0x77, 0xff, 0x72, 0x08, 0x6a, 0x00, 0xe8
+.data1 	0x58, 0x32, 0x00, 0x00, 0x83, 0xc4, 0x18, 0x89
+.data1 	0x45, 0xe8, 0x85, 0xc0, 0x0f, 0x84, 0x11, 0x01
+.data1 	0x00, 0x00, 0xff, 0x75, 0xe8, 0x68, 0x20, 0x05
+.data1 	0x00, 0x00, 0xe8, 0xab, 0xf8, 0xff, 0xff, 0x50
+.data1 	0xe8, 0x1f, 0x2e, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xe9, 0xf6, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x68
+.data1 	0x80, 0x00, 0x00, 0x00, 0xe8, 0x63, 0x0d, 0x00
+.data1 	0x00, 0x59, 0x59, 0x85, 0xc0, 0x75, 0x0a, 0xbf
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe9, 0xda, 0x00, 0x00
+.data1 	0x00, 0x6a, 0x08, 0x6a, 0x08, 0xe8, 0x4a, 0x0d
+.data1 	0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x75, 0x0a
+.data1 	0xbf, 0xff, 0xff, 0xff, 0xff, 0xe9, 0xc1, 0x00
+.data1 	0x00, 0x00, 0x81, 0x7d, 0x0c, 0x09, 0x04, 0x00
+.data1 	0x00, 0x75, 0x3f, 0x8b, 0x55, 0xfc, 0x68, 0x00
+.data1 	0x02, 0x00, 0x00, 0xff, 0x36, 0xff, 0x75, 0x08
+.data1 	0x6a, 0x77, 0xff, 0x72, 0x08, 0x6a, 0x00, 0xe8
+.data1 	0xd8, 0x31, 0x00, 0x00, 0x83, 0xc4, 0x18, 0x89
+.data1 	0x45, 0xe8, 0x85, 0xc0, 0x0f, 0x84, 0x5c, 0x00
+.data1 	0x00, 0x00, 0xff, 0x75, 0xe8, 0x68, 0x04, 0x05
+.data1 	0x00, 0x00, 0xe8, 0x2b, 0xf8, 0xff, 0xff, 0x50
+.data1 	0xe8, 0x9f, 0x2d, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xeb, 0x44, 0x8b, 0x55, 0xfc, 0x68, 0x00, 0x02
+.data1 	0x00, 0x00, 0xff, 0x36, 0xff, 0x75, 0x08, 0x6a
+.data1 	0x77, 0xff, 0x72, 0x08, 0x6a, 0x01, 0xe8, 0x99
+.data1 	0x31, 0x00, 0x00, 0x83, 0xc4, 0x18, 0x89, 0x45
+.data1 	0xe8, 0x85, 0xc0, 0x74, 0x16, 0xff, 0x75, 0xe8
+.data1 	0x68, 0xe8, 0x04, 0x00, 0x00, 0xe8, 0xf0, 0xf7
+.data1 	0xff, 0xff, 0x50, 0xe8, 0x64, 0x2d, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0xe8, 0x10, 0x0c, 0x00, 0x00
+.data1 	0x89, 0xc7, 0x85, 0xc0, 0x75, 0x35, 0x81, 0x6d
+.data1 	0xb8, 0x00, 0x02, 0x00, 0x00, 0x81, 0x45, 0x10
+.data1 	0x00, 0x02, 0x00, 0x00, 0x81, 0x06, 0x00, 0x02
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x04, 0x81, 0xea, 0x00
+.data1 	0x02, 0x00, 0x00, 0x89, 0x56, 0x04, 0x83, 0x7e
+.data1 	0x04, 0x00, 0x0f, 0x85, 0x90, 0xfe, 0xff, 0xff
+.data1 	0x83, 0xc6, 0x08, 0xff, 0x4d, 0x18, 0xe9, 0x85
+.data1 	0xfe, 0xff, 0xff, 0x85, 0xff, 0x0f, 0x84, 0x92
+.data1 	0xfb, 0xff, 0xff, 0x83, 0xff, 0xfe, 0x74, 0x12
+.data1 	0xff, 0x45, 0xe4, 0x8b, 0x15, 0xb4, 0x12, 0x00
+.data1 	0x00, 0x39, 0x55, 0xe4, 0x0f, 0x85, 0x7b, 0xfb
+.data1 	0xff, 0xff, 0xc7, 0x05, 0x70, 0x22, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xb8, 0xfb, 0xff, 0xff
+.data1 	0xff, 0xeb, 0x0c, 0xc7, 0x05, 0x70, 0x22, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0xc0, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x2c, 0x56, 0x57, 0x8b, 0x75, 0x08, 0x8b, 0x15
+.data1 	0x40, 0x22, 0x00, 0x00, 0x89, 0x55, 0xfc, 0x8b
+.data1 	0x7a, 0x08, 0x8b, 0x52, 0x0c, 0x89, 0x55, 0xf4
+.data1 	0x8b, 0x15, 0x40, 0x22, 0x00, 0x00, 0x8b, 0x12
+.data1 	0xf6, 0xc2, 0x20, 0x74, 0x0a, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe9, 0x6c, 0x01, 0x00, 0x00, 0x6a
+.data1 	0x00, 0x68, 0x80, 0x00, 0x00, 0x00, 0xe8, 0xf9
+.data1 	0x0b, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x75
+.data1 	0x1c, 0xe8, 0x1c, 0xf7, 0xff, 0xff, 0x50, 0x68
+.data1 	0x64, 0x06, 0x00, 0x00, 0xe8, 0xdf, 0x25, 0x00
+.data1 	0x00, 0x59, 0x59, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x3e, 0x01, 0x00, 0x00, 0x6a, 0x62, 0x0f
+.data1 	0xb6, 0x46, 0x05, 0x50, 0x8d, 0x47, 0x06, 0x50
+.data1 	0xe8, 0x53, 0x30, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0x45, 0xd4, 0x85, 0xc0, 0x74, 0x16, 0xff
+.data1 	0x75, 0xd4, 0x68, 0x3c, 0x06, 0x00, 0x00, 0xe8
+.data1 	0xde, 0xf6, 0xff, 0xff, 0x50, 0xe8, 0x52, 0x2c
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x6a, 0x00, 0x68
+.data1 	0x80, 0x00, 0x00, 0x00, 0xe8, 0x9b, 0x0b, 0x00
+.data1 	0x00, 0x59, 0x59, 0x85, 0xc0, 0x75, 0x1c, 0xe8
+.data1 	0xbe, 0xf6, 0xff, 0xff, 0x50, 0x68, 0x1c, 0x06
+.data1 	0x00, 0x00, 0xe8, 0x81, 0x25, 0x00, 0x00, 0x59
+.data1 	0x59, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0xe0
+.data1 	0x00, 0x00, 0x00, 0x6a, 0x00, 0xff, 0x35, 0xb8
+.data1 	0x12, 0x00, 0x00, 0xe8, 0x6c, 0x30, 0x00, 0x00
+.data1 	0x59, 0x59, 0x8b, 0x55, 0xfc, 0x66, 0xc7, 0x42
+.data1 	0x04, 0x00, 0x01, 0x0f, 0xb6, 0x56, 0x06, 0x89
+.data1 	0x15, 0x70, 0x22, 0x00, 0x00, 0xba, 0xff, 0xff
+.data1 	0x00, 0x00, 0x23, 0x55, 0xf4, 0x66, 0x89, 0x55
+.data1 	0xd8, 0x8b, 0x55, 0xfc, 0x83, 0x7a, 0x3c, 0x08
+.data1 	0x72, 0x07, 0xb8, 0x08, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x02, 0x31, 0xc0, 0x88, 0x45, 0xda, 0x8d, 0x57
+.data1 	0x01, 0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x66
+.data1 	0x89, 0x55, 0xdc, 0x8a, 0x0e, 0x88, 0x4d, 0xde
+.data1 	0x8d, 0x57, 0x02, 0x81, 0xe2, 0xff, 0xff, 0x00
+.data1 	0x00, 0x66, 0x89, 0x55, 0xe0, 0x8a, 0x4e, 0x01
+.data1 	0x88, 0x4d, 0xe2, 0x8d, 0x57, 0x03, 0x81, 0xe2
+.data1 	0xff, 0xff, 0x00, 0x00, 0x66, 0x89, 0x55, 0xe4
+.data1 	0x8a, 0x4e, 0x02, 0x88, 0x4d, 0xe6, 0x8d, 0x57
+.data1 	0x04, 0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x66
+.data1 	0x89, 0x55, 0xe8, 0x8a, 0x4e, 0x03, 0x88, 0x4d
+.data1 	0xea, 0x8d, 0x57, 0x05, 0x81, 0xe2, 0xff, 0xff
+.data1 	0x00, 0x00, 0x66, 0x89, 0x55, 0xec, 0x8a, 0x4e
+.data1 	0x04, 0x88, 0x4d, 0xee, 0x8d, 0x57, 0x07, 0x81
+.data1 	0xe2, 0xff, 0xff, 0x00, 0x00, 0x66, 0x89, 0x55
+.data1 	0xf0, 0x8a, 0x4e, 0x06, 0x88, 0x4d, 0xf2, 0x6a
+.data1 	0x07, 0x8d, 0x45, 0xd8, 0x50, 0xe8, 0xb2, 0x30
+.data1 	0x00, 0x00, 0x59, 0x59, 0x89, 0x45, 0xd4, 0x85
+.data1 	0xc0, 0x74, 0x16, 0xff, 0x75, 0xd4, 0x68, 0xf0
+.data1 	0x05, 0x00, 0x00, 0xe8, 0xd2, 0xf5, 0xff, 0xff
+.data1 	0x50, 0xe8, 0x46, 0x2b, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x40, 0x56, 0x57, 0x8b
+.data1 	0x75, 0x08, 0x8b, 0x15, 0x40, 0x22, 0x00, 0x00
+.data1 	0x89, 0x55, 0xfc, 0x8b, 0x7a, 0x08, 0x8b, 0x52
+.data1 	0x0c, 0x89, 0x55, 0xf4, 0x8b, 0x15, 0x40, 0x22
+.data1 	0x00, 0x00, 0x8b, 0x12, 0xf6, 0xc2, 0x20, 0x74
+.data1 	0x0a, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x95
+.data1 	0x01, 0x00, 0x00, 0x6a, 0x00, 0x68, 0x80, 0x00
+.data1 	0x00, 0x00, 0xe8, 0x55, 0x0a, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x75, 0x1c, 0xe8, 0x78, 0xf5
+.data1 	0xff, 0xff, 0x50, 0x68, 0xf4, 0x06, 0x00, 0x00
+.data1 	0xe8, 0x3b, 0x24, 0x00, 0x00, 0x59, 0x59, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe9, 0x67, 0x01, 0x00
+.data1 	0x00, 0x6a, 0x62, 0x0f, 0xb6, 0x46, 0x05, 0x50
+.data1 	0x8d, 0x47, 0x06, 0x50, 0xe8, 0xaf, 0x2e, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45, 0xc4, 0x85
+.data1 	0xc0, 0x74, 0x16, 0xff, 0x75, 0xc4, 0x68, 0xcc
+.data1 	0x06, 0x00, 0x00, 0xe8, 0x3a, 0xf5, 0xff, 0xff
+.data1 	0x50, 0xe8, 0xae, 0x2a, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x6a, 0x00, 0x68, 0x80, 0x00, 0x00, 0x00
+.data1 	0xe8, 0xf7, 0x09, 0x00, 0x00, 0x59, 0x59, 0x85
+.data1 	0xc0, 0x75, 0x1c, 0xe8, 0x1a, 0xf5, 0xff, 0xff
+.data1 	0x50, 0x68, 0xac, 0x06, 0x00, 0x00, 0xe8, 0xdd
+.data1 	0x23, 0x00, 0x00, 0x59, 0x59, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe9, 0x09, 0x01, 0x00, 0x00, 0x6a
+.data1 	0x00, 0xff, 0x35, 0xb8, 0x12, 0x00, 0x00, 0xe8
+.data1 	0xc8, 0x2e, 0x00, 0x00, 0x59, 0x59, 0x8b, 0x55
+.data1 	0xfc, 0x66, 0xc7, 0x42, 0x04, 0x00, 0x01, 0x0f
+.data1 	0xb6, 0x56, 0x06, 0x89, 0x15, 0x70, 0x22, 0x00
+.data1 	0x00, 0xba, 0xff, 0xff, 0x00, 0x00, 0x23, 0x55
+.data1 	0xf4, 0x66, 0x89, 0x55, 0xc8, 0xc6, 0x45, 0xca
+.data1 	0x00, 0x8d, 0x57, 0x02, 0x81, 0xe2, 0xff, 0xff
+.data1 	0x00, 0x00, 0x66, 0x89, 0x55, 0xcc, 0x8a, 0x4e
+.data1 	0x07, 0x88, 0x4d, 0xce, 0x8d, 0x57, 0x03, 0x81
+.data1 	0xe2, 0xff, 0xff, 0x00, 0x00, 0x66, 0x89, 0x55
+.data1 	0xd0, 0x8a, 0x4e, 0x08, 0x88, 0x4d, 0xd2, 0x8d
+.data1 	0x57, 0x04, 0x81, 0xe2, 0xff, 0xff, 0x00, 0x00
+.data1 	0x66, 0x89, 0x55, 0xd4, 0x8a, 0x4e, 0x09, 0x88
+.data1 	0x4d, 0xd6, 0x8d, 0x57, 0x05, 0x81, 0xe2, 0xff
+.data1 	0xff, 0x00, 0x00, 0x66, 0x89, 0x55, 0xd8, 0x8a
+.data1 	0x4e, 0x0a, 0x88, 0x4d, 0xda, 0x8d, 0x57, 0x02
+.data1 	0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x66, 0x89
+.data1 	0x55, 0xdc, 0x8a, 0x4e, 0x01, 0x88, 0x4d, 0xde
+.data1 	0x8d, 0x57, 0x03, 0x81, 0xe2, 0xff, 0xff, 0x00
+.data1 	0x00, 0x66, 0x89, 0x55, 0xe0, 0x8a, 0x4e, 0x02
+.data1 	0x88, 0x4d, 0xe2, 0x8d, 0x57, 0x04, 0x81, 0xe2
+.data1 	0xff, 0xff, 0x00, 0x00, 0x66, 0x89, 0x55, 0xe4
+.data1 	0x8a, 0x4e, 0x03, 0x88, 0x4d, 0xe6, 0x8d, 0x57
+.data1 	0x05, 0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x66
+.data1 	0x89, 0x55, 0xe8, 0x8a, 0x4e, 0x04, 0x88, 0x4d
+.data1 	0xea, 0x8d, 0x57, 0x07, 0x81, 0xe2, 0xff, 0xff
+.data1 	0x00, 0x00, 0x66, 0x89, 0x55, 0xf0, 0x8a, 0x4e
+.data1 	0x06, 0x88, 0x4d, 0xf2, 0x6a, 0x0b, 0x8d, 0x45
+.data1 	0xc8, 0x50, 0xe8, 0xe5, 0x2e, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0x45, 0xc4, 0x85, 0xc0, 0x74, 0x16
+.data1 	0xff, 0x75, 0xc4, 0x68, 0x80, 0x06, 0x00, 0x00
+.data1 	0xe8, 0x05, 0xf4, 0xff, 0xff, 0x50, 0xe8, 0x79
+.data1 	0x29, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x31, 0xc0
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x30, 0x56, 0x57, 0x8b, 0x15, 0x40, 0x22
+.data1 	0x00, 0x00, 0x89, 0x55, 0xd4, 0x8b, 0x45, 0x08
+.data1 	0x8b, 0x10, 0x89, 0x55, 0xec, 0xc7, 0x45, 0xe8
+.data1 	0x00, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xe4, 0x00
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x45, 0xdc, 0x00, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x45, 0xf0, 0x00, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7d, 0xec, 0x00, 0x0f, 0x84, 0x49
+.data1 	0x01, 0x00, 0x00, 0x8b, 0x55, 0xe8, 0xc1, 0xe2
+.data1 	0x03, 0x03, 0x55, 0x10, 0x8b, 0x52, 0x04, 0x2b
+.data1 	0x55, 0xf0, 0x89, 0xd7, 0x39, 0x7d, 0xec, 0x73
+.data1 	0x03, 0x8b, 0x7d, 0xec, 0x85, 0xff, 0x74, 0x08
+.data1 	0xf7, 0xc7, 0x01, 0x00, 0x00, 0x00, 0x74, 0x1e
+.data1 	0x8b, 0x55, 0xe8, 0xc1, 0xe2, 0x03, 0x03, 0x55
+.data1 	0x10, 0xff, 0x72, 0x04, 0x68, 0x14, 0x09, 0x00
+.data1 	0x00, 0x68, 0x24, 0x09, 0x00, 0x00, 0xe8, 0xf1
+.data1 	0x28, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55
+.data1 	0xe8, 0x8b, 0x4d, 0x10, 0x8b, 0x5d, 0xf0, 0x03
+.data1 	0x1c, 0xd1, 0x8d, 0x45, 0xf8, 0x50, 0x57, 0x53
+.data1 	0x6a, 0x01, 0xff, 0x75, 0x0c, 0xe8, 0x52, 0x2d
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x14, 0x89, 0xc6, 0x85
+.data1 	0xf6, 0x74, 0x13, 0x56, 0x68, 0xf4, 0x08, 0x00
+.data1 	0x00, 0x68, 0x0c, 0x09, 0x00, 0x00, 0xe8, 0xb9
+.data1 	0x28, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55
+.data1 	0xf8, 0xf6, 0xc2, 0x01, 0x74, 0x17, 0x68, 0xcc
+.data1 	0x08, 0x00, 0x00, 0xe8, 0xf8, 0x21, 0x00, 0x00
+.data1 	0x59, 0xc7, 0x45, 0xdc, 0x01, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xaf, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xf8
+.data1 	0x01, 0xfa, 0x83, 0xea, 0x01, 0xb9, 0x00, 0x00
+.data1 	0x01, 0x00, 0x89, 0xd0, 0x31, 0xd2, 0xf7, 0xf1
+.data1 	0x50, 0x8b, 0x45, 0xf8, 0x31, 0xd2, 0xf7, 0xf1
+.data1 	0x5a, 0x39, 0xc2, 0x74, 0x17, 0x8b, 0x45, 0xf8
+.data1 	0x31, 0xd2, 0xf7, 0xf1, 0x05, 0x01, 0x00, 0x00
+.data1 	0x00, 0x69, 0xc0, 0x00, 0x00, 0x01, 0x00, 0x2b
+.data1 	0x45, 0xf8, 0x89, 0xc7, 0x81, 0x7d, 0xe4, 0x00
+.data1 	0x04, 0x00, 0x00, 0x7c, 0x0c, 0xc7, 0x45, 0xdc
+.data1 	0x01, 0x00, 0x00, 0x00, 0xe9, 0x63, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xe4, 0x8b, 0x4d, 0xf8, 0x89
+.data1 	0x0c, 0xd5, 0x84, 0xa2, 0x00, 0x00, 0xba, 0xff
+.data1 	0xff, 0x00, 0x00, 0x21, 0xfa, 0x8b, 0x4d, 0xe4
+.data1 	0x66, 0x89, 0x14, 0xcd, 0x88, 0xa2, 0x00, 0x00
+.data1 	0x8b, 0x55, 0xe4, 0xc6, 0x04, 0xd5, 0x8a, 0xa2
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0xe4, 0xc6, 0x04
+.data1 	0xd5, 0x8b, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x45
+.data1 	0xe4, 0x01, 0x7d, 0xf0, 0x8b, 0x55, 0xe8, 0xc1
+.data1 	0xe2, 0x03, 0x03, 0x55, 0x10, 0x8b, 0x4d, 0xf0
+.data1 	0x39, 0x4a, 0x04, 0x77, 0x0a, 0xff, 0x45, 0xe8
+.data1 	0xc7, 0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xec, 0x29, 0xfa, 0x89, 0x55, 0xec, 0xe9
+.data1 	0xad, 0xfe, 0xff, 0xff, 0x83, 0x7d, 0xdc, 0x00
+.data1 	0x75, 0x3d, 0x83, 0x7d, 0xe4, 0x00, 0x7e, 0x09
+.data1 	0x81, 0x7d, 0xe4, 0x00, 0x04, 0x00, 0x00, 0x7e
+.data1 	0x15, 0xff, 0x75, 0xe4, 0x68, 0xb4, 0x08, 0x00
+.data1 	0x00, 0x68, 0xc4, 0x08, 0x00, 0x00, 0xe8, 0xc1
+.data1 	0x27, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55
+.data1 	0xe4, 0x4a, 0x8d, 0x14, 0xd5, 0x8b, 0xa2, 0x00
+.data1 	0x00, 0x89, 0x55, 0xd0, 0x0f, 0xb6, 0x0a, 0x81
+.data1 	0xc9, 0x80, 0x00, 0x00, 0x00, 0x88, 0x0a, 0x83
+.data1 	0x7d, 0x14, 0x00, 0x75, 0x0d, 0x83, 0x7d, 0xdc
+.data1 	0x00, 0x74, 0x07, 0xb8, 0x01, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x02, 0x31, 0xc0, 0x8b, 0x5d, 0x18, 0x89
+.data1 	0x03, 0x83, 0x7d, 0xdc, 0x00, 0x0f, 0x84, 0xb7
+.data1 	0x01, 0x00, 0x00, 0x8b, 0x45, 0x08, 0x8b, 0x10
+.data1 	0x89, 0x55, 0xec, 0x81, 0xfa, 0x00, 0x80, 0x00
+.data1 	0x00, 0x76, 0x0d, 0xba, 0x00, 0x80, 0x00, 0x00
+.data1 	0x89, 0x55, 0xec, 0x8b, 0x45, 0x08, 0x89, 0x10
+.data1 	0x83, 0x7d, 0x14, 0x00, 0x0f, 0x84, 0x69, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x45, 0xf0, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xec, 0x39, 0x55, 0xf0, 0x0f
+.data1 	0x83, 0x56, 0x00, 0x00, 0x00, 0x2b, 0x55, 0xf0
+.data1 	0x89, 0xd7, 0x8b, 0x55, 0x10, 0x39, 0x7a, 0x04
+.data1 	0x73, 0x03, 0x8b, 0x7a, 0x04, 0x8b, 0x45, 0xf0
+.data1 	0x05, 0x80, 0x22, 0x00, 0x00, 0x8b, 0x5d, 0x10
+.data1 	0x57, 0x50, 0x6a, 0x01, 0x68, 0xce, 0x8a, 0x00
+.data1 	0x00, 0xff, 0x33, 0x6a, 0x01, 0xff, 0x75, 0x0c
+.data1 	0xe8, 0x13, 0x2c, 0x00, 0x00, 0x83, 0xc4, 0x1c
+.data1 	0x89, 0xc6, 0x85, 0xf6, 0x74, 0x14, 0x56, 0x68
+.data1 	0x94, 0x08, 0x00, 0x00, 0xe8, 0x89, 0xf1, 0xff
+.data1 	0xff, 0x50, 0xe8, 0xfd, 0x26, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x83, 0x45, 0x10, 0x08, 0x01, 0x7d
+.data1 	0xf0, 0xeb, 0x9e, 0x8b, 0x15, 0x80, 0xa2, 0x00
+.data1 	0x00, 0x89, 0x55, 0xfc, 0xf6, 0xc2, 0x01, 0x74
+.data1 	0x15, 0xff, 0x75, 0xfc, 0x68, 0x68, 0x08, 0x00
+.data1 	0x00, 0x68, 0x8c, 0x08, 0x00, 0x00, 0xe8, 0xd1
+.data1 	0x26, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc7, 0x45
+.data1 	0xe4, 0x00, 0x00, 0x00, 0x00, 0x81, 0x7d, 0xe4
+.data1 	0x00, 0x04, 0x00, 0x00, 0x0f, 0x8d, 0xd3, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7d, 0xec, 0x00, 0x75, 0x15
+.data1 	0xff, 0x75, 0xec, 0x68, 0x48, 0x08, 0x00, 0x00
+.data1 	0x68, 0x60, 0x08, 0x00, 0x00, 0xe8, 0xa2, 0x26
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55, 0xec
+.data1 	0xf6, 0xc2, 0x01, 0x74, 0x15, 0xff, 0x75, 0xec
+.data1 	0x68, 0x20, 0x08, 0x00, 0x00, 0x68, 0x40, 0x08
+.data1 	0x00, 0x00, 0xe8, 0x85, 0x26, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x8b, 0x7d, 0xec, 0x8b, 0x55, 0xfc
+.data1 	0x01, 0xfa, 0x83, 0xea, 0x01, 0xb9, 0x00, 0x00
+.data1 	0x01, 0x00, 0x89, 0xd0, 0x31, 0xd2, 0xf7, 0xf1
+.data1 	0x50, 0x8b, 0x45, 0xfc, 0x31, 0xd2, 0xf7, 0xf1
+.data1 	0x5a, 0x39, 0xc2, 0x74, 0x17, 0x8b, 0x45, 0xfc
+.data1 	0x31, 0xd2, 0xf7, 0xf1, 0x05, 0x01, 0x00, 0x00
+.data1 	0x00, 0x69, 0xc0, 0x00, 0x00, 0x01, 0x00, 0x2b
+.data1 	0x45, 0xfc, 0x89, 0xc7, 0x8b, 0x55, 0xe4, 0x8b
+.data1 	0x4d, 0xfc, 0x89, 0x0c, 0xd5, 0x84, 0xa2, 0x00
+.data1 	0x00, 0xba, 0xff, 0xff, 0x00, 0x00, 0x21, 0xfa
+.data1 	0x8b, 0x4d, 0xe4, 0x66, 0x89, 0x14, 0xcd, 0x88
+.data1 	0xa2, 0x00, 0x00, 0x8b, 0x55, 0xe4, 0xc6, 0x04
+.data1 	0xd5, 0x8a, 0xa2, 0x00, 0x00, 0x00, 0x8b, 0x55
+.data1 	0xe4, 0xc6, 0x04, 0xd5, 0x8b, 0xa2, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xec, 0x29, 0xfa, 0x89, 0x55
+.data1 	0xec, 0x75, 0x1a, 0x8b, 0x55, 0xe4, 0x8d, 0x14
+.data1 	0xd5, 0x8b, 0xa2, 0x00, 0x00, 0x89, 0x55, 0xd0
+.data1 	0x0f, 0xb6, 0x0a, 0x81, 0xc9, 0x80, 0x00, 0x00
+.data1 	0x00, 0x88, 0x0a, 0xeb, 0x08, 0xff, 0x45, 0xe8
+.data1 	0xe9, 0x20, 0xff, 0xff, 0xff, 0x83, 0x7d, 0xec
+.data1 	0x00, 0x74, 0x17, 0x68, 0x00, 0x80, 0x00, 0x00
+.data1 	0x68, 0x00, 0x08, 0x00, 0x00, 0x68, 0x18, 0x08
+.data1 	0x00, 0x00, 0xe8, 0xcd, 0x25, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x8b, 0x55, 0xd4, 0x6a, 0x62, 0x6a
+.data1 	0x00, 0xff, 0x72, 0x10, 0xe8, 0x9f, 0x29, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x89, 0xc6, 0x85, 0xf6
+.data1 	0x74, 0x13, 0x56, 0x68, 0xdc, 0x07, 0x00, 0x00
+.data1 	0x68, 0xf8, 0x07, 0x00, 0x00, 0xe8, 0xa2, 0x25
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55, 0xd4
+.data1 	0xb9, 0x02, 0x00, 0x00, 0x00, 0x03, 0x4a, 0x10
+.data1 	0x6a, 0x62, 0x8d, 0x45, 0xd8, 0x50, 0x51, 0xe8
+.data1 	0xb4, 0x28, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0xc6, 0x85, 0xf6, 0x74, 0x13, 0x56, 0x68, 0xb8
+.data1 	0x07, 0x00, 0x00, 0x68, 0xd4, 0x07, 0x00, 0x00
+.data1 	0xe8, 0x6f, 0x25, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x8b, 0x55, 0xd8, 0xf6, 0xc2, 0x01, 0x74, 0x17
+.data1 	0x68, 0x00, 0x80, 0x00, 0x00, 0x68, 0x98, 0x07
+.data1 	0x00, 0x00, 0x68, 0xb0, 0x07, 0x00, 0x00, 0xe8
+.data1 	0x50, 0x25, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b
+.data1 	0x15, 0x84, 0xc2, 0x00, 0x00, 0xf6, 0xc2, 0x03
+.data1 	0x74, 0x18, 0xff, 0x35, 0x84, 0xc2, 0x00, 0x00
+.data1 	0x68, 0x7c, 0x07, 0x00, 0x00, 0x68, 0x90, 0x07
+.data1 	0x00, 0x00, 0xe8, 0x2d, 0x25, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x8b, 0x55, 0xd4, 0xb9, 0x04, 0x00
+.data1 	0x00, 0x00, 0x03, 0x4a, 0x10, 0x6a, 0x6c, 0xff
+.data1 	0x35, 0x84, 0xc2, 0x00, 0x00, 0x51, 0xe8, 0xf5
+.data1 	0x28, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0xc6
+.data1 	0x85, 0xf6, 0x74, 0x13, 0x56, 0x68, 0x58, 0x07
+.data1 	0x00, 0x00, 0x68, 0x74, 0x07, 0x00, 0x00, 0xe8
+.data1 	0xf8, 0x24, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b
+.data1 	0x55, 0xd4, 0xb9, 0x02, 0x00, 0x00, 0x00, 0x03
+.data1 	0x4a, 0x10, 0x6a, 0x62, 0x6a, 0x06, 0x51, 0xe8
+.data1 	0xc4, 0x28, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0xc6, 0x85, 0xf6, 0x74, 0x13, 0x56, 0x68, 0x34
+.data1 	0x07, 0x00, 0x00, 0x68, 0x50, 0x07, 0x00, 0x00
+.data1 	0xe8, 0xc7, 0x24, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xc7, 0x45, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7d, 0x14, 0x00, 0x75, 0x04, 0x83, 0x4d, 0xd8
+.data1 	0x08, 0x8b, 0x55, 0xd4, 0x6a, 0x62, 0xff, 0x75
+.data1 	0xd8, 0xff, 0x72, 0x10, 0xe8, 0x87, 0x28, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x89, 0xc6, 0x85, 0xf6
+.data1 	0x74, 0x13, 0x56, 0x68, 0x10, 0x07, 0x00, 0x00
+.data1 	0x68, 0x2c, 0x07, 0x00, 0x00, 0xe8, 0x8a, 0x24
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x56, 0x57, 0x31, 0xff
+.data1 	0xbe, 0x20, 0x15, 0x00, 0x00, 0x81, 0xfe, 0x40
+.data1 	0x22, 0x00, 0x00, 0x73, 0x1d, 0x8b, 0x15, 0x40
+.data1 	0x22, 0x00, 0x00, 0x8b, 0x52, 0x08, 0x39, 0x56
+.data1 	0x08, 0x75, 0x06, 0x83, 0x0e, 0x02, 0x83, 0x26
+.data1 	0xfe, 0x81, 0xc6, 0xa4, 0x01, 0x00, 0x00, 0x47
+.data1 	0xeb, 0xdb, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x8b, 0x55, 0x0c, 0xff, 0x72, 0x08, 0xe8
+.data1 	0x31, 0xe6, 0xff, 0xff, 0x59, 0x85, 0xc0, 0x75
+.data1 	0x07, 0xb8, 0xfa, 0xff, 0xff, 0xff, 0xeb, 0x2f
+.data1 	0x8b, 0x15, 0x40, 0x22, 0x00, 0x00, 0x8b, 0x52
+.data1 	0x50, 0x83, 0xea, 0x01, 0x8b, 0x0d, 0x40, 0x22
+.data1 	0x00, 0x00, 0x89, 0x51, 0x50, 0x8b, 0x15, 0x40
+.data1 	0x22, 0x00, 0x00, 0x83, 0x7a, 0x50, 0x00, 0x75
+.data1 	0x0c, 0x8b, 0x12, 0xf6, 0xc2, 0x08, 0x74, 0x05
+.data1 	0xe8, 0x28, 0x05, 0x00, 0x00, 0x31, 0xc0, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b, 0x15, 0x40
+.data1 	0x22, 0x00, 0x00, 0x8b, 0x12, 0xf6, 0xc2, 0x20
+.data1 	0x74, 0x07, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x22, 0xff, 0x75, 0x08, 0xe8, 0x02, 0xf7, 0xff
+.data1 	0xff, 0x59, 0x89, 0xc6, 0x85, 0xc0, 0x75, 0x07
+.data1 	0xe8, 0x8b, 0x02, 0x00, 0x00, 0x89, 0xc6, 0xc7
+.data1 	0x05, 0x70, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x89, 0xf0, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x56, 0x8b, 0x35, 0x40, 0x22, 0x00, 0x00
+.data1 	0xe9, 0x56, 0x00, 0x00, 0x00, 0x81, 0x7e, 0x4c
+.data1 	0x00, 0x10, 0x00, 0x00, 0x76, 0x09, 0xc7, 0x46
+.data1 	0x4c, 0x00, 0x10, 0x00, 0x00, 0xeb, 0x07, 0xc7
+.data1 	0x46, 0x4c, 0x00, 0x02, 0x00, 0x00, 0x83, 0x3d
+.data1 	0xd0, 0x12, 0x00, 0x00, 0x00, 0x74, 0x05, 0x83
+.data1 	0x0e, 0x20, 0xeb, 0x22, 0x83, 0x3d, 0xd4, 0x12
+.data1 	0x00, 0x00, 0x00, 0x75, 0x19, 0xff, 0x35, 0x70
+.data1 	0x22, 0x00, 0x00, 0xe8, 0x02, 0xee, 0xff, 0xff
+.data1 	0x50, 0x68, 0x5c, 0x09, 0x00, 0x00, 0xe8, 0xc5
+.data1 	0x1c, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xe8, 0xe6
+.data1 	0xfe, 0xff, 0xff, 0x66, 0xc7, 0x46, 0x04, 0x00
+.data1 	0x00, 0xeb, 0x0f, 0xbb, 0x2c, 0x09, 0x00, 0x00
+.data1 	0xa1, 0x70, 0x22, 0x00, 0x00, 0xe9, 0x1a, 0x31
+.data1 	0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0x57, 0x8b, 0x35, 0x40, 0x22, 0x00, 0x00
+.data1 	0x8b, 0x15, 0x40, 0x22, 0x00, 0x00, 0x8b, 0x12
+.data1 	0xf6, 0xc2, 0x20, 0x74, 0x0a, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe9, 0xdb, 0x00, 0x00, 0x00, 0x6a
+.data1 	0x1e, 0xe8, 0x7e, 0x20, 0x00, 0x00, 0x59, 0x6a
+.data1 	0x62, 0x6a, 0x04, 0xff, 0x76, 0x0c, 0xe8, 0xfd
+.data1 	0x26, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0xc7
+.data1 	0x85, 0xc0, 0x74, 0x14, 0x57, 0x68, 0xb8, 0x09
+.data1 	0x00, 0x00, 0xe8, 0x8b, 0xed, 0xff, 0xff, 0x50
+.data1 	0xe8, 0xff, 0x22, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x6a, 0x01, 0xe8, 0x4d, 0x20, 0x00, 0x00, 0x59
+.data1 	0x6a, 0x62, 0x6a, 0x00, 0xff, 0x76, 0x0c, 0xe8
+.data1 	0xcc, 0x26, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0xc7, 0x85, 0xc0, 0x74, 0x14, 0x57, 0x68, 0x9c
+.data1 	0x09, 0x00, 0x00, 0xe8, 0x5a, 0xed, 0xff, 0xff
+.data1 	0x50, 0xe8, 0xce, 0x22, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x6a, 0x01, 0xe8, 0x1c, 0x20, 0x00, 0x00
+.data1 	0x59, 0x6a, 0x00, 0x68, 0x80, 0x00, 0x00, 0x00
+.data1 	0xe8, 0x0f, 0x02, 0x00, 0x00, 0x59, 0x59, 0x85
+.data1 	0xc0, 0x75, 0x19, 0xe8, 0x32, 0xed, 0xff, 0xff
+.data1 	0x50, 0x68, 0x7c, 0x09, 0x00, 0x00, 0xe8, 0xf5
+.data1 	0x1b, 0x00, 0x00, 0x59, 0x59, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xeb, 0x46, 0xbe, 0x20, 0x15, 0x00
+.data1 	0x00, 0x81, 0xfe, 0x40, 0x22, 0x00, 0x00, 0x73
+.data1 	0x37, 0x8b, 0x15, 0x40, 0x22, 0x00, 0x00, 0x8b
+.data1 	0x52, 0x08, 0x39, 0x56, 0x08, 0x75, 0x21, 0x83
+.data1 	0x26, 0xfd, 0x8b, 0x15, 0x40, 0x22, 0x00, 0x00
+.data1 	0x83, 0x7a, 0x1c, 0x00, 0x74, 0x12, 0x83, 0xc2
+.data1 	0x20, 0x52, 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x03
+.data1 	0xe8, 0xc7, 0x25, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x81, 0xc6, 0xa4, 0x01, 0x00, 0x00, 0xeb, 0xc1
+.data1 	0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x30, 0x56, 0x8b, 0x15, 0x40
+.data1 	0x22, 0x00, 0x00, 0x83, 0x7a, 0x14, 0x00, 0x0f
+.data1 	0x84, 0xda, 0x00, 0x00, 0x00, 0x8b, 0x15, 0x40
+.data1 	0x22, 0x00, 0x00, 0x0f, 0xb7, 0x4a, 0x04, 0xf7
+.data1 	0xc1, 0x80, 0x01, 0x00, 0x00, 0x0f, 0x84, 0xd2
+.data1 	0x00, 0x00, 0x00, 0x8d, 0x45, 0xd4, 0x50, 0x68
+.data1 	0xce, 0x7a, 0x00, 0x00, 0xe8, 0xcf, 0x2b, 0x00
+.data1 	0x00, 0x59, 0x59, 0x89, 0x45, 0xd0, 0x85, 0xc0
+.data1 	0x74, 0x0f, 0x56, 0x68, 0x18, 0x0a, 0x00, 0x00
+.data1 	0xe8, 0x53, 0x1b, 0x00, 0x00, 0x59, 0x59, 0xeb
+.data1 	0xc4, 0x81, 0x7d, 0xd8, 0x01, 0x10, 0x00, 0x00
+.data1 	0x75, 0x07, 0xe8, 0x27, 0xfe, 0xff, 0xff, 0xeb
+.data1 	0xb4, 0x81, 0x7d, 0xd8, 0x03, 0x10, 0x00, 0x00
+.data1 	0x75, 0x56, 0x8b, 0x15, 0x40, 0x22, 0x00, 0x00
+.data1 	0xb9, 0x07, 0x00, 0x00, 0x00, 0x03, 0x4a, 0x08
+.data1 	0x6a, 0x62, 0x8d, 0x45, 0xf8, 0x50, 0x51, 0xe8
+.data1 	0xf4, 0x24, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0xc6, 0x85, 0xf6, 0x74, 0x13, 0x56, 0x68, 0x00
+.data1 	0x0a, 0x00, 0x00, 0x68, 0x10, 0x0a, 0x00, 0x00
+.data1 	0xe8, 0xaf, 0x21, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xba, 0xff, 0xff, 0x00, 0x00, 0x23, 0x55, 0xf8
+.data1 	0x8b, 0x0d, 0x40, 0x22, 0x00, 0x00, 0x66, 0x89
+.data1 	0x51, 0x04, 0xff, 0x75, 0xe8, 0xe8, 0x4f, 0x0b
+.data1 	0x00, 0x00, 0x59, 0xe9, 0x55, 0xff, 0xff, 0xff
+.data1 	0x81, 0x7d, 0xd8, 0x06, 0x10, 0x00, 0x00, 0x75
+.data1 	0x0e, 0xff, 0x75, 0xd4, 0xe8, 0x5f, 0x2b, 0x00
+.data1 	0x00, 0x59, 0xe9, 0x3e, 0xff, 0xff, 0xff, 0xff
+.data1 	0x75, 0xd4, 0xff, 0x75, 0xd8, 0x68, 0xd4, 0x09
+.data1 	0x00, 0x00, 0xe8, 0xb9, 0x1a, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xe9, 0x26, 0xff, 0xff, 0xff, 0x6a
+.data1 	0x00, 0x68, 0x80, 0x00, 0x00, 0x00, 0xe8, 0xa9
+.data1 	0x00, 0x00, 0x00, 0x59, 0x59, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c, 0x56, 0xe8
+.data1 	0xf2, 0xfe, 0xff, 0xff, 0x8b, 0x15, 0x40, 0x22
+.data1 	0x00, 0x00, 0x0f, 0xb7, 0x4a, 0x04, 0xf6, 0xc1
+.data1 	0xa1, 0x75, 0x07, 0x31, 0xf6, 0xe9, 0x5d, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x15, 0x40, 0x22, 0x00, 0x00
+.data1 	0xb9, 0x01, 0x00, 0x00, 0x00, 0x03, 0x4a, 0x08
+.data1 	0x6a, 0x62, 0x8d, 0x45, 0xf4, 0x50, 0x51, 0xe8
+.data1 	0x3c, 0x24, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0x45, 0xf8, 0x85, 0xc0, 0x74, 0x16, 0xff, 0x75
+.data1 	0xf8, 0x68, 0x44, 0x0a, 0x00, 0x00, 0xe8, 0x7f
+.data1 	0xeb, 0xff, 0xff, 0x50, 0xe8, 0xf3, 0x20, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x15, 0x40, 0x22
+.data1 	0x00, 0x00, 0x0f, 0xb7, 0x4a, 0x04, 0xf6, 0xc1
+.data1 	0x01, 0x74, 0x0f, 0x8b, 0x55, 0xf4, 0xf6, 0xc2
+.data1 	0x80, 0x74, 0x07, 0xbe, 0xfe, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x05, 0xbe, 0xff, 0xff, 0xff, 0xff, 0x8b
+.data1 	0x15, 0x40, 0x22, 0x00, 0x00, 0x0f, 0xb7, 0x4a
+.data1 	0x04, 0x81, 0xc9, 0x00, 0x01, 0x00, 0x00, 0x81
+.data1 	0xe1, 0xff, 0xff, 0x00, 0x00, 0x8b, 0x15, 0x40
+.data1 	0x22, 0x00, 0x00, 0x66, 0x89, 0x4a, 0x04, 0x89
+.data1 	0xf0, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x0c, 0x56, 0x8d, 0x45, 0xf8, 0x50, 0xe8
+.data1 	0xb4, 0x19, 0x00, 0x00, 0x59, 0x8b, 0x15, 0x40
+.data1 	0x22, 0x00, 0x00, 0xb9, 0x07, 0x00, 0x00, 0x00
+.data1 	0x03, 0x4a, 0x08, 0x6a, 0x62, 0x8d, 0x45, 0xfc
+.data1 	0x50, 0x51, 0xe8, 0xa9, 0x23, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0xc6, 0x85, 0xc0, 0x74, 0x14
+.data1 	0x56, 0x68, 0x88, 0x0a, 0x00, 0x00, 0xe8, 0xef
+.data1 	0xea, 0xff, 0xff, 0x50, 0xe8, 0x63, 0x20, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xba, 0xff, 0xff, 0x00
+.data1 	0x00, 0x23, 0x55, 0xfc, 0x8b, 0x0d, 0x40, 0x22
+.data1 	0x00, 0x00, 0x66, 0x89, 0x51, 0x04, 0x8b, 0x15
+.data1 	0x40, 0x22, 0x00, 0x00, 0x0f, 0xb7, 0x4a, 0x04
+.data1 	0x23, 0x4d, 0x08, 0x39, 0x4d, 0x0c, 0x75, 0x07
+.data1 	0xb8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x36, 0x8d
+.data1 	0x45, 0xf4, 0x50, 0xe8, 0x48, 0x19, 0x00, 0x00
+.data1 	0x59, 0x89, 0xc6, 0x85, 0xc0, 0x75, 0x0e, 0x8b
+.data1 	0x55, 0xf4, 0x2b, 0x55, 0xf8, 0x39, 0x15, 0xb0
+.data1 	0x12, 0x00, 0x00, 0x7f, 0x80, 0x85, 0xf6, 0x74
+.data1 	0x0d, 0x56, 0x68, 0x5c, 0x0a, 0x00, 0x00, 0xe8
+.data1 	0x5c, 0x19, 0x00, 0x00, 0x59, 0x59, 0xe8, 0x7e
+.data1 	0xfb, 0xff, 0xff, 0x31, 0xc0, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c, 0x56, 0x8d
+.data1 	0x45, 0xf8, 0x50, 0xe8, 0x08, 0x19, 0x00, 0x00
+.data1 	0x59, 0x8b, 0x15, 0x40, 0x22, 0x00, 0x00, 0xb9
+.data1 	0x02, 0x00, 0x00, 0x00, 0x03, 0x4a, 0x10, 0x6a
+.data1 	0x62, 0x8d, 0x45, 0xfc, 0x50, 0x51, 0xe8, 0xfd
+.data1 	0x22, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0xc6
+.data1 	0x85, 0xc0, 0x74, 0x14, 0x56, 0x68, 0xcc, 0x0a
+.data1 	0x00, 0x00, 0xe8, 0x43, 0xea, 0xff, 0xff, 0x50
+.data1 	0xe8, 0xb7, 0x1f, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x8b, 0x55, 0xfc, 0x23, 0x55, 0x08, 0x39, 0x55
+.data1 	0x0c, 0x75, 0x07, 0xb8, 0x01, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x31, 0x8d, 0x45, 0xf4, 0x50, 0xe8, 0xb5
+.data1 	0x18, 0x00, 0x00, 0x59, 0x89, 0xc6, 0x85, 0xc0
+.data1 	0x75, 0x0e, 0x8b, 0x55, 0xf4, 0x2b, 0x55, 0xf8
+.data1 	0x39, 0x15, 0xb0, 0x12, 0x00, 0x00, 0x7f, 0x99
+.data1 	0x85, 0xf6, 0x74, 0x0d, 0x56, 0x68, 0xa0, 0x0a
+.data1 	0x00, 0x00, 0xe8, 0xc9, 0x18, 0x00, 0x00, 0x59
+.data1 	0x59, 0x31, 0xc0, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x08, 0x8b, 0x35
+.data1 	0x40, 0x22, 0x00, 0x00, 0x8b, 0x16, 0xf6, 0xc2
+.data1 	0x08, 0x74, 0x2f, 0x68, 0x00, 0x02, 0x00, 0x00
+.data1 	0xff, 0x76, 0x60, 0xff, 0x76, 0x5c, 0xe8, 0xb5
+.data1 	0x28, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xb9, 0x00
+.data1 	0x08, 0x00, 0x00, 0x31, 0xd2, 0xf7, 0xf1, 0x89
+.data1 	0x47, 0x10, 0xc7, 0x47, 0x14, 0x40, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x47, 0x18, 0x20, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x12, 0x8b, 0x56, 0x2c, 0x89, 0x57, 0x10
+.data1 	0x8b, 0x56, 0x30, 0x89, 0x57, 0x14, 0x8b, 0x56
+.data1 	0x34, 0x89, 0x57, 0x18, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x68, 0x00
+.data1 	0x04, 0x00, 0x00, 0x68, 0x00, 0x80, 0x0c, 0x00
+.data1 	0x8d, 0x45, 0xf8, 0x50, 0xe8, 0x87, 0x28, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x15, 0x40, 0x22
+.data1 	0x00, 0x00, 0x50, 0x83, 0xc2, 0x5c, 0x52, 0xb9
+.data1 	0x02, 0x00, 0x00, 0x00, 0xe8, 0x67, 0x2c, 0x00
+.data1 	0x00, 0x31, 0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x04
+.data1 	0x56, 0xc6, 0x05, 0x24, 0xc4, 0x00, 0x00, 0x03
+.data1 	0xc6, 0x05, 0x25, 0xc4, 0x00, 0x00, 0x00, 0xc6
+.data1 	0x05, 0x26, 0xc4, 0x00, 0x00, 0x00, 0xc6, 0x05
+.data1 	0x27, 0xc4, 0x00, 0x00, 0x00, 0xc6, 0x05, 0x28
+.data1 	0xc4, 0x00, 0x00, 0x12, 0xc6, 0x05, 0x29, 0xc4
+.data1 	0x00, 0x00, 0x00, 0xc6, 0x05, 0x2b, 0xc4, 0x00
+.data1 	0x00, 0x00, 0xc6, 0x05, 0x2c, 0xc4, 0x00, 0x00
+.data1 	0x00, 0xc6, 0x05, 0x2d, 0xc4, 0x00, 0x00, 0x00
+.data1 	0xc6, 0x05, 0x2e, 0xc4, 0x00, 0x00, 0x00, 0xc6
+.data1 	0x05, 0x2f, 0xc4, 0x00, 0x00, 0x00, 0x31, 0xf6
+.data1 	0x83, 0xfe, 0x12, 0x7d, 0x0a, 0xc6, 0x86, 0x30
+.data1 	0xc4, 0x00, 0x00, 0xff, 0x46, 0xeb, 0xf1, 0x6a
+.data1 	0x12, 0x68, 0x24, 0xc4, 0x00, 0x00, 0xe8, 0x73
+.data1 	0x04, 0x00, 0x00, 0x59, 0x59, 0x89, 0x45, 0xfc
+.data1 	0x85, 0xc0, 0x74, 0x10, 0x68, 0x40, 0x0b, 0x00
+.data1 	0x00, 0xe8, 0xaa, 0x17, 0x00, 0x00, 0x59, 0xe9
+.data1 	0x78, 0x00, 0x00, 0x00, 0xe8, 0x40, 0x0b, 0x00
+.data1 	0x00, 0x85, 0xc0, 0x7f, 0x0b, 0x68, 0x1c, 0x0b
+.data1 	0x00, 0x00, 0xe8, 0x91, 0x17, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x15, 0x40, 0x22, 0x00, 0x00, 0x6a, 0x12
+.data1 	0x68, 0x30, 0xc4, 0x00, 0x00, 0x68, 0xce, 0x8a
+.data1 	0x00, 0x00, 0x6a, 0x77, 0xff, 0x72, 0x08, 0x6a
+.data1 	0x00, 0xe8, 0x36, 0x22, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x18, 0x85, 0xc0, 0x74, 0x0b, 0x68, 0xfc, 0x0a
+.data1 	0x00, 0x00, 0xe8, 0x61, 0x17, 0x00, 0x00, 0x59
+.data1 	0x68, 0xf0, 0x0a, 0x00, 0x00, 0xe8, 0x56, 0x17
+.data1 	0x00, 0x00, 0x59, 0x31, 0xf6, 0x83, 0xfe, 0x12
+.data1 	0x7d, 0x17, 0x0f, 0xb6, 0x86, 0x30, 0xc4, 0x00
+.data1 	0x00, 0x50, 0x68, 0xe8, 0x0a, 0x00, 0x00, 0xe8
+.data1 	0x3c, 0x17, 0x00, 0x00, 0x59, 0x59, 0x46, 0xeb
+.data1 	0xe4, 0x68, 0xe4, 0x0a, 0x00, 0x00, 0xe8, 0x2d
+.data1 	0x17, 0x00, 0x00, 0x59, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x48, 0x56, 0x57, 0x8b
+.data1 	0x15, 0x40, 0x22, 0x00, 0x00, 0x89, 0x55, 0xfc
+.data1 	0x8b, 0x55, 0x18, 0xc1, 0xe2, 0x03, 0x03, 0x55
+.data1 	0x14, 0x89, 0x55, 0xf4, 0x8b, 0x15, 0x7c, 0x22
+.data1 	0x00, 0x00, 0xff, 0x72, 0x0c, 0xff, 0x72, 0x08
+.data1 	0xe8, 0xff, 0x26, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0x45, 0xd4, 0x31, 0xd2, 0x89, 0x55, 0xe4, 0x89
+.data1 	0x55, 0xe8, 0x83, 0x7d, 0x18, 0x00, 0x0f, 0x84
+.data1 	0x8a, 0x03, 0x00, 0x00, 0x83, 0x7d, 0xe4, 0x00
+.data1 	0x0f, 0x85, 0x80, 0x03, 0x00, 0x00, 0x8b, 0x15
+.data1 	0x7c, 0x22, 0x00, 0x00, 0xff, 0x75, 0x10, 0xff
+.data1 	0x72, 0x04, 0xff, 0x32, 0x8d, 0x45, 0xb8, 0x50
+.data1 	0xe8, 0x6f, 0x26, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x8b, 0x10, 0x8b, 0x48, 0x04, 0x89, 0x55, 0xdc
+.data1 	0x89, 0x4d, 0xe0, 0x68, 0x00, 0x08, 0x00, 0x00
+.data1 	0xff, 0x75, 0xe0, 0xff, 0x75, 0xdc, 0xe8, 0xbd
+.data1 	0x26, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45
+.data1 	0xd8, 0x68, 0x00, 0x08, 0x00, 0x00, 0xff, 0x75
+.data1 	0xe0, 0xff, 0x75, 0xdc, 0xe8, 0xba, 0x26, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45, 0xc4, 0x31
+.data1 	0xd2, 0x89, 0xd7, 0x89, 0x55, 0xd0, 0x8b, 0x55
+.data1 	0x14, 0x89, 0x55, 0xf8, 0x8b, 0x55, 0xf4, 0x39
+.data1 	0x55, 0xf8, 0x73, 0x27, 0x8b, 0x55, 0xf8, 0x8b
+.data1 	0x52, 0x04, 0x01, 0x55, 0xd0, 0x8b, 0x55, 0xd0
+.data1 	0x03, 0x55, 0xc4, 0xb9, 0x00, 0x08, 0x00, 0x00
+.data1 	0x89, 0xd0, 0x31, 0xd2, 0xf7, 0xf1, 0x85, 0xd2
+.data1 	0x75, 0x03, 0x8b, 0x7d, 0xd0, 0x83, 0x45, 0xf8
+.data1 	0x08, 0xeb, 0xd1, 0x85, 0xff, 0x74, 0x03, 0x89
+.data1 	0x7d, 0xd0, 0x8b, 0x55, 0xd0, 0x0b, 0x55, 0xc4
+.data1 	0xf6, 0xc2, 0x01, 0x74, 0x0a, 0xb8, 0xea, 0xff
+.data1 	0xff, 0xff, 0xe9, 0xe3, 0x02, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xd4, 0x39, 0x55, 0x10, 0x72, 0x07, 0x31
+.data1 	0xc0, 0xe9, 0xd4, 0x02, 0x00, 0x00, 0x8b, 0x55
+.data1 	0x10, 0x03, 0x55, 0xd0, 0x39, 0x55, 0xd4, 0x73
+.data1 	0x09, 0x8b, 0x55, 0xd4, 0x2b, 0x55, 0x10, 0x89
+.data1 	0x55, 0xd0, 0x8b, 0x55, 0xd0, 0x03, 0x55, 0xc4
+.data1 	0x81, 0xc2, 0xff, 0x07, 0x00, 0x00, 0xb9, 0x00
+.data1 	0x08, 0x00, 0x00, 0x89, 0xd0, 0x31, 0xd2, 0xf7
+.data1 	0xf1, 0x89, 0x45, 0xcc, 0x8b, 0x5d, 0xfc, 0x8b
+.data1 	0x13, 0xf6, 0xc2, 0x01, 0x75, 0x13, 0xe8, 0x43
+.data1 	0xe8, 0xff, 0xff, 0x85, 0xc0, 0x74, 0x0a, 0xb8
+.data1 	0xfb, 0xff, 0xff, 0xff, 0xe9, 0x89, 0x02, 0x00
+.data1 	0x00, 0xc6, 0x05, 0x18, 0xc4, 0x00, 0x00, 0x28
+.data1 	0xc6, 0x05, 0x19, 0xc4, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xd8, 0xc1, 0xea, 0x18, 0x88, 0x15, 0x1a
+.data1 	0xc4, 0x00, 0x00, 0x8b, 0x55, 0xd8, 0xc1, 0xea
+.data1 	0x10, 0x88, 0x15, 0x1b, 0xc4, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xd8, 0xc1, 0xea, 0x08, 0x88, 0x15, 0x1c
+.data1 	0xc4, 0x00, 0x00, 0x8b, 0x55, 0xd8, 0x88, 0x15
+.data1 	0x1d, 0xc4, 0x00, 0x00, 0x8b, 0x55, 0xcc, 0xc1
+.data1 	0xea, 0x08, 0x88, 0x15, 0x1f, 0xc4, 0x00, 0x00
+.data1 	0x8b, 0x55, 0xcc, 0x88, 0x15, 0x20, 0xc4, 0x00
+.data1 	0x00, 0xc6, 0x05, 0x21, 0xc4, 0x00, 0x00, 0x00
+.data1 	0xc6, 0x05, 0x22, 0xc4, 0x00, 0x00, 0x00, 0xc6
+.data1 	0x05, 0x23, 0xc4, 0x00, 0x00, 0x00, 0x69, 0x45
+.data1 	0xcc, 0x00, 0x08, 0x00, 0x00, 0x50, 0x68, 0x18
+.data1 	0xc4, 0x00, 0x00, 0xe8, 0x16, 0x02, 0x00, 0x00
+.data1 	0x59, 0x59, 0x89, 0x45, 0xf0, 0x85, 0xc0, 0x0f
+.data1 	0x85, 0x93, 0x01, 0x00, 0x00, 0xe8, 0xef, 0x08
+.data1 	0x00, 0x00, 0x89, 0x45, 0xf0, 0x85, 0xc0, 0x0f
+.data1 	0x8e, 0x79, 0x01, 0x00, 0x00, 0x8b, 0x7d, 0xf0
+.data1 	0x83, 0x7d, 0xc4, 0x00, 0x0f, 0x84, 0x69, 0x00
+.data1 	0x00, 0x00, 0x85, 0xff, 0x0f, 0x84, 0x61, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x75, 0xc4, 0x39, 0xfe, 0x76
+.data1 	0x02, 0x89, 0xfe, 0x81, 0xfe, 0x00, 0x02, 0x00
+.data1 	0x00, 0x76, 0x05, 0xbe, 0x00, 0x02, 0x00, 0x00
+.data1 	0x8b, 0x55, 0xfc, 0x56, 0xff, 0x35, 0x14, 0xdd
+.data1 	0x00, 0x00, 0x68, 0xce, 0x8a, 0x00, 0x00, 0x6a
+.data1 	0x77, 0xff, 0x72, 0x08, 0x6a, 0x00, 0xe8, 0xc1
+.data1 	0x1f, 0x00, 0x00, 0x83, 0xc4, 0x18, 0x89, 0x45
+.data1 	0xec, 0x85, 0xc0, 0x74, 0x16, 0xff, 0x75, 0xec
+.data1 	0x68, 0xb4, 0x0b, 0x00, 0x00, 0xe8, 0x18, 0xe6
+.data1 	0xff, 0xff, 0x50, 0xe8, 0x8c, 0x1b, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x8b, 0x55, 0xc4, 0x29, 0xf2
+.data1 	0x89, 0x55, 0xc4, 0x89, 0xfa, 0x29, 0xf2, 0x89
+.data1 	0xd7, 0xeb, 0x8d, 0x83, 0x7d, 0xd0, 0x00, 0x0f
+.data1 	0x84, 0x9f, 0x00, 0x00, 0x00, 0x85, 0xff, 0x0f
+.data1 	0x84, 0x97, 0x00, 0x00, 0x00, 0x8b, 0x75, 0xd0
+.data1 	0x39, 0xfe, 0x76, 0x02, 0x89, 0xfe, 0x8b, 0x55
+.data1 	0x14, 0x39, 0x72, 0x04, 0x73, 0x03, 0x8b, 0x72
+.data1 	0x04, 0x8b, 0x45, 0x14, 0x8b, 0x55, 0xfc, 0x56
+.data1 	0xff, 0x30, 0xff, 0x75, 0x08, 0x6a, 0x77, 0xff
+.data1 	0x72, 0x08, 0x6a, 0x00, 0xe8, 0x53, 0x1f, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x18, 0x89, 0x45, 0xec, 0x85
+.data1 	0xc0, 0x74, 0x16, 0xff, 0x75, 0xec, 0x68, 0x98
+.data1 	0x0b, 0x00, 0x00, 0xe8, 0xaa, 0xe5, 0xff, 0xff
+.data1 	0x50, 0xe8, 0x1e, 0x1b, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x01, 0x75, 0x10, 0x8b, 0x55, 0xd0, 0x29
+.data1 	0xf2, 0x89, 0x55, 0xd0, 0x89, 0xfa, 0x29, 0xf2
+.data1 	0x89, 0xd7, 0x8b, 0x45, 0x14, 0x01, 0x30, 0xc7
+.data1 	0x45, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x55
+.data1 	0x14, 0x8b, 0x52, 0x04, 0x29, 0xf2, 0x8b, 0x4d
+.data1 	0x14, 0x89, 0x51, 0x04, 0x8b, 0x55, 0x14, 0x83
+.data1 	0x7a, 0x04, 0x00, 0x0f, 0x85, 0x6a, 0xff, 0xff
+.data1 	0xff, 0x83, 0x45, 0x14, 0x08, 0xff, 0x4d, 0x18
+.data1 	0xc7, 0x45, 0xe4, 0x01, 0x00, 0x00, 0x00, 0xe9
+.data1 	0x57, 0xff, 0xff, 0xff, 0x85, 0xff, 0x0f, 0x84
+.data1 	0xc9, 0xfe, 0xff, 0xff, 0x89, 0xfe, 0x81, 0xfe
+.data1 	0x00, 0x02, 0x00, 0x00, 0x76, 0x05, 0xbe, 0x00
+.data1 	0x02, 0x00, 0x00, 0x8b, 0x55, 0xfc, 0x56, 0xff
+.data1 	0x35, 0x14, 0xdd, 0x00, 0x00, 0x68, 0xce, 0x8a
+.data1 	0x00, 0x00, 0x6a, 0x77, 0xff, 0x72, 0x08, 0x6a
+.data1 	0x00, 0xe8, 0xb6, 0x1e, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x18, 0x89, 0x45, 0xec, 0x85, 0xc0, 0x74, 0x16
+.data1 	0xff, 0x75, 0xec, 0x68, 0x7c, 0x0b, 0x00, 0x00
+.data1 	0xe8, 0x0d, 0xe5, 0xff, 0xff, 0x50, 0xe8, 0x81
+.data1 	0x1a, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0xfa
+.data1 	0x29, 0xf2, 0x89, 0xd7, 0xeb, 0xa6, 0x83, 0x7d
+.data1 	0xf0, 0x00, 0x0f, 0x89, 0xd2, 0xfc, 0xff, 0xff
+.data1 	0x83, 0x3d, 0xcc, 0x12, 0x00, 0x00, 0x00, 0x74
+.data1 	0x05, 0xe8, 0x84, 0xfb, 0xff, 0xff, 0xff, 0x45
+.data1 	0xe8, 0x8b, 0x15, 0xb4, 0x12, 0x00, 0x00, 0x39
+.data1 	0x55, 0xe8, 0x75, 0x29, 0xc7, 0x05, 0x70, 0x22
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x3d
+.data1 	0xcc, 0x12, 0x00, 0x00, 0x00, 0x74, 0x0f, 0xff
+.data1 	0x75, 0xe8, 0x68, 0x6c, 0x0b, 0x00, 0x00, 0xe8
+.data1 	0x84, 0x13, 0x00, 0x00, 0x59, 0x59, 0xb8, 0xfb
+.data1 	0xff, 0xff, 0xff, 0xeb, 0x2d, 0x83, 0x3d, 0xcc
+.data1 	0x12, 0x00, 0x00, 0x00, 0x0f, 0x84, 0x80, 0xfc
+.data1 	0xff, 0xff, 0xff, 0x75, 0xe8, 0x68, 0x60, 0x0b
+.data1 	0x00, 0x00, 0xe8, 0x61, 0x13, 0x00, 0x00, 0x59
+.data1 	0x59, 0xe9, 0x6c, 0xfc, 0xff, 0xff, 0xc7, 0x05
+.data1 	0x70, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x24, 0x56, 0x57, 0x8b, 0x35
+.data1 	0x40, 0x22, 0x00, 0x00, 0x8b, 0x16, 0xf6, 0xc2
+.data1 	0x20, 0x74, 0x0a, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x17, 0x02, 0x00, 0x00, 0xba, 0x06, 0x00
+.data1 	0x00, 0x00, 0x03, 0x56, 0x08, 0x6a, 0x62, 0xff
+.data1 	0x76, 0x44, 0x52, 0xe8, 0xa8, 0x1d, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0xc7, 0x85, 0xc0, 0x74
+.data1 	0x14, 0x57, 0x68, 0xd0, 0x0c, 0x00, 0x00, 0xe8
+.data1 	0x36, 0xe4, 0xff, 0xff, 0x50, 0xe8, 0xaa, 0x19
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x6a, 0x00, 0x68
+.data1 	0x88, 0x00, 0x00, 0x00, 0xe8, 0xf3, 0xf8, 0xff
+.data1 	0xff, 0x59, 0x59, 0x85, 0xc0, 0x75, 0x1c, 0xe8
+.data1 	0x16, 0xe4, 0xff, 0xff, 0x50, 0x68, 0xa8, 0x0c
+.data1 	0x00, 0x00, 0xe8, 0xd9, 0x12, 0x00, 0x00, 0x59
+.data1 	0x59, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0xb9
+.data1 	0x01, 0x00, 0x00, 0x6a, 0x00, 0xff, 0x35, 0xb8
+.data1 	0x12, 0x00, 0x00, 0xe8, 0xc4, 0x1d, 0x00, 0x00
+.data1 	0x59, 0x59, 0x81, 0x7d, 0x0c, 0xfe, 0xff, 0x00
+.data1 	0x00, 0x76, 0x07, 0xc7, 0x45, 0x0c, 0xfe, 0xff
+.data1 	0x00, 0x00, 0xc7, 0x05, 0x70, 0x22, 0x00, 0x00
+.data1 	0xa0, 0x00, 0x00, 0x00, 0xba, 0x01, 0x00, 0x00
+.data1 	0x00, 0x03, 0x56, 0x08, 0x81, 0xe2, 0xff, 0xff
+.data1 	0x00, 0x00, 0x66, 0x89, 0x55, 0xe4, 0xc6, 0x45
+.data1 	0xe6, 0x00, 0xba, 0x02, 0x00, 0x00, 0x00, 0x03
+.data1 	0x56, 0x08, 0x81, 0xe2, 0xff, 0xff, 0x00, 0x00
+.data1 	0x66, 0x89, 0x55, 0xe8, 0xc6, 0x45, 0xea, 0x00
+.data1 	0xba, 0x03, 0x00, 0x00, 0x00, 0x03, 0x56, 0x08
+.data1 	0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x66, 0x89
+.data1 	0x55, 0xec, 0xc6, 0x45, 0xee, 0x00, 0xba, 0x04
+.data1 	0x00, 0x00, 0x00, 0x03, 0x56, 0x08, 0x81, 0xe2
+.data1 	0xff, 0xff, 0x00, 0x00, 0x66, 0x89, 0x55, 0xf0
+.data1 	0x8b, 0x55, 0x0c, 0x88, 0x55, 0xf2, 0xba, 0x05
+.data1 	0x00, 0x00, 0x00, 0x03, 0x56, 0x08, 0x81, 0xe2
+.data1 	0xff, 0xff, 0x00, 0x00, 0x66, 0x89, 0x55, 0xf4
+.data1 	0x8b, 0x55, 0x0c, 0xc1, 0xea, 0x08, 0x88, 0x55
+.data1 	0xf6, 0xba, 0x07, 0x00, 0x00, 0x00, 0x03, 0x56
+.data1 	0x08, 0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x66
+.data1 	0x89, 0x55, 0xf8, 0x8b, 0x15, 0x70, 0x22, 0x00
+.data1 	0x00, 0x88, 0x55, 0xfa, 0x83, 0x3d, 0xcc, 0x12
+.data1 	0x00, 0x00, 0x00, 0x74, 0x12, 0xff, 0x35, 0x70
+.data1 	0x22, 0x00, 0x00, 0x68, 0x9c, 0x0c, 0x00, 0x00
+.data1 	0xe8, 0xfb, 0x11, 0x00, 0x00, 0x59, 0x59, 0x6a
+.data1 	0x06, 0x8d, 0x45, 0xe4, 0x50, 0xe8, 0xea, 0x1d
+.data1 	0x00, 0x00, 0x59, 0x59, 0x89, 0xc7, 0x85, 0xc0
+.data1 	0x74, 0x14, 0x57, 0x68, 0x70, 0x0c, 0x00, 0x00
+.data1 	0xe8, 0x0d, 0xe3, 0xff, 0xff, 0x50, 0xe8, 0x81
+.data1 	0x18, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x6a, 0x08
+.data1 	0x68, 0x88, 0x00, 0x00, 0x00, 0xe8, 0xca, 0xf7
+.data1 	0xff, 0xff, 0x59, 0x59, 0x85, 0xc0, 0x75, 0x1c
+.data1 	0xe8, 0xed, 0xe2, 0xff, 0xff, 0x50, 0x68, 0x50
+.data1 	0x0c, 0x00, 0x00, 0xe8, 0xb0, 0x11, 0x00, 0x00
+.data1 	0x59, 0x59, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9
+.data1 	0x90, 0x00, 0x00, 0x00, 0x0f, 0xb7, 0x56, 0x04
+.data1 	0x81, 0xca, 0x00, 0x01, 0x00, 0x00, 0x81, 0xe2
+.data1 	0xff, 0xff, 0x00, 0x00, 0x66, 0x89, 0x56, 0x04
+.data1 	0x6a, 0x0c, 0xff, 0x75, 0x08, 0x68, 0xce, 0x8a
+.data1 	0x00, 0x00, 0x6a, 0x77, 0xff, 0x76, 0x08, 0x6a
+.data1 	0x01, 0xe8, 0x3e, 0x1c, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x18, 0x89, 0xc7, 0x85, 0xc0, 0x74, 0x14, 0x57
+.data1 	0x68, 0x3c, 0x0c, 0x00, 0x00, 0xe8, 0x98, 0xe2
+.data1 	0xff, 0xff, 0x50, 0xe8, 0x0c, 0x18, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x83, 0x3d, 0xcc, 0x12, 0x00
+.data1 	0x00, 0x00, 0x74, 0x3e, 0x68, 0x2c, 0x0c, 0x00
+.data1 	0x00, 0xe8, 0x4a, 0x11, 0x00, 0x00, 0x59, 0xc7
+.data1 	0x45, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x83, 0x7d
+.data1 	0xdc, 0x0c, 0x7d, 0x1b, 0x8b, 0x55, 0x08, 0x03
+.data1 	0x55, 0xdc, 0x0f, 0xb6, 0x02, 0x50, 0x68, 0x24
+.data1 	0x0c, 0x00, 0x00, 0xe8, 0x28, 0x11, 0x00, 0x00
+.data1 	0x59, 0x59, 0xff, 0x45, 0xdc, 0xeb, 0xdf, 0x68
+.data1 	0x20, 0x0c, 0x00, 0x00, 0xe8, 0x17, 0x11, 0x00
+.data1 	0x00, 0x59, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x10, 0x56, 0x57
+.data1 	0x8b, 0x75, 0x0c, 0x81, 0x7e, 0x04, 0x05, 0x04
+.data1 	0x00, 0x00, 0x74, 0x0a, 0xb8, 0xea, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x44, 0x01, 0x00, 0x00, 0x81, 0x7e
+.data1 	0x10, 0x06, 0x64, 0x04, 0x40, 0x0f, 0x85, 0xde
+.data1 	0x00, 0x00, 0x00, 0x6a, 0x04, 0x8d, 0x45, 0xf8
+.data1 	0x50, 0x6a, 0x01, 0x68, 0xce, 0x8a, 0x00, 0x00
+.data1 	0xff, 0x76, 0x1c, 0x6a, 0x01, 0xff, 0x76, 0x0c
+.data1 	0xe8, 0x73, 0x1c, 0x00, 0x00, 0x83, 0xc4, 0x1c
+.data1 	0x89, 0xc7, 0x85, 0xc0, 0x74, 0x07, 0x89, 0xf8
+.data1 	0xe9, 0x0d, 0x01, 0x00, 0x00, 0x83, 0x7d, 0xf8
+.data1 	0x00, 0x75, 0x2d, 0xc7, 0x05, 0xb0, 0x12, 0x00
+.data1 	0x00, 0x2c, 0x01, 0x00, 0x00, 0xc7, 0x05, 0xb4
+.data1 	0x12, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x05, 0xb8, 0x12, 0x00, 0x00, 0x80, 0x07, 0x00
+.data1 	0x00, 0xc7, 0x05, 0xd4, 0x12, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0xe9, 0x7a, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0xf8, 0x00, 0x79, 0x0a, 0xb8, 0xea
+.data1 	0xff, 0xff, 0xff, 0xe9, 0xca, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x15, 0xb8, 0x12, 0x00, 0x00, 0x89, 0x55
+.data1 	0xf4, 0x83, 0x3d, 0xbc, 0x12, 0x00, 0x00, 0x00
+.data1 	0x75, 0x2e, 0x8b, 0x55, 0xf8, 0x89, 0x15, 0xb8
+.data1 	0x12, 0x00, 0x00, 0xc7, 0x05, 0xb4, 0x12, 0x00
+.data1 	0x00, 0x03, 0x00, 0x00, 0x00, 0xc7, 0x05, 0xd4
+.data1 	0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xf8, 0x39, 0x15, 0xb0, 0x12, 0x00, 0x00
+.data1 	0x7e, 0x06, 0x89, 0x15, 0xb0, 0x12, 0x00, 0x00
+.data1 	0x6a, 0x04, 0xff, 0x76, 0x1c, 0x6a, 0x01, 0xff
+.data1 	0x76, 0x0c, 0x8d, 0x45, 0xf4, 0x50, 0x6a, 0x01
+.data1 	0x68, 0xce, 0x8a, 0x00, 0x00, 0xe8, 0xc6, 0x1b
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x1c, 0x89, 0xc7, 0x85
+.data1 	0xc0, 0x74, 0x07, 0x89, 0xf8, 0xe9, 0x60, 0x00
+.data1 	0x00, 0x00, 0x31, 0xc0, 0xe9, 0x59, 0x00, 0x00
+.data1 	0x00, 0x81, 0x7e, 0x10, 0x07, 0x64, 0x04, 0x80
+.data1 	0x75, 0x4b, 0xff, 0x76, 0x08, 0xe8, 0x93, 0xd8
+.data1 	0xff, 0xff, 0x59, 0x85, 0xc0, 0x75, 0x07, 0xb8
+.data1 	0xfa, 0xff, 0xff, 0xff, 0xeb, 0x3c, 0x8b, 0x15
+.data1 	0x40, 0x22, 0x00, 0x00, 0x8b, 0x52, 0x50, 0x89
+.data1 	0x55, 0xf0, 0x6a, 0x04, 0xff, 0x76, 0x1c, 0x6a
+.data1 	0x01, 0xff, 0x76, 0x0c, 0x8d, 0x45, 0xf0, 0x50
+.data1 	0x6a, 0x01, 0x68, 0xce, 0x8a, 0x00, 0x00, 0xe8
+.data1 	0x6c, 0x1b, 0x00, 0x00, 0x83, 0xc4, 0x1c, 0x89
+.data1 	0xc7, 0x85, 0xc0, 0x74, 0x04, 0x89, 0xf8, 0xeb
+.data1 	0x09, 0x31, 0xc0, 0xeb, 0x05, 0xb8, 0xea, 0xff
+.data1 	0xff, 0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x8b, 0x55, 0x0c, 0xff, 0x72, 0x14, 0xe8
+.data1 	0x05, 0x00, 0x00, 0x00, 0x59, 0x31, 0xc0, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x56
+.data1 	0x57, 0x8b, 0x7d, 0x08, 0x31, 0xf6, 0x83, 0xfe
+.data1 	0x08, 0x0f, 0x83, 0xd0, 0x00, 0x00, 0x00, 0x85
+.data1 	0xff, 0x0f, 0x84, 0xc8, 0x00, 0x00, 0x00, 0x69
+.data1 	0xc6, 0xa4, 0x01, 0x00, 0x00, 0x8b, 0x90, 0x20
+.data1 	0x15, 0x00, 0x00, 0xf6, 0xc2, 0x20, 0x0f, 0x85
+.data1 	0xad, 0x00, 0x00, 0x00, 0x69, 0xc6, 0xa4, 0x01
+.data1 	0x00, 0x00, 0x83, 0xb8, 0x3c, 0x15, 0x00, 0x00
+.data1 	0x00, 0x0f, 0x84, 0x9a, 0x00, 0x00, 0x00, 0x69
+.data1 	0xc6, 0xa4, 0x01, 0x00, 0x00, 0x85, 0xb8, 0x38
+.data1 	0x15, 0x00, 0x00, 0x0f, 0x84, 0x88, 0x00, 0x00
+.data1 	0x00, 0x69, 0xc6, 0xa4, 0x01, 0x00, 0x00, 0xba
+.data1 	0x07, 0x00, 0x00, 0x00, 0x03, 0x90, 0x28, 0x15
+.data1 	0x00, 0x00, 0x6a, 0x62, 0x8d, 0x45, 0xf8, 0x50
+.data1 	0x52, 0xe8, 0xfa, 0x18, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x85, 0xc0, 0x74, 0x14, 0x56, 0x68, 0x14
+.data1 	0x0d, 0x00, 0x00, 0xe8, 0x42, 0xe0, 0xff, 0xff
+.data1 	0x50, 0xe8, 0xb6, 0x15, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0xba, 0xff, 0xff, 0x00, 0x00, 0x23, 0x55
+.data1 	0xf8, 0x69, 0xc6, 0xa4, 0x01, 0x00, 0x00, 0x66
+.data1 	0x89, 0x90, 0x24, 0x15, 0x00, 0x00, 0x69, 0xc6
+.data1 	0xa4, 0x01, 0x00, 0x00, 0x05, 0x40, 0x15, 0x00
+.data1 	0x00, 0x50, 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x03
+.data1 	0xe8, 0xef, 0x18, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x85, 0xc0, 0x74, 0x0d, 0x56, 0x68, 0xf4, 0x0c
+.data1 	0x00, 0x00, 0xe8, 0xc9, 0x0e, 0x00, 0x00, 0x59
+.data1 	0x59, 0x69, 0xc6, 0xa4, 0x01, 0x00, 0x00, 0x8b
+.data1 	0x90, 0x38, 0x15, 0x00, 0x00, 0xf7, 0xd2, 0x21
+.data1 	0xd7, 0x46, 0xe9, 0x27, 0xff, 0xff, 0xff, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b
+.data1 	0x75, 0x08, 0xc6, 0x05, 0x50, 0xc3, 0x00, 0x00
+.data1 	0x00, 0xf7, 0xc6, 0x80, 0x00, 0x00, 0x00, 0x74
+.data1 	0x22, 0x68, 0x7c, 0x0d, 0x00, 0x00, 0x68, 0x50
+.data1 	0xc3, 0x00, 0x00, 0xe8, 0x5c, 0x1f, 0x00, 0x00
+.data1 	0x59, 0x59, 0x68, 0x78, 0x0d, 0x00, 0x00, 0x68
+.data1 	0x50, 0xc3, 0x00, 0x00, 0xe8, 0x4b, 0x1f, 0x00
+.data1 	0x00, 0x59, 0x59, 0xf7, 0xc6, 0x40, 0x00, 0x00
+.data1 	0x00, 0x74, 0x22, 0x68, 0x70, 0x0d, 0x00, 0x00
+.data1 	0x68, 0x50, 0xc3, 0x00, 0x00, 0xe8, 0x32, 0x1f
+.data1 	0x00, 0x00, 0x59, 0x59, 0x68, 0x6c, 0x0d, 0x00
+.data1 	0x00, 0x68, 0x50, 0xc3, 0x00, 0x00, 0xe8, 0x21
+.data1 	0x1f, 0x00, 0x00, 0x59, 0x59, 0xf7, 0xc6, 0x20
+.data1 	0x00, 0x00, 0x00, 0x74, 0x22, 0x68, 0x64, 0x0d
+.data1 	0x00, 0x00, 0x68, 0x50, 0xc3, 0x00, 0x00, 0xe8
+.data1 	0x08, 0x1f, 0x00, 0x00, 0x59, 0x59, 0x68, 0x60
+.data1 	0x0d, 0x00, 0x00, 0x68, 0x50, 0xc3, 0x00, 0x00
+.data1 	0xe8, 0xf7, 0x1e, 0x00, 0x00, 0x59, 0x59, 0xf7
+.data1 	0xc6, 0x10, 0x00, 0x00, 0x00, 0x74, 0x22, 0x68
+.data1 	0x58, 0x0d, 0x00, 0x00, 0x68, 0x50, 0xc3, 0x00
+.data1 	0x00, 0xe8, 0xde, 0x1e, 0x00, 0x00, 0x59, 0x59
+.data1 	0x68, 0x54, 0x0d, 0x00, 0x00, 0x68, 0x50, 0xc3
+.data1 	0x00, 0x00, 0xe8, 0xcd, 0x1e, 0x00, 0x00, 0x59
+.data1 	0x59, 0xf7, 0xc6, 0x08, 0x00, 0x00, 0x00, 0x74
+.data1 	0x22, 0x68, 0x50, 0x0d, 0x00, 0x00, 0x68, 0x50
+.data1 	0xc3, 0x00, 0x00, 0xe8, 0xb4, 0x1e, 0x00, 0x00
+.data1 	0x59, 0x59, 0x68, 0x4c, 0x0d, 0x00, 0x00, 0x68
+.data1 	0x50, 0xc3, 0x00, 0x00, 0xe8, 0xa3, 0x1e, 0x00
+.data1 	0x00, 0x59, 0x59, 0xf7, 0xc6, 0x04, 0x00, 0x00
+.data1 	0x00, 0x74, 0x22, 0x68, 0x44, 0x0d, 0x00, 0x00
+.data1 	0x68, 0x50, 0xc3, 0x00, 0x00, 0xe8, 0x8a, 0x1e
+.data1 	0x00, 0x00, 0x59, 0x59, 0x68, 0x40, 0x0d, 0x00
+.data1 	0x00, 0x68, 0x50, 0xc3, 0x00, 0x00, 0xe8, 0x79
+.data1 	0x1e, 0x00, 0x00, 0x59, 0x59, 0xf7, 0xc6, 0x01
+.data1 	0x00, 0x00, 0x00, 0x74, 0x22, 0x68, 0x38, 0x0d
+.data1 	0x00, 0x00, 0x68, 0x50, 0xc3, 0x00, 0x00, 0xe8
+.data1 	0x60, 0x1e, 0x00, 0x00, 0x59, 0x59, 0x68, 0x34
+.data1 	0x0d, 0x00, 0x00, 0x68, 0x50, 0xc3, 0x00, 0x00
+.data1 	0xe8, 0x4f, 0x1e, 0x00, 0x00, 0x59, 0x59, 0xb8
+.data1 	0x50, 0xc3, 0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0x8b, 0x75, 0x08, 0xc6, 0x05
+.data1 	0x88, 0xc2, 0x00, 0x00, 0x00, 0xf7, 0xc6, 0x80
+.data1 	0x00, 0x00, 0x00, 0x74, 0x22, 0x68, 0xac, 0x0d
+.data1 	0x00, 0x00, 0x68, 0x88, 0xc2, 0x00, 0x00, 0xe8
+.data1 	0x20, 0x1e, 0x00, 0x00, 0x59, 0x59, 0x68, 0xa8
+.data1 	0x0d, 0x00, 0x00, 0x68, 0x88, 0xc2, 0x00, 0x00
+.data1 	0xe8, 0x0f, 0x1e, 0x00, 0x00, 0x59, 0x59, 0xf7
+.data1 	0xc6, 0x40, 0x00, 0x00, 0x00, 0x74, 0x22, 0x68
+.data1 	0xa4, 0x0d, 0x00, 0x00, 0x68, 0x88, 0xc2, 0x00
+.data1 	0x00, 0xe8, 0xf6, 0x1d, 0x00, 0x00, 0x59, 0x59
+.data1 	0x68, 0xa0, 0x0d, 0x00, 0x00, 0x68, 0x88, 0xc2
+.data1 	0x00, 0x00, 0xe8, 0xe5, 0x1d, 0x00, 0x00, 0x59
+.data1 	0x59, 0xf7, 0xc6, 0x10, 0x00, 0x00, 0x00, 0x74
+.data1 	0x22, 0x68, 0x9c, 0x0d, 0x00, 0x00, 0x68, 0x88
+.data1 	0xc2, 0x00, 0x00, 0xe8, 0xcc, 0x1d, 0x00, 0x00
+.data1 	0x59, 0x59, 0x68, 0x98, 0x0d, 0x00, 0x00, 0x68
+.data1 	0x88, 0xc2, 0x00, 0x00, 0xe8, 0xbb, 0x1d, 0x00
+.data1 	0x00, 0x59, 0x59, 0xf7, 0xc6, 0x04, 0x00, 0x00
+.data1 	0x00, 0x74, 0x22, 0x68, 0x94, 0x0d, 0x00, 0x00
+.data1 	0x68, 0x88, 0xc2, 0x00, 0x00, 0xe8, 0xa2, 0x1d
+.data1 	0x00, 0x00, 0x59, 0x59, 0x68, 0x90, 0x0d, 0x00
+.data1 	0x00, 0x68, 0x88, 0xc2, 0x00, 0x00, 0xe8, 0x91
+.data1 	0x1d, 0x00, 0x00, 0x59, 0x59, 0xf7, 0xc6, 0x02
+.data1 	0x00, 0x00, 0x00, 0x74, 0x22, 0x68, 0x8c, 0x0d
+.data1 	0x00, 0x00, 0x68, 0x88, 0xc2, 0x00, 0x00, 0xe8
+.data1 	0x78, 0x1d, 0x00, 0x00, 0x59, 0x59, 0x68, 0x88
+.data1 	0x0d, 0x00, 0x00, 0x68, 0x88, 0xc2, 0x00, 0x00
+.data1 	0xe8, 0x67, 0x1d, 0x00, 0x00, 0x59, 0x59, 0xf7
+.data1 	0xc6, 0x01, 0x00, 0x00, 0x00, 0x74, 0x22, 0x68
+.data1 	0x84, 0x0d, 0x00, 0x00, 0x68, 0x88, 0xc2, 0x00
+.data1 	0x00, 0xe8, 0x4e, 0x1d, 0x00, 0x00, 0x59, 0x59
+.data1 	0x68, 0x80, 0x0d, 0x00, 0x00, 0x68, 0x88, 0xc2
+.data1 	0x00, 0x00, 0xe8, 0x3d, 0x1d, 0x00, 0x00, 0x59
+.data1 	0x59, 0xb8, 0x88, 0xc2, 0x00, 0x00, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x2c, 0x56
+.data1 	0x57, 0x8b, 0x35, 0x40, 0x22, 0x00, 0x00, 0xe8
+.data1 	0xaa, 0xf0, 0xff, 0xff, 0xba, 0x01, 0x00, 0x00
+.data1 	0x00, 0x03, 0x56, 0x08, 0x81, 0xe2, 0xff, 0xff
+.data1 	0x00, 0x00, 0x66, 0x89, 0x55, 0xec, 0xba, 0x04
+.data1 	0x00, 0x00, 0x00, 0x03, 0x56, 0x08, 0x81, 0xe2
+.data1 	0xff, 0xff, 0x00, 0x00, 0x66, 0x89, 0x55, 0xf0
+.data1 	0xba, 0x05, 0x00, 0x00, 0x00, 0x03, 0x56, 0x08
+.data1 	0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x66, 0x89
+.data1 	0x55, 0xf4, 0xba, 0x02, 0x00, 0x00, 0x00, 0x03
+.data1 	0x56, 0x08, 0x81, 0xe2, 0xff, 0xff, 0x00, 0x00
+.data1 	0x66, 0x89, 0x55, 0xf8, 0x6a, 0x04, 0x8d, 0x45
+.data1 	0xec, 0x50, 0xe8, 0x69, 0x17, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0x45, 0xe8, 0x85, 0xc0, 0x74, 0x16
+.data1 	0xff, 0x75, 0xe8, 0x68, 0xb0, 0x0e, 0x00, 0x00
+.data1 	0xe8, 0x15, 0xdd, 0xff, 0xff, 0x50, 0xe8, 0x89
+.data1 	0x12, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x0f, 0xb6
+.data1 	0x55, 0xee, 0x89, 0x55, 0xe4, 0x0f, 0xb6, 0x55
+.data1 	0xf2, 0x89, 0xd7, 0x0f, 0xb6, 0x55, 0xf6, 0xc1
+.data1 	0xe2, 0x08, 0x09, 0xd7, 0x0f, 0xb6, 0x55, 0xfa
+.data1 	0x89, 0x55, 0xdc, 0x0f, 0xb7, 0x56, 0x04, 0xf6
+.data1 	0xc2, 0x81, 0x74, 0x42, 0x83, 0x3d, 0xcc, 0x12
+.data1 	0x00, 0x00, 0x00, 0x74, 0x2f, 0xff, 0x75, 0xdc
+.data1 	0x57, 0xff, 0x75, 0xe4, 0xe8, 0x2e, 0xfe, 0xff
+.data1 	0xff, 0x59, 0x50, 0xff, 0x75, 0xe4, 0x0f, 0xb7
+.data1 	0x46, 0x04, 0x50, 0xe8, 0xe3, 0xfc, 0xff, 0xff
+.data1 	0x59, 0x50, 0x0f, 0xb7, 0x46, 0x04, 0x50, 0x68
+.data1 	0x80, 0x0e, 0x00, 0x00, 0xe8, 0x7f, 0x0b, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x1c, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x68, 0x00, 0x00, 0x00, 0x0f, 0xb7
+.data1 	0x56, 0x04, 0x83, 0xe2, 0x08, 0xb9, 0x03, 0x00
+.data1 	0x00, 0x00, 0x23, 0x4d, 0xdc, 0x09, 0xd1, 0x89
+.data1 	0x4d, 0xd4, 0xeb, 0x2e, 0xc7, 0x45, 0xd8, 0x00
+.data1 	0x00, 0x00, 0x00, 0xeb, 0x32, 0xc7, 0x45, 0xd8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x29, 0xc7, 0x45
+.data1 	0xd8, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x20, 0x89
+.data1 	0x7d, 0xd8, 0xeb, 0x1b, 0x89, 0x7d, 0xd8, 0xeb
+.data1 	0x16, 0xc7, 0x45, 0xd8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x0d, 0xbb, 0xb0, 0x0d, 0x00, 0x00, 0x8b
+.data1 	0x45, 0xd4, 0xe9, 0x69, 0x1f, 0x00, 0x00, 0x0f
+.data1 	0xb7, 0x56, 0x04, 0x81, 0xca, 0x00, 0x01, 0x00
+.data1 	0x00, 0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x66
+.data1 	0x89, 0x56, 0x04, 0x8b, 0x45, 0xd8, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x2c, 0x56, 0x57, 0x8b, 0x75, 0x08, 0xe8
+.data1 	0x45, 0x01, 0x00, 0x00, 0x8d, 0x45, 0xd4, 0x50
+.data1 	0x68, 0xce, 0x7a, 0x00, 0x00, 0xe8, 0x4e, 0x1b
+.data1 	0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x75, 0xec
+.data1 	0x8b, 0x55, 0xd4, 0x89, 0x15, 0x1c, 0xdd, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xe0, 0x89, 0x55, 0xf8, 0xe9
+.data1 	0xdb, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xd4, 0x50
+.data1 	0x56, 0xff, 0x56, 0x04, 0x59, 0x59, 0x89, 0xc7
+.data1 	0xe9, 0xd7, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xd4
+.data1 	0x50, 0x56, 0xff, 0x56, 0x08, 0x59, 0x59, 0x89
+.data1 	0xc7, 0xe9, 0xc6, 0x00, 0x00, 0x00, 0x8d, 0x45
+.data1 	0xd4, 0x50, 0x56, 0xff, 0x56, 0x0c, 0x59, 0x59
+.data1 	0x89, 0xc7, 0xe9, 0xb5, 0x00, 0x00, 0x00, 0x8d
+.data1 	0x45, 0xd4, 0x50, 0x56, 0xff, 0x56, 0x28, 0x59
+.data1 	0x59, 0x89, 0xc7, 0xe9, 0xa4, 0x00, 0x00, 0x00
+.data1 	0x8d, 0x45, 0xd4, 0x50, 0x56, 0xff, 0x56, 0x2c
+.data1 	0x59, 0x59, 0x89, 0xc7, 0xe9, 0x93, 0x00, 0x00
+.data1 	0x00, 0x8d, 0x45, 0xd4, 0x50, 0x56, 0xe8, 0x1e
+.data1 	0x01, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc7, 0xe9
+.data1 	0x80, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xd4, 0x50
+.data1 	0x56, 0xe8, 0xb7, 0x01, 0x00, 0x00, 0x59, 0x59
+.data1 	0x89, 0xc7, 0xe9, 0x6d, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7e, 0x34, 0x00, 0x0f, 0x84, 0x53, 0xff, 0xff
+.data1 	0xff, 0x8d, 0x45, 0xd4, 0x50, 0x56, 0xff, 0x56
+.data1 	0x34, 0x59, 0x59, 0xe9, 0x44, 0xff, 0xff, 0xff
+.data1 	0x8d, 0x45, 0xd4, 0x50, 0x56, 0xff, 0x56, 0x20
+.data1 	0x59, 0x59, 0xe9, 0x35, 0xff, 0xff, 0xff, 0x8d
+.data1 	0x45, 0xd4, 0x50, 0x56, 0xff, 0x56, 0x24, 0x59
+.data1 	0x59, 0xe9, 0x26, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0xd4, 0xe8, 0xa2, 0x1a, 0x00, 0x00, 0x59, 0xe9
+.data1 	0x18, 0xff, 0xff, 0xff, 0x83, 0x7e, 0x30, 0x00
+.data1 	0x74, 0x0e, 0x8d, 0x45, 0xd4, 0x50, 0x56, 0xff
+.data1 	0x56, 0x30, 0x59, 0x59, 0x89, 0xc7, 0xeb, 0x14
+.data1 	0xbf, 0xea, 0xff, 0xff, 0xff, 0xeb, 0x0d, 0xbb
+.data1 	0xc8, 0x0e, 0x00, 0x00, 0x8b, 0x45, 0xd8, 0xe9
+.data1 	0x58, 0x1e, 0x00, 0x00, 0xff, 0x56, 0x18, 0x81
+.data1 	0xff, 0x37, 0xff, 0xff, 0xff, 0x0f, 0x84, 0xe1
+.data1 	0xfe, 0xff, 0xff, 0xc7, 0x45, 0xd8, 0x44, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x55, 0xf8, 0x89, 0x55, 0xdc
+.data1 	0x89, 0x7d, 0xe0, 0x8d, 0x45, 0xd4, 0x50, 0xff
+.data1 	0x35, 0x1c, 0xdd, 0x00, 0x00, 0xe8, 0x0a, 0x1a
+.data1 	0x00, 0x00, 0x59, 0x59, 0xe9, 0xbb, 0xfe, 0xff
+.data1 	0xff, 0x55, 0x89, 0xe5, 0x56, 0xc7, 0x05, 0x14
+.data1 	0xdd, 0x00, 0x00, 0x94, 0xcc, 0x00, 0x00, 0x68
+.data1 	0x18, 0xdd, 0x00, 0x00, 0x68, 0x00, 0x04, 0x00
+.data1 	0x00, 0x68, 0x94, 0xcc, 0x00, 0x00, 0x6a, 0x01
+.data1 	0x68, 0xce, 0x8a, 0x00, 0x00, 0xe8, 0xb2, 0x14
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x14, 0xba, 0xff, 0xff
+.data1 	0x00, 0x00, 0x23, 0x15, 0x18, 0xdd, 0x00, 0x00
+.data1 	0x81, 0xea, 0x00, 0x00, 0x01, 0x00, 0xf7, 0xda
+.data1 	0x89, 0xd6, 0x81, 0xfa, 0x00, 0x02, 0x00, 0x00
+.data1 	0x73, 0x14, 0x89, 0xf2, 0x03, 0x15, 0x14, 0xdd
+.data1 	0x00, 0x00, 0x89, 0x15, 0x14, 0xdd, 0x00, 0x00
+.data1 	0x01, 0x35, 0x18, 0xdd, 0x00, 0x00, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x14, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x0c, 0x83, 0x7e, 0x10, 0x00
+.data1 	0x79, 0x0a, 0xb8, 0xea, 0xff, 0xff, 0xff, 0xe9
+.data1 	0x8d, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xec, 0x50
+.data1 	0xff, 0x76, 0x10, 0xff, 0x76, 0x1c, 0x6a, 0x01
+.data1 	0xff, 0x76, 0x0c, 0xe8, 0x4c, 0x14, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x14, 0x83, 0x7d, 0xec, 0x00, 0x75
+.data1 	0x0a, 0xb8, 0xf2, 0xff, 0xff, 0xff, 0xe9, 0x66
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x08, 0xff, 0x76
+.data1 	0x08, 0xff, 0x52, 0x10, 0x59, 0x85, 0xc0, 0x75
+.data1 	0x0a, 0xb8, 0xfa, 0xff, 0xff, 0xff, 0xe9, 0x4e
+.data1 	0x00, 0x00, 0x00, 0x81, 0x7e, 0x04, 0x03, 0x04
+.data1 	0x00, 0x00, 0x75, 0x07, 0xb8, 0x09, 0x04, 0x00
+.data1 	0x00, 0xeb, 0x05, 0xb8, 0x08, 0x04, 0x00, 0x00
+.data1 	0x89, 0x45, 0xf0, 0x8b, 0x56, 0x1c, 0x89, 0x55
+.data1 	0xf8, 0x8b, 0x56, 0x10, 0x89, 0x55, 0xfc, 0x8b
+.data1 	0x55, 0x08, 0x6a, 0x01, 0x8d, 0x45, 0xf8, 0x50
+.data1 	0xff, 0x76, 0x14, 0xff, 0x75, 0xf0, 0xff, 0x76
+.data1 	0x0c, 0xff, 0x52, 0x14, 0x83, 0xc4, 0x14, 0x89
+.data1 	0xc7, 0x85, 0xff, 0x75, 0x0a, 0x8b, 0x56, 0x10
+.data1 	0x2b, 0x55, 0xfc, 0x89, 0xd0, 0xeb, 0x02, 0x89
+.data1 	0xf8, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x10, 0x56, 0x57, 0x8b, 0x75, 0x0c
+.data1 	0x8b, 0x7e, 0x10, 0x83, 0xff, 0x40, 0x76, 0x05
+.data1 	0xbf, 0x40, 0x00, 0x00, 0x00, 0x89, 0xfa, 0xc1
+.data1 	0xe2, 0x03, 0x89, 0x55, 0xf8, 0x52, 0x68, 0x94
+.data1 	0xd0, 0x00, 0x00, 0x6a, 0x01, 0x68, 0xce, 0x8a
+.data1 	0x00, 0x00, 0xff, 0x76, 0x1c, 0x6a, 0x01, 0xff
+.data1 	0x36, 0xe8, 0x12, 0x14, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x1c, 0x85, 0xc0, 0x74, 0x15, 0x8b, 0x45, 0x08
+.data1 	0xff, 0x36, 0x68, 0x40, 0x0f, 0x00, 0x00, 0xff
+.data1 	0x10, 0x50, 0xe8, 0xfd, 0x0e, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xc7, 0x45, 0xfc, 0x94, 0xd0, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x08, 0xff, 0x76, 0x08, 0xff
+.data1 	0x52, 0x10, 0x59, 0x85, 0xc0, 0x75, 0x07, 0xb8
+.data1 	0xfa, 0xff, 0xff, 0xff, 0xeb, 0x3a, 0x8b, 0x55
+.data1 	0x08, 0x57, 0xff, 0x75, 0xfc, 0xff, 0x76, 0x14
+.data1 	0xff, 0x76, 0x04, 0xff, 0x76, 0x0c, 0xff, 0x52
+.data1 	0x14, 0x83, 0xc4, 0x14, 0x89, 0x45, 0xf0, 0xff
+.data1 	0x75, 0xf8, 0xff, 0x76, 0x1c, 0x6a, 0x01, 0xff
+.data1 	0x36, 0x68, 0x94, 0xd0, 0x00, 0x00, 0x6a, 0x01
+.data1 	0x68, 0xce, 0x8a, 0x00, 0x00, 0xe8, 0xa6, 0x13
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x1c, 0x8b, 0x45, 0xf0
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0xb8
+.data1 	0x30, 0x13, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0xeb, 0x19, 0xb8, 0xed, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x22, 0x31, 0xc0, 0xeb, 0x1e, 0xb8, 0xe7
+.data1 	0xff, 0xff, 0xff, 0xeb, 0x17, 0xb8, 0xfb, 0xff
+.data1 	0xff, 0xff, 0xeb, 0x10, 0x8b, 0x55, 0x0c, 0xbb
+.data1 	0x54, 0x0f, 0x00, 0x00, 0x8b, 0x42, 0x04, 0xe9
+.data1 	0x04, 0x1c, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x31, 0xc0, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x31
+.data1 	0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x31, 0xc0
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x24
+.data1 	0x56, 0x57, 0x8b, 0x75, 0x0c, 0x81, 0x7e, 0x10
+.data1 	0x03, 0x64, 0x1c, 0x40, 0x74, 0x2a, 0x81, 0x7e
+.data1 	0x10, 0x04, 0x64, 0x1c, 0x80, 0x74, 0x21, 0x8b
+.data1 	0x55, 0x08, 0x83, 0x7a, 0x30, 0x00, 0x74, 0x0e
+.data1 	0x56, 0xff, 0x75, 0x08, 0xff, 0x52, 0x30, 0x59
+.data1 	0x59, 0xe9, 0xc6, 0x00, 0x00, 0x00, 0xb8, 0xe7
+.data1 	0xff, 0xff, 0xff, 0xe9, 0xbc, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x08, 0xff, 0x76, 0x08, 0xff, 0x52
+.data1 	0x10, 0x59, 0x89, 0xc7, 0x85, 0xc0, 0x75, 0x0a
+.data1 	0xb8, 0xfa, 0xff, 0xff, 0xff, 0xe9, 0xa2, 0x00
+.data1 	0x00, 0x00, 0x81, 0x7e, 0x10, 0x03, 0x64, 0x1c
+.data1 	0x40, 0x75, 0x4f, 0x6a, 0x1c, 0x8d, 0x45, 0xe0
+.data1 	0x50, 0x6a, 0x01, 0x68, 0xce, 0x8a, 0x00, 0x00
+.data1 	0xff, 0x76, 0x1c, 0x6a, 0x01, 0xff, 0x76, 0x0c
+.data1 	0xe8, 0xc3, 0x12, 0x00, 0x00, 0x83, 0xc4, 0x1c
+.data1 	0x89, 0x45, 0xdc, 0x85, 0xc0, 0x74, 0x05, 0xe9
+.data1 	0x70, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xe0, 0x50
+.data1 	0x57, 0xb9, 0x02, 0x00, 0x00, 0x00, 0xe8, 0x2d
+.data1 	0x1b, 0x00, 0x00, 0x8d, 0x45, 0xe8, 0x50, 0x8d
+.data1 	0x47, 0x08, 0x50, 0xb9, 0x02, 0x00, 0x00, 0x00
+.data1 	0xe8, 0x1b, 0x1b, 0x00, 0x00, 0xe9, 0x48, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x17, 0x8b, 0x4f, 0x04, 0x89
+.data1 	0x55, 0xe0, 0x89, 0x4d, 0xe4, 0x8b, 0x57, 0x08
+.data1 	0x8b, 0x4f, 0x0c, 0x89, 0x55, 0xe8, 0x89, 0x4d
+.data1 	0xec, 0x8b, 0x55, 0x08, 0x8d, 0x45, 0xe0, 0x50
+.data1 	0xff, 0x52, 0x1c, 0x59, 0x6a, 0x1c, 0xff, 0x76
+.data1 	0x1c, 0x6a, 0x01, 0xff, 0x76, 0x0c, 0x8d, 0x45
+.data1 	0xe0, 0x50, 0x6a, 0x01, 0x68, 0xce, 0x8a, 0x00
+.data1 	0x00, 0xe8, 0x52, 0x12, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x1c, 0x89, 0x45, 0xdc, 0x85, 0xc0, 0x74, 0x02
+.data1 	0xeb, 0x02, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x6c, 0x56, 0x57
+.data1 	0x8b, 0x55, 0x08, 0xff, 0x75, 0x0c, 0xff, 0x52
+.data1 	0x10, 0x59, 0x89, 0xc7, 0x85, 0xc0, 0x0f, 0x84
+.data1 	0xb4, 0x01, 0x00, 0x00, 0x6a, 0x00, 0xff, 0x77
+.data1 	0x0c, 0xff, 0x77, 0x08, 0xe8, 0x5b, 0x16, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x0f, 0x84
+.data1 	0x9c, 0x01, 0x00, 0x00, 0x68, 0x00, 0x02, 0x00
+.data1 	0x00, 0xff, 0x77, 0x04, 0xff, 0x37, 0xe8, 0x6d
+.data1 	0x16, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45
+.data1 	0xac, 0x68, 0x00, 0x02, 0x00, 0x00, 0xff, 0x77
+.data1 	0x0c, 0xff, 0x77, 0x08, 0xe8, 0x57, 0x16, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x03, 0x45, 0xac, 0x89
+.data1 	0x45, 0xa8, 0x8d, 0x45, 0xc0, 0x50, 0x6a, 0x00
+.data1 	0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0xe8, 0x8f
+.data1 	0x02, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x85, 0xc0
+.data1 	0x75, 0x49, 0xe9, 0x51, 0x01, 0x00, 0x00, 0x83
+.data1 	0x45, 0x0c, 0x70, 0xeb, 0x4b, 0x8d, 0x45, 0xc0
+.data1 	0x50, 0xe8, 0xf4, 0x02, 0x00, 0x00, 0x59, 0xff
+.data1 	0x45, 0x0c, 0xeb, 0x3c, 0xb9, 0x05, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x45, 0x0c, 0x99, 0xf7, 0xf9, 0x89
+.data1 	0x45, 0xb8, 0x8b, 0x45, 0x0c, 0x99, 0xf7, 0xf9
+.data1 	0x4a, 0x89, 0x55, 0xb4, 0x8b, 0x55, 0xb8, 0xc1
+.data1 	0xe2, 0x02, 0x03, 0x55, 0xb4, 0xc1, 0xe2, 0x02
+.data1 	0x81, 0xc2, 0x80, 0x00, 0x00, 0x00, 0x89, 0x55
+.data1 	0x0c, 0xeb, 0x0d, 0xbb, 0x6c, 0x0f, 0x00, 0x00
+.data1 	0x8b, 0x45, 0x10, 0xe9, 0x10, 0x1a, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x08, 0xff, 0x75, 0x0c, 0xff, 0x52
+.data1 	0x10, 0x59, 0x89, 0xc7, 0x85, 0xc0, 0x0f, 0x84
+.data1 	0xec, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xb4, 0x00
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xb4, 0x04, 0x0f
+.data1 	0x8d, 0xdb, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xb4
+.data1 	0xc1, 0xe2, 0x04, 0x8d, 0x4d, 0xc0, 0x89, 0xd6
+.data1 	0x01, 0xce, 0x8b, 0x56, 0x0c, 0x03, 0x56, 0x08
+.data1 	0x89, 0x55, 0xa4, 0x39, 0x56, 0x08, 0x76, 0x06
+.data1 	0x8b, 0x55, 0xa8, 0x89, 0x55, 0xa4, 0x8b, 0x55
+.data1 	0xa8, 0x39, 0x55, 0xa4, 0x76, 0x03, 0x89, 0x55
+.data1 	0xa4, 0x8b, 0x55, 0xac, 0x39, 0x56, 0x08, 0x73
+.data1 	0x03, 0x89, 0x56, 0x08, 0x8b, 0x55, 0xa4, 0x39
+.data1 	0x56, 0x08, 0x76, 0x06, 0x8b, 0x56, 0x08, 0x89
+.data1 	0x55, 0xa4, 0x68, 0x00, 0x02, 0x00, 0x00, 0xff
+.data1 	0x76, 0x08, 0x8d, 0x45, 0x9c, 0x50, 0xe8, 0x85
+.data1 	0x15, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x50, 0x57
+.data1 	0xb9, 0x02, 0x00, 0x00, 0x00, 0xe8, 0x6e, 0x19
+.data1 	0x00, 0x00, 0x8b, 0x55, 0xa4, 0x2b, 0x56, 0x08
+.data1 	0x68, 0x00, 0x02, 0x00, 0x00, 0x52, 0x8d, 0x45
+.data1 	0x94, 0x50, 0xe8, 0x61, 0x15, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x50, 0x8d, 0x47, 0x08, 0x50, 0xb9
+.data1 	0x02, 0x00, 0x00, 0x00, 0xe8, 0x47, 0x19, 0x00
+.data1 	0x00, 0x83, 0x7d, 0x10, 0x01, 0x75, 0x3e, 0x80
+.data1 	0x7e, 0x04, 0x81, 0x75, 0x17, 0x8b, 0x55, 0xb4
+.data1 	0x03, 0x55, 0x0c, 0xff, 0x75, 0x14, 0x6a, 0x02
+.data1 	0x52, 0xff, 0x75, 0x08, 0xe8, 0x5f, 0xfe, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x10, 0x80, 0x7e, 0x04, 0x05
+.data1 	0x74, 0x06, 0x80, 0x7e, 0x04, 0x0f, 0x75, 0x15
+.data1 	0x8b, 0x55, 0xb4, 0x03, 0x55, 0x0c, 0xff, 0x76
+.data1 	0x08, 0x52, 0xff, 0x75, 0x08, 0xe8, 0x12, 0x00
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xff, 0x45, 0xb4
+.data1 	0x83, 0xc7, 0x10, 0xe9, 0x1b, 0xff, 0xff, 0xff
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x6c, 0x56, 0x57, 0xb9, 0x05, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x45, 0x0c, 0x99, 0xf7, 0xf9, 0x89
+.data1 	0x45, 0xb4, 0x8b, 0x45, 0x0c, 0x99, 0xf7, 0xf9
+.data1 	0x4a, 0x89, 0xd7, 0x8b, 0x55, 0xb4, 0xc1, 0xe2
+.data1 	0x02, 0x01, 0xfa, 0xc1, 0xe2, 0x02, 0x81, 0xc2
+.data1 	0x80, 0x00, 0x00, 0x00, 0x89, 0x55, 0xb8, 0xc7
+.data1 	0x45, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x45
+.data1 	0xc0, 0x50, 0xff, 0x75, 0xa8, 0xff, 0x75, 0x0c
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xe2, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0x85, 0xc0, 0x0f, 0x84, 0xd3
+.data1 	0x00, 0x00, 0x00, 0x8d, 0x45, 0xc0, 0x50, 0xe8
+.data1 	0x4e, 0x01, 0x00, 0x00, 0x59, 0xc7, 0x45, 0xa4
+.data1 	0x00, 0x00, 0x00, 0x00, 0x31, 0xff, 0x83, 0xff
+.data1 	0x04, 0x0f, 0x8d, 0xa9, 0x00, 0x00, 0x00, 0x89
+.data1 	0xfa, 0xc1, 0xe2, 0x04, 0x8d, 0x4d, 0xc0, 0x89
+.data1 	0xd6, 0x01, 0xce, 0x80, 0x7e, 0x04, 0x05, 0x74
+.data1 	0x06, 0x80, 0x7e, 0x04, 0x0f, 0x75, 0x0b, 0x8b
+.data1 	0x56, 0x08, 0x89, 0x55, 0xa4, 0xe9, 0x80, 0x00
+.data1 	0x00, 0x00, 0x80, 0x7e, 0x04, 0x00, 0x0f, 0x84
+.data1 	0x76, 0x00, 0x00, 0x00, 0x8b, 0x55, 0x08, 0xff
+.data1 	0x75, 0xb8, 0xff, 0x52, 0x10, 0x59, 0x89, 0x45
+.data1 	0xac, 0x85, 0xc0, 0x0f, 0x84, 0x75, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xa8, 0x03, 0x55, 0x10, 0x03
+.data1 	0x56, 0x08, 0x68, 0x00, 0x02, 0x00, 0x00, 0x52
+.data1 	0x8d, 0x45, 0x9c, 0x50, 0xe8, 0x2f, 0x14, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x50, 0xff, 0x75, 0xac
+.data1 	0xb9, 0x02, 0x00, 0x00, 0x00, 0xe8, 0x16, 0x18
+.data1 	0x00, 0x00, 0x68, 0x00, 0x02, 0x00, 0x00, 0xff
+.data1 	0x76, 0x0c, 0x8d, 0x45, 0x94, 0x50, 0xe8, 0x0d
+.data1 	0x14, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55
+.data1 	0xac, 0x50, 0x83, 0xc2, 0x08, 0x52, 0xb9, 0x02
+.data1 	0x00, 0x00, 0x00, 0xe8, 0xf0, 0x17, 0x00, 0x00
+.data1 	0xff, 0x45, 0xb8, 0xb9, 0x04, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x45, 0xb8, 0x99, 0xf7, 0xf9, 0x85, 0xd2
+.data1 	0x74, 0x14, 0x47, 0xe9, 0x4e, 0xff, 0xff, 0xff
+.data1 	0x8b, 0x55, 0xa4, 0x89, 0x55, 0xa8, 0x85, 0xd2
+.data1 	0x0f, 0x85, 0x10, 0xff, 0xff, 0xff, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c
+.data1 	0x8b, 0x55, 0x10, 0xc1, 0xe2, 0x09, 0x89, 0x55
+.data1 	0xf4, 0xc7, 0x45, 0xf8, 0x94, 0xd2, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xfc, 0x00, 0x08, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x08, 0xff, 0x75, 0x0c, 0xff, 0x52, 0x10
+.data1 	0x59, 0x85, 0xc0, 0x74, 0x1c, 0x8b, 0x55, 0x08
+.data1 	0x6a, 0x01, 0x8d, 0x45, 0xf8, 0x50, 0xff, 0x75
+.data1 	0xf4, 0x68, 0x09, 0x04, 0x00, 0x00, 0x68, 0xce
+.data1 	0x8a, 0x00, 0x00, 0xff, 0x52, 0x14, 0x83, 0xc4
+.data1 	0x14, 0x83, 0x7d, 0xfc, 0x00, 0x74, 0x04, 0x31
+.data1 	0xc0, 0xeb, 0x2d, 0x80, 0x3d, 0x92, 0xd4, 0x00
+.data1 	0x00, 0x55, 0x75, 0x09, 0x80, 0x3d, 0x93, 0xd4
+.data1 	0x00, 0x00, 0xaa, 0x74, 0x04, 0x31, 0xc0, 0xeb
+.data1 	0x17, 0x6a, 0x40, 0x68, 0x52, 0xd4, 0x00, 0x00
+.data1 	0xff, 0x75, 0x14, 0xe8, 0xd4, 0x13, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0xb8, 0x01, 0x00, 0x00, 0x00
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x14
+.data1 	0x56, 0x57, 0xbf, 0x04, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x75, 0x08, 0x8b, 0x55, 0x08, 0x83, 0xc2, 0x30
+.data1 	0x39, 0xf2, 0x76, 0x49, 0x80, 0x7e, 0x04, 0x00
+.data1 	0x74, 0x0e, 0x8b, 0x56, 0x18, 0x39, 0x56, 0x08
+.data1 	0x76, 0x36, 0x80, 0x7e, 0x14, 0x00, 0x74, 0x30
+.data1 	0x56, 0x8d, 0x45, 0xec, 0x50, 0xb9, 0x04, 0x00
+.data1 	0x00, 0x00, 0xe8, 0x09, 0x17, 0x00, 0x00, 0x8d
+.data1 	0x46, 0x10, 0x50, 0x56, 0xb9, 0x04, 0x00, 0x00
+.data1 	0x00, 0xe8, 0xfa, 0x16, 0x00, 0x00, 0x8d, 0x45
+.data1 	0xec, 0x50, 0x8d, 0x46, 0x10, 0x50, 0xb9, 0x04
+.data1 	0x00, 0x00, 0x00, 0xe8, 0xe8, 0x16, 0x00, 0x00
+.data1 	0x83, 0xc6, 0x10, 0xeb, 0xad, 0x4f, 0x85, 0xff
+.data1 	0x7f, 0xa5, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x81, 0xec, 0xb4, 0x00, 0x00
+.data1 	0x00, 0x56, 0x57, 0xc7, 0x85, 0x74, 0xff, 0xff
+.data1 	0xff, 0x38, 0x13, 0x00, 0x00, 0x83, 0xc4, 0xf8
+.data1 	0x89, 0xe0, 0x89, 0xc7, 0xc7, 0x85, 0x6c, 0xff
+.data1 	0xff, 0xff, 0x05, 0x00, 0x00, 0x00, 0x83, 0xbd
+.data1 	0x6c, 0xff, 0xff, 0xff, 0x00, 0x7e, 0x19, 0xff
+.data1 	0x8d, 0x6c, 0xff, 0xff, 0xff, 0x8b, 0x85, 0x74
+.data1 	0xff, 0xff, 0xff, 0xff, 0x85, 0x74, 0xff, 0xff
+.data1 	0xff, 0x8a, 0x08, 0x88, 0x0f, 0x47, 0xeb, 0xde
+.data1 	0x8d, 0xbd, 0x67, 0xff, 0xff, 0xff, 0x89, 0xe0
+.data1 	0x89, 0x85, 0x74, 0xff, 0xff, 0xff, 0xc7, 0x85
+.data1 	0x6c, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00
+.data1 	0x83, 0xbd, 0x6c, 0xff, 0xff, 0xff, 0x00, 0x7e
+.data1 	0x19, 0xff, 0x8d, 0x6c, 0xff, 0xff, 0xff, 0x8b
+.data1 	0x85, 0x74, 0xff, 0xff, 0xff, 0xff, 0x85, 0x74
+.data1 	0xff, 0xff, 0xff, 0x8a, 0x08, 0x88, 0x0f, 0x47
+.data1 	0xeb, 0xde, 0x59, 0x59, 0x68, 0x80, 0x00, 0x00
+.data1 	0x00, 0x8d, 0x85, 0x78, 0xff, 0xff, 0xff, 0x50
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xbb, 0x06, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x85, 0x5c, 0xff, 0xff
+.data1 	0xff, 0x85, 0xc0, 0x74, 0x29, 0x83, 0xbd, 0x5c
+.data1 	0xff, 0xff, 0xff, 0xfd, 0x75, 0x07, 0x6a, 0x00
+.data1 	0xe9, 0xb6, 0x01, 0x00, 0x00, 0xff, 0xb5, 0x5c
+.data1 	0xff, 0xff, 0xff, 0x68, 0xbc, 0x0f, 0x00, 0x00
+.data1 	0xe8, 0xe3, 0x01, 0x00, 0x00, 0x59, 0x59, 0x6a
+.data1 	0x04, 0xe9, 0x9d, 0x01, 0x00, 0x00, 0x8d, 0xb5
+.data1 	0x78, 0xff, 0xff, 0xff, 0x68, 0xb8, 0x0f, 0x00
+.data1 	0x00, 0x56, 0xe8, 0xed, 0x12, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x75, 0x07, 0x6a, 0x01, 0xe9
+.data1 	0x7f, 0x01, 0x00, 0x00, 0x68, 0xb4, 0x0f, 0x00
+.data1 	0x00, 0x56, 0xe8, 0xd5, 0x12, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x75, 0x07, 0x6a, 0x02, 0xe9
+.data1 	0x67, 0x01, 0x00, 0x00, 0xc7, 0x85, 0x58, 0xff
+.data1 	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x85
+.data1 	0x50, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00
+.data1 	0x80, 0x3e, 0x20, 0x75, 0x03, 0x46, 0xeb, 0xf8
+.data1 	0x80, 0x3e, 0x00, 0x75, 0x0b, 0xff, 0xb5, 0x50
+.data1 	0xff, 0xff, 0xff, 0xe9, 0x3b, 0x01, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x0c, 0x80, 0x3a, 0x00, 0x0f, 0x84
+.data1 	0x27, 0x01, 0x00, 0x00, 0x0f, 0xbe, 0x06, 0x50
+.data1 	0x8d, 0x85, 0x67, 0xff, 0xff, 0xff, 0x50, 0xe8
+.data1 	0x40, 0x12, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x0f, 0x84, 0x89, 0x00, 0x00, 0x00, 0x8b, 0x55
+.data1 	0x0c, 0x0f, 0xbe, 0x02, 0x50, 0x8d, 0x85, 0x67
+.data1 	0xff, 0xff, 0xff, 0x50, 0xe8, 0x23, 0x12, 0x00
+.data1 	0x00, 0x59, 0x59, 0x85, 0xc0, 0x74, 0x06, 0xff
+.data1 	0x85, 0x58, 0xff, 0xff, 0xff, 0x8b, 0x45, 0x0c
+.data1 	0xff, 0x45, 0x0c, 0x0f, 0xbe, 0x00, 0x0f, 0xbe
+.data1 	0x1e, 0x39, 0xd8, 0x75, 0x01, 0x46, 0x8b, 0x55
+.data1 	0x0c, 0x0f, 0xbe, 0x02, 0x3d, 0x20, 0x00, 0x00
+.data1 	0x00, 0x7d, 0x85, 0x0f, 0xbe, 0x02, 0xf7, 0xd8
+.data1 	0x03, 0x45, 0x0c, 0x89, 0x45, 0x0c, 0xe9, 0x75
+.data1 	0xff, 0xff, 0xff, 0xc7, 0x85, 0x54, 0xff, 0xff
+.data1 	0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x40, 0xc7
+.data1 	0x85, 0x54, 0xff, 0xff, 0xff, 0x0a, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x34, 0xc7, 0x85, 0x54, 0xff, 0xff
+.data1 	0xff, 0x08, 0x00, 0x00, 0x00, 0xeb, 0x28, 0xc7
+.data1 	0x85, 0x54, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x1c, 0xc7, 0x85, 0x54, 0xff, 0xff
+.data1 	0xff, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x10, 0x8b
+.data1 	0x55, 0x0c, 0x0f, 0xbe, 0x02, 0xbb, 0x84, 0x0f
+.data1 	0x00, 0x00, 0xe9, 0x2d, 0x15, 0x00, 0x00, 0x83
+.data1 	0xbd, 0x54, 0xff, 0xff, 0xff, 0x00, 0x79, 0x1d
+.data1 	0x0f, 0xbe, 0x06, 0x50, 0x8d, 0x85, 0x67, 0xff
+.data1 	0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00
+.data1 	0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00
+.data1 	0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00
+.data1 	0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xff, 0xff, 0x50, 0xe8, 0x84, 0x11, 0x00, 0x00
+.data1 	0x59, 0x59, 0x85, 0xc0, 0x0f, 0x85, 0x06, 0xff
+.data1 	0xff, 0xff, 0x46, 0xeb, 0xe3, 0xff, 0xb5, 0x54
+.data1 	0xff, 0xff, 0xff, 0x8d, 0x45, 0xf8, 0x50, 0x56
+.data1 	0xe8, 0x57, 0x0d, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0x85, 0x60, 0xff, 0xff, 0xff, 0x39, 0x75
+.data1 	0xf8, 0x74, 0x30, 0x8b, 0x75, 0xf8, 0x8b, 0x55
+.data1 	0x10, 0x39, 0x95, 0x58, 0xff, 0xff, 0xff, 0x0f
+.data1 	0x85, 0xd3, 0xfe, 0xff, 0xff, 0x39, 0x45, 0x18
+.data1 	0x7f, 0x19, 0x39, 0x45, 0x1c, 0x7c, 0x14, 0x8b
+.data1 	0x5d, 0x14, 0x89, 0x03, 0xc7, 0x85, 0x50, 0xff
+.data1 	0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0xe9, 0xb5
+.data1 	0xfe, 0xff, 0xff, 0xff, 0x75, 0x08, 0xe8, 0x89
+.data1 	0x06, 0x00, 0x00, 0x58, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0xc7, 0x45
+.data1 	0xe0, 0x19, 0x06, 0x00, 0x00, 0xc7, 0x45, 0xe4
+.data1 	0xce, 0x6a, 0x00, 0x00, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x68, 0x19, 0x06, 0x00, 0x00, 0x6a, 0xfe, 0xe8
+.data1 	0xec, 0x03, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0x45, 0xd8, 0x8b, 0x55, 0xf4, 0x8b, 0x45, 0x08
+.data1 	0x89, 0x10, 0x8b, 0x45, 0xd8, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x40, 0x56, 0x57
+.data1 	0xc7, 0x45, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x8d
+.data1 	0x7d, 0x0c, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08
+.data1 	0x0f, 0xbe, 0x00, 0x89, 0xc6, 0x85, 0xc0, 0x0f
+.data1 	0x84, 0x03, 0x03, 0x00, 0x00, 0x83, 0xfe, 0x25
+.data1 	0x74, 0x0c, 0xff, 0x45, 0xf8, 0x56, 0xe8, 0x05
+.data1 	0x03, 0x00, 0x00, 0x59, 0xeb, 0xdc, 0x8b, 0x45
+.data1 	0x08, 0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89
+.data1 	0xc6, 0xc7, 0x45, 0xf4, 0x01, 0x00, 0x00, 0x00
+.data1 	0x83, 0xfe, 0x2d, 0x75, 0x12, 0xc7, 0x45, 0xf4
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x45, 0x08, 0xff
+.data1 	0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0xc6, 0xc7
+.data1 	0x45, 0xec, 0x20, 0x00, 0x00, 0x00, 0x83, 0xfe
+.data1 	0x30, 0x75, 0x12, 0xc7, 0x45, 0xec, 0x30, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08
+.data1 	0x0f, 0xbe, 0x00, 0x89, 0xc6, 0xc7, 0x45, 0xe8
+.data1 	0x00, 0x00, 0x00, 0x00, 0x83, 0xfe, 0x2a, 0x75
+.data1 	0x18, 0x8d, 0x57, 0x04, 0x89, 0xd7, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0xe8, 0x8b, 0x45, 0x08, 0xff
+.data1 	0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0xc6, 0xeb
+.data1 	0x2f, 0x89, 0xf2, 0x83, 0xea, 0x30, 0x83, 0xfa
+.data1 	0x0a, 0x73, 0x25, 0x6b, 0x45, 0xe8, 0x0a, 0x89
+.data1 	0xf2, 0x83, 0xea, 0x30, 0x01, 0xc2, 0x89, 0x55
+.data1 	0xe8, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f
+.data1 	0xbe, 0x00, 0x89, 0xc6, 0x2d, 0x30, 0x00, 0x00
+.data1 	0x00, 0x3d, 0x0a, 0x00, 0x00, 0x00, 0x72, 0xdb
+.data1 	0xc7, 0x45, 0xe4, 0xff, 0xff, 0xff, 0x7f, 0x83
+.data1 	0xfe, 0x2e, 0x0f, 0x85, 0x60, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f, 0xbe
+.data1 	0x00, 0x89, 0xc6, 0x3d, 0x2a, 0x00, 0x00, 0x00
+.data1 	0x75, 0x18, 0x8d, 0x57, 0x04, 0x89, 0xd7, 0x8b
+.data1 	0x52, 0xfc, 0x89, 0x55, 0xe4, 0x8b, 0x45, 0x08
+.data1 	0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0xc6
+.data1 	0xeb, 0x36, 0x89, 0xf2, 0x83, 0xea, 0x30, 0x83
+.data1 	0xfa, 0x0a, 0x73, 0x2c, 0xc7, 0x45, 0xe4, 0x00
+.data1 	0x00, 0x00, 0x00, 0x6b, 0x45, 0xe4, 0x0a, 0x89
+.data1 	0xf2, 0x83, 0xea, 0x30, 0x01, 0xc2, 0x89, 0x55
+.data1 	0xe4, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f
+.data1 	0xbe, 0x00, 0x89, 0xc6, 0x2d, 0x30, 0x00, 0x00
+.data1 	0x00, 0x3d, 0x0a, 0x00, 0x00, 0x00, 0x72, 0xdb
+.data1 	0xc7, 0x45, 0xd8, 0x54, 0x13, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xd0, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x45
+.data1 	0xdc, 0x0a, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xf0
+.data1 	0x01, 0x00, 0x00, 0x00, 0x83, 0xfe, 0x6c, 0x74
+.data1 	0x05, 0x83, 0xfe, 0x4c, 0x75, 0x12, 0xc7, 0x45
+.data1 	0xf0, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x45, 0x08
+.data1 	0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0xc6
+.data1 	0x85, 0xf6, 0x0f, 0x85, 0x9c, 0x01, 0x00, 0x00
+.data1 	0xe9, 0xa3, 0x01, 0x00, 0x00, 0x83, 0x7d, 0xf0
+.data1 	0x00, 0x75, 0x0a, 0x8d, 0x57, 0x04, 0x89, 0xd7
+.data1 	0x8b, 0x42, 0xfc, 0xeb, 0x08, 0x8d, 0x57, 0x04
+.data1 	0x89, 0xd7, 0x8b, 0x42, 0xfc, 0x89, 0x45, 0xd0
+.data1 	0x85, 0xc0, 0x79, 0x04, 0xf7, 0xd8, 0xeb, 0x03
+.data1 	0x8b, 0x45, 0xd0, 0x89, 0x45, 0xcc, 0xeb, 0x32
+.data1 	0xc7, 0x45, 0xdc, 0x08, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x0e, 0xc7, 0x45, 0xd8, 0x40, 0x13, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xdc, 0x10, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7d, 0xf0, 0x00, 0x75, 0x0a, 0x8d, 0x57, 0x04
+.data1 	0x89, 0xd7, 0x8b, 0x42, 0xfc, 0xeb, 0x08, 0x8d
+.data1 	0x57, 0x04, 0x89, 0xd7, 0x8b, 0x42, 0xfc, 0x89
+.data1 	0x45, 0xcc, 0x8d, 0x55, 0xcb, 0x89, 0x55, 0xd4
+.data1 	0xc6, 0x02, 0x00, 0x8b, 0x45, 0xcc, 0x31, 0xd2
+.data1 	0xf7, 0x75, 0xdc, 0x03, 0x55, 0xd8, 0x0f, 0xb6
+.data1 	0x02, 0x50, 0xff, 0x4d, 0xd4, 0x8b, 0x55, 0xd4
+.data1 	0x59, 0x88, 0x0a, 0x8b, 0x45, 0xcc, 0x31, 0xd2
+.data1 	0xf7, 0x75, 0xdc, 0x89, 0x45, 0xcc, 0x85, 0xc0
+.data1 	0x75, 0xd9, 0xeb, 0x39, 0x8d, 0x55, 0xc0, 0x89
+.data1 	0x55, 0xd4, 0x8d, 0x57, 0x04, 0x89, 0xd7, 0x8b
+.data1 	0x4d, 0xd4, 0x8b, 0x52, 0xfc, 0x88, 0x11, 0xc7
+.data1 	0x45, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x3c
+.data1 	0x8d, 0x55, 0xc0, 0x89, 0x55, 0xd4, 0xc6, 0x02
+.data1 	0x25, 0xc7, 0x45, 0xe0, 0x01, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x2a, 0x8d, 0x57, 0x04, 0x89, 0xd7, 0x8b
+.data1 	0x52, 0xfc, 0x89, 0x55, 0xd4, 0xc7, 0x45, 0xe0
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xd4, 0x03
+.data1 	0x55, 0xe0, 0x80, 0x3a, 0x00, 0x74, 0x0d, 0x8b
+.data1 	0x55, 0xe4, 0x39, 0x55, 0xe0, 0x7d, 0x05, 0xff
+.data1 	0x45, 0xe0, 0xeb, 0xe8, 0x8b, 0x55, 0xe8, 0x2b
+.data1 	0x55, 0xe0, 0x89, 0x55, 0xe8, 0x83, 0x7d, 0xd0
+.data1 	0x00, 0x79, 0x03, 0xff, 0x4d, 0xe8, 0x83, 0x7d
+.data1 	0xec, 0x30, 0x75, 0x11, 0x83, 0x7d, 0xd0, 0x00
+.data1 	0x79, 0x0b, 0xff, 0x45, 0xf8, 0x6a, 0x2d, 0xe8
+.data1 	0xa4, 0x00, 0x00, 0x00, 0x59, 0x83, 0x7d, 0xf4
+.data1 	0x01, 0x75, 0x17, 0x83, 0x7d, 0xe8, 0x00, 0x7e
+.data1 	0x11, 0xff, 0x45, 0xf8, 0xff, 0x75, 0xec, 0xe8
+.data1 	0x8c, 0x00, 0x00, 0x00, 0x59, 0xff, 0x4d, 0xe8
+.data1 	0xeb, 0xe9, 0x83, 0x7d, 0xec, 0x20, 0x75, 0x11
+.data1 	0x83, 0x7d, 0xd0, 0x00, 0x79, 0x0b, 0xff, 0x45
+.data1 	0xf8, 0x6a, 0x2d, 0xe8, 0x70, 0x00, 0x00, 0x00
+.data1 	0x59, 0x83, 0x7d, 0xe0, 0x00, 0x7e, 0x18, 0xff
+.data1 	0x45, 0xf8, 0x8b, 0x45, 0xd4, 0xff, 0x45, 0xd4
+.data1 	0x0f, 0xb6, 0x18, 0x53, 0xe8, 0x57, 0x00, 0x00
+.data1 	0x00, 0x59, 0xff, 0x4d, 0xe0, 0xeb, 0xe2, 0x83
+.data1 	0x7d, 0xe8, 0x00, 0x0f, 0x8e, 0x21, 0xfd, 0xff
+.data1 	0xff, 0xff, 0x45, 0xf8, 0xff, 0x75, 0xec, 0xe8
+.data1 	0x3c, 0x00, 0x00, 0x00, 0x59, 0xff, 0x4d, 0xe8
+.data1 	0xeb, 0xe5, 0xff, 0x45, 0xf8, 0x6a, 0x25, 0xe8
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x59, 0xff, 0x45, 0xf8
+.data1 	0x56, 0xe8, 0x22, 0x00, 0x00, 0x00, 0x59, 0xe9
+.data1 	0xf6, 0xfc, 0xff, 0xff, 0xbb, 0xf0, 0x0f, 0x00
+.data1 	0x00, 0x89, 0xf0, 0xe9, 0x4c, 0x11, 0x00, 0x00
+.data1 	0x6a, 0x00, 0xe8, 0x09, 0x00, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x45, 0xf8, 0x5f, 0x5e, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x30, 0x56, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x75, 0x09, 0x83, 0x3d, 0xe4
+.data1 	0xda, 0x00, 0x00, 0x00, 0x7f, 0x09, 0x83, 0x3d
+.data1 	0xe4, 0xda, 0x00, 0x00, 0x50, 0x75, 0x59, 0x68
+.data1 	0x68, 0x13, 0x00, 0x00, 0x8d, 0x45, 0xd0, 0x50
+.data1 	0xb9, 0x03, 0x00, 0x00, 0x00, 0xe8, 0xc6, 0x10
+.data1 	0x00, 0x00, 0x31, 0xf6, 0x81, 0x7c, 0xb5, 0xd0
+.data1 	0xce, 0x6a, 0x00, 0x00, 0x74, 0x30, 0x8b, 0x15
+.data1 	0xe4, 0xda, 0x00, 0x00, 0x89, 0x55, 0xe4, 0xc7
+.data1 	0x45, 0xf0, 0x94, 0xda, 0x00, 0x00, 0xc7, 0x45
+.data1 	0xe8, 0xce, 0x8a, 0x00, 0x00, 0xc7, 0x45, 0xe0
+.data1 	0x64, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0xff, 0x74, 0xb5, 0xd0, 0xe8, 0xdb, 0x0c, 0x00
+.data1 	0x00, 0x59, 0x59, 0x46, 0xeb, 0xc6, 0xc7, 0x05
+.data1 	0xe4, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x08, 0x00, 0x74, 0x1d, 0x8b, 0x45
+.data1 	0x08, 0x0f, 0xbe, 0xc0, 0x8b, 0x15, 0xe4, 0xda
+.data1 	0x00, 0x00, 0x89, 0xd1, 0x41, 0x89, 0x0d, 0xe4
+.data1 	0xda, 0x00, 0x00, 0x89, 0xd3, 0x88, 0x83, 0x94
+.data1 	0xda, 0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x75, 0x10
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x56, 0x04, 0x56, 0xff
+.data1 	0x75, 0x08, 0xe8, 0x8d, 0x0c, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0xc7, 0x85, 0xff, 0x74, 0x04, 0x89
+.data1 	0xf8, 0xeb, 0x03, 0x8b, 0x46, 0x04, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x4c, 0x56, 0x83, 0x7d, 0x08, 0x00, 0x0f
+.data1 	0x8e, 0x7a, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xe4
+.data1 	0xce, 0x8a, 0x00, 0x00, 0x8b, 0x55, 0x08, 0x89
+.data1 	0x55, 0xf0, 0xc7, 0x45, 0xe8, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8d, 0x45, 0xdc, 0x50, 0x68, 0x18, 0x06
+.data1 	0x00, 0x00, 0x6a, 0xfe, 0xe8, 0x9f, 0xff, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x89, 0xc6, 0x85, 0xf6
+.data1 	0x74, 0x04, 0x89, 0xf0, 0xeb, 0x4b, 0x8d, 0x45
+.data1 	0xb8, 0x50, 0x6a, 0xfd, 0xe8, 0x17, 0x0c, 0x00
+.data1 	0x00, 0x59, 0x59, 0x83, 0x7d, 0xf0, 0x00, 0x7e
+.data1 	0x32, 0x81, 0x7d, 0xf0, 0xff, 0xff, 0xff, 0x7f
+.data1 	0x74, 0x29, 0x8b, 0x55, 0xf0, 0x2b, 0x55, 0x08
+.data1 	0x89, 0x55, 0xf0, 0x85, 0xd2, 0x7f, 0x07, 0xc7
+.data1 	0x45, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0x68, 0x18, 0x06, 0x00, 0x00, 0x6a
+.data1 	0xfe, 0xe8, 0x52, 0xff, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0x89, 0xc6, 0x89, 0xf0, 0xeb, 0x02, 0x89
+.data1 	0xe8, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b
+.data1 	0x55, 0x08, 0x89, 0x15, 0x74, 0x13, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x15, 0x78, 0x13, 0x00
+.data1 	0x00, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x34, 0x56, 0x57, 0x83, 0x7d, 0x08, 0x00, 0x75
+.data1 	0x0a, 0xb8, 0xea, 0xff, 0xff, 0xff, 0xe9, 0x41
+.data1 	0x01, 0x00, 0x00, 0xff, 0x75, 0x08, 0xe8, 0x89
+.data1 	0x0c, 0x00, 0x00, 0x59, 0x89, 0x45, 0xcc, 0xbe
+.data1 	0x01, 0x00, 0x00, 0x00, 0x39, 0x35, 0x74, 0x13
+.data1 	0x00, 0x00, 0x0f, 0x8e, 0x88, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x15, 0x78, 0x13, 0x00, 0x00, 0xff, 0x75
+.data1 	0xcc, 0xff, 0x75, 0x08, 0xff, 0x34, 0xb2, 0xe8
+.data1 	0x70, 0x0c, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85
+.data1 	0xc0, 0x0f, 0x85, 0x63, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x15, 0x78, 0x13, 0x00, 0x00, 0xff, 0x34, 0xb2
+.data1 	0xe8, 0x47, 0x0c, 0x00, 0x00, 0x59, 0x39, 0x45
+.data1 	0xcc, 0x73, 0x4f, 0x8b, 0x15, 0x78, 0x13, 0x00
+.data1 	0x00, 0x8b, 0x14, 0xb2, 0x03, 0x55, 0xcc, 0x80
+.data1 	0x3a, 0x3d, 0x75, 0x3e, 0x8b, 0x15, 0x78, 0x13
+.data1 	0x00, 0x00, 0x8b, 0x14, 0xb2, 0x03, 0x55, 0xcc
+.data1 	0x89, 0xd7, 0x47, 0x57, 0xe8, 0x1b, 0x0c, 0x00
+.data1 	0x00, 0x59, 0x05, 0x01, 0x00, 0x00, 0x00, 0x3d
+.data1 	0x80, 0x00, 0x00, 0x00, 0x76, 0x0a, 0xb8, 0xf9
+.data1 	0xff, 0xff, 0xff, 0xe9, 0xb4, 0x00, 0x00, 0x00
+.data1 	0x57, 0xff, 0x75, 0x0c, 0xe8, 0xdb, 0x0b, 0x00
+.data1 	0x00, 0x59, 0x59, 0x31, 0xc0, 0xe9, 0xa2, 0x00
+.data1 	0x00, 0x00, 0x46, 0xe9, 0x6c, 0xff, 0xff, 0xff
+.data1 	0xc7, 0x45, 0xe0, 0x1a, 0x06, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xec, 0x04, 0x00, 0x00, 0x00, 0xc7, 0x45
+.data1 	0xf0, 0xce, 0x8a, 0x00, 0x00, 0xc7, 0x45, 0xe4
+.data1 	0x00, 0x02, 0x00, 0x00, 0xc7, 0x45, 0xf4, 0xe8
+.data1 	0xda, 0x00, 0x00, 0x8d, 0x45, 0xdc, 0x50, 0x68
+.data1 	0x1a, 0x06, 0x00, 0x00, 0x6a, 0xfe, 0xe8, 0x3d
+.data1 	0xfe, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x89, 0x45
+.data1 	0xd0, 0x85, 0xc0, 0x74, 0x1a, 0x68, 0x00, 0x02
+.data1 	0x00, 0x00, 0xff, 0x75, 0xd0, 0x68, 0x40, 0x10
+.data1 	0x00, 0x00, 0xe8, 0x49, 0xfa, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x8b, 0x45, 0xd0, 0xeb, 0x45, 0xff
+.data1 	0x75, 0x08, 0x68, 0xe8, 0xda, 0x00, 0x00, 0xe8
+.data1 	0x3c, 0x00, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc7
+.data1 	0x85, 0xc0, 0x75, 0x07, 0xb8, 0xfd, 0xff, 0xff
+.data1 	0xff, 0xeb, 0x29, 0xff, 0x75, 0x10, 0x57, 0xff
+.data1 	0x75, 0x0c, 0xe8, 0x8d, 0x0b, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x57, 0xe8, 0x64, 0x0b, 0x00, 0x00
+.data1 	0x59, 0x05, 0x01, 0x00, 0x00, 0x00, 0x39, 0x45
+.data1 	0x10, 0x73, 0x07, 0xb8, 0xf9, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x02, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x75, 0x08
+.data1 	0x80, 0x3e, 0x00, 0x74, 0x2e, 0x8b, 0x7d, 0x0c
+.data1 	0x80, 0x3f, 0x00, 0x74, 0x0e, 0x0f, 0xbe, 0x07
+.data1 	0x0f, 0xbe, 0x1e, 0x39, 0xd8, 0x75, 0x04, 0x47
+.data1 	0x46, 0xeb, 0xed, 0x80, 0x3f, 0x00, 0x75, 0x0a
+.data1 	0x80, 0x3e, 0x3d, 0x75, 0x05, 0x8d, 0x46, 0x01
+.data1 	0xeb, 0x0b, 0x8a, 0x06, 0x46, 0x84, 0xc0, 0x74
+.data1 	0xcf, 0xeb, 0xf7, 0x31, 0xc0, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x68, 0x80, 0x00, 0x00, 0x00, 0x68, 0x7c, 0x13
+.data1 	0x00, 0x00, 0xff, 0x75, 0x08, 0xe8, 0x49, 0xfe
+.data1 	0xff, 0xff, 0x83, 0xc4, 0x0c, 0x89, 0xc6, 0x85
+.data1 	0xc0, 0x75, 0x12, 0x83, 0xfe, 0xfd, 0x74, 0x0d
+.data1 	0x56, 0x68, 0x88, 0x10, 0x00, 0x00, 0xe8, 0x85
+.data1 	0xf9, 0xff, 0xff, 0x59, 0x59, 0x68, 0x7c, 0x13
+.data1 	0x00, 0x00, 0xff, 0x75, 0x08, 0x68, 0x64, 0x10
+.data1 	0x00, 0x00, 0xe8, 0x71, 0xf9, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x68, 0x00, 0x80, 0x00, 0x00, 0x68
+.data1 	0x5c, 0x10, 0x00, 0x00, 0x68, 0x60, 0x10, 0x00
+.data1 	0x00, 0xe8, 0x06, 0x00, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0xc7, 0x05, 0xfc, 0x13, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x83, 0x7d, 0x08, 0x00
+.data1 	0x74, 0x3a, 0x83, 0x7d, 0x0c, 0x00, 0x74, 0x34
+.data1 	0x81, 0x7d, 0x10, 0x00, 0x80, 0x00, 0x00, 0x74
+.data1 	0x18, 0xff, 0x75, 0x10, 0xff, 0x75, 0x0c, 0xff
+.data1 	0x75, 0x08, 0x68, 0xd0, 0x10, 0x00, 0x00, 0xe8
+.data1 	0x1c, 0xf9, 0xff, 0xff, 0x83, 0xc4, 0x10, 0xeb
+.data1 	0x13, 0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0x68
+.data1 	0xbc, 0x10, 0x00, 0x00, 0xe8, 0x07, 0xf9, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x6a, 0x09, 0x68, 0xce
+.data1 	0x8a, 0x00, 0x00, 0xe8, 0x60, 0x03, 0x00, 0x00
+.data1 	0x59, 0x59, 0xba, 0xff, 0xff, 0xff, 0xff, 0x89
+.data1 	0x55, 0xd8, 0xff, 0xd2, 0xeb, 0xfe, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x56, 0xc7
+.data1 	0x45, 0xdc, 0x0a, 0x03, 0x00, 0x00, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe0, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xe4, 0x8d, 0x45, 0xd8, 0x50, 0xff, 0x35
+.data1 	0x00, 0x14, 0x00, 0x00, 0xe8, 0x3b, 0x09, 0x00
+.data1 	0x00, 0x59, 0x59, 0x89, 0xc6, 0x85, 0xf6, 0x74
+.data1 	0x13, 0x56, 0x68, 0x14, 0x11, 0x00, 0x00, 0x68
+.data1 	0x34, 0x11, 0x00, 0x00, 0xe8, 0x53, 0xff, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x83, 0x7d, 0xdc, 0x00
+.data1 	0x74, 0x15, 0xff, 0x75, 0xdc, 0x68, 0xe8, 0x10
+.data1 	0x00, 0x00, 0x68, 0x10, 0x11, 0x00, 0x00, 0xe8
+.data1 	0x38, 0xff, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x8b
+.data1 	0x45, 0xec, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x56, 0xc7
+.data1 	0x45, 0xdc, 0x08, 0x03, 0x00, 0x00, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe0, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xe4, 0x8d, 0x45, 0xd8, 0x50, 0xff, 0x35
+.data1 	0x00, 0x14, 0x00, 0x00, 0xe8, 0xd3, 0x08, 0x00
+.data1 	0x00, 0x59, 0x59, 0x89, 0xc6, 0x85, 0xf6, 0x74
+.data1 	0x13, 0x56, 0x68, 0x60, 0x11, 0x00, 0x00, 0x68
+.data1 	0x80, 0x11, 0x00, 0x00, 0xe8, 0xeb, 0xfe, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x83, 0x7d, 0xdc, 0x00
+.data1 	0x74, 0x15, 0xff, 0x75, 0xdc, 0x68, 0x38, 0x11
+.data1 	0x00, 0x00, 0x68, 0x5c, 0x11, 0x00, 0x00, 0xe8
+.data1 	0xd0, 0xfe, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x8b
+.data1 	0x55, 0xec, 0x0f, 0xb6, 0xc2, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x56, 0xc7
+.data1 	0x45, 0xdc, 0x01, 0x03, 0x00, 0x00, 0x8d, 0x45
+.data1 	0xd8, 0x50, 0xff, 0x35, 0x00, 0x14, 0x00, 0x00
+.data1 	0xe8, 0x77, 0x08, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0xc6, 0x85, 0xf6, 0x74, 0x13, 0x56, 0x68, 0xb0
+.data1 	0x11, 0x00, 0x00, 0x68, 0xd4, 0x11, 0x00, 0x00
+.data1 	0xe8, 0x8f, 0xfe, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x83, 0x7d, 0xdc, 0x01, 0x75, 0x2b, 0x8b, 0x55
+.data1 	0xe0, 0x8b, 0x45, 0x08, 0x89, 0x10, 0xba, 0xff
+.data1 	0xff, 0x00, 0x00, 0x23, 0x55, 0xe4, 0x8b, 0x4d
+.data1 	0x0c, 0x66, 0x89, 0x11, 0xba, 0xff, 0xff, 0x00
+.data1 	0x00, 0x23, 0x55, 0xe8, 0x8b, 0x4d, 0x10, 0x66
+.data1 	0x89, 0x11, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x1d, 0x83, 0x7d, 0xdc, 0x00, 0x74, 0x15, 0xff
+.data1 	0x75, 0xdc, 0x68, 0x84, 0x11, 0x00, 0x00, 0x68
+.data1 	0xac, 0x11, 0x00, 0x00, 0xe8, 0x43, 0xfe, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x31, 0xc0, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x68
+.data1 	0xd8, 0x11, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00
+.data1 	0x00, 0x59, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x2c, 0x56, 0x57, 0x68, 0x00, 0x14, 0x00
+.data1 	0x00, 0x68, 0x58, 0x12, 0x00, 0x00, 0xe8, 0xf9
+.data1 	0x06, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc6, 0x85
+.data1 	0xf6, 0x74, 0x13, 0x56, 0x68, 0x28, 0x12, 0x00
+.data1 	0x00, 0x68, 0x54, 0x12, 0x00, 0x00, 0xe8, 0xf9
+.data1 	0xfd, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0xc7, 0x45
+.data1 	0xd8, 0x00, 0x03, 0x00, 0x00, 0xff, 0x75, 0x08
+.data1 	0xe8, 0x8f, 0x08, 0x00, 0x00, 0x59, 0x89, 0xc7
+.data1 	0x8d, 0x57, 0x01, 0x83, 0xfa, 0x0e, 0x77, 0x10
+.data1 	0xff, 0x75, 0x08, 0x8d, 0x45, 0xe8, 0x50, 0xe8
+.data1 	0x58, 0x08, 0x00, 0x00, 0x59, 0x59, 0xeb, 0x1a
+.data1 	0xbf, 0x0d, 0x00, 0x00, 0x00, 0x57, 0xff, 0x75
+.data1 	0x08, 0x8d, 0x45, 0xe8, 0x50, 0xe8, 0xc2, 0x07
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc6, 0x44, 0x3d
+.data1 	0xe8, 0x00, 0x8d, 0x45, 0xd4, 0x50, 0xff, 0x35
+.data1 	0x00, 0x14, 0x00, 0x00, 0xe8, 0x73, 0x07, 0x00
+.data1 	0x00, 0x59, 0x59, 0x89, 0xc6, 0x85, 0xf6, 0x74
+.data1 	0x13, 0x56, 0x68, 0x04, 0x12, 0x00, 0x00, 0x68
+.data1 	0x24, 0x12, 0x00, 0x00, 0xe8, 0x8b, 0xfd, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x83, 0x7d, 0xd8, 0x00
+.data1 	0x74, 0x15, 0xff, 0x75, 0xd8, 0x68, 0xdc, 0x11
+.data1 	0x00, 0x00, 0x68, 0x00, 0x12, 0x00, 0x00, 0xe8
+.data1 	0x70, 0xfd, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x56, 0xc7, 0x45, 0xdc, 0x02, 0x03
+.data1 	0x00, 0x00, 0x8b, 0x45, 0x08, 0x8b, 0x10, 0x89
+.data1 	0x55, 0xe0, 0x8d, 0x45, 0xd8, 0x50, 0xff, 0x35
+.data1 	0x00, 0x14, 0x00, 0x00, 0xe8, 0x13, 0x07, 0x00
+.data1 	0x00, 0x59, 0x59, 0x89, 0xc6, 0x85, 0xf6, 0x74
+.data1 	0x13, 0x56, 0x68, 0x88, 0x12, 0x00, 0x00, 0x68
+.data1 	0xa8, 0x12, 0x00, 0x00, 0xe8, 0x2b, 0xfd, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x83, 0x7d, 0xdc, 0x01
+.data1 	0x75, 0x2b, 0x8b, 0x55, 0xe0, 0x8b, 0x45, 0x08
+.data1 	0x89, 0x10, 0xba, 0xff, 0xff, 0x00, 0x00, 0x23
+.data1 	0x55, 0xe4, 0x8b, 0x4d, 0x0c, 0x66, 0x89, 0x11
+.data1 	0xba, 0xff, 0xff, 0x00, 0x00, 0x23, 0x55, 0xe8
+.data1 	0x8b, 0x4d, 0x10, 0x66, 0x89, 0x11, 0xb8, 0x01
+.data1 	0x00, 0x00, 0x00, 0xeb, 0x1d, 0x83, 0x7d, 0xdc
+.data1 	0x00, 0x74, 0x15, 0xff, 0x75, 0xdc, 0x68, 0x5c
+.data1 	0x12, 0x00, 0x00, 0x68, 0x84, 0x12, 0x00, 0x00
+.data1 	0xe8, 0xdf, 0xfc, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x31, 0xc0, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x8b, 0x55
+.data1 	0x10, 0x89, 0x55, 0xe4, 0xc7, 0x45, 0xec, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x08, 0x89, 0x55
+.data1 	0xf0, 0x8d, 0x45, 0xdc, 0x50, 0x68, 0x15, 0x06
+.data1 	0x00, 0x00, 0x6a, 0xfe, 0xe8, 0xd7, 0xf9, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x89, 0x45, 0xd8, 0x8b
+.data1 	0x55, 0xf4, 0x8b, 0x45, 0x0c, 0x89, 0x10, 0x8b
+.data1 	0x45, 0xd8, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0xc7, 0x45, 0xe0, 0x13, 0x06, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x08, 0x66, 0x89, 0x55, 0xe4
+.data1 	0x8b, 0x55, 0x0c, 0x66, 0x89, 0x55, 0xe6, 0x8b
+.data1 	0x55, 0x10, 0x89, 0x55, 0xe8, 0x8b, 0x45, 0x14
+.data1 	0x8b, 0x10, 0x89, 0x55, 0xf8, 0x8d, 0x45, 0xdc
+.data1 	0x50, 0x68, 0x13, 0x06, 0x00, 0x00, 0x6a, 0xfe
+.data1 	0xe8, 0x8b, 0xf9, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0x45, 0xd8, 0x83, 0x7d, 0x08, 0x01, 0x75
+.data1 	0x08, 0x8b, 0x55, 0xf8, 0x8b, 0x45, 0x14, 0x89
+.data1 	0x10, 0x8b, 0x45, 0xd8, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xe8, 0x8d, 0x45, 0xdc, 0x50, 0x68, 0x06
+.data1 	0x06, 0x00, 0x00, 0x6a, 0xfe, 0xe8, 0x4e, 0xf9
+.data1 	0xff, 0xff, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x10, 0x89, 0x55, 0xe4, 0xc7, 0x45, 0xec, 0x01
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x08, 0x89, 0x55
+.data1 	0xf0, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf4, 0x8d
+.data1 	0x45, 0xdc, 0x50, 0x68, 0x15, 0x06, 0x00, 0x00
+.data1 	0x6a, 0xfe, 0xe8, 0x19, 0xf9, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xec
+.data1 	0x8b, 0x55, 0x10, 0x89, 0x55, 0xe4, 0x8b, 0x55
+.data1 	0x0c, 0x89, 0x55, 0xf0, 0x8b, 0x55, 0x14, 0x89
+.data1 	0x55, 0xe8, 0x8b, 0x55, 0x18, 0x89, 0x55, 0xf8
+.data1 	0x8b, 0x55, 0x1c, 0x89, 0x55, 0xf4, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0x68, 0x16, 0x06, 0x00, 0x00, 0x6a
+.data1 	0xfe, 0xe8, 0xda, 0xf8, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xf0
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x55, 0xe8, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0x68, 0x18, 0x06, 0x00, 0x00, 0x6a
+.data1 	0xfe, 0xe8, 0xb2, 0xf8, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe8
+.data1 	0x8b, 0x55, 0x0c, 0x66, 0x89, 0x55, 0xe4, 0x8b
+.data1 	0x55, 0x10, 0x89, 0x55, 0xf0, 0x8b, 0x55, 0x14
+.data1 	0x89, 0x55, 0xf8, 0x8d, 0x45, 0xdc, 0x50, 0x68
+.data1 	0x0e, 0x06, 0x00, 0x00, 0x6a, 0xfe, 0xe8, 0x7d
+.data1 	0xf8, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x89, 0x45
+.data1 	0xd8, 0x8b, 0x55, 0xf4, 0x8b, 0x45, 0x18, 0x89
+.data1 	0x10, 0x8b, 0x45, 0xd8, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0xc7, 0x45
+.data1 	0xe4, 0x62, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xec
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x55, 0x08, 0x89
+.data1 	0x55, 0xf8, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf4
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x68, 0x17, 0x06, 0x00
+.data1 	0x00, 0x6a, 0xfe, 0xe8, 0x38, 0xf8, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x83, 0x7d
+.data1 	0x20, 0x00, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x3f
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xe8, 0x8b, 0x55
+.data1 	0x0c, 0x66, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x10
+.data1 	0x89, 0x55, 0xf0, 0x8b, 0x55, 0x14, 0x89, 0x55
+.data1 	0xec, 0x8b, 0x55, 0x18, 0x66, 0x89, 0x55, 0xe6
+.data1 	0x8b, 0x55, 0x1c, 0x89, 0x55, 0xf4, 0x8b, 0x55
+.data1 	0x20, 0x89, 0x55, 0xf8, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x68, 0x0f, 0x06, 0x00, 0x00, 0x6a, 0xfe, 0xe8
+.data1 	0xe4, 0xf7, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0xc7, 0x45, 0xe4, 0x62, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xec, 0x01, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xf8, 0x8b, 0x55
+.data1 	0x0c, 0x89, 0x55, 0xf4, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x68, 0x17, 0x06, 0x00, 0x00, 0x6a, 0xfe, 0xe8
+.data1 	0xac, 0xf7, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x35, 0x04, 0x14, 0x00, 0x00, 0x4e, 0x78
+.data1 	0x09, 0xff, 0x14, 0xb5, 0x20, 0xdd, 0x00, 0x00
+.data1 	0xeb, 0xf4, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0xe8, 0xdf, 0xff, 0xff, 0xff, 0x83, 0x3d, 0x08
+.data1 	0x14, 0x00, 0x00, 0x00, 0x74, 0x06, 0xff, 0x15
+.data1 	0x08, 0x14, 0x00, 0x00, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x20, 0x03, 0x00, 0x00, 0x59, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x18, 0x56, 0x8b
+.data1 	0x75, 0x08, 0x85, 0xf6, 0x7e, 0x0a, 0x83, 0xfe
+.data1 	0x17, 0x7f, 0x05, 0x83, 0xfe, 0x09, 0x75, 0x11
+.data1 	0xc7, 0x05, 0x10, 0x14, 0x00, 0x00, 0x16, 0x00
+.data1 	0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x36, 0x8d, 0x45, 0xf8, 0x50, 0xe8, 0x92, 0x02
+.data1 	0x00, 0x00, 0x59, 0xc7, 0x45, 0xfc, 0x00, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf4
+.data1 	0x8d, 0x45, 0xe8, 0x50, 0x8d, 0x45, 0xf4, 0x50
+.data1 	0x56, 0xe8, 0xe6, 0x01, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x85, 0xc0, 0x79, 0x07, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xeb, 0x03, 0x8b, 0x45, 0xe8, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x75, 0x08, 0x6a, 0x01, 0xff, 0x75, 0x10
+.data1 	0xff, 0x75, 0x0c, 0x56, 0xe8, 0x21, 0x00, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x10, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0x8b, 0x75, 0x08, 0x6a, 0x00
+.data1 	0xff, 0x75, 0x10, 0xff, 0x75, 0x0c, 0x56, 0xe8
+.data1 	0x06, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x1c
+.data1 	0x56, 0x57, 0x8b, 0x75, 0x08, 0xc7, 0x45, 0xf8
+.data1 	0x00, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xf0, 0x00
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x45, 0xec, 0x01, 0x00
+.data1 	0x00, 0x00, 0x89, 0x75, 0xe8, 0x83, 0x7d, 0x0c
+.data1 	0x00, 0x74, 0x05, 0x8b, 0x45, 0x0c, 0x89, 0x30
+.data1 	0x0f, 0xbe, 0x06, 0xf6, 0x80, 0x15, 0x14, 0x00
+.data1 	0x00, 0x08, 0x74, 0x03, 0x46, 0xeb, 0xf1, 0x0f
+.data1 	0xbe, 0x06, 0x89, 0xc7, 0x83, 0xff, 0x2d, 0x74
+.data1 	0x05, 0x83, 0xff, 0x2b, 0x75, 0x0d, 0x83, 0xff
+.data1 	0x2d, 0x75, 0x07, 0xc7, 0x45, 0xec, 0xff, 0xff
+.data1 	0xff, 0xff, 0x46, 0x89, 0x75, 0xe4, 0x83, 0x7d
+.data1 	0x10, 0x00, 0x75, 0x2c, 0x80, 0x3e, 0x30, 0x75
+.data1 	0x1e, 0x46, 0x80, 0x3e, 0x78, 0x74, 0x05, 0x80
+.data1 	0x3e, 0x58, 0x75, 0x0a, 0xc7, 0x45, 0x10, 0x10
+.data1 	0x00, 0x00, 0x00, 0x46, 0xeb, 0x29, 0xc7, 0x45
+.data1 	0x10, 0x08, 0x00, 0x00, 0x00, 0xeb, 0x20, 0xc7
+.data1 	0x45, 0x10, 0x0a, 0x00, 0x00, 0x00, 0xeb, 0x17
+.data1 	0x83, 0x7d, 0x10, 0x10, 0x75, 0x11, 0x80, 0x3e
+.data1 	0x30, 0x75, 0x0c, 0x46, 0x80, 0x3e, 0x78, 0x74
+.data1 	0x05, 0x80, 0x3e, 0x58, 0x75, 0x01, 0x46, 0x0f
+.data1 	0xbe, 0x06, 0x89, 0xc7, 0x89, 0xfa, 0x83, 0xea
+.data1 	0x30, 0x83, 0xfa, 0x09, 0x77, 0x0a, 0x89, 0xfa
+.data1 	0x83, 0xea, 0x30, 0x89, 0x55, 0xfc, 0xeb, 0x26
+.data1 	0x89, 0xfa, 0x83, 0xea, 0x61, 0x83, 0xfa, 0x19
+.data1 	0x77, 0x0a, 0x89, 0xfa, 0x83, 0xea, 0x57, 0x89
+.data1 	0x55, 0xfc, 0xeb, 0x12, 0x89, 0xfa, 0x83, 0xea
+.data1 	0x41, 0x83, 0xfa, 0x19, 0x77, 0x37, 0x89, 0xfa
+.data1 	0x83, 0xea, 0x37, 0x89, 0x55, 0xfc, 0x8b, 0x55
+.data1 	0xfc, 0x39, 0x55, 0x10, 0x76, 0x27, 0xba, 0xff
+.data1 	0xff, 0xff, 0xff, 0x2b, 0x55, 0xfc, 0x89, 0xd0
+.data1 	0x31, 0xd2, 0xf7, 0x75, 0x10, 0x39, 0x45, 0xf8
+.data1 	0x76, 0x03, 0xff, 0x45, 0xf0, 0x8b, 0x55, 0x10
+.data1 	0x0f, 0xaf, 0x55, 0xf8, 0x03, 0x55, 0xfc, 0x89
+.data1 	0x55, 0xf8, 0x46, 0xeb, 0x92, 0x83, 0x7d, 0x0c
+.data1 	0x00, 0x74, 0x14, 0x39, 0x75, 0xe4, 0x75, 0x0a
+.data1 	0x8b, 0x55, 0xe8, 0x8b, 0x45, 0x0c, 0x89, 0x10
+.data1 	0xeb, 0x05, 0x8b, 0x45, 0x0c, 0x89, 0x30, 0x83
+.data1 	0x7d, 0xf0, 0x00, 0x75, 0x27, 0x83, 0x7d, 0x14
+.data1 	0x00, 0x74, 0x21, 0x83, 0x7d, 0xec, 0x00, 0x79
+.data1 	0x09, 0x81, 0x7d, 0xf8, 0x00, 0x00, 0x00, 0x80
+.data1 	0x77, 0x0f, 0x83, 0x7d, 0xec, 0x00, 0x7e, 0x0c
+.data1 	0x81, 0x7d, 0xf8, 0xff, 0xff, 0xff, 0x7f, 0x76
+.data1 	0x03, 0xff, 0x45, 0xf0, 0x83, 0x7d, 0xf0, 0x00
+.data1 	0x74, 0x2b, 0xc7, 0x05, 0x10, 0x14, 0x00, 0x00
+.data1 	0x22, 0x00, 0x00, 0x00, 0x83, 0x7d, 0x14, 0x00
+.data1 	0x74, 0x14, 0x83, 0x7d, 0xec, 0x00, 0x79, 0x07
+.data1 	0xb8, 0x00, 0x00, 0x00, 0x80, 0xeb, 0x17, 0xb8
+.data1 	0xff, 0xff, 0xff, 0x7f, 0xeb, 0x10, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xeb, 0x09, 0x8b, 0x55, 0xec
+.data1 	0x0f, 0xaf, 0x55, 0xf8, 0x89, 0xd0, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe8
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf0, 0x8b, 0x55
+.data1 	0x10, 0x89, 0x55, 0xf4, 0xc7, 0x45, 0xf8, 0xd4
+.data1 	0x50, 0x00, 0x00, 0x8d, 0x45, 0xdc, 0x50, 0x6a
+.data1 	0x47, 0x6a, 0x00, 0xe8, 0x10, 0x03, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0x7d, 0x0c, 0x17, 0x76
+.data1 	0x11, 0xc7, 0x05, 0x10, 0x14, 0x00, 0x00, 0x16
+.data1 	0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x11, 0x8b, 0x4d, 0x0c, 0xba, 0x01, 0x00
+.data1 	0x00, 0x00, 0xd3, 0xe2, 0x8b, 0x45, 0x08, 0x09
+.data1 	0x10, 0x31, 0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0x7d, 0x0c, 0x17, 0x76, 0x11, 0xc7, 0x05
+.data1 	0x10, 0x14, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x13, 0x8b
+.data1 	0x4d, 0x0c, 0xba, 0x01, 0x00, 0x00, 0x00, 0xd3
+.data1 	0xe2, 0xf7, 0xd2, 0x8b, 0x45, 0x08, 0x21, 0x10
+.data1 	0x31, 0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b
+.data1 	0x45, 0x08, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b
+.data1 	0x45, 0x08, 0xc7, 0x00, 0xff, 0xff, 0xff, 0x00
+.data1 	0x31, 0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0x7d, 0x0c, 0x17, 0x76, 0x11, 0xc7, 0x05, 0x10
+.data1 	0x14, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x1a, 0x8b, 0x4d
+.data1 	0x0c, 0xba, 0x01, 0x00, 0x00, 0x00, 0xd3, 0xe2
+.data1 	0x8b, 0x45, 0x08, 0x85, 0x10, 0x74, 0x07, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x00, 0xeb, 0x02, 0x31, 0xc0
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0xe9, 0x93, 0x02, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0xfb, 0x01, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0x03, 0xff, 0xff
+.data1 	0xff, 0x00, 0x00, 0x00, 0xe9, 0x8b, 0xff, 0xff
+.data1 	0xff, 0x00, 0x00, 0x00, 0x8b, 0x44, 0x24, 0x04
+.data1 	0x8b, 0x54, 0x24, 0x08, 0x03, 0x54, 0x24, 0x10
+.data1 	0x89, 0x10, 0x8b, 0x54, 0x24, 0x0c, 0x83, 0xd2
+.data1 	0x00, 0x89, 0x50, 0x04, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x89, 0xe1, 0x31, 0xc0, 0x8b, 0x51, 0x04, 0x2b
+.data1 	0x51, 0x0c, 0x8b, 0x51, 0x08, 0x1b, 0x51, 0x10
+.data1 	0x19, 0xc0, 0x8b, 0x51, 0x0c, 0x2b, 0x51, 0x04
+.data1 	0x8b, 0x51, 0x10, 0x1b, 0x51, 0x08, 0x15, 0x00
+.data1 	0x00, 0x00, 0x00, 0xc3, 0x89, 0xe1, 0xff, 0x71
+.data1 	0x10, 0xc7, 0x41, 0x10, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe8, 0xcd, 0xff, 0xff, 0xff, 0x8f, 0x41, 0x10
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x8b, 0x44, 0x24, 0x04
+.data1 	0x83, 0x7c, 0x24, 0x08, 0x00, 0x74, 0x05, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x31, 0xd2, 0x8b, 0x44, 0x24, 0x08, 0xf7, 0x74
+.data1 	0x24, 0x0c, 0x8b, 0x44, 0x24, 0x04, 0xf7, 0x74
+.data1 	0x24, 0x0c, 0xc3, 0x59, 0xe8, 0xe7, 0xff, 0xff
+.data1 	0xff, 0x89, 0xd0, 0xff, 0xe1, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x4c, 0x24, 0x04, 0x8b, 0x44, 0x24, 0x08
+.data1 	0xf7, 0x64, 0x24, 0x0c, 0x89, 0x01, 0x89, 0x51
+.data1 	0x04, 0x89, 0xc8, 0xc3, 0x83, 0xc4, 0x10, 0xe9
+.data1 	0x32, 0x02, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x01
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x02, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x03
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0xb9
+.data1 	0x04, 0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x53, 0x8b, 0x5d, 0x08
+.data1 	0xb9, 0x08, 0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b
+.data1 	0x5d, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x7d, 0x08, 0x8b, 0x75, 0x0c, 0x8b
+.data1 	0x4d, 0x10, 0xe9, 0x27, 0x02, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xba, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x5a, 0x02, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x57
+.data1 	0xfc, 0x8b, 0x7d, 0x08, 0xba, 0x10, 0x00, 0x00
+.data1 	0x00, 0xd1, 0xe2, 0x89, 0xd1, 0x30, 0xc0, 0xf2
+.data1 	0xae, 0x9c, 0x29, 0xd1, 0xf7, 0xd9, 0x29, 0xcf
+.data1 	0x8a, 0x45, 0x0c, 0xf2, 0xae, 0x74, 0x08, 0x9d
+.data1 	0x75, 0xe7, 0x31, 0xc0, 0x5f, 0x5d, 0xc3, 0x58
+.data1 	0x8d, 0x47, 0xff, 0x5f, 0x5d, 0xc3, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xb9, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x3a, 0x02, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0xb9, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x55
+.data1 	0x02, 0x00, 0x00, 0x8b, 0x45, 0x08, 0x5f, 0x5e
+.data1 	0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xb9, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x5a, 0x02, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x4c, 0x24, 0x0c
+.data1 	0xe9, 0xfb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x4d, 0x10, 0xe8, 0x17, 0x02, 0x00
+.data1 	0x00, 0x89, 0xd1, 0xf3, 0xaa, 0x8b, 0x45, 0x08
+.data1 	0x5f, 0x5e, 0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xf0
+.data1 	0xc7, 0x45, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff
+.data1 	0x75, 0x08, 0xe8, 0xa5, 0xff, 0xff, 0xff, 0x59
+.data1 	0x05, 0x01, 0x00, 0x00, 0x00, 0x89, 0x45, 0xe8
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x50, 0x6a, 0x00
+.data1 	0xe8, 0x1b, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x85, 0xc0, 0x79, 0x07, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xeb, 0x0a, 0x8b, 0x55, 0xe4, 0x8b, 0x45
+.data1 	0x0c, 0x89, 0x10, 0x31, 0xc0, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x75, 0x10
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x56, 0x04, 0x56, 0xff
+.data1 	0x75, 0x08, 0xe8, 0x85, 0xfe, 0xff, 0xff, 0x59
+.data1 	0x59, 0x89, 0xc7, 0x85, 0xff, 0x74, 0x03, 0x89
+.data1 	0x7e, 0x04, 0x83, 0x7e, 0x04, 0x00, 0x79, 0x12
+.data1 	0x8b, 0x56, 0x04, 0xf7, 0xda, 0x89, 0x15, 0x10
+.data1 	0x14, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x03, 0x8b, 0x46, 0x04, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe0
+.data1 	0x8d, 0x45, 0xd8, 0x50, 0x6a, 0x01, 0x6a, 0x00
+.data1 	0xe8, 0xa3, 0xff, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0xba, 0xff, 0xff, 0xff, 0xff, 0x89, 0x55, 0xfc
+.data1 	0xff, 0xd2, 0xeb, 0xfe, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x48, 0x56, 0x8b, 0x75, 0x08, 0x8b, 0x16
+.data1 	0x89, 0x55, 0xb8, 0x8b, 0x56, 0x04, 0x89, 0x55
+.data1 	0xbc, 0x8b, 0x56, 0x08, 0x89, 0x55, 0xec, 0x8b
+.data1 	0x56, 0x0c, 0x89, 0x55, 0xf8, 0x8b, 0x56, 0x10
+.data1 	0x89, 0x55, 0xd0, 0x8b, 0x55, 0x0c, 0x89, 0x55
+.data1 	0xe4, 0x8d, 0x45, 0xb8, 0x50, 0xe8, 0x04, 0x00
+.data1 	0x00, 0x00, 0x59, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x04, 0x56, 0x8b, 0x75, 0x08
+.data1 	0x8d, 0x45, 0xfc, 0x50, 0xe8, 0xab, 0xfc, 0xff
+.data1 	0xff, 0x59, 0x6a, 0x00, 0x8d, 0x45, 0xfc, 0x50
+.data1 	0x6a, 0x02, 0xe8, 0x31, 0x01, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x8b, 0x56, 0x04, 0x89, 0x15, 0xfc
+.data1 	0xdc, 0x00, 0x00, 0x8b, 0x16, 0x89, 0x15, 0xf4
+.data1 	0xdc, 0x00, 0x00, 0x89, 0x35, 0x04, 0xdd, 0x00
+.data1 	0x00, 0x68, 0xe8, 0xdc, 0x00, 0x00, 0x6a, 0x4b
+.data1 	0x6a, 0x00, 0xe8, 0x11, 0xff, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x08
+.data1 	0x8b, 0x75, 0x0c, 0x8b, 0x4d, 0x10, 0x89, 0xf8
+.data1 	0x29, 0xf0, 0x39, 0xc8, 0x72, 0x2f, 0xfc, 0x83
+.data1 	0xf9, 0x10, 0x72, 0x20, 0x89, 0xf0, 0x09, 0xf8
+.data1 	0xa8, 0x01, 0x75, 0x18, 0xa8, 0x02, 0x75, 0x0d
+.data1 	0x0f, 0xac, 0xc8, 0x02, 0xc1, 0xe9, 0x02, 0xf3
+.data1 	0xa5, 0x0f, 0xa4, 0xc1, 0x02, 0xd1, 0xe9, 0xf3
+.data1 	0x66, 0xa5, 0x11, 0xc9, 0xf3, 0xa4, 0x8b, 0x45
+.data1 	0x08, 0x5f, 0x5e, 0x5d, 0xc3, 0xfd, 0x8d, 0x74
+.data1 	0x0e, 0xff, 0x8d, 0x7c, 0x0f, 0xff, 0xf3, 0xa4
+.data1 	0xfc, 0xeb, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x08
+.data1 	0xb9, 0xff, 0xff, 0xff, 0xff, 0x30, 0xc0, 0xfc
+.data1 	0xf2, 0xae, 0x4f, 0x57, 0x8b, 0x7d, 0x0c, 0x89
+.data1 	0xd1, 0xf2, 0xae, 0x75, 0x01, 0x41, 0x29, 0xca
+.data1 	0x89, 0xd1, 0x8b, 0x75, 0x0c, 0x5f, 0xf3, 0xa4
+.data1 	0xaa, 0x8b, 0x45, 0x08, 0x5f, 0x5e, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x85, 0xc9, 0x74
+.data1 	0x13, 0x8b, 0x75, 0x08, 0x8b, 0x7d, 0x0c, 0xfc
+.data1 	0xa6, 0x75, 0x09, 0x80, 0x7e, 0xff, 0x00, 0x74
+.data1 	0x03, 0x49, 0x75, 0xf4, 0x0f, 0x97, 0xc0, 0x0f
+.data1 	0x92, 0xc4, 0x28, 0xe0, 0x0f, 0xbe, 0xc0, 0x5f
+.data1 	0x5e, 0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x7d, 0x0c, 0x30, 0xc0, 0x89, 0xca, 0xfc
+.data1 	0xf2, 0xae, 0x29, 0xca, 0x87, 0xca, 0x8b, 0x75
+.data1 	0x0c, 0x8b, 0x7d, 0x08, 0xf3, 0xa4, 0xc3, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x57, 0x8b, 0x7d, 0x08, 0x30
+.data1 	0xc0, 0x89, 0xca, 0x80, 0xf9, 0x01, 0xfc, 0xf2
+.data1 	0xae, 0x75, 0x01, 0x41, 0x89, 0xd0, 0x29, 0xc8
+.data1 	0x5f, 0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x83, 0x7d
+.data1 	0x0c, 0x00, 0x75, 0x10, 0xc7, 0x45, 0xe4, 0x04
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x45, 0xf0, 0x00, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x0e, 0x8b, 0x55, 0x08, 0x89
+.data1 	0x55, 0xe4, 0x8b, 0x45, 0x0c, 0x8b, 0x10, 0x89
+.data1 	0x55, 0xf0, 0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x4a
+.data1 	0x6a, 0x00, 0xe8, 0xd1, 0xfd, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x85, 0xc0, 0x79, 0x07, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xeb, 0x11, 0x83, 0x7d, 0x10
+.data1 	0x00, 0x74, 0x08, 0x8b, 0x55, 0xf0, 0x8b, 0x45
+.data1 	0x10, 0x89, 0x10, 0x8b, 0x45, 0xe0, 0xc9, 0xc3
+.data1 	0x89, 0xe3, 0x89, 0xf0, 0x89, 0xfa, 0x8b, 0x7b
+.data1 	0x04, 0x8b, 0x73, 0x08, 0xf3, 0xa5, 0x89, 0xc6
+.data1 	0x89, 0xd7, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x13, 0x2b, 0x43, 0x04, 0x3b, 0x43, 0x08
+.data1 	0x77, 0x0c, 0xc1, 0xe0, 0x02, 0x01, 0xc3, 0x8b
+.data1 	0x5b, 0x0c, 0x85, 0xdb, 0x75, 0x11, 0x89, 0xd3
+.data1 	0x85, 0xdb, 0x75, 0x0b, 0xb8, 0x14, 0x00, 0x00
+.data1 	0x00, 0x50, 0xe9, 0x2d, 0x00, 0x00, 0x00, 0xff
+.data1 	0xe3, 0x00, 0x00, 0x00, 0x8b, 0x13, 0x8b, 0x4b
+.data1 	0x04, 0x83, 0xc3, 0x08, 0x49, 0x7c, 0x18, 0x3b
+.data1 	0x03, 0x75, 0xf6, 0x8b, 0x5b, 0x04, 0x85, 0xdb
+.data1 	0x75, 0x0b, 0xb8, 0x14, 0x00, 0x00, 0x00, 0x50
+.data1 	0xe9, 0x07, 0x00, 0x00, 0x00, 0xff, 0xe3, 0x89
+.data1 	0xd3, 0xeb, 0xeb, 0x00, 0xe8, 0x0f, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x77, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00
+.data1 	0x31, 0xdb, 0x87, 0x1d, 0x18, 0x15, 0x00, 0x00
+.data1 	0x85, 0xdb, 0x74, 0x05, 0x50, 0xff, 0xd3, 0x58
+.data1 	0xc3, 0x50, 0xe8, 0xe1, 0xff, 0xff, 0xff, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x61
+.data1 	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x41, 0x54, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x63, 0x6f, 0x70
+.data1 	0x79, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65
+.data1 	0x74, 0x65, 0x72, 0x73, 0x00, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74
+.data1 	0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x42, 0x49
+.data1 	0x4f, 0x53, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x72, 0x65, 0x61
+.data1 	0x64, 0x20, 0x42, 0x49, 0x4f, 0x53, 0x00, 0x00
+.data1 	0x63, 0x61, 0x6e, 0x27, 0x74, 0x20, 0x6d, 0x61
+.data1 	0x70, 0x20, 0x70, 0x72, 0x64, 0x20, 0x74, 0x61
+.data1 	0x62, 0x6c, 0x65, 0x00, 0x61, 0x74, 0x5f, 0x77
+.data1 	0x69, 0x6e, 0x69, 0x00, 0x63, 0x61, 0x6e, 0x27
+.data1 	0x74, 0x20, 0x6d, 0x61, 0x70, 0x20, 0x64, 0x6d
+.data1 	0x61, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72
+.data1 	0x00, 0x00, 0x00, 0x00, 0x61, 0x74, 0x5f, 0x77
+.data1 	0x69, 0x6e, 0x69, 0x00, 0x44, 0x4d, 0x41, 0x20
+.data1 	0x66, 0x6f, 0x72, 0x20, 0x41, 0x54, 0x41, 0x20
+.data1 	0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20
+.data1 	0x69, 0x73, 0x20, 0x64, 0x69, 0x73, 0x61, 0x62
+.data1 	0x6c, 0x65, 0x64, 0x2e, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0x61, 0x74, 0x61, 0x70
+.data1 	0x69, 0x5f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0x61, 0x74, 0x61, 0x5f
+.data1 	0x6e, 0x6f, 0x5f, 0x64, 0x6d, 0x61, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0x61, 0x74, 0x61, 0x5f
+.data1 	0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00
+.data1 	0x61, 0x74, 0x61, 0x5f, 0x70, 0x63, 0x69, 0x5f
+.data1 	0x64, 0x65, 0x62, 0x75, 0x67, 0x00, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0x61, 0x74, 0x61, 0x5f
+.data1 	0x73, 0x74, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65
+.data1 	0x6f, 0x75, 0x74, 0x00, 0x61, 0x74, 0x61, 0x70
+.data1 	0x63, 0x69, 0x3a, 0x20, 0x69, 0x67, 0x6e, 0x6f
+.data1 	0x72, 0x65, 0x64, 0x20, 0x64, 0x72, 0x69, 0x76
+.data1 	0x65, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x73, 0x65
+.data1 	0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20
+.data1 	0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2c
+.data1 	0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x25, 0x78
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x61, 0x74, 0x61, 0x70
+.data1 	0x63, 0x69, 0x20, 0x25, 0x64, 0x3a, 0x20, 0x30
+.data1 	0x78, 0x25, 0x78, 0x20, 0x30, 0x78, 0x25, 0x78
+.data1 	0x20, 0x69, 0x72, 0x71, 0x20, 0x25, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x61, 0x74, 0x61, 0x70
+.data1 	0x63, 0x69, 0x3a, 0x20, 0x69, 0x67, 0x6e, 0x6f
+.data1 	0x72, 0x65, 0x64, 0x20, 0x64, 0x72, 0x69, 0x76
+.data1 	0x65, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x70, 0x72
+.data1 	0x69, 0x6d, 0x61, 0x72, 0x79, 0x20, 0x63, 0x68
+.data1 	0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2c, 0x20, 0x62
+.data1 	0x61, 0x73, 0x65, 0x20, 0x25, 0x78, 0x0a, 0x00
+.data1 	0x61, 0x74, 0x61, 0x70, 0x63, 0x69, 0x20, 0x25
+.data1 	0x64, 0x3a, 0x20, 0x30, 0x78, 0x25, 0x78, 0x20
+.data1 	0x30, 0x78, 0x25, 0x78, 0x20, 0x69, 0x72, 0x71
+.data1 	0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x61, 0x74, 0x61, 0x70, 0x63, 0x69, 0x3a, 0x20
+.data1 	0x63, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74
+.data1 	0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20
+.data1 	0x49, 0x52, 0x51, 0x20, 0x6c, 0x69, 0x6e, 0x65
+.data1 	0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x61, 0x74, 0x61, 0x70, 0x63, 0x69, 0x3a, 0x20
+.data1 	0x63, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74
+.data1 	0x20, 0x73, 0x65, 0x74, 0x20, 0x49, 0x52, 0x51
+.data1 	0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x20
+.data1 	0x25, 0x64, 0x0a, 0x00, 0x61, 0x74, 0x61, 0x70
+.data1 	0x63, 0x69, 0x20, 0x73, 0x6b, 0x69, 0x70, 0x70
+.data1 	0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x6e, 0x74
+.data1 	0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x28
+.data1 	0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x25
+.data1 	0x64, 0x29, 0x0a, 0x00, 0x66, 0x6f, 0x75, 0x6e
+.data1 	0x64, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72
+.data1 	0x74, 0x65, 0x64, 0x20, 0x52, 0x41, 0x49, 0x44
+.data1 	0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c
+.data1 	0x6c, 0x65, 0x72, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x61, 0x74, 0x61, 0x70, 0x63, 0x69, 0x20, 0x73
+.data1 	0x6b, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20
+.data1 	0x75, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72
+.data1 	0x74, 0x65, 0x64, 0x20, 0x52, 0x41, 0x49, 0x44
+.data1 	0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c
+.data1 	0x6c, 0x65, 0x72, 0x20, 0x30, 0x78, 0x25, 0x30
+.data1 	0x34, 0x78, 0x20, 0x2f, 0x20, 0x30, 0x78, 0x25
+.data1 	0x30, 0x34, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x63, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74
+.data1 	0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20
+.data1 	0x49, 0x52, 0x51, 0x20, 0x6c, 0x69, 0x6e, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x73, 0x65, 0x74
+.data1 	0x20, 0x49, 0x52, 0x51, 0x20, 0x70, 0x6f, 0x6c
+.data1 	0x69, 0x63, 0x79, 0x00, 0x43, 0x61, 0x6c, 0x6c
+.data1 	0x20, 0x74, 0x6f, 0x20, 0x73, 0x79, 0x73, 0x5f
+.data1 	0x69, 0x6e, 0x73, 0x77, 0x28, 0x29, 0x20, 0x66
+.data1 	0x61, 0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x6e, 0x6f, 0x20, 0x44, 0x4d, 0x41, 0x20, 0x73
+.data1 	0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x0a, 0x00
+.data1 	0x69, 0x64, 0x5f, 0x64, 0x6d, 0x61, 0x20, 0x25
+.data1 	0x64, 0x2c, 0x20, 0x64, 0x6d, 0x61, 0x5f, 0x62
+.data1 	0x61, 0x73, 0x65, 0x20, 0x30, 0x78, 0x25, 0x78
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x30, 0x00, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x55, 0x6c, 0x74, 0x72, 0x61, 0x20, 0x44, 0x4d
+.data1 	0x41, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x73
+.data1 	0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x3a
+.data1 	0x25, 0x73, 0x25, 0x73, 0x25, 0x73, 0x25, 0x73
+.data1 	0x25, 0x73, 0x25, 0x73, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x20, 0x35, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x20, 0x34, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x20, 0x33, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x20, 0x32, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x20, 0x31, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x00, 0x00
+.data1 	0x25, 0x73, 0x3a, 0x20, 0x55, 0x6c, 0x74, 0x72
+.data1 	0x61, 0x20, 0x44, 0x4d, 0x41, 0x20, 0x6d, 0x6f
+.data1 	0x64, 0x65, 0x73, 0x20, 0x73, 0x75, 0x70, 0x70
+.data1 	0x6f, 0x72, 0x74, 0x65, 0x64, 0x3a, 0x25, 0x73
+.data1 	0x25, 0x73, 0x25, 0x73, 0x25, 0x73, 0x25, 0x73
+.data1 	0x25, 0x73, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x30, 0x00, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x6d, 0x75, 0x6c, 0x74, 0x69, 0x77, 0x6f, 0x72
+.data1 	0x64, 0x20, 0x44, 0x4d, 0x41, 0x20, 0x6d, 0x6f
+.data1 	0x64, 0x65, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63
+.data1 	0x74, 0x65, 0x64, 0x3a, 0x25, 0x73, 0x25, 0x73
+.data1 	0x25, 0x73, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x30, 0x00, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x6d, 0x75, 0x6c, 0x74, 0x69, 0x77, 0x6f, 0x72
+.data1 	0x64, 0x20, 0x44, 0x4d, 0x41, 0x20, 0x6d, 0x6f
+.data1 	0x64, 0x65, 0x73, 0x20, 0x73, 0x75, 0x70, 0x70
+.data1 	0x6f, 0x72, 0x74, 0x65, 0x64, 0x3a, 0x25, 0x73
+.data1 	0x25, 0x73, 0x25, 0x73, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x75, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74
+.data1 	0x6f, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x44
+.data1 	0x4d, 0x41, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75
+.data1 	0x73, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74
+.data1 	0x65, 0x72, 0x00, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6e, 0x20, 0x41
+.data1 	0x54, 0x41, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63
+.data1 	0x65, 0x3f, 0x0a, 0x00, 0x43, 0x61, 0x6c, 0x6c
+.data1 	0x20, 0x74, 0x6f, 0x20, 0x73, 0x79, 0x73, 0x5f
+.data1 	0x69, 0x6e, 0x73, 0x77, 0x28, 0x29, 0x20, 0x66
+.data1 	0x61, 0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74
+.data1 	0x20, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20
+.data1 	0x62, 0x61, 0x63, 0x6b, 0x20, 0x64, 0x65, 0x76
+.data1 	0x69, 0x63, 0x65, 0x73, 0x00, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74
+.data1 	0x20, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20
+.data1 	0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x00
+.data1 	0x43, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x6f, 0x20
+.data1 	0x73, 0x79, 0x73, 0x5f, 0x6f, 0x75, 0x74, 0x73
+.data1 	0x77, 0x28, 0x29, 0x20, 0x66, 0x61, 0x69, 0x6c
+.data1 	0x65, 0x64, 0x00, 0x00, 0x43, 0x61, 0x6c, 0x6c
+.data1 	0x20, 0x74, 0x6f, 0x20, 0x73, 0x79, 0x73, 0x5f
+.data1 	0x69, 0x6e, 0x73, 0x77, 0x28, 0x29, 0x20, 0x66
+.data1 	0x61, 0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x43, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x6f, 0x20
+.data1 	0x73, 0x79, 0x73, 0x5f, 0x69, 0x6e, 0x73, 0x77
+.data1 	0x28, 0x29, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x77, 0x5f, 0x74, 0x72
+.data1 	0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x3a, 0x20
+.data1 	0x73, 0x79, 0x73, 0x5f, 0x76, 0x69, 0x72, 0x63
+.data1 	0x6f, 0x70, 0x79, 0x20, 0x66, 0x61, 0x69, 0x6c
+.data1 	0x65, 0x64, 0x00, 0x00, 0x44, 0x4d, 0x41, 0x20
+.data1 	0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x74
+.data1 	0x6f, 0x6f, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x44, 0x4d, 0x41, 0x20
+.data1 	0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x74
+.data1 	0x6f, 0x6f, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c
+.data1 	0x00, 0x00, 0x00, 0x00, 0x61, 0x74, 0x5f, 0x77
+.data1 	0x69, 0x6e, 0x69, 0x3a, 0x20, 0x44, 0x4d, 0x41
+.data1 	0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x0a, 0x00
+.data1 	0x44, 0x4d, 0x41, 0x20, 0x64, 0x69, 0x64, 0x20
+.data1 	0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70
+.data1 	0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x77, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66
+.data1 	0x65, 0x72, 0x3a, 0x20, 0x73, 0x79, 0x73, 0x5f
+.data1 	0x69, 0x6e, 0x62, 0x20, 0x66, 0x61, 0x69, 0x6c
+.data1 	0x65, 0x64, 0x00, 0x00, 0x61, 0x74, 0x5f, 0x77
+.data1 	0x69, 0x6e, 0x69, 0x00, 0x63, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x67, 0x65, 0x74
+.data1 	0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x00
+.data1 	0x43, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74
+.data1 	0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x72
+.data1 	0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x73
+.data1 	0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x73, 0x79
+.data1 	0x73, 0x5f, 0x76, 0x6f, 0x75, 0x74, 0x62, 0x28
+.data1 	0x29, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x63, 0x6f, 0x6d, 0x5f, 0x6f, 0x75, 0x74, 0x3a
+.data1 	0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x20, 0x6e
+.data1 	0x6f, 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x79
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x77, 0x72, 0x69
+.data1 	0x74, 0x65, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73
+.data1 	0x74, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x73
+.data1 	0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x64, 0x72
+.data1 	0x69, 0x76, 0x65, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c
+.data1 	0x65, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72
+.data1 	0x65, 0x61, 0x64, 0x79, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74
+.data1 	0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x72
+.data1 	0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x73
+.data1 	0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x73, 0x79
+.data1 	0x73, 0x5f, 0x76, 0x6f, 0x75, 0x74, 0x62, 0x28
+.data1 	0x29, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x63, 0x6f, 0x6d, 0x5f, 0x6f, 0x75, 0x74, 0x3a
+.data1 	0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x20, 0x6e
+.data1 	0x6f, 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x79
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x77, 0x72, 0x69
+.data1 	0x74, 0x65, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73
+.data1 	0x74, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x73
+.data1 	0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x64, 0x72
+.data1 	0x69, 0x76, 0x65, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c
+.data1 	0x65, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72
+.data1 	0x65, 0x61, 0x64, 0x79, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x73, 0x65, 0x74, 0x75, 0x70, 0x5f, 0x64, 0x6d
+.data1 	0x61, 0x3a, 0x20, 0x73, 0x79, 0x73, 0x5f, 0x6f
+.data1 	0x75, 0x74, 0x62, 0x20, 0x66, 0x61, 0x69, 0x6c
+.data1 	0x65, 0x64, 0x00, 0x00, 0x61, 0x74, 0x5f, 0x77
+.data1 	0x69, 0x6e, 0x69, 0x00, 0x73, 0x65, 0x74, 0x75
+.data1 	0x70, 0x5f, 0x64, 0x6d, 0x61, 0x3a, 0x20, 0x73
+.data1 	0x79, 0x73, 0x5f, 0x6f, 0x75, 0x74, 0x62, 0x20
+.data1 	0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x00, 0x00
+.data1 	0x61, 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x69, 0x00
+.data1 	0x73, 0x65, 0x74, 0x75, 0x70, 0x5f, 0x64, 0x6d
+.data1 	0x61, 0x3a, 0x20, 0x73, 0x79, 0x73, 0x5f, 0x6f
+.data1 	0x75, 0x74, 0x6c, 0x20, 0x66, 0x61, 0x69, 0x6c
+.data1 	0x65, 0x64, 0x00, 0x00, 0x61, 0x74, 0x5f, 0x77
+.data1 	0x69, 0x6e, 0x69, 0x00, 0x70, 0x72, 0x64, 0x74
+.data1 	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6c, 0x69
+.data1 	0x67, 0x6e, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x61, 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x69, 0x00
+.data1 	0x42, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x73, 0x74
+.data1 	0x65, 0x72, 0x20, 0x49, 0x44, 0x45, 0x20, 0x61
+.data1 	0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00
+.data1 	0x61, 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x69, 0x00
+.data1 	0x73, 0x65, 0x74, 0x75, 0x70, 0x5f, 0x64, 0x6d
+.data1 	0x61, 0x3a, 0x20, 0x73, 0x79, 0x73, 0x5f, 0x69
+.data1 	0x6e, 0x62, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x61, 0x74, 0x5f, 0x77
+.data1 	0x69, 0x6e, 0x69, 0x00, 0x73, 0x65, 0x74, 0x75
+.data1 	0x70, 0x5f, 0x64, 0x6d, 0x61, 0x3a, 0x20, 0x73
+.data1 	0x79, 0x73, 0x5f, 0x6f, 0x75, 0x74, 0x62, 0x20
+.data1 	0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x00, 0x00
+.data1 	0x61, 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x69, 0x00
+.data1 	0x73, 0x69, 0x7a, 0x65, 0x20, 0x74, 0x6f, 0x20
+.data1 	0x6c, 0x61, 0x72, 0x67, 0x65, 0x20, 0x66, 0x6f
+.data1 	0x72, 0x20, 0x70, 0x72, 0x64, 0x74, 0x00, 0x00
+.data1 	0x61, 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x69, 0x00
+.data1 	0x62, 0x61, 0x64, 0x20, 0x73, 0x69, 0x7a, 0x65
+.data1 	0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65
+.data1 	0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x65
+.data1 	0x74, 0x75, 0x70, 0x5f, 0x64, 0x6d, 0x61, 0x00
+.data1 	0x61, 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x69, 0x00
+.data1 	0x62, 0x61, 0x64, 0x20, 0x73, 0x69, 0x7a, 0x65
+.data1 	0x20, 0x69, 0x6e, 0x20, 0x73, 0x65, 0x74, 0x75
+.data1 	0x70, 0x5f, 0x64, 0x6d, 0x61, 0x00, 0x00, 0x00
+.data1 	0x61, 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x69, 0x00
+.data1 	0x62, 0x61, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66
+.data1 	0x65, 0x72, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e
+.data1 	0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20
+.data1 	0x73, 0x65, 0x74, 0x75, 0x70, 0x5f, 0x64, 0x6d
+.data1 	0x61, 0x00, 0x00, 0x00, 0x61, 0x74, 0x5f, 0x77
+.data1 	0x69, 0x6e, 0x69, 0x00, 0x73, 0x65, 0x74, 0x75
+.data1 	0x70, 0x5f, 0x64, 0x6d, 0x61, 0x3a, 0x20, 0x73
+.data1 	0x79, 0x73, 0x5f, 0x76, 0x69, 0x72, 0x63, 0x6f
+.data1 	0x70, 0x79, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x62, 0x61, 0x64, 0x20
+.data1 	0x70, 0x72, 0x64, 0x74, 0x20, 0x69, 0x6e, 0x64
+.data1 	0x65, 0x78, 0x00, 0x00, 0x61, 0x74, 0x5f, 0x77
+.data1 	0x69, 0x6e, 0x69, 0x00, 0x73, 0x65, 0x74, 0x75
+.data1 	0x70, 0x5f, 0x64, 0x6d, 0x61, 0x3a, 0x20, 0x75
+.data1 	0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x66, 0x66
+.data1 	0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f
+.data1 	0x74, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x65
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x63, 0x61, 0x6e, 0x27
+.data1 	0x74, 0x20, 0x6d, 0x61, 0x70, 0x20, 0x75, 0x73
+.data1 	0x65, 0x72, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65
+.data1 	0x72, 0x00, 0x00, 0x00, 0x61, 0x74, 0x5f, 0x77
+.data1 	0x69, 0x6e, 0x69, 0x00, 0x62, 0x61, 0x64, 0x20
+.data1 	0x73, 0x69, 0x7a, 0x65, 0x20, 0x69, 0x6e, 0x20
+.data1 	0x69, 0x6f, 0x76, 0x00, 0x61, 0x74, 0x5f, 0x77
+.data1 	0x69, 0x6e, 0x69, 0x00, 0x96, 0x23, 0x00, 0x00
+.data1 	0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe2, 0x23, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
+.data1 	0x7d, 0x23, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00
+.data1 	0x7d, 0x23, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00
+.data1 	0x7d, 0x23, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00
+.data1 	0x7d, 0x23, 0x00, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20
+.data1 	0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61
+.data1 	0x6e, 0x64, 0x20, 0x30, 0x78, 0x25, 0x30, 0x32
+.data1 	0x78, 0x0a, 0x00, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x64, 0x72
+.data1 	0x69, 0x76, 0x65, 0x20, 0x62, 0x75, 0x73, 0x79
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x73, 0x74, 0x72
+.data1 	0x6f, 0x62, 0x65, 0x20, 0x72, 0x65, 0x73, 0x65
+.data1 	0x74, 0x20, 0x62, 0x69, 0x74, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74
+.data1 	0x20, 0x73, 0x74, 0x72, 0x6f, 0x62, 0x65, 0x20
+.data1 	0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x62, 0x69
+.data1 	0x74, 0x00, 0x00, 0x00, 0x41, 0x54, 0x5f, 0x57
+.data1 	0x49, 0x4e, 0x49, 0x20, 0x67, 0x6f, 0x74, 0x20
+.data1 	0x75, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74
+.data1 	0x65, 0x64, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61
+.data1 	0x67, 0x65, 0x20, 0x25, 0x64, 0x20, 0x66, 0x72
+.data1 	0x6f, 0x6d, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x73, 0x79, 0x73, 0x5f, 0x69, 0x6e, 0x62, 0x20
+.data1 	0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x00, 0x00
+.data1 	0x61, 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x69, 0x00
+.data1 	0x77, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x5f, 0x77
+.data1 	0x61, 0x69, 0x74, 0x3a, 0x20, 0x72, 0x65, 0x63
+.data1 	0x65, 0x69, 0x76, 0x65, 0x20, 0x66, 0x72, 0x6f
+.data1 	0x6d, 0x20, 0x41, 0x4e, 0x59, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x64
+.data1 	0x29, 0x0a, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x72, 0x65, 0x61
+.data1 	0x64, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74
+.data1 	0x65, 0x72, 0x00, 0x00, 0x41, 0x54, 0x5f, 0x57
+.data1 	0x49, 0x4e, 0x49, 0x3a, 0x20, 0x77, 0x61, 0x72
+.data1 	0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x67, 0x65
+.data1 	0x74, 0x5f, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65
+.data1 	0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x3a
+.data1 	0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74
+.data1 	0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x72, 0x65
+.data1 	0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, 0x00
+.data1 	0x41, 0x54, 0x5f, 0x57, 0x49, 0x4e, 0x49, 0x3a
+.data1 	0x20, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67
+.data1 	0x2c, 0x20, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x70
+.data1 	0x74, 0x69, 0x6d, 0x65, 0x20, 0x66, 0x61, 0x69
+.data1 	0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x72, 0x65, 0x61
+.data1 	0x64, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74
+.data1 	0x65, 0x72, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x20, 0x25, 0x30, 0x32, 0x78, 0x00, 0x00, 0x00
+.data1 	0x73, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x61
+.data1 	0x74, 0x61, 0x3a, 0x00, 0x57, 0x41, 0x52, 0x4e
+.data1 	0x49, 0x4e, 0x47, 0x3a, 0x20, 0x73, 0x65, 0x6e
+.data1 	0x73, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x69
+.data1 	0x6e, 0x67, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x57, 0x41, 0x52, 0x4e
+.data1 	0x49, 0x4e, 0x47, 0x3a, 0x20, 0x72, 0x65, 0x71
+.data1 	0x75, 0x65, 0x73, 0x74, 0x20, 0x72, 0x65, 0x73
+.data1 	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20
+.data1 	0x73, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x63, 0x6f
+.data1 	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x72, 0x65, 0x74, 0x72, 0x79, 0x20, 0x28, 0x25
+.data1 	0x64, 0x29, 0x0a, 0x00, 0x67, 0x69, 0x76, 0x69
+.data1 	0x6e, 0x67, 0x20, 0x75, 0x70, 0x20, 0x28, 0x25
+.data1 	0x64, 0x29, 0x0a, 0x00, 0x43, 0x61, 0x6c, 0x6c
+.data1 	0x20, 0x74, 0x6f, 0x20, 0x73, 0x79, 0x73, 0x5f
+.data1 	0x69, 0x6e, 0x73, 0x77, 0x28, 0x29, 0x20, 0x66
+.data1 	0x61, 0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x43, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x6f, 0x20
+.data1 	0x73, 0x79, 0x73, 0x5f, 0x69, 0x6e, 0x73, 0x77
+.data1 	0x28, 0x29, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x43, 0x61, 0x6c, 0x6c
+.data1 	0x20, 0x74, 0x6f, 0x20, 0x73, 0x79, 0x73, 0x5f
+.data1 	0x69, 0x6e, 0x73, 0x77, 0x28, 0x29, 0x20, 0x66
+.data1 	0x61, 0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x3d, 0x25
+.data1 	0x75, 0x2c, 0x20, 0x6e, 0x62, 0x79, 0x74, 0x65
+.data1 	0x73, 0x3d, 0x25, 0x75, 0x2c, 0x20, 0x63, 0x6f
+.data1 	0x75, 0x6e, 0x74, 0x3d, 0x25, 0x75, 0x0a, 0x00
+.data1 	0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3d, 0x25, 0x6c
+.data1 	0x75, 0x2c, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72
+.data1 	0x65, 0x3d, 0x25, 0x75, 0x2c, 0x20, 0x6e, 0x62
+.data1 	0x79, 0x74, 0x65, 0x73, 0x3d, 0x25, 0x75, 0x2c
+.data1 	0x20, 0x6e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73
+.data1 	0x3d, 0x25, 0x75, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x20, 0x25, 0x30, 0x32
+.data1 	0x78, 0x00, 0x00, 0x00, 0x73, 0x65, 0x6e, 0x74
+.data1 	0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64
+.data1 	0x3a, 0x00, 0x00, 0x00, 0x73, 0x79, 0x73, 0x5f
+.data1 	0x6f, 0x75, 0x74, 0x73, 0x77, 0x28, 0x29, 0x20
+.data1 	0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x00, 0x00
+.data1 	0x25, 0x73, 0x3a, 0x20, 0x74, 0x69, 0x6d, 0x65
+.data1 	0x6f, 0x75, 0x74, 0x20, 0x28, 0x42, 0x53, 0x59
+.data1 	0x7c, 0x44, 0x52, 0x51, 0x20, 0x2d, 0x3e, 0x20
+.data1 	0x44, 0x52, 0x51, 0x29, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74
+.data1 	0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x72
+.data1 	0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x73
+.data1 	0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x73, 0x79
+.data1 	0x73, 0x5f, 0x76, 0x6f, 0x75, 0x74, 0x62, 0x28
+.data1 	0x29, 0x00, 0x00, 0x00, 0x63, 0x6d, 0x64, 0x3a
+.data1 	0x20, 0x25, 0x78, 0x20, 0x20, 0x00, 0x00, 0x00
+.data1 	0x25, 0x73, 0x3a, 0x20, 0x61, 0x74, 0x61, 0x70
+.data1 	0x69, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x70, 0x61
+.data1 	0x63, 0x6b, 0x65, 0x74, 0x3a, 0x20, 0x64, 0x72
+.data1 	0x69, 0x76, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20
+.data1 	0x72, 0x65, 0x61, 0x64, 0x79, 0x0a, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74
+.data1 	0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20
+.data1 	0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x20
+.data1 	0x73, 0x6c, 0x61, 0x76, 0x65, 0x20, 0x64, 0x72
+.data1 	0x69, 0x76, 0x65, 0x00, 0x63, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x72, 0x65, 0x2d
+.data1 	0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x64
+.data1 	0x72, 0x69, 0x76, 0x65, 0x20, 0x25, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x61, 0x63, 0x6b
+.data1 	0x20, 0x69, 0x72, 0x71, 0x20, 0x6f, 0x6e, 0x20
+.data1 	0x64, 0x72, 0x69, 0x76, 0x65, 0x20, 0x25, 0x64
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
+.data1 	0x43, 0x48, 0x45, 0x43, 0x4b, 0x00, 0x00, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0x43, 0x4f, 0x52, 0x52
+.data1 	0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
+.data1 	0x44, 0x52, 0x51, 0x00, 0x20, 0x00, 0x00, 0x00
+.data1 	0x53, 0x52, 0x56, 0x43, 0x44, 0x53, 0x43, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0x44, 0x4d, 0x41, 0x44
+.data1 	0x46, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
+.data1 	0x44, 0x52, 0x44, 0x59, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0x42, 0x53, 0x59, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0x44, 0x4d, 0x00, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0x54, 0x4b, 0x00, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0x41, 0x43, 0x00, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0x49, 0x44, 0x00, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0x45, 0x43, 0x43, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00
+.data1 	0x51, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x35, 0x35, 0x00, 0x00
+.data1 	0x51, 0x35, 0x00, 0x00, 0x51, 0x35, 0x00, 0x00
+.data1 	0x2c, 0x35, 0x00, 0x00, 0x51, 0x35, 0x00, 0x00
+.data1 	0x51, 0x35, 0x00, 0x00, 0x51, 0x35, 0x00, 0x00
+.data1 	0x51, 0x35, 0x00, 0x00, 0x47, 0x35, 0x00, 0x00
+.data1 	0x3e, 0x35, 0x00, 0x00, 0x4c, 0x35, 0x00, 0x00
+.data1 	0x41, 0x43, 0x44, 0x3a, 0x20, 0x50, 0x68, 0x61
+.data1 	0x73, 0x65, 0x20, 0x55, 0x6e, 0x6b, 0x6e, 0x6f
+.data1 	0x77, 0x6e, 0x0a, 0x00, 0x41, 0x43, 0x44, 0x3a
+.data1 	0x20, 0x50, 0x68, 0x61, 0x73, 0x65, 0x20, 0x44
+.data1 	0x61, 0x74, 0x61, 0x20, 0x49, 0x6e, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x41, 0x43, 0x44, 0x3a
+.data1 	0x20, 0x50, 0x68, 0x61, 0x73, 0x65, 0x20, 0x44
+.data1 	0x61, 0x74, 0x61, 0x20, 0x4f, 0x75, 0x74, 0x20
+.data1 	0x25, 0x64, 0x0a, 0x00, 0x41, 0x43, 0x44, 0x3a
+.data1 	0x20, 0x50, 0x68, 0x61, 0x73, 0x65, 0x20, 0x43
+.data1 	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x4f
+.data1 	0x75, 0x74, 0x0a, 0x00, 0x41, 0x43, 0x44, 0x3a
+.data1 	0x20, 0x50, 0x68, 0x61, 0x73, 0x65, 0x20, 0x43
+.data1 	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x41
+.data1 	0x62, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x0a, 0x00
+.data1 	0x41, 0x43, 0x44, 0x3a, 0x20, 0x50, 0x68, 0x61
+.data1 	0x73, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x61
+.data1 	0x6e, 0x64, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6c
+.data1 	0x65, 0x74, 0x65, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x61, 0x74, 0x61, 0x70, 0x69, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x3a, 0x20, 0x20, 0x53, 0x3d, 0x25
+.data1 	0x78, 0x3d, 0x25, 0x73, 0x20, 0x45, 0x3d, 0x25
+.data1 	0x30, 0x32, 0x78, 0x3d, 0x25, 0x73, 0x20, 0x4c
+.data1 	0x3d, 0x25, 0x30, 0x34, 0x78, 0x20, 0x49, 0x3d
+.data1 	0x25, 0x30, 0x32, 0x78, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x41, 0x54, 0x41, 0x50, 0x49, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x20, 0x73, 0x79, 0x73
+.data1 	0x5f, 0x76, 0x69, 0x6e, 0x62, 0x28, 0x29, 0x00
+.data1 	0x7c, 0x36, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00
+.data1 	0x00, 0x04, 0x00, 0x00, 0xef, 0x35, 0x00, 0x00
+.data1 	0x03, 0x04, 0x00, 0x00, 0x11, 0x36, 0x00, 0x00
+.data1 	0x04, 0x04, 0x00, 0x00, 0x11, 0x36, 0x00, 0x00
+.data1 	0x05, 0x04, 0x00, 0x00, 0xde, 0x35, 0x00, 0x00
+.data1 	0x06, 0x04, 0x00, 0x00, 0xbc, 0x35, 0x00, 0x00
+.data1 	0x07, 0x04, 0x00, 0x00, 0xcd, 0x35, 0x00, 0x00
+.data1 	0x08, 0x04, 0x00, 0x00, 0x24, 0x36, 0x00, 0x00
+.data1 	0x09, 0x04, 0x00, 0x00, 0x24, 0x36, 0x00, 0x00
+.data1 	0x0c, 0x04, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00
+.data1 	0x01, 0x10, 0x00, 0x00, 0x5f, 0x36, 0x00, 0x00
+.data1 	0x02, 0x10, 0x00, 0x00, 0x50, 0x36, 0x00, 0x00
+.data1 	0x03, 0x10, 0x00, 0x00, 0x37, 0x36, 0x00, 0x00
+.data1 	0x04, 0x10, 0x00, 0x00, 0x50, 0x36, 0x00, 0x00
+.data1 	0x06, 0x10, 0x00, 0x00, 0x6e, 0x36, 0x00, 0x00
+.data1 	0x62, 0x61, 0x64, 0x20, 0x49, 0x2f, 0x4f, 0x20
+.data1 	0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x62
+.data1 	0x79, 0x00, 0x00, 0x00, 0xb5, 0x38, 0x00, 0x00
+.data1 	0x05, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0xae, 0x38, 0x00, 0x00, 0xa3, 0x38, 0x00, 0x00
+.data1 	0xaa, 0x38, 0x00, 0x00, 0xc0, 0x3a, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x6f, 0x3a, 0x00, 0x00, 0x75, 0x3a, 0x00, 0x00
+.data1 	0x84, 0x3a, 0x00, 0x00, 0x43, 0x40, 0x00, 0x00
+.data1 	0x05, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00
+.data1 	0x83, 0x3f, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00
+.data1 	0xb3, 0x3f, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00
+.data1 	0x8f, 0x3f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00
+.data1 	0x9b, 0x3f, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
+.data1 	0xa7, 0x3f, 0x00, 0x00, 0x6f, 0x6e, 0x00, 0x00
+.data1 	0x6f, 0x66, 0x66, 0x00, 0x57, 0x41, 0x52, 0x4e
+.data1 	0x49, 0x4e, 0x47, 0x3a, 0x20, 0x67, 0x65, 0x74
+.data1 	0x5f, 0x6d, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x72
+.data1 	0x61, 0x6d, 0x28, 0x29, 0x20, 0x66, 0x61, 0x69
+.data1 	0x6c, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x65
+.data1 	0x6e, 0x76, 0x5f, 0x70, 0x61, 0x72, 0x73, 0x65
+.data1 	0x28, 0x29, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00
+.data1 	0x8a, 0x43, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00
+.data1 	0x25, 0x00, 0x00, 0x00, 0xb8, 0x42, 0x00, 0x00
+.data1 	0x58, 0x00, 0x00, 0x00, 0x41, 0x42, 0x00, 0x00
+.data1 	0x63, 0x00, 0x00, 0x00, 0x9c, 0x42, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0x0d, 0x42, 0x00, 0x00
+.data1 	0x6f, 0x00, 0x00, 0x00, 0x38, 0x42, 0x00, 0x00
+.data1 	0x70, 0x00, 0x00, 0x00, 0x41, 0x42, 0x00, 0x00
+.data1 	0x73, 0x00, 0x00, 0x00, 0xca, 0x42, 0x00, 0x00
+.data1 	0x75, 0x00, 0x00, 0x00, 0x4f, 0x42, 0x00, 0x00
+.data1 	0x78, 0x00, 0x00, 0x00, 0x48, 0x42, 0x00, 0x00
+.data1 	0x53, 0x59, 0x53, 0x5f, 0x47, 0x45, 0x54, 0x49
+.data1 	0x4e, 0x46, 0x4f, 0x3a, 0x20, 0x25, 0x64, 0x20
+.data1 	0x28, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x25, 0x75
+.data1 	0x29, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0x64, 0x20
+.data1 	0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d
+.data1 	0x65, 0x6e, 0x74, 0x20, 0x73, 0x65, 0x74, 0x74
+.data1 	0x69, 0x6e, 0x67, 0x3a, 0x20, 0x27, 0x25, 0x73
+.data1 	0x20, 0x3d, 0x20, 0x25, 0x73, 0x27, 0x0a, 0x00
+.data1 	0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x3a
+.data1 	0x20, 0x67, 0x65, 0x74, 0x5f, 0x6d, 0x6f, 0x6e
+.data1 	0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x28, 0x29
+.data1 	0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20
+.data1 	0x69, 0x6e, 0x20, 0x65, 0x6e, 0x76, 0x5f, 0x70
+.data1 	0x61, 0x6e, 0x69, 0x63, 0x28, 0x29, 0x3a, 0x20
+.data1 	0x25, 0x64, 0x0a, 0x00, 0x50, 0x61, 0x6e, 0x69
+.data1 	0x63, 0x20, 0x69, 0x6e, 0x20, 0x25, 0x73, 0x3a
+.data1 	0x20, 0x25, 0x73, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x50, 0x61, 0x6e, 0x69, 0x63, 0x20, 0x69, 0x6e
+.data1 	0x20, 0x25, 0x73, 0x3a, 0x20, 0x25, 0x73, 0x3a
+.data1 	0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x70, 0x63, 0x69, 0x5f, 0x61, 0x74, 0x74, 0x72
+.data1 	0x5f, 0x72, 0x33, 0x32, 0x3a, 0x20, 0x67, 0x6f
+.data1 	0x74, 0x20, 0x62, 0x61, 0x64, 0x20, 0x72, 0x65
+.data1 	0x70, 0x6c, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d
+.data1 	0x20, 0x50, 0x43, 0x49, 0x00, 0x00, 0x00, 0x00
+.data1 	0x70, 0x63, 0x69, 0x00, 0x70, 0x63, 0x69, 0x5f
+.data1 	0x61, 0x74, 0x74, 0x72, 0x5f, 0x72, 0x33, 0x32
+.data1 	0x3a, 0x20, 0x63, 0x61, 0x6e, 0x27, 0x74, 0x20
+.data1 	0x74, 0x61, 0x6c, 0x6b, 0x20, 0x74, 0x6f, 0x20
+.data1 	0x50, 0x43, 0x49, 0x00, 0x70, 0x63, 0x69, 0x00
+.data1 	0x70, 0x63, 0x69, 0x5f, 0x61, 0x74, 0x74, 0x72
+.data1 	0x5f, 0x72, 0x38, 0x3a, 0x20, 0x67, 0x6f, 0x74
+.data1 	0x20, 0x62, 0x61, 0x64, 0x20, 0x72, 0x65, 0x70
+.data1 	0x6c, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20
+.data1 	0x50, 0x43, 0x49, 0x00, 0x70, 0x63, 0x69, 0x00
+.data1 	0x70, 0x63, 0x69, 0x5f, 0x61, 0x74, 0x74, 0x72
+.data1 	0x5f, 0x72, 0x38, 0x3a, 0x20, 0x63, 0x61, 0x6e
+.data1 	0x27, 0x74, 0x20, 0x74, 0x61, 0x6c, 0x6b, 0x20
+.data1 	0x74, 0x6f, 0x20, 0x50, 0x43, 0x49, 0x00, 0x00
+.data1 	0x70, 0x63, 0x69, 0x00, 0x70, 0x63, 0x69, 0x5f
+.data1 	0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x64, 0x65
+.data1 	0x76, 0x3a, 0x20, 0x67, 0x6f, 0x74, 0x20, 0x62
+.data1 	0x61, 0x64, 0x20, 0x72, 0x65, 0x70, 0x6c, 0x79
+.data1 	0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x50, 0x43
+.data1 	0x49, 0x00, 0x00, 0x00, 0x70, 0x63, 0x69, 0x00
+.data1 	0x70, 0x63, 0x69, 0x5f, 0x66, 0x69, 0x72, 0x73
+.data1 	0x74, 0x5f, 0x64, 0x65, 0x76, 0x3a, 0x20, 0x63
+.data1 	0x61, 0x6e, 0x27, 0x74, 0x20, 0x74, 0x61, 0x6c
+.data1 	0x6b, 0x20, 0x74, 0x6f, 0x20, 0x50, 0x43, 0x49
+.data1 	0x00, 0x00, 0x00, 0x00, 0x70, 0x63, 0x69, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x70, 0x63, 0x69, 0x5f
+.data1 	0x69, 0x6e, 0x69, 0x74, 0x31, 0x3a, 0x20, 0x67
+.data1 	0x6f, 0x74, 0x20, 0x62, 0x61, 0x64, 0x20, 0x72
+.data1 	0x65, 0x70, 0x6c, 0x79, 0x20, 0x66, 0x72, 0x6f
+.data1 	0x6d, 0x20, 0x50, 0x43, 0x49, 0x00, 0x00, 0x00
+.data1 	0x70, 0x63, 0x69, 0x00, 0x70, 0x63, 0x69, 0x5f
+.data1 	0x69, 0x6e, 0x69, 0x74, 0x31, 0x3a, 0x20, 0x63
+.data1 	0x61, 0x6e, 0x27, 0x74, 0x20, 0x74, 0x61, 0x6c
+.data1 	0x6b, 0x20, 0x74, 0x6f, 0x20, 0x50, 0x43, 0x49
+.data1 	0x00, 0x00, 0x00, 0x00, 0x70, 0x63, 0x69, 0x00
+.data1 	0x70, 0x63, 0x69, 0x5f, 0x69, 0x6e, 0x69, 0x74
+.data1 	0x31, 0x3a, 0x20, 0x5f, 0x70, 0x6d, 0x5f, 0x66
+.data1 	0x69, 0x6e, 0x64, 0x70, 0x72, 0x6f, 0x63, 0x20
+.data1 	0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x66
+.data1 	0x6f, 0x72, 0x20, 0x27, 0x70, 0x63, 0x69, 0x27
+.data1 	0x00, 0x00, 0x00, 0x00, 0x70, 0x63, 0x69, 0x00
+.data1 	0x70, 0x63, 0x69, 0x00, 0x70, 0x63, 0x69, 0x5f
+.data1 	0x6e, 0x65, 0x78, 0x74, 0x5f, 0x64, 0x65, 0x76
+.data1 	0x3a, 0x20, 0x67, 0x6f, 0x74, 0x20, 0x62, 0x61
+.data1 	0x64, 0x20, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x20
+.data1 	0x66, 0x72, 0x6f, 0x6d, 0x20, 0x50, 0x43, 0x49
+.data1 	0x00, 0x00, 0x00, 0x00, 0x70, 0x63, 0x69, 0x00
+.data1 	0x70, 0x63, 0x69, 0x5f, 0x6e, 0x65, 0x78, 0x74
+.data1 	0x5f, 0x64, 0x65, 0x76, 0x3a, 0x20, 0x63, 0x61
+.data1 	0x6e, 0x27, 0x74, 0x20, 0x74, 0x61, 0x6c, 0x6b
+.data1 	0x20, 0x74, 0x6f, 0x20, 0x50, 0x43, 0x49, 0x00
+.data1 	0x70, 0x63, 0x69, 0x00, 0x10, 0xdd, 0x00, 0x00
+.data1 	0x2c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+.data1 	0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
+.data1 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+.data1 	0x06, 0x11, 0x49, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0xba, 0x11, 0x00, 0x00, 0x43, 0x08, 0x00, 0x00
+.data1 	0xe6, 0x22, 0x00, 0x00, 0xf2, 0x38, 0x00, 0x00
+.data1 	0x25, 0x09, 0x00, 0x00, 0x37, 0x15, 0x00, 0x00
+.data1 	0xdf, 0x38, 0x00, 0x00, 0xc6, 0x27, 0x00, 0x00
+.data1 	0xce, 0x38, 0x00, 0x00, 0xd3, 0x38, 0x00, 0x00
+.data1 	0xe4, 0x38, 0x00, 0x00, 0xeb, 0x38, 0x00, 0x00
+.data1 	0x78, 0x2f, 0x00, 0x00, 0xde, 0x30, 0x00, 0x00
+.data1 	0x41, 0x54, 0x2d, 0x44, 0x30, 0x00, 0x00, 0x00
+.data1 	0x6e, 0x6f, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00
+.data1 	0x3a, 0x2c, 0x3b, 0x2e, 0x00, 0x00, 0x00, 0x00
+.data1 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
+.data1 	0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46
+.data1 	0x00, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33
+.data1 	0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62
+.data1 	0x63, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x00
+.data1 	0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+.data1 	0xce, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x3c, 0x75, 0x6e, 0x6b
+.data1 	0x6e, 0x6f, 0x77, 0x6e, 0x3e, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xce, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x53, 0x53, 0x53, 0x53
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20
+.data1 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x28
+.data1 	0x28, 0x28, 0x28, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x20, 0x20, 0x20, 0x20, 0x08, 0x10, 0x10
+.data1 	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x10, 0x10, 0x10, 0x10, 0x04, 0x04, 0x04
+.data1 	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x10
+.data1 	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x41, 0x41
+.data1 	0x41, 0x41, 0x41, 0x41, 0x01, 0x01, 0x01, 0x01
+.data1 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+.data1 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+.data1 	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x42, 0x42
+.data1 	0x42, 0x42, 0x42, 0x42, 0x02, 0x02, 0x02, 0x02
+.data1 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+.data1 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+.data1 	0x10, 0x10, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x03, 0x20, 0x10, 0x20, 0x00, 0x00, 0x00
+.data1 	0xf0, 0x24, 0x00, 0x00, 0x3c, 0x07, 0x00, 0x00
+.data1 	0x84, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc0, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0xed, 0x8b, 0x04, 0x24, 0x8d, 0x54, 0x24
+.data1 	0x04, 0x8d, 0x4c, 0x84, 0x08, 0xbb, 0x28, 0x06
+.data1 	0x00, 0x00, 0x81, 0xfb, 0x3c, 0x07, 0x00, 0x00
+.data1 	0x73, 0x13, 0xf6, 0xc3, 0x03, 0x75, 0x0e, 0x81
+.data1 	0x3b, 0x53, 0x53, 0x53, 0x53, 0x75, 0x06, 0x89
+.data1 	0x1d, 0x00, 0x05, 0x00, 0x00, 0x8b, 0x1d, 0x00
+.data1 	0x05, 0x00, 0x00, 0x89, 0x0b, 0x51, 0x52, 0x50
+.data1 	0x0f, 0x01, 0xe0, 0xa8, 0x04, 0x0f, 0x94, 0x05
+.data1 	0x2c, 0x23, 0x00, 0x00, 0xe8, 0x07, 0x00, 0x00
+.data1 	0x00, 0x50, 0xe8, 0x1e, 0x1d, 0x00, 0x00, 0xf4
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x10, 0xc7, 0x45
+.data1 	0xf0, 0x04, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xf4
+.data1 	0x50, 0xe8, 0x0a, 0x1f, 0x00, 0x00, 0x59, 0xc7
+.data1 	0x45, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x00
+.data1 	0x8d, 0x45, 0xf0, 0x50, 0x6a, 0x0f, 0xe8, 0xed
+.data1 	0x1e, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0
+.data1 	0x79, 0x18, 0xff, 0x35, 0x2c, 0x06, 0x00, 0x00
+.data1 	0x68, 0x1c, 0x00, 0x00, 0x00, 0x68, 0x30, 0x00
+.data1 	0x00, 0x00, 0xe8, 0x2d, 0x1b, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00
+.data1 	0x00, 0x6a, 0x01, 0x6a, 0x00, 0x8d, 0x45, 0xfc
+.data1 	0x50, 0x6a, 0x00, 0x68, 0x04, 0x00, 0x00, 0x00
+.data1 	0x68, 0x08, 0x00, 0x00, 0x00, 0xe8, 0x56, 0x12
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x18, 0x8b, 0x55, 0xfc
+.data1 	0x89, 0x15, 0x08, 0x05, 0x00, 0x00, 0x68, 0x0c
+.data1 	0x05, 0x00, 0x00, 0xe8, 0xe4, 0x09, 0x00, 0x00
+.data1 	0x59, 0x31, 0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0x8b, 0x75, 0x08, 0x83, 0xfe, 0x28, 0x7d
+.data1 	0x39, 0xb9, 0x05, 0x00, 0x00, 0x00, 0x89, 0xf0
+.data1 	0x99, 0xf7, 0xf9, 0xa3, 0xa0, 0x12, 0x00, 0x00
+.data1 	0x69, 0x1d, 0xa0, 0x12, 0x00, 0x00, 0x6c, 0x01
+.data1 	0x00, 0x00, 0x81, 0xc3, 0x3c, 0x07, 0x00, 0x00
+.data1 	0x89, 0x1d, 0x9c, 0x12, 0x00, 0x00, 0x89, 0xf0
+.data1 	0x99, 0xf7, 0xf9, 0xc1, 0xe2, 0x04, 0x8d, 0x54
+.data1 	0x13, 0x1c, 0x89, 0x15, 0xa4, 0x12, 0x00, 0x00
+.data1 	0xeb, 0x4c, 0x81, 0xee, 0x80, 0x00, 0x00, 0x00
+.data1 	0x81, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x73, 0x3a
+.data1 	0xb9, 0x10, 0x00, 0x00, 0x00, 0x89, 0xf0, 0x99
+.data1 	0xf7, 0xf9, 0xa3, 0xa0, 0x12, 0x00, 0x00, 0x69
+.data1 	0x1d, 0xa0, 0x12, 0x00, 0x00, 0x6c, 0x01, 0x00
+.data1 	0x00, 0x81, 0xc3, 0x3c, 0x07, 0x00, 0x00, 0x89
+.data1 	0x1d, 0x9c, 0x12, 0x00, 0x00, 0x89, 0xf0, 0x99
+.data1 	0xf7, 0xf9, 0xc1, 0xe2, 0x04, 0x83, 0xc3, 0x6c
+.data1 	0x01, 0xda, 0x89, 0x15, 0xa4, 0x12, 0x00, 0x00
+.data1 	0xeb, 0x04, 0x31, 0xc0, 0xeb, 0x1e, 0x83, 0x3d
+.data1 	0xa0, 0x12, 0x00, 0x00, 0x08, 0x7d, 0x0c, 0x8b
+.data1 	0x15, 0x9c, 0x12, 0x00, 0x00, 0x83, 0x7a, 0x14
+.data1 	0x00, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x05, 0xa1
+.data1 	0xa4, 0x12, 0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0xba, 0x30, 0x00, 0x00, 0x00, 0x03
+.data1 	0x15, 0xa0, 0x12, 0x00, 0x00, 0x88, 0x15, 0x4a
+.data1 	0x05, 0x00, 0x00, 0xb8, 0x44, 0x05, 0x00, 0x00
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x81, 0xec, 0x80
+.data1 	0x00, 0x00, 0x00, 0x56, 0x57, 0x8b, 0x7d, 0x14
+.data1 	0x8b, 0x15, 0x9c, 0x12, 0x00, 0x00, 0x89, 0x55
+.data1 	0xfc, 0x8b, 0x55, 0x18, 0xc1, 0xe2, 0x03, 0x01
+.data1 	0xfa, 0x89, 0x55, 0xf4, 0x8b, 0x15, 0xa4, 0x12
+.data1 	0x00, 0x00, 0xff, 0x72, 0x0c, 0xff, 0x72, 0x08
+.data1 	0xe8, 0xfb, 0x1d, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0x45, 0xd0, 0x8b, 0x55, 0xfc, 0x8b, 0x4d, 0xfc
+.data1 	0x8b, 0x52, 0x04, 0x0f, 0xaf, 0x51, 0x08, 0x89
+.data1 	0x55, 0xcc, 0xf7, 0x45, 0x10, 0xff, 0x01, 0x00
+.data1 	0x00, 0x74, 0x0a, 0xb8, 0xea, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x20, 0x04, 0x00, 0x00, 0xc7, 0x45, 0xec
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x15, 0xac, 0x12
+.data1 	0x00, 0x00, 0x83, 0xea, 0x10, 0x89, 0x55, 0xd8
+.data1 	0x81, 0xe2, 0x00, 0xfe, 0xff, 0xff, 0x89, 0x55
+.data1 	0xd4, 0x75, 0x0b, 0x68, 0x48, 0x01, 0x00, 0x00
+.data1 	0xe8, 0x77, 0x19, 0x00, 0x00, 0x59, 0x83, 0x7d
+.data1 	0x18, 0x00, 0x0f, 0x84, 0xeb, 0x03, 0x00, 0x00
+.data1 	0x31, 0xf6, 0x89, 0x7d, 0xf8, 0x8b, 0x55, 0xf4
+.data1 	0x39, 0x55, 0xf8, 0x73, 0x22, 0x8b, 0x55, 0xf8
+.data1 	0x89, 0xf1, 0x03, 0x4a, 0x04, 0x39, 0x4d, 0xd4
+.data1 	0x73, 0x09, 0x85, 0xf6, 0x75, 0x11, 0x8b, 0x75
+.data1 	0xd4, 0xeb, 0x0c, 0x8b, 0x55, 0xf8, 0x03, 0x72
+.data1 	0x04, 0x83, 0x45, 0xf8, 0x08, 0xeb, 0xd6, 0xf7
+.data1 	0xc6, 0xff, 0x01, 0x00, 0x00, 0x74, 0x0a, 0xb8
+.data1 	0xea, 0xff, 0xff, 0xff, 0xe9, 0xac, 0x03, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xd0, 0x39, 0x55, 0x10, 0x72
+.data1 	0x07, 0x31, 0xc0, 0xe9, 0x9d, 0x03, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x10, 0x01, 0xf2, 0x39, 0x55, 0xd0
+.data1 	0x73, 0x08, 0x8b, 0x55, 0xd0, 0x2b, 0x55, 0x10
+.data1 	0x89, 0xd6, 0x8b, 0x15, 0xa4, 0x12, 0x00, 0x00
+.data1 	0x68, 0x00, 0x02, 0x00, 0x00, 0xff, 0x75, 0x10
+.data1 	0xff, 0x72, 0x04, 0xff, 0x32, 0x8d, 0x45, 0x8c
+.data1 	0x50, 0xe8, 0xca, 0x1c, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x10, 0xff, 0x70, 0x04, 0xff, 0x30, 0xe8, 0x29
+.data1 	0x1d, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45
+.data1 	0xdc, 0x83, 0x7d, 0xec, 0x00, 0x7e, 0x05, 0xbe
+.data1 	0x00, 0x02, 0x00, 0x00, 0x81, 0x7d, 0x0c, 0x08
+.data1 	0x04, 0x00, 0x00, 0x0f, 0x85, 0x86, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xe4, 0x00, 0x00, 0x00, 0x00
+.data1 	0x89, 0x7d, 0xf8, 0x39, 0x75, 0xe4, 0x0f, 0x83
+.data1 	0x73, 0x00, 0x00, 0x00, 0x8b, 0x57, 0x04, 0x89
+.data1 	0x55, 0xe0, 0x03, 0x55, 0xe4, 0x39, 0xf2, 0x76
+.data1 	0x08, 0x89, 0xf2, 0x2b, 0x55, 0xe4, 0x89, 0x55
+.data1 	0xe0, 0x8b, 0x55, 0xd4, 0x39, 0x55, 0xe0, 0x76
+.data1 	0x0b, 0x68, 0x00, 0x01, 0x00, 0x00, 0xe8, 0x89
+.data1 	0x18, 0x00, 0x00, 0x59, 0x8b, 0x55, 0xe4, 0x03
+.data1 	0x15, 0xa8, 0x12, 0x00, 0x00, 0x8b, 0x45, 0xf8
+.data1 	0xff, 0x75, 0xe0, 0x52, 0x6a, 0x01, 0x6a, 0xfe
+.data1 	0xff, 0x30, 0x6a, 0x01, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xcc, 0x19, 0x00, 0x00, 0x83, 0xc4, 0x1c, 0x89
+.data1 	0x45, 0xf0, 0x85, 0xc0, 0x74, 0x15, 0xff, 0x75
+.data1 	0xf0, 0x68, 0xe0, 0x00, 0x00, 0x00, 0x68, 0xf4
+.data1 	0x00, 0x00, 0x00, 0xe8, 0x74, 0x18, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x8b, 0x55, 0xe0, 0x01, 0x55
+.data1 	0xe4, 0x83, 0x45, 0xf8, 0x08, 0xeb, 0x84, 0x8b
+.data1 	0x55, 0xfc, 0x83, 0x7a, 0x18, 0x00, 0x0f, 0x84
+.data1 	0xf2, 0x00, 0x00, 0x00, 0xc6, 0x45, 0xbc, 0x10
+.data1 	0xc6, 0x45, 0xbd, 0x00, 0x89, 0xf2, 0xc1, 0xea
+.data1 	0x09, 0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x66
+.data1 	0x89, 0x55, 0xbe, 0xb9, 0x10, 0x00, 0x00, 0x00
+.data1 	0xa1, 0xb0, 0x12, 0x00, 0x00, 0x31, 0xd2, 0xf7
+.data1 	0xf1, 0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x66
+.data1 	0x89, 0x55, 0xc0, 0x8b, 0x15, 0xb0, 0x12, 0x00
+.data1 	0x00, 0xc1, 0xea, 0x04, 0x81, 0xe2, 0xff, 0xff
+.data1 	0x00, 0x00, 0x66, 0x89, 0x55, 0xc2, 0x8b, 0x55
+.data1 	0xdc, 0x89, 0x55, 0xc4, 0xc7, 0x45, 0xc8, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0xd8, 0x03, 0x15
+.data1 	0xa8, 0x12, 0x00, 0x00, 0x6a, 0x10, 0x52, 0x6a
+.data1 	0x01, 0x6a, 0xfe, 0x8d, 0x45, 0xbc, 0x50, 0x6a
+.data1 	0x01, 0x68, 0xce, 0x8a, 0x00, 0x00, 0xe8, 0x25
+.data1 	0x19, 0x00, 0x00, 0x83, 0xc4, 0x1c, 0x89, 0x45
+.data1 	0xf0, 0x85, 0xc0, 0x74, 0x15, 0xff, 0x75, 0xf0
+.data1 	0x68, 0xc0, 0x00, 0x00, 0x00, 0x68, 0xd4, 0x00
+.data1 	0x00, 0x00, 0xe8, 0xcd, 0x17, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xc6, 0x45, 0x94, 0x13, 0x81, 0x7d
+.data1 	0x0c, 0x08, 0x04, 0x00, 0x00, 0x75, 0x07, 0xb8
+.data1 	0x00, 0x43, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0x00
+.data1 	0x42, 0x00, 0x00, 0x25, 0xff, 0xff, 0x00, 0x00
+.data1 	0x66, 0x89, 0x45, 0xa0, 0x8b, 0x55, 0xfc, 0x8b
+.data1 	0x52, 0x10, 0x88, 0x55, 0xac, 0x8b, 0x15, 0xb0
+.data1 	0x12, 0x00, 0x00, 0x03, 0x55, 0xd8, 0xb9, 0x10
+.data1 	0x00, 0x00, 0x00, 0x89, 0xd0, 0x31, 0xd2, 0xf7
+.data1 	0xf1, 0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x66
+.data1 	0x89, 0x55, 0xb0, 0x8b, 0x15, 0xb0, 0x12, 0x00
+.data1 	0x00, 0x03, 0x55, 0xd8, 0xc1, 0xea, 0x04, 0x81
+.data1 	0xe2, 0xff, 0xff, 0x00, 0x00, 0x66, 0x89, 0x55
+.data1 	0x9c, 0xe9, 0xaa, 0x00, 0x00, 0x00, 0x8b, 0x45
+.data1 	0xdc, 0x31, 0xd2, 0xf7, 0x75, 0xcc, 0x89, 0x45
+.data1 	0x88, 0x8b, 0x55, 0xfc, 0x8b, 0x4a, 0x08, 0x8b
+.data1 	0x45, 0xdc, 0x31, 0xd2, 0xf7, 0xf1, 0x83, 0xc2
+.data1 	0x01, 0x89, 0x55, 0x84, 0x8b, 0x45, 0xdc, 0x31
+.data1 	0xd2, 0xf7, 0x75, 0xcc, 0x8b, 0x4d, 0xfc, 0x8b
+.data1 	0x49, 0x08, 0x89, 0xd0, 0x31, 0xd2, 0xf7, 0xf1
+.data1 	0x89, 0x45, 0x80, 0xc6, 0x45, 0x94, 0x13, 0x81
+.data1 	0x7d, 0x0c, 0x08, 0x04, 0x00, 0x00, 0x75, 0x07
+.data1 	0xb8, 0x03, 0x00, 0x00, 0x00, 0xeb, 0x05, 0xb8
+.data1 	0x02, 0x00, 0x00, 0x00, 0x88, 0x45, 0xa1, 0x89
+.data1 	0xf2, 0xc1, 0xea, 0x09, 0x88, 0x55, 0xa0, 0xb9
+.data1 	0x10, 0x00, 0x00, 0x00, 0xa1, 0xb0, 0x12, 0x00
+.data1 	0x00, 0x31, 0xd2, 0xf7, 0xf1, 0x81, 0xe2, 0xff
+.data1 	0xff, 0x00, 0x00, 0x66, 0x89, 0x55, 0xa4, 0x8b
+.data1 	0x15, 0xb0, 0x12, 0x00, 0x00, 0xc1, 0xea, 0x04
+.data1 	0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x66, 0x89
+.data1 	0x55, 0x9e, 0x8b, 0x55, 0x88, 0x88, 0x55, 0xa9
+.data1 	0xba, 0x00, 0x03, 0x00, 0x00, 0x23, 0x55, 0x88
+.data1 	0xc1, 0xea, 0x02, 0x0b, 0x55, 0x84, 0x88, 0x55
+.data1 	0xa8, 0x8b, 0x55, 0x80, 0x88, 0x55, 0xad, 0x8b
+.data1 	0x55, 0xfc, 0x8b, 0x52, 0x10, 0x88, 0x55, 0xac
+.data1 	0x8d, 0x45, 0x94, 0x50, 0xe8, 0x5f, 0x17, 0x00
+.data1 	0x00, 0x59, 0x89, 0x45, 0xf0, 0x85, 0xc0, 0x74
+.data1 	0x15, 0xff, 0x75, 0xf0, 0x68, 0xa0, 0x00, 0x00
+.data1 	0x00, 0x68, 0xb4, 0x00, 0x00, 0x00, 0xe8, 0x99
+.data1 	0x16, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x0f, 0xb7
+.data1 	0x55, 0x94, 0xf6, 0xc2, 0x01, 0x74, 0x17, 0xff
+.data1 	0x45, 0xec, 0x83, 0x7d, 0xec, 0x02, 0x0f, 0x85
+.data1 	0xe2, 0xfc, 0xff, 0xff, 0xb8, 0xfb, 0xff, 0xff
+.data1 	0xff, 0xe9, 0xcf, 0x00, 0x00, 0x00, 0x81, 0x7d
+.data1 	0x0c, 0x09, 0x04, 0x00, 0x00, 0x0f, 0x85, 0x86
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x45, 0xe4, 0x00, 0x00
+.data1 	0x00, 0x00, 0x89, 0x7d, 0xf8, 0x39, 0x75, 0xe4
+.data1 	0x0f, 0x83, 0x73, 0x00, 0x00, 0x00, 0x8b, 0x57
+.data1 	0x04, 0x89, 0x55, 0xe0, 0x03, 0x55, 0xe4, 0x39
+.data1 	0xf2, 0x76, 0x08, 0x89, 0xf2, 0x2b, 0x55, 0xe4
+.data1 	0x89, 0x55, 0xe0, 0x8b, 0x55, 0xd4, 0x39, 0x55
+.data1 	0xe0, 0x76, 0x0b, 0x68, 0x58, 0x00, 0x00, 0x00
+.data1 	0xe8, 0x07, 0x16, 0x00, 0x00, 0x59, 0x8b, 0x45
+.data1 	0xf8, 0x8b, 0x55, 0xe4, 0x03, 0x15, 0xa8, 0x12
+.data1 	0x00, 0x00, 0xff, 0x75, 0xe0, 0xff, 0x30, 0x6a
+.data1 	0x01, 0xff, 0x75, 0x08, 0x52, 0x6a, 0x01, 0x6a
+.data1 	0xfe, 0xe8, 0x4a, 0x17, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x1c, 0x89, 0x45, 0xf0, 0x85, 0xc0, 0x74, 0x15
+.data1 	0xff, 0x75, 0xf0, 0x68, 0x38, 0x00, 0x00, 0x00
+.data1 	0x68, 0x4c, 0x00, 0x00, 0x00, 0xe8, 0xf2, 0x15
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55, 0xe0
+.data1 	0x01, 0x55, 0xe4, 0x83, 0x45, 0xf8, 0x08, 0xeb
+.data1 	0x84, 0x01, 0x75, 0x10, 0x39, 0x77, 0x04, 0x76
+.data1 	0x0f, 0x01, 0x37, 0x8b, 0x57, 0x04, 0x29, 0xf2
+.data1 	0x89, 0x57, 0x04, 0xe9, 0x2e, 0xfc, 0xff, 0xff
+.data1 	0x89, 0xf2, 0x2b, 0x57, 0x04, 0x89, 0xd6, 0x8b
+.data1 	0x57, 0x04, 0x01, 0x17, 0xc7, 0x47, 0x04, 0x00
+.data1 	0x00, 0x00, 0x00, 0x85, 0xf6, 0x75, 0x04, 0x31
+.data1 	0xc0, 0xeb, 0x0a, 0x83, 0xc7, 0x08, 0xff, 0x4d
+.data1 	0x18, 0xeb, 0xc9, 0x31, 0xc0, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0x3d, 0x4c, 0x05
+.data1 	0x00, 0x00, 0x00, 0x75, 0x0f, 0xe8, 0x8e, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x05, 0x4c, 0x05, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0xff
+.data1 	0x72, 0x08, 0xe8, 0x8e, 0xfa, 0xff, 0xff, 0x59
+.data1 	0x85, 0xc0, 0x75, 0x07, 0xb8, 0xfa, 0xff, 0xff
+.data1 	0xff, 0xeb, 0x38, 0x8b, 0x15, 0x9c, 0x12, 0x00
+.data1 	0x00, 0x8b, 0x52, 0x0c, 0xb9, 0x01, 0x00, 0x00
+.data1 	0x00, 0x01, 0xd1, 0x8b, 0x1d, 0x9c, 0x12, 0x00
+.data1 	0x00, 0x89, 0x4b, 0x0c, 0x85, 0xd2, 0x75, 0x19
+.data1 	0x6b, 0x05, 0xa0, 0x12, 0x00, 0x00, 0x05, 0x6a
+.data1 	0x00, 0x6a, 0x01, 0x50, 0x68, 0x0c, 0x05, 0x00
+.data1 	0x00, 0xe8, 0x9a, 0x08, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x10, 0x31, 0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x8b, 0x55, 0x0c, 0xff, 0x72, 0x08, 0xe8, 0x3a
+.data1 	0xfa, 0xff, 0xff, 0x59, 0x85, 0xc0, 0x75, 0x07
+.data1 	0xb8, 0xfa, 0xff, 0xff, 0xff, 0xeb, 0x17, 0x8b
+.data1 	0x15, 0x9c, 0x12, 0x00, 0x00, 0x8b, 0x52, 0x0c
+.data1 	0x83, 0xea, 0x01, 0x8b, 0x0d, 0x9c, 0x12, 0x00
+.data1 	0x00, 0x89, 0x51, 0x0c, 0x31, 0xc0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x68, 0x56, 0x57
+.data1 	0x6a, 0x04, 0x68, 0xac, 0x12, 0x00, 0x00, 0x6a
+.data1 	0x04, 0x68, 0xa8, 0x12, 0x00, 0x00, 0x6a, 0x0e
+.data1 	0xe8, 0x53, 0x15, 0x00, 0x00, 0x83, 0xc4, 0x14
+.data1 	0x89, 0xc6, 0x85, 0xf6, 0x74, 0x13, 0x56, 0x68
+.data1 	0xb4, 0x02, 0x00, 0x00, 0x68, 0xd0, 0x02, 0x00
+.data1 	0x00, 0xe8, 0xce, 0x14, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x68, 0xb0, 0x12, 0x00, 0x00, 0xff, 0x35
+.data1 	0xac, 0x12, 0x00, 0x00, 0xff, 0x35, 0xa8, 0x12
+.data1 	0x00, 0x00, 0x6a, 0x01, 0x6a, 0xfe, 0xe8, 0xa9
+.data1 	0x15, 0x00, 0x00, 0x83, 0xc4, 0x14, 0x89, 0xc6
+.data1 	0x85, 0xf6, 0x74, 0x13, 0x56, 0x68, 0x98, 0x02
+.data1 	0x00, 0x00, 0x68, 0xa8, 0x02, 0x00, 0x00, 0xe8
+.data1 	0x98, 0x14, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b
+.data1 	0x15, 0xb0, 0x12, 0x00, 0x00, 0x03, 0x15, 0xac
+.data1 	0x12, 0x00, 0x00, 0x81, 0xfa, 0x00, 0x00, 0x10
+.data1 	0x00, 0x76, 0x18, 0xff, 0x35, 0xb0, 0x12, 0x00
+.data1 	0x00, 0x68, 0x74, 0x02, 0x00, 0x00, 0x68, 0x8c
+.data1 	0x02, 0x00, 0x00, 0xe8, 0x6c, 0x14, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0xc7, 0x45, 0xf8, 0x00, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7d, 0xf8, 0x08, 0x0f, 0x8d
+.data1 	0x98, 0x02, 0x00, 0x00, 0x83, 0x3d, 0x08, 0x05
+.data1 	0x00, 0x00, 0x00, 0x74, 0x1c, 0x83, 0x7d, 0xf8
+.data1 	0x07, 0x75, 0x09, 0xc7, 0x45, 0xf4, 0x80, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x18, 0xba, 0x81, 0x00, 0x00
+.data1 	0x00, 0x03, 0x55, 0xf8, 0x89, 0x55, 0xf4, 0xeb
+.data1 	0x0b, 0xba, 0x80, 0x00, 0x00, 0x00, 0x03, 0x55
+.data1 	0xf8, 0x89, 0x55, 0xf4, 0x6b, 0x45, 0xf8, 0x05
+.data1 	0x50, 0xe8, 0x2f, 0xf9, 0xff, 0xff, 0x59, 0x8b
+.data1 	0x3d, 0x9c, 0x12, 0x00, 0x00, 0x8b, 0x55, 0xf4
+.data1 	0x89, 0x57, 0x10, 0xc6, 0x45, 0xa0, 0x13, 0xc6
+.data1 	0x45, 0xad, 0x08, 0x8b, 0x55, 0xf4, 0x88, 0x55
+.data1 	0xb8, 0x8d, 0x45, 0xa0, 0x50, 0xe8, 0xa6, 0x14
+.data1 	0x00, 0x00, 0x59, 0x89, 0xc6, 0x85, 0xf6, 0x74
+.data1 	0x13, 0x56, 0x68, 0x54, 0x02, 0x00, 0x00, 0x68
+.data1 	0x68, 0x02, 0x00, 0x00, 0xe8, 0xe3, 0x13, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x0f, 0xb7, 0x55, 0xa0
+.data1 	0xf6, 0xc2, 0x01, 0x75, 0x06, 0x0f, 0xb6, 0x45
+.data1 	0xb8, 0xeb, 0x03, 0x8b, 0x45, 0xf8, 0x89, 0x45
+.data1 	0xf0, 0x05, 0x80, 0x00, 0x00, 0x00, 0x39, 0x45
+.data1 	0xf4, 0x0f, 0x8d, 0xf5, 0x01, 0x00, 0x00, 0xc7
+.data1 	0x47, 0x14, 0x01, 0x00, 0x00, 0x00, 0x0f, 0xb6
+.data1 	0x55, 0xb9, 0x42, 0x89, 0x57, 0x04, 0x0f, 0xb6
+.data1 	0x55, 0xb4, 0x83, 0xe2, 0x3f, 0x89, 0x57, 0x08
+.data1 	0x0f, 0xb6, 0x55, 0xb4, 0x81, 0xe2, 0xc0, 0x00
+.data1 	0x00, 0x00, 0xc1, 0xe2, 0x02, 0x0f, 0xb6, 0x4d
+.data1 	0xb5, 0x09, 0xd1, 0x41, 0x89, 0x0f, 0x0f, 0xaf
+.data1 	0x4f, 0x04, 0x0f, 0xaf, 0x4f, 0x08, 0x89, 0x4d
+.data1 	0xe8, 0xc6, 0x45, 0xa0, 0x13, 0xc6, 0x45, 0xad
+.data1 	0x41, 0x66, 0xc7, 0x45, 0xb0, 0xaa, 0x55, 0x8b
+.data1 	0x55, 0xf4, 0x88, 0x55, 0xb8, 0x83, 0x3d, 0x04
+.data1 	0x05, 0x00, 0x00, 0x00, 0x74, 0x23, 0x8d, 0x45
+.data1 	0xa0, 0x50, 0xe8, 0x09, 0x14, 0x00, 0x00, 0x59
+.data1 	0x89, 0xc6, 0x85, 0xf6, 0x74, 0x13, 0x56, 0x68
+.data1 	0x34, 0x02, 0x00, 0x00, 0x68, 0x48, 0x02, 0x00
+.data1 	0x00, 0xe8, 0x46, 0x13, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x0f, 0xb7, 0x55, 0xa0, 0xf6, 0xc2, 0x01
+.data1 	0x0f, 0x85, 0x12, 0x01, 0x00, 0x00, 0x0f, 0xb7
+.data1 	0x55, 0xb0, 0x81, 0xfa, 0x55, 0xaa, 0x00, 0x00
+.data1 	0x0f, 0x85, 0x02, 0x01, 0x00, 0x00, 0x0f, 0xb7
+.data1 	0x55, 0xb4, 0xf6, 0xc2, 0x01, 0x0f, 0x84, 0xf5
+.data1 	0x00, 0x00, 0x00, 0x66, 0xc7, 0x45, 0xc8, 0x1e
+.data1 	0x00, 0x6a, 0x20, 0xff, 0x35, 0xa8, 0x12, 0x00
+.data1 	0x00, 0x6a, 0x01, 0x6a, 0xfe, 0x8d, 0x45, 0xc8
+.data1 	0x50, 0x6a, 0x01, 0x68, 0xce, 0x8a, 0x00, 0x00
+.data1 	0xe8, 0x33, 0x14, 0x00, 0x00, 0x83, 0xc4, 0x1c
+.data1 	0x89, 0xc6, 0x85, 0xf6, 0x74, 0x13, 0x56, 0x68
+.data1 	0x14, 0x02, 0x00, 0x00, 0x68, 0x28, 0x02, 0x00
+.data1 	0x00, 0xe8, 0xde, 0x12, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0xc6, 0x45, 0xa0, 0x13, 0xc6, 0x45, 0xad
+.data1 	0x48, 0x8b, 0x55, 0xf4, 0x88, 0x55, 0xb8, 0xb9
+.data1 	0x10, 0x00, 0x00, 0x00, 0xa1, 0xb0, 0x12, 0x00
+.data1 	0x00, 0x31, 0xd2, 0xf7, 0xf1, 0x81, 0xe2, 0xff
+.data1 	0xff, 0x00, 0x00, 0x66, 0x89, 0x55, 0xbc, 0x8b
+.data1 	0x15, 0xb0, 0x12, 0x00, 0x00, 0xc1, 0xea, 0x04
+.data1 	0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x66, 0x89
+.data1 	0x55, 0xa8, 0x8d, 0x45, 0xa0, 0x50, 0xe8, 0x45
+.data1 	0x13, 0x00, 0x00, 0x59, 0x89, 0xc6, 0x85, 0xf6
+.data1 	0x74, 0x13, 0x56, 0x68, 0xf4, 0x01, 0x00, 0x00
+.data1 	0x68, 0x08, 0x02, 0x00, 0x00, 0xe8, 0x82, 0x12
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x6a, 0x20, 0x8d
+.data1 	0x45, 0xc8, 0x50, 0x6a, 0x01, 0x68, 0xce, 0x8a
+.data1 	0x00, 0x00, 0xff, 0x35, 0xa8, 0x12, 0x00, 0x00
+.data1 	0x6a, 0x01, 0x6a, 0xfe, 0xe8, 0x9f, 0x13, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x1c, 0x89, 0xc6, 0x85, 0xf6
+.data1 	0x74, 0x13, 0x56, 0x68, 0xd4, 0x01, 0x00, 0x00
+.data1 	0x68, 0xe8, 0x01, 0x00, 0x00, 0xe8, 0x4a, 0x12
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x0f, 0xb7, 0x55
+.data1 	0xa0, 0xf6, 0xc2, 0x01, 0x75, 0x1a, 0xc7, 0x47
+.data1 	0x18, 0x01, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xd8
+.data1 	0x89, 0x55, 0xe8, 0x83, 0x7d, 0xdc, 0x00, 0x74
+.data1 	0x07, 0xc7, 0x45, 0xe8, 0xff, 0xff, 0xff, 0xff
+.data1 	0x83, 0x7f, 0x18, 0x00, 0x74, 0x18, 0xff, 0x75
+.data1 	0xe8, 0xe8, 0xd9, 0xf7, 0xff, 0xff, 0x50, 0x68
+.data1 	0xc0, 0x01, 0x00, 0x00, 0xe8, 0xc7, 0x0b, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xeb, 0x1b, 0xff, 0x77
+.data1 	0x08, 0xff, 0x77, 0x04, 0xff, 0x37, 0xe8, 0xbc
+.data1 	0xf7, 0xff, 0xff, 0x50, 0x68, 0x8c, 0x01, 0x00
+.data1 	0x00, 0xe8, 0xaa, 0x0b, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x14, 0x68, 0x00, 0x02, 0x00, 0x00, 0xff, 0x75
+.data1 	0xe8, 0x8d, 0x45, 0x98, 0x50, 0xe8, 0x1a, 0x16
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x50, 0x8d, 0x47
+.data1 	0x24, 0x50, 0xb9, 0x02, 0x00, 0x00, 0x00, 0xe8
+.data1 	0x5c, 0x1a, 0x00, 0x00, 0xff, 0x45, 0xf8, 0xe9
+.data1 	0x5e, 0xfd, 0xff, 0xff, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x15, 0x9c, 0x12, 0x00
+.data1 	0x00, 0x8b, 0x4d, 0x08, 0x8b, 0x12, 0x89, 0x51
+.data1 	0x10, 0x8b, 0x15, 0x9c, 0x12, 0x00, 0x00, 0x8b
+.data1 	0x4d, 0x08, 0x8b, 0x52, 0x04, 0x89, 0x51, 0x14
+.data1 	0x8b, 0x15, 0x9c, 0x12, 0x00, 0x00, 0x8b, 0x4d
+.data1 	0x08, 0x8b, 0x52, 0x08, 0x89, 0x51, 0x18, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x10, 0x56
+.data1 	0x8b, 0x75, 0x0c, 0x81, 0x7e, 0x04, 0x05, 0x04
+.data1 	0x00, 0x00, 0x74, 0x0a, 0xb8, 0xea, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x58, 0x00, 0x00, 0x00, 0x81, 0x7e
+.data1 	0x10, 0x07, 0x64, 0x04, 0x80, 0x75, 0x4a, 0xff
+.data1 	0x76, 0x08, 0xe8, 0x6e, 0xf6, 0xff, 0xff, 0x59
+.data1 	0x85, 0xc0, 0x75, 0x07, 0xb8, 0xfa, 0xff, 0xff
+.data1 	0xff, 0xeb, 0x3b, 0x8b, 0x15, 0x9c, 0x12, 0x00
+.data1 	0x00, 0x8b, 0x52, 0x0c, 0x89, 0x55, 0xf0, 0x6a
+.data1 	0x04, 0xff, 0x76, 0x1c, 0x6a, 0x01, 0xff, 0x76
+.data1 	0x0c, 0x8d, 0x45, 0xf0, 0x50, 0x6a, 0x01, 0x68
+.data1 	0xce, 0x8a, 0x00, 0x00, 0xe8, 0x67, 0x12, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x1c, 0x89, 0x45, 0xfc, 0x85
+.data1 	0xc0, 0x74, 0x02, 0xeb, 0x09, 0x31, 0xc0, 0xeb
+.data1 	0x05, 0xb8, 0xea, 0xff, 0xff, 0xff, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x2c, 0x56, 0x57, 0x8b, 0x75, 0x08, 0xe8
+.data1 	0x45, 0x01, 0x00, 0x00, 0x8d, 0x45, 0xd4, 0x50
+.data1 	0x68, 0xce, 0x7a, 0x00, 0x00, 0xe8, 0x5a, 0x15
+.data1 	0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x75, 0xec
+.data1 	0x8b, 0x55, 0xd4, 0x89, 0x15, 0x3c, 0x23, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xe0, 0x89, 0x55, 0xf8, 0xe9
+.data1 	0xdb, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xd4, 0x50
+.data1 	0x56, 0xff, 0x56, 0x04, 0x59, 0x59, 0x89, 0xc7
+.data1 	0xe9, 0xd7, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xd4
+.data1 	0x50, 0x56, 0xff, 0x56, 0x08, 0x59, 0x59, 0x89
+.data1 	0xc7, 0xe9, 0xc6, 0x00, 0x00, 0x00, 0x8d, 0x45
+.data1 	0xd4, 0x50, 0x56, 0xff, 0x56, 0x0c, 0x59, 0x59
+.data1 	0x89, 0xc7, 0xe9, 0xb5, 0x00, 0x00, 0x00, 0x8d
+.data1 	0x45, 0xd4, 0x50, 0x56, 0xff, 0x56, 0x28, 0x59
+.data1 	0x59, 0x89, 0xc7, 0xe9, 0xa4, 0x00, 0x00, 0x00
+.data1 	0x8d, 0x45, 0xd4, 0x50, 0x56, 0xff, 0x56, 0x2c
+.data1 	0x59, 0x59, 0x89, 0xc7, 0xe9, 0x93, 0x00, 0x00
+.data1 	0x00, 0x8d, 0x45, 0xd4, 0x50, 0x56, 0xe8, 0x1e
+.data1 	0x01, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc7, 0xe9
+.data1 	0x80, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xd4, 0x50
+.data1 	0x56, 0xe8, 0xb7, 0x01, 0x00, 0x00, 0x59, 0x59
+.data1 	0x89, 0xc7, 0xe9, 0x6d, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7e, 0x34, 0x00, 0x0f, 0x84, 0x53, 0xff, 0xff
+.data1 	0xff, 0x8d, 0x45, 0xd4, 0x50, 0x56, 0xff, 0x56
+.data1 	0x34, 0x59, 0x59, 0xe9, 0x44, 0xff, 0xff, 0xff
+.data1 	0x8d, 0x45, 0xd4, 0x50, 0x56, 0xff, 0x56, 0x20
+.data1 	0x59, 0x59, 0xe9, 0x35, 0xff, 0xff, 0xff, 0x8d
+.data1 	0x45, 0xd4, 0x50, 0x56, 0xff, 0x56, 0x24, 0x59
+.data1 	0x59, 0xe9, 0x26, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0xd4, 0xe8, 0xae, 0x14, 0x00, 0x00, 0x59, 0xe9
+.data1 	0x18, 0xff, 0xff, 0xff, 0x83, 0x7e, 0x30, 0x00
+.data1 	0x74, 0x0e, 0x8d, 0x45, 0xd4, 0x50, 0x56, 0xff
+.data1 	0x56, 0x30, 0x59, 0x59, 0x89, 0xc7, 0xeb, 0x14
+.data1 	0xbf, 0xea, 0xff, 0xff, 0xff, 0xeb, 0x0d, 0xbb
+.data1 	0xdc, 0x02, 0x00, 0x00, 0x8b, 0x45, 0xd8, 0xe9
+.data1 	0xc8, 0x18, 0x00, 0x00, 0xff, 0x56, 0x18, 0x81
+.data1 	0xff, 0x37, 0xff, 0xff, 0xff, 0x0f, 0x84, 0xe1
+.data1 	0xfe, 0xff, 0xff, 0xc7, 0x45, 0xd8, 0x44, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x55, 0xf8, 0x89, 0x55, 0xdc
+.data1 	0x89, 0x7d, 0xe0, 0x8d, 0x45, 0xd4, 0x50, 0xff
+.data1 	0x35, 0x3c, 0x23, 0x00, 0x00, 0xe8, 0x16, 0x14
+.data1 	0x00, 0x00, 0x59, 0x59, 0xe9, 0xbb, 0xfe, 0xff
+.data1 	0xff, 0x55, 0x89, 0xe5, 0x56, 0xc7, 0x05, 0x34
+.data1 	0x23, 0x00, 0x00, 0xb4, 0x12, 0x00, 0x00, 0x68
+.data1 	0x38, 0x23, 0x00, 0x00, 0x68, 0x00, 0x04, 0x00
+.data1 	0x00, 0x68, 0xb4, 0x12, 0x00, 0x00, 0x6a, 0x01
+.data1 	0x68, 0xce, 0x8a, 0x00, 0x00, 0xe8, 0x8a, 0x10
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x14, 0xba, 0xff, 0xff
+.data1 	0x00, 0x00, 0x23, 0x15, 0x38, 0x23, 0x00, 0x00
+.data1 	0x81, 0xea, 0x00, 0x00, 0x01, 0x00, 0xf7, 0xda
+.data1 	0x89, 0xd6, 0x81, 0xfa, 0x00, 0x02, 0x00, 0x00
+.data1 	0x73, 0x14, 0x89, 0xf2, 0x03, 0x15, 0x34, 0x23
+.data1 	0x00, 0x00, 0x89, 0x15, 0x34, 0x23, 0x00, 0x00
+.data1 	0x01, 0x35, 0x38, 0x23, 0x00, 0x00, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x14, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x0c, 0x83, 0x7e, 0x10, 0x00
+.data1 	0x79, 0x0a, 0xb8, 0xea, 0xff, 0xff, 0xff, 0xe9
+.data1 	0x8d, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xec, 0x50
+.data1 	0xff, 0x76, 0x10, 0xff, 0x76, 0x1c, 0x6a, 0x01
+.data1 	0xff, 0x76, 0x0c, 0xe8, 0x24, 0x10, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x14, 0x83, 0x7d, 0xec, 0x00, 0x75
+.data1 	0x0a, 0xb8, 0xf2, 0xff, 0xff, 0xff, 0xe9, 0x66
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x08, 0xff, 0x76
+.data1 	0x08, 0xff, 0x52, 0x10, 0x59, 0x85, 0xc0, 0x75
+.data1 	0x0a, 0xb8, 0xfa, 0xff, 0xff, 0xff, 0xe9, 0x4e
+.data1 	0x00, 0x00, 0x00, 0x81, 0x7e, 0x04, 0x03, 0x04
+.data1 	0x00, 0x00, 0x75, 0x07, 0xb8, 0x09, 0x04, 0x00
+.data1 	0x00, 0xeb, 0x05, 0xb8, 0x08, 0x04, 0x00, 0x00
+.data1 	0x89, 0x45, 0xf0, 0x8b, 0x56, 0x1c, 0x89, 0x55
+.data1 	0xf8, 0x8b, 0x56, 0x10, 0x89, 0x55, 0xfc, 0x8b
+.data1 	0x55, 0x08, 0x6a, 0x01, 0x8d, 0x45, 0xf8, 0x50
+.data1 	0xff, 0x76, 0x14, 0xff, 0x75, 0xf0, 0xff, 0x76
+.data1 	0x0c, 0xff, 0x52, 0x14, 0x83, 0xc4, 0x14, 0x89
+.data1 	0xc7, 0x85, 0xff, 0x75, 0x0a, 0x8b, 0x56, 0x10
+.data1 	0x2b, 0x55, 0xfc, 0x89, 0xd0, 0xeb, 0x02, 0x89
+.data1 	0xf8, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x10, 0x56, 0x57, 0x8b, 0x75, 0x0c
+.data1 	0x8b, 0x7e, 0x10, 0x83, 0xff, 0x40, 0x76, 0x05
+.data1 	0xbf, 0x40, 0x00, 0x00, 0x00, 0x89, 0xfa, 0xc1
+.data1 	0xe2, 0x03, 0x89, 0x55, 0xf8, 0x52, 0x68, 0xb4
+.data1 	0x16, 0x00, 0x00, 0x6a, 0x01, 0x68, 0xce, 0x8a
+.data1 	0x00, 0x00, 0xff, 0x76, 0x1c, 0x6a, 0x01, 0xff
+.data1 	0x36, 0xe8, 0xb2, 0x0f, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x1c, 0x85, 0xc0, 0x74, 0x15, 0x8b, 0x45, 0x08
+.data1 	0xff, 0x36, 0x68, 0x54, 0x03, 0x00, 0x00, 0xff
+.data1 	0x10, 0x50, 0xe8, 0x5d, 0x0e, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xc7, 0x45, 0xfc, 0xb4, 0x16, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x08, 0xff, 0x76, 0x08, 0xff
+.data1 	0x52, 0x10, 0x59, 0x85, 0xc0, 0x75, 0x07, 0xb8
+.data1 	0xfa, 0xff, 0xff, 0xff, 0xeb, 0x3a, 0x8b, 0x55
+.data1 	0x08, 0x57, 0xff, 0x75, 0xfc, 0xff, 0x76, 0x14
+.data1 	0xff, 0x76, 0x04, 0xff, 0x76, 0x0c, 0xff, 0x52
+.data1 	0x14, 0x83, 0xc4, 0x14, 0x89, 0x45, 0xf0, 0xff
+.data1 	0x75, 0xf8, 0xff, 0x76, 0x1c, 0x6a, 0x01, 0xff
+.data1 	0x36, 0x68, 0xb4, 0x16, 0x00, 0x00, 0x6a, 0x01
+.data1 	0x68, 0xce, 0x8a, 0x00, 0x00, 0xe8, 0x46, 0x0f
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x1c, 0x8b, 0x45, 0xf0
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0xb8
+.data1 	0x50, 0x05, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0xeb, 0x19, 0xb8, 0xed, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x22, 0x31, 0xc0, 0xeb, 0x1e, 0xb8, 0xe7
+.data1 	0xff, 0xff, 0xff, 0xeb, 0x17, 0xb8, 0xfb, 0xff
+.data1 	0xff, 0xff, 0xeb, 0x10, 0x8b, 0x55, 0x0c, 0xbb
+.data1 	0x68, 0x03, 0x00, 0x00, 0x8b, 0x42, 0x04, 0xe9
+.data1 	0x74, 0x16, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x31, 0xc0, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x31
+.data1 	0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x31, 0xc0
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x24
+.data1 	0x56, 0x57, 0x8b, 0x75, 0x0c, 0x81, 0x7e, 0x10
+.data1 	0x03, 0x64, 0x1c, 0x40, 0x74, 0x2a, 0x81, 0x7e
+.data1 	0x10, 0x04, 0x64, 0x1c, 0x80, 0x74, 0x21, 0x8b
+.data1 	0x55, 0x08, 0x83, 0x7a, 0x30, 0x00, 0x74, 0x0e
+.data1 	0x56, 0xff, 0x75, 0x08, 0xff, 0x52, 0x30, 0x59
+.data1 	0x59, 0xe9, 0xc6, 0x00, 0x00, 0x00, 0xb8, 0xe7
+.data1 	0xff, 0xff, 0xff, 0xe9, 0xbc, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x08, 0xff, 0x76, 0x08, 0xff, 0x52
+.data1 	0x10, 0x59, 0x89, 0xc7, 0x85, 0xc0, 0x75, 0x0a
+.data1 	0xb8, 0xfa, 0xff, 0xff, 0xff, 0xe9, 0xa2, 0x00
+.data1 	0x00, 0x00, 0x81, 0x7e, 0x10, 0x03, 0x64, 0x1c
+.data1 	0x40, 0x75, 0x4f, 0x6a, 0x1c, 0x8d, 0x45, 0xe0
+.data1 	0x50, 0x6a, 0x01, 0x68, 0xce, 0x8a, 0x00, 0x00
+.data1 	0xff, 0x76, 0x1c, 0x6a, 0x01, 0xff, 0x76, 0x0c
+.data1 	0xe8, 0x63, 0x0e, 0x00, 0x00, 0x83, 0xc4, 0x1c
+.data1 	0x89, 0x45, 0xdc, 0x85, 0xc0, 0x74, 0x05, 0xe9
+.data1 	0x70, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xe0, 0x50
+.data1 	0x57, 0xb9, 0x02, 0x00, 0x00, 0x00, 0xe8, 0x9d
+.data1 	0x15, 0x00, 0x00, 0x8d, 0x45, 0xe8, 0x50, 0x8d
+.data1 	0x47, 0x08, 0x50, 0xb9, 0x02, 0x00, 0x00, 0x00
+.data1 	0xe8, 0x8b, 0x15, 0x00, 0x00, 0xe9, 0x48, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x17, 0x8b, 0x4f, 0x04, 0x89
+.data1 	0x55, 0xe0, 0x89, 0x4d, 0xe4, 0x8b, 0x57, 0x08
+.data1 	0x8b, 0x4f, 0x0c, 0x89, 0x55, 0xe8, 0x89, 0x4d
+.data1 	0xec, 0x8b, 0x55, 0x08, 0x8d, 0x45, 0xe0, 0x50
+.data1 	0xff, 0x52, 0x1c, 0x59, 0x6a, 0x1c, 0xff, 0x76
+.data1 	0x1c, 0x6a, 0x01, 0xff, 0x76, 0x0c, 0x8d, 0x45
+.data1 	0xe0, 0x50, 0x6a, 0x01, 0x68, 0xce, 0x8a, 0x00
+.data1 	0x00, 0xe8, 0xf2, 0x0d, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x1c, 0x89, 0x45, 0xdc, 0x85, 0xc0, 0x74, 0x02
+.data1 	0xeb, 0x02, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x6c, 0x56, 0x57
+.data1 	0x8b, 0x55, 0x08, 0xff, 0x75, 0x0c, 0xff, 0x52
+.data1 	0x10, 0x59, 0x89, 0xc7, 0x85, 0xc0, 0x0f, 0x84
+.data1 	0xb4, 0x01, 0x00, 0x00, 0x6a, 0x00, 0xff, 0x77
+.data1 	0x0c, 0xff, 0x77, 0x08, 0xe8, 0x6f, 0x10, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x0f, 0x84
+.data1 	0x9c, 0x01, 0x00, 0x00, 0x68, 0x00, 0x02, 0x00
+.data1 	0x00, 0xff, 0x77, 0x04, 0xff, 0x37, 0xe8, 0x81
+.data1 	0x10, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45
+.data1 	0xac, 0x68, 0x00, 0x02, 0x00, 0x00, 0xff, 0x77
+.data1 	0x0c, 0xff, 0x77, 0x08, 0xe8, 0x6b, 0x10, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x03, 0x45, 0xac, 0x89
+.data1 	0x45, 0xa8, 0x8d, 0x45, 0xc0, 0x50, 0x6a, 0x00
+.data1 	0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0xe8, 0x8f
+.data1 	0x02, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x85, 0xc0
+.data1 	0x75, 0x49, 0xe9, 0x51, 0x01, 0x00, 0x00, 0x83
+.data1 	0x45, 0x0c, 0x70, 0xeb, 0x4b, 0x8d, 0x45, 0xc0
+.data1 	0x50, 0xe8, 0xf4, 0x02, 0x00, 0x00, 0x59, 0xff
+.data1 	0x45, 0x0c, 0xeb, 0x3c, 0xb9, 0x05, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x45, 0x0c, 0x99, 0xf7, 0xf9, 0x89
+.data1 	0x45, 0xb8, 0x8b, 0x45, 0x0c, 0x99, 0xf7, 0xf9
+.data1 	0x4a, 0x89, 0x55, 0xb4, 0x8b, 0x55, 0xb8, 0xc1
+.data1 	0xe2, 0x02, 0x03, 0x55, 0xb4, 0xc1, 0xe2, 0x02
+.data1 	0x81, 0xc2, 0x80, 0x00, 0x00, 0x00, 0x89, 0x55
+.data1 	0x0c, 0xeb, 0x0d, 0xbb, 0x80, 0x03, 0x00, 0x00
+.data1 	0x8b, 0x45, 0x10, 0xe9, 0x80, 0x14, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x08, 0xff, 0x75, 0x0c, 0xff, 0x52
+.data1 	0x10, 0x59, 0x89, 0xc7, 0x85, 0xc0, 0x0f, 0x84
+.data1 	0xec, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xb4, 0x00
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xb4, 0x04, 0x0f
+.data1 	0x8d, 0xdb, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xb4
+.data1 	0xc1, 0xe2, 0x04, 0x8d, 0x4d, 0xc0, 0x89, 0xd6
+.data1 	0x01, 0xce, 0x8b, 0x56, 0x0c, 0x03, 0x56, 0x08
+.data1 	0x89, 0x55, 0xa4, 0x39, 0x56, 0x08, 0x76, 0x06
+.data1 	0x8b, 0x55, 0xa8, 0x89, 0x55, 0xa4, 0x8b, 0x55
+.data1 	0xa8, 0x39, 0x55, 0xa4, 0x76, 0x03, 0x89, 0x55
+.data1 	0xa4, 0x8b, 0x55, 0xac, 0x39, 0x56, 0x08, 0x73
+.data1 	0x03, 0x89, 0x56, 0x08, 0x8b, 0x55, 0xa4, 0x39
+.data1 	0x56, 0x08, 0x76, 0x06, 0x8b, 0x56, 0x08, 0x89
+.data1 	0x55, 0xa4, 0x68, 0x00, 0x02, 0x00, 0x00, 0xff
+.data1 	0x76, 0x08, 0x8d, 0x45, 0x9c, 0x50, 0xe8, 0x99
+.data1 	0x0f, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x50, 0x57
+.data1 	0xb9, 0x02, 0x00, 0x00, 0x00, 0xe8, 0xde, 0x13
+.data1 	0x00, 0x00, 0x8b, 0x55, 0xa4, 0x2b, 0x56, 0x08
+.data1 	0x68, 0x00, 0x02, 0x00, 0x00, 0x52, 0x8d, 0x45
+.data1 	0x94, 0x50, 0xe8, 0x75, 0x0f, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x50, 0x8d, 0x47, 0x08, 0x50, 0xb9
+.data1 	0x02, 0x00, 0x00, 0x00, 0xe8, 0xb7, 0x13, 0x00
+.data1 	0x00, 0x83, 0x7d, 0x10, 0x01, 0x75, 0x3e, 0x80
+.data1 	0x7e, 0x04, 0x81, 0x75, 0x17, 0x8b, 0x55, 0xb4
+.data1 	0x03, 0x55, 0x0c, 0xff, 0x75, 0x14, 0x6a, 0x02
+.data1 	0x52, 0xff, 0x75, 0x08, 0xe8, 0x5f, 0xfe, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x10, 0x80, 0x7e, 0x04, 0x05
+.data1 	0x74, 0x06, 0x80, 0x7e, 0x04, 0x0f, 0x75, 0x15
+.data1 	0x8b, 0x55, 0xb4, 0x03, 0x55, 0x0c, 0xff, 0x76
+.data1 	0x08, 0x52, 0xff, 0x75, 0x08, 0xe8, 0x12, 0x00
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xff, 0x45, 0xb4
+.data1 	0x83, 0xc7, 0x10, 0xe9, 0x1b, 0xff, 0xff, 0xff
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x6c, 0x56, 0x57, 0xb9, 0x05, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x45, 0x0c, 0x99, 0xf7, 0xf9, 0x89
+.data1 	0x45, 0xb4, 0x8b, 0x45, 0x0c, 0x99, 0xf7, 0xf9
+.data1 	0x4a, 0x89, 0xd7, 0x8b, 0x55, 0xb4, 0xc1, 0xe2
+.data1 	0x02, 0x01, 0xfa, 0xc1, 0xe2, 0x02, 0x81, 0xc2
+.data1 	0x80, 0x00, 0x00, 0x00, 0x89, 0x55, 0xb8, 0xc7
+.data1 	0x45, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x45
+.data1 	0xc0, 0x50, 0xff, 0x75, 0xa8, 0xff, 0x75, 0x0c
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xe2, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0x85, 0xc0, 0x0f, 0x84, 0xd3
+.data1 	0x00, 0x00, 0x00, 0x8d, 0x45, 0xc0, 0x50, 0xe8
+.data1 	0x4e, 0x01, 0x00, 0x00, 0x59, 0xc7, 0x45, 0xa4
+.data1 	0x00, 0x00, 0x00, 0x00, 0x31, 0xff, 0x83, 0xff
+.data1 	0x04, 0x0f, 0x8d, 0xa9, 0x00, 0x00, 0x00, 0x89
+.data1 	0xfa, 0xc1, 0xe2, 0x04, 0x8d, 0x4d, 0xc0, 0x89
+.data1 	0xd6, 0x01, 0xce, 0x80, 0x7e, 0x04, 0x05, 0x74
+.data1 	0x06, 0x80, 0x7e, 0x04, 0x0f, 0x75, 0x0b, 0x8b
+.data1 	0x56, 0x08, 0x89, 0x55, 0xa4, 0xe9, 0x80, 0x00
+.data1 	0x00, 0x00, 0x80, 0x7e, 0x04, 0x00, 0x0f, 0x84
+.data1 	0x76, 0x00, 0x00, 0x00, 0x8b, 0x55, 0x08, 0xff
+.data1 	0x75, 0xb8, 0xff, 0x52, 0x10, 0x59, 0x89, 0x45
+.data1 	0xac, 0x85, 0xc0, 0x0f, 0x84, 0x75, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xa8, 0x03, 0x55, 0x10, 0x03
+.data1 	0x56, 0x08, 0x68, 0x00, 0x02, 0x00, 0x00, 0x52
+.data1 	0x8d, 0x45, 0x9c, 0x50, 0xe8, 0x43, 0x0e, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x50, 0xff, 0x75, 0xac
+.data1 	0xb9, 0x02, 0x00, 0x00, 0x00, 0xe8, 0x86, 0x12
+.data1 	0x00, 0x00, 0x68, 0x00, 0x02, 0x00, 0x00, 0xff
+.data1 	0x76, 0x0c, 0x8d, 0x45, 0x94, 0x50, 0xe8, 0x21
+.data1 	0x0e, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55
+.data1 	0xac, 0x50, 0x83, 0xc2, 0x08, 0x52, 0xb9, 0x02
+.data1 	0x00, 0x00, 0x00, 0xe8, 0x60, 0x12, 0x00, 0x00
+.data1 	0xff, 0x45, 0xb8, 0xb9, 0x04, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x45, 0xb8, 0x99, 0xf7, 0xf9, 0x85, 0xd2
+.data1 	0x74, 0x14, 0x47, 0xe9, 0x4e, 0xff, 0xff, 0xff
+.data1 	0x8b, 0x55, 0xa4, 0x89, 0x55, 0xa8, 0x85, 0xd2
+.data1 	0x0f, 0x85, 0x10, 0xff, 0xff, 0xff, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c
+.data1 	0x8b, 0x55, 0x10, 0xc1, 0xe2, 0x09, 0x89, 0x55
+.data1 	0xf4, 0xc7, 0x45, 0xf8, 0xb4, 0x18, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xfc, 0x00, 0x08, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x08, 0xff, 0x75, 0x0c, 0xff, 0x52, 0x10
+.data1 	0x59, 0x85, 0xc0, 0x74, 0x1c, 0x8b, 0x55, 0x08
+.data1 	0x6a, 0x01, 0x8d, 0x45, 0xf8, 0x50, 0xff, 0x75
+.data1 	0xf4, 0x68, 0x09, 0x04, 0x00, 0x00, 0x68, 0xce
+.data1 	0x8a, 0x00, 0x00, 0xff, 0x52, 0x14, 0x83, 0xc4
+.data1 	0x14, 0x83, 0x7d, 0xfc, 0x00, 0x74, 0x04, 0x31
+.data1 	0xc0, 0xeb, 0x2d, 0x80, 0x3d, 0xb2, 0x1a, 0x00
+.data1 	0x00, 0x55, 0x75, 0x09, 0x80, 0x3d, 0xb3, 0x1a
+.data1 	0x00, 0x00, 0xaa, 0x74, 0x04, 0x31, 0xc0, 0xeb
+.data1 	0x17, 0x6a, 0x40, 0x68, 0x72, 0x1a, 0x00, 0x00
+.data1 	0xff, 0x75, 0x14, 0xe8, 0xe0, 0x0d, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0xb8, 0x01, 0x00, 0x00, 0x00
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x14
+.data1 	0x56, 0x57, 0xbf, 0x04, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x75, 0x08, 0x8b, 0x55, 0x08, 0x83, 0xc2, 0x30
+.data1 	0x39, 0xf2, 0x76, 0x49, 0x80, 0x7e, 0x04, 0x00
+.data1 	0x74, 0x0e, 0x8b, 0x56, 0x18, 0x39, 0x56, 0x08
+.data1 	0x76, 0x36, 0x80, 0x7e, 0x14, 0x00, 0x74, 0x30
+.data1 	0x56, 0x8d, 0x45, 0xec, 0x50, 0xb9, 0x04, 0x00
+.data1 	0x00, 0x00, 0xe8, 0x79, 0x11, 0x00, 0x00, 0x8d
+.data1 	0x46, 0x10, 0x50, 0x56, 0xb9, 0x04, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x6a, 0x11, 0x00, 0x00, 0x8d, 0x45
+.data1 	0xec, 0x50, 0x8d, 0x46, 0x10, 0x50, 0xb9, 0x04
+.data1 	0x00, 0x00, 0x00, 0xe8, 0x58, 0x11, 0x00, 0x00
+.data1 	0x83, 0xc6, 0x10, 0xeb, 0xad, 0x4f, 0x85, 0xff
+.data1 	0x7f, 0xa5, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x81, 0xec, 0xb4, 0x00, 0x00
+.data1 	0x00, 0x56, 0x57, 0xc7, 0x85, 0x74, 0xff, 0xff
+.data1 	0xff, 0x58, 0x05, 0x00, 0x00, 0x83, 0xc4, 0xf8
+.data1 	0x89, 0xe0, 0x89, 0xc7, 0xc7, 0x85, 0x6c, 0xff
+.data1 	0xff, 0xff, 0x05, 0x00, 0x00, 0x00, 0x83, 0xbd
+.data1 	0x6c, 0xff, 0xff, 0xff, 0x00, 0x7e, 0x19, 0xff
+.data1 	0x8d, 0x6c, 0xff, 0xff, 0xff, 0x8b, 0x85, 0x74
+.data1 	0xff, 0xff, 0xff, 0xff, 0x85, 0x74, 0xff, 0xff
+.data1 	0xff, 0x8a, 0x08, 0x88, 0x0f, 0x47, 0xeb, 0xde
+.data1 	0x8d, 0xbd, 0x67, 0xff, 0xff, 0xff, 0x89, 0xe0
+.data1 	0x89, 0x85, 0x74, 0xff, 0xff, 0xff, 0xc7, 0x85
+.data1 	0x6c, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00
+.data1 	0x83, 0xbd, 0x6c, 0xff, 0xff, 0xff, 0x00, 0x7e
+.data1 	0x19, 0xff, 0x8d, 0x6c, 0xff, 0xff, 0xff, 0x8b
+.data1 	0x85, 0x74, 0xff, 0xff, 0xff, 0xff, 0x85, 0x74
+.data1 	0xff, 0xff, 0xff, 0x8a, 0x08, 0x88, 0x0f, 0x47
+.data1 	0xeb, 0xde, 0x59, 0x59, 0x68, 0x80, 0x00, 0x00
+.data1 	0x00, 0x8d, 0x85, 0x78, 0xff, 0xff, 0xff, 0x50
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xc7, 0x05, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x85, 0x5c, 0xff, 0xff
+.data1 	0xff, 0x85, 0xc0, 0x74, 0x29, 0x83, 0xbd, 0x5c
+.data1 	0xff, 0xff, 0xff, 0xfd, 0x75, 0x07, 0x6a, 0x00
+.data1 	0xe9, 0xb6, 0x01, 0x00, 0x00, 0xff, 0xb5, 0x5c
+.data1 	0xff, 0xff, 0xff, 0x68, 0xd0, 0x03, 0x00, 0x00
+.data1 	0xe8, 0xab, 0x01, 0x00, 0x00, 0x59, 0x59, 0x6a
+.data1 	0x04, 0xe9, 0x9d, 0x01, 0x00, 0x00, 0x8d, 0xb5
+.data1 	0x78, 0xff, 0xff, 0xff, 0x68, 0xcc, 0x03, 0x00
+.data1 	0x00, 0x56, 0xe8, 0xe9, 0x0c, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x75, 0x07, 0x6a, 0x01, 0xe9
+.data1 	0x7f, 0x01, 0x00, 0x00, 0x68, 0xc8, 0x03, 0x00
+.data1 	0x00, 0x56, 0xe8, 0xd1, 0x0c, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x75, 0x07, 0x6a, 0x02, 0xe9
+.data1 	0x67, 0x01, 0x00, 0x00, 0xc7, 0x85, 0x58, 0xff
+.data1 	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x85
+.data1 	0x50, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00
+.data1 	0x80, 0x3e, 0x20, 0x75, 0x03, 0x46, 0xeb, 0xf8
+.data1 	0x80, 0x3e, 0x00, 0x75, 0x0b, 0xff, 0xb5, 0x50
+.data1 	0xff, 0xff, 0xff, 0xe9, 0x3b, 0x01, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x0c, 0x80, 0x3a, 0x00, 0x0f, 0x84
+.data1 	0x27, 0x01, 0x00, 0x00, 0x0f, 0xbe, 0x06, 0x50
+.data1 	0x8d, 0x85, 0x67, 0xff, 0xff, 0xff, 0x50, 0xe8
+.data1 	0x3c, 0x0c, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x0f, 0x84, 0x89, 0x00, 0x00, 0x00, 0x8b, 0x55
+.data1 	0x0c, 0x0f, 0xbe, 0x02, 0x50, 0x8d, 0x85, 0x67
+.data1 	0xff, 0xff, 0xff, 0x50, 0xe8, 0x1f, 0x0c, 0x00
+.data1 	0x00, 0x59, 0x59, 0x85, 0xc0, 0x74, 0x06, 0xff
+.data1 	0x85, 0x58, 0xff, 0xff, 0xff, 0x8b, 0x45, 0x0c
+.data1 	0xff, 0x45, 0x0c, 0x0f, 0xbe, 0x00, 0x0f, 0xbe
+.data1 	0x1e, 0x39, 0xd8, 0x75, 0x01, 0x46, 0x8b, 0x55
+.data1 	0x0c, 0x0f, 0xbe, 0x02, 0x3d, 0x20, 0x00, 0x00
+.data1 	0x00, 0x7d, 0x85, 0x0f, 0xbe, 0x02, 0xf7, 0xd8
+.data1 	0x03, 0x45, 0x0c, 0x89, 0x45, 0x0c, 0xe9, 0x75
+.data1 	0xff, 0xff, 0xff, 0xc7, 0x85, 0x54, 0xff, 0xff
+.data1 	0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x40, 0xc7
+.data1 	0x85, 0x54, 0xff, 0xff, 0xff, 0x0a, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x34, 0xc7, 0x85, 0x54, 0xff, 0xff
+.data1 	0xff, 0x08, 0x00, 0x00, 0x00, 0xeb, 0x28, 0xc7
+.data1 	0x85, 0x54, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x1c, 0xc7, 0x85, 0x54, 0xff, 0xff
+.data1 	0xff, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x10, 0x8b
+.data1 	0x55, 0x0c, 0x0f, 0xbe, 0x02, 0xbb, 0x98, 0x03
+.data1 	0x00, 0x00, 0xe9, 0x9d, 0x0f, 0x00, 0x00, 0x83
+.data1 	0xbd, 0x54, 0xff, 0xff, 0xff, 0x00, 0x79, 0x1d
+.data1 	0x0f, 0xbe, 0x06, 0x50, 0x8d, 0x85, 0x67, 0xff
+.data1 	0xff, 0xff, 0x50, 0xe8, 0x80, 0x0b, 0x00, 0x00
+.data1 	0x59, 0x59, 0x85, 0xc0, 0x0f, 0x85, 0x06, 0xff
+.data1 	0xff, 0xff, 0x46, 0xeb, 0xe3, 0xff, 0xb5, 0x54
+.data1 	0xff, 0xff, 0xff, 0x8d, 0x45, 0xf8, 0x50, 0x56
+.data1 	0xe8, 0x5b, 0x08, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0x85, 0x60, 0xff, 0xff, 0xff, 0x39, 0x75
+.data1 	0xf8, 0x74, 0x30, 0x8b, 0x75, 0xf8, 0x8b, 0x55
+.data1 	0x10, 0x39, 0x95, 0x58, 0xff, 0xff, 0xff, 0x0f
+.data1 	0x85, 0xd3, 0xfe, 0xff, 0xff, 0x39, 0x45, 0x18
+.data1 	0x7f, 0x19, 0x39, 0x45, 0x1c, 0x7c, 0x14, 0x8b
+.data1 	0x5d, 0x14, 0x89, 0x03, 0xc7, 0x85, 0x50, 0xff
+.data1 	0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0xe9, 0xb5
+.data1 	0xfe, 0xff, 0xff, 0xff, 0x75, 0x08, 0xe8, 0x95
+.data1 	0x05, 0x00, 0x00, 0x58, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x40, 0x56, 0x57
+.data1 	0xc7, 0x45, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x8d
+.data1 	0x7d, 0x0c, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08
+.data1 	0x0f, 0xbe, 0x00, 0x89, 0xc6, 0x85, 0xc0, 0x0f
+.data1 	0x84, 0x03, 0x03, 0x00, 0x00, 0x83, 0xfe, 0x25
+.data1 	0x74, 0x0c, 0xff, 0x45, 0xf8, 0x56, 0xe8, 0x05
+.data1 	0x03, 0x00, 0x00, 0x59, 0xeb, 0xdc, 0x8b, 0x45
+.data1 	0x08, 0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89
+.data1 	0xc6, 0xc7, 0x45, 0xf4, 0x01, 0x00, 0x00, 0x00
+.data1 	0x83, 0xfe, 0x2d, 0x75, 0x12, 0xc7, 0x45, 0xf4
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x45, 0x08, 0xff
+.data1 	0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0xc6, 0xc7
+.data1 	0x45, 0xec, 0x20, 0x00, 0x00, 0x00, 0x83, 0xfe
+.data1 	0x30, 0x75, 0x12, 0xc7, 0x45, 0xec, 0x30, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08
+.data1 	0x0f, 0xbe, 0x00, 0x89, 0xc6, 0xc7, 0x45, 0xe8
+.data1 	0x00, 0x00, 0x00, 0x00, 0x83, 0xfe, 0x2a, 0x75
+.data1 	0x18, 0x8d, 0x57, 0x04, 0x89, 0xd7, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0xe8, 0x8b, 0x45, 0x08, 0xff
+.data1 	0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0xc6, 0xeb
+.data1 	0x2f, 0x89, 0xf2, 0x83, 0xea, 0x30, 0x83, 0xfa
+.data1 	0x0a, 0x73, 0x25, 0x6b, 0x45, 0xe8, 0x0a, 0x89
+.data1 	0xf2, 0x83, 0xea, 0x30, 0x01, 0xc2, 0x89, 0x55
+.data1 	0xe8, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f
+.data1 	0xbe, 0x00, 0x89, 0xc6, 0x2d, 0x30, 0x00, 0x00
+.data1 	0x00, 0x3d, 0x0a, 0x00, 0x00, 0x00, 0x72, 0xdb
+.data1 	0xc7, 0x45, 0xe4, 0xff, 0xff, 0xff, 0x7f, 0x83
+.data1 	0xfe, 0x2e, 0x0f, 0x85, 0x60, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f, 0xbe
+.data1 	0x00, 0x89, 0xc6, 0x3d, 0x2a, 0x00, 0x00, 0x00
+.data1 	0x75, 0x18, 0x8d, 0x57, 0x04, 0x89, 0xd7, 0x8b
+.data1 	0x52, 0xfc, 0x89, 0x55, 0xe4, 0x8b, 0x45, 0x08
+.data1 	0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0xc6
+.data1 	0xeb, 0x36, 0x89, 0xf2, 0x83, 0xea, 0x30, 0x83
+.data1 	0xfa, 0x0a, 0x73, 0x2c, 0xc7, 0x45, 0xe4, 0x00
+.data1 	0x00, 0x00, 0x00, 0x6b, 0x45, 0xe4, 0x0a, 0x89
+.data1 	0xf2, 0x83, 0xea, 0x30, 0x01, 0xc2, 0x89, 0x55
+.data1 	0xe4, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f
+.data1 	0xbe, 0x00, 0x89, 0xc6, 0x2d, 0x30, 0x00, 0x00
+.data1 	0x00, 0x3d, 0x0a, 0x00, 0x00, 0x00, 0x72, 0xdb
+.data1 	0xc7, 0x45, 0xd8, 0x74, 0x05, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xd0, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x45
+.data1 	0xdc, 0x0a, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xf0
+.data1 	0x01, 0x00, 0x00, 0x00, 0x83, 0xfe, 0x6c, 0x74
+.data1 	0x05, 0x83, 0xfe, 0x4c, 0x75, 0x12, 0xc7, 0x45
+.data1 	0xf0, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x45, 0x08
+.data1 	0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0xc6
+.data1 	0x85, 0xf6, 0x0f, 0x85, 0x9c, 0x01, 0x00, 0x00
+.data1 	0xe9, 0xa3, 0x01, 0x00, 0x00, 0x83, 0x7d, 0xf0
+.data1 	0x00, 0x75, 0x0a, 0x8d, 0x57, 0x04, 0x89, 0xd7
+.data1 	0x8b, 0x42, 0xfc, 0xeb, 0x08, 0x8d, 0x57, 0x04
+.data1 	0x89, 0xd7, 0x8b, 0x42, 0xfc, 0x89, 0x45, 0xd0
+.data1 	0x85, 0xc0, 0x79, 0x04, 0xf7, 0xd8, 0xeb, 0x03
+.data1 	0x8b, 0x45, 0xd0, 0x89, 0x45, 0xcc, 0xeb, 0x32
+.data1 	0xc7, 0x45, 0xdc, 0x08, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x0e, 0xc7, 0x45, 0xd8, 0x60, 0x05, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xdc, 0x10, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7d, 0xf0, 0x00, 0x75, 0x0a, 0x8d, 0x57, 0x04
+.data1 	0x89, 0xd7, 0x8b, 0x42, 0xfc, 0xeb, 0x08, 0x8d
+.data1 	0x57, 0x04, 0x89, 0xd7, 0x8b, 0x42, 0xfc, 0x89
+.data1 	0x45, 0xcc, 0x8d, 0x55, 0xcb, 0x89, 0x55, 0xd4
+.data1 	0xc6, 0x02, 0x00, 0x8b, 0x45, 0xcc, 0x31, 0xd2
+.data1 	0xf7, 0x75, 0xdc, 0x03, 0x55, 0xd8, 0x0f, 0xb6
+.data1 	0x02, 0x50, 0xff, 0x4d, 0xd4, 0x8b, 0x55, 0xd4
+.data1 	0x59, 0x88, 0x0a, 0x8b, 0x45, 0xcc, 0x31, 0xd2
+.data1 	0xf7, 0x75, 0xdc, 0x89, 0x45, 0xcc, 0x85, 0xc0
+.data1 	0x75, 0xd9, 0xeb, 0x39, 0x8d, 0x55, 0xc0, 0x89
+.data1 	0x55, 0xd4, 0x8d, 0x57, 0x04, 0x89, 0xd7, 0x8b
+.data1 	0x4d, 0xd4, 0x8b, 0x52, 0xfc, 0x88, 0x11, 0xc7
+.data1 	0x45, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x3c
+.data1 	0x8d, 0x55, 0xc0, 0x89, 0x55, 0xd4, 0xc6, 0x02
+.data1 	0x25, 0xc7, 0x45, 0xe0, 0x01, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x2a, 0x8d, 0x57, 0x04, 0x89, 0xd7, 0x8b
+.data1 	0x52, 0xfc, 0x89, 0x55, 0xd4, 0xc7, 0x45, 0xe0
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xd4, 0x03
+.data1 	0x55, 0xe0, 0x80, 0x3a, 0x00, 0x74, 0x0d, 0x8b
+.data1 	0x55, 0xe4, 0x39, 0x55, 0xe0, 0x7d, 0x05, 0xff
+.data1 	0x45, 0xe0, 0xeb, 0xe8, 0x8b, 0x55, 0xe8, 0x2b
+.data1 	0x55, 0xe0, 0x89, 0x55, 0xe8, 0x83, 0x7d, 0xd0
+.data1 	0x00, 0x79, 0x03, 0xff, 0x4d, 0xe8, 0x83, 0x7d
+.data1 	0xec, 0x30, 0x75, 0x11, 0x83, 0x7d, 0xd0, 0x00
+.data1 	0x79, 0x0b, 0xff, 0x45, 0xf8, 0x6a, 0x2d, 0xe8
+.data1 	0xa4, 0x00, 0x00, 0x00, 0x59, 0x83, 0x7d, 0xf4
+.data1 	0x01, 0x75, 0x17, 0x83, 0x7d, 0xe8, 0x00, 0x7e
+.data1 	0x11, 0xff, 0x45, 0xf8, 0xff, 0x75, 0xec, 0xe8
+.data1 	0x8c, 0x00, 0x00, 0x00, 0x59, 0xff, 0x4d, 0xe8
+.data1 	0xeb, 0xe9, 0x83, 0x7d, 0xec, 0x20, 0x75, 0x11
+.data1 	0x83, 0x7d, 0xd0, 0x00, 0x79, 0x0b, 0xff, 0x45
+.data1 	0xf8, 0x6a, 0x2d, 0xe8, 0x70, 0x00, 0x00, 0x00
+.data1 	0x59, 0x83, 0x7d, 0xe0, 0x00, 0x7e, 0x18, 0xff
+.data1 	0x45, 0xf8, 0x8b, 0x45, 0xd4, 0xff, 0x45, 0xd4
+.data1 	0x0f, 0xb6, 0x18, 0x53, 0xe8, 0x57, 0x00, 0x00
+.data1 	0x00, 0x59, 0xff, 0x4d, 0xe0, 0xeb, 0xe2, 0x83
+.data1 	0x7d, 0xe8, 0x00, 0x0f, 0x8e, 0x21, 0xfd, 0xff
+.data1 	0xff, 0xff, 0x45, 0xf8, 0xff, 0x75, 0xec, 0xe8
+.data1 	0x3c, 0x00, 0x00, 0x00, 0x59, 0xff, 0x4d, 0xe8
+.data1 	0xeb, 0xe5, 0xff, 0x45, 0xf8, 0x6a, 0x25, 0xe8
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x59, 0xff, 0x45, 0xf8
+.data1 	0x56, 0xe8, 0x22, 0x00, 0x00, 0x00, 0x59, 0xe9
+.data1 	0xf6, 0xfc, 0xff, 0xff, 0xbb, 0x04, 0x04, 0x00
+.data1 	0x00, 0x89, 0xf0, 0xe9, 0xf4, 0x0b, 0x00, 0x00
+.data1 	0x6a, 0x00, 0xe8, 0x09, 0x00, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x45, 0xf8, 0x5f, 0x5e, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x30, 0x56, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x75, 0x09, 0x83, 0x3d, 0x04
+.data1 	0x21, 0x00, 0x00, 0x00, 0x7f, 0x09, 0x83, 0x3d
+.data1 	0x04, 0x21, 0x00, 0x00, 0x50, 0x75, 0x59, 0x68
+.data1 	0x88, 0x05, 0x00, 0x00, 0x8d, 0x45, 0xd0, 0x50
+.data1 	0xb9, 0x03, 0x00, 0x00, 0x00, 0xe8, 0x6e, 0x0b
+.data1 	0x00, 0x00, 0x31, 0xf6, 0x81, 0x7c, 0xb5, 0xd0
+.data1 	0xce, 0x6a, 0x00, 0x00, 0x74, 0x30, 0x8b, 0x15
+.data1 	0x04, 0x21, 0x00, 0x00, 0x89, 0x55, 0xe4, 0xc7
+.data1 	0x45, 0xf0, 0xb4, 0x20, 0x00, 0x00, 0xc7, 0x45
+.data1 	0xe8, 0xce, 0x8a, 0x00, 0x00, 0xc7, 0x45, 0xe0
+.data1 	0x64, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0xff, 0x74, 0xb5, 0xd0, 0xe8, 0x1f, 0x07, 0x00
+.data1 	0x00, 0x59, 0x59, 0x46, 0xeb, 0xc6, 0xc7, 0x05
+.data1 	0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x08, 0x00, 0x74, 0x1d, 0x8b, 0x45
+.data1 	0x08, 0x0f, 0xbe, 0xc0, 0x8b, 0x15, 0x04, 0x21
+.data1 	0x00, 0x00, 0x89, 0xd1, 0x41, 0x89, 0x0d, 0x04
+.data1 	0x21, 0x00, 0x00, 0x89, 0xd3, 0x88, 0x83, 0xb4
+.data1 	0x20, 0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x55, 0x08, 0x89, 0x15
+.data1 	0x94, 0x05, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x15, 0x98, 0x05, 0x00, 0x00, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x34, 0x56, 0x57, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x75, 0x0a, 0xb8, 0xea, 0xff
+.data1 	0xff, 0xff, 0xe9, 0x41, 0x01, 0x00, 0x00, 0xff
+.data1 	0x75, 0x08, 0xe8, 0x79, 0x07, 0x00, 0x00, 0x59
+.data1 	0x89, 0x45, 0xcc, 0xbe, 0x01, 0x00, 0x00, 0x00
+.data1 	0x39, 0x35, 0x94, 0x05, 0x00, 0x00, 0x0f, 0x8e
+.data1 	0x88, 0x00, 0x00, 0x00, 0x8b, 0x15, 0x98, 0x05
+.data1 	0x00, 0x00, 0xff, 0x75, 0xcc, 0xff, 0x75, 0x08
+.data1 	0xff, 0x34, 0xb2, 0xe8, 0x60, 0x07, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x0f, 0x85, 0x63
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x15, 0x98, 0x05, 0x00
+.data1 	0x00, 0xff, 0x34, 0xb2, 0xe8, 0x37, 0x07, 0x00
+.data1 	0x00, 0x59, 0x39, 0x45, 0xcc, 0x73, 0x4f, 0x8b
+.data1 	0x15, 0x98, 0x05, 0x00, 0x00, 0x8b, 0x14, 0xb2
+.data1 	0x03, 0x55, 0xcc, 0x80, 0x3a, 0x3d, 0x75, 0x3e
+.data1 	0x8b, 0x15, 0x98, 0x05, 0x00, 0x00, 0x8b, 0x14
+.data1 	0xb2, 0x03, 0x55, 0xcc, 0x89, 0xd7, 0x47, 0x57
+.data1 	0xe8, 0x0b, 0x07, 0x00, 0x00, 0x59, 0x05, 0x01
+.data1 	0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00
+.data1 	0x76, 0x0a, 0xb8, 0xf9, 0xff, 0xff, 0xff, 0xe9
+.data1 	0xb4, 0x00, 0x00, 0x00, 0x57, 0xff, 0x75, 0x0c
+.data1 	0xe8, 0xcb, 0x06, 0x00, 0x00, 0x59, 0x59, 0x31
+.data1 	0xc0, 0xe9, 0xa2, 0x00, 0x00, 0x00, 0x46, 0xe9
+.data1 	0x6c, 0xff, 0xff, 0xff, 0xc7, 0x45, 0xe0, 0x1a
+.data1 	0x06, 0x00, 0x00, 0xc7, 0x45, 0xec, 0x04, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x45, 0xf0, 0xce, 0x8a, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xe4, 0x00, 0x02, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xf4, 0x08, 0x21, 0x00, 0x00, 0x8d
+.data1 	0x45, 0xdc, 0x50, 0x68, 0x1a, 0x06, 0x00, 0x00
+.data1 	0x6a, 0xfe, 0xe8, 0x11, 0x01, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0x45, 0xd0, 0x85, 0xc0, 0x74
+.data1 	0x1a, 0x68, 0x00, 0x02, 0x00, 0x00, 0xff, 0x75
+.data1 	0xd0, 0x68, 0x54, 0x04, 0x00, 0x00, 0xe8, 0x05
+.data1 	0xfb, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x8b, 0x45
+.data1 	0xd0, 0xeb, 0x45, 0xff, 0x75, 0x08, 0x68, 0x08
+.data1 	0x21, 0x00, 0x00, 0xe8, 0x3c, 0x00, 0x00, 0x00
+.data1 	0x59, 0x59, 0x89, 0xc7, 0x85, 0xc0, 0x75, 0x07
+.data1 	0xb8, 0xfd, 0xff, 0xff, 0xff, 0xeb, 0x29, 0xff
+.data1 	0x75, 0x10, 0x57, 0xff, 0x75, 0x0c, 0xe8, 0x7d
+.data1 	0x06, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x57, 0xe8
+.data1 	0x54, 0x06, 0x00, 0x00, 0x59, 0x05, 0x01, 0x00
+.data1 	0x00, 0x00, 0x39, 0x45, 0x10, 0x73, 0x07, 0xb8
+.data1 	0xf9, 0xff, 0xff, 0xff, 0xeb, 0x02, 0x31, 0xc0
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x08, 0x80, 0x3e, 0x00, 0x74
+.data1 	0x2e, 0x8b, 0x7d, 0x0c, 0x80, 0x3f, 0x00, 0x74
+.data1 	0x0e, 0x0f, 0xbe, 0x07, 0x0f, 0xbe, 0x1e, 0x39
+.data1 	0xd8, 0x75, 0x04, 0x47, 0x46, 0xeb, 0xed, 0x80
+.data1 	0x3f, 0x00, 0x75, 0x0a, 0x80, 0x3e, 0x3d, 0x75
+.data1 	0x05, 0x8d, 0x46, 0x01, 0xeb, 0x0b, 0x8a, 0x06
+.data1 	0x46, 0x84, 0xc0, 0x74, 0xcf, 0xeb, 0xf7, 0x31
+.data1 	0xc0, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x68, 0x80, 0x00, 0x00
+.data1 	0x00, 0x68, 0x9c, 0x05, 0x00, 0x00, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x49, 0xfe, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0x89, 0xc6, 0x85, 0xc0, 0x75, 0x12, 0x83
+.data1 	0xfe, 0xfd, 0x74, 0x0d, 0x56, 0x68, 0x9c, 0x04
+.data1 	0x00, 0x00, 0xe8, 0x41, 0xfa, 0xff, 0xff, 0x59
+.data1 	0x59, 0x68, 0x9c, 0x05, 0x00, 0x00, 0xff, 0x75
+.data1 	0x08, 0x68, 0x78, 0x04, 0x00, 0x00, 0xe8, 0x2d
+.data1 	0xfa, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x68, 0x00
+.data1 	0x80, 0x00, 0x00, 0x68, 0x70, 0x04, 0x00, 0x00
+.data1 	0x68, 0x74, 0x04, 0x00, 0x00, 0xe8, 0x5a, 0x00
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x75, 0x10
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x56, 0x04, 0x56, 0xff
+.data1 	0x75, 0x08, 0xe8, 0xb9, 0x04, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0xc7, 0x85, 0xff, 0x74, 0x04, 0x89
+.data1 	0xf8, 0xeb, 0x03, 0x8b, 0x46, 0x04, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0xff
+.data1 	0x75, 0x08, 0x68, 0xd0, 0x04, 0x00, 0x00, 0xe8
+.data1 	0xd4, 0xf9, 0xff, 0xff, 0x59, 0x59, 0x68, 0x00
+.data1 	0x80, 0x00, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0xe8
+.data1 	0x08, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0xc7, 0x05, 0x1c, 0x06, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x83, 0x7d, 0x08, 0x00
+.data1 	0x74, 0x3a, 0x83, 0x7d, 0x0c, 0x00, 0x74, 0x34
+.data1 	0x81, 0x7d, 0x10, 0x00, 0x80, 0x00, 0x00, 0x74
+.data1 	0x18, 0xff, 0x75, 0x10, 0xff, 0x75, 0x0c, 0xff
+.data1 	0x75, 0x08, 0x68, 0xe8, 0x04, 0x00, 0x00, 0xe8
+.data1 	0x84, 0xf9, 0xff, 0xff, 0x83, 0xc4, 0x10, 0xeb
+.data1 	0x13, 0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0x68
+.data1 	0xd4, 0x04, 0x00, 0x00, 0xe8, 0x6f, 0xf9, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x6a, 0x09, 0x68, 0xce
+.data1 	0x8a, 0x00, 0x00, 0xe8, 0x74, 0x00, 0x00, 0x00
+.data1 	0x59, 0x59, 0xba, 0xff, 0xff, 0xff, 0xff, 0x89
+.data1 	0x55, 0xd8, 0xff, 0xd2, 0xeb, 0xfe, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xec, 0xc7, 0x45, 0xf0, 0xce
+.data1 	0x8a, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0x89, 0x55
+.data1 	0xf4, 0x8b, 0x55, 0x10, 0x89, 0x55, 0xe4, 0x8b
+.data1 	0x55, 0x14, 0x89, 0x55, 0xf8, 0x8b, 0x55, 0x18
+.data1 	0x89, 0x55, 0xe8, 0x8d, 0x45, 0xdc, 0x50, 0x68
+.data1 	0x1a, 0x06, 0x00, 0x00, 0x6a, 0xfe, 0xe8, 0x05
+.data1 	0xff, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xf0, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x68, 0x14, 0x06, 0x00, 0x00, 0x6a, 0xfe, 0xe8
+.data1 	0xe4, 0xfe, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x55, 0xe8, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0x68, 0x06, 0x06, 0x00, 0x00, 0x6a
+.data1 	0xfe, 0xe8, 0xba, 0xfe, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe8
+.data1 	0x8b, 0x55, 0x0c, 0x66, 0x89, 0x55, 0xe4, 0x8b
+.data1 	0x55, 0x10, 0x89, 0x55, 0xf0, 0x8b, 0x55, 0x14
+.data1 	0x89, 0x55, 0xf8, 0x8d, 0x45, 0xdc, 0x50, 0x68
+.data1 	0x0e, 0x06, 0x00, 0x00, 0x6a, 0xfe, 0xe8, 0x85
+.data1 	0xfe, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x89, 0x45
+.data1 	0xd8, 0x8b, 0x55, 0xf4, 0x8b, 0x45, 0x18, 0x89
+.data1 	0x10, 0x8b, 0x45, 0xd8, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x83, 0x7d
+.data1 	0x20, 0x00, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x3f
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xe8, 0x8b, 0x55
+.data1 	0x0c, 0x66, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x10
+.data1 	0x89, 0x55, 0xf0, 0x8b, 0x55, 0x14, 0x89, 0x55
+.data1 	0xec, 0x8b, 0x55, 0x18, 0x66, 0x89, 0x55, 0xe6
+.data1 	0x8b, 0x55, 0x1c, 0x89, 0x55, 0xf4, 0x8b, 0x55
+.data1 	0x20, 0x89, 0x55, 0xf8, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x68, 0x0f, 0x06, 0x00, 0x00, 0x6a, 0xfe, 0xe8
+.data1 	0x24, 0xfe, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x35, 0x20, 0x06, 0x00, 0x00, 0x4e, 0x78
+.data1 	0x09, 0xff, 0x14, 0xb5, 0x40, 0x23, 0x00, 0x00
+.data1 	0xeb, 0xf4, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0xe8, 0xdf, 0xff, 0xff, 0xff, 0x83, 0x3d, 0x24
+.data1 	0x06, 0x00, 0x00, 0x00, 0x74, 0x06, 0xff, 0x15
+.data1 	0x24, 0x06, 0x00, 0x00, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xd4, 0x01, 0x00, 0x00, 0x59, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x75, 0x08, 0x6a
+.data1 	0x01, 0xff, 0x75, 0x10, 0xff, 0x75, 0x0c, 0x56
+.data1 	0xe8, 0x21, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b
+.data1 	0x75, 0x08, 0x6a, 0x00, 0xff, 0x75, 0x10, 0xff
+.data1 	0x75, 0x0c, 0x56, 0xe8, 0x06, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x1c, 0x56, 0x57, 0x8b, 0x75
+.data1 	0x08, 0xc7, 0x45, 0xf8, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xec, 0x01, 0x00, 0x00, 0x00, 0x89, 0x75
+.data1 	0xe8, 0x83, 0x7d, 0x0c, 0x00, 0x74, 0x05, 0x8b
+.data1 	0x45, 0x0c, 0x89, 0x30, 0x0f, 0xbe, 0x06, 0xf6
+.data1 	0x80, 0x31, 0x06, 0x00, 0x00, 0x08, 0x74, 0x03
+.data1 	0x46, 0xeb, 0xf1, 0x0f, 0xbe, 0x06, 0x89, 0xc7
+.data1 	0x83, 0xff, 0x2d, 0x74, 0x05, 0x83, 0xff, 0x2b
+.data1 	0x75, 0x0d, 0x83, 0xff, 0x2d, 0x75, 0x07, 0xc7
+.data1 	0x45, 0xec, 0xff, 0xff, 0xff, 0xff, 0x46, 0x89
+.data1 	0x75, 0xe4, 0x83, 0x7d, 0x10, 0x00, 0x75, 0x2c
+.data1 	0x80, 0x3e, 0x30, 0x75, 0x1e, 0x46, 0x80, 0x3e
+.data1 	0x78, 0x74, 0x05, 0x80, 0x3e, 0x58, 0x75, 0x0a
+.data1 	0xc7, 0x45, 0x10, 0x10, 0x00, 0x00, 0x00, 0x46
+.data1 	0xeb, 0x29, 0xc7, 0x45, 0x10, 0x08, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x20, 0xc7, 0x45, 0x10, 0x0a, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x17, 0x83, 0x7d, 0x10, 0x10
+.data1 	0x75, 0x11, 0x80, 0x3e, 0x30, 0x75, 0x0c, 0x46
+.data1 	0x80, 0x3e, 0x78, 0x74, 0x05, 0x80, 0x3e, 0x58
+.data1 	0x75, 0x01, 0x46, 0x0f, 0xbe, 0x06, 0x89, 0xc7
+.data1 	0x89, 0xfa, 0x83, 0xea, 0x30, 0x83, 0xfa, 0x09
+.data1 	0x77, 0x0a, 0x89, 0xfa, 0x83, 0xea, 0x30, 0x89
+.data1 	0x55, 0xfc, 0xeb, 0x26, 0x89, 0xfa, 0x83, 0xea
+.data1 	0x61, 0x83, 0xfa, 0x19, 0x77, 0x0a, 0x89, 0xfa
+.data1 	0x83, 0xea, 0x57, 0x89, 0x55, 0xfc, 0xeb, 0x12
+.data1 	0x89, 0xfa, 0x83, 0xea, 0x41, 0x83, 0xfa, 0x19
+.data1 	0x77, 0x37, 0x89, 0xfa, 0x83, 0xea, 0x37, 0x89
+.data1 	0x55, 0xfc, 0x8b, 0x55, 0xfc, 0x39, 0x55, 0x10
+.data1 	0x76, 0x27, 0xba, 0xff, 0xff, 0xff, 0xff, 0x2b
+.data1 	0x55, 0xfc, 0x89, 0xd0, 0x31, 0xd2, 0xf7, 0x75
+.data1 	0x10, 0x39, 0x45, 0xf8, 0x76, 0x03, 0xff, 0x45
+.data1 	0xf0, 0x8b, 0x55, 0x10, 0x0f, 0xaf, 0x55, 0xf8
+.data1 	0x03, 0x55, 0xfc, 0x89, 0x55, 0xf8, 0x46, 0xeb
+.data1 	0x92, 0x83, 0x7d, 0x0c, 0x00, 0x74, 0x14, 0x39
+.data1 	0x75, 0xe4, 0x75, 0x0a, 0x8b, 0x55, 0xe8, 0x8b
+.data1 	0x45, 0x0c, 0x89, 0x10, 0xeb, 0x05, 0x8b, 0x45
+.data1 	0x0c, 0x89, 0x30, 0x83, 0x7d, 0xf0, 0x00, 0x75
+.data1 	0x27, 0x83, 0x7d, 0x14, 0x00, 0x74, 0x21, 0x83
+.data1 	0x7d, 0xec, 0x00, 0x79, 0x09, 0x81, 0x7d, 0xf8
+.data1 	0x00, 0x00, 0x00, 0x80, 0x77, 0x0f, 0x83, 0x7d
+.data1 	0xec, 0x00, 0x7e, 0x0c, 0x81, 0x7d, 0xf8, 0xff
+.data1 	0xff, 0xff, 0x7f, 0x76, 0x03, 0xff, 0x45, 0xf0
+.data1 	0x83, 0x7d, 0xf0, 0x00, 0x74, 0x2b, 0xc7, 0x05
+.data1 	0x2c, 0x06, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x14, 0x00, 0x74, 0x14, 0x83, 0x7d
+.data1 	0xec, 0x00, 0x79, 0x07, 0xb8, 0x00, 0x00, 0x00
+.data1 	0x80, 0xeb, 0x17, 0xb8, 0xff, 0xff, 0xff, 0x7f
+.data1 	0xeb, 0x10, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x09, 0x8b, 0x55, 0xec, 0x0f, 0xaf, 0x55, 0xf8
+.data1 	0x89, 0xd0, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0xe9, 0xe3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x8b, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x44, 0x24, 0x04, 0x8b, 0x54, 0x24, 0x08
+.data1 	0x03, 0x54, 0x24, 0x10, 0x89, 0x10, 0x8b, 0x54
+.data1 	0x24, 0x0c, 0x83, 0xd2, 0x00, 0x89, 0x50, 0x04
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x89, 0xe1, 0x31, 0xc0
+.data1 	0x8b, 0x51, 0x04, 0x2b, 0x51, 0x0c, 0x8b, 0x51
+.data1 	0x08, 0x1b, 0x51, 0x10, 0x19, 0xc0, 0x8b, 0x51
+.data1 	0x0c, 0x2b, 0x51, 0x04, 0x8b, 0x51, 0x10, 0x1b
+.data1 	0x51, 0x08, 0x15, 0x00, 0x00, 0x00, 0x00, 0xc3
+.data1 	0x89, 0xe1, 0xff, 0x71, 0x10, 0xc7, 0x41, 0x10
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe8, 0xcd, 0xff, 0xff
+.data1 	0xff, 0x8f, 0x41, 0x10, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x44, 0x24, 0x04, 0x83, 0x7c, 0x24, 0x08
+.data1 	0x00, 0x74, 0x05, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x31, 0xd2, 0x8b, 0x44
+.data1 	0x24, 0x08, 0xf7, 0x74, 0x24, 0x0c, 0x8b, 0x44
+.data1 	0x24, 0x04, 0xf7, 0x74, 0x24, 0x0c, 0xc3, 0x59
+.data1 	0xe8, 0xe7, 0xff, 0xff, 0xff, 0x89, 0xd0, 0xff
+.data1 	0xe1, 0x00, 0x00, 0x00, 0x8b, 0x4c, 0x24, 0x04
+.data1 	0x8b, 0x44, 0x24, 0x08, 0xf7, 0x64, 0x24, 0x0c
+.data1 	0x89, 0x01, 0x89, 0x51, 0x04, 0x89, 0xc8, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x01, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x02
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x03, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0xb9, 0x04, 0x00, 0x00, 0x00
+.data1 	0xcd, 0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x53, 0x8b, 0x5d, 0x08, 0xb9, 0x08, 0x00, 0x00
+.data1 	0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x08
+.data1 	0x8b, 0x75, 0x0c, 0x8b, 0x4d, 0x10, 0xe9, 0xeb
+.data1 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x57, 0xfc, 0x8b, 0x7d, 0x08
+.data1 	0xba, 0x10, 0x00, 0x00, 0x00, 0xd1, 0xe2, 0x89
+.data1 	0xd1, 0x30, 0xc0, 0xf2, 0xae, 0x9c, 0x29, 0xd1
+.data1 	0xf7, 0xd9, 0x29, 0xcf, 0x8a, 0x45, 0x0c, 0xf2
+.data1 	0xae, 0x74, 0x08, 0x9d, 0x75, 0xe7, 0x31, 0xc0
+.data1 	0x5f, 0x5d, 0xc3, 0x58, 0x8d, 0x47, 0xff, 0x5f
+.data1 	0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb9, 0xff, 0xff, 0xff, 0xff, 0xe9, 0xde, 0x01
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0xb9, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe8, 0xf9, 0x01, 0x00, 0x00, 0x8b
+.data1 	0x45, 0x08, 0x5f, 0x5e, 0x5d, 0xc3, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb9, 0xff, 0xff, 0xff, 0xff, 0xe9, 0xfe, 0x01
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x4c, 0x24, 0x0c, 0xe9, 0x9f, 0x01, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x4d, 0x10
+.data1 	0xe8, 0xbb, 0x01, 0x00, 0x00, 0x89, 0xd1, 0xf3
+.data1 	0xaa, 0x8b, 0x45, 0x08, 0x5f, 0x5e, 0x5d, 0xc3
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe0, 0x8d, 0x45, 0xd8, 0x50
+.data1 	0x6a, 0x01, 0x6a, 0x00, 0xe8, 0xcf, 0x01, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xba, 0xff, 0xff, 0xff
+.data1 	0xff, 0x89, 0x55, 0xfc, 0xff, 0xd2, 0xeb, 0xfe
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe8, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xf0, 0x8b, 0x55, 0x10, 0x89, 0x55, 0xf4
+.data1 	0xc7, 0x45, 0xf8, 0x58, 0x22, 0x00, 0x00, 0x8d
+.data1 	0x45, 0xdc, 0x50, 0x6a, 0x47, 0x6a, 0x00, 0xe8
+.data1 	0x94, 0x01, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0x7d, 0x0c, 0x17, 0x76, 0x11, 0xc7, 0x05, 0x2c
+.data1 	0x06, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x11, 0x8b, 0x4d
+.data1 	0x0c, 0xba, 0x01, 0x00, 0x00, 0x00, 0xd3, 0xe2
+.data1 	0x8b, 0x45, 0x08, 0x09, 0x10, 0x31, 0xc0, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0x7d, 0x0c, 0x17
+.data1 	0x76, 0x11, 0xc7, 0x05, 0x2c, 0x06, 0x00, 0x00
+.data1 	0x16, 0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xeb, 0x13, 0x8b, 0x4d, 0x0c, 0xba, 0x01
+.data1 	0x00, 0x00, 0x00, 0xd3, 0xe2, 0xf7, 0xd2, 0x8b
+.data1 	0x45, 0x08, 0x21, 0x10, 0x31, 0xc0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x45, 0x08, 0xc7, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x31, 0xc0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x45, 0x08, 0xc7, 0x00
+.data1 	0xff, 0xff, 0xff, 0x00, 0x31, 0xc0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0x7d, 0x0c, 0x17, 0x76
+.data1 	0x11, 0xc7, 0x05, 0x2c, 0x06, 0x00, 0x00, 0x16
+.data1 	0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x1a, 0x8b, 0x4d, 0x0c, 0xba, 0x01, 0x00
+.data1 	0x00, 0x00, 0xd3, 0xe2, 0x8b, 0x45, 0x08, 0x85
+.data1 	0x10, 0x74, 0x07, 0xb8, 0x01, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x02, 0x31, 0xc0, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0xe9, 0x4e, 0x01, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x08
+.data1 	0x8b, 0x75, 0x0c, 0x8b, 0x4d, 0x10, 0x89, 0xf8
+.data1 	0x29, 0xf0, 0x39, 0xc8, 0x72, 0x2f, 0xfc, 0x83
+.data1 	0xf9, 0x10, 0x72, 0x20, 0x89, 0xf0, 0x09, 0xf8
+.data1 	0xa8, 0x01, 0x75, 0x18, 0xa8, 0x02, 0x75, 0x0d
+.data1 	0x0f, 0xac, 0xc8, 0x02, 0xc1, 0xe9, 0x02, 0xf3
+.data1 	0xa5, 0x0f, 0xa4, 0xc1, 0x02, 0xd1, 0xe9, 0xf3
+.data1 	0x66, 0xa5, 0x11, 0xc9, 0xf3, 0xa4, 0x8b, 0x45
+.data1 	0x08, 0x5f, 0x5e, 0x5d, 0xc3, 0xfd, 0x8d, 0x74
+.data1 	0x0e, 0xff, 0x8d, 0x7c, 0x0f, 0xff, 0xf3, 0xa4
+.data1 	0xfc, 0xeb, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x85, 0xc9, 0x74
+.data1 	0x13, 0x8b, 0x75, 0x08, 0x8b, 0x7d, 0x0c, 0xfc
+.data1 	0xa6, 0x75, 0x09, 0x80, 0x7e, 0xff, 0x00, 0x74
+.data1 	0x03, 0x49, 0x75, 0xf4, 0x0f, 0x97, 0xc0, 0x0f
+.data1 	0x92, 0xc4, 0x28, 0xe0, 0x0f, 0xbe, 0xc0, 0x5f
+.data1 	0x5e, 0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x7d, 0x0c, 0x30, 0xc0, 0x89, 0xca, 0xfc
+.data1 	0xf2, 0xae, 0x29, 0xca, 0x87, 0xca, 0x8b, 0x75
+.data1 	0x0c, 0x8b, 0x7d, 0x08, 0xf3, 0xa4, 0xc3, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x57, 0x8b, 0x7d, 0x08, 0x30
+.data1 	0xc0, 0x89, 0xca, 0x80, 0xf9, 0x01, 0xfc, 0xf2
+.data1 	0xae, 0x75, 0x01, 0x41, 0x89, 0xd0, 0x29, 0xc8
+.data1 	0x5f, 0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x75, 0x10
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x56, 0x04, 0x56, 0xff
+.data1 	0x75, 0x08, 0xe8, 0xf9, 0xfc, 0xff, 0xff, 0x59
+.data1 	0x59, 0x89, 0xc7, 0x85, 0xff, 0x74, 0x03, 0x89
+.data1 	0x7e, 0x04, 0x83, 0x7e, 0x04, 0x00, 0x79, 0x12
+.data1 	0x8b, 0x56, 0x04, 0xf7, 0xda, 0x89, 0x15, 0x2c
+.data1 	0x06, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x03, 0x8b, 0x46, 0x04, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x48, 0x56, 0x8b, 0x75, 0x08, 0x8b, 0x16
+.data1 	0x89, 0x55, 0xb8, 0x8b, 0x56, 0x04, 0x89, 0x55
+.data1 	0xbc, 0x8b, 0x56, 0x08, 0x89, 0x55, 0xec, 0x8b
+.data1 	0x56, 0x0c, 0x89, 0x55, 0xf8, 0x8b, 0x56, 0x10
+.data1 	0x89, 0x55, 0xd0, 0x8b, 0x55, 0x0c, 0x89, 0x55
+.data1 	0xe4, 0x8d, 0x45, 0xb8, 0x50, 0xe8, 0x04, 0x00
+.data1 	0x00, 0x00, 0x59, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x04, 0x56, 0x8b, 0x75, 0x08
+.data1 	0x8d, 0x45, 0xfc, 0x50, 0xe8, 0x4f, 0xfe, 0xff
+.data1 	0xff, 0x59, 0x6a, 0x00, 0x8d, 0x45, 0xfc, 0x50
+.data1 	0x6a, 0x02, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x8b, 0x56, 0x04, 0x89, 0x15, 0x1c
+.data1 	0x23, 0x00, 0x00, 0x8b, 0x16, 0x89, 0x15, 0x14
+.data1 	0x23, 0x00, 0x00, 0x89, 0x35, 0x24, 0x23, 0x00
+.data1 	0x00, 0x68, 0x08, 0x23, 0x00, 0x00, 0x6a, 0x4b
+.data1 	0x6a, 0x00, 0xe8, 0x39, 0xff, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x83, 0x7d
+.data1 	0x0c, 0x00, 0x75, 0x10, 0xc7, 0x45, 0xe4, 0x04
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x45, 0xf0, 0x00, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x0e, 0x8b, 0x55, 0x08, 0x89
+.data1 	0x55, 0xe4, 0x8b, 0x45, 0x0c, 0x8b, 0x10, 0x89
+.data1 	0x55, 0xf0, 0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x4a
+.data1 	0x6a, 0x00, 0xe8, 0xf9, 0xfe, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x85, 0xc0, 0x79, 0x07, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xeb, 0x11, 0x83, 0x7d, 0x10
+.data1 	0x00, 0x74, 0x08, 0x8b, 0x55, 0xf0, 0x8b, 0x45
+.data1 	0x10, 0x89, 0x10, 0x8b, 0x45, 0xe0, 0xc9, 0xc3
+.data1 	0x89, 0xe3, 0x89, 0xf0, 0x89, 0xfa, 0x8b, 0x7b
+.data1 	0x04, 0x8b, 0x73, 0x08, 0xf3, 0xa5, 0x89, 0xc6
+.data1 	0x89, 0xd7, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x13, 0x2b, 0x43, 0x04, 0x3b, 0x43, 0x08
+.data1 	0x77, 0x0c, 0xc1, 0xe0, 0x02, 0x01, 0xc3, 0x8b
+.data1 	0x5b, 0x0c, 0x85, 0xdb, 0x75, 0x11, 0x89, 0xd3
+.data1 	0x85, 0xdb, 0x75, 0x0b, 0xb8, 0x14, 0x00, 0x00
+.data1 	0x00, 0x50, 0xe9, 0x2d, 0x00, 0x00, 0x00, 0xff
+.data1 	0xe3, 0x00, 0x00, 0x00, 0x8b, 0x13, 0x8b, 0x4b
+.data1 	0x04, 0x83, 0xc3, 0x08, 0x49, 0x7c, 0x18, 0x3b
+.data1 	0x03, 0x75, 0xf6, 0x8b, 0x5b, 0x04, 0x85, 0xdb
+.data1 	0x75, 0x0b, 0xb8, 0x14, 0x00, 0x00, 0x00, 0x50
+.data1 	0xe9, 0x07, 0x00, 0x00, 0x00, 0xff, 0xe3, 0x89
+.data1 	0xd3, 0xeb, 0xeb, 0x00, 0xe8, 0x0f, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x73, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00
+.data1 	0x31, 0xdb, 0x87, 0x1d, 0x34, 0x07, 0x00, 0x00
+.data1 	0x85, 0xdb, 0x74, 0x05, 0x50, 0xff, 0xd3, 0x58
+.data1 	0xc3, 0x50, 0xe8, 0xe1, 0xff, 0xff, 0xff, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00
+.data1 	0x62, 0x69, 0x6f, 0x73, 0x5f, 0x72, 0x65, 0x6d
+.data1 	0x61, 0x70, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x61
+.data1 	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x42, 0x49, 0x4f, 0x53, 0x00, 0x00, 0x00, 0x00
+.data1 	0x73, 0x79, 0x73, 0x5f, 0x76, 0x69, 0x72, 0x63
+.data1 	0x6f, 0x70, 0x79, 0x20, 0x66, 0x61, 0x69, 0x6c
+.data1 	0x65, 0x64, 0x00, 0x00, 0x42, 0x49, 0x4f, 0x53
+.data1 	0x5f, 0x57, 0x49, 0x4e, 0x49, 0x00, 0x00, 0x00
+.data1 	0x41, 0x73, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f
+.data1 	0x6e, 0x20, 0x22, 0x63, 0x68, 0x75, 0x6e, 0x6b
+.data1 	0x20, 0x3c, 0x3d, 0x20, 0x72, 0x65, 0x6d, 0x5f
+.data1 	0x62, 0x75, 0x66, 0x5f, 0x73, 0x69, 0x7a, 0x65
+.data1 	0x22, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64
+.data1 	0x2c, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x22
+.data1 	0x62, 0x69, 0x6f, 0x73, 0x5f, 0x77, 0x69, 0x6e
+.data1 	0x69, 0x2e, 0x63, 0x22, 0x2c, 0x20, 0x6c, 0x69
+.data1 	0x6e, 0x65, 0x20, 0x32, 0x38, 0x30, 0x0a, 0x00
+.data1 	0x42, 0x49, 0x4f, 0x53, 0x20, 0x63, 0x61, 0x6c
+.data1 	0x6c, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x42, 0x49, 0x4f, 0x53
+.data1 	0x5f, 0x57, 0x49, 0x4e, 0x49, 0x00, 0x00, 0x00
+.data1 	0x73, 0x79, 0x73, 0x5f, 0x76, 0x69, 0x72, 0x63
+.data1 	0x6f, 0x70, 0x79, 0x20, 0x66, 0x61, 0x69, 0x6c
+.data1 	0x65, 0x64, 0x00, 0x00, 0x42, 0x49, 0x4f, 0x53
+.data1 	0x5f, 0x57, 0x49, 0x4e, 0x49, 0x00, 0x00, 0x00
+.data1 	0x73, 0x79, 0x73, 0x5f, 0x76, 0x69, 0x72, 0x63
+.data1 	0x6f, 0x70, 0x79, 0x20, 0x66, 0x61, 0x69, 0x6c
+.data1 	0x65, 0x64, 0x00, 0x00, 0x42, 0x49, 0x4f, 0x53
+.data1 	0x5f, 0x57, 0x49, 0x4e, 0x49, 0x00, 0x00, 0x00
+.data1 	0x41, 0x73, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f
+.data1 	0x6e, 0x20, 0x22, 0x63, 0x68, 0x75, 0x6e, 0x6b
+.data1 	0x20, 0x3c, 0x3d, 0x20, 0x72, 0x65, 0x6d, 0x5f
+.data1 	0x62, 0x75, 0x66, 0x5f, 0x73, 0x69, 0x7a, 0x65
+.data1 	0x22, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64
+.data1 	0x2c, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x22
+.data1 	0x62, 0x69, 0x6f, 0x73, 0x5f, 0x77, 0x69, 0x6e
+.data1 	0x69, 0x2e, 0x63, 0x22, 0x2c, 0x20, 0x6c, 0x69
+.data1 	0x6e, 0x65, 0x20, 0x32, 0x31, 0x36, 0x0a, 0x00
+.data1 	0x41, 0x73, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f
+.data1 	0x6e, 0x20, 0x22, 0x72, 0x65, 0x6d, 0x5f, 0x62
+.data1 	0x75, 0x66, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x20
+.data1 	0x21, 0x3d, 0x20, 0x30, 0x22, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x66, 0x69
+.data1 	0x6c, 0x65, 0x20, 0x22, 0x62, 0x69, 0x6f, 0x73
+.data1 	0x5f, 0x77, 0x69, 0x6e, 0x69, 0x2e, 0x63, 0x22
+.data1 	0x2c, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x31
+.data1 	0x38, 0x37, 0x0a, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x25, 0x64, 0x20, 0x63, 0x79, 0x6c, 0x69, 0x6e
+.data1 	0x64, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x25, 0x64
+.data1 	0x20, 0x68, 0x65, 0x61, 0x64, 0x73, 0x2c, 0x20
+.data1 	0x25, 0x64, 0x20, 0x73, 0x65, 0x63, 0x74, 0x6f
+.data1 	0x72, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20, 0x74
+.data1 	0x72, 0x61, 0x63, 0x6b, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x25, 0x73, 0x3a, 0x20, 0x25, 0x6c, 0x75, 0x20
+.data1 	0x73, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x73, 0x79, 0x73, 0x5f
+.data1 	0x76, 0x69, 0x72, 0x63, 0x6f, 0x70, 0x79, 0x20
+.data1 	0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x0a, 0x00
+.data1 	0x42, 0x49, 0x4f, 0x53, 0x5f, 0x57, 0x49, 0x4e
+.data1 	0x49, 0x00, 0x00, 0x00, 0x42, 0x49, 0x4f, 0x53
+.data1 	0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x42, 0x49, 0x4f, 0x53, 0x5f, 0x57, 0x49, 0x4e
+.data1 	0x49, 0x00, 0x00, 0x00, 0x73, 0x79, 0x73, 0x5f
+.data1 	0x76, 0x69, 0x72, 0x63, 0x6f, 0x70, 0x79, 0x20
+.data1 	0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x0a, 0x00
+.data1 	0x42, 0x49, 0x4f, 0x53, 0x5f, 0x57, 0x49, 0x4e
+.data1 	0x49, 0x00, 0x00, 0x00, 0x42, 0x49, 0x4f, 0x53
+.data1 	0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x42, 0x49, 0x4f, 0x53, 0x5f, 0x57, 0x49, 0x4e
+.data1 	0x49, 0x00, 0x00, 0x00, 0x42, 0x49, 0x4f, 0x53
+.data1 	0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x42, 0x49, 0x4f, 0x53, 0x5f, 0x57, 0x49, 0x4e
+.data1 	0x49, 0x00, 0x00, 0x00, 0x62, 0x61, 0x64, 0x20
+.data1 	0x42, 0x49, 0x4f, 0x53, 0x20, 0x62, 0x75, 0x66
+.data1 	0x66, 0x65, 0x72, 0x2c, 0x20, 0x70, 0x68, 0x79
+.data1 	0x73, 0x00, 0x00, 0x00, 0x42, 0x49, 0x4f, 0x53
+.data1 	0x5f, 0x57, 0x49, 0x4e, 0x49, 0x00, 0x00, 0x00
+.data1 	0x73, 0x79, 0x73, 0x5f, 0x75, 0x6d, 0x61, 0x70
+.data1 	0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x00
+.data1 	0x42, 0x49, 0x4f, 0x53, 0x5f, 0x57, 0x49, 0x4e
+.data1 	0x49, 0x00, 0x00, 0x00, 0x73, 0x79, 0x73, 0x5f
+.data1 	0x67, 0x65, 0x74, 0x62, 0x69, 0x6f, 0x73, 0x62
+.data1 	0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x42, 0x49, 0x4f, 0x53, 0x5f, 0x57, 0x49, 0x4e
+.data1 	0x49, 0x00, 0x00, 0x00, 0xac, 0x0b, 0x00, 0x00
+.data1 	0x0e, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00
+.data1 	0x1f, 0x0b, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00
+.data1 	0x41, 0x0b, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00
+.data1 	0x41, 0x0b, 0x00, 0x00, 0x05, 0x04, 0x00, 0x00
+.data1 	0x0e, 0x0b, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00
+.data1 	0xec, 0x0a, 0x00, 0x00, 0x07, 0x04, 0x00, 0x00
+.data1 	0xfd, 0x0a, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00
+.data1 	0x54, 0x0b, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00
+.data1 	0x54, 0x0b, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00
+.data1 	0x30, 0x0b, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00
+.data1 	0x8f, 0x0b, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00
+.data1 	0x80, 0x0b, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00
+.data1 	0x67, 0x0b, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00
+.data1 	0x80, 0x0b, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00
+.data1 	0x9e, 0x0b, 0x00, 0x00, 0x62, 0x61, 0x64, 0x20
+.data1 	0x49, 0x2f, 0x4f, 0x20, 0x76, 0x65, 0x63, 0x74
+.data1 	0x6f, 0x72, 0x20, 0x62, 0x79, 0x00, 0x00, 0x00
+.data1 	0xe5, 0x0d, 0x00, 0x00, 0x05, 0x04, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0xde, 0x0d, 0x00, 0x00
+.data1 	0xd3, 0x0d, 0x00, 0x00, 0xda, 0x0d, 0x00, 0x00
+.data1 	0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x9f, 0x0f, 0x00, 0x00
+.data1 	0xa5, 0x0f, 0x00, 0x00, 0xb4, 0x0f, 0x00, 0x00
+.data1 	0x73, 0x15, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
+.data1 	0x2a, 0x00, 0x00, 0x00, 0xb3, 0x14, 0x00, 0x00
+.data1 	0x63, 0x00, 0x00, 0x00, 0xe3, 0x14, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0xbf, 0x14, 0x00, 0x00
+.data1 	0x6f, 0x00, 0x00, 0x00, 0xcb, 0x14, 0x00, 0x00
+.data1 	0x78, 0x00, 0x00, 0x00, 0xd7, 0x14, 0x00, 0x00
+.data1 	0x6f, 0x6e, 0x00, 0x00, 0x6f, 0x66, 0x66, 0x00
+.data1 	0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x3a
+.data1 	0x20, 0x67, 0x65, 0x74, 0x5f, 0x6d, 0x6f, 0x6e
+.data1 	0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x28, 0x29
+.data1 	0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20
+.data1 	0x69, 0x6e, 0x20, 0x65, 0x6e, 0x76, 0x5f, 0x70
+.data1 	0x61, 0x72, 0x73, 0x65, 0x28, 0x29, 0x3a, 0x20
+.data1 	0x25, 0x64, 0x0a, 0x00, 0x82, 0x18, 0x00, 0x00
+.data1 	0x09, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00
+.data1 	0xb0, 0x17, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00
+.data1 	0x39, 0x17, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00
+.data1 	0x94, 0x17, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00
+.data1 	0x05, 0x17, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00
+.data1 	0x30, 0x17, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00
+.data1 	0x39, 0x17, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00
+.data1 	0xc2, 0x17, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00
+.data1 	0x47, 0x17, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
+.data1 	0x40, 0x17, 0x00, 0x00, 0x53, 0x59, 0x53, 0x5f
+.data1 	0x47, 0x45, 0x54, 0x49, 0x4e, 0x46, 0x4f, 0x3a
+.data1 	0x20, 0x25, 0x64, 0x20, 0x28, 0x73, 0x69, 0x7a
+.data1 	0x65, 0x20, 0x25, 0x75, 0x29, 0x0a, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x65, 0x6e, 0x76, 0x69
+.data1 	0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20
+.data1 	0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x3a
+.data1 	0x20, 0x27, 0x25, 0x73, 0x20, 0x3d, 0x20, 0x25
+.data1 	0x73, 0x27, 0x0a, 0x00, 0x57, 0x41, 0x52, 0x4e
+.data1 	0x49, 0x4e, 0x47, 0x3a, 0x20, 0x67, 0x65, 0x74
+.data1 	0x5f, 0x6d, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x72
+.data1 	0x61, 0x6d, 0x28, 0x29, 0x20, 0x66, 0x61, 0x69
+.data1 	0x6c, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x65
+.data1 	0x6e, 0x76, 0x5f, 0x70, 0x61, 0x6e, 0x69, 0x63
+.data1 	0x28, 0x29, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00
+.data1 	0x25, 0x73, 0x00, 0x00, 0x50, 0x61, 0x6e, 0x69
+.data1 	0x63, 0x20, 0x69, 0x6e, 0x20, 0x25, 0x73, 0x3a
+.data1 	0x20, 0x25, 0x73, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x50, 0x61, 0x6e, 0x69, 0x63, 0x20, 0x69, 0x6e
+.data1 	0x20, 0x25, 0x73, 0x3a, 0x20, 0x25, 0x73, 0x3a
+.data1 	0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x30, 0x23, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x87, 0x01, 0x00, 0x00
+.data1 	0x21, 0x06, 0x00, 0x00, 0x8d, 0x06, 0x00, 0x00
+.data1 	0x22, 0x0e, 0x00, 0x00, 0xd5, 0x00, 0x00, 0x00
+.data1 	0xa2, 0x01, 0x00, 0x00, 0x0f, 0x0e, 0x00, 0x00
+.data1 	0x08, 0x0a, 0x00, 0x00, 0xfe, 0x0d, 0x00, 0x00
+.data1 	0x03, 0x0e, 0x00, 0x00, 0x14, 0x0e, 0x00, 0x00
+.data1 	0x1b, 0x0e, 0x00, 0x00, 0x39, 0x0a, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x62, 0x69, 0x6f, 0x73
+.data1 	0x2d, 0x64, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x6e, 0x6f, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00
+.data1 	0x3a, 0x2c, 0x3b, 0x2e, 0x00, 0x00, 0x00, 0x00
+.data1 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
+.data1 	0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46
+.data1 	0x00, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33
+.data1 	0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62
+.data1 	0x63, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x00
+.data1 	0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+.data1 	0xce, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x3c, 0x75, 0x6e, 0x6b
+.data1 	0x6e, 0x6f, 0x77, 0x6e, 0x3e, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x53, 0x53, 0x53, 0x53, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x20, 0x28, 0x28, 0x28, 0x28, 0x28, 0x20
+.data1 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04
+.data1 	0x04, 0x04, 0x04, 0x10, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x10, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41
+.data1 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+.data1 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+.data1 	0x01, 0x01, 0x01, 0x01, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x10, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42
+.data1 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+.data1 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+.data1 	0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10
+.data1 	0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x03, 0x20, 0x10, 0x20, 0x00, 0x00, 0x00
+.data1 	0x80, 0x19, 0x00, 0x00, 0xb4, 0x09, 0x00, 0x00
+.data1 	0x94, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x48, 0xd2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0xed, 0x8b, 0x04, 0x24, 0x8d, 0x54, 0x24
+.data1 	0x04, 0x8d, 0x4c, 0x84, 0x08, 0xbb, 0xc0, 0x07
+.data1 	0x00, 0x00, 0x81, 0xfb, 0xb4, 0x09, 0x00, 0x00
+.data1 	0x73, 0x13, 0xf6, 0xc3, 0x03, 0x75, 0x0e, 0x81
+.data1 	0x3b, 0x53, 0x53, 0x53, 0x53, 0x75, 0x06, 0x89
+.data1 	0x1d, 0x9c, 0x07, 0x00, 0x00, 0x8b, 0x1d, 0x9c
+.data1 	0x07, 0x00, 0x00, 0x89, 0x0b, 0x51, 0x52, 0x50
+.data1 	0x0f, 0x01, 0xe0, 0xa8, 0x04, 0x0f, 0x94, 0x05
+.data1 	0xc0, 0x09, 0x00, 0x00, 0xe8, 0x07, 0x00, 0x00
+.data1 	0x00, 0x50, 0xe8, 0x42, 0x03, 0x00, 0x00, 0xf4
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x40, 0x56, 0x57
+.data1 	0xbf, 0xa0, 0x07, 0x00, 0x00, 0x83, 0xc4, 0xf4
+.data1 	0x89, 0xe0, 0x89, 0xc6, 0xc7, 0x45, 0xd8, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xd8, 0x00, 0x7e
+.data1 	0x0b, 0xff, 0x4d, 0xd8, 0x8a, 0x07, 0x47, 0x88
+.data1 	0x06, 0x46, 0xeb, 0xef, 0x8d, 0x75, 0xce, 0x89
+.data1 	0xe0, 0x89, 0xc7, 0xc7, 0x45, 0xd8, 0x0a, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7d, 0xd8, 0x00, 0x7e, 0x0b
+.data1 	0xff, 0x4d, 0xd8, 0x8a, 0x07, 0x47, 0x88, 0x06
+.data1 	0x46, 0xeb, 0xef, 0x83, 0xc4, 0x0c, 0xbb, 0xac
+.data1 	0x07, 0x00, 0x00, 0xb9, 0x0c, 0x00, 0x00, 0x00
+.data1 	0xe8, 0x94, 0x18, 0x00, 0x00, 0x8d, 0x75, 0xc2
+.data1 	0x89, 0xe0, 0x89, 0xc7, 0xc7, 0x45, 0xd8, 0x0c
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xd8, 0x00, 0x7e
+.data1 	0x0b, 0xff, 0x4d, 0xd8, 0x8a, 0x07, 0x47, 0x88
+.data1 	0x06, 0x46, 0xeb, 0xef, 0x83, 0xc4, 0x0c, 0xc7
+.data1 	0x45, 0xec, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x45
+.data1 	0xfc, 0x00, 0x00, 0x00, 0x00, 0x83, 0x7d, 0xfc
+.data1 	0x08, 0x0f, 0x8d, 0x85, 0x02, 0x00, 0x00, 0xba
+.data1 	0x30, 0x00, 0x00, 0x00, 0x03, 0x55, 0xfc, 0x88
+.data1 	0x55, 0xd6, 0x6a, 0x00, 0x8d, 0x45, 0xce, 0x50
+.data1 	0xe8, 0x37, 0x03, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0x45, 0xf4, 0x85, 0xc0, 0x79, 0x35, 0x83, 0x3d
+.data1 	0xc4, 0x07, 0x00, 0x00, 0x06, 0x0f, 0x84, 0x51
+.data1 	0x02, 0x00, 0x00, 0xff, 0x35, 0xc4, 0x07, 0x00
+.data1 	0x00, 0xe8, 0x96, 0x02, 0x00, 0x00, 0x59, 0x50
+.data1 	0x8d, 0x45, 0xce, 0x50, 0x68, 0x94, 0x00, 0x00
+.data1 	0x00, 0x68, 0xf8, 0x07, 0x00, 0x00, 0xe8, 0xa5
+.data1 	0x02, 0x00, 0x00, 0x83, 0xc4, 0x10, 0xe9, 0x29
+.data1 	0x02, 0x00, 0x00, 0x6a, 0x00, 0x68, 0x00, 0x80
+.data1 	0x00, 0x00, 0xff, 0x75, 0xf4, 0xe8, 0xe2, 0x02
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45, 0xe8
+.data1 	0x3d, 0x00, 0x80, 0x00, 0x00, 0x74, 0x0e, 0xff
+.data1 	0x75, 0xf4, 0xe8, 0xc5, 0x02, 0x00, 0x00, 0x59
+.data1 	0xe9, 0xff, 0x01, 0x00, 0x00, 0x68, 0x00, 0x08
+.data1 	0x00, 0x00, 0x68, 0xc8, 0x09, 0x00, 0x00, 0xff
+.data1 	0x75, 0xf4, 0xe8, 0xc5, 0x02, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0x45, 0xf8, 0x3d, 0x00, 0x08
+.data1 	0x00, 0x00, 0x74, 0x31, 0xff, 0x35, 0xc4, 0x07
+.data1 	0x00, 0x00, 0xe8, 0x25, 0x02, 0x00, 0x00, 0x59
+.data1 	0x50, 0x8d, 0x45, 0xce, 0x50, 0x68, 0x6c, 0x00
+.data1 	0x00, 0x00, 0x68, 0xf8, 0x07, 0x00, 0x00, 0xe8
+.data1 	0x34, 0x02, 0x00, 0x00, 0x83, 0xc4, 0x10, 0xff
+.data1 	0x75, 0xf4, 0xe8, 0x75, 0x02, 0x00, 0x00, 0x59
+.data1 	0xe9, 0xaf, 0x01, 0x00, 0x00, 0xff, 0x75, 0xf4
+.data1 	0xe8, 0x67, 0x02, 0x00, 0x00, 0x59, 0x80, 0x3d
+.data1 	0xc8, 0x09, 0x00, 0x00, 0x01, 0x0f, 0x85, 0x99
+.data1 	0x01, 0x00, 0x00, 0x80, 0x3d, 0xc9, 0x09, 0x00
+.data1 	0x00, 0x43, 0x0f, 0x85, 0x8c, 0x01, 0x00, 0x00
+.data1 	0x80, 0x3d, 0xca, 0x09, 0x00, 0x00, 0x44, 0x0f
+.data1 	0x85, 0x7f, 0x01, 0x00, 0x00, 0x80, 0x3d, 0xcb
+.data1 	0x09, 0x00, 0x00, 0x30, 0x0f, 0x85, 0x72, 0x01
+.data1 	0x00, 0x00, 0x80, 0x3d, 0xcc, 0x09, 0x00, 0x00
+.data1 	0x30, 0x0f, 0x85, 0x65, 0x01, 0x00, 0x00, 0x80
+.data1 	0x3d, 0xcd, 0x09, 0x00, 0x00, 0x31, 0x0f, 0x85
+.data1 	0x58, 0x01, 0x00, 0x00, 0x80, 0x3d, 0xce, 0x09
+.data1 	0x00, 0x00, 0x01, 0x0f, 0x85, 0x4b, 0x01, 0x00
+.data1 	0x00, 0x6a, 0x05, 0x68, 0x64, 0x00, 0x00, 0x00
+.data1 	0x68, 0xf0, 0x09, 0x00, 0x00, 0xe8, 0x1a, 0x02
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x0f
+.data1 	0x85, 0x2f, 0x01, 0x00, 0x00, 0xc7, 0x45, 0xec
+.data1 	0x01, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xf0, 0x01
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xf0, 0x02, 0x0f
+.data1 	0x8f, 0xf9, 0x00, 0x00, 0x00, 0xba, 0x30, 0x00
+.data1 	0x00, 0x00, 0x03, 0x55, 0xfc, 0x88, 0x55, 0xca
+.data1 	0xba, 0x30, 0x00, 0x00, 0x00, 0x03, 0x55, 0xf0
+.data1 	0x88, 0x55, 0xcc, 0x6a, 0x00, 0x8d, 0x45, 0xc2
+.data1 	0x50, 0xe8, 0xc6, 0x01, 0x00, 0x00, 0x59, 0x59
+.data1 	0x89, 0x45, 0xf4, 0x85, 0xc0, 0x79, 0x38, 0x83
+.data1 	0x3d, 0xc4, 0x07, 0x00, 0x00, 0x06, 0x74, 0x23
+.data1 	0xff, 0x35, 0xc4, 0x07, 0x00, 0x00, 0xe8, 0x29
+.data1 	0x01, 0x00, 0x00, 0x59, 0x50, 0x8d, 0x45, 0xc2
+.data1 	0x50, 0x68, 0x4c, 0x00, 0x00, 0x00, 0x68, 0xf8
+.data1 	0x07, 0x00, 0x00, 0xe8, 0x38, 0x01, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0xc7, 0x45, 0xec, 0x00, 0x00
+.data1 	0x00, 0x00, 0xe9, 0x97, 0x00, 0x00, 0x00, 0x68
+.data1 	0x00, 0x08, 0x00, 0x00, 0x68, 0xc8, 0x09, 0x00
+.data1 	0x00, 0xff, 0x75, 0xf4, 0xe8, 0x7b, 0x01, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45, 0xf8, 0x3d
+.data1 	0x00, 0x08, 0x00, 0x00, 0x74, 0x35, 0xff, 0x35
+.data1 	0xc4, 0x07, 0x00, 0x00, 0xe8, 0xdb, 0x00, 0x00
+.data1 	0x00, 0x59, 0x50, 0x8d, 0x45, 0xc2, 0x50, 0x68
+.data1 	0x20, 0x00, 0x00, 0x00, 0x68, 0xf8, 0x07, 0x00
+.data1 	0x00, 0xe8, 0xea, 0x00, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x10, 0xff, 0x75, 0xf4, 0xe8, 0x2b, 0x01, 0x00
+.data1 	0x00, 0x59, 0xc7, 0x45, 0xec, 0x00, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x43, 0xff, 0x75, 0xf4, 0xe8, 0x19
+.data1 	0x01, 0x00, 0x00, 0x59, 0xba, 0xe0, 0x0d, 0x00
+.data1 	0x00, 0x89, 0x55, 0xe4, 0x0f, 0xb7, 0x0a, 0x81
+.data1 	0xf9, 0x5a, 0x4d, 0x00, 0x00, 0x74, 0x1f, 0x8d
+.data1 	0x45, 0xc2, 0x50, 0x68, 0x08, 0x00, 0x00, 0x00
+.data1 	0x68, 0xf8, 0x07, 0x00, 0x00, 0xe8, 0xa6, 0x00
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc7, 0x45, 0xec
+.data1 	0x00, 0x00, 0x00, 0x00, 0xeb, 0x08, 0xff, 0x45
+.data1 	0xf0, 0xe9, 0xfd, 0xfe, 0xff, 0xff, 0x83, 0x7d
+.data1 	0xec, 0x00, 0x74, 0x18, 0x8d, 0x45, 0xce, 0x50
+.data1 	0x68, 0x04, 0x00, 0x00, 0x00, 0xe8, 0x9e, 0x00
+.data1 	0x00, 0x00, 0x59, 0x59, 0x6a, 0x00, 0xe8, 0x2e
+.data1 	0x00, 0x00, 0x00, 0x59, 0xff, 0x45, 0xfc, 0xe9
+.data1 	0x71, 0xfd, 0xff, 0xff, 0xb8, 0x01, 0x00, 0x00
+.data1 	0x00, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x35, 0xb8, 0x07
+.data1 	0x00, 0x00, 0x4e, 0x78, 0x09, 0xff, 0x14, 0xb5
+.data1 	0xc8, 0x11, 0x00, 0x00, 0xeb, 0xf4, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0xe8, 0xdf, 0xff, 0xff
+.data1 	0xff, 0x83, 0x3d, 0xbc, 0x07, 0x00, 0x00, 0x00
+.data1 	0x74, 0x06, 0xff, 0x15, 0xbc, 0x07, 0x00, 0x00
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x6c, 0x00, 0x00, 0x00
+.data1 	0x59, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x75, 0x08, 0x85, 0xf6, 0x78, 0x08, 0x39
+.data1 	0x35, 0xa0, 0x09, 0x00, 0x00, 0x7f, 0x07, 0xb8
+.data1 	0xac, 0x00, 0x00, 0x00, 0xeb, 0x07, 0x8b, 0x04
+.data1 	0xb5, 0x70, 0x08, 0x00, 0x00, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x8d, 0x55
+.data1 	0x10, 0x89, 0x55, 0xfc, 0xff, 0x75, 0x08, 0xff
+.data1 	0x75, 0xfc, 0xff, 0x75, 0x0c, 0xe8, 0x70, 0x03
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x8d, 0x55
+.data1 	0x0c, 0x89, 0x55, 0xfc, 0x68, 0xe0, 0x07, 0x00
+.data1 	0x00, 0xff, 0x75, 0xfc, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x4e, 0x03, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0xe9, 0x33, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0x53, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0x6b, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0x9b, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0xf7, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x4c, 0x24, 0x0c
+.data1 	0xe9, 0x6b, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe0
+.data1 	0x8d, 0x45, 0xd8, 0x50, 0x6a, 0x01, 0x6a, 0x00
+.data1 	0xe8, 0x9f, 0x10, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xba, 0xff, 0xff, 0xff, 0xff, 0x89, 0x55, 0xfc
+.data1 	0xff, 0xd2, 0xeb, 0xfe, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x06, 0x6a, 0x01
+.data1 	0xe8, 0x77, 0x10, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf0, 0x8b, 0x55
+.data1 	0x10, 0x89, 0x55, 0xe8, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x6a, 0x13, 0x6a, 0x01, 0xe8, 0x4b, 0x10, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x79, 0x07
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x03, 0x8b
+.data1 	0x45, 0xf0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x56, 0x8d, 0x75, 0x10, 0x8b, 0x55
+.data1 	0x0c, 0xf6, 0xc2, 0x40, 0x74, 0x2a, 0xff, 0x75
+.data1 	0x08, 0xe8, 0xfa, 0x0b, 0x00, 0x00, 0x59, 0x05
+.data1 	0x01, 0x00, 0x00, 0x00, 0x89, 0x45, 0xe0, 0x8b
+.data1 	0x55, 0x0c, 0x89, 0x55, 0xe4, 0x8d, 0x56, 0x04
+.data1 	0x89, 0xd6, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xe8
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xec, 0xeb, 0x14
+.data1 	0x8d, 0x45, 0xd8, 0x50, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xb4, 0x0f, 0x00, 0x00, 0x59, 0x59, 0x8b, 0x55
+.data1 	0x0c, 0x89, 0x55, 0xe4, 0x8d, 0x45, 0xd8, 0x50
+.data1 	0x6a, 0x05, 0x6a, 0x01, 0xe8, 0xdb, 0x0f, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x5e, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x10, 0x89
+.data1 	0x55, 0xe8, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf0
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x03, 0x6a, 0x01
+.data1 	0xe8, 0xaf, 0x0f, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x08, 0x56, 0x57, 0x8b, 0x75, 0x08, 0x80
+.data1 	0x3e, 0x2a, 0x75, 0x18, 0x8b, 0x45, 0x10, 0x8b
+.data1 	0x10, 0x83, 0xc2, 0x04, 0x8b, 0x45, 0x10, 0x89
+.data1 	0x10, 0x8b, 0x52, 0xfc, 0x8b, 0x45, 0x0c, 0x89
+.data1 	0x10, 0x46, 0xeb, 0x25, 0x31, 0xff, 0x0f, 0xbe
+.data1 	0x06, 0x2d, 0x30, 0x00, 0x00, 0x00, 0x89, 0x45
+.data1 	0xf8, 0x78, 0x11, 0x83, 0x7d, 0xf8, 0x09, 0x7f
+.data1 	0x0b, 0x6b, 0xdf, 0x0a, 0x8b, 0x7d, 0xf8, 0x01
+.data1 	0xdf, 0x46, 0xeb, 0xe2, 0x8b, 0x45, 0x0c, 0x89
+.data1 	0x38, 0x89, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x10, 0x56, 0x57, 0x8b
+.data1 	0x75, 0x10, 0x8b, 0x7d, 0x08, 0x89, 0x75, 0xf4
+.data1 	0xe9, 0x80, 0x00, 0x00, 0x00, 0x83, 0x7d, 0x1c
+.data1 	0x00, 0x74, 0x18, 0x8b, 0x17, 0x83, 0xc2, 0x04
+.data1 	0x89, 0x17, 0x8b, 0x42, 0xfc, 0x0f, 0xbf, 0xc0
+.data1 	0x0f, 0xbf, 0xc0, 0x89, 0x45, 0xfc, 0xe9, 0x76
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x17, 0x83, 0xc2, 0x04
+.data1 	0x89, 0x17, 0xb9, 0xff, 0xff, 0x00, 0x00, 0x23
+.data1 	0x4a, 0xfc, 0x89, 0x4d, 0xf8, 0xe9, 0x5f, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7d, 0x1c, 0x00, 0x74, 0x12
+.data1 	0x8b, 0x17, 0x83, 0xc2, 0x04, 0x89, 0x17, 0x8b
+.data1 	0x52, 0xfc, 0x89, 0x55, 0xfc, 0xe9, 0x47, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x17, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x17, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xf8, 0xeb
+.data1 	0x38, 0x83, 0x7d, 0x1c, 0x00, 0x74, 0x0f, 0x8b
+.data1 	0x17, 0x83, 0xc2, 0x04, 0x89, 0x17, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0xfc, 0xeb, 0x23, 0x8b, 0x17
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x17, 0x8b, 0x52, 0xfc
+.data1 	0x89, 0x55, 0xf8, 0xeb, 0x14, 0xba, 0x60, 0x00
+.data1 	0x00, 0x00, 0x23, 0x55, 0x0c, 0xbb, 0x34, 0x06
+.data1 	0x00, 0x00, 0x89, 0xd0, 0xe9, 0x8b, 0x12, 0x00
+.data1 	0x00, 0x83, 0x7d, 0x1c, 0x00, 0x74, 0x2f, 0x83
+.data1 	0x7d, 0xfc, 0x00, 0x79, 0x09, 0xc6, 0x06, 0x2d
+.data1 	0x46, 0xf7, 0x5d, 0xfc, 0xeb, 0x1a, 0x8b, 0x55
+.data1 	0x0c, 0xf6, 0xc2, 0x02, 0x74, 0x06, 0xc6, 0x06
+.data1 	0x2b, 0x46, 0xeb, 0x0c, 0x8b, 0x55, 0x0c, 0xf6
+.data1 	0xc2, 0x04, 0x74, 0x04, 0xc6, 0x06, 0x20, 0x46
+.data1 	0x8b, 0x55, 0xfc, 0x89, 0x55, 0xf8, 0x8b, 0x55
+.data1 	0x0c, 0xf6, 0xc2, 0x08, 0x74, 0x0a, 0x80, 0x7d
+.data1 	0x14, 0x6f, 0x75, 0x04, 0xc6, 0x06, 0x30, 0x46
+.data1 	0x83, 0x7d, 0xf8, 0x00, 0x75, 0x11, 0x83, 0x7d
+.data1 	0x18, 0x00, 0x0f, 0x85, 0x60, 0x00, 0x00, 0x00
+.data1 	0x89, 0xf0, 0xe9, 0x9f, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x0c, 0xf6, 0xc2, 0x08, 0x74, 0x0c, 0x80
+.data1 	0x7d, 0x14, 0x78, 0x74, 0x0c, 0x80, 0x7d, 0x14
+.data1 	0x58, 0x74, 0x06, 0x80, 0x7d, 0x14, 0x70, 0x75
+.data1 	0x3f, 0xc6, 0x06, 0x30, 0x46, 0x80, 0x7d, 0x14
+.data1 	0x58, 0x75, 0x07, 0xb8, 0x58, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x05, 0xb8, 0x78, 0x00, 0x00, 0x00, 0x88
+.data1 	0x06, 0x46, 0xeb, 0x24, 0xc7, 0x45, 0xf0, 0x02
+.data1 	0x00, 0x00, 0x00, 0xeb, 0x29, 0xc7, 0x45, 0xf0
+.data1 	0x08, 0x00, 0x00, 0x00, 0xeb, 0x20, 0xc7, 0x45
+.data1 	0xf0, 0x0a, 0x00, 0x00, 0x00, 0xeb, 0x17, 0xc7
+.data1 	0x45, 0xf0, 0x10, 0x00, 0x00, 0x00, 0xeb, 0x0e
+.data1 	0x0f, 0xbe, 0x45, 0x14, 0xbb, 0x4c, 0x06, 0x00
+.data1 	0x00, 0xe9, 0xc6, 0x11, 0x00, 0x00, 0xff, 0x75
+.data1 	0x18, 0x56, 0xff, 0x75, 0xf0, 0xff, 0x75, 0xf8
+.data1 	0xe8, 0x2b, 0x09, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x89, 0xc6, 0x80, 0x7d, 0x14, 0x58, 0x75, 0x1c
+.data1 	0x39, 0x75, 0xf4, 0x74, 0x17, 0x8b, 0x55, 0xf4
+.data1 	0x0f, 0xbe, 0x02, 0x50, 0xe8, 0xd7, 0x0c, 0x00
+.data1 	0x00, 0x59, 0x8b, 0x55, 0xf4, 0x88, 0x02, 0xff
+.data1 	0x45, 0xf4, 0xeb, 0xe4, 0x89, 0xf0, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x81, 0xec, 0x34
+.data1 	0x04, 0x00, 0x00, 0x56, 0x57, 0x8b, 0x75, 0x10
+.data1 	0xc7, 0x45, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x45, 0x08, 0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00
+.data1 	0x89, 0x45, 0xf0, 0x85, 0xc0, 0x0f, 0x84, 0x0b
+.data1 	0x06, 0x00, 0x00, 0x83, 0x7d, 0xf0, 0x25, 0x0f
+.data1 	0x84, 0x4d, 0x00, 0x00, 0x00, 0x8b, 0x16, 0x4a
+.data1 	0x89, 0x16, 0x78, 0x13, 0x8b, 0x55, 0xf0, 0x0f
+.data1 	0xb6, 0xca, 0x8b, 0x46, 0x14, 0x83, 0x46, 0x14
+.data1 	0x01, 0x88, 0x08, 0x89, 0xc8, 0xeb, 0x0b, 0x56
+.data1 	0xff, 0x75, 0xf0, 0xe8, 0x24, 0x06, 0x00, 0x00
+.data1 	0x59, 0x59, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x1c, 0x83, 0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b
+.data1 	0x55, 0xd8, 0xf7, 0xda, 0x89, 0xd0, 0xe9, 0xc6
+.data1 	0x05, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0xbc, 0x05, 0x00, 0x00, 0xff, 0x45, 0xd8
+.data1 	0xeb, 0x95, 0x31, 0xff, 0xeb, 0x21, 0x83, 0xcf
+.data1 	0x01, 0xeb, 0x2c, 0x83, 0xcf, 0x02, 0xeb, 0x27
+.data1 	0x83, 0xcf, 0x04, 0xeb, 0x22, 0x83, 0xcf, 0x08
+.data1 	0xeb, 0x1d, 0x83, 0xcf, 0x10, 0xeb, 0x18, 0x81
+.data1 	0xcf, 0x00, 0x10, 0x00, 0x00, 0xeb, 0x13, 0x8b
+.data1 	0x55, 0x08, 0x0f, 0xbe, 0x02, 0xbb, 0x94, 0x06
+.data1 	0x00, 0x00, 0xe9, 0xd5, 0x10, 0x00, 0x00, 0xff
+.data1 	0x45, 0x08, 0xf7, 0xc7, 0x00, 0x10, 0x00, 0x00
+.data1 	0x74, 0xe5, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xd4
+.data1 	0x8d, 0x45, 0x0c, 0x50, 0x8d, 0x45, 0xec, 0x50
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x2c, 0xfd, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x45, 0x08, 0x39, 0x45
+.data1 	0xd4, 0x74, 0x06, 0x81, 0xcf, 0x00, 0x01, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x08, 0x80, 0x3a, 0x2e, 0x75
+.data1 	0x2b, 0xff, 0x45, 0x08, 0x8b, 0x55, 0x08, 0x89
+.data1 	0x55, 0xd4, 0x8d, 0x45, 0x0c, 0x50, 0x8d, 0x45
+.data1 	0xe8, 0x50, 0xff, 0x75, 0x08, 0xe8, 0xfa, 0xfc
+.data1 	0xff, 0xff, 0x83, 0xc4, 0x0c, 0x89, 0x45, 0x08
+.data1 	0x83, 0x7d, 0xe8, 0x00, 0x78, 0x06, 0x81, 0xcf
+.data1 	0x00, 0x02, 0x00, 0x00, 0xf7, 0xc7, 0x00, 0x01
+.data1 	0x00, 0x00, 0x74, 0x0c, 0x83, 0x7d, 0xec, 0x00
+.data1 	0x79, 0x06, 0xf7, 0x5d, 0xec, 0x83, 0xcf, 0x01
+.data1 	0xf7, 0xc7, 0x00, 0x01, 0x00, 0x00, 0x75, 0x07
+.data1 	0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, 0x00, 0xf7
+.data1 	0xc7, 0x02, 0x00, 0x00, 0x00, 0x74, 0x03, 0x83
+.data1 	0xe7, 0xfb, 0xf7, 0xc7, 0x01, 0x00, 0x00, 0x00
+.data1 	0x74, 0x03, 0x83, 0xe7, 0xef, 0x8d, 0x95, 0xcf
+.data1 	0xfb, 0xff, 0xff, 0x89, 0x55, 0xd0, 0x89, 0x55
+.data1 	0xfc, 0xeb, 0x24, 0x83, 0xcf, 0x20, 0xff, 0x45
+.data1 	0x08, 0xe9, 0x23, 0x02, 0x00, 0x00, 0x83, 0xcf
+.data1 	0x40, 0xff, 0x45, 0x08, 0xe9, 0x18, 0x02, 0x00
+.data1 	0x00, 0x81, 0xcf, 0x80, 0x00, 0x00, 0x00, 0xff
+.data1 	0x45, 0x08, 0xe9, 0x0a, 0x02, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x08, 0x0f, 0xbe, 0x02, 0xbb, 0xc4, 0x06
+.data1 	0x00, 0x00, 0xe9, 0xf5, 0x0f, 0x00, 0x00, 0x8b
+.data1 	0x16, 0x4a, 0x89, 0x16, 0x78, 0x13, 0x8b, 0x55
+.data1 	0xf0, 0x0f, 0xb6, 0xca, 0x8b, 0x46, 0x14, 0x83
+.data1 	0x46, 0x14, 0x01, 0x88, 0x08, 0x89, 0xc8, 0xeb
+.data1 	0x0b, 0x56, 0xff, 0x75, 0xf0, 0xe8, 0xc2, 0x04
+.data1 	0x00, 0x00, 0x59, 0x59, 0x3d, 0xff, 0xff, 0xff
+.data1 	0xff, 0x75, 0x1c, 0x83, 0x7d, 0xd8, 0x00, 0x74
+.data1 	0x0c, 0x8b, 0x55, 0xd8, 0xf7, 0xda, 0x89, 0xd0
+.data1 	0xe9, 0x64, 0x04, 0x00, 0x00, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe9, 0x5a, 0x04, 0x00, 0x00, 0xff
+.data1 	0x45, 0xd8, 0xe9, 0x30, 0xfe, 0xff, 0xff, 0xf7
+.data1 	0xc7, 0x20, 0x00, 0x00, 0x00, 0x74, 0x1a, 0x8b
+.data1 	0x45, 0xd8, 0x0f, 0xbf, 0xc0, 0x8b, 0x55, 0x0c
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c, 0x8b, 0x52
+.data1 	0xfc, 0x66, 0x89, 0x02, 0xe9, 0x0e, 0xfe, 0xff
+.data1 	0xff, 0xf7, 0xc7, 0x40, 0x00, 0x00, 0x00, 0x74
+.data1 	0x16, 0x8b, 0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x8b, 0x4d, 0xd8
+.data1 	0x89, 0x0a, 0xe9, 0xf0, 0xfd, 0xff, 0xff, 0x8b
+.data1 	0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c
+.data1 	0x8b, 0x52, 0xfc, 0x8b, 0x4d, 0xd8, 0x89, 0x0a
+.data1 	0xe9, 0xda, 0xfd, 0xff, 0xff, 0x8b, 0x55, 0x0c
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0xd0, 0x85, 0xd2, 0x75, 0x07
+.data1 	0xc7, 0x45, 0xd0, 0x74, 0x07, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xd0, 0x89, 0x55, 0xfc, 0x83, 0x7d, 0xe8
+.data1 	0x00, 0x75, 0x0c, 0xf7, 0xc7, 0x00, 0x02, 0x00
+.data1 	0x00, 0x0f, 0x85, 0x38, 0x01, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xfc, 0x80, 0x3a, 0x00, 0x0f, 0x84, 0x2c
+.data1 	0x01, 0x00, 0x00, 0xff, 0x45, 0xfc, 0xff, 0x4d
+.data1 	0xe8, 0xeb, 0xda, 0xf7, 0xc7, 0x00, 0x02, 0x00
+.data1 	0x00, 0x75, 0x09, 0xc7, 0x45, 0xe8, 0x01, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x09, 0x83, 0x7d, 0xf0, 0x70
+.data1 	0x74, 0x03, 0x83, 0xe7, 0xef, 0x8b, 0x45, 0xf0
+.data1 	0x0f, 0xbe, 0xc0, 0x6a, 0x00, 0xff, 0x75, 0xe8
+.data1 	0x50, 0xff, 0x75, 0xfc, 0x57, 0x8d, 0x45, 0x0c
+.data1 	0x50, 0xe8, 0xa1, 0xfb, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x18, 0x89, 0x45, 0xfc, 0xe9, 0xe6, 0x00, 0x00
+.data1 	0x00, 0x81, 0xcf, 0x00, 0x04, 0x00, 0x00, 0xf7
+.data1 	0xc7, 0x00, 0x02, 0x00, 0x00, 0x75, 0x09, 0xc7
+.data1 	0x45, 0xe8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x03
+.data1 	0x83, 0xe7, 0xef, 0x8b, 0x45, 0xf0, 0x0f, 0xbe
+.data1 	0xc0, 0x6a, 0x01, 0xff, 0x75, 0xe8, 0x50, 0xff
+.data1 	0x75, 0xfc, 0x57, 0x8d, 0x45, 0x0c, 0x50, 0xe8
+.data1 	0x63, 0xfb, 0xff, 0xff, 0x83, 0xc4, 0x18, 0x89
+.data1 	0x45, 0xfc, 0xe9, 0xa8, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c
+.data1 	0x8b, 0x4d, 0xfc, 0x8b, 0x52, 0xfc, 0x88, 0x11
+.data1 	0xff, 0x45, 0xfc, 0xe9, 0x8f, 0x00, 0x00, 0x00
+.data1 	0xf7, 0xc7, 0x00, 0x02, 0x00, 0x00, 0x74, 0x0d
+.data1 	0x83, 0x7d, 0xe8, 0x00, 0x75, 0x07, 0xc7, 0x45
+.data1 	0xe8, 0x01, 0x00, 0x00, 0x00, 0xf7, 0xc7, 0x00
+.data1 	0x02, 0x00, 0x00, 0x75, 0x07, 0xc7, 0x45, 0xe8
+.data1 	0x06, 0x00, 0x00, 0x00, 0x81, 0x7d, 0xe8, 0x01
+.data1 	0x04, 0x00, 0x00, 0x72, 0x07, 0xc7, 0x45, 0xe8
+.data1 	0x00, 0x04, 0x00, 0x00, 0x81, 0xcf, 0x00, 0x04
+.data1 	0x00, 0x00, 0x8b, 0x45, 0xf0, 0x0f, 0xbe, 0xc0
+.data1 	0xff, 0x75, 0xe8, 0x50, 0xff, 0x75, 0xfc, 0x57
+.data1 	0x8d, 0x45, 0x0c, 0x50, 0xe8, 0x2f, 0x06, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x14, 0x89, 0x45, 0xfc, 0xeb
+.data1 	0x36, 0x8b, 0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0x0c
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0x08, 0xe9, 0x86, 0xfc, 0xff
+.data1 	0xff, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f
+.data1 	0xbe, 0x00, 0x89, 0x45, 0xf0, 0xbb, 0xe4, 0x06
+.data1 	0x00, 0x00, 0xe9, 0xe5, 0x0d, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xe4, 0x20, 0x00, 0x00, 0x00, 0xf7, 0xc7
+.data1 	0x10, 0x00, 0x00, 0x00, 0x74, 0x07, 0xc7, 0x45
+.data1 	0xe4, 0x30, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xfc
+.data1 	0x2b, 0x55, 0xd0, 0x89, 0x55, 0xf8, 0xc7, 0x45
+.data1 	0xdc, 0x00, 0x00, 0x00, 0x00, 0xf7, 0xc7, 0x10
+.data1 	0x00, 0x00, 0x00, 0x74, 0x37, 0x83, 0x7d, 0xf0
+.data1 	0x78, 0x74, 0x06, 0x83, 0x7d, 0xf0, 0x58, 0x75
+.data1 	0x08, 0xf7, 0xc7, 0x08, 0x00, 0x00, 0x00, 0x75
+.data1 	0x20, 0x83, 0x7d, 0xf0, 0x70, 0x74, 0x1a, 0xf7
+.data1 	0xc7, 0x00, 0x04, 0x00, 0x00, 0x74, 0x15, 0x8b
+.data1 	0x55, 0xd0, 0x80, 0x3a, 0x2b, 0x74, 0x0a, 0x80
+.data1 	0x3a, 0x2d, 0x74, 0x05, 0x80, 0x3a, 0x20, 0x75
+.data1 	0x03, 0xff, 0x45, 0xdc, 0x8b, 0x55, 0xec, 0x2b
+.data1 	0x55, 0xf8, 0x89, 0x55, 0xf4, 0x85, 0xd2, 0x0f
+.data1 	0x8e, 0x61, 0x01, 0x00, 0x00, 0xf7, 0xc7, 0x01
+.data1 	0x00, 0x00, 0x00, 0x0f, 0x85, 0x55, 0x01, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xf4, 0x01, 0x55, 0xd8, 0x83
+.data1 	0x7d, 0xdc, 0x00, 0x0f, 0x84, 0xf8, 0x00, 0x00
+.data1 	0x00, 0xf7, 0xc7, 0x00, 0x04, 0x00, 0x00, 0x0f
+.data1 	0x84, 0x5c, 0x00, 0x00, 0x00, 0xff, 0x4d, 0xf8
+.data1 	0xff, 0x45, 0xd8, 0x8b, 0x16, 0x4a, 0x89, 0x16
+.data1 	0x78, 0x16, 0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0
+.data1 	0x0f, 0xb6, 0x10, 0x8b, 0x46, 0x14, 0x83, 0x46
+.data1 	0x14, 0x01, 0x88, 0x10, 0x89, 0xd0, 0xeb, 0x12
+.data1 	0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xbe
+.data1 	0x00, 0x56, 0x50, 0xe8, 0x04, 0x02, 0x00, 0x00
+.data1 	0x59, 0x59, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x0f
+.data1 	0x85, 0xac, 0x00, 0x00, 0x00, 0x83, 0x7d, 0xd8
+.data1 	0x00, 0x74, 0x0c, 0x8b, 0x55, 0xd8, 0xf7, 0xda
+.data1 	0x89, 0xd0, 0xe9, 0xa2, 0x01, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe9, 0x98, 0x01, 0x00
+.data1 	0x00, 0x83, 0x6d, 0xf8, 0x02, 0x83, 0x45, 0xd8
+.data1 	0x02, 0x8b, 0x16, 0x4a, 0x89, 0x16, 0x78, 0x16
+.data1 	0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xb6
+.data1 	0x10, 0x8b, 0x46, 0x14, 0x83, 0x46, 0x14, 0x01
+.data1 	0x88, 0x10, 0x89, 0xd0, 0xeb, 0x12, 0x8b, 0x45
+.data1 	0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xbe, 0x00, 0x56
+.data1 	0x50, 0xe8, 0xa6, 0x01, 0x00, 0x00, 0x59, 0x59
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x74, 0x36, 0x8b
+.data1 	0x16, 0x4a, 0x89, 0x16, 0x78, 0x16, 0x8b, 0x45
+.data1 	0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xb6, 0x10, 0x8b
+.data1 	0x46, 0x14, 0x83, 0x46, 0x14, 0x01, 0x88, 0x10
+.data1 	0x89, 0xd0, 0xeb, 0x12, 0x8b, 0x45, 0xd0, 0xff
+.data1 	0x45, 0xd0, 0x0f, 0xbe, 0x00, 0x56, 0x50, 0xe8
+.data1 	0x70, 0x01, 0x00, 0x00, 0x59, 0x59, 0x3d, 0xff
+.data1 	0xff, 0xff, 0xff, 0x75, 0x1c, 0x83, 0x7d, 0xd8
+.data1 	0x00, 0x74, 0x0c, 0x8b, 0x55, 0xd8, 0xf7, 0xda
+.data1 	0x89, 0xd0, 0xe9, 0x12, 0x01, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe9, 0x08, 0x01, 0x00
+.data1 	0x00, 0x8b, 0x16, 0x4a, 0x89, 0x16, 0x78, 0x13
+.data1 	0x8b, 0x55, 0xe4, 0x0f, 0xb6, 0xca, 0x8b, 0x46
+.data1 	0x14, 0x83, 0x46, 0x14, 0x01, 0x88, 0x08, 0x89
+.data1 	0xc8, 0xeb, 0x0b, 0x56, 0xff, 0x75, 0xe4, 0xe8
+.data1 	0x28, 0x01, 0x00, 0x00, 0x59, 0x59, 0x3d, 0xff
+.data1 	0xff, 0xff, 0xff, 0x75, 0x1c, 0x83, 0x7d, 0xd8
+.data1 	0x00, 0x74, 0x0c, 0x8b, 0x55, 0xd8, 0xf7, 0xda
+.data1 	0x89, 0xd0, 0xe9, 0xca, 0x00, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe9, 0xc0, 0x00, 0x00
+.data1 	0x00, 0xff, 0x4d, 0xf4, 0x75, 0xb3, 0x8b, 0x55
+.data1 	0xf8, 0x01, 0x55, 0xd8, 0xff, 0x4d, 0xf8, 0x0f
+.data1 	0x88, 0x52, 0x00, 0x00, 0x00, 0x8b, 0x16, 0x4a
+.data1 	0x89, 0x16, 0x78, 0x16, 0x8b, 0x45, 0xd0, 0xff
+.data1 	0x45, 0xd0, 0x0f, 0xb6, 0x10, 0x8b, 0x46, 0x14
+.data1 	0x83, 0x46, 0x14, 0x01, 0x88, 0x10, 0x89, 0xd0
+.data1 	0xeb, 0x12, 0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0
+.data1 	0x0f, 0xbe, 0x00, 0x56, 0x50, 0xe8, 0xc2, 0x00
+.data1 	0x00, 0x00, 0x59, 0x59, 0x3d, 0xff, 0xff, 0xff
+.data1 	0xff, 0x75, 0xc1, 0x83, 0x7d, 0xd8, 0x00, 0x74
+.data1 	0x0c, 0x8b, 0x55, 0xd8, 0xf7, 0xda, 0x89, 0xd0
+.data1 	0xe9, 0x64, 0x00, 0x00, 0x00, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe9, 0x5a, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7d, 0xf4, 0x00, 0x7e, 0x06, 0x8b, 0x55, 0xf4
+.data1 	0x01, 0x55, 0xd8, 0xff, 0x4d, 0xf4, 0x0f, 0x88
+.data1 	0x23, 0xfa, 0xff, 0xff, 0x8b, 0x16, 0x4a, 0x89
+.data1 	0x16, 0x78, 0x13, 0x8b, 0x55, 0xe4, 0x0f, 0xb6
+.data1 	0xca, 0x8b, 0x46, 0x14, 0x83, 0x46, 0x14, 0x01
+.data1 	0x88, 0x08, 0x89, 0xc8, 0xeb, 0x0b, 0x56, 0xff
+.data1 	0x75, 0xe4, 0xe8, 0x65, 0x00, 0x00, 0x00, 0x59
+.data1 	0x59, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0xcb
+.data1 	0x83, 0x7d, 0xd8, 0x00, 0x74, 0x09, 0x8b, 0x55
+.data1 	0xd8, 0xf7, 0xda, 0x89, 0xd0, 0xeb, 0x0a, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x03, 0x8b, 0x45
+.data1 	0xd8, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x10
+.data1 	0x57, 0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xd4, 0x07, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0xc6, 0x85, 0xc0, 0x7e, 0x14, 0x39, 0xfe, 0x7d
+.data1 	0x10, 0x89, 0xfa, 0x29, 0xf2, 0x89, 0xd7, 0x89
+.data1 	0xf2, 0x03, 0x55, 0x0c, 0x89, 0x55, 0x0c, 0xeb
+.data1 	0xd7, 0x31, 0xc0, 0x85, 0xf6, 0x0f, 0x9f, 0xc0
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x08, 0x56, 0x57, 0x8b, 0x75, 0x0c, 0x8b
+.data1 	0x7d, 0x08, 0xc7, 0x05, 0xbc, 0x07, 0x00, 0x00
+.data1 	0x45, 0x17, 0x00, 0x00, 0x83, 0x7e, 0x04, 0x00
+.data1 	0x79, 0x0a, 0x89, 0xfa, 0x0f, 0xb6, 0xc2, 0xe9
+.data1 	0x55, 0x02, 0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6
+.data1 	0xc2, 0x02, 0x75, 0x0a, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x43, 0x02, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x80, 0x74, 0x0f, 0xf6, 0xc2
+.data1 	0x10, 0x75, 0x0a, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x2c, 0x02, 0x00, 0x00, 0x81, 0x66, 0x08
+.data1 	0x7f, 0xff, 0xff, 0xff, 0x81, 0x4e, 0x08, 0x00
+.data1 	0x01, 0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2
+.data1 	0x04, 0x0f, 0x85, 0x8f, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7e, 0x10, 0x00, 0x0f, 0x85, 0x85, 0x00, 0x00
+.data1 	0x00, 0x81, 0xfe, 0xe0, 0x07, 0x00, 0x00, 0x75
+.data1 	0x3e, 0xff, 0x35, 0xe4, 0x07, 0x00, 0x00, 0xe8
+.data1 	0xec, 0x06, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x74
+.data1 	0x2e, 0x68, 0x00, 0x04, 0x00, 0x00, 0xe8, 0x20
+.data1 	0x03, 0x00, 0x00, 0x59, 0x89, 0x46, 0x10, 0x85
+.data1 	0xc0, 0x75, 0x09, 0x83, 0x4e, 0x08, 0x04, 0xe9
+.data1 	0x4c, 0x00, 0x00, 0x00, 0x83, 0x4e, 0x08, 0x48
+.data1 	0xc7, 0x46, 0x0c, 0x00, 0x04, 0x00, 0x00, 0xc7
+.data1 	0x06, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x39, 0x68
+.data1 	0x00, 0x04, 0x00, 0x00, 0xe8, 0xf2, 0x02, 0x00
+.data1 	0x00, 0x59, 0x89, 0x46, 0x10, 0x85, 0xc0, 0x75
+.data1 	0x06, 0x83, 0x4e, 0x08, 0x04, 0xeb, 0x21, 0x83
+.data1 	0x4e, 0x08, 0x08, 0xc7, 0x46, 0x0c, 0x00, 0x04
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x40
+.data1 	0x75, 0x08, 0xc7, 0x06, 0xff, 0x03, 0x00, 0x00
+.data1 	0xeb, 0x06, 0xc7, 0x06, 0xff, 0xff, 0xff, 0xff
+.data1 	0x8b, 0x56, 0x10, 0x89, 0x56, 0x14, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x04, 0x0f, 0x84, 0x68, 0x00
+.data1 	0x00, 0x00, 0x89, 0xfa, 0x88, 0x55, 0xff, 0xc7
+.data1 	0x06, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x46, 0x08
+.data1 	0x00, 0x02, 0x00, 0x00, 0x74, 0x24, 0x6a, 0x02
+.data1 	0x6a, 0x00, 0xff, 0x76, 0x04, 0xe8, 0x9a, 0xf5
+.data1 	0xff, 0xff, 0x83, 0xc4, 0x0c, 0x3d, 0xff, 0xff
+.data1 	0xff, 0xff, 0x75, 0x0e, 0x83, 0x4e, 0x08, 0x20
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x3f, 0x01
+.data1 	0x00, 0x00, 0x6a, 0x01, 0x8d, 0x45, 0xff, 0x50
+.data1 	0xff, 0x76, 0x04, 0xe8, 0x60, 0x06, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x3d, 0x01, 0x00, 0x00, 0x00
+.data1 	0x74, 0x0e, 0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xe9, 0x19, 0x01, 0x00, 0x00
+.data1 	0x89, 0xfa, 0x0f, 0xb6, 0xc2, 0xe9, 0x0f, 0x01
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x40
+.data1 	0x0f, 0x84, 0x84, 0x00, 0x00, 0x00, 0x89, 0xfa
+.data1 	0x8b, 0x46, 0x14, 0x83, 0x46, 0x14, 0x01, 0x88
+.data1 	0x10, 0x83, 0xff, 0x0a, 0x74, 0x0d, 0x8b, 0x56
+.data1 	0x0c, 0xf7, 0xda, 0x39, 0x16, 0x0f, 0x85, 0xe1
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x16, 0xf7, 0xda, 0x89
+.data1 	0x55, 0xf8, 0x8b, 0x56, 0x10, 0x89, 0x56, 0x14
+.data1 	0xc7, 0x06, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x46
+.data1 	0x08, 0x00, 0x02, 0x00, 0x00, 0x74, 0x24, 0x6a
+.data1 	0x02, 0x6a, 0x00, 0xff, 0x76, 0x04, 0xe8, 0x01
+.data1 	0xf5, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x3d, 0xff
+.data1 	0xff, 0xff, 0xff, 0x75, 0x0e, 0x83, 0x4e, 0x08
+.data1 	0x20, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0xa6
+.data1 	0x00, 0x00, 0x00, 0xff, 0x75, 0xf8, 0xff, 0x76
+.data1 	0x10, 0xff, 0x76, 0x04, 0xe8, 0xdf, 0xfd, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x0f, 0x85
+.data1 	0x88, 0x00, 0x00, 0x00, 0x83, 0x4e, 0x08, 0x20
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x7f, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x14, 0x2b, 0x56, 0x10
+.data1 	0x89, 0x55, 0xf8, 0x8b, 0x56, 0x0c, 0x4a, 0x89
+.data1 	0x16, 0x8b, 0x56, 0x10, 0x83, 0xc2, 0x01, 0x89
+.data1 	0x56, 0x14, 0x83, 0x7d, 0xf8, 0x00, 0x0f, 0x8e
+.data1 	0x51, 0x00, 0x00, 0x00, 0xf7, 0x46, 0x08, 0x00
+.data1 	0x02, 0x00, 0x00, 0x74, 0x21, 0x6a, 0x02, 0x6a
+.data1 	0x00, 0xff, 0x76, 0x04, 0xe8, 0x8b, 0xf4, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x3d, 0xff, 0xff, 0xff
+.data1 	0xff, 0x75, 0x0b, 0x83, 0x4e, 0x08, 0x20, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x33, 0xff, 0x75
+.data1 	0xf8, 0xff, 0x76, 0x10, 0xff, 0x76, 0x04, 0xe8
+.data1 	0x6c, 0xfd, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x85
+.data1 	0xc0, 0x75, 0x12, 0x89, 0xfa, 0x8b, 0x4e, 0x10
+.data1 	0x88, 0x11, 0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xeb, 0x0c, 0x89, 0xfa, 0x8b
+.data1 	0x4e, 0x10, 0x88, 0x11, 0x89, 0xfa, 0x0f, 0xb6
+.data1 	0xc2, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x75, 0x10
+.data1 	0x8b, 0x45, 0x08, 0x31, 0xd2, 0xf7, 0x75, 0x0c
+.data1 	0x89, 0xd7, 0x8b, 0x45, 0x08, 0x31, 0xd2, 0xf7
+.data1 	0x75, 0x0c, 0x89, 0x45, 0x08, 0x85, 0xc0, 0x75
+.data1 	0x06, 0x83, 0x7d, 0x14, 0x01, 0x7e, 0x16, 0x8b
+.data1 	0x55, 0x14, 0x4a, 0x52, 0x56, 0xff, 0x75, 0x0c
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xc8, 0xff, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x10, 0x89, 0xc6, 0x83, 0xff, 0x09
+.data1 	0x7e, 0x09, 0x89, 0xfa, 0x83, 0xea, 0xa9, 0x89
+.data1 	0xd0, 0xeb, 0x03, 0x8d, 0x47, 0x30, 0x88, 0x06
+.data1 	0x8d, 0x46, 0x01, 0x5f, 0x5e, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x85, 0xc9, 0x74
+.data1 	0x13, 0x8b, 0x75, 0x08, 0x8b, 0x7d, 0x0c, 0xfc
+.data1 	0xa6, 0x75, 0x09, 0x80, 0x7e, 0xff, 0x00, 0x74
+.data1 	0x03, 0x49, 0x75, 0xf4, 0x0f, 0x97, 0xc0, 0x0f
+.data1 	0x92, 0xc4, 0x28, 0xe0, 0x0f, 0xbe, 0xc0, 0x5f
+.data1 	0x5e, 0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb9, 0xff, 0xff, 0xff, 0xff, 0xe9, 0xee, 0x06
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x68, 0x7c, 0x07, 0x00, 0x00
+.data1 	0x68, 0xf8, 0x07, 0x00, 0x00, 0xe8, 0xce, 0xf2
+.data1 	0xff, 0xff, 0x59, 0x59, 0x6a, 0x01, 0xe8, 0x7e
+.data1 	0xf2, 0xff, 0xff, 0x59, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x15, 0xb8, 0x09
+.data1 	0x00, 0x00, 0x03, 0x55, 0x08, 0x39, 0x15, 0xb8
+.data1 	0x09, 0x00, 0x00, 0x77, 0x1f, 0x8b, 0x55, 0x08
+.data1 	0x03, 0x15, 0xb8, 0x09, 0x00, 0x00, 0x81, 0xc2
+.data1 	0xff, 0x0f, 0x00, 0x00, 0x81, 0xe2, 0x00, 0xf0
+.data1 	0xff, 0xff, 0x89, 0xd6, 0x39, 0x15, 0xb8, 0x09
+.data1 	0x00, 0x00, 0x76, 0x0e, 0xc7, 0x05, 0xc4, 0x07
+.data1 	0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x31, 0xc0
+.data1 	0xeb, 0x36, 0x56, 0xe8, 0xe8, 0x02, 0x00, 0x00
+.data1 	0x59, 0x85, 0xc0, 0x74, 0x04, 0x31, 0xc0, 0xeb
+.data1 	0x27, 0x8b, 0x15, 0xb8, 0x09, 0x00, 0x00, 0x89
+.data1 	0x72, 0xfc, 0xc7, 0x46, 0xfc, 0x00, 0x00, 0x00
+.data1 	0x00, 0xff, 0x35, 0xb8, 0x09, 0x00, 0x00, 0xe8
+.data1 	0x26, 0x02, 0x00, 0x00, 0x59, 0x89, 0x35, 0xb8
+.data1 	0x09, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x00
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x18, 0x56, 0x57, 0x83, 0x7d, 0x08, 0x00, 0x75
+.data1 	0x07, 0x31, 0xc0, 0xe9, 0xf4, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7d, 0xe8, 0x02, 0x0f, 0x83, 0xe1, 0x00, 0x00
+.data1 	0x00, 0xba, 0x03, 0x00, 0x00, 0x00, 0x03, 0x55
+.data1 	0x08, 0x83, 0xe2, 0xfc, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x55, 0xec, 0x83, 0xfa, 0x08, 0x73, 0x11, 0xc7
+.data1 	0x05, 0xc4, 0x07, 0x00, 0x00, 0x0c, 0x00, 0x00
+.data1 	0x00, 0x31, 0xc0, 0xe9, 0xbc, 0x00, 0x00, 0x00
+.data1 	0x83, 0x3d, 0xb4, 0x09, 0x00, 0x00, 0x00, 0x75
+.data1 	0x38, 0x6a, 0x08, 0xe8, 0x97, 0x02, 0x00, 0x00
+.data1 	0x59, 0x89, 0xc6, 0x3d, 0xff, 0xff, 0xff, 0xff
+.data1 	0x75, 0x07, 0x31, 0xc0, 0xe9, 0x9b, 0x00, 0x00
+.data1 	0x00, 0x8d, 0x56, 0x03, 0xbe, 0xfc, 0xff, 0xff
+.data1 	0xff, 0x21, 0xd6, 0x83, 0xc6, 0x04, 0x89, 0x35
+.data1 	0xb4, 0x09, 0x00, 0x00, 0x89, 0x35, 0xb8, 0x09
+.data1 	0x00, 0x00, 0xc7, 0x46, 0xfc, 0x00, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x35, 0xbc, 0x09, 0x00, 0x00, 0x85, 0xf6
+.data1 	0x0f, 0x84, 0x4f, 0x00, 0x00, 0x00, 0x8b, 0x56
+.data1 	0xfc, 0x89, 0x55, 0xf4, 0x89, 0xf2, 0x8b, 0x7d
+.data1 	0xec, 0x01, 0xd7, 0x39, 0x7d, 0xf4, 0x72, 0x36
+.data1 	0x39, 0xf7, 0x76, 0x32, 0x8d, 0x57, 0x04, 0x39
+.data1 	0x55, 0xf4, 0x76, 0x0f, 0x8b, 0x55, 0xf4, 0x89
+.data1 	0x57, 0xfc, 0x89, 0x7e, 0xfc, 0x8b, 0x16, 0x89
+.data1 	0x17, 0x89, 0x3e, 0x83, 0x7d, 0xfc, 0x00, 0x74
+.data1 	0x09, 0x8b, 0x16, 0x8b, 0x45, 0xfc, 0x89, 0x10
+.data1 	0xeb, 0x08, 0x8b, 0x16, 0x89, 0x15, 0xbc, 0x09
+.data1 	0x00, 0x00, 0x89, 0xf0, 0xeb, 0x1e, 0x89, 0x75
+.data1 	0xfc, 0x8b, 0x36, 0xeb, 0xa9, 0xff, 0x75, 0xec
+.data1 	0xe8, 0x8b, 0xfe, 0xff, 0xff, 0x59, 0x85, 0xc0
+.data1 	0x74, 0x08, 0xff, 0x45, 0xe8, 0xe9, 0x15, 0xff
+.data1 	0xff, 0xff, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x1c, 0x56, 0x57
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xec, 0x85, 0xd2
+.data1 	0x75, 0x0e, 0xff, 0x75, 0x0c, 0xe8, 0xd9, 0xfe
+.data1 	0xff, 0xff, 0x59, 0xe9, 0xe6, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x0c, 0x00, 0x75, 0x10, 0xff, 0x75
+.data1 	0xec, 0xe8, 0xdc, 0x00, 0x00, 0x00, 0x59, 0x31
+.data1 	0xc0, 0xe9, 0xd0, 0x00, 0x00, 0x00, 0xba, 0x03
+.data1 	0x00, 0x00, 0x00, 0x03, 0x55, 0x0c, 0x83, 0xe2
+.data1 	0xfc, 0x83, 0xc2, 0x04, 0x89, 0x55, 0xe8, 0x8b
+.data1 	0x55, 0xec, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xf4
+.data1 	0x2b, 0x55, 0xec, 0x89, 0x55, 0xe4, 0xc7, 0x45
+.data1 	0xfc, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x3d, 0xbc
+.data1 	0x09, 0x00, 0x00, 0x85, 0xff, 0x0f, 0x84, 0x3c
+.data1 	0x00, 0x00, 0x00, 0x39, 0x7d, 0xf4, 0x72, 0x37
+.data1 	0x39, 0x7d, 0xf4, 0x75, 0x2b, 0x8b, 0x55, 0xec
+.data1 	0x8b, 0x4f, 0xfc, 0x89, 0x4a, 0xfc, 0x83, 0x7d
+.data1 	0xfc, 0x00, 0x74, 0x09, 0x8b, 0x17, 0x8b, 0x45
+.data1 	0xfc, 0x89, 0x10, 0xeb, 0x08, 0x8b, 0x17, 0x89
+.data1 	0x15, 0xbc, 0x09, 0x00, 0x00, 0x8b, 0x55, 0xec
+.data1 	0x8b, 0x52, 0xfc, 0x89, 0x55, 0xf4, 0xeb, 0x07
+.data1 	0x89, 0x7d, 0xfc, 0x8b, 0x3f, 0xeb, 0xbc, 0x8b
+.data1 	0x55, 0xec, 0x8b, 0x75, 0xe8, 0x01, 0xd6, 0x39
+.data1 	0x75, 0xf4, 0x72, 0x25, 0x39, 0x75, 0xec, 0x77
+.data1 	0x20, 0x8d, 0x56, 0x04, 0x39, 0x55, 0xf4, 0x76
+.data1 	0x13, 0x8b, 0x55, 0xf4, 0x89, 0x56, 0xfc, 0x8b
+.data1 	0x55, 0xec, 0x89, 0x72, 0xfc, 0x56, 0xe8, 0x37
+.data1 	0x00, 0x00, 0x00, 0x59, 0x8b, 0x45, 0xec, 0xeb
+.data1 	0x2d, 0xff, 0x75, 0x0c, 0xe8, 0x12, 0xfe, 0xff
+.data1 	0xff, 0x59, 0x89, 0xc6, 0x85, 0xc0, 0x75, 0x04
+.data1 	0x31, 0xc0, 0xeb, 0x1a, 0xff, 0x75, 0xe4, 0xff
+.data1 	0x75, 0xec, 0x56, 0xe8, 0x68, 0x04, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0xff, 0x75, 0xec, 0xe8, 0x07
+.data1 	0x00, 0x00, 0x00, 0x59, 0x89, 0xf0, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c
+.data1 	0x56, 0x57, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xf4
+.data1 	0x85, 0xd2, 0x0f, 0x84, 0x62, 0x00, 0x00, 0x00
+.data1 	0x31, 0xff, 0x8b, 0x35, 0xbc, 0x09, 0x00, 0x00
+.data1 	0x85, 0xf6, 0x74, 0x0b, 0x39, 0x75, 0xf4, 0x72
+.data1 	0x06, 0x89, 0xf7, 0x8b, 0x36, 0xeb, 0xf1, 0x8b
+.data1 	0x45, 0xf4, 0x89, 0x30, 0x85, 0xff, 0x74, 0x07
+.data1 	0x8b, 0x55, 0xf4, 0x89, 0x17, 0xeb, 0x09, 0x8b
+.data1 	0x55, 0xf4, 0x89, 0x15, 0xbc, 0x09, 0x00, 0x00
+.data1 	0x85, 0xf6, 0x74, 0x15, 0x8b, 0x55, 0xf4, 0x39
+.data1 	0x72, 0xfc, 0x75, 0x0d, 0x8b, 0x4e, 0xfc, 0x89
+.data1 	0x4a, 0xfc, 0x8b, 0x16, 0x8b, 0x45, 0xf4, 0x89
+.data1 	0x10, 0x85, 0xff, 0x74, 0x15, 0x8b, 0x55, 0xf4
+.data1 	0x39, 0x57, 0xfc, 0x75, 0x0d, 0x8b, 0x52, 0xfc
+.data1 	0x89, 0x57, 0xfc, 0x8b, 0x45, 0xf4, 0x8b, 0x10
+.data1 	0x89, 0x17, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x55, 0x08, 0x83, 0xea
+.data1 	0x61, 0x83, 0xfa, 0x1a, 0x73, 0x0a, 0x8b, 0x55
+.data1 	0x08, 0x83, 0xea, 0x20, 0x89, 0xd0, 0xeb, 0x03
+.data1 	0x8b, 0x45, 0x08, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x15
+.data1 	0xa8, 0x09, 0x00, 0x00, 0x39, 0x55, 0x08, 0x74
+.data1 	0x2a, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xf0, 0x8d
+.data1 	0x45, 0xdc, 0x50, 0x6a, 0x11, 0x6a, 0x00, 0xe8
+.data1 	0xa0, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85
+.data1 	0xc0, 0x79, 0x07, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x0b, 0x8b, 0x55, 0xf8, 0x89, 0x15, 0xa8
+.data1 	0x09, 0x00, 0x00, 0x31, 0xc0, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0x57, 0x8b, 0x35, 0xa8, 0x09
+.data1 	0x00, 0x00, 0x8b, 0x15, 0xa8, 0x09, 0x00, 0x00
+.data1 	0x8b, 0x7d, 0x08, 0x01, 0xd7, 0x83, 0x7d, 0x08
+.data1 	0x00, 0x7e, 0x04, 0x39, 0xf7, 0x72, 0x0a, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x79, 0x0b, 0x39, 0xf7, 0x76
+.data1 	0x07, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x14
+.data1 	0x57, 0xe8, 0x8a, 0xff, 0xff, 0xff, 0x59, 0x85
+.data1 	0xc0, 0x75, 0x04, 0x89, 0xf0, 0xeb, 0x05, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x0c, 0xfc, 0xff, 0xff, 0x59, 0xbe, 0x01, 0x00
+.data1 	0x00, 0x00, 0x01, 0xc6, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x72, 0x08, 0x8b, 0x55, 0x0c, 0x8b, 0x4d, 0x08
+.data1 	0x89, 0x4a, 0x10, 0x83, 0xfe, 0x0e, 0x77, 0x11
+.data1 	0x8b, 0x55, 0x0c, 0xff, 0x75, 0x08, 0x83, 0xc2
+.data1 	0x14, 0x52, 0xe8, 0x19, 0x03, 0x00, 0x00, 0x59
+.data1 	0x59, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x10, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x56, 0x04, 0x56, 0xff, 0x75, 0x08, 0xe8, 0x85
+.data1 	0x02, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc7, 0x85
+.data1 	0xff, 0x74, 0x03, 0x89, 0x7e, 0x04, 0x83, 0x7e
+.data1 	0x04, 0x00, 0x79, 0x12, 0x8b, 0x56, 0x04, 0xf7
+.data1 	0xda, 0x89, 0x15, 0xc4, 0x07, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x03, 0x8b, 0x46
+.data1 	0x04, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0xff, 0x75, 0x08, 0xe8, 0x0e, 0x00
+.data1 	0x00, 0x00, 0x59, 0x59, 0x31, 0xdb, 0x85, 0xc0
+.data1 	0x0f, 0x94, 0xc3, 0x89, 0xd8, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0xff, 0x75, 0x0c, 0x68, 0x08
+.data1 	0x54, 0x24, 0x80, 0xff, 0x75, 0x08, 0xe8, 0xbd
+.data1 	0x02, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x10, 0x89
+.data1 	0x55, 0xe8, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf0
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x04, 0x6a, 0x01
+.data1 	0xe8, 0x5f, 0xff, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x14, 0x56, 0x57, 0x8b, 0x75, 0x08, 0xc7
+.data1 	0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x85, 0xf6
+.data1 	0x75, 0x34, 0x31, 0xff, 0x83, 0xff, 0x14, 0x7d
+.data1 	0x25, 0x83, 0x3c, 0xbd, 0x10, 0x08, 0x00, 0x00
+.data1 	0x00, 0x74, 0x18, 0xff, 0x34, 0xbd, 0x10, 0x08
+.data1 	0x00, 0x00, 0xe8, 0xcd, 0xff, 0xff, 0xff, 0x59
+.data1 	0x85, 0xc0, 0x74, 0x07, 0xc7, 0x45, 0xf0, 0xff
+.data1 	0xff, 0xff, 0xff, 0x47, 0xeb, 0xd6, 0x8b, 0x45
+.data1 	0xf0, 0xe9, 0x43, 0x01, 0x00, 0x00, 0x83, 0x7e
+.data1 	0x10, 0x00, 0x74, 0x11, 0x8b, 0x56, 0x08, 0xf6
+.data1 	0xc2, 0x80, 0x75, 0x10, 0xf7, 0x46, 0x08, 0x00
+.data1 	0x01, 0x00, 0x00, 0x75, 0x07, 0x31, 0xc0, 0xe9
+.data1 	0x25, 0x01, 0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6
+.data1 	0xc2, 0x80, 0x0f, 0x84, 0x86, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, 0x00, 0xf7
+.data1 	0x46, 0x08, 0x00, 0x04, 0x00, 0x00, 0x74, 0x07
+.data1 	0x31, 0xc0, 0xe9, 0x02, 0x01, 0x00, 0x00, 0x83
+.data1 	0x7e, 0x10, 0x00, 0x74, 0x0f, 0x8b, 0x56, 0x08
+.data1 	0xf6, 0xc2, 0x04, 0x75, 0x07, 0x8b, 0x16, 0xf7
+.data1 	0xda, 0x89, 0x55, 0xec, 0xc7, 0x06, 0x00, 0x00
+.data1 	0x00, 0x00, 0x6a, 0x01, 0xff, 0x75, 0xec, 0xff
+.data1 	0x76, 0x04, 0xe8, 0x35, 0xee, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x17, 0x83, 0x3d, 0xc4, 0x07, 0x00, 0x00, 0x1d
+.data1 	0x74, 0x0e, 0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xe9, 0xb9, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x05, 0xc4, 0x07, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x02
+.data1 	0x74, 0x07, 0x81, 0x66, 0x08, 0x7f, 0xfe, 0xff
+.data1 	0xff, 0x8b, 0x56, 0x10, 0x89, 0x56, 0x14, 0x31
+.data1 	0xc0, 0xe9, 0x93, 0x00, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x04, 0x74, 0x07, 0x31, 0xc0
+.data1 	0xe9, 0x84, 0x00, 0x00, 0x00, 0x8b, 0x56, 0x08
+.data1 	0xf6, 0xc2, 0x01, 0x74, 0x07, 0x81, 0x66, 0x08
+.data1 	0xff, 0xfe, 0xff, 0xff, 0x8b, 0x56, 0x14, 0x2b
+.data1 	0x56, 0x10, 0x89, 0x55, 0xfc, 0x8b, 0x56, 0x10
+.data1 	0x89, 0x56, 0x14, 0x83, 0x7d, 0xfc, 0x00, 0x7f
+.data1 	0x07, 0x31, 0xc0, 0xe9, 0x59, 0x00, 0x00, 0x00
+.data1 	0xf7, 0x46, 0x08, 0x00, 0x02, 0x00, 0x00, 0x74
+.data1 	0x21, 0x6a, 0x02, 0x6a, 0x00, 0xff, 0x76, 0x04
+.data1 	0xe8, 0x9f, 0xed, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x0b, 0x83
+.data1 	0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x2f, 0xff, 0x75, 0xfc, 0xff, 0x76, 0x10
+.data1 	0xff, 0x76, 0x04, 0xe8, 0x68, 0xfe, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x45, 0xf8, 0xc7, 0x06
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xf8, 0x39
+.data1 	0x55, 0xfc, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x09
+.data1 	0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0x31, 0xf6, 0x83, 0xfe, 0x14, 0x7d, 0x2a
+.data1 	0x83, 0x3c, 0xb5, 0x10, 0x08, 0x00, 0x00, 0x00
+.data1 	0x74, 0x1d, 0x8b, 0x14, 0xb5, 0x10, 0x08, 0x00
+.data1 	0x00, 0xf7, 0x42, 0x08, 0x00, 0x01, 0x00, 0x00
+.data1 	0x74, 0x0d, 0xff, 0x34, 0xb5, 0x10, 0x08, 0x00
+.data1 	0x00, 0xe8, 0x3e, 0xfe, 0xff, 0xff, 0x59, 0x46
+.data1 	0xeb, 0xd1, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x01, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x02
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x03, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0xb9, 0x04, 0x00, 0x00, 0x00
+.data1 	0xcd, 0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x53, 0x8b, 0x5d, 0x08, 0xb9, 0x08, 0x00, 0x00
+.data1 	0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x57, 0x8b, 0x7d, 0x08, 0x30
+.data1 	0xc0, 0x89, 0xca, 0x80, 0xf9, 0x01, 0xfc, 0xf2
+.data1 	0xae, 0x75, 0x01, 0x41, 0x89, 0xd0, 0x29, 0xc8
+.data1 	0x5f, 0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x08
+.data1 	0x8b, 0x75, 0x0c, 0x8b, 0x4d, 0x10, 0xe9, 0x6f
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0xb9, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe8, 0x9d, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x45, 0x08, 0x5f, 0x5e, 0x5d, 0xc3, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xec, 0x8b, 0x55, 0x10, 0x89, 0x55, 0xf8
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x36, 0x6a, 0x01
+.data1 	0xe8, 0xa7, 0xfc, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x7d, 0x08, 0x8b, 0x75, 0x0c, 0x8b
+.data1 	0x4d, 0x10, 0x89, 0xf8, 0x29, 0xf0, 0x39, 0xc8
+.data1 	0x72, 0x2f, 0xfc, 0x83, 0xf9, 0x10, 0x72, 0x20
+.data1 	0x89, 0xf0, 0x09, 0xf8, 0xa8, 0x01, 0x75, 0x18
+.data1 	0xa8, 0x02, 0x75, 0x0d, 0x0f, 0xac, 0xc8, 0x02
+.data1 	0xc1, 0xe9, 0x02, 0xf3, 0xa5, 0x0f, 0xa4, 0xc1
+.data1 	0x02, 0xd1, 0xe9, 0xf3, 0x66, 0xa5, 0x11, 0xc9
+.data1 	0xf3, 0xa4, 0x8b, 0x45, 0x08, 0x5f, 0x5e, 0x5d
+.data1 	0xc3, 0xfd, 0x8d, 0x74, 0x0e, 0xff, 0x8d, 0x7c
+.data1 	0x0f, 0xff, 0xf3, 0xa4, 0xfc, 0xeb, 0xeb, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x7d, 0x0c, 0x30
+.data1 	0xc0, 0x89, 0xca, 0xfc, 0xf2, 0xae, 0x29, 0xca
+.data1 	0x87, 0xca, 0x8b, 0x75, 0x0c, 0x8b, 0x7d, 0x08
+.data1 	0xf3, 0xa4, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x13, 0x8b, 0x4b
+.data1 	0x04, 0x83, 0xc3, 0x08, 0x49, 0x7c, 0x18, 0x3b
+.data1 	0x03, 0x75, 0xf6, 0x8b, 0x5b, 0x04, 0x85, 0xdb
+.data1 	0x75, 0x0b, 0xb8, 0x14, 0x00, 0x00, 0x00, 0x50
+.data1 	0xe9, 0x07, 0x00, 0x00, 0x00, 0xff, 0xe3, 0x89
+.data1 	0xd3, 0xeb, 0xeb, 0x00, 0xe8, 0x47, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x89, 0xc8, 0xd1, 0xf9, 0x73, 0x06, 0x0f
+.data1 	0xbe, 0x03, 0x50, 0xff, 0xe2, 0xd1, 0xf9, 0x73
+.data1 	0x06, 0x0f, 0xbf, 0x03, 0x50, 0xff, 0xe2, 0x52
+.data1 	0x89, 0xf2, 0x89, 0xde, 0x5b, 0x29, 0xc4, 0xeb
+.data1 	0x0a, 0x89, 0xf2, 0x89, 0xde, 0x5b, 0x29, 0xcc
+.data1 	0xc1, 0xf9, 0x02, 0x89, 0xf8, 0x89, 0xe7, 0xf3
+.data1 	0xa5, 0x89, 0xd6, 0x89, 0xc7, 0xff, 0xe3, 0x00
+.data1 	0xe9, 0xf7, 0xea, 0xff, 0xff, 0x00, 0x00, 0x00
+.data1 	0x31, 0xdb, 0x87, 0x1d, 0xac, 0x09, 0x00, 0x00
+.data1 	0x85, 0xdb, 0x74, 0x05, 0x50, 0xff, 0xd3, 0x58
+.data1 	0xc3, 0x50, 0xe8, 0xe1, 0xff, 0xff, 0xff, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x25, 0x73, 0x0a, 0x00
+.data1 	0x62, 0x61, 0x64, 0x20, 0x73, 0x75, 0x70, 0x65
+.data1 	0x72, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20
+.data1 	0x6f, 0x6e, 0x20, 0x25, 0x73, 0x0a, 0x00, 0x00
+.data1 	0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x72, 0x65
+.data1 	0x61, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x75
+.data1 	0x70, 0x65, 0x72, 0x20, 0x62, 0x6c, 0x6f, 0x63
+.data1 	0x6b, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x27
+.data1 	0x25, 0x73, 0x27, 0x3a, 0x20, 0x25, 0x73, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x6f, 0x70, 0x65, 0x6e
+.data1 	0x20, 0x27, 0x25, 0x73, 0x27, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25, 0x73
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x4d, 0x49, 0x4e, 0x49
+.data1 	0x58, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x20, 0x72, 0x65, 0x61, 0x64, 0x69, 0x6e
+.data1 	0x67, 0x20, 0x43, 0x44, 0x20, 0x6c, 0x61, 0x62
+.data1 	0x65, 0x6c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20
+.data1 	0x27, 0x25, 0x73, 0x27, 0x3a, 0x20, 0x25, 0x73
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x6f, 0x70, 0x65, 0x6e
+.data1 	0x20, 0x27, 0x25, 0x73, 0x27, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25, 0x73
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x74
+.data1 	0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x6e, 0x6f, 0x74
+.data1 	0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62
+.data1 	0x6c, 0x65, 0x00, 0x00, 0x53, 0x6f, 0x63, 0x6b
+.data1 	0x65, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61
+.data1 	0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x6e, 0x20
+.data1 	0x6e, 0x6f, 0x6e, 0x2d, 0x73, 0x6f, 0x63, 0x6b
+.data1 	0x65, 0x74, 0x00, 0x00, 0x4d, 0x65, 0x73, 0x73
+.data1 	0x61, 0x67, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x20
+.data1 	0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61
+.data1 	0x64, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x72
+.data1 	0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x00, 0x00
+.data1 	0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20
+.data1 	0x6e, 0x6f, 0x74, 0x20, 0x61, 0x76, 0x61, 0x69
+.data1 	0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00
+.data1 	0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f
+.data1 	0x6e, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x72, 0x6f
+.data1 	0x67, 0x72, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00
+.data1 	0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c
+.data1 	0x20, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x74
+.data1 	0x79, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20
+.data1 	0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x00, 0x00
+.data1 	0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c
+.data1 	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70
+.data1 	0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x62
+.data1 	0x79, 0x20, 0x41, 0x46, 0x00, 0x00, 0x00, 0x00
+.data1 	0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20
+.data1 	0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x20, 0x6e
+.data1 	0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f
+.data1 	0x72, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x00, 0x00, 0x41, 0x6c, 0x72, 0x65
+.data1 	0x61, 0x64, 0x79, 0x20, 0x73, 0x68, 0x75, 0x74
+.data1 	0x64, 0x6f, 0x77, 0x6e, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65
+.data1 	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x75, 0x72, 0x67, 0x65, 0x6e
+.data1 	0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x70
+.data1 	0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x00, 0x00
+.data1 	0x55, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x20, 0x64
+.data1 	0x61, 0x74, 0x61, 0x20, 0x70, 0x72, 0x65, 0x73
+.data1 	0x65, 0x6e, 0x74, 0x00, 0x43, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74
+.data1 	0x69, 0x6d, 0x65, 0x64, 0x20, 0x6f, 0x75, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72
+.data1 	0x65, 0x73, 0x65, 0x74, 0x00, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x72, 0x65, 0x66, 0x75, 0x73
+.data1 	0x65, 0x64, 0x00, 0x00, 0x41, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x75
+.data1 	0x73, 0x65, 0x00, 0x00, 0x41, 0x6c, 0x72, 0x65
+.data1 	0x61, 0x64, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74
+.data1 	0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x6f, 0x74, 0x20
+.data1 	0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c
+.data1 	0x65, 0x00, 0x00, 0x00, 0x42, 0x61, 0x64, 0x20
+.data1 	0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74
+.data1 	0x69, 0x6f, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x00, 0x57, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x6d, 0x6f, 0x64, 0x65
+.data1 	0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6f, 0x63
+.data1 	0x74, 0x6c, 0x00, 0x00, 0x49, 0x6c, 0x6c, 0x65
+.data1 	0x67, 0x61, 0x6c, 0x20, 0x69, 0x6f, 0x63, 0x74
+.data1 	0x6c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x65
+.data1 	0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x65, 0x6e, 0x6f, 0x75
+.data1 	0x67, 0x68, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65
+.data1 	0x72, 0x73, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x00
+.data1 	0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20
+.data1 	0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x73
+.data1 	0x69, 0x7a, 0x65, 0x00, 0x54, 0x6f, 0x6f, 0x20
+.data1 	0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x65, 0x76
+.data1 	0x65, 0x6c, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x73
+.data1 	0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, 0x20
+.data1 	0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x00, 0x00, 0x00
+.data1 	0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72
+.data1 	0x79, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x6d
+.data1 	0x70, 0x74, 0x79, 0x00, 0x46, 0x75, 0x6e, 0x63
+.data1 	0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x6f, 0x74
+.data1 	0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65
+.data1 	0x6e, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x6c, 0x6f, 0x63, 0x6b, 0x73
+.data1 	0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62
+.data1 	0x6c, 0x65, 0x00, 0x00, 0x46, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f
+.data1 	0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x00
+.data1 	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65
+.data1 	0x20, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x6f, 0x63
+.data1 	0x6b, 0x20, 0x61, 0x76, 0x6f, 0x69, 0x64, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x75
+.data1 	0x6c, 0x74, 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c
+.data1 	0x61, 0x72, 0x67, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4d, 0x61, 0x74, 0x68, 0x20, 0x61, 0x72, 0x67
+.data1 	0x75, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00
+.data1 	0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x70
+.data1 	0x69, 0x70, 0x65, 0x00, 0x54, 0x6f, 0x6f, 0x20
+.data1 	0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x69, 0x6e
+.data1 	0x6b, 0x73, 0x00, 0x00, 0x52, 0x65, 0x61, 0x64
+.data1 	0x2d, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x66, 0x69
+.data1 	0x6c, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65
+.data1 	0x6d, 0x00, 0x00, 0x00, 0x49, 0x6c, 0x6c, 0x65
+.data1 	0x67, 0x61, 0x6c, 0x20, 0x73, 0x65, 0x65, 0x6b
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x70, 0x61, 0x63, 0x65, 0x20, 0x6c, 0x65, 0x66
+.data1 	0x74, 0x20, 0x6f, 0x6e, 0x20, 0x64, 0x65, 0x76
+.data1 	0x69, 0x63, 0x65, 0x00, 0x46, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x61, 0x72
+.data1 	0x67, 0x65, 0x00, 0x00, 0x54, 0x65, 0x78, 0x74
+.data1 	0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x62, 0x75
+.data1 	0x73, 0x79, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x61, 0x20, 0x74, 0x79, 0x70, 0x65, 0x77, 0x72
+.data1 	0x69, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00
+.data1 	0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79
+.data1 	0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x66, 0x69
+.data1 	0x6c, 0x65, 0x73, 0x00, 0x46, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f
+.data1 	0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x00
+.data1 	0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20
+.data1 	0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x49, 0x73, 0x20, 0x61
+.data1 	0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f
+.data1 	0x72, 0x79, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x61, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74
+.data1 	0x6f, 0x72, 0x79, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x64, 0x65, 0x76, 0x69
+.data1 	0x63, 0x65, 0x00, 0x00, 0x43, 0x72, 0x6f, 0x73
+.data1 	0x73, 0x2d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x00, 0x00, 0x00
+.data1 	0x46, 0x69, 0x6c, 0x65, 0x20, 0x65, 0x78, 0x69
+.data1 	0x73, 0x74, 0x73, 0x00, 0x52, 0x65, 0x73, 0x6f
+.data1 	0x75, 0x72, 0x63, 0x65, 0x20, 0x62, 0x75, 0x73
+.data1 	0x79, 0x00, 0x00, 0x00, 0x42, 0x6c, 0x6f, 0x63
+.data1 	0x6b, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x42, 0x61, 0x64, 0x20
+.data1 	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x00
+.data1 	0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x64, 0x65, 0x6e, 0x69, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x63
+.data1 	0x6f, 0x72, 0x65, 0x00, 0x52, 0x65, 0x73, 0x6f
+.data1 	0x75, 0x72, 0x63, 0x65, 0x20, 0x74, 0x65, 0x6d
+.data1 	0x70, 0x6f, 0x72, 0x61, 0x72, 0x69, 0x6c, 0x79
+.data1 	0x20, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c
+.data1 	0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64
+.data1 	0x72, 0x65, 0x6e, 0x00, 0x42, 0x61, 0x64, 0x20
+.data1 	0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x75, 0x6d
+.data1 	0x62, 0x65, 0x72, 0x00, 0x45, 0x78, 0x65, 0x63
+.data1 	0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20
+.data1 	0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00
+.data1 	0x41, 0x72, 0x67, 0x20, 0x6c, 0x69, 0x73, 0x74
+.data1 	0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x6f, 0x6e
+.data1 	0x67, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x64, 0x65, 0x76, 0x69
+.data1 	0x63, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x64
+.data1 	0x64, 0x72, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00
+.data1 	0x49, 0x2f, 0x4f, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x74, 0x65
+.data1 	0x72, 0x72, 0x75, 0x70, 0x74, 0x65, 0x64, 0x20
+.data1 	0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x63
+.data1 	0x61, 0x6c, 0x6c, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x70, 0x72, 0x6f, 0x63
+.data1 	0x65, 0x73, 0x73, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x66, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x6f, 0x72, 0x20, 0x64, 0x69, 0x72, 0x65
+.data1 	0x63, 0x74, 0x6f, 0x72, 0x79, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x6f, 0x77, 0x6e, 0x65
+.data1 	0x72, 0x00, 0x00, 0x00, 0x45, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x20, 0x30, 0x00, 0x29, 0x06, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
+.data1 	0xcd, 0x05, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+.data1 	0x02, 0x06, 0x00, 0x00, 0x26, 0x07, 0x00, 0x00
+.data1 	0x08, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x07, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00
+.data1 	0xf4, 0x06, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00
+.data1 	0x06, 0x07, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00
+.data1 	0x06, 0x07, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00
+.data1 	0xfd, 0x06, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x07, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00
+.data1 	0x06, 0x07, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x07, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00
+.data1 	0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
+.data1 	0xf0, 0x07, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00
+.data1 	0xf5, 0x07, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x07, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00
+.data1 	0xe6, 0x07, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00
+.data1 	0xfa, 0x07, 0x00, 0x00, 0xf1, 0x0a, 0x00, 0x00
+.data1 	0x03, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00
+.data1 	0xd9, 0x08, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00
+.data1 	0xc3, 0x08, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00
+.data1 	0xce, 0x08, 0x00, 0x00, 0xf7, 0x08, 0x00, 0x00
+.data1 	0x11, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00
+.data1 	0x8d, 0x0a, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00
+.data1 	0x78, 0x0a, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00
+.data1 	0xe3, 0x09, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00
+.data1 	0xe3, 0x09, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00
+.data1 	0x5f, 0x0a, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00
+.data1 	0x21, 0x0a, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00
+.data1 	0x8d, 0x0a, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00
+.data1 	0x8d, 0x0a, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00
+.data1 	0x78, 0x0a, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00
+.data1 	0x21, 0x0a, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00
+.data1 	0x47, 0x09, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00
+.data1 	0xe3, 0x09, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00
+.data1 	0xe3, 0x09, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00
+.data1 	0xd1, 0x0a, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00
+.data1 	0x9d, 0x09, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00
+.data1 	0xe3, 0x09, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
+.data1 	0xe3, 0x09, 0x00, 0x00, 0x28, 0x6e, 0x75, 0x6c
+.data1 	0x6c, 0x29, 0x00, 0x00, 0x63, 0x61, 0x6e, 0x6e
+.data1 	0x6f, 0x74, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74
+.data1 	0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x69, 0x6e
+.data1 	0x67, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0xc4, 0x09, 0x00, 0x00
+.data1 	0x2f, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x30, 0x64
+.data1 	0x58, 0x00, 0x00, 0x00, 0x2f, 0x64, 0x65, 0x76
+.data1 	0x2f, 0x63, 0x30, 0x64, 0x58, 0x70, 0x59, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x53, 0x53, 0x53, 0x53, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc8, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00
+.data1 	0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20
+.data1 	0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00
+.data1 	0x2c, 0x06, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00
+.data1 	0x04, 0x06, 0x00, 0x00, 0xf4, 0x05, 0x00, 0x00
+.data1 	0xdc, 0x05, 0x00, 0x00, 0xd0, 0x05, 0x00, 0x00
+.data1 	0xb4, 0x05, 0x00, 0x00, 0xa0, 0x05, 0x00, 0x00
+.data1 	0x8c, 0x05, 0x00, 0x00, 0x7c, 0x05, 0x00, 0x00
+.data1 	0x70, 0x05, 0x00, 0x00, 0x4c, 0x05, 0x00, 0x00
+.data1 	0x3c, 0x05, 0x00, 0x00, 0x28, 0x05, 0x00, 0x00
+.data1 	0x1c, 0x05, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00
+.data1 	0xf4, 0x04, 0x00, 0x00, 0xe8, 0x04, 0x00, 0x00
+.data1 	0xd4, 0x04, 0x00, 0x00, 0xc4, 0x04, 0x00, 0x00
+.data1 	0xb4, 0x04, 0x00, 0x00, 0xa4, 0x04, 0x00, 0x00
+.data1 	0x90, 0x04, 0x00, 0x00, 0x7c, 0x04, 0x00, 0x00
+.data1 	0x68, 0x04, 0x00, 0x00, 0x54, 0x04, 0x00, 0x00
+.data1 	0x44, 0x04, 0x00, 0x00, 0x34, 0x04, 0x00, 0x00
+.data1 	0x1c, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00
+.data1 	0xf4, 0x03, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x00
+.data1 	0xd8, 0x03, 0x00, 0x00, 0xc8, 0x03, 0x00, 0x00
+.data1 	0xb4, 0x03, 0x00, 0x00, 0x98, 0x03, 0x00, 0x00
+.data1 	0x84, 0x03, 0x00, 0x00, 0x70, 0x03, 0x00, 0x00
+.data1 	0x54, 0x03, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00
+.data1 	0x1c, 0x03, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00
+.data1 	0x60, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00
+.data1 	0x60, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00
+.data1 	0x60, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00
+.data1 	0x60, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00
+.data1 	0x08, 0x03, 0x00, 0x00, 0xf0, 0x02, 0x00, 0x00
+.data1 	0xd4, 0x02, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x00
+.data1 	0xb4, 0x02, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00
+.data1 	0x80, 0x02, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00
+.data1 	0x5c, 0x02, 0x00, 0x00, 0x48, 0x02, 0x00, 0x00
+.data1 	0x34, 0x02, 0x00, 0x00, 0x1c, 0x02, 0x00, 0x00
+.data1 	0x08, 0x02, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00
+.data1 	0xe0, 0x01, 0x00, 0x00, 0xcc, 0x01, 0x00, 0x00
+.data1 	0xb8, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00
+.data1 	0x78, 0x01, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00
+.data1 	0x40, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00
+.data1 	0x08, 0x01, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00
+.data1 	0xd4, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00
+.data1 	0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x48, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x03, 0x20, 0x10, 0x20, 0x00, 0x00, 0x00
+.data1 	0x80, 0x1c, 0x00, 0x00, 0x94, 0x0a, 0x00, 0x00
+.data1 	0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x28, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0xed, 0x8b, 0x04, 0x24, 0x8d, 0x54, 0x24
+.data1 	0x04, 0x8d, 0x4c, 0x84, 0x08, 0xbb, 0x9c, 0x07
+.data1 	0x00, 0x00, 0x81, 0xfb, 0x94, 0x0a, 0x00, 0x00
+.data1 	0x73, 0x13, 0xf6, 0xc3, 0x03, 0x75, 0x0e, 0x81
+.data1 	0x3b, 0x53, 0x53, 0x53, 0x53, 0x75, 0x06, 0x89
+.data1 	0x1d, 0x90, 0x07, 0x00, 0x00, 0x8b, 0x1d, 0x90
+.data1 	0x07, 0x00, 0x00, 0x89, 0x0b, 0x51, 0x52, 0x50
+.data1 	0x0f, 0x01, 0xe0, 0xa8, 0x04, 0x0f, 0x94, 0x05
+.data1 	0xa0, 0x0a, 0x00, 0x00, 0xe8, 0x07, 0x00, 0x00
+.data1 	0x00, 0x50, 0xe8, 0x46, 0x01, 0x00, 0x00, 0xf4
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x30, 0x56, 0x57
+.data1 	0x8b, 0x75, 0x0c, 0x83, 0x7d, 0x08, 0x01, 0x7e
+.data1 	0x06, 0x83, 0x7d, 0x08, 0x03, 0x7e, 0x20, 0x8b
+.data1 	0x16, 0x52, 0x52, 0x68, 0x38, 0x00, 0x00, 0x00
+.data1 	0x68, 0xd4, 0x07, 0x00, 0x00, 0xe8, 0x0e, 0x03
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x10, 0xb8, 0x01, 0x00
+.data1 	0x00, 0x00, 0xe9, 0xd7, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7d, 0x08, 0x02, 0x75, 0x0e, 0xff, 0x76, 0x04
+.data1 	0xe8, 0xcf, 0x00, 0x00, 0x00, 0x59, 0x89, 0x45
+.data1 	0xf4, 0xeb, 0x22, 0x83, 0x7d, 0x08, 0x03, 0x75
+.data1 	0x1c, 0xff, 0x76, 0x04, 0xe8, 0xbb, 0x00, 0x00
+.data1 	0x00, 0x59, 0xc1, 0xe0, 0x08, 0x50, 0xff, 0x76
+.data1 	0x08, 0xe8, 0xae, 0x00, 0x00, 0x00, 0x59, 0x5a
+.data1 	0x09, 0xd0, 0x89, 0x45, 0xf4, 0x68, 0x30, 0x00
+.data1 	0x00, 0x00, 0xe8, 0x99, 0x03, 0x00, 0x00, 0x59
+.data1 	0x85, 0xc0, 0x79, 0x15, 0x68, 0x24, 0x00, 0x00
+.data1 	0x00, 0xe8, 0xd2, 0x02, 0x00, 0x00, 0x59, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x00, 0xe9, 0x7d, 0x00, 0x00
+.data1 	0x00, 0x68, 0x20, 0x00, 0x00, 0x00, 0xe8, 0x81
+.data1 	0x03, 0x00, 0x00, 0x59, 0x89, 0x45, 0xfc, 0x85
+.data1 	0xc0, 0x75, 0x15, 0x68, 0x14, 0x00, 0x00, 0x00
+.data1 	0xe8, 0xab, 0x02, 0x00, 0x00, 0x59, 0xb8, 0x01
+.data1 	0x00, 0x00, 0x00, 0xe9, 0x56, 0x00, 0x00, 0x00
+.data1 	0xff, 0x75, 0xfc, 0xe8, 0x64, 0x03, 0x00, 0x00
+.data1 	0x59, 0x89, 0xc7, 0x85, 0xc0, 0x74, 0x42, 0x8d
+.data1 	0x45, 0xd0, 0x50, 0x8d, 0x47, 0x05, 0x50, 0xe8
+.data1 	0x58, 0x03, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x78, 0xde, 0x0f, 0xb7, 0x55, 0xd8, 0xf7, 0xc2
+.data1 	0x00, 0x60, 0x00, 0x00, 0x74, 0xd2, 0x0f, 0xbf
+.data1 	0x45, 0xe0, 0x39, 0x45, 0xf4, 0x75, 0xc9, 0x8d
+.data1 	0x47, 0x05, 0x50, 0x68, 0x04, 0x00, 0x00, 0x00
+.data1 	0x68, 0x0c, 0x00, 0x00, 0x00, 0xe8, 0xe2, 0x02
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x31, 0xc0, 0xeb
+.data1 	0x05, 0xb8, 0x01, 0x00, 0x00, 0x00, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x75, 0x08, 0x6a, 0x0a, 0x6a, 0x00, 0x56
+.data1 	0xe8, 0x43, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x5e, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x35, 0x94, 0x07, 0x00, 0x00, 0x4e, 0x78
+.data1 	0x09, 0xff, 0x14, 0xb5, 0xa8, 0x0a, 0x00, 0x00
+.data1 	0xeb, 0xf4, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0xe8, 0xdf, 0xff, 0xff, 0xff, 0x83, 0x3d, 0x98
+.data1 	0x07, 0x00, 0x00, 0x00, 0x74, 0x06, 0xff, 0x15
+.data1 	0x98, 0x07, 0x00, 0x00, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xa4, 0x02, 0x00, 0x00, 0x59, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x75, 0x08, 0x6a
+.data1 	0x01, 0xff, 0x75, 0x10, 0xff, 0x75, 0x0c, 0x56
+.data1 	0xe8, 0x21, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b
+.data1 	0x75, 0x08, 0x6a, 0x00, 0xff, 0x75, 0x10, 0xff
+.data1 	0x75, 0x0c, 0x56, 0xe8, 0x06, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x1c, 0x56, 0x57, 0x8b, 0x75
+.data1 	0x08, 0xc7, 0x45, 0xf8, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xec, 0x01, 0x00, 0x00, 0x00, 0x89, 0x75
+.data1 	0xe8, 0x83, 0x7d, 0x0c, 0x00, 0x74, 0x05, 0x8b
+.data1 	0x45, 0x0c, 0x89, 0x30, 0x0f, 0xbe, 0x06, 0xf6
+.data1 	0x80, 0x3d, 0x08, 0x00, 0x00, 0x08, 0x74, 0x03
+.data1 	0x46, 0xeb, 0xf1, 0x0f, 0xbe, 0x06, 0x89, 0xc7
+.data1 	0x83, 0xff, 0x2d, 0x74, 0x05, 0x83, 0xff, 0x2b
+.data1 	0x75, 0x0d, 0x83, 0xff, 0x2d, 0x75, 0x07, 0xc7
+.data1 	0x45, 0xec, 0xff, 0xff, 0xff, 0xff, 0x46, 0x89
+.data1 	0x75, 0xe4, 0x83, 0x7d, 0x10, 0x00, 0x75, 0x2c
+.data1 	0x80, 0x3e, 0x30, 0x75, 0x1e, 0x46, 0x80, 0x3e
+.data1 	0x78, 0x74, 0x05, 0x80, 0x3e, 0x58, 0x75, 0x0a
+.data1 	0xc7, 0x45, 0x10, 0x10, 0x00, 0x00, 0x00, 0x46
+.data1 	0xeb, 0x29, 0xc7, 0x45, 0x10, 0x08, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x20, 0xc7, 0x45, 0x10, 0x0a, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x17, 0x83, 0x7d, 0x10, 0x10
+.data1 	0x75, 0x11, 0x80, 0x3e, 0x30, 0x75, 0x0c, 0x46
+.data1 	0x80, 0x3e, 0x78, 0x74, 0x05, 0x80, 0x3e, 0x58
+.data1 	0x75, 0x01, 0x46, 0x0f, 0xbe, 0x06, 0x89, 0xc7
+.data1 	0x89, 0xfa, 0x83, 0xea, 0x30, 0x83, 0xfa, 0x09
+.data1 	0x77, 0x0a, 0x89, 0xfa, 0x83, 0xea, 0x30, 0x89
+.data1 	0x55, 0xfc, 0xeb, 0x26, 0x89, 0xfa, 0x83, 0xea
+.data1 	0x61, 0x83, 0xfa, 0x19, 0x77, 0x0a, 0x89, 0xfa
+.data1 	0x83, 0xea, 0x57, 0x89, 0x55, 0xfc, 0xeb, 0x12
+.data1 	0x89, 0xfa, 0x83, 0xea, 0x41, 0x83, 0xfa, 0x19
+.data1 	0x77, 0x37, 0x89, 0xfa, 0x83, 0xea, 0x37, 0x89
+.data1 	0x55, 0xfc, 0x8b, 0x55, 0xfc, 0x39, 0x55, 0x10
+.data1 	0x76, 0x27, 0xba, 0xff, 0xff, 0xff, 0xff, 0x2b
+.data1 	0x55, 0xfc, 0x89, 0xd0, 0x31, 0xd2, 0xf7, 0x75
+.data1 	0x10, 0x39, 0x45, 0xf8, 0x76, 0x03, 0xff, 0x45
+.data1 	0xf0, 0x8b, 0x55, 0x10, 0x0f, 0xaf, 0x55, 0xf8
+.data1 	0x03, 0x55, 0xfc, 0x89, 0x55, 0xf8, 0x46, 0xeb
+.data1 	0x92, 0x83, 0x7d, 0x0c, 0x00, 0x74, 0x14, 0x39
+.data1 	0x75, 0xe4, 0x75, 0x0a, 0x8b, 0x55, 0xe8, 0x8b
+.data1 	0x45, 0x0c, 0x89, 0x10, 0xeb, 0x05, 0x8b, 0x45
+.data1 	0x0c, 0x89, 0x30, 0x83, 0x7d, 0xf0, 0x00, 0x75
+.data1 	0x27, 0x83, 0x7d, 0x14, 0x00, 0x74, 0x21, 0x83
+.data1 	0x7d, 0xec, 0x00, 0x79, 0x09, 0x81, 0x7d, 0xf8
+.data1 	0x00, 0x00, 0x00, 0x80, 0x77, 0x0f, 0x83, 0x7d
+.data1 	0xec, 0x00, 0x7e, 0x0c, 0x81, 0x7d, 0xf8, 0xff
+.data1 	0xff, 0xff, 0x7f, 0x76, 0x03, 0xff, 0x45, 0xf0
+.data1 	0x83, 0x7d, 0xf0, 0x00, 0x74, 0x2b, 0xc7, 0x05
+.data1 	0xa0, 0x07, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x14, 0x00, 0x74, 0x14, 0x83, 0x7d
+.data1 	0xec, 0x00, 0x79, 0x07, 0xb8, 0x00, 0x00, 0x00
+.data1 	0x80, 0xeb, 0x17, 0xb8, 0xff, 0xff, 0xff, 0x7f
+.data1 	0xeb, 0x10, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x09, 0x8b, 0x55, 0xec, 0x0f, 0xaf, 0x55, 0xf8
+.data1 	0x89, 0xd0, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x8d, 0x55
+.data1 	0x10, 0x89, 0x55, 0xfc, 0xff, 0x75, 0x08, 0xff
+.data1 	0x75, 0xfc, 0xff, 0x75, 0x0c, 0xe8, 0xcc, 0x05
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0xff, 0x35, 0xa0
+.data1 	0x07, 0x00, 0x00, 0xe8, 0xdc, 0x00, 0x00, 0x00
+.data1 	0x59, 0x89, 0xc7, 0x8b, 0x35, 0xd8, 0x07, 0x00
+.data1 	0x00, 0x68, 0xbc, 0x07, 0x00, 0x00, 0xe8, 0xe1
+.data1 	0x0b, 0x00, 0x00, 0x59, 0x68, 0xd4, 0x07, 0x00
+.data1 	0x00, 0xe8, 0xd6, 0x0b, 0x00, 0x00, 0x59, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x74, 0x2e, 0x8b, 0x55, 0x08
+.data1 	0x80, 0x3a, 0x00, 0x74, 0x26, 0xff, 0x75, 0x08
+.data1 	0xe8, 0x97, 0x00, 0x00, 0x00, 0x59, 0x50, 0xff
+.data1 	0x75, 0x08, 0x56, 0xe8, 0x4c, 0x03, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x6a, 0x02, 0x68, 0x6c, 0x00
+.data1 	0x00, 0x00, 0x56, 0xe8, 0x3c, 0x03, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x57, 0xe8, 0x73, 0x00, 0x00
+.data1 	0x00, 0x59, 0x50, 0x57, 0x56, 0xe8, 0x2a, 0x03
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x6a, 0x01, 0x68
+.data1 	0x68, 0x00, 0x00, 0x00, 0x56, 0xe8, 0x1a, 0x03
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x08, 0x8d, 0x55, 0x0c, 0x89, 0x55, 0xfc
+.data1 	0x68, 0xbc, 0x07, 0x00, 0x00, 0xff, 0x75, 0xfc
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x1e, 0x05, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x7b, 0x00, 0x00, 0x00, 0xe9, 0x9c, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0xb3, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0xa7, 0x01, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0x8b, 0x02, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xb9, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x75, 0x08, 0x85, 0xf6, 0x78, 0x08, 0x39
+.data1 	0x35, 0x84, 0x0a, 0x00, 0x00, 0x7f, 0x07, 0xb8
+.data1 	0x70, 0x00, 0x00, 0x00, 0xeb, 0x07, 0x8b, 0x04
+.data1 	0xb5, 0x54, 0x09, 0x00, 0x00, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe0, 0x8d, 0x45, 0xd8, 0x50
+.data1 	0x6a, 0x01, 0x6a, 0x00, 0xe8, 0x13, 0x14, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xba, 0xff, 0xff, 0xff
+.data1 	0xff, 0x89, 0x55, 0xfc, 0xff, 0xd2, 0xeb, 0xfe
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0xff, 0x75, 0x08, 0xe8, 0xb6, 0x13
+.data1 	0x00, 0x00, 0x59, 0x59, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x6a, 0x0c, 0x6a, 0x01, 0xe8, 0xe3, 0x13, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55, 0x08, 0x89
+.data1 	0x55, 0xe4, 0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x56
+.data1 	0x6a, 0x01, 0xe8, 0xc5, 0x13, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x34, 0x56, 0x57, 0x8d, 0x45, 0xd0, 0x50
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xd4, 0x01, 0x00, 0x00
+.data1 	0x59, 0x59, 0x85, 0xc0, 0x79, 0x07, 0x31, 0xc0
+.data1 	0xe9, 0xd6, 0x00, 0x00, 0x00, 0x0f, 0xb7, 0x55
+.data1 	0xd8, 0x81, 0xe2, 0x00, 0xf0, 0x00, 0x00, 0x81
+.data1 	0xfa, 0x00, 0x40, 0x00, 0x00, 0x74, 0x11, 0xc7
+.data1 	0x05, 0xa0, 0x07, 0x00, 0x00, 0x14, 0x00, 0x00
+.data1 	0x00, 0x31, 0xc0, 0xe9, 0xb3, 0x00, 0x00, 0x00
+.data1 	0x68, 0x00, 0x08, 0x00, 0x00, 0xff, 0x75, 0x08
+.data1 	0xe8, 0xaf, 0x14, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0xc7, 0x85, 0xc0, 0x79, 0x07, 0x31, 0xc0, 0xe9
+.data1 	0x97, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xd0, 0x50
+.data1 	0x57, 0xe8, 0x1a, 0x14, 0x00, 0x00, 0x59, 0x59
+.data1 	0x85, 0xc0, 0x78, 0x53, 0xc7, 0x05, 0xa0, 0x07
+.data1 	0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0f, 0xb7
+.data1 	0x55, 0xd8, 0x81, 0xe2, 0x00, 0xf0, 0x00, 0x00
+.data1 	0x81, 0xfa, 0x00, 0x40, 0x00, 0x00, 0x75, 0x37
+.data1 	0x6a, 0x01, 0x57, 0xe8, 0x90, 0x13, 0x00, 0x00
+.data1 	0x59, 0x59, 0x89, 0x45, 0xf8, 0x85, 0xc0, 0x78
+.data1 	0x26, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x50, 0x6a
+.data1 	0x02, 0x57, 0xe8, 0x79, 0x13, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x85, 0xc0, 0x78, 0x11, 0x68, 0x54
+.data1 	0x04, 0x00, 0x00, 0xe8, 0x8b, 0x0f, 0x00, 0x00
+.data1 	0x59, 0x89, 0xc6, 0x85, 0xc0, 0x75, 0x1d, 0x8b
+.data1 	0x15, 0xa0, 0x07, 0x00, 0x00, 0x89, 0x55, 0xcc
+.data1 	0x57, 0xe8, 0x32, 0x13, 0x00, 0x00, 0x59, 0x8b
+.data1 	0x55, 0xcc, 0x89, 0x15, 0xa0, 0x07, 0x00, 0x00
+.data1 	0x31, 0xc0, 0xeb, 0x17, 0x89, 0xfa, 0x88, 0x16
+.data1 	0xc6, 0x46, 0x01, 0xff, 0x66, 0xc7, 0x46, 0x02
+.data1 	0x00, 0x00, 0xc7, 0x46, 0x04, 0x00, 0x00, 0x00
+.data1 	0x00, 0x89, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x75, 0x08
+.data1 	0x85, 0xf6, 0x75, 0x11, 0xc7, 0x05, 0xa0, 0x07
+.data1 	0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x31, 0xc0
+.data1 	0xe9, 0xca, 0x00, 0x00, 0x00, 0x0f, 0xbf, 0x46
+.data1 	0x02, 0x85, 0xc0, 0x7f, 0x51, 0x0f, 0xbe, 0x06
+.data1 	0x68, 0x00, 0x04, 0x00, 0x00, 0x8d, 0x5e, 0x0c
+.data1 	0x53, 0x50, 0xe8, 0x31, 0x14, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x0f, 0xbf, 0xc0, 0x66, 0x89, 0x46
+.data1 	0x02, 0x0f, 0xbf, 0x5e, 0x02, 0x85, 0xdb, 0x7f
+.data1 	0x07, 0x31, 0xc0, 0xe9, 0x97, 0x00, 0x00, 0x00
+.data1 	0x0f, 0xbf, 0x46, 0x02, 0xc1, 0xe8, 0x03, 0x0f
+.data1 	0xbf, 0xc0, 0x66, 0x89, 0x46, 0x02, 0x8d, 0x56
+.data1 	0x0c, 0x89, 0x56, 0x08, 0x0f, 0xbe, 0x46, 0x01
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x07, 0x0f
+.data1 	0xbe, 0x46, 0x10, 0x88, 0x46, 0x01, 0x80, 0x7e
+.data1 	0x01, 0x00, 0x75, 0x05, 0x8b, 0x7e, 0x08, 0xeb
+.data1 	0x2c, 0x89, 0xf7, 0x81, 0xc7, 0x0c, 0x04, 0x00
+.data1 	0x00, 0x8b, 0x56, 0x08, 0x8b, 0x12, 0x89, 0x17
+.data1 	0xc6, 0x47, 0x04, 0x07, 0x8b, 0x56, 0x08, 0x6a
+.data1 	0x3c, 0x83, 0xc2, 0x04, 0x52, 0x8d, 0x47, 0x05
+.data1 	0x50, 0xe8, 0xea, 0x0d, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0xc6, 0x47, 0x41, 0x00, 0x0f, 0xb6, 0x57
+.data1 	0x04, 0x42, 0xc1, 0xe2, 0x03, 0x03, 0x56, 0x08
+.data1 	0x89, 0x56, 0x08, 0x0f, 0xbf, 0x46, 0x02, 0x0f
+.data1 	0xb6, 0x57, 0x04, 0x42, 0x29, 0xc2, 0xf7, 0xda
+.data1 	0x89, 0xd0, 0x0f, 0xbf, 0xc0, 0x66, 0x89, 0x46
+.data1 	0x02, 0x0f, 0xb6, 0x57, 0x04, 0x42, 0xc1, 0xe2
+.data1 	0x03, 0x01, 0x56, 0x04, 0x83, 0x3f, 0x00, 0x0f
+.data1 	0x84, 0x38, 0xff, 0xff, 0xff, 0x89, 0xf8, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0xff, 0x75, 0x08, 0xe8, 0x6a, 0xfd
+.data1 	0xff, 0xff, 0x59, 0x05, 0x01, 0x00, 0x00, 0x00
+.data1 	0x89, 0x45, 0xe4, 0x8b, 0x55, 0x08, 0x89, 0x55
+.data1 	0xf0, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf4, 0x8d
+.data1 	0x45, 0xdc, 0x50, 0x6a, 0x12, 0x6a, 0x01, 0xe8
+.data1 	0xa8, 0x11, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4
+.data1 	0x8b, 0x55, 0x10, 0x89, 0x55, 0xe8, 0x8b, 0x55
+.data1 	0x0c, 0x89, 0x55, 0xf0, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x6a, 0x04, 0x6a, 0x01, 0xe8, 0x7b, 0x11, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x56, 0x57
+.data1 	0x8b, 0x75, 0x08, 0x80, 0x3e, 0x2a, 0x75, 0x18
+.data1 	0x8b, 0x45, 0x10, 0x8b, 0x10, 0x83, 0xc2, 0x04
+.data1 	0x8b, 0x45, 0x10, 0x89, 0x10, 0x8b, 0x52, 0xfc
+.data1 	0x8b, 0x45, 0x0c, 0x89, 0x10, 0x46, 0xeb, 0x25
+.data1 	0x31, 0xff, 0x0f, 0xbe, 0x06, 0x2d, 0x30, 0x00
+.data1 	0x00, 0x00, 0x89, 0x45, 0xf8, 0x78, 0x11, 0x83
+.data1 	0x7d, 0xf8, 0x09, 0x7f, 0x0b, 0x6b, 0xdf, 0x0a
+.data1 	0x8b, 0x7d, 0xf8, 0x01, 0xdf, 0x46, 0xeb, 0xe2
+.data1 	0x8b, 0x45, 0x0c, 0x89, 0x38, 0x89, 0xf0, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x10, 0x56, 0x57, 0x8b, 0x75, 0x10, 0x8b, 0x7d
+.data1 	0x08, 0x89, 0x75, 0xf4, 0xe9, 0x80, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7d, 0x1c, 0x00, 0x74, 0x18, 0x8b
+.data1 	0x17, 0x83, 0xc2, 0x04, 0x89, 0x17, 0x8b, 0x42
+.data1 	0xfc, 0x0f, 0xbf, 0xc0, 0x0f, 0xbf, 0xc0, 0x89
+.data1 	0x45, 0xfc, 0xe9, 0x76, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x17, 0x83, 0xc2, 0x04, 0x89, 0x17, 0xb9, 0xff
+.data1 	0xff, 0x00, 0x00, 0x23, 0x4a, 0xfc, 0x89, 0x4d
+.data1 	0xf8, 0xe9, 0x5f, 0x00, 0x00, 0x00, 0x83, 0x7d
+.data1 	0x1c, 0x00, 0x74, 0x12, 0x8b, 0x17, 0x83, 0xc2
+.data1 	0x04, 0x89, 0x17, 0x8b, 0x52, 0xfc, 0x89, 0x55
+.data1 	0xfc, 0xe9, 0x47, 0x00, 0x00, 0x00, 0x8b, 0x17
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x17, 0x8b, 0x52, 0xfc
+.data1 	0x89, 0x55, 0xf8, 0xeb, 0x38, 0x83, 0x7d, 0x1c
+.data1 	0x00, 0x74, 0x0f, 0x8b, 0x17, 0x83, 0xc2, 0x04
+.data1 	0x89, 0x17, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xfc
+.data1 	0xeb, 0x23, 0x8b, 0x17, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x17, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xf8, 0xeb
+.data1 	0x14, 0xba, 0x60, 0x00, 0x00, 0x00, 0x23, 0x55
+.data1 	0x0c, 0xbb, 0x80, 0x00, 0x00, 0x00, 0x89, 0xd0
+.data1 	0xe9, 0xb7, 0x13, 0x00, 0x00, 0x83, 0x7d, 0x1c
+.data1 	0x00, 0x74, 0x2f, 0x83, 0x7d, 0xfc, 0x00, 0x79
+.data1 	0x09, 0xc6, 0x06, 0x2d, 0x46, 0xf7, 0x5d, 0xfc
+.data1 	0xeb, 0x1a, 0x8b, 0x55, 0x0c, 0xf6, 0xc2, 0x02
+.data1 	0x74, 0x06, 0xc6, 0x06, 0x2b, 0x46, 0xeb, 0x0c
+.data1 	0x8b, 0x55, 0x0c, 0xf6, 0xc2, 0x04, 0x74, 0x04
+.data1 	0xc6, 0x06, 0x20, 0x46, 0x8b, 0x55, 0xfc, 0x89
+.data1 	0x55, 0xf8, 0x8b, 0x55, 0x0c, 0xf6, 0xc2, 0x08
+.data1 	0x74, 0x0a, 0x80, 0x7d, 0x14, 0x6f, 0x75, 0x04
+.data1 	0xc6, 0x06, 0x30, 0x46, 0x83, 0x7d, 0xf8, 0x00
+.data1 	0x75, 0x11, 0x83, 0x7d, 0x18, 0x00, 0x0f, 0x85
+.data1 	0x60, 0x00, 0x00, 0x00, 0x89, 0xf0, 0xe9, 0x9f
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0xf6, 0xc2
+.data1 	0x08, 0x74, 0x0c, 0x80, 0x7d, 0x14, 0x78, 0x74
+.data1 	0x0c, 0x80, 0x7d, 0x14, 0x58, 0x74, 0x06, 0x80
+.data1 	0x7d, 0x14, 0x70, 0x75, 0x3f, 0xc6, 0x06, 0x30
+.data1 	0x46, 0x80, 0x7d, 0x14, 0x58, 0x75, 0x07, 0xb8
+.data1 	0x58, 0x00, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0x78
+.data1 	0x00, 0x00, 0x00, 0x88, 0x06, 0x46, 0xeb, 0x24
+.data1 	0xc7, 0x45, 0xf0, 0x02, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x29, 0xc7, 0x45, 0xf0, 0x08, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x20, 0xc7, 0x45, 0xf0, 0x0a, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x17, 0xc7, 0x45, 0xf0, 0x10, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x0e, 0x0f, 0xbe, 0x45, 0x14
+.data1 	0xbb, 0x98, 0x00, 0x00, 0x00, 0xe9, 0xf2, 0x12
+.data1 	0x00, 0x00, 0xff, 0x75, 0x18, 0x56, 0xff, 0x75
+.data1 	0xf0, 0xff, 0x75, 0xf8, 0xe8, 0xf7, 0x0a, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x10, 0x89, 0xc6, 0x80, 0x7d
+.data1 	0x14, 0x58, 0x75, 0x1c, 0x39, 0x75, 0xf4, 0x74
+.data1 	0x17, 0x8b, 0x55, 0xf4, 0x0f, 0xbe, 0x02, 0x50
+.data1 	0xe8, 0xa3, 0x0e, 0x00, 0x00, 0x59, 0x8b, 0x55
+.data1 	0xf4, 0x88, 0x02, 0xff, 0x45, 0xf4, 0xeb, 0xe4
+.data1 	0x89, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x81, 0xec, 0x34, 0x04, 0x00, 0x00, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x10, 0xc7, 0x45, 0xd8, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x45, 0x08, 0xff, 0x45
+.data1 	0x08, 0x0f, 0xbe, 0x00, 0x89, 0x45, 0xf0, 0x85
+.data1 	0xc0, 0x0f, 0x84, 0x0b, 0x06, 0x00, 0x00, 0x83
+.data1 	0x7d, 0xf0, 0x25, 0x0f, 0x84, 0x4d, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x16, 0x4a, 0x89, 0x16, 0x78, 0x13
+.data1 	0x8b, 0x55, 0xf0, 0x0f, 0xb6, 0xca, 0x8b, 0x46
+.data1 	0x14, 0x83, 0x46, 0x14, 0x01, 0x88, 0x08, 0x89
+.data1 	0xc8, 0xeb, 0x0b, 0x56, 0xff, 0x75, 0xf0, 0xe8
+.data1 	0xf0, 0x07, 0x00, 0x00, 0x59, 0x59, 0x3d, 0xff
+.data1 	0xff, 0xff, 0xff, 0x75, 0x1c, 0x83, 0x7d, 0xd8
+.data1 	0x00, 0x74, 0x0c, 0x8b, 0x55, 0xd8, 0xf7, 0xda
+.data1 	0x89, 0xd0, 0xe9, 0xc6, 0x05, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe9, 0xbc, 0x05, 0x00
+.data1 	0x00, 0xff, 0x45, 0xd8, 0xeb, 0x95, 0x31, 0xff
+.data1 	0xeb, 0x21, 0x83, 0xcf, 0x01, 0xeb, 0x2c, 0x83
+.data1 	0xcf, 0x02, 0xeb, 0x27, 0x83, 0xcf, 0x04, 0xeb
+.data1 	0x22, 0x83, 0xcf, 0x08, 0xeb, 0x1d, 0x83, 0xcf
+.data1 	0x10, 0xeb, 0x18, 0x81, 0xcf, 0x00, 0x10, 0x00
+.data1 	0x00, 0xeb, 0x13, 0x8b, 0x55, 0x08, 0x0f, 0xbe
+.data1 	0x02, 0xbb, 0xe0, 0x00, 0x00, 0x00, 0xe9, 0x01
+.data1 	0x12, 0x00, 0x00, 0xff, 0x45, 0x08, 0xf7, 0xc7
+.data1 	0x00, 0x10, 0x00, 0x00, 0x74, 0xe5, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xd4, 0x8d, 0x45, 0x0c, 0x50
+.data1 	0x8d, 0x45, 0xec, 0x50, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x2c, 0xfd, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0x45, 0x08, 0x39, 0x45, 0xd4, 0x74, 0x06, 0x81
+.data1 	0xcf, 0x00, 0x01, 0x00, 0x00, 0x8b, 0x55, 0x08
+.data1 	0x80, 0x3a, 0x2e, 0x75, 0x2b, 0xff, 0x45, 0x08
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xd4, 0x8d, 0x45
+.data1 	0x0c, 0x50, 0x8d, 0x45, 0xe8, 0x50, 0xff, 0x75
+.data1 	0x08, 0xe8, 0xfa, 0xfc, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0x89, 0x45, 0x08, 0x83, 0x7d, 0xe8, 0x00
+.data1 	0x78, 0x06, 0x81, 0xcf, 0x00, 0x02, 0x00, 0x00
+.data1 	0xf7, 0xc7, 0x00, 0x01, 0x00, 0x00, 0x74, 0x0c
+.data1 	0x83, 0x7d, 0xec, 0x00, 0x79, 0x06, 0xf7, 0x5d
+.data1 	0xec, 0x83, 0xcf, 0x01, 0xf7, 0xc7, 0x00, 0x01
+.data1 	0x00, 0x00, 0x75, 0x07, 0xc7, 0x45, 0xec, 0x00
+.data1 	0x00, 0x00, 0x00, 0xf7, 0xc7, 0x02, 0x00, 0x00
+.data1 	0x00, 0x74, 0x03, 0x83, 0xe7, 0xfb, 0xf7, 0xc7
+.data1 	0x01, 0x00, 0x00, 0x00, 0x74, 0x03, 0x83, 0xe7
+.data1 	0xef, 0x8d, 0x95, 0xcf, 0xfb, 0xff, 0xff, 0x89
+.data1 	0x55, 0xd0, 0x89, 0x55, 0xfc, 0xeb, 0x24, 0x83
+.data1 	0xcf, 0x20, 0xff, 0x45, 0x08, 0xe9, 0x23, 0x02
+.data1 	0x00, 0x00, 0x83, 0xcf, 0x40, 0xff, 0x45, 0x08
+.data1 	0xe9, 0x18, 0x02, 0x00, 0x00, 0x81, 0xcf, 0x80
+.data1 	0x00, 0x00, 0x00, 0xff, 0x45, 0x08, 0xe9, 0x0a
+.data1 	0x02, 0x00, 0x00, 0x8b, 0x55, 0x08, 0x0f, 0xbe
+.data1 	0x02, 0xbb, 0x10, 0x01, 0x00, 0x00, 0xe9, 0x21
+.data1 	0x11, 0x00, 0x00, 0x8b, 0x16, 0x4a, 0x89, 0x16
+.data1 	0x78, 0x13, 0x8b, 0x55, 0xf0, 0x0f, 0xb6, 0xca
+.data1 	0x8b, 0x46, 0x14, 0x83, 0x46, 0x14, 0x01, 0x88
+.data1 	0x08, 0x89, 0xc8, 0xeb, 0x0b, 0x56, 0xff, 0x75
+.data1 	0xf0, 0xe8, 0x8e, 0x06, 0x00, 0x00, 0x59, 0x59
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x1c, 0x83
+.data1 	0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b, 0x55, 0xd8
+.data1 	0xf7, 0xda, 0x89, 0xd0, 0xe9, 0x64, 0x04, 0x00
+.data1 	0x00, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x5a
+.data1 	0x04, 0x00, 0x00, 0xff, 0x45, 0xd8, 0xe9, 0x30
+.data1 	0xfe, 0xff, 0xff, 0xf7, 0xc7, 0x20, 0x00, 0x00
+.data1 	0x00, 0x74, 0x1a, 0x8b, 0x45, 0xd8, 0x0f, 0xbf
+.data1 	0xc0, 0x8b, 0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x66, 0x89, 0x02
+.data1 	0xe9, 0x0e, 0xfe, 0xff, 0xff, 0xf7, 0xc7, 0x40
+.data1 	0x00, 0x00, 0x00, 0x74, 0x16, 0x8b, 0x55, 0x0c
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c, 0x8b, 0x52
+.data1 	0xfc, 0x8b, 0x4d, 0xd8, 0x89, 0x0a, 0xe9, 0xf0
+.data1 	0xfd, 0xff, 0xff, 0x8b, 0x55, 0x0c, 0x83, 0xc2
+.data1 	0x04, 0x89, 0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x8b
+.data1 	0x4d, 0xd8, 0x89, 0x0a, 0xe9, 0xda, 0xfd, 0xff
+.data1 	0xff, 0x8b, 0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xd0
+.data1 	0x85, 0xd2, 0x75, 0x07, 0xc7, 0x45, 0xd0, 0xc0
+.data1 	0x01, 0x00, 0x00, 0x8b, 0x55, 0xd0, 0x89, 0x55
+.data1 	0xfc, 0x83, 0x7d, 0xe8, 0x00, 0x75, 0x0c, 0xf7
+.data1 	0xc7, 0x00, 0x02, 0x00, 0x00, 0x0f, 0x85, 0x38
+.data1 	0x01, 0x00, 0x00, 0x8b, 0x55, 0xfc, 0x80, 0x3a
+.data1 	0x00, 0x0f, 0x84, 0x2c, 0x01, 0x00, 0x00, 0xff
+.data1 	0x45, 0xfc, 0xff, 0x4d, 0xe8, 0xeb, 0xda, 0xf7
+.data1 	0xc7, 0x00, 0x02, 0x00, 0x00, 0x75, 0x09, 0xc7
+.data1 	0x45, 0xe8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x09
+.data1 	0x83, 0x7d, 0xf0, 0x70, 0x74, 0x03, 0x83, 0xe7
+.data1 	0xef, 0x8b, 0x45, 0xf0, 0x0f, 0xbe, 0xc0, 0x6a
+.data1 	0x00, 0xff, 0x75, 0xe8, 0x50, 0xff, 0x75, 0xfc
+.data1 	0x57, 0x8d, 0x45, 0x0c, 0x50, 0xe8, 0xa1, 0xfb
+.data1 	0xff, 0xff, 0x83, 0xc4, 0x18, 0x89, 0x45, 0xfc
+.data1 	0xe9, 0xe6, 0x00, 0x00, 0x00, 0x81, 0xcf, 0x00
+.data1 	0x04, 0x00, 0x00, 0xf7, 0xc7, 0x00, 0x02, 0x00
+.data1 	0x00, 0x75, 0x09, 0xc7, 0x45, 0xe8, 0x01, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x03, 0x83, 0xe7, 0xef, 0x8b
+.data1 	0x45, 0xf0, 0x0f, 0xbe, 0xc0, 0x6a, 0x01, 0xff
+.data1 	0x75, 0xe8, 0x50, 0xff, 0x75, 0xfc, 0x57, 0x8d
+.data1 	0x45, 0x0c, 0x50, 0xe8, 0x63, 0xfb, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x18, 0x89, 0x45, 0xfc, 0xe9, 0xa8
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0x83, 0xc2
+.data1 	0x04, 0x89, 0x55, 0x0c, 0x8b, 0x4d, 0xfc, 0x8b
+.data1 	0x52, 0xfc, 0x88, 0x11, 0xff, 0x45, 0xfc, 0xe9
+.data1 	0x8f, 0x00, 0x00, 0x00, 0xf7, 0xc7, 0x00, 0x02
+.data1 	0x00, 0x00, 0x74, 0x0d, 0x83, 0x7d, 0xe8, 0x00
+.data1 	0x75, 0x07, 0xc7, 0x45, 0xe8, 0x01, 0x00, 0x00
+.data1 	0x00, 0xf7, 0xc7, 0x00, 0x02, 0x00, 0x00, 0x75
+.data1 	0x07, 0xc7, 0x45, 0xe8, 0x06, 0x00, 0x00, 0x00
+.data1 	0x81, 0x7d, 0xe8, 0x01, 0x04, 0x00, 0x00, 0x72
+.data1 	0x07, 0xc7, 0x45, 0xe8, 0x00, 0x04, 0x00, 0x00
+.data1 	0x81, 0xcf, 0x00, 0x04, 0x00, 0x00, 0x8b, 0x45
+.data1 	0xf0, 0x0f, 0xbe, 0xc0, 0xff, 0x75, 0xe8, 0x50
+.data1 	0xff, 0x75, 0xfc, 0x57, 0x8d, 0x45, 0x0c, 0x50
+.data1 	0xe8, 0xfb, 0x07, 0x00, 0x00, 0x83, 0xc4, 0x14
+.data1 	0x89, 0x45, 0xfc, 0xeb, 0x36, 0x8b, 0x55, 0x0c
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0x08
+.data1 	0xe9, 0x86, 0xfc, 0xff, 0xff, 0x8b, 0x45, 0x08
+.data1 	0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0x45
+.data1 	0xf0, 0xbb, 0x30, 0x01, 0x00, 0x00, 0xe9, 0x11
+.data1 	0x0f, 0x00, 0x00, 0xc7, 0x45, 0xe4, 0x20, 0x00
+.data1 	0x00, 0x00, 0xf7, 0xc7, 0x10, 0x00, 0x00, 0x00
+.data1 	0x74, 0x07, 0xc7, 0x45, 0xe4, 0x30, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xfc, 0x2b, 0x55, 0xd0, 0x89
+.data1 	0x55, 0xf8, 0xc7, 0x45, 0xdc, 0x00, 0x00, 0x00
+.data1 	0x00, 0xf7, 0xc7, 0x10, 0x00, 0x00, 0x00, 0x74
+.data1 	0x37, 0x83, 0x7d, 0xf0, 0x78, 0x74, 0x06, 0x83
+.data1 	0x7d, 0xf0, 0x58, 0x75, 0x08, 0xf7, 0xc7, 0x08
+.data1 	0x00, 0x00, 0x00, 0x75, 0x20, 0x83, 0x7d, 0xf0
+.data1 	0x70, 0x74, 0x1a, 0xf7, 0xc7, 0x00, 0x04, 0x00
+.data1 	0x00, 0x74, 0x15, 0x8b, 0x55, 0xd0, 0x80, 0x3a
+.data1 	0x2b, 0x74, 0x0a, 0x80, 0x3a, 0x2d, 0x74, 0x05
+.data1 	0x80, 0x3a, 0x20, 0x75, 0x03, 0xff, 0x45, 0xdc
+.data1 	0x8b, 0x55, 0xec, 0x2b, 0x55, 0xf8, 0x89, 0x55
+.data1 	0xf4, 0x85, 0xd2, 0x0f, 0x8e, 0x61, 0x01, 0x00
+.data1 	0x00, 0xf7, 0xc7, 0x01, 0x00, 0x00, 0x00, 0x0f
+.data1 	0x85, 0x55, 0x01, 0x00, 0x00, 0x8b, 0x55, 0xf4
+.data1 	0x01, 0x55, 0xd8, 0x83, 0x7d, 0xdc, 0x00, 0x0f
+.data1 	0x84, 0xf8, 0x00, 0x00, 0x00, 0xf7, 0xc7, 0x00
+.data1 	0x04, 0x00, 0x00, 0x0f, 0x84, 0x5c, 0x00, 0x00
+.data1 	0x00, 0xff, 0x4d, 0xf8, 0xff, 0x45, 0xd8, 0x8b
+.data1 	0x16, 0x4a, 0x89, 0x16, 0x78, 0x16, 0x8b, 0x45
+.data1 	0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xb6, 0x10, 0x8b
+.data1 	0x46, 0x14, 0x83, 0x46, 0x14, 0x01, 0x88, 0x10
+.data1 	0x89, 0xd0, 0xeb, 0x12, 0x8b, 0x45, 0xd0, 0xff
+.data1 	0x45, 0xd0, 0x0f, 0xbe, 0x00, 0x56, 0x50, 0xe8
+.data1 	0xd0, 0x03, 0x00, 0x00, 0x59, 0x59, 0x3d, 0xff
+.data1 	0xff, 0xff, 0xff, 0x0f, 0x85, 0xac, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b
+.data1 	0x55, 0xd8, 0xf7, 0xda, 0x89, 0xd0, 0xe9, 0xa2
+.data1 	0x01, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x98, 0x01, 0x00, 0x00, 0x83, 0x6d, 0xf8
+.data1 	0x02, 0x83, 0x45, 0xd8, 0x02, 0x8b, 0x16, 0x4a
+.data1 	0x89, 0x16, 0x78, 0x16, 0x8b, 0x45, 0xd0, 0xff
+.data1 	0x45, 0xd0, 0x0f, 0xb6, 0x10, 0x8b, 0x46, 0x14
+.data1 	0x83, 0x46, 0x14, 0x01, 0x88, 0x10, 0x89, 0xd0
+.data1 	0xeb, 0x12, 0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0
+.data1 	0x0f, 0xbe, 0x00, 0x56, 0x50, 0xe8, 0x72, 0x03
+.data1 	0x00, 0x00, 0x59, 0x59, 0x3d, 0xff, 0xff, 0xff
+.data1 	0xff, 0x74, 0x36, 0x8b, 0x16, 0x4a, 0x89, 0x16
+.data1 	0x78, 0x16, 0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0
+.data1 	0x0f, 0xb6, 0x10, 0x8b, 0x46, 0x14, 0x83, 0x46
+.data1 	0x14, 0x01, 0x88, 0x10, 0x89, 0xd0, 0xeb, 0x12
+.data1 	0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xbe
+.data1 	0x00, 0x56, 0x50, 0xe8, 0x3c, 0x03, 0x00, 0x00
+.data1 	0x59, 0x59, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x1c, 0x83, 0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b
+.data1 	0x55, 0xd8, 0xf7, 0xda, 0x89, 0xd0, 0xe9, 0x12
+.data1 	0x01, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x08, 0x01, 0x00, 0x00, 0x8b, 0x16, 0x4a
+.data1 	0x89, 0x16, 0x78, 0x13, 0x8b, 0x55, 0xe4, 0x0f
+.data1 	0xb6, 0xca, 0x8b, 0x46, 0x14, 0x83, 0x46, 0x14
+.data1 	0x01, 0x88, 0x08, 0x89, 0xc8, 0xeb, 0x0b, 0x56
+.data1 	0xff, 0x75, 0xe4, 0xe8, 0xf4, 0x02, 0x00, 0x00
+.data1 	0x59, 0x59, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x1c, 0x83, 0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b
+.data1 	0x55, 0xd8, 0xf7, 0xda, 0x89, 0xd0, 0xe9, 0xca
+.data1 	0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0xc0, 0x00, 0x00, 0x00, 0xff, 0x4d, 0xf4
+.data1 	0x75, 0xb3, 0x8b, 0x55, 0xf8, 0x01, 0x55, 0xd8
+.data1 	0xff, 0x4d, 0xf8, 0x0f, 0x88, 0x52, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x16, 0x4a, 0x89, 0x16, 0x78, 0x16
+.data1 	0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xb6
+.data1 	0x10, 0x8b, 0x46, 0x14, 0x83, 0x46, 0x14, 0x01
+.data1 	0x88, 0x10, 0x89, 0xd0, 0xeb, 0x12, 0x8b, 0x45
+.data1 	0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xbe, 0x00, 0x56
+.data1 	0x50, 0xe8, 0x8e, 0x02, 0x00, 0x00, 0x59, 0x59
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0xc1, 0x83
+.data1 	0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b, 0x55, 0xd8
+.data1 	0xf7, 0xda, 0x89, 0xd0, 0xe9, 0x64, 0x00, 0x00
+.data1 	0x00, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x5a
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xf4, 0x00, 0x7e
+.data1 	0x06, 0x8b, 0x55, 0xf4, 0x01, 0x55, 0xd8, 0xff
+.data1 	0x4d, 0xf4, 0x0f, 0x88, 0x23, 0xfa, 0xff, 0xff
+.data1 	0x8b, 0x16, 0x4a, 0x89, 0x16, 0x78, 0x13, 0x8b
+.data1 	0x55, 0xe4, 0x0f, 0xb6, 0xca, 0x8b, 0x46, 0x14
+.data1 	0x83, 0x46, 0x14, 0x01, 0x88, 0x08, 0x89, 0xc8
+.data1 	0xeb, 0x0b, 0x56, 0xff, 0x75, 0xe4, 0xe8, 0x31
+.data1 	0x02, 0x00, 0x00, 0x59, 0x59, 0x3d, 0xff, 0xff
+.data1 	0xff, 0xff, 0x75, 0xcb, 0x83, 0x7d, 0xd8, 0x00
+.data1 	0x74, 0x09, 0x8b, 0x55, 0xd8, 0xf7, 0xda, 0x89
+.data1 	0xd0, 0xeb, 0x0a, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x03, 0x8b, 0x45, 0xd8, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x14, 0x56, 0x57, 0x8b, 0x75, 0x08, 0xc7
+.data1 	0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x85, 0xf6
+.data1 	0x75, 0x34, 0x31, 0xff, 0x83, 0xff, 0x14, 0x7d
+.data1 	0x25, 0x83, 0x3c, 0xbd, 0xec, 0x07, 0x00, 0x00
+.data1 	0x00, 0x74, 0x18, 0xff, 0x34, 0xbd, 0xec, 0x07
+.data1 	0x00, 0x00, 0xe8, 0xcd, 0xff, 0xff, 0xff, 0x59
+.data1 	0x85, 0xc0, 0x74, 0x07, 0xc7, 0x45, 0xf0, 0xff
+.data1 	0xff, 0xff, 0xff, 0x47, 0xeb, 0xd6, 0x8b, 0x45
+.data1 	0xf0, 0xe9, 0x43, 0x01, 0x00, 0x00, 0x83, 0x7e
+.data1 	0x10, 0x00, 0x74, 0x11, 0x8b, 0x56, 0x08, 0xf6
+.data1 	0xc2, 0x80, 0x75, 0x10, 0xf7, 0x46, 0x08, 0x00
+.data1 	0x01, 0x00, 0x00, 0x75, 0x07, 0x31, 0xc0, 0xe9
+.data1 	0x25, 0x01, 0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6
+.data1 	0xc2, 0x80, 0x0f, 0x84, 0x86, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, 0x00, 0xf7
+.data1 	0x46, 0x08, 0x00, 0x04, 0x00, 0x00, 0x74, 0x07
+.data1 	0x31, 0xc0, 0xe9, 0x02, 0x01, 0x00, 0x00, 0x83
+.data1 	0x7e, 0x10, 0x00, 0x74, 0x0f, 0x8b, 0x56, 0x08
+.data1 	0xf6, 0xc2, 0x04, 0x75, 0x07, 0x8b, 0x16, 0xf7
+.data1 	0xda, 0x89, 0x55, 0xec, 0xc7, 0x06, 0x00, 0x00
+.data1 	0x00, 0x00, 0x6a, 0x01, 0xff, 0x75, 0xec, 0xff
+.data1 	0x76, 0x04, 0xe8, 0x8d, 0x09, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x17, 0x83, 0x3d, 0xa0, 0x07, 0x00, 0x00, 0x1d
+.data1 	0x74, 0x0e, 0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xe9, 0xb9, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x05, 0xa0, 0x07, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x02
+.data1 	0x74, 0x07, 0x81, 0x66, 0x08, 0x7f, 0xfe, 0xff
+.data1 	0xff, 0x8b, 0x56, 0x10, 0x89, 0x56, 0x14, 0x31
+.data1 	0xc0, 0xe9, 0x93, 0x00, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x04, 0x74, 0x07, 0x31, 0xc0
+.data1 	0xe9, 0x84, 0x00, 0x00, 0x00, 0x8b, 0x56, 0x08
+.data1 	0xf6, 0xc2, 0x01, 0x74, 0x07, 0x81, 0x66, 0x08
+.data1 	0xff, 0xfe, 0xff, 0xff, 0x8b, 0x56, 0x14, 0x2b
+.data1 	0x56, 0x10, 0x89, 0x55, 0xfc, 0x8b, 0x56, 0x10
+.data1 	0x89, 0x56, 0x14, 0x83, 0x7d, 0xfc, 0x00, 0x7f
+.data1 	0x07, 0x31, 0xc0, 0xe9, 0x59, 0x00, 0x00, 0x00
+.data1 	0xf7, 0x46, 0x08, 0x00, 0x02, 0x00, 0x00, 0x74
+.data1 	0x21, 0x6a, 0x02, 0x6a, 0x00, 0xff, 0x76, 0x04
+.data1 	0xe8, 0xf7, 0x08, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x0b, 0x83
+.data1 	0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x2f, 0xff, 0x75, 0xfc, 0xff, 0x76, 0x10
+.data1 	0xff, 0x76, 0x04, 0xe8, 0x2c, 0xf6, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x45, 0xf8, 0xc7, 0x06
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xf8, 0x39
+.data1 	0x55, 0xfc, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x09
+.data1 	0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0x31, 0xf6, 0x83, 0xfe, 0x14, 0x7d, 0x2a
+.data1 	0x83, 0x3c, 0xb5, 0xec, 0x07, 0x00, 0x00, 0x00
+.data1 	0x74, 0x1d, 0x8b, 0x14, 0xb5, 0xec, 0x07, 0x00
+.data1 	0x00, 0xf7, 0x42, 0x08, 0x00, 0x01, 0x00, 0x00
+.data1 	0x74, 0x0d, 0xff, 0x34, 0xb5, 0xec, 0x07, 0x00
+.data1 	0x00, 0xe8, 0x3e, 0xfe, 0xff, 0xff, 0x59, 0x46
+.data1 	0xeb, 0xd1, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x10
+.data1 	0x57, 0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xb8, 0xf5, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0xc6, 0x85, 0xc0, 0x7e, 0x14, 0x39, 0xfe, 0x7d
+.data1 	0x10, 0x89, 0xfa, 0x29, 0xf2, 0x89, 0xd7, 0x89
+.data1 	0xf2, 0x03, 0x55, 0x0c, 0x89, 0x55, 0x0c, 0xeb
+.data1 	0xd7, 0x31, 0xc0, 0x85, 0xf6, 0x0f, 0x9f, 0xc0
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x08, 0x56, 0x57, 0x8b, 0x75, 0x0c, 0x8b
+.data1 	0x7d, 0x08, 0xc7, 0x05, 0x98, 0x07, 0x00, 0x00
+.data1 	0x3d, 0x11, 0x00, 0x00, 0x83, 0x7e, 0x04, 0x00
+.data1 	0x79, 0x0a, 0x89, 0xfa, 0x0f, 0xb6, 0xc2, 0xe9
+.data1 	0x55, 0x02, 0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6
+.data1 	0xc2, 0x02, 0x75, 0x0a, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x43, 0x02, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x80, 0x74, 0x0f, 0xf6, 0xc2
+.data1 	0x10, 0x75, 0x0a, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x2c, 0x02, 0x00, 0x00, 0x81, 0x66, 0x08
+.data1 	0x7f, 0xff, 0xff, 0xff, 0x81, 0x4e, 0x08, 0x00
+.data1 	0x01, 0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2
+.data1 	0x04, 0x0f, 0x85, 0x8f, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7e, 0x10, 0x00, 0x0f, 0x85, 0x85, 0x00, 0x00
+.data1 	0x00, 0x81, 0xfe, 0xbc, 0x07, 0x00, 0x00, 0x75
+.data1 	0x3e, 0xff, 0x35, 0xc0, 0x07, 0x00, 0x00, 0xe8
+.data1 	0x90, 0x07, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x74
+.data1 	0x2e, 0x68, 0x00, 0x04, 0x00, 0x00, 0xe8, 0x20
+.data1 	0x03, 0x00, 0x00, 0x59, 0x89, 0x46, 0x10, 0x85
+.data1 	0xc0, 0x75, 0x09, 0x83, 0x4e, 0x08, 0x04, 0xe9
+.data1 	0x4c, 0x00, 0x00, 0x00, 0x83, 0x4e, 0x08, 0x48
+.data1 	0xc7, 0x46, 0x0c, 0x00, 0x04, 0x00, 0x00, 0xc7
+.data1 	0x06, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x39, 0x68
+.data1 	0x00, 0x04, 0x00, 0x00, 0xe8, 0xf2, 0x02, 0x00
+.data1 	0x00, 0x59, 0x89, 0x46, 0x10, 0x85, 0xc0, 0x75
+.data1 	0x06, 0x83, 0x4e, 0x08, 0x04, 0xeb, 0x21, 0x83
+.data1 	0x4e, 0x08, 0x08, 0xc7, 0x46, 0x0c, 0x00, 0x04
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x40
+.data1 	0x75, 0x08, 0xc7, 0x06, 0xff, 0x03, 0x00, 0x00
+.data1 	0xeb, 0x06, 0xc7, 0x06, 0xff, 0xff, 0xff, 0xff
+.data1 	0x8b, 0x56, 0x10, 0x89, 0x56, 0x14, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x04, 0x0f, 0x84, 0x68, 0x00
+.data1 	0x00, 0x00, 0x89, 0xfa, 0x88, 0x55, 0xff, 0xc7
+.data1 	0x06, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x46, 0x08
+.data1 	0x00, 0x02, 0x00, 0x00, 0x74, 0x24, 0x6a, 0x02
+.data1 	0x6a, 0x00, 0xff, 0x76, 0x04, 0xe8, 0x12, 0x07
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x3d, 0xff, 0xff
+.data1 	0xff, 0xff, 0x75, 0x0e, 0x83, 0x4e, 0x08, 0x20
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x3f, 0x01
+.data1 	0x00, 0x00, 0x6a, 0x01, 0x8d, 0x45, 0xff, 0x50
+.data1 	0xff, 0x76, 0x04, 0xe8, 0x44, 0xf4, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x3d, 0x01, 0x00, 0x00, 0x00
+.data1 	0x74, 0x0e, 0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xe9, 0x19, 0x01, 0x00, 0x00
+.data1 	0x89, 0xfa, 0x0f, 0xb6, 0xc2, 0xe9, 0x0f, 0x01
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x40
+.data1 	0x0f, 0x84, 0x84, 0x00, 0x00, 0x00, 0x89, 0xfa
+.data1 	0x8b, 0x46, 0x14, 0x83, 0x46, 0x14, 0x01, 0x88
+.data1 	0x10, 0x83, 0xff, 0x0a, 0x74, 0x0d, 0x8b, 0x56
+.data1 	0x0c, 0xf7, 0xda, 0x39, 0x16, 0x0f, 0x85, 0xe1
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x16, 0xf7, 0xda, 0x89
+.data1 	0x55, 0xf8, 0x8b, 0x56, 0x10, 0x89, 0x56, 0x14
+.data1 	0xc7, 0x06, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x46
+.data1 	0x08, 0x00, 0x02, 0x00, 0x00, 0x74, 0x24, 0x6a
+.data1 	0x02, 0x6a, 0x00, 0xff, 0x76, 0x04, 0xe8, 0x79
+.data1 	0x06, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x3d, 0xff
+.data1 	0xff, 0xff, 0xff, 0x75, 0x0e, 0x83, 0x4e, 0x08
+.data1 	0x20, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0xa6
+.data1 	0x00, 0x00, 0x00, 0xff, 0x75, 0xf8, 0xff, 0x76
+.data1 	0x10, 0xff, 0x76, 0x04, 0xe8, 0xdf, 0xfd, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x0f, 0x85
+.data1 	0x88, 0x00, 0x00, 0x00, 0x83, 0x4e, 0x08, 0x20
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x7f, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x14, 0x2b, 0x56, 0x10
+.data1 	0x89, 0x55, 0xf8, 0x8b, 0x56, 0x0c, 0x4a, 0x89
+.data1 	0x16, 0x8b, 0x56, 0x10, 0x83, 0xc2, 0x01, 0x89
+.data1 	0x56, 0x14, 0x83, 0x7d, 0xf8, 0x00, 0x0f, 0x8e
+.data1 	0x51, 0x00, 0x00, 0x00, 0xf7, 0x46, 0x08, 0x00
+.data1 	0x02, 0x00, 0x00, 0x74, 0x21, 0x6a, 0x02, 0x6a
+.data1 	0x00, 0xff, 0x76, 0x04, 0xe8, 0x03, 0x06, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x3d, 0xff, 0xff, 0xff
+.data1 	0xff, 0x75, 0x0b, 0x83, 0x4e, 0x08, 0x20, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x33, 0xff, 0x75
+.data1 	0xf8, 0xff, 0x76, 0x10, 0xff, 0x76, 0x04, 0xe8
+.data1 	0x6c, 0xfd, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x85
+.data1 	0xc0, 0x75, 0x12, 0x89, 0xfa, 0x8b, 0x4e, 0x10
+.data1 	0x88, 0x11, 0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xeb, 0x0c, 0x89, 0xfa, 0x8b
+.data1 	0x4e, 0x10, 0x88, 0x11, 0x89, 0xfa, 0x0f, 0xb6
+.data1 	0xc2, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x75, 0x10
+.data1 	0x8b, 0x45, 0x08, 0x31, 0xd2, 0xf7, 0x75, 0x0c
+.data1 	0x89, 0xd7, 0x8b, 0x45, 0x08, 0x31, 0xd2, 0xf7
+.data1 	0x75, 0x0c, 0x89, 0x45, 0x08, 0x85, 0xc0, 0x75
+.data1 	0x06, 0x83, 0x7d, 0x14, 0x01, 0x7e, 0x16, 0x8b
+.data1 	0x55, 0x14, 0x4a, 0x52, 0x56, 0xff, 0x75, 0x0c
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xc8, 0xff, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x10, 0x89, 0xc6, 0x83, 0xff, 0x09
+.data1 	0x7e, 0x09, 0x89, 0xfa, 0x83, 0xea, 0xa9, 0x89
+.data1 	0xd0, 0xeb, 0x03, 0x8d, 0x47, 0x30, 0x88, 0x06
+.data1 	0x8d, 0x46, 0x01, 0x5f, 0x5e, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x57, 0x8b, 0x7d, 0x08, 0x30
+.data1 	0xc0, 0x89, 0xca, 0x80, 0xf9, 0x01, 0xfc, 0xf2
+.data1 	0xae, 0x75, 0x01, 0x41, 0x89, 0xd0, 0x29, 0xc8
+.data1 	0x5f, 0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x08
+.data1 	0x8b, 0x75, 0x0c, 0x8b, 0x4d, 0x10, 0xe9, 0x7f
+.data1 	0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x68, 0xc8, 0x01, 0x00, 0x00
+.data1 	0x68, 0xd4, 0x07, 0x00, 0x00, 0xe8, 0xa6, 0xee
+.data1 	0xff, 0xff, 0x59, 0x59, 0x6a, 0x01, 0xe8, 0xaa
+.data1 	0xec, 0xff, 0xff, 0x59, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x15, 0x98, 0x0a
+.data1 	0x00, 0x00, 0x03, 0x55, 0x08, 0x39, 0x15, 0x98
+.data1 	0x0a, 0x00, 0x00, 0x77, 0x1f, 0x8b, 0x55, 0x08
+.data1 	0x03, 0x15, 0x98, 0x0a, 0x00, 0x00, 0x81, 0xc2
+.data1 	0xff, 0x0f, 0x00, 0x00, 0x81, 0xe2, 0x00, 0xf0
+.data1 	0xff, 0xff, 0x89, 0xd6, 0x39, 0x15, 0x98, 0x0a
+.data1 	0x00, 0x00, 0x76, 0x0e, 0xc7, 0x05, 0xa0, 0x07
+.data1 	0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x31, 0xc0
+.data1 	0xeb, 0x36, 0x56, 0xe8, 0xe8, 0x02, 0x00, 0x00
+.data1 	0x59, 0x85, 0xc0, 0x74, 0x04, 0x31, 0xc0, 0xeb
+.data1 	0x27, 0x8b, 0x15, 0x98, 0x0a, 0x00, 0x00, 0x89
+.data1 	0x72, 0xfc, 0xc7, 0x46, 0xfc, 0x00, 0x00, 0x00
+.data1 	0x00, 0xff, 0x35, 0x98, 0x0a, 0x00, 0x00, 0xe8
+.data1 	0x26, 0x02, 0x00, 0x00, 0x59, 0x89, 0x35, 0x98
+.data1 	0x0a, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x00
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x18, 0x56, 0x57, 0x83, 0x7d, 0x08, 0x00, 0x75
+.data1 	0x07, 0x31, 0xc0, 0xe9, 0xf4, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7d, 0xe8, 0x02, 0x0f, 0x83, 0xe1, 0x00, 0x00
+.data1 	0x00, 0xba, 0x03, 0x00, 0x00, 0x00, 0x03, 0x55
+.data1 	0x08, 0x83, 0xe2, 0xfc, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x55, 0xec, 0x83, 0xfa, 0x08, 0x73, 0x11, 0xc7
+.data1 	0x05, 0xa0, 0x07, 0x00, 0x00, 0x0c, 0x00, 0x00
+.data1 	0x00, 0x31, 0xc0, 0xe9, 0xbc, 0x00, 0x00, 0x00
+.data1 	0x83, 0x3d, 0x94, 0x0a, 0x00, 0x00, 0x00, 0x75
+.data1 	0x38, 0x6a, 0x08, 0xe8, 0x97, 0x02, 0x00, 0x00
+.data1 	0x59, 0x89, 0xc6, 0x3d, 0xff, 0xff, 0xff, 0xff
+.data1 	0x75, 0x07, 0x31, 0xc0, 0xe9, 0x9b, 0x00, 0x00
+.data1 	0x00, 0x8d, 0x56, 0x03, 0xbe, 0xfc, 0xff, 0xff
+.data1 	0xff, 0x21, 0xd6, 0x83, 0xc6, 0x04, 0x89, 0x35
+.data1 	0x94, 0x0a, 0x00, 0x00, 0x89, 0x35, 0x98, 0x0a
+.data1 	0x00, 0x00, 0xc7, 0x46, 0xfc, 0x00, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x35, 0x9c, 0x0a, 0x00, 0x00, 0x85, 0xf6
+.data1 	0x0f, 0x84, 0x4f, 0x00, 0x00, 0x00, 0x8b, 0x56
+.data1 	0xfc, 0x89, 0x55, 0xf4, 0x89, 0xf2, 0x8b, 0x7d
+.data1 	0xec, 0x01, 0xd7, 0x39, 0x7d, 0xf4, 0x72, 0x36
+.data1 	0x39, 0xf7, 0x76, 0x32, 0x8d, 0x57, 0x04, 0x39
+.data1 	0x55, 0xf4, 0x76, 0x0f, 0x8b, 0x55, 0xf4, 0x89
+.data1 	0x57, 0xfc, 0x89, 0x7e, 0xfc, 0x8b, 0x16, 0x89
+.data1 	0x17, 0x89, 0x3e, 0x83, 0x7d, 0xfc, 0x00, 0x74
+.data1 	0x09, 0x8b, 0x16, 0x8b, 0x45, 0xfc, 0x89, 0x10
+.data1 	0xeb, 0x08, 0x8b, 0x16, 0x89, 0x15, 0x9c, 0x0a
+.data1 	0x00, 0x00, 0x89, 0xf0, 0xeb, 0x1e, 0x89, 0x75
+.data1 	0xfc, 0x8b, 0x36, 0xeb, 0xa9, 0xff, 0x75, 0xec
+.data1 	0xe8, 0x8b, 0xfe, 0xff, 0xff, 0x59, 0x85, 0xc0
+.data1 	0x74, 0x08, 0xff, 0x45, 0xe8, 0xe9, 0x15, 0xff
+.data1 	0xff, 0xff, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x1c, 0x56, 0x57
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xec, 0x85, 0xd2
+.data1 	0x75, 0x0e, 0xff, 0x75, 0x0c, 0xe8, 0xd9, 0xfe
+.data1 	0xff, 0xff, 0x59, 0xe9, 0xe6, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x0c, 0x00, 0x75, 0x10, 0xff, 0x75
+.data1 	0xec, 0xe8, 0xdc, 0x00, 0x00, 0x00, 0x59, 0x31
+.data1 	0xc0, 0xe9, 0xd0, 0x00, 0x00, 0x00, 0xba, 0x03
+.data1 	0x00, 0x00, 0x00, 0x03, 0x55, 0x0c, 0x83, 0xe2
+.data1 	0xfc, 0x83, 0xc2, 0x04, 0x89, 0x55, 0xe8, 0x8b
+.data1 	0x55, 0xec, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xf4
+.data1 	0x2b, 0x55, 0xec, 0x89, 0x55, 0xe4, 0xc7, 0x45
+.data1 	0xfc, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x3d, 0x9c
+.data1 	0x0a, 0x00, 0x00, 0x85, 0xff, 0x0f, 0x84, 0x3c
+.data1 	0x00, 0x00, 0x00, 0x39, 0x7d, 0xf4, 0x72, 0x37
+.data1 	0x39, 0x7d, 0xf4, 0x75, 0x2b, 0x8b, 0x55, 0xec
+.data1 	0x8b, 0x4f, 0xfc, 0x89, 0x4a, 0xfc, 0x83, 0x7d
+.data1 	0xfc, 0x00, 0x74, 0x09, 0x8b, 0x17, 0x8b, 0x45
+.data1 	0xfc, 0x89, 0x10, 0xeb, 0x08, 0x8b, 0x17, 0x89
+.data1 	0x15, 0x9c, 0x0a, 0x00, 0x00, 0x8b, 0x55, 0xec
+.data1 	0x8b, 0x52, 0xfc, 0x89, 0x55, 0xf4, 0xeb, 0x07
+.data1 	0x89, 0x7d, 0xfc, 0x8b, 0x3f, 0xeb, 0xbc, 0x8b
+.data1 	0x55, 0xec, 0x8b, 0x75, 0xe8, 0x01, 0xd6, 0x39
+.data1 	0x75, 0xf4, 0x72, 0x25, 0x39, 0x75, 0xec, 0x77
+.data1 	0x20, 0x8d, 0x56, 0x04, 0x39, 0x55, 0xf4, 0x76
+.data1 	0x13, 0x8b, 0x55, 0xf4, 0x89, 0x56, 0xfc, 0x8b
+.data1 	0x55, 0xec, 0x89, 0x72, 0xfc, 0x56, 0xe8, 0x37
+.data1 	0x00, 0x00, 0x00, 0x59, 0x8b, 0x45, 0xec, 0xeb
+.data1 	0x2d, 0xff, 0x75, 0x0c, 0xe8, 0x12, 0xfe, 0xff
+.data1 	0xff, 0x59, 0x89, 0xc6, 0x85, 0xc0, 0x75, 0x04
+.data1 	0x31, 0xc0, 0xeb, 0x1a, 0xff, 0x75, 0xe4, 0xff
+.data1 	0x75, 0xec, 0x56, 0xe8, 0x40, 0xfd, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0xff, 0x75, 0xec, 0xe8, 0x07
+.data1 	0x00, 0x00, 0x00, 0x59, 0x89, 0xf0, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c
+.data1 	0x56, 0x57, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xf4
+.data1 	0x85, 0xd2, 0x0f, 0x84, 0x62, 0x00, 0x00, 0x00
+.data1 	0x31, 0xff, 0x8b, 0x35, 0x9c, 0x0a, 0x00, 0x00
+.data1 	0x85, 0xf6, 0x74, 0x0b, 0x39, 0x75, 0xf4, 0x72
+.data1 	0x06, 0x89, 0xf7, 0x8b, 0x36, 0xeb, 0xf1, 0x8b
+.data1 	0x45, 0xf4, 0x89, 0x30, 0x85, 0xff, 0x74, 0x07
+.data1 	0x8b, 0x55, 0xf4, 0x89, 0x17, 0xeb, 0x09, 0x8b
+.data1 	0x55, 0xf4, 0x89, 0x15, 0x9c, 0x0a, 0x00, 0x00
+.data1 	0x85, 0xf6, 0x74, 0x15, 0x8b, 0x55, 0xf4, 0x39
+.data1 	0x72, 0xfc, 0x75, 0x0d, 0x8b, 0x4e, 0xfc, 0x89
+.data1 	0x4a, 0xfc, 0x8b, 0x16, 0x8b, 0x45, 0xf4, 0x89
+.data1 	0x10, 0x85, 0xff, 0x74, 0x15, 0x8b, 0x55, 0xf4
+.data1 	0x39, 0x57, 0xfc, 0x75, 0x0d, 0x8b, 0x52, 0xfc
+.data1 	0x89, 0x57, 0xfc, 0x8b, 0x45, 0xf4, 0x8b, 0x10
+.data1 	0x89, 0x17, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x55, 0x08, 0x83, 0xea
+.data1 	0x61, 0x83, 0xfa, 0x1a, 0x73, 0x0a, 0x8b, 0x55
+.data1 	0x08, 0x83, 0xea, 0x20, 0x89, 0xd0, 0xeb, 0x03
+.data1 	0x8b, 0x45, 0x08, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x15
+.data1 	0x88, 0x0a, 0x00, 0x00, 0x39, 0x55, 0x08, 0x74
+.data1 	0x2a, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xf0, 0x8d
+.data1 	0x45, 0xdc, 0x50, 0x6a, 0x11, 0x6a, 0x00, 0xe8
+.data1 	0xa0, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85
+.data1 	0xc0, 0x79, 0x07, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x0b, 0x8b, 0x55, 0xf8, 0x89, 0x15, 0x88
+.data1 	0x0a, 0x00, 0x00, 0x31, 0xc0, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0x57, 0x8b, 0x35, 0x88, 0x0a
+.data1 	0x00, 0x00, 0x8b, 0x15, 0x88, 0x0a, 0x00, 0x00
+.data1 	0x8b, 0x7d, 0x08, 0x01, 0xd7, 0x83, 0x7d, 0x08
+.data1 	0x00, 0x7e, 0x04, 0x39, 0xf7, 0x72, 0x0a, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x79, 0x0b, 0x39, 0xf7, 0x76
+.data1 	0x07, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x14
+.data1 	0x57, 0xe8, 0x8a, 0xff, 0xff, 0xff, 0x59, 0x85
+.data1 	0xc0, 0x75, 0x04, 0x89, 0xf0, 0xeb, 0x05, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xd0, 0xeb, 0xff, 0xff, 0x59, 0xbe, 0x01, 0x00
+.data1 	0x00, 0x00, 0x01, 0xc6, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x72, 0x08, 0x8b, 0x55, 0x0c, 0x8b, 0x4d, 0x08
+.data1 	0x89, 0x4a, 0x10, 0x83, 0xfe, 0x0e, 0x77, 0x11
+.data1 	0x8b, 0x55, 0x0c, 0xff, 0x75, 0x08, 0x83, 0xc2
+.data1 	0x14, 0x52, 0xe8, 0xad, 0x02, 0x00, 0x00, 0x59
+.data1 	0x59, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x10, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x56, 0x04, 0x56, 0xff, 0x75, 0x08, 0xe8, 0xf9
+.data1 	0x01, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc7, 0x85
+.data1 	0xff, 0x74, 0x03, 0x89, 0x7e, 0x04, 0x83, 0x7e
+.data1 	0x04, 0x00, 0x79, 0x12, 0x8b, 0x56, 0x04, 0xf7
+.data1 	0xda, 0x89, 0x15, 0xa0, 0x07, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x03, 0x8b, 0x46
+.data1 	0x04, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x6a, 0x06, 0x6a, 0x01, 0xe8, 0xa3, 0xff, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x56, 0x8d
+.data1 	0x75, 0x10, 0xc7, 0x45, 0xe8, 0x00, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x1a, 0x8d, 0x56, 0x04, 0x89, 0xd6, 0x8b
+.data1 	0x52, 0xfc, 0x89, 0x55, 0xe8, 0xeb, 0x1a, 0x8d
+.data1 	0x56, 0x04, 0x89, 0xd6, 0x8b, 0x52, 0xfc, 0x89
+.data1 	0x55, 0xec, 0xeb, 0x0d, 0xbb, 0x60, 0x07, 0x00
+.data1 	0x00, 0x8b, 0x45, 0x0c, 0xe9, 0x6f, 0x02, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe0, 0x8b
+.data1 	0x55, 0x0c, 0x89, 0x55, 0xe4, 0x8d, 0x45, 0xd8
+.data1 	0x50, 0x6a, 0x37, 0x6a, 0x01, 0xe8, 0x42, 0xff
+.data1 	0xff, 0xff, 0x83, 0xc4, 0x0c, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xf0, 0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x1c
+.data1 	0x6a, 0x01, 0xe8, 0x1d, 0xff, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8d, 0x45, 0xdc, 0x50, 0xff, 0x75
+.data1 	0x08, 0xe8, 0xd6, 0x00, 0x00, 0x00, 0x59, 0x59
+.data1 	0x31, 0xdb, 0x85, 0xc0, 0x0f, 0x94, 0xc3, 0x89
+.data1 	0xd8, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf0, 0x8b, 0x55
+.data1 	0x10, 0x89, 0x55, 0xe8, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x6a, 0x13, 0x6a, 0x01, 0xe8, 0xd3, 0xfe, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x79, 0x07
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x03, 0x8b
+.data1 	0x45, 0xf0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x56, 0x8d, 0x75, 0x10, 0x8b, 0x55
+.data1 	0x0c, 0xf6, 0xc2, 0x40, 0x74, 0x2a, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x46, 0xea, 0xff, 0xff, 0x59, 0x05
+.data1 	0x01, 0x00, 0x00, 0x00, 0x89, 0x45, 0xe0, 0x8b
+.data1 	0x55, 0x0c, 0x89, 0x55, 0xe4, 0x8d, 0x56, 0x04
+.data1 	0x89, 0xd6, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xe8
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xec, 0xeb, 0x14
+.data1 	0x8d, 0x45, 0xd8, 0x50, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x3c, 0xfe, 0xff, 0xff, 0x59, 0x59, 0x8b, 0x55
+.data1 	0x0c, 0x89, 0x55, 0xe4, 0x8d, 0x45, 0xd8, 0x50
+.data1 	0x6a, 0x05, 0x6a, 0x01, 0xe8, 0x63, 0xfe, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x5e, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x10, 0x89
+.data1 	0x55, 0xe8, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf0
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x03, 0x6a, 0x01
+.data1 	0xe8, 0x37, 0xfe, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0xff
+.data1 	0x75, 0x0c, 0x68, 0x08, 0x54, 0x24, 0x80, 0xff
+.data1 	0x75, 0x08, 0xe8, 0xe5, 0x00, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x01
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x02, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x03
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0xb9
+.data1 	0x04, 0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x53, 0x8b, 0x5d, 0x08
+.data1 	0xb9, 0x08, 0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b
+.data1 	0x5d, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x7d, 0x08, 0x8b, 0x75, 0x0c, 0x8b
+.data1 	0x4d, 0x10, 0x89, 0xf8, 0x29, 0xf0, 0x39, 0xc8
+.data1 	0x72, 0x2f, 0xfc, 0x83, 0xf9, 0x10, 0x72, 0x20
+.data1 	0x89, 0xf0, 0x09, 0xf8, 0xa8, 0x01, 0x75, 0x18
+.data1 	0xa8, 0x02, 0x75, 0x0d, 0x0f, 0xac, 0xc8, 0x02
+.data1 	0xc1, 0xe9, 0x02, 0xf3, 0xa5, 0x0f, 0xa4, 0xc1
+.data1 	0x02, 0xd1, 0xe9, 0xf3, 0x66, 0xa5, 0x11, 0xc9
+.data1 	0xf3, 0xa4, 0x8b, 0x45, 0x08, 0x5f, 0x5e, 0x5d
+.data1 	0xc3, 0xfd, 0x8d, 0x74, 0x0e, 0xff, 0x8d, 0x7c
+.data1 	0x0f, 0xff, 0xf3, 0xa4, 0xfc, 0xeb, 0xeb, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0xb9, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x3d
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x45, 0x08, 0x5f, 0x5e
+.data1 	0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x55, 0xec, 0x8b, 0x55
+.data1 	0x10, 0x89, 0x55, 0xf8, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x6a, 0x36, 0x6a, 0x01, 0xe8, 0x13, 0xfd, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x8b, 0x7d, 0x0c, 0x30, 0xc0, 0x89, 0xca, 0xfc
+.data1 	0xf2, 0xae, 0x29, 0xca, 0x87, 0xca, 0x8b, 0x75
+.data1 	0x0c, 0x8b, 0x7d, 0x08, 0xf3, 0xa4, 0xc3, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x13, 0x2b, 0x43, 0x04, 0x3b, 0x43, 0x08
+.data1 	0x77, 0x0c, 0xc1, 0xe0, 0x02, 0x01, 0xc3, 0x8b
+.data1 	0x5b, 0x0c, 0x85, 0xdb, 0x75, 0x11, 0x89, 0xd3
+.data1 	0x85, 0xdb, 0x75, 0x0b, 0xb8, 0x14, 0x00, 0x00
+.data1 	0x00, 0x50, 0xe9, 0x2d, 0x00, 0x00, 0x00, 0xff
+.data1 	0xe3, 0x00, 0x00, 0x00, 0x8b, 0x13, 0x8b, 0x4b
+.data1 	0x04, 0x83, 0xc3, 0x08, 0x49, 0x7c, 0x18, 0x3b
+.data1 	0x03, 0x75, 0xf6, 0x8b, 0x5b, 0x04, 0x85, 0xdb
+.data1 	0x75, 0x0b, 0xb8, 0x14, 0x00, 0x00, 0x00, 0x50
+.data1 	0xe9, 0x07, 0x00, 0x00, 0x00, 0xff, 0xe3, 0x89
+.data1 	0xd3, 0xeb, 0xeb, 0x00, 0xe8, 0x0f, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x5b, 0xe8, 0xff, 0xff, 0x00, 0x00, 0x00
+.data1 	0x31, 0xdb, 0x87, 0x1d, 0x8c, 0x0a, 0x00, 0x00
+.data1 	0x85, 0xdb, 0x74, 0x05, 0x50, 0xff, 0xd3, 0x58
+.data1 	0xc3, 0x50, 0xe8, 0xe1, 0xff, 0xff, 0xff, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x2f, 0x64, 0x65, 0x76
+.data1 	0x00, 0x00, 0x00, 0x00, 0x25, 0x73, 0x2f, 0x25
+.data1 	0x73, 0x0a, 0x00, 0x00, 0x2e, 0x20, 0x69, 0x6e
+.data1 	0x20, 0x2f, 0x64, 0x65, 0x76, 0x00, 0x00, 0x00
+.data1 	0x2e, 0x00, 0x00, 0x00, 0x2f, 0x64, 0x65, 0x76
+.data1 	0x20, 0x63, 0x68, 0x64, 0x69, 0x72, 0x00, 0x00
+.data1 	0x2f, 0x64, 0x65, 0x76, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x0a
+.data1 	0x25, 0x73, 0x20, 0x3c, 0x6d, 0x61, 0x6a, 0x6f
+.data1 	0x72, 0x3e, 0x20, 0x3c, 0x6d, 0x69, 0x6e, 0x6f
+.data1 	0x72, 0x3e, 0x0a, 0x25, 0x73, 0x20, 0x3c, 0x64
+.data1 	0x65, 0x76, 0x69, 0x63, 0x65, 0x6e, 0x75, 0x6d
+.data1 	0x62, 0x65, 0x72, 0x3e, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x3a, 0x20, 0x00, 0x00
+.data1 	0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20
+.data1 	0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00
+.data1 	0x35, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0xd9, 0x07, 0x00, 0x00
+.data1 	0x40, 0x00, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00
+.data1 	0x32, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00
+.data1 	0x58, 0x00, 0x00, 0x00, 0x1b, 0x09, 0x00, 0x00
+.data1 	0x62, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0x12, 0x09, 0x00, 0x00
+.data1 	0x69, 0x00, 0x00, 0x00, 0x12, 0x09, 0x00, 0x00
+.data1 	0x6f, 0x00, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00
+.data1 	0x70, 0x00, 0x00, 0x00, 0x1b, 0x09, 0x00, 0x00
+.data1 	0x75, 0x00, 0x00, 0x00, 0x12, 0x09, 0x00, 0x00
+.data1 	0x78, 0x00, 0x00, 0x00, 0x1b, 0x09, 0x00, 0x00
+.data1 	0x0b, 0x0a, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0xfc, 0x09, 0x00, 0x00
+.data1 	0x23, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00
+.data1 	0x2b, 0x00, 0x00, 0x00, 0xf7, 0x09, 0x00, 0x00
+.data1 	0x2d, 0x00, 0x00, 0x00, 0xf2, 0x09, 0x00, 0x00
+.data1 	0x30, 0x00, 0x00, 0x00, 0x06, 0x0a, 0x00, 0x00
+.data1 	0xfd, 0x0c, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
+.data1 	0x4c, 0x00, 0x00, 0x00, 0xe5, 0x0a, 0x00, 0x00
+.data1 	0x68, 0x00, 0x00, 0x00, 0xcf, 0x0a, 0x00, 0x00
+.data1 	0x6c, 0x00, 0x00, 0x00, 0xda, 0x0a, 0x00, 0x00
+.data1 	0x03, 0x0b, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00
+.data1 	0x45, 0x00, 0x00, 0x00, 0x99, 0x0c, 0x00, 0x00
+.data1 	0x47, 0x00, 0x00, 0x00, 0x84, 0x0c, 0x00, 0x00
+.data1 	0x58, 0x00, 0x00, 0x00, 0xef, 0x0b, 0x00, 0x00
+.data1 	0x62, 0x00, 0x00, 0x00, 0xef, 0x0b, 0x00, 0x00
+.data1 	0x63, 0x00, 0x00, 0x00, 0x6b, 0x0c, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0x2d, 0x0c, 0x00, 0x00
+.data1 	0x65, 0x00, 0x00, 0x00, 0x99, 0x0c, 0x00, 0x00
+.data1 	0x66, 0x00, 0x00, 0x00, 0x99, 0x0c, 0x00, 0x00
+.data1 	0x67, 0x00, 0x00, 0x00, 0x84, 0x0c, 0x00, 0x00
+.data1 	0x69, 0x00, 0x00, 0x00, 0x2d, 0x0c, 0x00, 0x00
+.data1 	0x6e, 0x00, 0x00, 0x00, 0x53, 0x0b, 0x00, 0x00
+.data1 	0x6f, 0x00, 0x00, 0x00, 0xef, 0x0b, 0x00, 0x00
+.data1 	0x70, 0x00, 0x00, 0x00, 0xef, 0x0b, 0x00, 0x00
+.data1 	0x72, 0x00, 0x00, 0x00, 0xdd, 0x0c, 0x00, 0x00
+.data1 	0x73, 0x00, 0x00, 0x00, 0xa9, 0x0b, 0x00, 0x00
+.data1 	0x75, 0x00, 0x00, 0x00, 0xef, 0x0b, 0x00, 0x00
+.data1 	0x78, 0x00, 0x00, 0x00, 0xef, 0x0b, 0x00, 0x00
+.data1 	0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x00, 0x00
+.data1 	0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x70
+.data1 	0x72, 0x69, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x6f
+.data1 	0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x6f
+.data1 	0x69, 0x6e, 0x74, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c
+.data1 	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x76, 0x61
+.data1 	0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00
+.data1 	0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x6f
+.data1 	0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e
+.data1 	0x20, 0x6f, 0x6e, 0x20, 0x6e, 0x6f, 0x6e, 0x2d
+.data1 	0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x00, 0x00
+.data1 	0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20
+.data1 	0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67
+.data1 	0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61
+.data1 	0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x69
+.data1 	0x6e, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65
+.data1 	0x73, 0x73, 0x00, 0x00, 0x41, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20
+.data1 	0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c
+.data1 	0x65, 0x00, 0x00, 0x00, 0x4f, 0x70, 0x65, 0x72
+.data1 	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e
+.data1 	0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73
+.data1 	0x73, 0x00, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x74
+.data1 	0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x77, 0x72, 0x6f
+.data1 	0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20
+.data1 	0x66, 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x63, 0x6b
+.data1 	0x65, 0x74, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x74
+.data1 	0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x6e, 0x6f, 0x74
+.data1 	0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74
+.data1 	0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x41, 0x46
+.data1 	0x00, 0x00, 0x00, 0x00, 0x41, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x20, 0x66, 0x61, 0x6d, 0x69
+.data1 	0x6c, 0x79, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73
+.data1 	0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x63, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00
+.data1 	0x41, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20
+.data1 	0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x63
+.data1 	0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f
+.data1 	0x6e, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x75
+.data1 	0x72, 0x67, 0x65, 0x6e, 0x74, 0x20, 0x64, 0x61
+.data1 	0x74, 0x61, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65
+.data1 	0x6e, 0x74, 0x00, 0x00, 0x55, 0x72, 0x67, 0x65
+.data1 	0x6e, 0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20
+.data1 	0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x00
+.data1 	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x64
+.data1 	0x20, 0x6f, 0x75, 0x74, 0x00, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x65, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72
+.data1 	0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x00, 0x00
+.data1 	0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20
+.data1 	0x69, 0x6e, 0x20, 0x75, 0x73, 0x65, 0x00, 0x00
+.data1 	0x41, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20
+.data1 	0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x44, 0x65, 0x73, 0x74
+.data1 	0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20
+.data1 	0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x61, 0x63
+.data1 	0x68, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x64, 0x65, 0x73, 0x74
+.data1 	0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20
+.data1 	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x00
+.data1 	0x57, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x6c
+.data1 	0x6f, 0x63, 0x6b, 0x00, 0x42, 0x61, 0x64, 0x20
+.data1 	0x6d, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72
+.data1 	0x20, 0x69, 0x6f, 0x63, 0x74, 0x6c, 0x00, 0x00
+.data1 	0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20
+.data1 	0x69, 0x6f, 0x63, 0x74, 0x6c, 0x20, 0x66, 0x6f
+.data1 	0x72, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x62
+.data1 	0x75, 0x66, 0x66, 0x65, 0x72, 0x73, 0x20, 0x6c
+.data1 	0x65, 0x66, 0x74, 0x00, 0x49, 0x6e, 0x76, 0x61
+.data1 	0x6c, 0x69, 0x64, 0x20, 0x70, 0x61, 0x63, 0x6b
+.data1 	0x65, 0x74, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x00
+.data1 	0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79
+.data1 	0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x20
+.data1 	0x6f, 0x66, 0x20, 0x73, 0x79, 0x6d, 0x62, 0x6f
+.data1 	0x6c, 0x69, 0x63, 0x20, 0x6c, 0x69, 0x6e, 0x6b
+.data1 	0x73, 0x00, 0x00, 0x00, 0x44, 0x69, 0x72, 0x65
+.data1 	0x63, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x6e, 0x6f
+.data1 	0x74, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x00
+.data1 	0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e
+.data1 	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6d, 0x70
+.data1 	0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x6c
+.data1 	0x6f, 0x63, 0x6b, 0x73, 0x20, 0x61, 0x76, 0x61
+.data1 	0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00
+.data1 	0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d
+.data1 	0x65, 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x6f
+.data1 	0x6e, 0x67, 0x00, 0x00, 0x52, 0x65, 0x73, 0x6f
+.data1 	0x75, 0x72, 0x63, 0x65, 0x20, 0x64, 0x65, 0x61
+.data1 	0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x61, 0x76
+.data1 	0x6f, 0x69, 0x64, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x74
+.data1 	0x6f, 0x6f, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4d, 0x61, 0x74, 0x68
+.data1 	0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e
+.data1 	0x74, 0x00, 0x00, 0x00, 0x42, 0x72, 0x6f, 0x6b
+.data1 	0x65, 0x6e, 0x20, 0x70, 0x69, 0x70, 0x65, 0x00
+.data1 	0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79
+.data1 	0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x00, 0x00
+.data1 	0x52, 0x65, 0x61, 0x64, 0x2d, 0x6f, 0x6e, 0x6c
+.data1 	0x79, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x73
+.data1 	0x79, 0x73, 0x74, 0x65, 0x6d, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20
+.data1 	0x73, 0x65, 0x65, 0x6b, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65
+.data1 	0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x6f, 0x6e
+.data1 	0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00
+.data1 	0x46, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6f
+.data1 	0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x00, 0x00
+.data1 	0x54, 0x65, 0x78, 0x74, 0x20, 0x66, 0x69, 0x6c
+.data1 	0x65, 0x20, 0x62, 0x75, 0x73, 0x79, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x74, 0x79
+.data1 	0x70, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72
+.data1 	0x00, 0x00, 0x00, 0x00, 0x54, 0x6f, 0x6f, 0x20
+.data1 	0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6f, 0x70, 0x65
+.data1 	0x6e, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x00
+.data1 	0x46, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x61, 0x62
+.data1 	0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x66
+.data1 	0x6c, 0x6f, 0x77, 0x00, 0x49, 0x6e, 0x76, 0x61
+.data1 	0x6c, 0x69, 0x64, 0x20, 0x61, 0x72, 0x67, 0x75
+.data1 	0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00
+.data1 	0x49, 0x73, 0x20, 0x61, 0x20, 0x64, 0x69, 0x72
+.data1 	0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x64, 0x69
+.data1 	0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00
+.data1 	0x43, 0x72, 0x6f, 0x73, 0x73, 0x2d, 0x64, 0x65
+.data1 	0x76, 0x69, 0x63, 0x65, 0x20, 0x6c, 0x69, 0x6e
+.data1 	0x6b, 0x00, 0x00, 0x00, 0x46, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x00
+.data1 	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65
+.data1 	0x20, 0x62, 0x75, 0x73, 0x79, 0x00, 0x00, 0x00
+.data1 	0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x64, 0x65
+.data1 	0x76, 0x69, 0x63, 0x65, 0x20, 0x72, 0x65, 0x71
+.data1 	0x75, 0x69, 0x72, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x61, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x00, 0x50, 0x65, 0x72, 0x6d
+.data1 	0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x64
+.data1 	0x65, 0x6e, 0x69, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x65, 0x6e, 0x6f, 0x75
+.data1 	0x67, 0x68, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x00
+.data1 	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65
+.data1 	0x20, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61
+.data1 	0x72, 0x69, 0x6c, 0x79, 0x20, 0x75, 0x6e, 0x61
+.data1 	0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x63
+.data1 	0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x66, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x00
+.data1 	0x45, 0x78, 0x65, 0x63, 0x20, 0x66, 0x6f, 0x72
+.data1 	0x6d, 0x61, 0x74, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0x41, 0x72, 0x67, 0x20
+.data1 	0x6c, 0x69, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x6f
+.data1 	0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x6f
+.data1 	0x72, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73
+.data1 	0x73, 0x00, 0x00, 0x00, 0x49, 0x2f, 0x4f, 0x20
+.data1 	0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70
+.data1 	0x74, 0x65, 0x64, 0x20, 0x73, 0x79, 0x73, 0x74
+.data1 	0x65, 0x6d, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x66, 0x69, 0x6c, 0x65, 0x20, 0x6f, 0x72, 0x20
+.data1 	0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72
+.data1 	0x79, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x6f, 0x77, 0x6e, 0x65, 0x72, 0x00, 0x00, 0x00
+.data1 	0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x30, 0x00
+.data1 	0x89, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x08, 0x00, 0x00, 0x00, 0x62, 0x19, 0x00, 0x00
+.data1 	0x89, 0x19, 0x00, 0x00, 0x62, 0x19, 0x00, 0x00
+.data1 	0x89, 0x19, 0x00, 0x00, 0x62, 0x19, 0x00, 0x00
+.data1 	0x6f, 0x19, 0x00, 0x00, 0x6f, 0x19, 0x00, 0x00
+.data1 	0x6f, 0x19, 0x00, 0x00, 0x6f, 0x19, 0x00, 0x00
+.data1 	0xa4, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x53, 0x53, 0x53, 0x53
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xa4, 0x07, 0x00, 0x00
+.data1 	0xbc, 0x07, 0x00, 0x00, 0xd4, 0x07, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20
+.data1 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x28
+.data1 	0x28, 0x28, 0x28, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x20, 0x20, 0x20, 0x20, 0x08, 0x10, 0x10
+.data1 	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x10, 0x10, 0x10, 0x10, 0x04, 0x04, 0x04
+.data1 	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x10
+.data1 	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x41, 0x41
+.data1 	0x41, 0x41, 0x41, 0x41, 0x01, 0x01, 0x01, 0x01
+.data1 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+.data1 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+.data1 	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x42, 0x42
+.data1 	0x42, 0x42, 0x42, 0x42, 0x02, 0x02, 0x02, 0x02
+.data1 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+.data1 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+.data1 	0x10, 0x10, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x55, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0x58, 0x07, 0x00, 0x00
+.data1 	0x4c, 0x07, 0x00, 0x00, 0x30, 0x07, 0x00, 0x00
+.data1 	0x20, 0x07, 0x00, 0x00, 0x08, 0x07, 0x00, 0x00
+.data1 	0xfc, 0x06, 0x00, 0x00, 0xe0, 0x06, 0x00, 0x00
+.data1 	0xcc, 0x06, 0x00, 0x00, 0xb8, 0x06, 0x00, 0x00
+.data1 	0xa8, 0x06, 0x00, 0x00, 0x9c, 0x06, 0x00, 0x00
+.data1 	0x78, 0x06, 0x00, 0x00, 0x68, 0x06, 0x00, 0x00
+.data1 	0x54, 0x06, 0x00, 0x00, 0x48, 0x06, 0x00, 0x00
+.data1 	0x30, 0x06, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00
+.data1 	0x14, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00
+.data1 	0xf0, 0x05, 0x00, 0x00, 0xe0, 0x05, 0x00, 0x00
+.data1 	0xd0, 0x05, 0x00, 0x00, 0xbc, 0x05, 0x00, 0x00
+.data1 	0xa8, 0x05, 0x00, 0x00, 0x94, 0x05, 0x00, 0x00
+.data1 	0x80, 0x05, 0x00, 0x00, 0x70, 0x05, 0x00, 0x00
+.data1 	0x60, 0x05, 0x00, 0x00, 0x48, 0x05, 0x00, 0x00
+.data1 	0x38, 0x05, 0x00, 0x00, 0x20, 0x05, 0x00, 0x00
+.data1 	0x10, 0x05, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00
+.data1 	0xf4, 0x04, 0x00, 0x00, 0xe0, 0x04, 0x00, 0x00
+.data1 	0xc4, 0x04, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00
+.data1 	0x9c, 0x04, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00
+.data1 	0x6c, 0x04, 0x00, 0x00, 0x48, 0x04, 0x00, 0x00
+.data1 	0x44, 0x09, 0x00, 0x00, 0x44, 0x09, 0x00, 0x00
+.data1 	0x44, 0x09, 0x00, 0x00, 0x44, 0x09, 0x00, 0x00
+.data1 	0x44, 0x09, 0x00, 0x00, 0x44, 0x09, 0x00, 0x00
+.data1 	0x44, 0x09, 0x00, 0x00, 0x44, 0x09, 0x00, 0x00
+.data1 	0x44, 0x09, 0x00, 0x00, 0x34, 0x04, 0x00, 0x00
+.data1 	0x1c, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00
+.data1 	0xec, 0x03, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00
+.data1 	0xc8, 0x03, 0x00, 0x00, 0xac, 0x03, 0x00, 0x00
+.data1 	0x98, 0x03, 0x00, 0x00, 0x88, 0x03, 0x00, 0x00
+.data1 	0x74, 0x03, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00
+.data1 	0x48, 0x03, 0x00, 0x00, 0x34, 0x03, 0x00, 0x00
+.data1 	0x1c, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00
+.data1 	0xf8, 0x02, 0x00, 0x00, 0xe4, 0x02, 0x00, 0x00
+.data1 	0xc4, 0x02, 0x00, 0x00, 0xa4, 0x02, 0x00, 0x00
+.data1 	0x84, 0x02, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00
+.data1 	0x54, 0x02, 0x00, 0x00, 0x34, 0x02, 0x00, 0x00
+.data1 	0x20, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00
+.data1 	0xe8, 0x01, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00
+.data1 	0x28, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x03, 0x20, 0x10, 0x20, 0x00, 0x00, 0x00
+.data1 	0x00, 0x29, 0x00, 0x00, 0xe8, 0x05, 0x00, 0x00
+.data1 	0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x18, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0xed, 0x8b, 0x04, 0x24, 0x8d, 0x54, 0x24
+.data1 	0x04, 0x8d, 0x4c, 0x84, 0x08, 0xbb, 0xd8, 0x05
+.data1 	0x00, 0x00, 0x81, 0xfb, 0xe8, 0x05, 0x00, 0x00
+.data1 	0x73, 0x13, 0xf6, 0xc3, 0x03, 0x75, 0x0e, 0x81
+.data1 	0x3b, 0x53, 0x53, 0x53, 0x53, 0x75, 0x06, 0x89
+.data1 	0x1d, 0x0c, 0x05, 0x00, 0x00, 0x8b, 0x1d, 0x0c
+.data1 	0x05, 0x00, 0x00, 0x89, 0x0b, 0x51, 0x52, 0x50
+.data1 	0x0f, 0x01, 0xe0, 0xa8, 0x04, 0x0f, 0x94, 0x05
+.data1 	0x84, 0x15, 0x00, 0x00, 0xe8, 0x07, 0x00, 0x00
+.data1 	0x00, 0x50, 0xe8, 0x3a, 0x25, 0x00, 0x00, 0xf4
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0xc7, 0x05, 0x2c
+.data1 	0x07, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0xc7
+.data1 	0x05, 0x1c, 0x07, 0x00, 0x00, 0xff, 0xff, 0xff
+.data1 	0x7f, 0xc7, 0x05, 0x18, 0x07, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0xbe, 0xe8, 0x05, 0x00, 0x00
+.data1 	0x81, 0xfe, 0xd8, 0x06, 0x00, 0x00, 0x73, 0x21
+.data1 	0xc7, 0x06, 0xff, 0xff, 0xff, 0xff, 0xc6, 0x46
+.data1 	0x15, 0x64, 0xc6, 0x46, 0x16, 0xff, 0xc7, 0x46
+.data1 	0x1c, 0xff, 0xff, 0xff, 0x7f, 0xc7, 0x46, 0x18
+.data1 	0x00, 0x00, 0x00, 0x00, 0x83, 0xc6, 0x78, 0xeb
+.data1 	0xd7, 0xc7, 0x05, 0xd8, 0x06, 0x00, 0x00, 0x06
+.data1 	0x00, 0x00, 0x00, 0x68, 0xd8, 0x06, 0x00, 0x00
+.data1 	0x6a, 0x00, 0x6a, 0x06, 0x6a, 0x01, 0xe8, 0x65
+.data1 	0x1d, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x89, 0xc7
+.data1 	0x85, 0xc0, 0x74, 0x13, 0x57, 0x68, 0x24, 0x00
+.data1 	0x00, 0x00, 0x68, 0x3c, 0x00, 0x00, 0x00, 0xe8
+.data1 	0xa4, 0x1c, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x68
+.data1 	0xd8, 0x06, 0x00, 0x00, 0x6a, 0x00, 0x6a, 0x00
+.data1 	0x6a, 0x03, 0xe8, 0x39, 0x1d, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x10, 0x89, 0xc7, 0x85, 0xc0, 0x74, 0x13
+.data1 	0x57, 0x68, 0x04, 0x00, 0x00, 0x00, 0x68, 0x1c
+.data1 	0x00, 0x00, 0x00, 0xe8, 0x78, 0x1c, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x68, 0x54, 0x05, 0x00, 0x00
+.data1 	0xe8, 0x0f, 0x14, 0x00, 0x00, 0x59, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08
+.data1 	0x56, 0x8d, 0x45, 0xfc, 0x50, 0xe8, 0xd2, 0x1e
+.data1 	0x00, 0x00, 0x59, 0x89, 0xc6, 0x85, 0xc0, 0x74
+.data1 	0x13, 0x56, 0x68, 0x6c, 0x00, 0x00, 0x00, 0x68
+.data1 	0x8c, 0x00, 0x00, 0x00, 0xe8, 0x3f, 0x1c, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x6a, 0x00, 0xff, 0x75
+.data1 	0xfc, 0x68, 0x28, 0x07, 0x00, 0x00, 0xe8, 0xf5
+.data1 	0x22, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x83, 0x3d
+.data1 	0x28, 0x07, 0x00, 0x00, 0x00, 0x75, 0x0c, 0xc7
+.data1 	0x05, 0x2c, 0x07, 0x00, 0x00, 0xff, 0xff, 0xff
+.data1 	0x7f, 0xeb, 0x37, 0x8b, 0x15, 0x28, 0x07, 0x00
+.data1 	0x00, 0x8b, 0x52, 0x04, 0x89, 0x15, 0x2c, 0x07
+.data1 	0x00, 0x00, 0x6a, 0x01, 0xff, 0x35, 0x2c, 0x07
+.data1 	0x00, 0x00, 0xe8, 0x51, 0x1d, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0xc6, 0x85, 0xc0, 0x74, 0x13, 0x56
+.data1 	0x68, 0x44, 0x00, 0x00, 0x00, 0x68, 0x64, 0x00
+.data1 	0x00, 0x00, 0xe8, 0xe1, 0x1b, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x04, 0x56, 0x8d, 0x45, 0xfc, 0x50
+.data1 	0xe8, 0x47, 0x1e, 0x00, 0x00, 0x59, 0x89, 0xc6
+.data1 	0x85, 0xc0, 0x74, 0x13, 0x56, 0x68, 0xbc, 0x00
+.data1 	0x00, 0x00, 0x68, 0xdc, 0x00, 0x00, 0x00, 0xe8
+.data1 	0xb4, 0x1b, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b
+.data1 	0x55, 0x0c, 0x03, 0x55, 0xfc, 0x6a, 0x00, 0xff
+.data1 	0x75, 0x10, 0x52, 0xff, 0x75, 0x08, 0x68, 0x28
+.data1 	0x07, 0x00, 0x00, 0xe8, 0xac, 0x22, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x14, 0x8b, 0x15, 0x28, 0x07, 0x00
+.data1 	0x00, 0x8b, 0x0d, 0x2c, 0x07, 0x00, 0x00, 0x39
+.data1 	0x4a, 0x04, 0x74, 0x31, 0x8b, 0x52, 0x04, 0x89
+.data1 	0x15, 0x2c, 0x07, 0x00, 0x00, 0x6a, 0x01, 0xff
+.data1 	0x35, 0x2c, 0x07, 0x00, 0x00, 0xe8, 0xc6, 0x1c
+.data1 	0x00, 0x00, 0x59, 0x59, 0x89, 0xc6, 0x85, 0xc0
+.data1 	0x74, 0x13, 0x56, 0x68, 0x94, 0x00, 0x00, 0x00
+.data1 	0x68, 0xb4, 0x00, 0x00, 0x00, 0xe8, 0x56, 0x1b
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x56, 0x8b
+.data1 	0x75, 0x08, 0x89, 0x35, 0xe8, 0x06, 0x00, 0x00
+.data1 	0xba, 0x03, 0xff, 0xff, 0xff, 0x21, 0xf2, 0x89
+.data1 	0x15, 0xe4, 0x06, 0x00, 0x00, 0x83, 0x3d, 0xe4
+.data1 	0x06, 0x00, 0x00, 0x02, 0x72, 0x07, 0x31, 0xc0
+.data1 	0xe9, 0xa9, 0x00, 0x00, 0x00, 0x6b, 0x05, 0xe4
+.data1 	0x06, 0x00, 0x00, 0x78, 0x05, 0xe8, 0x05, 0x00
+.data1 	0x00, 0xa3, 0xec, 0x06, 0x00, 0x00, 0x05, 0x28
+.data1 	0x00, 0x00, 0x00, 0xa3, 0x00, 0x07, 0x00, 0x00
+.data1 	0x8b, 0x15, 0xec, 0x06, 0x00, 0x00, 0x0f, 0xb6
+.data1 	0x4a, 0x15, 0x83, 0xf9, 0x07, 0x7d, 0x56, 0x8b
+.data1 	0x15, 0xec, 0x06, 0x00, 0x00, 0x0f, 0xb6, 0x4a
+.data1 	0x15, 0x8d, 0x14, 0xcd, 0x10, 0x05, 0x00, 0x00
+.data1 	0x89, 0x15, 0xf0, 0x06, 0x00, 0x00, 0x0f, 0xb6
+.data1 	0x0a, 0x89, 0x0d, 0xf8, 0x06, 0x00, 0x00, 0x8b
+.data1 	0x15, 0xf0, 0x06, 0x00, 0x00, 0xd1, 0xe1, 0x0f
+.data1 	0xb6, 0x5a, 0x01, 0x0f, 0xaf, 0xd9, 0x68, 0x00
+.data1 	0x02, 0x00, 0x00, 0x53, 0x8d, 0x45, 0xf8, 0x50
+.data1 	0xe8, 0x8b, 0x23, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x8b, 0x15, 0xec, 0x06, 0x00, 0x00, 0x50, 0x83
+.data1 	0xc2, 0x30, 0x52, 0xb9, 0x02, 0x00, 0x00, 0x00
+.data1 	0xe8, 0x87, 0x25, 0x00, 0x00, 0x83, 0xe6, 0x7c
+.data1 	0x83, 0xfe, 0x70, 0x7c, 0x1c, 0x8b, 0x15, 0xec
+.data1 	0x06, 0x00, 0x00, 0x89, 0xf1, 0x83, 0xe9, 0x70
+.data1 	0xc1, 0xf9, 0x02, 0xc1, 0xe1, 0x04, 0x83, 0xc2
+.data1 	0x38, 0x01, 0xd1, 0x89, 0x0d, 0x00, 0x07, 0x00
+.data1 	0x00, 0xa1, 0x00, 0x07, 0x00, 0x00, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0xba, 0x30, 0x00, 0x00
+.data1 	0x00, 0x03, 0x15, 0xe4, 0x06, 0x00, 0x00, 0x88
+.data1 	0x15, 0x8e, 0x05, 0x00, 0x00, 0xb8, 0x8c, 0x05
+.data1 	0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b
+.data1 	0x15, 0xec, 0x06, 0x00, 0x00, 0x8b, 0x0d, 0xe4
+.data1 	0x06, 0x00, 0x00, 0x89, 0x4a, 0x24, 0x8b, 0x15
+.data1 	0xec, 0x06, 0x00, 0x00, 0x68, 0xf3, 0x09, 0x00
+.data1 	0x00, 0x68, 0xb4, 0x00, 0x00, 0x00, 0x83, 0xc2
+.data1 	0x18, 0x52, 0xe8, 0x56, 0xfe, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x8b, 0x15, 0xec, 0x06, 0x00, 0x00
+.data1 	0xc7, 0x42, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x81, 0xec, 0x8c, 0x00
+.data1 	0x00, 0x00, 0x56, 0x57, 0x8b, 0x7d, 0x14, 0x8b
+.data1 	0x15, 0xec, 0x06, 0x00, 0x00, 0x89, 0x55, 0xfc
+.data1 	0x8b, 0x55, 0x18, 0xc1, 0xe2, 0x03, 0x01, 0xfa
+.data1 	0x89, 0x55, 0xf4, 0x8b, 0x15, 0x00, 0x07, 0x00
+.data1 	0x00, 0xff, 0x72, 0x0c, 0xff, 0x72, 0x08, 0xe8
+.data1 	0x88, 0x22, 0x00, 0x00, 0x59, 0x59, 0x89, 0x45
+.data1 	0xd0, 0xf7, 0x45, 0x10, 0xff, 0x01, 0x00, 0x00
+.data1 	0x74, 0x0a, 0xb8, 0xea, 0xff, 0xff, 0xff, 0xe9
+.data1 	0x6d, 0x04, 0x00, 0x00, 0xc7, 0x45, 0xe8, 0x00
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0x18, 0x00, 0x0f
+.data1 	0x84, 0x5a, 0x04, 0x00, 0x00, 0x31, 0xf6, 0x89
+.data1 	0x7d, 0xf8, 0x8b, 0x55, 0xf4, 0x39, 0x55, 0xf8
+.data1 	0x73, 0x0c, 0x8b, 0x55, 0xf8, 0x03, 0x72, 0x04
+.data1 	0x83, 0x45, 0xf8, 0x08, 0xeb, 0xec, 0x8b, 0x55
+.data1 	0xd0, 0x39, 0x55, 0x10, 0x72, 0x07, 0x31, 0xc0
+.data1 	0xe9, 0x34, 0x04, 0x00, 0x00, 0x8b, 0x55, 0x10
+.data1 	0x01, 0xf2, 0x39, 0x55, 0xd0, 0x73, 0x08, 0x8b
+.data1 	0x55, 0xd0, 0x2b, 0x55, 0x10, 0x89, 0xd6, 0x8b
+.data1 	0x15, 0x00, 0x07, 0x00, 0x00, 0x68, 0x00, 0x02
+.data1 	0x00, 0x00, 0xff, 0x75, 0x10, 0xff, 0x72, 0x04
+.data1 	0xff, 0x32, 0x8d, 0x85, 0x74, 0xff, 0xff, 0xff
+.data1 	0x50, 0xe8, 0xae, 0x21, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x10, 0xff, 0x70, 0x04, 0xff, 0x30, 0xe8, 0x0d
+.data1 	0x22, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45
+.data1 	0xe4, 0xf7, 0xc6, 0xff, 0x01, 0x00, 0x00, 0x74
+.data1 	0x0a, 0xb8, 0xea, 0xff, 0xff, 0xff, 0xe9, 0xde
+.data1 	0x03, 0x00, 0x00, 0x8b, 0x15, 0xe8, 0x06, 0x00
+.data1 	0x00, 0xf6, 0xc2, 0x80, 0x0f, 0x84, 0x82, 0x00
+.data1 	0x00, 0x00, 0x81, 0x7d, 0x0c, 0x08, 0x04, 0x00
+.data1 	0x00, 0x74, 0x0a, 0xb8, 0xfb, 0xff, 0xff, 0xff
+.data1 	0xe9, 0xbc, 0x03, 0x00, 0x00, 0x81, 0x7f, 0x04
+.data1 	0x0b, 0x02, 0x00, 0x00, 0x73, 0x0a, 0xb8, 0xea
+.data1 	0xff, 0xff, 0xff, 0xe9, 0xa9, 0x03, 0x00, 0x00
+.data1 	0xba, 0x00, 0x02, 0x00, 0x00, 0x03, 0x17, 0x6a
+.data1 	0x0b, 0x68, 0x04, 0x07, 0x00, 0x00, 0x6a, 0x01
+.data1 	0x68, 0xce, 0x8a, 0x00, 0x00, 0x52, 0x6a, 0x01
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xb4, 0x1a, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x1c, 0x89, 0x45, 0xf0, 0x85, 0xc0
+.data1 	0x74, 0x15, 0xff, 0x75, 0xf0, 0x68, 0x34, 0x01
+.data1 	0x00, 0x00, 0x68, 0x48, 0x01, 0x00, 0x00, 0xe8
+.data1 	0xd4, 0x18, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x80
+.data1 	0x3d, 0x08, 0x07, 0x00, 0x00, 0x00, 0x75, 0x0a
+.data1 	0xb8, 0xfb, 0xff, 0xff, 0xff, 0xe9, 0x57, 0x03
+.data1 	0x00, 0x00, 0xba, 0x00, 0x02, 0x00, 0x00, 0x89
+.data1 	0xd6, 0x89, 0x57, 0x04, 0x83, 0x7d, 0xe8, 0x00
+.data1 	0x7e, 0x05, 0xbe, 0x00, 0x02, 0x00, 0x00, 0x8b
+.data1 	0x15, 0xf8, 0x06, 0x00, 0x00, 0xd1, 0xe2, 0x89
+.data1 	0xd1, 0x8b, 0x45, 0xe4, 0x31, 0xd2, 0xf7, 0xf1
+.data1 	0x8b, 0x55, 0xfc, 0x89, 0x42, 0x08, 0x8b, 0x15
+.data1 	0xf0, 0x06, 0x00, 0x00, 0x8b, 0x4d, 0xfc, 0x0f
+.data1 	0xb6, 0x5a, 0x02, 0x0f, 0xaf, 0x59, 0x08, 0x89
+.data1 	0x59, 0x04, 0x8b, 0x15, 0xf8, 0x06, 0x00, 0x00
+.data1 	0xd1, 0xe2, 0x89, 0xd1, 0x8b, 0x45, 0xe4, 0x31
+.data1 	0xd2, 0xf7, 0xf1, 0x89, 0xd0, 0x31, 0xd2, 0xf7
+.data1 	0x35, 0xf8, 0x06, 0x00, 0x00, 0x8b, 0x55, 0xfc
+.data1 	0x89, 0x42, 0x10, 0x8d, 0x55, 0x84, 0x89, 0x55
+.data1 	0x80, 0x8d, 0x55, 0xcc, 0x39, 0x55, 0x80, 0x73
+.data1 	0x0f, 0x8b, 0x45, 0x80, 0xc7, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x83, 0x45, 0x80, 0x04, 0xeb, 0xe9
+.data1 	0xc7, 0x45, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x89
+.data1 	0x7d, 0xf8, 0x8b, 0x45, 0xe4, 0x31, 0xd2, 0xf7
+.data1 	0x35, 0xf8, 0x06, 0x00, 0x00, 0x89, 0x55, 0xd4
+.data1 	0x8b, 0x45, 0xf8, 0x8b, 0x10, 0x89, 0x55, 0xcc
+.data1 	0x8b, 0x55, 0xf8, 0x8b, 0x52, 0x04, 0x89, 0x55
+.data1 	0xd8, 0xf7, 0xc2, 0xff, 0x01, 0x00, 0x00, 0x74
+.data1 	0x0a, 0xb8, 0xea, 0xff, 0xff, 0xff, 0xe9, 0x9e
+.data1 	0x02, 0x00, 0x00, 0x83, 0x7d, 0xd8, 0x00, 0x74
+.data1 	0x3b, 0x8b, 0x55, 0xd4, 0xb9, 0x01, 0x00, 0x00
+.data1 	0x00, 0x01, 0xd1, 0x89, 0x4d, 0xd4, 0x8b, 0x4d
+.data1 	0xcc, 0x89, 0x4c, 0x95, 0x84, 0x81, 0x6d, 0xd8
+.data1 	0x00, 0x02, 0x00, 0x00, 0x81, 0x45, 0xcc, 0x00
+.data1 	0x02, 0x00, 0x00, 0x81, 0x45, 0xdc, 0x00, 0x02
+.data1 	0x00, 0x00, 0x8b, 0x15, 0xf8, 0x06, 0x00, 0x00
+.data1 	0x39, 0x55, 0xd4, 0x74, 0x0d, 0x39, 0x75, 0xdc
+.data1 	0x75, 0xc1, 0xeb, 0x06, 0x83, 0x45, 0xf8, 0x08
+.data1 	0xeb, 0x96, 0x83, 0x3d, 0xe0, 0x06, 0x00, 0x00
+.data1 	0x00, 0x74, 0x05, 0xe8, 0x26, 0x0b, 0x00, 0x00
+.data1 	0xe8, 0x32, 0x03, 0x00, 0x00, 0x8b, 0x15, 0xf4
+.data1 	0x06, 0x00, 0x00, 0x39, 0x15, 0xf0, 0x06, 0x00
+.data1 	0x00, 0x0f, 0x84, 0x6f, 0x00, 0x00, 0x00, 0xc6
+.data1 	0x85, 0x7d, 0xff, 0xff, 0xff, 0x03, 0x8b, 0x15
+.data1 	0xf0, 0x06, 0x00, 0x00, 0x8a, 0x4a, 0x07, 0x88
+.data1 	0x8d, 0x7e, 0xff, 0xff, 0xff, 0xc6, 0x85, 0x7f
+.data1 	0xff, 0xff, 0xff, 0x02, 0x6a, 0x03, 0x8d, 0x85
+.data1 	0x7d, 0xff, 0xff, 0xff, 0x50, 0xe8, 0x29, 0x09
+.data1 	0x00, 0x00, 0x59, 0x59, 0x8b, 0x15, 0xf0, 0x06
+.data1 	0x00, 0x00, 0x6a, 0x62, 0x0f, 0xb6, 0x42, 0x04
+.data1 	0x50, 0x68, 0xf7, 0x03, 0x00, 0x00, 0xe8, 0x79
+.data1 	0x18, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45
+.data1 	0xf0, 0x85, 0xc0, 0x74, 0x15, 0xff, 0x75, 0xf0
+.data1 	0x68, 0x1c, 0x01, 0x00, 0x00, 0x68, 0x2c, 0x01
+.data1 	0x00, 0x00, 0xe8, 0x39, 0x17, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x8b, 0x15, 0xf0, 0x06, 0x00, 0x00
+.data1 	0x89, 0x15, 0xf4, 0x06, 0x00, 0x00, 0xe8, 0x5d
+.data1 	0x04, 0x00, 0x00, 0x89, 0x45, 0xec, 0x8b, 0x55
+.data1 	0xfc, 0x83, 0x7a, 0x0c, 0xff, 0x75, 0x10, 0x81
+.data1 	0x7d, 0xdc, 0x00, 0x0c, 0x00, 0x00, 0x73, 0x07
+.data1 	0xc7, 0x42, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x31
+.data1 	0xf6, 0x39, 0x75, 0xdc, 0x0f, 0x86, 0x5b, 0x01
+.data1 	0x00, 0x00, 0x8b, 0x55, 0xfc, 0x83, 0x7a, 0x0c
+.data1 	0xff, 0x75, 0x17, 0x83, 0x7d, 0xec, 0x00, 0x75
+.data1 	0x11, 0xe8, 0xda, 0x0b, 0x00, 0x00, 0x85, 0xc0
+.data1 	0x74, 0x08, 0xe8, 0xd1, 0x0b, 0x00, 0x00, 0x89
+.data1 	0x45, 0xec, 0x83, 0x7d, 0xec, 0x00, 0x75, 0x33
+.data1 	0x8b, 0x55, 0xfc, 0x8b, 0x0d, 0xf8, 0x06, 0x00
+.data1 	0x00, 0x39, 0x4a, 0x0c, 0x72, 0x07, 0xc7, 0x42
+.data1 	0x0c, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xfc
+.data1 	0x8b, 0x52, 0x0c, 0x8d, 0x54, 0x95, 0x84, 0x89
+.data1 	0x55, 0x80, 0x8b, 0x45, 0x80, 0x83, 0x38, 0x00
+.data1 	0x75, 0x09, 0x8b, 0x45, 0xfc, 0x83, 0x40, 0x0c
+.data1 	0x01, 0xeb, 0xcd, 0x83, 0x7d, 0xec, 0x00, 0x75
+.data1 	0x49, 0x81, 0x7d, 0x0c, 0x08, 0x04, 0x00, 0x00
+.data1 	0x75, 0x40, 0x8b, 0x45, 0x80, 0x68, 0x00, 0x02
+.data1 	0x00, 0x00, 0xff, 0x35, 0x90, 0x15, 0x00, 0x00
+.data1 	0x6a, 0x01, 0x68, 0xce, 0x8a, 0x00, 0x00, 0xff
+.data1 	0x30, 0x6a, 0x01, 0xff, 0x75, 0x08, 0xe8, 0x39
+.data1 	0x18, 0x00, 0x00, 0x83, 0xc4, 0x1c, 0x89, 0x45
+.data1 	0xf0, 0x85, 0xc0, 0x74, 0x15, 0xff, 0x75, 0xf0
+.data1 	0x68, 0x00, 0x01, 0x00, 0x00, 0x68, 0x14, 0x01
+.data1 	0x00, 0x00, 0xe8, 0x59, 0x16, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x83, 0x7d, 0xec, 0x00, 0x75, 0x23
+.data1 	0xff, 0x75, 0x0c, 0xe8, 0xe5, 0x00, 0x00, 0x00
+.data1 	0x59, 0x85, 0xc0, 0x74, 0x0a, 0xb8, 0xfb, 0xff
+.data1 	0xff, 0xff, 0xe9, 0xd2, 0x00, 0x00, 0x00, 0xff
+.data1 	0x75, 0x0c, 0xe8, 0xac, 0x04, 0x00, 0x00, 0x59
+.data1 	0x89, 0x45, 0xec, 0x83, 0x7d, 0xec, 0x00, 0x75
+.data1 	0x49, 0x81, 0x7d, 0x0c, 0x09, 0x04, 0x00, 0x00
+.data1 	0x75, 0x40, 0x8b, 0x45, 0x80, 0x68, 0x00, 0x02
+.data1 	0x00, 0x00, 0xff, 0x30, 0x6a, 0x01, 0xff, 0x75
+.data1 	0x08, 0xff, 0x35, 0x90, 0x15, 0x00, 0x00, 0x6a
+.data1 	0x01, 0x68, 0xce, 0x8a, 0x00, 0x00, 0xe8, 0xc1
+.data1 	0x17, 0x00, 0x00, 0x83, 0xc4, 0x1c, 0x89, 0x45
+.data1 	0xf0, 0x85, 0xc0, 0x74, 0x15, 0xff, 0x75, 0xf0
+.data1 	0x68, 0xe4, 0x00, 0x00, 0x00, 0x68, 0xf8, 0x00
+.data1 	0x00, 0x00, 0xe8, 0xe1, 0x15, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x83, 0x7d, 0xec, 0x00, 0x74, 0x2a
+.data1 	0x83, 0x7d, 0xec, 0xf9, 0x7e, 0x09, 0xff, 0x45
+.data1 	0xe8, 0x83, 0x7d, 0xe8, 0x06, 0x75, 0x0a, 0xb8
+.data1 	0xfb, 0xff, 0xff, 0xff, 0xe9, 0x58, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7d, 0xe8, 0x03, 0x75, 0x07, 0x8b
+.data1 	0x55, 0xfc, 0xc6, 0x42, 0x14, 0x00, 0x31, 0xf6
+.data1 	0xeb, 0x0b, 0x81, 0xc6, 0x00, 0x02, 0x00, 0x00
+.data1 	0xe9, 0x9c, 0xfe, 0xff, 0xff, 0x01, 0x75, 0x10
+.data1 	0x39, 0x77, 0x04, 0x76, 0x0f, 0x01, 0x37, 0x8b
+.data1 	0x57, 0x04, 0x29, 0xf2, 0x89, 0x57, 0x04, 0xe9
+.data1 	0xbf, 0xfb, 0xff, 0xff, 0x89, 0xf2, 0x2b, 0x57
+.data1 	0x04, 0x89, 0xd6, 0x8b, 0x57, 0x04, 0x01, 0x17
+.data1 	0xc7, 0x47, 0x04, 0x00, 0x00, 0x00, 0x00, 0x85
+.data1 	0xf6, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x0a, 0x83
+.data1 	0xc7, 0x08, 0xff, 0x4d, 0x18, 0xeb, 0xc9, 0x31
+.data1 	0xc0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x28, 0xba, 0xff, 0xff, 0xff, 0x00
+.data1 	0x23, 0x15, 0x8c, 0x15, 0x00, 0x00, 0x39, 0x15
+.data1 	0x8c, 0x15, 0x00, 0x00, 0x74, 0x21, 0x68, 0x00
+.data1 	0x80, 0x00, 0x00, 0x68, 0x78, 0x01, 0x00, 0x00
+.data1 	0x68, 0xa0, 0x01, 0x00, 0x00, 0xe8, 0xc2, 0x1b
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xb8, 0xfb, 0xff
+.data1 	0xff, 0xff, 0xe9, 0xae, 0x00, 0x00, 0x00, 0x66
+.data1 	0xc7, 0x45, 0xdc, 0x0a, 0x00, 0xc6, 0x45, 0xde
+.data1 	0x06, 0x66, 0xc7, 0x45, 0xe0, 0x0c, 0x00, 0xc6
+.data1 	0x45, 0xe2, 0x00, 0x66, 0xc7, 0x45, 0xe4, 0x0b
+.data1 	0x00, 0x81, 0x7d, 0x08, 0x08, 0x04, 0x00, 0x00
+.data1 	0x75, 0x07, 0xb8, 0x4a, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x05, 0xb8, 0x46, 0x00, 0x00, 0x00, 0x88, 0x45
+.data1 	0xe6, 0x66, 0xc7, 0x45, 0xe8, 0x04, 0x00, 0x8b
+.data1 	0x15, 0x8c, 0x15, 0x00, 0x00, 0x88, 0x55, 0xea
+.data1 	0x66, 0xc7, 0x45, 0xec, 0x04, 0x00, 0x8b, 0x15
+.data1 	0x8c, 0x15, 0x00, 0x00, 0xc1, 0xea, 0x08, 0x88
+.data1 	0x55, 0xee, 0x66, 0xc7, 0x45, 0xf0, 0x81, 0x00
+.data1 	0x8b, 0x15, 0x8c, 0x15, 0x00, 0x00, 0xc1, 0xea
+.data1 	0x10, 0x88, 0x55, 0xf2, 0x66, 0xc7, 0x45, 0xf4
+.data1 	0x05, 0x00, 0xc6, 0x45, 0xf6, 0xff, 0x66, 0xc7
+.data1 	0x45, 0xf8, 0x05, 0x00, 0xc6, 0x45, 0xfa, 0x01
+.data1 	0x66, 0xc7, 0x45, 0xfc, 0x0a, 0x00, 0xc6, 0x45
+.data1 	0xfe, 0x02, 0x6a, 0x09, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0xe8, 0xb3, 0x16, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0x45, 0xd8, 0x85, 0xc0, 0x74, 0x15, 0xff, 0x75
+.data1 	0xd8, 0x68, 0x50, 0x01, 0x00, 0x00, 0x68, 0x70
+.data1 	0x01, 0x00, 0x00, 0xe8, 0x80, 0x14, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x31, 0xc0, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x30, 0x56, 0x8b, 0x0d
+.data1 	0xe4, 0x06, 0x00, 0x00, 0xba, 0x01, 0x00, 0x00
+.data1 	0x00, 0xd3, 0xe2, 0x89, 0xd6, 0x89, 0xf2, 0x23
+.data1 	0x15, 0xdc, 0x06, 0x00, 0x00, 0x89, 0x55, 0xf4
+.data1 	0x09, 0x35, 0xdc, 0x06, 0x00, 0x00, 0x8b, 0x15
+.data1 	0xdc, 0x06, 0x00, 0x00, 0xc1, 0xe2, 0x04, 0x83
+.data1 	0xca, 0x0c, 0x0b, 0x15, 0xe4, 0x06, 0x00, 0x00
+.data1 	0x6a, 0x62, 0x52, 0x68, 0xf2, 0x03, 0x00, 0x00
+.data1 	0xe8, 0x57, 0x15, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0x45, 0xfc, 0x85, 0xc0, 0x74, 0x15, 0xff
+.data1 	0x75, 0xfc, 0x68, 0xa8, 0x01, 0x00, 0x00, 0x68
+.data1 	0xcc, 0x01, 0x00, 0x00, 0xe8, 0x17, 0x14, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x83, 0x7d, 0xf4, 0x00
+.data1 	0x0f, 0x85, 0x82, 0x00, 0x00, 0x00, 0x8b, 0x15
+.data1 	0xf0, 0x06, 0x00, 0x00, 0x68, 0x4e, 0x12, 0x00
+.data1 	0x00, 0x0f, 0xb6, 0x42, 0x05, 0x50, 0x68, 0x18
+.data1 	0x07, 0x00, 0x00, 0xe8, 0x15, 0xf8, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x66, 0xc7, 0x05, 0xfc, 0x06
+.data1 	0x00, 0x00, 0x01, 0x00, 0x8d, 0x45, 0xd0, 0x50
+.data1 	0x68, 0xce, 0x7a, 0x00, 0x00, 0xe8, 0xce, 0x1c
+.data1 	0x00, 0x00, 0x59, 0x59, 0x81, 0x7d, 0xd4, 0x01
+.data1 	0x10, 0x00, 0x00, 0x75, 0x0d, 0x6a, 0x00, 0x6a
+.data1 	0x00, 0xe8, 0x5c, 0xf7, 0xff, 0xff, 0x59, 0x59
+.data1 	0xeb, 0x1d, 0x81, 0x7d, 0xd4, 0x06, 0x10, 0x00
+.data1 	0x00, 0x75, 0x0b, 0xff, 0x75, 0xd0, 0xe8, 0xcd
+.data1 	0x1c, 0x00, 0x00, 0x59, 0xeb, 0x09, 0x66, 0xc7
+.data1 	0x05, 0xfc, 0x06, 0x00, 0x00, 0x00, 0x00, 0x0f
+.data1 	0xb7, 0x15, 0xfc, 0x06, 0x00, 0x00, 0x83, 0xfa
+.data1 	0x01, 0x74, 0xb1, 0x8b, 0x15, 0xec, 0x06, 0x00
+.data1 	0x00, 0xc7, 0x42, 0x0c, 0xff, 0xff, 0xff, 0xff
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x04, 0x8b, 0x55, 0x08, 0x8b, 0x4a, 0x0c, 0xba
+.data1 	0x01, 0x00, 0x00, 0x00, 0xd3, 0xe2, 0xf7, 0xd2
+.data1 	0x21, 0x15, 0xdc, 0x06, 0x00, 0x00, 0x8b, 0x15
+.data1 	0xdc, 0x06, 0x00, 0x00, 0xc1, 0xe2, 0x04, 0x83
+.data1 	0xca, 0x0c, 0x6a, 0x62, 0x52, 0x68, 0xf2, 0x03
+.data1 	0x00, 0x00, 0xe8, 0x75, 0x14, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0x45, 0xfc, 0x85, 0xc0, 0x74
+.data1 	0x15, 0xff, 0x75, 0xfc, 0x68, 0xd4, 0x01, 0x00
+.data1 	0x00, 0x68, 0xf4, 0x01, 0x00, 0x00, 0xe8, 0x35
+.data1 	0x13, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x8b, 0x55
+.data1 	0x0c, 0x8b, 0x52, 0x14, 0x89, 0x55, 0xf8, 0x6a
+.data1 	0x0f, 0x8d, 0x45, 0xf8, 0x50, 0xe8, 0x52, 0x1b
+.data1 	0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x75, 0x11
+.data1 	0x6a, 0x1f, 0x8d, 0x45, 0xf8, 0x50, 0xe8, 0x41
+.data1 	0x1b, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x74
+.data1 	0x35, 0x6a, 0x62, 0x6a, 0x0c, 0x68, 0xf2, 0x03
+.data1 	0x00, 0x00, 0xe8, 0x15, 0x14, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0x45, 0xfc, 0x85, 0xc0, 0x74
+.data1 	0x15, 0xff, 0x75, 0xfc, 0x68, 0xfc, 0x01, 0x00
+.data1 	0x00, 0x68, 0x20, 0x02, 0x00, 0x00, 0xe8, 0xd5
+.data1 	0x12, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x6a, 0x00
+.data1 	0xe8, 0xdc, 0x1a, 0x00, 0x00, 0x59, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x30, 0x56, 0x8b
+.data1 	0x35, 0xec, 0x06, 0x00, 0x00, 0x80, 0x7e, 0x14
+.data1 	0x00, 0x75, 0x13, 0xe8, 0x7d, 0x05, 0x00, 0x00
+.data1 	0x85, 0xc0, 0x74, 0x0a, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x1a, 0x01, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x04, 0x39, 0x16, 0x75, 0x07, 0x31, 0xc0, 0xe9
+.data1 	0x0c, 0x01, 0x00, 0x00, 0xc6, 0x45, 0xd1, 0x0f
+.data1 	0x8b, 0x56, 0x10, 0xc1, 0xe2, 0x02, 0x0b, 0x15
+.data1 	0xe4, 0x06, 0x00, 0x00, 0x88, 0x55, 0xd2, 0x8b
+.data1 	0x56, 0x04, 0x88, 0x55, 0xd3, 0x6a, 0x03, 0x8d
+.data1 	0x45, 0xd1, 0x50, 0xe8, 0x2b, 0x04, 0x00, 0x00
+.data1 	0x59, 0x59, 0x85, 0xc0, 0x74, 0x0a, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xe9, 0xd8, 0x00, 0x00, 0x00
+.data1 	0xe8, 0xbb, 0x06, 0x00, 0x00, 0x85, 0xc0, 0x74
+.data1 	0x0a, 0xb8, 0xf8, 0xff, 0xff, 0xff, 0xe9, 0xc5
+.data1 	0x00, 0x00, 0x00, 0x6a, 0x08, 0xe8, 0x50, 0x04
+.data1 	0x00, 0x00, 0x59, 0xe8, 0xbb, 0x02, 0x00, 0x00
+.data1 	0x89, 0x45, 0xf8, 0x85, 0xc0, 0x75, 0x1e, 0x0f
+.data1 	0xb6, 0x15, 0x10, 0x07, 0x00, 0x00, 0x81, 0xe2
+.data1 	0xf8, 0x00, 0x00, 0x00, 0x83, 0xfa, 0x20, 0x75
+.data1 	0x0c, 0x0f, 0xb6, 0x15, 0x11, 0x07, 0x00, 0x00
+.data1 	0x39, 0x56, 0x04, 0x74, 0x0a, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe9, 0x89, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x15, 0xe8, 0x06, 0x00, 0x00, 0xf6, 0xc2, 0x80
+.data1 	0x0f, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x68, 0x4e
+.data1 	0x12, 0x00, 0x00, 0x6a, 0x02, 0x68, 0x18, 0x07
+.data1 	0x00, 0x00, 0xe8, 0x16, 0xf6, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x66, 0xc7, 0x05, 0xfc, 0x06, 0x00
+.data1 	0x00, 0x01, 0x00, 0x8d, 0x45, 0xd4, 0x50, 0x68
+.data1 	0xce, 0x7a, 0x00, 0x00, 0xe8, 0xcf, 0x1a, 0x00
+.data1 	0x00, 0x59, 0x59, 0x81, 0x7d, 0xd8, 0x01, 0x10
+.data1 	0x00, 0x00, 0x75, 0x0d, 0x6a, 0x00, 0x6a, 0x00
+.data1 	0xe8, 0x5d, 0xf5, 0xff, 0xff, 0x59, 0x59, 0xeb
+.data1 	0x1d, 0x81, 0x7d, 0xd8, 0x06, 0x10, 0x00, 0x00
+.data1 	0x75, 0x0b, 0xff, 0x75, 0xd4, 0xe8, 0xce, 0x1a
+.data1 	0x00, 0x00, 0x59, 0xeb, 0x09, 0x66, 0xc7, 0x05
+.data1 	0xfc, 0x06, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xb7
+.data1 	0x15, 0xfc, 0x06, 0x00, 0x00, 0x83, 0xfa, 0x01
+.data1 	0x74, 0xb1, 0x8b, 0x56, 0x04, 0x89, 0x16, 0xc7
+.data1 	0x46, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x31, 0xc0
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x18, 0x56, 0x57, 0x8b, 0x35, 0xec, 0x06, 0x00
+.data1 	0x00, 0x80, 0x7e, 0x14, 0x00, 0x75, 0x0a, 0xb8
+.data1 	0xfe, 0xff, 0xff, 0xff, 0xe9, 0xde, 0x01, 0x00
+.data1 	0x00, 0x8b, 0x0d, 0xe4, 0x06, 0x00, 0x00, 0xba
+.data1 	0x01, 0x00, 0x00, 0x00, 0xd3, 0xe2, 0x85, 0x15
+.data1 	0xdc, 0x06, 0x00, 0x00, 0x75, 0x0a, 0xb8, 0xfe
+.data1 	0xff, 0xff, 0xff, 0xe9, 0xbf, 0x01, 0x00, 0x00
+.data1 	0x8b, 0x15, 0xe8, 0x06, 0x00, 0x00, 0xf6, 0xc2
+.data1 	0x80, 0x74, 0x56, 0xc6, 0x45, 0xeb, 0x4d, 0x8b
+.data1 	0x56, 0x10, 0xc1, 0xe2, 0x02, 0x0b, 0x15, 0xe4
+.data1 	0x06, 0x00, 0x00, 0x88, 0x55, 0xec, 0x8a, 0x0d
+.data1 	0x07, 0x07, 0x00, 0x00, 0x88, 0x4d, 0xed, 0x8a
+.data1 	0x0d, 0x08, 0x07, 0x00, 0x00, 0x88, 0x4d, 0xee
+.data1 	0x8a, 0x0d, 0x0b, 0x07, 0x00, 0x00, 0x88, 0x4d
+.data1 	0xef, 0x8a, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x88
+.data1 	0x4d, 0xf0, 0x6a, 0x06, 0x8d, 0x45, 0xeb, 0x50
+.data1 	0xe8, 0xb6, 0x02, 0x00, 0x00, 0x59, 0x59, 0x85
+.data1 	0xc0, 0x0f, 0x84, 0x80, 0x00, 0x00, 0x00, 0xb8
+.data1 	0xfe, 0xff, 0xff, 0xff, 0xe9, 0x5e, 0x01, 0x00
+.data1 	0x00, 0x81, 0x7d, 0x08, 0x08, 0x04, 0x00, 0x00
+.data1 	0x75, 0x07, 0xb8, 0xc5, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x05, 0xb8, 0xe6, 0x00, 0x00, 0x00, 0x88, 0x45
+.data1 	0xeb, 0x8b, 0x56, 0x10, 0xc1, 0xe2, 0x02, 0x0b
+.data1 	0x15, 0xe4, 0x06, 0x00, 0x00, 0x88, 0x55, 0xec
+.data1 	0x8b, 0x56, 0x08, 0x88, 0x55, 0xed, 0x8b, 0x56
+.data1 	0x10, 0x88, 0x55, 0xee, 0xba, 0x01, 0x00, 0x00
+.data1 	0x00, 0x03, 0x56, 0x0c, 0x88, 0x55, 0xef, 0xc6
+.data1 	0x45, 0xf0, 0x02, 0x8b, 0x15, 0xf8, 0x06, 0x00
+.data1 	0x00, 0x88, 0x55, 0xf1, 0x8b, 0x15, 0xf0, 0x06
+.data1 	0x00, 0x00, 0x8a, 0x4a, 0x06, 0x88, 0x4d, 0xf2
+.data1 	0xc6, 0x45, 0xf3, 0xff, 0x6a, 0x09, 0x8d, 0x45
+.data1 	0xeb, 0x50, 0xe8, 0x3c, 0x02, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x74, 0x0a, 0xb8, 0xfe, 0xff
+.data1 	0xff, 0xff, 0xe9, 0xe8, 0x00, 0x00, 0x00, 0xe8
+.data1 	0xcc, 0x04, 0x00, 0x00, 0x85, 0xc0, 0x74, 0x1c
+.data1 	0xe8, 0xec, 0xf5, 0xff, 0xff, 0x50, 0x68, 0x4c
+.data1 	0x02, 0x00, 0x00, 0xe8, 0x0c, 0x13, 0x00, 0x00
+.data1 	0x59, 0x59, 0xb8, 0xf8, 0xff, 0xff, 0xff, 0xe9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0xe8, 0xc2, 0x00, 0x00
+.data1 	0x00, 0x89, 0x45, 0xf8, 0x85, 0xc0, 0x74, 0x05
+.data1 	0xe9, 0xb2, 0x00, 0x00, 0x00, 0xf6, 0x05, 0x11
+.data1 	0x07, 0x00, 0x00, 0x02, 0x74, 0x1c, 0xe8, 0xb6
+.data1 	0xf5, 0xff, 0xff, 0x50, 0x68, 0x28, 0x02, 0x00
+.data1 	0x00, 0xe8, 0xd6, 0x12, 0x00, 0x00, 0x59, 0x59
+.data1 	0xb8, 0xf9, 0xff, 0xff, 0xff, 0xe9, 0x8d, 0x00
+.data1 	0x00, 0x00, 0xf6, 0x05, 0x10, 0x07, 0x00, 0x00
+.data1 	0xd8, 0x74, 0x0a, 0xb8, 0xfe, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x7a, 0x00, 0x00, 0x00, 0x0f, 0xb6, 0x15
+.data1 	0x12, 0x07, 0x00, 0x00, 0x0f, 0xb6, 0x0d, 0x11
+.data1 	0x07, 0x00, 0x00, 0x09, 0xca, 0x74, 0x07, 0xb8
+.data1 	0xfe, 0xff, 0xff, 0xff, 0xeb, 0x61, 0x8b, 0x15
+.data1 	0xe8, 0x06, 0x00, 0x00, 0xf6, 0xc2, 0x80, 0x74
+.data1 	0x04, 0x31, 0xc0, 0xeb, 0x52, 0x0f, 0xb6, 0x15
+.data1 	0x13, 0x07, 0x00, 0x00, 0x2b, 0x56, 0x08, 0xd1
+.data1 	0xe2, 0x0f, 0xaf, 0x15, 0xf8, 0x06, 0x00, 0x00
+.data1 	0x89, 0xd7, 0x0f, 0xb6, 0x15, 0x14, 0x07, 0x00
+.data1 	0x00, 0x2b, 0x56, 0x10, 0x0f, 0xaf, 0x15, 0xf8
+.data1 	0x06, 0x00, 0x00, 0x01, 0xfa, 0x89, 0xd7, 0x0f
+.data1 	0xb6, 0x15, 0x15, 0x07, 0x00, 0x00, 0x4a, 0x2b
+.data1 	0x56, 0x0c, 0x01, 0xfa, 0x89, 0xd7, 0x83, 0xff
+.data1 	0x01, 0x74, 0x07, 0xb8, 0xfe, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x0d, 0x0f, 0xb6, 0x15, 0x15, 0x07, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x56, 0x0c, 0x31, 0xc0, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x18, 0x56, 0x57, 0x31, 0xff, 0x8d, 0x45, 0xf0
+.data1 	0x50, 0xe8, 0xee, 0x11, 0x00, 0x00, 0x59, 0x6a
+.data1 	0x62, 0x8d, 0x45, 0xf4, 0x50, 0x68, 0xf4, 0x03
+.data1 	0x00, 0x00, 0xe8, 0xcd, 0x0f, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0xc6, 0x85, 0xc0, 0x74, 0x13
+.data1 	0x56, 0x68, 0xfc, 0x02, 0x00, 0x00, 0x68, 0x1c
+.data1 	0x03, 0x00, 0x00, 0xe8, 0x48, 0x0f, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x8b, 0x55, 0xf4, 0x81, 0xe2
+.data1 	0xd0, 0x00, 0x00, 0x00, 0x89, 0x55, 0xf4, 0x81
+.data1 	0xfa, 0xd0, 0x00, 0x00, 0x00, 0x75, 0x41, 0x83
+.data1 	0xff, 0x07, 0x0f, 0x8d, 0x93, 0x00, 0x00, 0x00
+.data1 	0x6a, 0x62, 0x8d, 0x45, 0xe8, 0x50, 0x68, 0xf5
+.data1 	0x03, 0x00, 0x00, 0xe8, 0x84, 0x0f, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0xc6, 0x85, 0xc0, 0x74
+.data1 	0x13, 0x56, 0x68, 0xd4, 0x02, 0x00, 0x00, 0x68
+.data1 	0xf4, 0x02, 0x00, 0x00, 0xe8, 0xff, 0x0e, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55, 0xe8, 0x88
+.data1 	0x97, 0x10, 0x07, 0x00, 0x00, 0x47, 0xeb, 0x3c
+.data1 	0x81, 0x7d, 0xf4, 0x80, 0x00, 0x00, 0x00, 0x75
+.data1 	0x33, 0x68, 0xd8, 0x06, 0x00, 0x00, 0x6a, 0x00
+.data1 	0x6a, 0x00, 0x6a, 0x03, 0xe8, 0x7f, 0x0f, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x10, 0x89, 0xc6, 0x85, 0xc0
+.data1 	0x74, 0x13, 0x56, 0x68, 0xb4, 0x02, 0x00, 0x00
+.data1 	0x68, 0xcc, 0x02, 0x00, 0x00, 0xe8, 0xbe, 0x0e
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x31, 0xc0, 0xe9
+.data1 	0x6b, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xec, 0x50
+.data1 	0xe8, 0x27, 0x11, 0x00, 0x00, 0x59, 0x89, 0xc6
+.data1 	0x85, 0xc0, 0x75, 0x0f, 0x8b, 0x55, 0xec, 0x2b
+.data1 	0x55, 0xf0, 0x83, 0xfa, 0x1e, 0x0f, 0x8c, 0x24
+.data1 	0xff, 0xff, 0xff, 0x85, 0xf6, 0x74, 0x0d, 0x56
+.data1 	0x68, 0x8c, 0x02, 0x00, 0x00, 0xe8, 0x3a, 0x11
+.data1 	0x00, 0x00, 0x59, 0x59, 0xc7, 0x05, 0xe0, 0x06
+.data1 	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x68, 0xd8
+.data1 	0x06, 0x00, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0x6a
+.data1 	0x03, 0xe8, 0x12, 0x0f, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x10, 0x89, 0xc6, 0x85, 0xc0, 0x74, 0x13, 0x56
+.data1 	0x68, 0x6c, 0x02, 0x00, 0x00, 0x68, 0x84, 0x02
+.data1 	0x00, 0x00, 0xe8, 0x51, 0x0e, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xb8, 0xfd, 0xff, 0xff, 0xff, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x68, 0x4e
+.data1 	0x12, 0x00, 0x00, 0x6a, 0x78, 0x68, 0x18, 0x07
+.data1 	0x00, 0x00, 0xe8, 0x56, 0xf2, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x66, 0xc7, 0x05, 0xfc, 0x06, 0x00
+.data1 	0x00, 0x01, 0x00, 0x83, 0x7d, 0x0c, 0x00, 0x7e
+.data1 	0x15, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f
+.data1 	0xb6, 0x18, 0x53, 0xe8, 0x1a, 0x00, 0x00, 0x00
+.data1 	0x59, 0xff, 0x4d, 0x0c, 0xeb, 0xe5, 0x83, 0x3d
+.data1 	0xe0, 0x06, 0x00, 0x00, 0x00, 0x74, 0x07, 0xb8
+.data1 	0xfa, 0xff, 0xff, 0xff, 0xeb, 0x02, 0x31, 0xc0
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x10
+.data1 	0x56, 0x83, 0x3d, 0xe0, 0x06, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x85, 0xac, 0x00, 0x00, 0x00, 0x8d, 0x45
+.data1 	0xfc, 0x50, 0xe8, 0x55, 0x10, 0x00, 0x00, 0x59
+.data1 	0x8d, 0x45, 0xf8, 0x50, 0xe8, 0x4b, 0x10, 0x00
+.data1 	0x00, 0x59, 0x89, 0xc6, 0x85, 0xc0, 0x75, 0x2b
+.data1 	0x8b, 0x55, 0xf8, 0x2b, 0x55, 0xfc, 0x83, 0xfa
+.data1 	0x1e, 0x7e, 0x20, 0x85, 0xf6, 0x74, 0x0d, 0x56
+.data1 	0x68, 0x70, 0x03, 0x00, 0x00, 0xe8, 0x62, 0x10
+.data1 	0x00, 0x00, 0x59, 0x59, 0xc7, 0x05, 0xe0, 0x06
+.data1 	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe9, 0x67
+.data1 	0x00, 0x00, 0x00, 0x6a, 0x62, 0x8d, 0x45, 0xf0
+.data1 	0x50, 0x68, 0xf4, 0x03, 0x00, 0x00, 0xe8, 0xf9
+.data1 	0x0d, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0xc6
+.data1 	0x85, 0xc0, 0x74, 0x13, 0x56, 0x68, 0x4c, 0x03
+.data1 	0x00, 0x00, 0x68, 0x68, 0x03, 0x00, 0x00, 0xe8
+.data1 	0x74, 0x0d, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xba
+.data1 	0xc0, 0x00, 0x00, 0x00, 0x23, 0x55, 0xf0, 0x81
+.data1 	0xfa, 0x80, 0x00, 0x00, 0x00, 0x75, 0x89, 0x6a
+.data1 	0x62, 0xff, 0x75, 0x08, 0x68, 0xf5, 0x03, 0x00
+.data1 	0x00, 0xe8, 0x76, 0x0e, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x89, 0xc6, 0x85, 0xc0, 0x74, 0x13, 0x56
+.data1 	0x68, 0x24, 0x03, 0x00, 0x00, 0x68, 0x44, 0x03
+.data1 	0x00, 0x00, 0xe8, 0x39, 0x0d, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x0c, 0x56, 0x8b, 0x35, 0xec, 0x06
+.data1 	0x00, 0x00, 0xc6, 0x45, 0xf6, 0x07, 0x8b, 0x15
+.data1 	0xe4, 0x06, 0x00, 0x00, 0x88, 0x55, 0xf7, 0x6a
+.data1 	0x02, 0x8d, 0x45, 0xf6, 0x50, 0xe8, 0xc9, 0xfe
+.data1 	0xff, 0xff, 0x59, 0x59, 0x85, 0xc0, 0x74, 0x0a
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x71, 0x00
+.data1 	0x00, 0x00, 0xe8, 0x59, 0x01, 0x00, 0x00, 0x85
+.data1 	0xc0, 0x74, 0x0a, 0xb8, 0xf8, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x5e, 0x00, 0x00, 0x00, 0x6a, 0x08, 0xe8
+.data1 	0xee, 0xfe, 0xff, 0xff, 0x59, 0xe8, 0x59, 0xfd
+.data1 	0xff, 0xff, 0x89, 0x45, 0xf8, 0xc7, 0x06, 0xff
+.data1 	0xff, 0xff, 0xff, 0xc7, 0x46, 0x0c, 0xff, 0xff
+.data1 	0xff, 0xff, 0x83, 0x7d, 0xf8, 0x00, 0x75, 0x1b
+.data1 	0x0f, 0xb6, 0x15, 0x10, 0x07, 0x00, 0x00, 0x81
+.data1 	0xe2, 0xf8, 0x00, 0x00, 0x00, 0x83, 0xfa, 0x20
+.data1 	0x75, 0x09, 0x80, 0x3d, 0x11, 0x07, 0x00, 0x00
+.data1 	0x00, 0x74, 0x11, 0xc7, 0x05, 0xe0, 0x06, 0x00
+.data1 	0x00, 0x01, 0x00, 0x00, 0x00, 0xb8, 0xfb, 0xff
+.data1 	0xff, 0xff, 0xeb, 0x0f, 0xc6, 0x46, 0x14, 0x01
+.data1 	0x0f, 0xb6, 0x15, 0x11, 0x07, 0x00, 0x00, 0x89
+.data1 	0x16, 0x31, 0xc0, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x34, 0x56, 0xc7, 0x05, 0xe0
+.data1 	0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a
+.data1 	0x00, 0x6a, 0x00, 0xe8, 0x2b, 0xfe, 0xff, 0xff
+.data1 	0x59, 0x59, 0xc7, 0x05, 0xdc, 0x06, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x66, 0xc7, 0x45, 0xf8
+.data1 	0xf2, 0x03, 0xc6, 0x45, 0xfa, 0x00, 0x66, 0xc7
+.data1 	0x45, 0xfc, 0xf2, 0x03, 0xc6, 0x45, 0xfe, 0x0c
+.data1 	0x6a, 0x02, 0x8d, 0x45, 0xf8, 0x50, 0xe8, 0x5d
+.data1 	0x0e, 0x00, 0x00, 0x59, 0x59, 0x89, 0x45, 0xf4
+.data1 	0x85, 0xc0, 0x74, 0x15, 0xff, 0x75, 0xf4, 0x68
+.data1 	0x98, 0x03, 0x00, 0x00, 0x68, 0xb8, 0x03, 0x00
+.data1 	0x00, 0xe8, 0x2a, 0x0c, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x8d, 0x45, 0xcc, 0x50, 0x68, 0xce, 0x7a
+.data1 	0x00, 0x00, 0xe8, 0x11, 0x15, 0x00, 0x00, 0x59
+.data1 	0x59, 0x81, 0x7d, 0xd0, 0x01, 0x10, 0x00, 0x00
+.data1 	0x75, 0x0d, 0x6a, 0x00, 0x6a, 0x00, 0xe8, 0x9f
+.data1 	0xef, 0xff, 0xff, 0x59, 0x59, 0xeb, 0x1d, 0x81
+.data1 	0x7d, 0xd0, 0x06, 0x10, 0x00, 0x00, 0x75, 0x0b
+.data1 	0xff, 0x75, 0xcc, 0xe8, 0x10, 0x15, 0x00, 0x00
+.data1 	0x59, 0xeb, 0x09, 0x66, 0xc7, 0x05, 0xfc, 0x06
+.data1 	0x00, 0x00, 0x00, 0x00, 0x0f, 0xb7, 0x15, 0xfc
+.data1 	0x06, 0x00, 0x00, 0x83, 0xfa, 0x01, 0x74, 0xb1
+.data1 	0x31, 0xf6, 0x83, 0xfe, 0x04, 0x7d, 0x10, 0x6a
+.data1 	0x08, 0xe8, 0xd4, 0xfd, 0xff, 0xff, 0x59, 0xe8
+.data1 	0x3f, 0xfc, 0xff, 0xff, 0x46, 0xeb, 0xeb, 0x31
+.data1 	0xf6, 0x83, 0xfe, 0x02, 0x7d, 0x0d, 0x6b, 0xc6
+.data1 	0x78, 0xc6, 0x80, 0xfc, 0x05, 0x00, 0x00, 0x00
+.data1 	0x46, 0xeb, 0xee, 0xc7, 0x05, 0xf4, 0x06, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0x68, 0xce, 0x7a, 0x00, 0x00, 0xe8
+.data1 	0x84, 0x14, 0x00, 0x00, 0x59, 0x59, 0x81, 0x7d
+.data1 	0xe0, 0x01, 0x10, 0x00, 0x00, 0x75, 0x0d, 0x6a
+.data1 	0x00, 0x6a, 0x00, 0xe8, 0x12, 0xef, 0xff, 0xff
+.data1 	0x59, 0x59, 0xeb, 0x1d, 0x81, 0x7d, 0xe0, 0x06
+.data1 	0x10, 0x00, 0x00, 0x75, 0x0b, 0xff, 0x75, 0xdc
+.data1 	0xe8, 0x83, 0x14, 0x00, 0x00, 0x59, 0xeb, 0x09
+.data1 	0x66, 0xc7, 0x05, 0xfc, 0x06, 0x00, 0x00, 0x00
+.data1 	0x00, 0x0f, 0xb7, 0x15, 0xfc, 0x06, 0x00, 0x00
+.data1 	0x83, 0xfa, 0x01, 0x74, 0xb1, 0x0f, 0xb7, 0x15
+.data1 	0xfc, 0x06, 0x00, 0x00, 0x83, 0xfa, 0x02, 0x75
+.data1 	0x11, 0xc7, 0x05, 0xe0, 0x06, 0x00, 0x00, 0x01
+.data1 	0x00, 0x00, 0x00, 0xb8, 0xf8, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x02, 0x31, 0xc0, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x0f, 0xb7, 0x15, 0xfc, 0x06, 0x00, 0x00
+.data1 	0x83, 0xfa, 0x01, 0x75, 0x09, 0x66, 0xc7, 0x05
+.data1 	0xfc, 0x06, 0x00, 0x00, 0x02, 0x00, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57
+.data1 	0x8b, 0x35, 0xec, 0x06, 0x00, 0x00, 0x80, 0x7e
+.data1 	0x14, 0x00, 0x75, 0x0a, 0xb8, 0xfc, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x9e, 0x00, 0x00, 0x00, 0x8b, 0x0d
+.data1 	0xe4, 0x06, 0x00, 0x00, 0xba, 0x01, 0x00, 0x00
+.data1 	0x00, 0xd3, 0xe2, 0x85, 0x15, 0xdc, 0x06, 0x00
+.data1 	0x00, 0x75, 0x0a, 0xb8, 0xfc, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x7f, 0x00, 0x00, 0x00, 0xc6, 0x45, 0xf6
+.data1 	0x4a, 0x8b, 0x56, 0x10, 0xc1, 0xe2, 0x02, 0x0b
+.data1 	0x15, 0xe4, 0x06, 0x00, 0x00, 0x88, 0x55, 0xf7
+.data1 	0x6a, 0x02, 0x8d, 0x45, 0xf6, 0x50, 0xe8, 0x70
+.data1 	0xfc, 0xff, 0xff, 0x59, 0x59, 0x85, 0xc0, 0x74
+.data1 	0x07, 0xb8, 0xfc, 0xff, 0xff, 0xff, 0xeb, 0x54
+.data1 	0xe8, 0x03, 0xff, 0xff, 0xff, 0x85, 0xc0, 0x74
+.data1 	0x07, 0xb8, 0xf8, 0xff, 0xff, 0xff, 0xeb, 0x44
+.data1 	0xe8, 0x0e, 0xfb, 0xff, 0xff, 0x89, 0xc7, 0x85
+.data1 	0xff, 0x74, 0x04, 0x89, 0xf8, 0xeb, 0x35, 0xf6
+.data1 	0x05, 0x10, 0x07, 0x00, 0x00, 0xd8, 0x74, 0x07
+.data1 	0xb8, 0xfc, 0xff, 0xff, 0xff, 0xeb, 0x25, 0x0f
+.data1 	0xb6, 0x15, 0x12, 0x07, 0x00, 0x00, 0x0f, 0xb6
+.data1 	0x0d, 0x11, 0x07, 0x00, 0x00, 0x09, 0xca, 0x74
+.data1 	0x07, 0xb8, 0xfc, 0xff, 0xff, 0xff, 0xeb, 0x0c
+.data1 	0x0f, 0xb6, 0x15, 0x15, 0x07, 0x00, 0x00, 0x89
+.data1 	0x56, 0x0c, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x55, 0x0c
+.data1 	0xff, 0x72, 0x08, 0xe8, 0xf0, 0xee, 0xff, 0xff
+.data1 	0x59, 0x85, 0xc0, 0x75, 0x0a, 0xb8, 0xfa, 0xff
+.data1 	0xff, 0xff, 0xe9, 0x17, 0x01, 0x00, 0x00, 0xba
+.data1 	0x7c, 0x00, 0x00, 0x00, 0x23, 0x15, 0xe8, 0x06
+.data1 	0x00, 0x00, 0x89, 0xd6, 0x83, 0xfe, 0x70, 0x7c
+.data1 	0x02, 0x31, 0xf6, 0x85, 0xf6, 0x74, 0x35, 0x89
+.data1 	0xf2, 0xc1, 0xfa, 0x02, 0x4a, 0x89, 0xd6, 0x83
+.data1 	0xfe, 0x07, 0x7c, 0x0a, 0xb8, 0xfa, 0xff, 0xff
+.data1 	0xff, 0xe9, 0xe8, 0x00, 0x00, 0x00, 0x8b, 0x15
+.data1 	0xec, 0x06, 0x00, 0x00, 0x89, 0xf1, 0x88, 0x4a
+.data1 	0x15, 0xff, 0x35, 0xe8, 0x06, 0x00, 0x00, 0xe8
+.data1 	0x9c, 0xee, 0xff, 0xff, 0x59, 0x31, 0xc0, 0xe9
+.data1 	0xca, 0x00, 0x00, 0x00, 0x8b, 0x15, 0xe8, 0x06
+.data1 	0x00, 0x00, 0xf6, 0xc2, 0x80, 0x74, 0x0a, 0xb8
+.data1 	0xfb, 0xff, 0xff, 0xff, 0xe9, 0xb5, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x15, 0xec, 0x06, 0x00, 0x00, 0x80
+.data1 	0x7a, 0x15, 0x64, 0x74, 0x38, 0x8b, 0x0d, 0xe4
+.data1 	0x06, 0x00, 0x00, 0xba, 0x01, 0x00, 0x00, 0x00
+.data1 	0xd3, 0xe2, 0x85, 0x15, 0xdc, 0x06, 0x00, 0x00
+.data1 	0x74, 0x07, 0x31, 0xc0, 0xe9, 0x8d, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x15, 0xec, 0x06, 0x00, 0x00, 0x0f
+.data1 	0xb6, 0x42, 0x15, 0x50, 0xe8, 0x81, 0x00, 0x00
+.data1 	0x00, 0x59, 0x85, 0xc0, 0x75, 0x07, 0x31, 0xc0
+.data1 	0xe9, 0x71, 0x00, 0x00, 0x00, 0xbf, 0x48, 0x05
+.data1 	0x00, 0x00, 0x81, 0xff, 0x54, 0x05, 0x00, 0x00
+.data1 	0x73, 0x55, 0x0f, 0xb6, 0x17, 0x89, 0xd6, 0x8b
+.data1 	0x15, 0xec, 0x06, 0x00, 0x00, 0x89, 0xf1, 0xbb
+.data1 	0x01, 0x00, 0x00, 0x00, 0xd3, 0xe3, 0x0f, 0xb6
+.data1 	0x4a, 0x16, 0x85, 0xd9, 0x74, 0x34, 0x56, 0xe8
+.data1 	0x46, 0x00, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x75
+.data1 	0x1d, 0x8b, 0x15, 0xec, 0x06, 0x00, 0x00, 0x0f
+.data1 	0xb6, 0x4a, 0x16, 0x0f, 0xb6, 0x57, 0x01, 0x21
+.data1 	0xd1, 0x8b, 0x15, 0xec, 0x06, 0x00, 0x00, 0x88
+.data1 	0x4a, 0x16, 0x31, 0xc0, 0xeb, 0x20, 0x0f, 0xb7
+.data1 	0x15, 0xfc, 0x06, 0x00, 0x00, 0x83, 0xfa, 0x02
+.data1 	0x74, 0x05, 0x83, 0xc7, 0x02, 0xeb, 0xa3, 0x8b
+.data1 	0x15, 0xec, 0x06, 0x00, 0x00, 0xc6, 0x42, 0x15
+.data1 	0x64, 0xb8, 0xfb, 0xff, 0xff, 0xff, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x14
+.data1 	0x8b, 0x15, 0xec, 0x06, 0x00, 0x00, 0x8b, 0x4d
+.data1 	0x08, 0x88, 0x4a, 0x15, 0x8b, 0x55, 0x08, 0x42
+.data1 	0xc1, 0xe2, 0x02, 0x03, 0x15, 0xe4, 0x06, 0x00
+.data1 	0x00, 0x89, 0x55, 0xfc, 0x52, 0xe8, 0x9e, 0xed
+.data1 	0xff, 0xff, 0x59, 0x8b, 0x15, 0xf0, 0x06, 0x00
+.data1 	0x00, 0x0f, 0xb6, 0x4a, 0x03, 0xc1, 0xe1, 0x09
+.data1 	0x89, 0x4d, 0xf8, 0x8b, 0x15, 0x90, 0x15, 0x00
+.data1 	0x00, 0x89, 0x55, 0xf0, 0xc7, 0x45, 0xf4, 0x00
+.data1 	0x02, 0x00, 0x00, 0x6a, 0x01, 0x8d, 0x45, 0xf0
+.data1 	0x50, 0xff, 0x75, 0xf8, 0x68, 0x09, 0x04, 0x00
+.data1 	0x00, 0x68, 0xce, 0x8a, 0x00, 0x00, 0xe8, 0x96
+.data1 	0xee, 0xff, 0xff, 0x83, 0xc4, 0x14, 0x89, 0x45
+.data1 	0xec, 0x83, 0x7d, 0xf4, 0x00, 0x74, 0x07, 0xb8
+.data1 	0xfb, 0xff, 0xff, 0xff, 0xeb, 0x19, 0x6a, 0x00
+.data1 	0x6a, 0x00, 0xff, 0x35, 0xe4, 0x06, 0x00, 0x00
+.data1 	0x68, 0x54, 0x05, 0x00, 0x00, 0xe8, 0x9e, 0x04
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x10, 0x31, 0xc0, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x8b, 0x15, 0xf0, 0x06
+.data1 	0x00, 0x00, 0x8b, 0x4d, 0x08, 0x0f, 0xb6, 0x5a
+.data1 	0x01, 0x89, 0x59, 0x10, 0x8b, 0x55, 0x08, 0xc7
+.data1 	0x42, 0x14, 0x02, 0x00, 0x00, 0x00, 0x8b, 0x55
+.data1 	0x08, 0x8b, 0x0d, 0xf8, 0x06, 0x00, 0x00, 0x89
+.data1 	0x4a, 0x18, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x2c, 0x56, 0x57, 0x8b, 0x75, 0x08, 0xe8
+.data1 	0x45, 0x01, 0x00, 0x00, 0x8d, 0x45, 0xd4, 0x50
+.data1 	0x68, 0xce, 0x7a, 0x00, 0x00, 0xe8, 0x36, 0x11
+.data1 	0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x75, 0xec
+.data1 	0x8b, 0x55, 0xd4, 0x89, 0x15, 0x94, 0x15, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xe0, 0x89, 0x55, 0xf8, 0xe9
+.data1 	0xdb, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xd4, 0x50
+.data1 	0x56, 0xff, 0x56, 0x04, 0x59, 0x59, 0x89, 0xc7
+.data1 	0xe9, 0xd7, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xd4
+.data1 	0x50, 0x56, 0xff, 0x56, 0x08, 0x59, 0x59, 0x89
+.data1 	0xc7, 0xe9, 0xc6, 0x00, 0x00, 0x00, 0x8d, 0x45
+.data1 	0xd4, 0x50, 0x56, 0xff, 0x56, 0x0c, 0x59, 0x59
+.data1 	0x89, 0xc7, 0xe9, 0xb5, 0x00, 0x00, 0x00, 0x8d
+.data1 	0x45, 0xd4, 0x50, 0x56, 0xff, 0x56, 0x28, 0x59
+.data1 	0x59, 0x89, 0xc7, 0xe9, 0xa4, 0x00, 0x00, 0x00
+.data1 	0x8d, 0x45, 0xd4, 0x50, 0x56, 0xff, 0x56, 0x2c
+.data1 	0x59, 0x59, 0x89, 0xc7, 0xe9, 0x93, 0x00, 0x00
+.data1 	0x00, 0x8d, 0x45, 0xd4, 0x50, 0x56, 0xe8, 0x1e
+.data1 	0x01, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc7, 0xe9
+.data1 	0x80, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xd4, 0x50
+.data1 	0x56, 0xe8, 0xb7, 0x01, 0x00, 0x00, 0x59, 0x59
+.data1 	0x89, 0xc7, 0xe9, 0x6d, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7e, 0x34, 0x00, 0x0f, 0x84, 0x53, 0xff, 0xff
+.data1 	0xff, 0x8d, 0x45, 0xd4, 0x50, 0x56, 0xff, 0x56
+.data1 	0x34, 0x59, 0x59, 0xe9, 0x44, 0xff, 0xff, 0xff
+.data1 	0x8d, 0x45, 0xd4, 0x50, 0x56, 0xff, 0x56, 0x20
+.data1 	0x59, 0x59, 0xe9, 0x35, 0xff, 0xff, 0xff, 0x8d
+.data1 	0x45, 0xd4, 0x50, 0x56, 0xff, 0x56, 0x24, 0x59
+.data1 	0x59, 0xe9, 0x26, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0xd4, 0xe8, 0x8a, 0x10, 0x00, 0x00, 0x59, 0xe9
+.data1 	0x18, 0xff, 0xff, 0xff, 0x83, 0x7e, 0x30, 0x00
+.data1 	0x74, 0x0e, 0x8d, 0x45, 0xd4, 0x50, 0x56, 0xff
+.data1 	0x56, 0x30, 0x59, 0x59, 0x89, 0xc7, 0xeb, 0x14
+.data1 	0xbf, 0xea, 0xff, 0xff, 0xff, 0xeb, 0x0d, 0xbb
+.data1 	0xc0, 0x03, 0x00, 0x00, 0x8b, 0x45, 0xd8, 0xe9
+.data1 	0x64, 0x12, 0x00, 0x00, 0xff, 0x56, 0x18, 0x81
+.data1 	0xff, 0x37, 0xff, 0xff, 0xff, 0x0f, 0x84, 0xe1
+.data1 	0xfe, 0xff, 0xff, 0xc7, 0x45, 0xd8, 0x44, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x55, 0xf8, 0x89, 0x55, 0xdc
+.data1 	0x89, 0x7d, 0xe0, 0x8d, 0x45, 0xd4, 0x50, 0xff
+.data1 	0x35, 0x94, 0x15, 0x00, 0x00, 0xe8, 0xf2, 0x0f
+.data1 	0x00, 0x00, 0x59, 0x59, 0xe9, 0xbb, 0xfe, 0xff
+.data1 	0xff, 0x55, 0x89, 0xe5, 0x56, 0xc7, 0x05, 0x90
+.data1 	0x15, 0x00, 0x00, 0x30, 0x07, 0x00, 0x00, 0x68
+.data1 	0x8c, 0x15, 0x00, 0x00, 0x68, 0x00, 0x04, 0x00
+.data1 	0x00, 0x68, 0x30, 0x07, 0x00, 0x00, 0x6a, 0x01
+.data1 	0x68, 0xce, 0x8a, 0x00, 0x00, 0xe8, 0x5e, 0x08
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x14, 0xba, 0xff, 0xff
+.data1 	0x00, 0x00, 0x23, 0x15, 0x8c, 0x15, 0x00, 0x00
+.data1 	0x81, 0xea, 0x00, 0x00, 0x01, 0x00, 0xf7, 0xda
+.data1 	0x89, 0xd6, 0x81, 0xfa, 0x00, 0x02, 0x00, 0x00
+.data1 	0x73, 0x14, 0x89, 0xf2, 0x03, 0x15, 0x90, 0x15
+.data1 	0x00, 0x00, 0x89, 0x15, 0x90, 0x15, 0x00, 0x00
+.data1 	0x01, 0x35, 0x8c, 0x15, 0x00, 0x00, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x14, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x0c, 0x83, 0x7e, 0x10, 0x00
+.data1 	0x79, 0x0a, 0xb8, 0xea, 0xff, 0xff, 0xff, 0xe9
+.data1 	0x8d, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xec, 0x50
+.data1 	0xff, 0x76, 0x10, 0xff, 0x76, 0x1c, 0x6a, 0x01
+.data1 	0xff, 0x76, 0x0c, 0xe8, 0xf8, 0x07, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x14, 0x83, 0x7d, 0xec, 0x00, 0x75
+.data1 	0x0a, 0xb8, 0xf2, 0xff, 0xff, 0xff, 0xe9, 0x66
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x08, 0xff, 0x76
+.data1 	0x08, 0xff, 0x52, 0x10, 0x59, 0x85, 0xc0, 0x75
+.data1 	0x0a, 0xb8, 0xfa, 0xff, 0xff, 0xff, 0xe9, 0x4e
+.data1 	0x00, 0x00, 0x00, 0x81, 0x7e, 0x04, 0x03, 0x04
+.data1 	0x00, 0x00, 0x75, 0x07, 0xb8, 0x09, 0x04, 0x00
+.data1 	0x00, 0xeb, 0x05, 0xb8, 0x08, 0x04, 0x00, 0x00
+.data1 	0x89, 0x45, 0xf0, 0x8b, 0x56, 0x1c, 0x89, 0x55
+.data1 	0xf8, 0x8b, 0x56, 0x10, 0x89, 0x55, 0xfc, 0x8b
+.data1 	0x55, 0x08, 0x6a, 0x01, 0x8d, 0x45, 0xf8, 0x50
+.data1 	0xff, 0x76, 0x14, 0xff, 0x75, 0xf0, 0xff, 0x76
+.data1 	0x0c, 0xff, 0x52, 0x14, 0x83, 0xc4, 0x14, 0x89
+.data1 	0xc7, 0x85, 0xff, 0x75, 0x0a, 0x8b, 0x56, 0x10
+.data1 	0x2b, 0x55, 0xfc, 0x89, 0xd0, 0xeb, 0x02, 0x89
+.data1 	0xf8, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x10, 0x56, 0x57, 0x8b, 0x75, 0x0c
+.data1 	0x8b, 0x7e, 0x10, 0x83, 0xff, 0x40, 0x76, 0x05
+.data1 	0xbf, 0x40, 0x00, 0x00, 0x00, 0x89, 0xfa, 0xc1
+.data1 	0xe2, 0x03, 0x89, 0x55, 0xf8, 0x52, 0x68, 0x30
+.data1 	0x0b, 0x00, 0x00, 0x6a, 0x01, 0x68, 0xce, 0x8a
+.data1 	0x00, 0x00, 0xff, 0x76, 0x1c, 0x6a, 0x01, 0xff
+.data1 	0x36, 0xe8, 0x86, 0x07, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x1c, 0x85, 0xc0, 0x74, 0x15, 0x8b, 0x45, 0x08
+.data1 	0xff, 0x36, 0x68, 0x38, 0x04, 0x00, 0x00, 0xff
+.data1 	0x10, 0x50, 0xe8, 0xa9, 0x05, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xc7, 0x45, 0xfc, 0x30, 0x0b, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x08, 0xff, 0x76, 0x08, 0xff
+.data1 	0x52, 0x10, 0x59, 0x85, 0xc0, 0x75, 0x07, 0xb8
+.data1 	0xfa, 0xff, 0xff, 0xff, 0xeb, 0x3a, 0x8b, 0x55
+.data1 	0x08, 0x57, 0xff, 0x75, 0xfc, 0xff, 0x76, 0x14
+.data1 	0xff, 0x76, 0x04, 0xff, 0x76, 0x0c, 0xff, 0x52
+.data1 	0x14, 0x83, 0xc4, 0x14, 0x89, 0x45, 0xf0, 0xff
+.data1 	0x75, 0xf8, 0xff, 0x76, 0x1c, 0x6a, 0x01, 0xff
+.data1 	0x36, 0x68, 0x30, 0x0b, 0x00, 0x00, 0x6a, 0x01
+.data1 	0x68, 0xce, 0x8a, 0x00, 0x00, 0xe8, 0x1a, 0x07
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x1c, 0x8b, 0x45, 0xf0
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0xb8
+.data1 	0x90, 0x05, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0xeb, 0x19, 0xb8, 0xed, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x22, 0x31, 0xc0, 0xeb, 0x1e, 0xb8, 0xe7
+.data1 	0xff, 0xff, 0xff, 0xeb, 0x17, 0xb8, 0xfb, 0xff
+.data1 	0xff, 0xff, 0xeb, 0x10, 0x8b, 0x55, 0x0c, 0xbb
+.data1 	0x4c, 0x04, 0x00, 0x00, 0x8b, 0x42, 0x04, 0xe9
+.data1 	0x10, 0x10, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x31, 0xc0, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x31
+.data1 	0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x31, 0xc0
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x24
+.data1 	0x56, 0x57, 0x8b, 0x75, 0x0c, 0x81, 0x7e, 0x10
+.data1 	0x03, 0x64, 0x1c, 0x40, 0x74, 0x2a, 0x81, 0x7e
+.data1 	0x10, 0x04, 0x64, 0x1c, 0x80, 0x74, 0x21, 0x8b
+.data1 	0x55, 0x08, 0x83, 0x7a, 0x30, 0x00, 0x74, 0x0e
+.data1 	0x56, 0xff, 0x75, 0x08, 0xff, 0x52, 0x30, 0x59
+.data1 	0x59, 0xe9, 0xc6, 0x00, 0x00, 0x00, 0xb8, 0xe7
+.data1 	0xff, 0xff, 0xff, 0xe9, 0xbc, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x08, 0xff, 0x76, 0x08, 0xff, 0x52
+.data1 	0x10, 0x59, 0x89, 0xc7, 0x85, 0xc0, 0x75, 0x0a
+.data1 	0xb8, 0xfa, 0xff, 0xff, 0xff, 0xe9, 0xa2, 0x00
+.data1 	0x00, 0x00, 0x81, 0x7e, 0x10, 0x03, 0x64, 0x1c
+.data1 	0x40, 0x75, 0x4f, 0x6a, 0x1c, 0x8d, 0x45, 0xe0
+.data1 	0x50, 0x6a, 0x01, 0x68, 0xce, 0x8a, 0x00, 0x00
+.data1 	0xff, 0x76, 0x1c, 0x6a, 0x01, 0xff, 0x76, 0x0c
+.data1 	0xe8, 0x37, 0x06, 0x00, 0x00, 0x83, 0xc4, 0x1c
+.data1 	0x89, 0x45, 0xdc, 0x85, 0xc0, 0x74, 0x05, 0xe9
+.data1 	0x70, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xe0, 0x50
+.data1 	0x57, 0xb9, 0x02, 0x00, 0x00, 0x00, 0xe8, 0x39
+.data1 	0x0f, 0x00, 0x00, 0x8d, 0x45, 0xe8, 0x50, 0x8d
+.data1 	0x47, 0x08, 0x50, 0xb9, 0x02, 0x00, 0x00, 0x00
+.data1 	0xe8, 0x27, 0x0f, 0x00, 0x00, 0xe9, 0x48, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x17, 0x8b, 0x4f, 0x04, 0x89
+.data1 	0x55, 0xe0, 0x89, 0x4d, 0xe4, 0x8b, 0x57, 0x08
+.data1 	0x8b, 0x4f, 0x0c, 0x89, 0x55, 0xe8, 0x89, 0x4d
+.data1 	0xec, 0x8b, 0x55, 0x08, 0x8d, 0x45, 0xe0, 0x50
+.data1 	0xff, 0x52, 0x1c, 0x59, 0x6a, 0x1c, 0xff, 0x76
+.data1 	0x1c, 0x6a, 0x01, 0xff, 0x76, 0x0c, 0x8d, 0x45
+.data1 	0xe0, 0x50, 0x6a, 0x01, 0x68, 0xce, 0x8a, 0x00
+.data1 	0x00, 0xe8, 0xc6, 0x05, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x1c, 0x89, 0x45, 0xdc, 0x85, 0xc0, 0x74, 0x02
+.data1 	0xeb, 0x02, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x6c, 0x56, 0x57
+.data1 	0x8b, 0x55, 0x08, 0xff, 0x75, 0x0c, 0xff, 0x52
+.data1 	0x10, 0x59, 0x89, 0xc7, 0x85, 0xc0, 0x0f, 0x84
+.data1 	0xb4, 0x01, 0x00, 0x00, 0x6a, 0x00, 0xff, 0x77
+.data1 	0x0c, 0xff, 0x77, 0x08, 0xe8, 0x4b, 0x0c, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x0f, 0x84
+.data1 	0x9c, 0x01, 0x00, 0x00, 0x68, 0x00, 0x02, 0x00
+.data1 	0x00, 0xff, 0x77, 0x04, 0xff, 0x37, 0xe8, 0x5d
+.data1 	0x0c, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45
+.data1 	0xac, 0x68, 0x00, 0x02, 0x00, 0x00, 0xff, 0x77
+.data1 	0x0c, 0xff, 0x77, 0x08, 0xe8, 0x47, 0x0c, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x03, 0x45, 0xac, 0x89
+.data1 	0x45, 0xa8, 0x8d, 0x45, 0xc0, 0x50, 0x6a, 0x00
+.data1 	0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0xe8, 0x8f
+.data1 	0x02, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x85, 0xc0
+.data1 	0x75, 0x49, 0xe9, 0x51, 0x01, 0x00, 0x00, 0x83
+.data1 	0x45, 0x0c, 0x70, 0xeb, 0x4b, 0x8d, 0x45, 0xc0
+.data1 	0x50, 0xe8, 0xf4, 0x02, 0x00, 0x00, 0x59, 0xff
+.data1 	0x45, 0x0c, 0xeb, 0x3c, 0xb9, 0x05, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x45, 0x0c, 0x99, 0xf7, 0xf9, 0x89
+.data1 	0x45, 0xb8, 0x8b, 0x45, 0x0c, 0x99, 0xf7, 0xf9
+.data1 	0x4a, 0x89, 0x55, 0xb4, 0x8b, 0x55, 0xb8, 0xc1
+.data1 	0xe2, 0x02, 0x03, 0x55, 0xb4, 0xc1, 0xe2, 0x02
+.data1 	0x81, 0xc2, 0x80, 0x00, 0x00, 0x00, 0x89, 0x55
+.data1 	0x0c, 0xeb, 0x0d, 0xbb, 0x64, 0x04, 0x00, 0x00
+.data1 	0x8b, 0x45, 0x10, 0xe9, 0x1c, 0x0e, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x08, 0xff, 0x75, 0x0c, 0xff, 0x52
+.data1 	0x10, 0x59, 0x89, 0xc7, 0x85, 0xc0, 0x0f, 0x84
+.data1 	0xec, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xb4, 0x00
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xb4, 0x04, 0x0f
+.data1 	0x8d, 0xdb, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xb4
+.data1 	0xc1, 0xe2, 0x04, 0x8d, 0x4d, 0xc0, 0x89, 0xd6
+.data1 	0x01, 0xce, 0x8b, 0x56, 0x0c, 0x03, 0x56, 0x08
+.data1 	0x89, 0x55, 0xa4, 0x39, 0x56, 0x08, 0x76, 0x06
+.data1 	0x8b, 0x55, 0xa8, 0x89, 0x55, 0xa4, 0x8b, 0x55
+.data1 	0xa8, 0x39, 0x55, 0xa4, 0x76, 0x03, 0x89, 0x55
+.data1 	0xa4, 0x8b, 0x55, 0xac, 0x39, 0x56, 0x08, 0x73
+.data1 	0x03, 0x89, 0x56, 0x08, 0x8b, 0x55, 0xa4, 0x39
+.data1 	0x56, 0x08, 0x76, 0x06, 0x8b, 0x56, 0x08, 0x89
+.data1 	0x55, 0xa4, 0x68, 0x00, 0x02, 0x00, 0x00, 0xff
+.data1 	0x76, 0x08, 0x8d, 0x45, 0x9c, 0x50, 0xe8, 0x75
+.data1 	0x0b, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x50, 0x57
+.data1 	0xb9, 0x02, 0x00, 0x00, 0x00, 0xe8, 0x7a, 0x0d
+.data1 	0x00, 0x00, 0x8b, 0x55, 0xa4, 0x2b, 0x56, 0x08
+.data1 	0x68, 0x00, 0x02, 0x00, 0x00, 0x52, 0x8d, 0x45
+.data1 	0x94, 0x50, 0xe8, 0x51, 0x0b, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x50, 0x8d, 0x47, 0x08, 0x50, 0xb9
+.data1 	0x02, 0x00, 0x00, 0x00, 0xe8, 0x53, 0x0d, 0x00
+.data1 	0x00, 0x83, 0x7d, 0x10, 0x01, 0x75, 0x3e, 0x80
+.data1 	0x7e, 0x04, 0x81, 0x75, 0x17, 0x8b, 0x55, 0xb4
+.data1 	0x03, 0x55, 0x0c, 0xff, 0x75, 0x14, 0x6a, 0x02
+.data1 	0x52, 0xff, 0x75, 0x08, 0xe8, 0x5f, 0xfe, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x10, 0x80, 0x7e, 0x04, 0x05
+.data1 	0x74, 0x06, 0x80, 0x7e, 0x04, 0x0f, 0x75, 0x15
+.data1 	0x8b, 0x55, 0xb4, 0x03, 0x55, 0x0c, 0xff, 0x76
+.data1 	0x08, 0x52, 0xff, 0x75, 0x08, 0xe8, 0x12, 0x00
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xff, 0x45, 0xb4
+.data1 	0x83, 0xc7, 0x10, 0xe9, 0x1b, 0xff, 0xff, 0xff
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x6c, 0x56, 0x57, 0xb9, 0x05, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x45, 0x0c, 0x99, 0xf7, 0xf9, 0x89
+.data1 	0x45, 0xb4, 0x8b, 0x45, 0x0c, 0x99, 0xf7, 0xf9
+.data1 	0x4a, 0x89, 0xd7, 0x8b, 0x55, 0xb4, 0xc1, 0xe2
+.data1 	0x02, 0x01, 0xfa, 0xc1, 0xe2, 0x02, 0x81, 0xc2
+.data1 	0x80, 0x00, 0x00, 0x00, 0x89, 0x55, 0xb8, 0xc7
+.data1 	0x45, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x45
+.data1 	0xc0, 0x50, 0xff, 0x75, 0xa8, 0xff, 0x75, 0x0c
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xe2, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0x85, 0xc0, 0x0f, 0x84, 0xd3
+.data1 	0x00, 0x00, 0x00, 0x8d, 0x45, 0xc0, 0x50, 0xe8
+.data1 	0x4e, 0x01, 0x00, 0x00, 0x59, 0xc7, 0x45, 0xa4
+.data1 	0x00, 0x00, 0x00, 0x00, 0x31, 0xff, 0x83, 0xff
+.data1 	0x04, 0x0f, 0x8d, 0xa9, 0x00, 0x00, 0x00, 0x89
+.data1 	0xfa, 0xc1, 0xe2, 0x04, 0x8d, 0x4d, 0xc0, 0x89
+.data1 	0xd6, 0x01, 0xce, 0x80, 0x7e, 0x04, 0x05, 0x74
+.data1 	0x06, 0x80, 0x7e, 0x04, 0x0f, 0x75, 0x0b, 0x8b
+.data1 	0x56, 0x08, 0x89, 0x55, 0xa4, 0xe9, 0x80, 0x00
+.data1 	0x00, 0x00, 0x80, 0x7e, 0x04, 0x00, 0x0f, 0x84
+.data1 	0x76, 0x00, 0x00, 0x00, 0x8b, 0x55, 0x08, 0xff
+.data1 	0x75, 0xb8, 0xff, 0x52, 0x10, 0x59, 0x89, 0x45
+.data1 	0xac, 0x85, 0xc0, 0x0f, 0x84, 0x75, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xa8, 0x03, 0x55, 0x10, 0x03
+.data1 	0x56, 0x08, 0x68, 0x00, 0x02, 0x00, 0x00, 0x52
+.data1 	0x8d, 0x45, 0x9c, 0x50, 0xe8, 0x1f, 0x0a, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x50, 0xff, 0x75, 0xac
+.data1 	0xb9, 0x02, 0x00, 0x00, 0x00, 0xe8, 0x22, 0x0c
+.data1 	0x00, 0x00, 0x68, 0x00, 0x02, 0x00, 0x00, 0xff
+.data1 	0x76, 0x0c, 0x8d, 0x45, 0x94, 0x50, 0xe8, 0xfd
+.data1 	0x09, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55
+.data1 	0xac, 0x50, 0x83, 0xc2, 0x08, 0x52, 0xb9, 0x02
+.data1 	0x00, 0x00, 0x00, 0xe8, 0xfc, 0x0b, 0x00, 0x00
+.data1 	0xff, 0x45, 0xb8, 0xb9, 0x04, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x45, 0xb8, 0x99, 0xf7, 0xf9, 0x85, 0xd2
+.data1 	0x74, 0x14, 0x47, 0xe9, 0x4e, 0xff, 0xff, 0xff
+.data1 	0x8b, 0x55, 0xa4, 0x89, 0x55, 0xa8, 0x85, 0xd2
+.data1 	0x0f, 0x85, 0x10, 0xff, 0xff, 0xff, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c
+.data1 	0x8b, 0x55, 0x10, 0xc1, 0xe2, 0x09, 0x89, 0x55
+.data1 	0xf4, 0xc7, 0x45, 0xf8, 0x30, 0x0d, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xfc, 0x00, 0x08, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x08, 0xff, 0x75, 0x0c, 0xff, 0x52, 0x10
+.data1 	0x59, 0x85, 0xc0, 0x74, 0x1c, 0x8b, 0x55, 0x08
+.data1 	0x6a, 0x01, 0x8d, 0x45, 0xf8, 0x50, 0xff, 0x75
+.data1 	0xf4, 0x68, 0x09, 0x04, 0x00, 0x00, 0x68, 0xce
+.data1 	0x8a, 0x00, 0x00, 0xff, 0x52, 0x14, 0x83, 0xc4
+.data1 	0x14, 0x83, 0x7d, 0xfc, 0x00, 0x74, 0x04, 0x31
+.data1 	0xc0, 0xeb, 0x2d, 0x80, 0x3d, 0x2e, 0x0f, 0x00
+.data1 	0x00, 0x55, 0x75, 0x09, 0x80, 0x3d, 0x2f, 0x0f
+.data1 	0x00, 0x00, 0xaa, 0x74, 0x04, 0x31, 0xc0, 0xeb
+.data1 	0x17, 0x6a, 0x40, 0x68, 0xee, 0x0e, 0x00, 0x00
+.data1 	0xff, 0x75, 0x14, 0xe8, 0xbc, 0x09, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0xb8, 0x01, 0x00, 0x00, 0x00
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x14
+.data1 	0x56, 0x57, 0xbf, 0x04, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x75, 0x08, 0x8b, 0x55, 0x08, 0x83, 0xc2, 0x30
+.data1 	0x39, 0xf2, 0x76, 0x49, 0x80, 0x7e, 0x04, 0x00
+.data1 	0x74, 0x0e, 0x8b, 0x56, 0x18, 0x39, 0x56, 0x08
+.data1 	0x76, 0x36, 0x80, 0x7e, 0x14, 0x00, 0x74, 0x30
+.data1 	0x56, 0x8d, 0x45, 0xec, 0x50, 0xb9, 0x04, 0x00
+.data1 	0x00, 0x00, 0xe8, 0x15, 0x0b, 0x00, 0x00, 0x8d
+.data1 	0x46, 0x10, 0x50, 0x56, 0xb9, 0x04, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x06, 0x0b, 0x00, 0x00, 0x8d, 0x45
+.data1 	0xec, 0x50, 0x8d, 0x46, 0x10, 0x50, 0xb9, 0x04
+.data1 	0x00, 0x00, 0x00, 0xe8, 0xf4, 0x0a, 0x00, 0x00
+.data1 	0x83, 0xc6, 0x10, 0xeb, 0xad, 0x4f, 0x85, 0xff
+.data1 	0x7f, 0xa5, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0xc7, 0x05
+.data1 	0x98, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x08, 0x00, 0x74, 0x3a, 0x83, 0x7d
+.data1 	0x0c, 0x00, 0x74, 0x34, 0x81, 0x7d, 0x10, 0x00
+.data1 	0x80, 0x00, 0x00, 0x74, 0x18, 0xff, 0x75, 0x10
+.data1 	0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0x68, 0x90
+.data1 	0x04, 0x00, 0x00, 0xe8, 0x7c, 0x02, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0xeb, 0x13, 0xff, 0x75, 0x0c
+.data1 	0xff, 0x75, 0x08, 0x68, 0x7c, 0x04, 0x00, 0x00
+.data1 	0xe8, 0x67, 0x02, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x6a, 0x09, 0x68, 0xce, 0x8a, 0x00, 0x00, 0xe8
+.data1 	0xa0, 0x00, 0x00, 0x00, 0x59, 0x59, 0xba, 0xff
+.data1 	0xff, 0xff, 0xff, 0x89, 0x55, 0xd8, 0xff, 0xd2
+.data1 	0xeb, 0xfe, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x8b, 0x55, 0x10, 0x89, 0x55, 0xe4
+.data1 	0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x08, 0x89, 0x55, 0xf0, 0x8d, 0x45, 0xdc
+.data1 	0x50, 0x68, 0x15, 0x06, 0x00, 0x00, 0x6a, 0xfe
+.data1 	0xe8, 0xbb, 0x01, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0x45, 0xd8, 0x8b, 0x55, 0xf4, 0x8b, 0x45
+.data1 	0x0c, 0x89, 0x10, 0x8b, 0x45, 0xd8, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0xc7, 0x45
+.data1 	0xe0, 0x13, 0x06, 0x00, 0x00, 0x8b, 0x55, 0x08
+.data1 	0x66, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x0c, 0x66
+.data1 	0x89, 0x55, 0xe6, 0x8b, 0x55, 0x10, 0x89, 0x55
+.data1 	0xe8, 0x8b, 0x45, 0x14, 0x8b, 0x10, 0x89, 0x55
+.data1 	0xf8, 0x8d, 0x45, 0xdc, 0x50, 0x68, 0x13, 0x06
+.data1 	0x00, 0x00, 0x6a, 0xfe, 0xe8, 0x6f, 0x01, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45, 0xd8, 0x83
+.data1 	0x7d, 0x08, 0x01, 0x75, 0x08, 0x8b, 0x55, 0xf8
+.data1 	0x8b, 0x45, 0x14, 0x89, 0x10, 0x8b, 0x45, 0xd8
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x55, 0xe8, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0x68, 0x06, 0x06, 0x00, 0x00, 0x6a
+.data1 	0xfe, 0xe8, 0x32, 0x01, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x10, 0x89, 0x55, 0xe4
+.data1 	0xc7, 0x45, 0xec, 0x01, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x08, 0x89, 0x55, 0xf0, 0x8b, 0x55, 0x0c
+.data1 	0x89, 0x55, 0xf4, 0x8d, 0x45, 0xdc, 0x50, 0x68
+.data1 	0x15, 0x06, 0x00, 0x00, 0x6a, 0xfe, 0xe8, 0xfd
+.data1 	0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xf0, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xe8, 0x8d, 0x45, 0xdc, 0x50, 0x68, 0x18
+.data1 	0x06, 0x00, 0x00, 0x6a, 0xfe, 0xe8, 0xd6, 0x00
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe8, 0x8b, 0x55, 0x0c, 0x66
+.data1 	0x89, 0x55, 0xe4, 0x8b, 0x55, 0x10, 0x89, 0x55
+.data1 	0xf0, 0x8b, 0x55, 0x14, 0x89, 0x55, 0xf8, 0x8d
+.data1 	0x45, 0xdc, 0x50, 0x68, 0x0e, 0x06, 0x00, 0x00
+.data1 	0x6a, 0xfe, 0xe8, 0xa1, 0x00, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0x45, 0xd8, 0x8b, 0x55, 0xf4
+.data1 	0x8b, 0x45, 0x18, 0x89, 0x10, 0x8b, 0x45, 0xd8
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x83, 0x7d, 0x20, 0x00, 0x75, 0x04
+.data1 	0x31, 0xc0, 0xeb, 0x3f, 0x8b, 0x55, 0x08, 0x89
+.data1 	0x55, 0xe8, 0x8b, 0x55, 0x0c, 0x66, 0x89, 0x55
+.data1 	0xe4, 0x8b, 0x55, 0x10, 0x89, 0x55, 0xf0, 0x8b
+.data1 	0x55, 0x14, 0x89, 0x55, 0xec, 0x8b, 0x55, 0x18
+.data1 	0x66, 0x89, 0x55, 0xe6, 0x8b, 0x55, 0x1c, 0x89
+.data1 	0x55, 0xf4, 0x8b, 0x55, 0x20, 0x89, 0x55, 0xf8
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x68, 0x0f, 0x06, 0x00
+.data1 	0x00, 0x6a, 0xfe, 0xe8, 0x40, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0xc7, 0x45
+.data1 	0xe4, 0x62, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xec
+.data1 	0x01, 0x00, 0x00, 0x00, 0x8b, 0x55, 0x08, 0x89
+.data1 	0x55, 0xf8, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf4
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x68, 0x17, 0x06, 0x00
+.data1 	0x00, 0x6a, 0xfe, 0xe8, 0x08, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x75, 0x10
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x56, 0x04, 0x56, 0xff
+.data1 	0x75, 0x08, 0xe8, 0xa5, 0x06, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0xc7, 0x85, 0xff, 0x74, 0x04, 0x89
+.data1 	0xf8, 0xeb, 0x03, 0x8b, 0x46, 0x04, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0xc7, 0x45, 0xe0, 0x19, 0x06, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xe4, 0xce, 0x6a, 0x00, 0x00
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x68, 0x19, 0x06, 0x00
+.data1 	0x00, 0x6a, 0xfe, 0xe8, 0xb0, 0xff, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x45, 0xd8, 0x8b, 0x55
+.data1 	0xf4, 0x8b, 0x45, 0x08, 0x89, 0x10, 0x8b, 0x45
+.data1 	0xd8, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x40, 0x56, 0x57, 0xc7, 0x45, 0xf8, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8d, 0x7d, 0x0c, 0x8b, 0x45
+.data1 	0x08, 0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89
+.data1 	0xc6, 0x85, 0xc0, 0x0f, 0x84, 0x03, 0x03, 0x00
+.data1 	0x00, 0x83, 0xfe, 0x25, 0x74, 0x0c, 0xff, 0x45
+.data1 	0xf8, 0x56, 0xe8, 0x05, 0x03, 0x00, 0x00, 0x59
+.data1 	0xeb, 0xdc, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08
+.data1 	0x0f, 0xbe, 0x00, 0x89, 0xc6, 0xc7, 0x45, 0xf4
+.data1 	0x01, 0x00, 0x00, 0x00, 0x83, 0xfe, 0x2d, 0x75
+.data1 	0x12, 0xc7, 0x45, 0xf4, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f, 0xbe
+.data1 	0x00, 0x89, 0xc6, 0xc7, 0x45, 0xec, 0x20, 0x00
+.data1 	0x00, 0x00, 0x83, 0xfe, 0x30, 0x75, 0x12, 0xc7
+.data1 	0x45, 0xec, 0x30, 0x00, 0x00, 0x00, 0x8b, 0x45
+.data1 	0x08, 0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89
+.data1 	0xc6, 0xc7, 0x45, 0xe8, 0x00, 0x00, 0x00, 0x00
+.data1 	0x83, 0xfe, 0x2a, 0x75, 0x18, 0x8d, 0x57, 0x04
+.data1 	0x89, 0xd7, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xe8
+.data1 	0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f, 0xbe
+.data1 	0x00, 0x89, 0xc6, 0xeb, 0x2f, 0x89, 0xf2, 0x83
+.data1 	0xea, 0x30, 0x83, 0xfa, 0x0a, 0x73, 0x25, 0x6b
+.data1 	0x45, 0xe8, 0x0a, 0x89, 0xf2, 0x83, 0xea, 0x30
+.data1 	0x01, 0xc2, 0x89, 0x55, 0xe8, 0x8b, 0x45, 0x08
+.data1 	0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0xc6
+.data1 	0x2d, 0x30, 0x00, 0x00, 0x00, 0x3d, 0x0a, 0x00
+.data1 	0x00, 0x00, 0x72, 0xdb, 0xc7, 0x45, 0xe4, 0xff
+.data1 	0xff, 0xff, 0x7f, 0x83, 0xfe, 0x2e, 0x0f, 0x85
+.data1 	0x60, 0x00, 0x00, 0x00, 0x8b, 0x45, 0x08, 0xff
+.data1 	0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0xc6, 0x3d
+.data1 	0x2a, 0x00, 0x00, 0x00, 0x75, 0x18, 0x8d, 0x57
+.data1 	0x04, 0x89, 0xd7, 0x8b, 0x52, 0xfc, 0x89, 0x55
+.data1 	0xe4, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f
+.data1 	0xbe, 0x00, 0x89, 0xc6, 0xeb, 0x36, 0x89, 0xf2
+.data1 	0x83, 0xea, 0x30, 0x83, 0xfa, 0x0a, 0x73, 0x2c
+.data1 	0xc7, 0x45, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x6b
+.data1 	0x45, 0xe4, 0x0a, 0x89, 0xf2, 0x83, 0xea, 0x30
+.data1 	0x01, 0xc2, 0x89, 0x55, 0xe4, 0x8b, 0x45, 0x08
+.data1 	0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0xc6
+.data1 	0x2d, 0x30, 0x00, 0x00, 0x00, 0x3d, 0x0a, 0x00
+.data1 	0x00, 0x00, 0x72, 0xdb, 0xc7, 0x45, 0xd8, 0xb0
+.data1 	0x05, 0x00, 0x00, 0xc7, 0x45, 0xd0, 0x00, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x45, 0xdc, 0x0a, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xf0, 0x01, 0x00, 0x00, 0x00
+.data1 	0x83, 0xfe, 0x6c, 0x74, 0x05, 0x83, 0xfe, 0x4c
+.data1 	0x75, 0x12, 0xc7, 0x45, 0xf0, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f
+.data1 	0xbe, 0x00, 0x89, 0xc6, 0x85, 0xf6, 0x0f, 0x85
+.data1 	0x9c, 0x01, 0x00, 0x00, 0xe9, 0xa3, 0x01, 0x00
+.data1 	0x00, 0x83, 0x7d, 0xf0, 0x00, 0x75, 0x0a, 0x8d
+.data1 	0x57, 0x04, 0x89, 0xd7, 0x8b, 0x42, 0xfc, 0xeb
+.data1 	0x08, 0x8d, 0x57, 0x04, 0x89, 0xd7, 0x8b, 0x42
+.data1 	0xfc, 0x89, 0x45, 0xd0, 0x85, 0xc0, 0x79, 0x04
+.data1 	0xf7, 0xd8, 0xeb, 0x03, 0x8b, 0x45, 0xd0, 0x89
+.data1 	0x45, 0xcc, 0xeb, 0x32, 0xc7, 0x45, 0xdc, 0x08
+.data1 	0x00, 0x00, 0x00, 0xeb, 0x0e, 0xc7, 0x45, 0xd8
+.data1 	0x9c, 0x05, 0x00, 0x00, 0xc7, 0x45, 0xdc, 0x10
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xf0, 0x00, 0x75
+.data1 	0x0a, 0x8d, 0x57, 0x04, 0x89, 0xd7, 0x8b, 0x42
+.data1 	0xfc, 0xeb, 0x08, 0x8d, 0x57, 0x04, 0x89, 0xd7
+.data1 	0x8b, 0x42, 0xfc, 0x89, 0x45, 0xcc, 0x8d, 0x55
+.data1 	0xcb, 0x89, 0x55, 0xd4, 0xc6, 0x02, 0x00, 0x8b
+.data1 	0x45, 0xcc, 0x31, 0xd2, 0xf7, 0x75, 0xdc, 0x03
+.data1 	0x55, 0xd8, 0x0f, 0xb6, 0x02, 0x50, 0xff, 0x4d
+.data1 	0xd4, 0x8b, 0x55, 0xd4, 0x59, 0x88, 0x0a, 0x8b
+.data1 	0x45, 0xcc, 0x31, 0xd2, 0xf7, 0x75, 0xdc, 0x89
+.data1 	0x45, 0xcc, 0x85, 0xc0, 0x75, 0xd9, 0xeb, 0x39
+.data1 	0x8d, 0x55, 0xc0, 0x89, 0x55, 0xd4, 0x8d, 0x57
+.data1 	0x04, 0x89, 0xd7, 0x8b, 0x4d, 0xd4, 0x8b, 0x52
+.data1 	0xfc, 0x88, 0x11, 0xc7, 0x45, 0xe0, 0x01, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x3c, 0x8d, 0x55, 0xc0, 0x89
+.data1 	0x55, 0xd4, 0xc6, 0x02, 0x25, 0xc7, 0x45, 0xe0
+.data1 	0x01, 0x00, 0x00, 0x00, 0xeb, 0x2a, 0x8d, 0x57
+.data1 	0x04, 0x89, 0xd7, 0x8b, 0x52, 0xfc, 0x89, 0x55
+.data1 	0xd4, 0xc7, 0x45, 0xe0, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x55, 0xd4, 0x03, 0x55, 0xe0, 0x80, 0x3a
+.data1 	0x00, 0x74, 0x0d, 0x8b, 0x55, 0xe4, 0x39, 0x55
+.data1 	0xe0, 0x7d, 0x05, 0xff, 0x45, 0xe0, 0xeb, 0xe8
+.data1 	0x8b, 0x55, 0xe8, 0x2b, 0x55, 0xe0, 0x89, 0x55
+.data1 	0xe8, 0x83, 0x7d, 0xd0, 0x00, 0x79, 0x03, 0xff
+.data1 	0x4d, 0xe8, 0x83, 0x7d, 0xec, 0x30, 0x75, 0x11
+.data1 	0x83, 0x7d, 0xd0, 0x00, 0x79, 0x0b, 0xff, 0x45
+.data1 	0xf8, 0x6a, 0x2d, 0xe8, 0xa4, 0x00, 0x00, 0x00
+.data1 	0x59, 0x83, 0x7d, 0xf4, 0x01, 0x75, 0x17, 0x83
+.data1 	0x7d, 0xe8, 0x00, 0x7e, 0x11, 0xff, 0x45, 0xf8
+.data1 	0xff, 0x75, 0xec, 0xe8, 0x8c, 0x00, 0x00, 0x00
+.data1 	0x59, 0xff, 0x4d, 0xe8, 0xeb, 0xe9, 0x83, 0x7d
+.data1 	0xec, 0x20, 0x75, 0x11, 0x83, 0x7d, 0xd0, 0x00
+.data1 	0x79, 0x0b, 0xff, 0x45, 0xf8, 0x6a, 0x2d, 0xe8
+.data1 	0x70, 0x00, 0x00, 0x00, 0x59, 0x83, 0x7d, 0xe0
+.data1 	0x00, 0x7e, 0x18, 0xff, 0x45, 0xf8, 0x8b, 0x45
+.data1 	0xd4, 0xff, 0x45, 0xd4, 0x0f, 0xb6, 0x18, 0x53
+.data1 	0xe8, 0x57, 0x00, 0x00, 0x00, 0x59, 0xff, 0x4d
+.data1 	0xe0, 0xeb, 0xe2, 0x83, 0x7d, 0xe8, 0x00, 0x0f
+.data1 	0x8e, 0x21, 0xfd, 0xff, 0xff, 0xff, 0x45, 0xf8
+.data1 	0xff, 0x75, 0xec, 0xe8, 0x3c, 0x00, 0x00, 0x00
+.data1 	0x59, 0xff, 0x4d, 0xe8, 0xeb, 0xe5, 0xff, 0x45
+.data1 	0xf8, 0x6a, 0x25, 0xe8, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x59, 0xff, 0x45, 0xf8, 0x56, 0xe8, 0x22, 0x00
+.data1 	0x00, 0x00, 0x59, 0xe9, 0xf6, 0xfc, 0xff, 0xff
+.data1 	0xbb, 0xa8, 0x04, 0x00, 0x00, 0x89, 0xf0, 0xe9
+.data1 	0x4c, 0x05, 0x00, 0x00, 0x6a, 0x00, 0xe8, 0x09
+.data1 	0x00, 0x00, 0x00, 0x59, 0x8b, 0x45, 0xf8, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x30, 0x56, 0x83, 0x7d, 0x08, 0x00, 0x75
+.data1 	0x09, 0x83, 0x3d, 0x80, 0x15, 0x00, 0x00, 0x00
+.data1 	0x7f, 0x09, 0x83, 0x3d, 0x80, 0x15, 0x00, 0x00
+.data1 	0x50, 0x75, 0x59, 0x68, 0xc4, 0x05, 0x00, 0x00
+.data1 	0x8d, 0x45, 0xd0, 0x50, 0xb9, 0x03, 0x00, 0x00
+.data1 	0x00, 0xe8, 0xc6, 0x04, 0x00, 0x00, 0x31, 0xf6
+.data1 	0x81, 0x7c, 0xb5, 0xd0, 0xce, 0x6a, 0x00, 0x00
+.data1 	0x74, 0x30, 0x8b, 0x15, 0x80, 0x15, 0x00, 0x00
+.data1 	0x89, 0x55, 0xe4, 0xc7, 0x45, 0xf0, 0x30, 0x15
+.data1 	0x00, 0x00, 0xc7, 0x45, 0xe8, 0xce, 0x8a, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xe0, 0x64, 0x00, 0x00, 0x00
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0xff, 0x74, 0xb5, 0xd0
+.data1 	0xe8, 0xb7, 0x02, 0x00, 0x00, 0x59, 0x59, 0x46
+.data1 	0xeb, 0xc6, 0xc7, 0x05, 0x80, 0x15, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x83, 0x7d, 0x08, 0x00
+.data1 	0x74, 0x1d, 0x8b, 0x45, 0x08, 0x0f, 0xbe, 0xc0
+.data1 	0x8b, 0x15, 0x80, 0x15, 0x00, 0x00, 0x89, 0xd1
+.data1 	0x41, 0x89, 0x0d, 0x80, 0x15, 0x00, 0x00, 0x89
+.data1 	0xd3, 0x88, 0x83, 0x30, 0x15, 0x00, 0x00, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x81
+.data1 	0x7d, 0x10, 0x00, 0x80, 0x00, 0x00, 0x74, 0x18
+.data1 	0xff, 0x75, 0x10, 0xff, 0x75, 0x0c, 0xff, 0x75
+.data1 	0x08, 0x68, 0x00, 0x05, 0x00, 0x00, 0xe8, 0x09
+.data1 	0xfc, 0xff, 0xff, 0x83, 0xc4, 0x10, 0xeb, 0x13
+.data1 	0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0x68, 0xf8
+.data1 	0x04, 0x00, 0x00, 0xe8, 0xf4, 0xfb, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x08
+.data1 	0x8b, 0x37, 0x85, 0xf6, 0x74, 0x1a, 0x8b, 0x55
+.data1 	0x0c, 0x39, 0x56, 0x04, 0x7f, 0x12, 0x8b, 0x16
+.data1 	0x89, 0x17, 0xc7, 0x46, 0x04, 0xff, 0xff, 0xff
+.data1 	0x7f, 0x56, 0xff, 0x56, 0x08, 0x59, 0xeb, 0xe0
+.data1 	0x83, 0x7d, 0x10, 0x00, 0x74, 0x1a, 0x83, 0x3f
+.data1 	0x00, 0x74, 0x0c, 0x8b, 0x17, 0x8b, 0x52, 0x04
+.data1 	0x8b, 0x45, 0x10, 0x89, 0x10, 0xeb, 0x09, 0x8b
+.data1 	0x45, 0x10, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x08, 0x56, 0x57, 0x8b, 0x7d, 0x0c, 0xc7
+.data1 	0x45, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x45
+.data1 	0x08, 0x83, 0x38, 0x00, 0x74, 0x08, 0x8b, 0x10
+.data1 	0x8b, 0x52, 0x04, 0x89, 0x55, 0xf8, 0x6a, 0x00
+.data1 	0x57, 0xff, 0x75, 0x08, 0xe8, 0x47, 0x00, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55, 0x10, 0x89
+.data1 	0x57, 0x04, 0x8b, 0x55, 0x14, 0x89, 0x57, 0x08
+.data1 	0x8b, 0x75, 0x08, 0x83, 0x3e, 0x00, 0x74, 0x0e
+.data1 	0x8b, 0x16, 0x8b, 0x4d, 0x10, 0x39, 0x4a, 0x04
+.data1 	0x7f, 0x04, 0x8b, 0x36, 0xeb, 0xed, 0x8b, 0x16
+.data1 	0x89, 0x17, 0x89, 0x3e, 0x83, 0x7d, 0x18, 0x00
+.data1 	0x74, 0x0d, 0x8b, 0x45, 0x08, 0x8b, 0x10, 0x8b
+.data1 	0x52, 0x04, 0x8b, 0x45, 0x18, 0x89, 0x10, 0x8b
+.data1 	0x45, 0xf8, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57
+.data1 	0x8b, 0x7d, 0x08, 0x83, 0x3f, 0x00, 0x74, 0x0a
+.data1 	0x8b, 0x17, 0x8b, 0x52, 0x04, 0x89, 0x55, 0xf4
+.data1 	0xeb, 0x07, 0xc7, 0x45, 0xf4, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x0c, 0xc7, 0x42, 0x04, 0xff
+.data1 	0xff, 0xff, 0x7f, 0x89, 0xfe, 0x83, 0x3e, 0x00
+.data1 	0x74, 0x14, 0x8b, 0x55, 0x0c, 0x39, 0x16, 0x75
+.data1 	0x09, 0x8b, 0x45, 0x0c, 0x8b, 0x10, 0x89, 0x16
+.data1 	0xeb, 0x04, 0x8b, 0x36, 0xeb, 0xe7, 0x83, 0x7d
+.data1 	0x10, 0x00, 0x74, 0x1a, 0x83, 0x3f, 0x00, 0x74
+.data1 	0x0c, 0x8b, 0x17, 0x8b, 0x52, 0x04, 0x8b, 0x45
+.data1 	0x10, 0x89, 0x10, 0xeb, 0x09, 0x8b, 0x45, 0x10
+.data1 	0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x45
+.data1 	0xf4, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x35, 0xd0, 0x05
+.data1 	0x00, 0x00, 0x4e, 0x78, 0x09, 0xff, 0x14, 0xb5
+.data1 	0x98, 0x15, 0x00, 0x00, 0xeb, 0xf4, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0xe8, 0xdf, 0xff, 0xff
+.data1 	0xff, 0x83, 0x3d, 0xd4, 0x05, 0x00, 0x00, 0x00
+.data1 	0x74, 0x06, 0xff, 0x15, 0xd4, 0x05, 0x00, 0x00
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x04, 0x00, 0x00, 0x00
+.data1 	0x59, 0xc9, 0xc3, 0x00, 0xe9, 0x2b, 0x01, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0xc7, 0x01, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x44, 0x24, 0x04
+.data1 	0x8b, 0x54, 0x24, 0x08, 0x03, 0x54, 0x24, 0x10
+.data1 	0x89, 0x10, 0x8b, 0x54, 0x24, 0x0c, 0x83, 0xd2
+.data1 	0x00, 0x89, 0x50, 0x04, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x89, 0xe1, 0x31, 0xc0, 0x8b, 0x51, 0x04, 0x2b
+.data1 	0x51, 0x0c, 0x8b, 0x51, 0x08, 0x1b, 0x51, 0x10
+.data1 	0x19, 0xc0, 0x8b, 0x51, 0x0c, 0x2b, 0x51, 0x04
+.data1 	0x8b, 0x51, 0x10, 0x1b, 0x51, 0x08, 0x15, 0x00
+.data1 	0x00, 0x00, 0x00, 0xc3, 0x89, 0xe1, 0xff, 0x71
+.data1 	0x10, 0xc7, 0x41, 0x10, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe8, 0xcd, 0xff, 0xff, 0xff, 0x8f, 0x41, 0x10
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x8b, 0x44, 0x24, 0x04
+.data1 	0x83, 0x7c, 0x24, 0x08, 0x00, 0x74, 0x05, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x31, 0xd2, 0x8b, 0x44, 0x24, 0x08, 0xf7, 0x74
+.data1 	0x24, 0x0c, 0x8b, 0x44, 0x24, 0x04, 0xf7, 0x74
+.data1 	0x24, 0x0c, 0xc3, 0x59, 0xe8, 0xe7, 0xff, 0xff
+.data1 	0xff, 0x89, 0xd0, 0xff, 0xe1, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x4c, 0x24, 0x04, 0x8b, 0x44, 0x24, 0x08
+.data1 	0xf7, 0x64, 0x24, 0x0c, 0x89, 0x01, 0x89, 0x51
+.data1 	0x04, 0x89, 0xc8, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x01
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x02, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x03
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0xb9
+.data1 	0x04, 0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x53, 0x8b, 0x5d, 0x08
+.data1 	0xb9, 0x08, 0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b
+.data1 	0x5d, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x7d, 0x08, 0x8b, 0x75, 0x0c, 0x8b
+.data1 	0x4d, 0x10, 0xe9, 0xff, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe0
+.data1 	0x8d, 0x45, 0xd8, 0x50, 0x6a, 0x01, 0x6a, 0x00
+.data1 	0xe8, 0x23, 0x01, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xba, 0xff, 0xff, 0xff, 0xff, 0x89, 0x55, 0xfc
+.data1 	0xff, 0xd2, 0xeb, 0xfe, 0x55, 0x89, 0xe5, 0x83
+.data1 	0x7d, 0x0c, 0x17, 0x76, 0x11, 0xc7, 0x05, 0xdc
+.data1 	0x05, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x11, 0x8b, 0x4d
+.data1 	0x0c, 0xba, 0x01, 0x00, 0x00, 0x00, 0xd3, 0xe2
+.data1 	0x8b, 0x45, 0x08, 0x09, 0x10, 0x31, 0xc0, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0x7d, 0x0c, 0x17
+.data1 	0x76, 0x11, 0xc7, 0x05, 0xdc, 0x05, 0x00, 0x00
+.data1 	0x16, 0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xeb, 0x13, 0x8b, 0x4d, 0x0c, 0xba, 0x01
+.data1 	0x00, 0x00, 0x00, 0xd3, 0xe2, 0xf7, 0xd2, 0x8b
+.data1 	0x45, 0x08, 0x21, 0x10, 0x31, 0xc0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x45, 0x08, 0xc7, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x31, 0xc0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x45, 0x08, 0xc7, 0x00
+.data1 	0xff, 0xff, 0xff, 0x00, 0x31, 0xc0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0x7d, 0x0c, 0x17, 0x76
+.data1 	0x11, 0xc7, 0x05, 0xdc, 0x05, 0x00, 0x00, 0x16
+.data1 	0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x1a, 0x8b, 0x4d, 0x0c, 0xba, 0x01, 0x00
+.data1 	0x00, 0x00, 0xd3, 0xe2, 0x8b, 0x45, 0x08, 0x85
+.data1 	0x10, 0x74, 0x07, 0xb8, 0x01, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x02, 0x31, 0xc0, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x08
+.data1 	0x8b, 0x75, 0x0c, 0x8b, 0x4d, 0x10, 0x89, 0xf8
+.data1 	0x29, 0xf0, 0x39, 0xc8, 0x72, 0x2f, 0xfc, 0x83
+.data1 	0xf9, 0x10, 0x72, 0x20, 0x89, 0xf0, 0x09, 0xf8
+.data1 	0xa8, 0x01, 0x75, 0x18, 0xa8, 0x02, 0x75, 0x0d
+.data1 	0x0f, 0xac, 0xc8, 0x02, 0xc1, 0xe9, 0x02, 0xf3
+.data1 	0xa5, 0x0f, 0xa4, 0xc1, 0x02, 0xd1, 0xe9, 0xf3
+.data1 	0x66, 0xa5, 0x11, 0xc9, 0xf3, 0xa4, 0x8b, 0x45
+.data1 	0x08, 0x5f, 0x5e, 0x5d, 0xc3, 0xfd, 0x8d, 0x74
+.data1 	0x0e, 0xff, 0x8d, 0x7c, 0x0f, 0xff, 0xf3, 0xa4
+.data1 	0xfc, 0xeb, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x75, 0x10
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x56, 0x04, 0x56, 0xff
+.data1 	0x75, 0x08, 0xe8, 0x55, 0xfe, 0xff, 0xff, 0x59
+.data1 	0x59, 0x89, 0xc7, 0x85, 0xff, 0x74, 0x03, 0x89
+.data1 	0x7e, 0x04, 0x83, 0x7e, 0x04, 0x00, 0x79, 0x12
+.data1 	0x8b, 0x56, 0x04, 0xf7, 0xda, 0x89, 0x15, 0xdc
+.data1 	0x05, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x03, 0x8b, 0x46, 0x04, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x89, 0xe3, 0x89, 0xf0
+.data1 	0x89, 0xfa, 0x8b, 0x7b, 0x04, 0x8b, 0x73, 0x08
+.data1 	0xf3, 0xa5, 0x89, 0xc6, 0x89, 0xd7, 0xc2, 0x08
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x13, 0x2b, 0x43
+.data1 	0x04, 0x3b, 0x43, 0x08, 0x77, 0x0c, 0xc1, 0xe0
+.data1 	0x02, 0x01, 0xc3, 0x8b, 0x5b, 0x0c, 0x85, 0xdb
+.data1 	0x75, 0x11, 0x89, 0xd3, 0x85, 0xdb, 0x75, 0x0b
+.data1 	0xb8, 0x14, 0x00, 0x00, 0x00, 0x50, 0xe9, 0x2d
+.data1 	0x00, 0x00, 0x00, 0xff, 0xe3, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x13, 0x8b, 0x4b, 0x04, 0x83, 0xc3, 0x08
+.data1 	0x49, 0x7c, 0x18, 0x3b, 0x03, 0x75, 0xf6, 0x8b
+.data1 	0x5b, 0x04, 0x85, 0xdb, 0x75, 0x0b, 0xb8, 0x14
+.data1 	0x00, 0x00, 0x00, 0x50, 0xe9, 0x07, 0x00, 0x00
+.data1 	0x00, 0xff, 0xe3, 0x89, 0xd3, 0xeb, 0xeb, 0x00
+.data1 	0xe8, 0x0f, 0x00, 0x00, 0x00, 0xe8, 0x02, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0x03, 0xfe, 0xff
+.data1 	0xff, 0x00, 0x00, 0x00, 0x31, 0xdb, 0x87, 0x1d
+.data1 	0xe0, 0x05, 0x00, 0x00, 0x85, 0xdb, 0x74, 0x05
+.data1 	0x50, 0xff, 0xd3, 0x58, 0xc3, 0x50, 0xe8, 0xe1
+.data1 	0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x65, 0x6e, 0x61
+.data1 	0x62, 0x6c, 0x65, 0x20, 0x49, 0x52, 0x51, 0x73
+.data1 	0x00, 0x00, 0x00, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x73, 0x65, 0x74
+.data1 	0x20, 0x49, 0x52, 0x51, 0x20, 0x70, 0x6f, 0x6c
+.data1 	0x69, 0x63, 0x79, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x73, 0x65, 0x74
+.data1 	0x20, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f
+.data1 	0x6e, 0x6f, 0x75, 0x73, 0x20, 0x61, 0x6c, 0x61
+.data1 	0x72, 0x6d, 0x2e, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x67, 0x65, 0x74
+.data1 	0x20, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x20
+.data1 	0x66, 0x72, 0x6f, 0x6d, 0x20, 0x63, 0x6c, 0x6f
+.data1 	0x63, 0x6b, 0x2e, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x73, 0x65, 0x74
+.data1 	0x20, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f
+.data1 	0x6e, 0x6f, 0x75, 0x73, 0x20, 0x61, 0x6c, 0x61
+.data1 	0x72, 0x6d, 0x2e, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x67, 0x65, 0x74
+.data1 	0x20, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x20
+.data1 	0x66, 0x72, 0x6f, 0x6d, 0x20, 0x63, 0x6c, 0x6f
+.data1 	0x63, 0x6b, 0x2e, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x00, 0x00, 0x53, 0x79, 0x73, 0x5f
+.data1 	0x76, 0x69, 0x72, 0x63, 0x6f, 0x70, 0x79, 0x20
+.data1 	0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x00, 0x00
+.data1 	0x46, 0x4c, 0x4f, 0x50, 0x50, 0x59, 0x00, 0x00
+.data1 	0x53, 0x79, 0x73, 0x5f, 0x76, 0x69, 0x72, 0x63
+.data1 	0x6f, 0x70, 0x79, 0x20, 0x66, 0x61, 0x69, 0x6c
+.data1 	0x65, 0x64, 0x00, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x00, 0x00, 0x53, 0x79, 0x73, 0x5f
+.data1 	0x6f, 0x75, 0x74, 0x62, 0x20, 0x66, 0x61, 0x69
+.data1 	0x6c, 0x65, 0x64, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x00, 0x00, 0x53, 0x79, 0x73, 0x5f
+.data1 	0x76, 0x69, 0x72, 0x63, 0x6f, 0x70, 0x79, 0x20
+.data1 	0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x00, 0x00
+.data1 	0x46, 0x4c, 0x4f, 0x50, 0x50, 0x59, 0x00, 0x00
+.data1 	0x53, 0x79, 0x73, 0x5f, 0x76, 0x6f, 0x75, 0x74
+.data1 	0x62, 0x20, 0x69, 0x6e, 0x20, 0x64, 0x6d, 0x61
+.data1 	0x5f, 0x73, 0x65, 0x74, 0x75, 0x70, 0x28, 0x29
+.data1 	0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x00
+.data1 	0x46, 0x4c, 0x4f, 0x50, 0x50, 0x59, 0x00, 0x00
+.data1 	0x44, 0x4d, 0x41, 0x20, 0x64, 0x65, 0x6e, 0x69
+.data1 	0x65, 0x64, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75
+.data1 	0x73, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65
+.data1 	0x73, 0x73, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f
+.data1 	0x66, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00
+.data1 	0x46, 0x4c, 0x4f, 0x50, 0x50, 0x59, 0x00, 0x00
+.data1 	0x53, 0x79, 0x73, 0x5f, 0x6f, 0x75, 0x74, 0x62
+.data1 	0x20, 0x69, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x72
+.data1 	0x74, 0x5f, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x28
+.data1 	0x29, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x00, 0x00, 0x53, 0x79, 0x73, 0x5f
+.data1 	0x6f, 0x75, 0x74, 0x62, 0x20, 0x69, 0x6e, 0x20
+.data1 	0x73, 0x74, 0x6f, 0x70, 0x5f, 0x6d, 0x6f, 0x74
+.data1 	0x6f, 0x72, 0x28, 0x29, 0x20, 0x66, 0x61, 0x69
+.data1 	0x6c, 0x65, 0x64, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x00, 0x00, 0x53, 0x79, 0x73, 0x5f
+.data1 	0x6f, 0x75, 0x74, 0x62, 0x20, 0x69, 0x6e, 0x20
+.data1 	0x66, 0x6c, 0x6f, 0x70, 0x70, 0x79, 0x5f, 0x73
+.data1 	0x74, 0x6f, 0x70, 0x28, 0x29, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x46, 0x4c, 0x4f, 0x50, 0x50, 0x59, 0x00, 0x00
+.data1 	0x25, 0x73, 0x3a, 0x20, 0x64, 0x69, 0x73, 0x6b
+.data1 	0x65, 0x74, 0x74, 0x65, 0x20, 0x69, 0x73, 0x20
+.data1 	0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x70, 0x72
+.data1 	0x6f, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x2e
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x64, 0x69, 0x73, 0x6b, 0x20, 0x69, 0x6e, 0x74
+.data1 	0x65, 0x72, 0x72, 0x75, 0x70, 0x74, 0x20, 0x74
+.data1 	0x69, 0x6d, 0x65, 0x64, 0x20, 0x6f, 0x75, 0x74
+.data1 	0x2e, 0x0a, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x65, 0x6e, 0x61
+.data1 	0x62, 0x6c, 0x65, 0x20, 0x49, 0x52, 0x51, 0x73
+.data1 	0x00, 0x00, 0x00, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x00, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x3a, 0x20, 0x77, 0x61, 0x72, 0x6e
+.data1 	0x69, 0x6e, 0x67, 0x2c, 0x20, 0x67, 0x65, 0x74
+.data1 	0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x66
+.data1 	0x61, 0x69, 0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x65, 0x6e, 0x61
+.data1 	0x62, 0x6c, 0x65, 0x20, 0x49, 0x52, 0x51, 0x73
+.data1 	0x00, 0x00, 0x00, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x00, 0x00, 0x53, 0x79, 0x73, 0x5f
+.data1 	0x69, 0x6e, 0x62, 0x20, 0x69, 0x6e, 0x20, 0x66
+.data1 	0x64, 0x63, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c
+.data1 	0x74, 0x73, 0x28, 0x29, 0x20, 0x66, 0x61, 0x69
+.data1 	0x6c, 0x65, 0x64, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x00, 0x00, 0x53, 0x79, 0x73, 0x5f
+.data1 	0x69, 0x6e, 0x62, 0x20, 0x69, 0x6e, 0x20, 0x66
+.data1 	0x64, 0x63, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c
+.data1 	0x74, 0x73, 0x28, 0x29, 0x20, 0x66, 0x61, 0x69
+.data1 	0x6c, 0x65, 0x64, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x00, 0x00, 0x53, 0x79, 0x73, 0x5f
+.data1 	0x6f, 0x75, 0x74, 0x62, 0x20, 0x69, 0x6e, 0x20
+.data1 	0x66, 0x64, 0x63, 0x5f, 0x6f, 0x75, 0x74, 0x28
+.data1 	0x29, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x46, 0x4c, 0x4f, 0x50
+.data1 	0x50, 0x59, 0x00, 0x00, 0x53, 0x79, 0x73, 0x5f
+.data1 	0x69, 0x6e, 0x62, 0x20, 0x69, 0x6e, 0x20, 0x66
+.data1 	0x64, 0x63, 0x5f, 0x6f, 0x75, 0x74, 0x28, 0x29
+.data1 	0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x00
+.data1 	0x46, 0x4c, 0x4f, 0x50, 0x50, 0x59, 0x00, 0x00
+.data1 	0x46, 0x4c, 0x4f, 0x50, 0x50, 0x59, 0x3a, 0x20
+.data1 	0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x2c
+.data1 	0x20, 0x67, 0x65, 0x74, 0x75, 0x70, 0x74, 0x69
+.data1 	0x6d, 0x65, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65
+.data1 	0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x53, 0x79, 0x73, 0x5f, 0x76, 0x6f, 0x75, 0x74
+.data1 	0x62, 0x20, 0x69, 0x6e, 0x20, 0x66, 0x5f, 0x72
+.data1 	0x65, 0x73, 0x65, 0x74, 0x28, 0x29, 0x20, 0x66
+.data1 	0x61, 0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x46, 0x4c, 0x4f, 0x50, 0x50, 0x59, 0x00, 0x00
+.data1 	0x14, 0x16, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00
+.data1 	0x00, 0x04, 0x00, 0x00, 0x87, 0x15, 0x00, 0x00
+.data1 	0x03, 0x04, 0x00, 0x00, 0xa9, 0x15, 0x00, 0x00
+.data1 	0x04, 0x04, 0x00, 0x00, 0xa9, 0x15, 0x00, 0x00
+.data1 	0x05, 0x04, 0x00, 0x00, 0x76, 0x15, 0x00, 0x00
+.data1 	0x06, 0x04, 0x00, 0x00, 0x54, 0x15, 0x00, 0x00
+.data1 	0x07, 0x04, 0x00, 0x00, 0x65, 0x15, 0x00, 0x00
+.data1 	0x08, 0x04, 0x00, 0x00, 0xbc, 0x15, 0x00, 0x00
+.data1 	0x09, 0x04, 0x00, 0x00, 0xbc, 0x15, 0x00, 0x00
+.data1 	0x0c, 0x04, 0x00, 0x00, 0x98, 0x15, 0x00, 0x00
+.data1 	0x01, 0x10, 0x00, 0x00, 0xf7, 0x15, 0x00, 0x00
+.data1 	0x02, 0x10, 0x00, 0x00, 0xe8, 0x15, 0x00, 0x00
+.data1 	0x03, 0x10, 0x00, 0x00, 0xcf, 0x15, 0x00, 0x00
+.data1 	0x04, 0x10, 0x00, 0x00, 0xe8, 0x15, 0x00, 0x00
+.data1 	0x06, 0x10, 0x00, 0x00, 0x06, 0x16, 0x00, 0x00
+.data1 	0x62, 0x61, 0x64, 0x20, 0x49, 0x2f, 0x4f, 0x20
+.data1 	0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x62
+.data1 	0x79, 0x00, 0x00, 0x00, 0x4d, 0x18, 0x00, 0x00
+.data1 	0x05, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x46, 0x18, 0x00, 0x00, 0x3b, 0x18, 0x00, 0x00
+.data1 	0x42, 0x18, 0x00, 0x00, 0x58, 0x1a, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x07, 0x1a, 0x00, 0x00, 0x0d, 0x1a, 0x00, 0x00
+.data1 	0x1c, 0x1a, 0x00, 0x00, 0x50, 0x61, 0x6e, 0x69
+.data1 	0x63, 0x20, 0x69, 0x6e, 0x20, 0x25, 0x73, 0x3a
+.data1 	0x20, 0x25, 0x73, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x50, 0x61, 0x6e, 0x69, 0x63, 0x20, 0x69, 0x6e
+.data1 	0x20, 0x25, 0x73, 0x3a, 0x20, 0x25, 0x73, 0x3a
+.data1 	0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x2e, 0x23, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00
+.data1 	0x25, 0x00, 0x00, 0x00, 0x5c, 0x22, 0x00, 0x00
+.data1 	0x58, 0x00, 0x00, 0x00, 0xe5, 0x21, 0x00, 0x00
+.data1 	0x63, 0x00, 0x00, 0x00, 0x40, 0x22, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0xb1, 0x21, 0x00, 0x00
+.data1 	0x6f, 0x00, 0x00, 0x00, 0xdc, 0x21, 0x00, 0x00
+.data1 	0x70, 0x00, 0x00, 0x00, 0xe5, 0x21, 0x00, 0x00
+.data1 	0x73, 0x00, 0x00, 0x00, 0x6e, 0x22, 0x00, 0x00
+.data1 	0x75, 0x00, 0x00, 0x00, 0xf3, 0x21, 0x00, 0x00
+.data1 	0x78, 0x00, 0x00, 0x00, 0xec, 0x21, 0x00, 0x00
+.data1 	0x25, 0x73, 0x3a, 0x20, 0x25, 0x73, 0x0a, 0x00
+.data1 	0x25, 0x73, 0x3a, 0x20, 0x25, 0x73, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x88, 0x15, 0x00, 0x00
+.data1 	0x09, 0x28, 0x01, 0x24, 0x02, 0x1e, 0x2a, 0xdf
+.data1 	0x0f, 0x50, 0x01, 0x0e, 0x00, 0x1e, 0x1b, 0xdf
+.data1 	0x09, 0x28, 0x02, 0x12, 0x02, 0x1e, 0x2a, 0xdf
+.data1 	0x09, 0x50, 0x01, 0x24, 0x02, 0x2d, 0x2a, 0xdf
+.data1 	0x09, 0x28, 0x02, 0x12, 0x01, 0x1e, 0x23, 0xdf
+.data1 	0x09, 0x50, 0x01, 0x24, 0x01, 0x1e, 0x23, 0xdf
+.data1 	0x12, 0x50, 0x01, 0x11, 0x00, 0x2d, 0x1b, 0xcf
+.data1 	0x06, 0x48, 0x01, 0x32, 0x03, 0x4c, 0x04, 0x32
+.data1 	0x05, 0x32, 0x02, 0x0c, 0x01, 0x03, 0x00, 0x00
+.data1 	0x28, 0x13, 0x00, 0x00, 0x36, 0x18, 0x00, 0x00
+.data1 	0x8a, 0x18, 0x00, 0x00, 0x28, 0x02, 0x00, 0x00
+.data1 	0x59, 0x03, 0x00, 0x00, 0x1c, 0x03, 0x00, 0x00
+.data1 	0xf1, 0x14, 0x00, 0x00, 0x48, 0x0a, 0x00, 0x00
+.data1 	0x12, 0x01, 0x00, 0x00, 0x7c, 0x18, 0x00, 0x00
+.data1 	0x83, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x66, 0x64, 0x30, 0x00
+.data1 	0x6e, 0x6f, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33
+.data1 	0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42
+.data1 	0x43, 0x44, 0x45, 0x46, 0x00, 0x00, 0x00, 0x00
+.data1 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
+.data1 	0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
+.data1 	0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
+.data1 	0x04, 0x00, 0x00, 0x00, 0xce, 0x6a, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x53, 0x53, 0x53, 0x53, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x03, 0x20, 0x10, 0x20, 0x00, 0x00, 0x00
+.data1 	0x90, 0x18, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00
+.data1 	0x94, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xf4, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0xed, 0x8b, 0x04, 0x24, 0x8d, 0x54, 0x24
+.data1 	0x04, 0x8d, 0x4c, 0x84, 0x08, 0xbb, 0x6c, 0x08
+.data1 	0x00, 0x00, 0x81, 0xfb, 0x60, 0x0a, 0x00, 0x00
+.data1 	0x73, 0x13, 0xf6, 0xc3, 0x03, 0x75, 0x0e, 0x81
+.data1 	0x3b, 0x53, 0x53, 0x53, 0x53, 0x75, 0x06, 0x89
+.data1 	0x1d, 0x60, 0x08, 0x00, 0x00, 0x8b, 0x1d, 0x60
+.data1 	0x08, 0x00, 0x00, 0x89, 0x0b, 0x51, 0x52, 0x50
+.data1 	0x0f, 0x01, 0xe0, 0xa8, 0x04, 0x0f, 0x94, 0x05
+.data1 	0x6c, 0x0a, 0x00, 0x00, 0xe8, 0x07, 0x00, 0x00
+.data1 	0x00, 0x50, 0xe8, 0x0a, 0x03, 0x00, 0x00, 0xf4
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x18, 0x56, 0x57
+.data1 	0x83, 0x7d, 0x08, 0x02, 0x74, 0x19, 0x68, 0x14
+.data1 	0x01, 0x00, 0x00, 0x68, 0xa4, 0x08, 0x00, 0x00
+.data1 	0xe8, 0x33, 0x03, 0x00, 0x00, 0x59, 0x59, 0x6a
+.data1 	0x01, 0xe8, 0xe3, 0x02, 0x00, 0x00, 0x59, 0x8b
+.data1 	0x55, 0x0c, 0x8b, 0x7a, 0x04, 0x6a, 0x00, 0x57
+.data1 	0xe8, 0x53, 0x03, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0x45, 0xec, 0x85, 0xc0, 0x79, 0x28, 0xff, 0x35
+.data1 	0x70, 0x08, 0x00, 0x00, 0xe8, 0xe3, 0x02, 0x00
+.data1 	0x00, 0x59, 0x50, 0x57, 0x68, 0xf8, 0x00, 0x00
+.data1 	0x00, 0x68, 0xa4, 0x08, 0x00, 0x00, 0xe8, 0xf5
+.data1 	0x02, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x6a, 0x01
+.data1 	0xe8, 0xa4, 0x02, 0x00, 0x00, 0x59, 0xc7, 0x05
+.data1 	0x70, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xff, 0x75, 0xec, 0xe8, 0xbb, 0x01, 0x00, 0x00
+.data1 	0x59, 0x89, 0x45, 0xf8, 0x83, 0x3d, 0x70, 0x08
+.data1 	0x00, 0x00, 0x00, 0x74, 0x28, 0xff, 0x35, 0x70
+.data1 	0x08, 0x00, 0x00, 0xe8, 0x9c, 0x02, 0x00, 0x00
+.data1 	0x59, 0x50, 0x57, 0x68, 0xd8, 0x00, 0x00, 0x00
+.data1 	0x68, 0xa4, 0x08, 0x00, 0x00, 0xe8, 0xae, 0x02
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x10, 0x6a, 0x01, 0xe8
+.data1 	0x5d, 0x02, 0x00, 0x00, 0x59, 0x6a, 0x00, 0x6a
+.data1 	0x00, 0xff, 0x75, 0xec, 0xe8, 0xc7, 0x02, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x74, 0x28
+.data1 	0xff, 0x35, 0x70, 0x08, 0x00, 0x00, 0xe8, 0x61
+.data1 	0x02, 0x00, 0x00, 0x59, 0x50, 0x57, 0x68, 0xb8
+.data1 	0x00, 0x00, 0x00, 0x68, 0xa4, 0x08, 0x00, 0x00
+.data1 	0xe8, 0x73, 0x02, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x6a, 0x01, 0xe8, 0x22, 0x02, 0x00, 0x00, 0x59
+.data1 	0x6a, 0x02, 0x68, 0xac, 0x00, 0x00, 0x00, 0xe8
+.data1 	0x94, 0x02, 0x00, 0x00, 0x59, 0x59, 0x89, 0x45
+.data1 	0xe8, 0x85, 0xc0, 0x79, 0x2c, 0xff, 0x35, 0x70
+.data1 	0x08, 0x00, 0x00, 0xe8, 0x24, 0x02, 0x00, 0x00
+.data1 	0x59, 0x50, 0x68, 0x84, 0x00, 0x00, 0x00, 0x68
+.data1 	0x90, 0x00, 0x00, 0x00, 0x68, 0xa4, 0x08, 0x00
+.data1 	0x00, 0xe8, 0x32, 0x02, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x10, 0x6a, 0x01, 0xe8, 0xe1, 0x01, 0x00, 0x00
+.data1 	0x59, 0x8d, 0x45, 0xf8, 0x50, 0x68, 0x03, 0x6d
+.data1 	0x04, 0x40, 0xff, 0x75, 0xe8, 0xe8, 0x3e, 0x02
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0xc6, 0x85
+.data1 	0xf6, 0x74, 0x2f, 0xff, 0x35, 0x70, 0x08, 0x00
+.data1 	0x00, 0xe8, 0xde, 0x01, 0x00, 0x00, 0x59, 0x50
+.data1 	0x68, 0x54, 0x00, 0x00, 0x00, 0xff, 0x75, 0xf8
+.data1 	0x68, 0x60, 0x00, 0x00, 0x00, 0x68, 0xa4, 0x08
+.data1 	0x00, 0x00, 0xe8, 0xe9, 0x01, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x14, 0x6a, 0x01, 0xe8, 0x98, 0x01, 0x00
+.data1 	0x00, 0x59, 0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xf8, 0x39, 0x55, 0xfc, 0x0f
+.data1 	0x83, 0xa2, 0x00, 0x00, 0x00, 0x68, 0x00, 0x28
+.data1 	0x00, 0x00, 0x68, 0x74, 0x0a, 0x00, 0x00, 0xff
+.data1 	0x75, 0xec, 0xe8, 0xf9, 0x01, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0xc6, 0x85, 0xf6, 0x7f, 0x33
+.data1 	0x85, 0xf6, 0x75, 0x07, 0xb8, 0x2c, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x0c, 0xff, 0x35, 0x70, 0x08, 0x00
+.data1 	0x00, 0xe8, 0x76, 0x01, 0x00, 0x00, 0x59, 0x50
+.data1 	0x57, 0x68, 0x3c, 0x00, 0x00, 0x00, 0x68, 0xa4
+.data1 	0x08, 0x00, 0x00, 0xe8, 0x88, 0x01, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0x6a, 0x01, 0xe8, 0x37, 0x01
+.data1 	0x00, 0x00, 0x59, 0x56, 0x68, 0x74, 0x0a, 0x00
+.data1 	0x00, 0xff, 0x75, 0xe8, 0xe8, 0xb7, 0x01, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45, 0xf0, 0x39
+.data1 	0xf0, 0x74, 0x34, 0x83, 0x7d, 0xf0, 0x00, 0x78
+.data1 	0x07, 0xb8, 0x04, 0x00, 0x00, 0x00, 0xeb, 0x0c
+.data1 	0xff, 0x35, 0x70, 0x08, 0x00, 0x00, 0xe8, 0x29
+.data1 	0x01, 0x00, 0x00, 0x59, 0x50, 0x68, 0x10, 0x00
+.data1 	0x00, 0x00, 0x68, 0xa4, 0x08, 0x00, 0x00, 0xe8
+.data1 	0x3c, 0x01, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x6a
+.data1 	0x01, 0xe8, 0xeb, 0x00, 0x00, 0x00, 0x59, 0x01
+.data1 	0x75, 0xfc, 0xe9, 0x52, 0xff, 0xff, 0xff, 0x6a
+.data1 	0x00, 0xe8, 0xdb, 0x00, 0x00, 0x00, 0x59, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x14, 0x56, 0x57, 0x31, 0xff, 0xc7, 0x45, 0xec
+.data1 	0xff, 0xff, 0xff, 0xff, 0x8b, 0x55, 0xec, 0x29
+.data1 	0xfa, 0xd1, 0xea, 0x89, 0xfe, 0x01, 0xd6, 0x39
+.data1 	0xfe, 0x0f, 0x86, 0x8f, 0x00, 0x00, 0x00, 0x6a
+.data1 	0x00, 0x56, 0xff, 0x75, 0x08, 0xe8, 0x1e, 0x01
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x39, 0xf0, 0x74
+.data1 	0x28, 0xff, 0x35, 0x70, 0x08, 0x00, 0x00, 0xe8
+.data1 	0xb8, 0x00, 0x00, 0x00, 0x59, 0x50, 0x56, 0x68
+.data1 	0x54, 0x01, 0x00, 0x00, 0x68, 0xa4, 0x08, 0x00
+.data1 	0x00, 0xe8, 0xca, 0x00, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x10, 0x6a, 0x01, 0xe8, 0x79, 0x00, 0x00, 0x00
+.data1 	0x59, 0x6a, 0x01, 0x8d, 0x45, 0xff, 0x50, 0xff
+.data1 	0x75, 0x08, 0xe8, 0xf1, 0x00, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0x45, 0xf8, 0x85, 0xc0, 0x79
+.data1 	0x28, 0xff, 0x35, 0x70, 0x08, 0x00, 0x00, 0xe8
+.data1 	0x78, 0x00, 0x00, 0x00, 0x59, 0x50, 0x56, 0x68
+.data1 	0x30, 0x01, 0x00, 0x00, 0x68, 0xa4, 0x08, 0x00
+.data1 	0x00, 0xe8, 0x8a, 0x00, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x10, 0x6a, 0x01, 0xe8, 0x39, 0x00, 0x00, 0x00
+.data1 	0x59, 0x83, 0x7d, 0xf8, 0x00, 0x7e, 0x07, 0x89
+.data1 	0xf7, 0xe9, 0x66, 0xff, 0xff, 0xff, 0x89, 0x75
+.data1 	0xec, 0xe9, 0x5e, 0xff, 0xff, 0xff, 0x8b, 0x45
+.data1 	0xec, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x35, 0x64, 0x08
+.data1 	0x00, 0x00, 0x4e, 0x78, 0x09, 0xff, 0x14, 0xb5
+.data1 	0x74, 0x32, 0x00, 0x00, 0xeb, 0xf4, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0xe8, 0xdf, 0xff, 0xff
+.data1 	0xff, 0x83, 0x3d, 0x68, 0x08, 0x00, 0x00, 0x00
+.data1 	0x74, 0x06, 0xff, 0x15, 0x68, 0x08, 0x00, 0x00
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x48, 0x00, 0x00, 0x00
+.data1 	0x59, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x75, 0x08, 0x85, 0xf6, 0x78, 0x08, 0x39
+.data1 	0x35, 0x4c, 0x0a, 0x00, 0x00, 0x7f, 0x07, 0xb8
+.data1 	0x70, 0x01, 0x00, 0x00, 0xeb, 0x07, 0x8b, 0x04
+.data1 	0xb5, 0x1c, 0x09, 0x00, 0x00, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x8d, 0x55
+.data1 	0x10, 0x89, 0x55, 0xfc, 0xff, 0x75, 0x08, 0xff
+.data1 	0x75, 0xfc, 0xff, 0x75, 0x0c, 0xe8, 0x7c, 0x03
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00
+.data1 	0xe9, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x1f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe0, 0x8d, 0x45, 0xd8, 0x50
+.data1 	0x6a, 0x01, 0x6a, 0x00, 0xe8, 0xa7, 0x10, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xba, 0xff, 0xff, 0xff
+.data1 	0xff, 0x89, 0x55, 0xfc, 0xff, 0xd2, 0xeb, 0xfe
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xec, 0x8b, 0x55, 0x10, 0x89, 0x55, 0xf8
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x36, 0x6a, 0x01
+.data1 	0xe8, 0x73, 0x10, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf0, 0x8b, 0x55
+.data1 	0x10, 0x89, 0x55, 0xe8, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x6a, 0x13, 0x6a, 0x01, 0xe8, 0x47, 0x10, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x79, 0x07
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x03, 0x8b
+.data1 	0x45, 0xf0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x56, 0x8d, 0x75, 0x10, 0x8b, 0x55
+.data1 	0x0c, 0xf6, 0xc2, 0x40, 0x74, 0x2a, 0xff, 0x75
+.data1 	0x08, 0xe8, 0xf6, 0x0b, 0x00, 0x00, 0x59, 0x05
+.data1 	0x01, 0x00, 0x00, 0x00, 0x89, 0x45, 0xe0, 0x8b
+.data1 	0x55, 0x0c, 0x89, 0x55, 0xe4, 0x8d, 0x56, 0x04
+.data1 	0x89, 0xd6, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xe8
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xec, 0xeb, 0x14
+.data1 	0x8d, 0x45, 0xd8, 0x50, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xb0, 0x0f, 0x00, 0x00, 0x59, 0x59, 0x8b, 0x55
+.data1 	0x0c, 0x89, 0x55, 0xe4, 0x8d, 0x45, 0xd8, 0x50
+.data1 	0x6a, 0x05, 0x6a, 0x01, 0xe8, 0xd7, 0x0f, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x5e, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x10, 0x89
+.data1 	0x55, 0xe8, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf0
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x03, 0x6a, 0x01
+.data1 	0xe8, 0xab, 0x0f, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4
+.data1 	0x8b, 0x55, 0x10, 0x89, 0x55, 0xe8, 0x8b, 0x55
+.data1 	0x0c, 0x89, 0x55, 0xf0, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x6a, 0x04, 0x6a, 0x01, 0xe8, 0x7f, 0x0f, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x56, 0x57
+.data1 	0x8b, 0x75, 0x08, 0x80, 0x3e, 0x2a, 0x75, 0x18
+.data1 	0x8b, 0x45, 0x10, 0x8b, 0x10, 0x83, 0xc2, 0x04
+.data1 	0x8b, 0x45, 0x10, 0x89, 0x10, 0x8b, 0x52, 0xfc
+.data1 	0x8b, 0x45, 0x0c, 0x89, 0x10, 0x46, 0xeb, 0x25
+.data1 	0x31, 0xff, 0x0f, 0xbe, 0x06, 0x2d, 0x30, 0x00
+.data1 	0x00, 0x00, 0x89, 0x45, 0xf8, 0x78, 0x11, 0x83
+.data1 	0x7d, 0xf8, 0x09, 0x7f, 0x0b, 0x6b, 0xdf, 0x0a
+.data1 	0x8b, 0x7d, 0xf8, 0x01, 0xdf, 0x46, 0xeb, 0xe2
+.data1 	0x8b, 0x45, 0x0c, 0x89, 0x38, 0x89, 0xf0, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x10, 0x56, 0x57, 0x8b, 0x75, 0x10, 0x8b, 0x7d
+.data1 	0x08, 0x89, 0x75, 0xf4, 0xe9, 0x80, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7d, 0x1c, 0x00, 0x74, 0x18, 0x8b
+.data1 	0x17, 0x83, 0xc2, 0x04, 0x89, 0x17, 0x8b, 0x42
+.data1 	0xfc, 0x0f, 0xbf, 0xc0, 0x0f, 0xbf, 0xc0, 0x89
+.data1 	0x45, 0xfc, 0xe9, 0x76, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x17, 0x83, 0xc2, 0x04, 0x89, 0x17, 0xb9, 0xff
+.data1 	0xff, 0x00, 0x00, 0x23, 0x4a, 0xfc, 0x89, 0x4d
+.data1 	0xf8, 0xe9, 0x5f, 0x00, 0x00, 0x00, 0x83, 0x7d
+.data1 	0x1c, 0x00, 0x74, 0x12, 0x8b, 0x17, 0x83, 0xc2
+.data1 	0x04, 0x89, 0x17, 0x8b, 0x52, 0xfc, 0x89, 0x55
+.data1 	0xfc, 0xe9, 0x47, 0x00, 0x00, 0x00, 0x8b, 0x17
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x17, 0x8b, 0x52, 0xfc
+.data1 	0x89, 0x55, 0xf8, 0xeb, 0x38, 0x83, 0x7d, 0x1c
+.data1 	0x00, 0x74, 0x0f, 0x8b, 0x17, 0x83, 0xc2, 0x04
+.data1 	0x89, 0x17, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xfc
+.data1 	0xeb, 0x23, 0x8b, 0x17, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x17, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xf8, 0xeb
+.data1 	0x14, 0xba, 0x60, 0x00, 0x00, 0x00, 0x23, 0x55
+.data1 	0x0c, 0xbb, 0xf8, 0x06, 0x00, 0x00, 0x89, 0xd0
+.data1 	0xe9, 0x03, 0x12, 0x00, 0x00, 0x83, 0x7d, 0x1c
+.data1 	0x00, 0x74, 0x2f, 0x83, 0x7d, 0xfc, 0x00, 0x79
+.data1 	0x09, 0xc6, 0x06, 0x2d, 0x46, 0xf7, 0x5d, 0xfc
+.data1 	0xeb, 0x1a, 0x8b, 0x55, 0x0c, 0xf6, 0xc2, 0x02
+.data1 	0x74, 0x06, 0xc6, 0x06, 0x2b, 0x46, 0xeb, 0x0c
+.data1 	0x8b, 0x55, 0x0c, 0xf6, 0xc2, 0x04, 0x74, 0x04
+.data1 	0xc6, 0x06, 0x20, 0x46, 0x8b, 0x55, 0xfc, 0x89
+.data1 	0x55, 0xf8, 0x8b, 0x55, 0x0c, 0xf6, 0xc2, 0x08
+.data1 	0x74, 0x0a, 0x80, 0x7d, 0x14, 0x6f, 0x75, 0x04
+.data1 	0xc6, 0x06, 0x30, 0x46, 0x83, 0x7d, 0xf8, 0x00
+.data1 	0x75, 0x11, 0x83, 0x7d, 0x18, 0x00, 0x0f, 0x85
+.data1 	0x60, 0x00, 0x00, 0x00, 0x89, 0xf0, 0xe9, 0x9f
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0xf6, 0xc2
+.data1 	0x08, 0x74, 0x0c, 0x80, 0x7d, 0x14, 0x78, 0x74
+.data1 	0x0c, 0x80, 0x7d, 0x14, 0x58, 0x74, 0x06, 0x80
+.data1 	0x7d, 0x14, 0x70, 0x75, 0x3f, 0xc6, 0x06, 0x30
+.data1 	0x46, 0x80, 0x7d, 0x14, 0x58, 0x75, 0x07, 0xb8
+.data1 	0x58, 0x00, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0x78
+.data1 	0x00, 0x00, 0x00, 0x88, 0x06, 0x46, 0xeb, 0x24
+.data1 	0xc7, 0x45, 0xf0, 0x02, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x29, 0xc7, 0x45, 0xf0, 0x08, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x20, 0xc7, 0x45, 0xf0, 0x0a, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x17, 0xc7, 0x45, 0xf0, 0x10, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x0e, 0x0f, 0xbe, 0x45, 0x14
+.data1 	0xbb, 0x10, 0x07, 0x00, 0x00, 0xe9, 0x3e, 0x11
+.data1 	0x00, 0x00, 0xff, 0x75, 0x18, 0x56, 0xff, 0x75
+.data1 	0xf0, 0xff, 0x75, 0xf8, 0xe8, 0x2b, 0x09, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x10, 0x89, 0xc6, 0x80, 0x7d
+.data1 	0x14, 0x58, 0x75, 0x1c, 0x39, 0x75, 0xf4, 0x74
+.data1 	0x17, 0x8b, 0x55, 0xf4, 0x0f, 0xbe, 0x02, 0x50
+.data1 	0xe8, 0xa7, 0x0c, 0x00, 0x00, 0x59, 0x8b, 0x55
+.data1 	0xf4, 0x88, 0x02, 0xff, 0x45, 0xf4, 0xeb, 0xe4
+.data1 	0x89, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x81, 0xec, 0x34, 0x04, 0x00, 0x00, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x10, 0xc7, 0x45, 0xd8, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x45, 0x08, 0xff, 0x45
+.data1 	0x08, 0x0f, 0xbe, 0x00, 0x89, 0x45, 0xf0, 0x85
+.data1 	0xc0, 0x0f, 0x84, 0x0b, 0x06, 0x00, 0x00, 0x83
+.data1 	0x7d, 0xf0, 0x25, 0x0f, 0x84, 0x4d, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x16, 0x4a, 0x89, 0x16, 0x78, 0x13
+.data1 	0x8b, 0x55, 0xf0, 0x0f, 0xb6, 0xca, 0x8b, 0x46
+.data1 	0x14, 0x83, 0x46, 0x14, 0x01, 0x88, 0x08, 0x89
+.data1 	0xc8, 0xeb, 0x0b, 0x56, 0xff, 0x75, 0xf0, 0xe8
+.data1 	0x24, 0x06, 0x00, 0x00, 0x59, 0x59, 0x3d, 0xff
+.data1 	0xff, 0xff, 0xff, 0x75, 0x1c, 0x83, 0x7d, 0xd8
+.data1 	0x00, 0x74, 0x0c, 0x8b, 0x55, 0xd8, 0xf7, 0xda
+.data1 	0x89, 0xd0, 0xe9, 0xc6, 0x05, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe9, 0xbc, 0x05, 0x00
+.data1 	0x00, 0xff, 0x45, 0xd8, 0xeb, 0x95, 0x31, 0xff
+.data1 	0xeb, 0x21, 0x83, 0xcf, 0x01, 0xeb, 0x2c, 0x83
+.data1 	0xcf, 0x02, 0xeb, 0x27, 0x83, 0xcf, 0x04, 0xeb
+.data1 	0x22, 0x83, 0xcf, 0x08, 0xeb, 0x1d, 0x83, 0xcf
+.data1 	0x10, 0xeb, 0x18, 0x81, 0xcf, 0x00, 0x10, 0x00
+.data1 	0x00, 0xeb, 0x13, 0x8b, 0x55, 0x08, 0x0f, 0xbe
+.data1 	0x02, 0xbb, 0x58, 0x07, 0x00, 0x00, 0xe9, 0x4d
+.data1 	0x10, 0x00, 0x00, 0xff, 0x45, 0x08, 0xf7, 0xc7
+.data1 	0x00, 0x10, 0x00, 0x00, 0x74, 0xe5, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xd4, 0x8d, 0x45, 0x0c, 0x50
+.data1 	0x8d, 0x45, 0xec, 0x50, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x2c, 0xfd, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0x45, 0x08, 0x39, 0x45, 0xd4, 0x74, 0x06, 0x81
+.data1 	0xcf, 0x00, 0x01, 0x00, 0x00, 0x8b, 0x55, 0x08
+.data1 	0x80, 0x3a, 0x2e, 0x75, 0x2b, 0xff, 0x45, 0x08
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xd4, 0x8d, 0x45
+.data1 	0x0c, 0x50, 0x8d, 0x45, 0xe8, 0x50, 0xff, 0x75
+.data1 	0x08, 0xe8, 0xfa, 0xfc, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0x89, 0x45, 0x08, 0x83, 0x7d, 0xe8, 0x00
+.data1 	0x78, 0x06, 0x81, 0xcf, 0x00, 0x02, 0x00, 0x00
+.data1 	0xf7, 0xc7, 0x00, 0x01, 0x00, 0x00, 0x74, 0x0c
+.data1 	0x83, 0x7d, 0xec, 0x00, 0x79, 0x06, 0xf7, 0x5d
+.data1 	0xec, 0x83, 0xcf, 0x01, 0xf7, 0xc7, 0x00, 0x01
+.data1 	0x00, 0x00, 0x75, 0x07, 0xc7, 0x45, 0xec, 0x00
+.data1 	0x00, 0x00, 0x00, 0xf7, 0xc7, 0x02, 0x00, 0x00
+.data1 	0x00, 0x74, 0x03, 0x83, 0xe7, 0xfb, 0xf7, 0xc7
+.data1 	0x01, 0x00, 0x00, 0x00, 0x74, 0x03, 0x83, 0xe7
+.data1 	0xef, 0x8d, 0x95, 0xcf, 0xfb, 0xff, 0xff, 0x89
+.data1 	0x55, 0xd0, 0x89, 0x55, 0xfc, 0xeb, 0x24, 0x83
+.data1 	0xcf, 0x20, 0xff, 0x45, 0x08, 0xe9, 0x23, 0x02
+.data1 	0x00, 0x00, 0x83, 0xcf, 0x40, 0xff, 0x45, 0x08
+.data1 	0xe9, 0x18, 0x02, 0x00, 0x00, 0x81, 0xcf, 0x80
+.data1 	0x00, 0x00, 0x00, 0xff, 0x45, 0x08, 0xe9, 0x0a
+.data1 	0x02, 0x00, 0x00, 0x8b, 0x55, 0x08, 0x0f, 0xbe
+.data1 	0x02, 0xbb, 0x88, 0x07, 0x00, 0x00, 0xe9, 0x6d
+.data1 	0x0f, 0x00, 0x00, 0x8b, 0x16, 0x4a, 0x89, 0x16
+.data1 	0x78, 0x13, 0x8b, 0x55, 0xf0, 0x0f, 0xb6, 0xca
+.data1 	0x8b, 0x46, 0x14, 0x83, 0x46, 0x14, 0x01, 0x88
+.data1 	0x08, 0x89, 0xc8, 0xeb, 0x0b, 0x56, 0xff, 0x75
+.data1 	0xf0, 0xe8, 0xc2, 0x04, 0x00, 0x00, 0x59, 0x59
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x1c, 0x83
+.data1 	0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b, 0x55, 0xd8
+.data1 	0xf7, 0xda, 0x89, 0xd0, 0xe9, 0x64, 0x04, 0x00
+.data1 	0x00, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x5a
+.data1 	0x04, 0x00, 0x00, 0xff, 0x45, 0xd8, 0xe9, 0x30
+.data1 	0xfe, 0xff, 0xff, 0xf7, 0xc7, 0x20, 0x00, 0x00
+.data1 	0x00, 0x74, 0x1a, 0x8b, 0x45, 0xd8, 0x0f, 0xbf
+.data1 	0xc0, 0x8b, 0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x66, 0x89, 0x02
+.data1 	0xe9, 0x0e, 0xfe, 0xff, 0xff, 0xf7, 0xc7, 0x40
+.data1 	0x00, 0x00, 0x00, 0x74, 0x16, 0x8b, 0x55, 0x0c
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c, 0x8b, 0x52
+.data1 	0xfc, 0x8b, 0x4d, 0xd8, 0x89, 0x0a, 0xe9, 0xf0
+.data1 	0xfd, 0xff, 0xff, 0x8b, 0x55, 0x0c, 0x83, 0xc2
+.data1 	0x04, 0x89, 0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x8b
+.data1 	0x4d, 0xd8, 0x89, 0x0a, 0xe9, 0xda, 0xfd, 0xff
+.data1 	0xff, 0x8b, 0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xd0
+.data1 	0x85, 0xd2, 0x75, 0x07, 0xc7, 0x45, 0xd0, 0x38
+.data1 	0x08, 0x00, 0x00, 0x8b, 0x55, 0xd0, 0x89, 0x55
+.data1 	0xfc, 0x83, 0x7d, 0xe8, 0x00, 0x75, 0x0c, 0xf7
+.data1 	0xc7, 0x00, 0x02, 0x00, 0x00, 0x0f, 0x85, 0x38
+.data1 	0x01, 0x00, 0x00, 0x8b, 0x55, 0xfc, 0x80, 0x3a
+.data1 	0x00, 0x0f, 0x84, 0x2c, 0x01, 0x00, 0x00, 0xff
+.data1 	0x45, 0xfc, 0xff, 0x4d, 0xe8, 0xeb, 0xda, 0xf7
+.data1 	0xc7, 0x00, 0x02, 0x00, 0x00, 0x75, 0x09, 0xc7
+.data1 	0x45, 0xe8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x09
+.data1 	0x83, 0x7d, 0xf0, 0x70, 0x74, 0x03, 0x83, 0xe7
+.data1 	0xef, 0x8b, 0x45, 0xf0, 0x0f, 0xbe, 0xc0, 0x6a
+.data1 	0x00, 0xff, 0x75, 0xe8, 0x50, 0xff, 0x75, 0xfc
+.data1 	0x57, 0x8d, 0x45, 0x0c, 0x50, 0xe8, 0xa1, 0xfb
+.data1 	0xff, 0xff, 0x83, 0xc4, 0x18, 0x89, 0x45, 0xfc
+.data1 	0xe9, 0xe6, 0x00, 0x00, 0x00, 0x81, 0xcf, 0x00
+.data1 	0x04, 0x00, 0x00, 0xf7, 0xc7, 0x00, 0x02, 0x00
+.data1 	0x00, 0x75, 0x09, 0xc7, 0x45, 0xe8, 0x01, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x03, 0x83, 0xe7, 0xef, 0x8b
+.data1 	0x45, 0xf0, 0x0f, 0xbe, 0xc0, 0x6a, 0x01, 0xff
+.data1 	0x75, 0xe8, 0x50, 0xff, 0x75, 0xfc, 0x57, 0x8d
+.data1 	0x45, 0x0c, 0x50, 0xe8, 0x63, 0xfb, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x18, 0x89, 0x45, 0xfc, 0xe9, 0xa8
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0x83, 0xc2
+.data1 	0x04, 0x89, 0x55, 0x0c, 0x8b, 0x4d, 0xfc, 0x8b
+.data1 	0x52, 0xfc, 0x88, 0x11, 0xff, 0x45, 0xfc, 0xe9
+.data1 	0x8f, 0x00, 0x00, 0x00, 0xf7, 0xc7, 0x00, 0x02
+.data1 	0x00, 0x00, 0x74, 0x0d, 0x83, 0x7d, 0xe8, 0x00
+.data1 	0x75, 0x07, 0xc7, 0x45, 0xe8, 0x01, 0x00, 0x00
+.data1 	0x00, 0xf7, 0xc7, 0x00, 0x02, 0x00, 0x00, 0x75
+.data1 	0x07, 0xc7, 0x45, 0xe8, 0x06, 0x00, 0x00, 0x00
+.data1 	0x81, 0x7d, 0xe8, 0x01, 0x04, 0x00, 0x00, 0x72
+.data1 	0x07, 0xc7, 0x45, 0xe8, 0x00, 0x04, 0x00, 0x00
+.data1 	0x81, 0xcf, 0x00, 0x04, 0x00, 0x00, 0x8b, 0x45
+.data1 	0xf0, 0x0f, 0xbe, 0xc0, 0xff, 0x75, 0xe8, 0x50
+.data1 	0xff, 0x75, 0xfc, 0x57, 0x8d, 0x45, 0x0c, 0x50
+.data1 	0xe8, 0xff, 0x05, 0x00, 0x00, 0x83, 0xc4, 0x14
+.data1 	0x89, 0x45, 0xfc, 0xeb, 0x36, 0x8b, 0x55, 0x0c
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0x08
+.data1 	0xe9, 0x86, 0xfc, 0xff, 0xff, 0x8b, 0x45, 0x08
+.data1 	0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0x45
+.data1 	0xf0, 0xbb, 0xa8, 0x07, 0x00, 0x00, 0xe9, 0x5d
+.data1 	0x0d, 0x00, 0x00, 0xc7, 0x45, 0xe4, 0x20, 0x00
+.data1 	0x00, 0x00, 0xf7, 0xc7, 0x10, 0x00, 0x00, 0x00
+.data1 	0x74, 0x07, 0xc7, 0x45, 0xe4, 0x30, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xfc, 0x2b, 0x55, 0xd0, 0x89
+.data1 	0x55, 0xf8, 0xc7, 0x45, 0xdc, 0x00, 0x00, 0x00
+.data1 	0x00, 0xf7, 0xc7, 0x10, 0x00, 0x00, 0x00, 0x74
+.data1 	0x37, 0x83, 0x7d, 0xf0, 0x78, 0x74, 0x06, 0x83
+.data1 	0x7d, 0xf0, 0x58, 0x75, 0x08, 0xf7, 0xc7, 0x08
+.data1 	0x00, 0x00, 0x00, 0x75, 0x20, 0x83, 0x7d, 0xf0
+.data1 	0x70, 0x74, 0x1a, 0xf7, 0xc7, 0x00, 0x04, 0x00
+.data1 	0x00, 0x74, 0x15, 0x8b, 0x55, 0xd0, 0x80, 0x3a
+.data1 	0x2b, 0x74, 0x0a, 0x80, 0x3a, 0x2d, 0x74, 0x05
+.data1 	0x80, 0x3a, 0x20, 0x75, 0x03, 0xff, 0x45, 0xdc
+.data1 	0x8b, 0x55, 0xec, 0x2b, 0x55, 0xf8, 0x89, 0x55
+.data1 	0xf4, 0x85, 0xd2, 0x0f, 0x8e, 0x61, 0x01, 0x00
+.data1 	0x00, 0xf7, 0xc7, 0x01, 0x00, 0x00, 0x00, 0x0f
+.data1 	0x85, 0x55, 0x01, 0x00, 0x00, 0x8b, 0x55, 0xf4
+.data1 	0x01, 0x55, 0xd8, 0x83, 0x7d, 0xdc, 0x00, 0x0f
+.data1 	0x84, 0xf8, 0x00, 0x00, 0x00, 0xf7, 0xc7, 0x00
+.data1 	0x04, 0x00, 0x00, 0x0f, 0x84, 0x5c, 0x00, 0x00
+.data1 	0x00, 0xff, 0x4d, 0xf8, 0xff, 0x45, 0xd8, 0x8b
+.data1 	0x16, 0x4a, 0x89, 0x16, 0x78, 0x16, 0x8b, 0x45
+.data1 	0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xb6, 0x10, 0x8b
+.data1 	0x46, 0x14, 0x83, 0x46, 0x14, 0x01, 0x88, 0x10
+.data1 	0x89, 0xd0, 0xeb, 0x12, 0x8b, 0x45, 0xd0, 0xff
+.data1 	0x45, 0xd0, 0x0f, 0xbe, 0x00, 0x56, 0x50, 0xe8
+.data1 	0x04, 0x02, 0x00, 0x00, 0x59, 0x59, 0x3d, 0xff
+.data1 	0xff, 0xff, 0xff, 0x0f, 0x85, 0xac, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b
+.data1 	0x55, 0xd8, 0xf7, 0xda, 0x89, 0xd0, 0xe9, 0xa2
+.data1 	0x01, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x98, 0x01, 0x00, 0x00, 0x83, 0x6d, 0xf8
+.data1 	0x02, 0x83, 0x45, 0xd8, 0x02, 0x8b, 0x16, 0x4a
+.data1 	0x89, 0x16, 0x78, 0x16, 0x8b, 0x45, 0xd0, 0xff
+.data1 	0x45, 0xd0, 0x0f, 0xb6, 0x10, 0x8b, 0x46, 0x14
+.data1 	0x83, 0x46, 0x14, 0x01, 0x88, 0x10, 0x89, 0xd0
+.data1 	0xeb, 0x12, 0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0
+.data1 	0x0f, 0xbe, 0x00, 0x56, 0x50, 0xe8, 0xa6, 0x01
+.data1 	0x00, 0x00, 0x59, 0x59, 0x3d, 0xff, 0xff, 0xff
+.data1 	0xff, 0x74, 0x36, 0x8b, 0x16, 0x4a, 0x89, 0x16
+.data1 	0x78, 0x16, 0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0
+.data1 	0x0f, 0xb6, 0x10, 0x8b, 0x46, 0x14, 0x83, 0x46
+.data1 	0x14, 0x01, 0x88, 0x10, 0x89, 0xd0, 0xeb, 0x12
+.data1 	0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xbe
+.data1 	0x00, 0x56, 0x50, 0xe8, 0x70, 0x01, 0x00, 0x00
+.data1 	0x59, 0x59, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x1c, 0x83, 0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b
+.data1 	0x55, 0xd8, 0xf7, 0xda, 0x89, 0xd0, 0xe9, 0x12
+.data1 	0x01, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x08, 0x01, 0x00, 0x00, 0x8b, 0x16, 0x4a
+.data1 	0x89, 0x16, 0x78, 0x13, 0x8b, 0x55, 0xe4, 0x0f
+.data1 	0xb6, 0xca, 0x8b, 0x46, 0x14, 0x83, 0x46, 0x14
+.data1 	0x01, 0x88, 0x08, 0x89, 0xc8, 0xeb, 0x0b, 0x56
+.data1 	0xff, 0x75, 0xe4, 0xe8, 0x28, 0x01, 0x00, 0x00
+.data1 	0x59, 0x59, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x1c, 0x83, 0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b
+.data1 	0x55, 0xd8, 0xf7, 0xda, 0x89, 0xd0, 0xe9, 0xca
+.data1 	0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0xc0, 0x00, 0x00, 0x00, 0xff, 0x4d, 0xf4
+.data1 	0x75, 0xb3, 0x8b, 0x55, 0xf8, 0x01, 0x55, 0xd8
+.data1 	0xff, 0x4d, 0xf8, 0x0f, 0x88, 0x52, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x16, 0x4a, 0x89, 0x16, 0x78, 0x16
+.data1 	0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xb6
+.data1 	0x10, 0x8b, 0x46, 0x14, 0x83, 0x46, 0x14, 0x01
+.data1 	0x88, 0x10, 0x89, 0xd0, 0xeb, 0x12, 0x8b, 0x45
+.data1 	0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xbe, 0x00, 0x56
+.data1 	0x50, 0xe8, 0xc2, 0x00, 0x00, 0x00, 0x59, 0x59
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0xc1, 0x83
+.data1 	0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b, 0x55, 0xd8
+.data1 	0xf7, 0xda, 0x89, 0xd0, 0xe9, 0x64, 0x00, 0x00
+.data1 	0x00, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x5a
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xf4, 0x00, 0x7e
+.data1 	0x06, 0x8b, 0x55, 0xf4, 0x01, 0x55, 0xd8, 0xff
+.data1 	0x4d, 0xf4, 0x0f, 0x88, 0x23, 0xfa, 0xff, 0xff
+.data1 	0x8b, 0x16, 0x4a, 0x89, 0x16, 0x78, 0x13, 0x8b
+.data1 	0x55, 0xe4, 0x0f, 0xb6, 0xca, 0x8b, 0x46, 0x14
+.data1 	0x83, 0x46, 0x14, 0x01, 0x88, 0x08, 0x89, 0xc8
+.data1 	0xeb, 0x0b, 0x56, 0xff, 0x75, 0xe4, 0xe8, 0x65
+.data1 	0x00, 0x00, 0x00, 0x59, 0x59, 0x3d, 0xff, 0xff
+.data1 	0xff, 0xff, 0x75, 0xcb, 0x83, 0x7d, 0xd8, 0x00
+.data1 	0x74, 0x09, 0x8b, 0x55, 0xd8, 0xf7, 0xda, 0x89
+.data1 	0xd0, 0xeb, 0x0a, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x03, 0x8b, 0x45, 0xd8, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x7d, 0x10, 0x57, 0xff, 0x75, 0x0c
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x84, 0xf7, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0xc6, 0x85, 0xc0, 0x7e
+.data1 	0x14, 0x39, 0xfe, 0x7d, 0x10, 0x89, 0xfa, 0x29
+.data1 	0xf2, 0x89, 0xd7, 0x89, 0xf2, 0x03, 0x55, 0x0c
+.data1 	0x89, 0x55, 0x0c, 0xeb, 0xd7, 0x31, 0xc0, 0x85
+.data1 	0xf6, 0x0f, 0x9f, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x56, 0x57
+.data1 	0x8b, 0x75, 0x0c, 0x8b, 0x7d, 0x08, 0xc7, 0x05
+.data1 	0x68, 0x08, 0x00, 0x00, 0xbd, 0x16, 0x00, 0x00
+.data1 	0x83, 0x7e, 0x04, 0x00, 0x79, 0x0a, 0x89, 0xfa
+.data1 	0x0f, 0xb6, 0xc2, 0xe9, 0x55, 0x02, 0x00, 0x00
+.data1 	0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x02, 0x75, 0x0a
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x43, 0x02
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x80
+.data1 	0x74, 0x0f, 0xf6, 0xc2, 0x10, 0x75, 0x0a, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe9, 0x2c, 0x02, 0x00
+.data1 	0x00, 0x81, 0x66, 0x08, 0x7f, 0xff, 0xff, 0xff
+.data1 	0x81, 0x4e, 0x08, 0x00, 0x01, 0x00, 0x00, 0x8b
+.data1 	0x56, 0x08, 0xf6, 0xc2, 0x04, 0x0f, 0x85, 0x8f
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7e, 0x10, 0x00, 0x0f
+.data1 	0x85, 0x85, 0x00, 0x00, 0x00, 0x81, 0xfe, 0x8c
+.data1 	0x08, 0x00, 0x00, 0x75, 0x3e, 0xff, 0x35, 0x90
+.data1 	0x08, 0x00, 0x00, 0xe8, 0xbc, 0x06, 0x00, 0x00
+.data1 	0x59, 0x85, 0xc0, 0x74, 0x2e, 0x68, 0x00, 0x04
+.data1 	0x00, 0x00, 0xe8, 0xf0, 0x02, 0x00, 0x00, 0x59
+.data1 	0x89, 0x46, 0x10, 0x85, 0xc0, 0x75, 0x09, 0x83
+.data1 	0x4e, 0x08, 0x04, 0xe9, 0x4c, 0x00, 0x00, 0x00
+.data1 	0x83, 0x4e, 0x08, 0x48, 0xc7, 0x46, 0x0c, 0x00
+.data1 	0x04, 0x00, 0x00, 0xc7, 0x06, 0xff, 0xff, 0xff
+.data1 	0xff, 0xeb, 0x39, 0x68, 0x00, 0x04, 0x00, 0x00
+.data1 	0xe8, 0xc2, 0x02, 0x00, 0x00, 0x59, 0x89, 0x46
+.data1 	0x10, 0x85, 0xc0, 0x75, 0x06, 0x83, 0x4e, 0x08
+.data1 	0x04, 0xeb, 0x21, 0x83, 0x4e, 0x08, 0x08, 0xc7
+.data1 	0x46, 0x0c, 0x00, 0x04, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x40, 0x75, 0x08, 0xc7, 0x06
+.data1 	0xff, 0x03, 0x00, 0x00, 0xeb, 0x06, 0xc7, 0x06
+.data1 	0xff, 0xff, 0xff, 0xff, 0x8b, 0x56, 0x10, 0x89
+.data1 	0x56, 0x14, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x04
+.data1 	0x0f, 0x84, 0x68, 0x00, 0x00, 0x00, 0x89, 0xfa
+.data1 	0x88, 0x55, 0xff, 0xc7, 0x06, 0x00, 0x00, 0x00
+.data1 	0x00, 0xf7, 0x46, 0x08, 0x00, 0x02, 0x00, 0x00
+.data1 	0x74, 0x24, 0x6a, 0x02, 0x6a, 0x00, 0xff, 0x76
+.data1 	0x04, 0xe8, 0x6e, 0xf5, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x0e
+.data1 	0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x3f, 0x01, 0x00, 0x00, 0x6a, 0x01
+.data1 	0x8d, 0x45, 0xff, 0x50, 0xff, 0x76, 0x04, 0xe8
+.data1 	0x10, 0xf6, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x3d
+.data1 	0x01, 0x00, 0x00, 0x00, 0x74, 0x0e, 0x83, 0x4e
+.data1 	0x08, 0x20, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9
+.data1 	0x19, 0x01, 0x00, 0x00, 0x89, 0xfa, 0x0f, 0xb6
+.data1 	0xc2, 0xe9, 0x0f, 0x01, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x40, 0x0f, 0x84, 0x84, 0x00
+.data1 	0x00, 0x00, 0x89, 0xfa, 0x8b, 0x46, 0x14, 0x83
+.data1 	0x46, 0x14, 0x01, 0x88, 0x10, 0x83, 0xff, 0x0a
+.data1 	0x74, 0x0d, 0x8b, 0x56, 0x0c, 0xf7, 0xda, 0x39
+.data1 	0x16, 0x0f, 0x85, 0xe1, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x16, 0xf7, 0xda, 0x89, 0x55, 0xf8, 0x8b, 0x56
+.data1 	0x10, 0x89, 0x56, 0x14, 0xc7, 0x06, 0x00, 0x00
+.data1 	0x00, 0x00, 0xf7, 0x46, 0x08, 0x00, 0x02, 0x00
+.data1 	0x00, 0x74, 0x24, 0x6a, 0x02, 0x6a, 0x00, 0xff
+.data1 	0x76, 0x04, 0xe8, 0xd5, 0xf4, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x0e, 0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe9, 0xa6, 0x00, 0x00, 0x00, 0xff
+.data1 	0x75, 0xf8, 0xff, 0x76, 0x10, 0xff, 0x76, 0x04
+.data1 	0xe8, 0xdf, 0xfd, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x85, 0xc0, 0x0f, 0x85, 0x88, 0x00, 0x00, 0x00
+.data1 	0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x7f, 0x00, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x14, 0x2b, 0x56, 0x10, 0x89, 0x55, 0xf8, 0x8b
+.data1 	0x56, 0x0c, 0x4a, 0x89, 0x16, 0x8b, 0x56, 0x10
+.data1 	0x83, 0xc2, 0x01, 0x89, 0x56, 0x14, 0x83, 0x7d
+.data1 	0xf8, 0x00, 0x0f, 0x8e, 0x51, 0x00, 0x00, 0x00
+.data1 	0xf7, 0x46, 0x08, 0x00, 0x02, 0x00, 0x00, 0x74
+.data1 	0x21, 0x6a, 0x02, 0x6a, 0x00, 0xff, 0x76, 0x04
+.data1 	0xe8, 0x5f, 0xf4, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x0b, 0x83
+.data1 	0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x33, 0xff, 0x75, 0xf8, 0xff, 0x76, 0x10
+.data1 	0xff, 0x76, 0x04, 0xe8, 0x6c, 0xfd, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x75, 0x12, 0x89
+.data1 	0xfa, 0x8b, 0x4e, 0x10, 0x88, 0x11, 0x83, 0x4e
+.data1 	0x08, 0x20, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x0c, 0x89, 0xfa, 0x8b, 0x4e, 0x10, 0x88, 0x11
+.data1 	0x89, 0xfa, 0x0f, 0xb6, 0xc2, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x10, 0x8b, 0x45, 0x08, 0x31
+.data1 	0xd2, 0xf7, 0x75, 0x0c, 0x89, 0xd7, 0x8b, 0x45
+.data1 	0x08, 0x31, 0xd2, 0xf7, 0x75, 0x0c, 0x89, 0x45
+.data1 	0x08, 0x85, 0xc0, 0x75, 0x06, 0x83, 0x7d, 0x14
+.data1 	0x01, 0x7e, 0x16, 0x8b, 0x55, 0x14, 0x4a, 0x52
+.data1 	0x56, 0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xc8, 0xff, 0xff, 0xff, 0x83, 0xc4, 0x10, 0x89
+.data1 	0xc6, 0x83, 0xff, 0x09, 0x7e, 0x09, 0x89, 0xfa
+.data1 	0x83, 0xea, 0xa9, 0x89, 0xd0, 0xeb, 0x03, 0x8d
+.data1 	0x47, 0x30, 0x88, 0x06, 0x8d, 0x46, 0x01, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x00, 0xb9, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0xc2, 0x06, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x68
+.data1 	0x40, 0x08, 0x00, 0x00, 0x68, 0xa4, 0x08, 0x00
+.data1 	0x00, 0xe8, 0xf2, 0xf2, 0xff, 0xff, 0x59, 0x59
+.data1 	0x6a, 0x01, 0xe8, 0xa2, 0xf2, 0xff, 0xff, 0x59
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x15, 0x64, 0x0a, 0x00, 0x00, 0x03, 0x55
+.data1 	0x08, 0x39, 0x15, 0x64, 0x0a, 0x00, 0x00, 0x77
+.data1 	0x1f, 0x8b, 0x55, 0x08, 0x03, 0x15, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x81, 0xc2, 0xff, 0x0f, 0x00, 0x00
+.data1 	0x81, 0xe2, 0x00, 0xf0, 0xff, 0xff, 0x89, 0xd6
+.data1 	0x39, 0x15, 0x64, 0x0a, 0x00, 0x00, 0x76, 0x0e
+.data1 	0xc7, 0x05, 0x70, 0x08, 0x00, 0x00, 0x0c, 0x00
+.data1 	0x00, 0x00, 0x31, 0xc0, 0xeb, 0x36, 0x56, 0xe8
+.data1 	0xe8, 0x02, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x74
+.data1 	0x04, 0x31, 0xc0, 0xeb, 0x27, 0x8b, 0x15, 0x64
+.data1 	0x0a, 0x00, 0x00, 0x89, 0x72, 0xfc, 0xc7, 0x46
+.data1 	0xfc, 0x00, 0x00, 0x00, 0x00, 0xff, 0x35, 0x64
+.data1 	0x0a, 0x00, 0x00, 0xe8, 0x26, 0x02, 0x00, 0x00
+.data1 	0x59, 0x89, 0x35, 0x64, 0x0a, 0x00, 0x00, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x18, 0x56, 0x57, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x75, 0x07, 0x31, 0xc0, 0xe9
+.data1 	0xf4, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xe8, 0x00
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xe8, 0x02, 0x0f
+.data1 	0x83, 0xe1, 0x00, 0x00, 0x00, 0xba, 0x03, 0x00
+.data1 	0x00, 0x00, 0x03, 0x55, 0x08, 0x83, 0xe2, 0xfc
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0xec, 0x83, 0xfa
+.data1 	0x08, 0x73, 0x11, 0xc7, 0x05, 0x70, 0x08, 0x00
+.data1 	0x00, 0x0c, 0x00, 0x00, 0x00, 0x31, 0xc0, 0xe9
+.data1 	0xbc, 0x00, 0x00, 0x00, 0x83, 0x3d, 0x60, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x75, 0x38, 0x6a, 0x08, 0xe8
+.data1 	0x97, 0x02, 0x00, 0x00, 0x59, 0x89, 0xc6, 0x3d
+.data1 	0xff, 0xff, 0xff, 0xff, 0x75, 0x07, 0x31, 0xc0
+.data1 	0xe9, 0x9b, 0x00, 0x00, 0x00, 0x8d, 0x56, 0x03
+.data1 	0xbe, 0xfc, 0xff, 0xff, 0xff, 0x21, 0xd6, 0x83
+.data1 	0xc6, 0x04, 0x89, 0x35, 0x60, 0x0a, 0x00, 0x00
+.data1 	0x89, 0x35, 0x64, 0x0a, 0x00, 0x00, 0xc7, 0x46
+.data1 	0xfc, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xfc
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x35, 0x68, 0x0a
+.data1 	0x00, 0x00, 0x85, 0xf6, 0x0f, 0x84, 0x4f, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x56, 0xfc, 0x89, 0x55, 0xf4
+.data1 	0x89, 0xf2, 0x8b, 0x7d, 0xec, 0x01, 0xd7, 0x39
+.data1 	0x7d, 0xf4, 0x72, 0x36, 0x39, 0xf7, 0x76, 0x32
+.data1 	0x8d, 0x57, 0x04, 0x39, 0x55, 0xf4, 0x76, 0x0f
+.data1 	0x8b, 0x55, 0xf4, 0x89, 0x57, 0xfc, 0x89, 0x7e
+.data1 	0xfc, 0x8b, 0x16, 0x89, 0x17, 0x89, 0x3e, 0x83
+.data1 	0x7d, 0xfc, 0x00, 0x74, 0x09, 0x8b, 0x16, 0x8b
+.data1 	0x45, 0xfc, 0x89, 0x10, 0xeb, 0x08, 0x8b, 0x16
+.data1 	0x89, 0x15, 0x68, 0x0a, 0x00, 0x00, 0x89, 0xf0
+.data1 	0xeb, 0x1e, 0x89, 0x75, 0xfc, 0x8b, 0x36, 0xeb
+.data1 	0xa9, 0xff, 0x75, 0xec, 0xe8, 0x8b, 0xfe, 0xff
+.data1 	0xff, 0x59, 0x85, 0xc0, 0x74, 0x08, 0xff, 0x45
+.data1 	0xe8, 0xe9, 0x15, 0xff, 0xff, 0xff, 0x31, 0xc0
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x1c, 0x56, 0x57, 0x8b, 0x55, 0x08, 0x89
+.data1 	0x55, 0xec, 0x85, 0xd2, 0x75, 0x0e, 0xff, 0x75
+.data1 	0x0c, 0xe8, 0xd9, 0xfe, 0xff, 0xff, 0x59, 0xe9
+.data1 	0xe6, 0x00, 0x00, 0x00, 0x83, 0x7d, 0x0c, 0x00
+.data1 	0x75, 0x10, 0xff, 0x75, 0xec, 0xe8, 0xdc, 0x00
+.data1 	0x00, 0x00, 0x59, 0x31, 0xc0, 0xe9, 0xd0, 0x00
+.data1 	0x00, 0x00, 0xba, 0x03, 0x00, 0x00, 0x00, 0x03
+.data1 	0x55, 0x0c, 0x83, 0xe2, 0xfc, 0x83, 0xc2, 0x04
+.data1 	0x89, 0x55, 0xe8, 0x8b, 0x55, 0xec, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0xf4, 0x2b, 0x55, 0xec, 0x89
+.data1 	0x55, 0xe4, 0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x3d, 0x68, 0x0a, 0x00, 0x00, 0x85
+.data1 	0xff, 0x0f, 0x84, 0x3c, 0x00, 0x00, 0x00, 0x39
+.data1 	0x7d, 0xf4, 0x72, 0x37, 0x39, 0x7d, 0xf4, 0x75
+.data1 	0x2b, 0x8b, 0x55, 0xec, 0x8b, 0x4f, 0xfc, 0x89
+.data1 	0x4a, 0xfc, 0x83, 0x7d, 0xfc, 0x00, 0x74, 0x09
+.data1 	0x8b, 0x17, 0x8b, 0x45, 0xfc, 0x89, 0x10, 0xeb
+.data1 	0x08, 0x8b, 0x17, 0x89, 0x15, 0x68, 0x0a, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xec, 0x8b, 0x52, 0xfc, 0x89
+.data1 	0x55, 0xf4, 0xeb, 0x07, 0x89, 0x7d, 0xfc, 0x8b
+.data1 	0x3f, 0xeb, 0xbc, 0x8b, 0x55, 0xec, 0x8b, 0x75
+.data1 	0xe8, 0x01, 0xd6, 0x39, 0x75, 0xf4, 0x72, 0x25
+.data1 	0x39, 0x75, 0xec, 0x77, 0x20, 0x8d, 0x56, 0x04
+.data1 	0x39, 0x55, 0xf4, 0x76, 0x13, 0x8b, 0x55, 0xf4
+.data1 	0x89, 0x56, 0xfc, 0x8b, 0x55, 0xec, 0x89, 0x72
+.data1 	0xfc, 0x56, 0xe8, 0x37, 0x00, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x45, 0xec, 0xeb, 0x2d, 0xff, 0x75, 0x0c
+.data1 	0xe8, 0x12, 0xfe, 0xff, 0xff, 0x59, 0x89, 0xc6
+.data1 	0x85, 0xc0, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x1a
+.data1 	0xff, 0x75, 0xe4, 0xff, 0x75, 0xec, 0x56, 0xe8
+.data1 	0x3c, 0x04, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xff
+.data1 	0x75, 0xec, 0xe8, 0x07, 0x00, 0x00, 0x00, 0x59
+.data1 	0x89, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xf4, 0x85, 0xd2, 0x0f, 0x84
+.data1 	0x62, 0x00, 0x00, 0x00, 0x31, 0xff, 0x8b, 0x35
+.data1 	0x68, 0x0a, 0x00, 0x00, 0x85, 0xf6, 0x74, 0x0b
+.data1 	0x39, 0x75, 0xf4, 0x72, 0x06, 0x89, 0xf7, 0x8b
+.data1 	0x36, 0xeb, 0xf1, 0x8b, 0x45, 0xf4, 0x89, 0x30
+.data1 	0x85, 0xff, 0x74, 0x07, 0x8b, 0x55, 0xf4, 0x89
+.data1 	0x17, 0xeb, 0x09, 0x8b, 0x55, 0xf4, 0x89, 0x15
+.data1 	0x68, 0x0a, 0x00, 0x00, 0x85, 0xf6, 0x74, 0x15
+.data1 	0x8b, 0x55, 0xf4, 0x39, 0x72, 0xfc, 0x75, 0x0d
+.data1 	0x8b, 0x4e, 0xfc, 0x89, 0x4a, 0xfc, 0x8b, 0x16
+.data1 	0x8b, 0x45, 0xf4, 0x89, 0x10, 0x85, 0xff, 0x74
+.data1 	0x15, 0x8b, 0x55, 0xf4, 0x39, 0x57, 0xfc, 0x75
+.data1 	0x0d, 0x8b, 0x52, 0xfc, 0x89, 0x57, 0xfc, 0x8b
+.data1 	0x45, 0xf4, 0x8b, 0x10, 0x89, 0x17, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x8b
+.data1 	0x55, 0x08, 0x83, 0xea, 0x61, 0x83, 0xfa, 0x1a
+.data1 	0x73, 0x0a, 0x8b, 0x55, 0x08, 0x83, 0xea, 0x20
+.data1 	0x89, 0xd0, 0xeb, 0x03, 0x8b, 0x45, 0x08, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x15, 0x54, 0x0a, 0x00, 0x00
+.data1 	0x39, 0x55, 0x08, 0x74, 0x2a, 0x8b, 0x55, 0x08
+.data1 	0x89, 0x55, 0xf0, 0x8d, 0x45, 0xdc, 0x50, 0x6a
+.data1 	0x11, 0x6a, 0x00, 0xe8, 0xa0, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x79, 0x07, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x0b, 0x8b, 0x55
+.data1 	0xf8, 0x89, 0x15, 0x54, 0x0a, 0x00, 0x00, 0x31
+.data1 	0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x57
+.data1 	0x8b, 0x35, 0x54, 0x0a, 0x00, 0x00, 0x8b, 0x15
+.data1 	0x54, 0x0a, 0x00, 0x00, 0x8b, 0x7d, 0x08, 0x01
+.data1 	0xd7, 0x83, 0x7d, 0x08, 0x00, 0x7e, 0x04, 0x39
+.data1 	0xf7, 0x72, 0x0a, 0x83, 0x7d, 0x08, 0x00, 0x79
+.data1 	0x0b, 0x39, 0xf7, 0x76, 0x07, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xeb, 0x14, 0x57, 0xe8, 0x8a, 0xff
+.data1 	0xff, 0xff, 0x59, 0x85, 0xc0, 0x75, 0x04, 0x89
+.data1 	0xf0, 0xeb, 0x05, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x0c, 0xfc, 0xff, 0xff
+.data1 	0x59, 0xbe, 0x01, 0x00, 0x00, 0x00, 0x01, 0xc6
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x72, 0x08, 0x8b, 0x55
+.data1 	0x0c, 0x8b, 0x4d, 0x08, 0x89, 0x4a, 0x10, 0x83
+.data1 	0xfe, 0x0e, 0x77, 0x11, 0x8b, 0x55, 0x0c, 0xff
+.data1 	0x75, 0x08, 0x83, 0xc2, 0x14, 0x52, 0xe8, 0xed
+.data1 	0x02, 0x00, 0x00, 0x59, 0x59, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x75, 0x10
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x56, 0x04, 0x56, 0xff
+.data1 	0x75, 0x08, 0xe8, 0x59, 0x02, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0xc7, 0x85, 0xff, 0x74, 0x03, 0x89
+.data1 	0x7e, 0x04, 0x83, 0x7e, 0x04, 0x00, 0x79, 0x12
+.data1 	0x8b, 0x56, 0x04, 0xf7, 0xda, 0x89, 0x15, 0x70
+.data1 	0x08, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x03, 0x8b, 0x46, 0x04, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8d, 0x45, 0xdc, 0x50, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x0e, 0x00, 0x00, 0x00, 0x59, 0x59
+.data1 	0x31, 0xdb, 0x85, 0xc0, 0x0f, 0x94, 0xc3, 0x89
+.data1 	0xd8, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0xff
+.data1 	0x75, 0x0c, 0x68, 0x08, 0x54, 0x24, 0x80, 0xff
+.data1 	0x75, 0x08, 0xe8, 0xf1, 0xee, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x14, 0x56, 0x57, 0x8b, 0x75, 0x08, 0xc7
+.data1 	0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x85, 0xf6
+.data1 	0x75, 0x34, 0x31, 0xff, 0x83, 0xff, 0x14, 0x7d
+.data1 	0x25, 0x83, 0x3c, 0xbd, 0xbc, 0x08, 0x00, 0x00
+.data1 	0x00, 0x74, 0x18, 0xff, 0x34, 0xbd, 0xbc, 0x08
+.data1 	0x00, 0x00, 0xe8, 0xcd, 0xff, 0xff, 0xff, 0x59
+.data1 	0x85, 0xc0, 0x74, 0x07, 0xc7, 0x45, 0xf0, 0xff
+.data1 	0xff, 0xff, 0xff, 0x47, 0xeb, 0xd6, 0x8b, 0x45
+.data1 	0xf0, 0xe9, 0x43, 0x01, 0x00, 0x00, 0x83, 0x7e
+.data1 	0x10, 0x00, 0x74, 0x11, 0x8b, 0x56, 0x08, 0xf6
+.data1 	0xc2, 0x80, 0x75, 0x10, 0xf7, 0x46, 0x08, 0x00
+.data1 	0x01, 0x00, 0x00, 0x75, 0x07, 0x31, 0xc0, 0xe9
+.data1 	0x25, 0x01, 0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6
+.data1 	0xc2, 0x80, 0x0f, 0x84, 0x86, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, 0x00, 0xf7
+.data1 	0x46, 0x08, 0x00, 0x04, 0x00, 0x00, 0x74, 0x07
+.data1 	0x31, 0xc0, 0xe9, 0x02, 0x01, 0x00, 0x00, 0x83
+.data1 	0x7e, 0x10, 0x00, 0x74, 0x0f, 0x8b, 0x56, 0x08
+.data1 	0xf6, 0xc2, 0x04, 0x75, 0x07, 0x8b, 0x16, 0xf7
+.data1 	0xda, 0x89, 0x55, 0xec, 0xc7, 0x06, 0x00, 0x00
+.data1 	0x00, 0x00, 0x6a, 0x01, 0xff, 0x75, 0xec, 0xff
+.data1 	0x76, 0x04, 0xe8, 0x65, 0xee, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x17, 0x83, 0x3d, 0x70, 0x08, 0x00, 0x00, 0x1d
+.data1 	0x74, 0x0e, 0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xe9, 0xb9, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x05, 0x70, 0x08, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x02
+.data1 	0x74, 0x07, 0x81, 0x66, 0x08, 0x7f, 0xfe, 0xff
+.data1 	0xff, 0x8b, 0x56, 0x10, 0x89, 0x56, 0x14, 0x31
+.data1 	0xc0, 0xe9, 0x93, 0x00, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x04, 0x74, 0x07, 0x31, 0xc0
+.data1 	0xe9, 0x84, 0x00, 0x00, 0x00, 0x8b, 0x56, 0x08
+.data1 	0xf6, 0xc2, 0x01, 0x74, 0x07, 0x81, 0x66, 0x08
+.data1 	0xff, 0xfe, 0xff, 0xff, 0x8b, 0x56, 0x14, 0x2b
+.data1 	0x56, 0x10, 0x89, 0x55, 0xfc, 0x8b, 0x56, 0x10
+.data1 	0x89, 0x56, 0x14, 0x83, 0x7d, 0xfc, 0x00, 0x7f
+.data1 	0x07, 0x31, 0xc0, 0xe9, 0x59, 0x00, 0x00, 0x00
+.data1 	0xf7, 0x46, 0x08, 0x00, 0x02, 0x00, 0x00, 0x74
+.data1 	0x21, 0x6a, 0x02, 0x6a, 0x00, 0xff, 0x76, 0x04
+.data1 	0xe8, 0xcf, 0xed, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x0b, 0x83
+.data1 	0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x2f, 0xff, 0x75, 0xfc, 0xff, 0x76, 0x10
+.data1 	0xff, 0x76, 0x04, 0xe8, 0x74, 0xee, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x45, 0xf8, 0xc7, 0x06
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xf8, 0x39
+.data1 	0x55, 0xfc, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x09
+.data1 	0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0x31, 0xf6, 0x83, 0xfe, 0x14, 0x7d, 0x2a
+.data1 	0x83, 0x3c, 0xb5, 0xbc, 0x08, 0x00, 0x00, 0x00
+.data1 	0x74, 0x1d, 0x8b, 0x14, 0xb5, 0xbc, 0x08, 0x00
+.data1 	0x00, 0xf7, 0x42, 0x08, 0x00, 0x01, 0x00, 0x00
+.data1 	0x74, 0x0d, 0xff, 0x34, 0xb5, 0xbc, 0x08, 0x00
+.data1 	0x00, 0xe8, 0x3e, 0xfe, 0xff, 0xff, 0x59, 0x46
+.data1 	0xeb, 0xd1, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x01, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x02
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x03, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0xb9, 0x04, 0x00, 0x00, 0x00
+.data1 	0xcd, 0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x53, 0x8b, 0x5d, 0x08, 0xb9, 0x08, 0x00, 0x00
+.data1 	0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x57, 0x8b, 0x7d, 0x08, 0x30
+.data1 	0xc0, 0x89, 0xca, 0x80, 0xf9, 0x01, 0xfc, 0xf2
+.data1 	0xae, 0x75, 0x01, 0x41, 0x89, 0xd0, 0x29, 0xc8
+.data1 	0x5f, 0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x08
+.data1 	0x8b, 0x75, 0x0c, 0x8b, 0x4d, 0x10, 0xe9, 0x43
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0xb9, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe8, 0x71, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x45, 0x08, 0x5f, 0x5e, 0x5d, 0xc3, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x08
+.data1 	0x8b, 0x75, 0x0c, 0x8b, 0x4d, 0x10, 0x89, 0xf8
+.data1 	0x29, 0xf0, 0x39, 0xc8, 0x72, 0x2f, 0xfc, 0x83
+.data1 	0xf9, 0x10, 0x72, 0x20, 0x89, 0xf0, 0x09, 0xf8
+.data1 	0xa8, 0x01, 0x75, 0x18, 0xa8, 0x02, 0x75, 0x0d
+.data1 	0x0f, 0xac, 0xc8, 0x02, 0xc1, 0xe9, 0x02, 0xf3
+.data1 	0xa5, 0x0f, 0xa4, 0xc1, 0x02, 0xd1, 0xe9, 0xf3
+.data1 	0x66, 0xa5, 0x11, 0xc9, 0xf3, 0xa4, 0x8b, 0x45
+.data1 	0x08, 0x5f, 0x5e, 0x5d, 0xc3, 0xfd, 0x8d, 0x74
+.data1 	0x0e, 0xff, 0x8d, 0x7c, 0x0f, 0xff, 0xf3, 0xa4
+.data1 	0xfc, 0xeb, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x7d, 0x0c, 0x30, 0xc0, 0x89, 0xca, 0xfc
+.data1 	0xf2, 0xae, 0x29, 0xca, 0x87, 0xca, 0x8b, 0x75
+.data1 	0x0c, 0x8b, 0x7d, 0x08, 0xf3, 0xa4, 0xc3, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x13, 0x8b, 0x4b, 0x04, 0x83, 0xc3, 0x08
+.data1 	0x49, 0x7c, 0x18, 0x3b, 0x03, 0x75, 0xf6, 0x8b
+.data1 	0x5b, 0x04, 0x85, 0xdb, 0x75, 0x0b, 0xb8, 0x14
+.data1 	0x00, 0x00, 0x00, 0x50, 0xe9, 0x07, 0x00, 0x00
+.data1 	0x00, 0xff, 0xe3, 0x89, 0xd3, 0xeb, 0xeb, 0x00
+.data1 	0xe8, 0x0f, 0x00, 0x00, 0x00, 0xe8, 0x02, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0x7f, 0xeb, 0xff
+.data1 	0xff, 0x00, 0x00, 0x00, 0x31, 0xdb, 0x87, 0x1d
+.data1 	0x58, 0x0a, 0x00, 0x00, 0x85, 0xdb, 0x74, 0x05
+.data1 	0x50, 0xff, 0xd3, 0x58, 0xc3, 0x50, 0xe8, 0xe1
+.data1 	0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x73, 0x68, 0x6f, 0x72
+.data1 	0x74, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x00
+.data1 	0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x77, 0x72
+.data1 	0x69, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f
+.data1 	0x20, 0x27, 0x25, 0x73, 0x27, 0x3a, 0x20, 0x25
+.data1 	0x73, 0x0a, 0x00, 0x00, 0x75, 0x6e, 0x65, 0x78
+.data1 	0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x45
+.data1 	0x4f, 0x46, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x20, 0x72, 0x65, 0x61, 0x64, 0x69, 0x6e
+.data1 	0x67, 0x20, 0x27, 0x25, 0x73, 0x27, 0x3a, 0x20
+.data1 	0x25, 0x73, 0x0a, 0x00, 0x2f, 0x64, 0x65, 0x76
+.data1 	0x2f, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4d, 0x49, 0x4f, 0x43, 0x52, 0x41, 0x4d, 0x53
+.data1 	0x49, 0x5a, 0x45, 0x20, 0x25, 0x6c, 0x75, 0x20
+.data1 	0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x6f
+.data1 	0x6e, 0x20, 0x27, 0x25, 0x73, 0x27, 0x3a, 0x20
+.data1 	0x25, 0x73, 0x0a, 0x00, 0x2f, 0x64, 0x65, 0x76
+.data1 	0x2f, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74
+.data1 	0x6f, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x27
+.data1 	0x25, 0x73, 0x27, 0x3a, 0x20, 0x25, 0x73, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x2f, 0x64, 0x65, 0x76
+.data1 	0x2f, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4c, 0x73, 0x65, 0x65, 0x6b, 0x28, 0x30, 0x29
+.data1 	0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20
+.data1 	0x6f, 0x6e, 0x20, 0x27, 0x25, 0x73, 0x27, 0x3a
+.data1 	0x20, 0x25, 0x73, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4c, 0x73, 0x65, 0x65, 0x6b, 0x28, 0x65, 0x6e
+.data1 	0x64, 0x29, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65
+.data1 	0x64, 0x20, 0x6f, 0x6e, 0x20, 0x27, 0x25, 0x73
+.data1 	0x27, 0x3a, 0x20, 0x25, 0x73, 0x0a, 0x00, 0x00
+.data1 	0x55, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74
+.data1 	0x6f, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x27
+.data1 	0x25, 0x73, 0x27, 0x3a, 0x20, 0x25, 0x73, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67
+.data1 	0x65, 0x3a, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x72
+.data1 	0x61, 0x6d, 0x64, 0x69, 0x73, 0x6b, 0x20, 0x3c
+.data1 	0x66, 0x69, 0x6c, 0x65, 0x3e, 0x0a, 0x00, 0x00
+.data1 	0x72, 0x65, 0x61, 0x64, 0x20, 0x66, 0x61, 0x69
+.data1 	0x6c, 0x65, 0x64, 0x20, 0x61, 0x74, 0x20, 0x70
+.data1 	0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20
+.data1 	0x25, 0x6c, 0x75, 0x3a, 0x20, 0x25, 0x73, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x6c, 0x73, 0x65, 0x65
+.data1 	0x6b, 0x20, 0x74, 0x6f, 0x20, 0x25, 0x6c, 0x75
+.data1 	0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x3a
+.data1 	0x20, 0x25, 0x73, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20
+.data1 	0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00
+.data1 	0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c
+.data1 	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x76, 0x61
+.data1 	0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00
+.data1 	0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x6f
+.data1 	0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e
+.data1 	0x20, 0x6f, 0x6e, 0x20, 0x6e, 0x6f, 0x6e, 0x2d
+.data1 	0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x00, 0x00
+.data1 	0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20
+.data1 	0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67
+.data1 	0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61
+.data1 	0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x69
+.data1 	0x6e, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65
+.data1 	0x73, 0x73, 0x00, 0x00, 0x41, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20
+.data1 	0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c
+.data1 	0x65, 0x00, 0x00, 0x00, 0x4f, 0x70, 0x65, 0x72
+.data1 	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e
+.data1 	0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73
+.data1 	0x73, 0x00, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x74
+.data1 	0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x77, 0x72, 0x6f
+.data1 	0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20
+.data1 	0x66, 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x63, 0x6b
+.data1 	0x65, 0x74, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x74
+.data1 	0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x6e, 0x6f, 0x74
+.data1 	0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74
+.data1 	0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x41, 0x46
+.data1 	0x00, 0x00, 0x00, 0x00, 0x41, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x20, 0x66, 0x61, 0x6d, 0x69
+.data1 	0x6c, 0x79, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73
+.data1 	0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x63, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00
+.data1 	0x41, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20
+.data1 	0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x63
+.data1 	0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f
+.data1 	0x6e, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x75
+.data1 	0x72, 0x67, 0x65, 0x6e, 0x74, 0x20, 0x64, 0x61
+.data1 	0x74, 0x61, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65
+.data1 	0x6e, 0x74, 0x00, 0x00, 0x55, 0x72, 0x67, 0x65
+.data1 	0x6e, 0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20
+.data1 	0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x00
+.data1 	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x64
+.data1 	0x20, 0x6f, 0x75, 0x74, 0x00, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x65, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72
+.data1 	0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x00, 0x00
+.data1 	0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20
+.data1 	0x69, 0x6e, 0x20, 0x75, 0x73, 0x65, 0x00, 0x00
+.data1 	0x41, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20
+.data1 	0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x44, 0x65, 0x73, 0x74
+.data1 	0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20
+.data1 	0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x61, 0x63
+.data1 	0x68, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x64, 0x65, 0x73, 0x74
+.data1 	0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20
+.data1 	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x00
+.data1 	0x57, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x6c
+.data1 	0x6f, 0x63, 0x6b, 0x00, 0x42, 0x61, 0x64, 0x20
+.data1 	0x6d, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72
+.data1 	0x20, 0x69, 0x6f, 0x63, 0x74, 0x6c, 0x00, 0x00
+.data1 	0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20
+.data1 	0x69, 0x6f, 0x63, 0x74, 0x6c, 0x20, 0x66, 0x6f
+.data1 	0x72, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x62
+.data1 	0x75, 0x66, 0x66, 0x65, 0x72, 0x73, 0x20, 0x6c
+.data1 	0x65, 0x66, 0x74, 0x00, 0x49, 0x6e, 0x76, 0x61
+.data1 	0x6c, 0x69, 0x64, 0x20, 0x70, 0x61, 0x63, 0x6b
+.data1 	0x65, 0x74, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x00
+.data1 	0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79
+.data1 	0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x20
+.data1 	0x6f, 0x66, 0x20, 0x73, 0x79, 0x6d, 0x62, 0x6f
+.data1 	0x6c, 0x69, 0x63, 0x20, 0x6c, 0x69, 0x6e, 0x6b
+.data1 	0x73, 0x00, 0x00, 0x00, 0x44, 0x69, 0x72, 0x65
+.data1 	0x63, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x6e, 0x6f
+.data1 	0x74, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x00
+.data1 	0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e
+.data1 	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6d, 0x70
+.data1 	0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x6c
+.data1 	0x6f, 0x63, 0x6b, 0x73, 0x20, 0x61, 0x76, 0x61
+.data1 	0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00
+.data1 	0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d
+.data1 	0x65, 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x6f
+.data1 	0x6e, 0x67, 0x00, 0x00, 0x52, 0x65, 0x73, 0x6f
+.data1 	0x75, 0x72, 0x63, 0x65, 0x20, 0x64, 0x65, 0x61
+.data1 	0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x61, 0x76
+.data1 	0x6f, 0x69, 0x64, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x74
+.data1 	0x6f, 0x6f, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4d, 0x61, 0x74, 0x68
+.data1 	0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e
+.data1 	0x74, 0x00, 0x00, 0x00, 0x42, 0x72, 0x6f, 0x6b
+.data1 	0x65, 0x6e, 0x20, 0x70, 0x69, 0x70, 0x65, 0x00
+.data1 	0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79
+.data1 	0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x00, 0x00
+.data1 	0x52, 0x65, 0x61, 0x64, 0x2d, 0x6f, 0x6e, 0x6c
+.data1 	0x79, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x73
+.data1 	0x79, 0x73, 0x74, 0x65, 0x6d, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20
+.data1 	0x73, 0x65, 0x65, 0x6b, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65
+.data1 	0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x6f, 0x6e
+.data1 	0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00
+.data1 	0x46, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6f
+.data1 	0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x00, 0x00
+.data1 	0x54, 0x65, 0x78, 0x74, 0x20, 0x66, 0x69, 0x6c
+.data1 	0x65, 0x20, 0x62, 0x75, 0x73, 0x79, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x74, 0x79
+.data1 	0x70, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72
+.data1 	0x00, 0x00, 0x00, 0x00, 0x54, 0x6f, 0x6f, 0x20
+.data1 	0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6f, 0x70, 0x65
+.data1 	0x6e, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x00
+.data1 	0x46, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x61, 0x62
+.data1 	0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x66
+.data1 	0x6c, 0x6f, 0x77, 0x00, 0x49, 0x6e, 0x76, 0x61
+.data1 	0x6c, 0x69, 0x64, 0x20, 0x61, 0x72, 0x67, 0x75
+.data1 	0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00
+.data1 	0x49, 0x73, 0x20, 0x61, 0x20, 0x64, 0x69, 0x72
+.data1 	0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x64, 0x69
+.data1 	0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00
+.data1 	0x43, 0x72, 0x6f, 0x73, 0x73, 0x2d, 0x64, 0x65
+.data1 	0x76, 0x69, 0x63, 0x65, 0x20, 0x6c, 0x69, 0x6e
+.data1 	0x6b, 0x00, 0x00, 0x00, 0x46, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x00
+.data1 	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65
+.data1 	0x20, 0x62, 0x75, 0x73, 0x79, 0x00, 0x00, 0x00
+.data1 	0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x64, 0x65
+.data1 	0x76, 0x69, 0x63, 0x65, 0x20, 0x72, 0x65, 0x71
+.data1 	0x75, 0x69, 0x72, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x61, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x00, 0x50, 0x65, 0x72, 0x6d
+.data1 	0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x64
+.data1 	0x65, 0x6e, 0x69, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x65, 0x6e, 0x6f, 0x75
+.data1 	0x67, 0x68, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x00
+.data1 	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65
+.data1 	0x20, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61
+.data1 	0x72, 0x69, 0x6c, 0x79, 0x20, 0x75, 0x6e, 0x61
+.data1 	0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x63
+.data1 	0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x66, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x00
+.data1 	0x45, 0x78, 0x65, 0x63, 0x20, 0x66, 0x6f, 0x72
+.data1 	0x6d, 0x61, 0x74, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0x41, 0x72, 0x67, 0x20
+.data1 	0x6c, 0x69, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x6f
+.data1 	0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x6f
+.data1 	0x72, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73
+.data1 	0x73, 0x00, 0x00, 0x00, 0x49, 0x2f, 0x4f, 0x20
+.data1 	0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70
+.data1 	0x74, 0x65, 0x64, 0x20, 0x73, 0x79, 0x73, 0x74
+.data1 	0x65, 0x6d, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x66, 0x69, 0x6c, 0x65, 0x20, 0x6f, 0x72, 0x20
+.data1 	0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72
+.data1 	0x79, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x6f, 0x77, 0x6e, 0x65, 0x72, 0x00, 0x00, 0x00
+.data1 	0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x30, 0x00
+.data1 	0xfd, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0xa1, 0x05, 0x00, 0x00
+.data1 	0x40, 0x00, 0x00, 0x00, 0xd6, 0x05, 0x00, 0x00
+.data1 	0xfa, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00
+.data1 	0x58, 0x00, 0x00, 0x00, 0xe3, 0x06, 0x00, 0x00
+.data1 	0x62, 0x00, 0x00, 0x00, 0xc8, 0x06, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0xda, 0x06, 0x00, 0x00
+.data1 	0x69, 0x00, 0x00, 0x00, 0xda, 0x06, 0x00, 0x00
+.data1 	0x6f, 0x00, 0x00, 0x00, 0xd1, 0x06, 0x00, 0x00
+.data1 	0x70, 0x00, 0x00, 0x00, 0xe3, 0x06, 0x00, 0x00
+.data1 	0x75, 0x00, 0x00, 0x00, 0xda, 0x06, 0x00, 0x00
+.data1 	0x78, 0x00, 0x00, 0x00, 0xe3, 0x06, 0x00, 0x00
+.data1 	0xd3, 0x07, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0xc4, 0x07, 0x00, 0x00
+.data1 	0x23, 0x00, 0x00, 0x00, 0xc9, 0x07, 0x00, 0x00
+.data1 	0x2b, 0x00, 0x00, 0x00, 0xbf, 0x07, 0x00, 0x00
+.data1 	0x2d, 0x00, 0x00, 0x00, 0xba, 0x07, 0x00, 0x00
+.data1 	0x30, 0x00, 0x00, 0x00, 0xce, 0x07, 0x00, 0x00
+.data1 	0xc5, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
+.data1 	0x4c, 0x00, 0x00, 0x00, 0xad, 0x08, 0x00, 0x00
+.data1 	0x68, 0x00, 0x00, 0x00, 0x97, 0x08, 0x00, 0x00
+.data1 	0x6c, 0x00, 0x00, 0x00, 0xa2, 0x08, 0x00, 0x00
+.data1 	0xcb, 0x08, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00
+.data1 	0x45, 0x00, 0x00, 0x00, 0x61, 0x0a, 0x00, 0x00
+.data1 	0x47, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x00, 0x00
+.data1 	0x58, 0x00, 0x00, 0x00, 0xb7, 0x09, 0x00, 0x00
+.data1 	0x62, 0x00, 0x00, 0x00, 0xb7, 0x09, 0x00, 0x00
+.data1 	0x63, 0x00, 0x00, 0x00, 0x33, 0x0a, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0xf5, 0x09, 0x00, 0x00
+.data1 	0x65, 0x00, 0x00, 0x00, 0x61, 0x0a, 0x00, 0x00
+.data1 	0x66, 0x00, 0x00, 0x00, 0x61, 0x0a, 0x00, 0x00
+.data1 	0x67, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x00, 0x00
+.data1 	0x69, 0x00, 0x00, 0x00, 0xf5, 0x09, 0x00, 0x00
+.data1 	0x6e, 0x00, 0x00, 0x00, 0x1b, 0x09, 0x00, 0x00
+.data1 	0x6f, 0x00, 0x00, 0x00, 0xb7, 0x09, 0x00, 0x00
+.data1 	0x70, 0x00, 0x00, 0x00, 0xb7, 0x09, 0x00, 0x00
+.data1 	0x72, 0x00, 0x00, 0x00, 0xa5, 0x0a, 0x00, 0x00
+.data1 	0x73, 0x00, 0x00, 0x00, 0x71, 0x09, 0x00, 0x00
+.data1 	0x75, 0x00, 0x00, 0x00, 0xb7, 0x09, 0x00, 0x00
+.data1 	0x78, 0x00, 0x00, 0x00, 0xb7, 0x09, 0x00, 0x00
+.data1 	0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x00, 0x00
+.data1 	0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x70
+.data1 	0x72, 0x69, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x6f
+.data1 	0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x6f
+.data1 	0x69, 0x6e, 0x74, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x70, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x53, 0x53, 0x53, 0x53
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x74, 0x08, 0x00, 0x00
+.data1 	0x8c, 0x08, 0x00, 0x00, 0xa4, 0x08, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0xf0, 0x06, 0x00, 0x00
+.data1 	0xe4, 0x06, 0x00, 0x00, 0xc8, 0x06, 0x00, 0x00
+.data1 	0xb8, 0x06, 0x00, 0x00, 0xa0, 0x06, 0x00, 0x00
+.data1 	0x94, 0x06, 0x00, 0x00, 0x78, 0x06, 0x00, 0x00
+.data1 	0x64, 0x06, 0x00, 0x00, 0x50, 0x06, 0x00, 0x00
+.data1 	0x40, 0x06, 0x00, 0x00, 0x34, 0x06, 0x00, 0x00
+.data1 	0x10, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00
+.data1 	0xec, 0x05, 0x00, 0x00, 0xe0, 0x05, 0x00, 0x00
+.data1 	0xc8, 0x05, 0x00, 0x00, 0xb8, 0x05, 0x00, 0x00
+.data1 	0xac, 0x05, 0x00, 0x00, 0x98, 0x05, 0x00, 0x00
+.data1 	0x88, 0x05, 0x00, 0x00, 0x78, 0x05, 0x00, 0x00
+.data1 	0x68, 0x05, 0x00, 0x00, 0x54, 0x05, 0x00, 0x00
+.data1 	0x40, 0x05, 0x00, 0x00, 0x2c, 0x05, 0x00, 0x00
+.data1 	0x18, 0x05, 0x00, 0x00, 0x08, 0x05, 0x00, 0x00
+.data1 	0xf8, 0x04, 0x00, 0x00, 0xe0, 0x04, 0x00, 0x00
+.data1 	0xd0, 0x04, 0x00, 0x00, 0xb8, 0x04, 0x00, 0x00
+.data1 	0xa8, 0x04, 0x00, 0x00, 0x9c, 0x04, 0x00, 0x00
+.data1 	0x8c, 0x04, 0x00, 0x00, 0x78, 0x04, 0x00, 0x00
+.data1 	0x5c, 0x04, 0x00, 0x00, 0x48, 0x04, 0x00, 0x00
+.data1 	0x34, 0x04, 0x00, 0x00, 0x18, 0x04, 0x00, 0x00
+.data1 	0x04, 0x04, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00
+.data1 	0x0c, 0x09, 0x00, 0x00, 0x0c, 0x09, 0x00, 0x00
+.data1 	0x0c, 0x09, 0x00, 0x00, 0x0c, 0x09, 0x00, 0x00
+.data1 	0x0c, 0x09, 0x00, 0x00, 0x0c, 0x09, 0x00, 0x00
+.data1 	0x0c, 0x09, 0x00, 0x00, 0x0c, 0x09, 0x00, 0x00
+.data1 	0x0c, 0x09, 0x00, 0x00, 0xcc, 0x03, 0x00, 0x00
+.data1 	0xb4, 0x03, 0x00, 0x00, 0x98, 0x03, 0x00, 0x00
+.data1 	0x84, 0x03, 0x00, 0x00, 0x78, 0x03, 0x00, 0x00
+.data1 	0x60, 0x03, 0x00, 0x00, 0x44, 0x03, 0x00, 0x00
+.data1 	0x30, 0x03, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00
+.data1 	0x0c, 0x03, 0x00, 0x00, 0xf8, 0x02, 0x00, 0x00
+.data1 	0xe0, 0x02, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x00
+.data1 	0xb4, 0x02, 0x00, 0x00, 0xa4, 0x02, 0x00, 0x00
+.data1 	0x90, 0x02, 0x00, 0x00, 0x7c, 0x02, 0x00, 0x00
+.data1 	0x5c, 0x02, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x00
+.data1 	0x1c, 0x02, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00
+.data1 	0xec, 0x01, 0x00, 0x00, 0xcc, 0x01, 0x00, 0x00
+.data1 	0xb8, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00
+.data1 	0x80, 0x01, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0xf4, 0x32, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x03, 0x20, 0x10, 0x20, 0x00, 0x00, 0x00
+.data1 	0x30, 0x15, 0x00, 0x00, 0x34, 0x09, 0x00, 0x00
+.data1 	0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc8, 0x09, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0xed, 0x8b, 0x04, 0x24, 0x8d, 0x54, 0x24
+.data1 	0x04, 0x8d, 0x4c, 0x84, 0x08, 0xbb, 0x40, 0x07
+.data1 	0x00, 0x00, 0x81, 0xfb, 0x34, 0x09, 0x00, 0x00
+.data1 	0x73, 0x13, 0xf6, 0xc3, 0x03, 0x75, 0x0e, 0x81
+.data1 	0x3b, 0x53, 0x53, 0x53, 0x53, 0x75, 0x06, 0x89
+.data1 	0x1d, 0x34, 0x07, 0x00, 0x00, 0x8b, 0x1d, 0x34
+.data1 	0x07, 0x00, 0x00, 0x89, 0x0b, 0x51, 0x52, 0x50
+.data1 	0x0f, 0x01, 0xe0, 0xa8, 0x04, 0x0f, 0x94, 0x05
+.data1 	0x40, 0x09, 0x00, 0x00, 0xe8, 0x07, 0x00, 0x00
+.data1 	0x00, 0x50, 0xe8, 0x8e, 0x00, 0x00, 0x00, 0xf4
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x83, 0x7d
+.data1 	0x08, 0x02, 0x74, 0x19, 0x68, 0x24, 0x00, 0x00
+.data1 	0x00, 0x68, 0x78, 0x07, 0x00, 0x00, 0xe8, 0xb9
+.data1 	0x00, 0x00, 0x00, 0x59, 0x59, 0x6a, 0x01, 0xe8
+.data1 	0x69, 0x00, 0x00, 0x00, 0x59, 0x8b, 0x55, 0x0c
+.data1 	0x8b, 0x52, 0x04, 0x89, 0x55, 0xf8, 0x6a, 0x00
+.data1 	0x68, 0x20, 0x00, 0x00, 0x00, 0xff, 0x75, 0xf8
+.data1 	0xe8, 0xbf, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0x45, 0xfc, 0x85, 0xc0, 0x74, 0x27, 0xff
+.data1 	0x35, 0x44, 0x07, 0x00, 0x00, 0xe8, 0x5e, 0x00
+.data1 	0x00, 0x00, 0x59, 0x50, 0x68, 0x04, 0x00, 0x00
+.data1 	0x00, 0x68, 0x78, 0x07, 0x00, 0x00, 0xe8, 0x71
+.data1 	0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x6a, 0x01
+.data1 	0xe8, 0x20, 0x00, 0x00, 0x00, 0x59, 0x31, 0xc0
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x35, 0x38, 0x07, 0x00, 0x00, 0x4e, 0x78
+.data1 	0x09, 0xff, 0x14, 0xb5, 0x48, 0x09, 0x00, 0x00
+.data1 	0xeb, 0xf4, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0xe8, 0xdf, 0xff, 0xff, 0xff, 0x83, 0x3d, 0x3c
+.data1 	0x07, 0x00, 0x00, 0x00, 0x74, 0x06, 0xff, 0x15
+.data1 	0x3c, 0x07, 0x00, 0x00, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x48, 0x00, 0x00, 0x00, 0x59, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x75, 0x08, 0x85
+.data1 	0xf6, 0x78, 0x08, 0x39, 0x35, 0x20, 0x09, 0x00
+.data1 	0x00, 0x7f, 0x07, 0xb8, 0x44, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x07, 0x8b, 0x04, 0xb5, 0xf0, 0x07, 0x00
+.data1 	0x00, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x08, 0x8d, 0x55, 0x10, 0x89, 0x55, 0xfc
+.data1 	0xff, 0x75, 0x08, 0xff, 0x75, 0xfc, 0xff, 0x75
+.data1 	0x0c, 0xe8, 0x88, 0x02, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0xc9, 0xc3, 0x00, 0xe9, 0x0b, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0x2b, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe0
+.data1 	0x8d, 0x45, 0xd8, 0x50, 0x6a, 0x01, 0x6a, 0x00
+.data1 	0xe8, 0x97, 0x0f, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xba, 0xff, 0xff, 0xff, 0xff, 0x89, 0x55, 0xfc
+.data1 	0xff, 0xd2, 0xeb, 0xfe, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0xff, 0x75, 0x08, 0xe8, 0x92, 0x0b
+.data1 	0x00, 0x00, 0x59, 0x05, 0x01, 0x00, 0x00, 0x00
+.data1 	0x89, 0x45, 0xe4, 0xff, 0x75, 0x0c, 0xe8, 0x81
+.data1 	0x0b, 0x00, 0x00, 0x59, 0x05, 0x01, 0x00, 0x00
+.data1 	0x00, 0x89, 0x45, 0xe8, 0x8b, 0x55, 0x10, 0x89
+.data1 	0x55, 0xec, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xf0
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf4, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0x6a, 0x15, 0x6a, 0x01, 0xe8, 0x41
+.data1 	0x0f, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x56, 0x57
+.data1 	0x8b, 0x75, 0x08, 0x80, 0x3e, 0x2a, 0x75, 0x18
+.data1 	0x8b, 0x45, 0x10, 0x8b, 0x10, 0x83, 0xc2, 0x04
+.data1 	0x8b, 0x45, 0x10, 0x89, 0x10, 0x8b, 0x52, 0xfc
+.data1 	0x8b, 0x45, 0x0c, 0x89, 0x10, 0x46, 0xeb, 0x25
+.data1 	0x31, 0xff, 0x0f, 0xbe, 0x06, 0x2d, 0x30, 0x00
+.data1 	0x00, 0x00, 0x89, 0x45, 0xf8, 0x78, 0x11, 0x83
+.data1 	0x7d, 0xf8, 0x09, 0x7f, 0x0b, 0x6b, 0xdf, 0x0a
+.data1 	0x8b, 0x7d, 0xf8, 0x01, 0xdf, 0x46, 0xeb, 0xe2
+.data1 	0x8b, 0x45, 0x0c, 0x89, 0x38, 0x89, 0xf0, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x10, 0x56, 0x57, 0x8b, 0x75, 0x10, 0x8b, 0x7d
+.data1 	0x08, 0x89, 0x75, 0xf4, 0xe9, 0x80, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7d, 0x1c, 0x00, 0x74, 0x18, 0x8b
+.data1 	0x17, 0x83, 0xc2, 0x04, 0x89, 0x17, 0x8b, 0x42
+.data1 	0xfc, 0x0f, 0xbf, 0xc0, 0x0f, 0xbf, 0xc0, 0x89
+.data1 	0x45, 0xfc, 0xe9, 0x76, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x17, 0x83, 0xc2, 0x04, 0x89, 0x17, 0xb9, 0xff
+.data1 	0xff, 0x00, 0x00, 0x23, 0x4a, 0xfc, 0x89, 0x4d
+.data1 	0xf8, 0xe9, 0x5f, 0x00, 0x00, 0x00, 0x83, 0x7d
+.data1 	0x1c, 0x00, 0x74, 0x12, 0x8b, 0x17, 0x83, 0xc2
+.data1 	0x04, 0x89, 0x17, 0x8b, 0x52, 0xfc, 0x89, 0x55
+.data1 	0xfc, 0xe9, 0x47, 0x00, 0x00, 0x00, 0x8b, 0x17
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x17, 0x8b, 0x52, 0xfc
+.data1 	0x89, 0x55, 0xf8, 0xeb, 0x38, 0x83, 0x7d, 0x1c
+.data1 	0x00, 0x74, 0x0f, 0x8b, 0x17, 0x83, 0xc2, 0x04
+.data1 	0x89, 0x17, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xfc
+.data1 	0xeb, 0x23, 0x8b, 0x17, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x17, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xf8, 0xeb
+.data1 	0x14, 0xba, 0x60, 0x00, 0x00, 0x00, 0x23, 0x55
+.data1 	0x0c, 0xbb, 0xcc, 0x05, 0x00, 0x00, 0x89, 0xd0
+.data1 	0xe9, 0x17, 0x12, 0x00, 0x00, 0x83, 0x7d, 0x1c
+.data1 	0x00, 0x74, 0x2f, 0x83, 0x7d, 0xfc, 0x00, 0x79
+.data1 	0x09, 0xc6, 0x06, 0x2d, 0x46, 0xf7, 0x5d, 0xfc
+.data1 	0xeb, 0x1a, 0x8b, 0x55, 0x0c, 0xf6, 0xc2, 0x02
+.data1 	0x74, 0x06, 0xc6, 0x06, 0x2b, 0x46, 0xeb, 0x0c
+.data1 	0x8b, 0x55, 0x0c, 0xf6, 0xc2, 0x04, 0x74, 0x04
+.data1 	0xc6, 0x06, 0x20, 0x46, 0x8b, 0x55, 0xfc, 0x89
+.data1 	0x55, 0xf8, 0x8b, 0x55, 0x0c, 0xf6, 0xc2, 0x08
+.data1 	0x74, 0x0a, 0x80, 0x7d, 0x14, 0x6f, 0x75, 0x04
+.data1 	0xc6, 0x06, 0x30, 0x46, 0x83, 0x7d, 0xf8, 0x00
+.data1 	0x75, 0x11, 0x83, 0x7d, 0x18, 0x00, 0x0f, 0x85
+.data1 	0x60, 0x00, 0x00, 0x00, 0x89, 0xf0, 0xe9, 0x9f
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0xf6, 0xc2
+.data1 	0x08, 0x74, 0x0c, 0x80, 0x7d, 0x14, 0x78, 0x74
+.data1 	0x0c, 0x80, 0x7d, 0x14, 0x58, 0x74, 0x06, 0x80
+.data1 	0x7d, 0x14, 0x70, 0x75, 0x3f, 0xc6, 0x06, 0x30
+.data1 	0x46, 0x80, 0x7d, 0x14, 0x58, 0x75, 0x07, 0xb8
+.data1 	0x58, 0x00, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0x78
+.data1 	0x00, 0x00, 0x00, 0x88, 0x06, 0x46, 0xeb, 0x24
+.data1 	0xc7, 0x45, 0xf0, 0x02, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x29, 0xc7, 0x45, 0xf0, 0x08, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x20, 0xc7, 0x45, 0xf0, 0x0a, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x17, 0xc7, 0x45, 0xf0, 0x10, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x0e, 0x0f, 0xbe, 0x45, 0x14
+.data1 	0xbb, 0xe4, 0x05, 0x00, 0x00, 0xe9, 0x52, 0x11
+.data1 	0x00, 0x00, 0xff, 0x75, 0x18, 0x56, 0xff, 0x75
+.data1 	0xf0, 0xff, 0x75, 0xf8, 0xe8, 0x2b, 0x09, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x10, 0x89, 0xc6, 0x80, 0x7d
+.data1 	0x14, 0x58, 0x75, 0x1c, 0x39, 0x75, 0xf4, 0x74
+.data1 	0x17, 0x8b, 0x55, 0xf4, 0x0f, 0xbe, 0x02, 0x50
+.data1 	0xe8, 0xa7, 0x0c, 0x00, 0x00, 0x59, 0x8b, 0x55
+.data1 	0xf4, 0x88, 0x02, 0xff, 0x45, 0xf4, 0xeb, 0xe4
+.data1 	0x89, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x81, 0xec, 0x34, 0x04, 0x00, 0x00, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x10, 0xc7, 0x45, 0xd8, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x45, 0x08, 0xff, 0x45
+.data1 	0x08, 0x0f, 0xbe, 0x00, 0x89, 0x45, 0xf0, 0x85
+.data1 	0xc0, 0x0f, 0x84, 0x0b, 0x06, 0x00, 0x00, 0x83
+.data1 	0x7d, 0xf0, 0x25, 0x0f, 0x84, 0x4d, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x16, 0x4a, 0x89, 0x16, 0x78, 0x13
+.data1 	0x8b, 0x55, 0xf0, 0x0f, 0xb6, 0xca, 0x8b, 0x46
+.data1 	0x14, 0x83, 0x46, 0x14, 0x01, 0x88, 0x08, 0x89
+.data1 	0xc8, 0xeb, 0x0b, 0x56, 0xff, 0x75, 0xf0, 0xe8
+.data1 	0x24, 0x06, 0x00, 0x00, 0x59, 0x59, 0x3d, 0xff
+.data1 	0xff, 0xff, 0xff, 0x75, 0x1c, 0x83, 0x7d, 0xd8
+.data1 	0x00, 0x74, 0x0c, 0x8b, 0x55, 0xd8, 0xf7, 0xda
+.data1 	0x89, 0xd0, 0xe9, 0xc6, 0x05, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe9, 0xbc, 0x05, 0x00
+.data1 	0x00, 0xff, 0x45, 0xd8, 0xeb, 0x95, 0x31, 0xff
+.data1 	0xeb, 0x21, 0x83, 0xcf, 0x01, 0xeb, 0x2c, 0x83
+.data1 	0xcf, 0x02, 0xeb, 0x27, 0x83, 0xcf, 0x04, 0xeb
+.data1 	0x22, 0x83, 0xcf, 0x08, 0xeb, 0x1d, 0x83, 0xcf
+.data1 	0x10, 0xeb, 0x18, 0x81, 0xcf, 0x00, 0x10, 0x00
+.data1 	0x00, 0xeb, 0x13, 0x8b, 0x55, 0x08, 0x0f, 0xbe
+.data1 	0x02, 0xbb, 0x2c, 0x06, 0x00, 0x00, 0xe9, 0x61
+.data1 	0x10, 0x00, 0x00, 0xff, 0x45, 0x08, 0xf7, 0xc7
+.data1 	0x00, 0x10, 0x00, 0x00, 0x74, 0xe5, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xd4, 0x8d, 0x45, 0x0c, 0x50
+.data1 	0x8d, 0x45, 0xec, 0x50, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x2c, 0xfd, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0x45, 0x08, 0x39, 0x45, 0xd4, 0x74, 0x06, 0x81
+.data1 	0xcf, 0x00, 0x01, 0x00, 0x00, 0x8b, 0x55, 0x08
+.data1 	0x80, 0x3a, 0x2e, 0x75, 0x2b, 0xff, 0x45, 0x08
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xd4, 0x8d, 0x45
+.data1 	0x0c, 0x50, 0x8d, 0x45, 0xe8, 0x50, 0xff, 0x75
+.data1 	0x08, 0xe8, 0xfa, 0xfc, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0x89, 0x45, 0x08, 0x83, 0x7d, 0xe8, 0x00
+.data1 	0x78, 0x06, 0x81, 0xcf, 0x00, 0x02, 0x00, 0x00
+.data1 	0xf7, 0xc7, 0x00, 0x01, 0x00, 0x00, 0x74, 0x0c
+.data1 	0x83, 0x7d, 0xec, 0x00, 0x79, 0x06, 0xf7, 0x5d
+.data1 	0xec, 0x83, 0xcf, 0x01, 0xf7, 0xc7, 0x00, 0x01
+.data1 	0x00, 0x00, 0x75, 0x07, 0xc7, 0x45, 0xec, 0x00
+.data1 	0x00, 0x00, 0x00, 0xf7, 0xc7, 0x02, 0x00, 0x00
+.data1 	0x00, 0x74, 0x03, 0x83, 0xe7, 0xfb, 0xf7, 0xc7
+.data1 	0x01, 0x00, 0x00, 0x00, 0x74, 0x03, 0x83, 0xe7
+.data1 	0xef, 0x8d, 0x95, 0xcf, 0xfb, 0xff, 0xff, 0x89
+.data1 	0x55, 0xd0, 0x89, 0x55, 0xfc, 0xeb, 0x24, 0x83
+.data1 	0xcf, 0x20, 0xff, 0x45, 0x08, 0xe9, 0x23, 0x02
+.data1 	0x00, 0x00, 0x83, 0xcf, 0x40, 0xff, 0x45, 0x08
+.data1 	0xe9, 0x18, 0x02, 0x00, 0x00, 0x81, 0xcf, 0x80
+.data1 	0x00, 0x00, 0x00, 0xff, 0x45, 0x08, 0xe9, 0x0a
+.data1 	0x02, 0x00, 0x00, 0x8b, 0x55, 0x08, 0x0f, 0xbe
+.data1 	0x02, 0xbb, 0x5c, 0x06, 0x00, 0x00, 0xe9, 0x81
+.data1 	0x0f, 0x00, 0x00, 0x8b, 0x16, 0x4a, 0x89, 0x16
+.data1 	0x78, 0x13, 0x8b, 0x55, 0xf0, 0x0f, 0xb6, 0xca
+.data1 	0x8b, 0x46, 0x14, 0x83, 0x46, 0x14, 0x01, 0x88
+.data1 	0x08, 0x89, 0xc8, 0xeb, 0x0b, 0x56, 0xff, 0x75
+.data1 	0xf0, 0xe8, 0xc2, 0x04, 0x00, 0x00, 0x59, 0x59
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x1c, 0x83
+.data1 	0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b, 0x55, 0xd8
+.data1 	0xf7, 0xda, 0x89, 0xd0, 0xe9, 0x64, 0x04, 0x00
+.data1 	0x00, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x5a
+.data1 	0x04, 0x00, 0x00, 0xff, 0x45, 0xd8, 0xe9, 0x30
+.data1 	0xfe, 0xff, 0xff, 0xf7, 0xc7, 0x20, 0x00, 0x00
+.data1 	0x00, 0x74, 0x1a, 0x8b, 0x45, 0xd8, 0x0f, 0xbf
+.data1 	0xc0, 0x8b, 0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x66, 0x89, 0x02
+.data1 	0xe9, 0x0e, 0xfe, 0xff, 0xff, 0xf7, 0xc7, 0x40
+.data1 	0x00, 0x00, 0x00, 0x74, 0x16, 0x8b, 0x55, 0x0c
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c, 0x8b, 0x52
+.data1 	0xfc, 0x8b, 0x4d, 0xd8, 0x89, 0x0a, 0xe9, 0xf0
+.data1 	0xfd, 0xff, 0xff, 0x8b, 0x55, 0x0c, 0x83, 0xc2
+.data1 	0x04, 0x89, 0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x8b
+.data1 	0x4d, 0xd8, 0x89, 0x0a, 0xe9, 0xda, 0xfd, 0xff
+.data1 	0xff, 0x8b, 0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xd0
+.data1 	0x85, 0xd2, 0x75, 0x07, 0xc7, 0x45, 0xd0, 0x0c
+.data1 	0x07, 0x00, 0x00, 0x8b, 0x55, 0xd0, 0x89, 0x55
+.data1 	0xfc, 0x83, 0x7d, 0xe8, 0x00, 0x75, 0x0c, 0xf7
+.data1 	0xc7, 0x00, 0x02, 0x00, 0x00, 0x0f, 0x85, 0x38
+.data1 	0x01, 0x00, 0x00, 0x8b, 0x55, 0xfc, 0x80, 0x3a
+.data1 	0x00, 0x0f, 0x84, 0x2c, 0x01, 0x00, 0x00, 0xff
+.data1 	0x45, 0xfc, 0xff, 0x4d, 0xe8, 0xeb, 0xda, 0xf7
+.data1 	0xc7, 0x00, 0x02, 0x00, 0x00, 0x75, 0x09, 0xc7
+.data1 	0x45, 0xe8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x09
+.data1 	0x83, 0x7d, 0xf0, 0x70, 0x74, 0x03, 0x83, 0xe7
+.data1 	0xef, 0x8b, 0x45, 0xf0, 0x0f, 0xbe, 0xc0, 0x6a
+.data1 	0x00, 0xff, 0x75, 0xe8, 0x50, 0xff, 0x75, 0xfc
+.data1 	0x57, 0x8d, 0x45, 0x0c, 0x50, 0xe8, 0xa1, 0xfb
+.data1 	0xff, 0xff, 0x83, 0xc4, 0x18, 0x89, 0x45, 0xfc
+.data1 	0xe9, 0xe6, 0x00, 0x00, 0x00, 0x81, 0xcf, 0x00
+.data1 	0x04, 0x00, 0x00, 0xf7, 0xc7, 0x00, 0x02, 0x00
+.data1 	0x00, 0x75, 0x09, 0xc7, 0x45, 0xe8, 0x01, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x03, 0x83, 0xe7, 0xef, 0x8b
+.data1 	0x45, 0xf0, 0x0f, 0xbe, 0xc0, 0x6a, 0x01, 0xff
+.data1 	0x75, 0xe8, 0x50, 0xff, 0x75, 0xfc, 0x57, 0x8d
+.data1 	0x45, 0x0c, 0x50, 0xe8, 0x63, 0xfb, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x18, 0x89, 0x45, 0xfc, 0xe9, 0xa8
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0x83, 0xc2
+.data1 	0x04, 0x89, 0x55, 0x0c, 0x8b, 0x4d, 0xfc, 0x8b
+.data1 	0x52, 0xfc, 0x88, 0x11, 0xff, 0x45, 0xfc, 0xe9
+.data1 	0x8f, 0x00, 0x00, 0x00, 0xf7, 0xc7, 0x00, 0x02
+.data1 	0x00, 0x00, 0x74, 0x0d, 0x83, 0x7d, 0xe8, 0x00
+.data1 	0x75, 0x07, 0xc7, 0x45, 0xe8, 0x01, 0x00, 0x00
+.data1 	0x00, 0xf7, 0xc7, 0x00, 0x02, 0x00, 0x00, 0x75
+.data1 	0x07, 0xc7, 0x45, 0xe8, 0x06, 0x00, 0x00, 0x00
+.data1 	0x81, 0x7d, 0xe8, 0x01, 0x04, 0x00, 0x00, 0x72
+.data1 	0x07, 0xc7, 0x45, 0xe8, 0x00, 0x04, 0x00, 0x00
+.data1 	0x81, 0xcf, 0x00, 0x04, 0x00, 0x00, 0x8b, 0x45
+.data1 	0xf0, 0x0f, 0xbe, 0xc0, 0xff, 0x75, 0xe8, 0x50
+.data1 	0xff, 0x75, 0xfc, 0x57, 0x8d, 0x45, 0x0c, 0x50
+.data1 	0xe8, 0xff, 0x05, 0x00, 0x00, 0x83, 0xc4, 0x14
+.data1 	0x89, 0x45, 0xfc, 0xeb, 0x36, 0x8b, 0x55, 0x0c
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0x08
+.data1 	0xe9, 0x86, 0xfc, 0xff, 0xff, 0x8b, 0x45, 0x08
+.data1 	0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0x45
+.data1 	0xf0, 0xbb, 0x7c, 0x06, 0x00, 0x00, 0xe9, 0x71
+.data1 	0x0d, 0x00, 0x00, 0xc7, 0x45, 0xe4, 0x20, 0x00
+.data1 	0x00, 0x00, 0xf7, 0xc7, 0x10, 0x00, 0x00, 0x00
+.data1 	0x74, 0x07, 0xc7, 0x45, 0xe4, 0x30, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xfc, 0x2b, 0x55, 0xd0, 0x89
+.data1 	0x55, 0xf8, 0xc7, 0x45, 0xdc, 0x00, 0x00, 0x00
+.data1 	0x00, 0xf7, 0xc7, 0x10, 0x00, 0x00, 0x00, 0x74
+.data1 	0x37, 0x83, 0x7d, 0xf0, 0x78, 0x74, 0x06, 0x83
+.data1 	0x7d, 0xf0, 0x58, 0x75, 0x08, 0xf7, 0xc7, 0x08
+.data1 	0x00, 0x00, 0x00, 0x75, 0x20, 0x83, 0x7d, 0xf0
+.data1 	0x70, 0x74, 0x1a, 0xf7, 0xc7, 0x00, 0x04, 0x00
+.data1 	0x00, 0x74, 0x15, 0x8b, 0x55, 0xd0, 0x80, 0x3a
+.data1 	0x2b, 0x74, 0x0a, 0x80, 0x3a, 0x2d, 0x74, 0x05
+.data1 	0x80, 0x3a, 0x20, 0x75, 0x03, 0xff, 0x45, 0xdc
+.data1 	0x8b, 0x55, 0xec, 0x2b, 0x55, 0xf8, 0x89, 0x55
+.data1 	0xf4, 0x85, 0xd2, 0x0f, 0x8e, 0x61, 0x01, 0x00
+.data1 	0x00, 0xf7, 0xc7, 0x01, 0x00, 0x00, 0x00, 0x0f
+.data1 	0x85, 0x55, 0x01, 0x00, 0x00, 0x8b, 0x55, 0xf4
+.data1 	0x01, 0x55, 0xd8, 0x83, 0x7d, 0xdc, 0x00, 0x0f
+.data1 	0x84, 0xf8, 0x00, 0x00, 0x00, 0xf7, 0xc7, 0x00
+.data1 	0x04, 0x00, 0x00, 0x0f, 0x84, 0x5c, 0x00, 0x00
+.data1 	0x00, 0xff, 0x4d, 0xf8, 0xff, 0x45, 0xd8, 0x8b
+.data1 	0x16, 0x4a, 0x89, 0x16, 0x78, 0x16, 0x8b, 0x45
+.data1 	0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xb6, 0x10, 0x8b
+.data1 	0x46, 0x14, 0x83, 0x46, 0x14, 0x01, 0x88, 0x10
+.data1 	0x89, 0xd0, 0xeb, 0x12, 0x8b, 0x45, 0xd0, 0xff
+.data1 	0x45, 0xd0, 0x0f, 0xbe, 0x00, 0x56, 0x50, 0xe8
+.data1 	0x04, 0x02, 0x00, 0x00, 0x59, 0x59, 0x3d, 0xff
+.data1 	0xff, 0xff, 0xff, 0x0f, 0x85, 0xac, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b
+.data1 	0x55, 0xd8, 0xf7, 0xda, 0x89, 0xd0, 0xe9, 0xa2
+.data1 	0x01, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x98, 0x01, 0x00, 0x00, 0x83, 0x6d, 0xf8
+.data1 	0x02, 0x83, 0x45, 0xd8, 0x02, 0x8b, 0x16, 0x4a
+.data1 	0x89, 0x16, 0x78, 0x16, 0x8b, 0x45, 0xd0, 0xff
+.data1 	0x45, 0xd0, 0x0f, 0xb6, 0x10, 0x8b, 0x46, 0x14
+.data1 	0x83, 0x46, 0x14, 0x01, 0x88, 0x10, 0x89, 0xd0
+.data1 	0xeb, 0x12, 0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0
+.data1 	0x0f, 0xbe, 0x00, 0x56, 0x50, 0xe8, 0xa6, 0x01
+.data1 	0x00, 0x00, 0x59, 0x59, 0x3d, 0xff, 0xff, 0xff
+.data1 	0xff, 0x74, 0x36, 0x8b, 0x16, 0x4a, 0x89, 0x16
+.data1 	0x78, 0x16, 0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0
+.data1 	0x0f, 0xb6, 0x10, 0x8b, 0x46, 0x14, 0x83, 0x46
+.data1 	0x14, 0x01, 0x88, 0x10, 0x89, 0xd0, 0xeb, 0x12
+.data1 	0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xbe
+.data1 	0x00, 0x56, 0x50, 0xe8, 0x70, 0x01, 0x00, 0x00
+.data1 	0x59, 0x59, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x1c, 0x83, 0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b
+.data1 	0x55, 0xd8, 0xf7, 0xda, 0x89, 0xd0, 0xe9, 0x12
+.data1 	0x01, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x08, 0x01, 0x00, 0x00, 0x8b, 0x16, 0x4a
+.data1 	0x89, 0x16, 0x78, 0x13, 0x8b, 0x55, 0xe4, 0x0f
+.data1 	0xb6, 0xca, 0x8b, 0x46, 0x14, 0x83, 0x46, 0x14
+.data1 	0x01, 0x88, 0x08, 0x89, 0xc8, 0xeb, 0x0b, 0x56
+.data1 	0xff, 0x75, 0xe4, 0xe8, 0x28, 0x01, 0x00, 0x00
+.data1 	0x59, 0x59, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x1c, 0x83, 0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b
+.data1 	0x55, 0xd8, 0xf7, 0xda, 0x89, 0xd0, 0xe9, 0xca
+.data1 	0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0xc0, 0x00, 0x00, 0x00, 0xff, 0x4d, 0xf4
+.data1 	0x75, 0xb3, 0x8b, 0x55, 0xf8, 0x01, 0x55, 0xd8
+.data1 	0xff, 0x4d, 0xf8, 0x0f, 0x88, 0x52, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x16, 0x4a, 0x89, 0x16, 0x78, 0x16
+.data1 	0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xb6
+.data1 	0x10, 0x8b, 0x46, 0x14, 0x83, 0x46, 0x14, 0x01
+.data1 	0x88, 0x10, 0x89, 0xd0, 0xeb, 0x12, 0x8b, 0x45
+.data1 	0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xbe, 0x00, 0x56
+.data1 	0x50, 0xe8, 0xc2, 0x00, 0x00, 0x00, 0x59, 0x59
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0xc1, 0x83
+.data1 	0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b, 0x55, 0xd8
+.data1 	0xf7, 0xda, 0x89, 0xd0, 0xe9, 0x64, 0x00, 0x00
+.data1 	0x00, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x5a
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xf4, 0x00, 0x7e
+.data1 	0x06, 0x8b, 0x55, 0xf4, 0x01, 0x55, 0xd8, 0xff
+.data1 	0x4d, 0xf4, 0x0f, 0x88, 0x23, 0xfa, 0xff, 0xff
+.data1 	0x8b, 0x16, 0x4a, 0x89, 0x16, 0x78, 0x13, 0x8b
+.data1 	0x55, 0xe4, 0x0f, 0xb6, 0xca, 0x8b, 0x46, 0x14
+.data1 	0x83, 0x46, 0x14, 0x01, 0x88, 0x08, 0x89, 0xc8
+.data1 	0xeb, 0x0b, 0x56, 0xff, 0x75, 0xe4, 0xe8, 0x65
+.data1 	0x00, 0x00, 0x00, 0x59, 0x59, 0x3d, 0xff, 0xff
+.data1 	0xff, 0xff, 0x75, 0xcb, 0x83, 0x7d, 0xd8, 0x00
+.data1 	0x74, 0x09, 0x8b, 0x55, 0xd8, 0xf7, 0xda, 0x89
+.data1 	0xd0, 0xeb, 0x0a, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x03, 0x8b, 0x45, 0xd8, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x7d, 0x10, 0x57, 0xff, 0x75, 0x0c
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xa0, 0x07, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0xc6, 0x85, 0xc0, 0x7e
+.data1 	0x14, 0x39, 0xfe, 0x7d, 0x10, 0x89, 0xfa, 0x29
+.data1 	0xf2, 0x89, 0xd7, 0x89, 0xf2, 0x03, 0x55, 0x0c
+.data1 	0x89, 0x55, 0x0c, 0xeb, 0xd7, 0x31, 0xc0, 0x85
+.data1 	0xf6, 0x0f, 0x9f, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x56, 0x57
+.data1 	0x8b, 0x75, 0x0c, 0x8b, 0x7d, 0x08, 0xc7, 0x05
+.data1 	0x3c, 0x07, 0x00, 0x00, 0x75, 0x13, 0x00, 0x00
+.data1 	0x83, 0x7e, 0x04, 0x00, 0x79, 0x0a, 0x89, 0xfa
+.data1 	0x0f, 0xb6, 0xc2, 0xe9, 0x55, 0x02, 0x00, 0x00
+.data1 	0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x02, 0x75, 0x0a
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x43, 0x02
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x80
+.data1 	0x74, 0x0f, 0xf6, 0xc2, 0x10, 0x75, 0x0a, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe9, 0x2c, 0x02, 0x00
+.data1 	0x00, 0x81, 0x66, 0x08, 0x7f, 0xff, 0xff, 0xff
+.data1 	0x81, 0x4e, 0x08, 0x00, 0x01, 0x00, 0x00, 0x8b
+.data1 	0x56, 0x08, 0xf6, 0xc2, 0x04, 0x0f, 0x85, 0x8f
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7e, 0x10, 0x00, 0x0f
+.data1 	0x85, 0x85, 0x00, 0x00, 0x00, 0x81, 0xfe, 0x60
+.data1 	0x07, 0x00, 0x00, 0x75, 0x3e, 0xff, 0x35, 0x64
+.data1 	0x07, 0x00, 0x00, 0xe8, 0x80, 0x06, 0x00, 0x00
+.data1 	0x59, 0x85, 0xc0, 0x74, 0x2e, 0x68, 0x00, 0x04
+.data1 	0x00, 0x00, 0xe8, 0xf0, 0x02, 0x00, 0x00, 0x59
+.data1 	0x89, 0x46, 0x10, 0x85, 0xc0, 0x75, 0x09, 0x83
+.data1 	0x4e, 0x08, 0x04, 0xe9, 0x4c, 0x00, 0x00, 0x00
+.data1 	0x83, 0x4e, 0x08, 0x48, 0xc7, 0x46, 0x0c, 0x00
+.data1 	0x04, 0x00, 0x00, 0xc7, 0x06, 0xff, 0xff, 0xff
+.data1 	0xff, 0xeb, 0x39, 0x68, 0x00, 0x04, 0x00, 0x00
+.data1 	0xe8, 0xc2, 0x02, 0x00, 0x00, 0x59, 0x89, 0x46
+.data1 	0x10, 0x85, 0xc0, 0x75, 0x06, 0x83, 0x4e, 0x08
+.data1 	0x04, 0xeb, 0x21, 0x83, 0x4e, 0x08, 0x08, 0xc7
+.data1 	0x46, 0x0c, 0x00, 0x04, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x40, 0x75, 0x08, 0xc7, 0x06
+.data1 	0xff, 0x03, 0x00, 0x00, 0xeb, 0x06, 0xc7, 0x06
+.data1 	0xff, 0xff, 0xff, 0xff, 0x8b, 0x56, 0x10, 0x89
+.data1 	0x56, 0x14, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x04
+.data1 	0x0f, 0x84, 0x68, 0x00, 0x00, 0x00, 0x89, 0xfa
+.data1 	0x88, 0x55, 0xff, 0xc7, 0x06, 0x00, 0x00, 0x00
+.data1 	0x00, 0xf7, 0x46, 0x08, 0x00, 0x02, 0x00, 0x00
+.data1 	0x74, 0x24, 0x6a, 0x02, 0x6a, 0x00, 0xff, 0x76
+.data1 	0x04, 0xe8, 0x02, 0x06, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x0e
+.data1 	0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x3f, 0x01, 0x00, 0x00, 0x6a, 0x01
+.data1 	0x8d, 0x45, 0xff, 0x50, 0xff, 0x76, 0x04, 0xe8
+.data1 	0x2c, 0x06, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x3d
+.data1 	0x01, 0x00, 0x00, 0x00, 0x74, 0x0e, 0x83, 0x4e
+.data1 	0x08, 0x20, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9
+.data1 	0x19, 0x01, 0x00, 0x00, 0x89, 0xfa, 0x0f, 0xb6
+.data1 	0xc2, 0xe9, 0x0f, 0x01, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x40, 0x0f, 0x84, 0x84, 0x00
+.data1 	0x00, 0x00, 0x89, 0xfa, 0x8b, 0x46, 0x14, 0x83
+.data1 	0x46, 0x14, 0x01, 0x88, 0x10, 0x83, 0xff, 0x0a
+.data1 	0x74, 0x0d, 0x8b, 0x56, 0x0c, 0xf7, 0xda, 0x39
+.data1 	0x16, 0x0f, 0x85, 0xe1, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x16, 0xf7, 0xda, 0x89, 0x55, 0xf8, 0x8b, 0x56
+.data1 	0x10, 0x89, 0x56, 0x14, 0xc7, 0x06, 0x00, 0x00
+.data1 	0x00, 0x00, 0xf7, 0x46, 0x08, 0x00, 0x02, 0x00
+.data1 	0x00, 0x74, 0x24, 0x6a, 0x02, 0x6a, 0x00, 0xff
+.data1 	0x76, 0x04, 0xe8, 0x69, 0x05, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x0e, 0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe9, 0xa6, 0x00, 0x00, 0x00, 0xff
+.data1 	0x75, 0xf8, 0xff, 0x76, 0x10, 0xff, 0x76, 0x04
+.data1 	0xe8, 0xdf, 0xfd, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x85, 0xc0, 0x0f, 0x85, 0x88, 0x00, 0x00, 0x00
+.data1 	0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x7f, 0x00, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x14, 0x2b, 0x56, 0x10, 0x89, 0x55, 0xf8, 0x8b
+.data1 	0x56, 0x0c, 0x4a, 0x89, 0x16, 0x8b, 0x56, 0x10
+.data1 	0x83, 0xc2, 0x01, 0x89, 0x56, 0x14, 0x83, 0x7d
+.data1 	0xf8, 0x00, 0x0f, 0x8e, 0x51, 0x00, 0x00, 0x00
+.data1 	0xf7, 0x46, 0x08, 0x00, 0x02, 0x00, 0x00, 0x74
+.data1 	0x21, 0x6a, 0x02, 0x6a, 0x00, 0xff, 0x76, 0x04
+.data1 	0xe8, 0xf3, 0x04, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x0b, 0x83
+.data1 	0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x33, 0xff, 0x75, 0xf8, 0xff, 0x76, 0x10
+.data1 	0xff, 0x76, 0x04, 0xe8, 0x6c, 0xfd, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x75, 0x12, 0x89
+.data1 	0xfa, 0x8b, 0x4e, 0x10, 0x88, 0x11, 0x83, 0x4e
+.data1 	0x08, 0x20, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x0c, 0x89, 0xfa, 0x8b, 0x4e, 0x10, 0x88, 0x11
+.data1 	0x89, 0xfa, 0x0f, 0xb6, 0xc2, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x10, 0x8b, 0x45, 0x08, 0x31
+.data1 	0xd2, 0xf7, 0x75, 0x0c, 0x89, 0xd7, 0x8b, 0x45
+.data1 	0x08, 0x31, 0xd2, 0xf7, 0x75, 0x0c, 0x89, 0x45
+.data1 	0x08, 0x85, 0xc0, 0x75, 0x06, 0x83, 0x7d, 0x14
+.data1 	0x01, 0x7e, 0x16, 0x8b, 0x55, 0x14, 0x4a, 0x52
+.data1 	0x56, 0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xc8, 0xff, 0xff, 0xff, 0x83, 0xc4, 0x10, 0x89
+.data1 	0xc6, 0x83, 0xff, 0x09, 0x7e, 0x09, 0x89, 0xfa
+.data1 	0x83, 0xea, 0xa9, 0x89, 0xd0, 0xeb, 0x03, 0x8d
+.data1 	0x47, 0x30, 0x88, 0x06, 0x8d, 0x46, 0x01, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x00, 0xb9, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0xea, 0x06, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x68
+.data1 	0x14, 0x07, 0x00, 0x00, 0x68, 0x78, 0x07, 0x00
+.data1 	0x00, 0xe8, 0xe6, 0xf3, 0xff, 0xff, 0x59, 0x59
+.data1 	0x6a, 0x01, 0xe8, 0x96, 0xf3, 0xff, 0xff, 0x59
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x15, 0x38, 0x09, 0x00, 0x00, 0x03, 0x55
+.data1 	0x08, 0x39, 0x15, 0x38, 0x09, 0x00, 0x00, 0x77
+.data1 	0x1f, 0x8b, 0x55, 0x08, 0x03, 0x15, 0x38, 0x09
+.data1 	0x00, 0x00, 0x81, 0xc2, 0xff, 0x0f, 0x00, 0x00
+.data1 	0x81, 0xe2, 0x00, 0xf0, 0xff, 0xff, 0x89, 0xd6
+.data1 	0x39, 0x15, 0x38, 0x09, 0x00, 0x00, 0x76, 0x0e
+.data1 	0xc7, 0x05, 0x44, 0x07, 0x00, 0x00, 0x0c, 0x00
+.data1 	0x00, 0x00, 0x31, 0xc0, 0xeb, 0x36, 0x56, 0xe8
+.data1 	0xe8, 0x02, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x74
+.data1 	0x04, 0x31, 0xc0, 0xeb, 0x27, 0x8b, 0x15, 0x38
+.data1 	0x09, 0x00, 0x00, 0x89, 0x72, 0xfc, 0xc7, 0x46
+.data1 	0xfc, 0x00, 0x00, 0x00, 0x00, 0xff, 0x35, 0x38
+.data1 	0x09, 0x00, 0x00, 0xe8, 0x26, 0x02, 0x00, 0x00
+.data1 	0x59, 0x89, 0x35, 0x38, 0x09, 0x00, 0x00, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x18, 0x56, 0x57, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x75, 0x07, 0x31, 0xc0, 0xe9
+.data1 	0xf4, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xe8, 0x00
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xe8, 0x02, 0x0f
+.data1 	0x83, 0xe1, 0x00, 0x00, 0x00, 0xba, 0x03, 0x00
+.data1 	0x00, 0x00, 0x03, 0x55, 0x08, 0x83, 0xe2, 0xfc
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0xec, 0x83, 0xfa
+.data1 	0x08, 0x73, 0x11, 0xc7, 0x05, 0x44, 0x07, 0x00
+.data1 	0x00, 0x0c, 0x00, 0x00, 0x00, 0x31, 0xc0, 0xe9
+.data1 	0xbc, 0x00, 0x00, 0x00, 0x83, 0x3d, 0x34, 0x09
+.data1 	0x00, 0x00, 0x00, 0x75, 0x38, 0x6a, 0x08, 0xe8
+.data1 	0x97, 0x02, 0x00, 0x00, 0x59, 0x89, 0xc6, 0x3d
+.data1 	0xff, 0xff, 0xff, 0xff, 0x75, 0x07, 0x31, 0xc0
+.data1 	0xe9, 0x9b, 0x00, 0x00, 0x00, 0x8d, 0x56, 0x03
+.data1 	0xbe, 0xfc, 0xff, 0xff, 0xff, 0x21, 0xd6, 0x83
+.data1 	0xc6, 0x04, 0x89, 0x35, 0x34, 0x09, 0x00, 0x00
+.data1 	0x89, 0x35, 0x38, 0x09, 0x00, 0x00, 0xc7, 0x46
+.data1 	0xfc, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xfc
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x35, 0x3c, 0x09
+.data1 	0x00, 0x00, 0x85, 0xf6, 0x0f, 0x84, 0x4f, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x56, 0xfc, 0x89, 0x55, 0xf4
+.data1 	0x89, 0xf2, 0x8b, 0x7d, 0xec, 0x01, 0xd7, 0x39
+.data1 	0x7d, 0xf4, 0x72, 0x36, 0x39, 0xf7, 0x76, 0x32
+.data1 	0x8d, 0x57, 0x04, 0x39, 0x55, 0xf4, 0x76, 0x0f
+.data1 	0x8b, 0x55, 0xf4, 0x89, 0x57, 0xfc, 0x89, 0x7e
+.data1 	0xfc, 0x8b, 0x16, 0x89, 0x17, 0x89, 0x3e, 0x83
+.data1 	0x7d, 0xfc, 0x00, 0x74, 0x09, 0x8b, 0x16, 0x8b
+.data1 	0x45, 0xfc, 0x89, 0x10, 0xeb, 0x08, 0x8b, 0x16
+.data1 	0x89, 0x15, 0x3c, 0x09, 0x00, 0x00, 0x89, 0xf0
+.data1 	0xeb, 0x1e, 0x89, 0x75, 0xfc, 0x8b, 0x36, 0xeb
+.data1 	0xa9, 0xff, 0x75, 0xec, 0xe8, 0x8b, 0xfe, 0xff
+.data1 	0xff, 0x59, 0x85, 0xc0, 0x74, 0x08, 0xff, 0x45
+.data1 	0xe8, 0xe9, 0x15, 0xff, 0xff, 0xff, 0x31, 0xc0
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x1c, 0x56, 0x57, 0x8b, 0x55, 0x08, 0x89
+.data1 	0x55, 0xec, 0x85, 0xd2, 0x75, 0x0e, 0xff, 0x75
+.data1 	0x0c, 0xe8, 0xd9, 0xfe, 0xff, 0xff, 0x59, 0xe9
+.data1 	0xe6, 0x00, 0x00, 0x00, 0x83, 0x7d, 0x0c, 0x00
+.data1 	0x75, 0x10, 0xff, 0x75, 0xec, 0xe8, 0xdc, 0x00
+.data1 	0x00, 0x00, 0x59, 0x31, 0xc0, 0xe9, 0xd0, 0x00
+.data1 	0x00, 0x00, 0xba, 0x03, 0x00, 0x00, 0x00, 0x03
+.data1 	0x55, 0x0c, 0x83, 0xe2, 0xfc, 0x83, 0xc2, 0x04
+.data1 	0x89, 0x55, 0xe8, 0x8b, 0x55, 0xec, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0xf4, 0x2b, 0x55, 0xec, 0x89
+.data1 	0x55, 0xe4, 0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x3d, 0x3c, 0x09, 0x00, 0x00, 0x85
+.data1 	0xff, 0x0f, 0x84, 0x3c, 0x00, 0x00, 0x00, 0x39
+.data1 	0x7d, 0xf4, 0x72, 0x37, 0x39, 0x7d, 0xf4, 0x75
+.data1 	0x2b, 0x8b, 0x55, 0xec, 0x8b, 0x4f, 0xfc, 0x89
+.data1 	0x4a, 0xfc, 0x83, 0x7d, 0xfc, 0x00, 0x74, 0x09
+.data1 	0x8b, 0x17, 0x8b, 0x45, 0xfc, 0x89, 0x10, 0xeb
+.data1 	0x08, 0x8b, 0x17, 0x89, 0x15, 0x3c, 0x09, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xec, 0x8b, 0x52, 0xfc, 0x89
+.data1 	0x55, 0xf4, 0xeb, 0x07, 0x89, 0x7d, 0xfc, 0x8b
+.data1 	0x3f, 0xeb, 0xbc, 0x8b, 0x55, 0xec, 0x8b, 0x75
+.data1 	0xe8, 0x01, 0xd6, 0x39, 0x75, 0xf4, 0x72, 0x25
+.data1 	0x39, 0x75, 0xec, 0x77, 0x20, 0x8d, 0x56, 0x04
+.data1 	0x39, 0x55, 0xf4, 0x76, 0x13, 0x8b, 0x55, 0xf4
+.data1 	0x89, 0x56, 0xfc, 0x8b, 0x55, 0xec, 0x89, 0x72
+.data1 	0xfc, 0x56, 0xe8, 0x37, 0x00, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x45, 0xec, 0xeb, 0x2d, 0xff, 0x75, 0x0c
+.data1 	0xe8, 0x12, 0xfe, 0xff, 0xff, 0x59, 0x89, 0xc6
+.data1 	0x85, 0xc0, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x1a
+.data1 	0xff, 0x75, 0xe4, 0xff, 0x75, 0xec, 0x56, 0xe8
+.data1 	0x64, 0x04, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xff
+.data1 	0x75, 0xec, 0xe8, 0x07, 0x00, 0x00, 0x00, 0x59
+.data1 	0x89, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xf4, 0x85, 0xd2, 0x0f, 0x84
+.data1 	0x62, 0x00, 0x00, 0x00, 0x31, 0xff, 0x8b, 0x35
+.data1 	0x3c, 0x09, 0x00, 0x00, 0x85, 0xf6, 0x74, 0x0b
+.data1 	0x39, 0x75, 0xf4, 0x72, 0x06, 0x89, 0xf7, 0x8b
+.data1 	0x36, 0xeb, 0xf1, 0x8b, 0x45, 0xf4, 0x89, 0x30
+.data1 	0x85, 0xff, 0x74, 0x07, 0x8b, 0x55, 0xf4, 0x89
+.data1 	0x17, 0xeb, 0x09, 0x8b, 0x55, 0xf4, 0x89, 0x15
+.data1 	0x3c, 0x09, 0x00, 0x00, 0x85, 0xf6, 0x74, 0x15
+.data1 	0x8b, 0x55, 0xf4, 0x39, 0x72, 0xfc, 0x75, 0x0d
+.data1 	0x8b, 0x4e, 0xfc, 0x89, 0x4a, 0xfc, 0x8b, 0x16
+.data1 	0x8b, 0x45, 0xf4, 0x89, 0x10, 0x85, 0xff, 0x74
+.data1 	0x15, 0x8b, 0x55, 0xf4, 0x39, 0x57, 0xfc, 0x75
+.data1 	0x0d, 0x8b, 0x52, 0xfc, 0x89, 0x57, 0xfc, 0x8b
+.data1 	0x45, 0xf4, 0x8b, 0x10, 0x89, 0x17, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x8b
+.data1 	0x55, 0x08, 0x83, 0xea, 0x61, 0x83, 0xfa, 0x1a
+.data1 	0x73, 0x0a, 0x8b, 0x55, 0x08, 0x83, 0xea, 0x20
+.data1 	0x89, 0xd0, 0xeb, 0x03, 0x8b, 0x45, 0x08, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x15, 0x28, 0x09, 0x00, 0x00
+.data1 	0x39, 0x55, 0x08, 0x74, 0x2a, 0x8b, 0x55, 0x08
+.data1 	0x89, 0x55, 0xf0, 0x8d, 0x45, 0xdc, 0x50, 0x6a
+.data1 	0x11, 0x6a, 0x00, 0xe8, 0x64, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x79, 0x07, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x0b, 0x8b, 0x55
+.data1 	0xf8, 0x89, 0x15, 0x28, 0x09, 0x00, 0x00, 0x31
+.data1 	0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x57
+.data1 	0x8b, 0x35, 0x28, 0x09, 0x00, 0x00, 0x8b, 0x15
+.data1 	0x28, 0x09, 0x00, 0x00, 0x8b, 0x7d, 0x08, 0x01
+.data1 	0xd7, 0x83, 0x7d, 0x08, 0x00, 0x7e, 0x04, 0x39
+.data1 	0xf7, 0x72, 0x0a, 0x83, 0x7d, 0x08, 0x00, 0x79
+.data1 	0x0b, 0x39, 0xf7, 0x76, 0x07, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xeb, 0x14, 0x57, 0xe8, 0x8a, 0xff
+.data1 	0xff, 0xff, 0x59, 0x85, 0xc0, 0x75, 0x04, 0x89
+.data1 	0xf0, 0xeb, 0x05, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x10, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x56, 0x04, 0x56, 0xff, 0x75, 0x08, 0xe8, 0xbd
+.data1 	0x02, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc7, 0x85
+.data1 	0xff, 0x74, 0x03, 0x89, 0x7e, 0x04, 0x83, 0x7e
+.data1 	0x04, 0x00, 0x79, 0x12, 0x8b, 0x56, 0x04, 0xf7
+.data1 	0xda, 0x89, 0x15, 0x44, 0x07, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x03, 0x8b, 0x46
+.data1 	0x04, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0xff, 0x75, 0x08, 0xe8, 0x46, 0x00
+.data1 	0x00, 0x00, 0x59, 0x59, 0x31, 0xdb, 0x85, 0xc0
+.data1 	0x0f, 0x94, 0xc3, 0x89, 0xd8, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xf0, 0x8b, 0x55, 0x10, 0x89, 0x55, 0xe8
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x13, 0x6a, 0x01
+.data1 	0xe8, 0x77, 0xff, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x85, 0xc0, 0x79, 0x07, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xeb, 0x03, 0x8b, 0x45, 0xf0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0xff, 0x75, 0x0c, 0x68, 0x08
+.data1 	0x54, 0x24, 0x80, 0xff, 0x75, 0x08, 0xe8, 0x9d
+.data1 	0x02, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x10, 0x89
+.data1 	0x55, 0xe8, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf0
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x04, 0x6a, 0x01
+.data1 	0xe8, 0x27, 0xff, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x14, 0x56, 0x57, 0x8b, 0x75, 0x08, 0xc7
+.data1 	0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x85, 0xf6
+.data1 	0x75, 0x34, 0x31, 0xff, 0x83, 0xff, 0x14, 0x7d
+.data1 	0x25, 0x83, 0x3c, 0xbd, 0x90, 0x07, 0x00, 0x00
+.data1 	0x00, 0x74, 0x18, 0xff, 0x34, 0xbd, 0x90, 0x07
+.data1 	0x00, 0x00, 0xe8, 0xcd, 0xff, 0xff, 0xff, 0x59
+.data1 	0x85, 0xc0, 0x74, 0x07, 0xc7, 0x45, 0xf0, 0xff
+.data1 	0xff, 0xff, 0xff, 0x47, 0xeb, 0xd6, 0x8b, 0x45
+.data1 	0xf0, 0xe9, 0x43, 0x01, 0x00, 0x00, 0x83, 0x7e
+.data1 	0x10, 0x00, 0x74, 0x11, 0x8b, 0x56, 0x08, 0xf6
+.data1 	0xc2, 0x80, 0x75, 0x10, 0xf7, 0x46, 0x08, 0x00
+.data1 	0x01, 0x00, 0x00, 0x75, 0x07, 0x31, 0xc0, 0xe9
+.data1 	0x25, 0x01, 0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6
+.data1 	0xc2, 0x80, 0x0f, 0x84, 0x86, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, 0x00, 0xf7
+.data1 	0x46, 0x08, 0x00, 0x04, 0x00, 0x00, 0x74, 0x07
+.data1 	0x31, 0xc0, 0xe9, 0x02, 0x01, 0x00, 0x00, 0x83
+.data1 	0x7e, 0x10, 0x00, 0x74, 0x0f, 0x8b, 0x56, 0x08
+.data1 	0xf6, 0xc2, 0x04, 0x75, 0x07, 0x8b, 0x16, 0xf7
+.data1 	0xda, 0x89, 0x55, 0xec, 0xc7, 0x06, 0x00, 0x00
+.data1 	0x00, 0x00, 0x6a, 0x01, 0xff, 0x75, 0xec, 0xff
+.data1 	0x76, 0x04, 0xe8, 0xd1, 0xfe, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x17, 0x83, 0x3d, 0x44, 0x07, 0x00, 0x00, 0x1d
+.data1 	0x74, 0x0e, 0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xe9, 0xb9, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x05, 0x44, 0x07, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x02
+.data1 	0x74, 0x07, 0x81, 0x66, 0x08, 0x7f, 0xfe, 0xff
+.data1 	0xff, 0x8b, 0x56, 0x10, 0x89, 0x56, 0x14, 0x31
+.data1 	0xc0, 0xe9, 0x93, 0x00, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x04, 0x74, 0x07, 0x31, 0xc0
+.data1 	0xe9, 0x84, 0x00, 0x00, 0x00, 0x8b, 0x56, 0x08
+.data1 	0xf6, 0xc2, 0x01, 0x74, 0x07, 0x81, 0x66, 0x08
+.data1 	0xff, 0xfe, 0xff, 0xff, 0x8b, 0x56, 0x14, 0x2b
+.data1 	0x56, 0x10, 0x89, 0x55, 0xfc, 0x8b, 0x56, 0x10
+.data1 	0x89, 0x56, 0x14, 0x83, 0x7d, 0xfc, 0x00, 0x7f
+.data1 	0x07, 0x31, 0xc0, 0xe9, 0x59, 0x00, 0x00, 0x00
+.data1 	0xf7, 0x46, 0x08, 0x00, 0x02, 0x00, 0x00, 0x74
+.data1 	0x21, 0x6a, 0x02, 0x6a, 0x00, 0xff, 0x76, 0x04
+.data1 	0xe8, 0x3b, 0xfe, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x0b, 0x83
+.data1 	0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x2f, 0xff, 0x75, 0xfc, 0xff, 0x76, 0x10
+.data1 	0xff, 0x76, 0x04, 0xe8, 0x68, 0xfe, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x45, 0xf8, 0xc7, 0x06
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xf8, 0x39
+.data1 	0x55, 0xfc, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x09
+.data1 	0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0x31, 0xf6, 0x83, 0xfe, 0x14, 0x7d, 0x2a
+.data1 	0x83, 0x3c, 0xb5, 0x90, 0x07, 0x00, 0x00, 0x00
+.data1 	0x74, 0x1d, 0x8b, 0x14, 0xb5, 0x90, 0x07, 0x00
+.data1 	0x00, 0xf7, 0x42, 0x08, 0x00, 0x01, 0x00, 0x00
+.data1 	0x74, 0x0d, 0xff, 0x34, 0xb5, 0x90, 0x07, 0x00
+.data1 	0x00, 0xe8, 0x3e, 0xfe, 0xff, 0xff, 0x59, 0x46
+.data1 	0xeb, 0xd1, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x01, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x02
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x03, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0xb9, 0x04, 0x00, 0x00, 0x00
+.data1 	0xcd, 0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x53, 0x8b, 0x5d, 0x08, 0xb9, 0x08, 0x00, 0x00
+.data1 	0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x57, 0x8b, 0x7d, 0x08, 0x30
+.data1 	0xc0, 0x89, 0xca, 0x80, 0xf9, 0x01, 0xfc, 0xf2
+.data1 	0xae, 0x75, 0x01, 0x41, 0x89, 0xd0, 0x29, 0xc8
+.data1 	0x5f, 0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x08
+.data1 	0x8b, 0x75, 0x0c, 0x8b, 0x4d, 0x10, 0xe9, 0x4f
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xec, 0x8b, 0x55, 0x10, 0x89, 0x55, 0xf8
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x36, 0x6a, 0x01
+.data1 	0xe8, 0x8f, 0xfc, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x7d, 0x08, 0x8b, 0x75, 0x0c, 0x8b
+.data1 	0x4d, 0x10, 0x89, 0xf8, 0x29, 0xf0, 0x39, 0xc8
+.data1 	0x72, 0x2f, 0xfc, 0x83, 0xf9, 0x10, 0x72, 0x20
+.data1 	0x89, 0xf0, 0x09, 0xf8, 0xa8, 0x01, 0x75, 0x18
+.data1 	0xa8, 0x02, 0x75, 0x0d, 0x0f, 0xac, 0xc8, 0x02
+.data1 	0xc1, 0xe9, 0x02, 0xf3, 0xa5, 0x0f, 0xa4, 0xc1
+.data1 	0x02, 0xd1, 0xe9, 0xf3, 0x66, 0xa5, 0x11, 0xc9
+.data1 	0xf3, 0xa4, 0x8b, 0x45, 0x08, 0x5f, 0x5e, 0x5d
+.data1 	0xc3, 0xfd, 0x8d, 0x74, 0x0e, 0xff, 0x8d, 0x7c
+.data1 	0x0f, 0xff, 0xf3, 0xa4, 0xfc, 0xeb, 0xeb, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x13, 0x8b, 0x4b
+.data1 	0x04, 0x83, 0xc3, 0x08, 0x49, 0x7c, 0x18, 0x3b
+.data1 	0x03, 0x75, 0xf6, 0x8b, 0x5b, 0x04, 0x85, 0xdb
+.data1 	0x75, 0x0b, 0xb8, 0x14, 0x00, 0x00, 0x00, 0x50
+.data1 	0xe9, 0x07, 0x00, 0x00, 0x00, 0xff, 0xe3, 0x89
+.data1 	0xd3, 0xeb, 0xeb, 0x00, 0xe8, 0x0f, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x3f, 0xec, 0xff, 0xff, 0x00, 0x00, 0x00
+.data1 	0x31, 0xdb, 0x87, 0x1d, 0x2c, 0x09, 0x00, 0x00
+.data1 	0x85, 0xdb, 0x74, 0x05, 0x50, 0xff, 0xd3, 0x58
+.data1 	0xc3, 0x50, 0xe8, 0xe1, 0xff, 0xff, 0xff, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x6e, 0x65, 0x77, 0x72
+.data1 	0x6f, 0x6f, 0x74, 0x3a, 0x20, 0x6d, 0x6f, 0x75
+.data1 	0x6e, 0x74, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65
+.data1 	0x64, 0x3a, 0x20, 0x25, 0x73, 0x0a, 0x00, 0x00
+.data1 	0x2f, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67
+.data1 	0x65, 0x3a, 0x20, 0x6e, 0x65, 0x77, 0x72, 0x6f
+.data1 	0x6f, 0x74, 0x20, 0x3c, 0x62, 0x6c, 0x6f, 0x63
+.data1 	0x6b, 0x2d, 0x73, 0x70, 0x65, 0x63, 0x69, 0x61
+.data1 	0x6c, 0x3e, 0x0a, 0x00, 0x75, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x74
+.data1 	0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x6e, 0x6f, 0x74
+.data1 	0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62
+.data1 	0x6c, 0x65, 0x00, 0x00, 0x53, 0x6f, 0x63, 0x6b
+.data1 	0x65, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61
+.data1 	0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x6e, 0x20
+.data1 	0x6e, 0x6f, 0x6e, 0x2d, 0x73, 0x6f, 0x63, 0x6b
+.data1 	0x65, 0x74, 0x00, 0x00, 0x4d, 0x65, 0x73, 0x73
+.data1 	0x61, 0x67, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x20
+.data1 	0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61
+.data1 	0x64, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x72
+.data1 	0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x00, 0x00
+.data1 	0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20
+.data1 	0x6e, 0x6f, 0x74, 0x20, 0x61, 0x76, 0x61, 0x69
+.data1 	0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00
+.data1 	0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f
+.data1 	0x6e, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x72, 0x6f
+.data1 	0x67, 0x72, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00
+.data1 	0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c
+.data1 	0x20, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x74
+.data1 	0x79, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20
+.data1 	0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x00, 0x00
+.data1 	0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c
+.data1 	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70
+.data1 	0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x62
+.data1 	0x79, 0x20, 0x41, 0x46, 0x00, 0x00, 0x00, 0x00
+.data1 	0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20
+.data1 	0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x20, 0x6e
+.data1 	0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f
+.data1 	0x72, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x00, 0x00, 0x41, 0x6c, 0x72, 0x65
+.data1 	0x61, 0x64, 0x79, 0x20, 0x73, 0x68, 0x75, 0x74
+.data1 	0x64, 0x6f, 0x77, 0x6e, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65
+.data1 	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x75, 0x72, 0x67, 0x65, 0x6e
+.data1 	0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x70
+.data1 	0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x00, 0x00
+.data1 	0x55, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x20, 0x64
+.data1 	0x61, 0x74, 0x61, 0x20, 0x70, 0x72, 0x65, 0x73
+.data1 	0x65, 0x6e, 0x74, 0x00, 0x43, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74
+.data1 	0x69, 0x6d, 0x65, 0x64, 0x20, 0x6f, 0x75, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72
+.data1 	0x65, 0x73, 0x65, 0x74, 0x00, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x72, 0x65, 0x66, 0x75, 0x73
+.data1 	0x65, 0x64, 0x00, 0x00, 0x41, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x75
+.data1 	0x73, 0x65, 0x00, 0x00, 0x41, 0x6c, 0x72, 0x65
+.data1 	0x61, 0x64, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74
+.data1 	0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x6f, 0x74, 0x20
+.data1 	0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c
+.data1 	0x65, 0x00, 0x00, 0x00, 0x42, 0x61, 0x64, 0x20
+.data1 	0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74
+.data1 	0x69, 0x6f, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x00, 0x57, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x6d, 0x6f, 0x64, 0x65
+.data1 	0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6f, 0x63
+.data1 	0x74, 0x6c, 0x00, 0x00, 0x49, 0x6c, 0x6c, 0x65
+.data1 	0x67, 0x61, 0x6c, 0x20, 0x69, 0x6f, 0x63, 0x74
+.data1 	0x6c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x65
+.data1 	0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x65, 0x6e, 0x6f, 0x75
+.data1 	0x67, 0x68, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65
+.data1 	0x72, 0x73, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x00
+.data1 	0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20
+.data1 	0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x73
+.data1 	0x69, 0x7a, 0x65, 0x00, 0x54, 0x6f, 0x6f, 0x20
+.data1 	0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x65, 0x76
+.data1 	0x65, 0x6c, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x73
+.data1 	0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, 0x20
+.data1 	0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x00, 0x00, 0x00
+.data1 	0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72
+.data1 	0x79, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x6d
+.data1 	0x70, 0x74, 0x79, 0x00, 0x46, 0x75, 0x6e, 0x63
+.data1 	0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x6f, 0x74
+.data1 	0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65
+.data1 	0x6e, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x6c, 0x6f, 0x63, 0x6b, 0x73
+.data1 	0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62
+.data1 	0x6c, 0x65, 0x00, 0x00, 0x46, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f
+.data1 	0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x00
+.data1 	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65
+.data1 	0x20, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x6f, 0x63
+.data1 	0x6b, 0x20, 0x61, 0x76, 0x6f, 0x69, 0x64, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x75
+.data1 	0x6c, 0x74, 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c
+.data1 	0x61, 0x72, 0x67, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4d, 0x61, 0x74, 0x68, 0x20, 0x61, 0x72, 0x67
+.data1 	0x75, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00
+.data1 	0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x70
+.data1 	0x69, 0x70, 0x65, 0x00, 0x54, 0x6f, 0x6f, 0x20
+.data1 	0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x69, 0x6e
+.data1 	0x6b, 0x73, 0x00, 0x00, 0x52, 0x65, 0x61, 0x64
+.data1 	0x2d, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x66, 0x69
+.data1 	0x6c, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65
+.data1 	0x6d, 0x00, 0x00, 0x00, 0x49, 0x6c, 0x6c, 0x65
+.data1 	0x67, 0x61, 0x6c, 0x20, 0x73, 0x65, 0x65, 0x6b
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x70, 0x61, 0x63, 0x65, 0x20, 0x6c, 0x65, 0x66
+.data1 	0x74, 0x20, 0x6f, 0x6e, 0x20, 0x64, 0x65, 0x76
+.data1 	0x69, 0x63, 0x65, 0x00, 0x46, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x61, 0x72
+.data1 	0x67, 0x65, 0x00, 0x00, 0x54, 0x65, 0x78, 0x74
+.data1 	0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x62, 0x75
+.data1 	0x73, 0x79, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x61, 0x20, 0x74, 0x79, 0x70, 0x65, 0x77, 0x72
+.data1 	0x69, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00
+.data1 	0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79
+.data1 	0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x66, 0x69
+.data1 	0x6c, 0x65, 0x73, 0x00, 0x46, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f
+.data1 	0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x00
+.data1 	0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20
+.data1 	0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x49, 0x73, 0x20, 0x61
+.data1 	0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f
+.data1 	0x72, 0x79, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x61, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74
+.data1 	0x6f, 0x72, 0x79, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x64, 0x65, 0x76, 0x69
+.data1 	0x63, 0x65, 0x00, 0x00, 0x43, 0x72, 0x6f, 0x73
+.data1 	0x73, 0x2d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x00, 0x00, 0x00
+.data1 	0x46, 0x69, 0x6c, 0x65, 0x20, 0x65, 0x78, 0x69
+.data1 	0x73, 0x74, 0x73, 0x00, 0x52, 0x65, 0x73, 0x6f
+.data1 	0x75, 0x72, 0x63, 0x65, 0x20, 0x62, 0x75, 0x73
+.data1 	0x79, 0x00, 0x00, 0x00, 0x42, 0x6c, 0x6f, 0x63
+.data1 	0x6b, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x42, 0x61, 0x64, 0x20
+.data1 	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x00
+.data1 	0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x64, 0x65, 0x6e, 0x69, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x63
+.data1 	0x6f, 0x72, 0x65, 0x00, 0x52, 0x65, 0x73, 0x6f
+.data1 	0x75, 0x72, 0x63, 0x65, 0x20, 0x74, 0x65, 0x6d
+.data1 	0x70, 0x6f, 0x72, 0x61, 0x72, 0x69, 0x6c, 0x79
+.data1 	0x20, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c
+.data1 	0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64
+.data1 	0x72, 0x65, 0x6e, 0x00, 0x42, 0x61, 0x64, 0x20
+.data1 	0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x75, 0x6d
+.data1 	0x62, 0x65, 0x72, 0x00, 0x45, 0x78, 0x65, 0x63
+.data1 	0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20
+.data1 	0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00
+.data1 	0x41, 0x72, 0x67, 0x20, 0x6c, 0x69, 0x73, 0x74
+.data1 	0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x6f, 0x6e
+.data1 	0x67, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x64, 0x65, 0x76, 0x69
+.data1 	0x63, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x64
+.data1 	0x64, 0x72, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00
+.data1 	0x49, 0x2f, 0x4f, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x74, 0x65
+.data1 	0x72, 0x72, 0x75, 0x70, 0x74, 0x65, 0x64, 0x20
+.data1 	0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x63
+.data1 	0x61, 0x6c, 0x6c, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x70, 0x72, 0x6f, 0x63
+.data1 	0x65, 0x73, 0x73, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x66, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x6f, 0x72, 0x20, 0x64, 0x69, 0x72, 0x65
+.data1 	0x63, 0x74, 0x6f, 0x72, 0x79, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x6f, 0x77, 0x6e, 0x65
+.data1 	0x72, 0x00, 0x00, 0x00, 0x45, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x20, 0x30, 0x00, 0x8d, 0x02, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
+.data1 	0x31, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+.data1 	0x66, 0x02, 0x00, 0x00, 0x8a, 0x03, 0x00, 0x00
+.data1 	0x08, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00
+.data1 	0x73, 0x03, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00
+.data1 	0x58, 0x03, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00
+.data1 	0x6a, 0x03, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00
+.data1 	0x6a, 0x03, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00
+.data1 	0x61, 0x03, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00
+.data1 	0x73, 0x03, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00
+.data1 	0x6a, 0x03, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
+.data1 	0x73, 0x03, 0x00, 0x00, 0x63, 0x04, 0x00, 0x00
+.data1 	0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
+.data1 	0x54, 0x04, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00
+.data1 	0x59, 0x04, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00
+.data1 	0x4f, 0x04, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00
+.data1 	0x4a, 0x04, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00
+.data1 	0x5e, 0x04, 0x00, 0x00, 0x55, 0x07, 0x00, 0x00
+.data1 	0x03, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00
+.data1 	0x3d, 0x05, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00
+.data1 	0x27, 0x05, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00
+.data1 	0x32, 0x05, 0x00, 0x00, 0x5b, 0x05, 0x00, 0x00
+.data1 	0x11, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00
+.data1 	0xf1, 0x06, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00
+.data1 	0xdc, 0x06, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00
+.data1 	0x47, 0x06, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00
+.data1 	0x47, 0x06, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00
+.data1 	0xc3, 0x06, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00
+.data1 	0x85, 0x06, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00
+.data1 	0xf1, 0x06, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00
+.data1 	0xf1, 0x06, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00
+.data1 	0xdc, 0x06, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00
+.data1 	0x85, 0x06, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00
+.data1 	0xab, 0x05, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00
+.data1 	0x47, 0x06, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00
+.data1 	0x47, 0x06, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00
+.data1 	0x35, 0x07, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00
+.data1 	0x01, 0x06, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00
+.data1 	0x47, 0x06, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
+.data1 	0x47, 0x06, 0x00, 0x00, 0x28, 0x6e, 0x75, 0x6c
+.data1 	0x6c, 0x29, 0x00, 0x00, 0x63, 0x61, 0x6e, 0x6e
+.data1 	0x6f, 0x74, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74
+.data1 	0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x69, 0x6e
+.data1 	0x67, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x44, 0x09, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x53, 0x53, 0x53, 0x53, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x48, 0x07, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00
+.data1 	0x78, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20
+.data1 	0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00
+.data1 	0xc4, 0x05, 0x00, 0x00, 0xb8, 0x05, 0x00, 0x00
+.data1 	0x9c, 0x05, 0x00, 0x00, 0x8c, 0x05, 0x00, 0x00
+.data1 	0x74, 0x05, 0x00, 0x00, 0x68, 0x05, 0x00, 0x00
+.data1 	0x4c, 0x05, 0x00, 0x00, 0x38, 0x05, 0x00, 0x00
+.data1 	0x24, 0x05, 0x00, 0x00, 0x14, 0x05, 0x00, 0x00
+.data1 	0x08, 0x05, 0x00, 0x00, 0xe4, 0x04, 0x00, 0x00
+.data1 	0xd4, 0x04, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x00
+.data1 	0xb4, 0x04, 0x00, 0x00, 0x9c, 0x04, 0x00, 0x00
+.data1 	0x8c, 0x04, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00
+.data1 	0x6c, 0x04, 0x00, 0x00, 0x5c, 0x04, 0x00, 0x00
+.data1 	0x4c, 0x04, 0x00, 0x00, 0x3c, 0x04, 0x00, 0x00
+.data1 	0x28, 0x04, 0x00, 0x00, 0x14, 0x04, 0x00, 0x00
+.data1 	0x00, 0x04, 0x00, 0x00, 0xec, 0x03, 0x00, 0x00
+.data1 	0xdc, 0x03, 0x00, 0x00, 0xcc, 0x03, 0x00, 0x00
+.data1 	0xb4, 0x03, 0x00, 0x00, 0xa4, 0x03, 0x00, 0x00
+.data1 	0x8c, 0x03, 0x00, 0x00, 0x7c, 0x03, 0x00, 0x00
+.data1 	0x70, 0x03, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00
+.data1 	0x4c, 0x03, 0x00, 0x00, 0x30, 0x03, 0x00, 0x00
+.data1 	0x1c, 0x03, 0x00, 0x00, 0x08, 0x03, 0x00, 0x00
+.data1 	0xec, 0x02, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00
+.data1 	0xb4, 0x02, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00
+.data1 	0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00
+.data1 	0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00
+.data1 	0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00
+.data1 	0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00
+.data1 	0xa0, 0x02, 0x00, 0x00, 0x88, 0x02, 0x00, 0x00
+.data1 	0x6c, 0x02, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00
+.data1 	0x4c, 0x02, 0x00, 0x00, 0x34, 0x02, 0x00, 0x00
+.data1 	0x18, 0x02, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00
+.data1 	0xf4, 0x01, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00
+.data1 	0xcc, 0x01, 0x00, 0x00, 0xb4, 0x01, 0x00, 0x00
+.data1 	0xa0, 0x01, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00
+.data1 	0x78, 0x01, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00
+.data1 	0x50, 0x01, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00
+.data1 	0x10, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00
+.data1 	0xd8, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00
+.data1 	0xa0, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00
+.data1 	0x6c, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00
+.data1 	0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0xc8, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x03, 0x20, 0x10, 0x20, 0x00, 0x00, 0x00
+.data1 	0xe0, 0x50, 0x00, 0x00, 0xe4, 0x2e, 0x00, 0x00
+.data1 	0x4c, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x30, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0xed, 0x8b, 0x04, 0x24, 0x8d, 0x54, 0x24
+.data1 	0x04, 0x8d, 0x4c, 0x84, 0x08, 0xbb, 0xd0, 0x2d
+.data1 	0x00, 0x00, 0x81, 0xfb, 0xe4, 0x2e, 0x00, 0x00
+.data1 	0x73, 0x13, 0xf6, 0xc3, 0x03, 0x75, 0x0e, 0x81
+.data1 	0x3b, 0x53, 0x53, 0x53, 0x53, 0x75, 0x06, 0x89
+.data1 	0x1d, 0x40, 0x26, 0x00, 0x00, 0x8b, 0x1d, 0x40
+.data1 	0x26, 0x00, 0x00, 0x89, 0x0b, 0x51, 0x52, 0x50
+.data1 	0x0f, 0x01, 0xe0, 0xa8, 0x04, 0x0f, 0x94, 0x05
+.data1 	0xa8, 0x48, 0x00, 0x00, 0xe8, 0x07, 0x00, 0x00
+.data1 	0x00, 0x50, 0xe8, 0x12, 0x4b, 0x00, 0x00, 0xf4
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x2c, 0x56, 0x57
+.data1 	0xe8, 0xe3, 0x08, 0x00, 0x00, 0x31, 0xf6, 0x83
+.data1 	0xfe, 0x10, 0x7d, 0x10, 0x6b, 0xc6, 0x14, 0xc7
+.data1 	0x80, 0xf4, 0x2e, 0x00, 0x00, 0xce, 0x7a, 0x00
+.data1 	0x00, 0x46, 0xeb, 0xeb, 0x8d, 0x45, 0xd4, 0x50
+.data1 	0x68, 0xce, 0x7a, 0x00, 0x00, 0xe8, 0xfe, 0x4c
+.data1 	0x00, 0x00, 0x59, 0x59, 0x89, 0xc7, 0x85, 0xff
+.data1 	0x0f, 0x89, 0x00, 0x01, 0x00, 0x00, 0x57, 0x68
+.data1 	0xb0, 0x00, 0x00, 0x00, 0xe8, 0x77, 0x46, 0x00
+.data1 	0x00, 0x59, 0x59, 0xe9, 0xfb, 0x00, 0x00, 0x00
+.data1 	0x8d, 0x45, 0xd4, 0x50, 0xe8, 0x27, 0x01, 0x00
+.data1 	0x00, 0x59, 0xeb, 0xc8, 0x8d, 0x45, 0xd4, 0x50
+.data1 	0xe8, 0xcd, 0x01, 0x00, 0x00, 0x59, 0xeb, 0xbc
+.data1 	0x8d, 0x45, 0xd4, 0x50, 0xe8, 0x22, 0x02, 0x00
+.data1 	0x00, 0x59, 0xeb, 0xb0, 0x8d, 0x45, 0xd4, 0x50
+.data1 	0xe8, 0x7d, 0x02, 0x00, 0x00, 0x59, 0xeb, 0xa4
+.data1 	0x8d, 0x45, 0xd4, 0x50, 0xe8, 0xdd, 0x02, 0x00
+.data1 	0x00, 0x59, 0xeb, 0x98, 0x8d, 0x45, 0xd4, 0x50
+.data1 	0xe8, 0x2e, 0x03, 0x00, 0x00, 0x59, 0xeb, 0x8c
+.data1 	0x8d, 0x45, 0xd4, 0x50, 0xe8, 0xd1, 0x03, 0x00
+.data1 	0x00, 0x59, 0xeb, 0x80, 0x8d, 0x45, 0xd4, 0x50
+.data1 	0xe8, 0x4d, 0x04, 0x00, 0x00, 0x59, 0xe9, 0x71
+.data1 	0xff, 0xff, 0xff, 0x8d, 0x45, 0xd4, 0x50, 0xe8
+.data1 	0xbf, 0x04, 0x00, 0x00, 0x59, 0xe9, 0x62, 0xff
+.data1 	0xff, 0xff, 0x8d, 0x45, 0xd4, 0x50, 0xe8, 0x07
+.data1 	0x05, 0x00, 0x00, 0x59, 0xe9, 0x53, 0xff, 0xff
+.data1 	0xff, 0x8d, 0x45, 0xd4, 0x50, 0xe8, 0x4b, 0x05
+.data1 	0x00, 0x00, 0x59, 0xe9, 0x44, 0xff, 0xff, 0xff
+.data1 	0x8d, 0x45, 0xd4, 0x50, 0xe8, 0x8f, 0x05, 0x00
+.data1 	0x00, 0x59, 0xe9, 0x35, 0xff, 0xff, 0xff, 0x8d
+.data1 	0x45, 0xd4, 0x50, 0xe8, 0xdb, 0x05, 0x00, 0x00
+.data1 	0x59, 0xe9, 0x26, 0xff, 0xff, 0xff, 0x8d, 0x45
+.data1 	0xd4, 0x50, 0xe8, 0x2d, 0x06, 0x00, 0x00, 0x59
+.data1 	0xe9, 0x17, 0xff, 0xff, 0xff, 0x8d, 0x45, 0xd4
+.data1 	0x50, 0xe8, 0x75, 0x06, 0x00, 0x00, 0x59, 0xe9
+.data1 	0x08, 0xff, 0xff, 0xff, 0xe8, 0x30, 0x00, 0x00
+.data1 	0x00, 0xe9, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0x75
+.data1 	0xd8, 0xff, 0x75, 0xd4, 0x68, 0x8c, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x8a, 0x45, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0xe9, 0xe6, 0xfe, 0xff, 0xff, 0xbb, 0x04
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x45, 0xd8, 0xe9, 0xe9
+.data1 	0x4e, 0x00, 0x00, 0x31, 0xc0, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x8d
+.data1 	0x45, 0xfc, 0x50, 0xe8, 0xac, 0x4b, 0x00, 0x00
+.data1 	0x59, 0x85, 0xc0, 0x75, 0x19, 0x6a, 0x0f, 0x8d
+.data1 	0x45, 0xfc, 0x50, 0xe8, 0xa4, 0x4b, 0x00, 0x00
+.data1 	0x59, 0x59, 0x85, 0xc0, 0x74, 0x08, 0x6a, 0x00
+.data1 	0xe8, 0x94, 0x49, 0x00, 0x00, 0x59, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57
+.data1 	0x8b, 0x7d, 0x08, 0xc7, 0x45, 0xf4, 0xff, 0xff
+.data1 	0xff, 0xff, 0x31, 0xf6, 0x83, 0xfe, 0x10, 0x7d
+.data1 	0x33, 0x83, 0x7d, 0xf4, 0xff, 0x75, 0x12, 0x6b
+.data1 	0xc6, 0x14, 0x81, 0xb8, 0xf4, 0x2e, 0x00, 0x00
+.data1 	0xce, 0x7a, 0x00, 0x00, 0x75, 0x03, 0x89, 0x75
+.data1 	0xf4, 0x6b, 0xc6, 0x14, 0x8d, 0x5f, 0x14, 0x53
+.data1 	0x05, 0xe4, 0x2e, 0x00, 0x00, 0x50, 0xe8, 0xf9
+.data1 	0x4b, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x74
+.data1 	0x03, 0x46, 0xeb, 0xc8, 0x83, 0xfe, 0x10, 0x7d
+.data1 	0x11, 0x6b, 0xc6, 0x14, 0x05, 0xe4, 0x2e, 0x00
+.data1 	0x00, 0x50, 0xe8, 0xd7, 0x0a, 0x00, 0x00, 0x59
+.data1 	0xeb, 0x17, 0x8b, 0x75, 0xf4, 0x6b, 0xc6, 0x14
+.data1 	0x8d, 0x5f, 0x14, 0x53, 0x05, 0xe4, 0x2e, 0x00
+.data1 	0x00, 0x50, 0xe8, 0xd5, 0x4b, 0x00, 0x00, 0x59
+.data1 	0x59, 0x6b, 0xc6, 0x14, 0x8b, 0x17, 0x89, 0x90
+.data1 	0xf4, 0x2e, 0x00, 0x00, 0xc7, 0x47, 0x04, 0x00
+.data1 	0x00, 0x00, 0x00, 0x57, 0xff, 0x37, 0xe8, 0x09
+.data1 	0x4b, 0x00, 0x00, 0x59, 0x59, 0x89, 0x45, 0xf8
+.data1 	0x85, 0xc0, 0x74, 0x12, 0xff, 0x75, 0xf8, 0xff
+.data1 	0x37, 0x68, 0xd4, 0x00, 0x00, 0x00, 0xe8, 0x95
+.data1 	0x44, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c
+.data1 	0x56, 0x57, 0x8b, 0x75, 0x08, 0x8d, 0x45, 0xf4
+.data1 	0x50, 0x8d, 0x45, 0xf6, 0x50, 0x8d, 0x45, 0xf8
+.data1 	0x50, 0xe8, 0xa8, 0x07, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x89, 0xc7, 0x83, 0xff, 0x01, 0x75, 0x14
+.data1 	0x8b, 0x55, 0xf8, 0x89, 0x56, 0x08, 0x0f, 0xb7
+.data1 	0x55, 0xf6, 0x89, 0x56, 0x0c, 0x0f, 0xb7, 0x55
+.data1 	0xf4, 0x89, 0x56, 0x10, 0x89, 0x7e, 0x04, 0x56
+.data1 	0xff, 0x36, 0xe8, 0xa5, 0x4a, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0xc7, 0x85, 0xff, 0x74, 0x10, 0x57
+.data1 	0xff, 0x36, 0x68, 0xf8, 0x00, 0x00, 0x00, 0xe8
+.data1 	0x34, 0x44, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x0c, 0x56, 0x57, 0x8b, 0x75, 0x08, 0x8b, 0x56
+.data1 	0x08, 0x89, 0x55, 0xf8, 0x8d, 0x45, 0xf4, 0x50
+.data1 	0x8d, 0x45, 0xf6, 0x50, 0x8d, 0x45, 0xf8, 0x50
+.data1 	0xe8, 0xa3, 0x07, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0xc7, 0x83, 0xff, 0x01, 0x75, 0x14, 0x8b
+.data1 	0x55, 0xf8, 0x89, 0x56, 0x08, 0x0f, 0xb7, 0x55
+.data1 	0xf6, 0x89, 0x56, 0x0c, 0x0f, 0xb7, 0x55, 0xf4
+.data1 	0x89, 0x56, 0x10, 0x89, 0x7e, 0x04, 0x56, 0xff
+.data1 	0x36, 0xe8, 0x3e, 0x4a, 0x00, 0x00, 0x59, 0x59
+.data1 	0x89, 0xc7, 0x85, 0xff, 0x74, 0x10, 0x57, 0xff
+.data1 	0x36, 0x68, 0x20, 0x01, 0x00, 0x00, 0xe8, 0xcd
+.data1 	0x43, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c
+.data1 	0x56, 0x57, 0x8b, 0x75, 0x08, 0x8b, 0x56, 0x08
+.data1 	0x88, 0x55, 0xf7, 0x8b, 0x56, 0x0c, 0x88, 0x55
+.data1 	0xf6, 0x8b, 0x56, 0x10, 0x88, 0x55, 0xf5, 0x8d
+.data1 	0x45, 0xf8, 0x50, 0x0f, 0xb6, 0x45, 0xf5, 0x50
+.data1 	0x0f, 0xb6, 0x45, 0xf6, 0x50, 0x0f, 0xb6, 0x45
+.data1 	0xf7, 0x50, 0xe8, 0x47, 0x06, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x10, 0x89, 0xc7, 0x83, 0xff, 0x01, 0x75
+.data1 	0x06, 0x8b, 0x55, 0xf8, 0x89, 0x56, 0x08, 0x89
+.data1 	0x7e, 0x04, 0x56, 0xff, 0x36, 0xe8, 0xd2, 0x49
+.data1 	0x00, 0x00, 0x59, 0x59, 0x89, 0xc7, 0x85, 0xff
+.data1 	0x74, 0x10, 0x57, 0xff, 0x36, 0x68, 0x48, 0x01
+.data1 	0x00, 0x00, 0xe8, 0x61, 0x43, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57, 0x8b, 0x75
+.data1 	0x08, 0x8b, 0x56, 0x08, 0x89, 0x55, 0xf8, 0x8d
+.data1 	0x45, 0xf4, 0x50, 0x8d, 0x45, 0xf6, 0x50, 0xff
+.data1 	0x75, 0xf8, 0xe8, 0x7c, 0x09, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x0f, 0xb7, 0x55, 0xf6, 0x89, 0x56
+.data1 	0x08, 0x0f, 0xb7, 0x55, 0xf4, 0x89, 0x56, 0x0c
+.data1 	0xc7, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x56
+.data1 	0xff, 0x36, 0xe8, 0x75, 0x49, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0xc7, 0x85, 0xff, 0x74, 0x10, 0x57
+.data1 	0xff, 0x36, 0x68, 0x70, 0x01, 0x00, 0x00, 0xe8
+.data1 	0x04, 0x43, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x18, 0x56, 0x57, 0x8b, 0x75, 0x08, 0xba, 0xff
+.data1 	0xff, 0x00, 0x00, 0x23, 0x56, 0x08, 0x66, 0x89
+.data1 	0x55, 0xf2, 0xba, 0xff, 0xff, 0x00, 0x00, 0x23
+.data1 	0x56, 0x0c, 0x66, 0x89, 0x55, 0xf0, 0x8b, 0x56
+.data1 	0x10, 0x89, 0x55, 0xf8, 0x8b, 0x56, 0x14, 0x89
+.data1 	0x55, 0xec, 0x0f, 0xb7, 0x45, 0xf0, 0x50, 0x0f
+.data1 	0xb7, 0x45, 0xf2, 0x50, 0xe8, 0xdc, 0x09, 0x00
+.data1 	0x00, 0x59, 0x59, 0x89, 0x45, 0xe8, 0x85, 0xc0
+.data1 	0x75, 0x07, 0xbf, 0xfe, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x3a, 0xff, 0x75, 0xe8, 0xe8, 0xd3, 0x49, 0x00
+.data1 	0x00, 0x59, 0x05, 0x01, 0x00, 0x00, 0x00, 0x89
+.data1 	0x45, 0xf4, 0x39, 0x45, 0xf8, 0x7d, 0x06, 0x8b
+.data1 	0x55, 0xf8, 0x89, 0x55, 0xf4, 0xff, 0x75, 0xf4
+.data1 	0xff, 0x75, 0xec, 0x6a, 0x01, 0xff, 0x36, 0xff
+.data1 	0x75, 0xe8, 0x6a, 0x01, 0x68, 0xce, 0x8a, 0x00
+.data1 	0x00, 0xe8, 0xd2, 0x3d, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x1c, 0x89, 0xc7, 0x89, 0x7e, 0x04, 0x56, 0xff
+.data1 	0x36, 0xe8, 0xc6, 0x48, 0x00, 0x00, 0x59, 0x59
+.data1 	0x89, 0xc7, 0x85, 0xff, 0x74, 0x10, 0x57, 0xff
+.data1 	0x36, 0x68, 0x94, 0x01, 0x00, 0x00, 0xe8, 0x55
+.data1 	0x42, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x18
+.data1 	0x56, 0x57, 0x8b, 0x75, 0x08, 0x8b, 0x56, 0x08
+.data1 	0x89, 0x55, 0xf8, 0x8b, 0x56, 0x0c, 0x89, 0x55
+.data1 	0xf4, 0x8b, 0x56, 0x14, 0x89, 0x55, 0xec, 0xff
+.data1 	0x75, 0xf8, 0xe8, 0xc2, 0x08, 0x00, 0x00, 0x59
+.data1 	0x89, 0x45, 0xe8, 0x50, 0xe8, 0x4b, 0x49, 0x00
+.data1 	0x00, 0x59, 0x05, 0x01, 0x00, 0x00, 0x00, 0x89
+.data1 	0x45, 0xf0, 0x39, 0x45, 0xf4, 0x7d, 0x06, 0x8b
+.data1 	0x55, 0xf4, 0x89, 0x55, 0xf0, 0xff, 0x75, 0xf0
+.data1 	0xff, 0x75, 0xec, 0x6a, 0x01, 0xff, 0x36, 0xff
+.data1 	0x75, 0xe8, 0x6a, 0x01, 0x68, 0xce, 0x8a, 0x00
+.data1 	0x00, 0xe8, 0x4a, 0x3d, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x1c, 0x89, 0xc7, 0x89, 0x7e, 0x04, 0x56, 0xff
+.data1 	0x36, 0xe8, 0x3e, 0x48, 0x00, 0x00, 0x59, 0x59
+.data1 	0x89, 0xc7, 0x85, 0xff, 0x74, 0x10, 0x57, 0xff
+.data1 	0x36, 0x68, 0xbc, 0x01, 0x00, 0x00, 0xe8, 0xcd
+.data1 	0x41, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c
+.data1 	0x56, 0x57, 0x8b, 0x75, 0x08, 0x31, 0xff, 0x83
+.data1 	0xff, 0x10, 0x7d, 0x10, 0x6b, 0xc7, 0x14, 0x8b
+.data1 	0x16, 0x39, 0x90, 0xf4, 0x2e, 0x00, 0x00, 0x74
+.data1 	0x03, 0x47, 0xeb, 0xeb, 0x83, 0xff, 0x10, 0x7c
+.data1 	0x10, 0xff, 0x36, 0x68, 0x0c, 0x02, 0x00, 0x00
+.data1 	0xe8, 0x93, 0x41, 0x00, 0x00, 0x59, 0x59, 0xeb
+.data1 	0x46, 0x8b, 0x56, 0x08, 0x89, 0x55, 0xf4, 0x6b
+.data1 	0xc7, 0x14, 0x05, 0xe4, 0x2e, 0x00, 0x00, 0x50
+.data1 	0xff, 0x36, 0xff, 0x75, 0xf4, 0xe8, 0x76, 0x05
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc7, 0x46, 0x04
+.data1 	0x00, 0x00, 0x00, 0x00, 0x56, 0xff, 0x36, 0xe8
+.data1 	0xc0, 0x47, 0x00, 0x00, 0x59, 0x59, 0x89, 0x45
+.data1 	0xf8, 0x85, 0xc0, 0x74, 0x12, 0xff, 0x75, 0xf8
+.data1 	0xff, 0x36, 0x68, 0xe4, 0x01, 0x00, 0x00, 0xe8
+.data1 	0x4c, 0x41, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x10, 0x56, 0x57, 0x8b, 0x75, 0x08, 0x8b, 0x56
+.data1 	0x08, 0x89, 0x55, 0xf8, 0x8b, 0x56, 0x0c, 0x89
+.data1 	0x55, 0xf4, 0x52, 0xff, 0x75, 0xf8, 0xe8, 0x83
+.data1 	0x08, 0x00, 0x00, 0x59, 0x59, 0x88, 0x45, 0xf3
+.data1 	0x0f, 0xb6, 0x55, 0xf3, 0x89, 0x56, 0x14, 0xc7
+.data1 	0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x56, 0xff
+.data1 	0x36, 0xe8, 0x66, 0x47, 0x00, 0x00, 0x59, 0x59
+.data1 	0x89, 0xc7, 0x85, 0xff, 0x74, 0x10, 0x57, 0xff
+.data1 	0x36, 0x68, 0x3c, 0x02, 0x00, 0x00, 0xe8, 0xf5
+.data1 	0x40, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x10
+.data1 	0x56, 0x57, 0x8b, 0x75, 0x08, 0x8b, 0x56, 0x08
+.data1 	0x89, 0x55, 0xf8, 0x8b, 0x56, 0x0c, 0x89, 0x55
+.data1 	0xf4, 0x52, 0xff, 0x75, 0xf8, 0xe8, 0x64, 0x08
+.data1 	0x00, 0x00, 0x59, 0x59, 0x89, 0x45, 0xf0, 0x89
+.data1 	0x46, 0x14, 0xc7, 0x46, 0x04, 0x00, 0x00, 0x00
+.data1 	0x00, 0x56, 0xff, 0x36, 0xe8, 0x13, 0x47, 0x00
+.data1 	0x00, 0x59, 0x59, 0x89, 0xc7, 0x85, 0xff, 0x74
+.data1 	0x10, 0x57, 0xff, 0x36, 0x68, 0x64, 0x02, 0x00
+.data1 	0x00, 0xe8, 0xa2, 0x40, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x10, 0x56, 0x57, 0x8b, 0x75, 0x08
+.data1 	0x8b, 0x56, 0x08, 0x89, 0x55, 0xf8, 0x8b, 0x56
+.data1 	0x0c, 0x89, 0x55, 0xf4, 0x52, 0xff, 0x75, 0xf8
+.data1 	0xe8, 0x49, 0x08, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0x45, 0xf0, 0x89, 0x46, 0x14, 0xc7, 0x46, 0x04
+.data1 	0x00, 0x00, 0x00, 0x00, 0x56, 0xff, 0x36, 0xe8
+.data1 	0xc0, 0x46, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc7
+.data1 	0x85, 0xff, 0x74, 0x10, 0x57, 0xff, 0x36, 0x68
+.data1 	0x8c, 0x02, 0x00, 0x00, 0xe8, 0x4f, 0x40, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x10, 0x56, 0x57
+.data1 	0x8b, 0x75, 0x08, 0x8b, 0x56, 0x08, 0x89, 0x55
+.data1 	0xf8, 0x8b, 0x56, 0x0c, 0x89, 0x55, 0xf4, 0x8b
+.data1 	0x56, 0x14, 0x88, 0x55, 0xf3, 0x0f, 0xb6, 0x45
+.data1 	0xf3, 0x50, 0xff, 0x75, 0xf4, 0xff, 0x75, 0xf8
+.data1 	0xe8, 0x21, 0x08, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xc7, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x56
+.data1 	0xff, 0x36, 0xe8, 0x65, 0x46, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0xc7, 0x85, 0xff, 0x74, 0x10, 0x57
+.data1 	0xff, 0x36, 0x68, 0xb4, 0x02, 0x00, 0x00, 0xe8
+.data1 	0xf4, 0x3f, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x10, 0x56, 0x57, 0x8b, 0x75, 0x08, 0x8b, 0x56
+.data1 	0x08, 0x89, 0x55, 0xf8, 0x8b, 0x56, 0x0c, 0x89
+.data1 	0x55, 0xf4, 0xba, 0xff, 0xff, 0x00, 0x00, 0x23
+.data1 	0x56, 0x14, 0x66, 0x89, 0x55, 0xf2, 0x0f, 0xb7
+.data1 	0x45, 0xf2, 0x50, 0xff, 0x75, 0xf4, 0xff, 0x75
+.data1 	0xf8, 0xe8, 0xfd, 0x07, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0xc7, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00
+.data1 	0x56, 0xff, 0x36, 0xe8, 0x04, 0x46, 0x00, 0x00
+.data1 	0x59, 0x59, 0x89, 0xc7, 0x85, 0xff, 0x74, 0x10
+.data1 	0x57, 0xff, 0x36, 0x68, 0xdc, 0x02, 0x00, 0x00
+.data1 	0xe8, 0x93, 0x3f, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x10, 0x56, 0x57, 0x8b, 0x75, 0x08, 0x8b
+.data1 	0x56, 0x08, 0x89, 0x55, 0xf8, 0x8b, 0x56, 0x0c
+.data1 	0x89, 0x55, 0xf4, 0x8b, 0x56, 0x14, 0x89, 0x55
+.data1 	0xf0, 0x52, 0xff, 0x75, 0xf4, 0xff, 0x75, 0xf8
+.data1 	0xe8, 0xe3, 0x07, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xc7, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x56
+.data1 	0xff, 0x36, 0xe8, 0xad, 0x45, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0xc7, 0x85, 0xff, 0x74, 0x10, 0x57
+.data1 	0xff, 0x36, 0x68, 0x04, 0x03, 0x00, 0x00, 0xe8
+.data1 	0x3c, 0x3f, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x08, 0x56, 0x57, 0x8b, 0x75, 0x08, 0x8b, 0x56
+.data1 	0x08, 0x89, 0x55, 0xf8, 0x52, 0xe8, 0x90, 0x05
+.data1 	0x00, 0x00, 0x59, 0xc7, 0x46, 0x04, 0x00, 0x00
+.data1 	0x00, 0x00, 0x56, 0xff, 0x36, 0xe8, 0x6a, 0x45
+.data1 	0x00, 0x00, 0x59, 0x59, 0x89, 0xc7, 0x85, 0xff
+.data1 	0x74, 0x10, 0x57, 0xff, 0x36, 0x68, 0x2c, 0x03
+.data1 	0x00, 0x00, 0xe8, 0xf9, 0x3e, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x6a, 0x62
+.data1 	0x8d, 0x45, 0xfc, 0x50, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x68, 0x39, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0x45, 0xf8, 0x85, 0xc0, 0x74, 0x0f, 0xff, 0x75
+.data1 	0xf8, 0x68, 0x58, 0x03, 0x00, 0x00, 0xe8, 0xc5
+.data1 	0x3e, 0x00, 0x00, 0x59, 0x59, 0x8b, 0x45, 0xfc
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08
+.data1 	0x6a, 0x77, 0x8d, 0x45, 0xfc, 0x50, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x36, 0x39, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x89, 0x45, 0xf8, 0x85, 0xc0, 0x74, 0x0f
+.data1 	0xff, 0x75, 0xf8, 0x68, 0x7c, 0x03, 0x00, 0x00
+.data1 	0xe8, 0x93, 0x3e, 0x00, 0x00, 0x59, 0x59, 0x8b
+.data1 	0x45, 0xfc, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x08, 0x6a, 0x6c, 0x8d, 0x45, 0xfc, 0x50
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x04, 0x39, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x45, 0xf8, 0x85, 0xc0
+.data1 	0x74, 0x0f, 0xff, 0x75, 0xf8, 0x68, 0xa0, 0x03
+.data1 	0x00, 0x00, 0xe8, 0x61, 0x3e, 0x00, 0x00, 0x59
+.data1 	0x59, 0x8b, 0x45, 0xfc, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x04, 0x6a, 0x62, 0xff, 0x75
+.data1 	0x0c, 0xff, 0x75, 0x08, 0xe8, 0x37, 0x39, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45, 0xfc, 0x85
+.data1 	0xc0, 0x74, 0x0f, 0xff, 0x75, 0xfc, 0x68, 0xc4
+.data1 	0x03, 0x00, 0x00, 0xe8, 0x30, 0x3e, 0x00, 0x00
+.data1 	0x59, 0x59, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x04, 0x6a, 0x77, 0xff, 0x75, 0x0c, 0xff
+.data1 	0x75, 0x08, 0xe8, 0x09, 0x39, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0x45, 0xfc, 0x85, 0xc0, 0x74
+.data1 	0x0f, 0xff, 0x75, 0xfc, 0x68, 0xe8, 0x03, 0x00
+.data1 	0x00, 0xe8, 0x02, 0x3e, 0x00, 0x00, 0x59, 0x59
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x04
+.data1 	0x6a, 0x6c, 0xff, 0x75, 0x0c, 0xff, 0x75, 0x08
+.data1 	0xe8, 0xdb, 0x38, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0x45, 0xfc, 0x85, 0xc0, 0x74, 0x0f, 0xff
+.data1 	0x75, 0xfc, 0x68, 0x0c, 0x04, 0x00, 0x00, 0xe8
+.data1 	0xd4, 0x3d, 0x00, 0x00, 0x59, 0x59, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x83, 0x3d
+.data1 	0x54, 0x26, 0x00, 0x00, 0x00, 0x0f, 0x84, 0x71
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x45, 0xfc, 0x00, 0x00
+.data1 	0x00, 0x00, 0x6a, 0x01, 0x6a, 0x00, 0x8d, 0x45
+.data1 	0xfc, 0x50, 0x6a, 0x00, 0x68, 0x40, 0x04, 0x00
+.data1 	0x00, 0x68, 0x44, 0x04, 0x00, 0x00, 0xe8, 0x2d
+.data1 	0x3b, 0x00, 0x00, 0x83, 0xc4, 0x18, 0x8b, 0x55
+.data1 	0xfc, 0x89, 0x15, 0x50, 0x26, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x01
+.data1 	0x6a, 0x00, 0x8d, 0x45, 0xfc, 0x50, 0x6a, 0x00
+.data1 	0x68, 0x30, 0x04, 0x00, 0x00, 0x68, 0x34, 0x04
+.data1 	0x00, 0x00, 0xe8, 0x01, 0x3b, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x18, 0x8b, 0x55, 0xfc, 0x89, 0x15, 0x44
+.data1 	0x26, 0x00, 0x00, 0xc7, 0x05, 0x54, 0x26, 0x00
+.data1 	0x00, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x11, 0x06
+.data1 	0x00, 0x00, 0xc7, 0x05, 0x54, 0x26, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x56, 0x31, 0xf6, 0x39, 0x35, 0x4c, 0x26
+.data1 	0x00, 0x00, 0x7e, 0x45, 0x89, 0xf2, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x55, 0x08, 0x0f
+.data1 	0xb6, 0x88, 0x54, 0x32, 0x00, 0x00, 0x39, 0xd1
+.data1 	0x75, 0x2c, 0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0x0f, 0xb6, 0x55, 0x0c, 0x0f, 0xb6, 0x88
+.data1 	0x55, 0x32, 0x00, 0x00, 0x39, 0xd1, 0x75, 0x16
+.data1 	0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f
+.data1 	0xb6, 0x55, 0x10, 0x0f, 0xb6, 0x88, 0x56, 0x32
+.data1 	0x00, 0x00, 0x39, 0xd1, 0x74, 0x03, 0x46, 0xeb
+.data1 	0xb3, 0x39, 0x35, 0x4c, 0x26, 0x00, 0x00, 0x7f
+.data1 	0x04, 0x31, 0xc0, 0xeb, 0x1e, 0x89, 0xf2, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x80, 0xb8, 0x5f, 0x32
+.data1 	0x00, 0x00, 0x00, 0x74, 0x04, 0x31, 0xc0, 0xeb
+.data1 	0x0a, 0x8b, 0x45, 0x14, 0x89, 0x30, 0xb8, 0x01
+.data1 	0x00, 0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x56, 0x31, 0xf6, 0x39, 0x35, 0x4c, 0x26
+.data1 	0x00, 0x00, 0x7e, 0x13, 0x89, 0xf2, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x80, 0xb8, 0x5f, 0x32, 0x00
+.data1 	0x00, 0x00, 0x74, 0x03, 0x46, 0xeb, 0xe5, 0x39
+.data1 	0x35, 0x4c, 0x26, 0x00, 0x00, 0x7f, 0x04, 0x31
+.data1 	0xc0, 0xeb, 0x32, 0x8b, 0x45, 0x08, 0x89, 0x30
+.data1 	0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x8b
+.data1 	0x55, 0x0c, 0x66, 0x8b, 0x88, 0x5a, 0x32, 0x00
+.data1 	0x00, 0x66, 0x89, 0x0a, 0x89, 0xf2, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x8b, 0x55, 0x10, 0x66, 0x8b
+.data1 	0x88, 0x5c, 0x32, 0x00, 0x00, 0x66, 0x89, 0x0a
+.data1 	0xb8, 0x01, 0x00, 0x00, 0x00, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x10, 0x42, 0x89, 0xd6, 0x39, 0x35, 0x4c, 0x26
+.data1 	0x00, 0x00, 0x7e, 0x13, 0x89, 0xf2, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x80, 0xb8, 0x5f, 0x32, 0x00
+.data1 	0x00, 0x00, 0x74, 0x03, 0x46, 0xeb, 0xe5, 0x39
+.data1 	0x35, 0x4c, 0x26, 0x00, 0x00, 0x7f, 0x04, 0x31
+.data1 	0xc0, 0xeb, 0x32, 0x8b, 0x45, 0x08, 0x89, 0x30
+.data1 	0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x8b
+.data1 	0x55, 0x0c, 0x66, 0x8b, 0x88, 0x5a, 0x32, 0x00
+.data1 	0x00, 0x66, 0x89, 0x0a, 0x89, 0xf2, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x8b, 0x55, 0x10, 0x66, 0x8b
+.data1 	0x88, 0x5c, 0x32, 0x00, 0x00, 0x66, 0x89, 0x0a
+.data1 	0xb8, 0x01, 0x00, 0x00, 0x00, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x1c, 0x56, 0x57
+.data1 	0x8b, 0x55, 0x08, 0xc1, 0xe2, 0x07, 0x89, 0xd0
+.data1 	0xc6, 0x80, 0x5f, 0x32, 0x00, 0x00, 0x01, 0x8b
+.data1 	0x55, 0x08, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0xff
+.data1 	0x75, 0x10, 0x05, 0xc4, 0x32, 0x00, 0x00, 0x50
+.data1 	0xe8, 0xdf, 0x42, 0x00, 0x00, 0x59, 0x59, 0x31
+.data1 	0xf6, 0x8b, 0x55, 0x08, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0x39, 0xb0, 0xc0, 0x32, 0x00, 0x00, 0x0f
+.data1 	0x8e, 0x51, 0x01, 0x00, 0x00, 0x8b, 0x55, 0x08
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89, 0xf2, 0xc1
+.data1 	0xe2, 0x04, 0x8b, 0x94, 0x10, 0x60, 0x32, 0x00
+.data1 	0x00, 0xf6, 0xc2, 0x02, 0x74, 0x12, 0x56, 0x68
+.data1 	0x5c, 0x05, 0x00, 0x00, 0xe8, 0x97, 0x3b, 0x00
+.data1 	0x00, 0x59, 0x59, 0xe9, 0x20, 0x01, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x08, 0xc1, 0xe2, 0x07, 0x89, 0xd0
+.data1 	0x89, 0xf2, 0xc1, 0xe2, 0x04, 0x8b, 0x94, 0x10
+.data1 	0x60, 0x32, 0x00, 0x00, 0xf6, 0xc2, 0x01, 0x0f
+.data1 	0x84, 0x86, 0x00, 0x00, 0x00, 0x8b, 0x55, 0x08
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89, 0xf2, 0xc1
+.data1 	0xe2, 0x04, 0x8b, 0x94, 0x10, 0x68, 0x32, 0x00
+.data1 	0x00, 0x89, 0x55, 0xec, 0x8b, 0x55, 0x08, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x89, 0xf2, 0xc1, 0xe2
+.data1 	0x04, 0x8b, 0x4d, 0xec, 0x03, 0x8c, 0x10, 0x6c
+.data1 	0x32, 0x00, 0x00, 0x83, 0xe9, 0x01, 0x89, 0x4d
+.data1 	0xf0, 0x83, 0x3d, 0x44, 0x26, 0x00, 0x00, 0x00
+.data1 	0x74, 0x16, 0xff, 0x75, 0xf0, 0xff, 0x75, 0xec
+.data1 	0xff, 0x75, 0x0c, 0x68, 0x20, 0x05, 0x00, 0x00
+.data1 	0xe8, 0x23, 0x3b, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x8d, 0x45, 0xec, 0x50, 0x6a, 0x00, 0x6a, 0x02
+.data1 	0xff, 0x75, 0x0c, 0xe8, 0x34, 0x36, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0x89, 0xc7, 0x85, 0xff, 0x0f
+.data1 	0x84, 0x93, 0x00, 0x00, 0x00, 0x57, 0xff, 0x75
+.data1 	0x0c, 0x68, 0xfc, 0x04, 0x00, 0x00, 0xe8, 0xf5
+.data1 	0x3a, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xe9, 0x7d
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x08, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x89, 0xf2, 0xc1, 0xe2, 0x04
+.data1 	0x8b, 0x94, 0x10, 0x68, 0x32, 0x00, 0x00, 0x89
+.data1 	0x55, 0xe4, 0x8b, 0x55, 0x08, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x89, 0xf2, 0xc1, 0xe2, 0x04, 0x8b
+.data1 	0x4d, 0xe4, 0x03, 0x8c, 0x10, 0x6c, 0x32, 0x00
+.data1 	0x00, 0x83, 0xe9, 0x01, 0x89, 0x4d, 0xe8, 0x83
+.data1 	0x3d, 0x44, 0x26, 0x00, 0x00, 0x00, 0x74, 0x16
+.data1 	0xff, 0x75, 0xe8, 0xff, 0x75, 0xe4, 0xff, 0x75
+.data1 	0x0c, 0x68, 0xb8, 0x04, 0x00, 0x00, 0xe8, 0x9d
+.data1 	0x3a, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x8d, 0x45
+.data1 	0xe4, 0x50, 0x6a, 0x00, 0x6a, 0x03, 0xff, 0x75
+.data1 	0x0c, 0xe8, 0xae, 0x35, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x10, 0x89, 0xc7, 0x85, 0xff, 0x74, 0x11, 0x57
+.data1 	0xff, 0x75, 0x0c, 0x68, 0x94, 0x04, 0x00, 0x00
+.data1 	0xe8, 0x73, 0x3a, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x46, 0xe9, 0x9b, 0xfe, 0xff, 0xff, 0x8b, 0x55
+.data1 	0x08, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x8a, 0x88
+.data1 	0x5e, 0x32, 0x00, 0x00, 0x88, 0x4d, 0xf7, 0x80
+.data1 	0x7d, 0xf7, 0xff, 0x74, 0x45, 0x83, 0x3d, 0x44
+.data1 	0x26, 0x00, 0x00, 0x00, 0x74, 0x11, 0x0f, 0xb6
+.data1 	0x45, 0xf7, 0x50, 0x68, 0x74, 0x04, 0x00, 0x00
+.data1 	0xe8, 0x3b, 0x3a, 0x00, 0x00, 0x59, 0x59, 0x6a
+.data1 	0x00, 0x0f, 0xb6, 0x45, 0xf7, 0x50, 0x6a, 0x04
+.data1 	0xff, 0x75, 0x0c, 0xe8, 0x4c, 0x35, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0x89, 0xc7, 0x85, 0xff, 0x74
+.data1 	0x11, 0x57, 0xff, 0x75, 0x0c, 0x68, 0x50, 0x04
+.data1 	0x00, 0x00, 0xe8, 0x11, 0x3a, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x56, 0x31, 0xf6, 0x39, 0x35, 0x4c, 0x26
+.data1 	0x00, 0x00, 0x7e, 0x3c, 0x89, 0xf2, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x80, 0xb8, 0x5f, 0x32, 0x00
+.data1 	0x00, 0x00, 0x74, 0x29, 0x89, 0xf2, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0xff, 0x75, 0x08, 0x05, 0xc4
+.data1 	0x32, 0x00, 0x00, 0x50, 0xe8, 0xd3, 0x40, 0x00
+.data1 	0x00, 0x59, 0x59, 0x85, 0xc0, 0x75, 0x0e, 0x89
+.data1 	0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0xc6, 0x80
+.data1 	0x5f, 0x32, 0x00, 0x00, 0x00, 0x46, 0xeb, 0xbc
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b, 0x55
+.data1 	0x08, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x8b, 0x55
+.data1 	0x0c, 0x66, 0x8b, 0x88, 0x5a, 0x32, 0x00, 0x00
+.data1 	0x66, 0x89, 0x0a, 0x8b, 0x55, 0x08, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x8b, 0x55, 0x10, 0x66, 0x8b
+.data1 	0x88, 0x5c, 0x32, 0x00, 0x00, 0x66, 0x89, 0x0a
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x04
+.data1 	0x0f, 0xb6, 0x45, 0x08, 0x50, 0xe8, 0x3a, 0x21
+.data1 	0x00, 0x00, 0x59, 0x89, 0x45, 0xfc, 0x50, 0xe8
+.data1 	0x50, 0x05, 0x00, 0x00, 0x59, 0xe8, 0xe7, 0x11
+.data1 	0x00, 0x00, 0xe8, 0x01, 0x13, 0x00, 0x00, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x56
+.data1 	0xc7, 0x45, 0xf8, 0x58, 0x26, 0x00, 0x00, 0xbe
+.data1 	0x64, 0x26, 0x00, 0x00, 0x8b, 0x55, 0x08, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x56, 0x8d, 0x5d, 0xf8
+.data1 	0x53, 0x0f, 0xb6, 0x98, 0x54, 0x32, 0x00, 0x00
+.data1 	0x53, 0xe8, 0xc8, 0x26, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x8b, 0x45, 0xf8, 0xff, 0x45, 0xf8, 0xc6
+.data1 	0x00, 0x2e, 0x8b, 0x55, 0x08, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x56, 0x8d, 0x5d, 0xf8, 0x53, 0x0f
+.data1 	0xb6, 0x98, 0x55, 0x32, 0x00, 0x00, 0x53, 0xe8
+.data1 	0xa2, 0x26, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b
+.data1 	0x45, 0xf8, 0xff, 0x45, 0xf8, 0xc6, 0x00, 0x2e
+.data1 	0x8b, 0x55, 0x08, 0xc1, 0xe2, 0x07, 0x89, 0xd0
+.data1 	0x56, 0x8d, 0x5d, 0xf8, 0x53, 0x0f, 0xb6, 0x98
+.data1 	0x56, 0x32, 0x00, 0x00, 0x53, 0xe8, 0x7c, 0x26
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xb8, 0x58, 0x26
+.data1 	0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0x31, 0xf6, 0x83, 0x3c, 0xf5, 0x24, 0x27
+.data1 	0x00, 0x00, 0x00, 0x74, 0x2c, 0x0f, 0xb7, 0x55
+.data1 	0x08, 0x0f, 0xb7, 0x0c, 0xf5, 0x20, 0x27, 0x00
+.data1 	0x00, 0x39, 0xd1, 0x75, 0x19, 0x0f, 0xb7, 0x55
+.data1 	0x0c, 0x0f, 0xb7, 0x0c, 0xf5, 0x22, 0x27, 0x00
+.data1 	0x00, 0x39, 0xd1, 0x75, 0x09, 0x8b, 0x04, 0xf5
+.data1 	0x24, 0x27, 0x00, 0x00, 0xeb, 0x05, 0x46, 0xeb
+.data1 	0xca, 0x31, 0xc0, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x04, 0x56, 0x8b, 0x55, 0x08
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x90
+.data1 	0x54, 0x32, 0x00, 0x00, 0x89, 0x55, 0xfc, 0x52
+.data1 	0xe8, 0x3f, 0x20, 0x00, 0x00, 0x59, 0x89, 0xc6
+.data1 	0x6b, 0xc6, 0x38, 0xff, 0x75, 0x0c, 0xff, 0x75
+.data1 	0x08, 0x56, 0xff, 0x90, 0x3c, 0x30, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x04, 0x56, 0x8b, 0x55, 0x08
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x90
+.data1 	0x54, 0x32, 0x00, 0x00, 0x89, 0x55, 0xfc, 0x52
+.data1 	0xe8, 0x07, 0x20, 0x00, 0x00, 0x59, 0x89, 0xc6
+.data1 	0x6b, 0xc6, 0x38, 0xff, 0x75, 0x0c, 0xff, 0x75
+.data1 	0x08, 0x56, 0xff, 0x90, 0x40, 0x30, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x04, 0x56, 0x8b, 0x55, 0x08
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x90
+.data1 	0x54, 0x32, 0x00, 0x00, 0x89, 0x55, 0xfc, 0x52
+.data1 	0xe8, 0xcf, 0x1f, 0x00, 0x00, 0x59, 0x89, 0xc6
+.data1 	0x6b, 0xc6, 0x38, 0xff, 0x75, 0x0c, 0xff, 0x75
+.data1 	0x08, 0x56, 0xff, 0x90, 0x44, 0x30, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x04, 0x56, 0x8b, 0x55, 0x08
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x90
+.data1 	0x54, 0x32, 0x00, 0x00, 0x89, 0x55, 0xfc, 0x52
+.data1 	0xe8, 0x97, 0x1f, 0x00, 0x00, 0x59, 0x89, 0xc6
+.data1 	0x6b, 0xc6, 0x38, 0x0f, 0xb7, 0x5d, 0x10, 0x53
+.data1 	0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0x56, 0xff
+.data1 	0x90, 0x48, 0x30, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x04, 0x56, 0x8b, 0x55, 0x08, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x0f, 0xb6, 0x90, 0x54, 0x32, 0x00
+.data1 	0x00, 0x89, 0x55, 0xfc, 0x52, 0xe8, 0x5a, 0x1f
+.data1 	0x00, 0x00, 0x59, 0x89, 0xc6, 0x6b, 0xc6, 0x38
+.data1 	0x0f, 0xb7, 0x5d, 0x10, 0x53, 0xff, 0x75, 0x0c
+.data1 	0xff, 0x75, 0x08, 0x56, 0xff, 0x90, 0x4c, 0x30
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x10, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x56, 0x8b
+.data1 	0x55, 0x08, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f
+.data1 	0xb6, 0x90, 0x54, 0x32, 0x00, 0x00, 0x89, 0x55
+.data1 	0xfc, 0x52, 0xe8, 0x1d, 0x1f, 0x00, 0x00, 0x59
+.data1 	0x89, 0xc6, 0x6b, 0xc6, 0x38, 0xff, 0x75, 0x10
+.data1 	0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0x56, 0xff
+.data1 	0x90, 0x50, 0x30, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x28, 0x56, 0x57, 0xc7, 0x45, 0xfc, 0x00, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x45, 0xf8, 0x00, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xf4, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x55, 0xfc, 0xc1, 0xe2, 0x10, 0x81, 0xe2
+.data1 	0x00, 0x00, 0xff, 0x00, 0x81, 0xca, 0x00, 0x00
+.data1 	0x00, 0x80, 0x8b, 0x4d, 0xf8, 0xc1, 0xe1, 0x0b
+.data1 	0x81, 0xe1, 0x00, 0xf8, 0x00, 0x00, 0x09, 0xd1
+.data1 	0x8b, 0x55, 0xf4, 0xc1, 0xe2, 0x08, 0x81, 0xe2
+.data1 	0x00, 0x07, 0x00, 0x00, 0x09, 0xca, 0x52, 0x68
+.data1 	0xf8, 0x0c, 0x00, 0x00, 0xe8, 0xf1, 0xf8, 0xff
+.data1 	0xff, 0x59, 0x59, 0x68, 0xfd, 0x0c, 0x00, 0x00
+.data1 	0xe8, 0xf3, 0xf7, 0xff, 0xff, 0x59, 0xc1, 0xe0
+.data1 	0x08, 0x8b, 0x55, 0xfc, 0xc1, 0xe2, 0x10, 0x81
+.data1 	0xe2, 0x00, 0x00, 0xff, 0x00, 0x81, 0xca, 0x00
+.data1 	0x00, 0x00, 0x80, 0x8b, 0x4d, 0xf8, 0xc1, 0xe1
+.data1 	0x0b, 0x81, 0xe1, 0x00, 0xf8, 0x00, 0x00, 0x09
+.data1 	0xd1, 0x8b, 0x55, 0xf4, 0xc1, 0xe2, 0x08, 0x81
+.data1 	0xe2, 0x00, 0x07, 0x00, 0x00, 0x09, 0xca, 0x50
+.data1 	0x52, 0x68, 0xf8, 0x0c, 0x00, 0x00, 0xe8, 0xa7
+.data1 	0xf8, 0xff, 0xff, 0x59, 0x59, 0x68, 0xfc, 0x0c
+.data1 	0x00, 0x00, 0xe8, 0xa9, 0xf7, 0xff, 0xff, 0x59
+.data1 	0x5a, 0x09, 0xd0, 0x25, 0xff, 0xff, 0x00, 0x00
+.data1 	0x66, 0x89, 0x45, 0xf2, 0x8b, 0x55, 0xfc, 0xc1
+.data1 	0xe2, 0x10, 0x81, 0xe2, 0x00, 0x00, 0xff, 0x00
+.data1 	0x81, 0xca, 0x00, 0x00, 0x00, 0x80, 0x8b, 0x4d
+.data1 	0xf8, 0xc1, 0xe1, 0x0b, 0x81, 0xe1, 0x00, 0xf8
+.data1 	0x00, 0x00, 0x09, 0xd1, 0x8b, 0x55, 0xf4, 0xc1
+.data1 	0xe2, 0x08, 0x81, 0xe2, 0x00, 0x07, 0x00, 0x00
+.data1 	0x09, 0xca, 0x52, 0x68, 0xf8, 0x0c, 0x00, 0x00
+.data1 	0xe8, 0x55, 0xf8, 0xff, 0xff, 0x59, 0x59, 0x68
+.data1 	0xff, 0x0c, 0x00, 0x00, 0xe8, 0x57, 0xf7, 0xff
+.data1 	0xff, 0x59, 0xc1, 0xe0, 0x08, 0x8b, 0x55, 0xfc
+.data1 	0xc1, 0xe2, 0x10, 0x81, 0xe2, 0x00, 0x00, 0xff
+.data1 	0x00, 0x81, 0xca, 0x00, 0x00, 0x00, 0x80, 0x8b
+.data1 	0x4d, 0xf8, 0xc1, 0xe1, 0x0b, 0x81, 0xe1, 0x00
+.data1 	0xf8, 0x00, 0x00, 0x09, 0xd1, 0x8b, 0x55, 0xf4
+.data1 	0xc1, 0xe2, 0x08, 0x81, 0xe2, 0x00, 0x07, 0x00
+.data1 	0x00, 0x09, 0xca, 0x50, 0x52, 0x68, 0xf8, 0x0c
+.data1 	0x00, 0x00, 0xe8, 0x0b, 0xf8, 0xff, 0xff, 0x59
+.data1 	0x59, 0x68, 0xfe, 0x0c, 0x00, 0x00, 0xe8, 0x0d
+.data1 	0xf7, 0xff, 0xff, 0x59, 0x5a, 0x09, 0xd0, 0x25
+.data1 	0xff, 0xff, 0x00, 0x00, 0x66, 0x89, 0x45, 0xf0
+.data1 	0x6a, 0x6c, 0x6a, 0x00, 0x68, 0xf8, 0x0c, 0x00
+.data1 	0x00, 0xe8, 0xd2, 0x30, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x89, 0x45, 0xec, 0x85, 0xc0, 0x74, 0x0f
+.data1 	0xff, 0x75, 0xec, 0x68, 0xc8, 0x05, 0x00, 0x00
+.data1 	0xe8, 0xcb, 0x35, 0x00, 0x00, 0x59, 0x59, 0x0f
+.data1 	0xb7, 0x55, 0xf2, 0x81, 0xfa, 0xff, 0xff, 0x00
+.data1 	0x00, 0x75, 0x10, 0x0f, 0xb7, 0x55, 0xf0, 0x81
+.data1 	0xfa, 0xff, 0xff, 0x00, 0x00, 0x0f, 0x84, 0x85
+.data1 	0x01, 0x00, 0x00, 0x83, 0x3d, 0x48, 0x26, 0x00
+.data1 	0x00, 0x0a, 0x7c, 0x18, 0xff, 0x35, 0x48, 0x26
+.data1 	0x00, 0x00, 0x68, 0xb0, 0x05, 0x00, 0x00, 0x68
+.data1 	0xc4, 0x05, 0x00, 0x00, 0xe8, 0xaf, 0x2f, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x35, 0x48, 0x26
+.data1 	0x00, 0x00, 0xff, 0x05, 0x48, 0x26, 0x00, 0x00
+.data1 	0x6b, 0xc6, 0x38, 0xc7, 0x80, 0x24, 0x30, 0x00
+.data1 	0x00, 0x01, 0x00, 0x00, 0x00, 0x6b, 0xc6, 0x38
+.data1 	0xc7, 0x80, 0x28, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x6b, 0xc6, 0x38, 0xc7, 0x80, 0x2c
+.data1 	0x30, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x6b
+.data1 	0xc6, 0x38, 0xc7, 0x80, 0x30, 0x30, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x6b, 0xc6, 0x38, 0xc7
+.data1 	0x80, 0x34, 0x30, 0x00, 0x00, 0xff, 0xff, 0xff
+.data1 	0xff, 0x6b, 0xc6, 0x38, 0xc7, 0x80, 0x38, 0x30
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0xc6
+.data1 	0x38, 0xc7, 0x80, 0x3c, 0x30, 0x00, 0x00, 0x3a
+.data1 	0x36, 0x00, 0x00, 0x6b, 0xc6, 0x38, 0xc7, 0x80
+.data1 	0x40, 0x30, 0x00, 0x00, 0xf6, 0x36, 0x00, 0x00
+.data1 	0x6b, 0xc6, 0x38, 0xc7, 0x80, 0x44, 0x30, 0x00
+.data1 	0x00, 0x45, 0x38, 0x00, 0x00, 0x6b, 0xc6, 0x38
+.data1 	0xc7, 0x80, 0x48, 0x30, 0x00, 0x00, 0xa3, 0x3a
+.data1 	0x00, 0x00, 0x6b, 0xc6, 0x38, 0xc7, 0x80, 0x4c
+.data1 	0x30, 0x00, 0x00, 0x5e, 0x3b, 0x00, 0x00, 0x6b
+.data1 	0xc6, 0x38, 0xc7, 0x80, 0x50, 0x30, 0x00, 0x00
+.data1 	0xac, 0x3c, 0x00, 0x00, 0x6b, 0xc6, 0x38, 0xc7
+.data1 	0x80, 0x54, 0x30, 0x00, 0x00, 0x0a, 0x3f, 0x00
+.data1 	0x00, 0x6b, 0xc6, 0x38, 0xc7, 0x80, 0x58, 0x30
+.data1 	0x00, 0x00, 0xb5, 0x3f, 0x00, 0x00, 0x0f, 0xb7
+.data1 	0x45, 0xf0, 0x50, 0x0f, 0xb7, 0x45, 0xf2, 0x50
+.data1 	0xe8, 0xd8, 0xfb, 0xff, 0xff, 0x59, 0x59, 0x89
+.data1 	0x45, 0xd8, 0x85, 0xc0, 0x75, 0x07, 0xc7, 0x45
+.data1 	0xd8, 0xa0, 0x05, 0x00, 0x00, 0x83, 0x3d, 0x44
+.data1 	0x26, 0x00, 0x00, 0x00, 0x74, 0x1a, 0x0f, 0xb7
+.data1 	0x45, 0xf0, 0x50, 0x0f, 0xb7, 0x45, 0xf2, 0x50
+.data1 	0xff, 0x75, 0xd8, 0x68, 0x80, 0x05, 0x00, 0x00
+.data1 	0xe8, 0x8b, 0x34, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x56, 0xe8, 0x5e, 0x00, 0x00, 0x00, 0x59, 0x56
+.data1 	0xe8, 0x1e, 0x16, 0x00, 0x00, 0x59, 0x89, 0x45
+.data1 	0xe4, 0x85, 0xc0, 0x74, 0x3a, 0x6b, 0xde, 0x38
+.data1 	0x8b, 0x93, 0x38, 0x30, 0x00, 0x00, 0x89, 0x55
+.data1 	0xdc, 0x31, 0xff, 0x39, 0x3d, 0x4c, 0x26, 0x00
+.data1 	0x00, 0x7e, 0x35, 0x89, 0xfa, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x0f, 0xb6, 0x90, 0x54, 0x32, 0x00
+.data1 	0x00, 0x39, 0x55, 0xdc, 0x75, 0x0e, 0x89, 0xfa
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0xc6, 0x80, 0x5f
+.data1 	0x32, 0x00, 0x00, 0x01, 0x47, 0xeb, 0xd4, 0x56
+.data1 	0xe8, 0x27, 0x18, 0x00, 0x00, 0x59, 0xe8, 0xa6
+.data1 	0x0c, 0x00, 0x00, 0xe8, 0xc0, 0x0d, 0x00, 0x00
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x56, 0x57, 0x83, 0x3d, 0x4c, 0x26
+.data1 	0x00, 0x00, 0x28, 0x7c, 0x18, 0xff, 0x35, 0x4c
+.data1 	0x26, 0x00, 0x00, 0x68, 0x38, 0x07, 0x00, 0x00
+.data1 	0x68, 0x50, 0x07, 0x00, 0x00, 0xe8, 0x1e, 0x2e
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x35, 0x4c
+.data1 	0x26, 0x00, 0x00, 0x6b, 0x45, 0x08, 0x38, 0x8b
+.data1 	0x90, 0x38, 0x30, 0x00, 0x00, 0x89, 0x55, 0xe0
+.data1 	0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7d, 0xfc, 0x20, 0x0f, 0x83, 0x84, 0x03, 0x00
+.data1 	0x00, 0x31, 0xff, 0x83, 0xff, 0x08, 0x0f, 0x83
+.data1 	0x71, 0x03, 0x00, 0x00, 0x8b, 0x55, 0xe0, 0x89
+.data1 	0xf1, 0xc1, 0xe1, 0x07, 0x89, 0xc8, 0x88, 0x90
+.data1 	0x54, 0x32, 0x00, 0x00, 0x8b, 0x55, 0xfc, 0x89
+.data1 	0xf1, 0xc1, 0xe1, 0x07, 0x89, 0xc8, 0x88, 0x90
+.data1 	0x55, 0x32, 0x00, 0x00, 0x89, 0xfa, 0x89, 0xf1
+.data1 	0xc1, 0xe1, 0x07, 0x89, 0xc8, 0x88, 0x90, 0x56
+.data1 	0x32, 0x00, 0x00, 0x68, 0x00, 0x70, 0x00, 0x00
+.data1 	0x56, 0xe8, 0x86, 0x22, 0x00, 0x00, 0x59, 0x59
+.data1 	0x6a, 0x00, 0x56, 0xe8, 0x1e, 0xfb, 0xff, 0xff
+.data1 	0x59, 0x59, 0x66, 0x89, 0x45, 0xf2, 0x6a, 0x02
+.data1 	0x56, 0xe8, 0x10, 0xfb, 0xff, 0xff, 0x59, 0x59
+.data1 	0x66, 0x89, 0x45, 0xf0, 0x6a, 0x0e, 0x56, 0xe8
+.data1 	0xca, 0xfa, 0xff, 0xff, 0x59, 0x59, 0x88, 0x45
+.data1 	0xed, 0x56, 0xe8, 0x69, 0x21, 0x00, 0x00, 0x59
+.data1 	0x66, 0x89, 0x45, 0xee, 0x0f, 0xb7, 0x55, 0xf2
+.data1 	0x81, 0xfa, 0xff, 0xff, 0x00, 0x00, 0x75, 0x0d
+.data1 	0x85, 0xff, 0x0f, 0x85, 0xe7, 0x02, 0x00, 0x00
+.data1 	0xe9, 0xe8, 0x02, 0x00, 0x00, 0x0f, 0xb7, 0x55
+.data1 	0xee, 0xf7, 0xc2, 0x00, 0x70, 0x00, 0x00, 0x74
+.data1 	0x2f, 0x83, 0x3d, 0x50, 0x26, 0x00, 0x00, 0x00
+.data1 	0x74, 0x19, 0x0f, 0xb7, 0x55, 0xee, 0x81, 0xe2
+.data1 	0x00, 0x70, 0x00, 0x00, 0x52, 0x68, 0x08, 0x07
+.data1 	0x00, 0x00, 0xe8, 0x19, 0x33, 0x00, 0x00, 0x59
+.data1 	0x59, 0xeb, 0x0d, 0x85, 0xff, 0x0f, 0x85, 0xac
+.data1 	0x02, 0x00, 0x00, 0xe9, 0xad, 0x02, 0x00, 0x00
+.data1 	0x0f, 0xb7, 0x45, 0xf0, 0x50, 0x0f, 0xb7, 0x45
+.data1 	0xf2, 0x50, 0xe8, 0x16, 0xfa, 0xff, 0xff, 0x59
+.data1 	0x59, 0x89, 0x45, 0xd8, 0x83, 0x3d, 0x44, 0x26
+.data1 	0x00, 0x00, 0x00, 0x0f, 0x84, 0x83, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7d, 0xd8, 0x00, 0x74, 0x23, 0x0f
+.data1 	0xb7, 0x45, 0xf0, 0x50, 0x0f, 0xb7, 0x45, 0xf2
+.data1 	0x50, 0xff, 0x75, 0xd8, 0x57, 0xff, 0x75, 0xfc
+.data1 	0xff, 0x75, 0x08, 0x68, 0xec, 0x06, 0x00, 0x00
+.data1 	0xe8, 0xc3, 0x32, 0x00, 0x00, 0x83, 0xc4, 0x1c
+.data1 	0xeb, 0x2a, 0x0f, 0xb7, 0x45, 0xf0, 0x50, 0x0f
+.data1 	0xb7, 0x45, 0xf2, 0x50, 0xe8, 0x77, 0x1f, 0x00
+.data1 	0x00, 0x59, 0x50, 0x0f, 0xb7, 0x45, 0xf2, 0x50
+.data1 	0x57, 0xff, 0x75, 0xfc, 0xff, 0x75, 0x08, 0x68
+.data1 	0xb0, 0x06, 0x00, 0x00, 0xe8, 0x97, 0x32, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x1c, 0x56, 0x68, 0x9c, 0x06
+.data1 	0x00, 0x00, 0xe8, 0x89, 0x32, 0x00, 0x00, 0x59
+.data1 	0x59, 0x6a, 0x2e, 0x56, 0xe8, 0x15, 0xfa, 0xff
+.data1 	0xff, 0x59, 0x59, 0x50, 0x6a, 0x2c, 0x56, 0xe8
+.data1 	0x0a, 0xfa, 0xff, 0xff, 0x59, 0x59, 0x50, 0x68
+.data1 	0x7c, 0x06, 0x00, 0x00, 0xe8, 0x67, 0x32, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x6a, 0x0b, 0x56, 0xe8
+.data1 	0xba, 0xf9, 0xff, 0xff, 0x59, 0x59, 0x88, 0x45
+.data1 	0xec, 0x6a, 0x0a, 0x56, 0xe8, 0xad, 0xf9, 0xff
+.data1 	0xff, 0x59, 0x59, 0x88, 0x45, 0xeb, 0x6a, 0x09
+.data1 	0x56, 0xe8, 0xa0, 0xf9, 0xff, 0xff, 0x59, 0x59
+.data1 	0x88, 0x45, 0xea, 0x0f, 0xb6, 0x45, 0xea, 0x50
+.data1 	0x0f, 0xb6, 0x45, 0xeb, 0x50, 0x0f, 0xb6, 0x45
+.data1 	0xec, 0x50, 0xe8, 0x56, 0x1f, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0x45, 0xdc, 0x85, 0xc0, 0x75
+.data1 	0x0e, 0x0f, 0xb6, 0x45, 0xec, 0x50, 0xe8, 0x11
+.data1 	0x1f, 0x00, 0x00, 0x59, 0x89, 0x45, 0xdc, 0x83
+.data1 	0x7d, 0xdc, 0x00, 0x75, 0x07, 0xc7, 0x45, 0xdc
+.data1 	0x6c, 0x06, 0x00, 0x00, 0x83, 0x3d, 0x44, 0x26
+.data1 	0x00, 0x00, 0x00, 0x74, 0x1f, 0x0f, 0xb6, 0x45
+.data1 	0xea, 0x50, 0x0f, 0xb6, 0x45, 0xeb, 0x50, 0x0f
+.data1 	0xb6, 0x45, 0xec, 0x50, 0xff, 0x75, 0xdc, 0x68
+.data1 	0x54, 0x06, 0x00, 0x00, 0xe8, 0xdf, 0x31, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x14, 0x57, 0xff, 0x75, 0xfc
+.data1 	0xff, 0x75, 0xe0, 0xe8, 0x81, 0x01, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x74, 0x22, 0x68
+.data1 	0x44, 0x06, 0x00, 0x00, 0xe8, 0xbf, 0x31, 0x00
+.data1 	0x00, 0x59, 0x85, 0xff, 0x0f, 0x85, 0x55, 0x01
+.data1 	0x00, 0x00, 0xf6, 0x45, 0xed, 0x80, 0x0f, 0x85
+.data1 	0x4b, 0x01, 0x00, 0x00, 0xe9, 0x4c, 0x01, 0x00
+.data1 	0x00, 0x8b, 0x35, 0x4c, 0x26, 0x00, 0x00, 0xff
+.data1 	0x05, 0x4c, 0x26, 0x00, 0x00, 0x89, 0xf2, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x8a, 0x4d, 0xec, 0x88
+.data1 	0x88, 0x57, 0x32, 0x00, 0x00, 0x89, 0xf2, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x8a, 0x4d, 0xeb, 0x88
+.data1 	0x88, 0x58, 0x32, 0x00, 0x00, 0x89, 0xf2, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x8a, 0x4d, 0xea, 0x88
+.data1 	0x88, 0x59, 0x32, 0x00, 0x00, 0x89, 0xf2, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x66, 0x8b, 0x55, 0xf2
+.data1 	0x66, 0x89, 0x90, 0x5a, 0x32, 0x00, 0x00, 0x89
+.data1 	0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x66, 0x8b
+.data1 	0x55, 0xf0, 0x66, 0x89, 0x90, 0x5c, 0x32, 0x00
+.data1 	0x00, 0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0
+.data1 	0xc6, 0x80, 0x5f, 0x32, 0x00, 0x00, 0x00, 0x89
+.data1 	0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0xc7, 0x80
+.data1 	0xc0, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x56, 0xe8, 0x32, 0x01, 0x00, 0x00, 0x59, 0xeb
+.data1 	0x39, 0x56, 0xe8, 0xef, 0x02, 0x00, 0x00, 0x59
+.data1 	0xeb, 0x43, 0x56, 0xe8, 0x83, 0x04, 0x00, 0x00
+.data1 	0x59, 0xeb, 0x3a, 0x56, 0xe8, 0xd5, 0x05, 0x00
+.data1 	0x00, 0x59, 0xeb, 0x31, 0x0f, 0xb6, 0x55, 0xed
+.data1 	0x83, 0xe2, 0x7f, 0x52, 0x57, 0xff, 0x75, 0xfc
+.data1 	0xff, 0x75, 0x08, 0x68, 0x20, 0x06, 0x00, 0x00
+.data1 	0xe8, 0xeb, 0x30, 0x00, 0x00, 0x83, 0xc4, 0x14
+.data1 	0xeb, 0x13, 0x0f, 0xb6, 0x55, 0xed, 0x83, 0xe2
+.data1 	0x7f, 0xbb, 0xec, 0x05, 0x00, 0x00, 0x89, 0xd0
+.data1 	0xe9, 0x1b, 0x3a, 0x00, 0x00, 0x83, 0x3d, 0x44
+.data1 	0x26, 0x00, 0x00, 0x00, 0x74, 0x07, 0x56, 0xe8
+.data1 	0x0f, 0x2a, 0x00, 0x00, 0x59, 0x0f, 0xb6, 0x55
+.data1 	0xec, 0xc1, 0xe2, 0x10, 0x0f, 0xb6, 0x4d, 0xeb
+.data1 	0xc1, 0xe1, 0x08, 0x09, 0xd1, 0x0f, 0xb6, 0x55
+.data1 	0xea, 0x09, 0xca, 0x89, 0x55, 0xf4, 0x81, 0xfa
+.data1 	0x00, 0x00, 0x03, 0x00, 0x74, 0x09, 0x81, 0x7d
+.data1 	0xf4, 0x00, 0x01, 0x00, 0x00, 0x75, 0x07, 0x56
+.data1 	0xe8, 0xb8, 0x1c, 0x00, 0x00, 0x59, 0x83, 0x3d
+.data1 	0x4c, 0x26, 0x00, 0x00, 0x28, 0x7c, 0x18, 0xff
+.data1 	0x35, 0x4c, 0x26, 0x00, 0x00, 0x68, 0x04, 0x06
+.data1 	0x00, 0x00, 0x68, 0x1c, 0x06, 0x00, 0x00, 0xe8
+.data1 	0x94, 0x2a, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b
+.data1 	0x35, 0x4c, 0x26, 0x00, 0x00, 0x85, 0xff, 0x75
+.data1 	0x06, 0xf6, 0x45, 0xed, 0x80, 0x74, 0x06, 0x47
+.data1 	0xe9, 0x86, 0xfc, 0xff, 0xff, 0xff, 0x45, 0xfc
+.data1 	0xe9, 0x72, 0xfc, 0xff, 0xff, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x56, 0x31, 0xf6, 0x39
+.data1 	0x35, 0x4c, 0x26, 0x00, 0x00, 0x7e, 0x4c, 0x89
+.data1 	0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f, 0xb6
+.data1 	0x55, 0x08, 0x0f, 0xb6, 0x88, 0x54, 0x32, 0x00
+.data1 	0x00, 0x39, 0xd1, 0x75, 0x33, 0x89, 0xf2, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x55, 0x0c
+.data1 	0x0f, 0xb6, 0x88, 0x55, 0x32, 0x00, 0x00, 0x39
+.data1 	0xd1, 0x75, 0x1d, 0x89, 0xf2, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x0f, 0xb6, 0x55, 0x10, 0x0f, 0xb6
+.data1 	0x88, 0x56, 0x32, 0x00, 0x00, 0x39, 0xd1, 0x75
+.data1 	0x07, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x05
+.data1 	0x46, 0xeb, 0xac, 0x31, 0xc0, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x14, 0x56, 0x57
+.data1 	0x8b, 0x7d, 0x08, 0x6a, 0x3c, 0x57, 0xe8, 0x3b
+.data1 	0xf7, 0xff, 0xff, 0x59, 0x59, 0x89, 0xc6, 0x6a
+.data1 	0x3d, 0x57, 0xe8, 0x2f, 0xf7, 0xff, 0xff, 0x59
+.data1 	0x59, 0x89, 0x45, 0xf8, 0x85, 0xf6, 0x75, 0x32
+.data1 	0x83, 0x7d, 0xf8, 0x00, 0x74, 0x27, 0x83, 0x3d
+.data1 	0x64, 0x26, 0x00, 0x00, 0x00, 0x74, 0x1e, 0x83
+.data1 	0x3d, 0x44, 0x26, 0x00, 0x00, 0x00, 0x74, 0x15
+.data1 	0xc7, 0x05, 0x64, 0x26, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x68, 0x0c, 0x08, 0x00, 0x00, 0xe8
+.data1 	0x9c, 0x2f, 0x00, 0x00, 0x59, 0xbe, 0xff, 0x00
+.data1 	0x00, 0x00, 0x89, 0xf2, 0x89, 0xf9, 0xc1, 0xe1
+.data1 	0x07, 0x89, 0xc8, 0x88, 0x90, 0x5e, 0x32, 0x00
+.data1 	0x00, 0x81, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x75
+.data1 	0x0a, 0x83, 0x7d, 0xf8, 0x00, 0x0f, 0x84, 0x47
+.data1 	0x01, 0x00, 0x00, 0x81, 0xfe, 0xff, 0x00, 0x00
+.data1 	0x00, 0x74, 0x2f, 0x83, 0x7d, 0xf8, 0x00, 0x74
+.data1 	0x29, 0x83, 0x3d, 0x44, 0x26, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x84, 0x2c, 0x01, 0x00, 0x00, 0xba, 0x40
+.data1 	0x00, 0x00, 0x00, 0x03, 0x55, 0xf8, 0x52, 0x56
+.data1 	0x68, 0xf8, 0x07, 0x00, 0x00, 0xe8, 0x46, 0x2f
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xe9, 0x10, 0x01
+.data1 	0x00, 0x00, 0x81, 0xfe, 0xff, 0x00, 0x00, 0x00
+.data1 	0x74, 0x40, 0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89, 0xd3
+.data1 	0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89, 0xd1, 0x0f
+.data1 	0xb6, 0x90, 0x56, 0x32, 0x00, 0x00, 0x52, 0x0f
+.data1 	0xb6, 0x83, 0x55, 0x32, 0x00, 0x00, 0x50, 0x0f
+.data1 	0xb6, 0x81, 0x54, 0x32, 0x00, 0x00, 0x50, 0x56
+.data1 	0x68, 0xb8, 0x07, 0x00, 0x00, 0xe8, 0xfe, 0x2e
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x14, 0xe9, 0xc8, 0x00
+.data1 	0x00, 0x00, 0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0x0f, 0xb6, 0x90, 0x54, 0x32, 0x00, 0x00
+.data1 	0x89, 0x55, 0xf4, 0x52, 0xe8, 0x9b, 0x16, 0x00
+.data1 	0x00, 0x59, 0x89, 0x45, 0xf0, 0x6b, 0x5d, 0xf0
+.data1 	0x38, 0x83, 0xbb, 0x24, 0x30, 0x00, 0x00, 0x03
+.data1 	0x75, 0x56, 0x6b, 0x5d, 0xf0, 0x38, 0x8b, 0x93
+.data1 	0x34, 0x30, 0x00, 0x00, 0x89, 0x55, 0xec, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd3, 0x0f, 0xb6, 0x93, 0x5e
+.data1 	0x32, 0x00, 0x00, 0x89, 0xd6, 0x81, 0xfe, 0xff
+.data1 	0x00, 0x00, 0x00, 0x74, 0x33, 0x83, 0x3d, 0x44
+.data1 	0x26, 0x00, 0x00, 0x00, 0x74, 0x0d, 0x56, 0x68
+.data1 	0x94, 0x07, 0x00, 0x00, 0xe8, 0x97, 0x2e, 0x00
+.data1 	0x00, 0x59, 0x59, 0x56, 0x6a, 0x3c, 0x57, 0xe8
+.data1 	0x92, 0xf6, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0xf2, 0x89, 0xf9, 0xc1, 0xe1, 0x07, 0x89, 0xc8
+.data1 	0x88, 0x90, 0x5e, 0x32, 0x00, 0x00, 0xeb, 0x4a
+.data1 	0x83, 0x3d, 0x44, 0x26, 0x00, 0x00, 0x00, 0x74
+.data1 	0x41, 0xba, 0x40, 0x00, 0x00, 0x00, 0x03, 0x55
+.data1 	0xf8, 0x89, 0xf9, 0xc1, 0xe1, 0x07, 0x89, 0xc8
+.data1 	0x89, 0xf9, 0xc1, 0xe1, 0x07, 0x89, 0xcb, 0x89
+.data1 	0xf9, 0xc1, 0xe1, 0x07, 0x52, 0x0f, 0xb6, 0x90
+.data1 	0x56, 0x32, 0x00, 0x00, 0x52, 0x0f, 0xb6, 0x83
+.data1 	0x55, 0x32, 0x00, 0x00, 0x50, 0x0f, 0xb6, 0x81
+.data1 	0x54, 0x32, 0x00, 0x00, 0x50, 0x68, 0x54, 0x07
+.data1 	0x00, 0x00, 0xe8, 0x31, 0x2e, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x14, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x28, 0x56, 0x57, 0x8b, 0x7d
+.data1 	0x08, 0x31, 0xf6, 0xc7, 0x45, 0xf4, 0x10, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7d, 0xf4, 0x24, 0x7f, 0x10
+.data1 	0x56, 0x57, 0xe8, 0x07, 0x04, 0x00, 0x00, 0x59
+.data1 	0x59, 0x46, 0x83, 0x45, 0xf4, 0x04, 0xeb, 0xea
+.data1 	0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x80
+.data1 	0xb8, 0x57, 0x32, 0x00, 0x00, 0x01, 0x0f, 0x85
+.data1 	0x5b, 0x01, 0x00, 0x00, 0x89, 0xfa, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x80, 0xb8, 0x58, 0x32, 0x00
+.data1 	0x00, 0x01, 0x0f, 0x85, 0x47, 0x01, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x89, 0xfa
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0xf6, 0x80, 0x59
+.data1 	0x32, 0x00, 0x00, 0x01, 0x75, 0x1b, 0x83, 0x3d
+.data1 	0x44, 0x26, 0x00, 0x00, 0x00, 0x74, 0x0b, 0x68
+.data1 	0x98, 0x08, 0x00, 0x00, 0xe8, 0xa7, 0x2d, 0x00
+.data1 	0x00, 0x59, 0xc7, 0x45, 0xe8, 0x01, 0x00, 0x00
+.data1 	0x00, 0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89, 0xd0
+.data1 	0xf6, 0x80, 0x59, 0x32, 0x00, 0x00, 0x04, 0x75
+.data1 	0x1b, 0x83, 0x3d, 0x44, 0x26, 0x00, 0x00, 0x00
+.data1 	0x74, 0x0b, 0x68, 0x58, 0x08, 0x00, 0x00, 0xe8
+.data1 	0x7c, 0x2d, 0x00, 0x00, 0x59, 0xc7, 0x45, 0xe4
+.data1 	0x01, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xf8, 0x00
+.data1 	0x00, 0x00, 0x00, 0x31, 0xf6, 0x89, 0xfa, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x39, 0xb0, 0xc0, 0x32
+.data1 	0x00, 0x00, 0x0f, 0x8e, 0xb7, 0x00, 0x00, 0x00
+.data1 	0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89
+.data1 	0xf2, 0xc1, 0xe2, 0x04, 0x8b, 0x94, 0x10, 0x64
+.data1 	0x32, 0x00, 0x00, 0x89, 0x55, 0xe0, 0x85, 0xd2
+.data1 	0x74, 0x06, 0x83, 0x7d, 0xe0, 0x01, 0x75, 0x27
+.data1 	0x83, 0x7d, 0xe8, 0x00, 0x74, 0x21, 0x83, 0x3d
+.data1 	0x44, 0x26, 0x00, 0x00, 0x00, 0x0f, 0x84, 0x7e
+.data1 	0x00, 0x00, 0x00, 0xff, 0x75, 0xe0, 0x68, 0x44
+.data1 	0x08, 0x00, 0x00, 0xe8, 0x18, 0x2d, 0x00, 0x00
+.data1 	0x59, 0x59, 0xe9, 0x6a, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7d, 0xe0, 0x02, 0x74, 0x06, 0x83, 0x7d, 0xe0
+.data1 	0x03, 0x75, 0x20, 0x83, 0x7d, 0xe4, 0x00, 0x74
+.data1 	0x1a, 0x83, 0x3d, 0x44, 0x26, 0x00, 0x00, 0x00
+.data1 	0x74, 0x4f, 0xff, 0x75, 0xe0, 0x68, 0x30, 0x08
+.data1 	0x00, 0x00, 0xe8, 0xe9, 0x2c, 0x00, 0x00, 0x59
+.data1 	0x59, 0xeb, 0x3e, 0x39, 0x75, 0xf8, 0x74, 0x39
+.data1 	0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89
+.data1 	0xf2, 0xc1, 0xe2, 0x04, 0x89, 0xf9, 0xc1, 0xe1
+.data1 	0x07, 0x89, 0xcb, 0x8b, 0x4d, 0xf8, 0xc1, 0xe1
+.data1 	0x04, 0x50, 0x8d, 0x84, 0x10, 0x60, 0x32, 0x00
+.data1 	0x00, 0x87, 0x04, 0x24, 0x8d, 0x84, 0x0b, 0x60
+.data1 	0x32, 0x00, 0x00, 0x50, 0xb9, 0x04, 0x00, 0x00
+.data1 	0x00, 0xe8, 0xda, 0x35, 0x00, 0x00, 0xff, 0x45
+.data1 	0xf8, 0x46, 0xe9, 0x36, 0xff, 0xff, 0xff, 0x89
+.data1 	0xfa, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x8b, 0x55
+.data1 	0xf8, 0x89, 0x90, 0xc0, 0x32, 0x00, 0x00, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x0c, 0x56, 0x57, 0x6a, 0x00, 0xff, 0x75, 0x08
+.data1 	0xe8, 0x79, 0x02, 0x00, 0x00, 0x59, 0x59, 0x6a
+.data1 	0x01, 0xff, 0x75, 0x08, 0xe8, 0x6d, 0x02, 0x00
+.data1 	0x00, 0x59, 0x59, 0x6a, 0x1c, 0xff, 0x75, 0x08
+.data1 	0xe8, 0xc1, 0xf3, 0xff, 0xff, 0x59, 0x59, 0x25
+.data1 	0xf0, 0x00, 0x00, 0x00, 0xc1, 0xe0, 0x08, 0x50
+.data1 	0x6a, 0x30, 0xff, 0x75, 0x08, 0xe8, 0xe4, 0xf3
+.data1 	0xff, 0xff, 0x59, 0x59, 0xc1, 0xe0, 0x10, 0x5a
+.data1 	0x09, 0xd0, 0x89, 0xc7, 0x6a, 0x1d, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x98, 0xf3, 0xff, 0xff, 0x59, 0x59
+.data1 	0x25, 0xf0, 0x00, 0x00, 0x00, 0xc1, 0xe0, 0x08
+.data1 	0x0d, 0xff, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x0f
+.data1 	0x00, 0x00, 0x50, 0x6a, 0x32, 0xff, 0x75, 0x08
+.data1 	0xe8, 0xb1, 0xf3, 0xff, 0xff, 0x59, 0x59, 0xc1
+.data1 	0xe0, 0x10, 0x5a, 0x09, 0xd0, 0x89, 0xc6, 0x89
+.data1 	0xf2, 0x29, 0xfa, 0x83, 0xc2, 0x01, 0x89, 0x55
+.data1 	0xf4, 0x83, 0x3d, 0x44, 0x26, 0x00, 0x00, 0x00
+.data1 	0x74, 0x12, 0xff, 0x75, 0xf4, 0x56, 0x57, 0x68
+.data1 	0x4c, 0x09, 0x00, 0x00, 0xe8, 0xef, 0x2b, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x10, 0x6a, 0x20, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x78, 0xf3, 0xff, 0xff, 0x59, 0x59
+.data1 	0x25, 0xf0, 0xff, 0x00, 0x00, 0xc1, 0xe0, 0x10
+.data1 	0x89, 0xc7, 0x6a, 0x22, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x62, 0xf3, 0xff, 0xff, 0x59, 0x59, 0x25, 0xf0
+.data1 	0xff, 0x00, 0x00, 0xc1, 0xe0, 0x10, 0x0d, 0xff
+.data1 	0xff, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0f, 0x00
+.data1 	0x89, 0xc6, 0x89, 0xf2, 0x29, 0xfa, 0x83, 0xc2
+.data1 	0x01, 0x89, 0x55, 0xf4, 0x83, 0x3d, 0x44, 0x26
+.data1 	0x00, 0x00, 0x00, 0x74, 0x12, 0xff, 0x75, 0xf4
+.data1 	0x56, 0x57, 0x68, 0x18, 0x09, 0x00, 0x00, 0xe8
+.data1 	0x94, 0x2b, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x6a
+.data1 	0x24, 0xff, 0x75, 0x08, 0xe8, 0x1d, 0xf3, 0xff
+.data1 	0xff, 0x59, 0x59, 0x25, 0xf0, 0xff, 0x00, 0x00
+.data1 	0xc1, 0xe0, 0x10, 0x89, 0xc7, 0x6a, 0x26, 0xff
+.data1 	0x75, 0x08, 0xe8, 0x07, 0xf3, 0xff, 0xff, 0x59
+.data1 	0x59, 0x25, 0xf0, 0xff, 0x00, 0x00, 0xc1, 0xe0
+.data1 	0x10, 0x0d, 0xff, 0xff, 0x00, 0x00, 0x0d, 0x00
+.data1 	0x00, 0x0f, 0x00, 0x89, 0xc6, 0x89, 0xf2, 0x29
+.data1 	0xfa, 0x83, 0xc2, 0x01, 0x89, 0x55, 0xf4, 0x83
+.data1 	0x3d, 0x44, 0x26, 0x00, 0x00, 0x00, 0x74, 0x12
+.data1 	0xff, 0x75, 0xf4, 0x56, 0x57, 0x68, 0xd8, 0x08
+.data1 	0x00, 0x00, 0xe8, 0x39, 0x2b, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x10, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57, 0x6a, 0x00
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x1e, 0x01, 0x00, 0x00
+.data1 	0x59, 0x59, 0x6a, 0x1c, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xe2, 0xf2, 0xff, 0xff, 0x59, 0x59, 0x89, 0xc7
+.data1 	0x6a, 0x20, 0xff, 0x75, 0x08, 0xe8, 0xd4, 0xf2
+.data1 	0xff, 0xff, 0x59, 0x59, 0xbe, 0xff, 0x0f, 0x00
+.data1 	0x00, 0x09, 0xc6, 0x89, 0xf2, 0x29, 0xfa, 0x83
+.data1 	0xc2, 0x01, 0x89, 0x55, 0xf4, 0x83, 0x3d, 0x44
+.data1 	0x26, 0x00, 0x00, 0x00, 0x74, 0x12, 0xff, 0x75
+.data1 	0xf4, 0x56, 0x57, 0x68, 0x10, 0x0a, 0x00, 0x00
+.data1 	0xe8, 0xdb, 0x2a, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x6a, 0x24, 0xff, 0x75, 0x08, 0xe8, 0x9c, 0xf2
+.data1 	0xff, 0xff, 0x59, 0x59, 0x89, 0xc7, 0x6a, 0x28
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x8e, 0xf2, 0xff, 0xff
+.data1 	0x59, 0x59, 0xbe, 0xff, 0x0f, 0x00, 0x00, 0x09
+.data1 	0xc6, 0x89, 0xf2, 0x29, 0xfa, 0x83, 0xc2, 0x01
+.data1 	0x89, 0x55, 0xf4, 0x83, 0x3d, 0x44, 0x26, 0x00
+.data1 	0x00, 0x00, 0x74, 0x12, 0xff, 0x75, 0xf4, 0x56
+.data1 	0x57, 0x68, 0xdc, 0x09, 0x00, 0x00, 0xe8, 0x95
+.data1 	0x2a, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x6a, 0x2c
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x56, 0xf2, 0xff, 0xff
+.data1 	0x59, 0x59, 0x89, 0xc7, 0x6a, 0x30, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x48, 0xf2, 0xff, 0xff, 0x59, 0x59
+.data1 	0xbe, 0x03, 0x00, 0x00, 0x00, 0x09, 0xc6, 0x89
+.data1 	0xf2, 0x29, 0xfa, 0x83, 0xc2, 0x01, 0x89, 0x55
+.data1 	0xf4, 0x83, 0x3d, 0x44, 0x26, 0x00, 0x00, 0x00
+.data1 	0x74, 0x12, 0xff, 0x75, 0xf4, 0x56, 0x57, 0x68
+.data1 	0xac, 0x09, 0x00, 0x00, 0xe8, 0x4f, 0x2a, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x10, 0x6a, 0x34, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x10, 0xf2, 0xff, 0xff, 0x59, 0x59
+.data1 	0x89, 0xc7, 0x6a, 0x38, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x02, 0xf2, 0xff, 0xff, 0x59, 0x59, 0xbe, 0x03
+.data1 	0x00, 0x00, 0x00, 0x09, 0xc6, 0x89, 0xf2, 0x29
+.data1 	0xfa, 0x83, 0xc2, 0x01, 0x89, 0x55, 0xf4, 0x83
+.data1 	0x3d, 0x44, 0x26, 0x00, 0x00, 0x00, 0x74, 0x12
+.data1 	0xff, 0x75, 0xf4, 0x56, 0x57, 0x68, 0x7c, 0x09
+.data1 	0x00, 0x00, 0xe8, 0x09, 0x2a, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x10, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x18, 0x56, 0x57, 0x8b, 0x7d
+.data1 	0x08, 0x8b, 0x55, 0x0c, 0xc1, 0xe2, 0x02, 0x83
+.data1 	0xc2, 0x10, 0x89, 0x55, 0xfc, 0x52, 0x57, 0xe8
+.data1 	0xb2, 0xf1, 0xff, 0xff, 0x59, 0x59, 0x89, 0x45
+.data1 	0xec, 0xa8, 0x01, 0x0f, 0x84, 0x06, 0x01, 0x00
+.data1 	0x00, 0x6a, 0xff, 0xff, 0x75, 0xfc, 0x57, 0xe8
+.data1 	0x4c, 0xf2, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0xff
+.data1 	0x75, 0xfc, 0x57, 0xe8, 0x8e, 0xf1, 0xff, 0xff
+.data1 	0x59, 0x59, 0x89, 0x45, 0xe8, 0xff, 0x75, 0xec
+.data1 	0xff, 0x75, 0xfc, 0x57, 0xe8, 0x2f, 0xf2, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x83, 0x65, 0xec, 0xfc
+.data1 	0x83, 0x65, 0xe8, 0xfc, 0x8b, 0x55, 0xe8, 0xf7
+.data1 	0xd2, 0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x83
+.data1 	0xc2, 0x01, 0x89, 0x55, 0xe8, 0x83, 0x3d, 0x44
+.data1 	0x26, 0x00, 0x00, 0x00, 0x74, 0x16, 0xff, 0x75
+.data1 	0xec, 0xff, 0x75, 0xe8, 0xff, 0x75, 0x0c, 0x68
+.data1 	0x90, 0x0a, 0x00, 0x00, 0xe8, 0x77, 0x29, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x10, 0x89, 0xfa, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x05, 0xc0, 0x32, 0x00, 0x00
+.data1 	0x89, 0xc6, 0x8b, 0x10, 0x89, 0xd1, 0x41, 0x89
+.data1 	0x0e, 0x89, 0x55, 0xf0, 0x89, 0xfa, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x8b, 0x55, 0xf0, 0xc1, 0xe2
+.data1 	0x04, 0xc7, 0x84, 0x10, 0x60, 0x32, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x89, 0xfa, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x8b, 0x55, 0xf0, 0xc1, 0xe2
+.data1 	0x04, 0x8b, 0x4d, 0xec, 0x89, 0x8c, 0x10, 0x68
+.data1 	0x32, 0x00, 0x00, 0x89, 0xfa, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x8b, 0x55, 0xf0, 0xc1, 0xe2, 0x04
+.data1 	0x8b, 0x4d, 0xe8, 0x89, 0x8c, 0x10, 0x6c, 0x32
+.data1 	0x00, 0x00, 0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0x8b, 0x55, 0xf0, 0xc1, 0xe2, 0x04, 0x8b
+.data1 	0x4d, 0x0c, 0x89, 0x8c, 0x10, 0x64, 0x32, 0x00
+.data1 	0x00, 0x83, 0x7d, 0xec, 0x00, 0x0f, 0x85, 0x6a
+.data1 	0x01, 0x00, 0x00, 0x89, 0xfa, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x8b, 0x55, 0xf0, 0xc1, 0xe2, 0x04
+.data1 	0x8d, 0x94, 0x10, 0x60, 0x32, 0x00, 0x00, 0x89
+.data1 	0xd6, 0xb9, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x0a
+.data1 	0x89, 0x0e, 0xe9, 0x46, 0x01, 0x00, 0x00, 0x6a
+.data1 	0xff, 0xff, 0x75, 0xfc, 0x57, 0xe8, 0x46, 0xf1
+.data1 	0xff, 0xff, 0x83, 0xc4, 0x0c, 0xff, 0x75, 0xfc
+.data1 	0x57, 0xe8, 0x88, 0xf0, 0xff, 0xff, 0x59, 0x59
+.data1 	0x89, 0x45, 0xe8, 0xff, 0x75, 0xec, 0xff, 0x75
+.data1 	0xfc, 0x57, 0xe8, 0x29, 0xf1, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x83, 0x7d, 0xe8, 0x00, 0x0f, 0x84
+.data1 	0x11, 0x01, 0x00, 0x00, 0xba, 0x08, 0x00, 0x00
+.data1 	0x00, 0x23, 0x55, 0xec, 0x31, 0xc0, 0x85, 0xd2
+.data1 	0x0f, 0x95, 0xc0, 0x89, 0x45, 0xf8, 0xba, 0x06
+.data1 	0x00, 0x00, 0x00, 0x23, 0x55, 0xec, 0x89, 0x55
+.data1 	0xf4, 0x83, 0x65, 0xec, 0xf0, 0x83, 0x65, 0xe8
+.data1 	0xf0, 0x8b, 0x55, 0xe8, 0xf7, 0xd2, 0x83, 0xc2
+.data1 	0x01, 0x89, 0x55, 0xe8, 0x83, 0x3d, 0x44, 0x26
+.data1 	0x00, 0x00, 0x00, 0x74, 0x3e, 0x83, 0x7d, 0xf8
+.data1 	0x00, 0x74, 0x07, 0xb8, 0x58, 0x0a, 0x00, 0x00
+.data1 	0xeb, 0x05, 0xb8, 0x54, 0x0a, 0x00, 0x00, 0x50
+.data1 	0xff, 0x75, 0xec, 0xff, 0x75, 0xe8, 0xff, 0x75
+.data1 	0x0c, 0x68, 0x68, 0x0a, 0x00, 0x00, 0xe8, 0x3d
+.data1 	0x28, 0x00, 0x00, 0x83, 0xc4, 0x14, 0x83, 0x7d
+.data1 	0xf4, 0x00, 0x74, 0x0f, 0xff, 0x75, 0xf4, 0x68
+.data1 	0x44, 0x0a, 0x00, 0x00, 0xe8, 0x27, 0x28, 0x00
+.data1 	0x00, 0x59, 0x59, 0x89, 0xfa, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x05, 0xc0, 0x32, 0x00, 0x00, 0x89
+.data1 	0xc6, 0x8b, 0x10, 0x89, 0xd1, 0x41, 0x89, 0x0e
+.data1 	0x89, 0x55, 0xf0, 0x89, 0xfa, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x8b, 0x55, 0xf0, 0xc1, 0xe2, 0x04
+.data1 	0xc7, 0x84, 0x10, 0x60, 0x32, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x89, 0xfa, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x8b, 0x55, 0xf0, 0xc1, 0xe2, 0x04
+.data1 	0x8b, 0x4d, 0xec, 0x89, 0x8c, 0x10, 0x68, 0x32
+.data1 	0x00, 0x00, 0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0x8b, 0x55, 0xf0, 0xc1, 0xe2, 0x04, 0x8b
+.data1 	0x4d, 0xe8, 0x89, 0x8c, 0x10, 0x6c, 0x32, 0x00
+.data1 	0x00, 0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89, 0xd0
+.data1 	0x8b, 0x55, 0xf0, 0xc1, 0xe2, 0x04, 0x8b, 0x4d
+.data1 	0x0c, 0x89, 0x8c, 0x10, 0x64, 0x32, 0x00, 0x00
+.data1 	0x83, 0x7d, 0xec, 0x00, 0x75, 0x1f, 0x89, 0xfa
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x8b, 0x55, 0xf0
+.data1 	0xc1, 0xe2, 0x04, 0x8d, 0x94, 0x10, 0x60, 0x32
+.data1 	0x00, 0x00, 0x89, 0xd6, 0xb9, 0x02, 0x00, 0x00
+.data1 	0x00, 0x0b, 0x0a, 0x89, 0x0e, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x10, 0x56
+.data1 	0x57, 0x31, 0xff, 0x39, 0x3d, 0x48, 0x26, 0x00
+.data1 	0x00, 0x0f, 0x8e, 0x05, 0x01, 0x00, 0x00, 0x6b
+.data1 	0xc7, 0x38, 0x83, 0xb8, 0x28, 0x30, 0x00, 0x00
+.data1 	0x00, 0x0f, 0x84, 0xef, 0x00, 0x00, 0x00, 0x57
+.data1 	0x68, 0x58, 0x0b, 0x00, 0x00, 0xe8, 0x56, 0x27
+.data1 	0x00, 0x00, 0x59, 0x59, 0xe8, 0x9b, 0x08, 0x00
+.data1 	0x00, 0x89, 0x45, 0xf8, 0x50, 0x68, 0x44, 0x0b
+.data1 	0x00, 0x00, 0xe8, 0x41, 0x27, 0x00, 0x00, 0x59
+.data1 	0x59, 0x6b, 0xc7, 0x38, 0x8b, 0xb0, 0x34, 0x30
+.data1 	0x00, 0x00, 0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0x0f, 0xb6, 0x90, 0x54, 0x32, 0x00, 0x00
+.data1 	0x89, 0x55, 0xf0, 0x85, 0xd2, 0x74, 0x0b, 0x68
+.data1 	0x00, 0x0b, 0x00, 0x00, 0xe8, 0x17, 0x27, 0x00
+.data1 	0x00, 0x59, 0x6b, 0xc7, 0x38, 0xc7, 0x80, 0x28
+.data1 	0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b
+.data1 	0xc7, 0x38, 0x8b, 0x55, 0xf8, 0x89, 0x90, 0x38
+.data1 	0x30, 0x00, 0x00, 0x56, 0x68, 0xf0, 0x0a, 0x00
+.data1 	0x00, 0xe8, 0xf2, 0x26, 0x00, 0x00, 0x59, 0x59
+.data1 	0xff, 0x75, 0xf0, 0x68, 0xe0, 0x0a, 0x00, 0x00
+.data1 	0xe8, 0xe3, 0x26, 0x00, 0x00, 0x59, 0x59, 0xff
+.data1 	0x75, 0xf0, 0x6a, 0x18, 0x56, 0xe8, 0xdc, 0xee
+.data1 	0xff, 0xff, 0x83, 0xc4, 0x0c, 0xff, 0x75, 0xf8
+.data1 	0x6a, 0x19, 0x56, 0xe8, 0xce, 0xee, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0xff, 0x75, 0xf8, 0x6a, 0x1a
+.data1 	0x56, 0xe8, 0xc0, 0xee, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0x6a, 0x04, 0x56, 0xe8, 0x45, 0xee, 0xff
+.data1 	0xff, 0x59, 0x59, 0x50, 0x68, 0xd4, 0x0a, 0x00
+.data1 	0x00, 0xe8, 0xa2, 0x26, 0x00, 0x00, 0x59, 0x59
+.data1 	0x6a, 0x1b, 0x56, 0xe8, 0xf6, 0xed, 0xff, 0xff
+.data1 	0x59, 0x59, 0x50, 0x68, 0xc4, 0x0a, 0x00, 0x00
+.data1 	0xe8, 0x8b, 0x26, 0x00, 0x00, 0x59, 0x59, 0x6a
+.data1 	0x3e, 0x56, 0xe8, 0x17, 0xee, 0xff, 0xff, 0x59
+.data1 	0x59, 0x50, 0x68, 0xb0, 0x0a, 0x00, 0x00, 0xe8
+.data1 	0x74, 0x26, 0x00, 0x00, 0x59, 0x59, 0x47, 0xe9
+.data1 	0xef, 0xfe, 0xff, 0xff, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x81, 0xec, 0x48, 0x01, 0x00
+.data1 	0x00, 0x56, 0x57, 0x68, 0x00, 0x01, 0x00, 0x00
+.data1 	0x8d, 0x85, 0xbc, 0xfe, 0xff, 0xff, 0x50, 0x68
+.data1 	0xa8, 0x0d, 0x00, 0x00, 0xe8, 0x36, 0x22, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45, 0xf4, 0x85
+.data1 	0xc0, 0x74, 0x15, 0xff, 0x75, 0xf4, 0x68, 0x8c
+.data1 	0x0d, 0x00, 0x00, 0x68, 0xa4, 0x0d, 0x00, 0x00
+.data1 	0xe8, 0x4b, 0x20, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xc7, 0x45, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x8d
+.data1 	0x95, 0xbc, 0xfe, 0xff, 0xff, 0x89, 0x55, 0xc0
+.data1 	0x8b, 0x55, 0xc0, 0x80, 0x3a, 0x00, 0x0f, 0x84
+.data1 	0xc4, 0x00, 0x00, 0x00, 0x6a, 0x10, 0x8d, 0x45
+.data1 	0xbc, 0x50, 0xff, 0x75, 0xc0, 0xe8, 0x8d, 0x2a
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45, 0xd4
+.data1 	0x8b, 0x55, 0xc0, 0x39, 0x55, 0xbc, 0x74, 0x08
+.data1 	0x8b, 0x55, 0xbc, 0x80, 0x3a, 0x3a, 0x74, 0x24
+.data1 	0x8d, 0x85, 0xbc, 0xfe, 0xff, 0xff, 0x50, 0x68
+.data1 	0x60, 0x0d, 0x00, 0x00, 0xe8, 0xd7, 0x25, 0x00
+.data1 	0x00, 0x59, 0x59, 0x68, 0x00, 0x80, 0x00, 0x00
+.data1 	0x6a, 0x00, 0x6a, 0x00, 0xe8, 0xe7, 0x1f, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55, 0xbc, 0x83
+.data1 	0xc2, 0x01, 0x89, 0x55, 0xc0, 0x6a, 0x10, 0x8d
+.data1 	0x45, 0xbc, 0x50, 0xff, 0x75, 0xc0, 0xe8, 0x3c
+.data1 	0x2a, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45
+.data1 	0xd0, 0x8b, 0x55, 0xc0, 0x39, 0x55, 0xbc, 0x74
+.data1 	0x0d, 0x8b, 0x55, 0xbc, 0x80, 0x3a, 0x2c, 0x74
+.data1 	0x29, 0x80, 0x3a, 0x00, 0x74, 0x24, 0x8d, 0x85
+.data1 	0xbc, 0xfe, 0xff, 0xff, 0x50, 0x68, 0x34, 0x0d
+.data1 	0x00, 0x00, 0xe8, 0x81, 0x25, 0x00, 0x00, 0x59
+.data1 	0x59, 0x68, 0x00, 0x80, 0x00, 0x00, 0x6a, 0x00
+.data1 	0x6a, 0x00, 0xe8, 0x91, 0x1f, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x8b, 0x55, 0xbc, 0x83, 0xc2, 0x01
+.data1 	0x89, 0x55, 0xc0, 0x8b, 0x55, 0xd0, 0x03, 0x55
+.data1 	0xd4, 0x39, 0x55, 0xe8, 0x0f, 0x83, 0x3e, 0xff
+.data1 	0xff, 0xff, 0x8b, 0x55, 0xd0, 0x03, 0x55, 0xd4
+.data1 	0x89, 0x55, 0xe8, 0xe9, 0x30, 0xff, 0xff, 0xff
+.data1 	0xc7, 0x45, 0xe4, 0x00, 0x00, 0x00, 0xfe, 0x83
+.data1 	0x3d, 0x44, 0x26, 0x00, 0x00, 0x00, 0x74, 0x13
+.data1 	0xff, 0x75, 0xe4, 0xff, 0x75, 0xe8, 0x68, 0x08
+.data1 	0x0d, 0x00, 0x00, 0xe8, 0x28, 0x25, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x31, 0xf6, 0x39, 0x35, 0x4c
+.data1 	0x26, 0x00, 0x00, 0x0f, 0x8e, 0xc3, 0x00, 0x00
+.data1 	0x00, 0x31, 0xff, 0x89, 0xf2, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x39, 0xb8, 0xc0, 0x32, 0x00, 0x00
+.data1 	0x0f, 0x8e, 0xa8, 0x00, 0x00, 0x00, 0x89, 0xf2
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89, 0xfa, 0xc1
+.data1 	0xe2, 0x04, 0x8b, 0x94, 0x10, 0x60, 0x32, 0x00
+.data1 	0x00, 0xf6, 0xc2, 0x01, 0x0f, 0x85, 0x86, 0x00
+.data1 	0x00, 0x00, 0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0x89, 0xfa, 0xc1, 0xe2, 0x04, 0x8b, 0x94
+.data1 	0x10, 0x60, 0x32, 0x00, 0x00, 0xf6, 0xc2, 0x02
+.data1 	0x0f, 0x85, 0x6a, 0x00, 0x00, 0x00, 0x89, 0xf2
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89, 0xfa, 0xc1
+.data1 	0xe2, 0x04, 0x8b, 0x94, 0x10, 0x68, 0x32, 0x00
+.data1 	0x00, 0x89, 0x55, 0xd4, 0x89, 0xf2, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x89, 0xfa, 0xc1, 0xe2, 0x04
+.data1 	0x8b, 0x94, 0x10, 0x6c, 0x32, 0x00, 0x00, 0x89
+.data1 	0x55, 0xd0, 0x8b, 0x55, 0xe4, 0x39, 0x55, 0xd4
+.data1 	0x73, 0x36, 0x8b, 0x55, 0xd0, 0x03, 0x55, 0xd4
+.data1 	0x39, 0x55, 0xe8, 0x73, 0x2b, 0x8b, 0x55, 0xd0
+.data1 	0x03, 0x55, 0xd4, 0x2b, 0x55, 0xe8, 0x89, 0x55
+.data1 	0xc8, 0x8b, 0x55, 0xe4, 0x2b, 0x55, 0xd4, 0x89
+.data1 	0x55, 0xc4, 0x39, 0x55, 0xc8, 0x73, 0x0b, 0x8b
+.data1 	0x55, 0xd0, 0x03, 0x55, 0xd4, 0x89, 0x55, 0xe8
+.data1 	0xeb, 0x06, 0x8b, 0x55, 0xd4, 0x89, 0x55, 0xe4
+.data1 	0x47, 0xe9, 0x45, 0xff, 0xff, 0xff, 0x46, 0xe9
+.data1 	0x31, 0xff, 0xff, 0xff, 0x83, 0x3d, 0x44, 0x26
+.data1 	0x00, 0x00, 0x00, 0x74, 0x13, 0xff, 0x75, 0xe4
+.data1 	0xff, 0x75, 0xe8, 0x68, 0xd4, 0x0c, 0x00, 0x00
+.data1 	0xe8, 0x3b, 0x24, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x8b, 0x55, 0xe8, 0x39, 0x55, 0xe4, 0x73, 0x24
+.data1 	0xff, 0x75, 0xe4, 0xff, 0x75, 0xe8, 0x68, 0xac
+.data1 	0x0c, 0x00, 0x00, 0xe8, 0x20, 0x24, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x68, 0x00, 0x80, 0x00, 0x00
+.data1 	0x6a, 0x00, 0x6a, 0x00, 0xe8, 0x2f, 0x1e, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xc7, 0x45, 0xdc, 0x00
+.data1 	0x00, 0x01, 0x00, 0xc7, 0x45, 0xe0, 0x00, 0x04
+.data1 	0x00, 0x00, 0x31, 0xf6, 0x39, 0x35, 0x4c, 0x26
+.data1 	0x00, 0x00, 0x0f, 0x8e, 0xbc, 0x00, 0x00, 0x00
+.data1 	0x31, 0xff, 0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0x39, 0xb8, 0xc0, 0x32, 0x00, 0x00, 0x0f
+.data1 	0x8e, 0xa1, 0x00, 0x00, 0x00, 0x89, 0xf2, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x89, 0xfa, 0xc1, 0xe2
+.data1 	0x04, 0x8b, 0x94, 0x10, 0x60, 0x32, 0x00, 0x00
+.data1 	0xf6, 0xc2, 0x01, 0x0f, 0x84, 0x7f, 0x00, 0x00
+.data1 	0x00, 0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0
+.data1 	0x89, 0xfa, 0xc1, 0xe2, 0x04, 0x8b, 0x94, 0x10
+.data1 	0x60, 0x32, 0x00, 0x00, 0xf6, 0xc2, 0x02, 0x0f
+.data1 	0x85, 0x63, 0x00, 0x00, 0x00, 0x89, 0xf2, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x89, 0xfa, 0xc1, 0xe2
+.data1 	0x04, 0x8b, 0x94, 0x10, 0x68, 0x32, 0x00, 0x00
+.data1 	0x89, 0x55, 0xd4, 0x89, 0xf2, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x89, 0xfa, 0xc1, 0xe2, 0x04, 0x8b
+.data1 	0x94, 0x10, 0x6c, 0x32, 0x00, 0x00, 0x89, 0x55
+.data1 	0xd0, 0x8b, 0x55, 0xdc, 0x39, 0x55, 0xd4, 0x73
+.data1 	0x2f, 0x8b, 0x55, 0xd0, 0x03, 0x55, 0xd4, 0x39
+.data1 	0x55, 0xe0, 0x73, 0x24, 0x8b, 0x55, 0xd0, 0x03
+.data1 	0x55, 0xd4, 0x2b, 0x55, 0xe0, 0x8b, 0x4d, 0xdc
+.data1 	0x2b, 0x4d, 0xd4, 0x39, 0xca, 0x73, 0x0b, 0x8b
+.data1 	0x55, 0xd0, 0x03, 0x55, 0xd4, 0x89, 0x55, 0xe0
+.data1 	0xeb, 0x06, 0x8b, 0x55, 0xd4, 0x89, 0x55, 0xdc
+.data1 	0x47, 0xe9, 0x4c, 0xff, 0xff, 0xff, 0x46, 0xe9
+.data1 	0x38, 0xff, 0xff, 0xff, 0x8b, 0x55, 0xe0, 0x39
+.data1 	0x55, 0xdc, 0x73, 0x2b, 0x83, 0x3d, 0x44, 0x26
+.data1 	0x00, 0x00, 0x00, 0x74, 0x0d, 0x68, 0x88, 0x0c
+.data1 	0x00, 0x00, 0xe8, 0x19, 0x23, 0x00, 0x00, 0x59
+.data1 	0xeb, 0x15, 0xff, 0x75, 0xdc, 0x68, 0x70, 0x0c
+.data1 	0x00, 0x00, 0x68, 0x84, 0x0c, 0x00, 0x00, 0xe8
+.data1 	0x24, 0x1d, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x83
+.data1 	0x3d, 0x44, 0x26, 0x00, 0x00, 0x00, 0x74, 0x13
+.data1 	0xff, 0x75, 0xdc, 0xff, 0x75, 0xe0, 0x68, 0x54
+.data1 	0x0c, 0x00, 0x00, 0xe8, 0xe8, 0x22, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x31, 0xf6, 0x39, 0x35, 0x4c
+.data1 	0x26, 0x00, 0x00, 0x0f, 0x8e, 0x00, 0x03, 0x00
+.data1 	0x00, 0x31, 0xff, 0x89, 0xf2, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x39, 0xb8, 0xc0, 0x32, 0x00, 0x00
+.data1 	0x0f, 0x8e, 0x5d, 0x01, 0x00, 0x00, 0x89, 0xf2
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89, 0xfa, 0xc1
+.data1 	0xe2, 0x04, 0x8b, 0x94, 0x10, 0x60, 0x32, 0x00
+.data1 	0x00, 0xf6, 0xc2, 0x01, 0x0f, 0x85, 0x3b, 0x01
+.data1 	0x00, 0x00, 0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0x89, 0xfa, 0xc1, 0xe2, 0x04, 0x8b, 0x94
+.data1 	0x10, 0x60, 0x32, 0x00, 0x00, 0xf6, 0xc2, 0x02
+.data1 	0x0f, 0x84, 0x1f, 0x01, 0x00, 0x00, 0x89, 0xf2
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89, 0xfa, 0xc1
+.data1 	0xe2, 0x04, 0x8b, 0x94, 0x10, 0x6c, 0x32, 0x00
+.data1 	0x00, 0x89, 0x55, 0xd0, 0x81, 0xfa, 0x00, 0x10
+.data1 	0x00, 0x00, 0x73, 0x07, 0xc7, 0x45, 0xd0, 0x00
+.data1 	0x10, 0x00, 0x00, 0x8b, 0x55, 0xe4, 0x2b, 0x55
+.data1 	0xd0, 0x89, 0x55, 0xd4, 0x8b, 0x55, 0xd0, 0x4a
+.data1 	0xf7, 0xd2, 0x21, 0x55, 0xd4, 0x8b, 0x55, 0xe8
+.data1 	0x39, 0x55, 0xd4, 0x73, 0x15, 0xff, 0x75, 0xd4
+.data1 	0x68, 0x3c, 0x0c, 0x00, 0x00, 0x68, 0x50, 0x0c
+.data1 	0x00, 0x00, 0xe8, 0x59, 0x1c, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x8b, 0x55, 0xd4, 0x89, 0x55, 0xe4
+.data1 	0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89
+.data1 	0xfa, 0xc1, 0xe2, 0x04, 0x8b, 0x94, 0x10, 0x64
+.data1 	0x32, 0x00, 0x00, 0x89, 0x55, 0xf0, 0xc1, 0xe2
+.data1 	0x02, 0x83, 0xc2, 0x10, 0x89, 0x55, 0xec, 0x52
+.data1 	0x56, 0xe8, 0xd8, 0xe9, 0xff, 0xff, 0x59, 0x59
+.data1 	0x89, 0x45, 0xcc, 0x0b, 0x45, 0xd4, 0x50, 0xff
+.data1 	0x75, 0xec, 0x56, 0xe8, 0x78, 0xea, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x83, 0x3d, 0x44, 0x26, 0x00
+.data1 	0x00, 0x00, 0x74, 0x43, 0x89, 0xf2, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x89, 0xf2, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd3, 0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd1, 0xff, 0x75, 0xf0, 0x0f, 0xb6, 0x90, 0x56
+.data1 	0x32, 0x00, 0x00, 0x52, 0x0f, 0xb6, 0x83, 0x55
+.data1 	0x32, 0x00, 0x00, 0x50, 0x0f, 0xb6, 0x81, 0x54
+.data1 	0x32, 0x00, 0x00, 0x50, 0xff, 0x75, 0xd0, 0xff
+.data1 	0x75, 0xd4, 0x68, 0x00, 0x0c, 0x00, 0x00, 0xe8
+.data1 	0xac, 0x21, 0x00, 0x00, 0x83, 0xc4, 0x1c, 0x89
+.data1 	0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89, 0xfa
+.data1 	0xc1, 0xe2, 0x04, 0x8b, 0x4d, 0xd4, 0x89, 0x8c
+.data1 	0x10, 0x68, 0x32, 0x00, 0x00, 0x89, 0xf2, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x89, 0xfa, 0xc1, 0xe2
+.data1 	0x04, 0x8d, 0x94, 0x10, 0x60, 0x32, 0x00, 0x00
+.data1 	0x89, 0x95, 0xb8, 0xfe, 0xff, 0xff, 0xb9, 0xfd
+.data1 	0xff, 0xff, 0xff, 0x23, 0x0a, 0x8b, 0x85, 0xb8
+.data1 	0xfe, 0xff, 0xff, 0x89, 0x08, 0x47, 0xe9, 0x90
+.data1 	0xfe, 0xff, 0xff, 0x8b, 0x55, 0xdc, 0x89, 0x55
+.data1 	0xd8, 0x31, 0xff, 0x89, 0xf2, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x39, 0xb8, 0xc0, 0x32, 0x00, 0x00
+.data1 	0x0f, 0x8e, 0x55, 0x01, 0x00, 0x00, 0x89, 0xf2
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89, 0xfa, 0xc1
+.data1 	0xe2, 0x04, 0x8b, 0x94, 0x10, 0x60, 0x32, 0x00
+.data1 	0x00, 0xf6, 0xc2, 0x01, 0x0f, 0x84, 0x33, 0x01
+.data1 	0x00, 0x00, 0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0x89, 0xfa, 0xc1, 0xe2, 0x04, 0x8b, 0x94
+.data1 	0x10, 0x60, 0x32, 0x00, 0x00, 0xf6, 0xc2, 0x02
+.data1 	0x0f, 0x84, 0x17, 0x01, 0x00, 0x00, 0x89, 0xf2
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89, 0xfa, 0xc1
+.data1 	0xe2, 0x04, 0x8b, 0x94, 0x10, 0x6c, 0x32, 0x00
+.data1 	0x00, 0x89, 0x55, 0xd0, 0x8b, 0x55, 0xdc, 0x2b
+.data1 	0x55, 0xd0, 0x89, 0x55, 0xd4, 0x8b, 0x55, 0xd0
+.data1 	0x4a, 0xf7, 0xd2, 0x21, 0x55, 0xd4, 0x81, 0x65
+.data1 	0xd4, 0xff, 0xfc, 0x00, 0x00, 0x8b, 0x55, 0xe0
+.data1 	0x39, 0x55, 0xd4, 0x73, 0x15, 0xff, 0x75, 0xd4
+.data1 	0x68, 0xe8, 0x0b, 0x00, 0x00, 0x68, 0xfc, 0x0b
+.data1 	0x00, 0x00, 0xe8, 0xe9, 0x1a, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x8b, 0x55, 0xd4, 0x89, 0x55, 0xdc
+.data1 	0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89
+.data1 	0xfa, 0xc1, 0xe2, 0x04, 0x8b, 0x94, 0x10, 0x64
+.data1 	0x32, 0x00, 0x00, 0x89, 0x55, 0xf0, 0xc1, 0xe2
+.data1 	0x02, 0x83, 0xc2, 0x10, 0x89, 0x55, 0xec, 0x52
+.data1 	0x56, 0xe8, 0x68, 0xe8, 0xff, 0xff, 0x59, 0x59
+.data1 	0x89, 0x45, 0xcc, 0x0b, 0x45, 0xd4, 0x50, 0xff
+.data1 	0x75, 0xec, 0x56, 0xe8, 0x08, 0xe9, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x83, 0x3d, 0x44, 0x26, 0x00
+.data1 	0x00, 0x00, 0x74, 0x43, 0x89, 0xf2, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x89, 0xf2, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd3, 0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd1, 0xff, 0x75, 0xf0, 0x0f, 0xb6, 0x90, 0x56
+.data1 	0x32, 0x00, 0x00, 0x52, 0x0f, 0xb6, 0x83, 0x55
+.data1 	0x32, 0x00, 0x00, 0x50, 0x0f, 0xb6, 0x81, 0x54
+.data1 	0x32, 0x00, 0x00, 0x50, 0xff, 0x75, 0xd0, 0xff
+.data1 	0x75, 0xd4, 0x68, 0xac, 0x0b, 0x00, 0x00, 0xe8
+.data1 	0x3c, 0x20, 0x00, 0x00, 0x83, 0xc4, 0x1c, 0x89
+.data1 	0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89, 0xfa
+.data1 	0xc1, 0xe2, 0x04, 0x8b, 0x4d, 0xd4, 0x89, 0x8c
+.data1 	0x10, 0x68, 0x32, 0x00, 0x00, 0x89, 0xf2, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x89, 0xfa, 0xc1, 0xe2
+.data1 	0x04, 0x8d, 0x94, 0x10, 0x60, 0x32, 0x00, 0x00
+.data1 	0x89, 0x95, 0xb8, 0xfe, 0xff, 0xff, 0xb9, 0xfd
+.data1 	0xff, 0xff, 0xff, 0x23, 0x0a, 0x8b, 0x85, 0xb8
+.data1 	0xfe, 0xff, 0xff, 0x89, 0x08, 0x47, 0xe9, 0x98
+.data1 	0xfe, 0xff, 0xff, 0x8b, 0x55, 0xd8, 0x39, 0x55
+.data1 	0xdc, 0x74, 0x10, 0x2b, 0x55, 0xdc, 0x52, 0xff
+.data1 	0x75, 0xdc, 0x56, 0xe8, 0x53, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x46, 0xe9, 0xf4, 0xfc, 0xff
+.data1 	0xff, 0x31, 0xf6, 0x39, 0x35, 0x4c, 0x26, 0x00
+.data1 	0x00, 0x7e, 0x3c, 0x31, 0xff, 0x89, 0xf2, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x39, 0xb8, 0xc0, 0x32
+.data1 	0x00, 0x00, 0x7e, 0x28, 0x89, 0xf2, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x89, 0xfa, 0xc1, 0xe2, 0x04
+.data1 	0x8b, 0x94, 0x10, 0x60, 0x32, 0x00, 0x00, 0xf6
+.data1 	0xc2, 0x02, 0x74, 0x0d, 0x56, 0x68, 0x80, 0x0b
+.data1 	0x00, 0x00, 0xe8, 0x99, 0x1f, 0x00, 0x00, 0x59
+.data1 	0x59, 0x47, 0xeb, 0xc9, 0x46, 0xeb, 0xbc, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x14, 0x56, 0x57, 0x8b, 0x55, 0x08, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x90, 0x54, 0x32
+.data1 	0x00, 0x00, 0x89, 0x55, 0xfc, 0x52, 0xe8, 0x29
+.data1 	0x07, 0x00, 0x00, 0x59, 0x89, 0x45, 0xf8, 0x6b
+.data1 	0x5d, 0xf8, 0x38, 0x8b, 0xb3, 0x24, 0x30, 0x00
+.data1 	0x00, 0x83, 0xfe, 0x01, 0x0f, 0x84, 0x9e, 0x00
+.data1 	0x00, 0x00, 0x83, 0xfe, 0x02, 0x75, 0x10, 0x68
+.data1 	0x08, 0x0e, 0x00, 0x00, 0xe8, 0x47, 0x1f, 0x00
+.data1 	0x00, 0x59, 0xe9, 0x89, 0x00, 0x00, 0x00, 0x83
+.data1 	0xfe, 0x03, 0x74, 0x13, 0x56, 0x68, 0xdc, 0x0d
+.data1 	0x00, 0x00, 0x68, 0x04, 0x0e, 0x00, 0x00, 0xe8
+.data1 	0x4c, 0x19, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x83
+.data1 	0x3d, 0x44, 0x26, 0x00, 0x00, 0x00, 0x74, 0x13
+.data1 	0xff, 0x75, 0x0c, 0xff, 0x75, 0x10, 0x68, 0xb0
+.data1 	0x0d, 0x00, 0x00, 0xe8, 0x10, 0x1f, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x6b, 0x45, 0xf8, 0x38, 0x8b
+.data1 	0xb8, 0x34, 0x30, 0x00, 0x00, 0x8b, 0x55, 0x10
+.data1 	0x03, 0x55, 0x0c, 0x83, 0xea, 0x01, 0x52, 0x6a
+.data1 	0x30, 0x57, 0xe8, 0x71, 0xe7, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0xff, 0x75, 0x0c, 0x6a, 0x2c, 0x57
+.data1 	0xe8, 0x63, 0xe7, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x6a, 0x04, 0xff, 0x75, 0x08, 0xe8, 0x6c, 0xe6
+.data1 	0xff, 0xff, 0x59, 0x59, 0x66, 0x89, 0x45, 0xee
+.data1 	0x0f, 0xb7, 0x55, 0xee, 0x83, 0xca, 0x01, 0x83
+.data1 	0xca, 0x04, 0x52, 0x6a, 0x04, 0xff, 0x75, 0x08
+.data1 	0xe8, 0xfe, 0xe6, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0xbf, 0x01, 0x00, 0x00, 0x00, 0x31, 0xf6
+.data1 	0x39, 0x35, 0x48, 0x26, 0x00, 0x00, 0x7e, 0x3d
+.data1 	0x6b, 0xc6, 0x38, 0x83, 0xb8, 0x28, 0x30, 0x00
+.data1 	0x00, 0x00, 0x75, 0x2e, 0x6b, 0xc6, 0x38, 0x83
+.data1 	0xb8, 0x24, 0x30, 0x00, 0x00, 0x01, 0x74, 0x22
+.data1 	0x6b, 0xc6, 0x38, 0x39, 0xb8, 0x38, 0x30, 0x00
+.data1 	0x00, 0x7f, 0x0c, 0x6b, 0xc6, 0x38, 0x8b, 0x90
+.data1 	0x38, 0x30, 0x00, 0x00, 0x42, 0x89, 0xd7, 0x68
+.data1 	0x40, 0x0e, 0x00, 0x00, 0xe8, 0x67, 0x1e, 0x00
+.data1 	0x00, 0x59, 0x46, 0xeb, 0xbb, 0x89, 0xf8, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x28, 0x56, 0x57, 0xc7, 0x45, 0xe8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xc7, 0x45, 0xe4, 0xff, 0xff, 0xff
+.data1 	0xff, 0x31, 0xff, 0x31, 0xd2, 0x66, 0x89, 0x55
+.data1 	0xe0, 0x66, 0x89, 0x55, 0xe2, 0x6b, 0x45, 0x08
+.data1 	0x38, 0x8b, 0x90, 0x38, 0x30, 0x00, 0x00, 0x89
+.data1 	0x55, 0xec, 0x31, 0xf6, 0x39, 0x35, 0x4c, 0x26
+.data1 	0x00, 0x00, 0x0f, 0x8e, 0xde, 0x00, 0x00, 0x00
+.data1 	0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f
+.data1 	0xb6, 0x90, 0x54, 0x32, 0x00, 0x00, 0x39, 0x55
+.data1 	0xec, 0x0f, 0x85, 0xc1, 0x00, 0x00, 0x00, 0x89
+.data1 	0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f, 0xb6
+.data1 	0x90, 0x57, 0x32, 0x00, 0x00, 0xc1, 0xe2, 0x10
+.data1 	0x89, 0xf1, 0xc1, 0xe1, 0x07, 0x89, 0xc8, 0x0f
+.data1 	0xb6, 0x88, 0x58, 0x32, 0x00, 0x00, 0xc1, 0xe1
+.data1 	0x08, 0x09, 0xd1, 0x89, 0xf2, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x0f, 0xb6, 0x90, 0x59, 0x32, 0x00
+.data1 	0x00, 0x09, 0xca, 0x89, 0x55, 0xdc, 0x81, 0xfa
+.data1 	0x00, 0x01, 0x06, 0x00, 0x75, 0x03, 0x89, 0x75
+.data1 	0xe8, 0x89, 0xf2, 0xc1, 0xe2, 0x07, 0x89, 0xd0
+.data1 	0x66, 0x8b, 0x90, 0x5a, 0x32, 0x00, 0x00, 0x66
+.data1 	0x89, 0x55, 0xe2, 0x89, 0xf2, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd0, 0x66, 0x8b, 0x90, 0x5c, 0x32, 0x00
+.data1 	0x00, 0x66, 0x89, 0x55, 0xe0, 0x31, 0xff, 0x6b
+.data1 	0xc7, 0x0c, 0x0f, 0xb7, 0x90, 0x50, 0x2c, 0x00
+.data1 	0x00, 0x85, 0xd2, 0x74, 0x38, 0x6b, 0xc7, 0x0c
+.data1 	0x0f, 0xb7, 0x55, 0xe2, 0x0f, 0xb7, 0x88, 0x50
+.data1 	0x2c, 0x00, 0x00, 0x39, 0xd1, 0x75, 0x23, 0x6b
+.data1 	0xc7, 0x0c, 0x0f, 0xb7, 0x55, 0xe0, 0x0f, 0xb7
+.data1 	0x88, 0x52, 0x2c, 0x00, 0x00, 0x39, 0xd1, 0x75
+.data1 	0x11, 0x6b, 0xc7, 0x0c, 0x83, 0xb8, 0x54, 0x2c
+.data1 	0x00, 0x00, 0x00, 0x74, 0x08, 0x39, 0x75, 0xe8
+.data1 	0x74, 0x03, 0x47, 0xeb, 0xba, 0x6b, 0xc7, 0x0c
+.data1 	0x0f, 0xb7, 0x90, 0x50, 0x2c, 0x00, 0x00, 0x85
+.data1 	0xd2, 0x74, 0x05, 0x89, 0x75, 0xe4, 0xeb, 0x06
+.data1 	0x46, 0xe9, 0x16, 0xff, 0xff, 0xff, 0x83, 0x7d
+.data1 	0xe4, 0xff, 0x0f, 0x84, 0xcb, 0x00, 0x00, 0x00
+.data1 	0x0f, 0xb7, 0x45, 0xe0, 0x50, 0x0f, 0xb7, 0x45
+.data1 	0xe2, 0x50, 0xe8, 0x46, 0xe4, 0xff, 0xff, 0x59
+.data1 	0x59, 0x89, 0x45, 0xd8, 0x85, 0xc0, 0x75, 0x07
+.data1 	0xc7, 0x45, 0xd8, 0x34, 0x0f, 0x00, 0x00, 0x83
+.data1 	0x3d, 0x44, 0x26, 0x00, 0x00, 0x00, 0x74, 0x1a
+.data1 	0xff, 0x75, 0xd8, 0x0f, 0xb7, 0x45, 0xe0, 0x50
+.data1 	0x0f, 0xb7, 0x45, 0xe2, 0x50, 0x68, 0x10, 0x0f
+.data1 	0x00, 0x00, 0xe8, 0xf9, 0x1c, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x10, 0x6b, 0x45, 0x08, 0x38, 0x8b, 0x55
+.data1 	0xe4, 0x89, 0x90, 0x2c, 0x30, 0x00, 0x00, 0x6b
+.data1 	0xc7, 0x0c, 0x8b, 0x90, 0x58, 0x2c, 0x00, 0x00
+.data1 	0x89, 0x55, 0xf0, 0x6b, 0x45, 0x08, 0x38, 0x89
+.data1 	0x90, 0x30, 0x30, 0x00, 0x00, 0xeb, 0x4f, 0xff
+.data1 	0x75, 0xe4, 0xe8, 0xbf, 0x04, 0x00, 0x00, 0x59
+.data1 	0x89, 0x45, 0xf4, 0xeb, 0x4e, 0xff, 0x75, 0xe4
+.data1 	0xe8, 0xa9, 0x07, 0x00, 0x00, 0x59, 0x89, 0x45
+.data1 	0xf4, 0xeb, 0x40, 0xff, 0x75, 0xe4, 0xe8, 0xbd
+.data1 	0x05, 0x00, 0x00, 0x59, 0x89, 0x45, 0xf4, 0xeb
+.data1 	0x32, 0xff, 0x75, 0xe4, 0xe8, 0xfe, 0x06, 0x00
+.data1 	0x00, 0x59, 0x89, 0x45, 0xf4, 0xeb, 0x24, 0xff
+.data1 	0x75, 0xf0, 0x68, 0xf4, 0x0e, 0x00, 0x00, 0x68
+.data1 	0x0c, 0x0f, 0x00, 0x00, 0xe8, 0xa7, 0x16, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xeb, 0x0d, 0xbb, 0x74
+.data1 	0x0e, 0x00, 0x00, 0x8b, 0x45, 0xf0, 0xe9, 0xbd
+.data1 	0x25, 0x00, 0x00, 0x8b, 0x45, 0xf4, 0xe9, 0x5d
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xe8, 0xff, 0x75
+.data1 	0x1c, 0x83, 0x3d, 0x44, 0x26, 0x00, 0x00, 0x00
+.data1 	0x74, 0x0f, 0xff, 0x75, 0x08, 0x68, 0xc8, 0x0e
+.data1 	0x00, 0x00, 0xe8, 0x51, 0x1c, 0x00, 0x00, 0x59
+.data1 	0x59, 0x31, 0xc0, 0xeb, 0x3b, 0x83, 0x3d, 0x44
+.data1 	0x26, 0x00, 0x00, 0x00, 0x74, 0x30, 0x8b, 0x55
+.data1 	0xe8, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x8b, 0x55
+.data1 	0xe8, 0xc1, 0xe2, 0x07, 0x89, 0xd3, 0xff, 0x75
+.data1 	0x08, 0x0f, 0xb7, 0x88, 0x5c, 0x32, 0x00, 0x00
+.data1 	0x51, 0x0f, 0xb7, 0x83, 0x5a, 0x32, 0x00, 0x00
+.data1 	0x50, 0x68, 0x90, 0x0e, 0x00, 0x00, 0xe8, 0x15
+.data1 	0x1c, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x31, 0xc0
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x56, 0x57, 0x31, 0xd2, 0x66, 0x89
+.data1 	0x55, 0xe8, 0x66, 0x89, 0x55, 0xea, 0x6b, 0x45
+.data1 	0x08, 0x38, 0x8b, 0x90, 0x38, 0x30, 0x00, 0x00
+.data1 	0x89, 0x55, 0xf4, 0x31, 0xff, 0x39, 0x3d, 0x4c
+.data1 	0x26, 0x00, 0x00, 0x0f, 0x8e, 0x97, 0x03, 0x00
+.data1 	0x00, 0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89, 0xd0
+.data1 	0x0f, 0xb6, 0x90, 0x54, 0x32, 0x00, 0x00, 0x39
+.data1 	0x55, 0xf4, 0x0f, 0x85, 0x7a, 0x03, 0x00, 0x00
+.data1 	0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x66
+.data1 	0x8b, 0x90, 0x5a, 0x32, 0x00, 0x00, 0x66, 0x89
+.data1 	0x55, 0xea, 0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0x66, 0x8b, 0x90, 0x5c, 0x32, 0x00, 0x00
+.data1 	0x66, 0x89, 0x55, 0xe8, 0xc7, 0x45, 0xfc, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0xfc, 0x0f, 0xb7
+.data1 	0x0c, 0xd5, 0xf8, 0x2c, 0x00, 0x00, 0x85, 0xc9
+.data1 	0x74, 0x25, 0x0f, 0xb7, 0x4d, 0xea, 0x0f, 0xb7
+.data1 	0x1c, 0xd5, 0xf8, 0x2c, 0x00, 0x00, 0x39, 0xcb
+.data1 	0x75, 0x10, 0x0f, 0xb7, 0x4d, 0xe8, 0x0f, 0xb7
+.data1 	0x1c, 0xd5, 0xfa, 0x2c, 0x00, 0x00, 0x39, 0xcb
+.data1 	0x74, 0x05, 0xff, 0x45, 0xfc, 0xeb, 0xcc, 0x8b
+.data1 	0x55, 0xfc, 0x8b, 0x14, 0xd5, 0xfc, 0x2c, 0x00
+.data1 	0x00, 0x89, 0x55, 0xec, 0x8b, 0x55, 0xfc, 0x0f
+.data1 	0xb7, 0x0c, 0xd5, 0xf8, 0x2c, 0x00, 0x00, 0x85
+.data1 	0xc9, 0x0f, 0x85, 0xfd, 0x00, 0x00, 0x00, 0x6a
+.data1 	0x0e, 0x57, 0xe8, 0x9f, 0xe2, 0xff, 0xff, 0x59
+.data1 	0x59, 0x88, 0x45, 0xe3, 0xc7, 0x45, 0xec, 0x00
+.data1 	0x00, 0x00, 0x00, 0x0f, 0xb6, 0x55, 0xe3, 0x83
+.data1 	0xe2, 0x7f, 0x83, 0xfa, 0x01, 0x75, 0x09, 0xc7
+.data1 	0x45, 0xec, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x17
+.data1 	0x0f, 0xb6, 0x55, 0xe3, 0x83, 0xe2, 0x7f, 0x83
+.data1 	0xfa, 0x02, 0x0f, 0x85, 0xc2, 0x02, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xec, 0x02, 0x00, 0x00, 0x00, 0x6a
+.data1 	0x0b, 0x57, 0xe8, 0x5f, 0xe2, 0xff, 0xff, 0x59
+.data1 	0x59, 0x88, 0x45, 0xe6, 0x6a, 0x0a, 0x57, 0xe8
+.data1 	0x52, 0xe2, 0xff, 0xff, 0x59, 0x59, 0x88, 0x45
+.data1 	0xe5, 0x6a, 0x09, 0x57, 0xe8, 0x45, 0xe2, 0xff
+.data1 	0xff, 0x59, 0x59, 0x88, 0x45, 0xe4, 0x0f, 0xb6
+.data1 	0x55, 0xe6, 0xc1, 0xe2, 0x10, 0x0f, 0xb6, 0x4d
+.data1 	0xe5, 0xc1, 0xe1, 0x08, 0x09, 0xd1, 0x0f, 0xb6
+.data1 	0x55, 0xe4, 0x09, 0xca, 0x89, 0x55, 0xdc, 0x83
+.data1 	0x7d, 0xec, 0x01, 0x75, 0x3d, 0x81, 0x7d, 0xdc
+.data1 	0x00, 0x04, 0x06, 0x00, 0x74, 0x34, 0x81, 0x7d
+.data1 	0xdc, 0x01, 0x04, 0x06, 0x00, 0x74, 0x2b, 0x0f
+.data1 	0xb7, 0x45, 0xe8, 0x50, 0x0f, 0xb7, 0x45, 0xea
+.data1 	0x50, 0x0f, 0xb6, 0x45, 0xe4, 0x50, 0x0f, 0xb6
+.data1 	0x45, 0xe5, 0x50, 0x0f, 0xb6, 0x45, 0xe6, 0x50
+.data1 	0x68, 0x2c, 0x10, 0x00, 0x00, 0xe8, 0x8e, 0x1a
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x18, 0xe9, 0x38, 0x02
+.data1 	0x00, 0x00, 0x83, 0x7d, 0xec, 0x02, 0x75, 0x34
+.data1 	0x81, 0x7d, 0xdc, 0x00, 0x07, 0x06, 0x00, 0x74
+.data1 	0x2b, 0x0f, 0xb7, 0x45, 0xe8, 0x50, 0x0f, 0xb7
+.data1 	0x45, 0xea, 0x50, 0x0f, 0xb6, 0x45, 0xe4, 0x50
+.data1 	0x0f, 0xb6, 0x45, 0xe5, 0x50, 0x0f, 0xb6, 0x45
+.data1 	0xe6, 0x50, 0x68, 0xe4, 0x0f, 0x00, 0x00, 0xe8
+.data1 	0x54, 0x1a, 0x00, 0x00, 0x83, 0xc4, 0x18, 0xe9
+.data1 	0xfe, 0x01, 0x00, 0x00, 0x83, 0x3d, 0x44, 0x26
+.data1 	0x00, 0x00, 0x00, 0x74, 0x44, 0x89, 0xfa, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x89, 0xfa, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd3, 0x89, 0xfa, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd1, 0x0f, 0xb7, 0x55, 0xe8, 0x52, 0x0f
+.data1 	0xb7, 0x55, 0xea, 0x52, 0x0f, 0xb6, 0x90, 0x56
+.data1 	0x32, 0x00, 0x00, 0x52, 0x0f, 0xb6, 0x83, 0x55
+.data1 	0x32, 0x00, 0x00, 0x50, 0x0f, 0xb6, 0x81, 0x54
+.data1 	0x32, 0x00, 0x00, 0x50, 0x68, 0xbc, 0x0f, 0x00
+.data1 	0x00, 0xe8, 0x02, 0x1a, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x18, 0x6a, 0x19, 0x57, 0xe8, 0x55, 0xe1, 0xff
+.data1 	0xff, 0x59, 0x59, 0x88, 0x45, 0xe7, 0x83, 0x3d
+.data1 	0x48, 0x26, 0x00, 0x00, 0x0a, 0x7c, 0x18, 0xff
+.data1 	0x35, 0x48, 0x26, 0x00, 0x00, 0x68, 0xa4, 0x0f
+.data1 	0x00, 0x00, 0x68, 0xb8, 0x0f, 0x00, 0x00, 0xe8
+.data1 	0xf4, 0x13, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b
+.data1 	0x35, 0x48, 0x26, 0x00, 0x00, 0xff, 0x05, 0x48
+.data1 	0x26, 0x00, 0x00, 0x6b, 0xc6, 0x38, 0xc7, 0x80
+.data1 	0x24, 0x30, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x6b, 0xc6, 0x38, 0xc7, 0x80, 0x28, 0x30, 0x00
+.data1 	0x00, 0x01, 0x00, 0x00, 0x00, 0x6b, 0xc6, 0x38
+.data1 	0xc7, 0x80, 0x2c, 0x30, 0x00, 0x00, 0xff, 0xff
+.data1 	0xff, 0xff, 0x6b, 0xc6, 0x38, 0xc7, 0x80, 0x30
+.data1 	0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b
+.data1 	0xc6, 0x38, 0x89, 0xb8, 0x34, 0x30, 0x00, 0x00
+.data1 	0x6b, 0xc6, 0x38, 0x0f, 0xb6, 0x55, 0xe7, 0x89
+.data1 	0x90, 0x38, 0x30, 0x00, 0x00, 0x6b, 0x45, 0x08
+.data1 	0x38, 0x6b, 0xde, 0x38, 0x8b, 0x90, 0x3c, 0x30
+.data1 	0x00, 0x00, 0x89, 0x93, 0x3c, 0x30, 0x00, 0x00
+.data1 	0x6b, 0x45, 0x08, 0x38, 0x6b, 0xde, 0x38, 0x8b
+.data1 	0x90, 0x40, 0x30, 0x00, 0x00, 0x89, 0x93, 0x40
+.data1 	0x30, 0x00, 0x00, 0x6b, 0x45, 0x08, 0x38, 0x6b
+.data1 	0xde, 0x38, 0x8b, 0x90, 0x44, 0x30, 0x00, 0x00
+.data1 	0x89, 0x93, 0x44, 0x30, 0x00, 0x00, 0x6b, 0x45
+.data1 	0x08, 0x38, 0x6b, 0xde, 0x38, 0x8b, 0x90, 0x48
+.data1 	0x30, 0x00, 0x00, 0x89, 0x93, 0x48, 0x30, 0x00
+.data1 	0x00, 0x6b, 0x45, 0x08, 0x38, 0x6b, 0xde, 0x38
+.data1 	0x8b, 0x90, 0x4c, 0x30, 0x00, 0x00, 0x89, 0x93
+.data1 	0x4c, 0x30, 0x00, 0x00, 0x6b, 0x45, 0x08, 0x38
+.data1 	0x6b, 0xde, 0x38, 0x8b, 0x90, 0x50, 0x30, 0x00
+.data1 	0x00, 0x89, 0x93, 0x50, 0x30, 0x00, 0x00, 0xe9
+.data1 	0x7b, 0x00, 0x00, 0x00, 0x6b, 0xc6, 0x38, 0xc7
+.data1 	0x80, 0x54, 0x30, 0x00, 0x00, 0x48, 0x35, 0x00
+.data1 	0x00, 0x6b, 0xc6, 0x38, 0xc7, 0x80, 0x58, 0x30
+.data1 	0x00, 0x00, 0x69, 0x35, 0x00, 0x00, 0xe9, 0x69
+.data1 	0x00, 0x00, 0x00, 0x6b, 0xc6, 0x38, 0xc7, 0x80
+.data1 	0x24, 0x30, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
+.data1 	0x6b, 0xc6, 0x38, 0xc7, 0x80, 0x54, 0x30, 0x00
+.data1 	0x00, 0x90, 0x35, 0x00, 0x00, 0x6b, 0xc6, 0x38
+.data1 	0xc7, 0x80, 0x58, 0x30, 0x00, 0x00, 0xb1, 0x35
+.data1 	0x00, 0x00, 0xeb, 0x40, 0x6b, 0xc6, 0x38, 0xc7
+.data1 	0x80, 0x54, 0x30, 0x00, 0x00, 0xd8, 0x35, 0x00
+.data1 	0x00, 0x6b, 0xc6, 0x38, 0xc7, 0x80, 0x58, 0x30
+.data1 	0x00, 0x00, 0xef, 0x35, 0x00, 0x00, 0xeb, 0x24
+.data1 	0xff, 0x75, 0xec, 0x68, 0x84, 0x0f, 0x00, 0x00
+.data1 	0x68, 0xa0, 0x0f, 0x00, 0x00, 0xe8, 0xae, 0x12
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xeb, 0x0d, 0xbb
+.data1 	0x44, 0x0f, 0x00, 0x00, 0x8b, 0x45, 0xec, 0xe9
+.data1 	0xc4, 0x21, 0x00, 0x00, 0x80, 0x7d, 0xe7, 0x00
+.data1 	0x75, 0x0d, 0x68, 0x5c, 0x0f, 0x00, 0x00, 0xe8
+.data1 	0x6c, 0x18, 0x00, 0x00, 0x59, 0xeb, 0x1b, 0x6b
+.data1 	0xc6, 0x38, 0xc7, 0x80, 0x28, 0x30, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x56, 0xe8, 0x32, 0xe4
+.data1 	0xff, 0xff, 0x59, 0x56, 0xe8, 0x43, 0xfc, 0xff
+.data1 	0xff, 0x59, 0x47, 0xe9, 0x5d, 0xfc, 0xff, 0xff
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x31, 0xf6, 0x39, 0x35, 0x48, 0x26, 0x00, 0x00
+.data1 	0x7e, 0x14, 0x6b, 0xc6, 0x38, 0x8b, 0x55, 0x08
+.data1 	0x39, 0x90, 0x38, 0x30, 0x00, 0x00, 0x75, 0x03
+.data1 	0x56, 0xeb, 0x17, 0x46, 0xeb, 0xe4, 0xff, 0x75
+.data1 	0x08, 0x68, 0x78, 0x10, 0x00, 0x00, 0x68, 0x94
+.data1 	0x10, 0x00, 0x00, 0xe8, 0x30, 0x12, 0x00, 0x00
+.data1 	0x59, 0x59, 0x58, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x24, 0x56, 0x57, 0x8b, 0x55
+.data1 	0x08, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f, 0xb6
+.data1 	0x90, 0x55, 0x32, 0x00, 0x00, 0x89, 0x55, 0xf4
+.data1 	0x8b, 0x55, 0x08, 0xc1, 0xe2, 0x07, 0x89, 0xd0
+.data1 	0x0f, 0xb6, 0x90, 0x56, 0x32, 0x00, 0x00, 0x89
+.data1 	0x55, 0xf0, 0x6a, 0x62, 0x8d, 0x45, 0xe4, 0x50
+.data1 	0x68, 0xd0, 0x04, 0x00, 0x00, 0xe8, 0x5a, 0x12
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45, 0xf8
+.data1 	0x85, 0xc0, 0x74, 0x0f, 0xff, 0x75, 0xf8, 0x68
+.data1 	0x04, 0x11, 0x00, 0x00, 0xe8, 0xb7, 0x17, 0x00
+.data1 	0x00, 0x59, 0x59, 0x6a, 0x62, 0x8d, 0x45, 0xe0
+.data1 	0x50, 0x68, 0xd1, 0x04, 0x00, 0x00, 0xe8, 0x31
+.data1 	0x12, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45
+.data1 	0xf8, 0x85, 0xc0, 0x74, 0x0f, 0xff, 0x75, 0xf8
+.data1 	0x68, 0xe4, 0x10, 0x00, 0x00, 0xe8, 0x8e, 0x17
+.data1 	0x00, 0x00, 0x59, 0x59, 0x8b, 0x55, 0xe0, 0xc1
+.data1 	0xe2, 0x08, 0x0b, 0x55, 0xe4, 0x89, 0x55, 0xdc
+.data1 	0x31, 0xf6, 0x83, 0xfe, 0x04, 0x0f, 0x8d, 0x7f
+.data1 	0x00, 0x00, 0x00, 0x8d, 0x46, 0x60, 0x50, 0xff
+.data1 	0x75, 0x08, 0xe8, 0xc7, 0xde, 0xff, 0xff, 0x59
+.data1 	0x59, 0x89, 0x45, 0xec, 0xa8, 0x80, 0x74, 0x1b
+.data1 	0x83, 0x3d, 0x44, 0x26, 0x00, 0x00, 0x00, 0x74
+.data1 	0x5b, 0x8d, 0x46, 0x41, 0x50, 0x68, 0xd0, 0x10
+.data1 	0x00, 0x00, 0xe8, 0x49, 0x17, 0x00, 0x00, 0x59
+.data1 	0x59, 0xeb, 0x49, 0x8b, 0x55, 0xec, 0xbf, 0x0f
+.data1 	0x00, 0x00, 0x00, 0x21, 0xd7, 0x83, 0x3d, 0x44
+.data1 	0x26, 0x00, 0x00, 0x00, 0x74, 0x12, 0x57, 0x8d
+.data1 	0x46, 0x41, 0x50, 0x68, 0xc4, 0x10, 0x00, 0x00
+.data1 	0xe8, 0x23, 0x17, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0xf9, 0xba, 0x01, 0x00, 0x00, 0x00, 0xd3
+.data1 	0xe2, 0x85, 0x55, 0xdc, 0x75, 0x16, 0x83, 0x3d
+.data1 	0x44, 0x26, 0x00, 0x00, 0x00, 0x74, 0x0d, 0x57
+.data1 	0x68, 0x98, 0x10, 0x00, 0x00, 0xe8, 0xfe, 0x16
+.data1 	0x00, 0x00, 0x59, 0x59, 0x46, 0xe9, 0x78, 0xff
+.data1 	0xff, 0xff, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x20, 0x56, 0x57
+.data1 	0xc7, 0x45, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x08, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f
+.data1 	0xb6, 0x90, 0x54, 0x32, 0x00, 0x00, 0x89, 0x55
+.data1 	0xf8, 0x8b, 0x55, 0x08, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0x0f, 0xb6, 0x90, 0x55, 0x32, 0x00, 0x00
+.data1 	0x89, 0x55, 0xf4, 0x83, 0x3d, 0x4c, 0x26, 0x00
+.data1 	0x00, 0x28, 0x7c, 0x18, 0xff, 0x35, 0x4c, 0x26
+.data1 	0x00, 0x00, 0x68, 0x70, 0x11, 0x00, 0x00, 0x68
+.data1 	0x88, 0x11, 0x00, 0x00, 0xe8, 0xbf, 0x10, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x3d, 0x4c, 0x26
+.data1 	0x00, 0x00, 0x8b, 0x55, 0xf8, 0x89, 0xf9, 0xc1
+.data1 	0xe1, 0x07, 0x89, 0xc8, 0x88, 0x90, 0x54, 0x32
+.data1 	0x00, 0x00, 0x8b, 0x55, 0xf4, 0x89, 0xf9, 0xc1
+.data1 	0xe1, 0x07, 0x89, 0xc8, 0x88, 0x90, 0x55, 0x32
+.data1 	0x00, 0x00, 0x8b, 0x55, 0xf0, 0x89, 0xf9, 0xc1
+.data1 	0xe1, 0x07, 0x89, 0xc8, 0x88, 0x90, 0x56, 0x32
+.data1 	0x00, 0x00, 0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0xc6, 0x80, 0x5f, 0x32, 0x00, 0x00, 0x01
+.data1 	0xff, 0x05, 0x4c, 0x26, 0x00, 0x00, 0x6a, 0x54
+.data1 	0x57, 0xe8, 0xa8, 0xdd, 0xff, 0xff, 0x59, 0x59
+.data1 	0x88, 0x45, 0xe3, 0x6a, 0x56, 0x57, 0xe8, 0xd3
+.data1 	0xdd, 0xff, 0xff, 0x59, 0x59, 0x66, 0x89, 0x45
+.data1 	0xe0, 0x31, 0xf6, 0x83, 0xfe, 0x04, 0x0f, 0x8d
+.data1 	0x7f, 0x00, 0x00, 0x00, 0x89, 0xf1, 0x0f, 0xb6
+.data1 	0x55, 0xe3, 0xd3, 0xfa, 0x83, 0xe2, 0x01, 0x89
+.data1 	0x55, 0xe4, 0x89, 0xf2, 0xc1, 0xe2, 0x02, 0x89
+.data1 	0xd1, 0x0f, 0xb7, 0x55, 0xe0, 0xd3, 0xfa, 0x83
+.data1 	0xe2, 0x0f, 0x89, 0x55, 0xe8, 0x75, 0x1b, 0x83
+.data1 	0x3d, 0x44, 0x26, 0x00, 0x00, 0x00, 0x74, 0x4d
+.data1 	0x8d, 0x46, 0x41, 0x50, 0x68, 0x5c, 0x11, 0x00
+.data1 	0x00, 0xe8, 0xf2, 0x15, 0x00, 0x00, 0x59, 0x59
+.data1 	0xeb, 0x3b, 0x83, 0x3d, 0x44, 0x26, 0x00, 0x00
+.data1 	0x00, 0x74, 0x14, 0xff, 0x75, 0xe8, 0x8d, 0x46
+.data1 	0x41, 0x50, 0x68, 0x50, 0x11, 0x00, 0x00, 0xe8
+.data1 	0xd4, 0x15, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x83
+.data1 	0x7d, 0xe4, 0x00, 0x74, 0x18, 0x83, 0x3d, 0x44
+.data1 	0x26, 0x00, 0x00, 0x00, 0x74, 0x0f, 0xff, 0x75
+.data1 	0xe8, 0x68, 0x24, 0x11, 0x00, 0x00, 0xe8, 0xb5
+.data1 	0x15, 0x00, 0x00, 0x59, 0x59, 0x46, 0xe9, 0x78
+.data1 	0xff, 0xff, 0xff, 0xff, 0x0d, 0x4c, 0x26, 0x00
+.data1 	0x00, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57, 0x8b
+.data1 	0x55, 0x08, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f
+.data1 	0xb6, 0x90, 0x55, 0x32, 0x00, 0x00, 0x89, 0x55
+.data1 	0xf8, 0x8b, 0x55, 0x08, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0x0f, 0xb6, 0x90, 0x56, 0x32, 0x00, 0x00
+.data1 	0x89, 0x55, 0xf4, 0x31, 0xff, 0x31, 0xf6, 0x83
+.data1 	0xfe, 0x04, 0x7d, 0x54, 0x8d, 0x46, 0x41, 0x50
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xbe, 0xdc, 0xff, 0xff
+.data1 	0x59, 0x59, 0x89, 0xc7, 0xf7, 0xc7, 0x80, 0x00
+.data1 	0x00, 0x00, 0x74, 0x1b, 0x83, 0x3d, 0x44, 0x26
+.data1 	0x00, 0x00, 0x00, 0x74, 0x30, 0x8d, 0x46, 0x41
+.data1 	0x50, 0x68, 0x98, 0x11, 0x00, 0x00, 0xe8, 0x3d
+.data1 	0x15, 0x00, 0x00, 0x59, 0x59, 0xeb, 0x1e, 0x83
+.data1 	0xe7, 0x0f, 0x83, 0x3d, 0x44, 0x26, 0x00, 0x00
+.data1 	0x00, 0x74, 0x12, 0x57, 0x8d, 0x46, 0x41, 0x50
+.data1 	0x68, 0x8c, 0x11, 0x00, 0x00, 0xe8, 0x1e, 0x15
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x46, 0xeb, 0xa7
+.data1 	0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x18, 0x56, 0x57, 0x8b, 0x55
+.data1 	0x08, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f, 0xb6
+.data1 	0x90, 0x55, 0x32, 0x00, 0x00, 0x89, 0x55, 0xf8
+.data1 	0x8b, 0x55, 0x08, 0xc1, 0xe2, 0x07, 0x89, 0xd0
+.data1 	0x0f, 0xb6, 0x90, 0x56, 0x32, 0x00, 0x00, 0x89
+.data1 	0x55, 0xf4, 0x6a, 0x54, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x3a, 0xdc, 0xff, 0xff, 0x59, 0x59, 0x88, 0x45
+.data1 	0xeb, 0x31, 0xf6, 0xc7, 0x45, 0xec, 0x00, 0x00
+.data1 	0x00, 0x00, 0x31, 0xff, 0x83, 0xff, 0x04, 0x0f
+.data1 	0x8d, 0xe2, 0x00, 0x00, 0x00, 0xe9, 0x74, 0x00
+.data1 	0x00, 0x00, 0x0f, 0xb6, 0x55, 0xeb, 0x83, 0xe2
+.data1 	0x08, 0x89, 0x55, 0xec, 0x6a, 0x56, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x08, 0xdc, 0xff, 0xff, 0x59, 0x59
+.data1 	0xc1, 0xf8, 0x04, 0x89, 0xc6, 0xe9, 0x60, 0x00
+.data1 	0x00, 0x00, 0x0f, 0xb6, 0x55, 0xeb, 0x83, 0xe2
+.data1 	0x04, 0x89, 0x55, 0xec, 0x6a, 0x56, 0xff, 0x75
+.data1 	0x08, 0xe8, 0xe8, 0xdb, 0xff, 0xff, 0x59, 0x59
+.data1 	0x89, 0xc6, 0xeb, 0x46, 0x0f, 0xb6, 0x55, 0xeb
+.data1 	0x83, 0xe2, 0x02, 0x89, 0x55, 0xec, 0x6a, 0x57
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xce, 0xdb, 0xff, 0xff
+.data1 	0x59, 0x59, 0xc1, 0xf8, 0x04, 0x89, 0xc6, 0xeb
+.data1 	0x29, 0x0f, 0xb6, 0x55, 0xeb, 0x83, 0xe2, 0x01
+.data1 	0x89, 0x55, 0xec, 0x6a, 0x55, 0xff, 0x75, 0x08
+.data1 	0xe8, 0xb1, 0xdb, 0xff, 0xff, 0x59, 0x59, 0xc1
+.data1 	0xf8, 0x04, 0x89, 0xc6, 0xeb, 0x0c, 0xbb, 0xac
+.data1 	0x11, 0x00, 0x00, 0x89, 0xf8, 0xe9, 0x86, 0x1d
+.data1 	0x00, 0x00, 0x83, 0xe6, 0x0f, 0x75, 0x1b, 0x83
+.data1 	0x3d, 0x44, 0x26, 0x00, 0x00, 0x00, 0x74, 0x49
+.data1 	0x8d, 0x47, 0x41, 0x50, 0x68, 0x00, 0x12, 0x00
+.data1 	0x00, 0xe8, 0x22, 0x14, 0x00, 0x00, 0x59, 0x59
+.data1 	0xeb, 0x37, 0x83, 0x3d, 0x44, 0x26, 0x00, 0x00
+.data1 	0x00, 0x74, 0x12, 0x56, 0x8d, 0x47, 0x41, 0x50
+.data1 	0x68, 0xf4, 0x11, 0x00, 0x00, 0xe8, 0x06, 0x14
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x83, 0x7d, 0xec
+.data1 	0x00, 0x74, 0x16, 0x83, 0x3d, 0x44, 0x26, 0x00
+.data1 	0x00, 0x00, 0x74, 0x0d, 0x56, 0x68, 0xc8, 0x11
+.data1 	0x00, 0x00, 0xe8, 0xe9, 0x13, 0x00, 0x00, 0x59
+.data1 	0x59, 0x47, 0xe9, 0x15, 0xff, 0xff, 0xff, 0x31
+.data1 	0xc0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x08, 0x56, 0x57, 0x8b, 0x7d, 0x08
+.data1 	0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x31
+.data1 	0xf6, 0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89, 0xd0
+.data1 	0x39, 0xb0, 0xc0, 0x32, 0x00, 0x00, 0x7e, 0x39
+.data1 	0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89
+.data1 	0xf2, 0xc1, 0xe2, 0x04, 0x8b, 0x94, 0x10, 0x60
+.data1 	0x32, 0x00, 0x00, 0xf6, 0xc2, 0x01, 0x75, 0x1e
+.data1 	0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89
+.data1 	0xf2, 0xc1, 0xe2, 0x04, 0x8b, 0x94, 0x10, 0x6c
+.data1 	0x32, 0x00, 0x00, 0x89, 0x55, 0xf8, 0x39, 0x55
+.data1 	0xfc, 0x77, 0x03, 0x89, 0x55, 0xfc, 0x46, 0xeb
+.data1 	0xb8, 0x83, 0x7d, 0xf8, 0x00, 0x74, 0x3d, 0x89
+.data1 	0xfa, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x89, 0xfa
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd3, 0x89, 0xfa, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd1, 0xff, 0x75, 0xfc, 0x0f
+.data1 	0xb6, 0x90, 0x56, 0x32, 0x00, 0x00, 0x52, 0x0f
+.data1 	0xb6, 0x83, 0x55, 0x32, 0x00, 0x00, 0x50, 0x0f
+.data1 	0xb6, 0x81, 0x54, 0x32, 0x00, 0x00, 0x50, 0x68
+.data1 	0x14, 0x12, 0x00, 0x00, 0xe8, 0x3f, 0x13, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x14, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x31, 0xf6, 0x83, 0x3c
+.data1 	0xf5, 0x6c, 0x26, 0x00, 0x00, 0x00, 0x74, 0x1c
+.data1 	0x0f, 0xb7, 0x55, 0x08, 0x0f, 0xb7, 0x0c, 0xf5
+.data1 	0x68, 0x26, 0x00, 0x00, 0x39, 0xd1, 0x75, 0x09
+.data1 	0x8b, 0x04, 0xf5, 0x6c, 0x26, 0x00, 0x00, 0xeb
+.data1 	0x08, 0x46, 0xeb, 0xda, 0xb8, 0x48, 0x12, 0x00
+.data1 	0x00, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x31, 0xf6, 0x83, 0x3c, 0xf5, 0x4c, 0x2a, 0x00
+.data1 	0x00, 0x00, 0x74, 0x1c, 0x0f, 0xb6, 0x55, 0x08
+.data1 	0x0f, 0xb6, 0x0c, 0xf5, 0x48, 0x2a, 0x00, 0x00
+.data1 	0x39, 0xd1, 0x75, 0x09, 0x8b, 0x04, 0xf5, 0x4c
+.data1 	0x2a, 0x00, 0x00, 0xeb, 0x05, 0x46, 0xeb, 0xda
+.data1 	0x31, 0xc0, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0x31, 0xf6, 0x83, 0x3c, 0xf5, 0xec, 0x2a
+.data1 	0x00, 0x00, 0x00, 0x74, 0x4c, 0x0f, 0xb6, 0x55
+.data1 	0x08, 0x0f, 0xb6, 0x0c, 0xf5, 0xe8, 0x2a, 0x00
+.data1 	0x00, 0x39, 0xd1, 0x75, 0x39, 0x0f, 0xb6, 0x55
+.data1 	0x0c, 0x0f, 0xb6, 0x0c, 0xf5, 0xe9, 0x2a, 0x00
+.data1 	0x00, 0x39, 0xd1, 0x75, 0x29, 0x0f, 0xb6, 0x55
+.data1 	0x10, 0x0f, 0xb7, 0x0c, 0xf5, 0xea, 0x2a, 0x00
+.data1 	0x00, 0x39, 0xd1, 0x74, 0x10, 0x0f, 0xb7, 0x14
+.data1 	0xf5, 0xea, 0x2a, 0x00, 0x00, 0x81, 0xfa, 0xff
+.data1 	0xff, 0x00, 0x00, 0x75, 0x09, 0x8b, 0x04, 0xf5
+.data1 	0xec, 0x2a, 0x00, 0x00, 0xeb, 0x05, 0x46, 0xeb
+.data1 	0xaa, 0x31, 0xc0, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x14, 0x56, 0x57, 0x8b, 0x7d
+.data1 	0x0c, 0x83, 0x7d, 0x08, 0x00, 0x75, 0x0b, 0xc6
+.data1 	0x45, 0xec, 0x30, 0xbe, 0x01, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x2d, 0x31, 0xf6, 0x83, 0x7d, 0x08, 0x00
+.data1 	0x74, 0x25, 0xb9, 0x0a, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x45, 0x08, 0x31, 0xd2, 0xf7, 0xf1, 0x83, 0xc2
+.data1 	0x30, 0x89, 0xd0, 0x0f, 0xbe, 0xc0, 0x88, 0x44
+.data1 	0x35, 0xec, 0x8b, 0x45, 0x08, 0x31, 0xd2, 0xf7
+.data1 	0xf1, 0x89, 0x45, 0x08, 0x46, 0xeb, 0xd5, 0x85
+.data1 	0xf6, 0x7e, 0x17, 0x8b, 0x55, 0x10, 0x39, 0x17
+.data1 	0x74, 0x10, 0x89, 0xf2, 0x4a, 0x8b, 0x0f, 0x8a
+.data1 	0x54, 0x15, 0xec, 0x88, 0x11, 0xff, 0x07, 0x4e
+.data1 	0xeb, 0xe5, 0x8b, 0x55, 0x10, 0x39, 0x17, 0x75
+.data1 	0x06, 0xc6, 0x42, 0xff, 0x00, 0xeb, 0x05, 0x8b
+.data1 	0x17, 0xc6, 0x02, 0x00, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x56, 0x8b
+.data1 	0x55, 0x08, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f
+.data1 	0xb6, 0x90, 0x54, 0x32, 0x00, 0x00, 0x89, 0x55
+.data1 	0xfc, 0x52, 0xe8, 0x95, 0xf9, 0xff, 0xff, 0x59
+.data1 	0x89, 0xc6, 0x6b, 0xc6, 0x38, 0x56, 0xff, 0x90
+.data1 	0x54, 0x30, 0x00, 0x00, 0x59, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x6b, 0x45
+.data1 	0x08, 0x38, 0x8b, 0x90, 0x34, 0x30, 0x00, 0x00
+.data1 	0x89, 0x55, 0xfc, 0x6a, 0x1e, 0xff, 0x75, 0xfc
+.data1 	0xe8, 0x41, 0xd9, 0xff, 0xff, 0x59, 0x59, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x6b
+.data1 	0x45, 0x08, 0x38, 0x8b, 0x90, 0x34, 0x30, 0x00
+.data1 	0x00, 0x89, 0x55, 0xfc, 0x0f, 0xb7, 0x45, 0x0c
+.data1 	0x50, 0x6a, 0x1e, 0xff, 0x75, 0xfc, 0xe8, 0xc8
+.data1 	0xd9, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x6b, 0x45
+.data1 	0x08, 0x38, 0x8b, 0x90, 0x34, 0x30, 0x00, 0x00
+.data1 	0x89, 0x55, 0xfc, 0x6a, 0x16, 0xff, 0x75, 0xfc
+.data1 	0xe8, 0xf9, 0xd8, 0xff, 0xff, 0x59, 0x59, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x6b
+.data1 	0x45, 0x08, 0x38, 0x8b, 0x90, 0x34, 0x30, 0x00
+.data1 	0x00, 0x89, 0x55, 0xfc, 0x0f, 0xb7, 0x45, 0x0c
+.data1 	0x50, 0x6a, 0x16, 0xff, 0x75, 0xfc, 0xe8, 0x80
+.data1 	0xd9, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x6b, 0x45
+.data1 	0x08, 0x38, 0x8b, 0x90, 0x34, 0x30, 0x00, 0x00
+.data1 	0x89, 0x55, 0xfc, 0x31, 0xc0, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x04, 0x6b, 0x45, 0x08
+.data1 	0x38, 0x8b, 0x90, 0x34, 0x30, 0x00, 0x00, 0x89
+.data1 	0x55, 0xfc, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x04, 0x56, 0x8b, 0x55, 0x08, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x90, 0x54, 0x32
+.data1 	0x00, 0x00, 0x89, 0x55, 0xfc, 0x52, 0xe8, 0xa9
+.data1 	0xf8, 0xff, 0xff, 0x59, 0x89, 0xc6, 0x6b, 0xc6
+.data1 	0x38, 0x0f, 0xb7, 0x5d, 0x0c, 0x53, 0x56, 0xff
+.data1 	0x90, 0x58, 0x30, 0x00, 0x00, 0x59, 0x59, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08
+.data1 	0x6b, 0x45, 0x08, 0x38, 0x8b, 0x90, 0x38, 0x30
+.data1 	0x00, 0x00, 0xc1, 0xe2, 0x10, 0x81, 0xe2, 0x00
+.data1 	0x00, 0xff, 0x00, 0x81, 0xca, 0x00, 0x00, 0x00
+.data1 	0x80, 0x8b, 0x4d, 0x0c, 0xc1, 0xe1, 0x07, 0x89
+.data1 	0xc8, 0x0f, 0xb6, 0x88, 0x55, 0x32, 0x00, 0x00
+.data1 	0xc1, 0xe1, 0x0b, 0x81, 0xe1, 0x00, 0xf8, 0x00
+.data1 	0x00, 0x09, 0xd1, 0x8b, 0x55, 0x0c, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x90, 0x56, 0x32
+.data1 	0x00, 0x00, 0xc1, 0xe2, 0x08, 0x81, 0xe2, 0x00
+.data1 	0x07, 0x00, 0x00, 0x09, 0xca, 0xb9, 0x04, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x45, 0x10, 0x52, 0x99, 0xf7
+.data1 	0xf9, 0xc1, 0xe0, 0x02, 0x25, 0xfc, 0x00, 0x00
+.data1 	0x00, 0x5a, 0x09, 0xd0, 0x50, 0x68, 0xf8, 0x0c
+.data1 	0x00, 0x00, 0xe8, 0x63, 0xd2, 0xff, 0xff, 0x59
+.data1 	0x59, 0xba, 0x03, 0x00, 0x00, 0x00, 0x23, 0x55
+.data1 	0x10, 0x81, 0xc2, 0xfc, 0x0c, 0x00, 0x00, 0x52
+.data1 	0xe8, 0x5b, 0xd1, 0xff, 0xff, 0x59, 0x88, 0x45
+.data1 	0xff, 0x6a, 0x6c, 0x6a, 0x00, 0x68, 0xf8, 0x0c
+.data1 	0x00, 0x00, 0xe8, 0x29, 0x0b, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0x45, 0xf8, 0x85, 0xc0, 0x74
+.data1 	0x0f, 0xff, 0x75, 0xf8, 0x68, 0x50, 0x12, 0x00
+.data1 	0x00, 0xe8, 0x22, 0x10, 0x00, 0x00, 0x59, 0x59
+.data1 	0x0f, 0xb6, 0x45, 0xff, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x08, 0x56, 0x57, 0x8b, 0x75
+.data1 	0x10, 0x8b, 0x7d, 0x0c, 0x6b, 0x45, 0x08, 0x38
+.data1 	0x8b, 0x90, 0x38, 0x30, 0x00, 0x00, 0xc1, 0xe2
+.data1 	0x10, 0x81, 0xe2, 0x00, 0x00, 0xff, 0x00, 0x81
+.data1 	0xca, 0x00, 0x00, 0x00, 0x80, 0x89, 0xf9, 0xc1
+.data1 	0xe1, 0x07, 0x89, 0xc8, 0x0f, 0xb6, 0x88, 0x55
+.data1 	0x32, 0x00, 0x00, 0xc1, 0xe1, 0x0b, 0x81, 0xe1
+.data1 	0x00, 0xf8, 0x00, 0x00, 0x09, 0xd1, 0x89, 0xfa
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x90
+.data1 	0x56, 0x32, 0x00, 0x00, 0xc1, 0xe2, 0x08, 0x81
+.data1 	0xe2, 0x00, 0x07, 0x00, 0x00, 0x09, 0xca, 0x89
+.data1 	0xf1, 0x41, 0xbb, 0x04, 0x00, 0x00, 0x00, 0x89
+.data1 	0xc8, 0x52, 0x99, 0xf7, 0xfb, 0xc1, 0xe0, 0x02
+.data1 	0x25, 0xfc, 0x00, 0x00, 0x00, 0x5a, 0x09, 0xd0
+.data1 	0x50, 0x68, 0xf8, 0x0c, 0x00, 0x00, 0xe8, 0x9f
+.data1 	0xd1, 0xff, 0xff, 0x59, 0x59, 0x89, 0xf2, 0x42
+.data1 	0x83, 0xe2, 0x03, 0x81, 0xc2, 0xfc, 0x0c, 0x00
+.data1 	0x00, 0x52, 0xe8, 0x99, 0xd0, 0xff, 0xff, 0x59
+.data1 	0xc1, 0xe0, 0x08, 0x6b, 0x5d, 0x08, 0x38, 0x8b
+.data1 	0x93, 0x38, 0x30, 0x00, 0x00, 0xc1, 0xe2, 0x10
+.data1 	0x81, 0xe2, 0x00, 0x00, 0xff, 0x00, 0x81, 0xca
+.data1 	0x00, 0x00, 0x00, 0x80, 0x89, 0xf9, 0xc1, 0xe1
+.data1 	0x07, 0x89, 0xcb, 0x0f, 0xb6, 0x8b, 0x55, 0x32
+.data1 	0x00, 0x00, 0xc1, 0xe1, 0x0b, 0x81, 0xe1, 0x00
+.data1 	0xf8, 0x00, 0x00, 0x09, 0xd1, 0x89, 0xfa, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd3, 0x0f, 0xb6, 0x93, 0x56
+.data1 	0x32, 0x00, 0x00, 0xc1, 0xe2, 0x08, 0x81, 0xe2
+.data1 	0x00, 0x07, 0x00, 0x00, 0x09, 0xca, 0x50, 0xb9
+.data1 	0x04, 0x00, 0x00, 0x00, 0x89, 0xf0, 0x52, 0x99
+.data1 	0xf7, 0xf9, 0xc1, 0xe0, 0x02, 0x25, 0xfc, 0x00
+.data1 	0x00, 0x00, 0x5a, 0x09, 0xd0, 0x50, 0x68, 0xf8
+.data1 	0x0c, 0x00, 0x00, 0xe8, 0x1a, 0xd1, 0xff, 0xff
+.data1 	0x59, 0x59, 0xba, 0x03, 0x00, 0x00, 0x00, 0x21
+.data1 	0xf2, 0x81, 0xc2, 0xfc, 0x0c, 0x00, 0x00, 0x52
+.data1 	0xe8, 0x13, 0xd0, 0xff, 0xff, 0x59, 0x5a, 0x09
+.data1 	0xd0, 0x25, 0xff, 0xff, 0x00, 0x00, 0x66, 0x89
+.data1 	0x45, 0xfe, 0x6a, 0x6c, 0x6a, 0x00, 0x68, 0xf8
+.data1 	0x0c, 0x00, 0x00, 0xe8, 0xd8, 0x09, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x45, 0xf8, 0x85, 0xc0
+.data1 	0x74, 0x0b, 0x68, 0x74, 0x12, 0x00, 0x00, 0xe8
+.data1 	0xd4, 0x0e, 0x00, 0x00, 0x59, 0x0f, 0xb7, 0x45
+.data1 	0xfe, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x08, 0x56, 0x57, 0x8b, 0x75, 0x10
+.data1 	0x8b, 0x7d, 0x0c, 0x6b, 0x45, 0x08, 0x38, 0x8b
+.data1 	0x90, 0x38, 0x30, 0x00, 0x00, 0xc1, 0xe2, 0x10
+.data1 	0x81, 0xe2, 0x00, 0x00, 0xff, 0x00, 0x81, 0xca
+.data1 	0x00, 0x00, 0x00, 0x80, 0x89, 0xf9, 0xc1, 0xe1
+.data1 	0x07, 0x89, 0xc8, 0x0f, 0xb6, 0x88, 0x55, 0x32
+.data1 	0x00, 0x00, 0xc1, 0xe1, 0x0b, 0x81, 0xe1, 0x00
+.data1 	0xf8, 0x00, 0x00, 0x09, 0xd1, 0x89, 0xfa, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x90, 0x56
+.data1 	0x32, 0x00, 0x00, 0xc1, 0xe2, 0x08, 0x81, 0xe2
+.data1 	0x00, 0x07, 0x00, 0x00, 0x09, 0xca, 0xb9, 0x04
+.data1 	0x00, 0x00, 0x00, 0x8d, 0x46, 0x03, 0x52, 0x99
+.data1 	0xf7, 0xf9, 0xc1, 0xe0, 0x02, 0x25, 0xfc, 0x00
+.data1 	0x00, 0x00, 0x5a, 0x09, 0xd0, 0x50, 0x68, 0xf8
+.data1 	0x0c, 0x00, 0x00, 0xe8, 0x52, 0xd0, 0xff, 0xff
+.data1 	0x59, 0x59, 0x8d, 0x56, 0x03, 0x83, 0xe2, 0x03
+.data1 	0x81, 0xc2, 0xfc, 0x0c, 0x00, 0x00, 0x52, 0xe8
+.data1 	0x4c, 0xcf, 0xff, 0xff, 0x59, 0xc1, 0xe0, 0x08
+.data1 	0x6b, 0x5d, 0x08, 0x38, 0x8b, 0x93, 0x38, 0x30
+.data1 	0x00, 0x00, 0xc1, 0xe2, 0x10, 0x81, 0xe2, 0x00
+.data1 	0x00, 0xff, 0x00, 0x81, 0xca, 0x00, 0x00, 0x00
+.data1 	0x80, 0x89, 0xf9, 0xc1, 0xe1, 0x07, 0x89, 0xcb
+.data1 	0x0f, 0xb6, 0x8b, 0x55, 0x32, 0x00, 0x00, 0xc1
+.data1 	0xe1, 0x0b, 0x81, 0xe1, 0x00, 0xf8, 0x00, 0x00
+.data1 	0x09, 0xd1, 0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd3, 0x0f, 0xb6, 0x93, 0x56, 0x32, 0x00, 0x00
+.data1 	0xc1, 0xe2, 0x08, 0x81, 0xe2, 0x00, 0x07, 0x00
+.data1 	0x00, 0x09, 0xca, 0x50, 0xb9, 0x04, 0x00, 0x00
+.data1 	0x00, 0x8d, 0x46, 0x02, 0x52, 0x99, 0xf7, 0xf9
+.data1 	0xc1, 0xe0, 0x02, 0x25, 0xfc, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x09, 0xd0, 0x50, 0x68, 0xf8, 0x0c, 0x00
+.data1 	0x00, 0xe8, 0xcc, 0xcf, 0xff, 0xff, 0x59, 0x59
+.data1 	0x8d, 0x56, 0x02, 0x83, 0xe2, 0x03, 0x81, 0xc2
+.data1 	0xfc, 0x0c, 0x00, 0x00, 0x52, 0xe8, 0xc6, 0xce
+.data1 	0xff, 0xff, 0x59, 0x5a, 0x09, 0xd0, 0xc1, 0xe0
+.data1 	0x10, 0x6b, 0x5d, 0x08, 0x38, 0x8b, 0x93, 0x38
+.data1 	0x30, 0x00, 0x00, 0xc1, 0xe2, 0x10, 0x81, 0xe2
+.data1 	0x00, 0x00, 0xff, 0x00, 0x81, 0xca, 0x00, 0x00
+.data1 	0x00, 0x80, 0x89, 0xf9, 0xc1, 0xe1, 0x07, 0x89
+.data1 	0xcb, 0x0f, 0xb6, 0x8b, 0x55, 0x32, 0x00, 0x00
+.data1 	0xc1, 0xe1, 0x0b, 0x81, 0xe1, 0x00, 0xf8, 0x00
+.data1 	0x00, 0x09, 0xd1, 0x89, 0xfa, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd3, 0x0f, 0xb6, 0x93, 0x56, 0x32, 0x00
+.data1 	0x00, 0xc1, 0xe2, 0x08, 0x81, 0xe2, 0x00, 0x07
+.data1 	0x00, 0x00, 0x09, 0xca, 0x89, 0xf1, 0x41, 0x50
+.data1 	0xbb, 0x04, 0x00, 0x00, 0x00, 0x89, 0xc8, 0x52
+.data1 	0x99, 0xf7, 0xfb, 0xc1, 0xe0, 0x02, 0x25, 0xfc
+.data1 	0x00, 0x00, 0x00, 0x5a, 0x09, 0xd0, 0x50, 0x68
+.data1 	0xf8, 0x0c, 0x00, 0x00, 0xe8, 0x41, 0xcf, 0xff
+.data1 	0xff, 0x59, 0x59, 0x89, 0xf2, 0x42, 0x83, 0xe2
+.data1 	0x03, 0x81, 0xc2, 0xfc, 0x0c, 0x00, 0x00, 0x52
+.data1 	0xe8, 0x3b, 0xce, 0xff, 0xff, 0x59, 0xc1, 0xe0
+.data1 	0x08, 0x6b, 0x5d, 0x08, 0x38, 0x8b, 0x93, 0x38
+.data1 	0x30, 0x00, 0x00, 0xc1, 0xe2, 0x10, 0x81, 0xe2
+.data1 	0x00, 0x00, 0xff, 0x00, 0x81, 0xca, 0x00, 0x00
+.data1 	0x00, 0x80, 0x89, 0xf9, 0xc1, 0xe1, 0x07, 0x89
+.data1 	0xcb, 0x0f, 0xb6, 0x8b, 0x55, 0x32, 0x00, 0x00
+.data1 	0xc1, 0xe1, 0x0b, 0x81, 0xe1, 0x00, 0xf8, 0x00
+.data1 	0x00, 0x09, 0xd1, 0x89, 0xfa, 0xc1, 0xe2, 0x07
+.data1 	0x89, 0xd3, 0x0f, 0xb6, 0x93, 0x56, 0x32, 0x00
+.data1 	0x00, 0xc1, 0xe2, 0x08, 0x81, 0xe2, 0x00, 0x07
+.data1 	0x00, 0x00, 0x09, 0xca, 0x50, 0xb9, 0x04, 0x00
+.data1 	0x00, 0x00, 0x89, 0xf0, 0x52, 0x99, 0xf7, 0xf9
+.data1 	0xc1, 0xe0, 0x02, 0x25, 0xfc, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x09, 0xd0, 0x50, 0x68, 0xf8, 0x0c, 0x00
+.data1 	0x00, 0xe8, 0xbc, 0xce, 0xff, 0xff, 0x59, 0x59
+.data1 	0xba, 0x03, 0x00, 0x00, 0x00, 0x21, 0xf2, 0x81
+.data1 	0xc2, 0xfc, 0x0c, 0x00, 0x00, 0x52, 0xe8, 0xb5
+.data1 	0xcd, 0xff, 0xff, 0x59, 0x5a, 0x09, 0xd0, 0x5a
+.data1 	0x09, 0xd0, 0x89, 0x45, 0xfc, 0x6a, 0x6c, 0x6a
+.data1 	0x00, 0x68, 0xf8, 0x0c, 0x00, 0x00, 0xe8, 0x7d
+.data1 	0x07, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45
+.data1 	0xf8, 0x85, 0xc0, 0x74, 0x0f, 0xff, 0x75, 0xf8
+.data1 	0x68, 0x98, 0x12, 0x00, 0x00, 0xe8, 0x76, 0x0c
+.data1 	0x00, 0x00, 0x59, 0x59, 0x8b, 0x45, 0xfc, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x04, 0x6b, 0x45, 0x08, 0x38, 0x8b, 0x90, 0x38
+.data1 	0x30, 0x00, 0x00, 0xc1, 0xe2, 0x10, 0x81, 0xe2
+.data1 	0x00, 0x00, 0xff, 0x00, 0x81, 0xca, 0x00, 0x00
+.data1 	0x00, 0x80, 0x8b, 0x4d, 0x0c, 0xc1, 0xe1, 0x07
+.data1 	0x89, 0xc8, 0x0f, 0xb6, 0x88, 0x55, 0x32, 0x00
+.data1 	0x00, 0xc1, 0xe1, 0x0b, 0x81, 0xe1, 0x00, 0xf8
+.data1 	0x00, 0x00, 0x09, 0xd1, 0x8b, 0x55, 0x0c, 0xc1
+.data1 	0xe2, 0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x90, 0x56
+.data1 	0x32, 0x00, 0x00, 0xc1, 0xe2, 0x08, 0x81, 0xe2
+.data1 	0x00, 0x07, 0x00, 0x00, 0x09, 0xca, 0xb9, 0x04
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x45, 0x10, 0x52, 0x99
+.data1 	0xf7, 0xf9, 0xc1, 0xe0, 0x02, 0x25, 0xfc, 0x00
+.data1 	0x00, 0x00, 0x5a, 0x09, 0xd0, 0x50, 0x68, 0xf8
+.data1 	0x0c, 0x00, 0x00, 0xe8, 0xfa, 0xcd, 0xff, 0xff
+.data1 	0x59, 0x59, 0xba, 0x03, 0x00, 0x00, 0x00, 0x23
+.data1 	0x55, 0x10, 0x81, 0xc2, 0xfc, 0x0c, 0x00, 0x00
+.data1 	0x0f, 0xb6, 0x45, 0x14, 0x50, 0x52, 0xe8, 0x83
+.data1 	0xcd, 0xff, 0xff, 0x59, 0x59, 0x6a, 0x6c, 0x6a
+.data1 	0x00, 0x68, 0xf8, 0x0c, 0x00, 0x00, 0xe8, 0xbd
+.data1 	0x06, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45
+.data1 	0xfc, 0x85, 0xc0, 0x74, 0x0f, 0xff, 0x75, 0xfc
+.data1 	0x68, 0xbc, 0x12, 0x00, 0x00, 0xe8, 0xb6, 0x0b
+.data1 	0x00, 0x00, 0x59, 0x59, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x04, 0x56, 0x57, 0x8b, 0x75
+.data1 	0x10, 0x8b, 0x7d, 0x0c, 0x6b, 0x45, 0x08, 0x38
+.data1 	0x8b, 0x90, 0x38, 0x30, 0x00, 0x00, 0xc1, 0xe2
+.data1 	0x10, 0x81, 0xe2, 0x00, 0x00, 0xff, 0x00, 0x81
+.data1 	0xca, 0x00, 0x00, 0x00, 0x80, 0x89, 0xf9, 0xc1
+.data1 	0xe1, 0x07, 0x89, 0xc8, 0x0f, 0xb6, 0x88, 0x55
+.data1 	0x32, 0x00, 0x00, 0xc1, 0xe1, 0x0b, 0x81, 0xe1
+.data1 	0x00, 0xf8, 0x00, 0x00, 0x09, 0xd1, 0x89, 0xfa
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x90
+.data1 	0x56, 0x32, 0x00, 0x00, 0xc1, 0xe2, 0x08, 0x81
+.data1 	0xe2, 0x00, 0x07, 0x00, 0x00, 0x09, 0xca, 0xb9
+.data1 	0x04, 0x00, 0x00, 0x00, 0x89, 0xf0, 0x52, 0x99
+.data1 	0xf7, 0xf9, 0xc1, 0xe0, 0x02, 0x25, 0xfc, 0x00
+.data1 	0x00, 0x00, 0x5a, 0x09, 0xd0, 0x50, 0x68, 0xf8
+.data1 	0x0c, 0x00, 0x00, 0xe8, 0x3a, 0xcd, 0xff, 0xff
+.data1 	0x59, 0x59, 0xba, 0x03, 0x00, 0x00, 0x00, 0x21
+.data1 	0xf2, 0x81, 0xc2, 0xfc, 0x0c, 0x00, 0x00, 0x0f
+.data1 	0xb7, 0x45, 0x14, 0x50, 0x52, 0xe8, 0xc4, 0xcc
+.data1 	0xff, 0xff, 0x59, 0x59, 0x6b, 0x45, 0x08, 0x38
+.data1 	0x8b, 0x90, 0x38, 0x30, 0x00, 0x00, 0xc1, 0xe2
+.data1 	0x10, 0x81, 0xe2, 0x00, 0x00, 0xff, 0x00, 0x81
+.data1 	0xca, 0x00, 0x00, 0x00, 0x80, 0x89, 0xf9, 0xc1
+.data1 	0xe1, 0x07, 0x89, 0xc8, 0x0f, 0xb6, 0x88, 0x55
+.data1 	0x32, 0x00, 0x00, 0xc1, 0xe1, 0x0b, 0x81, 0xe1
+.data1 	0x00, 0xf8, 0x00, 0x00, 0x09, 0xd1, 0x89, 0xfa
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x90
+.data1 	0x56, 0x32, 0x00, 0x00, 0xc1, 0xe2, 0x08, 0x81
+.data1 	0xe2, 0x00, 0x07, 0x00, 0x00, 0x09, 0xca, 0x89
+.data1 	0xf1, 0x41, 0xbb, 0x04, 0x00, 0x00, 0x00, 0x89
+.data1 	0xc8, 0x52, 0x99, 0xf7, 0xfb, 0xc1, 0xe0, 0x02
+.data1 	0x25, 0xfc, 0x00, 0x00, 0x00, 0x5a, 0x09, 0xd0
+.data1 	0x50, 0x68, 0xf8, 0x0c, 0x00, 0x00, 0xe8, 0xaf
+.data1 	0xcc, 0xff, 0xff, 0x59, 0x59, 0x0f, 0xb7, 0x55
+.data1 	0x14, 0xc1, 0xfa, 0x08, 0x89, 0xf1, 0x41, 0x83
+.data1 	0xe1, 0x03, 0x81, 0xc1, 0xfc, 0x0c, 0x00, 0x00
+.data1 	0x52, 0x51, 0xe8, 0x37, 0xcc, 0xff, 0xff, 0x59
+.data1 	0x59, 0x6a, 0x6c, 0x6a, 0x00, 0x68, 0xf8, 0x0c
+.data1 	0x00, 0x00, 0xe8, 0x71, 0x05, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0x45, 0xfc, 0x85, 0xc0, 0x74
+.data1 	0x0f, 0xff, 0x75, 0xfc, 0x68, 0xe0, 0x12, 0x00
+.data1 	0x00, 0xe8, 0x6a, 0x0a, 0x00, 0x00, 0x59, 0x59
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x04, 0x56, 0x57, 0x8b, 0x75, 0x10, 0x8b
+.data1 	0x7d, 0x0c, 0x6b, 0x45, 0x08, 0x38, 0x8b, 0x90
+.data1 	0x38, 0x30, 0x00, 0x00, 0xc1, 0xe2, 0x10, 0x81
+.data1 	0xe2, 0x00, 0x00, 0xff, 0x00, 0x81, 0xca, 0x00
+.data1 	0x00, 0x00, 0x80, 0x89, 0xf9, 0xc1, 0xe1, 0x07
+.data1 	0x89, 0xc8, 0x0f, 0xb6, 0x88, 0x55, 0x32, 0x00
+.data1 	0x00, 0xc1, 0xe1, 0x0b, 0x81, 0xe1, 0x00, 0xf8
+.data1 	0x00, 0x00, 0x09, 0xd1, 0x89, 0xfa, 0xc1, 0xe2
+.data1 	0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x90, 0x56, 0x32
+.data1 	0x00, 0x00, 0xc1, 0xe2, 0x08, 0x81, 0xe2, 0x00
+.data1 	0x07, 0x00, 0x00, 0x09, 0xca, 0xb9, 0x04, 0x00
+.data1 	0x00, 0x00, 0x89, 0xf0, 0x52, 0x99, 0xf7, 0xf9
+.data1 	0xc1, 0xe0, 0x02, 0x25, 0xfc, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x09, 0xd0, 0x50, 0x68, 0xf8, 0x0c, 0x00
+.data1 	0x00, 0xe8, 0xec, 0xcb, 0xff, 0xff, 0x59, 0x59
+.data1 	0xba, 0x03, 0x00, 0x00, 0x00, 0x21, 0xf2, 0x81
+.data1 	0xc2, 0xfc, 0x0c, 0x00, 0x00, 0xff, 0x75, 0x14
+.data1 	0x52, 0xe8, 0x78, 0xcb, 0xff, 0xff, 0x59, 0x59
+.data1 	0x6b, 0x45, 0x08, 0x38, 0x8b, 0x90, 0x38, 0x30
+.data1 	0x00, 0x00, 0xc1, 0xe2, 0x10, 0x81, 0xe2, 0x00
+.data1 	0x00, 0xff, 0x00, 0x81, 0xca, 0x00, 0x00, 0x00
+.data1 	0x80, 0x89, 0xf9, 0xc1, 0xe1, 0x07, 0x89, 0xc8
+.data1 	0x0f, 0xb6, 0x88, 0x55, 0x32, 0x00, 0x00, 0xc1
+.data1 	0xe1, 0x0b, 0x81, 0xe1, 0x00, 0xf8, 0x00, 0x00
+.data1 	0x09, 0xd1, 0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89
+.data1 	0xd0, 0x0f, 0xb6, 0x90, 0x56, 0x32, 0x00, 0x00
+.data1 	0xc1, 0xe2, 0x08, 0x81, 0xe2, 0x00, 0x07, 0x00
+.data1 	0x00, 0x09, 0xca, 0x89, 0xf1, 0x41, 0xbb, 0x04
+.data1 	0x00, 0x00, 0x00, 0x89, 0xc8, 0x52, 0x99, 0xf7
+.data1 	0xfb, 0xc1, 0xe0, 0x02, 0x25, 0xfc, 0x00, 0x00
+.data1 	0x00, 0x5a, 0x09, 0xd0, 0x50, 0x68, 0xf8, 0x0c
+.data1 	0x00, 0x00, 0xe8, 0x63, 0xcb, 0xff, 0xff, 0x59
+.data1 	0x59, 0x8b, 0x55, 0x14, 0xc1, 0xea, 0x08, 0x89
+.data1 	0xf1, 0x41, 0x83, 0xe1, 0x03, 0x81, 0xc1, 0xfc
+.data1 	0x0c, 0x00, 0x00, 0x52, 0x51, 0xe8, 0xec, 0xca
+.data1 	0xff, 0xff, 0x59, 0x59, 0x6b, 0x45, 0x08, 0x38
+.data1 	0x8b, 0x90, 0x38, 0x30, 0x00, 0x00, 0xc1, 0xe2
+.data1 	0x10, 0x81, 0xe2, 0x00, 0x00, 0xff, 0x00, 0x81
+.data1 	0xca, 0x00, 0x00, 0x00, 0x80, 0x89, 0xf9, 0xc1
+.data1 	0xe1, 0x07, 0x89, 0xc8, 0x0f, 0xb6, 0x88, 0x55
+.data1 	0x32, 0x00, 0x00, 0xc1, 0xe1, 0x0b, 0x81, 0xe1
+.data1 	0x00, 0xf8, 0x00, 0x00, 0x09, 0xd1, 0x89, 0xfa
+.data1 	0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f, 0xb6, 0x90
+.data1 	0x56, 0x32, 0x00, 0x00, 0xc1, 0xe2, 0x08, 0x81
+.data1 	0xe2, 0x00, 0x07, 0x00, 0x00, 0x09, 0xca, 0xb9
+.data1 	0x04, 0x00, 0x00, 0x00, 0x8d, 0x46, 0x02, 0x52
+.data1 	0x99, 0xf7, 0xf9, 0xc1, 0xe0, 0x02, 0x25, 0xfc
+.data1 	0x00, 0x00, 0x00, 0x5a, 0x09, 0xd0, 0x50, 0x68
+.data1 	0xf8, 0x0c, 0x00, 0x00, 0xe8, 0xd9, 0xca, 0xff
+.data1 	0xff, 0x59, 0x59, 0x8b, 0x55, 0x14, 0xc1, 0xea
+.data1 	0x10, 0x8d, 0x4e, 0x02, 0x83, 0xe1, 0x03, 0x81
+.data1 	0xc1, 0xfc, 0x0c, 0x00, 0x00, 0x52, 0x51, 0xe8
+.data1 	0x62, 0xca, 0xff, 0xff, 0x59, 0x59, 0x6b, 0x45
+.data1 	0x08, 0x38, 0x8b, 0x90, 0x38, 0x30, 0x00, 0x00
+.data1 	0xc1, 0xe2, 0x10, 0x81, 0xe2, 0x00, 0x00, 0xff
+.data1 	0x00, 0x81, 0xca, 0x00, 0x00, 0x00, 0x80, 0x89
+.data1 	0xf9, 0xc1, 0xe1, 0x07, 0x89, 0xc8, 0x0f, 0xb6
+.data1 	0x88, 0x55, 0x32, 0x00, 0x00, 0xc1, 0xe1, 0x0b
+.data1 	0x81, 0xe1, 0x00, 0xf8, 0x00, 0x00, 0x09, 0xd1
+.data1 	0x89, 0xfa, 0xc1, 0xe2, 0x07, 0x89, 0xd0, 0x0f
+.data1 	0xb6, 0x90, 0x56, 0x32, 0x00, 0x00, 0xc1, 0xe2
+.data1 	0x08, 0x81, 0xe2, 0x00, 0x07, 0x00, 0x00, 0x09
+.data1 	0xca, 0xb9, 0x04, 0x00, 0x00, 0x00, 0x8d, 0x46
+.data1 	0x03, 0x52, 0x99, 0xf7, 0xf9, 0xc1, 0xe0, 0x02
+.data1 	0x25, 0xfc, 0x00, 0x00, 0x00, 0x5a, 0x09, 0xd0
+.data1 	0x50, 0x68, 0xf8, 0x0c, 0x00, 0x00, 0xe8, 0x4f
+.data1 	0xca, 0xff, 0xff, 0x59, 0x59, 0x8b, 0x55, 0x14
+.data1 	0xc1, 0xea, 0x10, 0xc1, 0xea, 0x08, 0x8d, 0x4e
+.data1 	0x03, 0x83, 0xe1, 0x03, 0x81, 0xc1, 0xfc, 0x0c
+.data1 	0x00, 0x00, 0x52, 0x51, 0xe8, 0xd5, 0xc9, 0xff
+.data1 	0xff, 0x59, 0x59, 0x6a, 0x6c, 0x6a, 0x00, 0x68
+.data1 	0xf8, 0x0c, 0x00, 0x00, 0xe8, 0x0f, 0x03, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45, 0xfc, 0x85
+.data1 	0xc0, 0x74, 0x0b, 0x68, 0x04, 0x13, 0x00, 0x00
+.data1 	0xe8, 0x0b, 0x08, 0x00, 0x00, 0x59, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08
+.data1 	0x6b, 0x45, 0x08, 0x38, 0x8b, 0x90, 0x38, 0x30
+.data1 	0x00, 0x00, 0xc1, 0xe2, 0x10, 0x81, 0xe2, 0x00
+.data1 	0x00, 0xff, 0x00, 0x81, 0xca, 0x00, 0x00, 0x00
+.data1 	0x80, 0x83, 0xca, 0x04, 0x52, 0x68, 0xf8, 0x0c
+.data1 	0x00, 0x00, 0xe8, 0xdb, 0xc9, 0xff, 0xff, 0x59
+.data1 	0x59, 0x68, 0xff, 0x0c, 0x00, 0x00, 0xe8, 0xdd
+.data1 	0xc8, 0xff, 0xff, 0x59, 0xc1, 0xe0, 0x08, 0x6b
+.data1 	0x5d, 0x08, 0x38, 0x8b, 0x93, 0x38, 0x30, 0x00
+.data1 	0x00, 0xc1, 0xe2, 0x10, 0x81, 0xe2, 0x00, 0x00
+.data1 	0xff, 0x00, 0x81, 0xca, 0x00, 0x00, 0x00, 0x80
+.data1 	0x83, 0xca, 0x04, 0x50, 0x52, 0x68, 0xf8, 0x0c
+.data1 	0x00, 0x00, 0xe8, 0xa3, 0xc9, 0xff, 0xff, 0x59
+.data1 	0x59, 0x68, 0xfe, 0x0c, 0x00, 0x00, 0xe8, 0xa5
+.data1 	0xc8, 0xff, 0xff, 0x59, 0x5a, 0x09, 0xd0, 0x25
+.data1 	0xff, 0xff, 0x00, 0x00, 0x66, 0x89, 0x45, 0xfe
+.data1 	0x6a, 0x6c, 0x6a, 0x00, 0x68, 0xf8, 0x0c, 0x00
+.data1 	0x00, 0xe8, 0x6a, 0x02, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x89, 0x45, 0xf8, 0x85, 0xc0, 0x74, 0x0f
+.data1 	0xff, 0x75, 0xf8, 0x68, 0x28, 0x13, 0x00, 0x00
+.data1 	0xe8, 0x63, 0x07, 0x00, 0x00, 0x59, 0x59, 0x0f
+.data1 	0xb7, 0x45, 0xfe, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x04, 0x6b, 0x45, 0x08, 0x38, 0x8b
+.data1 	0x90, 0x38, 0x30, 0x00, 0x00, 0xc1, 0xe2, 0x10
+.data1 	0x81, 0xe2, 0x00, 0x00, 0xff, 0x00, 0x81, 0xca
+.data1 	0x00, 0x00, 0x00, 0x80, 0x83, 0xca, 0x04, 0x52
+.data1 	0x68, 0xf8, 0x0c, 0x00, 0x00, 0xe8, 0x30, 0xc9
+.data1 	0x45, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00
+.data1 	0x48, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00
+.data1 	0x4a, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00
+.data1 	0x4c, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xff, 0xff, 0x59, 0x59, 0x0f, 0xb7, 0x45, 0x0c
+.data1 	0x50, 0x68, 0xfe, 0x0c, 0x00, 0x00, 0xe8, 0xc3
+.data1 	0xc8, 0xff, 0xff, 0x59, 0x59, 0x6b, 0x45, 0x08
+.data1 	0x38, 0x8b, 0x90, 0x38, 0x30, 0x00, 0x00, 0xc1
+.data1 	0xe2, 0x10, 0x81, 0xe2, 0x00, 0x00, 0xff, 0x00
+.data1 	0x81, 0xca, 0x00, 0x00, 0x00, 0x80, 0x83, 0xca
+.data1 	0x04, 0x52, 0x68, 0xf8, 0x0c, 0x00, 0x00, 0xe8
+.data1 	0xf6, 0xc8, 0xff, 0xff, 0x59, 0x59, 0x0f, 0xb7
+.data1 	0x55, 0x0c, 0xc1, 0xfa, 0x08, 0x52, 0x68, 0xff
+.data1 	0x0c, 0x00, 0x00, 0xe8, 0x86, 0xc8, 0xff, 0xff
+.data1 	0x59, 0x59, 0x6a, 0x6c, 0x6a, 0x00, 0x68, 0xf8
+.data1 	0x0c, 0x00, 0x00, 0xe8, 0xc0, 0x01, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x45, 0xfc, 0x85, 0xc0
+.data1 	0x74, 0x0f, 0xff, 0x75, 0xfc, 0x68, 0x4c, 0x13
+.data1 	0x00, 0x00, 0xe8, 0xb9, 0x06, 0x00, 0x00, 0x59
+.data1 	0x59, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x04, 0x56, 0x57, 0x8b, 0x7d, 0x08, 0x6a, 0x06
+.data1 	0x57, 0xe8, 0x38, 0xce, 0xff, 0xff, 0x59, 0x59
+.data1 	0x88, 0x45, 0xff, 0xf6, 0x45, 0xff, 0x10, 0x0f
+.data1 	0x84, 0xad, 0x00, 0x00, 0x00, 0x6a, 0x34, 0x57
+.data1 	0xe8, 0xe9, 0xcd, 0xff, 0xff, 0x59, 0x59, 0x25
+.data1 	0xfc, 0x00, 0x00, 0x00, 0x88, 0x45, 0xfe, 0x80
+.data1 	0x7d, 0xfe, 0x00, 0x0f, 0x84, 0x91, 0x00, 0x00
+.data1 	0x00, 0x0f, 0xb6, 0x45, 0xfe, 0x50, 0x57, 0xe8
+.data1 	0xca, 0xcd, 0xff, 0xff, 0x59, 0x59, 0x88, 0x45
+.data1 	0xfd, 0x0f, 0xb6, 0x55, 0xfe, 0x42, 0x52, 0x57
+.data1 	0xe8, 0xb9, 0xcd, 0xff, 0xff, 0x59, 0x59, 0x25
+.data1 	0xfc, 0x00, 0x00, 0x00, 0x88, 0x45, 0xfc, 0xeb
+.data1 	0x38, 0xbe, 0x68, 0x14, 0x00, 0x00, 0xeb, 0x3f
+.data1 	0xbe, 0x64, 0x14, 0x00, 0x00, 0xeb, 0x38, 0xbe
+.data1 	0x50, 0x14, 0x00, 0x00, 0xeb, 0x31, 0xbe, 0x3c
+.data1 	0x14, 0x00, 0x00, 0xeb, 0x2a, 0xbe, 0x20, 0x14
+.data1 	0x00, 0x00, 0xeb, 0x23, 0xbe, 0x0c, 0x14, 0x00
+.data1 	0x00, 0xeb, 0x1c, 0xbe, 0xf8, 0x13, 0x00, 0x00
+.data1 	0xeb, 0x15, 0xbe, 0xec, 0x13, 0x00, 0x00, 0xeb
+.data1 	0x0e, 0xbb, 0x70, 0x13, 0x00, 0x00, 0x0f, 0xb6
+.data1 	0x45, 0xfd, 0xe9, 0x51, 0x0f, 0x00, 0x00, 0x56
+.data1 	0x0f, 0xb6, 0x45, 0xfd, 0x50, 0x0f, 0xb6, 0x45
+.data1 	0xfe, 0x50, 0x68, 0xb8, 0x13, 0x00, 0x00, 0xe8
+.data1 	0xf4, 0x05, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x8a
+.data1 	0x4d, 0xfc, 0x88, 0x4d, 0xfe, 0xe9, 0x65, 0xff
+.data1 	0xff, 0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0xc7, 0x05
+.data1 	0x00, 0x2d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x08, 0x00, 0x74, 0x3a, 0x83, 0x7d
+.data1 	0x0c, 0x00, 0x74, 0x34, 0x81, 0x7d, 0x10, 0x00
+.data1 	0x80, 0x00, 0x00, 0x74, 0x18, 0xff, 0x75, 0x10
+.data1 	0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0x68, 0xf0
+.data1 	0x24, 0x00, 0x00, 0xe8, 0xa8, 0x05, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0xeb, 0x13, 0xff, 0x75, 0x0c
+.data1 	0xff, 0x75, 0x08, 0x68, 0xdc, 0x24, 0x00, 0x00
+.data1 	0xe8, 0x93, 0x05, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x6a, 0x09, 0x68, 0xce, 0x8a, 0x00, 0x00, 0xe8
+.data1 	0x4c, 0x00, 0x00, 0x00, 0x59, 0x59, 0xba, 0xff
+.data1 	0xff, 0xff, 0xff, 0x89, 0x55, 0xd8, 0xff, 0xd2
+.data1 	0xeb, 0xfe, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x8b, 0x55, 0x10, 0x89, 0x55, 0xe4
+.data1 	0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x08, 0x89, 0x55, 0xf0, 0x8d, 0x45, 0xdc
+.data1 	0x50, 0x68, 0x15, 0x06, 0x00, 0x00, 0x6a, 0xfe
+.data1 	0xe8, 0xf7, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0x45, 0xd8, 0x8b, 0x55, 0xf4, 0x8b, 0x45
+.data1 	0x0c, 0x89, 0x10, 0x8b, 0x45, 0xd8, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xe8, 0x8d, 0x45, 0xdc, 0x50, 0x68, 0x06
+.data1 	0x06, 0x00, 0x00, 0x6a, 0xfe, 0xe8, 0xc2, 0x00
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x10, 0x89, 0x55, 0xe4, 0xc7, 0x45, 0xec, 0x01
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x08, 0x89, 0x55
+.data1 	0xf0, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf4, 0x8d
+.data1 	0x45, 0xdc, 0x50, 0x68, 0x15, 0x06, 0x00, 0x00
+.data1 	0x6a, 0xfe, 0xe8, 0x8d, 0x00, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x55, 0xe8, 0x8b, 0x55
+.data1 	0x10, 0x89, 0x55, 0xec, 0x8b, 0x55, 0x14, 0x89
+.data1 	0x55, 0xf8, 0x8d, 0x45, 0xdc, 0x50, 0x68, 0x04
+.data1 	0x06, 0x00, 0x00, 0x6a, 0xfe, 0xe8, 0x5a, 0x00
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x83, 0x7d
+.data1 	0x20, 0x00, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x3f
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xe8, 0x8b, 0x55
+.data1 	0x0c, 0x66, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x10
+.data1 	0x89, 0x55, 0xf0, 0x8b, 0x55, 0x14, 0x89, 0x55
+.data1 	0xec, 0x8b, 0x55, 0x18, 0x66, 0x89, 0x55, 0xe6
+.data1 	0x8b, 0x55, 0x1c, 0x89, 0x55, 0xf4, 0x8b, 0x55
+.data1 	0x20, 0x89, 0x55, 0xf8, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x68, 0x0f, 0x06, 0x00, 0x00, 0x6a, 0xfe, 0xe8
+.data1 	0x08, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x10, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x56, 0x04, 0x56, 0xff, 0x75, 0x08, 0xe8, 0xc1
+.data1 	0x0a, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc7, 0x85
+.data1 	0xff, 0x74, 0x04, 0x89, 0xf8, 0xeb, 0x03, 0x8b
+.data1 	0x46, 0x04, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x55, 0x08, 0x89, 0x15
+.data1 	0x04, 0x2d, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x15, 0x08, 0x2d, 0x00, 0x00, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x34, 0x56, 0x57, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x75, 0x0a, 0xb8, 0xea, 0xff
+.data1 	0xff, 0xff, 0xe9, 0x41, 0x01, 0x00, 0x00, 0xff
+.data1 	0x75, 0x08, 0xe8, 0x1d, 0x0b, 0x00, 0x00, 0x59
+.data1 	0x89, 0x45, 0xcc, 0xbe, 0x01, 0x00, 0x00, 0x00
+.data1 	0x39, 0x35, 0x04, 0x2d, 0x00, 0x00, 0x0f, 0x8e
+.data1 	0x88, 0x00, 0x00, 0x00, 0x8b, 0x15, 0x08, 0x2d
+.data1 	0x00, 0x00, 0xff, 0x75, 0xcc, 0xff, 0x75, 0x08
+.data1 	0xff, 0x34, 0xb2, 0xe8, 0x04, 0x0b, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x0f, 0x85, 0x63
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x15, 0x08, 0x2d, 0x00
+.data1 	0x00, 0xff, 0x34, 0xb2, 0xe8, 0xdb, 0x0a, 0x00
+.data1 	0x00, 0x59, 0x39, 0x45, 0xcc, 0x73, 0x4f, 0x8b
+.data1 	0x15, 0x08, 0x2d, 0x00, 0x00, 0x8b, 0x14, 0xb2
+.data1 	0x03, 0x55, 0xcc, 0x80, 0x3a, 0x3d, 0x75, 0x3e
+.data1 	0x8b, 0x15, 0x08, 0x2d, 0x00, 0x00, 0x8b, 0x14
+.data1 	0xb2, 0x03, 0x55, 0xcc, 0x89, 0xd7, 0x47, 0x57
+.data1 	0xe8, 0xaf, 0x0a, 0x00, 0x00, 0x59, 0x05, 0x01
+.data1 	0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00
+.data1 	0x76, 0x0a, 0xb8, 0xf9, 0xff, 0xff, 0xff, 0xe9
+.data1 	0xb4, 0x00, 0x00, 0x00, 0x57, 0xff, 0x75, 0x0c
+.data1 	0xe8, 0x6f, 0x0a, 0x00, 0x00, 0x59, 0x59, 0x31
+.data1 	0xc0, 0xe9, 0xa2, 0x00, 0x00, 0x00, 0x46, 0xe9
+.data1 	0x6c, 0xff, 0xff, 0xff, 0xc7, 0x45, 0xe0, 0x1a
+.data1 	0x06, 0x00, 0x00, 0xc7, 0x45, 0xec, 0x04, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x45, 0xf0, 0xce, 0x8a, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xe4, 0x00, 0x02, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xf4, 0x54, 0x46, 0x00, 0x00, 0x8d
+.data1 	0x45, 0xdc, 0x50, 0x68, 0x1a, 0x06, 0x00, 0x00
+.data1 	0x6a, 0xfe, 0xe8, 0xcd, 0xfe, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0x45, 0xd0, 0x85, 0xc0, 0x74
+.data1 	0x1a, 0x68, 0x00, 0x02, 0x00, 0x00, 0xff, 0x75
+.data1 	0xd0, 0x68, 0x08, 0x25, 0x00, 0x00, 0xe8, 0x05
+.data1 	0x03, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x45
+.data1 	0xd0, 0xeb, 0x45, 0xff, 0x75, 0x08, 0x68, 0x54
+.data1 	0x46, 0x00, 0x00, 0xe8, 0x3c, 0x00, 0x00, 0x00
+.data1 	0x59, 0x59, 0x89, 0xc7, 0x85, 0xc0, 0x75, 0x07
+.data1 	0xb8, 0xfd, 0xff, 0xff, 0xff, 0xeb, 0x29, 0xff
+.data1 	0x75, 0x10, 0x57, 0xff, 0x75, 0x0c, 0xe8, 0x21
+.data1 	0x0a, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x57, 0xe8
+.data1 	0xf8, 0x09, 0x00, 0x00, 0x59, 0x05, 0x01, 0x00
+.data1 	0x00, 0x00, 0x39, 0x45, 0x10, 0x73, 0x07, 0xb8
+.data1 	0xf9, 0xff, 0xff, 0xff, 0xeb, 0x02, 0x31, 0xc0
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x08, 0x80, 0x3e, 0x00, 0x74
+.data1 	0x2e, 0x8b, 0x7d, 0x0c, 0x80, 0x3f, 0x00, 0x74
+.data1 	0x0e, 0x0f, 0xbe, 0x07, 0x0f, 0xbe, 0x1e, 0x39
+.data1 	0xd8, 0x75, 0x04, 0x47, 0x46, 0xeb, 0xed, 0x80
+.data1 	0x3f, 0x00, 0x75, 0x0a, 0x80, 0x3e, 0x3d, 0x75
+.data1 	0x05, 0x8d, 0x46, 0x01, 0xeb, 0x0b, 0x8a, 0x06
+.data1 	0x46, 0x84, 0xc0, 0x74, 0xcf, 0xeb, 0xf7, 0x31
+.data1 	0xc0, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x81, 0xec, 0xb4, 0x00, 0x00
+.data1 	0x00, 0x56, 0x57, 0xc7, 0x85, 0x74, 0xff, 0xff
+.data1 	0xff, 0x0c, 0x2d, 0x00, 0x00, 0x83, 0xc4, 0xf8
+.data1 	0x89, 0xe0, 0x89, 0xc7, 0xc7, 0x85, 0x6c, 0xff
+.data1 	0xff, 0xff, 0x05, 0x00, 0x00, 0x00, 0x83, 0xbd
+.data1 	0x6c, 0xff, 0xff, 0xff, 0x00, 0x7e, 0x19, 0xff
+.data1 	0x8d, 0x6c, 0xff, 0xff, 0xff, 0x8b, 0x85, 0x74
+.data1 	0xff, 0xff, 0xff, 0xff, 0x85, 0x74, 0xff, 0xff
+.data1 	0xff, 0x8a, 0x08, 0x88, 0x0f, 0x47, 0xeb, 0xde
+.data1 	0x8d, 0xbd, 0x67, 0xff, 0xff, 0xff, 0x89, 0xe0
+.data1 	0x89, 0x85, 0x74, 0xff, 0xff, 0xff, 0xc7, 0x85
+.data1 	0x6c, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00
+.data1 	0x83, 0xbd, 0x6c, 0xff, 0xff, 0xff, 0x00, 0x7e
+.data1 	0x19, 0xff, 0x8d, 0x6c, 0xff, 0xff, 0xff, 0x8b
+.data1 	0x85, 0x74, 0xff, 0xff, 0xff, 0xff, 0x85, 0x74
+.data1 	0xff, 0xff, 0xff, 0x8a, 0x08, 0x88, 0x0f, 0x47
+.data1 	0xeb, 0xde, 0x59, 0x59, 0x68, 0x80, 0x00, 0x00
+.data1 	0x00, 0x8d, 0x85, 0x78, 0xff, 0xff, 0xff, 0x50
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xc7, 0xfd, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x85, 0x5c, 0xff, 0xff
+.data1 	0xff, 0x85, 0xc0, 0x74, 0x29, 0x83, 0xbd, 0x5c
+.data1 	0xff, 0xff, 0xff, 0xfd, 0x75, 0x07, 0x6a, 0x00
+.data1 	0xe9, 0xb6, 0x01, 0x00, 0x00, 0xff, 0xb5, 0x5c
+.data1 	0xff, 0xff, 0xff, 0x68, 0x5c, 0x25, 0x00, 0x00
+.data1 	0xe8, 0xab, 0x01, 0x00, 0x00, 0x59, 0x59, 0x6a
+.data1 	0x04, 0xe9, 0x9d, 0x01, 0x00, 0x00, 0x8d, 0xb5
+.data1 	0x78, 0xff, 0xff, 0xff, 0x68, 0x58, 0x25, 0x00
+.data1 	0x00, 0x56, 0xe8, 0x8d, 0x08, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x75, 0x07, 0x6a, 0x01, 0xe9
+.data1 	0x7f, 0x01, 0x00, 0x00, 0x68, 0x54, 0x25, 0x00
+.data1 	0x00, 0x56, 0xe8, 0x75, 0x08, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x75, 0x07, 0x6a, 0x02, 0xe9
+.data1 	0x67, 0x01, 0x00, 0x00, 0xc7, 0x85, 0x58, 0xff
+.data1 	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x85
+.data1 	0x50, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00
+.data1 	0x80, 0x3e, 0x20, 0x75, 0x03, 0x46, 0xeb, 0xf8
+.data1 	0x80, 0x3e, 0x00, 0x75, 0x0b, 0xff, 0xb5, 0x50
+.data1 	0xff, 0xff, 0xff, 0xe9, 0x3b, 0x01, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x0c, 0x80, 0x3a, 0x00, 0x0f, 0x84
+.data1 	0x27, 0x01, 0x00, 0x00, 0x0f, 0xbe, 0x06, 0x50
+.data1 	0x8d, 0x85, 0x67, 0xff, 0xff, 0xff, 0x50, 0xe8
+.data1 	0xe0, 0x07, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x0f, 0x84, 0x89, 0x00, 0x00, 0x00, 0x8b, 0x55
+.data1 	0x0c, 0x0f, 0xbe, 0x02, 0x50, 0x8d, 0x85, 0x67
+.data1 	0xff, 0xff, 0xff, 0x50, 0xe8, 0xc3, 0x07, 0x00
+.data1 	0x00, 0x59, 0x59, 0x85, 0xc0, 0x74, 0x06, 0xff
+.data1 	0x85, 0x58, 0xff, 0xff, 0xff, 0x8b, 0x45, 0x0c
+.data1 	0xff, 0x45, 0x0c, 0x0f, 0xbe, 0x00, 0x0f, 0xbe
+.data1 	0x1e, 0x39, 0xd8, 0x75, 0x01, 0x46, 0x8b, 0x55
+.data1 	0x0c, 0x0f, 0xbe, 0x02, 0x3d, 0x20, 0x00, 0x00
+.data1 	0x00, 0x7d, 0x85, 0x0f, 0xbe, 0x02, 0xf7, 0xd8
+.data1 	0x03, 0x45, 0x0c, 0x89, 0x45, 0x0c, 0xe9, 0x75
+.data1 	0xff, 0xff, 0xff, 0xc7, 0x85, 0x54, 0xff, 0xff
+.data1 	0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x40, 0xc7
+.data1 	0x85, 0x54, 0xff, 0xff, 0xff, 0x0a, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x34, 0xc7, 0x85, 0x54, 0xff, 0xff
+.data1 	0xff, 0x08, 0x00, 0x00, 0x00, 0xeb, 0x28, 0xc7
+.data1 	0x85, 0x54, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x1c, 0xc7, 0x85, 0x54, 0xff, 0xff
+.data1 	0xff, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x10, 0x8b
+.data1 	0x55, 0x0c, 0x0f, 0xbe, 0x02, 0xbb, 0x24, 0x25
+.data1 	0x00, 0x00, 0xe9, 0xf5, 0x09, 0x00, 0x00, 0x83
+.data1 	0xbd, 0x54, 0xff, 0xff, 0xff, 0x00, 0x79, 0x1d
+.data1 	0x0f, 0xbe, 0x06, 0x50, 0x8d, 0x85, 0x67, 0xff
+.data1 	0xff, 0xff, 0x50, 0xe8, 0x24, 0x07, 0x00, 0x00
+.data1 	0x59, 0x59, 0x85, 0xc0, 0x0f, 0x85, 0x06, 0xff
+.data1 	0xff, 0xff, 0x46, 0xeb, 0xe3, 0xff, 0xb5, 0x54
+.data1 	0xff, 0xff, 0xff, 0x8d, 0x45, 0xf8, 0x50, 0x56
+.data1 	0xe8, 0xbf, 0x04, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0x85, 0x60, 0xff, 0xff, 0xff, 0x39, 0x75
+.data1 	0xf8, 0x74, 0x30, 0x8b, 0x75, 0xf8, 0x8b, 0x55
+.data1 	0x10, 0x39, 0x95, 0x58, 0xff, 0xff, 0xff, 0x0f
+.data1 	0x85, 0xd3, 0xfe, 0xff, 0xff, 0x39, 0x45, 0x18
+.data1 	0x7f, 0x19, 0x39, 0x45, 0x1c, 0x7c, 0x14, 0x8b
+.data1 	0x5d, 0x14, 0x89, 0x03, 0xc7, 0x85, 0x50, 0xff
+.data1 	0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0xe9, 0xb5
+.data1 	0xfe, 0xff, 0xff, 0xff, 0x75, 0x08, 0xe8, 0xdd
+.data1 	0x03, 0x00, 0x00, 0x58, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x40, 0x56, 0x57
+.data1 	0xc7, 0x45, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x8d
+.data1 	0x7d, 0x0c, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08
+.data1 	0x0f, 0xbe, 0x00, 0x89, 0xc6, 0x85, 0xc0, 0x0f
+.data1 	0x84, 0x03, 0x03, 0x00, 0x00, 0x83, 0xfe, 0x25
+.data1 	0x74, 0x0c, 0xff, 0x45, 0xf8, 0x56, 0xe8, 0x05
+.data1 	0x03, 0x00, 0x00, 0x59, 0xeb, 0xdc, 0x8b, 0x45
+.data1 	0x08, 0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89
+.data1 	0xc6, 0xc7, 0x45, 0xf4, 0x01, 0x00, 0x00, 0x00
+.data1 	0x83, 0xfe, 0x2d, 0x75, 0x12, 0xc7, 0x45, 0xf4
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x45, 0x08, 0xff
+.data1 	0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0xc6, 0xc7
+.data1 	0x45, 0xec, 0x20, 0x00, 0x00, 0x00, 0x83, 0xfe
+.data1 	0x30, 0x75, 0x12, 0xc7, 0x45, 0xec, 0x30, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08
+.data1 	0x0f, 0xbe, 0x00, 0x89, 0xc6, 0xc7, 0x45, 0xe8
+.data1 	0x00, 0x00, 0x00, 0x00, 0x83, 0xfe, 0x2a, 0x75
+.data1 	0x18, 0x8d, 0x57, 0x04, 0x89, 0xd7, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0xe8, 0x8b, 0x45, 0x08, 0xff
+.data1 	0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0xc6, 0xeb
+.data1 	0x2f, 0x89, 0xf2, 0x83, 0xea, 0x30, 0x83, 0xfa
+.data1 	0x0a, 0x73, 0x25, 0x6b, 0x45, 0xe8, 0x0a, 0x89
+.data1 	0xf2, 0x83, 0xea, 0x30, 0x01, 0xc2, 0x89, 0x55
+.data1 	0xe8, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f
+.data1 	0xbe, 0x00, 0x89, 0xc6, 0x2d, 0x30, 0x00, 0x00
+.data1 	0x00, 0x3d, 0x0a, 0x00, 0x00, 0x00, 0x72, 0xdb
+.data1 	0xc7, 0x45, 0xe4, 0xff, 0xff, 0xff, 0x7f, 0x83
+.data1 	0xfe, 0x2e, 0x0f, 0x85, 0x60, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f, 0xbe
+.data1 	0x00, 0x89, 0xc6, 0x3d, 0x2a, 0x00, 0x00, 0x00
+.data1 	0x75, 0x18, 0x8d, 0x57, 0x04, 0x89, 0xd7, 0x8b
+.data1 	0x52, 0xfc, 0x89, 0x55, 0xe4, 0x8b, 0x45, 0x08
+.data1 	0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0xc6
+.data1 	0xeb, 0x36, 0x89, 0xf2, 0x83, 0xea, 0x30, 0x83
+.data1 	0xfa, 0x0a, 0x73, 0x2c, 0xc7, 0x45, 0xe4, 0x00
+.data1 	0x00, 0x00, 0x00, 0x6b, 0x45, 0xe4, 0x0a, 0x89
+.data1 	0xf2, 0x83, 0xea, 0x30, 0x01, 0xc2, 0x89, 0x55
+.data1 	0xe4, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f
+.data1 	0xbe, 0x00, 0x89, 0xc6, 0x2d, 0x30, 0x00, 0x00
+.data1 	0x00, 0x3d, 0x0a, 0x00, 0x00, 0x00, 0x72, 0xdb
+.data1 	0xc7, 0x45, 0xd8, 0x28, 0x2d, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xd0, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x45
+.data1 	0xdc, 0x0a, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xf0
+.data1 	0x01, 0x00, 0x00, 0x00, 0x83, 0xfe, 0x6c, 0x74
+.data1 	0x05, 0x83, 0xfe, 0x4c, 0x75, 0x12, 0xc7, 0x45
+.data1 	0xf0, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x45, 0x08
+.data1 	0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00, 0x89, 0xc6
+.data1 	0x85, 0xf6, 0x0f, 0x85, 0x9c, 0x01, 0x00, 0x00
+.data1 	0xe9, 0xa3, 0x01, 0x00, 0x00, 0x83, 0x7d, 0xf0
+.data1 	0x00, 0x75, 0x0a, 0x8d, 0x57, 0x04, 0x89, 0xd7
+.data1 	0x8b, 0x42, 0xfc, 0xeb, 0x08, 0x8d, 0x57, 0x04
+.data1 	0x89, 0xd7, 0x8b, 0x42, 0xfc, 0x89, 0x45, 0xd0
+.data1 	0x85, 0xc0, 0x79, 0x04, 0xf7, 0xd8, 0xeb, 0x03
+.data1 	0x8b, 0x45, 0xd0, 0x89, 0x45, 0xcc, 0xeb, 0x32
+.data1 	0xc7, 0x45, 0xdc, 0x08, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x0e, 0xc7, 0x45, 0xd8, 0x14, 0x2d, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xdc, 0x10, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7d, 0xf0, 0x00, 0x75, 0x0a, 0x8d, 0x57, 0x04
+.data1 	0x89, 0xd7, 0x8b, 0x42, 0xfc, 0xeb, 0x08, 0x8d
+.data1 	0x57, 0x04, 0x89, 0xd7, 0x8b, 0x42, 0xfc, 0x89
+.data1 	0x45, 0xcc, 0x8d, 0x55, 0xcb, 0x89, 0x55, 0xd4
+.data1 	0xc6, 0x02, 0x00, 0x8b, 0x45, 0xcc, 0x31, 0xd2
+.data1 	0xf7, 0x75, 0xdc, 0x03, 0x55, 0xd8, 0x0f, 0xb6
+.data1 	0x02, 0x50, 0xff, 0x4d, 0xd4, 0x8b, 0x55, 0xd4
+.data1 	0x59, 0x88, 0x0a, 0x8b, 0x45, 0xcc, 0x31, 0xd2
+.data1 	0xf7, 0x75, 0xdc, 0x89, 0x45, 0xcc, 0x85, 0xc0
+.data1 	0x75, 0xd9, 0xeb, 0x39, 0x8d, 0x55, 0xc0, 0x89
+.data1 	0x55, 0xd4, 0x8d, 0x57, 0x04, 0x89, 0xd7, 0x8b
+.data1 	0x4d, 0xd4, 0x8b, 0x52, 0xfc, 0x88, 0x11, 0xc7
+.data1 	0x45, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x3c
+.data1 	0x8d, 0x55, 0xc0, 0x89, 0x55, 0xd4, 0xc6, 0x02
+.data1 	0x25, 0xc7, 0x45, 0xe0, 0x01, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x2a, 0x8d, 0x57, 0x04, 0x89, 0xd7, 0x8b
+.data1 	0x52, 0xfc, 0x89, 0x55, 0xd4, 0xc7, 0x45, 0xe0
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xd4, 0x03
+.data1 	0x55, 0xe0, 0x80, 0x3a, 0x00, 0x74, 0x0d, 0x8b
+.data1 	0x55, 0xe4, 0x39, 0x55, 0xe0, 0x7d, 0x05, 0xff
+.data1 	0x45, 0xe0, 0xeb, 0xe8, 0x8b, 0x55, 0xe8, 0x2b
+.data1 	0x55, 0xe0, 0x89, 0x55, 0xe8, 0x83, 0x7d, 0xd0
+.data1 	0x00, 0x79, 0x03, 0xff, 0x4d, 0xe8, 0x83, 0x7d
+.data1 	0xec, 0x30, 0x75, 0x11, 0x83, 0x7d, 0xd0, 0x00
+.data1 	0x79, 0x0b, 0xff, 0x45, 0xf8, 0x6a, 0x2d, 0xe8
+.data1 	0xa4, 0x00, 0x00, 0x00, 0x59, 0x83, 0x7d, 0xf4
+.data1 	0x01, 0x75, 0x17, 0x83, 0x7d, 0xe8, 0x00, 0x7e
+.data1 	0x11, 0xff, 0x45, 0xf8, 0xff, 0x75, 0xec, 0xe8
+.data1 	0x8c, 0x00, 0x00, 0x00, 0x59, 0xff, 0x4d, 0xe8
+.data1 	0xeb, 0xe9, 0x83, 0x7d, 0xec, 0x20, 0x75, 0x11
+.data1 	0x83, 0x7d, 0xd0, 0x00, 0x79, 0x0b, 0xff, 0x45
+.data1 	0xf8, 0x6a, 0x2d, 0xe8, 0x70, 0x00, 0x00, 0x00
+.data1 	0x59, 0x83, 0x7d, 0xe0, 0x00, 0x7e, 0x18, 0xff
+.data1 	0x45, 0xf8, 0x8b, 0x45, 0xd4, 0xff, 0x45, 0xd4
+.data1 	0x0f, 0xb6, 0x18, 0x53, 0xe8, 0x57, 0x00, 0x00
+.data1 	0x00, 0x59, 0xff, 0x4d, 0xe0, 0xeb, 0xe2, 0x83
+.data1 	0x7d, 0xe8, 0x00, 0x0f, 0x8e, 0x21, 0xfd, 0xff
+.data1 	0xff, 0xff, 0x45, 0xf8, 0xff, 0x75, 0xec, 0xe8
+.data1 	0x3c, 0x00, 0x00, 0x00, 0x59, 0xff, 0x4d, 0xe8
+.data1 	0xeb, 0xe5, 0xff, 0x45, 0xf8, 0x6a, 0x25, 0xe8
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x59, 0xff, 0x45, 0xf8
+.data1 	0x56, 0xe8, 0x22, 0x00, 0x00, 0x00, 0x59, 0xe9
+.data1 	0xf6, 0xfc, 0xff, 0xff, 0xbb, 0x90, 0x25, 0x00
+.data1 	0x00, 0x89, 0xf0, 0xe9, 0x4c, 0x06, 0x00, 0x00
+.data1 	0x6a, 0x00, 0xe8, 0x09, 0x00, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x45, 0xf8, 0x5f, 0x5e, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x30, 0x56, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x75, 0x09, 0x83, 0x3d, 0xa4
+.data1 	0x48, 0x00, 0x00, 0x00, 0x7f, 0x09, 0x83, 0x3d
+.data1 	0xa4, 0x48, 0x00, 0x00, 0x50, 0x75, 0x59, 0x68
+.data1 	0x3c, 0x2d, 0x00, 0x00, 0x8d, 0x45, 0xd0, 0x50
+.data1 	0xb9, 0x03, 0x00, 0x00, 0x00, 0xe8, 0xc6, 0x05
+.data1 	0x00, 0x00, 0x31, 0xf6, 0x81, 0x7c, 0xb5, 0xd0
+.data1 	0xce, 0x6a, 0x00, 0x00, 0x74, 0x30, 0x8b, 0x15
+.data1 	0xa4, 0x48, 0x00, 0x00, 0x89, 0x55, 0xe4, 0xc7
+.data1 	0x45, 0xf0, 0x54, 0x48, 0x00, 0x00, 0xc7, 0x45
+.data1 	0xe8, 0xce, 0x8a, 0x00, 0x00, 0xc7, 0x45, 0xe0
+.data1 	0x64, 0x00, 0x00, 0x00, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0xff, 0x74, 0xb5, 0xd0, 0xe8, 0xe3, 0x02, 0x00
+.data1 	0x00, 0x59, 0x59, 0x46, 0xeb, 0xc6, 0xc7, 0x05
+.data1 	0xa4, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x08, 0x00, 0x74, 0x1d, 0x8b, 0x45
+.data1 	0x08, 0x0f, 0xbe, 0xc0, 0x8b, 0x15, 0xa4, 0x48
+.data1 	0x00, 0x00, 0x89, 0xd1, 0x41, 0x89, 0x0d, 0xa4
+.data1 	0x48, 0x00, 0x00, 0x89, 0xd3, 0x88, 0x83, 0x54
+.data1 	0x48, 0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x68, 0x80, 0x00, 0x00
+.data1 	0x00, 0x68, 0x48, 0x2d, 0x00, 0x00, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x01, 0xf8, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0x89, 0xc6, 0x85, 0xc0, 0x75, 0x12, 0x83
+.data1 	0xfe, 0xfd, 0x74, 0x0d, 0x56, 0x68, 0x0c, 0x26
+.data1 	0x00, 0x00, 0xe8, 0xf9, 0xfb, 0xff, 0xff, 0x59
+.data1 	0x59, 0x68, 0x48, 0x2d, 0x00, 0x00, 0xff, 0x75
+.data1 	0x08, 0x68, 0xe8, 0x25, 0x00, 0x00, 0xe8, 0xe5
+.data1 	0xfb, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x68, 0x00
+.data1 	0x80, 0x00, 0x00, 0x68, 0xe0, 0x25, 0x00, 0x00
+.data1 	0x68, 0xe4, 0x25, 0x00, 0x00, 0xe8, 0xee, 0xf5
+.data1 	0xff, 0xff, 0x83, 0xc4, 0x0c, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x35, 0xc8, 0x2d
+.data1 	0x00, 0x00, 0x4e, 0x78, 0x09, 0xff, 0x14, 0xb5
+.data1 	0xb0, 0x48, 0x00, 0x00, 0xeb, 0xf4, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0xe8, 0xdf, 0xff, 0xff
+.data1 	0xff, 0x83, 0x3d, 0xcc, 0x2d, 0x00, 0x00, 0x00
+.data1 	0x74, 0x06, 0xff, 0x15, 0xcc, 0x2d, 0x00, 0x00
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xd4, 0x01, 0x00, 0x00
+.data1 	0x59, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x75, 0x08, 0x6a, 0x01, 0xff, 0x75, 0x10
+.data1 	0xff, 0x75, 0x0c, 0x56, 0xe8, 0x21, 0x00, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x10, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0x8b, 0x75, 0x08, 0x6a, 0x00
+.data1 	0xff, 0x75, 0x10, 0xff, 0x75, 0x0c, 0x56, 0xe8
+.data1 	0x06, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x1c
+.data1 	0x56, 0x57, 0x8b, 0x75, 0x08, 0xc7, 0x45, 0xf8
+.data1 	0x00, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xf0, 0x00
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x45, 0xec, 0x01, 0x00
+.data1 	0x00, 0x00, 0x89, 0x75, 0xe8, 0x83, 0x7d, 0x0c
+.data1 	0x00, 0x74, 0x05, 0x8b, 0x45, 0x0c, 0x89, 0x30
+.data1 	0x0f, 0xbe, 0x06, 0xf6, 0x80, 0xd9, 0x2d, 0x00
+.data1 	0x00, 0x08, 0x74, 0x03, 0x46, 0xeb, 0xf1, 0x0f
+.data1 	0xbe, 0x06, 0x89, 0xc7, 0x83, 0xff, 0x2d, 0x74
+.data1 	0x05, 0x83, 0xff, 0x2b, 0x75, 0x0d, 0x83, 0xff
+.data1 	0x2d, 0x75, 0x07, 0xc7, 0x45, 0xec, 0xff, 0xff
+.data1 	0xff, 0xff, 0x46, 0x89, 0x75, 0xe4, 0x83, 0x7d
+.data1 	0x10, 0x00, 0x75, 0x2c, 0x80, 0x3e, 0x30, 0x75
+.data1 	0x1e, 0x46, 0x80, 0x3e, 0x78, 0x74, 0x05, 0x80
+.data1 	0x3e, 0x58, 0x75, 0x0a, 0xc7, 0x45, 0x10, 0x10
+.data1 	0x00, 0x00, 0x00, 0x46, 0xeb, 0x29, 0xc7, 0x45
+.data1 	0x10, 0x08, 0x00, 0x00, 0x00, 0xeb, 0x20, 0xc7
+.data1 	0x45, 0x10, 0x0a, 0x00, 0x00, 0x00, 0xeb, 0x17
+.data1 	0x83, 0x7d, 0x10, 0x10, 0x75, 0x11, 0x80, 0x3e
+.data1 	0x30, 0x75, 0x0c, 0x46, 0x80, 0x3e, 0x78, 0x74
+.data1 	0x05, 0x80, 0x3e, 0x58, 0x75, 0x01, 0x46, 0x0f
+.data1 	0xbe, 0x06, 0x89, 0xc7, 0x89, 0xfa, 0x83, 0xea
+.data1 	0x30, 0x83, 0xfa, 0x09, 0x77, 0x0a, 0x89, 0xfa
+.data1 	0x83, 0xea, 0x30, 0x89, 0x55, 0xfc, 0xeb, 0x26
+.data1 	0x89, 0xfa, 0x83, 0xea, 0x61, 0x83, 0xfa, 0x19
+.data1 	0x77, 0x0a, 0x89, 0xfa, 0x83, 0xea, 0x57, 0x89
+.data1 	0x55, 0xfc, 0xeb, 0x12, 0x89, 0xfa, 0x83, 0xea
+.data1 	0x41, 0x83, 0xfa, 0x19, 0x77, 0x37, 0x89, 0xfa
+.data1 	0x83, 0xea, 0x37, 0x89, 0x55, 0xfc, 0x8b, 0x55
+.data1 	0xfc, 0x39, 0x55, 0x10, 0x76, 0x27, 0xba, 0xff
+.data1 	0xff, 0xff, 0xff, 0x2b, 0x55, 0xfc, 0x89, 0xd0
+.data1 	0x31, 0xd2, 0xf7, 0x75, 0x10, 0x39, 0x45, 0xf8
+.data1 	0x76, 0x03, 0xff, 0x45, 0xf0, 0x8b, 0x55, 0x10
+.data1 	0x0f, 0xaf, 0x55, 0xf8, 0x03, 0x55, 0xfc, 0x89
+.data1 	0x55, 0xf8, 0x46, 0xeb, 0x92, 0x83, 0x7d, 0x0c
+.data1 	0x00, 0x74, 0x14, 0x39, 0x75, 0xe4, 0x75, 0x0a
+.data1 	0x8b, 0x55, 0xe8, 0x8b, 0x45, 0x0c, 0x89, 0x10
+.data1 	0xeb, 0x05, 0x8b, 0x45, 0x0c, 0x89, 0x30, 0x83
+.data1 	0x7d, 0xf0, 0x00, 0x75, 0x27, 0x83, 0x7d, 0x14
+.data1 	0x00, 0x74, 0x21, 0x83, 0x7d, 0xec, 0x00, 0x79
+.data1 	0x09, 0x81, 0x7d, 0xf8, 0x00, 0x00, 0x00, 0x80
+.data1 	0x77, 0x0f, 0x83, 0x7d, 0xec, 0x00, 0x7e, 0x0c
+.data1 	0x81, 0x7d, 0xf8, 0xff, 0xff, 0xff, 0x7f, 0x76
+.data1 	0x03, 0xff, 0x45, 0xf0, 0x83, 0x7d, 0xf0, 0x00
+.data1 	0x74, 0x2b, 0xc7, 0x05, 0xd4, 0x2d, 0x00, 0x00
+.data1 	0x22, 0x00, 0x00, 0x00, 0x83, 0x7d, 0x14, 0x00
+.data1 	0x74, 0x14, 0x83, 0x7d, 0xec, 0x00, 0x79, 0x07
+.data1 	0xb8, 0x00, 0x00, 0x00, 0x80, 0xeb, 0x17, 0xb8
+.data1 	0xff, 0xff, 0xff, 0x7f, 0xeb, 0x10, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xeb, 0x09, 0x8b, 0x55, 0xec
+.data1 	0x0f, 0xaf, 0x55, 0xf8, 0x89, 0xd0, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0xe9, 0x9b, 0x01, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0x1b, 0x01, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0x2f, 0x02, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x01
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x02, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x03
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0xb9
+.data1 	0x04, 0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x53, 0x8b, 0x5d, 0x08
+.data1 	0xb9, 0x08, 0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b
+.data1 	0x5d, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x57
+.data1 	0xfc, 0x8b, 0x7d, 0x08, 0xba, 0x10, 0x00, 0x00
+.data1 	0x00, 0xd1, 0xe2, 0x89, 0xd1, 0x30, 0xc0, 0xf2
+.data1 	0xae, 0x9c, 0x29, 0xd1, 0xf7, 0xd9, 0x29, 0xcf
+.data1 	0x8a, 0x45, 0x0c, 0xf2, 0xae, 0x74, 0x08, 0x9d
+.data1 	0x75, 0xe7, 0x31, 0xc0, 0x5f, 0x5d, 0xc3, 0x58
+.data1 	0x8d, 0x47, 0xff, 0x5f, 0x5d, 0xc3, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xb9, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0xba, 0x01, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0xb9, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xd5
+.data1 	0x01, 0x00, 0x00, 0x8b, 0x45, 0x08, 0x5f, 0x5e
+.data1 	0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xb9, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0xda, 0x01, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x4c, 0x24, 0x0c
+.data1 	0xe9, 0x7b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x4d, 0x10, 0xe8, 0x97, 0x01, 0x00
+.data1 	0x00, 0x89, 0xd1, 0xf3, 0xaa, 0x8b, 0x45, 0x08
+.data1 	0x5f, 0x5e, 0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0xc7, 0x45, 0xe4, 0xce, 0x8a, 0x00
+.data1 	0x00, 0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x4e, 0x6a
+.data1 	0x00, 0xe8, 0x1a, 0x00, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x85, 0xc0, 0x79, 0x07, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xeb, 0x0a, 0x8b, 0x55, 0xf0, 0x8b
+.data1 	0x45, 0x08, 0x89, 0x10, 0x31, 0xc0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x75, 0x10
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x56, 0x04, 0x56, 0xff
+.data1 	0x75, 0x08, 0xe8, 0xcd, 0xfe, 0xff, 0xff, 0x59
+.data1 	0x59, 0x89, 0xc7, 0x85, 0xff, 0x74, 0x03, 0x89
+.data1 	0x7e, 0x04, 0x83, 0x7e, 0x04, 0x00, 0x79, 0x12
+.data1 	0x8b, 0x56, 0x04, 0xf7, 0xda, 0x89, 0x15, 0xd4
+.data1 	0x2d, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x03, 0x8b, 0x46, 0x04, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe0
+.data1 	0x8d, 0x45, 0xd8, 0x50, 0x6a, 0x01, 0x6a, 0x00
+.data1 	0xe8, 0xa3, 0xff, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0xba, 0xff, 0xff, 0xff, 0xff, 0x89, 0x55, 0xfc
+.data1 	0xff, 0xd2, 0xeb, 0xfe, 0x55, 0x89, 0xe5, 0x83
+.data1 	0x7d, 0x0c, 0x17, 0x76, 0x11, 0xc7, 0x05, 0xd4
+.data1 	0x2d, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x11, 0x8b, 0x4d
+.data1 	0x0c, 0xba, 0x01, 0x00, 0x00, 0x00, 0xd3, 0xe2
+.data1 	0x8b, 0x45, 0x08, 0x09, 0x10, 0x31, 0xc0, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0x7d, 0x0c, 0x17
+.data1 	0x76, 0x11, 0xc7, 0x05, 0xd4, 0x2d, 0x00, 0x00
+.data1 	0x16, 0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xeb, 0x13, 0x8b, 0x4d, 0x0c, 0xba, 0x01
+.data1 	0x00, 0x00, 0x00, 0xd3, 0xe2, 0xf7, 0xd2, 0x8b
+.data1 	0x45, 0x08, 0x21, 0x10, 0x31, 0xc0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x45, 0x08, 0xc7, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x31, 0xc0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x45, 0x08, 0xc7, 0x00
+.data1 	0xff, 0xff, 0xff, 0x00, 0x31, 0xc0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0x7d, 0x0c, 0x17, 0x76
+.data1 	0x11, 0xc7, 0x05, 0xd4, 0x2d, 0x00, 0x00, 0x16
+.data1 	0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x1a, 0x8b, 0x4d, 0x0c, 0xba, 0x01, 0x00
+.data1 	0x00, 0x00, 0xd3, 0xe2, 0x8b, 0x45, 0x08, 0x85
+.data1 	0x10, 0x74, 0x07, 0xb8, 0x01, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x02, 0x31, 0xc0, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x85, 0xc9, 0x74
+.data1 	0x13, 0x8b, 0x75, 0x08, 0x8b, 0x7d, 0x0c, 0xfc
+.data1 	0xa6, 0x75, 0x09, 0x80, 0x7e, 0xff, 0x00, 0x74
+.data1 	0x03, 0x49, 0x75, 0xf4, 0x0f, 0x97, 0xc0, 0x0f
+.data1 	0x92, 0xc4, 0x28, 0xe0, 0x0f, 0xbe, 0xc0, 0x5f
+.data1 	0x5e, 0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x7d, 0x0c, 0x30, 0xc0, 0x89, 0xca, 0xfc
+.data1 	0xf2, 0xae, 0x29, 0xca, 0x87, 0xca, 0x8b, 0x75
+.data1 	0x0c, 0x8b, 0x7d, 0x08, 0xf3, 0xa4, 0xc3, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x57, 0x8b, 0x7d, 0x08, 0x30
+.data1 	0xc0, 0x89, 0xca, 0x80, 0xf9, 0x01, 0xfc, 0xf2
+.data1 	0xae, 0x75, 0x01, 0x41, 0x89, 0xd0, 0x29, 0xc8
+.data1 	0x5f, 0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x89, 0xe3, 0x89, 0xf0, 0x89, 0xfa, 0x8b, 0x7b
+.data1 	0x04, 0x8b, 0x73, 0x08, 0xf3, 0xa5, 0x89, 0xc6
+.data1 	0x89, 0xd7, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x13, 0x2b, 0x43, 0x04, 0x3b, 0x43, 0x08
+.data1 	0x77, 0x0c, 0xc1, 0xe0, 0x02, 0x01, 0xc3, 0x8b
+.data1 	0x5b, 0x0c, 0x85, 0xdb, 0x75, 0x11, 0x89, 0xd3
+.data1 	0x85, 0xdb, 0x75, 0x0b, 0xb8, 0x14, 0x00, 0x00
+.data1 	0x00, 0x50, 0xe9, 0x2d, 0x00, 0x00, 0x00, 0xff
+.data1 	0xe3, 0x00, 0x00, 0x00, 0x8b, 0x13, 0x8b, 0x4b
+.data1 	0x04, 0x83, 0xc3, 0x08, 0x49, 0x7c, 0x18, 0x3b
+.data1 	0x03, 0x75, 0xf6, 0x8b, 0x5b, 0x04, 0x85, 0xdb
+.data1 	0x75, 0x0b, 0xb8, 0x14, 0x00, 0x00, 0x00, 0x50
+.data1 	0xe9, 0x07, 0x00, 0x00, 0x00, 0xff, 0xe3, 0x89
+.data1 	0xd3, 0xeb, 0xeb, 0x00, 0xe8, 0x0f, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x37, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00
+.data1 	0x31, 0xdb, 0x87, 0x1d, 0xdc, 0x2e, 0x00, 0x00
+.data1 	0x85, 0xdb, 0x74, 0x05, 0x50, 0xff, 0xd3, 0x58
+.data1 	0xc3, 0x50, 0xe8, 0xe1, 0xff, 0xff, 0xff, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00
+.data1 	0x10, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00
+.data1 	0xa0, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00
+.data1 	0xac, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00
+.data1 	0xb8, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00
+.data1 	0xc4, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00
+.data1 	0xd0, 0x00, 0x00, 0x00, 0x05, 0x03, 0x00, 0x00
+.data1 	0xdc, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00
+.data1 	0xe8, 0x00, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00
+.data1 	0xf4, 0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x00
+.data1 	0x03, 0x01, 0x00, 0x00, 0x09, 0x03, 0x00, 0x00
+.data1 	0x12, 0x01, 0x00, 0x00, 0x0a, 0x03, 0x00, 0x00
+.data1 	0x21, 0x01, 0x00, 0x00, 0x0b, 0x03, 0x00, 0x00
+.data1 	0x30, 0x01, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00
+.data1 	0x3f, 0x01, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00
+.data1 	0x4e, 0x01, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00
+.data1 	0x5d, 0x01, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00
+.data1 	0x6c, 0x01, 0x00, 0x00, 0x50, 0x43, 0x49, 0x3a
+.data1 	0x20, 0x67, 0x6f, 0x74, 0x20, 0x6d, 0x65, 0x73
+.data1 	0x73, 0x61, 0x67, 0x65, 0x20, 0x66, 0x72, 0x6f
+.data1 	0x6d, 0x20, 0x25, 0x64, 0x2c, 0x20, 0x74, 0x79
+.data1 	0x70, 0x65, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x50, 0x43, 0x49, 0x3a, 0x20, 0x72, 0x65, 0x63
+.data1 	0x65, 0x69, 0x76, 0x65, 0x20, 0x66, 0x72, 0x6f
+.data1 	0x6d, 0x20, 0x41, 0x4e, 0x59, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25, 0x64
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x64, 0x6f, 0x5f, 0x69
+.data1 	0x6e, 0x69, 0x74, 0x3a, 0x20, 0x75, 0x6e, 0x61
+.data1 	0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x73
+.data1 	0x65, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x25
+.data1 	0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x64, 0x6f, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74
+.data1 	0x5f, 0x64, 0x65, 0x76, 0x3a, 0x20, 0x75, 0x6e
+.data1 	0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20
+.data1 	0x73, 0x65, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20
+.data1 	0x25, 0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00
+.data1 	0x64, 0x6f, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f
+.data1 	0x64, 0x65, 0x76, 0x3a, 0x20, 0x75, 0x6e, 0x61
+.data1 	0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x73
+.data1 	0x65, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x25
+.data1 	0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x64, 0x6f, 0x5f, 0x66, 0x69, 0x6e, 0x64, 0x5f
+.data1 	0x64, 0x65, 0x76, 0x3a, 0x20, 0x75, 0x6e, 0x61
+.data1 	0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x73
+.data1 	0x65, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x25
+.data1 	0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x64, 0x6f, 0x5f, 0x69, 0x64, 0x73, 0x3a, 0x20
+.data1 	0x75, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74
+.data1 	0x6f, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x74
+.data1 	0x6f, 0x20, 0x25, 0x64, 0x3a, 0x20, 0x25, 0x64
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x64, 0x6f, 0x5f, 0x64
+.data1 	0x65, 0x76, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x3a
+.data1 	0x20, 0x75, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20
+.data1 	0x74, 0x6f, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20
+.data1 	0x74, 0x6f, 0x20, 0x25, 0x64, 0x3a, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x64, 0x6f, 0x5f, 0x73
+.data1 	0x6c, 0x6f, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65
+.data1 	0x3a, 0x20, 0x75, 0x6e, 0x61, 0x62, 0x6c, 0x65
+.data1 	0x20, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x6e, 0x64
+.data1 	0x20, 0x74, 0x6f, 0x20, 0x25, 0x64, 0x3a, 0x20
+.data1 	0x25, 0x64, 0x0a, 0x00, 0x64, 0x6f, 0x5f, 0x72
+.data1 	0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x3a, 0x20
+.data1 	0x75, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74
+.data1 	0x6f, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x74
+.data1 	0x6f, 0x20, 0x25, 0x64, 0x3a, 0x20, 0x25, 0x64
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x70, 0x63, 0x69, 0x60
+.data1 	0x64, 0x6f, 0x5f, 0x72, 0x65, 0x73, 0x65, 0x72
+.data1 	0x76, 0x65, 0x3a, 0x20, 0x74, 0x61, 0x73, 0x6b
+.data1 	0x20, 0x25, 0x64, 0x20, 0x64, 0x69, 0x64, 0x20
+.data1 	0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, 0x6c, 0x6c
+.data1 	0x20, 0x70, 0x63, 0x69, 0x5f, 0x69, 0x6e, 0x69
+.data1 	0x74, 0x0a, 0x00, 0x00, 0x64, 0x6f, 0x5f, 0x61
+.data1 	0x74, 0x74, 0x72, 0x5f, 0x72, 0x38, 0x3a, 0x20
+.data1 	0x75, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74
+.data1 	0x6f, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x74
+.data1 	0x6f, 0x20, 0x25, 0x64, 0x3a, 0x20, 0x25, 0x64
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x64, 0x6f, 0x5f, 0x61
+.data1 	0x74, 0x74, 0x72, 0x5f, 0x72, 0x31, 0x36, 0x3a
+.data1 	0x20, 0x75, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20
+.data1 	0x74, 0x6f, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20
+.data1 	0x74, 0x6f, 0x20, 0x25, 0x64, 0x3a, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x64, 0x6f, 0x5f, 0x61
+.data1 	0x74, 0x74, 0x72, 0x5f, 0x72, 0x33, 0x32, 0x3a
+.data1 	0x20, 0x75, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20
+.data1 	0x74, 0x6f, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20
+.data1 	0x74, 0x6f, 0x20, 0x25, 0x64, 0x3a, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x64, 0x6f, 0x5f, 0x61
+.data1 	0x74, 0x74, 0x72, 0x5f, 0x77, 0x38, 0x3a, 0x20
+.data1 	0x75, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74
+.data1 	0x6f, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x74
+.data1 	0x6f, 0x20, 0x25, 0x64, 0x3a, 0x20, 0x25, 0x64
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x64, 0x6f, 0x5f, 0x61
+.data1 	0x74, 0x74, 0x72, 0x5f, 0x77, 0x31, 0x36, 0x3a
+.data1 	0x20, 0x75, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20
+.data1 	0x74, 0x6f, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20
+.data1 	0x74, 0x6f, 0x20, 0x25, 0x64, 0x3a, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x64, 0x6f, 0x5f, 0x61
+.data1 	0x74, 0x74, 0x72, 0x5f, 0x77, 0x33, 0x32, 0x3a
+.data1 	0x20, 0x75, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20
+.data1 	0x74, 0x6f, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20
+.data1 	0x74, 0x6f, 0x20, 0x25, 0x64, 0x3a, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x64, 0x6f, 0x5f, 0x72
+.data1 	0x65, 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x62, 0x75
+.data1 	0x73, 0x3a, 0x20, 0x75, 0x6e, 0x61, 0x62, 0x6c
+.data1 	0x65, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x6e
+.data1 	0x64, 0x20, 0x74, 0x6f, 0x20, 0x25, 0x64, 0x3a
+.data1 	0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x50, 0x43, 0x49, 0x3a, 0x20, 0x77, 0x61, 0x72
+.data1 	0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x73, 0x79
+.data1 	0x73, 0x5f, 0x69, 0x6e, 0x62, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25, 0x64
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x50, 0x43, 0x49, 0x3a
+.data1 	0x20, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67
+.data1 	0x2c, 0x20, 0x73, 0x79, 0x73, 0x5f, 0x69, 0x6e
+.data1 	0x77, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64
+.data1 	0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x50, 0x43, 0x49, 0x3a, 0x20, 0x77, 0x61, 0x72
+.data1 	0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x73, 0x79
+.data1 	0x73, 0x5f, 0x69, 0x6e, 0x6c, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25, 0x64
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x50, 0x43, 0x49, 0x3a
+.data1 	0x20, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67
+.data1 	0x2c, 0x20, 0x73, 0x79, 0x73, 0x5f, 0x6f, 0x75
+.data1 	0x74, 0x62, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65
+.data1 	0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x50, 0x43, 0x49, 0x3a, 0x20, 0x77, 0x61, 0x72
+.data1 	0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x73, 0x79
+.data1 	0x73, 0x5f, 0x6f, 0x75, 0x74, 0x77, 0x20, 0x66
+.data1 	0x61, 0x69, 0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x50, 0x43, 0x49, 0x3a
+.data1 	0x20, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67
+.data1 	0x2c, 0x20, 0x73, 0x79, 0x73, 0x5f, 0x6f, 0x75
+.data1 	0x74, 0x6c, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65
+.data1 	0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0x70, 0x63, 0x69, 0x5f
+.data1 	0x64, 0x65, 0x62, 0x75, 0x67, 0x00, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0x71, 0x65, 0x6d, 0x75
+.data1 	0x5f, 0x70, 0x63, 0x69, 0x00, 0x00, 0x00, 0x00
+.data1 	0x73, 0x79, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x76
+.data1 	0x63, 0x74, 0x6c, 0x20, 0x66, 0x61, 0x69, 0x6c
+.data1 	0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70
+.data1 	0x72, 0x6f, 0x63, 0x20, 0x25, 0x64, 0x3a, 0x20
+.data1 	0x25, 0x64, 0x0a, 0x00, 0x70, 0x63, 0x69, 0x5f
+.data1 	0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x33
+.data1 	0x3a, 0x20, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67
+.data1 	0x20, 0x49, 0x52, 0x51, 0x20, 0x25, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x73, 0x79, 0x73, 0x5f
+.data1 	0x70, 0x72, 0x69, 0x76, 0x63, 0x74, 0x6c, 0x20
+.data1 	0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x66
+.data1 	0x6f, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x20
+.data1 	0x25, 0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00
+.data1 	0x70, 0x63, 0x69, 0x5f, 0x72, 0x65, 0x73, 0x65
+.data1 	0x72, 0x76, 0x65, 0x33, 0x3a, 0x20, 0x66, 0x6f
+.data1 	0x72, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x20, 0x25
+.data1 	0x64, 0x2c, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x20, 0x61, 0x64, 0x64, 0x20, 0x6d, 0x65
+.data1 	0x6d, 0x6f, 0x72, 0x79, 0x20, 0x72, 0x61, 0x6e
+.data1 	0x67, 0x65, 0x20, 0x5b, 0x30, 0x78, 0x25, 0x78
+.data1 	0x2e, 0x2e, 0x30, 0x78, 0x25, 0x78, 0x5d, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x73, 0x79, 0x73, 0x5f
+.data1 	0x70, 0x72, 0x69, 0x76, 0x63, 0x74, 0x6c, 0x20
+.data1 	0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x66
+.data1 	0x6f, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x20
+.data1 	0x25, 0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00
+.data1 	0x70, 0x63, 0x69, 0x5f, 0x72, 0x65, 0x73, 0x65
+.data1 	0x72, 0x76, 0x65, 0x33, 0x3a, 0x20, 0x66, 0x6f
+.data1 	0x72, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x20, 0x25
+.data1 	0x64, 0x2c, 0x20, 0x61, 0x64, 0x64, 0x69, 0x6e
+.data1 	0x67, 0x20, 0x49, 0x2f, 0x4f, 0x20, 0x72, 0x61
+.data1 	0x6e, 0x67, 0x65, 0x20, 0x5b, 0x30, 0x78, 0x25
+.data1 	0x78, 0x2e, 0x2e, 0x30, 0x78, 0x25, 0x78, 0x5d
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x70, 0x63, 0x69, 0x5f
+.data1 	0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x33
+.data1 	0x3a, 0x20, 0x42, 0x41, 0x52, 0x20, 0x25, 0x64
+.data1 	0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6f
+.data1 	0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x0a, 0x00
+.data1 	0x70, 0x63, 0x69, 0x5f, 0x69, 0x6e, 0x74, 0x65
+.data1 	0x6c, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x3a, 0x20
+.data1 	0x25, 0x73, 0x20, 0x28, 0x25, 0x30, 0x34, 0x58
+.data1 	0x2f, 0x25, 0x30, 0x34, 0x58, 0x29, 0x0a, 0x00
+.data1 	0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20
+.data1 	0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00
+.data1 	0x74, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79
+.data1 	0x20, 0x50, 0x43, 0x49, 0x20, 0x62, 0x75, 0x73
+.data1 	0x73, 0x65, 0x73, 0x00, 0x50, 0x43, 0x49, 0x00
+.data1 	0x50, 0x43, 0x49, 0x3a, 0x20, 0x77, 0x61, 0x72
+.data1 	0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x73, 0x79
+.data1 	0x73, 0x5f, 0x6f, 0x75, 0x74, 0x6c, 0x20, 0x66
+.data1 	0x61, 0x69, 0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x0c, 0x16, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0xf1, 0x15, 0x00, 0x00, 0xfa, 0x15, 0x00, 0x00
+.data1 	0x03, 0x16, 0x00, 0x00, 0x74, 0x6f, 0x6f, 0x20
+.data1 	0x6d, 0x61, 0x6e, 0x79, 0x20, 0x50, 0x43, 0x49
+.data1 	0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73
+.data1 	0x00, 0x00, 0x00, 0x00, 0x50, 0x43, 0x49, 0x00
+.data1 	0x09, 0x25, 0x64, 0x2e, 0x25, 0x64, 0x2e, 0x25
+.data1 	0x64, 0x3a, 0x20, 0x75, 0x6e, 0x6b, 0x6e, 0x6f
+.data1 	0x77, 0x6e, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65
+.data1 	0x72, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x09, 0x64, 0x75, 0x70
+.data1 	0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x21, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x09, 0x63, 0x6c, 0x61
+.data1 	0x73, 0x73, 0x20, 0x25, 0x73, 0x20, 0x28, 0x25
+.data1 	0x58, 0x2f, 0x25, 0x58, 0x2f, 0x25, 0x58, 0x29
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x28, 0x75, 0x6e, 0x6b
+.data1 	0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x63, 0x6c, 0x61
+.data1 	0x73, 0x73, 0x29, 0x00, 0x53, 0x75, 0x62, 0x73
+.data1 	0x79, 0x73, 0x74, 0x65, 0x6d, 0x3a, 0x20, 0x56
+.data1 	0x69, 0x64, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2c
+.data1 	0x20, 0x64, 0x69, 0x64, 0x20, 0x30, 0x78, 0x25
+.data1 	0x78, 0x0a, 0x00, 0x00, 0x44, 0x65, 0x76, 0x69
+.data1 	0x63, 0x65, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78
+.data1 	0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x25, 0x64, 0x2e, 0x25, 0x6c, 0x75, 0x2e, 0x25
+.data1 	0x6c, 0x75, 0x3a, 0x20, 0x55, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x64, 0x65, 0x76, 0x69
+.data1 	0x63, 0x65, 0x2c, 0x20, 0x76, 0x65, 0x6e, 0x64
+.data1 	0x6f, 0x72, 0x20, 0x25, 0x30, 0x34, 0x58, 0x20
+.data1 	0x28, 0x25, 0x73, 0x29, 0x2c, 0x20, 0x64, 0x65
+.data1 	0x76, 0x69, 0x63, 0x65, 0x20, 0x25, 0x30, 0x34
+.data1 	0x58, 0x0a, 0x00, 0x00, 0x25, 0x64, 0x2e, 0x25
+.data1 	0x6c, 0x75, 0x2e, 0x25, 0x6c, 0x75, 0x3a, 0x20
+.data1 	0x25, 0x73, 0x20, 0x28, 0x25, 0x30, 0x34, 0x58
+.data1 	0x2f, 0x25, 0x30, 0x34, 0x58, 0x29, 0x0a, 0x00
+.data1 	0x70, 0x63, 0x69, 0x3a, 0x20, 0x69, 0x67, 0x6e
+.data1 	0x6f, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x62, 0x61
+.data1 	0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20
+.data1 	0x30, 0x78, 0x25, 0x78, 0x20, 0x69, 0x6e, 0x20
+.data1 	0x73, 0x74, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20
+.data1 	0x51, 0x45, 0x4d, 0x55, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x74, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79
+.data1 	0x20, 0x50, 0x43, 0x49, 0x20, 0x64, 0x65, 0x76
+.data1 	0x69, 0x63, 0x65, 0x73, 0x00, 0x00, 0x00, 0x00
+.data1 	0x50, 0x43, 0x49, 0x00, 0x50, 0x43, 0x49, 0x3a
+.data1 	0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20
+.data1 	0x25, 0x64, 0x2e, 0x25, 0x64, 0x2e, 0x25, 0x64
+.data1 	0x20, 0x75, 0x73, 0x65, 0x73, 0x20, 0x49, 0x4e
+.data1 	0x54, 0x25, 0x63, 0x20, 0x62, 0x75, 0x74, 0x20
+.data1 	0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61
+.data1 	0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20
+.data1 	0x61, 0x6e, 0x79, 0x20, 0x49, 0x52, 0x51, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x61, 0x73, 0x73, 0x69
+.data1 	0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x49, 0x52
+.data1 	0x51, 0x20, 0x25, 0x64, 0x20, 0x74, 0x6f, 0x20
+.data1 	0x43, 0x61, 0x72, 0x64, 0x62, 0x75, 0x73, 0x20
+.data1 	0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0a, 0x00
+.data1 	0x50, 0x43, 0x49, 0x3a, 0x20, 0x49, 0x52, 0x51
+.data1 	0x20, 0x25, 0x64, 0x20, 0x69, 0x73, 0x20, 0x61
+.data1 	0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2c
+.data1 	0x20, 0x62, 0x75, 0x74, 0x20, 0x64, 0x65, 0x76
+.data1 	0x69, 0x63, 0x65, 0x20, 0x25, 0x64, 0x2e, 0x25
+.data1 	0x64, 0x2e, 0x25, 0x64, 0x20, 0x64, 0x6f, 0x65
+.data1 	0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6e, 0x65
+.data1 	0x65, 0x64, 0x20, 0x69, 0x74, 0x0a, 0x00, 0x00
+.data1 	0x09, 0x49, 0x52, 0x51, 0x20, 0x25, 0x64, 0x20
+.data1 	0x66, 0x6f, 0x72, 0x20, 0x49, 0x4e, 0x54, 0x25
+.data1 	0x63, 0x0a, 0x00, 0x00, 0x50, 0x43, 0x49, 0x3a
+.data1 	0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x67, 0x65
+.data1 	0x2c, 0x20, 0x42, 0x49, 0x4f, 0x53, 0x20, 0x61
+.data1 	0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20
+.data1 	0x49, 0x52, 0x51, 0x30, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x73, 0x6b, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67
+.data1 	0x20, 0x62, 0x61, 0x72, 0x20, 0x25, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x73, 0x6b, 0x69, 0x70
+.data1 	0x70, 0x69, 0x6e, 0x67, 0x20, 0x62, 0x61, 0x72
+.data1 	0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x20
+.data1 	0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20
+.data1 	0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69
+.data1 	0x6e, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65
+.data1 	0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x63
+.data1 	0x6c, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x20
+.data1 	0x42, 0x41, 0x52, 0x73, 0x20, 0x32, 0x20, 0x61
+.data1 	0x6e, 0x64, 0x20, 0x33, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x20
+.data1 	0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20
+.data1 	0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69
+.data1 	0x6e, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65
+.data1 	0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x63
+.data1 	0x6c, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x20
+.data1 	0x42, 0x41, 0x52, 0x73, 0x20, 0x30, 0x20, 0x61
+.data1 	0x6e, 0x64, 0x20, 0x31, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x09, 0x50, 0x72, 0x65, 0x66, 0x65, 0x74, 0x63
+.data1 	0x68, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x65
+.data1 	0x6d, 0x6f, 0x72, 0x79, 0x20, 0x77, 0x69, 0x6e
+.data1 	0x64, 0x6f, 0x77, 0x3a, 0x20, 0x62, 0x61, 0x73
+.data1 	0x65, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20
+.data1 	0x6c, 0x69, 0x6d, 0x69, 0x74, 0x20, 0x30, 0x78
+.data1 	0x25, 0x78, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65
+.data1 	0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00
+.data1 	0x09, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20
+.data1 	0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x3a, 0x20
+.data1 	0x62, 0x61, 0x73, 0x65, 0x20, 0x30, 0x78, 0x25
+.data1 	0x78, 0x2c, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74
+.data1 	0x20, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x73
+.data1 	0x69, 0x7a, 0x65, 0x20, 0x30, 0x78, 0x25, 0x78
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x09, 0x49, 0x2f, 0x4f
+.data1 	0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x3a
+.data1 	0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x30, 0x78
+.data1 	0x25, 0x78, 0x2c, 0x20, 0x6c, 0x69, 0x6d, 0x69
+.data1 	0x74, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20
+.data1 	0x73, 0x69, 0x7a, 0x65, 0x20, 0x25, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x09, 0x49, 0x2f, 0x4f
+.data1 	0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20
+.data1 	0x31, 0x3a, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20
+.data1 	0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x6c, 0x69
+.data1 	0x6d, 0x69, 0x74, 0x20, 0x30, 0x78, 0x25, 0x78
+.data1 	0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x09, 0x49, 0x2f, 0x4f
+.data1 	0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20
+.data1 	0x30, 0x3a, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20
+.data1 	0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x6c, 0x69
+.data1 	0x6d, 0x69, 0x74, 0x20, 0x30, 0x78, 0x25, 0x78
+.data1 	0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x09, 0x4d, 0x65, 0x6d
+.data1 	0x6f, 0x72, 0x79, 0x20, 0x77, 0x69, 0x6e, 0x64
+.data1 	0x6f, 0x77, 0x20, 0x31, 0x3a, 0x20, 0x62, 0x61
+.data1 	0x73, 0x65, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2c
+.data1 	0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x20, 0x30
+.data1 	0x78, 0x25, 0x78, 0x2c, 0x20, 0x73, 0x69, 0x7a
+.data1 	0x65, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x09, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20
+.data1 	0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x30
+.data1 	0x3a, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x30
+.data1 	0x78, 0x25, 0x78, 0x2c, 0x20, 0x6c, 0x69, 0x6d
+.data1 	0x69, 0x74, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2c
+.data1 	0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x25, 0x64
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x74, 0x79, 0x70, 0x65
+.data1 	0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x70, 0x72, 0x65, 0x66, 0x65, 0x74, 0x63
+.data1 	0x68, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00
+.data1 	0x09, 0x62, 0x61, 0x72, 0x5f, 0x25, 0x64, 0x3a
+.data1 	0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 0x62, 0x79
+.data1 	0x74, 0x65, 0x73, 0x20, 0x61, 0x74, 0x20, 0x30
+.data1 	0x78, 0x25, 0x78, 0x25, 0x73, 0x20, 0x6d, 0x65
+.data1 	0x6d, 0x6f, 0x72, 0x79, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x09, 0x62, 0x61, 0x72, 0x5f, 0x25, 0x64, 0x3a
+.data1 	0x20, 0x25, 0x64, 0x20, 0x62, 0x79, 0x74, 0x65
+.data1 	0x73, 0x20, 0x61, 0x74, 0x20, 0x30, 0x78, 0x25
+.data1 	0x78, 0x20, 0x49, 0x2f, 0x4f, 0x0a, 0x00, 0x00
+.data1 	0x42, 0x52, 0x49, 0x44, 0x47, 0x45, 0x43, 0x54
+.data1 	0x52, 0x4c, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25
+.data1 	0x78, 0x0a, 0x00, 0x00, 0x53, 0x45, 0x43, 0x42
+.data1 	0x4c, 0x54, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25
+.data1 	0x78, 0x0a, 0x00, 0x00, 0x43, 0x52, 0x20, 0x3d
+.data1 	0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00
+.data1 	0x70, 0x72, 0x69, 0x6d, 0x5f, 0x62, 0x75, 0x73
+.data1 	0x6e, 0x72, 0x3d, 0x20, 0x25, 0x64, 0x0a, 0x00
+.data1 	0x64, 0x65, 0x76, 0x69, 0x6e, 0x64, 0x20, 0x3d
+.data1 	0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65
+.data1 	0x5f, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x3a
+.data1 	0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x69, 0x6e
+.data1 	0x67, 0x20, 0x73, 0x75, 0x62, 0x6f, 0x72, 0x64
+.data1 	0x69, 0x6e, 0x61, 0x74, 0x65, 0x20, 0x62, 0x75
+.data1 	0x73, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72
+.data1 	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6d, 0x70
+.data1 	0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x67, 0x6f, 0x74, 0x20
+.data1 	0x62, 0x75, 0x73, 0x20, 0x6e, 0x75, 0x6d, 0x62
+.data1 	0x65, 0x72, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x61
+.data1 	0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x20
+.data1 	0x62, 0x75, 0x73, 0x20, 0x6e, 0x75, 0x6d, 0x62
+.data1 	0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x62
+.data1 	0x75, 0x73, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x61
+.data1 	0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x20
+.data1 	0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65
+.data1 	0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x65
+.data1 	0x76, 0x69, 0x63, 0x65, 0x20, 0x25, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6d, 0x70
+.data1 	0x6c, 0x65, 0x74, 0x65, 0x5f, 0x62, 0x61, 0x72
+.data1 	0x73, 0x3a, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x63
+.data1 	0x61, 0x74, 0x65, 0x64, 0x20, 0x30, 0x78, 0x25
+.data1 	0x78, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x25
+.data1 	0x64, 0x20, 0x74, 0x6f, 0x20, 0x25, 0x64, 0x2e
+.data1 	0x25, 0x64, 0x2e, 0x25, 0x64, 0x2c, 0x20, 0x62
+.data1 	0x61, 0x72, 0x5f, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x49, 0x2f, 0x4f, 0x20, 0x62, 0x61, 0x73, 0x65
+.data1 	0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x6f, 0x77
+.data1 	0x00, 0x00, 0x00, 0x00, 0x70, 0x63, 0x69, 0x00
+.data1 	0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65
+.data1 	0x5f, 0x62, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x61
+.data1 	0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64
+.data1 	0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 0x73, 0x69
+.data1 	0x7a, 0x65, 0x20, 0x25, 0x64, 0x20, 0x74, 0x6f
+.data1 	0x20, 0x25, 0x64, 0x2e, 0x25, 0x64, 0x2e, 0x25
+.data1 	0x64, 0x2c, 0x20, 0x62, 0x61, 0x72, 0x5f, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x6d, 0x65, 0x6d, 0x6f
+.data1 	0x72, 0x79, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20
+.data1 	0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x00
+.data1 	0x70, 0x63, 0x69, 0x00, 0x49, 0x2f, 0x4f, 0x20
+.data1 	0x72, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x3d, 0x20
+.data1 	0x5b, 0x30, 0x78, 0x25, 0x78, 0x2e, 0x2e, 0x30
+.data1 	0x78, 0x25, 0x78, 0x3e, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x69, 0x6f, 0x67, 0x61, 0x70, 0x5f, 0x68, 0x69
+.data1 	0x67, 0x68, 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c
+.data1 	0x6f, 0x77, 0x00, 0x00, 0x70, 0x63, 0x69, 0x00
+.data1 	0x69, 0x6f, 0x67, 0x61, 0x70, 0x5f, 0x68, 0x69
+.data1 	0x67, 0x68, 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c
+.data1 	0x6f, 0x77, 0x2c, 0x20, 0x73, 0x68, 0x6f, 0x75
+.data1 	0x6c, 0x64, 0x20, 0x70, 0x61, 0x6e, 0x69, 0x63
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x70, 0x63, 0x69, 0x3a
+.data1 	0x20, 0x62, 0x61, 0x64, 0x20, 0x6d, 0x65, 0x6d
+.data1 	0x6f, 0x72, 0x79, 0x20, 0x67, 0x61, 0x70, 0x3a
+.data1 	0x20, 0x5b, 0x30, 0x78, 0x25, 0x78, 0x20, 0x2e
+.data1 	0x2e, 0x20, 0x30, 0x78, 0x25, 0x78, 0x3e, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6d, 0x70
+.data1 	0x6c, 0x65, 0x74, 0x65, 0x5f, 0x62, 0x61, 0x72
+.data1 	0x73, 0x3a, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72
+.data1 	0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20
+.data1 	0x67, 0x61, 0x70, 0x3a, 0x20, 0x5b, 0x30, 0x78
+.data1 	0x25, 0x78, 0x20, 0x2e, 0x2e, 0x20, 0x30, 0x78
+.data1 	0x25, 0x78, 0x3e, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65
+.data1 	0x5f, 0x62, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x69
+.data1 	0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x67
+.data1 	0x61, 0x70, 0x3a, 0x20, 0x5b, 0x30, 0x78, 0x25
+.data1 	0x78, 0x20, 0x2e, 0x2e, 0x20, 0x30, 0x78, 0x25
+.data1 	0x78, 0x3e, 0x0a, 0x00, 0x70, 0x63, 0x69, 0x3a
+.data1 	0x20, 0x62, 0x61, 0x64, 0x20, 0x6d, 0x65, 0x6d
+.data1 	0x6f, 0x72, 0x79, 0x20, 0x65, 0x6e, 0x76, 0x69
+.data1 	0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20
+.data1 	0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x27
+.data1 	0x25, 0x73, 0x27, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x70, 0x63, 0x69, 0x3a, 0x20, 0x62, 0x61, 0x64
+.data1 	0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20
+.data1 	0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d
+.data1 	0x65, 0x6e, 0x74, 0x20, 0x73, 0x74, 0x72, 0x69
+.data1 	0x6e, 0x67, 0x20, 0x27, 0x25, 0x73, 0x27, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x65, 0x6e, 0x76, 0x5f
+.data1 	0x67, 0x65, 0x74, 0x5f, 0x70, 0x61, 0x72, 0x61
+.data1 	0x6d, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x70, 0x63, 0x69, 0x00
+.data1 	0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x00, 0x00
+.data1 	0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x62
+.data1 	0x72, 0x69, 0x64, 0x67, 0x65, 0x34, 0x64, 0x65
+.data1 	0x76, 0x5f, 0x69, 0x6f, 0x3a, 0x20, 0x61, 0x64
+.data1 	0x64, 0x69, 0x6e, 0x67, 0x20, 0x30, 0x78, 0x25
+.data1 	0x78, 0x20, 0x61, 0x74, 0x20, 0x30, 0x78, 0x25
+.data1 	0x78, 0x0a, 0x00, 0x00, 0x75, 0x70, 0x64, 0x61
+.data1 	0x74, 0x65, 0x5f, 0x62, 0x72, 0x69, 0x64, 0x67
+.data1 	0x65, 0x34, 0x64, 0x65, 0x76, 0x5f, 0x69, 0x6f
+.data1 	0x3a, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x67
+.data1 	0x65, 0x20, 0x62, 0x75, 0x73, 0x20, 0x74, 0x79
+.data1 	0x70, 0x65, 0x00, 0x00, 0x70, 0x63, 0x69, 0x00
+.data1 	0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x62
+.data1 	0x72, 0x69, 0x64, 0x67, 0x65, 0x34, 0x64, 0x65
+.data1 	0x76, 0x5f, 0x69, 0x6f, 0x3a, 0x20, 0x6e, 0x6f
+.data1 	0x74, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d
+.data1 	0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x66, 0x6f
+.data1 	0x72, 0x20, 0x50, 0x43, 0x49, 0x20, 0x62, 0x72
+.data1 	0x69, 0x64, 0x67, 0x65, 0x73, 0x0a, 0x00, 0x00
+.data1 	0x67, 0x65, 0x74, 0x5f, 0x66, 0x72, 0x65, 0x65
+.data1 	0x62, 0x75, 0x73, 0x3a, 0x20, 0x73, 0x68, 0x6f
+.data1 	0x75, 0x6c, 0x64, 0x20, 0x63, 0x68, 0x65, 0x63
+.data1 	0x6b, 0x20, 0x73, 0x75, 0x62, 0x6f, 0x72, 0x69
+.data1 	0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x20, 0x62
+.data1 	0x75, 0x73, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65
+.data1 	0x72, 0x0a, 0x00, 0x00, 0x77, 0x2a, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
+.data1 	0x3f, 0x2a, 0x00, 0x00, 0x4d, 0x2a, 0x00, 0x00
+.data1 	0x5b, 0x2a, 0x00, 0x00, 0x69, 0x2a, 0x00, 0x00
+.data1 	0x28, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67
+.data1 	0x29, 0x20, 0x75, 0x6e, 0x73, 0x75, 0x70, 0x70
+.data1 	0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x49, 0x53
+.data1 	0x41, 0x20, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65
+.data1 	0x20, 0x25, 0x30, 0x34, 0x58, 0x2f, 0x25, 0x30
+.data1 	0x34, 0x58, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x62
+.data1 	0x75, 0x73, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x28, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67
+.data1 	0x29, 0x20, 0x6e, 0x6f, 0x20, 0x49, 0x53, 0x41
+.data1 	0x20, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x20
+.data1 	0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x6f, 0x6e
+.data1 	0x20, 0x62, 0x75, 0x73, 0x20, 0x25, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x49, 0x53, 0x41, 0x20
+.data1 	0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x20, 0x74
+.data1 	0x79, 0x70, 0x65, 0x00, 0x50, 0x43, 0x49, 0x00
+.data1 	0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x49, 0x53
+.data1 	0x41, 0x20, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65
+.data1 	0x20, 0x28, 0x25, 0x30, 0x34, 0x58, 0x2f, 0x25
+.data1 	0x30, 0x34, 0x58, 0x29, 0x20, 0x25, 0x73, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x64, 0x65, 0x76, 0x69
+.data1 	0x63, 0x65, 0x00, 0x00, 0x70, 0x2e, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x0c, 0x2e, 0x00, 0x00, 0x2b, 0x2e, 0x00, 0x00
+.data1 	0x54, 0x2e, 0x00, 0x00, 0x53, 0x65, 0x63, 0x6f
+.data1 	0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x62, 0x75
+.data1 	0x73, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72
+.data1 	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6e, 0x69
+.data1 	0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x50, 0x43, 0x49, 0x2d
+.data1 	0x50, 0x43, 0x49, 0x20, 0x62, 0x72, 0x69, 0x64
+.data1 	0x67, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x00
+.data1 	0x50, 0x43, 0x49, 0x00, 0x74, 0x6f, 0x6f, 0x20
+.data1 	0x6d, 0x61, 0x6e, 0x79, 0x20, 0x50, 0x43, 0x49
+.data1 	0x20, 0x62, 0x75, 0x73, 0x73, 0x65, 0x73, 0x00
+.data1 	0x50, 0x43, 0x49, 0x00, 0x25, 0x75, 0x2e, 0x25
+.data1 	0x75, 0x2e, 0x25, 0x75, 0x3a, 0x20, 0x50, 0x43
+.data1 	0x49, 0x2d, 0x74, 0x6f, 0x2d, 0x50, 0x43, 0x49
+.data1 	0x20, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x3a
+.data1 	0x20, 0x25, 0x30, 0x34, 0x58, 0x2f, 0x25, 0x30
+.data1 	0x34, 0x58, 0x0a, 0x00, 0x55, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x50, 0x43, 0x49, 0x20
+.data1 	0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x25, 0x30
+.data1 	0x32, 0x78, 0x3a, 0x25, 0x30, 0x32, 0x78, 0x3a
+.data1 	0x25, 0x30, 0x32, 0x78, 0x20, 0x66, 0x6f, 0x72
+.data1 	0x20, 0x43, 0x61, 0x72, 0x64, 0x62, 0x75, 0x73
+.data1 	0x20, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x2c
+.data1 	0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20
+.data1 	0x25, 0x30, 0x34, 0x58, 0x2f, 0x25, 0x30, 0x34
+.data1 	0x58, 0x0a, 0x00, 0x00, 0x55, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x50, 0x43, 0x49, 0x20
+.data1 	0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x25, 0x30
+.data1 	0x32, 0x78, 0x3a, 0x25, 0x30, 0x32, 0x78, 0x3a
+.data1 	0x25, 0x30, 0x32, 0x78, 0x20, 0x66, 0x6f, 0x72
+.data1 	0x20, 0x50, 0x43, 0x49, 0x2d, 0x74, 0x6f, 0x2d
+.data1 	0x50, 0x43, 0x49, 0x20, 0x62, 0x72, 0x69, 0x64
+.data1 	0x67, 0x65, 0x2c, 0x20, 0x64, 0x65, 0x76, 0x69
+.data1 	0x63, 0x65, 0x20, 0x25, 0x30, 0x34, 0x58, 0x2f
+.data1 	0x25, 0x30, 0x34, 0x58, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x67, 0x65, 0x74, 0x5f, 0x62, 0x75, 0x73, 0x69
+.data1 	0x6e, 0x64, 0x3a, 0x20, 0x63, 0x61, 0x6e, 0x27
+.data1 	0x74, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x62
+.data1 	0x75, 0x73, 0x00, 0x00, 0x70, 0x63, 0x69, 0x00
+.data1 	0x28, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67
+.data1 	0x29, 0x20, 0x49, 0x52, 0x51, 0x20, 0x25, 0x64
+.data1 	0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20
+.data1 	0x6c, 0x65, 0x76, 0x65, 0x6c, 0x20, 0x74, 0x72
+.data1 	0x69, 0x67, 0x67, 0x65, 0x72, 0x65, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x49, 0x4e, 0x54, 0x25
+.data1 	0x63, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x49, 0x4e, 0x54, 0x25, 0x63, 0x3a, 0x20, 0x64
+.data1 	0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x57, 0x61, 0x72, 0x6e
+.data1 	0x69, 0x6e, 0x67, 0x2c, 0x20, 0x73, 0x79, 0x73
+.data1 	0x5f, 0x69, 0x6e, 0x62, 0x20, 0x66, 0x61, 0x69
+.data1 	0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x57, 0x61, 0x72, 0x6e
+.data1 	0x69, 0x6e, 0x67, 0x2c, 0x20, 0x73, 0x79, 0x73
+.data1 	0x5f, 0x69, 0x6e, 0x62, 0x20, 0x66, 0x61, 0x69
+.data1 	0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x28, 0x77, 0x61, 0x72
+.data1 	0x6e, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x49, 0x52
+.data1 	0x51, 0x20, 0x25, 0x64, 0x20, 0x69, 0x73, 0x20
+.data1 	0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x65, 0x76, 0x65
+.data1 	0x6c, 0x20, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65
+.data1 	0x72, 0x65, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x49, 0x4e, 0x54, 0x25, 0x63, 0x3a, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x49, 0x4e, 0x54, 0x25
+.data1 	0x63, 0x3a, 0x20, 0x64, 0x69, 0x73, 0x61, 0x62
+.data1 	0x6c, 0x65, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x74, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79
+.data1 	0x20, 0x50, 0x43, 0x49, 0x20, 0x64, 0x65, 0x76
+.data1 	0x69, 0x63, 0x65, 0x73, 0x00, 0x00, 0x00, 0x00
+.data1 	0x50, 0x43, 0x49, 0x00, 0x49, 0x4e, 0x54, 0x25
+.data1 	0x63, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x49, 0x4e, 0x54, 0x25, 0x63, 0x3a, 0x20, 0x64
+.data1 	0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0xd2, 0x32, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
+.data1 	0x52, 0x32, 0x00, 0x00, 0x72, 0x32, 0x00, 0x00
+.data1 	0x8c, 0x32, 0x00, 0x00, 0xa9, 0x32, 0x00, 0x00
+.data1 	0x28, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67
+.data1 	0x29, 0x20, 0x49, 0x52, 0x51, 0x20, 0x25, 0x64
+.data1 	0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20
+.data1 	0x6c, 0x65, 0x76, 0x65, 0x6c, 0x20, 0x74, 0x72
+.data1 	0x69, 0x67, 0x67, 0x65, 0x72, 0x65, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x49, 0x4e, 0x54, 0x25
+.data1 	0x63, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x49, 0x4e, 0x54, 0x25, 0x63, 0x3a, 0x20, 0x64
+.data1 	0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x50, 0x43, 0x49, 0x3a
+.data1 	0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x6d
+.data1 	0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x66, 0x6f
+.data1 	0x72, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x20, 0x61, 0x74, 0x20, 0x25, 0x64, 0x2e, 0x25
+.data1 	0x64, 0x2e, 0x25, 0x64, 0x3a, 0x20, 0x25, 0x64
+.data1 	0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x0a, 0x00
+.data1 	0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00
+.data1 	0x50, 0x43, 0x49, 0x3a, 0x20, 0x77, 0x61, 0x72
+.data1 	0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x73, 0x79
+.data1 	0x73, 0x5f, 0x6f, 0x75, 0x74, 0x6c, 0x20, 0x66
+.data1 	0x61, 0x69, 0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x50, 0x43, 0x49, 0x3a
+.data1 	0x20, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67
+.data1 	0x2c, 0x20, 0x73, 0x79, 0x73, 0x5f, 0x6f, 0x75
+.data1 	0x74, 0x6c, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65
+.data1 	0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x50, 0x43, 0x49, 0x3a, 0x20, 0x77, 0x61, 0x72
+.data1 	0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x73, 0x79
+.data1 	0x73, 0x5f, 0x6f, 0x75, 0x74, 0x6c, 0x20, 0x66
+.data1 	0x61, 0x69, 0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x50, 0x43, 0x49, 0x3a
+.data1 	0x20, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67
+.data1 	0x2c, 0x20, 0x73, 0x79, 0x73, 0x5f, 0x6f, 0x75
+.data1 	0x74, 0x6c, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65
+.data1 	0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x50, 0x43, 0x49, 0x3a, 0x20, 0x77, 0x61, 0x72
+.data1 	0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x73, 0x79
+.data1 	0x73, 0x5f, 0x6f, 0x75, 0x74, 0x6c, 0x20, 0x66
+.data1 	0x61, 0x69, 0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x50, 0x43, 0x49, 0x3a
+.data1 	0x20, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67
+.data1 	0x2c, 0x20, 0x73, 0x79, 0x73, 0x5f, 0x6f, 0x75
+.data1 	0x74, 0x6c, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65
+.data1 	0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x50, 0x43, 0x49, 0x3a, 0x20, 0x77, 0x61, 0x72
+.data1 	0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x73, 0x79
+.data1 	0x73, 0x5f, 0x6f, 0x75, 0x74, 0x6c, 0x20, 0x66
+.data1 	0x61, 0x69, 0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x50, 0x43, 0x49, 0x3a
+.data1 	0x20, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67
+.data1 	0x2c, 0x20, 0x73, 0x79, 0x73, 0x5f, 0x6f, 0x75
+.data1 	0x74, 0x6c, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65
+.data1 	0x64, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00
+.data1 	0x07, 0x41, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x0e, 0x00, 0x00, 0x00, 0xc1, 0x40, 0x00, 0x00
+.data1 	0xc8, 0x40, 0x00, 0x00, 0xcf, 0x40, 0x00, 0x00
+.data1 	0xd6, 0x40, 0x00, 0x00, 0xdd, 0x40, 0x00, 0x00
+.data1 	0xe4, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00
+.data1 	0xeb, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00
+.data1 	0x07, 0x41, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00
+.data1 	0x07, 0x41, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00
+.data1 	0x07, 0x41, 0x00, 0x00, 0xf2, 0x40, 0x00, 0x00
+.data1 	0x20, 0x40, 0x30, 0x78, 0x25, 0x78, 0x3a, 0x20
+.data1 	0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69
+.data1 	0x74, 0x79, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20
+.data1 	0x30, 0x78, 0x25, 0x78, 0x3a, 0x20, 0x25, 0x73
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x28, 0x75, 0x6e, 0x6b
+.data1 	0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x74, 0x79, 0x70
+.data1 	0x65, 0x29, 0x00, 0x00, 0x41, 0x4d, 0x44, 0x20
+.data1 	0x49, 0x2f, 0x4f, 0x20, 0x4d, 0x4d, 0x55, 0x00
+.data1 	0x41, 0x4d, 0x44, 0x20, 0x48, 0x79, 0x70, 0x65
+.data1 	0x72, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f
+.data1 	0x72, 0x74, 0x00, 0x00, 0x43, 0x6f, 0x6d, 0x70
+.data1 	0x61, 0x63, 0x74, 0x50, 0x43, 0x49, 0x20, 0x48
+.data1 	0x6f, 0x74, 0x20, 0x53, 0x77, 0x61, 0x70, 0x00
+.data1 	0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20
+.data1 	0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x65, 0x64
+.data1 	0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75
+.data1 	0x70, 0x74, 0x73, 0x00, 0x53, 0x6c, 0x6f, 0x74
+.data1 	0x20, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66
+.data1 	0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00
+.data1 	0x56, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x50, 0x72
+.data1 	0x6f, 0x64, 0x75, 0x63, 0x74, 0x20, 0x44, 0x61
+.data1 	0x74, 0x61, 0x00, 0x00, 0x41, 0x47, 0x50, 0x00
+.data1 	0x50, 0x43, 0x49, 0x20, 0x50, 0x6f, 0x77, 0x65
+.data1 	0x72, 0x20, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65
+.data1 	0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00
+.data1 	0x41, 0x64, 0x61, 0x70, 0x74, 0x65, 0x63, 0x00
+.data1 	0x41, 0x64, 0x61, 0x70, 0x74, 0x65, 0x63, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x00, 0x00, 0x00
+.data1 	0x53, 0x33, 0x00, 0x00, 0x45, 0x6e, 0x73, 0x6f
+.data1 	0x6e, 0x69, 0x71, 0x00, 0x45, 0x53, 0x53, 0x20
+.data1 	0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f
+.data1 	0x67, 0x79, 0x00, 0x00, 0x53, 0x69, 0x65, 0x6d
+.data1 	0x65, 0x6e, 0x73, 0x20, 0x4e, 0x69, 0x78, 0x64
+.data1 	0x6f, 0x72, 0x66, 0x20, 0x41, 0x47, 0x00, 0x00
+.data1 	0x56, 0x49, 0x41, 0x00, 0x52, 0x65, 0x61, 0x6c
+.data1 	0x74, 0x65, 0x6b, 0x00, 0x6e, 0x56, 0x69, 0x64
+.data1 	0x69, 0x61, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f
+.data1 	0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00
+.data1 	0x4e, 0x65, 0x6f, 0x6d, 0x61, 0x67, 0x69, 0x63
+.data1 	0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61
+.data1 	0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00
+.data1 	0x41, 0x63, 0x65, 0x72, 0x4c, 0x61, 0x62, 0x73
+.data1 	0x20, 0x28, 0x41, 0x4c, 0x49, 0x29, 0x00, 0x00
+.data1 	0x33, 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x6f, 0x72
+.data1 	0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e
+.data1 	0x00, 0x00, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x6d
+.data1 	0x69, 0x73, 0x65, 0x20, 0x54, 0x65, 0x63, 0x68
+.data1 	0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x00, 0x00
+.data1 	0x54, 0x65, 0x78, 0x61, 0x73, 0x20, 0x49, 0x6e
+.data1 	0x73, 0x74, 0x72, 0x75, 0x6d, 0x65, 0x6e, 0x74
+.data1 	0x73, 0x00, 0x00, 0x00, 0x53, 0x69, 0x6c, 0x69
+.data1 	0x63, 0x6f, 0x6e, 0x20, 0x49, 0x6e, 0x74, 0x65
+.data1 	0x67, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x53
+.data1 	0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x28
+.data1 	0x53, 0x69, 0x53, 0x29, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4d, 0x61, 0x74, 0x72, 0x6f, 0x78, 0x20, 0x47
+.data1 	0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2c
+.data1 	0x20, 0x49, 0x6e, 0x63, 0x2e, 0x00, 0x00, 0x00
+.data1 	0x41, 0x64, 0x76, 0x61, 0x6e, 0x63, 0x65, 0x64
+.data1 	0x20, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x20, 0x44
+.data1 	0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x00, 0x00
+.data1 	0x43, 0x69, 0x72, 0x72, 0x75, 0x73, 0x20, 0x4c
+.data1 	0x6f, 0x67, 0x69, 0x63, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c
+.data1 	0x20, 0x53, 0x65, 0x6d, 0x69, 0x63, 0x6f, 0x6e
+.data1 	0x64, 0x75, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x43
+.data1 	0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x00, 0x00, 0x41, 0x54, 0x49, 0x20
+.data1 	0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f
+.data1 	0x67, 0x69, 0x65, 0x73, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x43, 0x52, 0x00, 0x41, 0x64, 0x61, 0x70
+.data1 	0x74, 0x65, 0x63, 0x20, 0x41, 0x49, 0x43, 0x2d
+.data1 	0x37, 0x38, 0x39, 0x32, 0x41, 0x20, 0x55, 0x6c
+.data1 	0x74, 0x72, 0x61, 0x31, 0x36, 0x30, 0x2f, 0x6d
+.data1 	0x20, 0x50, 0x43, 0x49, 0x20, 0x53, 0x43, 0x53
+.data1 	0x49, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f
+.data1 	0x6c, 0x6c, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00
+.data1 	0x41, 0x64, 0x61, 0x70, 0x74, 0x65, 0x63, 0x20
+.data1 	0x41, 0x48, 0x41, 0x2d, 0x32, 0x39, 0x34, 0x30
+.data1 	0x55, 0x2f, 0x32, 0x39, 0x34, 0x30, 0x55, 0x57
+.data1 	0x20, 0x55, 0x6c, 0x74, 0x72, 0x61, 0x2f, 0x55
+.data1 	0x6c, 0x74, 0x72, 0x61, 0x2d, 0x57, 0x69, 0x64
+.data1 	0x65, 0x20, 0x53, 0x43, 0x53, 0x49, 0x20, 0x43
+.data1 	0x74, 0x72, 0x6c, 0x72, 0x00, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x34, 0x34, 0x33, 0x42, 0x58, 0x20, 0x28, 0x48
+.data1 	0x6f, 0x73, 0x74, 0x2d, 0x74, 0x6f, 0x2d, 0x50
+.data1 	0x43, 0x49, 0x20, 0x62, 0x72, 0x69, 0x64, 0x67
+.data1 	0x65, 0x29, 0x00, 0x00, 0x49, 0x6e, 0x74, 0x65
+.data1 	0x6c, 0x20, 0x38, 0x32, 0x34, 0x34, 0x33, 0x42
+.data1 	0x58, 0x20, 0x28, 0x41, 0x47, 0x50, 0x20, 0x62
+.data1 	0x72, 0x69, 0x64, 0x67, 0x65, 0x29, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x34, 0x34, 0x33, 0x42, 0x58, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x38, 0x30, 0x31, 0x41, 0x41, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x33, 0x37, 0x31, 0x41, 0x42, 0x20, 0x28, 0x50
+.data1 	0x6f, 0x77, 0x65, 0x72, 0x29, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x33, 0x37, 0x31, 0x41, 0x42, 0x20, 0x28, 0x55
+.data1 	0x53, 0x42, 0x29, 0x00, 0x49, 0x6e, 0x74, 0x65
+.data1 	0x6c, 0x20, 0x38, 0x32, 0x33, 0x37, 0x31, 0x41
+.data1 	0x42, 0x20, 0x28, 0x49, 0x44, 0x45, 0x29, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x33, 0x37, 0x31, 0x41, 0x42, 0x20, 0x28, 0x50
+.data1 	0x49, 0x49, 0x58, 0x34, 0x29, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x33, 0x37, 0x31, 0x41, 0x42, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x33, 0x37, 0x31, 0x41, 0x42, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x34, 0x33, 0x37, 0x56, 0x58, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x33, 0x37, 0x31, 0x53, 0x42, 0x20, 0x28, 0x55
+.data1 	0x53, 0x42, 0x29, 0x00, 0x49, 0x6e, 0x74, 0x65
+.data1 	0x6c, 0x20, 0x38, 0x32, 0x33, 0x37, 0x31, 0x53
+.data1 	0x42, 0x20, 0x28, 0x49, 0x44, 0x45, 0x29, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x33, 0x37, 0x31, 0x53, 0x42, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x38, 0x34, 0x35, 0x47, 0x2f, 0x47, 0x4c, 0x2f
+.data1 	0x47, 0x45, 0x2f, 0x50, 0x45, 0x20, 0x48, 0x6f
+.data1 	0x73, 0x74, 0x2d, 0x74, 0x6f, 0x2d, 0x41, 0x47
+.data1 	0x50, 0x20, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x74, 0x65
+.data1 	0x6c, 0x20, 0x38, 0x32, 0x38, 0x34, 0x35, 0x47
+.data1 	0x2f, 0x47, 0x4c, 0x5b, 0x42, 0x72, 0x6f, 0x6f
+.data1 	0x6b, 0x64, 0x61, 0x6c, 0x65, 0x2d, 0x47, 0x5d
+.data1 	0x2f, 0x47, 0x45, 0x2f, 0x50, 0x45, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x38, 0x30, 0x31, 0x20, 0x50, 0x43, 0x49, 0x20
+.data1 	0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x45, 0x74
+.data1 	0x68, 0x65, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65
+.data1 	0x73, 0x73, 0x50, 0x72, 0x6f, 0x31, 0x30, 0x30
+.data1 	0x20, 0x38, 0x32, 0x35, 0x36, 0x32, 0x45, 0x4d
+.data1 	0x00, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x74, 0x65
+.data1 	0x6c, 0x20, 0x38, 0x32, 0x38, 0x30, 0x31, 0x42
+.data1 	0x20, 0x50, 0x43, 0x49, 0x20, 0x74, 0x6f, 0x20
+.data1 	0x49, 0x53, 0x41, 0x20, 0x62, 0x72, 0x69, 0x64
+.data1 	0x67, 0x65, 0x00, 0x00, 0x49, 0x6e, 0x74, 0x65
+.data1 	0x6c, 0x20, 0x38, 0x32, 0x38, 0x34, 0x35, 0x42
+.data1 	0x2f, 0x41, 0x20, 0x50, 0x43, 0x49, 0x20, 0x42
+.data1 	0x72, 0x69, 0x64, 0x67, 0x65, 0x20, 0x74, 0x6f
+.data1 	0x20, 0x41, 0x47, 0x50, 0x20, 0x70, 0x6f, 0x72
+.data1 	0x74, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x74, 0x65
+.data1 	0x6c, 0x20, 0x38, 0x32, 0x38, 0x34, 0x35, 0x42
+.data1 	0x2f, 0x41, 0x20, 0x4d, 0x43, 0x48, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x34, 0x33, 0x39, 0x48, 0x58, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x34, 0x34, 0x31, 0x46, 0x58, 0x20, 0x28, 0x34
+.data1 	0x34, 0x30, 0x46, 0x58, 0x29, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x33, 0x37, 0x31, 0x46, 0x42, 0x20, 0x28, 0x49
+.data1 	0x44, 0x45, 0x29, 0x00, 0x49, 0x6e, 0x74, 0x65
+.data1 	0x6c, 0x20, 0x38, 0x32, 0x33, 0x37, 0x31, 0x46
+.data1 	0x42, 0x20, 0x28, 0x50, 0x49, 0x49, 0x58, 0x29
+.data1 	0x00, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x74, 0x65
+.data1 	0x6c, 0x20, 0x38, 0x32, 0x34, 0x33, 0x37, 0x46
+.data1 	0x58, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x74, 0x65
+.data1 	0x6c, 0x20, 0x45, 0x74, 0x68, 0x65, 0x72, 0x45
+.data1 	0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x50, 0x72
+.data1 	0x6f, 0x31, 0x30, 0x30, 0x20, 0x38, 0x32, 0x35
+.data1 	0x35, 0x37, 0x2f, 0x38, 0x2f, 0x39, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x45, 0x74
+.data1 	0x68, 0x65, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65
+.data1 	0x73, 0x73, 0x50, 0x72, 0x6f, 0x31, 0x30, 0x30
+.data1 	0x20, 0x38, 0x32, 0x35, 0x35, 0x39, 0x45, 0x52
+.data1 	0x00, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x74, 0x65
+.data1 	0x6c, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72
+.data1 	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x38, 0x32
+.data1 	0x35, 0x35, 0x39, 0x20, 0x49, 0x6e, 0x42, 0x75
+.data1 	0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x31
+.data1 	0x30, 0x2f, 0x31, 0x30, 0x30, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x45, 0x74
+.data1 	0x68, 0x65, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65
+.data1 	0x73, 0x73, 0x50, 0x72, 0x6f, 0x31, 0x30, 0x30
+.data1 	0x20, 0x49, 0x44, 0x31, 0x30, 0x32, 0x39, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x38, 0x32
+.data1 	0x35, 0x34, 0x33, 0x47, 0x43, 0x20, 0x47, 0x69
+.data1 	0x67, 0x61, 0x62, 0x69, 0x74, 0x20, 0x45, 0x74
+.data1 	0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x43
+.data1 	0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65
+.data1 	0x72, 0x00, 0x00, 0x00, 0x53, 0x33, 0x20, 0x56
+.data1 	0x69, 0x72, 0x67, 0x65, 0x2f, 0x44, 0x58, 0x20
+.data1 	0x6f, 0x72, 0x20, 0x2f, 0x47, 0x58, 0x00, 0x00
+.data1 	0x53, 0x33, 0x20, 0x56, 0x69, 0x73, 0x69, 0x6f
+.data1 	0x6e, 0x20, 0x39, 0x36, 0x34, 0x20, 0x76, 0x65
+.data1 	0x72, 0x73, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x53, 0x33, 0x20, 0x56, 0x69, 0x72, 0x67, 0x65
+.data1 	0x2f, 0x56, 0x58, 0x00, 0x53, 0x33, 0x20, 0x38
+.data1 	0x36, 0x63, 0x37, 0x36, 0x34, 0x2f, 0x37, 0x36
+.data1 	0x35, 0x20, 0x5b, 0x54, 0x72, 0x69, 0x6f, 0x33
+.data1 	0x32, 0x2f, 0x36, 0x34, 0x2f, 0x36, 0x34, 0x56
+.data1 	0x2b, 0x5d, 0x00, 0x00, 0x45, 0x6e, 0x73, 0x6f
+.data1 	0x6e, 0x69, 0x71, 0x20, 0x43, 0x54, 0x35, 0x38
+.data1 	0x38, 0x30, 0x20, 0x5b, 0x41, 0x75, 0x64, 0x69
+.data1 	0x6f, 0x50, 0x43, 0x49, 0x5d, 0x00, 0x00, 0x00
+.data1 	0x45, 0x6e, 0x73, 0x6f, 0x6e, 0x69, 0x71, 0x20
+.data1 	0x45, 0x53, 0x31, 0x33, 0x37, 0x30, 0x00, 0x00
+.data1 	0x45, 0x6e, 0x73, 0x6f, 0x6e, 0x69, 0x71, 0x20
+.data1 	0x45, 0x53, 0x31, 0x33, 0x37, 0x31, 0x20, 0x5b
+.data1 	0x41, 0x75, 0x64, 0x69, 0x6f, 0x50, 0x43, 0x49
+.data1 	0x2d, 0x39, 0x37, 0x5d, 0x00, 0x00, 0x00, 0x00
+.data1 	0x45, 0x53, 0x53, 0x20, 0x45, 0x53, 0x31, 0x39
+.data1 	0x36, 0x39, 0x20, 0x53, 0x6f, 0x6c, 0x6f, 0x2d
+.data1 	0x31, 0x20, 0x41, 0x75, 0x64, 0x69, 0x6f, 0x64
+.data1 	0x72, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x44, 0x2d, 0x4c, 0x69, 0x6e, 0x6b, 0x20, 0x52
+.data1 	0x54, 0x4c, 0x38, 0x31, 0x33, 0x39, 0x00, 0x00
+.data1 	0x53, 0x69, 0x65, 0x6d, 0x65, 0x6e, 0x73, 0x20
+.data1 	0x4e, 0x69, 0x78, 0x64, 0x6f, 0x72, 0x66, 0x20
+.data1 	0x54, 0x75, 0x6c, 0x69, 0x70, 0x20, 0x43, 0x6e
+.data1 	0x74, 0x6c, 0x72, 0x2e, 0x2c, 0x20, 0x50, 0x6f
+.data1 	0x77, 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x61
+.data1 	0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00
+.data1 	0x56, 0x54, 0x38, 0x32, 0x33, 0x37, 0x20, 0x50
+.data1 	0x43, 0x49, 0x20, 0x62, 0x72, 0x69, 0x64, 0x67
+.data1 	0x65, 0x00, 0x00, 0x00, 0x56, 0x49, 0x41, 0x20
+.data1 	0x56, 0x54, 0x38, 0x33, 0x36, 0x37, 0x20, 0x5b
+.data1 	0x4b, 0x54, 0x32, 0x36, 0x36, 0x20, 0x41, 0x47
+.data1 	0x50, 0x5d, 0x00, 0x00, 0x56, 0x49, 0x41, 0x20
+.data1 	0x56, 0x54, 0x38, 0x33, 0x36, 0x35, 0x20, 0x5b
+.data1 	0x4b, 0x4d, 0x31, 0x33, 0x33, 0x20, 0x41, 0x47
+.data1 	0x50, 0x5d, 0x00, 0x00, 0x4b, 0x38, 0x4d, 0x38
+.data1 	0x30, 0x30, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20
+.data1 	0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x00, 0x00
+.data1 	0x56, 0x54, 0x38, 0x32, 0x33, 0x37, 0x20, 0x49
+.data1 	0x53, 0x41, 0x20, 0x62, 0x72, 0x69, 0x64, 0x67
+.data1 	0x65, 0x00, 0x00, 0x00, 0x4b, 0x38, 0x4d, 0x38
+.data1 	0x30, 0x30, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20
+.data1 	0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x00, 0x00
+.data1 	0x56, 0x49, 0x41, 0x20, 0x56, 0x54, 0x36, 0x34
+.data1 	0x32, 0x30, 0x20, 0x53, 0x41, 0x54, 0x41, 0x20
+.data1 	0x52, 0x41, 0x49, 0x44, 0x20, 0x43, 0x6f, 0x6e
+.data1 	0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00
+.data1 	0x56, 0x49, 0x41, 0x20, 0x53, 0x33, 0x20, 0x55
+.data1 	0x6e, 0x69, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65
+.data1 	0x20, 0x50, 0x72, 0x6f, 0x20, 0x56, 0x47, 0x41
+.data1 	0x20, 0x41, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72
+.data1 	0x00, 0x00, 0x00, 0x00, 0x56, 0x49, 0x41, 0x20
+.data1 	0x55, 0x53, 0x42, 0x20, 0x32, 0x2e, 0x30, 0x00
+.data1 	0x56, 0x49, 0x41, 0x20, 0x56, 0x54, 0x38, 0x33
+.data1 	0x36, 0x37, 0x20, 0x5b, 0x4b, 0x54, 0x32, 0x36
+.data1 	0x36, 0x5d, 0x00, 0x00, 0x56, 0x49, 0x41, 0x20
+.data1 	0x56, 0x54, 0x38, 0x32, 0x33, 0x33, 0x00, 0x00
+.data1 	0x56, 0x54, 0x36, 0x31, 0x30, 0x32, 0x20, 0x5b
+.data1 	0x52, 0x68, 0x69, 0x6e, 0x65, 0x2d, 0x49, 0x49
+.data1 	0x5d, 0x00, 0x00, 0x00, 0x56, 0x49, 0x41, 0x20
+.data1 	0x41, 0x43, 0x39, 0x37, 0x20, 0x41, 0x75, 0x64
+.data1 	0x69, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72
+.data1 	0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x00, 0x00
+.data1 	0x56, 0x49, 0x41, 0x20, 0x41, 0x43, 0x39, 0x37
+.data1 	0x20, 0x41, 0x75, 0x64, 0x69, 0x6f, 0x20, 0x43
+.data1 	0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65
+.data1 	0x72, 0x00, 0x00, 0x00, 0x56, 0x54, 0x38, 0x32
+.data1 	0x43, 0x36, 0x38, 0x36, 0x41, 0x20, 0x41, 0x43
+.data1 	0x50, 0x49, 0x20, 0x50, 0x6f, 0x77, 0x65, 0x72
+.data1 	0x20, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d
+.data1 	0x65, 0x6e, 0x74, 0x20, 0x43, 0x6f, 0x6e, 0x74
+.data1 	0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x00
+.data1 	0x56, 0x54, 0x38, 0x33, 0x43, 0x35, 0x37, 0x32
+.data1 	0x20, 0x50, 0x43, 0x49, 0x20, 0x55, 0x53, 0x42
+.data1 	0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c
+.data1 	0x6c, 0x65, 0x72, 0x00, 0x4b, 0x38, 0x4d, 0x38
+.data1 	0x30, 0x30, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20
+.data1 	0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x00, 0x00
+.data1 	0x4b, 0x38, 0x4d, 0x38, 0x30, 0x30, 0x20, 0x48
+.data1 	0x6f, 0x73, 0x74, 0x20, 0x42, 0x72, 0x69, 0x64
+.data1 	0x67, 0x65, 0x00, 0x00, 0x56, 0x49, 0x41, 0x20
+.data1 	0x56, 0x54, 0x38, 0x32, 0x43, 0x36, 0x38, 0x36
+.data1 	0x20, 0x28, 0x41, 0x70, 0x6f, 0x6c, 0x6c, 0x6f
+.data1 	0x20, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x42
+.data1 	0x72, 0x69, 0x64, 0x67, 0x65, 0x29, 0x00, 0x00
+.data1 	0x56, 0x49, 0x41, 0x20, 0x49, 0x44, 0x45, 0x20
+.data1 	0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c
+.data1 	0x65, 0x72, 0x00, 0x00, 0x56, 0x49, 0x41, 0x20
+.data1 	0x56, 0x54, 0x38, 0x33, 0x36, 0x33, 0x2f, 0x38
+.data1 	0x33, 0x36, 0x35, 0x20, 0x5b, 0x4b, 0x54, 0x31
+.data1 	0x33, 0x33, 0x2f, 0x4b, 0x4d, 0x31, 0x33, 0x33
+.data1 	0x5d, 0x00, 0x00, 0x00, 0x52, 0x65, 0x61, 0x6c
+.data1 	0x74, 0x65, 0x6b, 0x20, 0x52, 0x54, 0x4c, 0x38
+.data1 	0x31, 0x33, 0x39, 0x00, 0x52, 0x65, 0x61, 0x6c
+.data1 	0x74, 0x65, 0x6b, 0x20, 0x52, 0x54, 0x4c, 0x38
+.data1 	0x30, 0x32, 0x39, 0x00, 0x6e, 0x56, 0x69, 0x64
+.data1 	0x69, 0x61, 0x20, 0x47, 0x65, 0x46, 0x6f, 0x72
+.data1 	0x63, 0x65, 0x32, 0x20, 0x4d, 0x58, 0x20, 0x5b
+.data1 	0x4e, 0x56, 0x31, 0x31, 0x5d, 0x00, 0x00, 0x00
+.data1 	0x6e, 0x56, 0x69, 0x64, 0x69, 0x61, 0x20, 0x52
+.data1 	0x69, 0x76, 0x61, 0x20, 0x54, 0x6e, 0x54, 0x20
+.data1 	0x5b, 0x4e, 0x56, 0x30, 0x34, 0x5d, 0x00, 0x00
+.data1 	0x4e, 0x65, 0x6f, 0x6d, 0x61, 0x67, 0x69, 0x63
+.data1 	0x20, 0x4e, 0x4d, 0x32, 0x32, 0x30, 0x30, 0x20
+.data1 	0x4d, 0x61, 0x67, 0x69, 0x63, 0x20, 0x47, 0x72
+.data1 	0x61, 0x70, 0x68, 0x20, 0x32, 0x35, 0x36, 0x41
+.data1 	0x56, 0x20, 0x41, 0x75, 0x64, 0x69, 0x6f, 0x00
+.data1 	0x4e, 0x65, 0x6f, 0x6d, 0x61, 0x67, 0x69, 0x63
+.data1 	0x20, 0x4e, 0x4d, 0x32, 0x32, 0x30, 0x30, 0x20
+.data1 	0x4d, 0x61, 0x67, 0x69, 0x63, 0x20, 0x47, 0x72
+.data1 	0x61, 0x70, 0x68, 0x20, 0x32, 0x35, 0x36, 0x41
+.data1 	0x56, 0x00, 0x00, 0x00, 0x41, 0x4c, 0x49, 0x20
+.data1 	0x4d, 0x37, 0x31, 0x30, 0x31, 0x20, 0x50, 0x4d
+.data1 	0x55, 0x00, 0x00, 0x00, 0x41, 0x4c, 0x49, 0x20
+.data1 	0x4d, 0x35, 0x32, 0x34, 0x33, 0x00, 0x00, 0x00
+.data1 	0x41, 0x4c, 0x49, 0x20, 0x4d, 0x35, 0x32, 0x32
+.data1 	0x39, 0x20, 0x28, 0x49, 0x44, 0x45, 0x29, 0x00
+.data1 	0x41, 0x4c, 0x49, 0x20, 0x4d, 0x31, 0x35, 0x34
+.data1 	0x31, 0x00, 0x00, 0x00, 0x41, 0x4c, 0x49, 0x20
+.data1 	0x4d, 0x31, 0x35, 0x33, 0x33, 0x20, 0x49, 0x53
+.data1 	0x41, 0x2d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65
+.data1 	0x20, 0x5b, 0x41, 0x6c, 0x61, 0x64, 0x64, 0x69
+.data1 	0x6e, 0x20, 0x49, 0x56, 0x5d, 0x00, 0x00, 0x00
+.data1 	0x33, 0x43, 0x6f, 0x6d, 0x20, 0x33, 0x63, 0x39
+.data1 	0x38, 0x30, 0x2d, 0x54, 0x58, 0x20, 0x50, 0x79
+.data1 	0x74, 0x68, 0x6f, 0x6e, 0x2d, 0x54, 0x00, 0x00
+.data1 	0x33, 0x43, 0x6f, 0x6d, 0x20, 0x33, 0x63, 0x39
+.data1 	0x30, 0x35, 0x42, 0x2d, 0x43, 0x6f, 0x6d, 0x62
+.data1 	0x6f, 0x00, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x6d
+.data1 	0x69, 0x73, 0x65, 0x20, 0x54, 0x65, 0x63, 0x68
+.data1 	0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x20, 0x32
+.data1 	0x30, 0x32, 0x36, 0x35, 0x00, 0x00, 0x00, 0x00
+.data1 	0x54, 0x49, 0x20, 0x50, 0x43, 0x49, 0x31, 0x32
+.data1 	0x32, 0x35, 0x00, 0x00, 0x53, 0x69, 0x53, 0x20
+.data1 	0x35, 0x35, 0x38, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x53, 0x69, 0x53, 0x20, 0x38, 0x35, 0x43, 0x35
+.data1 	0x30, 0x31, 0x2f, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x53, 0x69, 0x53, 0x20, 0x35, 0x35, 0x39, 0x37
+.data1 	0x2f, 0x35, 0x35, 0x39, 0x38, 0x20, 0x56, 0x47
+.data1 	0x41, 0x00, 0x00, 0x00, 0x53, 0x69, 0x53, 0x20
+.data1 	0x38, 0x35, 0x43, 0x35, 0x30, 0x33, 0x2f, 0x35
+.data1 	0x35, 0x31, 0x33, 0x00, 0x4d, 0x61, 0x74, 0x72
+.data1 	0x6f, 0x78, 0x20, 0x4d, 0x47, 0x41, 0x20, 0x47
+.data1 	0x34, 0x30, 0x30, 0x20, 0x41, 0x47, 0x50, 0x00
+.data1 	0x4d, 0x61, 0x74, 0x72, 0x6f, 0x78, 0x20, 0x4d
+.data1 	0x47, 0x41, 0x20, 0x32, 0x31, 0x36, 0x34, 0x57
+.data1 	0x20, 0x5b, 0x4d, 0x69, 0x6c, 0x6c, 0x65, 0x6e
+.data1 	0x6e, 0x69, 0x75, 0x6d, 0x20, 0x49, 0x49, 0x5d
+.data1 	0x00, 0x00, 0x00, 0x00, 0x41, 0x4d, 0x44, 0x2d
+.data1 	0x37, 0x36, 0x36, 0x20, 0x45, 0x49, 0x44, 0x45
+.data1 	0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c
+.data1 	0x6c, 0x65, 0x72, 0x00, 0x41, 0x4d, 0x44, 0x2d
+.data1 	0x37, 0x36, 0x36, 0x20, 0x50, 0x43, 0x49, 0x20
+.data1 	0x74, 0x6f, 0x20, 0x49, 0x53, 0x41, 0x2f, 0x4c
+.data1 	0x50, 0x43, 0x20, 0x42, 0x72, 0x69, 0x64, 0x67
+.data1 	0x65, 0x00, 0x00, 0x00, 0x41, 0x4d, 0x44, 0x2d
+.data1 	0x37, 0x36, 0x32, 0x20, 0x43, 0x50, 0x55, 0x20
+.data1 	0x74, 0x6f, 0x20, 0x50, 0x43, 0x49, 0x20, 0x42
+.data1 	0x72, 0x69, 0x64, 0x67, 0x65, 0x20, 0x28, 0x41
+.data1 	0x47, 0x50, 0x20, 0x34, 0x78, 0x29, 0x00, 0x00
+.data1 	0x41, 0x4d, 0x44, 0x2d, 0x37, 0x36, 0x32, 0x20
+.data1 	0x43, 0x50, 0x55, 0x20, 0x74, 0x6f, 0x20, 0x50
+.data1 	0x43, 0x49, 0x20, 0x42, 0x72, 0x69, 0x64, 0x67
+.data1 	0x65, 0x20, 0x28, 0x53, 0x4d, 0x50, 0x20, 0x63
+.data1 	0x68, 0x69, 0x70, 0x73, 0x65, 0x74, 0x29, 0x00
+.data1 	0x41, 0x4d, 0x44, 0x20, 0x4c, 0x61, 0x6e, 0x63
+.data1 	0x65, 0x2f, 0x50, 0x43, 0x49, 0x00, 0x00, 0x00
+.data1 	0x4b, 0x38, 0x20, 0x5b, 0x41, 0x74, 0x68, 0x6c
+.data1 	0x6f, 0x6e, 0x36, 0x34, 0x2f, 0x4f, 0x70, 0x74
+.data1 	0x65, 0x72, 0x6f, 0x6e, 0x5d, 0x20, 0x4d, 0x69
+.data1 	0x73, 0x63, 0x2e, 0x20, 0x43, 0x6f, 0x6e, 0x74
+.data1 	0x72, 0x6f, 0x6c, 0x00, 0x4b, 0x38, 0x20, 0x5b
+.data1 	0x41, 0x74, 0x68, 0x6c, 0x6f, 0x6e, 0x36, 0x34
+.data1 	0x2f, 0x4f, 0x70, 0x74, 0x65, 0x72, 0x6f, 0x6e
+.data1 	0x5d, 0x20, 0x44, 0x52, 0x41, 0x4d, 0x20, 0x43
+.data1 	0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65
+.data1 	0x72, 0x00, 0x00, 0x00, 0x4b, 0x38, 0x20, 0x5b
+.data1 	0x41, 0x74, 0x68, 0x6c, 0x6f, 0x6e, 0x36, 0x34
+.data1 	0x2f, 0x4f, 0x70, 0x74, 0x65, 0x72, 0x6f, 0x6e
+.data1 	0x5d, 0x20, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73
+.data1 	0x73, 0x20, 0x4d, 0x61, 0x70, 0x00, 0x00, 0x00
+.data1 	0x4b, 0x38, 0x20, 0x48, 0x79, 0x70, 0x65, 0x72
+.data1 	0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72
+.data1 	0x74, 0x20, 0x54, 0x65, 0x63, 0x68, 0x2e, 0x20
+.data1 	0x43, 0x6f, 0x6e, 0x66, 0x2e, 0x00, 0x00, 0x00
+.data1 	0x43, 0x69, 0x72, 0x72, 0x75, 0x73, 0x20, 0x4c
+.data1 	0x6f, 0x67, 0x69, 0x63, 0x20, 0x43, 0x53, 0x34
+.data1 	0x36, 0x31, 0x34, 0x2f, 0x32, 0x32, 0x2f, 0x32
+.data1 	0x34, 0x20, 0x43, 0x72, 0x79, 0x73, 0x74, 0x61
+.data1 	0x6c, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x00, 0x00
+.data1 	0x43, 0x69, 0x72, 0x72, 0x75, 0x73, 0x20, 0x4c
+.data1 	0x6f, 0x67, 0x69, 0x63, 0x20, 0x47, 0x44, 0x20
+.data1 	0x35, 0x34, 0x34, 0x36, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x61, 0x74, 0x2e, 0x20, 0x53, 0x65, 0x6d
+.data1 	0x69, 0x2e, 0x20, 0x38, 0x37, 0x34, 0x31, 0x30
+.data1 	0x00, 0x00, 0x00, 0x00, 0x41, 0x54, 0x49, 0x20
+.data1 	0x52, 0x61, 0x67, 0x65, 0x20, 0x58, 0x4c, 0x20
+.data1 	0x50, 0x43, 0x49, 0x00, 0x4e, 0x43, 0x52, 0x20
+.data1 	0x35, 0x33, 0x43, 0x38, 0x37, 0x35, 0x00, 0x00
+.data1 	0x4e, 0x43, 0x52, 0x20, 0x35, 0x33, 0x43, 0x38
+.data1 	0x31, 0x30, 0x00, 0x00, 0x4d, 0x69, 0x73, 0x63
+.data1 	0x2e, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0x74, 0x61
+.data1 	0x20, 0x61, 0x63, 0x71, 0x75, 0x69, 0x73, 0x69
+.data1 	0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e
+.data1 	0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00
+.data1 	0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x2f, 0x64, 0x65, 0x63, 0x72, 0x79
+.data1 	0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f
+.data1 	0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72
+.data1 	0x00, 0x00, 0x00, 0x00, 0x53, 0x61, 0x74, 0x65
+.data1 	0x6c, 0x6c, 0x69, 0x74, 0x65, 0x20, 0x63, 0x6f
+.data1 	0x6d, 0x6d, 0x2e, 0x20, 0x63, 0x6f, 0x6e, 0x74
+.data1 	0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x6c, 0x6c, 0x69, 0x67
+.data1 	0x65, 0x6e, 0x74, 0x20, 0x49, 0x2f, 0x4f, 0x20
+.data1 	0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c
+.data1 	0x65, 0x72, 0x00, 0x00, 0x57, 0x69, 0x72, 0x65
+.data1 	0x6c, 0x65, 0x73, 0x73, 0x20, 0x63, 0x6f, 0x6e
+.data1 	0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00
+.data1 	0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x62
+.data1 	0x75, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72
+.data1 	0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x00, 0x00
+.data1 	0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0x44, 0x6f, 0x63, 0x6b
+.data1 	0x69, 0x6e, 0x67, 0x20, 0x73, 0x74, 0x61, 0x74
+.data1 	0x69, 0x6f, 0x6e, 0x00, 0x49, 0x6e, 0x70, 0x75
+.data1 	0x74, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0x73, 0x65
+.data1 	0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20
+.data1 	0x70, 0x65, 0x72, 0x69, 0x70, 0x68, 0x65, 0x72
+.data1 	0x61, 0x6c, 0x00, 0x00, 0x53, 0x69, 0x6d, 0x70
+.data1 	0x6c, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x2e
+.data1 	0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c
+.data1 	0x6c, 0x65, 0x72, 0x00, 0x42, 0x72, 0x69, 0x64
+.data1 	0x67, 0x65, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63
+.data1 	0x65, 0x00, 0x00, 0x00, 0x4d, 0x65, 0x6d, 0x6f
+.data1 	0x72, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72
+.data1 	0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x00, 0x00
+.data1 	0x4d, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x65, 0x64
+.data1 	0x69, 0x61, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63
+.data1 	0x65, 0x00, 0x00, 0x00, 0x44, 0x69, 0x73, 0x70
+.data1 	0x6c, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x74
+.data1 	0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x00
+.data1 	0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20
+.data1 	0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c
+.data1 	0x65, 0x72, 0x00, 0x00, 0x4d, 0x61, 0x73, 0x73
+.data1 	0x20, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65
+.data1 	0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c
+.data1 	0x6c, 0x65, 0x72, 0x00, 0x4e, 0x6f, 0x20, 0x64
+.data1 	0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x63, 0x6c
+.data1 	0x61, 0x73, 0x73, 0x00, 0x53, 0x4d, 0x42, 0x75
+.data1 	0x73, 0x00, 0x00, 0x00, 0x46, 0x69, 0x62, 0x72
+.data1 	0x65, 0x20, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65
+.data1 	0x6c, 0x00, 0x00, 0x00, 0x55, 0x53, 0x42, 0x20
+.data1 	0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00
+.data1 	0x55, 0x53, 0x42, 0x20, 0x28, 0x6f, 0x74, 0x68
+.data1 	0x65, 0x72, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x20
+.data1 	0x69, 0x6e, 0x66, 0x2e, 0x29, 0x00, 0x00, 0x00
+.data1 	0x55, 0x53, 0x42, 0x20, 0x28, 0x77, 0x69, 0x74
+.data1 	0x68, 0x20, 0x4f, 0x48, 0x43, 0x29, 0x00, 0x00
+.data1 	0x55, 0x53, 0x42, 0x20, 0x28, 0x77, 0x69, 0x74
+.data1 	0x68, 0x20, 0x55, 0x48, 0x43, 0x29, 0x00, 0x00
+.data1 	0x53, 0x53, 0x41, 0x00, 0x41, 0x43, 0x43, 0x45
+.data1 	0x53, 0x53, 0x20, 0x62, 0x75, 0x73, 0x00, 0x00
+.data1 	0x49, 0x45, 0x45, 0x45, 0x20, 0x31, 0x33, 0x39
+.data1 	0x34, 0x20, 0x28, 0x4f, 0x70, 0x65, 0x6e, 0x48
+.data1 	0x43, 0x49, 0x29, 0x00, 0x49, 0x45, 0x45, 0x45
+.data1 	0x20, 0x31, 0x33, 0x39, 0x34, 0x20, 0x28, 0x46
+.data1 	0x69, 0x72, 0x65, 0x57, 0x69, 0x72, 0x65, 0x29
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4f, 0x74, 0x68, 0x65
+.data1 	0x72, 0x20, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65
+.data1 	0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00
+.data1 	0x53, 0x65, 0x6d, 0x69, 0x2d, 0x74, 0x72, 0x61
+.data1 	0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74
+.data1 	0x20, 0x50, 0x43, 0x49, 0x2d, 0x74, 0x6f, 0x2d
+.data1 	0x50, 0x43, 0x49, 0x20, 0x62, 0x72, 0x69, 0x64
+.data1 	0x67, 0x65, 0x00, 0x00, 0x52, 0x41, 0x43, 0x45
+.data1 	0x77, 0x61, 0x79, 0x20, 0x62, 0x72, 0x69, 0x64
+.data1 	0x67, 0x65, 0x00, 0x00, 0x43, 0x61, 0x72, 0x64
+.data1 	0x42, 0x75, 0x73, 0x20, 0x62, 0x72, 0x69, 0x64
+.data1 	0x67, 0x65, 0x00, 0x00, 0x4e, 0x75, 0x42, 0x75
+.data1 	0x73, 0x20, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x50, 0x43, 0x4d, 0x43
+.data1 	0x49, 0x41, 0x20, 0x62, 0x72, 0x69, 0x64, 0x67
+.data1 	0x65, 0x00, 0x00, 0x00, 0x53, 0x75, 0x62, 0x74
+.data1 	0x72, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20
+.data1 	0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x50
+.data1 	0x43, 0x49, 0x2d, 0x74, 0x6f, 0x2d, 0x50, 0x43
+.data1 	0x49, 0x20, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x50, 0x43, 0x49, 0x2d
+.data1 	0x74, 0x6f, 0x2d, 0x50, 0x43, 0x49, 0x20, 0x62
+.data1 	0x72, 0x69, 0x64, 0x67, 0x65, 0x00, 0x00, 0x00
+.data1 	0x4d, 0x43, 0x41, 0x20, 0x62, 0x72, 0x69, 0x64
+.data1 	0x67, 0x65, 0x00, 0x00, 0x45, 0x49, 0x53, 0x41
+.data1 	0x20, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x00
+.data1 	0x49, 0x53, 0x41, 0x20, 0x62, 0x72, 0x69, 0x64
+.data1 	0x67, 0x65, 0x00, 0x00, 0x48, 0x6f, 0x73, 0x74
+.data1 	0x20, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x00
+.data1 	0x4f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6d, 0x75
+.data1 	0x6c, 0x74, 0x69, 0x6d, 0x65, 0x64, 0x69, 0x61
+.data1 	0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00
+.data1 	0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72
+.data1 	0x20, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f
+.data1 	0x6e, 0x79, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63
+.data1 	0x65, 0x00, 0x00, 0x00, 0x41, 0x75, 0x64, 0x69
+.data1 	0x6f, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x56, 0x69, 0x64, 0x65
+.data1 	0x6f, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4f, 0x74, 0x68, 0x65
+.data1 	0x72, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61
+.data1 	0x79, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f
+.data1 	0x6c, 0x6c, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00
+.data1 	0x33, 0x44, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72
+.data1 	0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x00, 0x00
+.data1 	0x58, 0x47, 0x41, 0x20, 0x63, 0x6f, 0x6e, 0x74
+.data1 	0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x00
+.data1 	0x38, 0x35, 0x31, 0x34, 0x2d, 0x63, 0x6f, 0x6d
+.data1 	0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x20
+.data1 	0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c
+.data1 	0x65, 0x72, 0x00, 0x00, 0x56, 0x47, 0x41, 0x2d
+.data1 	0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62
+.data1 	0x6c, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72
+.data1 	0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x00, 0x00
+.data1 	0x4f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6e, 0x65
+.data1 	0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x63, 0x6f
+.data1 	0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72
+.data1 	0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x44, 0x4e
+.data1 	0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c
+.data1 	0x6c, 0x65, 0x72, 0x00, 0x41, 0x54, 0x4d, 0x20
+.data1 	0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c
+.data1 	0x65, 0x72, 0x00, 0x00, 0x46, 0x44, 0x44, 0x49
+.data1 	0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c
+.data1 	0x6c, 0x65, 0x72, 0x00, 0x54, 0x6f, 0x6b, 0x65
+.data1 	0x6e, 0x20, 0x52, 0x69, 0x6e, 0x67, 0x20, 0x63
+.data1 	0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65
+.data1 	0x72, 0x00, 0x00, 0x00, 0x45, 0x74, 0x68, 0x65
+.data1 	0x72, 0x6e, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e
+.data1 	0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00
+.data1 	0x4f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6d, 0x61
+.data1 	0x73, 0x73, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x61
+.data1 	0x67, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72
+.data1 	0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x00, 0x00
+.data1 	0x52, 0x41, 0x49, 0x44, 0x20, 0x63, 0x6f, 0x6e
+.data1 	0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00
+.data1 	0x49, 0x50, 0x49, 0x20, 0x63, 0x6f, 0x6e, 0x74
+.data1 	0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x00
+.data1 	0x46, 0x6c, 0x6f, 0x70, 0x70, 0x79, 0x20, 0x64
+.data1 	0x69, 0x73, 0x6b, 0x20, 0x63, 0x6f, 0x6e, 0x74
+.data1 	0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x00
+.data1 	0x49, 0x44, 0x45, 0x20, 0x63, 0x6f, 0x6e, 0x74
+.data1 	0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x00
+.data1 	0x53, 0x43, 0x53, 0x49, 0x20, 0x62, 0x75, 0x73
+.data1 	0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c
+.data1 	0x6c, 0x65, 0x72, 0x00, 0x56, 0x47, 0x41, 0x2d
+.data1 	0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62
+.data1 	0x6c, 0x65, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63
+.data1 	0x65, 0x00, 0x00, 0x00, 0x50, 0x61, 0x6e, 0x69
+.data1 	0x63, 0x20, 0x69, 0x6e, 0x20, 0x25, 0x73, 0x3a
+.data1 	0x20, 0x25, 0x73, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x50, 0x61, 0x6e, 0x69, 0x63, 0x20, 0x69, 0x6e
+.data1 	0x20, 0x25, 0x73, 0x3a, 0x20, 0x25, 0x73, 0x3a
+.data1 	0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x53, 0x59, 0x53, 0x5f, 0x47, 0x45, 0x54, 0x49
+.data1 	0x4e, 0x46, 0x4f, 0x3a, 0x20, 0x25, 0x64, 0x20
+.data1 	0x28, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x25, 0x75
+.data1 	0x29, 0x0a, 0x00, 0x00, 0x03, 0x47, 0x00, 0x00
+.data1 	0x05, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00
+.data1 	0x43, 0x46, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00
+.data1 	0x73, 0x46, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00
+.data1 	0x4f, 0x46, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00
+.data1 	0x5b, 0x46, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
+.data1 	0x67, 0x46, 0x00, 0x00, 0x6f, 0x6e, 0x00, 0x00
+.data1 	0x6f, 0x66, 0x66, 0x00, 0x57, 0x41, 0x52, 0x4e
+.data1 	0x49, 0x4e, 0x47, 0x3a, 0x20, 0x67, 0x65, 0x74
+.data1 	0x5f, 0x6d, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x72
+.data1 	0x61, 0x6d, 0x28, 0x29, 0x20, 0x66, 0x61, 0x69
+.data1 	0x6c, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x65
+.data1 	0x6e, 0x76, 0x5f, 0x70, 0x61, 0x72, 0x73, 0x65
+.data1 	0x28, 0x29, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00
+.data1 	0x12, 0x4a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00
+.data1 	0x25, 0x00, 0x00, 0x00, 0x40, 0x49, 0x00, 0x00
+.data1 	0x58, 0x00, 0x00, 0x00, 0xc9, 0x48, 0x00, 0x00
+.data1 	0x63, 0x00, 0x00, 0x00, 0x24, 0x49, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0x95, 0x48, 0x00, 0x00
+.data1 	0x6f, 0x00, 0x00, 0x00, 0xc0, 0x48, 0x00, 0x00
+.data1 	0x70, 0x00, 0x00, 0x00, 0xc9, 0x48, 0x00, 0x00
+.data1 	0x73, 0x00, 0x00, 0x00, 0x52, 0x49, 0x00, 0x00
+.data1 	0x75, 0x00, 0x00, 0x00, 0xd7, 0x48, 0x00, 0x00
+.data1 	0x78, 0x00, 0x00, 0x00, 0xd0, 0x48, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x65, 0x6e, 0x76, 0x69
+.data1 	0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20
+.data1 	0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x3a
+.data1 	0x20, 0x27, 0x25, 0x73, 0x20, 0x3d, 0x20, 0x25
+.data1 	0x73, 0x27, 0x0a, 0x00, 0x57, 0x41, 0x52, 0x4e
+.data1 	0x49, 0x4e, 0x47, 0x3a, 0x20, 0x67, 0x65, 0x74
+.data1 	0x5f, 0x6d, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x72
+.data1 	0x61, 0x6d, 0x28, 0x29, 0x20, 0x66, 0x61, 0x69
+.data1 	0x6c, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x65
+.data1 	0x6e, 0x76, 0x5f, 0x70, 0x61, 0x6e, 0x69, 0x63
+.data1 	0x28, 0x29, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00
+.data1 	0xac, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x64, 0x64, 0x64, 0x2e, 0x64, 0x64, 0x64, 0x2e
+.data1 	0x64, 0x64, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x00, 0x10, 0x00, 0x00, 0xe8, 0x15, 0x00, 0x00
+.data1 	0x02, 0x10, 0x00, 0x00, 0xd4, 0x15, 0x00, 0x00
+.data1 	0x0b, 0x10, 0x00, 0x00, 0xb0, 0x15, 0x00, 0x00
+.data1 	0x13, 0x10, 0x00, 0x00, 0xa0, 0x15, 0x00, 0x00
+.data1 	0x22, 0x10, 0x00, 0x00, 0x88, 0x15, 0x00, 0x00
+.data1 	0x2b, 0x10, 0x00, 0x00, 0x70, 0x15, 0x00, 0x00
+.data1 	0x39, 0x10, 0x00, 0x00, 0x4c, 0x15, 0x00, 0x00
+.data1 	0x4c, 0x10, 0x00, 0x00, 0x38, 0x15, 0x00, 0x00
+.data1 	0x5a, 0x10, 0x00, 0x00, 0x24, 0x15, 0x00, 0x00
+.data1 	0xb7, 0x10, 0x00, 0x00, 0x10, 0x15, 0x00, 0x00
+.data1 	0xb9, 0x10, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00
+.data1 	0xc8, 0x10, 0x00, 0x00, 0xe8, 0x14, 0x00, 0x00
+.data1 	0xde, 0x10, 0x00, 0x00, 0xd4, 0x14, 0x00, 0x00
+.data1 	0xec, 0x10, 0x00, 0x00, 0xcc, 0x14, 0x00, 0x00
+.data1 	0x06, 0x11, 0x00, 0x00, 0xc8, 0x14, 0x00, 0x00
+.data1 	0x0a, 0x11, 0x00, 0x00, 0xb4, 0x14, 0x00, 0x00
+.data1 	0x5d, 0x12, 0x00, 0x00, 0xa4, 0x14, 0x00, 0x00
+.data1 	0x74, 0x12, 0x00, 0x00, 0x9c, 0x14, 0x00, 0x00
+.data1 	0x33, 0x53, 0x00, 0x00, 0x98, 0x14, 0x00, 0x00
+.data1 	0x86, 0x80, 0x00, 0x00, 0x90, 0x14, 0x00, 0x00
+.data1 	0x04, 0x90, 0x00, 0x00, 0x88, 0x14, 0x00, 0x00
+.data1 	0x05, 0x90, 0x00, 0x00, 0x80, 0x14, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x10, 0x01, 0x00, 0xe8, 0x1f, 0x00, 0x00
+.data1 	0x00, 0x10, 0x0f, 0x00, 0xdc, 0x1f, 0x00, 0x00
+.data1 	0x02, 0x10, 0x52, 0x47, 0xcc, 0x1f, 0x00, 0x00
+.data1 	0x0b, 0x10, 0x01, 0xd0, 0xb8, 0x1f, 0x00, 0x00
+.data1 	0x13, 0x10, 0xb8, 0x00, 0xa0, 0x1f, 0x00, 0x00
+.data1 	0x13, 0x10, 0x03, 0x60, 0x78, 0x1f, 0x00, 0x00
+.data1 	0x22, 0x10, 0x00, 0x11, 0x58, 0x1f, 0x00, 0x00
+.data1 	0x22, 0x10, 0x01, 0x11, 0x34, 0x1f, 0x00, 0x00
+.data1 	0x22, 0x10, 0x02, 0x11, 0x0c, 0x1f, 0x00, 0x00
+.data1 	0x22, 0x10, 0x03, 0x11, 0xe8, 0x1e, 0x00, 0x00
+.data1 	0x22, 0x10, 0x00, 0x20, 0xd8, 0x1e, 0x00, 0x00
+.data1 	0x22, 0x10, 0x0c, 0x70, 0xb0, 0x1e, 0x00, 0x00
+.data1 	0x22, 0x10, 0x0d, 0x70, 0x8c, 0x1e, 0x00, 0x00
+.data1 	0x22, 0x10, 0x10, 0x74, 0x6c, 0x1e, 0x00, 0x00
+.data1 	0x22, 0x10, 0x11, 0x74, 0x54, 0x1e, 0x00, 0x00
+.data1 	0x2b, 0x10, 0x1b, 0x05, 0x30, 0x1e, 0x00, 0x00
+.data1 	0x2b, 0x10, 0x25, 0x05, 0x1c, 0x1e, 0x00, 0x00
+.data1 	0x39, 0x10, 0x08, 0x00, 0x0c, 0x1e, 0x00, 0x00
+.data1 	0x39, 0x10, 0x00, 0x02, 0xf8, 0x1d, 0x00, 0x00
+.data1 	0x39, 0x10, 0x06, 0x04, 0xe8, 0x1d, 0x00, 0x00
+.data1 	0x39, 0x10, 0x97, 0x55, 0xdc, 0x1d, 0x00, 0x00
+.data1 	0x4c, 0x10, 0x1c, 0xac, 0xd0, 0x1d, 0x00, 0x00
+.data1 	0x5a, 0x10, 0x30, 0x0d, 0xb4, 0x1d, 0x00, 0x00
+.data1 	0xb7, 0x10, 0x58, 0x90, 0xa0, 0x1d, 0x00, 0x00
+.data1 	0xb7, 0x10, 0x05, 0x98, 0x88, 0x1d, 0x00, 0x00
+.data1 	0xb9, 0x10, 0x33, 0x15, 0x64, 0x1d, 0x00, 0x00
+.data1 	0xb9, 0x10, 0x41, 0x15, 0x58, 0x1d, 0x00, 0x00
+.data1 	0xb9, 0x10, 0x29, 0x52, 0x48, 0x1d, 0x00, 0x00
+.data1 	0xb9, 0x10, 0x43, 0x52, 0x3c, 0x1d, 0x00, 0x00
+.data1 	0xb9, 0x10, 0x01, 0x71, 0x2c, 0x1d, 0x00, 0x00
+.data1 	0xc8, 0x10, 0x05, 0x00, 0x08, 0x1d, 0x00, 0x00
+.data1 	0xc8, 0x10, 0x05, 0x80, 0xe0, 0x1c, 0x00, 0x00
+.data1 	0xde, 0x10, 0x20, 0x00, 0xc8, 0x1c, 0x00, 0x00
+.data1 	0xde, 0x10, 0x10, 0x01, 0xac, 0x1c, 0x00, 0x00
+.data1 	0xec, 0x10, 0x29, 0x80, 0x9c, 0x1c, 0x00, 0x00
+.data1 	0xec, 0x10, 0x39, 0x81, 0x8c, 0x1c, 0x00, 0x00
+.data1 	0x06, 0x11, 0x05, 0x03, 0x6c, 0x1c, 0x00, 0x00
+.data1 	0x06, 0x11, 0x71, 0x05, 0x58, 0x1c, 0x00, 0x00
+.data1 	0x06, 0x11, 0x86, 0x06, 0x34, 0x1c, 0x00, 0x00
+.data1 	0x06, 0x11, 0x04, 0x12, 0x20, 0x1c, 0x00, 0x00
+.data1 	0x06, 0x11, 0x04, 0x22, 0x0c, 0x1c, 0x00, 0x00
+.data1 	0x06, 0x11, 0x38, 0x30, 0xf0, 0x1b, 0x00, 0x00
+.data1 	0x06, 0x11, 0x57, 0x30, 0xc4, 0x1b, 0x00, 0x00
+.data1 	0x06, 0x11, 0x58, 0x30, 0xa8, 0x1b, 0x00, 0x00
+.data1 	0x06, 0x11, 0x59, 0x30, 0x8c, 0x1b, 0x00, 0x00
+.data1 	0x06, 0x11, 0x65, 0x30, 0x78, 0x1b, 0x00, 0x00
+.data1 	0x06, 0x11, 0x74, 0x30, 0x6c, 0x1b, 0x00, 0x00
+.data1 	0x06, 0x11, 0x99, 0x30, 0x58, 0x1b, 0x00, 0x00
+.data1 	0x06, 0x11, 0x04, 0x31, 0x4c, 0x1b, 0x00, 0x00
+.data1 	0x06, 0x11, 0x08, 0x31, 0x28, 0x1b, 0x00, 0x00
+.data1 	0x06, 0x11, 0x49, 0x31, 0x08, 0x1b, 0x00, 0x00
+.data1 	0x06, 0x11, 0x04, 0x32, 0xf4, 0x1a, 0x00, 0x00
+.data1 	0x06, 0x11, 0x27, 0x32, 0xe0, 0x1a, 0x00, 0x00
+.data1 	0x06, 0x11, 0x04, 0x42, 0xcc, 0x1a, 0x00, 0x00
+.data1 	0x06, 0x11, 0x05, 0x83, 0xb4, 0x1a, 0x00, 0x00
+.data1 	0x06, 0x11, 0x99, 0xb0, 0x9c, 0x1a, 0x00, 0x00
+.data1 	0x06, 0x11, 0x88, 0xb1, 0x88, 0x1a, 0x00, 0x00
+.data1 	0x0a, 0x11, 0x05, 0x00, 0x58, 0x1a, 0x00, 0x00
+.data1 	0x86, 0x11, 0x00, 0x13, 0x48, 0x1a, 0x00, 0x00
+.data1 	0x5d, 0x12, 0x69, 0x19, 0x28, 0x1a, 0x00, 0x00
+.data1 	0x74, 0x12, 0x71, 0x13, 0x08, 0x1a, 0x00, 0x00
+.data1 	0x74, 0x12, 0x00, 0x50, 0xf8, 0x19, 0x00, 0x00
+.data1 	0x74, 0x12, 0x80, 0x58, 0xdc, 0x19, 0x00, 0x00
+.data1 	0x33, 0x53, 0x11, 0x88, 0xbc, 0x19, 0x00, 0x00
+.data1 	0x33, 0x53, 0x3d, 0x88, 0xb0, 0x19, 0x00, 0x00
+.data1 	0x33, 0x53, 0xd0, 0x88, 0x98, 0x19, 0x00, 0x00
+.data1 	0x33, 0x53, 0x01, 0x8a, 0x84, 0x19, 0x00, 0x00
+.data1 	0x86, 0x80, 0x04, 0x10, 0x58, 0x19, 0x00, 0x00
+.data1 	0x86, 0x80, 0x29, 0x10, 0x38, 0x19, 0x00, 0x00
+.data1 	0x86, 0x80, 0x30, 0x10, 0x0c, 0x19, 0x00, 0x00
+.data1 	0x86, 0x80, 0x09, 0x12, 0xe8, 0x18, 0x00, 0x00
+.data1 	0x86, 0x80, 0x29, 0x12, 0xc4, 0x18, 0x00, 0x00
+.data1 	0x86, 0x80, 0x2d, 0x12, 0xb4, 0x18, 0x00, 0x00
+.data1 	0x86, 0x80, 0x2e, 0x12, 0x9c, 0x18, 0x00, 0x00
+.data1 	0x86, 0x80, 0x30, 0x12, 0x88, 0x18, 0x00, 0x00
+.data1 	0x86, 0x80, 0x37, 0x12, 0x70, 0x18, 0x00, 0x00
+.data1 	0x86, 0x80, 0x50, 0x12, 0x60, 0x18, 0x00, 0x00
+.data1 	0x86, 0x80, 0x30, 0x1a, 0x4c, 0x18, 0x00, 0x00
+.data1 	0x86, 0x80, 0x31, 0x1a, 0x24, 0x18, 0x00, 0x00
+.data1 	0x86, 0x80, 0x40, 0x24, 0x04, 0x18, 0x00, 0x00
+.data1 	0x86, 0x80, 0x49, 0x24, 0xe0, 0x17, 0x00, 0x00
+.data1 	0x86, 0x80, 0x4e, 0x24, 0xc8, 0x17, 0x00, 0x00
+.data1 	0x86, 0x80, 0x60, 0x25, 0xa4, 0x17, 0x00, 0x00
+.data1 	0x86, 0x80, 0x61, 0x25, 0x78, 0x17, 0x00, 0x00
+.data1 	0x86, 0x80, 0x00, 0x70, 0x68, 0x17, 0x00, 0x00
+.data1 	0x86, 0x80, 0x10, 0x70, 0x54, 0x17, 0x00, 0x00
+.data1 	0x86, 0x80, 0x20, 0x70, 0x40, 0x17, 0x00, 0x00
+.data1 	0x86, 0x80, 0x30, 0x70, 0x30, 0x17, 0x00, 0x00
+.data1 	0x86, 0x80, 0x00, 0x71, 0x20, 0x17, 0x00, 0x00
+.data1 	0x86, 0x80, 0x00, 0x71, 0x10, 0x17, 0x00, 0x00
+.data1 	0x86, 0x80, 0x10, 0x71, 0xf8, 0x16, 0x00, 0x00
+.data1 	0x86, 0x80, 0x11, 0x71, 0xe4, 0x16, 0x00, 0x00
+.data1 	0x86, 0x80, 0x12, 0x71, 0xd0, 0x16, 0x00, 0x00
+.data1 	0x86, 0x80, 0x13, 0x71, 0xb8, 0x16, 0x00, 0x00
+.data1 	0x86, 0x80, 0x24, 0x71, 0xa8, 0x16, 0x00, 0x00
+.data1 	0x86, 0x80, 0x90, 0x71, 0x98, 0x16, 0x00, 0x00
+.data1 	0x86, 0x80, 0x91, 0x71, 0x7c, 0x16, 0x00, 0x00
+.data1 	0x86, 0x80, 0x92, 0x71, 0x58, 0x16, 0x00, 0x00
+.data1 	0x04, 0x90, 0x78, 0x81, 0x20, 0x16, 0x00, 0x00
+.data1 	0x05, 0x90, 0x80, 0x00, 0xec, 0x15, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x7c, 0x21, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x64, 0x21, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x50, 0x21, 0x00, 0x00
+.data1 	0x03, 0x00, 0x00, 0x00, 0x3c, 0x21, 0x00, 0x00
+.data1 	0x04, 0x00, 0x00, 0x00, 0x28, 0x21, 0x00, 0x00
+.data1 	0x05, 0x00, 0x00, 0x00, 0x14, 0x21, 0x00, 0x00
+.data1 	0x06, 0x00, 0x00, 0x00, 0x04, 0x21, 0x00, 0x00
+.data1 	0x07, 0x00, 0x00, 0x00, 0xec, 0x20, 0x00, 0x00
+.data1 	0x08, 0x00, 0x00, 0x00, 0xd4, 0x20, 0x00, 0x00
+.data1 	0x09, 0x00, 0x00, 0x00, 0xc4, 0x20, 0x00, 0x00
+.data1 	0x0a, 0x00, 0x00, 0x00, 0xb4, 0x20, 0x00, 0x00
+.data1 	0x0b, 0x00, 0x00, 0x00, 0xa8, 0x20, 0x00, 0x00
+.data1 	0x0c, 0x00, 0x00, 0x00, 0x90, 0x20, 0x00, 0x00
+.data1 	0x0d, 0x00, 0x00, 0x00, 0x7c, 0x20, 0x00, 0x00
+.data1 	0x0e, 0x00, 0x00, 0x00, 0x60, 0x20, 0x00, 0x00
+.data1 	0x0f, 0x00, 0x00, 0x00, 0x44, 0x20, 0x00, 0x00
+.data1 	0x10, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00
+.data1 	0x11, 0x00, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00
+.data1 	0xff, 0x00, 0x00, 0x00, 0xf4, 0x1f, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x01, 0x00, 0x00, 0xc4, 0x24, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0xb0, 0x24, 0x00, 0x00
+.data1 	0x01, 0x01, 0xff, 0xff, 0xa0, 0x24, 0x00, 0x00
+.data1 	0x01, 0x02, 0x00, 0x00, 0x88, 0x24, 0x00, 0x00
+.data1 	0x01, 0x03, 0x00, 0x00, 0x78, 0x24, 0x00, 0x00
+.data1 	0x01, 0x04, 0x00, 0x00, 0x68, 0x24, 0x00, 0x00
+.data1 	0x01, 0x80, 0x00, 0x00, 0x48, 0x24, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x34, 0x24, 0x00, 0x00
+.data1 	0x02, 0x01, 0x00, 0x00, 0x1c, 0x24, 0x00, 0x00
+.data1 	0x02, 0x02, 0x00, 0x00, 0x0c, 0x24, 0x00, 0x00
+.data1 	0x02, 0x03, 0x00, 0x00, 0xfc, 0x23, 0x00, 0x00
+.data1 	0x02, 0x04, 0x00, 0x00, 0xec, 0x23, 0x00, 0x00
+.data1 	0x02, 0x80, 0x00, 0x00, 0xd0, 0x23, 0x00, 0x00
+.data1 	0x03, 0x00, 0x00, 0x00, 0xb4, 0x23, 0x00, 0x00
+.data1 	0x03, 0x00, 0x01, 0x00, 0x98, 0x23, 0x00, 0x00
+.data1 	0x03, 0x01, 0x00, 0x00, 0x88, 0x23, 0x00, 0x00
+.data1 	0x03, 0x02, 0x00, 0x00, 0x78, 0x23, 0x00, 0x00
+.data1 	0x03, 0x80, 0x00, 0x00, 0x5c, 0x23, 0x00, 0x00
+.data1 	0x04, 0x00, 0x00, 0x00, 0x4c, 0x23, 0x00, 0x00
+.data1 	0x04, 0x01, 0x00, 0x00, 0x3c, 0x23, 0x00, 0x00
+.data1 	0x04, 0x02, 0x00, 0x00, 0x20, 0x23, 0x00, 0x00
+.data1 	0x04, 0x80, 0x00, 0x00, 0x08, 0x23, 0x00, 0x00
+.data1 	0x06, 0x00, 0x00, 0x00, 0xfc, 0x22, 0x00, 0x00
+.data1 	0x06, 0x01, 0x00, 0x00, 0xf0, 0x22, 0x00, 0x00
+.data1 	0x06, 0x02, 0x00, 0x00, 0xe4, 0x22, 0x00, 0x00
+.data1 	0x06, 0x03, 0x00, 0x00, 0xd8, 0x22, 0x00, 0x00
+.data1 	0x06, 0x04, 0x00, 0x00, 0xc4, 0x22, 0x00, 0x00
+.data1 	0x06, 0x04, 0x01, 0x00, 0x9c, 0x22, 0x00, 0x00
+.data1 	0x06, 0x05, 0x00, 0x00, 0x8c, 0x22, 0x00, 0x00
+.data1 	0x06, 0x06, 0x00, 0x00, 0x7c, 0x22, 0x00, 0x00
+.data1 	0x06, 0x07, 0x00, 0x00, 0x6c, 0x22, 0x00, 0x00
+.data1 	0x06, 0x08, 0xff, 0xff, 0x5c, 0x22, 0x00, 0x00
+.data1 	0x06, 0x09, 0xff, 0xff, 0x38, 0x22, 0x00, 0x00
+.data1 	0x06, 0x80, 0x00, 0x00, 0x24, 0x22, 0x00, 0x00
+.data1 	0x0c, 0x00, 0x00, 0x00, 0x0c, 0x22, 0x00, 0x00
+.data1 	0x0c, 0x00, 0x10, 0x00, 0xf8, 0x21, 0x00, 0x00
+.data1 	0x0c, 0x01, 0x00, 0x00, 0xec, 0x21, 0x00, 0x00
+.data1 	0x0c, 0x02, 0x00, 0x00, 0xe8, 0x21, 0x00, 0x00
+.data1 	0x0c, 0x03, 0x00, 0x00, 0xd8, 0x21, 0x00, 0x00
+.data1 	0x0c, 0x03, 0x10, 0x00, 0xc8, 0x21, 0x00, 0x00
+.data1 	0x0c, 0x03, 0x80, 0x00, 0xb0, 0x21, 0x00, 0x00
+.data1 	0x0c, 0x03, 0xfe, 0x00, 0xa4, 0x21, 0x00, 0x00
+.data1 	0x0c, 0x04, 0x00, 0x00, 0x94, 0x21, 0x00, 0x00
+.data1 	0x0c, 0x05, 0x00, 0x00, 0x8c, 0x21, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x22, 0x10, 0x10, 0x74, 0x01, 0x00, 0x00, 0x00
+.data1 	0x03, 0x00, 0x00, 0x00, 0x39, 0x10, 0x08, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+.data1 	0xb9, 0x10, 0x33, 0x15, 0x01, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x06, 0x11, 0x86, 0x06
+.data1 	0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x06, 0x11, 0x74, 0x30, 0x01, 0x00, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x06, 0x11, 0x27, 0x32
+.data1 	0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x86, 0x80, 0x2e, 0x12, 0x01, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x86, 0x80, 0x40, 0x24
+.data1 	0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x86, 0x80, 0x00, 0x70, 0x01, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x86, 0x80, 0x30, 0x70
+.data1 	0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x86, 0x80, 0x00, 0x71, 0x01, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x86, 0x80, 0x10, 0x71
+.data1 	0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x86, 0x80, 0x24, 0x71, 0x01, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x3a, 0x2c, 0x3b, 0x2e
+.data1 	0x00, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33
+.data1 	0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42
+.data1 	0x43, 0x44, 0x45, 0x46, 0x00, 0x00, 0x00, 0x00
+.data1 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
+.data1 	0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
+.data1 	0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
+.data1 	0x04, 0x00, 0x00, 0x00, 0xce, 0x6a, 0x00, 0x00
+.data1 	0x3c, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e
+.data1 	0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x53, 0x53, 0x53, 0x53, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x20, 0x28, 0x28, 0x28, 0x28, 0x28, 0x20
+.data1 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04
+.data1 	0x04, 0x04, 0x04, 0x10, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x10, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41
+.data1 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+.data1 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+.data1 	0x01, 0x01, 0x01, 0x01, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x10, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42
+.data1 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+.data1 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+.data1 	0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10
+.data1 	0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x03, 0x20, 0x10, 0x20, 0x00, 0x00, 0x00
+.data1 	0x00, 0xfa, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00
+.data1 	0xe4, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc4, 0xc6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0xed, 0x8b, 0x04, 0x24, 0x8d, 0x54, 0x24
+.data1 	0x04, 0x8d, 0x4c, 0x84, 0x08, 0xbb, 0xec, 0x27
+.data1 	0x00, 0x00, 0x81, 0xfb, 0xe0, 0x29, 0x00, 0x00
+.data1 	0x73, 0x13, 0xf6, 0xc3, 0x03, 0x75, 0x0e, 0x81
+.data1 	0x3b, 0x53, 0x53, 0x53, 0x53, 0x75, 0x06, 0x89
+.data1 	0x1d, 0x2c, 0x19, 0x00, 0x00, 0x8b, 0x1d, 0x2c
+.data1 	0x19, 0x00, 0x00, 0x89, 0x0b, 0x51, 0x52, 0x50
+.data1 	0x0f, 0x01, 0xe0, 0xa8, 0x04, 0x0f, 0x94, 0x05
+.data1 	0x5c, 0x2c, 0x00, 0x00, 0xe8, 0xfb, 0x53, 0x00
+.data1 	0x00, 0x50, 0xe8, 0x36, 0xd5, 0x00, 0x00, 0xf4
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x34, 0x56, 0x57
+.data1 	0xc7, 0x45, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x68
+.data1 	0x88, 0x2c, 0x00, 0x00, 0xe8, 0x40, 0x6c, 0x00
+.data1 	0x00, 0x59, 0x8b, 0x15, 0x80, 0x2c, 0x00, 0x00
+.data1 	0x8b, 0x12, 0x89, 0xd6, 0x85, 0xd2, 0x75, 0x26
+.data1 	0x6a, 0x01, 0x68, 0x24, 0x01, 0x00, 0x00, 0xe8
+.data1 	0x7c, 0x9b, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc6
+.data1 	0x85, 0xc0, 0x75, 0x0b, 0x68, 0x14, 0x01, 0x00
+.data1 	0x00, 0xe8, 0x7a, 0x05, 0x00, 0x00, 0x59, 0xc7
+.data1 	0x45, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x80, 0x3e
+.data1 	0x2f, 0x74, 0x15, 0x6a, 0x01, 0x68, 0x0c, 0x01
+.data1 	0x00, 0x00, 0xe8, 0x51, 0x9b, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0x45, 0xf8, 0x85, 0xc0, 0x75, 0x07
+.data1 	0xc7, 0x45, 0xf8, 0x88, 0x2c, 0x00, 0x00, 0x56
+.data1 	0x8d, 0x45, 0xf8, 0x50, 0xe8, 0xc9, 0x1a, 0x00
+.data1 	0x00, 0x59, 0x59, 0x89, 0xc7, 0x85, 0xc0, 0x74
+.data1 	0x40, 0x8d, 0x45, 0xd0, 0x50, 0x57, 0xe8, 0xdd
+.data1 	0xea, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x78
+.data1 	0xde, 0x0f, 0xb7, 0x55, 0xd8, 0x81, 0xe2, 0x00
+.data1 	0xf0, 0x00, 0x00, 0x81, 0xfa, 0x00, 0x40, 0x00
+.data1 	0x00, 0x75, 0xcc, 0xff, 0x75, 0xcc, 0x56, 0x57
+.data1 	0xe8, 0xc3, 0xeb, 0x00, 0x00, 0x59, 0x59, 0x50
+.data1 	0x57, 0xe8, 0x1c, 0x00, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x85, 0xc0, 0x78, 0xb2, 0x6a, 0x00, 0xeb
+.data1 	0x0c, 0x56, 0x68, 0xfc, 0x00, 0x00, 0x00, 0xe8
+.data1 	0xf4, 0x04, 0x00, 0x00, 0x59, 0x58, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0x3d, 0x70
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x74, 0x07, 0xc7, 0x45
+.data1 	0x0c, 0x01, 0x00, 0x00, 0x00, 0xff, 0x05, 0x90
+.data1 	0x2c, 0x00, 0x00, 0xff, 0x75, 0x08, 0xe8, 0xc9
+.data1 	0xe9, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x79, 0x26
+.data1 	0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89
+.data1 	0x15, 0x90, 0x2c, 0x00, 0x00, 0x75, 0x10, 0xff
+.data1 	0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2
+.data1 	0x74, 0x05, 0xe8, 0x48, 0x04, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x4b, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x91, 0x00, 0x00, 0x00, 0x59, 0x8b
+.data1 	0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x75, 0x10, 0xff, 0x35
+.data1 	0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74
+.data1 	0x05, 0xe8, 0x19, 0x04, 0x00, 0x00, 0x83, 0x7d
+.data1 	0x0c, 0x00, 0x74, 0x1b, 0x80, 0x3d, 0x77, 0x2c
+.data1 	0x00, 0x00, 0x00, 0x74, 0x12, 0xff, 0x35, 0xa8
+.data1 	0x1c, 0x00, 0x00, 0x68, 0x2c, 0x01, 0x00, 0x00
+.data1 	0xe8, 0xb1, 0x91, 0x00, 0x00, 0x59, 0x59, 0x31
+.data1 	0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x08, 0x56, 0x8b, 0x35, 0x6c, 0x2c, 0x00, 0x00
+.data1 	0x85, 0xf6, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x34
+.data1 	0x8b, 0x15, 0x6c, 0x2c, 0x00, 0x00, 0x89, 0x55
+.data1 	0xf8, 0x80, 0x3e, 0x2f, 0x74, 0x08, 0x80, 0x3e
+.data1 	0x00, 0x74, 0x03, 0x46, 0xeb, 0xf3, 0x80, 0x3e
+.data1 	0x00, 0x75, 0x0c, 0xc7, 0x05, 0x6c, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x0a, 0xc6
+.data1 	0x06, 0x00, 0x46, 0x89, 0x35, 0x6c, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x45, 0xf8, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0x57, 0xe8, 0xeb, 0x1f, 0x00
+.data1 	0x00, 0xff, 0x75, 0x08, 0xe8, 0xd7, 0xea, 0x00
+.data1 	0x00, 0x59, 0x40, 0x50, 0xe8, 0xb1, 0x58, 0x00
+.data1 	0x00, 0x59, 0xa3, 0x6c, 0x2c, 0x00, 0x00, 0xff
+.data1 	0x75, 0x08, 0xff, 0x35, 0x6c, 0x2c, 0x00, 0x00
+.data1 	0xe8, 0x9b, 0xea, 0x00, 0x00, 0x59, 0x59, 0x8b
+.data1 	0x35, 0xa8, 0x1c, 0x00, 0x00, 0x8b, 0x15, 0xac
+.data1 	0x1c, 0x00, 0x00, 0x89, 0x15, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x08, 0x80, 0x3a, 0x2f, 0x74
+.data1 	0x4b, 0x83, 0x3d, 0x68, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x84, 0x3b, 0x01, 0x00, 0x00, 0x8b, 0x3d
+.data1 	0x68, 0x2c, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x74
+.data1 	0x26, 0x8b, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x78, 0x08
+.data1 	0x8a, 0x07, 0x47, 0x88, 0x06, 0x46, 0xeb, 0xe4
+.data1 	0xe8, 0xd0, 0x5a, 0x00, 0x00, 0x89, 0xc6, 0x8a
+.data1 	0x07, 0x47, 0x88, 0x06, 0x46, 0xeb, 0xd5, 0x80
+.data1 	0x7f, 0xff, 0x2f, 0x75, 0x07, 0xff, 0x05, 0x84
+.data1 	0x2c, 0x00, 0x00, 0x4e, 0xe8, 0x1a, 0xff, 0xff
+.data1 	0xff, 0x89, 0xc7, 0x85, 0xc0, 0x0f, 0x84, 0x88
+.data1 	0x00, 0x00, 0x00, 0x68, 0x34, 0x01, 0x00, 0x00
+.data1 	0x57, 0xe8, 0x0a, 0xea, 0x00, 0x00, 0x59, 0x59
+.data1 	0x85, 0xc0, 0x75, 0x16, 0x39, 0x35, 0xa8, 0x1c
+.data1 	0x00, 0x00, 0x73, 0xd8, 0xff, 0x05, 0x84, 0x2c
+.data1 	0x00, 0x00, 0x4e, 0x80, 0x3e, 0x2f, 0x74, 0xcc
+.data1 	0xeb, 0xea, 0x80, 0x3f, 0x00, 0x74, 0xc5, 0x68
+.data1 	0x30, 0x01, 0x00, 0x00, 0x57, 0xe8, 0xde, 0xe9
+.data1 	0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x74, 0xb4
+.data1 	0x8b, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x4a, 0x89
+.data1 	0x15, 0x84, 0x2c, 0x00, 0x00, 0x78, 0x06, 0xc6
+.data1 	0x06, 0x2f, 0x46, 0xeb, 0x0b, 0xe8, 0x53, 0x5a
+.data1 	0x00, 0x00, 0x89, 0xc6, 0xc6, 0x06, 0x2f, 0x46
+.data1 	0x80, 0x3f, 0x00, 0x74, 0x8f, 0x8b, 0x15, 0x84
+.data1 	0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x84, 0x2c
+.data1 	0x00, 0x00, 0x78, 0x08, 0x8a, 0x07, 0x47, 0x88
+.data1 	0x06, 0x46, 0xeb, 0xe4, 0xe8, 0x2c, 0x5a, 0x00
+.data1 	0x00, 0x89, 0xc6, 0x8a, 0x07, 0x47, 0x88, 0x06
+.data1 	0x46, 0xeb, 0xd5, 0x39, 0x35, 0xa8, 0x1c, 0x00
+.data1 	0x00, 0x75, 0x20, 0x8b, 0x15, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0x84, 0x2c, 0x00, 0x00
+.data1 	0x78, 0x06, 0xc6, 0x06, 0x2f, 0x46, 0xeb, 0x0b
+.data1 	0xe8, 0x00, 0x5a, 0x00, 0x00, 0x89, 0xc6, 0xc6
+.data1 	0x06, 0x2f, 0x46, 0x83, 0x3d, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x75, 0x0c, 0xe8, 0xec, 0x59, 0x00
+.data1 	0x00, 0x89, 0xc6, 0xc6, 0x06, 0x00, 0xeb, 0x03
+.data1 	0xc6, 0x06, 0x00, 0x83, 0x3d, 0x68, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x74, 0x0c, 0xff, 0x35, 0x68, 0x2c
+.data1 	0x00, 0x00, 0xe8, 0x0f, 0xd5, 0x00, 0x00, 0x59
+.data1 	0xff, 0x35, 0xa8, 0x1c, 0x00, 0x00, 0xe8, 0x18
+.data1 	0x57, 0x00, 0x00, 0x59, 0xa3, 0x68, 0x2c, 0x00
+.data1 	0x00, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0xe8, 0x4a, 0x00, 0x00, 0x00, 0xff, 0x35, 0x68
+.data1 	0x2c, 0x00, 0x00, 0xe8, 0x8c, 0x8d, 0x00, 0x00
+.data1 	0x59, 0xa1, 0xa4, 0x23, 0x00, 0x00, 0xff, 0x48
+.data1 	0x04, 0x8b, 0x15, 0xa4, 0x23, 0x00, 0x00, 0x83
+.data1 	0x7a, 0x04, 0x00, 0x79, 0x1a, 0xff, 0x35, 0xa4
+.data1 	0x23, 0x00, 0x00, 0xe8, 0xcc, 0x8d, 0x00, 0x00
+.data1 	0x59, 0xa1, 0xa4, 0x23, 0x00, 0x00, 0x8b, 0x18
+.data1 	0xff, 0x00, 0xc6, 0x03, 0x0a, 0xeb, 0x0c, 0xa1
+.data1 	0xa4, 0x23, 0x00, 0x00, 0x8b, 0x18, 0xff, 0x00
+.data1 	0xc6, 0x03, 0x0a, 0x31, 0xc0, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x81, 0xec, 0x18, 0x01, 0x00, 0x00
+.data1 	0x56, 0x57, 0x83, 0x3d, 0x68, 0x2c, 0x00, 0x00
+.data1 	0x00, 0x0f, 0x85, 0x79, 0x01, 0x00, 0x00, 0xff
+.data1 	0x05, 0x90, 0x2c, 0x00, 0x00, 0x8d, 0x85, 0xe8
+.data1 	0xfe, 0xff, 0xff, 0x50, 0xe8, 0x87, 0xe7, 0x00
+.data1 	0x00, 0x59, 0x85, 0xc0, 0x79, 0x0b, 0x68, 0x74
+.data1 	0x01, 0x00, 0x00, 0xe8, 0xe8, 0x01, 0x00, 0x00
+.data1 	0x59, 0x6a, 0x01, 0x6a, 0x00, 0xe8, 0x29, 0x44
+.data1 	0x00, 0x00, 0x59, 0x59, 0x89, 0x85, 0xf0, 0xfe
+.data1 	0xff, 0xff, 0x6a, 0x02, 0x6a, 0x00, 0xff, 0xb5
+.data1 	0xf0, 0xfe, 0xff, 0xff, 0xe8, 0x7e, 0x45, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x75, 0x57
+.data1 	0xff, 0xb5, 0xe8, 0xfe, 0xff, 0xff, 0xe8, 0xbd
+.data1 	0xe6, 0x00, 0x00, 0x59, 0x83, 0xbd, 0xec, 0xfe
+.data1 	0xff, 0xff, 0x01, 0x74, 0x23, 0x6a, 0x01, 0xe8
+.data1 	0xac, 0xe6, 0x00, 0x00, 0x59, 0x6a, 0x01, 0xff
+.data1 	0xb5, 0xec, 0xfe, 0xff, 0xff, 0xe8, 0x5f, 0x88
+.data1 	0x00, 0x00, 0x59, 0x59, 0xff, 0xb5, 0xec, 0xfe
+.data1 	0xff, 0xff, 0xe8, 0x91, 0xe6, 0x00, 0x00, 0x59
+.data1 	0x6a, 0x00, 0x68, 0x64, 0x01, 0x00, 0x00, 0x68
+.data1 	0x68, 0x01, 0x00, 0x00, 0xe8, 0x8f, 0xe6, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x68, 0x4c, 0x01, 0x00
+.data1 	0x00, 0xe8, 0x6a, 0x01, 0x00, 0x00, 0x59, 0xff
+.data1 	0xb5, 0xec, 0xfe, 0xff, 0xff, 0xe8, 0x66, 0xe6
+.data1 	0x00, 0x00, 0x59, 0xc7, 0x85, 0xec, 0xfe, 0xff
+.data1 	0xff, 0xff, 0xff, 0xff, 0xff, 0x8d, 0xb5, 0x00
+.data1 	0xff, 0xff, 0xff, 0x8d, 0x55, 0x00, 0x29, 0xf2
+.data1 	0x52, 0x56, 0xff, 0xb5, 0xe8, 0xfe, 0xff, 0xff
+.data1 	0xe8, 0xd3, 0xe6, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0xc7, 0x85, 0xc0, 0x7f, 0x0e, 0x83, 0xff
+.data1 	0xff, 0x75, 0x15, 0x83, 0x3d, 0xf0, 0x27, 0x00
+.data1 	0x00, 0x04, 0x75, 0x0c, 0x85, 0xff, 0x7e, 0xd3
+.data1 	0x89, 0xf2, 0x89, 0xfe, 0x01, 0xd6, 0xeb, 0xcb
+.data1 	0xff, 0xb5, 0xe8, 0xfe, 0xff, 0xff, 0xe8, 0x15
+.data1 	0xe6, 0x00, 0x00, 0x59, 0xc7, 0x85, 0xe8, 0xfe
+.data1 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb5
+.data1 	0xf0, 0xfe, 0xff, 0xff, 0xe8, 0x93, 0x46, 0x00
+.data1 	0x00, 0x59, 0x89, 0x85, 0xf4, 0xfe, 0xff, 0xff
+.data1 	0x85, 0xc0, 0x74, 0x08, 0x6a, 0x00, 0xe8, 0xe5
+.data1 	0x00, 0x00, 0x00, 0x59, 0x85, 0xff, 0x78, 0x10
+.data1 	0x8d, 0x95, 0x00, 0xff, 0xff, 0xff, 0x39, 0xd6
+.data1 	0x74, 0x06, 0x80, 0x7e, 0xff, 0x0a, 0x74, 0x0b
+.data1 	0x68, 0x38, 0x01, 0x00, 0x00, 0xe8, 0xc6, 0x00
+.data1 	0x00, 0x00, 0x59, 0xc6, 0x46, 0xff, 0x00, 0x8d
+.data1 	0x85, 0x00, 0xff, 0xff, 0xff, 0x50, 0xe8, 0x50
+.data1 	0x55, 0x00, 0x00, 0x59, 0xa3, 0x68, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x75, 0x10
+.data1 	0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85
+.data1 	0xd2, 0x74, 0x05, 0xe8, 0x2f, 0x00, 0x00, 0x00
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0x3d, 0x94, 0x2c, 0x00, 0x00, 0x00, 0x75, 0x05
+.data1 	0xe8, 0x33, 0xcf, 0x00, 0x00, 0x8b, 0x55, 0x08
+.data1 	0x89, 0x15, 0x98, 0x2c, 0x00, 0x00, 0x6a, 0x01
+.data1 	0xff, 0x35, 0x94, 0x2c, 0x00, 0x00, 0xe8, 0xe7
+.data1 	0xe7, 0x00, 0x00, 0x59, 0x59, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0xff, 0x35, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x5a, 0x85, 0xd2, 0x74, 0x08, 0xff, 0x05, 0x8c
+.data1 	0x2c, 0x00, 0x00, 0xeb, 0x31, 0xc7, 0x05, 0x8c
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83
+.data1 	0x3d, 0xa0, 0x2c, 0x00, 0x00, 0x00, 0x74, 0x13
+.data1 	0x80, 0x3d, 0x77, 0x2c, 0x00, 0x00, 0x00, 0x74
+.data1 	0x0a, 0x6a, 0x00, 0xe8, 0x9c, 0xff, 0xff, 0xff
+.data1 	0x59, 0xeb, 0x0b, 0x68, 0x82, 0x00, 0x00, 0x00
+.data1 	0xe8, 0x0f, 0xe5, 0x00, 0x00, 0x59, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0xff, 0x75, 0x0c, 0xff, 0x75
+.data1 	0x08, 0x68, 0x88, 0x01, 0x00, 0x00, 0xe8, 0x05
+.data1 	0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0xc7, 0x05
+.data1 	0x8c, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xff, 0x05, 0x90, 0x2c, 0x00, 0x00, 0x8d, 0x55
+.data1 	0x0c, 0x89, 0x55, 0xfc, 0x83, 0x7d, 0x08, 0x00
+.data1 	0x0f, 0x84, 0x6e, 0x00, 0x00, 0x00, 0x83, 0x3d
+.data1 	0x9c, 0x2c, 0x00, 0x00, 0x00, 0x74, 0x18, 0xff
+.data1 	0x35, 0x9c, 0x2c, 0x00, 0x00, 0x68, 0x90, 0x01
+.data1 	0x00, 0x00, 0x68, 0x7c, 0x23, 0x00, 0x00, 0xe8
+.data1 	0xf5, 0x8c, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xff
+.data1 	0x75, 0xfc, 0xff, 0x75, 0x08, 0x68, 0x7c, 0x23
+.data1 	0x00, 0x00, 0xe8, 0x8d, 0x8d, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xa1, 0xa8, 0x23, 0x00, 0x00, 0xff
+.data1 	0x48, 0x04, 0x8b, 0x15, 0xa8, 0x23, 0x00, 0x00
+.data1 	0x83, 0x7a, 0x04, 0x00, 0x79, 0x1a, 0xff, 0x35
+.data1 	0xa8, 0x23, 0x00, 0x00, 0xe8, 0x13, 0x8b, 0x00
+.data1 	0x00, 0x59, 0xa1, 0xa8, 0x23, 0x00, 0x00, 0x8b
+.data1 	0x18, 0xff, 0x00, 0xc6, 0x03, 0x0a, 0xeb, 0x0c
+.data1 	0xa1, 0xa8, 0x23, 0x00, 0x00, 0x8b, 0x18, 0xff
+.data1 	0x00, 0xc6, 0x03, 0x0a, 0xe8, 0xde, 0x8b, 0x00
+.data1 	0x00, 0x6a, 0x01, 0xe8, 0xd4, 0xfe, 0xff, 0xff
+.data1 	0x59, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x0c, 0x56, 0x57, 0x83, 0x7d, 0x08, 0x01
+.data1 	0x0f, 0x8e, 0xc3, 0x00, 0x00, 0x00, 0x8b, 0x55
+.data1 	0x0c, 0x8b, 0x7a, 0x04, 0x83, 0x7d, 0x08, 0x02
+.data1 	0x0f, 0x8e, 0xac, 0x00, 0x00, 0x00, 0x8b, 0x35
+.data1 	0xa8, 0x1c, 0x00, 0x00, 0x8b, 0x15, 0xac, 0x1c
+.data1 	0x00, 0x00, 0x89, 0x15, 0x84, 0x2c, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x0c, 0x83, 0xc2, 0x08, 0x89, 0x55
+.data1 	0xf4, 0x80, 0x3f, 0x00, 0x74, 0x26, 0x8b, 0x15
+.data1 	0x84, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x84
+.data1 	0x2c, 0x00, 0x00, 0x78, 0x08, 0x8a, 0x07, 0x47
+.data1 	0x88, 0x06, 0x46, 0xeb, 0xe4, 0xe8, 0x43, 0x56
+.data1 	0x00, 0x00, 0x89, 0xc6, 0x8a, 0x07, 0x47, 0x88
+.data1 	0x06, 0x46, 0xeb, 0xd5, 0x8b, 0x45, 0xf4, 0x83
+.data1 	0x45, 0xf4, 0x04, 0x8b, 0x10, 0x89, 0xd7, 0x85
+.data1 	0xd2, 0x74, 0x22, 0x8b, 0x15, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0x84, 0x2c, 0x00, 0x00
+.data1 	0x78, 0x06, 0xc6, 0x06, 0x20, 0x46, 0xeb, 0xb1
+.data1 	0xe8, 0x10, 0x56, 0x00, 0x00, 0x89, 0xc6, 0xc6
+.data1 	0x06, 0x20, 0x46, 0xeb, 0xa4, 0x8b, 0x15, 0x84
+.data1 	0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x84, 0x2c
+.data1 	0x00, 0x00, 0x78, 0x06, 0xc6, 0x06, 0x00, 0x46
+.data1 	0xeb, 0x0b, 0xe8, 0xee, 0x55, 0x00, 0x00, 0x89
+.data1 	0xc6, 0xc6, 0x06, 0x00, 0x46, 0x8b, 0x15, 0xac
+.data1 	0x1c, 0x00, 0x00, 0x2b, 0x15, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x52, 0xe8, 0x53, 0x53, 0x00, 0x00, 0x59
+.data1 	0x89, 0xc7, 0x57, 0xe8, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x59, 0xa1, 0xa4, 0x2c, 0x00, 0x00, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x10
+.data1 	0x8d, 0x45, 0xf0, 0x50, 0xe8, 0x1e, 0x54, 0x00
+.data1 	0x00, 0x59, 0x6a, 0x01, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xd8, 0x39, 0x00, 0x00, 0x59, 0x59, 0x6a, 0x00
+.data1 	0xe8, 0xbb, 0x65, 0x00, 0x00, 0x59, 0x89, 0x45
+.data1 	0xfc, 0x3d, 0xc4, 0x2c, 0x00, 0x00, 0x74, 0x18
+.data1 	0x6a, 0x00, 0xff, 0x75, 0xfc, 0xe8, 0x1f, 0x00
+.data1 	0x00, 0x00, 0x59, 0x59, 0x8d, 0x45, 0xf0, 0x50
+.data1 	0xe8, 0x12, 0x54, 0x00, 0x00, 0x59, 0xeb, 0xd6
+.data1 	0xe8, 0x5d, 0x3a, 0x00, 0x00, 0x8d, 0x45, 0xf0
+.data1 	0x50, 0xe8, 0x01, 0x54, 0x00, 0x00, 0x59, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x08, 0x8b, 0x7d, 0x0c, 0x85
+.data1 	0xf6, 0x0f, 0x85, 0xb5, 0x01, 0x00, 0x00, 0xe9
+.data1 	0x02, 0x02, 0x00, 0x00, 0x6a, 0x00, 0xff, 0x76
+.data1 	0x04, 0xe8, 0xdb, 0xff, 0xff, 0xff, 0x59, 0x59
+.data1 	0x83, 0x3d, 0xb0, 0x2c, 0x00, 0x00, 0x00, 0x0f
+.data1 	0x85, 0xa3, 0x01, 0x00, 0x00, 0x57, 0xff, 0x76
+.data1 	0x08, 0xe8, 0xc3, 0xff, 0xff, 0xff, 0x59, 0x59
+.data1 	0xe9, 0x93, 0x01, 0x00, 0x00, 0x6a, 0x02, 0xff
+.data1 	0x76, 0x04, 0xe8, 0xb2, 0xff, 0xff, 0xff, 0x59
+.data1 	0x59, 0x83, 0x3d, 0xb0, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x85, 0x7a, 0x01, 0x00, 0x00, 0x83, 0x3d
+.data1 	0xa4, 0x2c, 0x00, 0x00, 0x00, 0x0f, 0x85, 0x6d
+.data1 	0x01, 0x00, 0x00, 0x57, 0xff, 0x76, 0x08, 0xe8
+.data1 	0x8d, 0xff, 0xff, 0xff, 0x59, 0x59, 0xe9, 0x5d
+.data1 	0x01, 0x00, 0x00, 0x6a, 0x02, 0xff, 0x76, 0x04
+.data1 	0xe8, 0x7c, 0xff, 0xff, 0xff, 0x59, 0x59, 0x83
+.data1 	0x3d, 0xb0, 0x2c, 0x00, 0x00, 0x00, 0x0f, 0x85
+.data1 	0x44, 0x01, 0x00, 0x00, 0x83, 0x3d, 0xa4, 0x2c
+.data1 	0x00, 0x00, 0x00, 0x0f, 0x84, 0x37, 0x01, 0x00
+.data1 	0x00, 0x57, 0xff, 0x76, 0x08, 0xe8, 0x57, 0xff
+.data1 	0xff, 0xff, 0x59, 0x59, 0xe9, 0x27, 0x01, 0x00
+.data1 	0x00, 0xff, 0x76, 0x08, 0xe8, 0x66, 0x04, 0x00
+.data1 	0x00, 0x59, 0x6a, 0x01, 0xff, 0x76, 0x08, 0xe8
+.data1 	0xb8, 0x7f, 0x00, 0x00, 0x59, 0x59, 0x57, 0xff
+.data1 	0x76, 0x04, 0xe8, 0x32, 0xff, 0xff, 0xff, 0x59
+.data1 	0x59, 0xe8, 0x43, 0x83, 0x00, 0x00, 0xe9, 0xfd
+.data1 	0x00, 0x00, 0x00, 0x57, 0x56, 0xe8, 0x9f, 0x03
+.data1 	0x00, 0x00, 0x59, 0x59, 0xe9, 0xef, 0x00, 0x00
+.data1 	0x00, 0x57, 0x56, 0xe8, 0x91, 0x03, 0x00, 0x00
+.data1 	0x59, 0x59, 0xe9, 0xe1, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x02
+.data1 	0xff, 0x76, 0x04, 0xe8, 0xf9, 0xfe, 0xff, 0xff
+.data1 	0x59, 0x59, 0x83, 0x3d, 0xb0, 0x2c, 0x00, 0x00
+.data1 	0x00, 0x0f, 0x85, 0xc1, 0x00, 0x00, 0x00, 0x83
+.data1 	0x3d, 0xa4, 0x2c, 0x00, 0x00, 0x00, 0x75, 0x16
+.data1 	0x57, 0xff, 0x76, 0x08, 0xe8, 0xd8, 0xfe, 0xff
+.data1 	0xff, 0x59, 0x59, 0x8b, 0x15, 0xa4, 0x2c, 0x00
+.data1 	0x00, 0x89, 0x55, 0xfc, 0xeb, 0x1a, 0x83, 0x7e
+.data1 	0x0c, 0x00, 0x74, 0x14, 0x57, 0xff, 0x76, 0x0c
+.data1 	0xe8, 0xbc, 0xfe, 0xff, 0xff, 0x59, 0x59, 0x8b
+.data1 	0x15, 0xa4, 0x2c, 0x00, 0x00, 0x89, 0x55, 0xfc
+.data1 	0x8b, 0x55, 0xfc, 0x89, 0x15, 0xa4, 0x2c, 0x00
+.data1 	0x00, 0xe9, 0x7a, 0x00, 0x00, 0x00, 0x56, 0xe8
+.data1 	0xbe, 0x00, 0x00, 0x00, 0x59, 0xe9, 0x6e, 0x00
+.data1 	0x00, 0x00, 0x56, 0xe8, 0x78, 0x01, 0x00, 0x00
+.data1 	0x59, 0xe9, 0x62, 0x00, 0x00, 0x00, 0x57, 0x56
+.data1 	0xe8, 0x70, 0x02, 0x00, 0x00, 0x59, 0x59, 0xeb
+.data1 	0x57, 0xff, 0x76, 0x04, 0xff, 0x76, 0x08, 0xe8
+.data1 	0x2b, 0x1c, 0x00, 0x00, 0x59, 0x59, 0xc7, 0x05
+.data1 	0xa4, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x3e, 0x56, 0xe8, 0xd4, 0x03, 0x00, 0x00
+.data1 	0x59, 0xeb, 0x35, 0x6a, 0x00, 0x57, 0x56, 0xe8
+.data1 	0x60, 0x06, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xeb
+.data1 	0x27, 0xff, 0x36, 0x68, 0xe0, 0x01, 0x00, 0x00
+.data1 	0xe8, 0xc1, 0x89, 0x00, 0x00, 0x59, 0x59, 0x68
+.data1 	0x68, 0x23, 0x00, 0x00, 0xe8, 0xf1, 0x88, 0x00
+.data1 	0x00, 0x59, 0xeb, 0x0c, 0xbb, 0x98, 0x01, 0x00
+.data1 	0x00, 0x8b, 0x06, 0xe9, 0x78, 0xef, 0x00, 0x00
+.data1 	0x83, 0x3d, 0xc0, 0x2c, 0x00, 0x00, 0x00, 0x74
+.data1 	0x05, 0xe8, 0x5e, 0x86, 0x00, 0x00, 0xf7, 0xc7
+.data1 	0x01, 0x00, 0x00, 0x00, 0x75, 0x24, 0x80, 0x3d
+.data1 	0x74, 0x2c, 0x00, 0x00, 0x00, 0x74, 0x27, 0x83
+.data1 	0x3d, 0xa4, 0x2c, 0x00, 0x00, 0x00, 0x74, 0x1e
+.data1 	0xf7, 0xc7, 0x02, 0x00, 0x00, 0x00, 0x75, 0x16
+.data1 	0x83, 0x3e, 0x01, 0x74, 0x05, 0x83, 0x3e, 0x05
+.data1 	0x75, 0x0c, 0xff, 0x35, 0xa4, 0x2c, 0x00, 0x00
+.data1 	0xe8, 0xb4, 0x86, 0x00, 0x00, 0x59, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0xff, 0x05
+.data1 	0xb8, 0x2c, 0x00, 0x00, 0x31, 0xf6, 0x8b, 0x55
+.data1 	0x08, 0x6a, 0x02, 0xff, 0x72, 0x04, 0xe8, 0xc6
+.data1 	0xfd, 0xff, 0xff, 0x59, 0x59, 0x83, 0x3d, 0xb0
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x74, 0x50, 0x83, 0x3d
+.data1 	0xb0, 0x2c, 0x00, 0x00, 0x02, 0x75, 0x1d, 0x8b
+.data1 	0x15, 0xb4, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0xb4, 0x2c, 0x00, 0x00, 0x85, 0xd2, 0x7f, 0x0c
+.data1 	0xc7, 0x05, 0xb0, 0x2c, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0xeb, 0xc2, 0x83, 0x3d, 0xb0, 0x2c
+.data1 	0x00, 0x00, 0x01, 0x0f, 0x85, 0x60, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x15, 0xb4, 0x2c, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0xb4, 0x2c, 0x00, 0x00, 0x85, 0xd2
+.data1 	0x7f, 0x4f, 0xc7, 0x05, 0xb0, 0x2c, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xeb, 0x43, 0x8b, 0x45
+.data1 	0x08, 0x83, 0x38, 0x09, 0x75, 0x0b, 0x83, 0x3d
+.data1 	0xa4, 0x2c, 0x00, 0x00, 0x00, 0x74, 0x0b, 0xeb
+.data1 	0x30, 0x83, 0x3d, 0xa4, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x74, 0x27, 0x8b, 0x55, 0x08, 0x6a, 0x00, 0xff
+.data1 	0x72, 0x08, 0xe8, 0x42, 0xfd, 0xff, 0xff, 0x59
+.data1 	0x59, 0x8b, 0x35, 0xa4, 0x2c, 0x00, 0x00, 0x83
+.data1 	0x3d, 0xb0, 0x2c, 0x00, 0x00, 0x00, 0x0f, 0x84
+.data1 	0x5a, 0xff, 0xff, 0xff, 0xe9, 0x6d, 0xff, 0xff
+.data1 	0xff, 0xff, 0x0d, 0xb8, 0x2c, 0x00, 0x00, 0x89
+.data1 	0x35, 0xa4, 0x2c, 0x00, 0x00, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x1c, 0x56, 0x57
+.data1 	0x8d, 0x45, 0xe4, 0x50, 0xe8, 0xde, 0x50, 0x00
+.data1 	0x00, 0x59, 0x8d, 0x55, 0xf8, 0x89, 0x55, 0xfc
+.data1 	0x8b, 0x55, 0x08, 0x8b, 0x7a, 0x04, 0x85, 0xff
+.data1 	0x74, 0x2d, 0x8b, 0x15, 0xa4, 0x2c, 0x00, 0x00
+.data1 	0x89, 0x15, 0xbc, 0x2c, 0x00, 0x00, 0x6a, 0x01
+.data1 	0x8d, 0x45, 0xf8, 0x50, 0x57, 0xe8, 0x51, 0x1b
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x83, 0x3d, 0xb0
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x0f, 0x85, 0xad, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x7f, 0x04, 0xeb, 0xcf, 0x8b
+.data1 	0x45, 0xfc, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x05, 0xa4, 0x2c, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0xff, 0x05, 0xb8, 0x2c, 0x00, 0x00
+.data1 	0x8b, 0x75, 0xf8, 0x85, 0xf6, 0x0f, 0x84, 0x7e
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x08, 0x6a, 0x00
+.data1 	0xff, 0x76, 0x04, 0xff, 0x72, 0x0c, 0xe8, 0x47
+.data1 	0x8e, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55
+.data1 	0x08, 0x6a, 0x00, 0xff, 0x72, 0x08, 0xe8, 0x86
+.data1 	0xfc, 0xff, 0xff, 0x59, 0x59, 0x83, 0x3d, 0xb0
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x74, 0x4c, 0x83, 0x3d
+.data1 	0xb0, 0x2c, 0x00, 0x00, 0x02, 0x75, 0x1d, 0x8b
+.data1 	0x15, 0xb4, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0xb4, 0x2c, 0x00, 0x00, 0x85, 0xd2, 0x7f, 0x0c
+.data1 	0xc7, 0x05, 0xb0, 0x2c, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x26, 0x83, 0x3d, 0xb0, 0x2c
+.data1 	0x00, 0x00, 0x01, 0x75, 0x24, 0x8b, 0x15, 0xb4
+.data1 	0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0xb4, 0x2c
+.data1 	0x00, 0x00, 0x85, 0xd2, 0x7f, 0x13, 0xc7, 0x05
+.data1 	0xb0, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x07, 0x8b, 0x36, 0xe9, 0x7a, 0xff, 0xff
+.data1 	0xff, 0xff, 0x0d, 0xb8, 0x2c, 0x00, 0x00, 0x8d
+.data1 	0x45, 0xe4, 0x50, 0xe8, 0x17, 0x50, 0x00, 0x00
+.data1 	0x59, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x1c, 0x56, 0x57, 0x8d, 0x45, 0xe4
+.data1 	0x50, 0xe8, 0xd9, 0x4f, 0x00, 0x00, 0x59, 0x8d
+.data1 	0x55, 0xf0, 0x89, 0x55, 0xf4, 0x8b, 0x15, 0xa4
+.data1 	0x2c, 0x00, 0x00, 0x89, 0x15, 0xbc, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x08, 0x6a, 0x00, 0x8d, 0x45
+.data1 	0xf0, 0x50, 0xff, 0x72, 0x04, 0xe8, 0x51, 0x1a
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55, 0x08
+.data1 	0x8b, 0x72, 0x08, 0x85, 0xf6, 0x74, 0x44, 0x83
+.data1 	0x3d, 0xb0, 0x2c, 0x00, 0x00, 0x00, 0x75, 0x3b
+.data1 	0x8b, 0x7e, 0x08, 0x85, 0xff, 0x74, 0x2f, 0x8b
+.data1 	0x55, 0xf0, 0xff, 0x72, 0x04, 0x57, 0xe8, 0x81
+.data1 	0x30, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x74
+.data1 	0x18, 0x83, 0x3d, 0xb0, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x75, 0x19, 0xff, 0x75, 0x0c, 0xff, 0x76, 0x0c
+.data1 	0xe8, 0x9c, 0xfb, 0xff, 0xff, 0x59, 0x59, 0xeb
+.data1 	0x0a, 0x8b, 0x7f, 0x04, 0xeb, 0xcd, 0x8b, 0x76
+.data1 	0x04, 0xeb, 0xb8, 0x8d, 0x45, 0xe4, 0x50, 0xe8
+.data1 	0x83, 0x4f, 0x00, 0x00, 0x59, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x08, 0x31, 0xc0, 0x83, 0x3e
+.data1 	0x04, 0x75, 0x01, 0x40, 0x89, 0xc7, 0xff, 0x76
+.data1 	0x08, 0xe8, 0x81, 0x00, 0x00, 0x00, 0x59, 0x6a
+.data1 	0x01, 0x56, 0xe8, 0xcc, 0x3b, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0x45, 0xfc, 0x57, 0x56, 0xff, 0x75
+.data1 	0xfc, 0xe8, 0x29, 0x3d, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x85, 0xc0, 0x75, 0x27, 0x85, 0xff, 0x74
+.data1 	0x04, 0x83, 0x65, 0x0c, 0xfd, 0x6a, 0x00, 0xff
+.data1 	0x76, 0x08, 0xe8, 0xad, 0x7b, 0x00, 0x00, 0x59
+.data1 	0x59, 0xba, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x55
+.data1 	0x0c, 0x52, 0xff, 0x76, 0x04, 0xe8, 0x1f, 0xfb
+.data1 	0xff, 0xff, 0x59, 0x59, 0x85, 0xff, 0x75, 0x33
+.data1 	0xff, 0x05, 0x90, 0x2c, 0x00, 0x00, 0xff, 0x75
+.data1 	0xfc, 0xe8, 0xce, 0x3e, 0x00, 0x00, 0x59, 0xa3
+.data1 	0xa4, 0x2c, 0x00, 0x00, 0x8b, 0x15, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00
+.data1 	0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8, 0xac
+.data1 	0xf8, 0xff, 0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x0c, 0x56, 0x8b, 0x75
+.data1 	0x08, 0x85, 0xf6, 0x0f, 0x84, 0x40, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x15, 0xa4, 0x2c, 0x00, 0x00, 0x89
+.data1 	0x15, 0xbc, 0x2c, 0x00, 0x00, 0x83, 0x3e, 0x11
+.data1 	0x74, 0x0a, 0x83, 0x3e, 0x10, 0x74, 0x05, 0x83
+.data1 	0x3e, 0x12, 0x75, 0x20, 0x8d, 0x55, 0xf4, 0x89
+.data1 	0x55, 0xf8, 0x6a, 0x00, 0x8d, 0x45, 0xf4, 0x50
+.data1 	0xff, 0x76, 0x0c, 0xe8, 0x13, 0x19, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x8b, 0x55, 0xf4, 0x8b, 0x52
+.data1 	0x04, 0x89, 0x56, 0x10, 0x8b, 0x76, 0x04, 0xeb
+.data1 	0xb8, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x18, 0x56, 0x57, 0xc7, 0x45, 0xf4, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x08, 0x8b, 0x72
+.data1 	0x08, 0x85, 0xf6, 0x74, 0x07, 0xff, 0x45, 0xf4
+.data1 	0x8b, 0x36, 0xeb, 0xf5, 0xff, 0x05, 0x90, 0x2c
+.data1 	0x00, 0x00, 0xff, 0x75, 0xf4, 0xff, 0x75, 0x08
+.data1 	0xe8, 0xce, 0x3a, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0x45, 0xfc, 0xbf, 0xff, 0xff, 0xff, 0xff, 0x8b
+.data1 	0x55, 0x08, 0x8b, 0x72, 0x08, 0x85, 0xf6, 0x0f
+.data1 	0x84, 0xe9, 0x00, 0x00, 0x00, 0xff, 0x76, 0x04
+.data1 	0xe8, 0xe5, 0x0b, 0x00, 0x00, 0x59, 0xc7, 0x45
+.data1 	0xec, 0xff, 0xff, 0xff, 0xff, 0x83, 0x3e, 0x00
+.data1 	0x74, 0x20, 0x8d, 0x45, 0xe8, 0x50, 0xe8, 0xdd
+.data1 	0xdd, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x79, 0x12
+.data1 	0x57, 0xe8, 0x4a, 0xdd, 0x00, 0x00, 0x59, 0x68
+.data1 	0xf0, 0x01, 0x00, 0x00, 0xe8, 0x37, 0xf8, 0xff
+.data1 	0xff, 0x59, 0x8b, 0x55, 0x08, 0xff, 0x72, 0x04
+.data1 	0xff, 0x76, 0x04, 0xff, 0x75, 0xfc, 0xe8, 0xdc
+.data1 	0x3b, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0
+.data1 	0x0f, 0x85, 0x7a, 0x00, 0x00, 0x00, 0x8b, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x75, 0x10, 0xff, 0x35, 0x8c
+.data1 	0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05
+.data1 	0xe8, 0x9a, 0xf7, 0xff, 0xff, 0x85, 0xff, 0x7e
+.data1 	0x19, 0x6a, 0x00, 0xe8, 0xf8, 0xdc, 0x00, 0x00
+.data1 	0x59, 0x6a, 0x00, 0x57, 0xe8, 0xb0, 0x7e, 0x00
+.data1 	0x00, 0x59, 0x59, 0x57, 0xe8, 0xe7, 0xdc, 0x00
+.data1 	0x00, 0x59, 0x83, 0x7d, 0xec, 0x00, 0x78, 0x2c
+.data1 	0xff, 0x75, 0xe8, 0xe8, 0xd8, 0xdc, 0x00, 0x00
+.data1 	0x59, 0x83, 0x7d, 0xec, 0x01, 0x74, 0x1d, 0x6a
+.data1 	0x01, 0xe8, 0xca, 0xdc, 0x00, 0x00, 0x59, 0x6a
+.data1 	0x01, 0xff, 0x75, 0xec, 0xe8, 0x80, 0x7e, 0x00
+.data1 	0x00, 0x59, 0x59, 0xff, 0x75, 0xec, 0xe8, 0xb5
+.data1 	0xdc, 0x00, 0x00, 0x59, 0x6a, 0x01, 0xff, 0x76
+.data1 	0x04, 0xe8, 0x7b, 0xf9, 0xff, 0xff, 0x59, 0x59
+.data1 	0x85, 0xff, 0x78, 0x07, 0x57, 0xe8, 0x9e, 0xdc
+.data1 	0x00, 0x00, 0x59, 0x8b, 0x7d, 0xe8, 0xff, 0x75
+.data1 	0xec, 0xe8, 0x92, 0xdc, 0x00, 0x00, 0x59, 0x8b
+.data1 	0x36, 0xe9, 0x0f, 0xff, 0xff, 0xff, 0x8b, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x75, 0x10, 0xff, 0x35, 0x8c
+.data1 	0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05
+.data1 	0xe8, 0x02, 0xf7, 0xff, 0xff, 0x8b, 0x55, 0x08
+.data1 	0x83, 0x7a, 0x04, 0x00, 0x75, 0x33, 0xff, 0x05
+.data1 	0x90, 0x2c, 0x00, 0x00, 0xff, 0x75, 0xfc, 0xe8
+.data1 	0xe8, 0x3c, 0x00, 0x00, 0x59, 0xa3, 0xa4, 0x2c
+.data1 	0x00, 0x00, 0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x75
+.data1 	0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a
+.data1 	0x85, 0xd2, 0x74, 0x05, 0xe8, 0xc6, 0xf6, 0xff
+.data1 	0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x18, 0x56, 0x57, 0x8b, 0x75, 0x0c
+.data1 	0x8b, 0x7d, 0x08, 0x8d, 0x45, 0xe8, 0x50, 0xe8
+.data1 	0xbb, 0x4c, 0x00, 0x00, 0x59, 0xc7, 0x06, 0xff
+.data1 	0xff, 0xff, 0xff, 0xc7, 0x46, 0x04, 0x00, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x46, 0x08, 0x00, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x46, 0x0c, 0x00, 0x00, 0x00, 0x00
+.data1 	0x85, 0xff, 0x0f, 0x84, 0xbe, 0x00, 0x00, 0x00
+.data1 	0x83, 0x3f, 0x01, 0x75, 0x1d, 0x8b, 0x15, 0xbc
+.data1 	0x2c, 0x00, 0x00, 0x89, 0x15, 0xa4, 0x2c, 0x00
+.data1 	0x00, 0x56, 0x6a, 0x04, 0x57, 0xe8, 0xb2, 0x00
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xe9, 0x9c, 0x00
+.data1 	0x00, 0x00, 0x8d, 0x45, 0xf8, 0x50, 0xe8, 0x4d
+.data1 	0xdc, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x79, 0x0b
+.data1 	0x68, 0x04, 0x02, 0x00, 0x00, 0xe8, 0xae, 0xf6
+.data1 	0xff, 0xff, 0x59, 0x6a, 0x01, 0x57, 0xe8, 0xf0
+.data1 	0x38, 0x00, 0x00, 0x59, 0x59, 0x89, 0x45, 0xf4
+.data1 	0x6a, 0x02, 0x57, 0xff, 0x75, 0xf4, 0xe8, 0x4c
+.data1 	0x3a, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0
+.data1 	0x75, 0x50, 0xc7, 0x05, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xff, 0x35, 0x8c, 0x2c
+.data1 	0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8
+.data1 	0x13, 0xf6, 0xff, 0xff, 0xff, 0x75, 0xf8, 0xe8
+.data1 	0x74, 0xdb, 0x00, 0x00, 0x59, 0x83, 0x7d, 0xfc
+.data1 	0x01, 0x74, 0x1d, 0x6a, 0x01, 0xe8, 0x66, 0xdb
+.data1 	0x00, 0x00, 0x59, 0x6a, 0x01, 0xff, 0x75, 0xfc
+.data1 	0xe8, 0x1c, 0x7d, 0x00, 0x00, 0x59, 0x59, 0xff
+.data1 	0x75, 0xfc, 0xe8, 0x51, 0xdb, 0x00, 0x00, 0x59
+.data1 	0x6a, 0x01, 0x57, 0xe8, 0x19, 0xf8, 0xff, 0xff
+.data1 	0x59, 0x59, 0xff, 0x75, 0xfc, 0xe8, 0x3e, 0xdb
+.data1 	0x00, 0x00, 0x59, 0x8b, 0x55, 0xf8, 0x89, 0x16
+.data1 	0x8b, 0x55, 0xf4, 0x89, 0x56, 0x0c, 0x8d, 0x45
+.data1 	0xe8, 0x50, 0xe8, 0xf8, 0x4b, 0x00, 0x00, 0x59
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x81
+.data1 	0xec, 0x8c, 0x00, 0x00, 0x00, 0x56, 0x57, 0x8d
+.data1 	0x45, 0xf4, 0x50, 0xe8, 0xb7, 0x4b, 0x00, 0x00
+.data1 	0x59, 0x8d, 0x55, 0xe8, 0x89, 0x55, 0xec, 0x8d
+.data1 	0x55, 0xe0, 0x89, 0x55, 0xe4, 0xc7, 0x45, 0xd0
+.data1 	0x01, 0x00, 0x00, 0x00, 0x8b, 0x15, 0xa4, 0x2c
+.data1 	0x00, 0x00, 0x89, 0x15, 0xbc, 0x2c, 0x00, 0x00
+.data1 	0xc7, 0x05, 0xa4, 0x2c, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x55, 0x08, 0x8b, 0x52, 0x08
+.data1 	0x89, 0x55, 0xf0, 0x83, 0x7d, 0xf0, 0x00, 0x0f
+.data1 	0x84, 0x68, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xf0
+.data1 	0x8b, 0x52, 0x08, 0x89, 0x55, 0xc8, 0x83, 0x7d
+.data1 	0xd0, 0x00, 0x74, 0x36, 0x0f, 0xbe, 0x02, 0xf6
+.data1 	0x80, 0x9d, 0x22, 0x00, 0x00, 0x0e, 0x74, 0x2a
+.data1 	0xff, 0x45, 0xc8, 0x8b, 0x55, 0xc8, 0x0f, 0xbe
+.data1 	0x02, 0xf6, 0x80, 0x9d, 0x22, 0x00, 0x00, 0x0f
+.data1 	0x75, 0xee, 0x80, 0x3a, 0x3d, 0x75, 0x13, 0x6a
+.data1 	0x00, 0x8d, 0x45, 0xe0, 0x50, 0xff, 0x75, 0xf0
+.data1 	0xe8, 0xd6, 0x15, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xeb, 0x18, 0x6a, 0x01, 0x8d, 0x45, 0xe8, 0x50
+.data1 	0xff, 0x75, 0xf0, 0xe8, 0xc3, 0x15, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0xc7, 0x45, 0xd0, 0x00, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x55, 0xf0, 0x8b, 0x52, 0x04
+.data1 	0x89, 0x55, 0xf0, 0xeb, 0x8e, 0x8b, 0x45, 0xec
+.data1 	0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x45
+.data1 	0xe4, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x08, 0xff, 0x72, 0x0c, 0xe8, 0x3d, 0xfc
+.data1 	0xff, 0xff, 0x59, 0xc7, 0x45, 0xd8, 0x00, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x55, 0xe8, 0x89, 0x55, 0xcc
+.data1 	0x83, 0x7d, 0xcc, 0x00, 0x74, 0x0d, 0xff, 0x45
+.data1 	0xd8, 0x8b, 0x45, 0xcc, 0x8b, 0x10, 0x89, 0x55
+.data1 	0xcc, 0xeb, 0xed, 0x8b, 0x55, 0xd8, 0x42, 0xc1
+.data1 	0xe2, 0x02, 0x52, 0xe8, 0xda, 0x49, 0x00, 0x00
+.data1 	0x59, 0x89, 0x45, 0xdc, 0x8b, 0x55, 0xe8, 0x89
+.data1 	0x55, 0xcc, 0x83, 0x7d, 0xcc, 0x00, 0x74, 0x19
+.data1 	0x8b, 0x55, 0xcc, 0x8b, 0x45, 0xdc, 0xff, 0x72
+.data1 	0x04, 0x83, 0x45, 0xdc, 0x04, 0x8f, 0x00, 0x8b
+.data1 	0x45, 0xcc, 0x8b, 0x10, 0x89, 0x55, 0xcc, 0xeb
+.data1 	0xe1, 0x8b, 0x45, 0xdc, 0xc7, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x85, 0x74, 0xff, 0xff, 0xff
+.data1 	0x00, 0x00, 0x00, 0x00, 0x80, 0x3d, 0x77, 0x2c
+.data1 	0x00, 0x00, 0x00, 0x74, 0x1b, 0x83, 0x3d, 0xac
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x75, 0x12, 0x83, 0x7d
+.data1 	0xd8, 0x00, 0x7e, 0x0c, 0x8b, 0x55, 0xdc, 0x8b
+.data1 	0x52, 0xfc, 0x89, 0x95, 0x74, 0xff, 0xff, 0xff
+.data1 	0x8b, 0x55, 0xd8, 0xc1, 0xe2, 0x02, 0xf7, 0xda
+.data1 	0x03, 0x55, 0xdc, 0x89, 0x55, 0xdc, 0x80, 0x3d
+.data1 	0x7b, 0x2c, 0x00, 0x00, 0x01, 0x0f, 0x85, 0x2f
+.data1 	0x01, 0x00, 0x00, 0x8b, 0x15, 0x80, 0x23, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0x80, 0x23, 0x00, 0x00
+.data1 	0x79, 0x1b, 0x68, 0x7c, 0x23, 0x00, 0x00, 0xe8
+.data1 	0x10, 0x80, 0x00, 0x00, 0x59, 0xa1, 0x7c, 0x23
+.data1 	0x00, 0x00, 0xff, 0x05, 0x7c, 0x23, 0x00, 0x00
+.data1 	0xc6, 0x00, 0x2b, 0xeb, 0x0e, 0xa1, 0x7c, 0x23
+.data1 	0x00, 0x00, 0xff, 0x05, 0x7c, 0x23, 0x00, 0x00
+.data1 	0xc6, 0x00, 0x2b, 0x8b, 0x55, 0xe0, 0x89, 0x55
+.data1 	0xcc, 0x83, 0x7d, 0xcc, 0x00, 0x74, 0x4e, 0x8b
+.data1 	0x15, 0x80, 0x23, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0x80, 0x23, 0x00, 0x00, 0x79, 0x1b, 0x68, 0x7c
+.data1 	0x23, 0x00, 0x00, 0xe8, 0xcc, 0x7f, 0x00, 0x00
+.data1 	0x59, 0xa1, 0x7c, 0x23, 0x00, 0x00, 0xff, 0x05
+.data1 	0x7c, 0x23, 0x00, 0x00, 0xc6, 0x00, 0x20, 0xeb
+.data1 	0x0e, 0xa1, 0x7c, 0x23, 0x00, 0x00, 0xff, 0x05
+.data1 	0x7c, 0x23, 0x00, 0x00, 0xc6, 0x00, 0x20, 0x8b
+.data1 	0x55, 0xcc, 0xff, 0x72, 0x04, 0xe8, 0x57, 0x7f
+.data1 	0x00, 0x00, 0x59, 0x8b, 0x45, 0xcc, 0x8b, 0x10
+.data1 	0x89, 0x55, 0xcc, 0xeb, 0xac, 0x8b, 0x55, 0xe8
+.data1 	0x89, 0x55, 0xcc, 0x83, 0x7d, 0xcc, 0x00, 0x74
+.data1 	0x4e, 0x8b, 0x15, 0x80, 0x23, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0x80, 0x23, 0x00, 0x00, 0x79, 0x1b
+.data1 	0x68, 0x7c, 0x23, 0x00, 0x00, 0xe8, 0x72, 0x7f
+.data1 	0x00, 0x00, 0x59, 0xa1, 0x7c, 0x23, 0x00, 0x00
+.data1 	0xff, 0x05, 0x7c, 0x23, 0x00, 0x00, 0xc6, 0x00
+.data1 	0x20, 0xeb, 0x0e, 0xa1, 0x7c, 0x23, 0x00, 0x00
+.data1 	0xff, 0x05, 0x7c, 0x23, 0x00, 0x00, 0xc6, 0x00
+.data1 	0x20, 0x8b, 0x55, 0xcc, 0xff, 0x72, 0x04, 0xe8
+.data1 	0xfd, 0x7e, 0x00, 0x00, 0x59, 0x8b, 0x45, 0xcc
+.data1 	0x8b, 0x10, 0x89, 0x55, 0xcc, 0xeb, 0xac, 0x8b
+.data1 	0x15, 0x80, 0x23, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0x80, 0x23, 0x00, 0x00, 0x79, 0x1b, 0x68, 0x7c
+.data1 	0x23, 0x00, 0x00, 0xe8, 0x24, 0x7f, 0x00, 0x00
+.data1 	0x59, 0xa1, 0x7c, 0x23, 0x00, 0x00, 0xff, 0x05
+.data1 	0x7c, 0x23, 0x00, 0x00, 0xc6, 0x00, 0x0a, 0xeb
+.data1 	0x0e, 0xa1, 0x7c, 0x23, 0x00, 0x00, 0xff, 0x05
+.data1 	0x7c, 0x23, 0x00, 0x00, 0xc6, 0x00, 0x0a, 0x68
+.data1 	0x7c, 0x23, 0x00, 0x00, 0xe8, 0x01, 0x80, 0x00
+.data1 	0x00, 0x59, 0x83, 0x7d, 0xd8, 0x00, 0x75, 0x13
+.data1 	0xc7, 0x45, 0xb4, 0x01, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xe9, 0xad
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x45, 0xdc, 0x6a, 0x01
+.data1 	0x8d, 0x5d, 0xb4, 0x53, 0xff, 0x30, 0xe8, 0x9b
+.data1 	0x0b, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x83, 0x7d
+.data1 	0xb4, 0xff, 0x75, 0x24, 0xc7, 0x05, 0xa4, 0x2c
+.data1 	0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x68, 0x7c
+.data1 	0x23, 0x00, 0x00, 0xe8, 0xba, 0x7f, 0x00, 0x00
+.data1 	0x59, 0x8d, 0x45, 0xf4, 0x50, 0xe8, 0xf5, 0x48
+.data1 	0x00, 0x00, 0x59, 0xe9, 0x96, 0x06, 0x00, 0x00
+.data1 	0x83, 0x7d, 0xb4, 0x01, 0x0f, 0x85, 0x66, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7d, 0xb8, 0x00, 0x0f, 0x85
+.data1 	0x5c, 0x00, 0x00, 0x00, 0x83, 0x45, 0xdc, 0x04
+.data1 	0xff, 0x4d, 0xd8, 0x74, 0x53, 0x8b, 0x45, 0xdc
+.data1 	0xff, 0x30, 0xe8, 0x9e, 0x0e, 0x00, 0x00, 0x59
+.data1 	0x89, 0x45, 0xb8, 0x85, 0xc0, 0x79, 0x3b, 0x8b
+.data1 	0x5d, 0xdc, 0xff, 0x33, 0x68, 0x74, 0x02, 0x00
+.data1 	0x00, 0x68, 0x7c, 0x23, 0x00, 0x00, 0xe8, 0x0e
+.data1 	0x80, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc7, 0x05
+.data1 	0xa4, 0x2c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x68, 0x7c, 0x23, 0x00, 0x00, 0xe8, 0x50, 0x7f
+.data1 	0x00, 0x00, 0x59, 0x8d, 0x45, 0xf4, 0x50, 0xe8
+.data1 	0x8b, 0x48, 0x00, 0x00, 0x59, 0xe9, 0x2c, 0x06
+.data1 	0x00, 0x00, 0x83, 0x7d, 0xb8, 0x00, 0x74, 0xa4
+.data1 	0x8b, 0x55, 0x08, 0x83, 0x7a, 0x04, 0x00, 0x75
+.data1 	0x30, 0x83, 0x7d, 0xb4, 0x00, 0x75, 0x08, 0x8b
+.data1 	0x55, 0x0c, 0xf6, 0xc2, 0x01, 0x74, 0x22, 0x8b
+.data1 	0x55, 0x0c, 0xf6, 0xc2, 0x04, 0x0f, 0x84, 0xc1
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xb4, 0x01, 0x75
+.data1 	0x10, 0x83, 0x7d, 0xb8, 0x03, 0x74, 0x0a, 0x83
+.data1 	0x7d, 0xb8, 0x05, 0x0f, 0x85, 0xab, 0x00, 0x00
+.data1 	0x00, 0x6a, 0x01, 0xff, 0x75, 0x08, 0xe8, 0xb0
+.data1 	0x34, 0x00, 0x00, 0x59, 0x59, 0x89, 0x45, 0xb0
+.data1 	0x8b, 0x55, 0x08, 0x8b, 0x52, 0x04, 0x89, 0x55
+.data1 	0xc4, 0x8b, 0x55, 0x0c, 0xf6, 0xc2, 0x04, 0x74
+.data1 	0x20, 0xc7, 0x45, 0xc4, 0x02, 0x00, 0x00, 0x00
+.data1 	0x8d, 0x45, 0xbc, 0x50, 0xe8, 0xcf, 0xd7, 0x00
+.data1 	0x00, 0x59, 0x85, 0xc0, 0x79, 0x0b, 0x68, 0x60
+.data1 	0x02, 0x00, 0x00, 0xe8, 0x30, 0xf2, 0xff, 0xff
+.data1 	0x59, 0xff, 0x75, 0xc4, 0xff, 0x75, 0x08, 0xff
+.data1 	0x75, 0xb0, 0xe8, 0xd8, 0x35, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x85, 0xc0, 0x0f, 0x85, 0x11, 0x05
+.data1 	0x00, 0x00, 0x8b, 0x55, 0x0c, 0xf6, 0xc2, 0x04
+.data1 	0x74, 0x46, 0xc7, 0x05, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xff, 0x35, 0x8c, 0x2c
+.data1 	0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8
+.data1 	0x93, 0xf1, 0xff, 0xff, 0xff, 0x75, 0xbc, 0xe8
+.data1 	0xf4, 0xd6, 0x00, 0x00, 0x59, 0x83, 0x7d, 0xc0
+.data1 	0x01, 0x74, 0x1d, 0x6a, 0x01, 0xe8, 0xe6, 0xd6
+.data1 	0x00, 0x00, 0x59, 0x6a, 0x01, 0xff, 0x75, 0xc0
+.data1 	0xe8, 0x9c, 0x78, 0x00, 0x00, 0x59, 0x59, 0xff
+.data1 	0x75, 0xc0, 0xe8, 0xd1, 0xd6, 0x00, 0x00, 0x59
+.data1 	0x83, 0x4d, 0x0c, 0x01, 0x83, 0x7d, 0xb4, 0x02
+.data1 	0x0f, 0x85, 0x0a, 0x02, 0x00, 0x00, 0x68, 0x4c
+.data1 	0x02, 0x00, 0x00, 0xe8, 0xc6, 0x78, 0x00, 0x00
+.data1 	0x59, 0xff, 0x75, 0xdc, 0xe8, 0xcc, 0x78, 0x00
+.data1 	0x00, 0x59, 0x8b, 0x55, 0x08, 0x6a, 0x01, 0xff
+.data1 	0x72, 0x0c, 0xe8, 0xed, 0x73, 0x00, 0x00, 0x59
+.data1 	0x59, 0x68, 0xcc, 0x2c, 0x00, 0x00, 0x8d, 0x45
+.data1 	0x80, 0x50, 0xb9, 0x05, 0x00, 0x00, 0x00, 0xe8
+.data1 	0x94, 0xe4, 0x00, 0x00, 0xc6, 0x05, 0xd0, 0x2c
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0xd8, 0x4a, 0x89
+.data1 	0x15, 0xcc, 0x2c, 0x00, 0x00, 0x8b, 0x55, 0xdc
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x15, 0xd4, 0x2c, 0x00
+.data1 	0x00, 0xc7, 0x05, 0xd8, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0xff, 0x05, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x15, 0x64, 0x2c, 0x00, 0x00, 0x89
+.data1 	0x95, 0x7c, 0xff, 0xff, 0xff, 0xc7, 0x05, 0x64
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x75, 0x10, 0xff, 0x35
+.data1 	0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74
+.data1 	0x05, 0xe8, 0xc1, 0xf0, 0xff, 0xff, 0xff, 0x35
+.data1 	0x18, 0x02, 0x00, 0x00, 0x6a, 0x01, 0x8d, 0x45
+.data1 	0x9c, 0x50, 0xe8, 0x51, 0xd8, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x85, 0xc0, 0x74, 0x5c, 0x83, 0x3d
+.data1 	0x98, 0x2c, 0x00, 0x00, 0x02, 0x75, 0x0c, 0x8d
+.data1 	0x45, 0x80, 0x50, 0xe8, 0x8a, 0x54, 0x00, 0x00
+.data1 	0x59, 0xeb, 0x1e, 0x68, 0xcc, 0x2c, 0x00, 0x00
+.data1 	0xe8, 0x7d, 0x54, 0x00, 0x00, 0x59, 0x8d, 0x45
+.data1 	0x80, 0x50, 0x68, 0xcc, 0x2c, 0x00, 0x00, 0xb9
+.data1 	0x05, 0x00, 0x00, 0x00, 0xe8, 0xe7, 0xe3, 0x00
+.data1 	0x00, 0xe8, 0x75, 0x8b, 0x00, 0x00, 0xff, 0xb5
+.data1 	0x7c, 0xff, 0xff, 0xff, 0x8f, 0x05, 0x64, 0x2c
+.data1 	0x00, 0x00, 0xff, 0x75, 0x98, 0x8f, 0x05, 0x94
+.data1 	0x2c, 0x00, 0x00, 0x6a, 0x01, 0xff, 0x35, 0x94
+.data1 	0x2c, 0x00, 0x00, 0xe8, 0x32, 0xd8, 0x00, 0x00
+.data1 	0x59, 0x59, 0x8b, 0x15, 0x94, 0x2c, 0x00, 0x00
+.data1 	0x89, 0x55, 0x98, 0x8d, 0x55, 0x9c, 0x89, 0x15
+.data1 	0x94, 0x2c, 0x00, 0x00, 0x8b, 0x55, 0xe0, 0x89
+.data1 	0x55, 0xcc, 0x83, 0x7d, 0xcc, 0x00, 0x74, 0x16
+.data1 	0x8b, 0x55, 0xcc, 0xff, 0x72, 0x04, 0xe8, 0x00
+.data1 	0x8a, 0x00, 0x00, 0x59, 0x8b, 0x45, 0xcc, 0x8b
+.data1 	0x10, 0x89, 0x55, 0xcc, 0xeb, 0xe4, 0xff, 0x05
+.data1 	0xac, 0x2c, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0xf6
+.data1 	0xc2, 0x02, 0x74, 0x0e, 0x6a, 0x02, 0xff, 0x75
+.data1 	0xb8, 0xe8, 0x3b, 0xf2, 0xff, 0xff, 0x59, 0x59
+.data1 	0xeb, 0x0c, 0x6a, 0x00, 0xff, 0x75, 0xb8, 0xe8
+.data1 	0x2d, 0xf2, 0xff, 0xff, 0x59, 0x59, 0xff, 0x0d
+.data1 	0xac, 0x2c, 0x00, 0x00, 0xff, 0x05, 0x90, 0x2c
+.data1 	0x00, 0x00, 0xe8, 0xe4, 0x8a, 0x00, 0x00, 0xff
+.data1 	0xb5, 0x7c, 0xff, 0xff, 0xff, 0x8f, 0x05, 0x64
+.data1 	0x2c, 0x00, 0x00, 0x68, 0xcc, 0x2c, 0x00, 0x00
+.data1 	0xe8, 0xbd, 0x53, 0x00, 0x00, 0x59, 0x8d, 0x45
+.data1 	0x80, 0x50, 0x68, 0xcc, 0x2c, 0x00, 0x00, 0xb9
+.data1 	0x05, 0x00, 0x00, 0x00, 0xe8, 0x27, 0xe3, 0x00
+.data1 	0x00, 0xff, 0x75, 0x98, 0x8f, 0x05, 0x94, 0x2c
+.data1 	0x00, 0x00, 0xe8, 0xfa, 0x75, 0x00, 0x00, 0x8b
+.data1 	0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x75, 0x10, 0xff, 0x35
+.data1 	0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74
+.data1 	0x05, 0xe8, 0x89, 0xef, 0xff, 0xff, 0x83, 0x3d
+.data1 	0xb0, 0x2c, 0x00, 0x00, 0x03, 0x75, 0x14, 0xc7
+.data1 	0x05, 0xb0, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x05, 0xb4, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0xf6, 0xc2
+.data1 	0x01, 0x0f, 0x84, 0x17, 0x03, 0x00, 0x00, 0xff
+.data1 	0x35, 0xa4, 0x2c, 0x00, 0x00, 0xe8, 0x5f, 0x7a
+.data1 	0x00, 0x00, 0x59, 0xe9, 0x06, 0x03, 0x00, 0x00
+.data1 	0x83, 0x7d, 0xb4, 0x01, 0x0f, 0x85, 0xf0, 0x01
+.data1 	0x00, 0x00, 0x68, 0x38, 0x02, 0x00, 0x00, 0xe8
+.data1 	0xb2, 0x76, 0x00, 0x00, 0x59, 0xff, 0x75, 0xdc
+.data1 	0xe8, 0xb8, 0x76, 0x00, 0x00, 0x59, 0x83, 0x7d
+.data1 	0xb8, 0x06, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x05
+.data1 	0xb8, 0x01, 0x00, 0x00, 0x00, 0x89, 0x45, 0xc4
+.data1 	0x83, 0x7d, 0x0c, 0x04, 0x75, 0x24, 0xc7, 0x05
+.data1 	0x94, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x15, 0x98, 0x23, 0x00, 0x00, 0x89, 0x15
+.data1 	0x90, 0x23, 0x00, 0x00, 0xc7, 0x05, 0x9c, 0x23
+.data1 	0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x83, 0x4d
+.data1 	0xc4, 0x02, 0x8b, 0x55, 0x08, 0xff, 0x75, 0xc4
+.data1 	0xff, 0x72, 0x0c, 0xe8, 0x9c, 0x71, 0x00, 0x00
+.data1 	0x59, 0x59, 0x8b, 0x15, 0x9c, 0x2c, 0x00, 0x00
+.data1 	0x89, 0x55, 0x94, 0x8b, 0x55, 0xe0, 0x89, 0x15
+.data1 	0xa8, 0x2c, 0x00, 0x00, 0xc7, 0x85, 0x78, 0xff
+.data1 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x35
+.data1 	0x1c, 0x02, 0x00, 0x00, 0x6a, 0x01, 0x8d, 0x45
+.data1 	0x9c, 0x50, 0xe8, 0x59, 0xd6, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x85, 0xc0, 0x74, 0x2a, 0x8b, 0x15
+.data1 	0x98, 0x2c, 0x00, 0x00, 0x89, 0x95, 0x78, 0xff
+.data1 	0xff, 0xff, 0xff, 0xb5, 0x78, 0xff, 0xff, 0xff
+.data1 	0x5a, 0x85, 0xd2, 0x75, 0x07, 0xb8, 0x82, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x05, 0xb8, 0x02, 0x00, 0x00
+.data1 	0x00, 0xa3, 0xa4, 0x2c, 0x00, 0x00, 0xeb, 0x4f
+.data1 	0x8b, 0x15, 0x94, 0x2c, 0x00, 0x00, 0x89, 0x55
+.data1 	0x98, 0x8d, 0x55, 0x9c, 0x89, 0x15, 0x94, 0x2c
+.data1 	0x00, 0x00, 0x8b, 0x45, 0xdc, 0x8b, 0x10, 0x89
+.data1 	0x15, 0x9c, 0x2c, 0x00, 0x00, 0x8b, 0x55, 0xdc
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x15, 0x80, 0x2c, 0x00
+.data1 	0x00, 0xc7, 0x05, 0xc8, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0xb8, 0xff, 0x75
+.data1 	0xdc, 0xff, 0x75, 0xd8, 0xff, 0x14, 0x95, 0x30
+.data1 	0x19, 0x00, 0x00, 0x59, 0x59, 0xa3, 0xa4, 0x2c
+.data1 	0x00, 0x00, 0xe8, 0x10, 0x7b, 0x00, 0x00, 0xc7
+.data1 	0x05, 0xa4, 0x23, 0x00, 0x00, 0x68, 0x23, 0x00
+.data1 	0x00, 0xc7, 0x05, 0xa8, 0x23, 0x00, 0x00, 0x7c
+.data1 	0x23, 0x00, 0x00, 0xe8, 0x66, 0x7b, 0x00, 0x00
+.data1 	0xff, 0xb5, 0x78, 0xff, 0xff, 0xff, 0x5a, 0x83
+.data1 	0xfa, 0x02, 0x74, 0x1d, 0xff, 0x75, 0x94, 0x8f
+.data1 	0x05, 0x9c, 0x2c, 0x00, 0x00, 0x8b, 0x55, 0x0c
+.data1 	0xf6, 0xc2, 0x01, 0x74, 0x0c, 0xff, 0x35, 0xa4
+.data1 	0x2c, 0x00, 0x00, 0xe8, 0x01, 0x79, 0x00, 0x00
+.data1 	0x59, 0xff, 0x75, 0x98, 0x8f, 0x05, 0x94, 0x2c
+.data1 	0x00, 0x00, 0xff, 0xb5, 0x78, 0xff, 0xff, 0xff
+.data1 	0x5a, 0x83, 0xfa, 0xff, 0x74, 0x4a, 0xff, 0xb5
+.data1 	0x78, 0xff, 0xff, 0xff, 0x5a, 0x83, 0xfa, 0x01
+.data1 	0x75, 0x18, 0x83, 0x7d, 0xb8, 0x00, 0x74, 0x12
+.data1 	0x83, 0x7d, 0xb8, 0x03, 0x74, 0x0c, 0x83, 0x7d
+.data1 	0xb8, 0x05, 0x74, 0x06, 0x83, 0x7d, 0xb8, 0x06
+.data1 	0x75, 0x0c, 0xff, 0xb5, 0x78, 0xff, 0xff, 0xff
+.data1 	0xe8, 0x87, 0xed, 0xff, 0xff, 0x59, 0xc7, 0x05
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85
+.data1 	0xd2, 0x74, 0x05, 0xe8, 0x97, 0xed, 0xff, 0xff
+.data1 	0x83, 0x7d, 0xb8, 0x06, 0x74, 0x05, 0xe8, 0xde
+.data1 	0x73, 0x00, 0x00, 0x83, 0x7d, 0x0c, 0x04, 0x0f
+.data1 	0x85, 0x39, 0x01, 0x00, 0x00, 0x8b, 0x55, 0x10
+.data1 	0x8b, 0x0d, 0x98, 0x23, 0x00, 0x00, 0x89, 0x4a
+.data1 	0x04, 0x8b, 0x15, 0x90, 0x23, 0x00, 0x00, 0x2b
+.data1 	0x15, 0x98, 0x23, 0x00, 0x00, 0x8b, 0x4d, 0x10
+.data1 	0x89, 0x51, 0x08, 0xc7, 0x05, 0x98, 0x23, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x0c, 0x01
+.data1 	0x00, 0x00, 0x68, 0x24, 0x02, 0x00, 0x00, 0xe8
+.data1 	0xc2, 0x74, 0x00, 0x00, 0x59, 0xff, 0x75, 0xdc
+.data1 	0xe8, 0xc8, 0x74, 0x00, 0x00, 0x59, 0xe8, 0x23
+.data1 	0x74, 0x00, 0x00, 0x8b, 0x55, 0x08, 0x6a, 0x00
+.data1 	0xff, 0x72, 0x0c, 0xe8, 0xe4, 0x6f, 0x00, 0x00
+.data1 	0x59, 0x59, 0x83, 0x7d, 0xe0, 0x00, 0x74, 0x31
+.data1 	0x8b, 0x15, 0xe8, 0x2c, 0x00, 0x00, 0x83, 0xc2
+.data1 	0x05, 0x52, 0xe8, 0x59, 0xd4, 0x00, 0x00, 0x59
+.data1 	0x40, 0x50, 0xe8, 0x33, 0x42, 0x00, 0x00, 0x59
+.data1 	0x89, 0x45, 0xc8, 0x8b, 0x15, 0xe8, 0x2c, 0x00
+.data1 	0x00, 0x83, 0xc2, 0x05, 0x52, 0xff, 0x75, 0xc8
+.data1 	0xe8, 0x1b, 0xd4, 0x00, 0x00, 0x59, 0x59, 0xeb
+.data1 	0x0c, 0x8b, 0x15, 0xe8, 0x2c, 0x00, 0x00, 0x83
+.data1 	0xc2, 0x05, 0x89, 0x55, 0xc8, 0x8b, 0x55, 0xe0
+.data1 	0x89, 0x55, 0xcc, 0x83, 0x7d, 0xcc, 0x00, 0x74
+.data1 	0x19, 0x8b, 0x55, 0xcc, 0x6a, 0x11, 0xff, 0x72
+.data1 	0x04, 0xe8, 0x8b, 0x81, 0x00, 0x00, 0x59, 0x59
+.data1 	0x8b, 0x45, 0xcc, 0x8b, 0x10, 0x89, 0x55, 0xcc
+.data1 	0xeb, 0xe1, 0xe8, 0x9f, 0x83, 0x00, 0x00, 0x89
+.data1 	0x45, 0xd4, 0xff, 0x75, 0xb8, 0xff, 0x75, 0xc8
+.data1 	0xff, 0x75, 0xd4, 0xff, 0x75, 0xdc, 0xe8, 0xd5
+.data1 	0x01, 0x00, 0x00, 0x83, 0xc4, 0x10, 0xe9, 0x5b
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xc4, 0x00, 0x75
+.data1 	0x35, 0xff, 0x05, 0x90, 0x2c, 0x00, 0x00, 0xff
+.data1 	0x75, 0xb0, 0xe8, 0x8d, 0x32, 0x00, 0x00, 0x59
+.data1 	0xa3, 0xa4, 0x2c, 0x00, 0x00, 0x8b, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x75, 0x32, 0xff, 0x35, 0x8c, 0x2c
+.data1 	0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x27, 0xe8
+.data1 	0x6b, 0xec, 0xff, 0xff, 0xeb, 0x20, 0x83, 0x7d
+.data1 	0xc4, 0x02, 0x75, 0x1a, 0x8b, 0x55, 0xbc, 0x8b
+.data1 	0x45, 0x10, 0x89, 0x10, 0xff, 0x75, 0xc0, 0xe8
+.data1 	0xbc, 0xd1, 0x00, 0x00, 0x59, 0x8b, 0x55, 0x10
+.data1 	0x8b, 0x4d, 0xb0, 0x89, 0x4a, 0x0c, 0x83, 0xbd
+.data1 	0x74, 0xff, 0xff, 0xff, 0x00, 0x74, 0x15, 0x6a
+.data1 	0x00, 0xff, 0xb5, 0x74, 0xff, 0xff, 0xff, 0x68
+.data1 	0x20, 0x02, 0x00, 0x00, 0xe8, 0x19, 0x80, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x8d, 0x45, 0xf4, 0x50
+.data1 	0xe8, 0x5a, 0x42, 0x00, 0x00, 0x59, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08
+.data1 	0x8b, 0x45, 0x08, 0x83, 0x38, 0x01, 0x75, 0x2a
+.data1 	0x8b, 0x55, 0x08, 0x8b, 0x52, 0x08, 0xff, 0x72
+.data1 	0x08, 0xe8, 0xd3, 0x6d, 0x00, 0x00, 0x59, 0x85
+.data1 	0xc0, 0x74, 0x17, 0x8b, 0x55, 0x08, 0x8b, 0x52
+.data1 	0x08, 0x6a, 0x00, 0x8d, 0x45, 0xf8, 0x50, 0xff
+.data1 	0x72, 0x08, 0xe8, 0x9f, 0x04, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0xff
+.data1 	0x35, 0xa8, 0x2c, 0x00, 0x00, 0xe8, 0x90, 0x81
+.data1 	0x00, 0x00, 0x59, 0xa1, 0xa4, 0x2c, 0x00, 0x00
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0xbe, 0x01
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0x08, 0x01, 0x7e
+.data1 	0x0e, 0x8b, 0x55, 0x0c, 0xff, 0x72, 0x04, 0xe8
+.data1 	0xf1, 0x47, 0x00, 0x00, 0x59, 0x89, 0xc6, 0x39
+.data1 	0x35, 0xb8, 0x2c, 0x00, 0x00, 0x7d, 0x06, 0x8b
+.data1 	0x35, 0xb8, 0x2c, 0x00, 0x00, 0x85, 0xf6, 0x7e
+.data1 	0x21, 0x8b, 0x45, 0x0c, 0x8b, 0x10, 0x80, 0x3a
+.data1 	0x63, 0x75, 0x07, 0xb8, 0x02, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x05, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xa3
+.data1 	0xb0, 0x2c, 0x00, 0x00, 0x89, 0x35, 0xb4, 0x2c
+.data1 	0x00, 0x00, 0x31, 0xc0, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0x8b, 0x35, 0xbc, 0x2c, 0x00
+.data1 	0x00, 0x83, 0x7d, 0x08, 0x01, 0x7e, 0x0e, 0x8b
+.data1 	0x55, 0x0c, 0xff, 0x72, 0x04, 0xe8, 0x9b, 0x47
+.data1 	0x00, 0x00, 0x59, 0x89, 0xc6, 0x83, 0x3d, 0xac
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x74, 0x14, 0xc7, 0x05
+.data1 	0xb0, 0x2c, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x05, 0xb4, 0x2c, 0x00, 0x00, 0x01, 0x00
+.data1 	0x00, 0x00, 0x89, 0xf0, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x8b, 0x45, 0x0c, 0x68, 0x84, 0x02
+.data1 	0x00, 0x00, 0xff, 0x30, 0xe8, 0x37, 0xd2, 0x00
+.data1 	0x00, 0x59, 0x59, 0x85, 0xc0, 0x75, 0x07, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x00, 0xeb, 0x02, 0x31, 0xc0
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0x7d, 0x08
+.data1 	0x01, 0x7e, 0x30, 0xc6, 0x05, 0x77, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x6a, 0x00, 0xe8, 0xd7, 0x75, 0x00
+.data1 	0x00, 0x59, 0x8b, 0x15, 0xe8, 0x2c, 0x00, 0x00
+.data1 	0x6a, 0x00, 0x83, 0xc2, 0x05, 0x52, 0xe8, 0xcb
+.data1 	0x81, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0x50, 0x83
+.data1 	0xc2, 0x04, 0x52, 0xe8, 0x08, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0x31, 0xc0, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x56, 0x57
+.data1 	0x8b, 0x75, 0x08, 0x6a, 0x2f, 0xff, 0x36, 0xe8
+.data1 	0x9a, 0x46, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x74, 0x19, 0xff, 0x75, 0x0c, 0x56, 0xff, 0x36
+.data1 	0xe8, 0x7c, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x8b, 0x3d, 0xf0, 0x27, 0x00, 0x00, 0xe9, 0x59
+.data1 	0x00, 0x00, 0x00, 0xbf, 0x02, 0x00, 0x00, 0x00
+.data1 	0xff, 0x36, 0x8d, 0x45, 0x10, 0x50, 0xe8, 0x77
+.data1 	0x00, 0x00, 0x00, 0x59, 0x59, 0x89, 0x45, 0xfc
+.data1 	0x85, 0xc0, 0x74, 0x40, 0xff, 0x4d, 0x14, 0x79
+.data1 	0x30, 0x83, 0x3d, 0xec, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x75, 0x27, 0xff, 0x75, 0x0c, 0x56, 0xff, 0x75
+.data1 	0xfc, 0xe8, 0x3b, 0x00, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x83, 0x3d, 0xf0, 0x27, 0x00, 0x00, 0x02
+.data1 	0x74, 0x0f, 0x83, 0x3d, 0xf0, 0x27, 0x00, 0x00
+.data1 	0x14, 0x74, 0x06, 0x8b, 0x3d, 0xf0, 0x27, 0x00
+.data1 	0x00, 0xff, 0x75, 0xfc, 0xe8, 0x25, 0x40, 0x00
+.data1 	0x00, 0x59, 0xeb, 0xac, 0x57, 0xe8, 0x52, 0xc0
+.data1 	0x00, 0x00, 0x59, 0x50, 0xff, 0x36, 0xe8, 0x85
+.data1 	0xea, 0xff, 0xff, 0x59, 0x59, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0xff
+.data1 	0x75, 0x10, 0xff, 0x75, 0x0c, 0xff, 0x75, 0x08
+.data1 	0xe8, 0xa3, 0xcf, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x10
+.data1 	0x56, 0x57, 0x8b, 0x45, 0x08, 0x83, 0x38, 0x00
+.data1 	0x75, 0x07, 0x31, 0xc0, 0xe9, 0xbf, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x45, 0x08, 0x8b, 0x10, 0x89, 0x55
+.data1 	0xf4, 0x89, 0xd6, 0x80, 0x3e, 0x00, 0x74, 0x0d
+.data1 	0x80, 0x3e, 0x3a, 0x74, 0x08, 0x80, 0x3e, 0x25
+.data1 	0x74, 0x03, 0x46, 0xeb, 0xee, 0xff, 0x75, 0x0c
+.data1 	0xe8, 0x23, 0xd1, 0x00, 0x00, 0x59, 0x89, 0xf2
+.data1 	0x2b, 0x55, 0xf4, 0x01, 0xc2, 0x83, 0xc2, 0x02
+.data1 	0x89, 0x55, 0xf0, 0x8b, 0x55, 0xf0, 0x39, 0x15
+.data1 	0xac, 0x1c, 0x00, 0x00, 0x7d, 0x07, 0xe8, 0x64
+.data1 	0x40, 0x00, 0x00, 0xeb, 0xee, 0x8b, 0x3d, 0xa8
+.data1 	0x1c, 0x00, 0x00, 0x39, 0x75, 0xf4, 0x74, 0x21
+.data1 	0x89, 0xf2, 0x2b, 0x55, 0xf4, 0x52, 0x57, 0xff
+.data1 	0x75, 0xf4, 0xe8, 0xa1, 0x45, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0xf2, 0x2b, 0x55, 0xf4, 0x89
+.data1 	0xf9, 0x89, 0xd7, 0x01, 0xcf, 0xc6, 0x07, 0x2f
+.data1 	0x47, 0xff, 0x75, 0x0c, 0x57, 0xe8, 0xae, 0xd0
+.data1 	0x00, 0x00, 0x59, 0x59, 0xc7, 0x05, 0xec, 0x2c
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3e
+.data1 	0x25, 0x75, 0x14, 0x46, 0x89, 0x35, 0xec, 0x2c
+.data1 	0x00, 0x00, 0x80, 0x3e, 0x00, 0x74, 0x08, 0x80
+.data1 	0x3e, 0x3a, 0x74, 0x03, 0x46, 0xeb, 0xf3, 0x80
+.data1 	0x3e, 0x3a, 0x75, 0x0a, 0x8d, 0x56, 0x01, 0x8b
+.data1 	0x45, 0x08, 0x89, 0x10, 0xeb, 0x09, 0x8b, 0x45
+.data1 	0x08, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff
+.data1 	0x75, 0xf0, 0xe8, 0x6b, 0x3e, 0x00, 0x00, 0x59
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x1c, 0x56, 0x57, 0x83, 0x7d, 0x08, 0x01
+.data1 	0x7f, 0x2a, 0xbf, 0xf0, 0x2c, 0x00, 0x00, 0x81
+.data1 	0xff, 0x6c, 0x2d, 0x00, 0x00, 0x73, 0x16, 0x8b
+.data1 	0x37, 0x85, 0xf6, 0x74, 0x0b, 0x56, 0xe8, 0xd4
+.data1 	0x00, 0x00, 0x00, 0x59, 0x8b, 0x36, 0xeb, 0xf1
+.data1 	0x83, 0xc7, 0x04, 0xeb, 0xe2, 0x31, 0xc0, 0xe9
+.data1 	0xbf, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xf0, 0x00
+.data1 	0x00, 0x00, 0x00, 0x68, 0x8c, 0x02, 0x00, 0x00
+.data1 	0xe8, 0xf4, 0x4f, 0x00, 0x00, 0x59, 0x89, 0x45
+.data1 	0xf4, 0x85, 0xc0, 0x74, 0x1b, 0x83, 0x7d, 0xf4
+.data1 	0x72, 0x75, 0x0a, 0x6a, 0x00, 0xe8, 0x43, 0x06
+.data1 	0x00, 0x00, 0x59, 0xeb, 0xde, 0x83, 0x7d, 0xf4
+.data1 	0x76, 0x75, 0xd8, 0xff, 0x45, 0xf0, 0xeb, 0xd3
+.data1 	0x8b, 0x15, 0x80, 0x2c, 0x00, 0x00, 0x8b, 0x12
+.data1 	0x89, 0x55, 0xe4, 0x85, 0xd2, 0x0f, 0x84, 0x76
+.data1 	0x00, 0x00, 0x00, 0x6a, 0x00, 0xff, 0x75, 0xe4
+.data1 	0xe8, 0x1c, 0x07, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0xc6, 0x85, 0xc0, 0x74, 0x21, 0x0f, 0xb7, 0x56
+.data1 	0x08, 0x85, 0xd2, 0x74, 0x14, 0x0f, 0xbf, 0x46
+.data1 	0x08, 0x3d, 0x01, 0x00, 0x00, 0x00, 0x75, 0x0e
+.data1 	0x83, 0x3d, 0x58, 0x1b, 0x00, 0x00, 0x00, 0x78
+.data1 	0x05, 0xe8, 0xd3, 0x07, 0x00, 0x00, 0x6a, 0x01
+.data1 	0x8d, 0x45, 0xe8, 0x50, 0xff, 0x75, 0xe4, 0xe8
+.data1 	0x3a, 0x01, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x83
+.data1 	0x7d, 0xf0, 0x00, 0x74, 0x20, 0x83, 0x7d, 0xe8
+.data1 	0xff, 0x74, 0x15, 0x6a, 0x00, 0xff, 0x75, 0xe4
+.data1 	0xe8, 0xcc, 0x06, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0xc6, 0x56, 0xe8, 0x18, 0x00, 0x00, 0x00, 0x59
+.data1 	0xe8, 0x32, 0x75, 0x00, 0x00, 0x83, 0x05, 0x80
+.data1 	0x2c, 0x00, 0x00, 0x04, 0xe9, 0x77, 0xff, 0xff
+.data1 	0xff, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57, 0x8b
+.data1 	0x75, 0x08, 0x0f, 0xb7, 0x56, 0x08, 0x85, 0xd2
+.data1 	0x75, 0x36, 0x8b, 0x7e, 0x04, 0x8b, 0x15, 0xe8
+.data1 	0x2c, 0x00, 0x00, 0x83, 0xc2, 0x05, 0x89, 0x55
+.data1 	0xf8, 0x8d, 0x46, 0x0b, 0x50, 0x8d, 0x45, 0xf8
+.data1 	0x50, 0xe8, 0xfc, 0xfd, 0xff, 0xff, 0x59, 0x59
+.data1 	0x89, 0x45, 0xf4, 0x50, 0xe8, 0xe5, 0x3d, 0x00
+.data1 	0x00, 0x59, 0x4f, 0x79, 0xe4, 0xff, 0x75, 0xf4
+.data1 	0xe8, 0x8f, 0x73, 0x00, 0x00, 0x59, 0xeb, 0x38
+.data1 	0x0f, 0xbf, 0x46, 0x08, 0x3d, 0x01, 0x00, 0x00
+.data1 	0x00, 0x75, 0x12, 0x8d, 0x46, 0x0b, 0x50, 0x68
+.data1 	0x9c, 0x02, 0x00, 0x00, 0xe8, 0x9d, 0x75, 0x00
+.data1 	0x00, 0x59, 0x59, 0xeb, 0x1b, 0x0f, 0xbf, 0x46
+.data1 	0x08, 0x3d, 0x02, 0x00, 0x00, 0x00, 0x75, 0x10
+.data1 	0x8d, 0x46, 0x0b, 0x50, 0x68, 0x90, 0x02, 0x00
+.data1 	0x00, 0xe8, 0x80, 0x75, 0x00, 0x00, 0x59, 0x59
+.data1 	0x80, 0x7e, 0x0a, 0x00, 0x74, 0x3a, 0xa1, 0xa4
+.data1 	0x23, 0x00, 0x00, 0xff, 0x48, 0x04, 0x8b, 0x15
+.data1 	0xa4, 0x23, 0x00, 0x00, 0x83, 0x7a, 0x04, 0x00
+.data1 	0x79, 0x1a, 0xff, 0x35, 0xa4, 0x23, 0x00, 0x00
+.data1 	0xe8, 0x8f, 0x73, 0x00, 0x00, 0x59, 0xa1, 0xa4
+.data1 	0x23, 0x00, 0x00, 0x8b, 0x18, 0xff, 0x00, 0xc6
+.data1 	0x03, 0x2a, 0xeb, 0x0c, 0xa1, 0xa4, 0x23, 0x00
+.data1 	0x00, 0x8b, 0x18, 0xff, 0x00, 0xc6, 0x03, 0x2a
+.data1 	0xa1, 0xa4, 0x23, 0x00, 0x00, 0xff, 0x48, 0x04
+.data1 	0x8b, 0x15, 0xa4, 0x23, 0x00, 0x00, 0x83, 0x7a
+.data1 	0x04, 0x00, 0x79, 0x1a, 0xff, 0x35, 0xa4, 0x23
+.data1 	0x00, 0x00, 0xe8, 0x55, 0x73, 0x00, 0x00, 0x59
+.data1 	0xa1, 0xa4, 0x23, 0x00, 0x00, 0x8b, 0x18, 0xff
+.data1 	0x00, 0xc6, 0x03, 0x0a, 0xeb, 0x0c, 0xa1, 0xa4
+.data1 	0x23, 0x00, 0x00, 0x8b, 0x18, 0xff, 0x00, 0xc6
+.data1 	0x03, 0x0a, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x40, 0x56, 0x57, 0x8b, 0x7d
+.data1 	0x08, 0x6a, 0x2f, 0x57, 0xe8, 0x0d, 0x43, 0x00
+.data1 	0x00, 0x59, 0x59, 0x85, 0xc0, 0x74, 0x18, 0x8b
+.data1 	0x45, 0x0c, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x0c, 0xc7, 0x42, 0x04, 0x00, 0x00
+.data1 	0x00, 0x00, 0xe9, 0x22, 0x03, 0x00, 0x00, 0x6a
+.data1 	0x00, 0x57, 0xe8, 0x72, 0x05, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0xc6, 0x85, 0xc0, 0x74, 0x0a, 0x80
+.data1 	0x7e, 0x0a, 0x00, 0x0f, 0x84, 0xe6, 0x02, 0x00
+.data1 	0x00, 0x83, 0x3d, 0x58, 0x1b, 0x00, 0x00, 0x00
+.data1 	0x79, 0x58, 0x57, 0xe8, 0xfd, 0x02, 0x00, 0x00
+.data1 	0x59, 0x89, 0x45, 0xc0, 0x85, 0xc0, 0x78, 0x4a
+.data1 	0xff, 0x05, 0x90, 0x2c, 0x00, 0x00, 0x6a, 0x01
+.data1 	0x57, 0xe8, 0x3b, 0x05, 0x00, 0x00, 0x59, 0x59
+.data1 	0x89, 0xc6, 0x66, 0xc7, 0x46, 0x08, 0x01, 0x00
+.data1 	0x8b, 0x55, 0xc0, 0x89, 0x56, 0x04, 0x8b, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x0f, 0x85, 0x9e, 0x02, 0x00
+.data1 	0x00, 0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a
+.data1 	0x85, 0xd2, 0x0f, 0x84, 0x8f, 0x02, 0x00, 0x00
+.data1 	0xe8, 0xa2, 0xe6, 0xff, 0xff, 0xe9, 0x85, 0x02
+.data1 	0x00, 0x00, 0xc7, 0x45, 0xf4, 0xff, 0xff, 0xff
+.data1 	0xff, 0x85, 0xf6, 0x74, 0x1c, 0x0f, 0xbf, 0x46
+.data1 	0x08, 0x3d, 0x01, 0x00, 0x00, 0x00, 0x75, 0x0b
+.data1 	0x8b, 0x15, 0x58, 0x1b, 0x00, 0x00, 0x89, 0x55
+.data1 	0xf4, 0xeb, 0x06, 0x8b, 0x56, 0x04, 0x89, 0x55
+.data1 	0xf4, 0x8b, 0x15, 0xe8, 0x2c, 0x00, 0x00, 0x83
+.data1 	0xc2, 0x05, 0x89, 0x55, 0xf0, 0xc7, 0x45, 0xc4
+.data1 	0x02, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xf8, 0xff
+.data1 	0xff, 0xff, 0xff, 0x57, 0x8d, 0x45, 0xf0, 0x50
+.data1 	0xe8, 0x35, 0xfc, 0xff, 0xff, 0x59, 0x59, 0x89
+.data1 	0x45, 0xec, 0x85, 0xc0, 0x0f, 0x84, 0xf5, 0x01
+.data1 	0x00, 0x00, 0xff, 0x75, 0xec, 0xe8, 0x14, 0x3c
+.data1 	0x00, 0x00, 0x59, 0xff, 0x45, 0xf8, 0x83, 0x3d
+.data1 	0xec, 0x2c, 0x00, 0x00, 0x00, 0x0f, 0x84, 0x88
+.data1 	0x00, 0x00, 0x00, 0xff, 0x35, 0xec, 0x2c, 0x00
+.data1 	0x00, 0x68, 0xd0, 0x02, 0x00, 0x00, 0xe8, 0x31
+.data1 	0x42, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x74
+.data1 	0x58, 0x57, 0xe8, 0x1e, 0x02, 0x00, 0x00, 0x59
+.data1 	0x89, 0x45, 0xc0, 0x85, 0xc0, 0x78, 0xac, 0xff
+.data1 	0x05, 0x90, 0x2c, 0x00, 0x00, 0x6a, 0x01, 0x57
+.data1 	0xe8, 0x5c, 0x04, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0xc6, 0x66, 0xc7, 0x46, 0x08, 0x01, 0x00, 0x8b
+.data1 	0x55, 0xc0, 0x89, 0x56, 0x04, 0x8b, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x0f, 0x85, 0xbf, 0x01, 0x00, 0x00
+.data1 	0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85
+.data1 	0xd2, 0x0f, 0x84, 0xb0, 0x01, 0x00, 0x00, 0xe8
+.data1 	0xc3, 0xe5, 0xff, 0xff, 0xe9, 0xa6, 0x01, 0x00
+.data1 	0x00, 0xff, 0x35, 0xec, 0x2c, 0x00, 0x00, 0x68
+.data1 	0xc8, 0x02, 0x00, 0x00, 0xe8, 0xc3, 0x41, 0x00
+.data1 	0x00, 0x59, 0x59, 0x85, 0xc0, 0x0f, 0x84, 0x48
+.data1 	0xff, 0xff, 0xff, 0x8b, 0x55, 0xec, 0x80, 0x3a
+.data1 	0x2f, 0x75, 0x16, 0x8b, 0x55, 0xf4, 0x39, 0x55
+.data1 	0xf8, 0x7f, 0x0e, 0x39, 0x55, 0xf8, 0x0f, 0x8d
+.data1 	0x73, 0x01, 0x00, 0x00, 0xe9, 0x2a, 0xff, 0xff
+.data1 	0xff, 0x8d, 0x45, 0xc8, 0x50, 0xff, 0x75, 0xec
+.data1 	0xe8, 0x83, 0xcb, 0x00, 0x00, 0x59, 0x59, 0x85
+.data1 	0xc0, 0x79, 0x28, 0x83, 0x3d, 0xf0, 0x27, 0x00
+.data1 	0x00, 0x02, 0x0f, 0x84, 0x0b, 0xff, 0xff, 0xff
+.data1 	0x83, 0x3d, 0xf0, 0x27, 0x00, 0x00, 0x14, 0x0f
+.data1 	0x84, 0xfe, 0xfe, 0xff, 0xff, 0x8b, 0x15, 0xf0
+.data1 	0x27, 0x00, 0x00, 0x89, 0x55, 0xc4, 0xe9, 0xf0
+.data1 	0xfe, 0xff, 0xff, 0xc7, 0x45, 0xc4, 0x0d, 0x00
+.data1 	0x00, 0x00, 0x0f, 0xb7, 0x55, 0xd0, 0x81, 0xe2
+.data1 	0x00, 0xf0, 0x00, 0x00, 0x81, 0xfa, 0x00, 0x80
+.data1 	0x00, 0x00, 0x0f, 0x85, 0xd3, 0xfe, 0xff, 0xff
+.data1 	0x83, 0x3d, 0xec, 0x2c, 0x00, 0x00, 0x00, 0x74
+.data1 	0x54, 0xff, 0x75, 0xec, 0xe8, 0x5f, 0xcc, 0x00
+.data1 	0x00, 0x59, 0x40, 0x50, 0xe8, 0x39, 0x3a, 0x00
+.data1 	0x00, 0x59, 0xff, 0x75, 0xec, 0xe8, 0x5c, 0x38
+.data1 	0x00, 0x00, 0x59, 0x6a, 0x00, 0x57, 0xe8, 0x66
+.data1 	0x03, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc6, 0x85
+.data1 	0xc0, 0x74, 0x0b, 0x0f, 0xbf, 0x46, 0x08, 0x3d
+.data1 	0x02, 0x00, 0x00, 0x00, 0x74, 0x11, 0xff, 0x75
+.data1 	0xec, 0x57, 0x68, 0xb0, 0x02, 0x00, 0x00, 0xe8
+.data1 	0x44, 0xe5, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0xff
+.data1 	0x75, 0xec, 0xe8, 0xaf, 0x3a, 0x00, 0x00, 0x59
+.data1 	0xe9, 0xba, 0x00, 0x00, 0x00, 0xe8, 0x76, 0xca
+.data1 	0x00, 0x00, 0x0f, 0xbf, 0x5d, 0xd4, 0x39, 0xd8
+.data1 	0x75, 0x0e, 0x0f, 0xb7, 0x55, 0xd0, 0xf6, 0xc2
+.data1 	0x40, 0x75, 0x2d, 0xe9, 0x5b, 0xfe, 0xff, 0xff
+.data1 	0xe8, 0x53, 0xca, 0x00, 0x00, 0x0f, 0xbf, 0x5d
+.data1 	0xd6, 0x39, 0xd8, 0x75, 0x0e, 0x0f, 0xb7, 0x55
+.data1 	0xd0, 0xf6, 0xc2, 0x08, 0x75, 0x12, 0xe9, 0x40
+.data1 	0xfe, 0xff, 0xff, 0x0f, 0xb7, 0x55, 0xd0, 0xf6
+.data1 	0xc2, 0x01, 0x0f, 0x84, 0x33, 0xfe, 0xff, 0xff
+.data1 	0xff, 0x05, 0x90, 0x2c, 0x00, 0x00, 0x6a, 0x01
+.data1 	0x57, 0xe8, 0xe3, 0x02, 0x00, 0x00, 0x59, 0x59
+.data1 	0x89, 0xc6, 0x66, 0xc7, 0x46, 0x08, 0x00, 0x00
+.data1 	0x8b, 0x55, 0xf8, 0x89, 0x56, 0x04, 0x8b, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x75, 0x4a, 0xff, 0x35, 0x8c
+.data1 	0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x3f
+.data1 	0xe8, 0x52, 0xe4, 0xff, 0xff, 0xeb, 0x38, 0x85
+.data1 	0xf6, 0x74, 0x05, 0xe8, 0x89, 0x03, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x10, 0x00, 0x74, 0x1e, 0xff, 0x75
+.data1 	0xc4, 0xe8, 0x46, 0xba, 0x00, 0x00, 0x59, 0x50
+.data1 	0x57, 0x68, 0xa8, 0x02, 0x00, 0x00, 0xff, 0x35
+.data1 	0xa8, 0x23, 0x00, 0x00, 0xe8, 0xc0, 0x71, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x10, 0x8b, 0x45, 0x0c, 0xc7
+.data1 	0x00, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x22, 0xc6
+.data1 	0x46, 0x0a, 0x00, 0x0f, 0xbf, 0x46, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0x89, 0x03, 0x8b, 0x55, 0x0c, 0x8d
+.data1 	0x46, 0x04, 0x50, 0x83, 0xc2, 0x04, 0x52, 0xb9
+.data1 	0x01, 0x00, 0x00, 0x00, 0xe8, 0x67, 0xd7, 0x00
+.data1 	0x00, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0xbe, 0x98, 0x19, 0x00, 0x00, 0x83, 0x3e
+.data1 	0x00, 0x74, 0x29, 0x8b, 0x16, 0x0f, 0xbe, 0x02
+.data1 	0x8b, 0x55, 0x08, 0x0f, 0xbe, 0x1a, 0x39, 0xd8
+.data1 	0x75, 0x15, 0xff, 0x75, 0x08, 0xff, 0x36, 0xe8
+.data1 	0xdc, 0xca, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x75, 0x05, 0x8b, 0x46, 0x04, 0xeb, 0x0a, 0x83
+.data1 	0xc6, 0x08, 0xeb, 0xd2, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0xbf, 0xf0, 0x2c, 0x00, 0x00, 0x81, 0xff
+.data1 	0x6c, 0x2d, 0x00, 0x00, 0x73, 0x2f, 0x8b, 0x37
+.data1 	0x85, 0xf6, 0x74, 0x24, 0x0f, 0xb7, 0x56, 0x08
+.data1 	0x85, 0xd2, 0x74, 0x14, 0x0f, 0xbf, 0x46, 0x08
+.data1 	0x3d, 0x01, 0x00, 0x00, 0x00, 0x75, 0x0d, 0x83
+.data1 	0x3d, 0x58, 0x1b, 0x00, 0x00, 0x00, 0x78, 0x04
+.data1 	0xc6, 0x46, 0x0a, 0x01, 0x8b, 0x36, 0xeb, 0xd8
+.data1 	0x83, 0xc7, 0x04, 0xeb, 0xc9, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x14, 0x56
+.data1 	0x57, 0x8b, 0x3d, 0xe8, 0x2c, 0x00, 0x00, 0x83
+.data1 	0xc7, 0x05, 0x8b, 0x75, 0x08, 0xc7, 0x45, 0xf0
+.data1 	0x0f, 0x27, 0x00, 0x00, 0xc7, 0x45, 0xf4, 0x00
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x45, 0xec, 0xff, 0xff
+.data1 	0xff, 0xff, 0x0f, 0xbe, 0x07, 0x0f, 0xbe, 0x1e
+.data1 	0x39, 0xd8, 0x74, 0x1f, 0x8b, 0x55, 0xf4, 0x89
+.data1 	0x55, 0xf0, 0x80, 0x3f, 0x00, 0x75, 0x05, 0x80
+.data1 	0x3e, 0x3a, 0x74, 0x0a, 0x80, 0x3f, 0x3a, 0x75
+.data1 	0x08, 0x80, 0x3e, 0x00, 0x75, 0x03, 0xff, 0x45
+.data1 	0xf0, 0x89, 0xf7, 0x80, 0x3e, 0x00, 0x74, 0x31
+.data1 	0x80, 0x3e, 0x25, 0x75, 0x20, 0x83, 0x7d, 0xec
+.data1 	0x00, 0x79, 0x1a, 0x8d, 0x46, 0x01, 0x50, 0x68
+.data1 	0xd8, 0x02, 0x00, 0x00, 0xe8, 0x13, 0x3f, 0x00
+.data1 	0x00, 0x59, 0x59, 0x85, 0xc0, 0x74, 0x06, 0x8b
+.data1 	0x55, 0xf4, 0x89, 0x55, 0xec, 0x80, 0x3e, 0x3a
+.data1 	0x75, 0x03, 0xff, 0x45, 0xf4, 0x46, 0x47, 0xeb
+.data1 	0xa1, 0x83, 0x3d, 0x58, 0x1b, 0x00, 0x00, 0x00
+.data1 	0x79, 0x0f, 0x83, 0x7d, 0xec, 0x00, 0x78, 0x09
+.data1 	0x8b, 0x55, 0xec, 0x89, 0x15, 0x58, 0x1b, 0x00
+.data1 	0x00, 0x83, 0x3d, 0x58, 0x1b, 0x00, 0x00, 0x00
+.data1 	0x78, 0x0d, 0x83, 0x7d, 0xec, 0x00, 0x79, 0x07
+.data1 	0xc7, 0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff
+.data1 	0x75, 0xf0, 0xe8, 0x0e, 0x00, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x55, 0xec, 0x89, 0x15, 0x58, 0x1b, 0x00
+.data1 	0x00, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x08, 0x56, 0x57, 0xff, 0x05, 0x90
+.data1 	0x2c, 0x00, 0x00, 0xbf, 0xf0, 0x2c, 0x00, 0x00
+.data1 	0x81, 0xff, 0x6c, 0x2d, 0x00, 0x00, 0x0f, 0x83
+.data1 	0x4c, 0x00, 0x00, 0x00, 0x89, 0x7d, 0xf8, 0x8b
+.data1 	0x45, 0xf8, 0x8b, 0x30, 0x85, 0xf6, 0x74, 0x3b
+.data1 	0x0f, 0xb7, 0x56, 0x08, 0x85, 0xd2, 0x75, 0x08
+.data1 	0x8b, 0x55, 0x08, 0x39, 0x56, 0x04, 0x7d, 0x16
+.data1 	0x0f, 0xbf, 0x46, 0x08, 0x3d, 0x01, 0x00, 0x00
+.data1 	0x00, 0x75, 0x1b, 0x8b, 0x55, 0x08, 0x39, 0x15
+.data1 	0x58, 0x1b, 0x00, 0x00, 0x7c, 0x10, 0x8b, 0x16
+.data1 	0x8b, 0x45, 0xf8, 0x89, 0x10, 0x56, 0xe8, 0x2b
+.data1 	0xb5, 0x00, 0x00, 0x59, 0xeb, 0xc1, 0x89, 0x75
+.data1 	0xf8, 0xeb, 0xbc, 0x83, 0xc7, 0x04, 0xeb, 0xa8
+.data1 	0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89
+.data1 	0x15, 0x90, 0x2c, 0x00, 0x00, 0x75, 0x10, 0xff
+.data1 	0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2
+.data1 	0x74, 0x05, 0xe8, 0x18, 0xe2, 0xff, 0xff, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x08, 0x56, 0x57, 0xff, 0x05, 0x90, 0x2c, 0x00
+.data1 	0x00, 0xbf, 0xf0, 0x2c, 0x00, 0x00, 0x81, 0xff
+.data1 	0x6c, 0x2d, 0x00, 0x00, 0x73, 0x38, 0x89, 0x7d
+.data1 	0xf8, 0x8b, 0x45, 0xf8, 0x8b, 0x30, 0x85, 0xf6
+.data1 	0x74, 0x27, 0x0f, 0xbf, 0x5e, 0x08, 0x83, 0xfb
+.data1 	0x02, 0x75, 0x19, 0x8b, 0x16, 0x8b, 0x45, 0xf8
+.data1 	0x89, 0x10, 0xff, 0x76, 0x04, 0xe8, 0x91, 0x42
+.data1 	0x00, 0x00, 0x59, 0x56, 0xe8, 0xb5, 0xb4, 0x00
+.data1 	0x00, 0x59, 0xeb, 0xd5, 0x89, 0x75, 0xf8, 0xeb
+.data1 	0xd0, 0x83, 0xc7, 0x04, 0xeb, 0xc0, 0x8b, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x75, 0x10, 0xff, 0x35, 0x8c
+.data1 	0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05
+.data1 	0xe8, 0xa2, 0xe1, 0xff, 0xff, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x10, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x08, 0x0f, 0xbe, 0x06, 0xc1
+.data1 	0xe0, 0x04, 0x89, 0x45, 0xfc, 0x80, 0x3e, 0x00
+.data1 	0x74, 0x09, 0x0f, 0xbe, 0x06, 0x46, 0x01, 0x45
+.data1 	0xfc, 0xeb, 0xf2, 0x81, 0x65, 0xfc, 0xff, 0x7f
+.data1 	0x00, 0x00, 0xb9, 0x1f, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x45, 0xfc, 0x99, 0xf7, 0xf9, 0x8d, 0x14, 0x95
+.data1 	0xf0, 0x2c, 0x00, 0x00, 0x89, 0x55, 0xf0, 0x8b
+.data1 	0x45, 0xf0, 0x8b, 0x38, 0x85, 0xff, 0x74, 0x19
+.data1 	0xff, 0x75, 0x08, 0x8d, 0x47, 0x0b, 0x50, 0xe8
+.data1 	0x5c, 0xc8, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x74, 0x07, 0x89, 0x7d, 0xf0, 0x8b, 0x3f, 0xeb
+.data1 	0xe3, 0x83, 0x7d, 0x0c, 0x00, 0x0f, 0x84, 0x67
+.data1 	0x00, 0x00, 0x00, 0x85, 0xff, 0x0f, 0x85, 0x5f
+.data1 	0x00, 0x00, 0x00, 0xff, 0x05, 0x90, 0x2c, 0x00
+.data1 	0x00, 0xff, 0x75, 0x08, 0xe8, 0x5f, 0xc8, 0x00
+.data1 	0x00, 0x59, 0x05, 0x0c, 0x00, 0x00, 0x00, 0x50
+.data1 	0xe8, 0xc3, 0x35, 0x00, 0x00, 0x59, 0x8b, 0x5d
+.data1 	0xf0, 0x89, 0x03, 0x89, 0xc7, 0xc7, 0x07, 0x00
+.data1 	0x00, 0x00, 0x00, 0x66, 0xc7, 0x47, 0x08, 0xff
+.data1 	0xff, 0xc6, 0x47, 0x0a, 0x00, 0xff, 0x75, 0x08
+.data1 	0x8d, 0x47, 0x0b, 0x50, 0xe8, 0x0f, 0xc8, 0x00
+.data1 	0x00, 0x59, 0x59, 0x8b, 0x15, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00
+.data1 	0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8, 0xcd, 0xe0
+.data1 	0xff, 0xff, 0x8b, 0x55, 0xf0, 0x89, 0x15, 0x6c
+.data1 	0x2d, 0x00, 0x00, 0x89, 0xf8, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x56, 0xff, 0x05, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x8b, 0x15, 0x6c, 0x2d, 0x00
+.data1 	0x00, 0x8b, 0x32, 0x8b, 0x0e, 0x89, 0x0a, 0x56
+.data1 	0xe8, 0x89, 0xb3, 0x00, 0x00, 0x59, 0x8b, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x75, 0x10, 0xff, 0x35, 0x8c
+.data1 	0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05
+.data1 	0xe8, 0x82, 0xe0, 0xff, 0xff, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0xff, 0x05, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x6a, 0x01, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xcd, 0xfe, 0xff, 0xff, 0x59, 0x59, 0x89, 0xc6
+.data1 	0x0f, 0xbf, 0x46, 0x08, 0x3d, 0x02, 0x00, 0x00
+.data1 	0x00, 0x75, 0x09, 0xff, 0x76, 0x04, 0xe8, 0x10
+.data1 	0x41, 0x00, 0x00, 0x59, 0x8b, 0x45, 0x0c, 0x8b
+.data1 	0x00, 0x0f, 0xbf, 0xc0, 0x66, 0x89, 0x46, 0x08
+.data1 	0x8b, 0x55, 0x0c, 0x83, 0xc2, 0x04, 0x52, 0x8d
+.data1 	0x46, 0x04, 0x50, 0xb9, 0x01, 0x00, 0x00, 0x00
+.data1 	0xe8, 0xa3, 0xd3, 0x00, 0x00, 0x8b, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c
+.data1 	0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8
+.data1 	0x13, 0xe0, 0xff, 0xff, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x08, 0xff, 0x05, 0x90
+.data1 	0x2c, 0x00, 0x00, 0xc7, 0x45, 0xf8, 0x02, 0x00
+.data1 	0x00, 0x00, 0xff, 0x75, 0x0c, 0xe8, 0x86, 0x3c
+.data1 	0x00, 0x00, 0x59, 0x89, 0x45, 0xfc, 0x8d, 0x45
+.data1 	0xf8, 0x50, 0xff, 0x75, 0x08, 0xe8, 0x66, 0xff
+.data1 	0xff, 0xff, 0x59, 0x59, 0x8b, 0x15, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00
+.data1 	0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8, 0xc4
+.data1 	0xdf, 0xff, 0xff, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0x6a, 0x00, 0xff, 0x75, 0x08, 0xe8, 0x16
+.data1 	0xfe, 0xff, 0xff, 0x59, 0x59, 0x89, 0xc6, 0x85
+.data1 	0xc0, 0x74, 0x19, 0x0f, 0xbf, 0x46, 0x08, 0x3d
+.data1 	0x02, 0x00, 0x00, 0x00, 0x75, 0x0e, 0xff, 0x76
+.data1 	0x04, 0xe8, 0x55, 0x40, 0x00, 0x00, 0x59, 0xe8
+.data1 	0xd5, 0xfe, 0xff, 0xff, 0x5e, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x55, 0x0c, 0x89, 0x15
+.data1 	0xb0, 0x1c, 0x00, 0x00, 0x6a, 0x00, 0x6a, 0x00
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x23, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x8b, 0x15, 0x70, 0x2d, 0x00
+.data1 	0x00, 0x2b, 0x15, 0xa8, 0x1c, 0x00, 0x00, 0x52
+.data1 	0xff, 0x35, 0xa8, 0x1c, 0x00, 0x00, 0xff, 0x75
+.data1 	0x0c, 0xe8, 0x0c, 0x72, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x0c, 0x56, 0x57, 0xc7, 0x05, 0x70, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x55, 0x08
+.data1 	0x8b, 0x52, 0x0c, 0x89, 0x15, 0x74, 0x2d, 0x00
+.data1 	0x00, 0x8b, 0x15, 0xa8, 0x1c, 0x00, 0x00, 0x89
+.data1 	0x15, 0x70, 0x2d, 0x00, 0x00, 0x8b, 0x15, 0xac
+.data1 	0x1c, 0x00, 0x00, 0x89, 0x15, 0x84, 0x2c, 0x00
+.data1 	0x00, 0xc7, 0x05, 0x78, 0x2d, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x05, 0x88, 0x2d, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x55, 0x08
+.data1 	0xff, 0x75, 0x10, 0xff, 0x72, 0x08, 0xe8, 0x32
+.data1 	0x01, 0x00, 0x00, 0x59, 0x59, 0x83, 0x7d, 0x0c
+.data1 	0x00, 0x0f, 0x84, 0x22, 0x01, 0x00, 0x00, 0x8b
+.data1 	0x15, 0x84, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0x84, 0x2c, 0x00, 0x00, 0x78, 0x10, 0xa1, 0x70
+.data1 	0x2d, 0x00, 0x00, 0xff, 0x05, 0x70, 0x2d, 0x00
+.data1 	0x00, 0xc6, 0x00, 0x00, 0xeb, 0x13, 0xe8, 0x72
+.data1 	0x36, 0x00, 0x00, 0xa3, 0x70, 0x2d, 0x00, 0x00
+.data1 	0xff, 0x05, 0x70, 0x2d, 0x00, 0x00, 0xc6, 0x00
+.data1 	0x00, 0x8b, 0x15, 0xac, 0x1c, 0x00, 0x00, 0x2b
+.data1 	0x15, 0x84, 0x2c, 0x00, 0x00, 0x52, 0xe8, 0xcf
+.data1 	0x33, 0x00, 0x00, 0x59, 0x89, 0xc7, 0xc7, 0x05
+.data1 	0x90, 0x2d, 0x00, 0x00, 0x8c, 0x2d, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x10, 0x00, 0x74, 0x31, 0x68, 0x8c
+.data1 	0x2d, 0x00, 0x00, 0x57, 0xe8, 0x67, 0x0b, 0x00
+.data1 	0x00, 0x59, 0x59, 0x8b, 0x15, 0x90, 0x2d, 0x00
+.data1 	0x00, 0xc7, 0x02, 0x00, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x05, 0x90, 0x2d, 0x00, 0x00, 0x8c, 0x2d, 0x00
+.data1 	0x00, 0xff, 0x35, 0x8c, 0x2d, 0x00, 0x00, 0xe8
+.data1 	0x9f, 0x0c, 0x00, 0x00, 0x59, 0xeb, 0x1b, 0x6a
+.data1 	0x08, 0xe8, 0x84, 0x33, 0x00, 0x00, 0x59, 0x89
+.data1 	0xc6, 0x89, 0x7e, 0x04, 0x8b, 0x15, 0x90, 0x2d
+.data1 	0x00, 0x00, 0x89, 0x32, 0x89, 0x35, 0x90, 0x2d
+.data1 	0x00, 0x00, 0x83, 0x3d, 0x78, 0x2d, 0x00, 0x00
+.data1 	0x00, 0x74, 0x47, 0xff, 0x05, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x15, 0x78, 0x2d, 0x00, 0x00, 0x8b
+.data1 	0x12, 0x89, 0x55, 0xf4, 0xff, 0x35, 0x78, 0x2d
+.data1 	0x00, 0x00, 0xe8, 0x0f, 0xb1, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x55, 0xf4, 0x89, 0x15, 0x78, 0x2d, 0x00
+.data1 	0x00, 0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x75, 0xc2
+.data1 	0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85
+.data1 	0xd2, 0x74, 0xb7, 0xe8, 0xff, 0xdd, 0xff, 0xff
+.data1 	0xeb, 0xb0, 0x8b, 0x15, 0x90, 0x2d, 0x00, 0x00
+.data1 	0xc7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x83, 0x3d
+.data1 	0x8c, 0x2d, 0x00, 0x00, 0x00, 0x74, 0x1a, 0x8b
+.data1 	0x55, 0x0c, 0x8b, 0x52, 0x04, 0x8b, 0x0d, 0x8c
+.data1 	0x2d, 0x00, 0x00, 0x89, 0x0a, 0x8b, 0x55, 0x0c
+.data1 	0x8b, 0x0d, 0x90, 0x2d, 0x00, 0x00, 0x89, 0x4a
+.data1 	0x04, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x04, 0x56, 0x8b, 0x75, 0x08, 0xe9
+.data1 	0xf6, 0x00, 0x00, 0x00, 0x83, 0x7d, 0x0c, 0x00
+.data1 	0x74, 0x36, 0x8b, 0x15, 0x84, 0x2c, 0x00, 0x00
+.data1 	0x4a, 0x89, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x78
+.data1 	0x12, 0xa1, 0x70, 0x2d, 0x00, 0x00, 0xff, 0x05
+.data1 	0x70, 0x2d, 0x00, 0x00, 0x8a, 0x4d, 0xff, 0x88
+.data1 	0x08, 0xeb, 0x15, 0xe8, 0x35, 0x35, 0x00, 0x00
+.data1 	0xa3, 0x70, 0x2d, 0x00, 0x00, 0xff, 0x05, 0x70
+.data1 	0x2d, 0x00, 0x00, 0x8a, 0x4d, 0xff, 0x88, 0x08
+.data1 	0x8a, 0x06, 0x46, 0x88, 0x45, 0xff, 0x8b, 0x15
+.data1 	0x84, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x84
+.data1 	0x2c, 0x00, 0x00, 0x78, 0x15, 0xa1, 0x70, 0x2d
+.data1 	0x00, 0x00, 0xff, 0x05, 0x70, 0x2d, 0x00, 0x00
+.data1 	0x8a, 0x4d, 0xff, 0x88, 0x08, 0xe9, 0x90, 0x00
+.data1 	0x00, 0x00, 0xe8, 0xf6, 0x34, 0x00, 0x00, 0xa3
+.data1 	0x70, 0x2d, 0x00, 0x00, 0xff, 0x05, 0x70, 0x2d
+.data1 	0x00, 0x00, 0x8a, 0x4d, 0xff, 0x88, 0x08, 0xe9
+.data1 	0x76, 0x00, 0x00, 0x00, 0xff, 0x75, 0x0c, 0x56
+.data1 	0xe8, 0xc7, 0x02, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0xc6, 0xe9, 0x64, 0x00, 0x00, 0x00, 0x0f, 0xbe
+.data1 	0x45, 0xff, 0x25, 0x01, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x15, 0x74, 0x2d, 0x00, 0x00, 0xff, 0x75, 0x0c
+.data1 	0x50, 0xff, 0x72, 0x04, 0xe8, 0x5f, 0x00, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x15, 0x74, 0x2d
+.data1 	0x00, 0x00, 0x8b, 0x12, 0x89, 0x15, 0x74, 0x2d
+.data1 	0x00, 0x00, 0xeb, 0x36, 0x8b, 0x15, 0x84, 0x2c
+.data1 	0x00, 0x00, 0x4a, 0x89, 0x15, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x78, 0x12, 0xa1, 0x70, 0x2d, 0x00, 0x00
+.data1 	0xff, 0x05, 0x70, 0x2d, 0x00, 0x00, 0x8a, 0x4d
+.data1 	0xff, 0x88, 0x08, 0xeb, 0x15, 0xe8, 0x7b, 0x34
+.data1 	0x00, 0x00, 0xa3, 0x70, 0x2d, 0x00, 0x00, 0xff
+.data1 	0x05, 0x70, 0x2d, 0x00, 0x00, 0x8a, 0x4d, 0xff
+.data1 	0x88, 0x08, 0x8a, 0x06, 0x46, 0x88, 0x45, 0xff
+.data1 	0x0f, 0xbe, 0xc0, 0xbb, 0xe0, 0x02, 0x00, 0x00
+.data1 	0xe9, 0x67, 0xd0, 0x00, 0x00, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x81, 0xec, 0xc4, 0x00, 0x00
+.data1 	0x00, 0x56, 0x57, 0x8b, 0x35, 0x70, 0x2d, 0x00
+.data1 	0x00, 0x89, 0xf2, 0x2b, 0x15, 0xa8, 0x1c, 0x00
+.data1 	0x00, 0x89, 0x95, 0x44, 0xff, 0xff, 0xff, 0x83
+.data1 	0x7d, 0x0c, 0x00, 0x74, 0x07, 0xb8, 0x95, 0x20
+.data1 	0x00, 0x00, 0xeb, 0x05, 0xb8, 0x91, 0x1f, 0x00
+.data1 	0x00, 0x89, 0x85, 0x40, 0xff, 0xff, 0xff, 0xff
+.data1 	0x05, 0x90, 0x2c, 0x00, 0x00, 0x68, 0x78, 0x2d
+.data1 	0x00, 0x00, 0x8d, 0x85, 0x54, 0xff, 0xff, 0xff
+.data1 	0x50, 0xb9, 0x04, 0x00, 0x00, 0x00, 0xe8, 0xcd
+.data1 	0xcf, 0x00, 0x00, 0x8b, 0x15, 0x88, 0x2d, 0x00
+.data1 	0x00, 0x89, 0x95, 0x50, 0xff, 0xff, 0xff, 0x8b
+.data1 	0x15, 0x74, 0x2d, 0x00, 0x00, 0x89, 0x95, 0x4c
+.data1 	0xff, 0xff, 0xff, 0x8b, 0x15, 0xb0, 0x1c, 0x00
+.data1 	0x00, 0x89, 0x95, 0x3c, 0xff, 0xff, 0xff, 0xc7
+.data1 	0x05, 0xb0, 0x1c, 0x00, 0x00, 0xff, 0xff, 0xff
+.data1 	0xff, 0x8b, 0x15, 0xac, 0x1c, 0x00, 0x00, 0x2b
+.data1 	0x15, 0x84, 0x2c, 0x00, 0x00, 0x52, 0xe8, 0x3f
+.data1 	0x31, 0x00, 0x00, 0x59, 0x89, 0xc7, 0x8d, 0x45
+.data1 	0xf0, 0x50, 0xff, 0x75, 0x08, 0xe8, 0x4b, 0xe5
+.data1 	0xff, 0xff, 0x59, 0x59, 0x56, 0x57, 0xe8, 0x3d
+.data1 	0x34, 0x00, 0x00, 0x59, 0x59, 0x8d, 0x85, 0x54
+.data1 	0xff, 0xff, 0xff, 0x50, 0x68, 0x78, 0x2d, 0x00
+.data1 	0x00, 0xb9, 0x04, 0x00, 0x00, 0x00, 0xe8, 0x5d
+.data1 	0xcf, 0x00, 0x00, 0x8b, 0x95, 0x50, 0xff, 0xff
+.data1 	0xff, 0x89, 0x15, 0x88, 0x2d, 0x00, 0x00, 0x8b
+.data1 	0x95, 0x4c, 0xff, 0xff, 0xff, 0x89, 0x15, 0x74
+.data1 	0x2d, 0x00, 0x00, 0x8b, 0x95, 0x3c, 0xff, 0xff
+.data1 	0xff, 0x89, 0x15, 0xb0, 0x1c, 0x00, 0x00, 0x8b
+.data1 	0x7d, 0xf4, 0xc6, 0x85, 0x4b, 0xff, 0xff, 0xff
+.data1 	0x00, 0xff, 0x4d, 0xf8, 0x79, 0x48, 0x83, 0x7d
+.data1 	0xf0, 0x00, 0x0f, 0x88, 0xba, 0x00, 0x00, 0x00
+.data1 	0x68, 0x80, 0x00, 0x00, 0x00, 0x8d, 0x85, 0x6c
+.data1 	0xff, 0xff, 0xff, 0x50, 0xff, 0x75, 0xf0, 0xe8
+.data1 	0x94, 0xc1, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0x45, 0xec, 0x85, 0xc0, 0x79, 0x09, 0x83, 0x3d
+.data1 	0xf0, 0x27, 0x00, 0x00, 0x04, 0x74, 0xd9, 0x83
+.data1 	0x7d, 0xec, 0x00, 0x0f, 0x8e, 0x89, 0x00, 0x00
+.data1 	0x00, 0x8d, 0xbd, 0x6c, 0xff, 0xff, 0xff, 0x8b
+.data1 	0x55, 0xec, 0x4a, 0x89, 0x55, 0xf8, 0x8a, 0x07
+.data1 	0x47, 0x88, 0x85, 0x4b, 0xff, 0xff, 0xff, 0x80
+.data1 	0xbd, 0x4b, 0xff, 0xff, 0xff, 0x00, 0x74, 0xa1
+.data1 	0x83, 0x7d, 0x10, 0x00, 0x74, 0x32, 0x0f, 0xbe
+.data1 	0x85, 0x4b, 0xff, 0xff, 0xff, 0x03, 0x85, 0x40
+.data1 	0xff, 0xff, 0xff, 0x80, 0x38, 0x0a, 0x75, 0x20
+.data1 	0x8b, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x4a, 0x89
+.data1 	0x15, 0x84, 0x2c, 0x00, 0x00, 0x78, 0x06, 0xc6
+.data1 	0x06, 0x81, 0x46, 0xeb, 0x0b, 0xe8, 0xd3, 0x32
+.data1 	0x00, 0x00, 0x89, 0xc6, 0xc6, 0x06, 0x81, 0x46
+.data1 	0x8b, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x4a, 0x89
+.data1 	0x15, 0x84, 0x2c, 0x00, 0x00, 0x78, 0x0e, 0x8a
+.data1 	0x8d, 0x4b, 0xff, 0xff, 0xff, 0x88, 0x0e, 0x46
+.data1 	0xe9, 0x4c, 0xff, 0xff, 0xff, 0xe8, 0xab, 0x32
+.data1 	0x00, 0x00, 0x89, 0xc6, 0x8a, 0x8d, 0x4b, 0xff
+.data1 	0xff, 0xff, 0x88, 0x0e, 0x46, 0xe9, 0x37, 0xff
+.data1 	0xff, 0xff, 0x80, 0xbd, 0x4b, 0xff, 0xff, 0xff
+.data1 	0x0a, 0x75, 0x07, 0xff, 0x05, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x4e, 0x83, 0x7d, 0xf0, 0x00, 0x78, 0x09
+.data1 	0xff, 0x75, 0xf0, 0xe8, 0x40, 0xc0, 0x00, 0x00
+.data1 	0x59, 0x83, 0x7d, 0xf4, 0x00, 0x74, 0x09, 0xff
+.data1 	0x75, 0xf4, 0xe8, 0xaf, 0xad, 0x00, 0x00, 0x59
+.data1 	0x83, 0x7d, 0xfc, 0x00, 0x74, 0x0e, 0xff, 0x75
+.data1 	0xfc, 0xe8, 0xb6, 0x20, 0x00, 0x00, 0x59, 0xa3
+.data1 	0xa4, 0x2c, 0x00, 0x00, 0x83, 0x7d, 0x0c, 0x00
+.data1 	0x75, 0x19, 0x89, 0xf2, 0x2b, 0x15, 0xa8, 0x1c
+.data1 	0x00, 0x00, 0x6a, 0x00, 0x52, 0xff, 0xb5, 0x44
+.data1 	0xff, 0xff, 0xff, 0xe8, 0x11, 0x07, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x35, 0x70, 0x2d, 0x00
+.data1 	0x00, 0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x75, 0x10
+.data1 	0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85
+.data1 	0xd2, 0x74, 0x05, 0xe8, 0x6f, 0xda, 0xff, 0xff
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x56, 0x57, 0x8b, 0x75, 0x08, 0x0f
+.data1 	0xbe, 0x06, 0x46, 0x89, 0x45, 0xf8, 0x25, 0x07
+.data1 	0x00, 0x00, 0x00, 0x89, 0x45, 0xfc, 0x89, 0x75
+.data1 	0xf4, 0xc7, 0x45, 0xe4, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0f, 0xbe, 0x1e, 0xf6, 0x83, 0x9d, 0x22, 0x00
+.data1 	0x00, 0x0e, 0x75, 0x07, 0xc7, 0x45, 0xe4, 0x01
+.data1 	0x00, 0x00, 0x00, 0x6a, 0x3d, 0x56, 0xe8, 0x03
+.data1 	0x36, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc6, 0x46
+.data1 	0x83, 0x7d, 0xe4, 0x00, 0x74, 0x14, 0x8b, 0x55
+.data1 	0xf4, 0x0f, 0xbe, 0x02, 0x50, 0xe8, 0x16, 0x03
+.data1 	0x00, 0x00, 0x59, 0x89, 0x45, 0xe8, 0x31, 0xff
+.data1 	0xeb, 0x2e, 0xff, 0x75, 0xf4, 0xe8, 0x0a, 0x70
+.data1 	0x00, 0x00, 0x59, 0x89, 0xc7, 0x85, 0xff, 0x74
+.data1 	0x0d, 0x8b, 0x55, 0xf8, 0xf6, 0xc2, 0x20, 0x74
+.data1 	0x10, 0x80, 0x3f, 0x00, 0x75, 0x0b, 0x31, 0xff
+.data1 	0xc7, 0x45, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x07, 0xc7, 0x45, 0xe8, 0x01, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x15, 0x70, 0x2d, 0x00, 0x00, 0x2b, 0x15
+.data1 	0xa8, 0x1c, 0x00, 0x00, 0x89, 0x55, 0xe0, 0x83
+.data1 	0x7d, 0xe8, 0x00, 0x0f, 0x84, 0xd5, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7d, 0xfc, 0x03, 0x0f, 0x84, 0xcb
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xe4, 0x00, 0x74
+.data1 	0x20, 0xba, 0x40, 0x00, 0x00, 0x00, 0x23, 0x55
+.data1 	0xf8, 0x8b, 0x4d, 0xf4, 0x0f, 0xbe, 0x01, 0xff
+.data1 	0x75, 0x0c, 0x52, 0x50, 0xe8, 0x18, 0x03, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xe9, 0xa5, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xf8, 0xf6, 0xc2, 0x40, 0x74
+.data1 	0x07, 0xb8, 0x95, 0x20, 0x00, 0x00, 0xeb, 0x05
+.data1 	0xb8, 0x91, 0x1f, 0x00, 0x00, 0x89, 0x45, 0xdc
+.data1 	0x80, 0x3f, 0x00, 0x0f, 0x84, 0x85, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7d, 0x0c, 0x00, 0x74, 0x3d, 0x0f
+.data1 	0xbe, 0x07, 0x03, 0x45, 0xdc, 0x80, 0x38, 0x0a
+.data1 	0x75, 0x32, 0x8b, 0x15, 0x84, 0x2c, 0x00, 0x00
+.data1 	0x4a, 0x89, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x78
+.data1 	0x10, 0xa1, 0x70, 0x2d, 0x00, 0x00, 0xff, 0x05
+.data1 	0x70, 0x2d, 0x00, 0x00, 0xc6, 0x00, 0x81, 0xeb
+.data1 	0x13, 0xe8, 0xe7, 0x30, 0x00, 0x00, 0xa3, 0x70
+.data1 	0x2d, 0x00, 0x00, 0xff, 0x05, 0x70, 0x2d, 0x00
+.data1 	0x00, 0xc6, 0x00, 0x81, 0x8b, 0x15, 0x84, 0x2c
+.data1 	0x00, 0x00, 0x4a, 0x89, 0x15, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x78, 0x13, 0x8a, 0x07, 0x47, 0x8b, 0x1d
+.data1 	0x70, 0x2d, 0x00, 0x00, 0xff, 0x05, 0x70, 0x2d
+.data1 	0x00, 0x00, 0x88, 0x03, 0xeb, 0x92, 0xe8, 0xb2
+.data1 	0x30, 0x00, 0x00, 0xa3, 0x70, 0x2d, 0x00, 0x00
+.data1 	0x8a, 0x07, 0x47, 0x8b, 0x1d, 0x70, 0x2d, 0x00
+.data1 	0x00, 0xff, 0x05, 0x70, 0x2d, 0x00, 0x00, 0x88
+.data1 	0x03, 0xe9, 0x72, 0xff, 0xff, 0xff, 0x83, 0x7d
+.data1 	0xfc, 0x03, 0x75, 0x0c, 0x31, 0xc0, 0x83, 0x7d
+.data1 	0xe8, 0x00, 0x0f, 0x94, 0xc0, 0x89, 0x45, 0xe8
+.data1 	0x8b, 0x55, 0xf8, 0xf6, 0xc2, 0x40, 0x74, 0x11
+.data1 	0x8b, 0x55, 0xf4, 0x80, 0x3a, 0x40, 0x75, 0x36
+.data1 	0x83, 0x3d, 0xcc, 0x2c, 0x00, 0x00, 0x01, 0x74
+.data1 	0x2d, 0x83, 0x7d, 0xe8, 0x00, 0x75, 0x06, 0x83
+.data1 	0x7d, 0xfc, 0x01, 0x75, 0x21, 0xba, 0x40, 0x00
+.data1 	0x00, 0x00, 0x23, 0x55, 0xf8, 0x8b, 0x0d, 0x70
+.data1 	0x2d, 0x00, 0x00, 0x2b, 0x0d, 0xa8, 0x1c, 0x00
+.data1 	0x00, 0x52, 0x51, 0xff, 0x75, 0xe0, 0xe8, 0x16
+.data1 	0x05, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x83, 0x7d
+.data1 	0xe8, 0x00, 0x0f, 0x85, 0x17, 0x01, 0x00, 0x00
+.data1 	0x83, 0x7d, 0xfc, 0x01, 0x0f, 0x84, 0x0d, 0x01
+.data1 	0x00, 0x00, 0x83, 0x7d, 0xfc, 0x03, 0x74, 0x06
+.data1 	0x83, 0x7d, 0xfc, 0x02, 0x75, 0x10, 0xff, 0x75
+.data1 	0x0c, 0x56, 0xe8, 0xa6, 0xfa, 0xff, 0xff, 0x59
+.data1 	0x59, 0xe9, 0xf1, 0x00, 0x00, 0x00, 0x8b, 0x15
+.data1 	0xb0, 0x1c, 0x00, 0x00, 0x89, 0x55, 0xd8, 0xc7
+.data1 	0x05, 0xb0, 0x1c, 0x00, 0x00, 0xff, 0xff, 0xff
+.data1 	0xff, 0x6a, 0x00, 0x56, 0xe8, 0x84, 0xfa, 0xff
+.data1 	0xff, 0x59, 0x59, 0x83, 0x3d, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x75, 0x0f, 0xe8, 0xe4, 0x2f, 0x00
+.data1 	0x00, 0xa3, 0x70, 0x2d, 0x00, 0x00, 0xc6, 0x00
+.data1 	0x00, 0xeb, 0x09, 0x8b, 0x15, 0x70, 0x2d, 0x00
+.data1 	0x00, 0xc6, 0x02, 0x00, 0x8b, 0x55, 0xd8, 0x89
+.data1 	0x15, 0xb0, 0x1c, 0x00, 0x00, 0x8b, 0x55, 0xe0
+.data1 	0x03, 0x15, 0xa8, 0x1c, 0x00, 0x00, 0x89, 0x55
+.data1 	0xdc, 0x83, 0x7d, 0xfc, 0x05, 0x75, 0x45, 0x6a
+.data1 	0x00, 0xff, 0x75, 0xdc, 0xff, 0x75, 0xf4, 0xe8
+.data1 	0xee, 0x6b, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b
+.data1 	0x55, 0xdc, 0x2b, 0x15, 0x70, 0x2d, 0x00, 0x00
+.data1 	0x03, 0x15, 0x70, 0x2d, 0x00, 0x00, 0x89, 0x15
+.data1 	0x70, 0x2d, 0x00, 0x00, 0x8b, 0x55, 0xdc, 0x2b
+.data1 	0x15, 0x70, 0x2d, 0x00, 0x00, 0x2b, 0x15, 0x84
+.data1 	0x2c, 0x00, 0x00, 0xf7, 0xda, 0x89, 0x15, 0x84
+.data1 	0x2c, 0x00, 0x00, 0x83, 0x65, 0xf8, 0xdf, 0xe9
+.data1 	0xa4, 0xfd, 0xff, 0xff, 0x0f, 0xbe, 0x06, 0x3d
+.data1 	0x83, 0xff, 0xff, 0xff, 0x74, 0x1d, 0xff, 0x75
+.data1 	0xdc, 0x68, 0x40, 0x03, 0x00, 0x00, 0x68, 0x7c
+.data1 	0x23, 0x00, 0x00, 0xe8, 0x49, 0x65, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x6a, 0x00, 0xe8, 0x06, 0xd8
+.data1 	0xff, 0xff, 0x59, 0x8b, 0x55, 0xf8, 0xf6, 0xc2
+.data1 	0x20, 0x74, 0x07, 0xb8, 0x18, 0x03, 0x00, 0x00
+.data1 	0xeb, 0x05, 0xb8, 0x88, 0x2c, 0x00, 0x00, 0x89
+.data1 	0xf2, 0x2b, 0x55, 0xf4, 0x4a, 0x50, 0xff, 0x75
+.data1 	0xf4, 0x52, 0x68, 0x24, 0x03, 0x00, 0x00, 0xe8
+.data1 	0xdc, 0xd7, 0xff, 0xff, 0x83, 0xc4, 0x10, 0x83
+.data1 	0x7d, 0xfc, 0x01, 0x0f, 0x84, 0x69, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xd8, 0x01, 0x00, 0x00, 0x00
+.data1 	0x0f, 0xbe, 0x06, 0x46, 0x89, 0x45, 0xec, 0x3d
+.data1 	0x81, 0xff, 0xff, 0xff, 0x75, 0x03, 0x46, 0xeb
+.data1 	0xef, 0x83, 0x7d, 0xec, 0x84, 0x74, 0x06, 0x83
+.data1 	0x7d, 0xec, 0x85, 0x75, 0x1f, 0x83, 0x7d, 0xe8
+.data1 	0x00, 0x74, 0xdd, 0x83, 0x3d, 0x74, 0x2d, 0x00
+.data1 	0x00, 0x00, 0x74, 0xd4, 0x8b, 0x15, 0x74, 0x2d
+.data1 	0x00, 0x00, 0x8b, 0x12, 0x89, 0x15, 0x74, 0x2d
+.data1 	0x00, 0x00, 0xeb, 0xc4, 0x83, 0x7d, 0xec, 0x82
+.data1 	0x75, 0x15, 0x0f, 0xbe, 0x06, 0x46, 0x25, 0x07
+.data1 	0x00, 0x00, 0x00, 0x3d, 0x01, 0x00, 0x00, 0x00
+.data1 	0x74, 0xae, 0xff, 0x45, 0xd8, 0xeb, 0xa9, 0x83
+.data1 	0x7d, 0xec, 0x83, 0x75, 0xa3, 0xff, 0x4d, 0xd8
+.data1 	0x75, 0x9e, 0x89, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x80, 0x7d, 0x08, 0x21
+.data1 	0x75, 0x14, 0x83, 0x3d, 0xd4, 0x1b, 0x00, 0x00
+.data1 	0xff, 0x0f, 0x85, 0x5a, 0x00, 0x00, 0x00, 0x31
+.data1 	0xc0, 0xe9, 0x58, 0x00, 0x00, 0x00, 0x80, 0x7d
+.data1 	0x08, 0x40, 0x74, 0x06, 0x80, 0x7d, 0x08, 0x2a
+.data1 	0x75, 0x0f, 0x8b, 0x15, 0xd4, 0x2c, 0x00, 0x00
+.data1 	0x83, 0x3a, 0x00, 0x75, 0x3c, 0x31, 0xc0, 0xeb
+.data1 	0x3d, 0x0f, 0xbe, 0x45, 0x08, 0x2d, 0x31, 0x00
+.data1 	0x00, 0x00, 0x88, 0x45, 0x08, 0x0f, 0xbe, 0x5d
+.data1 	0x08, 0x83, 0xfb, 0x08, 0x77, 0x23, 0x8b, 0x35
+.data1 	0xd4, 0x2c, 0x00, 0x00, 0x8b, 0x06, 0x83, 0xc6
+.data1 	0x04, 0x85, 0xc0, 0x75, 0x04, 0x31, 0xc0, 0xeb
+.data1 	0x15, 0x0f, 0xbe, 0x45, 0x08, 0x48, 0x88, 0x45
+.data1 	0x08, 0x0f, 0xbe, 0x5d, 0x08, 0x85, 0xdb, 0x79
+.data1 	0xe3, 0xb8, 0x01, 0x00, 0x00, 0x00, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x38, 0x56
+.data1 	0x57, 0xe9, 0xe1, 0x02, 0x00, 0x00, 0x8b, 0x3d
+.data1 	0x9c, 0x2d, 0x00, 0x00, 0xeb, 0x16, 0x8b, 0x3d
+.data1 	0xbc, 0x2c, 0x00, 0x00, 0xeb, 0x0e, 0x8b, 0x3d
+.data1 	0xcc, 0x2c, 0x00, 0x00, 0xeb, 0x06, 0x8b, 0x3d
+.data1 	0xd4, 0x1b, 0x00, 0x00, 0x8d, 0x75, 0xfb, 0xc6
+.data1 	0x45, 0xfb, 0x00, 0xb9, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x89, 0xf8, 0x99, 0xf7, 0xf9, 0x83, 0xc2, 0x30
+.data1 	0x89, 0xd0, 0x0f, 0xbe, 0xc0, 0x4e, 0x88, 0x06
+.data1 	0x89, 0xf8, 0x99, 0xf7, 0xf9, 0x89, 0xc7, 0x85
+.data1 	0xff, 0x75, 0xe0, 0x80, 0x3e, 0x00, 0x0f, 0x84
+.data1 	0xa1, 0x02, 0x00, 0x00, 0x8b, 0x15, 0x84, 0x2c
+.data1 	0x00, 0x00, 0x4a, 0x89, 0x15, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x78, 0x13, 0x8a, 0x06, 0x46, 0x8b, 0x1d
+.data1 	0x70, 0x2d, 0x00, 0x00, 0xff, 0x05, 0x70, 0x2d
+.data1 	0x00, 0x00, 0x88, 0x03, 0xeb, 0xd5, 0xe8, 0xaa
+.data1 	0x2d, 0x00, 0x00, 0xa3, 0x70, 0x2d, 0x00, 0x00
+.data1 	0x8a, 0x06, 0x46, 0x8b, 0x1d, 0x70, 0x2d, 0x00
+.data1 	0x00, 0xff, 0x05, 0x70, 0x2d, 0x00, 0x00, 0x88
+.data1 	0x03, 0xeb, 0xb8, 0xc7, 0x45, 0xd4, 0x00, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x45, 0xd4, 0x80, 0xb8, 0x5c
+.data1 	0x1d, 0x00, 0x00, 0x00, 0x0f, 0x84, 0x4b, 0x02
+.data1 	0x00, 0x00, 0x80, 0xb8, 0x74, 0x2c, 0x00, 0x00
+.data1 	0x00, 0x74, 0x46, 0x8b, 0x15, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0x84, 0x2c, 0x00, 0x00
+.data1 	0x78, 0x19, 0x8b, 0x1d, 0x70, 0x2d, 0x00, 0x00
+.data1 	0x0f, 0xb6, 0x88, 0x5c, 0x1d, 0x00, 0x00, 0x51
+.data1 	0xff, 0x05, 0x70, 0x2d, 0x00, 0x00, 0x5a, 0x88
+.data1 	0x13, 0xeb, 0x1e, 0xe8, 0x45, 0x2d, 0x00, 0x00
+.data1 	0xa3, 0x70, 0x2d, 0x00, 0x00, 0x8b, 0x5d, 0xd4
+.data1 	0x0f, 0xb6, 0x8b, 0x5c, 0x1d, 0x00, 0x00, 0x51
+.data1 	0xff, 0x05, 0x70, 0x2d, 0x00, 0x00, 0x5a, 0x88
+.data1 	0x10, 0xff, 0x45, 0xd4, 0xeb, 0x9c, 0x83, 0x7d
+.data1 	0x10, 0x00, 0x74, 0x06, 0xc6, 0x45, 0xd3, 0x00
+.data1 	0xeb, 0x04, 0xc6, 0x45, 0xd3, 0x20, 0x83, 0x7d
+.data1 	0x0c, 0x00, 0x74, 0x0d, 0x83, 0x7d, 0x10, 0x00
+.data1 	0x74, 0x07, 0xb8, 0x95, 0x20, 0x00, 0x00, 0xeb
+.data1 	0x05, 0xb8, 0x91, 0x1f, 0x00, 0x00, 0x89, 0x45
+.data1 	0xc8, 0x8b, 0x15, 0xd4, 0x2c, 0x00, 0x00, 0x89
+.data1 	0x55, 0xcc, 0x8b, 0x45, 0xcc, 0x83, 0x45, 0xcc
+.data1 	0x04, 0x8b, 0x10, 0x89, 0xd6, 0x85, 0xd2, 0x0f
+.data1 	0x84, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x3e, 0x00
+.data1 	0x0f, 0x84, 0x7f, 0x00, 0x00, 0x00, 0x0f, 0xbe
+.data1 	0x06, 0x03, 0x45, 0xc8, 0x80, 0x38, 0x0a, 0x75
+.data1 	0x32, 0x8b, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x78, 0x10
+.data1 	0xa1, 0x70, 0x2d, 0x00, 0x00, 0xff, 0x05, 0x70
+.data1 	0x2d, 0x00, 0x00, 0xc6, 0x00, 0x81, 0xeb, 0x13
+.data1 	0xe8, 0xa8, 0x2c, 0x00, 0x00, 0xa3, 0x70, 0x2d
+.data1 	0x00, 0x00, 0xff, 0x05, 0x70, 0x2d, 0x00, 0x00
+.data1 	0xc6, 0x00, 0x81, 0x8b, 0x15, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0x84, 0x2c, 0x00, 0x00
+.data1 	0x78, 0x13, 0x8a, 0x06, 0x46, 0x8b, 0x1d, 0x70
+.data1 	0x2d, 0x00, 0x00, 0xff, 0x05, 0x70, 0x2d, 0x00
+.data1 	0x00, 0x88, 0x03, 0xeb, 0x98, 0xe8, 0x73, 0x2c
+.data1 	0x00, 0x00, 0xa3, 0x70, 0x2d, 0x00, 0x00, 0x8a
+.data1 	0x06, 0x46, 0x8b, 0x1d, 0x70, 0x2d, 0x00, 0x00
+.data1 	0xff, 0x05, 0x70, 0x2d, 0x00, 0x00, 0x88, 0x03
+.data1 	0xe9, 0x78, 0xff, 0xff, 0xff, 0x8b, 0x45, 0xcc
+.data1 	0x83, 0x38, 0x00, 0x0f, 0x84, 0x59, 0xff, 0xff
+.data1 	0xff, 0x8b, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x78, 0x15
+.data1 	0xa1, 0x70, 0x2d, 0x00, 0x00, 0xff, 0x05, 0x70
+.data1 	0x2d, 0x00, 0x00, 0x8a, 0x4d, 0xd3, 0x88, 0x08
+.data1 	0xe9, 0x35, 0xff, 0xff, 0xff, 0xe8, 0x23, 0x2c
+.data1 	0x00, 0x00, 0xa3, 0x70, 0x2d, 0x00, 0x00, 0xff
+.data1 	0x05, 0x70, 0x2d, 0x00, 0x00, 0x8a, 0x4d, 0xd3
+.data1 	0x88, 0x08, 0xe9, 0x1b, 0xff, 0xff, 0xff, 0x8b
+.data1 	0x35, 0x98, 0x2d, 0x00, 0x00, 0x83, 0x7d, 0x0c
+.data1 	0x00, 0x74, 0x0d, 0x83, 0x7d, 0x10, 0x00, 0x74
+.data1 	0x07, 0xb8, 0x95, 0x20, 0x00, 0x00, 0xeb, 0x05
+.data1 	0xb8, 0x91, 0x1f, 0x00, 0x00, 0x89, 0x45, 0xc8
+.data1 	0x80, 0x3e, 0x00, 0x0f, 0x84, 0xb4, 0x00, 0x00
+.data1 	0x00, 0x0f, 0xbe, 0x06, 0x03, 0x45, 0xc8, 0x80
+.data1 	0x38, 0x0a, 0x75, 0x32, 0x8b, 0x15, 0x84, 0x2c
+.data1 	0x00, 0x00, 0x4a, 0x89, 0x15, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x78, 0x10, 0xa1, 0x70, 0x2d, 0x00, 0x00
+.data1 	0xff, 0x05, 0x70, 0x2d, 0x00, 0x00, 0xc6, 0x00
+.data1 	0x81, 0xeb, 0x13, 0xe8, 0xb5, 0x2b, 0x00, 0x00
+.data1 	0xa3, 0x70, 0x2d, 0x00, 0x00, 0xff, 0x05, 0x70
+.data1 	0x2d, 0x00, 0x00, 0xc6, 0x00, 0x81, 0x8b, 0x15
+.data1 	0x84, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x84
+.data1 	0x2c, 0x00, 0x00, 0x78, 0x13, 0x8a, 0x06, 0x46
+.data1 	0x8b, 0x1d, 0x70, 0x2d, 0x00, 0x00, 0xff, 0x05
+.data1 	0x70, 0x2d, 0x00, 0x00, 0x88, 0x03, 0xeb, 0x98
+.data1 	0xe8, 0x80, 0x2b, 0x00, 0x00, 0xa3, 0x70, 0x2d
+.data1 	0x00, 0x00, 0x8a, 0x06, 0x46, 0x8b, 0x1d, 0x70
+.data1 	0x2d, 0x00, 0x00, 0xff, 0x05, 0x70, 0x2d, 0x00
+.data1 	0x00, 0x88, 0x03, 0xe9, 0x78, 0xff, 0xff, 0xff
+.data1 	0x0f, 0xbe, 0x45, 0x08, 0x2d, 0x31, 0x00, 0x00
+.data1 	0x00, 0x88, 0x45, 0x08, 0x0f, 0xbe, 0x5d, 0x08
+.data1 	0x83, 0xfb, 0x08, 0x77, 0x20, 0x0f, 0xbe, 0x5d
+.data1 	0x08, 0x8b, 0x15, 0xd4, 0x2c, 0x00, 0x00, 0x8b
+.data1 	0x34, 0x9a, 0xe9, 0x36, 0xff, 0xff, 0xff, 0x0f
+.data1 	0xbe, 0x45, 0x08, 0xbb, 0x44, 0x03, 0x00, 0x00
+.data1 	0xe9, 0x3f, 0xc7, 0x00, 0x00, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x56, 0x83, 0x3d, 0x88
+.data1 	0x2d, 0x00, 0x00, 0x00, 0x75, 0x07, 0xbe, 0x78
+.data1 	0x2d, 0x00, 0x00, 0xeb, 0x12, 0x6a, 0x10, 0xe8
+.data1 	0x1c, 0x28, 0x00, 0x00, 0x59, 0x89, 0xc6, 0x8b
+.data1 	0x15, 0x88, 0x2d, 0x00, 0x00, 0x89, 0x32, 0x89
+.data1 	0x35, 0x88, 0x2d, 0x00, 0x00, 0x8b, 0x15, 0x88
+.data1 	0x2d, 0x00, 0x00, 0xc7, 0x02, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x15, 0x88, 0x2d, 0x00, 0x00, 0x8b
+.data1 	0x4d, 0x08, 0x89, 0x4a, 0x04, 0x8b, 0x15, 0x88
+.data1 	0x2d, 0x00, 0x00, 0x8b, 0x4d, 0x0c, 0x89, 0x4a
+.data1 	0x08, 0x8b, 0x15, 0x88, 0x2d, 0x00, 0x00, 0x8b
+.data1 	0x4d, 0x10, 0x89, 0x4a, 0x0c, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x18, 0x56, 0x57
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xf4, 0x83, 0x3d
+.data1 	0x88, 0x2d, 0x00, 0x00, 0x00, 0x0f, 0x84, 0x1e
+.data1 	0x01, 0x00, 0x00, 0xc7, 0x45, 0xfc, 0x78, 0x2d
+.data1 	0x00, 0x00, 0x8b, 0x55, 0xfc, 0x8b, 0x4d, 0x08
+.data1 	0x8b, 0x72, 0x04, 0x01, 0xce, 0x83, 0x7a, 0x0c
+.data1 	0x00, 0x74, 0x07, 0xb8, 0x88, 0x2c, 0x00, 0x00
+.data1 	0xeb, 0x09, 0x8b, 0x15, 0xa8, 0x2d, 0x00, 0x00
+.data1 	0x8d, 0x42, 0x04, 0x89, 0x45, 0xe8, 0x8b, 0x55
+.data1 	0xfc, 0x8b, 0x4d, 0x08, 0x03, 0x4a, 0x08, 0x39
+.data1 	0xf1, 0x0f, 0x86, 0x96, 0x00, 0x00, 0x00, 0x89
+.data1 	0x75, 0xec, 0x0f, 0xbe, 0x06, 0x3d, 0x81, 0xff
+.data1 	0xff, 0xff, 0x75, 0x01, 0x46, 0x0f, 0xbe, 0x06
+.data1 	0x46, 0x50, 0xff, 0x75, 0xe8, 0xe8, 0x8c, 0x2e
+.data1 	0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x74, 0xce
+.data1 	0x8b, 0x55, 0xf4, 0x39, 0x55, 0xec, 0x77, 0x08
+.data1 	0x8b, 0x55, 0xe8, 0x80, 0x3a, 0x20, 0x74, 0x24
+.data1 	0x8b, 0x55, 0xec, 0xc6, 0x02, 0x00, 0x6a, 0x08
+.data1 	0xe8, 0xb5, 0x27, 0x00, 0x00, 0x59, 0x89, 0xc7
+.data1 	0x8b, 0x55, 0xf4, 0x89, 0x57, 0x04, 0x8b, 0x55
+.data1 	0x0c, 0x8b, 0x52, 0x04, 0x89, 0x3a, 0x8b, 0x55
+.data1 	0x0c, 0x89, 0x7a, 0x04, 0x8b, 0x55, 0xe8, 0x80
+.data1 	0x3a, 0x20, 0x75, 0x31, 0x8b, 0x55, 0xfc, 0x8b
+.data1 	0x4d, 0x08, 0x03, 0x4a, 0x08, 0x39, 0xf1, 0x76
+.data1 	0x24, 0x89, 0x75, 0xec, 0x0f, 0xbe, 0x06, 0x3d
+.data1 	0x81, 0xff, 0xff, 0xff, 0x75, 0x01, 0x46, 0x0f
+.data1 	0xbe, 0x06, 0x46, 0x50, 0xff, 0x75, 0xe8, 0xe8
+.data1 	0x22, 0x2e, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x75, 0xd2, 0x8b, 0x75, 0xec, 0x89, 0x75, 0xf4
+.data1 	0xe9, 0x59, 0xff, 0xff, 0xff, 0x8b, 0x45, 0xfc
+.data1 	0x8b, 0x10, 0x89, 0x55, 0xfc, 0x85, 0xd2, 0x0f
+.data1 	0x85, 0x25, 0xff, 0xff, 0xff, 0x8b, 0x55, 0xf4
+.data1 	0x80, 0x3a, 0x00, 0x75, 0x14, 0x8b, 0x55, 0xe8
+.data1 	0x80, 0x3a, 0x20, 0x0f, 0x84, 0x46, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x08, 0x39, 0x55, 0xf4, 0x76
+.data1 	0x3e, 0x6a, 0x08, 0xe8, 0x2a, 0x27, 0x00, 0x00
+.data1 	0x59, 0x89, 0xc7, 0x8b, 0x55, 0xf4, 0x89, 0x57
+.data1 	0x04, 0x8b, 0x55, 0x0c, 0x8b, 0x52, 0x04, 0x89
+.data1 	0x3a, 0x8b, 0x55, 0x0c, 0x89, 0x7a, 0x04, 0xeb
+.data1 	0x1e, 0x6a, 0x08, 0xe8, 0x0a, 0x27, 0x00, 0x00
+.data1 	0x59, 0x89, 0xc7, 0x8b, 0x55, 0xf4, 0x89, 0x57
+.data1 	0x04, 0x8b, 0x55, 0x0c, 0x8b, 0x52, 0x04, 0x89
+.data1 	0x3a, 0x8b, 0x55, 0x0c, 0x89, 0x7a, 0x04, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x14, 0x56, 0x57, 0x8b, 0x75, 0x08, 0x85, 0xf6
+.data1 	0x0f, 0x84, 0x3f, 0x01, 0x00, 0x00, 0x80, 0x3d
+.data1 	0x75, 0x2c, 0x00, 0x00, 0x00, 0x0f, 0x85, 0xdb
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x7e, 0x04, 0x80, 0x3f
+.data1 	0x7e, 0x75, 0x0c, 0x57, 0xe8, 0x28, 0x01, 0x00
+.data1 	0x00, 0x59, 0x89, 0xc7, 0x89, 0x46, 0x04, 0x8a
+.data1 	0x07, 0x47, 0x88, 0x45, 0xf3, 0x0f, 0xb6, 0xd0
+.data1 	0x84, 0xd2, 0x0f, 0x84, 0xb6, 0x00, 0x00, 0x00
+.data1 	0x80, 0x7d, 0xf3, 0x2a, 0x74, 0x12, 0x80, 0x7d
+.data1 	0xf3, 0x3f, 0x74, 0x0c, 0x80, 0x7d, 0xf3, 0x5b
+.data1 	0x74, 0x06, 0x80, 0x7d, 0xf3, 0x21, 0x75, 0xd7
+.data1 	0x8b, 0x15, 0x90, 0x2d, 0x00, 0x00, 0x89, 0x55
+.data1 	0xf8, 0xff, 0x05, 0x90, 0x2c, 0x00, 0x00, 0x83
+.data1 	0x3d, 0x94, 0x2d, 0x00, 0x00, 0x00, 0x75, 0x29
+.data1 	0xff, 0x76, 0x04, 0xe8, 0x90, 0xb8, 0x00, 0x00
+.data1 	0x59, 0x89, 0x45, 0xec, 0x3d, 0x00, 0x08, 0x00
+.data1 	0x00, 0x7d, 0x07, 0xb8, 0x00, 0x08, 0x00, 0x00
+.data1 	0xeb, 0x03, 0x8b, 0x45, 0xec, 0x50, 0xe8, 0xe5
+.data1 	0x25, 0x00, 0x00, 0x59, 0xa3, 0x94, 0x2d, 0x00
+.data1 	0x00, 0xff, 0x76, 0x04, 0xff, 0x35, 0x94, 0x2d
+.data1 	0x00, 0x00, 0xe8, 0x80, 0x02, 0x00, 0x00, 0x59
+.data1 	0x59, 0xff, 0x35, 0x94, 0x2d, 0x00, 0x00, 0xe8
+.data1 	0xfa, 0xa3, 0x00, 0x00, 0x59, 0xc7, 0x05, 0x94
+.data1 	0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x75, 0x10, 0xff, 0x35
+.data1 	0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74
+.data1 	0x05, 0xe8, 0xe9, 0xd0, 0xff, 0xff, 0x8b, 0x55
+.data1 	0xf8, 0x39, 0x15, 0x90, 0x2d, 0x00, 0x00, 0x75
+.data1 	0x26, 0x80, 0x3d, 0x7c, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x85, 0x50, 0x00, 0x00, 0x00, 0x8b, 0x15
+.data1 	0x90, 0x2d, 0x00, 0x00, 0x89, 0x32, 0xff, 0x76
+.data1 	0x04, 0xe8, 0x8a, 0x07, 0x00, 0x00, 0x59, 0x89
+.data1 	0x35, 0x90, 0x2d, 0x00, 0x00, 0xeb, 0x37, 0x8b
+.data1 	0x15, 0x90, 0x2d, 0x00, 0x00, 0xc7, 0x02, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x45, 0xf8, 0xff, 0x30
+.data1 	0xe8, 0xda, 0x04, 0x00, 0x00, 0x59, 0x89, 0x45
+.data1 	0xf4, 0x8b, 0x5d, 0xf8, 0x89, 0x03, 0x8b, 0x45
+.data1 	0xf4, 0x83, 0x38, 0x00, 0x74, 0x07, 0x8b, 0x10
+.data1 	0x89, 0x55, 0xf4, 0xeb, 0xf1, 0x8b, 0x55, 0xf4
+.data1 	0x89, 0x15, 0x90, 0x2d, 0x00, 0x00, 0x8b, 0x36
+.data1 	0xe9, 0xb9, 0xfe, 0xff, 0xff, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x81, 0xec, 0xb0, 0x00
+.data1 	0x00, 0x00, 0x56, 0x57, 0x8b, 0x75, 0x08, 0x56
+.data1 	0x80, 0x3e, 0x7e, 0x75, 0x07, 0xb8, 0x01, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x05, 0xb8, 0x03, 0x00, 0x00
+.data1 	0x00, 0x5a, 0x01, 0xd0, 0x89, 0x45, 0xfc, 0x8d
+.data1 	0x7d, 0xd4, 0x8b, 0x55, 0xfc, 0x80, 0x3a, 0x00
+.data1 	0x74, 0x20, 0x80, 0x3a, 0x2f, 0x74, 0x1b, 0x8d
+.data1 	0x55, 0xf3, 0x39, 0xd7, 0x72, 0x07, 0x89, 0xf0
+.data1 	0xe9, 0x8e, 0x01, 0x00, 0x00, 0x8b, 0x45, 0xfc
+.data1 	0xff, 0x45, 0xfc, 0x8a, 0x08, 0x88, 0x0f, 0x47
+.data1 	0xeb, 0xd8, 0xc6, 0x07, 0x00, 0x80, 0x7d, 0xd4
+.data1 	0x00, 0x0f, 0x85, 0x73, 0x00, 0x00, 0x00, 0x80
+.data1 	0x3e, 0x7e, 0x75, 0x6e, 0x68, 0x98, 0x03, 0x00
+.data1 	0x00, 0xe8, 0x0e, 0x66, 0x00, 0x00, 0x59, 0x89
+.data1 	0xc7, 0x85, 0xc0, 0x75, 0x07, 0x89, 0xf0, 0xe9
+.data1 	0x57, 0x01, 0x00, 0x00, 0x57, 0xe8, 0x36, 0xb7
+.data1 	0x00, 0x00, 0x59, 0x89, 0x85, 0x50, 0xff, 0xff
+.data1 	0xff, 0xff, 0x75, 0xfc, 0xe8, 0x27, 0xb7, 0x00
+.data1 	0x00, 0x59, 0x03, 0x85, 0x50, 0xff, 0xff, 0xff
+.data1 	0x40, 0x50, 0xe8, 0xfb, 0x24, 0x00, 0x00, 0x59
+.data1 	0x89, 0xc6, 0x57, 0x56, 0xe8, 0xef, 0xb6, 0x00
+.data1 	0x00, 0x59, 0x59, 0x89, 0xf2, 0x03, 0x95, 0x50
+.data1 	0xff, 0xff, 0xff, 0xff, 0x75, 0xfc, 0x52, 0xe8
+.data1 	0xdc, 0xb6, 0x00, 0x00, 0x59, 0x59, 0xc7, 0x05
+.data1 	0x70, 0x2c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x89, 0x75, 0x08, 0x89, 0xf0, 0xe9, 0x01, 0x01
+.data1 	0x00, 0x00, 0x6a, 0x01, 0x68, 0x8c, 0x03, 0x00
+.data1 	0x00, 0xe8, 0x53, 0x0a, 0x00, 0x00, 0x59, 0x59
+.data1 	0x8d, 0x85, 0x54, 0xff, 0xff, 0xff, 0x50, 0x8d
+.data1 	0x45, 0xd4, 0x50, 0xe8, 0xc8, 0xb6, 0x00, 0x00
+.data1 	0x59, 0x5a, 0x89, 0xc7, 0x01, 0xd7, 0x68, 0x80
+.data1 	0x00, 0x00, 0x00, 0x8d, 0x85, 0x54, 0xff, 0xff
+.data1 	0xff, 0x50, 0xe8, 0x29, 0x07, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x0f, 0x84, 0xbb, 0x00, 0x00
+.data1 	0x00, 0x0f, 0xbe, 0x85, 0x54, 0xff, 0xff, 0xff
+.data1 	0x0f, 0xbe, 0x5d, 0xd4, 0x39, 0xd8, 0x75, 0xd6
+.data1 	0x8d, 0x85, 0x54, 0xff, 0xff, 0xff, 0x50, 0x8d
+.data1 	0x45, 0xd4, 0x50, 0xe8, 0x5c, 0x2b, 0x00, 0x00
+.data1 	0x59, 0x59, 0x85, 0xc0, 0x74, 0xc0, 0x80, 0x3f
+.data1 	0x3a, 0x75, 0xbb, 0xc7, 0x85, 0x50, 0xff, 0xff
+.data1 	0xff, 0x04, 0x00, 0x00, 0x00, 0x47, 0x80, 0x3f
+.data1 	0x00, 0x74, 0x05, 0x80, 0x3f, 0x3a, 0x75, 0xf5
+.data1 	0xff, 0x8d, 0x50, 0xff, 0xff, 0xff, 0x83, 0xbd
+.data1 	0x50, 0xff, 0xff, 0xff, 0x00, 0x7f, 0xe6, 0x80
+.data1 	0x3f, 0x00, 0x0f, 0x84, 0x64, 0x00, 0x00, 0x00
+.data1 	0x47, 0x89, 0xfe, 0x80, 0x3e, 0x00, 0x74, 0x0d
+.data1 	0x80, 0x3e, 0x0a, 0x74, 0x08, 0x80, 0x3e, 0x3a
+.data1 	0x74, 0x03, 0x46, 0xeb, 0xee, 0xc6, 0x06, 0x00
+.data1 	0x89, 0xf2, 0x29, 0xfa, 0x89, 0x95, 0x50, 0xff
+.data1 	0xff, 0xff, 0xff, 0x75, 0xfc, 0xe8, 0x26, 0xb6
+.data1 	0x00, 0x00, 0x59, 0x03, 0x85, 0x50, 0xff, 0xff
+.data1 	0xff, 0x40, 0x50, 0xe8, 0xfa, 0x23, 0x00, 0x00
+.data1 	0x59, 0x89, 0xc6, 0x57, 0x56, 0xe8, 0xee, 0xb5
+.data1 	0x00, 0x00, 0x59, 0x59, 0x89, 0xf2, 0x03, 0x95
+.data1 	0x50, 0xff, 0xff, 0xff, 0xff, 0x75, 0xfc, 0x52
+.data1 	0xe8, 0xdb, 0xb5, 0x00, 0x00, 0x59, 0x59, 0xc7
+.data1 	0x05, 0x70, 0x2c, 0x00, 0x00, 0x01, 0x00, 0x00
+.data1 	0x00, 0x89, 0x75, 0x08, 0xe8, 0x31, 0x0b, 0x00
+.data1 	0x00, 0x89, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x4c, 0x56, 0x57, 0xc7
+.data1 	0x45, 0xec, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x55
+.data1 	0x0c, 0x89, 0x55, 0xf4, 0x8b, 0x75, 0x0c, 0x80
+.data1 	0x3e, 0x2a, 0x74, 0x05, 0x80, 0x3e, 0x3f, 0x75
+.data1 	0x0c, 0xc7, 0x45, 0xec, 0x01, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x65, 0x00, 0x00, 0x00, 0x80, 0x3e, 0x5b
+.data1 	0x75, 0x31, 0x89, 0xf7, 0x47, 0x80, 0x3f, 0x21
+.data1 	0x75, 0x01, 0x47, 0x0f, 0xbe, 0x07, 0x3d, 0x81
+.data1 	0xff, 0xff, 0xff, 0x75, 0x01, 0x47, 0x80, 0x3f
+.data1 	0x2f, 0x0f, 0x84, 0x43, 0x00, 0x00, 0x00, 0x80
+.data1 	0x3f, 0x00, 0x74, 0x3e, 0x47, 0x80, 0x3f, 0x5d
+.data1 	0x75, 0xe1, 0xc7, 0x45, 0xec, 0x01, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x2f, 0x80, 0x3e, 0x21, 0x75, 0x1a
+.data1 	0x80, 0x7e, 0x01, 0x21, 0x75, 0x14, 0x39, 0x75
+.data1 	0x0c, 0x74, 0x06, 0x80, 0x7e, 0xff, 0x2f, 0x75
+.data1 	0x09, 0xc7, 0x45, 0xec, 0x01, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x10, 0x80, 0x3e, 0x00, 0x74, 0x22, 0x0f
+.data1 	0xbe, 0x06, 0x3d, 0x81, 0xff, 0xff, 0xff, 0x75
+.data1 	0x01, 0x46, 0x80, 0x3e, 0x2f, 0x75, 0x0c, 0x83
+.data1 	0x7d, 0xec, 0x00, 0x75, 0x0c, 0x8d, 0x56, 0x01
+.data1 	0x89, 0x55, 0xf4, 0x46, 0xe9, 0x6e, 0xff, 0xff
+.data1 	0xff, 0x83, 0x7d, 0xec, 0x00, 0x0f, 0x85, 0x5e
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x15, 0x94, 0x2d, 0x00
+.data1 	0x00, 0x39, 0x55, 0x08, 0x74, 0x03, 0xff, 0x45
+.data1 	0xec, 0x8b, 0x75, 0x0c, 0x0f, 0xbe, 0x06, 0x3d
+.data1 	0x81, 0xff, 0xff, 0xff, 0x75, 0x01, 0x46, 0x8b
+.data1 	0x55, 0x08, 0x8a, 0x0e, 0x88, 0x0a, 0xff, 0x45
+.data1 	0x08, 0x80, 0x3e, 0x00, 0x74, 0x03, 0x46, 0xeb
+.data1 	0xe3, 0x83, 0x7d, 0xec, 0x00, 0x74, 0x19, 0x8d
+.data1 	0x45, 0xc8, 0x50, 0xff, 0x35, 0x94, 0x2d, 0x00
+.data1 	0x00, 0xe8, 0xb2, 0xb3, 0x00, 0x00, 0x59, 0x59
+.data1 	0x85, 0xc0, 0x0f, 0x88, 0x91, 0x01, 0x00, 0x00
+.data1 	0xff, 0x35, 0x94, 0x2d, 0x00, 0x00, 0xe8, 0x8a
+.data1 	0x01, 0x00, 0x00, 0x59, 0xe9, 0x80, 0x01, 0x00
+.data1 	0x00, 0x89, 0x75, 0xf0, 0x8b, 0x55, 0x0c, 0x39
+.data1 	0x55, 0xf4, 0x74, 0x20, 0x8b, 0x75, 0x0c, 0x39
+.data1 	0x75, 0xf4, 0x76, 0x18, 0x0f, 0xbe, 0x06, 0x3d
+.data1 	0x81, 0xff, 0xff, 0xff, 0x75, 0x01, 0x46, 0x8a
+.data1 	0x06, 0x46, 0x8b, 0x55, 0x08, 0x88, 0x02, 0xff
+.data1 	0x45, 0x08, 0xeb, 0xe3, 0x8b, 0x15, 0x94, 0x2d
+.data1 	0x00, 0x00, 0x39, 0x55, 0x08, 0x75, 0x07, 0xbe
+.data1 	0xa4, 0x03, 0x00, 0x00, 0xeb, 0x2d, 0x8b, 0x15
+.data1 	0x94, 0x2d, 0x00, 0x00, 0x83, 0xc2, 0x01, 0x39
+.data1 	0x55, 0x08, 0x75, 0x12, 0x8b, 0x15, 0x94, 0x2d
+.data1 	0x00, 0x00, 0x80, 0x3a, 0x2f, 0x75, 0x07, 0xbe
+.data1 	0xa0, 0x03, 0x00, 0x00, 0xeb, 0x0d, 0x8b, 0x35
+.data1 	0x94, 0x2d, 0x00, 0x00, 0x8b, 0x55, 0x08, 0xc6
+.data1 	0x42, 0xff, 0x00, 0x56, 0xe8, 0x07, 0xb3, 0x00
+.data1 	0x00, 0x59, 0x89, 0x45, 0xc4, 0x85, 0xc0, 0x0f
+.data1 	0x84, 0x04, 0x01, 0x00, 0x00, 0x8b, 0x15, 0x94
+.data1 	0x2d, 0x00, 0x00, 0x39, 0x55, 0x08, 0x74, 0x07
+.data1 	0x8b, 0x55, 0x08, 0xc6, 0x42, 0xff, 0x2f, 0x8b
+.data1 	0x55, 0xf0, 0x80, 0x3a, 0x00, 0x75, 0x09, 0xc7
+.data1 	0x45, 0xbc, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x10
+.data1 	0xc7, 0x45, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xf0, 0xc6, 0x02, 0x00, 0xff, 0x45, 0xf0
+.data1 	0xc7, 0x45, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xf4, 0x80, 0x3a, 0x2e, 0x74, 0x10, 0x0f
+.data1 	0xbe, 0x02, 0x3d, 0x81, 0xff, 0xff, 0xff, 0x75
+.data1 	0x09, 0x80, 0x7a, 0x01, 0x2e, 0x75, 0x03, 0xff
+.data1 	0x45, 0xb8, 0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00
+.data1 	0x5a, 0x85, 0xd2, 0x0f, 0x85, 0x8a, 0x00, 0x00
+.data1 	0x00, 0xff, 0x75, 0xc4, 0xe8, 0xa7, 0xb2, 0x00
+.data1 	0x00, 0x59, 0x89, 0x45, 0xc0, 0x85, 0xc0, 0x0f
+.data1 	0x84, 0x76, 0x00, 0x00, 0x00, 0x80, 0x78, 0x05
+.data1 	0x2e, 0x75, 0x06, 0x83, 0x7d, 0xb8, 0x00, 0x74
+.data1 	0xd1, 0x8b, 0x55, 0xc0, 0x83, 0xc2, 0x05, 0x52
+.data1 	0xff, 0x75, 0xf4, 0xe8, 0x75, 0x01, 0x00, 0x00
+.data1 	0x59, 0x59, 0x85, 0xc0, 0x74, 0xbc, 0x83, 0x7d
+.data1 	0xbc, 0x00, 0x74, 0x1f, 0x8b, 0x55, 0xc0, 0x83
+.data1 	0xc2, 0x05, 0x52, 0xff, 0x75, 0x08, 0xe8, 0x85
+.data1 	0xb3, 0x00, 0x00, 0x59, 0x59, 0xff, 0x35, 0x94
+.data1 	0x2d, 0x00, 0x00, 0xe8, 0x4d, 0x00, 0x00, 0x00
+.data1 	0x59, 0xeb, 0x97, 0x8b, 0x75, 0x08, 0x8b, 0x55
+.data1 	0xc0, 0x83, 0xc2, 0x05, 0x89, 0x55, 0xb4, 0x8b
+.data1 	0x45, 0xb4, 0xff, 0x45, 0xb4, 0x0f, 0xb6, 0x10
+.data1 	0x88, 0x16, 0x46, 0x84, 0xd2, 0x75, 0xf0, 0xc6
+.data1 	0x46, 0xff, 0x2f, 0xff, 0x75, 0xf0, 0x56, 0xe8
+.data1 	0x8b, 0xfd, 0xff, 0xff, 0x59, 0x59, 0xe9, 0x67
+.data1 	0xff, 0xff, 0xff, 0xff, 0x75, 0xc4, 0xe8, 0x8d
+.data1 	0xb1, 0x00, 0x00, 0x59, 0x83, 0x7d, 0xbc, 0x00
+.data1 	0x75, 0x07, 0x8b, 0x55, 0xf0, 0xc6, 0x42, 0xff
+.data1 	0x2f, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0x57, 0xff, 0x75, 0x08, 0xe8, 0x3e, 0xb3
+.data1 	0x00, 0x00, 0x59, 0x40, 0x50, 0xe8, 0x18, 0x21
+.data1 	0x00, 0x00, 0x59, 0x89, 0xc7, 0xff, 0x75, 0x08
+.data1 	0x57, 0xe8, 0x0a, 0xb3, 0x00, 0x00, 0x59, 0x59
+.data1 	0x6a, 0x08, 0xe8, 0x03, 0x21, 0x00, 0x00, 0x59
+.data1 	0x89, 0xc6, 0x89, 0x7e, 0x04, 0x8b, 0x15, 0x90
+.data1 	0x2d, 0x00, 0x00, 0x89, 0x32, 0x89, 0x35, 0x90
+.data1 	0x2d, 0x00, 0x00, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0x57, 0x31, 0xff, 0x8b, 0x75
+.data1 	0x08, 0x85, 0xf6, 0x74, 0x05, 0x47, 0x8b, 0x36
+.data1 	0xeb, 0xf7, 0x57, 0xff, 0x75, 0x08, 0xe8, 0x06
+.data1 	0x00, 0x00, 0x00, 0x59, 0x59, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x14, 0x56
+.data1 	0x57, 0x83, 0x7d, 0x0c, 0x01, 0x7f, 0x08, 0x8b
+.data1 	0x45, 0x08, 0xe9, 0x82, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x0c, 0xd1, 0xfa, 0x89, 0x55, 0xf0, 0x8b
+.data1 	0x75, 0x08, 0x89, 0x55, 0xec, 0xff, 0x4d, 0xec
+.data1 	0x78, 0x07, 0x89, 0x75, 0xf8, 0x8b, 0x36, 0xeb
+.data1 	0xf4, 0x8b, 0x45, 0xf8, 0xc7, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0xff, 0x75, 0xf0, 0xff, 0x75, 0x08
+.data1 	0xe8, 0xbc, 0xff, 0xff, 0xff, 0x59, 0x59, 0x89
+.data1 	0x45, 0xf8, 0x8b, 0x55, 0x0c, 0x2b, 0x55, 0xf0
+.data1 	0x52, 0x56, 0xe8, 0xaa, 0xff, 0xff, 0xff, 0x59
+.data1 	0x59, 0x89, 0xc6, 0x8d, 0x7d, 0x08, 0x8b, 0x55
+.data1 	0xf8, 0xff, 0x72, 0x04, 0xff, 0x76, 0x04, 0xe8
+.data1 	0x4c, 0xb2, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x79, 0x11, 0x89, 0x37, 0x89, 0xf7, 0x8b, 0x37
+.data1 	0x85, 0xf6, 0x75, 0xe2, 0x8b, 0x55, 0xf8, 0x89
+.data1 	0x17, 0xeb, 0x13, 0x8b, 0x55, 0xf8, 0x89, 0x17
+.data1 	0x8b, 0x7d, 0xf8, 0x8b, 0x17, 0x89, 0x55, 0xf8
+.data1 	0x85, 0xd2, 0x75, 0xca, 0x89, 0x37, 0x8b, 0x45
+.data1 	0x08, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0x8b, 0x75, 0x08, 0x80, 0x3e, 0x21, 0x75
+.data1 	0x1d, 0x80, 0x7e, 0x01, 0x21, 0x75, 0x17, 0x6a
+.data1 	0x01, 0xff, 0x75, 0x0c, 0x8d, 0x46, 0x02, 0x50
+.data1 	0xe8, 0x17, 0x00, 0x00, 0x00, 0x59, 0x59, 0x5a
+.data1 	0x29, 0xc2, 0x89, 0xd0, 0xeb, 0x0b, 0xff, 0x75
+.data1 	0x0c, 0x56, 0xe8, 0x05, 0x00, 0x00, 0x00, 0x59
+.data1 	0x59, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x1c, 0x56, 0x57, 0x8b, 0x75, 0x08, 0x8b
+.data1 	0x7d, 0x0c, 0xe9, 0x64, 0x01, 0x00, 0x00, 0x0f
+.data1 	0xbe, 0x07, 0x47, 0x0f, 0xbe, 0x1e, 0x46, 0x39
+.data1 	0xd8, 0x0f, 0x84, 0x54, 0x01, 0x00, 0x00, 0x31
+.data1 	0xc0, 0xe9, 0x6e, 0x01, 0x00, 0x00, 0x8a, 0x07
+.data1 	0x47, 0x84, 0xc0, 0x0f, 0x85, 0x42, 0x01, 0x00
+.data1 	0x00, 0x31, 0xc0, 0xe9, 0x5c, 0x01, 0x00, 0x00
+.data1 	0x8a, 0x0e, 0x88, 0x4d, 0xf7, 0x0f, 0xbe, 0x45
+.data1 	0xf7, 0x3d, 0x81, 0xff, 0xff, 0xff, 0x74, 0x2c
+.data1 	0x80, 0x7d, 0xf7, 0x3f, 0x74, 0x26, 0x80, 0x7d
+.data1 	0xf7, 0x2a, 0x74, 0x20, 0x80, 0x7d, 0xf7, 0x5b
+.data1 	0x74, 0x1a, 0x0f, 0xbe, 0x07, 0x0f, 0xbe, 0x5d
+.data1 	0xf7, 0x39, 0xd8, 0x74, 0x0f, 0x80, 0x3f, 0x00
+.data1 	0x75, 0x07, 0x31, 0xc0, 0xe9, 0x23, 0x01, 0x00
+.data1 	0x00, 0x47, 0xeb, 0xe6, 0x57, 0x56, 0xe8, 0x81
+.data1 	0xff, 0xff, 0xff, 0x59, 0x59, 0x85, 0xc0, 0x74
+.data1 	0x0a, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xe9, 0x09
+.data1 	0x01, 0x00, 0x00, 0x8a, 0x07, 0x47, 0x84, 0xc0
+.data1 	0x75, 0xe2, 0x31, 0xc0, 0xe9, 0xfb, 0x00, 0x00
+.data1 	0x00, 0x89, 0x75, 0xf0, 0x80, 0x3e, 0x21, 0x75
+.data1 	0x03, 0xff, 0x45, 0xf0, 0x8b, 0x55, 0xf0, 0x80
+.data1 	0x3a, 0x00, 0x0f, 0x84, 0xb3, 0x00, 0x00, 0x00
+.data1 	0x0f, 0xbe, 0x02, 0x3d, 0x81, 0xff, 0xff, 0xff
+.data1 	0x75, 0x03, 0xff, 0x45, 0xf0, 0xff, 0x45, 0xf0
+.data1 	0x8b, 0x55, 0xf0, 0x80, 0x3a, 0x5d, 0x75, 0xdc
+.data1 	0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, 0x00, 0x80
+.data1 	0x3e, 0x21, 0x75, 0x04, 0xff, 0x45, 0xec, 0x46
+.data1 	0xc7, 0x45, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x8a
+.data1 	0x07, 0x47, 0x88, 0x45, 0xe7, 0x8a, 0x26, 0x46
+.data1 	0x88, 0x65, 0xf7, 0x0f, 0xbe, 0x45, 0xf7, 0x3d
+.data1 	0x81, 0xff, 0xff, 0xff, 0x75, 0x06, 0x8a, 0x06
+.data1 	0x46, 0x88, 0x45, 0xf7, 0x80, 0x3e, 0x2d, 0x75
+.data1 	0x33, 0x80, 0x7e, 0x01, 0x5d, 0x74, 0x2d, 0x46
+.data1 	0x0f, 0xbe, 0x06, 0x3d, 0x81, 0xff, 0xff, 0xff
+.data1 	0x75, 0x01, 0x46, 0x0f, 0xbe, 0x45, 0xe7, 0x0f
+.data1 	0xbe, 0x5d, 0xf7, 0x39, 0xd8, 0x7c, 0x12, 0x0f
+.data1 	0xbe, 0x06, 0x0f, 0xbe, 0x5d, 0xe7, 0x39, 0xd8
+.data1 	0x7c, 0x07, 0xc7, 0x45, 0xe8, 0x01, 0x00, 0x00
+.data1 	0x00, 0x46, 0xeb, 0x13, 0x0f, 0xbe, 0x45, 0xe7
+.data1 	0x0f, 0xbe, 0x5d, 0xf7, 0x39, 0xd8, 0x75, 0x07
+.data1 	0xc7, 0x45, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x8a
+.data1 	0x06, 0x46, 0x88, 0x45, 0xf7, 0x0f, 0xbe, 0xc0
+.data1 	0x3d, 0x5d, 0x00, 0x00, 0x00, 0x75, 0x94, 0x8b
+.data1 	0x55, 0xec, 0x39, 0x55, 0xe8, 0x75, 0x14, 0x31
+.data1 	0xc0, 0xeb, 0x31, 0x0f, 0xbe, 0x07, 0x47, 0x0f
+.data1 	0xbe, 0x5d, 0xf7, 0x39, 0xd8, 0x74, 0x04, 0x31
+.data1 	0xc0, 0xeb, 0x21, 0x8a, 0x06, 0x46, 0x88, 0x45
+.data1 	0xf7, 0x0f, 0xbe, 0xc0, 0xbb, 0xa8, 0x03, 0x00
+.data1 	0x00, 0xe9, 0xfe, 0xbc, 0x00, 0x00, 0x80, 0x3f
+.data1 	0x00, 0x74, 0x04, 0x31, 0xc0, 0xeb, 0x05, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x00, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x75, 0x08
+.data1 	0x0f, 0xbe, 0x06, 0x3d, 0x81, 0xff, 0xff, 0xff
+.data1 	0x74, 0x09, 0x8a, 0x06, 0x46, 0x84, 0xc0, 0x75
+.data1 	0xef, 0xeb, 0x1d, 0x89, 0xf7, 0x80, 0x3e, 0x00
+.data1 	0x74, 0x13, 0x0f, 0xbe, 0x06, 0x3d, 0x81, 0xff
+.data1 	0xff, 0xff, 0x75, 0x01, 0x46, 0x8a, 0x06, 0x46
+.data1 	0x88, 0x07, 0x47, 0xeb, 0xe8, 0xc6, 0x07, 0x00
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x14, 0x8d, 0x45, 0xf4, 0x50, 0xe8, 0xfc
+.data1 	0x1e, 0x00, 0x00, 0x59, 0x8b, 0x55, 0x08, 0x8b
+.data1 	0x52, 0x0c, 0x89, 0x15, 0x74, 0x2d, 0x00, 0x00
+.data1 	0x8b, 0x15, 0xa8, 0x1c, 0x00, 0x00, 0x89, 0x15
+.data1 	0x70, 0x2d, 0x00, 0x00, 0x8b, 0x15, 0xac, 0x1c
+.data1 	0x00, 0x00, 0x89, 0x15, 0x84, 0x2c, 0x00, 0x00
+.data1 	0xc7, 0x05, 0x88, 0x2d, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x55, 0x08, 0x6a, 0x01, 0xff
+.data1 	0x72, 0x08, 0xe8, 0xe6, 0xea, 0xff, 0xff, 0x59
+.data1 	0x59, 0x8b, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x78, 0x10
+.data1 	0xa1, 0x70, 0x2d, 0x00, 0x00, 0xff, 0x05, 0x70
+.data1 	0x2d, 0x00, 0x00, 0xc6, 0x00, 0x00, 0xeb, 0x13
+.data1 	0xe8, 0x30, 0x20, 0x00, 0x00, 0xa3, 0x70, 0x2d
+.data1 	0x00, 0x00, 0xff, 0x05, 0x70, 0x2d, 0x00, 0x00
+.data1 	0xc6, 0x00, 0x00, 0x8b, 0x15, 0xac, 0x1c, 0x00
+.data1 	0x00, 0x2b, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x52
+.data1 	0xe8, 0x8d, 0x1d, 0x00, 0x00, 0x59, 0x89, 0x45
+.data1 	0xec, 0xff, 0x75, 0x0c, 0xff, 0x75, 0xec, 0xe8
+.data1 	0x51, 0xfd, 0xff, 0xff, 0x59, 0x59, 0x89, 0x45
+.data1 	0xf0, 0x8d, 0x45, 0xf4, 0x50, 0xe8, 0x85, 0x1e
+.data1 	0x00, 0x00, 0x59, 0x8b, 0x45, 0xf0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x56, 0x57
+.data1 	0x8b, 0x75, 0x08, 0x8b, 0x55, 0x0c, 0x89, 0x55
+.data1 	0xf8, 0xff, 0x4d, 0xf8, 0x83, 0x7d, 0xf8, 0x00
+.data1 	0x7e, 0x41, 0x8b, 0x15, 0xac, 0x2d, 0x00, 0x00
+.data1 	0x4a, 0x89, 0x15, 0xac, 0x2d, 0x00, 0x00, 0x78
+.data1 	0x10, 0xa1, 0xb0, 0x2d, 0x00, 0x00, 0xff, 0x05
+.data1 	0xb0, 0x2d, 0x00, 0x00, 0x0f, 0xbe, 0x00, 0xeb
+.data1 	0x05, 0xe8, 0x50, 0x00, 0x00, 0x00, 0x89, 0xc7
+.data1 	0x81, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x75, 0x09
+.data1 	0x39, 0x75, 0x08, 0x75, 0x0e, 0x31, 0xc0, 0xeb
+.data1 	0x10, 0x89, 0xfa, 0x88, 0x16, 0x46, 0x83, 0xff
+.data1 	0x0a, 0x75, 0xb6, 0xc6, 0x06, 0x00, 0x8b, 0x45
+.data1 	0x08, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x8b, 0x15, 0xac, 0x2d, 0x00, 0x00, 0x4a, 0x89
+.data1 	0x15, 0xac, 0x2d, 0x00, 0x00, 0x78, 0x10, 0xa1
+.data1 	0xb0, 0x2d, 0x00, 0x00, 0xff, 0x05, 0xb0, 0x2d
+.data1 	0x00, 0x00, 0x0f, 0xbe, 0x00, 0xeb, 0x05, 0xe8
+.data1 	0x02, 0x00, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x18, 0x56, 0x57, 0x83, 0x3d
+.data1 	0xcc, 0x31, 0x00, 0x00, 0x00, 0x74, 0x3e, 0x8b
+.data1 	0x15, 0xcc, 0x31, 0x00, 0x00, 0x89, 0x15, 0xb0
+.data1 	0x2d, 0x00, 0x00, 0xc7, 0x05, 0xcc, 0x31, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x15, 0xd0
+.data1 	0x31, 0x00, 0x00, 0x89, 0x15, 0xac, 0x2d, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0xac, 0x2d, 0x00, 0x00
+.data1 	0x78, 0x13, 0xa1, 0xb0, 0x2d, 0x00, 0x00, 0xff
+.data1 	0x05, 0xb0, 0x2d, 0x00, 0x00, 0x0f, 0xbe, 0x00
+.data1 	0xe9, 0xe0, 0x01, 0x00, 0x00, 0x83, 0x3d, 0xac
+.data1 	0x2d, 0x00, 0x00, 0x9d, 0x74, 0x0c, 0x8b, 0x15
+.data1 	0xa8, 0x1b, 0x00, 0x00, 0x83, 0x7a, 0x14, 0x00
+.data1 	0x75, 0x0a, 0xb8, 0x7f, 0xff, 0xff, 0xff, 0xe9
+.data1 	0xc1, 0x01, 0x00, 0x00, 0x68, 0x68, 0x23, 0x00
+.data1 	0x00, 0xe8, 0x34, 0x54, 0x00, 0x00, 0x59, 0x68
+.data1 	0x7c, 0x23, 0x00, 0x00, 0xe8, 0x29, 0x54, 0x00
+.data1 	0x00, 0x59, 0x83, 0x3d, 0xac, 0x1b, 0x00, 0x00
+.data1 	0x00, 0x0f, 0x84, 0x7a, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x15, 0xa8, 0x1b, 0x00, 0x00, 0x8b, 0x52, 0x14
+.data1 	0x89, 0x15, 0xb0, 0x2d, 0x00, 0x00, 0x89, 0xd6
+.data1 	0x8b, 0x15, 0xac, 0x1b, 0x00, 0x00, 0x89, 0x55
+.data1 	0xf0, 0xc7, 0x05, 0xac, 0x1b, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0xff, 0x75, 0xf0, 0xe8, 0x16
+.data1 	0x87, 0x00, 0x00, 0x59, 0x89, 0x45, 0xec, 0x85
+.data1 	0xc0, 0x75, 0x14, 0xc7, 0x05, 0xac, 0x2d, 0x00
+.data1 	0x00, 0x9d, 0xff, 0xff, 0xff, 0xb8, 0x7f, 0xff
+.data1 	0xff, 0xff, 0xe9, 0x56, 0x01, 0x00, 0x00, 0xff
+.data1 	0x75, 0xec, 0x56, 0xe8, 0xf8, 0xad, 0x00, 0x00
+.data1 	0x59, 0x59, 0xff, 0x75, 0xec, 0xe8, 0xb4, 0x99
+.data1 	0x00, 0x00, 0x59, 0x56, 0xe8, 0x07, 0xae, 0x00
+.data1 	0x00, 0x59, 0x89, 0xc7, 0x89, 0xfa, 0x42, 0x6a
+.data1 	0x0a, 0x56, 0x57, 0x89, 0xd7, 0x5a, 0x59, 0x01
+.data1 	0xd1, 0x5a, 0x88, 0x11, 0xe9, 0xb8, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x15, 0xa8, 0x1b, 0x00, 0x00, 0x8b
+.data1 	0x52, 0x14, 0x89, 0x15, 0xb0, 0x2d, 0x00, 0x00
+.data1 	0x89, 0xd6, 0x8b, 0x15, 0xa8, 0x1b, 0x00, 0x00
+.data1 	0x68, 0x00, 0x04, 0x00, 0x00, 0x56, 0xff, 0x72
+.data1 	0x04, 0xe8, 0x82, 0xac, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x89, 0xc7, 0x85, 0xff, 0x0f, 0x8f, 0x86
+.data1 	0x00, 0x00, 0x00, 0x85, 0xff, 0x0f, 0x89, 0x6a
+.data1 	0x00, 0x00, 0x00, 0x83, 0x3d, 0xf0, 0x27, 0x00
+.data1 	0x00, 0x04, 0x74, 0xbd, 0x8b, 0x15, 0xa8, 0x1b
+.data1 	0x00, 0x00, 0x83, 0x7a, 0x04, 0x00, 0x0f, 0x85
+.data1 	0x51, 0x00, 0x00, 0x00, 0x83, 0x3d, 0xf0, 0x27
+.data1 	0x00, 0x00, 0x36, 0x75, 0x48, 0x6a, 0x00, 0x6a
+.data1 	0x03, 0x6a, 0x00, 0xe8, 0xd0, 0xab, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x45, 0xe8, 0x85, 0xc0
+.data1 	0x78, 0x33, 0xf7, 0x45, 0xe8, 0x00, 0x08, 0x00
+.data1 	0x00, 0x74, 0x2a, 0x81, 0x65, 0xe8, 0xff, 0xf7
+.data1 	0xff, 0xff, 0xff, 0x75, 0xe8, 0x6a, 0x04, 0x6a
+.data1 	0x00, 0xe8, 0xaa, 0xab, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x85, 0xc0, 0x78, 0x10, 0x68, 0xd8, 0x03
+.data1 	0x00, 0x00, 0xe8, 0xb2, 0x51, 0x00, 0x00, 0x59
+.data1 	0xe9, 0x5c, 0xff, 0xff, 0xff, 0xc7, 0x05, 0xac
+.data1 	0x2d, 0x00, 0x00, 0x9d, 0xff, 0xff, 0xff, 0xb8
+.data1 	0x7f, 0xff, 0xff, 0xff, 0xe9, 0x6c, 0x00, 0x00
+.data1 	0x00, 0x89, 0xfa, 0x4a, 0x89, 0x15, 0xac, 0x2d
+.data1 	0x00, 0x00, 0x8a, 0x06, 0x46, 0x84, 0xc0, 0x74
+.data1 	0x15, 0x4f, 0x85, 0xff, 0x7f, 0xf4, 0xa1, 0xb0
+.data1 	0x2d, 0x00, 0x00, 0xff, 0x05, 0xb0, 0x2d, 0x00
+.data1 	0x00, 0x0f, 0xbe, 0x00, 0xeb, 0x47, 0x8d, 0x56
+.data1 	0x56, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00
+.data1 	0x59, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00
+.data1 	0x5b, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00
+.data1 	0x5d, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00
+.data1 	0x5f, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00
+.data1 	0x61, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00
+.data1 	0x63, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00
+.data1 	0x65, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00
+.data1 	0x67, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00
+.data1 	0x69, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00
+.data1 	0x6b, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00
+.data1 	0x6d, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00
+.data1 	0x6f, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00
+.data1 	0x71, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00
+.data1 	0x73, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xff, 0x89, 0x55, 0xf8, 0x4f, 0x85, 0xff, 0x7e
+.data1 	0x12, 0x80, 0x3e, 0x00, 0x74, 0x0a, 0x8b, 0x55
+.data1 	0xf8, 0x8a, 0x0e, 0x88, 0x0a, 0xff, 0x45, 0xf8
+.data1 	0x46, 0xeb, 0xe9, 0x8b, 0x15, 0xa8, 0x1b, 0x00
+.data1 	0x00, 0x8b, 0x4d, 0xf8, 0x39, 0x4a, 0x14, 0x0f
+.data1 	0x84, 0xf4, 0xfe, 0xff, 0xff, 0x2b, 0x4a, 0x14
+.data1 	0x49, 0x89, 0x0d, 0xac, 0x2d, 0x00, 0x00, 0xa1
+.data1 	0xb0, 0x2d, 0x00, 0x00, 0xff, 0x05, 0xb0, 0x2d
+.data1 	0x00, 0x00, 0x0f, 0xbe, 0x00, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0xff, 0x05, 0xac, 0x2d
+.data1 	0x00, 0x00, 0xff, 0x0d, 0xb0, 0x2d, 0x00, 0x00
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b, 0x15, 0xb0
+.data1 	0x2d, 0x00, 0x00, 0x89, 0x15, 0xcc, 0x31, 0x00
+.data1 	0x00, 0x8b, 0x15, 0xac, 0x2d, 0x00, 0x00, 0x89
+.data1 	0x15, 0xd0, 0x31, 0x00, 0x00, 0x8b, 0x55, 0x08
+.data1 	0x89, 0x15, 0xb0, 0x2d, 0x00, 0x00, 0x8b, 0x55
+.data1 	0x0c, 0x89, 0x15, 0xac, 0x2d, 0x00, 0x00, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x56, 0x57, 0xff, 0x05
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x6a, 0x00, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x12, 0xab, 0x00, 0x00, 0x59, 0x59
+.data1 	0x89, 0xc6, 0x85, 0xc0, 0x79, 0x0f, 0xff, 0x75
+.data1 	0x08, 0x68, 0x10, 0x04, 0x00, 0x00, 0xe8, 0x7d
+.data1 	0xc5, 0xff, 0xff, 0x59, 0x59, 0x83, 0xfe, 0x0a
+.data1 	0x7d, 0x24, 0x6a, 0x0a, 0x56, 0xe8, 0x37, 0x4c
+.data1 	0x00, 0x00, 0x59, 0x59, 0x89, 0xc7, 0x56, 0xe8
+.data1 	0x6c, 0xaa, 0x00, 0x00, 0x59, 0x85, 0xff, 0x79
+.data1 	0x0b, 0x68, 0xf8, 0x03, 0x00, 0x00, 0xe8, 0x55
+.data1 	0xc5, 0xff, 0xff, 0x59, 0x89, 0xfe, 0xff, 0x75
+.data1 	0x0c, 0x56, 0xe8, 0x25, 0x00, 0x00, 0x00, 0x59
+.data1 	0x59, 0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x75, 0x10
+.data1 	0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85
+.data1 	0xd2, 0x74, 0x05, 0xe8, 0xc7, 0xc4, 0xff, 0xff
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x6a
+.data1 	0x01, 0xff, 0x75, 0x08, 0xe8, 0x3f, 0xaa, 0x00
+.data1 	0x00, 0x59, 0x59, 0x0d, 0x01, 0x00, 0x00, 0x00
+.data1 	0x50, 0x6a, 0x02, 0xff, 0x75, 0x08, 0xe8, 0x2d
+.data1 	0xaa, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x83, 0x7d
+.data1 	0x0c, 0x00, 0x74, 0x19, 0xe8, 0xce, 0x00, 0x00
+.data1 	0x00, 0x68, 0x00, 0x04, 0x00, 0x00, 0xe8, 0x3d
+.data1 	0x19, 0x00, 0x00, 0x59, 0x8b, 0x15, 0xa8, 0x1b
+.data1 	0x00, 0x00, 0x89, 0x42, 0x14, 0x8b, 0x15, 0xa8
+.data1 	0x1b, 0x00, 0x00, 0x83, 0x7a, 0x04, 0x00, 0x7e
+.data1 	0x09, 0xff, 0x72, 0x04, 0xe8, 0xd7, 0xa9, 0x00
+.data1 	0x00, 0x59, 0x8b, 0x15, 0xa8, 0x1b, 0x00, 0x00
+.data1 	0x8b, 0x4d, 0x08, 0x89, 0x4a, 0x04, 0x8b, 0x15
+.data1 	0xa8, 0x1b, 0x00, 0x00, 0x83, 0x7a, 0x14, 0x00
+.data1 	0x75, 0x14, 0x68, 0x00, 0x04, 0x00, 0x00, 0xe8
+.data1 	0xfc, 0x18, 0x00, 0x00, 0x59, 0x8b, 0x15, 0xa8
+.data1 	0x1b, 0x00, 0x00, 0x89, 0x42, 0x14, 0xc7, 0x05
+.data1 	0xac, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x05, 0xa4, 0x1b, 0x00, 0x00, 0x01, 0x00
+.data1 	0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0xff
+.data1 	0x05, 0x90, 0x2c, 0x00, 0x00, 0x83, 0x7d, 0x0c
+.data1 	0x00, 0x74, 0x05, 0xe8, 0x4f, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x15, 0xb0, 0x2d, 0x00
+.data1 	0x00, 0xff, 0x75, 0x08, 0xe8, 0x47, 0xab, 0x00
+.data1 	0x00, 0x59, 0xa3, 0xac, 0x2d, 0x00, 0x00, 0x8b
+.data1 	0x15, 0xa8, 0x1b, 0x00, 0x00, 0xc7, 0x42, 0x14
+.data1 	0x00, 0x00, 0x00, 0x00, 0xc7, 0x05, 0xa4, 0x1b
+.data1 	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8b, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x75, 0x10, 0xff, 0x35, 0x8c
+.data1 	0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05
+.data1 	0xe8, 0xca, 0xc3, 0xff, 0xff, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0x8b, 0x15, 0xa8, 0x1b, 0x00
+.data1 	0x00, 0x8b, 0x0d, 0xac, 0x2d, 0x00, 0x00, 0x89
+.data1 	0x4a, 0x08, 0x8b, 0x15, 0xa8, 0x1b, 0x00, 0x00
+.data1 	0x8b, 0x0d, 0xb0, 0x2d, 0x00, 0x00, 0x89, 0x4a
+.data1 	0x0c, 0x8b, 0x15, 0xa8, 0x1b, 0x00, 0x00, 0x8b
+.data1 	0x0d, 0xa4, 0x1b, 0x00, 0x00, 0x89, 0x0a, 0x6a
+.data1 	0x18, 0xe8, 0x42, 0x18, 0x00, 0x00, 0x59, 0x89
+.data1 	0xc6, 0x8b, 0x15, 0xa8, 0x1b, 0x00, 0x00, 0x89
+.data1 	0x56, 0x10, 0xc7, 0x46, 0x04, 0xff, 0xff, 0xff
+.data1 	0xff, 0x89, 0x35, 0xa8, 0x1b, 0x00, 0x00, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b, 0x35
+.data1 	0xa8, 0x1b, 0x00, 0x00, 0xff, 0x05, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x83, 0x7e, 0x04, 0x00, 0x78, 0x09
+.data1 	0xff, 0x76, 0x04, 0xe8, 0xc0, 0xa8, 0x00, 0x00
+.data1 	0x59, 0x83, 0x7e, 0x14, 0x00, 0x74, 0x09, 0xff
+.data1 	0x76, 0x14, 0xe8, 0x2f, 0x96, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x56, 0x10, 0x89, 0x15, 0xa8, 0x1b, 0x00
+.data1 	0x00, 0x56, 0xe8, 0x1f, 0x96, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x15, 0xa8, 0x1b, 0x00, 0x00, 0x8b, 0x52
+.data1 	0x08, 0x89, 0x15, 0xac, 0x2d, 0x00, 0x00, 0x8b
+.data1 	0x15, 0xa8, 0x1b, 0x00, 0x00, 0x8b, 0x52, 0x0c
+.data1 	0x89, 0x15, 0xb0, 0x2d, 0x00, 0x00, 0x8b, 0x15
+.data1 	0xa8, 0x1b, 0x00, 0x00, 0x8b, 0x12, 0x89, 0x15
+.data1 	0xa4, 0x1b, 0x00, 0x00, 0x8b, 0x15, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00
+.data1 	0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8, 0xec
+.data1 	0xc2, 0xff, 0xff, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x81, 0x3d, 0xa8, 0x1b, 0x00, 0x00, 0xb4
+.data1 	0x2d, 0x00, 0x00, 0x74, 0x07, 0xe8, 0x60, 0xff
+.data1 	0xff, 0xff, 0xeb, 0xed, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0xe8, 0xe0, 0xff, 0xff, 0xff, 0x8b, 0x15
+.data1 	0xa8, 0x1b, 0x00, 0x00, 0x83, 0x7a, 0x04, 0x00
+.data1 	0x7e, 0x16, 0xff, 0x72, 0x04, 0xe8, 0x1e, 0xa8
+.data1 	0x00, 0x00, 0x59, 0x8b, 0x15, 0xa8, 0x1b, 0x00
+.data1 	0x00, 0xc7, 0x42, 0x04, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x6a
+.data1 	0x00, 0xe8, 0x05, 0x00, 0x00, 0x00, 0x59, 0x31
+.data1 	0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x58, 0x56, 0x57, 0x6a, 0x00, 0x6a, 0x00, 0xe8
+.data1 	0x2f, 0x09, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x7f, 0xf1, 0xc7, 0x45, 0xfc, 0x01, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x35, 0xd4, 0x31, 0x00, 0x00, 0x8b
+.data1 	0x15, 0xd8, 0x31, 0x00, 0x00, 0x39, 0x55, 0xfc
+.data1 	0x0f, 0x8f, 0xf9, 0x01, 0x00, 0x00, 0x80, 0x7e
+.data1 	0x19, 0x00, 0x0f, 0x84, 0xe4, 0x01, 0x00, 0x00
+.data1 	0x83, 0x7e, 0x10, 0x00, 0x75, 0x0c, 0x56, 0xe8
+.data1 	0xe7, 0x01, 0x00, 0x00, 0x59, 0xe9, 0xd2, 0x01
+.data1 	0x00, 0x00, 0x83, 0x7d, 0x08, 0x00, 0x74, 0x0a
+.data1 	0x80, 0x7e, 0x1a, 0x00, 0x0f, 0x84, 0xc2, 0x01
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x10, 0x89, 0x55, 0xf8
+.data1 	0x8b, 0x7e, 0x0c, 0x39, 0x7e, 0x0c, 0x75, 0x1a
+.data1 	0xff, 0x37, 0xff, 0x75, 0xfc, 0x68, 0x4c, 0x04
+.data1 	0x00, 0x00, 0x6a, 0x40, 0x8d, 0x45, 0xa8, 0x50
+.data1 	0xe8, 0xe9, 0x4f, 0x00, 0x00, 0x83, 0xc4, 0x14
+.data1 	0xeb, 0x15, 0xff, 0x37, 0x68, 0x44, 0x04, 0x00
+.data1 	0x00, 0x6a, 0x40, 0x8d, 0x45, 0xa8, 0x50, 0xe8
+.data1 	0xd2, 0x4f, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x8d
+.data1 	0x45, 0xa8, 0x50, 0xe8, 0x7c, 0x4d, 0x00, 0x00
+.data1 	0x59, 0x8d, 0x45, 0xa8, 0x50, 0xe8, 0x26, 0xa9
+.data1 	0x00, 0x00, 0x59, 0x89, 0x45, 0xe8, 0xc6, 0x45
+.data1 	0xa8, 0x00, 0x0f, 0xbf, 0x5f, 0x04, 0x83, 0xfb
+.data1 	0xff, 0x0f, 0x84, 0x9e, 0x00, 0x00, 0x00, 0x0f
+.data1 	0xb7, 0x57, 0x04, 0xf6, 0xc2, 0xff, 0x75, 0x20
+.data1 	0x0f, 0xbf, 0x5f, 0x04, 0xc1, 0xfb, 0x08, 0x53
+.data1 	0x68, 0x3c, 0x04, 0x00, 0x00, 0x6a, 0x40, 0x8d
+.data1 	0x45, 0xa8, 0x50, 0xe8, 0x86, 0x4f, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0xe9, 0x75, 0x00, 0x00, 0x00
+.data1 	0x0f, 0xbf, 0x47, 0x04, 0x89, 0x45, 0xf4, 0x25
+.data1 	0x7f, 0x00, 0x00, 0x00, 0x3d, 0x17, 0x00, 0x00
+.data1 	0x00, 0x7f, 0x2e, 0xba, 0x7f, 0x00, 0x00, 0x00
+.data1 	0x23, 0x55, 0xf4, 0x83, 0x3c, 0x95, 0xb0, 0x1e
+.data1 	0x00, 0x00, 0x00, 0x74, 0x1c, 0xba, 0x7f, 0x00
+.data1 	0x00, 0x00, 0x23, 0x55, 0xf4, 0xff, 0x34, 0x95
+.data1 	0xb0, 0x1e, 0x00, 0x00, 0x8d, 0x45, 0xa8, 0x50
+.data1 	0xe8, 0x8b, 0xa8, 0x00, 0x00, 0x59, 0x59, 0xeb
+.data1 	0x1c, 0xba, 0x7f, 0x00, 0x00, 0x00, 0x23, 0x55
+.data1 	0xf4, 0x52, 0x68, 0x30, 0x04, 0x00, 0x00, 0x6a
+.data1 	0x40, 0x8d, 0x45, 0xa8, 0x50, 0xe8, 0x24, 0x4f
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x10, 0x8b, 0x55, 0xf4
+.data1 	0xf6, 0xc2, 0x80, 0x74, 0x10, 0x68, 0x20, 0x04
+.data1 	0x00, 0x00, 0x8d, 0x45, 0xa8, 0x50, 0xe8, 0xf5
+.data1 	0xa7, 0x00, 0x00, 0x59, 0x59, 0x8d, 0x45, 0xa8
+.data1 	0x50, 0xe8, 0xb6, 0x4c, 0x00, 0x00, 0x59, 0x8d
+.data1 	0x45, 0xa8, 0x50, 0xe8, 0x60, 0xa8, 0x00, 0x00
+.data1 	0x59, 0x01, 0x45, 0xe8, 0xa1, 0xa4, 0x23, 0x00
+.data1 	0x00, 0xff, 0x48, 0x04, 0x8b, 0x15, 0xa4, 0x23
+.data1 	0x00, 0x00, 0x83, 0x7a, 0x04, 0x00, 0x79, 0x1a
+.data1 	0xff, 0x35, 0xa4, 0x23, 0x00, 0x00, 0xe8, 0xe9
+.data1 	0x4c, 0x00, 0x00, 0x59, 0xa1, 0xa4, 0x23, 0x00
+.data1 	0x00, 0x8b, 0x18, 0xff, 0x00, 0xc6, 0x03, 0x20
+.data1 	0xeb, 0x0c, 0xa1, 0xa4, 0x23, 0x00, 0x00, 0x8b
+.data1 	0x18, 0xff, 0x00, 0xc6, 0x03, 0x20, 0xff, 0x45
+.data1 	0xe8, 0x83, 0x7d, 0xe8, 0x1e, 0x7c, 0xbd, 0xff
+.data1 	0x77, 0x08, 0xe8, 0x5d, 0x4c, 0x00, 0x00, 0x59
+.data1 	0xa1, 0xa4, 0x23, 0x00, 0x00, 0xff, 0x48, 0x04
+.data1 	0x8b, 0x15, 0xa4, 0x23, 0x00, 0x00, 0x83, 0x7a
+.data1 	0x04, 0x00, 0x79, 0x1a, 0xff, 0x35, 0xa4, 0x23
+.data1 	0x00, 0x00, 0xe8, 0x9d, 0x4c, 0x00, 0x00, 0x59
+.data1 	0xa1, 0xa4, 0x23, 0x00, 0x00, 0x8b, 0x18, 0xff
+.data1 	0x00, 0xc6, 0x03, 0x0a, 0xeb, 0x0c, 0xa1, 0xa4
+.data1 	0x23, 0x00, 0x00, 0x8b, 0x18, 0xff, 0x00, 0xc6
+.data1 	0x03, 0x0a, 0xff, 0x4d, 0xf8, 0x83, 0x7d, 0xf8
+.data1 	0x00, 0x7e, 0x08, 0x83, 0xc7, 0x0c, 0xe9, 0x58
+.data1 	0xfe, 0xff, 0xff, 0xc6, 0x46, 0x1a, 0x00, 0x80
+.data1 	0x7e, 0x18, 0x02, 0x75, 0x07, 0x56, 0xe8, 0x10
+.data1 	0x00, 0x00, 0x00, 0x59, 0xff, 0x45, 0xfc, 0x83
+.data1 	0xc6, 0x1c, 0xe9, 0xf8, 0xfd, 0xff, 0xff, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x08, 0x56, 0x57, 0x8b, 0x7d, 0x08, 0xff, 0x05
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x8b, 0x57, 0x10, 0x89
+.data1 	0x55, 0xf8, 0x8b, 0x77, 0x0c, 0xff, 0x4d, 0xf8
+.data1 	0x78, 0x17, 0x81, 0x7e, 0x08, 0x88, 0x2c, 0x00
+.data1 	0x00, 0x74, 0x09, 0xff, 0x76, 0x08, 0xe8, 0x1b
+.data1 	0x93, 0x00, 0x00, 0x59, 0x83, 0xc6, 0x0c, 0xeb
+.data1 	0xe4, 0x39, 0x7f, 0x0c, 0x74, 0x09, 0xff, 0x77
+.data1 	0x0c, 0xe8, 0x08, 0x93, 0x00, 0x00, 0x59, 0xc6
+.data1 	0x47, 0x19, 0x00, 0x8b, 0x15, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00
+.data1 	0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8, 0xfd, 0xbf
+.data1 	0xff, 0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x08, 0x56, 0x57, 0x83, 0x7d
+.data1 	0x08, 0x01, 0x7e, 0x10, 0x8b, 0x55, 0x0c, 0xff
+.data1 	0x72, 0x04, 0xe8, 0x3c, 0x01, 0x00, 0x00, 0x59
+.data1 	0x89, 0xc6, 0xeb, 0x02, 0x31, 0xf6, 0x85, 0xf6
+.data1 	0x74, 0x50, 0x80, 0x7e, 0x18, 0x00, 0x0f, 0x84
+.data1 	0x72, 0x00, 0x00, 0x00, 0x8b, 0x56, 0x10, 0x4a
+.data1 	0x6b, 0xc2, 0x0c, 0x03, 0x46, 0x0c, 0x0f, 0xbf
+.data1 	0x40, 0x04, 0x89, 0x45, 0xf8, 0xa8, 0xff, 0x75
+.data1 	0x0b, 0xc1, 0xf8, 0x08, 0x0f, 0xb6, 0xd0, 0x89
+.data1 	0x55, 0xf8, 0xeb, 0x11, 0xba, 0x7f, 0x00, 0x00
+.data1 	0x00, 0x23, 0x55, 0xf8, 0x81, 0xc2, 0x80, 0x00
+.data1 	0x00, 0x00, 0x89, 0x55, 0xf8, 0x80, 0x3d, 0x77
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x75, 0x07, 0x56, 0xe8
+.data1 	0x27, 0xff, 0xff, 0xff, 0x59, 0x8b, 0x45, 0xf8
+.data1 	0xeb, 0x3c, 0x8b, 0x3d, 0xd4, 0x31, 0x00, 0x00
+.data1 	0x6b, 0x05, 0xd8, 0x31, 0x00, 0x00, 0x1c, 0x03
+.data1 	0x05, 0xd4, 0x31, 0x00, 0x00, 0x39, 0xf8, 0x77
+.data1 	0x04, 0x31, 0xc0, 0xeb, 0x21, 0x80, 0x7f, 0x19
+.data1 	0x00, 0x74, 0x06, 0x80, 0x7f, 0x18, 0x00, 0x74
+.data1 	0x05, 0x83, 0xc7, 0x1c, 0xeb, 0xda, 0x6a, 0x00
+.data1 	0x6a, 0x01, 0xe8, 0xfc, 0x05, 0x00, 0x00, 0x59
+.data1 	0x59, 0xe9, 0x70, 0xff, 0xff, 0xff, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b
+.data1 	0x55, 0x0c, 0xff, 0x72, 0x04, 0xe8, 0x91, 0x00
+.data1 	0x00, 0x00, 0x59, 0x89, 0xc7, 0x31, 0xf6, 0x39
+.data1 	0x77, 0x10, 0x0f, 0x8e, 0x7d, 0x00, 0x00, 0x00
+.data1 	0x6b, 0xc6, 0x0c, 0x03, 0x47, 0x0c, 0xff, 0x30
+.data1 	0x68, 0x58, 0x04, 0x00, 0x00, 0xe8, 0xcc, 0x4c
+.data1 	0x00, 0x00, 0x59, 0x59, 0xa1, 0xa4, 0x23, 0x00
+.data1 	0x00, 0xff, 0x48, 0x04, 0x8b, 0x15, 0xa4, 0x23
+.data1 	0x00, 0x00, 0x83, 0x7a, 0x04, 0x00, 0x79, 0x2f
+.data1 	0xff, 0x35, 0xa4, 0x23, 0x00, 0x00, 0xe8, 0xe1
+.data1 	0x4a, 0x00, 0x00, 0x59, 0x46, 0x39, 0x77, 0x10
+.data1 	0x7e, 0x07, 0xb8, 0x20, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x05, 0xb8, 0x0a, 0x00, 0x00, 0x00, 0x0f, 0xbe
+.data1 	0xc0, 0x8b, 0x1d, 0xa4, 0x23, 0x00, 0x00, 0x8b
+.data1 	0x0b, 0xff, 0x03, 0x88, 0x01, 0xeb, 0xa0, 0x46
+.data1 	0x39, 0x77, 0x10, 0x7e, 0x07, 0xb8, 0x20, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x05, 0xb8, 0x0a, 0x00, 0x00
+.data1 	0x00, 0x0f, 0xbe, 0xc0, 0x8b, 0x1d, 0xa4, 0x23
+.data1 	0x00, 0x00, 0x8b, 0x0b, 0xff, 0x03, 0x88, 0x01
+.data1 	0xe9, 0x7a, 0xff, 0xff, 0xff, 0x31, 0xc0, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x10, 0x56, 0x57, 0x83, 0x7d, 0x08, 0x00, 0x75
+.data1 	0x10, 0x68, 0x7c, 0x04, 0x00, 0x00, 0xe8, 0xed
+.data1 	0xbe, 0xff, 0xff, 0x59, 0xe9, 0x1f, 0x01, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x08, 0x80, 0x3a, 0x25, 0x0f
+.data1 	0x85, 0xbd, 0x00, 0x00, 0x00, 0x0f, 0xbe, 0x42
+.data1 	0x01, 0x2d, 0x30, 0x00, 0x00, 0x00, 0x3d, 0x09
+.data1 	0x00, 0x00, 0x00, 0x77, 0x4b, 0x8b, 0x55, 0x08
+.data1 	0x83, 0xc2, 0x01, 0x52, 0xe8, 0x9c, 0x1a, 0x00
+.data1 	0x00, 0x59, 0x89, 0x45, 0xfc, 0x85, 0xc0, 0x0f
+.data1 	0x8e, 0xeb, 0x00, 0x00, 0x00, 0x39, 0x05, 0xd8
+.data1 	0x31, 0x00, 0x00, 0x0f, 0x8c, 0xdf, 0x00, 0x00
+.data1 	0x00, 0x48, 0x6b, 0xc0, 0x1c, 0x03, 0x05, 0xd4
+.data1 	0x31, 0x00, 0x00, 0x80, 0x78, 0x19, 0x00, 0x0f
+.data1 	0x84, 0xcb, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xfc
+.data1 	0x4a, 0x6b, 0xc2, 0x1c, 0x03, 0x05, 0xd4, 0x31
+.data1 	0x00, 0x00, 0x50, 0xe9, 0xc6, 0x00, 0x00, 0x00
+.data1 	0x31, 0xff, 0x8b, 0x35, 0xd4, 0x31, 0x00, 0x00
+.data1 	0x8b, 0x15, 0xd8, 0x31, 0x00, 0x00, 0x89, 0x55
+.data1 	0xf0, 0xff, 0x4d, 0xf0, 0x78, 0x3e, 0x80, 0x7e
+.data1 	0x19, 0x00, 0x74, 0x33, 0x83, 0x7e, 0x10, 0x00
+.data1 	0x7e, 0x2d, 0x8b, 0x56, 0x0c, 0x8b, 0x4d, 0x08
+.data1 	0xff, 0x72, 0x08, 0x83, 0xc1, 0x01, 0x51, 0xe8
+.data1 	0x00, 0x1a, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x74, 0x15, 0x85, 0xff, 0x74, 0x0f, 0xff, 0x75
+.data1 	0x08, 0x68, 0x6c, 0x04, 0x00, 0x00, 0xe8, 0x35
+.data1 	0xbe, 0xff, 0xff, 0x59, 0x59, 0x89, 0xf7, 0x83
+.data1 	0xc6, 0x1c, 0xeb, 0xbd, 0x85, 0xff, 0x0f, 0x84
+.data1 	0x5c, 0x00, 0x00, 0x00, 0x57, 0xe9, 0x64, 0x00
+.data1 	0x00, 0x00, 0xff, 0x75, 0x08, 0xe8, 0x1d, 0x1a
+.data1 	0x00, 0x00, 0x59, 0x85, 0xc0, 0x0f, 0x84, 0x45
+.data1 	0x00, 0x00, 0x00, 0xff, 0x75, 0x08, 0xe8, 0xe2
+.data1 	0x19, 0x00, 0x00, 0x59, 0x89, 0x45, 0xf4, 0x8b
+.data1 	0x35, 0xd4, 0x31, 0x00, 0x00, 0x8b, 0x15, 0xd8
+.data1 	0x31, 0x00, 0x00, 0x89, 0x55, 0xf0, 0xff, 0x4d
+.data1 	0xf0, 0x78, 0x25, 0x80, 0x7e, 0x19, 0x00, 0x74
+.data1 	0x1a, 0x83, 0x7e, 0x10, 0x00, 0x7e, 0x14, 0x8b
+.data1 	0x56, 0x10, 0x4a, 0x6b, 0xc2, 0x0c, 0x03, 0x46
+.data1 	0x0c, 0x8b, 0x55, 0xf4, 0x39, 0x10, 0x75, 0x03
+.data1 	0x56, 0xeb, 0x13, 0x83, 0xc6, 0x1c, 0xeb, 0xd6
+.data1 	0xff, 0x75, 0x08, 0x68, 0x5c, 0x04, 0x00, 0x00
+.data1 	0xe8, 0xbb, 0xbd, 0xff, 0xff, 0x59, 0x58, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x57
+.data1 	0x8b, 0x3d, 0xd8, 0x31, 0x00, 0x00, 0x8b, 0x35
+.data1 	0xd4, 0x31, 0x00, 0x00, 0x4f, 0x0f, 0x89, 0xef
+.data1 	0x00, 0x00, 0x00, 0xff, 0x05, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x83, 0x3d, 0xd8, 0x31, 0x00, 0x00, 0x00
+.data1 	0x75, 0x12, 0x6a, 0x70, 0xe8, 0xd7, 0x11, 0x00
+.data1 	0x00, 0x59, 0xa3, 0xd4, 0x31, 0x00, 0x00, 0xe9
+.data1 	0x71, 0x00, 0x00, 0x00, 0xba, 0x04, 0x00, 0x00
+.data1 	0x00, 0x03, 0x15, 0xd8, 0x31, 0x00, 0x00, 0x6b
+.data1 	0xc2, 0x1c, 0x50, 0xe8, 0xb8, 0x11, 0x00, 0x00
+.data1 	0x59, 0x89, 0xc6, 0x6b, 0x05, 0xd8, 0x31, 0x00
+.data1 	0x00, 0x1c, 0x50, 0x56, 0xff, 0x35, 0xd4, 0x31
+.data1 	0x00, 0x00, 0xe8, 0xe9, 0x18, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x31, 0xff, 0x39, 0x3d, 0xd8, 0x31
+.data1 	0x00, 0x00, 0x7e, 0x27, 0x6b, 0xc7, 0x1c, 0x03
+.data1 	0x05, 0xd4, 0x31, 0x00, 0x00, 0x6b, 0xdf, 0x1c
+.data1 	0x03, 0x1d, 0xd4, 0x31, 0x00, 0x00, 0x39, 0x58
+.data1 	0x0c, 0x75, 0x0d, 0x6b, 0xc7, 0x1c, 0x01, 0xf0
+.data1 	0x6b, 0xdf, 0x1c, 0x01, 0xf3, 0x89, 0x43, 0x0c
+.data1 	0x47, 0xeb, 0xd1, 0xff, 0x35, 0xd4, 0x31, 0x00
+.data1 	0x00, 0xe8, 0x98, 0x8f, 0x00, 0x00, 0x59, 0x89
+.data1 	0x35, 0xd4, 0x31, 0x00, 0x00, 0x6b, 0x05, 0xd8
+.data1 	0x31, 0x00, 0x00, 0x1c, 0x8b, 0x15, 0xd4, 0x31
+.data1 	0x00, 0x00, 0x89, 0xc6, 0x01, 0xd6, 0xbf, 0x04
+.data1 	0x00, 0x00, 0x00, 0x4f, 0x78, 0x23, 0x8b, 0x15
+.data1 	0xd8, 0x31, 0x00, 0x00, 0x89, 0xd1, 0x41, 0x6a
+.data1 	0x00, 0xff, 0x35, 0xd4, 0x31, 0x00, 0x00, 0x89
+.data1 	0x0d, 0xd8, 0x31, 0x00, 0x00, 0x6b, 0xc2, 0x1c
+.data1 	0x5a, 0x01, 0xc2, 0x59, 0x88, 0x4a, 0x19, 0xeb
+.data1 	0xda, 0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x75, 0x20
+.data1 	0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85
+.data1 	0xd2, 0x74, 0x15, 0xe8, 0x4f, 0xbc, 0xff, 0xff
+.data1 	0xeb, 0x0e, 0x80, 0x7e, 0x19, 0x00, 0x74, 0x08
+.data1 	0x83, 0xc6, 0x1c, 0xe9, 0xfc, 0xfe, 0xff, 0xff
+.data1 	0xff, 0x05, 0x90, 0x2c, 0x00, 0x00, 0xc6, 0x46
+.data1 	0x18, 0x00, 0xc6, 0x46, 0x19, 0x01, 0xc6, 0x46
+.data1 	0x1a, 0x00, 0xc7, 0x46, 0x10, 0x00, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7d, 0x0c, 0x01, 0x7e, 0x10, 0x6b
+.data1 	0x45, 0x0c, 0x0c, 0x50, 0xe8, 0xc7, 0x10, 0x00
+.data1 	0x00, 0x59, 0x89, 0x46, 0x0c, 0xeb, 0x03, 0x89
+.data1 	0x76, 0x0c, 0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x75
+.data1 	0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a
+.data1 	0x85, 0xd2, 0x74, 0x05, 0xe8, 0xee, 0xbb, 0xff
+.data1 	0xff, 0x89, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x14, 0x56, 0x57, 0x8b
+.data1 	0x7d, 0x08, 0xff, 0x05, 0x90, 0x2c, 0x00, 0x00
+.data1 	0xe8, 0x63, 0xa1, 0x00, 0x00, 0x89, 0x45, 0xfc
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x2a, 0x8b
+.data1 	0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x75, 0x10, 0xff, 0x35
+.data1 	0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74
+.data1 	0x05, 0xe8, 0xa9, 0xbb, 0xff, 0xff, 0x68, 0xb0
+.data1 	0x04, 0x00, 0x00, 0xe8, 0x00, 0xbc, 0xff, 0xff
+.data1 	0x59, 0x83, 0x7d, 0xfc, 0x00, 0x0f, 0x85, 0xdf
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x15, 0xa0, 0x2c, 0x00
+.data1 	0x00, 0x89, 0x55, 0xf0, 0xc7, 0x05, 0xa0, 0x2c
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x15
+.data1 	0xd8, 0x31, 0x00, 0x00, 0x89, 0x55, 0xec, 0x8b
+.data1 	0x35, 0xd4, 0x31, 0x00, 0x00, 0xff, 0x4d, 0xec
+.data1 	0x78, 0x12, 0x80, 0x7e, 0x19, 0x00, 0x74, 0x07
+.data1 	0x56, 0xe8, 0xfd, 0xfa, 0xff, 0xff, 0x59, 0x83
+.data1 	0xc6, 0x1c, 0xeb, 0xe9, 0xe8, 0x85, 0xf8, 0xff
+.data1 	0xff, 0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x75, 0x10
+.data1 	0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85
+.data1 	0xd2, 0x74, 0x05, 0xe8, 0x37, 0xbb, 0xff, 0xff
+.data1 	0xe8, 0xc3, 0x43, 0x00, 0x00, 0x83, 0x7d, 0x10
+.data1 	0x01, 0x75, 0x48, 0x6a, 0x02, 0xe8, 0x29, 0x45
+.data1 	0x00, 0x00, 0x59, 0x6a, 0x03, 0xe8, 0x21, 0x45
+.data1 	0x00, 0x00, 0x59, 0x85, 0xff, 0x74, 0x06, 0x83
+.data1 	0x7f, 0x10, 0x00, 0x75, 0x2e, 0xe8, 0x66, 0x42
+.data1 	0x00, 0x00, 0x85, 0xc0, 0x75, 0x25, 0x6a, 0x00
+.data1 	0xe8, 0x6b, 0xa0, 0x00, 0x00, 0x59, 0x6a, 0x00
+.data1 	0x68, 0xa4, 0x04, 0x00, 0x00, 0xe8, 0xd6, 0xa0
+.data1 	0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x74, 0x0b
+.data1 	0x68, 0x8c, 0x04, 0x00, 0x00, 0xe8, 0x46, 0xbb
+.data1 	0xff, 0xff, 0x59, 0x83, 0x7d, 0xf0, 0x00, 0x74
+.data1 	0x21, 0x80, 0x3d, 0x77, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x74, 0x18, 0x6a, 0x02, 0xe8, 0xd9, 0x43, 0x00
+.data1 	0x00, 0x59, 0x6a, 0x03, 0xe8, 0xd1, 0x43, 0x00
+.data1 	0x00, 0x59, 0x6a, 0x0f, 0xe8, 0xc9, 0x43, 0x00
+.data1 	0x00, 0x59, 0x8b, 0x45, 0xfc, 0xe9, 0xae, 0x00
+.data1 	0x00, 0x00, 0x83, 0x3d, 0xa0, 0x2c, 0x00, 0x00
+.data1 	0x00, 0x74, 0x29, 0x83, 0x7d, 0x10, 0x02, 0x74
+.data1 	0x23, 0x80, 0x3d, 0x78, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x74, 0x1a, 0x85, 0xff, 0x74, 0x06, 0x83, 0x7f
+.data1 	0x10, 0x00, 0x75, 0x08, 0x8b, 0x55, 0xfc, 0x89
+.data1 	0x55, 0xf8, 0xeb, 0x08, 0x8b, 0x57, 0x0c, 0x8b
+.data1 	0x12, 0x89, 0x55, 0xf8, 0x83, 0x7d, 0x10, 0x01
+.data1 	0x75, 0x09, 0x8b, 0x55, 0xfc, 0x89, 0x15, 0xd4
+.data1 	0x1b, 0x00, 0x00, 0x85, 0xff, 0x74, 0x47, 0x8b
+.data1 	0x47, 0x10, 0xff, 0x77, 0x0c, 0xff, 0x47, 0x10
+.data1 	0x6b, 0xc0, 0x0c, 0x5a, 0x89, 0xc6, 0x01, 0xd6
+.data1 	0x8b, 0x55, 0xfc, 0x89, 0x16, 0x66, 0xc7, 0x46
+.data1 	0x04, 0xff, 0xff, 0xc7, 0x46, 0x08, 0x88, 0x2c
+.data1 	0x00, 0x00, 0x80, 0x3d, 0x77, 0x2c, 0x00, 0x00
+.data1 	0x00, 0x74, 0x1b, 0x83, 0x3d, 0xa0, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x74, 0x12, 0x83, 0x7d, 0x0c, 0x00
+.data1 	0x74, 0x0c, 0xff, 0x75, 0x0c, 0xe8, 0x2a, 0x03
+.data1 	0x00, 0x00, 0x59, 0x89, 0x46, 0x08, 0x8b, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x75, 0x10, 0xff, 0x35, 0x8c
+.data1 	0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05
+.data1 	0xe8, 0x0a, 0xba, 0xff, 0xff, 0x8b, 0x45, 0xfc
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x08, 0x56, 0x57, 0x8b, 0x75, 0x08, 0xff
+.data1 	0x05, 0x90, 0x2c, 0x00, 0x00, 0x80, 0x7e, 0x18
+.data1 	0x00, 0x75, 0x11, 0x56, 0x6a, 0x01, 0xe8, 0x90
+.data1 	0x00, 0x00, 0x00, 0x59, 0x59, 0x3d, 0xff, 0xff
+.data1 	0xff, 0xff, 0x75, 0xe9, 0x8b, 0x56, 0x10, 0x4a
+.data1 	0x6b, 0xc2, 0x0c, 0x03, 0x46, 0x0c, 0x0f, 0xbf
+.data1 	0x40, 0x04, 0x89, 0xc7, 0xf7, 0xc7, 0xff, 0x00
+.data1 	0x00, 0x00, 0x75, 0x0d, 0x89, 0xfa, 0xc1, 0xfa
+.data1 	0x08, 0x0f, 0xb6, 0xca, 0x89, 0x4d, 0xf8, 0xeb
+.data1 	0x10, 0xba, 0x7f, 0x00, 0x00, 0x00, 0x21, 0xfa
+.data1 	0x81, 0xc2, 0x80, 0x00, 0x00, 0x00, 0x89, 0x55
+.data1 	0xf8, 0x56, 0xe8, 0x3c, 0xf9, 0xff, 0xff, 0x59
+.data1 	0xc7, 0x05, 0x8c, 0x2c, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0xba, 0x7f, 0x00, 0x00, 0x00, 0x21
+.data1 	0xfa, 0x83, 0xfa, 0x02, 0x75, 0x0f, 0x6a, 0x02
+.data1 	0xe8, 0x33, 0x9f, 0x00, 0x00, 0x50, 0xe8, 0x4d
+.data1 	0x9f, 0x00, 0x00, 0x59, 0x59, 0x8b, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c
+.data1 	0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8
+.data1 	0x5b, 0xb9, 0xff, 0xff, 0x8b, 0x45, 0xf8, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x24, 0x56, 0x57, 0x8d, 0x45, 0xf8, 0x50, 0xff
+.data1 	0x75, 0x08, 0xe8, 0x1b, 0x02, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0x45, 0xfc, 0x3d, 0xff, 0xff, 0xff
+.data1 	0xff, 0x75, 0x09, 0x83, 0x3d, 0xf0, 0x27, 0x00
+.data1 	0x00, 0x04, 0x74, 0xdf, 0x83, 0x7d, 0xfc, 0x00
+.data1 	0x7f, 0x08, 0x8b, 0x45, 0xfc, 0xe9, 0xf4, 0x01
+.data1 	0x00, 0x00, 0xff, 0x05, 0x90, 0x2c, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x35, 0xd4, 0x31, 0x00, 0x00, 0x6b, 0x05, 0xd8
+.data1 	0x31, 0x00, 0x00, 0x1c, 0x03, 0x05, 0xd4, 0x31
+.data1 	0x00, 0x00, 0x39, 0xf0, 0x0f, 0x86, 0x99, 0x00
+.data1 	0x00, 0x00, 0x80, 0x7e, 0x19, 0x00, 0x0f, 0x84
+.data1 	0x87, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xe8, 0x01
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x45, 0xe4, 0x01, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x7e, 0x0c, 0x6b, 0x46, 0x10
+.data1 	0x0c, 0x03, 0x46, 0x0c, 0x39, 0xf8, 0x76, 0x41
+.data1 	0x83, 0x3f, 0xff, 0x74, 0x37, 0x8b, 0x55, 0xfc
+.data1 	0x39, 0x17, 0x75, 0x0d, 0x8b, 0x45, 0xf8, 0x0f
+.data1 	0xbf, 0xc0, 0x66, 0x89, 0x47, 0x04, 0x89, 0x75
+.data1 	0xec, 0x0f, 0xbf, 0x47, 0x04, 0x3d, 0xff, 0xff
+.data1 	0xff, 0xff, 0x75, 0x09, 0xc7, 0x45, 0xe4, 0x00
+.data1 	0x00, 0x00, 0x00, 0xeb, 0x0f, 0x0f, 0xbf, 0x47
+.data1 	0x04, 0x3c, 0x7f, 0x75, 0x07, 0xc7, 0x45, 0xe8
+.data1 	0x00, 0x00, 0x00, 0x00, 0x83, 0xc7, 0x0c, 0xeb
+.data1 	0xb4, 0x83, 0x7d, 0xe4, 0x00, 0x74, 0x24, 0x83
+.data1 	0x7d, 0xe8, 0x00, 0x74, 0x07, 0xb8, 0x02, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x05, 0xb8, 0x01, 0x00, 0x00
+.data1 	0x00, 0x89, 0x45, 0xdc, 0x0f, 0xbe, 0x5e, 0x18
+.data1 	0x39, 0x5d, 0xdc, 0x74, 0x06, 0x0f, 0xbe, 0xc0
+.data1 	0x88, 0x46, 0x18, 0x83, 0xc6, 0x1c, 0xe9, 0x52
+.data1 	0xff, 0xff, 0xff, 0x8b, 0x15, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00
+.data1 	0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8, 0x3d, 0xb8
+.data1 	0xff, 0xff, 0x83, 0x3d, 0xa0, 0x2c, 0x00, 0x00
+.data1 	0x00, 0x74, 0x1f, 0x80, 0x3d, 0x77, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x74, 0x16, 0x83, 0x7d, 0x0c, 0x00
+.data1 	0x0f, 0x84, 0xe8, 0x00, 0x00, 0x00, 0x8b, 0x55
+.data1 	0x0c, 0x39, 0x55, 0xec, 0x0f, 0x85, 0xdc, 0x00
+.data1 	0x00, 0x00, 0xba, 0x80, 0x00, 0x00, 0x00, 0x23
+.data1 	0x55, 0xf8, 0x89, 0x55, 0xe0, 0x8b, 0x55, 0xf8
+.data1 	0x83, 0xe2, 0x7f, 0x89, 0x55, 0xf8, 0x0f, 0x84
+.data1 	0xcf, 0x00, 0x00, 0x00, 0x83, 0x7d, 0xf8, 0x02
+.data1 	0x0f, 0x84, 0xc5, 0x00, 0x00, 0x00, 0x83, 0x7d
+.data1 	0xf8, 0x0d, 0x0f, 0x84, 0xbb, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x0c, 0x39, 0x55, 0xec, 0x74, 0x16
+.data1 	0xff, 0x75, 0xfc, 0x68, 0xd8, 0x04, 0x00, 0x00
+.data1 	0xff, 0x35, 0xa8, 0x23, 0x00, 0x00, 0xe8, 0x66
+.data1 	0x45, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x83, 0x7d
+.data1 	0xf8, 0x17, 0x7f, 0x1c, 0x8b, 0x55, 0xf8, 0x83
+.data1 	0x3c, 0x95, 0xb0, 0x1e, 0x00, 0x00, 0x00, 0x74
+.data1 	0x0f, 0xff, 0x34, 0x95, 0xb0, 0x1e, 0x00, 0x00
+.data1 	0xe8, 0x4c, 0x43, 0x00, 0x00, 0x59, 0xeb, 0x16
+.data1 	0xff, 0x75, 0xf8, 0x68, 0xcc, 0x04, 0x00, 0x00
+.data1 	0xff, 0x35, 0xa8, 0x23, 0x00, 0x00, 0xe8, 0x2e
+.data1 	0x45, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x83, 0x7d
+.data1 	0xe0, 0x00, 0x74, 0x0b, 0x68, 0xbc, 0x04, 0x00
+.data1 	0x00, 0xe8, 0x23, 0x43, 0x00, 0x00, 0x59, 0xa1
+.data1 	0xa8, 0x23, 0x00, 0x00, 0xff, 0x48, 0x04, 0x8b
+.data1 	0x15, 0xa8, 0x23, 0x00, 0x00, 0x83, 0x7a, 0x04
+.data1 	0x00, 0x79, 0x1a, 0xff, 0x35, 0xa8, 0x23, 0x00
+.data1 	0x00, 0xe8, 0x4e, 0x43, 0x00, 0x00, 0x59, 0xa1
+.data1 	0xa8, 0x23, 0x00, 0x00, 0x8b, 0x18, 0xff, 0x00
+.data1 	0xc6, 0x03, 0x0a, 0xeb, 0x0c, 0xa1, 0xa8, 0x23
+.data1 	0x00, 0x00, 0x8b, 0x18, 0xff, 0x00, 0xc6, 0x03
+.data1 	0x0a, 0x68, 0x7c, 0x23, 0x00, 0x00, 0xe8, 0x2f
+.data1 	0x44, 0x00, 0x00, 0x59, 0xeb, 0x0d, 0x83, 0x7d
+.data1 	0xec, 0x00, 0x74, 0x07, 0x8b, 0x55, 0xec, 0xc6
+.data1 	0x42, 0x1a, 0x01, 0x8b, 0x45, 0xfc, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0x7d, 0x08
+.data1 	0x00, 0x75, 0x07, 0xb8, 0x01, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x02, 0x31, 0xc0, 0x50, 0xff, 0x75, 0x0c
+.data1 	0x6a, 0xff, 0xe8, 0x31, 0x9d, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x04, 0x6a, 0x32, 0xe8, 0xa7, 0x0b, 0x00
+.data1 	0x00, 0x59, 0x89, 0x45, 0xfc, 0xa3, 0xdc, 0x31
+.data1 	0x00, 0x00, 0xc7, 0x05, 0xe0, 0x31, 0x00, 0x00
+.data1 	0x2e, 0x00, 0x00, 0x00, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x0f, 0x00, 0x00, 0x00, 0x59, 0x8b, 0x15, 0xdc
+.data1 	0x31, 0x00, 0x00, 0xc6, 0x02, 0x00, 0x8b, 0x45
+.data1 	0xfc, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x14, 0x56, 0x57, 0x8b, 0x75, 0x08, 0x85, 0xf6
+.data1 	0x0f, 0x85, 0xcd, 0x02, 0x00, 0x00, 0xe9, 0xd4
+.data1 	0x02, 0x00, 0x00, 0xff, 0x76, 0x04, 0xe8, 0xe0
+.data1 	0xff, 0xff, 0xff, 0x59, 0x68, 0xe4, 0x05, 0x00
+.data1 	0x00, 0xe8, 0xc5, 0x02, 0x00, 0x00, 0x59, 0xff
+.data1 	0x76, 0x08, 0xe8, 0xcc, 0xff, 0xff, 0xff, 0x59
+.data1 	0xe9, 0xb2, 0x02, 0x00, 0x00, 0xff, 0x76, 0x04
+.data1 	0xe8, 0xbe, 0xff, 0xff, 0xff, 0x59, 0x68, 0xdc
+.data1 	0x05, 0x00, 0x00, 0xe8, 0xa3, 0x02, 0x00, 0x00
+.data1 	0x59, 0xff, 0x76, 0x08, 0xe8, 0xaa, 0xff, 0xff
+.data1 	0xff, 0x59, 0xe9, 0x90, 0x02, 0x00, 0x00, 0xff
+.data1 	0x76, 0x04, 0xe8, 0x9c, 0xff, 0xff, 0xff, 0x59
+.data1 	0x68, 0xd4, 0x05, 0x00, 0x00, 0xe8, 0x81, 0x02
+.data1 	0x00, 0x00, 0x59, 0xff, 0x76, 0x08, 0xe8, 0x88
+.data1 	0xff, 0xff, 0xff, 0x59, 0xe9, 0x6e, 0x02, 0x00
+.data1 	0x00, 0x8b, 0x56, 0x08, 0x89, 0x55, 0xf8, 0x83
+.data1 	0x7d, 0xf8, 0x00, 0x0f, 0x84, 0x5e, 0x02, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xf8, 0xff, 0x72, 0x04, 0xe8
+.data1 	0x67, 0xff, 0xff, 0xff, 0x59, 0x8b, 0x45, 0xf8
+.data1 	0x83, 0x38, 0x00, 0x74, 0x0b, 0x68, 0xd0, 0x05
+.data1 	0x00, 0x00, 0xe8, 0x44, 0x02, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x45, 0xf8, 0x8b, 0x10, 0x89, 0x55, 0xf8
+.data1 	0xeb, 0xcd, 0x68, 0xcc, 0x05, 0x00, 0x00, 0xe8
+.data1 	0x2f, 0x02, 0x00, 0x00, 0x59, 0xff, 0x76, 0x04
+.data1 	0xe8, 0x36, 0xff, 0xff, 0xff, 0x59, 0x68, 0xc8
+.data1 	0x05, 0x00, 0x00, 0xe8, 0x1b, 0x02, 0x00, 0x00
+.data1 	0x59, 0xe9, 0x11, 0x02, 0x00, 0x00, 0xff, 0x76
+.data1 	0x04, 0xe8, 0x1d, 0xff, 0xff, 0xff, 0x59, 0xe9
+.data1 	0x03, 0x02, 0x00, 0x00, 0x68, 0xc4, 0x05, 0x00
+.data1 	0x00, 0xe8, 0xfd, 0x01, 0x00, 0x00, 0x59, 0xff
+.data1 	0x76, 0x04, 0xe8, 0x04, 0xff, 0xff, 0xff, 0x59
+.data1 	0x68, 0xbc, 0x05, 0x00, 0x00, 0xe8, 0xe9, 0x01
+.data1 	0x00, 0x00, 0x59, 0xff, 0x76, 0x08, 0xe8, 0xf0
+.data1 	0xfe, 0xff, 0xff, 0x59, 0x68, 0xb8, 0x05, 0x00
+.data1 	0x00, 0xe8, 0xd5, 0x01, 0x00, 0x00, 0x59, 0xe9
+.data1 	0xcb, 0x01, 0x00, 0x00, 0x68, 0xb0, 0x05, 0x00
+.data1 	0x00, 0xe8, 0xc5, 0x01, 0x00, 0x00, 0x59, 0xeb
+.data1 	0x0b, 0x68, 0xa8, 0x05, 0x00, 0x00, 0xe8, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x59, 0xff, 0x76, 0x04, 0xe8
+.data1 	0xbf, 0xfe, 0xff, 0xff, 0x59, 0x68, 0xa0, 0x05
+.data1 	0x00, 0x00, 0xe8, 0xa4, 0x01, 0x00, 0x00, 0x59
+.data1 	0xff, 0x76, 0x08, 0xe8, 0xab, 0xfe, 0xff, 0xff
+.data1 	0x59, 0x68, 0x98, 0x05, 0x00, 0x00, 0xe8, 0x90
+.data1 	0x01, 0x00, 0x00, 0x59, 0xe9, 0x86, 0x01, 0x00
+.data1 	0x00, 0x68, 0x90, 0x05, 0x00, 0x00, 0xe8, 0x80
+.data1 	0x01, 0x00, 0x00, 0x59, 0xff, 0x76, 0x0c, 0xe8
+.data1 	0x77, 0x01, 0x00, 0x00, 0x59, 0x68, 0x88, 0x05
+.data1 	0x00, 0x00, 0xe8, 0x6c, 0x01, 0x00, 0x00, 0x59
+.data1 	0xe9, 0x62, 0x01, 0x00, 0x00, 0x68, 0x80, 0x05
+.data1 	0x00, 0x00, 0xe8, 0x5c, 0x01, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x56, 0x04, 0xff, 0x72, 0x08, 0xe8, 0x50
+.data1 	0x01, 0x00, 0x00, 0x59, 0x68, 0x78, 0x05, 0x00
+.data1 	0x00, 0xe8, 0x45, 0x01, 0x00, 0x00, 0x59, 0xe9
+.data1 	0x3b, 0x01, 0x00, 0x00, 0xff, 0x76, 0x08, 0xe8
+.data1 	0x37, 0x01, 0x00, 0x00, 0x59, 0x68, 0x70, 0x05
+.data1 	0x00, 0x00, 0xe8, 0x2c, 0x01, 0x00, 0x00, 0x59
+.data1 	0xe9, 0x22, 0x01, 0x00, 0x00, 0x8b, 0x7e, 0x08
+.data1 	0x85, 0xff, 0x74, 0x1d, 0x57, 0xe8, 0x29, 0xfe
+.data1 	0xff, 0xff, 0x59, 0x83, 0x7f, 0x04, 0x00, 0x74
+.data1 	0x0b, 0x68, 0x6c, 0x05, 0x00, 0x00, 0xe8, 0x08
+.data1 	0x01, 0x00, 0x00, 0x59, 0x8b, 0x7f, 0x04, 0xeb
+.data1 	0xdf, 0x8b, 0x7e, 0x0c, 0x85, 0xff, 0x0f, 0x84
+.data1 	0xf3, 0x00, 0x00, 0x00, 0x68, 0x68, 0x05, 0x00
+.data1 	0x00, 0xe8, 0xed, 0x00, 0x00, 0x00, 0x59, 0x57
+.data1 	0xe8, 0xf6, 0xfd, 0xff, 0xff, 0x59, 0x8b, 0x7f
+.data1 	0x04, 0xeb, 0xe1, 0xff, 0x76, 0x08, 0xe8, 0xd8
+.data1 	0x00, 0x00, 0x00, 0x59, 0xe9, 0xce, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xf4, 0x64, 0x05, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xf0, 0x01, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x3e, 0xc7, 0x45, 0xf4, 0x60, 0x05, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xf0, 0x01, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x2e, 0xc7, 0x45, 0xf4, 0x5c, 0x05, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xf0, 0x01, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x1e, 0xc7, 0x45, 0xf4, 0x58, 0x05, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x0e, 0xc7, 0x45, 0xf4, 0x54, 0x05, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xf0, 0x39, 0x56, 0x08, 0x74, 0x19, 0xba
+.data1 	0x30, 0x00, 0x00, 0x00, 0x03, 0x56, 0x08, 0x88
+.data1 	0x55, 0xee, 0xc6, 0x45, 0xef, 0x00, 0x8d, 0x45
+.data1 	0xee, 0x50, 0xe8, 0x64, 0x00, 0x00, 0x00, 0x59
+.data1 	0xff, 0x75, 0xf4, 0xe8, 0x5b, 0x00, 0x00, 0x00
+.data1 	0x59, 0x83, 0x3e, 0x13, 0x74, 0x05, 0x83, 0x3e
+.data1 	0x14, 0x75, 0x1b, 0xba, 0x30, 0x00, 0x00, 0x00
+.data1 	0x03, 0x56, 0x0c, 0x88, 0x55, 0xee, 0xc6, 0x45
+.data1 	0xef, 0x00, 0x8d, 0x45, 0xee, 0x50, 0xe8, 0x38
+.data1 	0x00, 0x00, 0x00, 0x59, 0xeb, 0x31, 0xff, 0x76
+.data1 	0x0c, 0xe8, 0x3d, 0xfd, 0xff, 0xff, 0x59, 0xeb
+.data1 	0x26, 0x68, 0x4c, 0x05, 0x00, 0x00, 0xe8, 0x20
+.data1 	0x00, 0x00, 0x00, 0x59, 0xeb, 0x19, 0x68, 0x48
+.data1 	0x05, 0x00, 0x00, 0xe8, 0x13, 0x00, 0x00, 0x00
+.data1 	0x59, 0xeb, 0x0c, 0xbb, 0xe0, 0x04, 0x00, 0x00
+.data1 	0x8b, 0x06, 0xe9, 0x69, 0xa7, 0x00, 0x00, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x10, 0x56, 0x57, 0xc7, 0x45, 0xf0, 0x00, 0x00
+.data1 	0x00, 0x00, 0x83, 0x3d, 0xe0, 0x31, 0x00, 0x00
+.data1 	0x00, 0x0f, 0x8e, 0xef, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x7d, 0x08, 0x8b, 0x35, 0xdc, 0x31, 0x00, 0x00
+.data1 	0x8a, 0x07, 0x47, 0x88, 0x45, 0xf7, 0x0f, 0xb6
+.data1 	0xd0, 0x84, 0xd2, 0x0f, 0x84, 0xcf, 0x00, 0x00
+.data1 	0x00, 0x0f, 0xbe, 0x45, 0xf7, 0x3d, 0x81, 0xff
+.data1 	0xff, 0xff, 0x75, 0x0b, 0x8a, 0x07, 0x47, 0x88
+.data1 	0x06, 0x46, 0xe9, 0x98, 0x00, 0x00, 0x00, 0x0f
+.data1 	0xbe, 0x45, 0xf7, 0x3d, 0x82, 0xff, 0xff, 0xff
+.data1 	0x75, 0x25, 0xc6, 0x06, 0x24, 0x46, 0x8b, 0x15
+.data1 	0xe0, 0x31, 0x00, 0x00, 0x4a, 0x89, 0x15, 0xe0
+.data1 	0x31, 0x00, 0x00, 0x85, 0xd2, 0x7e, 0x04, 0xc6
+.data1 	0x06, 0x7b, 0x46, 0x0f, 0xbe, 0x07, 0x47, 0x89
+.data1 	0x45, 0xf0, 0xe9, 0x68, 0x00, 0x00, 0x00, 0x80
+.data1 	0x7d, 0xf7, 0x3d, 0x75, 0x23, 0x83, 0x7d, 0xf0
+.data1 	0x00, 0x74, 0x1d, 0xba, 0x07, 0x00, 0x00, 0x00
+.data1 	0x23, 0x55, 0xf0, 0x4a, 0x89, 0xd0, 0x8a, 0x88
+.data1 	0xe8, 0x05, 0x00, 0x00, 0x88, 0x0e, 0x46, 0xc7
+.data1 	0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x3f
+.data1 	0x0f, 0xbe, 0x45, 0xf7, 0x3d, 0x83, 0xff, 0xff
+.data1 	0xff, 0x75, 0x06, 0xc6, 0x06, 0x7d, 0x46, 0xeb
+.data1 	0x2e, 0x0f, 0xbe, 0x45, 0xf7, 0x31, 0xdb, 0x3d
+.data1 	0x84, 0xff, 0xff, 0xff, 0x75, 0x01, 0x43, 0x0f
+.data1 	0xbe, 0x45, 0xf7, 0x31, 0xc9, 0x3d, 0x85, 0xff
+.data1 	0xff, 0xff, 0x75, 0x01, 0x41, 0x09, 0xd9, 0x74
+.data1 	0x08, 0xff, 0x05, 0xe0, 0x31, 0x00, 0x00, 0xeb
+.data1 	0x06, 0x8a, 0x4d, 0xf7, 0x88, 0x0e, 0x46, 0x8b
+.data1 	0x15, 0xe0, 0x31, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0xe0, 0x31, 0x00, 0x00, 0x85, 0xd2, 0x0f, 0x8f
+.data1 	0x2c, 0xff, 0xff, 0xff, 0xc6, 0x06, 0x2e, 0x46
+.data1 	0xc6, 0x06, 0x2e, 0x46, 0xc6, 0x06, 0x2e, 0x46
+.data1 	0x89, 0x35, 0xdc, 0x31, 0x00, 0x00, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x40, 0x56, 0x57, 0x83, 0x7d, 0x08, 0x00
+.data1 	0x74, 0x0a, 0xc7, 0x05, 0xe4, 0x31, 0x00, 0x00
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x83, 0x3d, 0xe4, 0x31
+.data1 	0x00, 0x00, 0x00, 0x0f, 0x84, 0x34, 0x01, 0x00
+.data1 	0x00, 0x8d, 0x45, 0xe4, 0x50, 0xe8, 0xad, 0x08
+.data1 	0x00, 0x00, 0x59, 0x8b, 0x15, 0x14, 0x32, 0x00
+.data1 	0x00, 0xf6, 0xc2, 0x20, 0x75, 0x0b, 0x8b, 0x15
+.data1 	0x18, 0x32, 0x00, 0x00, 0x8d, 0x42, 0x09, 0xeb
+.data1 	0x09, 0x8b, 0x15, 0x24, 0x32, 0x00, 0x00, 0x8d
+.data1 	0x42, 0x05, 0x89, 0x45, 0xf8, 0x31, 0xff, 0x39
+.data1 	0x3d, 0xe4, 0x31, 0x00, 0x00, 0x0f, 0x8e, 0xea
+.data1 	0x00, 0x00, 0x00, 0x68, 0x88, 0x2c, 0x00, 0x00
+.data1 	0x8d, 0x45, 0xf8, 0x50, 0xe8, 0x41, 0xc8, 0xff
+.data1 	0xff, 0x59, 0x59, 0x89, 0x45, 0xf4, 0x85, 0xc0
+.data1 	0x0f, 0x84, 0xcf, 0x00, 0x00, 0x00, 0x80, 0x38
+.data1 	0x00, 0x0f, 0x84, 0xc0, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x75, 0xf4, 0x80, 0x3e, 0x00, 0x74, 0x03, 0x46
+.data1 	0xeb, 0xf8, 0x80, 0x7e, 0xff, 0x2f, 0x74, 0x05
+.data1 	0xe8, 0x4b, 0x81, 0x00, 0x00, 0xc6, 0x46, 0xff
+.data1 	0x00, 0x8d, 0x45, 0xc0, 0x50, 0xff, 0x75, 0xf4
+.data1 	0xe8, 0x2b, 0x98, 0x00, 0x00, 0x59, 0x59, 0x85
+.data1 	0xc0, 0x79, 0x07, 0xc7, 0x45, 0xdc, 0x00, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7d, 0x08, 0x00, 0x0f, 0x85
+.data1 	0x79, 0x00, 0x00, 0x00, 0x83, 0x7d, 0xd4, 0x00
+.data1 	0x0f, 0x84, 0x6f, 0x00, 0x00, 0x00, 0x8b, 0x55
+.data1 	0xdc, 0x39, 0x14, 0xbd, 0xe8, 0x31, 0x00, 0x00
+.data1 	0x0f, 0x8d, 0x5f, 0x00, 0x00, 0x00, 0x39, 0x55
+.data1 	0xd8, 0x0f, 0x8d, 0x56, 0x00, 0x00, 0x00, 0x83
+.data1 	0x3d, 0xec, 0x2c, 0x00, 0x00, 0x00, 0x74, 0x07
+.data1 	0xa1, 0xec, 0x2c, 0x00, 0x00, 0xeb, 0x05, 0xb8
+.data1 	0xf0, 0x05, 0x00, 0x00, 0x50, 0xe8, 0x6f, 0x3d
+.data1 	0x00, 0x00, 0x59, 0xa1, 0xa8, 0x23, 0x00, 0x00
+.data1 	0xff, 0x48, 0x04, 0x8b, 0x15, 0xa8, 0x23, 0x00
+.data1 	0x00, 0x83, 0x7a, 0x04, 0x00, 0x79, 0x1a, 0xff
+.data1 	0x35, 0xa8, 0x23, 0x00, 0x00, 0xe8, 0x9a, 0x3d
+.data1 	0x00, 0x00, 0x59, 0xa1, 0xa8, 0x23, 0x00, 0x00
+.data1 	0x8b, 0x18, 0xff, 0x00, 0xc6, 0x03, 0x0a, 0xeb
+.data1 	0x0c, 0xa1, 0xa8, 0x23, 0x00, 0x00, 0x8b, 0x18
+.data1 	0xff, 0x00, 0xc6, 0x03, 0x0a, 0x8b, 0x55, 0xdc
+.data1 	0x89, 0x14, 0xbd, 0xe8, 0x31, 0x00, 0x00, 0x47
+.data1 	0xe9, 0x0a, 0xff, 0xff, 0xff, 0x89, 0x3d, 0xe4
+.data1 	0x31, 0x00, 0x00, 0x8d, 0x45, 0xe4, 0x50, 0xe8
+.data1 	0xab, 0x07, 0x00, 0x00, 0x59, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x34, 0x56, 0x57, 0xc7, 0x45, 0xd0, 0x00
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x45, 0xcc, 0x00, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x45, 0xdc, 0x00, 0x00, 0x00
+.data1 	0x00, 0xff, 0x35, 0x00, 0x06, 0x00, 0x00, 0x6a
+.data1 	0x01, 0x8d, 0x45, 0xec, 0x50, 0xe8, 0xde, 0x98
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x0f
+.data1 	0x84, 0xf5, 0x00, 0x00, 0x00, 0x83, 0x3d, 0x98
+.data1 	0x2c, 0x00, 0x00, 0x02, 0x75, 0x27, 0xe8, 0xd5
+.data1 	0x96, 0x00, 0x00, 0xa3, 0x9c, 0x2d, 0x00, 0x00
+.data1 	0xc7, 0x05, 0xa0, 0x2c, 0x00, 0x00, 0x01, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x05, 0x30, 0x32, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xdc, 0x03
+.data1 	0x00, 0x00, 0x00, 0xeb, 0x22, 0xff, 0x75, 0xdc
+.data1 	0x5a, 0x85, 0xd2, 0x74, 0x12, 0x80, 0x3d, 0x77
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x74, 0x09, 0x83, 0x3d
+.data1 	0xa0, 0x2c, 0x00, 0x00, 0x00, 0x75, 0x08, 0x6a
+.data1 	0x02, 0xe8, 0xeb, 0x3b, 0x00, 0x00, 0x59, 0xe8
+.data1 	0x43, 0x4e, 0x00, 0x00, 0x83, 0x3d, 0x98, 0x2c
+.data1 	0x00, 0x00, 0x00, 0x75, 0x45, 0xa1, 0xa8, 0x23
+.data1 	0x00, 0x00, 0xff, 0x48, 0x04, 0x8b, 0x15, 0xa8
+.data1 	0x23, 0x00, 0x00, 0x83, 0x7a, 0x04, 0x00, 0x79
+.data1 	0x1a, 0xff, 0x35, 0xa8, 0x23, 0x00, 0x00, 0xe8
+.data1 	0xa0, 0x3c, 0x00, 0x00, 0x59, 0xa1, 0xa8, 0x23
+.data1 	0x00, 0x00, 0x8b, 0x18, 0xff, 0x00, 0xc6, 0x03
+.data1 	0x0a, 0xeb, 0x0c, 0xa1, 0xa8, 0x23, 0x00, 0x00
+.data1 	0x8b, 0x18, 0xff, 0x00, 0xc6, 0x03, 0x0a, 0x68
+.data1 	0x7c, 0x23, 0x00, 0x00, 0xe8, 0x81, 0x3d, 0x00
+.data1 	0x00, 0x59, 0x8d, 0x45, 0xe0, 0x50, 0xe8, 0xbc
+.data1 	0x06, 0x00, 0x00, 0x59, 0xc7, 0x05, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x35
+.data1 	0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74
+.data1 	0x05, 0xe8, 0x69, 0xb0, 0xff, 0xff, 0xff, 0x75
+.data1 	0xdc, 0x5a, 0x83, 0xfa, 0x01, 0x0f, 0x84, 0xa1
+.data1 	0x00, 0x00, 0x00, 0xff, 0x75, 0xdc, 0x5a, 0x83
+.data1 	0xfa, 0x02, 0x0f, 0x84, 0x31, 0x01, 0x00, 0x00
+.data1 	0xff, 0x75, 0xdc, 0x5a, 0x83, 0xfa, 0x03, 0x0f
+.data1 	0x85, 0x03, 0x02, 0x00, 0x00, 0xe9, 0x97, 0x01
+.data1 	0x00, 0x00, 0x8d, 0x55, 0xec, 0x89, 0x15, 0x94
+.data1 	0x2c, 0x00, 0x00, 0xe8, 0xe0, 0x95, 0x00, 0x00
+.data1 	0xa3, 0x9c, 0x2d, 0x00, 0x00, 0xc7, 0x05, 0xa0
+.data1 	0x2c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe8
+.data1 	0x3c, 0x4d, 0x00, 0x00, 0x8d, 0x45, 0xe0, 0x50
+.data1 	0xe8, 0x22, 0x06, 0x00, 0x00, 0x59, 0xff, 0x75
+.data1 	0x0c, 0xff, 0x75, 0x08, 0xe8, 0xd7, 0x10, 0x00
+.data1 	0x00, 0x59, 0x59, 0x80, 0x3d, 0x74, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x74, 0x07, 0xc6, 0x05, 0x74, 0x2c
+.data1 	0x00, 0x00, 0x02, 0x80, 0x3d, 0x7b, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x74, 0x07, 0xc6, 0x05, 0x7b, 0x2c
+.data1 	0x00, 0x00, 0x02, 0x8b, 0x45, 0x0c, 0x83, 0x38
+.data1 	0x00, 0x0f, 0x84, 0x86, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x10, 0x80, 0x3a, 0x2d, 0x0f, 0x85, 0x7b, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x45, 0xdc, 0x01, 0x00, 0x00
+.data1 	0x00, 0x68, 0x3c, 0x06, 0x00, 0x00, 0xe8, 0xb2
+.data1 	0x02, 0x00, 0x00, 0x59, 0xc7, 0x45, 0xdc, 0x02
+.data1 	0x00, 0x00, 0x00, 0x68, 0x34, 0x06, 0x00, 0x00
+.data1 	0xe8, 0xa3, 0x7f, 0x00, 0x00, 0x59, 0x89, 0x45
+.data1 	0xd4, 0x85, 0xc0, 0x74, 0x43, 0xff, 0x75, 0xd4
+.data1 	0xe8, 0xdb, 0x96, 0x00, 0x00, 0x59, 0x05, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x50, 0xe8, 0x5e, 0x80, 0x00
+.data1 	0x00, 0x59, 0x89, 0x45, 0xd0, 0x85, 0xc0, 0x74
+.data1 	0x27, 0xff, 0x75, 0xd4, 0xff, 0x75, 0xd0, 0xe8
+.data1 	0x9c, 0x96, 0x00, 0x00, 0x59, 0x59, 0x68, 0x28
+.data1 	0x06, 0x00, 0x00, 0xff, 0x75, 0xd0, 0xe8, 0x2d
+.data1 	0x96, 0x00, 0x00, 0x59, 0x59, 0xff, 0x75, 0xd0
+.data1 	0xe8, 0x58, 0x02, 0x00, 0x00, 0x59, 0xeb, 0x41
+.data1 	0x68, 0x1c, 0x06, 0x00, 0x00, 0xe8, 0x4b, 0x02
+.data1 	0x00, 0x00, 0x59, 0xeb, 0x34, 0x80, 0x3d, 0x7a
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x75, 0x09, 0x83, 0x3d
+.data1 	0x30, 0x32, 0x00, 0x00, 0x00, 0x74, 0x22, 0x68
+.data1 	0x14, 0x06, 0x00, 0x00, 0xe8, 0x2f, 0x7f, 0x00
+.data1 	0x00, 0x59, 0x89, 0x45, 0xd8, 0x85, 0xc0, 0x74
+.data1 	0x10, 0xc7, 0x45, 0xdc, 0x02, 0x00, 0x00, 0x00
+.data1 	0xff, 0x75, 0xd8, 0xe8, 0x02, 0xb1, 0xff, 0xff
+.data1 	0x59, 0x83, 0x7d, 0xd0, 0x00, 0x74, 0x09, 0xff
+.data1 	0x75, 0xd0, 0xe8, 0xf7, 0x81, 0x00, 0x00, 0x59
+.data1 	0xc7, 0x45, 0xdc, 0x03, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x45, 0x0c, 0x83, 0x38, 0x00, 0x74, 0x07, 0x8b
+.data1 	0x10, 0x80, 0x3a, 0x2d, 0x74, 0x53, 0x68, 0x0c
+.data1 	0x06, 0x00, 0x00, 0xe8, 0xe8, 0x7e, 0x00, 0x00
+.data1 	0x59, 0x89, 0x45, 0xd4, 0x85, 0xc0, 0x74, 0x41
+.data1 	0xff, 0x75, 0xd4, 0xe8, 0x20, 0x96, 0x00, 0x00
+.data1 	0x59, 0x05, 0x08, 0x00, 0x00, 0x00, 0x50, 0xe8
+.data1 	0xa3, 0x7f, 0x00, 0x00, 0x59, 0x89, 0x45, 0xcc
+.data1 	0x85, 0xc0, 0x74, 0x25, 0xff, 0x75, 0xd4, 0xff
+.data1 	0x75, 0xcc, 0xe8, 0xe1, 0x95, 0x00, 0x00, 0x59
+.data1 	0x59, 0x68, 0x04, 0x06, 0x00, 0x00, 0xff, 0x75
+.data1 	0xcc, 0xe8, 0x72, 0x95, 0x00, 0x00, 0x59, 0x59
+.data1 	0xff, 0x75, 0xcc, 0xe8, 0x9d, 0x01, 0x00, 0x00
+.data1 	0x59, 0x83, 0x7d, 0xcc, 0x00, 0x74, 0x09, 0xff
+.data1 	0x75, 0xcc, 0xe8, 0x7f, 0x81, 0x00, 0x00, 0x59
+.data1 	0x80, 0x3d, 0x74, 0x2c, 0x00, 0x00, 0x00, 0x74
+.data1 	0x07, 0xc6, 0x05, 0x74, 0x2c, 0x00, 0x00, 0x01
+.data1 	0x80, 0x3d, 0x7b, 0x2c, 0x00, 0x00, 0x00, 0x74
+.data1 	0x07, 0xc6, 0x05, 0x7b, 0x2c, 0x00, 0x00, 0x01
+.data1 	0xc7, 0x05, 0xa4, 0x2c, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x45, 0xdc, 0x04, 0x00, 0x00
+.data1 	0x00, 0x83, 0x3d, 0x30, 0x32, 0x00, 0x00, 0x00
+.data1 	0x74, 0x0c, 0xff, 0x35, 0x30, 0x32, 0x00, 0x00
+.data1 	0xe8, 0x35, 0xb0, 0xff, 0xff, 0x59, 0x80, 0x3d
+.data1 	0x7a, 0x2c, 0x00, 0x00, 0x00, 0x75, 0x09, 0x83
+.data1 	0x3d, 0x30, 0x32, 0x00, 0x00, 0x00, 0x75, 0x08
+.data1 	0x6a, 0x01, 0xe8, 0x11, 0x00, 0x00, 0x00, 0x59
+.data1 	0xff, 0x35, 0xa4, 0x2c, 0x00, 0x00, 0xe8, 0x36
+.data1 	0x39, 0x00, 0x00, 0x59, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x18, 0x56, 0x57
+.data1 	0x8d, 0x45, 0xf0, 0x50, 0xe8, 0x26, 0x04, 0x00
+.data1 	0x00, 0x59, 0xc7, 0x45, 0xe8, 0x00, 0x00, 0x00
+.data1 	0x00, 0x83, 0x3d, 0xc0, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x74, 0x05, 0xe8, 0x7d, 0x38, 0x00, 0x00, 0x31
+.data1 	0xff, 0x80, 0x3d, 0x77, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x74, 0x22, 0x83, 0x7d, 0x08, 0x00, 0x74, 0x1c
+.data1 	0x47, 0x6a, 0x01, 0xe8, 0x53, 0xeb, 0xff, 0xff
+.data1 	0x59, 0x6a, 0x00, 0xe8, 0x14, 0xfb, 0xff, 0xff
+.data1 	0x59, 0x68, 0x68, 0x23, 0x00, 0x00, 0xe8, 0xc7
+.data1 	0x3a, 0x00, 0x00, 0x59, 0x57, 0xe8, 0x8e, 0x15
+.data1 	0x00, 0x00, 0x59, 0x89, 0xc6, 0x81, 0xfe, 0xc4
+.data1 	0x2c, 0x00, 0x00, 0x75, 0x2a, 0x80, 0x3d, 0x76
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x0f, 0x84, 0x9d, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7d, 0xe8, 0x32, 0x0f, 0x8d
+.data1 	0x93, 0x00, 0x00, 0x00, 0x68, 0x4c, 0x06, 0x00
+.data1 	0x00, 0xe8, 0x43, 0x39, 0x00, 0x00, 0x59, 0xff
+.data1 	0x45, 0xe8, 0xe9, 0x71, 0x00, 0x00, 0x00, 0x85
+.data1 	0xf6, 0x0f, 0x84, 0x69, 0x00, 0x00, 0x00, 0x80
+.data1 	0x3d, 0x79, 0x2c, 0x00, 0x00, 0x00, 0x75, 0x60
+.data1 	0x85, 0xff, 0x74, 0x52, 0xff, 0x05, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x83, 0x3d, 0x2c, 0x32, 0x00, 0x00
+.data1 	0x00, 0x74, 0x0c, 0xff, 0x35, 0x2c, 0x32, 0x00
+.data1 	0x00, 0xe8, 0x25, 0x0e, 0x00, 0x00, 0x59, 0x8b
+.data1 	0x15, 0x28, 0x32, 0x00, 0x00, 0x89, 0x15, 0x2c
+.data1 	0x32, 0x00, 0x00, 0x56, 0xe8, 0xe7, 0x09, 0x00
+.data1 	0x00, 0x59, 0xa3, 0x28, 0x32, 0x00, 0x00, 0x8b
+.data1 	0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x75, 0x10, 0xff, 0x35
+.data1 	0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74
+.data1 	0x05, 0xe8, 0x31, 0xad, 0xff, 0xff, 0x6a, 0x00
+.data1 	0x56, 0xe8, 0x63, 0xaf, 0xff, 0xff, 0x59, 0x59
+.data1 	0x8d, 0x45, 0xf0, 0x50, 0xe8, 0x56, 0x03, 0x00
+.data1 	0x00, 0x59, 0xe9, 0x0a, 0xff, 0xff, 0xff, 0x8d
+.data1 	0x45, 0xf0, 0x50, 0xe8, 0x47, 0x03, 0x00, 0x00
+.data1 	0x59, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0xff, 0x05, 0x90, 0x2c, 0x00, 0x00, 0x6a
+.data1 	0x00, 0xff, 0x75, 0x08, 0xe8, 0xd7, 0x92, 0x00
+.data1 	0x00, 0x59, 0x59, 0x89, 0xc6, 0x85, 0xc0, 0x78
+.data1 	0x0a, 0x6a, 0x01, 0x56, 0xe8, 0x23, 0xe8, 0xff
+.data1 	0xff, 0x59, 0x59, 0x8b, 0x15, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00
+.data1 	0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8, 0xc5, 0xac
+.data1 	0xff, 0xff, 0x85, 0xf6, 0x78, 0x0d, 0x6a, 0x00
+.data1 	0xe8, 0x93, 0xfe, 0xff, 0xff, 0x59, 0xe8, 0x3f
+.data1 	0xe9, 0xff, 0xff, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x04, 0xff, 0x05, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x6a, 0x00, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x7c, 0x92, 0x00, 0x00, 0x59, 0x59, 0x89, 0x45
+.data1 	0xfc, 0x85, 0xc0, 0x78, 0x0e, 0x6a, 0x01, 0xff
+.data1 	0x75, 0xfc, 0xe8, 0xc5, 0xe7, 0xff, 0xff, 0x59
+.data1 	0x59, 0xeb, 0x0f, 0xff, 0x75, 0x08, 0x68, 0x6c
+.data1 	0x06, 0x00, 0x00, 0xe8, 0xd8, 0xac, 0xff, 0xff
+.data1 	0x59, 0x59, 0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x75
+.data1 	0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a
+.data1 	0x85, 0xd2, 0x74, 0x05, 0xe8, 0x56, 0xac, 0xff
+.data1 	0xff, 0x6a, 0x00, 0xe8, 0x28, 0xfe, 0xff, 0xff
+.data1 	0x59, 0xe8, 0xd4, 0xe8, 0xff, 0xff, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0xc7, 0x05, 0xa4, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x7d, 0x08
+.data1 	0x02, 0x7c, 0x28, 0x8b, 0x55, 0x0c, 0x6a, 0x01
+.data1 	0xff, 0x72, 0x04, 0xe8, 0xe1, 0xe6, 0xff, 0xff
+.data1 	0x59, 0x59, 0x8b, 0x55, 0x0c, 0x8b, 0x52, 0x04
+.data1 	0x89, 0x15, 0x9c, 0x2c, 0x00, 0x00, 0x6a, 0x00
+.data1 	0xe8, 0xeb, 0xfd, 0xff, 0xff, 0x59, 0xe8, 0x97
+.data1 	0xe8, 0xff, 0xff, 0xa1, 0xa4, 0x2c, 0x00, 0x00
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0x7d, 0x08
+.data1 	0x01, 0x7e, 0x13, 0x8b, 0x55, 0x0c, 0xff, 0x72
+.data1 	0x04, 0xe8, 0x2f, 0x08, 0x00, 0x00, 0x59, 0xa3
+.data1 	0xa4, 0x2c, 0x00, 0x00, 0xeb, 0x0c, 0x8b, 0x15
+.data1 	0xbc, 0x2c, 0x00, 0x00, 0x89, 0x15, 0xa4, 0x2c
+.data1 	0x00, 0x00, 0xff, 0x35, 0xa4, 0x2c, 0x00, 0x00
+.data1 	0xe8, 0xdc, 0x36, 0x00, 0x00, 0x59, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0x7d, 0x08, 0x01, 0x7e
+.data1 	0x17, 0x8b, 0x55, 0x0c, 0xff, 0x35, 0x2c, 0x32
+.data1 	0x00, 0x00, 0xff, 0x72, 0x04, 0xe8, 0xa5, 0xcb
+.data1 	0xff, 0xff, 0x59, 0x59, 0x31, 0xc0, 0xeb, 0x5b
+.data1 	0xff, 0x05, 0x90, 0x2c, 0x00, 0x00, 0xff, 0x35
+.data1 	0x28, 0x32, 0x00, 0x00, 0xe8, 0x5a, 0x0c, 0x00
+.data1 	0x00, 0x59, 0x8b, 0x15, 0x2c, 0x32, 0x00, 0x00
+.data1 	0x89, 0x15, 0x28, 0x32, 0x00, 0x00, 0xc7, 0x05
+.data1 	0x2c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89
+.data1 	0x15, 0x90, 0x2c, 0x00, 0x00, 0x75, 0x10, 0xff
+.data1 	0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2
+.data1 	0x74, 0x05, 0xe8, 0x68, 0xab, 0xff, 0xff, 0x6a
+.data1 	0x00, 0xff, 0x35, 0x28, 0x32, 0x00, 0x00, 0xe8
+.data1 	0x95, 0xad, 0xff, 0xff, 0x59, 0x59, 0xa1, 0xa4
+.data1 	0x2c, 0x00, 0x00, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x13, 0x7c, 0x00, 0x00, 0x59, 0x89, 0xc6, 0x85
+.data1 	0xc0, 0x75, 0x0b, 0x68, 0x7c, 0x06, 0x00, 0x00
+.data1 	0xe8, 0x93, 0xab, 0xff, 0xff, 0x59, 0x89, 0xf0
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b
+.data1 	0x75, 0x08, 0xff, 0x75, 0x0c, 0x56, 0xe8, 0xf9
+.data1 	0x7c, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc6, 0x85
+.data1 	0xc0, 0x75, 0x0b, 0x68, 0x8c, 0x06, 0x00, 0x00
+.data1 	0xe8, 0x6b, 0xab, 0xff, 0xff, 0x59, 0x89, 0xf0
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0xff
+.data1 	0x75, 0x08, 0xe8, 0x39, 0x92, 0x00, 0x00, 0x59
+.data1 	0x40, 0x50, 0xe8, 0xa1, 0xff, 0xff, 0xff, 0x59
+.data1 	0x89, 0xc6, 0xff, 0x75, 0x08, 0x56, 0xe8, 0x05
+.data1 	0x92, 0x00, 0x00, 0x59, 0x59, 0x89, 0xf0, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c
+.data1 	0x56, 0x57, 0xba, 0x03, 0x00, 0x00, 0x00, 0x03
+.data1 	0x55, 0x08, 0x83, 0xe2, 0xfc, 0x89, 0x55, 0x08
+.data1 	0x39, 0x15, 0xac, 0x1c, 0x00, 0x00, 0x0f, 0x8d
+.data1 	0x68, 0x00, 0x00, 0x00, 0x8b, 0x7d, 0x08, 0x81
+.data1 	0xff, 0xf8, 0x01, 0x00, 0x00, 0x7d, 0x05, 0xbf
+.data1 	0xf8, 0x01, 0x00, 0x00, 0xff, 0x05, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x8d, 0x47, 0x04, 0x50, 0xe8, 0x4d
+.data1 	0xff, 0xff, 0xff, 0x59, 0x89, 0x45, 0xf4, 0x8b
+.data1 	0x15, 0xa4, 0x1c, 0x00, 0x00, 0x8b, 0x45, 0xf4
+.data1 	0x89, 0x10, 0x8b, 0x55, 0xf4, 0x83, 0xc2, 0x04
+.data1 	0x89, 0x15, 0xa8, 0x1c, 0x00, 0x00, 0x89, 0x3d
+.data1 	0xac, 0x1c, 0x00, 0x00, 0x8b, 0x55, 0xf4, 0x89
+.data1 	0x15, 0xa4, 0x1c, 0x00, 0x00, 0x8b, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c
+.data1 	0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8
+.data1 	0x53, 0xaa, 0xff, 0xff, 0x8b, 0x35, 0xa8, 0x1c
+.data1 	0x00, 0x00, 0x8b, 0x55, 0x08, 0x03, 0x15, 0xa8
+.data1 	0x1c, 0x00, 0x00, 0x89, 0x15, 0xa8, 0x1c, 0x00
+.data1 	0x00, 0x8b, 0x15, 0xac, 0x1c, 0x00, 0x00, 0x2b
+.data1 	0x55, 0x08, 0x89, 0x15, 0xac, 0x1c, 0x00, 0x00
+.data1 	0x89, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0x7d, 0x08, 0x00, 0x75, 0x16, 0x6a
+.data1 	0x0a, 0x68, 0x9c, 0x06, 0x00, 0x00, 0x6a, 0x02
+.data1 	0xe8, 0x43, 0x90, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xe8, 0x23, 0x79, 0x00, 0x00, 0x8b, 0x15, 0xa8
+.data1 	0x1c, 0x00, 0x00, 0x2b, 0x55, 0x08, 0x01, 0x15
+.data1 	0xac, 0x1c, 0x00, 0x00, 0x8b, 0x55, 0x08, 0x89
+.data1 	0x15, 0xa8, 0x1c, 0x00, 0x00, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x8b, 0x15, 0xa4, 0x1c, 0x00, 0x00
+.data1 	0x8b, 0x45, 0x08, 0x89, 0x10, 0x8b, 0x55, 0x08
+.data1 	0x8b, 0x0d, 0xa8, 0x1c, 0x00, 0x00, 0x89, 0x4a
+.data1 	0x04, 0x8b, 0x55, 0x08, 0x8b, 0x0d, 0xac, 0x1c
+.data1 	0x00, 0x00, 0x89, 0x4a, 0x08, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0xff, 0x05, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x45, 0x08, 0x8b, 0x15, 0xa4, 0x1c
+.data1 	0x00, 0x00, 0x39, 0x10, 0x74, 0x17, 0x8b, 0x35
+.data1 	0xa4, 0x1c, 0x00, 0x00, 0x8b, 0x16, 0x89, 0x15
+.data1 	0xa4, 0x1c, 0x00, 0x00, 0x56, 0xe8, 0x84, 0x7c
+.data1 	0x00, 0x00, 0x59, 0xeb, 0xdc, 0x8b, 0x55, 0x08
+.data1 	0x8b, 0x52, 0x04, 0x89, 0x15, 0xa8, 0x1c, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x08, 0x8b, 0x52, 0x08, 0x89
+.data1 	0x15, 0xac, 0x1c, 0x00, 0x00, 0x8b, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c
+.data1 	0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8
+.data1 	0x63, 0xa9, 0xff, 0xff, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x10, 0x56, 0x57, 0x8b
+.data1 	0x15, 0xac, 0x1c, 0x00, 0x00, 0xd1, 0xe2, 0xbf
+.data1 	0x64, 0x00, 0x00, 0x00, 0x01, 0xd7, 0x8b, 0x15
+.data1 	0xa8, 0x1c, 0x00, 0x00, 0x89, 0x55, 0xf4, 0x8b
+.data1 	0x15, 0xac, 0x1c, 0x00, 0x00, 0x89, 0x55, 0xf0
+.data1 	0x8b, 0x15, 0xa4, 0x1c, 0x00, 0x00, 0x83, 0xc2
+.data1 	0x04, 0x39, 0x15, 0xa8, 0x1c, 0x00, 0x00, 0x0f
+.data1 	0x85, 0x6c, 0x00, 0x00, 0x00, 0x81, 0x3d, 0xa4
+.data1 	0x1c, 0x00, 0x00, 0x34, 0x32, 0x00, 0x00, 0x74
+.data1 	0x60, 0xff, 0x05, 0x90, 0x2c, 0x00, 0x00, 0x8b
+.data1 	0x35, 0xa4, 0x1c, 0x00, 0x00, 0x8b, 0x16, 0x89
+.data1 	0x15, 0xa4, 0x1c, 0x00, 0x00, 0x8d, 0x47, 0x04
+.data1 	0x50, 0x56, 0xe8, 0xcc, 0xfd, 0xff, 0xff, 0x59
+.data1 	0x59, 0x89, 0xc6, 0x8b, 0x15, 0xa4, 0x1c, 0x00
+.data1 	0x00, 0x89, 0x16, 0x89, 0x35, 0xa4, 0x1c, 0x00
+.data1 	0x00, 0x8d, 0x56, 0x04, 0x89, 0x15, 0xa8, 0x1c
+.data1 	0x00, 0x00, 0x89, 0x3d, 0xac, 0x1c, 0x00, 0x00
+.data1 	0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89
+.data1 	0x15, 0x90, 0x2c, 0x00, 0x00, 0x75, 0x3c, 0xff
+.data1 	0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2
+.data1 	0x74, 0x31, 0xe8, 0xb8, 0xa8, 0xff, 0xff, 0xeb
+.data1 	0x2a, 0x57, 0xe8, 0xd3, 0xfd, 0xff, 0xff, 0x59
+.data1 	0x89, 0x45, 0xfc, 0xff, 0x75, 0xf0, 0xff, 0x75
+.data1 	0xfc, 0xff, 0x75, 0xf4, 0xe8, 0x97, 0x04, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x55, 0xfc, 0x89
+.data1 	0x15, 0xa8, 0x1c, 0x00, 0x00, 0x01, 0x3d, 0xac
+.data1 	0x1c, 0x00, 0x00, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0x8b, 0x75, 0x08, 0x8d, 0x56
+.data1 	0x03, 0x83, 0xe2, 0xfc, 0x89, 0xd6, 0x89, 0xf2
+.data1 	0x03, 0x15, 0xa8, 0x1c, 0x00, 0x00, 0x89, 0x15
+.data1 	0xa8, 0x1c, 0x00, 0x00, 0x8b, 0x15, 0xac, 0x1c
+.data1 	0x00, 0x00, 0x29, 0xf2, 0x89, 0x15, 0xac, 0x1c
+.data1 	0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0x8b, 0x35, 0xac, 0x1c, 0x00, 0x00, 0x83
+.data1 	0x3d, 0xb0, 0x1c, 0x00, 0x00, 0x00, 0x78, 0x2d
+.data1 	0x81, 0xfe, 0x00, 0x04, 0x00, 0x00, 0x7c, 0x25
+.data1 	0x56, 0xff, 0x35, 0xa8, 0x1c, 0x00, 0x00, 0xff
+.data1 	0x35, 0xb0, 0x1c, 0x00, 0x00, 0xe8, 0xe0, 0x3a
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0xf2, 0x4a
+.data1 	0x89, 0x15, 0x84, 0x2c, 0x00, 0x00, 0xa1, 0xa8
+.data1 	0x1c, 0x00, 0x00, 0xeb, 0x1e, 0xe8, 0xb5, 0xfe
+.data1 	0xff, 0xff, 0x8b, 0x15, 0xac, 0x1c, 0x00, 0x00
+.data1 	0x29, 0xf2, 0x4a, 0x89, 0x15, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x15, 0xa8, 0x1c, 0x00, 0x00, 0x01
+.data1 	0xf2, 0x89, 0xd0, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x56, 0x8b, 0x15, 0xac, 0x1c, 0x00, 0x00
+.data1 	0x2b, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x89, 0xd6
+.data1 	0xe8, 0x82, 0xfe, 0xff, 0xff, 0x8b, 0x15, 0xac
+.data1 	0x1c, 0x00, 0x00, 0x29, 0xf2, 0x89, 0x15, 0x84
+.data1 	0x2c, 0x00, 0x00, 0x8b, 0x15, 0xa8, 0x1c, 0x00
+.data1 	0x00, 0x01, 0xf2, 0x89, 0xd0, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x15, 0xa8, 0x1c, 0x00
+.data1 	0x00, 0x2b, 0x55, 0x08, 0x01, 0x15, 0xac, 0x1c
+.data1 	0x00, 0x00, 0x8b, 0x55, 0x08, 0x89, 0x15, 0xa8
+.data1 	0x1c, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0x2b, 0x55
+.data1 	0x08, 0x2b, 0x15, 0xac, 0x1c, 0x00, 0x00, 0xf7
+.data1 	0xda, 0x89, 0x15, 0x84, 0x2c, 0x00, 0x00, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x56, 0x57, 0xc7, 0x45, 0xf0, 0x00
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x45, 0xec, 0x00, 0x00
+.data1 	0x00, 0x00, 0x68, 0xb8, 0x06, 0x00, 0x00, 0xe8
+.data1 	0x6d, 0x0e, 0x00, 0x00, 0x59, 0x89, 0x45, 0xd8
+.data1 	0x85, 0xc0, 0x74, 0x1a, 0x83, 0x7d, 0xd8, 0x70
+.data1 	0x75, 0x0b, 0x8b, 0x15, 0x30, 0x34, 0x00, 0x00
+.data1 	0x89, 0x55, 0xec, 0xeb, 0xdd, 0xc7, 0x45, 0xf0
+.data1 	0x01, 0x00, 0x00, 0x00, 0xeb, 0xd4, 0x83, 0x7d
+.data1 	0xec, 0x00, 0x74, 0x1a, 0x6a, 0x00, 0xe8, 0x0d
+.data1 	0x8d, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x74, 0x0e
+.data1 	0xff, 0x75, 0xec, 0xe8, 0xd9, 0x32, 0x00, 0x00
+.data1 	0x59, 0xe8, 0x09, 0x34, 0x00, 0x00, 0x8b, 0x3d
+.data1 	0x80, 0x2c, 0x00, 0x00, 0x83, 0x3f, 0x00, 0x75
+.data1 	0x0b, 0x68, 0xac, 0x06, 0x00, 0x00, 0xe8, 0x7d
+.data1 	0xa7, 0xff, 0xff, 0x59, 0x6a, 0x01, 0x68, 0xa8
+.data1 	0x06, 0x00, 0x00, 0xe8, 0x60, 0x3d, 0x00, 0x00
+.data1 	0x59, 0x59, 0x89, 0x45, 0xe8, 0x85, 0xc0, 0x75
+.data1 	0x07, 0xc7, 0x45, 0xe8, 0x88, 0x2c, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xc7, 0x45
+.data1 	0xf8, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x35, 0xa8
+.data1 	0x1c, 0x00, 0x00, 0x8b, 0x15, 0xac, 0x1c, 0x00
+.data1 	0x00, 0x89, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x6a
+.data1 	0x01, 0x8d, 0x45, 0xf7, 0x50, 0x6a, 0x00, 0xe8
+.data1 	0xc4, 0x8c, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x3d
+.data1 	0x01, 0x00, 0x00, 0x00, 0x74, 0x0c, 0xc7, 0x45
+.data1 	0xdc, 0x01, 0x00, 0x00, 0x00, 0xe9, 0x79, 0x01
+.data1 	0x00, 0x00, 0x80, 0x7d, 0xf7, 0x00, 0x74, 0xd7
+.data1 	0x83, 0x7d, 0xf8, 0x00, 0x74, 0x33, 0xc7, 0x45
+.data1 	0xf8, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7d, 0xf7
+.data1 	0x0a, 0x74, 0xc4, 0x8b, 0x15, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0x84, 0x2c, 0x00, 0x00
+.data1 	0x78, 0x08, 0x8a, 0x4d, 0xf7, 0x88, 0x0e, 0x46
+.data1 	0xeb, 0xad, 0xe8, 0x26, 0xfe, 0xff, 0xff, 0x89
+.data1 	0xc6, 0x8a, 0x4d, 0xf7, 0x88, 0x0e, 0x46, 0xeb
+.data1 	0x9e, 0x83, 0x7d, 0xf0, 0x00, 0x74, 0x0b, 0x80
+.data1 	0x7d, 0xf7, 0x5c, 0x75, 0x05, 0xff, 0x45, 0xf8
+.data1 	0xeb, 0x8d, 0x80, 0x7d, 0xf7, 0x0a, 0x0f, 0x84
+.data1 	0x1f, 0x01, 0x00, 0x00, 0x83, 0x7d, 0xe0, 0x00
+.data1 	0x74, 0x1f, 0x8b, 0x55, 0xe8, 0x80, 0x3a, 0x20
+.data1 	0x75, 0x17, 0x0f, 0xbe, 0x45, 0xf7, 0x50, 0xff
+.data1 	0x75, 0xe8, 0xe8, 0x17, 0x02, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x0f, 0x85, 0x5e, 0xff, 0xff
+.data1 	0xff, 0xc7, 0x45, 0xe0, 0x00, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0xf8, 0x00, 0x0f, 0x84, 0x55, 0x00
+.data1 	0x00, 0x00, 0x80, 0x7d, 0xf7, 0x5c, 0x75, 0x4f
+.data1 	0x6a, 0x01, 0x8d, 0x45, 0xf7, 0x50, 0x6a, 0x00
+.data1 	0xe8, 0x0b, 0x8c, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x3d, 0x01, 0x00, 0x00, 0x00, 0x74, 0x0c, 0xc7
+.data1 	0x45, 0xdc, 0x01, 0x00, 0x00, 0x00, 0xe9, 0xc0
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x15, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0x84, 0x2c, 0x00, 0x00
+.data1 	0x78, 0x0b, 0x8a, 0x4d, 0xf7, 0x88, 0x0e, 0x46
+.data1 	0xe9, 0x0a, 0xff, 0xff, 0xff, 0xe8, 0x83, 0xfd
+.data1 	0xff, 0xff, 0x89, 0xc6, 0x8a, 0x4d, 0xf7, 0x88
+.data1 	0x0e, 0x46, 0xe9, 0xf8, 0xfe, 0xff, 0xff, 0x83
+.data1 	0x7f, 0x04, 0x00, 0x0f, 0x84, 0x5e, 0x00, 0x00
+.data1 	0x00, 0x0f, 0xbe, 0x45, 0xf7, 0x50, 0xff, 0x75
+.data1 	0xe8, 0xe8, 0x90, 0x01, 0x00, 0x00, 0x59, 0x59
+.data1 	0x85, 0xc0, 0x74, 0x4b, 0x83, 0x3d, 0x84, 0x2c
+.data1 	0x00, 0x00, 0x00, 0x75, 0x0c, 0xe8, 0x4b, 0xfd
+.data1 	0xff, 0xff, 0x89, 0xc6, 0xc6, 0x06, 0x00, 0xeb
+.data1 	0x03, 0xc6, 0x06, 0x00, 0x6a, 0x00, 0xff, 0x35
+.data1 	0xa8, 0x1c, 0x00, 0x00, 0xff, 0x37, 0xe8, 0x77
+.data1 	0x39, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x83, 0xc7
+.data1 	0x04, 0xc7, 0x45, 0xe0, 0x01, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x35, 0xa8, 0x1c, 0x00, 0x00, 0x8b, 0x15
+.data1 	0xac, 0x1c, 0x00, 0x00, 0x89, 0x15, 0x84, 0x2c
+.data1 	0x00, 0x00, 0xe9, 0x90, 0xfe, 0xff, 0xff, 0x8b
+.data1 	0x15, 0x84, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0x84, 0x2c, 0x00, 0x00, 0x78, 0x0b, 0x8a, 0x4d
+.data1 	0xf7, 0x88, 0x0e, 0x46, 0xe9, 0x76, 0xfe, 0xff
+.data1 	0xff, 0xe8, 0xef, 0xfc, 0xff, 0xff, 0x89, 0xc6
+.data1 	0x8a, 0x4d, 0xf7, 0x88, 0x0e, 0x46, 0xe9, 0x64
+.data1 	0xfe, 0xff, 0xff, 0x83, 0x3d, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x75, 0x0c, 0xe8, 0xd4, 0xfc, 0xff
+.data1 	0xff, 0x89, 0xc6, 0xc6, 0x06, 0x00, 0xeb, 0x03
+.data1 	0xc6, 0x06, 0x00, 0x6a, 0x00, 0xff, 0x35, 0xa8
+.data1 	0x1c, 0x00, 0x00, 0xff, 0x37, 0xe8, 0x00, 0x39
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x83, 0xc7, 0x04
+.data1 	0x83, 0x3f, 0x00, 0x74, 0x13, 0x6a, 0x00, 0x68
+.data1 	0x88, 0x2c, 0x00, 0x00, 0xff, 0x37, 0xe8, 0xe7
+.data1 	0x38, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xeb, 0xe5
+.data1 	0x8b, 0x45, 0xdc, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57, 0x8b
+.data1 	0x55, 0x0c, 0x8b, 0x52, 0x04, 0x89, 0xd7, 0x85
+.data1 	0xd2, 0x75, 0x45, 0xff, 0x05, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x6a, 0x00, 0xe8, 0xf0, 0x8a, 0x00, 0x00
+.data1 	0x59, 0x89, 0xc6, 0x56, 0xe8, 0xe7, 0x8a, 0x00
+.data1 	0x00, 0x59, 0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x75
+.data1 	0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a
+.data1 	0x85, 0xd2, 0x74, 0x05, 0xe8, 0xa6, 0xa4, 0xff
+.data1 	0xff, 0x56, 0x68, 0xd0, 0x06, 0x00, 0x00, 0xe8
+.data1 	0x52, 0x32, 0x00, 0x00, 0x59, 0x59, 0xeb, 0x3d
+.data1 	0x31, 0xf6, 0x0f, 0xbe, 0x07, 0x2d, 0x30, 0x00
+.data1 	0x00, 0x00, 0x89, 0x45, 0xf4, 0x3d, 0x08, 0x00
+.data1 	0x00, 0x00, 0x72, 0x12, 0x8b, 0x55, 0x0c, 0xff
+.data1 	0x72, 0x04, 0x68, 0xbc, 0x06, 0x00, 0x00, 0xe8
+.data1 	0xd4, 0xa4, 0xff, 0xff, 0x59, 0x59, 0x89, 0xf2
+.data1 	0xc1, 0xe2, 0x03, 0x8b, 0x75, 0xf4, 0x01, 0xd6
+.data1 	0x47, 0x80, 0x3f, 0x00, 0x75, 0xcc, 0x56, 0xe8
+.data1 	0x7c, 0x8a, 0x00, 0x00, 0x59, 0x31, 0xc0, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x0c, 0x8b, 0x7d, 0x08, 0xff
+.data1 	0x4d, 0x10, 0x83, 0x7d, 0x10, 0x00, 0x7e, 0x0f
+.data1 	0x8a, 0x07, 0x47, 0x88, 0x06, 0x46, 0x0f, 0xb6
+.data1 	0xd0, 0x84, 0xd2, 0x75, 0xea, 0xeb, 0x03, 0xc6
+.data1 	0x06, 0x00, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x56, 0x8b, 0x75, 0x08, 0x0f, 0xbe, 0x06
+.data1 	0x0f, 0xbe, 0x5d, 0x0c, 0x39, 0xd8, 0x74, 0x0b
+.data1 	0x8a, 0x06, 0x46, 0x84, 0xc0, 0x75, 0xee, 0x31
+.data1 	0xc0, 0xeb, 0x02, 0x89, 0xf0, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x0c
+.data1 	0x8b, 0x75, 0x08, 0xff, 0x4d, 0x10, 0x78, 0x08
+.data1 	0x8a, 0x06, 0x46, 0x88, 0x07, 0x47, 0xeb, 0xf3
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x08, 0x8b, 0x7d, 0x0c, 0x80
+.data1 	0x3e, 0x00, 0x74, 0x10, 0x0f, 0xbe, 0x06, 0x46
+.data1 	0x0f, 0xbe, 0x1f, 0x47, 0x39, 0xd8, 0x74, 0xef
+.data1 	0x31, 0xc0, 0xeb, 0x05, 0xb8, 0x01, 0x00, 0x00
+.data1 	0x00, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x1f, 0x00, 0x00, 0x00
+.data1 	0x59, 0x85, 0xc0, 0x75, 0x0f, 0xff, 0x75, 0x08
+.data1 	0x68, 0xd8, 0x06, 0x00, 0x00, 0xe8, 0xee, 0xa3
+.data1 	0xff, 0xff, 0x59, 0x59, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xd0, 0x72, 0x00, 0x00, 0x59, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0x8b, 0x75, 0x08, 0x0f, 0xbe
+.data1 	0x06, 0x2d, 0x30, 0x00, 0x00, 0x00, 0x3d, 0x09
+.data1 	0x00, 0x00, 0x00, 0x76, 0x04, 0x31, 0xc0, 0xeb
+.data1 	0x0b, 0x46, 0x80, 0x3e, 0x00, 0x75, 0xe7, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0x7d, 0x08, 0x00, 0x75
+.data1 	0x04, 0x31, 0xc0, 0xeb, 0x49, 0xc7, 0x05, 0x34
+.data1 	0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x05, 0x38, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0xff, 0x75, 0x08, 0xe8, 0x2f, 0x00, 0x00
+.data1 	0x00, 0x59, 0x8b, 0x15, 0x38, 0x34, 0x00, 0x00
+.data1 	0x03, 0x15, 0x34, 0x34, 0x00, 0x00, 0x52, 0xe8
+.data1 	0xe4, 0xf7, 0xff, 0xff, 0x59, 0xa3, 0x3c, 0x34
+.data1 	0x00, 0x00, 0x03, 0x05, 0x34, 0x34, 0x00, 0x00
+.data1 	0xa3, 0x40, 0x34, 0x00, 0x00, 0xff, 0x75, 0x08
+.data1 	0xe8, 0x88, 0x01, 0x00, 0x00, 0x59, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x75, 0x08, 0x85
+.data1 	0xf6, 0x0f, 0x84, 0x49, 0x01, 0x00, 0x00, 0x8b
+.data1 	0x16, 0x0f, 0xbf, 0x04, 0x55, 0x04, 0x1d, 0x00
+.data1 	0x00, 0x01, 0x05, 0x34, 0x34, 0x00, 0x00, 0xe9
+.data1 	0x28, 0x01, 0x00, 0x00, 0xff, 0x76, 0x08, 0xe8
+.data1 	0xd4, 0xff, 0xff, 0xff, 0x59, 0xff, 0x76, 0x04
+.data1 	0xe8, 0xcb, 0xff, 0xff, 0xff, 0x59, 0xe9, 0x1d
+.data1 	0x01, 0x00, 0x00, 0xff, 0x76, 0x0c, 0xe8, 0xbd
+.data1 	0xff, 0xff, 0xff, 0x59, 0xff, 0x76, 0x08, 0xe8
+.data1 	0xb4, 0xff, 0xff, 0xff, 0x59, 0xe9, 0x06, 0x01
+.data1 	0x00, 0x00, 0xff, 0x76, 0x08, 0xe8, 0x01, 0x01
+.data1 	0x00, 0x00, 0x59, 0xe9, 0xf8, 0x00, 0x00, 0x00
+.data1 	0xff, 0x76, 0x08, 0xe8, 0x98, 0xff, 0xff, 0xff
+.data1 	0x59, 0xff, 0x76, 0x04, 0xe8, 0x8f, 0xff, 0xff
+.data1 	0xff, 0x59, 0xe9, 0xe1, 0x00, 0x00, 0x00, 0xff
+.data1 	0x76, 0x0c, 0xe8, 0x81, 0xff, 0xff, 0xff, 0x59
+.data1 	0xff, 0x76, 0x08, 0xe8, 0x78, 0xff, 0xff, 0xff
+.data1 	0x59, 0xff, 0x76, 0x04, 0xe8, 0x6f, 0xff, 0xff
+.data1 	0xff, 0x59, 0xe9, 0xc1, 0x00, 0x00, 0x00, 0xff
+.data1 	0x76, 0x0c, 0xe8, 0xb9, 0x89, 0x00, 0x00, 0x59
+.data1 	0x40, 0x01, 0x05, 0x38, 0x34, 0x00, 0x00, 0xff
+.data1 	0x76, 0x08, 0xe8, 0x51, 0xff, 0xff, 0xff, 0x59
+.data1 	0xff, 0x76, 0x04, 0xe8, 0x48, 0xff, 0xff, 0xff
+.data1 	0x59, 0xe9, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x76
+.data1 	0x08, 0xe8, 0x3a, 0xff, 0xff, 0xff, 0x59, 0xff
+.data1 	0x76, 0x04, 0xe8, 0x31, 0xff, 0xff, 0xff, 0x59
+.data1 	0xe9, 0x83, 0x00, 0x00, 0x00, 0xff, 0x76, 0x0c
+.data1 	0xe8, 0x23, 0xff, 0xff, 0xff, 0x59, 0xff, 0x76
+.data1 	0x08, 0xe8, 0x1a, 0xff, 0xff, 0xff, 0x59, 0xff
+.data1 	0x76, 0x04, 0xe8, 0x11, 0xff, 0xff, 0xff, 0x59
+.data1 	0xe9, 0x63, 0x00, 0x00, 0x00, 0xff, 0x76, 0x0c
+.data1 	0xe8, 0x5e, 0x00, 0x00, 0x00, 0x59, 0xff, 0x76
+.data1 	0x08, 0xe8, 0x52, 0x89, 0x00, 0x00, 0x59, 0x40
+.data1 	0x01, 0x05, 0x38, 0x34, 0x00, 0x00, 0xff, 0x76
+.data1 	0x04, 0xe8, 0xea, 0xfe, 0xff, 0xff, 0x59, 0xeb
+.data1 	0x3f, 0xff, 0x76, 0x0c, 0xe8, 0xdf, 0xfe, 0xff
+.data1 	0xff, 0x59, 0xff, 0x76, 0x04, 0xe8, 0xd6, 0xfe
+.data1 	0xff, 0xff, 0x59, 0xeb, 0x2b, 0xff, 0x76, 0x04
+.data1 	0xe8, 0xcb, 0xfe, 0xff, 0xff, 0x59, 0xeb, 0x20
+.data1 	0xff, 0x76, 0x0c, 0xe8, 0xc0, 0xfe, 0xff, 0xff
+.data1 	0x59, 0xff, 0x76, 0x04, 0xe8, 0xb7, 0xfe, 0xff
+.data1 	0xff, 0x59, 0xeb, 0x0c, 0xbb, 0xe8, 0x06, 0x00
+.data1 	0x00, 0x8b, 0x06, 0xe9, 0x48, 0x95, 0x00, 0x00
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b
+.data1 	0x75, 0x08, 0x85, 0xf6, 0x74, 0x1c, 0xa1, 0x34
+.data1 	0x34, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00
+.data1 	0xa3, 0x34, 0x34, 0x00, 0x00, 0xff, 0x76, 0x04
+.data1 	0xe8, 0x83, 0xfe, 0xff, 0xff, 0x59, 0x8b, 0x36
+.data1 	0xeb, 0xe0, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0x57, 0x8b, 0x7d, 0x08, 0x85, 0xff, 0x75
+.data1 	0x07, 0x31, 0xc0, 0xe9, 0xc1, 0x01, 0x00, 0x00
+.data1 	0x8b, 0x35, 0x3c, 0x34, 0x00, 0x00, 0x8b, 0x17
+.data1 	0x0f, 0xbf, 0x04, 0x55, 0x04, 0x1d, 0x00, 0x00
+.data1 	0x03, 0x05, 0x3c, 0x34, 0x00, 0x00, 0xa3, 0x3c
+.data1 	0x34, 0x00, 0x00, 0xe9, 0x8f, 0x01, 0x00, 0x00
+.data1 	0xff, 0x77, 0x08, 0xe8, 0xc5, 0xff, 0xff, 0xff
+.data1 	0x59, 0x89, 0x46, 0x08, 0xff, 0x77, 0x04, 0xe8
+.data1 	0xb9, 0xff, 0xff, 0xff, 0x59, 0x89, 0x46, 0x04
+.data1 	0xe9, 0x7e, 0x01, 0x00, 0x00, 0xff, 0x77, 0x0c
+.data1 	0xe8, 0xa8, 0xff, 0xff, 0xff, 0x59, 0x89, 0x46
+.data1 	0x0c, 0xff, 0x77, 0x08, 0xe8, 0x9c, 0xff, 0xff
+.data1 	0xff, 0x59, 0x89, 0x46, 0x08, 0x8b, 0x57, 0x04
+.data1 	0x89, 0x56, 0x04, 0xe9, 0x5b, 0x01, 0x00, 0x00
+.data1 	0xff, 0x77, 0x08, 0xe8, 0x5d, 0x01, 0x00, 0x00
+.data1 	0x59, 0x89, 0x46, 0x08, 0x8b, 0x57, 0x04, 0x89
+.data1 	0x56, 0x04, 0xe9, 0x44, 0x01, 0x00, 0x00, 0xff
+.data1 	0x77, 0x08, 0xe8, 0x6e, 0xff, 0xff, 0xff, 0x59
+.data1 	0x89, 0x46, 0x08, 0xff, 0x77, 0x04, 0xe8, 0x62
+.data1 	0xff, 0xff, 0xff, 0x59, 0x89, 0x46, 0x04, 0xe9
+.data1 	0x27, 0x01, 0x00, 0x00, 0xff, 0x77, 0x0c, 0xe8
+.data1 	0x51, 0xff, 0xff, 0xff, 0x59, 0x89, 0x46, 0x0c
+.data1 	0xff, 0x77, 0x08, 0xe8, 0x45, 0xff, 0xff, 0xff
+.data1 	0x59, 0x89, 0x46, 0x08, 0xff, 0x77, 0x04, 0xe8
+.data1 	0x39, 0xff, 0xff, 0xff, 0x59, 0x89, 0x46, 0x04
+.data1 	0xe9, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x77, 0x0c
+.data1 	0xe8, 0x42, 0x01, 0x00, 0x00, 0x59, 0x89, 0x46
+.data1 	0x0c, 0xff, 0x77, 0x08, 0xe8, 0x1c, 0xff, 0xff
+.data1 	0xff, 0x59, 0x89, 0x46, 0x08, 0xff, 0x77, 0x04
+.data1 	0xe8, 0x10, 0xff, 0xff, 0xff, 0x59, 0x89, 0x46
+.data1 	0x04, 0xe9, 0xd5, 0x00, 0x00, 0x00, 0xff, 0x77
+.data1 	0x08, 0xe8, 0xff, 0xfe, 0xff, 0xff, 0x59, 0x89
+.data1 	0x46, 0x08, 0xff, 0x77, 0x04, 0xe8, 0xf3, 0xfe
+.data1 	0xff, 0xff, 0x59, 0x89, 0x46, 0x04, 0xe9, 0xb8
+.data1 	0x00, 0x00, 0x00, 0xff, 0x77, 0x0c, 0xe8, 0xe2
+.data1 	0xfe, 0xff, 0xff, 0x59, 0x89, 0x46, 0x0c, 0xff
+.data1 	0x77, 0x08, 0xe8, 0xd6, 0xfe, 0xff, 0xff, 0x59
+.data1 	0x89, 0x46, 0x08, 0xff, 0x77, 0x04, 0xe8, 0xca
+.data1 	0xfe, 0xff, 0xff, 0x59, 0x89, 0x46, 0x04, 0xe9
+.data1 	0x8f, 0x00, 0x00, 0x00, 0xff, 0x77, 0x0c, 0xe8
+.data1 	0x91, 0x00, 0x00, 0x00, 0x59, 0x89, 0x46, 0x0c
+.data1 	0xff, 0x77, 0x08, 0xe8, 0xc7, 0x00, 0x00, 0x00
+.data1 	0x59, 0x89, 0x46, 0x08, 0xff, 0x77, 0x04, 0xe8
+.data1 	0xa1, 0xfe, 0xff, 0xff, 0x59, 0x89, 0x46, 0x04
+.data1 	0xe9, 0x66, 0x00, 0x00, 0x00, 0xff, 0x77, 0x0c
+.data1 	0xe8, 0x90, 0xfe, 0xff, 0xff, 0x59, 0x89, 0x46
+.data1 	0x0c, 0x8b, 0x57, 0x08, 0x89, 0x56, 0x08, 0xff
+.data1 	0x77, 0x04, 0xe8, 0x7e, 0xfe, 0xff, 0xff, 0x59
+.data1 	0x89, 0x46, 0x04, 0xeb, 0x46, 0x8b, 0x57, 0x0c
+.data1 	0x89, 0x56, 0x0c, 0x8b, 0x57, 0x08, 0x89, 0x56
+.data1 	0x08, 0xff, 0x77, 0x04, 0xe8, 0x64, 0xfe, 0xff
+.data1 	0xff, 0x59, 0x89, 0x46, 0x04, 0xeb, 0x2c, 0xff
+.data1 	0x77, 0x0c, 0xe8, 0x56, 0xfe, 0xff, 0xff, 0x59
+.data1 	0x89, 0x46, 0x0c, 0x8b, 0x57, 0x08, 0x89, 0x56
+.data1 	0x08, 0xff, 0x77, 0x04, 0xe8, 0x44, 0xfe, 0xff
+.data1 	0xff, 0x59, 0x89, 0x46, 0x04, 0xeb, 0x0c, 0xbb
+.data1 	0x50, 0x07, 0x00, 0x00, 0x8b, 0x07, 0xe9, 0x4d
+.data1 	0x93, 0x00, 0x00, 0x8b, 0x17, 0x89, 0x16, 0x89
+.data1 	0xf0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x04, 0x56, 0x57, 0x8b, 0x7d, 0x08
+.data1 	0x8d, 0x75, 0xfc, 0x85, 0xff, 0x74, 0x23, 0x8b
+.data1 	0x15, 0x3c, 0x34, 0x00, 0x00, 0x89, 0x16, 0x83
+.data1 	0x05, 0x3c, 0x34, 0x00, 0x00, 0x08, 0xff, 0x77
+.data1 	0x04, 0xe8, 0xff, 0xfd, 0xff, 0xff, 0x59, 0x8b
+.data1 	0x16, 0x89, 0x42, 0x04, 0x8b, 0x3f, 0x8b, 0x36
+.data1 	0xeb, 0xd9, 0xc7, 0x06, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x45, 0xfc, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57, 0x8b
+.data1 	0x7d, 0x08, 0x8b, 0x35, 0x40, 0x34, 0x00, 0x00
+.data1 	0x8b, 0x15, 0x40, 0x34, 0x00, 0x00, 0x89, 0x55
+.data1 	0xf4, 0x8a, 0x07, 0x47, 0x88, 0x06, 0x46, 0x0f
+.data1 	0xb6, 0xd0, 0x84, 0xd2, 0x75, 0xf3, 0x89, 0x35
+.data1 	0x40, 0x34, 0x00, 0x00, 0x8b, 0x45, 0xf4, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0x7d
+.data1 	0x08, 0x00, 0x74, 0x09, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x1a, 0x72, 0x00, 0x00, 0x59, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x15, 0x80, 0x2c, 0x00, 0x00, 0x83, 0x7d, 0x08
+.data1 	0x00, 0x7e, 0x07, 0x83, 0x05, 0x80, 0x2c, 0x00
+.data1 	0x00, 0x04, 0xbe, 0x74, 0x2c, 0x00, 0x00, 0x81
+.data1 	0xfe, 0x7e, 0x2c, 0x00, 0x00, 0x73, 0x06, 0xc6
+.data1 	0x06, 0x02, 0x46, 0xeb, 0xf2, 0x6a, 0x01, 0xe8
+.data1 	0x0e, 0x01, 0x00, 0x00, 0x59, 0x8b, 0x15, 0x80
+.data1 	0x2c, 0x00, 0x00, 0x83, 0x3a, 0x00, 0x75, 0x10
+.data1 	0x83, 0x3d, 0x30, 0x32, 0x00, 0x00, 0x00, 0x75
+.data1 	0x07, 0xc6, 0x05, 0x7a, 0x2c, 0x00, 0x00, 0x01
+.data1 	0x6a, 0x00, 0xe8, 0xa1, 0x84, 0x00, 0x00, 0x59
+.data1 	0x85, 0xc0, 0x74, 0x13, 0x6a, 0x01, 0xe8, 0x95
+.data1 	0x84, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x74, 0x07
+.data1 	0xb8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x02, 0x31
+.data1 	0xc0, 0xa3, 0x44, 0x34, 0x00, 0x00, 0x80, 0x3d
+.data1 	0x77, 0x2c, 0x00, 0x00, 0x02, 0x75, 0x19, 0x80
+.data1 	0x3d, 0x7a, 0x2c, 0x00, 0x00, 0x01, 0x75, 0x10
+.data1 	0x83, 0x3d, 0x44, 0x34, 0x00, 0x00, 0x00, 0x74
+.data1 	0x07, 0xc6, 0x05, 0x77, 0x2c, 0x00, 0x00, 0x01
+.data1 	0x80, 0x3d, 0x78, 0x2c, 0x00, 0x00, 0x02, 0x75
+.data1 	0x0c, 0x8a, 0x0d, 0x77, 0x2c, 0x00, 0x00, 0x88
+.data1 	0x0d, 0x78, 0x2c, 0x00, 0x00, 0xbe, 0x74, 0x2c
+.data1 	0x00, 0x00, 0x81, 0xfe, 0x7e, 0x2c, 0x00, 0x00
+.data1 	0x73, 0x0b, 0x80, 0x3e, 0x02, 0x75, 0x03, 0xc6
+.data1 	0x06, 0x00, 0x46, 0xeb, 0xed, 0x8b, 0x45, 0x0c
+.data1 	0x8b, 0x10, 0x89, 0x15, 0x98, 0x2d, 0x00, 0x00
+.data1 	0x80, 0x3d, 0x7a, 0x2c, 0x00, 0x00, 0x00, 0x75
+.data1 	0x32, 0xa1, 0x80, 0x2c, 0x00, 0x00, 0x83, 0x05
+.data1 	0x80, 0x2c, 0x00, 0x00, 0x04, 0x8b, 0x10, 0x89
+.data1 	0x15, 0x98, 0x2d, 0x00, 0x00, 0x83, 0x3d, 0x30
+.data1 	0x32, 0x00, 0x00, 0x00, 0x75, 0x15, 0x89, 0x15
+.data1 	0x9c, 0x2c, 0x00, 0x00, 0x6a, 0x00, 0xff, 0x35
+.data1 	0x9c, 0x2c, 0x00, 0x00, 0xe8, 0xe0, 0xd8, 0xff
+.data1 	0xff, 0x59, 0x59, 0x8b, 0x15, 0x80, 0x2c, 0x00
+.data1 	0x00, 0x89, 0x15, 0xd4, 0x2c, 0x00, 0x00, 0x8b
+.data1 	0x15, 0x80, 0x2c, 0x00, 0x00, 0x83, 0x3a, 0x00
+.data1 	0x74, 0x0f, 0xff, 0x05, 0xcc, 0x2c, 0x00, 0x00
+.data1 	0x83, 0x05, 0x80, 0x2c, 0x00, 0x00, 0x04, 0xeb
+.data1 	0xe6, 0x0f, 0xbe, 0x05, 0x77, 0x2c, 0x00, 0x00
+.data1 	0x50, 0xe8, 0xca, 0x28, 0x00, 0x00, 0x59, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x10
+.data1 	0x56, 0x57, 0x83, 0x7d, 0x08, 0x00, 0x74, 0x0a
+.data1 	0xc7, 0x05, 0x30, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x15, 0x80, 0x2c, 0x00, 0x00
+.data1 	0x8b, 0x12, 0x89, 0xd6, 0x85, 0xd2, 0x0f, 0x84
+.data1 	0xf3, 0x00, 0x00, 0x00, 0x83, 0x05, 0x80, 0x2c
+.data1 	0x00, 0x00, 0x04, 0x0f, 0xbe, 0x06, 0x46, 0x89
+.data1 	0xc7, 0x3d, 0x2d, 0x00, 0x00, 0x00, 0x0f, 0x85
+.data1 	0x61, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xf8, 0x01
+.data1 	0x00, 0x00, 0x00, 0x80, 0x3e, 0x00, 0x74, 0x13
+.data1 	0x80, 0x3e, 0x2d, 0x0f, 0x85, 0x66, 0x00, 0x00
+.data1 	0x00, 0x80, 0x7e, 0x01, 0x00, 0x0f, 0x85, 0x5c
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0x08, 0x00, 0x0f
+.data1 	0x85, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x3e, 0x00
+.data1 	0x75, 0x13, 0x31, 0xd2, 0x88, 0x15, 0x7d, 0x2c
+.data1 	0x00, 0x00, 0x88, 0x15, 0x7b, 0x2c, 0x00, 0x00
+.data1 	0xe9, 0x9a, 0x00, 0x00, 0x00, 0x8b, 0x15, 0x80
+.data1 	0x2c, 0x00, 0x00, 0x83, 0x3a, 0x00, 0x0f, 0x85
+.data1 	0x8b, 0x00, 0x00, 0x00, 0xff, 0x35, 0x80, 0x2c
+.data1 	0x00, 0x00, 0xe8, 0xc8, 0x00, 0x00, 0x00, 0x59
+.data1 	0xe9, 0x7a, 0x00, 0x00, 0x00, 0x83, 0xff, 0x2b
+.data1 	0x75, 0x09, 0xc7, 0x45, 0xf8, 0x00, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x0c, 0x83, 0x05, 0x80, 0x2c, 0x00
+.data1 	0x00, 0xfc, 0xe9, 0x60, 0x00, 0x00, 0x00, 0x0f
+.data1 	0xbe, 0x06, 0x46, 0x89, 0xc7, 0x85, 0xc0, 0x74
+.data1 	0x4c, 0x83, 0xff, 0x63, 0x75, 0x3a, 0x83, 0x7d
+.data1 	0x08, 0x00, 0x74, 0x34, 0xa1, 0x80, 0x2c, 0x00
+.data1 	0x00, 0x83, 0x05, 0x80, 0x2c, 0x00, 0x00, 0x04
+.data1 	0x8b, 0x10, 0x89, 0x55, 0xf0, 0x85, 0xd2, 0x74
+.data1 	0x09, 0x83, 0x3d, 0x30, 0x32, 0x00, 0x00, 0x00
+.data1 	0x74, 0x0b, 0x68, 0xb8, 0x07, 0x00, 0x00, 0xe8
+.data1 	0x54, 0x9d, 0xff, 0xff, 0x59, 0x8b, 0x55, 0xf0
+.data1 	0x89, 0x15, 0x30, 0x32, 0x00, 0x00, 0xeb, 0xb7
+.data1 	0xff, 0x75, 0xf8, 0x57, 0xe8, 0x12, 0x00, 0x00
+.data1 	0x00, 0x59, 0x59, 0xeb, 0xaa, 0x83, 0x7d, 0x08
+.data1 	0x00, 0x0f, 0x85, 0xfb, 0xfe, 0xff, 0xff, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x0f
+.data1 	0xbe, 0x45, 0x08, 0x50, 0x68, 0x5c, 0x1d, 0x00
+.data1 	0x00, 0xe8, 0x90, 0xf8, 0xff, 0xff, 0x59, 0x59
+.data1 	0x89, 0xc6, 0x85, 0xc0, 0x75, 0x11, 0x0f, 0xbe
+.data1 	0x45, 0x08, 0x50, 0x68, 0xc8, 0x07, 0x00, 0x00
+.data1 	0xe8, 0x03, 0x9d, 0xff, 0xff, 0x59, 0x59, 0x8b
+.data1 	0x45, 0x0c, 0x0f, 0xbe, 0xc0, 0x50, 0x89, 0xf0
+.data1 	0x2d, 0x5c, 0x1d, 0x00, 0x00, 0x5a, 0x88, 0x90
+.data1 	0x74, 0x2c, 0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x04, 0x56, 0x57, 0x31
+.data1 	0xf6, 0x8b, 0x55, 0x08, 0x83, 0x3c, 0xb2, 0x00
+.data1 	0x74, 0x03, 0x46, 0xeb, 0xf4, 0x89, 0xf2, 0x42
+.data1 	0xc1, 0xe2, 0x02, 0x52, 0xe8, 0x17, 0xf1, 0xff
+.data1 	0xff, 0x59, 0x89, 0x45, 0xfc, 0x89, 0xc7, 0x8b
+.data1 	0x45, 0x08, 0x83, 0x38, 0x00, 0x74, 0x16, 0x8b
+.data1 	0x5d, 0x08, 0x83, 0x45, 0x08, 0x04, 0xff, 0x33
+.data1 	0xe8, 0x46, 0xf1, 0xff, 0xff, 0x59, 0x89, 0x07
+.data1 	0x83, 0xc7, 0x04, 0xeb, 0xe2, 0xc7, 0x07, 0x00
+.data1 	0x00, 0x00, 0x00, 0x68, 0xcc, 0x2c, 0x00, 0x00
+.data1 	0xe8, 0x25, 0x00, 0x00, 0x00, 0x59, 0xc6, 0x05
+.data1 	0xd0, 0x2c, 0x00, 0x00, 0x01, 0x89, 0x35, 0xcc
+.data1 	0x2c, 0x00, 0x00, 0x8b, 0x55, 0xfc, 0x89, 0x15
+.data1 	0xd4, 0x2c, 0x00, 0x00, 0xc7, 0x05, 0xd8, 0x2c
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b, 0x55
+.data1 	0x08, 0x80, 0x7a, 0x04, 0x00, 0x74, 0x24, 0x8b
+.data1 	0x55, 0x08, 0x8b, 0x72, 0x08, 0x83, 0x3e, 0x00
+.data1 	0x74, 0x0d, 0xff, 0x36, 0xe8, 0xd5, 0x6e, 0x00
+.data1 	0x00, 0x59, 0x83, 0xc6, 0x04, 0xeb, 0xee, 0x8b
+.data1 	0x55, 0x08, 0xff, 0x72, 0x08, 0xe8, 0xc4, 0x6e
+.data1 	0x00, 0x00, 0x59, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57, 0xbe, 0x01
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0x08, 0x01, 0x7e
+.data1 	0x0e, 0x8b, 0x55, 0x0c, 0xff, 0x72, 0x04, 0xe8
+.data1 	0xf9, 0xf7, 0xff, 0xff, 0x59, 0x89, 0xc6, 0x39
+.data1 	0x35, 0xcc, 0x2c, 0x00, 0x00, 0x7d, 0x06, 0x8b
+.data1 	0x35, 0xcc, 0x2c, 0x00, 0x00, 0xff, 0x05, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x8b, 0x15, 0xcc, 0x2c, 0x00
+.data1 	0x00, 0x29, 0xf2, 0x89, 0x15, 0xcc, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x3d, 0xd4, 0x2c, 0x00, 0x00, 0x4e
+.data1 	0x78, 0x16, 0x80, 0x3d, 0xd0, 0x2c, 0x00, 0x00
+.data1 	0x00, 0x74, 0x08, 0xff, 0x37, 0xe8, 0x64, 0x6e
+.data1 	0x00, 0x00, 0x59, 0x83, 0xc7, 0x04, 0xeb, 0xe7
+.data1 	0x8b, 0x15, 0xd4, 0x2c, 0x00, 0x00, 0x89, 0x55
+.data1 	0xf4, 0x8b, 0x07, 0x83, 0xc7, 0x04, 0x8b, 0x5d
+.data1 	0xf4, 0x89, 0x03, 0x83, 0x45, 0xf4, 0x04, 0x85
+.data1 	0xc0, 0x75, 0xee, 0xc7, 0x05, 0xd8, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c
+.data1 	0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8
+.data1 	0x33, 0x9b, 0xff, 0xff, 0x31, 0xc0, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0x7d, 0x08
+.data1 	0x01, 0x75, 0x0f, 0xff, 0x75, 0x0c, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x07, 0x33, 0x00, 0x00, 0x59, 0x59
+.data1 	0xeb, 0x54, 0xff, 0x05, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x6a, 0x00, 0xe8, 0x1b, 0xfd, 0xff, 0xff, 0x59
+.data1 	0x0f, 0xbe, 0x05, 0x77, 0x2c, 0x00, 0x00, 0x50
+.data1 	0xe8, 0xd3, 0x25, 0x00, 0x00, 0x59, 0x8b, 0x15
+.data1 	0x80, 0x2c, 0x00, 0x00, 0x83, 0x3a, 0x00, 0x74
+.data1 	0x0c, 0xff, 0x35, 0x80, 0x2c, 0x00, 0x00, 0xe8
+.data1 	0x5b, 0xfe, 0xff, 0xff, 0x59, 0x8b, 0x15, 0x90
+.data1 	0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c
+.data1 	0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8
+.data1 	0xc3, 0x9a, 0xff, 0xff, 0x31, 0xc0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x14, 0x56, 0x57
+.data1 	0x83, 0x7d, 0x08, 0x03, 0x74, 0x0b, 0x68, 0x2c
+.data1 	0x08, 0x00, 0x00, 0xe8, 0x08, 0x9b, 0xff, 0xff
+.data1 	0x59, 0x83, 0x3d, 0xd8, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x75, 0x16, 0x8b, 0x15, 0xd4, 0x2c, 0x00, 0x00
+.data1 	0x89, 0x15, 0xd8, 0x2c, 0x00, 0x00, 0xc7, 0x05
+.data1 	0xdc, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x35, 0xdc, 0x2c, 0x00, 0x00, 0x85, 0xf6
+.data1 	0x74, 0x09, 0x80, 0x3e, 0x00, 0x0f, 0x85, 0x7b
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x15, 0xd8, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x32, 0x85, 0xf6, 0x74, 0x0b, 0x80
+.data1 	0x3e, 0x2d, 0x75, 0x06, 0x46, 0x80, 0x3e, 0x00
+.data1 	0x75, 0x52, 0x8b, 0x15, 0xd8, 0x2c, 0x00, 0x00
+.data1 	0x2b, 0x15, 0xd4, 0x2c, 0x00, 0x00, 0xb9, 0x04
+.data1 	0x00, 0x00, 0x00, 0x89, 0xd0, 0x99, 0xf7, 0xf9
+.data1 	0x40, 0x50, 0x68, 0x28, 0x08, 0x00, 0x00, 0x6a
+.data1 	0x0a, 0x8d, 0x45, 0xed, 0x50, 0xe8, 0x0c, 0x28
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x10, 0x6a, 0x00, 0x8d
+.data1 	0x45, 0xed, 0x50, 0x68, 0x20, 0x08, 0x00, 0x00
+.data1 	0xe8, 0x0d, 0x2e, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xc7, 0x05, 0xd8, 0x2c, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xe9
+.data1 	0x01, 0x01, 0x00, 0x00, 0x83, 0x05, 0xd8, 0x2c
+.data1 	0x00, 0x00, 0x04, 0x80, 0x3e, 0x2d, 0x75, 0x06
+.data1 	0x80, 0x7e, 0x01, 0x00, 0x74, 0x9c, 0x8a, 0x06
+.data1 	0x46, 0x88, 0x45, 0xf7, 0x8b, 0x55, 0x0c, 0x8b
+.data1 	0x7a, 0x04, 0x0f, 0xbe, 0x07, 0x0f, 0xbe, 0x5d
+.data1 	0xf7, 0x39, 0xd8, 0x74, 0x28, 0x80, 0x3f, 0x00
+.data1 	0x75, 0x1a, 0x0f, 0xbe, 0x45, 0xf7, 0x50, 0x68
+.data1 	0x0c, 0x08, 0x00, 0x00, 0xe8, 0x85, 0x27, 0x00
+.data1 	0x00, 0x59, 0x59, 0xc6, 0x45, 0xf7, 0x3f, 0xe9
+.data1 	0x55, 0x00, 0x00, 0x00, 0x47, 0x80, 0x3f, 0x3a
+.data1 	0x75, 0xd0, 0x47, 0xeb, 0xcd, 0x47, 0x80, 0x3f
+.data1 	0x3a, 0x75, 0x46, 0x80, 0x3e, 0x00, 0x75, 0x2c
+.data1 	0x8b, 0x15, 0xd8, 0x2c, 0x00, 0x00, 0x8b, 0x12
+.data1 	0x89, 0xd6, 0x85, 0xd2, 0x75, 0x17, 0x0f, 0xbe
+.data1 	0x45, 0xf7, 0x50, 0x68, 0xf4, 0x07, 0x00, 0x00
+.data1 	0xe8, 0x49, 0x27, 0x00, 0x00, 0x59, 0x59, 0xc6
+.data1 	0x45, 0xf7, 0x3f, 0xeb, 0x1c, 0x83, 0x05, 0xd8
+.data1 	0x2c, 0x00, 0x00, 0x04, 0x6a, 0x00, 0x56, 0x68
+.data1 	0xec, 0x07, 0x00, 0x00, 0xe8, 0x61, 0x2d, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xbe, 0xe8, 0x07, 0x00
+.data1 	0x00, 0x89, 0x35, 0xdc, 0x2c, 0x00, 0x00, 0x8a
+.data1 	0x4d, 0xf7, 0x88, 0x4d, 0xed, 0xc6, 0x45, 0xee
+.data1 	0x00, 0x8b, 0x55, 0x0c, 0x6a, 0x00, 0x8d, 0x45
+.data1 	0xed, 0x50, 0xff, 0x72, 0x08, 0xe8, 0x38, 0x2d
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x8b, 0x15, 0xd8
+.data1 	0x2c, 0x00, 0x00, 0x2b, 0x15, 0xd4, 0x2c, 0x00
+.data1 	0x00, 0xb9, 0x04, 0x00, 0x00, 0x00, 0x89, 0xd0
+.data1 	0x99, 0xf7, 0xf9, 0x40, 0x50, 0x68, 0xe4, 0x07
+.data1 	0x00, 0x00, 0x6a, 0x0a, 0x8d, 0x45, 0xed, 0x50
+.data1 	0xe8, 0xf9, 0x26, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x6a, 0x00, 0x8d, 0x45, 0xed, 0x50, 0x68, 0xdc
+.data1 	0x07, 0x00, 0x00, 0xe8, 0xfa, 0x2c, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x31, 0xc0, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c, 0x56
+.data1 	0x57, 0x8b, 0x35, 0xc8, 0x2c, 0x00, 0x00, 0x85
+.data1 	0xf6, 0x74, 0x05, 0x80, 0x3e, 0x00, 0x75, 0x37
+.data1 	0x8b, 0x15, 0x80, 0x2c, 0x00, 0x00, 0x8b, 0x32
+.data1 	0x85, 0xf6, 0x74, 0x0b, 0x80, 0x3e, 0x2d, 0x75
+.data1 	0x06, 0x46, 0x80, 0x3e, 0x00, 0x75, 0x07, 0x31
+.data1 	0xc0, 0xe9, 0x8e, 0x00, 0x00, 0x00, 0x83, 0x05
+.data1 	0x80, 0x2c, 0x00, 0x00, 0x04, 0x80, 0x3e, 0x2d
+.data1 	0x75, 0x0d, 0x80, 0x7e, 0x01, 0x00, 0x75, 0x07
+.data1 	0x31, 0xc0, 0xe9, 0x75, 0x00, 0x00, 0x00, 0x8a
+.data1 	0x06, 0x46, 0x88, 0x45, 0xf7, 0x8b, 0x7d, 0x08
+.data1 	0x0f, 0xbe, 0x07, 0x0f, 0xbe, 0x5d, 0xf7, 0x39
+.data1 	0xd8, 0x74, 0x1f, 0x80, 0x3f, 0x00, 0x75, 0x11
+.data1 	0x0f, 0xbe, 0x45, 0xf7, 0x50, 0x68, 0x64, 0x08
+.data1 	0x00, 0x00, 0xe8, 0xf1, 0x98, 0xff, 0xff, 0x59
+.data1 	0x59, 0x47, 0x80, 0x3f, 0x3a, 0x75, 0xd9, 0x47
+.data1 	0xeb, 0xd6, 0x47, 0x80, 0x3f, 0x3a, 0x75, 0x32
+.data1 	0x80, 0x3e, 0x00, 0x75, 0x25, 0xa1, 0x80, 0x2c
+.data1 	0x00, 0x00, 0x83, 0x05, 0x80, 0x2c, 0x00, 0x00
+.data1 	0x04, 0x8b, 0x10, 0x89, 0xd6, 0x85, 0xd2, 0x75
+.data1 	0x11, 0x0f, 0xbe, 0x45, 0xf7, 0x50, 0x68, 0x4c
+.data1 	0x08, 0x00, 0x00, 0xe8, 0xb8, 0x98, 0xff, 0xff
+.data1 	0x59, 0x59, 0x89, 0x35, 0x30, 0x34, 0x00, 0x00
+.data1 	0x31, 0xf6, 0x89, 0x35, 0xc8, 0x2c, 0x00, 0x00
+.data1 	0x0f, 0xbe, 0x45, 0xf7, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x15, 0x54, 0x34, 0x00, 0x00, 0x85
+.data1 	0xd2, 0x74, 0x24, 0x83, 0x3d, 0xa4, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x75, 0x0b, 0x8b, 0x15, 0x80, 0x34
+.data1 	0x00, 0x00, 0x8d, 0x42, 0x04, 0xeb, 0x09, 0x8b
+.data1 	0x15, 0x98, 0x34, 0x00, 0x00, 0x8d, 0x42, 0x04
+.data1 	0x50, 0xe8, 0x7b, 0x19, 0x00, 0x00, 0x59, 0xc7
+.data1 	0x05, 0x58, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x60, 0x0b, 0x00, 0x00, 0x89, 0x45
+.data1 	0xfc, 0x85, 0xc0, 0x75, 0x07, 0xb8, 0xc4, 0x2c
+.data1 	0x00, 0x00, 0xeb, 0x18, 0x83, 0x7d, 0xfc, 0x01
+.data1 	0x75, 0x04, 0x31, 0xc0, 0xeb, 0x0e, 0xff, 0x05
+.data1 	0xc4, 0x2c, 0x00, 0x00, 0x6a, 0x01, 0xe8, 0x03
+.data1 	0x00, 0x00, 0x00, 0x59, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x14, 0x56, 0x57, 0xc7, 0x05
+.data1 	0x64, 0x34, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x08, 0x00, 0x75, 0x19, 0x68, 0x8c
+.data1 	0x1d, 0x00, 0x00, 0xe8, 0x00, 0x0b, 0x00, 0x00
+.data1 	0x5a, 0x01, 0xc2, 0x80, 0x3a, 0x00, 0x74, 0x07
+.data1 	0x31, 0xc0, 0xe9, 0x34, 0x01, 0x00, 0x00, 0xe8
+.data1 	0x33, 0x01, 0x00, 0x00, 0x89, 0x45, 0xfc, 0xc7
+.data1 	0x45, 0xec, 0x01, 0x00, 0x00, 0x00, 0xe9, 0x08
+.data1 	0x01, 0x00, 0x00, 0x8d, 0x7d, 0xfc, 0x83, 0x7d
+.data1 	0xec, 0x00, 0x75, 0x0e, 0x8b, 0x45, 0xfc, 0x83
+.data1 	0x38, 0x00, 0x75, 0x06, 0x8b, 0x7d, 0xfc, 0x83
+.data1 	0xc7, 0x08, 0x8b, 0x17, 0x83, 0x3a, 0x01, 0x74
+.data1 	0x05, 0x83, 0x3a, 0x02, 0x75, 0x0b, 0x8b, 0x17
+.data1 	0xc7, 0x42, 0x04, 0x01, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x35, 0x8b, 0x17, 0x83, 0x3a, 0x03, 0x75, 0x08
+.data1 	0xc7, 0x02, 0x04, 0x00, 0x00, 0x00, 0xeb, 0x26
+.data1 	0x6a, 0x0c, 0xe8, 0x6b, 0xec, 0xff, 0xff, 0x59
+.data1 	0x89, 0xc6, 0xc7, 0x06, 0x04, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x17, 0x89, 0x56, 0x04, 0xc7, 0x46, 0x08
+.data1 	0x00, 0x00, 0x00, 0x00, 0x89, 0x37, 0xeb, 0x06
+.data1 	0xff, 0x05, 0xc4, 0x2c, 0x00, 0x00, 0xe8, 0x8b
+.data1 	0x0a, 0x00, 0x00, 0x3d, 0x01, 0x00, 0x00, 0x00
+.data1 	0x75, 0x13, 0xe8, 0xc5, 0x09, 0x00, 0x00, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x74, 0x0e, 0x8b, 0x45, 0xfc
+.data1 	0xe9, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x05, 0xc4
+.data1 	0x2c, 0x00, 0x00, 0xc7, 0x05, 0x64, 0x34, 0x00
+.data1 	0x00, 0x02, 0x00, 0x00, 0x00, 0x68, 0x8c, 0x1d
+.data1 	0x00, 0x00, 0xe8, 0x41, 0x0a, 0x00, 0x00, 0x5a
+.data1 	0x01, 0xc2, 0x80, 0x3a, 0x00, 0x74, 0x08, 0x8b
+.data1 	0x45, 0xfc, 0xe9, 0x74, 0x00, 0x00, 0x00, 0xe8
+.data1 	0x73, 0x00, 0x00, 0x00, 0x89, 0x45, 0xf8, 0x6a
+.data1 	0x0c, 0xe8, 0xf4, 0xeb, 0xff, 0xff, 0x59, 0x89
+.data1 	0xc6, 0xc7, 0x06, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xfc, 0x89, 0x56, 0x04, 0x8b, 0x55, 0xf8
+.data1 	0x89, 0x56, 0x08, 0x89, 0x75, 0xfc, 0xeb, 0x42
+.data1 	0x83, 0x3d, 0x4c, 0x34, 0x00, 0x00, 0x00, 0x74
+.data1 	0x07, 0xe8, 0x56, 0x09, 0x00, 0x00, 0xeb, 0x05
+.data1 	0xe8, 0x1c, 0xd1, 0xff, 0xff, 0x8b, 0x45, 0xfc
+.data1 	0xeb, 0x31, 0x83, 0x7d, 0x08, 0x00, 0x74, 0x08
+.data1 	0x6a, 0xff, 0xe8, 0x97, 0x18, 0x00, 0x00, 0x59
+.data1 	0xff, 0x05, 0xc4, 0x2c, 0x00, 0x00, 0x8b, 0x45
+.data1 	0xfc, 0xeb, 0x18, 0xe8, 0xe6, 0x09, 0x00, 0x00
+.data1 	0xbb, 0x90, 0x09, 0x00, 0x00, 0xe9, 0xfe, 0x89
+.data1 	0x00, 0x00, 0xc7, 0x45, 0xec, 0x00, 0x00, 0x00
+.data1 	0x00, 0xeb, 0xe8, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x08, 0x56, 0x57, 0xe8
+.data1 	0x58, 0x00, 0x00, 0x00, 0x89, 0x45, 0xfc, 0xe8
+.data1 	0xba, 0x09, 0x00, 0x00, 0x89, 0xc7, 0x3d, 0x04
+.data1 	0x00, 0x00, 0x00, 0x75, 0x07, 0xbf, 0x06, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x17, 0x83, 0xff, 0x05, 0x75
+.data1 	0x07, 0xbf, 0x07, 0x00, 0x00, 0x00, 0xeb, 0x0b
+.data1 	0xff, 0x05, 0xc4, 0x2c, 0x00, 0x00, 0x8b, 0x45
+.data1 	0xfc, 0xeb, 0x25, 0xe8, 0x24, 0x00, 0x00, 0x00
+.data1 	0x89, 0x45, 0xf8, 0x6a, 0x0c, 0xe8, 0x40, 0xeb
+.data1 	0xff, 0xff, 0x59, 0x89, 0xc6, 0x89, 0x3e, 0x8b
+.data1 	0x55, 0xfc, 0x89, 0x56, 0x04, 0x8b, 0x55, 0xf8
+.data1 	0x89, 0x56, 0x08, 0x89, 0x75, 0xfc, 0xeb, 0xaf
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x10, 0x56, 0x57, 0xe8, 0x79, 0x00, 0x00
+.data1 	0x00, 0x89, 0x45, 0xfc, 0xe8, 0x55, 0x09, 0x00
+.data1 	0x00, 0x3d, 0x06, 0x00, 0x00, 0x00, 0x0f, 0x85
+.data1 	0x59, 0x00, 0x00, 0x00, 0x6a, 0x0c, 0xe8, 0xff
+.data1 	0xea, 0xff, 0xff, 0x59, 0x89, 0xc7, 0xc7, 0x07
+.data1 	0x02, 0x00, 0x00, 0x00, 0xc7, 0x47, 0x04, 0x00
+.data1 	0x00, 0x00, 0x00, 0x6a, 0x08, 0xe8, 0xe8, 0xea
+.data1 	0xff, 0xff, 0x59, 0x89, 0xc6, 0x89, 0x77, 0x08
+.data1 	0x8b, 0x55, 0xfc, 0x89, 0x56, 0x04, 0x89, 0x75
+.data1 	0xf0, 0x6a, 0x08, 0xe8, 0xd2, 0xea, 0xff, 0xff
+.data1 	0x59, 0x89, 0xc6, 0xe8, 0x2a, 0x00, 0x00, 0x00
+.data1 	0x89, 0x46, 0x04, 0x8b, 0x45, 0xf0, 0x89, 0x30
+.data1 	0xe8, 0x01, 0x09, 0x00, 0x00, 0x3d, 0x06, 0x00
+.data1 	0x00, 0x00, 0x74, 0xda, 0xc7, 0x06, 0x00, 0x00
+.data1 	0x00, 0x00, 0x89, 0x7d, 0xfc, 0xff, 0x05, 0xc4
+.data1 	0x2c, 0x00, 0x00, 0x8b, 0x45, 0xfc, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x28
+.data1 	0x56, 0x57, 0xc7, 0x05, 0x64, 0x34, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xe4, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8d, 0x55, 0xe4, 0x89, 0x55
+.data1 	0xe0, 0xe8, 0xc0, 0x08, 0x00, 0x00, 0x3d, 0x0b
+.data1 	0x00, 0x00, 0x00, 0x75, 0x18, 0x8b, 0x35, 0x6c
+.data1 	0x34, 0x00, 0x00, 0x8b, 0x45, 0xe0, 0x89, 0x30
+.data1 	0x8d, 0x56, 0x04, 0x89, 0x55, 0xe0, 0xe8, 0x83
+.data1 	0x06, 0x00, 0x00, 0xeb, 0xdc, 0xff, 0x05, 0xc4
+.data1 	0x2c, 0x00, 0x00, 0xe9, 0x0c, 0x05, 0x00, 0x00
+.data1 	0x6a, 0x10, 0xe8, 0x4b, 0xea, 0xff, 0xff, 0x59
+.data1 	0x89, 0xc7, 0xc7, 0x07, 0x08, 0x00, 0x00, 0x00
+.data1 	0x6a, 0x00, 0xe8, 0x47, 0xfd, 0xff, 0xff, 0x59
+.data1 	0x89, 0x47, 0x04, 0xe8, 0x76, 0x08, 0x00, 0x00
+.data1 	0x3d, 0x0e, 0x00, 0x00, 0x00, 0x74, 0x08, 0x6a
+.data1 	0x0e, 0xe8, 0x08, 0x17, 0x00, 0x00, 0x59, 0x6a
+.data1 	0x00, 0xe8, 0x28, 0xfd, 0xff, 0xff, 0x59, 0x89
+.data1 	0x47, 0x08, 0x89, 0xfe, 0xe8, 0x55, 0x08, 0x00
+.data1 	0x00, 0x3d, 0x10, 0x00, 0x00, 0x00, 0x75, 0x40
+.data1 	0x6a, 0x10, 0xe8, 0x03, 0xea, 0xff, 0xff, 0x59
+.data1 	0x89, 0x46, 0x0c, 0x8b, 0x76, 0x0c, 0xc7, 0x06
+.data1 	0x08, 0x00, 0x00, 0x00, 0x6a, 0x00, 0xe8, 0xfb
+.data1 	0xfc, 0xff, 0xff, 0x59, 0x89, 0x46, 0x04, 0xe8
+.data1 	0x2a, 0x08, 0x00, 0x00, 0x3d, 0x0e, 0x00, 0x00
+.data1 	0x00, 0x74, 0x08, 0x6a, 0x0e, 0xe8, 0xbc, 0x16
+.data1 	0x00, 0x00, 0x59, 0x6a, 0x00, 0xe8, 0xdc, 0xfc
+.data1 	0xff, 0xff, 0x59, 0x89, 0x46, 0x08, 0xeb, 0xb4
+.data1 	0x83, 0x3d, 0x5c, 0x34, 0x00, 0x00, 0x0f, 0x75
+.data1 	0x0d, 0x6a, 0x00, 0xe8, 0xc6, 0xfc, 0xff, 0xff
+.data1 	0x59, 0x89, 0x46, 0x0c, 0xeb, 0x0d, 0xc7, 0x46
+.data1 	0x0c, 0x00, 0x00, 0x00, 0x00, 0xff, 0x05, 0xc4
+.data1 	0x2c, 0x00, 0x00, 0xe8, 0xe6, 0x07, 0x00, 0x00
+.data1 	0x3d, 0x11, 0x00, 0x00, 0x00, 0x74, 0x08, 0x6a
+.data1 	0x11, 0xe8, 0x78, 0x16, 0x00, 0x00, 0x59, 0xc7
+.data1 	0x05, 0x64, 0x34, 0x00, 0x00, 0x01, 0x00, 0x00
+.data1 	0x00, 0xe9, 0x4d, 0x04, 0x00, 0x00, 0x6a, 0x0c
+.data1 	0xe8, 0x7d, 0xe9, 0xff, 0xff, 0x59, 0x89, 0xc7
+.data1 	0x83, 0x3d, 0x5c, 0x34, 0x00, 0x00, 0x12, 0x75
+.data1 	0x07, 0xb8, 0x09, 0x00, 0x00, 0x00, 0xeb, 0x05
+.data1 	0xb8, 0x0a, 0x00, 0x00, 0x00, 0x89, 0x07, 0x6a
+.data1 	0x00, 0xe8, 0x68, 0xfc, 0xff, 0xff, 0x59, 0x89
+.data1 	0x47, 0x04, 0xe8, 0x97, 0x07, 0x00, 0x00, 0x89
+.data1 	0x45, 0xd8, 0x3d, 0x15, 0x00, 0x00, 0x00, 0x74
+.data1 	0x08, 0x6a, 0x15, 0xe8, 0x26, 0x16, 0x00, 0x00
+.data1 	0x59, 0x6a, 0x00, 0xe8, 0x46, 0xfc, 0xff, 0xff
+.data1 	0x59, 0x89, 0x47, 0x08, 0xe8, 0x75, 0x07, 0x00
+.data1 	0x00, 0x3d, 0x16, 0x00, 0x00, 0x00, 0x74, 0x08
+.data1 	0x6a, 0x16, 0xe8, 0x07, 0x16, 0x00, 0x00, 0x59
+.data1 	0xc7, 0x05, 0x64, 0x34, 0x00, 0x00, 0x01, 0x00
+.data1 	0x00, 0x00, 0xe9, 0xdc, 0x03, 0x00, 0x00, 0xe8
+.data1 	0x52, 0x07, 0x00, 0x00, 0x3d, 0x0c, 0x00, 0x00
+.data1 	0x00, 0x75, 0x19, 0x83, 0x3d, 0x70, 0x34, 0x00
+.data1 	0x00, 0x00, 0x75, 0x10, 0xff, 0x35, 0x60, 0x34
+.data1 	0x00, 0x00, 0xe8, 0xa2, 0x15, 0x00, 0x00, 0x59
+.data1 	0x85, 0xc0, 0x75, 0x0b, 0x68, 0x38, 0x0a, 0x00
+.data1 	0x00, 0xe8, 0x2c, 0x16, 0x00, 0x00, 0x59, 0x6a
+.data1 	0x10, 0xe8, 0xdc, 0xe8, 0xff, 0xff, 0x59, 0x89
+.data1 	0xc7, 0xc7, 0x07, 0x0b, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x15, 0x60, 0x34, 0x00, 0x00, 0x89, 0x57, 0x0c
+.data1 	0xe8, 0x09, 0x07, 0x00, 0x00, 0x3d, 0x0c, 0x00
+.data1 	0x00, 0x00, 0x0f, 0x85, 0x97, 0x00, 0x00, 0x00
+.data1 	0x83, 0x3d, 0x70, 0x34, 0x00, 0x00, 0x00, 0x0f
+.data1 	0x85, 0x8a, 0x00, 0x00, 0x00, 0x68, 0x34, 0x0a
+.data1 	0x00, 0x00, 0xff, 0x35, 0x60, 0x34, 0x00, 0x00
+.data1 	0xe8, 0x8b, 0x7a, 0x00, 0x00, 0x59, 0x59, 0x85
+.data1 	0xc0, 0x0f, 0x85, 0x70, 0x00, 0x00, 0x00, 0x8d
+.data1 	0x55, 0xf4, 0x89, 0x55, 0xf0, 0xe8, 0xcc, 0x06
+.data1 	0x00, 0x00, 0x3d, 0x0c, 0x00, 0x00, 0x00, 0x75
+.data1 	0x2f, 0x6a, 0x10, 0xe8, 0x7a, 0xe8, 0xff, 0xff
+.data1 	0x59, 0x89, 0xc6, 0xc7, 0x06, 0x0f, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x15, 0x60, 0x34, 0x00, 0x00, 0x89
+.data1 	0x56, 0x08, 0x8b, 0x15, 0x68, 0x34, 0x00, 0x00
+.data1 	0x89, 0x56, 0x0c, 0x8b, 0x45, 0xf0, 0x89, 0x30
+.data1 	0x8d, 0x56, 0x04, 0x89, 0x55, 0xf0, 0xeb, 0xc5
+.data1 	0x8b, 0x45, 0xf0, 0xc7, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xf4, 0x89, 0x57, 0x04, 0x83
+.data1 	0x3d, 0x5c, 0x34, 0x00, 0x00, 0x01, 0x0f, 0x84
+.data1 	0x53, 0x00, 0x00, 0x00, 0x83, 0x3d, 0x5c, 0x34
+.data1 	0x00, 0x00, 0x02, 0x74, 0x4a, 0x6a, 0xff, 0xe8
+.data1 	0x0a, 0x15, 0x00, 0x00, 0x59, 0xeb, 0x40, 0x6a
+.data1 	0x10, 0xe8, 0x1c, 0xe8, 0xff, 0xff, 0x59, 0x89
+.data1 	0xc6, 0xc7, 0x06, 0x0f, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x46, 0x08, 0x50, 0x1e, 0x00, 0x00, 0xc7, 0x46
+.data1 	0x0c, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x46, 0x04
+.data1 	0x00, 0x00, 0x00, 0x00, 0x89, 0x77, 0x04, 0x83
+.data1 	0x3d, 0x5c, 0x34, 0x00, 0x00, 0x01, 0x74, 0x0f
+.data1 	0x83, 0x3d, 0x5c, 0x34, 0x00, 0x00, 0x02, 0x74
+.data1 	0x06, 0xff, 0x05, 0xc4, 0x2c, 0x00, 0x00, 0xc7
+.data1 	0x05, 0x64, 0x34, 0x00, 0x00, 0x02, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x18, 0x06, 0x00, 0x00, 0x89, 0x45
+.data1 	0xdc, 0x3d, 0x15, 0x00, 0x00, 0x00, 0x75, 0x09
+.data1 	0xc7, 0x45, 0xdc, 0x16, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x17, 0x83, 0x7d, 0xdc, 0x17, 0x75, 0x09, 0xc7
+.data1 	0x45, 0xdc, 0x18, 0x00, 0x00, 0x00, 0xeb, 0x08
+.data1 	0x6a, 0xff, 0xe8, 0x8f, 0x14, 0x00, 0x00, 0x59
+.data1 	0x6a, 0x00, 0xe8, 0xaf, 0xfa, 0xff, 0xff, 0x59
+.data1 	0x89, 0x47, 0x08, 0xe8, 0xde, 0x05, 0x00, 0x00
+.data1 	0x39, 0x45, 0xdc, 0x74, 0x09, 0xff, 0x75, 0xdc
+.data1 	0xe8, 0x71, 0x14, 0x00, 0x00, 0x59, 0xc7, 0x05
+.data1 	0x64, 0x34, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x46, 0x02, 0x00, 0x00, 0x6a, 0x0c, 0xe8
+.data1 	0x76, 0xe7, 0xff, 0xff, 0x59, 0x89, 0xc7, 0xc7
+.data1 	0x07, 0x0c, 0x00, 0x00, 0x00, 0xe8, 0xac, 0x05
+.data1 	0x00, 0x00, 0x3d, 0x0c, 0x00, 0x00, 0x00, 0x74
+.data1 	0x08, 0x6a, 0x0c, 0xe8, 0x3e, 0x14, 0x00, 0x00
+.data1 	0x59, 0x6a, 0x10, 0xe8, 0x52, 0xe7, 0xff, 0xff
+.data1 	0x59, 0x89, 0xc6, 0x89, 0x47, 0x04, 0xc7, 0x06
+.data1 	0x0f, 0x00, 0x00, 0x00, 0x8b, 0x15, 0x60, 0x34
+.data1 	0x00, 0x00, 0x89, 0x56, 0x08, 0x8b, 0x15, 0x68
+.data1 	0x34, 0x00, 0x00, 0x89, 0x56, 0x0c, 0xc7, 0x46
+.data1 	0x04, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x6c, 0x05
+.data1 	0x00, 0x00, 0x3d, 0x01, 0x00, 0x00, 0x00, 0x74
+.data1 	0xf4, 0x83, 0x3d, 0x5c, 0x34, 0x00, 0x00, 0x0c
+.data1 	0x75, 0x16, 0x68, 0x30, 0x0a, 0x00, 0x00, 0xff
+.data1 	0x35, 0x60, 0x34, 0x00, 0x00, 0xe8, 0xf6, 0x78
+.data1 	0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x74, 0x0b
+.data1 	0x68, 0x20, 0x0a, 0x00, 0x00, 0xe8, 0x40, 0x14
+.data1 	0x00, 0x00, 0x59, 0x8d, 0x57, 0x08, 0x89, 0x55
+.data1 	0xe8, 0xc7, 0x05, 0x64, 0x34, 0x00, 0x00, 0x02
+.data1 	0x00, 0x00, 0x00, 0xe8, 0x26, 0x05, 0x00, 0x00
+.data1 	0x3d, 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x85, 0xda
+.data1 	0x00, 0x00, 0x00, 0x6a, 0x10, 0xe8, 0xd0, 0xe6
+.data1 	0xff, 0xff, 0x59, 0x89, 0x45, 0xec, 0x8b, 0x5d
+.data1 	0xe8, 0x89, 0x03, 0x8b, 0x45, 0xec, 0xc7, 0x00
+.data1 	0x0d, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xec, 0x83
+.data1 	0xc2, 0x08, 0x89, 0x55, 0xf0, 0x6a, 0x10, 0xe8
+.data1 	0xae, 0xe6, 0xff, 0xff, 0x59, 0x89, 0x45, 0xf4
+.data1 	0x8b, 0x5d, 0xf0, 0x89, 0x03, 0x8b, 0x45, 0xf4
+.data1 	0xc7, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x8b, 0x55
+.data1 	0xf4, 0x8b, 0x0d, 0x60, 0x34, 0x00, 0x00, 0x89
+.data1 	0x4a, 0x08, 0x8b, 0x55, 0xf4, 0x8b, 0x0d, 0x68
+.data1 	0x34, 0x00, 0x00, 0x89, 0x4a, 0x0c, 0xe8, 0xc3
+.data1 	0x04, 0x00, 0x00, 0x3d, 0x06, 0x00, 0x00, 0x00
+.data1 	0x75, 0x1f, 0x8b, 0x55, 0xf4, 0x83, 0xc2, 0x04
+.data1 	0x89, 0x55, 0xf0, 0xe8, 0xae, 0x04, 0x00, 0x00
+.data1 	0x3d, 0x0c, 0x00, 0x00, 0x00, 0x74, 0xae, 0x6a
+.data1 	0x0c, 0xe8, 0x40, 0x13, 0x00, 0x00, 0x59, 0xeb
+.data1 	0xa4, 0x8b, 0x55, 0xf4, 0xc7, 0x42, 0x04, 0x00
+.data1 	0x00, 0x00, 0x00, 0x83, 0x3d, 0x5c, 0x34, 0x00
+.data1 	0x00, 0x08, 0x74, 0x08, 0x6a, 0x08, 0xe8, 0x23
+.data1 	0x13, 0x00, 0x00, 0x59, 0x6a, 0x00, 0xe8, 0x43
+.data1 	0xf9, 0xff, 0xff, 0x59, 0x8b, 0x55, 0xec, 0x89
+.data1 	0x42, 0x0c, 0xe8, 0x6f, 0x04, 0x00, 0x00, 0x89
+.data1 	0x45, 0xdc, 0x3d, 0x1a, 0x00, 0x00, 0x00, 0x75
+.data1 	0x08, 0xff, 0x05, 0xc4, 0x2c, 0x00, 0x00, 0xeb
+.data1 	0x0e, 0x83, 0x7d, 0xdc, 0x09, 0x74, 0x08, 0x6a
+.data1 	0x09, 0xe8, 0xf0, 0x12, 0x00, 0x00, 0x59, 0x8b
+.data1 	0x55, 0xec, 0x83, 0xc2, 0x04, 0x89, 0x55, 0xe8
+.data1 	0xe9, 0x0c, 0xff, 0xff, 0xff, 0x8b, 0x45, 0xe8
+.data1 	0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x3d
+.data1 	0x5c, 0x34, 0x00, 0x00, 0x1a, 0x74, 0x08, 0x6a
+.data1 	0x1a, 0xe8, 0xc8, 0x12, 0x00, 0x00, 0x59, 0xc7
+.data1 	0x05, 0x64, 0x34, 0x00, 0x00, 0x01, 0x00, 0x00
+.data1 	0x00, 0xe9, 0x9d, 0x00, 0x00, 0x00, 0x6a, 0x0c
+.data1 	0xe8, 0xcd, 0xe5, 0xff, 0xff, 0x59, 0x89, 0xc7
+.data1 	0xc7, 0x07, 0x05, 0x00, 0x00, 0x00, 0x6a, 0x00
+.data1 	0xe8, 0xc9, 0xf8, 0xff, 0xff, 0x59, 0x89, 0x47
+.data1 	0x04, 0xc7, 0x47, 0x08, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe8, 0xf1, 0x03, 0x00, 0x00, 0x3d, 0x08, 0x00
+.data1 	0x00, 0x00, 0x74, 0x08, 0x6a, 0x08, 0xe8, 0x83
+.data1 	0x12, 0x00, 0x00, 0x59, 0xc7, 0x05, 0x64, 0x34
+.data1 	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x5b
+.data1 	0x6a, 0x00, 0xe8, 0x97, 0xf8, 0xff, 0xff, 0x59
+.data1 	0x89, 0xc7, 0xe8, 0xc7, 0x03, 0x00, 0x00, 0x3d
+.data1 	0x18, 0x00, 0x00, 0x00, 0x74, 0x08, 0x6a, 0x18
+.data1 	0xe8, 0x59, 0x12, 0x00, 0x00, 0x59, 0xc7, 0x05
+.data1 	0x64, 0x34, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x31, 0xff, 0x05, 0xc4, 0x2c, 0x00, 0x00
+.data1 	0xff, 0x75, 0xe4, 0xff, 0x75, 0xe0, 0xe8, 0x7f
+.data1 	0x00, 0x00, 0x00, 0x59, 0x59, 0xe9, 0x74, 0x00
+.data1 	0x00, 0x00, 0x6a, 0xff, 0xe8, 0x2d, 0x12, 0x00
+.data1 	0x00, 0x59, 0xeb, 0x0f, 0xe8, 0x85, 0x03, 0x00
+.data1 	0x00, 0xbb, 0xac, 0x09, 0x00, 0x00, 0xe9, 0x9d
+.data1 	0x83, 0x00, 0x00, 0xe8, 0x76, 0x03, 0x00, 0x00
+.data1 	0x3d, 0x0b, 0x00, 0x00, 0x00, 0x75, 0x18, 0x8b
+.data1 	0x35, 0x6c, 0x34, 0x00, 0x00, 0x8b, 0x45, 0xe0
+.data1 	0x89, 0x30, 0x8d, 0x56, 0x04, 0x89, 0x55, 0xe0
+.data1 	0xe8, 0x39, 0x01, 0x00, 0x00, 0xeb, 0xdc, 0xff
+.data1 	0x05, 0xc4, 0x2c, 0x00, 0x00, 0x8b, 0x45, 0xe0
+.data1 	0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x7d
+.data1 	0xe4, 0x00, 0x74, 0x20, 0x83, 0x3f, 0x05, 0x74
+.data1 	0x15, 0x6a, 0x0c, 0xe8, 0xf2, 0xe4, 0xff, 0xff
+.data1 	0x59, 0x89, 0xc6, 0xc7, 0x06, 0x03, 0x00, 0x00
+.data1 	0x00, 0x89, 0x7e, 0x04, 0x89, 0xf7, 0x8b, 0x55
+.data1 	0xe4, 0x89, 0x57, 0x08, 0x89, 0xf8, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c
+.data1 	0x56, 0x57, 0x8b, 0x7d, 0x08, 0x89, 0x7d, 0xf4
+.data1 	0x83, 0x7d, 0x0c, 0x00, 0x75, 0x03, 0x8d, 0x7d
+.data1 	0x0c, 0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8d, 0x55, 0xfc, 0x89, 0x55, 0xf8, 0x89, 0x7d
+.data1 	0xf4, 0xe8, 0xf0, 0x02, 0x00, 0x00, 0x3d, 0x0c
+.data1 	0x00, 0x00, 0x00, 0x75, 0x2f, 0x6a, 0x10, 0xe8
+.data1 	0x9e, 0xe4, 0xff, 0xff, 0x59, 0x89, 0xc6, 0xc7
+.data1 	0x06, 0x0f, 0x00, 0x00, 0x00, 0x8b, 0x15, 0x60
+.data1 	0x34, 0x00, 0x00, 0x89, 0x56, 0x08, 0x8b, 0x15
+.data1 	0x68, 0x34, 0x00, 0x00, 0x89, 0x56, 0x0c, 0x8b
+.data1 	0x45, 0xf8, 0x89, 0x30, 0x8d, 0x56, 0x04, 0x89
+.data1 	0x55, 0xf8, 0xeb, 0xc5, 0x83, 0x3d, 0x5c, 0x34
+.data1 	0x00, 0x00, 0x0b, 0x75, 0x14, 0x8b, 0x35, 0x6c
+.data1 	0x34, 0x00, 0x00, 0x89, 0x37, 0x89, 0xf7, 0x83
+.data1 	0xc7, 0x04, 0xe8, 0x7f, 0x00, 0x00, 0x00, 0xeb
+.data1 	0xa8, 0x83, 0x3d, 0x5c, 0x34, 0x00, 0x00, 0x07
+.data1 	0x75, 0x36, 0x8b, 0x55, 0xfc, 0x83, 0xc2, 0x04
+.data1 	0x39, 0x55, 0xf8, 0x75, 0x2b, 0x39, 0x7d, 0xf4
+.data1 	0x75, 0x26, 0xe8, 0x7f, 0x02, 0x00, 0x00, 0x3d
+.data1 	0x08, 0x00, 0x00, 0x00, 0x74, 0x08, 0x6a, 0x08
+.data1 	0xe8, 0x11, 0x11, 0x00, 0x00, 0x59, 0xc7, 0x06
+.data1 	0x0e, 0x00, 0x00, 0x00, 0xe8, 0x81, 0xf9, 0xff
+.data1 	0xff, 0x89, 0x46, 0x04, 0x89, 0xf0, 0xeb, 0x3a
+.data1 	0xff, 0x05, 0xc4, 0x2c, 0x00, 0x00, 0x8b, 0x45
+.data1 	0xf8, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x07, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x10, 0xe8
+.data1 	0xfe, 0xe3, 0xff, 0xff, 0x59, 0x89, 0xc6, 0xc7
+.data1 	0x06, 0x01, 0x00, 0x00, 0x00, 0xc7, 0x46, 0x04
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xfc, 0x89
+.data1 	0x56, 0x08, 0x8b, 0x55, 0x0c, 0x89, 0x56, 0x0c
+.data1 	0x89, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x10, 0x56, 0x57, 0x8b, 0x35
+.data1 	0x6c, 0x34, 0x00, 0x00, 0xe8, 0x0d, 0x02, 0x00
+.data1 	0x00, 0x3d, 0x0c, 0x00, 0x00, 0x00, 0x74, 0x08
+.data1 	0x6a, 0xff, 0xe8, 0x9f, 0x10, 0x00, 0x00, 0x59
+.data1 	0x83, 0x3e, 0x15, 0x0f, 0x85, 0xb3, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x3d, 0x48, 0x34, 0x00, 0x00, 0x83
+.data1 	0x3d, 0x70, 0x34, 0x00, 0x00, 0x00, 0x75, 0x06
+.data1 	0xc7, 0x06, 0x16, 0x00, 0x00, 0x00, 0x83, 0x7f
+.data1 	0x0c, 0x00, 0x74, 0x13, 0x8b, 0x15, 0x60, 0x34
+.data1 	0x00, 0x00, 0x80, 0x3a, 0x09, 0x75, 0x08, 0xff
+.data1 	0x05, 0x60, 0x34, 0x00, 0x00, 0xeb, 0xed, 0xff
+.data1 	0x35, 0x60, 0x34, 0x00, 0x00, 0xe8, 0xe9, 0x0f
+.data1 	0x00, 0x00, 0x59, 0x85, 0xc0, 0x74, 0x19, 0xff
+.data1 	0x35, 0x60, 0x34, 0x00, 0x00, 0xe8, 0x86, 0x75
+.data1 	0x00, 0x00, 0x59, 0x89, 0x45, 0xf0, 0x85, 0xc0
+.data1 	0x74, 0x06, 0x83, 0x7d, 0xf0, 0x4f, 0x7e, 0x0b
+.data1 	0x68, 0x60, 0x0a, 0x00, 0x00, 0xe8, 0x98, 0x10
+.data1 	0x00, 0x00, 0x59, 0xff, 0x35, 0x60, 0x34, 0x00
+.data1 	0x00, 0xe8, 0xea, 0xc4, 0xff, 0xff, 0x59, 0x8b
+.data1 	0x15, 0x60, 0x34, 0x00, 0x00, 0x89, 0x57, 0x08
+.data1 	0xc7, 0x07, 0x00, 0x00, 0x00, 0x00, 0x83, 0x3d
+.data1 	0x4c, 0x34, 0x00, 0x00, 0x00, 0x75, 0x0b, 0x89
+.data1 	0x3d, 0x4c, 0x34, 0x00, 0x00, 0xe9, 0xa6, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x15, 0x4c, 0x34, 0x00, 0x00
+.data1 	0x89, 0x55, 0xf4, 0x8b, 0x45, 0xf4, 0x83, 0x38
+.data1 	0x00, 0x74, 0x07, 0x8b, 0x10, 0x89, 0x55, 0xf4
+.data1 	0xeb, 0xf1, 0x8b, 0x45, 0xf4, 0x89, 0x38, 0xe9
+.data1 	0x84, 0x00, 0x00, 0x00, 0x83, 0x3e, 0x13, 0x74
+.data1 	0x05, 0x83, 0x3e, 0x14, 0x75, 0x4d, 0x8b, 0x15
+.data1 	0x60, 0x34, 0x00, 0x00, 0x0f, 0xbe, 0x02, 0x2d
+.data1 	0x30, 0x00, 0x00, 0x00, 0x3d, 0x09, 0x00, 0x00
+.data1 	0x00, 0x77, 0x0d, 0x0f, 0xbe, 0x02, 0x2d, 0x30
+.data1 	0x00, 0x00, 0x00, 0x89, 0x46, 0x0c, 0xeb, 0x12
+.data1 	0x8b, 0x15, 0x60, 0x34, 0x00, 0x00, 0x80, 0x3a
+.data1 	0x2d, 0x75, 0x13, 0xc7, 0x46, 0x0c, 0xff, 0xff
+.data1 	0xff, 0xff, 0x8b, 0x15, 0x60, 0x34, 0x00, 0x00
+.data1 	0x80, 0x7a, 0x01, 0x00, 0x74, 0x3a, 0x68, 0x50
+.data1 	0x0a, 0x00, 0x00, 0xe8, 0xf2, 0x0f, 0x00, 0x00
+.data1 	0x59, 0xeb, 0x2d, 0x6a, 0x10, 0xe8, 0xa0, 0xe2
+.data1 	0xff, 0xff, 0x59, 0x89, 0x46, 0x0c, 0x8b, 0x76
+.data1 	0x0c, 0xc7, 0x06, 0x0f, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x15
+.data1 	0x60, 0x34, 0x00, 0x00, 0x89, 0x56, 0x08, 0x8b
+.data1 	0x15, 0x68, 0x34, 0x00, 0x00, 0x89, 0x56, 0x0c
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x83, 0x3d, 0x4c, 0x34, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x84, 0x8e, 0x00, 0x00, 0x00, 0x8b, 0x3d
+.data1 	0x4c, 0x34, 0x00, 0x00, 0x8b, 0x17, 0x89, 0x15
+.data1 	0x4c, 0x34, 0x00, 0x00, 0x83, 0x3d, 0x58, 0x34
+.data1 	0x00, 0x00, 0x00, 0x74, 0x1a, 0x8b, 0x15, 0x8c
+.data1 	0x34, 0x00, 0x00, 0x83, 0xc2, 0x04, 0x52, 0xe8
+.data1 	0x8d, 0x0e, 0x00, 0x00, 0x59, 0xc7, 0x05, 0x58
+.data1 	0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x57, 0x04, 0xff, 0x77, 0x0c, 0xff, 0x77, 0x08
+.data1 	0x83, 0x3a, 0x15, 0x75, 0x07, 0xb8, 0x99, 0x21
+.data1 	0x00, 0x00, 0xeb, 0x05, 0xb8, 0x95, 0x20, 0x00
+.data1 	0x00, 0x50, 0xe8, 0x0e, 0xc5, 0xff, 0xff, 0x50
+.data1 	0xe8, 0xf0, 0x02, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x6a, 0x10, 0xe8, 0x03, 0xe2, 0xff, 0xff, 0x59
+.data1 	0x89, 0xc6, 0xc7, 0x06, 0x0f, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x15, 0x60, 0x34, 0x00, 0x00, 0x89, 0x56, 0x08
+.data1 	0x8b, 0x15, 0x68, 0x34, 0x00, 0x00, 0x89, 0x56
+.data1 	0x0c, 0x8b, 0x57, 0x04, 0x89, 0x72, 0x0c, 0xe9
+.data1 	0x65, 0xff, 0xff, 0xff, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0xe8, 0x0b
+.data1 	0x00, 0x00, 0x00, 0x89, 0x45, 0xfc, 0xff, 0x05
+.data1 	0xc4, 0x2c, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x56, 0x57, 0xe8, 0xa8, 0x00, 0x00, 0x00
+.data1 	0x89, 0xc7, 0x83, 0x3d, 0x64, 0x34, 0x00, 0x00
+.data1 	0x00, 0x0f, 0x84, 0x93, 0x00, 0x00, 0x00, 0x83
+.data1 	0x3d, 0x64, 0x34, 0x00, 0x00, 0x02, 0x75, 0x1d
+.data1 	0xc7, 0x05, 0x64, 0x34, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x83, 0xff, 0x01, 0x75, 0x18, 0xe8
+.data1 	0x10, 0xff, 0xff, 0xff, 0xe8, 0x77, 0x00, 0x00
+.data1 	0x00, 0x89, 0xc7, 0xeb, 0xed, 0xc7, 0x05, 0x64
+.data1 	0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83
+.data1 	0xff, 0x0c, 0x0f, 0x85, 0x5a, 0x00, 0x00, 0x00
+.data1 	0x83, 0x3d, 0x70, 0x34, 0x00, 0x00, 0x00, 0x75
+.data1 	0x51, 0xbe, 0x14, 0x1e, 0x00, 0x00, 0x83, 0x3e
+.data1 	0x00, 0x74, 0x47, 0x8b, 0x16, 0x0f, 0xbe, 0x02
+.data1 	0x8b, 0x15, 0x60, 0x34, 0x00, 0x00, 0x0f, 0xbe
+.data1 	0x1a, 0x39, 0xd8, 0x75, 0x30, 0xff, 0x35, 0x60
+.data1 	0x34, 0x00, 0x00, 0xff, 0x36, 0xe8, 0x26, 0x73
+.data1 	0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x75, 0x1d
+.data1 	0x89, 0xf0, 0x2d, 0x14, 0x1e, 0x00, 0x00, 0xb9
+.data1 	0x04, 0x00, 0x00, 0x00, 0x99, 0xf7, 0xf9, 0x05
+.data1 	0x0d, 0x00, 0x00, 0x00, 0x89, 0xc7, 0xa3, 0x5c
+.data1 	0x34, 0x00, 0x00, 0xeb, 0x05, 0x83, 0xc6, 0x04
+.data1 	0xeb, 0xb4, 0x89, 0xf8, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x83, 0x3d, 0xc4, 0x2c
+.data1 	0x00, 0x00, 0x00, 0x74, 0x15, 0xc7, 0x05, 0xc4
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff
+.data1 	0x35, 0x5c, 0x34, 0x00, 0x00, 0xe9, 0xc7, 0x01
+.data1 	0x00, 0x00, 0x83, 0x3d, 0x58, 0x34, 0x00, 0x00
+.data1 	0x00, 0x74, 0x1a, 0x8b, 0x15, 0x8c, 0x34, 0x00
+.data1 	0x00, 0x83, 0xc2, 0x04, 0x52, 0xe8, 0x1f, 0x0d
+.data1 	0x00, 0x00, 0x59, 0xc7, 0x05, 0x58, 0x34, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x15, 0xa4
+.data1 	0x1b, 0x00, 0x00, 0x89, 0x15, 0x74, 0x34, 0x00
+.data1 	0x00, 0x8b, 0x15, 0xac, 0x2d, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0xac, 0x2d, 0x00, 0x00, 0x78, 0x10
+.data1 	0xa1, 0xb0, 0x2d, 0x00, 0x00, 0xff, 0x05, 0xb0
+.data1 	0x2d, 0x00, 0x00, 0x0f, 0xbe, 0x00, 0xeb, 0x05
+.data1 	0xe8, 0xb9, 0xc3, 0xff, 0xff, 0x89, 0xc6, 0x83
+.data1 	0xfe, 0x20, 0x74, 0xd5, 0x83, 0xfe, 0x09, 0x0f
+.data1 	0x85, 0x45, 0x01, 0x00, 0x00, 0xeb, 0xca, 0xe8
+.data1 	0x79, 0xc3, 0xff, 0xff, 0x89, 0xc6, 0x3d, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x74, 0x08, 0x81, 0xfe, 0x7f
+.data1 	0xff, 0xff, 0xff, 0x75, 0xea, 0xe8, 0xbf, 0xc5
+.data1 	0xff, 0xff, 0xeb, 0xad, 0xe8, 0x5c, 0xc3, 0xff
+.data1 	0xff, 0x3d, 0x0a, 0x00, 0x00, 0x00, 0x75, 0x30
+.data1 	0xff, 0x05, 0xa4, 0x1b, 0x00, 0x00, 0x8b, 0x15
+.data1 	0xa4, 0x1b, 0x00, 0x00, 0x89, 0x15, 0x74, 0x34
+.data1 	0x00, 0x00, 0x83, 0x3d, 0x54, 0x34, 0x00, 0x00
+.data1 	0x00, 0x74, 0x86, 0x8b, 0x15, 0x8c, 0x34, 0x00
+.data1 	0x00, 0x83, 0xc2, 0x04, 0x52, 0xe8, 0x7f, 0x0c
+.data1 	0x00, 0x00, 0x59, 0xe9, 0x71, 0xff, 0xff, 0xff
+.data1 	0xe8, 0x7c, 0xc5, 0xff, 0xff, 0xe9, 0xec, 0x00
+.data1 	0x00, 0x00, 0xff, 0x05, 0xa4, 0x1b, 0x00, 0x00
+.data1 	0x8b, 0x15, 0x54, 0x34, 0x00, 0x00, 0x89, 0x15
+.data1 	0x58, 0x34, 0x00, 0x00, 0xba, 0x01, 0x00, 0x00
+.data1 	0x00, 0x89, 0x15, 0x5c, 0x34, 0x00, 0x00, 0x52
+.data1 	0xe9, 0xdc, 0x00, 0x00, 0x00, 0x31, 0xd2, 0x89
+.data1 	0x15, 0x5c, 0x34, 0x00, 0x00, 0x52, 0xe9, 0xce
+.data1 	0x00, 0x00, 0x00, 0xe8, 0xe5, 0xc2, 0xff, 0xff
+.data1 	0x3d, 0x26, 0x00, 0x00, 0x00, 0x75, 0x11, 0xba
+.data1 	0x04, 0x00, 0x00, 0x00, 0x89, 0x15, 0x5c, 0x34
+.data1 	0x00, 0x00, 0x52, 0xe9, 0xb1, 0x00, 0x00, 0x00
+.data1 	0xe8, 0x24, 0xc5, 0xff, 0xff, 0xba, 0x03, 0x00
+.data1 	0x00, 0x00, 0x89, 0x15, 0x5c, 0x34, 0x00, 0x00
+.data1 	0x52, 0xe9, 0x9b, 0x00, 0x00, 0x00, 0xe8, 0xb2
+.data1 	0xc2, 0xff, 0xff, 0x3d, 0x7c, 0x00, 0x00, 0x00
+.data1 	0x75, 0x11, 0xba, 0x05, 0x00, 0x00, 0x00, 0x89
+.data1 	0x15, 0x5c, 0x34, 0x00, 0x00, 0x52, 0xe9, 0x7e
+.data1 	0x00, 0x00, 0x00, 0xe8, 0xf1, 0xc4, 0xff, 0xff
+.data1 	0xba, 0x06, 0x00, 0x00, 0x00, 0x89, 0x15, 0x5c
+.data1 	0x34, 0x00, 0x00, 0x52, 0xe9, 0x68, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x7f, 0xc2, 0xff, 0xff, 0x3d, 0x3b
+.data1 	0x00, 0x00, 0x00, 0x75, 0x0e, 0xba, 0x09, 0x00
+.data1 	0x00, 0x00, 0x89, 0x15, 0x5c, 0x34, 0x00, 0x00
+.data1 	0x52, 0xeb, 0x4e, 0xe8, 0xc1, 0xc4, 0xff, 0xff
+.data1 	0xba, 0x02, 0x00, 0x00, 0x00, 0x89, 0x15, 0x5c
+.data1 	0x34, 0x00, 0x00, 0x52, 0xeb, 0x3b, 0xba, 0x07
+.data1 	0x00, 0x00, 0x00, 0x89, 0x15, 0x5c, 0x34, 0x00
+.data1 	0x00, 0x52, 0xeb, 0x2d, 0xba, 0x08, 0x00, 0x00
+.data1 	0x00, 0x89, 0x15, 0x5c, 0x34, 0x00, 0x00, 0x52
+.data1 	0xeb, 0x1f, 0xbb, 0x88, 0x0a, 0x00, 0x00, 0x89
+.data1 	0xf0, 0xe9, 0xc6, 0x7d, 0x00, 0x00, 0x6a, 0x00
+.data1 	0x6a, 0x00, 0x68, 0x91, 0x1f, 0x00, 0x00, 0x56
+.data1 	0xe8, 0x08, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x50, 0x58, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x81, 0xec, 0xb8, 0x00, 0x00, 0x00, 0x56, 0x57
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xfc, 0x8b, 0x15
+.data1 	0xa4, 0x1b, 0x00, 0x00, 0x89, 0x15, 0x74, 0x34
+.data1 	0x00, 0x00, 0xc7, 0x45, 0x98, 0x00, 0x00, 0x00
+.data1 	0x00, 0x81, 0x7d, 0x0c, 0x95, 0x20, 0x00, 0x00
+.data1 	0x75, 0x07, 0xc7, 0x45, 0x98, 0x01, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x45, 0x9c, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xa0, 0x00, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x45, 0x94, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x15
+.data1 	0xa8, 0x1c, 0x00, 0x00, 0x89, 0x55, 0xf8, 0x8b
+.data1 	0x15, 0xac, 0x1c, 0x00, 0x00, 0x89, 0x15, 0x84
+.data1 	0x2c, 0x00, 0x00, 0xe9, 0x4d, 0x03, 0x00, 0x00
+.data1 	0x83, 0x3d, 0x84, 0x2c, 0x00, 0x00, 0x03, 0x0f
+.data1 	0x8d, 0x10, 0x02, 0x00, 0x00, 0xe8, 0x8c, 0xe1
+.data1 	0xff, 0xff, 0x89, 0x45, 0xf8, 0xe9, 0x03, 0x02
+.data1 	0x00, 0x00, 0x81, 0x7d, 0x0c, 0x91, 0x1f, 0x00
+.data1 	0x00, 0x0f, 0x84, 0x35, 0x02, 0x00, 0x00, 0xff
+.data1 	0x0d, 0x84, 0x2c, 0x00, 0x00, 0x8b, 0x45, 0xfc
+.data1 	0x0f, 0xbe, 0xc0, 0x8b, 0x5d, 0xf8, 0xff, 0x45
+.data1 	0xf8, 0x88, 0x03, 0xff, 0x05, 0xa4, 0x1b, 0x00
+.data1 	0x00, 0x83, 0x3d, 0x54, 0x34, 0x00, 0x00, 0x00
+.data1 	0x74, 0x10, 0x8b, 0x15, 0x8c, 0x34, 0x00, 0x00
+.data1 	0x83, 0xc2, 0x04, 0x52, 0xe8, 0xb0, 0x0a, 0x00
+.data1 	0x00, 0x59, 0xe8, 0x56, 0xc1, 0xff, 0xff, 0x89
+.data1 	0x45, 0xfc, 0xe9, 0xe6, 0x02, 0x00, 0x00, 0xff
+.data1 	0x0d, 0x84, 0x2c, 0x00, 0x00, 0x8b, 0x45, 0xfc
+.data1 	0x0f, 0xbe, 0xc0, 0x8b, 0x5d, 0xf8, 0xff, 0x45
+.data1 	0xf8, 0x88, 0x03, 0xe9, 0xb0, 0x01, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x10, 0x00, 0x74, 0x06, 0x83, 0x7d
+.data1 	0x98, 0x00, 0x74, 0x0f, 0xff, 0x0d, 0x84, 0x2c
+.data1 	0x00, 0x00, 0x8b, 0x45, 0xf8, 0xff, 0x45, 0xf8
+.data1 	0xc6, 0x00, 0x81, 0xff, 0x0d, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x45, 0xfc, 0x0f, 0xbe, 0xc0, 0x8b
+.data1 	0x5d, 0xf8, 0xff, 0x45, 0xf8, 0x88, 0x03, 0xe9
+.data1 	0x7c, 0x01, 0x00, 0x00, 0xe8, 0xfc, 0xc0, 0xff
+.data1 	0xff, 0x89, 0x45, 0xfc, 0x3d, 0x7f, 0xff, 0xff
+.data1 	0xff, 0x75, 0x19, 0xff, 0x0d, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x5d, 0xf8, 0xff, 0x45, 0xf8, 0xc6
+.data1 	0x03, 0x5c, 0xe8, 0x3a, 0xc3, 0xff, 0xff, 0xe9
+.data1 	0x54, 0x01, 0x00, 0x00, 0x83, 0x7d, 0xfc, 0x0a
+.data1 	0x75, 0x22, 0x83, 0x3d, 0x54, 0x34, 0x00, 0x00
+.data1 	0x00, 0x0f, 0x84, 0x41, 0x01, 0x00, 0x00, 0x8b
+.data1 	0x15, 0x8c, 0x34, 0x00, 0x00, 0x83, 0xc2, 0x04
+.data1 	0x52, 0xe8, 0x0b, 0x0a, 0x00, 0x00, 0x59, 0xe9
+.data1 	0x2c, 0x01, 0x00, 0x00, 0x83, 0x7d, 0x98, 0x00
+.data1 	0x74, 0x2d, 0x83, 0x7d, 0xfc, 0x5c, 0x74, 0x27
+.data1 	0x83, 0x7d, 0xfc, 0x60, 0x74, 0x21, 0x83, 0x7d
+.data1 	0xfc, 0x24, 0x74, 0x1b, 0x83, 0x7d, 0xfc, 0x22
+.data1 	0x75, 0x06, 0x83, 0x7d, 0x10, 0x00, 0x74, 0x0f
+.data1 	0xff, 0x0d, 0x84, 0x2c, 0x00, 0x00, 0x8b, 0x45
+.data1 	0xf8, 0xff, 0x45, 0xf8, 0xc6, 0x00, 0x5c, 0x8b
+.data1 	0x45, 0xfc, 0x80, 0xb8, 0x99, 0x21, 0x00, 0x00
+.data1 	0x0a, 0x75, 0x0f, 0xff, 0x0d, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x5d, 0xf8, 0xff, 0x45, 0xf8, 0xc6
+.data1 	0x03, 0x81, 0xff, 0x0d, 0x84, 0x2c, 0x00, 0x00
+.data1 	0x8b, 0x45, 0xfc, 0x0f, 0xbe, 0xc0, 0x8b, 0x5d
+.data1 	0xf8, 0xff, 0x45, 0xf8, 0x88, 0x03, 0xff, 0x45
+.data1 	0x9c, 0xe9, 0xc2, 0x00, 0x00, 0x00, 0xc7, 0x45
+.data1 	0x0c, 0x99, 0x21, 0x00, 0x00, 0xe9, 0xb6, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x45, 0x0c, 0x95, 0x20, 0x00
+.data1 	0x00, 0xc7, 0x45, 0x98, 0x01, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xa3, 0x00, 0x00, 0x00, 0x83, 0x7d, 0x10
+.data1 	0x00, 0x74, 0x19, 0xff, 0x0d, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x45, 0xfc, 0x0f, 0xbe, 0xc0, 0x8b
+.data1 	0x5d, 0xf8, 0xff, 0x45, 0xf8, 0x88, 0x03, 0xe9
+.data1 	0x84, 0x00, 0x00, 0x00, 0xc7, 0x45, 0x0c, 0x91
+.data1 	0x1f, 0x00, 0x00, 0xff, 0x45, 0x9c, 0xc7, 0x45
+.data1 	0x98, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x6e, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7d, 0x94, 0x00, 0x7e, 0x17
+.data1 	0xff, 0x4d, 0x94, 0xff, 0x0d, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x45, 0xf8, 0xff, 0x45, 0xf8, 0xc6
+.data1 	0x00, 0x83, 0xe9, 0x51, 0x00, 0x00, 0x00, 0xff
+.data1 	0x0d, 0x84, 0x2c, 0x00, 0x00, 0x8b, 0x45, 0xfc
+.data1 	0x0f, 0xbe, 0xc0, 0x8b, 0x5d, 0xf8, 0xff, 0x45
+.data1 	0xf8, 0x88, 0x03, 0xeb, 0x3b, 0xc7, 0x45, 0x90
+.data1 	0x01, 0x00, 0x00, 0x00, 0xe9, 0x14, 0x05, 0x00
+.data1 	0x00, 0x83, 0x7d, 0x94, 0x00, 0x74, 0x55, 0xff
+.data1 	0x0d, 0x84, 0x2c, 0x00, 0x00, 0x8b, 0x45, 0xfc
+.data1 	0x0f, 0xbe, 0xc0, 0x8b, 0x5d, 0xf8, 0xff, 0x45
+.data1 	0xf8, 0x88, 0x03, 0xeb, 0x13, 0x8b, 0x55, 0x0c
+.data1 	0x03, 0x55, 0xfc, 0x0f, 0xbe, 0x02, 0xbb, 0xe8
+.data1 	0x0a, 0x00, 0x00, 0xe9, 0xf0, 0x7a, 0x00, 0x00
+.data1 	0x8b, 0x15, 0xac, 0x2d, 0x00, 0x00, 0x4a, 0x89
+.data1 	0x15, 0xac, 0x2d, 0x00, 0x00, 0x78, 0x10, 0xa1
+.data1 	0xb0, 0x2d, 0x00, 0x00, 0xff, 0x05, 0xb0, 0x2d
+.data1 	0x00, 0x00, 0x0f, 0xbe, 0x00, 0xeb, 0x05, 0xe8
+.data1 	0x8a, 0xbf, 0xff, 0xff, 0x89, 0x45, 0xfc, 0xe9
+.data1 	0xa4, 0xfd, 0xff, 0xff, 0x81, 0x7d, 0x0c, 0x91
+.data1 	0x1f, 0x00, 0x00, 0x74, 0x1a, 0x83, 0x3d, 0x50
+.data1 	0x34, 0x00, 0x00, 0x00, 0x75, 0x11, 0x83, 0x7d
+.data1 	0x10, 0x00, 0x75, 0x0b, 0x68, 0x44, 0x0b, 0x00
+.data1 	0x00, 0xe8, 0x84, 0x09, 0x00, 0x00, 0x59, 0x83
+.data1 	0x7d, 0x94, 0x00, 0x74, 0x17, 0x8b, 0x15, 0xa4
+.data1 	0x1b, 0x00, 0x00, 0x89, 0x15, 0x74, 0x34, 0x00
+.data1 	0x00, 0x68, 0x38, 0x0b, 0x00, 0x00, 0xe8, 0x67
+.data1 	0x09, 0x00, 0x00, 0x59, 0xff, 0x0d, 0x84, 0x2c
+.data1 	0x00, 0x00, 0x8b, 0x45, 0xf8, 0xff, 0x45, 0xf8
+.data1 	0xc6, 0x00, 0x00, 0x8b, 0x55, 0xf8, 0x2b, 0x15
+.data1 	0xa8, 0x1c, 0x00, 0x00, 0x89, 0x55, 0xf4, 0x8b
+.data1 	0x15, 0xa8, 0x1c, 0x00, 0x00, 0x89, 0x55, 0xf8
+.data1 	0x83, 0x7d, 0x10, 0x00, 0x0f, 0x85, 0x4e, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7d, 0xfc, 0x3e, 0x74, 0x06
+.data1 	0x83, 0x7d, 0xfc, 0x3c, 0x75, 0x3d, 0x83, 0x7d
+.data1 	0x9c, 0x00, 0x75, 0x37, 0x83, 0x7d, 0xf4, 0x02
+.data1 	0x7f, 0x31, 0x8b, 0x55, 0xf8, 0x80, 0x3a, 0x00
+.data1 	0x0f, 0x84, 0x1b, 0x01, 0x00, 0x00, 0x0f, 0xbe
+.data1 	0x02, 0x2d, 0x30, 0x00, 0x00, 0x00, 0x3d, 0x09
+.data1 	0x00, 0x00, 0x00, 0x77, 0x16, 0xe9, 0x07, 0x01
+.data1 	0x00, 0x00, 0xba, 0x0b, 0x00, 0x00, 0x00, 0x89
+.data1 	0x15, 0x5c, 0x34, 0x00, 0x00, 0x52, 0xe9, 0xf1
+.data1 	0x07, 0x00, 0x00, 0xe8, 0xf9, 0xc0, 0xff, 0xff
+.data1 	0x8b, 0x55, 0x9c, 0x89, 0x15, 0x70, 0x34, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xa0, 0x89, 0x15, 0x68, 0x34
+.data1 	0x00, 0x00, 0xff, 0x75, 0xf4, 0xe8, 0xdd, 0xdd
+.data1 	0xff, 0xff, 0x59, 0x8b, 0x55, 0xf8, 0x89, 0x15
+.data1 	0x60, 0x34, 0x00, 0x00, 0xba, 0x0c, 0x00, 0x00
+.data1 	0x00, 0x89, 0x15, 0x5c, 0x34, 0x00, 0x00, 0x52
+.data1 	0xe9, 0xb7, 0x07, 0x00, 0x00, 0x83, 0x7d, 0x10
+.data1 	0x00, 0x0f, 0x84, 0xa9, 0xfc, 0xff, 0xff, 0x83
+.data1 	0x7d, 0x14, 0x00, 0x74, 0x10, 0x83, 0x7d, 0xfc
+.data1 	0x09, 0x75, 0x0a, 0xe8, 0x4d, 0xbe, 0xff, 0xff
+.data1 	0x89, 0x45, 0xfc, 0xeb, 0xf0, 0x8b, 0x55, 0x10
+.data1 	0x0f, 0xbe, 0x02, 0x39, 0x45, 0xfc, 0x0f, 0x85
+.data1 	0x84, 0xfc, 0xff, 0xff, 0x6a, 0x50, 0x8d, 0x45
+.data1 	0xa4, 0x50, 0xe8, 0xc9, 0xbd, 0xff, 0xff, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x0f, 0x84, 0x6f, 0xfc, 0xff
+.data1 	0xff, 0x8d, 0x55, 0xa4, 0x89, 0x55, 0x8c, 0x8b
+.data1 	0x55, 0x10, 0x83, 0xc2, 0x01, 0x89, 0x55, 0x88
+.data1 	0x8b, 0x55, 0x88, 0x80, 0x3a, 0x00, 0x74, 0x18
+.data1 	0x8b, 0x55, 0x8c, 0x0f, 0xbe, 0x02, 0x8b, 0x55
+.data1 	0x88, 0x0f, 0xbe, 0x1a, 0x39, 0xd8, 0x75, 0x08
+.data1 	0xff, 0x45, 0x8c, 0xff, 0x45, 0x88, 0xeb, 0xe0
+.data1 	0x8b, 0x55, 0x8c, 0x80, 0x3a, 0x0a, 0x75, 0x26
+.data1 	0x8b, 0x55, 0x88, 0x80, 0x3a, 0x00, 0x75, 0x1e
+.data1 	0xc7, 0x45, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff
+.data1 	0x05, 0xa4, 0x1b, 0x00, 0x00, 0x8b, 0x15, 0x54
+.data1 	0x34, 0x00, 0x00, 0x89, 0x15, 0x58, 0x34, 0x00
+.data1 	0x00, 0xe9, 0x12, 0xfc, 0xff, 0xff, 0x8d, 0x45
+.data1 	0xa4, 0x50, 0xe8, 0xe1, 0x6c, 0x00, 0x00, 0x59
+.data1 	0x50, 0x8d, 0x45, 0xa4, 0x50, 0xe8, 0x20, 0xc0
+.data1 	0xff, 0xff, 0x59, 0x59, 0xe9, 0xf7, 0xfb, 0xff
+.data1 	0xff, 0x8b, 0x55, 0xf8, 0x8a, 0x0a, 0x88, 0x4d
+.data1 	0x87, 0x6a, 0x14, 0xe8, 0xa2, 0xda, 0xff, 0xff
+.data1 	0x59, 0x89, 0x45, 0x80, 0x83, 0x7d, 0xfc, 0x3e
+.data1 	0x75, 0x4b, 0xc7, 0x40, 0x08, 0x01, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x87, 0xbd, 0xff, 0xff, 0x89, 0x45
+.data1 	0xfc, 0x3d, 0x3e, 0x00, 0x00, 0x00, 0x75, 0x0e
+.data1 	0x8b, 0x45, 0x80, 0xc7, 0x00, 0x12, 0x00, 0x00
+.data1 	0x00, 0xe9, 0xc3, 0x00, 0x00, 0x00, 0x83, 0x7d
+.data1 	0xfc, 0x26, 0x75, 0x0e, 0x8b, 0x45, 0x80, 0xc7
+.data1 	0x00, 0x13, 0x00, 0x00, 0x00, 0xe9, 0xaf, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x45, 0x80, 0xc7, 0x00, 0x10
+.data1 	0x00, 0x00, 0x00, 0xe8, 0xa9, 0xbf, 0xff, 0xff
+.data1 	0xe9, 0x9c, 0x00, 0x00, 0x00, 0x8b, 0x55, 0x80
+.data1 	0xc7, 0x42, 0x08, 0x00, 0x00, 0x00, 0x00, 0xe8
+.data1 	0x39, 0xbd, 0xff, 0xff, 0x89, 0x45, 0xfc, 0x3d
+.data1 	0x3c, 0x00, 0x00, 0x00, 0x0f, 0x85, 0x60, 0x00
+.data1 	0x00, 0x00, 0x6a, 0x10, 0xe8, 0x29, 0xda, 0xff
+.data1 	0xff, 0x59, 0x89, 0x45, 0x80, 0xc7, 0x40, 0x08
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x45, 0x80, 0xc7
+.data1 	0x00, 0x15, 0x00, 0x00, 0x00, 0x6a, 0x10, 0xe8
+.data1 	0x0e, 0xda, 0xff, 0xff, 0x59, 0xa3, 0x48, 0x34
+.data1 	0x00, 0x00, 0x8b, 0x55, 0x80, 0x89, 0x50, 0x04
+.data1 	0xe8, 0xf8, 0xbc, 0xff, 0xff, 0x89, 0x45, 0xfc
+.data1 	0x3d, 0x2d, 0x00, 0x00, 0x00, 0x75, 0x0f, 0x8b
+.data1 	0x15, 0x48, 0x34, 0x00, 0x00, 0xc7, 0x42, 0x0c
+.data1 	0x01, 0x00, 0x00, 0x00, 0xeb, 0x33, 0x8b, 0x15
+.data1 	0x48, 0x34, 0x00, 0x00, 0xc7, 0x42, 0x0c, 0x00
+.data1 	0x00, 0x00, 0x00, 0xe8, 0x29, 0xbf, 0xff, 0xff
+.data1 	0xeb, 0x1f, 0x83, 0x7d, 0xfc, 0x26, 0x75, 0x0b
+.data1 	0x8b, 0x45, 0x80, 0xc7, 0x00, 0x14, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x0e, 0x8b, 0x45, 0x80, 0xc7, 0x00
+.data1 	0x11, 0x00, 0x00, 0x00, 0xe8, 0x08, 0xbf, 0xff
+.data1 	0xff, 0x80, 0x7d, 0x87, 0x00, 0x74, 0x0f, 0x0f
+.data1 	0xbe, 0x45, 0x87, 0x2d, 0x30, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x80, 0x89, 0x42, 0x08, 0x8b, 0x55
+.data1 	0x80, 0x89, 0x15, 0x6c, 0x34, 0x00, 0x00, 0xe9
+.data1 	0xd6, 0xfd, 0xff, 0xff, 0xe8, 0x84, 0xbc, 0xff
+.data1 	0xff, 0x89, 0x45, 0xfc, 0x3d, 0x28, 0x00, 0x00
+.data1 	0x00, 0x74, 0x31, 0x83, 0x7d, 0xfc, 0x7b, 0x74
+.data1 	0x2b, 0xf6, 0x80, 0x9d, 0x22, 0x00, 0x00, 0x0e
+.data1 	0x75, 0x22, 0xf6, 0x80, 0x9d, 0x22, 0x00, 0x00
+.data1 	0x11, 0x75, 0x19, 0xff, 0x0d, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x5d, 0xf8, 0xff, 0x45, 0xf8, 0xc6
+.data1 	0x03, 0x24, 0xe8, 0xaa, 0xbe, 0xff, 0xff, 0xe9
+.data1 	0xc4, 0xfc, 0xff, 0xff, 0x83, 0x7d, 0xfc, 0x28
+.data1 	0x75, 0x0c, 0xc7, 0x45, 0x90, 0x00, 0x00, 0x00
+.data1 	0x00, 0xe9, 0x97, 0x01, 0x00, 0x00, 0xff, 0x0d
+.data1 	0x84, 0x2c, 0x00, 0x00, 0x8b, 0x45, 0xf8, 0xff
+.data1 	0x45, 0xf8, 0xc6, 0x00, 0x82, 0x8b, 0x55, 0xf8
+.data1 	0x2b, 0x15, 0xa8, 0x1c, 0x00, 0x00, 0x89, 0x95
+.data1 	0x78, 0xff, 0xff, 0xff, 0xff, 0x0d, 0x84, 0x2c
+.data1 	0x00, 0x00, 0x8b, 0x45, 0xf8, 0xff, 0x45, 0xf8
+.data1 	0xc6, 0x00, 0x01, 0xc7, 0x85, 0x7c, 0xff, 0xff
+.data1 	0xff, 0x01, 0x00, 0x00, 0x00, 0x83, 0x7d, 0xfc
+.data1 	0x7b, 0x75, 0x12, 0xe8, 0xf5, 0xbb, 0xff, 0xff
+.data1 	0x89, 0x45, 0xfc, 0xc7, 0x85, 0x7c, 0xff, 0xff
+.data1 	0xff, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x45, 0xfc
+.data1 	0xf6, 0x80, 0x9d, 0x22, 0x00, 0x00, 0x0e, 0x74
+.data1 	0x48, 0x8b, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x78, 0x10
+.data1 	0x8b, 0x45, 0xfc, 0x0f, 0xbe, 0xc0, 0x8b, 0x5d
+.data1 	0xf8, 0xff, 0x45, 0xf8, 0x88, 0x03, 0xeb, 0x16
+.data1 	0xe8, 0x40, 0xdb, 0xff, 0xff, 0x89, 0x45, 0xf8
+.data1 	0x8b, 0x45, 0xfc, 0x0f, 0xbe, 0xc0, 0x8b, 0x5d
+.data1 	0xf8, 0xff, 0x45, 0xf8, 0x88, 0x03, 0xe8, 0xa2
+.data1 	0xbb, 0xff, 0xff, 0x89, 0x45, 0xfc, 0xf6, 0x80
+.data1 	0x9d, 0x22, 0x00, 0x00, 0x0f, 0x75, 0xba, 0xeb
+.data1 	0x33, 0x8b, 0x45, 0xfc, 0xf6, 0x80, 0x9d, 0x22
+.data1 	0x00, 0x00, 0x11, 0x75, 0x0b, 0x68, 0x24, 0x0b
+.data1 	0x00, 0x00, 0xe8, 0xcb, 0x05, 0x00, 0x00, 0x59
+.data1 	0xff, 0x0d, 0x84, 0x2c, 0x00, 0x00, 0x8b, 0x45
+.data1 	0xfc, 0x0f, 0xbe, 0xc0, 0x8b, 0x5d, 0xf8, 0xff
+.data1 	0x45, 0xf8, 0x88, 0x03, 0xe8, 0x64, 0xbb, 0xff
+.data1 	0xff, 0x89, 0x45, 0xfc, 0x8b, 0x15, 0x84, 0x2c
+.data1 	0x00, 0x00, 0x4a, 0x89, 0x15, 0x84, 0x2c, 0x00
+.data1 	0x00, 0x78, 0x0b, 0x8b, 0x45, 0xf8, 0xff, 0x45
+.data1 	0xf8, 0xc6, 0x00, 0x3d, 0xeb, 0x0e, 0xe8, 0xca
+.data1 	0xda, 0xff, 0xff, 0x89, 0x45, 0xf8, 0xff, 0x45
+.data1 	0xf8, 0xc6, 0x00, 0x3d, 0xc7, 0x85, 0x74, 0xff
+.data1 	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x83, 0xbd
+.data1 	0x7c, 0xff, 0xff, 0xff, 0x00, 0x75, 0x40, 0x83
+.data1 	0x7d, 0xfc, 0x3a, 0x75, 0x12, 0xc7, 0x85, 0x74
+.data1 	0xff, 0xff, 0xff, 0x20, 0x00, 0x00, 0x00, 0xe8
+.data1 	0x11, 0xbb, 0xff, 0xff, 0x89, 0x45, 0xfc, 0xff
+.data1 	0x75, 0xfc, 0x68, 0x58, 0x1e, 0x00, 0x00, 0xe8
+.data1 	0xba, 0xde, 0xff, 0xff, 0x59, 0x59, 0x89, 0x45
+.data1 	0x80, 0x85, 0xc0, 0x0f, 0x84, 0x6c, 0xff, 0xff
+.data1 	0xff, 0x2d, 0x58, 0x1e, 0x00, 0x00, 0x40, 0x89
+.data1 	0x85, 0x7c, 0xff, 0xff, 0xff, 0xeb, 0x05, 0xe8
+.data1 	0x3d, 0xbd, 0xff, 0xff, 0x83, 0x7d, 0x98, 0x00
+.data1 	0x74, 0x07, 0x83, 0x8d, 0x74, 0xff, 0xff, 0xff
+.data1 	0x40, 0x8b, 0x95, 0x74, 0xff, 0xff, 0xff, 0x0b
+.data1 	0x95, 0x7c, 0xff, 0xff, 0xff, 0x89, 0xd0, 0x0f
+.data1 	0xbe, 0xc0, 0x8b, 0x15, 0xa8, 0x1c, 0x00, 0x00
+.data1 	0x03, 0x95, 0x78, 0xff, 0xff, 0xff, 0x88, 0x02
+.data1 	0x83, 0xbd, 0x7c, 0xff, 0xff, 0xff, 0x01, 0x0f
+.data1 	0x84, 0x23, 0xfb, 0xff, 0xff, 0xff, 0x45, 0x94
+.data1 	0xe9, 0x1b, 0xfb, 0xff, 0xff, 0x8b, 0x15, 0x50
+.data1 	0x34, 0x00, 0x00, 0x89, 0x95, 0x7c, 0xff, 0xff
+.data1 	0xff, 0xff, 0x35, 0x20, 0x0b, 0x00, 0x00, 0x6a
+.data1 	0x01, 0x8d, 0x85, 0x58, 0xff, 0xff, 0xff, 0x50
+.data1 	0xe8, 0x03, 0x6a, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x85, 0xc0, 0x74, 0x3c, 0xff, 0xb5, 0x6c, 0xff
+.data1 	0xff, 0xff, 0x5a, 0x85, 0xd2, 0x74, 0x0c, 0xff
+.data1 	0xb5, 0x6c, 0xff, 0xff, 0xff, 0xe8, 0x2c, 0x55
+.data1 	0x00, 0x00, 0x59, 0xc7, 0x05, 0x50, 0x34, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb5, 0x54
+.data1 	0xff, 0xff, 0xff, 0x8f, 0x05, 0x94, 0x2c, 0x00
+.data1 	0x00, 0x6a, 0x01, 0xff, 0x35, 0x94, 0x2c, 0x00
+.data1 	0x00, 0xe8, 0x04, 0x6a, 0x00, 0x00, 0x59, 0x59
+.data1 	0xff, 0x05, 0x90, 0x2c, 0x00, 0x00, 0xc7, 0x85
+.data1 	0x6c, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x55, 0xf8, 0x2b, 0x15, 0xa8, 0x1c, 0x00
+.data1 	0x00, 0x89, 0x95, 0x78, 0xff, 0xff, 0xff, 0x85
+.data1 	0xd2, 0x7e, 0x2c, 0xff, 0xb5, 0x78, 0xff, 0xff
+.data1 	0xff, 0xe8, 0xa2, 0xd6, 0xff, 0xff, 0x59, 0x89
+.data1 	0x85, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xb5, 0x78
+.data1 	0xff, 0xff, 0xff, 0xff, 0xb5, 0x6c, 0xff, 0xff
+.data1 	0xff, 0xff, 0x35, 0xa8, 0x1c, 0x00, 0x00, 0xe8
+.data1 	0xcc, 0xdd, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x8b
+.data1 	0x15, 0x94, 0x2c, 0x00, 0x00, 0x89, 0x95, 0x54
+.data1 	0xff, 0xff, 0xff, 0x8d, 0x95, 0x58, 0xff, 0xff
+.data1 	0xff, 0x89, 0x15, 0x94, 0x2c, 0x00, 0x00, 0x8b
+.data1 	0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x75, 0x10, 0xff, 0x35
+.data1 	0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74
+.data1 	0x05, 0xe8, 0x99, 0x81, 0xff, 0xff, 0x83, 0x7d
+.data1 	0x90, 0x00, 0x0f, 0x84, 0x8e, 0x01, 0x00, 0x00
+.data1 	0x8b, 0x15, 0xa8, 0x1c, 0x00, 0x00, 0x89, 0x55
+.data1 	0x8c, 0x8b, 0x15, 0xac, 0x1c, 0x00, 0x00, 0x89
+.data1 	0x15, 0x84, 0x2c, 0x00, 0x00, 0xe8, 0x93, 0xb9
+.data1 	0xff, 0xff, 0x89, 0x85, 0x50, 0xff, 0xff, 0xff
+.data1 	0x3d, 0x60, 0x00, 0x00, 0x00, 0x0f, 0x84, 0xd7
+.data1 	0x00, 0x00, 0x00, 0x83, 0xbd, 0x50, 0xff, 0xff
+.data1 	0xff, 0x5c, 0x0f, 0x85, 0x5f, 0x00, 0x00, 0x00
+.data1 	0xe8, 0x70, 0xb9, 0xff, 0xff, 0x89, 0x85, 0x50
+.data1 	0xff, 0xff, 0xff, 0x3d, 0x5c, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x84, 0x49, 0x00, 0x00, 0x00, 0x83, 0xbd
+.data1 	0x50, 0xff, 0xff, 0xff, 0x60, 0x74, 0x40, 0x83
+.data1 	0xbd, 0x50, 0xff, 0xff, 0xff, 0x24, 0x74, 0x37
+.data1 	0x83, 0x7d, 0x98, 0x00, 0x74, 0x09, 0x83, 0xbd
+.data1 	0x50, 0xff, 0xff, 0xff, 0x22, 0x74, 0x28, 0x8b
+.data1 	0x15, 0x84, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0x84, 0x2c, 0x00, 0x00, 0x78, 0x0b, 0x8b, 0x45
+.data1 	0x8c, 0xff, 0x45, 0x8c, 0xc6, 0x00, 0x5c, 0xeb
+.data1 	0x0e, 0xe8, 0xa7, 0xd8, 0xff, 0xff, 0x89, 0x45
+.data1 	0x8c, 0xff, 0x45, 0x8c, 0xc6, 0x00, 0x5c, 0x83
+.data1 	0xbd, 0x50, 0xff, 0xff, 0xff, 0x0a, 0x75, 0x1f
+.data1 	0xff, 0x05, 0xa4, 0x1b, 0x00, 0x00, 0x83, 0x3d
+.data1 	0x54, 0x34, 0x00, 0x00, 0x00, 0x74, 0x10, 0x8b
+.data1 	0x15, 0x8c, 0x34, 0x00, 0x00, 0x83, 0xc2, 0x04
+.data1 	0x52, 0xe8, 0x43, 0x02, 0x00, 0x00, 0x59, 0x8b
+.data1 	0x15, 0x84, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0x84, 0x2c, 0x00, 0x00, 0x78, 0x16, 0x8b, 0x85
+.data1 	0x50, 0xff, 0xff, 0xff, 0x0f, 0xbe, 0xc0, 0x8b
+.data1 	0x5d, 0x8c, 0xff, 0x45, 0x8c, 0x88, 0x03, 0xe9
+.data1 	0x31, 0xff, 0xff, 0xff, 0xe8, 0x4c, 0xd8, 0xff
+.data1 	0xff, 0x89, 0x45, 0x8c, 0x8b, 0x85, 0x50, 0xff
+.data1 	0xff, 0xff, 0x0f, 0xbe, 0xc0, 0x8b, 0x5d, 0x8c
+.data1 	0xff, 0x45, 0x8c, 0x88, 0x03, 0xe9, 0x13, 0xff
+.data1 	0xff, 0xff, 0x8b, 0x15, 0x84, 0x2c, 0x00, 0x00
+.data1 	0x4a, 0x89, 0x15, 0x84, 0x2c, 0x00, 0x00, 0x78
+.data1 	0x0b, 0x8b, 0x45, 0x8c, 0xff, 0x45, 0x8c, 0xc6
+.data1 	0x00, 0x00, 0xeb, 0x0e, 0xe8, 0x14, 0xd8, 0xff
+.data1 	0xff, 0x89, 0x45, 0x8c, 0xff, 0x45, 0x8c, 0xc6
+.data1 	0x00, 0x00, 0x8b, 0x55, 0x8c, 0x2b, 0x15, 0xa8
+.data1 	0x1c, 0x00, 0x00, 0x89, 0x95, 0x4c, 0xff, 0xff
+.data1 	0xff, 0x85, 0xd2, 0x7e, 0x2c, 0xff, 0xb5, 0x4c
+.data1 	0xff, 0xff, 0xff, 0xe8, 0xf8, 0xd4, 0xff, 0xff
+.data1 	0x59, 0x89, 0x85, 0x48, 0xff, 0xff, 0xff, 0xff
+.data1 	0xb5, 0x4c, 0xff, 0xff, 0xff, 0xff, 0xb5, 0x48
+.data1 	0xff, 0xff, 0xff, 0xff, 0x35, 0xa8, 0x1c, 0x00
+.data1 	0x00, 0xe8, 0x22, 0xdc, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0x6a, 0x01, 0xff, 0xb5, 0x48, 0xff, 0xff
+.data1 	0xff, 0xe8, 0xee, 0xbb, 0xff, 0xff, 0x59, 0x59
+.data1 	0x8b, 0x15, 0x54, 0x34, 0x00, 0x00, 0x89, 0x95
+.data1 	0x74, 0xff, 0xff, 0xff, 0xc7, 0x05, 0x54, 0x34
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x55
+.data1 	0xa0, 0x89, 0x55, 0x80, 0x8b, 0x45, 0x80, 0x83
+.data1 	0x38, 0x00, 0x74, 0x07, 0x8b, 0x10, 0x89, 0x55
+.data1 	0x80, 0xeb, 0xf1, 0x6a, 0x08, 0xe8, 0x08, 0xd5
+.data1 	0xff, 0xff, 0x59, 0x8b, 0x5d, 0x80, 0x89, 0x03
+.data1 	0x8b, 0x45, 0x80, 0x8b, 0x10, 0xc7, 0x02, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x90, 0x89, 0x15
+.data1 	0x50, 0x34, 0x00, 0x00, 0x6a, 0x00, 0xe8, 0xf3
+.data1 	0xe7, 0xff, 0xff, 0x59, 0x89, 0x85, 0x70, 0xff
+.data1 	0xff, 0xff, 0x83, 0x7d, 0x90, 0x00, 0x75, 0x14
+.data1 	0xe8, 0x19, 0xf3, 0xff, 0xff, 0x3d, 0x08, 0x00
+.data1 	0x00, 0x00, 0x74, 0x08, 0x6a, 0x08, 0xe8, 0xab
+.data1 	0x01, 0x00, 0x00, 0x59, 0x8b, 0x45, 0x80, 0x8b
+.data1 	0x10, 0x8b, 0x8d, 0x70, 0xff, 0xff, 0xff, 0x89
+.data1 	0x4a, 0x04, 0x83, 0x7d, 0x90, 0x00, 0x74, 0x11
+.data1 	0xe8, 0x15, 0xbc, 0xff, 0xff, 0x8b, 0x95, 0x74
+.data1 	0xff, 0xff, 0xff, 0x89, 0x15, 0x54, 0x34, 0x00
+.data1 	0x00, 0x8b, 0x95, 0x78, 0xff, 0xff, 0xff, 0x39
+.data1 	0x15, 0xac, 0x1c, 0x00, 0x00, 0x7f, 0x07, 0xe8
+.data1 	0x0b, 0xd6, 0xff, 0xff, 0xeb, 0xeb, 0x8b, 0x15
+.data1 	0xa8, 0x1c, 0x00, 0x00, 0x89, 0x55, 0xf8, 0x8b
+.data1 	0x15, 0xac, 0x1c, 0x00, 0x00, 0x89, 0x15, 0x84
+.data1 	0x2c, 0x00, 0x00, 0xff, 0xb5, 0x6c, 0xff, 0xff
+.data1 	0xff, 0x5a, 0x85, 0xd2, 0x0f, 0x84, 0x70, 0x00
+.data1 	0x00, 0x00, 0xff, 0xb5, 0x78, 0xff, 0xff, 0xff
+.data1 	0xff, 0x75, 0xf8, 0xff, 0xb5, 0x6c, 0xff, 0xff
+.data1 	0xff, 0xe8, 0x2a, 0xdb, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0x8b, 0x95, 0x78, 0xff, 0xff, 0xff, 0x03
+.data1 	0x55, 0xf8, 0x89, 0x55, 0xf8, 0x8b, 0x15, 0x84
+.data1 	0x2c, 0x00, 0x00, 0x2b, 0x95, 0x78, 0xff, 0xff
+.data1 	0xff, 0x89, 0x15, 0x84, 0x2c, 0x00, 0x00, 0xff
+.data1 	0x05, 0x90, 0x2c, 0x00, 0x00, 0xff, 0xb5, 0x6c
+.data1 	0xff, 0xff, 0xff, 0xe8, 0xe6, 0x51, 0x00, 0x00
+.data1 	0x59, 0xc7, 0x85, 0x6c, 0xff, 0xff, 0xff, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x15, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00
+.data1 	0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8, 0xd5, 0x7e
+.data1 	0xff, 0xff, 0x8b, 0x95, 0x7c, 0xff, 0xff, 0xff
+.data1 	0x89, 0x15, 0x50, 0x34, 0x00, 0x00, 0xff, 0xb5
+.data1 	0x54, 0xff, 0xff, 0xff, 0x8f, 0x05, 0x94, 0x2c
+.data1 	0x00, 0x00, 0xff, 0x0d, 0x84, 0x2c, 0x00, 0x00
+.data1 	0xba, 0x84, 0xff, 0xff, 0xff, 0x03, 0x55, 0x98
+.data1 	0x89, 0xd0, 0x0f, 0xbe, 0xc0, 0x8b, 0x5d, 0xf8
+.data1 	0xff, 0x45, 0xf8, 0x88, 0x03, 0x83, 0x7d, 0x90
+.data1 	0x00, 0x0f, 0x84, 0x31, 0xf7, 0xff, 0xff, 0xe9
+.data1 	0x2c, 0xf7, 0xff, 0xff, 0x58, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0x3d, 0x44, 0x34
+.data1 	0x00, 0x00, 0x00, 0x74, 0x0b, 0x8b, 0x55, 0x08
+.data1 	0x89, 0x15, 0xac, 0x1b, 0x00, 0x00, 0xeb, 0x09
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x11, 0x0a, 0x00, 0x00
+.data1 	0x59, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x08, 0x56, 0x8b, 0x75, 0x08, 0x8a, 0x06, 0x46
+.data1 	0x88, 0x45, 0xfb, 0x0f, 0xb6, 0xd0, 0x84, 0xd2
+.data1 	0x74, 0x1f, 0x0f, 0xbe, 0x45, 0xfb, 0x3d, 0x81
+.data1 	0xff, 0xff, 0xff, 0x75, 0x03, 0x46, 0xeb, 0xe5
+.data1 	0x0f, 0xbe, 0x45, 0xfb, 0x80, 0xb8, 0x91, 0x1f
+.data1 	0x00, 0x00, 0x0a, 0x75, 0xd8, 0x31, 0xc0, 0xeb
+.data1 	0x05, 0xb8, 0x01, 0x00, 0x00, 0x00, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b, 0x75, 0x08
+.data1 	0x0f, 0xbe, 0x06, 0xf6, 0x80, 0x9d, 0x22, 0x00
+.data1 	0x00, 0x0e, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x1b
+.data1 	0x46, 0x80, 0x3e, 0x00, 0x74, 0x10, 0x0f, 0xbe
+.data1 	0x06, 0xf6, 0x80, 0x9d, 0x22, 0x00, 0x00, 0x0f
+.data1 	0x75, 0xee, 0x31, 0xc0, 0xeb, 0x05, 0xb8, 0x01
+.data1 	0x00, 0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x40, 0x83, 0x7d, 0x08, 0x00
+.data1 	0x78, 0x2c, 0x8b, 0x55, 0x08, 0x8b, 0x0d, 0x5c
+.data1 	0x34, 0x00, 0x00, 0xff, 0x34, 0x95, 0xa8, 0x1d
+.data1 	0x00, 0x00, 0xff, 0x34, 0x8d, 0xa8, 0x1d, 0x00
+.data1 	0x00, 0x68, 0x70, 0x0b, 0x00, 0x00, 0x6a, 0x40
+.data1 	0x8d, 0x45, 0xc0, 0x50, 0xe8, 0x9d, 0x0b, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x14, 0xeb, 0x20, 0x8b, 0x15
+.data1 	0x5c, 0x34, 0x00, 0x00, 0xff, 0x34, 0x95, 0xa8
+.data1 	0x1d, 0x00, 0x00, 0x68, 0x60, 0x0b, 0x00, 0x00
+.data1 	0x6a, 0x40, 0x8d, 0x45, 0xc0, 0x50, 0xe8, 0x7b
+.data1 	0x0b, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x8d, 0x45
+.data1 	0xc0, 0x50, 0xe8, 0x03, 0x00, 0x00, 0x00, 0x59
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0x3d, 0x9c
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x74, 0x1e, 0xff, 0x35
+.data1 	0x74, 0x34, 0x00, 0x00, 0xff, 0x35, 0x9c, 0x2c
+.data1 	0x00, 0x00, 0x68, 0xa4, 0x0b, 0x00, 0x00, 0x68
+.data1 	0x7c, 0x23, 0x00, 0x00, 0xe8, 0x08, 0x0b, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x10, 0xff, 0x75, 0x08, 0x68
+.data1 	0x90, 0x0b, 0x00, 0x00, 0x68, 0x7c, 0x23, 0x00
+.data1 	0x00, 0xe8, 0xf3, 0x0a, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x6a, 0x00, 0xe8, 0xb0, 0x7d, 0xff, 0xff
+.data1 	0x59, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x1c, 0x56, 0x57, 0xbe, 0x0a, 0x00, 0x00
+.data1 	0x00, 0x4e, 0x78, 0x07, 0xc6, 0x44, 0x35, 0xe6
+.data1 	0x00, 0xeb, 0xf6, 0xba, 0x02, 0x00, 0x00, 0x00
+.data1 	0x23, 0x55, 0x0c, 0x88, 0x55, 0xe7, 0x8b, 0x55
+.data1 	0x0c, 0xf6, 0xc2, 0x01, 0x74, 0x35, 0x6a, 0x18
+.data1 	0xe8, 0xcb, 0xd1, 0xff, 0xff, 0x59, 0x89, 0x45
+.data1 	0xf8, 0x31, 0xf6, 0x83, 0xfe, 0x0a, 0x7d, 0x0f
+.data1 	0x8b, 0x55, 0xf8, 0x83, 0xc2, 0x04, 0x66, 0xc7
+.data1 	0x04, 0x72, 0xfe, 0xff, 0x46, 0xeb, 0xec, 0x8b
+.data1 	0x15, 0x9c, 0x34, 0x00, 0x00, 0x8b, 0x45, 0xf8
+.data1 	0x89, 0x10, 0x8b, 0x55, 0xf8, 0x89, 0x15, 0x9c
+.data1 	0x34, 0x00, 0x00, 0x8b, 0x55, 0x08, 0x89, 0x55
+.data1 	0xfc, 0x83, 0x7d, 0xfc, 0x00, 0x0f, 0x84, 0xb4
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0xfc, 0x8b, 0x7a
+.data1 	0x08, 0x8b, 0x55, 0x0c, 0xf6, 0xc2, 0x01, 0x0f
+.data1 	0x84, 0x75, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xf8
+.data1 	0x83, 0xc2, 0x04, 0x0f, 0xbf, 0x04, 0x7a, 0x3d
+.data1 	0xfe, 0xff, 0xff, 0xff, 0x0f, 0x85, 0x60, 0x00
+.data1 	0x00, 0x00, 0xff, 0x05, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x6a, 0x0a, 0x57, 0xe8, 0xd1, 0x03, 0x00, 0x00
+.data1 	0x59, 0x59, 0x89, 0xc6, 0x3d, 0xfe, 0xff, 0xff
+.data1 	0xff, 0x74, 0x16, 0x89, 0xf0, 0x0f, 0xbf, 0xc0
+.data1 	0x8b, 0x55, 0xf8, 0x83, 0xc2, 0x04, 0x66, 0x89
+.data1 	0x04, 0x7a, 0x57, 0xe8, 0xf0, 0x61, 0x00, 0x00
+.data1 	0x59, 0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x75, 0x10
+.data1 	0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85
+.data1 	0xd2, 0x74, 0x05, 0xe8, 0x67, 0x7c, 0xff, 0xff
+.data1 	0x83, 0xfe, 0xfe, 0x75, 0x14, 0x68, 0xb0, 0x0b
+.data1 	0x00, 0x00, 0xe8, 0xb9, 0x7c, 0xff, 0xff, 0x59
+.data1 	0xeb, 0x07, 0x57, 0xe8, 0xb8, 0x61, 0x00, 0x00
+.data1 	0x59, 0x85, 0xff, 0x75, 0x06, 0xff, 0x05, 0x84
+.data1 	0x1e, 0x00, 0x00, 0x8d, 0x45, 0xe6, 0x50, 0xff
+.data1 	0x75, 0xfc, 0xe8, 0x34, 0x00, 0x00, 0x00, 0x59
+.data1 	0x59, 0x8b, 0x55, 0xfc, 0x8b, 0x52, 0x04, 0x89
+.data1 	0x55, 0xfc, 0xe9, 0x42, 0xff, 0xff, 0xff, 0x80
+.data1 	0x7d, 0xe7, 0x00, 0x74, 0x0a, 0xc7, 0x05, 0xa4
+.data1 	0x23, 0x00, 0x00, 0x90, 0x23, 0x00, 0x00, 0x80
+.data1 	0x7d, 0xe8, 0x00, 0x74, 0x0a, 0xc7, 0x05, 0xa8
+.data1 	0x23, 0x00, 0x00, 0x90, 0x23, 0x00, 0x00, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x0c, 0x56, 0x57, 0x8b, 0x7d, 0x08, 0x8b, 0x57
+.data1 	0x08, 0x89, 0x55, 0xfc, 0xc7, 0x05, 0xa4, 0x2c
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x05
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0x03
+.data1 	0x55, 0xfc, 0xc6, 0x02, 0x00, 0xe9, 0x0e, 0x01
+.data1 	0x00, 0x00, 0x8b, 0x77, 0x10, 0x6a, 0x00, 0x56
+.data1 	0xe8, 0xab, 0x61, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0x45, 0xf4, 0x85, 0xc0, 0x79, 0x1b, 0xff, 0x35
+.data1 	0xf0, 0x27, 0x00, 0x00, 0xe8, 0xc3, 0x51, 0x00
+.data1 	0x00, 0x59, 0x50, 0x56, 0x68, 0x20, 0x0c, 0x00
+.data1 	0x00, 0xe8, 0x0a, 0x7c, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0x8b, 0x55, 0xfc, 0x39, 0x55, 0xf4, 0x0f
+.data1 	0x84, 0xdf, 0x00, 0x00, 0x00, 0xff, 0x75, 0xfc
+.data1 	0xff, 0x75, 0xf4, 0xe8, 0xb9, 0x02, 0x00, 0x00
+.data1 	0x59, 0x59, 0xff, 0x75, 0xf4, 0xe8, 0xee, 0x60
+.data1 	0x00, 0x00, 0x59, 0xe9, 0xc4, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x77, 0x10, 0x68, 0xb6, 0x01, 0x00, 0x00
+.data1 	0x68, 0x41, 0x02, 0x00, 0x00, 0x56, 0xe8, 0x4d
+.data1 	0x61, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0x45
+.data1 	0xf4, 0x85, 0xc0, 0x79, 0xbc, 0xff, 0x35, 0xf0
+.data1 	0x27, 0x00, 0x00, 0xe8, 0x64, 0x51, 0x00, 0x00
+.data1 	0x59, 0x50, 0x56, 0x68, 0x08, 0x0c, 0x00, 0x00
+.data1 	0xe8, 0xab, 0x7b, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0xeb, 0x9f, 0x8b, 0x77, 0x10, 0x68, 0xb6, 0x01
+.data1 	0x00, 0x00, 0x68, 0x41, 0x04, 0x00, 0x00, 0x56
+.data1 	0xe8, 0x13, 0x61, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0x45, 0xf4, 0x85, 0xc0, 0x79, 0x82, 0xff
+.data1 	0x35, 0xf0, 0x27, 0x00, 0x00, 0xe8, 0x2a, 0x51
+.data1 	0x00, 0x00, 0x59, 0x50, 0x56, 0x68, 0xf0, 0x0b
+.data1 	0x00, 0x00, 0xe8, 0x71, 0x7b, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0xe9, 0x62, 0xff, 0xff, 0xff, 0x83
+.data1 	0x7f, 0x0c, 0x00, 0x78, 0x47, 0x8b, 0x55, 0x0c
+.data1 	0x03, 0x57, 0x0c, 0x80, 0x3a, 0x00, 0x74, 0x0b
+.data1 	0x8b, 0x55, 0x0c, 0x03, 0x55, 0xfc, 0xc6, 0x02
+.data1 	0x01, 0xeb, 0x31, 0xff, 0x75, 0xfc, 0xff, 0x77
+.data1 	0x0c, 0xe8, 0x0b, 0x02, 0x00, 0x00, 0x59, 0x59
+.data1 	0xeb, 0x22, 0x57, 0xe8, 0x3f, 0x00, 0x00, 0x00
+.data1 	0x59, 0x89, 0x45, 0xf4, 0xe9, 0x28, 0xff, 0xff
+.data1 	0xff, 0xe8, 0xe2, 0x49, 0x00, 0x00, 0xeb, 0x0c
+.data1 	0xbb, 0xc8, 0x0b, 0x00, 0x00, 0x8b, 0x07, 0xe9
+.data1 	0x44, 0x6e, 0x00, 0x00, 0x8b, 0x15, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00
+.data1 	0x00, 0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8, 0x9c
+.data1 	0x7a, 0xff, 0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x08, 0x56, 0x57, 0x8b
+.data1 	0x75, 0x08, 0x8d, 0x45, 0xf8, 0x50, 0xe8, 0x75
+.data1 	0x60, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x79, 0x0b
+.data1 	0x68, 0x34, 0x0c, 0x00, 0x00, 0xe8, 0xd6, 0x7a
+.data1 	0xff, 0xff, 0x59, 0x83, 0x3e, 0x15, 0x75, 0x2d
+.data1 	0x8b, 0x56, 0x0c, 0xff, 0x72, 0x08, 0xe8, 0xa5
+.data1 	0x61, 0x00, 0x00, 0x59, 0x89, 0xc7, 0x81, 0xff
+.data1 	0x00, 0x10, 0x00, 0x00, 0x7f, 0x17, 0x8b, 0x56
+.data1 	0x0c, 0x57, 0xff, 0x72, 0x08, 0xff, 0x75, 0xfc
+.data1 	0xe8, 0xfd, 0x0c, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xe9, 0x84, 0x00, 0x00, 0x00, 0x6a, 0x02, 0x6a
+.data1 	0x00, 0x6a, 0x00, 0xe8, 0x4f, 0xbe, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x0f, 0x85, 0x6e
+.data1 	0x00, 0x00, 0x00, 0xff, 0x75, 0xf8, 0xe8, 0x8d
+.data1 	0x5f, 0x00, 0x00, 0x59, 0x6a, 0x01, 0x6a, 0x02
+.data1 	0xe8, 0xc3, 0x4f, 0x00, 0x00, 0x59, 0x59, 0x6a
+.data1 	0x01, 0x6a, 0x03, 0xe8, 0xb8, 0x4f, 0x00, 0x00
+.data1 	0x59, 0x59, 0x6a, 0x01, 0x6a, 0x01, 0xe8, 0xad
+.data1 	0x4f, 0x00, 0x00, 0x59, 0x59, 0x6a, 0x01, 0x6a
+.data1 	0x14, 0xe8, 0xa2, 0x4f, 0x00, 0x00, 0x59, 0x59
+.data1 	0x6a, 0x00, 0x6a, 0x0d, 0xe8, 0x97, 0x4f, 0x00
+.data1 	0x00, 0x59, 0x59, 0x83, 0x3e, 0x15, 0x75, 0x14
+.data1 	0x8b, 0x56, 0x0c, 0x57, 0xff, 0x72, 0x08, 0xff
+.data1 	0x75, 0xfc, 0xe8, 0x8b, 0x0c, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xeb, 0x0d, 0xff, 0x75, 0xfc, 0xff
+.data1 	0x76, 0x0c, 0xe8, 0x39, 0x9a, 0xff, 0xff, 0x59
+.data1 	0x59, 0x6a, 0x00, 0xe8, 0x14, 0x5f, 0x00, 0x00
+.data1 	0x59, 0xff, 0x75, 0xfc, 0xe8, 0x1f, 0x5f, 0x00
+.data1 	0x00, 0x59, 0x8b, 0x45, 0xf8, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x35
+.data1 	0x9c, 0x34, 0x00, 0x00, 0x31, 0xff, 0x83, 0xff
+.data1 	0x0a, 0x7d, 0x4b, 0x8d, 0x56, 0x04, 0x0f, 0xbf
+.data1 	0x04, 0x7a, 0x3d, 0xfe, 0xff, 0xff, 0xff, 0x74
+.data1 	0x3a, 0x85, 0xff, 0x75, 0x06, 0xff, 0x0d, 0x84
+.data1 	0x1e, 0x00, 0x00, 0x57, 0xe8, 0xe7, 0x5e, 0x00
+.data1 	0x00, 0x59, 0x8d, 0x56, 0x04, 0x0f, 0xbf, 0x04
+.data1 	0x7a, 0x85, 0xc0, 0x78, 0x1e, 0x8d, 0x56, 0x04
+.data1 	0x0f, 0xbf, 0x04, 0x7a, 0x57, 0x50, 0xe8, 0x8e
+.data1 	0x00, 0x00, 0x00, 0x59, 0x59, 0x8d, 0x56, 0x04
+.data1 	0x0f, 0xbf, 0x04, 0x7a, 0x50, 0xe8, 0xbe, 0x5e
+.data1 	0x00, 0x00, 0x59, 0x47, 0xeb, 0xb0, 0xff, 0x05
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x8b, 0x16, 0x89, 0x15
+.data1 	0x9c, 0x34, 0x00, 0x00, 0x56, 0xe8, 0x24, 0x4c
+.data1 	0x00, 0x00, 0x59, 0x8b, 0x15, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00
+.data1 	0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8, 0x1d, 0x79
+.data1 	0xff, 0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x56, 0x57, 0x8b, 0x35, 0x9c, 0x34, 0x00
+.data1 	0x00, 0x85, 0xf6, 0x74, 0x30, 0x31, 0xff, 0x83
+.data1 	0xff, 0x0a, 0x7d, 0x25, 0x8d, 0x56, 0x04, 0x0f
+.data1 	0xbf, 0x04, 0x7a, 0x85, 0xc0, 0x78, 0x0e, 0x8d
+.data1 	0x56, 0x04, 0x0f, 0xbf, 0x04, 0x7a, 0x50, 0xe8
+.data1 	0x54, 0x5e, 0x00, 0x00, 0x59, 0x8d, 0x56, 0x04
+.data1 	0x66, 0xc7, 0x04, 0x7a, 0xfe, 0xff, 0x47, 0xeb
+.data1 	0xd6, 0x8b, 0x36, 0xeb, 0xcc, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x56, 0xff, 0x75, 0x0c
+.data1 	0x6a, 0x00, 0xff, 0x75, 0x08, 0xe8, 0x4e, 0x5e
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0xc6, 0x85
+.data1 	0xf6, 0x79, 0x10, 0x83, 0x3d, 0xf0, 0x27, 0x00
+.data1 	0x00, 0x18, 0x75, 0x07, 0xb8, 0xfe, 0xff, 0xff
+.data1 	0xff, 0xeb, 0x02, 0x89, 0xf0, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x31, 0xc0, 0x83, 0x3d, 0x84
+.data1 	0x1e, 0x00, 0x00, 0x00, 0x0f, 0x95, 0xc0, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x08, 0x56, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x6c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x04, 0x56, 0x57, 0x83, 0x7d, 0x08, 0x01
+.data1 	0x7f, 0x30, 0x31, 0xf6, 0x83, 0xfe, 0x17, 0x7f
+.data1 	0x22, 0x83, 0x3c, 0xb5, 0xa4, 0x34, 0x00, 0x00
+.data1 	0x00, 0x74, 0x15, 0xff, 0x34, 0xb5, 0xa4, 0x34
+.data1 	0x00, 0x00, 0x56, 0x68, 0x5c, 0x0d, 0x00, 0x00
+.data1 	0xe8, 0xf1, 0x05, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x46, 0xeb, 0xd9, 0x31, 0xc0, 0xe9, 0xba, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x7d, 0x0c, 0x83, 0xc7, 0x04
+.data1 	0xff, 0x37, 0xe8, 0x88, 0xd4, 0xff, 0xff, 0x59
+.data1 	0x85, 0xc0, 0x74, 0x09, 0xc7, 0x45, 0xfc, 0x00
+.data1 	0x00, 0x00, 0x00, 0xeb, 0x08, 0x8b, 0x17, 0x89
+.data1 	0x55, 0xfc, 0x83, 0xc7, 0x04, 0x83, 0x3f, 0x00
+.data1 	0x0f, 0x84, 0x8c, 0x00, 0x00, 0x00, 0xff, 0x37
+.data1 	0xe8, 0x38, 0xd4, 0xff, 0xff, 0x59, 0x89, 0xc6
+.data1 	0x85, 0xc0, 0x78, 0x05, 0x83, 0xfe, 0x17, 0x7e
+.data1 	0x0e, 0xff, 0x37, 0x68, 0x4c, 0x0d, 0x00, 0x00
+.data1 	0xe8, 0x43, 0x78, 0xff, 0xff, 0x59, 0x59, 0xff
+.data1 	0x05, 0x90, 0x2c, 0x00, 0x00, 0x83, 0x7d, 0xfc
+.data1 	0x00, 0x74, 0x0c, 0xff, 0x75, 0xfc, 0xe8, 0xc8
+.data1 	0xcc, 0xff, 0xff, 0x59, 0x89, 0x45, 0xfc, 0x83
+.data1 	0x3c, 0xb5, 0xa4, 0x34, 0x00, 0x00, 0x00, 0x74
+.data1 	0x0d, 0xff, 0x34, 0xb5, 0xa4, 0x34, 0x00, 0x00
+.data1 	0xe8, 0x99, 0x4a, 0x00, 0x00, 0x59, 0x8b, 0x55
+.data1 	0xfc, 0x89, 0x14, 0xb5, 0xa4, 0x34, 0x00, 0x00
+.data1 	0x85, 0xf6, 0x74, 0x07, 0x56, 0xe8, 0xa8, 0x00
+.data1 	0x00, 0x00, 0x59, 0x8b, 0x15, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00
+.data1 	0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8, 0x7d, 0x77
+.data1 	0xff, 0xff, 0x83, 0xc7, 0x04, 0xe9, 0x6b, 0xff
+.data1 	0xff, 0xff, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0xbe, 0xa4, 0x34, 0x00
+.data1 	0x00, 0x81, 0xfe, 0x00, 0x35, 0x00, 0x00, 0x0f
+.data1 	0x87, 0x62, 0x00, 0x00, 0x00, 0x83, 0x3e, 0x00
+.data1 	0x74, 0x58, 0x8b, 0x16, 0x80, 0x3a, 0x00, 0x74
+.data1 	0x51, 0xff, 0x05, 0x90, 0x2c, 0x00, 0x00, 0xff
+.data1 	0x36, 0xe8, 0x28, 0x4a, 0x00, 0x00, 0x59, 0xc7
+.data1 	0x06, 0x00, 0x00, 0x00, 0x00, 0x81, 0xfe, 0xa4
+.data1 	0x34, 0x00, 0x00, 0x74, 0x16, 0x89, 0xf0, 0x2d
+.data1 	0xa4, 0x34, 0x00, 0x00, 0xb9, 0x04, 0x00, 0x00
+.data1 	0x00, 0x99, 0xf7, 0xf9, 0x50, 0xe8, 0x28, 0x00
+.data1 	0x00, 0x00, 0x59, 0x8b, 0x15, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x75, 0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00
+.data1 	0x5a, 0x85, 0xd2, 0x74, 0x05, 0xe8, 0xfd, 0x76
+.data1 	0xff, 0xff, 0x83, 0xc6, 0x04, 0xeb, 0x92, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08
+.data1 	0x56, 0x57, 0x8b, 0x55, 0x08, 0x8b, 0x14, 0x95
+.data1 	0xa4, 0x34, 0x00, 0x00, 0x89, 0xd6, 0x85, 0xd2
+.data1 	0x75, 0x07, 0xbf, 0x01, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x11, 0x80, 0x3e, 0x00, 0x74, 0x07, 0xbf, 0x02
+.data1 	0x00, 0x00, 0x00, 0xeb, 0x05, 0xbf, 0x03, 0x00
+.data1 	0x00, 0x00, 0x83, 0x3d, 0xa0, 0x2c, 0x00, 0x00
+.data1 	0x00, 0x74, 0x34, 0x83, 0xff, 0x01, 0x75, 0x2f
+.data1 	0xeb, 0x20, 0x80, 0x3d, 0x77, 0x2c, 0x00, 0x00
+.data1 	0x00, 0x74, 0x24, 0xbf, 0x02, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x1d, 0x80, 0x3d, 0x77, 0x2c, 0x00, 0x00
+.data1 	0x00, 0x74, 0x14, 0xbf, 0x03, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x0d, 0xbb, 0x64, 0x0d, 0x00, 0x00, 0x8b
+.data1 	0x45, 0x08, 0xe9, 0x3d, 0x6a, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x08, 0x4a, 0x89, 0xd6, 0x81, 0xc6, 0x04
+.data1 	0x35, 0x00, 0x00, 0x80, 0x3e, 0x00, 0x75, 0x2f
+.data1 	0x6a, 0x01, 0xff, 0x75, 0x08, 0xe8, 0x16, 0x4c
+.data1 	0x00, 0x00, 0x59, 0x59, 0x89, 0x45, 0xf8, 0x3d
+.data1 	0xff, 0xff, 0xff, 0xff, 0x75, 0x0b, 0x68, 0x9c
+.data1 	0x0d, 0x00, 0x00, 0xe8, 0xb8, 0x76, 0xff, 0xff
+.data1 	0x59, 0x83, 0x7d, 0xf8, 0x01, 0x75, 0x05, 0xc6
+.data1 	0x06, 0x04, 0xeb, 0x03, 0xc6, 0x06, 0x03, 0x80
+.data1 	0x3e, 0x04, 0x74, 0x07, 0x0f, 0xbe, 0x06, 0x39
+.data1 	0xf8, 0x75, 0x1f, 0x31, 0xc0, 0xeb, 0x38, 0xc7
+.data1 	0x45, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x1e
+.data1 	0xc7, 0x45, 0xf8, 0xef, 0x8f, 0x00, 0x00, 0xeb
+.data1 	0x15, 0xc7, 0x45, 0xf8, 0x01, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x0c, 0xbb, 0x84, 0x0d, 0x00, 0x00, 0x89
+.data1 	0xf8, 0xe9, 0x9a, 0x69, 0x00, 0x00, 0x89, 0xfa
+.data1 	0x88, 0x16, 0xff, 0x75, 0xf8, 0xff, 0x75, 0x08
+.data1 	0xe8, 0xab, 0x4b, 0x00, 0x00, 0x59, 0x59, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b
+.data1 	0x75, 0x08, 0x89, 0xf2, 0x4a, 0x89, 0xd0, 0x80
+.data1 	0xb8, 0x04, 0x35, 0x00, 0x00, 0x03, 0x74, 0x18
+.data1 	0x89, 0xf2, 0x4a, 0x89, 0xd0, 0x80, 0xb8, 0x04
+.data1 	0x35, 0x00, 0x00, 0x04, 0x74, 0x0a, 0x6a, 0x01
+.data1 	0x56, 0xe8, 0x7a, 0x4b, 0x00, 0x00, 0x59, 0x59
+.data1 	0x89, 0xf2, 0x4a, 0x89, 0xd0, 0xc6, 0x80, 0x04
+.data1 	0x35, 0x00, 0x00, 0x04, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x68, 0xef, 0x8f, 0x00, 0x00, 0xff
+.data1 	0x75, 0x08, 0xe8, 0x59, 0x4b, 0x00, 0x00, 0x59
+.data1 	0x59, 0x83, 0x7d, 0x08, 0x02, 0x75, 0x10, 0x83
+.data1 	0x3d, 0xac, 0x34, 0x00, 0x00, 0x00, 0x75, 0x07
+.data1 	0xe8, 0x9a, 0x75, 0xff, 0xff, 0xeb, 0x13, 0x8b
+.data1 	0x55, 0x08, 0x4a, 0x89, 0xd0, 0xc6, 0x80, 0x1c
+.data1 	0x35, 0x00, 0x00, 0x01, 0xff, 0x05, 0xc0, 0x2c
+.data1 	0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x08, 0x56, 0xbe, 0x01, 0x00, 0x00, 0x00
+.data1 	0x89, 0xf2, 0x4a, 0x89, 0xd0, 0x80, 0xb8, 0x1c
+.data1 	0x35, 0x00, 0x00, 0x00, 0x75, 0x08, 0x83, 0xfe
+.data1 	0x17, 0x7d, 0x30, 0x46, 0xeb, 0xea, 0x89, 0xf2
+.data1 	0x4a, 0x89, 0xd0, 0xc6, 0x80, 0x1c, 0x35, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x15, 0xa4, 0x2c, 0x00, 0x00
+.data1 	0x89, 0x55, 0xf8, 0xff, 0x34, 0xb5, 0xa4, 0x34
+.data1 	0x00, 0x00, 0xe8, 0x23, 0x77, 0xff, 0xff, 0x59
+.data1 	0x8b, 0x55, 0xf8, 0x89, 0x15, 0xa4, 0x2c, 0x00
+.data1 	0x00, 0xeb, 0xb8, 0xc7, 0x05, 0xc0, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x15, 0x34, 0x35, 0x00
+.data1 	0x00, 0x39, 0x55, 0x08, 0x74, 0x21, 0x6a, 0x02
+.data1 	0xe8, 0x1d, 0xfe, 0xff, 0xff, 0x59, 0x6a, 0x03
+.data1 	0xe8, 0x15, 0xfe, 0xff, 0xff, 0x59, 0x6a, 0x0f
+.data1 	0xe8, 0x0d, 0xfe, 0xff, 0xff, 0x59, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x15, 0x34, 0x35, 0x00, 0x00, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x2c, 0x56
+.data1 	0x57, 0xff, 0x35, 0xb8, 0x0d, 0x00, 0x00, 0x6a
+.data1 	0x01, 0x8d, 0x45, 0xec, 0x50, 0xe8, 0x7e, 0x5c
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x75
+.data1 	0x46, 0xff, 0x35, 0xbc, 0x0d, 0x00, 0x00, 0x6a
+.data1 	0x01, 0x8d, 0x45, 0xd8, 0x50, 0xe8, 0x66, 0x5c
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x75
+.data1 	0x3c, 0x8d, 0x55, 0xec, 0x89, 0x15, 0x94, 0x2c
+.data1 	0x00, 0x00, 0x8b, 0x15, 0xa4, 0x34, 0x00, 0x00
+.data1 	0x89, 0x55, 0xd4, 0x85, 0xd2, 0x74, 0x18, 0x80
+.data1 	0x3a, 0x00, 0x74, 0x13, 0xc7, 0x05, 0xa4, 0x34
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x75
+.data1 	0xd4, 0xe8, 0x74, 0x76, 0xff, 0xff, 0x59, 0x8d
+.data1 	0x55, 0xd8, 0x89, 0x15, 0x94, 0x2c, 0x00, 0x00
+.data1 	0xe8, 0x5a, 0x01, 0x00, 0x00, 0xff, 0x75, 0x08
+.data1 	0xe8, 0xcf, 0x59, 0x00, 0x00, 0x59, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0xff
+.data1 	0x35, 0xa4, 0x23, 0x00, 0x00, 0xff, 0x75, 0x08
+.data1 	0xe8, 0x19, 0x00, 0x00, 0x00, 0x59, 0x59, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0xff, 0x35, 0xa8, 0x23
+.data1 	0x00, 0x00, 0xff, 0x75, 0x08, 0xe8, 0x04, 0x00
+.data1 	0x00, 0x00, 0x59, 0x59, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x56, 0x57, 0x8b, 0x75, 0x0c, 0x8b, 0x7d
+.data1 	0x08, 0x80, 0x3f, 0x00, 0x74, 0x22, 0xff, 0x4e
+.data1 	0x04, 0x79, 0x12, 0x56, 0xe8, 0x1b, 0x00, 0x00
+.data1 	0x00, 0x59, 0x8a, 0x07, 0x47, 0x8b, 0x1e, 0xff
+.data1 	0x06, 0x88, 0x03, 0xeb, 0xe4, 0x8a, 0x07, 0x47
+.data1 	0x8b, 0x1e, 0xff, 0x06, 0x88, 0x03, 0xeb, 0xd9
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x08, 0x0f, 0xbf, 0x46, 0x10
+.data1 	0x3d, 0xfe, 0xff, 0xff, 0xff, 0x75, 0x22, 0xc7
+.data1 	0x06, 0x38, 0x35, 0x00, 0x00, 0xc7, 0x46, 0x04
+.data1 	0x10, 0x00, 0x00, 0x00, 0x0f, 0xbf, 0x46, 0x12
+.data1 	0x0d, 0x01, 0x00, 0x00, 0x00, 0x0f, 0xbf, 0xc0
+.data1 	0x66, 0x89, 0x46, 0x12, 0xe9, 0xaf, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7e, 0x08, 0x00, 0x75, 0x46, 0xff
+.data1 	0x05, 0x90, 0x2c, 0x00, 0x00, 0xff, 0x76, 0x0c
+.data1 	0xe8, 0x7b, 0xc8, 0xff, 0xff, 0x59, 0x89, 0x46
+.data1 	0x08, 0x89, 0x06, 0x8b, 0x56, 0x0c, 0x89, 0x56
+.data1 	0x04, 0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a
+.data1 	0x89, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x0f, 0x85
+.data1 	0x7c, 0x00, 0x00, 0x00, 0xff, 0x35, 0x8c, 0x2c
+.data1 	0x00, 0x00, 0x5a, 0x85, 0xd2, 0x0f, 0x84, 0x6d
+.data1 	0x00, 0x00, 0x00, 0xe8, 0x97, 0x73, 0xff, 0xff
+.data1 	0xe9, 0x63, 0x00, 0x00, 0x00, 0x0f, 0xbf, 0x46
+.data1 	0x10, 0x3d, 0xfd, 0xff, 0xff, 0xff, 0x75, 0x51
+.data1 	0x8b, 0x7e, 0x0c, 0xff, 0x05, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x8b, 0x56, 0x0c, 0xd1, 0xe2, 0x89, 0x56
+.data1 	0x0c, 0xff, 0x76, 0x0c, 0xff, 0x76, 0x08, 0xe8
+.data1 	0x3f, 0xc8, 0xff, 0xff, 0x59, 0x59, 0x89, 0x46
+.data1 	0x08, 0x8b, 0x56, 0x0c, 0x29, 0xfa, 0x89, 0x56
+.data1 	0x04, 0x89, 0xfa, 0x03, 0x56, 0x08, 0x89, 0x16
+.data1 	0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89
+.data1 	0x15, 0x90, 0x2c, 0x00, 0x00, 0x75, 0x19, 0xff
+.data1 	0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2
+.data1 	0x74, 0x0e, 0xe8, 0x38, 0x73, 0xff, 0xff, 0xeb
+.data1 	0x07, 0x56, 0xe8, 0x23, 0x00, 0x00, 0x00, 0x59
+.data1 	0xff, 0x4e, 0x04, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x68, 0x68, 0x23, 0x00, 0x00, 0xe8
+.data1 	0x0e, 0x00, 0x00, 0x00, 0x59, 0x68, 0x7c, 0x23
+.data1 	0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x00, 0x59
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b, 0x75
+.data1 	0x08, 0x83, 0x7e, 0x08, 0x00, 0x74, 0x44, 0x8b
+.data1 	0x56, 0x08, 0x39, 0x16, 0x74, 0x3d, 0x0f, 0xbf
+.data1 	0x46, 0x10, 0x85, 0xc0, 0x78, 0x35, 0x8b, 0x16
+.data1 	0x2b, 0x56, 0x08, 0x0f, 0xbf, 0x46, 0x10, 0x52
+.data1 	0xff, 0x76, 0x08, 0x50, 0xe8, 0x91, 0x05, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x79, 0x10
+.data1 	0x0f, 0xbf, 0x46, 0x12, 0x0d, 0x01, 0x00, 0x00
+.data1 	0x00, 0x0f, 0xbf, 0xc0, 0x66, 0x89, 0x46, 0x12
+.data1 	0x8b, 0x56, 0x08, 0x89, 0x16, 0x8b, 0x56, 0x0c
+.data1 	0x89, 0x56, 0x04, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0xff, 0x05, 0x90, 0x2c, 0x00, 0x00, 0x83
+.data1 	0x3d, 0x70, 0x23, 0x00, 0x00, 0x00, 0x74, 0x20
+.data1 	0xff, 0x35, 0x70, 0x23, 0x00, 0x00, 0xe8, 0x83
+.data1 	0x45, 0x00, 0x00, 0x59, 0xc7, 0x05, 0x70, 0x23
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x05
+.data1 	0x6c, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89
+.data1 	0x15, 0x90, 0x2c, 0x00, 0x00, 0x75, 0x10, 0xff
+.data1 	0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2
+.data1 	0x74, 0x05, 0xe8, 0x68, 0x72, 0xff, 0xff, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x8d
+.data1 	0x55, 0x10, 0x89, 0x55, 0xfc, 0x52, 0xff, 0x75
+.data1 	0x0c, 0xff, 0x75, 0x08, 0xe8, 0x93, 0x00, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x04, 0x8d, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xfc, 0x52, 0xff, 0x75, 0x08, 0xff, 0x35
+.data1 	0xa4, 0x23, 0x00, 0x00, 0xe8, 0x73, 0x00, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x18, 0x8d, 0x55, 0x14, 0x89
+.data1 	0x55, 0xfc, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe8
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x55, 0xec, 0x66, 0xc7
+.data1 	0x45, 0xf8, 0xfe, 0xff, 0x66, 0xc7, 0x45, 0xfa
+.data1 	0x00, 0x00, 0xff, 0x75, 0xfc, 0xff, 0x75, 0x10
+.data1 	0x8d, 0x45, 0xe8, 0x50, 0xe8, 0x3b, 0x00, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xff, 0x4d, 0xec, 0x79
+.data1 	0x15, 0x8d, 0x45, 0xe8, 0x50, 0xe8, 0xd2, 0xfd
+.data1 	0xff, 0xff, 0x59, 0x8b, 0x45, 0xe8, 0xff, 0x45
+.data1 	0xe8, 0xc6, 0x00, 0x00, 0xeb, 0x09, 0x8b, 0x45
+.data1 	0xe8, 0xff, 0x45, 0xe8, 0xc6, 0x00, 0x00, 0x0f
+.data1 	0xb7, 0x55, 0xfa, 0xf6, 0xc2, 0x01, 0x74, 0x0a
+.data1 	0x8b, 0x55, 0x0c, 0x4a, 0x03, 0x55, 0x08, 0xc6
+.data1 	0x02, 0x00, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x50, 0x56, 0x57, 0x8b, 0x75, 0x08, 0x8b
+.data1 	0x7d, 0x0c, 0x8a, 0x07, 0x47, 0x88, 0x45, 0xff
+.data1 	0x0f, 0xb6, 0xd0, 0x84, 0xd2, 0x0f, 0x84, 0x4b
+.data1 	0x04, 0x00, 0x00, 0x80, 0x7d, 0xff, 0x25, 0x74
+.data1 	0x28, 0xff, 0x4e, 0x04, 0x79, 0x15, 0x56, 0xe8
+.data1 	0x78, 0xfd, 0xff, 0xff, 0x59, 0x8b, 0x06, 0x0f
+.data1 	0xb6, 0x5d, 0xff, 0x53, 0xff, 0x06, 0x5a, 0x88
+.data1 	0x10, 0xeb, 0xcf, 0x8b, 0x06, 0x0f, 0xb6, 0x5d
+.data1 	0xff, 0x53, 0xff, 0x06, 0x5a, 0x88, 0x10, 0xeb
+.data1 	0xc1, 0xc7, 0x45, 0xe0, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xd8, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x45
+.data1 	0xd4, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x45, 0xd0
+.data1 	0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x2d, 0x75
+.data1 	0x05, 0xff, 0x45, 0xe0, 0xeb, 0x08, 0x80, 0x3f
+.data1 	0x23, 0x75, 0x06, 0xff, 0x45, 0xdc, 0x47, 0xeb
+.data1 	0xeb, 0x80, 0x3f, 0x2a, 0x75, 0x12, 0x8b, 0x55
+.data1 	0x10, 0x83, 0xc2, 0x04, 0x89, 0x55, 0x10, 0x8b
+.data1 	0x52, 0xfc, 0x89, 0x55, 0xd8, 0x47, 0xeb, 0x23
+.data1 	0x0f, 0xbe, 0x07, 0x2d, 0x30, 0x00, 0x00, 0x00
+.data1 	0x3d, 0x09, 0x00, 0x00, 0x00, 0x77, 0x14, 0x0f
+.data1 	0xbe, 0x07, 0x47, 0x2d, 0x30, 0x00, 0x00, 0x00
+.data1 	0x6b, 0x5d, 0xd8, 0x0a, 0x01, 0xc3, 0x89, 0x5d
+.data1 	0xd8, 0xeb, 0xdd, 0x80, 0x3f, 0x2e, 0x75, 0x42
+.data1 	0x47, 0x80, 0x3f, 0x2a, 0x75, 0x12, 0x8b, 0x55
+.data1 	0x10, 0x83, 0xc2, 0x04, 0x89, 0x55, 0x10, 0x8b
+.data1 	0x52, 0xfc, 0x89, 0x55, 0xd4, 0x47, 0xeb, 0x2a
+.data1 	0xc7, 0x45, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x0f
+.data1 	0xbe, 0x07, 0x2d, 0x30, 0x00, 0x00, 0x00, 0x3d
+.data1 	0x09, 0x00, 0x00, 0x00, 0x77, 0x14, 0x0f, 0xbe
+.data1 	0x07, 0x47, 0x2d, 0x30, 0x00, 0x00, 0x00, 0x6b
+.data1 	0x5d, 0xd4, 0x0a, 0x01, 0xc3, 0x89, 0x5d, 0xd4
+.data1 	0xeb, 0xdd, 0x80, 0x3f, 0x6c, 0x0f, 0x85, 0x48
+.data1 	0x03, 0x00, 0x00, 0xff, 0x45, 0xd0, 0x47, 0xe9
+.data1 	0x3f, 0x03, 0x00, 0x00, 0x83, 0x7d, 0xd0, 0x00
+.data1 	0x74, 0x11, 0x8b, 0x55, 0x10, 0x83, 0xc2, 0x04
+.data1 	0x89, 0x55, 0x10, 0x8b, 0x52, 0xfc, 0x89, 0x55
+.data1 	0xc4, 0xeb, 0x0f, 0x8b, 0x55, 0x10, 0x83, 0xc2
+.data1 	0x04, 0x89, 0x55, 0x10, 0x8b, 0x52, 0xfc, 0x89
+.data1 	0x55, 0xc4, 0xc7, 0x45, 0xc8, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xc4, 0x89, 0x55, 0xc0, 0x83
+.data1 	0x7d, 0xc4, 0x00, 0x79, 0x0f, 0x8b, 0x55, 0xc4
+.data1 	0xf7, 0xda, 0x89, 0x55, 0xc0, 0xc7, 0x45, 0xc8
+.data1 	0x01, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xbc, 0x0a
+.data1 	0x00, 0x00, 0x00, 0xe9, 0x46, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xbc, 0x0a, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x10, 0xc7, 0x45, 0xbc, 0x08, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x07, 0xc7, 0x45, 0xbc, 0x10, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xc8, 0x00, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0xd0, 0x00, 0x74, 0x11, 0x8b, 0x55
+.data1 	0x10, 0x83, 0xc2, 0x04, 0x89, 0x55, 0x10, 0x8b
+.data1 	0x52, 0xfc, 0x89, 0x55, 0xc0, 0xeb, 0x0f, 0x8b
+.data1 	0x55, 0x10, 0x83, 0xc2, 0x04, 0x89, 0x55, 0x10
+.data1 	0x8b, 0x52, 0xfc, 0x89, 0x55, 0xc0, 0x8d, 0x55
+.data1 	0xfe, 0x89, 0x55, 0xcc, 0xc6, 0x02, 0x00, 0x83
+.data1 	0x7d, 0xc0, 0x00, 0x74, 0x28, 0x8b, 0x45, 0xc0
+.data1 	0x31, 0xd2, 0xf7, 0x75, 0xbc, 0x89, 0xd0, 0x0f
+.data1 	0xb6, 0x98, 0xac, 0x23, 0x00, 0x00, 0x53, 0xff
+.data1 	0x4d, 0xcc, 0x8b, 0x55, 0xcc, 0x59, 0x88, 0x0a
+.data1 	0x8b, 0x45, 0xc0, 0x31, 0xd2, 0xf7, 0x75, 0xbc
+.data1 	0x89, 0x45, 0xc0, 0xeb, 0xd2, 0x8d, 0x55, 0xfe
+.data1 	0x2b, 0x55, 0xcc, 0x89, 0x55, 0xb8, 0x83, 0x7d
+.data1 	0xd4, 0x00, 0x79, 0x07, 0xc7, 0x45, 0xd4, 0x01
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xdc, 0x00, 0x74
+.data1 	0x11, 0x80, 0x3f, 0x6f, 0x75, 0x0c, 0x8b, 0x55
+.data1 	0xb8, 0x39, 0x55, 0xd4, 0x7f, 0x04, 0x42, 0x89
+.data1 	0x55, 0xd4, 0xc7, 0x45, 0xb0, 0x00, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7d, 0xd8, 0x00, 0x0f, 0x84, 0x49
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0xb8, 0x89, 0x55
+.data1 	0xb4, 0x39, 0x55, 0xd4, 0x7e, 0x06, 0x8b, 0x55
+.data1 	0xd4, 0x89, 0x55, 0xb4, 0x8b, 0x55, 0xc8, 0x01
+.data1 	0x55, 0xb4, 0x8b, 0x55, 0xd8, 0x2b, 0x55, 0xb4
+.data1 	0x89, 0x55, 0xb0, 0x83, 0x7d, 0xe0, 0x00, 0x75
+.data1 	0x23, 0xff, 0x4d, 0xb0, 0x78, 0x1e, 0xff, 0x4e
+.data1 	0x04, 0x79, 0x10, 0x56, 0xe8, 0x4b, 0xfb, 0xff
+.data1 	0xff, 0x59, 0x8b, 0x06, 0xff, 0x06, 0xc6, 0x00
+.data1 	0x20, 0xeb, 0xe6, 0x8b, 0x06, 0xff, 0x06, 0xc6
+.data1 	0x00, 0x20, 0xeb, 0xdd, 0x83, 0x7d, 0xc8, 0x00
+.data1 	0x74, 0x1c, 0xff, 0x4e, 0x04, 0x79, 0x10, 0x56
+.data1 	0xe8, 0x27, 0xfb, 0xff, 0xff, 0x59, 0x8b, 0x06
+.data1 	0xff, 0x06, 0xc6, 0x00, 0x2d, 0xeb, 0x07, 0x8b
+.data1 	0x06, 0xff, 0x06, 0xc6, 0x00, 0x2d, 0x8b, 0x55
+.data1 	0xd4, 0x2b, 0x55, 0xb8, 0x89, 0x55, 0xd4, 0xff
+.data1 	0x4d, 0xd4, 0x78, 0x1e, 0xff, 0x4e, 0x04, 0x79
+.data1 	0x10, 0x56, 0xe8, 0xfd, 0xfa, 0xff, 0xff, 0x59
+.data1 	0x8b, 0x06, 0xff, 0x06, 0xc6, 0x00, 0x30, 0xeb
+.data1 	0xe6, 0x8b, 0x06, 0xff, 0x06, 0xc6, 0x00, 0x30
+.data1 	0xeb, 0xdd, 0x8b, 0x55, 0xcc, 0x80, 0x3a, 0x00
+.data1 	0x74, 0x32, 0xff, 0x4e, 0x04, 0x79, 0x1a, 0x56
+.data1 	0xe8, 0xd7, 0xfa, 0xff, 0xff, 0x59, 0x8b, 0x45
+.data1 	0xcc, 0xff, 0x45, 0xcc, 0x8b, 0x1e, 0x0f, 0xb6
+.data1 	0x08, 0x51, 0xff, 0x06, 0x5a, 0x88, 0x13, 0xeb
+.data1 	0xd9, 0x8b, 0x45, 0xcc, 0xff, 0x45, 0xcc, 0x8b
+.data1 	0x1e, 0x0f, 0xb6, 0x08, 0x51, 0xff, 0x06, 0x5a
+.data1 	0x88, 0x13, 0xeb, 0xc6, 0xff, 0x4d, 0xb0, 0x0f
+.data1 	0x88, 0x63, 0x01, 0x00, 0x00, 0xff, 0x4e, 0x04
+.data1 	0x79, 0x10, 0x56, 0xe8, 0x9c, 0xfa, 0xff, 0xff
+.data1 	0x59, 0x8b, 0x06, 0xff, 0x06, 0xc6, 0x00, 0x20
+.data1 	0xeb, 0xe2, 0x8b, 0x06, 0xff, 0x06, 0xc6, 0x00
+.data1 	0x20, 0xeb, 0xd9, 0x8b, 0x55, 0x10, 0x83, 0xc2
+.data1 	0x04, 0x89, 0x55, 0x10, 0x8b, 0x52, 0xfc, 0x89
+.data1 	0x55, 0xcc, 0xc7, 0x45, 0xb0, 0x00, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7d, 0xd8, 0x00, 0x0f, 0x84, 0x4f
+.data1 	0x00, 0x00, 0x00, 0xff, 0x75, 0xcc, 0xe8, 0xb5
+.data1 	0x55, 0x00, 0x00, 0x59, 0x89, 0x45, 0xb8, 0x83
+.data1 	0x7d, 0xd4, 0x00, 0x78, 0x0b, 0x39, 0x45, 0xd4
+.data1 	0x7d, 0x06, 0x8b, 0x55, 0xd4, 0x89, 0x55, 0xb8
+.data1 	0x8b, 0x55, 0xd8, 0x2b, 0x55, 0xb8, 0x89, 0x55
+.data1 	0xb0, 0x83, 0x7d, 0xe0, 0x00, 0x75, 0x23, 0xff
+.data1 	0x4d, 0xb0, 0x78, 0x1e, 0xff, 0x4e, 0x04, 0x79
+.data1 	0x10, 0x56, 0xe8, 0x2d, 0xfa, 0xff, 0xff, 0x59
+.data1 	0x8b, 0x06, 0xff, 0x06, 0xc6, 0x00, 0x20, 0xeb
+.data1 	0xe6, 0x8b, 0x06, 0xff, 0x06, 0xc6, 0x00, 0x20
+.data1 	0xeb, 0xdd, 0xff, 0x45, 0xd4, 0xff, 0x4d, 0xd4
+.data1 	0x74, 0x3a, 0x8b, 0x55, 0xcc, 0x80, 0x3a, 0x00
+.data1 	0x74, 0x32, 0xff, 0x4e, 0x04, 0x79, 0x1a, 0x56
+.data1 	0xe8, 0xff, 0xf9, 0xff, 0xff, 0x59, 0x8b, 0x45
+.data1 	0xcc, 0xff, 0x45, 0xcc, 0x8b, 0x1e, 0x0f, 0xb6
+.data1 	0x08, 0x51, 0xff, 0x06, 0x5a, 0x88, 0x13, 0xeb
+.data1 	0xd4, 0x8b, 0x45, 0xcc, 0xff, 0x45, 0xcc, 0x8b
+.data1 	0x1e, 0x0f, 0xb6, 0x08, 0x51, 0xff, 0x06, 0x5a
+.data1 	0x88, 0x13, 0xeb, 0xc1, 0xff, 0x4d, 0xb0, 0x0f
+.data1 	0x88, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x4e, 0x04
+.data1 	0x79, 0x10, 0x56, 0xe8, 0xc4, 0xf9, 0xff, 0xff
+.data1 	0x59, 0x8b, 0x06, 0xff, 0x06, 0xc6, 0x00, 0x20
+.data1 	0xeb, 0xe2, 0x8b, 0x06, 0xff, 0x06, 0xc6, 0x00
+.data1 	0x20, 0xeb, 0xd9, 0x8b, 0x55, 0x10, 0x83, 0xc2
+.data1 	0x04, 0x89, 0x55, 0x10, 0x8b, 0x52, 0xfc, 0x88
+.data1 	0x55, 0xff, 0xff, 0x4e, 0x04, 0x79, 0x18, 0x56
+.data1 	0xe8, 0x97, 0xf9, 0xff, 0xff, 0x59, 0x8b, 0x06
+.data1 	0x0f, 0xb6, 0x5d, 0xff, 0x53, 0xff, 0x06, 0x5a
+.data1 	0x88, 0x10, 0xe9, 0x41, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x06, 0x0f, 0xb6, 0x5d, 0xff, 0x53, 0xff, 0x06
+.data1 	0x5a, 0x88, 0x10, 0xeb, 0x33, 0xff, 0x4e, 0x04
+.data1 	0x79, 0x14, 0x56, 0xe8, 0x6c, 0xf9, 0xff, 0xff
+.data1 	0x59, 0x8b, 0x06, 0x0f, 0xb6, 0x1f, 0x53, 0xff
+.data1 	0x06, 0x5a, 0x88, 0x10, 0xeb, 0x1a, 0x8b, 0x06
+.data1 	0x0f, 0xb6, 0x1f, 0x53, 0xff, 0x06, 0x5a, 0x88
+.data1 	0x10, 0xeb, 0x0d, 0x0f, 0xbe, 0x07, 0xbb, 0xc0
+.data1 	0x0d, 0x00, 0x00, 0xe9, 0x0c, 0x61, 0x00, 0x00
+.data1 	0x47, 0xe9, 0xa4, 0xfb, 0xff, 0xff, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x04
+.data1 	0x56, 0x57, 0x8b, 0x75, 0x10, 0xc7, 0x45, 0xfc
+.data1 	0x00, 0x00, 0x00, 0x00, 0x56, 0xff, 0x75, 0x0c
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x60, 0x53, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0xc7, 0x85, 0xff, 0x7e
+.data1 	0x20, 0x89, 0xf2, 0x29, 0xfa, 0x89, 0xd6, 0x85
+.data1 	0xf6, 0x7f, 0x05, 0x8b, 0x45, 0x10, 0xeb, 0x35
+.data1 	0x89, 0xfa, 0x03, 0x55, 0x0c, 0x89, 0x55, 0x0c
+.data1 	0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xeb
+.data1 	0xcb, 0x85, 0xff, 0x75, 0x12, 0xff, 0x45, 0xfc
+.data1 	0x83, 0x7d, 0xfc, 0x0a, 0x7e, 0xbe, 0x8b, 0x55
+.data1 	0x10, 0x29, 0xf2, 0x89, 0xd0, 0xeb, 0x0e, 0x83
+.data1 	0x3d, 0xf0, 0x27, 0x00, 0x00, 0x04, 0x74, 0xac
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0xff
+.data1 	0x75, 0x10, 0xff, 0x75, 0x0c, 0xff, 0x75, 0x08
+.data1 	0xe8, 0x8b, 0x52, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0x45, 0xfc, 0x3d, 0xff, 0xff, 0xff, 0xff
+.data1 	0x75, 0x09, 0x83, 0x3d, 0xf0, 0x27, 0x00, 0x00
+.data1 	0x04, 0x74, 0xdc, 0x8b, 0x45, 0xfc, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x56, 0x57
+.data1 	0xbe, 0xe0, 0x23, 0x00, 0x00, 0x8b, 0x16, 0x89
+.data1 	0x55, 0xf8, 0x85, 0xd2, 0x74, 0x36, 0x8b, 0x52
+.data1 	0x04, 0xf6, 0xc2, 0x01, 0x75, 0x29, 0xff, 0x76
+.data1 	0x08, 0xe8, 0x34, 0x09, 0x00, 0x00, 0x59, 0x89
+.data1 	0xc7, 0x8b, 0x17, 0x8b, 0x45, 0xf8, 0x89, 0x10
+.data1 	0x8b, 0x55, 0xf8, 0x89, 0x17, 0x8b, 0x55, 0xf8
+.data1 	0x8b, 0x4e, 0x08, 0x89, 0x4a, 0x08, 0x8b, 0x55
+.data1 	0xf8, 0x8b, 0x4e, 0x04, 0x89, 0x4a, 0x04, 0x83
+.data1 	0xc6, 0x0c, 0xeb, 0xc1, 0x8b, 0x15, 0x7c, 0x34
+.data1 	0x00, 0x00, 0xf6, 0xc2, 0x01, 0x75, 0x3f, 0x68
+.data1 	0x50, 0x0e, 0x00, 0x00, 0xe8, 0xf9, 0x08, 0x00
+.data1 	0x00, 0x59, 0x89, 0xc7, 0x8b, 0x17, 0x89, 0x15
+.data1 	0x78, 0x34, 0x00, 0x00, 0xc7, 0x07, 0x78, 0x34
+.data1 	0x00, 0x00, 0xe8, 0xf1, 0x51, 0x00, 0x00, 0x85
+.data1 	0xc0, 0x74, 0x07, 0xb8, 0x48, 0x0e, 0x00, 0x00
+.data1 	0xeb, 0x05, 0xb8, 0x40, 0x0e, 0x00, 0x00, 0xa3
+.data1 	0x80, 0x34, 0x00, 0x00, 0xc7, 0x05, 0x7c, 0x34
+.data1 	0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x18
+.data1 	0x56, 0x57, 0xc7, 0x45, 0xe8, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x75, 0x08, 0x0f, 0xbe, 0x06, 0x46
+.data1 	0xf6, 0x80, 0x9d, 0x22, 0x00, 0x00, 0x0e, 0x75
+.data1 	0x07, 0xc7, 0x45, 0xe8, 0x01, 0x00, 0x00, 0x00
+.data1 	0x0f, 0xbe, 0x06, 0xf6, 0x80, 0x9d, 0x22, 0x00
+.data1 	0x00, 0x0f, 0x75, 0x11, 0x80, 0x3e, 0x00, 0x74
+.data1 	0x0f, 0x80, 0x3e, 0x3d, 0x74, 0x0a, 0xc7, 0x45
+.data1 	0xe8, 0x01, 0x00, 0x00, 0x00, 0x46, 0xeb, 0xe0
+.data1 	0x89, 0xf2, 0x2b, 0x55, 0x08, 0x89, 0xd7, 0x83
+.data1 	0x7d, 0xe8, 0x00, 0x74, 0x11, 0xff, 0x75, 0x08
+.data1 	0x57, 0x68, 0x58, 0x0e, 0x00, 0x00, 0xe8, 0x15
+.data1 	0x6c, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x8d, 0x57
+.data1 	0x02, 0x89, 0x55, 0xf4, 0x83, 0x7d, 0x0c, 0x00
+.data1 	0x75, 0x06, 0x83, 0x4d, 0x10, 0x20, 0xeb, 0x0c
+.data1 	0xff, 0x75, 0x0c, 0xe8, 0xd8, 0x52, 0x00, 0x00
+.data1 	0x59, 0x01, 0x45, 0xf4, 0xff, 0x75, 0xf4, 0xe8
+.data1 	0x3c, 0xc0, 0xff, 0xff, 0x59, 0x89, 0x45, 0xec
+.data1 	0x89, 0xc6, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xf8
+.data1 	0x4f, 0x78, 0x0d, 0x8b, 0x45, 0xf8, 0xff, 0x45
+.data1 	0xf8, 0x8a, 0x08, 0x88, 0x0e, 0x46, 0xeb, 0xf0
+.data1 	0xc6, 0x06, 0x3d, 0x46, 0xc6, 0x06, 0x00, 0x83
+.data1 	0x7d, 0x0c, 0x00, 0x74, 0x0b, 0xff, 0x75, 0x0c
+.data1 	0x56, 0xe8, 0x7a, 0x52, 0x00, 0x00, 0x59, 0x59
+.data1 	0xff, 0x75, 0x10, 0xff, 0x75, 0xec, 0xe8, 0x06
+.data1 	0x00, 0x00, 0x00, 0x59, 0x59, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c, 0x56
+.data1 	0x57, 0x8b, 0x7d, 0x08, 0x57, 0xe8, 0xe0, 0x07
+.data1 	0x00, 0x00, 0x59, 0x89, 0x45, 0xf8, 0x8b, 0x5d
+.data1 	0xf8, 0x8b, 0x33, 0x85, 0xf6, 0x0f, 0x84, 0xbc
+.data1 	0x00, 0x00, 0x00, 0xff, 0x76, 0x08, 0x57, 0xe8
+.data1 	0xfe, 0x07, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x0f, 0x84, 0xa2, 0x00, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x04, 0xf6, 0xc2, 0x02, 0x74, 0x20, 0x6a, 0x3d
+.data1 	0x57, 0xe8, 0xd8, 0xc6, 0xff, 0xff, 0x59, 0x59
+.data1 	0x29, 0xf8, 0x89, 0x45, 0xf4, 0x57, 0xff, 0x75
+.data1 	0xf4, 0x68, 0x6c, 0x0e, 0x00, 0x00, 0xe8, 0x4d
+.data1 	0x6b, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0xff, 0x05
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x81, 0xfe, 0xe0, 0x2c
+.data1 	0x00, 0x00, 0x75, 0x0a, 0x8d, 0x47, 0x05, 0x50
+.data1 	0xe8, 0x64, 0x87, 0xff, 0xff, 0x59, 0x8b, 0x56
+.data1 	0x04, 0xf6, 0xc2, 0x18, 0x75, 0x09, 0xff, 0x76
+.data1 	0x08, 0xe8, 0xa8, 0x3d, 0x00, 0x00, 0x59, 0x83
+.data1 	0x66, 0x04, 0xc7, 0x8b, 0x55, 0x0c, 0x09, 0x56
+.data1 	0x04, 0x89, 0x7e, 0x08, 0x81, 0xfe, 0x10, 0x32
+.data1 	0x00, 0x00, 0x74, 0x13, 0x81, 0xfe, 0x1c, 0x32
+.data1 	0x00, 0x00, 0x75, 0x13, 0x8b, 0x15, 0x14, 0x32
+.data1 	0x00, 0x00, 0xf6, 0xc2, 0x20, 0x74, 0x08, 0x6a
+.data1 	0x01, 0xe8, 0xc6, 0xb7, 0xff, 0xff, 0x59, 0x8b
+.data1 	0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x75, 0x38, 0xff, 0x35
+.data1 	0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2, 0x74
+.data1 	0x2d, 0xe8, 0x71, 0x6a, 0xff, 0xff, 0xeb, 0x26
+.data1 	0x8b, 0x36, 0xe9, 0x3c, 0xff, 0xff, 0xff, 0x6a
+.data1 	0x0c, 0xe8, 0x12, 0xbf, 0xff, 0xff, 0x59, 0x89
+.data1 	0xc6, 0x8b, 0x55, 0x0c, 0x89, 0x56, 0x04, 0x89
+.data1 	0x7e, 0x08, 0x8b, 0x45, 0xf8, 0x8b, 0x10, 0x89
+.data1 	0x16, 0x8b, 0x45, 0xf8, 0x89, 0x30, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0xff, 0x05
+.data1 	0x90, 0x2c, 0x00, 0x00, 0x8b, 0x75, 0x08, 0x85
+.data1 	0xf6, 0x74, 0x17, 0x6a, 0x00, 0xff, 0x76, 0x04
+.data1 	0xe8, 0x26, 0xbf, 0xff, 0xff, 0x59, 0x50, 0xe8
+.data1 	0xdd, 0xfe, 0xff, 0xff, 0x59, 0x59, 0x8b, 0x36
+.data1 	0xeb, 0xe5, 0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00
+.data1 	0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x75
+.data1 	0x10, 0xff, 0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a
+.data1 	0x85, 0xd2, 0x74, 0x05, 0xe8, 0xfe, 0x69, 0xff
+.data1 	0xff, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x9a, 0x06, 0x00, 0x00
+.data1 	0x59, 0x8b, 0x30, 0x85, 0xf6, 0x74, 0x34, 0xff
+.data1 	0x75, 0x08, 0xff, 0x76, 0x08, 0xe8, 0xc0, 0x06
+.data1 	0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x74, 0x1f
+.data1 	0x8b, 0x56, 0x04, 0xf6, 0xc2, 0x20, 0x74, 0x04
+.data1 	0x31, 0xc0, 0xeb, 0x19, 0x6a, 0x3d, 0xff, 0x76
+.data1 	0x08, 0xe8, 0x98, 0xc5, 0xff, 0xff, 0x59, 0x59
+.data1 	0x05, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x06, 0x8b
+.data1 	0x36, 0xeb, 0xc8, 0x31, 0xc0, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x3d, 0xa8
+.data1 	0x2c, 0x00, 0x00, 0x85, 0xff, 0x74, 0x2b, 0xff
+.data1 	0x75, 0x08, 0xff, 0x77, 0x04, 0xe8, 0x78, 0x06
+.data1 	0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x74, 0x16
+.data1 	0x6a, 0x3d, 0xff, 0x77, 0x04, 0xe8, 0x5c, 0xc5
+.data1 	0xff, 0xff, 0x59, 0x59, 0x05, 0x01, 0x00, 0x00
+.data1 	0x00, 0xe9, 0x54, 0x00, 0x00, 0x00, 0x8b, 0x3f
+.data1 	0xeb, 0xd1, 0xff, 0x75, 0x08, 0xe8, 0x18, 0x06
+.data1 	0x00, 0x00, 0x59, 0x8b, 0x30, 0x85, 0xf6, 0x74
+.data1 	0x3f, 0xff, 0x75, 0x08, 0xff, 0x76, 0x08, 0xe8
+.data1 	0x3e, 0x06, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x74, 0x2a, 0x8b, 0x56, 0x04, 0xf6, 0xc2, 0x20
+.data1 	0x75, 0x0b, 0x83, 0x7d, 0x0c, 0x00, 0x75, 0x09
+.data1 	0xf6, 0xc2, 0x01, 0x75, 0x04, 0x31, 0xc0, 0xeb
+.data1 	0x19, 0x6a, 0x3d, 0xff, 0x76, 0x08, 0xe8, 0x0b
+.data1 	0xc5, 0xff, 0xff, 0x59, 0x59, 0x05, 0x01, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x06, 0x8b, 0x36, 0xeb, 0xbd
+.data1 	0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x14, 0x56, 0x57, 0xc7, 0x45
+.data1 	0xfc, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x54, 0x35
+.data1 	0x00, 0x00, 0x81, 0xff, 0xf0, 0x35, 0x00, 0x00
+.data1 	0x73, 0x1a, 0x8b, 0x37, 0x85, 0xf6, 0x74, 0x0f
+.data1 	0x8b, 0x56, 0x04, 0xf6, 0xc2, 0x01, 0x74, 0x03
+.data1 	0xff, 0x45, 0xfc, 0x8b, 0x36, 0xeb, 0xed, 0x83
+.data1 	0xc7, 0x04, 0xeb, 0xde, 0x8b, 0x55, 0xfc, 0x42
+.data1 	0xc1, 0xe2, 0x02, 0x52, 0xe8, 0x01, 0xbe, 0xff
+.data1 	0xff, 0x59, 0x89, 0x45, 0xf0, 0x89, 0x45, 0xec
+.data1 	0xbf, 0x54, 0x35, 0x00, 0x00, 0x81, 0xff, 0xf0
+.data1 	0x35, 0x00, 0x00, 0x73, 0x23, 0x8b, 0x37, 0x85
+.data1 	0xf6, 0x74, 0x18, 0x8b, 0x56, 0x04, 0xf6, 0xc2
+.data1 	0x01, 0x74, 0x0c, 0x8b, 0x56, 0x08, 0x8b, 0x45
+.data1 	0xec, 0x89, 0x10, 0x83, 0x45, 0xec, 0x04, 0x8b
+.data1 	0x36, 0xeb, 0xe4, 0x83, 0xc7, 0x04, 0xeb, 0xd5
+.data1 	0x8b, 0x45, 0xec, 0xc7, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x45, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57
+.data1 	0xbf, 0x54, 0x35, 0x00, 0x00, 0x81, 0xff, 0xf0
+.data1 	0x35, 0x00, 0x00, 0x0f, 0x83, 0x63, 0x00, 0x00
+.data1 	0x00, 0x89, 0x7d, 0xf4, 0x8b, 0x45, 0xf4, 0x8b
+.data1 	0x30, 0x85, 0xf6, 0x0f, 0x84, 0x4e, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x56, 0x04, 0xf6, 0xc2, 0x01, 0x75
+.data1 	0x29, 0x8b, 0x16, 0x8b, 0x45, 0xf4, 0x89, 0x10
+.data1 	0x8b, 0x56, 0x04, 0xf6, 0xc2, 0x08, 0x75, 0x09
+.data1 	0xff, 0x76, 0x08, 0xe8, 0x36, 0x3b, 0x00, 0x00
+.data1 	0x59, 0x8b, 0x56, 0x04, 0xf6, 0xc2, 0x04, 0x75
+.data1 	0xcb, 0x56, 0xe8, 0x27, 0x3b, 0x00, 0x00, 0x59
+.data1 	0xeb, 0xc2, 0x8b, 0x56, 0x04, 0xf6, 0xc2, 0x10
+.data1 	0x74, 0x10, 0xff, 0x76, 0x08, 0xe8, 0x29, 0xbd
+.data1 	0xff, 0xff, 0x59, 0x89, 0x46, 0x08, 0x83, 0x66
+.data1 	0x04, 0xef, 0x89, 0x75, 0xf4, 0xeb, 0xa5, 0x83
+.data1 	0xc7, 0x04, 0xeb, 0x91, 0xe8, 0x67, 0xfb, 0xff
+.data1 	0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0x57, 0xbf, 0x54, 0x35, 0x00, 0x00, 0x81
+.data1 	0xff, 0xf0, 0x35, 0x00, 0x00, 0x73, 0x26, 0x8b
+.data1 	0x37, 0x85, 0xf6, 0x74, 0x1b, 0x8b, 0x56, 0x04
+.data1 	0xf6, 0xc2, 0x20, 0x75, 0x0f, 0xff, 0x76, 0x08
+.data1 	0x68, 0x80, 0x0e, 0x00, 0x00, 0xe8, 0x9c, 0xf5
+.data1 	0xff, 0xff, 0x59, 0x59, 0x8b, 0x36, 0xeb, 0xe1
+.data1 	0x83, 0xc7, 0x04, 0xeb, 0xd2, 0x31, 0xc0, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x14, 0x56, 0x57, 0x8b, 0x45, 0x0c, 0x8b, 0x10
+.data1 	0x80, 0x3a, 0x72, 0x75, 0x07, 0xb8, 0x02, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x05, 0xb8, 0x01, 0x00, 0x00
+.data1 	0x00, 0x89, 0x45, 0xec, 0xff, 0x35, 0xa8, 0x2c
+.data1 	0x00, 0x00, 0xe8, 0x63, 0xfd, 0xff, 0xff, 0x59
+.data1 	0x83, 0x7d, 0x08, 0x01, 0x0f, 0x8e, 0x71, 0x00
+.data1 	0x00, 0x00, 0xa1, 0x80, 0x2c, 0x00, 0x00, 0x83
+.data1 	0x05, 0x80, 0x2c, 0x00, 0x00, 0x04, 0x8b, 0x10
+.data1 	0x89, 0x55, 0xf4, 0x85, 0xd2, 0x0f, 0x84, 0x1c
+.data1 	0x01, 0x00, 0x00, 0x6a, 0x3d, 0xff, 0x75, 0xf4
+.data1 	0xe8, 0x51, 0xc3, 0xff, 0xff, 0x59, 0x59, 0x89
+.data1 	0xc7, 0x85, 0xc0, 0x74, 0x03, 0x47, 0xeb, 0x32
+.data1 	0xff, 0x75, 0xf4, 0xe8, 0x12, 0x04, 0x00, 0x00
+.data1 	0x59, 0x89, 0x45, 0xfc, 0x8b, 0x5d, 0xfc, 0x8b
+.data1 	0x33, 0x85, 0xf6, 0x74, 0x1d, 0xff, 0x75, 0xf4
+.data1 	0xff, 0x76, 0x08, 0xe8, 0x32, 0x04, 0x00, 0x00
+.data1 	0x59, 0x59, 0x85, 0xc0, 0x74, 0x08, 0x8b, 0x55
+.data1 	0xec, 0x09, 0x56, 0x04, 0xeb, 0xa4, 0x8b, 0x36
+.data1 	0xeb, 0xdf, 0xff, 0x75, 0xec, 0x57, 0xff, 0x75
+.data1 	0xf4, 0xe8, 0x1c, 0xfb, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0xeb, 0x8f, 0xc7, 0x45, 0xfc, 0x54, 0x35
+.data1 	0x00, 0x00, 0x81, 0x7d, 0xfc, 0xf0, 0x35, 0x00
+.data1 	0x00, 0x0f, 0x83, 0xb0, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x45, 0xfc, 0x8b, 0x30, 0x85, 0xf6, 0x0f, 0x84
+.data1 	0x9a, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xec, 0x85
+.data1 	0x56, 0x04, 0x0f, 0x84, 0x87, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x7e, 0x08, 0x80, 0x3f, 0x3d, 0x74, 0x45
+.data1 	0xa1, 0xa4, 0x23, 0x00, 0x00, 0xff, 0x48, 0x04
+.data1 	0x8b, 0x15, 0xa4, 0x23, 0x00, 0x00, 0x83, 0x7a
+.data1 	0x04, 0x00, 0x79, 0x1e, 0xff, 0x35, 0xa4, 0x23
+.data1 	0x00, 0x00, 0xe8, 0xc5, 0xf2, 0xff, 0xff, 0x59
+.data1 	0x0f, 0xb6, 0x07, 0x50, 0xa1, 0xa4, 0x23, 0x00
+.data1 	0x00, 0x8b, 0x18, 0xff, 0x00, 0x5a, 0x88, 0x13
+.data1 	0xeb, 0x10, 0x0f, 0xb6, 0x07, 0x50, 0xa1, 0xa4
+.data1 	0x23, 0x00, 0x00, 0x8b, 0x18, 0xff, 0x00, 0x5a
+.data1 	0x88, 0x13, 0x47, 0xeb, 0xb6, 0xa1, 0xa4, 0x23
+.data1 	0x00, 0x00, 0xff, 0x48, 0x04, 0x8b, 0x15, 0xa4
+.data1 	0x23, 0x00, 0x00, 0x83, 0x7a, 0x04, 0x00, 0x79
+.data1 	0x1a, 0xff, 0x35, 0xa4, 0x23, 0x00, 0x00, 0xe8
+.data1 	0x80, 0xf2, 0xff, 0xff, 0x59, 0xa1, 0xa4, 0x23
+.data1 	0x00, 0x00, 0x8b, 0x18, 0xff, 0x00, 0xc6, 0x03
+.data1 	0x0a, 0xeb, 0x0c, 0xa1, 0xa4, 0x23, 0x00, 0x00
+.data1 	0x8b, 0x18, 0xff, 0x00, 0xc6, 0x03, 0x0a, 0x8b
+.data1 	0x36, 0xe9, 0x5e, 0xff, 0xff, 0xff, 0x83, 0x45
+.data1 	0xfc, 0x04, 0xe9, 0x43, 0xff, 0xff, 0xff, 0x31
+.data1 	0xc0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x04, 0x83, 0x3d, 0xac, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x75, 0x0b, 0x68, 0x84, 0x0e, 0x00
+.data1 	0x00, 0xe8, 0xaa, 0x66, 0xff, 0xff, 0x59, 0xa1
+.data1 	0x80, 0x2c, 0x00, 0x00, 0x83, 0x05, 0x80, 0x2c
+.data1 	0x00, 0x00, 0x04, 0x8b, 0x10, 0x89, 0x55, 0xfc
+.data1 	0x85, 0xd2, 0x74, 0x0b, 0xff, 0x75, 0xfc, 0xe8
+.data1 	0x07, 0x00, 0x00, 0x00, 0x59, 0xeb, 0xe0, 0x31
+.data1 	0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x08, 0x56, 0x57, 0xff, 0x05, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x6a, 0x10, 0xe8, 0xc0, 0xba, 0xff, 0xff
+.data1 	0x59, 0x89, 0xc7, 0x8b, 0x55, 0x08, 0x80, 0x3a
+.data1 	0x2d, 0x75, 0x2a, 0x80, 0x7a, 0x01, 0x00, 0x75
+.data1 	0x24, 0x6a, 0x0b, 0xe8, 0xa8, 0xba, 0xff, 0xff
+.data1 	0x59, 0x89, 0x47, 0x0c, 0x6a, 0x0b, 0xff, 0x77
+.data1 	0x0c, 0x68, 0x74, 0x2c, 0x00, 0x00, 0xe8, 0xdd
+.data1 	0xc1, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x31, 0xf6
+.data1 	0xe9, 0xaa, 0x00, 0x00, 0x00, 0xff, 0x75, 0x08
+.data1 	0xe8, 0x7d, 0x02, 0x00, 0x00, 0x59, 0x89, 0x45
+.data1 	0xf8, 0x8b, 0x5d, 0xf8, 0x8b, 0x33, 0x85, 0xf6
+.data1 	0x74, 0x15, 0xff, 0x75, 0x08, 0xff, 0x76, 0x08
+.data1 	0xe8, 0x9d, 0x02, 0x00, 0x00, 0x59, 0x59, 0x85
+.data1 	0xc0, 0x75, 0x04, 0x8b, 0x36, 0xeb, 0xe7, 0x85
+.data1 	0xf6, 0x75, 0x49, 0x6a, 0x3d, 0xff, 0x75, 0x08
+.data1 	0xe8, 0x79, 0xc1, 0xff, 0xff, 0x59, 0x59, 0x85
+.data1 	0xc0, 0x74, 0x15, 0x6a, 0x04, 0xff, 0x75, 0x08
+.data1 	0xe8, 0x8e, 0xba, 0xff, 0xff, 0x59, 0x50, 0xe8
+.data1 	0x45, 0xfa, 0xff, 0xff, 0x59, 0x59, 0xeb, 0x0f
+.data1 	0x6a, 0x04, 0x6a, 0x00, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x66, 0xf9, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x8b
+.data1 	0x45, 0xf8, 0x8b, 0x30, 0xc7, 0x47, 0x0c, 0x00
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x47, 0x08, 0x20, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x33, 0x8b, 0x56, 0x08, 0x89
+.data1 	0x57, 0x0c, 0x8b, 0x56, 0x04, 0x89, 0x57, 0x08
+.data1 	0x83, 0x4e, 0x04, 0x0c, 0x6a, 0x3d, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x20, 0xc1, 0xff, 0xff, 0x59, 0x59
+.data1 	0x85, 0xc0, 0x74, 0x13, 0x6a, 0x00, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x35, 0xba, 0xff, 0xff, 0x59, 0x50
+.data1 	0xe8, 0xec, 0xf9, 0xff, 0xff, 0x59, 0x59, 0x89
+.data1 	0x77, 0x04, 0x8b, 0x15, 0x64, 0x2c, 0x00, 0x00
+.data1 	0x89, 0x17, 0x89, 0x3d, 0x64, 0x2c, 0x00, 0x00
+.data1 	0x8b, 0x15, 0x90, 0x2c, 0x00, 0x00, 0x4a, 0x89
+.data1 	0x15, 0x90, 0x2c, 0x00, 0x00, 0x75, 0x10, 0xff
+.data1 	0x35, 0x8c, 0x2c, 0x00, 0x00, 0x5a, 0x85, 0xd2
+.data1 	0x74, 0x05, 0xe8, 0x00, 0x65, 0xff, 0xff, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x57
+.data1 	0x8b, 0x35, 0x64, 0x2c, 0x00, 0x00, 0x85, 0xf6
+.data1 	0x0f, 0x84, 0x6a, 0x00, 0x00, 0x00, 0x8b, 0x16
+.data1 	0x89, 0x15, 0x64, 0x2c, 0x00, 0x00, 0x8b, 0x7e
+.data1 	0x04, 0x85, 0xff, 0x75, 0x1d, 0x6a, 0x0b, 0x68
+.data1 	0x74, 0x2c, 0x00, 0x00, 0xff, 0x76, 0x0c, 0xe8
+.data1 	0xc4, 0xc0, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0xff
+.data1 	0x76, 0x0c, 0xe8, 0xa7, 0x37, 0x00, 0x00, 0x59
+.data1 	0xeb, 0x35, 0xba, 0x24, 0x00, 0x00, 0x00, 0x23
+.data1 	0x56, 0x08, 0x83, 0xfa, 0x20, 0x75, 0x0b, 0xff
+.data1 	0x77, 0x08, 0xe8, 0x9b, 0x00, 0x00, 0x00, 0x59
+.data1 	0xeb, 0x1d, 0x8b, 0x57, 0x04, 0xf6, 0xc2, 0x08
+.data1 	0x75, 0x09, 0xff, 0x77, 0x08, 0xe8, 0x7c, 0x37
+.data1 	0x00, 0x00, 0x59, 0x8b, 0x56, 0x08, 0x89, 0x57
+.data1 	0x04, 0x8b, 0x56, 0x0c, 0x89, 0x57, 0x08, 0x56
+.data1 	0xe8, 0x69, 0x37, 0x00, 0x00, 0x59, 0xeb, 0x88
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0x7d, 0x08, 0x02, 0x7f, 0x0f, 0xff, 0x75, 0x0c
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x31, 0x00, 0x00, 0x00
+.data1 	0x59, 0x59, 0xeb, 0x2b, 0x83, 0x7d, 0x08, 0x03
+.data1 	0x75, 0x18, 0x8b, 0x55, 0x0c, 0x8b, 0x4d, 0x0c
+.data1 	0x6a, 0x00, 0xff, 0x72, 0x08, 0xff, 0x71, 0x04
+.data1 	0xe8, 0x35, 0xf8, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0xeb, 0x0b, 0x68, 0x98, 0x0e, 0x00, 0x00, 0xe8
+.data1 	0x9c, 0x64, 0xff, 0xff, 0x59, 0x31, 0xc0, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b, 0x75, 0x0c
+.data1 	0x83, 0xc6, 0x04, 0x83, 0x3e, 0x00, 0x74, 0x15
+.data1 	0xff, 0x36, 0xe8, 0x5e, 0x84, 0xff, 0xff, 0x59
+.data1 	0xff, 0x36, 0xe8, 0x0b, 0x00, 0x00, 0x00, 0x59
+.data1 	0x83, 0xc6, 0x04, 0xeb, 0xe6, 0x31, 0xc0, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x57, 0xff
+.data1 	0x75, 0x08, 0xe8, 0xab, 0x00, 0x00, 0x00, 0x59
+.data1 	0x89, 0xc7, 0x8b, 0x37, 0x85, 0xf6, 0x0f, 0x84
+.data1 	0x9a, 0x00, 0x00, 0x00, 0xff, 0x75, 0x08, 0xff
+.data1 	0x76, 0x08, 0xe8, 0xcb, 0x00, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x0f, 0x84, 0x7c, 0x00, 0x00
+.data1 	0x00, 0xff, 0x05, 0x90, 0x2c, 0x00, 0x00, 0x6a
+.data1 	0x3d, 0xff, 0x76, 0x08, 0xe8, 0xa5, 0xbf, 0xff
+.data1 	0xff, 0x59, 0x59, 0x80, 0x78, 0x01, 0x00, 0x75
+.data1 	0x08, 0x8b, 0x56, 0x04, 0xf6, 0xc2, 0x02, 0x74
+.data1 	0x12, 0x6a, 0x00, 0x68, 0x88, 0x2c, 0x00, 0x00
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x9a, 0xf7, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x83, 0x66, 0x04, 0xfe, 0x83
+.data1 	0x4e, 0x04, 0x20, 0x8b, 0x56, 0x04, 0xf6, 0xc2
+.data1 	0x04, 0x75, 0x19, 0xf6, 0xc2, 0x08, 0x75, 0x09
+.data1 	0xff, 0x76, 0x08, 0xe8, 0x76, 0x36, 0x00, 0x00
+.data1 	0x59, 0x8b, 0x16, 0x89, 0x17, 0x56, 0xe8, 0x6b
+.data1 	0x36, 0x00, 0x00, 0x59, 0x8b, 0x15, 0x90, 0x2c
+.data1 	0x00, 0x00, 0x4a, 0x89, 0x15, 0x90, 0x2c, 0x00
+.data1 	0x00, 0x75, 0x1b, 0xff, 0x35, 0x8c, 0x2c, 0x00
+.data1 	0x00, 0x5a, 0x85, 0xd2, 0x74, 0x10, 0xe8, 0x64
+.data1 	0x63, 0xff, 0xff, 0xeb, 0x09, 0x89, 0xf7, 0x8b
+.data1 	0x37, 0xe9, 0x5e, 0xff, 0xff, 0xff, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b
+.data1 	0x75, 0x08, 0x0f, 0xbe, 0x06, 0xc1, 0xe0, 0x04
+.data1 	0x89, 0xc7, 0x80, 0x3e, 0x00, 0x74, 0x0d, 0x80
+.data1 	0x3e, 0x3d, 0x74, 0x08, 0x0f, 0xbe, 0x06, 0x46
+.data1 	0x01, 0xc7, 0xeb, 0xee, 0xb9, 0x27, 0x00, 0x00
+.data1 	0x00, 0x89, 0xf8, 0x31, 0xd2, 0xf7, 0xf1, 0x8d
+.data1 	0x04, 0x95, 0x54, 0x35, 0x00, 0x00, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b
+.data1 	0x75, 0x08, 0x8b, 0x7d, 0x0c, 0x0f, 0xbe, 0x07
+.data1 	0x47, 0x0f, 0xbe, 0x1e, 0x39, 0xd8, 0x75, 0x0e
+.data1 	0x8a, 0x06, 0x46, 0x3c, 0x3d, 0x75, 0xee, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x00, 0xeb, 0x14, 0x80, 0x3e
+.data1 	0x3d, 0x75, 0x0d, 0x80, 0x7f, 0xff, 0x00, 0x75
+.data1 	0x07, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x02
+.data1 	0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0xba, 0xcc, 0x2d, 0x00
+.data1 	0x00, 0x89, 0x15, 0xc8, 0x2d, 0x00, 0x00, 0x89
+.data1 	0x15, 0xc0, 0x2d, 0x00, 0x00, 0xe8, 0x16, 0xf6
+.data1 	0xff, 0xff, 0x8b, 0x35, 0xec, 0x27, 0x00, 0x00
+.data1 	0x83, 0x3e, 0x00, 0x74, 0x1f, 0x6a, 0x3d, 0xff
+.data1 	0x36, 0xe8, 0x88, 0xbe, 0xff, 0xff, 0x59, 0x59
+.data1 	0x85, 0xc0, 0x74, 0x0b, 0x6a, 0x09, 0xff, 0x36
+.data1 	0xe8, 0x5c, 0xf7, 0xff, 0xff, 0x59, 0x59, 0x83
+.data1 	0xc6, 0x04, 0xeb, 0xdc, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0xc7, 0x05, 0xb0, 0x2c, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xc7, 0x05, 0xb8, 0x2c
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x05
+.data1 	0xac, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x83, 0x3d, 0x98, 0x2c, 0x00, 0x00, 0x02, 0x74
+.data1 	0x0a, 0xc7, 0x05, 0xac, 0x2d, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0xe8, 0x76, 0x9f, 0xff, 0xff
+.data1 	0xc7, 0x05, 0xc4, 0x2c, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x83, 0x3d, 0x9c, 0x34, 0x00, 0x00
+.data1 	0x00, 0x74, 0x07, 0xe8, 0x99, 0xe8, 0xff, 0xff
+.data1 	0xeb, 0xf0, 0xc7, 0x05, 0xa4, 0x23, 0x00, 0x00
+.data1 	0x68, 0x23, 0x00, 0x00, 0xc7, 0x05, 0xa8, 0x23
+.data1 	0x00, 0x00, 0x7c, 0x23, 0x00, 0x00, 0x83, 0x3d
+.data1 	0x98, 0x23, 0x00, 0x00, 0x00, 0x74, 0x16, 0xff
+.data1 	0x35, 0x98, 0x23, 0x00, 0x00, 0xe8, 0x04, 0x35
+.data1 	0x00, 0x00, 0x59, 0xc7, 0x05, 0x98, 0x23, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0xc7, 0x05, 0xa4, 0x2c, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xe9, 0x7f
+.data1 	0xff, 0xff, 0xe8, 0x0f, 0x9f, 0xff, 0xff, 0xc7
+.data1 	0x05, 0xd4, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xff
+.data1 	0xff, 0xbe, 0x74, 0x2c, 0x00, 0x00, 0x81, 0xfe
+.data1 	0x7f, 0x2c, 0x00, 0x00, 0x73, 0x06, 0xc6, 0x06
+.data1 	0x00, 0x46, 0xeb, 0xf2, 0xe8, 0xbd, 0xe8, 0xff
+.data1 	0xff, 0xe8, 0x62, 0xea, 0xff, 0xff, 0xbe, 0x04
+.data1 	0x35, 0x00, 0x00, 0x81, 0xfe, 0x1b, 0x35, 0x00
+.data1 	0x00, 0x73, 0x0b, 0x80, 0x3e, 0x03, 0x75, 0x03
+.data1 	0xc6, 0x06, 0x04, 0x46, 0xeb, 0xed, 0xe8, 0x1d
+.data1 	0xf9, 0xff, 0xff, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x18, 0x56, 0x57
+.data1 	0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x7d
+.data1 	0x0c, 0x83, 0x7d, 0x08, 0x00, 0x74, 0x03, 0x83
+.data1 	0xc7, 0x04, 0x8b, 0x37, 0x85, 0xf6, 0x74, 0x44
+.data1 	0x68, 0x10, 0x0f, 0x00, 0x00, 0x56, 0xe8, 0x8d
+.data1 	0x48, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x75
+.data1 	0x03, 0x83, 0xc7, 0x04, 0x68, 0x0c, 0x0f, 0x00
+.data1 	0x00, 0x56, 0xe8, 0x79, 0x48, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x75, 0x08, 0xff, 0x45, 0xec
+.data1 	0x83, 0xc7, 0x04, 0xeb, 0x17, 0x68, 0x08, 0x0f
+.data1 	0x00, 0x00, 0x56, 0xe8, 0x60, 0x48, 0x00, 0x00
+.data1 	0x59, 0x59, 0x85, 0xc0, 0x75, 0x06, 0xff, 0x45
+.data1 	0xe8, 0x83, 0xc7, 0x04, 0x8b, 0x07, 0x83, 0xc7
+.data1 	0x04, 0x89, 0xc6, 0x85, 0xc0, 0x0f, 0x84, 0x3f
+.data1 	0x01, 0x00, 0x00, 0x8a, 0x06, 0x46, 0x88, 0x45
+.data1 	0xf7, 0x0f, 0xb6, 0xd0, 0x84, 0xd2, 0x0f, 0x84
+.data1 	0xe3, 0x00, 0x00, 0x00, 0x80, 0x7d, 0xf7, 0x5c
+.data1 	0x0f, 0x85, 0x8d, 0x00, 0x00, 0x00, 0x83, 0x7d
+.data1 	0xe8, 0x00, 0x0f, 0x84, 0x83, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x70, 0x00, 0x00, 0x00, 0xc6, 0x45, 0xf7
+.data1 	0x08, 0xe9, 0x75, 0x00, 0x00, 0x00, 0x31, 0xc0
+.data1 	0xe9, 0x47, 0x01, 0x00, 0x00, 0xc6, 0x45, 0xf7
+.data1 	0x0c, 0xe9, 0x65, 0x00, 0x00, 0x00, 0xc6, 0x45
+.data1 	0xf7, 0x0a, 0xe9, 0x5c, 0x00, 0x00, 0x00, 0xc6
+.data1 	0x45, 0xf7, 0x0d, 0xe9, 0x53, 0x00, 0x00, 0x00
+.data1 	0xc6, 0x45, 0xf7, 0x09, 0xeb, 0x4d, 0xc6, 0x45
+.data1 	0xf7, 0x0b, 0xeb, 0x47, 0xc6, 0x45, 0xf7, 0x00
+.data1 	0xc7, 0x45, 0xf0, 0x03, 0x00, 0x00, 0x00, 0xff
+.data1 	0x4d, 0xf0, 0x78, 0x37, 0x0f, 0xbe, 0x06, 0x2d
+.data1 	0x30, 0x00, 0x00, 0x00, 0x3d, 0x08, 0x00, 0x00
+.data1 	0x00, 0x73, 0x28, 0x0f, 0xbe, 0x06, 0x46, 0x2d
+.data1 	0x30, 0x00, 0x00, 0x00, 0x0f, 0xbe, 0x5d, 0xf7
+.data1 	0xc1, 0xe3, 0x03, 0x01, 0xc3, 0x88, 0x5d, 0xf7
+.data1 	0xeb, 0xd5, 0x4e, 0xeb, 0x0e, 0x0f, 0xbe, 0x06
+.data1 	0x46, 0xbb, 0xb8, 0x0e, 0x00, 0x00, 0xe9, 0x41
+.data1 	0x54, 0x00, 0x00, 0xa1, 0xa4, 0x23, 0x00, 0x00
+.data1 	0xff, 0x48, 0x04, 0x8b, 0x15, 0xa4, 0x23, 0x00
+.data1 	0x00, 0x83, 0x7a, 0x04, 0x00, 0x79, 0x22, 0xff
+.data1 	0x35, 0xa4, 0x23, 0x00, 0x00, 0xe8, 0x5a, 0xec
+.data1 	0xff, 0xff, 0x59, 0x0f, 0xb6, 0x45, 0xf7, 0x50
+.data1 	0xa1, 0xa4, 0x23, 0x00, 0x00, 0x8b, 0x18, 0xff
+.data1 	0x00, 0x5a, 0x88, 0x13, 0xe9, 0x22, 0xff, 0xff
+.data1 	0xff, 0x0f, 0xb6, 0x45, 0xf7, 0x50, 0xa1, 0xa4
+.data1 	0x23, 0x00, 0x00, 0x8b, 0x18, 0xff, 0x00, 0x5a
+.data1 	0x88, 0x13, 0xe9, 0x0c, 0xff, 0xff, 0xff, 0x83
+.data1 	0x3f, 0x00, 0x0f, 0x84, 0xf4, 0xfe, 0xff, 0xff
+.data1 	0xa1, 0xa4, 0x23, 0x00, 0x00, 0xff, 0x48, 0x04
+.data1 	0x8b, 0x15, 0xa4, 0x23, 0x00, 0x00, 0x83, 0x7a
+.data1 	0x04, 0x00, 0x79, 0x1d, 0xff, 0x35, 0xa4, 0x23
+.data1 	0x00, 0x00, 0xe8, 0x05, 0xec, 0xff, 0xff, 0x59
+.data1 	0xa1, 0xa4, 0x23, 0x00, 0x00, 0x8b, 0x18, 0xff
+.data1 	0x00, 0xc6, 0x03, 0x20, 0xe9, 0xc3, 0xfe, 0xff
+.data1 	0xff, 0xa1, 0xa4, 0x23, 0x00, 0x00, 0x8b, 0x18
+.data1 	0xff, 0x00, 0xc6, 0x03, 0x20, 0xe9, 0xb2, 0xfe
+.data1 	0xff, 0xff, 0x83, 0x7d, 0xec, 0x00, 0x75, 0x3a
+.data1 	0xa1, 0xa4, 0x23, 0x00, 0x00, 0xff, 0x48, 0x04
+.data1 	0x8b, 0x15, 0xa4, 0x23, 0x00, 0x00, 0x83, 0x7a
+.data1 	0x04, 0x00, 0x79, 0x1a, 0xff, 0x35, 0xa4, 0x23
+.data1 	0x00, 0x00, 0xe8, 0xbd, 0xeb, 0xff, 0xff, 0x59
+.data1 	0xa1, 0xa4, 0x23, 0x00, 0x00, 0x8b, 0x18, 0xff
+.data1 	0x00, 0xc6, 0x03, 0x0a, 0xeb, 0x0c, 0xa1, 0xa4
+.data1 	0x23, 0x00, 0x00, 0x8b, 0x18, 0xff, 0x00, 0xc6
+.data1 	0x03, 0x0a, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x81, 0xec, 0xf8, 0x00, 0x00
+.data1 	0x00, 0x56, 0x57, 0x8b, 0x45, 0x0c, 0x8b, 0x10
+.data1 	0x8a, 0x0a, 0x88, 0x4d, 0xf7, 0xc7, 0x45, 0xec
+.data1 	0x01, 0x00, 0x00, 0x00, 0x80, 0x7d, 0xf7, 0x74
+.data1 	0x75, 0x09, 0xc7, 0x45, 0xec, 0x00, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x40, 0x80, 0x7d, 0xf7, 0x5b, 0x75
+.data1 	0x3a, 0x8b, 0x55, 0x08, 0x4a, 0x8b, 0x4d, 0x0c
+.data1 	0x68, 0x6c, 0x0f, 0x00, 0x00, 0xff, 0x34, 0x91
+.data1 	0xe8, 0x7b, 0x46, 0x00, 0x00, 0x59, 0x59, 0x85
+.data1 	0xc0, 0x74, 0x0b, 0x68, 0x60, 0x0f, 0x00, 0x00
+.data1 	0xe8, 0xbb, 0x5f, 0xff, 0xff, 0x59, 0x8b, 0x55
+.data1 	0x08, 0x4a, 0x8b, 0x4d, 0x0c, 0xc7, 0x04, 0x91
+.data1 	0x00, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xec, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x0c, 0x83, 0xc2
+.data1 	0x04, 0x89, 0x55, 0xfc, 0xc7, 0x85, 0x0c, 0xff
+.data1 	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x45
+.data1 	0xe8, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xdc
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8d, 0x7d, 0xd8, 0x8d
+.data1 	0xb5, 0x3c, 0xff, 0xff, 0xff, 0x8b, 0x45, 0xfc
+.data1 	0x83, 0x38, 0x00, 0x75, 0x19, 0xc7, 0x85, 0x3c
+.data1 	0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x85, 0x40, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00
+.data1 	0x00, 0xe9, 0x00, 0x03, 0x00, 0x00, 0x8b, 0x55
+.data1 	0xfc, 0x8b, 0x12, 0x89, 0x55, 0xf8, 0x83, 0x45
+.data1 	0xfc, 0x04, 0x83, 0x7d, 0xf8, 0x00, 0x75, 0x0b
+.data1 	0x68, 0x50, 0x0f, 0x00, 0x00, 0xe8, 0x3e, 0x5f
+.data1 	0xff, 0xff, 0x59, 0x8b, 0x55, 0xf8, 0x80, 0x3a
+.data1 	0x28, 0x75, 0x0c, 0x80, 0x7a, 0x01, 0x00, 0x75
+.data1 	0x06, 0x83, 0x45, 0xe8, 0x10, 0xeb, 0xcf, 0x8b
+.data1 	0x45, 0xfc, 0x83, 0x38, 0x00, 0x74, 0x4c, 0x68
+.data1 	0x34, 0x24, 0x00, 0x00, 0xff, 0x75, 0xf8, 0xe8
+.data1 	0xaf, 0x06, 0x00, 0x00, 0x59, 0x59, 0x89, 0x45
+.data1 	0xe4, 0x85, 0xc0, 0x78, 0x36, 0x8d, 0x55, 0xa8
+.data1 	0x39, 0xd7, 0x75, 0x0b, 0x68, 0x38, 0x0f, 0x00
+.data1 	0x00, 0xe8, 0xfa, 0x5e, 0xff, 0xff, 0x59, 0x83
+.data1 	0xc7, 0xfc, 0x8b, 0x55, 0xe4, 0x66, 0x89, 0x17
+.data1 	0x8b, 0x45, 0xe4, 0x0f, 0xbe, 0x98, 0xd0, 0x24
+.data1 	0x00, 0x00, 0x03, 0x5d, 0xe8, 0x89, 0xd8, 0x0f
+.data1 	0xbf, 0xc0, 0x66, 0x89, 0x47, 0x02, 0xe9, 0x7b
+.data1 	0xff, 0xff, 0xff, 0xc7, 0x06, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xf8, 0x89, 0x56, 0x04, 0x83
+.data1 	0xc6, 0x08, 0x8b, 0x55, 0xfc, 0x8b, 0x12, 0x89
+.data1 	0x55, 0xf8, 0x83, 0x45, 0xfc, 0x04, 0x83, 0x7d
+.data1 	0xf8, 0x00, 0x75, 0x13, 0x83, 0x7d, 0xe8, 0x00
+.data1 	0x0f, 0x85, 0x62, 0xff, 0xff, 0xff, 0xc7, 0x45
+.data1 	0xe0, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x49, 0x8b
+.data1 	0x55, 0xf8, 0x80, 0x3a, 0x29, 0x75, 0x06, 0x80
+.data1 	0x7a, 0x01, 0x00, 0x74, 0x30, 0x68, 0x80, 0x24
+.data1 	0x00, 0x00, 0xff, 0x75, 0xf8, 0xe8, 0x21, 0x06
+.data1 	0x00, 0x00, 0x59, 0x59, 0x89, 0x45, 0xe4, 0x85
+.data1 	0xc0, 0x0f, 0x88, 0x31, 0xff, 0xff, 0xff, 0x83
+.data1 	0x45, 0xe4, 0x12, 0x8b, 0x45, 0xe4, 0x0f, 0xbe
+.data1 	0x98, 0xd0, 0x24, 0x00, 0x00, 0x03, 0x5d, 0xe8
+.data1 	0x89, 0x5d, 0xe0, 0xeb, 0x0b, 0x83, 0x6d, 0xe8
+.data1 	0x10, 0x79, 0x97, 0xe9, 0x10, 0xff, 0xff, 0xff
+.data1 	0x8d, 0x55, 0xd8, 0x39, 0xd7, 0x0f, 0x83, 0x72
+.data1 	0x01, 0x00, 0x00, 0x0f, 0xbf, 0x47, 0x02, 0x39
+.data1 	0x45, 0xe0, 0x0f, 0x8f, 0x65, 0x01, 0x00, 0x00
+.data1 	0x0f, 0xbf, 0x07, 0x89, 0x45, 0xd8, 0x83, 0xc6
+.data1 	0xf8, 0x0f, 0xbf, 0x07, 0x8a, 0x88, 0xf8, 0x24
+.data1 	0x00, 0x00, 0x88, 0x4d, 0xf7, 0x80, 0x7d, 0xf7
+.data1 	0x01, 0x75, 0x1c, 0x83, 0x3e, 0x00, 0x75, 0x0c
+.data1 	0xff, 0x76, 0x04, 0xe8, 0x04, 0x2d, 0x00, 0x00
+.data1 	0x59, 0x89, 0x46, 0x04, 0xc7, 0x06, 0x01, 0x00
+.data1 	0x00, 0x00, 0xe9, 0xde, 0x00, 0x00, 0x00, 0x0f
+.data1 	0xbe, 0x45, 0xf7, 0x3d, 0x02, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x8c, 0xcf, 0x00, 0x00, 0x00, 0x83, 0x3e
+.data1 	0x01, 0x75, 0x28, 0x6a, 0x20, 0xe8, 0xb0, 0xb2
+.data1 	0xff, 0xff, 0x59, 0x89, 0x45, 0xf0, 0xff, 0x76
+.data1 	0x04, 0x68, 0x34, 0x0f, 0x00, 0x00, 0x6a, 0x20
+.data1 	0xff, 0x75, 0xf0, 0xe8, 0x4e, 0xeb, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x10, 0x8b, 0x55, 0xf0, 0x89, 0x56
+.data1 	0x04, 0xeb, 0x1b, 0x83, 0x3e, 0x02, 0x75, 0x16
+.data1 	0x83, 0x7e, 0x04, 0x00, 0x74, 0x09, 0xc7, 0x46
+.data1 	0x04, 0x2c, 0x0f, 0x00, 0x00, 0xeb, 0x07, 0xc7
+.data1 	0x46, 0x04, 0x28, 0x0f, 0x00, 0x00, 0xc7, 0x06
+.data1 	0x00, 0x00, 0x00, 0x00, 0x0f, 0xbe, 0x45, 0xf7
+.data1 	0x3d, 0x03, 0x00, 0x00, 0x00, 0x0f, 0x8c, 0x72
+.data1 	0x00, 0x00, 0x00, 0x0f, 0xbe, 0x45, 0xf7, 0x39
+.data1 	0x85, 0x08, 0xff, 0xff, 0xff, 0x75, 0x1d, 0x83
+.data1 	0xbd, 0x0c, 0xff, 0xff, 0xff, 0x00, 0x74, 0x14
+.data1 	0xff, 0x76, 0x04, 0xff, 0xb5, 0x0c, 0xff, 0xff
+.data1 	0xff, 0xe8, 0x2a, 0x44, 0x00, 0x00, 0x59, 0x59
+.data1 	0x85, 0xc0, 0x74, 0x49, 0x0f, 0xbe, 0x45, 0xf7
+.data1 	0x89, 0x85, 0x08, 0xff, 0xff, 0xff, 0x8b, 0x56
+.data1 	0x04, 0x89, 0x95, 0x0c, 0xff, 0xff, 0xff, 0x80
+.data1 	0x7d, 0xf7, 0x03, 0x75, 0x19, 0x8d, 0x85, 0x14
+.data1 	0xff, 0xff, 0xff, 0x50, 0xff, 0x76, 0x04, 0xe8
+.data1 	0xf4, 0x42, 0x00, 0x00, 0x59, 0x59, 0x89, 0x85
+.data1 	0x10, 0xff, 0xff, 0xff, 0xeb, 0x17, 0x8d, 0x85
+.data1 	0x14, 0xff, 0xff, 0xff, 0x50, 0xff, 0x76, 0x04
+.data1 	0xe8, 0xab, 0x42, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0x85, 0x10, 0xff, 0xff, 0xff, 0x83, 0x7d, 0xd8
+.data1 	0x12, 0x7c, 0x0c, 0xc7, 0x45, 0xd8, 0x00, 0x00
+.data1 	0x00, 0x00, 0xe9, 0xdf, 0xfe, 0xff, 0xff, 0x83
+.data1 	0x7d, 0xdc, 0x00, 0x75, 0x16, 0x0f, 0xbf, 0x07
+.data1 	0x8d, 0x9d, 0x08, 0xff, 0xff, 0xff, 0x53, 0x56
+.data1 	0x50, 0xe8, 0x3e, 0x01, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0xeb, 0x17, 0x0f, 0xbf, 0x07, 0x3d, 0x14
+.data1 	0x00, 0x00, 0x00, 0x74, 0x0a, 0x0f, 0xbf, 0x07
+.data1 	0x3d, 0x12, 0x00, 0x00, 0x00, 0x75, 0x03, 0xff
+.data1 	0x4d, 0xdc, 0x83, 0xc6, 0x08, 0x83, 0xc7, 0x04
+.data1 	0xe9, 0x83, 0xfe, 0xff, 0xff, 0x83, 0x7d, 0xf8
+.data1 	0x00, 0x0f, 0x84, 0x77, 0x00, 0x00, 0x00, 0x8d
+.data1 	0x55, 0xa8, 0x39, 0xd7, 0x0f, 0x84, 0xc2, 0xfd
+.data1 	0xff, 0xff, 0x83, 0x7d, 0xe4, 0x14, 0x74, 0x06
+.data1 	0x83, 0x7d, 0xe4, 0x15, 0x75, 0x1e, 0xc7, 0x45
+.data1 	0xe4, 0x14, 0x00, 0x00, 0x00, 0x83, 0x7d, 0xdc
+.data1 	0x00, 0x75, 0x0e, 0x8d, 0x46, 0xf8, 0x50, 0xe8
+.data1 	0xaf, 0x00, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x74
+.data1 	0x03, 0xff, 0x45, 0xdc, 0x83, 0x7d, 0xe4, 0x12
+.data1 	0x74, 0x06, 0x83, 0x7d, 0xe4, 0x13, 0x75, 0x1e
+.data1 	0xc7, 0x45, 0xe4, 0x12, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7d, 0xdc, 0x00, 0x75, 0x0e, 0x8d, 0x46, 0xf8
+.data1 	0x50, 0xe8, 0x85, 0x00, 0x00, 0x00, 0x59, 0x85
+.data1 	0xc0, 0x75, 0x03, 0xff, 0x45, 0xdc, 0x83, 0xc7
+.data1 	0xfc, 0x8b, 0x55, 0xe4, 0x66, 0x89, 0x17, 0x8b
+.data1 	0x45, 0xe0, 0x0f, 0xbf, 0xc0, 0x66, 0x89, 0x47
+.data1 	0x02, 0xe9, 0x00, 0xfd, 0xff, 0xff, 0x83, 0x7d
+.data1 	0xec, 0x00, 0x74, 0x4e, 0x83, 0xbd, 0x3c, 0xff
+.data1 	0xff, 0xff, 0x00, 0x75, 0x14, 0xff, 0xb5, 0x40
+.data1 	0xff, 0xff, 0xff, 0x68, 0x24, 0x0f, 0x00, 0x00
+.data1 	0xe8, 0x91, 0xe9, 0xff, 0xff, 0x59, 0x59, 0xeb
+.data1 	0x31, 0x83, 0xbd, 0x3c, 0xff, 0xff, 0xff, 0x01
+.data1 	0x75, 0x14, 0xff, 0xb5, 0x40, 0xff, 0xff, 0xff
+.data1 	0x68, 0x1c, 0x0f, 0x00, 0x00, 0xe8, 0x74, 0xe9
+.data1 	0xff, 0xff, 0x59, 0x59, 0xeb, 0x14, 0x83, 0xbd
+.data1 	0x40, 0xff, 0xff, 0xff, 0x00, 0x74, 0x0b, 0x68
+.data1 	0x14, 0x0f, 0x00, 0x00, 0xe8, 0x5d, 0xe9, 0xff
+.data1 	0xff, 0x59, 0x8d, 0x85, 0x3c, 0xff, 0xff, 0xff
+.data1 	0x50, 0xe8, 0x05, 0x00, 0x00, 0x00, 0x59, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b, 0x45
+.data1 	0x08, 0x83, 0x38, 0x00, 0x75, 0x12, 0x8b, 0x55
+.data1 	0x08, 0x8b, 0x52, 0x04, 0x80, 0x3a, 0x00, 0x75
+.data1 	0x17, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x12
+.data1 	0x8b, 0x55, 0x08, 0x83, 0x7a, 0x04, 0x00, 0x75
+.data1 	0x07, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x02
+.data1 	0x31, 0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x50, 0x56, 0x57, 0x8b, 0x75, 0x0c, 0xe9
+.data1 	0x3e, 0x03, 0x00, 0x00, 0x56, 0xe8, 0xb9, 0xff
+.data1 	0xff, 0xff, 0x59, 0x89, 0x46, 0x04, 0xc7, 0x06
+.data1 	0x02, 0x00, 0x00, 0x00, 0xe9, 0x36, 0x03, 0x00
+.data1 	0x00, 0xbf, 0x04, 0x00, 0x00, 0x00, 0xeb, 0x0c
+.data1 	0xbf, 0x02, 0x00, 0x00, 0x00, 0xeb, 0x05, 0xbf
+.data1 	0x01, 0x00, 0x00, 0x00, 0xe8, 0xcf, 0x40, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x10, 0x0f, 0xbf, 0x5a, 0x18
+.data1 	0x39, 0xd8, 0x75, 0x08, 0xc1, 0xe7, 0x06, 0xe9
+.data1 	0x85, 0x00, 0x00, 0x00, 0xe8, 0xaf, 0x40, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x10, 0x0f, 0xbf, 0x5a, 0x1a
+.data1 	0x39, 0xd8, 0x0f, 0x85, 0x71, 0x00, 0x00, 0x00
+.data1 	0xc1, 0xe7, 0x03, 0xe9, 0x69, 0x00, 0x00, 0x00
+.data1 	0xbf, 0x00, 0x80, 0x00, 0x00, 0xeb, 0x1a, 0xbf
+.data1 	0x00, 0x40, 0x00, 0x00, 0xeb, 0x13, 0xbf, 0x00
+.data1 	0x20, 0x00, 0x00, 0xeb, 0x0c, 0xbf, 0x00, 0x60
+.data1 	0x00, 0x00, 0xeb, 0x05, 0xbf, 0x00, 0x10, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x10, 0x0f, 0xb7, 0x4a, 0x14
+.data1 	0x81, 0xe1, 0x00, 0xf0, 0x00, 0x00, 0x39, 0xf9
+.data1 	0x75, 0x12, 0x8b, 0x55, 0x10, 0x83, 0x7a, 0x08
+.data1 	0x00, 0x78, 0x09, 0xc7, 0x46, 0x04, 0x01, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x07, 0xc7, 0x46, 0x04, 0x00
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x06, 0x02, 0x00, 0x00
+.data1 	0x00, 0xe9, 0x99, 0x02, 0x00, 0x00, 0xbf, 0x00
+.data1 	0x08, 0x00, 0x00, 0xeb, 0x0c, 0xbf, 0x00, 0x04
+.data1 	0x00, 0x00, 0xeb, 0x05, 0xbf, 0x00, 0x02, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x10, 0x0f, 0xb7, 0x4a, 0x14
+.data1 	0x85, 0xf9, 0x74, 0xd0, 0x8b, 0x55, 0x10, 0x83
+.data1 	0x7a, 0x08, 0x00, 0x78, 0xc7, 0xeb, 0xbc, 0x8b
+.data1 	0x55, 0x10, 0x83, 0x7a, 0x08, 0x00, 0x78, 0x05
+.data1 	0x8b, 0x42, 0x20, 0xeb, 0x02, 0x31, 0xc0, 0x89
+.data1 	0x46, 0x04, 0xc7, 0x06, 0x01, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x52, 0x02, 0x00, 0x00, 0x8b, 0x55, 0x10
+.data1 	0x0f, 0xb7, 0x4a, 0x14, 0x81, 0xe1, 0x00, 0xf0
+.data1 	0x00, 0x00, 0x81, 0xf9, 0x00, 0xa0, 0x00, 0x00
+.data1 	0x75, 0x09, 0x8b, 0x55, 0x10, 0x83, 0x7a, 0x08
+.data1 	0x00, 0x79, 0x80, 0x8b, 0x45, 0x10, 0xc7, 0x00
+.data1 	0x03, 0x00, 0x00, 0x00, 0xe9, 0x7b, 0xff, 0xff
+.data1 	0xff, 0x8d, 0x45, 0xd8, 0x50, 0xff, 0x76, 0x04
+.data1 	0xe8, 0x2b, 0x40, 0x00, 0x00, 0x59, 0x59, 0x85
+.data1 	0xc0, 0x74, 0x09, 0xc7, 0x46, 0x04, 0x00, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x29, 0x8d, 0x45, 0xb4, 0x50
+.data1 	0xff, 0x76, 0x0c, 0xe8, 0x10, 0x40, 0x00, 0x00
+.data1 	0x59, 0x59, 0x85, 0xc0, 0x74, 0x09, 0xc7, 0x46
+.data1 	0x04, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x0e, 0x8b
+.data1 	0x55, 0xd0, 0x31, 0xc0, 0x39, 0x55, 0xf4, 0x7c
+.data1 	0x01, 0x40, 0x89, 0x46, 0x04, 0xc7, 0x06, 0x01
+.data1 	0x00, 0x00, 0x00, 0xe9, 0xd7, 0x01, 0x00, 0x00
+.data1 	0xff, 0x76, 0x04, 0xe8, 0xa0, 0x3f, 0x00, 0x00
+.data1 	0x59, 0x89, 0x46, 0x04, 0xc7, 0x06, 0x02, 0x00
+.data1 	0x00, 0x00, 0xe9, 0xc0, 0x01, 0x00, 0x00, 0x8b
+.data1 	0x56, 0x04, 0x80, 0x3a, 0x00, 0x0f, 0x85, 0x09
+.data1 	0xff, 0xff, 0xff, 0xe9, 0xfb, 0xfe, 0xff, 0xff
+.data1 	0xff, 0x76, 0x04, 0xe8, 0xf0, 0x40, 0x00, 0x00
+.data1 	0x59, 0x89, 0x46, 0x04, 0xc7, 0x06, 0x01, 0x00
+.data1 	0x00, 0x00, 0xe9, 0x98, 0x01, 0x00, 0x00, 0x8d
+.data1 	0x46, 0x08, 0x50, 0x56, 0xb9, 0x02, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x02, 0x4d, 0x00, 0x00, 0xe9, 0x84
+.data1 	0x01, 0x00, 0x00, 0x31, 0xff, 0xff, 0x76, 0x0c
+.data1 	0xff, 0x76, 0x04, 0xe8, 0x90, 0x40, 0x00, 0x00
+.data1 	0x59, 0x59, 0x85, 0xc0, 0x75, 0x01, 0x47, 0x83
+.data1 	0x7d, 0x08, 0x17, 0x75, 0x09, 0xba, 0x01, 0x00
+.data1 	0x00, 0x00, 0x29, 0xfa, 0x89, 0xd7, 0x89, 0x7e
+.data1 	0x04, 0xc7, 0x06, 0x02, 0x00, 0x00, 0x00, 0xe9
+.data1 	0x53, 0x01, 0x00, 0x00, 0x8b, 0x56, 0x04, 0x39
+.data1 	0x56, 0x0c, 0x0f, 0x85, 0x9c, 0xfe, 0xff, 0xff
+.data1 	0xe9, 0x8e, 0xfe, 0xff, 0xff, 0x8b, 0x56, 0x04
+.data1 	0x39, 0x56, 0x0c, 0x0f, 0x84, 0x8b, 0xfe, 0xff
+.data1 	0xff, 0xe9, 0x7d, 0xfe, 0xff, 0xff, 0x8b, 0x56
+.data1 	0x04, 0x39, 0x56, 0x0c, 0x0f, 0x8d, 0x7a, 0xfe
+.data1 	0xff, 0xff, 0xe9, 0x6c, 0xfe, 0xff, 0xff, 0x8b
+.data1 	0x56, 0x04, 0x39, 0x56, 0x0c, 0x0f, 0x8e, 0x69
+.data1 	0xfe, 0xff, 0xff, 0xe9, 0x5b, 0xfe, 0xff, 0xff
+.data1 	0x8b, 0x56, 0x04, 0x39, 0x56, 0x0c, 0x0f, 0x8c
+.data1 	0x58, 0xfe, 0xff, 0xff, 0xe9, 0x4a, 0xfe, 0xff
+.data1 	0xff, 0x8b, 0x56, 0x04, 0x39, 0x56, 0x0c, 0x0f
+.data1 	0x8f, 0x47, 0xfe, 0xff, 0xff, 0xe9, 0x39, 0xfe
+.data1 	0xff, 0xff, 0x8b, 0x56, 0x0c, 0x01, 0x56, 0x04
+.data1 	0xe9, 0xe2, 0x00, 0x00, 0x00, 0x8b, 0x56, 0x04
+.data1 	0x2b, 0x56, 0x0c, 0x89, 0x56, 0x04, 0xe9, 0xd4
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x56, 0x0c, 0x0f, 0xaf
+.data1 	0x56, 0x04, 0x89, 0x56, 0x04, 0xe9, 0xc5, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7e, 0x0c, 0x00, 0x75, 0x0b
+.data1 	0x68, 0x24, 0x10, 0x00, 0x00, 0xe8, 0x1e, 0x59
+.data1 	0xff, 0xff, 0x59, 0x8b, 0x4e, 0x0c, 0x8b, 0x46
+.data1 	0x04, 0x99, 0xf7, 0xf9, 0x89, 0x46, 0x04, 0xe9
+.data1 	0xa3, 0x00, 0x00, 0x00, 0x83, 0x7e, 0x0c, 0x00
+.data1 	0x75, 0x0b, 0x68, 0x10, 0x10, 0x00, 0x00, 0xe8
+.data1 	0xfc, 0x58, 0xff, 0xff, 0x59, 0x8b, 0x4e, 0x0c
+.data1 	0x8b, 0x46, 0x04, 0x99, 0xf7, 0xf9, 0x89, 0x56
+.data1 	0x04, 0xe9, 0x81, 0x00, 0x00, 0x00, 0xff, 0x76
+.data1 	0x0c, 0xe8, 0xd2, 0x00, 0x00, 0x00, 0x59, 0x89
+.data1 	0x45, 0xb0, 0xff, 0x76, 0x04, 0xff, 0x75, 0xb0
+.data1 	0xe8, 0x85, 0x03, 0x00, 0x00, 0x59, 0x59, 0x85
+.data1 	0xc0, 0x74, 0x35, 0x0f, 0xbf, 0x05, 0x2c, 0x36
+.data1 	0x00, 0x00, 0x85, 0xc0, 0x7e, 0x18, 0x8b, 0x15
+.data1 	0xf4, 0x35, 0x00, 0x00, 0x89, 0x56, 0x04, 0x0f
+.data1 	0xbf, 0x05, 0x1a, 0x36, 0x00, 0x00, 0x03, 0x46
+.data1 	0x04, 0xc6, 0x00, 0x00, 0xeb, 0x41, 0x0f, 0xbf
+.data1 	0x05, 0x18, 0x36, 0x00, 0x00, 0x89, 0x46, 0x04
+.data1 	0xc7, 0x06, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x2f
+.data1 	0x0f, 0xbf, 0x05, 0x2c, 0x36, 0x00, 0x00, 0x85
+.data1 	0xc0, 0x7e, 0x08, 0x8b, 0x56, 0x04, 0xc6, 0x02
+.data1 	0x00, 0xeb, 0x1c, 0xc7, 0x46, 0x04, 0x00, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x06, 0x01, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x0d, 0xbb, 0x70, 0x0f, 0x00, 0x00, 0x8b
+.data1 	0x45, 0x08, 0xe9, 0x91, 0x4b, 0x00, 0x00, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x0c, 0x56, 0x57, 0x8b, 0x55, 0x08, 0x8a, 0x4a
+.data1 	0x01, 0x88, 0x4d, 0xf7, 0x8b, 0x75, 0x0c, 0x8b
+.data1 	0x3e, 0x85, 0xff, 0x74, 0x31, 0x0f, 0xbe, 0x47
+.data1 	0x01, 0x0f, 0xbe, 0x5d, 0xf7, 0x39, 0xd8, 0x75
+.data1 	0x20, 0xff, 0x75, 0x08, 0x57, 0xe8, 0xe6, 0x3e
+.data1 	0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x75, 0x11
+.data1 	0x89, 0xf2, 0x2b, 0x55, 0x0c, 0xb9, 0x04, 0x00
+.data1 	0x00, 0x00, 0x89, 0xd0, 0x99, 0xf7, 0xf9, 0xeb
+.data1 	0x0a, 0x83, 0xc6, 0x04, 0xeb, 0xc9, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x3c, 0x56, 0x57
+.data1 	0x8b, 0x7d, 0x08, 0x80, 0x3f, 0x5e, 0x75, 0x01
+.data1 	0x47, 0x57, 0xe8, 0xd9, 0x3e, 0x00, 0x00, 0x59
+.data1 	0xd1, 0xe0, 0x40, 0x50, 0xe8, 0x5e, 0x28, 0x00
+.data1 	0x00, 0x59, 0x89, 0xc6, 0x89, 0x45, 0xf4, 0x89
+.data1 	0x75, 0xec, 0x8d, 0x55, 0xce, 0x89, 0x55, 0xd8
+.data1 	0xc7, 0x45, 0xc8, 0x00, 0x00, 0x00, 0x00, 0xe9
+.data1 	0x4f, 0x02, 0x00, 0x00, 0xc6, 0x06, 0x00, 0xe9
+.data1 	0x5a, 0x02, 0x00, 0x00, 0xc6, 0x06, 0x02, 0x46
+.data1 	0xc7, 0x45, 0xe4, 0x01, 0x00, 0x00, 0x00, 0xe9
+.data1 	0x37, 0x02, 0x00, 0x00, 0x89, 0x75, 0xec, 0xc6
+.data1 	0x06, 0x03, 0x80, 0x3f, 0x5e, 0x75, 0x04, 0xc6
+.data1 	0x06, 0x04, 0x47, 0x46, 0xc7, 0x45, 0xe0, 0x01
+.data1 	0x00, 0x00, 0x00, 0x80, 0x3f, 0x5d, 0x75, 0x0a
+.data1 	0x83, 0x7d, 0xe0, 0x01, 0x0f, 0x85, 0x43, 0x00
+.data1 	0x00, 0x00, 0x80, 0x7f, 0x01, 0x2d, 0x75, 0x1a
+.data1 	0x80, 0x7f, 0x02, 0x5d, 0x74, 0x14, 0xc6, 0x06
+.data1 	0x2d, 0x46, 0x8a, 0x0f, 0x88, 0x0e, 0x46, 0x8a
+.data1 	0x4f, 0x02, 0x88, 0x0e, 0x46, 0x83, 0xc7, 0x03
+.data1 	0xeb, 0x1a, 0x80, 0x3f, 0x2d, 0x75, 0x0f, 0xc6
+.data1 	0x06, 0x2d, 0x46, 0xc6, 0x06, 0x2d, 0x46, 0xc6
+.data1 	0x06, 0x2d, 0x46, 0x47, 0xeb, 0x06, 0x8a, 0x07
+.data1 	0x47, 0x88, 0x06, 0x46, 0xc7, 0x45, 0xe0, 0x00
+.data1 	0x00, 0x00, 0x00, 0xeb, 0xae, 0x47, 0xc6, 0x06
+.data1 	0x00, 0x46, 0x89, 0xf2, 0x2b, 0x55, 0xec, 0x89
+.data1 	0x55, 0xe4, 0xe9, 0xbc, 0x01, 0x00, 0x00, 0x80
+.data1 	0x3f, 0x00, 0x0f, 0x85, 0xa2, 0x01, 0x00, 0x00
+.data1 	0xc6, 0x06, 0x08, 0x46, 0xe9, 0xaa, 0x01, 0x00
+.data1 	0x00, 0x83, 0x7d, 0xe4, 0x00, 0x0f, 0x84, 0x8f
+.data1 	0x01, 0x00, 0x00, 0xc7, 0x45, 0xdc, 0x09, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7d, 0xdc, 0x0a, 0x75, 0x07
+.data1 	0xb8, 0x03, 0x00, 0x00, 0x00, 0xeb, 0x05, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x00, 0x89, 0x45, 0xc4, 0x01
+.data1 	0xf0, 0x89, 0x45, 0xe8, 0x8b, 0x55, 0xe4, 0xf7
+.data1 	0xda, 0x01, 0xf2, 0x89, 0x55, 0xec, 0x4e, 0x89
+.data1 	0xf2, 0x03, 0x55, 0xc4, 0x8a, 0x0e, 0x88, 0x0a
+.data1 	0xff, 0x4d, 0xe4, 0x83, 0x7d, 0xe4, 0x00, 0x7f
+.data1 	0xed, 0x8b, 0x75, 0xec, 0x8b, 0x55, 0xdc, 0x88
+.data1 	0x16, 0x46, 0x83, 0x7d, 0xdc, 0x0a, 0x0f, 0x85
+.data1 	0x85, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xc4, 0x00
+.data1 	0x00, 0x00, 0x00, 0x0f, 0xbe, 0x07, 0x2d, 0x30
+.data1 	0x00, 0x00, 0x00, 0x3d, 0x09, 0x00, 0x00, 0x00
+.data1 	0x77, 0x14, 0x0f, 0xbe, 0x07, 0x47, 0x2d, 0x30
+.data1 	0x00, 0x00, 0x00, 0x6b, 0x5d, 0xc4, 0x0a, 0x01
+.data1 	0xc3, 0x89, 0x5d, 0xc4, 0xeb, 0xdd, 0x8b, 0x55
+.data1 	0xc4, 0x88, 0x16, 0x46, 0x80, 0x3f, 0x2c, 0x74
+.data1 	0x08, 0x8b, 0x55, 0xc4, 0x88, 0x16, 0x46, 0xeb
+.data1 	0x31, 0x47, 0xc7, 0x45, 0xc4, 0x00, 0x00, 0x00
+.data1 	0x00, 0x0f, 0xbe, 0x07, 0x2d, 0x30, 0x00, 0x00
+.data1 	0x00, 0x3d, 0x09, 0x00, 0x00, 0x00, 0x77, 0x14
+.data1 	0x0f, 0xbe, 0x07, 0x47, 0x2d, 0x30, 0x00, 0x00
+.data1 	0x00, 0x6b, 0x5d, 0xc4, 0x0a, 0x01, 0xc3, 0x89
+.data1 	0x5d, 0xc4, 0xeb, 0xdd, 0x8b, 0x55, 0xc4, 0x88
+.data1 	0x16, 0x46, 0x80, 0x3f, 0x5c, 0x75, 0x06, 0x47
+.data1 	0x80, 0x3f, 0x7d, 0x74, 0x0b, 0x68, 0x2c, 0x11
+.data1 	0x00, 0x00, 0xe8, 0x51, 0x56, 0xff, 0xff, 0x59
+.data1 	0x47, 0x8b, 0x75, 0xe8, 0xe9, 0xc2, 0x00, 0x00
+.data1 	0x00, 0x8a, 0x07, 0x47, 0x88, 0x45, 0xfb, 0x0f
+.data1 	0xbe, 0xc0, 0x3d, 0x28, 0x00, 0x00, 0x00, 0x75
+.data1 	0x35, 0xff, 0x45, 0xc8, 0x83, 0x7d, 0xc8, 0x09
+.data1 	0x7e, 0x0b, 0x68, 0x20, 0x11, 0x00, 0x00, 0xe8
+.data1 	0x24, 0x56, 0xff, 0xff, 0x59, 0xc6, 0x06, 0x05
+.data1 	0x46, 0x8b, 0x55, 0xc8, 0x88, 0x16, 0x46, 0x8b
+.data1 	0x55, 0xd8, 0x8b, 0x4d, 0xc8, 0x88, 0x0a, 0xff
+.data1 	0x45, 0xd8, 0xc7, 0x45, 0xe4, 0x00, 0x00, 0x00
+.data1 	0x00, 0xe9, 0x7d, 0x00, 0x00, 0x00, 0x80, 0x7d
+.data1 	0xfb, 0x29, 0x75, 0x2b, 0x8d, 0x55, 0xce, 0x39
+.data1 	0x55, 0xd8, 0x75, 0x0b, 0x68, 0x14, 0x11, 0x00
+.data1 	0x00, 0xe8, 0xea, 0x55, 0xff, 0xff, 0x59, 0xc6
+.data1 	0x06, 0x06, 0x46, 0xff, 0x4d, 0xd8, 0x8b, 0x55
+.data1 	0xd8, 0x8a, 0x0a, 0x88, 0x0e, 0x46, 0xc7, 0x45
+.data1 	0xe4, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x4c, 0x80
+.data1 	0x7d, 0xfb, 0x7b, 0x75, 0x0c, 0xc7, 0x45, 0xdc
+.data1 	0x0a, 0x00, 0x00, 0x00, 0xe9, 0xa1, 0xfe, 0xff
+.data1 	0xff, 0x0f, 0xbe, 0x45, 0xfb, 0x2d, 0x31, 0x00
+.data1 	0x00, 0x00, 0x3d, 0x09, 0x00, 0x00, 0x00, 0x73
+.data1 	0x19, 0xc6, 0x06, 0x07, 0x46, 0x0f, 0xbe, 0x45
+.data1 	0xfb, 0x2d, 0x30, 0x00, 0x00, 0x00, 0x88, 0x06
+.data1 	0x46, 0xc7, 0x45, 0xe4, 0x02, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x11, 0xc6, 0x06, 0x01, 0x46, 0x8a, 0x4d
+.data1 	0xfb, 0x88, 0x0e, 0x46, 0xc7, 0x45, 0xe4, 0x02
+.data1 	0x00, 0x00, 0x00, 0x8a, 0x07, 0x47, 0x88, 0x45
+.data1 	0xfb, 0x0f, 0xbe, 0xc0, 0xbb, 0xd0, 0x10, 0x00
+.data1 	0x00, 0xe9, 0xc6, 0x48, 0x00, 0x00, 0x8d, 0x55
+.data1 	0xce, 0x39, 0x55, 0xd8, 0x74, 0x0b, 0x68, 0x08
+.data1 	0x11, 0x00, 0x00, 0xe8, 0x60, 0x55, 0xff, 0xff
+.data1 	0x59, 0x8b, 0x55, 0xc8, 0x66, 0x89, 0x15, 0x2c
+.data1 	0x36, 0x00, 0x00, 0x8b, 0x45, 0xf4, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b, 0x55
+.data1 	0x0c, 0x89, 0x15, 0xf0, 0x35, 0x00, 0x00, 0xbe
+.data1 	0xf4, 0x35, 0x00, 0x00, 0x81, 0xfe, 0x14, 0x36
+.data1 	0x00, 0x00, 0x77, 0x0b, 0xc7, 0x06, 0x00, 0x00
+.data1 	0x00, 0x00, 0x83, 0xc6, 0x04, 0xeb, 0xed, 0xff
+.data1 	0x75, 0x0c, 0xff, 0x75, 0x08, 0xe8, 0x05, 0x00
+.data1 	0x00, 0x00, 0x59, 0x59, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x34, 0x56, 0x57, 0x8b
+.data1 	0x75, 0x08, 0x8b, 0x7d, 0x0c, 0xc7, 0x45, 0xf4
+.data1 	0x00, 0x00, 0x00, 0x00, 0x83, 0x7d, 0xf4, 0x00
+.data1 	0x0f, 0x84, 0x7c, 0x01, 0x00, 0x00, 0xff, 0x45
+.data1 	0xe8, 0x8b, 0x55, 0xec, 0x39, 0x55, 0xe8, 0x0f
+.data1 	0x8f, 0x7b, 0x01, 0x00, 0x00, 0x8b, 0x75, 0xe4
+.data1 	0xe9, 0x65, 0x01, 0x00, 0x00, 0x89, 0xfa, 0x2b
+.data1 	0x15, 0xf0, 0x35, 0x00, 0x00, 0x66, 0x89, 0x15
+.data1 	0x18, 0x36, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00
+.data1 	0x00, 0xe9, 0xad, 0x01, 0x00, 0x00, 0x0f, 0xbe
+.data1 	0x07, 0x47, 0x0f, 0xbe, 0x1e, 0x46, 0x39, 0xd8
+.data1 	0x74, 0xba, 0xe9, 0x49, 0x01, 0x00, 0x00, 0x8a
+.data1 	0x07, 0x47, 0x84, 0xc0, 0x75, 0xae, 0xe9, 0x3d
+.data1 	0x01, 0x00, 0x00, 0xc7, 0x45, 0xdc, 0x00, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x07, 0xc7, 0x45, 0xdc, 0x01
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x45, 0xd8, 0x00, 0x00
+.data1 	0x00, 0x00, 0x8a, 0x07, 0x47, 0x88, 0x45, 0xcf
+.data1 	0x80, 0x3e, 0x00, 0x74, 0x3b, 0x80, 0x3e, 0x2d
+.data1 	0x75, 0x21, 0x46, 0x0f, 0xbe, 0x06, 0x0f, 0xbe
+.data1 	0x5d, 0xcf, 0x39, 0xd8, 0x7f, 0x27, 0x46, 0x0f
+.data1 	0xbe, 0x06, 0x0f, 0xbe, 0x5d, 0xcf, 0x39, 0xd8
+.data1 	0x7c, 0x1b, 0xc7, 0x45, 0xd8, 0x01, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x12, 0x0f, 0xbe, 0x06, 0x0f, 0xbe
+.data1 	0x5d, 0xcf, 0x39, 0xd8, 0x75, 0x07, 0xc7, 0x45
+.data1 	0xd8, 0x01, 0x00, 0x00, 0x00, 0x46, 0xeb, 0xc0
+.data1 	0x46, 0x8b, 0x55, 0xdc, 0x39, 0x55, 0xd8, 0x0f
+.data1 	0x84, 0xd3, 0x00, 0x00, 0x00, 0x80, 0x7d, 0xcf
+.data1 	0x00, 0x0f, 0x85, 0x35, 0xff, 0xff, 0xff, 0xe9
+.data1 	0xc4, 0x00, 0x00, 0x00, 0x0f, 0xbe, 0x06, 0x46
+.data1 	0x89, 0x3c, 0x85, 0xf0, 0x35, 0x00, 0x00, 0xe9
+.data1 	0x20, 0xff, 0xff, 0xff, 0x0f, 0xbe, 0x06, 0x89
+.data1 	0xfa, 0x2b, 0x14, 0x85, 0xf0, 0x35, 0x00, 0x00
+.data1 	0x89, 0xd0, 0x0f, 0xbf, 0xc0, 0x0f, 0xbe, 0x1e
+.data1 	0x66, 0x89, 0x04, 0x5d, 0x18, 0x36, 0x00, 0x00
+.data1 	0x46, 0xe9, 0xfe, 0xfe, 0xff, 0xff, 0x0f, 0xbe
+.data1 	0x06, 0x8b, 0x14, 0x85, 0xf0, 0x35, 0x00, 0x00
+.data1 	0x89, 0x55, 0xd4, 0x0f, 0xbe, 0x06, 0x46, 0x0f
+.data1 	0xbf, 0x04, 0x45, 0x18, 0x36, 0x00, 0x00, 0x89
+.data1 	0x45, 0xd0, 0xff, 0x4d, 0xd0, 0x0f, 0x88, 0xd9
+.data1 	0xfe, 0xff, 0xff, 0x0f, 0xbe, 0x07, 0x47, 0x8b
+.data1 	0x5d, 0xd4, 0xff, 0x45, 0xd4, 0x0f, 0xbe, 0x1b
+.data1 	0x39, 0xd8, 0x74, 0xe6, 0xe9, 0x57, 0x00, 0x00
+.data1 	0x00, 0x80, 0x3f, 0x00, 0x0f, 0x84, 0xba, 0xfe
+.data1 	0xff, 0xff, 0xeb, 0x4c, 0xc7, 0x45, 0xf0, 0x00
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x45, 0xec, 0xff, 0x7f
+.data1 	0x00, 0x00, 0xeb, 0x19, 0x0f, 0xbe, 0x06, 0x46
+.data1 	0x89, 0x45, 0xf0, 0x0f, 0xbe, 0x1e, 0x46, 0x89
+.data1 	0x5d, 0xec, 0x85, 0xdb, 0x75, 0x07, 0xc7, 0x45
+.data1 	0xec, 0xff, 0x7f, 0x00, 0x00, 0x89, 0x75, 0xe4
+.data1 	0x89, 0x7d, 0xe0, 0xc7, 0x45, 0xe8, 0x00, 0x00
+.data1 	0x00, 0x00, 0xff, 0x45, 0xf4, 0xe9, 0x7a, 0xfe
+.data1 	0xff, 0xff, 0x0f, 0xbe, 0x06, 0x46, 0xbb, 0x38
+.data1 	0x11, 0x00, 0x00, 0xe9, 0x98, 0x46, 0x00, 0x00
+.data1 	0x83, 0x7d, 0xf4, 0x00, 0x75, 0x04, 0x31, 0xc0
+.data1 	0xeb, 0x49, 0xc7, 0x45, 0xd0, 0x01, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xe4, 0x80, 0x3a, 0x07, 0x75
+.data1 	0x0f, 0x0f, 0xbe, 0x42, 0x01, 0x0f, 0xbf, 0x04
+.data1 	0x45, 0x18, 0x36, 0x00, 0x00, 0x89, 0x45, 0xd0
+.data1 	0xff, 0x4d, 0xe8, 0x8b, 0x55, 0xf0, 0x39, 0x55
+.data1 	0xe8, 0x7c, 0x1e, 0x8b, 0x55, 0xe8, 0x0f, 0xaf
+.data1 	0x55, 0xd0, 0x03, 0x55, 0xe0, 0x52, 0x56, 0xe8
+.data1 	0x13, 0xfe, 0xff, 0xff, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x74, 0xde, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x02, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0x3d, 0xac, 0x2b, 0x00
+.data1 	0x00, 0x00, 0x74, 0x20, 0xff, 0x35, 0xac, 0x2b
+.data1 	0x00, 0x00, 0xff, 0x35, 0xec, 0x29, 0x00, 0x00
+.data1 	0x6a, 0x01, 0xe8, 0xc9, 0x38, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xc7, 0x05, 0xac, 0x2b, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x0f, 0xbe, 0x45, 0x08, 0x8b, 0x15, 0xec
+.data1 	0x29, 0x00, 0x00, 0x03, 0x15, 0xac, 0x2b, 0x00
+.data1 	0x00, 0x88, 0x02, 0x8b, 0x15, 0xac, 0x2b, 0x00
+.data1 	0x00, 0x42, 0x89, 0x15, 0xac, 0x2b, 0x00, 0x00
+.data1 	0x8b, 0x0d, 0xb0, 0x2b, 0x00, 0x00, 0x49, 0x39
+.data1 	0xca, 0x72, 0x22, 0xa1, 0xb0, 0x2b, 0x00, 0x00
+.data1 	0x05, 0x00, 0x01, 0x00, 0x00, 0xa3, 0xb0, 0x2b
+.data1 	0x00, 0x00, 0x50, 0xff, 0x35, 0xec, 0x29, 0x00
+.data1 	0x00, 0xe8, 0x1e, 0x24, 0x00, 0x00, 0x59, 0x59
+.data1 	0xa3, 0xec, 0x29, 0x00, 0x00, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x8b, 0x55, 0x08, 0x80, 0x3a, 0x00
+.data1 	0x74, 0x0f, 0xff, 0x45, 0x08, 0x0f, 0xb6, 0x02
+.data1 	0x50, 0xe8, 0x98, 0xff, 0xff, 0xff, 0x59, 0xeb
+.data1 	0xe9, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x80, 0x7d
+.data1 	0x08, 0x7f, 0x75, 0x15, 0x6a, 0x5e, 0xe8, 0x83
+.data1 	0xff, 0xff, 0xff, 0x59, 0x6a, 0x3f, 0xe8, 0x7b
+.data1 	0xff, 0xff, 0xff, 0x59, 0xe9, 0x61, 0x00, 0x00
+.data1 	0x00, 0x80, 0x7d, 0x08, 0x00, 0x74, 0x21, 0x0f
+.data1 	0xb6, 0x55, 0x08, 0x83, 0xfa, 0x20, 0x7d, 0x18
+.data1 	0x6a, 0x5e, 0xe8, 0x5f, 0xff, 0xff, 0xff, 0x59
+.data1 	0x0f, 0xb6, 0x55, 0x08, 0x83, 0xc2, 0x40, 0x52
+.data1 	0xe8, 0x51, 0xff, 0xff, 0xff, 0x59, 0xeb, 0x3a
+.data1 	0x83, 0x3d, 0x2c, 0x25, 0x00, 0x00, 0x00, 0x74
+.data1 	0x26, 0xf6, 0x45, 0x08, 0x80, 0x74, 0x20, 0x6a
+.data1 	0x4d, 0xe8, 0x38, 0xff, 0xff, 0xff, 0x59, 0x6a
+.data1 	0x2d, 0xe8, 0x30, 0xff, 0xff, 0xff, 0x59, 0x0f
+.data1 	0xb6, 0x55, 0x08, 0x83, 0xe2, 0x7f, 0x52, 0xe8
+.data1 	0x22, 0xff, 0xff, 0xff, 0x59, 0xeb, 0x0b, 0x0f
+.data1 	0xb6, 0x45, 0x08, 0x50, 0xe8, 0x15, 0xff, 0xff
+.data1 	0xff, 0x59, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b
+.data1 	0x55, 0x08, 0x80, 0x3a, 0x00, 0x74, 0x0f, 0xff
+.data1 	0x45, 0x08, 0x0f, 0xb6, 0x02, 0x50, 0xe8, 0x68
+.data1 	0xff, 0xff, 0xff, 0x59, 0xeb, 0xe9, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0xe8, 0xbd
+.data1 	0xfe, 0xff, 0xff, 0x83, 0x3d, 0xa0, 0x2b, 0x00
+.data1 	0x00, 0x00, 0x74, 0x11, 0xc7, 0x05, 0xa0, 0x2b
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x9c
+.data1 	0x2b, 0x00, 0x00, 0xeb, 0x38, 0x8b, 0x15, 0x24
+.data1 	0x25, 0x00, 0x00, 0x80, 0x3a, 0x00, 0x74, 0x0b
+.data1 	0xff, 0x05, 0x24, 0x25, 0x00, 0x00, 0x0f, 0xb6
+.data1 	0x02, 0xeb, 0x22, 0x6a, 0x01, 0x8d, 0x45, 0xff
+.data1 	0x50, 0x6a, 0x00, 0xe8, 0x30, 0x37, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x3d, 0x01, 0x00, 0x00, 0x00
+.data1 	0x75, 0x06, 0x0f, 0xb6, 0x45, 0xff, 0xeb, 0x05
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0xff, 0x4d, 0x08, 0x78, 0x21, 0x83
+.data1 	0x3d, 0xb4, 0x2b, 0x00, 0x00, 0x00, 0x74, 0x0e
+.data1 	0xff, 0x35, 0xb4, 0x2b, 0x00, 0x00, 0xe8, 0xcc
+.data1 	0xfe, 0xff, 0xff, 0x59, 0xeb, 0xe4, 0x6a, 0x08
+.data1 	0xe8, 0x71, 0xfe, 0xff, 0xff, 0x59, 0xeb, 0xda
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x81, 0xec, 0x08
+.data1 	0x08, 0x00, 0x00, 0x56, 0x83, 0x3d, 0xc8, 0x2b
+.data1 	0x00, 0x00, 0x00, 0x0f, 0x85, 0xd5, 0x00, 0x00
+.data1 	0x00, 0xff, 0x05, 0xc8, 0x2b, 0x00, 0x00, 0x31
+.data1 	0xd2, 0x89, 0x15, 0xbc, 0x2b, 0x00, 0x00, 0x89
+.data1 	0x15, 0xb8, 0x2b, 0x00, 0x00, 0x8d, 0x95, 0xfc
+.data1 	0xf7, 0xff, 0xff, 0x89, 0x95, 0xf8, 0xf7, 0xff
+.data1 	0xff, 0x68, 0x84, 0x11, 0x00, 0x00, 0xe8, 0xad
+.data1 	0x20, 0x00, 0x00, 0x59, 0x89, 0xc6, 0x85, 0xc0
+.data1 	0x75, 0x05, 0xbe, 0x7c, 0x11, 0x00, 0x00, 0x56
+.data1 	0x8d, 0x85, 0xfc, 0xf7, 0xff, 0xff, 0x50, 0xe8
+.data1 	0xe4, 0x29, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x79, 0x19, 0xc7, 0x05, 0xb8, 0x2b, 0x00, 0x00
+.data1 	0x50, 0x00, 0x00, 0x00, 0xc7, 0x05, 0xbc, 0x2b
+.data1 	0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xe9, 0x73
+.data1 	0x00, 0x00, 0x00, 0x8d, 0x85, 0xf8, 0xf7, 0xff
+.data1 	0xff, 0x50, 0x68, 0x78, 0x11, 0x00, 0x00, 0xe8
+.data1 	0xe7, 0x2b, 0x00, 0x00, 0x59, 0x59, 0xa3, 0xb4
+.data1 	0x2b, 0x00, 0x00, 0x85, 0xc0, 0x74, 0x11, 0xff
+.data1 	0x35, 0xb4, 0x2b, 0x00, 0x00, 0xe8, 0x1e, 0x29
+.data1 	0x00, 0x00, 0x59, 0xa3, 0xb4, 0x2b, 0x00, 0x00
+.data1 	0x68, 0x74, 0x11, 0x00, 0x00, 0xe8, 0x09, 0x2b
+.data1 	0x00, 0x00, 0x59, 0xa3, 0xb8, 0x2b, 0x00, 0x00
+.data1 	0x68, 0x70, 0x11, 0x00, 0x00, 0xe8, 0xf9, 0x2a
+.data1 	0x00, 0x00, 0x59, 0xa3, 0xbc, 0x2b, 0x00, 0x00
+.data1 	0x83, 0x3d, 0xb8, 0x2b, 0x00, 0x00, 0x00, 0x7e
+.data1 	0x09, 0x83, 0x3d, 0xbc, 0x2b, 0x00, 0x00, 0x00
+.data1 	0x7f, 0x14, 0xc7, 0x05, 0xb8, 0x2b, 0x00, 0x00
+.data1 	0x50, 0x00, 0x00, 0x00, 0xc7, 0x05, 0xbc, 0x2b
+.data1 	0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x20, 0x56
+.data1 	0x57, 0xc7, 0x45, 0xe4, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0xf6, 0x39, 0x75, 0x08, 0x7e, 0x19, 0x8b
+.data1 	0x55, 0x0c, 0xff, 0x34, 0xb2, 0xe8, 0x26, 0x37
+.data1 	0x00, 0x00, 0x59, 0x89, 0xc7, 0x39, 0x45, 0xe4
+.data1 	0x7d, 0x03, 0x89, 0x7d, 0xe4, 0x46, 0xeb, 0xe2
+.data1 	0xba, 0x03, 0x00, 0x00, 0x00, 0x03, 0x55, 0xe4
+.data1 	0x89, 0xd1, 0xa1, 0xb8, 0x2b, 0x00, 0x00, 0x99
+.data1 	0xf7, 0xf9, 0x89, 0x45, 0xe0, 0x68, 0x28, 0x25
+.data1 	0x00, 0x00, 0xe8, 0x80, 0xfd, 0xff, 0xff, 0x59
+.data1 	0x8b, 0x45, 0x08, 0x99, 0xf7, 0x7d, 0xe0, 0x40
+.data1 	0x89, 0x45, 0xe8, 0x31, 0xf6, 0x39, 0x75, 0xe8
+.data1 	0x0f, 0x8e, 0x6f, 0x00, 0x00, 0x00, 0x89, 0xf7
+.data1 	0x39, 0x7d, 0x08, 0x0f, 0x8e, 0x56, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x0c, 0x8b, 0x14, 0xba, 0x89
+.data1 	0x55, 0xfc, 0x52, 0xe8, 0xc8, 0x36, 0x00, 0x00
+.data1 	0x59, 0x89, 0x45, 0xec, 0x89, 0x45, 0xf0, 0xff
+.data1 	0x4d, 0xf0, 0x78, 0x12, 0x8b, 0x55, 0xfc, 0x0f
+.data1 	0xb6, 0x02, 0x50, 0xe8, 0xe6, 0xfc, 0xff, 0xff
+.data1 	0x59, 0xff, 0x45, 0xfc, 0xeb, 0xe9, 0x8b, 0x55
+.data1 	0xe8, 0x01, 0xfa, 0x39, 0x55, 0x08, 0x7e, 0x1a
+.data1 	0xff, 0x45, 0xec, 0xba, 0x03, 0x00, 0x00, 0x00
+.data1 	0x03, 0x55, 0xe4, 0x39, 0x55, 0xec, 0x7d, 0x0a
+.data1 	0x6a, 0x20, 0xe8, 0xbf, 0xfc, 0xff, 0xff, 0x59
+.data1 	0xeb, 0xe6, 0x03, 0x7d, 0xe8, 0xeb, 0xa1, 0x68
+.data1 	0x28, 0x25, 0x00, 0x00, 0xe8, 0xfe, 0xfc, 0xff
+.data1 	0xff, 0x59, 0x46, 0xeb, 0x88, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x56, 0x57, 0x6a, 0x0d
+.data1 	0xe8, 0x99, 0xfc, 0xff, 0xff, 0x59, 0xff, 0x35
+.data1 	0xe4, 0x29, 0x00, 0x00, 0xe8, 0xde, 0xfc, 0xff
+.data1 	0xff, 0x59, 0x8b, 0x3d, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x8b, 0x35, 0xe0, 0x29, 0x00, 0x00, 0x4f, 0x78
+.data1 	0x0d, 0x0f, 0xb6, 0x06, 0x50, 0xe8, 0xe1, 0xfc
+.data1 	0xff, 0xff, 0x59, 0x46, 0xeb, 0xf0, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0x3d, 0xb4
+.data1 	0x2b, 0x00, 0x00, 0x00, 0x74, 0x0e, 0xff, 0x35
+.data1 	0xb4, 0x2b, 0x00, 0x00, 0xe8, 0xa6, 0xfc, 0xff
+.data1 	0xff, 0x59, 0xeb, 0x08, 0x6a, 0x08, 0xe8, 0x4b
+.data1 	0xfc, 0xff, 0xff, 0x59, 0x83, 0x3d, 0x98, 0x2b
+.data1 	0x00, 0x00, 0x00, 0x0f, 0x84, 0xa7, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x15, 0x98, 0x2b, 0x00, 0x00, 0x4a
+.data1 	0x03, 0x15, 0xe0, 0x29, 0x00, 0x00, 0x80, 0x3a
+.data1 	0x00, 0x74, 0x3c, 0x8b, 0x15, 0x98, 0x2b, 0x00
+.data1 	0x00, 0x4a, 0x03, 0x15, 0xe0, 0x29, 0x00, 0x00
+.data1 	0x0f, 0xb6, 0x0a, 0x83, 0xf9, 0x20, 0x7d, 0x27
+.data1 	0x83, 0x3d, 0xb4, 0x2b, 0x00, 0x00, 0x00, 0x74
+.data1 	0x11, 0xff, 0x35, 0xb4, 0x2b, 0x00, 0x00, 0xe8
+.data1 	0x53, 0xfc, 0xff, 0xff, 0x59, 0xe9, 0x66, 0x00
+.data1 	0x00, 0x00, 0x6a, 0x08, 0xe8, 0xf5, 0xfb, 0xff
+.data1 	0xff, 0x59, 0xe9, 0x59, 0x00, 0x00, 0x00, 0x83
+.data1 	0x3d, 0x2c, 0x25, 0x00, 0x00, 0x00, 0x74, 0x50
+.data1 	0x8b, 0x15, 0x98, 0x2b, 0x00, 0x00, 0x4a, 0x03
+.data1 	0x15, 0xe0, 0x29, 0x00, 0x00, 0xf6, 0x02, 0x80
+.data1 	0x74, 0x3e, 0x83, 0x3d, 0xb4, 0x2b, 0x00, 0x00
+.data1 	0x00, 0x74, 0x0e, 0xff, 0x35, 0xb4, 0x2b, 0x00
+.data1 	0x00, 0xe8, 0x11, 0xfc, 0xff, 0xff, 0x59, 0xeb
+.data1 	0x08, 0x6a, 0x08, 0xe8, 0xb6, 0xfb, 0xff, 0xff
+.data1 	0x59, 0x83, 0x3d, 0xb4, 0x2b, 0x00, 0x00, 0x00
+.data1 	0x74, 0x0e, 0xff, 0x35, 0xb4, 0x2b, 0x00, 0x00
+.data1 	0xe8, 0xf2, 0xfb, 0xff, 0xff, 0x59, 0xeb, 0x08
+.data1 	0x6a, 0x08, 0xe8, 0x97, 0xfb, 0xff, 0xff, 0x59
+.data1 	0x83, 0x7d, 0x08, 0x02, 0x75, 0x06, 0xff, 0x0d
+.data1 	0x98, 0x2b, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x8b, 0x15, 0xe0, 0x29, 0x00, 0x00, 0x03
+.data1 	0x15, 0x98, 0x2b, 0x00, 0x00, 0x0f, 0xb6, 0x02
+.data1 	0x50, 0xe8, 0xdd, 0xfb, 0xff, 0xff, 0x59, 0x83
+.data1 	0x7d, 0x08, 0x02, 0x75, 0x06, 0xff, 0x05, 0x98
+.data1 	0x2b, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x6a, 0x07, 0xe8, 0x57, 0xfb, 0xff, 0xff, 0x59
+.data1 	0xe8, 0x23, 0xfb, 0xff, 0xff, 0xb8, 0x04, 0x00
+.data1 	0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x04, 0xc6, 0x45, 0xfc, 0x5f, 0x8b, 0x55
+.data1 	0x08, 0x88, 0x55, 0xfd, 0xc6, 0x45, 0xfe, 0x5f
+.data1 	0xc6, 0x45, 0xff, 0x00, 0x8d, 0x45, 0xfc, 0x50
+.data1 	0xe8, 0xab, 0x1d, 0x00, 0x00, 0x59, 0xa3, 0x24
+.data1 	0x25, 0x00, 0x00, 0x85, 0xc0, 0x75, 0x11, 0xc7
+.data1 	0x05, 0x24, 0x25, 0x00, 0x00, 0x20, 0x25, 0x00
+.data1 	0x00, 0xe8, 0xaf, 0xff, 0xff, 0xff, 0xeb, 0x05
+.data1 	0xb8, 0x04, 0x00, 0x00, 0x00, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0x57, 0x31, 0xff, 0x8b, 0x15
+.data1 	0xe0, 0x29, 0x00, 0x00, 0x8b, 0x35, 0x98, 0x2b
+.data1 	0x00, 0x00, 0x01, 0xd6, 0x8b, 0x15, 0x8c, 0x2b
+.data1 	0x00, 0x00, 0x39, 0x15, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x7d, 0x2a, 0x80, 0x3e, 0x20, 0x74, 0x0e, 0x0f
+.data1 	0xb6, 0x16, 0x81, 0xc2, 0xe1, 0x26, 0x00, 0x00
+.data1 	0xf6, 0x02, 0x07, 0x75, 0x17, 0x83, 0x7d, 0x08
+.data1 	0x02, 0x75, 0x08, 0x6a, 0x04, 0xe8, 0x3c, 0xff
+.data1 	0xff, 0xff, 0x59, 0xff, 0x05, 0x98, 0x2b, 0x00
+.data1 	0x00, 0x46, 0xeb, 0xc8, 0x8b, 0x15, 0x8c, 0x2b
+.data1 	0x00, 0x00, 0x39, 0x15, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x7d, 0x25, 0x0f, 0xb6, 0x16, 0x81, 0xc2, 0xe1
+.data1 	0x26, 0x00, 0x00, 0xf6, 0x02, 0x07, 0x74, 0x17
+.data1 	0x83, 0x7d, 0x08, 0x02, 0x75, 0x08, 0x6a, 0x04
+.data1 	0xe8, 0x09, 0xff, 0xff, 0xff, 0x59, 0xff, 0x05
+.data1 	0x98, 0x2b, 0x00, 0x00, 0x46, 0xeb, 0xcd, 0x8b
+.data1 	0x15, 0x8c, 0x2b, 0x00, 0x00, 0x39, 0x15, 0x98
+.data1 	0x2b, 0x00, 0x00, 0x74, 0x0d, 0x47, 0x39, 0x3d
+.data1 	0x88, 0x2b, 0x00, 0x00, 0x0f, 0x8f, 0x6c, 0xff
+.data1 	0xff, 0xff, 0xb8, 0x04, 0x00, 0x00, 0x00, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x0c, 0x56, 0x57, 0x6a, 0x04, 0xe8, 0x4d, 0xff
+.data1 	0xff, 0xff, 0x59, 0x8b, 0x15, 0x98, 0x2b, 0x00
+.data1 	0x00, 0x39, 0x15, 0x94, 0x2b, 0x00, 0x00, 0x0f
+.data1 	0x84, 0x8c, 0x00, 0x00, 0x00, 0x2b, 0x15, 0x94
+.data1 	0x2b, 0x00, 0x00, 0x89, 0x55, 0xf4, 0x79, 0x03
+.data1 	0xf7, 0x5d, 0xf4, 0x8b, 0x15, 0x94, 0x2b, 0x00
+.data1 	0x00, 0x89, 0x15, 0x98, 0x2b, 0x00, 0x00, 0x03
+.data1 	0x55, 0xf4, 0x89, 0x55, 0xf8, 0x39, 0x15, 0x8c
+.data1 	0x2b, 0x00, 0x00, 0x7d, 0x09, 0x8b, 0x15, 0x8c
+.data1 	0x2b, 0x00, 0x00, 0x89, 0x55, 0xf8, 0x8b, 0x3d
+.data1 	0x98, 0x2b, 0x00, 0x00, 0x8b, 0x15, 0xe0, 0x29
+.data1 	0x00, 0x00, 0x89, 0xfe, 0x01, 0xd6, 0x39, 0x7d
+.data1 	0xf8, 0x0f, 0x8e, 0x42, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x75, 0x19, 0x0f, 0xb6, 0x16
+.data1 	0x83, 0xea, 0x61, 0x83, 0xfa, 0x1a, 0x73, 0x25
+.data1 	0x0f, 0xb6, 0x06, 0x50, 0xe8, 0x87, 0x24, 0x00
+.data1 	0x00, 0x59, 0x88, 0x06, 0xeb, 0x17, 0x0f, 0xb6
+.data1 	0x16, 0x83, 0xea, 0x41, 0x83, 0xfa, 0x1a, 0x73
+.data1 	0x0c, 0x0f, 0xb6, 0x06, 0x50, 0xe8, 0x4e, 0x24
+.data1 	0x00, 0x00, 0x59, 0x88, 0x06, 0x6a, 0x02, 0xe8
+.data1 	0x32, 0xfe, 0xff, 0xff, 0x59, 0x47, 0x46, 0xeb
+.data1 	0xb5, 0xb8, 0x04, 0x00, 0x00, 0x00, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x6a, 0x01, 0xe8
+.data1 	0x3f, 0xff, 0xff, 0xff, 0x59, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x6a, 0x00, 0xe8, 0x32, 0xff, 0xff
+.data1 	0xff, 0x59, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x04, 0x56, 0x57, 0xc7, 0x45, 0xfc, 0x00
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x35, 0x98, 0x2b, 0x00
+.data1 	0x00, 0x8b, 0x15, 0xe0, 0x29, 0x00, 0x00, 0x89
+.data1 	0xf7, 0x01, 0xd7, 0x39, 0x35, 0x8c, 0x2b, 0x00
+.data1 	0x00, 0x0f, 0x8c, 0x48, 0x00, 0x00, 0x00, 0x6a
+.data1 	0x20, 0xe8, 0x60, 0xf9, 0xff, 0xff, 0x59, 0x80
+.data1 	0x3f, 0x00, 0x74, 0x15, 0x0f, 0xb6, 0x17, 0x83
+.data1 	0xfa, 0x20, 0x7d, 0x0d, 0x6a, 0x20, 0xe8, 0x4b
+.data1 	0xf9, 0xff, 0xff, 0x59, 0xff, 0x45, 0xfc, 0xeb
+.data1 	0x22, 0x83, 0x3d, 0x2c, 0x25, 0x00, 0x00, 0x00
+.data1 	0x74, 0x19, 0xf6, 0x07, 0x80, 0x74, 0x14, 0x6a
+.data1 	0x20, 0xe8, 0x30, 0xf9, 0xff, 0xff, 0x59, 0x6a
+.data1 	0x20, 0xe8, 0x28, 0xf9, 0xff, 0xff, 0x59, 0x83
+.data1 	0x45, 0xfc, 0x02, 0x46, 0x47, 0xeb, 0xac, 0x03
+.data1 	0x75, 0xfc, 0x39, 0x35, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x7d, 0x22, 0x83, 0x3d, 0xb4, 0x2b, 0x00, 0x00
+.data1 	0x00, 0x74, 0x0e, 0xff, 0x35, 0xb4, 0x2b, 0x00
+.data1 	0x00, 0xe8, 0x51, 0xf9, 0xff, 0xff, 0x59, 0xeb
+.data1 	0x08, 0x6a, 0x08, 0xe8, 0xf6, 0xf8, 0xff, 0xff
+.data1 	0x59, 0x4e, 0xeb, 0xd6, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0xff, 0x35, 0xe4, 0x29, 0x00
+.data1 	0x00, 0xe8, 0xaa, 0x32, 0x00, 0x00, 0x59, 0xf7
+.data1 	0xd8, 0xa3, 0x98, 0x2b, 0x00, 0x00, 0x6a, 0x0d
+.data1 	0xe8, 0xd1, 0xf8, 0xff, 0xff, 0x59, 0xe8, 0x39
+.data1 	0xff, 0xff, 0xff, 0xc7, 0x05, 0x98, 0x2b, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x05, 0x8c
+.data1 	0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x15, 0xe0, 0x29, 0x00, 0x00, 0xc6, 0x02, 0x00
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x10
+.data1 	0x56, 0x57, 0xff, 0x75, 0x08, 0xe8, 0x66, 0x32
+.data1 	0x00, 0x00, 0x59, 0x89, 0xc6, 0x89, 0xf2, 0x03
+.data1 	0x15, 0x8c, 0x2b, 0x00, 0x00, 0x39, 0x15, 0xa8
+.data1 	0x2b, 0x00, 0x00, 0x77, 0x61, 0x89, 0xf2, 0x03
+.data1 	0x15, 0xa8, 0x2b, 0x00, 0x00, 0x83, 0xc2, 0x40
+.data1 	0x52, 0xe8, 0xd1, 0x1b, 0x00, 0x00, 0x59, 0x89
+.data1 	0x45, 0xf4, 0x85, 0xc0, 0x75, 0x0a, 0xb8, 0x04
+.data1 	0x00, 0x00, 0x00, 0xe9, 0xd5, 0x00, 0x00, 0x00
+.data1 	0x83, 0x3d, 0xa8, 0x2b, 0x00, 0x00, 0x00, 0x74
+.data1 	0x23, 0xff, 0x35, 0xa8, 0x2b, 0x00, 0x00, 0xff
+.data1 	0x35, 0xe0, 0x29, 0x00, 0x00, 0xff, 0x75, 0xf4
+.data1 	0xe8, 0x73, 0x31, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xff, 0x35, 0xe0, 0x29, 0x00, 0x00, 0xe8, 0xab
+.data1 	0x1d, 0x00, 0x00, 0x59, 0x8b, 0x55, 0xf4, 0x89
+.data1 	0x15, 0xe0, 0x29, 0x00, 0x00, 0x8d, 0x56, 0x40
+.data1 	0x01, 0x15, 0xa8, 0x2b, 0x00, 0x00, 0x8b, 0x15
+.data1 	0x98, 0x2b, 0x00, 0x00, 0x03, 0x15, 0xe0, 0x29
+.data1 	0x00, 0x00, 0x89, 0x55, 0xf0, 0x8b, 0x15, 0x8c
+.data1 	0x2b, 0x00, 0x00, 0x2b, 0x15, 0x98, 0x2b, 0x00
+.data1 	0x00, 0x89, 0xd7, 0x4f, 0x78, 0x12, 0x8b, 0x55
+.data1 	0xf0, 0x01, 0xfa, 0x89, 0xf1, 0x01, 0xf9, 0x03
+.data1 	0x4d, 0xf0, 0x8a, 0x12, 0x88, 0x11, 0xeb, 0xeb
+.data1 	0x8b, 0x15, 0xe0, 0x29, 0x00, 0x00, 0x03, 0x15
+.data1 	0x98, 0x2b, 0x00, 0x00, 0x56, 0xff, 0x75, 0x08
+.data1 	0x52, 0xe8, 0x0a, 0x31, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x8b, 0x15, 0x8c, 0x2b, 0x00, 0x00, 0x01
+.data1 	0xf2, 0x89, 0x15, 0x8c, 0x2b, 0x00, 0x00, 0x03
+.data1 	0x15, 0xe0, 0x29, 0x00, 0x00, 0xc6, 0x02, 0x00
+.data1 	0x8b, 0x15, 0xe0, 0x29, 0x00, 0x00, 0x03, 0x15
+.data1 	0x98, 0x2b, 0x00, 0x00, 0x52, 0xe8, 0xa2, 0xf8
+.data1 	0xff, 0xff, 0x59, 0x8b, 0x15, 0x98, 0x2b, 0x00
+.data1 	0x00, 0x01, 0xf2, 0x89, 0x15, 0x98, 0x2b, 0x00
+.data1 	0x00, 0x39, 0x15, 0x8c, 0x2b, 0x00, 0x00, 0x75
+.data1 	0x07, 0xb8, 0x04, 0x00, 0x00, 0x00, 0xeb, 0x05
+.data1 	0xb8, 0x02, 0x00, 0x00, 0x00, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x68, 0x28, 0x25, 0x00
+.data1 	0x00, 0xe8, 0xd1, 0xf7, 0xff, 0xff, 0x59, 0xff
+.data1 	0x35, 0xe4, 0x29, 0x00, 0x00, 0xe8, 0xc5, 0xf7
+.data1 	0xff, 0xff, 0x59, 0xff, 0x35, 0xe0, 0x29, 0x00
+.data1 	0x00, 0xe8, 0x56, 0xf8, 0xff, 0xff, 0x59, 0xb8
+.data1 	0x02, 0x00, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x31, 0xc0, 0x83, 0x3d, 0x2c, 0x25, 0x00
+.data1 	0x00, 0x00, 0x0f, 0x94, 0xc0, 0xa3, 0x2c, 0x25
+.data1 	0x00, 0x00, 0xe8, 0xba, 0xff, 0xff, 0xff, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x8b, 0x15, 0xf0, 0x29
+.data1 	0x00, 0x00, 0x4a, 0x39, 0x15, 0xf4, 0x29, 0x00
+.data1 	0x00, 0x7c, 0x04, 0x31, 0xc0, 0xeb, 0x13, 0xff
+.data1 	0x05, 0xf4, 0x29, 0x00, 0x00, 0x8b, 0x15, 0xf4
+.data1 	0x29, 0x00, 0x00, 0x8b, 0x04, 0x95, 0xf8, 0x29
+.data1 	0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0x3d, 0xf4, 0x29, 0x00, 0x00, 0x00, 0x75, 0x04
+.data1 	0x31, 0xc0, 0xeb, 0x14, 0x8b, 0x15, 0xf4, 0x29
+.data1 	0x00, 0x00, 0x4a, 0x89, 0x15, 0xf4, 0x29, 0x00
+.data1 	0x00, 0x8b, 0x04, 0x95, 0xf8, 0x29, 0x00, 0x00
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0x7d, 0x08
+.data1 	0x00, 0x75, 0x07, 0xe8, 0x85, 0xfb, 0xff, 0xff
+.data1 	0xeb, 0x27, 0xc7, 0x05, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe8, 0x30, 0xfa, 0xff
+.data1 	0xff, 0xe8, 0x3e, 0xfd, 0xff, 0xff, 0xc7, 0x05
+.data1 	0x8c, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x12, 0xfe, 0xff, 0xff
+.data1 	0x59, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x04, 0x56, 0x31, 0xf6, 0xff, 0x55, 0x08, 0x89
+.data1 	0x45, 0xfc, 0x85, 0xc0, 0x75, 0x07, 0xe8, 0x42
+.data1 	0xfb, 0xff, 0xff, 0xeb, 0x12, 0x46, 0x39, 0x35
+.data1 	0x88, 0x2b, 0x00, 0x00, 0x7f, 0xe6, 0xff, 0x75
+.data1 	0xfc, 0xe8, 0x9c, 0xff, 0xff, 0xff, 0x59, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x68, 0xe1, 0xbb
+.data1 	0x00, 0x00, 0xe8, 0xc4, 0xff, 0xff, 0xff, 0x59
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x68, 0x0c, 0xbc
+.data1 	0x00, 0x00, 0xe8, 0xb4, 0xff, 0xff, 0xff, 0x59
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x31, 0xd2, 0x89
+.data1 	0x15, 0xf4, 0x29, 0x00, 0x00, 0xff, 0x34, 0x95
+.data1 	0xf8, 0x29, 0x00, 0x00, 0xe8, 0x61, 0xff, 0xff
+.data1 	0xff, 0x59, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b
+.data1 	0x15, 0xf0, 0x29, 0x00, 0x00, 0x4a, 0x89, 0x15
+.data1 	0xf4, 0x29, 0x00, 0x00, 0xff, 0x34, 0x95, 0xf8
+.data1 	0x29, 0x00, 0x00, 0xe8, 0x42, 0xff, 0xff, 0xff
+.data1 	0x59, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x04, 0x56, 0x8b, 0x75, 0x08, 0x8b, 0x55, 0x0c
+.data1 	0x0f, 0xb6, 0x0a, 0x88, 0x4d, 0xff, 0x84, 0xc9
+.data1 	0x75, 0x0c, 0x0f, 0xb6, 0x16, 0x31, 0xc0, 0x85
+.data1 	0xd2, 0x0f, 0x94, 0xc0, 0xeb, 0x2f, 0x80, 0x3e
+.data1 	0x00, 0x74, 0x25, 0x0f, 0xbe, 0x06, 0x0f, 0xbe
+.data1 	0x5d, 0xff, 0x39, 0xd8, 0x75, 0x17, 0xff, 0x75
+.data1 	0x10, 0xff, 0x75, 0x0c, 0x56, 0xe8, 0xde, 0x2f
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x75
+.data1 	0x04, 0x31, 0xc0, 0xeb, 0x08, 0x46, 0xeb, 0xd6
+.data1 	0xb8, 0x01, 0x00, 0x00, 0x00, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57
+.data1 	0x8b, 0x75, 0x08, 0x85, 0xf6, 0x74, 0x28, 0x80
+.data1 	0x3e, 0x00, 0x74, 0x23, 0x83, 0x3d, 0xc4, 0x2b
+.data1 	0x00, 0x00, 0x00, 0x74, 0x0c, 0xff, 0x35, 0xc4
+.data1 	0x2b, 0x00, 0x00, 0xe8, 0x26, 0x1b, 0x00, 0x00
+.data1 	0x59, 0x56, 0xe8, 0x01, 0x21, 0x00, 0x00, 0x59
+.data1 	0xa3, 0xc4, 0x2b, 0x00, 0x00, 0xeb, 0x21, 0x83
+.data1 	0x3d, 0xc4, 0x2b, 0x00, 0x00, 0x00, 0x74, 0x0b
+.data1 	0x8b, 0x15, 0xc4, 0x2b, 0x00, 0x00, 0x80, 0x3a
+.data1 	0x00, 0x75, 0x07, 0x31, 0xc0, 0xe9, 0x6f, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x35, 0xc4, 0x2b, 0x00, 0x00
+.data1 	0x80, 0x3e, 0x5e, 0x75, 0x0c, 0xc7, 0x45, 0xf4
+.data1 	0x10, 0xed, 0x00, 0x00, 0x89, 0xf7, 0x47, 0xeb
+.data1 	0x09, 0xc7, 0x45, 0xf4, 0xf3, 0xbc, 0x00, 0x00
+.data1 	0x89, 0xf7, 0x57, 0xe8, 0x30, 0x2f, 0x00, 0x00
+.data1 	0x59, 0x89, 0x45, 0xfc, 0x8b, 0x15, 0xf4, 0x29
+.data1 	0x00, 0x00, 0x89, 0x55, 0xf8, 0xff, 0x55, 0x0c
+.data1 	0x85, 0xc0, 0x74, 0x2a, 0x8b, 0x15, 0xf4, 0x29
+.data1 	0x00, 0x00, 0xff, 0x75, 0xfc, 0x57, 0xff, 0x34
+.data1 	0x95, 0xf8, 0x29, 0x00, 0x00, 0xff, 0x55, 0xf4
+.data1 	0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x75, 0xde, 0x8b
+.data1 	0x15, 0xf4, 0x29, 0x00, 0x00, 0x8b, 0x04, 0x95
+.data1 	0xf8, 0x29, 0x00, 0x00, 0xeb, 0x0b, 0x8b, 0x55
+.data1 	0xf8, 0x89, 0x15, 0xf4, 0x29, 0x00, 0x00, 0x31
+.data1 	0xc0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x08, 0x56, 0x83, 0x3d, 0xc0, 0x2b
+.data1 	0x00, 0x00, 0x00, 0x74, 0x0a, 0xe8, 0xa3, 0xf9
+.data1 	0xff, 0xff, 0xe9, 0xb4, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x05, 0xc0, 0x2b, 0x00, 0x00, 0x01, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x02, 0xfc, 0xff, 0xff, 0x8b, 0x15
+.data1 	0xe4, 0x29, 0x00, 0x00, 0x89, 0x55, 0xfc, 0xba
+.data1 	0x8c, 0x11, 0x00, 0x00, 0x89, 0x15, 0xe4, 0x29
+.data1 	0x00, 0x00, 0x52, 0xe8, 0x27, 0xf5, 0xff, 0xff
+.data1 	0x59, 0x83, 0x3d, 0x88, 0x2b, 0x00, 0x00, 0xff
+.data1 	0x75, 0x07, 0xb8, 0x0c, 0xbc, 0x00, 0x00, 0xeb
+.data1 	0x05, 0xb8, 0xe1, 0xbb, 0x00, 0x00, 0x89, 0x45
+.data1 	0xf8, 0xe8, 0x38, 0x06, 0x00, 0x00, 0x89, 0xc6
+.data1 	0x8b, 0x55, 0xfc, 0x89, 0x15, 0xe4, 0x29, 0x00
+.data1 	0x00, 0xc7, 0x05, 0xc0, 0x2b, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0xff, 0x35, 0xe4, 0x29, 0x00
+.data1 	0x00, 0xe8, 0xe9, 0xf4, 0xff, 0xff, 0x59, 0x85
+.data1 	0xf6, 0x75, 0x1f, 0x83, 0x3d, 0xa4, 0x2b, 0x00
+.data1 	0x00, 0x00, 0x7e, 0x16, 0xc7, 0x05, 0xa4, 0x2b
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x8d
+.data1 	0xfb, 0xff, 0xff, 0xe8, 0xe9, 0xfc, 0xff, 0xff
+.data1 	0xeb, 0x29, 0xff, 0x75, 0xf8, 0x56, 0xe8, 0x8d
+.data1 	0xfe, 0xff, 0xff, 0x59, 0x59, 0x89, 0xc6, 0xe8
+.data1 	0x74, 0xfb, 0xff, 0xff, 0x85, 0xf6, 0x75, 0x0c
+.data1 	0xe8, 0xf8, 0xf8, 0xff, 0xff, 0xe8, 0xc7, 0xfc
+.data1 	0xff, 0xff, 0xeb, 0x07, 0x56, 0xe8, 0x58, 0xfd
+.data1 	0xff, 0xff, 0x59, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x56, 0x31, 0xf6, 0x8b, 0x15, 0x8c, 0x2b
+.data1 	0x00, 0x00, 0x39, 0x15, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x7d, 0x11, 0x6a, 0x02, 0xe8, 0xa5, 0xf8, 0xff
+.data1 	0xff, 0x59, 0x46, 0x39, 0x35, 0x88, 0x2b, 0x00
+.data1 	0x00, 0x7f, 0xe1, 0xb8, 0x04, 0x00, 0x00, 0x00
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b
+.data1 	0x75, 0x0c, 0x83, 0x3d, 0xe8, 0x29, 0x00, 0x00
+.data1 	0x00, 0x74, 0x16, 0xff, 0x35, 0xe8, 0x29, 0x00
+.data1 	0x00, 0xe8, 0x70, 0x19, 0x00, 0x00, 0x59, 0xc7
+.data1 	0x05, 0xe8, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x85, 0xf6, 0x7e, 0x37, 0x8d, 0x46, 0x01
+.data1 	0x50, 0xe8, 0x41, 0x17, 0x00, 0x00, 0x59, 0xa3
+.data1 	0xe8, 0x29, 0x00, 0x00, 0x85, 0xc0, 0x74, 0x24
+.data1 	0x8b, 0x15, 0xe0, 0x29, 0x00, 0x00, 0x03, 0x55
+.data1 	0x08, 0x56, 0x52, 0xff, 0x35, 0xe8, 0x29, 0x00
+.data1 	0x00, 0xe8, 0xf2, 0x2c, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x8b, 0x15, 0xe8, 0x29, 0x00, 0x00, 0x01
+.data1 	0xf2, 0xc6, 0x02, 0x00, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0x57, 0x83, 0x7d, 0x08, 0x00
+.data1 	0x7e, 0x0e, 0x8b, 0x15, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x39, 0x15, 0x8c, 0x2b, 0x00, 0x00, 0x75, 0x0a
+.data1 	0xe8, 0x38, 0xf8, 0xff, 0xff, 0xe9, 0x32, 0x01
+.data1 	0x00, 0x00, 0x83, 0x7d, 0x08, 0x01, 0x0f, 0x85
+.data1 	0x87, 0x00, 0x00, 0x00, 0x8b, 0x15, 0x8c, 0x2b
+.data1 	0x00, 0x00, 0x4a, 0x39, 0x15, 0x98, 0x2b, 0x00
+.data1 	0x00, 0x0f, 0x85, 0x74, 0x00, 0x00, 0x00, 0xff
+.data1 	0x0d, 0x8c, 0x2b, 0x00, 0x00, 0x8b, 0x15, 0xe0
+.data1 	0x29, 0x00, 0x00, 0x8b, 0x35, 0x98, 0x2b, 0x00
+.data1 	0x00, 0x01, 0xd6, 0xbf, 0x01, 0x00, 0x00, 0x00
+.data1 	0x6a, 0x20, 0xe8, 0x57, 0xf3, 0xff, 0xff, 0x59
+.data1 	0x80, 0x3e, 0x00, 0x74, 0x17, 0x0f, 0xb6, 0x16
+.data1 	0x83, 0xfa, 0x20, 0x7d, 0x0f, 0xbf, 0x02, 0x00
+.data1 	0x00, 0x00, 0x6a, 0x20, 0xe8, 0x3d, 0xf3, 0xff
+.data1 	0xff, 0x59, 0xeb, 0x23, 0x83, 0x3d, 0x2c, 0x25
+.data1 	0x00, 0x00, 0x00, 0x74, 0x1a, 0xf6, 0x06, 0x80
+.data1 	0x74, 0x15, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x6a
+.data1 	0x20, 0xe8, 0x20, 0xf3, 0xff, 0xff, 0x59, 0x6a
+.data1 	0x20, 0xe8, 0x18, 0xf3, 0xff, 0xff, 0x59, 0x57
+.data1 	0xe8, 0x7a, 0xf4, 0xff, 0xff, 0x59, 0xc6, 0x06
+.data1 	0x00, 0xb8, 0x02, 0x00, 0x00, 0x00, 0xe9, 0xa1
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x55, 0x08, 0x03, 0x15
+.data1 	0x98, 0x2b, 0x00, 0x00, 0x39, 0x15, 0x8c, 0x2b
+.data1 	0x00, 0x00, 0x7d, 0x1d, 0x8b, 0x15, 0x8c, 0x2b
+.data1 	0x00, 0x00, 0x2b, 0x15, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x89, 0x55, 0x08, 0x85, 0xd2, 0x7f, 0x0a, 0xb8
+.data1 	0x04, 0x00, 0x00, 0x00, 0xe9, 0x73, 0x00, 0x00
+.data1 	0x00, 0x83, 0x7d, 0x08, 0x01, 0x7e, 0x10, 0xff
+.data1 	0x75, 0x08, 0xff, 0x35, 0x98, 0x2b, 0x00, 0x00
+.data1 	0xe8, 0xa6, 0xfe, 0xff, 0xff, 0x59, 0x59, 0x8b
+.data1 	0x15, 0xe0, 0x29, 0x00, 0x00, 0x8b, 0x35, 0x98
+.data1 	0x2b, 0x00, 0x00, 0x01, 0xd6, 0x8b, 0x55, 0x08
+.data1 	0x03, 0x15, 0x98, 0x2b, 0x00, 0x00, 0x2b, 0x15
+.data1 	0x8c, 0x2b, 0x00, 0x00, 0xf7, 0xda, 0x42, 0x89
+.data1 	0xd7, 0x4f, 0x78, 0x0c, 0x89, 0xf2, 0x03, 0x55
+.data1 	0x08, 0x8a, 0x0a, 0x88, 0x0e, 0x46, 0xeb, 0xf1
+.data1 	0xe8, 0xf7, 0xf8, 0xff, 0xff, 0x8b, 0x15, 0x8c
+.data1 	0x2b, 0x00, 0x00, 0x2b, 0x55, 0x08, 0x89, 0x15
+.data1 	0x8c, 0x2b, 0x00, 0x00, 0x8b, 0x15, 0xe0, 0x29
+.data1 	0x00, 0x00, 0x03, 0x15, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x52, 0xe8, 0x56, 0xf3, 0xff, 0xff, 0x59, 0xb8
+.data1 	0x02, 0x00, 0x00, 0x00, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x31, 0xf6, 0x83, 0x3d
+.data1 	0x98, 0x2b, 0x00, 0x00, 0x00, 0x74, 0x11, 0x6a
+.data1 	0x02, 0xe8, 0xdc, 0xf5, 0xff, 0xff, 0x59, 0x46
+.data1 	0x39, 0x35, 0x88, 0x2b, 0x00, 0x00, 0x7f, 0xe6
+.data1 	0xb8, 0x04, 0x00, 0x00, 0x00, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x31, 0xf6, 0x83, 0x3d
+.data1 	0x98, 0x2b, 0x00, 0x00, 0x00, 0x74, 0x11, 0x6a
+.data1 	0x02, 0xe8, 0xb4, 0xf5, 0xff, 0xff, 0x59, 0x46
+.data1 	0x39, 0x35, 0x88, 0x2b, 0x00, 0x00, 0x7f, 0xe6
+.data1 	0x56, 0xe8, 0x59, 0xfe, 0xff, 0xff, 0x59, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x04
+.data1 	0x83, 0x3d, 0x88, 0x2b, 0x00, 0x00, 0xff, 0x74
+.data1 	0x65, 0x8b, 0x15, 0x98, 0x2b, 0x00, 0x00, 0x39
+.data1 	0x15, 0x88, 0x2b, 0x00, 0x00, 0x7d, 0x26, 0x89
+.data1 	0x55, 0xfc, 0x8b, 0x15, 0x88, 0x2b, 0x00, 0x00
+.data1 	0x89, 0x15, 0x98, 0x2b, 0x00, 0x00, 0xe8, 0x36
+.data1 	0xf5, 0xff, 0xff, 0x8b, 0x55, 0xfc, 0x2b, 0x15
+.data1 	0x98, 0x2b, 0x00, 0x00, 0x52, 0xe8, 0x15, 0xfe
+.data1 	0xff, 0xff, 0x59, 0xeb, 0x2a, 0x8b, 0x15, 0x98
+.data1 	0x2b, 0x00, 0x00, 0x39, 0x15, 0x88, 0x2b, 0x00
+.data1 	0x00, 0x7e, 0x1c, 0x6a, 0x02, 0xe8, 0x2c, 0xf6
+.data1 	0xff, 0xff, 0x59, 0x8b, 0x15, 0x88, 0x2b, 0x00
+.data1 	0x00, 0x2b, 0x15, 0x98, 0x2b, 0x00, 0x00, 0x4a
+.data1 	0x52, 0xe8, 0xe9, 0xfd, 0xff, 0xff, 0x59, 0xb8
+.data1 	0x02, 0x00, 0x00, 0x00, 0xeb, 0x3f, 0x8b, 0x15
+.data1 	0x8c, 0x2b, 0x00, 0x00, 0x2b, 0x15, 0x98, 0x2b
+.data1 	0x00, 0x00, 0x52, 0xff, 0x35, 0x98, 0x2b, 0x00
+.data1 	0x00, 0xe8, 0x65, 0xfd, 0xff, 0xff, 0x59, 0x59
+.data1 	0x8b, 0x15, 0xe0, 0x29, 0x00, 0x00, 0x03, 0x15
+.data1 	0x98, 0x2b, 0x00, 0x00, 0xc6, 0x02, 0x00, 0xe8
+.data1 	0xd8, 0xf7, 0xff, 0xff, 0x8b, 0x15, 0x98, 0x2b
+.data1 	0x00, 0x00, 0x89, 0x15, 0x8c, 0x2b, 0x00, 0x00
+.data1 	0xb8, 0x04, 0x00, 0x00, 0x00, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x14, 0x56, 0x57, 0x83
+.data1 	0x3d, 0x88, 0x2b, 0x00, 0x00, 0xff, 0x74, 0x09
+.data1 	0x83, 0x3d, 0x88, 0x2b, 0x00, 0x00, 0x02, 0x7d
+.data1 	0x16, 0x8b, 0x55, 0x08, 0x88, 0x55, 0xfa, 0xc6
+.data1 	0x45, 0xfb, 0x00, 0x8d, 0x45, 0xfa, 0x50, 0xe8
+.data1 	0x7e, 0xf8, 0xff, 0xff, 0x59, 0xeb, 0x54, 0x8b
+.data1 	0x15, 0x88, 0x2b, 0x00, 0x00, 0x42, 0x52, 0xe8
+.data1 	0x73, 0x14, 0x00, 0x00, 0x59, 0x89, 0xc7, 0x85
+.data1 	0xc0, 0x75, 0x07, 0xb8, 0x04, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x39, 0x8b, 0x15, 0x88, 0x2b, 0x00, 0x00
+.data1 	0x89, 0x55, 0xec, 0x89, 0xfe, 0xff, 0x4d, 0xec
+.data1 	0x78, 0x08, 0x8b, 0x55, 0x08, 0x88, 0x16, 0x46
+.data1 	0xeb, 0xf3, 0xc6, 0x06, 0x00, 0xc7, 0x05, 0x88
+.data1 	0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57
+.data1 	0xe8, 0x35, 0xf8, 0xff, 0xff, 0x59, 0x89, 0x45
+.data1 	0xfc, 0x57, 0xe8, 0x47, 0x16, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x45, 0xfc, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0x57, 0xe8, 0xcf, 0xf1, 0xff
+.data1 	0xff, 0x89, 0xc6, 0x3d, 0xff, 0xff, 0xff, 0xff
+.data1 	0x75, 0x0a, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xe9
+.data1 	0xe6, 0x00, 0x00, 0x00, 0x83, 0xfe, 0x5b, 0x74
+.data1 	0x43, 0x83, 0xfe, 0x4f, 0x75, 0x4f, 0xeb, 0x3c
+.data1 	0xe8, 0x40, 0xf5, 0xff, 0xff, 0xe9, 0xd0, 0x00
+.data1 	0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xe9
+.data1 	0xc6, 0x00, 0x00, 0x00, 0xe8, 0x11, 0xfa, 0xff
+.data1 	0xff, 0xe9, 0xbc, 0x00, 0x00, 0x00, 0xe8, 0xf7
+.data1 	0xf9, 0xff, 0xff, 0xe9, 0xb2, 0x00, 0x00, 0x00
+.data1 	0xe8, 0x31, 0xfc, 0xff, 0xff, 0xe9, 0xa8, 0x00
+.data1 	0x00, 0x00, 0xe8, 0x11, 0xfe, 0xff, 0xff, 0xe9
+.data1 	0x9e, 0x00, 0x00, 0x00, 0xe8, 0x6f, 0xf1, 0xff
+.data1 	0xff, 0x89, 0xc6, 0xbb, 0x98, 0x11, 0x00, 0x00
+.data1 	0xe9, 0x97, 0x36, 0x00, 0x00, 0x89, 0xf2, 0x83
+.data1 	0xea, 0x30, 0x83, 0xfa, 0x0a, 0x73, 0x4f, 0x89
+.data1 	0xf2, 0x83, 0xea, 0x30, 0x89, 0x15, 0x88, 0x2b
+.data1 	0x00, 0x00, 0xe8, 0x49, 0xf1, 0xff, 0xff, 0x89
+.data1 	0xc6, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x74, 0x1f
+.data1 	0x89, 0xf2, 0x83, 0xea, 0x30, 0x83, 0xfa, 0x0a
+.data1 	0x73, 0x15, 0x6b, 0x05, 0x88, 0x2b, 0x00, 0x00
+.data1 	0x0a, 0x01, 0xf0, 0x2d, 0x30, 0x00, 0x00, 0x00
+.data1 	0xa3, 0x88, 0x2b, 0x00, 0x00, 0xeb, 0xd3, 0xc7
+.data1 	0x05, 0xa0, 0x2b, 0x00, 0x00, 0x01, 0x00, 0x00
+.data1 	0x00, 0x89, 0x35, 0x9c, 0x2b, 0x00, 0x00, 0xb8
+.data1 	0x04, 0x00, 0x00, 0x00, 0xeb, 0x34, 0x89, 0xf2
+.data1 	0x83, 0xea, 0x41, 0x83, 0xfa, 0x1a, 0x73, 0x09
+.data1 	0x56, 0xe8, 0xa6, 0xf4, 0xff, 0xff, 0x59, 0xeb
+.data1 	0x21, 0xbf, 0x54, 0x26, 0x00, 0x00, 0x83, 0x7f
+.data1 	0x04, 0x00, 0x74, 0x11, 0x0f, 0xb6, 0x17, 0x39
+.data1 	0xf2, 0x75, 0x05, 0xff, 0x57, 0x04, 0xeb, 0x0a
+.data1 	0x83, 0xc7, 0x08, 0xeb, 0xe9, 0xe8, 0x6b, 0xf4
+.data1 	0xff, 0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x04, 0x56, 0x57, 0x8b, 0x7d
+.data1 	0x08, 0x8b, 0x15, 0x98, 0x2b, 0x00, 0x00, 0x89
+.data1 	0x15, 0x94, 0x2b, 0x00, 0x00, 0x83, 0x3d, 0x2c
+.data1 	0x25, 0x00, 0x00, 0x00, 0x74, 0x26, 0xf7, 0xc7
+.data1 	0x80, 0x00, 0x00, 0x00, 0x74, 0x1e, 0xc7, 0x05
+.data1 	0xa0, 0x2b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0xba, 0x7f, 0x00, 0x00, 0x00, 0x21, 0xfa, 0x89
+.data1 	0x15, 0x9c, 0x2b, 0x00, 0x00, 0xe8, 0xb5, 0xfe
+.data1 	0xff, 0xff, 0xeb, 0x42, 0xbe, 0x4c, 0x25, 0x00
+.data1 	0x00, 0x83, 0x7e, 0x04, 0x00, 0x74, 0x0c, 0x0f
+.data1 	0xb6, 0x16, 0x39, 0xfa, 0x74, 0x05, 0x83, 0xc6
+.data1 	0x08, 0xeb, 0xee, 0x83, 0x7e, 0x04, 0x00, 0x74
+.data1 	0x05, 0xff, 0x56, 0x04, 0xeb, 0x07, 0x57, 0xe8
+.data1 	0x03, 0xfe, 0xff, 0xff, 0x59, 0x89, 0x45, 0xfc
+.data1 	0x83, 0x3d, 0xa0, 0x2b, 0x00, 0x00, 0x00, 0x75
+.data1 	0x0a, 0xc7, 0x05, 0x88, 0x2b, 0x00, 0x00, 0xff
+.data1 	0xff, 0xff, 0xff, 0x8b, 0x45, 0xfc, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b, 0x75
+.data1 	0x08, 0xf7, 0xc6, 0x80, 0x00, 0x00, 0x00, 0x74
+.data1 	0x0a, 0xb8, 0x03, 0x00, 0x00, 0x00, 0xe9, 0xa0
+.data1 	0x00, 0x00, 0x00, 0x39, 0x35, 0x34, 0x36, 0x00
+.data1 	0x00, 0x74, 0x05, 0x83, 0xfe, 0x7f, 0x75, 0x0a
+.data1 	0xe8, 0xdb, 0xfc, 0xff, 0xff, 0xe9, 0x89, 0x00
+.data1 	0x00, 0x00, 0x39, 0x35, 0x3c, 0x36, 0x00, 0x00
+.data1 	0x75, 0x29, 0x83, 0x3d, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x00, 0x74, 0x0f, 0xc7, 0x05, 0x98, 0x2b, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x47, 0xf2
+.data1 	0xff, 0xff, 0xc7, 0x05, 0x88, 0x2b, 0x00, 0x00
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe8, 0xd1, 0xfc, 0xff
+.data1 	0xff, 0xeb, 0x58, 0x39, 0x35, 0x30, 0x36, 0x00
+.data1 	0x00, 0x75, 0x19, 0x83, 0x3d, 0x98, 0x2b, 0x00
+.data1 	0x00, 0x00, 0x75, 0x10, 0x83, 0x3d, 0x8c, 0x2b
+.data1 	0x00, 0x00, 0x00, 0x75, 0x07, 0xb8, 0x01, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x37, 0x39, 0x35, 0x38, 0x36
+.data1 	0x00, 0x00, 0x75, 0x11, 0xc7, 0x05, 0xa4, 0x2b
+.data1 	0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xb8, 0x05
+.data1 	0x00, 0x00, 0x00, 0xeb, 0x1e, 0x39, 0x35, 0x40
+.data1 	0x36, 0x00, 0x00, 0x75, 0x11, 0xc7, 0x05, 0xa4
+.data1 	0x2b, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0x03
+.data1 	0x00, 0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x56, 0xc7, 0x05, 0x88, 0x2b, 0x00, 0x00
+.data1 	0xff, 0xff, 0xff, 0xff, 0x31, 0xd2, 0x89, 0x15
+.data1 	0x8c, 0x2b, 0x00, 0x00, 0x89, 0x15, 0x90, 0x2b
+.data1 	0x00, 0x00, 0x89, 0x15, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x89, 0x15, 0x94, 0x2b, 0x00, 0x00, 0x8b, 0x15
+.data1 	0xe0, 0x29, 0x00, 0x00, 0xc6, 0x02, 0x00, 0xc7
+.data1 	0x05, 0xa4, 0x2b, 0x00, 0x00, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe8, 0x4a, 0xef, 0xff, 0xff, 0x89, 0xc6
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x74, 0x56, 0xeb
+.data1 	0x43, 0xa1, 0xe0, 0x29, 0x00, 0x00, 0xeb, 0x4f
+.data1 	0x31, 0xc0, 0xeb, 0x4b, 0xb8, 0x14, 0x12, 0x00
+.data1 	0x00, 0xeb, 0x44, 0xe8, 0x79, 0xf1, 0xff, 0xff
+.data1 	0xeb, 0xd7, 0xa1, 0xe0, 0x29, 0x00, 0x00, 0xeb
+.data1 	0x36, 0x31, 0xc0, 0xeb, 0x32, 0xb8, 0x10, 0x12
+.data1 	0x00, 0x00, 0xeb, 0x2b, 0xe8, 0x60, 0xf1, 0xff
+.data1 	0xff, 0xeb, 0xbe, 0x56, 0xe8, 0x35, 0xfe, 0xff
+.data1 	0xff, 0x59, 0xbb, 0xc8, 0x11, 0x00, 0x00, 0xe9
+.data1 	0x04, 0x34, 0x00, 0x00, 0x56, 0xe8, 0xb0, 0xfe
+.data1 	0xff, 0xff, 0x59, 0xbb, 0xec, 0x11, 0x00, 0x00
+.data1 	0xe9, 0xf3, 0x33, 0x00, 0x00, 0x31, 0xc0, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b
+.data1 	0x7d, 0x08, 0x57, 0xe8, 0x20, 0x19, 0x00, 0x00
+.data1 	0x59, 0x89, 0xc7, 0x85, 0xc0, 0x74, 0x5c, 0x83
+.data1 	0x3d, 0xf0, 0x29, 0x00, 0x00, 0x64, 0x7d, 0x18
+.data1 	0x8b, 0x15, 0xf0, 0x29, 0x00, 0x00, 0x89, 0xd1
+.data1 	0x41, 0x89, 0x0d, 0xf0, 0x29, 0x00, 0x00, 0x89
+.data1 	0x3c, 0x95, 0xf8, 0x29, 0x00, 0x00, 0xeb, 0x2e
+.data1 	0xff, 0x35, 0xf8, 0x29, 0x00, 0x00, 0xe8, 0x0b
+.data1 	0x13, 0x00, 0x00, 0x59, 0x31, 0xf6, 0x83, 0xfe
+.data1 	0x63, 0x7d, 0x14, 0x89, 0xf2, 0x42, 0x8b, 0x14
+.data1 	0x95, 0xf8, 0x29, 0x00, 0x00, 0x89, 0x14, 0xb5
+.data1 	0xf8, 0x29, 0x00, 0x00, 0x46, 0xeb, 0xe7, 0x89
+.data1 	0x3c, 0xb5, 0xf8, 0x29, 0x00, 0x00, 0x8b, 0x15
+.data1 	0xf0, 0x29, 0x00, 0x00, 0x4a, 0x89, 0x15, 0xf4
+.data1 	0x29, 0x00, 0x00, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x56
+.data1 	0x83, 0x3d, 0xe0, 0x29, 0x00, 0x00, 0x00, 0x75
+.data1 	0x22, 0xba, 0x40, 0x00, 0x00, 0x00, 0x89, 0x15
+.data1 	0xa8, 0x2b, 0x00, 0x00, 0x52, 0xe8, 0x95, 0x10
+.data1 	0x00, 0x00, 0x59, 0xa3, 0xe0, 0x29, 0x00, 0x00
+.data1 	0x85, 0xc0, 0x75, 0x07, 0x31, 0xc0, 0xe9, 0xfe
+.data1 	0x00, 0x00, 0x00, 0xe8, 0xba, 0xee, 0xff, 0xff
+.data1 	0x6a, 0x00, 0xe8, 0xc1, 0x08, 0x00, 0x00, 0x59
+.data1 	0x68, 0x20, 0x25, 0x00, 0x00, 0xe8, 0x38, 0xff
+.data1 	0xff, 0xff, 0x59, 0xba, 0x00, 0x01, 0x00, 0x00
+.data1 	0x89, 0x15, 0xb0, 0x2b, 0x00, 0x00, 0x52, 0xe8
+.data1 	0x5b, 0x10, 0x00, 0x00, 0x59, 0xa3, 0xec, 0x29
+.data1 	0x00, 0x00, 0x83, 0x7d, 0x08, 0x00, 0x74, 0x05
+.data1 	0x8b, 0x45, 0x08, 0xeb, 0x05, 0xb8, 0x20, 0x25
+.data1 	0x00, 0x00, 0xa3, 0xe4, 0x29, 0x00, 0x00, 0x50
+.data1 	0xe8, 0x32, 0xed, 0xff, 0xff, 0x59, 0xe8, 0x5b
+.data1 	0xfe, 0xff, 0xff, 0x89, 0xc6, 0x85, 0xc0, 0x74
+.data1 	0x19, 0x56, 0xe8, 0x21, 0x18, 0x00, 0x00, 0x59
+.data1 	0x89, 0xc6, 0x68, 0x28, 0x25, 0x00, 0x00, 0xe8
+.data1 	0x13, 0xed, 0xff, 0xff, 0x59, 0xe8, 0x8e, 0xec
+.data1 	0xff, 0xff, 0x6a, 0x01, 0xe8, 0x57, 0x08, 0x00
+.data1 	0x00, 0x59, 0xff, 0x35, 0xec, 0x29, 0x00, 0x00
+.data1 	0xe8, 0x19, 0x12, 0x00, 0x00, 0x59, 0x8b, 0x15
+.data1 	0xf0, 0x29, 0x00, 0x00, 0x4a, 0x89, 0x15, 0xf0
+.data1 	0x29, 0x00, 0x00, 0xff, 0x34, 0x95, 0xf8, 0x29
+.data1 	0x00, 0x00, 0xe8, 0xff, 0x11, 0x00, 0x00, 0x59
+.data1 	0x85, 0xf6, 0x74, 0x2f, 0x80, 0x3e, 0x00, 0x74
+.data1 	0x2a, 0x83, 0x3d, 0xf0, 0x29, 0x00, 0x00, 0x00
+.data1 	0x74, 0x1a, 0x8b, 0x15, 0xf0, 0x29, 0x00, 0x00
+.data1 	0x4a, 0xff, 0x34, 0x95, 0xf8, 0x29, 0x00, 0x00
+.data1 	0x56, 0xe8, 0x02, 0x26, 0x00, 0x00, 0x59, 0x59
+.data1 	0x85, 0xc0, 0x74, 0x07, 0x56, 0xe8, 0x80, 0xfe
+.data1 	0xff, 0xff, 0x59, 0x83, 0x3d, 0xa4, 0x2b, 0x00
+.data1 	0x00, 0x00, 0x7e, 0x23, 0x8b, 0x15, 0xa4, 0x2b
+.data1 	0x00, 0x00, 0x89, 0x55, 0xf8, 0xc7, 0x05, 0xa4
+.data1 	0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff
+.data1 	0x75, 0xf8, 0xe8, 0x71, 0x24, 0x00, 0x00, 0x50
+.data1 	0xe8, 0x8b, 0x24, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0xf0, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0x3d, 0x98, 0x2b
+.data1 	0x00, 0x00, 0x00, 0x74, 0x11, 0xc7, 0x05, 0x98
+.data1 	0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8
+.data1 	0x02, 0x00, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0x04
+.data1 	0x00, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0x3d, 0x88, 0x2b, 0x00, 0x00, 0xff, 0x75
+.data1 	0x07, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x05
+.data1 	0xa1, 0x88, 0x2b, 0x00, 0x00, 0x50, 0xe8, 0x2c
+.data1 	0xf8, 0xff, 0xff, 0x59, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x8b, 0x15, 0x8c, 0x2b, 0x00, 0x00, 0x39
+.data1 	0x15, 0x98, 0x2b, 0x00, 0x00, 0x74, 0x0d, 0x89
+.data1 	0x15, 0x98, 0x2b, 0x00, 0x00, 0xb8, 0x02, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x05, 0xb8, 0x04, 0x00, 0x00
+.data1 	0x00, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x10, 0x56, 0x57, 0x8b, 0x15, 0xe0, 0x29, 0x00
+.data1 	0x00, 0x8b, 0x35, 0x98, 0x2b, 0x00, 0x00, 0x01
+.data1 	0xd6, 0x39, 0x35, 0xe0, 0x29, 0x00, 0x00, 0x73
+.data1 	0x2a, 0x4e, 0x39, 0x35, 0xe0, 0x29, 0x00, 0x00
+.data1 	0x73, 0x09, 0x80, 0x7e, 0xff, 0x5c, 0x75, 0x03
+.data1 	0x4e, 0xeb, 0xe6, 0x0f, 0xbe, 0x06, 0x0f, 0xbe
+.data1 	0xc0, 0x50, 0x68, 0x30, 0x25, 0x00, 0x00, 0xe8
+.data1 	0xd4, 0x24, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x74, 0xcf, 0x46, 0x89, 0xf2, 0x2b, 0x15, 0xe0
+.data1 	0x29, 0x00, 0x00, 0x2b, 0x15, 0x98, 0x2b, 0x00
+.data1 	0x00, 0xf7, 0xda, 0x42, 0x89, 0x55, 0xf0, 0x52
+.data1 	0xe8, 0xb2, 0x0e, 0x00, 0x00, 0x59, 0x89, 0x45
+.data1 	0xf4, 0x85, 0xc0, 0x75, 0x04, 0x31, 0xc0, 0xeb
+.data1 	0x37, 0x8b, 0x7d, 0xf4, 0x8b, 0x15, 0xe0, 0x29
+.data1 	0x00, 0x00, 0x03, 0x15, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x39, 0xf2, 0x76, 0x1e, 0x80, 0x3e, 0x5c, 0x75
+.data1 	0x11, 0x8b, 0x15, 0xe0, 0x29, 0x00, 0x00, 0x03
+.data1 	0x15, 0x98, 0x2b, 0x00, 0x00, 0x46, 0x39, 0xf2
+.data1 	0x74, 0x08, 0x8a, 0x06, 0x46, 0x88, 0x07, 0x47
+.data1 	0xeb, 0xd2, 0xc6, 0x07, 0x00, 0x8b, 0x45, 0xf4
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x04, 0x56, 0x57, 0xe8, 0x4a, 0xff, 0xff
+.data1 	0xff, 0x89, 0xc7, 0x8d, 0x45, 0xfc, 0x50, 0x57
+.data1 	0xe8, 0x4c, 0x0c, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0xc6, 0x85, 0xff, 0x74, 0x07, 0x57, 0xe8, 0x5b
+.data1 	0x10, 0x00, 0x00, 0x59, 0x85, 0xf6, 0x74, 0x2c
+.data1 	0xff, 0x75, 0xfc, 0x56, 0xe8, 0x60, 0xed, 0xff
+.data1 	0xff, 0x59, 0x59, 0x4e, 0x78, 0x0e, 0x8b, 0x55
+.data1 	0xfc, 0xff, 0x34, 0xb2, 0xe8, 0x3d, 0x10, 0x00
+.data1 	0x00, 0x59, 0xeb, 0xef, 0xff, 0x75, 0xfc, 0xe8
+.data1 	0x32, 0x10, 0x00, 0x00, 0x59, 0xb8, 0x02, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x05, 0xe8, 0x54, 0xef, 0xff
+.data1 	0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x1c, 0x56, 0x57, 0xe8, 0xe9, 0xfe
+.data1 	0xff, 0xff, 0x89, 0xc7, 0x8d, 0x45, 0xe8, 0x50
+.data1 	0x57, 0xe8, 0xf2, 0x09, 0x00, 0x00, 0x59, 0x59
+.data1 	0x89, 0xc6, 0x85, 0xff, 0x74, 0x07, 0x57, 0xe8
+.data1 	0xfa, 0x0f, 0x00, 0x00, 0x59, 0x85, 0xf6, 0x0f
+.data1 	0x84, 0x9d, 0x00, 0x00, 0x00, 0x56, 0xe8, 0x45
+.data1 	0x24, 0x00, 0x00, 0x59, 0x89, 0x45, 0xec, 0x89
+.data1 	0xf7, 0xd1, 0xe0, 0x05, 0x01, 0x00, 0x00, 0x00
+.data1 	0x50, 0xe8, 0xc1, 0x0d, 0x00, 0x00, 0x59, 0x89
+.data1 	0x45, 0xf8, 0x89, 0x45, 0xf0, 0x80, 0x3e, 0x00
+.data1 	0x0f, 0x84, 0x41, 0x00, 0x00, 0x00, 0x0f, 0xb6
+.data1 	0x16, 0x83, 0xfa, 0x20, 0x7c, 0x17, 0x0f, 0xbe
+.data1 	0x06, 0x0f, 0xbe, 0xc0, 0x50, 0x68, 0x30, 0x25
+.data1 	0x00, 0x00, 0xe8, 0x99, 0x23, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x74, 0x15, 0x83, 0x7d, 0xe8
+.data1 	0x00, 0x74, 0x06, 0x80, 0x7e, 0x01, 0x00, 0x74
+.data1 	0x09, 0x8b, 0x55, 0xf8, 0xc6, 0x02, 0x5c, 0xff
+.data1 	0x45, 0xf8, 0x8a, 0x06, 0x46, 0x8b, 0x55, 0xf8
+.data1 	0x88, 0x02, 0xff, 0x45, 0xf8, 0xeb, 0xb6, 0x8b
+.data1 	0x55, 0xf8, 0xc6, 0x02, 0x00, 0x57, 0xe8, 0x7b
+.data1 	0x0f, 0x00, 0x00, 0x59, 0x83, 0x7d, 0xec, 0x00
+.data1 	0x74, 0x0c, 0xff, 0x75, 0xf0, 0xe8, 0x50, 0xf1
+.data1 	0xff, 0xff, 0x59, 0x89, 0x45, 0xe4, 0xff, 0x75
+.data1 	0xf0, 0xe8, 0x60, 0x0f, 0x00, 0x00, 0x59, 0x83
+.data1 	0x7d, 0xec, 0x00, 0x74, 0x05, 0x8b, 0x45, 0xe4
+.data1 	0xeb, 0x05, 0xe8, 0xcd, 0xfe, 0xff, 0xff, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b, 0x15
+.data1 	0xe0, 0x29, 0x00, 0x00, 0x03, 0x15, 0x8c, 0x2b
+.data1 	0x00, 0x00, 0xc6, 0x02, 0x00, 0x31, 0xc0, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x83
+.data1 	0x3d, 0x98, 0x2b, 0x00, 0x00, 0x00, 0x0f, 0x84
+.data1 	0x8f, 0x00, 0x00, 0x00, 0x8b, 0x15, 0x8c, 0x2b
+.data1 	0x00, 0x00, 0x39, 0x15, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x75, 0x08, 0x6a, 0x02, 0xe8, 0x31, 0xed, 0xff
+.data1 	0xff, 0x59, 0x8b, 0x15, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x4a, 0x03, 0x15, 0xe0, 0x29, 0x00, 0x00, 0x8a
+.data1 	0x0a, 0x88, 0x4d, 0xff, 0x6a, 0x04, 0xe8, 0x17
+.data1 	0xed, 0xff, 0xff, 0x59, 0x8b, 0x15, 0xe0, 0x29
+.data1 	0x00, 0x00, 0x03, 0x15, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x8b, 0x0d, 0x98, 0x2b, 0x00, 0x00, 0x49, 0x03
+.data1 	0x0d, 0xe0, 0x29, 0x00, 0x00, 0x8a, 0x12, 0x88
+.data1 	0x11, 0x8b, 0x15, 0x98, 0x2b, 0x00, 0x00, 0x4a
+.data1 	0x03, 0x15, 0xe0, 0x29, 0x00, 0x00, 0x0f, 0xb6
+.data1 	0x02, 0x50, 0xe8, 0xbc, 0xe9, 0xff, 0xff, 0x59
+.data1 	0x8b, 0x15, 0x98, 0x2b, 0x00, 0x00, 0x89, 0xd1
+.data1 	0x41, 0x0f, 0xb6, 0x45, 0xff, 0x50, 0xff, 0x35
+.data1 	0xe0, 0x29, 0x00, 0x00, 0x89, 0x0d, 0x98, 0x2b
+.data1 	0x00, 0x00, 0x59, 0x01, 0xd1, 0x5a, 0x88, 0x11
+.data1 	0x0f, 0xb6, 0x45, 0xff, 0x50, 0xe8, 0x91, 0xe9
+.data1 	0xff, 0xff, 0x59, 0xb8, 0x04, 0x00, 0x00, 0x00
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x04
+.data1 	0xe8, 0x1b, 0xea, 0xff, 0xff, 0x89, 0x45, 0xfc
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x07, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x00, 0xeb, 0x09, 0xff, 0x75
+.data1 	0xfc, 0xe8, 0xa1, 0xf7, 0xff, 0xff, 0x59, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x8b
+.data1 	0x15, 0x8c, 0x2b, 0x00, 0x00, 0x39, 0x15, 0x90
+.data1 	0x2b, 0x00, 0x00, 0x7e, 0x07, 0xe8, 0x7b, 0xed
+.data1 	0xff, 0xff, 0xeb, 0x44, 0x8b, 0x15, 0x90, 0x2b
+.data1 	0x00, 0x00, 0x39, 0x15, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x7e, 0x23, 0x8b, 0x15, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x89, 0x55, 0xfc, 0x8b, 0x15, 0x90, 0x2b, 0x00
+.data1 	0x00, 0x89, 0x15, 0x98, 0x2b, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xfc, 0x89, 0x15, 0x90, 0x2b, 0x00, 0x00
+.data1 	0xe8, 0x04, 0xec, 0xff, 0xff, 0x8b, 0x15, 0x90
+.data1 	0x2b, 0x00, 0x00, 0x2b, 0x15, 0x98, 0x2b, 0x00
+.data1 	0x00, 0x52, 0xe8, 0xe0, 0xf4, 0xff, 0xff, 0x59
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b, 0x15, 0x98
+.data1 	0x2b, 0x00, 0x00, 0x89, 0x15, 0x90, 0x2b, 0x00
+.data1 	0x00, 0xb8, 0x04, 0x00, 0x00, 0x00, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0xe8, 0x7f, 0xe9, 0xff
+.data1 	0xff, 0x89, 0xc6, 0x3d, 0x18, 0x00, 0x00, 0x00
+.data1 	0x74, 0x13, 0x83, 0xfe, 0xff, 0x75, 0x07, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x00, 0xeb, 0x35, 0xe8, 0xfa
+.data1 	0xec, 0xff, 0xff, 0xeb, 0x2e, 0x8b, 0x15, 0x90
+.data1 	0x2b, 0x00, 0x00, 0x89, 0xd6, 0x39, 0x15, 0x8c
+.data1 	0x2b, 0x00, 0x00, 0x72, 0x19, 0x8b, 0x15, 0x98
+.data1 	0x2b, 0x00, 0x00, 0x89, 0x15, 0x90, 0x2b, 0x00
+.data1 	0x00, 0x89, 0x35, 0x98, 0x2b, 0x00, 0x00, 0xb8
+.data1 	0x02, 0x00, 0x00, 0x00, 0xeb, 0x05, 0xb8, 0x04
+.data1 	0x00, 0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0x3d, 0xe8, 0x29, 0x00, 0x00, 0x00
+.data1 	0x74, 0x19, 0x8b, 0x15, 0xe8, 0x29, 0x00, 0x00
+.data1 	0x80, 0x3a, 0x00, 0x74, 0x0e, 0xff, 0x35, 0xe8
+.data1 	0x29, 0x00, 0x00, 0xe8, 0x5a, 0xef, 0xff, 0xff
+.data1 	0x59, 0xeb, 0x05, 0xb8, 0x04, 0x00, 0x00, 0x00
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b, 0x15, 0x8c
+.data1 	0x2b, 0x00, 0x00, 0x39, 0x15, 0x90, 0x2b, 0x00
+.data1 	0x00, 0x7e, 0x07, 0xe8, 0x85, 0xec, 0xff, 0xff
+.data1 	0xeb, 0x49, 0x8b, 0x15, 0x90, 0x2b, 0x00, 0x00
+.data1 	0x39, 0x15, 0x98, 0x2b, 0x00, 0x00, 0x7e, 0x1c
+.data1 	0x8b, 0x15, 0x98, 0x2b, 0x00, 0x00, 0x2b, 0x15
+.data1 	0x90, 0x2b, 0x00, 0x00, 0x52, 0xff, 0x35, 0x90
+.data1 	0x2b, 0x00, 0x00, 0xe8, 0xa3, 0xf3, 0xff, 0xff
+.data1 	0x59, 0x59, 0xeb, 0x1a, 0x8b, 0x15, 0x90, 0x2b
+.data1 	0x00, 0x00, 0x2b, 0x15, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x52, 0xff, 0x35, 0x98, 0x2b, 0x00, 0x00, 0xe8
+.data1 	0x87, 0xf3, 0xff, 0xff, 0x59, 0x59, 0xb8, 0x04
+.data1 	0x00, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x04, 0x56, 0x57, 0xe8, 0x96, 0xe8
+.data1 	0xff, 0xff, 0x89, 0x45, 0xfc, 0x3d, 0xff, 0xff
+.data1 	0xff, 0xff, 0x75, 0x07, 0xb8, 0x01, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x39, 0x8b, 0x15, 0x98, 0x2b, 0x00
+.data1 	0x00, 0x42, 0x89, 0xd6, 0x8b, 0x15, 0xe0, 0x29
+.data1 	0x00, 0x00, 0x89, 0xf7, 0x01, 0xd7, 0x39, 0x35
+.data1 	0x8c, 0x2b, 0x00, 0x00, 0x7e, 0x19, 0x0f, 0xb6
+.data1 	0x17, 0x39, 0x55, 0xfc, 0x75, 0x0d, 0x89, 0x35
+.data1 	0x98, 0x2b, 0x00, 0x00, 0xb8, 0x02, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x09, 0x46, 0x47, 0xeb, 0xdf, 0xb8
+.data1 	0x04, 0x00, 0x00, 0x00, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x6a, 0x02, 0xe8, 0x2d, 0xec
+.data1 	0xff, 0xff, 0x59, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0xec, 0x04, 0x6a, 0x04, 0xe8, 0x1d, 0xec
+.data1 	0xff, 0xff, 0x59, 0x8b, 0x15, 0x98, 0x2b, 0x00
+.data1 	0x00, 0x39, 0x15, 0x94, 0x2b, 0x00, 0x00, 0x74
+.data1 	0x20, 0x2b, 0x15, 0x94, 0x2b, 0x00, 0x00, 0x89
+.data1 	0x55, 0xfc, 0x8b, 0x15, 0x94, 0x2b, 0x00, 0x00
+.data1 	0x89, 0x15, 0x98, 0x2b, 0x00, 0x00, 0xff, 0x75
+.data1 	0xfc, 0xe8, 0x41, 0xf3, 0xff, 0xff, 0x59, 0xeb
+.data1 	0x05, 0xb8, 0x04, 0x00, 0x00, 0x00, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x31, 0xff, 0x8b
+.data1 	0x15, 0xe0, 0x29, 0x00, 0x00, 0x8b, 0x35, 0x98
+.data1 	0x2b, 0x00, 0x00, 0x01, 0xd6, 0x39, 0x35, 0xe0
+.data1 	0x29, 0x00, 0x00, 0x73, 0x1a, 0x0f, 0xb6, 0x56
+.data1 	0xff, 0x81, 0xc2, 0xe1, 0x26, 0x00, 0x00, 0xf6
+.data1 	0x02, 0x07, 0x75, 0x0b, 0x6a, 0x02, 0xe8, 0x4f
+.data1 	0xea, 0xff, 0xff, 0x59, 0x4e, 0xeb, 0xde, 0x39
+.data1 	0x35, 0xe0, 0x29, 0x00, 0x00, 0x73, 0x20, 0x80
+.data1 	0x7e, 0xff, 0x20, 0x74, 0x1a, 0x0f, 0xb6, 0x56
+.data1 	0xff, 0x81, 0xc2, 0xe1, 0x26, 0x00, 0x00, 0xf6
+.data1 	0x02, 0x07, 0x74, 0x0b, 0x6a, 0x02, 0xe8, 0x27
+.data1 	0xea, 0xff, 0xff, 0x59, 0x4e, 0xeb, 0xd8, 0x83
+.data1 	0x3d, 0x98, 0x2b, 0x00, 0x00, 0x00, 0x74, 0x09
+.data1 	0x47, 0x39, 0x3d, 0x88, 0x2b, 0x00, 0x00, 0x7f
+.data1 	0x96, 0xb8, 0x04, 0x00, 0x00, 0x00, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0xe8, 0x7e, 0xff
+.data1 	0xff, 0xff, 0x8b, 0x15, 0x98, 0x2b, 0x00, 0x00
+.data1 	0x39, 0x15, 0x94, 0x2b, 0x00, 0x00, 0x74, 0x15
+.data1 	0x8b, 0x15, 0x94, 0x2b, 0x00, 0x00, 0x2b, 0x15
+.data1 	0x98, 0x2b, 0x00, 0x00, 0x52, 0xe8, 0x95, 0xf2
+.data1 	0xff, 0xff, 0x59, 0xeb, 0x05, 0xb8, 0x04, 0x00
+.data1 	0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x14, 0x56, 0x57, 0xba, 0x40, 0x00, 0x00
+.data1 	0x00, 0x89, 0x55, 0xec, 0xc1, 0xe2, 0x02, 0x52
+.data1 	0xe8, 0x82, 0x09, 0x00, 0x00, 0x59, 0x89, 0x45
+.data1 	0xf8, 0x8b, 0x5d, 0x0c, 0x89, 0x03, 0x85, 0xc0
+.data1 	0x75, 0x07, 0x31, 0xc0, 0xe9, 0xf4, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x75, 0x08, 0x0f, 0xb6, 0x16, 0x81
+.data1 	0xc2, 0xe1, 0x26, 0x00, 0x00, 0xf6, 0x02, 0x08
+.data1 	0x74, 0x03, 0x46, 0xeb, 0xef, 0x80, 0x3e, 0x0a
+.data1 	0x74, 0x05, 0x80, 0x3e, 0x00, 0x75, 0x07, 0x31
+.data1 	0xc0, 0xe9, 0xcf, 0x00, 0x00, 0x00, 0x31, 0xff
+.data1 	0x89, 0xfa, 0x42, 0x56, 0xff, 0x75, 0xf8, 0x57
+.data1 	0x89, 0xd7, 0x5a, 0x59, 0x8f, 0x04, 0x91, 0x80
+.data1 	0x3e, 0x00, 0x0f, 0x84, 0xa6, 0x00, 0x00, 0x00
+.data1 	0x80, 0x3e, 0x0a, 0x0f, 0x84, 0x9d, 0x00, 0x00
+.data1 	0x00, 0x0f, 0xb6, 0x16, 0x81, 0xc2, 0xe1, 0x26
+.data1 	0x00, 0x00, 0xf6, 0x02, 0x08, 0x0f, 0x84, 0x85
+.data1 	0x00, 0x00, 0x00, 0xc6, 0x06, 0x00, 0x46, 0x80
+.data1 	0x3e, 0x00, 0x74, 0xd3, 0x80, 0x3e, 0x0a, 0x74
+.data1 	0xce, 0x89, 0xfa, 0x42, 0x39, 0x55, 0xec, 0x0f
+.data1 	0x85, 0x57, 0x00, 0x00, 0x00, 0xba, 0x40, 0x00
+.data1 	0x00, 0x00, 0x03, 0x55, 0xec, 0xc1, 0xe2, 0x02
+.data1 	0x52, 0xe8, 0xe9, 0x08, 0x00, 0x00, 0x59, 0x89
+.data1 	0x45, 0xf4, 0x85, 0xc0, 0x75, 0x11, 0x8b, 0x55
+.data1 	0xf8, 0xc7, 0x04, 0xba, 0x00, 0x00, 0x00, 0x00
+.data1 	0x89, 0xf8, 0xe9, 0x56, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xec, 0xc1, 0xe2, 0x02, 0x52, 0xff, 0x75
+.data1 	0xf8, 0xff, 0x75, 0xf4, 0xe8, 0x8f, 0x1e, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x83, 0x45, 0xec, 0x40
+.data1 	0xff, 0x75, 0xf8, 0xe8, 0xc6, 0x0a, 0x00, 0x00
+.data1 	0x59, 0x8b, 0x55, 0xf4, 0x89, 0x55, 0xf8, 0x8b
+.data1 	0x45, 0x0c, 0x89, 0x10, 0x89, 0xfa, 0x42, 0x56
+.data1 	0xff, 0x75, 0xf8, 0x57, 0x89, 0xd7, 0x5a, 0x59
+.data1 	0x8f, 0x04, 0x91, 0xe9, 0x57, 0xff, 0xff, 0xff
+.data1 	0x46, 0xe9, 0x51, 0xff, 0xff, 0xff, 0xc6, 0x06
+.data1 	0x00, 0x8b, 0x55, 0xf8, 0xc7, 0x04, 0xba, 0x00
+.data1 	0x00, 0x00, 0x00, 0x89, 0xf8, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c, 0x56
+.data1 	0x57, 0x83, 0x3d, 0xf0, 0x29, 0x00, 0x00, 0x01
+.data1 	0x74, 0x16, 0x8b, 0x15, 0xf0, 0x29, 0x00, 0x00
+.data1 	0x83, 0xea, 0x02, 0x8b, 0x14, 0x95, 0xf8, 0x29
+.data1 	0x00, 0x00, 0x89, 0xd6, 0x85, 0xd2, 0x75, 0x0a
+.data1 	0xe8, 0x90, 0xe9, 0xff, 0xff, 0xe9, 0x88, 0x00
+.data1 	0x00, 0x00, 0x56, 0xe8, 0x38, 0x10, 0x00, 0x00
+.data1 	0x59, 0x89, 0xc6, 0x85, 0xc0, 0x75, 0x0a, 0xb8
+.data1 	0x04, 0x00, 0x00, 0x00, 0xe9, 0x71, 0x00, 0x00
+.data1 	0x00, 0x8d, 0x45, 0xfc, 0x50, 0x56, 0xe8, 0x89
+.data1 	0xfe, 0xff, 0xff, 0x59, 0x59, 0x89, 0xc7, 0x83
+.data1 	0x3d, 0x88, 0x2b, 0x00, 0x00, 0xff, 0x74, 0x26
+.data1 	0x39, 0x3d, 0x88, 0x2b, 0x00, 0x00, 0x7d, 0x14
+.data1 	0x8b, 0x15, 0x88, 0x2b, 0x00, 0x00, 0x8b, 0x4d
+.data1 	0xfc, 0xff, 0x34, 0x91, 0xe8, 0xf9, 0xeb, 0xff
+.data1 	0xff, 0x59, 0xeb, 0x05, 0xe8, 0x3c, 0xe9, 0xff
+.data1 	0xff, 0x89, 0x45, 0xf4, 0xeb, 0x1d, 0x85, 0xff
+.data1 	0x74, 0x11, 0x89, 0xfa, 0x4a, 0x8b, 0x4d, 0xfc
+.data1 	0xff, 0x34, 0x91, 0xe8, 0xda, 0xeb, 0xff, 0xff
+.data1 	0x59, 0xeb, 0x05, 0xb8, 0x04, 0x00, 0x00, 0x00
+.data1 	0x89, 0x45, 0xf4, 0x85, 0xff, 0x74, 0x09, 0xff
+.data1 	0x75, 0xfc, 0xe8, 0xdf, 0x09, 0x00, 0x00, 0x59
+.data1 	0x56, 0xe8, 0xd8, 0x09, 0x00, 0x00, 0x59, 0x8b
+.data1 	0x45, 0xf4, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x83, 0x7d
+.data1 	0x08, 0x00, 0x0f, 0x85, 0x9e, 0x00, 0x00, 0x00
+.data1 	0x68, 0xcc, 0x2b, 0x00, 0x00, 0x6a, 0x00, 0xe8
+.data1 	0xdc, 0x1c, 0x00, 0x00, 0x59, 0x59, 0x0f, 0xb6
+.data1 	0x15, 0xde, 0x2b, 0x00, 0x00, 0x89, 0x15, 0x34
+.data1 	0x36, 0x00, 0x00, 0x0f, 0xb6, 0x15, 0xe0, 0x2b
+.data1 	0x00, 0x00, 0x89, 0x15, 0x3c, 0x36, 0x00, 0x00
+.data1 	0x0f, 0xb6, 0x15, 0xdc, 0x2b, 0x00, 0x00, 0x89
+.data1 	0x15, 0x30, 0x36, 0x00, 0x00, 0x0f, 0xb6, 0x15
+.data1 	0xdf, 0x2b, 0x00, 0x00, 0x89, 0x15, 0x38, 0x36
+.data1 	0x00, 0x00, 0x0f, 0xb6, 0x15, 0xe2, 0x2b, 0x00
+.data1 	0x00, 0x89, 0x15, 0x40, 0x36, 0x00, 0x00, 0x68
+.data1 	0xcc, 0x2b, 0x00, 0x00, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0xb9, 0x09, 0x00, 0x00, 0x00, 0xe8, 0xe6, 0x29
+.data1 	0x00, 0x00, 0x0f, 0xb7, 0x55, 0xe2, 0x83, 0xe2
+.data1 	0x8e, 0x81, 0xe2, 0xff, 0xff, 0x00, 0x00, 0x66
+.data1 	0x89, 0x55, 0xe2, 0x0f, 0xb7, 0x55, 0xdc, 0x83
+.data1 	0xe2, 0xfd, 0x81, 0xe2, 0xff, 0xff, 0x00, 0x00
+.data1 	0x66, 0x89, 0x55, 0xdc, 0xc6, 0x45, 0xf1, 0x01
+.data1 	0xc6, 0x45, 0xf3, 0x00, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x6a, 0x02, 0x6a, 0x00, 0xe8, 0x57, 0x1c, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xeb, 0x11, 0x68, 0xcc
+.data1 	0x2b, 0x00, 0x00, 0x6a, 0x02, 0x6a, 0x00, 0xe8
+.data1 	0x44, 0x1c, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8d
+.data1 	0x45, 0xdc, 0x50, 0xff, 0x75, 0x08, 0xe8, 0x1d
+.data1 	0x1c, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x78
+.data1 	0x29, 0x0f, 0xb7, 0x55, 0xe4, 0x81, 0xe2, 0x00
+.data1 	0xf0, 0x00, 0x00, 0x81, 0xfa, 0x00, 0x40, 0x00
+.data1 	0x00, 0x75, 0x07, 0xb8, 0x1c, 0x12, 0x00, 0x00
+.data1 	0xeb, 0x05, 0xb8, 0x18, 0x12, 0x00, 0x00, 0x50
+.data1 	0xff, 0x75, 0x0c, 0xe8, 0xa8, 0x1c, 0x00, 0x00
+.data1 	0x59, 0x59, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x08, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xfc
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf8, 0x8b, 0x45
+.data1 	0xf8, 0x8b, 0x5d, 0xfc, 0xff, 0x30, 0xff, 0x33
+.data1 	0xe8, 0xd3, 0x1c, 0x00, 0x00, 0x59, 0x59, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x30, 0x56
+.data1 	0x57, 0xff, 0x75, 0x08, 0xe8, 0x97, 0x1b, 0x00
+.data1 	0x00, 0x59, 0x89, 0x45, 0xf0, 0x85, 0xc0, 0x75
+.data1 	0x07, 0x31, 0xc0, 0xe9, 0xd0, 0x01, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x31
+.data1 	0xff, 0xff, 0x75, 0x0c, 0xe8, 0xcf, 0x1c, 0x00
+.data1 	0x00, 0x59, 0x89, 0x45, 0xe4, 0xc7, 0x45, 0xe0
+.data1 	0x00, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xdc, 0x00
+.data1 	0x00, 0x00, 0x00, 0xff, 0x75, 0xf0, 0xe8, 0x75
+.data1 	0x1b, 0x00, 0x00, 0x59, 0x89, 0x45, 0xec, 0x85
+.data1 	0xc0, 0x0f, 0x84, 0xe7, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x75, 0xec, 0x83, 0xc6, 0x05, 0x80, 0x3e, 0x2e
+.data1 	0x75, 0x12, 0x80, 0x7e, 0x01, 0x00, 0x74, 0xdb
+.data1 	0x80, 0x7e, 0x01, 0x2e, 0x75, 0x06, 0x80, 0x7e
+.data1 	0x02, 0x00, 0x74, 0xcf, 0x83, 0x7d, 0xe4, 0x00
+.data1 	0x74, 0x13, 0xff, 0x75, 0xe4, 0xff, 0x75, 0x0c
+.data1 	0x56, 0xe8, 0x9a, 0x1c, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x85, 0xc0, 0x75, 0xb6, 0xff, 0x45, 0xe0
+.data1 	0x56, 0xe8, 0x6a, 0x1c, 0x00, 0x00, 0x59, 0x01
+.data1 	0x45, 0xdc, 0x81, 0x7d, 0xdc, 0x00, 0x10, 0x00
+.data1 	0x00, 0x76, 0x13, 0x85, 0xff, 0x74, 0x9c, 0x4f
+.data1 	0x8b, 0x55, 0xfc, 0xff, 0x34, 0xba, 0xe8, 0xf3
+.data1 	0x07, 0x00, 0x00, 0x59, 0xeb, 0xed, 0xb9, 0x40
+.data1 	0x00, 0x00, 0x00, 0x89, 0xf8, 0x31, 0xd2, 0xf7
+.data1 	0xf1, 0x85, 0xd2, 0x75, 0x4c, 0x8d, 0x57, 0x40
+.data1 	0xc1, 0xe2, 0x02, 0x52, 0xe8, 0xbe, 0x05, 0x00
+.data1 	0x00, 0x59, 0x89, 0x45, 0xf8, 0x85, 0xc0, 0x75
+.data1 	0x0c, 0xc7, 0x45, 0xdc, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x59, 0x00, 0x00, 0x00, 0x85, 0xff, 0x74
+.data1 	0x1d, 0x89, 0xfa, 0xc1, 0xe2, 0x02, 0x52, 0xff
+.data1 	0x75, 0xfc, 0xff, 0x75, 0xf8, 0xe8, 0x66, 0x1b
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xff, 0x75, 0xfc
+.data1 	0xe8, 0xa1, 0x07, 0x00, 0x00, 0x59, 0x8b, 0x55
+.data1 	0xf8, 0x89, 0x55, 0xfc, 0x8b, 0x45, 0x10, 0x89
+.data1 	0x10, 0x56, 0xe8, 0x71, 0x0d, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x55, 0xfc, 0x89, 0x04, 0xba, 0x85, 0xc0
+.data1 	0x75, 0x16, 0x85, 0xff, 0x75, 0x09, 0xff, 0x75
+.data1 	0xfc, 0xe8, 0x78, 0x07, 0x00, 0x00, 0x59, 0xc7
+.data1 	0x45, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x06
+.data1 	0x47, 0xe9, 0x05, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0xf0, 0xe8, 0xea, 0x19, 0x00, 0x00, 0x59, 0x81
+.data1 	0x7d, 0xdc, 0x00, 0x10, 0x00, 0x00, 0x0f, 0x86
+.data1 	0x83, 0x00, 0x00, 0x00, 0x8d, 0x75, 0xdc, 0x4e
+.data1 	0xc6, 0x06, 0x00, 0x83, 0x7d, 0xe0, 0x00, 0x74
+.data1 	0x23, 0xb9, 0x0a, 0x00, 0x00, 0x00, 0x8b, 0x45
+.data1 	0xe0, 0x31, 0xd2, 0xf7, 0xf1, 0x83, 0xc2, 0x30
+.data1 	0x89, 0xd0, 0x0f, 0xbe, 0xc0, 0x4e, 0x88, 0x06
+.data1 	0x8b, 0x45, 0xe0, 0x31, 0xd2, 0xf7, 0xf1, 0x89
+.data1 	0x45, 0xe0, 0xeb, 0xd7, 0x8d, 0x55, 0xd4, 0x39
+.data1 	0xd6, 0x76, 0x06, 0x4e, 0xc6, 0x06, 0x20, 0xeb
+.data1 	0xf3, 0x56, 0xe8, 0xf1, 0x0c, 0x00, 0x00, 0x59
+.data1 	0x89, 0xc6, 0x85, 0xc0, 0x74, 0x13, 0x89, 0xfa
+.data1 	0x56, 0xff, 0x75, 0xfc, 0x57, 0xbf, 0x01, 0x00
+.data1 	0x00, 0x00, 0x01, 0xd7, 0x5a, 0x59, 0x8f, 0x04
+.data1 	0x91, 0x68, 0x20, 0x12, 0x00, 0x00, 0xe8, 0xcd
+.data1 	0x0c, 0x00, 0x00, 0x59, 0x89, 0xc6, 0x85, 0xc0
+.data1 	0x74, 0x2c, 0x89, 0xfa, 0x56, 0xff, 0x75, 0xfc
+.data1 	0x57, 0xbf, 0x01, 0x00, 0x00, 0x00, 0x01, 0xd7
+.data1 	0x5a, 0x59, 0x8f, 0x04, 0x91, 0xeb, 0x17, 0x85
+.data1 	0xff, 0x74, 0x13, 0x68, 0xcc, 0xcf, 0x00, 0x00
+.data1 	0x6a, 0x04, 0x57, 0xff, 0x75, 0xfc, 0xe8, 0x39
+.data1 	0x07, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x89, 0xf8
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x6a, 0x2f, 0xff, 0x75, 0x08, 0xe8, 0x2d
+.data1 	0x1b, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc6, 0x85
+.data1 	0xc0, 0x75, 0x38, 0x68, 0xdc, 0x26, 0x00, 0x00
+.data1 	0xe8, 0x73, 0x0c, 0x00, 0x00, 0x59, 0x89, 0xc7
+.data1 	0x85, 0xc0, 0x75, 0x0a, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x66, 0x00, 0x00, 0x00, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x5a, 0x0c, 0x00, 0x00, 0x59, 0x89
+.data1 	0xc6, 0x85, 0xc0, 0x75, 0x4b, 0x57, 0xe8, 0x6b
+.data1 	0x06, 0x00, 0x00, 0x59, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xeb, 0x49, 0xff, 0x75, 0x08, 0xe8, 0x3d
+.data1 	0x0c, 0x00, 0x00, 0x59, 0x89, 0xc7, 0x85, 0xc0
+.data1 	0x75, 0x07, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x33, 0x89, 0xf2, 0x2b, 0x55, 0x08, 0x42, 0x01
+.data1 	0xfa, 0xc6, 0x02, 0x00, 0x46, 0x56, 0xe8, 0x1d
+.data1 	0x0c, 0x00, 0x00, 0x59, 0x89, 0xc6, 0x85, 0xc0
+.data1 	0x75, 0x0e, 0x57, 0xe8, 0x2e, 0x06, 0x00, 0x00
+.data1 	0x59, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x0c
+.data1 	0x8b, 0x45, 0x0c, 0x89, 0x38, 0x8b, 0x45, 0x10
+.data1 	0x89, 0x30, 0x31, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x56, 0x57
+.data1 	0x8d, 0x45, 0xf4, 0x50, 0x8d, 0x45, 0xf8, 0x50
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x4c, 0xff, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x79, 0x07, 0x31
+.data1 	0xc0, 0xe9, 0xcf, 0x01, 0x00, 0x00, 0x8d, 0x45
+.data1 	0xfc, 0x50, 0xff, 0x75, 0xf4, 0xff, 0x75, 0xf8
+.data1 	0xe8, 0x3c, 0xfd, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0x45, 0xe8, 0x85, 0xc0, 0x75, 0x19, 0xff
+.data1 	0x75, 0xf8, 0xe8, 0xcf, 0x05, 0x00, 0x00, 0x59
+.data1 	0xff, 0x75, 0xf4, 0xe8, 0xc6, 0x05, 0x00, 0x00
+.data1 	0x59, 0x31, 0xc0, 0xe9, 0x9d, 0x01, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff
+.data1 	0x75, 0xf4, 0xe8, 0x09, 0x1a, 0x00, 0x00, 0x59
+.data1 	0x89, 0x45, 0xd8, 0x83, 0x7d, 0xe8, 0x01, 0x0f
+.data1 	0x85, 0xbd, 0x00, 0x00, 0x00, 0x8b, 0x45, 0x0c
+.data1 	0xc7, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8b, 0x45
+.data1 	0xfc, 0xff, 0x30, 0xe8, 0xe8, 0x19, 0x00, 0x00
+.data1 	0x59, 0x2b, 0x45, 0xd8, 0xbf, 0x02, 0x00, 0x00
+.data1 	0x00, 0x01, 0xc7, 0x8d, 0x47, 0x01, 0x50, 0xe8
+.data1 	0x63, 0x03, 0x00, 0x00, 0x59, 0x89, 0x45, 0xec
+.data1 	0x85, 0xc0, 0x0f, 0x84, 0x19, 0x01, 0x00, 0x00
+.data1 	0x8b, 0x5d, 0xfc, 0x8b, 0x13, 0x03, 0x55, 0xd8
+.data1 	0x57, 0x52, 0xff, 0x75, 0xec, 0xe8, 0x16, 0x19
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xff, 0x75, 0xf8
+.data1 	0xe8, 0xab, 0x19, 0x00, 0x00, 0x59, 0x8b, 0x5d
+.data1 	0xfc, 0x50, 0xff, 0x33, 0xe8, 0x9f, 0x19, 0x00
+.data1 	0x00, 0x59, 0x5a, 0x01, 0xd0, 0x05, 0x02, 0x00
+.data1 	0x00, 0x00, 0x50, 0xe8, 0x1f, 0x03, 0x00, 0x00
+.data1 	0x59, 0x89, 0x45, 0xf0, 0x85, 0xc0, 0x0f, 0x84
+.data1 	0xd5, 0x00, 0x00, 0x00, 0xff, 0x75, 0xf8, 0xff
+.data1 	0x75, 0xf0, 0xe8, 0x59, 0x19, 0x00, 0x00, 0x59
+.data1 	0x59, 0x68, 0x28, 0x12, 0x00, 0x00, 0xff, 0x75
+.data1 	0xf0, 0xe8, 0xea, 0x18, 0x00, 0x00, 0x59, 0x59
+.data1 	0x8b, 0x45, 0xfc, 0xff, 0x30, 0xff, 0x75, 0xf0
+.data1 	0xe8, 0xdb, 0x18, 0x00, 0x00, 0x59, 0x59, 0xff
+.data1 	0x75, 0xec, 0xff, 0x75, 0xf0, 0xe8, 0xe7, 0xfb
+.data1 	0xff, 0xff, 0x59, 0x59, 0xff, 0x75, 0xf0, 0xe8
+.data1 	0xea, 0x04, 0x00, 0x00, 0x59, 0xe9, 0x8f, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x45, 0x0c, 0xc7, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xd8, 0x00, 0x0f
+.data1 	0x84, 0x7c, 0x00, 0x00, 0x00, 0x8b, 0x75, 0xd8
+.data1 	0x8b, 0x45, 0xfc, 0xff, 0x30, 0xe8, 0x1e, 0x19
+.data1 	0x00, 0x00, 0x59, 0x89, 0x45, 0xe4, 0x39, 0x75
+.data1 	0xe4, 0x76, 0x29, 0xbf, 0x01, 0x00, 0x00, 0x00
+.data1 	0x39, 0x7d, 0xe8, 0x76, 0x1c, 0x8b, 0x55, 0xfc
+.data1 	0x8b, 0x14, 0xba, 0x01, 0xf2, 0x0f, 0xbe, 0x02
+.data1 	0x8b, 0x5d, 0xfc, 0x8b, 0x13, 0x01, 0xf2, 0x0f
+.data1 	0xbe, 0x0a, 0x39, 0xc8, 0x75, 0x06, 0x47, 0xeb
+.data1 	0xdf, 0x46, 0xeb, 0xd2, 0x39, 0x75, 0xd8, 0x73
+.data1 	0x38, 0x89, 0xf2, 0x2b, 0x55, 0xd8, 0xbf, 0x01
+.data1 	0x00, 0x00, 0x00, 0x01, 0xd7, 0x57, 0xe8, 0x64
+.data1 	0x02, 0x00, 0x00, 0x59, 0x89, 0x45, 0xec, 0x85
+.data1 	0xc0, 0x74, 0x1e, 0x8b, 0x5d, 0xfc, 0x8b, 0x13
+.data1 	0x03, 0x55, 0xd8, 0x57, 0x52, 0xff, 0x75, 0xec
+.data1 	0xe8, 0x1b, 0x18, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0xfa, 0x4a, 0x03, 0x55, 0xec, 0xc6, 0x02
+.data1 	0x00, 0xff, 0x75, 0xf8, 0xe8, 0x4d, 0x04, 0x00
+.data1 	0x00, 0x59, 0xff, 0x75, 0xf4, 0xe8, 0x44, 0x04
+.data1 	0x00, 0x00, 0x59, 0x31, 0xf6, 0x39, 0x75, 0xe8
+.data1 	0x76, 0x0f, 0x8b, 0x55, 0xfc, 0xff, 0x34, 0xb2
+.data1 	0xe8, 0x31, 0x04, 0x00, 0x00, 0x59, 0x46, 0xeb
+.data1 	0xec, 0xff, 0x75, 0xfc, 0xe8, 0x25, 0x04, 0x00
+.data1 	0x00, 0x59, 0x8b, 0x45, 0xec, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x0c, 0x8d
+.data1 	0x45, 0xf8, 0x50, 0x8d, 0x45, 0xfc, 0x50, 0xff
+.data1 	0x75, 0x08, 0xe8, 0x55, 0xfd, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x85, 0xc0, 0x79, 0x04, 0x31, 0xc0
+.data1 	0xeb, 0x29, 0xff, 0x75, 0x0c, 0xff, 0x75, 0xf8
+.data1 	0xff, 0x75, 0xfc, 0xe8, 0x49, 0xfb, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x45, 0xf4, 0xff, 0x75
+.data1 	0xfc, 0xe8, 0xe0, 0x03, 0x00, 0x00, 0x59, 0xff
+.data1 	0x75, 0xf8, 0xe8, 0xd7, 0x03, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x45, 0xf4, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0x3d, 0xe8, 0x27, 0x00
+.data1 	0x00, 0x00, 0x74, 0x06, 0xff, 0x15, 0xe8, 0x27
+.data1 	0x00, 0x00, 0x6a, 0x06, 0xe8, 0x4f, 0x06, 0x00
+.data1 	0x00, 0x59, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x75, 0x08, 0x6a, 0x0a, 0x6a, 0x00, 0x56
+.data1 	0xe8, 0xeb, 0x06, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x5e, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x08, 0x56, 0x57, 0x8b, 0x75, 0x08, 0x31
+.data1 	0xff, 0xc7, 0x45, 0xf8, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0f, 0xbe, 0x06, 0xf6, 0x80, 0xe1, 0x26, 0x00
+.data1 	0x00, 0x08, 0x74, 0x03, 0x46, 0xeb, 0xf1, 0x80
+.data1 	0x3e, 0x2b, 0x75, 0x03, 0x46, 0xeb, 0x0d, 0x80
+.data1 	0x3e, 0x2d, 0x75, 0x08, 0xc7, 0x45, 0xf8, 0x01
+.data1 	0x00, 0x00, 0x00, 0x46, 0x0f, 0xbe, 0x06, 0x2d
+.data1 	0x30, 0x00, 0x00, 0x00, 0x3d, 0x0a, 0x00, 0x00
+.data1 	0x00, 0x73, 0x12, 0x6b, 0xc7, 0x0a, 0x89, 0xc7
+.data1 	0x0f, 0xbe, 0x06, 0x46, 0x2d, 0x30, 0x00, 0x00
+.data1 	0x00, 0x01, 0xc7, 0xeb, 0xdf, 0x83, 0x7d, 0xf8
+.data1 	0x00, 0x74, 0x08, 0x89, 0xfa, 0xf7, 0xda, 0x89
+.data1 	0xd0, 0xeb, 0x02, 0x89, 0xf8, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x35, 0xe4, 0x27, 0x00, 0x00, 0x4e, 0x78
+.data1 	0x09, 0xff, 0x14, 0xb5, 0x44, 0x36, 0x00, 0x00
+.data1 	0xeb, 0xf4, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0xe8, 0xdf, 0xff, 0xff, 0xff, 0x83, 0x3d, 0xe8
+.data1 	0x27, 0x00, 0x00, 0x00, 0x74, 0x06, 0xff, 0x15
+.data1 	0xe8, 0x27, 0x00, 0x00, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x60, 0x15, 0x00, 0x00, 0x59, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x56, 0x57
+.data1 	0x8b, 0x15, 0x2c, 0x19, 0x00, 0x00, 0x8b, 0x12
+.data1 	0x89, 0x55, 0xfc, 0x85, 0xd2, 0x74, 0x06, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x75, 0x04, 0x31, 0xc0, 0xeb
+.data1 	0x36, 0x8b, 0x45, 0xfc, 0x83, 0x45, 0xfc, 0x04
+.data1 	0x8b, 0x10, 0x89, 0xd7, 0x85, 0xd2, 0x74, 0x25
+.data1 	0x8b, 0x75, 0x08, 0x80, 0x3e, 0x00, 0x74, 0x0e
+.data1 	0x0f, 0xbe, 0x07, 0x47, 0x0f, 0xbe, 0x1e, 0x39
+.data1 	0xd8, 0x75, 0x03, 0x46, 0xeb, 0xed, 0x80, 0x3e
+.data1 	0x00, 0x75, 0xd6, 0x80, 0x3f, 0x3d, 0x75, 0xd1
+.data1 	0x8d, 0x47, 0x01, 0xeb, 0x02, 0x31, 0xc0, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x15, 0xf4, 0x2b, 0x00, 0x00, 0x03, 0x55
+.data1 	0x08, 0x39, 0x15, 0xf4, 0x2b, 0x00, 0x00, 0x77
+.data1 	0x1f, 0x8b, 0x55, 0x08, 0x03, 0x15, 0xf4, 0x2b
+.data1 	0x00, 0x00, 0x81, 0xc2, 0xff, 0x0f, 0x00, 0x00
+.data1 	0x81, 0xe2, 0x00, 0xf0, 0xff, 0xff, 0x89, 0xd6
+.data1 	0x39, 0x15, 0xf4, 0x2b, 0x00, 0x00, 0x76, 0x0e
+.data1 	0xc7, 0x05, 0xf0, 0x27, 0x00, 0x00, 0x0c, 0x00
+.data1 	0x00, 0x00, 0x31, 0xc0, 0xeb, 0x36, 0x56, 0xe8
+.data1 	0xa4, 0x07, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x74
+.data1 	0x04, 0x31, 0xc0, 0xeb, 0x27, 0x8b, 0x15, 0xf4
+.data1 	0x2b, 0x00, 0x00, 0x89, 0x72, 0xfc, 0xc7, 0x46
+.data1 	0xfc, 0x00, 0x00, 0x00, 0x00, 0xff, 0x35, 0xf4
+.data1 	0x2b, 0x00, 0x00, 0xe8, 0x26, 0x02, 0x00, 0x00
+.data1 	0x59, 0x89, 0x35, 0xf4, 0x2b, 0x00, 0x00, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x18, 0x56, 0x57, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x75, 0x07, 0x31, 0xc0, 0xe9
+.data1 	0xf4, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xe8, 0x00
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xe8, 0x02, 0x0f
+.data1 	0x83, 0xe1, 0x00, 0x00, 0x00, 0xba, 0x03, 0x00
+.data1 	0x00, 0x00, 0x03, 0x55, 0x08, 0x83, 0xe2, 0xfc
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0xec, 0x83, 0xfa
+.data1 	0x08, 0x73, 0x11, 0xc7, 0x05, 0xf0, 0x27, 0x00
+.data1 	0x00, 0x0c, 0x00, 0x00, 0x00, 0x31, 0xc0, 0xe9
+.data1 	0xbc, 0x00, 0x00, 0x00, 0x83, 0x3d, 0xf0, 0x2b
+.data1 	0x00, 0x00, 0x00, 0x75, 0x38, 0x6a, 0x08, 0xe8
+.data1 	0x53, 0x07, 0x00, 0x00, 0x59, 0x89, 0xc6, 0x3d
+.data1 	0xff, 0xff, 0xff, 0xff, 0x75, 0x07, 0x31, 0xc0
+.data1 	0xe9, 0x9b, 0x00, 0x00, 0x00, 0x8d, 0x56, 0x03
+.data1 	0xbe, 0xfc, 0xff, 0xff, 0xff, 0x21, 0xd6, 0x83
+.data1 	0xc6, 0x04, 0x89, 0x35, 0xf0, 0x2b, 0x00, 0x00
+.data1 	0x89, 0x35, 0xf4, 0x2b, 0x00, 0x00, 0xc7, 0x46
+.data1 	0xfc, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xfc
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x35, 0xf8, 0x2b
+.data1 	0x00, 0x00, 0x85, 0xf6, 0x0f, 0x84, 0x4f, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x56, 0xfc, 0x89, 0x55, 0xf4
+.data1 	0x89, 0xf2, 0x8b, 0x7d, 0xec, 0x01, 0xd7, 0x39
+.data1 	0x7d, 0xf4, 0x72, 0x36, 0x39, 0xf7, 0x76, 0x32
+.data1 	0x8d, 0x57, 0x04, 0x39, 0x55, 0xf4, 0x76, 0x0f
+.data1 	0x8b, 0x55, 0xf4, 0x89, 0x57, 0xfc, 0x89, 0x7e
+.data1 	0xfc, 0x8b, 0x16, 0x89, 0x17, 0x89, 0x3e, 0x83
+.data1 	0x7d, 0xfc, 0x00, 0x74, 0x09, 0x8b, 0x16, 0x8b
+.data1 	0x45, 0xfc, 0x89, 0x10, 0xeb, 0x08, 0x8b, 0x16
+.data1 	0x89, 0x15, 0xf8, 0x2b, 0x00, 0x00, 0x89, 0xf0
+.data1 	0xeb, 0x1e, 0x89, 0x75, 0xfc, 0x8b, 0x36, 0xeb
+.data1 	0xa9, 0xff, 0x75, 0xec, 0xe8, 0x8b, 0xfe, 0xff
+.data1 	0xff, 0x59, 0x85, 0xc0, 0x74, 0x08, 0xff, 0x45
+.data1 	0xe8, 0xe9, 0x15, 0xff, 0xff, 0xff, 0x31, 0xc0
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x1c, 0x56, 0x57, 0x8b, 0x55, 0x08, 0x89
+.data1 	0x55, 0xec, 0x85, 0xd2, 0x75, 0x0e, 0xff, 0x75
+.data1 	0x0c, 0xe8, 0xd9, 0xfe, 0xff, 0xff, 0x59, 0xe9
+.data1 	0xe6, 0x00, 0x00, 0x00, 0x83, 0x7d, 0x0c, 0x00
+.data1 	0x75, 0x10, 0xff, 0x75, 0xec, 0xe8, 0xdc, 0x00
+.data1 	0x00, 0x00, 0x59, 0x31, 0xc0, 0xe9, 0xd0, 0x00
+.data1 	0x00, 0x00, 0xba, 0x03, 0x00, 0x00, 0x00, 0x03
+.data1 	0x55, 0x0c, 0x83, 0xe2, 0xfc, 0x83, 0xc2, 0x04
+.data1 	0x89, 0x55, 0xe8, 0x8b, 0x55, 0xec, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0xf4, 0x2b, 0x55, 0xec, 0x89
+.data1 	0x55, 0xe4, 0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x3d, 0xf8, 0x2b, 0x00, 0x00, 0x85
+.data1 	0xff, 0x0f, 0x84, 0x3c, 0x00, 0x00, 0x00, 0x39
+.data1 	0x7d, 0xf4, 0x72, 0x37, 0x39, 0x7d, 0xf4, 0x75
+.data1 	0x2b, 0x8b, 0x55, 0xec, 0x8b, 0x4f, 0xfc, 0x89
+.data1 	0x4a, 0xfc, 0x83, 0x7d, 0xfc, 0x00, 0x74, 0x09
+.data1 	0x8b, 0x17, 0x8b, 0x45, 0xfc, 0x89, 0x10, 0xeb
+.data1 	0x08, 0x8b, 0x17, 0x89, 0x15, 0xf8, 0x2b, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xec, 0x8b, 0x52, 0xfc, 0x89
+.data1 	0x55, 0xf4, 0xeb, 0x07, 0x89, 0x7d, 0xfc, 0x8b
+.data1 	0x3f, 0xeb, 0xbc, 0x8b, 0x55, 0xec, 0x8b, 0x75
+.data1 	0xe8, 0x01, 0xd6, 0x39, 0x75, 0xf4, 0x72, 0x25
+.data1 	0x39, 0x75, 0xec, 0x77, 0x20, 0x8d, 0x56, 0x04
+.data1 	0x39, 0x55, 0xf4, 0x76, 0x13, 0x8b, 0x55, 0xf4
+.data1 	0x89, 0x56, 0xfc, 0x8b, 0x55, 0xec, 0x89, 0x72
+.data1 	0xfc, 0x56, 0xe8, 0x37, 0x00, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x45, 0xec, 0xeb, 0x2d, 0xff, 0x75, 0x0c
+.data1 	0xe8, 0x12, 0xfe, 0xff, 0xff, 0x59, 0x89, 0xc6
+.data1 	0x85, 0xc0, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x1a
+.data1 	0xff, 0x75, 0xe4, 0xff, 0x75, 0xec, 0x56, 0xe8
+.data1 	0xcc, 0x13, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xff
+.data1 	0x75, 0xec, 0xe8, 0x07, 0x00, 0x00, 0x00, 0x59
+.data1 	0x89, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xf4, 0x85, 0xd2, 0x0f, 0x84
+.data1 	0x62, 0x00, 0x00, 0x00, 0x31, 0xff, 0x8b, 0x35
+.data1 	0xf8, 0x2b, 0x00, 0x00, 0x85, 0xf6, 0x74, 0x0b
+.data1 	0x39, 0x75, 0xf4, 0x72, 0x06, 0x89, 0xf7, 0x8b
+.data1 	0x36, 0xeb, 0xf1, 0x8b, 0x45, 0xf4, 0x89, 0x30
+.data1 	0x85, 0xff, 0x74, 0x07, 0x8b, 0x55, 0xf4, 0x89
+.data1 	0x17, 0xeb, 0x09, 0x8b, 0x55, 0xf4, 0x89, 0x15
+.data1 	0xf8, 0x2b, 0x00, 0x00, 0x85, 0xf6, 0x74, 0x15
+.data1 	0x8b, 0x55, 0xf4, 0x39, 0x72, 0xfc, 0x75, 0x0d
+.data1 	0x8b, 0x4e, 0xfc, 0x89, 0x4a, 0xfc, 0x8b, 0x16
+.data1 	0x8b, 0x45, 0xf4, 0x89, 0x10, 0x85, 0xff, 0x74
+.data1 	0x15, 0x8b, 0x55, 0xf4, 0x39, 0x57, 0xfc, 0x75
+.data1 	0x0d, 0x8b, 0x52, 0xfc, 0x89, 0x57, 0xfc, 0x8b
+.data1 	0x45, 0xf4, 0x8b, 0x10, 0x89, 0x17, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0x7d, 0x0c, 0x00, 0x74, 0x23, 0x8b, 0x55, 0x14
+.data1 	0x89, 0x15, 0xfc, 0x2b, 0x00, 0x00, 0x8b, 0x55
+.data1 	0x0c, 0x4a, 0x0f, 0xaf, 0x55, 0x10, 0x03, 0x55
+.data1 	0x08, 0xff, 0x75, 0x10, 0x52, 0xff, 0x75, 0x08
+.data1 	0xe8, 0x05, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec, 0x14
+.data1 	0x56, 0x57, 0x8b, 0x7d, 0x10, 0x8b, 0x55, 0x08
+.data1 	0x39, 0x55, 0x0c, 0x0f, 0x86, 0x5e, 0x01, 0x00
+.data1 	0x00, 0x89, 0x55, 0xfc, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xf8, 0x8b, 0x55, 0x0c, 0x2b, 0x55, 0x08
+.data1 	0x01, 0xfa, 0x89, 0xf9, 0xd1, 0xe1, 0x89, 0xd0
+.data1 	0x31, 0xd2, 0xf7, 0xf1, 0x0f, 0xaf, 0xc7, 0x03
+.data1 	0x45, 0x08, 0x89, 0x45, 0xf0, 0x89, 0xc6, 0x39
+.data1 	0x75, 0xfc, 0x73, 0x3c, 0x56, 0xff, 0x75, 0xfc
+.data1 	0xff, 0x15, 0xfc, 0x2b, 0x00, 0x00, 0x59, 0x59
+.data1 	0x89, 0x45, 0xec, 0x85, 0xc0, 0x7f, 0x29, 0x83
+.data1 	0x7d, 0xec, 0x00, 0x79, 0x0a, 0x89, 0xfa, 0x03
+.data1 	0x55, 0xfc, 0x89, 0x55, 0xfc, 0xeb, 0xd8, 0x89
+.data1 	0xfa, 0xf7, 0xda, 0x89, 0xf1, 0x89, 0xd6, 0x01
+.data1 	0xce, 0x57, 0x56, 0xff, 0x75, 0xfc, 0xe8, 0x00
+.data1 	0x01, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xeb, 0xbf
+.data1 	0x8b, 0x55, 0xf0, 0x39, 0x55, 0xf8, 0x0f, 0x86
+.data1 	0x9a, 0x00, 0x00, 0x00, 0xff, 0x75, 0xf0, 0xff
+.data1 	0x75, 0xf8, 0xff, 0x15, 0xfc, 0x2b, 0x00, 0x00
+.data1 	0x59, 0x59, 0x89, 0x45, 0xec, 0x85, 0xc0, 0x0f
+.data1 	0x89, 0x50, 0x00, 0x00, 0x00, 0x39, 0x75, 0xfc
+.data1 	0x73, 0x26, 0x57, 0xff, 0x75, 0xf8, 0xff, 0x75
+.data1 	0xfc, 0xe8, 0xc5, 0x00, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x89, 0xfa, 0x03, 0x55, 0xfc, 0x89, 0x55
+.data1 	0xfc, 0x89, 0xfa, 0xf7, 0xda, 0x03, 0x55, 0xf8
+.data1 	0x89, 0x55, 0xf8, 0xe9, 0x6f, 0xff, 0xff, 0xff
+.data1 	0x89, 0xfa, 0x03, 0x55, 0xf0, 0x89, 0x55, 0xf0
+.data1 	0x57, 0xff, 0x75, 0xf8, 0xff, 0x75, 0xf0, 0xff
+.data1 	0x75, 0xfc, 0xe8, 0xc8, 0x00, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x10, 0x89, 0xf2, 0x89, 0xfe, 0x01, 0xd6
+.data1 	0x89, 0x75, 0xfc, 0xeb, 0x8b, 0x83, 0x7d, 0xec
+.data1 	0x00, 0x75, 0x1c, 0x89, 0xfa, 0x03, 0x55, 0xf0
+.data1 	0x89, 0x55, 0xf0, 0x57, 0xff, 0x75, 0xf0, 0xff
+.data1 	0x75, 0xf8, 0xe8, 0x6c, 0x00, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xe9, 0x69, 0xff, 0xff, 0xff, 0x89
+.data1 	0xfa, 0xf7, 0xda, 0x03, 0x55, 0xf8, 0x89, 0x55
+.data1 	0xf8, 0xe9, 0x5a, 0xff, 0xff, 0xff, 0x39, 0x75
+.data1 	0xfc, 0x73, 0x2c, 0x89, 0xfa, 0xf7, 0xda, 0x89
+.data1 	0xf1, 0x89, 0xd6, 0x01, 0xce, 0x57, 0xff, 0x75
+.data1 	0xfc, 0x56, 0xff, 0x75, 0xf8, 0xe8, 0x6d, 0x00
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x10, 0x89, 0xfa, 0xf7
+.data1 	0xda, 0x03, 0x55, 0xf0, 0x89, 0x55, 0xf0, 0x89
+.data1 	0x55, 0xf8, 0xe9, 0xe8, 0xfe, 0xff, 0xff, 0x89
+.data1 	0xfa, 0xf7, 0xda, 0x01, 0xf2, 0x57, 0x52, 0xff
+.data1 	0x75, 0x08, 0xe8, 0x9b, 0xfe, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0xfa, 0x03, 0x55, 0xf0, 0x89
+.data1 	0x55, 0x08, 0xe9, 0x96, 0xfe, 0xff, 0xff, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x04, 0x56, 0x57, 0x8b, 0x75, 0x0c, 0x8b, 0x7d
+.data1 	0x08, 0x8b, 0x55, 0x10, 0x89, 0xd1, 0x83, 0xe9
+.data1 	0x01, 0x89, 0x4d, 0x10, 0x85, 0xd2, 0x74, 0x13
+.data1 	0x0f, 0xbe, 0x07, 0x89, 0x45, 0xfc, 0x8a, 0x0e
+.data1 	0x88, 0x0f, 0x47, 0x8b, 0x55, 0xfc, 0x88, 0x16
+.data1 	0x46, 0xeb, 0xde, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x04, 0x56, 0x57, 0x8b
+.data1 	0x75, 0x10, 0x8b, 0x7d, 0x0c, 0x8b, 0x55, 0x14
+.data1 	0x89, 0xd1, 0x83, 0xe9, 0x01, 0x89, 0x4d, 0x14
+.data1 	0x85, 0xd2, 0x74, 0x1d, 0x8b, 0x55, 0x08, 0x0f
+.data1 	0xbe, 0x02, 0x89, 0x45, 0xfc, 0x8a, 0x0e, 0x88
+.data1 	0x0a, 0xff, 0x45, 0x08, 0x8a, 0x0f, 0x88, 0x0e
+.data1 	0x46, 0x8b, 0x55, 0xfc, 0x88, 0x17, 0x47, 0xeb
+.data1 	0xd4, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0x7d, 0x08, 0x00, 0x78
+.data1 	0x06, 0x83, 0x7d, 0x08, 0x17, 0x7e, 0x07, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x10, 0xff, 0x75
+.data1 	0x08, 0xe8, 0xc2, 0x08, 0x00, 0x00, 0x50, 0xe8
+.data1 	0xd4, 0x08, 0x00, 0x00, 0x59, 0x59, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x18, 0x56, 0x8b
+.data1 	0x75, 0x08, 0x85, 0xf6, 0x7e, 0x0a, 0x83, 0xfe
+.data1 	0x17, 0x7f, 0x05, 0x83, 0xfe, 0x09, 0x75, 0x11
+.data1 	0xc7, 0x05, 0xf0, 0x27, 0x00, 0x00, 0x16, 0x00
+.data1 	0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x36, 0x8d, 0x45, 0xf8, 0x50, 0xe8, 0x52, 0x09
+.data1 	0x00, 0x00, 0x59, 0xc7, 0x45, 0xfc, 0x00, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf4
+.data1 	0x8d, 0x45, 0xe8, 0x50, 0x8d, 0x45, 0xf4, 0x50
+.data1 	0x56, 0xe8, 0xa6, 0x08, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x85, 0xc0, 0x79, 0x07, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xeb, 0x03, 0x8b, 0x45, 0xe8, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x75, 0x08, 0x85, 0xf6, 0x78, 0x08, 0x39
+.data1 	0x35, 0x3c, 0x29, 0x00, 0x00, 0x7f, 0x07, 0xb8
+.data1 	0x2c, 0x12, 0x00, 0x00, 0xeb, 0x07, 0x8b, 0x04
+.data1 	0xb5, 0x0c, 0x28, 0x00, 0x00, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x75, 0x08, 0x6a
+.data1 	0x01, 0xff, 0x75, 0x10, 0xff, 0x75, 0x0c, 0x56
+.data1 	0xe8, 0x21, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b
+.data1 	0x75, 0x08, 0x6a, 0x00, 0xff, 0x75, 0x10, 0xff
+.data1 	0x75, 0x0c, 0x56, 0xe8, 0x06, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x1c, 0x56, 0x57, 0x8b, 0x75
+.data1 	0x08, 0xc7, 0x45, 0xf8, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xec, 0x01, 0x00, 0x00, 0x00, 0x89, 0x75
+.data1 	0xe8, 0x83, 0x7d, 0x0c, 0x00, 0x74, 0x05, 0x8b
+.data1 	0x45, 0x0c, 0x89, 0x30, 0x0f, 0xbe, 0x06, 0xf6
+.data1 	0x80, 0xe1, 0x26, 0x00, 0x00, 0x08, 0x74, 0x03
+.data1 	0x46, 0xeb, 0xf1, 0x0f, 0xbe, 0x06, 0x89, 0xc7
+.data1 	0x83, 0xff, 0x2d, 0x74, 0x05, 0x83, 0xff, 0x2b
+.data1 	0x75, 0x0d, 0x83, 0xff, 0x2d, 0x75, 0x07, 0xc7
+.data1 	0x45, 0xec, 0xff, 0xff, 0xff, 0xff, 0x46, 0x89
+.data1 	0x75, 0xe4, 0x83, 0x7d, 0x10, 0x00, 0x75, 0x2c
+.data1 	0x80, 0x3e, 0x30, 0x75, 0x1e, 0x46, 0x80, 0x3e
+.data1 	0x78, 0x74, 0x05, 0x80, 0x3e, 0x58, 0x75, 0x0a
+.data1 	0xc7, 0x45, 0x10, 0x10, 0x00, 0x00, 0x00, 0x46
+.data1 	0xeb, 0x29, 0xc7, 0x45, 0x10, 0x08, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x20, 0xc7, 0x45, 0x10, 0x0a, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x17, 0x83, 0x7d, 0x10, 0x10
+.data1 	0x75, 0x11, 0x80, 0x3e, 0x30, 0x75, 0x0c, 0x46
+.data1 	0x80, 0x3e, 0x78, 0x74, 0x05, 0x80, 0x3e, 0x58
+.data1 	0x75, 0x01, 0x46, 0x0f, 0xbe, 0x06, 0x89, 0xc7
+.data1 	0x89, 0xfa, 0x83, 0xea, 0x30, 0x83, 0xfa, 0x09
+.data1 	0x77, 0x0a, 0x89, 0xfa, 0x83, 0xea, 0x30, 0x89
+.data1 	0x55, 0xfc, 0xeb, 0x26, 0x89, 0xfa, 0x83, 0xea
+.data1 	0x61, 0x83, 0xfa, 0x19, 0x77, 0x0a, 0x89, 0xfa
+.data1 	0x83, 0xea, 0x57, 0x89, 0x55, 0xfc, 0xeb, 0x12
+.data1 	0x89, 0xfa, 0x83, 0xea, 0x41, 0x83, 0xfa, 0x19
+.data1 	0x77, 0x37, 0x89, 0xfa, 0x83, 0xea, 0x37, 0x89
+.data1 	0x55, 0xfc, 0x8b, 0x55, 0xfc, 0x39, 0x55, 0x10
+.data1 	0x76, 0x27, 0xba, 0xff, 0xff, 0xff, 0xff, 0x2b
+.data1 	0x55, 0xfc, 0x89, 0xd0, 0x31, 0xd2, 0xf7, 0x75
+.data1 	0x10, 0x39, 0x45, 0xf8, 0x76, 0x03, 0xff, 0x45
+.data1 	0xf0, 0x8b, 0x55, 0x10, 0x0f, 0xaf, 0x55, 0xf8
+.data1 	0x03, 0x55, 0xfc, 0x89, 0x55, 0xf8, 0x46, 0xeb
+.data1 	0x92, 0x83, 0x7d, 0x0c, 0x00, 0x74, 0x14, 0x39
+.data1 	0x75, 0xe4, 0x75, 0x0a, 0x8b, 0x55, 0xe8, 0x8b
+.data1 	0x45, 0x0c, 0x89, 0x10, 0xeb, 0x05, 0x8b, 0x45
+.data1 	0x0c, 0x89, 0x30, 0x83, 0x7d, 0xf0, 0x00, 0x75
+.data1 	0x27, 0x83, 0x7d, 0x14, 0x00, 0x74, 0x21, 0x83
+.data1 	0x7d, 0xec, 0x00, 0x79, 0x09, 0x81, 0x7d, 0xf8
+.data1 	0x00, 0x00, 0x00, 0x80, 0x77, 0x0f, 0x83, 0x7d
+.data1 	0xec, 0x00, 0x7e, 0x0c, 0x81, 0x7d, 0xf8, 0xff
+.data1 	0xff, 0xff, 0x7f, 0x76, 0x03, 0xff, 0x45, 0xf0
+.data1 	0x83, 0x7d, 0xf0, 0x00, 0x74, 0x2b, 0xc7, 0x05
+.data1 	0xf0, 0x27, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x14, 0x00, 0x74, 0x14, 0x83, 0x7d
+.data1 	0xec, 0x00, 0x79, 0x07, 0xb8, 0x00, 0x00, 0x00
+.data1 	0x80, 0xeb, 0x17, 0xb8, 0xff, 0xff, 0xff, 0x7f
+.data1 	0xeb, 0x10, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x09, 0x8b, 0x55, 0xec, 0x0f, 0xaf, 0x55, 0xf8
+.data1 	0x89, 0xd0, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x55, 0x08, 0x83, 0xea
+.data1 	0x41, 0x83, 0xfa, 0x1a, 0x73, 0x0a, 0x8b, 0x55
+.data1 	0x08, 0x83, 0xea, 0xe0, 0x89, 0xd0, 0xeb, 0x03
+.data1 	0x8b, 0x45, 0x08, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x55, 0x08, 0x83, 0xea
+.data1 	0x61, 0x83, 0xfa, 0x1a, 0x73, 0x0a, 0x8b, 0x55
+.data1 	0x08, 0x83, 0xea, 0x20, 0x89, 0xd0, 0xeb, 0x03
+.data1 	0x8b, 0x45, 0x08, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x15
+.data1 	0xf8, 0x27, 0x00, 0x00, 0x39, 0x55, 0x08, 0x74
+.data1 	0x2a, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xf0, 0x8d
+.data1 	0x45, 0xdc, 0x50, 0x6a, 0x11, 0x6a, 0x00, 0xe8
+.data1 	0xa0, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85
+.data1 	0xc0, 0x79, 0x07, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x0b, 0x8b, 0x55, 0xf8, 0x89, 0x15, 0xf8
+.data1 	0x27, 0x00, 0x00, 0x31, 0xc0, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x56, 0x57, 0x8b, 0x35, 0xf8, 0x27
+.data1 	0x00, 0x00, 0x8b, 0x15, 0xf8, 0x27, 0x00, 0x00
+.data1 	0x8b, 0x7d, 0x08, 0x01, 0xd7, 0x83, 0x7d, 0x08
+.data1 	0x00, 0x7e, 0x04, 0x39, 0xf7, 0x72, 0x0a, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x79, 0x0b, 0x39, 0xf7, 0x76
+.data1 	0x07, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x14
+.data1 	0x57, 0xe8, 0x8a, 0xff, 0xff, 0xff, 0x59, 0x85
+.data1 	0xc0, 0x75, 0x04, 0x89, 0xf0, 0xeb, 0x05, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x56, 0xff
+.data1 	0x75, 0x08, 0xe8, 0x69, 0x0e, 0x00, 0x00, 0x59
+.data1 	0x05, 0x01, 0x00, 0x00, 0x00, 0x89, 0x45, 0xfc
+.data1 	0x50, 0xe8, 0xe9, 0xf7, 0xff, 0xff, 0x59, 0x89
+.data1 	0xc6, 0x85, 0xf6, 0x75, 0x04, 0x31, 0xc0, 0xeb
+.data1 	0x0d, 0xff, 0x75, 0x08, 0x56, 0xe8, 0x26, 0x0e
+.data1 	0x00, 0x00, 0x59, 0x59, 0x89, 0xf0, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x10, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x56, 0x04, 0x56, 0xff, 0x75, 0x08, 0xe8, 0x4d
+.data1 	0x0d, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc7, 0x85
+.data1 	0xff, 0x74, 0x03, 0x89, 0x7e, 0x04, 0x83, 0x7e
+.data1 	0x04, 0x00, 0x79, 0x12, 0x8b, 0x56, 0x04, 0xf7
+.data1 	0xda, 0x89, 0x15, 0xf0, 0x27, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x03, 0x8b, 0x46
+.data1 	0x04, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x14, 0x56, 0x57
+.data1 	0x8b, 0x7d, 0x08, 0xff, 0x75, 0x0c, 0xe8, 0xe5
+.data1 	0x0d, 0x00, 0x00, 0x59, 0x66, 0x89, 0x45, 0xf2
+.data1 	0x89, 0x3d, 0xf4, 0x27, 0x00, 0x00, 0x68, 0x68
+.data1 	0x12, 0x00, 0x00, 0xe8, 0x88, 0xf6, 0xff, 0xff
+.data1 	0x59, 0x89, 0x45, 0xf8, 0x85, 0xc0, 0x75, 0x09
+.data1 	0xc7, 0x45, 0xf8, 0x58, 0x12, 0x00, 0x00, 0xeb
+.data1 	0x50, 0x8b, 0x55, 0xf8, 0x80, 0x3a, 0x2f, 0x74
+.data1 	0x48, 0x68, 0x50, 0x12, 0x00, 0x00, 0xe8, 0x65
+.data1 	0xf6, 0xff, 0xff, 0x59, 0x89, 0x45, 0xf4, 0x85
+.data1 	0xc0, 0x74, 0x2f, 0xff, 0x75, 0x0c, 0xff, 0x75
+.data1 	0xf4, 0xe8, 0x6a, 0x0d, 0x00, 0x00, 0x59, 0x59
+.data1 	0x85, 0xc0, 0x75, 0x1e, 0xc6, 0x07, 0x00, 0x68
+.data1 	0xff, 0x03, 0x00, 0x00, 0xff, 0x75, 0xf8, 0x57
+.data1 	0xe8, 0x93, 0x0d, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xb8, 0x01, 0x00, 0x00, 0x00, 0xe9, 0xf5, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x45, 0xf8, 0x40, 0x12, 0x00
+.data1 	0x00, 0x68, 0x3c, 0x12, 0x00, 0x00, 0xff, 0x75
+.data1 	0xf8, 0xe8, 0xc2, 0x09, 0x00, 0x00, 0x59, 0x59
+.data1 	0x89, 0x45, 0xfc, 0x85, 0xc0, 0x75, 0x14, 0xc7
+.data1 	0x05, 0xf4, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0xc4
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x45, 0xec, 0x00, 0x00
+.data1 	0x00, 0x00, 0x89, 0xfe, 0xba, 0x00, 0x04, 0x00
+.data1 	0x00, 0x2b, 0x55, 0xec, 0x89, 0xf9, 0x03, 0x4d
+.data1 	0xec, 0xff, 0x75, 0xfc, 0x52, 0x51, 0xe8, 0xdd
+.data1 	0x07, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0
+.data1 	0x75, 0x1a, 0xff, 0x75, 0xfc, 0xe8, 0x5a, 0x05
+.data1 	0x00, 0x00, 0x59, 0xc7, 0x05, 0xf4, 0x27, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0xc0, 0xe9
+.data1 	0x83, 0x00, 0x00, 0x00, 0x57, 0xe8, 0xfe, 0x0c
+.data1 	0x00, 0x00, 0x59, 0x2d, 0x02, 0x00, 0x00, 0x00
+.data1 	0x89, 0x45, 0xec, 0x01, 0xf8, 0x80, 0x38, 0x5c
+.data1 	0x74, 0xb2, 0x0f, 0xbe, 0x06, 0xf6, 0x80, 0xe1
+.data1 	0x26, 0x00, 0x00, 0x08, 0x74, 0x03, 0x46, 0xeb
+.data1 	0xf1, 0x80, 0x3e, 0x23, 0x74, 0x95, 0x0f, 0xbf
+.data1 	0x45, 0xf2, 0x50, 0x56, 0xff, 0x75, 0x0c, 0xe8
+.data1 	0xec, 0x0c, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85
+.data1 	0xc0, 0x75, 0x26, 0x0f, 0xbf, 0x45, 0xf2, 0x01
+.data1 	0xf0, 0x80, 0x38, 0x7c, 0x74, 0x0b, 0x0f, 0xbf
+.data1 	0x45, 0xf2, 0x01, 0xf0, 0x80, 0x38, 0x3a, 0x75
+.data1 	0x10, 0xff, 0x75, 0xfc, 0xe8, 0xeb, 0x04, 0x00
+.data1 	0x00, 0x59, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x1e, 0x80, 0x3e, 0x00, 0x74, 0x0d, 0x80, 0x3e
+.data1 	0x7c, 0x74, 0x08, 0x80, 0x3e, 0x3a, 0x74, 0x03
+.data1 	0x46, 0xeb, 0xee, 0x8a, 0x06, 0x46, 0x3c, 0x7c
+.data1 	0x74, 0xac, 0xe9, 0x3c, 0xff, 0xff, 0xff, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b
+.data1 	0x35, 0xf4, 0x27, 0x00, 0x00, 0x85, 0xf6, 0x74
+.data1 	0x06, 0x83, 0x7d, 0x08, 0x00, 0x75, 0x07, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x45, 0x8a, 0x06
+.data1 	0x46, 0x3c, 0x3a, 0x74, 0x0d, 0x80, 0x7e, 0xff
+.data1 	0x00, 0x75, 0xf3, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x31, 0x0f, 0xbe, 0x06, 0xf6, 0x80, 0xe1
+.data1 	0x26, 0x00, 0x00, 0x08, 0x74, 0x03, 0x46, 0xeb
+.data1 	0xf1, 0x6a, 0x02, 0xff, 0x75, 0x08, 0x56, 0xe8
+.data1 	0x54, 0x0c, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85
+.data1 	0xc0, 0x75, 0xcb, 0x80, 0x7e, 0x02, 0x23, 0x75
+.data1 	0xc5, 0x8d, 0x46, 0x03, 0x50, 0xe8, 0x12, 0xf4
+.data1 	0xff, 0xff, 0x59, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x56, 0x8b, 0x35, 0xf4, 0x27, 0x00, 0x00
+.data1 	0x85, 0xf6, 0x74, 0x06, 0x83, 0x7d, 0x08, 0x00
+.data1 	0x75, 0x07, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x37, 0x8a, 0x06, 0x46, 0x3c, 0x3a, 0x74, 0x0a
+.data1 	0x80, 0x7e, 0xff, 0x00, 0x75, 0xf3, 0x31, 0xc0
+.data1 	0xeb, 0x26, 0x0f, 0xbe, 0x06, 0xf6, 0x80, 0xe1
+.data1 	0x26, 0x00, 0x00, 0x08, 0x74, 0x03, 0x46, 0xeb
+.data1 	0xf1, 0x6a, 0x02, 0xff, 0x75, 0x08, 0x56, 0xe8
+.data1 	0xf4, 0x0b, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85
+.data1 	0xc0, 0x75, 0xce, 0xb8, 0x01, 0x00, 0x00, 0x00
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x14, 0x56, 0x57, 0x8b, 0x35, 0xf4, 0x27, 0x00
+.data1 	0x00, 0x8b, 0x45, 0x0c, 0x8b, 0x38, 0x85, 0xf6
+.data1 	0x74, 0x06, 0x83, 0x7d, 0x08, 0x00, 0x75, 0x07
+.data1 	0x31, 0xc0, 0xe9, 0x19, 0x01, 0x00, 0x00, 0x8a
+.data1 	0x06, 0x46, 0x3c, 0x3a, 0x74, 0x0d, 0x80, 0x7e
+.data1 	0xff, 0x00, 0x75, 0xf3, 0x31, 0xc0, 0xe9, 0x05
+.data1 	0x01, 0x00, 0x00, 0x0f, 0xbe, 0x06, 0xf6, 0x80
+.data1 	0xe1, 0x26, 0x00, 0x00, 0x08, 0x74, 0x03, 0x46
+.data1 	0xeb, 0xf1, 0x6a, 0x02, 0xff, 0x75, 0x08, 0x56
+.data1 	0xe8, 0x93, 0x0b, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x85, 0xc0, 0x75, 0xcb, 0x80, 0x7e, 0x02, 0x3d
+.data1 	0x75, 0xc5, 0x83, 0xc6, 0x03, 0x80, 0x3e, 0x00
+.data1 	0x0f, 0x84, 0xbe, 0x00, 0x00, 0x00, 0x80, 0x3e
+.data1 	0x3a, 0x0f, 0x84, 0xb5, 0x00, 0x00, 0x00, 0xe9
+.data1 	0x9c, 0x00, 0x00, 0x00, 0x46, 0x0f, 0xbe, 0x06
+.data1 	0x2d, 0x40, 0x00, 0x00, 0x00, 0x88, 0x07, 0xe9
+.data1 	0x99, 0x00, 0x00, 0x00, 0xc6, 0x07, 0x1b, 0xe9
+.data1 	0x91, 0x00, 0x00, 0x00, 0xc6, 0x07, 0x0a, 0xe9
+.data1 	0x89, 0x00, 0x00, 0x00, 0xc6, 0x07, 0x0d, 0xe9
+.data1 	0x81, 0x00, 0x00, 0x00, 0xc6, 0x07, 0x09, 0xe9
+.data1 	0x79, 0x00, 0x00, 0x00, 0xc6, 0x07, 0x08, 0xe9
+.data1 	0x71, 0x00, 0x00, 0x00, 0xc6, 0x07, 0x0c, 0xe9
+.data1 	0x69, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xf0, 0x00
+.data1 	0x00, 0x00, 0x00, 0xc7, 0x45, 0xf4, 0x00, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7d, 0xf4, 0x03, 0x7d, 0x26
+.data1 	0x0f, 0xbe, 0x06, 0x2d, 0x30, 0x00, 0x00, 0x00
+.data1 	0x3d, 0x0a, 0x00, 0x00, 0x00, 0x73, 0x17, 0x0f
+.data1 	0xbe, 0x06, 0x8b, 0x55, 0xf0, 0xc1, 0xe2, 0x03
+.data1 	0x01, 0xc2, 0x83, 0xea, 0x30, 0x89, 0x55, 0xf0
+.data1 	0xff, 0x45, 0xf4, 0x46, 0xeb, 0xd4, 0x8b, 0x55
+.data1 	0xf0, 0x88, 0x17, 0x4e, 0xeb, 0x27, 0x8a, 0x0e
+.data1 	0x88, 0x0f, 0xeb, 0x21, 0x46, 0x0f, 0xbe, 0x06
+.data1 	0xbb, 0x70, 0x12, 0x00, 0x00, 0xe9, 0x2a, 0x17
+.data1 	0x00, 0x00, 0x8a, 0x0e, 0x88, 0x0f, 0xeb, 0x0d
+.data1 	0x0f, 0xbe, 0x06, 0xbb, 0xc8, 0x12, 0x00, 0x00
+.data1 	0xe9, 0xeb, 0x16, 0x00, 0x00, 0x47, 0x46, 0xe9
+.data1 	0x39, 0xff, 0xff, 0xff, 0xc6, 0x07, 0x00, 0x47
+.data1 	0x8b, 0x45, 0x0c, 0x8b, 0x10, 0x89, 0x55, 0xec
+.data1 	0x8b, 0x45, 0x0c, 0x89, 0x38, 0x8b, 0x45, 0xec
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x0c, 0x56, 0x57, 0xbe, 0x00, 0x2c, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xf8, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x08, 0x80, 0x3a, 0x00, 0x0f, 0x84, 0x44
+.data1 	0x01, 0x00, 0x00, 0x80, 0x3a, 0x25, 0x0f, 0x85
+.data1 	0x2b, 0x01, 0x00, 0x00, 0xe9, 0x13, 0x01, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xf8, 0x01, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x22, 0x01, 0x00, 0x00, 0xc7, 0x45, 0xf4
+.data1 	0x01, 0x00, 0x00, 0x00, 0xe9, 0x16, 0x01, 0x00
+.data1 	0x00, 0x83, 0x7d, 0xf4, 0x00, 0x75, 0x05, 0x8b
+.data1 	0x45, 0x10, 0xeb, 0x03, 0x8b, 0x45, 0x0c, 0x89
+.data1 	0xc7, 0xff, 0x45, 0x08, 0x8b, 0x55, 0x08, 0x0f
+.data1 	0xbe, 0x02, 0x8b, 0x55, 0xf8, 0x01, 0xfa, 0x01
+.data1 	0xc2, 0x88, 0x16, 0x46, 0xba, 0x01, 0x00, 0x00
+.data1 	0x00, 0x2b, 0x55, 0xf4, 0x89, 0x55, 0xf4, 0xe9
+.data1 	0xe3, 0x00, 0x00, 0x00, 0x83, 0x7d, 0xf4, 0x00
+.data1 	0x75, 0x05, 0x8b, 0x45, 0x10, 0xeb, 0x03, 0x8b
+.data1 	0x45, 0x0c, 0x89, 0xc7, 0x8b, 0x55, 0xf8, 0x01
+.data1 	0xfa, 0xb9, 0x64, 0x00, 0x00, 0x00, 0x89, 0xd0
+.data1 	0x99, 0xf7, 0xf9, 0x89, 0xd7, 0xb9, 0x0a, 0x00
+.data1 	0x00, 0x00, 0x89, 0xf8, 0x99, 0xf7, 0xf9, 0x05
+.data1 	0x30, 0x00, 0x00, 0x00, 0x88, 0x06, 0x46, 0x89
+.data1 	0xf8, 0x99, 0xf7, 0xf9, 0x83, 0xc2, 0x30, 0x88
+.data1 	0x16, 0x46, 0xba, 0x01, 0x00, 0x00, 0x00, 0x2b
+.data1 	0x55, 0xf4, 0x89, 0x55, 0xf4, 0xe9, 0x95, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7d, 0xf4, 0x00, 0x75, 0x05
+.data1 	0x8b, 0x45, 0x10, 0xeb, 0x03, 0x8b, 0x45, 0x0c
+.data1 	0x89, 0xc7, 0x8b, 0x55, 0xf8, 0x01, 0xfa, 0xb9
+.data1 	0xe8, 0x03, 0x00, 0x00, 0x89, 0xd0, 0x99, 0xf7
+.data1 	0xf9, 0x89, 0xd7, 0x83, 0xff, 0x63, 0x7e, 0x12
+.data1 	0xb9, 0x64, 0x00, 0x00, 0x00, 0x89, 0xf8, 0x99
+.data1 	0xf7, 0xf9, 0x05, 0x30, 0x00, 0x00, 0x00, 0x88
+.data1 	0x06, 0x46, 0x83, 0xff, 0x09, 0x7e, 0x13, 0xb9
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x89, 0xf8, 0x99, 0xf7
+.data1 	0xf9, 0x99, 0xf7, 0xf9, 0x83, 0xc2, 0x30, 0x88
+.data1 	0x16, 0x46, 0xb9, 0x0a, 0x00, 0x00, 0x00, 0x89
+.data1 	0xf8, 0x99, 0xf7, 0xf9, 0x83, 0xc2, 0x30, 0x88
+.data1 	0x16, 0x46, 0xba, 0x01, 0x00, 0x00, 0x00, 0x2b
+.data1 	0x55, 0xf4, 0x89, 0x55, 0xf4, 0xeb, 0x28, 0xc6
+.data1 	0x06, 0x25, 0x46, 0xeb, 0x22, 0xb8, 0x18, 0x13
+.data1 	0x00, 0x00, 0xeb, 0x2b, 0xff, 0x45, 0x08, 0x8b
+.data1 	0x55, 0x08, 0x0f, 0xbe, 0x02, 0xbb, 0xe0, 0x12
+.data1 	0x00, 0x00, 0xe9, 0x9d, 0x15, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x08, 0x8a, 0x0a, 0x88, 0x0e, 0x46, 0xff
+.data1 	0x45, 0x08, 0xe9, 0xb0, 0xfe, 0xff, 0xff, 0xc6
+.data1 	0x06, 0x00, 0xb8, 0x00, 0x2c, 0x00, 0x00, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b
+.data1 	0x75, 0x08, 0x85, 0xf6, 0x75, 0x07, 0xb8, 0x01
+.data1 	0x00, 0x00, 0x00, 0xeb, 0x15, 0x80, 0x3e, 0x00
+.data1 	0x74, 0x0b, 0x0f, 0xbe, 0x06, 0x46, 0x50, 0xff
+.data1 	0x55, 0x10, 0x59, 0xeb, 0xf0, 0xb8, 0x01, 0x00
+.data1 	0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0x6a, 0x14, 0x6a, 0x00, 0xe8, 0x91
+.data1 	0xfa, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xe8, 0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x25
+.data1 	0x6a, 0x00, 0xe8, 0x6d, 0xfa, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe8
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf0, 0x8b, 0x55
+.data1 	0x10, 0x89, 0x55, 0xf4, 0xc7, 0x45, 0xf8, 0xe8
+.data1 	0xeb, 0x00, 0x00, 0x8d, 0x45, 0xdc, 0x50, 0x6a
+.data1 	0x47, 0x6a, 0x00, 0xe8, 0x3c, 0xfa, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0x7d, 0x0c, 0x17, 0x76
+.data1 	0x11, 0xc7, 0x05, 0xf0, 0x27, 0x00, 0x00, 0x16
+.data1 	0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x11, 0x8b, 0x4d, 0x0c, 0xba, 0x01, 0x00
+.data1 	0x00, 0x00, 0xd3, 0xe2, 0x8b, 0x45, 0x08, 0x09
+.data1 	0x10, 0x31, 0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x83, 0x7d, 0x0c, 0x17, 0x76, 0x11, 0xc7, 0x05
+.data1 	0xf0, 0x27, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x13, 0x8b
+.data1 	0x4d, 0x0c, 0xba, 0x01, 0x00, 0x00, 0x00, 0xd3
+.data1 	0xe2, 0xf7, 0xd2, 0x8b, 0x45, 0x08, 0x21, 0x10
+.data1 	0x31, 0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b
+.data1 	0x45, 0x08, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b
+.data1 	0x45, 0x08, 0xc7, 0x00, 0xff, 0xff, 0xff, 0x00
+.data1 	0x31, 0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0x7d, 0x0c, 0x17, 0x76, 0x11, 0xc7, 0x05, 0xf0
+.data1 	0x27, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x1a, 0x8b, 0x4d
+.data1 	0x0c, 0xba, 0x01, 0x00, 0x00, 0x00, 0xd3, 0xe2
+.data1 	0x8b, 0x45, 0x08, 0x85, 0x10, 0x74, 0x07, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x00, 0xeb, 0x02, 0x31, 0xc0
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x31, 0xff, 0x31, 0xf6, 0x83, 0xfe, 0x14
+.data1 	0x7d, 0x1c, 0x8b, 0x55, 0x08, 0x39, 0x14, 0xb5
+.data1 	0x88, 0x29, 0x00, 0x00, 0x75, 0x0d, 0xc7, 0x04
+.data1 	0xb5, 0x88, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x03, 0x46, 0xeb, 0xdf, 0x83, 0xfe
+.data1 	0x14, 0x7c, 0x0a, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0x6a, 0x00, 0x00, 0x00, 0xff, 0x75, 0x08
+.data1 	0xe8, 0x67, 0x00, 0x00, 0x00, 0x59, 0x85, 0xc0
+.data1 	0x74, 0x05, 0xbf, 0xff, 0xff, 0xff, 0xff, 0x8b
+.data1 	0x55, 0x08, 0xff, 0x72, 0x04, 0xe8, 0xfa, 0x08
+.data1 	0x00, 0x00, 0x59, 0x85, 0xc0, 0x74, 0x05, 0xbf
+.data1 	0xff, 0xff, 0xff, 0xff, 0x8b, 0x55, 0x08, 0x8b
+.data1 	0x52, 0x08, 0xf6, 0xc2, 0x08, 0x74, 0x12, 0x8b
+.data1 	0x55, 0x08, 0x83, 0x7a, 0x10, 0x00, 0x74, 0x09
+.data1 	0xff, 0x72, 0x10, 0xe8, 0xe6, 0xf2, 0xff, 0xff
+.data1 	0x59, 0x81, 0x7d, 0x08, 0x40, 0x29, 0x00, 0x00
+.data1 	0x74, 0x1b, 0x81, 0x7d, 0x08, 0x58, 0x29, 0x00
+.data1 	0x00, 0x74, 0x12, 0x81, 0x7d, 0x08, 0x70, 0x29
+.data1 	0x00, 0x00, 0x74, 0x09, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xc2, 0xf2, 0xff, 0xff, 0x59, 0x89, 0xf8, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x14, 0x56, 0x57, 0x8b, 0x75, 0x08, 0xc7
+.data1 	0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x85, 0xf6
+.data1 	0x75, 0x34, 0x31, 0xff, 0x83, 0xff, 0x14, 0x7d
+.data1 	0x25, 0x83, 0x3c, 0xbd, 0x88, 0x29, 0x00, 0x00
+.data1 	0x00, 0x74, 0x18, 0xff, 0x34, 0xbd, 0x88, 0x29
+.data1 	0x00, 0x00, 0xe8, 0xcd, 0xff, 0xff, 0xff, 0x59
+.data1 	0x85, 0xc0, 0x74, 0x07, 0xc7, 0x45, 0xf0, 0xff
+.data1 	0xff, 0xff, 0xff, 0x47, 0xeb, 0xd6, 0x8b, 0x45
+.data1 	0xf0, 0xe9, 0x43, 0x01, 0x00, 0x00, 0x83, 0x7e
+.data1 	0x10, 0x00, 0x74, 0x11, 0x8b, 0x56, 0x08, 0xf6
+.data1 	0xc2, 0x80, 0x75, 0x10, 0xf7, 0x46, 0x08, 0x00
+.data1 	0x01, 0x00, 0x00, 0x75, 0x07, 0x31, 0xc0, 0xe9
+.data1 	0x25, 0x01, 0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6
+.data1 	0xc2, 0x80, 0x0f, 0x84, 0x86, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, 0x00, 0xf7
+.data1 	0x46, 0x08, 0x00, 0x04, 0x00, 0x00, 0x74, 0x07
+.data1 	0x31, 0xc0, 0xe9, 0x02, 0x01, 0x00, 0x00, 0x83
+.data1 	0x7e, 0x10, 0x00, 0x74, 0x0f, 0x8b, 0x56, 0x08
+.data1 	0xf6, 0xc2, 0x04, 0x75, 0x07, 0x8b, 0x16, 0xf7
+.data1 	0xda, 0x89, 0x55, 0xec, 0xc7, 0x06, 0x00, 0x00
+.data1 	0x00, 0x00, 0x6a, 0x01, 0xff, 0x75, 0xec, 0xff
+.data1 	0x76, 0x04, 0xe8, 0x05, 0x0c, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x17, 0x83, 0x3d, 0xf0, 0x27, 0x00, 0x00, 0x1d
+.data1 	0x74, 0x0e, 0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xe9, 0xb9, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x05, 0xf0, 0x27, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x02
+.data1 	0x74, 0x07, 0x81, 0x66, 0x08, 0x7f, 0xfe, 0xff
+.data1 	0xff, 0x8b, 0x56, 0x10, 0x89, 0x56, 0x14, 0x31
+.data1 	0xc0, 0xe9, 0x93, 0x00, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x04, 0x74, 0x07, 0x31, 0xc0
+.data1 	0xe9, 0x84, 0x00, 0x00, 0x00, 0x8b, 0x56, 0x08
+.data1 	0xf6, 0xc2, 0x01, 0x74, 0x07, 0x81, 0x66, 0x08
+.data1 	0xff, 0xfe, 0xff, 0xff, 0x8b, 0x56, 0x14, 0x2b
+.data1 	0x56, 0x10, 0x89, 0x55, 0xfc, 0x8b, 0x56, 0x10
+.data1 	0x89, 0x56, 0x14, 0x83, 0x7d, 0xfc, 0x00, 0x7f
+.data1 	0x07, 0x31, 0xc0, 0xe9, 0x59, 0x00, 0x00, 0x00
+.data1 	0xf7, 0x46, 0x08, 0x00, 0x02, 0x00, 0x00, 0x74
+.data1 	0x21, 0x6a, 0x02, 0x6a, 0x00, 0xff, 0x76, 0x04
+.data1 	0xe8, 0x6f, 0x0b, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x0b, 0x83
+.data1 	0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x2f, 0xff, 0x75, 0xfc, 0xff, 0x76, 0x10
+.data1 	0xff, 0x76, 0x04, 0xe8, 0x70, 0x10, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x45, 0xf8, 0xc7, 0x06
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xf8, 0x39
+.data1 	0x55, 0xfc, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x09
+.data1 	0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x56, 0x31, 0xf6, 0x83, 0xfe, 0x14, 0x7d, 0x2a
+.data1 	0x83, 0x3c, 0xb5, 0x88, 0x29, 0x00, 0x00, 0x00
+.data1 	0x74, 0x1d, 0x8b, 0x14, 0xb5, 0x88, 0x29, 0x00
+.data1 	0x00, 0xf7, 0x42, 0x08, 0x00, 0x01, 0x00, 0x00
+.data1 	0x74, 0x0d, 0xff, 0x34, 0xb5, 0x88, 0x29, 0x00
+.data1 	0x00, 0xe8, 0x3e, 0xfe, 0xff, 0xff, 0x59, 0x46
+.data1 	0xeb, 0xd1, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x04, 0x56, 0x57
+.data1 	0x8b, 0x75, 0x10, 0x8b, 0x7d, 0x08, 0xff, 0x4d
+.data1 	0x0c, 0x83, 0x7d, 0x0c, 0x00, 0x7e, 0x2f, 0x8b
+.data1 	0x16, 0x4a, 0x89, 0x16, 0x78, 0x0e, 0x8b, 0x46
+.data1 	0x14, 0x83, 0x46, 0x14, 0x01, 0x0f, 0xb6, 0x18
+.data1 	0x53, 0x58, 0xeb, 0x07, 0x56, 0xe8, 0x3a, 0x00
+.data1 	0x00, 0x00, 0x59, 0x89, 0x45, 0xfc, 0x3d, 0xff
+.data1 	0xff, 0xff, 0xff, 0x74, 0x09, 0x88, 0x07, 0x47
+.data1 	0x83, 0x7d, 0xfc, 0x0a, 0x75, 0xc8, 0x83, 0x7d
+.data1 	0xfc, 0xff, 0x75, 0x15, 0x8b, 0x56, 0x08, 0xf6
+.data1 	0xc2, 0x10, 0x74, 0x09, 0x39, 0x7d, 0x08, 0x75
+.data1 	0x08, 0x31, 0xc0, 0xeb, 0x0a, 0x31, 0xc0, 0xeb
+.data1 	0x06, 0xc6, 0x07, 0x00, 0x8b, 0x45, 0x08, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x08, 0xc7, 0x06, 0x00, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7e, 0x04, 0x00, 0x79, 0x0a
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x1a, 0x01
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x30
+.data1 	0x74, 0x0a, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9
+.data1 	0x08, 0x01, 0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6
+.data1 	0xc2, 0x01, 0x75, 0x0e, 0x83, 0x4e, 0x08, 0x20
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0xf2, 0x00
+.data1 	0x00, 0x00, 0xf7, 0x46, 0x08, 0x00, 0x01, 0x00
+.data1 	0x00, 0x74, 0x0e, 0x83, 0x4e, 0x08, 0x20, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe9, 0xdb, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x80, 0x75
+.data1 	0x07, 0x81, 0x4e, 0x08, 0x80, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x04, 0x75, 0x2b
+.data1 	0x83, 0x7e, 0x10, 0x00, 0x75, 0x25, 0x68, 0x00
+.data1 	0x04, 0x00, 0x00, 0xe8, 0xe7, 0xed, 0xff, 0xff
+.data1 	0x59, 0x89, 0x46, 0x10, 0x83, 0x7e, 0x10, 0x00
+.data1 	0x75, 0x06, 0x83, 0x4e, 0x08, 0x04, 0xeb, 0x0b
+.data1 	0x83, 0x4e, 0x08, 0x08, 0xc7, 0x46, 0x0c, 0x00
+.data1 	0x04, 0x00, 0x00, 0x31, 0xff, 0x83, 0xff, 0x14
+.data1 	0x7d, 0x39, 0x83, 0x3c, 0xbd, 0x88, 0x29, 0x00
+.data1 	0x00, 0x00, 0x74, 0x2c, 0x8b, 0x14, 0xbd, 0x88
+.data1 	0x29, 0x00, 0x00, 0x8b, 0x52, 0x08, 0xf6, 0xc2
+.data1 	0x40, 0x74, 0x1d, 0x8b, 0x14, 0xbd, 0x88, 0x29
+.data1 	0x00, 0x00, 0xf7, 0x42, 0x08, 0x00, 0x01, 0x00
+.data1 	0x00, 0x74, 0x0d, 0xff, 0x34, 0xbd, 0x88, 0x29
+.data1 	0x00, 0x00, 0xe8, 0xed, 0xfc, 0xff, 0xff, 0x59
+.data1 	0x47, 0xeb, 0xc2, 0x83, 0x7e, 0x10, 0x00, 0x75
+.data1 	0x12, 0x8b, 0x46, 0x04, 0x05, 0x18, 0x2c, 0x00
+.data1 	0x00, 0x89, 0x46, 0x10, 0xc7, 0x46, 0x0c, 0x01
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x56, 0x10, 0x89, 0x56
+.data1 	0x14, 0xff, 0x76, 0x0c, 0xff, 0x76, 0x10, 0xff
+.data1 	0x76, 0x04, 0xe8, 0x9d, 0x0b, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0x06, 0x85, 0xc0, 0x7f, 0x16
+.data1 	0x83, 0x3e, 0x00, 0x75, 0x06, 0x83, 0x4e, 0x08
+.data1 	0x10, 0xeb, 0x04, 0x83, 0x4e, 0x08, 0x20, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x0e, 0xff, 0x0e
+.data1 	0x8b, 0x46, 0x14, 0x83, 0x46, 0x14, 0x01, 0x0f
+.data1 	0xb6, 0x18, 0x53, 0x58, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x38, 0x56, 0x57
+.data1 	0xc7, 0x45, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x31, 0xf6
+.data1 	0x31, 0xff, 0x83, 0x3c, 0xbd, 0x88, 0x29, 0x00
+.data1 	0x00, 0x00, 0x74, 0x4e, 0x83, 0xff, 0x13, 0x7c
+.data1 	0x07, 0x31, 0xc0, 0xe9, 0x7e, 0x01, 0x00, 0x00
+.data1 	0x47, 0xeb, 0xe7, 0x81, 0xce, 0x81, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xf8, 0x00, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x43, 0x81, 0xce, 0x02, 0x01, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xf8, 0x01, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xf4, 0x30, 0x00, 0x00, 0x00, 0xeb, 0x2d
+.data1 	0x81, 0xce, 0x02, 0x03, 0x00, 0x00, 0xc7, 0x45
+.data1 	0xf8, 0x01, 0x00, 0x00, 0x00, 0x83, 0x4d, 0xf4
+.data1 	0x50, 0xeb, 0x1a, 0x31, 0xc0, 0xe9, 0x3c, 0x01
+.data1 	0x00, 0x00, 0x8b, 0x45, 0x0c, 0xff, 0x45, 0x0c
+.data1 	0x0f, 0xbe, 0x00, 0xbb, 0x20, 0x13, 0x00, 0x00
+.data1 	0xe9, 0x8f, 0x0f, 0x00, 0x00, 0x8b, 0x55, 0x0c
+.data1 	0x80, 0x3a, 0x00, 0x74, 0x21, 0xeb, 0x0c, 0xc7
+.data1 	0x45, 0xf8, 0x02, 0x00, 0x00, 0x00, 0x83, 0xce
+.data1 	0x03, 0xeb, 0xea, 0x8b, 0x45, 0x0c, 0xff, 0x45
+.data1 	0x0c, 0x0f, 0xbe, 0x00, 0xbb, 0x40, 0x13, 0x00
+.data1 	0x00, 0xe9, 0x66, 0x0f, 0x00, 0x00, 0x8b, 0x55
+.data1 	0xf4, 0xf6, 0xc2, 0x20, 0x75, 0x1c, 0xff, 0x75
+.data1 	0xf8, 0xff, 0x75, 0x08, 0xe8, 0x13, 0x09, 0x00
+.data1 	0x00, 0x59, 0x59, 0x89, 0x45, 0xc8, 0x85, 0xc0
+.data1 	0x79, 0x40, 0x8b, 0x55, 0xf4, 0xf6, 0xc2, 0x10
+.data1 	0x74, 0x38, 0x68, 0xb6, 0x01, 0x00, 0x00, 0xff
+.data1 	0x75, 0x08, 0xe8, 0xb1, 0x04, 0x00, 0x00, 0x59
+.data1 	0x59, 0x89, 0x45, 0xc8, 0x85, 0xc0, 0x7e, 0x22
+.data1 	0xba, 0x01, 0x00, 0x00, 0x00, 0x09, 0xf2, 0x74
+.data1 	0x19, 0xff, 0x75, 0xc8, 0xe8, 0x3b, 0x04, 0x00
+.data1 	0x00, 0x59, 0xff, 0x75, 0xf8, 0xff, 0x75, 0x08
+.data1 	0xe8, 0xcf, 0x08, 0x00, 0x00, 0x59, 0x59, 0x89
+.data1 	0x45, 0xc8, 0x83, 0x7d, 0xc8, 0x00, 0x79, 0x07
+.data1 	0x31, 0xc0, 0xe9, 0x97, 0x00, 0x00, 0x00, 0x8d
+.data1 	0x45, 0xcc, 0x50, 0xff, 0x75, 0xc8, 0xe8, 0xd5
+.data1 	0x00, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x79
+.data1 	0x10, 0xff, 0x75, 0xc8, 0xe8, 0x03, 0x04, 0x00
+.data1 	0x00, 0x59, 0x31, 0xc0, 0xe9, 0x75, 0x00, 0x00
+.data1 	0x00, 0x0f, 0xb7, 0x55, 0xd4, 0x81, 0xe2, 0x00
+.data1 	0xf0, 0x00, 0x00, 0x81, 0xfa, 0x00, 0x10, 0x00
+.data1 	0x00, 0x75, 0x06, 0x81, 0xce, 0x00, 0x04, 0x00
+.data1 	0x00, 0x6a, 0x18, 0xe8, 0xd7, 0xeb, 0xff, 0xff
+.data1 	0x59, 0x89, 0x45, 0xf0, 0x85, 0xc0, 0x75, 0x0d
+.data1 	0xff, 0x75, 0xc8, 0xe8, 0xcc, 0x03, 0x00, 0x00
+.data1 	0x59, 0x31, 0xc0, 0xeb, 0x41, 0xba, 0x03, 0x00
+.data1 	0x00, 0x00, 0x21, 0xf2, 0x83, 0xfa, 0x03, 0x75
+.data1 	0x06, 0x81, 0xe6, 0x7f, 0xfe, 0xff, 0xff, 0x8b
+.data1 	0x45, 0xf0, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x55, 0xf0, 0x8b, 0x4d, 0xc8, 0x89, 0x4a
+.data1 	0x04, 0x8b, 0x55, 0xf0, 0x89, 0x72, 0x08, 0x8b
+.data1 	0x55, 0xf0, 0xc7, 0x42, 0x10, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xf0, 0x89, 0x14, 0xbd, 0x88
+.data1 	0x29, 0x00, 0x00, 0x8b, 0x45, 0xf0, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0xe9, 0x0f, 0x03, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0x2f, 0x03, 0x00
+.data1 	0x00, 0xe9, 0x50, 0x03, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x67, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xdf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xf3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xfb, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x53, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x63, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x7f, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xa3, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xab, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xbf, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xd3, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xf7, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xa3, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x3f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x8f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xeb, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xdf, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x33, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xfb, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x2b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x3b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x7f, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0x9b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xd3, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0xe9, 0x76, 0x0a, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x01, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x02
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x03, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0xb9, 0x04, 0x00, 0x00, 0x00
+.data1 	0xcd, 0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x53, 0x8b, 0x5d, 0x08, 0xb9, 0x08, 0x00, 0x00
+.data1 	0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x08
+.data1 	0x8b, 0x75, 0x0c, 0x8b, 0x4d, 0x10, 0xe9, 0x97
+.data1 	0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xba, 0xff, 0xff, 0xff, 0xff, 0xe9, 0xca, 0x0b
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x57, 0xfc, 0x8b, 0x7d, 0x08
+.data1 	0xba, 0x10, 0x00, 0x00, 0x00, 0xd1, 0xe2, 0x89
+.data1 	0xd1, 0x30, 0xc0, 0xf2, 0xae, 0x9c, 0x29, 0xd1
+.data1 	0xf7, 0xd9, 0x29, 0xcf, 0x8a, 0x45, 0x0c, 0xf2
+.data1 	0xae, 0x74, 0x08, 0x9d, 0x75, 0xe7, 0x31, 0xc0
+.data1 	0x5f, 0x5d, 0xc3, 0x58, 0x8d, 0x47, 0xff, 0x5f
+.data1 	0x5d, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb9, 0xff, 0xff, 0xff, 0xff, 0xe9, 0xaa, 0x0b
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0xb9, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe8, 0xc5, 0x0b, 0x00, 0x00, 0x8b
+.data1 	0x45, 0x08, 0x5f, 0x5e, 0x5d, 0xc3, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb9, 0xff, 0xff, 0xff, 0xff, 0xe9, 0xca, 0x0b
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x54, 0x24, 0x0c, 0xe9, 0x3b, 0x0b, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x4c, 0x24, 0x0c, 0xe9, 0x5b, 0x0b, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x57, 0x8b, 0x7d, 0x08, 0xb9
+.data1 	0xff, 0xff, 0xff, 0xff, 0x30, 0xc0, 0xfc, 0xf2
+.data1 	0xae, 0xf7, 0xd1, 0x4f, 0x8a, 0x45, 0x0c, 0xfd
+.data1 	0xf2, 0xae, 0xfc, 0x75, 0x06, 0x8d, 0x47, 0x01
+.data1 	0x5f, 0x5d, 0xc3, 0x31, 0xc0, 0x5f, 0x5d, 0xc3
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x8b, 0x55, 0x08, 0x8b, 0x4d
+.data1 	0x0c, 0x89, 0x4a, 0x10, 0x83, 0x7d, 0x0c, 0x00
+.data1 	0x74, 0x0d, 0x8b, 0x55, 0x08, 0x83, 0xc2, 0x0c
+.data1 	0x52, 0xe8, 0x7f, 0x00, 0x00, 0x00, 0x59, 0x8b
+.data1 	0x5d, 0x08, 0xff, 0x75, 0x00, 0x8d, 0x45, 0x08
+.data1 	0x50, 0xff, 0x75, 0x10, 0xb9, 0x0c, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x36, 0x0c, 0x00, 0x00, 0x31, 0xc0
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b, 0x45, 0x08
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b, 0x55, 0x08
+.data1 	0x83, 0x7a, 0x10, 0x00, 0x74, 0x0a, 0x83, 0xc2
+.data1 	0x0c, 0x52, 0xe8, 0x5a, 0x00, 0x00, 0x00, 0x59
+.data1 	0xff, 0x75, 0x08, 0x68, 0x2c, 0x2c, 0x00, 0x00
+.data1 	0xb9, 0x03, 0x00, 0x00, 0x00, 0xe8, 0x66, 0x0b
+.data1 	0x00, 0x00, 0x8b, 0x55, 0x0c, 0x52, 0x85, 0xd2
+.data1 	0x75, 0x03, 0x5a, 0x42, 0x52, 0xe8, 0xc0, 0xff
+.data1 	0xff, 0xff, 0x59, 0xbb, 0x2c, 0x2c, 0x00, 0x00
+.data1 	0xe9, 0xc3, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0xeb, 0x02, 0xeb, 0x0c, 0xbb
+.data1 	0xd0, 0x18, 0x00, 0x00, 0x31, 0xc0, 0xe9, 0x4d
+.data1 	0x0b, 0x00, 0x00, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0xff, 0x75, 0x08, 0x6a, 0x00, 0x6a, 0x02, 0xe8
+.data1 	0xd8, 0x07, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x6a, 0x00, 0xff, 0x75
+.data1 	0x08, 0x6a, 0x02, 0xe8, 0xc4, 0x07, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe0, 0x8d, 0x45, 0xd8, 0x50
+.data1 	0x6a, 0x01, 0x6a, 0x00, 0xe8, 0x83, 0xf0, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0xba, 0xff, 0xff, 0xff
+.data1 	0xff, 0x89, 0x55, 0xfc, 0xff, 0xd2, 0xeb, 0xfe
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0xff, 0x75, 0x08, 0xe8, 0x92, 0x0a
+.data1 	0x00, 0x00, 0x59, 0x59, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x6a, 0x0c, 0x6a, 0x01, 0xe8, 0x53, 0xf0, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55, 0x08, 0x89
+.data1 	0x55, 0xe4, 0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x56
+.data1 	0x6a, 0x01, 0xe8, 0x35, 0xf0, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x06, 0x6a, 0x01
+.data1 	0xe8, 0x17, 0xf0, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x04, 0x83, 0x7d, 0x08, 0x00, 0x75, 0x11
+.data1 	0xc7, 0x05, 0xf0, 0x27, 0x00, 0x00, 0x09, 0x00
+.data1 	0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x1b, 0x8b, 0x55, 0x08, 0x0f, 0xbe, 0x02, 0x89
+.data1 	0x45, 0xfc, 0xff, 0x75, 0x08, 0xe8, 0xc4, 0xe9
+.data1 	0xff, 0xff, 0x59, 0xff, 0x75, 0xfc, 0xe8, 0xa9
+.data1 	0xff, 0xff, 0xff, 0x59, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x0c, 0x89, 0x55, 0xe8, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xec, 0x09, 0x00, 0x00
+.data1 	0x59, 0x59, 0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x08
+.data1 	0x6a, 0x01, 0xe8, 0xad, 0xef, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x8b
+.data1 	0x15, 0x2c, 0x19, 0x00, 0x00, 0xff, 0x32, 0x8d
+.data1 	0x45, 0x0c, 0x50, 0xff, 0x75, 0x08, 0xe8, 0x05
+.data1 	0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x4c, 0x56, 0x57
+.data1 	0xc7, 0x45, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x31
+.data1 	0xf6, 0xc7, 0x45, 0xe0, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x0c, 0x89, 0x55, 0xfc, 0x8b, 0x45, 0xfc
+.data1 	0x83, 0x38, 0x00, 0x74, 0x2b, 0xff, 0x30, 0xe8
+.data1 	0x94, 0xfd, 0xff, 0xff, 0x59, 0x05, 0x05, 0x00
+.data1 	0x00, 0x00, 0x89, 0x45, 0xdc, 0x01, 0xc6, 0x39
+.data1 	0x75, 0xdc, 0x76, 0x07, 0xc7, 0x45, 0xd8, 0x01
+.data1 	0x00, 0x00, 0x00, 0x83, 0x45, 0xe0, 0x04, 0xff
+.data1 	0x45, 0xe8, 0x83, 0x45, 0xfc, 0x04, 0xeb, 0xcd
+.data1 	0x8b, 0x55, 0x10, 0x89, 0x55, 0xf8, 0x8b, 0x45
+.data1 	0xf8, 0x83, 0x38, 0x00, 0x74, 0x28, 0xff, 0x30
+.data1 	0xe8, 0x5b, 0xfd, 0xff, 0xff, 0x59, 0x05, 0x05
+.data1 	0x00, 0x00, 0x00, 0x89, 0x45, 0xdc, 0x01, 0xc6
+.data1 	0x39, 0x75, 0xdc, 0x76, 0x07, 0xc7, 0x45, 0xd8
+.data1 	0x01, 0x00, 0x00, 0x00, 0x83, 0x45, 0xe0, 0x04
+.data1 	0x83, 0x45, 0xf8, 0x04, 0xeb, 0xd0, 0x83, 0xc6
+.data1 	0x0c, 0x83, 0x45, 0xe0, 0x0c, 0x8d, 0x56, 0x03
+.data1 	0xbe, 0xfc, 0xff, 0xff, 0xff, 0x21, 0xd6, 0x83
+.data1 	0x7d, 0xd8, 0x00, 0x75, 0x05, 0x83, 0xfe, 0x0c
+.data1 	0x73, 0x14, 0xc7, 0x05, 0xf0, 0x27, 0x00, 0x00
+.data1 	0x07, 0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x4b, 0x01, 0x00, 0x00, 0x56, 0xe8
+.data1 	0x43, 0xee, 0xff, 0xff, 0x59, 0x89, 0x45, 0xf4
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x14, 0xc7
+.data1 	0x05, 0xf0, 0x27, 0x00, 0x00, 0x07, 0x00, 0x00
+.data1 	0x00, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x26
+.data1 	0x01, 0x00, 0x00, 0x8b, 0x55, 0xe8, 0x8b, 0x45
+.data1 	0xf4, 0x89, 0x10, 0x8b, 0x55, 0xf4, 0x83, 0xc2
+.data1 	0x04, 0x89, 0x55, 0xf0, 0x8b, 0x55, 0xf4, 0x8b
+.data1 	0x7d, 0xe0, 0x01, 0xd7, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xfc, 0x8b, 0x45, 0xfc, 0x83, 0x38, 0x00
+.data1 	0x74, 0x3d, 0x89, 0xfa, 0x2b, 0x55, 0xf4, 0x8b
+.data1 	0x45, 0xf0, 0x89, 0x10, 0x83, 0x45, 0xf0, 0x04
+.data1 	0x8b, 0x45, 0xfc, 0xff, 0x30, 0xe8, 0xa6, 0xfc
+.data1 	0xff, 0xff, 0x59, 0x05, 0x01, 0x00, 0x00, 0x00
+.data1 	0x89, 0x45, 0xdc, 0x8b, 0x5d, 0xfc, 0x50, 0xff
+.data1 	0x33, 0x57, 0xe8, 0xf1, 0xfb, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0xfa, 0x8b, 0x7d, 0xdc, 0x01
+.data1 	0xd7, 0x83, 0x45, 0xfc, 0x04, 0xeb, 0xbb, 0x8b
+.data1 	0x45, 0xf0, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x83, 0x45, 0xf0, 0x04, 0x8b, 0x55, 0x10, 0x89
+.data1 	0x55, 0xf8, 0x8b, 0x45, 0xf8, 0x83, 0x38, 0x00
+.data1 	0x74, 0x3d, 0x89, 0xfa, 0x2b, 0x55, 0xf4, 0x8b
+.data1 	0x45, 0xf0, 0x89, 0x10, 0x83, 0x45, 0xf0, 0x04
+.data1 	0x8b, 0x45, 0xf8, 0xff, 0x30, 0xe8, 0x4e, 0xfc
+.data1 	0xff, 0xff, 0x59, 0x05, 0x01, 0x00, 0x00, 0x00
+.data1 	0x89, 0x45, 0xdc, 0x8b, 0x5d, 0xf8, 0x50, 0xff
+.data1 	0x33, 0x57, 0xe8, 0x99, 0xfb, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0xfa, 0x8b, 0x7d, 0xdc, 0x01
+.data1 	0xd7, 0x83, 0x45, 0xf8, 0x04, 0xeb, 0xbb, 0x8b
+.data1 	0x45, 0xf0, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x83, 0x45, 0xf0, 0x04, 0x8b, 0x55, 0xf4, 0x01
+.data1 	0xf2, 0x39, 0xfa, 0x76, 0x06, 0xc6, 0x07, 0x00
+.data1 	0x47, 0xeb, 0xf1, 0xff, 0x75, 0x08, 0xe8, 0x05
+.data1 	0xfc, 0xff, 0xff, 0x59, 0x05, 0x01, 0x00, 0x00
+.data1 	0x00, 0x89, 0x45, 0xbc, 0x89, 0x75, 0xc0, 0x8b
+.data1 	0x55, 0x08, 0x89, 0x55, 0xc8, 0x8b, 0x55, 0xf4
+.data1 	0x89, 0x55, 0xcc, 0xc7, 0x45, 0xc4, 0x00, 0x00
+.data1 	0x00, 0x00, 0xc7, 0x45, 0xd0, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8d, 0x45, 0xb4, 0x50, 0x6a, 0x3b, 0x6a
+.data1 	0x00, 0xe8, 0x96, 0xed, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0x89, 0xf2, 0xf7, 0xda, 0x52, 0xe8, 0x04
+.data1 	0xed, 0xff, 0xff, 0x59, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x56, 0x8d
+.data1 	0x75, 0x10, 0xc7, 0x45, 0xe8, 0x00, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x1a, 0x8d, 0x56, 0x04, 0x89, 0xd6, 0x8b
+.data1 	0x52, 0xfc, 0x89, 0x55, 0xe8, 0xeb, 0x1a, 0x8d
+.data1 	0x56, 0x04, 0x89, 0xd6, 0x8b, 0x52, 0xfc, 0x89
+.data1 	0x55, 0xec, 0xeb, 0x0d, 0xbb, 0xe4, 0x18, 0x00
+.data1 	0x00, 0x8b, 0x45, 0x0c, 0xe9, 0xbf, 0x07, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe0, 0x8b
+.data1 	0x55, 0x0c, 0x89, 0x55, 0xe4, 0x8d, 0x45, 0xd8
+.data1 	0x50, 0x6a, 0x37, 0x6a, 0x01, 0xe8, 0x22, 0xed
+.data1 	0xff, 0xff, 0x83, 0xc4, 0x0c, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0x6a, 0x02, 0x6a, 0x00, 0xe8, 0x09
+.data1 	0xed, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xf0, 0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x1c
+.data1 	0x6a, 0x01, 0xe8, 0xe5, 0xec, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x2f
+.data1 	0x6a, 0x00, 0xe8, 0xcd, 0xec, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x85, 0xc0, 0x79, 0x07, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xeb, 0x06, 0x8b, 0x45, 0xe4
+.data1 	0x0f, 0xbe, 0xc0, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0x6a, 0x18, 0x6a, 0x00, 0xe8, 0xa1
+.data1 	0xec, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x85, 0xc0
+.data1 	0x79, 0x07, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x06, 0x8b, 0x45, 0xe4, 0x0f, 0xbf, 0xc0, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x18
+.data1 	0x6a, 0x00, 0xe8, 0x75, 0xec, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x0f, 0xbf, 0xc0, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xec, 0x8b, 0x55, 0x10, 0x89, 0x55, 0xf8
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x36, 0x6a, 0x01
+.data1 	0xe8, 0x47, 0xec, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8d, 0x45, 0xdc, 0x50, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x6a, 0x04, 0x00, 0x00, 0x59, 0x59
+.data1 	0x31, 0xdb, 0x85, 0xc0, 0x0f, 0x94, 0xc3, 0x89
+.data1 	0xd8, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf0, 0x8b, 0x55
+.data1 	0x10, 0x89, 0x55, 0xe8, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x6a, 0x13, 0x6a, 0x01, 0xe8, 0xfb, 0xeb, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x79, 0x07
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x03, 0x8b
+.data1 	0x45, 0xf0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0xff, 0x75, 0x08, 0xe8, 0x16, 0xfa
+.data1 	0xff, 0xff, 0x59, 0x05, 0x01, 0x00, 0x00, 0x00
+.data1 	0x89, 0x45, 0xe4, 0x8b, 0x55, 0x08, 0x89, 0x55
+.data1 	0xf0, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf4, 0x8d
+.data1 	0x45, 0xdc, 0x50, 0x6a, 0x32, 0x6a, 0x01, 0xe8
+.data1 	0xb8, 0xeb, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0x45, 0xd8, 0x85, 0xc0, 0x79, 0x09, 0x83, 0x3d
+.data1 	0xf0, 0x27, 0x00, 0x00, 0x26, 0x74, 0x05, 0x8b
+.data1 	0x45, 0xd8, 0xeb, 0x0d, 0xff, 0x75, 0x0c, 0xff
+.data1 	0x75, 0x08, 0xe8, 0x99, 0x03, 0x00, 0x00, 0x59
+.data1 	0x59, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x28, 0x56, 0x8d, 0x75, 0x10, 0x8b, 0x55
+.data1 	0x0c, 0xf6, 0xc2, 0x40, 0x74, 0x2a, 0xff, 0x75
+.data1 	0x08, 0xe8, 0xb2, 0xf9, 0xff, 0xff, 0x59, 0x05
+.data1 	0x01, 0x00, 0x00, 0x00, 0x89, 0x45, 0xe0, 0x8b
+.data1 	0x55, 0x0c, 0x89, 0x55, 0xe4, 0x8d, 0x56, 0x04
+.data1 	0x89, 0xd6, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xe8
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xec, 0xeb, 0x14
+.data1 	0x8d, 0x45, 0xd8, 0x50, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x78, 0x05, 0x00, 0x00, 0x59, 0x59, 0x8b, 0x55
+.data1 	0x0c, 0x89, 0x55, 0xe4, 0x8d, 0x45, 0xd8, 0x50
+.data1 	0x6a, 0x05, 0x6a, 0x01, 0xe8, 0x33, 0xeb, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0x5e, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x34, 0x56, 0x57
+.data1 	0x8d, 0x45, 0xd0, 0x50, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x1c, 0x03, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0
+.data1 	0x79, 0x07, 0x31, 0xc0, 0xe9, 0xd6, 0x00, 0x00
+.data1 	0x00, 0x0f, 0xb7, 0x55, 0xd8, 0x81, 0xe2, 0x00
+.data1 	0xf0, 0x00, 0x00, 0x81, 0xfa, 0x00, 0x40, 0x00
+.data1 	0x00, 0x74, 0x11, 0xc7, 0x05, 0xf0, 0x27, 0x00
+.data1 	0x00, 0x14, 0x00, 0x00, 0x00, 0x31, 0xc0, 0xe9
+.data1 	0xb3, 0x00, 0x00, 0x00, 0x68, 0x00, 0x08, 0x00
+.data1 	0x00, 0xff, 0x75, 0x08, 0xe8, 0x4b, 0xff, 0xff
+.data1 	0xff, 0x59, 0x59, 0x89, 0xc7, 0x85, 0xc0, 0x79
+.data1 	0x07, 0x31, 0xc0, 0xe9, 0x97, 0x00, 0x00, 0x00
+.data1 	0x8d, 0x45, 0xd0, 0x50, 0x57, 0xe8, 0xbe, 0xfd
+.data1 	0xff, 0xff, 0x59, 0x59, 0x85, 0xc0, 0x78, 0x53
+.data1 	0xc7, 0x05, 0xf0, 0x27, 0x00, 0x00, 0x14, 0x00
+.data1 	0x00, 0x00, 0x0f, 0xb7, 0x55, 0xd8, 0x81, 0xe2
+.data1 	0x00, 0xf0, 0x00, 0x00, 0x81, 0xfa, 0x00, 0x40
+.data1 	0x00, 0x00, 0x75, 0x37, 0x6a, 0x01, 0x57, 0xe8
+.data1 	0x1c, 0xfd, 0xff, 0xff, 0x59, 0x59, 0x89, 0x45
+.data1 	0xf8, 0x85, 0xc0, 0x78, 0x26, 0x0d, 0x01, 0x00
+.data1 	0x00, 0x00, 0x50, 0x6a, 0x02, 0x57, 0xe8, 0x05
+.data1 	0xfd, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x85, 0xc0
+.data1 	0x78, 0x11, 0x68, 0x54, 0x04, 0x00, 0x00, 0xe8
+.data1 	0x3b, 0xe2, 0xff, 0xff, 0x59, 0x89, 0xc6, 0x85
+.data1 	0xc0, 0x75, 0x1d, 0x8b, 0x15, 0xf0, 0x27, 0x00
+.data1 	0x00, 0x89, 0x55, 0xcc, 0x57, 0xe8, 0x2a, 0xfa
+.data1 	0xff, 0xff, 0x59, 0x8b, 0x55, 0xcc, 0x89, 0x15
+.data1 	0xf0, 0x27, 0x00, 0x00, 0x31, 0xc0, 0xeb, 0x17
+.data1 	0x89, 0xfa, 0x88, 0x16, 0xc6, 0x46, 0x01, 0xff
+.data1 	0x66, 0xc7, 0x46, 0x02, 0x00, 0x00, 0xc7, 0x46
+.data1 	0x04, 0x00, 0x00, 0x00, 0x00, 0x89, 0xf0, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x2a
+.data1 	0x6a, 0x01, 0xe8, 0x1d, 0xea, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x85, 0xc0, 0x79, 0x07, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xeb, 0x13, 0x8b, 0x55, 0xe4
+.data1 	0x8b, 0x45, 0x08, 0x89, 0x10, 0x8b, 0x55, 0x08
+.data1 	0x8b, 0x4d, 0xe8, 0x89, 0x4a, 0x04, 0x31, 0xc0
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4
+.data1 	0x8b, 0x55, 0x10, 0x89, 0x55, 0xe8, 0x8b, 0x55
+.data1 	0x0c, 0x89, 0x55, 0xf0, 0x8d, 0x45, 0xdc, 0x50
+.data1 	0x6a, 0x03, 0x6a, 0x01, 0xe8, 0xd3, 0xe9, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x75, 0x08
+.data1 	0x85, 0xf6, 0x75, 0x11, 0xc7, 0x05, 0xf0, 0x27
+.data1 	0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x31, 0xc0
+.data1 	0xe9, 0xca, 0x00, 0x00, 0x00, 0x0f, 0xbf, 0x46
+.data1 	0x02, 0x85, 0xc0, 0x7f, 0x51, 0x0f, 0xbe, 0x06
+.data1 	0x68, 0x00, 0x04, 0x00, 0x00, 0x8d, 0x5e, 0x0c
+.data1 	0x53, 0x50, 0xe8, 0x9d, 0xff, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x0f, 0xbf, 0xc0, 0x66, 0x89, 0x46
+.data1 	0x02, 0x0f, 0xbf, 0x5e, 0x02, 0x85, 0xdb, 0x7f
+.data1 	0x07, 0x31, 0xc0, 0xe9, 0x97, 0x00, 0x00, 0x00
+.data1 	0x0f, 0xbf, 0x46, 0x02, 0xc1, 0xe8, 0x03, 0x0f
+.data1 	0xbf, 0xc0, 0x66, 0x89, 0x46, 0x02, 0x8d, 0x56
+.data1 	0x0c, 0x89, 0x56, 0x08, 0x0f, 0xbe, 0x46, 0x01
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x07, 0x0f
+.data1 	0xbe, 0x46, 0x10, 0x88, 0x46, 0x01, 0x80, 0x7e
+.data1 	0x01, 0x00, 0x75, 0x05, 0x8b, 0x7e, 0x08, 0xeb
+.data1 	0x2c, 0x89, 0xf7, 0x81, 0xc7, 0x0c, 0x04, 0x00
+.data1 	0x00, 0x8b, 0x56, 0x08, 0x8b, 0x12, 0x89, 0x17
+.data1 	0xc6, 0x47, 0x04, 0x07, 0x8b, 0x56, 0x08, 0x6a
+.data1 	0x3c, 0x83, 0xc2, 0x04, 0x52, 0x8d, 0x47, 0x05
+.data1 	0x50, 0xe8, 0xc2, 0xf6, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0xc6, 0x47, 0x41, 0x00, 0x0f, 0xb6, 0x57
+.data1 	0x04, 0x42, 0xc1, 0xe2, 0x03, 0x03, 0x56, 0x08
+.data1 	0x89, 0x56, 0x08, 0x0f, 0xbf, 0x46, 0x02, 0x0f
+.data1 	0xb6, 0x57, 0x04, 0x42, 0x29, 0xc2, 0xf7, 0xda
+.data1 	0x89, 0xd0, 0x0f, 0xbf, 0xc0, 0x66, 0x89, 0x46
+.data1 	0x02, 0x0f, 0xb6, 0x57, 0x04, 0x42, 0xc1, 0xe2
+.data1 	0x03, 0x01, 0x56, 0x04, 0x83, 0x3f, 0x00, 0x0f
+.data1 	0x84, 0x38, 0xff, 0xff, 0xff, 0x89, 0xf8, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x83, 0x7d, 0x0c, 0x00, 0x75, 0x10
+.data1 	0xc7, 0x45, 0xe4, 0x04, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x0e
+.data1 	0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4, 0x8b, 0x45
+.data1 	0x0c, 0x8b, 0x10, 0x89, 0x55, 0xf0, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0x6a, 0x4a, 0x6a, 0x00, 0xe8, 0xa9
+.data1 	0xe8, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x85, 0xc0
+.data1 	0x79, 0x07, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x11, 0x83, 0x7d, 0x10, 0x00, 0x74, 0x08, 0x8b
+.data1 	0x55, 0xf0, 0x8b, 0x45, 0x10, 0x89, 0x10, 0x8b
+.data1 	0x45, 0xe0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x48, 0x56, 0x8b, 0x75, 0x08, 0x8b, 0x16
+.data1 	0x89, 0x55, 0xb8, 0x8b, 0x56, 0x04, 0x89, 0x55
+.data1 	0xbc, 0x8b, 0x56, 0x08, 0x89, 0x55, 0xec, 0x8b
+.data1 	0x56, 0x0c, 0x89, 0x55, 0xf8, 0x8b, 0x56, 0x10
+.data1 	0x89, 0x55, 0xd0, 0x8b, 0x55, 0x0c, 0x89, 0x55
+.data1 	0xe4, 0x8d, 0x45, 0xb8, 0x50, 0xe8, 0x04, 0x00
+.data1 	0x00, 0x00, 0x59, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x04, 0x56, 0x8b, 0x75, 0x08
+.data1 	0x8d, 0x45, 0xfc, 0x50, 0xe8, 0x73, 0xee, 0xff
+.data1 	0xff, 0x59, 0x6a, 0x00, 0x8d, 0x45, 0xfc, 0x50
+.data1 	0x6a, 0x02, 0xe8, 0x4d, 0xff, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x8b, 0x56, 0x04, 0x89, 0x15, 0x4c
+.data1 	0x2c, 0x00, 0x00, 0x8b, 0x16, 0x89, 0x15, 0x44
+.data1 	0x2c, 0x00, 0x00, 0x89, 0x35, 0x54, 0x2c, 0x00
+.data1 	0x00, 0x68, 0x38, 0x2c, 0x00, 0x00, 0x6a, 0x4b
+.data1 	0x6a, 0x00, 0xe8, 0x05, 0xe8, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x2a, 0xf6, 0xff, 0xff, 0x59, 0x05
+.data1 	0x01, 0x00, 0x00, 0x00, 0x89, 0x45, 0xe4, 0x8b
+.data1 	0x55, 0x08, 0x89, 0x55, 0xf0, 0x8b, 0x55, 0x0c
+.data1 	0x89, 0x55, 0xf4, 0x8d, 0x45, 0xdc, 0x50, 0x6a
+.data1 	0x12, 0x6a, 0x01, 0xe8, 0xcc, 0xe7, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0xff, 0x75, 0x0c, 0x68, 0x08
+.data1 	0x54, 0x24, 0x80, 0xff, 0x75, 0x08, 0xe8, 0x45
+.data1 	0xfb, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0xeb, 0x26, 0xbe, 0x09
+.data1 	0x54, 0x24, 0x40, 0xeb, 0x2c, 0xbe, 0x0a, 0x54
+.data1 	0x24, 0x40, 0xeb, 0x25, 0xbe, 0x0b, 0x54, 0x24
+.data1 	0x40, 0xeb, 0x1e, 0xc7, 0x05, 0xf0, 0x27, 0x00
+.data1 	0x00, 0x16, 0x00, 0x00, 0x00, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xeb, 0x1c, 0xbb, 0x14, 0x19, 0x00
+.data1 	0x00, 0x8b, 0x45, 0x0c, 0xe9, 0xf7, 0x01, 0x00
+.data1 	0x00, 0xff, 0x75, 0x10, 0x56, 0xff, 0x75, 0x08
+.data1 	0xe8, 0xfb, 0xfa, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x5e, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x3c, 0x6a, 0x01
+.data1 	0xe8, 0x47, 0xe7, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x25, 0xff, 0xff, 0x00, 0x00, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x10, 0x89
+.data1 	0x55, 0xe8, 0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x0b
+.data1 	0x6a, 0x00, 0xe8, 0x1d, 0xe7, 0xff, 0xff, 0x83
+.data1 	0xc4, 0x0c, 0x85, 0xc0, 0x79, 0x07, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xeb, 0x11, 0x83, 0x7d, 0x0c
+.data1 	0x00, 0x74, 0x08, 0x8b, 0x55, 0xe4, 0x8b, 0x45
+.data1 	0x0c, 0x89, 0x10, 0x8b, 0x45, 0xe0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x10, 0x89
+.data1 	0x55, 0xe8, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf0
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x04, 0x6a, 0x01
+.data1 	0xe8, 0xd7, 0xe6, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x7d, 0x08, 0x8b, 0x75, 0x0c, 0x8b
+.data1 	0x4d, 0x10, 0x89, 0xf8, 0x29, 0xf0, 0x39, 0xc8
+.data1 	0x72, 0x2f, 0xfc, 0x83, 0xf9, 0x10, 0x72, 0x20
+.data1 	0x89, 0xf0, 0x09, 0xf8, 0xa8, 0x01, 0x75, 0x18
+.data1 	0xa8, 0x02, 0x75, 0x0d, 0x0f, 0xac, 0xc8, 0x02
+.data1 	0xc1, 0xe9, 0x02, 0xf3, 0xa5, 0x0f, 0xa4, 0xc1
+.data1 	0x02, 0xd1, 0xe9, 0xf3, 0x66, 0xa5, 0x11, 0xc9
+.data1 	0xf3, 0xa4, 0x8b, 0x45, 0x08, 0x5f, 0x5e, 0x5d
+.data1 	0xc3, 0xfd, 0x8d, 0x74, 0x0e, 0xff, 0x8d, 0x7c
+.data1 	0x0f, 0xff, 0xf3, 0xa4, 0xfc, 0xeb, 0xeb, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x7d, 0x08, 0xb9, 0xff, 0xff, 0xff
+.data1 	0xff, 0x30, 0xc0, 0xfc, 0xf2, 0xae, 0x4f, 0x57
+.data1 	0x8b, 0x7d, 0x0c, 0x89, 0xd1, 0xf2, 0xae, 0x75
+.data1 	0x01, 0x41, 0x29, 0xca, 0x89, 0xd1, 0x8b, 0x75
+.data1 	0x0c, 0x5f, 0xf3, 0xa4, 0xaa, 0x8b, 0x45, 0x08
+.data1 	0x5f, 0x5e, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x85, 0xc9, 0x74, 0x13, 0x8b, 0x75, 0x08
+.data1 	0x8b, 0x7d, 0x0c, 0xfc, 0xa6, 0x75, 0x09, 0x80
+.data1 	0x7e, 0xff, 0x00, 0x74, 0x03, 0x49, 0x75, 0xf4
+.data1 	0x0f, 0x97, 0xc0, 0x0f, 0x92, 0xc4, 0x28, 0xe0
+.data1 	0x0f, 0xbe, 0xc0, 0x5f, 0x5e, 0x5d, 0xc3, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x7d, 0x0c, 0x30
+.data1 	0xc0, 0x89, 0xca, 0xfc, 0xf2, 0xae, 0x29, 0xca
+.data1 	0x87, 0xca, 0x8b, 0x75, 0x0c, 0x8b, 0x7d, 0x08
+.data1 	0xf3, 0xa4, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x57
+.data1 	0x8b, 0x7d, 0x08, 0x30, 0xc0, 0x89, 0xca, 0x80
+.data1 	0xf9, 0x01, 0xfc, 0xf2, 0xae, 0x75, 0x01, 0x41
+.data1 	0x89, 0xd0, 0x29, 0xc8, 0x5f, 0x5d, 0xc3, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x00, 0xf4, 0xff, 0xff
+.data1 	0x59, 0xbe, 0x01, 0x00, 0x00, 0x00, 0x01, 0xc6
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x72, 0x08, 0x8b, 0x55
+.data1 	0x0c, 0x8b, 0x4d, 0x08, 0x89, 0x4a, 0x10, 0x83
+.data1 	0xfe, 0x0e, 0x77, 0x11, 0x8b, 0x55, 0x0c, 0xff
+.data1 	0x75, 0x08, 0x83, 0xc2, 0x14, 0x52, 0xe8, 0xb5
+.data1 	0xf3, 0xff, 0xff, 0x59, 0x59, 0x5e, 0xc9, 0xc3
+.data1 	0x89, 0xe3, 0x89, 0xf0, 0x89, 0xfa, 0x8b, 0x7b
+.data1 	0x04, 0x8b, 0x73, 0x08, 0xf3, 0xa5, 0x89, 0xc6
+.data1 	0x89, 0xd7, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x13, 0x2b, 0x43, 0x04, 0x3b, 0x43, 0x08
+.data1 	0x77, 0x0c, 0xc1, 0xe0, 0x02, 0x01, 0xc3, 0x8b
+.data1 	0x5b, 0x0c, 0x85, 0xdb, 0x75, 0x11, 0x89, 0xd3
+.data1 	0x85, 0xdb, 0x75, 0x0b, 0xb8, 0x14, 0x00, 0x00
+.data1 	0x00, 0x50, 0xe9, 0x2d, 0x00, 0x00, 0x00, 0xff
+.data1 	0xe3, 0x00, 0x00, 0x00, 0x8b, 0x13, 0x8b, 0x4b
+.data1 	0x04, 0x83, 0xc3, 0x08, 0x49, 0x7c, 0x18, 0x3b
+.data1 	0x03, 0x75, 0xf6, 0x8b, 0x5b, 0x04, 0x85, 0xdb
+.data1 	0x75, 0x0b, 0xb8, 0x14, 0x00, 0x00, 0x00, 0x50
+.data1 	0xe9, 0x07, 0x00, 0x00, 0x00, 0xff, 0xe3, 0x89
+.data1 	0xd3, 0xeb, 0xeb, 0x00, 0xe8, 0x4b, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x6b, 0x08, 0x8b, 0x63, 0x04, 0xff, 0x23
+.data1 	0x5a, 0xd1, 0xf9, 0x73, 0x05, 0x58, 0x88, 0x03
+.data1 	0xff, 0xe2, 0xd1, 0xf9, 0x73, 0x06, 0x58, 0x66
+.data1 	0x89, 0x03, 0xff, 0xe2, 0x52, 0x89, 0xfa, 0x89
+.data1 	0xdf, 0x5b, 0xeb, 0x08, 0x89, 0xfa, 0x89, 0xdf
+.data1 	0x5b, 0xc1, 0xf9, 0x02, 0x89, 0xf0, 0x89, 0xe6
+.data1 	0xf3, 0xa5, 0x89, 0xf4, 0x89, 0xd7, 0x89, 0xc6
+.data1 	0xff, 0xe3, 0x00, 0x00, 0xe9, 0x3f, 0xf4, 0xff
+.data1 	0xff, 0x00, 0x00, 0x00, 0x31, 0xdb, 0x87, 0x1d
+.data1 	0xd8, 0x29, 0x00, 0x00, 0x85, 0xdb, 0x74, 0x05
+.data1 	0x50, 0xff, 0xd3, 0x58, 0xc3, 0x50, 0xe8, 0xe1
+.data1 	0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x77, 0x61, 0x69, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x73, 0x65
+.data1 	0x74, 0x00, 0x00, 0x00, 0x75, 0x6d, 0x61, 0x73
+.data1 	0x6b, 0x00, 0x00, 0x00, 0x66, 0x61, 0x6c, 0x73
+.data1 	0x65, 0x00, 0x00, 0x00, 0x74, 0x72, 0x75, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00
+.data1 	0x74, 0x72, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00
+.data1 	0x73, 0x68, 0x69, 0x66, 0x74, 0x00, 0x00, 0x00
+.data1 	0x73, 0x65, 0x74, 0x76, 0x61, 0x72, 0x00, 0x00
+.data1 	0x73, 0x65, 0x74, 0x00, 0x72, 0x65, 0x74, 0x75
+.data1 	0x72, 0x6e, 0x00, 0x00, 0x72, 0x65, 0x61, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x70, 0x77, 0x64, 0x00
+.data1 	0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x00
+.data1 	0x6a, 0x6f, 0x62, 0x73, 0x00, 0x00, 0x00, 0x00
+.data1 	0x6a, 0x6f, 0x62, 0x69, 0x64, 0x00, 0x00, 0x00
+.data1 	0x68, 0x61, 0x73, 0x68, 0x00, 0x00, 0x00, 0x00
+.data1 	0x67, 0x65, 0x74, 0x6f, 0x70, 0x74, 0x73, 0x00
+.data1 	0x5b, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x65, 0x78, 0x70, 0x72
+.data1 	0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x61, 0x64
+.data1 	0x6f, 0x6e, 0x6c, 0x79, 0x00, 0x00, 0x00, 0x00
+.data1 	0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x00
+.data1 	0x65, 0x78, 0x69, 0x74, 0x00, 0x00, 0x00, 0x00
+.data1 	0x65, 0x78, 0x65, 0x63, 0x00, 0x00, 0x00, 0x00
+.data1 	0x65, 0x76, 0x61, 0x6c, 0x00, 0x00, 0x00, 0x00
+.data1 	0x65, 0x63, 0x68, 0x6f, 0x00, 0x00, 0x00, 0x00
+.data1 	0x2e, 0x00, 0x00, 0x00, 0x63, 0x68, 0x64, 0x69
+.data1 	0x72, 0x00, 0x00, 0x00, 0x63, 0x64, 0x00, 0x00
+.data1 	0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x62, 0x72, 0x65, 0x61
+.data1 	0x6b, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6d, 0x6d
+.data1 	0x61, 0x6e, 0x64, 0x00, 0x63, 0x61, 0x6e, 0x27
+.data1 	0x74, 0x20, 0x63, 0x64, 0x20, 0x74, 0x6f, 0x20
+.data1 	0x25, 0x73, 0x00, 0x00, 0x43, 0x44, 0x50, 0x41
+.data1 	0x54, 0x48, 0x00, 0x00, 0x48, 0x4f, 0x4d, 0x45
+.data1 	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x65, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x48, 0x4f, 0x4d, 0x45
+.data1 	0x00, 0x00, 0x00, 0x00, 0x25, 0x73, 0x0a, 0x00
+.data1 	0x2e, 0x00, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0x00
+.data1 	0x70, 0x77, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x6d
+.data1 	0x61, 0x6e, 0x64, 0x20, 0x66, 0x61, 0x69, 0x6c
+.data1 	0x65, 0x64, 0x00, 0x00, 0x43, 0x61, 0x6e, 0x6e
+.data1 	0x6f, 0x74, 0x20, 0x65, 0x78, 0x65, 0x63, 0x20
+.data1 	0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x70, 0x77, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x70, 0x77, 0x64, 0x00
+.data1 	0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x70, 0x77, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x50, 0x69, 0x70, 0x65
+.data1 	0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x25, 0x73, 0x3a, 0x20, 0x25, 0x73, 0x00, 0x00
+.data1 	0x25, 0x73, 0x3a, 0x20, 0x00, 0x00, 0x00, 0x00
+.data1 	0x99, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0e, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00
+.data1 	0x8b, 0x09, 0x00, 0x00, 0x82, 0x09, 0x00, 0x00
+.data1 	0x99, 0x08, 0x00, 0x00, 0xd1, 0x08, 0x00, 0x00
+.data1 	0xc3, 0x08, 0x00, 0x00, 0x2d, 0x08, 0x00, 0x00
+.data1 	0x63, 0x08, 0x00, 0x00, 0xdf, 0x08, 0x00, 0x00
+.data1 	0x46, 0x09, 0x00, 0x00, 0x46, 0x09, 0x00, 0x00
+.data1 	0x52, 0x09, 0x00, 0x00, 0x5e, 0x09, 0x00, 0x00
+.data1 	0x99, 0x09, 0x00, 0x00, 0x69, 0x09, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x79, 0x70
+.data1 	0x65, 0x20, 0x3d, 0x20, 0x25, 0x64, 0x0a, 0x00
+.data1 	0x50, 0x69, 0x70, 0x65, 0x20, 0x63, 0x61, 0x6c
+.data1 	0x6c, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x50, 0x69, 0x70, 0x65
+.data1 	0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0xff, 0x14, 0x00, 0x00, 0xf7, 0x16, 0x00, 0x00
+.data1 	0x5f, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x72, 0x6d
+.data1 	0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61
+.data1 	0x6e, 0x64, 0x3a, 0x20, 0x20, 0x00, 0x00, 0x00
+.data1 	0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x20
+.data1 	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x3a
+.data1 	0x20, 0x20, 0x00, 0x00, 0x53, 0x68, 0x65, 0x6c
+.data1 	0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x3a, 0x20, 0x20, 0x00, 0x00, 0x00
+.data1 	0x50, 0x69, 0x70, 0x65, 0x20, 0x63, 0x61, 0x6c
+.data1 	0x6c, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e
+.data1 	0x64, 0x0a, 0x00, 0x00, 0x66, 0x61, 0x6c, 0x73
+.data1 	0x65, 0x00, 0x00, 0x00, 0x72, 0x76, 0x00, 0x00
+.data1 	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e
+.data1 	0x20, 0x25, 0x73, 0x00, 0x62, 0x75, 0x69, 0x6c
+.data1 	0x74, 0x69, 0x6e, 0x20, 0x25, 0x73, 0x00, 0x00
+.data1 	0x25, 0x73, 0x3a, 0x20, 0x25, 0x73, 0x0a, 0x00
+.data1 	0x25, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x64
+.data1 	0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69
+.data1 	0x6e, 0x20, 0x25, 0x73, 0x00, 0x00, 0x00, 0x00
+.data1 	0x66, 0x75, 0x6e, 0x63, 0x00, 0x00, 0x00, 0x00
+.data1 	0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x00
+.data1 	0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x00
+.data1 	0xb4, 0x28, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00
+.data1 	0x81, 0xff, 0xff, 0xff, 0xf4, 0x27, 0x00, 0x00
+.data1 	0x82, 0xff, 0xff, 0xff, 0x74, 0x28, 0x00, 0x00
+.data1 	0x83, 0xff, 0xff, 0xff, 0xfd, 0x28, 0x00, 0x00
+.data1 	0x84, 0xff, 0xff, 0xff, 0x86, 0x28, 0x00, 0x00
+.data1 	0x85, 0xff, 0xff, 0xff, 0x86, 0x28, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xfd, 0x28, 0x00, 0x00
+.data1 	0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x6f, 0x72, 0x20
+.data1 	0x00, 0x00, 0x00, 0x00, 0x25, 0x2e, 0x2a, 0x73
+.data1 	0x3a, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65
+.data1 	0x74, 0x65, 0x72, 0x20, 0x25, 0x73, 0x6e, 0x6f
+.data1 	0x74, 0x20, 0x73, 0x65, 0x74, 0x00, 0x00, 0x00
+.data1 	0x25, 0x73, 0x0a, 0x00, 0xf0, 0x31, 0x00, 0x00
+.data1 	0x08, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x2f, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00
+.data1 	0x46, 0x2f, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00
+.data1 	0x36, 0x2f, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00
+.data1 	0x3a, 0x30, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00
+.data1 	0xc3, 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00
+.data1 	0x47, 0x31, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00
+.data1 	0x3e, 0x2f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+.data1 	0x2e, 0x30, 0x00, 0x00, 0x2f, 0x65, 0x74, 0x63
+.data1 	0x2f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x64, 0x00
+.data1 	0x48, 0x4f, 0x4d, 0x45, 0x00, 0x00, 0x00, 0x00
+.data1 	0x2f, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00
+.data1 	0x43, 0x3c, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
+.data1 	0x81, 0xff, 0xff, 0xff, 0xef, 0x3a, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x00, 0x00
+.data1 	0x2a, 0x00, 0x00, 0x00, 0x18, 0x3b, 0x00, 0x00
+.data1 	0x3f, 0x00, 0x00, 0x00, 0x06, 0x3b, 0x00, 0x00
+.data1 	0x5b, 0x00, 0x00, 0x00, 0x79, 0x3b, 0x00, 0x00
+.data1 	0x73, 0x68, 0x3a, 0x20, 0x74, 0x75, 0x72, 0x6e
+.data1 	0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x66, 0x20
+.data1 	0x4e, 0x44, 0x45, 0x4c, 0x41, 0x59, 0x20, 0x6d
+.data1 	0x6f, 0x64, 0x65, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x66
+.data1 	0x69, 0x6c, 0x65, 0x20, 0x64, 0x65, 0x73, 0x63
+.data1 	0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x00
+.data1 	0x43, 0x61, 0x6e, 0x27, 0x74, 0x20, 0x6f, 0x70
+.data1 	0x65, 0x6e, 0x20, 0x25, 0x73, 0x00, 0x00, 0x00
+.data1 	0x20, 0x28, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x64
+.data1 	0x75, 0x6d, 0x70, 0x65, 0x64, 0x29, 0x00, 0x00
+.data1 	0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x25
+.data1 	0x64, 0x00, 0x00, 0x00, 0x45, 0x78, 0x69, 0x74
+.data1 	0x20, 0x25, 0x64, 0x00, 0x20, 0x20, 0x20, 0x20
+.data1 	0x25, 0x64, 0x20, 0x00, 0x5b, 0x25, 0x64, 0x5d
+.data1 	0x20, 0x25, 0x64, 0x20, 0x00, 0x00, 0x00, 0x00
+.data1 	0x25, 0x64, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x6a, 0x6f, 0x62, 0x3a
+.data1 	0x20, 0x25, 0x73, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x61, 0x6d, 0x62, 0x69, 0x67, 0x75, 0x6f, 0x75
+.data1 	0x73, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x63
+.data1 	0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x6a
+.data1 	0x6f, 0x62, 0x00, 0x00, 0x43, 0x61, 0x6e, 0x27
+.data1 	0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x2f
+.data1 	0x64, 0x65, 0x76, 0x2f, 0x6e, 0x75, 0x6c, 0x6c
+.data1 	0x00, 0x00, 0x00, 0x00, 0x2f, 0x64, 0x65, 0x76
+.data1 	0x2f, 0x6e, 0x75, 0x6c, 0x6c, 0x00, 0x00, 0x00
+.data1 	0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x66
+.data1 	0x6f, 0x72, 0x6b, 0x00, 0x20, 0x2d, 0x20, 0x63
+.data1 	0x6f, 0x72, 0x65, 0x20, 0x64, 0x75, 0x6d, 0x70
+.data1 	0x65, 0x64, 0x00, 0x00, 0x53, 0x69, 0x67, 0x6e
+.data1 	0x61, 0x6c, 0x20, 0x25, 0x64, 0x00, 0x00, 0x00
+.data1 	0x25, 0x64, 0x3a, 0x20, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb6, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x16, 0x00, 0x00, 0x00, 0xfb, 0x4e, 0x00, 0x00
+.data1 	0xad, 0x50, 0x00, 0x00, 0x61, 0x4f, 0x00, 0x00
+.data1 	0xbe, 0x4f, 0x00, 0x00, 0xbe, 0x4f, 0x00, 0x00
+.data1 	0x9a, 0x4f, 0x00, 0x00, 0x1d, 0x4f, 0x00, 0x00
+.data1 	0x3f, 0x4f, 0x00, 0x00, 0xcc, 0x4f, 0x00, 0x00
+.data1 	0x04, 0x50, 0x00, 0x00, 0x11, 0x50, 0x00, 0x00
+.data1 	0x49, 0x50, 0x00, 0x00, 0x6d, 0x50, 0x00, 0x00
+.data1 	0xb6, 0x51, 0x00, 0x00, 0x94, 0x50, 0x00, 0x00
+.data1 	0xf3, 0x50, 0x00, 0x00, 0x01, 0x51, 0x00, 0x00
+.data1 	0x31, 0x51, 0x00, 0x00, 0x11, 0x51, 0x00, 0x00
+.data1 	0x21, 0x51, 0x00, 0x00, 0x41, 0x51, 0x00, 0x00
+.data1 	0xa9, 0x51, 0x00, 0x00, 0xa9, 0x51, 0x00, 0x00
+.data1 	0x3f, 0x3f, 0x3f, 0x00, 0x3c, 0x3c, 0x2e, 0x2e
+.data1 	0x2e, 0x00, 0x00, 0x00, 0x3c, 0x26, 0x00, 0x00
+.data1 	0x3c, 0x00, 0x00, 0x00, 0x3e, 0x26, 0x00, 0x00
+.data1 	0x3e, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
+.data1 	0x28, 0x29, 0x20, 0x2e, 0x2e, 0x2e, 0x00, 0x00
+.data1 	0x20, 0x69, 0x6e, 0x20, 0x2e, 0x2e, 0x2e, 0x00
+.data1 	0x63, 0x61, 0x73, 0x65, 0x20, 0x00, 0x00, 0x00
+.data1 	0x20, 0x69, 0x6e, 0x20, 0x2e, 0x2e, 0x2e, 0x00
+.data1 	0x66, 0x6f, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00
+.data1 	0x3b, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x00, 0x00
+.data1 	0x3b, 0x20, 0x64, 0x6f, 0x20, 0x00, 0x00, 0x00
+.data1 	0x75, 0x6e, 0x74, 0x69, 0x6c, 0x20, 0x00, 0x00
+.data1 	0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x00, 0x00
+.data1 	0x2e, 0x2e, 0x2e, 0x00, 0x3b, 0x20, 0x74, 0x68
+.data1 	0x65, 0x6e, 0x20, 0x00, 0x69, 0x66, 0x20, 0x00
+.data1 	0x29, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00
+.data1 	0x20, 0x7c, 0x20, 0x00, 0x20, 0x7c, 0x7c, 0x20
+.data1 	0x00, 0x00, 0x00, 0x00, 0x20, 0x26, 0x26, 0x20
+.data1 	0x00, 0x00, 0x00, 0x00, 0x3b, 0x20, 0x00, 0x00
+.data1 	0x7d, 0x2d, 0x2b, 0x3f, 0x3d, 0x00, 0x00, 0x00
+.data1 	0x59, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x76, 0x65
+.data1 	0x20, 0x6d, 0x61, 0x69, 0x6c, 0x00, 0x00, 0x00
+.data1 	0x72, 0x54, 0x00, 0x00, 0x2f, 0x2e, 0x61, 0x73
+.data1 	0x68, 0x72, 0x63, 0x00, 0x48, 0x4f, 0x4d, 0x45
+.data1 	0x00, 0x00, 0x00, 0x00, 0x53, 0x48, 0x49, 0x4e
+.data1 	0x49, 0x54, 0x00, 0x00, 0x2e, 0x70, 0x72, 0x6f
+.data1 	0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c
+.data1 	0x65, 0x00, 0x00, 0x00, 0x48, 0x4f, 0x4d, 0x45
+.data1 	0x00, 0x00, 0x00, 0x00, 0x2f, 0x65, 0x74, 0x63
+.data1 	0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x0a, 0x55, 0x73, 0x65
+.data1 	0x20, 0x22, 0x65, 0x78, 0x69, 0x74, 0x22, 0x20
+.data1 	0x74, 0x6f, 0x20, 0x6c, 0x65, 0x61, 0x76, 0x65
+.data1 	0x20, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x2e, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0x6e, 0x27
+.data1 	0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x25
+.data1 	0x73, 0x00, 0x00, 0x00, 0x4f, 0x75, 0x74, 0x20
+.data1 	0x6f, 0x66, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4f, 0x75, 0x74, 0x20
+.data1 	0x6f, 0x66, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x73, 0x74, 0x75, 0x6e
+.data1 	0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x0a, 0x00, 0x00
+.data1 	0x49, 0x46, 0x53, 0x00, 0x61, 0x72, 0x67, 0x20
+.data1 	0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00
+.data1 	0x65, 0x70, 0x3a, 0x00, 0x49, 0x6c, 0x6c, 0x65
+.data1 	0x67, 0x61, 0x6c, 0x20, 0x6e, 0x75, 0x6d, 0x62
+.data1 	0x65, 0x72, 0x3a, 0x20, 0x25, 0x73, 0x00, 0x00
+.data1 	0x25, 0x2e, 0x34, 0x6f, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20
+.data1 	0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x00, 0x00
+.data1 	0xf0, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x16, 0x00, 0x00, 0x00, 0xbc, 0x62, 0x00, 0x00
+.data1 	0xd3, 0x62, 0x00, 0x00, 0xea, 0x62, 0x00, 0x00
+.data1 	0xf8, 0x62, 0x00, 0x00, 0xf8, 0x62, 0x00, 0x00
+.data1 	0xf8, 0x62, 0x00, 0x00, 0xbc, 0x62, 0x00, 0x00
+.data1 	0xbc, 0x62, 0x00, 0x00, 0x0f, 0x63, 0x00, 0x00
+.data1 	0xbc, 0x62, 0x00, 0x00, 0xbc, 0x62, 0x00, 0x00
+.data1 	0x2f, 0x63, 0x00, 0x00, 0x56, 0x63, 0x00, 0x00
+.data1 	0x6d, 0x63, 0x00, 0x00, 0x8d, 0x63, 0x00, 0x00
+.data1 	0x8d, 0x63, 0x00, 0x00, 0xb1, 0x63, 0x00, 0x00
+.data1 	0xb1, 0x63, 0x00, 0x00, 0xb1, 0x63, 0x00, 0x00
+.data1 	0xc5, 0x63, 0x00, 0x00, 0xc5, 0x63, 0x00, 0x00
+.data1 	0xd0, 0x63, 0x00, 0x00, 0xd0, 0x63, 0x00, 0x00
+.data1 	0xeb, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x16, 0x00, 0x00, 0x00, 0x50, 0x64, 0x00, 0x00
+.data1 	0x6d, 0x64, 0x00, 0x00, 0x90, 0x64, 0x00, 0x00
+.data1 	0xa7, 0x64, 0x00, 0x00, 0xa7, 0x64, 0x00, 0x00
+.data1 	0xa7, 0x64, 0x00, 0x00, 0x50, 0x64, 0x00, 0x00
+.data1 	0x50, 0x64, 0x00, 0x00, 0xc4, 0x64, 0x00, 0x00
+.data1 	0x50, 0x64, 0x00, 0x00, 0x50, 0x64, 0x00, 0x00
+.data1 	0xed, 0x64, 0x00, 0x00, 0x16, 0x65, 0x00, 0x00
+.data1 	0x33, 0x65, 0x00, 0x00, 0x5c, 0x65, 0x00, 0x00
+.data1 	0x5c, 0x65, 0x00, 0x00, 0x85, 0x65, 0x00, 0x00
+.data1 	0x85, 0x65, 0x00, 0x00, 0x85, 0x65, 0x00, 0x00
+.data1 	0xa5, 0x65, 0x00, 0x00, 0xa5, 0x65, 0x00, 0x00
+.data1 	0xbf, 0x65, 0x00, 0x00, 0xbf, 0x65, 0x00, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x2d, 0x63, 0x20, 0x6f
+.data1 	0x70, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20
+.data1 	0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x2d
+.data1 	0x25, 0x63, 0x00, 0x00, 0x4f, 0x50, 0x54, 0x49
+.data1 	0x4e, 0x44, 0x00, 0x00, 0x25, 0x64, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4f, 0x50, 0x54, 0x41
+.data1 	0x52, 0x47, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x61
+.data1 	0x72, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x2d
+.data1 	0x25, 0x63, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f
+.data1 	0x6e, 0x0a, 0x00, 0x00, 0x49, 0x6c, 0x6c, 0x65
+.data1 	0x67, 0x61, 0x6c, 0x20, 0x6f, 0x70, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x2d, 0x25, 0x63, 0x0a, 0x00
+.data1 	0x4f, 0x50, 0x54, 0x49, 0x4e, 0x44, 0x00, 0x00
+.data1 	0x25, 0x64, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67
+.data1 	0x65, 0x3a, 0x20, 0x67, 0x65, 0x74, 0x6f, 0x70
+.data1 	0x74, 0x73, 0x20, 0x6f, 0x70, 0x74, 0x73, 0x74
+.data1 	0x72, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x61, 0x72
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x61
+.data1 	0x72, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x2d
+.data1 	0x25, 0x63, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f
+.data1 	0x6e, 0x00, 0x00, 0x00, 0x49, 0x6c, 0x6c, 0x65
+.data1 	0x67, 0x61, 0x6c, 0x20, 0x6f, 0x70, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x2d, 0x25, 0x63, 0x00, 0x00
+.data1 	0x22, 0x65, 0x73, 0x61, 0x63, 0x22, 0x00, 0x00
+.data1 	0x22, 0x63, 0x61, 0x73, 0x65, 0x22, 0x00, 0x00
+.data1 	0x22, 0x7d, 0x22, 0x00, 0x22, 0x7b, 0x22, 0x00
+.data1 	0x22, 0x64, 0x6f, 0x6e, 0x65, 0x22, 0x00, 0x00
+.data1 	0x22, 0x64, 0x6f, 0x22, 0x00, 0x00, 0x00, 0x00
+.data1 	0x22, 0x66, 0x6f, 0x72, 0x22, 0x00, 0x00, 0x00
+.data1 	0x22, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x22, 0x00
+.data1 	0x22, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x22, 0x00
+.data1 	0x22, 0x66, 0x69, 0x22, 0x00, 0x00, 0x00, 0x00
+.data1 	0x22, 0x65, 0x6c, 0x69, 0x66, 0x22, 0x00, 0x00
+.data1 	0x22, 0x65, 0x6c, 0x73, 0x65, 0x22, 0x00, 0x00
+.data1 	0x22, 0x74, 0x68, 0x65, 0x6e, 0x22, 0x00, 0x00
+.data1 	0x22, 0x69, 0x66, 0x22, 0x00, 0x00, 0x00, 0x00
+.data1 	0x77, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74
+.data1 	0x69, 0x6f, 0x6e, 0x00, 0x22, 0x60, 0x22, 0x00
+.data1 	0x22, 0x3b, 0x3b, 0x22, 0x00, 0x00, 0x00, 0x00
+.data1 	0x22, 0x29, 0x22, 0x00, 0x22, 0x28, 0x22, 0x00
+.data1 	0x22, 0x7c, 0x22, 0x00, 0x22, 0x7c, 0x7c, 0x22
+.data1 	0x00, 0x00, 0x00, 0x00, 0x22, 0x26, 0x26, 0x22
+.data1 	0x00, 0x00, 0x00, 0x00, 0x22, 0x26, 0x22, 0x00
+.data1 	0x22, 0x3b, 0x22, 0x00, 0x6e, 0x65, 0x77, 0x6c
+.data1 	0x69, 0x6e, 0x65, 0x00, 0x65, 0x6e, 0x64, 0x20
+.data1 	0x6f, 0x66, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x00
+.data1 	0x65, 0x73, 0x61, 0x63, 0x00, 0x00, 0x00, 0x00
+.data1 	0x63, 0x61, 0x73, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x7d, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00
+.data1 	0x64, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x64, 0x6f, 0x00, 0x00, 0x66, 0x6f, 0x72, 0x00
+.data1 	0x75, 0x6e, 0x74, 0x69, 0x6c, 0x00, 0x00, 0x00
+.data1 	0x77, 0x68, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x00
+.data1 	0x66, 0x69, 0x00, 0x00, 0x65, 0x6c, 0x69, 0x66
+.data1 	0x00, 0x00, 0x00, 0x00, 0x65, 0x6c, 0x73, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x74, 0x68, 0x65, 0x6e
+.data1 	0x00, 0x00, 0x00, 0x00, 0x69, 0x66, 0x00, 0x00
+.data1 	0x12, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x03, 0x00, 0x00, 0x00, 0xf8, 0x6e, 0x00, 0x00
+.data1 	0x80, 0x6e, 0x00, 0x00, 0x86, 0x6e, 0x00, 0x00
+.data1 	0x23, 0x6e, 0x00, 0x00, 0x82, 0x75, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00
+.data1 	0x6a, 0x75, 0x00, 0x00, 0x6a, 0x75, 0x00, 0x00
+.data1 	0x6a, 0x75, 0x00, 0x00, 0x82, 0x75, 0x00, 0x00
+.data1 	0x82, 0x75, 0x00, 0x00, 0x82, 0x75, 0x00, 0x00
+.data1 	0x82, 0x75, 0x00, 0x00, 0xfe, 0x74, 0x00, 0x00
+.data1 	0x6a, 0x75, 0x00, 0x00, 0x82, 0x75, 0x00, 0x00
+.data1 	0x82, 0x75, 0x00, 0x00, 0x82, 0x75, 0x00, 0x00
+.data1 	0x6a, 0x75, 0x00, 0x00, 0x80, 0x70, 0x00, 0x00
+.data1 	0x82, 0x75, 0x00, 0x00, 0x82, 0x75, 0x00, 0x00
+.data1 	0x82, 0x75, 0x00, 0x00, 0x82, 0x75, 0x00, 0x00
+.data1 	0x4e, 0x71, 0x00, 0x00, 0x4e, 0x71, 0x00, 0x00
+.data1 	0xbf, 0x71, 0x00, 0x00, 0x82, 0x75, 0x00, 0x00
+.data1 	0x82, 0x75, 0x00, 0x00, 0x40, 0x75, 0x00, 0x00
+.data1 	0x6a, 0x75, 0x00, 0x00, 0x55, 0x73, 0x00, 0x00
+.data1 	0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6e
+.data1 	0x67, 0x20, 0x22, 0x69, 0x6e, 0x22, 0x00, 0x00
+.data1 	0x69, 0x6e, 0x00, 0x00, 0x69, 0x6e, 0x00, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20
+.data1 	0x6c, 0x6f, 0x6f, 0x70, 0x20, 0x76, 0x61, 0x72
+.data1 	0x69, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x66, 0x64, 0x20, 0x6e
+.data1 	0x75, 0x6d, 0x62, 0x65, 0x72, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20
+.data1 	0x65, 0x6f, 0x66, 0x20, 0x6d, 0x61, 0x72, 0x6b
+.data1 	0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x3c
+.data1 	0x3c, 0x20, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65
+.data1 	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00
+.data1 	0x9e, 0x7b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00
+.data1 	0x7f, 0xff, 0xff, 0xff, 0xd5, 0x7a, 0x00, 0x00
+.data1 	0x09, 0x00, 0x00, 0x00, 0x19, 0x7a, 0x00, 0x00
+.data1 	0x0a, 0x00, 0x00, 0x00, 0xb2, 0x7a, 0x00, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0x19, 0x7a, 0x00, 0x00
+.data1 	0x23, 0x00, 0x00, 0x00, 0x4f, 0x7a, 0x00, 0x00
+.data1 	0x26, 0x00, 0x00, 0x00, 0xe3, 0x7a, 0x00, 0x00
+.data1 	0x28, 0x00, 0x00, 0x00, 0x76, 0x7b, 0x00, 0x00
+.data1 	0x29, 0x00, 0x00, 0x00, 0x84, 0x7b, 0x00, 0x00
+.data1 	0x3b, 0x00, 0x00, 0x00, 0x49, 0x7b, 0x00, 0x00
+.data1 	0x5c, 0x00, 0x00, 0x00, 0x6c, 0x7a, 0x00, 0x00
+.data1 	0x7c, 0x00, 0x00, 0x00, 0x16, 0x7b, 0x00, 0x00
+.data1 	0x19, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x7f, 0x7c, 0x00, 0x00
+.data1 	0x32, 0x7c, 0x00, 0x00, 0xcc, 0x7c, 0x00, 0x00
+.data1 	0x86, 0x7d, 0x00, 0x00, 0x92, 0x7d, 0x00, 0x00
+.data1 	0xa5, 0x7d, 0x00, 0x00, 0x0d, 0x7e, 0x00, 0x00
+.data1 	0x44, 0x81, 0x00, 0x00, 0xda, 0x7d, 0x00, 0x00
+.data1 	0x74, 0x7e, 0x00, 0x00, 0x98, 0x7c, 0x00, 0x00
+.data1 	0x4d, 0x83, 0x00, 0x00, 0x42, 0x61, 0x64, 0x20
+.data1 	0x73, 0x75, 0x62, 0x73, 0x74, 0x69, 0x74, 0x75
+.data1 	0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20
+.data1 	0x27, 0x7d, 0x27, 0x00, 0x55, 0x6e, 0x74, 0x65
+.data1 	0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64
+.data1 	0x20, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x64, 0x20
+.data1 	0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x00, 0x00
+.data1 	0x25, 0x73, 0x20, 0x75, 0x6e, 0x65, 0x78, 0x70
+.data1 	0x65, 0x63, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x25, 0x73, 0x20, 0x75, 0x6e, 0x65, 0x78, 0x70
+.data1 	0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x28, 0x65
+.data1 	0x78, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6e, 0x67
+.data1 	0x20, 0x25, 0x73, 0x29, 0x00, 0x00, 0x00, 0x00
+.data1 	0x53, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x20, 0x65
+.data1 	0x72, 0x72, 0x6f, 0x72, 0x3a, 0x20, 0x25, 0x73
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x25, 0x64, 0x3a, 0x20, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x66
+.data1 	0x69, 0x6c, 0x65, 0x20, 0x64, 0x65, 0x73, 0x63
+.data1 	0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x00
+.data1 	0xe1, 0x8a, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00
+.data1 	0x06, 0x00, 0x00, 0x00, 0x30, 0x8a, 0x00, 0x00
+.data1 	0xda, 0x89, 0x00, 0x00, 0x6a, 0x8a, 0x00, 0x00
+.data1 	0xa7, 0x8a, 0x00, 0x00, 0xa7, 0x8a, 0x00, 0x00
+.data1 	0xd2, 0x8a, 0x00, 0x00, 0xd2, 0x8a, 0x00, 0x00
+.data1 	0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x63
+.data1 	0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x25, 0x73
+.data1 	0x3a, 0x20, 0x25, 0x73, 0x00, 0x00, 0x00, 0x00
+.data1 	0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x63
+.data1 	0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x25, 0x73
+.data1 	0x3a, 0x20, 0x25, 0x73, 0x00, 0x00, 0x00, 0x00
+.data1 	0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x6f
+.data1 	0x70, 0x65, 0x6e, 0x20, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x25, 0x73, 0x00, 0x00, 0x50, 0x69, 0x70, 0x65
+.data1 	0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x53, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x20
+.data1 	0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x29
+.data1 	0x00, 0x00, 0x00, 0x00, 0x53, 0x74, 0x6f, 0x70
+.data1 	0x70, 0x65, 0x64, 0x20, 0x28, 0x69, 0x6e, 0x70
+.data1 	0x75, 0x74, 0x29, 0x00, 0x53, 0x74, 0x6f, 0x70
+.data1 	0x70, 0x65, 0x64, 0x00, 0x53, 0x74, 0x6f, 0x70
+.data1 	0x70, 0x65, 0x64, 0x00, 0x45, 0x4d, 0x54, 0x20
+.data1 	0x74, 0x72, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00
+.data1 	0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74
+.data1 	0x65, 0x64, 0x00, 0x00, 0x41, 0x6c, 0x61, 0x72
+.data1 	0x6d, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x00, 0x00
+.data1 	0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x70
+.data1 	0x69, 0x70, 0x65, 0x00, 0x55, 0x73, 0x65, 0x72
+.data1 	0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20
+.data1 	0x32, 0x00, 0x00, 0x00, 0x4d, 0x65, 0x6d, 0x6f
+.data1 	0x72, 0x79, 0x20, 0x66, 0x61, 0x75, 0x6c, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x73, 0x65, 0x72
+.data1 	0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20
+.data1 	0x31, 0x00, 0x00, 0x00, 0x4b, 0x69, 0x6c, 0x6c
+.data1 	0x65, 0x64, 0x00, 0x00, 0x46, 0x6c, 0x6f, 0x61
+.data1 	0x74, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x78, 0x63
+.data1 	0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00
+.data1 	0x42, 0x75, 0x73, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0x61, 0x62, 0x6f, 0x72
+.data1 	0x74, 0x00, 0x00, 0x00, 0x54, 0x72, 0x61, 0x63
+.data1 	0x65, 0x2f, 0x42, 0x50, 0x54, 0x20, 0x74, 0x72
+.data1 	0x61, 0x70, 0x00, 0x00, 0x49, 0x6c, 0x6c, 0x65
+.data1 	0x67, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x73, 0x74
+.data1 	0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00
+.data1 	0x51, 0x75, 0x69, 0x74, 0x00, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70
+.data1 	0x74, 0x00, 0x00, 0x00, 0x48, 0x61, 0x6e, 0x67
+.data1 	0x75, 0x70, 0x00, 0x00, 0x25, 0x73, 0x3a, 0x20
+.data1 	0x62, 0x61, 0x64, 0x20, 0x74, 0x72, 0x61, 0x70
+.data1 	0x00, 0x00, 0x00, 0x00, 0x25, 0x64, 0x3a, 0x20
+.data1 	0x25, 0x73, 0x0a, 0x00, 0x27, 0x8f, 0x00, 0x00
+.data1 	0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0xfa, 0x8e, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
+.data1 	0x0a, 0x8f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00
+.data1 	0x0a, 0x8f, 0x00, 0x00, 0x9e, 0x8f, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x77, 0x8f, 0x00, 0x00, 0x80, 0x8f, 0x00, 0x00
+.data1 	0x89, 0x8f, 0x00, 0x00, 0x53, 0x69, 0x67, 0x6e
+.data1 	0x61, 0x6c, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65
+.data1 	0x6d, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x66
+.data1 	0x61, 0x69, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0xd2, 0x90, 0x00, 0x00, 0xea, 0x90, 0x00, 0x00
+.data1 	0x25, 0x98, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00
+.data1 	0x58, 0x00, 0x00, 0x00, 0x72, 0x95, 0x00, 0x00
+.data1 	0x63, 0x00, 0x00, 0x00, 0xeb, 0x97, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0x0c, 0x95, 0x00, 0x00
+.data1 	0x6f, 0x00, 0x00, 0x00, 0x69, 0x95, 0x00, 0x00
+.data1 	0x73, 0x00, 0x00, 0x00, 0x13, 0x97, 0x00, 0x00
+.data1 	0x75, 0x00, 0x00, 0x00, 0x60, 0x95, 0x00, 0x00
+.data1 	0x78, 0x00, 0x00, 0x00, 0x72, 0x95, 0x00, 0x00
+.data1 	0x50, 0x53, 0x45, 0x3d, 0x2a, 0x20, 0x00, 0x00
+.data1 	0x50, 0x53, 0x32, 0x3d, 0x3e, 0x20, 0x00, 0x00
+.data1 	0x50, 0x41, 0x54, 0x48, 0x3d, 0x3a, 0x2f, 0x62
+.data1 	0x69, 0x6e, 0x3a, 0x2f, 0x75, 0x73, 0x72, 0x2f
+.data1 	0x62, 0x69, 0x6e, 0x00, 0x4d, 0x41, 0x49, 0x4c
+.data1 	0x50, 0x41, 0x54, 0x48, 0x3d, 0x00, 0x00, 0x00
+.data1 	0x4d, 0x41, 0x49, 0x4c, 0x3d, 0x00, 0x00, 0x00
+.data1 	0x49, 0x46, 0x53, 0x3d, 0x20, 0x09, 0x0a, 0x00
+.data1 	0x50, 0x53, 0x31, 0x3d, 0x23, 0x20, 0x00, 0x00
+.data1 	0x50, 0x53, 0x31, 0x3d, 0x24, 0x20, 0x00, 0x00
+.data1 	0x50, 0x53, 0x31, 0x3d, 0x00, 0x00, 0x00, 0x00
+.data1 	0x25, 0x2e, 0x2a, 0x73, 0x3a, 0x20, 0x69, 0x73
+.data1 	0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x6f, 0x6e
+.data1 	0x6c, 0x79, 0x00, 0x00, 0x25, 0x2e, 0x2a, 0x73
+.data1 	0x3a, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x61
+.data1 	0x64, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x00, 0x00
+.data1 	0x25, 0x73, 0x0a, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x69, 0x6e, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e
+.data1 	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00
+.data1 	0x4c, 0x69, 0x73, 0x74, 0x20, 0x61, 0x73, 0x73
+.data1 	0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20
+.data1 	0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6d, 0x70, 0x6c
+.data1 	0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x00
+.data1 	0x12, 0xa5, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00
+.data1 	0x30, 0x00, 0x00, 0x00, 0xdc, 0xa4, 0x00, 0x00
+.data1 	0x5c, 0x00, 0x00, 0x00, 0x23, 0xa5, 0x00, 0x00
+.data1 	0x62, 0x00, 0x00, 0x00, 0xa5, 0xa4, 0x00, 0x00
+.data1 	0x63, 0x00, 0x00, 0x00, 0xae, 0xa4, 0x00, 0x00
+.data1 	0x66, 0x00, 0x00, 0x00, 0xb5, 0xa4, 0x00, 0x00
+.data1 	0x6e, 0x00, 0x00, 0x00, 0xbe, 0xa4, 0x00, 0x00
+.data1 	0x72, 0x00, 0x00, 0x00, 0xc7, 0xa4, 0x00, 0x00
+.data1 	0x74, 0x00, 0x00, 0x00, 0xd0, 0xa4, 0x00, 0x00
+.data1 	0x76, 0x00, 0x00, 0x00, 0xd6, 0xa4, 0x00, 0x00
+.data1 	0x2d, 0x65, 0x00, 0x00, 0x2d, 0x6e, 0x00, 0x00
+.data1 	0x2d, 0x2d, 0x00, 0x00, 0x74, 0x72, 0x75, 0x65
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x25, 0x6c, 0x64, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x25, 0x73, 0x0a, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x74, 0x72, 0x75, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x25, 0x64, 0x00, 0x00
+.data1 	0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x63
+.data1 	0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x00, 0x00
+.data1 	0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x20, 0x65
+.data1 	0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00
+.data1 	0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20
+.data1 	0x5d, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00
+.data1 	0xa7, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x24, 0x00, 0x00, 0x00, 0x5c, 0xaa, 0x00, 0x00
+.data1 	0x71, 0xaa, 0x00, 0x00, 0x78, 0xaa, 0x00, 0x00
+.data1 	0x7f, 0xaa, 0x00, 0x00, 0xb8, 0xaa, 0x00, 0x00
+.data1 	0xbf, 0xaa, 0x00, 0x00, 0xc6, 0xaa, 0x00, 0x00
+.data1 	0xcd, 0xaa, 0x00, 0x00, 0xd4, 0xaa, 0x00, 0x00
+.data1 	0x0e, 0xab, 0x00, 0x00, 0x15, 0xab, 0x00, 0x00
+.data1 	0x1c, 0xab, 0x00, 0x00, 0x37, 0xab, 0x00, 0x00
+.data1 	0x55, 0xab, 0x00, 0x00, 0x55, 0xab, 0x00, 0x00
+.data1 	0xd0, 0xab, 0x00, 0x00, 0xe7, 0xab, 0x00, 0x00
+.data1 	0xf8, 0xab, 0x00, 0x00, 0x0f, 0xac, 0x00, 0x00
+.data1 	0xa7, 0xad, 0x00, 0x00, 0x0f, 0xac, 0x00, 0x00
+.data1 	0xa7, 0xad, 0x00, 0x00, 0x23, 0xac, 0x00, 0x00
+.data1 	0x23, 0xac, 0x00, 0x00, 0x81, 0xab, 0x00, 0x00
+.data1 	0x54, 0xac, 0x00, 0x00, 0x65, 0xac, 0x00, 0x00
+.data1 	0x76, 0xac, 0x00, 0x00, 0x87, 0xac, 0x00, 0x00
+.data1 	0x98, 0xac, 0x00, 0x00, 0xa9, 0xac, 0x00, 0x00
+.data1 	0xba, 0xac, 0x00, 0x00, 0xc5, 0xac, 0x00, 0x00
+.data1 	0xd3, 0xac, 0x00, 0x00, 0xe2, 0xac, 0x00, 0x00
+.data1 	0x04, 0xad, 0x00, 0x00, 0x26, 0xad, 0x00, 0x00
+.data1 	0x44, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e
+.data1 	0x20, 0x62, 0x79, 0x20, 0x7a, 0x65, 0x72, 0x6f
+.data1 	0x00, 0x00, 0x00, 0x00, 0x44, 0x69, 0x76, 0x69
+.data1 	0x73, 0x69, 0x6f, 0x6e, 0x20, 0x62, 0x79, 0x20
+.data1 	0x7a, 0x65, 0x72, 0x6f, 0x00, 0x00, 0x00, 0x00
+.data1 	0x2d, 0x6e, 0x00, 0x00, 0x2d, 0x7a, 0x00, 0x00
+.data1 	0x2d, 0x74, 0x00, 0x00, 0x2d, 0x4c, 0x00, 0x00
+.data1 	0x2d, 0x68, 0x00, 0x00, 0x2d, 0x73, 0x00, 0x00
+.data1 	0x2d, 0x6b, 0x00, 0x00, 0x2d, 0x67, 0x00, 0x00
+.data1 	0x2d, 0x75, 0x00, 0x00, 0x2d, 0x70, 0x00, 0x00
+.data1 	0x2d, 0x62, 0x00, 0x00, 0x2d, 0x63, 0x00, 0x00
+.data1 	0x2d, 0x64, 0x00, 0x00, 0x2d, 0x66, 0x00, 0x00
+.data1 	0x2d, 0x78, 0x00, 0x00, 0x2d, 0x77, 0x00, 0x00
+.data1 	0x2d, 0x72, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00
+.data1 	0x3a, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00
+.data1 	0x2f, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00
+.data1 	0x2d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00
+.data1 	0x2d, 0x67, 0x65, 0x00, 0x2d, 0x6c, 0x65, 0x00
+.data1 	0x2d, 0x6c, 0x74, 0x00, 0x2d, 0x67, 0x74, 0x00
+.data1 	0x2d, 0x6e, 0x65, 0x00, 0x2d, 0x65, 0x71, 0x00
+.data1 	0x2d, 0x6e, 0x65, 0x77, 0x65, 0x72, 0x00, 0x00
+.data1 	0x21, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00
+.data1 	0x26, 0x00, 0x00, 0x00, 0x2d, 0x61, 0x00, 0x00
+.data1 	0x7c, 0x00, 0x00, 0x00, 0x2d, 0x6f, 0x00, 0x00
+.data1 	0x7a, 0xb0, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x3c, 0xae, 0x00, 0x00
+.data1 	0x24, 0x00, 0x00, 0x00, 0xcf, 0xae, 0x00, 0x00
+.data1 	0x2a, 0x00, 0x00, 0x00, 0xe1, 0xae, 0x00, 0x00
+.data1 	0x2e, 0x00, 0x00, 0x00, 0x44, 0xae, 0x00, 0x00
+.data1 	0x5b, 0x00, 0x00, 0x00, 0x54, 0xae, 0x00, 0x00
+.data1 	0x5c, 0x00, 0x00, 0x00, 0xc9, 0xaf, 0x00, 0x00
+.data1 	0x52, 0x45, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72
+.data1 	0x00, 0x00, 0x00, 0x00, 0x52, 0x45, 0x20, 0x65
+.data1 	0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00
+.data1 	0x52, 0x45, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72
+.data1 	0x00, 0x00, 0x00, 0x00, 0x52, 0x45, 0x20, 0x65
+.data1 	0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0c, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x2d, 0xb1, 0x00, 0x00
+.data1 	0x46, 0xb1, 0x00, 0x00, 0x57, 0xb1, 0x00, 0x00
+.data1 	0x63, 0xb1, 0x00, 0x00, 0x6c, 0xb1, 0x00, 0x00
+.data1 	0xdc, 0xb1, 0x00, 0x00, 0xec, 0xb1, 0x00, 0x00
+.data1 	0x0e, 0xb2, 0x00, 0x00, 0x49, 0xb2, 0x00, 0x00
+.data1 	0x54, 0xb2, 0x00, 0x00, 0x64, 0xb2, 0x00, 0x00
+.data1 	0x6c, 0x69, 0x00, 0x00, 0x63, 0x6f, 0x00, 0x00
+.data1 	0x6c, 0x65, 0x00, 0x00, 0x64, 0x75, 0x6d, 0x62
+.data1 	0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x52, 0x4d
+.data1 	0x00, 0x00, 0x00, 0x00, 0x53, 0x65, 0x61, 0x72
+.data1 	0x63, 0x68, 0x3a, 0x20, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0xc2, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
+.data1 	0xff, 0xff, 0xff, 0xff, 0x8a, 0xc2, 0x00, 0x00
+.data1 	0x41, 0x00, 0x00, 0x00, 0x94, 0xc2, 0x00, 0x00
+.data1 	0x42, 0x00, 0x00, 0x00, 0x9e, 0xc2, 0x00, 0x00
+.data1 	0x43, 0x00, 0x00, 0x00, 0xa8, 0xc2, 0x00, 0x00
+.data1 	0x44, 0x00, 0x00, 0x00, 0xb2, 0xc2, 0x00, 0x00
+.data1 	0xe1, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x05, 0x00, 0x00, 0x00, 0x0a, 0xc5, 0x00, 0x00
+.data1 	0x11, 0xc5, 0x00, 0x00, 0x1c, 0xc5, 0x00, 0x00
+.data1 	0xe1, 0xc4, 0x00, 0x00, 0xe1, 0xc4, 0x00, 0x00
+.data1 	0x15, 0xc5, 0x00, 0x00, 0xe1, 0xc4, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
+.data1 	0xf1, 0xc4, 0x00, 0x00, 0xf8, 0xc4, 0x00, 0x00
+.data1 	0x03, 0xc5, 0x00, 0x00, 0x23, 0xc5, 0x00, 0x00
+.data1 	0xe1, 0xc4, 0x00, 0x00, 0xfc, 0xc4, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00
+.data1 	0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x00
+.data1 	0x2f, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00
+.data1 	0x2f, 0x65, 0x74, 0x63, 0x2f, 0x74, 0x65, 0x72
+.data1 	0x6d, 0x63, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00
+.data1 	0x54, 0x45, 0x52, 0x4d, 0x00, 0x00, 0x00, 0x00
+.data1 	0x2f, 0x65, 0x74, 0x63, 0x2f, 0x74, 0x65, 0x72
+.data1 	0x6d, 0x63, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00
+.data1 	0x54, 0x45, 0x52, 0x4d, 0x43, 0x41, 0x50, 0x00
+.data1 	0x26, 0xe2, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x30, 0x00, 0x00, 0x00, 0xe4, 0xe1, 0x00, 0x00
+.data1 	0x31, 0x00, 0x00, 0x00, 0xe4, 0xe1, 0x00, 0x00
+.data1 	0x32, 0x00, 0x00, 0x00, 0xe4, 0xe1, 0x00, 0x00
+.data1 	0x33, 0x00, 0x00, 0x00, 0xe4, 0xe1, 0x00, 0x00
+.data1 	0x45, 0x00, 0x00, 0x00, 0xb4, 0xe1, 0x00, 0x00
+.data1 	0x62, 0x00, 0x00, 0x00, 0xd4, 0xe1, 0x00, 0x00
+.data1 	0x66, 0x00, 0x00, 0x00, 0xdc, 0xe1, 0x00, 0x00
+.data1 	0x6e, 0x00, 0x00, 0x00, 0xbc, 0xe1, 0x00, 0x00
+.data1 	0x72, 0x00, 0x00, 0x00, 0xc4, 0xe1, 0x00, 0x00
+.data1 	0x74, 0x00, 0x00, 0x00, 0xcc, 0xe1, 0x00, 0x00
+.data1 	0x3a, 0xe2, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x2c, 0xe2, 0x00, 0x00
+.data1 	0x3a, 0xe2, 0x00, 0x00, 0xa4, 0xe1, 0x00, 0x00
+.data1 	0xad, 0xe3, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00
+.data1 	0x25, 0x00, 0x00, 0x00, 0xa7, 0xe3, 0x00, 0x00
+.data1 	0x2b, 0x00, 0x00, 0x00, 0xb9, 0xe2, 0x00, 0x00
+.data1 	0x32, 0x00, 0x00, 0x00, 0xec, 0xe2, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0x3a, 0xe3, 0x00, 0x00
+.data1 	0x69, 0x00, 0x00, 0x00, 0xa1, 0xe2, 0x00, 0x00
+.data1 	0x72, 0x00, 0x00, 0x00, 0xad, 0xe2, 0x00, 0x00
+.data1 	0x4f, 0x4f, 0x50, 0x53, 0x00, 0x00, 0x00, 0x00
+.data1 	0xbb, 0xe9, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
+.data1 	0x61, 0x00, 0x00, 0x00, 0xa8, 0xe9, 0x00, 0x00
+.data1 	0x72, 0x00, 0x00, 0x00, 0x83, 0xe9, 0x00, 0x00
+.data1 	0x77, 0x00, 0x00, 0x00, 0x92, 0xe9, 0x00, 0x00
+.data1 	0xfe, 0xe9, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x2b, 0x00, 0x00, 0x00, 0xdf, 0xe9, 0x00, 0x00
+.data1 	0x62, 0x00, 0x00, 0x00, 0xd5, 0xe9, 0x00, 0x00
+.data1 	0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c
+.data1 	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x76, 0x61
+.data1 	0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00
+.data1 	0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x6f
+.data1 	0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e
+.data1 	0x20, 0x6f, 0x6e, 0x20, 0x6e, 0x6f, 0x6e, 0x2d
+.data1 	0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x00, 0x00
+.data1 	0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20
+.data1 	0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67
+.data1 	0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61
+.data1 	0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x69
+.data1 	0x6e, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65
+.data1 	0x73, 0x73, 0x00, 0x00, 0x41, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20
+.data1 	0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c
+.data1 	0x65, 0x00, 0x00, 0x00, 0x4f, 0x70, 0x65, 0x72
+.data1 	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e
+.data1 	0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73
+.data1 	0x73, 0x00, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x74
+.data1 	0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x77, 0x72, 0x6f
+.data1 	0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20
+.data1 	0x66, 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x63, 0x6b
+.data1 	0x65, 0x74, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x74
+.data1 	0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x6e, 0x6f, 0x74
+.data1 	0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74
+.data1 	0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x41, 0x46
+.data1 	0x00, 0x00, 0x00, 0x00, 0x41, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x20, 0x66, 0x61, 0x6d, 0x69
+.data1 	0x6c, 0x79, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73
+.data1 	0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x63, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00
+.data1 	0x41, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20
+.data1 	0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x63
+.data1 	0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f
+.data1 	0x6e, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x75
+.data1 	0x72, 0x67, 0x65, 0x6e, 0x74, 0x20, 0x64, 0x61
+.data1 	0x74, 0x61, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65
+.data1 	0x6e, 0x74, 0x00, 0x00, 0x55, 0x72, 0x67, 0x65
+.data1 	0x6e, 0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20
+.data1 	0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x00
+.data1 	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x64
+.data1 	0x20, 0x6f, 0x75, 0x74, 0x00, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x65, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72
+.data1 	0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x00, 0x00
+.data1 	0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20
+.data1 	0x69, 0x6e, 0x20, 0x75, 0x73, 0x65, 0x00, 0x00
+.data1 	0x41, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20
+.data1 	0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x44, 0x65, 0x73, 0x74
+.data1 	0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20
+.data1 	0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x61, 0x63
+.data1 	0x68, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x64, 0x65, 0x73, 0x74
+.data1 	0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20
+.data1 	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x00
+.data1 	0x57, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x6c
+.data1 	0x6f, 0x63, 0x6b, 0x00, 0x42, 0x61, 0x64, 0x20
+.data1 	0x6d, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72
+.data1 	0x20, 0x69, 0x6f, 0x63, 0x74, 0x6c, 0x00, 0x00
+.data1 	0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20
+.data1 	0x69, 0x6f, 0x63, 0x74, 0x6c, 0x20, 0x66, 0x6f
+.data1 	0x72, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x62
+.data1 	0x75, 0x66, 0x66, 0x65, 0x72, 0x73, 0x20, 0x6c
+.data1 	0x65, 0x66, 0x74, 0x00, 0x49, 0x6e, 0x76, 0x61
+.data1 	0x6c, 0x69, 0x64, 0x20, 0x70, 0x61, 0x63, 0x6b
+.data1 	0x65, 0x74, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x00
+.data1 	0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79
+.data1 	0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x20
+.data1 	0x6f, 0x66, 0x20, 0x73, 0x79, 0x6d, 0x62, 0x6f
+.data1 	0x6c, 0x69, 0x63, 0x20, 0x6c, 0x69, 0x6e, 0x6b
+.data1 	0x73, 0x00, 0x00, 0x00, 0x44, 0x69, 0x72, 0x65
+.data1 	0x63, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x6e, 0x6f
+.data1 	0x74, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x00
+.data1 	0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e
+.data1 	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6d, 0x70
+.data1 	0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x6c
+.data1 	0x6f, 0x63, 0x6b, 0x73, 0x20, 0x61, 0x76, 0x61
+.data1 	0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00
+.data1 	0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d
+.data1 	0x65, 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x6f
+.data1 	0x6e, 0x67, 0x00, 0x00, 0x52, 0x65, 0x73, 0x6f
+.data1 	0x75, 0x72, 0x63, 0x65, 0x20, 0x64, 0x65, 0x61
+.data1 	0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x61, 0x76
+.data1 	0x6f, 0x69, 0x64, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x74
+.data1 	0x6f, 0x6f, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4d, 0x61, 0x74, 0x68
+.data1 	0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e
+.data1 	0x74, 0x00, 0x00, 0x00, 0x42, 0x72, 0x6f, 0x6b
+.data1 	0x65, 0x6e, 0x20, 0x70, 0x69, 0x70, 0x65, 0x00
+.data1 	0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79
+.data1 	0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x00, 0x00
+.data1 	0x52, 0x65, 0x61, 0x64, 0x2d, 0x6f, 0x6e, 0x6c
+.data1 	0x79, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x73
+.data1 	0x79, 0x73, 0x74, 0x65, 0x6d, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20
+.data1 	0x73, 0x65, 0x65, 0x6b, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65
+.data1 	0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x6f, 0x6e
+.data1 	0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00
+.data1 	0x46, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6f
+.data1 	0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x00, 0x00
+.data1 	0x54, 0x65, 0x78, 0x74, 0x20, 0x66, 0x69, 0x6c
+.data1 	0x65, 0x20, 0x62, 0x75, 0x73, 0x79, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x74, 0x79
+.data1 	0x70, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72
+.data1 	0x00, 0x00, 0x00, 0x00, 0x54, 0x6f, 0x6f, 0x20
+.data1 	0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6f, 0x70, 0x65
+.data1 	0x6e, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x00
+.data1 	0x46, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x61, 0x62
+.data1 	0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x66
+.data1 	0x6c, 0x6f, 0x77, 0x00, 0x49, 0x6e, 0x76, 0x61
+.data1 	0x6c, 0x69, 0x64, 0x20, 0x61, 0x72, 0x67, 0x75
+.data1 	0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00
+.data1 	0x49, 0x73, 0x20, 0x61, 0x20, 0x64, 0x69, 0x72
+.data1 	0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x64, 0x69
+.data1 	0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00
+.data1 	0x43, 0x72, 0x6f, 0x73, 0x73, 0x2d, 0x64, 0x65
+.data1 	0x76, 0x69, 0x63, 0x65, 0x20, 0x6c, 0x69, 0x6e
+.data1 	0x6b, 0x00, 0x00, 0x00, 0x46, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x00
+.data1 	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65
+.data1 	0x20, 0x62, 0x75, 0x73, 0x79, 0x00, 0x00, 0x00
+.data1 	0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x64, 0x65
+.data1 	0x76, 0x69, 0x63, 0x65, 0x20, 0x72, 0x65, 0x71
+.data1 	0x75, 0x69, 0x72, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x61, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x00, 0x50, 0x65, 0x72, 0x6d
+.data1 	0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x64
+.data1 	0x65, 0x6e, 0x69, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x65, 0x6e, 0x6f, 0x75
+.data1 	0x67, 0x68, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x00
+.data1 	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65
+.data1 	0x20, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61
+.data1 	0x72, 0x69, 0x6c, 0x79, 0x20, 0x75, 0x6e, 0x61
+.data1 	0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x63
+.data1 	0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x66, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x00
+.data1 	0x45, 0x78, 0x65, 0x63, 0x20, 0x66, 0x6f, 0x72
+.data1 	0x6d, 0x61, 0x74, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0x41, 0x72, 0x67, 0x20
+.data1 	0x6c, 0x69, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x6f
+.data1 	0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x6f
+.data1 	0x72, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73
+.data1 	0x73, 0x00, 0x00, 0x00, 0x49, 0x2f, 0x4f, 0x20
+.data1 	0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70
+.data1 	0x74, 0x65, 0x64, 0x20, 0x73, 0x79, 0x73, 0x74
+.data1 	0x65, 0x6d, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x66, 0x69, 0x6c, 0x65, 0x20, 0x6f, 0x72, 0x20
+.data1 	0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72
+.data1 	0x79, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x6f, 0x77, 0x6e, 0x65, 0x72, 0x00, 0x00, 0x00
+.data1 	0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x30, 0x00
+.data1 	0xeb, 0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0xeb, 0xed, 0x00, 0x00
+.data1 	0xeb, 0xed, 0x00, 0x00, 0x79, 0xf1, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00
+.data1 	0x52, 0xf1, 0x00, 0x00, 0x79, 0xf1, 0x00, 0x00
+.data1 	0x52, 0xf1, 0x00, 0x00, 0x79, 0xf1, 0x00, 0x00
+.data1 	0x52, 0xf1, 0x00, 0x00, 0x5f, 0xf1, 0x00, 0x00
+.data1 	0x5f, 0xf1, 0x00, 0x00, 0x5f, 0xf1, 0x00, 0x00
+.data1 	0x5f, 0xf1, 0x00, 0x00, 0x23, 0xf7, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x0e, 0xf7, 0x00, 0x00, 0x15, 0xf7, 0x00, 0x00
+.data1 	0x1c, 0xf7, 0x00, 0x00, 0x60, 0x2c, 0x00, 0x00
+.data1 	0xcc, 0x19, 0x00, 0x00, 0xe2, 0x19, 0x00, 0x00
+.data1 	0x50, 0x00, 0x00, 0x00, 0x68, 0x59, 0x00, 0x00
+.data1 	0x00, 0xa4, 0x00, 0x00, 0xb4, 0x06, 0x00, 0x00
+.data1 	0x9a, 0x1a, 0x00, 0x00, 0xaa, 0x59, 0x00, 0x00
+.data1 	0xdb, 0x9d, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00
+.data1 	0xf0, 0x6a, 0x00, 0x00, 0x6c, 0x1c, 0x00, 0x00
+.data1 	0x6a, 0x46, 0x00, 0x00, 0x0c, 0x43, 0x00, 0x00
+.data1 	0x4d, 0x9f, 0x00, 0x00, 0x9d, 0x03, 0x00, 0x00
+.data1 	0x1c, 0x5e, 0x00, 0x00, 0x37, 0x1a, 0x00, 0x00
+.data1 	0x82, 0x6a, 0x00, 0x00, 0x34, 0xa1, 0x00, 0x00
+.data1 	0xd6, 0x69, 0x00, 0x00, 0x44, 0x8d, 0x00, 0x00
+.data1 	0x77, 0x1a, 0x00, 0x00, 0xbf, 0x60, 0x00, 0x00
+.data1 	0x79, 0xa1, 0x00, 0x00, 0xb6, 0x45, 0x00, 0x00
+.data1 	0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xec, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0xe0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0xdc, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0xd4, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0xd0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
+.data1 	0xc8, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+.data1 	0xc0, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
+.data1 	0xb8, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00
+.data1 	0xb0, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00
+.data1 	0xa8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00
+.data1 	0x9c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00
+.data1 	0x94, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00
+.data1 	0x8c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00
+.data1 	0x88, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00
+.data1 	0x80, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x78, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00
+.data1 	0x70, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00
+.data1 	0x68, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00
+.data1 	0x60, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00
+.data1 	0x5c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00
+.data1 	0x54, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00
+.data1 	0x4c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00
+.data1 	0x48, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00
+.data1 	0x40, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00
+.data1 	0x38, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
+.data1 	0x30, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00
+.data1 	0x24, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00
+.data1 	0x1c, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00
+.data1 	0x14, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00
+.data1 	0x0c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00
+.data1 	0x04, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x40, 0x28, 0x23, 0x29, 0x63, 0x64, 0x2e, 0x63
+.data1 	0x09, 0x35, 0x2e, 0x32, 0x20, 0x28, 0x42, 0x65
+.data1 	0x72, 0x6b, 0x65, 0x6c, 0x65, 0x79, 0x29, 0x20
+.data1 	0x33, 0x2f, 0x31, 0x33, 0x2f, 0x39, 0x31, 0x00
+.data1 	0x40, 0x28, 0x23, 0x29, 0x64, 0x69, 0x72, 0x65
+.data1 	0x6e, 0x74, 0x2e, 0x63, 0x09, 0x35, 0x2e, 0x31
+.data1 	0x20, 0x28, 0x42, 0x65, 0x72, 0x6b, 0x65, 0x6c
+.data1 	0x65, 0x79, 0x29, 0x20, 0x33, 0x2f, 0x37, 0x2f
+.data1 	0x39, 0x31, 0x00, 0x00, 0x40, 0x28, 0x23, 0x29
+.data1 	0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x63, 0x09
+.data1 	0x35, 0x2e, 0x31, 0x20, 0x28, 0x42, 0x65, 0x72
+.data1 	0x6b, 0x65, 0x6c, 0x65, 0x79, 0x29, 0x20, 0x33
+.data1 	0x2f, 0x37, 0x2f, 0x39, 0x31, 0x00, 0x00, 0x00
+.data1 	0x40, 0x28, 0x23, 0x29, 0x65, 0x76, 0x61, 0x6c
+.data1 	0x2e, 0x63, 0x09, 0x35, 0x2e, 0x33, 0x20, 0x28
+.data1 	0x42, 0x65, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x79
+.data1 	0x29, 0x20, 0x34, 0x2f, 0x31, 0x32, 0x2f, 0x39
+.data1 	0x31, 0x00, 0x00, 0x00, 0x40, 0x28, 0x23, 0x29
+.data1 	0x65, 0x78, 0x65, 0x63, 0x2e, 0x63, 0x09, 0x35
+.data1 	0x2e, 0x32, 0x20, 0x28, 0x42, 0x65, 0x72, 0x6b
+.data1 	0x65, 0x6c, 0x65, 0x79, 0x29, 0x20, 0x33, 0x2f
+.data1 	0x31, 0x33, 0x2f, 0x39, 0x31, 0x00, 0x00, 0x00
+.data1 	0xff, 0xff, 0xff, 0xff, 0x40, 0x28, 0x23, 0x29
+.data1 	0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x2e, 0x63
+.data1 	0x09, 0x35, 0x2e, 0x31, 0x20, 0x28, 0x42, 0x65
+.data1 	0x72, 0x6b, 0x65, 0x6c, 0x65, 0x79, 0x29, 0x20
+.data1 	0x33, 0x2f, 0x37, 0x2f, 0x39, 0x31, 0x00, 0x00
+.data1 	0x40, 0x28, 0x23, 0x29, 0x69, 0x6e, 0x70, 0x75
+.data1 	0x74, 0x2e, 0x63, 0x09, 0x35, 0x2e, 0x34, 0x20
+.data1 	0x28, 0x42, 0x65, 0x72, 0x6b, 0x65, 0x6c, 0x65
+.data1 	0x79, 0x29, 0x20, 0x37, 0x2f, 0x31, 0x2f, 0x39
+.data1 	0x31, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0xb4, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x40, 0x28, 0x23, 0x29, 0x6a, 0x6f, 0x62, 0x73
+.data1 	0x2e, 0x63, 0x09, 0x35, 0x2e, 0x31, 0x20, 0x28
+.data1 	0x42, 0x65, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x79
+.data1 	0x29, 0x20, 0x33, 0x2f, 0x37, 0x2f, 0x39, 0x31
+.data1 	0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
+.data1 	0x40, 0x28, 0x23, 0x29, 0x6d, 0x61, 0x69, 0x6c
+.data1 	0x2e, 0x63, 0x09, 0x35, 0x2e, 0x31, 0x20, 0x28
+.data1 	0x42, 0x65, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x79
+.data1 	0x29, 0x20, 0x33, 0x2f, 0x37, 0x2f, 0x39, 0x31
+.data1 	0x00, 0x00, 0x00, 0x00, 0x40, 0x28, 0x23, 0x29
+.data1 	0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67
+.data1 	0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x31
+.data1 	0x39, 0x39, 0x31, 0x20, 0x54, 0x68, 0x65, 0x20
+.data1 	0x52, 0x65, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x20
+.data1 	0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x55
+.data1 	0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x69, 0x74
+.data1 	0x79, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6c
+.data1 	0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x2e
+.data1 	0x0a, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x72, 0x69
+.data1 	0x67, 0x68, 0x74, 0x73, 0x20, 0x72, 0x65, 0x73
+.data1 	0x65, 0x72, 0x76, 0x65, 0x64, 0x2e, 0x0a, 0x00
+.data1 	0x40, 0x28, 0x23, 0x29, 0x6d, 0x61, 0x69, 0x6e
+.data1 	0x2e, 0x63, 0x09, 0x35, 0x2e, 0x32, 0x20, 0x28
+.data1 	0x42, 0x65, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x79
+.data1 	0x29, 0x20, 0x33, 0x2f, 0x31, 0x33, 0x2f, 0x39
+.data1 	0x31, 0x00, 0x00, 0x00, 0x40, 0x28, 0x23, 0x29
+.data1 	0x6d, 0x65, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63
+.data1 	0x2e, 0x63, 0x09, 0x35, 0x2e, 0x32, 0x20, 0x28
+.data1 	0x42, 0x65, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x79
+.data1 	0x29, 0x20, 0x33, 0x2f, 0x31, 0x33, 0x2f, 0x39
+.data1 	0x31, 0x00, 0x00, 0x00, 0x34, 0x32, 0x00, 0x00
+.data1 	0x38, 0x32, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00
+.data1 	0xff, 0xff, 0xff, 0xff, 0x40, 0x28, 0x23, 0x29
+.data1 	0x6d, 0x69, 0x73, 0x63, 0x62, 0x6c, 0x74, 0x69
+.data1 	0x6e, 0x2e, 0x63, 0x09, 0x35, 0x2e, 0x32, 0x20
+.data1 	0x28, 0x42, 0x65, 0x72, 0x6b, 0x65, 0x6c, 0x65
+.data1 	0x79, 0x29, 0x20, 0x33, 0x2f, 0x31, 0x33, 0x2f
+.data1 	0x39, 0x31, 0x00, 0x00, 0x40, 0x28, 0x23, 0x29
+.data1 	0x6d, 0x79, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67
+.data1 	0x2e, 0x63, 0x09, 0x35, 0x2e, 0x31, 0x20, 0x28
+.data1 	0x42, 0x65, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x79
+.data1 	0x29, 0x20, 0x33, 0x2f, 0x37, 0x2f, 0x39, 0x31
+.data1 	0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00
+.data1 	0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00
+.data1 	0x0c, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00
+.data1 	0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x10, 0x00
+.data1 	0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00
+.data1 	0x14, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00
+.data1 	0x10, 0x00, 0x00, 0x00, 0x40, 0x28, 0x23, 0x29
+.data1 	0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e
+.data1 	0x63, 0x09, 0x35, 0x2e, 0x32, 0x20, 0x28, 0x42
+.data1 	0x65, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x79, 0x29
+.data1 	0x20, 0x33, 0x2f, 0x31, 0x33, 0x2f, 0x39, 0x31
+.data1 	0x00, 0x00, 0x00, 0x00, 0x65, 0x66, 0x49, 0x69
+.data1 	0x6a, 0x6e, 0x73, 0x78, 0x7a, 0x76, 0x00, 0x00
+.data1 	0x40, 0x28, 0x23, 0x29, 0x70, 0x61, 0x72, 0x73
+.data1 	0x65, 0x72, 0x2e, 0x63, 0x09, 0x35, 0x2e, 0x33
+.data1 	0x20, 0x28, 0x42, 0x65, 0x72, 0x6b, 0x65, 0x6c
+.data1 	0x65, 0x79, 0x29, 0x20, 0x34, 0x2f, 0x31, 0x32
+.data1 	0x2f, 0x39, 0x31, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00
+.data1 	0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00
+.data1 	0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
+.data1 	0x2c, 0x09, 0x00, 0x00, 0x24, 0x09, 0x00, 0x00
+.data1 	0x20, 0x09, 0x00, 0x00, 0x1c, 0x09, 0x00, 0x00
+.data1 	0x14, 0x09, 0x00, 0x00, 0x0c, 0x09, 0x00, 0x00
+.data1 	0x08, 0x09, 0x00, 0x00, 0x04, 0x09, 0x00, 0x00
+.data1 	0x00, 0x09, 0x00, 0x00, 0xf8, 0x08, 0x00, 0x00
+.data1 	0xf4, 0x08, 0x00, 0x00, 0xe8, 0x08, 0x00, 0x00
+.data1 	0xe0, 0x08, 0x00, 0x00, 0xd8, 0x08, 0x00, 0x00
+.data1 	0xd0, 0x08, 0x00, 0x00, 0xc8, 0x08, 0x00, 0x00
+.data1 	0xc0, 0x08, 0x00, 0x00, 0xb8, 0x08, 0x00, 0x00
+.data1 	0xb0, 0x08, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x00
+.data1 	0xa0, 0x08, 0x00, 0x00, 0x98, 0x08, 0x00, 0x00
+.data1 	0x90, 0x08, 0x00, 0x00, 0x8c, 0x08, 0x00, 0x00
+.data1 	0x88, 0x08, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00
+.data1 	0x78, 0x08, 0x00, 0x00, 0x8c, 0x09, 0x00, 0x00
+.data1 	0x84, 0x09, 0x00, 0x00, 0x7c, 0x09, 0x00, 0x00
+.data1 	0x74, 0x09, 0x00, 0x00, 0x70, 0x09, 0x00, 0x00
+.data1 	0x68, 0x09, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00
+.data1 	0x5c, 0x09, 0x00, 0x00, 0x58, 0x09, 0x00, 0x00
+.data1 	0x50, 0x09, 0x00, 0x00, 0x4c, 0x09, 0x00, 0x00
+.data1 	0x48, 0x09, 0x00, 0x00, 0x40, 0x09, 0x00, 0x00
+.data1 	0x38, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x82, 0x41, 0x40, 0x3d, 0x00, 0x00, 0x00, 0x00
+.data1 	0x7d, 0x2d, 0x2b, 0x3f, 0x3d, 0x00, 0x00, 0x00
+.data1 	0x40, 0x28, 0x23, 0x29, 0x72, 0x65, 0x64, 0x69
+.data1 	0x72, 0x2e, 0x63, 0x09, 0x35, 0x2e, 0x31, 0x20
+.data1 	0x28, 0x42, 0x65, 0x72, 0x6b, 0x65, 0x6c, 0x65
+.data1 	0x79, 0x29, 0x20, 0x33, 0x2f, 0x37, 0x2f, 0x39
+.data1 	0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x40, 0x28, 0x23, 0x29, 0x73, 0x68, 0x6f, 0x77
+.data1 	0x2e, 0x63, 0x09, 0x35, 0x2e, 0x32, 0x20, 0x28
+.data1 	0x42, 0x65, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x79
+.data1 	0x29, 0x20, 0x34, 0x2f, 0x31, 0x32, 0x2f, 0x39
+.data1 	0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x44, 0x0d, 0x00, 0x00
+.data1 	0x38, 0x0d, 0x00, 0x00, 0x30, 0x0d, 0x00, 0x00
+.data1 	0x1c, 0x0d, 0x00, 0x00, 0x0c, 0x0d, 0x00, 0x00
+.data1 	0x04, 0x0d, 0x00, 0x00, 0xf8, 0x0c, 0x00, 0x00
+.data1 	0xe4, 0x0c, 0x00, 0x00, 0xdc, 0x0c, 0x00, 0x00
+.data1 	0xcc, 0x0c, 0x00, 0x00, 0xbc, 0x0c, 0x00, 0x00
+.data1 	0xac, 0x0c, 0x00, 0x00, 0xa0, 0x0c, 0x00, 0x00
+.data1 	0x94, 0x0c, 0x00, 0x00, 0x88, 0x0c, 0x00, 0x00
+.data1 	0x7c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x74, 0x0c, 0x00, 0x00
+.data1 	0x6c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5c, 0x0c, 0x00, 0x00, 0x48, 0x0c, 0x00, 0x00
+.data1 	0x09, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x0b, 0x01, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x0b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x0b
+.data1 	0x03, 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x0b, 0x0b, 0x00, 0x0b
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00
+.data1 	0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x08, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x0a, 0x0a
+.data1 	0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x05
+.data1 	0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0a, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x09, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x05, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00
+.data1 	0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
+.data1 	0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x01
+.data1 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x02, 0x02
+.data1 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+.data1 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+.data1 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+.data1 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x04
+.data1 	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04
+.data1 	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04
+.data1 	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x40, 0x28, 0x23, 0x29, 0x74, 0x72, 0x61, 0x70
+.data1 	0x2e, 0x63, 0x09, 0x35, 0x2e, 0x32, 0x20, 0x28
+.data1 	0x42, 0x65, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x79
+.data1 	0x29, 0x20, 0x34, 0x2f, 0x31, 0x32, 0x2f, 0x39
+.data1 	0x31, 0x00, 0x00, 0x00, 0x40, 0x28, 0x23, 0x29
+.data1 	0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2e, 0x63
+.data1 	0x09, 0x35, 0x2e, 0x31, 0x20, 0x28, 0x42, 0x65
+.data1 	0x72, 0x6b, 0x65, 0x6c, 0x65, 0x79, 0x29, 0x20
+.data1 	0x33, 0x2f, 0x37, 0x2f, 0x39, 0x31, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xfd, 0xff, 0x00, 0x00, 0x68, 0x23, 0x00, 0x00
+.data1 	0x7c, 0x23, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33
+.data1 	0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42
+.data1 	0x43, 0x44, 0x45, 0x46, 0x40, 0x28, 0x23, 0x29
+.data1 	0x76, 0x61, 0x72, 0x2e, 0x63, 0x09, 0x35, 0x2e
+.data1 	0x33, 0x20, 0x28, 0x42, 0x65, 0x72, 0x6b, 0x65
+.data1 	0x6c, 0x65, 0x79, 0x29, 0x20, 0x34, 0x2f, 0x31
+.data1 	0x32, 0x2f, 0x39, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa0, 0x2d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00
+.data1 	0x38, 0x0e, 0x00, 0x00, 0x1c, 0x32, 0x00, 0x00
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x30, 0x0e, 0x00, 0x00
+.data1 	0x10, 0x32, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x24, 0x0e, 0x00, 0x00, 0xe0, 0x2c, 0x00, 0x00
+.data1 	0x0c, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0x00
+.data1 	0x84, 0x34, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00
+.data1 	0x08, 0x0e, 0x00, 0x00, 0x90, 0x34, 0x00, 0x00
+.data1 	0x0c, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x00, 0x00
+.data1 	0x78, 0x10, 0x00, 0x00, 0x74, 0x10, 0x00, 0x00
+.data1 	0x70, 0x10, 0x00, 0x00, 0x6c, 0x10, 0x00, 0x00
+.data1 	0x68, 0x10, 0x00, 0x00, 0x64, 0x10, 0x00, 0x00
+.data1 	0x60, 0x10, 0x00, 0x00, 0x5c, 0x10, 0x00, 0x00
+.data1 	0x58, 0x10, 0x00, 0x00, 0x54, 0x10, 0x00, 0x00
+.data1 	0x50, 0x10, 0x00, 0x00, 0x4c, 0x10, 0x00, 0x00
+.data1 	0x48, 0x10, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00
+.data1 	0x40, 0x10, 0x00, 0x00, 0x3c, 0x10, 0x00, 0x00
+.data1 	0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xcc, 0x10, 0x00, 0x00, 0xc8, 0x10, 0x00, 0x00
+.data1 	0xc4, 0x10, 0x00, 0x00, 0xc0, 0x10, 0x00, 0x00
+.data1 	0xbc, 0x10, 0x00, 0x00, 0xb8, 0x10, 0x00, 0x00
+.data1 	0xb0, 0x10, 0x00, 0x00, 0xac, 0x10, 0x00, 0x00
+.data1 	0xa8, 0x10, 0x00, 0x00, 0xa4, 0x10, 0x00, 0x00
+.data1 	0xa0, 0x10, 0x00, 0x00, 0x9c, 0x10, 0x00, 0x00
+.data1 	0x98, 0x10, 0x00, 0x00, 0x94, 0x10, 0x00, 0x00
+.data1 	0x90, 0x10, 0x00, 0x00, 0x8c, 0x10, 0x00, 0x00
+.data1 	0x88, 0x10, 0x00, 0x00, 0x84, 0x10, 0x00, 0x00
+.data1 	0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x03, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c
+.data1 	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c
+.data1 	0x0c, 0x0c, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04
+.data1 	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05
+.data1 	0x05, 0x06, 0x06, 0x06, 0x07, 0x00, 0x00, 0x00
+.data1 	0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03
+.data1 	0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x01
+.data1 	0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02
+.data1 	0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+.data1 	0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x20, 0x25, 0x00, 0x00
+.data1 	0x0d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x22, 0x23, 0x24, 0x26, 0x27, 0x28, 0x29, 0x2a
+.data1 	0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x5b, 0x5c
+.data1 	0x5d, 0x5e, 0x60, 0x7b, 0x7c, 0x7d, 0x7e, 0x0a
+.data1 	0x09, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x92, 0xca, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x01, 0xc7, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0xc8, 0xc0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+.data1 	0x25, 0xc7, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
+.data1 	0x46, 0xc7, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00
+.data1 	0xde, 0xbe, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00
+.data1 	0xc5, 0xb7, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00
+.data1 	0xf0, 0xc0, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00
+.data1 	0x75, 0xc8, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x4b, 0xc9, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00
+.data1 	0x1a, 0xc1, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00
+.data1 	0x99, 0xbb, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00
+.data1 	0x4b, 0xc9, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00
+.data1 	0x9a, 0xbc, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00
+.data1 	0xc5, 0xb7, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00
+.data1 	0xaa, 0xbc, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00
+.data1 	0xc5, 0xb7, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00
+.data1 	0x0d, 0xbe, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00
+.data1 	0xc5, 0xb7, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
+.data1 	0x61, 0xc9, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00
+.data1 	0xc5, 0xb7, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00
+.data1 	0x0a, 0xca, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00
+.data1 	0xb2, 0xcc, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00
+.data1 	0xa8, 0xca, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00
+.data1 	0xfe, 0xca, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00
+.data1 	0x46, 0xc7, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00
+.data1 	0x57, 0xc2, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00
+.data1 	0x8d, 0xcb, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00
+.data1 	0xc5, 0xb7, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00
+.data1 	0xc5, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00
+.data1 	0x31, 0xca, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00
+.data1 	0x31, 0xca, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
+.data1 	0x92, 0xca, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00
+.data1 	0x09, 0xce, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00
+.data1 	0xba, 0xbc, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00
+.data1 	0xd4, 0xbc, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00
+.data1 	0x14, 0xc8, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00
+.data1 	0x38, 0xcc, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00
+.data1 	0xf5, 0xcb, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00
+.data1 	0xe8, 0xcb, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00
+.data1 	0x7a, 0xb9, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00
+.data1 	0xc6, 0xbb, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00
+.data1 	0x87, 0xb9, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00
+.data1 	0xfe, 0xca, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00
+.data1 	0x2a, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00
+.data1 	0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x20, 0x28, 0x28, 0x28, 0x28, 0x28, 0x20
+.data1 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04
+.data1 	0x04, 0x04, 0x04, 0x10, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x10, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41
+.data1 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+.data1 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+.data1 	0x01, 0x01, 0x01, 0x01, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x10, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42
+.data1 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+.data1 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+.data1 	0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10
+.data1 	0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x53, 0x53, 0x53, 0x53
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc4, 0x36, 0x00, 0x00, 0x55, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0xc8, 0x18, 0x00, 0x00
+.data1 	0xbc, 0x18, 0x00, 0x00, 0xa0, 0x18, 0x00, 0x00
+.data1 	0x90, 0x18, 0x00, 0x00, 0x78, 0x18, 0x00, 0x00
+.data1 	0x6c, 0x18, 0x00, 0x00, 0x50, 0x18, 0x00, 0x00
+.data1 	0x3c, 0x18, 0x00, 0x00, 0x28, 0x18, 0x00, 0x00
+.data1 	0x18, 0x18, 0x00, 0x00, 0x0c, 0x18, 0x00, 0x00
+.data1 	0xe8, 0x17, 0x00, 0x00, 0xd8, 0x17, 0x00, 0x00
+.data1 	0xc4, 0x17, 0x00, 0x00, 0xb8, 0x17, 0x00, 0x00
+.data1 	0xa0, 0x17, 0x00, 0x00, 0x90, 0x17, 0x00, 0x00
+.data1 	0x84, 0x17, 0x00, 0x00, 0x70, 0x17, 0x00, 0x00
+.data1 	0x60, 0x17, 0x00, 0x00, 0x50, 0x17, 0x00, 0x00
+.data1 	0x40, 0x17, 0x00, 0x00, 0x2c, 0x17, 0x00, 0x00
+.data1 	0x18, 0x17, 0x00, 0x00, 0x04, 0x17, 0x00, 0x00
+.data1 	0xf0, 0x16, 0x00, 0x00, 0xe0, 0x16, 0x00, 0x00
+.data1 	0xd0, 0x16, 0x00, 0x00, 0xb8, 0x16, 0x00, 0x00
+.data1 	0xa8, 0x16, 0x00, 0x00, 0x90, 0x16, 0x00, 0x00
+.data1 	0x80, 0x16, 0x00, 0x00, 0x74, 0x16, 0x00, 0x00
+.data1 	0x64, 0x16, 0x00, 0x00, 0x50, 0x16, 0x00, 0x00
+.data1 	0x34, 0x16, 0x00, 0x00, 0x20, 0x16, 0x00, 0x00
+.data1 	0x0c, 0x16, 0x00, 0x00, 0xf0, 0x15, 0x00, 0x00
+.data1 	0xdc, 0x15, 0x00, 0x00, 0xb8, 0x15, 0x00, 0x00
+.data1 	0xfc, 0x27, 0x00, 0x00, 0xfc, 0x27, 0x00, 0x00
+.data1 	0xfc, 0x27, 0x00, 0x00, 0xfc, 0x27, 0x00, 0x00
+.data1 	0xfc, 0x27, 0x00, 0x00, 0xfc, 0x27, 0x00, 0x00
+.data1 	0xfc, 0x27, 0x00, 0x00, 0xfc, 0x27, 0x00, 0x00
+.data1 	0xfc, 0x27, 0x00, 0x00, 0xa4, 0x15, 0x00, 0x00
+.data1 	0x8c, 0x15, 0x00, 0x00, 0x70, 0x15, 0x00, 0x00
+.data1 	0x5c, 0x15, 0x00, 0x00, 0x50, 0x15, 0x00, 0x00
+.data1 	0x38, 0x15, 0x00, 0x00, 0x1c, 0x15, 0x00, 0x00
+.data1 	0x08, 0x15, 0x00, 0x00, 0xf8, 0x14, 0x00, 0x00
+.data1 	0xe4, 0x14, 0x00, 0x00, 0xd0, 0x14, 0x00, 0x00
+.data1 	0xb8, 0x14, 0x00, 0x00, 0xa4, 0x14, 0x00, 0x00
+.data1 	0x8c, 0x14, 0x00, 0x00, 0x7c, 0x14, 0x00, 0x00
+.data1 	0x68, 0x14, 0x00, 0x00, 0x54, 0x14, 0x00, 0x00
+.data1 	0x34, 0x14, 0x00, 0x00, 0x14, 0x14, 0x00, 0x00
+.data1 	0xf4, 0x13, 0x00, 0x00, 0xdc, 0x13, 0x00, 0x00
+.data1 	0xc4, 0x13, 0x00, 0x00, 0xa4, 0x13, 0x00, 0x00
+.data1 	0x90, 0x13, 0x00, 0x00, 0x70, 0x13, 0x00, 0x00
+.data1 	0x58, 0x13, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x40, 0x29, 0x00, 0x00, 0x58, 0x29, 0x00, 0x00
+.data1 	0x70, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x03, 0x20, 0x10, 0x20, 0x00, 0x00, 0x00
+.data1 	0x20, 0x1e, 0x00, 0x00, 0xc0, 0x0d, 0x00, 0x00
+.data1 	0xb0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x70, 0x1e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0xed, 0x8b, 0x04, 0x24, 0x8d, 0x54, 0x24
+.data1 	0x04, 0x8d, 0x4c, 0x84, 0x08, 0xbb, 0xc8, 0x0a
+.data1 	0x00, 0x00, 0x81, 0xfb, 0xc0, 0x0d, 0x00, 0x00
+.data1 	0x73, 0x13, 0xf6, 0xc3, 0x03, 0x75, 0x0e, 0x81
+.data1 	0x3b, 0x53, 0x53, 0x53, 0x53, 0x75, 0x06, 0x89
+.data1 	0x1d, 0xa4, 0x0a, 0x00, 0x00, 0x8b, 0x1d, 0xa4
+.data1 	0x0a, 0x00, 0x00, 0x89, 0x0b, 0x51, 0x52, 0x50
+.data1 	0x0f, 0x01, 0xe0, 0xa8, 0x04, 0x0f, 0x94, 0x05
+.data1 	0xe8, 0x1d, 0x00, 0x00, 0xe8, 0x9a, 0x04, 0x00
+.data1 	0x00, 0x50, 0xe8, 0x5a, 0x06, 0x00, 0x00, 0xf4
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x75, 0x08, 0xff
+.data1 	0x75, 0x0c, 0x68, 0x00, 0x01, 0x00, 0x00, 0xe8
+.data1 	0x08, 0x09, 0x00, 0x00, 0x59, 0x59, 0x68, 0xf8
+.data1 	0x00, 0x00, 0x00, 0xe8, 0xfc, 0x08, 0x00, 0x00
+.data1 	0x59, 0x68, 0xa4, 0x00, 0x00, 0x00, 0x68, 0xac
+.data1 	0x00, 0x00, 0x00, 0x68, 0xb4, 0x00, 0x00, 0x00
+.data1 	0x56, 0x68, 0xbc, 0x00, 0x00, 0x00, 0xe8, 0xe1
+.data1 	0x08, 0x00, 0x00, 0x83, 0xc4, 0x14, 0x56, 0x68
+.data1 	0x90, 0x00, 0x00, 0x00, 0xe8, 0xd3, 0x08, 0x00
+.data1 	0x00, 0x59, 0x59, 0x56, 0x68, 0x78, 0x00, 0x00
+.data1 	0x00, 0xe8, 0xc6, 0x08, 0x00, 0x00, 0x59, 0x59
+.data1 	0x56, 0x68, 0x60, 0x00, 0x00, 0x00, 0xe8, 0xb9
+.data1 	0x08, 0x00, 0x00, 0x59, 0x59, 0x56, 0x68, 0x4c
+.data1 	0x00, 0x00, 0x00, 0xe8, 0xac, 0x08, 0x00, 0x00
+.data1 	0x59, 0x59, 0x68, 0x48, 0x00, 0x00, 0x00, 0xe8
+.data1 	0xa0, 0x08, 0x00, 0x00, 0x59, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0xff, 0x75, 0x08, 0xff, 0x75
+.data1 	0x08, 0xe8, 0xee, 0x05, 0x00, 0x00, 0x59, 0x50
+.data1 	0x68, 0x10, 0x01, 0x00, 0x00, 0xe8, 0x82, 0x08
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xff, 0x75, 0x08
+.data1 	0xe8, 0xb4, 0x05, 0x00, 0x00, 0x59, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x2c, 0x56, 0x57
+.data1 	0x8b, 0x75, 0x0c, 0x83, 0x7d, 0x08, 0x02, 0x7d
+.data1 	0x16, 0x68, 0x50, 0x03, 0x00, 0x00, 0xff, 0x36
+.data1 	0xe8, 0x3b, 0xff, 0xff, 0xff, 0x59, 0x59, 0x6a
+.data1 	0x16, 0xe8, 0x8b, 0x05, 0x00, 0x00, 0x59, 0xc7
+.data1 	0x05, 0xc0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x83, 0x3d, 0xc0, 0x0d, 0x00, 0x00, 0x06
+.data1 	0x73, 0x23, 0x8b, 0x15, 0xc0, 0x0d, 0x00, 0x00
+.data1 	0xff, 0x76, 0x04, 0xff, 0x34, 0x95, 0xa8, 0x0a
+.data1 	0x00, 0x00, 0xe8, 0xb9, 0x08, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x74, 0x08, 0xff, 0x05, 0xc0
+.data1 	0x0d, 0x00, 0x00, 0xeb, 0xd4, 0x83, 0x3d, 0xc0
+.data1 	0x0d, 0x00, 0x00, 0x06, 0x75, 0x16, 0x68, 0x38
+.data1 	0x03, 0x00, 0x00, 0xff, 0x36, 0xe8, 0xe6, 0xfe
+.data1 	0xff, 0xff, 0x59, 0x59, 0x6a, 0x26, 0xe8, 0x36
+.data1 	0x05, 0x00, 0x00, 0x59, 0xba, 0x00, 0x07, 0x00
+.data1 	0x00, 0x03, 0x15, 0xc0, 0x0d, 0x00, 0x00, 0x89
+.data1 	0x55, 0xd4, 0x81, 0xfa, 0x00, 0x07, 0x00, 0x00
+.data1 	0x0f, 0x85, 0x39, 0x02, 0x00, 0x00, 0x8b, 0x55
+.data1 	0x08, 0x4a, 0x83, 0xfa, 0x02, 0x7d, 0x16, 0x68
+.data1 	0x14, 0x03, 0x00, 0x00, 0xff, 0x36, 0xe8, 0xad
+.data1 	0xfe, 0xff, 0xff, 0x59, 0x59, 0x6a, 0x16, 0xe8
+.data1 	0xfd, 0x04, 0x00, 0x00, 0x59, 0x8b, 0x56, 0x08
+.data1 	0x89, 0x15, 0xc8, 0x0d, 0x00, 0x00, 0x80, 0x3a
+.data1 	0x2f, 0x74, 0x16, 0x68, 0xf4, 0x02, 0x00, 0x00
+.data1 	0xff, 0x36, 0xe8, 0x89, 0xfe, 0xff, 0xff, 0x59
+.data1 	0x59, 0x6a, 0x16, 0xe8, 0xd9, 0x04, 0x00, 0x00
+.data1 	0x59, 0x8d, 0x45, 0xdc, 0x50, 0xff, 0x35, 0xc8
+.data1 	0x0d, 0x00, 0x00, 0xe8, 0xb8, 0x07, 0x00, 0x00
+.data1 	0x59, 0x59, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x29, 0xff, 0x35, 0xc8, 0x0d, 0x00, 0x00, 0xe8
+.data1 	0xec, 0x06, 0x00, 0x00, 0x59, 0x68, 0xd8, 0x02
+.data1 	0x00, 0x00, 0x68, 0x00, 0x0b, 0x00, 0x00, 0xe8
+.data1 	0xbc, 0x06, 0x00, 0x00, 0x59, 0x59, 0xff, 0x35
+.data1 	0xcc, 0x0a, 0x00, 0x00, 0xe8, 0x98, 0x04, 0x00
+.data1 	0x00, 0x59, 0x0f, 0xb7, 0x55, 0xe4, 0xf7, 0xc2
+.data1 	0x00, 0x80, 0x00, 0x00, 0x75, 0x16, 0x68, 0xb8
+.data1 	0x02, 0x00, 0x00, 0xff, 0x36, 0xe8, 0x26, 0xfe
+.data1 	0xff, 0xff, 0x59, 0x59, 0x6a, 0x16, 0xe8, 0x76
+.data1 	0x04, 0x00, 0x00, 0x59, 0xbf, 0x03, 0x00, 0x00
+.data1 	0x00, 0x39, 0x7d, 0x08, 0x0f, 0x8e, 0x9a, 0x02
+.data1 	0x00, 0x00, 0x89, 0xfa, 0x42, 0x39, 0x55, 0x08
+.data1 	0x7f, 0x16, 0x68, 0x98, 0x02, 0x00, 0x00, 0xff
+.data1 	0x36, 0xe8, 0xfa, 0xfd, 0xff, 0xff, 0x59, 0x59
+.data1 	0x6a, 0x16, 0xe8, 0x4a, 0x04, 0x00, 0x00, 0x59
+.data1 	0x89, 0xf2, 0x68, 0x90, 0x02, 0x00, 0x00, 0xff
+.data1 	0x34, 0xba, 0xe8, 0x91, 0x07, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x75, 0x13, 0x89, 0xfa, 0x42
+.data1 	0x89, 0xf1, 0x8b, 0x14, 0x91, 0x89, 0x15, 0xcc
+.data1 	0x0d, 0x00, 0x00, 0xe9, 0x37, 0x01, 0x00, 0x00
+.data1 	0x89, 0xf2, 0x68, 0x88, 0x02, 0x00, 0x00, 0xff
+.data1 	0x34, 0xba, 0xe8, 0x69, 0x07, 0x00, 0x00, 0x59
+.data1 	0x59, 0x85, 0xc0, 0x0f, 0x85, 0x62, 0x00, 0x00
+.data1 	0x00, 0x89, 0xfa, 0x42, 0x89, 0xf1, 0x6a, 0x0a
+.data1 	0x8d, 0x45, 0xd8, 0x50, 0xff, 0x34, 0x91, 0xe8
+.data1 	0x3c, 0x04, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xa3
+.data1 	0xd4, 0x0d, 0x00, 0x00, 0x68, 0x84, 0x02, 0x00
+.data1 	0x00, 0xff, 0x75, 0xd8, 0xe8, 0x37, 0x07, 0x00
+.data1 	0x00, 0x59, 0x59, 0x85, 0xc0, 0x75, 0x0c, 0x6b
+.data1 	0x05, 0xd4, 0x0d, 0x00, 0x00, 0x3c, 0xa3, 0xd4
+.data1 	0x0d, 0x00, 0x00, 0x83, 0x3d, 0xd4, 0x0d, 0x00
+.data1 	0x00, 0x00, 0x0f, 0x8f, 0xd7, 0x00, 0x00, 0x00
+.data1 	0x68, 0x64, 0x02, 0x00, 0x00, 0xff, 0x36, 0xe8
+.data1 	0x5c, 0xfd, 0xff, 0xff, 0x59, 0x59, 0x6a, 0x16
+.data1 	0xe8, 0xac, 0x03, 0x00, 0x00, 0x59, 0xe9, 0xbc
+.data1 	0x00, 0x00, 0x00, 0x89, 0xf2, 0x68, 0x5c, 0x02
+.data1 	0x00, 0x00, 0xff, 0x34, 0xba, 0xe8, 0xee, 0x06
+.data1 	0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x0f, 0x85
+.data1 	0x68, 0x00, 0x00, 0x00, 0x89, 0xfa, 0x42, 0x89
+.data1 	0xf1, 0x8d, 0x45, 0xdc, 0x50, 0xff, 0x34, 0x91
+.data1 	0xe8, 0x6b, 0x06, 0x00, 0x00, 0x59, 0x59, 0x3d
+.data1 	0xff, 0xff, 0xff, 0xff, 0x75, 0x1a, 0x68, 0x3c
+.data1 	0x02, 0x00, 0x00, 0xff, 0x36, 0xe8, 0x0e, 0xfd
+.data1 	0xff, 0xff, 0x59, 0x59, 0xff, 0x35, 0xcc, 0x0a
+.data1 	0x00, 0x00, 0xe8, 0x5a, 0x03, 0x00, 0x00, 0x59
+.data1 	0x0f, 0xb7, 0x55, 0xe4, 0xf7, 0xc2, 0x00, 0x60
+.data1 	0x00, 0x00, 0x75, 0x16, 0x68, 0x1c, 0x02, 0x00
+.data1 	0x00, 0xff, 0x36, 0xe8, 0xe8, 0xfc, 0xff, 0xff
+.data1 	0x59, 0x59, 0x6a, 0x16, 0xe8, 0x38, 0x03, 0x00
+.data1 	0x00, 0x59, 0x0f, 0xbf, 0x45, 0xec, 0xc1, 0xf8
+.data1 	0x08, 0x0f, 0xb6, 0xd0, 0x89, 0x15, 0xd0, 0x0d
+.data1 	0x00, 0x00, 0xeb, 0x3b, 0x89, 0xf2, 0x68, 0x14
+.data1 	0x02, 0x00, 0x00, 0xff, 0x34, 0xba, 0xe8, 0x6d
+.data1 	0x06, 0x00, 0x00, 0x59, 0x59, 0x85, 0xc0, 0x75
+.data1 	0x10, 0x89, 0xfa, 0x42, 0x89, 0xf1, 0x8b, 0x14
+.data1 	0x91, 0x89, 0x15, 0xd8, 0x0d, 0x00, 0x00, 0xeb
+.data1 	0x16, 0x68, 0xf4, 0x01, 0x00, 0x00, 0xff, 0x36
+.data1 	0xe8, 0x9b, 0xfc, 0xff, 0xff, 0x59, 0x59, 0x6a
+.data1 	0x16, 0xe8, 0xeb, 0x02, 0x00, 0x00, 0x59, 0x83
+.data1 	0xc7, 0x02, 0xe9, 0x72, 0xfe, 0xff, 0xff, 0x81
+.data1 	0x7d, 0xd4, 0x01, 0x07, 0x00, 0x00, 0x74, 0x09
+.data1 	0x81, 0x7d, 0xd4, 0x02, 0x07, 0x00, 0x00, 0x75
+.data1 	0x57, 0x8b, 0x55, 0x08, 0x4a, 0x83, 0xfa, 0x02
+.data1 	0x7d, 0x16, 0x68, 0xd4, 0x01, 0x00, 0x00, 0xff
+.data1 	0x36, 0xe8, 0x62, 0xfc, 0xff, 0xff, 0x59, 0x59
+.data1 	0x6a, 0x16, 0xe8, 0xb2, 0x02, 0x00, 0x00, 0x59
+.data1 	0xff, 0x76, 0x08, 0xe8, 0x78, 0x02, 0x00, 0x00
+.data1 	0x59, 0xa3, 0xc4, 0x0d, 0x00, 0x00, 0x31, 0xdb
+.data1 	0x85, 0xc0, 0x0f, 0x94, 0xc3, 0x85, 0xdb, 0x0f
+.data1 	0x8e, 0xc7, 0x00, 0x00, 0x00, 0x68, 0xb4, 0x01
+.data1 	0x00, 0x00, 0xff, 0x36, 0xe8, 0x2f, 0xfc, 0xff
+.data1 	0xff, 0x59, 0x59, 0x6a, 0x16, 0xe8, 0x7f, 0x02
+.data1 	0x00, 0x00, 0x59, 0xe9, 0xac, 0x00, 0x00, 0x00
+.data1 	0x81, 0x7d, 0xd4, 0x03, 0x07, 0x00, 0x00, 0x0f
+.data1 	0x85, 0x96, 0x00, 0x00, 0x00, 0x8b, 0x55, 0x08
+.data1 	0x4a, 0x83, 0xfa, 0x02, 0x7d, 0x16, 0x68, 0x90
+.data1 	0x01, 0x00, 0x00, 0xff, 0x36, 0xe8, 0xfe, 0xfb
+.data1 	0xff, 0xff, 0x59, 0x59, 0x6a, 0x16, 0xe8, 0x4e
+.data1 	0x02, 0x00, 0x00, 0x59, 0x8b, 0x56, 0x08, 0x89
+.data1 	0x15, 0xc8, 0x0d, 0x00, 0x00, 0x80, 0x3a, 0x2f
+.data1 	0x74, 0x16, 0x68, 0x6c, 0x01, 0x00, 0x00, 0xff
+.data1 	0x36, 0xe8, 0xda, 0xfb, 0xff, 0xff, 0x59, 0x59
+.data1 	0x6a, 0x16, 0xe8, 0x2a, 0x02, 0x00, 0x00, 0x59
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0xff, 0x76, 0x08, 0xe8
+.data1 	0x0c, 0x05, 0x00, 0x00, 0x59, 0x59, 0x3d, 0xff
+.data1 	0xff, 0xff, 0xff, 0x75, 0x1a, 0x68, 0x48, 0x01
+.data1 	0x00, 0x00, 0xff, 0x36, 0xe8, 0xaf, 0xfb, 0xff
+.data1 	0xff, 0x59, 0x59, 0xff, 0x35, 0xcc, 0x0a, 0x00
+.data1 	0x00, 0xe8, 0xfb, 0x01, 0x00, 0x00, 0x59, 0x0f
+.data1 	0xb7, 0x55, 0xe4, 0xf7, 0xc2, 0x00, 0x40, 0x00
+.data1 	0x00, 0x75, 0x21, 0x68, 0x30, 0x01, 0x00, 0x00
+.data1 	0xff, 0x36, 0xe8, 0x89, 0xfb, 0xff, 0xff, 0x59
+.data1 	0x59, 0x6a, 0x16, 0xe8, 0xd9, 0x01, 0x00, 0x00
+.data1 	0x59, 0xeb, 0x09, 0x81, 0x7d, 0xd4, 0x04, 0x07
+.data1 	0x00, 0x00, 0x75, 0x00, 0x8b, 0x45, 0xd4, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83, 0xec
+.data1 	0x28, 0x56, 0x57, 0xff, 0x75, 0x0c, 0xff, 0x75
+.data1 	0x08, 0xe8, 0x02, 0xfc, 0xff, 0xff, 0x59, 0x59
+.data1 	0x89, 0xc7, 0xe9, 0x3a, 0x01, 0x00, 0x00, 0xff
+.data1 	0x35, 0xc8, 0x0d, 0x00, 0x00, 0x68, 0xdc, 0x0d
+.data1 	0x00, 0x00, 0xe8, 0x01, 0x05, 0x00, 0x00, 0x59
+.data1 	0x59, 0x6a, 0x20, 0x68, 0xdc, 0x0d, 0x00, 0x00
+.data1 	0xff, 0x35, 0xc8, 0x0d, 0x00, 0x00, 0xe8, 0x0d
+.data1 	0x05, 0x00, 0x00, 0x59, 0x5a, 0x01, 0xc2, 0x59
+.data1 	0x88, 0x0a, 0xff, 0x35, 0xcc, 0x0d, 0x00, 0x00
+.data1 	0x68, 0xdc, 0x0d, 0x00, 0x00, 0xff, 0x35, 0xc8
+.data1 	0x0d, 0x00, 0x00, 0xe8, 0xf0, 0x04, 0x00, 0x00
+.data1 	0x59, 0x5a, 0x01, 0xc2, 0x83, 0xc2, 0x01, 0x52
+.data1 	0xe8, 0xc3, 0x04, 0x00, 0x00, 0x59, 0x59, 0xc7
+.data1 	0x45, 0xf0, 0xdc, 0x0d, 0x00, 0x00, 0x68, 0xdc
+.data1 	0x0d, 0x00, 0x00, 0xe8, 0xd0, 0x04, 0x00, 0x00
+.data1 	0x59, 0x89, 0x45, 0xe4, 0x8b, 0x15, 0xd0, 0x0d
+.data1 	0x00, 0x00, 0x89, 0x55, 0xec, 0x8b, 0x15, 0xd4
+.data1 	0x0d, 0x00, 0x00, 0x89, 0x55, 0xe8, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0x57, 0x6a, 0x02, 0xe8, 0xca, 0x00
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0xc6, 0x85
+.data1 	0xc0, 0x74, 0x07, 0x56, 0xe8, 0x3f, 0xfb, 0xff
+.data1 	0xff, 0x59, 0x8b, 0x55, 0xe0, 0x89, 0x55, 0xd8
+.data1 	0xe9, 0xa8, 0x00, 0x00, 0x00, 0x8b, 0x15, 0xc4
+.data1 	0x0d, 0x00, 0x00, 0x89, 0x55, 0xe4, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0x57, 0x6a, 0x02, 0xe8, 0x9a, 0x00
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x89, 0xc6, 0x85
+.data1 	0xc0, 0x0f, 0x84, 0x86, 0x00, 0x00, 0x00, 0x56
+.data1 	0xe8, 0x0b, 0xfb, 0xff, 0xff, 0x59, 0xe9, 0x7a
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x15, 0xc8, 0x0d, 0x00
+.data1 	0x00, 0x89, 0x55, 0xf0, 0xff, 0x35, 0xc8, 0x0d
+.data1 	0x00, 0x00, 0xe8, 0x51, 0x04, 0x00, 0x00, 0x59
+.data1 	0x89, 0x45, 0xe4, 0x8d, 0x45, 0xdc, 0x50, 0x57
+.data1 	0x6a, 0x02, 0xe8, 0x5d, 0x00, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x89, 0xc6, 0x85, 0xc0, 0x74, 0x4d
+.data1 	0x56, 0xe8, 0xd2, 0xfa, 0xff, 0xff, 0x59, 0xeb
+.data1 	0x44, 0x8d, 0x45, 0xdc, 0x50, 0x57, 0x6a, 0x02
+.data1 	0xe8, 0x3f, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x89, 0xc6, 0x85, 0xc0, 0x74, 0x2f, 0x56, 0xe8
+.data1 	0xb4, 0xfa, 0xff, 0xff, 0x59, 0xeb, 0x26, 0x8b
+.data1 	0x45, 0x0c, 0x68, 0x8c, 0x03, 0x00, 0x00, 0xff
+.data1 	0x30, 0xe8, 0x22, 0xfa, 0xff, 0xff, 0x59, 0x59
+.data1 	0xc7, 0x45, 0xd8, 0x63, 0x00, 0x00, 0x00, 0xeb
+.data1 	0x0c, 0xbb, 0x6c, 0x03, 0x00, 0x00, 0x89, 0xf8
+.data1 	0xe9, 0x4f, 0x17, 0x00, 0x00, 0x8b, 0x45, 0xd8
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x10, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x56, 0x04, 0x56, 0xff, 0x75, 0x08, 0xe8, 0x65
+.data1 	0x03, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc7, 0x85
+.data1 	0xff, 0x74, 0x04, 0x89, 0xf8, 0xeb, 0x03, 0x8b
+.data1 	0x46, 0x04, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x75, 0x08, 0x6a
+.data1 	0x0a, 0x6a, 0x00, 0x56, 0xe8, 0x67, 0x00, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x5e, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x35, 0xc0, 0x0a
+.data1 	0x00, 0x00, 0x4e, 0x78, 0x09, 0xff, 0x14, 0xb5
+.data1 	0xf0, 0x1d, 0x00, 0x00, 0xeb, 0xf4, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0xe8, 0xdf, 0xff, 0xff
+.data1 	0xff, 0x83, 0x3d, 0xc4, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x74, 0x06, 0xff, 0x15, 0xc4, 0x0a, 0x00, 0x00
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xc8, 0x02, 0x00, 0x00
+.data1 	0x59, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x75, 0x08, 0x85, 0xf6, 0x78, 0x08, 0x39
+.data1 	0x35, 0xac, 0x0d, 0x00, 0x00, 0x7f, 0x07, 0xb8
+.data1 	0xac, 0x03, 0x00, 0x00, 0xeb, 0x07, 0x8b, 0x04
+.data1 	0xb5, 0x7c, 0x0c, 0x00, 0x00, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x75, 0x08, 0x6a
+.data1 	0x01, 0xff, 0x75, 0x10, 0xff, 0x75, 0x0c, 0x56
+.data1 	0xe8, 0x21, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x8b
+.data1 	0x75, 0x08, 0x6a, 0x00, 0xff, 0x75, 0x10, 0xff
+.data1 	0x75, 0x0c, 0x56, 0xe8, 0x06, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x10, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x1c, 0x56, 0x57, 0x8b, 0x75
+.data1 	0x08, 0xc7, 0x45, 0xf8, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x45, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xec, 0x01, 0x00, 0x00, 0x00, 0x89, 0x75
+.data1 	0xe8, 0x83, 0x7d, 0x0c, 0x00, 0x74, 0x05, 0x8b
+.data1 	0x45, 0x0c, 0x89, 0x30, 0x0f, 0xbe, 0x06, 0xf6
+.data1 	0x80, 0x69, 0x0b, 0x00, 0x00, 0x08, 0x74, 0x03
+.data1 	0x46, 0xeb, 0xf1, 0x0f, 0xbe, 0x06, 0x89, 0xc7
+.data1 	0x83, 0xff, 0x2d, 0x74, 0x05, 0x83, 0xff, 0x2b
+.data1 	0x75, 0x0d, 0x83, 0xff, 0x2d, 0x75, 0x07, 0xc7
+.data1 	0x45, 0xec, 0xff, 0xff, 0xff, 0xff, 0x46, 0x89
+.data1 	0x75, 0xe4, 0x83, 0x7d, 0x10, 0x00, 0x75, 0x2c
+.data1 	0x80, 0x3e, 0x30, 0x75, 0x1e, 0x46, 0x80, 0x3e
+.data1 	0x78, 0x74, 0x05, 0x80, 0x3e, 0x58, 0x75, 0x0a
+.data1 	0xc7, 0x45, 0x10, 0x10, 0x00, 0x00, 0x00, 0x46
+.data1 	0xeb, 0x29, 0xc7, 0x45, 0x10, 0x08, 0x00, 0x00
+.data1 	0x00, 0xeb, 0x20, 0xc7, 0x45, 0x10, 0x0a, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x17, 0x83, 0x7d, 0x10, 0x10
+.data1 	0x75, 0x11, 0x80, 0x3e, 0x30, 0x75, 0x0c, 0x46
+.data1 	0x80, 0x3e, 0x78, 0x74, 0x05, 0x80, 0x3e, 0x58
+.data1 	0x75, 0x01, 0x46, 0x0f, 0xbe, 0x06, 0x89, 0xc7
+.data1 	0x89, 0xfa, 0x83, 0xea, 0x30, 0x83, 0xfa, 0x09
+.data1 	0x77, 0x0a, 0x89, 0xfa, 0x83, 0xea, 0x30, 0x89
+.data1 	0x55, 0xfc, 0xeb, 0x26, 0x89, 0xfa, 0x83, 0xea
+.data1 	0x61, 0x83, 0xfa, 0x19, 0x77, 0x0a, 0x89, 0xfa
+.data1 	0x83, 0xea, 0x57, 0x89, 0x55, 0xfc, 0xeb, 0x12
+.data1 	0x89, 0xfa, 0x83, 0xea, 0x41, 0x83, 0xfa, 0x19
+.data1 	0x77, 0x37, 0x89, 0xfa, 0x83, 0xea, 0x37, 0x89
+.data1 	0x55, 0xfc, 0x8b, 0x55, 0xfc, 0x39, 0x55, 0x10
+.data1 	0x76, 0x27, 0xba, 0xff, 0xff, 0xff, 0xff, 0x2b
+.data1 	0x55, 0xfc, 0x89, 0xd0, 0x31, 0xd2, 0xf7, 0x75
+.data1 	0x10, 0x39, 0x45, 0xf8, 0x76, 0x03, 0xff, 0x45
+.data1 	0xf0, 0x8b, 0x55, 0x10, 0x0f, 0xaf, 0x55, 0xf8
+.data1 	0x03, 0x55, 0xfc, 0x89, 0x55, 0xf8, 0x46, 0xeb
+.data1 	0x92, 0x83, 0x7d, 0x0c, 0x00, 0x74, 0x14, 0x39
+.data1 	0x75, 0xe4, 0x75, 0x0a, 0x8b, 0x55, 0xe8, 0x8b
+.data1 	0x45, 0x0c, 0x89, 0x10, 0xeb, 0x05, 0x8b, 0x45
+.data1 	0x0c, 0x89, 0x30, 0x83, 0x7d, 0xf0, 0x00, 0x75
+.data1 	0x27, 0x83, 0x7d, 0x14, 0x00, 0x74, 0x21, 0x83
+.data1 	0x7d, 0xec, 0x00, 0x79, 0x09, 0x81, 0x7d, 0xf8
+.data1 	0x00, 0x00, 0x00, 0x80, 0x77, 0x0f, 0x83, 0x7d
+.data1 	0xec, 0x00, 0x7e, 0x0c, 0x81, 0x7d, 0xf8, 0xff
+.data1 	0xff, 0xff, 0x7f, 0x76, 0x03, 0xff, 0x45, 0xf0
+.data1 	0x83, 0x7d, 0xf0, 0x00, 0x74, 0x2b, 0xc7, 0x05
+.data1 	0xcc, 0x0a, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00
+.data1 	0x83, 0x7d, 0x14, 0x00, 0x74, 0x14, 0x83, 0x7d
+.data1 	0xec, 0x00, 0x79, 0x07, 0xb8, 0x00, 0x00, 0x00
+.data1 	0x80, 0xeb, 0x17, 0xb8, 0xff, 0xff, 0xff, 0x7f
+.data1 	0xeb, 0x10, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x09, 0x8b, 0x55, 0xec, 0x0f, 0xaf, 0x55, 0xf8
+.data1 	0x89, 0xd0, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x8d, 0x55
+.data1 	0x10, 0x89, 0x55, 0xfc, 0xff, 0x75, 0x08, 0xff
+.data1 	0x75, 0xfc, 0xff, 0x75, 0x0c, 0xe8, 0xf0, 0x03
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0xff, 0x35, 0xcc
+.data1 	0x0a, 0x00, 0x00, 0xe8, 0xdc, 0xfd, 0xff, 0xff
+.data1 	0x59, 0x89, 0xc7, 0x8b, 0x35, 0x04, 0x0b, 0x00
+.data1 	0x00, 0x68, 0xe8, 0x0a, 0x00, 0x00, 0xe8, 0x05
+.data1 	0x0a, 0x00, 0x00, 0x59, 0x68, 0x00, 0x0b, 0x00
+.data1 	0x00, 0xe8, 0xfa, 0x09, 0x00, 0x00, 0x59, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x74, 0x2e, 0x8b, 0x55, 0x08
+.data1 	0x80, 0x3a, 0x00, 0x74, 0x26, 0xff, 0x75, 0x08
+.data1 	0xe8, 0x0b, 0x01, 0x00, 0x00, 0x59, 0x50, 0xff
+.data1 	0x75, 0x08, 0x56, 0xe8, 0x70, 0x01, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x6a, 0x02, 0x68, 0xc0, 0x03
+.data1 	0x00, 0x00, 0x56, 0xe8, 0x60, 0x01, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x57, 0xe8, 0xe7, 0x00, 0x00
+.data1 	0x00, 0x59, 0x50, 0x57, 0x56, 0xe8, 0x4e, 0x01
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x6a, 0x01, 0x68
+.data1 	0xbc, 0x03, 0x00, 0x00, 0x56, 0xe8, 0x3e, 0x01
+.data1 	0x00, 0x00, 0x83, 0xc4, 0x0c, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x08, 0x8d, 0x55, 0x0c, 0x89, 0x55, 0xfc
+.data1 	0x68, 0xe8, 0x0a, 0x00, 0x00, 0xff, 0x75, 0xfc
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x42, 0x03, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x01, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x02
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x03, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0xb9, 0x04, 0x00, 0x00, 0x00
+.data1 	0xcd, 0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0x53, 0x8b, 0x5d, 0x08, 0xb9, 0x08, 0x00, 0x00
+.data1 	0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3, 0x00, 0x00
+.data1 	0xb9, 0xff, 0xff, 0xff, 0xff, 0xe9, 0xe2, 0x0d
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0xb9, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe8, 0xfd, 0x0d, 0x00, 0x00, 0x8b
+.data1 	0x45, 0x08, 0x5f, 0x5e, 0x5d, 0xc3, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb9, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x02, 0x0e
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe0, 0x8d, 0x45, 0xd8, 0x50
+.data1 	0x6a, 0x01, 0x6a, 0x00, 0xe8, 0xdb, 0x11, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0xba, 0xff, 0xff, 0xff
+.data1 	0xff, 0x89, 0x55, 0xfc, 0xff, 0xd2, 0xeb, 0xfe
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0xff, 0x75
+.data1 	0x08, 0xe8, 0xba, 0xff, 0xff, 0xff, 0x59, 0x05
+.data1 	0x01, 0x00, 0x00, 0x00, 0x89, 0x45, 0xe4, 0x8b
+.data1 	0x55, 0x08, 0x89, 0x55, 0xf0, 0x8b, 0x55, 0x0c
+.data1 	0x89, 0x55, 0xf4, 0x8d, 0x45, 0xdc, 0x50, 0x6a
+.data1 	0x12, 0x6a, 0x01, 0xe8, 0x9c, 0x11, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x10, 0x89
+.data1 	0x55, 0xe8, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf0
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x04, 0x6a, 0x01
+.data1 	0xe8, 0x6f, 0x11, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x08, 0x56, 0x57, 0x8b, 0x75, 0x08, 0x80
+.data1 	0x3e, 0x2a, 0x75, 0x18, 0x8b, 0x45, 0x10, 0x8b
+.data1 	0x10, 0x83, 0xc2, 0x04, 0x8b, 0x45, 0x10, 0x89
+.data1 	0x10, 0x8b, 0x52, 0xfc, 0x8b, 0x45, 0x0c, 0x89
+.data1 	0x10, 0x46, 0xeb, 0x25, 0x31, 0xff, 0x0f, 0xbe
+.data1 	0x06, 0x2d, 0x30, 0x00, 0x00, 0x00, 0x89, 0x45
+.data1 	0xf8, 0x78, 0x11, 0x83, 0x7d, 0xf8, 0x09, 0x7f
+.data1 	0x0b, 0x6b, 0xdf, 0x0a, 0x8b, 0x7d, 0xf8, 0x01
+.data1 	0xdf, 0x46, 0xeb, 0xe2, 0x8b, 0x45, 0x0c, 0x89
+.data1 	0x38, 0x89, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x10, 0x56, 0x57, 0x8b
+.data1 	0x75, 0x10, 0x8b, 0x7d, 0x08, 0x89, 0x75, 0xf4
+.data1 	0xe9, 0x80, 0x00, 0x00, 0x00, 0x83, 0x7d, 0x1c
+.data1 	0x00, 0x74, 0x18, 0x8b, 0x17, 0x83, 0xc2, 0x04
+.data1 	0x89, 0x17, 0x8b, 0x42, 0xfc, 0x0f, 0xbf, 0xc0
+.data1 	0x0f, 0xbf, 0xc0, 0x89, 0x45, 0xfc, 0xe9, 0x76
+.data1 	0x00, 0x00, 0x00, 0x8b, 0x17, 0x83, 0xc2, 0x04
+.data1 	0x89, 0x17, 0xb9, 0xff, 0xff, 0x00, 0x00, 0x23
+.data1 	0x4a, 0xfc, 0x89, 0x4d, 0xf8, 0xe9, 0x5f, 0x00
+.data1 	0x00, 0x00, 0x83, 0x7d, 0x1c, 0x00, 0x74, 0x12
+.data1 	0x8b, 0x17, 0x83, 0xc2, 0x04, 0x89, 0x17, 0x8b
+.data1 	0x52, 0xfc, 0x89, 0x55, 0xfc, 0xe9, 0x47, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x17, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x17, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0xf8, 0xeb
+.data1 	0x38, 0x83, 0x7d, 0x1c, 0x00, 0x74, 0x0f, 0x8b
+.data1 	0x17, 0x83, 0xc2, 0x04, 0x89, 0x17, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0xfc, 0xeb, 0x23, 0x8b, 0x17
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x17, 0x8b, 0x52, 0xfc
+.data1 	0x89, 0x55, 0xf8, 0xeb, 0x14, 0xba, 0x60, 0x00
+.data1 	0x00, 0x00, 0x23, 0x55, 0x0c, 0xbb, 0x3c, 0x09
+.data1 	0x00, 0x00, 0x89, 0xd0, 0xe9, 0xf7, 0x11, 0x00
+.data1 	0x00, 0x83, 0x7d, 0x1c, 0x00, 0x74, 0x2f, 0x83
+.data1 	0x7d, 0xfc, 0x00, 0x79, 0x09, 0xc6, 0x06, 0x2d
+.data1 	0x46, 0xf7, 0x5d, 0xfc, 0xeb, 0x1a, 0x8b, 0x55
+.data1 	0x0c, 0xf6, 0xc2, 0x02, 0x74, 0x06, 0xc6, 0x06
+.data1 	0x2b, 0x46, 0xeb, 0x0c, 0x8b, 0x55, 0x0c, 0xf6
+.data1 	0xc2, 0x04, 0x74, 0x04, 0xc6, 0x06, 0x20, 0x46
+.data1 	0x8b, 0x55, 0xfc, 0x89, 0x55, 0xf8, 0x8b, 0x55
+.data1 	0x0c, 0xf6, 0xc2, 0x08, 0x74, 0x0a, 0x80, 0x7d
+.data1 	0x14, 0x6f, 0x75, 0x04, 0xc6, 0x06, 0x30, 0x46
+.data1 	0x83, 0x7d, 0xf8, 0x00, 0x75, 0x11, 0x83, 0x7d
+.data1 	0x18, 0x00, 0x0f, 0x85, 0x60, 0x00, 0x00, 0x00
+.data1 	0x89, 0xf0, 0xe9, 0x9f, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x0c, 0xf6, 0xc2, 0x08, 0x74, 0x0c, 0x80
+.data1 	0x7d, 0x14, 0x78, 0x74, 0x0c, 0x80, 0x7d, 0x14
+.data1 	0x58, 0x74, 0x06, 0x80, 0x7d, 0x14, 0x70, 0x75
+.data1 	0x3f, 0xc6, 0x06, 0x30, 0x46, 0x80, 0x7d, 0x14
+.data1 	0x58, 0x75, 0x07, 0xb8, 0x58, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x05, 0xb8, 0x78, 0x00, 0x00, 0x00, 0x88
+.data1 	0x06, 0x46, 0xeb, 0x24, 0xc7, 0x45, 0xf0, 0x02
+.data1 	0x00, 0x00, 0x00, 0xeb, 0x29, 0xc7, 0x45, 0xf0
+.data1 	0x08, 0x00, 0x00, 0x00, 0xeb, 0x20, 0xc7, 0x45
+.data1 	0xf0, 0x0a, 0x00, 0x00, 0x00, 0xeb, 0x17, 0xc7
+.data1 	0x45, 0xf0, 0x10, 0x00, 0x00, 0x00, 0xeb, 0x0e
+.data1 	0x0f, 0xbe, 0x45, 0x14, 0xbb, 0x54, 0x09, 0x00
+.data1 	0x00, 0xe9, 0x32, 0x11, 0x00, 0x00, 0xff, 0x75
+.data1 	0x18, 0x56, 0xff, 0x75, 0xf0, 0xff, 0x75, 0xf8
+.data1 	0xe8, 0xf7, 0x0a, 0x00, 0x00, 0x83, 0xc4, 0x10
+.data1 	0x89, 0xc6, 0x80, 0x7d, 0x14, 0x58, 0x75, 0x1c
+.data1 	0x39, 0x75, 0xf4, 0x74, 0x17, 0x8b, 0x55, 0xf4
+.data1 	0x0f, 0xbe, 0x02, 0x50, 0xe8, 0xd3, 0x0e, 0x00
+.data1 	0x00, 0x59, 0x8b, 0x55, 0xf4, 0x88, 0x02, 0xff
+.data1 	0x45, 0xf4, 0xeb, 0xe4, 0x89, 0xf0, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x81, 0xec, 0x34
+.data1 	0x04, 0x00, 0x00, 0x56, 0x57, 0x8b, 0x75, 0x10
+.data1 	0xc7, 0x45, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x45, 0x08, 0xff, 0x45, 0x08, 0x0f, 0xbe, 0x00
+.data1 	0x89, 0x45, 0xf0, 0x85, 0xc0, 0x0f, 0x84, 0x0b
+.data1 	0x06, 0x00, 0x00, 0x83, 0x7d, 0xf0, 0x25, 0x0f
+.data1 	0x84, 0x4d, 0x00, 0x00, 0x00, 0x8b, 0x16, 0x4a
+.data1 	0x89, 0x16, 0x78, 0x13, 0x8b, 0x55, 0xf0, 0x0f
+.data1 	0xb6, 0xca, 0x8b, 0x46, 0x14, 0x83, 0x46, 0x14
+.data1 	0x01, 0x88, 0x08, 0x89, 0xc8, 0xeb, 0x0b, 0x56
+.data1 	0xff, 0x75, 0xf0, 0xe8, 0xf0, 0x07, 0x00, 0x00
+.data1 	0x59, 0x59, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x1c, 0x83, 0x7d, 0xd8, 0x00, 0x74, 0x0c, 0x8b
+.data1 	0x55, 0xd8, 0xf7, 0xda, 0x89, 0xd0, 0xe9, 0xc6
+.data1 	0x05, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xe9, 0xbc, 0x05, 0x00, 0x00, 0xff, 0x45, 0xd8
+.data1 	0xeb, 0x95, 0x31, 0xff, 0xeb, 0x21, 0x83, 0xcf
+.data1 	0x01, 0xeb, 0x2c, 0x83, 0xcf, 0x02, 0xeb, 0x27
+.data1 	0x83, 0xcf, 0x04, 0xeb, 0x22, 0x83, 0xcf, 0x08
+.data1 	0xeb, 0x1d, 0x83, 0xcf, 0x10, 0xeb, 0x18, 0x81
+.data1 	0xcf, 0x00, 0x10, 0x00, 0x00, 0xeb, 0x13, 0x8b
+.data1 	0x55, 0x08, 0x0f, 0xbe, 0x02, 0xbb, 0x9c, 0x09
+.data1 	0x00, 0x00, 0xe9, 0x41, 0x10, 0x00, 0x00, 0xff
+.data1 	0x45, 0x08, 0xf7, 0xc7, 0x00, 0x10, 0x00, 0x00
+.data1 	0x74, 0xe5, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xd4
+.data1 	0x8d, 0x45, 0x0c, 0x50, 0x8d, 0x45, 0xec, 0x50
+.data1 	0xff, 0x75, 0x08, 0xe8, 0x2c, 0xfd, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0x45, 0x08, 0x39, 0x45
+.data1 	0xd4, 0x74, 0x06, 0x81, 0xcf, 0x00, 0x01, 0x00
+.data1 	0x00, 0x8b, 0x55, 0x08, 0x80, 0x3a, 0x2e, 0x75
+.data1 	0x2b, 0xff, 0x45, 0x08, 0x8b, 0x55, 0x08, 0x89
+.data1 	0x55, 0xd4, 0x8d, 0x45, 0x0c, 0x50, 0x8d, 0x45
+.data1 	0xe8, 0x50, 0xff, 0x75, 0x08, 0xe8, 0xfa, 0xfc
+.data1 	0xff, 0xff, 0x83, 0xc4, 0x0c, 0x89, 0x45, 0x08
+.data1 	0x83, 0x7d, 0xe8, 0x00, 0x78, 0x06, 0x81, 0xcf
+.data1 	0x00, 0x02, 0x00, 0x00, 0xf7, 0xc7, 0x00, 0x01
+.data1 	0x00, 0x00, 0x74, 0x0c, 0x83, 0x7d, 0xec, 0x00
+.data1 	0x79, 0x06, 0xf7, 0x5d, 0xec, 0x83, 0xcf, 0x01
+.data1 	0xf7, 0xc7, 0x00, 0x01, 0x00, 0x00, 0x75, 0x07
+.data1 	0xc7, 0x45, 0xec, 0x00, 0x00, 0x00, 0x00, 0xf7
+.data1 	0xc7, 0x02, 0x00, 0x00, 0x00, 0x74, 0x03, 0x83
+.data1 	0xe7, 0xfb, 0xf7, 0xc7, 0x01, 0x00, 0x00, 0x00
+.data1 	0x74, 0x03, 0x83, 0xe7, 0xef, 0x8d, 0x95, 0xcf
+.data1 	0xfb, 0xff, 0xff, 0x89, 0x55, 0xd0, 0x89, 0x55
+.data1 	0xfc, 0xeb, 0x24, 0x83, 0xcf, 0x20, 0xff, 0x45
+.data1 	0x08, 0xe9, 0x23, 0x02, 0x00, 0x00, 0x83, 0xcf
+.data1 	0x40, 0xff, 0x45, 0x08, 0xe9, 0x18, 0x02, 0x00
+.data1 	0x00, 0x81, 0xcf, 0x80, 0x00, 0x00, 0x00, 0xff
+.data1 	0x45, 0x08, 0xe9, 0x0a, 0x02, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x08, 0x0f, 0xbe, 0x02, 0xbb, 0xcc, 0x09
+.data1 	0x00, 0x00, 0xe9, 0x61, 0x0f, 0x00, 0x00, 0x8b
+.data1 	0x16, 0x4a, 0x89, 0x16, 0x78, 0x13, 0x8b, 0x55
+.data1 	0xf0, 0x0f, 0xb6, 0xca, 0x8b, 0x46, 0x14, 0x83
+.data1 	0x46, 0x14, 0x01, 0x88, 0x08, 0x89, 0xc8, 0xeb
+.data1 	0x0b, 0x56, 0xff, 0x75, 0xf0, 0xe8, 0x8e, 0x06
+.data1 	0x00, 0x00, 0x59, 0x59, 0x3d, 0xff, 0xff, 0xff
+.data1 	0xff, 0x75, 0x1c, 0x83, 0x7d, 0xd8, 0x00, 0x74
+.data1 	0x0c, 0x8b, 0x55, 0xd8, 0xf7, 0xda, 0x89, 0xd0
+.data1 	0xe9, 0x64, 0x04, 0x00, 0x00, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe9, 0x5a, 0x04, 0x00, 0x00, 0xff
+.data1 	0x45, 0xd8, 0xe9, 0x30, 0xfe, 0xff, 0xff, 0xf7
+.data1 	0xc7, 0x20, 0x00, 0x00, 0x00, 0x74, 0x1a, 0x8b
+.data1 	0x45, 0xd8, 0x0f, 0xbf, 0xc0, 0x8b, 0x55, 0x0c
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c, 0x8b, 0x52
+.data1 	0xfc, 0x66, 0x89, 0x02, 0xe9, 0x0e, 0xfe, 0xff
+.data1 	0xff, 0xf7, 0xc7, 0x40, 0x00, 0x00, 0x00, 0x74
+.data1 	0x16, 0x8b, 0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x8b, 0x4d, 0xd8
+.data1 	0x89, 0x0a, 0xe9, 0xf0, 0xfd, 0xff, 0xff, 0x8b
+.data1 	0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c
+.data1 	0x8b, 0x52, 0xfc, 0x8b, 0x4d, 0xd8, 0x89, 0x0a
+.data1 	0xe9, 0xda, 0xfd, 0xff, 0xff, 0x8b, 0x55, 0x0c
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0xd0, 0x85, 0xd2, 0x75, 0x07
+.data1 	0xc7, 0x45, 0xd0, 0x7c, 0x0a, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xd0, 0x89, 0x55, 0xfc, 0x83, 0x7d, 0xe8
+.data1 	0x00, 0x75, 0x0c, 0xf7, 0xc7, 0x00, 0x02, 0x00
+.data1 	0x00, 0x0f, 0x85, 0x38, 0x01, 0x00, 0x00, 0x8b
+.data1 	0x55, 0xfc, 0x80, 0x3a, 0x00, 0x0f, 0x84, 0x2c
+.data1 	0x01, 0x00, 0x00, 0xff, 0x45, 0xfc, 0xff, 0x4d
+.data1 	0xe8, 0xeb, 0xda, 0xf7, 0xc7, 0x00, 0x02, 0x00
+.data1 	0x00, 0x75, 0x09, 0xc7, 0x45, 0xe8, 0x01, 0x00
+.data1 	0x00, 0x00, 0xeb, 0x09, 0x83, 0x7d, 0xf0, 0x70
+.data1 	0x74, 0x03, 0x83, 0xe7, 0xef, 0x8b, 0x45, 0xf0
+.data1 	0x0f, 0xbe, 0xc0, 0x6a, 0x00, 0xff, 0x75, 0xe8
+.data1 	0x50, 0xff, 0x75, 0xfc, 0x57, 0x8d, 0x45, 0x0c
+.data1 	0x50, 0xe8, 0xa1, 0xfb, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x18, 0x89, 0x45, 0xfc, 0xe9, 0xe6, 0x00, 0x00
+.data1 	0x00, 0x81, 0xcf, 0x00, 0x04, 0x00, 0x00, 0xf7
+.data1 	0xc7, 0x00, 0x02, 0x00, 0x00, 0x75, 0x09, 0xc7
+.data1 	0x45, 0xe8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x03
+.data1 	0x83, 0xe7, 0xef, 0x8b, 0x45, 0xf0, 0x0f, 0xbe
+.data1 	0xc0, 0x6a, 0x01, 0xff, 0x75, 0xe8, 0x50, 0xff
+.data1 	0x75, 0xfc, 0x57, 0x8d, 0x45, 0x0c, 0x50, 0xe8
+.data1 	0x63, 0xfb, 0xff, 0xff, 0x83, 0xc4, 0x18, 0x89
+.data1 	0x45, 0xfc, 0xe9, 0xa8, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c
+.data1 	0x8b, 0x4d, 0xfc, 0x8b, 0x52, 0xfc, 0x88, 0x11
+.data1 	0xff, 0x45, 0xfc, 0xe9, 0x8f, 0x00, 0x00, 0x00
+.data1 	0xf7, 0xc7, 0x00, 0x02, 0x00, 0x00, 0x74, 0x0d
+.data1 	0x83, 0x7d, 0xe8, 0x00, 0x75, 0x07, 0xc7, 0x45
+.data1 	0xe8, 0x01, 0x00, 0x00, 0x00, 0xf7, 0xc7, 0x00
+.data1 	0x02, 0x00, 0x00, 0x75, 0x07, 0xc7, 0x45, 0xe8
+.data1 	0x06, 0x00, 0x00, 0x00, 0x81, 0x7d, 0xe8, 0x01
+.data1 	0x04, 0x00, 0x00, 0x72, 0x07, 0xc7, 0x45, 0xe8
+.data1 	0x00, 0x04, 0x00, 0x00, 0x81, 0xcf, 0x00, 0x04
+.data1 	0x00, 0x00, 0x8b, 0x45, 0xf0, 0x0f, 0xbe, 0xc0
+.data1 	0xff, 0x75, 0xe8, 0x50, 0xff, 0x75, 0xfc, 0x57
+.data1 	0x8d, 0x45, 0x0c, 0x50, 0xe8, 0x2b, 0x08, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x14, 0x89, 0x45, 0xfc, 0xeb
+.data1 	0x36, 0x8b, 0x55, 0x0c, 0x83, 0xc2, 0x04, 0x89
+.data1 	0x55, 0x0c, 0x8b, 0x52, 0xfc, 0x89, 0x55, 0x0c
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0x0c, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0x08, 0xe9, 0x86, 0xfc, 0xff
+.data1 	0xff, 0x8b, 0x45, 0x08, 0xff, 0x45, 0x08, 0x0f
+.data1 	0xbe, 0x00, 0x89, 0x45, 0xf0, 0xbb, 0xec, 0x09
+.data1 	0x00, 0x00, 0xe9, 0x51, 0x0d, 0x00, 0x00, 0xc7
+.data1 	0x45, 0xe4, 0x20, 0x00, 0x00, 0x00, 0xf7, 0xc7
+.data1 	0x10, 0x00, 0x00, 0x00, 0x74, 0x07, 0xc7, 0x45
+.data1 	0xe4, 0x30, 0x00, 0x00, 0x00, 0x8b, 0x55, 0xfc
+.data1 	0x2b, 0x55, 0xd0, 0x89, 0x55, 0xf8, 0xc7, 0x45
+.data1 	0xdc, 0x00, 0x00, 0x00, 0x00, 0xf7, 0xc7, 0x10
+.data1 	0x00, 0x00, 0x00, 0x74, 0x37, 0x83, 0x7d, 0xf0
+.data1 	0x78, 0x74, 0x06, 0x83, 0x7d, 0xf0, 0x58, 0x75
+.data1 	0x08, 0xf7, 0xc7, 0x08, 0x00, 0x00, 0x00, 0x75
+.data1 	0x20, 0x83, 0x7d, 0xf0, 0x70, 0x74, 0x1a, 0xf7
+.data1 	0xc7, 0x00, 0x04, 0x00, 0x00, 0x74, 0x15, 0x8b
+.data1 	0x55, 0xd0, 0x80, 0x3a, 0x2b, 0x74, 0x0a, 0x80
+.data1 	0x3a, 0x2d, 0x74, 0x05, 0x80, 0x3a, 0x20, 0x75
+.data1 	0x03, 0xff, 0x45, 0xdc, 0x8b, 0x55, 0xec, 0x2b
+.data1 	0x55, 0xf8, 0x89, 0x55, 0xf4, 0x85, 0xd2, 0x0f
+.data1 	0x8e, 0x61, 0x01, 0x00, 0x00, 0xf7, 0xc7, 0x01
+.data1 	0x00, 0x00, 0x00, 0x0f, 0x85, 0x55, 0x01, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xf4, 0x01, 0x55, 0xd8, 0x83
+.data1 	0x7d, 0xdc, 0x00, 0x0f, 0x84, 0xf8, 0x00, 0x00
+.data1 	0x00, 0xf7, 0xc7, 0x00, 0x04, 0x00, 0x00, 0x0f
+.data1 	0x84, 0x5c, 0x00, 0x00, 0x00, 0xff, 0x4d, 0xf8
+.data1 	0xff, 0x45, 0xd8, 0x8b, 0x16, 0x4a, 0x89, 0x16
+.data1 	0x78, 0x16, 0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0
+.data1 	0x0f, 0xb6, 0x10, 0x8b, 0x46, 0x14, 0x83, 0x46
+.data1 	0x14, 0x01, 0x88, 0x10, 0x89, 0xd0, 0xeb, 0x12
+.data1 	0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xbe
+.data1 	0x00, 0x56, 0x50, 0xe8, 0xd0, 0x03, 0x00, 0x00
+.data1 	0x59, 0x59, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x0f
+.data1 	0x85, 0xac, 0x00, 0x00, 0x00, 0x83, 0x7d, 0xd8
+.data1 	0x00, 0x74, 0x0c, 0x8b, 0x55, 0xd8, 0xf7, 0xda
+.data1 	0x89, 0xd0, 0xe9, 0xa2, 0x01, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe9, 0x98, 0x01, 0x00
+.data1 	0x00, 0x83, 0x6d, 0xf8, 0x02, 0x83, 0x45, 0xd8
+.data1 	0x02, 0x8b, 0x16, 0x4a, 0x89, 0x16, 0x78, 0x16
+.data1 	0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xb6
+.data1 	0x10, 0x8b, 0x46, 0x14, 0x83, 0x46, 0x14, 0x01
+.data1 	0x88, 0x10, 0x89, 0xd0, 0xeb, 0x12, 0x8b, 0x45
+.data1 	0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xbe, 0x00, 0x56
+.data1 	0x50, 0xe8, 0x72, 0x03, 0x00, 0x00, 0x59, 0x59
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x74, 0x36, 0x8b
+.data1 	0x16, 0x4a, 0x89, 0x16, 0x78, 0x16, 0x8b, 0x45
+.data1 	0xd0, 0xff, 0x45, 0xd0, 0x0f, 0xb6, 0x10, 0x8b
+.data1 	0x46, 0x14, 0x83, 0x46, 0x14, 0x01, 0x88, 0x10
+.data1 	0x89, 0xd0, 0xeb, 0x12, 0x8b, 0x45, 0xd0, 0xff
+.data1 	0x45, 0xd0, 0x0f, 0xbe, 0x00, 0x56, 0x50, 0xe8
+.data1 	0x3c, 0x03, 0x00, 0x00, 0x59, 0x59, 0x3d, 0xff
+.data1 	0xff, 0xff, 0xff, 0x75, 0x1c, 0x83, 0x7d, 0xd8
+.data1 	0x00, 0x74, 0x0c, 0x8b, 0x55, 0xd8, 0xf7, 0xda
+.data1 	0x89, 0xd0, 0xe9, 0x12, 0x01, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe9, 0x08, 0x01, 0x00
+.data1 	0x00, 0x8b, 0x16, 0x4a, 0x89, 0x16, 0x78, 0x13
+.data1 	0x8b, 0x55, 0xe4, 0x0f, 0xb6, 0xca, 0x8b, 0x46
+.data1 	0x14, 0x83, 0x46, 0x14, 0x01, 0x88, 0x08, 0x89
+.data1 	0xc8, 0xeb, 0x0b, 0x56, 0xff, 0x75, 0xe4, 0xe8
+.data1 	0xf4, 0x02, 0x00, 0x00, 0x59, 0x59, 0x3d, 0xff
+.data1 	0xff, 0xff, 0xff, 0x75, 0x1c, 0x83, 0x7d, 0xd8
+.data1 	0x00, 0x74, 0x0c, 0x8b, 0x55, 0xd8, 0xf7, 0xda
+.data1 	0x89, 0xd0, 0xe9, 0xca, 0x00, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe9, 0xc0, 0x00, 0x00
+.data1 	0x00, 0xff, 0x4d, 0xf4, 0x75, 0xb3, 0x8b, 0x55
+.data1 	0xf8, 0x01, 0x55, 0xd8, 0xff, 0x4d, 0xf8, 0x0f
+.data1 	0x88, 0x52, 0x00, 0x00, 0x00, 0x8b, 0x16, 0x4a
+.data1 	0x89, 0x16, 0x78, 0x16, 0x8b, 0x45, 0xd0, 0xff
+.data1 	0x45, 0xd0, 0x0f, 0xb6, 0x10, 0x8b, 0x46, 0x14
+.data1 	0x83, 0x46, 0x14, 0x01, 0x88, 0x10, 0x89, 0xd0
+.data1 	0xeb, 0x12, 0x8b, 0x45, 0xd0, 0xff, 0x45, 0xd0
+.data1 	0x0f, 0xbe, 0x00, 0x56, 0x50, 0xe8, 0x8e, 0x02
+.data1 	0x00, 0x00, 0x59, 0x59, 0x3d, 0xff, 0xff, 0xff
+.data1 	0xff, 0x75, 0xc1, 0x83, 0x7d, 0xd8, 0x00, 0x74
+.data1 	0x0c, 0x8b, 0x55, 0xd8, 0xf7, 0xda, 0x89, 0xd0
+.data1 	0xe9, 0x64, 0x00, 0x00, 0x00, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe9, 0x5a, 0x00, 0x00, 0x00, 0x83
+.data1 	0x7d, 0xf4, 0x00, 0x7e, 0x06, 0x8b, 0x55, 0xf4
+.data1 	0x01, 0x55, 0xd8, 0xff, 0x4d, 0xf4, 0x0f, 0x88
+.data1 	0x23, 0xfa, 0xff, 0xff, 0x8b, 0x16, 0x4a, 0x89
+.data1 	0x16, 0x78, 0x13, 0x8b, 0x55, 0xe4, 0x0f, 0xb6
+.data1 	0xca, 0x8b, 0x46, 0x14, 0x83, 0x46, 0x14, 0x01
+.data1 	0x88, 0x08, 0x89, 0xc8, 0xeb, 0x0b, 0x56, 0xff
+.data1 	0x75, 0xe4, 0xe8, 0x31, 0x02, 0x00, 0x00, 0x59
+.data1 	0x59, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0xcb
+.data1 	0x83, 0x7d, 0xd8, 0x00, 0x74, 0x09, 0x8b, 0x55
+.data1 	0xd8, 0xf7, 0xda, 0x89, 0xd0, 0xeb, 0x0a, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x03, 0x8b, 0x45
+.data1 	0xd8, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x14, 0x56, 0x57
+.data1 	0x8b, 0x75, 0x08, 0xc7, 0x45, 0xf0, 0x00, 0x00
+.data1 	0x00, 0x00, 0x85, 0xf6, 0x75, 0x34, 0x31, 0xff
+.data1 	0x83, 0xff, 0x14, 0x7d, 0x25, 0x83, 0x3c, 0xbd
+.data1 	0x18, 0x0b, 0x00, 0x00, 0x00, 0x74, 0x18, 0xff
+.data1 	0x34, 0xbd, 0x18, 0x0b, 0x00, 0x00, 0xe8, 0xcd
+.data1 	0xff, 0xff, 0xff, 0x59, 0x85, 0xc0, 0x74, 0x07
+.data1 	0xc7, 0x45, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x47
+.data1 	0xeb, 0xd6, 0x8b, 0x45, 0xf0, 0xe9, 0x43, 0x01
+.data1 	0x00, 0x00, 0x83, 0x7e, 0x10, 0x00, 0x74, 0x11
+.data1 	0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x80, 0x75, 0x10
+.data1 	0xf7, 0x46, 0x08, 0x00, 0x01, 0x00, 0x00, 0x75
+.data1 	0x07, 0x31, 0xc0, 0xe9, 0x25, 0x01, 0x00, 0x00
+.data1 	0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x80, 0x0f, 0x84
+.data1 	0x86, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xec, 0x00
+.data1 	0x00, 0x00, 0x00, 0xf7, 0x46, 0x08, 0x00, 0x04
+.data1 	0x00, 0x00, 0x74, 0x07, 0x31, 0xc0, 0xe9, 0x02
+.data1 	0x01, 0x00, 0x00, 0x83, 0x7e, 0x10, 0x00, 0x74
+.data1 	0x0f, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x04, 0x75
+.data1 	0x07, 0x8b, 0x16, 0xf7, 0xda, 0x89, 0x55, 0xec
+.data1 	0xc7, 0x06, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x01
+.data1 	0xff, 0x75, 0xec, 0xff, 0x76, 0x04, 0xe8, 0xdd
+.data1 	0x08, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x3d, 0xff
+.data1 	0xff, 0xff, 0xff, 0x75, 0x17, 0x83, 0x3d, 0xcc
+.data1 	0x0a, 0x00, 0x00, 0x1d, 0x74, 0x0e, 0x83, 0x4e
+.data1 	0x08, 0x20, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9
+.data1 	0xb9, 0x00, 0x00, 0x00, 0xc7, 0x05, 0xcc, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x02, 0x74, 0x07, 0x81, 0x66
+.data1 	0x08, 0x7f, 0xfe, 0xff, 0xff, 0x8b, 0x56, 0x10
+.data1 	0x89, 0x56, 0x14, 0x31, 0xc0, 0xe9, 0x93, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x04
+.data1 	0x74, 0x07, 0x31, 0xc0, 0xe9, 0x84, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x01, 0x74
+.data1 	0x07, 0x81, 0x66, 0x08, 0xff, 0xfe, 0xff, 0xff
+.data1 	0x8b, 0x56, 0x14, 0x2b, 0x56, 0x10, 0x89, 0x55
+.data1 	0xfc, 0x8b, 0x56, 0x10, 0x89, 0x56, 0x14, 0x83
+.data1 	0x7d, 0xfc, 0x00, 0x7f, 0x07, 0x31, 0xc0, 0xe9
+.data1 	0x59, 0x00, 0x00, 0x00, 0xf7, 0x46, 0x08, 0x00
+.data1 	0x02, 0x00, 0x00, 0x74, 0x21, 0x6a, 0x02, 0x6a
+.data1 	0x00, 0xff, 0x76, 0x04, 0xe8, 0x47, 0x08, 0x00
+.data1 	0x00, 0x83, 0xc4, 0x0c, 0x3d, 0xff, 0xff, 0xff
+.data1 	0xff, 0x75, 0x0b, 0x83, 0x4e, 0x08, 0x20, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x2f, 0xff, 0x75
+.data1 	0xfc, 0xff, 0x76, 0x10, 0xff, 0x76, 0x04, 0xe8
+.data1 	0x2c, 0xf6, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x89
+.data1 	0x45, 0xf8, 0xc7, 0x06, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x55, 0xf8, 0x39, 0x55, 0xfc, 0x75, 0x04
+.data1 	0x31, 0xc0, 0xeb, 0x09, 0x83, 0x4e, 0x08, 0x20
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x56, 0x31, 0xf6, 0x83
+.data1 	0xfe, 0x14, 0x7d, 0x2a, 0x83, 0x3c, 0xb5, 0x18
+.data1 	0x0b, 0x00, 0x00, 0x00, 0x74, 0x1d, 0x8b, 0x14
+.data1 	0xb5, 0x18, 0x0b, 0x00, 0x00, 0xf7, 0x42, 0x08
+.data1 	0x00, 0x01, 0x00, 0x00, 0x74, 0x0d, 0xff, 0x34
+.data1 	0xb5, 0x18, 0x0b, 0x00, 0x00, 0xe8, 0x3e, 0xfe
+.data1 	0xff, 0xff, 0x59, 0x46, 0xeb, 0xd1, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x7d, 0x10, 0x57, 0xff, 0x75, 0x0c
+.data1 	0xff, 0x75, 0x08, 0xe8, 0xb8, 0xf5, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x89, 0xc6, 0x85, 0xc0, 0x7e
+.data1 	0x14, 0x39, 0xfe, 0x7d, 0x10, 0x89, 0xfa, 0x29
+.data1 	0xf2, 0x89, 0xd7, 0x89, 0xf2, 0x03, 0x55, 0x0c
+.data1 	0x89, 0x55, 0x0c, 0xeb, 0xd7, 0x31, 0xc0, 0x85
+.data1 	0xf6, 0x0f, 0x9f, 0xc0, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x56, 0x57
+.data1 	0x8b, 0x75, 0x0c, 0x8b, 0x7d, 0x08, 0xc7, 0x05
+.data1 	0xc4, 0x0a, 0x00, 0x00, 0x99, 0x14, 0x00, 0x00
+.data1 	0x83, 0x7e, 0x04, 0x00, 0x79, 0x0a, 0x89, 0xfa
+.data1 	0x0f, 0xb6, 0xc2, 0xe9, 0x55, 0x02, 0x00, 0x00
+.data1 	0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x02, 0x75, 0x0a
+.data1 	0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x43, 0x02
+.data1 	0x00, 0x00, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x80
+.data1 	0x74, 0x0f, 0xf6, 0xc2, 0x10, 0x75, 0x0a, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xe9, 0x2c, 0x02, 0x00
+.data1 	0x00, 0x81, 0x66, 0x08, 0x7f, 0xff, 0xff, 0xff
+.data1 	0x81, 0x4e, 0x08, 0x00, 0x01, 0x00, 0x00, 0x8b
+.data1 	0x56, 0x08, 0xf6, 0xc2, 0x04, 0x0f, 0x85, 0x8f
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7e, 0x10, 0x00, 0x0f
+.data1 	0x85, 0x85, 0x00, 0x00, 0x00, 0x81, 0xfe, 0xe8
+.data1 	0x0a, 0x00, 0x00, 0x75, 0x3e, 0xff, 0x35, 0xec
+.data1 	0x0a, 0x00, 0x00, 0xe8, 0xe0, 0x06, 0x00, 0x00
+.data1 	0x59, 0x85, 0xc0, 0x74, 0x2e, 0x68, 0x00, 0x04
+.data1 	0x00, 0x00, 0xe8, 0x50, 0x03, 0x00, 0x00, 0x59
+.data1 	0x89, 0x46, 0x10, 0x85, 0xc0, 0x75, 0x09, 0x83
+.data1 	0x4e, 0x08, 0x04, 0xe9, 0x4c, 0x00, 0x00, 0x00
+.data1 	0x83, 0x4e, 0x08, 0x48, 0xc7, 0x46, 0x0c, 0x00
+.data1 	0x04, 0x00, 0x00, 0xc7, 0x06, 0xff, 0xff, 0xff
+.data1 	0xff, 0xeb, 0x39, 0x68, 0x00, 0x04, 0x00, 0x00
+.data1 	0xe8, 0x22, 0x03, 0x00, 0x00, 0x59, 0x89, 0x46
+.data1 	0x10, 0x85, 0xc0, 0x75, 0x06, 0x83, 0x4e, 0x08
+.data1 	0x04, 0xeb, 0x21, 0x83, 0x4e, 0x08, 0x08, 0xc7
+.data1 	0x46, 0x0c, 0x00, 0x04, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x40, 0x75, 0x08, 0xc7, 0x06
+.data1 	0xff, 0x03, 0x00, 0x00, 0xeb, 0x06, 0xc7, 0x06
+.data1 	0xff, 0xff, 0xff, 0xff, 0x8b, 0x56, 0x10, 0x89
+.data1 	0x56, 0x14, 0x8b, 0x56, 0x08, 0xf6, 0xc2, 0x04
+.data1 	0x0f, 0x84, 0x68, 0x00, 0x00, 0x00, 0x89, 0xfa
+.data1 	0x88, 0x55, 0xff, 0xc7, 0x06, 0x00, 0x00, 0x00
+.data1 	0x00, 0xf7, 0x46, 0x08, 0x00, 0x02, 0x00, 0x00
+.data1 	0x74, 0x24, 0x6a, 0x02, 0x6a, 0x00, 0xff, 0x76
+.data1 	0x04, 0xe8, 0x62, 0x06, 0x00, 0x00, 0x83, 0xc4
+.data1 	0x0c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x0e
+.data1 	0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x3f, 0x01, 0x00, 0x00, 0x6a, 0x01
+.data1 	0x8d, 0x45, 0xff, 0x50, 0xff, 0x76, 0x04, 0xe8
+.data1 	0x44, 0xf4, 0xff, 0xff, 0x83, 0xc4, 0x0c, 0x3d
+.data1 	0x01, 0x00, 0x00, 0x00, 0x74, 0x0e, 0x83, 0x4e
+.data1 	0x08, 0x20, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xe9
+.data1 	0x19, 0x01, 0x00, 0x00, 0x89, 0xfa, 0x0f, 0xb6
+.data1 	0xc2, 0xe9, 0x0f, 0x01, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x08, 0xf6, 0xc2, 0x40, 0x0f, 0x84, 0x84, 0x00
+.data1 	0x00, 0x00, 0x89, 0xfa, 0x8b, 0x46, 0x14, 0x83
+.data1 	0x46, 0x14, 0x01, 0x88, 0x10, 0x83, 0xff, 0x0a
+.data1 	0x74, 0x0d, 0x8b, 0x56, 0x0c, 0xf7, 0xda, 0x39
+.data1 	0x16, 0x0f, 0x85, 0xe1, 0x00, 0x00, 0x00, 0x8b
+.data1 	0x16, 0xf7, 0xda, 0x89, 0x55, 0xf8, 0x8b, 0x56
+.data1 	0x10, 0x89, 0x56, 0x14, 0xc7, 0x06, 0x00, 0x00
+.data1 	0x00, 0x00, 0xf7, 0x46, 0x08, 0x00, 0x02, 0x00
+.data1 	0x00, 0x74, 0x24, 0x6a, 0x02, 0x6a, 0x00, 0xff
+.data1 	0x76, 0x04, 0xe8, 0xc9, 0x05, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x75
+.data1 	0x0e, 0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xe9, 0xa6, 0x00, 0x00, 0x00, 0xff
+.data1 	0x75, 0xf8, 0xff, 0x76, 0x10, 0xff, 0x76, 0x04
+.data1 	0xe8, 0xdf, 0xfd, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x85, 0xc0, 0x0f, 0x85, 0x88, 0x00, 0x00, 0x00
+.data1 	0x83, 0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x7f, 0x00, 0x00, 0x00, 0x8b, 0x56
+.data1 	0x14, 0x2b, 0x56, 0x10, 0x89, 0x55, 0xf8, 0x8b
+.data1 	0x56, 0x0c, 0x4a, 0x89, 0x16, 0x8b, 0x56, 0x10
+.data1 	0x83, 0xc2, 0x01, 0x89, 0x56, 0x14, 0x83, 0x7d
+.data1 	0xf8, 0x00, 0x0f, 0x8e, 0x51, 0x00, 0x00, 0x00
+.data1 	0xf7, 0x46, 0x08, 0x00, 0x02, 0x00, 0x00, 0x74
+.data1 	0x21, 0x6a, 0x02, 0x6a, 0x00, 0xff, 0x76, 0x04
+.data1 	0xe8, 0x53, 0x05, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x0b, 0x83
+.data1 	0x4e, 0x08, 0x20, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0xeb, 0x33, 0xff, 0x75, 0xf8, 0xff, 0x76, 0x10
+.data1 	0xff, 0x76, 0x04, 0xe8, 0x6c, 0xfd, 0xff, 0xff
+.data1 	0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x75, 0x12, 0x89
+.data1 	0xfa, 0x8b, 0x4e, 0x10, 0x88, 0x11, 0x83, 0x4e
+.data1 	0x08, 0x20, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xeb
+.data1 	0x0c, 0x89, 0xfa, 0x8b, 0x4e, 0x10, 0x88, 0x11
+.data1 	0x89, 0xfa, 0x0f, 0xb6, 0xc2, 0x5f, 0x5e, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x10, 0x8b, 0x45, 0x08, 0x31
+.data1 	0xd2, 0xf7, 0x75, 0x0c, 0x89, 0xd7, 0x8b, 0x45
+.data1 	0x08, 0x31, 0xd2, 0xf7, 0x75, 0x0c, 0x89, 0x45
+.data1 	0x08, 0x85, 0xc0, 0x75, 0x06, 0x83, 0x7d, 0x14
+.data1 	0x01, 0x7e, 0x16, 0x8b, 0x55, 0x14, 0x4a, 0x52
+.data1 	0x56, 0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0xe8
+.data1 	0xc8, 0xff, 0xff, 0xff, 0x83, 0xc4, 0x10, 0x89
+.data1 	0xc6, 0x83, 0xff, 0x09, 0x7e, 0x09, 0x89, 0xfa
+.data1 	0x83, 0xea, 0xa9, 0x89, 0xd0, 0xeb, 0x03, 0x8d
+.data1 	0x47, 0x30, 0x88, 0x06, 0x8d, 0x46, 0x01, 0x5f
+.data1 	0x5e, 0xc9, 0xc3, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x85, 0xc9, 0x74, 0x13, 0x8b, 0x75, 0x08
+.data1 	0x8b, 0x7d, 0x0c, 0xfc, 0xa6, 0x75, 0x09, 0x80
+.data1 	0x7e, 0xff, 0x00, 0x74, 0x03, 0x49, 0x75, 0xf4
+.data1 	0x0f, 0x97, 0xc0, 0x0f, 0x92, 0xc4, 0x28, 0xe0
+.data1 	0x0f, 0xbe, 0xc0, 0x5f, 0x5e, 0x5d, 0xc3, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x7d, 0x0c, 0x30
+.data1 	0xc0, 0x89, 0xca, 0xfc, 0xf2, 0xae, 0x29, 0xca
+.data1 	0x87, 0xca, 0x8b, 0x75, 0x0c, 0x8b, 0x7d, 0x08
+.data1 	0xf3, 0xa4, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x57
+.data1 	0x8b, 0x7d, 0x08, 0x30, 0xc0, 0x89, 0xca, 0x80
+.data1 	0xf9, 0x01, 0xfc, 0xf2, 0xae, 0x75, 0x01, 0x41
+.data1 	0x89, 0xd0, 0x29, 0xc8, 0x5f, 0x5d, 0xc3, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x68
+.data1 	0x84, 0x0a, 0x00, 0x00, 0x68, 0x00, 0x0b, 0x00
+.data1 	0x00, 0xe8, 0x52, 0xf0, 0xff, 0xff, 0x59, 0x59
+.data1 	0x6a, 0x01, 0xe8, 0x32, 0xee, 0xff, 0xff, 0x59
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x15, 0xe0, 0x1d, 0x00, 0x00, 0x03, 0x55
+.data1 	0x08, 0x39, 0x15, 0xe0, 0x1d, 0x00, 0x00, 0x77
+.data1 	0x1f, 0x8b, 0x55, 0x08, 0x03, 0x15, 0xe0, 0x1d
+.data1 	0x00, 0x00, 0x81, 0xc2, 0xff, 0x0f, 0x00, 0x00
+.data1 	0x81, 0xe2, 0x00, 0xf0, 0xff, 0xff, 0x89, 0xd6
+.data1 	0x39, 0x15, 0xe0, 0x1d, 0x00, 0x00, 0x76, 0x0e
+.data1 	0xc7, 0x05, 0xcc, 0x0a, 0x00, 0x00, 0x0c, 0x00
+.data1 	0x00, 0x00, 0x31, 0xc0, 0xeb, 0x36, 0x56, 0xe8
+.data1 	0xe8, 0x02, 0x00, 0x00, 0x59, 0x85, 0xc0, 0x74
+.data1 	0x04, 0x31, 0xc0, 0xeb, 0x27, 0x8b, 0x15, 0xe0
+.data1 	0x1d, 0x00, 0x00, 0x89, 0x72, 0xfc, 0xc7, 0x46
+.data1 	0xfc, 0x00, 0x00, 0x00, 0x00, 0xff, 0x35, 0xe0
+.data1 	0x1d, 0x00, 0x00, 0xe8, 0x26, 0x02, 0x00, 0x00
+.data1 	0x59, 0x89, 0x35, 0xe0, 0x1d, 0x00, 0x00, 0xb8
+.data1 	0x01, 0x00, 0x00, 0x00, 0x5e, 0xc9, 0xc3, 0x55
+.data1 	0x89, 0xe5, 0x83, 0xec, 0x18, 0x56, 0x57, 0x83
+.data1 	0x7d, 0x08, 0x00, 0x75, 0x07, 0x31, 0xc0, 0xe9
+.data1 	0xf4, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xe8, 0x00
+.data1 	0x00, 0x00, 0x00, 0x83, 0x7d, 0xe8, 0x02, 0x0f
+.data1 	0x83, 0xe1, 0x00, 0x00, 0x00, 0xba, 0x03, 0x00
+.data1 	0x00, 0x00, 0x03, 0x55, 0x08, 0x83, 0xe2, 0xfc
+.data1 	0x83, 0xc2, 0x04, 0x89, 0x55, 0xec, 0x83, 0xfa
+.data1 	0x08, 0x73, 0x11, 0xc7, 0x05, 0xcc, 0x0a, 0x00
+.data1 	0x00, 0x0c, 0x00, 0x00, 0x00, 0x31, 0xc0, 0xe9
+.data1 	0xbc, 0x00, 0x00, 0x00, 0x83, 0x3d, 0xdc, 0x1d
+.data1 	0x00, 0x00, 0x00, 0x75, 0x38, 0x6a, 0x08, 0xe8
+.data1 	0x97, 0x02, 0x00, 0x00, 0x59, 0x89, 0xc6, 0x3d
+.data1 	0xff, 0xff, 0xff, 0xff, 0x75, 0x07, 0x31, 0xc0
+.data1 	0xe9, 0x9b, 0x00, 0x00, 0x00, 0x8d, 0x56, 0x03
+.data1 	0xbe, 0xfc, 0xff, 0xff, 0xff, 0x21, 0xd6, 0x83
+.data1 	0xc6, 0x04, 0x89, 0x35, 0xdc, 0x1d, 0x00, 0x00
+.data1 	0x89, 0x35, 0xe0, 0x1d, 0x00, 0x00, 0xc7, 0x46
+.data1 	0xfc, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x45, 0xfc
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x35, 0xe4, 0x1d
+.data1 	0x00, 0x00, 0x85, 0xf6, 0x0f, 0x84, 0x4f, 0x00
+.data1 	0x00, 0x00, 0x8b, 0x56, 0xfc, 0x89, 0x55, 0xf4
+.data1 	0x89, 0xf2, 0x8b, 0x7d, 0xec, 0x01, 0xd7, 0x39
+.data1 	0x7d, 0xf4, 0x72, 0x36, 0x39, 0xf7, 0x76, 0x32
+.data1 	0x8d, 0x57, 0x04, 0x39, 0x55, 0xf4, 0x76, 0x0f
+.data1 	0x8b, 0x55, 0xf4, 0x89, 0x57, 0xfc, 0x89, 0x7e
+.data1 	0xfc, 0x8b, 0x16, 0x89, 0x17, 0x89, 0x3e, 0x83
+.data1 	0x7d, 0xfc, 0x00, 0x74, 0x09, 0x8b, 0x16, 0x8b
+.data1 	0x45, 0xfc, 0x89, 0x10, 0xeb, 0x08, 0x8b, 0x16
+.data1 	0x89, 0x15, 0xe4, 0x1d, 0x00, 0x00, 0x89, 0xf0
+.data1 	0xeb, 0x1e, 0x89, 0x75, 0xfc, 0x8b, 0x36, 0xeb
+.data1 	0xa9, 0xff, 0x75, 0xec, 0xe8, 0x8b, 0xfe, 0xff
+.data1 	0xff, 0x59, 0x85, 0xc0, 0x74, 0x08, 0xff, 0x45
+.data1 	0xe8, 0xe9, 0x15, 0xff, 0xff, 0xff, 0x31, 0xc0
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x1c, 0x56, 0x57, 0x8b, 0x55, 0x08, 0x89
+.data1 	0x55, 0xec, 0x85, 0xd2, 0x75, 0x0e, 0xff, 0x75
+.data1 	0x0c, 0xe8, 0xd9, 0xfe, 0xff, 0xff, 0x59, 0xe9
+.data1 	0xe6, 0x00, 0x00, 0x00, 0x83, 0x7d, 0x0c, 0x00
+.data1 	0x75, 0x10, 0xff, 0x75, 0xec, 0xe8, 0xdc, 0x00
+.data1 	0x00, 0x00, 0x59, 0x31, 0xc0, 0xe9, 0xd0, 0x00
+.data1 	0x00, 0x00, 0xba, 0x03, 0x00, 0x00, 0x00, 0x03
+.data1 	0x55, 0x0c, 0x83, 0xe2, 0xfc, 0x83, 0xc2, 0x04
+.data1 	0x89, 0x55, 0xe8, 0x8b, 0x55, 0xec, 0x8b, 0x52
+.data1 	0xfc, 0x89, 0x55, 0xf4, 0x2b, 0x55, 0xec, 0x89
+.data1 	0x55, 0xe4, 0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00
+.data1 	0x00, 0x8b, 0x3d, 0xe4, 0x1d, 0x00, 0x00, 0x85
+.data1 	0xff, 0x0f, 0x84, 0x3c, 0x00, 0x00, 0x00, 0x39
+.data1 	0x7d, 0xf4, 0x72, 0x37, 0x39, 0x7d, 0xf4, 0x75
+.data1 	0x2b, 0x8b, 0x55, 0xec, 0x8b, 0x4f, 0xfc, 0x89
+.data1 	0x4a, 0xfc, 0x83, 0x7d, 0xfc, 0x00, 0x74, 0x09
+.data1 	0x8b, 0x17, 0x8b, 0x45, 0xfc, 0x89, 0x10, 0xeb
+.data1 	0x08, 0x8b, 0x17, 0x89, 0x15, 0xe4, 0x1d, 0x00
+.data1 	0x00, 0x8b, 0x55, 0xec, 0x8b, 0x52, 0xfc, 0x89
+.data1 	0x55, 0xf4, 0xeb, 0x07, 0x89, 0x7d, 0xfc, 0x8b
+.data1 	0x3f, 0xeb, 0xbc, 0x8b, 0x55, 0xec, 0x8b, 0x75
+.data1 	0xe8, 0x01, 0xd6, 0x39, 0x75, 0xf4, 0x72, 0x25
+.data1 	0x39, 0x75, 0xec, 0x77, 0x20, 0x8d, 0x56, 0x04
+.data1 	0x39, 0x55, 0xf4, 0x76, 0x13, 0x8b, 0x55, 0xf4
+.data1 	0x89, 0x56, 0xfc, 0x8b, 0x55, 0xec, 0x89, 0x72
+.data1 	0xfc, 0x56, 0xe8, 0x37, 0x00, 0x00, 0x00, 0x59
+.data1 	0x8b, 0x45, 0xec, 0xeb, 0x2d, 0xff, 0x75, 0x0c
+.data1 	0xe8, 0x12, 0xfe, 0xff, 0xff, 0x59, 0x89, 0xc6
+.data1 	0x85, 0xc0, 0x75, 0x04, 0x31, 0xc0, 0xeb, 0x1a
+.data1 	0xff, 0x75, 0xe4, 0xff, 0x75, 0xec, 0x56, 0xe8
+.data1 	0xec, 0x01, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xff
+.data1 	0x75, 0xec, 0xe8, 0x07, 0x00, 0x00, 0x00, 0x59
+.data1 	0x89, 0xf0, 0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89
+.data1 	0xe5, 0x83, 0xec, 0x0c, 0x56, 0x57, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xf4, 0x85, 0xd2, 0x0f, 0x84
+.data1 	0x62, 0x00, 0x00, 0x00, 0x31, 0xff, 0x8b, 0x35
+.data1 	0xe4, 0x1d, 0x00, 0x00, 0x85, 0xf6, 0x74, 0x0b
+.data1 	0x39, 0x75, 0xf4, 0x72, 0x06, 0x89, 0xf7, 0x8b
+.data1 	0x36, 0xeb, 0xf1, 0x8b, 0x45, 0xf4, 0x89, 0x30
+.data1 	0x85, 0xff, 0x74, 0x07, 0x8b, 0x55, 0xf4, 0x89
+.data1 	0x17, 0xeb, 0x09, 0x8b, 0x55, 0xf4, 0x89, 0x15
+.data1 	0xe4, 0x1d, 0x00, 0x00, 0x85, 0xf6, 0x74, 0x15
+.data1 	0x8b, 0x55, 0xf4, 0x39, 0x72, 0xfc, 0x75, 0x0d
+.data1 	0x8b, 0x4e, 0xfc, 0x89, 0x4a, 0xfc, 0x8b, 0x16
+.data1 	0x8b, 0x45, 0xf4, 0x89, 0x10, 0x85, 0xff, 0x74
+.data1 	0x15, 0x8b, 0x55, 0xf4, 0x39, 0x57, 0xfc, 0x75
+.data1 	0x0d, 0x8b, 0x52, 0xfc, 0x89, 0x57, 0xfc, 0x8b
+.data1 	0x45, 0xf4, 0x8b, 0x10, 0x89, 0x17, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x8b
+.data1 	0x55, 0x08, 0x83, 0xea, 0x61, 0x83, 0xfa, 0x1a
+.data1 	0x73, 0x0a, 0x8b, 0x55, 0x08, 0x83, 0xea, 0x20
+.data1 	0x89, 0xd0, 0xeb, 0x03, 0x8b, 0x45, 0x08, 0xc9
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x15, 0xb4, 0x0d, 0x00, 0x00
+.data1 	0x39, 0x55, 0x08, 0x74, 0x2a, 0x8b, 0x55, 0x08
+.data1 	0x89, 0x55, 0xf0, 0x8d, 0x45, 0xdc, 0x50, 0x6a
+.data1 	0x11, 0x6a, 0x00, 0xe8, 0x64, 0x00, 0x00, 0x00
+.data1 	0x83, 0xc4, 0x0c, 0x85, 0xc0, 0x79, 0x07, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x0b, 0x8b, 0x55
+.data1 	0xf8, 0x89, 0x15, 0xb4, 0x0d, 0x00, 0x00, 0x31
+.data1 	0xc0, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56, 0x57
+.data1 	0x8b, 0x35, 0xb4, 0x0d, 0x00, 0x00, 0x8b, 0x15
+.data1 	0xb4, 0x0d, 0x00, 0x00, 0x8b, 0x7d, 0x08, 0x01
+.data1 	0xd7, 0x83, 0x7d, 0x08, 0x00, 0x7e, 0x04, 0x39
+.data1 	0xf7, 0x72, 0x0a, 0x83, 0x7d, 0x08, 0x00, 0x79
+.data1 	0x0b, 0x39, 0xf7, 0x76, 0x07, 0xb8, 0xff, 0xff
+.data1 	0xff, 0xff, 0xeb, 0x14, 0x57, 0xe8, 0x8a, 0xff
+.data1 	0xff, 0xff, 0x59, 0x85, 0xc0, 0x75, 0x04, 0x89
+.data1 	0xf0, 0xeb, 0x05, 0xb8, 0xff, 0xff, 0xff, 0xff
+.data1 	0x5f, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x10, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x56, 0x04, 0x56, 0xff, 0x75, 0x08, 0xe8, 0x7d
+.data1 	0xed, 0xff, 0xff, 0x59, 0x59, 0x89, 0xc7, 0x85
+.data1 	0xff, 0x74, 0x03, 0x89, 0x7e, 0x04, 0x83, 0x7e
+.data1 	0x04, 0x00, 0x79, 0x12, 0x8b, 0x56, 0x04, 0xf7
+.data1 	0xda, 0x89, 0x15, 0xcc, 0x0a, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x03, 0x8b, 0x46
+.data1 	0x04, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8d, 0x45
+.data1 	0xdc, 0x50, 0xff, 0x75, 0x08, 0xe8, 0x46, 0x00
+.data1 	0x00, 0x00, 0x59, 0x59, 0x31, 0xdb, 0x85, 0xc0
+.data1 	0x0f, 0x94, 0xc3, 0x89, 0xd8, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xf0, 0x8b, 0x55, 0x10, 0x89, 0x55, 0xe8
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x13, 0x6a, 0x01
+.data1 	0xe8, 0x77, 0xff, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0x85, 0xc0, 0x79, 0x07, 0xb8, 0xff, 0xff, 0xff
+.data1 	0xff, 0xeb, 0x03, 0x8b, 0x45, 0xf0, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0xff, 0x75, 0x0c, 0x68, 0x08
+.data1 	0x54, 0x24, 0x80, 0xff, 0x75, 0x08, 0xe8, 0x25
+.data1 	0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8b, 0x7d, 0x08
+.data1 	0x8b, 0x75, 0x0c, 0x8b, 0x4d, 0x10, 0xe9, 0x4f
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x55, 0xec, 0x8b, 0x55, 0x10, 0x89, 0x55, 0xf8
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x36, 0x6a, 0x01
+.data1 	0xe8, 0x07, 0xff, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x7d, 0x08, 0x8b, 0x75, 0x0c, 0x8b
+.data1 	0x4d, 0x10, 0x89, 0xf8, 0x29, 0xf0, 0x39, 0xc8
+.data1 	0x72, 0x2f, 0xfc, 0x83, 0xf9, 0x10, 0x72, 0x20
+.data1 	0x89, 0xf0, 0x09, 0xf8, 0xa8, 0x01, 0x75, 0x18
+.data1 	0xa8, 0x02, 0x75, 0x0d, 0x0f, 0xac, 0xc8, 0x02
+.data1 	0xc1, 0xe9, 0x02, 0xf3, 0xa5, 0x0f, 0xa4, 0xc1
+.data1 	0x02, 0xd1, 0xe9, 0xf3, 0x66, 0xa5, 0x11, 0xc9
+.data1 	0xf3, 0xa4, 0x8b, 0x45, 0x08, 0x5f, 0x5e, 0x5d
+.data1 	0xc3, 0xfd, 0x8d, 0x74, 0x0e, 0xff, 0x8d, 0x7c
+.data1 	0x0f, 0xff, 0xf3, 0xa4, 0xfc, 0xeb, 0xeb, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x13, 0x2b, 0x43
+.data1 	0x04, 0x3b, 0x43, 0x08, 0x77, 0x0c, 0xc1, 0xe0
+.data1 	0x02, 0x01, 0xc3, 0x8b, 0x5b, 0x0c, 0x85, 0xdb
+.data1 	0x75, 0x11, 0x89, 0xd3, 0x85, 0xdb, 0x75, 0x0b
+.data1 	0xb8, 0x14, 0x00, 0x00, 0x00, 0x50, 0xe9, 0x2d
+.data1 	0x00, 0x00, 0x00, 0xff, 0xe3, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x13, 0x8b, 0x4b, 0x04, 0x83, 0xc3, 0x08
+.data1 	0x49, 0x7c, 0x18, 0x3b, 0x03, 0x75, 0xf6, 0x8b
+.data1 	0x5b, 0x04, 0x85, 0xdb, 0x75, 0x0b, 0xb8, 0x14
+.data1 	0x00, 0x00, 0x00, 0x50, 0xe9, 0x07, 0x00, 0x00
+.data1 	0x00, 0xff, 0xe3, 0x89, 0xd3, 0xeb, 0xeb, 0x00
+.data1 	0xe8, 0x0f, 0x00, 0x00, 0x00, 0xe8, 0x02, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0x47, 0xec, 0xff
+.data1 	0xff, 0x00, 0x00, 0x00, 0x31, 0xdb, 0x87, 0x1d
+.data1 	0xb8, 0x0d, 0x00, 0x00, 0x85, 0xdb, 0x74, 0x05
+.data1 	0x50, 0xff, 0xd3, 0x58, 0xc3, 0x50, 0xe8, 0xe1
+.data1 	0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x63, 0x61, 0x74, 0x63
+.data1 	0x68, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6c
+.data1 	0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20, 0x72, 0x65
+.data1 	0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x00, 0x00
+.data1 	0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e
+.data1 	0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x63
+.data1 	0x75, 0x65, 0x00, 0x00, 0x72, 0x65, 0x66, 0x72
+.data1 	0x65, 0x73, 0x68, 0x00, 0x64, 0x6f, 0x77, 0x6e
+.data1 	0x00, 0x00, 0x00, 0x00, 0x75, 0x70, 0x00, 0x00
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20
+.data1 	0x25, 0x73, 0x20, 0x73, 0x68, 0x75, 0x74, 0x64
+.data1 	0x6f, 0x77, 0x6e, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x20, 0x20, 0x20, 0x25, 0x73, 0x20, 0x72
+.data1 	0x65, 0x73, 0x63, 0x75, 0x65, 0x20, 0x3c, 0x64
+.data1 	0x69, 0x72, 0x3e, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x20, 0x20, 0x20, 0x25, 0x73, 0x20, 0x72
+.data1 	0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x20, 0x3c
+.data1 	0x70, 0x69, 0x64, 0x3e, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x20, 0x20, 0x20, 0x20, 0x25, 0x73, 0x20, 0x64
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x3c, 0x70, 0x69, 0x64
+.data1 	0x3e, 0x0a, 0x00, 0x00, 0x2d, 0x70, 0x65, 0x72
+.data1 	0x69, 0x6f, 0x64, 0x00, 0x2d, 0x64, 0x65, 0x76
+.data1 	0x00, 0x00, 0x00, 0x00, 0x2d, 0x61, 0x72, 0x67
+.data1 	0x73, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20
+.data1 	0x25, 0x73, 0x20, 0x75, 0x70, 0x20, 0x3c, 0x62
+.data1 	0x69, 0x6e, 0x61, 0x72, 0x79, 0x3e, 0x20, 0x5b
+.data1 	0x25, 0x73, 0x20, 0x3c, 0x61, 0x72, 0x67, 0x73
+.data1 	0x3e, 0x5d, 0x20, 0x5b, 0x25, 0x73, 0x20, 0x3c
+.data1 	0x73, 0x70, 0x65, 0x63, 0x69, 0x61, 0x6c, 0x3e
+.data1 	0x5d, 0x20, 0x5b, 0x25, 0x73, 0x20, 0x3c, 0x74
+.data1 	0x69, 0x63, 0x6b, 0x73, 0x3e, 0x5d, 0x0a, 0x00
+.data1 	0x55, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x0a, 0x00
+.data1 	0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x2c
+.data1 	0x20, 0x25, 0x73, 0x0a, 0x00, 0x00, 0x00, 0x00
+.data1 	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20
+.data1 	0x74, 0x6f, 0x20, 0x52, 0x53, 0x20, 0x66, 0x61
+.data1 	0x69, 0x6c, 0x65, 0x64, 0x3a, 0x20, 0x25, 0x73
+.data1 	0x20, 0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00
+.data1 	0x66, 0x69, 0x6c, 0x65, 0x20, 0x69, 0x73, 0x20
+.data1 	0x6e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x64, 0x69
+.data1 	0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x00
+.data1 	0x63, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74
+.data1 	0x20, 0x67, 0x65, 0x74, 0x20, 0x73, 0x74, 0x61
+.data1 	0x74, 0x75, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x64
+.data1 	0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79
+.data1 	0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x63
+.data1 	0x75, 0x65, 0x20, 0x64, 0x69, 0x72, 0x20, 0x73
+.data1 	0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65
+.data1 	0x20, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74
+.data1 	0x65, 0x20, 0x70, 0x61, 0x74, 0x68, 0x00, 0x00
+.data1 	0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72
+.data1 	0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20
+.data1 	0x72, 0x65, 0x73, 0x63, 0x75, 0x65, 0x20, 0x64
+.data1 	0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79
+.data1 	0x00, 0x00, 0x00, 0x00, 0x70, 0x69, 0x64, 0x20
+.data1 	0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20
+.data1 	0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20
+.data1 	0x74, 0x68, 0x61, 0x6e, 0x20, 0x7a, 0x65, 0x72
+.data1 	0x6f, 0x00, 0x00, 0x00, 0x61, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69
+.data1 	0x72, 0x65, 0x73, 0x20, 0x61, 0x20, 0x70, 0x69
+.data1 	0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x74, 0x6f
+.data1 	0x70, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x6f, 0x70, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x61, 0x72, 0x67
+.data1 	0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x67, 0x69
+.data1 	0x76, 0x65, 0x6e, 0x00, 0x2d, 0x61, 0x72, 0x67
+.data1 	0x73, 0x00, 0x00, 0x00, 0x73, 0x70, 0x65, 0x63
+.data1 	0x69, 0x61, 0x6c, 0x20, 0x66, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20
+.data1 	0x61, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x6e, 0x27, 0x74, 0x20, 0x67, 0x65, 0x74
+.data1 	0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20
+.data1 	0x6f, 0x66, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63
+.data1 	0x65, 0x00, 0x00, 0x00, 0x2d, 0x64, 0x65, 0x76
+.data1 	0x00, 0x00, 0x00, 0x00, 0x70, 0x65, 0x72, 0x69
+.data1 	0x6f, 0x64, 0x20, 0x69, 0x73, 0x20, 0x61, 0x74
+.data1 	0x20, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x20, 0x62
+.data1 	0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x69
+.data1 	0x63, 0x6b, 0x00, 0x00, 0x48, 0x5a, 0x00, 0x00
+.data1 	0x2d, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x00
+.data1 	0x2d, 0x61, 0x72, 0x67, 0x73, 0x00, 0x00, 0x00
+.data1 	0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c
+.data1 	0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e
+.data1 	0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f
+.data1 	0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00
+.data1 	0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x20, 0x69
+.data1 	0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x20
+.data1 	0x72, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x20
+.data1 	0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x63, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74
+.data1 	0x20, 0x67, 0x65, 0x74, 0x20, 0x73, 0x74, 0x61
+.data1 	0x74, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79
+.data1 	0x0a, 0x00, 0x00, 0x00, 0x62, 0x69, 0x6e, 0x61
+.data1 	0x72, 0x79, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x20, 0x62, 0x65, 0x20, 0x61, 0x62, 0x73
+.data1 	0x6f, 0x6c, 0x75, 0x74, 0x65, 0x20, 0x70, 0x61
+.data1 	0x74, 0x68, 0x00, 0x00, 0x61, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69
+.data1 	0x72, 0x65, 0x73, 0x20, 0x61, 0x20, 0x62, 0x69
+.data1 	0x6e, 0x61, 0x72, 0x79, 0x20, 0x74, 0x6f, 0x20
+.data1 	0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x00, 0x00
+.data1 	0x69, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20
+.data1 	0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20
+.data1 	0x74, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x77, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x6e, 0x75
+.data1 	0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20
+.data1 	0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74
+.data1 	0x73, 0x00, 0x00, 0x00, 0x1f, 0x06, 0x00, 0x00
+.data1 	0x00, 0x07, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+.data1 	0xff, 0x04, 0x00, 0x00, 0x9d, 0x05, 0x00, 0x00
+.data1 	0x9d, 0x05, 0x00, 0x00, 0xcb, 0x05, 0x00, 0x00
+.data1 	0x01, 0x06, 0x00, 0x00, 0x72, 0x65, 0x71, 0x75
+.data1 	0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e
+.data1 	0x6f, 0x74, 0x20, 0x79, 0x65, 0x74, 0x20, 0x73
+.data1 	0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x3a, 0x20, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x74
+.data1 	0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x6e, 0x6f, 0x74
+.data1 	0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62
+.data1 	0x6c, 0x65, 0x00, 0x00, 0x53, 0x6f, 0x63, 0x6b
+.data1 	0x65, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61
+.data1 	0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x6e, 0x20
+.data1 	0x6e, 0x6f, 0x6e, 0x2d, 0x73, 0x6f, 0x63, 0x6b
+.data1 	0x65, 0x74, 0x00, 0x00, 0x4d, 0x65, 0x73, 0x73
+.data1 	0x61, 0x67, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x20
+.data1 	0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61
+.data1 	0x64, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x72
+.data1 	0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x00, 0x00
+.data1 	0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20
+.data1 	0x6e, 0x6f, 0x74, 0x20, 0x61, 0x76, 0x61, 0x69
+.data1 	0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00
+.data1 	0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f
+.data1 	0x6e, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x72, 0x6f
+.data1 	0x67, 0x72, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00
+.data1 	0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c
+.data1 	0x20, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x74
+.data1 	0x79, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20
+.data1 	0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x00, 0x00
+.data1 	0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c
+.data1 	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70
+.data1 	0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x62
+.data1 	0x79, 0x20, 0x41, 0x46, 0x00, 0x00, 0x00, 0x00
+.data1 	0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20
+.data1 	0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x20, 0x6e
+.data1 	0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f
+.data1 	0x72, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x00, 0x00, 0x41, 0x6c, 0x72, 0x65
+.data1 	0x61, 0x64, 0x79, 0x20, 0x73, 0x68, 0x75, 0x74
+.data1 	0x64, 0x6f, 0x77, 0x6e, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65
+.data1 	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x75, 0x72, 0x67, 0x65, 0x6e
+.data1 	0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x70
+.data1 	0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x00, 0x00
+.data1 	0x55, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x20, 0x64
+.data1 	0x61, 0x74, 0x61, 0x20, 0x70, 0x72, 0x65, 0x73
+.data1 	0x65, 0x6e, 0x74, 0x00, 0x43, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74
+.data1 	0x69, 0x6d, 0x65, 0x64, 0x20, 0x6f, 0x75, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72
+.data1 	0x65, 0x73, 0x65, 0x74, 0x00, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x72, 0x65, 0x66, 0x75, 0x73
+.data1 	0x65, 0x64, 0x00, 0x00, 0x41, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x75
+.data1 	0x73, 0x65, 0x00, 0x00, 0x41, 0x6c, 0x72, 0x65
+.data1 	0x61, 0x64, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74
+.data1 	0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x6f, 0x74, 0x20
+.data1 	0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c
+.data1 	0x65, 0x00, 0x00, 0x00, 0x42, 0x61, 0x64, 0x20
+.data1 	0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74
+.data1 	0x69, 0x6f, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x00, 0x57, 0x6f, 0x75, 0x6c
+.data1 	0x64, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x6d, 0x6f, 0x64, 0x65
+.data1 	0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6f, 0x63
+.data1 	0x74, 0x6c, 0x00, 0x00, 0x49, 0x6c, 0x6c, 0x65
+.data1 	0x67, 0x61, 0x6c, 0x20, 0x69, 0x6f, 0x63, 0x74
+.data1 	0x6c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x65
+.data1 	0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x65, 0x6e, 0x6f, 0x75
+.data1 	0x67, 0x68, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65
+.data1 	0x72, 0x73, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x00
+.data1 	0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20
+.data1 	0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x73
+.data1 	0x69, 0x7a, 0x65, 0x00, 0x54, 0x6f, 0x6f, 0x20
+.data1 	0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x65, 0x76
+.data1 	0x65, 0x6c, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x73
+.data1 	0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, 0x20
+.data1 	0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x00, 0x00, 0x00
+.data1 	0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72
+.data1 	0x79, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x6d
+.data1 	0x70, 0x74, 0x79, 0x00, 0x46, 0x75, 0x6e, 0x63
+.data1 	0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x6f, 0x74
+.data1 	0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65
+.data1 	0x6e, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x6c, 0x6f, 0x63, 0x6b, 0x73
+.data1 	0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62
+.data1 	0x6c, 0x65, 0x00, 0x00, 0x46, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f
+.data1 	0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x00
+.data1 	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65
+.data1 	0x20, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x6f, 0x63
+.data1 	0x6b, 0x20, 0x61, 0x76, 0x6f, 0x69, 0x64, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x75
+.data1 	0x6c, 0x74, 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c
+.data1 	0x61, 0x72, 0x67, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4d, 0x61, 0x74, 0x68, 0x20, 0x61, 0x72, 0x67
+.data1 	0x75, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00
+.data1 	0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x70
+.data1 	0x69, 0x70, 0x65, 0x00, 0x54, 0x6f, 0x6f, 0x20
+.data1 	0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x69, 0x6e
+.data1 	0x6b, 0x73, 0x00, 0x00, 0x52, 0x65, 0x61, 0x64
+.data1 	0x2d, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x66, 0x69
+.data1 	0x6c, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65
+.data1 	0x6d, 0x00, 0x00, 0x00, 0x49, 0x6c, 0x6c, 0x65
+.data1 	0x67, 0x61, 0x6c, 0x20, 0x73, 0x65, 0x65, 0x6b
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x70, 0x61, 0x63, 0x65, 0x20, 0x6c, 0x65, 0x66
+.data1 	0x74, 0x20, 0x6f, 0x6e, 0x20, 0x64, 0x65, 0x76
+.data1 	0x69, 0x63, 0x65, 0x00, 0x46, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x61, 0x72
+.data1 	0x67, 0x65, 0x00, 0x00, 0x54, 0x65, 0x78, 0x74
+.data1 	0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x62, 0x75
+.data1 	0x73, 0x79, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x61, 0x20, 0x74, 0x79, 0x70, 0x65, 0x77, 0x72
+.data1 	0x69, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00
+.data1 	0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79
+.data1 	0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x66, 0x69
+.data1 	0x6c, 0x65, 0x73, 0x00, 0x46, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f
+.data1 	0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x00
+.data1 	0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20
+.data1 	0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x49, 0x73, 0x20, 0x61
+.data1 	0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f
+.data1 	0x72, 0x79, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x61, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74
+.data1 	0x6f, 0x72, 0x79, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x64, 0x65, 0x76, 0x69
+.data1 	0x63, 0x65, 0x00, 0x00, 0x43, 0x72, 0x6f, 0x73
+.data1 	0x73, 0x2d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x00, 0x00, 0x00
+.data1 	0x46, 0x69, 0x6c, 0x65, 0x20, 0x65, 0x78, 0x69
+.data1 	0x73, 0x74, 0x73, 0x00, 0x52, 0x65, 0x73, 0x6f
+.data1 	0x75, 0x72, 0x63, 0x65, 0x20, 0x62, 0x75, 0x73
+.data1 	0x79, 0x00, 0x00, 0x00, 0x42, 0x6c, 0x6f, 0x63
+.data1 	0x6b, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x42, 0x61, 0x64, 0x20
+.data1 	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x00
+.data1 	0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x64, 0x65, 0x6e, 0x69, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x63
+.data1 	0x6f, 0x72, 0x65, 0x00, 0x52, 0x65, 0x73, 0x6f
+.data1 	0x75, 0x72, 0x63, 0x65, 0x20, 0x74, 0x65, 0x6d
+.data1 	0x70, 0x6f, 0x72, 0x61, 0x72, 0x69, 0x6c, 0x79
+.data1 	0x20, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c
+.data1 	0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64
+.data1 	0x72, 0x65, 0x6e, 0x00, 0x42, 0x61, 0x64, 0x20
+.data1 	0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x75, 0x6d
+.data1 	0x62, 0x65, 0x72, 0x00, 0x45, 0x78, 0x65, 0x63
+.data1 	0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20
+.data1 	0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00
+.data1 	0x41, 0x72, 0x67, 0x20, 0x6c, 0x69, 0x73, 0x74
+.data1 	0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x6f, 0x6e
+.data1 	0x67, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x64, 0x65, 0x76, 0x69
+.data1 	0x63, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x64
+.data1 	0x64, 0x72, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00
+.data1 	0x49, 0x2f, 0x4f, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x74, 0x65
+.data1 	0x72, 0x72, 0x75, 0x70, 0x74, 0x65, 0x64, 0x20
+.data1 	0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x63
+.data1 	0x61, 0x6c, 0x6c, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x70, 0x72, 0x6f, 0x63
+.data1 	0x65, 0x73, 0x73, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x66, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x6f, 0x72, 0x20, 0x64, 0x69, 0x72, 0x65
+.data1 	0x63, 0x74, 0x6f, 0x72, 0x79, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x6f, 0x77, 0x6e, 0x65
+.data1 	0x72, 0x00, 0x00, 0x00, 0x45, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x20, 0x30, 0x00, 0x91, 0x0b, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
+.data1 	0x35, 0x0b, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+.data1 	0x6a, 0x0b, 0x00, 0x00, 0x8e, 0x0c, 0x00, 0x00
+.data1 	0x08, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00
+.data1 	0x77, 0x0c, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00
+.data1 	0x5c, 0x0c, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00
+.data1 	0x6e, 0x0c, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00
+.data1 	0x6e, 0x0c, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00
+.data1 	0x65, 0x0c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00
+.data1 	0x77, 0x0c, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00
+.data1 	0x6e, 0x0c, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
+.data1 	0x77, 0x0c, 0x00, 0x00, 0x67, 0x0d, 0x00, 0x00
+.data1 	0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
+.data1 	0x58, 0x0d, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00
+.data1 	0x5d, 0x0d, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00
+.data1 	0x53, 0x0d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x0d, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00
+.data1 	0x62, 0x0d, 0x00, 0x00, 0x59, 0x10, 0x00, 0x00
+.data1 	0x03, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00
+.data1 	0x41, 0x0e, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00
+.data1 	0x2b, 0x0e, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00
+.data1 	0x36, 0x0e, 0x00, 0x00, 0x5f, 0x0e, 0x00, 0x00
+.data1 	0x11, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00
+.data1 	0xf5, 0x0f, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00
+.data1 	0xe0, 0x0f, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00
+.data1 	0x4b, 0x0f, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00
+.data1 	0x4b, 0x0f, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x0f, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00
+.data1 	0x89, 0x0f, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00
+.data1 	0xf5, 0x0f, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00
+.data1 	0xf5, 0x0f, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00
+.data1 	0xe0, 0x0f, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00
+.data1 	0x89, 0x0f, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00
+.data1 	0xaf, 0x0e, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00
+.data1 	0x4b, 0x0f, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00
+.data1 	0x4b, 0x0f, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00
+.data1 	0x39, 0x10, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00
+.data1 	0x05, 0x0f, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00
+.data1 	0x4b, 0x0f, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
+.data1 	0x4b, 0x0f, 0x00, 0x00, 0x28, 0x6e, 0x75, 0x6c
+.data1 	0x6c, 0x29, 0x00, 0x00, 0x63, 0x61, 0x6e, 0x6e
+.data1 	0x6f, 0x74, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74
+.data1 	0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x69, 0x6e
+.data1 	0x67, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x0a
+.data1 	0x00, 0x00, 0x00, 0x00, 0xec, 0x1d, 0x00, 0x00
+.data1 	0x44, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00
+.data1 	0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x53, 0x53, 0x53, 0x53, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+.data1 	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+.data1 	0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd0, 0x0a, 0x00, 0x00, 0xe8, 0x0a, 0x00, 0x00
+.data1 	0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x20, 0x28, 0x28, 0x28, 0x28, 0x28, 0x20
+.data1 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+.data1 	0x20, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04
+.data1 	0x04, 0x04, 0x04, 0x10, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x10, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41
+.data1 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+.data1 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+.data1 	0x01, 0x01, 0x01, 0x01, 0x10, 0x10, 0x10, 0x10
+.data1 	0x10, 0x10, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42
+.data1 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+.data1 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+.data1 	0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10
+.data1 	0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0x34, 0x09, 0x00, 0x00
+.data1 	0x28, 0x09, 0x00, 0x00, 0x0c, 0x09, 0x00, 0x00
+.data1 	0xfc, 0x08, 0x00, 0x00, 0xe4, 0x08, 0x00, 0x00
+.data1 	0xd8, 0x08, 0x00, 0x00, 0xbc, 0x08, 0x00, 0x00
+.data1 	0xa8, 0x08, 0x00, 0x00, 0x94, 0x08, 0x00, 0x00
+.data1 	0x84, 0x08, 0x00, 0x00, 0x78, 0x08, 0x00, 0x00
+.data1 	0x54, 0x08, 0x00, 0x00, 0x44, 0x08, 0x00, 0x00
+.data1 	0x30, 0x08, 0x00, 0x00, 0x24, 0x08, 0x00, 0x00
+.data1 	0x0c, 0x08, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00
+.data1 	0xf0, 0x07, 0x00, 0x00, 0xdc, 0x07, 0x00, 0x00
+.data1 	0xcc, 0x07, 0x00, 0x00, 0xbc, 0x07, 0x00, 0x00
+.data1 	0xac, 0x07, 0x00, 0x00, 0x98, 0x07, 0x00, 0x00
+.data1 	0x84, 0x07, 0x00, 0x00, 0x70, 0x07, 0x00, 0x00
+.data1 	0x5c, 0x07, 0x00, 0x00, 0x4c, 0x07, 0x00, 0x00
+.data1 	0x3c, 0x07, 0x00, 0x00, 0x24, 0x07, 0x00, 0x00
+.data1 	0x14, 0x07, 0x00, 0x00, 0xfc, 0x06, 0x00, 0x00
+.data1 	0xec, 0x06, 0x00, 0x00, 0xe0, 0x06, 0x00, 0x00
+.data1 	0xd0, 0x06, 0x00, 0x00, 0xbc, 0x06, 0x00, 0x00
+.data1 	0xa0, 0x06, 0x00, 0x00, 0x8c, 0x06, 0x00, 0x00
+.data1 	0x78, 0x06, 0x00, 0x00, 0x5c, 0x06, 0x00, 0x00
+.data1 	0x48, 0x06, 0x00, 0x00, 0x24, 0x06, 0x00, 0x00
+.data1 	0x6c, 0x0c, 0x00, 0x00, 0x6c, 0x0c, 0x00, 0x00
+.data1 	0x6c, 0x0c, 0x00, 0x00, 0x6c, 0x0c, 0x00, 0x00
+.data1 	0x6c, 0x0c, 0x00, 0x00, 0x6c, 0x0c, 0x00, 0x00
+.data1 	0x6c, 0x0c, 0x00, 0x00, 0x6c, 0x0c, 0x00, 0x00
+.data1 	0x6c, 0x0c, 0x00, 0x00, 0x10, 0x06, 0x00, 0x00
+.data1 	0xf8, 0x05, 0x00, 0x00, 0xdc, 0x05, 0x00, 0x00
+.data1 	0xc8, 0x05, 0x00, 0x00, 0xbc, 0x05, 0x00, 0x00
+.data1 	0xa4, 0x05, 0x00, 0x00, 0x88, 0x05, 0x00, 0x00
+.data1 	0x74, 0x05, 0x00, 0x00, 0x64, 0x05, 0x00, 0x00
+.data1 	0x50, 0x05, 0x00, 0x00, 0x3c, 0x05, 0x00, 0x00
+.data1 	0x24, 0x05, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00
+.data1 	0xf8, 0x04, 0x00, 0x00, 0xe8, 0x04, 0x00, 0x00
+.data1 	0xd4, 0x04, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x00
+.data1 	0xa0, 0x04, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00
+.data1 	0x60, 0x04, 0x00, 0x00, 0x48, 0x04, 0x00, 0x00
+.data1 	0x30, 0x04, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00
+.data1 	0xfc, 0x03, 0x00, 0x00, 0xdc, 0x03, 0x00, 0x00
+.data1 	0xc4, 0x03, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x70, 0x1e, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x03, 0x20, 0x10, 0x20, 0x00, 0x00, 0x00
+.data1 	0x50, 0x04, 0x00, 0x00, 0x50, 0x07, 0x00, 0x00
+.data1 	0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd8, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0xed, 0x8b, 0x04, 0x24, 0x8d, 0x54, 0x24
+.data1 	0x04, 0x8d, 0x4c, 0x84, 0x08, 0xbb, 0xfc, 0x05
+.data1 	0x00, 0x00, 0x81, 0xfb, 0x50, 0x07, 0x00, 0x00
+.data1 	0x73, 0x13, 0xf6, 0xc3, 0x03, 0x75, 0x0e, 0x81
+.data1 	0x3b, 0x53, 0x53, 0x53, 0x53, 0x75, 0x06, 0x89
+.data1 	0x1d, 0xf0, 0x05, 0x00, 0x00, 0x8b, 0x1d, 0xf0
+.data1 	0x05, 0x00, 0x00, 0x89, 0x0b, 0x51, 0x52, 0x50
+.data1 	0x0f, 0x01, 0xe0, 0xa8, 0x04, 0x0f, 0x94, 0x05
+.data1 	0x50, 0x07, 0x00, 0x00, 0xe8, 0x37, 0x00, 0x00
+.data1 	0x00, 0x50, 0xe8, 0xbe, 0x01, 0x00, 0x00, 0xf4
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x57, 0x8d, 0x7d, 0x0c
+.data1 	0x8d, 0x57, 0x04, 0x89, 0xd7, 0x8b, 0x52, 0xfc
+.data1 	0x89, 0xd6, 0x85, 0xd2, 0x74, 0x16, 0x56, 0xe8
+.data1 	0x00, 0x02, 0x00, 0x00, 0x59, 0x50, 0x56, 0xff
+.data1 	0x75, 0x08, 0xe8, 0xed, 0x01, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xeb, 0xdc, 0x5f, 0x5e, 0xc9, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x81, 0xec, 0x20, 0x04, 0x00
+.data1 	0x00, 0x56, 0x57, 0xc7, 0x45, 0xe8, 0x00, 0x00
+.data1 	0x00, 0x00, 0xbe, 0x01, 0x00, 0x00, 0x00, 0x39
+.data1 	0x75, 0x08, 0x0f, 0x8e, 0x53, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x55, 0x0c, 0x8b, 0x14, 0xb2, 0x80, 0x3a
+.data1 	0x2d, 0x75, 0x48, 0x89, 0xf2, 0x42, 0xff, 0x75
+.data1 	0x0c, 0x56, 0x89, 0xd6, 0x5a, 0x59, 0x8b, 0x14
+.data1 	0x91, 0x83, 0xc2, 0x01, 0x89, 0x95, 0xe0, 0xfb
+.data1 	0xff, 0xff, 0x80, 0x3a, 0x2d, 0x75, 0x06, 0x80
+.data1 	0x7a, 0x01, 0x00, 0x74, 0x26, 0x8b, 0x95, 0xe0
+.data1 	0xfb, 0xff, 0xff, 0x80, 0x3a, 0x00, 0x74, 0xbf
+.data1 	0x6a, 0x00, 0x68, 0x24, 0x00, 0x00, 0x00, 0x6a
+.data1 	0x02, 0xe8, 0x6a, 0xff, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x0c, 0x6a, 0x01, 0xe8, 0x1d, 0x01, 0x00, 0x00
+.data1 	0x59, 0xeb, 0xa4, 0x39, 0x75, 0x08, 0x7e, 0x1a
+.data1 	0x8b, 0x55, 0x0c, 0x8b, 0x14, 0xb2, 0x89, 0x55
+.data1 	0xf0, 0x52, 0xe8, 0x65, 0x01, 0x00, 0x00, 0x59
+.data1 	0x05, 0x01, 0x00, 0x00, 0x00, 0x89, 0x45, 0xf4
+.data1 	0xeb, 0x0e, 0xc7, 0x45, 0xf0, 0x00, 0x00, 0x00
+.data1 	0x00, 0xc7, 0x45, 0xf4, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8d, 0x95, 0xe4, 0xfb, 0xff, 0xff, 0x89, 0x55
+.data1 	0xf8, 0xc7, 0x45, 0xfc, 0x00, 0x04, 0x00, 0x00
+.data1 	0x8d, 0x45, 0xf0, 0x50, 0x68, 0x05, 0x4d, 0x10
+.data1 	0x40, 0xe8, 0x1e, 0x01, 0x00, 0x00, 0x59, 0x59
+.data1 	0x3d, 0xff, 0xff, 0xff, 0xff, 0x75, 0x3e, 0x83
+.data1 	0x3d, 0x00, 0x06, 0x00, 0x00, 0x03, 0x75, 0x09
+.data1 	0x83, 0x4d, 0xe8, 0x02, 0xe9, 0x88, 0x00, 0x00
+.data1 	0x00, 0x83, 0x4d, 0xe8, 0x01, 0x6a, 0x00, 0x68
+.data1 	0x14, 0x00, 0x00, 0x00, 0xff, 0x35, 0x00, 0x06
+.data1 	0x00, 0x00, 0xe8, 0xc1, 0x00, 0x00, 0x00, 0x59
+.data1 	0x50, 0x68, 0x18, 0x00, 0x00, 0x00, 0x6a, 0x02
+.data1 	0xe8, 0xd3, 0xfe, 0xff, 0xff, 0x83, 0xc4, 0x14
+.data1 	0xe9, 0x5c, 0x00, 0x00, 0x00, 0x8b, 0x7d, 0xf8
+.data1 	0x57, 0x57, 0xe8, 0xdd, 0x00, 0x00, 0x00, 0x59
+.data1 	0x5a, 0x89, 0xc7, 0x01, 0xd7, 0xc6, 0x07, 0x0a
+.data1 	0x47, 0x39, 0x75, 0x08, 0x75, 0x05, 0x80, 0x3f
+.data1 	0x00, 0x75, 0xe5, 0x89, 0xfa, 0x2b, 0x55, 0xf8
+.data1 	0x52, 0xff, 0x75, 0xf8, 0x6a, 0x01, 0xe8, 0xb1
+.data1 	0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c, 0x85, 0xc0
+.data1 	0x79, 0x27, 0x83, 0x4d, 0xe8, 0x01, 0x6a, 0x00
+.data1 	0x68, 0x04, 0x00, 0x00, 0x00, 0xff, 0x35, 0x00
+.data1 	0x06, 0x00, 0x00, 0xe8, 0x60, 0x00, 0x00, 0x00
+.data1 	0x59, 0x50, 0x68, 0x08, 0x00, 0x00, 0x00, 0x6a
+.data1 	0x02, 0xe8, 0x72, 0xfe, 0xff, 0xff, 0x83, 0xc4
+.data1 	0x14, 0x46, 0x39, 0x75, 0x08, 0x0f, 0x8f, 0x08
+.data1 	0xff, 0xff, 0xff, 0x8b, 0x45, 0xe8, 0x5f, 0x5e
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x8b, 0x35, 0xf4, 0x05, 0x00, 0x00, 0x4e, 0x78
+.data1 	0x09, 0xff, 0x14, 0xb5, 0x58, 0x07, 0x00, 0x00
+.data1 	0xeb, 0xf4, 0x5e, 0xc9, 0xc3, 0x55, 0x89, 0xe5
+.data1 	0xe8, 0xdf, 0xff, 0xff, 0xff, 0x83, 0x3d, 0xf8
+.data1 	0x05, 0x00, 0x00, 0x00, 0x74, 0x06, 0xff, 0x15
+.data1 	0xf8, 0x05, 0x00, 0x00, 0xff, 0x75, 0x08, 0xe8
+.data1 	0x28, 0x00, 0x00, 0x00, 0x59, 0xc9, 0xc3, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x56, 0x8b, 0x75, 0x08, 0x85
+.data1 	0xf6, 0x78, 0x08, 0x39, 0x35, 0x44, 0x07, 0x00
+.data1 	0x00, 0x7f, 0x07, 0xb8, 0x40, 0x00, 0x00, 0x00
+.data1 	0xeb, 0x07, 0x8b, 0x04, 0xb5, 0x14, 0x06, 0x00
+.data1 	0x00, 0x5e, 0xc9, 0xc3, 0xe9, 0xc7, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0x1b, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xe9, 0xdf, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0xb9, 0xff, 0xff, 0xff
+.data1 	0xff, 0xe9, 0x5e, 0x01, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x83
+.data1 	0xec, 0x24, 0x8b, 0x55, 0x08, 0x89, 0x55, 0xe4
+.data1 	0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf8, 0xeb, 0x35
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x4d, 0x6a, 0x00
+.data1 	0xe8, 0x3f, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x0c
+.data1 	0xeb, 0x36, 0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x4d
+.data1 	0x6a, 0x01, 0xe8, 0x2d, 0x00, 0x00, 0x00, 0x83
+.data1 	0xc4, 0x0c, 0xeb, 0x24, 0xc7, 0x05, 0x00, 0x06
+.data1 	0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0xb8, 0xff
+.data1 	0xff, 0xff, 0xff, 0xeb, 0x13, 0x8b, 0x55, 0x08
+.data1 	0xc1, 0xfa, 0x08, 0xbb, 0xc8, 0x05, 0x00, 0x00
+.data1 	0x0f, 0xb6, 0xc2, 0xe9, 0x1c, 0x01, 0x00, 0x00
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x56
+.data1 	0x57, 0x8b, 0x75, 0x10, 0x8b, 0x55, 0x0c, 0x89
+.data1 	0x56, 0x04, 0x56, 0xff, 0x75, 0x08, 0xe8, 0xa9
+.data1 	0x00, 0x00, 0x00, 0x59, 0x59, 0x89, 0xc7, 0x85
+.data1 	0xff, 0x74, 0x03, 0x89, 0x7e, 0x04, 0x83, 0x7e
+.data1 	0x04, 0x00, 0x79, 0x12, 0x8b, 0x56, 0x04, 0xf7
+.data1 	0xda, 0x89, 0x15, 0x00, 0x06, 0x00, 0x00, 0xb8
+.data1 	0xff, 0xff, 0xff, 0xff, 0xeb, 0x03, 0x8b, 0x46
+.data1 	0x04, 0x5f, 0x5e, 0xc9, 0xc3, 0x00, 0x00, 0x00
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x28, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe0, 0x8d, 0x45, 0xd8, 0x50
+.data1 	0x6a, 0x01, 0x6a, 0x00, 0xe8, 0xa3, 0xff, 0xff
+.data1 	0xff, 0x83, 0xc4, 0x0c, 0xba, 0xff, 0xff, 0xff
+.data1 	0xff, 0x89, 0x55, 0xfc, 0xff, 0xd2, 0xeb, 0xfe
+.data1 	0x55, 0x89, 0xe5, 0x83, 0xec, 0x24, 0x8b, 0x55
+.data1 	0x08, 0x89, 0x55, 0xe4, 0x8b, 0x55, 0x10, 0x89
+.data1 	0x55, 0xe8, 0x8b, 0x55, 0x0c, 0x89, 0x55, 0xf0
+.data1 	0x8d, 0x45, 0xdc, 0x50, 0x6a, 0x04, 0x6a, 0x01
+.data1 	0xe8, 0x6f, 0xff, 0xff, 0xff, 0x83, 0xc4, 0x0c
+.data1 	0xc9, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x01
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0x8b
+.data1 	0x5d, 0x0c, 0xb9, 0x02, 0x00, 0x00, 0x00, 0xcd
+.data1 	0x21, 0x5b, 0x5d, 0xc3, 0x55, 0x89, 0xe5, 0x53
+.data1 	0x8b, 0x45, 0x08, 0x8b, 0x5d, 0x0c, 0xb9, 0x03
+.data1 	0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d, 0xc3
+.data1 	0x55, 0x89, 0xe5, 0x53, 0x8b, 0x45, 0x08, 0xb9
+.data1 	0x04, 0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b, 0x5d
+.data1 	0xc3, 0x55, 0x89, 0xe5, 0x53, 0x8b, 0x5d, 0x08
+.data1 	0xb9, 0x08, 0x00, 0x00, 0x00, 0xcd, 0x21, 0x5b
+.data1 	0x5d, 0xc3, 0x00, 0x00, 0x55, 0x89, 0xe5, 0x57
+.data1 	0x8b, 0x7d, 0x08, 0x30, 0xc0, 0x89, 0xca, 0x80
+.data1 	0xf9, 0x01, 0xfc, 0xf2, 0xae, 0x75, 0x01, 0x41
+.data1 	0x89, 0xd0, 0x29, 0xc8, 0x5f, 0x5d, 0xc3, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x8b, 0x13, 0x8b, 0x4b
+.data1 	0x04, 0x83, 0xc3, 0x08, 0x49, 0x7c, 0x18, 0x3b
+.data1 	0x03, 0x75, 0xf6, 0x8b, 0x5b, 0x04, 0x85, 0xdb
+.data1 	0x75, 0x0b, 0xb8, 0x14, 0x00, 0x00, 0x00, 0x50
+.data1 	0xe9, 0x07, 0x00, 0x00, 0x00, 0xff, 0xe3, 0x89
+.data1 	0xd3, 0xeb, 0xeb, 0x00, 0xe8, 0x0f, 0x00, 0x00
+.data1 	0x00, 0xe8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xe9, 0xf3, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00
+.data1 	0x31, 0xdb, 0x87, 0x1d, 0x48, 0x07, 0x00, 0x00
+.data1 	0x85, 0xdb, 0x74, 0x05, 0x50, 0xff, 0xd3, 0x58
+.data1 	0xc3, 0x50, 0xe8, 0xe1, 0xff, 0xff, 0xff, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x73, 0x79, 0x73, 0x65, 0x6e, 0x76, 0x3a, 0x20
+.data1 	0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x73, 0x79, 0x73, 0x65, 0x6e, 0x76, 0x3a, 0x20
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67
+.data1 	0x65, 0x3a, 0x20, 0x73, 0x79, 0x73, 0x65, 0x6e
+.data1 	0x76, 0x20, 0x5b, 0x6e, 0x61, 0x6d, 0x65, 0x20
+.data1 	0x2e, 0x2e, 0x2e, 0x5d, 0x0a, 0x00, 0x00, 0x00
+.data1 	0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20
+.data1 	0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00
+.data1 	0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c
+.data1 	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x76, 0x61
+.data1 	0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00
+.data1 	0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x6f
+.data1 	0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e
+.data1 	0x20, 0x6f, 0x6e, 0x20, 0x6e, 0x6f, 0x6e, 0x2d
+.data1 	0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x00, 0x00
+.data1 	0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20
+.data1 	0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67
+.data1 	0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61
+.data1 	0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x69
+.data1 	0x6e, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65
+.data1 	0x73, 0x73, 0x00, 0x00, 0x41, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20
+.data1 	0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c
+.data1 	0x65, 0x00, 0x00, 0x00, 0x4f, 0x70, 0x65, 0x72
+.data1 	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e
+.data1 	0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73
+.data1 	0x73, 0x00, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x74
+.data1 	0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x77, 0x72, 0x6f
+.data1 	0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20
+.data1 	0x66, 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x63, 0x6b
+.data1 	0x65, 0x74, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x74
+.data1 	0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x6e, 0x6f, 0x74
+.data1 	0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74
+.data1 	0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x41, 0x46
+.data1 	0x00, 0x00, 0x00, 0x00, 0x41, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x20, 0x66, 0x61, 0x6d, 0x69
+.data1 	0x6c, 0x79, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73
+.data1 	0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x73
+.data1 	0x75, 0x63, 0x68, 0x20, 0x63, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00
+.data1 	0x41, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20
+.data1 	0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x63
+.data1 	0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f
+.data1 	0x6e, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x75
+.data1 	0x72, 0x67, 0x65, 0x6e, 0x74, 0x20, 0x64, 0x61
+.data1 	0x74, 0x61, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65
+.data1 	0x6e, 0x74, 0x00, 0x00, 0x55, 0x72, 0x67, 0x65
+.data1 	0x6e, 0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20
+.data1 	0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x00
+.data1 	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x64
+.data1 	0x20, 0x6f, 0x75, 0x74, 0x00, 0x00, 0x00, 0x00
+.data1 	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69
+.data1 	0x6f, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x65, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x6e
+.data1 	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72
+.data1 	0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x00, 0x00
+.data1 	0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20
+.data1 	0x69, 0x6e, 0x20, 0x75, 0x73, 0x65, 0x00, 0x00
+.data1 	0x41, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20
+.data1 	0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65
+.data1 	0x64, 0x00, 0x00, 0x00, 0x44, 0x65, 0x73, 0x74
+.data1 	0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20
+.data1 	0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x61, 0x63
+.data1 	0x68, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x64, 0x65, 0x73, 0x74
+.data1 	0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20
+.data1 	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x00
+.data1 	0x57, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x6c
+.data1 	0x6f, 0x63, 0x6b, 0x00, 0x42, 0x61, 0x64, 0x20
+.data1 	0x6d, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72
+.data1 	0x20, 0x69, 0x6f, 0x63, 0x74, 0x6c, 0x00, 0x00
+.data1 	0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20
+.data1 	0x69, 0x6f, 0x63, 0x74, 0x6c, 0x20, 0x66, 0x6f
+.data1 	0x72, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x62
+.data1 	0x75, 0x66, 0x66, 0x65, 0x72, 0x73, 0x20, 0x6c
+.data1 	0x65, 0x66, 0x74, 0x00, 0x49, 0x6e, 0x76, 0x61
+.data1 	0x6c, 0x69, 0x64, 0x20, 0x70, 0x61, 0x63, 0x6b
+.data1 	0x65, 0x74, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x00
+.data1 	0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79
+.data1 	0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x20
+.data1 	0x6f, 0x66, 0x20, 0x73, 0x79, 0x6d, 0x62, 0x6f
+.data1 	0x6c, 0x69, 0x63, 0x20, 0x6c, 0x69, 0x6e, 0x6b
+.data1 	0x73, 0x00, 0x00, 0x00, 0x44, 0x69, 0x72, 0x65
+.data1 	0x63, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x6e, 0x6f
+.data1 	0x74, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x00
+.data1 	0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e
+.data1 	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6d, 0x70
+.data1 	0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x6c
+.data1 	0x6f, 0x63, 0x6b, 0x73, 0x20, 0x61, 0x76, 0x61
+.data1 	0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00
+.data1 	0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d
+.data1 	0x65, 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x6f
+.data1 	0x6e, 0x67, 0x00, 0x00, 0x52, 0x65, 0x73, 0x6f
+.data1 	0x75, 0x72, 0x63, 0x65, 0x20, 0x64, 0x65, 0x61
+.data1 	0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x61, 0x76
+.data1 	0x6f, 0x69, 0x64, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x74
+.data1 	0x6f, 0x6f, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4d, 0x61, 0x74, 0x68
+.data1 	0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e
+.data1 	0x74, 0x00, 0x00, 0x00, 0x42, 0x72, 0x6f, 0x6b
+.data1 	0x65, 0x6e, 0x20, 0x70, 0x69, 0x70, 0x65, 0x00
+.data1 	0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79
+.data1 	0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x00, 0x00
+.data1 	0x52, 0x65, 0x61, 0x64, 0x2d, 0x6f, 0x6e, 0x6c
+.data1 	0x79, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x73
+.data1 	0x79, 0x73, 0x74, 0x65, 0x6d, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x20
+.data1 	0x73, 0x65, 0x65, 0x6b, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65
+.data1 	0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x6f, 0x6e
+.data1 	0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00
+.data1 	0x46, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6f
+.data1 	0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x00, 0x00
+.data1 	0x54, 0x65, 0x78, 0x74, 0x20, 0x66, 0x69, 0x6c
+.data1 	0x65, 0x20, 0x62, 0x75, 0x73, 0x79, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x74, 0x79
+.data1 	0x70, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72
+.data1 	0x00, 0x00, 0x00, 0x00, 0x54, 0x6f, 0x6f, 0x20
+.data1 	0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6f, 0x70, 0x65
+.data1 	0x6e, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x00
+.data1 	0x46, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x61, 0x62
+.data1 	0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x66
+.data1 	0x6c, 0x6f, 0x77, 0x00, 0x49, 0x6e, 0x76, 0x61
+.data1 	0x6c, 0x69, 0x64, 0x20, 0x61, 0x72, 0x67, 0x75
+.data1 	0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00
+.data1 	0x49, 0x73, 0x20, 0x61, 0x20, 0x64, 0x69, 0x72
+.data1 	0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x64, 0x69
+.data1 	0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00
+.data1 	0x43, 0x72, 0x6f, 0x73, 0x73, 0x2d, 0x64, 0x65
+.data1 	0x76, 0x69, 0x63, 0x65, 0x20, 0x6c, 0x69, 0x6e
+.data1 	0x6b, 0x00, 0x00, 0x00, 0x46, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x00
+.data1 	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65
+.data1 	0x20, 0x62, 0x75, 0x73, 0x79, 0x00, 0x00, 0x00
+.data1 	0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x64, 0x65
+.data1 	0x76, 0x69, 0x63, 0x65, 0x20, 0x72, 0x65, 0x71
+.data1 	0x75, 0x69, 0x72, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x61, 0x64, 0x64, 0x72
+.data1 	0x65, 0x73, 0x73, 0x00, 0x50, 0x65, 0x72, 0x6d
+.data1 	0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x64
+.data1 	0x65, 0x6e, 0x69, 0x65, 0x64, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x74, 0x20, 0x65, 0x6e, 0x6f, 0x75
+.data1 	0x67, 0x68, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x00
+.data1 	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65
+.data1 	0x20, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61
+.data1 	0x72, 0x69, 0x6c, 0x79, 0x20, 0x75, 0x6e, 0x61
+.data1 	0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65
+.data1 	0x00, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x20, 0x63
+.data1 	0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x00
+.data1 	0x42, 0x61, 0x64, 0x20, 0x66, 0x69, 0x6c, 0x65
+.data1 	0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x00
+.data1 	0x45, 0x78, 0x65, 0x63, 0x20, 0x66, 0x6f, 0x72
+.data1 	0x6d, 0x61, 0x74, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0x41, 0x72, 0x67, 0x20
+.data1 	0x6c, 0x69, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x6f
+.data1 	0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x6f
+.data1 	0x72, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73
+.data1 	0x73, 0x00, 0x00, 0x00, 0x49, 0x2f, 0x4f, 0x20
+.data1 	0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00
+.data1 	0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70
+.data1 	0x74, 0x65, 0x64, 0x20, 0x73, 0x79, 0x73, 0x74
+.data1 	0x65, 0x6d, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x00
+.data1 	0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20
+.data1 	0x66, 0x69, 0x6c, 0x65, 0x20, 0x6f, 0x72, 0x20
+.data1 	0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72
+.data1 	0x79, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20
+.data1 	0x6f, 0x77, 0x6e, 0x65, 0x72, 0x00, 0x00, 0x00
+.data1 	0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x30, 0x00
+.data1 	0xb4, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+.data1 	0x46, 0x00, 0x00, 0x00, 0xa2, 0x02, 0x00, 0x00
+.data1 	0x49, 0x00, 0x00, 0x00, 0xa2, 0x02, 0x00, 0x00
+.data1 	0x4d, 0x00, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00
+.data1 	0x53, 0x00, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00
+.data1 	0x54, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x53, 0x53, 0x53, 0x53
+.data1 	0x00, 0x00, 0x00, 0x00, 0x55, 0x6e, 0x6b, 0x6e
+.data1 	0x6f, 0x77, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f
+.data1 	0x72, 0x00, 0x00, 0x00, 0xc0, 0x05, 0x00, 0x00
+.data1 	0xb4, 0x05, 0x00, 0x00, 0x98, 0x05, 0x00, 0x00
+.data1 	0x88, 0x05, 0x00, 0x00, 0x70, 0x05, 0x00, 0x00
+.data1 	0x64, 0x05, 0x00, 0x00, 0x48, 0x05, 0x00, 0x00
+.data1 	0x34, 0x05, 0x00, 0x00, 0x20, 0x05, 0x00, 0x00
+.data1 	0x10, 0x05, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00
+.data1 	0xe0, 0x04, 0x00, 0x00, 0xd0, 0x04, 0x00, 0x00
+.data1 	0xbc, 0x04, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00
+.data1 	0x98, 0x04, 0x00, 0x00, 0x88, 0x04, 0x00, 0x00
+.data1 	0x7c, 0x04, 0x00, 0x00, 0x68, 0x04, 0x00, 0x00
+.data1 	0x58, 0x04, 0x00, 0x00, 0x48, 0x04, 0x00, 0x00
+.data1 	0x38, 0x04, 0x00, 0x00, 0x24, 0x04, 0x00, 0x00
+.data1 	0x10, 0x04, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00
+.data1 	0xe8, 0x03, 0x00, 0x00, 0xd8, 0x03, 0x00, 0x00
+.data1 	0xc8, 0x03, 0x00, 0x00, 0xb0, 0x03, 0x00, 0x00
+.data1 	0xa0, 0x03, 0x00, 0x00, 0x88, 0x03, 0x00, 0x00
+.data1 	0x78, 0x03, 0x00, 0x00, 0x6c, 0x03, 0x00, 0x00
+.data1 	0x5c, 0x03, 0x00, 0x00, 0x48, 0x03, 0x00, 0x00
+.data1 	0x2c, 0x03, 0x00, 0x00, 0x18, 0x03, 0x00, 0x00
+.data1 	0x04, 0x03, 0x00, 0x00, 0xe8, 0x02, 0x00, 0x00
+.data1 	0xd4, 0x02, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00
+.data1 	0x04, 0x06, 0x00, 0x00, 0x04, 0x06, 0x00, 0x00
+.data1 	0x04, 0x06, 0x00, 0x00, 0x04, 0x06, 0x00, 0x00
+.data1 	0x04, 0x06, 0x00, 0x00, 0x04, 0x06, 0x00, 0x00
+.data1 	0x04, 0x06, 0x00, 0x00, 0x04, 0x06, 0x00, 0x00
+.data1 	0x04, 0x06, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00
+.data1 	0x84, 0x02, 0x00, 0x00, 0x68, 0x02, 0x00, 0x00
+.data1 	0x54, 0x02, 0x00, 0x00, 0x48, 0x02, 0x00, 0x00
+.data1 	0x30, 0x02, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00
+.data1 	0x00, 0x02, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00
+.data1 	0xdc, 0x01, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00
+.data1 	0xb0, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00
+.data1 	0x84, 0x01, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00
+.data1 	0x60, 0x01, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00
+.data1 	0x2c, 0x01, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00
+.data1 	0xec, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00
+.data1 	0xbc, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00
+.data1 	0x88, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00
+.data1 	0x50, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0e, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x0f, 0x00, 0x00, 0x00, 0x62, 0x6f, 0x6f, 0x74
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x10, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x11, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x12, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x30, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x13, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x30, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x14, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x30, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x15, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x30, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x16, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x17, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x31, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x18, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x31, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x19, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x31, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x1a, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x31, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x1b, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x1c, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x32, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x1d, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x32, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x1e, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x32, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x1f, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x32, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x20, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x21, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x33, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x22, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x33, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x23, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x33, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x24, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x30
+.data1 	0x70, 0x33, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x25, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x26, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x27, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x30, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x28, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x30, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x29, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x30, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x2a, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x30, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x2b, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x2c, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x31, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x2d, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x31, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x2e, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x31, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x2f, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x31, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x30, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x31, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x32, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x32, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x32, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x33, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x32, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x34, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x32, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x35, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x36, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x33, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x37, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x33, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x38, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x33, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x39, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x31
+.data1 	0x70, 0x33, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x3a, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x3b, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x3c, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x30, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x3d, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x30, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x3e, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x30, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x3f, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x30, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x40, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x41, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x31, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x42, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x31, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x43, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x31, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x44, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x31, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x45, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x46, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x32, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x47, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x32, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x48, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x32, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x49, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x32, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4a, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4b, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x33, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4c, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x33, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4d, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x33, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4e, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x32
+.data1 	0x70, 0x33, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x4f, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x50, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x51, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x30, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x52, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x30, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x53, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x30, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x54, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x30, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x55, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x56, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x31, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x57, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x31, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x58, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x31, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x59, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x31, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5a, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5b, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x32, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5c, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x32, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5d, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x32, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5e, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x32, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x5f, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x60, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x33, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x61, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x33, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x62, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x33, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x63, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x33
+.data1 	0x70, 0x33, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x64, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x65, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x66, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x30, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x67, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x30, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x68, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x30, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x69, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x30, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x6a, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x6b, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x31, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x6c, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x31, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x6d, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x31, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x6e, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x31, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x6f, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x70, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x32, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x71, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x32, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x72, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x32, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x73, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x32, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x74, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x75, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x33, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x76, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x33, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x77, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x33, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x78, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x34
+.data1 	0x70, 0x33, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x79, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x7a, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x7b, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x30, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x7c, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x30, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x7d, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x30, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x7e, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x30, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x7f, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x80, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x31, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x81, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x31, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x82, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x31, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x83, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x31, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x84, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x85, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x32, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x86, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x32, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x87, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x32, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x88, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x32, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x89, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8a, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x33, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8b, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x33, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8c, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x33, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8d, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x35
+.data1 	0x70, 0x33, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8e, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x8f, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x90, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x30, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x91, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x30, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x92, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x30, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x93, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x30, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x94, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x95, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x31, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x96, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x31, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x97, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x31, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x98, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x31, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x99, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x9a, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x32, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x9b, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x32, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x9c, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x32, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x9d, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x32, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x9e, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x9f, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x33, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa0, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x33, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa1, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x33, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa2, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x36
+.data1 	0x70, 0x33, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa3, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa4, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa5, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x30, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa6, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x30, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa7, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x30, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa8, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x30, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xa9, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xaa, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x31, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xab, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x31, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xac, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x31, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xad, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x31, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xae, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xaf, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x32, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb0, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x32, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb1, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x32, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb2, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x32, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb3, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb4, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x33, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb5, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x33, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb6, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x33, 0x73, 0x32, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb7, 0x00, 0x00, 0x00, 0x63, 0x30, 0x64, 0x37
+.data1 	0x70, 0x33, 0x73, 0x33, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb8, 0x00, 0x00, 0x00, 0x63, 0x6d, 0x6f, 0x73
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xb9, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6e, 0x73
+.data1 	0x6f, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xba, 0x00, 0x00, 0x00, 0x66, 0x64, 0x30, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xbb, 0x00, 0x00, 0x00, 0x6b, 0x62, 0x64, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xbc, 0x00, 0x00, 0x00, 0x6b, 0x62, 0x64, 0x61
+.data1 	0x75, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xbd, 0x00, 0x00, 0x00, 0x6b, 0x6c, 0x6f, 0x67
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xbe, 0x00, 0x00, 0x00, 0x6b, 0x6d, 0x65, 0x6d
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xbf, 0x00, 0x00, 0x00, 0x6c, 0x6f, 0x67, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc0, 0x00, 0x00, 0x00, 0x6c, 0x70, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc1, 0x00, 0x00, 0x00, 0x6d, 0x65, 0x6d, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc2, 0x00, 0x00, 0x00, 0x6e, 0x75, 0x6c, 0x6c
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc3, 0x00, 0x00, 0x00, 0x72, 0x61, 0x6d, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc4, 0x00, 0x00, 0x00, 0x72, 0x61, 0x6e, 0x64
+.data1 	0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc5, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x63
+.data1 	0x75, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc6, 0x00, 0x00, 0x00, 0x74, 0x74, 0x79, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc7, 0x00, 0x00, 0x00, 0x74, 0x74, 0x79, 0x30
+.data1 	0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc8, 0x00, 0x00, 0x00, 0x74, 0x74, 0x79, 0x30
+.data1 	0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xc9, 0x00, 0x00, 0x00, 0x74, 0x74, 0x79, 0x30
+.data1 	0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xca, 0x00, 0x00, 0x00, 0x74, 0x74, 0x79, 0x30
+.data1 	0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xcb, 0x00, 0x00, 0x00, 0x74, 0x74, 0x79, 0x63
+.data1 	0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xcc, 0x00, 0x00, 0x00, 0x74, 0x74, 0x79, 0x63
+.data1 	0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xcd, 0x00, 0x00, 0x00, 0x74, 0x74, 0x79, 0x63
+.data1 	0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xce, 0x00, 0x00, 0x00, 0x75, 0x72, 0x61, 0x6e
+.data1 	0x64, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xcf, 0x00, 0x00, 0x00, 0x76, 0x69, 0x64, 0x65
+.data1 	0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd0, 0x00, 0x00, 0x00, 0x7a, 0x65, 0x72, 0x6f
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd1, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x01, 0x00, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd2, 0x00, 0x00, 0x00, 0x6d, 0x74, 0x61, 0x62
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0xd3, 0x00, 0x00, 0x00, 0x72, 0x63, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x2f, 0x64, 0x65, 0x76, 0x2f, 0x69, 0x6d, 0x67
+.data1 	0x72, 0x64, 0x20, 0x2f, 0x20, 0x33, 0x20, 0x72
+.data1 	0x77, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x23, 0x21, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73
+.data1 	0x68, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x2d, 0x65
+.data1 	0x0a, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x65
+.data1 	0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x75, 0x70
+.data1 	0x20, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x70, 0x63
+.data1 	0x69, 0x0a, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73
+.data1 	0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x75
+.data1 	0x70, 0x20, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x66
+.data1 	0x6c, 0x6f, 0x70, 0x70, 0x79, 0x20, 0x2d, 0x64
+.data1 	0x65, 0x76, 0x20, 0x2f, 0x64, 0x65, 0x76, 0x2f
+.data1 	0x66, 0x64, 0x30, 0x0a, 0x69, 0x66, 0x20, 0x5b
+.data1 	0x20, 0x58, 0x60, 0x2f, 0x62, 0x69, 0x6e, 0x2f
+.data1 	0x73, 0x79, 0x73, 0x65, 0x6e, 0x76, 0x20, 0x62
+.data1 	0x69, 0x6f, 0x73, 0x5f, 0x77, 0x69, 0x6e, 0x69
+.data1 	0x60, 0x20, 0x3d, 0x20, 0x58, 0x79, 0x65, 0x73
+.data1 	0x20, 0x5d, 0x0a, 0x74, 0x68, 0x65, 0x6e, 0x0a
+.data1 	0x09, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x55, 0x73
+.data1 	0x69, 0x6e, 0x67, 0x20, 0x62, 0x69, 0x6f, 0x73
+.data1 	0x5f, 0x77, 0x69, 0x6e, 0x69, 0x2e, 0x0a, 0x09
+.data1 	0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x65, 0x72
+.data1 	0x76, 0x69, 0x63, 0x65, 0x20, 0x75, 0x70, 0x20
+.data1 	0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x62, 0x69, 0x6f
+.data1 	0x73, 0x5f, 0x77, 0x69, 0x6e, 0x69, 0x20, 0x2d
+.data1 	0x64, 0x65, 0x76, 0x20, 0x2f, 0x64, 0x65, 0x76
+.data1 	0x2f, 0x63, 0x30, 0x64, 0x30, 0x0a, 0x65, 0x6c
+.data1 	0x73, 0x65, 0x0a, 0x09, 0x2f, 0x62, 0x69, 0x6e
+.data1 	0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65
+.data1 	0x20, 0x75, 0x70, 0x20, 0x2f, 0x62, 0x69, 0x6e
+.data1 	0x2f, 0x61, 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x69
+.data1 	0x20, 0x2d, 0x64, 0x65, 0x76, 0x20, 0x2f, 0x64
+.data1 	0x65, 0x76, 0x2f, 0x63, 0x30, 0x64, 0x30, 0x0a
+.data1 	0x66, 0x69, 0x0a, 0x0a, 0x72, 0x6f, 0x6f, 0x74
+.data1 	0x64, 0x65, 0x76, 0x3d, 0x60, 0x73, 0x79, 0x73
+.data1 	0x65, 0x6e, 0x76, 0x20, 0x72, 0x6f, 0x6f, 0x74
+.data1 	0x64, 0x65, 0x76, 0x60, 0x20, 0x7c, 0x7c, 0x20
+.data1 	0x65, 0x63, 0x68, 0x6f, 0x20, 0x27, 0x4e, 0x6f
+.data1 	0x20, 0x72, 0x6f, 0x6f, 0x74, 0x64, 0x65, 0x76
+.data1 	0x3f, 0x27, 0x0a, 0x72, 0x6f, 0x6f, 0x74, 0x64
+.data1 	0x65, 0x76, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x60
+.data1 	0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x64, 0x65, 0x76
+.data1 	0x32, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x22, 0x24
+.data1 	0x72, 0x6f, 0x6f, 0x74, 0x64, 0x65, 0x76, 0x22
+.data1 	0x60, 0x20, 0x7c, 0x7c, 0x0a, 0x09, 0x7b, 0x20
+.data1 	0x65, 0x63, 0x68, 0x6f, 0x20, 0x27, 0x4e, 0x6f
+.data1 	0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20
+.data1 	0x6e, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72
+.data1 	0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x64, 0x65
+.data1 	0x76, 0x69, 0x63, 0x65, 0x27, 0x3b, 0x20, 0x65
+.data1 	0x78, 0x69, 0x74, 0x20, 0x31, 0x3b, 0x20, 0x7d
+.data1 	0x0a, 0x0a, 0x69, 0x66, 0x20, 0x73, 0x79, 0x73
+.data1 	0x65, 0x6e, 0x76, 0x20, 0x63, 0x64, 0x70, 0x72
+.data1 	0x6f, 0x62, 0x65, 0x72, 0x6f, 0x6f, 0x74, 0x20
+.data1 	0x3e, 0x2f, 0x64, 0x65, 0x76, 0x2f, 0x6e, 0x75
+.data1 	0x6c, 0x6c, 0x0a, 0x74, 0x68, 0x65, 0x6e, 0x0a
+.data1 	0x09, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x0a, 0x09
+.data1 	0x65, 0x63, 0x68, 0x6f, 0x20, 0x27, 0x4c, 0x6f
+.data1 	0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f
+.data1 	0x72, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x20, 0x43
+.data1 	0x44, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20
+.data1 	0x6d, 0x61, 0x79, 0x20, 0x74, 0x61, 0x6b, 0x65
+.data1 	0x20, 0x61, 0x20, 0x6d, 0x69, 0x6e, 0x75, 0x74
+.data1 	0x65, 0x2e, 0x27, 0x0a, 0x09, 0x65, 0x63, 0x68
+.data1 	0x6f, 0x20, 0x27, 0x50, 0x6c, 0x65, 0x61, 0x73
+.data1 	0x65, 0x20, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65
+.data1 	0x20, 0x61, 0x6e, 0x79, 0x20, 0x65, 0x72, 0x72
+.data1 	0x6f, 0x72, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61
+.data1 	0x67, 0x65, 0x73, 0x2e, 0x27, 0x0a, 0x09, 0x65
+.data1 	0x63, 0x68, 0x6f, 0x0a, 0x09, 0x63, 0x64, 0x64
+.data1 	0x65, 0x76, 0x3d, 0x60, 0x63, 0x64, 0x70, 0x72
+.data1 	0x6f, 0x62, 0x65, 0x60, 0x20, 0x7c, 0x7c, 0x20
+.data1 	0x7b, 0x20, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x27
+.data1 	0x4e, 0x6f, 0x20, 0x43, 0x44, 0x20, 0x66, 0x6f
+.data1 	0x75, 0x6e, 0x64, 0x27, 0x3b, 0x20, 0x65, 0x78
+.data1 	0x69, 0x74, 0x20, 0x31, 0x3b, 0x20, 0x7d, 0x0a
+.data1 	0x09, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x20
+.data1 	0x63, 0x64, 0x64, 0x65, 0x76, 0x0a, 0x09, 0x65
+.data1 	0x63, 0x68, 0x6f, 0x20, 0x22, 0x4c, 0x6f, 0x61
+.data1 	0x64, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x61, 0x6d
+.data1 	0x64, 0x69, 0x73, 0x6b, 0x20, 0x66, 0x72, 0x6f
+.data1 	0x6d, 0x20, 0x24, 0x7b, 0x63, 0x64, 0x64, 0x65
+.data1 	0x76, 0x7d, 0x70, 0x31, 0x22, 0x0a, 0x09, 0x6c
+.data1 	0x6f, 0x61, 0x64, 0x72, 0x61, 0x6d, 0x64, 0x69
+.data1 	0x73, 0x6b, 0x20, 0x22, 0x24, 0x63, 0x64, 0x64
+.data1 	0x65, 0x76, 0x22, 0x70, 0x31, 0x0a, 0x65, 0x6c
+.data1 	0x69, 0x66, 0x20, 0x5b, 0x20, 0x22, 0x24, 0x72
+.data1 	0x6f, 0x6f, 0x74, 0x64, 0x65, 0x76, 0x6e, 0x61
+.data1 	0x6d, 0x65, 0x22, 0x20, 0x3d, 0x20, 0x22, 0x2f
+.data1 	0x64, 0x65, 0x76, 0x2f, 0x72, 0x61, 0x6d, 0x22
+.data1 	0x20, 0x5d, 0x0a, 0x74, 0x68, 0x65, 0x6e, 0x0a
+.data1 	0x09, 0x72, 0x61, 0x6d, 0x69, 0x6d, 0x61, 0x67
+.data1 	0x65, 0x64, 0x65, 0x76, 0x3d, 0x60, 0x73, 0x79
+.data1 	0x73, 0x65, 0x6e, 0x76, 0x20, 0x72, 0x61, 0x6d
+.data1 	0x69, 0x6d, 0x61, 0x67, 0x65, 0x64, 0x65, 0x76
+.data1 	0x60, 0x20, 0x7c, 0x7c, 0x0a, 0x09, 0x09, 0x7b
+.data1 	0x20, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x27, 0x72
+.data1 	0x61, 0x6d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x64
+.data1 	0x65, 0x76, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66
+.data1 	0x6f, 0x75, 0x6e, 0x64, 0x27, 0x3b, 0x20, 0x65
+.data1 	0x78, 0x69, 0x74, 0x20, 0x31, 0x3b, 0x20, 0x7d
+.data1 	0x0a, 0x09, 0x72, 0x61, 0x6d, 0x69, 0x6d, 0x61
+.data1 	0x67, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x60
+.data1 	0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x64, 0x65, 0x76
+.data1 	0x32, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x22, 0x24
+.data1 	0x72, 0x61, 0x6d, 0x69, 0x6d, 0x61, 0x67, 0x65
+.data1 	0x64, 0x65, 0x76, 0x22, 0x60, 0x20, 0x7c, 0x7c
+.data1 	0x0a, 0x09, 0x09, 0x7b, 0x20, 0x65, 0x63, 0x68
+.data1 	0x6f, 0x20, 0x27, 0x4e, 0x6f, 0x20, 0x64, 0x65
+.data1 	0x76, 0x69, 0x63, 0x65, 0x20, 0x6e, 0x61, 0x6d
+.data1 	0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x61
+.data1 	0x6d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x64, 0x65
+.data1 	0x76, 0x27, 0x3b, 0x20, 0x65, 0x78, 0x69, 0x74
+.data1 	0x20, 0x31, 0x3b, 0x20, 0x7d, 0x0a, 0x09, 0x65
+.data1 	0x63, 0x68, 0x6f, 0x20, 0x22, 0x4c, 0x6f, 0x61
+.data1 	0x64, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x61, 0x6d
+.data1 	0x64, 0x69, 0x73, 0x6b, 0x20, 0x66, 0x72, 0x6f
+.data1 	0x6d, 0x20, 0x24, 0x72, 0x61, 0x6d, 0x69, 0x6d
+.data1 	0x61, 0x67, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22
+.data1 	0x0a, 0x09, 0x6c, 0x6f, 0x61, 0x64, 0x72, 0x61
+.data1 	0x6d, 0x64, 0x69, 0x73, 0x6b, 0x20, 0x22, 0x24
+.data1 	0x72, 0x61, 0x6d, 0x69, 0x6d, 0x61, 0x67, 0x65
+.data1 	0x6e, 0x61, 0x6d, 0x65, 0x22, 0x0a, 0x66, 0x69
+.data1 	0x0a, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x22, 0x52
+.data1 	0x6f, 0x6f, 0x74, 0x20, 0x64, 0x65, 0x76, 0x69
+.data1 	0x63, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20
+.data1 	0x69, 0x73, 0x20, 0x24, 0x72, 0x6f, 0x6f, 0x74
+.data1 	0x64, 0x65, 0x76, 0x6e, 0x61, 0x6d, 0x65, 0x22
+.data1 	0x0a, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x6e, 0x65
+.data1 	0x77, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x22, 0x24
+.data1 	0x72, 0x6f, 0x6f, 0x74, 0x64, 0x65, 0x76, 0x6e
+.data1 	0x61, 0x6d, 0x65, 0x22, 0x0a, 0x65, 0x78, 0x65
+.data1 	0x63, 0x20, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73
+.data1 	0x68, 0x20, 0x2f, 0x65, 0x74, 0x63, 0x2f, 0x72
+.data1 	0x63, 0x20, 0x22, 0x24, 0x40, 0x22, 0x0a, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.data1 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Index: /trunk/minix/drivers/memory/ramdisk/mtab
===================================================================
--- /trunk/minix/drivers/memory/ramdisk/mtab	(revision 9)
+++ /trunk/minix/drivers/memory/ramdisk/mtab	(revision 9)
@@ -0,0 +1,1 @@
+/dev/imgrd / 3 rw
Index: /trunk/minix/drivers/memory/ramdisk/proto
===================================================================
--- /trunk/minix/drivers/memory/ramdisk/proto	(revision 9)
+++ /trunk/minix/drivers/memory/ramdisk/proto	(revision 9)
@@ -0,0 +1,24 @@
+boot 
+140 310
+d--755 0 0
+	bin d--755 0 0
+		at_wini ---755 0 0 at_wini
+		bios_wini ---755 0 0 bios_wini
+		cdprobe ---755 0 0 cdprobe
+		dev2name ---755 0 0 dev2name
+		floppy ---755 0 0 floppy
+		loadramdisk ---755 0 0 loadramdisk
+		newroot ---755 0 0 newroot
+		pci ---755 0 0 pci
+		sh ---755 0 0 sh
+		service ---755 0 0 service
+		sysenv ---755 0 0 sysenv
+	$
+	dev d--755 0 0
+@DEV@
+	$
+	etc d--755 0 0
+		mtab ---644 0 0 mtab
+		rc ---755 0 0 rc
+	$
+$
Index: /trunk/minix/drivers/memory/ramdisk/proto.sh
===================================================================
--- /trunk/minix/drivers/memory/ramdisk/proto.sh	(revision 9)
+++ /trunk/minix/drivers/memory/ramdisk/proto.sh	(revision 9)
@@ -0,0 +1,10 @@
+#!/bin/sh
+sed -n '1,/@DEV/p' <proto  | grep -v @DEV@
+(
+cd /dev
+ls -aln | grep '^[bc]' | egrep -v ' (fd1|fd0p|tcp|eth|ip|udp|tty[pq]|pty)' | \
+sed	-e 's/^[bc]/& /' -e 's/rw-/6/g' -e 's/r--/4/g' \
+	-e 's/-w-/2/g'  -e 's/---/0/g' | \
+awk '{ printf "\t\t%s %s--%s %d %d %d %d \n", $11, $1, $2, $4, $5, $6, $7; }'
+)
+sed -n '/@DEV/,$p' <proto  | grep -v @DEV@
Index: /trunk/minix/drivers/memory/ramdisk/rc
===================================================================
--- /trunk/minix/drivers/memory/ramdisk/rc	(revision 9)
+++ /trunk/minix/drivers/memory/ramdisk/rc	(revision 9)
@@ -0,0 +1,38 @@
+#!/bin/sh
+set -e
+/bin/service up /bin/pci
+/bin/service up /bin/floppy -dev /dev/fd0
+if [ X`/bin/sysenv bios_wini` = Xyes ]
+then
+	echo Using bios_wini.
+	/bin/service up /bin/bios_wini -dev /dev/c0d0
+else
+	/bin/service up /bin/at_wini -dev /dev/c0d0
+fi
+
+rootdev=`sysenv rootdev` || echo 'No rootdev?'
+rootdevname=`/bin/dev2name "$rootdev"` ||
+	{ echo 'No device name for root device'; exit 1; }
+
+if sysenv cdproberoot >/dev/null
+then
+	echo 
+	echo 'Looking for boot CD. This may take a minute.'
+	echo 'Please ignore any error messages.'
+	echo
+	cddev=`cdprobe` || { echo 'No CD found'; exit 1; }
+	export cddev
+	echo "Loading ramdisk from ${cddev}p1"
+	loadramdisk "$cddev"p1
+elif [ "$rootdevname" = "/dev/ram" ]
+then
+	ramimagedev=`sysenv ramimagedev` ||
+		{ echo 'ramimagedev not found'; exit 1; }
+	ramimagename=`/bin/dev2name "$ramimagedev"` ||
+		{ echo 'No device name for ramimagedev'; exit 1; }
+	echo "Loading ramdisk from $ramimagename"
+	loadramdisk "$ramimagename"
+fi
+echo "Root device name is $rootdevname"
+/bin/newroot "$rootdevname"
+exec /bin/sh /etc/rc "$@"
Index: /trunk/minix/drivers/pci/.depend
===================================================================
--- /trunk/minix/drivers/pci/.depend	(revision 9)
+++ /trunk/minix/drivers/pci/.depend	(revision 9)
@@ -0,0 +1,96 @@
+
+main.o:	../drivers.h
+main.o:	/usr/include/ansi.h
+main.o:	/usr/include/errno.h
+main.o:	/usr/include/ibm/bios.h
+main.o:	/usr/include/ibm/interrupt.h
+main.o:	/usr/include/ibm/pci.h
+main.o:	/usr/include/ibm/ports.h
+main.o:	/usr/include/limits.h
+main.o:	/usr/include/minix/bitmap.h
+main.o:	/usr/include/minix/callnr.h
+main.o:	/usr/include/minix/com.h
+main.o:	/usr/include/minix/config.h
+main.o:	/usr/include/minix/const.h
+main.o:	/usr/include/minix/devio.h
+main.o:	/usr/include/minix/dmap.h
+main.o:	/usr/include/minix/ipc.h
+main.o:	/usr/include/minix/sys_config.h
+main.o:	/usr/include/minix/syslib.h
+main.o:	/usr/include/minix/sysutil.h
+main.o:	/usr/include/minix/type.h
+main.o:	/usr/include/signal.h
+main.o:	/usr/include/stddef.h
+main.o:	/usr/include/stdlib.h
+main.o:	/usr/include/string.h
+main.o:	/usr/include/sys/dir.h
+main.o:	/usr/include/sys/types.h
+main.o:	/usr/include/unistd.h
+main.o:	main.c
+main.o:	pci.h
+
+pci.o:	../drivers.h
+pci.o:	/usr/include/ansi.h
+pci.o:	/usr/include/assert.h
+pci.o:	/usr/include/errno.h
+pci.o:	/usr/include/ibm/bios.h
+pci.o:	/usr/include/ibm/interrupt.h
+pci.o:	/usr/include/ibm/pci.h
+pci.o:	/usr/include/ibm/ports.h
+pci.o:	/usr/include/limits.h
+pci.o:	/usr/include/minix/bitmap.h
+pci.o:	/usr/include/minix/callnr.h
+pci.o:	/usr/include/minix/com.h
+pci.o:	/usr/include/minix/config.h
+pci.o:	/usr/include/minix/const.h
+pci.o:	/usr/include/minix/devio.h
+pci.o:	/usr/include/minix/dmap.h
+pci.o:	/usr/include/minix/ipc.h
+pci.o:	/usr/include/minix/sys_config.h
+pci.o:	/usr/include/minix/syslib.h
+pci.o:	/usr/include/minix/sysutil.h
+pci.o:	/usr/include/minix/type.h
+pci.o:	/usr/include/signal.h
+pci.o:	/usr/include/stddef.h
+pci.o:	/usr/include/stdio.h
+pci.o:	/usr/include/stdlib.h
+pci.o:	/usr/include/string.h
+pci.o:	/usr/include/sys/dir.h
+pci.o:	/usr/include/sys/types.h
+pci.o:	/usr/include/sys/vm.h
+pci.o:	/usr/include/unistd.h
+pci.o:	pci.c
+pci.o:	pci.h
+pci.o:	pci_amd.h
+pci.o:	pci_intel.h
+pci.o:	pci_sis.h
+pci.o:	pci_via.h
+
+pci_table.o:	../drivers.h
+pci_table.o:	/usr/include/ansi.h
+pci_table.o:	/usr/include/errno.h
+pci_table.o:	/usr/include/ibm/bios.h
+pci_table.o:	/usr/include/ibm/interrupt.h
+pci_table.o:	/usr/include/ibm/ports.h
+pci_table.o:	/usr/include/limits.h
+pci_table.o:	/usr/include/minix/bitmap.h
+pci_table.o:	/usr/include/minix/callnr.h
+pci_table.o:	/usr/include/minix/com.h
+pci_table.o:	/usr/include/minix/config.h
+pci_table.o:	/usr/include/minix/const.h
+pci_table.o:	/usr/include/minix/devio.h
+pci_table.o:	/usr/include/minix/dmap.h
+pci_table.o:	/usr/include/minix/ipc.h
+pci_table.o:	/usr/include/minix/sys_config.h
+pci_table.o:	/usr/include/minix/syslib.h
+pci_table.o:	/usr/include/minix/sysutil.h
+pci_table.o:	/usr/include/minix/type.h
+pci_table.o:	/usr/include/signal.h
+pci_table.o:	/usr/include/stddef.h
+pci_table.o:	/usr/include/stdlib.h
+pci_table.o:	/usr/include/string.h
+pci_table.o:	/usr/include/sys/dir.h
+pci_table.o:	/usr/include/sys/types.h
+pci_table.o:	/usr/include/unistd.h
+pci_table.o:	pci.h
+pci_table.o:	pci_table.c
Index: /trunk/minix/drivers/pci/Makefile
===================================================================
--- /trunk/minix/drivers/pci/Makefile	(revision 9)
+++ /trunk/minix/drivers/pci/Makefile	(revision 9)
@@ -0,0 +1,40 @@
+# Makefile for PCI support
+DRIVER = pci
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+CC =	cc
+CFLAGS = -I$i
+LDFLAGS = -i 
+LIBS = -lsys -lsysutil -ltimers
+
+OBJ = main.o pci.o pci_table.o
+
+# build local binary
+all build:	$(DRIVER)
+$(DRIVER):	$(OBJ) 
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+	install -S 4096 $(DRIVER)
+
+# install with other drivers
+install:	/usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER):	$(DRIVER)
+	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f *.o *.bak $(DRIVER)
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/pci/main.c
===================================================================
--- /trunk/minix/drivers/pci/main.c	(revision 9)
+++ /trunk/minix/drivers/pci/main.c	(revision 9)
@@ -0,0 +1,447 @@
+/*
+main.c
+*/
+
+#include "../drivers.h"
+
+#include <ibm/pci.h>
+
+#include "pci.h"
+
+#define NR_DRIVERS	16
+
+PRIVATE struct name
+{
+	char name[M3_STRING];
+	int tasknr;
+} names[NR_DRIVERS];
+
+FORWARD _PROTOTYPE( void do_init, (message *mp)				);
+FORWARD _PROTOTYPE( void do_sig_handler, (void)				);
+FORWARD _PROTOTYPE( void do_first_dev, (message *mp)			);
+FORWARD _PROTOTYPE( void do_next_dev, (message *mp)			);
+FORWARD _PROTOTYPE( void do_find_dev, (message *mp)			);
+FORWARD _PROTOTYPE( void do_ids, (message *mp)				);
+FORWARD _PROTOTYPE( void do_dev_name, (message *mp)			);
+FORWARD _PROTOTYPE( void do_slot_name, (message *mp)			);
+FORWARD _PROTOTYPE( void do_reserve, (message *mp)			);
+FORWARD _PROTOTYPE( void do_attr_r8, (message *mp)			);
+FORWARD _PROTOTYPE( void do_attr_r16, (message *mp)			);
+FORWARD _PROTOTYPE( void do_attr_r32, (message *mp)			);
+FORWARD _PROTOTYPE( void do_attr_w8, (message *mp)			);
+FORWARD _PROTOTYPE( void do_attr_w16, (message *mp)			);
+FORWARD _PROTOTYPE( void do_attr_w32, (message *mp)			);
+FORWARD _PROTOTYPE( void do_rescan_bus, (message *mp)			);
+
+int main(void)
+{
+	int i, r;
+	message m;
+
+	pci_init();
+
+	for (i= 0; i<NR_DRIVERS; i++)
+		names[i].tasknr= ANY;
+
+	for(;;)
+	{
+		r= receive(ANY, &m);
+		if (r < 0)
+		{
+			printf("PCI: receive from ANY failed: %d\n", r);
+			break;
+		}
+		switch(m.m_type)
+		{
+		case BUSC_PCI_INIT: do_init(&m); break;
+		case BUSC_PCI_FIRST_DEV: do_first_dev(&m); break;
+		case BUSC_PCI_NEXT_DEV: do_next_dev(&m); break;
+		case BUSC_PCI_FIND_DEV: do_find_dev(&m); break;
+		case BUSC_PCI_IDS: do_ids(&m); break;
+		case BUSC_PCI_DEV_NAME: do_dev_name(&m); break;
+		case BUSC_PCI_SLOT_NAME: do_slot_name(&m); break;
+		case BUSC_PCI_RESERVE: do_reserve(&m); break;
+		case BUSC_PCI_ATTR_R8: do_attr_r8(&m); break;
+		case BUSC_PCI_ATTR_R16: do_attr_r16(&m); break;
+		case BUSC_PCI_ATTR_R32: do_attr_r32(&m); break;
+		case BUSC_PCI_ATTR_W8: do_attr_w8(&m); break;
+		case BUSC_PCI_ATTR_W16: do_attr_w16(&m); break;
+		case BUSC_PCI_ATTR_W32: do_attr_w32(&m); break;
+		case BUSC_PCI_RESCAN: do_rescan_bus(&m); break;
+		case PROC_EVENT: do_sig_handler(); break;
+		default:
+			printf("PCI: got message from %d, type %d\n",
+				m.m_source, m.m_type);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/*===========================================================================*
+ *				do_sig_handler                               *
+ *===========================================================================*/
+PRIVATE void do_sig_handler()
+{
+  sigset_t sigset;
+  int sig;
+
+  /* Try to obtain signal set from PM. */
+  if (getsigset(&sigset) != 0) return;
+
+  /* Check for known signals. */
+  if (sigismember(&sigset, SIGTERM)) {
+      exit(0);
+  }
+}
+
+PRIVATE void do_init(mp)
+message *mp;
+{
+	int i, r, empty;
+
+#if DEBUG
+	printf("pci_init: called by '%s'\n", mp->m3_ca1);
+#endif
+	empty= -1;
+	for (i= 0; i<NR_DRIVERS; i++)
+	{
+		if (empty == -1 && names[i].tasknr == ANY)
+			empty= i;
+		if (strcmp(names[i].name, mp->m3_ca1) == 0)
+			break;
+	}
+	if (i < NR_DRIVERS)
+		pci_release(names[i].name);
+	else
+	{
+		i= empty;
+		strcpy(names[i].name, mp->m3_ca1);
+	}
+	names[i].tasknr= mp->m_source;
+
+	mp->m_type= 0;
+	r= send(mp->m_source, mp);
+	if (r != 0)
+		printf("do_init: unable to send to %d: %d\n", mp->m_source, r);
+}
+
+PRIVATE void do_first_dev(mp)
+message *mp;
+{
+	int r, devind;
+	u16_t vid, did;
+
+	r= pci_first_dev(&devind, &vid, &did);
+	if (r == 1)
+	{
+		mp->m1_i1= devind;
+		mp->m1_i2= vid;
+		mp->m1_i3= did;
+	}
+	mp->m_type= r;
+	r= send(mp->m_source, mp);
+	if (r != 0)
+	{
+		printf("do_first_dev: unable to send to %d: %d\n",
+			mp->m_source, r);
+	}
+}
+
+PRIVATE void do_next_dev(mp)
+message *mp;
+{
+	int r, devind;
+	u16_t vid, did;
+
+	devind= mp->m1_i1;
+
+	r= pci_next_dev(&devind, &vid, &did);
+	if (r == 1)
+	{
+		mp->m1_i1= devind;
+		mp->m1_i2= vid;
+		mp->m1_i3= did;
+	}
+	mp->m_type= r;
+	r= send(mp->m_source, mp);
+	if (r != 0)
+	{
+		printf("do_next_dev: unable to send to %d: %d\n",
+			mp->m_source, r);
+	}
+}
+
+PRIVATE void do_find_dev(mp)
+message *mp;
+{
+	int r, devind;
+	u8_t bus, dev, func;
+
+	bus= mp->m1_i1;
+	dev= mp->m1_i2;
+	func= mp->m1_i3;
+
+	r= pci_find_dev(bus, dev, func, &devind);
+	if (r == 1)
+		mp->m1_i1= devind;
+	mp->m_type= r;
+	r= send(mp->m_source, mp);
+	if (r != 0)
+	{
+		printf("do_find_dev: unable to send to %d: %d\n",
+			mp->m_source, r);
+	}
+}
+
+PRIVATE void do_ids(mp)
+message *mp;
+{
+	int r, devind;
+	u16_t vid, did;
+
+	devind= mp->m1_i1;
+
+	pci_ids(devind, &vid, &did);
+	mp->m1_i1= vid;
+	mp->m1_i2= did;
+	mp->m_type= OK;
+	r= send(mp->m_source, mp);
+	if (r != 0)
+	{
+		printf("do_ids: unable to send to %d: %d\n",
+			mp->m_source, r);
+	}
+}
+
+PRIVATE void do_dev_name(mp)
+message *mp;
+{
+	int r, name_len, len;
+	u16_t vid, did;
+	char *name_ptr, *name;
+
+	vid= mp->m1_i1;
+	did= mp->m1_i2;
+	name_len= mp->m1_i3;
+	name_ptr= mp->m1_p1;
+
+	name= pci_dev_name(vid, did);
+	if (name == NULL)
+	{
+		/* No name */
+		r= ENOENT;
+	}
+	else
+	{
+		len= strlen(name)+1;
+		if (len > name_len)
+			len= name_len;
+		r= sys_vircopy(SELF, D, (vir_bytes)name, mp->m_source, D,
+			(vir_bytes)name_ptr, len);
+	}
+
+	mp->m_type= r;
+	r= send(mp->m_source, mp);
+	if (r != 0)
+	{
+		printf("do_dev_name: unable to send to %d: %d\n",
+			mp->m_source, r);
+	}
+}
+
+PRIVATE void do_slot_name(mp)
+message *mp;
+{
+	int r, devind, name_len, len;
+	char *name_ptr, *name;
+
+	devind= mp->m1_i1;
+	name_len= mp->m1_i2;
+	name_ptr= mp->m1_p1;
+
+	name= pci_slot_name(devind);
+
+	len= strlen(name)+1;
+	if (len > name_len)
+		len= name_len;
+	r= sys_vircopy(SELF, D, (vir_bytes)name, mp->m_source, D,
+		(vir_bytes)name_ptr, len);
+
+	mp->m_type= r;
+	r= send(mp->m_source, mp);
+	if (r != 0)
+	{
+		printf("do_slot_name: unable to send to %d: %d\n",
+			mp->m_source, r);
+	}
+}
+
+PRIVATE void do_reserve(mp)
+message *mp;
+{
+	int i, r, devind;
+
+	/* Find the name of the caller */
+	for (i= 0; i<NR_DRIVERS; i++)
+	{
+		if (names[i].tasknr == mp->m_source)
+			break;
+	}
+	if (i >= NR_DRIVERS)
+	{
+		printf("pci`do_reserve: task %d did not call pci_init\n",
+			mp->m_source);
+		return;
+	}
+
+	devind= mp->m1_i1;
+
+	pci_reserve3(devind, mp->m_source, names[i].name);
+	mp->m_type= OK;
+	r= send(mp->m_source, mp);
+	if (r != 0)
+	{
+		printf("do_reserve: unable to send to %d: %d\n",
+			mp->m_source, r);
+	}
+}
+
+PRIVATE void do_attr_r8(mp)
+message *mp;
+{
+	int r, devind, port;
+	u8_t v;
+
+	devind= mp->m2_i1;
+	port= mp->m2_i2;
+
+	v= pci_attr_r8(devind, port);
+	mp->m2_l1= v;
+	mp->m_type= OK;
+	r= send(mp->m_source, mp);
+	if (r != 0)
+	{
+		printf("do_attr_r8: unable to send to %d: %d\n",
+			mp->m_source, r);
+	}
+}
+
+PRIVATE void do_attr_r16(mp)
+message *mp;
+{
+	int r, devind, port;
+	u32_t v;
+
+	devind= mp->m2_i1;
+	port= mp->m2_i2;
+
+	v= pci_attr_r16(devind, port);
+	mp->m2_l1= v;
+	mp->m_type= OK;
+	r= send(mp->m_source, mp);
+	if (r != 0)
+	{
+		printf("do_attr_r16: unable to send to %d: %d\n",
+			mp->m_source, r);
+	}
+}
+
+PRIVATE void do_attr_r32(mp)
+message *mp;
+{
+	int r, devind, port;
+	u32_t v;
+
+	devind= mp->m2_i1;
+	port= mp->m2_i2;
+
+	v= pci_attr_r32(devind, port);
+	mp->m2_l1= v;
+	mp->m_type= OK;
+	r= send(mp->m_source, mp);
+	if (r != 0)
+	{
+		printf("do_attr_r32: unable to send to %d: %d\n",
+			mp->m_source, r);
+	}
+}
+
+PRIVATE void do_attr_w8(mp)
+message *mp;
+{
+	int r, devind, port;
+	u8_t v;
+
+	devind= mp->m2_i1;
+	port= mp->m2_i2;
+	v= mp->m2_l1;
+
+	pci_attr_w8(devind, port, v);
+	mp->m_type= OK;
+	r= send(mp->m_source, mp);
+	if (r != 0)
+	{
+		printf("do_attr_w8: unable to send to %d: %d\n",
+			mp->m_source, r);
+	}
+}
+
+PRIVATE void do_attr_w16(mp)
+message *mp;
+{
+	int r, devind, port;
+	u16_t v;
+
+	devind= mp->m2_i1;
+	port= mp->m2_i2;
+	v= mp->m2_l1;
+
+	pci_attr_w16(devind, port, v);
+	mp->m_type= OK;
+	r= send(mp->m_source, mp);
+	if (r != 0)
+	{
+		printf("do_attr_w16: unable to send to %d: %d\n",
+			mp->m_source, r);
+	}
+}
+
+PRIVATE void do_attr_w32(mp)
+message *mp;
+{
+	int r, devind, port;
+	u32_t v;
+
+	devind= mp->m2_i1;
+	port= mp->m2_i2;
+	v= mp->m2_l1;
+
+	pci_attr_w32(devind, port, v);
+	mp->m_type= OK;
+	r= send(mp->m_source, mp);
+	if (r != 0)
+	{
+		printf("do_attr_w32: unable to send to %d: %d\n",
+			mp->m_source, r);
+	}
+}
+
+PRIVATE void do_rescan_bus(mp)
+message *mp;
+{
+	int r, busnr;
+
+	busnr= mp->m2_i1;
+
+	pci_rescan_bus(busnr);
+	mp->m_type= OK;
+	r= send(mp->m_source, mp);
+	if (r != 0)
+	{
+		printf("do_rescan_bus: unable to send to %d: %d\n",
+			mp->m_source, r);
+	}
+}
+
Index: /trunk/minix/drivers/pci/pci.c
===================================================================
--- /trunk/minix/drivers/pci/pci.c	(revision 9)
+++ /trunk/minix/drivers/pci/pci.c	(revision 9)
@@ -0,0 +1,2433 @@
+#define USER_SPACE 1
+/*
+pci.c
+
+Configure devices on the PCI bus
+
+Created:	Jan 2000 by Philip Homburg <philip@cs.vu.nl>
+*/
+
+#include "../drivers.h"
+#define	NDEBUG			/* disable assertions */
+#include <assert.h>
+#include <ibm/pci.h>
+#include <sys/vm.h>
+#include <minix/com.h>
+#include <minix/syslib.h>
+
+#include "pci.h"
+#include "pci_amd.h"
+#include "pci_intel.h"
+#include "pci_sis.h"
+#include "pci_via.h"
+#if __minix_vmd
+#include "config.h"
+#endif
+
+#if !__minix_vmd
+#define irq_mode_pci(irq) ((void)0)
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <minix/sysutil.h>
+
+#define NR_PCIBUS	10
+#define NR_PCIDEV	40
+
+#define PBT_INTEL_HOST	 1
+#define PBT_PCIBRIDGE	 2
+#define PBT_CARDBUS	 3
+
+#define BAM_NR		6	/* Number of base-address registers */
+
+PRIVATE int debug= 0;
+
+PRIVATE struct pcibus
+{
+	int pb_type;
+	int pb_needinit;
+	int pb_isabridge_dev;
+	int pb_isabridge_type;
+
+	int pb_devind;
+	int pb_busnr;
+	u8_t (*pb_rreg8)(int busind, int devind, int port);
+	u16_t (*pb_rreg16)(int busind, int devind, int port);
+	u32_t (*pb_rreg32)(int busind, int devind, int port);
+	void (*pb_wreg8)(int busind, int devind, int port, U8_t value);
+	void (*pb_wreg16)(int busind, int devind, int port, U16_t value);
+	void (*pb_wreg32)(int busind, int devind, int port, u32_t value);
+	u16_t (*pb_rsts)(int busind);
+	void (*pb_wsts)(int busind, U16_t value);
+} pcibus[NR_PCIBUS];
+PRIVATE int nr_pcibus= 0;
+
+PRIVATE struct pcidev
+{
+	u8_t pd_busnr;
+	u8_t pd_dev;
+	u8_t pd_func;
+	u8_t pd_baseclass;
+	u8_t pd_subclass;
+	u8_t pd_infclass;
+	u16_t pd_vid;
+	u16_t pd_did;
+	u8_t pd_ilr;
+	u8_t pd_inuse;
+
+	struct bar
+	{
+		int pb_flags;
+		int pb_nr;
+		u32_t pb_base;
+		u32_t pb_size;
+	} pd_bar[BAM_NR];
+	int pd_bar_nr;
+
+	char pd_name[M3_STRING];
+} pcidev[NR_PCIDEV];
+
+/* pb_flags */
+#define PBF_IO		1	/* I/O else memory */
+#define PBF_INCOMPLETE	2	/* not allocated */
+
+PRIVATE int nr_pcidev= 0;
+
+/* Work around the limitations of the PCI emulation in QEMU 0.7.1 */
+PRIVATE int qemu_pci= 0;
+
+FORWARD _PROTOTYPE( void pci_intel_init, (void)				);
+FORWARD _PROTOTYPE( void probe_bus, (int busind)			);
+FORWARD _PROTOTYPE( int is_duplicate, (U8_t busnr, U8_t dev, U8_t func)	);
+FORWARD _PROTOTYPE( void record_irq, (int devind)			);
+FORWARD _PROTOTYPE( void record_bars, (int devind)			);
+FORWARD _PROTOTYPE( void record_bars_bridge, (int devind)		);
+FORWARD _PROTOTYPE( void record_bars_cardbus, (int devind)		);
+FORWARD _PROTOTYPE( void record_bar, (int devind, int bar_nr)		);
+FORWARD _PROTOTYPE( void complete_bridges, (void)			);
+FORWARD _PROTOTYPE( void complete_bars, (void)				);
+FORWARD _PROTOTYPE( void update_bridge4dev_io, (int devind,
+					u32_t io_base, u32_t io_size)	);
+FORWARD _PROTOTYPE( int get_freebus, (void)				);
+FORWARD _PROTOTYPE( int do_isabridge, (int busind)			);
+FORWARD _PROTOTYPE( void do_pcibridge, (int busind)			);
+FORWARD _PROTOTYPE( int get_busind, (int busnr)				);
+FORWARD _PROTOTYPE( int do_piix, (int devind)				);
+FORWARD _PROTOTYPE( int do_amd_isabr, (int devind)			);
+FORWARD _PROTOTYPE( int do_sis_isabr, (int devind)			);
+FORWARD _PROTOTYPE( int do_via_isabr, (int devind)			);
+FORWARD _PROTOTYPE( void report_vga, (int devind)			);
+FORWARD _PROTOTYPE( char *pci_vid_name, (U16_t vid)			);
+FORWARD _PROTOTYPE( char *pci_baseclass_name, (U8_t baseclass)		);
+FORWARD _PROTOTYPE( char *pci_subclass_name, (U8_t baseclass,
+					U8_t subclass, U8_t infclass)	);
+FORWARD _PROTOTYPE( void ntostr, (unsigned n, char **str, char *end)	);
+FORWARD _PROTOTYPE( u16_t pci_attr_rsts, (int devind)			);
+FORWARD _PROTOTYPE( void pci_attr_wsts, (int devind, U16_t value)	);
+FORWARD _PROTOTYPE( u16_t pcibr_std_rsts, (int busind)		);
+FORWARD _PROTOTYPE( void pcibr_std_wsts, (int busind, U16_t value)	);
+FORWARD _PROTOTYPE( u16_t pcibr_cb_rsts, (int busind)		);
+FORWARD _PROTOTYPE( void pcibr_cb_wsts, (int busind, U16_t value)	);
+FORWARD _PROTOTYPE( u16_t pcibr_via_rsts, (int busind)			);
+FORWARD _PROTOTYPE( void pcibr_via_wsts, (int busind, U16_t value)	);
+FORWARD _PROTOTYPE( u8_t pcii_rreg8, (int busind, int devind, int port)	);
+FORWARD _PROTOTYPE( u16_t pcii_rreg16, (int busind, int devind,
+							int port)	);
+FORWARD _PROTOTYPE( u32_t pcii_rreg32, (int busind, int devind,
+							int port)	);
+FORWARD _PROTOTYPE( void pcii_wreg8, (int busind, int devind, int port,
+							U8_t value)	);
+FORWARD _PROTOTYPE( void pcii_wreg16, (int busind, int devind, int port,
+							U16_t value)	);
+FORWARD _PROTOTYPE( void pcii_wreg32, (int busind, int devind, int port,
+							u32_t value)	);
+FORWARD _PROTOTYPE( u16_t pcii_rsts, (int busind)			);
+FORWARD _PROTOTYPE( void pcii_wsts, (int busind, U16_t value)		);
+FORWARD _PROTOTYPE( void print_capabilities, (int devind)		);
+
+/*===========================================================================*
+ *			helper functions for I/O			     *
+ *===========================================================================*/
+PUBLIC unsigned pci_inb(U16_t port) {
+	u32_t value;
+	int s;
+	if ((s=sys_inb(port, &value)) !=OK)
+		printf("PCI: warning, sys_inb failed: %d\n", s);
+	return value;
+}
+PUBLIC unsigned pci_inw(U16_t port) {
+	u32_t value;
+	int s;
+	if ((s=sys_inw(port, &value)) !=OK)
+		printf("PCI: warning, sys_inw failed: %d\n", s);
+	return value;
+}
+PUBLIC unsigned pci_inl(U16_t port) {
+	U32_t value;
+	int s;
+	if ((s=sys_inl(port, &value)) !=OK)
+		printf("PCI: warning, sys_inl failed: %d\n", s);
+	return value;
+}
+PUBLIC void pci_outb(U16_t port, U8_t value) {
+	int s;
+	if ((s=sys_outb(port, value)) !=OK)
+		printf("PCI: warning, sys_outb failed: %d\n", s);
+}
+PUBLIC void pci_outw(U16_t port, U16_t value) {
+	int s;
+	if ((s=sys_outw(port, value)) !=OK)
+		printf("PCI: warning, sys_outw failed: %d\n", s);
+}
+PUBLIC void pci_outl(U16_t port, U32_t value) {
+	int s;
+	if ((s=sys_outl(port, value)) !=OK)
+		printf("PCI: warning, sys_outl failed: %d\n", s);
+}
+
+/*===========================================================================*
+ *				pci_init				     *
+ *===========================================================================*/
+PUBLIC void pci_init()
+{
+	static int first_time= 1;
+
+	long v;
+
+	if (!first_time)
+		return;
+
+	v= 0;
+	env_parse("qemu_pci", "d", 0, &v, 0, 1);
+	qemu_pci= v;
+
+	v= 0;
+	env_parse("pci_debug", "d", 0, &v, 0, 1);
+	debug= v;
+
+	/* We don't expect to interrupted */
+	assert(first_time == 1);
+	first_time= -1;
+
+	/* Only Intel (compatible) PCI controllers are supported at the
+	 * moment.
+	 */
+	pci_intel_init();
+
+	first_time= 0;
+}
+
+/*===========================================================================*
+ *				pci_find_dev				     *
+ *===========================================================================*/
+PUBLIC int pci_find_dev(bus, dev, func, devindp)
+u8_t bus;
+u8_t dev;
+u8_t func;
+int *devindp;
+{
+	int devind;
+
+	for (devind= 0; devind < nr_pcidev; devind++)
+	{
+		if (pcidev[devind].pd_busnr == bus &&
+			pcidev[devind].pd_dev == dev &&
+			pcidev[devind].pd_func == func)
+		{
+			break;
+		}
+	}
+	if (devind >= nr_pcidev)
+		return 0;
+	if (pcidev[devind].pd_inuse)
+		return 0;
+	*devindp= devind;
+	return 1;
+}
+
+/*===========================================================================*
+ *				pci_first_dev				     *
+ *===========================================================================*/
+PUBLIC int pci_first_dev(devindp, vidp, didp)
+int *devindp;
+u16_t *vidp;
+u16_t *didp;
+{
+	int devind;
+
+	for (devind= 0; devind < nr_pcidev; devind++)
+	{
+		if (!pcidev[devind].pd_inuse)
+			break;
+	}
+	if (devind >= nr_pcidev)
+		return 0;
+	*devindp= devind;
+	*vidp= pcidev[devind].pd_vid;
+	*didp= pcidev[devind].pd_did;
+	return 1;
+}
+
+/*===========================================================================*
+ *				pci_next_dev				     *
+ *===========================================================================*/
+PUBLIC int pci_next_dev(devindp, vidp, didp)
+int *devindp;
+u16_t *vidp;
+u16_t *didp;
+{
+	int devind;
+
+	for (devind= *devindp+1; devind < nr_pcidev; devind++)
+	{
+		if (!pcidev[devind].pd_inuse)
+			break;
+	}
+	if (devind >= nr_pcidev)
+		return 0;
+	*devindp= devind;
+	*vidp= pcidev[devind].pd_vid;
+	*didp= pcidev[devind].pd_did;
+	return 1;
+}
+
+/*===========================================================================*
+ *				pci_reserve3				     *
+ *===========================================================================*/
+PUBLIC void pci_reserve3(devind, proc, name)
+int devind;
+int proc;
+char *name;
+{
+	int i, r;
+	u8_t ilr;
+	struct io_range ior;
+	struct mem_range mr;
+
+	assert(devind <= nr_pcidev);
+	assert(!pcidev[devind].pd_inuse);
+	pcidev[devind].pd_inuse= 1;
+	strcpy(pcidev[devind].pd_name, name);
+
+	for (i= 0; i<pcidev[devind].pd_bar_nr; i++)
+	{
+		if (pcidev[devind].pd_bar[i].pb_flags & PBF_INCOMPLETE)
+		{
+			printf("pci_reserve3: BAR %d is incomplete\n", i);
+			continue;
+		}
+		if (pcidev[devind].pd_bar[i].pb_flags & PBF_IO)
+		{
+			ior.ior_base= pcidev[devind].pd_bar[i].pb_base;
+			ior.ior_limit= ior.ior_base +
+				pcidev[devind].pd_bar[i].pb_size-1;
+
+			if(debug) {
+			   printf(
+		"pci_reserve3: for proc %d, adding I/O range [0x%x..0x%x]\n",
+				proc, ior.ior_base, ior.ior_limit);
+			}
+			r= sys_privctl(proc, SYS_PRIV_ADD_IO, 0, &ior);
+			if (r != OK)
+			{
+				printf("sys_privctl failed for proc %d: %d\n",
+					proc, r);
+			}
+		}
+		else
+		{
+			mr.mr_base= pcidev[devind].pd_bar[i].pb_base;
+			mr.mr_limit= mr.mr_base +
+				pcidev[devind].pd_bar[i].pb_size-1;
+
+			if(debug) {
+			   printf(
+	"pci_reserve3: for proc %d, should add memory range [0x%x..0x%x]\n",
+				proc, mr.mr_base, mr.mr_limit);
+			}
+			r= sys_privctl(proc, SYS_PRIV_ADD_MEM, 0, &mr);
+			if (r != OK)
+			{
+				printf("sys_privctl failed for proc %d: %d\n",
+					proc, r);
+			}
+		}
+	}
+	ilr= pcidev[devind].pd_ilr;
+	if (ilr != PCI_ILR_UNKNOWN)
+	{
+		if(debug) printf("pci_reserve3: adding IRQ %d\n", ilr);
+		r= sys_privctl(proc, SYS_PRIV_ADD_IRQ, ilr, NULL);
+		if (r != OK)
+		{
+			printf("sys_privctl failed for proc %d: %d\n",
+				proc, r);
+		}
+	}
+}
+
+/*===========================================================================*
+ *				pci_release				     *
+ *===========================================================================*/
+PUBLIC void pci_release(name)
+char *name;
+{
+	int i;
+
+	for (i= 0; i<nr_pcidev; i++)
+	{
+		if (!pcidev[i].pd_inuse)
+			continue;
+		if (strcmp(pcidev[i].pd_name, name) != 0)
+			continue;
+		pcidev[i].pd_inuse= 0;
+	}
+}
+
+/*===========================================================================*
+ *				pci_ids					     *
+ *===========================================================================*/
+PUBLIC void pci_ids(devind, vidp, didp)
+int devind;
+u16_t *vidp;
+u16_t *didp;
+{
+	assert(devind <= nr_pcidev);
+	*vidp= pcidev[devind].pd_vid;
+	*didp= pcidev[devind].pd_did;
+}
+
+/*===========================================================================*
+ *				pci_rescan_bus				     *
+ *===========================================================================*/
+PUBLIC void pci_rescan_bus(busnr)
+u8_t busnr;
+{
+	int busind;
+
+	busind= get_busind(busnr);
+	probe_bus(busind);
+
+	/* Allocate bus numbers for uninitialized bridges */
+	complete_bridges();
+
+	/* Allocate I/O and memory resources for uninitialized devices */
+	complete_bars();
+}
+
+/*===========================================================================*
+ *				pci_slot_name				     *
+ *===========================================================================*/
+PUBLIC char *pci_slot_name(devind)
+int devind;
+{
+	static char label[]= "ddd.ddd.ddd";
+	char *end;
+	char *p;
+
+	p= label;
+	end= label+sizeof(label);
+
+	ntostr(pcidev[devind].pd_busnr, &p, end);
+	*p++= '.';
+
+	ntostr(pcidev[devind].pd_dev, &p, end);
+	*p++= '.';
+
+	ntostr(pcidev[devind].pd_func, &p, end);
+
+	return label;
+}
+
+/*===========================================================================*
+ *				pci_dev_name				     *
+ *===========================================================================*/
+PUBLIC char *pci_dev_name(vid, did)
+u16_t vid;
+u16_t did;
+{
+	int i;
+
+	for (i= 0; pci_device_table[i].name; i++)
+	{
+		if (pci_device_table[i].vid == vid &&
+			pci_device_table[i].did == did)
+		{
+			return pci_device_table[i].name;
+		}
+	}
+	return NULL;
+}
+
+/*===========================================================================*
+ *				pci_attr_r8				     *
+ *===========================================================================*/
+PUBLIC u8_t pci_attr_r8(devind, port)
+int devind;
+int port;
+{
+	int busnr, busind;
+
+	busnr= pcidev[devind].pd_busnr;
+	busind= get_busind(busnr);
+	return pcibus[busind].pb_rreg8(busind, devind, port);
+}
+
+/*===========================================================================*
+ *				pci_attr_r16				     *
+ *===========================================================================*/
+PUBLIC u16_t pci_attr_r16(devind, port)
+int devind;
+int port;
+{
+	int busnr, busind;
+
+	busnr= pcidev[devind].pd_busnr;
+	busind= get_busind(busnr);
+	return pcibus[busind].pb_rreg16(busind, devind, port);
+}
+
+/*===========================================================================*
+ *				pci_attr_r32				     *
+ *===========================================================================*/
+PUBLIC u32_t pci_attr_r32(devind, port)
+int devind;
+int port;
+{
+	int busnr, busind;
+
+	busnr= pcidev[devind].pd_busnr;
+	busind= get_busind(busnr);
+	return pcibus[busind].pb_rreg32(busind, devind, port);
+}
+
+/*===========================================================================*
+ *				pci_attr_w8				     *
+ *===========================================================================*/
+PUBLIC void pci_attr_w8(devind, port, value)
+int devind;
+int port;
+u16_t value;
+{
+	int busnr, busind;
+
+	busnr= pcidev[devind].pd_busnr;
+	busind= get_busind(busnr);
+	pcibus[busind].pb_wreg8(busind, devind, port, value);
+}
+
+/*===========================================================================*
+ *				pci_attr_w16				     *
+ *===========================================================================*/
+PUBLIC void pci_attr_w16(devind, port, value)
+int devind;
+int port;
+u16_t value;
+{
+	int busnr, busind;
+
+	busnr= pcidev[devind].pd_busnr;
+	busind= get_busind(busnr);
+	pcibus[busind].pb_wreg16(busind, devind, port, value);
+}
+
+/*===========================================================================*
+ *				pci_attr_w32				     *
+ *===========================================================================*/
+PUBLIC void pci_attr_w32(devind, port, value)
+int devind;
+int port;
+u32_t value;
+{
+	int busnr, busind;
+
+	busnr= pcidev[devind].pd_busnr;
+	busind= get_busind(busnr);
+	pcibus[busind].pb_wreg32(busind, devind, port, value);
+}
+
+/*===========================================================================*
+ *				pci_intel_init				     *
+ *===========================================================================*/
+PRIVATE void pci_intel_init()
+{
+	/* Try to detect a know PCI controller. Read the Vendor ID and
+	 * the Device ID for function 0 of device 0.
+	 * Two times the value 0xffff suggests a system without a (compatible)
+	 * PCI controller. 
+	 */
+	u32_t bus, dev, func;
+	u16_t vid, did;
+	int s, i, r, busind, busnr;
+	char *dstr;
+
+	bus= 0;
+	dev= 0;
+	func= 0;
+
+	vid= PCII_RREG16_(bus, dev, func, PCI_VID);
+	did= PCII_RREG16_(bus, dev, func, PCI_DID);
+#if USER_SPACE
+	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
+		printf("PCI: warning, sys_outl failed: %d\n", s);
+#else
+	outl(PCII_CONFADD, PCII_UNSEL);
+#endif
+
+	if (vid == 0xffff && did == 0xffff)
+		return;	/* Nothing here */
+
+#if 0
+	for (i= 0; pci_intel_ctrl[i].vid; i++)
+	{
+		if (pci_intel_ctrl[i].vid == vid &&
+			pci_intel_ctrl[i].did == did)
+		{
+			break;
+		}
+	}
+
+	if (!pci_intel_ctrl[i].vid)
+	{
+		printf("pci_intel_init (warning): unknown PCI-controller:\n"
+			"\tvendor %04X (%s), device %04X\n",
+			vid, pci_vid_name(vid), did);
+	}
+#endif
+
+	if (nr_pcibus >= NR_PCIBUS)
+		panic("PCI","too many PCI busses", nr_pcibus);
+	busind= nr_pcibus;
+	nr_pcibus++;
+	pcibus[busind].pb_type= PBT_INTEL_HOST;
+	pcibus[busind].pb_needinit= 0;
+	pcibus[busind].pb_isabridge_dev= -1;
+	pcibus[busind].pb_isabridge_type= 0;
+	pcibus[busind].pb_devind= -1;
+	pcibus[busind].pb_busnr= 0;
+	pcibus[busind].pb_rreg8= pcii_rreg8;
+	pcibus[busind].pb_rreg16= pcii_rreg16;
+	pcibus[busind].pb_rreg32= pcii_rreg32;
+	pcibus[busind].pb_wreg8= pcii_wreg8;
+	pcibus[busind].pb_wreg16= pcii_wreg16;
+	pcibus[busind].pb_wreg32= pcii_wreg32;
+	pcibus[busind].pb_rsts= pcii_rsts;
+	pcibus[busind].pb_wsts= pcii_wsts;
+
+	dstr= pci_dev_name(vid, did);
+	if (!dstr)
+		dstr= "unknown device";
+	if (debug)
+	{
+		printf("pci_intel_init: %s (%04X/%04X)\n",
+			dstr, vid, did);
+	}
+
+	probe_bus(busind);
+
+	r= do_isabridge(busind);
+	if (r != OK)
+	{
+		busnr= pcibus[busind].pb_busnr;
+
+		/* Disable all devices for this bus */
+		for (i= 0; i<nr_pcidev; i++)
+		{
+			if (pcidev[i].pd_busnr != busnr)
+				continue;
+			pcidev[i].pd_inuse= 1;
+		}
+		return;
+	}
+
+	/* Look for PCI bridges */
+	do_pcibridge(busind);
+
+	/* Allocate bus numbers for uninitialized bridges */
+	complete_bridges();
+
+	/* Allocate I/O and memory resources for uninitialized devices */
+	complete_bars();
+}
+
+/*===========================================================================*
+ *				probe_bus				     *
+ *===========================================================================*/
+PRIVATE void probe_bus(busind)
+int busind;
+{
+	u32_t dev, func, t3;
+	u16_t vid, did, sts;
+	u8_t headt;
+	u8_t baseclass, subclass, infclass;
+	int devind, busnr;
+	char *s, *dstr;
+
+#if DEBUG
+printf("probe_bus(%d)\n", busind);
+#endif
+	if (nr_pcidev >= NR_PCIDEV)
+		panic("PCI","too many PCI devices", nr_pcidev);
+	devind= nr_pcidev;
+
+	busnr= pcibus[busind].pb_busnr;
+	for (dev= 0; dev<32; dev++)
+	{
+
+		for (func= 0; func < 8; func++)
+		{
+			pcidev[devind].pd_busnr= busnr;
+			pcidev[devind].pd_dev= dev;
+			pcidev[devind].pd_func= func;
+
+			pci_attr_wsts(devind, 
+				PSR_SSE|PSR_RMAS|PSR_RTAS);
+			vid= pci_attr_r16(devind, PCI_VID);
+			did= pci_attr_r16(devind, PCI_DID);
+			headt= pci_attr_r8(devind, PCI_HEADT);
+			sts= pci_attr_rsts(devind);
+
+#if 0
+			printf("vid 0x%x, did 0x%x, headt 0x%x, sts 0x%x\n",
+				vid, did, headt, sts);
+#endif
+
+			if (vid == NO_VID)
+			{
+				if (func == 0)
+					break;	/* Nothing here */
+
+				/* Scan all functions of a multifunction
+				 * device.
+				 */
+				continue;
+			}
+
+			if (sts & (PSR_SSE|PSR_RMAS|PSR_RTAS))
+			{
+				if (qemu_pci)
+				{
+					printf(
+			"pci: ignoring bad value 0x%x in sts for QEMU\n",
+					sts & (PSR_SSE|PSR_RMAS|PSR_RTAS));
+				}
+				else
+				{
+					if (func == 0)
+						break;	/* Nothing here */
+
+					/* Scan all functions of a
+					 * multifunction device.
+					 */
+					continue;
+				}
+			}
+
+			dstr= pci_dev_name(vid, did);
+			if (debug)
+			{
+				if (dstr)
+				{
+					printf("%d.%lu.%lu: %s (%04X/%04X)\n",
+						busind, (unsigned long)dev,
+						(unsigned long)func, dstr,
+						vid, did);
+				}
+				else
+				{
+					printf(
+		"%d.%lu.%lu: Unknown device, vendor %04X (%s), device %04X\n",
+						busind, (unsigned long)dev,
+						(unsigned long)func, vid,
+						pci_vid_name(vid), did);
+				}
+				printf("Device index: %d\n", devind);
+				printf("Subsystem: Vid 0x%x, did 0x%x\n",
+					pci_attr_r16(devind, PCI_SUBVID),
+					pci_attr_r16(devind, PCI_SUBDID));
+			}
+
+			baseclass= pci_attr_r8(devind, PCI_BCR);
+			subclass= pci_attr_r8(devind, PCI_SCR);
+			infclass= pci_attr_r8(devind, PCI_PIFR);
+			s= pci_subclass_name(baseclass, subclass, infclass);
+			if (!s)
+				s= pci_baseclass_name(baseclass);
+			{
+				if (!s)
+					s= "(unknown class)";
+			}
+			if (debug)
+			{
+				printf("\tclass %s (%X/%X/%X)\n", s,
+					baseclass, subclass, infclass);
+			}
+
+			if (is_duplicate(busnr, dev, func))
+			{
+				printf("\tduplicate!\n");
+				if (func == 0 && !(headt & PHT_MULTIFUNC))
+					break;
+				continue;
+			}
+
+			devind= nr_pcidev;
+			nr_pcidev++;
+			pcidev[devind].pd_baseclass= baseclass;
+			pcidev[devind].pd_subclass= subclass;
+			pcidev[devind].pd_infclass= infclass;
+			pcidev[devind].pd_vid= vid;
+			pcidev[devind].pd_did= did;
+			pcidev[devind].pd_inuse= 0;
+			pcidev[devind].pd_bar_nr= 0;
+			record_irq(devind);
+			switch(headt & PHT_MASK)
+			{
+			case PHT_NORMAL:
+				record_bars(devind);
+				break;
+			case PHT_BRIDGE:
+				record_bars_bridge(devind);
+				break;
+			case PHT_CARDBUS:
+				record_bars_cardbus(devind);
+				break;
+			default:
+				printf("\t%d.%d.%d: unknown header type %d\n",
+					busind, dev, func,
+					headt & PHT_MASK);
+				break;
+			}
+			if (debug)
+				print_capabilities(devind);
+
+			t3= ((baseclass << 16) | (subclass << 8) | infclass);
+			if (t3 == PCI_T3_VGA || t3 == PCI_T3_VGA_OLD)
+				report_vga(devind);
+
+			if (nr_pcidev >= NR_PCIDEV)
+			  panic("PCI","too many PCI devices", nr_pcidev);
+			devind= nr_pcidev;
+
+			if (func == 0 && !(headt & PHT_MULTIFUNC))
+				break;
+		}
+	}
+}
+
+/*===========================================================================*
+ *				is_duplicate				     *
+ *===========================================================================*/
+PRIVATE int is_duplicate(busnr, dev, func)
+u8_t busnr;
+u8_t dev;
+u8_t func;
+{
+	int i;
+
+	for (i= 0; i<nr_pcidev; i++)
+	{
+		if (pcidev[i].pd_busnr == busnr &&
+			pcidev[i].pd_dev == dev &&
+			pcidev[i].pd_func == func)
+		{
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*===========================================================================*
+ *				record_irq				     *
+ *===========================================================================*/
+PRIVATE void record_irq(devind)
+int devind;
+{
+	int ilr, ipr, busnr, busind, cb_devind;
+
+	ilr= pci_attr_r8(devind, PCI_ILR);
+	ipr= pci_attr_r8(devind, PCI_IPR);
+	if (ilr == 0)
+	{
+		static int first= 1;
+		if (ipr && first && debug)
+		{
+			first= 0;
+			printf("PCI: strange, BIOS assigned IRQ0\n");
+		}
+		ilr= PCI_ILR_UNKNOWN;
+	}
+	pcidev[devind].pd_ilr= ilr;
+	if (ilr == PCI_ILR_UNKNOWN && !ipr)
+	{
+	}
+	else if (ilr != PCI_ILR_UNKNOWN && ipr)
+	{
+		if (debug)
+			printf("\tIRQ %d for INT%c\n", ilr, 'A' + ipr-1);
+	}
+	else if (ilr != PCI_ILR_UNKNOWN)
+	{
+		printf(
+	"PCI: IRQ %d is assigned, but device %d.%d.%d does not need it\n",
+			ilr, pcidev[devind].pd_busnr, pcidev[devind].pd_dev,
+			pcidev[devind].pd_func);
+	}
+	else
+	{
+		/* Check for cardbus devices */
+		busnr= pcidev[devind].pd_busnr;
+		busind= get_busind(busnr);
+		if (pcibus[busind].pb_type == PBT_CARDBUS)
+		{
+			cb_devind= pcibus[busind].pb_devind;
+			ilr= pcidev[cb_devind].pd_ilr;
+			if (ilr != PCI_ILR_UNKNOWN)
+			{
+				if (debug)
+				{
+					printf(
+					"assigning IRQ %d to Cardbus device\n",
+						ilr);
+				}
+				pci_attr_w8(devind, PCI_ILR, ilr);
+				pcidev[devind].pd_ilr= ilr;
+				return;
+			}
+		}
+		if(debug) {
+			printf(
+		"PCI: device %d.%d.%d uses INT%c but is not assigned any IRQ\n",
+			pcidev[devind].pd_busnr, pcidev[devind].pd_dev,
+			pcidev[devind].pd_func, 'A' + ipr-1);
+		}
+	}
+}
+
+/*===========================================================================*
+ *				record_bars				     *
+ *===========================================================================*/
+PRIVATE void record_bars(devind)
+int devind;
+{
+	int i, j, reg, prefetch, type, clear_01, clear_23, pb_nr;
+	u32_t bar, bar2;
+
+	for (i= 0, reg= PCI_BAR; reg <= PCI_BAR_6; i++, reg += 4)
+	{
+		record_bar(devind, i);
+	}
+
+	/* Special case code for IDE controllers in compatibility mode */
+	if (pcidev[devind].pd_baseclass == PCI_BCR_MASS_STORAGE &&
+		pcidev[devind].pd_subclass == PCI_MS_IDE)
+	{
+		/* IDE device */
+		clear_01= 0;
+		clear_23= 0;
+		if (!(pcidev[devind].pd_infclass & PCI_IDE_PRI_NATIVE))
+		{
+			if (debug)
+			{
+				printf(
+	"primary channel is not in native mode, clearing BARs 0 and 1\n");
+			}
+			clear_01= 1;
+		}
+		if (!(pcidev[devind].pd_infclass & PCI_IDE_SEC_NATIVE))
+		{
+			if (debug)
+			{
+				printf(
+	"primary channel is not in native mode, clearing BARs 2 and 3\n");
+			}
+			clear_23= 1;
+		}
+
+		j= 0;
+		for (i= 0; i<pcidev[devind].pd_bar_nr; i++)
+		{
+			pb_nr= pcidev[devind].pd_bar[i].pb_nr;
+			if ((pb_nr == 0 || pb_nr == 1) && clear_01)
+			{
+				if (debug) printf("skipping bar %d\n", pb_nr);
+				continue;	/* Skip */
+			}
+			if ((pb_nr == 2 || pb_nr == 3) && clear_23)
+			{
+				if (debug) printf("skipping bar %d\n", pb_nr);
+				continue;	/* Skip */
+			}
+			if (i == j)
+				continue;	/* No need to copy */
+			pcidev[devind].pd_bar[j]=
+				pcidev[devind].pd_bar[i];
+			j++;
+		}
+		pcidev[devind].pd_bar_nr= j;
+	}
+}
+
+/*===========================================================================*
+ *				record_bars_bridge			     *
+ *===========================================================================*/
+PRIVATE void record_bars_bridge(devind)
+int devind;
+{
+	u32_t base, limit, size;
+
+	record_bar(devind, 0);
+	record_bar(devind, 1);
+
+	base= ((pci_attr_r8(devind, PPB_IOBASE) & PPB_IOB_MASK) << 8) |
+		(pci_attr_r16(devind, PPB_IOBASEU16) << 16);
+	limit= 0xff |
+		((pci_attr_r8(devind, PPB_IOLIMIT) & PPB_IOL_MASK) << 8) |
+		((~PPB_IOL_MASK & 0xff) << 8) |
+		(pci_attr_r16(devind, PPB_IOLIMITU16) << 16);
+	size= limit-base + 1;
+	if (debug)
+	{
+		printf("\tI/O window: base 0x%x, limit 0x%x, size %d\n",
+			base, limit, size);
+	}
+
+	base= ((pci_attr_r16(devind, PPB_MEMBASE) & PPB_MEMB_MASK) << 16);
+	limit= 0xffff |
+		((pci_attr_r16(devind, PPB_MEMLIMIT) & PPB_MEML_MASK) << 16) |
+		((~PPB_MEML_MASK & 0xffff) << 16);
+	size= limit-base + 1;
+	if (debug)
+	{
+		printf("\tMemory window: base 0x%x, limit 0x%x, size 0x%x\n",
+			base, limit, size);
+	}
+
+	/* Ignore the upper 32 bits */
+	base= ((pci_attr_r16(devind, PPB_PFMEMBASE) & PPB_PFMEMB_MASK) << 16);
+	limit= 0xffff |
+		((pci_attr_r16(devind, PPB_PFMEMLIMIT) &
+			PPB_PFMEML_MASK) << 16) |
+		((~PPB_PFMEML_MASK & 0xffff) << 16);
+	size= limit-base + 1;
+	if (debug)
+	{
+		printf(
+	"\tPrefetchable memory window: base 0x%x, limit 0x%x, size 0x%x\n",
+			base, limit, size);
+	}
+}
+
+/*===========================================================================*
+ *				record_bars_cardbus			     *
+ *===========================================================================*/
+PRIVATE void record_bars_cardbus(devind)
+int devind;
+{
+	u32_t base, limit, size;
+
+	record_bar(devind, 0);
+
+	base= pci_attr_r32(devind, CBB_MEMBASE_0);
+	limit= pci_attr_r32(devind, CBB_MEMLIMIT_0) |
+		(~CBB_MEML_MASK & 0xffffffff);
+	size= limit-base + 1;
+	if (debug)
+	{
+		printf("\tMemory window 0: base 0x%x, limit 0x%x, size %d\n",
+			base, limit, size);
+	}
+
+	base= pci_attr_r32(devind, CBB_MEMBASE_1);
+	limit= pci_attr_r32(devind, CBB_MEMLIMIT_1) |
+		(~CBB_MEML_MASK & 0xffffffff);
+	size= limit-base + 1;
+	if (debug)
+	{
+		printf("\tMemory window 1: base 0x%x, limit 0x%x, size %d\n",
+			base, limit, size);
+	}
+
+	base= pci_attr_r32(devind, CBB_IOBASE_0);
+	limit= pci_attr_r32(devind, CBB_IOLIMIT_0) |
+		(~CBB_IOL_MASK & 0xffffffff);
+	size= limit-base + 1;
+	if (debug)
+	{
+		printf("\tI/O window 0: base 0x%x, limit 0x%x, size %d\n",
+			base, limit, size);
+	}
+
+	base= pci_attr_r32(devind, CBB_IOBASE_1);
+	limit= pci_attr_r32(devind, CBB_IOLIMIT_1) |
+		(~CBB_IOL_MASK & 0xffffffff);
+	size= limit-base + 1;
+	if (debug)
+	{
+		printf("\tI/O window 1: base 0x%x, limit 0x%x, size %d\n",
+			base, limit, size);
+	}
+}
+
+/*===========================================================================*
+ *				record_bar				     *
+ *===========================================================================*/
+PRIVATE void record_bar(devind, bar_nr)
+int devind;
+int bar_nr;
+{
+	int reg, prefetch, type, dev_bar_nr;
+	u32_t bar, bar2;
+
+	reg= PCI_BAR+4*bar_nr;
+
+	bar= pci_attr_r32(devind, reg);
+	if (bar & PCI_BAR_IO)
+	{
+		/* Size register */
+		pci_attr_w32(devind, reg, 0xffffffff);
+		bar2= pci_attr_r32(devind, reg);
+		pci_attr_w32(devind, reg, bar);
+
+		bar &= ~(u32_t)3;	/* Clear non-address bits */
+		bar2 &= ~(u32_t)3;
+		bar2= (~bar2 & 0xffff)+1;
+		if (debug)
+		{
+			printf("\tbar_%d: %d bytes at 0x%x I/O\n",
+				bar_nr, bar2, bar);
+		}
+
+		dev_bar_nr= pcidev[devind].pd_bar_nr++;
+		assert(dev_bar_nr < BAR_NR);
+		pcidev[devind].pd_bar[dev_bar_nr].pb_flags= PBF_IO;
+		pcidev[devind].pd_bar[dev_bar_nr].pb_base= bar;
+		pcidev[devind].pd_bar[dev_bar_nr].pb_size= bar2;
+		pcidev[devind].pd_bar[dev_bar_nr].pb_nr= bar_nr;
+		if (bar == 0)
+		{
+			pcidev[devind].pd_bar[dev_bar_nr].pb_flags |= 
+				PBF_INCOMPLETE;
+		}
+	}
+	else
+	{
+		/* Size register */
+		pci_attr_w32(devind, reg, 0xffffffff);
+		bar2= pci_attr_r32(devind, reg);
+		pci_attr_w32(devind, reg, bar);
+
+		if (bar2 == 0)
+			return;	/* Reg. is not implemented */
+
+		prefetch= !!(bar & PCI_BAR_PREFETCH);
+		type= (bar & PCI_BAR_TYPE);
+		bar &= ~(u32_t)0xf;	/* Clear non-address bits */
+		bar2 &= ~(u32_t)0xf;
+		bar2= (~bar2)+1;
+		if (debug)
+		{
+			printf("\tbar_%d: 0x%x bytes at 0x%x%s memory\n",
+				bar_nr, bar2, bar,
+				prefetch ? " prefetchable" : "");
+			if (type != 0)
+				printf("type = 0x%x\n", type);
+		}
+
+		dev_bar_nr= pcidev[devind].pd_bar_nr++;
+		assert(dev_bar_nr < BAR_NR);
+		pcidev[devind].pd_bar[dev_bar_nr].pb_flags= 0;
+		pcidev[devind].pd_bar[dev_bar_nr].pb_base= bar;
+		pcidev[devind].pd_bar[dev_bar_nr].pb_size= bar2;
+		pcidev[devind].pd_bar[dev_bar_nr].pb_nr= bar_nr;
+		if (bar == 0)
+		{
+			pcidev[devind].pd_bar[dev_bar_nr].pb_flags |= 
+				PBF_INCOMPLETE;
+		}
+	}
+}
+
+/*===========================================================================*
+ *				complete_bridges			     *
+ *===========================================================================*/
+PRIVATE void complete_bridges()
+{
+	int i, freebus, devind, prim_busnr;
+
+	for (i= 0; i<nr_pcibus; i++)
+	{
+		if (!pcibus[i].pb_needinit)
+			continue;
+		printf("should allocate bus number for bus %d\n", i);
+		freebus= get_freebus();
+		printf("got bus number %d\n", freebus);
+
+		devind= pcibus[i].pb_devind;
+
+		prim_busnr= pcidev[devind].pd_busnr;
+		if (prim_busnr != 0)
+		{
+			printf(
+	"complete_bridge: updating subordinate bus number not implemented\n");
+		}
+
+		pcibus[i].pb_needinit= 0;
+		pcibus[i].pb_busnr= freebus;
+
+		printf("devind = %d\n", devind);
+		printf("prim_busnr= %d\n", prim_busnr);
+
+		pci_attr_w8(devind, PPB_PRIMBN, prim_busnr);
+		pci_attr_w8(devind, PPB_SECBN, freebus);
+		pci_attr_w8(devind, PPB_SUBORDBN, freebus);
+
+		printf("CR = 0x%x\n", pci_attr_r16(devind, PCI_CR));
+		printf("SECBLT = 0x%x\n", pci_attr_r8(devind, PPB_SECBLT));
+		printf("BRIDGECTRL = 0x%x\n",
+			pci_attr_r16(devind, PPB_BRIDGECTRL));
+	}
+}
+
+/*===========================================================================*
+ *				complete_bars				     *
+ *===========================================================================*/
+PRIVATE void complete_bars()
+{
+	int i, j, r, bar_nr, reg;
+	u32_t memgap_low, memgap_high, iogap_low, iogap_high, io_high,
+		base, size, v32, diff1, diff2;
+	char *cp, *next;
+	char memstr[256];
+
+	r= env_get_param("memory", memstr, sizeof(memstr));
+	if (r != OK)
+		panic("pci", "env_get_param failed", r);
+	
+	/* Set memgap_low to just above physical memory */
+	memgap_low= 0;
+	cp= memstr;
+	while (*cp != '\0')
+	{
+		base= strtoul(cp, &next, 16);
+		if (next == cp || *next != ':')
+		{
+			printf("pci: bad memory environment string '%s'\n",
+				memstr);
+			panic(NULL, NULL, NO_NUM);
+		}
+		cp= next+1;
+		size= strtoul(cp, &next, 16);
+		if (next == cp || (*next != ',' && *next != '\0'))
+		{
+			printf("pci: bad memory environment string '%s'\n",
+				memstr);
+			panic(NULL, NULL, NO_NUM);
+		}
+		cp= next+1;
+
+		if (base+size > memgap_low)
+			memgap_low= base+size;
+	}
+
+	memgap_high= 0xfe000000;	/* Leave space for the CPU (APIC) */
+
+	if (debug)
+	{
+		printf("complete_bars: initial gap: [0x%x .. 0x%x>\n",
+			memgap_low, memgap_high);
+	}
+
+	/* Find the lowest memory base */
+	for (i= 0; i<nr_pcidev; i++)
+	{
+		for (j= 0; j<pcidev[i].pd_bar_nr; j++)
+		{
+			if (pcidev[i].pd_bar[j].pb_flags & PBF_IO)
+				continue;
+			if (pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE)
+				continue;
+			base= pcidev[i].pd_bar[j].pb_base;
+			size= pcidev[i].pd_bar[j].pb_size;
+
+			if (base >= memgap_high)
+				continue;	/* Not in the gap */
+			if (base+size <= memgap_low)
+				continue;	/* Not in the gap */
+
+			/* Reduce the gap by the smallest amount */
+			diff1= base+size-memgap_low;
+			diff2= memgap_high-base;
+
+			if (diff1 < diff2)
+				memgap_low= base+size;
+			else
+				memgap_high= base;
+		}
+	}
+
+	if (debug)
+	{
+		printf("complete_bars: intermediate gap: [0x%x .. 0x%x>\n",
+			memgap_low, memgap_high);
+	}
+
+	/* Should check main memory size */
+	if (memgap_high < memgap_low)
+	{
+		printf("pci: bad memory gap: [0x%x .. 0x%x>\n",
+			memgap_low, memgap_high);
+		panic(NULL, NULL, NO_NUM);
+	}
+
+	iogap_high= 0x10000;
+	iogap_low= 0x400;
+
+	/* Find the free I/O space */
+	for (i= 0; i<nr_pcidev; i++)
+	{
+		for (j= 0; j<pcidev[i].pd_bar_nr; j++)
+		{
+			if (!(pcidev[i].pd_bar[j].pb_flags & PBF_IO))
+				continue;
+			if (pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE)
+				continue;
+			base= pcidev[i].pd_bar[j].pb_base;
+			size= pcidev[i].pd_bar[j].pb_size;
+			if (base >= iogap_high)
+				continue;
+			if (base+size <= iogap_low)
+				continue;
+#if 0
+			if (debug)
+			{
+				printf(
+		"pci device %d (%04x/%04x), bar %d: base 0x%x, size 0x%x\n",
+					i, pcidev[i].pd_vid, pcidev[i].pd_did,
+					j, base, size);
+			}
+#endif
+			if (base+size-iogap_low < iogap_high-base)
+				iogap_low= base+size;
+			else
+				iogap_high= base;
+		}
+	}
+
+	if (iogap_high < iogap_low)
+	{
+		if (debug)
+		{
+			printf("iogap_high too low, should panic\n");
+		}
+		else
+			panic("pci", "iogap_high too low", iogap_high);
+	}
+	if (debug)
+		printf("I/O range = [0x%x..0x%x>\n", iogap_low, iogap_high);
+
+	for (i= 0; i<nr_pcidev; i++)
+	{
+		for (j= 0; j<pcidev[i].pd_bar_nr; j++)
+		{
+			if (pcidev[i].pd_bar[j].pb_flags & PBF_IO)
+				continue;
+			if (!(pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE))
+				continue;
+			size= pcidev[i].pd_bar[j].pb_size;
+			if (size < PAGE_SIZE)
+				size= PAGE_SIZE;
+			base= memgap_high-size;
+			base &= ~(u32_t)(size-1);
+			if (base < memgap_low)
+				panic("pci", "memory base too low", base);
+			memgap_high= base;
+			bar_nr= pcidev[i].pd_bar[j].pb_nr;
+			reg= PCI_BAR + 4*bar_nr;
+			v32= pci_attr_r32(i, reg);
+			pci_attr_w32(i, reg, v32 | base);
+			if (debug)
+			{
+				printf(
+		"complete_bars: allocated 0x%x size %d to %d.%d.%d, bar_%d\n",
+					base, size, pcidev[i].pd_busnr,
+					pcidev[i].pd_dev, pcidev[i].pd_func,
+					bar_nr);
+			}
+			pcidev[i].pd_bar[j].pb_base= base;
+			pcidev[i].pd_bar[j].pb_flags &= ~PBF_INCOMPLETE;
+		}
+
+		io_high= iogap_high;
+		for (j= 0; j<pcidev[i].pd_bar_nr; j++)
+		{
+			if (!(pcidev[i].pd_bar[j].pb_flags & PBF_IO))
+				continue;
+			if (!(pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE))
+				continue;
+			size= pcidev[i].pd_bar[j].pb_size;
+			base= iogap_high-size;
+			base &= ~(u32_t)(size-1);
+
+			/* Assume that ISA compatibility is required. Only
+			 * use the lowest 256 bytes out of every 1024 bytes.
+			 */
+			base &= 0xfcff;
+
+			if (base < iogap_low)
+				panic("pci", "I/O base too low", base);
+
+			iogap_high= base;
+			bar_nr= pcidev[i].pd_bar[j].pb_nr;
+			reg= PCI_BAR + 4*bar_nr;
+			v32= pci_attr_r32(i, reg);
+			pci_attr_w32(i, reg, v32 | base);
+			if (debug)
+			{
+				printf(
+		"complete_bars: allocated 0x%x size %d to %d.%d.%d, bar_%d\n",
+					base, size, pcidev[i].pd_busnr,
+					pcidev[i].pd_dev, pcidev[i].pd_func,
+					bar_nr);
+			}
+			pcidev[i].pd_bar[j].pb_base= base;
+			pcidev[i].pd_bar[j].pb_flags &= ~PBF_INCOMPLETE;
+
+		}
+		if (iogap_high != io_high)
+		{
+			update_bridge4dev_io(i, iogap_high,
+				io_high-iogap_high);
+		}
+	}
+
+	for (i= 0; i<nr_pcidev; i++)
+	{
+		for (j= 0; j<pcidev[i].pd_bar_nr; j++)
+		{
+			if (!(pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE))
+				continue;
+			printf("should allocate resources for device %d\n", i);
+		}
+	}
+}
+
+/*===========================================================================*
+ *				update_bridge4dev_io			     *
+ *===========================================================================*/
+PRIVATE void update_bridge4dev_io(devind, io_base, io_size)
+int devind;
+u32_t io_base;
+u32_t io_size;
+{
+	int busnr, busind, type, br_devind;
+	u16_t v16;
+
+	busnr= pcidev[devind].pd_busnr;
+	busind= get_busind(busnr);
+	type= pcibus[busind].pb_type;
+	if (type == PBT_INTEL_HOST)
+		return;	/* Nothing to do for host controller */
+	if (type == PBT_PCIBRIDGE)
+	{
+		printf(
+		"update_bridge4dev_io: not implemented for PCI bridges\n");
+		return;	
+	}
+	if (type != PBT_CARDBUS)
+		panic("pci", "update_bridge4dev_io: strange bus type", type);
+
+	if (debug)
+	{
+		printf("update_bridge4dev_io: adding 0x%x at 0x%x\n",
+			io_size, io_base);
+	}
+	br_devind= pcibus[busind].pb_devind;
+	pci_attr_w32(br_devind, CBB_IOLIMIT_0, io_base+io_size-1);
+	pci_attr_w32(br_devind, CBB_IOBASE_0, io_base);
+
+	/* Enable I/O access. Enable busmaster access as well. */
+	v16= pci_attr_r16(devind, PCI_CR);
+	pci_attr_w16(devind, PCI_CR, v16 | PCI_CR_IO_EN | PCI_CR_MAST_EN);
+}
+
+/*===========================================================================*
+ *				get_freebus				     *
+ *===========================================================================*/
+PRIVATE int get_freebus()
+{
+	int i, freebus;
+
+	freebus= 1;
+	for (i= 0; i<nr_pcibus; i++)
+	{
+		if (pcibus[i].pb_needinit)
+			continue;
+		if (pcibus[i].pb_type == PBT_INTEL_HOST)
+			continue;
+		if (pcibus[i].pb_busnr <= freebus)
+			freebus= pcibus[i].pb_busnr+1;
+		printf("get_freebus: should check suboridinate bus number\n");
+	}
+	return freebus;
+}
+
+/*===========================================================================*
+ *				do_isabridge				     *
+ *===========================================================================*/
+PRIVATE int do_isabridge(busind)
+int busind;
+{
+	int i, j, r, type, busnr, unknown_bridge, bridge_dev;
+	u16_t vid, did;
+	u32_t t3;
+	char *dstr;
+
+	unknown_bridge= -1;
+	bridge_dev= -1;
+	j= 0;	/* lint */
+	vid= did= 0;	/* lint */
+	busnr= pcibus[busind].pb_busnr;
+	for (i= 0; i< nr_pcidev; i++)
+	{
+		if (pcidev[i].pd_busnr != busnr)
+			continue;
+		t3= ((pcidev[i].pd_baseclass << 16) |
+			(pcidev[i].pd_subclass << 8) | pcidev[i].pd_infclass);
+		if (t3 == PCI_T3_ISA)
+		{
+			/* ISA bridge. Report if no supported bridge is
+			 * found.
+			 */
+			unknown_bridge= i;
+		}
+
+		vid= pcidev[i].pd_vid;
+		did= pcidev[i].pd_did;
+		for (j= 0; pci_isabridge[j].vid != 0; j++)
+		{
+			if (pci_isabridge[j].vid != vid)
+				continue;
+			if (pci_isabridge[j].did != did)
+				continue;
+			if (pci_isabridge[j].checkclass &&
+				unknown_bridge != i)
+			{
+				/* This part of multifunction device is
+				 * not the bridge.
+				 */
+				continue;
+			}
+			break;
+		}
+		if (pci_isabridge[j].vid)
+		{
+			bridge_dev= i;
+			break;
+		}
+	}
+
+	if (bridge_dev != -1)
+	{
+		dstr= pci_dev_name(vid, did);
+		if (!dstr)
+			dstr= "unknown device";
+		if (debug)
+		{
+			printf("found ISA bridge (%04X/%04X) %s\n",
+				vid, did, dstr);
+		}
+		pcibus[busind].pb_isabridge_dev= bridge_dev;
+		type= pci_isabridge[j].type;
+		pcibus[busind].pb_isabridge_type= type;
+		switch(type)
+		{
+		case PCI_IB_PIIX:
+			r= do_piix(bridge_dev);
+			break;
+		case PCI_IB_VIA:
+			r= do_via_isabr(bridge_dev);
+			break;
+		case PCI_IB_AMD:
+			r= do_amd_isabr(bridge_dev);
+			break;
+		case PCI_IB_SIS:
+			r= do_sis_isabr(bridge_dev);
+			break;
+		default:
+			panic("PCI","unknown ISA bridge type", type);
+		}
+		return r;
+	}
+
+	if (unknown_bridge == -1)
+	{
+		if (debug)
+		{
+			printf("(warning) no ISA bridge found on bus %d\n",
+				busind);
+		}
+		return 0;
+	}
+	if (debug)
+	{
+		printf(
+		"(warning) unsupported ISA bridge %04X/%04X for bus %d\n",
+			pcidev[unknown_bridge].pd_vid,
+			pcidev[unknown_bridge].pd_did, busind);
+	}
+	return 0;
+}
+
+/*===========================================================================*
+ *				do_pcibridge				     *
+ *===========================================================================*/
+PRIVATE void do_pcibridge(busind)
+int busind;
+{
+	int i, devind, busnr;
+	int ind, type;
+	u16_t vid, did;
+	u8_t sbusn, baseclass, subclass, infclass, headt;
+	u32_t t3;
+
+	vid= did= 0;	/* lint */
+	busnr= pcibus[busind].pb_busnr;
+	for (devind= 0; devind< nr_pcidev; devind++)
+	{
+#if 0
+		printf("do_pcibridge: trying %u.%u.%u\n",
+			pcidev[devind].pd_busind, pcidev[devind].pd_dev, 
+			pcidev[devind].pd_func);
+#endif
+
+		if (pcidev[devind].pd_busnr != busnr)
+		{
+#if 0
+			printf("wrong bus\n");
+#endif
+			continue;
+		}
+
+		vid= pcidev[devind].pd_vid;
+		did= pcidev[devind].pd_did;
+		for (i= 0; pci_pcibridge[i].vid != 0; i++)
+		{
+			if (pci_pcibridge[i].vid != vid)
+				continue;
+			if (pci_pcibridge[i].did != did)
+				continue;
+			break;
+		}
+		type= pci_pcibridge[i].type;
+		if (pci_pcibridge[i].vid == 0)
+		{
+			headt= pci_attr_r8(devind, PCI_HEADT);
+			type= 0;
+			if ((headt & PHT_MASK) == PHT_BRIDGE)
+				type= PCI_PPB_STD;
+			else if ((headt & PHT_MASK) == PHT_CARDBUS)
+				type= PCI_PPB_CB;
+			else
+			{
+#if 0
+				printf("not a bridge\n");
+#endif
+				continue;	/* Not a bridge */
+			}
+
+			baseclass= pci_attr_r8(devind, PCI_BCR);
+			subclass= pci_attr_r8(devind, PCI_SCR);
+			infclass= pci_attr_r8(devind, PCI_PIFR);
+			t3= ((baseclass << 16) | (subclass << 8) | infclass);
+			if (type == PCI_PPB_STD &&
+				t3 != PCI_T3_PCI2PCI &&
+				t3 != PCI_T3_PCI2PCI_SUBTR)
+			{
+				printf(
+"Unknown PCI class %02x:%02x:%02x for PCI-to-PCI bridge, device %04X/%04X\n",
+					baseclass, subclass, infclass,
+					vid, did);
+				continue;
+			 }
+			if (type == PCI_PPB_CB &&
+				t3 != PCI_T3_CARDBUS)
+			{
+				printf(
+"Unknown PCI class %02x:%02x:%02x for Cardbus bridge, device %04X/%04X\n",
+					baseclass, subclass, infclass,
+					vid, did);
+				continue;
+			 }
+		}
+
+		if (debug)
+		{
+			printf("%u.%u.%u: PCI-to-PCI bridge: %04X/%04X\n",
+				pcidev[devind].pd_busnr,
+				pcidev[devind].pd_dev, 
+				pcidev[devind].pd_func, vid, did);
+		}
+
+		/* Assume that the BIOS initialized the secondary bus
+		 * number.
+		 */
+		sbusn= pci_attr_r8(devind, PPB_SECBN);
+#if DEBUG
+		printf("sbusn = %d\n", sbusn);
+		printf("subordn = %d\n", pci_attr_r8(devind, PPB_SUBORDBN));
+#endif
+
+		if (nr_pcibus >= NR_PCIBUS)
+			panic("PCI","too many PCI busses", nr_pcibus);
+		ind= nr_pcibus;
+		nr_pcibus++;
+		pcibus[ind].pb_type= PBT_PCIBRIDGE;
+		pcibus[ind].pb_needinit= 1;
+		pcibus[ind].pb_isabridge_dev= -1;
+		pcibus[ind].pb_isabridge_type= 0;
+		pcibus[ind].pb_devind= devind;
+		pcibus[ind].pb_busnr= sbusn;
+		pcibus[ind].pb_rreg8= pcibus[busind].pb_rreg8;
+		pcibus[ind].pb_rreg16= pcibus[busind].pb_rreg16;
+		pcibus[ind].pb_rreg32= pcibus[busind].pb_rreg32;
+		pcibus[ind].pb_wreg8= pcibus[busind].pb_wreg8;
+		pcibus[ind].pb_wreg16= pcibus[busind].pb_wreg16;
+		pcibus[ind].pb_wreg32= pcibus[busind].pb_wreg32;
+		switch(type)
+		{
+		case PCI_PPB_STD:
+			pcibus[ind].pb_rsts= pcibr_std_rsts;
+			pcibus[ind].pb_wsts= pcibr_std_wsts;
+			break;
+		case PCI_PPB_CB:
+			pcibus[ind].pb_type= PBT_CARDBUS;
+			pcibus[ind].pb_rsts= pcibr_cb_rsts;
+			pcibus[ind].pb_wsts= pcibr_cb_wsts;
+			break;
+		case PCI_AGPB_VIA:
+			pcibus[ind].pb_rsts= pcibr_via_rsts;
+			pcibus[ind].pb_wsts= pcibr_via_wsts;
+			break;
+		default:
+		    panic("PCI","unknown PCI-PCI bridge type", type);
+		}
+		if (sbusn == 0)
+		{
+			printf("Secondary bus number not initialized\n");
+			continue;
+		}
+		pcibus[ind].pb_needinit= 0;
+
+		probe_bus(ind);
+
+		/* Look for PCI bridges */
+		do_pcibridge(ind);
+	}
+}
+
+/*===========================================================================*
+ *				get_busind					     *
+ *===========================================================================*/
+PRIVATE int get_busind(busnr)
+int busnr;
+{
+	int i;
+
+	for (i= 0; i<nr_pcibus; i++)
+	{
+		if (pcibus[i].pb_busnr == busnr)
+			return i;
+	}
+	panic("pci", "get_busind: can't find bus", busnr);
+}
+
+/*===========================================================================*
+ *				do_piix					     *
+ *===========================================================================*/
+PRIVATE int do_piix(devind)
+int devind;
+{
+	int i, s, dev, func, irqrc, irq;
+	u32_t elcr1, elcr2, elcr;
+
+#if DEBUG
+	printf("in piix\n");
+#endif
+	dev= pcidev[devind].pd_dev;
+	func= pcidev[devind].pd_func;
+#if USER_SPACE
+	if (OK != (s=sys_inb(PIIX_ELCR1, &elcr1)))
+		printf("Warning, sys_inb failed: %d\n", s);
+	if (OK != (s=sys_inb(PIIX_ELCR2, &elcr2)))
+		printf("Warning, sys_inb failed: %d\n", s);
+#else
+	elcr1= inb(PIIX_ELCR1);
+	elcr2= inb(PIIX_ELCR2);
+#endif
+	elcr= elcr1 | (elcr2 << 8);
+	for (i= 0; i<4; i++)
+	{
+		irqrc= pci_attr_r8(devind, PIIX_PIRQRCA+i);
+		if (irqrc & PIIX_IRQ_DI)
+		{
+			if (debug)
+				printf("INT%c: disabled\n", 'A'+i);
+		}
+		else
+		{
+			irq= irqrc & PIIX_IRQ_MASK;
+			if (debug)
+				printf("INT%c: %d\n", 'A'+i, irq);
+			if (!(elcr & (1 << irq)))
+			{
+				if (debug)
+				{
+					printf(
+				"(warning) IRQ %d is not level triggered\n", 
+						irq);
+				}
+			}
+			irq_mode_pci(irq);
+		}
+	}
+	return 0;
+}
+
+/*===========================================================================*
+ *				do_amd_isabr				     *
+ *===========================================================================*/
+PRIVATE int do_amd_isabr(devind)
+int devind;
+{
+	int i, busnr, dev, func, xdevind, irq, edge;
+	u8_t levmask;
+	u16_t pciirq;
+
+	/* Find required function */
+	func= AMD_ISABR_FUNC;
+	busnr= pcidev[devind].pd_busnr;
+	dev= pcidev[devind].pd_dev;
+
+	/* Fake a device with the required function */
+	if (nr_pcidev >= NR_PCIDEV)
+		panic("PCI","too many PCI devices", nr_pcidev);
+	xdevind= nr_pcidev;
+	pcidev[xdevind].pd_busnr= busnr;
+	pcidev[xdevind].pd_dev= dev;
+	pcidev[xdevind].pd_func= func;
+	pcidev[xdevind].pd_inuse= 1;
+	nr_pcidev++;
+
+	levmask= pci_attr_r8(xdevind, AMD_ISABR_PCIIRQ_LEV);
+	pciirq= pci_attr_r16(xdevind, AMD_ISABR_PCIIRQ_ROUTE);
+	for (i= 0; i<4; i++)
+	{
+		edge= (levmask >> i) & 1;
+		irq= (pciirq >> (4*i)) & 0xf;
+		if (!irq)
+		{
+			if (debug)
+				printf("INT%c: disabled\n", 'A'+i);
+		}
+		else
+		{
+			if (debug)
+				printf("INT%c: %d\n", 'A'+i, irq);
+			if (edge && debug)
+			{
+				printf(
+				"(warning) IRQ %d is not level triggered\n",
+					irq);
+			}
+			irq_mode_pci(irq);
+		}
+	}
+	nr_pcidev--;
+	return 0;
+}
+
+/*===========================================================================*
+ *				do_sis_isabr				     *
+ *===========================================================================*/
+PRIVATE int do_sis_isabr(devind)
+int devind;
+{
+	int i, dev, func, irq;
+
+	dev= pcidev[devind].pd_dev;
+	func= pcidev[devind].pd_func;
+	irq= 0;	/* lint */
+	for (i= 0; i<4; i++)
+	{
+		irq= pci_attr_r8(devind, SIS_ISABR_IRQ_A+i);
+		if (irq & SIS_IRQ_DISABLED)
+		{
+			if (debug)
+				printf("INT%c: disabled\n", 'A'+i);
+		}
+		else
+		{
+			irq &= SIS_IRQ_MASK;
+			if (debug)
+				printf("INT%c: %d\n", 'A'+i, irq);
+			irq_mode_pci(irq);
+		}
+	}
+	return 0;
+}
+
+/*===========================================================================*
+ *				do_via_isabr				     *
+ *===========================================================================*/
+PRIVATE int do_via_isabr(devind)
+int devind;
+{
+	int i, dev, func, irq, edge;
+	u8_t levmask;
+
+	dev= pcidev[devind].pd_dev;
+	func= pcidev[devind].pd_func;
+	levmask= pci_attr_r8(devind, VIA_ISABR_EL);
+	irq= 0;	/* lint */
+	edge= 0; /* lint */
+	for (i= 0; i<4; i++)
+	{
+		switch(i)
+		{
+		case 0:
+			edge= (levmask & VIA_ISABR_EL_INTA);
+			irq= pci_attr_r8(devind, VIA_ISABR_IRQ_R2) >> 4;
+			break;
+		case 1:
+			edge= (levmask & VIA_ISABR_EL_INTB);
+			irq= pci_attr_r8(devind, VIA_ISABR_IRQ_R2);
+			break;
+		case 2:
+			edge= (levmask & VIA_ISABR_EL_INTC);
+			irq= pci_attr_r8(devind, VIA_ISABR_IRQ_R3) >> 4;
+			break;
+		case 3:
+			edge= (levmask & VIA_ISABR_EL_INTD);
+			irq= pci_attr_r8(devind, VIA_ISABR_IRQ_R1) >> 4;
+			break;
+		default:
+			assert(0);
+		}
+		irq &= 0xf;
+		if (!irq)
+		{
+			if (debug)
+				printf("INT%c: disabled\n", 'A'+i);
+		}
+		else
+		{
+			if (debug)
+				printf("INT%c: %d\n", 'A'+i, irq);
+			if (edge && debug)
+			{
+				printf(
+				"(warning) IRQ %d is not level triggered\n",
+					irq);
+			}
+			irq_mode_pci(irq);
+		}
+	}
+	return 0;
+}
+
+
+/*===========================================================================*
+ *				report_vga				     *
+ *===========================================================================*/
+PRIVATE void report_vga(devind)
+int devind;
+{
+	/* Report the amount of video memory. This is needed by the X11R6
+	 * postinstall script to chmem the X server. Hopefully this can be
+	 * removed when we get virtual memory.
+	 */
+	size_t amount, size;
+	int i;
+
+	amount= 0;
+	for (i= 0; i<pcidev[devind].pd_bar_nr; i++)
+	{
+		if (pcidev[devind].pd_bar[i].pb_flags & PBF_IO)
+			continue;
+		size= pcidev[devind].pd_bar[i].pb_size;
+		if (size < amount)
+			continue;
+		amount= size;
+	}
+	if (size != 0)
+	{
+		printf("PCI: video memory for device at %d.%d.%d: %d bytes\n",
+			pcidev[devind].pd_busnr,
+			pcidev[devind].pd_dev,
+			pcidev[devind].pd_func,
+			amount);
+	}
+}
+
+
+/*===========================================================================*
+ *				pci_vid_name				     *
+ *===========================================================================*/
+PRIVATE char *pci_vid_name(vid)
+u16_t vid;
+{
+	int i;
+
+	for (i= 0; pci_vendor_table[i].name; i++)
+	{
+		if (pci_vendor_table[i].vid == vid)
+			return pci_vendor_table[i].name;
+	}
+	return "unknown";
+}
+
+/*===========================================================================*
+ *				pci_baseclass_name			     *
+ *===========================================================================*/
+PRIVATE char *pci_baseclass_name(baseclass)
+u8_t baseclass;
+{
+	int i;
+
+	for (i= 0; pci_baseclass_table[i].name; i++)
+	{
+		if (pci_baseclass_table[i].baseclass == baseclass)
+			return pci_baseclass_table[i].name;
+	}
+	return NULL;
+}
+
+/*===========================================================================*
+ *				pci_subclass_name			     *
+ *===========================================================================*/
+PRIVATE char *pci_subclass_name(baseclass, subclass, infclass)
+u8_t baseclass;
+u8_t subclass;
+u8_t infclass;
+{
+	int i;
+
+	for (i= 0; pci_subclass_table[i].name; i++)
+	{
+		if (pci_subclass_table[i].baseclass != baseclass)
+			continue;
+		if (pci_subclass_table[i].subclass != subclass)
+			continue;
+		if (pci_subclass_table[i].infclass != infclass &&
+			pci_subclass_table[i].infclass != (u16_t)-1)
+		{
+			continue;
+		}
+		return pci_subclass_table[i].name;
+	}
+	return NULL;
+}
+
+/*===========================================================================*
+ *				ntostr					     *
+ *===========================================================================*/
+PRIVATE void ntostr(n, str, end)
+unsigned n;
+char **str;
+char *end;
+{
+	char tmpstr[20];
+	int i;
+
+	if (n == 0)
+	{
+		tmpstr[0]= '0';
+		i= 1;
+	}
+	else
+	{
+		for (i= 0; n; i++)
+		{
+			tmpstr[i]= '0' + (n%10);
+			n /= 10;
+		}
+	}
+	for (; i>0; i--)
+	{
+		if (*str == end)
+		{
+			break;
+		}
+		**str= tmpstr[i-1];
+		(*str)++;
+	}
+	if (*str == end)	
+		end[-1]= '\0';
+	else
+		**str= '\0';
+}
+
+/*===========================================================================*
+ *				pci_attr_rsts				     *
+ *===========================================================================*/
+PRIVATE u16_t pci_attr_rsts(devind)
+int devind;
+{
+	int busnr, busind;
+
+	busnr= pcidev[devind].pd_busnr;
+	busind= get_busind(busnr);
+	return pcibus[busind].pb_rsts(busind);
+}
+				
+
+/*===========================================================================*
+ *				pcibr_std_rsts				     *
+ *===========================================================================*/
+PRIVATE u16_t pcibr_std_rsts(busind)
+int busind;
+{
+	int devind;
+
+	devind= pcibus[busind].pb_devind;
+	return pci_attr_r16(devind, PPB_SSTS);
+}
+
+/*===========================================================================*
+ *				pcibr_std_wsts				     *
+ *===========================================================================*/
+PRIVATE void pcibr_std_wsts(busind, value)
+int busind;
+u16_t value;
+{
+	int devind;
+	devind= pcibus[busind].pb_devind;
+
+#if 0
+	printf("pcibr_std_wsts(%d, 0x%X), devind= %d\n", 
+		busind, value, devind);
+#endif
+	pci_attr_w16(devind, PPB_SSTS, value);
+}
+
+/*===========================================================================*
+ *				pcibr_cb_rsts				     *
+ *===========================================================================*/
+PRIVATE u16_t pcibr_cb_rsts(busind)
+int busind;
+{
+	int devind;
+	devind= pcibus[busind].pb_devind;
+
+	return pci_attr_r16(devind, CBB_SSTS);
+}
+
+/*===========================================================================*
+ *				pcibr_cb_wsts				     *
+ *===========================================================================*/
+PRIVATE void pcibr_cb_wsts(busind, value)
+int busind;
+u16_t value;
+{
+	int devind;
+	devind= pcibus[busind].pb_devind;
+
+#if 0
+	printf("pcibr_cb_wsts(%d, 0x%X), devind= %d\n", 
+		busind, value, devind);
+#endif
+	pci_attr_w16(devind, CBB_SSTS, value);
+}
+
+/*===========================================================================*
+ *				pcibr_via_rsts				     *
+ *===========================================================================*/
+PRIVATE u16_t pcibr_via_rsts(busind)
+int busind;
+{
+	int devind;
+	devind= pcibus[busind].pb_devind;
+
+	return 0;
+}
+
+/*===========================================================================*
+ *				pcibr_via_wsts				     *
+ *===========================================================================*/
+PRIVATE void pcibr_via_wsts(busind, value)
+int busind;
+u16_t value;
+{
+	int devind;
+	devind= pcibus[busind].pb_devind;
+
+#if 0
+	printf("pcibr_via_wsts(%d, 0x%X), devind= %d (not implemented)\n", 
+		busind, value, devind);
+#endif
+}
+
+/*===========================================================================*
+ *				pci_attr_wsts				     *
+ *===========================================================================*/
+PRIVATE void pci_attr_wsts(devind, value)
+int devind;
+u16_t value;
+{
+	int busnr, busind;
+
+	busnr= pcidev[devind].pd_busnr;
+	busind= get_busind(busnr);
+	pcibus[busind].pb_wsts(busind, value);
+}
+				
+
+/*===========================================================================*
+ *				pcii_rreg8				     *
+ *===========================================================================*/
+PRIVATE u8_t pcii_rreg8(busind, devind, port)
+int busind;
+int devind;
+int port;
+{
+	u8_t v;
+	int s;
+
+	v= PCII_RREG8_(pcibus[busind].pb_busnr, 
+		pcidev[devind].pd_dev, pcidev[devind].pd_func,
+		port);
+#if USER_SPACE
+	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
+		printf("PCI: warning, sys_outl failed: %d\n", s);
+#else
+	outl(PCII_CONFADD, PCII_UNSEL);
+#endif
+#if 0
+	printf("pcii_rreg8(%d, %d, 0x%X): %d.%d.%d= 0x%X\n",
+		busind, devind, port,
+		pcibus[busind].pb_bus, pcidev[devind].pd_dev,
+		pcidev[devind].pd_func, v);
+#endif
+	return v;
+}
+
+/*===========================================================================*
+ *				pcii_rreg16				     *
+ *===========================================================================*/
+PRIVATE u16_t pcii_rreg16(busind, devind, port)
+int busind;
+int devind;
+int port;
+{
+	u16_t v;
+	int s;
+
+	v= PCII_RREG16_(pcibus[busind].pb_busnr, 
+		pcidev[devind].pd_dev, pcidev[devind].pd_func,
+		port);
+#if USER_SPACE
+	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
+		printf("PCI: warning, sys_outl failed: %d\n");
+#else
+	outl(PCII_CONFADD, PCII_UNSEL);
+#endif
+#if 0
+	printf("pcii_rreg16(%d, %d, 0x%X): %d.%d.%d= 0x%X\n",
+		busind, devind, port,
+		pcibus[busind].pb_bus, pcidev[devind].pd_dev,
+		pcidev[devind].pd_func, v);
+#endif
+	return v;
+}
+
+/*===========================================================================*
+ *				pcii_rreg32				     *
+ *===========================================================================*/
+PRIVATE u32_t pcii_rreg32(busind, devind, port)
+int busind;
+int devind;
+int port;
+{
+	u32_t v;
+	int s;
+
+	v= PCII_RREG32_(pcibus[busind].pb_busnr, 
+		pcidev[devind].pd_dev, pcidev[devind].pd_func,
+		port);
+#if USER_SPACE
+	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
+		printf("PCI: warning, sys_outl failed: %d\n", s);
+#else
+	outl(PCII_CONFADD, PCII_UNSEL);
+#endif
+#if 0
+	printf("pcii_rreg32(%d, %d, 0x%X): %d.%d.%d= 0x%X\n",
+		busind, devind, port,
+		pcibus[busind].pb_bus, pcidev[devind].pd_dev,
+		pcidev[devind].pd_func, v);
+#endif
+	return v;
+}
+
+/*===========================================================================*
+ *				pcii_wreg8				     *
+ *===========================================================================*/
+PRIVATE void pcii_wreg8(busind, devind, port, value)
+int busind;
+int devind;
+int port;
+u8_t value;
+{
+	int s;
+#if 0
+	printf("pcii_wreg8(%d, %d, 0x%X, 0x%X): %d.%d.%d\n",
+		busind, devind, port, value,
+		pcibus[busind].pb_bus, pcidev[devind].pd_dev,
+		pcidev[devind].pd_func);
+#endif
+	PCII_WREG8_(pcibus[busind].pb_busnr, 
+		pcidev[devind].pd_dev, pcidev[devind].pd_func,
+		port, value);
+#if USER_SPACE
+	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
+		printf("PCI: warning, sys_outl failed: %d\n", s);
+#else
+	outl(PCII_CONFADD, PCII_UNSEL);
+#endif
+}
+
+/*===========================================================================*
+ *				pcii_wreg16				     *
+ *===========================================================================*/
+PRIVATE void pcii_wreg16(busind, devind, port, value)
+int busind;
+int devind;
+int port;
+u16_t value;
+{
+	int s;
+#if 0
+	printf("pcii_wreg16(%d, %d, 0x%X, 0x%X): %d.%d.%d\n",
+		busind, devind, port, value,
+		pcibus[busind].pb_bus, pcidev[devind].pd_dev,
+		pcidev[devind].pd_func);
+#endif
+	PCII_WREG16_(pcibus[busind].pb_busnr, 
+		pcidev[devind].pd_dev, pcidev[devind].pd_func,
+		port, value);
+#if USER_SPACE
+	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
+		printf("PCI: warning, sys_outl failed: %d\n", s);
+#else
+	outl(PCII_CONFADD, PCII_UNSEL);
+#endif
+}
+
+/*===========================================================================*
+ *				pcii_wreg32				     *
+ *===========================================================================*/
+PRIVATE void pcii_wreg32(busind, devind, port, value)
+int busind;
+int devind;
+int port;
+u32_t value;
+{
+	int s;
+#if 0
+	printf("pcii_wreg32(%d, %d, 0x%X, 0x%X): %d.%d.%d\n",
+		busind, devind, port, value,
+		pcibus[busind].pb_bus, pcidev[devind].pd_dev,
+		pcidev[devind].pd_func);
+#endif
+	PCII_WREG32_(pcibus[busind].pb_busnr, 
+		pcidev[devind].pd_dev, pcidev[devind].pd_func,
+		port, value);
+#if USER_SPACE
+	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
+		printf("PCI: warning, sys_outl failed: %d\n");
+#else
+	outl(PCII_CONFADD, PCII_UNSEL);
+#endif
+}
+
+/*===========================================================================*
+ *				pcii_rsts				     *
+ *===========================================================================*/
+PRIVATE u16_t pcii_rsts(busind)
+int busind;
+{
+	u16_t v;
+	int s;
+
+	v= PCII_RREG16_(pcibus[busind].pb_busnr, 0, 0, PCI_SR);
+#if USER_SPACE
+	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
+		printf("PCI: warning, sys_outl failed: %d\n", s);
+#else
+	outl(PCII_CONFADD, PCII_UNSEL);
+#endif
+	return v;
+}
+
+/*===========================================================================*
+ *				pcii_wsts				     *
+ *===========================================================================*/
+PRIVATE void pcii_wsts(busind, value)
+int busind;
+u16_t value;
+{
+	int s;
+	PCII_WREG16_(pcibus[busind].pb_busnr, 0, 0, PCI_SR, value);
+#if USER_SPACE
+	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
+		printf("PCI: warning, sys_outl failed: %d\n", s);
+#else
+	outl(PCII_CONFADD, PCII_UNSEL);
+#endif
+}
+
+
+/*===========================================================================*
+ *				print_capabilities			     *
+ *===========================================================================*/
+PRIVATE void print_capabilities(devind)
+int devind;
+{
+	u8_t status, capptr, type, next;
+	char *str;
+
+	/* Check capabilities bit in the device status register */
+	status= pci_attr_r16(devind, PCI_SR);
+	if (!(status & PSR_CAPPTR))
+		return;
+
+	capptr= (pci_attr_r8(devind, PCI_CAPPTR) & PCI_CP_MASK);
+	while (capptr != 0)
+	{
+		type = pci_attr_r8(devind, capptr+CAP_TYPE);
+		next= (pci_attr_r8(devind, capptr+CAP_NEXT) & PCI_CP_MASK);
+		switch(type)
+		{
+		case 1: str= "PCI Power Management"; break;
+		case 2: str= "AGP"; break;
+		case 3: str= "Vital Product Data"; break;
+		case 4:	str= "Slot Identification"; break;
+		case 5: str= "Message Signaled Interrupts"; break;
+		case 6: str= "CompactPCI Hot Swap"; break;
+		case 8: str= "AMD HyperTransport"; break;
+		case 0xf: str= "AMD I/O MMU"; break;
+		defuault: str= "(unknown type)"; break;
+		}
+
+		printf(" @0x%x: capability type 0x%x: %s\n",
+			capptr, type, str);
+		capptr= next;
+	}
+}
+
+/*
+ * $PchId: pci.c,v 1.7 2003/08/07 09:06:51 philip Exp $
+ */
Index: /trunk/minix/drivers/pci/pci.h
===================================================================
--- /trunk/minix/drivers/pci/pci.h	(revision 9)
+++ /trunk/minix/drivers/pci/pci.h	(revision 9)
@@ -0,0 +1,90 @@
+/*
+pci.h
+
+Created:	Jan 2000 by Philip Homburg <philip@cs.vu.nl>
+*/
+
+/* tempory functions: to be replaced later (see pci_intel.h) */
+_PROTOTYPE( unsigned pci_inb, (U16_t port) );
+_PROTOTYPE( unsigned pci_inw, (U16_t port) );
+_PROTOTYPE( unsigned pci_inl, (U16_t port) );
+
+_PROTOTYPE( void pci_outb, (U16_t port, U8_t value) );
+_PROTOTYPE( void pci_outw, (U16_t port, U16_t value) );
+_PROTOTYPE( void pci_outl, (U16_t port, U32_t value) );
+
+struct pci_vendor
+{
+	u16_t vid;
+	char *name;
+};
+
+struct pci_device
+{
+	u16_t vid;
+	u16_t did;
+	char *name;
+};
+
+struct pci_baseclass
+{
+	u8_t baseclass;
+	char *name;
+};
+
+struct pci_subclass
+{
+	u8_t baseclass;
+	u8_t subclass;
+	u16_t infclass;
+	char *name;
+};
+
+struct pci_intel_ctrl
+{
+	u16_t vid;
+	u16_t did;
+};
+
+struct pci_isabridge
+{
+	u16_t vid;
+	u16_t did;
+	int checkclass;
+	int type;
+};
+
+struct pci_pcibridge
+{
+	u16_t vid;
+	u16_t did;
+	int type;
+};
+
+#define PCI_IB_PIIX	1	/* Intel PIIX compatible ISA bridge */
+#define PCI_IB_VIA	2	/* VIA compatible ISA bridge */
+#define PCI_IB_AMD	3	/* AMD compatible ISA bridge */
+#define PCI_IB_SIS	4	/* SIS compatible ISA bridge */
+
+#define PCI_PPB_STD	1	/* Standard PCI-to-PCI bridge */
+#define PCI_PPB_CB	2	/* Cardbus bridge */
+/* Still needed? */
+#define PCI_AGPB_VIA	3	/* VIA compatible AGP bridge */
+
+extern struct pci_vendor pci_vendor_table[];
+extern struct pci_device pci_device_table[];
+extern struct pci_baseclass pci_baseclass_table[];
+extern struct pci_subclass pci_subclass_table[];
+#if 0
+extern struct pci_intel_ctrl pci_intel_ctrl[];
+#endif
+extern struct pci_isabridge pci_isabridge[];
+extern struct pci_pcibridge pci_pcibridge[];
+
+/* Utility functions */
+_PROTOTYPE( void pci_reserve3, (int devind, int proc, char name[M3_STRING]));
+_PROTOTYPE( void pci_release, (char name[M3_STRING])			);
+
+/*
+ * $PchId: pci.h,v 1.4 2001/12/06 20:21:22 philip Exp $
+ */
Index: /trunk/minix/drivers/pci/pci_amd.h
===================================================================
--- /trunk/minix/drivers/pci/pci_amd.h	(revision 9)
+++ /trunk/minix/drivers/pci/pci_amd.h	(revision 9)
@@ -0,0 +1,21 @@
+/*
+pci_amd.h
+
+Created:	Nov 2001 by Philip Homburg <philip@cs.vu.nl>
+*/
+
+#define AMD_ISABR_FUNC 3	/* Registers are in function 3 */
+#define		AMD_ISABR_PCIIRQ_LEV	0x54
+#define			AMD_PCILEV_INTA		0x1
+#define			AMD_PCILEV_INTB		0x2
+#define			AMD_PCILEV_INTC		4x2
+#define			AMD_PCILEV_INTD		4x8
+#define		AMD_ISABR_PCIIRQ_ROUTE	0x56
+#define			AMD_PCIIRQ_INTA_MASK	0x000F
+#define			AMD_PCIIRQ_INTB_MASK	0x00F0
+#define			AMD_PCIIRQ_INTC_MASK	0x0F00
+#define			AMD_PCIIRQ_INTD_MASK	0xF000
+
+/*
+ * $PchId: pci_amd.h,v 1.1 2001/11/09 19:57:37 philip Exp $
+ */
Index: /trunk/minix/drivers/pci/pci_intel.h
===================================================================
--- /trunk/minix/drivers/pci/pci_intel.h	(revision 9)
+++ /trunk/minix/drivers/pci/pci_intel.h	(revision 9)
@@ -0,0 +1,58 @@
+/*
+pci_intel.h
+
+Created:	Jan 2000 by Philip Homburg <philip@cs.vu.nl>
+*/
+
+#define PCII_CONFADD	0xCF8
+#define		PCIIC_CODE		0x80000000
+#define		PCIIC_BUSNUM_MASK	  0xff0000
+#define		PCIIC_BUSNUM_SHIFT	        16
+#define		PCIIC_DEVNUM_MASK	    0xf800
+#define		PCIIC_DEVNUM_SHIFT	        11
+#define		PCIIC_FUNCNUM_MASK	     0x700
+#define		PCIIC_FUNCNUM_SHIFT	         8
+#define		PCIIC_REGNUM_MASK	      0xfc
+#define		PCIIC_REGNUM_SHIFT	         2
+#define PCII_CONFDATA	0xCFC
+
+#define PCII_SELREG_(bus, dev, func, reg) \
+	(PCIIC_CODE | \
+	    (((bus) << PCIIC_BUSNUM_SHIFT) & PCIIC_BUSNUM_MASK) | \
+	    (((dev) << PCIIC_DEVNUM_SHIFT) & PCIIC_DEVNUM_MASK) | \
+	    (((func) << PCIIC_FUNCNUM_SHIFT) & PCIIC_FUNCNUM_MASK) | \
+	    ((((reg)/4) << PCIIC_REGNUM_SHIFT) & PCIIC_REGNUM_MASK))
+#define PCII_UNSEL 	(0)
+
+#define PCII_RREG8_(bus, dev, func, reg) \
+	(pci_outl(PCII_CONFADD, PCII_SELREG_(bus, dev, func, reg)), \
+	pci_inb(PCII_CONFDATA+((reg)&3)))
+#define PCII_RREG16_(bus, dev, func, reg) \
+	(PCII_RREG8_(bus, dev, func, reg) | \
+	(PCII_RREG8_(bus, dev, func, reg+1) << 8))
+#define PCII_RREG32_(bus, dev, func, reg) \
+	(PCII_RREG16_(bus, dev, func, reg) | \
+	(PCII_RREG16_(bus, dev, func, reg+2) << 16))
+
+#define PCII_WREG8_(bus, dev, func, reg, val) \
+	(pci_outl(PCII_CONFADD, PCII_SELREG_(bus, dev, func, reg)), \
+	pci_outb(PCII_CONFDATA+((reg)&3), (val)))
+#define PCII_WREG16_(bus, dev, func, reg, val) \
+	(PCII_WREG8_(bus, dev, func, reg, (val)), \
+	(PCII_WREG8_(bus, dev, func, reg+1, (val) >> 8)))
+#define PCII_WREG32_(bus, dev, func, reg, val) \
+	(PCII_WREG16_(bus, dev, func, reg, (val)), \
+	(PCII_WREG16_(bus, dev, func, reg+2, (val) >> 16)))
+
+/* PIIX configuration registers */
+#define PIIX_PIRQRCA	0x60
+#define 	PIIX_IRQ_DI	0x80
+#define 	PIIX_IRQ_MASK	0x0F
+
+/* PIIX extensions to the PIC */
+#define PIIX_ELCR1	0x4D0
+#define PIIX_ELCR2	0x4D1
+
+/*
+ * $PchId: pci_intel.h,v 1.1 2000/08/12 11:20:17 philip Exp $
+ */
Index: /trunk/minix/drivers/pci/pci_sis.h
===================================================================
--- /trunk/minix/drivers/pci/pci_sis.h	(revision 9)
+++ /trunk/minix/drivers/pci/pci_sis.h	(revision 9)
@@ -0,0 +1,17 @@
+/*
+pci_sis.h
+
+Created:	Nov 2001 by Philip Homburg <philip@cs.vu.nl>
+*/
+
+/* Constants are taken from pci-irq.c in the Linux kernel source */
+#define SIS_ISABR_IRQ_A 0x41	/* IRQA routing */
+#define SIS_ISABR_IRQ_B 0x42	/* IRQB routing */
+#define SIS_ISABR_IRQ_C 0x43	/* IRQC routing */
+#define SIS_ISABR_IRQ_D 0x44	/* IRQD routing */
+#define 	SIS_IRQ_DISABLED	0x80
+#define		SIS_IRQ_MASK		0x0F
+
+/*
+ * $PchId: pci_sis.h,v 1.1 2001/12/06 20:22:52 philip Exp $
+ */
Index: /trunk/minix/drivers/pci/pci_table.c
===================================================================
--- /trunk/minix/drivers/pci/pci_table.c	(revision 9)
+++ /trunk/minix/drivers/pci/pci_table.c	(revision 9)
@@ -0,0 +1,298 @@
+/*
+pci_table.c
+
+Tables with PCI vendor and device identifiers
+
+Created:	Jan 2000 by Philip Homburg <philip@cs.vu.nl>
+
+See the Linux PCI ID Repository <http://pciids.sourceforge.net/>.
+*/
+
+/* Changes from original Minix 2.0.4 version (2003-09-05):
+ * 2003-11-30 (kjb) Minix 2.0.4 FIX.TAZ add D-Link RTL8139 (0x1186, 0x1300)
+ * 2004-08-08 (asw) add Intel 82371AB (0x8086, 0x7100) 
+ */
+
+#include "../drivers.h"
+#include "pci.h"
+#if __minix_vmd
+#include "config.h"
+#endif
+
+struct pci_vendor pci_vendor_table[]=
+{
+	{ 0x1000, "NCR" },
+	{ 0x1002, "ATI Technologies" },
+	{ 0x100B, "National Semiconductor Corporation" },
+	{ 0x1013, "Cirrus Logic" },
+	{ 0x1022, "Advanced Micro Devices" },
+	{ 0x102B, "Matrox Graphics, Inc." },
+	{ 0x1039, "Silicon Integrated Systems (SiS)" },
+	{ 0x104C, "Texas Instruments" },
+	{ 0x105A, "Promise Technology" },
+	{ 0x10B7, "3Com Corporation" },
+	{ 0x10B9, "AcerLabs (ALI)" },
+	{ 0x10C8, "Neomagic Corporation" },
+	{ 0x10DE, "nVidia Corporation" },
+	{ 0x10EC, "Realtek" },
+	{ 0x1106, "VIA" },
+	{ 0x110A, "Siemens Nixdorf AG" },
+	{ 0x125D, "ESS Technology" },
+	{ 0x1274, "Ensoniq" },
+	{ 0x5333, "S3" },
+	{ 0x8086, "Intel" },
+	{ 0x9004, "Adaptec" },
+	{ 0x9005, "Adaptec" },
+	{ 0x0000, NULL }
+};
+
+struct pci_device pci_device_table[]=
+{
+	{ 0x1000, 0x0001, "NCR 53C810" },
+	{ 0x1000, 0x000F, "NCR 53C875" },
+	{ 0x1002, 0x4752, "ATI Rage XL PCI" },
+	{ 0x100B, 0xD001, "Nat. Semi. 87410" },
+	{ 0x1013, 0x00B8, "Cirrus Logic GD 5446" },
+	{ 0x1013, 0x6003, "Cirrus Logic CS4614/22/24 CrystalClear" },
+	{ 0x1022, 0x1100, "K8 HyperTransport Tech. Conf." },
+	{ 0x1022, 0x1101, "K8 [Athlon64/Opteron] Address Map" },
+	{ 0x1022, 0x1102, "K8 [Athlon64/Opteron] DRAM Controller" },
+	{ 0x1022, 0x1103, "K8 [Athlon64/Opteron] Misc. Control" },
+	{ 0x1022, 0x2000, "AMD Lance/PCI" },
+	{ 0x1022, 0x700C, "AMD-762 CPU to PCI Bridge (SMP chipset)" },
+	{ 0x1022, 0x700D, "AMD-762 CPU to PCI Bridge (AGP 4x)" },
+	{ 0x1022, 0x7410, "AMD-766 PCI to ISA/LPC Bridge" },
+	{ 0x1022, 0x7411, "AMD-766 EIDE Controller" },
+	{ 0x102B, 0x051B, "Matrox MGA 2164W [Millennium II]" },
+	{ 0x102B, 0x0525, "Matrox MGA G400 AGP" },
+	{ 0x1039, 0x0008, "SiS 85C503/5513" },
+	{ 0x1039, 0x0200, "SiS 5597/5598 VGA" },
+	{ 0x1039, 0x0406, "SiS 85C501/2" },
+	{ 0x1039, 0x5597, "SiS 5582" },
+	{ 0x104C, 0xAC1C, "TI PCI1225" },
+	{ 0x105A, 0x0D30, "Promise Technology 20265" },
+	{ 0x10B7, 0x9058, "3Com 3c905B-Combo" },
+	{ 0x10B7, 0x9805, "3Com 3c980-TX Python-T" },
+	{ 0x10B9, 0x1533, "ALI M1533 ISA-bridge [Aladdin IV]" },
+	{ 0x10B9, 0x1541, "ALI M1541" },
+	{ 0x10B9, 0x5229, "ALI M5229 (IDE)" },
+	{ 0x10B9, 0x5243, "ALI M5243" },
+	{ 0x10B9, 0x7101, "ALI M7101 PMU" },
+	{ 0x10C8, 0x0005, "Neomagic NM2200 Magic Graph 256AV" },
+	{ 0x10C8, 0x8005, "Neomagic NM2200 Magic Graph 256AV Audio" },
+	{ 0x10DE, 0x0020, "nVidia Riva TnT [NV04]" },
+	{ 0x10DE, 0x0110, "nVidia GeForce2 MX [NV11]" },
+	{ 0x10EC, 0x8029, "Realtek RTL8029" },
+	{ 0x10EC, 0x8139, "Realtek RTL8139" },
+	{ 0x1106, 0x0305, "VIA VT8363/8365 [KT133/KM133]" },
+	{ 0x1106, 0x0571, "VIA IDE controller" },
+	{ 0x1106, 0x0686, "VIA VT82C686 (Apollo South Bridge)" },
+	{ 0x1106, 0x1204, "K8M800 Host Bridge" },
+	{ 0x1106, 0x2204, "K8M800 Host Bridge" },
+	{ 0x1106, 0x3038, "VT83C572 PCI USB Controller" },
+	{ 0x1106, 0x3057, "VT82C686A ACPI Power Management Controller" },
+	{ 0x1106, 0x3058, "VIA AC97 Audio Controller" },
+	{ 0x1106, 0x3059, "VIA AC97 Audio Controller" },
+	{ 0x1106, 0x3065, "VT6102 [Rhine-II]" },
+	{ 0x1106, 0x3074, "VIA VT8233" },
+	{ 0x1106, 0x3099, "VIA VT8367 [KT266]" },
+	{ 0x1106, 0x3104, "VIA USB 2.0" },
+	{ 0x1106, 0x3108, "VIA S3 Unichrome Pro VGA Adapter" },
+	{ 0x1106, 0x3149, "VIA VT6420 SATA RAID Controller" },
+	{ 0x1106, 0x3204, "K8M800 Host Bridge" },
+	{ 0x1106, 0x3227, "VT8237 ISA bridge" },
+	{ 0x1106, 0x4204, "K8M800 Host Bridge" },
+	{ 0x1106, 0x8305, "VIA VT8365 [KM133 AGP]" },
+	{ 0x1106, 0xB099, "VIA VT8367 [KT266 AGP]" },
+	{ 0x1106, 0xB188, "VT8237 PCI bridge" },
+	{ 0x110A, 0x0005, "Siemens Nixdorf Tulip Cntlr., Power Management" },
+	{ 0x1186, 0x1300, "D-Link RTL8139" },
+	{ 0x125D, 0x1969, "ESS ES1969 Solo-1 Audiodrive" },
+	{ 0x1274, 0x1371, "Ensoniq ES1371 [AudioPCI-97]" },
+	{ 0x1274, 0x5000, "Ensoniq ES1370" },
+	{ 0x1274, 0x5880, "Ensoniq CT5880 [AudioPCI]" },
+	{ 0x5333, 0x8811, "S3 86c764/765 [Trio32/64/64V+]" },
+	{ 0x5333, 0x883d, "S3 Virge/VX" },
+	{ 0x5333, 0x88d0, "S3 Vision 964 vers 0" },
+	{ 0x5333, 0x8a01, "S3 Virge/DX or /GX" },
+	{ 0x8086, 0x1004, "Intel 82543GC Gigabit Ethernet Controller" },
+ 	{ 0x8086, 0x1029, "Intel EtherExpressPro100 ID1029" },
+ 	{ 0x8086, 0x1030, "Intel Corporation 82559 InBusiness 10/100" },
+ 	{ 0x8086, 0x1209, "Intel EtherExpressPro100 82559ER" },
+ 	{ 0x8086, 0x1229, "Intel EtherExpressPro100 82557/8/9" },
+	{ 0x8086, 0x122D, "Intel 82437FX" },
+	{ 0x8086, 0x122E, "Intel 82371FB (PIIX)" },
+	{ 0x8086, 0x1230, "Intel 82371FB (IDE)" },
+	{ 0x8086, 0x1237, "Intel 82441FX (440FX)" },
+	{ 0x8086, 0x1250, "Intel 82439HX" },
+	{ 0x8086, 0x1A30, "Intel 82845B/A MCH" },
+	{ 0x8086, 0x1A31, "Intel 82845B/A PCI Bridge to AGP port" },
+	{ 0x8086, 0x2440, "Intel 82801B PCI to ISA bridge" },
+ 	{ 0x8086, 0x2449, "Intel EtherExpressPro100 82562EM" },
+ 	{ 0x8086, 0x244e, "Intel 82801 PCI Bridge" },
+ 	{ 0x8086, 0x2560, "Intel 82845G/GL[Brookdale-G]/GE/PE" },
+ 	{ 0x8086, 0x2561, "Intel 82845G/GL/GE/PE Host-to-AGP Bridge" },
+	{ 0x8086, 0x7000, "Intel 82371SB" },
+	{ 0x8086, 0x7010, "Intel 82371SB (IDE)" },
+	{ 0x8086, 0x7020, "Intel 82371SB (USB)" },
+ 	{ 0x8086, 0x7030, "Intel 82437VX" },	/* asw 2005-03-02 */
+ 	{ 0x8086, 0x7100, "Intel 82371AB" },  	/* asw 2004-07-31 */
+	{ 0x8086, 0x7100, "Intel 82371AB" },
+	{ 0x8086, 0x7110, "Intel 82371AB (PIIX4)" },
+	{ 0x8086, 0x7111, "Intel 82371AB (IDE)" },
+	{ 0x8086, 0x7112, "Intel 82371AB (USB)" },
+	{ 0x8086, 0x7113, "Intel 82371AB (Power)" },
+ 	{ 0x8086, 0x7124, "Intel 82801AA" },	/* asw 2004-11-09 */
+	{ 0x8086, 0x7190, "Intel 82443BX" },
+	{ 0x8086, 0x7191, "Intel 82443BX (AGP bridge)" },
+	{ 0x8086, 0x7192, "Intel 82443BX (Host-to-PCI bridge)" },
+	{ 0x9004, 0x8178, "Adaptec AHA-2940U/2940UW Ultra/Ultra-Wide SCSI Ctrlr" },
+	{ 0x9005, 0x0080, "Adaptec AIC-7892A Ultra160/m PCI SCSI Controller" },
+	{ 0x0000, 0x0000, NULL }
+};
+
+struct pci_baseclass pci_baseclass_table[]=
+{
+	{ 0x00, "No device class" },
+	{ 0x01, "Mass storage controller" },
+	{ 0x02, "Network controller" },
+	{ 0x03, "Display controller" },
+	{ 0x04, "Multimedia device" },
+	{ 0x05, "Memory controller" },
+	{ 0x06, "Bridge device" },
+	{ 0x07, "Simple comm. controller" },
+	{ 0x08, "Base system peripheral" },
+	{ 0x09, "Input device" },
+	{ 0x0A, "Docking station" },
+	{ 0x0B, "Processor" },
+	{ 0x0C, "Serial bus controller" },
+	{ 0x0d, "Wireless controller" },
+	{ 0x0e, "Intelligent I/O controller" },
+	{ 0x0f, "Satellite comm. controller" },
+	{ 0x10, "Encryption/decryption controller" },
+	{ 0x11, "Data acquisition controller" },
+	{ 0xff, "Misc. device" },
+
+	{ 0x00, NULL }
+};
+
+/* -1 in the infclass field is a wildcard for infclass */
+struct pci_subclass pci_subclass_table[]=
+{
+	{ 0x00, 0x01, 0x00, "VGA-compatible device" },
+
+	{ 0x01, 0x00, 0x00, "SCSI bus controller" },
+	{ 0x01, 0x01, -1,   "IDE controller" },
+	{ 0x01, 0x02, 0x00, "Floppy disk controller" },
+	{ 0x01, 0x03, 0x00, "IPI controller" },
+	{ 0x01, 0x04, 0x00, "RAID controller" },
+	{ 0x01, 0x80, 0x00, "Other mass storage controller" },
+
+	{ 0x02, 0x00, 0x00, "Ethernet controller" },
+	{ 0x02, 0x01, 0x00, "Token Ring controller" },
+	{ 0x02, 0x02, 0x00, "FDDI controller" },
+	{ 0x02, 0x03, 0x00, "ATM controller" },
+	{ 0x02, 0x04, 0x00, "ISDN controller" },
+	{ 0x02, 0x80, 0x00, "Other network controller" },
+
+	{ 0x03, 0x00, 0x00, "VGA-compatible controller" },
+	{ 0x03, 0x00, 0x01, "8514-compatible controller" },
+	{ 0x03, 0x01, 0x00, "XGA controller" },
+	{ 0x03, 0x02, 0x00, "3D controller" },
+	{ 0x03, 0x80, 0x00, "Other display controller" },
+
+	{ 0x04, 0x00, 0x00, "Video device" },
+	{ 0x04, 0x01, 0x00, "Audio device" },
+	{ 0x04, 0x02, 0x00, "Computer telephony device" },
+	{ 0x04, 0x80, 0x00, "Other multimedia device" },
+
+	{ 0x06, 0x00, 0x00, "Host bridge" },
+	{ 0x06, 0x01, 0x00, "ISA bridge" },
+	{ 0x06, 0x02, 0x00, "EISA bridge" },
+	{ 0x06, 0x03, 0x00, "MCA bridge" },
+	{ 0x06, 0x04, 0x00, "PCI-to-PCI bridge" },
+	{ 0x06, 0x04, 0x01, "Subtractive decode PCI-to-PCI bridge" },
+	{ 0x06, 0x05, 0x00, "PCMCIA bridge" },
+	{ 0x06, 0x06, 0x00, "NuBus bridge" },
+	{ 0x06, 0x07, 0x00, "CardBus bridge" },
+	{ 0x06, 0x08, -1,   "RACEway bridge" },
+	{ 0x06, 0x09, -1,   "Semi-transparent PCI-to-PCI bridge" },
+	{ 0x06, 0x80, 0x00, "Other bridge device" },
+
+	{ 0x0C, 0x00, 0x00, "IEEE 1394 (FireWire)" },
+	{ 0x0C, 0x00, 0x10, "IEEE 1394 (OpenHCI)" },
+	{ 0x0C, 0x01, 0x00, "ACCESS bus" },
+	{ 0x0C, 0x02, 0x00, "SSA" },
+	{ 0x0C, 0x03, 0x00, "USB (with UHC)" },
+	{ 0x0C, 0x03, 0x10, "USB (with OHC)" },
+	{ 0x0C, 0x03, 0x80, "USB (other host inf.)" },
+	{ 0x0C, 0x03, 0xFE, "USB device" },
+	{ 0x0C, 0x04, 0x00, "Fibre Channel" },
+	{ 0x0C, 0x05, 0x00, "SMBus" },
+
+	{ 0x00, 0x00, 0x00, NULL }
+};
+
+#if 0
+struct pci_intel_ctrl pci_intel_ctrl[]=
+{
+	{ 0x1022, 0x700C, },	/* AMD-762 */
+	{ 0x1039, 0x0406, },	/* SiS 85C501/2 */
+	{ 0x1039, 0x5597, },	/* SiS 5582 */
+	{ 0x10B9, 0x1541, },	/* ALI M1541 */
+	{ 0x1106, 0x0305, },	/* VIA VT8363/8365 */
+	{ 0x1106, 0x3099, },	/* VIA VT8367 [KT266] */
+	{ 0x1106, 0x3188, },	/* VIA */
+	{ 0x1106, 0x0282, },	/* VIA */
+	{ 0x1106, 0x0204, },	/* VIA VT8367 [KT266] */
+	{ 0x8086, 0x122D, },	/* Intel 82437FX */
+	{ 0x8086, 0x1237, }, 	/* Intel 82441FX */
+	{ 0x8086, 0x1250, },	/* Intel 82439HX */
+	{ 0x8086, 0x1A30, },	/* Intel 82845 MCH */
+	{ 0x8086, 0x2560, },	/* Intel 82845G/GL[Brookdale-G]/GE/PE */
+ 	{ 0x8086, 0x7030, },	/* Intel 82437VX (asw 2005-03-02) */ 
+ 	{ 0x8086, 0x7100, },	/* Intel 82371AB (asw 2004-07-31) */
+ 	{ 0x8086, 0x7124, },	/* Intel 82801AA (asw 2004-11-09) */
+	{ 0x8086, 0x7190, },	/* Intel 82443BX - AGP enabled */
+	{ 0x8086, 0x7192, },	/* Intel 82443BX - AGP disabled */
+	{ 0x0000, 0x0000, },
+};
+#endif
+
+struct pci_isabridge pci_isabridge[]=
+{
+	{ 0x1022, 0x7410, 1, PCI_IB_AMD,	},	/* AMD-766 */
+	{ 0x1039, 0x0008, 1, PCI_IB_SIS,	},	/* SiS 85C503/5513 */
+	{ 0x10B9, 0x1533, 1, PCI_IB_PIIX,	},	/* ALI M1533 */
+	{ 0x1106, 0x0686, 1, PCI_IB_VIA,	},	/* VIA VT82C686 */
+	{ 0x1106, 0x3074, 1, PCI_IB_VIA,	},	/* VIA VT8233 */
+	{ 0x1106, 0x3227, 1, PCI_IB_VIA,	},	/* VIA */
+	{ 0x8086, 0x122E, 1, PCI_IB_PIIX,	},	/* Intel 82371FB */
+	{ 0x8086, 0x2440, 1, PCI_IB_PIIX,	},	/* Intel 82801B */
+	{ 0x8086, 0x7000, 1, PCI_IB_PIIX,	},	/* Intel 82371SB */
+ 	{ 0x8086, 0x7030, 1, PCI_IB_PIIX,	},	/* Intel 82437VX (asw 2005-03-02) */
+ 	{ 0x8086, 0x7100, 1, PCI_IB_PIIX,	},	/* Intel 82371AB (asw 2004-07-31) */
+ 	{ 0x8086, 0x7110, 1, PCI_IB_PIIX,	},	/* Intel PIIX4 */
+ 	{ 0x8086, 0x7124, 1, PCI_IB_PIIX,	},	/* Intel 82801AA (asw 2004-11-09) */
+	{ 0x0000, 0x0000, 0, 0, 		},
+};
+
+struct pci_pcibridge pci_pcibridge[]=
+{
+#if 0
+	{ 0x8086, 0x1A31, PCI_PCIB_INTEL, },	/* Intel 82845B/A AGP Bridge */
+	{ 0x8086, 0x2448, PCI_PCIB_INTEL, },	/* Intel 82801 Mobile */
+	{ 0x8086, 0x244e, PCI_PCIB_INTEL, },	/* Intel 82801 PCI Bridge */
+	{ 0x8086, 0x2561, PCI_PCIB_INTEL, },	/* Intel 82845 AGP Bridge */
+	{ 0x8086, 0x7191, PCI_PCIB_INTEL, },	/* Intel 82443BX (AGP bridge) */
+	{ 0x1022, 0x700D, PCI_PCIB_INTEL, },	/* AMD-762 (AGP 4x) */
+	{ 0x10B9, 0x5243, PCI_PCIB_INTEL, },	/* ALI M5243 */
+	{ 0x1106, 0x8305, PCI_AGPB_VIA, },	/* VIA VT8365 [KM133 AGP] */
+	{ 0x1106, 0xB188, PCI_AGPB_VIA, },	/* VT8237 PCI bridge */
+#endif
+	{ 0x0000, 0x0000, 0, },
+};
+
+/*
+ * $PchId: pci_table.c,v 1.7 2003/09/05 10:53:22 philip Exp $
+ */
Index: /trunk/minix/drivers/pci/pci_via.h
===================================================================
--- /trunk/minix/drivers/pci/pci_via.h	(revision 9)
+++ /trunk/minix/drivers/pci/pci_via.h	(revision 9)
@@ -0,0 +1,27 @@
+/*
+pci_via.h
+
+Created:	Jun 2001 by Philip Homburg <philip@cs.vu.nl>
+*/
+
+#define VIA_ISABR_EL	0x54	/* Edge or level triggered */
+#define		VIA_ISABR_EL_INTA	0x08	/* Edge (1) or level (0) */
+#define		VIA_ISABR_EL_INTB	0x04
+#define		VIA_ISABR_EL_INTC	0x02
+#define		VIA_ISABR_EL_INTD	0x01
+
+#define VIA_ISABR_IRQ_R1 0x55	/* IRQ routing 1 */
+#define		VIA_ISABR_IRQ_INTD	0xf0	/* routing for INTD */
+#define		VIA_ISABR_IRQ_INT0	0x0f	/* routing for INT0 */
+#define VIA_ISABR_IRQ_R2 0x56	/* IRQ routing 2 */
+#define		VIA_ISABR_IRQ_INTA	0xf0	/* routing for INTA */
+#define		VIA_ISABR_IRQ_INTB	0x0f	/* routing for INTB */
+#define VIA_ISABR_IRQ_R3 0x57	/* IRQ routing 3 */
+#define		VIA_ISABR_IRQ_INTC	0xf0	/* routing for INTC */
+#define		VIA_ISABR_IRQ_INT1	0x0f	/* routing for INT1 */
+#define VIA_ISABR_IRQ_R4 0x58	/* IRQ routing 4 */
+#define		VIA_ISABR_IRQ_INT2	0x0f	/* routing for INT2 */
+
+/*
+ * $PchId: pci_via.h,v 1.1 2001/06/20 15:50:25 philip Exp $
+ */
Index: /trunk/minix/drivers/printer/.depend
===================================================================
--- /trunk/minix/drivers/printer/.depend	(revision 9)
+++ /trunk/minix/drivers/printer/.depend	(revision 9)
@@ -0,0 +1,28 @@
+
+printer.o:	../drivers.h
+printer.o:	/usr/include/ansi.h
+printer.o:	/usr/include/errno.h
+printer.o:	/usr/include/ibm/bios.h
+printer.o:	/usr/include/ibm/interrupt.h
+printer.o:	/usr/include/ibm/ports.h
+printer.o:	/usr/include/limits.h
+printer.o:	/usr/include/minix/bitmap.h
+printer.o:	/usr/include/minix/callnr.h
+printer.o:	/usr/include/minix/com.h
+printer.o:	/usr/include/minix/config.h
+printer.o:	/usr/include/minix/const.h
+printer.o:	/usr/include/minix/devio.h
+printer.o:	/usr/include/minix/dmap.h
+printer.o:	/usr/include/minix/ipc.h
+printer.o:	/usr/include/minix/sys_config.h
+printer.o:	/usr/include/minix/syslib.h
+printer.o:	/usr/include/minix/sysutil.h
+printer.o:	/usr/include/minix/type.h
+printer.o:	/usr/include/signal.h
+printer.o:	/usr/include/stddef.h
+printer.o:	/usr/include/stdlib.h
+printer.o:	/usr/include/string.h
+printer.o:	/usr/include/sys/dir.h
+printer.o:	/usr/include/sys/types.h
+printer.o:	/usr/include/unistd.h
+printer.o:	printer.c
Index: /trunk/minix/drivers/printer/Makefile
===================================================================
--- /trunk/minix/drivers/printer/Makefile	(revision 9)
+++ /trunk/minix/drivers/printer/Makefile	(revision 9)
@@ -0,0 +1,41 @@
+# Makefile for Centronics printer driver (PRINTER)
+DRIVER = printer
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsys -lsysutil
+
+OBJ = printer.o
+
+# build local binary
+all build:	$(DRIVER)
+$(DRIVER):	$(OBJ)
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+#	install -S 64w $(DRIVER)
+
+# install with other drivers
+install:	/usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER):	$(DRIVER)
+	install -o root -c $? $@
+#	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f *.o *.bak $(DRIVER)
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/printer/printer.c
===================================================================
--- /trunk/minix/drivers/printer/printer.c	(revision 9)
+++ /trunk/minix/drivers/printer/printer.c	(revision 9)
@@ -0,0 +1,421 @@
+/* This file contains the printer driver. It is a fairly simple driver,
+ * supporting only one printer.  Characters that are written to the driver
+ * are written to the printer without any changes at all.
+ *
+ * Changes:
+ *	May 07, 2004	fix: wait until printer is ready  (Jorrit N. Herder)
+ *	May 06, 2004	printer driver moved to user-space  (Jorrit N. Herder) 
+ *
+ * The valid messages and their parameters are:
+ *
+ *   DEV_OPEN:	initializes the printer
+ *   DEV_CLOSE:	does nothing
+ *   HARD_INT:	interrupt handler has finished current chunk of output
+ *   DEV_WRITE:	a process wants to write on a terminal
+ *   CANCEL:	terminate a previous incomplete system call immediately
+ *
+ *    m_type      TTY_LINE   IO_ENDPT    COUNT    ADDRESS
+ * |-------------+---------+---------+---------+---------|
+ * | DEV_OPEN    |         |         |         |         |
+ * |-------------+---------+---------+---------+---------|
+ * | DEV_CLOSE   |         | proc nr |         |         |
+ * -------------------------------------------------------
+ * | HARD_INT    |         |         |         |         |
+ * |-------------+---------+---------+---------+---------|
+ * | SYS_EVENT   |         |         |         |         |
+ * |-------------+---------+---------+---------+---------|
+ * | DEV_WRITE   |minor dev| proc nr |  count  | buf ptr |
+ * |-------------+---------+---------+---------+---------|
+ * | CANCEL      |minor dev| proc nr |         |         |
+ * -------------------------------------------------------
+ * 
+ * Note: since only 1 printer is supported, minor dev is not used at present.
+ */
+
+#include "../drivers.h"
+
+/* Control bits (in port_base + 2).  "+" means positive logic and "-" means
+ * negative logic.  Most of the signals are negative logic on the pins but
+ * many are converted to positive logic in the ports.  Some manuals are
+ * misleading because they only document the pin logic.
+ *
+ *	+0x01	Pin 1	-Strobe
+ *	+0x02	Pin 14	-Auto Feed
+ *	-0x04	Pin 16	-Initialize Printer
+ *	+0x08	Pin 17	-Select Printer
+ *	+0x10	IRQ7 Enable
+ *
+ * Auto Feed and Select Printer are always enabled. Strobe is enabled briefly
+ * when characters are output.  Initialize Printer is enabled briefly when
+ * the task is started.  IRQ7 is enabled when the first character is output
+ * and left enabled until output is completed (or later after certain
+ * abnormal completions).
+ */
+#define ASSERT_STROBE   0x1D	/* strobe a character to the interface */
+#define NEGATE_STROBE   0x1C	/* enable interrupt on interface */
+#define PR_SELECT          0x0C	/* select printer bit */
+#define INIT_PRINTER    0x08	/* init printer bits */
+
+/* Status bits (in port_base + 2).
+ *
+ *	-0x08	Pin 15	-Error
+ *	+0x10	Pin 13	+Select Status
+ *	+0x20	Pin 12	+Out of Paper
+ *	-0x40	Pin 10	-Acknowledge
+ *	-0x80	Pin 11	+Busy
+ */
+#define BUSY_STATUS     0x10	/* printer gives this status when busy */
+#define NO_PAPER        0x20	/* status bit saying that paper is out */
+#define NORMAL_STATUS   0x90	/* printer gives this status when idle */
+#define ON_LINE         0x10	/* status bit saying that printer is online */
+#define STATUS_MASK	0xB0	/* mask to filter out status bits */ 
+
+#define MAX_ONLINE_RETRIES 120  /* about 60s: waits 0.5s after each retry */
+
+/* Centronics interface timing that must be met by software (in microsec).
+ *
+ * Strobe length:	0.5u to 100u (not sure about the upper limit).
+ * Data set up:		0.5u before strobe.
+ * Data hold:		0.5u after strobe.
+ * Init pulse length:	over 200u (not sure).
+ *
+ * The strobe length is about 50u with the code here and function calls for
+ * sys_outb() - not much to spare.  The 0.5u minimums will not be violated 
+ * with the sys_outb() messages exchanged.
+ */
+
+PRIVATE int caller;		/* process to tell when printing done (FS) */
+PRIVATE int revive_pending;	/* set to true if revive is pending */
+PRIVATE int revive_status;	/* revive status */
+PRIVATE int done_status;	/* status of last output completion */
+PRIVATE int oleft;		/* bytes of output left in obuf */
+PRIVATE char obuf[128];		/* output buffer */
+PRIVATE char *optr;		/* ptr to next char in obuf to print */
+PRIVATE int orig_count;		/* original byte count */
+PRIVATE int port_base;		/* I/O port for printer */
+PRIVATE int proc_nr;		/* user requesting the printing */
+PRIVATE int user_left;		/* bytes of output left in user buf */
+PRIVATE vir_bytes user_vir;	/* address of remainder of user buf */
+PRIVATE int writing;		/* nonzero while write is in progress */
+PRIVATE int irq_hook_id;	/* id of irq hook at kernel */
+
+extern int errno;		/* error number */
+
+FORWARD _PROTOTYPE( void do_cancel, (message *m_ptr) );
+FORWARD _PROTOTYPE( void output_done, (void) );
+FORWARD _PROTOTYPE( void do_write, (message *m_ptr) );
+FORWARD _PROTOTYPE( void do_status, (message *m_ptr) );
+FORWARD _PROTOTYPE( void prepare_output, (void) );
+FORWARD _PROTOTYPE( void do_initialize, (void) );
+FORWARD _PROTOTYPE( void reply, (int code,int replyee,int proc,int status));
+FORWARD _PROTOTYPE( void do_printer_output, (void) );
+FORWARD _PROTOTYPE( void do_signal, (message *m_ptr) );
+
+
+/*===========================================================================*
+ *				printer_task				     *
+ *===========================================================================*/
+PUBLIC void main(void)
+{
+/* Main routine of the printer task. */
+  message pr_mess;		/* buffer for all incoming messages */
+  struct sigaction sa;
+  int s;
+
+  /* Install signal handlers. Ask PM to transform signal into message. */
+  sa.sa_handler = SIG_MESS;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = 0;
+  if (sigaction(SIGTERM,&sa,NULL)<0) panic("PRN","sigaction failed", errno);
+  
+  while (TRUE) {
+	receive(ANY, &pr_mess);
+	switch(pr_mess.m_type) {
+	    case DEV_OPEN:
+                 do_initialize();		/* initialize */
+	        /* fall through */
+	    case DEV_CLOSE:
+		reply(TASK_REPLY, pr_mess.m_source, pr_mess.IO_ENDPT, OK);
+		break;
+	    case DEV_WRITE:	do_write(&pr_mess);	break;
+	    case DEV_STATUS:	do_status(&pr_mess);	break;
+	    case CANCEL:	do_cancel(&pr_mess);	break;
+	    case HARD_INT:	do_printer_output();	break;
+	    case SYS_SIG:	do_signal(&pr_mess); 	break;
+	    case DEV_PING:  	notify(pr_mess.m_source);	break;
+	    case PROC_EVENT:	break;
+	    default:
+		reply(TASK_REPLY, pr_mess.m_source, pr_mess.IO_ENDPT, EINVAL);
+	}
+  }
+}
+
+
+/*===========================================================================*
+ *				 do_signal	                             *
+ *===========================================================================*/
+PRIVATE void do_signal(m_ptr)
+message *m_ptr;					/* signal message */
+{
+  int sig;
+  sigset_t sigset = m_ptr->NOTIFY_ARG;
+  
+  /* Expect a SIGTERM signal when this server must shutdown. */
+  if (sigismember(&sigset, SIGTERM)) {
+	exit(0);
+  } 
+  /* Ignore all other signals. */
+}
+
+/*===========================================================================*
+ *				do_write				     *
+ *===========================================================================*/
+PRIVATE void do_write(m_ptr)
+register message *m_ptr;	/* pointer to the newly arrived message */
+{
+/* The printer is used by sending DEV_WRITE messages to it. Process one. */
+
+    register int r = SUSPEND;
+    int retries;
+    unsigned long status;
+
+    /* Reject command if last write is not yet finished, the count is not
+     * positive, or the user address is bad.
+     */
+    if (writing)  			r = EIO;
+    else if (m_ptr->COUNT <= 0)  	r = EINVAL;
+
+    /* Reply to FS, no matter what happened, possible SUSPEND caller. */
+    reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, r);
+
+    /* If no errors occurred, continue printing with SUSPENDED caller.
+     * First wait until the printer is online to prevent stupid errors.
+     */
+    if (SUSPEND == r) { 	
+	caller = m_ptr->m_source;
+	proc_nr = m_ptr->IO_ENDPT;
+	user_left = m_ptr->COUNT;
+	orig_count = m_ptr->COUNT;
+	user_vir = (vir_bytes) m_ptr->ADDRESS;
+	writing = TRUE;
+
+        retries = MAX_ONLINE_RETRIES + 1;  
+        while (--retries > 0) {
+            sys_inb(port_base + 1, &status);
+            if ((status & ON_LINE)) {		/* printer online! */
+	        prepare_output();
+	        do_printer_output();
+	        return;
+            }
+            tickdelay(30);		/* wait before retry */
+        }
+        /* If we reach this point, the printer was not online in time. */
+        done_status = status;
+        output_done();
+    }
+}
+
+/*===========================================================================*
+ *				output_done				     *
+ *===========================================================================*/
+PRIVATE void output_done()
+{
+/* Previous chunk of printing is finished.  Continue if OK and more.
+ * Otherwise, reply to caller (FS).
+ */
+    register int status;
+
+    if (!writing) return;	  	/* probably leftover interrupt */
+    if (done_status != OK) {      	/* printer error occurred */
+        status = EIO;
+	if ((done_status & ON_LINE) == 0) { 
+	    printf("Printer is not on line\n");
+	} else if ((done_status & NO_PAPER)) { 
+	    printf("Printer is out of paper\n");
+	    status = EAGAIN;	
+	} else {
+	    printf("Printer error, status is 0x%02X\n", done_status);
+	}
+	/* Some characters have been printed, tell how many. */
+	if (status == EAGAIN && user_left < orig_count) {
+		status = orig_count - user_left;
+	}
+	oleft = 0;			/* cancel further output */
+    } 
+    else if (user_left != 0) {		/* not yet done, continue! */
+	prepare_output();
+	return;
+    } 
+    else {				/* done! report back to FS */
+	status = orig_count;
+    }
+    revive_pending = TRUE;
+    revive_status = status;
+    notify(caller);
+}
+
+/*===========================================================================*
+ *				do_status				     *
+ *===========================================================================*/
+PRIVATE void do_status(m_ptr)
+register message *m_ptr;	/* pointer to the newly arrived message */
+{
+  if (revive_pending) {
+	m_ptr->m_type = DEV_REVIVE;		/* build message */
+	m_ptr->REP_ENDPT = proc_nr;
+	m_ptr->REP_STATUS = revive_status;
+
+	writing = FALSE;			/* unmark event */
+	revive_pending = FALSE;			/* unmark event */
+  } else {
+	m_ptr->m_type = DEV_NO_STATUS;
+  }
+  send(m_ptr->m_source, m_ptr);			/* send the message */
+}
+
+/*===========================================================================*
+ *				do_cancel				     *
+ *===========================================================================*/
+PRIVATE void do_cancel(m_ptr)
+register message *m_ptr;	/* pointer to the newly arrived message */
+{
+/* Cancel a print request that has already started.  Usually this means that
+ * the process doing the printing has been killed by a signal.  It is not
+ * clear if there are race conditions.  Try not to cancel the wrong process,
+ * but rely on FS to handle the EINTR reply and de-suspension properly.
+ */
+
+  if (writing && m_ptr->IO_ENDPT == proc_nr) {
+	oleft = 0;		/* cancel output by interrupt handler */
+	writing = FALSE;
+	revive_pending = FALSE;
+  }
+  reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EINTR);
+}
+
+/*===========================================================================*
+ *				reply					     *
+ *===========================================================================*/
+PRIVATE void reply(code, replyee, process, status)
+int code;			/* TASK_REPLY or REVIVE */
+int replyee;			/* destination for message (normally FS) */
+int process;			/* which user requested the printing */
+int status;			/* number of  chars printed or error code */
+{
+/* Send a reply telling FS that printing has started or stopped. */
+
+  message pr_mess;
+
+  pr_mess.m_type = code;		/* TASK_REPLY or REVIVE */
+  pr_mess.REP_STATUS = status;		/* count or EIO */
+  pr_mess.REP_ENDPT = process;	/* which user does this pertain to */
+  send(replyee, &pr_mess);		/* send the message */
+}
+
+/*===========================================================================*
+ *				do_initialize				     *
+ *===========================================================================*/
+PRIVATE void do_initialize()
+{
+/* Set global variables and initialize the printer. */
+  static int initialized = FALSE;
+  if (initialized) return;
+  initialized = TRUE;
+  
+  /* Get the base port for first printer.  */
+  sys_vircopy(SELF, BIOS_SEG, LPT1_IO_PORT_ADDR, 
+  	SELF, D, (vir_bytes) &port_base, LPT1_IO_PORT_SIZE);
+  sys_outb(port_base + 2, INIT_PRINTER);
+  tickdelay(1);			/* easily satisfies Centronics minimum */
+  				/* was 2 millisecs; now is ~17 millisecs */
+  sys_outb(port_base + 2, PR_SELECT);
+  irq_hook_id = 0;
+  sys_irqsetpolicy(PRINTER_IRQ, 0, &irq_hook_id);
+  sys_irqenable(&irq_hook_id);
+
+}
+
+/*==========================================================================*
+ *		    	      prepare_output				    *
+ *==========================================================================*/
+PRIVATE void prepare_output()
+{
+/* Start next chunk of printer output. Fetch the data from user space. */
+
+  register int chunk;
+
+  if ( (chunk = user_left) > sizeof obuf) chunk = sizeof obuf;
+  if (OK!=sys_datacopy(proc_nr, user_vir, SELF, (vir_bytes) obuf, chunk)) {
+  	done_status = EFAULT;
+  	output_done();
+  	return;
+  }
+  optr = obuf;
+  oleft = chunk;
+}
+
+/*===========================================================================*
+ *				do_printer_output				     *
+ *===========================================================================*/
+PRIVATE void do_printer_output()
+{
+/* This function does the actual output to the printer. This is called on
+ * a HARD_INT message sent from the generic interrupt handler that 'forwards'
+ * interrupts to this driver. The generic handler did not reenable the 
+ * printer IRQ yet! 
+ */
+
+  unsigned long status;
+  pvb_pair_t char_out[3];
+
+  if (oleft == 0) {
+	/* Nothing more to print.  Turn off printer interrupts in case they
+	 * are level-sensitive as on the PS/2.  This should be safe even
+	 * when the printer is busy with a previous character, because the
+	 * interrupt status does not affect the printer.
+	 */
+	sys_outb(port_base + 2, PR_SELECT);
+	sys_irqenable(&irq_hook_id);
+	return;
+  }
+
+  do {
+	/* Loop to handle fast (buffered) printers.  It is important that
+	 * processor interrupts are not disabled here, just printer interrupts.
+	 */
+	(void) sys_inb(port_base + 1, &status);
+	if ((status & STATUS_MASK) == BUSY_STATUS) {
+		/* Still busy with last output.  This normally happens
+		 * immediately after doing output to an unbuffered or slow
+		 * printer.  It may happen after a call from prepare_output or
+		 * pr_restart, since they are not synchronized with printer
+		 * interrupts.  It may happen after a spurious interrupt.
+		 */
+		sys_irqenable(&irq_hook_id);
+		return;
+	}
+	if ((status & STATUS_MASK) == NORMAL_STATUS) {
+		/* Everything is all right.  Output another character. */
+		pv_set(char_out[0], port_base, *optr++);	
+		pv_set(char_out[1], port_base+2, ASSERT_STROBE);
+		pv_set(char_out[2], port_base+2, NEGATE_STROBE);
+		sys_voutb(char_out, 3);	/* request series of port outb */
+
+		user_vir++;
+		user_left--;
+	} else {
+		/* Error.  This would be better ignored (treat as busy). */
+		done_status = status;
+		output_done();
+		sys_irqenable(&irq_hook_id);
+		return;
+	}
+  }
+  while (--oleft != 0);
+
+  /* Finished printing chunk OK. */
+  done_status = OK;
+  output_done();
+  sys_irqenable(&irq_hook_id);
+}
+
Index: /trunk/minix/drivers/random/.depend
===================================================================
--- /trunk/minix/drivers/random/.depend	(revision 9)
+++ /trunk/minix/drivers/random/.depend	(revision 9)
@@ -0,0 +1,160 @@
+
+main.o:	../../kernel/config.h
+main.o:	../../kernel/const.h
+main.o:	../../kernel/type.h
+main.o:	../drivers.h
+main.o:	../libdriver/driver.h
+main.o:	/usr/include/ansi.h
+main.o:	/usr/include/assert.h
+main.o:	/usr/include/errno.h
+main.o:	/usr/include/ibm/bios.h
+main.o:	/usr/include/ibm/cpu.h
+main.o:	/usr/include/ibm/interrupt.h
+main.o:	/usr/include/ibm/ports.h
+main.o:	/usr/include/limits.h
+main.o:	/usr/include/minix/bitmap.h
+main.o:	/usr/include/minix/callnr.h
+main.o:	/usr/include/minix/com.h
+main.o:	/usr/include/minix/config.h
+main.o:	/usr/include/minix/const.h
+main.o:	/usr/include/minix/devio.h
+main.o:	/usr/include/minix/dmap.h
+main.o:	/usr/include/minix/ioctl.h
+main.o:	/usr/include/minix/ipc.h
+main.o:	/usr/include/minix/partition.h
+main.o:	/usr/include/minix/sys_config.h
+main.o:	/usr/include/minix/syslib.h
+main.o:	/usr/include/minix/sysutil.h
+main.o:	/usr/include/minix/type.h
+main.o:	/usr/include/minix/u64.h
+main.o:	/usr/include/signal.h
+main.o:	/usr/include/stddef.h
+main.o:	/usr/include/stdlib.h
+main.o:	/usr/include/string.h
+main.o:	/usr/include/sys/dir.h
+main.o:	/usr/include/sys/ioc_memory.h
+main.o:	/usr/include/sys/types.h
+main.o:	/usr/include/unistd.h
+main.o:	main.c
+main.o:	random.h
+
+random.o:	../../kernel/config.h
+random.o:	../../kernel/const.h
+random.o:	../drivers.h
+random.o:	/usr/include/ansi.h
+random.o:	/usr/include/assert.h
+random.o:	/usr/include/errno.h
+random.o:	/usr/include/ibm/bios.h
+random.o:	/usr/include/ibm/cpu.h
+random.o:	/usr/include/ibm/interrupt.h
+random.o:	/usr/include/ibm/ports.h
+random.o:	/usr/include/limits.h
+random.o:	/usr/include/minix/bitmap.h
+random.o:	/usr/include/minix/callnr.h
+random.o:	/usr/include/minix/com.h
+random.o:	/usr/include/minix/config.h
+random.o:	/usr/include/minix/const.h
+random.o:	/usr/include/minix/devio.h
+random.o:	/usr/include/minix/dmap.h
+random.o:	/usr/include/minix/ipc.h
+random.o:	/usr/include/minix/sys_config.h
+random.o:	/usr/include/minix/syslib.h
+random.o:	/usr/include/minix/sysutil.h
+random.o:	/usr/include/minix/type.h
+random.o:	/usr/include/minix/u64.h
+random.o:	/usr/include/signal.h
+random.o:	/usr/include/stddef.h
+random.o:	/usr/include/stdlib.h
+random.o:	/usr/include/string.h
+random.o:	/usr/include/sys/dir.h
+random.o:	/usr/include/sys/types.h
+random.o:	/usr/include/unistd.h
+random.o:	aes/rijndael.h
+random.o:	random.c
+random.o:	random.h
+random.o:	sha2.h
+
+sha2.o:	/usr/include/ansi.h
+sha2.o:	/usr/include/assert.h
+sha2.o:	/usr/include/minix/u64.h
+sha2.o:	/usr/include/string.h
+sha2.o:	/usr/include/sys/types.h
+sha2.o:	sha2.c
+sha2.o:	sha2.h
+
+../libdriver/driver.o:	../libdriver/../drivers.h
+../libdriver/driver.o:	../libdriver/driver.c
+../libdriver/driver.o:	../libdriver/driver.h
+../libdriver/driver.o:	/usr/include/ansi.h
+../libdriver/driver.o:	/usr/include/errno.h
+../libdriver/driver.o:	/usr/include/ibm/bios.h
+../libdriver/driver.o:	/usr/include/ibm/interrupt.h
+../libdriver/driver.o:	/usr/include/ibm/ports.h
+../libdriver/driver.o:	/usr/include/limits.h
+../libdriver/driver.o:	/usr/include/minix/bitmap.h
+../libdriver/driver.o:	/usr/include/minix/callnr.h
+../libdriver/driver.o:	/usr/include/minix/com.h
+../libdriver/driver.o:	/usr/include/minix/config.h
+../libdriver/driver.o:	/usr/include/minix/const.h
+../libdriver/driver.o:	/usr/include/minix/devio.h
+../libdriver/driver.o:	/usr/include/minix/dmap.h
+../libdriver/driver.o:	/usr/include/minix/ioctl.h
+../libdriver/driver.o:	/usr/include/minix/ipc.h
+../libdriver/driver.o:	/usr/include/minix/partition.h
+../libdriver/driver.o:	/usr/include/minix/sys_config.h
+../libdriver/driver.o:	/usr/include/minix/syslib.h
+../libdriver/driver.o:	/usr/include/minix/sysutil.h
+../libdriver/driver.o:	/usr/include/minix/type.h
+../libdriver/driver.o:	/usr/include/minix/u64.h
+../libdriver/driver.o:	/usr/include/signal.h
+../libdriver/driver.o:	/usr/include/stddef.h
+../libdriver/driver.o:	/usr/include/stdlib.h
+../libdriver/driver.o:	/usr/include/string.h
+../libdriver/driver.o:	/usr/include/sys/dir.h
+../libdriver/driver.o:	/usr/include/sys/ioc_disk.h
+../libdriver/driver.o:	/usr/include/sys/types.h
+../libdriver/driver.o:	/usr/include/unistd.h
+
+../libdriver/drvlib.o:	../libdriver/driver.h
+../libdriver/drvlib.o:	../libdriver/drvlib.c
+../libdriver/drvlib.o:	../libdriver/drvlib.h
+../libdriver/drvlib.o:	/usr/include/ansi.h
+../libdriver/drvlib.o:	/usr/include/errno.h
+../libdriver/drvlib.o:	/usr/include/ibm/partition.h
+../libdriver/drvlib.o:	/usr/include/limits.h
+../libdriver/drvlib.o:	/usr/include/minix/callnr.h
+../libdriver/drvlib.o:	/usr/include/minix/com.h
+../libdriver/drvlib.o:	/usr/include/minix/config.h
+../libdriver/drvlib.o:	/usr/include/minix/const.h
+../libdriver/drvlib.o:	/usr/include/minix/devio.h
+../libdriver/drvlib.o:	/usr/include/minix/ipc.h
+../libdriver/drvlib.o:	/usr/include/minix/partition.h
+../libdriver/drvlib.o:	/usr/include/minix/sys_config.h
+../libdriver/drvlib.o:	/usr/include/minix/syslib.h
+../libdriver/drvlib.o:	/usr/include/minix/sysutil.h
+../libdriver/drvlib.o:	/usr/include/minix/type.h
+../libdriver/drvlib.o:	/usr/include/minix/u64.h
+../libdriver/drvlib.o:	/usr/include/stddef.h
+../libdriver/drvlib.o:	/usr/include/string.h
+../libdriver/drvlib.o:	/usr/include/sys/dir.h
+../libdriver/drvlib.o:	/usr/include/sys/types.h
+../libdriver/drvlib.o:	/usr/include/unistd.h
+
+aes/rijndael_alg.o:	/usr/include/ansi.h
+aes/rijndael_alg.o:	/usr/include/stdio.h
+aes/rijndael_alg.o:	/usr/include/stdlib.h
+aes/rijndael_alg.o:	/usr/include/sys/dir.h
+aes/rijndael_alg.o:	/usr/include/sys/types.h
+aes/rijndael_alg.o:	aes/boxes.dat
+aes/rijndael_alg.o:	aes/rijndael-alg.h
+aes/rijndael_alg.o:	aes/rijndael_alg.c
+aes/rijndael_alg.o:	aes/word_i386.h
+
+aes/rijndael_api.o:	/usr/include/ansi.h
+aes/rijndael_api.o:	/usr/include/stdlib.h
+aes/rijndael_api.o:	/usr/include/string.h
+aes/rijndael_api.o:	/usr/include/sys/types.h
+aes/rijndael_api.o:	aes/rijndael-alg.h
+aes/rijndael_api.o:	aes/rijndael-api.h
+aes/rijndael_api.o:	aes/rijndael_api.c
+aes/rijndael_api.o:	aes/word_i386.h
Index: /trunk/minix/drivers/random/Makefile
===================================================================
--- /trunk/minix/drivers/random/Makefile	(revision 9)
+++ /trunk/minix/drivers/random/Makefile	(revision 9)
@@ -0,0 +1,53 @@
+# Makefile for random driver (RANDOM)
+DRIVER = random
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+MAKE = exec make
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsys -lsysutil
+
+OBJ = main.o random.o sha2.o aes/rijndael_api.o aes/rijndael_alg.o
+LIBDRIVER = $d/libdriver/driver.o
+
+
+# build local binary
+all build:	$(DRIVER)
+$(DRIVER):	$(OBJ) $(LIBDRIVER)
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBDRIVER) $(LIBS)
+	install -S 1024w $(DRIVER)
+
+$(LIBDRIVER): 
+	cd $d/libdriver && $(MAKE) 
+
+aes/rijndael_api.o:
+	$(CC) -c -o $@ aes/rijndael_api.c
+
+aes/rijndael_alg.o:
+	$(CC) -c -o $@ aes/rijndael_alg.c
+
+# install with other drivers
+install:	/usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER):	$(DRIVER)
+	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f $(DRIVER) *.o *.bak 
+
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c ../libdriver/*.c aes/*.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/random/aes/boxes.dat
===================================================================
--- /trunk/minix/drivers/random/aes/boxes.dat	(revision 9)
+++ /trunk/minix/drivers/random/aes/boxes.dat	(revision 9)
@@ -0,0 +1,918 @@
+word8 S[256] = {
+ 99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215, 171, 118,
+202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
+183, 253, 147,  38,  54,  63, 247, 204,  52, 165, 229, 241, 113, 216,  49,  21,
+  4, 199,  35, 195,  24, 150,   5, 154,   7,  18, 128, 226, 235,  39, 178, 117,
+  9, 131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 179,  41, 227,  47, 132,
+ 83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 190,  57,  74,  76,  88, 207,
+208, 239, 170, 251,  67,  77,  51, 133,  69, 249,   2, 127,  80,  60, 159, 168,
+ 81, 163,  64, 143, 146, 157,  56, 245, 188, 182, 218,  33,  16, 255, 243, 210,
+205,  12,  19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 100,  93,  25, 115,
+ 96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 184,  20, 222,  94,  11, 219,
+224,  50,  58,  10,  73,   6,  36,  92, 194, 211, 172,  98, 145, 149, 228, 121,
+231, 200,  55, 109, 141, 213,  78, 169, 108,  86, 244, 234, 101, 122, 174,   8,
+186, 120,  37,  46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138,
+112,  62, 181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158,
+225, 248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85,  40, 223,
+140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15, 176,  84, 187,  22
+};
+
+#ifdef INTERMEDIATE_VALUE_KAT
+word8 Si[256] = {
+ 82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129, 243, 215, 251,
+124, 227,  57, 130, 155,  47, 255, 135,  52, 142,  67,  68, 196, 222, 233, 203,
+ 84, 123, 148,  50, 166, 194,  35,  61, 238,  76, 149,  11,  66, 250, 195,  78,
+  8,  46, 161, 102,  40, 217,  36, 178, 118,  91, 162,  73, 109, 139, 209,  37,
+114, 248, 246, 100, 134, 104, 152,  22, 212, 164,  92, 204,  93, 101, 182, 146,
+108, 112,  72,  80, 253, 237, 185, 218,  94,  21,  70,  87, 167, 141, 157, 132,
+144, 216, 171,   0, 140, 188, 211,  10, 247, 228,  88,   5, 184, 179,  69,   6,
+208,  44,  30, 143, 202,  63,  15,   2, 193, 175, 189,   3,   1,  19, 138, 107,
+ 58, 145,  17,  65,  79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
+150, 172, 116,  34, 231, 173,  53, 133, 226, 249,  55, 232,  28, 117, 223, 110,
+ 71, 241,  26, 113,  29,  41, 197, 137, 111, 183,  98,  14, 170,  24, 190,  27,
+252,  86,  62,  75, 198, 210, 121,  32, 154, 219, 192, 254, 120, 205,  90, 244,
+ 31, 221, 168,  51, 136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,
+ 96,  81, 127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147, 201, 156, 239,
+160, 224,  59,  77, 174,  42, 245, 176, 200, 235, 187,  60, 131,  83, 153,  97,
+ 23,  43,   4, 126, 186, 119, 214,  38, 225, 105,  20,  99,  85,  33,  12, 125
+};
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+word8 T1[256][4] = {
+{0xc6,0x63,0x63,0xa5}, {0xf8,0x7c,0x7c,0x84}, {0xee,0x77,0x77,0x99}, {0xf6,0x7b,0x7b,0x8d},
+{0xff,0xf2,0xf2,0x0d}, {0xd6,0x6b,0x6b,0xbd}, {0xde,0x6f,0x6f,0xb1}, {0x91,0xc5,0xc5,0x54},
+{0x60,0x30,0x30,0x50}, {0x02,0x01,0x01,0x03}, {0xce,0x67,0x67,0xa9}, {0x56,0x2b,0x2b,0x7d},
+{0xe7,0xfe,0xfe,0x19}, {0xb5,0xd7,0xd7,0x62}, {0x4d,0xab,0xab,0xe6}, {0xec,0x76,0x76,0x9a},
+{0x8f,0xca,0xca,0x45}, {0x1f,0x82,0x82,0x9d}, {0x89,0xc9,0xc9,0x40}, {0xfa,0x7d,0x7d,0x87},
+{0xef,0xfa,0xfa,0x15}, {0xb2,0x59,0x59,0xeb}, {0x8e,0x47,0x47,0xc9}, {0xfb,0xf0,0xf0,0x0b},
+{0x41,0xad,0xad,0xec}, {0xb3,0xd4,0xd4,0x67}, {0x5f,0xa2,0xa2,0xfd}, {0x45,0xaf,0xaf,0xea},
+{0x23,0x9c,0x9c,0xbf}, {0x53,0xa4,0xa4,0xf7}, {0xe4,0x72,0x72,0x96}, {0x9b,0xc0,0xc0,0x5b},
+{0x75,0xb7,0xb7,0xc2}, {0xe1,0xfd,0xfd,0x1c}, {0x3d,0x93,0x93,0xae}, {0x4c,0x26,0x26,0x6a},
+{0x6c,0x36,0x36,0x5a}, {0x7e,0x3f,0x3f,0x41}, {0xf5,0xf7,0xf7,0x02}, {0x83,0xcc,0xcc,0x4f},
+{0x68,0x34,0x34,0x5c}, {0x51,0xa5,0xa5,0xf4}, {0xd1,0xe5,0xe5,0x34}, {0xf9,0xf1,0xf1,0x08},
+{0xe2,0x71,0x71,0x93}, {0xab,0xd8,0xd8,0x73}, {0x62,0x31,0x31,0x53}, {0x2a,0x15,0x15,0x3f},
+{0x08,0x04,0x04,0x0c}, {0x95,0xc7,0xc7,0x52}, {0x46,0x23,0x23,0x65}, {0x9d,0xc3,0xc3,0x5e},
+{0x30,0x18,0x18,0x28}, {0x37,0x96,0x96,0xa1}, {0x0a,0x05,0x05,0x0f}, {0x2f,0x9a,0x9a,0xb5},
+{0x0e,0x07,0x07,0x09}, {0x24,0x12,0x12,0x36}, {0x1b,0x80,0x80,0x9b}, {0xdf,0xe2,0xe2,0x3d},
+{0xcd,0xeb,0xeb,0x26}, {0x4e,0x27,0x27,0x69}, {0x7f,0xb2,0xb2,0xcd}, {0xea,0x75,0x75,0x9f},
+{0x12,0x09,0x09,0x1b}, {0x1d,0x83,0x83,0x9e}, {0x58,0x2c,0x2c,0x74}, {0x34,0x1a,0x1a,0x2e},
+{0x36,0x1b,0x1b,0x2d}, {0xdc,0x6e,0x6e,0xb2}, {0xb4,0x5a,0x5a,0xee}, {0x5b,0xa0,0xa0,0xfb},
+{0xa4,0x52,0x52,0xf6}, {0x76,0x3b,0x3b,0x4d}, {0xb7,0xd6,0xd6,0x61}, {0x7d,0xb3,0xb3,0xce},
+{0x52,0x29,0x29,0x7b}, {0xdd,0xe3,0xe3,0x3e}, {0x5e,0x2f,0x2f,0x71}, {0x13,0x84,0x84,0x97},
+{0xa6,0x53,0x53,0xf5}, {0xb9,0xd1,0xd1,0x68}, {0x00,0x00,0x00,0x00}, {0xc1,0xed,0xed,0x2c},
+{0x40,0x20,0x20,0x60}, {0xe3,0xfc,0xfc,0x1f}, {0x79,0xb1,0xb1,0xc8}, {0xb6,0x5b,0x5b,0xed},
+{0xd4,0x6a,0x6a,0xbe}, {0x8d,0xcb,0xcb,0x46}, {0x67,0xbe,0xbe,0xd9}, {0x72,0x39,0x39,0x4b},
+{0x94,0x4a,0x4a,0xde}, {0x98,0x4c,0x4c,0xd4}, {0xb0,0x58,0x58,0xe8}, {0x85,0xcf,0xcf,0x4a},
+{0xbb,0xd0,0xd0,0x6b}, {0xc5,0xef,0xef,0x2a}, {0x4f,0xaa,0xaa,0xe5}, {0xed,0xfb,0xfb,0x16},
+{0x86,0x43,0x43,0xc5}, {0x9a,0x4d,0x4d,0xd7}, {0x66,0x33,0x33,0x55}, {0x11,0x85,0x85,0x94},
+{0x8a,0x45,0x45,0xcf}, {0xe9,0xf9,0xf9,0x10}, {0x04,0x02,0x02,0x06}, {0xfe,0x7f,0x7f,0x81},
+{0xa0,0x50,0x50,0xf0}, {0x78,0x3c,0x3c,0x44}, {0x25,0x9f,0x9f,0xba}, {0x4b,0xa8,0xa8,0xe3},
+{0xa2,0x51,0x51,0xf3}, {0x5d,0xa3,0xa3,0xfe}, {0x80,0x40,0x40,0xc0}, {0x05,0x8f,0x8f,0x8a},
+{0x3f,0x92,0x92,0xad}, {0x21,0x9d,0x9d,0xbc}, {0x70,0x38,0x38,0x48}, {0xf1,0xf5,0xf5,0x04},
+{0x63,0xbc,0xbc,0xdf}, {0x77,0xb6,0xb6,0xc1}, {0xaf,0xda,0xda,0x75}, {0x42,0x21,0x21,0x63},
+{0x20,0x10,0x10,0x30}, {0xe5,0xff,0xff,0x1a}, {0xfd,0xf3,0xf3,0x0e}, {0xbf,0xd2,0xd2,0x6d},
+{0x81,0xcd,0xcd,0x4c}, {0x18,0x0c,0x0c,0x14}, {0x26,0x13,0x13,0x35}, {0xc3,0xec,0xec,0x2f},
+{0xbe,0x5f,0x5f,0xe1}, {0x35,0x97,0x97,0xa2}, {0x88,0x44,0x44,0xcc}, {0x2e,0x17,0x17,0x39},
+{0x93,0xc4,0xc4,0x57}, {0x55,0xa7,0xa7,0xf2}, {0xfc,0x7e,0x7e,0x82}, {0x7a,0x3d,0x3d,0x47},
+{0xc8,0x64,0x64,0xac}, {0xba,0x5d,0x5d,0xe7}, {0x32,0x19,0x19,0x2b}, {0xe6,0x73,0x73,0x95},
+{0xc0,0x60,0x60,0xa0}, {0x19,0x81,0x81,0x98}, {0x9e,0x4f,0x4f,0xd1}, {0xa3,0xdc,0xdc,0x7f},
+{0x44,0x22,0x22,0x66}, {0x54,0x2a,0x2a,0x7e}, {0x3b,0x90,0x90,0xab}, {0x0b,0x88,0x88,0x83},
+{0x8c,0x46,0x46,0xca}, {0xc7,0xee,0xee,0x29}, {0x6b,0xb8,0xb8,0xd3}, {0x28,0x14,0x14,0x3c},
+{0xa7,0xde,0xde,0x79}, {0xbc,0x5e,0x5e,0xe2}, {0x16,0x0b,0x0b,0x1d}, {0xad,0xdb,0xdb,0x76},
+{0xdb,0xe0,0xe0,0x3b}, {0x64,0x32,0x32,0x56}, {0x74,0x3a,0x3a,0x4e}, {0x14,0x0a,0x0a,0x1e},
+{0x92,0x49,0x49,0xdb}, {0x0c,0x06,0x06,0x0a}, {0x48,0x24,0x24,0x6c}, {0xb8,0x5c,0x5c,0xe4},
+{0x9f,0xc2,0xc2,0x5d}, {0xbd,0xd3,0xd3,0x6e}, {0x43,0xac,0xac,0xef}, {0xc4,0x62,0x62,0xa6},
+{0x39,0x91,0x91,0xa8}, {0x31,0x95,0x95,0xa4}, {0xd3,0xe4,0xe4,0x37}, {0xf2,0x79,0x79,0x8b},
+{0xd5,0xe7,0xe7,0x32}, {0x8b,0xc8,0xc8,0x43}, {0x6e,0x37,0x37,0x59}, {0xda,0x6d,0x6d,0xb7},
+{0x01,0x8d,0x8d,0x8c}, {0xb1,0xd5,0xd5,0x64}, {0x9c,0x4e,0x4e,0xd2}, {0x49,0xa9,0xa9,0xe0},
+{0xd8,0x6c,0x6c,0xb4}, {0xac,0x56,0x56,0xfa}, {0xf3,0xf4,0xf4,0x07}, {0xcf,0xea,0xea,0x25},
+{0xca,0x65,0x65,0xaf}, {0xf4,0x7a,0x7a,0x8e}, {0x47,0xae,0xae,0xe9}, {0x10,0x08,0x08,0x18},
+{0x6f,0xba,0xba,0xd5}, {0xf0,0x78,0x78,0x88}, {0x4a,0x25,0x25,0x6f}, {0x5c,0x2e,0x2e,0x72},
+{0x38,0x1c,0x1c,0x24}, {0x57,0xa6,0xa6,0xf1}, {0x73,0xb4,0xb4,0xc7}, {0x97,0xc6,0xc6,0x51},
+{0xcb,0xe8,0xe8,0x23}, {0xa1,0xdd,0xdd,0x7c}, {0xe8,0x74,0x74,0x9c}, {0x3e,0x1f,0x1f,0x21},
+{0x96,0x4b,0x4b,0xdd}, {0x61,0xbd,0xbd,0xdc}, {0x0d,0x8b,0x8b,0x86}, {0x0f,0x8a,0x8a,0x85},
+{0xe0,0x70,0x70,0x90}, {0x7c,0x3e,0x3e,0x42}, {0x71,0xb5,0xb5,0xc4}, {0xcc,0x66,0x66,0xaa},
+{0x90,0x48,0x48,0xd8}, {0x06,0x03,0x03,0x05}, {0xf7,0xf6,0xf6,0x01}, {0x1c,0x0e,0x0e,0x12},
+{0xc2,0x61,0x61,0xa3}, {0x6a,0x35,0x35,0x5f}, {0xae,0x57,0x57,0xf9}, {0x69,0xb9,0xb9,0xd0},
+{0x17,0x86,0x86,0x91}, {0x99,0xc1,0xc1,0x58}, {0x3a,0x1d,0x1d,0x27}, {0x27,0x9e,0x9e,0xb9},
+{0xd9,0xe1,0xe1,0x38}, {0xeb,0xf8,0xf8,0x13}, {0x2b,0x98,0x98,0xb3}, {0x22,0x11,0x11,0x33},
+{0xd2,0x69,0x69,0xbb}, {0xa9,0xd9,0xd9,0x70}, {0x07,0x8e,0x8e,0x89}, {0x33,0x94,0x94,0xa7},
+{0x2d,0x9b,0x9b,0xb6}, {0x3c,0x1e,0x1e,0x22}, {0x15,0x87,0x87,0x92}, {0xc9,0xe9,0xe9,0x20},
+{0x87,0xce,0xce,0x49}, {0xaa,0x55,0x55,0xff}, {0x50,0x28,0x28,0x78}, {0xa5,0xdf,0xdf,0x7a},
+{0x03,0x8c,0x8c,0x8f}, {0x59,0xa1,0xa1,0xf8}, {0x09,0x89,0x89,0x80}, {0x1a,0x0d,0x0d,0x17},
+{0x65,0xbf,0xbf,0xda}, {0xd7,0xe6,0xe6,0x31}, {0x84,0x42,0x42,0xc6}, {0xd0,0x68,0x68,0xb8},
+{0x82,0x41,0x41,0xc3}, {0x29,0x99,0x99,0xb0}, {0x5a,0x2d,0x2d,0x77}, {0x1e,0x0f,0x0f,0x11},
+{0x7b,0xb0,0xb0,0xcb}, {0xa8,0x54,0x54,0xfc}, {0x6d,0xbb,0xbb,0xd6}, {0x2c,0x16,0x16,0x3a},
+};
+
+word8 T2[256][4] = {
+{0xa5,0xc6,0x63,0x63}, {0x84,0xf8,0x7c,0x7c}, {0x99,0xee,0x77,0x77}, {0x8d,0xf6,0x7b,0x7b},
+{0x0d,0xff,0xf2,0xf2}, {0xbd,0xd6,0x6b,0x6b}, {0xb1,0xde,0x6f,0x6f}, {0x54,0x91,0xc5,0xc5},
+{0x50,0x60,0x30,0x30}, {0x03,0x02,0x01,0x01}, {0xa9,0xce,0x67,0x67}, {0x7d,0x56,0x2b,0x2b},
+{0x19,0xe7,0xfe,0xfe}, {0x62,0xb5,0xd7,0xd7}, {0xe6,0x4d,0xab,0xab}, {0x9a,0xec,0x76,0x76},
+{0x45,0x8f,0xca,0xca}, {0x9d,0x1f,0x82,0x82}, {0x40,0x89,0xc9,0xc9}, {0x87,0xfa,0x7d,0x7d},
+{0x15,0xef,0xfa,0xfa}, {0xeb,0xb2,0x59,0x59}, {0xc9,0x8e,0x47,0x47}, {0x0b,0xfb,0xf0,0xf0},
+{0xec,0x41,0xad,0xad}, {0x67,0xb3,0xd4,0xd4}, {0xfd,0x5f,0xa2,0xa2}, {0xea,0x45,0xaf,0xaf},
+{0xbf,0x23,0x9c,0x9c}, {0xf7,0x53,0xa4,0xa4}, {0x96,0xe4,0x72,0x72}, {0x5b,0x9b,0xc0,0xc0},
+{0xc2,0x75,0xb7,0xb7}, {0x1c,0xe1,0xfd,0xfd}, {0xae,0x3d,0x93,0x93}, {0x6a,0x4c,0x26,0x26},
+{0x5a,0x6c,0x36,0x36}, {0x41,0x7e,0x3f,0x3f}, {0x02,0xf5,0xf7,0xf7}, {0x4f,0x83,0xcc,0xcc},
+{0x5c,0x68,0x34,0x34}, {0xf4,0x51,0xa5,0xa5}, {0x34,0xd1,0xe5,0xe5}, {0x08,0xf9,0xf1,0xf1},
+{0x93,0xe2,0x71,0x71}, {0x73,0xab,0xd8,0xd8}, {0x53,0x62,0x31,0x31}, {0x3f,0x2a,0x15,0x15},
+{0x0c,0x08,0x04,0x04}, {0x52,0x95,0xc7,0xc7}, {0x65,0x46,0x23,0x23}, {0x5e,0x9d,0xc3,0xc3},
+{0x28,0x30,0x18,0x18}, {0xa1,0x37,0x96,0x96}, {0x0f,0x0a,0x05,0x05}, {0xb5,0x2f,0x9a,0x9a},
+{0x09,0x0e,0x07,0x07}, {0x36,0x24,0x12,0x12}, {0x9b,0x1b,0x80,0x80}, {0x3d,0xdf,0xe2,0xe2},
+{0x26,0xcd,0xeb,0xeb}, {0x69,0x4e,0x27,0x27}, {0xcd,0x7f,0xb2,0xb2}, {0x9f,0xea,0x75,0x75},
+{0x1b,0x12,0x09,0x09}, {0x9e,0x1d,0x83,0x83}, {0x74,0x58,0x2c,0x2c}, {0x2e,0x34,0x1a,0x1a},
+{0x2d,0x36,0x1b,0x1b}, {0xb2,0xdc,0x6e,0x6e}, {0xee,0xb4,0x5a,0x5a}, {0xfb,0x5b,0xa0,0xa0},
+{0xf6,0xa4,0x52,0x52}, {0x4d,0x76,0x3b,0x3b}, {0x61,0xb7,0xd6,0xd6}, {0xce,0x7d,0xb3,0xb3},
+{0x7b,0x52,0x29,0x29}, {0x3e,0xdd,0xe3,0xe3}, {0x71,0x5e,0x2f,0x2f}, {0x97,0x13,0x84,0x84},
+{0xf5,0xa6,0x53,0x53}, {0x68,0xb9,0xd1,0xd1}, {0x00,0x00,0x00,0x00}, {0x2c,0xc1,0xed,0xed},
+{0x60,0x40,0x20,0x20}, {0x1f,0xe3,0xfc,0xfc}, {0xc8,0x79,0xb1,0xb1}, {0xed,0xb6,0x5b,0x5b},
+{0xbe,0xd4,0x6a,0x6a}, {0x46,0x8d,0xcb,0xcb}, {0xd9,0x67,0xbe,0xbe}, {0x4b,0x72,0x39,0x39},
+{0xde,0x94,0x4a,0x4a}, {0xd4,0x98,0x4c,0x4c}, {0xe8,0xb0,0x58,0x58}, {0x4a,0x85,0xcf,0xcf},
+{0x6b,0xbb,0xd0,0xd0}, {0x2a,0xc5,0xef,0xef}, {0xe5,0x4f,0xaa,0xaa}, {0x16,0xed,0xfb,0xfb},
+{0xc5,0x86,0x43,0x43}, {0xd7,0x9a,0x4d,0x4d}, {0x55,0x66,0x33,0x33}, {0x94,0x11,0x85,0x85},
+{0xcf,0x8a,0x45,0x45}, {0x10,0xe9,0xf9,0xf9}, {0x06,0x04,0x02,0x02}, {0x81,0xfe,0x7f,0x7f},
+{0xf0,0xa0,0x50,0x50}, {0x44,0x78,0x3c,0x3c}, {0xba,0x25,0x9f,0x9f}, {0xe3,0x4b,0xa8,0xa8},
+{0xf3,0xa2,0x51,0x51}, {0xfe,0x5d,0xa3,0xa3}, {0xc0,0x80,0x40,0x40}, {0x8a,0x05,0x8f,0x8f},
+{0xad,0x3f,0x92,0x92}, {0xbc,0x21,0x9d,0x9d}, {0x48,0x70,0x38,0x38}, {0x04,0xf1,0xf5,0xf5},
+{0xdf,0x63,0xbc,0xbc}, {0xc1,0x77,0xb6,0xb6}, {0x75,0xaf,0xda,0xda}, {0x63,0x42,0x21,0x21},
+{0x30,0x20,0x10,0x10}, {0x1a,0xe5,0xff,0xff}, {0x0e,0xfd,0xf3,0xf3}, {0x6d,0xbf,0xd2,0xd2},
+{0x4c,0x81,0xcd,0xcd}, {0x14,0x18,0x0c,0x0c}, {0x35,0x26,0x13,0x13}, {0x2f,0xc3,0xec,0xec},
+{0xe1,0xbe,0x5f,0x5f}, {0xa2,0x35,0x97,0x97}, {0xcc,0x88,0x44,0x44}, {0x39,0x2e,0x17,0x17},
+{0x57,0x93,0xc4,0xc4}, {0xf2,0x55,0xa7,0xa7}, {0x82,0xfc,0x7e,0x7e}, {0x47,0x7a,0x3d,0x3d},
+{0xac,0xc8,0x64,0x64}, {0xe7,0xba,0x5d,0x5d}, {0x2b,0x32,0x19,0x19}, {0x95,0xe6,0x73,0x73},
+{0xa0,0xc0,0x60,0x60}, {0x98,0x19,0x81,0x81}, {0xd1,0x9e,0x4f,0x4f}, {0x7f,0xa3,0xdc,0xdc},
+{0x66,0x44,0x22,0x22}, {0x7e,0x54,0x2a,0x2a}, {0xab,0x3b,0x90,0x90}, {0x83,0x0b,0x88,0x88},
+{0xca,0x8c,0x46,0x46}, {0x29,0xc7,0xee,0xee}, {0xd3,0x6b,0xb8,0xb8}, {0x3c,0x28,0x14,0x14},
+{0x79,0xa7,0xde,0xde}, {0xe2,0xbc,0x5e,0x5e}, {0x1d,0x16,0x0b,0x0b}, {0x76,0xad,0xdb,0xdb},
+{0x3b,0xdb,0xe0,0xe0}, {0x56,0x64,0x32,0x32}, {0x4e,0x74,0x3a,0x3a}, {0x1e,0x14,0x0a,0x0a},
+{0xdb,0x92,0x49,0x49}, {0x0a,0x0c,0x06,0x06}, {0x6c,0x48,0x24,0x24}, {0xe4,0xb8,0x5c,0x5c},
+{0x5d,0x9f,0xc2,0xc2}, {0x6e,0xbd,0xd3,0xd3}, {0xef,0x43,0xac,0xac}, {0xa6,0xc4,0x62,0x62},
+{0xa8,0x39,0x91,0x91}, {0xa4,0x31,0x95,0x95}, {0x37,0xd3,0xe4,0xe4}, {0x8b,0xf2,0x79,0x79},
+{0x32,0xd5,0xe7,0xe7}, {0x43,0x8b,0xc8,0xc8}, {0x59,0x6e,0x37,0x37}, {0xb7,0xda,0x6d,0x6d},
+{0x8c,0x01,0x8d,0x8d}, {0x64,0xb1,0xd5,0xd5}, {0xd2,0x9c,0x4e,0x4e}, {0xe0,0x49,0xa9,0xa9},
+{0xb4,0xd8,0x6c,0x6c}, {0xfa,0xac,0x56,0x56}, {0x07,0xf3,0xf4,0xf4}, {0x25,0xcf,0xea,0xea},
+{0xaf,0xca,0x65,0x65}, {0x8e,0xf4,0x7a,0x7a}, {0xe9,0x47,0xae,0xae}, {0x18,0x10,0x08,0x08},
+{0xd5,0x6f,0xba,0xba}, {0x88,0xf0,0x78,0x78}, {0x6f,0x4a,0x25,0x25}, {0x72,0x5c,0x2e,0x2e},
+{0x24,0x38,0x1c,0x1c}, {0xf1,0x57,0xa6,0xa6}, {0xc7,0x73,0xb4,0xb4}, {0x51,0x97,0xc6,0xc6},
+{0x23,0xcb,0xe8,0xe8}, {0x7c,0xa1,0xdd,0xdd}, {0x9c,0xe8,0x74,0x74}, {0x21,0x3e,0x1f,0x1f},
+{0xdd,0x96,0x4b,0x4b}, {0xdc,0x61,0xbd,0xbd}, {0x86,0x0d,0x8b,0x8b}, {0x85,0x0f,0x8a,0x8a},
+{0x90,0xe0,0x70,0x70}, {0x42,0x7c,0x3e,0x3e}, {0xc4,0x71,0xb5,0xb5}, {0xaa,0xcc,0x66,0x66},
+{0xd8,0x90,0x48,0x48}, {0x05,0x06,0x03,0x03}, {0x01,0xf7,0xf6,0xf6}, {0x12,0x1c,0x0e,0x0e},
+{0xa3,0xc2,0x61,0x61}, {0x5f,0x6a,0x35,0x35}, {0xf9,0xae,0x57,0x57}, {0xd0,0x69,0xb9,0xb9},
+{0x91,0x17,0x86,0x86}, {0x58,0x99,0xc1,0xc1}, {0x27,0x3a,0x1d,0x1d}, {0xb9,0x27,0x9e,0x9e},
+{0x38,0xd9,0xe1,0xe1}, {0x13,0xeb,0xf8,0xf8}, {0xb3,0x2b,0x98,0x98}, {0x33,0x22,0x11,0x11},
+{0xbb,0xd2,0x69,0x69}, {0x70,0xa9,0xd9,0xd9}, {0x89,0x07,0x8e,0x8e}, {0xa7,0x33,0x94,0x94},
+{0xb6,0x2d,0x9b,0x9b}, {0x22,0x3c,0x1e,0x1e}, {0x92,0x15,0x87,0x87}, {0x20,0xc9,0xe9,0xe9},
+{0x49,0x87,0xce,0xce}, {0xff,0xaa,0x55,0x55}, {0x78,0x50,0x28,0x28}, {0x7a,0xa5,0xdf,0xdf},
+{0x8f,0x03,0x8c,0x8c}, {0xf8,0x59,0xa1,0xa1}, {0x80,0x09,0x89,0x89}, {0x17,0x1a,0x0d,0x0d},
+{0xda,0x65,0xbf,0xbf}, {0x31,0xd7,0xe6,0xe6}, {0xc6,0x84,0x42,0x42}, {0xb8,0xd0,0x68,0x68},
+{0xc3,0x82,0x41,0x41}, {0xb0,0x29,0x99,0x99}, {0x77,0x5a,0x2d,0x2d}, {0x11,0x1e,0x0f,0x0f},
+{0xcb,0x7b,0xb0,0xb0}, {0xfc,0xa8,0x54,0x54}, {0xd6,0x6d,0xbb,0xbb}, {0x3a,0x2c,0x16,0x16},
+};
+
+word8 T3[256][4] = {
+{0x63,0xa5,0xc6,0x63}, {0x7c,0x84,0xf8,0x7c}, {0x77,0x99,0xee,0x77}, {0x7b,0x8d,0xf6,0x7b},
+{0xf2,0x0d,0xff,0xf2}, {0x6b,0xbd,0xd6,0x6b}, {0x6f,0xb1,0xde,0x6f}, {0xc5,0x54,0x91,0xc5},
+{0x30,0x50,0x60,0x30}, {0x01,0x03,0x02,0x01}, {0x67,0xa9,0xce,0x67}, {0x2b,0x7d,0x56,0x2b},
+{0xfe,0x19,0xe7,0xfe}, {0xd7,0x62,0xb5,0xd7}, {0xab,0xe6,0x4d,0xab}, {0x76,0x9a,0xec,0x76},
+{0xca,0x45,0x8f,0xca}, {0x82,0x9d,0x1f,0x82}, {0xc9,0x40,0x89,0xc9}, {0x7d,0x87,0xfa,0x7d},
+{0xfa,0x15,0xef,0xfa}, {0x59,0xeb,0xb2,0x59}, {0x47,0xc9,0x8e,0x47}, {0xf0,0x0b,0xfb,0xf0},
+{0xad,0xec,0x41,0xad}, {0xd4,0x67,0xb3,0xd4}, {0xa2,0xfd,0x5f,0xa2}, {0xaf,0xea,0x45,0xaf},
+{0x9c,0xbf,0x23,0x9c}, {0xa4,0xf7,0x53,0xa4}, {0x72,0x96,0xe4,0x72}, {0xc0,0x5b,0x9b,0xc0},
+{0xb7,0xc2,0x75,0xb7}, {0xfd,0x1c,0xe1,0xfd}, {0x93,0xae,0x3d,0x93}, {0x26,0x6a,0x4c,0x26},
+{0x36,0x5a,0x6c,0x36}, {0x3f,0x41,0x7e,0x3f}, {0xf7,0x02,0xf5,0xf7}, {0xcc,0x4f,0x83,0xcc},
+{0x34,0x5c,0x68,0x34}, {0xa5,0xf4,0x51,0xa5}, {0xe5,0x34,0xd1,0xe5}, {0xf1,0x08,0xf9,0xf1},
+{0x71,0x93,0xe2,0x71}, {0xd8,0x73,0xab,0xd8}, {0x31,0x53,0x62,0x31}, {0x15,0x3f,0x2a,0x15},
+{0x04,0x0c,0x08,0x04}, {0xc7,0x52,0x95,0xc7}, {0x23,0x65,0x46,0x23}, {0xc3,0x5e,0x9d,0xc3},
+{0x18,0x28,0x30,0x18}, {0x96,0xa1,0x37,0x96}, {0x05,0x0f,0x0a,0x05}, {0x9a,0xb5,0x2f,0x9a},
+{0x07,0x09,0x0e,0x07}, {0x12,0x36,0x24,0x12}, {0x80,0x9b,0x1b,0x80}, {0xe2,0x3d,0xdf,0xe2},
+{0xeb,0x26,0xcd,0xeb}, {0x27,0x69,0x4e,0x27}, {0xb2,0xcd,0x7f,0xb2}, {0x75,0x9f,0xea,0x75},
+{0x09,0x1b,0x12,0x09}, {0x83,0x9e,0x1d,0x83}, {0x2c,0x74,0x58,0x2c}, {0x1a,0x2e,0x34,0x1a},
+{0x1b,0x2d,0x36,0x1b}, {0x6e,0xb2,0xdc,0x6e}, {0x5a,0xee,0xb4,0x5a}, {0xa0,0xfb,0x5b,0xa0},
+{0x52,0xf6,0xa4,0x52}, {0x3b,0x4d,0x76,0x3b}, {0xd6,0x61,0xb7,0xd6}, {0xb3,0xce,0x7d,0xb3},
+{0x29,0x7b,0x52,0x29}, {0xe3,0x3e,0xdd,0xe3}, {0x2f,0x71,0x5e,0x2f}, {0x84,0x97,0x13,0x84},
+{0x53,0xf5,0xa6,0x53}, {0xd1,0x68,0xb9,0xd1}, {0x00,0x00,0x00,0x00}, {0xed,0x2c,0xc1,0xed},
+{0x20,0x60,0x40,0x20}, {0xfc,0x1f,0xe3,0xfc}, {0xb1,0xc8,0x79,0xb1}, {0x5b,0xed,0xb6,0x5b},
+{0x6a,0xbe,0xd4,0x6a}, {0xcb,0x46,0x8d,0xcb}, {0xbe,0xd9,0x67,0xbe}, {0x39,0x4b,0x72,0x39},
+{0x4a,0xde,0x94,0x4a}, {0x4c,0xd4,0x98,0x4c}, {0x58,0xe8,0xb0,0x58}, {0xcf,0x4a,0x85,0xcf},
+{0xd0,0x6b,0xbb,0xd0}, {0xef,0x2a,0xc5,0xef}, {0xaa,0xe5,0x4f,0xaa}, {0xfb,0x16,0xed,0xfb},
+{0x43,0xc5,0x86,0x43}, {0x4d,0xd7,0x9a,0x4d}, {0x33,0x55,0x66,0x33}, {0x85,0x94,0x11,0x85},
+{0x45,0xcf,0x8a,0x45}, {0xf9,0x10,0xe9,0xf9}, {0x02,0x06,0x04,0x02}, {0x7f,0x81,0xfe,0x7f},
+{0x50,0xf0,0xa0,0x50}, {0x3c,0x44,0x78,0x3c}, {0x9f,0xba,0x25,0x9f}, {0xa8,0xe3,0x4b,0xa8},
+{0x51,0xf3,0xa2,0x51}, {0xa3,0xfe,0x5d,0xa3}, {0x40,0xc0,0x80,0x40}, {0x8f,0x8a,0x05,0x8f},
+{0x92,0xad,0x3f,0x92}, {0x9d,0xbc,0x21,0x9d}, {0x38,0x48,0x70,0x38}, {0xf5,0x04,0xf1,0xf5},
+{0xbc,0xdf,0x63,0xbc}, {0xb6,0xc1,0x77,0xb6}, {0xda,0x75,0xaf,0xda}, {0x21,0x63,0x42,0x21},
+{0x10,0x30,0x20,0x10}, {0xff,0x1a,0xe5,0xff}, {0xf3,0x0e,0xfd,0xf3}, {0xd2,0x6d,0xbf,0xd2},
+{0xcd,0x4c,0x81,0xcd}, {0x0c,0x14,0x18,0x0c}, {0x13,0x35,0x26,0x13}, {0xec,0x2f,0xc3,0xec},
+{0x5f,0xe1,0xbe,0x5f}, {0x97,0xa2,0x35,0x97}, {0x44,0xcc,0x88,0x44}, {0x17,0x39,0x2e,0x17},
+{0xc4,0x57,0x93,0xc4}, {0xa7,0xf2,0x55,0xa7}, {0x7e,0x82,0xfc,0x7e}, {0x3d,0x47,0x7a,0x3d},
+{0x64,0xac,0xc8,0x64}, {0x5d,0xe7,0xba,0x5d}, {0x19,0x2b,0x32,0x19}, {0x73,0x95,0xe6,0x73},
+{0x60,0xa0,0xc0,0x60}, {0x81,0x98,0x19,0x81}, {0x4f,0xd1,0x9e,0x4f}, {0xdc,0x7f,0xa3,0xdc},
+{0x22,0x66,0x44,0x22}, {0x2a,0x7e,0x54,0x2a}, {0x90,0xab,0x3b,0x90}, {0x88,0x83,0x0b,0x88},
+{0x46,0xca,0x8c,0x46}, {0xee,0x29,0xc7,0xee}, {0xb8,0xd3,0x6b,0xb8}, {0x14,0x3c,0x28,0x14},
+{0xde,0x79,0xa7,0xde}, {0x5e,0xe2,0xbc,0x5e}, {0x0b,0x1d,0x16,0x0b}, {0xdb,0x76,0xad,0xdb},
+{0xe0,0x3b,0xdb,0xe0}, {0x32,0x56,0x64,0x32}, {0x3a,0x4e,0x74,0x3a}, {0x0a,0x1e,0x14,0x0a},
+{0x49,0xdb,0x92,0x49}, {0x06,0x0a,0x0c,0x06}, {0x24,0x6c,0x48,0x24}, {0x5c,0xe4,0xb8,0x5c},
+{0xc2,0x5d,0x9f,0xc2}, {0xd3,0x6e,0xbd,0xd3}, {0xac,0xef,0x43,0xac}, {0x62,0xa6,0xc4,0x62},
+{0x91,0xa8,0x39,0x91}, {0x95,0xa4,0x31,0x95}, {0xe4,0x37,0xd3,0xe4}, {0x79,0x8b,0xf2,0x79},
+{0xe7,0x32,0xd5,0xe7}, {0xc8,0x43,0x8b,0xc8}, {0x37,0x59,0x6e,0x37}, {0x6d,0xb7,0xda,0x6d},
+{0x8d,0x8c,0x01,0x8d}, {0xd5,0x64,0xb1,0xd5}, {0x4e,0xd2,0x9c,0x4e}, {0xa9,0xe0,0x49,0xa9},
+{0x6c,0xb4,0xd8,0x6c}, {0x56,0xfa,0xac,0x56}, {0xf4,0x07,0xf3,0xf4}, {0xea,0x25,0xcf,0xea},
+{0x65,0xaf,0xca,0x65}, {0x7a,0x8e,0xf4,0x7a}, {0xae,0xe9,0x47,0xae}, {0x08,0x18,0x10,0x08},
+{0xba,0xd5,0x6f,0xba}, {0x78,0x88,0xf0,0x78}, {0x25,0x6f,0x4a,0x25}, {0x2e,0x72,0x5c,0x2e},
+{0x1c,0x24,0x38,0x1c}, {0xa6,0xf1,0x57,0xa6}, {0xb4,0xc7,0x73,0xb4}, {0xc6,0x51,0x97,0xc6},
+{0xe8,0x23,0xcb,0xe8}, {0xdd,0x7c,0xa1,0xdd}, {0x74,0x9c,0xe8,0x74}, {0x1f,0x21,0x3e,0x1f},
+{0x4b,0xdd,0x96,0x4b}, {0xbd,0xdc,0x61,0xbd}, {0x8b,0x86,0x0d,0x8b}, {0x8a,0x85,0x0f,0x8a},
+{0x70,0x90,0xe0,0x70}, {0x3e,0x42,0x7c,0x3e}, {0xb5,0xc4,0x71,0xb5}, {0x66,0xaa,0xcc,0x66},
+{0x48,0xd8,0x90,0x48}, {0x03,0x05,0x06,0x03}, {0xf6,0x01,0xf7,0xf6}, {0x0e,0x12,0x1c,0x0e},
+{0x61,0xa3,0xc2,0x61}, {0x35,0x5f,0x6a,0x35}, {0x57,0xf9,0xae,0x57}, {0xb9,0xd0,0x69,0xb9},
+{0x86,0x91,0x17,0x86}, {0xc1,0x58,0x99,0xc1}, {0x1d,0x27,0x3a,0x1d}, {0x9e,0xb9,0x27,0x9e},
+{0xe1,0x38,0xd9,0xe1}, {0xf8,0x13,0xeb,0xf8}, {0x98,0xb3,0x2b,0x98}, {0x11,0x33,0x22,0x11},
+{0x69,0xbb,0xd2,0x69}, {0xd9,0x70,0xa9,0xd9}, {0x8e,0x89,0x07,0x8e}, {0x94,0xa7,0x33,0x94},
+{0x9b,0xb6,0x2d,0x9b}, {0x1e,0x22,0x3c,0x1e}, {0x87,0x92,0x15,0x87}, {0xe9,0x20,0xc9,0xe9},
+{0xce,0x49,0x87,0xce}, {0x55,0xff,0xaa,0x55}, {0x28,0x78,0x50,0x28}, {0xdf,0x7a,0xa5,0xdf},
+{0x8c,0x8f,0x03,0x8c}, {0xa1,0xf8,0x59,0xa1}, {0x89,0x80,0x09,0x89}, {0x0d,0x17,0x1a,0x0d},
+{0xbf,0xda,0x65,0xbf}, {0xe6,0x31,0xd7,0xe6}, {0x42,0xc6,0x84,0x42}, {0x68,0xb8,0xd0,0x68},
+{0x41,0xc3,0x82,0x41}, {0x99,0xb0,0x29,0x99}, {0x2d,0x77,0x5a,0x2d}, {0x0f,0x11,0x1e,0x0f},
+{0xb0,0xcb,0x7b,0xb0}, {0x54,0xfc,0xa8,0x54}, {0xbb,0xd6,0x6d,0xbb}, {0x16,0x3a,0x2c,0x16},
+};
+
+word8 T4[256][4] = {
+{0x63,0x63,0xa5,0xc6}, {0x7c,0x7c,0x84,0xf8}, {0x77,0x77,0x99,0xee}, {0x7b,0x7b,0x8d,0xf6},
+{0xf2,0xf2,0x0d,0xff}, {0x6b,0x6b,0xbd,0xd6}, {0x6f,0x6f,0xb1,0xde}, {0xc5,0xc5,0x54,0x91},
+{0x30,0x30,0x50,0x60}, {0x01,0x01,0x03,0x02}, {0x67,0x67,0xa9,0xce}, {0x2b,0x2b,0x7d,0x56},
+{0xfe,0xfe,0x19,0xe7}, {0xd7,0xd7,0x62,0xb5}, {0xab,0xab,0xe6,0x4d}, {0x76,0x76,0x9a,0xec},
+{0xca,0xca,0x45,0x8f}, {0x82,0x82,0x9d,0x1f}, {0xc9,0xc9,0x40,0x89}, {0x7d,0x7d,0x87,0xfa},
+{0xfa,0xfa,0x15,0xef}, {0x59,0x59,0xeb,0xb2}, {0x47,0x47,0xc9,0x8e}, {0xf0,0xf0,0x0b,0xfb},
+{0xad,0xad,0xec,0x41}, {0xd4,0xd4,0x67,0xb3}, {0xa2,0xa2,0xfd,0x5f}, {0xaf,0xaf,0xea,0x45},
+{0x9c,0x9c,0xbf,0x23}, {0xa4,0xa4,0xf7,0x53}, {0x72,0x72,0x96,0xe4}, {0xc0,0xc0,0x5b,0x9b},
+{0xb7,0xb7,0xc2,0x75}, {0xfd,0xfd,0x1c,0xe1}, {0x93,0x93,0xae,0x3d}, {0x26,0x26,0x6a,0x4c},
+{0x36,0x36,0x5a,0x6c}, {0x3f,0x3f,0x41,0x7e}, {0xf7,0xf7,0x02,0xf5}, {0xcc,0xcc,0x4f,0x83},
+{0x34,0x34,0x5c,0x68}, {0xa5,0xa5,0xf4,0x51}, {0xe5,0xe5,0x34,0xd1}, {0xf1,0xf1,0x08,0xf9},
+{0x71,0x71,0x93,0xe2}, {0xd8,0xd8,0x73,0xab}, {0x31,0x31,0x53,0x62}, {0x15,0x15,0x3f,0x2a},
+{0x04,0x04,0x0c,0x08}, {0xc7,0xc7,0x52,0x95}, {0x23,0x23,0x65,0x46}, {0xc3,0xc3,0x5e,0x9d},
+{0x18,0x18,0x28,0x30}, {0x96,0x96,0xa1,0x37}, {0x05,0x05,0x0f,0x0a}, {0x9a,0x9a,0xb5,0x2f},
+{0x07,0x07,0x09,0x0e}, {0x12,0x12,0x36,0x24}, {0x80,0x80,0x9b,0x1b}, {0xe2,0xe2,0x3d,0xdf},
+{0xeb,0xeb,0x26,0xcd}, {0x27,0x27,0x69,0x4e}, {0xb2,0xb2,0xcd,0x7f}, {0x75,0x75,0x9f,0xea},
+{0x09,0x09,0x1b,0x12}, {0x83,0x83,0x9e,0x1d}, {0x2c,0x2c,0x74,0x58}, {0x1a,0x1a,0x2e,0x34},
+{0x1b,0x1b,0x2d,0x36}, {0x6e,0x6e,0xb2,0xdc}, {0x5a,0x5a,0xee,0xb4}, {0xa0,0xa0,0xfb,0x5b},
+{0x52,0x52,0xf6,0xa4}, {0x3b,0x3b,0x4d,0x76}, {0xd6,0xd6,0x61,0xb7}, {0xb3,0xb3,0xce,0x7d},
+{0x29,0x29,0x7b,0x52}, {0xe3,0xe3,0x3e,0xdd}, {0x2f,0x2f,0x71,0x5e}, {0x84,0x84,0x97,0x13},
+{0x53,0x53,0xf5,0xa6}, {0xd1,0xd1,0x68,0xb9}, {0x00,0x00,0x00,0x00}, {0xed,0xed,0x2c,0xc1},
+{0x20,0x20,0x60,0x40}, {0xfc,0xfc,0x1f,0xe3}, {0xb1,0xb1,0xc8,0x79}, {0x5b,0x5b,0xed,0xb6},
+{0x6a,0x6a,0xbe,0xd4}, {0xcb,0xcb,0x46,0x8d}, {0xbe,0xbe,0xd9,0x67}, {0x39,0x39,0x4b,0x72},
+{0x4a,0x4a,0xde,0x94}, {0x4c,0x4c,0xd4,0x98}, {0x58,0x58,0xe8,0xb0}, {0xcf,0xcf,0x4a,0x85},
+{0xd0,0xd0,0x6b,0xbb}, {0xef,0xef,0x2a,0xc5}, {0xaa,0xaa,0xe5,0x4f}, {0xfb,0xfb,0x16,0xed},
+{0x43,0x43,0xc5,0x86}, {0x4d,0x4d,0xd7,0x9a}, {0x33,0x33,0x55,0x66}, {0x85,0x85,0x94,0x11},
+{0x45,0x45,0xcf,0x8a}, {0xf9,0xf9,0x10,0xe9}, {0x02,0x02,0x06,0x04}, {0x7f,0x7f,0x81,0xfe},
+{0x50,0x50,0xf0,0xa0}, {0x3c,0x3c,0x44,0x78}, {0x9f,0x9f,0xba,0x25}, {0xa8,0xa8,0xe3,0x4b},
+{0x51,0x51,0xf3,0xa2}, {0xa3,0xa3,0xfe,0x5d}, {0x40,0x40,0xc0,0x80}, {0x8f,0x8f,0x8a,0x05},
+{0x92,0x92,0xad,0x3f}, {0x9d,0x9d,0xbc,0x21}, {0x38,0x38,0x48,0x70}, {0xf5,0xf5,0x04,0xf1},
+{0xbc,0xbc,0xdf,0x63}, {0xb6,0xb6,0xc1,0x77}, {0xda,0xda,0x75,0xaf}, {0x21,0x21,0x63,0x42},
+{0x10,0x10,0x30,0x20}, {0xff,0xff,0x1a,0xe5}, {0xf3,0xf3,0x0e,0xfd}, {0xd2,0xd2,0x6d,0xbf},
+{0xcd,0xcd,0x4c,0x81}, {0x0c,0x0c,0x14,0x18}, {0x13,0x13,0x35,0x26}, {0xec,0xec,0x2f,0xc3},
+{0x5f,0x5f,0xe1,0xbe}, {0x97,0x97,0xa2,0x35}, {0x44,0x44,0xcc,0x88}, {0x17,0x17,0x39,0x2e},
+{0xc4,0xc4,0x57,0x93}, {0xa7,0xa7,0xf2,0x55}, {0x7e,0x7e,0x82,0xfc}, {0x3d,0x3d,0x47,0x7a},
+{0x64,0x64,0xac,0xc8}, {0x5d,0x5d,0xe7,0xba}, {0x19,0x19,0x2b,0x32}, {0x73,0x73,0x95,0xe6},
+{0x60,0x60,0xa0,0xc0}, {0x81,0x81,0x98,0x19}, {0x4f,0x4f,0xd1,0x9e}, {0xdc,0xdc,0x7f,0xa3},
+{0x22,0x22,0x66,0x44}, {0x2a,0x2a,0x7e,0x54}, {0x90,0x90,0xab,0x3b}, {0x88,0x88,0x83,0x0b},
+{0x46,0x46,0xca,0x8c}, {0xee,0xee,0x29,0xc7}, {0xb8,0xb8,0xd3,0x6b}, {0x14,0x14,0x3c,0x28},
+{0xde,0xde,0x79,0xa7}, {0x5e,0x5e,0xe2,0xbc}, {0x0b,0x0b,0x1d,0x16}, {0xdb,0xdb,0x76,0xad},
+{0xe0,0xe0,0x3b,0xdb}, {0x32,0x32,0x56,0x64}, {0x3a,0x3a,0x4e,0x74}, {0x0a,0x0a,0x1e,0x14},
+{0x49,0x49,0xdb,0x92}, {0x06,0x06,0x0a,0x0c}, {0x24,0x24,0x6c,0x48}, {0x5c,0x5c,0xe4,0xb8},
+{0xc2,0xc2,0x5d,0x9f}, {0xd3,0xd3,0x6e,0xbd}, {0xac,0xac,0xef,0x43}, {0x62,0x62,0xa6,0xc4},
+{0x91,0x91,0xa8,0x39}, {0x95,0x95,0xa4,0x31}, {0xe4,0xe4,0x37,0xd3}, {0x79,0x79,0x8b,0xf2},
+{0xe7,0xe7,0x32,0xd5}, {0xc8,0xc8,0x43,0x8b}, {0x37,0x37,0x59,0x6e}, {0x6d,0x6d,0xb7,0xda},
+{0x8d,0x8d,0x8c,0x01}, {0xd5,0xd5,0x64,0xb1}, {0x4e,0x4e,0xd2,0x9c}, {0xa9,0xa9,0xe0,0x49},
+{0x6c,0x6c,0xb4,0xd8}, {0x56,0x56,0xfa,0xac}, {0xf4,0xf4,0x07,0xf3}, {0xea,0xea,0x25,0xcf},
+{0x65,0x65,0xaf,0xca}, {0x7a,0x7a,0x8e,0xf4}, {0xae,0xae,0xe9,0x47}, {0x08,0x08,0x18,0x10},
+{0xba,0xba,0xd5,0x6f}, {0x78,0x78,0x88,0xf0}, {0x25,0x25,0x6f,0x4a}, {0x2e,0x2e,0x72,0x5c},
+{0x1c,0x1c,0x24,0x38}, {0xa6,0xa6,0xf1,0x57}, {0xb4,0xb4,0xc7,0x73}, {0xc6,0xc6,0x51,0x97},
+{0xe8,0xe8,0x23,0xcb}, {0xdd,0xdd,0x7c,0xa1}, {0x74,0x74,0x9c,0xe8}, {0x1f,0x1f,0x21,0x3e},
+{0x4b,0x4b,0xdd,0x96}, {0xbd,0xbd,0xdc,0x61}, {0x8b,0x8b,0x86,0x0d}, {0x8a,0x8a,0x85,0x0f},
+{0x70,0x70,0x90,0xe0}, {0x3e,0x3e,0x42,0x7c}, {0xb5,0xb5,0xc4,0x71}, {0x66,0x66,0xaa,0xcc},
+{0x48,0x48,0xd8,0x90}, {0x03,0x03,0x05,0x06}, {0xf6,0xf6,0x01,0xf7}, {0x0e,0x0e,0x12,0x1c},
+{0x61,0x61,0xa3,0xc2}, {0x35,0x35,0x5f,0x6a}, {0x57,0x57,0xf9,0xae}, {0xb9,0xb9,0xd0,0x69},
+{0x86,0x86,0x91,0x17}, {0xc1,0xc1,0x58,0x99}, {0x1d,0x1d,0x27,0x3a}, {0x9e,0x9e,0xb9,0x27},
+{0xe1,0xe1,0x38,0xd9}, {0xf8,0xf8,0x13,0xeb}, {0x98,0x98,0xb3,0x2b}, {0x11,0x11,0x33,0x22},
+{0x69,0x69,0xbb,0xd2}, {0xd9,0xd9,0x70,0xa9}, {0x8e,0x8e,0x89,0x07}, {0x94,0x94,0xa7,0x33},
+{0x9b,0x9b,0xb6,0x2d}, {0x1e,0x1e,0x22,0x3c}, {0x87,0x87,0x92,0x15}, {0xe9,0xe9,0x20,0xc9},
+{0xce,0xce,0x49,0x87}, {0x55,0x55,0xff,0xaa}, {0x28,0x28,0x78,0x50}, {0xdf,0xdf,0x7a,0xa5},
+{0x8c,0x8c,0x8f,0x03}, {0xa1,0xa1,0xf8,0x59}, {0x89,0x89,0x80,0x09}, {0x0d,0x0d,0x17,0x1a},
+{0xbf,0xbf,0xda,0x65}, {0xe6,0xe6,0x31,0xd7}, {0x42,0x42,0xc6,0x84}, {0x68,0x68,0xb8,0xd0},
+{0x41,0x41,0xc3,0x82}, {0x99,0x99,0xb0,0x29}, {0x2d,0x2d,0x77,0x5a}, {0x0f,0x0f,0x11,0x1e},
+{0xb0,0xb0,0xcb,0x7b}, {0x54,0x54,0xfc,0xa8}, {0xbb,0xbb,0xd6,0x6d}, {0x16,0x16,0x3a,0x2c},
+};
+
+word8 T5[256][4] = {
+{0x51,0xf4,0xa7,0x50}, {0x7e,0x41,0x65,0x53}, {0x1a,0x17,0xa4,0xc3}, {0x3a,0x27,0x5e,0x96},
+{0x3b,0xab,0x6b,0xcb}, {0x1f,0x9d,0x45,0xf1}, {0xac,0xfa,0x58,0xab}, {0x4b,0xe3,0x03,0x93},
+{0x20,0x30,0xfa,0x55}, {0xad,0x76,0x6d,0xf6}, {0x88,0xcc,0x76,0x91}, {0xf5,0x02,0x4c,0x25},
+{0x4f,0xe5,0xd7,0xfc}, {0xc5,0x2a,0xcb,0xd7}, {0x26,0x35,0x44,0x80}, {0xb5,0x62,0xa3,0x8f},
+{0xde,0xb1,0x5a,0x49}, {0x25,0xba,0x1b,0x67}, {0x45,0xea,0x0e,0x98}, {0x5d,0xfe,0xc0,0xe1},
+{0xc3,0x2f,0x75,0x02}, {0x81,0x4c,0xf0,0x12}, {0x8d,0x46,0x97,0xa3}, {0x6b,0xd3,0xf9,0xc6},
+{0x03,0x8f,0x5f,0xe7}, {0x15,0x92,0x9c,0x95}, {0xbf,0x6d,0x7a,0xeb}, {0x95,0x52,0x59,0xda},
+{0xd4,0xbe,0x83,0x2d}, {0x58,0x74,0x21,0xd3}, {0x49,0xe0,0x69,0x29}, {0x8e,0xc9,0xc8,0x44},
+{0x75,0xc2,0x89,0x6a}, {0xf4,0x8e,0x79,0x78}, {0x99,0x58,0x3e,0x6b}, {0x27,0xb9,0x71,0xdd},
+{0xbe,0xe1,0x4f,0xb6}, {0xf0,0x88,0xad,0x17}, {0xc9,0x20,0xac,0x66}, {0x7d,0xce,0x3a,0xb4},
+{0x63,0xdf,0x4a,0x18}, {0xe5,0x1a,0x31,0x82}, {0x97,0x51,0x33,0x60}, {0x62,0x53,0x7f,0x45},
+{0xb1,0x64,0x77,0xe0}, {0xbb,0x6b,0xae,0x84}, {0xfe,0x81,0xa0,0x1c}, {0xf9,0x08,0x2b,0x94},
+{0x70,0x48,0x68,0x58}, {0x8f,0x45,0xfd,0x19}, {0x94,0xde,0x6c,0x87}, {0x52,0x7b,0xf8,0xb7},
+{0xab,0x73,0xd3,0x23}, {0x72,0x4b,0x02,0xe2}, {0xe3,0x1f,0x8f,0x57}, {0x66,0x55,0xab,0x2a},
+{0xb2,0xeb,0x28,0x07}, {0x2f,0xb5,0xc2,0x03}, {0x86,0xc5,0x7b,0x9a}, {0xd3,0x37,0x08,0xa5},
+{0x30,0x28,0x87,0xf2}, {0x23,0xbf,0xa5,0xb2}, {0x02,0x03,0x6a,0xba}, {0xed,0x16,0x82,0x5c},
+{0x8a,0xcf,0x1c,0x2b}, {0xa7,0x79,0xb4,0x92}, {0xf3,0x07,0xf2,0xf0}, {0x4e,0x69,0xe2,0xa1},
+{0x65,0xda,0xf4,0xcd}, {0x06,0x05,0xbe,0xd5}, {0xd1,0x34,0x62,0x1f}, {0xc4,0xa6,0xfe,0x8a},
+{0x34,0x2e,0x53,0x9d}, {0xa2,0xf3,0x55,0xa0}, {0x05,0x8a,0xe1,0x32}, {0xa4,0xf6,0xeb,0x75},
+{0x0b,0x83,0xec,0x39}, {0x40,0x60,0xef,0xaa}, {0x5e,0x71,0x9f,0x06}, {0xbd,0x6e,0x10,0x51},
+{0x3e,0x21,0x8a,0xf9}, {0x96,0xdd,0x06,0x3d}, {0xdd,0x3e,0x05,0xae}, {0x4d,0xe6,0xbd,0x46},
+{0x91,0x54,0x8d,0xb5}, {0x71,0xc4,0x5d,0x05}, {0x04,0x06,0xd4,0x6f}, {0x60,0x50,0x15,0xff},
+{0x19,0x98,0xfb,0x24}, {0xd6,0xbd,0xe9,0x97}, {0x89,0x40,0x43,0xcc}, {0x67,0xd9,0x9e,0x77},
+{0xb0,0xe8,0x42,0xbd}, {0x07,0x89,0x8b,0x88}, {0xe7,0x19,0x5b,0x38}, {0x79,0xc8,0xee,0xdb},
+{0xa1,0x7c,0x0a,0x47}, {0x7c,0x42,0x0f,0xe9}, {0xf8,0x84,0x1e,0xc9}, {0x00,0x00,0x00,0x00},
+{0x09,0x80,0x86,0x83}, {0x32,0x2b,0xed,0x48}, {0x1e,0x11,0x70,0xac}, {0x6c,0x5a,0x72,0x4e},
+{0xfd,0x0e,0xff,0xfb}, {0x0f,0x85,0x38,0x56}, {0x3d,0xae,0xd5,0x1e}, {0x36,0x2d,0x39,0x27},
+{0x0a,0x0f,0xd9,0x64}, {0x68,0x5c,0xa6,0x21}, {0x9b,0x5b,0x54,0xd1}, {0x24,0x36,0x2e,0x3a},
+{0x0c,0x0a,0x67,0xb1}, {0x93,0x57,0xe7,0x0f}, {0xb4,0xee,0x96,0xd2}, {0x1b,0x9b,0x91,0x9e},
+{0x80,0xc0,0xc5,0x4f}, {0x61,0xdc,0x20,0xa2}, {0x5a,0x77,0x4b,0x69}, {0x1c,0x12,0x1a,0x16},
+{0xe2,0x93,0xba,0x0a}, {0xc0,0xa0,0x2a,0xe5}, {0x3c,0x22,0xe0,0x43}, {0x12,0x1b,0x17,0x1d},
+{0x0e,0x09,0x0d,0x0b}, {0xf2,0x8b,0xc7,0xad}, {0x2d,0xb6,0xa8,0xb9}, {0x14,0x1e,0xa9,0xc8},
+{0x57,0xf1,0x19,0x85}, {0xaf,0x75,0x07,0x4c}, {0xee,0x99,0xdd,0xbb}, {0xa3,0x7f,0x60,0xfd},
+{0xf7,0x01,0x26,0x9f}, {0x5c,0x72,0xf5,0xbc}, {0x44,0x66,0x3b,0xc5}, {0x5b,0xfb,0x7e,0x34},
+{0x8b,0x43,0x29,0x76}, {0xcb,0x23,0xc6,0xdc}, {0xb6,0xed,0xfc,0x68}, {0xb8,0xe4,0xf1,0x63},
+{0xd7,0x31,0xdc,0xca}, {0x42,0x63,0x85,0x10}, {0x13,0x97,0x22,0x40}, {0x84,0xc6,0x11,0x20},
+{0x85,0x4a,0x24,0x7d}, {0xd2,0xbb,0x3d,0xf8}, {0xae,0xf9,0x32,0x11}, {0xc7,0x29,0xa1,0x6d},
+{0x1d,0x9e,0x2f,0x4b}, {0xdc,0xb2,0x30,0xf3}, {0x0d,0x86,0x52,0xec}, {0x77,0xc1,0xe3,0xd0},
+{0x2b,0xb3,0x16,0x6c}, {0xa9,0x70,0xb9,0x99}, {0x11,0x94,0x48,0xfa}, {0x47,0xe9,0x64,0x22},
+{0xa8,0xfc,0x8c,0xc4}, {0xa0,0xf0,0x3f,0x1a}, {0x56,0x7d,0x2c,0xd8}, {0x22,0x33,0x90,0xef},
+{0x87,0x49,0x4e,0xc7}, {0xd9,0x38,0xd1,0xc1}, {0x8c,0xca,0xa2,0xfe}, {0x98,0xd4,0x0b,0x36},
+{0xa6,0xf5,0x81,0xcf}, {0xa5,0x7a,0xde,0x28}, {0xda,0xb7,0x8e,0x26}, {0x3f,0xad,0xbf,0xa4},
+{0x2c,0x3a,0x9d,0xe4}, {0x50,0x78,0x92,0x0d}, {0x6a,0x5f,0xcc,0x9b}, {0x54,0x7e,0x46,0x62},
+{0xf6,0x8d,0x13,0xc2}, {0x90,0xd8,0xb8,0xe8}, {0x2e,0x39,0xf7,0x5e}, {0x82,0xc3,0xaf,0xf5},
+{0x9f,0x5d,0x80,0xbe}, {0x69,0xd0,0x93,0x7c}, {0x6f,0xd5,0x2d,0xa9}, {0xcf,0x25,0x12,0xb3},
+{0xc8,0xac,0x99,0x3b}, {0x10,0x18,0x7d,0xa7}, {0xe8,0x9c,0x63,0x6e}, {0xdb,0x3b,0xbb,0x7b},
+{0xcd,0x26,0x78,0x09}, {0x6e,0x59,0x18,0xf4}, {0xec,0x9a,0xb7,0x01}, {0x83,0x4f,0x9a,0xa8},
+{0xe6,0x95,0x6e,0x65}, {0xaa,0xff,0xe6,0x7e}, {0x21,0xbc,0xcf,0x08}, {0xef,0x15,0xe8,0xe6},
+{0xba,0xe7,0x9b,0xd9}, {0x4a,0x6f,0x36,0xce}, {0xea,0x9f,0x09,0xd4}, {0x29,0xb0,0x7c,0xd6},
+{0x31,0xa4,0xb2,0xaf}, {0x2a,0x3f,0x23,0x31}, {0xc6,0xa5,0x94,0x30}, {0x35,0xa2,0x66,0xc0},
+{0x74,0x4e,0xbc,0x37}, {0xfc,0x82,0xca,0xa6}, {0xe0,0x90,0xd0,0xb0}, {0x33,0xa7,0xd8,0x15},
+{0xf1,0x04,0x98,0x4a}, {0x41,0xec,0xda,0xf7}, {0x7f,0xcd,0x50,0x0e}, {0x17,0x91,0xf6,0x2f},
+{0x76,0x4d,0xd6,0x8d}, {0x43,0xef,0xb0,0x4d}, {0xcc,0xaa,0x4d,0x54}, {0xe4,0x96,0x04,0xdf},
+{0x9e,0xd1,0xb5,0xe3}, {0x4c,0x6a,0x88,0x1b}, {0xc1,0x2c,0x1f,0xb8}, {0x46,0x65,0x51,0x7f},
+{0x9d,0x5e,0xea,0x04}, {0x01,0x8c,0x35,0x5d}, {0xfa,0x87,0x74,0x73}, {0xfb,0x0b,0x41,0x2e},
+{0xb3,0x67,0x1d,0x5a}, {0x92,0xdb,0xd2,0x52}, {0xe9,0x10,0x56,0x33}, {0x6d,0xd6,0x47,0x13},
+{0x9a,0xd7,0x61,0x8c}, {0x37,0xa1,0x0c,0x7a}, {0x59,0xf8,0x14,0x8e}, {0xeb,0x13,0x3c,0x89},
+{0xce,0xa9,0x27,0xee}, {0xb7,0x61,0xc9,0x35}, {0xe1,0x1c,0xe5,0xed}, {0x7a,0x47,0xb1,0x3c},
+{0x9c,0xd2,0xdf,0x59}, {0x55,0xf2,0x73,0x3f}, {0x18,0x14,0xce,0x79}, {0x73,0xc7,0x37,0xbf},
+{0x53,0xf7,0xcd,0xea}, {0x5f,0xfd,0xaa,0x5b}, {0xdf,0x3d,0x6f,0x14}, {0x78,0x44,0xdb,0x86},
+{0xca,0xaf,0xf3,0x81}, {0xb9,0x68,0xc4,0x3e}, {0x38,0x24,0x34,0x2c}, {0xc2,0xa3,0x40,0x5f},
+{0x16,0x1d,0xc3,0x72}, {0xbc,0xe2,0x25,0x0c}, {0x28,0x3c,0x49,0x8b}, {0xff,0x0d,0x95,0x41},
+{0x39,0xa8,0x01,0x71}, {0x08,0x0c,0xb3,0xde}, {0xd8,0xb4,0xe4,0x9c}, {0x64,0x56,0xc1,0x90},
+{0x7b,0xcb,0x84,0x61}, {0xd5,0x32,0xb6,0x70}, {0x48,0x6c,0x5c,0x74}, {0xd0,0xb8,0x57,0x42},
+};
+
+word8 T6[256][4] = {
+{0x50,0x51,0xf4,0xa7}, {0x53,0x7e,0x41,0x65}, {0xc3,0x1a,0x17,0xa4}, {0x96,0x3a,0x27,0x5e},
+{0xcb,0x3b,0xab,0x6b}, {0xf1,0x1f,0x9d,0x45}, {0xab,0xac,0xfa,0x58}, {0x93,0x4b,0xe3,0x03},
+{0x55,0x20,0x30,0xfa}, {0xf6,0xad,0x76,0x6d}, {0x91,0x88,0xcc,0x76}, {0x25,0xf5,0x02,0x4c},
+{0xfc,0x4f,0xe5,0xd7}, {0xd7,0xc5,0x2a,0xcb}, {0x80,0x26,0x35,0x44}, {0x8f,0xb5,0x62,0xa3},
+{0x49,0xde,0xb1,0x5a}, {0x67,0x25,0xba,0x1b}, {0x98,0x45,0xea,0x0e}, {0xe1,0x5d,0xfe,0xc0},
+{0x02,0xc3,0x2f,0x75}, {0x12,0x81,0x4c,0xf0}, {0xa3,0x8d,0x46,0x97}, {0xc6,0x6b,0xd3,0xf9},
+{0xe7,0x03,0x8f,0x5f}, {0x95,0x15,0x92,0x9c}, {0xeb,0xbf,0x6d,0x7a}, {0xda,0x95,0x52,0x59},
+{0x2d,0xd4,0xbe,0x83}, {0xd3,0x58,0x74,0x21}, {0x29,0x49,0xe0,0x69}, {0x44,0x8e,0xc9,0xc8},
+{0x6a,0x75,0xc2,0x89}, {0x78,0xf4,0x8e,0x79}, {0x6b,0x99,0x58,0x3e}, {0xdd,0x27,0xb9,0x71},
+{0xb6,0xbe,0xe1,0x4f}, {0x17,0xf0,0x88,0xad}, {0x66,0xc9,0x20,0xac}, {0xb4,0x7d,0xce,0x3a},
+{0x18,0x63,0xdf,0x4a}, {0x82,0xe5,0x1a,0x31}, {0x60,0x97,0x51,0x33}, {0x45,0x62,0x53,0x7f},
+{0xe0,0xb1,0x64,0x77}, {0x84,0xbb,0x6b,0xae}, {0x1c,0xfe,0x81,0xa0}, {0x94,0xf9,0x08,0x2b},
+{0x58,0x70,0x48,0x68}, {0x19,0x8f,0x45,0xfd}, {0x87,0x94,0xde,0x6c}, {0xb7,0x52,0x7b,0xf8},
+{0x23,0xab,0x73,0xd3}, {0xe2,0x72,0x4b,0x02}, {0x57,0xe3,0x1f,0x8f}, {0x2a,0x66,0x55,0xab},
+{0x07,0xb2,0xeb,0x28}, {0x03,0x2f,0xb5,0xc2}, {0x9a,0x86,0xc5,0x7b}, {0xa5,0xd3,0x37,0x08},
+{0xf2,0x30,0x28,0x87}, {0xb2,0x23,0xbf,0xa5}, {0xba,0x02,0x03,0x6a}, {0x5c,0xed,0x16,0x82},
+{0x2b,0x8a,0xcf,0x1c}, {0x92,0xa7,0x79,0xb4}, {0xf0,0xf3,0x07,0xf2}, {0xa1,0x4e,0x69,0xe2},
+{0xcd,0x65,0xda,0xf4}, {0xd5,0x06,0x05,0xbe}, {0x1f,0xd1,0x34,0x62}, {0x8a,0xc4,0xa6,0xfe},
+{0x9d,0x34,0x2e,0x53}, {0xa0,0xa2,0xf3,0x55}, {0x32,0x05,0x8a,0xe1}, {0x75,0xa4,0xf6,0xeb},
+{0x39,0x0b,0x83,0xec}, {0xaa,0x40,0x60,0xef}, {0x06,0x5e,0x71,0x9f}, {0x51,0xbd,0x6e,0x10},
+{0xf9,0x3e,0x21,0x8a}, {0x3d,0x96,0xdd,0x06}, {0xae,0xdd,0x3e,0x05}, {0x46,0x4d,0xe6,0xbd},
+{0xb5,0x91,0x54,0x8d}, {0x05,0x71,0xc4,0x5d}, {0x6f,0x04,0x06,0xd4}, {0xff,0x60,0x50,0x15},
+{0x24,0x19,0x98,0xfb}, {0x97,0xd6,0xbd,0xe9}, {0xcc,0x89,0x40,0x43}, {0x77,0x67,0xd9,0x9e},
+{0xbd,0xb0,0xe8,0x42}, {0x88,0x07,0x89,0x8b}, {0x38,0xe7,0x19,0x5b}, {0xdb,0x79,0xc8,0xee},
+{0x47,0xa1,0x7c,0x0a}, {0xe9,0x7c,0x42,0x0f}, {0xc9,0xf8,0x84,0x1e}, {0x00,0x00,0x00,0x00},
+{0x83,0x09,0x80,0x86}, {0x48,0x32,0x2b,0xed}, {0xac,0x1e,0x11,0x70}, {0x4e,0x6c,0x5a,0x72},
+{0xfb,0xfd,0x0e,0xff}, {0x56,0x0f,0x85,0x38}, {0x1e,0x3d,0xae,0xd5}, {0x27,0x36,0x2d,0x39},
+{0x64,0x0a,0x0f,0xd9}, {0x21,0x68,0x5c,0xa6}, {0xd1,0x9b,0x5b,0x54}, {0x3a,0x24,0x36,0x2e},
+{0xb1,0x0c,0x0a,0x67}, {0x0f,0x93,0x57,0xe7}, {0xd2,0xb4,0xee,0x96}, {0x9e,0x1b,0x9b,0x91},
+{0x4f,0x80,0xc0,0xc5}, {0xa2,0x61,0xdc,0x20}, {0x69,0x5a,0x77,0x4b}, {0x16,0x1c,0x12,0x1a},
+{0x0a,0xe2,0x93,0xba}, {0xe5,0xc0,0xa0,0x2a}, {0x43,0x3c,0x22,0xe0}, {0x1d,0x12,0x1b,0x17},
+{0x0b,0x0e,0x09,0x0d}, {0xad,0xf2,0x8b,0xc7}, {0xb9,0x2d,0xb6,0xa8}, {0xc8,0x14,0x1e,0xa9},
+{0x85,0x57,0xf1,0x19}, {0x4c,0xaf,0x75,0x07}, {0xbb,0xee,0x99,0xdd}, {0xfd,0xa3,0x7f,0x60},
+{0x9f,0xf7,0x01,0x26}, {0xbc,0x5c,0x72,0xf5}, {0xc5,0x44,0x66,0x3b}, {0x34,0x5b,0xfb,0x7e},
+{0x76,0x8b,0x43,0x29}, {0xdc,0xcb,0x23,0xc6}, {0x68,0xb6,0xed,0xfc}, {0x63,0xb8,0xe4,0xf1},
+{0xca,0xd7,0x31,0xdc}, {0x10,0x42,0x63,0x85}, {0x40,0x13,0x97,0x22}, {0x20,0x84,0xc6,0x11},
+{0x7d,0x85,0x4a,0x24}, {0xf8,0xd2,0xbb,0x3d}, {0x11,0xae,0xf9,0x32}, {0x6d,0xc7,0x29,0xa1},
+{0x4b,0x1d,0x9e,0x2f}, {0xf3,0xdc,0xb2,0x30}, {0xec,0x0d,0x86,0x52}, {0xd0,0x77,0xc1,0xe3},
+{0x6c,0x2b,0xb3,0x16}, {0x99,0xa9,0x70,0xb9}, {0xfa,0x11,0x94,0x48}, {0x22,0x47,0xe9,0x64},
+{0xc4,0xa8,0xfc,0x8c}, {0x1a,0xa0,0xf0,0x3f}, {0xd8,0x56,0x7d,0x2c}, {0xef,0x22,0x33,0x90},
+{0xc7,0x87,0x49,0x4e}, {0xc1,0xd9,0x38,0xd1}, {0xfe,0x8c,0xca,0xa2}, {0x36,0x98,0xd4,0x0b},
+{0xcf,0xa6,0xf5,0x81}, {0x28,0xa5,0x7a,0xde}, {0x26,0xda,0xb7,0x8e}, {0xa4,0x3f,0xad,0xbf},
+{0xe4,0x2c,0x3a,0x9d}, {0x0d,0x50,0x78,0x92}, {0x9b,0x6a,0x5f,0xcc}, {0x62,0x54,0x7e,0x46},
+{0xc2,0xf6,0x8d,0x13}, {0xe8,0x90,0xd8,0xb8}, {0x5e,0x2e,0x39,0xf7}, {0xf5,0x82,0xc3,0xaf},
+{0xbe,0x9f,0x5d,0x80}, {0x7c,0x69,0xd0,0x93}, {0xa9,0x6f,0xd5,0x2d}, {0xb3,0xcf,0x25,0x12},
+{0x3b,0xc8,0xac,0x99}, {0xa7,0x10,0x18,0x7d}, {0x6e,0xe8,0x9c,0x63}, {0x7b,0xdb,0x3b,0xbb},
+{0x09,0xcd,0x26,0x78}, {0xf4,0x6e,0x59,0x18}, {0x01,0xec,0x9a,0xb7}, {0xa8,0x83,0x4f,0x9a},
+{0x65,0xe6,0x95,0x6e}, {0x7e,0xaa,0xff,0xe6}, {0x08,0x21,0xbc,0xcf}, {0xe6,0xef,0x15,0xe8},
+{0xd9,0xba,0xe7,0x9b}, {0xce,0x4a,0x6f,0x36}, {0xd4,0xea,0x9f,0x09}, {0xd6,0x29,0xb0,0x7c},
+{0xaf,0x31,0xa4,0xb2}, {0x31,0x2a,0x3f,0x23}, {0x30,0xc6,0xa5,0x94}, {0xc0,0x35,0xa2,0x66},
+{0x37,0x74,0x4e,0xbc}, {0xa6,0xfc,0x82,0xca}, {0xb0,0xe0,0x90,0xd0}, {0x15,0x33,0xa7,0xd8},
+{0x4a,0xf1,0x04,0x98}, {0xf7,0x41,0xec,0xda}, {0x0e,0x7f,0xcd,0x50}, {0x2f,0x17,0x91,0xf6},
+{0x8d,0x76,0x4d,0xd6}, {0x4d,0x43,0xef,0xb0}, {0x54,0xcc,0xaa,0x4d}, {0xdf,0xe4,0x96,0x04},
+{0xe3,0x9e,0xd1,0xb5}, {0x1b,0x4c,0x6a,0x88}, {0xb8,0xc1,0x2c,0x1f}, {0x7f,0x46,0x65,0x51},
+{0x04,0x9d,0x5e,0xea}, {0x5d,0x01,0x8c,0x35}, {0x73,0xfa,0x87,0x74}, {0x2e,0xfb,0x0b,0x41},
+{0x5a,0xb3,0x67,0x1d}, {0x52,0x92,0xdb,0xd2}, {0x33,0xe9,0x10,0x56}, {0x13,0x6d,0xd6,0x47},
+{0x8c,0x9a,0xd7,0x61}, {0x7a,0x37,0xa1,0x0c}, {0x8e,0x59,0xf8,0x14}, {0x89,0xeb,0x13,0x3c},
+{0xee,0xce,0xa9,0x27}, {0x35,0xb7,0x61,0xc9}, {0xed,0xe1,0x1c,0xe5}, {0x3c,0x7a,0x47,0xb1},
+{0x59,0x9c,0xd2,0xdf}, {0x3f,0x55,0xf2,0x73}, {0x79,0x18,0x14,0xce}, {0xbf,0x73,0xc7,0x37},
+{0xea,0x53,0xf7,0xcd}, {0x5b,0x5f,0xfd,0xaa}, {0x14,0xdf,0x3d,0x6f}, {0x86,0x78,0x44,0xdb},
+{0x81,0xca,0xaf,0xf3}, {0x3e,0xb9,0x68,0xc4}, {0x2c,0x38,0x24,0x34}, {0x5f,0xc2,0xa3,0x40},
+{0x72,0x16,0x1d,0xc3}, {0x0c,0xbc,0xe2,0x25}, {0x8b,0x28,0x3c,0x49}, {0x41,0xff,0x0d,0x95},
+{0x71,0x39,0xa8,0x01}, {0xde,0x08,0x0c,0xb3}, {0x9c,0xd8,0xb4,0xe4}, {0x90,0x64,0x56,0xc1},
+{0x61,0x7b,0xcb,0x84}, {0x70,0xd5,0x32,0xb6}, {0x74,0x48,0x6c,0x5c}, {0x42,0xd0,0xb8,0x57},
+};
+
+word8 T7[256][4] = {
+{0xa7,0x50,0x51,0xf4}, {0x65,0x53,0x7e,0x41}, {0xa4,0xc3,0x1a,0x17}, {0x5e,0x96,0x3a,0x27},
+{0x6b,0xcb,0x3b,0xab}, {0x45,0xf1,0x1f,0x9d}, {0x58,0xab,0xac,0xfa}, {0x03,0x93,0x4b,0xe3},
+{0xfa,0x55,0x20,0x30}, {0x6d,0xf6,0xad,0x76}, {0x76,0x91,0x88,0xcc}, {0x4c,0x25,0xf5,0x02},
+{0xd7,0xfc,0x4f,0xe5}, {0xcb,0xd7,0xc5,0x2a}, {0x44,0x80,0x26,0x35}, {0xa3,0x8f,0xb5,0x62},
+{0x5a,0x49,0xde,0xb1}, {0x1b,0x67,0x25,0xba}, {0x0e,0x98,0x45,0xea}, {0xc0,0xe1,0x5d,0xfe},
+{0x75,0x02,0xc3,0x2f}, {0xf0,0x12,0x81,0x4c}, {0x97,0xa3,0x8d,0x46}, {0xf9,0xc6,0x6b,0xd3},
+{0x5f,0xe7,0x03,0x8f}, {0x9c,0x95,0x15,0x92}, {0x7a,0xeb,0xbf,0x6d}, {0x59,0xda,0x95,0x52},
+{0x83,0x2d,0xd4,0xbe}, {0x21,0xd3,0x58,0x74}, {0x69,0x29,0x49,0xe0}, {0xc8,0x44,0x8e,0xc9},
+{0x89,0x6a,0x75,0xc2}, {0x79,0x78,0xf4,0x8e}, {0x3e,0x6b,0x99,0x58}, {0x71,0xdd,0x27,0xb9},
+{0x4f,0xb6,0xbe,0xe1}, {0xad,0x17,0xf0,0x88}, {0xac,0x66,0xc9,0x20}, {0x3a,0xb4,0x7d,0xce},
+{0x4a,0x18,0x63,0xdf}, {0x31,0x82,0xe5,0x1a}, {0x33,0x60,0x97,0x51}, {0x7f,0x45,0x62,0x53},
+{0x77,0xe0,0xb1,0x64}, {0xae,0x84,0xbb,0x6b}, {0xa0,0x1c,0xfe,0x81}, {0x2b,0x94,0xf9,0x08},
+{0x68,0x58,0x70,0x48}, {0xfd,0x19,0x8f,0x45}, {0x6c,0x87,0x94,0xde}, {0xf8,0xb7,0x52,0x7b},
+{0xd3,0x23,0xab,0x73}, {0x02,0xe2,0x72,0x4b}, {0x8f,0x57,0xe3,0x1f}, {0xab,0x2a,0x66,0x55},
+{0x28,0x07,0xb2,0xeb}, {0xc2,0x03,0x2f,0xb5}, {0x7b,0x9a,0x86,0xc5}, {0x08,0xa5,0xd3,0x37},
+{0x87,0xf2,0x30,0x28}, {0xa5,0xb2,0x23,0xbf}, {0x6a,0xba,0x02,0x03}, {0x82,0x5c,0xed,0x16},
+{0x1c,0x2b,0x8a,0xcf}, {0xb4,0x92,0xa7,0x79}, {0xf2,0xf0,0xf3,0x07}, {0xe2,0xa1,0x4e,0x69},
+{0xf4,0xcd,0x65,0xda}, {0xbe,0xd5,0x06,0x05}, {0x62,0x1f,0xd1,0x34}, {0xfe,0x8a,0xc4,0xa6},
+{0x53,0x9d,0x34,0x2e}, {0x55,0xa0,0xa2,0xf3}, {0xe1,0x32,0x05,0x8a}, {0xeb,0x75,0xa4,0xf6},
+{0xec,0x39,0x0b,0x83}, {0xef,0xaa,0x40,0x60}, {0x9f,0x06,0x5e,0x71}, {0x10,0x51,0xbd,0x6e},
+{0x8a,0xf9,0x3e,0x21}, {0x06,0x3d,0x96,0xdd}, {0x05,0xae,0xdd,0x3e}, {0xbd,0x46,0x4d,0xe6},
+{0x8d,0xb5,0x91,0x54}, {0x5d,0x05,0x71,0xc4}, {0xd4,0x6f,0x04,0x06}, {0x15,0xff,0x60,0x50},
+{0xfb,0x24,0x19,0x98}, {0xe9,0x97,0xd6,0xbd}, {0x43,0xcc,0x89,0x40}, {0x9e,0x77,0x67,0xd9},
+{0x42,0xbd,0xb0,0xe8}, {0x8b,0x88,0x07,0x89}, {0x5b,0x38,0xe7,0x19}, {0xee,0xdb,0x79,0xc8},
+{0x0a,0x47,0xa1,0x7c}, {0x0f,0xe9,0x7c,0x42}, {0x1e,0xc9,0xf8,0x84}, {0x00,0x00,0x00,0x00},
+{0x86,0x83,0x09,0x80}, {0xed,0x48,0x32,0x2b}, {0x70,0xac,0x1e,0x11}, {0x72,0x4e,0x6c,0x5a},
+{0xff,0xfb,0xfd,0x0e}, {0x38,0x56,0x0f,0x85}, {0xd5,0x1e,0x3d,0xae}, {0x39,0x27,0x36,0x2d},
+{0xd9,0x64,0x0a,0x0f}, {0xa6,0x21,0x68,0x5c}, {0x54,0xd1,0x9b,0x5b}, {0x2e,0x3a,0x24,0x36},
+{0x67,0xb1,0x0c,0x0a}, {0xe7,0x0f,0x93,0x57}, {0x96,0xd2,0xb4,0xee}, {0x91,0x9e,0x1b,0x9b},
+{0xc5,0x4f,0x80,0xc0}, {0x20,0xa2,0x61,0xdc}, {0x4b,0x69,0x5a,0x77}, {0x1a,0x16,0x1c,0x12},
+{0xba,0x0a,0xe2,0x93}, {0x2a,0xe5,0xc0,0xa0}, {0xe0,0x43,0x3c,0x22}, {0x17,0x1d,0x12,0x1b},
+{0x0d,0x0b,0x0e,0x09}, {0xc7,0xad,0xf2,0x8b}, {0xa8,0xb9,0x2d,0xb6}, {0xa9,0xc8,0x14,0x1e},
+{0x19,0x85,0x57,0xf1}, {0x07,0x4c,0xaf,0x75}, {0xdd,0xbb,0xee,0x99}, {0x60,0xfd,0xa3,0x7f},
+{0x26,0x9f,0xf7,0x01}, {0xf5,0xbc,0x5c,0x72}, {0x3b,0xc5,0x44,0x66}, {0x7e,0x34,0x5b,0xfb},
+{0x29,0x76,0x8b,0x43}, {0xc6,0xdc,0xcb,0x23}, {0xfc,0x68,0xb6,0xed}, {0xf1,0x63,0xb8,0xe4},
+{0xdc,0xca,0xd7,0x31}, {0x85,0x10,0x42,0x63}, {0x22,0x40,0x13,0x97}, {0x11,0x20,0x84,0xc6},
+{0x24,0x7d,0x85,0x4a}, {0x3d,0xf8,0xd2,0xbb}, {0x32,0x11,0xae,0xf9}, {0xa1,0x6d,0xc7,0x29},
+{0x2f,0x4b,0x1d,0x9e}, {0x30,0xf3,0xdc,0xb2}, {0x52,0xec,0x0d,0x86}, {0xe3,0xd0,0x77,0xc1},
+{0x16,0x6c,0x2b,0xb3}, {0xb9,0x99,0xa9,0x70}, {0x48,0xfa,0x11,0x94}, {0x64,0x22,0x47,0xe9},
+{0x8c,0xc4,0xa8,0xfc}, {0x3f,0x1a,0xa0,0xf0}, {0x2c,0xd8,0x56,0x7d}, {0x90,0xef,0x22,0x33},
+{0x4e,0xc7,0x87,0x49}, {0xd1,0xc1,0xd9,0x38}, {0xa2,0xfe,0x8c,0xca}, {0x0b,0x36,0x98,0xd4},
+{0x81,0xcf,0xa6,0xf5}, {0xde,0x28,0xa5,0x7a}, {0x8e,0x26,0xda,0xb7}, {0xbf,0xa4,0x3f,0xad},
+{0x9d,0xe4,0x2c,0x3a}, {0x92,0x0d,0x50,0x78}, {0xcc,0x9b,0x6a,0x5f}, {0x46,0x62,0x54,0x7e},
+{0x13,0xc2,0xf6,0x8d}, {0xb8,0xe8,0x90,0xd8}, {0xf7,0x5e,0x2e,0x39}, {0xaf,0xf5,0x82,0xc3},
+{0x80,0xbe,0x9f,0x5d}, {0x93,0x7c,0x69,0xd0}, {0x2d,0xa9,0x6f,0xd5}, {0x12,0xb3,0xcf,0x25},
+{0x99,0x3b,0xc8,0xac}, {0x7d,0xa7,0x10,0x18}, {0x63,0x6e,0xe8,0x9c}, {0xbb,0x7b,0xdb,0x3b},
+{0x78,0x09,0xcd,0x26}, {0x18,0xf4,0x6e,0x59}, {0xb7,0x01,0xec,0x9a}, {0x9a,0xa8,0x83,0x4f},
+{0x6e,0x65,0xe6,0x95}, {0xe6,0x7e,0xaa,0xff}, {0xcf,0x08,0x21,0xbc}, {0xe8,0xe6,0xef,0x15},
+{0x9b,0xd9,0xba,0xe7}, {0x36,0xce,0x4a,0x6f}, {0x09,0xd4,0xea,0x9f}, {0x7c,0xd6,0x29,0xb0},
+{0xb2,0xaf,0x31,0xa4}, {0x23,0x31,0x2a,0x3f}, {0x94,0x30,0xc6,0xa5}, {0x66,0xc0,0x35,0xa2},
+{0xbc,0x37,0x74,0x4e}, {0xca,0xa6,0xfc,0x82}, {0xd0,0xb0,0xe0,0x90}, {0xd8,0x15,0x33,0xa7},
+{0x98,0x4a,0xf1,0x04}, {0xda,0xf7,0x41,0xec}, {0x50,0x0e,0x7f,0xcd}, {0xf6,0x2f,0x17,0x91},
+{0xd6,0x8d,0x76,0x4d}, {0xb0,0x4d,0x43,0xef}, {0x4d,0x54,0xcc,0xaa}, {0x04,0xdf,0xe4,0x96},
+{0xb5,0xe3,0x9e,0xd1}, {0x88,0x1b,0x4c,0x6a}, {0x1f,0xb8,0xc1,0x2c}, {0x51,0x7f,0x46,0x65},
+{0xea,0x04,0x9d,0x5e}, {0x35,0x5d,0x01,0x8c}, {0x74,0x73,0xfa,0x87}, {0x41,0x2e,0xfb,0x0b},
+{0x1d,0x5a,0xb3,0x67}, {0xd2,0x52,0x92,0xdb}, {0x56,0x33,0xe9,0x10}, {0x47,0x13,0x6d,0xd6},
+{0x61,0x8c,0x9a,0xd7}, {0x0c,0x7a,0x37,0xa1}, {0x14,0x8e,0x59,0xf8}, {0x3c,0x89,0xeb,0x13},
+{0x27,0xee,0xce,0xa9}, {0xc9,0x35,0xb7,0x61}, {0xe5,0xed,0xe1,0x1c}, {0xb1,0x3c,0x7a,0x47},
+{0xdf,0x59,0x9c,0xd2}, {0x73,0x3f,0x55,0xf2}, {0xce,0x79,0x18,0x14}, {0x37,0xbf,0x73,0xc7},
+{0xcd,0xea,0x53,0xf7}, {0xaa,0x5b,0x5f,0xfd}, {0x6f,0x14,0xdf,0x3d}, {0xdb,0x86,0x78,0x44},
+{0xf3,0x81,0xca,0xaf}, {0xc4,0x3e,0xb9,0x68}, {0x34,0x2c,0x38,0x24}, {0x40,0x5f,0xc2,0xa3},
+{0xc3,0x72,0x16,0x1d}, {0x25,0x0c,0xbc,0xe2}, {0x49,0x8b,0x28,0x3c}, {0x95,0x41,0xff,0x0d},
+{0x01,0x71,0x39,0xa8}, {0xb3,0xde,0x08,0x0c}, {0xe4,0x9c,0xd8,0xb4}, {0xc1,0x90,0x64,0x56},
+{0x84,0x61,0x7b,0xcb}, {0xb6,0x70,0xd5,0x32}, {0x5c,0x74,0x48,0x6c}, {0x57,0x42,0xd0,0xb8},
+};
+
+word8 T8[256][4] = {
+{0xf4,0xa7,0x50,0x51}, {0x41,0x65,0x53,0x7e}, {0x17,0xa4,0xc3,0x1a}, {0x27,0x5e,0x96,0x3a},
+{0xab,0x6b,0xcb,0x3b}, {0x9d,0x45,0xf1,0x1f}, {0xfa,0x58,0xab,0xac}, {0xe3,0x03,0x93,0x4b},
+{0x30,0xfa,0x55,0x20}, {0x76,0x6d,0xf6,0xad}, {0xcc,0x76,0x91,0x88}, {0x02,0x4c,0x25,0xf5},
+{0xe5,0xd7,0xfc,0x4f}, {0x2a,0xcb,0xd7,0xc5}, {0x35,0x44,0x80,0x26}, {0x62,0xa3,0x8f,0xb5},
+{0xb1,0x5a,0x49,0xde}, {0xba,0x1b,0x67,0x25}, {0xea,0x0e,0x98,0x45}, {0xfe,0xc0,0xe1,0x5d},
+{0x2f,0x75,0x02,0xc3}, {0x4c,0xf0,0x12,0x81}, {0x46,0x97,0xa3,0x8d}, {0xd3,0xf9,0xc6,0x6b},
+{0x8f,0x5f,0xe7,0x03}, {0x92,0x9c,0x95,0x15}, {0x6d,0x7a,0xeb,0xbf}, {0x52,0x59,0xda,0x95},
+{0xbe,0x83,0x2d,0xd4}, {0x74,0x21,0xd3,0x58}, {0xe0,0x69,0x29,0x49}, {0xc9,0xc8,0x44,0x8e},
+{0xc2,0x89,0x6a,0x75}, {0x8e,0x79,0x78,0xf4}, {0x58,0x3e,0x6b,0x99}, {0xb9,0x71,0xdd,0x27},
+{0xe1,0x4f,0xb6,0xbe}, {0x88,0xad,0x17,0xf0}, {0x20,0xac,0x66,0xc9}, {0xce,0x3a,0xb4,0x7d},
+{0xdf,0x4a,0x18,0x63}, {0x1a,0x31,0x82,0xe5}, {0x51,0x33,0x60,0x97}, {0x53,0x7f,0x45,0x62},
+{0x64,0x77,0xe0,0xb1}, {0x6b,0xae,0x84,0xbb}, {0x81,0xa0,0x1c,0xfe}, {0x08,0x2b,0x94,0xf9},
+{0x48,0x68,0x58,0x70}, {0x45,0xfd,0x19,0x8f}, {0xde,0x6c,0x87,0x94}, {0x7b,0xf8,0xb7,0x52},
+{0x73,0xd3,0x23,0xab}, {0x4b,0x02,0xe2,0x72}, {0x1f,0x8f,0x57,0xe3}, {0x55,0xab,0x2a,0x66},
+{0xeb,0x28,0x07,0xb2}, {0xb5,0xc2,0x03,0x2f}, {0xc5,0x7b,0x9a,0x86}, {0x37,0x08,0xa5,0xd3},
+{0x28,0x87,0xf2,0x30}, {0xbf,0xa5,0xb2,0x23}, {0x03,0x6a,0xba,0x02}, {0x16,0x82,0x5c,0xed},
+{0xcf,0x1c,0x2b,0x8a}, {0x79,0xb4,0x92,0xa7}, {0x07,0xf2,0xf0,0xf3}, {0x69,0xe2,0xa1,0x4e},
+{0xda,0xf4,0xcd,0x65}, {0x05,0xbe,0xd5,0x06}, {0x34,0x62,0x1f,0xd1}, {0xa6,0xfe,0x8a,0xc4},
+{0x2e,0x53,0x9d,0x34}, {0xf3,0x55,0xa0,0xa2}, {0x8a,0xe1,0x32,0x05}, {0xf6,0xeb,0x75,0xa4},
+{0x83,0xec,0x39,0x0b}, {0x60,0xef,0xaa,0x40}, {0x71,0x9f,0x06,0x5e}, {0x6e,0x10,0x51,0xbd},
+{0x21,0x8a,0xf9,0x3e}, {0xdd,0x06,0x3d,0x96}, {0x3e,0x05,0xae,0xdd}, {0xe6,0xbd,0x46,0x4d},
+{0x54,0x8d,0xb5,0x91}, {0xc4,0x5d,0x05,0x71}, {0x06,0xd4,0x6f,0x04}, {0x50,0x15,0xff,0x60},
+{0x98,0xfb,0x24,0x19}, {0xbd,0xe9,0x97,0xd6}, {0x40,0x43,0xcc,0x89}, {0xd9,0x9e,0x77,0x67},
+{0xe8,0x42,0xbd,0xb0}, {0x89,0x8b,0x88,0x07}, {0x19,0x5b,0x38,0xe7}, {0xc8,0xee,0xdb,0x79},
+{0x7c,0x0a,0x47,0xa1}, {0x42,0x0f,0xe9,0x7c}, {0x84,0x1e,0xc9,0xf8}, {0x00,0x00,0x00,0x00},
+{0x80,0x86,0x83,0x09}, {0x2b,0xed,0x48,0x32}, {0x11,0x70,0xac,0x1e}, {0x5a,0x72,0x4e,0x6c},
+{0x0e,0xff,0xfb,0xfd}, {0x85,0x38,0x56,0x0f}, {0xae,0xd5,0x1e,0x3d}, {0x2d,0x39,0x27,0x36},
+{0x0f,0xd9,0x64,0x0a}, {0x5c,0xa6,0x21,0x68}, {0x5b,0x54,0xd1,0x9b}, {0x36,0x2e,0x3a,0x24},
+{0x0a,0x67,0xb1,0x0c}, {0x57,0xe7,0x0f,0x93}, {0xee,0x96,0xd2,0xb4}, {0x9b,0x91,0x9e,0x1b},
+{0xc0,0xc5,0x4f,0x80}, {0xdc,0x20,0xa2,0x61}, {0x77,0x4b,0x69,0x5a}, {0x12,0x1a,0x16,0x1c},
+{0x93,0xba,0x0a,0xe2}, {0xa0,0x2a,0xe5,0xc0}, {0x22,0xe0,0x43,0x3c}, {0x1b,0x17,0x1d,0x12},
+{0x09,0x0d,0x0b,0x0e}, {0x8b,0xc7,0xad,0xf2}, {0xb6,0xa8,0xb9,0x2d}, {0x1e,0xa9,0xc8,0x14},
+{0xf1,0x19,0x85,0x57}, {0x75,0x07,0x4c,0xaf}, {0x99,0xdd,0xbb,0xee}, {0x7f,0x60,0xfd,0xa3},
+{0x01,0x26,0x9f,0xf7}, {0x72,0xf5,0xbc,0x5c}, {0x66,0x3b,0xc5,0x44}, {0xfb,0x7e,0x34,0x5b},
+{0x43,0x29,0x76,0x8b}, {0x23,0xc6,0xdc,0xcb}, {0xed,0xfc,0x68,0xb6}, {0xe4,0xf1,0x63,0xb8},
+{0x31,0xdc,0xca,0xd7}, {0x63,0x85,0x10,0x42}, {0x97,0x22,0x40,0x13}, {0xc6,0x11,0x20,0x84},
+{0x4a,0x24,0x7d,0x85}, {0xbb,0x3d,0xf8,0xd2}, {0xf9,0x32,0x11,0xae}, {0x29,0xa1,0x6d,0xc7},
+{0x9e,0x2f,0x4b,0x1d}, {0xb2,0x30,0xf3,0xdc}, {0x86,0x52,0xec,0x0d}, {0xc1,0xe3,0xd0,0x77},
+{0xb3,0x16,0x6c,0x2b}, {0x70,0xb9,0x99,0xa9}, {0x94,0x48,0xfa,0x11}, {0xe9,0x64,0x22,0x47},
+{0xfc,0x8c,0xc4,0xa8}, {0xf0,0x3f,0x1a,0xa0}, {0x7d,0x2c,0xd8,0x56}, {0x33,0x90,0xef,0x22},
+{0x49,0x4e,0xc7,0x87}, {0x38,0xd1,0xc1,0xd9}, {0xca,0xa2,0xfe,0x8c}, {0xd4,0x0b,0x36,0x98},
+{0xf5,0x81,0xcf,0xa6}, {0x7a,0xde,0x28,0xa5}, {0xb7,0x8e,0x26,0xda}, {0xad,0xbf,0xa4,0x3f},
+{0x3a,0x9d,0xe4,0x2c}, {0x78,0x92,0x0d,0x50}, {0x5f,0xcc,0x9b,0x6a}, {0x7e,0x46,0x62,0x54},
+{0x8d,0x13,0xc2,0xf6}, {0xd8,0xb8,0xe8,0x90}, {0x39,0xf7,0x5e,0x2e}, {0xc3,0xaf,0xf5,0x82},
+{0x5d,0x80,0xbe,0x9f}, {0xd0,0x93,0x7c,0x69}, {0xd5,0x2d,0xa9,0x6f}, {0x25,0x12,0xb3,0xcf},
+{0xac,0x99,0x3b,0xc8}, {0x18,0x7d,0xa7,0x10}, {0x9c,0x63,0x6e,0xe8}, {0x3b,0xbb,0x7b,0xdb},
+{0x26,0x78,0x09,0xcd}, {0x59,0x18,0xf4,0x6e}, {0x9a,0xb7,0x01,0xec}, {0x4f,0x9a,0xa8,0x83},
+{0x95,0x6e,0x65,0xe6}, {0xff,0xe6,0x7e,0xaa}, {0xbc,0xcf,0x08,0x21}, {0x15,0xe8,0xe6,0xef},
+{0xe7,0x9b,0xd9,0xba}, {0x6f,0x36,0xce,0x4a}, {0x9f,0x09,0xd4,0xea}, {0xb0,0x7c,0xd6,0x29},
+{0xa4,0xb2,0xaf,0x31}, {0x3f,0x23,0x31,0x2a}, {0xa5,0x94,0x30,0xc6}, {0xa2,0x66,0xc0,0x35},
+{0x4e,0xbc,0x37,0x74}, {0x82,0xca,0xa6,0xfc}, {0x90,0xd0,0xb0,0xe0}, {0xa7,0xd8,0x15,0x33},
+{0x04,0x98,0x4a,0xf1}, {0xec,0xda,0xf7,0x41}, {0xcd,0x50,0x0e,0x7f}, {0x91,0xf6,0x2f,0x17},
+{0x4d,0xd6,0x8d,0x76}, {0xef,0xb0,0x4d,0x43}, {0xaa,0x4d,0x54,0xcc}, {0x96,0x04,0xdf,0xe4},
+{0xd1,0xb5,0xe3,0x9e}, {0x6a,0x88,0x1b,0x4c}, {0x2c,0x1f,0xb8,0xc1}, {0x65,0x51,0x7f,0x46},
+{0x5e,0xea,0x04,0x9d}, {0x8c,0x35,0x5d,0x01}, {0x87,0x74,0x73,0xfa}, {0x0b,0x41,0x2e,0xfb},
+{0x67,0x1d,0x5a,0xb3}, {0xdb,0xd2,0x52,0x92}, {0x10,0x56,0x33,0xe9}, {0xd6,0x47,0x13,0x6d},
+{0xd7,0x61,0x8c,0x9a}, {0xa1,0x0c,0x7a,0x37}, {0xf8,0x14,0x8e,0x59}, {0x13,0x3c,0x89,0xeb},
+{0xa9,0x27,0xee,0xce}, {0x61,0xc9,0x35,0xb7}, {0x1c,0xe5,0xed,0xe1}, {0x47,0xb1,0x3c,0x7a},
+{0xd2,0xdf,0x59,0x9c}, {0xf2,0x73,0x3f,0x55}, {0x14,0xce,0x79,0x18}, {0xc7,0x37,0xbf,0x73},
+{0xf7,0xcd,0xea,0x53}, {0xfd,0xaa,0x5b,0x5f}, {0x3d,0x6f,0x14,0xdf}, {0x44,0xdb,0x86,0x78},
+{0xaf,0xf3,0x81,0xca}, {0x68,0xc4,0x3e,0xb9}, {0x24,0x34,0x2c,0x38}, {0xa3,0x40,0x5f,0xc2},
+{0x1d,0xc3,0x72,0x16}, {0xe2,0x25,0x0c,0xbc}, {0x3c,0x49,0x8b,0x28}, {0x0d,0x95,0x41,0xff},
+{0xa8,0x01,0x71,0x39}, {0x0c,0xb3,0xde,0x08}, {0xb4,0xe4,0x9c,0xd8}, {0x56,0xc1,0x90,0x64},
+{0xcb,0x84,0x61,0x7b}, {0x32,0xb6,0x70,0xd5}, {0x6c,0x5c,0x74,0x48}, {0xb8,0x57,0x42,0xd0},
+};
+
+word8 S5[256] = {
+0x52,0x09,0x6a,0xd5,
+0x30,0x36,0xa5,0x38,
+0xbf,0x40,0xa3,0x9e,
+0x81,0xf3,0xd7,0xfb,
+0x7c,0xe3,0x39,0x82,
+0x9b,0x2f,0xff,0x87,
+0x34,0x8e,0x43,0x44,
+0xc4,0xde,0xe9,0xcb,
+0x54,0x7b,0x94,0x32,
+0xa6,0xc2,0x23,0x3d,
+0xee,0x4c,0x95,0x0b,
+0x42,0xfa,0xc3,0x4e,
+0x08,0x2e,0xa1,0x66,
+0x28,0xd9,0x24,0xb2,
+0x76,0x5b,0xa2,0x49,
+0x6d,0x8b,0xd1,0x25,
+0x72,0xf8,0xf6,0x64,
+0x86,0x68,0x98,0x16,
+0xd4,0xa4,0x5c,0xcc,
+0x5d,0x65,0xb6,0x92,
+0x6c,0x70,0x48,0x50,
+0xfd,0xed,0xb9,0xda,
+0x5e,0x15,0x46,0x57,
+0xa7,0x8d,0x9d,0x84,
+0x90,0xd8,0xab,0x00,
+0x8c,0xbc,0xd3,0x0a,
+0xf7,0xe4,0x58,0x05,
+0xb8,0xb3,0x45,0x06,
+0xd0,0x2c,0x1e,0x8f,
+0xca,0x3f,0x0f,0x02,
+0xc1,0xaf,0xbd,0x03,
+0x01,0x13,0x8a,0x6b,
+0x3a,0x91,0x11,0x41,
+0x4f,0x67,0xdc,0xea,
+0x97,0xf2,0xcf,0xce,
+0xf0,0xb4,0xe6,0x73,
+0x96,0xac,0x74,0x22,
+0xe7,0xad,0x35,0x85,
+0xe2,0xf9,0x37,0xe8,
+0x1c,0x75,0xdf,0x6e,
+0x47,0xf1,0x1a,0x71,
+0x1d,0x29,0xc5,0x89,
+0x6f,0xb7,0x62,0x0e,
+0xaa,0x18,0xbe,0x1b,
+0xfc,0x56,0x3e,0x4b,
+0xc6,0xd2,0x79,0x20,
+0x9a,0xdb,0xc0,0xfe,
+0x78,0xcd,0x5a,0xf4,
+0x1f,0xdd,0xa8,0x33,
+0x88,0x07,0xc7,0x31,
+0xb1,0x12,0x10,0x59,
+0x27,0x80,0xec,0x5f,
+0x60,0x51,0x7f,0xa9,
+0x19,0xb5,0x4a,0x0d,
+0x2d,0xe5,0x7a,0x9f,
+0x93,0xc9,0x9c,0xef,
+0xa0,0xe0,0x3b,0x4d,
+0xae,0x2a,0xf5,0xb0,
+0xc8,0xeb,0xbb,0x3c,
+0x83,0x53,0x99,0x61,
+0x17,0x2b,0x04,0x7e,
+0xba,0x77,0xd6,0x26,
+0xe1,0x69,0x14,0x63,
+0x55,0x21,0x0c,0x7d,
+};
+
+word8 U1[256][4] = {
+{0x00,0x00,0x00,0x00}, {0x0e,0x09,0x0d,0x0b}, {0x1c,0x12,0x1a,0x16}, {0x12,0x1b,0x17,0x1d},
+{0x38,0x24,0x34,0x2c}, {0x36,0x2d,0x39,0x27}, {0x24,0x36,0x2e,0x3a}, {0x2a,0x3f,0x23,0x31},
+{0x70,0x48,0x68,0x58}, {0x7e,0x41,0x65,0x53}, {0x6c,0x5a,0x72,0x4e}, {0x62,0x53,0x7f,0x45},
+{0x48,0x6c,0x5c,0x74}, {0x46,0x65,0x51,0x7f}, {0x54,0x7e,0x46,0x62}, {0x5a,0x77,0x4b,0x69},
+{0xe0,0x90,0xd0,0xb0}, {0xee,0x99,0xdd,0xbb}, {0xfc,0x82,0xca,0xa6}, {0xf2,0x8b,0xc7,0xad},
+{0xd8,0xb4,0xe4,0x9c}, {0xd6,0xbd,0xe9,0x97}, {0xc4,0xa6,0xfe,0x8a}, {0xca,0xaf,0xf3,0x81},
+{0x90,0xd8,0xb8,0xe8}, {0x9e,0xd1,0xb5,0xe3}, {0x8c,0xca,0xa2,0xfe}, {0x82,0xc3,0xaf,0xf5},
+{0xa8,0xfc,0x8c,0xc4}, {0xa6,0xf5,0x81,0xcf}, {0xb4,0xee,0x96,0xd2}, {0xba,0xe7,0x9b,0xd9},
+{0xdb,0x3b,0xbb,0x7b}, {0xd5,0x32,0xb6,0x70}, {0xc7,0x29,0xa1,0x6d}, {0xc9,0x20,0xac,0x66},
+{0xe3,0x1f,0x8f,0x57}, {0xed,0x16,0x82,0x5c}, {0xff,0x0d,0x95,0x41}, {0xf1,0x04,0x98,0x4a},
+{0xab,0x73,0xd3,0x23}, {0xa5,0x7a,0xde,0x28}, {0xb7,0x61,0xc9,0x35}, {0xb9,0x68,0xc4,0x3e},
+{0x93,0x57,0xe7,0x0f}, {0x9d,0x5e,0xea,0x04}, {0x8f,0x45,0xfd,0x19}, {0x81,0x4c,0xf0,0x12},
+{0x3b,0xab,0x6b,0xcb}, {0x35,0xa2,0x66,0xc0}, {0x27,0xb9,0x71,0xdd}, {0x29,0xb0,0x7c,0xd6},
+{0x03,0x8f,0x5f,0xe7}, {0x0d,0x86,0x52,0xec}, {0x1f,0x9d,0x45,0xf1}, {0x11,0x94,0x48,0xfa},
+{0x4b,0xe3,0x03,0x93}, {0x45,0xea,0x0e,0x98}, {0x57,0xf1,0x19,0x85}, {0x59,0xf8,0x14,0x8e},
+{0x73,0xc7,0x37,0xbf}, {0x7d,0xce,0x3a,0xb4}, {0x6f,0xd5,0x2d,0xa9}, {0x61,0xdc,0x20,0xa2},
+{0xad,0x76,0x6d,0xf6}, {0xa3,0x7f,0x60,0xfd}, {0xb1,0x64,0x77,0xe0}, {0xbf,0x6d,0x7a,0xeb},
+{0x95,0x52,0x59,0xda}, {0x9b,0x5b,0x54,0xd1}, {0x89,0x40,0x43,0xcc}, {0x87,0x49,0x4e,0xc7},
+{0xdd,0x3e,0x05,0xae}, {0xd3,0x37,0x08,0xa5}, {0xc1,0x2c,0x1f,0xb8}, {0xcf,0x25,0x12,0xb3},
+{0xe5,0x1a,0x31,0x82}, {0xeb,0x13,0x3c,0x89}, {0xf9,0x08,0x2b,0x94}, {0xf7,0x01,0x26,0x9f},
+{0x4d,0xe6,0xbd,0x46}, {0x43,0xef,0xb0,0x4d}, {0x51,0xf4,0xa7,0x50}, {0x5f,0xfd,0xaa,0x5b},
+{0x75,0xc2,0x89,0x6a}, {0x7b,0xcb,0x84,0x61}, {0x69,0xd0,0x93,0x7c}, {0x67,0xd9,0x9e,0x77},
+{0x3d,0xae,0xd5,0x1e}, {0x33,0xa7,0xd8,0x15}, {0x21,0xbc,0xcf,0x08}, {0x2f,0xb5,0xc2,0x03},
+{0x05,0x8a,0xe1,0x32}, {0x0b,0x83,0xec,0x39}, {0x19,0x98,0xfb,0x24}, {0x17,0x91,0xf6,0x2f},
+{0x76,0x4d,0xd6,0x8d}, {0x78,0x44,0xdb,0x86}, {0x6a,0x5f,0xcc,0x9b}, {0x64,0x56,0xc1,0x90},
+{0x4e,0x69,0xe2,0xa1}, {0x40,0x60,0xef,0xaa}, {0x52,0x7b,0xf8,0xb7}, {0x5c,0x72,0xf5,0xbc},
+{0x06,0x05,0xbe,0xd5}, {0x08,0x0c,0xb3,0xde}, {0x1a,0x17,0xa4,0xc3}, {0x14,0x1e,0xa9,0xc8},
+{0x3e,0x21,0x8a,0xf9}, {0x30,0x28,0x87,0xf2}, {0x22,0x33,0x90,0xef}, {0x2c,0x3a,0x9d,0xe4},
+{0x96,0xdd,0x06,0x3d}, {0x98,0xd4,0x0b,0x36}, {0x8a,0xcf,0x1c,0x2b}, {0x84,0xc6,0x11,0x20},
+{0xae,0xf9,0x32,0x11}, {0xa0,0xf0,0x3f,0x1a}, {0xb2,0xeb,0x28,0x07}, {0xbc,0xe2,0x25,0x0c},
+{0xe6,0x95,0x6e,0x65}, {0xe8,0x9c,0x63,0x6e}, {0xfa,0x87,0x74,0x73}, {0xf4,0x8e,0x79,0x78},
+{0xde,0xb1,0x5a,0x49}, {0xd0,0xb8,0x57,0x42}, {0xc2,0xa3,0x40,0x5f}, {0xcc,0xaa,0x4d,0x54},
+{0x41,0xec,0xda,0xf7}, {0x4f,0xe5,0xd7,0xfc}, {0x5d,0xfe,0xc0,0xe1}, {0x53,0xf7,0xcd,0xea},
+{0x79,0xc8,0xee,0xdb}, {0x77,0xc1,0xe3,0xd0}, {0x65,0xda,0xf4,0xcd}, {0x6b,0xd3,0xf9,0xc6},
+{0x31,0xa4,0xb2,0xaf}, {0x3f,0xad,0xbf,0xa4}, {0x2d,0xb6,0xa8,0xb9}, {0x23,0xbf,0xa5,0xb2},
+{0x09,0x80,0x86,0x83}, {0x07,0x89,0x8b,0x88}, {0x15,0x92,0x9c,0x95}, {0x1b,0x9b,0x91,0x9e},
+{0xa1,0x7c,0x0a,0x47}, {0xaf,0x75,0x07,0x4c}, {0xbd,0x6e,0x10,0x51}, {0xb3,0x67,0x1d,0x5a},
+{0x99,0x58,0x3e,0x6b}, {0x97,0x51,0x33,0x60}, {0x85,0x4a,0x24,0x7d}, {0x8b,0x43,0x29,0x76},
+{0xd1,0x34,0x62,0x1f}, {0xdf,0x3d,0x6f,0x14}, {0xcd,0x26,0x78,0x09}, {0xc3,0x2f,0x75,0x02},
+{0xe9,0x10,0x56,0x33}, {0xe7,0x19,0x5b,0x38}, {0xf5,0x02,0x4c,0x25}, {0xfb,0x0b,0x41,0x2e},
+{0x9a,0xd7,0x61,0x8c}, {0x94,0xde,0x6c,0x87}, {0x86,0xc5,0x7b,0x9a}, {0x88,0xcc,0x76,0x91},
+{0xa2,0xf3,0x55,0xa0}, {0xac,0xfa,0x58,0xab}, {0xbe,0xe1,0x4f,0xb6}, {0xb0,0xe8,0x42,0xbd},
+{0xea,0x9f,0x09,0xd4}, {0xe4,0x96,0x04,0xdf}, {0xf6,0x8d,0x13,0xc2}, {0xf8,0x84,0x1e,0xc9},
+{0xd2,0xbb,0x3d,0xf8}, {0xdc,0xb2,0x30,0xf3}, {0xce,0xa9,0x27,0xee}, {0xc0,0xa0,0x2a,0xe5},
+{0x7a,0x47,0xb1,0x3c}, {0x74,0x4e,0xbc,0x37}, {0x66,0x55,0xab,0x2a}, {0x68,0x5c,0xa6,0x21},
+{0x42,0x63,0x85,0x10}, {0x4c,0x6a,0x88,0x1b}, {0x5e,0x71,0x9f,0x06}, {0x50,0x78,0x92,0x0d},
+{0x0a,0x0f,0xd9,0x64}, {0x04,0x06,0xd4,0x6f}, {0x16,0x1d,0xc3,0x72}, {0x18,0x14,0xce,0x79},
+{0x32,0x2b,0xed,0x48}, {0x3c,0x22,0xe0,0x43}, {0x2e,0x39,0xf7,0x5e}, {0x20,0x30,0xfa,0x55},
+{0xec,0x9a,0xb7,0x01}, {0xe2,0x93,0xba,0x0a}, {0xf0,0x88,0xad,0x17}, {0xfe,0x81,0xa0,0x1c},
+{0xd4,0xbe,0x83,0x2d}, {0xda,0xb7,0x8e,0x26}, {0xc8,0xac,0x99,0x3b}, {0xc6,0xa5,0x94,0x30},
+{0x9c,0xd2,0xdf,0x59}, {0x92,0xdb,0xd2,0x52}, {0x80,0xc0,0xc5,0x4f}, {0x8e,0xc9,0xc8,0x44},
+{0xa4,0xf6,0xeb,0x75}, {0xaa,0xff,0xe6,0x7e}, {0xb8,0xe4,0xf1,0x63}, {0xb6,0xed,0xfc,0x68},
+{0x0c,0x0a,0x67,0xb1}, {0x02,0x03,0x6a,0xba}, {0x10,0x18,0x7d,0xa7}, {0x1e,0x11,0x70,0xac},
+{0x34,0x2e,0x53,0x9d}, {0x3a,0x27,0x5e,0x96}, {0x28,0x3c,0x49,0x8b}, {0x26,0x35,0x44,0x80},
+{0x7c,0x42,0x0f,0xe9}, {0x72,0x4b,0x02,0xe2}, {0x60,0x50,0x15,0xff}, {0x6e,0x59,0x18,0xf4},
+{0x44,0x66,0x3b,0xc5}, {0x4a,0x6f,0x36,0xce}, {0x58,0x74,0x21,0xd3}, {0x56,0x7d,0x2c,0xd8},
+{0x37,0xa1,0x0c,0x7a}, {0x39,0xa8,0x01,0x71}, {0x2b,0xb3,0x16,0x6c}, {0x25,0xba,0x1b,0x67},
+{0x0f,0x85,0x38,0x56}, {0x01,0x8c,0x35,0x5d}, {0x13,0x97,0x22,0x40}, {0x1d,0x9e,0x2f,0x4b},
+{0x47,0xe9,0x64,0x22}, {0x49,0xe0,0x69,0x29}, {0x5b,0xfb,0x7e,0x34}, {0x55,0xf2,0x73,0x3f},
+{0x7f,0xcd,0x50,0x0e}, {0x71,0xc4,0x5d,0x05}, {0x63,0xdf,0x4a,0x18}, {0x6d,0xd6,0x47,0x13},
+{0xd7,0x31,0xdc,0xca}, {0xd9,0x38,0xd1,0xc1}, {0xcb,0x23,0xc6,0xdc}, {0xc5,0x2a,0xcb,0xd7},
+{0xef,0x15,0xe8,0xe6}, {0xe1,0x1c,0xe5,0xed}, {0xf3,0x07,0xf2,0xf0}, {0xfd,0x0e,0xff,0xfb},
+{0xa7,0x79,0xb4,0x92}, {0xa9,0x70,0xb9,0x99}, {0xbb,0x6b,0xae,0x84}, {0xb5,0x62,0xa3,0x8f},
+{0x9f,0x5d,0x80,0xbe}, {0x91,0x54,0x8d,0xb5}, {0x83,0x4f,0x9a,0xa8}, {0x8d,0x46,0x97,0xa3},
+};
+
+word8 U2[256][4] = {
+{0x00,0x00,0x00,0x00}, {0x0b,0x0e,0x09,0x0d}, {0x16,0x1c,0x12,0x1a}, {0x1d,0x12,0x1b,0x17},
+{0x2c,0x38,0x24,0x34}, {0x27,0x36,0x2d,0x39}, {0x3a,0x24,0x36,0x2e}, {0x31,0x2a,0x3f,0x23},
+{0x58,0x70,0x48,0x68}, {0x53,0x7e,0x41,0x65}, {0x4e,0x6c,0x5a,0x72}, {0x45,0x62,0x53,0x7f},
+{0x74,0x48,0x6c,0x5c}, {0x7f,0x46,0x65,0x51}, {0x62,0x54,0x7e,0x46}, {0x69,0x5a,0x77,0x4b},
+{0xb0,0xe0,0x90,0xd0}, {0xbb,0xee,0x99,0xdd}, {0xa6,0xfc,0x82,0xca}, {0xad,0xf2,0x8b,0xc7},
+{0x9c,0xd8,0xb4,0xe4}, {0x97,0xd6,0xbd,0xe9}, {0x8a,0xc4,0xa6,0xfe}, {0x81,0xca,0xaf,0xf3},
+{0xe8,0x90,0xd8,0xb8}, {0xe3,0x9e,0xd1,0xb5}, {0xfe,0x8c,0xca,0xa2}, {0xf5,0x82,0xc3,0xaf},
+{0xc4,0xa8,0xfc,0x8c}, {0xcf,0xa6,0xf5,0x81}, {0xd2,0xb4,0xee,0x96}, {0xd9,0xba,0xe7,0x9b},
+{0x7b,0xdb,0x3b,0xbb}, {0x70,0xd5,0x32,0xb6}, {0x6d,0xc7,0x29,0xa1}, {0x66,0xc9,0x20,0xac},
+{0x57,0xe3,0x1f,0x8f}, {0x5c,0xed,0x16,0x82}, {0x41,0xff,0x0d,0x95}, {0x4a,0xf1,0x04,0x98},
+{0x23,0xab,0x73,0xd3}, {0x28,0xa5,0x7a,0xde}, {0x35,0xb7,0x61,0xc9}, {0x3e,0xb9,0x68,0xc4},
+{0x0f,0x93,0x57,0xe7}, {0x04,0x9d,0x5e,0xea}, {0x19,0x8f,0x45,0xfd}, {0x12,0x81,0x4c,0xf0},
+{0xcb,0x3b,0xab,0x6b}, {0xc0,0x35,0xa2,0x66}, {0xdd,0x27,0xb9,0x71}, {0xd6,0x29,0xb0,0x7c},
+{0xe7,0x03,0x8f,0x5f}, {0xec,0x0d,0x86,0x52}, {0xf1,0x1f,0x9d,0x45}, {0xfa,0x11,0x94,0x48},
+{0x93,0x4b,0xe3,0x03}, {0x98,0x45,0xea,0x0e}, {0x85,0x57,0xf1,0x19}, {0x8e,0x59,0xf8,0x14},
+{0xbf,0x73,0xc7,0x37}, {0xb4,0x7d,0xce,0x3a}, {0xa9,0x6f,0xd5,0x2d}, {0xa2,0x61,0xdc,0x20},
+{0xf6,0xad,0x76,0x6d}, {0xfd,0xa3,0x7f,0x60}, {0xe0,0xb1,0x64,0x77}, {0xeb,0xbf,0x6d,0x7a},
+{0xda,0x95,0x52,0x59}, {0xd1,0x9b,0x5b,0x54}, {0xcc,0x89,0x40,0x43}, {0xc7,0x87,0x49,0x4e},
+{0xae,0xdd,0x3e,0x05}, {0xa5,0xd3,0x37,0x08}, {0xb8,0xc1,0x2c,0x1f}, {0xb3,0xcf,0x25,0x12},
+{0x82,0xe5,0x1a,0x31}, {0x89,0xeb,0x13,0x3c}, {0x94,0xf9,0x08,0x2b}, {0x9f,0xf7,0x01,0x26},
+{0x46,0x4d,0xe6,0xbd}, {0x4d,0x43,0xef,0xb0}, {0x50,0x51,0xf4,0xa7}, {0x5b,0x5f,0xfd,0xaa},
+{0x6a,0x75,0xc2,0x89}, {0x61,0x7b,0xcb,0x84}, {0x7c,0x69,0xd0,0x93}, {0x77,0x67,0xd9,0x9e},
+{0x1e,0x3d,0xae,0xd5}, {0x15,0x33,0xa7,0xd8}, {0x08,0x21,0xbc,0xcf}, {0x03,0x2f,0xb5,0xc2},
+{0x32,0x05,0x8a,0xe1}, {0x39,0x0b,0x83,0xec}, {0x24,0x19,0x98,0xfb}, {0x2f,0x17,0x91,0xf6},
+{0x8d,0x76,0x4d,0xd6}, {0x86,0x78,0x44,0xdb}, {0x9b,0x6a,0x5f,0xcc}, {0x90,0x64,0x56,0xc1},
+{0xa1,0x4e,0x69,0xe2}, {0xaa,0x40,0x60,0xef}, {0xb7,0x52,0x7b,0xf8}, {0xbc,0x5c,0x72,0xf5},
+{0xd5,0x06,0x05,0xbe}, {0xde,0x08,0x0c,0xb3}, {0xc3,0x1a,0x17,0xa4}, {0xc8,0x14,0x1e,0xa9},
+{0xf9,0x3e,0x21,0x8a}, {0xf2,0x30,0x28,0x87}, {0xef,0x22,0x33,0x90}, {0xe4,0x2c,0x3a,0x9d},
+{0x3d,0x96,0xdd,0x06}, {0x36,0x98,0xd4,0x0b}, {0x2b,0x8a,0xcf,0x1c}, {0x20,0x84,0xc6,0x11},
+{0x11,0xae,0xf9,0x32}, {0x1a,0xa0,0xf0,0x3f}, {0x07,0xb2,0xeb,0x28}, {0x0c,0xbc,0xe2,0x25},
+{0x65,0xe6,0x95,0x6e}, {0x6e,0xe8,0x9c,0x63}, {0x73,0xfa,0x87,0x74}, {0x78,0xf4,0x8e,0x79},
+{0x49,0xde,0xb1,0x5a}, {0x42,0xd0,0xb8,0x57}, {0x5f,0xc2,0xa3,0x40}, {0x54,0xcc,0xaa,0x4d},
+{0xf7,0x41,0xec,0xda}, {0xfc,0x4f,0xe5,0xd7}, {0xe1,0x5d,0xfe,0xc0}, {0xea,0x53,0xf7,0xcd},
+{0xdb,0x79,0xc8,0xee}, {0xd0,0x77,0xc1,0xe3}, {0xcd,0x65,0xda,0xf4}, {0xc6,0x6b,0xd3,0xf9},
+{0xaf,0x31,0xa4,0xb2}, {0xa4,0x3f,0xad,0xbf}, {0xb9,0x2d,0xb6,0xa8}, {0xb2,0x23,0xbf,0xa5},
+{0x83,0x09,0x80,0x86}, {0x88,0x07,0x89,0x8b}, {0x95,0x15,0x92,0x9c}, {0x9e,0x1b,0x9b,0x91},
+{0x47,0xa1,0x7c,0x0a}, {0x4c,0xaf,0x75,0x07}, {0x51,0xbd,0x6e,0x10}, {0x5a,0xb3,0x67,0x1d},
+{0x6b,0x99,0x58,0x3e}, {0x60,0x97,0x51,0x33}, {0x7d,0x85,0x4a,0x24}, {0x76,0x8b,0x43,0x29},
+{0x1f,0xd1,0x34,0x62}, {0x14,0xdf,0x3d,0x6f}, {0x09,0xcd,0x26,0x78}, {0x02,0xc3,0x2f,0x75},
+{0x33,0xe9,0x10,0x56}, {0x38,0xe7,0x19,0x5b}, {0x25,0xf5,0x02,0x4c}, {0x2e,0xfb,0x0b,0x41},
+{0x8c,0x9a,0xd7,0x61}, {0x87,0x94,0xde,0x6c}, {0x9a,0x86,0xc5,0x7b}, {0x91,0x88,0xcc,0x76},
+{0xa0,0xa2,0xf3,0x55}, {0xab,0xac,0xfa,0x58}, {0xb6,0xbe,0xe1,0x4f}, {0xbd,0xb0,0xe8,0x42},
+{0xd4,0xea,0x9f,0x09}, {0xdf,0xe4,0x96,0x04}, {0xc2,0xf6,0x8d,0x13}, {0xc9,0xf8,0x84,0x1e},
+{0xf8,0xd2,0xbb,0x3d}, {0xf3,0xdc,0xb2,0x30}, {0xee,0xce,0xa9,0x27}, {0xe5,0xc0,0xa0,0x2a},
+{0x3c,0x7a,0x47,0xb1}, {0x37,0x74,0x4e,0xbc}, {0x2a,0x66,0x55,0xab}, {0x21,0x68,0x5c,0xa6},
+{0x10,0x42,0x63,0x85}, {0x1b,0x4c,0x6a,0x88}, {0x06,0x5e,0x71,0x9f}, {0x0d,0x50,0x78,0x92},
+{0x64,0x0a,0x0f,0xd9}, {0x6f,0x04,0x06,0xd4}, {0x72,0x16,0x1d,0xc3}, {0x79,0x18,0x14,0xce},
+{0x48,0x32,0x2b,0xed}, {0x43,0x3c,0x22,0xe0}, {0x5e,0x2e,0x39,0xf7}, {0x55,0x20,0x30,0xfa},
+{0x01,0xec,0x9a,0xb7}, {0x0a,0xe2,0x93,0xba}, {0x17,0xf0,0x88,0xad}, {0x1c,0xfe,0x81,0xa0},
+{0x2d,0xd4,0xbe,0x83}, {0x26,0xda,0xb7,0x8e}, {0x3b,0xc8,0xac,0x99}, {0x30,0xc6,0xa5,0x94},
+{0x59,0x9c,0xd2,0xdf}, {0x52,0x92,0xdb,0xd2}, {0x4f,0x80,0xc0,0xc5}, {0x44,0x8e,0xc9,0xc8},
+{0x75,0xa4,0xf6,0xeb}, {0x7e,0xaa,0xff,0xe6}, {0x63,0xb8,0xe4,0xf1}, {0x68,0xb6,0xed,0xfc},
+{0xb1,0x0c,0x0a,0x67}, {0xba,0x02,0x03,0x6a}, {0xa7,0x10,0x18,0x7d}, {0xac,0x1e,0x11,0x70},
+{0x9d,0x34,0x2e,0x53}, {0x96,0x3a,0x27,0x5e}, {0x8b,0x28,0x3c,0x49}, {0x80,0x26,0x35,0x44},
+{0xe9,0x7c,0x42,0x0f}, {0xe2,0x72,0x4b,0x02}, {0xff,0x60,0x50,0x15}, {0xf4,0x6e,0x59,0x18},
+{0xc5,0x44,0x66,0x3b}, {0xce,0x4a,0x6f,0x36}, {0xd3,0x58,0x74,0x21}, {0xd8,0x56,0x7d,0x2c},
+{0x7a,0x37,0xa1,0x0c}, {0x71,0x39,0xa8,0x01}, {0x6c,0x2b,0xb3,0x16}, {0x67,0x25,0xba,0x1b},
+{0x56,0x0f,0x85,0x38}, {0x5d,0x01,0x8c,0x35}, {0x40,0x13,0x97,0x22}, {0x4b,0x1d,0x9e,0x2f},
+{0x22,0x47,0xe9,0x64}, {0x29,0x49,0xe0,0x69}, {0x34,0x5b,0xfb,0x7e}, {0x3f,0x55,0xf2,0x73},
+{0x0e,0x7f,0xcd,0x50}, {0x05,0x71,0xc4,0x5d}, {0x18,0x63,0xdf,0x4a}, {0x13,0x6d,0xd6,0x47},
+{0xca,0xd7,0x31,0xdc}, {0xc1,0xd9,0x38,0xd1}, {0xdc,0xcb,0x23,0xc6}, {0xd7,0xc5,0x2a,0xcb},
+{0xe6,0xef,0x15,0xe8}, {0xed,0xe1,0x1c,0xe5}, {0xf0,0xf3,0x07,0xf2}, {0xfb,0xfd,0x0e,0xff},
+{0x92,0xa7,0x79,0xb4}, {0x99,0xa9,0x70,0xb9}, {0x84,0xbb,0x6b,0xae}, {0x8f,0xb5,0x62,0xa3},
+{0xbe,0x9f,0x5d,0x80}, {0xb5,0x91,0x54,0x8d}, {0xa8,0x83,0x4f,0x9a}, {0xa3,0x8d,0x46,0x97},
+};
+
+word8 U3[256][4] = {
+{0x00,0x00,0x00,0x00}, {0x0d,0x0b,0x0e,0x09}, {0x1a,0x16,0x1c,0x12}, {0x17,0x1d,0x12,0x1b},
+{0x34,0x2c,0x38,0x24}, {0x39,0x27,0x36,0x2d}, {0x2e,0x3a,0x24,0x36}, {0x23,0x31,0x2a,0x3f},
+{0x68,0x58,0x70,0x48}, {0x65,0x53,0x7e,0x41}, {0x72,0x4e,0x6c,0x5a}, {0x7f,0x45,0x62,0x53},
+{0x5c,0x74,0x48,0x6c}, {0x51,0x7f,0x46,0x65}, {0x46,0x62,0x54,0x7e}, {0x4b,0x69,0x5a,0x77},
+{0xd0,0xb0,0xe0,0x90}, {0xdd,0xbb,0xee,0x99}, {0xca,0xa6,0xfc,0x82}, {0xc7,0xad,0xf2,0x8b},
+{0xe4,0x9c,0xd8,0xb4}, {0xe9,0x97,0xd6,0xbd}, {0xfe,0x8a,0xc4,0xa6}, {0xf3,0x81,0xca,0xaf},
+{0xb8,0xe8,0x90,0xd8}, {0xb5,0xe3,0x9e,0xd1}, {0xa2,0xfe,0x8c,0xca}, {0xaf,0xf5,0x82,0xc3},
+{0x8c,0xc4,0xa8,0xfc}, {0x81,0xcf,0xa6,0xf5}, {0x96,0xd2,0xb4,0xee}, {0x9b,0xd9,0xba,0xe7},
+{0xbb,0x7b,0xdb,0x3b}, {0xb6,0x70,0xd5,0x32}, {0xa1,0x6d,0xc7,0x29}, {0xac,0x66,0xc9,0x20},
+{0x8f,0x57,0xe3,0x1f}, {0x82,0x5c,0xed,0x16}, {0x95,0x41,0xff,0x0d}, {0x98,0x4a,0xf1,0x04},
+{0xd3,0x23,0xab,0x73}, {0xde,0x28,0xa5,0x7a}, {0xc9,0x35,0xb7,0x61}, {0xc4,0x3e,0xb9,0x68},
+{0xe7,0x0f,0x93,0x57}, {0xea,0x04,0x9d,0x5e}, {0xfd,0x19,0x8f,0x45}, {0xf0,0x12,0x81,0x4c},
+{0x6b,0xcb,0x3b,0xab}, {0x66,0xc0,0x35,0xa2}, {0x71,0xdd,0x27,0xb9}, {0x7c,0xd6,0x29,0xb0},
+{0x5f,0xe7,0x03,0x8f}, {0x52,0xec,0x0d,0x86}, {0x45,0xf1,0x1f,0x9d}, {0x48,0xfa,0x11,0x94},
+{0x03,0x93,0x4b,0xe3}, {0x0e,0x98,0x45,0xea}, {0x19,0x85,0x57,0xf1}, {0x14,0x8e,0x59,0xf8},
+{0x37,0xbf,0x73,0xc7}, {0x3a,0xb4,0x7d,0xce}, {0x2d,0xa9,0x6f,0xd5}, {0x20,0xa2,0x61,0xdc},
+{0x6d,0xf6,0xad,0x76}, {0x60,0xfd,0xa3,0x7f}, {0x77,0xe0,0xb1,0x64}, {0x7a,0xeb,0xbf,0x6d},
+{0x59,0xda,0x95,0x52}, {0x54,0xd1,0x9b,0x5b}, {0x43,0xcc,0x89,0x40}, {0x4e,0xc7,0x87,0x49},
+{0x05,0xae,0xdd,0x3e}, {0x08,0xa5,0xd3,0x37}, {0x1f,0xb8,0xc1,0x2c}, {0x12,0xb3,0xcf,0x25},
+{0x31,0x82,0xe5,0x1a}, {0x3c,0x89,0xeb,0x13}, {0x2b,0x94,0xf9,0x08}, {0x26,0x9f,0xf7,0x01},
+{0xbd,0x46,0x4d,0xe6}, {0xb0,0x4d,0x43,0xef}, {0xa7,0x50,0x51,0xf4}, {0xaa,0x5b,0x5f,0xfd},
+{0x89,0x6a,0x75,0xc2}, {0x84,0x61,0x7b,0xcb}, {0x93,0x7c,0x69,0xd0}, {0x9e,0x77,0x67,0xd9},
+{0xd5,0x1e,0x3d,0xae}, {0xd8,0x15,0x33,0xa7}, {0xcf,0x08,0x21,0xbc}, {0xc2,0x03,0x2f,0xb5},
+{0xe1,0x32,0x05,0x8a}, {0xec,0x39,0x0b,0x83}, {0xfb,0x24,0x19,0x98}, {0xf6,0x2f,0x17,0x91},
+{0xd6,0x8d,0x76,0x4d}, {0xdb,0x86,0x78,0x44}, {0xcc,0x9b,0x6a,0x5f}, {0xc1,0x90,0x64,0x56},
+{0xe2,0xa1,0x4e,0x69}, {0xef,0xaa,0x40,0x60}, {0xf8,0xb7,0x52,0x7b}, {0xf5,0xbc,0x5c,0x72},
+{0xbe,0xd5,0x06,0x05}, {0xb3,0xde,0x08,0x0c}, {0xa4,0xc3,0x1a,0x17}, {0xa9,0xc8,0x14,0x1e},
+{0x8a,0xf9,0x3e,0x21}, {0x87,0xf2,0x30,0x28}, {0x90,0xef,0x22,0x33}, {0x9d,0xe4,0x2c,0x3a},
+{0x06,0x3d,0x96,0xdd}, {0x0b,0x36,0x98,0xd4}, {0x1c,0x2b,0x8a,0xcf}, {0x11,0x20,0x84,0xc6},
+{0x32,0x11,0xae,0xf9}, {0x3f,0x1a,0xa0,0xf0}, {0x28,0x07,0xb2,0xeb}, {0x25,0x0c,0xbc,0xe2},
+{0x6e,0x65,0xe6,0x95}, {0x63,0x6e,0xe8,0x9c}, {0x74,0x73,0xfa,0x87}, {0x79,0x78,0xf4,0x8e},
+{0x5a,0x49,0xde,0xb1}, {0x57,0x42,0xd0,0xb8}, {0x40,0x5f,0xc2,0xa3}, {0x4d,0x54,0xcc,0xaa},
+{0xda,0xf7,0x41,0xec}, {0xd7,0xfc,0x4f,0xe5}, {0xc0,0xe1,0x5d,0xfe}, {0xcd,0xea,0x53,0xf7},
+{0xee,0xdb,0x79,0xc8}, {0xe3,0xd0,0x77,0xc1}, {0xf4,0xcd,0x65,0xda}, {0xf9,0xc6,0x6b,0xd3},
+{0xb2,0xaf,0x31,0xa4}, {0xbf,0xa4,0x3f,0xad}, {0xa8,0xb9,0x2d,0xb6}, {0xa5,0xb2,0x23,0xbf},
+{0x86,0x83,0x09,0x80}, {0x8b,0x88,0x07,0x89}, {0x9c,0x95,0x15,0x92}, {0x91,0x9e,0x1b,0x9b},
+{0x0a,0x47,0xa1,0x7c}, {0x07,0x4c,0xaf,0x75}, {0x10,0x51,0xbd,0x6e}, {0x1d,0x5a,0xb3,0x67},
+{0x3e,0x6b,0x99,0x58}, {0x33,0x60,0x97,0x51}, {0x24,0x7d,0x85,0x4a}, {0x29,0x76,0x8b,0x43},
+{0x62,0x1f,0xd1,0x34}, {0x6f,0x14,0xdf,0x3d}, {0x78,0x09,0xcd,0x26}, {0x75,0x02,0xc3,0x2f},
+{0x56,0x33,0xe9,0x10}, {0x5b,0x38,0xe7,0x19}, {0x4c,0x25,0xf5,0x02}, {0x41,0x2e,0xfb,0x0b},
+{0x61,0x8c,0x9a,0xd7}, {0x6c,0x87,0x94,0xde}, {0x7b,0x9a,0x86,0xc5}, {0x76,0x91,0x88,0xcc},
+{0x55,0xa0,0xa2,0xf3}, {0x58,0xab,0xac,0xfa}, {0x4f,0xb6,0xbe,0xe1}, {0x42,0xbd,0xb0,0xe8},
+{0x09,0xd4,0xea,0x9f}, {0x04,0xdf,0xe4,0x96}, {0x13,0xc2,0xf6,0x8d}, {0x1e,0xc9,0xf8,0x84},
+{0x3d,0xf8,0xd2,0xbb}, {0x30,0xf3,0xdc,0xb2}, {0x27,0xee,0xce,0xa9}, {0x2a,0xe5,0xc0,0xa0},
+{0xb1,0x3c,0x7a,0x47}, {0xbc,0x37,0x74,0x4e}, {0xab,0x2a,0x66,0x55}, {0xa6,0x21,0x68,0x5c},
+{0x85,0x10,0x42,0x63}, {0x88,0x1b,0x4c,0x6a}, {0x9f,0x06,0x5e,0x71}, {0x92,0x0d,0x50,0x78},
+{0xd9,0x64,0x0a,0x0f}, {0xd4,0x6f,0x04,0x06}, {0xc3,0x72,0x16,0x1d}, {0xce,0x79,0x18,0x14},
+{0xed,0x48,0x32,0x2b}, {0xe0,0x43,0x3c,0x22}, {0xf7,0x5e,0x2e,0x39}, {0xfa,0x55,0x20,0x30},
+{0xb7,0x01,0xec,0x9a}, {0xba,0x0a,0xe2,0x93}, {0xad,0x17,0xf0,0x88}, {0xa0,0x1c,0xfe,0x81},
+{0x83,0x2d,0xd4,0xbe}, {0x8e,0x26,0xda,0xb7}, {0x99,0x3b,0xc8,0xac}, {0x94,0x30,0xc6,0xa5},
+{0xdf,0x59,0x9c,0xd2}, {0xd2,0x52,0x92,0xdb}, {0xc5,0x4f,0x80,0xc0}, {0xc8,0x44,0x8e,0xc9},
+{0xeb,0x75,0xa4,0xf6}, {0xe6,0x7e,0xaa,0xff}, {0xf1,0x63,0xb8,0xe4}, {0xfc,0x68,0xb6,0xed},
+{0x67,0xb1,0x0c,0x0a}, {0x6a,0xba,0x02,0x03}, {0x7d,0xa7,0x10,0x18}, {0x70,0xac,0x1e,0x11},
+{0x53,0x9d,0x34,0x2e}, {0x5e,0x96,0x3a,0x27}, {0x49,0x8b,0x28,0x3c}, {0x44,0x80,0x26,0x35},
+{0x0f,0xe9,0x7c,0x42}, {0x02,0xe2,0x72,0x4b}, {0x15,0xff,0x60,0x50}, {0x18,0xf4,0x6e,0x59},
+{0x3b,0xc5,0x44,0x66}, {0x36,0xce,0x4a,0x6f}, {0x21,0xd3,0x58,0x74}, {0x2c,0xd8,0x56,0x7d},
+{0x0c,0x7a,0x37,0xa1}, {0x01,0x71,0x39,0xa8}, {0x16,0x6c,0x2b,0xb3}, {0x1b,0x67,0x25,0xba},
+{0x38,0x56,0x0f,0x85}, {0x35,0x5d,0x01,0x8c}, {0x22,0x40,0x13,0x97}, {0x2f,0x4b,0x1d,0x9e},
+{0x64,0x22,0x47,0xe9}, {0x69,0x29,0x49,0xe0}, {0x7e,0x34,0x5b,0xfb}, {0x73,0x3f,0x55,0xf2},
+{0x50,0x0e,0x7f,0xcd}, {0x5d,0x05,0x71,0xc4}, {0x4a,0x18,0x63,0xdf}, {0x47,0x13,0x6d,0xd6},
+{0xdc,0xca,0xd7,0x31}, {0xd1,0xc1,0xd9,0x38}, {0xc6,0xdc,0xcb,0x23}, {0xcb,0xd7,0xc5,0x2a},
+{0xe8,0xe6,0xef,0x15}, {0xe5,0xed,0xe1,0x1c}, {0xf2,0xf0,0xf3,0x07}, {0xff,0xfb,0xfd,0x0e},
+{0xb4,0x92,0xa7,0x79}, {0xb9,0x99,0xa9,0x70}, {0xae,0x84,0xbb,0x6b}, {0xa3,0x8f,0xb5,0x62},
+{0x80,0xbe,0x9f,0x5d}, {0x8d,0xb5,0x91,0x54}, {0x9a,0xa8,0x83,0x4f}, {0x97,0xa3,0x8d,0x46},
+};
+
+word8 U4[256][4] = {
+{0x00,0x00,0x00,0x00}, {0x09,0x0d,0x0b,0x0e}, {0x12,0x1a,0x16,0x1c}, {0x1b,0x17,0x1d,0x12},
+{0x24,0x34,0x2c,0x38}, {0x2d,0x39,0x27,0x36}, {0x36,0x2e,0x3a,0x24}, {0x3f,0x23,0x31,0x2a},
+{0x48,0x68,0x58,0x70}, {0x41,0x65,0x53,0x7e}, {0x5a,0x72,0x4e,0x6c}, {0x53,0x7f,0x45,0x62},
+{0x6c,0x5c,0x74,0x48}, {0x65,0x51,0x7f,0x46}, {0x7e,0x46,0x62,0x54}, {0x77,0x4b,0x69,0x5a},
+{0x90,0xd0,0xb0,0xe0}, {0x99,0xdd,0xbb,0xee}, {0x82,0xca,0xa6,0xfc}, {0x8b,0xc7,0xad,0xf2},
+{0xb4,0xe4,0x9c,0xd8}, {0xbd,0xe9,0x97,0xd6}, {0xa6,0xfe,0x8a,0xc4}, {0xaf,0xf3,0x81,0xca},
+{0xd8,0xb8,0xe8,0x90}, {0xd1,0xb5,0xe3,0x9e}, {0xca,0xa2,0xfe,0x8c}, {0xc3,0xaf,0xf5,0x82},
+{0xfc,0x8c,0xc4,0xa8}, {0xf5,0x81,0xcf,0xa6}, {0xee,0x96,0xd2,0xb4}, {0xe7,0x9b,0xd9,0xba},
+{0x3b,0xbb,0x7b,0xdb}, {0x32,0xb6,0x70,0xd5}, {0x29,0xa1,0x6d,0xc7}, {0x20,0xac,0x66,0xc9},
+{0x1f,0x8f,0x57,0xe3}, {0x16,0x82,0x5c,0xed}, {0x0d,0x95,0x41,0xff}, {0x04,0x98,0x4a,0xf1},
+{0x73,0xd3,0x23,0xab}, {0x7a,0xde,0x28,0xa5}, {0x61,0xc9,0x35,0xb7}, {0x68,0xc4,0x3e,0xb9},
+{0x57,0xe7,0x0f,0x93}, {0x5e,0xea,0x04,0x9d}, {0x45,0xfd,0x19,0x8f}, {0x4c,0xf0,0x12,0x81},
+{0xab,0x6b,0xcb,0x3b}, {0xa2,0x66,0xc0,0x35}, {0xb9,0x71,0xdd,0x27}, {0xb0,0x7c,0xd6,0x29},
+{0x8f,0x5f,0xe7,0x03}, {0x86,0x52,0xec,0x0d}, {0x9d,0x45,0xf1,0x1f}, {0x94,0x48,0xfa,0x11},
+{0xe3,0x03,0x93,0x4b}, {0xea,0x0e,0x98,0x45}, {0xf1,0x19,0x85,0x57}, {0xf8,0x14,0x8e,0x59},
+{0xc7,0x37,0xbf,0x73}, {0xce,0x3a,0xb4,0x7d}, {0xd5,0x2d,0xa9,0x6f}, {0xdc,0x20,0xa2,0x61},
+{0x76,0x6d,0xf6,0xad}, {0x7f,0x60,0xfd,0xa3}, {0x64,0x77,0xe0,0xb1}, {0x6d,0x7a,0xeb,0xbf},
+{0x52,0x59,0xda,0x95}, {0x5b,0x54,0xd1,0x9b}, {0x40,0x43,0xcc,0x89}, {0x49,0x4e,0xc7,0x87},
+{0x3e,0x05,0xae,0xdd}, {0x37,0x08,0xa5,0xd3}, {0x2c,0x1f,0xb8,0xc1}, {0x25,0x12,0xb3,0xcf},
+{0x1a,0x31,0x82,0xe5}, {0x13,0x3c,0x89,0xeb}, {0x08,0x2b,0x94,0xf9}, {0x01,0x26,0x9f,0xf7},
+{0xe6,0xbd,0x46,0x4d}, {0xef,0xb0,0x4d,0x43}, {0xf4,0xa7,0x50,0x51}, {0xfd,0xaa,0x5b,0x5f},
+{0xc2,0x89,0x6a,0x75}, {0xcb,0x84,0x61,0x7b}, {0xd0,0x93,0x7c,0x69}, {0xd9,0x9e,0x77,0x67},
+{0xae,0xd5,0x1e,0x3d}, {0xa7,0xd8,0x15,0x33}, {0xbc,0xcf,0x08,0x21}, {0xb5,0xc2,0x03,0x2f},
+{0x8a,0xe1,0x32,0x05}, {0x83,0xec,0x39,0x0b}, {0x98,0xfb,0x24,0x19}, {0x91,0xf6,0x2f,0x17},
+{0x4d,0xd6,0x8d,0x76}, {0x44,0xdb,0x86,0x78}, {0x5f,0xcc,0x9b,0x6a}, {0x56,0xc1,0x90,0x64},
+{0x69,0xe2,0xa1,0x4e}, {0x60,0xef,0xaa,0x40}, {0x7b,0xf8,0xb7,0x52}, {0x72,0xf5,0xbc,0x5c},
+{0x05,0xbe,0xd5,0x06}, {0x0c,0xb3,0xde,0x08}, {0x17,0xa4,0xc3,0x1a}, {0x1e,0xa9,0xc8,0x14},
+{0x21,0x8a,0xf9,0x3e}, {0x28,0x87,0xf2,0x30}, {0x33,0x90,0xef,0x22}, {0x3a,0x9d,0xe4,0x2c},
+{0xdd,0x06,0x3d,0x96}, {0xd4,0x0b,0x36,0x98}, {0xcf,0x1c,0x2b,0x8a}, {0xc6,0x11,0x20,0x84},
+{0xf9,0x32,0x11,0xae}, {0xf0,0x3f,0x1a,0xa0}, {0xeb,0x28,0x07,0xb2}, {0xe2,0x25,0x0c,0xbc},
+{0x95,0x6e,0x65,0xe6}, {0x9c,0x63,0x6e,0xe8}, {0x87,0x74,0x73,0xfa}, {0x8e,0x79,0x78,0xf4},
+{0xb1,0x5a,0x49,0xde}, {0xb8,0x57,0x42,0xd0}, {0xa3,0x40,0x5f,0xc2}, {0xaa,0x4d,0x54,0xcc},
+{0xec,0xda,0xf7,0x41}, {0xe5,0xd7,0xfc,0x4f}, {0xfe,0xc0,0xe1,0x5d}, {0xf7,0xcd,0xea,0x53},
+{0xc8,0xee,0xdb,0x79}, {0xc1,0xe3,0xd0,0x77}, {0xda,0xf4,0xcd,0x65}, {0xd3,0xf9,0xc6,0x6b},
+{0xa4,0xb2,0xaf,0x31}, {0xad,0xbf,0xa4,0x3f}, {0xb6,0xa8,0xb9,0x2d}, {0xbf,0xa5,0xb2,0x23},
+{0x80,0x86,0x83,0x09}, {0x89,0x8b,0x88,0x07}, {0x92,0x9c,0x95,0x15}, {0x9b,0x91,0x9e,0x1b},
+{0x7c,0x0a,0x47,0xa1}, {0x75,0x07,0x4c,0xaf}, {0x6e,0x10,0x51,0xbd}, {0x67,0x1d,0x5a,0xb3},
+{0x58,0x3e,0x6b,0x99}, {0x51,0x33,0x60,0x97}, {0x4a,0x24,0x7d,0x85}, {0x43,0x29,0x76,0x8b},
+{0x34,0x62,0x1f,0xd1}, {0x3d,0x6f,0x14,0xdf}, {0x26,0x78,0x09,0xcd}, {0x2f,0x75,0x02,0xc3},
+{0x10,0x56,0x33,0xe9}, {0x19,0x5b,0x38,0xe7}, {0x02,0x4c,0x25,0xf5}, {0x0b,0x41,0x2e,0xfb},
+{0xd7,0x61,0x8c,0x9a}, {0xde,0x6c,0x87,0x94}, {0xc5,0x7b,0x9a,0x86}, {0xcc,0x76,0x91,0x88},
+{0xf3,0x55,0xa0,0xa2}, {0xfa,0x58,0xab,0xac}, {0xe1,0x4f,0xb6,0xbe}, {0xe8,0x42,0xbd,0xb0},
+{0x9f,0x09,0xd4,0xea}, {0x96,0x04,0xdf,0xe4}, {0x8d,0x13,0xc2,0xf6}, {0x84,0x1e,0xc9,0xf8},
+{0xbb,0x3d,0xf8,0xd2}, {0xb2,0x30,0xf3,0xdc}, {0xa9,0x27,0xee,0xce}, {0xa0,0x2a,0xe5,0xc0},
+{0x47,0xb1,0x3c,0x7a}, {0x4e,0xbc,0x37,0x74}, {0x55,0xab,0x2a,0x66}, {0x5c,0xa6,0x21,0x68},
+{0x63,0x85,0x10,0x42}, {0x6a,0x88,0x1b,0x4c}, {0x71,0x9f,0x06,0x5e}, {0x78,0x92,0x0d,0x50},
+{0x0f,0xd9,0x64,0x0a}, {0x06,0xd4,0x6f,0x04}, {0x1d,0xc3,0x72,0x16}, {0x14,0xce,0x79,0x18},
+{0x2b,0xed,0x48,0x32}, {0x22,0xe0,0x43,0x3c}, {0x39,0xf7,0x5e,0x2e}, {0x30,0xfa,0x55,0x20},
+{0x9a,0xb7,0x01,0xec}, {0x93,0xba,0x0a,0xe2}, {0x88,0xad,0x17,0xf0}, {0x81,0xa0,0x1c,0xfe},
+{0xbe,0x83,0x2d,0xd4}, {0xb7,0x8e,0x26,0xda}, {0xac,0x99,0x3b,0xc8}, {0xa5,0x94,0x30,0xc6},
+{0xd2,0xdf,0x59,0x9c}, {0xdb,0xd2,0x52,0x92}, {0xc0,0xc5,0x4f,0x80}, {0xc9,0xc8,0x44,0x8e},
+{0xf6,0xeb,0x75,0xa4}, {0xff,0xe6,0x7e,0xaa}, {0xe4,0xf1,0x63,0xb8}, {0xed,0xfc,0x68,0xb6},
+{0x0a,0x67,0xb1,0x0c}, {0x03,0x6a,0xba,0x02}, {0x18,0x7d,0xa7,0x10}, {0x11,0x70,0xac,0x1e},
+{0x2e,0x53,0x9d,0x34}, {0x27,0x5e,0x96,0x3a}, {0x3c,0x49,0x8b,0x28}, {0x35,0x44,0x80,0x26},
+{0x42,0x0f,0xe9,0x7c}, {0x4b,0x02,0xe2,0x72}, {0x50,0x15,0xff,0x60}, {0x59,0x18,0xf4,0x6e},
+{0x66,0x3b,0xc5,0x44}, {0x6f,0x36,0xce,0x4a}, {0x74,0x21,0xd3,0x58}, {0x7d,0x2c,0xd8,0x56},
+{0xa1,0x0c,0x7a,0x37}, {0xa8,0x01,0x71,0x39}, {0xb3,0x16,0x6c,0x2b}, {0xba,0x1b,0x67,0x25},
+{0x85,0x38,0x56,0x0f}, {0x8c,0x35,0x5d,0x01}, {0x97,0x22,0x40,0x13}, {0x9e,0x2f,0x4b,0x1d},
+{0xe9,0x64,0x22,0x47}, {0xe0,0x69,0x29,0x49}, {0xfb,0x7e,0x34,0x5b}, {0xf2,0x73,0x3f,0x55},
+{0xcd,0x50,0x0e,0x7f}, {0xc4,0x5d,0x05,0x71}, {0xdf,0x4a,0x18,0x63}, {0xd6,0x47,0x13,0x6d},
+{0x31,0xdc,0xca,0xd7}, {0x38,0xd1,0xc1,0xd9}, {0x23,0xc6,0xdc,0xcb}, {0x2a,0xcb,0xd7,0xc5},
+{0x15,0xe8,0xe6,0xef}, {0x1c,0xe5,0xed,0xe1}, {0x07,0xf2,0xf0,0xf3}, {0x0e,0xff,0xfb,0xfd},
+{0x79,0xb4,0x92,0xa7}, {0x70,0xb9,0x99,0xa9}, {0x6b,0xae,0x84,0xbb}, {0x62,0xa3,0x8f,0xb5},
+{0x5d,0x80,0xbe,0x9f}, {0x54,0x8d,0xb5,0x91}, {0x4f,0x9a,0xa8,0x83}, {0x46,0x97,0xa3,0x8d},
+};
+
+word32 rcon[30] = { 
+  0x01,0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
+};
+
+/*
+ * $PchId: boxes.dat,v 1.2 2001/01/10 21:55:17 philip Exp $
+ */
Index: /trunk/minix/drivers/random/aes/rijndael-alg.h
===================================================================
--- /trunk/minix/drivers/random/aes/rijndael-alg.h	(revision 9)
+++ /trunk/minix/drivers/random/aes/rijndael-alg.h	(revision 9)
@@ -0,0 +1,36 @@
+/*
+ * rijndael-alg.h   v2.4   April '2000
+ *
+ * Optimised ANSI C code
+ */
+
+#ifndef __RIJNDAEL_ALG_H
+#define __RIJNDAEL_ALG_H
+
+#define MAXKC			(256/32)
+#define MAXROUNDS		14
+
+/* Fix me: something generic based on inttypes.h */
+#include "word_i386.h"
+
+int rijndael_KeySched(word8 k[MAXKC][4], word8 rk[MAXROUNDS+1][4][4], int ROUNDS);
+
+int rijndael_KeyEncToDec(word8 W[MAXROUNDS+1][4][4], int ROUNDS);
+
+int rijndael_Encrypt(const void *a, void *b, word8 rk[MAXROUNDS+1][4][4], int ROUNDS);
+
+#ifdef INTERMEDIATE_VALUE_KAT
+int rijndaelEncryptRound(word8 a[4][4], word8 rk[MAXROUNDS+1][4][4], int ROUNDS, int rounds);
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+int rijndael_Decrypt(const void *a, void *b, word8 rk[MAXROUNDS+1][4][4], int ROUNDS);
+
+#ifdef INTERMEDIATE_VALUE_KAT
+int rijndaelDecryptRound(word8 a[4][4], word8 rk[MAXROUNDS+1][4][4], int ROUNDS, int rounds);
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+#endif /* __RIJNDAEL_ALG_H */
+
+/*
+ * $PchId: rijndael-alg.h,v 1.3 2003/09/29 09:19:17 philip Exp $
+ */
Index: /trunk/minix/drivers/random/aes/rijndael-api.h
===================================================================
--- /trunk/minix/drivers/random/aes/rijndael-api.h	(revision 9)
+++ /trunk/minix/drivers/random/aes/rijndael-api.h	(revision 9)
@@ -0,0 +1,78 @@
+/*	rijndael-api.h - Rijndael encryption programming interface.
+ *							Author: Kees J. Bot
+ *								3 Nov 2000
+ * Heavily based on the original API code by Antoon Bosselaers,
+ * Vincent Rijmen, and Paulo Barreto, but with a different interface.
+ *
+ * This code (.h and .c) is in the public domain.
+ */
+
+#ifndef __RIJNDAEL_API_H
+#define __RIJNDAEL_API_H
+
+/* Error codes. */
+#define RD_BAD_KEY_MAT	    -1	/* Key material not of correct length */
+#define RD_BAD_BLOCK_LENGTH -2	/* Data is not a block multiple */
+#define RD_BAD_DATA	    -3	/* Data contents are invalid (bad padding?) */
+
+/* Key information. */
+#define RD_KEY_HEX	    -1	/* Key is in hex (otherwise octet length) */
+#define RD_MAXROUNDS	    14	/* Max number of encryption rounds. */
+
+typedef struct {
+	int	rounds;		/* Key-length-dependent number of rounds */
+	unsigned char encsched[RD_MAXROUNDS+1][4][4];	/* Encr key schedule */
+	unsigned char decsched[RD_MAXROUNDS+1][4][4];	/* Decr key schedule */
+} rd_keyinstance;
+
+/* Function prototypes. */
+
+int rijndael_makekey(rd_keyinstance *_key,
+	size_t _keylen, const void *_keymaterial);
+
+ssize_t rijndael_ecb_encrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_dummyIV);
+
+ssize_t rijndael_ecb_decrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_dummyIV);
+
+ssize_t rijndael_cbc_encrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_IV);
+
+ssize_t rijndael_cbc_decrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_IV);
+
+ssize_t rijndael_cfb1_encrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_IV);
+
+ssize_t rijndael_cfb1_decrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_IV);
+
+ssize_t rijndael_cfb8_encrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_IV);
+
+ssize_t rijndael_cfb8_decrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_IV);
+
+ssize_t rijndael_pad(void *_input, size_t _length);
+
+ssize_t rijndael_unpad(const void *_input, size_t _length);
+
+typedef ssize_t (*rd_function)(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_IV);
+
+#ifdef INTERMEDIATE_VALUE_KAT
+
+void cipherEncryptUpdateRounds(rd_keyinstance *key,
+	const void *input, void *output, int rounds);
+
+void cipherDecryptUpdateRounds(rd_keyinstance *key,
+	const void *input, void *output, int rounds);
+
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+#endif /* __RIJNDAEL_API_H */
+
+/*
+ * $PchId: rijndael-api.h,v 1.2 2001/01/10 22:02:21 philip Exp $
+ */
Index: /trunk/minix/drivers/random/aes/rijndael.h
===================================================================
--- /trunk/minix/drivers/random/aes/rijndael.h	(revision 9)
+++ /trunk/minix/drivers/random/aes/rijndael.h	(revision 9)
@@ -0,0 +1,80 @@
+/*	rijndael-api.h - Rijndael encryption programming interface.
+ *							Author: Kees J. Bot
+ *								3 Nov 2000
+ * Heavily based on the original API code by Antoon Bosselaers,
+ * Vincent Rijmen, and Paulo Barreto, but with a different interface.
+ *
+ * This code (.h and .c) is in the public domain.
+ */
+
+#ifndef _CRYPTO__RIJNDAEL_H
+#define _CRYPTO__RIJNDAEL_H
+
+/* Error codes. */
+#define RD_BAD_KEY_MAT	    -1	/* Key material not of correct length */
+#define RD_BAD_BLOCK_LENGTH -2	/* Data is not a block multiple */
+#define RD_BAD_DATA	    -3	/* Data contents are invalid (bad padding?) */
+
+/* Key information. */
+#define RD_KEY_HEX	    -1	/* Key is in hex (otherwise octet length) */
+#define RD_MAXROUNDS	    14	/* Max number of encryption rounds. */
+
+typedef struct {
+	int	rounds;		/* Key-length-dependent number of rounds */
+	unsigned char encsched[RD_MAXROUNDS+1][4][4];	/* Encr key schedule */
+	unsigned char decsched[RD_MAXROUNDS+1][4][4];	/* Decr key schedule */
+} rd_keyinstance;
+
+#define AES_BLOCKSIZE	16
+
+/* Function prototypes. */
+
+int rijndael_makekey(rd_keyinstance *_key,
+	size_t _keylen, const void *_keymaterial);
+
+ssize_t rijndael_ecb_encrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_dummyIV);
+
+ssize_t rijndael_ecb_decrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_dummyIV);
+
+ssize_t rijndael_cbc_encrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_IV);
+
+ssize_t rijndael_cbc_decrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_IV);
+
+ssize_t rijndael_cfb1_encrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_IV);
+
+ssize_t rijndael_cfb1_decrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_IV);
+
+ssize_t rijndael_cfb8_encrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_IV);
+
+ssize_t rijndael_cfb8_decrypt(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_IV);
+
+ssize_t rijndael_pad(void *_input, size_t _length);
+
+ssize_t rijndael_unpad(const void *_input, size_t _length);
+
+typedef ssize_t (*rd_function)(rd_keyinstance *_key,
+	const void *_input, void *_output, size_t _length, void *_IV);
+
+#ifdef INTERMEDIATE_VALUE_KAT
+
+void cipherEncryptUpdateRounds(rd_keyinstance *key,
+	const void *input, void *output, int rounds);
+
+void cipherDecryptUpdateRounds(rd_keyinstance *key,
+	const void *input, void *output, int rounds);
+
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+#endif /* _CRYPTO__RIJNDAEL_H */
+
+/*
+ * $PchId: rijndael.h,v 1.1 2005/06/01 10:13:45 philip Exp $
+ */
Index: /trunk/minix/drivers/random/aes/rijndael_alg.c
===================================================================
--- /trunk/minix/drivers/random/aes/rijndael_alg.c	(revision 9)
+++ /trunk/minix/drivers/random/aes/rijndael_alg.c	(revision 9)
@@ -0,0 +1,449 @@
+/*
+ * rijndael-alg.c   v2.4   April '2000
+ *
+ * Optimised ANSI C code
+ *
+ * authors: v1.0: Antoon Bosselaers
+ *          v2.0: Vincent Rijmen, K.U.Leuven
+ *          v2.3: Paulo Barreto
+ *          v2.4: Vincent Rijmen, K.U.Leuven
+ *
+ * This code is placed in the public domain.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "rijndael-alg.h"
+
+#include "boxes.dat"
+
+int rijndael_KeySched(word8 k[MAXKC][4], word8 W[MAXROUNDS+1][4][4], int ROUNDS) {
+	/* Calculate the necessary round keys
+	 * The number of calculations depends on keyBits and blockBits
+	 */ 
+	int j, r, t, rconpointer = 0;
+	word8 tk[MAXKC][4];
+	int KC = ROUNDS - 6;
+
+	for (j = KC-1; j >= 0; j--) {
+		*((word32*)tk[j]) = *((word32*)k[j]);
+	}
+	r = 0;
+	t = 0;
+	/* copy values into round key array */
+	for (j = 0; (j < KC) && (r < ROUNDS + 1); ) {
+		for (; (j < KC) && (t < 4); j++, t++) {
+			*((word32*)W[r][t]) = *((word32*)tk[j]);
+		}
+		if (t == 4) {
+			r++;
+			t = 0;
+		}
+	}
+		
+	while (r < ROUNDS + 1) { /* while not enough round key material calculated */
+		/* calculate new values */
+		tk[0][0] ^= S[tk[KC-1][1]];
+		tk[0][1] ^= S[tk[KC-1][2]];
+		tk[0][2] ^= S[tk[KC-1][3]];
+		tk[0][3] ^= S[tk[KC-1][0]];
+		tk[0][0] ^= rcon[rconpointer++];
+
+		if (KC != 8) {
+			for (j = 1; j < KC; j++) {
+				*((word32*)tk[j]) ^= *((word32*)tk[j-1]);
+			}
+		} else {
+			for (j = 1; j < KC/2; j++) {
+				*((word32*)tk[j]) ^= *((word32*)tk[j-1]);
+			}
+			tk[KC/2][0] ^= S[tk[KC/2 - 1][0]];
+			tk[KC/2][1] ^= S[tk[KC/2 - 1][1]];
+			tk[KC/2][2] ^= S[tk[KC/2 - 1][2]];
+			tk[KC/2][3] ^= S[tk[KC/2 - 1][3]];
+			for (j = KC/2 + 1; j < KC; j++) {
+				*((word32*)tk[j]) ^= *((word32*)tk[j-1]);
+			}
+		}
+		/* copy values into round key array */
+		for (j = 0; (j < KC) && (r < ROUNDS + 1); ) {
+			for (; (j < KC) && (t < 4); j++, t++) {
+				*((word32*)W[r][t]) = *((word32*)tk[j]);
+			}
+			if (t == 4) {
+				r++;
+				t = 0;
+			}
+		}
+	}		
+	return 0;
+}
+
+int rijndael_KeyEncToDec(word8 W[MAXROUNDS+1][4][4], int ROUNDS) {
+	int r;
+	word8 *w;
+
+	for (r = 1; r < ROUNDS; r++) {
+		w = W[r][0];
+		*((word32*)w) =
+			  *((word32*)U1[w[0]])
+			^ *((word32*)U2[w[1]])
+			^ *((word32*)U3[w[2]])
+			^ *((word32*)U4[w[3]]);
+
+		w = W[r][1];
+		*((word32*)w) =
+			  *((word32*)U1[w[0]])
+			^ *((word32*)U2[w[1]])
+			^ *((word32*)U3[w[2]])
+			^ *((word32*)U4[w[3]]);
+
+		w = W[r][2];
+		*((word32*)w) =
+			  *((word32*)U1[w[0]])
+			^ *((word32*)U2[w[1]])
+			^ *((word32*)U3[w[2]])
+			^ *((word32*)U4[w[3]]);
+
+		w = W[r][3];
+		*((word32*)w) =
+			  *((word32*)U1[w[0]])
+			^ *((word32*)U2[w[1]])
+			^ *((word32*)U3[w[2]])
+			^ *((word32*)U4[w[3]]);
+	}
+	return 0;
+}	
+
+/**
+ * Encrypt a single block. 
+ */
+int rijndael_Encrypt(const void *va, void *vb, word8 rk[MAXROUNDS+1][4][4], int ROUNDS) {
+	const word8 *a = va;
+	word8 *b = vb;
+	int r;
+	word8 temp[4][4];
+
+    *((word32*)temp[0]) = *((word32*)(a   )) ^ *((word32*)rk[0][0]);
+    *((word32*)temp[1]) = *((word32*)(a+ 4)) ^ *((word32*)rk[0][1]);
+    *((word32*)temp[2]) = *((word32*)(a+ 8)) ^ *((word32*)rk[0][2]);
+    *((word32*)temp[3]) = *((word32*)(a+12)) ^ *((word32*)rk[0][3]);
+    *((word32*)(b    )) = *((word32*)T1[temp[0][0]])
+						^ *((word32*)T2[temp[1][1]])
+						^ *((word32*)T3[temp[2][2]]) 
+						^ *((word32*)T4[temp[3][3]]);
+    *((word32*)(b + 4)) = *((word32*)T1[temp[1][0]])
+						^ *((word32*)T2[temp[2][1]])
+						^ *((word32*)T3[temp[3][2]]) 
+						^ *((word32*)T4[temp[0][3]]);
+    *((word32*)(b + 8)) = *((word32*)T1[temp[2][0]])
+						^ *((word32*)T2[temp[3][1]])
+						^ *((word32*)T3[temp[0][2]]) 
+						^ *((word32*)T4[temp[1][3]]);
+    *((word32*)(b +12)) = *((word32*)T1[temp[3][0]])
+						^ *((word32*)T2[temp[0][1]])
+						^ *((word32*)T3[temp[1][2]]) 
+						^ *((word32*)T4[temp[2][3]]);
+	for (r = 1; r < ROUNDS-1; r++) {
+		*((word32*)temp[0]) = *((word32*)(b   )) ^ *((word32*)rk[r][0]);
+		*((word32*)temp[1]) = *((word32*)(b+ 4)) ^ *((word32*)rk[r][1]);
+		*((word32*)temp[2]) = *((word32*)(b+ 8)) ^ *((word32*)rk[r][2]);
+		*((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[r][3]);
+
+		*((word32*)(b    )) = *((word32*)T1[temp[0][0]])
+							^ *((word32*)T2[temp[1][1]])
+							^ *((word32*)T3[temp[2][2]]) 
+							^ *((word32*)T4[temp[3][3]]);
+		*((word32*)(b + 4)) = *((word32*)T1[temp[1][0]])
+							^ *((word32*)T2[temp[2][1]])
+							^ *((word32*)T3[temp[3][2]]) 
+							^ *((word32*)T4[temp[0][3]]);
+		*((word32*)(b + 8)) = *((word32*)T1[temp[2][0]])
+							^ *((word32*)T2[temp[3][1]])
+							^ *((word32*)T3[temp[0][2]]) 
+							^ *((word32*)T4[temp[1][3]]);
+		*((word32*)(b +12)) = *((word32*)T1[temp[3][0]])
+							^ *((word32*)T2[temp[0][1]])
+							^ *((word32*)T3[temp[1][2]]) 
+							^ *((word32*)T4[temp[2][3]]);
+	}
+	/* last round is special */   
+	*((word32*)temp[0]) = *((word32*)(b   )) ^ *((word32*)rk[ROUNDS-1][0]);
+	*((word32*)temp[1]) = *((word32*)(b+ 4)) ^ *((word32*)rk[ROUNDS-1][1]);
+	*((word32*)temp[2]) = *((word32*)(b+ 8)) ^ *((word32*)rk[ROUNDS-1][2]);
+	*((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[ROUNDS-1][3]);
+	b[ 0] = T1[temp[0][0]][1];
+	b[ 1] = T1[temp[1][1]][1];
+	b[ 2] = T1[temp[2][2]][1];
+	b[ 3] = T1[temp[3][3]][1];
+	b[ 4] = T1[temp[1][0]][1];
+	b[ 5] = T1[temp[2][1]][1];
+	b[ 6] = T1[temp[3][2]][1];
+	b[ 7] = T1[temp[0][3]][1];
+	b[ 8] = T1[temp[2][0]][1];
+	b[ 9] = T1[temp[3][1]][1];
+	b[10] = T1[temp[0][2]][1];
+	b[11] = T1[temp[1][3]][1];
+	b[12] = T1[temp[3][0]][1];
+	b[13] = T1[temp[0][1]][1];
+	b[14] = T1[temp[1][2]][1];
+	b[15] = T1[temp[2][3]][1];
+	*((word32*)(b   )) ^= *((word32*)rk[ROUNDS][0]);
+	*((word32*)(b+ 4)) ^= *((word32*)rk[ROUNDS][1]);
+	*((word32*)(b+ 8)) ^= *((word32*)rk[ROUNDS][2]);
+	*((word32*)(b+12)) ^= *((word32*)rk[ROUNDS][3]);
+
+	return 0;
+}
+
+#ifdef INTERMEDIATE_VALUE_KAT
+/**
+ * Encrypt only a certain number of rounds.
+ * Only used in the Intermediate Value Known Answer Test.
+ */
+int rijndaelEncryptRound(word8 a[4][4], word8 rk[MAXROUNDS+1][4][4], int ROUNDS, int rounds) {
+	int r;
+	word8 temp[4][4];
+
+	/* make number of rounds sane */
+	if (rounds > ROUNDS) {
+		rounds = ROUNDS;
+	}
+
+	*((word32*)a[0]) = *((word32*)a[0]) ^ *((word32*)rk[0][0]);
+	*((word32*)a[1]) = *((word32*)a[1]) ^ *((word32*)rk[0][1]);
+	*((word32*)a[2]) = *((word32*)a[2]) ^ *((word32*)rk[0][2]);
+	*((word32*)a[3]) = *((word32*)a[3]) ^ *((word32*)rk[0][3]);
+
+	for (r = 1; (r <= rounds) && (r < ROUNDS); r++) {
+		*((word32*)temp[0]) = *((word32*)T1[a[0][0]])
+           ^ *((word32*)T2[a[1][1]])
+           ^ *((word32*)T3[a[2][2]]) 
+           ^ *((word32*)T4[a[3][3]]);
+		*((word32*)temp[1]) = *((word32*)T1[a[1][0]])
+           ^ *((word32*)T2[a[2][1]])
+           ^ *((word32*)T3[a[3][2]]) 
+           ^ *((word32*)T4[a[0][3]]);
+		*((word32*)temp[2]) = *((word32*)T1[a[2][0]])
+           ^ *((word32*)T2[a[3][1]])
+           ^ *((word32*)T3[a[0][2]]) 
+           ^ *((word32*)T4[a[1][3]]);
+		*((word32*)temp[3]) = *((word32*)T1[a[3][0]])
+           ^ *((word32*)T2[a[0][1]])
+           ^ *((word32*)T3[a[1][2]]) 
+           ^ *((word32*)T4[a[2][3]]);
+		*((word32*)a[0]) = *((word32*)temp[0]) ^ *((word32*)rk[r][0]);
+		*((word32*)a[1]) = *((word32*)temp[1]) ^ *((word32*)rk[r][1]);
+		*((word32*)a[2]) = *((word32*)temp[2]) ^ *((word32*)rk[r][2]);
+		*((word32*)a[3]) = *((word32*)temp[3]) ^ *((word32*)rk[r][3]);
+	}
+	if (rounds == ROUNDS) {
+	   	/* last round is special */   
+	   	temp[0][0] = T1[a[0][0]][1];
+	   	temp[0][1] = T1[a[1][1]][1];
+	   	temp[0][2] = T1[a[2][2]][1]; 
+	   	temp[0][3] = T1[a[3][3]][1];
+	   	temp[1][0] = T1[a[1][0]][1];
+	   	temp[1][1] = T1[a[2][1]][1];
+	   	temp[1][2] = T1[a[3][2]][1]; 
+	   	temp[1][3] = T1[a[0][3]][1];
+	   	temp[2][0] = T1[a[2][0]][1];
+	   	temp[2][1] = T1[a[3][1]][1];
+	   	temp[2][2] = T1[a[0][2]][1]; 
+	   	temp[2][3] = T1[a[1][3]][1];
+	   	temp[3][0] = T1[a[3][0]][1];
+	   	temp[3][1] = T1[a[0][1]][1];
+	   	temp[3][2] = T1[a[1][2]][1]; 
+	   	temp[3][3] = T1[a[2][3]][1];
+		*((word32*)a[0]) = *((word32*)temp[0]) ^ *((word32*)rk[ROUNDS][0]);
+		*((word32*)a[1]) = *((word32*)temp[1]) ^ *((word32*)rk[ROUNDS][1]);
+		*((word32*)a[2]) = *((word32*)temp[2]) ^ *((word32*)rk[ROUNDS][2]);
+		*((word32*)a[3]) = *((word32*)temp[3]) ^ *((word32*)rk[ROUNDS][3]);
+	}
+
+	return 0;
+}   
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+/**
+ * Decrypt a single block.
+ */
+int rijndael_Decrypt(const void *va, void *vb, word8 rk[MAXROUNDS+1][4][4], int ROUNDS) {
+	const word8 *a = va;
+	word8 *b = vb;
+	int r;
+	word8 temp[4][4];
+	
+    *((word32*)temp[0]) = *((word32*)(a   )) ^ *((word32*)rk[ROUNDS][0]);
+    *((word32*)temp[1]) = *((word32*)(a+ 4)) ^ *((word32*)rk[ROUNDS][1]);
+    *((word32*)temp[2]) = *((word32*)(a+ 8)) ^ *((word32*)rk[ROUNDS][2]);
+    *((word32*)temp[3]) = *((word32*)(a+12)) ^ *((word32*)rk[ROUNDS][3]);
+
+    *((word32*)(b   )) = *((word32*)T5[temp[0][0]])
+           ^ *((word32*)T6[temp[3][1]])
+           ^ *((word32*)T7[temp[2][2]]) 
+           ^ *((word32*)T8[temp[1][3]]);
+	*((word32*)(b+ 4)) = *((word32*)T5[temp[1][0]])
+           ^ *((word32*)T6[temp[0][1]])
+           ^ *((word32*)T7[temp[3][2]]) 
+           ^ *((word32*)T8[temp[2][3]]);
+	*((word32*)(b+ 8)) = *((word32*)T5[temp[2][0]])
+           ^ *((word32*)T6[temp[1][1]])
+           ^ *((word32*)T7[temp[0][2]]) 
+           ^ *((word32*)T8[temp[3][3]]);
+	*((word32*)(b+12)) = *((word32*)T5[temp[3][0]])
+           ^ *((word32*)T6[temp[2][1]])
+           ^ *((word32*)T7[temp[1][2]]) 
+           ^ *((word32*)T8[temp[0][3]]);
+	for (r = ROUNDS-1; r > 1; r--) {
+		*((word32*)temp[0]) = *((word32*)(b   )) ^ *((word32*)rk[r][0]);
+		*((word32*)temp[1]) = *((word32*)(b+ 4)) ^ *((word32*)rk[r][1]);
+		*((word32*)temp[2]) = *((word32*)(b+ 8)) ^ *((word32*)rk[r][2]);
+		*((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[r][3]);
+		*((word32*)(b   )) = *((word32*)T5[temp[0][0]])
+           ^ *((word32*)T6[temp[3][1]])
+           ^ *((word32*)T7[temp[2][2]]) 
+           ^ *((word32*)T8[temp[1][3]]);
+		*((word32*)(b+ 4)) = *((word32*)T5[temp[1][0]])
+           ^ *((word32*)T6[temp[0][1]])
+           ^ *((word32*)T7[temp[3][2]]) 
+           ^ *((word32*)T8[temp[2][3]]);
+		*((word32*)(b+ 8)) = *((word32*)T5[temp[2][0]])
+           ^ *((word32*)T6[temp[1][1]])
+           ^ *((word32*)T7[temp[0][2]]) 
+           ^ *((word32*)T8[temp[3][3]]);
+		*((word32*)(b+12)) = *((word32*)T5[temp[3][0]])
+           ^ *((word32*)T6[temp[2][1]])
+           ^ *((word32*)T7[temp[1][2]]) 
+           ^ *((word32*)T8[temp[0][3]]);
+	}
+	/* last round is special */   
+	*((word32*)temp[0]) = *((word32*)(b   )) ^ *((word32*)rk[1][0]);
+	*((word32*)temp[1]) = *((word32*)(b+ 4)) ^ *((word32*)rk[1][1]);
+	*((word32*)temp[2]) = *((word32*)(b+ 8)) ^ *((word32*)rk[1][2]);
+	*((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[1][3]);
+	b[ 0] = S5[temp[0][0]];
+	b[ 1] = S5[temp[3][1]];
+	b[ 2] = S5[temp[2][2]];
+	b[ 3] = S5[temp[1][3]];
+	b[ 4] = S5[temp[1][0]];
+	b[ 5] = S5[temp[0][1]];
+	b[ 6] = S5[temp[3][2]];
+	b[ 7] = S5[temp[2][3]];
+	b[ 8] = S5[temp[2][0]];
+	b[ 9] = S5[temp[1][1]];
+	b[10] = S5[temp[0][2]];
+	b[11] = S5[temp[3][3]];
+	b[12] = S5[temp[3][0]];
+	b[13] = S5[temp[2][1]];
+	b[14] = S5[temp[1][2]];
+	b[15] = S5[temp[0][3]];
+	*((word32*)(b   )) ^= *((word32*)rk[0][0]);
+	*((word32*)(b+ 4)) ^= *((word32*)rk[0][1]);
+	*((word32*)(b+ 8)) ^= *((word32*)rk[0][2]);
+	*((word32*)(b+12)) ^= *((word32*)rk[0][3]);
+
+	return 0;
+}
+
+#ifdef INTERMEDIATE_VALUE_KAT
+/**
+ * Decrypt only a certain number of rounds.
+ * Only used in the Intermediate Value Known Answer Test.
+ * Operations rearranged such that the intermediate values
+ * of decryption correspond with the intermediate values
+ * of encryption.
+ */
+int rijndaelDecryptRound(word8 a[4][4], word8 rk[MAXROUNDS+1][4][4], int ROUNDS, int rounds) {
+	int r, i;
+	word8 temp[4], shift;
+
+	/* make number of rounds sane */
+	if (rounds > ROUNDS) {
+		rounds = ROUNDS;
+	}
+    /* first round is special: */
+	*(word32 *)a[0] ^= *(word32 *)rk[ROUNDS][0];
+	*(word32 *)a[1] ^= *(word32 *)rk[ROUNDS][1];
+	*(word32 *)a[2] ^= *(word32 *)rk[ROUNDS][2];
+	*(word32 *)a[3] ^= *(word32 *)rk[ROUNDS][3];
+	for (i = 0; i < 4; i++) {
+		a[i][0] = Si[a[i][0]];
+		a[i][1] = Si[a[i][1]];
+		a[i][2] = Si[a[i][2]];
+		a[i][3] = Si[a[i][3]];
+	}
+	for (i = 1; i < 4; i++) {
+		shift = (4 - i) & 3;
+		temp[0] = a[(0 + shift) & 3][i];
+		temp[1] = a[(1 + shift) & 3][i];
+		temp[2] = a[(2 + shift) & 3][i];
+		temp[3] = a[(3 + shift) & 3][i];
+		a[0][i] = temp[0];
+		a[1][i] = temp[1];
+		a[2][i] = temp[2];
+		a[3][i] = temp[3];
+	}
+	/* ROUNDS-1 ordinary rounds */
+	for (r = ROUNDS-1; r > rounds; r--) {
+		*(word32 *)a[0] ^= *(word32 *)rk[r][0];
+		*(word32 *)a[1] ^= *(word32 *)rk[r][1];
+		*(word32 *)a[2] ^= *(word32 *)rk[r][2];
+		*(word32 *)a[3] ^= *(word32 *)rk[r][3];
+
+		*((word32*)a[0]) =
+			  *((word32*)U1[a[0][0]])
+			^ *((word32*)U2[a[0][1]])
+			^ *((word32*)U3[a[0][2]])
+			^ *((word32*)U4[a[0][3]]);
+
+		*((word32*)a[1]) =
+			  *((word32*)U1[a[1][0]])
+			^ *((word32*)U2[a[1][1]])
+			^ *((word32*)U3[a[1][2]])
+			^ *((word32*)U4[a[1][3]]);
+
+		*((word32*)a[2]) =
+			  *((word32*)U1[a[2][0]])
+			^ *((word32*)U2[a[2][1]])
+			^ *((word32*)U3[a[2][2]])
+			^ *((word32*)U4[a[2][3]]);
+
+		*((word32*)a[3]) =
+			  *((word32*)U1[a[3][0]])
+			^ *((word32*)U2[a[3][1]])
+			^ *((word32*)U3[a[3][2]])
+			^ *((word32*)U4[a[3][3]]);
+		for (i = 0; i < 4; i++) {
+			a[i][0] = Si[a[i][0]];
+			a[i][1] = Si[a[i][1]];
+			a[i][2] = Si[a[i][2]];
+			a[i][3] = Si[a[i][3]];
+		}
+		for (i = 1; i < 4; i++) {
+			shift = (4 - i) & 3;
+			temp[0] = a[(0 + shift) & 3][i];
+			temp[1] = a[(1 + shift) & 3][i];
+			temp[2] = a[(2 + shift) & 3][i];
+			temp[3] = a[(3 + shift) & 3][i];
+			a[0][i] = temp[0];
+			a[1][i] = temp[1];
+			a[2][i] = temp[2];
+			a[3][i] = temp[3];
+		}
+	}
+	if (rounds == 0) {
+		/* End with the extra key addition */	
+		*(word32 *)a[0] ^= *(word32 *)rk[0][0];
+		*(word32 *)a[1] ^= *(word32 *)rk[0][1];
+		*(word32 *)a[2] ^= *(word32 *)rk[0][2];
+		*(word32 *)a[3] ^= *(word32 *)rk[0][3];
+	}    
+	return 0;
+}
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+/*
+ * $PchId: rijndael_alg.c,v 1.2 2001/01/10 21:57:12 philip Exp $
+ */
Index: /trunk/minix/drivers/random/aes/rijndael_api.c
===================================================================
--- /trunk/minix/drivers/random/aes/rijndael_api.c	(revision 9)
+++ /trunk/minix/drivers/random/aes/rijndael_api.c	(revision 9)
@@ -0,0 +1,586 @@
+/*	rijndael-api.c - Rijndael encryption programming interface.
+ *							Author: Kees J. Bot
+ *								3 Nov 2000
+ * Heavily based on the original API code by Antoon Bosselaers,
+ * Vincent Rijmen, and Paulo Barreto, but with a different interface.
+ *
+ * Read this code top to bottom, not all comments are repeated.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "rijndael-alg.h"
+#include "rijndael-api.h"
+
+/* Map a byte (?) address to a word address or vv. */
+#define W(a)	((word32 *) (a))
+#define B(a)	((word8 *) (a))
+
+#if STRICT_ALIGN
+/* This machine checks alignment religiously.  (The code is not proper with
+ * respect to alignment.  We need a compiler that doesn't muck about with byte
+ * arrays that follow words in structs, and that places automatic variables
+ * at word boundaries if not odd-sized.  Most compilers are this nice.)
+ */
+
+#define aligned(a)		(((unsigned) (a) & 3) == 0)
+#define aligned2(a1, a2)	aligned((unsigned) (a1) | (unsigned) (a2))
+
+static void blockcpy(void *dst, const void *src)
+{
+    int i= 0;
+
+    do {
+	B(dst)[i+0] = B(src)[i+0];
+	B(dst)[i+1] = B(src)[i+1];
+	B(dst)[i+2] = B(src)[i+2];
+	B(dst)[i+3] = B(src)[i+3];
+    } while ((i += 4) < 16);
+}
+
+#else /* !STRICT_ALIGN */
+/* This machine doesn't mind misaligned accesses much. */
+
+#define aligned(a)		((void) (a), 1)
+#define aligned2(a1, a2)	((void) (a1), (void) (a2), 1)
+
+#if __GNUC__
+__inline
+#endif
+static void blockcpy(void *dst, const void *src)
+{
+    W(dst)[0] = W(src)[0];
+    W(dst)[1] = W(src)[1];
+    W(dst)[2] = W(src)[2];
+    W(dst)[3] = W(src)[3];
+}
+
+#endif /* !STRICT_ALIGN */
+
+#define between(a, c, z)	((unsigned) (c) - (a) <= (unsigned) (z) - (a))
+
+int rijndael_makekey(rd_keyinstance *key,
+	size_t keylen, const void *keymaterial)
+{
+    word8 k[MAXKC][4];
+
+    /* Initialize key schedule: */
+    if (keylen == RD_KEY_HEX) {
+	const word8 *kp;
+	int c, b;
+
+	kp= keymaterial;
+	keylen= 0;
+
+	for (;;) {
+	    c= *kp++;
+	    if (between('0', c, '9')) b= (c - '0' + 0x0) << 4;
+	    else
+	    if (between('a', c, 'f')) b= (c - 'a' + 0xa) << 4;
+	    else
+	    if (between('A', c, 'F')) b= (c - 'A' + 0xA) << 4;
+	    else break;
+
+	    c= *kp++;
+	    if (between('0', c, '9')) b |= (c - '0' + 0x0);
+	    else
+	    if (between('a', c, 'f')) b |= (c - 'a' + 0xa);
+	    else
+	    if (between('A', c, 'F')) b |= (c - 'A' + 0xA);
+	    else break;
+
+	    if (keylen >= 256/8) return RD_BAD_KEY_MAT;
+	    B(k)[keylen++] = b;
+	}
+	if (c != 0) return RD_BAD_KEY_MAT;
+
+	if (keylen != 128/8 && keylen != 192/8 && keylen != 256/8) {
+	    return RD_BAD_KEY_MAT;
+	}
+    } else {
+	if (keylen != 128/8 && keylen != 192/8 && keylen != 256/8) {
+	    return RD_BAD_KEY_MAT;
+	}
+	memcpy(k, keymaterial, keylen);
+    }
+
+    key->rounds= keylen * 8 / 32 + 6;
+
+    rijndael_KeySched(k, key->encsched, key->rounds);
+    memcpy(key->decsched, key->encsched, sizeof(key->decsched));
+    rijndael_KeyEncToDec(key->decsched, key->rounds);
+
+    return 0;
+}
+
+ssize_t rijndael_ecb_encrypt(rd_keyinstance *key,
+	const void *input, void *output, size_t length, void *dummyIV)
+{
+    /* Encrypt blocks of data in Electronic Codebook mode. */
+    const word8 *inp= input;
+    word8 *outp= output;
+    size_t i, nr_blocks, extra;
+    word32 in[4], out[4];
+    word8 t;
+
+    /* Compute the number of whole blocks, and the extra bytes beyond the
+     * last block.  Those extra bytes, if any, are encrypted by stealing
+     * enough bytes from the previous encrypted block to make a whole block.
+     * This is done by encrypting the last block, exchanging the first few
+     * encrypted bytes with the extra bytes, and encrypting the last whole
+     * block again.
+     */
+    nr_blocks= length / 16;
+    if ((extra= (length % 16)) > 0) {
+	if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
+	nr_blocks--;
+    }
+
+    /* Encrypt a number of blocks. */
+    if (aligned2(inp, outp)) {
+	for (i= 0; i < nr_blocks; i++) {
+	    rijndael_Encrypt(inp, outp, key->encsched, key->rounds);
+	    inp += 16;
+	    outp += 16;
+	}
+    } else {
+	for (i= 0; i < nr_blocks; i++) {
+	    blockcpy(in, inp);
+	    rijndael_Encrypt(in, out, key->encsched, key->rounds);
+	    blockcpy(outp, out);
+	    inp += 16;
+	    outp += 16;
+	}
+    }
+
+    /* Encrypt extra bytes by stealing from the last full block. */
+    if (extra > 0) {
+	blockcpy(in, inp);
+	rijndael_Encrypt(in, out, key->encsched, key->rounds);
+	for (i= 0; i < extra; i++) {
+	    t= B(out)[i];
+	    B(out)[i] = inp[16 + i];
+	    outp[16 + i] = t;
+	}
+	rijndael_Encrypt(out, out, key->encsched, key->rounds);
+	blockcpy(outp, out);
+    }
+    return length;
+}
+
+ssize_t rijndael_ecb_decrypt(rd_keyinstance *key,
+	const void *input, void *output, size_t length, void *dummyIV)
+{
+    /* Decrypt blocks of data in Electronic Codebook mode. */
+    const word8 *inp= input;
+    word8 *outp= output;
+    size_t i, nr_blocks, extra;
+    word32 in[4], out[4];
+    word8 t;
+
+    nr_blocks= length / 16;
+    if ((extra= (length % 16)) > 0) {
+	if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
+	nr_blocks--;
+    }
+
+    /* Decrypt a number of blocks. */
+    if (aligned2(inp, outp)) {
+	for (i= 0; i < nr_blocks; i++) {
+	    rijndael_Decrypt(inp, outp, key->decsched, key->rounds);
+	    inp += 16;
+	    outp += 16;
+	}
+    } else {
+	for (i= 0; i < nr_blocks; i++) {
+	    blockcpy(in, inp);
+	    rijndael_Decrypt(in, out, key->decsched, key->rounds);
+	    blockcpy(outp, out);
+	    inp += 16;
+	    outp += 16;
+	}
+    }
+
+    /* Decrypt extra bytes that stole from the last full block. */
+    if (extra > 0) {
+	blockcpy(in, inp);
+	rijndael_Decrypt(in, out, key->decsched, key->rounds);
+	for (i= 0; i < extra; i++) {
+	    t= B(out)[i];
+	    B(out)[i] = inp[16 + i];
+	    outp[16 + i] = t;
+	}
+	rijndael_Decrypt(out, out, key->decsched, key->rounds);
+	blockcpy(outp, out);
+    }
+    return length;
+}
+
+ssize_t rijndael_cbc_encrypt(rd_keyinstance *key,
+	const void *input, void *output, size_t length, void *IV)
+{
+    /* Encrypt blocks of data in Cypher Block Chaining mode. */
+    const word8 *inp= input;
+    word8 *outp= output;
+    size_t i, nr_blocks, extra;
+    word32 in[4], out[4], iv[4], *ivp;
+    word8 t;
+
+    nr_blocks= length / 16;
+    if ((extra= (length % 16)) > 0) {
+	if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
+	nr_blocks--;
+    }
+
+    /* Each input block is first XORed with the previous encryption result.
+     * The "Initialization Vector" is used to XOR the first block with.
+     * When done the last crypted block is stored back as the new IV to be
+     * used for another call to this function.
+     */
+    ivp= aligned(IV) ? IV : (blockcpy(iv, IV), iv);
+
+    if (aligned2(inp, outp)) {
+	for (i= 0; i < nr_blocks; i++) {
+	    in[0] = W(inp)[0] ^ ivp[0];
+	    in[1] = W(inp)[1] ^ ivp[1];
+	    in[2] = W(inp)[2] ^ ivp[2];
+	    in[3] = W(inp)[3] ^ ivp[3];
+	    rijndael_Encrypt(in, outp, key->encsched, key->rounds);
+	    ivp= W(outp);
+	    inp += 16;
+	    outp += 16;
+	}
+    } else {
+	for (i= 0; i < nr_blocks; i++) {
+	    blockcpy(in, inp);
+	    in[0] ^= ivp[0];
+	    in[1] ^= ivp[1];
+	    in[2] ^= ivp[2];
+	    in[3] ^= ivp[3];
+	    rijndael_Encrypt(in, out, key->encsched, key->rounds);
+	    blockcpy(outp, out);
+	    ivp= out;
+	    inp += 16;
+	    outp += 16;
+	}
+    }
+    if (extra > 0) {
+	blockcpy(in, inp);
+	in[0] ^= ivp[0];
+	in[1] ^= ivp[1];
+	in[2] ^= ivp[2];
+	in[3] ^= ivp[3];
+	rijndael_Encrypt(in, out, key->encsched, key->rounds);
+	for (i= 0; i < extra; i++) {
+	    t= B(out)[i];
+	    B(out)[i] ^= inp[16 + i];
+	    outp[16 + i] = t;
+	}
+	rijndael_Encrypt(out, out, key->encsched, key->rounds);
+	blockcpy(outp, out);
+	ivp= out;
+    }
+    blockcpy(IV, ivp);		/* Store last IV back. */
+    return length;
+}
+
+ssize_t rijndael_cbc_decrypt(rd_keyinstance *key,
+	const void *input, void *output, size_t length, void *IV)
+{
+    /* Decrypt blocks of data in Cypher Block Chaining mode. */
+    const word8 *inp= input;
+    word8 *outp= output;
+    size_t i, nr_blocks, extra;
+    word32 in[4], out[4], iv[4];
+    word8 t;
+
+    nr_blocks= length / 16;
+    if ((extra= (length % 16)) > 0) {
+	if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
+	nr_blocks--;
+    }
+
+    blockcpy(iv, IV);
+
+    if (aligned2(inp, outp)) {
+	for (i= 0; i < nr_blocks; i++) {
+	    rijndael_Decrypt(inp, out, key->decsched, key->rounds);
+	    out[0] ^= iv[0];
+	    out[1] ^= iv[1];
+	    out[2] ^= iv[2];
+	    out[3] ^= iv[3];
+	    iv[0] = W(inp)[0];
+	    iv[1] = W(inp)[1];
+	    iv[2] = W(inp)[2];
+	    iv[3] = W(inp)[3];
+	    W(outp)[0] = out[0];
+	    W(outp)[1] = out[1];
+	    W(outp)[2] = out[2];
+	    W(outp)[3] = out[3];
+	    inp += 16;
+	    outp += 16;
+	}
+    } else {
+	for (i= 0; i < nr_blocks; i++) {
+	    blockcpy(in, inp);
+	    rijndael_Decrypt(in, out, key->decsched, key->rounds);
+	    out[0] ^= iv[0];
+	    out[1] ^= iv[1];
+	    out[2] ^= iv[2];
+	    out[3] ^= iv[3];
+	    iv[0] = in[0];
+	    iv[1] = in[1];
+	    iv[2] = in[2];
+	    iv[3] = in[3];
+	    blockcpy(outp, out);
+	    inp += 16;
+	    outp += 16;
+	}
+    }
+    if (extra > 0) {
+	blockcpy(in, inp);
+	blockcpy(IV, in);
+	rijndael_Decrypt(in, out, key->decsched, key->rounds);
+	for (i= 0; i < extra; i++) {
+	    t= B(out)[i] ^ inp[16 + i];
+	    B(out)[i] = inp[16 + i];
+	    outp[16 + i] = t;
+	}
+	rijndael_Decrypt(out, out, key->decsched, key->rounds);
+	out[0] ^= iv[0];
+	out[1] ^= iv[1];
+	out[2] ^= iv[2];
+	out[3] ^= iv[3];
+	blockcpy(outp, out);
+    } else {
+	blockcpy(IV, iv);
+    }
+    return length;
+}
+
+ssize_t rijndael_cfb1_encrypt(rd_keyinstance *key,
+	const void *input, void *output, size_t length, void *IV)
+{
+    /* Encrypt blocks of data in Cypher Feedback mode, 1 bit at a time. */
+    const word8 *inp= input;
+    word8 *outp= output;
+    word8 t;
+    size_t i;
+    int b;
+    word32 iv[4], civ[4];
+
+    blockcpy(iv, IV);
+
+    for (i= 0; i < length; i++) {
+	t= *inp++;
+	for (b= 0; b < 8; b++) {
+	    rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
+	    t ^= (B(civ)[0] & 0x80) >> b;
+	    B(iv)[ 0] = (B(iv)[ 0] << 1) | (B(iv)[ 1] >> 7);
+	    B(iv)[ 1] = (B(iv)[ 1] << 1) | (B(iv)[ 2] >> 7);
+	    B(iv)[ 2] = (B(iv)[ 2] << 1) | (B(iv)[ 3] >> 7);
+	    B(iv)[ 3] = (B(iv)[ 3] << 1) | (B(iv)[ 4] >> 7);
+	    B(iv)[ 4] = (B(iv)[ 4] << 1) | (B(iv)[ 5] >> 7);
+	    B(iv)[ 5] = (B(iv)[ 5] << 1) | (B(iv)[ 6] >> 7);
+	    B(iv)[ 6] = (B(iv)[ 6] << 1) | (B(iv)[ 7] >> 7);
+	    B(iv)[ 7] = (B(iv)[ 7] << 1) | (B(iv)[ 8] >> 7);
+	    B(iv)[ 8] = (B(iv)[ 8] << 1) | (B(iv)[ 9] >> 7);
+	    B(iv)[ 9] = (B(iv)[ 9] << 1) | (B(iv)[10] >> 7);
+	    B(iv)[10] = (B(iv)[10] << 1) | (B(iv)[11] >> 7);
+	    B(iv)[11] = (B(iv)[11] << 1) | (B(iv)[12] >> 7);
+	    B(iv)[12] = (B(iv)[12] << 1) | (B(iv)[13] >> 7);
+	    B(iv)[13] = (B(iv)[13] << 1) | (B(iv)[14] >> 7);
+	    B(iv)[14] = (B(iv)[14] << 1) | (B(iv)[15] >> 7);
+	    B(iv)[15] = (B(iv)[15] << 1) | ((t >> (7-b)) & 1);
+	}
+	*outp++ = t;
+    }
+    blockcpy(IV, iv);
+    return length;
+}
+
+ssize_t rijndael_cfb1_decrypt(rd_keyinstance *key,
+	const void *input, void *output, size_t length, void *IV)
+{
+    /* Decrypt blocks of data in Cypher Feedback mode, 1 bit at a time. */
+    const word8 *inp= input;
+    word8 *outp= output;
+    word8 t;
+    size_t i;
+    int b;
+    word32 iv[4], civ[4];
+
+    blockcpy(iv, IV);
+
+    for (i= 0; i < length; i++) {
+	t= *inp++;
+	for (b= 0; b < 8; b++) {
+	    rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
+	    B(iv)[ 0] = (B(iv)[ 0] << 1) | (B(iv)[ 1] >> 7);
+	    B(iv)[ 1] = (B(iv)[ 1] << 1) | (B(iv)[ 2] >> 7);
+	    B(iv)[ 2] = (B(iv)[ 2] << 1) | (B(iv)[ 3] >> 7);
+	    B(iv)[ 3] = (B(iv)[ 3] << 1) | (B(iv)[ 4] >> 7);
+	    B(iv)[ 4] = (B(iv)[ 4] << 1) | (B(iv)[ 5] >> 7);
+	    B(iv)[ 5] = (B(iv)[ 5] << 1) | (B(iv)[ 6] >> 7);
+	    B(iv)[ 6] = (B(iv)[ 6] << 1) | (B(iv)[ 7] >> 7);
+	    B(iv)[ 7] = (B(iv)[ 7] << 1) | (B(iv)[ 8] >> 7);
+	    B(iv)[ 8] = (B(iv)[ 8] << 1) | (B(iv)[ 9] >> 7);
+	    B(iv)[ 9] = (B(iv)[ 9] << 1) | (B(iv)[10] >> 7);
+	    B(iv)[10] = (B(iv)[10] << 1) | (B(iv)[11] >> 7);
+	    B(iv)[11] = (B(iv)[11] << 1) | (B(iv)[12] >> 7);
+	    B(iv)[12] = (B(iv)[12] << 1) | (B(iv)[13] >> 7);
+	    B(iv)[13] = (B(iv)[13] << 1) | (B(iv)[14] >> 7);
+	    B(iv)[14] = (B(iv)[14] << 1) | (B(iv)[15] >> 7);
+	    B(iv)[15] = (B(iv)[15] << 1) | ((t >> (7-b)) & 1);
+	    t ^= (B(civ)[0] & 0x80) >> b;
+	}
+	*outp++ = t;
+    }
+    blockcpy(IV, iv);
+    return length;
+}
+
+ssize_t rijndael_cfb8_encrypt(rd_keyinstance *key,
+	const void *input, void *output, size_t length, void *IV)
+{
+    /* Encrypt blocks of data in Cypher Feedback mode, 8 bits at a time. */
+    const word8 *inp= input;
+    word8 *outp= output;
+    word8 t;
+    size_t i;
+    word32 iv[4], civ[4];
+
+    blockcpy(iv, IV);
+
+    for (i= 0; i < length; i++) {
+	t= *inp++;
+	rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
+	t ^= B(civ)[0];
+	B(iv)[ 0] = B(iv)[ 1];
+	B(iv)[ 1] = B(iv)[ 2];
+	B(iv)[ 2] = B(iv)[ 3];
+	B(iv)[ 3] = B(iv)[ 4];
+	B(iv)[ 4] = B(iv)[ 5];
+	B(iv)[ 5] = B(iv)[ 6];
+	B(iv)[ 6] = B(iv)[ 7];
+	B(iv)[ 7] = B(iv)[ 8];
+	B(iv)[ 8] = B(iv)[ 9];
+	B(iv)[ 9] = B(iv)[10];
+	B(iv)[10] = B(iv)[11];
+	B(iv)[11] = B(iv)[12];
+	B(iv)[12] = B(iv)[13];
+	B(iv)[13] = B(iv)[14];
+	B(iv)[14] = B(iv)[15];
+	B(iv)[15] = t;
+	*outp++ = t;
+    }
+    blockcpy(IV, iv);
+    return length;
+}
+
+ssize_t rijndael_cfb8_decrypt(rd_keyinstance *key,
+	const void *input, void *output, size_t length, void *IV)
+{
+    /* Decrypt blocks of data in Cypher Feedback mode, 1 byte at a time. */
+    const word8 *inp= input;
+    word8 *outp= output;
+    word8 t;
+    size_t i;
+    word32 iv[4], civ[4];
+
+    blockcpy(iv, IV);
+
+    for (i= 0; i < length; i++) {
+	t= *inp++;
+	rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
+	B(iv)[ 0] = B(iv)[ 1];
+	B(iv)[ 1] = B(iv)[ 2];
+	B(iv)[ 2] = B(iv)[ 3];
+	B(iv)[ 3] = B(iv)[ 4];
+	B(iv)[ 4] = B(iv)[ 5];
+	B(iv)[ 5] = B(iv)[ 6];
+	B(iv)[ 6] = B(iv)[ 7];
+	B(iv)[ 7] = B(iv)[ 8];
+	B(iv)[ 8] = B(iv)[ 9];
+	B(iv)[ 9] = B(iv)[10];
+	B(iv)[10] = B(iv)[11];
+	B(iv)[11] = B(iv)[12];
+	B(iv)[12] = B(iv)[13];
+	B(iv)[13] = B(iv)[14];
+	B(iv)[14] = B(iv)[15];
+	B(iv)[15] = t;
+	t ^= B(civ)[0];
+	*outp++ = t;
+    }
+    blockcpy(IV, iv);
+    return length;
+}
+
+ssize_t rijndael_pad(void *input, size_t length)
+{
+    /* Adds at most one block of RFC-2040 style padding to the input to make
+     * it a whole number of blocks for easier encryption.  To be used if the
+     * input may be less then one block in size, otherwise let the encryption
+     * routines use cypher stealing.  The input buffer should allow enough
+     * space for the padding.  The new length of the input is returned.
+     */
+    word8 *inp= input;
+    size_t padlen;
+
+    /* Add padding up until the next block boundary. */
+    padlen= 16 - (length % 16);
+    memset(inp + length, padlen, padlen);
+    return length + padlen;
+}
+
+ssize_t rijndael_unpad(const void *input, size_t length)
+{
+    /* Remove RFC-2040 style padding after decryption.  The true length of
+     * the input is returned, or the usual errors if the padding is incorrect.
+     */
+    const word8 *inp= input;
+    size_t i, padlen;
+
+    if (length == 0 || (length % 16) != 0) return RD_BAD_BLOCK_LENGTH;
+    padlen = inp[length-1];
+    if (padlen <= 0 || padlen > 16) return RD_BAD_DATA;
+    for (i= 2; i <= padlen; i++) {
+	if (inp[length-i] != padlen) return RD_BAD_DATA;
+    }
+    return length - padlen;
+}
+
+#ifdef INTERMEDIATE_VALUE_KAT
+
+void cipherEncryptUpdateRounds(rd_keyinstance *key,
+	const void *input, void *output, int rounds)
+{
+    /* Encrypt a block only a specified number of rounds. */
+    word8 block[4][4];
+
+    blockcpy(block, input);
+
+    rijndaelEncryptRound(block, key->encsched, key->rounds, rounds);
+
+    blockcpy(output, block);
+}
+
+void cipherDecryptUpdateRounds(rd_keyinstance *key,
+	const void *input, void *output, int rounds)
+{
+    /* Decrypt a block only a specified number of rounds. */
+    word8 block[4][4];
+
+    blockcpy(block, input);
+
+    rijndaelDecryptRound(block, key->decsched, key->rounds, rounds);
+
+    blockcpy(output, block);
+}
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+/*
+ * $PchId: rijndael_api.c,v 1.2 2001/01/10 22:01:20 philip Exp $
+ */
Index: /trunk/minix/drivers/random/aes/word_i386.h
===================================================================
--- /trunk/minix/drivers/random/aes/word_i386.h	(revision 9)
+++ /trunk/minix/drivers/random/aes/word_i386.h	(revision 9)
@@ -0,0 +1,9 @@
+typedef unsigned char byte;
+typedef unsigned char word8;
+typedef unsigned short word16;
+typedef unsigned word32;
+#define STRICT_ALIGN 1
+
+/*
+ * $PchId: word_i386.h,v 1.1 2003/09/29 09:20:13 philip Exp $
+ */
Index: /trunk/minix/drivers/random/main.c
===================================================================
--- /trunk/minix/drivers/random/main.c	(revision 9)
+++ /trunk/minix/drivers/random/main.c	(revision 9)
@@ -0,0 +1,246 @@
+/* This file contains the device dependent part of the drivers for the
+ * following special files:
+ *     /dev/random	- random number generator
+ */
+
+#include "../drivers.h"
+#include "../libdriver/driver.h"
+#include <sys/ioc_memory.h>
+#include "../../kernel/const.h"
+#include "../../kernel/config.h"
+#include "../../kernel/type.h"
+
+#include "assert.h"
+#include "random.h"
+
+#define NR_DEVS            1		/* number of minor devices */
+#  define RANDOM_DEV  0			/* minor device for /dev/random */
+
+#define KRANDOM_PERIOD    1 		/* ticks between krandom calls */
+
+PRIVATE struct device m_geom[NR_DEVS];  /* base and size of each device */
+PRIVATE int m_device;			/* current device */
+
+extern int errno;			/* error number for PM calls */
+
+FORWARD _PROTOTYPE( char *r_name, (void) );
+FORWARD _PROTOTYPE( struct device *r_prepare, (int device) );
+FORWARD _PROTOTYPE( int r_transfer, (int proc_nr, int opcode, off_t position,
+					iovec_t *iov, unsigned nr_req) );
+FORWARD _PROTOTYPE( int r_do_open, (struct driver *dp, message *m_ptr) );
+FORWARD _PROTOTYPE( void r_init, (void) );
+FORWARD _PROTOTYPE( int r_ioctl, (struct driver *dp, message *m_ptr) );
+FORWARD _PROTOTYPE( void r_geometry, (struct partition *entry) );
+FORWARD _PROTOTYPE( void r_random, (struct driver *dp, message *m_ptr) );
+
+/* Entry points to this driver. */
+PRIVATE struct driver r_dtab = {
+  r_name,	/* current device's name */
+  r_do_open,	/* open or mount */
+  do_nop,	/* nothing on a close */
+  r_ioctl,	/* specify ram disk geometry */
+  r_prepare,	/* prepare for I/O on a given minor device */
+  r_transfer,	/* do the I/O */
+  nop_cleanup,	/* no need to clean up */
+  r_geometry,	/* device "geometry" */
+  nop_signal,	/* system signals */
+  r_random, 	/* get randomness from kernel (alarm) */
+  nop_cancel,
+  nop_select,
+  NULL,
+  NULL
+};
+
+/* Buffer for the /dev/random number generator. */
+#define RANDOM_BUF_SIZE 		1024
+PRIVATE char random_buf[RANDOM_BUF_SIZE];
+
+/*===========================================================================*
+ *				   main 				     *
+ *===========================================================================*/
+PUBLIC int main(void)
+{
+  r_init();			/* initialize the memory driver */
+  driver_task(&r_dtab);		/* start driver's main loop */
+  return(OK);
+}
+
+/*===========================================================================*
+ *				 r_name					     *
+ *===========================================================================*/
+PRIVATE char *r_name()
+{
+/* Return a name for the current device. */
+  static char name[] = "random";
+  return name;  
+}
+
+/*===========================================================================*
+ *				r_prepare				     *
+ *===========================================================================*/
+PRIVATE struct device *r_prepare(device)
+int device;
+{
+/* Prepare for I/O on a device: check if the minor device number is ok. */
+
+  if (device < 0 || device >= NR_DEVS) return(NIL_DEV);
+  m_device = device;
+
+  return(&m_geom[device]);
+}
+
+/*===========================================================================*
+ *				r_transfer				     *
+ *===========================================================================*/
+PRIVATE int r_transfer(proc_nr, opcode, position, iov, nr_req)
+int proc_nr;			/* process doing the request */
+int opcode;			/* DEV_GATHER or DEV_SCATTER */
+off_t position;			/* offset on device to read or write */
+iovec_t *iov;			/* pointer to read or write request vector */
+unsigned nr_req;		/* length of request vector */
+{
+/* Read or write one the driver's minor devices. */
+  unsigned count, left, chunk;
+  vir_bytes user_vir;
+  struct device *dv;
+  unsigned long dv_size;
+
+  /* Get minor device number and check for /dev/null. */
+  dv = &m_geom[m_device];
+  dv_size = cv64ul(dv->dv_size);
+
+  while (nr_req > 0) {
+
+	/* How much to transfer and where to / from. */
+	count = iov->iov_size;
+	user_vir = iov->iov_addr;
+
+	switch (m_device) {
+
+	/* Random number generator. Character instead of block device. */
+	case RANDOM_DEV:
+	    if (opcode == DEV_GATHER && !random_isseeded())
+		    return(EAGAIN);
+	    left = count;
+	    while (left > 0) {
+	    	chunk = (left > RANDOM_BUF_SIZE) ? RANDOM_BUF_SIZE : left;
+ 	        if (opcode == DEV_GATHER) {
+		    random_getbytes(random_buf, chunk);
+	    	    sys_vircopy(SELF, D, (vir_bytes) random_buf, 
+	    	        proc_nr, D, user_vir, chunk);
+ 	        } else if (opcode == DEV_SCATTER) {
+	    	    sys_vircopy(proc_nr, D, user_vir, 
+	    	        SELF, D, (vir_bytes) random_buf, chunk);
+	    	        random_putbytes(random_buf, chunk);
+ 	        }
+ 	        user_vir += chunk;
+	    	left -= chunk;
+	    }
+	    break;
+
+	/* Unknown (illegal) minor device. */
+	default:
+	    return(EINVAL);
+	}
+
+	/* Book the number of bytes transferred. */
+	position += count;
+	iov->iov_addr += count;
+  	if ((iov->iov_size -= count) == 0) { iov++; nr_req--; }
+
+  }
+  return(OK);
+}
+
+/*============================================================================*
+ *				r_do_open				      *
+ *============================================================================*/
+PRIVATE int r_do_open(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+/* Check device number on open.  
+ */
+  if (r_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
+
+  return(OK);
+}
+
+/*===========================================================================*
+ *				r_init					     *
+ *===========================================================================*/
+PRIVATE void r_init()
+{
+  /* Initialize this task. All minor devices are initialized one by one. */
+  random_init();
+  r_random(NULL, NULL);				/* also set periodic timer */
+}
+
+/*===========================================================================*
+ *				r_ioctl					     *
+ *===========================================================================*/
+PRIVATE int r_ioctl(dp, m_ptr)
+struct driver *dp;			/* pointer to driver structure */
+message *m_ptr;				/* pointer to control message */
+{
+  struct device *dv;
+  if ((dv = r_prepare(m_ptr->DEVICE)) == NIL_DEV) return(ENXIO);
+
+  switch (m_ptr->REQUEST) {
+
+    default:
+  	return(do_diocntl(&r_dtab, m_ptr));
+  }
+  return(OK);
+}
+
+/*============================================================================*
+ *				r_random				      *
+ *============================================================================*/
+PRIVATE void r_random(dp, m_ptr)
+struct driver *dp;			/* pointer to driver structure */
+message *m_ptr;				/* pointer to alarm message */
+{
+  /* Fetch random information from the kernel to update /dev/random. */
+  int i, s, r_next, r_size, r_high;
+  struct randomness krandom;
+
+  if (OK != (s=sys_getrandomness(&krandom)))
+  	report("RANDOM", "sys_getrandomness failed", s);
+
+  for (i= 0; i<RANDOM_SOURCES; i++)	
+  {
+  	r_next= krandom.bin[i].r_next;
+  	r_size= krandom.bin[i].r_size;
+  	r_high= r_next+r_size;
+  	if (r_high <= RANDOM_ELEMENTS)
+  	{
+  		random_update(i, &krandom.bin[i].r_buf[r_next], r_size);
+	}
+	else
+	{
+		assert(r_next < RANDOM_ELEMENTS);
+  		random_update(i, &krandom.bin[i].r_buf[r_next],
+  			RANDOM_ELEMENTS-r_next);
+  		random_update(i, &krandom.bin[i].r_buf[0],
+  			r_high-RANDOM_ELEMENTS);
+	}
+  }
+
+  /* Schedule new alarm for next m_random call. */
+  if (OK != (s=sys_setalarm(KRANDOM_PERIOD, 0)))
+  	report("RANDOM", "sys_setalarm failed", s);
+}
+
+/*============================================================================*
+ *				r_geometry				      *
+ *============================================================================*/
+PRIVATE void r_geometry(entry)
+struct partition *entry;
+{
+  /* Memory devices don't have a geometry, but the outside world insists. */
+  entry->cylinders = div64u(m_geom[m_device].dv_size, SECTOR_SIZE) / (64 * 32);
+  entry->heads = 64;
+  entry->sectors = 32;
+}
+
Index: /trunk/minix/drivers/random/random.c
===================================================================
--- /trunk/minix/drivers/random/random.c	(revision 9)
+++ /trunk/minix/drivers/random/random.c	(revision 9)
@@ -0,0 +1,238 @@
+/*
+random.c
+
+Random number generator.
+
+The random number generator collects data from the kernel and compressed
+that data into a seed for a psuedo random number generator.
+*/
+
+#include "../drivers.h"
+#include "../../kernel/const.h"
+#include "assert.h"
+
+#include "random.h"
+#include "sha2.h"
+#include "aes/rijndael.h"
+
+#define N_DERIV	16
+#define NR_POOLS 32
+#define MIN_SAMPLES	256	/* Number of samples needed in pool 0 for a
+				 * re-seed.
+				 */
+
+PRIVATE unsigned long deriv[RANDOM_SOURCES][N_DERIV];
+PRIVATE int pool_ind[RANDOM_SOURCES];
+PRIVATE SHA256_CTX pool_ctx[NR_POOLS];
+PRIVATE unsigned samples= 0;
+PRIVATE int got_seeded= 0;
+PRIVATE u8_t random_key[2*AES_BLOCKSIZE];
+PRIVATE u32_t count_lo, count_hi;
+PRIVATE u32_t reseed_count;
+
+FORWARD _PROTOTYPE( void add_sample, (int source, unsigned long sample)	);
+FORWARD _PROTOTYPE( void data_block, (rd_keyinstance *keyp,
+							void *data)	);
+FORWARD _PROTOTYPE( void reseed, (void)					);
+
+PUBLIC void random_init()
+{
+	int i, j;
+
+	assert(&deriv[RANDOM_SOURCES-1][N_DERIV-1] ==
+		&deriv[0][0] + RANDOM_SOURCES*N_DERIV -1);
+
+	for (i= 0; i<RANDOM_SOURCES; i++)
+	{
+		for (j= 0; j<N_DERIV; j++)
+			deriv[i][j]= 0;
+		pool_ind[i]= 0;
+	}
+	for (i= 0; i<NR_POOLS; i++)
+		SHA256_Init(&pool_ctx[i]);
+	count_lo= 0;
+	count_hi= 0;
+	reseed_count= 0;
+}
+
+PUBLIC int random_isseeded()
+{
+	if (got_seeded)
+		return 1;
+	return 0;
+}
+
+PUBLIC void random_update(source, buf, count)
+int source;
+unsigned short *buf;
+int count;
+{
+	int i;
+
+#if 0
+	printf("random_update: got %d samples for source %d\n", count, source);
+#endif
+	if (source < 0 || source >= RANDOM_SOURCES)
+		panic("memory", "random_update: bad source", source);
+	for (i= 0; i<count; i++)
+		add_sample(source, buf[i]);
+	reseed();
+}
+
+PUBLIC void random_getbytes(buf, size)
+void *buf;
+size_t size;
+{
+	int n, r;
+	u8_t *cp;
+	rd_keyinstance key;
+	u8_t output[AES_BLOCKSIZE];
+
+	r= rijndael_makekey(&key, sizeof(random_key), random_key);
+	assert(r == 0);
+
+	cp= buf;
+	while (size > 0)
+	{
+		n= AES_BLOCKSIZE;
+		if (n > size)
+		{
+			n= size;
+			data_block(&key, output);
+			memcpy(cp, output, n);
+		}
+		else
+			data_block(&key, cp);
+		cp += n;
+		size -= n;
+	}
+
+	/* Generate new key */
+	assert(sizeof(random_key) == 2*AES_BLOCKSIZE);
+	data_block(&key, random_key);
+	data_block(&key, random_key+AES_BLOCKSIZE);
+}
+
+PUBLIC void random_putbytes(buf, size)
+void *buf;
+size_t size;
+{
+	/* Add bits to pool zero */
+	SHA256_Update(&pool_ctx[0], buf, size);
+
+	/* Assume that these bits are truely random. Increment samples
+	 * with the number of bits.
+	 */
+	samples += size*8;
+
+	reseed();
+}
+
+PRIVATE void add_sample(source, sample)
+int source;
+unsigned long sample;
+{
+	int i, pool_nr;
+	unsigned long d, v, di, min;
+
+	/* Delete bad sample. Compute the Nth derivative. Delete the sample
+	 * if any derivative is too small.
+	 */
+	min= (unsigned long)-1;
+	v= sample;
+	for (i= 0; i<N_DERIV; i++)
+	{
+		di= deriv[source][i];
+
+		/* Compute the difference */
+		if (v >= di)
+			d= v-di;
+		else
+			d= di-v;
+		deriv[source][i]= v;
+		v= d;
+		if (v <min)
+			min= v;
+	}
+	if (min < 2)
+	{
+#if 0
+		printf("ignoring sample '%u' from source %d\n",
+			sample, source);
+#endif
+		return;
+	}
+#if 0
+	printf("accepting sample '%u' from source %d\n", sample, source);
+#endif
+
+	pool_nr= pool_ind[source];
+	assert(pool_nr >= 0 && pool_nr < NR_POOLS);
+
+	SHA256_Update(&pool_ctx[pool_nr], (unsigned char *)&sample,
+		sizeof(sample));
+	if (pool_nr == 0)
+		samples++;
+	pool_nr++;
+	if (pool_nr >= NR_POOLS)
+		pool_nr= 0;
+	pool_ind[source]= pool_nr;
+}
+
+PRIVATE void data_block(keyp, data)
+rd_keyinstance *keyp;
+void *data;
+{
+	int r;
+	u8_t input[AES_BLOCKSIZE];
+
+	memset(input, '\0', sizeof(input));
+
+	/* Do we want the output of the random numbers to be portable 
+	 * across platforms (for example for RSA signatures)? At the moment
+	 * we don't do anything special. Encrypt the counter with the AES
+	 * key.
+	 */
+	assert(sizeof(count_lo)+sizeof(count_hi) <= AES_BLOCKSIZE);
+	memcpy(input, &count_lo, sizeof(count_lo));
+	memcpy(input+sizeof(count_lo), &count_hi, sizeof(count_hi));
+	r= rijndael_ecb_encrypt(keyp, input, data, AES_BLOCKSIZE, NULL);
+	assert(r == AES_BLOCKSIZE);
+
+	count_lo++;
+	if (count_lo == 0)
+		count_hi++;
+}
+
+PRIVATE void reseed()
+{
+	int i;
+	SHA256_CTX ctx;
+	u8_t digest[SHA256_DIGEST_LENGTH];
+
+	if (samples < MIN_SAMPLES)
+		return;
+
+	reseed_count++;
+	SHA256_Init(&ctx);
+	if (got_seeded)
+		SHA256_Update(&ctx, random_key, sizeof(random_key));
+	SHA256_Final(digest, &pool_ctx[0]);
+	SHA256_Update(&ctx, digest, sizeof(digest));
+	SHA256_Init(&pool_ctx[0]);
+	for (i= 1; i<NR_POOLS; i++)
+	{
+		if ((reseed_count & (1UL << (i-1))) != 0)
+			break;
+		SHA256_Final(digest, &pool_ctx[i]);
+		SHA256_Update(&ctx, digest, sizeof(digest));
+		SHA256_Init(&pool_ctx[i]);
+	}
+	SHA256_Final(digest, &ctx);
+	assert(sizeof(random_key) == sizeof(digest));
+	memcpy(random_key, &digest, sizeof(random_key));
+	samples= 0;
+
+	got_seeded= 1;
+}
+
Index: /trunk/minix/drivers/random/random.h
===================================================================
--- /trunk/minix/drivers/random/random.h	(revision 9)
+++ /trunk/minix/drivers/random/random.h	(revision 9)
@@ -0,0 +1,12 @@
+/*
+random.h
+
+Public interface to the random number generator 
+*/
+
+_PROTOTYPE( void random_init, (void)					);
+_PROTOTYPE( int random_isseeded, (void)					);
+_PROTOTYPE( void random_update, (int source, unsigned short *buf, 
+							int count)	);
+_PROTOTYPE( void random_getbytes, (void *buf, size_t size)		);
+_PROTOTYPE( void random_putbytes, (void *buf, size_t size)		);
Index: /trunk/minix/drivers/random/sha2.c
===================================================================
--- /trunk/minix/drivers/random/sha2.c	(revision 9)
+++ /trunk/minix/drivers/random/sha2.c	(revision 9)
@@ -0,0 +1,1086 @@
+/*	$FreeBSD: src/sys/crypto/sha2/sha2.c,v 1.2.2.2 2002/03/05 08:36:47 ume Exp $	*/
+/*	$KAME: sha2.c,v 1.8 2001/11/08 01:07:52 itojun Exp $	*/
+
+/*
+ * sha2.c
+ *
+ * Version 1.0.0beta1
+ *
+ * Written by Aaron D. Gifford <me@aarongifford.com>
+ *
+ * Copyright 2000 Aaron D. Gifford.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/types.h>
+/* #include <sys/time.h> */
+/* #include <sys/systm.h> */
+/* #include <machine/endian.h> */
+#include "sha2.h"
+
+/*
+ * ASSERT NOTE:
+ * Some sanity checking code is included using assert().  On my FreeBSD
+ * system, this additional code can be removed by compiling with NDEBUG
+ * defined.  Check your own systems manpage on assert() to see how to
+ * compile WITHOUT the sanity checking code on your system.
+ *
+ * UNROLLED TRANSFORM LOOP NOTE:
+ * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
+ * loop version for the hash transform rounds (defined using macros
+ * later in this file).  Either define on the command line, for example:
+ *
+ *   cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
+ *
+ * or define below:
+ *
+ *   #define SHA2_UNROLL_TRANSFORM
+ *
+ */
+
+#if defined(__bsdi__) || defined(__FreeBSD__)
+#define assert(x)
+#endif
+
+/*** SHA-256/384/512 Machine Architecture Definitions *****************/
+/*
+ * SHA2_BYTE_ORDER NOTE:
+ *
+ * Please make sure that your system defines SHA2_BYTE_ORDER.  If your
+ * architecture is little-endian, make sure it also defines
+ * SHA2_LITTLE_ENDIAN and that the two (SHA2_BYTE_ORDER and SHA2_LITTLE_ENDIAN) are
+ * equivilent.
+ *
+ * If your system does not define the above, then you can do so by
+ * hand like this:
+ *
+ *   #define SHA2_LITTLE_ENDIAN 1234
+ *   #define SHA2_BIG_ENDIAN    4321
+ *
+ * And for little-endian machines, add:
+ *
+ *   #define SHA2_BYTE_ORDER SHA2_LITTLE_ENDIAN 
+ *
+ * Or for big-endian machines:
+ *
+ *   #define SHA2_BYTE_ORDER SHA2_BIG_ENDIAN
+ *
+ * The FreeBSD machine this was written on defines BYTE_ORDER
+ * appropriately by including <sys/types.h> (which in turn includes
+ * <machine/endian.h> where the appropriate definitions are actually
+ * made).
+ */
+#if !defined(SHA2_BYTE_ORDER) || (SHA2_BYTE_ORDER != SHA2_LITTLE_ENDIAN && SHA2_BYTE_ORDER != SHA2_BIG_ENDIAN)
+#error Define SHA2_BYTE_ORDER to be equal to either SHA2_LITTLE_ENDIAN or SHA2_BIG_ENDIAN
+#endif
+
+/*
+ * Define the followingsha2_* types to types of the correct length on
+ * the native archtecture.   Most BSD systems and Linux define u_intXX_t
+ * types.  Machines with very recent ANSI C headers, can use the
+ * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H
+ * during compile or in the sha.h header file.
+ *
+ * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t
+ * will need to define these three typedefs below (and the appropriate
+ * ones in sha.h too) by hand according to their system architecture.
+ *
+ * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t
+ * types and pointing out recent ANSI C support for uintXX_t in inttypes.h.
+ */
+#if 0 /*def SHA2_USE_INTTYPES_H*/
+
+typedef uint8_t  sha2_byte;	/* Exactly 1 byte */
+typedef uint32_t sha2_word32;	/* Exactly 4 bytes */
+typedef uint64_t sha2_word64;	/* Exactly 8 bytes */
+
+#else /* SHA2_USE_INTTYPES_H */
+
+typedef u_int8_t  sha2_byte;	/* Exactly 1 byte */
+typedef u_int32_t sha2_word32;	/* Exactly 4 bytes */
+typedef u_int64_t sha2_word64;	/* Exactly 8 bytes */
+
+#endif /* SHA2_USE_INTTYPES_H */
+
+/*** SHA-256/384/512 Various Length Definitions ***********************/
+/* NOTE: Most of these are in sha2.h */
+#define SHA256_SHORT_BLOCK_LENGTH	(SHA256_BLOCK_LENGTH - 8)
+#define SHA384_SHORT_BLOCK_LENGTH	(SHA384_BLOCK_LENGTH - 16)
+#define SHA512_SHORT_BLOCK_LENGTH	(SHA512_BLOCK_LENGTH - 16)
+
+/*** ENDIAN REVERSAL MACROS *******************************************/
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+#define REVERSE32(w,x)	{ \
+	sha2_word32 tmp = (w); \
+	tmp = (tmp >> 16) | (tmp << 16); \
+	(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
+}
+#define REVERSE64(w,x)	{ \
+	sha2_word64 tmp = (w); \
+	tmp = (tmp >> 32) | (tmp << 32); \
+	tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
+	      ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
+	(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
+	      ((tmp & 0x0000ffff0000ffffULL) << 16); \
+}
+#if MINIX_64BIT
+#undef REVERSE64
+#define REVERSE64(w,x)	{ \
+	u32_t hi, lo; \
+	REVERSE32(ex64hi((w)), lo); \
+	REVERSE32(ex64lo((w)), hi); \
+	(x) = make64(lo, hi); \
+}
+#endif /* MINIX_64BIT */
+#endif /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+
+/*
+ * Macro for incrementally adding the unsigned 64-bit integer n to the
+ * unsigned 128-bit integer (represented using a two-element array of
+ * 64-bit words):
+ */
+#define ADDINC128(w,n)	{ \
+	(w)[0] += (sha2_word64)(n); \
+	if ((w)[0] < (n)) { \
+		(w)[1]++; \
+	} \
+}
+
+/*** THE SIX LOGICAL FUNCTIONS ****************************************/
+/*
+ * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
+ *
+ *   NOTE:  The naming of R and S appears backwards here (R is a SHIFT and
+ *   S is a ROTATION) because the SHA-256/384/512 description document
+ *   (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
+ *   same "backwards" definition.
+ */
+/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
+#define R(b,x) 		((x) >> (b))
+/* 32-bit Rotate-right (used in SHA-256): */
+#define S32(b,x)	(((x) >> (b)) | ((x) << (32 - (b))))
+/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
+#define S64(b,x)	(((x) >> (b)) | ((x) << (64 - (b))))
+
+/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
+#define Ch(x,y,z)	(((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z)	(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+/* Four of six logical functions used in SHA-256: */
+#define Sigma0_256(x)	(S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))
+#define Sigma1_256(x)	(S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))
+#define sigma0_256(x)	(S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))
+#define sigma1_256(x)	(S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))
+
+/* Four of six logical functions used in SHA-384 and SHA-512: */
+#define Sigma0_512(x)	(S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
+#define Sigma1_512(x)	(S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
+#define sigma0_512(x)	(S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7,   (x)))
+#define sigma1_512(x)	(S64(19, (x)) ^ S64(61, (x)) ^ R( 6,   (x)))
+
+/*** INTERNAL FUNCTION PROTOTYPES *************************************/
+/* NOTE: These should not be accessed directly from outside this
+ * library -- they are intended for private internal visibility/use
+ * only.
+ */
+void SHA512_Last(SHA512_CTX*);
+void SHA256_Transform(SHA256_CTX*, const sha2_word32*);
+void SHA512_Transform(SHA512_CTX*, const sha2_word64*);
+
+/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
+/* Hash constant words K for SHA-256: */
+const static sha2_word32 K256[64] = {
+	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+/* Initial hash value H for SHA-256: */
+const static sha2_word32 sha256_initial_hash_value[8] = {
+	0x6a09e667UL,
+	0xbb67ae85UL,
+	0x3c6ef372UL,
+	0xa54ff53aUL,
+	0x510e527fUL,
+	0x9b05688cUL,
+	0x1f83d9abUL,
+	0x5be0cd19UL
+};
+
+#if !NO_64BIT
+/* Hash constant words K for SHA-384 and SHA-512: */
+const static sha2_word64 K512[80] = {
+	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+	0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+	0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+	0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+	0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+	0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+	0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+	0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+	0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+	0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+	0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+	0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+	0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+	0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+	0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+	0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+	0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+	0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+	0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+	0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+	0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+	0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+	0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+	0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+	0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+	0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+	0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+	0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+	0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+	0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+	0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+	0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+	0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+	0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+	0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+	0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+	0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+	0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+	0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+	0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+/* Initial hash value H for SHA-384 */
+const static sha2_word64 sha384_initial_hash_value[8] = {
+	0xcbbb9d5dc1059ed8ULL,
+	0x629a292a367cd507ULL,
+	0x9159015a3070dd17ULL,
+	0x152fecd8f70e5939ULL,
+	0x67332667ffc00b31ULL,
+	0x8eb44a8768581511ULL,
+	0xdb0c2e0d64f98fa7ULL,
+	0x47b5481dbefa4fa4ULL
+};
+
+/* Initial hash value H for SHA-512 */
+const static sha2_word64 sha512_initial_hash_value[8] = {
+	0x6a09e667f3bcc908ULL,
+	0xbb67ae8584caa73bULL,
+	0x3c6ef372fe94f82bULL,
+	0xa54ff53a5f1d36f1ULL,
+	0x510e527fade682d1ULL,
+	0x9b05688c2b3e6c1fULL,
+	0x1f83d9abfb41bd6bULL,
+	0x5be0cd19137e2179ULL
+};
+#endif /* !NO_64BIT */
+
+/*
+ * Constant used by SHA256/384/512_End() functions for converting the
+ * digest to a readable hexadecimal character string:
+ */
+static const char *sha2_hex_digits = "0123456789abcdef";
+
+/*** SHA-256: *********************************************************/
+void SHA256_Init(SHA256_CTX* context) {
+	if (context == (SHA256_CTX*)0) {
+		return;
+	}
+	bcopy(sha256_initial_hash_value, context->state, SHA256_DIGEST_LENGTH);
+	bzero(context->buffer, SHA256_BLOCK_LENGTH);
+#if MINIX_64BIT
+	context->bitcount= cvu64(0);
+#else /* !MINIX_64BIT */
+	context->bitcount = 0;
+#endif /* MINIX_64BIT */
+}
+
+#ifdef SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-256 round macros: */
+
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
+	REVERSE32(*data++, W256[j]); \
+	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+             K256[j] + W256[j]; \
+	(d) += T1; \
+	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+	j++
+
+#else /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
+	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+	     K256[j] + (W256[j] = *data++); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+	j++
+
+#endif /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+
+#define ROUND256(a,b,c,d,e,f,g,h)	\
+	s0 = W256[(j+1)&0x0f]; \
+	s0 = sigma0_256(s0); \
+	s1 = W256[(j+14)&0x0f]; \
+	s1 = sigma1_256(s1); \
+	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
+	     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+	j++
+
+void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
+	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
+	sha2_word32	T1, *W256;
+	int		j;
+
+	W256 = (sha2_word32*)context->buffer;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+		/* Rounds 0 to 15 (unrolled): */
+		ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
+		ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
+		ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
+		ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
+		ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
+		ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
+		ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
+		ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
+	} while (j < 16);
+
+	/* Now for the remaining rounds to 64: */
+	do {
+		ROUND256(a,b,c,d,e,f,g,h);
+		ROUND256(h,a,b,c,d,e,f,g);
+		ROUND256(g,h,a,b,c,d,e,f);
+		ROUND256(f,g,h,a,b,c,d,e);
+		ROUND256(e,f,g,h,a,b,c,d);
+		ROUND256(d,e,f,g,h,a,b,c);
+		ROUND256(c,d,e,f,g,h,a,b);
+		ROUND256(b,c,d,e,f,g,h,a);
+	} while (j < 64);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = 0;
+}
+
+#else /* SHA2_UNROLL_TRANSFORM */
+
+void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
+	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
+	sha2_word32	T1, T2, *W256;
+	int		j;
+
+	W256 = (sha2_word32*)context->buffer;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+		/* Copy data while converting to host byte order */
+		REVERSE32(*data++,W256[j]);
+		/* Apply the SHA-256 compression function to update a..h */
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
+#else /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+		/* Apply the SHA-256 compression function to update a..h with copy */
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
+#endif /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+		T2 = Sigma0_256(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 16);
+
+	do {
+		/* Part of the message block expansion: */
+		s0 = W256[(j+1)&0x0f];
+		s0 = sigma0_256(s0);
+		s1 = W256[(j+14)&0x0f];	
+		s1 = sigma1_256(s1);
+
+		/* Apply the SHA-256 compression function to update a..h */
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + 
+		     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
+		T2 = Sigma0_256(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 64);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#endif /* SHA2_UNROLL_TRANSFORM */
+
+void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
+	unsigned int	freespace, usedspace;
+
+	if (len == 0) {
+		/* Calling with no data is valid - we do nothing */
+		return;
+	}
+
+	/* Sanity check: */
+	assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0);
+
+#if MINIX_64BIT
+	usedspace= rem64u(context->bitcount, SHA256_BLOCK_LENGTH*8)/8;
+#else /* !MINIX_64BIT */
+	usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
+#endif /* MINIX_64BIT */
+	if (usedspace > 0) {
+		/* Calculate how much free space is available in the buffer */
+		freespace = SHA256_BLOCK_LENGTH - usedspace;
+
+		if (len >= freespace) {
+			/* Fill the buffer completely and process it */
+			bcopy(data, &context->buffer[usedspace], freespace);
+#if MINIX_64BIT
+			context->bitcount= add64u(context->bitcount,
+				freespace << 3);
+#else /* !MINIX_64BIT */
+			context->bitcount += freespace << 3;
+#endif /* MINIX_64BIT */
+			len -= freespace;
+			data += freespace;
+			SHA256_Transform(context, (sha2_word32*)context->buffer);
+		} else {
+			/* The buffer is not yet full */
+			bcopy(data, &context->buffer[usedspace], len);
+#if MINIX_64BIT
+			context->bitcount= add64u(context->bitcount, len << 3);
+#else /* !MINIX_64BIT */
+			context->bitcount += len << 3;
+#endif /* MINIX_64BIT */
+			/* Clean up: */
+			usedspace = freespace = 0;
+			return;
+		}
+	}
+	while (len >= SHA256_BLOCK_LENGTH) {
+		/* Process as many complete blocks as we can */
+		SHA256_Transform(context, (const sha2_word32*)data);
+#if MINIX_64BIT
+		context->bitcount= add64u(context->bitcount,
+			SHA256_BLOCK_LENGTH << 3);
+#else /* !MINIX_64BIT */
+		context->bitcount += SHA256_BLOCK_LENGTH << 3;
+#endif /* MINIX_64BIT */
+		len -= SHA256_BLOCK_LENGTH;
+		data += SHA256_BLOCK_LENGTH;
+	}
+	if (len > 0) {
+		/* There's left-overs, so save 'em */
+		bcopy(data, context->buffer, len);
+#if MINIX_64BIT
+		context->bitcount= add64u(context->bitcount, len << 3);
+#else /* !MINIX_64BIT */
+		context->bitcount += len << 3;
+#endif /* MINIX_64BIT */
+	}
+	/* Clean up: */
+	usedspace = freespace = 0;
+}
+
+void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
+	sha2_word32	*d = (sha2_word32*)digest;
+	unsigned int	usedspace;
+
+	/* Sanity check: */
+	assert(context != (SHA256_CTX*)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (sha2_byte*)0) {
+#if MINIX_64BIT
+		usedspace= rem64u(context->bitcount, SHA256_BLOCK_LENGTH*8)/8;
+#else /* !MINIX_64BIT */
+		usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
+#endif /* MINIX_64BIT */
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+		/* Convert FROM host byte order */
+		REVERSE64(context->bitcount,context->bitcount);
+#endif
+		if (usedspace > 0) {
+			/* Begin padding with a 1 bit: */
+			context->buffer[usedspace++] = 0x80;
+
+			if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
+				/* Set-up for the last transform: */
+				bzero(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace);
+			} else {
+				if (usedspace < SHA256_BLOCK_LENGTH) {
+					bzero(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace);
+				}
+				/* Do second-to-last transform: */
+				SHA256_Transform(context, (sha2_word32*)context->buffer);
+
+				/* And set-up for the last transform: */
+				bzero(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
+			}
+		} else {
+			/* Set-up for the last transform: */
+			bzero(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
+
+			/* Begin padding with a 1 bit: */
+			*context->buffer = 0x80;
+		}
+		/* Set the bit count: */
+		*(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
+
+		/* Final transform: */
+		SHA256_Transform(context, (sha2_word32*)context->buffer);
+
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+		{
+			/* Convert TO host byte order */
+			int	j;
+			for (j = 0; j < 8; j++) {
+				REVERSE32(context->state[j],context->state[j]);
+				*d++ = context->state[j];
+			}
+		}
+#else
+		bcopy(context->state, d, SHA256_DIGEST_LENGTH);
+#endif
+	}
+
+	/* Clean up state data: */
+	bzero(context, sizeof(context));
+	usedspace = 0;
+}
+
+char *SHA256_End(SHA256_CTX* context, char buffer[]) {
+	sha2_byte	digest[SHA256_DIGEST_LENGTH], *d = digest;
+	int		i;
+
+	/* Sanity check: */
+	assert(context != (SHA256_CTX*)0);
+
+	if (buffer != (char*)0) {
+		SHA256_Final(digest, context);
+
+		for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+			*buffer++ = sha2_hex_digits[*d & 0x0f];
+			d++;
+		}
+		*buffer = (char)0;
+	} else {
+		bzero(context, sizeof(context));
+	}
+	bzero(digest, SHA256_DIGEST_LENGTH);
+	return buffer;
+}
+
+char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) {
+	SHA256_CTX	context;
+
+	SHA256_Init(&context);
+	SHA256_Update(&context, data, len);
+	return SHA256_End(&context, digest);
+}
+
+#if !NO_64BIT
+
+/*** SHA-512: *********************************************************/
+void SHA512_Init(SHA512_CTX* context) {
+	if (context == (SHA512_CTX*)0) {
+		return;
+	}
+	bcopy(sha512_initial_hash_value, context->state, SHA512_DIGEST_LENGTH);
+	bzero(context->buffer, SHA512_BLOCK_LENGTH);
+	context->bitcount[0] = context->bitcount[1] =  0;
+}
+
+#ifdef SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-512 round macros: */
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
+	REVERSE64(*data++, W512[j]); \
+	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+             K512[j] + W512[j]; \
+	(d) += T1, \
+	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
+	j++
+
+#else /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
+	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+             K512[j] + (W512[j] = *data++); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+	j++
+
+#endif /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+
+#define ROUND512(a,b,c,d,e,f,g,h)	\
+	s0 = W512[(j+1)&0x0f]; \
+	s0 = sigma0_512(s0); \
+	s1 = W512[(j+14)&0x0f]; \
+	s1 = sigma1_512(s1); \
+	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
+             (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+	j++
+
+void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
+	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
+	sha2_word64	T1, *W512 = (sha2_word64*)context->buffer;
+	int		j;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+		ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
+		ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
+		ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
+		ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
+		ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
+		ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
+		ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
+		ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
+	} while (j < 16);
+
+	/* Now for the remaining rounds up to 79: */
+	do {
+		ROUND512(a,b,c,d,e,f,g,h);
+		ROUND512(h,a,b,c,d,e,f,g);
+		ROUND512(g,h,a,b,c,d,e,f);
+		ROUND512(f,g,h,a,b,c,d,e);
+		ROUND512(e,f,g,h,a,b,c,d);
+		ROUND512(d,e,f,g,h,a,b,c);
+		ROUND512(c,d,e,f,g,h,a,b);
+		ROUND512(b,c,d,e,f,g,h,a);
+	} while (j < 80);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = 0;
+}
+
+#else /* SHA2_UNROLL_TRANSFORM */
+
+void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
+	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
+	sha2_word64	T1, T2, *W512 = (sha2_word64*)context->buffer;
+	int		j;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+		/* Convert TO host byte order */
+		REVERSE64(*data++, W512[j]);
+		/* Apply the SHA-512 compression function to update a..h */
+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
+#else /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+		/* Apply the SHA-512 compression function to update a..h with copy */
+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
+#endif /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+		T2 = Sigma0_512(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 16);
+
+	do {
+		/* Part of the message block expansion: */
+		s0 = W512[(j+1)&0x0f];
+		s0 = sigma0_512(s0);
+		s1 = W512[(j+14)&0x0f];
+		s1 =  sigma1_512(s1);
+
+		/* Apply the SHA-512 compression function to update a..h */
+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
+		     (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
+		T2 = Sigma0_512(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 80);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#endif /* SHA2_UNROLL_TRANSFORM */
+
+void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
+	unsigned int	freespace, usedspace;
+
+	if (len == 0) {
+		/* Calling with no data is valid - we do nothing */
+		return;
+	}
+
+	/* Sanity check: */
+	assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0);
+
+	usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
+	if (usedspace > 0) {
+		/* Calculate how much free space is available in the buffer */
+		freespace = SHA512_BLOCK_LENGTH - usedspace;
+
+		if (len >= freespace) {
+			/* Fill the buffer completely and process it */
+			bcopy(data, &context->buffer[usedspace], freespace);
+			ADDINC128(context->bitcount, freespace << 3);
+			len -= freespace;
+			data += freespace;
+			SHA512_Transform(context, (sha2_word64*)context->buffer);
+		} else {
+			/* The buffer is not yet full */
+			bcopy(data, &context->buffer[usedspace], len);
+			ADDINC128(context->bitcount, len << 3);
+			/* Clean up: */
+			usedspace = freespace = 0;
+			return;
+		}
+	}
+	while (len >= SHA512_BLOCK_LENGTH) {
+		/* Process as many complete blocks as we can */
+		SHA512_Transform(context, (const sha2_word64*)data);
+		ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
+		len -= SHA512_BLOCK_LENGTH;
+		data += SHA512_BLOCK_LENGTH;
+	}
+	if (len > 0) {
+		/* There's left-overs, so save 'em */
+		bcopy(data, context->buffer, len);
+		ADDINC128(context->bitcount, len << 3);
+	}
+	/* Clean up: */
+	usedspace = freespace = 0;
+}
+
+void SHA512_Last(SHA512_CTX* context) {
+	unsigned int	usedspace;
+
+	usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+	/* Convert FROM host byte order */
+	REVERSE64(context->bitcount[0],context->bitcount[0]);
+	REVERSE64(context->bitcount[1],context->bitcount[1]);
+#endif
+	if (usedspace > 0) {
+		/* Begin padding with a 1 bit: */
+		context->buffer[usedspace++] = 0x80;
+
+		if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
+			/* Set-up for the last transform: */
+			bzero(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace);
+		} else {
+			if (usedspace < SHA512_BLOCK_LENGTH) {
+				bzero(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace);
+			}
+			/* Do second-to-last transform: */
+			SHA512_Transform(context, (sha2_word64*)context->buffer);
+
+			/* And set-up for the last transform: */
+			bzero(context->buffer, SHA512_BLOCK_LENGTH - 2);
+		}
+	} else {
+		/* Prepare for final transform: */
+		bzero(context->buffer, SHA512_SHORT_BLOCK_LENGTH);
+
+		/* Begin padding with a 1 bit: */
+		*context->buffer = 0x80;
+	}
+	/* Store the length of input data (in bits): */
+	*(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1];
+	*(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0];
+
+	/* Final transform: */
+	SHA512_Transform(context, (sha2_word64*)context->buffer);
+}
+
+void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
+	sha2_word64	*d = (sha2_word64*)digest;
+
+	/* Sanity check: */
+	assert(context != (SHA512_CTX*)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (sha2_byte*)0) {
+		SHA512_Last(context);
+
+		/* Save the hash data for output: */
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+		{
+			/* Convert TO host byte order */
+			int	j;
+			for (j = 0; j < 8; j++) {
+				REVERSE64(context->state[j],context->state[j]);
+				*d++ = context->state[j];
+			}
+		}
+#else
+		bcopy(context->state, d, SHA512_DIGEST_LENGTH);
+#endif
+	}
+
+	/* Zero out state data */
+	bzero(context, sizeof(context));
+}
+
+char *SHA512_End(SHA512_CTX* context, char buffer[]) {
+	sha2_byte	digest[SHA512_DIGEST_LENGTH], *d = digest;
+	int		i;
+
+	/* Sanity check: */
+	assert(context != (SHA512_CTX*)0);
+
+	if (buffer != (char*)0) {
+		SHA512_Final(digest, context);
+
+		for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+			*buffer++ = sha2_hex_digits[*d & 0x0f];
+			d++;
+		}
+		*buffer = (char)0;
+	} else {
+		bzero(context, sizeof(context));
+	}
+	bzero(digest, SHA512_DIGEST_LENGTH);
+	return buffer;
+}
+
+char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) {
+	SHA512_CTX	context;
+
+	SHA512_Init(&context);
+	SHA512_Update(&context, data, len);
+	return SHA512_End(&context, digest);
+}
+
+/*** SHA-384: *********************************************************/
+void SHA384_Init(SHA384_CTX* context) {
+	if (context == (SHA384_CTX*)0) {
+		return;
+	}
+	bcopy(sha384_initial_hash_value, context->state, SHA512_DIGEST_LENGTH);
+	bzero(context->buffer, SHA384_BLOCK_LENGTH);
+	context->bitcount[0] = context->bitcount[1] = 0;
+}
+
+void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) {
+	SHA512_Update((SHA512_CTX*)context, data, len);
+}
+
+void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
+	sha2_word64	*d = (sha2_word64*)digest;
+
+	/* Sanity check: */
+	assert(context != (SHA384_CTX*)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (sha2_byte*)0) {
+		SHA512_Last((SHA512_CTX*)context);
+
+		/* Save the hash data for output: */
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+		{
+			/* Convert TO host byte order */
+			int	j;
+			for (j = 0; j < 6; j++) {
+				REVERSE64(context->state[j],context->state[j]);
+				*d++ = context->state[j];
+			}
+		}
+#else
+		bcopy(context->state, d, SHA384_DIGEST_LENGTH);
+#endif
+	}
+
+	/* Zero out state data */
+	bzero(context, sizeof(context));
+}
+
+char *SHA384_End(SHA384_CTX* context, char buffer[]) {
+	sha2_byte	digest[SHA384_DIGEST_LENGTH], *d = digest;
+	int		i;
+
+	/* Sanity check: */
+	assert(context != (SHA384_CTX*)0);
+
+	if (buffer != (char*)0) {
+		SHA384_Final(digest, context);
+
+		for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+			*buffer++ = sha2_hex_digits[*d & 0x0f];
+			d++;
+		}
+		*buffer = (char)0;
+	} else {
+		bzero(context, sizeof(context));
+	}
+	bzero(digest, SHA384_DIGEST_LENGTH);
+	return buffer;
+}
+
+char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) {
+	SHA384_CTX	context;
+
+	SHA384_Init(&context);
+	SHA384_Update(&context, data, len);
+	return SHA384_End(&context, digest);
+}
+
+#endif /* !NO_64BIT */
+
+/*
+ * $PchId: sha2.c,v 1.1 2005/06/28 14:29:23 philip Exp $
+ */
Index: /trunk/minix/drivers/random/sha2.h
===================================================================
--- /trunk/minix/drivers/random/sha2.h	(revision 9)
+++ /trunk/minix/drivers/random/sha2.h	(revision 9)
@@ -0,0 +1,165 @@
+/*	$FreeBSD: src/sys/crypto/sha2/sha2.h,v 1.1.2.1 2001/07/03 11:01:36 ume Exp $	*/
+/*	$KAME: sha2.h,v 1.3 2001/03/12 08:27:48 itojun Exp $	*/
+
+/*
+ * sha2.h
+ *
+ * Version 1.0.0beta1
+ *
+ * Written by Aaron D. Gifford <me@aarongifford.com>
+ *
+ * Copyright 2000 Aaron D. Gifford.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef __SHA2_H__
+#define __SHA2_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*** SHA-256/384/512 Various Length Definitions ***********************/
+#define SHA256_BLOCK_LENGTH		64
+#define SHA256_DIGEST_LENGTH		32
+#define SHA256_DIGEST_STRING_LENGTH	(SHA256_DIGEST_LENGTH * 2 + 1)
+#define SHA384_BLOCK_LENGTH		128
+#define SHA384_DIGEST_LENGTH		48
+#define SHA384_DIGEST_STRING_LENGTH	(SHA384_DIGEST_LENGTH * 2 + 1)
+#define SHA512_BLOCK_LENGTH		128
+#define SHA512_DIGEST_LENGTH		64
+#define SHA512_DIGEST_STRING_LENGTH	(SHA512_DIGEST_LENGTH * 2 + 1)
+
+#ifdef __minix
+#include <assert.h>
+#include <string.h>
+#include <sys/types.h>
+#include <minix/u64.h>
+
+typedef u8_t u_int8_t;	/* 1-byte  (8-bits)  */
+typedef u32_t u_int32_t;	/* 4-bytes (32-bits) */
+typedef u64_t u_int64_t;	/* 8-bytes (64-bits) */
+
+#ifndef __P
+#define __P(x) x
+#endif
+
+#define NO_64BIT	1
+#define MINIX_64BIT	1
+
+#define SHA2_BYTE_ORDER		0x04030201
+#define SHA2_LITTLE_ENDIAN	0x04030201
+#define SHA2_BIG_ENDIAN		0x01020204
+#define bcopy(s,d,l)	(memmove((d),(s),(l)))
+#define bzero(d,l)	(memset((d),'\0',(l)))
+#endif
+
+/*** SHA-256/384/512 Context Structures *******************************/
+/* NOTE: If your architecture does not define either u_intXX_t types or
+ * uintXX_t (from inttypes.h), you may need to define things by hand
+ * for your system:
+ */
+#if 0
+typedef unsigned char u_int8_t;		/* 1-byte  (8-bits)  */
+typedef unsigned int u_int32_t;		/* 4-bytes (32-bits) */
+typedef unsigned long long u_int64_t;	/* 8-bytes (64-bits) */
+#endif
+/*
+ * Most BSD systems already define u_intXX_t types, as does Linux.
+ * Some systems, however, like Compaq's Tru64 Unix instead can use
+ * uintXX_t types defined by very recent ANSI C standards and included
+ * in the file:
+ *
+ *   #include <inttypes.h>
+ *
+ * If you choose to use <inttypes.h> then please define: 
+ *
+ *   #define SHA2_USE_INTTYPES_H
+ *
+ * Or on the command line during compile:
+ *
+ *   cc -DSHA2_USE_INTTYPES_H ...
+ */
+#if 0 /*def SHA2_USE_INTTYPES_H*/
+
+typedef struct _SHA256_CTX {
+	uint32_t	state[8];
+	uint64_t	bitcount;
+	uint8_t	buffer[SHA256_BLOCK_LENGTH];
+} SHA256_CTX;
+typedef struct _SHA512_CTX {
+	uint64_t	state[8];
+	uint64_t	bitcount[2];
+	uint8_t	buffer[SHA512_BLOCK_LENGTH];
+} SHA512_CTX;
+
+#else /* SHA2_USE_INTTYPES_H */
+
+typedef struct _SHA256_CTX {
+	u_int32_t	state[8];
+	u_int64_t	bitcount;
+	u_int8_t	buffer[SHA256_BLOCK_LENGTH];
+} SHA256_CTX;
+typedef struct _SHA512_CTX {
+	u_int64_t	state[8];
+	u_int64_t	bitcount[2];
+	u_int8_t	buffer[SHA512_BLOCK_LENGTH];
+} SHA512_CTX;
+
+#endif /* SHA2_USE_INTTYPES_H */
+
+typedef SHA512_CTX SHA384_CTX;
+
+/*** SHA-256/384/512 Function Prototypes ******************************/
+
+void SHA256_Init __P((SHA256_CTX *));
+void SHA256_Update __P((SHA256_CTX*, const u_int8_t*, size_t));
+void SHA256_Final __P((u_int8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*));
+char* SHA256_End __P((SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]));
+char* SHA256_Data __P((const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]));
+
+void SHA384_Init __P((SHA384_CTX*));
+void SHA384_Update __P((SHA384_CTX*, const u_int8_t*, size_t));
+void SHA384_Final __P((u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*));
+char* SHA384_End __P((SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]));
+char* SHA384_Data __P((const u_int8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]));
+
+void SHA512_Init __P((SHA512_CTX*));
+void SHA512_Update __P((SHA512_CTX*, const u_int8_t*, size_t));
+void SHA512_Final __P((u_int8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*));
+char* SHA512_End __P((SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]));
+char* SHA512_Data __P((const u_int8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]));
+
+#ifdef	__cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __SHA2_H__ */
+
+/*
+ * $PchId: sha2.h,v 1.1 2005/06/28 14:29:33 philip Exp $
+ */
Index: /trunk/minix/drivers/rescue/.depend
===================================================================
--- /trunk/minix/drivers/rescue/.depend	(revision 9)
+++ /trunk/minix/drivers/rescue/.depend	(revision 9)
@@ -0,0 +1,93 @@
+
+rescue.o:	../../kernel/config.h
+rescue.o:	../../kernel/const.h
+rescue.o:	../../kernel/type.h
+rescue.o:	../drivers.h
+rescue.o:	../libdriver/driver.h
+rescue.o:	/usr/include/ansi.h
+rescue.o:	/usr/include/errno.h
+rescue.o:	/usr/include/ibm/bios.h
+rescue.o:	/usr/include/ibm/cpu.h
+rescue.o:	/usr/include/ibm/interrupt.h
+rescue.o:	/usr/include/ibm/ports.h
+rescue.o:	/usr/include/limits.h
+rescue.o:	/usr/include/minix/bitmap.h
+rescue.o:	/usr/include/minix/callnr.h
+rescue.o:	/usr/include/minix/com.h
+rescue.o:	/usr/include/minix/config.h
+rescue.o:	/usr/include/minix/const.h
+rescue.o:	/usr/include/minix/devio.h
+rescue.o:	/usr/include/minix/dmap.h
+rescue.o:	/usr/include/minix/ipc.h
+rescue.o:	/usr/include/minix/partition.h
+rescue.o:	/usr/include/minix/sys_config.h
+rescue.o:	/usr/include/minix/syslib.h
+rescue.o:	/usr/include/minix/sysutil.h
+rescue.o:	/usr/include/minix/type.h
+rescue.o:	/usr/include/minix/u64.h
+rescue.o:	/usr/include/signal.h
+rescue.o:	/usr/include/stddef.h
+rescue.o:	/usr/include/stdlib.h
+rescue.o:	/usr/include/string.h
+rescue.o:	/usr/include/sys/dir.h
+rescue.o:	/usr/include/sys/types.h
+rescue.o:	/usr/include/unistd.h
+rescue.o:	rescue.c
+
+../libdriver/driver.o:	../libdriver/../drivers.h
+../libdriver/driver.o:	../libdriver/driver.c
+../libdriver/driver.o:	../libdriver/driver.h
+../libdriver/driver.o:	/usr/include/ansi.h
+../libdriver/driver.o:	/usr/include/errno.h
+../libdriver/driver.o:	/usr/include/ibm/bios.h
+../libdriver/driver.o:	/usr/include/ibm/interrupt.h
+../libdriver/driver.o:	/usr/include/ibm/ports.h
+../libdriver/driver.o:	/usr/include/limits.h
+../libdriver/driver.o:	/usr/include/minix/bitmap.h
+../libdriver/driver.o:	/usr/include/minix/callnr.h
+../libdriver/driver.o:	/usr/include/minix/com.h
+../libdriver/driver.o:	/usr/include/minix/config.h
+../libdriver/driver.o:	/usr/include/minix/const.h
+../libdriver/driver.o:	/usr/include/minix/devio.h
+../libdriver/driver.o:	/usr/include/minix/dmap.h
+../libdriver/driver.o:	/usr/include/minix/ioctl.h
+../libdriver/driver.o:	/usr/include/minix/ipc.h
+../libdriver/driver.o:	/usr/include/minix/partition.h
+../libdriver/driver.o:	/usr/include/minix/sys_config.h
+../libdriver/driver.o:	/usr/include/minix/syslib.h
+../libdriver/driver.o:	/usr/include/minix/sysutil.h
+../libdriver/driver.o:	/usr/include/minix/type.h
+../libdriver/driver.o:	/usr/include/minix/u64.h
+../libdriver/driver.o:	/usr/include/signal.h
+../libdriver/driver.o:	/usr/include/stddef.h
+../libdriver/driver.o:	/usr/include/stdlib.h
+../libdriver/driver.o:	/usr/include/string.h
+../libdriver/driver.o:	/usr/include/sys/dir.h
+../libdriver/driver.o:	/usr/include/sys/ioc_disk.h
+../libdriver/driver.o:	/usr/include/sys/types.h
+../libdriver/driver.o:	/usr/include/unistd.h
+
+../libdriver/drvlib.o:	../libdriver/driver.h
+../libdriver/drvlib.o:	../libdriver/drvlib.c
+../libdriver/drvlib.o:	../libdriver/drvlib.h
+../libdriver/drvlib.o:	/usr/include/ansi.h
+../libdriver/drvlib.o:	/usr/include/errno.h
+../libdriver/drvlib.o:	/usr/include/ibm/partition.h
+../libdriver/drvlib.o:	/usr/include/limits.h
+../libdriver/drvlib.o:	/usr/include/minix/callnr.h
+../libdriver/drvlib.o:	/usr/include/minix/com.h
+../libdriver/drvlib.o:	/usr/include/minix/config.h
+../libdriver/drvlib.o:	/usr/include/minix/const.h
+../libdriver/drvlib.o:	/usr/include/minix/devio.h
+../libdriver/drvlib.o:	/usr/include/minix/ipc.h
+../libdriver/drvlib.o:	/usr/include/minix/partition.h
+../libdriver/drvlib.o:	/usr/include/minix/sys_config.h
+../libdriver/drvlib.o:	/usr/include/minix/syslib.h
+../libdriver/drvlib.o:	/usr/include/minix/sysutil.h
+../libdriver/drvlib.o:	/usr/include/minix/type.h
+../libdriver/drvlib.o:	/usr/include/minix/u64.h
+../libdriver/drvlib.o:	/usr/include/stddef.h
+../libdriver/drvlib.o:	/usr/include/string.h
+../libdriver/drvlib.o:	/usr/include/sys/dir.h
+../libdriver/drvlib.o:	/usr/include/sys/types.h
+../libdriver/drvlib.o:	/usr/include/unistd.h
Index: /trunk/minix/drivers/rescue/Makefile
===================================================================
--- /trunk/minix/drivers/rescue/Makefile	(revision 9)
+++ /trunk/minix/drivers/rescue/Makefile	(revision 9)
@@ -0,0 +1,48 @@
+# Makefile for rescue driver 
+DRIVER = rescue
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+MAKE = exec make
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsys -lsysutil
+
+OBJ = rescue.o
+LIBDRIVER = $d/libdriver/driver.o
+
+
+# build local binary
+all build:	$(DRIVER)
+$(DRIVER):	$(OBJ) $(LIBDRIVER)
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBDRIVER) $(LIBS)
+	install -S 1024w $(DRIVER)
+
+$(LIBDRIVER): 
+	cd $d/libdriver && $(MAKE) 
+
+
+# install with other drivers
+install:	/sbin/$(DRIVER)
+/sbin/$(DRIVER):	$(DRIVER)
+	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f $(DRIVER) *.o *.bak 
+
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c ../libdriver/*.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/rescue/rescue.c
===================================================================
--- /trunk/minix/drivers/rescue/rescue.c	(revision 9)
+++ /trunk/minix/drivers/rescue/rescue.c	(revision 9)
@@ -0,0 +1,222 @@
+/* This file contains the rescue device driver (/dev/rescue)
+ *
+ *  Changes:
+ *	Oct 21, 1992	created  (Jorrit N. Herder)
+ */
+
+#include "../drivers.h"
+#include "../libdriver/driver.h"
+#include "../../kernel/const.h"
+#include "../../kernel/config.h"
+#include "../../kernel/type.h"
+
+#define VERBOSE	 	   0		/* enable/ disable messages */
+#define NR_DEVS            1		/* number of rescue devices */
+#define RESCUE_KBYTES	 128		/* default size in kilobytes */
+
+PRIVATE struct device m_geom[NR_DEVS];  /* base and size of each device */
+PRIVATE int m_seg[NR_DEVS];  		/* segment index of each device */
+PRIVATE int m_device;			/* current device */
+
+extern int errno;			/* error number for PM calls */
+
+FORWARD _PROTOTYPE( void m_init, (int argc, char **argv) );
+FORWARD _PROTOTYPE( char *m_name, (void) 				);
+FORWARD _PROTOTYPE( struct device *m_prepare, (int device) 		);
+FORWARD _PROTOTYPE( int m_transfer, (int proc_nr, int opcode, off_t position,
+					iovec_t *iov, unsigned nr_req) 	);
+FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr) 	);
+FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) 		);
+
+/* Entry points to this driver. */
+PRIVATE struct driver m_dtab = {
+  m_name,	/* current device's name */
+  m_do_open,	/* open or mount */
+  do_nop,	/* nothing on a close */
+  do_diocntl,	/* standard I/O controls */
+  m_prepare,	/* prepare for I/O on a given minor device */
+  m_transfer,	/* do the I/O */
+  nop_cleanup,	/* no need to clean up */
+  m_geometry,	/* memory device "geometry" */
+  nop_signal,	/* system signals */
+  nop_alarm,
+  nop_cancel,
+  nop_select,
+  NULL,
+  NULL
+};
+
+
+/*===========================================================================*
+ *				   main 				     *
+ *===========================================================================*/
+PUBLIC int main(int argc, char **argv)
+{
+/* Main program. Initialize the rescue driver and start the main loop. */
+  m_init(argc, argv);			
+  driver_task(&m_dtab);		
+  return(OK);				
+}
+
+/*===========================================================================*
+ *				 m_name					     *
+ *===========================================================================*/
+PRIVATE char *m_name()
+{
+/* Return a name for the current device. */
+  static char name[] = "rescue";
+  return name;  
+}
+
+/*===========================================================================*
+ *				m_prepare				     *
+ *===========================================================================*/
+PRIVATE struct device *m_prepare(device)
+int device;
+{
+/* Prepare for I/O on a device: check if the minor device number is ok. */
+  if (device < 0 || device >= NR_DEVS) return(NIL_DEV);
+  m_device = device;
+
+  return(&m_geom[device]);
+}
+
+/*===========================================================================*
+ *				m_transfer				     *
+ *===========================================================================*/
+PRIVATE int m_transfer(proc_nr, opcode, position, iov, nr_req)
+int proc_nr;			/* process doing the request */
+int opcode;			/* DEV_GATHER or DEV_SCATTER */
+off_t position;			/* offset on device to read or write */
+iovec_t *iov;			/* pointer to read or write request vector */
+unsigned nr_req;		/* length of request vector */
+{
+/* Read or write one the driver's minor devices. */
+  int seg;
+  unsigned count, left, chunk;
+  vir_bytes user_vir;
+  struct device *dv;
+  unsigned long dv_size;
+  int s;
+
+  /* Get and check minor device number. */
+  if ((unsigned) m_device > NR_DEVS - 1) return(ENXIO);
+  dv = &m_geom[m_device];
+  dv_size = cv64ul(dv->dv_size);
+
+  while (nr_req > 0) {
+
+	/* How much to transfer and where to / from. */
+	count = iov->iov_size;
+	user_vir = iov->iov_addr;
+
+	/* Virtual copying. For rescue device. */
+	if (position >= dv_size) return(OK); 	/* check for EOF */
+	if (position + count > dv_size) count = dv_size - position;
+	seg = m_seg[m_device];
+
+	if (opcode == DEV_GATHER) {			/* copy actual data */
+	    sys_vircopy(SELF,seg,position, proc_nr,D,user_vir, count);
+	} else {
+	    sys_vircopy(proc_nr,D,user_vir, SELF,seg,position, count);
+	}
+
+	/* Book the number of bytes transferred. */
+	position += count;
+	iov->iov_addr += count;
+  	if ((iov->iov_size -= count) == 0) { iov++; nr_req--; }
+
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *				m_do_open				     *
+ *===========================================================================*/
+PRIVATE int m_do_open(dp, m_ptr)
+struct driver *dp;
+message *m_ptr;
+{
+/* Check device number on open. */
+  if (m_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				m_init					     *
+ *===========================================================================*/
+PRIVATE void m_init(argc,argv)
+int argc;
+char **argv;
+{
+  /* Initialize this task. All minor devices are initialized one by one. */
+  phys_bytes rescue_size;
+  phys_bytes rescue_base;
+  message m;
+  int i, s;
+
+  /* Initialize all rescue devices in a loop. */
+  for (i=0; i< NR_DEVS; i++) {
+
+      /* Determine size and base of rescue disks. See if rescue disk details 
+       * exist in the data store. If no memory for the rescue disk was claimed 
+       * yet, do it below. 
+       */
+      m.DS_KEY = (RESCUE_MAJOR << 8) + i;
+      if (OK == (s = _taskcall(DS_PROC_NR, DS_RETRIEVE, &m))) {
+          rescue_size = m.DS_VAL_L1;
+          rescue_base = m.DS_VAL_L2;
+      }
+      else {					/* no details known */
+          if (argc>i+1) rescue_size = atoi(argv[i+1]) * 1024;
+          else 		rescue_size = RESCUE_KBYTES * 1024;
+
+          if (allocmem(rescue_size, &rescue_base) < 0) {
+              report("RESCUE", "warning, allocmem failed", errno);
+              rescue_size = 0;
+          }
+      }
+
+      /* Now that we have the base and size of the rescue disk, set up all
+       * data structures if the rescue has a positive (nonzero) size. 
+       */
+      if (rescue_size > 0) {
+
+          /* Create a new remote segment to make virtual copies. */ 
+          if (OK != (s=sys_segctl(&m_seg[i], (u16_t *) &s, 
+                  (vir_bytes *) &s, rescue_base, rescue_size))) {
+              panic("RESCUE","Couldn't install remote segment.",s);
+          }
+
+          /* Set the device geometry for the outside world. */
+          m_geom[i].dv_base = cvul64(rescue_base);
+          m_geom[i].dv_size = cvul64(rescue_size);
+
+          /* Store the values in the data store for future retrieval. */
+          m.DS_KEY = (RESCUE_MAJOR << 8) + i;
+          m.DS_VAL_L1 = rescue_size;
+          m.DS_VAL_L2 = rescue_base;
+          if (OK != (s = _taskcall(DS_PROC_NR, DS_PUBLISH, &m))) {
+              panic("RESCUE","Couldn't store rescue disk details at DS.",s);
+          }
+
+#if VERBOSE
+          printf("RESCUE disk %d (size %u/base %u) initialized\n",
+              i, rescue_size, rescue_base);
+#endif
+      }
+  }
+}
+
+/*===========================================================================*
+ *				m_geometry				     *
+ *===========================================================================*/
+PRIVATE void m_geometry(entry)
+struct partition *entry;
+{
+  /* Memory devices don't have a geometry, but the outside world insists. */
+  entry->cylinders = div64u(m_geom[m_device].dv_size, SECTOR_SIZE) / (64 * 32);
+  entry->heads = 64;
+  entry->sectors = 32;
+}
+
Index: /trunk/minix/drivers/rtl8139/.depend
===================================================================
--- /trunk/minix/drivers/rtl8139/.depend	(revision 9)
+++ /trunk/minix/drivers/rtl8139/.depend	(revision 9)
@@ -0,0 +1,45 @@
+
+rtl8139.o:	../../kernel/config.h
+rtl8139.o:	../../kernel/const.h
+rtl8139.o:	../../kernel/type.h
+rtl8139.o:	../drivers.h
+rtl8139.o:	/usr/include/ansi.h
+rtl8139.o:	/usr/include/assert.h
+rtl8139.o:	/usr/include/errno.h
+rtl8139.o:	/usr/include/fcntl.h
+rtl8139.o:	/usr/include/ibm/bios.h
+rtl8139.o:	/usr/include/ibm/cpu.h
+rtl8139.o:	/usr/include/ibm/interrupt.h
+rtl8139.o:	/usr/include/ibm/pci.h
+rtl8139.o:	/usr/include/ibm/portio.h
+rtl8139.o:	/usr/include/ibm/ports.h
+rtl8139.o:	/usr/include/limits.h
+rtl8139.o:	/usr/include/minix/bitmap.h
+rtl8139.o:	/usr/include/minix/callnr.h
+rtl8139.o:	/usr/include/minix/com.h
+rtl8139.o:	/usr/include/minix/config.h
+rtl8139.o:	/usr/include/minix/const.h
+rtl8139.o:	/usr/include/minix/devio.h
+rtl8139.o:	/usr/include/minix/dmap.h
+rtl8139.o:	/usr/include/minix/ioctl.h
+rtl8139.o:	/usr/include/minix/ipc.h
+rtl8139.o:	/usr/include/minix/keymap.h
+rtl8139.o:	/usr/include/minix/sys_config.h
+rtl8139.o:	/usr/include/minix/syslib.h
+rtl8139.o:	/usr/include/minix/sysutil.h
+rtl8139.o:	/usr/include/minix/type.h
+rtl8139.o:	/usr/include/net/gen/eth_io.h
+rtl8139.o:	/usr/include/net/gen/ether.h
+rtl8139.o:	/usr/include/net/hton.h
+rtl8139.o:	/usr/include/signal.h
+rtl8139.o:	/usr/include/stddef.h
+rtl8139.o:	/usr/include/stdio.h
+rtl8139.o:	/usr/include/stdlib.h
+rtl8139.o:	/usr/include/string.h
+rtl8139.o:	/usr/include/sys/dir.h
+rtl8139.o:	/usr/include/sys/ioc_memory.h
+rtl8139.o:	/usr/include/sys/types.h
+rtl8139.o:	/usr/include/timers.h
+rtl8139.o:	/usr/include/unistd.h
+rtl8139.o:	rtl8139.c
+rtl8139.o:	rtl8139.h
Index: /trunk/minix/drivers/rtl8139/Makefile
===================================================================
--- /trunk/minix/drivers/rtl8139/Makefile	(revision 9)
+++ /trunk/minix/drivers/rtl8139/Makefile	(revision 9)
@@ -0,0 +1,41 @@
+# Makefile for the Realtek RTL8139 ethernet driver (RTL8139)
+DRIVER = rtl8139
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+MAKE = exec make
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsys -lsysutil -ltimers
+
+OBJ = rtl8139.o 
+
+# build local binary
+all build:	$(DRIVER)
+$(DRIVER):	$(OBJ) 
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+	install -S 50kw $(DRIVER)
+
+# install with other drivers
+install:	/usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER):	$(DRIVER)
+	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f $(DRIVER) *.o *.bak 
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/rtl8139/rtl8139.c
===================================================================
--- /trunk/minix/drivers/rtl8139/rtl8139.c	(revision 9)
+++ /trunk/minix/drivers/rtl8139/rtl8139.c	(revision 9)
@@ -0,0 +1,2675 @@
+/*
+ * rtl8139.c
+ *
+ * This file contains a ethernet device driver for Realtek rtl8139 based
+ * ethernet cards.
+ *
+ * The valid messages and their parameters are:
+ *
+ *   m_type	  DL_PORT    DL_PROC   DL_COUNT   DL_MODE   DL_ADDR
+ * |------------+----------+---------+----------+---------+---------|
+ * | HARD_INT	|          |         |          |         |         |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_WRITE	| port nr  | proc nr | count    | mode    | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_WRITEV	| port nr  | proc nr | count    | mode    | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_READ	| port nr  | proc nr | count    |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_READV	| port nr  | proc nr | count    |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_INIT	| port nr  | proc nr | mode     |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_GETSTAT	| port nr  | proc nr |          |         | address |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_GETNAME	|          |         |          |         |         |
+ * |------------|----------|---------|----------|---------|---------|
+ * | DL_STOP	| port_nr  |         |          |         |	    |
+ * |------------|----------|---------|----------|---------|---------|
+ *
+ * The messages sent are:
+ *
+ *   m-type	  DL_POR T   DL_PROC   DL_COUNT   DL_STAT   DL_CLCK
+ * |------------|----------|---------|----------|---------|---------|
+ * |DL_TASK_REPL| port nr  | proc nr | rd-count | err|stat| clock   |
+ * |------------|----------|---------|----------|---------|---------|
+ *
+ *   m_type	  m3_i1     m3_i2       m3_ca1
+ * |------------+---------+-----------+---------------|
+ * |DL_INIT_REPL| port nr | last port | ethernet addr |
+ * |------------|---------|-----------|---------------|
+ *
+ * Created:	Aug 2003 by Philip Homburg <philip@cs.vu.nl>
+ * Changes:
+ *   Aug 15, 2004   sync alarms replace watchdogs timers  (Jorrit N. Herder)
+ *   May 02, 2004   flag alarms replace micro_elapsed()  (Jorrit N. Herder)
+ *
+ */
+
+#include "../drivers.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+#include <minix/com.h>
+#include <minix/keymap.h>
+#include <minix/syslib.h>
+#include <minix/type.h>
+#include <minix/sysutil.h>
+#include <timers.h>
+#include <ibm/portio.h>
+#include <net/hton.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include <ibm/pci.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/ioc_memory.h>
+#include "../../kernel/const.h"
+#include "../../kernel/config.h"
+#include "../../kernel/type.h"
+
+#define tmra_ut			timer_t
+#define tmra_inittimer(tp)	tmr_inittimer(tp)
+#define Proc_number(p)		proc_number(p)
+#define debug			0
+#define printW()		((void)0)
+#define vm_1phys2bus(p)		(p)
+
+#define VERBOSE		1	/* display message during init */
+
+#include "rtl8139.h"
+
+#define RX_BUFSIZE	RL_RCR_RBLEN_64K_SIZE
+#define RX_BUFBITS	RL_RCR_RBLEN_64K
+#define N_TX_BUF	RL_N_TX
+
+#define RE_PORT_NR	1		/* Minix */
+
+/* I/O vectors are handled IOVEC_NR entries at a time. */
+#define IOVEC_NR	16
+
+/* Configuration */
+#define RL_ENVVAR	"RTLETH"
+
+PRIVATE struct pcitab
+{
+	u16_t vid;
+	u16_t did;
+	int checkclass;
+} pcitab[]=
+{
+	{ 0x10ec, 0x8139, 0 },		/* Realtek RTL8139 */
+	{ 0x1186, 0x1300, 0 },		/* D-Link RTL8139 */
+
+	{ 0x0000, 0x0000, 0 }
+};
+
+typedef struct re
+{
+	port_t re_base_port;
+	int re_irq;
+	int re_mode;
+	int re_flags;
+	int re_client;
+	int re_link_up;
+	int re_got_int;
+	int re_send_int;
+	int re_report_link;
+	int re_clear_rx;
+	int re_need_reset;
+	int re_tx_alive;
+	char *re_model;
+
+	/* Rx */
+	phys_bytes re_rx_buf;
+	char  *v_re_rx_buf;
+	vir_bytes re_read_s;
+
+	/* Tx */
+	int re_tx_head;
+	int re_tx_tail;
+	struct
+	{
+		int ret_busy;
+		phys_bytes ret_buf;
+		char * v_ret_buf;
+	} re_tx[N_TX_BUF];
+	u32_t re_ertxth;	/* Early Tx Threshold */
+
+	/* PCI related */
+	int re_seen;			/* TRUE iff device available */
+	u8_t re_pcibus;	
+	u8_t re_pcidev;	
+	u8_t re_pcifunc;	
+
+	/* 'large' items */
+	int re_hook_id;			/* IRQ hook id at kernel */
+	eth_stat_t re_stat;
+	ether_addr_t re_address;
+	message re_rx_mess;
+	message re_tx_mess;
+	char re_name[sizeof("rtl8139#n")];
+	iovec_t re_iovec[IOVEC_NR];
+}
+re_t;
+
+#define REM_DISABLED	0x0
+#define REM_ENABLED	0x1
+
+#define REF_PACK_SENT	0x001
+#define REF_PACK_RECV	0x002
+#define REF_SEND_AVAIL	0x004
+#define REF_READING	0x010
+#define REF_EMPTY	0x000
+#define REF_PROMISC	0x040
+#define REF_MULTI	0x080
+#define REF_BROAD	0x100
+#define REF_ENABLED	0x200
+
+static re_t re_table[RE_PORT_NR];
+
+static u16_t eth_ign_proto;
+static tmra_ut rl_watchdog;
+
+FORWARD _PROTOTYPE( unsigned my_inb, (U16_t port) );
+FORWARD _PROTOTYPE( unsigned my_inw, (U16_t port) );
+FORWARD _PROTOTYPE( unsigned my_inl, (U16_t port) );
+static unsigned my_inb(U16_t port) {
+	u32_t value;
+	int s;
+	if ((s=sys_inb(port, &value)) !=OK)
+		printf("RTL8139: warning, sys_inb failed: %d\n", s);
+	return value;
+}
+static unsigned my_inw(U16_t port) {
+	u32_t value;
+	int s;
+	if ((s=sys_inw(port, &value)) !=OK)
+		printf("RTL8139: warning, sys_inw failed: %d\n", s);
+	return value;
+}
+static unsigned my_inl(U16_t port) {
+	U32_t value;
+	int s;
+	if ((s=sys_inl(port, &value)) !=OK)
+		printf("RTL8139: warning, sys_inl failed: %d\n", s);
+	return value;
+}
+#define rl_inb(port, offset)	(my_inb((port) + (offset)))
+#define rl_inw(port, offset)	(my_inw((port) + (offset)))
+#define rl_inl(port, offset)	(my_inl((port) + (offset)))
+
+FORWARD _PROTOTYPE( void my_outb, (U16_t port, U8_t value) );
+FORWARD _PROTOTYPE( void my_outw, (U16_t port, U16_t value) );
+FORWARD _PROTOTYPE( void my_outl, (U16_t port, U32_t value) );
+static void my_outb(U16_t port, U8_t value) {
+	int s;
+	if ((s=sys_outb(port, value)) !=OK)
+		printf("RTL8139: warning, sys_outb failed: %d\n", s);
+}
+static void my_outw(U16_t port, U16_t value) {
+	int s;
+	if ((s=sys_outw(port, value)) !=OK)
+		printf("RTL8139: warning, sys_outw failed: %d\n", s);
+}
+static void my_outl(U16_t port, U32_t value) {
+	int s;
+	if ((s=sys_outl(port, value)) !=OK)
+		printf("RTL8139: warning, sys_outl failed: %d\n", s);
+}
+#define rl_outb(port, offset, value)	(my_outb((port) + (offset), (value)))
+#define rl_outw(port, offset, value)	(my_outw((port) + (offset), (value)))
+#define rl_outl(port, offset, value)	(my_outl((port) + (offset), (value)))
+
+_PROTOTYPE( static void sig_handler, (void)				);
+_PROTOTYPE( static void rl_init, (message *mp)				);
+_PROTOTYPE( static void rl_pci_conf, (void)				);
+_PROTOTYPE( static int rl_probe, (re_t *rep)				);
+_PROTOTYPE( static void rl_conf_hw, (re_t *rep)				);
+_PROTOTYPE( static void rl_init_buf, (re_t *rep)				);
+_PROTOTYPE( static void rl_init_hw, (re_t *rep)				);
+_PROTOTYPE( static void rl_reset_hw, (re_t *rep)			);
+_PROTOTYPE( static void rl_confaddr, (re_t *rep)			);
+_PROTOTYPE( static void rl_rec_mode, (re_t *rep)			);
+_PROTOTYPE( static void rl_readv, (message *mp, int from_int, 
+							int vectored)	);
+_PROTOTYPE( static void rl_writev, (message *mp, int from_int,
+							int vectored)	);
+_PROTOTYPE( static void rl_check_ints, (re_t *rep)			);
+_PROTOTYPE( static void rl_report_link, (re_t *rep)			);
+_PROTOTYPE( static void mii_print_techab, (U16_t techab)		);
+_PROTOTYPE( static void mii_print_stat_speed, (U16_t stat,
+							U16_t extstat)	);
+_PROTOTYPE( static void rl_clear_rx, (re_t *rep)			);
+_PROTOTYPE( static void rl_do_reset, (re_t *rep)			);
+_PROTOTYPE( static void rl_getstat, (message *mp)			);
+_PROTOTYPE( static void rl_getname, (message *mp)			);
+_PROTOTYPE( static void reply, (re_t *rep, int err, int may_block)	);
+_PROTOTYPE( static void mess_reply, (message *req, message *reply)	);
+_PROTOTYPE( static void put_userdata, (int user_proc,
+		vir_bytes user_addr, vir_bytes count, void *loc_addr)	);
+_PROTOTYPE( static void rtl8139_stop, (void)				);
+_PROTOTYPE( static void check_int_events, (void)				);
+_PROTOTYPE( static int do_hard_int, (void)				);
+_PROTOTYPE( static void rtl8139_dump, (message *m)				);
+#if 0
+_PROTOTYPE( static void dump_phy, (re_t *rep)				);
+#endif
+_PROTOTYPE( static int rl_handler, (re_t *rep)			);
+_PROTOTYPE( static void rl_watchdog_f, (timer_t *tp)			);
+
+/* The message used in the main loop is made global, so that rl_watchdog_f()
+ * can change its message type to fake a HARD_INT message.
+ */
+PRIVATE message m;
+PRIVATE int int_event_check;		/* set to TRUE if events arrived */
+
+static char *progname;
+extern int errno;
+
+/*===========================================================================*
+ *				main				     *
+ *===========================================================================*/
+int main(int argc, char *argv[])
+{
+	int fkeys, sfkeys;
+	int inet_proc_nr;
+	int i, r;
+	re_t *rep;
+	long v;
+
+	env_setargs(argc, argv);
+
+	v= 0;
+	(void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
+	eth_ign_proto= htons((u16_t) v);
+
+	/* Observe some function key for debug dumps. */
+	fkeys = sfkeys = 0; bit_set(sfkeys, 9);
+	if ((r=fkey_map(&fkeys, &sfkeys)) != OK) 
+	    printf("Warning: RTL8139 couldn't observe Shift+F9 key: %d\n",r);
+
+	/* Claim buffer memory now under Minix, before MM takes it all. */
+	for (rep= &re_table[0]; rep < re_table+RE_PORT_NR; rep++)
+		rl_init_buf(rep);
+
+	/* Try to notify INET that we are present (again). If INET cannot
+	 * be found, assume this is the first time we started and INET is
+	 * not yet alive.
+	 */
+	(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
+	r = _pm_findproc("inet", &inet_proc_nr);
+	if (r == OK) notify(inet_proc_nr);
+
+
+	while (TRUE)
+	{
+		if ((r= receive(ANY, &m)) != OK)
+			panic("rtl8139","receive failed", r);
+
+		switch (m.m_type)
+		{
+		case DEV_PING: notify(m.m_source);		continue;
+		case DL_WRITEV:	rl_writev(&m, FALSE, TRUE);	break;
+		case DL_WRITE:	rl_writev(&m, FALSE, FALSE);	break;
+#if 0
+		case DL_READ:	do_vread(&m, FALSE);		break;
+#endif
+		case DL_READV:	rl_readv(&m, FALSE, TRUE);	break;
+		case DL_INIT:	rl_init(&m);			break;
+		case DL_GETSTAT: rl_getstat(&m);		break;
+		case DL_GETNAME: rl_getname(&m);		break;
+#if 0
+		case DL_STOP:	do_stop(&m);			break;
+#endif
+		case SYN_ALARM:
+			/* Under MINIX, synchronous alarms are used instead of
+			 * watchdog functions. The approach is very different:
+			 * MINIX VMD timeouts are handled within the kernel 
+			 * (the watchdog is executed by CLOCK), and notify()
+			 * the driver in some cases.
+			 * MINIX timeouts result in a SYN_ALARM message to the
+			 * driver and thus are handled where they should be
+			 * handled. Locally, watchdog functions are used again. 
+			 */
+			rl_watchdog_f(NULL);     
+			break;		 
+		case HARD_INT:
+			do_hard_int();
+			if (int_event_check)
+				check_int_events();
+			break ;
+		case FKEY_PRESSED: rtl8139_dump(&m);		break;
+		case PROC_EVENT:
+			sig_handler();
+			break;
+		default:
+			panic("rtl8139","illegal message", m.m_type);
+		}
+	}
+}
+
+/*===========================================================================*
+ *				sig_handler                                  *
+ *===========================================================================*/
+PRIVATE void sig_handler()
+{
+  sigset_t sigset;
+  int sig;
+
+  /* Try to obtain signal set from PM. */
+  if (getsigset(&sigset) != 0) return;
+
+  /* Check for known signals. */
+  if (sigismember(&sigset, SIGTERM)) {
+      rtl8139_stop();
+  }
+}
+
+/*===========================================================================*
+ *				check_int_events			     *
+ *===========================================================================*/
+static void check_int_events(void) 
+{
+  int i;
+  re_t *rep;
+			for (i= 0, rep= &re_table[0]; i<RE_PORT_NR; i++, rep++)
+			{
+				if (rep->re_mode != REM_ENABLED)
+					continue;
+				if (!rep->re_got_int)
+					continue;
+				rep->re_got_int= 0;
+				assert(rep->re_flags & REF_ENABLED);
+				rl_check_ints(rep);
+			}
+}
+
+/*===========================================================================*
+ *				rtl8139_stop				     *
+ *===========================================================================*/
+static void rtl8139_stop()
+{
+	int i;
+	re_t *rep;
+
+	for (i= 0, rep= &re_table[0]; i<RE_PORT_NR; i++, rep++)
+	{
+		if (rep->re_mode != REM_ENABLED)
+			continue;
+		rl_outb(rep->re_base_port, RL_CR, 0);
+	}
+	sys_exit(0);
+}
+
+/*===========================================================================*
+ *				rtl8139_dump				     *
+ *===========================================================================*/
+static void rtl8139_dump(m)
+message *m;			/* pointer to request message */
+{
+	re_t *rep;
+	int i;
+
+	printf("\n");
+	for (i= 0, rep = &re_table[0]; i<RE_PORT_NR; i++, rep++)
+	{
+		if (rep->re_mode == REM_DISABLED)
+			printf("Realtek RTL 8139 port %d is disabled\n", i);
+
+		if (rep->re_mode != REM_ENABLED)
+			continue;
+
+		printf("Realtek RTL 8139 statistics of port %d:\n", i);
+
+		printf("recvErr    :%8ld\t", rep->re_stat.ets_recvErr);
+		printf("sendErr    :%8ld\t", rep->re_stat.ets_sendErr);
+		printf("OVW        :%8ld\n", rep->re_stat.ets_OVW);
+
+		printf("CRCerr     :%8ld\t", rep->re_stat.ets_CRCerr);
+		printf("frameAll   :%8ld\t", rep->re_stat.ets_frameAll);
+		printf("missedP    :%8ld\n", rep->re_stat.ets_missedP);
+
+		printf("packetR    :%8ld\t", rep->re_stat.ets_packetR);
+		printf("packetT    :%8ld\t", rep->re_stat.ets_packetT);
+		printf("transDef   :%8ld\n", rep->re_stat.ets_transDef);
+
+		printf("collision  :%8ld\t", rep->re_stat.ets_collision);
+		printf("transAb    :%8ld\t", rep->re_stat.ets_transAb);
+		printf("carrSense  :%8ld\n", rep->re_stat.ets_carrSense);
+
+		printf("fifoUnder  :%8ld\t", rep->re_stat.ets_fifoUnder);
+		printf("fifoOver   :%8ld\t", rep->re_stat.ets_fifoOver);
+		printf("CDheartbeat:%8ld\n", rep->re_stat.ets_CDheartbeat);
+
+		printf("OWC        :%8ld\t", rep->re_stat.ets_OWC);
+
+		printf("re_flags = 0x%x\n", rep->re_flags);
+
+		printf(
+	"TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+			rl_inw(rep->re_base_port, RL_TSAD),
+			rl_inl(rep->re_base_port, RL_TSD0+0*4),
+			rl_inl(rep->re_base_port, RL_TSD0+1*4),
+			rl_inl(rep->re_base_port, RL_TSD0+2*4),
+			rl_inl(rep->re_base_port, RL_TSD0+3*4));
+		printf("tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
+			rep->re_tx_head, rep->re_tx_tail,
+			rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,
+			rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
+	}
+}
+
+/*===========================================================================*
+ *				do_init					     *
+ *===========================================================================*/
+static void rl_init(mp)
+message *mp;
+{
+	static int first_time= 1;
+
+	int port;
+	re_t *rep;
+	message reply_mess;
+
+	if (first_time)
+	{
+		first_time= 0;
+		rl_pci_conf(); /* Configure PCI devices. */
+
+		tmra_inittimer(&rl_watchdog);
+		/* Use a synchronous alarm instead of a watchdog timer. */
+		sys_setalarm(HZ, 0);
+	}
+
+	port = mp->DL_PORT;
+	if (port < 0 || port >= RE_PORT_NR)
+	{
+		reply_mess.m_type= DL_INIT_REPLY;
+		reply_mess.m3_i1= ENXIO;
+		mess_reply(mp, &reply_mess);
+		return;
+	}
+	rep= &re_table[port];
+	if (rep->re_mode == REM_DISABLED)
+	{
+		/* This is the default, try to (re)locate the device. */
+		rl_conf_hw(rep);
+		if (rep->re_mode == REM_DISABLED)
+		{
+			/* Probe failed, or the device is configured off. */
+			reply_mess.m_type= DL_INIT_REPLY;
+			reply_mess.m3_i1= ENXIO;
+			mess_reply(mp, &reply_mess);
+			return;
+		}
+		if (rep->re_mode == REM_ENABLED)
+			rl_init_hw(rep);
+#if VERBOSE	/* load silently ... can always check status later */
+		rl_report_link(rep);
+#endif
+	}
+
+	assert(rep->re_mode == REM_ENABLED);
+	assert(rep->re_flags & REF_ENABLED);
+
+	rep->re_flags &= ~(REF_PROMISC | REF_MULTI | REF_BROAD);
+
+	if (mp->DL_MODE & DL_PROMISC_REQ)
+		rep->re_flags |= REF_PROMISC;
+	if (mp->DL_MODE & DL_MULTI_REQ)
+		rep->re_flags |= REF_MULTI;
+	if (mp->DL_MODE & DL_BROAD_REQ)
+		rep->re_flags |= REF_BROAD;
+
+	rep->re_client = mp->m_source;
+	rl_rec_mode(rep);
+
+	reply_mess.m_type = DL_INIT_REPLY;
+	reply_mess.m3_i1 = mp->DL_PORT;
+	reply_mess.m3_i2 = RE_PORT_NR;
+	*(ether_addr_t *) reply_mess.m3_ca1 = rep->re_address;
+
+	mess_reply(mp, &reply_mess);
+}
+
+/*===========================================================================*
+ *				rl_pci_conf				     *
+ *===========================================================================*/
+static void rl_pci_conf()
+{
+	int i, h;
+	re_t *rep;
+	static char envvar[] = RL_ENVVAR "#";
+	static char envfmt[] = "*:d.d.d";
+	static char val[128];
+	long v;
+
+	for (i= 0, rep= re_table; i<RE_PORT_NR; i++, rep++)
+	{
+		strcpy(rep->re_name, "rtl8139#0");
+		rep->re_name[8] += i;
+		rep->re_seen= FALSE;
+		envvar[sizeof(RL_ENVVAR)-1]= '0'+i;
+		if (0 == env_get_param(envvar, val, sizeof(val)) && 
+				! env_prefix(envvar, "pci")) {
+			env_panic(envvar);
+		}
+		v= 0;
+		(void) env_parse(envvar, envfmt, 1, &v, 0, 255);
+		rep->re_pcibus= v;
+		v= 0;
+		(void) env_parse(envvar, envfmt, 2, &v, 0, 255);
+		rep->re_pcidev= v;
+		v= 0;
+		(void) env_parse(envvar, envfmt, 3, &v, 0, 255);
+		rep->re_pcifunc= v;
+	}
+
+	pci_init();
+
+	for (h= 1; h >= 0; h--) {
+		for (i= 0, rep= re_table; i<RE_PORT_NR; i++, rep++)
+		{
+			if (((rep->re_pcibus | rep->re_pcidev |
+				rep->re_pcifunc) != 0) != h)
+			{
+				continue;
+			}
+			if (rl_probe(rep))
+				rep->re_seen= TRUE;
+		}
+	}
+}
+
+/*===========================================================================*
+ *				rl_probe				     *
+ *===========================================================================*/
+static int rl_probe(rep)
+re_t *rep;
+{
+	int i, r, devind, just_one;
+	u16_t vid, did;
+	u32_t bar;
+	u8_t ilr;
+	char *dname;
+
+	if ((rep->re_pcibus | rep->re_pcidev | rep->re_pcifunc) != 0)
+	{
+		/* Look for specific PCI device */
+		r= pci_find_dev(rep->re_pcibus, rep->re_pcidev,
+			rep->re_pcifunc, &devind);
+		if (r == 0)
+		{
+			printf("%s: no PCI found at %d.%d.%d\n",
+				rep->re_name, rep->re_pcibus,
+				rep->re_pcidev, rep->re_pcifunc);
+			return 0;
+		}
+		pci_ids(devind, &vid, &did);
+		just_one= TRUE;
+	}
+	else
+	{
+		r= pci_first_dev(&devind, &vid, &did);
+		if (r == 0)
+			return 0;
+		just_one= FALSE;
+	}
+
+	for(;;)
+	{
+		for (i= 0; pcitab[i].vid != 0; i++)
+		{
+			if (pcitab[i].vid != vid)
+				continue;
+			if (pcitab[i].did != did)
+				continue;
+			if (pcitab[i].checkclass)
+			{
+			  panic("rtl_probe",
+			    "class check not implemented", NO_NUM);
+			}
+			break;
+		}
+		if (pcitab[i].vid != 0)
+			break;
+
+		if (just_one)
+		{
+			printf(
+		"%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
+				rep->re_name, vid, did,
+				rep->re_pcibus,
+				rep->re_pcidev, rep->re_pcifunc);
+			return 0;
+		}
+
+		r= pci_next_dev(&devind, &vid, &did);
+		if (!r)
+			return 0;
+	}
+
+#if VERBOSE	/* stay silent at startup, can always get status later */
+	dname= pci_dev_name(vid, did);
+	if (!dname)
+		dname= "unknown device";
+	printf("%s: ", rep->re_name);
+	printf("%s (%x/%x) at %s\n", dname, vid, did, pci_slot_name(devind));
+#endif
+	pci_reserve(devind);
+	/* printf("cr = 0x%x\n", pci_attr_r16(devind, PCI_CR)); */
+	bar= pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
+	if (bar < 0x400)
+	{
+		panic("rtl_probe",
+			"base address is not properly configured", NO_NUM);
+	}
+	rep->re_base_port= bar;
+
+	ilr= pci_attr_r8(devind, PCI_ILR);
+	rep->re_irq= ilr;
+	if (debug)
+	{
+		printf("%s: using I/O address 0x%lx, IRQ %d\n",
+			rep->re_name, (unsigned long)bar, ilr);
+	}
+
+	return TRUE;
+}
+
+/*===========================================================================*
+ *				rl_conf_hw				     *
+ *===========================================================================*/
+static void rl_conf_hw(rep)
+re_t *rep;
+{
+	static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 	/* ,... */ };
+
+	rep->re_mode= REM_DISABLED;	/* Superfluous */
+
+	if (rep->re_seen)
+	{
+		/* PCI device is present */
+		rep->re_mode= REM_ENABLED;
+	}
+	if (rep->re_mode != REM_ENABLED)
+		return;
+
+	rep->re_flags= REF_EMPTY;
+	rep->re_link_up= -1;	/* Unknown */
+	rep->re_got_int= 0;
+	rep->re_send_int= 0;
+	rep->re_report_link= 0;
+	rep->re_clear_rx= 0;
+	rep->re_need_reset= 0;
+	rep->re_tx_alive= 0;
+	rep->re_read_s= 0;
+	rep->re_tx_head= 0;
+	rep->re_tx_tail= 0;
+	rep->re_ertxth= RL_TSD_ERTXTH_8;
+	rep->re_stat= empty_stat;
+}
+
+/*===========================================================================*
+ *				rl_init_buf				     *
+ *===========================================================================*/
+static void rl_init_buf(rep)
+re_t *rep;
+{
+	size_t rx_bufsize, tx_bufsize, tot_bufsize;
+	phys_bytes buf;
+	char *mallocbuf;
+	static struct memory chunk;
+	int fd, s, i, off;
+
+	/* Allocate receive and transmit buffers */
+	tx_bufsize= ETH_MAX_PACK_SIZE_TAGGED;
+	if (tx_bufsize % 4)
+		tx_bufsize += 4-(tx_bufsize % 4);	/* Align */
+	rx_bufsize= RX_BUFSIZE;
+	tot_bufsize= N_TX_BUF*tx_bufsize + rx_bufsize;
+
+	/* Now try to allocate a kernel memory buffer. */
+	chunk.size = tot_bufsize;
+
+#define BUF_ALIGNMENT (64*1024)
+
+	if(!(mallocbuf = malloc(BUF_ALIGNMENT + tot_bufsize))) {
+	    panic("RTL8139","Couldn't allocate kernel buffer",i);
+	}
+
+	if(OK != (i = sys_umap(SELF, D, (vir_bytes) mallocbuf, tot_bufsize, &buf))) {
+	    panic("RTL8139","Couldn't re-map malloced buffer",i);
+	}
+
+	/* click-align mallocced buffer. this is what we used to get
+	 * from kmalloc() too.
+	 */
+	if((off = buf % BUF_ALIGNMENT)) {
+		mallocbuf += BUF_ALIGNMENT - off;
+		buf += BUF_ALIGNMENT - off;
+	}
+
+	for (i= 0; i<N_TX_BUF; i++)
+	{
+		rep->re_tx[i].ret_buf= buf;
+		rep->re_tx[i].v_ret_buf= mallocbuf;
+		buf += tx_bufsize;
+		mallocbuf += tx_bufsize;
+	}
+	rep->re_rx_buf= buf;
+	rep->v_re_rx_buf= mallocbuf;
+}
+
+/*===========================================================================*
+ *				rl_init_hw				     *
+ *===========================================================================*/
+static void rl_init_hw(rep)
+re_t *rep;
+{
+	int s, i;
+
+	rep->re_flags = REF_EMPTY;
+	rep->re_flags |= REF_ENABLED;
+
+	/* Set the interrupt handler. The policy is to only send HARD_INT 
+	 * notifications. Don't reenable interrupts automatically. The id
+	 * that is passed back is the interrupt line number.
+	 */
+	rep->re_hook_id = rep->re_irq;	
+	if ((s=sys_irqsetpolicy(rep->re_irq, 0, &rep->re_hook_id)) != OK)
+		printf("RTL8139: error, couldn't set IRQ policy: %d\n", s);
+
+	rl_reset_hw(rep);
+
+	if ((s=sys_irqenable(&rep->re_hook_id)) != OK)
+		printf("RTL8139: error, couldn't enable interrupts: %d\n", s);
+
+#if VERBOSE	/* stay silent during startup, can always get status later */
+	if (rep->re_model) {
+		printf("%s: model %s\n", rep->re_name, rep->re_model);
+	} else
+	{
+		printf("%s: unknown model 0x%08x\n",
+			rep->re_name,
+			rl_inl(rep->re_base_port, RL_TCR) &
+			(RL_TCR_HWVER_AM | RL_TCR_HWVER_BM));
+	}
+#endif
+
+	rl_confaddr(rep);
+	if (debug)
+	{
+		printf("%s: Ethernet address ", rep->re_name);
+		for (i= 0; i < 6; i++)
+		{
+			printf("%x%c", rep->re_address.ea_addr[i],
+				i < 5 ? ':' : '\n');
+		}
+	}
+}
+
+/*===========================================================================*
+ *				rl_reset_hw				     *
+ *===========================================================================*/
+static void rl_reset_hw(rep)
+re_t *rep;
+{
+	port_t port;
+	u32_t t;
+	phys_bytes bus_buf;
+	int i;
+	clock_t t0,t1;
+
+	port= rep->re_base_port;
+
+#if 0
+	/* Reset the PHY */
+	rl_outb(port, RL_BMCR, MII_CTRL_RST);
+	getuptime(&t0);
+	do {
+		if (!(rl_inb(port, RL_BMCR) & MII_CTRL_RST))
+			break;
+	} while (getuptime(&t1)==OK && (t1-t0) < HZ);
+	if (rl_inb(port, RL_BMCR) & MII_CTRL_RST)
+		panic("rtl8139","reset PHY failed to complete", NO_NUM);
+#endif
+
+	/* Reset the device */
+	printf("rl_reset_hw: (before reset) port = 0x%x, RL_CR = 0x%x\n",
+		port, rl_inb(port, RL_CR));
+	rl_outb(port, RL_CR, RL_CR_RST);
+	getuptime(&t0);
+	do {
+		if (!(rl_inb(port, RL_CR) & RL_CR_RST))
+			break;
+	} while (getuptime(&t1)==OK && (t1-t0) < HZ);
+	printf("rl_reset_hw: (after reset) port = 0x%x, RL_CR = 0x%x\n",
+		port, rl_inb(port, RL_CR));
+	if (rl_inb(port, RL_CR) & RL_CR_RST)
+		printf("rtl8139: reset failed to complete");
+
+	t= rl_inl(port, RL_TCR);
+	switch(t & (RL_TCR_HWVER_AM | RL_TCR_HWVER_BM))
+	{
+	case RL_TCR_HWVER_RTL8139: rep->re_model= "RTL8139"; break;
+	case RL_TCR_HWVER_RTL8139A: rep->re_model= "RTL8139A"; break;
+	case RL_TCR_HWVER_RTL8139AG:
+		rep->re_model= "RTL8139A-G / RTL8139C";
+		break;
+	case RL_TCR_HWVER_RTL8139B:
+		rep->re_model= "RTL8139B / RTL8130";
+		break;
+	case RL_TCR_HWVER_RTL8100: rep->re_model= "RTL8100"; break;
+	case RL_TCR_HWVER_RTL8100B:
+		rep->re_model= "RTL8100B/RTL8139D";
+		break;
+	case RL_TCR_HWVER_RTL8139CP: rep->re_model= "RTL8139C+"; break;
+	case RL_TCR_HWVER_RTL8101: rep->re_model= "RTL8101"; break;
+	default:
+		rep->re_model= NULL;
+		break;
+	}
+
+#if 0
+	printf("REVID: 0x%02x\n", rl_inb(port, RL_REVID));
+#endif
+
+	/* Intialize Rx */
+
+	/* Should init multicast mask */
+#if 0
+08-0f	R/W	MAR[0-7]	multicast
+#endif
+	bus_buf= vm_1phys2bus(rep->re_rx_buf);
+	rl_outl(port, RL_RBSTART, bus_buf);
+
+	/* Initialize Tx */ 
+	for (i= 0; i<N_TX_BUF; i++)
+	{
+		rep->re_tx[i].ret_busy= FALSE;
+		bus_buf= vm_1phys2bus(rep->re_tx[i].ret_buf);
+		rl_outl(port, RL_TSAD0+i*4, bus_buf);
+		t= rl_inl(port, RL_TSD0+i*4);
+		assert(t & RL_TSD_OWN);
+	}
+
+#if 0
+	dump_phy(rep);
+#endif
+
+	t= rl_inw(port, RL_IMR);
+	rl_outw(port, RL_IMR, t | (RL_IMR_SERR | RL_IMR_TIMEOUT |
+		RL_IMR_LENCHG));
+
+	t= rl_inw(port, RL_IMR);
+	rl_outw(port, RL_IMR, t | (RL_IMR_FOVW | RL_IMR_PUN |
+		RL_IMR_RXOVW | RL_IMR_RER | RL_IMR_ROK));
+
+	t= rl_inw(port, RL_IMR);
+	rl_outw(port, RL_IMR, t | (RL_IMR_TER | RL_IMR_TOK));
+
+	t= rl_inb(port, RL_CR);
+	rl_outb(port, RL_CR, t | RL_CR_RE);
+
+	t= rl_inb(port, RL_CR);
+	rl_outb(port, RL_CR, t | RL_CR_TE);
+
+	rl_outl(port, RL_RCR, RX_BUFBITS);
+
+	t= rl_inl(port, RL_TCR);
+	rl_outl(port, RL_TCR, t | RL_TCR_IFG_STD);
+}
+
+/*===========================================================================*
+ *				rl_confaddr				     *
+ *===========================================================================*/
+static void rl_confaddr(rep)
+re_t *rep;
+{
+	static char eakey[]= RL_ENVVAR "#_EA";
+	static char eafmt[]= "x:x:x:x:x:x";
+
+	int i;
+	port_t port;
+	u32_t w;
+	long v;
+
+	/* User defined ethernet address? */
+	eakey[sizeof(RL_ENVVAR)-1]= '0' + (rep-re_table);
+
+	port= rep->re_base_port;
+
+	for (i= 0; i < 6; i++)
+	{
+		if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
+			break;
+		rep->re_address.ea_addr[i]= v;
+	}
+
+	if (i != 0 && i != 6) env_panic(eakey);	/* It's all or nothing */
+
+	/* Should update ethernet address in hardware */
+	if (i == 6)
+	{
+		port= rep->re_base_port;
+		rl_outb(port, RL_9346CR, RL_9346CR_EEM_CONFIG);
+		w= 0;
+		for (i= 0; i<4; i++)
+			w |= (rep->re_address.ea_addr[i] << (i*8));
+		rl_outl(port, RL_IDR, w);
+		w= 0;
+		for (i= 4; i<6; i++)
+			w |= (rep->re_address.ea_addr[i] << ((i-4)*8));
+		rl_outl(port, RL_IDR+4, w);
+		rl_outb(port, RL_9346CR, RL_9346CR_EEM_NORMAL);
+	}
+
+	/* Get ethernet address */
+	for (i= 0; i<6; i++)
+		rep->re_address.ea_addr[i]= rl_inb(port, RL_IDR+i);
+}
+
+/*===========================================================================*
+ *				rl_rec_mode				     *
+ *===========================================================================*/
+static void rl_rec_mode(rep)
+re_t *rep;
+{
+	port_t port;
+	u32_t rcr;
+
+	port= rep->re_base_port;
+	rcr= rl_inl(port, RL_RCR);
+	rcr &= ~(RL_RCR_AB|RL_RCR_AM|RL_RCR_APM|RL_RCR_AAP);
+	if (rep->re_flags & REF_PROMISC)
+		rcr |= RL_RCR_AB | RL_RCR_AM | RL_RCR_AAP;
+	if (rep->re_flags & REF_BROAD)
+		rcr |= RL_RCR_AB;
+	if (rep->re_flags & REF_MULTI)
+		rcr |= RL_RCR_AM;
+	rcr |= RL_RCR_APM;
+
+	rl_outl(port, RL_RCR, rcr);
+}
+
+/*===========================================================================*
+ *				rl_readv				     *
+ *===========================================================================*/
+static void rl_readv(mp, from_int, vectored)
+message *mp;
+int from_int;
+int vectored;
+{
+	int i, j, n, o, s, s1, dl_port, re_client, count, size;
+	port_t port;
+	unsigned amount, totlen, packlen;
+	phys_bytes src_phys, dst_phys, iov_src;
+	u16_t d_start, d_end;
+	u32_t l, rxstat = 0x12345678;
+	re_t *rep;
+	iovec_t *iovp;
+	int cps;
+
+	dl_port = mp->DL_PORT;
+	count = mp->DL_COUNT;
+	if (dl_port < 0 || dl_port >= RE_PORT_NR)
+		panic("rtl8139"," illegal port", dl_port);
+	rep= &re_table[dl_port];
+	re_client= mp->DL_PROC;
+	rep->re_client= re_client;
+
+	if (rep->re_clear_rx)
+		goto suspend;	/* Buffer overflow */
+
+	assert(rep->re_mode == REM_ENABLED);
+	assert(rep->re_flags & REF_ENABLED);
+
+	port= rep->re_base_port;
+
+	/* Assume that the RL_CR_BUFE check was been done by rl_checks_ints
+	 */
+	if (!from_int && (rl_inb(port, RL_CR) & RL_CR_BUFE))
+	{
+		/* Receive buffer is empty, suspend */
+		goto suspend;
+	}
+
+	d_start= rl_inw(port, RL_CAPR) + RL_CAPR_DATA_OFF;
+	d_end= rl_inw(port, RL_CBR) % RX_BUFSIZE;
+
+	if (d_start >= RX_BUFSIZE)
+	{
+		printf("rl_readv: strange value in RL_CAPR: 0x%x\n",
+			rl_inw(port, RL_CAPR));
+		d_start %= RX_BUFSIZE;
+	}
+
+	if (d_end > d_start)
+		amount= d_end-d_start;
+	else
+		amount= d_end+RX_BUFSIZE - d_start;
+
+	rxstat = *(u32_t *) (rep->v_re_rx_buf + d_start);
+
+#if DEAD_CODE
+	src_phys= rep->re_rx_buf + d_start;
+	cps = sys_physcopy(
+		NONE, PHYS_SEG, src_phys,
+		SELF, D, (vir_bytes) &rxstat, sizeof(rxstat));
+	if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
+#endif
+
+	if (rep->re_clear_rx)
+	{
+#if 0
+		printf("rl_readv: late buffer overflow\n");
+#endif
+		goto suspend;	/* Buffer overflow */
+	}
+
+	/* Should convert from little endian to host byte order */
+
+	if (!(rxstat & RL_RXS_ROK))
+	{
+		printf("rxstat = 0x%08lx\n", rxstat);
+		printf("d_start: 0x%x, d_end: 0x%x, rxstat: 0x%lx\n",
+			d_start, d_end, rxstat);
+		panic("rtl8139","received packet not OK", NO_NUM);
+	}
+	totlen= (rxstat >> RL_RXS_LEN_S);
+	if (totlen < 8 || totlen > 2*ETH_MAX_PACK_SIZE)
+	{
+		/* Someting went wrong */
+		printf(
+		"rl_readv: bad length (%u) in status 0x%08lx at offset 0x%x\n",
+			totlen, rxstat, d_start);
+		printf(
+		"d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%lx\n",
+			d_start, d_end, totlen, rxstat);
+		panic(NULL, NULL, NO_NUM);
+	}
+
+#if 0
+	printf("d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%x\n",
+		d_start, d_end, totlen, rxstat);
+#endif
+
+	if (totlen+4 > amount)
+	{
+		printf("rl_readv: packet not yet ready\n");
+		goto suspend;
+	}
+
+	/* Should subtract the CRC */
+	packlen= totlen - ETH_CRC_SIZE;
+
+	if (vectored)
+	{
+		int iov_offset = 0;
+#if 0
+		if ((cps = sys_umap(re_client, D, (vir_bytes) mp->DL_ADDR,
+			count * sizeof(rep->re_iovec[0]), &iov_src)) != OK)
+			printf("sys_umap failed: %d\n", cps);
+#endif
+
+		size= 0;
+		o= d_start+4;
+		src_phys= rep->re_rx_buf;
+		for (i= 0; i<count; i += IOVEC_NR,
+			iov_src += IOVEC_NR * sizeof(rep->re_iovec[0]),
+			iov_offset += IOVEC_NR * sizeof(rep->re_iovec[0]))
+		{
+			n= IOVEC_NR;
+			if (i+n > count)
+				n= count-i;
+#if 0
+			cps = sys_physcopy(NONE, PHYS_SEG, iov_src, SELF, D, (vir_bytes) rep->re_iovec, 
+				n * sizeof(rep->re_iovec[0]));
+	if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
+#else
+			cps = sys_vircopy(re_client, D, (vir_bytes) mp->DL_ADDR + iov_offset,
+				SELF, D, (vir_bytes) rep->re_iovec, n * sizeof(rep->re_iovec[0]));
+	if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
+#endif
+
+			for (j= 0, iovp= rep->re_iovec; j<n; j++, iovp++)
+			{
+				s= iovp->iov_size;
+				if (size + s > packlen)
+				{
+					assert(packlen > size);
+					s= packlen-size;
+				}
+
+#if 0
+				if (sys_umap(re_client, D, iovp->iov_addr, s, &dst_phys) != OK)
+				  panic("rtl8139","umap_local failed\n", NO_NUM);
+#endif
+
+				if (o >= RX_BUFSIZE)
+				{
+					o -= RX_BUFSIZE;
+					assert(o < RX_BUFSIZE);
+				}
+
+				if (o+s > RX_BUFSIZE)
+				{
+					assert(o<RX_BUFSIZE);
+					s1= RX_BUFSIZE-o;
+
+#if 0
+					cps = sys_abscopy(src_phys+o, dst_phys, s1);
+	if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
+					cps = sys_abscopy(src_phys, dst_phys+s1, s-s1);
+	if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
+#else
+					cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf+o,
+					re_client, D, iovp->iov_addr, s1);
+	if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
+					cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf,
+					re_client, D, iovp->iov_addr+s1, s-s1);
+	if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
+#endif
+				}
+				else
+				{
+#if 0
+					cps = sys_abscopy(src_phys+o, dst_phys, s);
+	if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
+#else
+					cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf+o,
+					re_client, D, iovp->iov_addr, s);
+	if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
+#endif
+				}
+
+				size += s;
+				if (size == packlen)
+					break;
+				o += s;
+			}
+			if (size == packlen)
+				break;
+		}
+		if (size < packlen)
+		{
+			assert(0);
+		}
+	}
+	else
+	{  
+		assert(0);
+#if 0
+		size= mp->DL_COUNT;
+		if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
+			panic("rtl8139","invalid packet size", size);
+		if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR, size, &phys_user))
+			panic("rtl8139","umap_local failed", NO_NUM);
+
+		p= rep->re_tx[tx_head].ret_buf;
+		cps = sys_abscopy(phys_user, p, size);
+		if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
+#endif
+		}
+
+		if (rep->re_clear_rx)
+		{
+			/* For some reason the receiver FIFO is not stopped when
+			 * the buffer is full.
+			 */
+	#if 0
+			printf("rl_readv: later buffer overflow\n");
+	#endif
+			goto suspend;	/* Buffer overflow */
+		}
+
+		rep->re_stat.ets_packetR++;
+		rep->re_read_s= packlen;
+		rep->re_flags= (rep->re_flags & ~REF_READING) | REF_PACK_RECV;
+
+		/* Avoid overflow in 16-bit computations */
+		l= d_start;
+		l += totlen+4;
+		l= (l+3) & ~3;	/* align */
+		if (l >= RX_BUFSIZE)
+		{
+			l -= RX_BUFSIZE;
+			assert(l < RX_BUFSIZE);
+		}
+		rl_outw(port, RL_CAPR, l-RL_CAPR_DATA_OFF);
+
+		if (!from_int)
+			reply(rep, OK, FALSE);
+
+		return;
+
+	suspend:
+		if (from_int)
+		{
+			assert(rep->re_flags & REF_READING);
+
+			/* No need to store any state */
+			return;
+		}
+
+		rep->re_rx_mess= *mp;
+		assert(!(rep->re_flags & REF_READING));
+		rep->re_flags |= REF_READING;
+
+		reply(rep, OK, FALSE);
+	}
+
+	/*===========================================================================*
+	 *				rl_writev				     *
+	 *===========================================================================*/
+	static void rl_writev(mp, from_int, vectored)
+	message *mp;
+	int from_int;
+	int vectored;
+	{
+		phys_bytes p, iov_src, phys_user;
+		int i, j, n, s, port, count, size;
+		int tx_head, re_client;
+		re_t *rep;
+		iovec_t *iovp;
+		char *ret;
+		int cps;
+
+		port = mp->DL_PORT;
+		count = mp->DL_COUNT;
+		if (port < 0 || port >= RE_PORT_NR)
+			panic("rtl8139","illegal port", port);
+		rep= &re_table[port];
+		re_client= mp->DL_PROC;
+		rep->re_client= re_client;
+
+		assert(rep->re_mode == REM_ENABLED);
+		assert(rep->re_flags & REF_ENABLED);
+
+		if (from_int)
+		{
+			assert(rep->re_flags & REF_SEND_AVAIL);
+			rep->re_flags &= ~REF_SEND_AVAIL;
+			rep->re_send_int= FALSE;
+			rep->re_tx_alive= TRUE;
+		}
+
+		tx_head= rep->re_tx_head;
+		if (rep->re_tx[tx_head].ret_busy)
+		{
+			assert(!(rep->re_flags & REF_SEND_AVAIL));
+			rep->re_flags |= REF_SEND_AVAIL;
+			if (rep->re_tx[tx_head].ret_busy)
+				goto suspend;
+
+			/* Race condition, the interrupt handler may clear re_busy
+			 * before we got a chance to set REF_SEND_AVAIL. Checking
+			 * ret_busy twice should be sufficient.
+			 */
+	#if 0
+			printf("rl_writev: race detected\n");
+	#endif
+			rep->re_flags &= ~REF_SEND_AVAIL;
+			rep->re_send_int= FALSE;
+		}
+
+		assert(!(rep->re_flags & REF_SEND_AVAIL));
+		assert(!(rep->re_flags & REF_PACK_SENT));
+
+		if (vectored)
+		{
+			int iov_offset = 0;
+
+#if 0
+			if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR,
+				count * sizeof(rep->re_iovec[0]), &iov_src))
+				panic("rtl8139","umap_local failed", NO_NUM);
+#endif
+
+			size= 0;
+#if 0
+			p= rep->re_tx[tx_head].ret_buf;
+#else
+			ret = rep->re_tx[tx_head].v_ret_buf;
+#endif
+			for (i= 0; i<count; i += IOVEC_NR,
+				iov_src += IOVEC_NR * sizeof(rep->re_iovec[0]),
+				iov_offset += IOVEC_NR * sizeof(rep->re_iovec[0]))
+			{
+				n= IOVEC_NR;
+				if (i+n > count)
+					n= count-i;
+#if 0
+				cps = sys_physcopy(NONE, PHYS_SEG, iov_src, SELF, D, (vir_bytes) rep->re_iovec, 
+					n * sizeof(rep->re_iovec[0]));
+		if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
+#else
+				cps = sys_vircopy(re_client, D, ((vir_bytes) mp->DL_ADDR) + iov_offset,
+					SELF, D, (vir_bytes) rep->re_iovec, 
+					n * sizeof(rep->re_iovec[0]));
+	if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps);
+#endif
+
+			for (j= 0, iovp= rep->re_iovec; j<n; j++, iovp++)
+			{
+				s= iovp->iov_size;
+				if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
+				{
+				  panic("rtl8139","invalid packet size",
+			  	    NO_NUM);
+				}
+
+				if (OK != sys_umap(re_client, D, iovp->iov_addr, s, &phys_user))
+				  panic("rtl8139","umap_local failed\n", NO_NUM);
+
+#if 0
+				cps = sys_abscopy(phys_user, p, s);
+	if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
+#else
+				cps = sys_vircopy(re_client, D, iovp->iov_addr,
+					SELF, D, (vir_bytes) ret, s);
+		if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps);
+#endif
+				size += s;
+#if 0
+				p += s;
+#endif
+				ret += s;
+			}
+		}
+		if (size < ETH_MIN_PACK_SIZE)
+			panic("rtl8139","invalid packet size", size);
+	}
+	else
+	{  
+		size= mp->DL_COUNT;
+		if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
+			panic("rtl8139","invalid packet size", size);
+#if 0
+		if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR, size, &phys_user))
+			panic("rtl8139","umap_local failed\n", NO_NUM);
+
+		p= rep->re_tx[tx_head].ret_buf;
+		cps = sys_abscopy(phys_user, p, size);
+	if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
+#else
+		ret = rep->re_tx[tx_head].v_ret_buf;
+		cps = sys_vircopy(re_client, D, (vir_bytes)mp->DL_ADDR, 
+			SELF, D, (vir_bytes) ret, size);
+	if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
+#endif
+	}
+
+	rl_outl(rep->re_base_port, RL_TSD0+tx_head*4, 
+		rep->re_ertxth | size);
+	rep->re_tx[tx_head].ret_busy= TRUE;
+
+	if (++tx_head == N_TX_BUF)
+		tx_head= 0;
+	assert(tx_head < RL_N_TX);
+	rep->re_tx_head= tx_head;
+
+	rep->re_flags |= REF_PACK_SENT;
+
+	/* If the interrupt handler called, don't send a reply. The reply
+	 * will be sent after all interrupts are handled. 
+	 */
+	if (from_int)
+		return;
+	reply(rep, OK, FALSE);
+	return;
+
+suspend:
+#if 0
+		printf("rl_writev: head %d, tail %d, busy: %d %d %d %d\n",
+			tx_head, rep->re_tx_tail,
+			rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,
+			rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
+		printf("rl_writev: TSD: 0x%x, 0x%x, 0x%x, 0x%x\n",
+			rl_inl(rep->re_base_port, RL_TSD0+0*4),
+			rl_inl(rep->re_base_port, RL_TSD0+1*4),
+			rl_inl(rep->re_base_port, RL_TSD0+2*4),
+			rl_inl(rep->re_base_port, RL_TSD0+3*4));
+#endif
+
+	if (from_int)
+		panic("rtl8139","should not be sending\n", NO_NUM);
+
+	rep->re_tx_mess= *mp;
+	reply(rep, OK, FALSE);
+}
+
+/*===========================================================================*
+ *				rl_check_ints				     *
+ *===========================================================================*/
+static void rl_check_ints(rep)
+re_t *rep;
+{
+#if 0
+10-1f	R/W	TSD[0-3]	Transmit Status of Descriptor [0-3]
+	31	R	CRS	Carrier Sense Lost
+	30	R	TABT	Transmit Abort
+	29	R	OWC	Out of Window Collision
+	27-24	R	NCC[3-0] Number of Collision Count
+	23-22			reserved
+	21-16	R/W	ERTXH[5-0] Early Tx Threshold
+	15	R	TOK	Transmit OK
+	14	R	TUN	Transmit FIFO Underrun
+	13	R/W	OWN	OWN
+	12-0	R/W	SIZE	Descriptor Size
+3e-3f	R/W	ISR		Interrupt Status Register
+	6	R/W	FOVW	Fx FIFO Overflow Interrupt
+	5	R/W	PUN/LinkChg Packet Underrun / Link Change Interrupt
+	3	R/W	TER	Transmit Error Interrupt
+	2	R/W	TOK	Transmit OK Interrupt
+3e-3f	R/W	ISR		Interrupt Status Register
+	15	R/W	SERR	System Error Interrupt
+	14	R/W	TimeOut	Time Out Interrupt
+	13	R/W	LenChg	Cable Length Change Interrupt
+3e-3f	R/W	ISR		Interrupt Status Register
+	4	R/W	RXOVW	Rx Buffer Overflow Interrupt
+	1	R/W	RER	Receive Error Interrupt
+	0	R/W	ROK	Receive OK Interrupt
+4c-4f	R/W	MPC		Missed Packet Counter
+60-61	R	TSAD		Transmit Status of All Descriptors
+	15-12	R	TOK[3-0] TOK bit of Descriptor [3-0]
+	11-8	R	TUN[3-0] TUN bit of Descriptor [3-0]
+	7-4	R	TABT[3-0] TABT bit of Descriptor [3-0]
+	3-0     R       OWN[3-0] OWN bit of Descriptor [3-0]
+6c-6d	R	DIS		Disconnect Counter
+	15-0	R	DCNT	Disconnect Counter
+6e-6f	R	FCSC		False Carrier Sense Counter
+	15-0	R	FCSCNT	False Carrier event counter
+72-73	R	REC		RX_ER Counter
+	15-0	R	RXERCNT	Received packet counter
+#endif
+
+	int re_flags;
+
+	re_flags= rep->re_flags;
+
+	if ((re_flags & REF_READING) &&
+		!(rl_inb(rep->re_base_port, RL_CR) & RL_CR_BUFE))
+	{
+		if (rep->re_rx_mess.m_type == DL_READV)
+		{
+			rl_readv(&rep->re_rx_mess, TRUE /* from int */,
+				TRUE /* vectored */);
+		}
+		else
+		{
+			assert(rep->re_rx_mess.m_type == DL_READ);
+			rl_readv(&rep->re_rx_mess, TRUE /* from int */,
+				FALSE /* !vectored */);
+		}
+	}
+	if (rep->re_clear_rx)
+		rl_clear_rx(rep);
+
+	if (rep->re_need_reset)
+		rl_do_reset(rep);
+
+	if (rep->re_send_int)
+	{
+		if (rep->re_tx_mess.m_type == DL_WRITEV)
+		{
+			rl_writev(&rep->re_tx_mess, TRUE /* from int */,
+				TRUE /* vectored */);
+		}
+		else
+		{
+			assert(rep->re_tx_mess.m_type == DL_WRITE);
+			rl_writev(&rep->re_tx_mess, TRUE /* from int */,
+				FALSE /* !vectored */);
+		}
+	}
+
+	if (rep->re_report_link)
+		rl_report_link(rep);
+
+	if (rep->re_flags & (REF_PACK_SENT | REF_PACK_RECV))
+		reply(rep, OK, TRUE);
+}
+
+/*===========================================================================*
+ *				rl_report_link				     *
+ *===========================================================================*/
+static void rl_report_link(rep)
+re_t *rep;
+{
+	port_t port;
+	u16_t mii_ctrl, mii_status, mii_ana, mii_anlpa, mii_ane, mii_extstat;
+	u8_t msr;
+	int f, link_up;
+
+	rep->re_report_link= FALSE;
+	port= rep->re_base_port;
+	msr= rl_inb(port, RL_MSR);
+	link_up= !(msr & RL_MSR_LINKB);
+	rep->re_link_up= link_up;
+	if (!link_up)
+	{
+		printf("%s: link down\n", rep->re_name);
+		return;
+	}
+
+	mii_ctrl= rl_inw(port, RL_BMCR);
+	mii_status= rl_inw(port, RL_BMSR);
+	mii_ana= rl_inw(port, RL_ANAR);
+	mii_anlpa= rl_inw(port, RL_ANLPAR);
+	mii_ane= rl_inw(port, RL_ANER);
+	mii_extstat= 0;
+
+	if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO))
+	{
+		printf("%s: PHY: ", rep->re_name);
+		f= 1;
+		if (mii_ctrl & MII_CTRL_LB)
+		{
+			printf("loopback mode");
+			f= 0;
+		}
+		if (mii_ctrl & MII_CTRL_PD)
+		{
+			if (!f) printf(", ");
+			f= 0;
+			printf("powered down");
+		}
+		if (mii_ctrl & MII_CTRL_ISO)
+		{
+			if (!f) printf(", ");
+			f= 0;
+			printf("isolated");
+		}
+		printf("\n");
+		return;
+	}
+	if (!(mii_ctrl & MII_CTRL_ANE))
+	{
+		printf("%s: manual config: ", rep->re_name);
+		switch(mii_ctrl & (MII_CTRL_SP_LSB|MII_CTRL_SP_MSB))
+		{
+		case MII_CTRL_SP_10:	printf("10 Mbps"); break;
+		case MII_CTRL_SP_100:	printf("100 Mbps"); break;
+		case MII_CTRL_SP_1000:	printf("1000 Mbps"); break;
+		case MII_CTRL_SP_RES:	printf("reserved speed"); break;
+		}
+		if (mii_ctrl & MII_CTRL_DM)
+			printf(", full duplex");
+		else
+			printf(", half duplex");
+		printf("\n");
+		return;
+	}
+
+	if (!debug) goto resspeed;
+
+	printf("%s: ", rep->re_name);
+	mii_print_stat_speed(mii_status, mii_extstat);
+	printf("\n");
+
+	if (!(mii_status & MII_STATUS_ANC))
+		printf("%s: auto-negotiation not complete\n", rep->re_name);
+	if (mii_status & MII_STATUS_RF)
+		printf("%s: remote fault detected\n", rep->re_name);
+	if (!(mii_status & MII_STATUS_ANA))
+	{
+		printf("%s: local PHY has no auto-negotiation ability\n",
+			rep->re_name);
+	}
+	if (!(mii_status & MII_STATUS_LS))
+		printf("%s: link down\n", rep->re_name);
+	if (mii_status & MII_STATUS_JD)
+		printf("%s: jabber condition detected\n", rep->re_name);
+	if (!(mii_status & MII_STATUS_EC))
+	{
+		printf("%s: no extended register set\n", rep->re_name);
+		goto resspeed;
+	}
+	if (!(mii_status & MII_STATUS_ANC))
+		goto resspeed;
+
+	printf("%s: local cap.: ", rep->re_name);
+	mii_print_techab(mii_ana);
+	printf("\n");
+
+	if (mii_ane & MII_ANE_PDF)
+		printf("%s: parallel detection fault\n", rep->re_name);
+	if (!(mii_ane & MII_ANE_LPANA))
+	{
+		printf("%s: link-partner does not support auto-negotiation\n",
+			rep->re_name);
+		goto resspeed;
+	}
+
+	printf("%s: remote cap.: ", rep->re_name);
+	mii_print_techab(mii_anlpa);
+	printf("\n");
+
+resspeed:
+	printf("%s: ", rep->re_name);
+	printf("link up at %d Mbps, ", (msr & RL_MSR_SPEED_10) ? 10 : 100);
+	printf("%s duplex\n", ((mii_ctrl & MII_CTRL_DM) ? "full" : "half"));
+
+}
+
+static void mii_print_techab(techab)
+u16_t techab;
+{
+	int fs, ft;
+	if ((techab & MII_ANA_SEL_M) != MII_ANA_SEL_802_3)
+	{
+		printf("strange selector 0x%x, value 0x%x",
+			techab & MII_ANA_SEL_M,
+			(techab & MII_ANA_TAF_M) >> MII_ANA_TAF_S);
+		return;
+	}
+	fs= 1;
+	if (techab & (MII_ANA_100T4 | MII_ANA_100TXFD | MII_ANA_100TXHD))
+	{
+		printf("100 Mbps: ");
+		fs= 0;
+		ft= 1;
+		if (techab & MII_ANA_100T4)
+		{
+			printf("T4");
+			ft= 0;
+		}
+		if (techab & (MII_ANA_100TXFD | MII_ANA_100TXHD))
+		{
+			if (!ft)
+				printf(", ");
+			ft= 0;
+			printf("TX-");
+			switch(techab & (MII_ANA_100TXFD|MII_ANA_100TXHD))
+			{
+			case MII_ANA_100TXFD:	printf("FD"); break;
+			case MII_ANA_100TXHD:	printf("HD"); break;
+			default:		printf("FD/HD"); break;
+			}
+		}
+	}
+	if (techab & (MII_ANA_10TFD | MII_ANA_10THD))
+	{
+		if (!fs)
+			printf(", ");
+		printf("10 Mbps: ");
+		fs= 0;
+		printf("T-");
+		switch(techab & (MII_ANA_10TFD|MII_ANA_10THD))
+		{
+		case MII_ANA_10TFD:	printf("FD"); break;
+		case MII_ANA_10THD:	printf("HD"); break;
+		default:		printf("FD/HD"); break;
+		}
+	}
+	if (techab & MII_ANA_PAUSE_SYM)
+	{
+		if (!fs)
+			printf(", ");
+		fs= 0;
+		printf("pause(SYM)");
+	}
+	if (techab & MII_ANA_PAUSE_ASYM)
+	{
+		if (!fs)
+			printf(", ");
+		fs= 0;
+		printf("pause(ASYM)");
+	}
+	if (techab & MII_ANA_TAF_RES)
+	{
+		if (!fs)
+			printf(", ");
+		fs= 0;
+		printf("0x%x", (techab & MII_ANA_TAF_RES) >> MII_ANA_TAF_S);
+	}
+}
+
+static void mii_print_stat_speed(stat, extstat)
+u16_t stat;
+u16_t extstat;
+{
+	int fs, ft;
+	fs= 1;
+	if (stat & MII_STATUS_EXT_STAT)
+	{
+		if (extstat & (MII_ESTAT_1000XFD | MII_ESTAT_1000XHD |
+			MII_ESTAT_1000TFD | MII_ESTAT_1000THD))
+		{
+			printf("1000 Mbps: ");
+			fs= 0;
+			ft= 1;
+			if (extstat & (MII_ESTAT_1000XFD | MII_ESTAT_1000XHD))
+			{
+				ft= 0;
+				printf("X-");
+				switch(extstat &
+					(MII_ESTAT_1000XFD|MII_ESTAT_1000XHD))
+				{
+				case MII_ESTAT_1000XFD:	printf("FD"); break;
+				case MII_ESTAT_1000XHD:	printf("HD"); break;
+				default:		printf("FD/HD"); break;
+				}
+			}
+			if (extstat & (MII_ESTAT_1000TFD | MII_ESTAT_1000THD))
+			{
+				if (!ft)
+					printf(", ");
+				ft= 0;
+				printf("T-");
+				switch(extstat &
+					(MII_ESTAT_1000TFD|MII_ESTAT_1000THD))
+				{
+				case MII_ESTAT_1000TFD:	printf("FD"); break;
+				case MII_ESTAT_1000THD:	printf("HD"); break;
+				default:		printf("FD/HD"); break;
+				}
+			}
+		}
+	}
+	if (stat & (MII_STATUS_100T4 |
+		MII_STATUS_100XFD | MII_STATUS_100XHD |
+		MII_STATUS_100T2FD | MII_STATUS_100T2HD))
+	{
+		if (!fs)
+			printf(", ");
+		fs= 0;
+		printf("100 Mbps: ");
+		ft= 1;
+		if (stat & MII_STATUS_100T4)
+		{
+			printf("T4");
+			ft= 0;
+		}
+		if (stat & (MII_STATUS_100XFD | MII_STATUS_100XHD))
+		{
+			if (!ft)
+				printf(", ");
+			ft= 0;
+			printf("TX-");
+			switch(stat & (MII_STATUS_100XFD|MII_STATUS_100XHD))
+			{
+			case MII_STATUS_100XFD:	printf("FD"); break;
+			case MII_STATUS_100XHD:	printf("HD"); break;
+			default:		printf("FD/HD"); break;
+			}
+		}
+		if (stat & (MII_STATUS_100T2FD | MII_STATUS_100T2HD))
+		{
+			if (!ft)
+				printf(", ");
+			ft= 0;
+			printf("T2-");
+			switch(stat & (MII_STATUS_100T2FD|MII_STATUS_100T2HD))
+			{
+			case MII_STATUS_100T2FD:	printf("FD"); break;
+			case MII_STATUS_100T2HD:	printf("HD"); break;
+			default:		printf("FD/HD"); break;
+			}
+		}
+	}
+	if (stat & (MII_STATUS_10FD | MII_STATUS_10HD))
+	{
+		if (!fs)
+			printf(", ");
+		printf("10 Mbps: ");
+		fs= 0;
+		printf("T-");
+		switch(stat & (MII_STATUS_10FD|MII_STATUS_10HD))
+		{
+		case MII_STATUS_10FD:	printf("FD"); break;
+		case MII_STATUS_10HD:	printf("HD"); break;
+		default:		printf("FD/HD"); break;
+		}
+	}
+}
+
+/*===========================================================================*
+ *				rl_clear_rx				     *
+ *===========================================================================*/
+static void rl_clear_rx(rep)
+re_t *rep;
+{
+	port_t port;
+	u8_t cr;
+	int i;
+	clock_t t0,t1;
+
+	rep->re_clear_rx= FALSE;
+	port= rep->re_base_port;
+
+	/* Reset the receiver */
+	cr= rl_inb(port, RL_CR);
+	cr &= ~RL_CR_RE;
+	rl_outb(port, RL_CR, cr);
+	getuptime(&t0);
+	do {
+		if (!(rl_inb(port, RL_CR) & RL_CR_RE))
+			break;
+	} while (getuptime(&t1)==OK && (t1-t0) < HZ);
+	if (rl_inb(port, RL_CR) & RL_CR_RE)
+		panic("rtl8139","cannot disable receiver", NO_NUM);
+
+#if 0
+	printf("RBSTART = 0x%08x\n", rl_inl(port, RL_RBSTART));
+	printf("CAPR = 0x%04x\n", rl_inw(port, RL_CAPR));
+	printf("CBR = 0x%04x\n", rl_inw(port, RL_CBR));
+	printf("RCR = 0x%08x\n", rl_inl(port, RL_RCR));
+#endif
+
+	rl_outb(port, RL_CR, cr | RL_CR_RE);
+
+	rl_outl(port, RL_RCR, RX_BUFBITS);
+
+	rl_rec_mode(rep);
+
+	rep->re_stat.ets_missedP++;
+}
+
+/*===========================================================================*
+ *				rl_do_reset				     *
+ *===========================================================================*/
+static void rl_do_reset(rep)
+re_t *rep;
+{
+	rep->re_need_reset= FALSE;
+	rl_reset_hw(rep);
+	rl_rec_mode(rep);
+
+	rep->re_tx_head= 0;
+	if (rep->re_flags & REF_SEND_AVAIL)
+	{
+		rep->re_tx[rep->re_tx_head].ret_busy= FALSE;
+		rep->re_send_int= TRUE;
+	}
+}
+
+/*===========================================================================*
+ *				rl_getstat				     *
+ *===========================================================================*/
+static void rl_getstat(mp)
+message *mp;
+{
+	int port;
+	eth_stat_t stats;
+	re_t *rep;
+
+	port = mp->DL_PORT;
+	if (port < 0 || port >= RE_PORT_NR)
+		panic("rtl8139","illegal port", port);
+	rep= &re_table[port];
+	rep->re_client= mp->DL_PROC;
+
+	assert(rep->re_mode == REM_ENABLED);
+	assert(rep->re_flags & REF_ENABLED);
+
+	stats= rep->re_stat;
+
+	put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+		(vir_bytes) sizeof(stats), &stats);
+	reply(rep, OK, FALSE);
+}
+
+
+/*===========================================================================*
+ *				rl_getname				     *
+ *===========================================================================*/
+static void rl_getname(mp)
+message *mp;
+{
+	int r;
+
+	strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
+	mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
+	mp->m_type= DL_NAME_REPLY;
+	r= send(mp->m_source, mp);
+	if (r != OK)
+		panic("RTL8139", "rl_getname: send failed: %d\n", r);
+}
+
+
+/*===========================================================================*
+ *				reply					     *
+ *===========================================================================*/
+static void reply(rep, err, may_block)
+re_t *rep;
+int err;
+int may_block;
+{
+	message reply;
+	int status;
+	int r;
+	clock_t now;
+
+	status = 0;
+	if (rep->re_flags & REF_PACK_SENT)
+		status |= DL_PACK_SEND;
+	if (rep->re_flags & REF_PACK_RECV)
+		status |= DL_PACK_RECV;
+
+	reply.m_type = DL_TASK_REPLY;
+	reply.DL_PORT = rep - re_table;
+	reply.DL_PROC = rep->re_client;
+	reply.DL_STAT = status | ((u32_t) err << 16);
+	reply.DL_COUNT = rep->re_read_s;
+	if (OK != (r = getuptime(&now)))
+		panic("rtl8139","getuptime() failed:", r);
+	reply.DL_CLCK = now;
+
+	r= send(rep->re_client, &reply);
+
+	if (r == ELOCKED && may_block)
+	{
+#if 0
+		printW(); printf("send locked\n");
+#endif
+		return;
+	}
+
+	if (r < 0) {
+		printf("RTL8139 tried sending to %d, type %d\n", rep->re_client, reply.m_type);
+		panic("rtl8139","send failed:", r);
+	}
+	
+	rep->re_read_s = 0;
+	rep->re_flags &= ~(REF_PACK_SENT | REF_PACK_RECV);
+}
+
+/*===========================================================================*
+ *				mess_reply				     *
+ *===========================================================================*/
+static void mess_reply(req, reply_mess)
+message *req;
+message *reply_mess;
+{
+	if (send(req->m_source, reply_mess) != OK)
+		panic("rtl8139","unable to mess_reply", NO_NUM);
+}
+
+/*===========================================================================*
+ *				put_userdata				     *
+ *===========================================================================*/
+static void put_userdata(user_proc, user_addr, count, loc_addr)
+int user_proc;
+vir_bytes user_addr;
+vir_bytes count;
+void *loc_addr;
+{
+	int cps;
+	cps = sys_datacopy(SELF, (vir_bytes) loc_addr, user_proc, user_addr, count);
+	if (cps != OK) printf("RTL8139: warning, scopy failed: %d\n", cps);
+}
+
+#if 0
+static void dump_phy(rep)
+re_t *rep;
+{
+	port_t port;
+	u32_t t;
+
+	port= rep->re_base_port;
+
+	t= rl_inb(port, RL_MSR);
+	printf("MSR: 0x%02lx\n", t);
+	if (t & RL_MSR_SPEED_10)
+		printf("\t10 Mbps\n");
+	if (t & RL_MSR_LINKB)
+		printf("\tLink failed\n");
+
+	t= rl_inb(port, RL_CONFIG1);
+	printf("CONFIG1: 0x%02lx\n", t);
+
+	t= rl_inb(port, RL_CONFIG3);
+	printf("CONFIG3: 0x%02lx\n", t);
+
+	t= rl_inb(port, RL_CONFIG4);
+	printf("CONFIG4: 0x%02lx\n", t);
+
+	t= rl_inw(port, RL_BMCR);
+	printf("BMCR (MII_CTRL): 0x%04lx\n", t);
+
+	t= rl_inw(port, RL_BMSR);
+	printf("BMSR:");
+	if (t & MII_STATUS_100T4)
+		printf(" 100Base-T4");
+	if (t & MII_STATUS_100XFD)
+		printf(" 100Base-X-FD");
+	if (t & MII_STATUS_100XHD)
+		printf(" 100Base-X-HD");
+	if (t & MII_STATUS_10FD)
+		printf(" 10Mbps-FD");
+	if (t & MII_STATUS_10HD)
+		printf(" 10Mbps-HD");
+	if (t & MII_STATUS_100T2FD)
+		printf(" 100Base-T2-FD");
+	if (t & MII_STATUS_100T2HD)
+		printf(" 100Base-T2-HD");
+	if (t & MII_STATUS_EXT_STAT)
+		printf(" Ext-stat");
+	if (t & MII_STATUS_RES)
+		printf(" res-0x%lx", t & MII_STATUS_RES);
+	if (t & MII_STATUS_MFPS)
+		printf(" MFPS");
+	if (t & MII_STATUS_ANC)
+		printf(" ANC");
+	if (t & MII_STATUS_RF)
+		printf(" remote-fault");
+	if (t & MII_STATUS_ANA)
+		printf(" ANA");
+	if (t & MII_STATUS_LS)
+		printf(" Link");
+	if (t & MII_STATUS_JD)
+		printf(" Jabber");
+	if (t & MII_STATUS_EC)
+		printf(" Extended-capability");
+	printf("\n");
+
+	t= rl_inw(port, RL_ANAR);
+	printf("ANAR (MII_ANA): 0x%04lx\n", t);
+
+	t= rl_inw(port, RL_ANLPAR);
+	printf("ANLPAR: 0x%04lx\n", t);
+
+	t= rl_inw(port, RL_ANER);
+	printf("ANER (MII_ANE): ");
+	if (t & MII_ANE_RES)
+		printf(" res-0x%lx", t & MII_ANE_RES);
+	if (t & MII_ANE_PDF)
+		printf(" Par-Detect-Fault");
+	if (t & MII_ANE_LPNPA)
+		printf(" LP-Next-Page-Able");
+	if (t & MII_ANE_NPA)
+		printf(" Loc-Next-Page-Able");
+	if (t & MII_ANE_PR)
+		printf(" Page-Received");
+	if (t & MII_ANE_LPANA)
+		printf(" LP-Auto-Neg-Able");
+	printf("\n");
+
+	t= rl_inw(port, RL_NWAYTR);
+	printf("NWAYTR: 0x%04lx\n", t);
+	t= rl_inw(port, RL_CSCR);
+	printf("CSCR: 0x%04lx\n", t);
+
+	t= rl_inb(port, RL_CONFIG5);
+	printf("CONFIG5: 0x%02lx\n", t);
+}
+#endif
+
+static int do_hard_int(void)
+{
+	int i,s;
+
+	for (i=0; i < RE_PORT_NR; i ++) {
+
+		/* Run interrupt handler at driver level. */
+		rl_handler( &re_table[i]);
+
+		/* Reenable interrupts for this hook. */
+	if ((s=sys_irqenable(&re_table[i].re_hook_id)) != OK)
+		printf("RTL8139: error, couldn't enable interrupts: %d\n", s);
+	}
+}
+
+/*===========================================================================*
+ *				rl_handler				     *
+ *===========================================================================*/
+static int rl_handler(rep)
+re_t *rep;
+{
+	int i, port, tx_head, tx_tail, link_up;
+	u16_t isr, tsad;
+	u32_t tsd, tcr, ertxth;
+#if 0
+	u8_t cr;
+#endif
+	clock_t t0,t1;
+	int_event_check = FALSE;	/* disable check by default */
+
+	port= rep->re_base_port;
+
+	/* Ack interrupt */
+	isr= rl_inw(port, RL_ISR);
+	rl_outw(port, RL_ISR, isr);
+
+	if (isr & RL_IMR_FOVW)
+	{
+		isr &= ~RL_IMR_FOVW;
+		/* Should do anything? */
+
+		rep->re_stat.ets_fifoOver++;
+	}
+	if (isr & RL_IMR_PUN)
+	{
+		isr &= ~RL_IMR_PUN;
+
+		/* Either the link status changed or there was a TX fifo
+		 * underrun.
+		 */
+		link_up= !(rl_inb(port, RL_MSR) & RL_MSR_LINKB);
+		if (link_up != rep->re_link_up)
+		{
+			rep->re_report_link= TRUE;
+			rep->re_got_int= TRUE;
+			int_event_check = TRUE;
+		}
+	}
+	if (isr & RL_IMR_RXOVW)
+	{
+		isr &= ~RL_IMR_RXOVW;
+
+		/* Clear the receive buffer */
+		rep->re_clear_rx= TRUE;
+		rep->re_got_int= TRUE;
+		int_event_check = TRUE;
+	}
+
+	if (isr & (RL_ISR_RER | RL_ISR_ROK))
+	{
+		isr &= ~(RL_ISR_RER | RL_ISR_ROK);
+
+		if (!rep->re_got_int && (rep->re_flags & REF_READING))
+		{
+			rep->re_got_int= TRUE;
+			int_event_check = TRUE;
+		}
+	}
+#if 0
+	if ((isr & (RL_ISR_TER | RL_ISR_TOK)) &&
+		(rep->re_flags & REF_SEND_AVAIL) &&
+		(rep->re_tx[0].ret_busy || rep->re_tx[1].ret_busy ||
+		rep->re_tx[2].ret_busy || rep->re_tx[3].ret_busy))
+		
+	{
+		printf(
+	"rl_handler, SEND_AVAIL: tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
+			rep->re_tx_head, rep->re_tx_tail,
+			rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,
+			rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
+		printf(
+	"rl_handler: TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+			rl_inw(port, RL_TSAD),
+			rl_inl(port, RL_TSD0+0*4),
+			rl_inl(port, RL_TSD0+1*4),
+			rl_inl(port, RL_TSD0+2*4),
+			rl_inl(port, RL_TSD0+3*4));
+	}
+#endif
+	if ((isr & (RL_ISR_TER | RL_ISR_TOK)) || 1)
+	{
+		isr &= ~(RL_ISR_TER | RL_ISR_TOK);
+
+		tsad= rl_inw(port, RL_TSAD);
+		if (tsad & (RL_TSAD_TABT0|RL_TSAD_TABT1|
+			RL_TSAD_TABT2|RL_TSAD_TABT3))
+		{
+#if 0
+			/* Do we need a watch dog? */
+			/* Just reset the whole chip */
+			rep->re_need_reset= TRUE;
+			rep->re_got_int= TRUE;
+			int_event_check = TRUE;
+#elif 0
+			/* Reset transmitter */
+			rep->re_stat.ets_transAb++;
+
+			cr= rl_inb(port, RL_CR);
+			cr &= ~RL_CR_TE;
+			rl_outb(port, RL_CR, cr);
+			getuptime(&t0);
+			do {
+				if (!(rl_inb(port, RL_CR) & RL_CR_TE))
+					break;
+			} while (getuptime(&t1)==OK && (t1-t0) < HZ);
+			if (rl_inb(port, RL_CR) & RL_CR_TE)
+			{
+			  panic("rtl8139","cannot disable transmitter",
+					NO_NUM);
+			}
+			rl_outb(port, RL_CR, cr | RL_CR_TE);
+
+			tcr= rl_inl(port, RL_TCR);
+			rl_outl(port, RL_TCR, tcr | RL_TCR_IFG_STD);
+
+			printf("rl_handler: reset after abort\n");
+
+			if (rep->re_flags & REF_SEND_AVAIL)
+			{
+				printf("rl_handler: REF_SEND_AVAIL\n");
+				rep->re_send_int= TRUE;
+				rep->re_got_int= TRUE;
+				int_event_check = TRUE;
+			}
+			for (i= 0; i< N_TX_BUF; i++)
+				rep->re_tx[i].ret_busy= FALSE;
+			rep->re_tx_head= 0;
+#else
+			printf("rl_handler, TABT, tasd = 0x%04x\n",
+				tsad);
+
+			/* Find the aborted transmit request */
+			for (i= 0; i< N_TX_BUF; i++)
+			{
+				tsd= rl_inl(port, RL_TSD0+i*4);
+				if (tsd & RL_TSD_TABT)
+					break;
+			}
+			if (i >= N_TX_BUF)
+			{
+				printf(
+				"rl_handler: can't find aborted TX req.\n");
+			}
+			else
+			{
+				printf("TSD%d = 0x%04lx\n", i, tsd);
+
+				/* Set head and tail to this buffer */
+				rep->re_tx_head= rep->re_tx_tail= i;
+			}
+
+			/* Aborted transmission, just kick the device
+			 * and be done with it.
+			 */
+			rep->re_stat.ets_transAb++;
+			tcr= rl_inl(port, RL_TCR);
+			rl_outl(port, RL_TCR, tcr | RL_TCR_CLRABT);
+#endif
+		}
+
+		/* Transmit completed */
+		tx_head= rep->re_tx_head;
+		tx_tail= rep->re_tx_tail;
+		for (i= 0; i< 2*N_TX_BUF; i++)
+		{
+			if (!rep->re_tx[tx_tail].ret_busy)
+			{
+				/* Strange, this buffer is not in-use.
+				 * Increment tx_tail until tx_head is
+				 * reached (or until we find a buffer that
+				 * is in-use.
+				 */
+				if (tx_tail == tx_head)
+					break;
+				if (++tx_tail >= N_TX_BUF)
+					tx_tail= 0;
+				assert(tx_tail < RL_N_TX);
+				rep->re_tx_tail= tx_tail;
+				continue;
+			}
+			tsd= rl_inl(port, RL_TSD0+tx_tail*4);
+			if (!(tsd & RL_TSD_OWN))
+			{
+				/* Buffer is not yet ready */
+				break;
+			}
+
+			/* Should collect statistics */
+			if (tsd & RL_TSD_CRS)
+				rep->re_stat.ets_carrSense++;
+			if (tsd & RL_TSD_TABT)
+			{
+				printf("rl_handler, TABT, TSD%d = 0x%04lx\n",
+					tx_tail, tsd);
+				assert(0);	/* CLRABT is not all that
+						 * effective, why not?
+						 */
+				rep->re_stat.ets_transAb++;
+				tcr= rl_inl(port, RL_TCR);
+				rl_outl(port, RL_TCR, tcr | RL_TCR_CLRABT);
+			}
+			if (tsd & RL_TSD_OWC)
+				rep->re_stat.ets_OWC++;
+			if (tsd & RL_TSD_CDH)
+				rep->re_stat.ets_CDheartbeat++;
+
+			/* What about collisions? */
+			if (tsd & RL_TSD_TOK)
+				rep->re_stat.ets_packetT++;
+			else
+				rep->re_stat.ets_sendErr++;
+			if (tsd & RL_TSD_TUN)
+			{
+				rep->re_stat.ets_fifoUnder++;
+
+				/* Increase ERTXTH */
+				ertxth= tsd + (1 << RL_TSD_ERTXTH_S);
+				ertxth &= RL_TSD_ERTXTH_M;
+				if (debug && ertxth > rep->re_ertxth)
+				{
+					printf("%s: new ertxth: %ld bytes\n",
+						rep->re_name,
+						(ertxth >> RL_TSD_ERTXTH_S) *
+						32);
+					rep->re_ertxth= ertxth;
+				}
+			}
+			rep->re_tx[tx_tail].ret_busy= FALSE;
+
+#if 0
+			if (rep->re_flags & REF_SEND_AVAIL)
+			{
+			printf("TSD%d: %08lx\n", tx_tail, tsd);
+			printf(
+			"rl_handler: head %d, tail %d, busy: %d %d %d %d\n", 
+				tx_head, tx_tail,
+				rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy, 
+				rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
+			}
+#endif
+
+			if (++tx_tail >= N_TX_BUF)
+				tx_tail= 0;
+			assert(tx_tail < RL_N_TX);
+			rep->re_tx_tail= tx_tail;
+
+			if (rep->re_flags & REF_SEND_AVAIL)
+			{
+#if 0
+				printf("rl_handler: REF_SEND_AVAIL\n");
+#endif
+				rep->re_send_int= TRUE;
+				if (!rep->re_got_int)
+				{
+					rep->re_got_int= TRUE;
+					int_event_check = TRUE;
+				}
+			}
+		}
+		assert(i < 2*N_TX_BUF);
+	}
+	if (isr)
+	{
+		printf("rl_handler: unhandled interrupt: isr = 0x%04x\n",
+			isr);
+	}
+
+	return 1;
+}
+
+/*===========================================================================*
+ *				rl_watchdog_f				     *
+ *===========================================================================*/
+static void rl_watchdog_f(tp)
+timer_t *tp;
+{
+	int i;
+	re_t *rep;
+	/* Use a synchronous alarm instead of a watchdog timer. */
+	sys_setalarm(HZ, 0);
+
+	for (i= 0, rep = &re_table[0]; i<RE_PORT_NR; i++, rep++)
+	{
+		if (rep->re_mode != REM_ENABLED)
+			continue;
+		if (!(rep->re_flags & REF_SEND_AVAIL))
+		{
+			/* Assume that an idle system is alive */
+			rep->re_tx_alive= TRUE;
+			continue;
+		}
+		if (rep->re_tx_alive)
+		{
+			rep->re_tx_alive= FALSE;
+			continue;
+		}
+		printf("rl_watchdog_f: resetting port %d\n", i);
+		printf(
+	"TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+			rl_inw(rep->re_base_port, RL_TSAD),
+			rl_inl(rep->re_base_port, RL_TSD0+0*4),
+			rl_inl(rep->re_base_port, RL_TSD0+1*4),
+			rl_inl(rep->re_base_port, RL_TSD0+2*4),
+			rl_inl(rep->re_base_port, RL_TSD0+3*4));
+		printf("tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
+			rep->re_tx_head, rep->re_tx_tail,
+			rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,
+			rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
+		rep->re_need_reset= TRUE;
+		rep->re_got_int= TRUE;
+			
+		check_int_events();
+	}
+}
+
+#if 0
+
+_PROTOTYPE( static void rtl_init, (struct dpeth *dep)			);
+_PROTOTYPE( static u16_t get_ee_word, (dpeth_t *dep, int a)		);
+_PROTOTYPE( static void ee_wen, (dpeth_t *dep)				);
+_PROTOTYPE( static void set_ee_word, (dpeth_t *dep, int a, U16_t w)	);
+_PROTOTYPE( static void ee_wds, (dpeth_t *dep)				);
+
+static void rtl_init(dep)
+dpeth_t *dep;
+{
+	u8_t reg_a, reg_b, cr, config0, config2, config3;
+	int i;
+	char val[128];
+
+	printf("rtl_init called\n");
+	ne_init(dep);
+
+	/* ID */
+	outb_reg0(dep, DP_CR, CR_PS_P0);
+	reg_a = inb_reg0(dep, DP_DUM1);
+	reg_b = inb_reg0(dep, DP_DUM2);
+
+	printf("rtl_init: '%c', '%c'\n", reg_a, reg_b);
+
+	outb_reg0(dep, DP_CR, CR_PS_P3);
+	config0 = inb_reg3(dep, 3);
+	config2 = inb_reg3(dep, 5);
+	config3 = inb_reg3(dep, 6);
+	outb_reg0(dep, DP_CR, CR_PS_P0);
+
+	printf("rtl_init: config 0/2/3 = %x/%x/%x\n",
+		config0, config2, config3);
+
+	if (0 == sys_getkenv("RTL8029FD",9+1, val, sizeof(val)))
+	{
+		printf("rtl_init: setting full-duplex mode\n");
+		outb_reg0(dep, DP_CR, CR_PS_P3);
+
+		cr= inb_reg3(dep, 1);
+		outb_reg3(dep, 1, cr | 0xc0);
+
+		outb_reg3(dep, 6, config3 | 0x40);
+		config3 = inb_reg3(dep, 6);
+
+		config2= inb_reg3(dep, 5);
+		outb_reg3(dep, 5, config2 | 0x20);
+		config2= inb_reg3(dep, 5);
+
+		outb_reg3(dep, 1, cr);
+
+		outb_reg0(dep, DP_CR, CR_PS_P0);
+
+		printf("rtl_init: config 2 = %x\n", config2);
+		printf("rtl_init: config 3 = %x\n", config3);
+	}
+
+	for (i= 0; i<64; i++)
+		printf("%x ", get_ee_word(dep, i));
+	printf("\n");
+
+	if (0 == sys_getkenv("RTL8029MN",9+1, val, sizeof(val)))
+	{
+		ee_wen(dep);
+
+		set_ee_word(dep, 0x78/2, 0x10ec);
+		set_ee_word(dep, 0x7A/2, 0x8029);
+		set_ee_word(dep, 0x7C/2, 0x10ec);
+		set_ee_word(dep, 0x7E/2, 0x8029);
+
+		ee_wds(dep);
+
+		assert(get_ee_word(dep, 0x78/2) == 0x10ec);
+		assert(get_ee_word(dep, 0x7A/2) == 0x8029);
+		assert(get_ee_word(dep, 0x7C/2) == 0x10ec);
+		assert(get_ee_word(dep, 0x7E/2) == 0x8029);
+	}
+
+	if (0 == sys_getkenv("RTL8029XXX",10+1, val, sizeof(val)))
+	{
+		ee_wen(dep);
+
+		set_ee_word(dep, 0x76/2, 0x8029);
+
+		ee_wds(dep);
+
+		assert(get_ee_word(dep, 0x76/2) == 0x8029);
+	}
+}
+
+static u16_t get_ee_word(dep, a)
+dpeth_t *dep;
+int a;
+{
+	int b, i, cmd;
+	u16_t w;
+
+	outb_reg0(dep, DP_CR, CR_PS_P3);	/* Bank 3 */
+
+	/* Switch to 9346 mode and enable CS */
+	outb_reg3(dep, 1, 0x80 | 0x8);
+
+	cmd= 0x180 | (a & 0x3f);	/* 1 1 0 a5 a4 a3 a2 a1 a0 */
+	for (i= 8; i >= 0; i--)
+	{
+		b= (cmd & (1 << i));
+		b= (b ? 2 : 0);
+
+		/* Cmd goes out on the rising edge of the clock */
+		outb_reg3(dep, 1, 0x80 | 0x8 | b);
+		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
+	}
+	outb_reg3(dep, 1, 0x80 | 0x8);	/* End of cmd */
+
+	w= 0;
+	for (i= 0; i<16; i++)
+	{
+		w <<= 1;
+
+		/* Data is shifted out on the rising edge. Read at the
+		 * falling edge.
+		 */
+		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4);
+		outb_reg3(dep, 1, 0x80 | 0x8 | b);
+		b= inb_reg3(dep, 1);
+		w |= (b & 1);
+	}
+
+	outb_reg3(dep, 1, 0x80);		/* drop CS */
+	outb_reg3(dep, 1, 0x00);		/* back to normal */
+	outb_reg0(dep, DP_CR, CR_PS_P0);	/* back to bank 0 */
+
+	return w;
+}
+
+static void ee_wen(dep)
+dpeth_t *dep;
+{
+	int b, i, cmd;
+	u16_t w;
+
+	outb_reg0(dep, DP_CR, CR_PS_P3);	/* Bank 3 */
+
+	/* Switch to 9346 mode and enable CS */
+	outb_reg3(dep, 1, 0x80 | 0x8);
+
+	cmd= 0x130;		/* 1 0 0 1 1 x x x x */
+	for (i= 8; i >= 0; i--)
+	{
+		b= (cmd & (1 << i));
+		b= (b ? 2 : 0);
+
+		/* Cmd goes out on the rising edge of the clock */
+		outb_reg3(dep, 1, 0x80 | 0x8 | b);
+		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
+	}
+	outb_reg3(dep, 1, 0x80 | 0x8);	/* End of cmd */
+	outb_reg3(dep, 1, 0x80);	/* Drop CS */
+	/* micro_delay(1); */			/* Is this required? */
+}
+
+static void set_ee_word(dep, a, w)
+dpeth_t *dep;
+int a;
+u16_t w;
+{
+	int b, i, cmd;
+	clock_t t0, t1;
+
+	outb_reg3(dep, 1, 0x80 | 0x8);		/* Set CS */
+
+	cmd= 0x140 | (a & 0x3f);		/* 1 0 1 a5 a4 a3 a2 a1 a0 */
+	for (i= 8; i >= 0; i--)
+	{
+		b= (cmd & (1 << i));
+		b= (b ? 2 : 0);
+
+		/* Cmd goes out on the rising edge of the clock */
+		outb_reg3(dep, 1, 0x80 | 0x8 | b);
+		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
+	}
+	for (i= 15; i >= 0; i--)
+	{
+		b= (w & (1 << i));
+		b= (b ? 2 : 0);
+
+		/* Cmd goes out on the rising edge of the clock */
+		outb_reg3(dep, 1, 0x80 | 0x8 | b);
+		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
+	}
+	outb_reg3(dep, 1, 0x80 | 0x8);	/* End of data */
+	outb_reg3(dep, 1, 0x80);	/* Drop CS */
+	/* micro_delay(1); */			/* Is this required? */
+	outb_reg3(dep, 1, 0x80 | 0x8);		/* Set CS */
+	getuptime(&t0);
+	do {
+		if (inb_reg3(dep, 1) & 1)
+			break;
+	} while (getuptime(&t1) == OK && (t1 == t0));
+	if (!(inb_reg3(dep, 1) & 1))
+		panic("set_ee_word","device remains busy", NO_NUM);
+}
+
+static void ee_wds(dep)
+dpeth_t *dep;
+{
+	int b, i, cmd;
+	u16_t w;
+
+	outb_reg0(dep, DP_CR, CR_PS_P3);	/* Bank 3 */
+
+	/* Switch to 9346 mode and enable CS */
+	outb_reg3(dep, 1, 0x80 | 0x8);
+
+	cmd= 0x100;		/* 1 0 0 0 0 x x x x */
+	for (i= 8; i >= 0; i--)
+	{
+		b= (cmd & (1 << i));
+		b= (b ? 2 : 0);
+
+		/* Cmd goes out on the rising edge of the clock */
+		outb_reg3(dep, 1, 0x80 | 0x8 | b);
+		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
+	}
+	outb_reg3(dep, 1, 0x80 | 0x8);	/* End of cmd */
+	outb_reg3(dep, 1, 0x80);	/* Drop CS */
+	outb_reg3(dep, 1, 0x00);		/* back to normal */
+	outb_reg0(dep, DP_CR, CR_PS_P0);	/* back to bank 0 */
+}
+#endif
+
+/*
+ * $PchId: rtl8139.c,v 1.3 2003/09/11 14:15:15 philip Exp $
+ */
Index: /trunk/minix/drivers/rtl8139/rtl8139.h
===================================================================
--- /trunk/minix/drivers/rtl8139/rtl8139.h	(revision 9)
+++ /trunk/minix/drivers/rtl8139/rtl8139.h	(revision 9)
@@ -0,0 +1,429 @@
+/*
+ibm/rtl8139.h
+
+Created:	Aug 2003 by Philip Homburg <philip@cs.vu.nl>
+*/
+
+#define	RL_IDR		0x00	/* Ethernet address
+				 * Note: RL_9346CR_EEM_CONFIG mode is
+				 * required the change the ethernet
+				 * address.
+				 * Note: 4-byte write access only.
+				 */
+#define		RL_N_TX		4	/* Number of transmit buffers */
+#define	RL_TSD0	0x010	/* Transmit Status of Descriptor 0 */
+#define		RL_TSD_CRS	0x80000000 /* Carrier Sense Lost */
+#define		RL_TSD_TABT	0x40000000 /* Transmit Abort */
+#define		RL_TSD_OWC	0x20000000 /* Out of Window Collision */
+#define		RL_TSD_CDH	0x10000000 /* CD Heart Beat */
+#define		RL_TSD_NCC_M	0x0F000000 /* Number of Collision Count */
+#define		RL_TSD_RES	0x00C00000 /* Reserved */
+#define		RL_TSD_ERTXTH_M	0x003F0000 /* Early Tx Threshold */
+#define			RL_TSD_ERTXTH_S		16		/* shift */
+#define			RL_TSD_ERTXTH_8		0x00000000	/* 8 bytes */
+#define		RL_TSD_TOK	0x00008000 /* Transmit OK */
+#define		RL_TSD_TUN	0x00004000 /* Transmit FIFO Underrun */
+#define		RL_TSD_OWN	0x00002000 /* Controller (does not) Own Buf. */
+#define		RL_TSD_SIZE	0x00001FFF /* Descriptor Size */
+#define RL_TSAD0	0x20	/* Transmit Start Address of Descriptor 0 */
+#define RL_RBSTART	0x30	/* Receive Buffer Start Address */
+#define	RL_CR		0x37	/* Command Register */
+#define		RL_CR_RES0	0xE0	/* Reserved */
+#define		RL_CR_RST	0x10	/* Reset */
+#define		RL_CR_RE	0x08	/* Receiver Enable */
+#define		RL_CR_TE	0x04	/* Transmitter Enable *
+					 * Note: start with transmit buffer
+					 * 0 after RL_CR_TE has been reset.
+					 */
+#define		RL_CR_RES1	0x02	/* Reserved */
+#define		RL_CR_BUFE	0x01	/* Receive Buffer Empty */
+#define	RL_CAPR		0x38	/* Current Address of Packet Read */
+#define		RL_CAPR_DATA_OFF	0x10	/* Packet Starts at Offset */
+#define	RL_CBR		0x3A	/* Current Buffer Address */
+#define	RL_IMR		0x3C	/* Interrupt Mask Register */
+#define		RL_IMR_SERR	0x8000	/* System Error */
+#define		RL_IMR_TIMEOUT	0x4000	/* Time Out */
+#define		RL_IMR_LENCHG	0x2000	/* Cable Length Change */
+#define		RL_IMR_RES	0x1F80	/* Reserved */
+#define		RL_IMR_FOVW	0x0040	/* Rx FIFO Overflow */
+#define		RL_IMR_PUN	0x0020	/* Packet Underrun / Link Change */
+#define		RL_IMR_RXOVW	0x0010	/* Rx Buffer Overflow */
+#define		RL_IMR_TER	0x0008	/* Transmit Error */
+#define		RL_IMR_TOK	0x0004	/* Transmit OK */
+#define		RL_IMR_RER	0x0002	/* Receive Error */
+#define		RL_IMR_ROK	0x0001	/* Receive OK */
+#define	RL_ISR		0x3E	/* Interrupt Status Register */
+#define		RL_ISR_SERR	0x8000	/* System Error */
+#define		RL_ISR_TIMEOUT	0x4000	/* Time Out */
+#define		RL_ISR_LENCHG	0x2000	/* Cable Length Change */
+#define		RL_ISR_RES	0x1F80	/* Reserved */
+#define		RL_ISR_FOVW	0x0040	/* Rx FIFO Overflow */
+#define		RL_ISR_PUN	0x0020	/* Packet Underrun / Link Change */
+#define		RL_ISR_RXOVW	0x0010	/* Rx Buffer Overflow */
+#define		RL_ISR_TER	0x0008	/* Transmit Error */
+#define		RL_ISR_TOK	0x0004	/* Transmit OK */
+#define		RL_ISR_RER	0x0002	/* Receive Error */
+#define		RL_ISR_ROK	0x0001	/* Receive OK */
+#define	RL_TCR		0x40	/* Transmit Configuration Register
+				 * Note: RL_CR_TE has to be set to
+				 * set/change RL_TCR.
+				 */
+#define		RL_TCR_RES0	0x80000000 /* Reserved */
+#define		RL_TCR_HWVER_AM 0x7C000000 /* Hardware Version ID A */
+#define		RL_TCR_IFG_M	0x03000000 /* Interframe Gap Time */
+#define			RL_TCR_IFG_STD		0x03000000 /* IEEE 802.3 std */
+#if 0
+#undef RL_TCR_IFG_STD
+#define			RL_TCR_IFG_STD		0x00000000 
+#endif
+#define		RL_TCR_HWVER_BM	0x00C00000 /* Hardware Version ID B */
+#define			RL_TCR_HWVER_RTL8139	0x60000000 /* RTL8139 */
+#define			RL_TCR_HWVER_RTL8139A	0x70000000 /* RTL8139A */
+#define			RL_TCR_HWVER_RTL8139AG	0x74000000 /* RTL8139A-G */
+#define			RL_TCR_HWVER_RTL8139B	0x78000000 /* RTL8139B */
+#define			RL_TCR_HWVER_RTL8130	0x78000000 /* RTL8130 (dup) */
+#define			RL_TCR_HWVER_RTL8139C	0x74000000 /* RTL8139C (dup) */
+#define			RL_TCR_HWVER_RTL8100	0x78800000 /* RTL8100 */
+#define			RL_TCR_HWVER_RTL8100B	0x74400000 /* RTL8100B /
+								RTL8139D */
+#define			RL_TCR_HWVER_RTL8139CP	0x74800000 /* RTL8139C+ */
+#define			RL_TCR_HWVER_RTL8101	0x74C00000 /* RTL8101 */
+#define		RL_TCR_RES1	0x00380000 /* Reserved */
+#define		RL_TCR_LBK_M	0x00060000 /* Loopback Test */
+#define			RL_TCR_LBK_NORMAL	0x00000000 /* Normal */
+#define			RL_TCR_LBK_LOOKBOCK	0x00060000 /* Loopback Mode */
+#define		RL_TCR_CRC	0x00010000 /* (Do not) Append CRC */
+#define		RL_TCR_RES2	0x0000F800 /* Reserved */
+#define		RL_TCR_MXDMA_M	0x00000700 /* Max DMA Burst Size Tx */
+#define			RL_TCR_MXDMA_16		0x00000000 /* 16 bytes */
+#define			RL_TCR_MXDMA_32		0x00000100 /* 32 bytes */
+#define			RL_TCR_MXDMA_64		0x00000200 /* 64 bytes */
+#define			RL_TCR_MXDMA_128	0x00000300 /* 128 bytes */
+#define			RL_TCR_MXDMA_128	0x00000300 /* 128 bytes */
+#define			RL_TCR_MXDMA_256	0x00000400 /* 256 bytes */
+#define			RL_TCR_MXDMA_512	0x00000500 /* 512 bytes */
+#define			RL_TCR_MXDMA_1024	0x00000600 /* 1024 bytes */
+#define			RL_TCR_MXDMA_2048	0x00000700 /* 2048 bytes */
+#define		RL_TCR_TXRR_M	0x000000F0 /* Tx Retry Count */
+#define		RL_TCR_RES3	0x0000000E /* Reserved */
+#define		RL_TCR_CLRABT	0x00000001 /* Clear Abort */
+#define RL_RCR		0x44	/* Receive Configuration Register
+				 * Note: RL_CR_RE has to be set to
+				 * set/change RL_RCR.
+				 */
+#define		RL_RCR_RES0	0xF0000000 /& Reserved */
+#define		RL_RCR_ERTH_M	0x0F000000 /* Early Rx Threshold */
+#define			RL_RCR_ERTH_0		0x00000000 /* No threshold */
+#define			RL_RCR_ERTH_1		0x01000000 /* 1/16 */
+#define			RL_RCR_ERTH_2		0x02000000 /* 2/16 */
+#define			RL_RCR_ERTH_3		0x03000000 /* 3/16 */
+#define			RL_RCR_ERTH_4		0x04000000 /* 4/16 */
+#define			RL_RCR_ERTH_5		0x05000000 /* 5/16 */
+#define			RL_RCR_ERTH_6		0x06000000 /* 6/16 */
+#define			RL_RCR_ERTH_7		0x07000000 /* 7/16 */
+#define			RL_RCR_ERTH_8		0x08000000 /* 8/16 */
+#define			RL_RCR_ERTH_9		0x09000000 /* 9/16 */
+#define			RL_RCR_ERTH_10		0x0A000000 /* 10/16 */
+#define			RL_RCR_ERTH_11		0x0B000000 /* 11/16 */
+#define			RL_RCR_ERTH_12		0x0C000000 /* 12/16 */
+#define			RL_RCR_ERTH_13		0x0D000000 /* 13/16 */
+#define			RL_RCR_ERTH_14		0x0E000000 /* 14/16 */
+#define			RL_RCR_ERTH_15		0x0F000000 /* 15/16 */
+#define		RL_RCR_RES1	0x00FC0000 /* Reserved */
+#define		RL_RCR_MULERINT	0x00020000 /* Multiple Early Int Select */
+#define		RL_RCR_RER8	0x00010000 /* Receive small error packet */
+#define		RL_RCR_RXFTH_M	0x0000E000 /* Rx FIFO Threshold */
+#define			RL_RCR_RXFTH_16		0x00000000 /* 16 bytes */
+#define			RL_RCR_RXFTH_32		0x00002000 /* 32 bytes */
+#define			RL_RCR_RXFTH_64		0x00004000 /* 64 bytes */
+#define			RL_RCR_RXFTH_128	0x00006000 /* 128 bytes */
+#define			RL_RCR_RXFTH_256	0x00008000 /* 256 bytes */
+#define			RL_RCR_RXFTH_512	0x0000A000 /* 512 bytes */
+#define			RL_RCR_RXFTH_1024	0x0000C000 /* 1024 bytes */
+#define			RL_RCR_RXFTH_UNLIM	0x0000E000 /* unlimited */
+#define		RL_RCR_RBLEM_M	0x00001800 /* Rx Buffer Length */
+#define			RL_RCR_RBLEN_8K		0x00000000 /* 8KB + 16 bytes */
+#define			RL_RCR_RBLEN_8K_SIZE	(8*1024)
+#define			RL_RCR_RBLEN_16K	0x00000800 /* 16KB + 16 bytes */
+#define			RL_RCR_RBLEN_16K_SIZE	(16*1024)
+#define			RL_RCR_RBLEN_32K	0x00001000 /* 32KB + 16 bytes */
+#define			RL_RCR_RBLEN_32K_SIZE	(32*1024)
+#define			RL_RCR_RBLEN_64K	0x00001800 /* 64KB + 16 bytes */
+#define			RL_RCR_RBLEN_64K_SIZE	(64*1024)
+			/* Note: the documentation for the RTL8139C(L) or
+			 * for the RTL8139D(L) claims that the buffer should
+			 * be 16 bytes larger. Multiples of 8KB are the 
+			 * correct values.
+			 */
+#define		RL_RCR_MXDMA_M	0x00000700 /* Rx DMA burst size */
+#define			RL_RCR_MXDMA_16		0x00000000 /* 16 bytes */
+#define			RL_RCR_MXDMA_32		0x00000100 /* 32 bytes */
+#define			RL_RCR_MXDMA_64		0x00000200 /* 64 bytes */
+#define			RL_RCR_MXDMA_128	0x00000300 /* 128 bytes */
+#define			RL_RCR_MXDMA_256	0x00000400 /* 256 bytes */
+#define			RL_RCR_MXDMA_512	0x00000500 /* 512 bytes */
+#define			RL_RCR_MXDMA_1024	0x00000600 /* 1024 bytes */
+#define			RL_RCR_MXDMA_UNLIM	0x00000700 /* unlimited */
+#define		RL_RCR_WRAP	0x00000080 /* (Do not) Wrap on receive */
+#define		RL_RCR_RES2	0x00000040 /* EEPROM type? */
+#define		RL_RCR_AER	0x00000020 /* Accept Error Packets */
+#define		RL_RCR_AR	0x00000010 /* Accept Runt Packets */
+#define		RL_RCR_AB	0x00000008 /* Accept Broadcast Packets */
+#define		RL_RCR_AM	0x00000004 /* Accept Multicast Packets */
+#define		RL_RCR_APM	0x00000002 /* Accept Physical Match Packets */
+#define		RL_RCR_AAP	0x00000001 /* Accept All Packets */
+#define	RL_MPC		0x4c	/* Missed Packet Counter */
+#define	RL_9346CR	0x50	/* 93C46 Command Register */
+#define		RL_9346CR_EEM_M	0xC0	/* Operating Mode */
+#define			RL_9346CR_EEM_NORMAL	0x00 /* Normal Mode */
+#define			RL_9346CR_EEM_AUTOLOAD	0x40 /* Load from 93C46 */
+#define			RL_9346CR_EEM_PROG	0x80 /* 93C46 Programming */
+#define			RL_9346CR_EEM_CONFIG	0xC0 /* Config Write Enable */
+#define		RL_9346CR_RES	0x30	/* Reserved */
+#define		RL_9346CR_EECS	0x08	/* EECS Pin */
+#define		RL_9346CR_EESK	0x04	/* EESK Pin */
+#define		RL_9346CR_EEDI	0x02	/* EEDI Pin */
+#define		RL_9346CR_EEDO	0x01	/* EEDO Pin */
+#define RL_CONFIG0	0x51	/* Configuration Register 0 */
+#define RL_CONFIG1	0x52	/* Configuration Register 1 */
+#define RL_MSR		0x58	/* Media Status Register */
+#define		RL_MSR_TXFCE	0x80	/* Tx Flow Control Enable */
+#define		RL_MSR_RXFCE	0x40	/* Rx Flow Control Enable */
+#define		RL_MSR_RES	0x20	/* Reserved */
+#define		RL_MSR_AUXSTAT	0x10	/* Aux. Power Present */
+#define		RL_MSR_SPEED_10	0x08	/* In 10 Mbps mode */
+#define		RL_MSR_LINKB	0x04	/* link Failed */
+#define		RL_MSR_TXPF	0x02	/* Sent Pause Packet */
+#define		RL_MSR_RXPF	0x01	/* Received Pause Packet */
+#define RL_CONFIG3	0x59	/* Configuration Register 3 */
+#define RL_CONFIG4	0x5A	/* Configuration Register 4 */
+/*			0x5B */	/* Reserved */
+#define RL_REVID	0x5E	/* PCI Revision ID */
+/*			0x5F */	/* Reserved */
+#define RL_TSAD		0x60	/* Transmit Status of All Descriptors */
+#define		RL_TSAD_TOK3	0x8000	/* TOK bit of Descriptor 3 */
+#define		RL_TSAD_TOK2	0x4000	/* TOK bit of Descriptor 2 */
+#define		RL_TSAD_TOK1	0x2000	/* TOK bit of Descriptor 1 */
+#define		RL_TSAD_TOK0	0x1000	/* TOK bit of Descriptor 0 */
+#define		RL_TSAD_TUN3	0x0800	/* TUN bit of Descriptor 3 */
+#define		RL_TSAD_TUN2	0x0400	/* TUN bit of Descriptor 2 */
+#define		RL_TSAD_TUN1	0x0200	/* TUN bit of Descriptor 1 */
+#define		RL_TSAD_TUN0	0x0100	/* TUN bit of Descriptor 0 */
+#define		RL_TSAD_TABT3	0x0080	/* TABT bit of Descriptor 3 */
+#define		RL_TSAD_TABT2	0x0040	/* TABT bit of Descriptor 2 */
+#define		RL_TSAD_TABT1	0x0020	/* TABT bit of Descriptor 1 */
+#define		RL_TSAD_TABT0	0x0010	/* TABT bit of Descriptor 0 */
+#define		RL_TSAD_OWN3	0x0008	/* OWN bit of Descriptor 3 */
+#define		RL_TSAD_OWN2	0x0004	/* OWN bit of Descriptor 2 */
+#define		RL_TSAD_OWN1	0x0002	/* OWN bit of Descriptor 1 */
+#define		RL_TSAD_OWN0	0x0001	/* OWN bit of Descriptor 0 */
+#define RL_BMCR		0x62	/* Basic Mode Control Register (MII_CTRL) */
+#define RL_BMSR		0x64	/* Basic Mode Status Register (MII_STATUS) */
+#define	RL_ANAR		0x66	/* Auto-Neg Advertisement Register (MII_ANA) */
+#define	RL_ANLPAR	0x68	/* Auto-Neg Link Partner Register (MII_ANLPA) */
+#define	RL_ANER		0x6a	/* Auto-Neg Expansion Register (MII_ANE) */
+#define	RL_NWAYTR	0x70	/* N-way Test Register */
+#define	RL_CSCR		0x74	/* CS Configuration Register */
+#define RL_CONFIG5	0xD8	/* Configuration Register 5 */
+
+/* Status word in receive buffer */
+#define RL_RXS_LEN_M	0xFFFF0000	/* Length Field, Excl. Status word */
+#define RL_RXS_LEN_S	16		/* Shift For Length */
+#define RL_RXS_MAR	0x00008000	/* Multicast Address Received */
+#define RL_RXS_PAR	0x00004000	/* Physical Address Matched */
+#define RL_RXS_BAR	0x00002000	/* Broadcast Address Received */
+#define RL_RXS_RES_M	0x00001FC0	/* Reserved */
+#define RL_RXS_ISE	0x00000020	/* Invalid Symbol Error */
+#define RL_RXS_RUNT	0x00000010	/* Runt Packet Received */
+#define RL_RXS_LONG	0x00000008	/* Long (>4KB) Packet */
+#define RL_RXS_CRC	0x00000004	/* CRC Error */
+#define RL_RXS_FAE	0x00000002	/* Frame Alignment Error */
+#define RL_RXS_ROK	0x00000001	/* Receive OK */
+
+/* Registers in the Machine Independent Interface (MII) to the PHY.
+ * IEEE 802.3 (2000 Edition) Clause 22.
+ */
+#define MII_CTRL	0x0	/* Control Register (basic) */
+#define		MII_CTRL_RST	0x8000	/* Reset PHY */
+#define		MII_CTRL_LB	0x4000	/* Enable Loopback Mode */
+#define		MII_CTRL_SP_LSB	0x2000	/* Speed Selection (LSB) */
+#define		MII_CTRL_ANE	0x1000	/* Auto Negotiation Enable */
+#define		MII_CTRL_PD	0x0800	/* Power Down */
+#define		MII_CTRL_ISO	0x0400	/* Isolate */
+#define		MII_CTRL_RAN	0x0200	/* Restart Auto-Negotiation Process */
+#define		MII_CTRL_DM	0x0100	/* Full Duplex */
+#define		MII_CTRL_CT	0x0080	/* Enable COL Signal Test */
+#define		MII_CTRL_SP_MSB	0x0040	/* Speed Selection (MSB) */
+#define			MII_CTRL_SP_10		0x0000	/* 10 Mb/s */
+#define			MII_CTRL_SP_100		0x2000	/* 100 Mb/s */
+#define			MII_CTRL_SP_1000	0x0040	/* 1000 Mb/s */
+#define			MII_CTRL_SP_RES		0x2040	/* Reserved */
+#define		MII_CTRL_RES	0x003F	/* Reserved */
+#define MII_STATUS	0x1	/* Status Register (basic) */
+#define		MII_STATUS_100T4	0x8000	/* 100Base-T4 support */
+#define		MII_STATUS_100XFD	0x4000	/* 100Base-X FD support */
+#define		MII_STATUS_100XHD	0x2000	/* 100Base-X HD support */
+#define		MII_STATUS_10FD		0x1000	/* 10 Mb/s FD support */
+#define		MII_STATUS_10HD		0x0800	/* 10 Mb/s HD support */
+#define		MII_STATUS_100T2FD	0x0400	/* 100Base-T2 FD support */
+#define		MII_STATUS_100T2HD	0x0200	/* 100Base-T2 HD support */
+#define		MII_STATUS_EXT_STAT	0x0100	/* Supports MII_EXT_STATUS */
+#define		MII_STATUS_RES		0x0080	/* Reserved */
+#define		MII_STATUS_MFPS		0x0040	/* MF Preamble Suppression */
+#define		MII_STATUS_ANC		0x0020	/* Auto-Negotiation Completed */
+#define		MII_STATUS_RF		0x0010	/* Remote Fault Detected */
+#define		MII_STATUS_ANA		0x0008	/* Auto-Negotiation Ability */
+#define		MII_STATUS_LS		0x0004	/* Link Up */
+#define		MII_STATUS_JD		0x0002	/* Jabber Condition Detected */
+#define		MII_STATUS_EC		0x0001	/* Ext Register Capabilities */
+#define MII_PHYID_H	0x2	/* PHY ID (high) */
+#define MII_PHYID_L	0x3	/* PHY ID (low) */
+#define MII_ANA		0x4	/* Auto-Negotiation Advertisement */
+#define		MII_ANA_NP	0x8000	/* Next PAge */
+#define		MII_ANA_RES	0x4000	/* Reserved */
+#define		MII_ANA_RF	0x2000	/* Remote Fault */
+#define		MII_ANA_TAF_M	0x1FE0	 /* Technology Ability Field */
+#define		MII_ANA_TAF_S	5	 /* Shift */
+#define			MII_ANA_TAF_RES		0x1000	/* Reserved */
+#define			MII_ANA_PAUSE_ASYM	0x0800	/* Asym. Pause */
+#define			MII_ANA_PAUSE_SYM	0x0400	/* Sym. Pause */
+#define			MII_ANA_100T4		0x0200	/* 100Base-T4 */
+#define			MII_ANA_100TXFD		0x0100	/* 100Base-TX FD */
+#define			MII_ANA_100TXHD		0x0080	/* 100Base-TX HD */
+#define			MII_ANA_10TFD		0x0040	/* 10Base-T FD */
+#define			MII_ANA_10THD		0x0020	/* 10Base-T HD */
+#define		MII_ANA_SEL_M	0x001F	 /* Selector Field */
+#define			MII_ANA_SEL_802_3 0x0001 /* 802.3 */
+#define MII_ANLPA	0x5	/* Auto-Neg Link Partner Ability Register */
+#define		MII_ANLPA_NP	0x8000	/* Next Page */
+#define		MII_ANLPA_ACK	0x4000	/* Acknowledge */
+#define		MII_ANLPA_RF	0x2000	/* Remote Fault */
+#define		MII_ANLPA_TAF_M	0x1FC0	 /* Technology Ability Field */
+#define		MII_ANLPA_SEL_M	0x001F	 /* Selector Field */
+#define MII_ANE		0x6	/* Auto-Negotiation Expansion */
+#define		MII_ANE_RES	0xFFE0	/* Reserved */
+#define		MII_ANE_PDF	0x0010	/* Parallel Detection Fault */
+#define		MII_ANE_LPNPA	0x0008	/* Link Partner is Next Page Able */
+#define		MII_ANE_NPA	0x0002	/* Local Device is Next Page Able */
+#define		MII_ANE_PR	0x0002	/* New Page has been received */
+#define		MII_ANE_LPANA	0x0001	/* Link Partner is Auto-Neg.able */
+#define MII_ANNPT	0x7	/* Auto-Negotiation Next Page Transmit */
+#define MII_ANLPRNP	0x8	/* Auto-Neg Link Partner Received Next Page */
+#define MII_MS_CTRL	0x9	/* MASTER-SLAVE Control Register */
+#define MII_MS_STATUS	0xA	/* MASTER-SLAVE Status Register */
+/* 0xB ... 0xE */		/* Reserved */
+#define MII_EXT_STATUS	0xF	/* Extended Status */
+#define		MII_ESTAT_1000XFD	0x8000	/* 1000Base-X Full Duplex */
+#define		MII_ESTAT_1000XHD	0x4000	/* 1000Base-X Half Duplex */
+#define		MII_ESTAT_1000TFD	0x2000	/* 1000Base-T Full Duplex */
+#define		MII_ESTAT_1000THD	0x1000	/* 1000Base-T Half Duplex */
+#define		MII_ESTAT_RES		0x0FFF	/* Reserved */
+/* 0x10 ... 0x1F */		/* Vendor Specific */
+
+#if 0
+34-35	R	ERBCR		Early Receive (Rx) Byte Count Register
+36	R	ERSR		Early Rx Status Register
+	7-4			reserved
+	3	R	ERGood	Early Rx Good packet
+	2	R	ERBad	Early Rx Bad packet
+	1	R	EROVW	Early Rx OverWrite
+	0	R	EROK	Early Rx OK
+51	R/W	CONFIG0		Configuration Register 0
+	7	R	SCR	Scrambler Mode
+	6	R	PCS	PCS Mode
+	5	R	T10	10 Mbps Mode
+	4-3	R	PL[1-0]	Select 10 Mbps medium type
+	2-0	R	BS[2-0]	Select Boot ROM size
+52	R/W	CONFIG1		Configuration Register 1
+	7-6	R/W	LEDS[1-0] LED PIN
+	5	R/W	DVRLOAD	Driver Load
+	4	R/W	LWACT	LWAKE active mode
+	3	R	MEMMAP	Memory Mapping
+	2	R	IOMAP	I/O Mapping
+	1	R/W	VPD	Set to enable Vital Product Data
+	0	R/W	PMEn	Power Management Enable
+59	R/W	CONFIG3		Configuration Register 3
+	7	R	GNTSel	Gnt Select
+	6	R/W	PARM_En	Parameter Enable
+	5	R/W	Magic	Magic Packet
+	4	R/W	LinkUp	Link Up
+	3			reserved
+	2	R	CLKRUN_En CLKRUN Enable
+	1			reserved
+	0	R	FBtBEn	Fast Back to Back Enable
+5a	R/W	CONFIG4		Configuration Register 4
+	7	R/W	RxFIFOAutoClr Auto Clear the Rx FIFO on overflow
+	6	R/W	AnaOff	Analog Power Off
+	5	R/W	LongWF	Long Wake-up Frame
+	4	R/W	LWPME	LANWAKE vs PMEB
+	3			reserved
+	2	R/W	LWPTN	LWAKE pattern
+	1			reserved
+	0	R/W	PBWakeup Pre-Boot Wakeup
+5c-5d	R/W	MULINT		Multiple Interrupt Select
+	15-12			reserved
+	11-0	R/W	MISR[11-0] Multiple Interrupt Select
+68-69	R	ANLPAR		Auto-Negotiation Link Partnet Register
+	15	R	NP	Next Page bit
+	14	R	ACK	acknowledge received from link partner
+	13	R/W	RF	received remote fault detection capability
+	12-11			reserved
+	10	R	Pause	Flow control is supported
+	9	R	T4	100Base-T4 is supported
+	8	R/W	TXFD	100Base-TX full duplex is supported
+	7	R/W	TX	100Base-TX is supported
+	6	R/W	10FD	10Base-T full duplex is supported
+	5	R/W	10	10Base-T is supported
+	4-0	R/W	Selector Binary encoded selector
+6a-6b	R	ANER		Auto-Negotiation Expansion Register
+	15-5			reserved
+	4	R	MLF	Multiple link fault occured
+	3	R	LP_NP_ABLE Link partner supports Next Page
+	2	R	NP_ABLE	Local node is able to send add. Next Pages
+	1	R	PAGE_RX	Link Code Word Page received
+	0	R	LP_NW_ABLE Link partner supports NWay auto-negotiation
+70-71	R/W	NWAYTR		N-way Test Register
+	15-8			reserved
+	7	R/W	NWLPBK	NWay loopback mode
+	6-4			reserved
+	3	R	ENNWLE	LED0 pin indicates linkpulse
+	2	R	FLAGABD	Auto-neg experienced ability detect state
+	1	R	FLAGPDF	Auto-neg exp. par. detection fault state
+	0	R	FLAGLSC	Auto-neg experienced link status check state
+74-75	R/W	CSCR		CS Configuration Register
+	15	W	Testfun	Auto-neg speeds up internal timer
+	14-10			reserved
+	9	R/W	LD	Active low TPI link disable signal
+	8	R/W	HEARTBEAT HEART BEAT enable
+	7	R/W	JBEN	Enable jabber function
+	6	R/W	F_LINK_100 Force 100 Mbps
+	5	R/W	F_Conect Bypass disconnect function
+	4			reserved
+	3	R	Con_status Connected link detected
+	2	R/W	Con_status_En Configures LED1 to indicate conn. stat.
+	1			reserved
+	0	R/W	PASS_SCR Bypass scramble
+76-77				reserved
+78-7b	R/W	PHY1_PARM	PHY parameter 1
+7c-7f	R/W	TW_PARM		Twister parameter
+80	R/W	PHY2_PARM	PHY parameter 2
+81-83				reserved
+84-8b	R/W	CRC[0-7]	Power Management CRC reg.[0-7] for frame[0-7]
+8c-cb	R/W	Wakeup[0-7]	Power Management wakeup frame[0-7] (64 bit)
+cc-d3	R/W	LSBCRC[0-7]	LSB of the mask byte of makeup frame[0-7]
+d4-d7				reserved
+d8	R/W	Config5		Configuration register 5
+	7			reserved
+	6	R/W	BWF	Broadcast Wakeup Frame
+	5	R/W	MWF	Multicast Wakeup Frame
+	4	R/W	UWF	Unicast Wakeup Frame
+	3	R/W	FifoAddrPtr FIFO Address Pointer
+	2	R/W	LDPS	Link Down Power Saving mode
+	1	R/W	LANWake	LANWake Signal
+	0	R/W	PME_STS	PME_Status bit
+d9-ff				reserved
+#endif
+
+/*
+ * $PchId: rtl8139.h,v 1.1 2003/09/05 10:58:50 philip Exp $
+ */
Index: /trunk/minix/drivers/sb16/.depend
===================================================================
--- /trunk/minix/drivers/sb16/.depend	(revision 9)
+++ /trunk/minix/drivers/sb16/.depend	(revision 9)
@@ -0,0 +1,96 @@
+
+sb16.o:	../drivers.h
+sb16.o:	/usr/include/ansi.h
+sb16.o:	/usr/include/errno.h
+sb16.o:	/usr/include/ibm/bios.h
+sb16.o:	/usr/include/ibm/interrupt.h
+sb16.o:	/usr/include/ibm/ports.h
+sb16.o:	/usr/include/limits.h
+sb16.o:	/usr/include/minix/bitmap.h
+sb16.o:	/usr/include/minix/callnr.h
+sb16.o:	/usr/include/minix/com.h
+sb16.o:	/usr/include/minix/config.h
+sb16.o:	/usr/include/minix/const.h
+sb16.o:	/usr/include/minix/devio.h
+sb16.o:	/usr/include/minix/dmap.h
+sb16.o:	/usr/include/minix/ioctl.h
+sb16.o:	/usr/include/minix/ipc.h
+sb16.o:	/usr/include/minix/sound.h
+sb16.o:	/usr/include/minix/sys_config.h
+sb16.o:	/usr/include/minix/syslib.h
+sb16.o:	/usr/include/minix/sysutil.h
+sb16.o:	/usr/include/minix/type.h
+sb16.o:	/usr/include/signal.h
+sb16.o:	/usr/include/stddef.h
+sb16.o:	/usr/include/stdlib.h
+sb16.o:	/usr/include/string.h
+sb16.o:	/usr/include/sys/dir.h
+sb16.o:	/usr/include/sys/ioc_sound.h
+sb16.o:	/usr/include/sys/types.h
+sb16.o:	/usr/include/unistd.h
+sb16.o:	sb16.c
+sb16.o:	sb16.h
+
+sb16_dsp.o:	../drivers.h
+sb16_dsp.o:	/usr/include/ansi.h
+sb16_dsp.o:	/usr/include/errno.h
+sb16_dsp.o:	/usr/include/ibm/bios.h
+sb16_dsp.o:	/usr/include/ibm/interrupt.h
+sb16_dsp.o:	/usr/include/ibm/ports.h
+sb16_dsp.o:	/usr/include/limits.h
+sb16_dsp.o:	/usr/include/minix/bitmap.h
+sb16_dsp.o:	/usr/include/minix/callnr.h
+sb16_dsp.o:	/usr/include/minix/com.h
+sb16_dsp.o:	/usr/include/minix/config.h
+sb16_dsp.o:	/usr/include/minix/const.h
+sb16_dsp.o:	/usr/include/minix/devio.h
+sb16_dsp.o:	/usr/include/minix/dmap.h
+sb16_dsp.o:	/usr/include/minix/ioctl.h
+sb16_dsp.o:	/usr/include/minix/ipc.h
+sb16_dsp.o:	/usr/include/minix/sound.h
+sb16_dsp.o:	/usr/include/minix/sys_config.h
+sb16_dsp.o:	/usr/include/minix/syslib.h
+sb16_dsp.o:	/usr/include/minix/sysutil.h
+sb16_dsp.o:	/usr/include/minix/type.h
+sb16_dsp.o:	/usr/include/signal.h
+sb16_dsp.o:	/usr/include/stddef.h
+sb16_dsp.o:	/usr/include/stdlib.h
+sb16_dsp.o:	/usr/include/string.h
+sb16_dsp.o:	/usr/include/sys/dir.h
+sb16_dsp.o:	/usr/include/sys/ioc_sound.h
+sb16_dsp.o:	/usr/include/sys/types.h
+sb16_dsp.o:	/usr/include/unistd.h
+sb16_dsp.o:	sb16.h
+sb16_dsp.o:	sb16_dsp.c
+
+sb16_mixer.o:	../drivers.h
+sb16_mixer.o:	/usr/include/ansi.h
+sb16_mixer.o:	/usr/include/errno.h
+sb16_mixer.o:	/usr/include/ibm/bios.h
+sb16_mixer.o:	/usr/include/ibm/interrupt.h
+sb16_mixer.o:	/usr/include/ibm/ports.h
+sb16_mixer.o:	/usr/include/limits.h
+sb16_mixer.o:	/usr/include/minix/bitmap.h
+sb16_mixer.o:	/usr/include/minix/callnr.h
+sb16_mixer.o:	/usr/include/minix/com.h
+sb16_mixer.o:	/usr/include/minix/config.h
+sb16_mixer.o:	/usr/include/minix/const.h
+sb16_mixer.o:	/usr/include/minix/devio.h
+sb16_mixer.o:	/usr/include/minix/dmap.h
+sb16_mixer.o:	/usr/include/minix/ioctl.h
+sb16_mixer.o:	/usr/include/minix/ipc.h
+sb16_mixer.o:	/usr/include/minix/sound.h
+sb16_mixer.o:	/usr/include/minix/sys_config.h
+sb16_mixer.o:	/usr/include/minix/syslib.h
+sb16_mixer.o:	/usr/include/minix/sysutil.h
+sb16_mixer.o:	/usr/include/minix/type.h
+sb16_mixer.o:	/usr/include/signal.h
+sb16_mixer.o:	/usr/include/stddef.h
+sb16_mixer.o:	/usr/include/stdlib.h
+sb16_mixer.o:	/usr/include/string.h
+sb16_mixer.o:	/usr/include/sys/dir.h
+sb16_mixer.o:	/usr/include/sys/ioc_sound.h
+sb16_mixer.o:	/usr/include/sys/types.h
+sb16_mixer.o:	/usr/include/unistd.h
+sb16_mixer.o:	sb16.h
+sb16_mixer.o:	sb16_mixer.c
Index: /trunk/minix/drivers/sb16/Makefile
===================================================================
--- /trunk/minix/drivers/sb16/Makefile	(revision 9)
+++ /trunk/minix/drivers/sb16/Makefile	(revision 9)
@@ -0,0 +1,41 @@
+# Makefile for the Sound Blaster 16 driver (SB16)
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsys -lsysutil
+
+
+# build local binary
+all build:	sb16_dsp sb16_mixer
+sb16_dsp:	sb16.o sb16_dsp.o
+	$(CC) -o $@ $(LDFLAGS) sb16.o sb16_dsp.o $(LIBS)
+sb16_mixer:	sb16.o sb16_mixer.o
+	$(CC) -o $@ $(LDFLAGS) sb16.o sb16_mixer.o $(LIBS)
+
+# install with other drivers
+install:	/usr/sbin/sb16_dsp /usr/sbin/sb16_mixer
+/usr/sbin/sb16_dsp:	sb16_dsp
+	install -o root -c $? $@
+/usr/sbin/sb16_mixer:	sb16_mixer
+	install -o root -c $? $@
+
+# clean up local files
+clean:
+	rm -f *.o *.bak sb16 sb16_dsp sb16_mixer
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/sb16/README
===================================================================
--- /trunk/minix/drivers/sb16/README	(revision 9)
+++ /trunk/minix/drivers/sb16/README	(revision 9)
@@ -0,0 +1,21 @@
+
+Sound Blaster 16 ISA driver for Minix 3
+
+Note: supports audio playback and volume control (mixer),
+recording is not yet supported
+
+
+Installation instructions SB16 driver Minix >= 3.0.7
+
+- set IRQ and I/O address in sb16.h
+(default 7 and 220)
+- make install
+- MAKEDEV /dev/audio (if /dev/audio doesn't allready exist)
+- service up /usr/sbin/sb16_dsp -dev /dev/audio
+- service up /usr/sbin/sb16_mixer -dev /dev/mixer
+done... (you can include the last 2 lines in /usr/etc/rc)
+
+
+Peter Boonstoppel - September 2005
+paboonst@cs.vu.nl
+
Index: /trunk/minix/drivers/sb16/sb16.c
===================================================================
--- /trunk/minix/drivers/sb16/sb16.c	(revision 9)
+++ /trunk/minix/drivers/sb16/sb16.c	(revision 9)
@@ -0,0 +1,47 @@
+#include "sb16.h"
+
+/*===========================================================================*
+ *				mixer_set
+ *===========================================================================*/
+PUBLIC int mixer_set(reg, data) 
+int reg;
+int data;
+{
+	int i;
+
+	sb16_outb(MIXER_REG, reg);
+	for(i = 0; i < 100; i++);
+	sb16_outb(MIXER_DATA, data);
+
+	return OK;
+}
+
+
+/*===========================================================================*
+ *				sb16_inb
+ *===========================================================================*/
+PUBLIC int sb16_inb(port)
+int port;
+{	
+	int s;
+	unsigned long value;
+
+	if ((s=sys_inb(port, &value)) != OK)
+		panic("SB16DSP","sys_inb() failed", s);
+	
+	return value;
+}
+
+
+/*===========================================================================*
+ *				sb16_outb
+ *===========================================================================*/
+PUBLIC void sb16_outb(port, value)
+int port;
+int value;
+{
+	int s;
+	
+	if ((s=sys_outb(port, value)) != OK)
+		panic("SB16DSP","sys_outb() failed", s);
+}
Index: /trunk/minix/drivers/sb16/sb16.h
===================================================================
--- /trunk/minix/drivers/sb16/sb16.h	(revision 9)
+++ /trunk/minix/drivers/sb16/sb16.h	(revision 9)
@@ -0,0 +1,183 @@
+#ifndef SB16_H
+#define SB16_H
+
+#include "../drivers.h"
+#include <sys/ioc_sound.h>
+#include <minix/sound.h>
+
+
+#define SB_TIMEOUT		32000   /* timeout count */
+
+/* IRQ, base address and DMA channels */
+#define SB_IRQ		7
+#define SB_BASE_ADDR	0x220		/* 0x210, 0x220, 0x230, 0x240,
+                                         * 0x250, 0x260, 0x280        
+                                         */
+#define SB_DMA_8	1		/* 0, 1, 3 */
+#define SB_DMA_16	5		/* 5, 6, 7 */
+#if _WORD_SIZE == 2
+#define DMA_SIZE	8192		/* Dma buffer MUST BE MULTIPLE OF 2 */
+#else
+#define DMA_SIZE	(64 * 1024)		/* Dma buffer MUST BE MULTIPLE OF 2 */
+#endif
+
+/* Some defaults for the DSP */
+#define DEFAULT_SPEED		22050      /* Sample rate */
+#define DEFAULT_BITS		8	   /* Nr. of bits */
+#define DEFAULT_SIGN		0	   /* 0 = unsigned, 1 = signed */
+#define DEFAULT_STEREO		0	   /* 0 = mono, 1 = stereo */
+
+/* DMA port addresses */
+#define DMA8_ADDR	((SB_DMA_8 & 3) << 1) + 0x00
+#define DMA8_COUNT	((SB_DMA_8 & 3) << 1) + 0x01 
+#define DMA8_MASK	0x0A
+#define DMA8_MODE	0x0B
+#define DMA8_CLEAR	0x0C
+
+
+/* If after this preprocessing stuff DMA8_PAGE is not defined
+ * the 8-bit DMA channel specified is not valid
+ */
+#if SB_DMA_8 == 0
+#  define DMA8_PAGE	0x87	
+#else 
+#  if SB_DMA_8 == 1
+#    define DMA8_PAGE	0x83	
+#  else 
+#    if SB_DMA_8 == 3
+#      define DMA8_PAGE	0x82
+#    endif
+#  endif
+#endif
+
+	
+#define DMA16_ADDR	((SB_DMA_16 & 3) << 2) + 0xC0
+#define DMA16_COUNT	((SB_DMA_16 & 3) << 2) + 0xC2 
+#define DMA16_MASK	0xD4
+#define DMA16_MODE	0xD6
+#define DMA16_CLEAR	0xD8
+
+
+/* If after this preprocessing stuff DMA16_PAGE is not defined
+ * the 16-bit DMA channel specified is not valid
+ */
+#if SB_DMA_16 == 5
+#  define DMA16_PAGE	  0x8B	
+#else 
+#  if SB_DMA_16 == 6
+#    define DMA16_PAGE	  0x89	
+#  else 
+#    if SB_DMA_16 == 7
+#      define DMA16_PAGE  0x8A
+#    endif
+#  endif
+#endif
+
+
+/* DMA modes */
+#define DMA16_AUTO_PLAY		0x58 + (SB_DMA_16 & 3)
+#define DMA16_AUTO_REC		0x54 + (SB_DMA_16 & 3)
+#define DMA8_AUTO_PLAY		0x58 + SB_DMA_8
+#define DMA8_AUTO_REC		0x54 + SB_DMA_8
+
+
+/* IO ports for soundblaster */
+#define DSP_RESET	0x6 + SB_BASE_ADDR
+#define DSP_READ	0xA + SB_BASE_ADDR
+#define DSP_WRITE	0xC + SB_BASE_ADDR
+#define DSP_COMMAND	0xC + SB_BASE_ADDR
+#define DSP_STATUS	0xC + SB_BASE_ADDR
+#define DSP_DATA_AVL	0xE + SB_BASE_ADDR
+#define DSP_DATA16_AVL	0xF + SB_BASE_ADDR
+#define MIXER_REG	0x4 + SB_BASE_ADDR
+#define MIXER_DATA	0x5 + SB_BASE_ADDR
+#define OPL3_LEFT	0x0 + SB_BASE_ADDR
+#define OPL3_RIGHT	0x2 + SB_BASE_ADDR
+#define OPL3_BOTH	0x8 + SB_BASE_ADDR
+
+
+/* DSP Commands */
+#define DSP_INPUT_RATE		0x42  /* set input sample rate */
+#define DSP_OUTPUT_RATE		0x41  /* set output sample rate */
+#define DSP_CMD_SPKON		0xD1  /* set speaker on */
+#define DSP_CMD_SPKOFF		0xD3  /* set speaker off */
+#define DSP_CMD_DMA8HALT	0xD0  /* halt DMA 8-bit operation */  
+#define DSP_CMD_DMA8CONT	0xD4  /* continue DMA 8-bit operation */
+#define DSP_CMD_DMA16HALT	0xD5  /* halt DMA 16-bit operation */
+#define DSP_CMD_DMA16CONT	0xD6  /* continue DMA 16-bit operation */
+#define DSP_GET_VERSION		0xE1  /* get version number of DSP */
+#define DSP_CMD_8BITAUTO_IN	0xCE  /* 8 bit auto-initialized input */
+#define DSP_CMD_8BITAUTO_OUT	0xC6  /* 8 bit auto-initialized output */
+#define DSP_CMD_16BITAUTO_IN	0xBE  /* 16 bit auto-initialized input */
+#define DSP_CMD_16BITAUTO_OUT	0xB6  /* 16 bit auto-initialized output */
+#define DSP_CMD_IRQREQ8		0xF2  /* Interrupt request 8 bit        */
+#define DSP_CMD_IRQREQ16	0xF3  /* Interrupt request 16 bit        */
+
+
+/* DSP Modes */
+#define DSP_MODE_MONO_US	0x00  /* Mono unsigned */
+#define DSP_MODE_MONO_S		0x10  /* Mono signed */
+#define DSP_MODE_STEREO_US	0x20  /* Stereo unsigned */
+#define DSP_MODE_STEREO_S	0x30  /* Stereo signed */
+
+
+/* MIXER commands */
+#define MIXER_RESET		0x00  /* Reset */
+#define MIXER_DAC_LEVEL		0x04  /* Used for detection only */
+#define MIXER_MASTER_LEFT	0x30  /* Master volume left */
+#define MIXER_MASTER_RIGHT	0x31  /* Master volume right */
+#define MIXER_DAC_LEFT		0x32  /* Dac level left */
+#define MIXER_DAC_RIGHT		0x33  /* Dac level right */
+#define MIXER_FM_LEFT		0x34  /* Fm level left */
+#define MIXER_FM_RIGHT		0x35  /* Fm level right */
+#define MIXER_CD_LEFT		0x36  /* Cd audio level left */
+#define MIXER_CD_RIGHT		0x37  /* Cd audio level right */
+#define MIXER_LINE_LEFT		0x38  /* Line in level left */
+#define MIXER_LINE_RIGHT	0x39  /* Line in level right */
+#define MIXER_MIC_LEVEL		0x3A  /* Microphone level */
+#define MIXER_PC_LEVEL		0x3B  /* Pc speaker level */
+#define MIXER_OUTPUT_CTRL	0x3C  /* Output control */
+#define MIXER_IN_LEFT		0x3D  /* Input control left */
+#define MIXER_IN_RIGHT		0x3E  /* Input control right */
+#define MIXER_GAIN_IN_LEFT	0x3F  /* Input gain control left */
+#define MIXER_GAIN_IN_RIGHT	0x40  /* Input gain control right */
+#define MIXER_GAIN_OUT_LEFT	0x41  /* Output gain control left */
+#define MIXER_GAIN_OUT_RIGHT	0x42  /* Output gain control rigth */
+#define MIXER_AGC		0x43  /* Automatic gain control */
+#define MIXER_TREBLE_LEFT	0x44  /* Treble left */
+#define MIXER_TREBLE_RIGHT	0x45  /* Treble right */
+#define MIXER_BASS_LEFT		0x46  /* Bass left */
+#define MIXER_BASS_RIGHT	0x47  /* Bass right */
+#define MIXER_SET_IRQ		0x80  /* Set irq number */
+#define MIXER_SET_DMA		0x81  /* Set DMA channels */
+#define MIXER_IRQ_STATUS	0x82  /* Irq status */
+
+/* Mixer constants */
+#define MIC				0x01  /* Microphone */
+#define CD_RIGHT		0x02   
+#define CD_LEFT			0x04
+#define LINE_RIGHT		0x08
+#define LINE_LEFT		0x10
+#define FM_RIGHT		0x20
+#define FM_LEFT			0x40
+
+/* DSP constants */
+#define DMA_NR_OF_BUFFERS		2
+#define DSP_MAX_SPEED			44100      /* Max sample speed in KHz */
+#define DSP_MIN_SPEED			4000       /* Min sample speed in KHz */
+#define DSP_MAX_FRAGMENT_SIZE	DMA_SIZE /  DMA_NR_OF_BUFFERS /* Maximum fragment size */
+#define DSP_MIN_FRAGMENT_SIZE	1024 	   /* Minimum fragment size */
+#define DSP_NR_OF_BUFFERS		8
+
+
+/* Number of bytes you can DMA before hitting a 64K boundary: */
+#define dma_bytes_left(phys)    \
+   ((unsigned) (sizeof(int) == 2 ? 0 : 0x10000) - (unsigned) ((phys) & 0xFFFF))
+
+
+_PROTOTYPE(int mixer_set, (int reg, int data));
+_PROTOTYPE( int sb16_inb, (int port) );
+_PROTOTYPE( void sb16_outb, (int port, int value) );
+
+
+#endif /* SB16_H */
Index: /trunk/minix/drivers/sb16/sb16_dsp.c
===================================================================
--- /trunk/minix/drivers/sb16/sb16_dsp.c	(revision 9)
+++ /trunk/minix/drivers/sb16/sb16_dsp.c	(revision 9)
@@ -0,0 +1,653 @@
+/* This file contains the driver for a DSP (Digital Sound Processor) on
+ * a SoundBlaster 16 soundcard.
+ *
+ * The driver supports the following operations (using message format m2):
+ *
+ *    m_type      DEVICE    IO_ENDPT     COUNT    POSITION  ADRRESS
+ * ----------------------------------------------------------------
+ * |  DEV_OPEN  | device  | proc nr |         |         |         |
+ * |------------+---------+---------+---------+---------+---------|
+ * |  DEV_CLOSE | device  | proc nr |         |         |         |
+ * |------------+---------+---------+---------+---------+---------|
+ * |  DEV_READ  | device  | proc nr |  bytes  |         | buf ptr |
+ * |------------+---------+---------+---------+---------+---------|
+ * |  DEV_WRITE | device  | proc nr |  bytes  |         | buf ptr |
+ * |------------+---------+---------+---------+---------+---------|
+ * |  DEV_IOCTL | device  | proc nr |func code|         | buf ptr |
+ * ----------------------------------------------------------------
+ *
+ * The file contains one entry point:
+ *
+ *   main:	main entry when driver is brought up
+ *	
+ *  August 24 2005		Ported driver to user space (only audio playback) (Peter Boonstoppel)
+ *  May 20 1995			Author: Michel R. Prevenier 
+ */
+
+#include "sb16.h"
+
+
+_PROTOTYPE(void main, (void));
+FORWARD _PROTOTYPE( int dsp_open, (void) );
+FORWARD _PROTOTYPE( int dsp_close, (void) );
+FORWARD _PROTOTYPE( int dsp_ioctl, (message *m_ptr) );
+FORWARD _PROTOTYPE( void dsp_write, (message *m_ptr) );
+FORWARD _PROTOTYPE( void dsp_hardware_msg, (void) );
+FORWARD _PROTOTYPE( void dsp_status, (message *m_ptr) );
+
+FORWARD _PROTOTYPE( void reply, (int code, int replyee, int process, int status) );
+FORWARD _PROTOTYPE( void init_buffer, (void) );
+FORWARD _PROTOTYPE( int dsp_init, (void) );
+FORWARD _PROTOTYPE( int dsp_reset, (void) );
+FORWARD _PROTOTYPE( int dsp_command, (int value) );
+FORWARD _PROTOTYPE( int dsp_set_size, (unsigned int size) );
+FORWARD _PROTOTYPE( int dsp_set_speed, (unsigned int speed) );
+FORWARD _PROTOTYPE( int dsp_set_stereo, (unsigned int stereo) );
+FORWARD _PROTOTYPE( int dsp_set_bits, (unsigned int bits) );
+FORWARD _PROTOTYPE( int dsp_set_sign, (unsigned int sign) );
+FORWARD _PROTOTYPE( void dsp_dma_setup, (phys_bytes address, int count) );
+FORWARD _PROTOTYPE( void dsp_setup, (void) );
+
+PRIVATE int irq_hook_id;	/* id of irq hook at the kernel */
+
+PRIVATE char DmaBuffer[DMA_SIZE + 64 * 1024];
+PRIVATE char* DmaPtr;
+PRIVATE phys_bytes DmaPhys;
+
+PRIVATE char Buffer[DSP_MAX_FRAGMENT_SIZE * DSP_NR_OF_BUFFERS];
+
+PRIVATE int DspVersion[2]; 
+PRIVATE unsigned int DspStereo = DEFAULT_STEREO;
+PRIVATE unsigned int DspSpeed = DEFAULT_SPEED; 
+PRIVATE unsigned int DspBits = DEFAULT_BITS;
+PRIVATE unsigned int DspSign = DEFAULT_SIGN;
+PRIVATE unsigned int DspFragmentSize = DSP_MAX_FRAGMENT_SIZE;
+PRIVATE int DspAvail = 0;
+PRIVATE int DspBusy = 0;
+PRIVATE int DmaMode = 0;
+PRIVATE int DmaBusy = -1;
+PRIVATE int DmaFillNext = 0;
+PRIVATE int BufReadNext = -1;
+PRIVATE int BufFillNext = 0;
+
+PRIVATE int revivePending = 0;
+PRIVATE int reviveStatus;
+PRIVATE int reviveProcNr;
+
+#define dprint (void)
+
+
+/*===========================================================================*
+ *				main
+ *===========================================================================*/
+PUBLIC void main() 
+{	
+	int r, caller, proc_nr, s;
+	message mess;
+
+	dprint("sb16_dsp.c: main()\n");
+
+	/* Get a DMA buffer. */
+	init_buffer();
+
+	while(TRUE) {
+		/* Wait for an incoming message */
+		receive(ANY, &mess);
+
+		caller = mess.m_source;
+		proc_nr = mess.IO_ENDPT;
+
+		/* Now carry out the work. */
+		switch(mess.m_type) {
+			case DEV_OPEN:		r = dsp_open();	break;
+			case DEV_CLOSE:		r = dsp_close(); break;
+			case DEV_IOCTL:		r = dsp_ioctl(&mess); break;
+
+			case DEV_READ:		r = EINVAL; break; /* Not yet implemented */
+			case DEV_WRITE:		dsp_write(&mess); continue; /* don't reply */
+			
+			case DEV_STATUS:	dsp_status(&mess); continue; /* don't reply */
+			case HARD_INT:		dsp_hardware_msg(); continue; /* don't reply */
+			case SYS_SIG:		continue; /* don't reply */
+			default:			r = EINVAL;
+		}
+
+		/* Finally, prepare and send the reply message. */
+		reply(TASK_REPLY, caller, proc_nr, r);
+	}
+
+}
+
+
+/*===========================================================================*
+ *				dsp_open
+ *===========================================================================*/
+PRIVATE int dsp_open()
+{
+	dprint("sb16_dsp.c: dsp_open()\n");
+	
+	/* try to detect SoundBlaster card */
+	if(!DspAvail && dsp_init() != OK) return EIO;
+
+	/* Only one open at a time with soundcards */
+	if(DspBusy) return EBUSY;
+
+	/* Start with a clean DSP */
+	if(dsp_reset() != OK) return EIO;
+
+	/* Setup default values */
+	DspStereo = DEFAULT_STEREO;
+	DspSpeed = DEFAULT_SPEED;
+	DspBits = DEFAULT_BITS;
+	DspSign = DEFAULT_SIGN;
+	DspFragmentSize = DMA_SIZE / 2;
+
+	DspBusy = 1;
+
+	return OK;
+}
+
+
+/*===========================================================================*
+ *				dsp_close
+ *===========================================================================*/
+PRIVATE int dsp_close()
+{
+	dprint("sb16_dsp.c: dsp_close()\n");
+
+	DspBusy = 0;                  /* soundcard available again */
+
+	return OK;
+}
+
+
+/*===========================================================================*
+ *				dsp_ioctl
+ *===========================================================================*/
+PRIVATE int dsp_ioctl(m_ptr)
+message *m_ptr;
+{
+	int status;
+	phys_bytes user_phys;
+	unsigned int val;
+
+	dprint("sb16_dsp.c: dsp_ioctl()\n");
+
+	/* Cannot change parameters during play or recording */
+	if(DmaBusy >= 0) return EBUSY;
+
+	/* Get user data */
+	if(m_ptr->REQUEST != DSPIORESET) {
+		sys_vircopy(m_ptr->IO_ENDPT, D, (vir_bytes)m_ptr->ADDRESS, SELF, D, (vir_bytes)&val, sizeof(val));
+	}
+
+	dprint("dsp_ioctl: got ioctl %d, argument: %d\n", m_ptr->REQUEST, val);
+
+	switch(m_ptr->REQUEST) {
+		case DSPIORATE:		status = dsp_set_speed(val); break;
+		case DSPIOSTEREO:	status = dsp_set_stereo(val); break;
+		case DSPIOBITS:		status = dsp_set_bits(val); break;
+		case DSPIOSIZE:		status = dsp_set_size(val); break;
+		case DSPIOSIGN:		status = dsp_set_sign(val); break;
+		case DSPIOMAX: 
+			val = DSP_MAX_FRAGMENT_SIZE;
+			sys_vircopy(SELF, D, (vir_bytes)&val, m_ptr->IO_ENDPT, D, (vir_bytes)m_ptr->ADDRESS, sizeof(val));
+			status = OK;
+			break;
+		case DSPIORESET:    status = dsp_reset(); break;
+		default:            status = ENOTTY; break;
+	}
+
+	return status;
+}
+
+
+/*===========================================================================*
+ *				dsp_write
+ *===========================================================================*/
+PRIVATE void dsp_write(m_ptr)
+message *m_ptr;
+{
+	int s;
+	message mess;
+	
+	dprint("sb16_dsp.c: dsp_write()\n");
+
+	if(m_ptr->COUNT != DspFragmentSize) {
+		reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EINVAL);
+		return;
+	}
+	if(m_ptr->m_type != DmaMode && DmaBusy >= 0) {
+		reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EBUSY);
+		return;
+	}
+	
+	reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, SUSPEND);
+
+	if(DmaBusy < 0) { /* Dma tranfer not yet started */
+
+		DmaMode = DEV_WRITE;           /* Dma mode is writing */
+		sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)DmaPtr, (phys_bytes)DspFragmentSize);
+		dsp_dma_setup(DmaPhys, DspFragmentSize * DMA_NR_OF_BUFFERS);
+		dsp_setup();
+		DmaBusy = 0;         /* Dma is busy */
+		dprint(" filled dma[0]\n");
+		DmaFillNext = 1;
+
+	} else if(DmaBusy != DmaFillNext) { /* Dma transfer started, but Dma buffer not yet full */
+
+		sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)DmaPtr + DmaFillNext * DspFragmentSize, (phys_bytes)DspFragmentSize);
+		dprint(" filled dma[%d]\n", DmaFillNext);
+		DmaFillNext = (DmaFillNext + 1) % DMA_NR_OF_BUFFERS;
+
+	} else if(BufReadNext < 0) { /* Dma buffer full, fill first element of second buffer */ 
+
+		sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)Buffer, (phys_bytes)DspFragmentSize);
+		dprint(" filled buf[0]\n");
+		BufReadNext = 0;
+		BufFillNext = 1;
+
+	} else { /* Dma buffer is full, filling second buffer */ 
+
+		while(BufReadNext == BufFillNext) { /* Second buffer also full, wait for space to become available */ 
+			receive(HARDWARE, &mess);
+			dsp_hardware_msg();
+		}
+		sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)Buffer + BufFillNext * DspFragmentSize, (phys_bytes)DspFragmentSize);
+		dprint(" filled buf[%d]\n", BufFillNext);
+		BufFillNext = (BufFillNext + 1) % DSP_NR_OF_BUFFERS;
+
+	} 
+	
+	revivePending = 1;
+	reviveStatus = DspFragmentSize;
+	reviveProcNr = m_ptr->IO_ENDPT;
+	notify(m_ptr->m_source);
+}
+
+
+/*===========================================================================*
+ *				dsp_hardware_msg
+ *===========================================================================*/
+PRIVATE void dsp_hardware_msg()
+{	
+	dprint("Interrupt: ");
+	if(DmaBusy >= 0) { /* Dma transfer was actually busy */
+		dprint("Finished playing dma[%d]; ", DmaBusy);
+		DmaBusy = (DmaBusy + 1) % DMA_NR_OF_BUFFERS;
+		if(DmaBusy == DmaFillNext) { /* Dma buffer empty, stop Dma transfer */
+
+			dsp_command((DspBits == 8 ? DSP_CMD_DMA8HALT : DSP_CMD_DMA16HALT));
+			dprint("No more work...!\n");
+			DmaBusy = -1;
+
+		} else if(BufReadNext >= 0) { /* Data in second buffer, copy one fragment to Dma buffer */
+			
+			/* Acknowledge the interrupt on the DSP */
+			sb16_inb((DspBits == 8 ? DSP_DATA_AVL : DSP_DATA16_AVL));
+
+			memcpy(DmaPtr + DmaFillNext * DspFragmentSize, Buffer + BufReadNext * DspFragmentSize, DspFragmentSize);
+			dprint("copy buf[%d] -> dma[%d]; ", BufReadNext, DmaFillNext);
+			BufReadNext = (BufReadNext + 1) % DSP_NR_OF_BUFFERS;
+			DmaFillNext = (DmaFillNext + 1) % DMA_NR_OF_BUFFERS;
+			if(BufReadNext == BufFillNext) {
+				BufReadNext = -1;
+			} 
+			dprint("Starting dma[%d]\n", DmaBusy);
+			
+			return;
+
+		} else { /* Second buffer empty, still data in Dma buffer, continue playback */
+			dprint("Starting dma[%d]\n", DmaBusy);
+		}
+	}
+
+	/* Acknowledge the interrupt on the DSP */
+	sb16_inb((DspBits == 8 ? DSP_DATA_AVL : DSP_DATA16_AVL));
+}
+
+
+/*===========================================================================*
+ *				dsp_status				     *
+ *===========================================================================*/
+PRIVATE void dsp_status(m_ptr)
+message *m_ptr;	/* pointer to the newly arrived message */
+{
+	if(revivePending) {
+		m_ptr->m_type = DEV_REVIVE;			/* build message */
+		m_ptr->REP_ENDPT = reviveProcNr;
+		m_ptr->REP_STATUS = reviveStatus;
+
+		revivePending = 0;					/* unmark event */
+	} else {
+		m_ptr->m_type = DEV_NO_STATUS;
+	}
+
+	send(m_ptr->m_source, m_ptr);			/* send the message */
+}
+
+
+/*===========================================================================*
+ *				reply					     *
+ *===========================================================================*/
+PRIVATE void reply(code, replyee, process, status)
+int code;
+int replyee;
+int process;
+int status;
+{
+	message m;
+
+	m.m_type = code;		/* TASK_REPLY or REVIVE */
+	m.REP_STATUS = status;	/* result of device operation */
+	m.REP_ENDPT = process;	/* which user made the request */
+
+	send(replyee, &m);
+}
+
+
+/*===========================================================================*
+ *				init_buffer
+ *===========================================================================*/
+PRIVATE void init_buffer()
+{
+/* Select a buffer that can safely be used for dma transfers.  
+ * Its absolute address is 'DmaPhys', the normal address is 'DmaPtr'.
+ */
+
+#if (CHIP == INTEL)
+	unsigned left;
+
+	DmaPtr = DmaBuffer;
+	sys_umap(SELF, D, (vir_bytes)DmaBuffer, (phys_bytes)sizeof(DmaBuffer), &DmaPhys);
+
+	if((left = dma_bytes_left(DmaPhys)) < DMA_SIZE) {
+		/* First half of buffer crosses a 64K boundary, can't DMA into that */
+		DmaPtr += left;
+		DmaPhys += left;
+	}
+#else /* CHIP != INTEL */
+	panic("SB16DSP","init_buffer() failed, CHIP != INTEL", 0);
+#endif /* CHIP == INTEL */
+}
+
+
+/*===========================================================================*
+ *				dsp_init
+ *===========================================================================*/
+PRIVATE int dsp_init()
+{
+	int i, s;
+
+	if(dsp_reset () != OK) { 
+		dprint("sb16: No SoundBlaster card detected\n");
+		return -1;
+	}
+
+	DspVersion[0] = DspVersion[1] = 0;
+	dsp_command(DSP_GET_VERSION);	/* Get DSP version bytes */
+
+	for(i = 1000; i; i--) {
+		if(sb16_inb(DSP_DATA_AVL) & 0x80) {		
+			if(DspVersion[0] == 0) {
+				DspVersion[0] = sb16_inb(DSP_READ);
+			} else {
+				DspVersion[1] = sb16_inb(DSP_READ);
+				break;
+			}
+		}
+	}
+
+	if(DspVersion[0] < 4) {
+		dprint("sb16: No SoundBlaster 16 compatible card detected\n");
+		return -1;
+	} 
+	
+	dprint("sb16: SoundBlaster DSP version %d.%d detected\n", DspVersion[0], DspVersion[1]);
+
+	/* set SB to use our IRQ and DMA channels */
+	mixer_set(MIXER_SET_IRQ, (1 << (SB_IRQ / 2 - 1)));
+	mixer_set(MIXER_SET_DMA, (1 << SB_DMA_8 | 1 << SB_DMA_16)); 
+
+	/* register interrupt vector and enable irq */
+	if ((s=sys_irqsetpolicy(SB_IRQ, IRQ_REENABLE, &irq_hook_id )) != OK)
+  		panic("SB16DSP", "Couldn't set IRQ policy", s);
+	if ((s=sys_irqenable(&irq_hook_id)) != OK)
+  		panic("SB16DSP", "Couldn't enable IRQ", s);
+
+	DspAvail = 1;
+	return OK;
+}
+
+
+/*===========================================================================*
+ *				dsp_reset
+ *===========================================================================*/
+PRIVATE int dsp_reset()
+{
+	int i;
+
+	sb16_outb(DSP_RESET, 1);
+	for(i = 0; i < 1000; i++); /* wait a while */
+	sb16_outb(DSP_RESET, 0);
+
+	for(i = 0; i < 1000 && !(sb16_inb(DSP_DATA_AVL) & 0x80); i++); 	
+	
+	if(sb16_inb(DSP_READ) != 0xAA) return EIO; /* No SoundBlaster */
+
+	DmaBusy = -1;
+
+	return OK;
+}
+
+
+/*===========================================================================*
+ *				dsp_command
+ *===========================================================================*/
+PRIVATE int dsp_command(value)
+int value;
+{
+	int i, status;
+
+	for (i = 0; i < SB_TIMEOUT; i++) {
+		if((sb16_inb(DSP_STATUS) & 0x80) == 0) {
+			sb16_outb(DSP_COMMAND, value);
+			return OK;
+		}
+	}
+
+	dprint("sb16: SoundBlaster: DSP Command(%x) timeout\n", value);
+	return -1;
+}
+
+
+/*===========================================================================*
+ *				dsp_set_size
+ *===========================================================================*/
+static int dsp_set_size(size)
+unsigned int size;
+{
+	dprint("dsp_set_size(): set fragment size to %u\n", size);
+
+	/* Sanity checks */
+	if(size < DSP_MIN_FRAGMENT_SIZE || size > DSP_MAX_FRAGMENT_SIZE || size % 2 != 0) {
+		return EINVAL;
+	}
+
+	DspFragmentSize = size; 
+
+	return OK;
+}
+
+
+/*===========================================================================*
+ *				dsp_set_speed
+ *===========================================================================*/
+static int dsp_set_speed(speed)
+unsigned int speed;
+{
+	dprint("sb16: setting speed to %u, stereo = %d\n", speed, DspStereo);
+
+	if(speed < DSP_MIN_SPEED || speed > DSP_MAX_SPEED) {
+		return EPERM;
+	}
+
+	/* Soundblaster 16 can be programmed with real sample rates
+	* instead of time constants
+	*
+	* Since you cannot sample and play at the same time
+	* we set in- and output rate to the same value 
+	*/
+
+	dsp_command(DSP_INPUT_RATE);		/* set input rate */
+	dsp_command(speed >> 8);			/* high byte of speed */
+	dsp_command(speed);			 		/* low byte of speed */
+	dsp_command(DSP_OUTPUT_RATE);		/* same for output rate */
+	dsp_command(speed >> 8);	
+	dsp_command(speed); 
+
+	DspSpeed = speed;
+
+	return OK;
+}
+
+
+/*===========================================================================*
+ *				dsp_set_stereo
+ *===========================================================================*/
+static int dsp_set_stereo(stereo)
+unsigned int stereo;
+{
+	if(stereo) { 
+		DspStereo = 1;
+	} else { 
+		DspStereo = 0;
+	}
+
+	return OK;
+}
+
+
+/*===========================================================================*
+ *				dsp_set_bits
+ *===========================================================================*/
+static int dsp_set_bits(bits)
+unsigned int bits;
+{
+	/* Sanity checks */
+	if(bits != 8 && bits != 16) {
+		return EINVAL;
+	}
+
+	DspBits = bits; 
+
+	return OK;
+}
+
+
+/*===========================================================================*
+ *				dsp_set_sign
+ *===========================================================================*/
+static int dsp_set_sign(sign)
+unsigned int sign;
+{
+	dprint("sb16: set sign to %u\n", sign);
+
+	DspSign = (sign > 0 ? 1 : 0); 
+
+	return OK;
+}
+
+
+/*===========================================================================*
+ *				dsp_dma_setup
+ *===========================================================================*/
+PRIVATE void dsp_dma_setup(address, count)
+phys_bytes address;
+int count;
+{
+	pvb_pair_t pvb[9];
+
+
+	dprint("Setting up %d bit DMA\n", DspBits);
+
+	if(DspBits == 8) {   /* 8 bit sound */
+		count--;     
+
+		pv_set(pvb[0], DMA8_MASK, SB_DMA_8 | 0x04);      /* Disable DMA channel */
+		pv_set(pvb[1], DMA8_CLEAR, 0x00);		       /* Clear flip flop */
+
+		/* set DMA mode */
+		pv_set(pvb[2], DMA8_MODE, (DmaMode == DEV_WRITE ? DMA8_AUTO_PLAY : DMA8_AUTO_REC)); 
+
+		pv_set(pvb[3], DMA8_ADDR, address >>  0);        /* Low_byte of address */
+		pv_set(pvb[4], DMA8_ADDR, address >>  8);        /* High byte of address */
+		pv_set(pvb[5], DMA8_PAGE, address >> 16);        /* 64K page number */
+		pv_set(pvb[6], DMA8_COUNT, count >> 0);          /* Low byte of count */
+		pv_set(pvb[7], DMA8_COUNT, count >> 8);          /* High byte of count */
+		pv_set(pvb[8], DMA8_MASK, SB_DMA_8);	       /* Enable DMA channel */
+
+		sys_voutb(pvb, 9);
+	} else {  /* 16 bit sound */
+		count-= 2;
+
+		pv_set(pvb[0], DMA16_MASK, (SB_DMA_16 & 3) | 0x04);	/* Disable DMA channel */
+		
+		pv_set(pvb[1], DMA16_CLEAR, 0x00);                  /* Clear flip flop */
+
+		/* Set dma mode */
+		pv_set(pvb[2], DMA16_MODE, (DmaMode == DEV_WRITE ? DMA16_AUTO_PLAY : DMA16_AUTO_REC));        
+
+		pv_set(pvb[3], DMA16_ADDR, (address >> 1) & 0xFF);  /* Low_byte of address */
+		pv_set(pvb[4], DMA16_ADDR, (address >> 9) & 0xFF);  /* High byte of address */
+		pv_set(pvb[5], DMA16_PAGE, (address >> 16) & 0xFE); /* 128K page number */
+		pv_set(pvb[6], DMA16_COUNT, count >> 1);            /* Low byte of count */
+		pv_set(pvb[7], DMA16_COUNT, count >> 9);            /* High byte of count */
+		pv_set(pvb[8], DMA16_MASK, SB_DMA_16 & 3);          /* Enable DMA channel */
+
+		sys_voutb(pvb, 9);
+	}
+}
+
+
+/*===========================================================================*
+ *				dsp_setup()
+ *===========================================================================*/
+PRIVATE void dsp_setup()
+{ 
+	/* Set current sample speed */
+	dsp_set_speed(DspSpeed);
+
+	/* Put the speaker on */
+	if(DmaMode == DEV_WRITE) {
+		dsp_command (DSP_CMD_SPKON); /* put speaker on */
+
+		/* Program DSP with dma mode */
+		dsp_command((DspBits == 8 ? DSP_CMD_8BITAUTO_OUT : DSP_CMD_16BITAUTO_OUT));     
+	} else {
+		dsp_command (DSP_CMD_SPKOFF); /* put speaker off */
+
+		/* Program DSP with dma mode */
+		dsp_command((DspBits == 8 ? DSP_CMD_8BITAUTO_IN : DSP_CMD_16BITAUTO_IN));     
+	}
+
+	/* Program DSP with transfer mode */
+	if (!DspSign) {
+		dsp_command((DspStereo == 1 ? DSP_MODE_STEREO_US : DSP_MODE_MONO_US));
+	} else {
+		dsp_command((DspStereo == 1 ? DSP_MODE_STEREO_S : DSP_MODE_MONO_S));
+	}
+
+	/* Give length of fragment to DSP */
+	if (DspBits == 8) { /* 8 bit transfer */
+		/* #bytes - 1 */
+		dsp_command((DspFragmentSize - 1) >> 0); 
+		dsp_command((DspFragmentSize - 1) >> 8);
+	} else {             /* 16 bit transfer */
+		/* #words - 1 */
+		dsp_command((DspFragmentSize - 1) >> 1);
+		dsp_command((DspFragmentSize - 1) >> 9);
+	}
+}
+
+  
Index: /trunk/minix/drivers/sb16/sb16_mixer.c
===================================================================
--- /trunk/minix/drivers/sb16/sb16_mixer.c	(revision 9)
+++ /trunk/minix/drivers/sb16/sb16_mixer.c	(revision 9)
@@ -0,0 +1,387 @@
+/* This file contains the driver for the mixer on
+ * a SoundBlaster 16 soundcard.
+ *
+ * The driver supports the following operations (using message format m2):
+ *
+ *    m_type      DEVICE    IO_ENDPT     COUNT    POSITION  ADRRESS
+ * ----------------------------------------------------------------
+ * |  DEV_OPEN  | device  | proc nr |         |         |         |
+ * |------------+---------+---------+---------+---------+---------|
+ * |  DEV_CLOSE | device  | proc nr |         |         |         |
+ * |------------+---------+---------+---------+---------+---------|
+ * |  DEV_IOCTL | device  | proc nr |func code|         | buf_ptr |
+ * ----------------------------------------------------------------
+ *
+ * The file contains one entry point:
+ *
+ *   sb16mixer_task:  main entry when system is brought up
+ *
+ *	August 24 2005		Ported driver to user space (Peter Boonstoppel)
+ *  May 20 1995			Author: Michel R. Prevenier 
+ */
+
+
+#include "sb16.h"
+
+
+_PROTOTYPE(void main, (void));
+FORWARD _PROTOTYPE( int mixer_init, (void)); 
+FORWARD _PROTOTYPE( int mixer_open, (message *m_ptr));
+FORWARD _PROTOTYPE( int mixer_close, (message *m_ptr));
+FORWARD _PROTOTYPE( int mixer_ioctl, (message *m_ptr));
+FORWARD _PROTOTYPE( int mixer_get, (int reg));
+FORWARD _PROTOTYPE( int get_set_volume, (message *m_ptr, int flag));
+FORWARD _PROTOTYPE( int get_set_input, (message *m_ptr, int flag, int channel));
+FORWARD _PROTOTYPE( int get_set_output, (message *m_ptr, int flag));
+
+
+PRIVATE int mixer_avail = 0;	/* Mixer exists? */
+
+
+#define dprint (void)
+
+
+/*===========================================================================*
+ *				main
+ *===========================================================================*/
+PUBLIC void main() {
+message mess;
+	int err, caller, proc_nr;
+
+	/* Here is the main loop of the mixer task. It waits for a message, carries
+	* it out, and sends a reply.
+	*/
+	while (TRUE) {
+		receive(ANY, &mess);
+
+		caller = mess.m_source;
+		proc_nr = mess.IO_ENDPT;
+
+		switch (caller) {
+			case HARDWARE: /* Leftover interrupt. */
+				continue;
+			case FS_PROC_NR: /* The only legitimate caller. */
+				break;
+			default:
+				dprint("sb16: got message from %d\n", caller);
+				continue;
+		}
+
+		/* Now carry out the work. */
+		switch(mess.m_type) {
+			case DEV_OPEN:      err = mixer_open(&mess); break;	
+			case DEV_CLOSE:     err = mixer_close(&mess); break; 
+			case DEV_IOCTL:     err = mixer_ioctl(&mess); break;
+			default:		err = EINVAL; break;
+		}
+
+		/* Finally, prepare and send the reply message. */
+		mess.m_type = TASK_REPLY;
+		mess.REP_ENDPT = proc_nr;
+	
+		dprint("%d %d", err, OK);
+		
+		mess.REP_STATUS = err;	/* error code */
+		send(caller, &mess);	/* send reply to caller */
+	}
+}
+
+
+/*=========================================================================*
+ *				mixer_open				   	
+ *=========================================================================*/
+PRIVATE int mixer_open(m_ptr)
+message *m_ptr;
+{
+	dprint("mixer_open\n");
+
+	/* try to detect the mixer type */
+	if (!mixer_avail && mixer_init() != OK) return EIO;
+
+	return OK;
+}
+
+
+/*=========================================================================*
+ *				mixer_close				   	
+ *=========================================================================*/
+PRIVATE int mixer_close(m_ptr)
+message *m_ptr;
+{
+	dprint("mixer_close\n");
+
+	return OK;
+}
+
+
+/*=========================================================================*
+ *				mixer_ioctl				   	
+ *=========================================================================*/
+PRIVATE int mixer_ioctl(m_ptr)
+message *m_ptr;
+{
+	int status;
+
+	dprint("mixer: got ioctl %d\n", m_ptr->REQUEST);
+
+
+	switch(m_ptr->REQUEST) {
+		case MIXIOGETVOLUME:      status = get_set_volume(m_ptr, 0); break;
+		case MIXIOSETVOLUME:      status = get_set_volume(m_ptr, 1); break;
+		case MIXIOGETINPUTLEFT:   status = get_set_input(m_ptr, 0, 0); break;
+		case MIXIOGETINPUTRIGHT:  status = get_set_input(m_ptr, 0, 1); break;
+		case MIXIOGETOUTPUT:      status = get_set_output(m_ptr, 0); break;
+		case MIXIOSETINPUTLEFT:   status = get_set_input(m_ptr, 1, 0); break;
+		case MIXIOSETINPUTRIGHT:  status = get_set_input(m_ptr, 1, 1); break;
+		case MIXIOSETOUTPUT:      status = get_set_output(m_ptr, 1); break;
+		default:                  status = ENOTTY;
+	}
+
+	return status;
+}
+
+
+/*=========================================================================*
+ *				mixer_init				   
+ *=========================================================================*/
+PRIVATE int mixer_init()
+{
+	/* Try to detect the mixer by writing to MIXER_DAC_LEVEL if the
+	* value written can be read back the mixer is there
+	*/
+
+	mixer_set(MIXER_DAC_LEVEL, 0x10);       /* write something to it */
+	if(mixer_get(MIXER_DAC_LEVEL) != 0x10) {
+		dprint("sb16: Mixer not detected\n");
+		return EIO;
+	}
+
+	/* Enable Automatic Gain Control */
+	mixer_set(MIXER_AGC, 0x01);
+
+	dprint("Mixer detected\n");
+
+	mixer_avail = 1;
+	return OK;
+}
+
+
+/*=========================================================================*
+ *				mixer_get				  
+ *=========================================================================*/
+PRIVATE int mixer_get(reg)
+int reg;
+{
+	int i;
+
+	sb16_outb(MIXER_REG, reg);
+	for(i = 0; i < 100; i++);
+	return sb16_inb(MIXER_DATA) & 0xff;
+}  
+
+
+/*=========================================================================*
+ *				get_set_volume				   *
+ *=========================================================================*/
+PRIVATE int get_set_volume(m_ptr, flag)
+message *m_ptr;
+int flag;	/* 0 = get, 1 = set */
+{
+	phys_bytes user_phys;
+	struct volume_level level;
+	int cmd_left, cmd_right, shift, max_level;
+
+	sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)&level, (phys_bytes)sizeof(level));
+
+	shift = 3;
+	max_level = 0x1F;
+
+	switch(level.device) {
+		case Master:
+			cmd_left = MIXER_MASTER_LEFT;
+			cmd_right = MIXER_MASTER_RIGHT;
+			break;
+		case Dac:
+			cmd_left = MIXER_DAC_LEFT;
+			cmd_right = MIXER_DAC_RIGHT;
+			break;
+		case Fm:
+			cmd_left = MIXER_FM_LEFT;
+			cmd_right = MIXER_FM_RIGHT;
+			break;
+		case Cd:
+			cmd_left = MIXER_CD_LEFT;
+			cmd_right = MIXER_CD_RIGHT;
+			break;
+		case Line:
+			cmd_left = MIXER_LINE_LEFT;
+			cmd_right = MIXER_LINE_RIGHT;
+			break;
+		case Mic:
+			cmd_left = cmd_right = MIXER_MIC_LEVEL;
+			break;
+		case Speaker:
+			cmd_left = cmd_right = MIXER_PC_LEVEL;
+			shift = 6;
+			max_level = 0x03;
+			break;
+		case Treble:
+			cmd_left = MIXER_TREBLE_LEFT;
+			cmd_right = MIXER_TREBLE_RIGHT;
+			shift = 4;
+			max_level = 0x0F;
+			break;
+		case Bass:  
+			cmd_left = MIXER_BASS_LEFT;
+			cmd_right = MIXER_BASS_RIGHT;
+			shift = 4;
+			max_level = 0x0F;
+			break;
+		default:     
+			return EINVAL;
+	}
+
+	if(flag) { /* Set volume level */
+		if(level.right < 0) level.right = 0;
+		else if(level.right > max_level) level.right = max_level;
+		if(level.left < 0) level.left = 0;
+		else if(level.left > max_level) level.left = max_level;
+
+		mixer_set(cmd_right, (level.right << shift));
+		mixer_set(cmd_left, (level.left << shift));
+	} else { /* Get volume level */
+		level.left = mixer_get(cmd_left);
+		level.right = mixer_get(cmd_right);
+
+		level.left >>= shift;
+		level.right >>= shift;
+
+		/* Copy back to user */
+		sys_datacopy(SELF, (vir_bytes)&level, m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, (phys_bytes)sizeof(level));
+	}
+
+	return OK;
+}
+
+
+/*=========================================================================*
+ *				get_set_input				   *
+ *=========================================================================*/
+PRIVATE int get_set_input(m_ptr, flag, channel)
+message *m_ptr;
+int flag;	/* 0 = get, 1 = set */
+int channel;    /* 0 = left, 1 = right */
+{
+	phys_bytes user_phys;
+	struct inout_ctrl input;
+	int input_cmd, input_mask, mask, del_mask, shift;
+
+	sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)&input, (phys_bytes)sizeof(input));
+
+	input_cmd = (channel == 0 ? MIXER_IN_LEFT : MIXER_IN_RIGHT);
+
+	mask = mixer_get(input_cmd); 
+
+	switch (input.device) {
+		case Fm:
+			shift = 5;
+			del_mask = 0x1F; 
+			break;
+		case Cd: 
+			shift = 1;
+			del_mask = 0x79;
+			break;
+		case Line:
+			shift = 3;
+			del_mask = 0x67;
+			break;
+		case Mic: 
+			shift = 0;
+			del_mask = 0x7E;
+			break;
+		default:   
+			return EINVAL;
+	}
+
+	if (flag) {  /* Set input */
+		input_mask = ((input.left == ON ? 1 : 0) << 1) | (input.right == ON ? 1 : 0);
+
+		if (shift > 0) input_mask <<= shift;
+		else input_mask >>= 1;
+
+		mask &= del_mask;   
+		mask |= input_mask;
+
+		mixer_set(input_cmd, mask);
+	} else {	/* Get input */
+		if (shift > 0) {
+			input.left = ((mask >> (shift+1)) & 1 == 1 ? ON : OFF);
+			input.right = ((mask >> shift) & 1 == 1 ? ON : OFF);
+		} else {
+			input.left = ((mask & 1) == 1 ? ON : OFF);
+		}
+
+		/* Copy back to user */
+		sys_datacopy(SELF, (vir_bytes)&input, m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, (phys_bytes)sizeof(input));
+	}
+
+	return OK;
+}
+
+
+/*=========================================================================*
+ *				get_set_output				   *
+ *=========================================================================*/
+PRIVATE int get_set_output(m_ptr, flag)
+message *m_ptr;
+int flag;	/* 0 = get, 1 = set */
+{
+	phys_bytes user_phys;
+	struct inout_ctrl output;
+	int output_mask, mask, del_mask, shift;
+
+	sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)&output, (phys_bytes)sizeof(output));
+
+	mask = mixer_get(MIXER_OUTPUT_CTRL); 
+
+	switch (output.device) {
+		case Cd:
+			shift = 1;
+			del_mask = 0x79;
+			break;
+		case Line:
+			shift = 3;
+			del_mask = 0x67;
+			break;
+		case Mic:
+			shift = 0;
+			del_mask = 0x7E;
+			break;
+		default:   
+			return EINVAL;
+	}
+
+	if (flag) {  /* Set input */
+		output_mask = ((output.left == ON ? 1 : 0) << 1) | (output.right == ON ? 1 : 0);
+
+		if (shift > 0) output_mask <<= shift;
+		else output_mask >>= 1;
+
+		mask &= del_mask;   
+		mask |= output_mask;
+
+		mixer_set(MIXER_OUTPUT_CTRL, mask);
+	} else {    /* Get input */
+		if (shift > 0) {
+			output.left = ((mask >> (shift+1)) & 1 == 1 ? ON : OFF);
+			output.right = ((mask >> shift) & 1 == 1 ? ON : OFF);
+		} else {
+			output.left = ((mask & 1) == 1 ? ON : OFF);
+		}
+
+		/* Copy back to user */
+		sys_datacopy(SELF, (vir_bytes)&output, m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, (phys_bytes)sizeof(output));
+	}
+
+	return OK;
+}
Index: /trunk/minix/drivers/ti1225/.depend
===================================================================
--- /trunk/minix/drivers/ti1225/.depend	(revision 9)
+++ /trunk/minix/drivers/ti1225/.depend	(revision 9)
@@ -0,0 +1,32 @@
+
+ti1225.o:	../drivers.h
+ti1225.o:	/usr/include/ansi.h
+ti1225.o:	/usr/include/errno.h
+ti1225.o:	/usr/include/ibm/bios.h
+ti1225.o:	/usr/include/ibm/interrupt.h
+ti1225.o:	/usr/include/ibm/pci.h
+ti1225.o:	/usr/include/ibm/ports.h
+ti1225.o:	/usr/include/limits.h
+ti1225.o:	/usr/include/minix/bitmap.h
+ti1225.o:	/usr/include/minix/callnr.h
+ti1225.o:	/usr/include/minix/com.h
+ti1225.o:	/usr/include/minix/config.h
+ti1225.o:	/usr/include/minix/const.h
+ti1225.o:	/usr/include/minix/devio.h
+ti1225.o:	/usr/include/minix/dmap.h
+ti1225.o:	/usr/include/minix/ipc.h
+ti1225.o:	/usr/include/minix/sys_config.h
+ti1225.o:	/usr/include/minix/syslib.h
+ti1225.o:	/usr/include/minix/sysutil.h
+ti1225.o:	/usr/include/minix/type.h
+ti1225.o:	/usr/include/signal.h
+ti1225.o:	/usr/include/stddef.h
+ti1225.o:	/usr/include/stdlib.h
+ti1225.o:	/usr/include/string.h
+ti1225.o:	/usr/include/sys/dir.h
+ti1225.o:	/usr/include/sys/types.h
+ti1225.o:	/usr/include/sys/vm.h
+ti1225.o:	/usr/include/unistd.h
+ti1225.o:	i82365.h
+ti1225.o:	ti1225.c
+ti1225.o:	ti1225.h
Index: /trunk/minix/drivers/ti1225/Makefile
===================================================================
--- /trunk/minix/drivers/ti1225/Makefile	(revision 9)
+++ /trunk/minix/drivers/ti1225/Makefile	(revision 9)
@@ -0,0 +1,40 @@
+# Makefile for the Texas Instruments PCI1225 PC Card controller driver (ti1225)
+DRIVER = ti1225
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i 
+LIBS = -lsys -lsysutil -ltimers
+
+OBJ = ti1225.o
+
+# build local binary
+all build:	$(DRIVER)
+$(DRIVER):	$(OBJ) 
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+	install -S 4096 $(DRIVER)
+
+# install with other drivers
+install:	/usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER):	$(DRIVER)
+	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f *.o *.bak $(DRIVER)
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/drivers/ti1225/i82365.h
===================================================================
--- /trunk/minix/drivers/ti1225/i82365.h	(revision 9)
+++ /trunk/minix/drivers/ti1225/i82365.h	(revision 9)
@@ -0,0 +1,167 @@
+/*
+i82365.h
+
+Created:	May 1995 by Philip Homburg <philip@cs.vu.nl>
+*/
+
+#ifndef I82365_H
+#define I82365_H
+
+/* The default I/O ports used by a i82365 are the following: */
+#define I365_INDEX	0x3E0
+#define I365_DATA	0x3E1
+
+/* The index register is used to select one of the following registers: */
+#define I365_REVISION		0x00	/* IDREG */
+#define		I365R_ID_MASK		0xC0
+#define			I365R_ID_IO		0x00
+#define			I365R_ID_MEM		0x40
+#define			I365R_ID_MEM_IO		0x80
+#define		I365R_RES_MASK		0x30
+#define		I365R_REV_MASK		0x0F
+
+#define I365_IF_STAT		0x01	/* ISTAT */
+#define			I365IS_GPI		0x80
+#define			CL6722IS_VPPVALID	0x80
+#define			I365IS_POWER		0x40
+#define			I365IS_READY		0x20
+#define			I365IS_WRTPROT		0x10
+#define		I365IS_CARD_MASK	0x0C
+#define			I365IS_CARD_ABSENT	0x00
+#define			I365IS_CARD_PART_0	0x04
+#define			I365IS_CARD_PART_1	0x08
+#define			I365IS_CARD_PRESENT	0x0C
+#define		I365IS_BAT_MASK		0x03
+#define			I365IS_BAT_LOST_0	0x00
+#define			I365IS_BAT_LOW		0x01
+#define			I365IS_BAT_LOST_1	0x02
+#define			I365IS_BAT_OKAY		0x03
+
+#define I365_PWR_CTL		0x02	/* PCTRL */
+#define 		I365PC_CARD_EN		0x80
+#define			I365PC_NORESET		0x40
+#define			CL6722PC_COMPAT_0	0x40
+#define 		I365PC_AUTO_PWR		0x20
+#define			I365PC_Vcc_MASK		0x18
+#define				I365PC_Vcc_NC		0x00
+#define				I365PC_Vcc_Reserved	0x08
+#define				I365PC_Vcc_5		0x10
+#define				I365PC_Vcc_33		0x18
+#define 		CL6722PC_Vcc_PWR	0x10
+#define 		CL6722PC_COMPAT_1	0x08
+#define 	I365PC_Vpp_MASK		0x03
+#define 		I365PC_Vpp_NC		0x00
+#define 		CL6722PC_Vpp_ZERO_0	0x00
+#define 		I365PC_Vpp_5		0x01
+#define 		CL6722PC_Vpp_Vcc	0x01
+#define 		I365PC_Vpp_12		0x02
+#define 		I365PC_Vpp_Reserved	0x03
+#define 		CL6722PC_Vpp_ZERO_1	0x03
+
+#define I365_INT_GEN_CTL	0x03
+#define 		I365IGC_RING_IND	0x80
+#define 		I365IGC_RESET		0x40
+#define 		I365IGC_CARD_IS_IO	0x20
+#define 		I365IGC_EN_MNG_INT	0x10
+#define 	I365IGC_IRQ_MASK	0x0F
+
+#define I365_CRD_STAT_CHG	0x04	/* CSTCH */
+#define 		I365CSC_GPI		0x10
+#define 		I365CSC_CARD_DETECT	0x08
+#define 		I365CSC_READY		0x04
+#define 		I365CSC_BAT_WARN	0x02
+#define 		I365CSC_BAT_DEAD	0x01
+
+#define I365_MNG_INT_CONF	0x05
+#define		I365MIC_IRQ_MASK	0xF0
+#define 		I365MIC_CARD_DETECT	0x08
+#define 		I365MIC_READY		0x04
+#define 		I365MIC_BAT_WARN	0x02
+#define 		I365MIC_BAT_DEAD	0x01
+
+#define I365_MAP_ENABLE		0x06	/* ADWEN */
+#define 		I365ME_IO_MAP_0		0x40
+#define 		I365ME_MEM_MAP_0	0x01
+
+#define I365_IO_WND_CTL		0x07
+#define 		I365IWC_AUTO_1		0x80
+#define 		CL6722IWC_TIMING_1	0x80
+#define 		I365IWC_0WS_1		0x40
+#define 		I365IWC_AUTO_SIZE_1	0x20
+#define 		I365IWC_IO_SIZE_1	0x10
+#define 		I365IWC_WAIT_0		0x08
+#define 		I365IWC_0WS_0		0x04
+#define 		CL6722IWC_TIMING_0	0x08
+#define 		I365IWC_AUTO_SIZE_0	0x02
+#define 		I365IWC_IO_SIZE_0	0x01
+
+#define I365_IO_0_START_LOW	0x08
+#define I365_IO_0_START_HIGH	0x09
+#define I365_IO_0_END_LOW	0x0A
+#define I365_IO_0_END_HIGH	0x0B
+#define I365_IO_1_START_LOW	0x0C
+#define I365_IO_1_START_HIGH	0x0D
+#define I365_IO_1_END_LOW	0x0E
+#define I365_IO_1_END_HIGH	0x0F
+
+#define I365_MEM_0_START_LOW	0x10
+#define I365_MEM_0_START_HIGH	0x11
+#define I365_MEM_0_END_LOW	0x12
+#define I365_MEM_0_END_HIGH	0x13
+#define I365_MEM_0_OFF_LOW	0x14
+#define I365_MEM_0_OFF_HIGH	0x15
+
+#define CL6722_MISC_CTL_1	0x16
+#define CL6722_FIFO_CTL		0x17
+
+#define I365_MEM_1_START_LOW	0x18
+#define I365_MEM_1_START_HIGH	0x19
+#define I365_MEM_1_END_LOW	0x1A
+#define I365_MEM_1_END_HIGH	0x1B
+#define I365_MEM_1_OFF_LOW	0x1C
+#define I365_MEM_1_OFF_HIGH	0x1D
+
+#define CL6722_MISC_CTL_2	0x1E
+#define CL6722_CHIP_INFO	0x1F
+#define		CL6722CI_ID_MASK	0xC0
+
+#define I365_MEM_2_START_LOW	0x20
+#define I365_MEM_2_START_HIGH	0x21
+#define I365_MEM_2_END_LOW	0x22
+#define I365_MEM_2_END_HIGH	0x23
+#define I365_MEM_2_OFF_LOW	0x24
+#define I365_MEM_2_OFF_HIGH	0x25
+
+#define CL6722_ATA_CONTROL	0x26	/* CPAGE */
+#define I365_RESERVED		0x27
+
+#define I365_MEM_3_START_LOW	0x28
+#define I365_MEM_3_START_HIGH	0x29
+#define I365_MEM_3_END_LOW	0x2A
+#define I365_MEM_3_END_HIGH	0x2B
+#define I365_MEM_3_OFF_LOW	0x2C
+#define I365_MEM_3_OFF_HIGH	0x2D
+
+#define CL6722_EXT_INDEX	0x2E	/* CSCTRL */
+#define CL6722_EXT_DATA		0x2F
+
+#define I365_MEM_4_START_LOW	0x30
+#define I365_MEM_4_START_HIGH	0x31
+#define I365_MEM_4_END_LOW	0x32
+#define I365_MEM_4_END_HIGH	0x33
+#define I365_MEM_4_OFF_LOW	0x34
+#define I365_MEM_4_OFF_HIGH	0x35
+
+#define CL6722_IO_0_OFF_LOW	0x36
+#define CL6722_IO_0_OFF_HIGH	0x37
+#define CL6722_IO_1_OFF_LOW	0x38
+#define CL6722_IO_1_OFF_HIGH	0x39
+
+#define I365_SETUP_TIM_0	0x3A
+#define I365_CMD_TIM_0		0x3B
+#define I365_RECOV_TIM_0	0x3C
+#define I365_SETUP_TIM_1	0x3D
+#define I365_CMD_TIM_1		0x3E
+#define I365_RECOV_TIM_1	0x3F
+
+#endif /* I82365_H */
Index: /trunk/minix/drivers/ti1225/ti1225.c
===================================================================
--- /trunk/minix/drivers/ti1225/ti1225.c	(revision 9)
+++ /trunk/minix/drivers/ti1225/ti1225.c	(revision 9)
@@ -0,0 +1,499 @@
+/*
+ti1225.c
+
+Created:	Dec 2005 by Philip Homburg
+*/
+
+#include "../drivers.h"
+#include <ibm/pci.h>
+#include <sys/vm.h>
+
+#include "ti1225.h"
+#include "i82365.h"
+
+/* The use of interrupts is not yet ready for prime time */
+#define USE_INTS	0
+
+#define MICROS_TO_TICKS(m)  (((m)*HZ/1000000)+1)
+
+#define NR_PORTS 2
+
+PRIVATE struct port
+{
+	unsigned p_flags;
+	int p_devind;
+	u8_t p_cb_busnr;
+	u16_t p_exca_port;
+#if USE_INTS
+	int p_irq;
+	int p_hook;
+#endif
+	char *base_ptr;
+	volatile struct csr *csr_ptr;
+
+	char buffer[2*PAGE_SIZE];
+} ports[NR_PORTS];
+
+#define PF_PRESENT	1
+
+struct pcitab
+{
+	u16_t vid;
+	u16_t did;
+	int checkclass;
+};
+
+PRIVATE struct pcitab pcitab_ti[]=
+{
+	{ 0x104C, 0xAC1C, 0 },		/* TI PCI1225 */
+
+	{ 0x0000, 0x0000, 0 }
+};
+PRIVATE char *progname;
+PRIVATE int debug;
+
+FORWARD _PROTOTYPE( void init, (void)					);
+FORWARD _PROTOTYPE( void hw_init, (struct port *pp)			);
+FORWARD _PROTOTYPE( void map_regs, (struct port *pp, u32_t base)	);
+FORWARD _PROTOTYPE( void do_int, (struct port *pp)			);
+FORWARD _PROTOTYPE( u8_t read_exca, (struct port *pp, int socket, int reg) );
+FORWARD _PROTOTYPE( void do_outb, (port_t port, u8_t value)		);
+FORWARD _PROTOTYPE( u8_t do_inb, (port_t port)				);
+FORWARD _PROTOTYPE( void micro_delay, (unsigned long usecs)		);
+
+int main(int argc, char *argv[])
+{
+	int c, r;
+	message m;
+
+	(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
+
+	debug= 0;
+	while (c= getopt(argc, argv, "d?"), c != -1)
+	{
+		switch(c)
+		{
+		case '?': panic("ti1225", "Usage: ti1225 [-d]", NO_NUM);
+		case 'd': debug++; break;
+		default: panic("ti1225", "getopt failed", NO_NUM);
+		}
+	}
+
+	init();
+
+	for (;;)
+	{
+		r= receive(ANY, &m);
+		if (r != OK)
+			panic("ti1225", "receive failed", r);
+		printf("ti1225: got message %u from %d\n",
+			m.m_type, m.m_source);
+	}
+	return 0;
+}
+
+PRIVATE void init()
+{
+	int i, r, first, devind, port;
+	u16_t vid, did;
+
+	pci_init1(progname);
+
+	first= 1;
+	port= 0;
+	for (;;)
+	{
+		if (first)
+		{
+			first= 0;
+			r= pci_first_dev(&devind, &vid, &did);
+		}
+		else
+			r= pci_next_dev(&devind, &vid, &did);
+		if (r != 1)
+			break;
+
+		for (i= 0; pcitab_ti[i].vid != 0; i++)
+		{
+			if (pcitab_ti[i].vid != vid)
+				continue;
+			if (pcitab_ti[i].did != did)
+				continue;
+			if (pcitab_ti[i].checkclass)
+			{
+				panic("ti1225",
+				"fxp_probe: class check not implemented",
+					NO_NUM);
+			}
+			break;
+		}
+		if (pcitab_ti[i].vid == 0)
+			continue;
+
+		pci_reserve(devind);
+
+		if (debug)
+			printf("ti1225: found device %04x/%04x\n", vid, did);
+		ports[port].p_devind= devind;
+		ports[port].p_flags |= PF_PRESENT;
+		port++;
+		if (port >= NR_PORTS)
+			break;
+	}
+
+	for (i= 0; i<NR_PORTS; i++)
+	{
+		if (!(ports[i].p_flags & PF_PRESENT))
+			continue;
+		hw_init(&ports[i]);
+	}
+}
+
+PRIVATE void hw_init(pp)
+struct port *pp;
+{
+	int i, r, devind, irq, socket;
+	u8_t v8;
+	u16_t v16;
+	u32_t v32;
+
+	devind= pp->p_devind;
+	if (debug)
+		printf("hw_init: devind = %d\n", devind);
+
+	if (debug)
+	{
+		v16= pci_attr_r16(devind, PCI_CR);
+		printf("ti1225: command register 0x%x\n", v16);
+	}
+
+	v32= pci_attr_r32(devind, TI_CB_BASEADDR);
+	if (debug)
+		printf("ti1225: Cardbus/ExCA base address 0x%x\n", v32);
+	map_regs(pp, v32);
+	pp->csr_ptr= (struct csr *)pp->base_ptr;
+
+	if (debug)
+	{
+		v8= pci_attr_r8(devind, TI_PCI_BUS_NR);
+		printf("ti1225: PCI bus number %d\n", v8);
+	}
+	v8= pci_attr_r8(devind, TI_CB_BUS_NR);
+	pp->p_cb_busnr= v8;
+	if (debug)
+	{
+		printf("ti1225: CardBus bus number %d\n", v8);
+		v8= pci_attr_r8(devind, TI_SO_BUS_NR);
+		printf("ti1225: Subordinate bus number %d\n", v8);
+	}
+
+#if USE_INTS
+	irq= pci_attr_r8(devind, PCI_ILR);
+	pp->p_irq= irq;
+	printf("ti1225 using IRQ %d\n", irq);
+#endif
+
+	v32= pci_attr_r32(devind, TI_LEGACY_BA);
+	v32 &= ~1;
+	if (debug)
+	{
+		printf("ti1225: PC Card 16-bit legacy-mode base address 0x%x\n",
+			v32);
+	}
+
+	if (v32 == 0)
+		panic("ti1225", "bad lagacy-mode base address 0x%x\n", v32);
+	pp->p_exca_port= v32;
+
+	if (debug)
+	{
+		v32= pci_attr_r32(devind, TI_MF_ROUTE);
+		printf("ti1225: Multifunction routing 0x%08x\n", v32);
+	}
+
+#if USE_INTS
+ 	pp->p_hook = pp->p_irq;
+	r= sys_irqsetpolicy(pp->p_irq, 0, &pp->p_hook);
+	if (r != OK)
+		panic("ti1225","sys_irqsetpolicy failed", r);
+#endif
+
+	/* Clear CBB_BC_INTEXCA */
+	v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
+	if (debug)
+		printf("ti1225: Bridge control 0x%04x\n", v16);
+	v16 &= ~CBB_BC_INTEXCA;
+	pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
+
+	if (debug)
+	{
+		v32= pci_attr_r32(devind, TI_SYSCTRL);
+		printf("ti1225: System Control Register 0x%08x\n", v32);
+
+		v8= pci_attr_r8(devind, TI_CARD_CTRL);
+		printf("ti1225: Card Control 0x%02x\n", v8);
+
+		v8= pci_attr_r8(devind, TI_DEV_CTRL);
+		printf("ti1225: Device Control 0x%02x\n", v8);
+	}
+
+	/* Enable socket interrupts */
+	pp->csr_ptr->csr_mask |= CM_PWRMASK | CM_CDMASK | CM_CSTSMASK;
+
+	do_int(pp);
+
+#if USE_INTS
+	r= sys_irqenable(&pp->p_hook);
+	if (r != OK)
+		panic("ti1225","unable enable interrupts", r);
+#endif
+}
+
+PRIVATE void map_regs(pp, base)
+struct port *pp;
+u32_t base;
+{
+	int r;
+	vir_bytes buf_base;
+
+	buf_base= (vir_bytes)pp->buffer;
+	if (buf_base % PAGE_SIZE)
+		buf_base += PAGE_SIZE-(buf_base % PAGE_SIZE);
+	pp->base_ptr= (char *)buf_base;
+	if (debug)
+	{
+		printf("ti1225: map_regs: using %p for %p\n",
+			pp->base_ptr, pp->buffer);
+	}
+
+	/* Clear low order bits in base */
+	base &= ~(u32_t)0xF;
+
+	r= sys_vm_map(SELF, 1 /* map */, (vir_bytes)pp->base_ptr,
+		PAGE_SIZE, (phys_bytes)base);
+	if (r != OK)
+		panic("ti1225", "map_regs: sys_vm_map failed", r);
+}
+
+PRIVATE void do_int(pp)
+struct port *pp;
+{
+	int i, r, devind, vcc_5v, vcc_3v, vcc_Xv, vcc_Yv,
+		socket_5v, socket_3v, socket_Xv, socket_Yv;
+	clock_t t0, t1;
+	u32_t csr_event, csr_present, csr_control;
+	u8_t v8;
+	u16_t v16;
+
+	devind= pp->p_devind;
+	v8= pci_attr_r8(devind, TI_CARD_CTRL);
+	if (v8 & TI_CCR_IFG)
+	{
+		printf("ti1225: got functional interrupt\n", v8);
+		pci_attr_w8(devind, TI_CARD_CTRL, v8);
+	}
+
+	if (debug)
+	{
+		printf("Socket event: 0x%x\n", pp->csr_ptr->csr_event);
+		printf("Socket mask: 0x%x\n", pp->csr_ptr->csr_mask);
+	}
+
+	csr_present= pp->csr_ptr->csr_present;
+	csr_control= pp->csr_ptr->csr_control;
+
+	if ((csr_present & (CP_CDETECT1|CP_CDETECT2)) != 0)
+	{
+		if (debug)
+			printf("do_int: no card present\n");
+		return;
+	}
+	if (csr_present & CP_BADVCCREQ)
+	{
+		printf("do_int: Bad Vcc request\n");
+		/* return; */
+	}
+	if (csr_present & CP_DATALOST)
+	{
+		/* Do we care? */
+		if (debug)
+			printf("do_int: Data lost\n");
+		/* return; */
+	}
+	if (csr_present & CP_NOTACARD)
+	{
+		printf("do_int: Not a card\n");
+		return;
+	}
+	if (debug)
+	{
+		if (csr_present & CP_CBCARD)
+			printf("do_int: Cardbus card detected\n");
+		if (csr_present & CP_16BITCARD)
+			printf("do_int: 16-bit card detected\n");
+	}
+	if (csr_present & CP_PWRCYCLE)
+	{
+		if (debug)
+			printf("do_int: powered up\n");
+		return;
+	}
+	vcc_5v= !!(csr_present & CP_5VCARD);
+	vcc_3v= !!(csr_present & CP_3VCARD);
+	vcc_Xv= !!(csr_present & CP_XVCARD);
+	vcc_Yv= !!(csr_present & CP_YVCARD);
+	if (debug)
+	{
+		printf("do_int: card supports:%s%s%s%s\n",
+			vcc_5v ? " 5V" : "", vcc_3v ? " 3V" : "",
+			vcc_Xv ? " X.X V" : "", vcc_Yv ? " Y.Y V" : "");
+	}
+	socket_5v= !!(csr_present & CP_5VSOCKET);
+	socket_3v= !!(csr_present & CP_3VSOCKET);
+	socket_Xv= !!(csr_present & CP_XVSOCKET);
+	socket_Yv= !!(csr_present & CP_YVSOCKET);
+	if (debug)
+	{
+		printf("do_int: socket supports:%s%s%s%s\n",
+			socket_5v ? " 5V" : "", socket_3v ? " 3V" : "",
+			socket_Xv ? " X.X V" : "", socket_Yv ? " Y.Y V" : "");
+	}
+	if (vcc_5v && socket_5v)
+	{
+		csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_5V;
+		pp->csr_ptr->csr_control= csr_control;
+		if (debug)
+			printf("do_int: applying 5V\n");
+	}
+	else if (vcc_3v && socket_3v)
+	{
+		csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_3V;
+		pp->csr_ptr->csr_control= csr_control;
+		if (debug)
+			printf("do_int: applying 3V\n");
+	}
+	else if (vcc_Xv && socket_Xv)
+	{
+		csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_XV;
+		pp->csr_ptr->csr_control= csr_control;
+		printf("do_int: applying X.X V\n");
+	}
+	else if (vcc_Yv && socket_Yv)
+	{
+		csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_YV;
+		pp->csr_ptr->csr_control= csr_control;
+		printf("do_int: applying Y.Y V\n");
+	}
+	else
+	{
+		printf("do_int: socket and card are not compatible\n");
+		return;
+	}
+
+	csr_event= pp->csr_ptr->csr_event;
+	if (csr_event)
+	{
+		if (debug)
+			printf("clearing socket event\n");
+		pp->csr_ptr->csr_event= csr_event;
+		if (debug)
+		{
+			printf("Socket event (cleared): 0x%x\n",
+				pp->csr_ptr->csr_event);
+		}
+	}
+
+	devind= pp->p_devind;
+	v8= pci_attr_r8(devind, TI_CARD_CTRL);
+	if (v8 & TI_CCR_IFG)
+	{
+		printf("ti1225: got functional interrupt\n", v8);
+		pci_attr_w8(devind, TI_CARD_CTRL, v8);
+	}
+
+	if (debug)
+	{
+		v8= pci_attr_r8(devind, TI_CARD_CTRL);
+		printf("TI_CARD_CTRL: 0x%02x\n", v8);
+	}
+
+	getuptime(&t0);
+	do {
+		csr_present= pp->csr_ptr->csr_present;
+		if (csr_present & CP_PWRCYCLE)
+			break;
+	} while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
+
+	if (!(csr_present & CP_PWRCYCLE))
+	{
+		printf("do_int: not powered up?\n");
+		return;
+	}
+
+	/* Reset device */
+	v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
+	v16 |= CBB_BC_CRST;
+	pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
+
+	/* Wait one microsecond. Is this correct? What are the specs? */
+	micro_delay(1);
+
+	/* Clear CBB_BC_CRST */
+	v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
+	v16 &= ~CBB_BC_CRST;
+	pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
+
+	/* Wait one microsecond after clearing the reset line. Is this
+	 * correct? What are the specs?
+	 */
+	micro_delay(1);
+
+	pci_rescan_bus(pp->p_cb_busnr);
+
+#if USE_INTS
+	r= sys_irqenable(&pp->p_hook);
+	if (r != OK)
+		panic("ti1225","unable enable interrupts", r);
+#endif
+
+}
+
+PRIVATE u8_t read_exca(pp, socket, reg)
+struct port *pp;
+int socket;
+int reg;
+{
+	u16_t port;
+
+	port= pp->p_exca_port;
+	if (port == 0)
+		panic("ti1225", "read_exca: bad port", NO_NUM);
+	do_outb(port, socket * 0x40 + reg);
+	return do_inb(port+1);
+}
+
+PRIVATE u8_t do_inb(port_t port)
+{
+	int r;
+	u32_t value;
+
+	r= sys_inb(port, &value);
+	if (r != OK)
+		panic("ti1225","sys_inb failed", r);
+	return value;
+}
+
+PRIVATE void do_outb(port_t port, u8_t value)
+{
+	int r;
+
+	r= sys_outb(port, value);
+	if (r != OK)
+		panic("ti1225","sys_outb failed", r);
+}
+
+PRIVATE void micro_delay(unsigned long usecs)
+{
+	tickdelay(MICROS_TO_TICKS(usecs));
+}
+
Index: /trunk/minix/drivers/ti1225/ti1225.h
===================================================================
--- /trunk/minix/drivers/ti1225/ti1225.h	(revision 9)
+++ /trunk/minix/drivers/ti1225/ti1225.h	(revision 9)
@@ -0,0 +1,71 @@
+/*
+ti1225.h
+
+Created:	Dec 2005 by Philip Homburg
+*/
+
+/* PCI attribute space registers */
+#define TI_CB_BASEADDR	0x10
+#define TI_PCI_BUS_NR	0x18
+#define TI_CB_BUS_NR	0x19
+#define TI_SO_BUS_NR	0x1A
+#define TI_LEGACY_BA	0x44
+#define TI_SYSCTRL	0x80
+#define TI_MF_ROUTE	0x8C
+#define TI_CARD_CTRL	0x91
+#define		TI_CCR_IFG	0x01
+#define TI_DEV_CTRL	0x92
+
+/* CardBus Socket Registers */
+struct csr
+{
+/*00*/	u32_t csr_event;
+/*04*/	u32_t csr_mask;
+/*08*/	u32_t csr_present;
+/*0C*/	u32_t csr_force_event;
+/*10*/	u32_t csr_control;
+/*14*/	u32_t csr_res0;
+/*18*/	u32_t csr_res1;
+/*1C*/	u32_t csr_res2;
+/*20*/	u32_t csr_power;
+};
+
+/* csr_mask */
+#define CM_PWRMASK	0x00000008
+#define CM_CDMASK	0x00000006
+#define CM_CSTSMASK	0x00000001
+
+/* csr_present */
+#define CP_YVSOCKET	0x80000000
+#define CP_XVSOCKET	0x40000000
+#define CP_3VSOCKET	0x20000000
+#define CP_5VSOCKET	0x10000000
+#define CP_YVCARD	0x00002000
+#define CP_XVCARD	0x00001000
+#define CP_3VCARD	0x00000800
+#define CP_5VCARD	0x00000400
+#define CP_BADVCCREQ	0x00000200
+#define CP_DATALOST	0x00000100
+#define CP_NOTACARD	0x00000080
+#define CP_IREQCINT	0x00000040
+#define CP_CBCARD	0x00000020
+#define CP_16BITCARD	0x00000010
+#define CP_PWRCYCLE	0x00000008
+#define CP_CDETECT2	0x00000004
+#define CP_CDETECT1	0x00000002
+#define CP_CARDSTS	0x00000001
+
+/* csr_control */
+#define CC_VCCCTRL	0x00000070
+#define 	CC_VCC_OFF	0x00000000
+#define 	CC_VCC_5V	0x00000020
+#define 	CC_VCC_3V	0x00000030
+#define 	CC_VCC_XV	0x00000040
+#define 	CC_VCC_YV	0x00000050
+#define CC_VPPCTRL	0x00000007
+#define 	CC_VPP_OFF	0x00000000
+#define 	CC_VPP_12V	0x00000001
+#define 	CC_VPP_5V	0x00000002
+#define 	CC_VPP_3V	0x00000003
+#define 	CC_VPP_XV	0x00000004
+#define 	CC_VPP_YV	0x00000005
Index: /trunk/minix/drivers/tty/.depend
===================================================================
--- /trunk/minix/drivers/tty/.depend	(revision 9)
+++ /trunk/minix/drivers/tty/.depend	(revision 9)
@@ -0,0 +1,214 @@
+
+console.o:	../../kernel/config.h
+console.o:	../../kernel/const.h
+console.o:	../../kernel/type.h
+console.o:	../drivers.h
+console.o:	/usr/include/ansi.h
+console.o:	/usr/include/errno.h
+console.o:	/usr/include/ibm/bios.h
+console.o:	/usr/include/ibm/cpu.h
+console.o:	/usr/include/ibm/interrupt.h
+console.o:	/usr/include/ibm/ports.h
+console.o:	/usr/include/limits.h
+console.o:	/usr/include/minix/bitmap.h
+console.o:	/usr/include/minix/callnr.h
+console.o:	/usr/include/minix/com.h
+console.o:	/usr/include/minix/config.h
+console.o:	/usr/include/minix/const.h
+console.o:	/usr/include/minix/devio.h
+console.o:	/usr/include/minix/dmap.h
+console.o:	/usr/include/minix/ioctl.h
+console.o:	/usr/include/minix/ipc.h
+console.o:	/usr/include/minix/sys_config.h
+console.o:	/usr/include/minix/syslib.h
+console.o:	/usr/include/minix/sysutil.h
+console.o:	/usr/include/minix/type.h
+console.o:	/usr/include/net/ioctl.h
+console.o:	/usr/include/signal.h
+console.o:	/usr/include/stddef.h
+console.o:	/usr/include/stdlib.h
+console.o:	/usr/include/string.h
+console.o:	/usr/include/sys/dir.h
+console.o:	/usr/include/sys/ioc_cmos.h
+console.o:	/usr/include/sys/ioc_disk.h
+console.o:	/usr/include/sys/ioc_file.h
+console.o:	/usr/include/sys/ioc_memory.h
+console.o:	/usr/include/sys/ioc_scsi.h
+console.o:	/usr/include/sys/ioc_sound.h
+console.o:	/usr/include/sys/ioc_tape.h
+console.o:	/usr/include/sys/ioc_tty.h
+console.o:	/usr/include/sys/ioctl.h
+console.o:	/usr/include/sys/types.h
+console.o:	/usr/include/sys/vm.h
+console.o:	/usr/include/termios.h
+console.o:	/usr/include/timers.h
+console.o:	/usr/include/unistd.h
+console.o:	console.c
+console.o:	tty.h
+
+keyboard.o:	../../kernel/config.h
+keyboard.o:	../../kernel/const.h
+keyboard.o:	../../kernel/priv.h
+keyboard.o:	../../kernel/proc.h
+keyboard.o:	../../kernel/protect.h
+keyboard.o:	../../kernel/type.h
+keyboard.o:	../drivers.h
+keyboard.o:	/usr/include/ansi.h
+keyboard.o:	/usr/include/errno.h
+keyboard.o:	/usr/include/ibm/bios.h
+keyboard.o:	/usr/include/ibm/cpu.h
+keyboard.o:	/usr/include/ibm/interrupt.h
+keyboard.o:	/usr/include/ibm/ports.h
+keyboard.o:	/usr/include/limits.h
+keyboard.o:	/usr/include/minix/bitmap.h
+keyboard.o:	/usr/include/minix/callnr.h
+keyboard.o:	/usr/include/minix/com.h
+keyboard.o:	/usr/include/minix/config.h
+keyboard.o:	/usr/include/minix/const.h
+keyboard.o:	/usr/include/minix/devio.h
+keyboard.o:	/usr/include/minix/dmap.h
+keyboard.o:	/usr/include/minix/ioctl.h
+keyboard.o:	/usr/include/minix/ipc.h
+keyboard.o:	/usr/include/minix/keymap.h
+keyboard.o:	/usr/include/minix/sys_config.h
+keyboard.o:	/usr/include/minix/syslib.h
+keyboard.o:	/usr/include/minix/sysutil.h
+keyboard.o:	/usr/include/minix/type.h
+keyboard.o:	/usr/include/net/ioctl.h
+keyboard.o:	/usr/include/signal.h
+keyboard.o:	/usr/include/stddef.h
+keyboard.o:	/usr/include/stdlib.h
+keyboard.o:	/usr/include/string.h
+keyboard.o:	/usr/include/sys/dir.h
+keyboard.o:	/usr/include/sys/ioc_cmos.h
+keyboard.o:	/usr/include/sys/ioc_disk.h
+keyboard.o:	/usr/include/sys/ioc_file.h
+keyboard.o:	/usr/include/sys/ioc_memory.h
+keyboard.o:	/usr/include/sys/ioc_scsi.h
+keyboard.o:	/usr/include/sys/ioc_sound.h
+keyboard.o:	/usr/include/sys/ioc_tape.h
+keyboard.o:	/usr/include/sys/ioc_tty.h
+keyboard.o:	/usr/include/sys/ioctl.h
+keyboard.o:	/usr/include/sys/kbdio.h
+keyboard.o:	/usr/include/sys/select.h
+keyboard.o:	/usr/include/sys/time.h
+keyboard.o:	/usr/include/sys/types.h
+keyboard.o:	/usr/include/termios.h
+keyboard.o:	/usr/include/timers.h
+keyboard.o:	/usr/include/unistd.h
+keyboard.o:	keyboard.c
+keyboard.o:	keymaps/us-std.src
+keyboard.o:	tty.h
+
+pty.o:	../../kernel/config.h
+pty.o:	../../kernel/const.h
+pty.o:	../../kernel/type.h
+pty.o:	../drivers.h
+pty.o:	/usr/include/ansi.h
+pty.o:	/usr/include/assert.h
+pty.o:	/usr/include/errno.h
+pty.o:	/usr/include/ibm/bios.h
+pty.o:	/usr/include/ibm/cpu.h
+pty.o:	/usr/include/ibm/interrupt.h
+pty.o:	/usr/include/ibm/ports.h
+pty.o:	/usr/include/limits.h
+pty.o:	/usr/include/minix/bitmap.h
+pty.o:	/usr/include/minix/callnr.h
+pty.o:	/usr/include/minix/com.h
+pty.o:	/usr/include/minix/config.h
+pty.o:	/usr/include/minix/const.h
+pty.o:	/usr/include/minix/devio.h
+pty.o:	/usr/include/minix/dmap.h
+pty.o:	/usr/include/minix/ipc.h
+pty.o:	/usr/include/minix/sys_config.h
+pty.o:	/usr/include/minix/syslib.h
+pty.o:	/usr/include/minix/sysutil.h
+pty.o:	/usr/include/minix/type.h
+pty.o:	/usr/include/signal.h
+pty.o:	/usr/include/stddef.h
+pty.o:	/usr/include/stdlib.h
+pty.o:	/usr/include/string.h
+pty.o:	/usr/include/sys/dir.h
+pty.o:	/usr/include/sys/select.h
+pty.o:	/usr/include/sys/time.h
+pty.o:	/usr/include/sys/types.h
+pty.o:	/usr/include/termios.h
+pty.o:	/usr/include/timers.h
+pty.o:	/usr/include/unistd.h
+pty.o:	pty.c
+pty.o:	tty.h
+
+rs232.o:	../../kernel/config.h
+rs232.o:	../../kernel/const.h
+rs232.o:	../../kernel/type.h
+rs232.o:	../drivers.h
+rs232.o:	/usr/include/ansi.h
+rs232.o:	/usr/include/errno.h
+rs232.o:	/usr/include/ibm/bios.h
+rs232.o:	/usr/include/ibm/cpu.h
+rs232.o:	/usr/include/ibm/interrupt.h
+rs232.o:	/usr/include/ibm/ports.h
+rs232.o:	/usr/include/limits.h
+rs232.o:	/usr/include/minix/bitmap.h
+rs232.o:	/usr/include/minix/callnr.h
+rs232.o:	/usr/include/minix/com.h
+rs232.o:	/usr/include/minix/config.h
+rs232.o:	/usr/include/minix/const.h
+rs232.o:	/usr/include/minix/devio.h
+rs232.o:	/usr/include/minix/dmap.h
+rs232.o:	/usr/include/minix/ipc.h
+rs232.o:	/usr/include/minix/sys_config.h
+rs232.o:	/usr/include/minix/syslib.h
+rs232.o:	/usr/include/minix/sysutil.h
+rs232.o:	/usr/include/minix/type.h
+rs232.o:	/usr/include/signal.h
+rs232.o:	/usr/include/stddef.h
+rs232.o:	/usr/include/stdlib.h
+rs232.o:	/usr/include/string.h
+rs232.o:	/usr/include/sys/dir.h
+rs232.o:	/usr/include/sys/types.h
+rs232.o:	/usr/include/termios.h
+rs232.o:	/usr/include/timers.h
+rs232.o:	/usr/include/unistd.h
+rs232.o:	rs232.c
+rs232.o:	tty.h
+
+tty.o:	../../kernel/config.h
+tty.o:	../../kernel/const.h
+tty.o:	../../kernel/type.h
+tty.o:	../drivers.h
+tty.o:	/usr/include/ansi.h
+tty.o:	/usr/include/errno.h
+tty.o:	/usr/include/ibm/bios.h
+tty.o:	/usr/include/ibm/cpu.h
+tty.o:	/usr/include/ibm/interrupt.h
+tty.o:	/usr/include/ibm/ports.h
+tty.o:	/usr/include/limits.h
+tty.o:	/usr/include/minix/bitmap.h
+tty.o:	/usr/include/minix/callnr.h
+tty.o:	/usr/include/minix/com.h
+tty.o:	/usr/include/minix/config.h
+tty.o:	/usr/include/minix/const.h
+tty.o:	/usr/include/minix/devio.h
+tty.o:	/usr/include/minix/dmap.h
+tty.o:	/usr/include/minix/ioctl.h
+tty.o:	/usr/include/minix/ipc.h
+tty.o:	/usr/include/minix/keymap.h
+tty.o:	/usr/include/minix/sys_config.h
+tty.o:	/usr/include/minix/syslib.h
+tty.o:	/usr/include/minix/sysutil.h
+tty.o:	/usr/include/minix/type.h
+tty.o:	/usr/include/signal.h
+tty.o:	/usr/include/stddef.h
+tty.o:	/usr/include/stdlib.h
+tty.o:	/usr/include/string.h
+tty.o:	/usr/include/sys/dir.h
+tty.o:	/usr/include/sys/ioc_tty.h
+tty.o:	/usr/include/sys/select.h
+tty.o:	/usr/include/sys/time.h
+tty.o:	/usr/include/sys/types.h
+tty.o:	/usr/include/termios.h
+tty.o:	/usr/include/timers.h
+tty.o:	/usr/include/unistd.h
+tty.o:	tty.c
+tty.o:	tty.h
Index: /trunk/minix/drivers/tty/Makefile
===================================================================
--- /trunk/minix/drivers/tty/Makefile	(revision 9)
+++ /trunk/minix/drivers/tty/Makefile	(revision 9)
@@ -0,0 +1,45 @@
+# Makefile for terminal driver (TTY)
+DRIVER = tty
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+MAKE = exec make
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsys -lsysutil -ltimers
+
+OBJ = tty.o console.o vidcopy.o keyboard.o pty.o rs232.o 
+
+# build local binary 
+all build:	$(DRIVER)
+$(DRIVER):	$(OBJ) 
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+	install -S 256w $(DRIVER)
+
+# install with other drivers
+install:	
+	cd keymaps && $(MAKE) -$(MAKEFLAGS) install
+
+#/sbin/$(DRIVER):	$(DRIVER)
+#	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	cd keymaps && $(MAKE) -$(MAKEFLAGS) $@
+	rm -f $(DRIVER) *.o *.bak 
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
+
Index: /trunk/minix/drivers/tty/console.c
===================================================================
--- /trunk/minix/drivers/tty/console.c	(revision 9)
+++ /trunk/minix/drivers/tty/console.c	(revision 9)
@@ -0,0 +1,1271 @@
+/* Code and data for the IBM console driver.
+ *
+ * The 6845 video controller used by the IBM PC shares its video memory with
+ * the CPU somewhere in the 0xB0000 memory bank.  To the 6845 this memory
+ * consists of 16-bit words.  Each word has a character code in the low byte
+ * and a so-called attribute byte in the high byte.  The CPU directly modifies
+ * video memory to display characters, and sets two registers on the 6845 that
+ * specify the video origin and the cursor position.  The video origin is the
+ * place in video memory where the first character (upper left corner) can
+ * be found.  Moving the origin is a fast way to scroll the screen.  Some
+ * video adapters wrap around the top of video memory, so the origin can
+ * move without bounds.  For other adapters screen memory must sometimes be
+ * moved to reset the origin.  All computations on video memory use character
+ * (word) addresses for simplicity and assume there is no wrapping.  The
+ * assembly support functions translate the word addresses to byte addresses
+ * and the scrolling function worries about wrapping.
+ */
+
+#include "../drivers.h"
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/vm.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include "tty.h"
+
+#include "../../kernel/const.h"
+#include "../../kernel/config.h"
+#include "../../kernel/type.h"
+
+/* Definitions used by the console driver. */
+#define MONO_BASE    0xB0000L	/* base of mono video memory */
+#define COLOR_BASE   0xB8000L	/* base of color video memory */
+#define MONO_SIZE     0x1000	/* 4K mono video memory */
+#define COLOR_SIZE    0x4000	/* 16K color video memory */
+#define EGA_SIZE      0x8000	/* EGA & VGA have at least 32K */
+#define BLANK_COLOR   0x0700	/* determines cursor color on blank screen */
+#define SCROLL_UP          0	/* scroll forward */
+#define SCROLL_DOWN        1	/* scroll backward */
+#define BLANK_MEM ((u16_t *) 0)	/* tells mem_vid_copy() to blank the screen */
+#define CONS_RAM_WORDS    80	/* video ram buffer size */
+#define MAX_ESC_PARMS      4	/* number of escape sequence params allowed */
+
+/* Constants relating to the controller chips. */
+#define M_6845         0x3B4	/* port for 6845 mono */
+#define C_6845         0x3D4	/* port for 6845 color */
+#define INDEX              0	/* 6845's index register */
+#define DATA               1	/* 6845's data register */
+#define STATUS             6	/* 6845's status register */
+#define VID_ORG           12	/* 6845's origin register */
+#define CURSOR            14	/* 6845's cursor register */
+
+/* The clock task should provide an interface for this */
+#define TIMER_FREQ  1193182L    /* clock frequency for timer in PC and AT */
+
+/* Beeper. */
+#define BEEP_FREQ     0x0533	/* value to put into timer to set beep freq */
+#define B_TIME		   3	/* length of CTRL-G beep is ticks */
+
+/* definitions used for font management */
+#define GA_SEQUENCER_INDEX	0x3C4
+#define GA_SEQUENCER_DATA	0x3C5
+#define GA_GRAPHICS_INDEX	0x3CE
+#define GA_GRAPHICS_DATA	0x3CF
+#define GA_VIDEO_ADDRESS	0xA0000L
+#define GA_FONT_SIZE		8192
+
+/* Global variables used by the console driver and assembly support. */
+PUBLIC int vid_index;		/* index of video segment in remote mem map */
+PUBLIC u16_t vid_seg;
+PUBLIC vir_bytes vid_off;	/* video ram is found at vid_seg:vid_off */
+PUBLIC unsigned vid_size;	/* 0x2000 for color or 0x0800 for mono */
+PUBLIC unsigned vid_mask;	/* 0x1FFF for color or 0x07FF for mono */
+PUBLIC unsigned blank_color = BLANK_COLOR; /* display code for blank */
+
+/* Private variables used by the console driver. */
+PRIVATE int vid_port;		/* I/O port for accessing 6845 */
+PRIVATE int wrap;		/* hardware can wrap? */
+PRIVATE int softscroll;		/* 1 = software scrolling, 0 = hardware */
+PRIVATE int beeping;		/* speaker is beeping? */
+PRIVATE unsigned font_lines;	/* font lines per character */
+PRIVATE unsigned scr_width;	/* # characters on a line */
+PRIVATE unsigned scr_lines;	/* # lines on the screen */
+PRIVATE unsigned scr_size;	/* # characters on the screen */
+
+/* Per console data. */
+typedef struct console {
+  tty_t *c_tty;			/* associated TTY struct */
+  int c_column;			/* current column number (0-origin) */
+  int c_row;			/* current row (0 at top of screen) */
+  int c_rwords;			/* number of WORDS (not bytes) in outqueue */
+  unsigned c_start;		/* start of video memory of this console */
+  unsigned c_limit;		/* limit of this console's video memory */
+  unsigned c_org;		/* location in RAM where 6845 base points */
+  unsigned c_cur;		/* current position of cursor in video RAM */
+  unsigned c_attr;		/* character attribute */
+  unsigned c_blank;		/* blank attribute */
+  char c_reverse;		/* reverse video */
+  char c_esc_state;		/* 0=normal, 1=ESC, 2=ESC[ */
+  char c_esc_intro;		/* Distinguishing character following ESC */
+  int *c_esc_parmp;		/* pointer to current escape parameter */
+  int c_esc_parmv[MAX_ESC_PARMS];	/* list of escape parameters */
+  u16_t c_ramqueue[CONS_RAM_WORDS];	/* buffer for video RAM */
+} console_t;
+
+PRIVATE int nr_cons= 1;		/* actual number of consoles */
+PRIVATE console_t cons_table[NR_CONS];
+PRIVATE console_t *curcons;	/* currently visible */
+
+/* Color if using a color controller. */
+#define color	(vid_port == C_6845)
+
+/* Map from ANSI colors to the attributes used by the PC */
+PRIVATE int ansi_colors[8] = {0, 4, 2, 6, 1, 5, 3, 7};
+
+/* Structure used for font management */
+struct sequence {
+	unsigned short index;
+	unsigned char port;
+	unsigned char value;
+};
+
+FORWARD _PROTOTYPE( int cons_write, (struct tty *tp, int try)		);
+FORWARD _PROTOTYPE( void cons_echo, (tty_t *tp, int c)			);
+FORWARD _PROTOTYPE( void out_char, (console_t *cons, int c)		);
+FORWARD _PROTOTYPE( void cons_putk, (int c)				);
+FORWARD _PROTOTYPE( void beep, (void)					);
+FORWARD _PROTOTYPE( void do_escape, (console_t *cons, int c)		);
+FORWARD _PROTOTYPE( void flush, (console_t *cons)			);
+FORWARD _PROTOTYPE( void parse_escape, (console_t *cons, int c)		);
+FORWARD _PROTOTYPE( void scroll_screen, (console_t *cons, int dir)	);
+FORWARD _PROTOTYPE( void set_6845, (int reg, unsigned val)		);
+FORWARD _PROTOTYPE( void get_6845, (int reg, unsigned *val)		);
+FORWARD _PROTOTYPE( void stop_beep, (timer_t *tmrp)			);
+FORWARD _PROTOTYPE( void cons_org0, (void)				);
+FORWARD _PROTOTYPE( int ga_program, (struct sequence *seq)		);
+FORWARD _PROTOTYPE( int cons_ioctl, (tty_t *tp, int)			);
+PRIVATE _PROTOTYPE( void ser_putc, (char c)				);
+
+/*===========================================================================*
+ *				cons_write				     *
+ *===========================================================================*/
+PRIVATE int cons_write(tp, try)
+register struct tty *tp;	/* tells which terminal is to be used */
+int try;
+{
+/* Copy as much data as possible to the output queue, then start I/O.  On
+ * memory-mapped terminals, such as the IBM console, the I/O will also be
+ * finished, and the counts updated.  Keep repeating until all I/O done.
+ */
+
+  int count;
+  int result;
+  register char *tbuf;
+  char buf[64];
+  console_t *cons = tp->tty_priv;
+
+  if (try) return 1;	/* we can always write to console */
+
+  /* Check quickly for nothing to do, so this can be called often without
+   * unmodular tests elsewhere.
+   */
+  if ((count = tp->tty_outleft) == 0 || tp->tty_inhibited) return;
+
+  /* Copy the user bytes to buf[] for decent addressing. Loop over the
+   * copies, since the user buffer may be much larger than buf[].
+   */
+  do {
+	if (count > sizeof(buf)) count = sizeof(buf);
+	if ((result = sys_vircopy(tp->tty_outproc, D, tp->tty_out_vir, 
+			SELF, D, (vir_bytes) buf, (vir_bytes) count)) != OK)
+		break;
+	tbuf = buf;
+
+	/* Update terminal data structure. */
+	tp->tty_out_vir += count;
+	tp->tty_outcum += count;
+	tp->tty_outleft -= count;
+
+	/* Output each byte of the copy to the screen.  Avoid calling
+	 * out_char() for the "easy" characters, put them into the buffer
+	 * directly.
+	 */
+	do {
+		if ((unsigned) *tbuf < ' ' || cons->c_esc_state > 0
+			|| cons->c_column >= scr_width
+			|| cons->c_rwords >= buflen(cons->c_ramqueue))
+		{
+			out_char(cons, *tbuf++);
+		} else {
+			cons->c_ramqueue[cons->c_rwords++] =
+					cons->c_attr | (*tbuf++ & BYTE);
+			cons->c_column++;
+		}
+	} while (--count != 0);
+  } while ((count = tp->tty_outleft) != 0 && !tp->tty_inhibited);
+
+  flush(cons);			/* transfer anything buffered to the screen */
+
+  /* Reply to the writer if all output is finished or if an error occured. */
+  if (tp->tty_outleft == 0 || result != OK) {
+	/* REVIVE is not possible. I/O on memory mapped consoles finishes. */
+	tty_reply(tp->tty_outrepcode, tp->tty_outcaller, tp->tty_outproc,
+							tp->tty_outcum);
+	tp->tty_outcum = 0;
+  }
+}
+
+/*===========================================================================*
+ *				cons_echo				     *
+ *===========================================================================*/
+PRIVATE void cons_echo(tp, c)
+register tty_t *tp;		/* pointer to tty struct */
+int c;				/* character to be echoed */
+{
+/* Echo keyboard input (print & flush). */
+  console_t *cons = tp->tty_priv;
+
+  out_char(cons, c);
+  flush(cons);
+}
+
+/*===========================================================================*
+ *				out_char				     *
+ *===========================================================================*/
+PRIVATE void out_char(cons, c)
+register console_t *cons;	/* pointer to console struct */
+int c;				/* character to be output */
+{
+/* Output a character on the console.  Check for escape sequences first. */
+  if (cons->c_esc_state > 0) {
+	parse_escape(cons, c);
+	return;
+  }
+
+  switch(c) {
+	case 000:		/* null is typically used for padding */
+		return;		/* better not do anything */
+
+	case 007:		/* ring the bell */
+		flush(cons);	/* print any chars queued for output */
+		beep();
+		return;
+
+	case '\b':		/* backspace */
+		if (--cons->c_column < 0) {
+			if (--cons->c_row >= 0) cons->c_column += scr_width;
+		}
+		flush(cons);
+		return;
+
+	case '\n':		/* line feed */
+		if ((cons->c_tty->tty_termios.c_oflag & (OPOST|ONLCR))
+						== (OPOST|ONLCR)) {
+			cons->c_column = 0;
+		}
+		/*FALL THROUGH*/
+	case 013:		/* CTRL-K */
+	case 014:		/* CTRL-L */
+		if (cons->c_row == scr_lines-1) {
+			scroll_screen(cons, SCROLL_UP);
+		} else {
+			cons->c_row++;
+		}
+		flush(cons);
+		return;
+
+	case '\r':		/* carriage return */
+		cons->c_column = 0;
+		flush(cons);
+		return;
+
+	case '\t':		/* tab */
+		cons->c_column = (cons->c_column + TAB_SIZE) & ~TAB_MASK;
+		if (cons->c_column > scr_width) {
+			cons->c_column -= scr_width;
+			if (cons->c_row == scr_lines-1) {
+				scroll_screen(cons, SCROLL_UP);
+			} else {
+				cons->c_row++;
+			}
+		}
+		flush(cons);
+		return;
+
+	case 033:		/* ESC - start of an escape sequence */
+		flush(cons);	/* print any chars queued for output */
+		cons->c_esc_state = 1;	/* mark ESC as seen */
+		return;
+
+	default:		/* printable chars are stored in ramqueue */
+		if (cons->c_column >= scr_width) {
+			if (!LINEWRAP) return;
+			if (cons->c_row == scr_lines-1) {
+				scroll_screen(cons, SCROLL_UP);
+			} else {
+				cons->c_row++;
+			}
+			cons->c_column = 0;
+			flush(cons);
+		}
+		if (cons->c_rwords == buflen(cons->c_ramqueue)) flush(cons);
+		cons->c_ramqueue[cons->c_rwords++] = cons->c_attr | (c & BYTE);
+		cons->c_column++;			/* next column */
+		return;
+  }
+}
+
+/*===========================================================================*
+ *				scroll_screen				     *
+ *===========================================================================*/
+PRIVATE void scroll_screen(cons, dir)
+register console_t *cons;	/* pointer to console struct */
+int dir;			/* SCROLL_UP or SCROLL_DOWN */
+{
+  unsigned new_line, new_org, chars;
+
+  flush(cons);
+  chars = scr_size - scr_width;		/* one screen minus one line */
+
+  /* Scrolling the screen is a real nuisance due to the various incompatible
+   * video cards.  This driver supports software scrolling (Hercules?),
+   * hardware scrolling (mono and CGA cards) and hardware scrolling without
+   * wrapping (EGA cards).  In the latter case we must make sure that
+   *		c_start <= c_org && c_org + scr_size <= c_limit
+   * holds, because EGA doesn't wrap around the end of video memory.
+   */
+  if (dir == SCROLL_UP) {
+	/* Scroll one line up in 3 ways: soft, avoid wrap, use origin. */
+	if (softscroll) {
+		vid_vid_copy(cons->c_start + scr_width, cons->c_start, chars);
+	} else
+	if (!wrap && cons->c_org + scr_size + scr_width >= cons->c_limit) {
+		vid_vid_copy(cons->c_org + scr_width, cons->c_start, chars);
+		cons->c_org = cons->c_start;
+	} else {
+		cons->c_org = (cons->c_org + scr_width) & vid_mask;
+	}
+	new_line = (cons->c_org + chars) & vid_mask;
+  } else {
+	/* Scroll one line down in 3 ways: soft, avoid wrap, use origin. */
+	if (softscroll) {
+		vid_vid_copy(cons->c_start, cons->c_start + scr_width, chars);
+	} else
+	if (!wrap && cons->c_org < cons->c_start + scr_width) {
+		new_org = cons->c_limit - scr_size;
+		vid_vid_copy(cons->c_org, new_org + scr_width, chars);
+		cons->c_org = new_org;
+	} else {
+		cons->c_org = (cons->c_org - scr_width) & vid_mask;
+	}
+	new_line = cons->c_org;
+  }
+  /* Blank the new line at top or bottom. */
+  blank_color = cons->c_blank;
+  mem_vid_copy(BLANK_MEM, new_line, scr_width);
+
+  /* Set the new video origin. */
+  if (cons == curcons) set_6845(VID_ORG, cons->c_org);
+  flush(cons);
+}
+
+/*===========================================================================*
+ *				flush					     *
+ *===========================================================================*/
+PRIVATE void flush(cons)
+register console_t *cons;	/* pointer to console struct */
+{
+/* Send characters buffered in 'ramqueue' to screen memory, check the new
+ * cursor position, compute the new hardware cursor position and set it.
+ */
+  unsigned cur;
+  tty_t *tp = cons->c_tty;
+
+  /* Have the characters in 'ramqueue' transferred to the screen. */
+  if (cons->c_rwords > 0) {
+	mem_vid_copy(cons->c_ramqueue, cons->c_cur, cons->c_rwords);
+	cons->c_rwords = 0;
+
+	/* TTY likes to know the current column and if echoing messed up. */
+	tp->tty_position = cons->c_column;
+	tp->tty_reprint = TRUE;
+  }
+
+  /* Check and update the cursor position. */
+  if (cons->c_column < 0) cons->c_column = 0;
+  if (cons->c_column > scr_width) cons->c_column = scr_width;
+  if (cons->c_row < 0) cons->c_row = 0;
+  if (cons->c_row >= scr_lines) cons->c_row = scr_lines - 1;
+  cur = cons->c_org + cons->c_row * scr_width + cons->c_column;
+  if (cur != cons->c_cur) {
+	if (cons == curcons) set_6845(CURSOR, cur);
+	cons->c_cur = cur;
+  }
+}
+
+/*===========================================================================*
+ *				parse_escape				     *
+ *===========================================================================*/
+PRIVATE void parse_escape(cons, c)
+register console_t *cons;	/* pointer to console struct */
+char c;				/* next character in escape sequence */
+{
+/* The following ANSI escape sequences are currently supported.
+ * If n and/or m are omitted, they default to 1.
+ *   ESC [nA moves up n lines
+ *   ESC [nB moves down n lines
+ *   ESC [nC moves right n spaces
+ *   ESC [nD moves left n spaces
+ *   ESC [m;nH" moves cursor to (m,n)
+ *   ESC [J clears screen from cursor
+ *   ESC [K clears line from cursor
+ *   ESC [nL inserts n lines ar cursor
+ *   ESC [nM deletes n lines at cursor
+ *   ESC [nP deletes n chars at cursor
+ *   ESC [n@ inserts n chars at cursor
+ *   ESC [nm enables rendition n (0=normal, 4=bold, 5=blinking, 7=reverse)
+ *   ESC M scrolls the screen backwards if the cursor is on the top line
+ */
+
+  switch (cons->c_esc_state) {
+    case 1:			/* ESC seen */
+	cons->c_esc_intro = '\0';
+	cons->c_esc_parmp = bufend(cons->c_esc_parmv);
+	do {
+		*--cons->c_esc_parmp = 0;
+	} while (cons->c_esc_parmp > cons->c_esc_parmv);
+	switch (c) {
+	    case '[':	/* Control Sequence Introducer */
+		cons->c_esc_intro = c;
+		cons->c_esc_state = 2;
+		break;
+	    case 'M':	/* Reverse Index */
+		do_escape(cons, c);
+		break;
+	    default:
+		cons->c_esc_state = 0;
+	}
+	break;
+
+    case 2:			/* ESC [ seen */
+	if (c >= '0' && c <= '9') {
+		if (cons->c_esc_parmp < bufend(cons->c_esc_parmv))
+			*cons->c_esc_parmp = *cons->c_esc_parmp * 10 + (c-'0');
+	} else
+	if (c == ';') {
+		if (cons->c_esc_parmp < bufend(cons->c_esc_parmv))
+			cons->c_esc_parmp++;
+	} else {
+		do_escape(cons, c);
+	}
+	break;
+  }
+}
+
+/*===========================================================================*
+ *				do_escape				     *
+ *===========================================================================*/
+PRIVATE void do_escape(cons, c)
+register console_t *cons;	/* pointer to console struct */
+char c;				/* next character in escape sequence */
+{
+  int value, n;
+  unsigned src, dst, count;
+  int *parmp;
+
+  /* Some of these things hack on screen RAM, so it had better be up to date */
+  flush(cons);
+
+  if (cons->c_esc_intro == '\0') {
+	/* Handle a sequence beginning with just ESC */
+	switch (c) {
+	    case 'M':		/* Reverse Index */
+		if (cons->c_row == 0) {
+			scroll_screen(cons, SCROLL_DOWN);
+		} else {
+			cons->c_row--;
+		}
+		flush(cons);
+		break;
+
+	    default: break;
+	}
+  } else
+  if (cons->c_esc_intro == '[') {
+	/* Handle a sequence beginning with ESC [ and parameters */
+	value = cons->c_esc_parmv[0];
+	switch (c) {
+	    case 'A':		/* ESC [nA moves up n lines */
+		n = (value == 0 ? 1 : value);
+		cons->c_row -= n;
+		flush(cons);
+		break;
+
+	    case 'B':		/* ESC [nB moves down n lines */
+		n = (value == 0 ? 1 : value);
+		cons->c_row += n;
+		flush(cons);
+		break;
+
+	    case 'C':		/* ESC [nC moves right n spaces */
+		n = (value == 0 ? 1 : value);
+		cons->c_column += n;
+		flush(cons);
+		break;
+
+	    case 'D':		/* ESC [nD moves left n spaces */
+		n = (value == 0 ? 1 : value);
+		cons->c_column -= n;
+		flush(cons);
+		break;
+
+	    case 'H':		/* ESC [m;nH" moves cursor to (m,n) */
+		cons->c_row = cons->c_esc_parmv[0] - 1;
+		cons->c_column = cons->c_esc_parmv[1] - 1;
+		flush(cons);
+		break;
+
+	    case 'J':		/* ESC [sJ clears in display */
+		switch (value) {
+		    case 0:	/* Clear from cursor to end of screen */
+			count = scr_size - (cons->c_cur - cons->c_org);
+			dst = cons->c_cur;
+			break;
+		    case 1:	/* Clear from start of screen to cursor */
+			count = cons->c_cur - cons->c_org;
+			dst = cons->c_org;
+			break;
+		    case 2:	/* Clear entire screen */
+			count = scr_size;
+			dst = cons->c_org;
+			break;
+		    default:	/* Do nothing */
+			count = 0;
+			dst = cons->c_org;
+		}
+		blank_color = cons->c_blank;
+		mem_vid_copy(BLANK_MEM, dst, count);
+		break;
+
+	    case 'K':		/* ESC [sK clears line from cursor */
+		switch (value) {
+		    case 0:	/* Clear from cursor to end of line */
+			count = scr_width - cons->c_column;
+			dst = cons->c_cur;
+			break;
+		    case 1:	/* Clear from beginning of line to cursor */
+			count = cons->c_column;
+			dst = cons->c_cur - cons->c_column;
+			break;
+		    case 2:	/* Clear entire line */
+			count = scr_width;
+			dst = cons->c_cur - cons->c_column;
+			break;
+		    default:	/* Do nothing */
+			count = 0;
+			dst = cons->c_cur;
+		}
+		blank_color = cons->c_blank;
+		mem_vid_copy(BLANK_MEM, dst, count);
+		break;
+
+	    case 'L':		/* ESC [nL inserts n lines at cursor */
+		n = value;
+		if (n < 1) n = 1;
+		if (n > (scr_lines - cons->c_row))
+			n = scr_lines - cons->c_row;
+
+		src = cons->c_org + cons->c_row * scr_width;
+		dst = src + n * scr_width;
+		count = (scr_lines - cons->c_row - n) * scr_width;
+		vid_vid_copy(src, dst, count);
+		blank_color = cons->c_blank;
+		mem_vid_copy(BLANK_MEM, src, n * scr_width);
+		break;
+
+	    case 'M':		/* ESC [nM deletes n lines at cursor */
+		n = value;
+		if (n < 1) n = 1;
+		if (n > (scr_lines - cons->c_row))
+			n = scr_lines - cons->c_row;
+
+		dst = cons->c_org + cons->c_row * scr_width;
+		src = dst + n * scr_width;
+		count = (scr_lines - cons->c_row - n) * scr_width;
+		vid_vid_copy(src, dst, count);
+		blank_color = cons->c_blank;
+		mem_vid_copy(BLANK_MEM, dst + count, n * scr_width);
+		break;
+
+	    case '@':		/* ESC [n@ inserts n chars at cursor */
+		n = value;
+		if (n < 1) n = 1;
+		if (n > (scr_width - cons->c_column))
+			n = scr_width - cons->c_column;
+
+		src = cons->c_cur;
+		dst = src + n;
+		count = scr_width - cons->c_column - n;
+		vid_vid_copy(src, dst, count);
+		blank_color = cons->c_blank;
+		mem_vid_copy(BLANK_MEM, src, n);
+		break;
+
+	    case 'P':		/* ESC [nP deletes n chars at cursor */
+		n = value;
+		if (n < 1) n = 1;
+		if (n > (scr_width - cons->c_column))
+			n = scr_width - cons->c_column;
+
+		dst = cons->c_cur;
+		src = dst + n;
+		count = scr_width - cons->c_column - n;
+		vid_vid_copy(src, dst, count);
+		blank_color = cons->c_blank;
+		mem_vid_copy(BLANK_MEM, dst + count, n);
+		break;
+
+	    case 'm':		/* ESC [nm enables rendition n */
+		for (parmp = cons->c_esc_parmv; parmp <= cons->c_esc_parmp
+				&& parmp < bufend(cons->c_esc_parmv); parmp++) {
+			if (cons->c_reverse) {
+				/* Unswap fg and bg colors */
+				cons->c_attr =	((cons->c_attr & 0x7000) >> 4) |
+						((cons->c_attr & 0x0700) << 4) |
+						((cons->c_attr & 0x8800));
+			}
+			switch (n = *parmp) {
+			    case 0:	/* NORMAL */
+				cons->c_attr = cons->c_blank = BLANK_COLOR;
+				cons->c_reverse = FALSE;
+				break;
+
+			    case 1:	/* BOLD  */
+				/* Set intensity bit */
+				cons->c_attr |= 0x0800;
+				break;
+
+			    case 4:	/* UNDERLINE */
+				if (color) {
+					/* Change white to cyan, i.e. lose red
+					 */
+					cons->c_attr = (cons->c_attr & 0xBBFF);
+				} else {
+					/* Set underline attribute */
+					cons->c_attr = (cons->c_attr & 0x99FF);
+				}
+				break;
+
+			    case 5:	/* BLINKING */
+				/* Set the blink bit */
+				cons->c_attr |= 0x8000;
+				break;
+
+			    case 7:	/* REVERSE */
+				cons->c_reverse = TRUE;
+				break;
+
+			    default:	/* COLOR */
+				if (n == 39) n = 37;	/* set default color */
+				if (n == 49) n = 40;
+
+				if (!color) {
+					/* Don't mess up a monochrome screen */
+				} else
+				if (30 <= n && n <= 37) {
+					/* Foreground color */
+					cons->c_attr =
+						(cons->c_attr & 0xF8FF) |
+						(ansi_colors[(n - 30)] << 8);
+					cons->c_blank =
+						(cons->c_blank & 0xF8FF) |
+						(ansi_colors[(n - 30)] << 8);
+				} else
+				if (40 <= n && n <= 47) {
+					/* Background color */
+					cons->c_attr =
+						(cons->c_attr & 0x8FFF) |
+						(ansi_colors[(n - 40)] << 12);
+					cons->c_blank =
+						(cons->c_blank & 0x8FFF) |
+						(ansi_colors[(n - 40)] << 12);
+				}
+			}
+			if (cons->c_reverse) {
+				/* Swap fg and bg colors */
+				cons->c_attr =	((cons->c_attr & 0x7000) >> 4) |
+						((cons->c_attr & 0x0700) << 4) |
+						((cons->c_attr & 0x8800));
+			}
+		}
+		break;
+	}
+  }
+  cons->c_esc_state = 0;
+}
+
+/*===========================================================================*
+ *				set_6845				     *
+ *===========================================================================*/
+PRIVATE void set_6845(reg, val)
+int reg;			/* which register pair to set */
+unsigned val;			/* 16-bit value to set it to */
+{
+/* Set a register pair inside the 6845.
+ * Registers 12-13 tell the 6845 where in video ram to start
+ * Registers 14-15 tell the 6845 where to put the cursor
+ */
+  pvb_pair_t char_out[4];
+  pv_set(char_out[0], vid_port + INDEX, reg);	/* set index register */
+  pv_set(char_out[1], vid_port + DATA, (val>>8) & BYTE);    /* high byte */
+  pv_set(char_out[2], vid_port + INDEX, reg + 1);	    /* again */
+  pv_set(char_out[3], vid_port + DATA, val&BYTE);	    /* low byte */
+  sys_voutb(char_out, 4);			/* do actual output */
+}
+
+/*===========================================================================*
+ *				get_6845				     *
+ *===========================================================================*/
+PRIVATE void get_6845(reg, val)
+int reg;			/* which register pair to set */
+unsigned *val;			/* 16-bit value to set it to */
+{
+  char v1, v2;
+  unsigned long v;
+/* Get a register pair inside the 6845.  */
+  sys_outb(vid_port + INDEX, reg); 
+  sys_inb(vid_port + DATA, &v); 
+  v1 = v;
+  sys_outb(vid_port + INDEX, reg+1); 
+  sys_inb(vid_port + DATA, &v); 
+  v2 = v;
+  *val = (v1 << 8) | v2;
+}
+
+/*===========================================================================*
+ *				beep					     *
+ *===========================================================================*/
+PRIVATE void beep()
+{
+/* Making a beeping sound on the speaker (output for CRTL-G).
+ * This routine works by turning on the bits 0 and 1 in port B of the 8255
+ * chip that drive the speaker.
+ */
+  static timer_t tmr_stop_beep;
+  pvb_pair_t char_out[3];
+  clock_t now;
+  unsigned long port_b_val;
+  int s;
+  
+  /* Fetch current time in advance to prevent beeping delay. */
+  if ((s=getuptime(&now)) != OK)
+  	panic("TTY","Console couldn't get clock's uptime.", s);
+  if (!beeping) {
+	/* Set timer channel 2, square wave, with given frequency. */
+        pv_set(char_out[0], TIMER_MODE, 0xB6);	
+        pv_set(char_out[1], TIMER2, (BEEP_FREQ >> 0) & BYTE);
+        pv_set(char_out[2], TIMER2, (BEEP_FREQ >> 8) & BYTE);
+        if (sys_voutb(char_out, 3)==OK) {
+        	if (sys_inb(PORT_B, &port_b_val)==OK &&
+        	    sys_outb(PORT_B, (port_b_val|3))==OK)
+        	    	beeping = TRUE;
+        }
+  }
+  /* Add a timer to the timers list. Possibly reschedule the alarm. */
+  tmrs_settimer(&tty_timers, &tmr_stop_beep, now+B_TIME, stop_beep, NULL);
+  if (tty_timers->tmr_exp_time != tty_next_timeout) {
+  	tty_next_timeout = tty_timers->tmr_exp_time;
+  	if ((s=sys_setalarm(tty_next_timeout, 1)) != OK)
+  		panic("TTY","Console couldn't set alarm.", s);
+  }
+}
+
+
+/*===========================================================================*
+ *				do_video				     *
+ *===========================================================================*/
+PUBLIC void do_video(message *m)
+{
+	int i, n, r, ops, watch;
+	unsigned char c;
+
+	/* Execute the requested device driver function. */
+	r= EINVAL;	/* just in case */
+	switch (m->m_type) {
+	    case DEV_OPEN:
+		/* Should grant IOPL */
+		r= OK;
+		break;
+	    case DEV_CLOSE:
+		r= OK;
+		break;
+	    case DEV_IOCTL:
+		if (m->TTY_REQUEST == MIOCMAP || m->TTY_REQUEST == MIOCUNMAP)
+		{
+			int r, do_map;
+			struct mapreq mapreq;
+
+			do_map= (m->REQUEST == MIOCMAP);	/* else unmap */
+
+			/* Get request structure */
+			r= sys_vircopy(m->IO_ENDPT, D,
+				(vir_bytes)m->ADDRESS,
+				SELF, D, (vir_bytes)&mapreq, sizeof(mapreq));
+			if (r != OK)
+			{
+				tty_reply(TASK_REPLY, m->m_source, m->IO_ENDPT,
+					r);
+				return;
+			}
+			r= sys_vm_map(m->IO_ENDPT, do_map,
+				(phys_bytes)mapreq.base, mapreq.size,
+				mapreq.offset);
+			tty_reply(TASK_REPLY, m->m_source, m->IO_ENDPT, r);
+			return;
+		}
+		r= ENOTTY;
+		break;
+
+	    default:		
+		printf(
+		"Warning, TTY(video) got unexpected request %d from %d\n",
+			m->m_type, m->m_source);
+		r= EINVAL;
+	}
+	tty_reply(TASK_REPLY, m->m_source, m->IO_ENDPT, r);
+}
+
+
+/*===========================================================================*
+ *				beep_x					     *
+ *===========================================================================*/
+PUBLIC void beep_x(freq, dur)
+unsigned freq;
+clock_t dur;
+{
+/* Making a beeping sound on the speaker.
+ * This routine works by turning on the bits 0 and 1 in port B of the 8255
+ * chip that drive the speaker.
+ */
+  static timer_t tmr_stop_beep;
+  pvb_pair_t char_out[3];
+  clock_t now;
+  unsigned long port_b_val;
+  int s;
+  
+  unsigned long ival= TIMER_FREQ / freq;
+  if (ival == 0 || ival > 0xffff)
+	return;	/* Frequency out of range */
+
+  /* Fetch current time in advance to prevent beeping delay. */
+  if ((s=getuptime(&now)) != OK)
+  	panic("TTY","Console couldn't get clock's uptime.", s);
+  if (!beeping) {
+	/* Set timer channel 2, square wave, with given frequency. */
+        pv_set(char_out[0], TIMER_MODE, 0xB6);	
+        pv_set(char_out[1], TIMER2, (ival >> 0) & BYTE);
+        pv_set(char_out[2], TIMER2, (ival >> 8) & BYTE);
+        if (sys_voutb(char_out, 3)==OK) {
+        	if (sys_inb(PORT_B, &port_b_val)==OK &&
+        	    sys_outb(PORT_B, (port_b_val|3))==OK)
+        	    	beeping = TRUE;
+        }
+  }
+  /* Add a timer to the timers list. Possibly reschedule the alarm. */
+  tmrs_settimer(&tty_timers, &tmr_stop_beep, now+dur, stop_beep, NULL);
+  if (tty_timers->tmr_exp_time != tty_next_timeout) {
+  	tty_next_timeout = tty_timers->tmr_exp_time;
+  	if ((s=sys_setalarm(tty_next_timeout, 1)) != OK)
+  		panic("TTY","Console couldn't set alarm.", s);
+  }
+}
+
+/*===========================================================================*
+ *				stop_beep				     *
+ *===========================================================================*/
+PRIVATE void stop_beep(tmrp)
+timer_t *tmrp;
+{
+/* Turn off the beeper by turning off bits 0 and 1 in PORT_B. */
+  unsigned long port_b_val;
+  if (sys_inb(PORT_B, &port_b_val)==OK && 
+	sys_outb(PORT_B, (port_b_val & ~3))==OK)
+		beeping = FALSE;
+}
+
+/*===========================================================================*
+ *				scr_init				     *
+ *===========================================================================*/
+PUBLIC void scr_init(tp)
+tty_t *tp;
+{
+/* Initialize the screen driver. */
+  console_t *cons;
+  phys_bytes vid_base;
+  u16_t bios_columns, bios_crtbase, bios_fontlines;
+  u8_t bios_rows;
+  int line;
+  int s;
+  static int vdu_initialized = 0;
+  unsigned page_size;
+
+  /* Associate console and TTY. */
+  line = tp - &tty_table[0];
+  if (line >= nr_cons) return;
+  cons = &cons_table[line];
+  cons->c_tty = tp;
+  tp->tty_priv = cons;
+
+  /* Fill in TTY function hooks. */
+  tp->tty_devwrite = cons_write;
+  tp->tty_echo = cons_echo;
+  tp->tty_ioctl = cons_ioctl;
+
+  /* Get the BIOS parameters that describe the VDU. */
+  if (! vdu_initialized++) {
+
+	/* How about error checking? What to do on failure??? */
+  	s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) VDU_SCREEN_COLS_ADDR,
+  		SELF, D, (vir_bytes) &bios_columns, VDU_SCREEN_COLS_SIZE);
+  	s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) VDU_CRT_BASE_ADDR, 
+  		SELF, D, (vir_bytes) &bios_crtbase, VDU_CRT_BASE_SIZE);
+  	s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) VDU_SCREEN_ROWS_ADDR, 
+  		SELF, D, (vir_bytes) &bios_rows, VDU_SCREEN_ROWS_SIZE);
+  	s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) VDU_FONTLINES_ADDR, 
+  		SELF, D, (vir_bytes) &bios_fontlines, VDU_FONTLINES_SIZE);
+
+  	vid_port = bios_crtbase;
+  	scr_width = bios_columns;
+  	font_lines = bios_fontlines;
+  	scr_lines = machine.vdu_ega ? bios_rows+1 : 25;
+
+  	if (color) {
+		vid_base = COLOR_BASE;
+		vid_size = COLOR_SIZE;
+  	} else {
+		vid_base = MONO_BASE;
+		vid_size = MONO_SIZE;
+  	}
+  	if (machine.vdu_ega) vid_size = EGA_SIZE;
+  	wrap = ! machine.vdu_ega;
+
+  	s = sys_segctl(&vid_index, &vid_seg, &vid_off, vid_base, vid_size);
+
+  	vid_size >>= 1;		/* word count */
+  	vid_mask = vid_size - 1;
+
+  	/* Size of the screen (number of displayed characters.) */
+  	scr_size = scr_lines * scr_width;
+
+  	/* There can be as many consoles as video memory allows. */
+  	nr_cons = vid_size / scr_size;
+  	if (nr_cons > NR_CONS) nr_cons = NR_CONS;
+  	if (nr_cons > 1) wrap = 0;
+  	page_size = vid_size / nr_cons;
+  }
+
+  cons->c_start = line * page_size;
+  cons->c_limit = cons->c_start + page_size;
+  cons->c_cur = cons->c_org = cons->c_start;
+  cons->c_attr = cons->c_blank = BLANK_COLOR;
+
+  if (line != 0) {
+        /* Clear the non-console vtys. */
+  	blank_color = BLANK_COLOR;
+	mem_vid_copy(BLANK_MEM, cons->c_start, scr_size);
+  } else {
+	int i, n;
+	/* Set the cursor of the console vty at the bottom. c_cur
+	 * is updated automatically later.
+	 */
+	scroll_screen(cons, SCROLL_UP);
+	cons->c_row = scr_lines - 1;
+	cons->c_column = 0;
+  }
+  select_console(0);
+  cons_ioctl(tp, 0);
+}
+
+/*===========================================================================*
+ *				kputc					     *
+ *===========================================================================*/
+PUBLIC void kputc(c)
+int c;
+{
+/* Accumulate a single character for a kernel message. Send a notification
+ * the to output driver if an END_OF_KMESS is encountered. 
+ */
+#if 0
+  ser_putc(c);
+  return;
+#endif
+
+  if (panicing)
+	cons_putk(c);
+  if (c != 0) {
+      kmess.km_buf[kmess.km_next] = c;	/* put normal char in buffer */
+      if (kmess.km_size < KMESS_BUF_SIZE)
+          kmess.km_size += 1;		
+      kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
+  } else {
+      notify(LOG_PROC_NR);
+  }
+}
+
+/*===========================================================================*
+ *				do_new_kmess				     *
+ *===========================================================================*/
+PUBLIC void do_new_kmess(m)
+message *m;
+{
+/* Notification for a new kernel message. */
+  struct kmessages kmess;			/* kmessages structure */
+  static int prev_next = 0;			/* previous next seen */
+  int size, next;
+  int bytes;
+  int r;
+
+  /* Try to get a fresh copy of the buffer with kernel messages. */
+#if DEAD_CODE	
+  /* During shutdown, the reply is garbled because new notifications arrive
+   * while the system task makes a copy of the kernel messages buffer.
+   * Hence, don't check the return value. 
+   */
+  if ((r=sys_getkmessages(&kmess)) != OK) {
+  	printf("TTY: couldn't get copy of kmessages: %d, 0x%x\n", r,r);
+  	return;
+  }
+#endif
+  sys_getkmessages(&kmess);
+
+  /* Print only the new part. Determine how many new bytes there are with 
+   * help of the current and previous 'next' index. Note that the kernel
+   * buffer is circular. This works fine if less then KMESS_BUF_SIZE bytes
+   * is new data; else we miss % KMESS_BUF_SIZE here.  
+   * Check for size being positive, the buffer might as well be emptied!
+   */
+  if (kmess.km_size > 0) {
+      bytes = ((kmess.km_next + KMESS_BUF_SIZE) - prev_next) % KMESS_BUF_SIZE;
+      r=prev_next;				/* start at previous old */ 
+      while (bytes > 0) {			
+          cons_putk( kmess.km_buf[(r%KMESS_BUF_SIZE)] );
+          bytes --;
+          r ++;
+      }
+      cons_putk(0);			/* terminate to flush output */
+  }
+
+  /* Almost done, store 'next' so that we can determine what part of the
+   * kernel messages buffer to print next time a notification arrives.
+   */
+  prev_next = kmess.km_next;
+}
+
+/*===========================================================================*
+ *				do_diagnostics				     *
+ *===========================================================================*/
+PUBLIC void do_diagnostics(m_ptr)
+message *m_ptr;			/* pointer to request message */
+{
+/* Print a string for a server. */
+  char c;
+  vir_bytes src;
+  int count;
+  int result = OK;
+  int proc_nr = m_ptr->DIAG_ENDPT;
+  if (proc_nr == SELF) proc_nr = m_ptr->m_source;
+
+  src = (vir_bytes) m_ptr->DIAG_PRINT_BUF;
+  for (count = m_ptr->DIAG_BUF_COUNT; count > 0; count--) {
+	if (sys_vircopy(proc_nr, D, src++, SELF, D, (vir_bytes) &c, 1) != OK) {
+		result = EFAULT;
+		break;
+	}
+	cons_putk(c);
+  }
+  cons_putk(0);			/* always terminate, even with EFAULT */
+  m_ptr->m_type = result;
+  send(m_ptr->m_source, m_ptr);
+}
+
+/*===========================================================================*
+ *				do_get_kmess				     *
+ *===========================================================================*/
+PUBLIC void do_get_kmess(m_ptr)
+message *m_ptr;			/* pointer to request message */
+{
+/* Provide the log device with debug output */
+  vir_bytes dst;
+  int r;
+
+  dst = (vir_bytes) m_ptr->GETKM_PTR;
+  r= OK;
+  if (sys_vircopy(SELF, D, (vir_bytes)&kmess, m_ptr->m_source, D,
+	dst, sizeof(kmess)) != OK) {
+	r = EFAULT;
+  }
+  m_ptr->m_type = r;
+  send(m_ptr->m_source, m_ptr);
+}
+
+/*===========================================================================*
+ *				cons_putk				     *
+ *===========================================================================*/
+PRIVATE void cons_putk(c)
+int c;				/* character to print */
+{
+/* This procedure is used to print a character on the console.
+ */
+  if (c != 0) {
+	if (c == '\n') cons_putk('\r');
+	out_char(&cons_table[0], (int) c);
+  } else {
+	flush(&cons_table[0]);
+  }
+}
+
+/*===========================================================================*
+ *				toggle_scroll				     *
+ *===========================================================================*/
+PUBLIC void toggle_scroll()
+{
+/* Toggle between hardware and software scroll. */
+
+  cons_org0();
+  softscroll = !softscroll;
+  printf("%sware scrolling enabled.\n", softscroll ? "Soft" : "Hard");
+}
+
+/*===========================================================================*
+ *				cons_stop				     *
+ *===========================================================================*/
+PUBLIC void cons_stop()
+{
+/* Prepare for halt or reboot. */
+  cons_org0();
+  softscroll = 1;
+  select_console(0);
+  cons_table[0].c_attr = cons_table[0].c_blank = BLANK_COLOR;
+}
+
+/*===========================================================================*
+ *				cons_org0				     *
+ *===========================================================================*/
+PRIVATE void cons_org0()
+{
+/* Scroll video memory back to put the origin at 0. */
+  int cons_line;
+  console_t *cons;
+  unsigned n;
+
+  for (cons_line = 0; cons_line < nr_cons; cons_line++) {
+	cons = &cons_table[cons_line];
+	while (cons->c_org > cons->c_start) {
+		n = vid_size - scr_size;	/* amount of unused memory */
+		if (n > cons->c_org - cons->c_start)
+			n = cons->c_org - cons->c_start;
+		vid_vid_copy(cons->c_org, cons->c_org - n, scr_size);
+		cons->c_org -= n;
+	}
+	flush(cons);
+  }
+  select_console(ccurrent);
+}
+
+/*===========================================================================*
+ *				select_console				     *
+ *===========================================================================*/
+PUBLIC void select_console(int cons_line)
+{
+/* Set the current console to console number 'cons_line'. */
+
+  if (cons_line < 0 || cons_line >= nr_cons) return;
+  ccurrent = cons_line;
+  curcons = &cons_table[cons_line];
+  set_6845(VID_ORG, curcons->c_org);
+  set_6845(CURSOR, curcons->c_cur);
+}
+
+/*===========================================================================*
+ *				con_loadfont				     *
+ *===========================================================================*/
+PUBLIC int con_loadfont(m)
+message *m;
+{
+/* Load a font into the EGA or VGA adapter. */
+  int result;
+  static struct sequence seq1[7] = {
+	{ GA_SEQUENCER_INDEX, 0x00, 0x01 },
+	{ GA_SEQUENCER_INDEX, 0x02, 0x04 },
+	{ GA_SEQUENCER_INDEX, 0x04, 0x07 },
+	{ GA_SEQUENCER_INDEX, 0x00, 0x03 },
+	{ GA_GRAPHICS_INDEX, 0x04, 0x02 },
+	{ GA_GRAPHICS_INDEX, 0x05, 0x00 },
+	{ GA_GRAPHICS_INDEX, 0x06, 0x00 },
+  };
+  static struct sequence seq2[7] = {
+	{ GA_SEQUENCER_INDEX, 0x00, 0x01 },
+	{ GA_SEQUENCER_INDEX, 0x02, 0x03 },
+	{ GA_SEQUENCER_INDEX, 0x04, 0x03 },
+	{ GA_SEQUENCER_INDEX, 0x00, 0x03 },
+	{ GA_GRAPHICS_INDEX, 0x04, 0x00 },
+	{ GA_GRAPHICS_INDEX, 0x05, 0x10 },
+	{ GA_GRAPHICS_INDEX, 0x06,    0 },
+  };
+
+  seq2[6].value= color ? 0x0E : 0x0A;
+
+  if (!machine.vdu_ega) return(ENOTTY);
+  result = ga_program(seq1);	/* bring font memory into view */
+
+  result = sys_physcopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS, 
+  	NONE, PHYS_SEG, (phys_bytes) GA_VIDEO_ADDRESS, (phys_bytes)GA_FONT_SIZE);
+
+  result = ga_program(seq2);	/* restore */
+
+  return(result);
+}
+
+/*===========================================================================*
+ *				ga_program				     *
+ *===========================================================================*/
+PRIVATE int ga_program(seq)
+struct sequence *seq;
+{
+  pvb_pair_t char_out[14];
+  int i;
+  for (i=0; i<7; i++) {
+      pv_set(char_out[2*i], seq->index, seq->port);
+      pv_set(char_out[2*i+1], seq->index+1, seq->value);
+      seq++;
+  } 
+  return sys_voutb(char_out, 14);
+}
+
+/*===========================================================================*
+ *				cons_ioctl				     *
+ *===========================================================================*/
+PRIVATE int cons_ioctl(tp, try)
+tty_t *tp;
+int try;
+{
+/* Set the screen dimensions. */
+
+  tp->tty_winsize.ws_row= scr_lines;
+  tp->tty_winsize.ws_col= scr_width;
+  tp->tty_winsize.ws_xpixel= scr_width * 8;
+  tp->tty_winsize.ws_ypixel= scr_lines * font_lines;
+}
+
+#define COM1_BASE	0x3F8
+#define COM1_THR	(COM1_BASE + 0)
+#define		LSR_THRE	0x20
+#define COM1_LSR	(COM1_BASE + 5)
+
+PRIVATE void ser_putc(char c)
+{
+	unsigned long b;
+	int i;
+	int lsr, thr;
+
+	lsr= COM1_LSR;
+	thr= COM1_THR;
+	for (i= 0; i<100; i++)
+	{
+		sys_inb(lsr, &b);
+		if (b & LSR_THRE)
+			break;
+	}
+	sys_outb(thr, c);
+}
Index: /trunk/minix/drivers/tty/keyboard.c
===================================================================
--- /trunk/minix/drivers/tty/keyboard.c	(revision 9)
+++ /trunk/minix/drivers/tty/keyboard.c	(revision 9)
@@ -0,0 +1,1214 @@
+/* Keyboard driver for PC's and AT's.
+ *
+ * Changes: 
+ *   Jul 13, 2004   processes can observe function keys  (Jorrit N. Herder)
+ *   Jun 15, 2004   removed wreboot(), except panic dumps (Jorrit N. Herder)
+ *   Feb 04, 1994   loadable keymaps  (Marcus Hampel)
+ */
+
+#include "../drivers.h"
+#include <sys/ioctl.h>
+#include <sys/kbdio.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include <termios.h>
+#include <signal.h>
+#include <unistd.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/keymap.h>
+#include "tty.h"
+#include "keymaps/us-std.src"
+#include "../../kernel/const.h"
+#include "../../kernel/config.h"
+#include "../../kernel/type.h"
+#include "../../kernel/proc.h"
+
+int irq_hook_id = -1;
+int aux_irq_hook_id = -1;
+
+/* Standard and AT keyboard.  (PS/2 MCA implies AT throughout.) */
+#define KEYBD		0x60	/* I/O port for keyboard data */
+
+/* AT keyboard. */
+#define KB_COMMAND	0x64	/* I/O port for commands on AT */
+#define KB_STATUS	0x64	/* I/O port for status on AT */
+#define KB_ACK		0xFA	/* keyboard ack response */
+#define KB_AUX_BYTE	0x20	/* Auxiliary Device Output Buffer Full */
+#define KB_OUT_FULL	0x01	/* status bit set when keypress char pending */
+#define KB_IN_FULL	0x02	/* status bit set when not ready to receive */
+#define KBC_RD_RAM_CCB	0x20	/* Read controller command byte */
+#define KBC_WR_RAM_CCB	0x60	/* Write controller command byte */
+#define KBC_DI_AUX	0xA7	/* Disable Auxiliary Device */
+#define KBC_EN_AUX	0xA8	/* Enable Auxiliary Device */
+#define KBC_DI_KBD	0xAD	/* Disable Keybard Interface */
+#define KBC_EN_KBD	0xAE	/* Enable Keybard Interface */
+#define KBC_WRITE_AUX	0xD4	/* Write to Auxiliary Device */
+#define LED_CODE	0xED	/* command to keyboard to set LEDs */
+#define MAX_KB_ACK_RETRIES 0x1000	/* max #times to wait for kb ack */
+#define MAX_KB_BUSY_RETRIES 0x1000	/* max #times to loop while kb busy */
+#define KBIT		0x80	/* bit used to ack characters to keyboard */
+
+#define KBC_IN_DELAY	7	/* wait 7 microseconds when polling */
+
+/* Miscellaneous. */
+#define ESC_SCAN	0x01	/* reboot key when panicking */
+#define SLASH_SCAN	0x35	/* to recognize numeric slash */
+#define RSHIFT_SCAN	0x36	/* to distinguish left and right shift */
+#define HOME_SCAN	0x47	/* first key on the numeric keypad */
+#define INS_SCAN	0x52	/* INS for use in CTRL-ALT-INS reboot */
+#define DEL_SCAN	0x53	/* DEL for use in CTRL-ALT-DEL reboot */
+
+#define KBD_BUFSZ	1024	/* Buffer size for raw scan codes */
+#define KBD_OUT_BUFSZ	16	/* Output buffer to sending data to the
+				 * keyboard.
+				 */
+
+#define MICROS_TO_TICKS(m)  (((m)*HZ/1000000)+1)
+
+#define CONSOLE		   0	/* line number for console */
+#define KB_IN_BYTES	  32	/* size of keyboard input buffer */
+PRIVATE char ibuf[KB_IN_BYTES];	/* input buffer */
+PRIVATE char *ihead = ibuf;	/* next free spot in input buffer */
+PRIVATE char *itail = ibuf;	/* scan code to return to TTY */
+PRIVATE int icount;		/* # codes in buffer */
+
+PRIVATE int esc;		/* escape scan code detected? */
+PRIVATE int alt_l;		/* left alt key state */
+PRIVATE int alt_r;		/* right alt key state */
+PRIVATE int alt;		/* either alt key */
+PRIVATE int ctrl_l;		/* left control key state */
+PRIVATE int ctrl_r;		/* right control key state */
+PRIVATE int ctrl;		/* either control key */
+PRIVATE int shift_l;		/* left shift key state */
+PRIVATE int shift_r;		/* right shift key state */
+PRIVATE int shift;		/* either shift key */
+PRIVATE int num_down;		/* num lock key depressed */
+PRIVATE int caps_down;		/* caps lock key depressed */
+PRIVATE int scroll_down;	/* scroll lock key depressed */
+PRIVATE int locks[NR_CONS];	/* per console lock keys state */
+
+/* Lock key active bits.  Chosen to be equal to the keyboard LED bits. */
+#define SCROLL_LOCK	0x01
+#define NUM_LOCK	0x02
+#define CAPS_LOCK	0x04
+
+PRIVATE char numpad_map[] =
+		{'H', 'Y', 'A', 'B', 'D', 'C', 'V', 'U', 'G', 'S', 'T', '@'};
+
+/* Variables and definition for observed function keys. */
+typedef struct observer { int proc_nr; int events; } obs_t;
+PRIVATE obs_t  fkey_obs[12];	/* observers for F1-F12 */
+PRIVATE obs_t sfkey_obs[12];	/* observers for SHIFT F1-F12 */
+
+PRIVATE struct kbd
+{
+	int minor;
+	int nr_open;
+	char buf[KBD_BUFSZ];
+	int offset;
+	int avail;
+	int req_size;
+	int req_proc;
+	vir_bytes req_addr;
+	int incaller;
+	int select_ops;
+	int select_proc;
+} kbd, kbdaux;
+
+/* Data that is to be sent to the keyboard. Each byte is ACKed by the
+ * keyboard.
+ */
+PRIVATE struct kbd_outack
+{
+	unsigned char buf[KBD_OUT_BUFSZ];
+	int offset;
+	int avail;
+	int expect_ack;
+} kbdout;
+
+PRIVATE int kbd_watchdog_set= 0;
+PRIVATE int kbd_alive= 1;
+PRIVATE timer_t tmr_kbd_wd;
+
+FORWARD _PROTOTYPE( void handle_req, (struct kbd *kbdp, message *m)	);
+FORWARD _PROTOTYPE( int handle_status, (struct kbd *kbdp, message *m)	);
+FORWARD _PROTOTYPE( void kbc_cmd0, (int cmd)				);
+FORWARD _PROTOTYPE( void kbc_cmd1, (int cmd, int data)			);
+FORWARD _PROTOTYPE( int kbc_read, (void)				);
+FORWARD _PROTOTYPE( void kbd_send, (void)				);
+FORWARD _PROTOTYPE( int kb_ack, (void) 					);
+FORWARD _PROTOTYPE( int kb_wait, (void)				 	);
+FORWARD _PROTOTYPE( int func_key, (int scode) 				);
+FORWARD _PROTOTYPE( int scan_keyboard, (unsigned char *bp, int *isauxp)	);
+FORWARD _PROTOTYPE( unsigned make_break, (int scode) 			);
+FORWARD _PROTOTYPE( void set_leds, (void) 				);
+FORWARD _PROTOTYPE( void show_key_mappings, (void) 			);
+FORWARD _PROTOTYPE( int kb_read, (struct tty *tp, int try) 		);
+FORWARD _PROTOTYPE( unsigned map_key, (int scode) 			);
+FORWARD _PROTOTYPE( void micro_delay, (unsigned long usecs)		);
+FORWARD _PROTOTYPE( void kbd_watchdog, (timer_t *tmrp)			);
+
+/*===========================================================================*
+ *				do_kbd					     *
+ *===========================================================================*/
+PUBLIC void do_kbd(message *m)
+{
+	handle_req(&kbd, m);
+}
+
+
+/*===========================================================================*
+ *				kbd_status				     *
+ *===========================================================================*/
+PUBLIC int kbd_status(message *m)
+{
+	int r;
+
+	r= handle_status(&kbd, m);
+	if (r)
+		return r;
+	return handle_status(&kbdaux, m);
+}
+
+
+/*===========================================================================*
+ *				do_kbdaux				     *
+ *===========================================================================*/
+PUBLIC void do_kbdaux(message *m)
+{
+	handle_req(&kbdaux, m);
+}
+
+
+/*===========================================================================*
+ *				handle_req				     *
+ *===========================================================================*/
+PRIVATE void handle_req(kbdp, m)
+struct kbd *kbdp;
+message *m;
+{
+	int i, n, r, ops, watch;
+	unsigned char c;
+
+	/* Execute the requested device driver function. */
+	r= EINVAL;	/* just in case */
+	switch (m->m_type) {
+	    case DEV_OPEN:
+		kbdp->nr_open++;
+		r= OK;
+		break;
+	    case DEV_CLOSE:
+		kbdp->nr_open--;
+		if (kbdp->nr_open < 0)
+		{
+			printf("TTY(kbd): open count is negative\n");
+			kbdp->nr_open= 0;
+		}
+		if (kbdp->nr_open == 0)
+			kbdp->avail= 0;
+		r= OK;
+		break;
+	    case DEV_READ:	 
+		if (kbdp->req_size)
+		{
+			/* We handle only request at a time */
+			r= EIO;
+			break;
+		}
+		if (kbdp->avail == 0)
+		{
+			/* Should record proc */
+			kbdp->req_size= m->COUNT;
+			kbdp->req_proc= m->IO_ENDPT;
+			kbdp->req_addr= (vir_bytes)m->ADDRESS;
+			kbdp->incaller= m->m_source;
+			r= SUSPEND;
+			break;
+		}
+
+		/* Handle read request */
+		n= kbdp->avail;
+		if (n > m->COUNT)
+			n= m->COUNT;
+		if (kbdp->offset + n > KBD_BUFSZ)
+			n= KBD_BUFSZ-kbdp->offset;
+		if (n <= 0)
+			panic("TTY", "do_kbd(READ): bad n", n);
+		r= sys_vircopy(SELF, D, (vir_bytes)&kbdp->buf[kbdp->offset], 
+			m->IO_ENDPT, D, (vir_bytes) m->ADDRESS, n);
+		if (r == OK)
+		{
+			kbdp->offset= (kbdp->offset+n) % KBD_BUFSZ;
+			kbdp->avail -= n;
+			r= n;
+		}
+
+		break;
+
+	    case DEV_WRITE:
+		if (kbdp != &kbdaux)
+		{
+			printf("write to keyboard not implemented\n");
+			r= EINVAL;
+			break;
+		}
+
+		/* Assume that output to AUX only happens during
+		 * initialization and we can afford to lose input. This should
+		 * be fixed at a later time.
+		 */
+		for (i= 0; i<m->COUNT; i++)
+		{
+			r= sys_vircopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS+i,
+				SELF, D, (vir_bytes)&c, 1);
+			if (r != OK)
+				break;
+			kbc_cmd1(KBC_WRITE_AUX, c);
+		}
+		r= i;
+		break;
+
+	    case CANCEL:
+		kbdp->req_size= 0;
+		r= OK;
+		break;
+	    case DEV_SELECT:
+		ops = m->IO_ENDPT & (SEL_RD|SEL_WR|SEL_ERR);
+		watch = (m->IO_ENDPT & SEL_NOTIFY) ? 1 : 0;
+		
+		r= 0;
+		if (kbdp->avail && (ops & SEL_RD))
+		{
+			r |= SEL_RD;
+			break;
+		}
+
+		if (ops && watch)
+		{
+			kbdp->select_ops |= ops;
+			kbdp->select_proc= m->m_source;
+		}
+		break;
+	    case DEV_IOCTL:
+		if (kbdp == &kbd && m->TTY_REQUEST == KIOCSLEDS)
+		{
+			kio_leds_t leds;
+			unsigned char b;
+
+			r= sys_vircopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS,
+				SELF, D, (vir_bytes)&leds, sizeof(leds));
+			if (r != OK)
+				break;
+			b= 0;
+			if (leds.kl_bits & KBD_LEDS_NUM) b |= NUM_LOCK;
+			if (leds.kl_bits & KBD_LEDS_CAPS) b |= CAPS_LOCK;
+			if (leds.kl_bits & KBD_LEDS_SCROLL) b |= SCROLL_LOCK;
+			if (kbdout.avail == 0)
+				kbdout.offset= 0;
+			if (kbdout.offset + kbdout.avail + 2 > KBD_OUT_BUFSZ)
+			{
+				/* Output buffer is full. Ignore this command.
+				 * Reset ACK flag.
+				 */
+				kbdout.expect_ack= 0;
+			}
+			else
+			{
+				kbdout.buf[kbdout.offset+kbdout.avail]=
+					LED_CODE;
+				kbdout.buf[kbdout.offset+kbdout.avail+1]= b;
+				kbdout.avail += 2;
+			 }
+			 if (!kbdout.expect_ack)
+				kbd_send();
+			 r= OK;
+			 break;
+		}
+		if (kbdp == &kbd && m->TTY_REQUEST == KIOCBELL)
+		{
+			kio_bell_t bell;
+			clock_t ticks;
+
+			r= sys_vircopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS,
+				SELF, D, (vir_bytes)&bell, sizeof(bell));
+			if (r != OK)
+				break;
+
+			ticks= bell.kb_duration.tv_usec * HZ / 1000000;
+			ticks += bell.kb_duration.tv_sec * HZ;
+			if (!ticks)
+				ticks++;
+			beep_x(bell.kb_pitch, ticks);
+
+			r= OK;
+			break;
+		}
+		r= ENOTTY;
+		break;
+
+	    default:		
+		printf("Warning, TTY(kbd) got unexpected request %d from %d\n",
+			m->m_type, m->m_source);
+		r= EINVAL;
+	}
+	tty_reply(TASK_REPLY, m->m_source, m->IO_ENDPT, r);
+}
+
+
+/*===========================================================================*
+ *				handle_status				     *
+ *===========================================================================*/
+PRIVATE int handle_status(kbdp, m)
+struct kbd *kbdp;
+message *m;
+{
+	int n, r;
+
+	if (kbdp->avail && kbdp->req_size && m->m_source == kbdp->incaller)
+	{
+		/* Handle read request */
+		n= kbdp->avail;
+		if (n > kbdp->req_size)
+			n= kbdp->req_size;
+		if (kbdp->offset + n > KBD_BUFSZ)
+			n= KBD_BUFSZ-kbdp->offset;
+		if (n <= 0)
+			panic("TTY", "kbd_status: bad n", n);
+		kbdp->req_size= 0;
+		r= sys_vircopy(SELF, D, (vir_bytes)&kbdp->buf[kbdp->offset], 
+			kbdp->req_proc, D, kbdp->req_addr, n);
+		if (r == OK)
+		{
+			kbdp->offset= (kbdp->offset+n) % KBD_BUFSZ;
+			kbdp->avail -= n;
+			r= n;
+		}
+
+		m->m_type = DEV_REVIVE;
+  		m->REP_ENDPT= kbdp->req_proc;
+  		m->REP_STATUS= r;
+		return 1;
+	}
+	if (kbdp->avail && (kbdp->select_ops & SEL_RD) &&
+		m->m_source == kbdp->select_proc)
+	{
+		m->m_type = DEV_IO_READY;
+		m->DEV_MINOR = kbdp->minor;
+		m->DEV_SEL_OPS = SEL_RD;
+
+		kbdp->select_ops &= ~SEL_RD;
+		return 1;
+	}
+
+	return 0;
+}
+
+
+/*===========================================================================*
+ *				map_key0				     *
+ *===========================================================================*/
+/* Map a scan code to an ASCII code ignoring modifiers. */
+#define map_key0(scode)	 \
+	((unsigned) keymap[(scode) * MAP_COLS])
+
+/*===========================================================================*
+ *				map_key					     *
+ *===========================================================================*/
+PRIVATE unsigned map_key(scode)
+int scode;
+{
+/* Map a scan code to an ASCII code. */
+
+  int caps, column, lk;
+  u16_t *keyrow;
+
+  if (scode == SLASH_SCAN && esc) return '/';	/* don't map numeric slash */
+
+  keyrow = &keymap[scode * MAP_COLS];
+
+  caps = shift;
+  lk = locks[ccurrent];
+  if ((lk & NUM_LOCK) && HOME_SCAN <= scode && scode <= DEL_SCAN) caps = !caps;
+  if ((lk & CAPS_LOCK) && (keyrow[0] & HASCAPS)) caps = !caps;
+
+  if (alt) {
+	column = 2;
+	if (ctrl || alt_r) column = 3;	/* Ctrl + Alt == AltGr */
+	if (caps) column = 4;
+  } else {
+	column = 0;
+	if (caps) column = 1;
+	if (ctrl) column = 5;
+  }
+  return keyrow[column] & ~HASCAPS;
+}
+
+/*===========================================================================*
+ *				kbd_interrupt				     *
+ *===========================================================================*/
+PUBLIC void kbd_interrupt(m_ptr)
+message *m_ptr;
+{
+/* A keyboard interrupt has occurred.  Process it. */
+  int o, isaux;
+  unsigned char scode;
+  struct kbd *kbdp;
+  static timer_t timer;		/* timer must be static! */
+
+  /* Fetch the character from the keyboard hardware and acknowledge it. */
+  if (!scan_keyboard(&scode, &isaux))
+	return;
+
+  if (isaux)
+	kbdp= &kbdaux;
+  else if (kbd.nr_open && !panicing)
+	kbdp= &kbd;
+  else
+	kbdp= NULL;
+
+  if (kbdp)
+  {
+	/* raw scan codes or aux data */
+	if (kbdp->avail >= KBD_BUFSZ)
+	{
+		printf("kbd_interrupt: %s buffer is full\n",
+			isaux ? "kbdaux" : "keyboard");
+		return;	/* Buffer is full */
+	}
+	 o= (kbdp->offset + kbdp->avail) % KBD_BUFSZ;
+	 kbdp->buf[o]= scode;
+	 kbdp->avail++;
+	 if (kbdp->req_size)
+		notify(kbdp->incaller);
+	 if (kbdp->select_ops & SEL_RD)
+		notify(kbdp->select_proc);
+	 return;
+  }
+
+  /* Store the scancode in memory so the task can get at it later. */
+  if (icount < KB_IN_BYTES) {
+	*ihead++ = scode;
+	if (ihead == ibuf + KB_IN_BYTES) ihead = ibuf;
+	icount++;
+	tty_table[ccurrent].tty_events = 1;
+	if (tty_table[ccurrent].tty_select_ops & SEL_RD) {
+		select_retry(&tty_table[ccurrent]);
+	}
+  }
+}
+
+/*===========================================================================*
+ *				kb_read					     *
+ *===========================================================================*/
+PRIVATE int kb_read(tp, try)
+tty_t *tp;
+int try;
+{
+/* Process characters from the circular keyboard buffer. */
+  char buf[3];
+  int scode;
+  unsigned ch;
+
+  tp = &tty_table[ccurrent];		/* always use the current console */
+
+  if (try) {
+  	if (icount > 0) return 1;
+  	return 0;
+  }
+
+  while (icount > 0) {
+	scode = *itail++;			/* take one key scan code */
+	if (itail == ibuf + KB_IN_BYTES) itail = ibuf;
+	icount--;
+
+	/* Function keys are being used for debug dumps. */
+	if (func_key(scode)) continue;
+
+	/* Perform make/break processing. */
+	ch = make_break(scode);
+
+	if (ch <= 0xFF) {
+		/* A normal character. */
+		buf[0] = ch;
+		(void) in_process(tp, buf, 1);
+	} else
+	if (HOME <= ch && ch <= INSRT) {
+		/* An ASCII escape sequence generated by the numeric pad. */
+		buf[0] = ESC;
+		buf[1] = '[';
+		buf[2] = numpad_map[ch - HOME];
+		(void) in_process(tp, buf, 3);
+	} else
+	if (ch == ALEFT) {
+		/* Choose lower numbered console as current console. */
+		select_console(ccurrent - 1);
+		set_leds();
+	} else
+	if (ch == ARIGHT) {
+		/* Choose higher numbered console as current console. */
+		select_console(ccurrent + 1);
+		set_leds();
+	} else
+	if (AF1 <= ch && ch <= AF12) {
+		/* Alt-F1 is console, Alt-F2 is ttyc1, etc. */
+		select_console(ch - AF1);
+		set_leds();
+	} else
+	if (CF1 <= ch && ch <= CF12) {
+	    switch(ch) {
+  		case CF1: show_key_mappings(); break; 
+  		case CF3: toggle_scroll(); break; /* hardware <-> software */	
+  		case CF7: sigchar(&tty_table[CONSOLE], SIGQUIT); break;
+  		case CF8: sigchar(&tty_table[CONSOLE], SIGINT); break;
+  		case CF9: sigchar(&tty_table[CONSOLE], SIGKILL); break;
+  	    }
+	}
+  }
+
+  return 1;
+}
+
+/*===========================================================================*
+ *				kbd_send				     *
+ *===========================================================================*/
+PRIVATE void kbd_send()
+{
+	unsigned long sb;
+	int r;
+	clock_t now;
+
+	if (!kbdout.avail)
+		return;
+	if (kbdout.expect_ack)
+		return;
+
+	sys_inb(KB_STATUS, &sb);
+	if (sb & (KB_OUT_FULL|KB_IN_FULL))
+	{
+		printf("not sending 1: sb = 0x%x\n", sb);
+		return;
+	}
+	micro_delay(KBC_IN_DELAY);
+	sys_inb(KB_STATUS, &sb);
+	if (sb & (KB_OUT_FULL|KB_IN_FULL))
+	{
+		printf("not sending 2: sb = 0x%x\n", sb);
+		return;
+	}
+
+	/* Okay, buffer is really empty */
+#if 0
+	printf("sending byte 0x%x to keyboard\n", kbdout.buf[kbdout.offset]);
+#endif
+	sys_outb(KEYBD, kbdout.buf[kbdout.offset]);
+	kbdout.offset++;
+	kbdout.avail--;
+	kbdout.expect_ack= 1;
+
+	kbd_alive= 1;
+	if (kbd_watchdog_set)
+	{
+		/* Add a timer to the timers list. Possibly reschedule the
+		 * alarm.
+		 */
+		if ((r= getuptime(&now)) != OK)
+			panic("TTY","Keyboard couldn't get clock's uptime.", r);
+		tmrs_settimer(&tty_timers, &tmr_kbd_wd, now+HZ, kbd_watchdog,
+			NULL);
+		if (tty_timers->tmr_exp_time != tty_next_timeout) {
+			tty_next_timeout = tty_timers->tmr_exp_time;
+			if ((r= sys_setalarm(tty_next_timeout, 1)) != OK)
+				panic("TTY","Keyboard couldn't set alarm.", r);
+		}
+		kbd_watchdog_set= 1;
+	 }
+}
+
+/*===========================================================================*
+ *				make_break				     *
+ *===========================================================================*/
+PRIVATE unsigned make_break(scode)
+int scode;			/* scan code of key just struck or released */
+{
+/* This routine can handle keyboards that interrupt only on key depression,
+ * as well as keyboards that interrupt on key depression and key release.
+ * For efficiency, the interrupt routine filters out most key releases.
+ */
+  int ch, make, escape;
+  static int CAD_count = 0;
+
+  /* Check for CTRL-ALT-DEL, and if found, halt the computer. This would
+   * be better done in keyboard() in case TTY is hung, except control and
+   * alt are set in the high level code.
+   */
+  if (ctrl && alt && (scode == DEL_SCAN || scode == INS_SCAN))
+  {
+	if (++CAD_count == 3) sys_abort(RBT_HALT);
+	sys_kill(INIT_PROC_NR, SIGABRT);
+	return -1;
+  }
+
+  /* High-order bit set on key release. */
+  make = (scode & KEY_RELEASE) == 0;		/* true if pressed */
+
+  ch = map_key(scode &= ASCII_MASK);		/* map to ASCII */
+
+  escape = esc;		/* Key is escaped?  (true if added since the XT) */
+  esc = 0;
+
+  switch (ch) {
+  	case CTRL:		/* Left or right control key */
+		*(escape ? &ctrl_r : &ctrl_l) = make;
+		ctrl = ctrl_l | ctrl_r;
+		break;
+  	case SHIFT:		/* Left or right shift key */
+		*(scode == RSHIFT_SCAN ? &shift_r : &shift_l) = make;
+		shift = shift_l | shift_r;
+		break;
+  	case ALT:		/* Left or right alt key */
+		*(escape ? &alt_r : &alt_l) = make;
+		alt = alt_l | alt_r;
+		break;
+  	case CALOCK:		/* Caps lock - toggle on 0 -> 1 transition */
+		if (caps_down < make) {
+			locks[ccurrent] ^= CAPS_LOCK;
+			set_leds();
+		}
+		caps_down = make;
+		break;
+  	case NLOCK:		/* Num lock */
+		if (num_down < make) {
+			locks[ccurrent] ^= NUM_LOCK;
+			set_leds();
+		}
+		num_down = make;
+		break;
+  	case SLOCK:		/* Scroll lock */
+		if (scroll_down < make) {
+			locks[ccurrent] ^= SCROLL_LOCK;
+			set_leds();
+		}
+		scroll_down = make;
+		break;
+  	case EXTKEY:		/* Escape keycode */
+		esc = 1;		/* Next key is escaped */
+		return(-1);
+  	default:		/* A normal key */
+		if (make) return(ch);
+  }
+
+  /* Key release, or a shift type key. */
+  return(-1);
+}
+
+/*===========================================================================*
+ *				set_leds				     *
+ *===========================================================================*/
+PRIVATE void set_leds()
+{
+/* Set the LEDs on the caps, num, and scroll lock keys */
+  int s;
+  if (! machine.pc_at) return;	/* PC/XT doesn't have LEDs */
+
+  kb_wait();			/* wait for buffer empty  */
+  if ((s=sys_outb(KEYBD, LED_CODE)) != OK)
+      printf("Warning, sys_outb couldn't prepare for LED values: %d\n", s);
+   				/* prepare keyboard to accept LED values */
+  kb_ack();			/* wait for ack response  */
+
+  kb_wait();			/* wait for buffer empty  */
+  if ((s=sys_outb(KEYBD, locks[ccurrent])) != OK)
+      printf("Warning, sys_outb couldn't give LED values: %d\n", s);
+				/* give keyboard LED values */
+  kb_ack();			/* wait for ack response  */
+}
+
+/*===========================================================================*
+ *				kbc_cmd0				     *
+ *===========================================================================*/
+PRIVATE void kbc_cmd0(cmd)
+int cmd;
+{
+	kb_wait();
+	sys_outb(KB_COMMAND, cmd);
+}
+
+/*===========================================================================*
+ *				kbc_cmd1				     *
+ *===========================================================================*/
+PRIVATE void kbc_cmd1(cmd, data)
+int cmd;
+int data;
+{
+	kb_wait();
+	sys_outb(KB_COMMAND, cmd);
+	kb_wait();
+	sys_outb(KEYBD, data);
+}
+
+
+/*===========================================================================*
+*                              kbc_read                                     *
+*===========================================================================*/
+PRIVATE int kbc_read()
+{
+	int i;
+	unsigned long byte, st;
+#if 0
+	struct micro_state ms;
+#endif
+
+#if DEBUG
+	printf("in kbc_read\n");
+#endif
+
+	/* Wait at most 1 second for a byte from the keyboard or
+	* the kbd controller, return -1 on a timeout.
+	*/
+	for (i= 0; i<1000; i++)
+ #if 0
+	micro_start(&ms);
+	do
+#endif
+	{
+		sys_inb(KB_STATUS, &st);
+		if (st & KB_OUT_FULL)
+		{
+			micro_delay(KBC_IN_DELAY);
+			sys_inb(KEYBD, &byte);
+			if (st & KB_AUX_BYTE)
+			{
+#if DEBUG
+				printf(
+		"keyboard`kbc_read: ignoring byte (0x%x) from aux device.\n",
+					byte);
+#endif
+				continue;
+			}
+#if DEBUG
+			printf("keyboard`kbc_read: returning byte 0x%x\n",
+				byte);
+#endif
+			return byte;
+		}
+	}
+#if 0
+	while (micro_elapsed(&ms) < 1000000);
+#endif
+	panic("TTY", "kbc_read failed to complete", NO_NUM);
+}
+
+
+
+/*===========================================================================*
+ *				kb_wait					     *
+ *===========================================================================*/
+PRIVATE int kb_wait()
+{
+/* Wait until the controller is ready; return zero if this times out. */
+
+  int retries;
+  unsigned long status, temp;
+  int s, isaux;
+  unsigned char byte;
+
+  retries = MAX_KB_BUSY_RETRIES + 1;	/* wait until not busy */
+  do {
+      s = sys_inb(KB_STATUS, &status);
+      if (status & KB_OUT_FULL) {
+	  if (scan_keyboard(&byte, &isaux))
+	  {
+#if 0
+		  printf("ignoring %sbyte in kb_wait\n", isaux ? "AUX " : "");
+#endif
+	  }
+      }
+      if (! (status & (KB_IN_FULL|KB_OUT_FULL)) )
+          break;			/* wait until ready */
+  } while (--retries != 0);		/* continue unless timeout */ 
+  return(retries);		/* zero on timeout, positive if ready */
+}
+
+/*===========================================================================*
+ *				kb_ack					     *
+ *===========================================================================*/
+PRIVATE int kb_ack()
+{
+/* Wait until kbd acknowledges last command; return zero if this times out. */
+
+  int retries, s;
+  unsigned long u8val;
+
+
+  retries = MAX_KB_ACK_RETRIES + 1;
+  do {
+      s = sys_inb(KEYBD, &u8val);
+      if (u8val == KB_ACK)	
+          break;		/* wait for ack */
+  } while(--retries != 0);	/* continue unless timeout */
+
+  return(retries);		/* nonzero if ack received */
+}
+
+/*===========================================================================*
+ *				kb_init					     *
+ *===========================================================================*/
+PUBLIC void kb_init(tp)
+tty_t *tp;
+{
+/* Initialize the keyboard driver. */
+
+  tp->tty_devread = kb_read;	/* input function */
+}
+
+/*===========================================================================*
+ *				kb_init_once				     *
+ *===========================================================================*/
+PUBLIC void kb_init_once(void)
+{
+  int i;
+  u8_t ccb;
+
+  set_leds();			/* turn off numlock led */
+  scan_keyboard(NULL, NULL);	/* discard leftover keystroke */
+
+      /* Clear the function key observers array. Also see func_key(). */
+      for (i=0; i<12; i++) {
+          fkey_obs[i].proc_nr = NONE;	/* F1-F12 observers */
+          fkey_obs[i].events = 0;	/* F1-F12 observers */
+          sfkey_obs[i].proc_nr = NONE;	/* Shift F1-F12 observers */
+          sfkey_obs[i].events = 0;	/* Shift F1-F12 observers */
+      }
+
+      kbd.minor= KBD_MINOR;
+      kbdaux.minor= KBDAUX_MINOR;
+
+      /* Set interrupt handler and enable keyboard IRQ. */
+      irq_hook_id = KEYBOARD_IRQ;	/* id to be returned on interrupt */
+      if ((i=sys_irqsetpolicy(KEYBOARD_IRQ, IRQ_REENABLE, &irq_hook_id)) != OK)
+          panic("TTY",  "Couldn't set keyboard IRQ policy", i);
+      if ((i=sys_irqenable(&irq_hook_id)) != OK)
+          panic("TTY", "Couldn't enable keyboard IRQs", i);
+      kbd_irq_set |= (1 << KEYBOARD_IRQ);
+
+      /* Set AUX interrupt handler and enable AUX IRQ. */
+      aux_irq_hook_id = KBD_AUX_IRQ;	/* id to be returned on interrupt */
+      if ((i=sys_irqsetpolicy(KBD_AUX_IRQ, IRQ_REENABLE,
+		&aux_irq_hook_id)) != OK)
+          panic("TTY",  "Couldn't set AUX IRQ policy", i);
+      if ((i=sys_irqenable(&aux_irq_hook_id)) != OK)
+          panic("TTY", "Couldn't enable AUX IRQs", i);
+      kbd_irq_set |= (1 << KBD_AUX_IRQ);
+
+	/* Disable the keyboard and aux */
+	kbc_cmd0(KBC_DI_KBD);
+	kbc_cmd0(KBC_DI_AUX);
+
+	/* Get the current configuration byte */
+	kbc_cmd0(KBC_RD_RAM_CCB);
+	ccb= kbc_read();
+
+	/* Enable both interrupts. */
+	kbc_cmd1(KBC_WR_RAM_CCB, ccb | 3);
+
+	/* Re-enable the keyboard device. */
+	kbc_cmd0(KBC_EN_KBD);
+
+	/* Enable the aux device. */
+	kbc_cmd0(KBC_EN_AUX);
+}
+
+/*===========================================================================*
+ *				kbd_loadmap				     *
+ *===========================================================================*/
+PUBLIC int kbd_loadmap(m)
+message *m;
+{
+/* Load a new keymap. */
+  int result;
+  result = sys_vircopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS,
+  	SELF, D, (vir_bytes) keymap, 
+  	(vir_bytes) sizeof(keymap));
+  return(result);
+}
+
+/*===========================================================================*
+ *				do_fkey_ctl				     *
+ *===========================================================================*/
+PUBLIC void do_fkey_ctl(m_ptr)
+message *m_ptr;			/* pointer to the request message */
+{
+/* This procedure allows processes to register a function key to receive
+ * notifications if it is pressed. At most one binding per key can exist.
+ */
+  int i; 
+  int result;
+
+  switch (m_ptr->FKEY_REQUEST) {	/* see what we must do */
+  case FKEY_MAP:			/* request for new mapping */
+      result = OK;			/* assume everything will be ok*/
+      for (i=0; i < 12; i++) {		/* check F1-F12 keys */
+          if (bit_isset(m_ptr->FKEY_FKEYS, i+1) ) {
+#if DEAD_CODE
+	/* Currently, we don't check if the slot is in use, so that IS
+	 * can recover after a crash by overtaking its existing mappings.
+	 * In future, a better solution will be implemented.
+	 */
+              if (fkey_obs[i].proc_nr == NONE) { 
+#endif
+    	          fkey_obs[i].proc_nr = m_ptr->m_source;
+    	          fkey_obs[i].events = 0;
+    	          bit_unset(m_ptr->FKEY_FKEYS, i+1);
+#if DEAD_CODE
+    	      } else {
+    	          printf("WARNING, fkey_map failed F%d\n", i+1);
+    	          result = EBUSY;	/* report failure, but try rest */
+    	      }
+#endif
+    	  }
+      }
+      for (i=0; i < 12; i++) {		/* check Shift+F1-F12 keys */
+          if (bit_isset(m_ptr->FKEY_SFKEYS, i+1) ) {
+#if DEAD_CODE
+              if (sfkey_obs[i].proc_nr == NONE) { 
+#endif
+    	          sfkey_obs[i].proc_nr = m_ptr->m_source;
+    	          sfkey_obs[i].events = 0;
+    	          bit_unset(m_ptr->FKEY_SFKEYS, i+1);
+#if DEAD_CODE
+    	      } else {
+    	          printf("WARNING, fkey_map failed Shift F%d\n", i+1);
+    	          result = EBUSY;	/* report failure but try rest */
+    	      }
+#endif
+    	  }
+      }
+      break;
+  case FKEY_UNMAP:
+      result = OK;			/* assume everything will be ok*/
+      for (i=0; i < 12; i++) {		/* check F1-F12 keys */
+          if (bit_isset(m_ptr->FKEY_FKEYS, i+1) ) {
+              if (fkey_obs[i].proc_nr == m_ptr->m_source) { 
+    	          fkey_obs[i].proc_nr = NONE;
+    	          fkey_obs[i].events = 0;
+    	          bit_unset(m_ptr->FKEY_FKEYS, i+1);
+    	      } else {
+    	          result = EPERM;	/* report failure, but try rest */
+    	      }
+    	  }
+      }
+      for (i=0; i < 12; i++) {		/* check Shift+F1-F12 keys */
+          if (bit_isset(m_ptr->FKEY_SFKEYS, i+1) ) {
+              if (sfkey_obs[i].proc_nr == m_ptr->m_source) { 
+    	          sfkey_obs[i].proc_nr = NONE;
+    	          sfkey_obs[i].events = 0;
+    	          bit_unset(m_ptr->FKEY_SFKEYS, i+1);
+    	      } else {
+    	          result = EPERM;	/* report failure, but try rest */
+    	      }
+    	  }
+      }
+      break;
+  case FKEY_EVENTS:
+      m_ptr->FKEY_FKEYS = m_ptr->FKEY_SFKEYS = 0;
+      for (i=0; i < 12; i++) {		/* check (Shift+) F1-F12 keys */
+          if (fkey_obs[i].proc_nr == m_ptr->m_source) {
+              if (fkey_obs[i].events) { 
+                  bit_set(m_ptr->FKEY_FKEYS, i+1);
+                  fkey_obs[i].events = 0;
+              }
+          }
+          if (sfkey_obs[i].proc_nr == m_ptr->m_source) {
+              if (sfkey_obs[i].events) { 
+                  bit_set(m_ptr->FKEY_SFKEYS, i+1);
+                  sfkey_obs[i].events = 0;
+              }
+          }
+      }
+      break;
+  default:
+          result =  EINVAL;		/* key cannot be observed */
+  }
+
+  /* Almost done, return result to caller. */
+  m_ptr->m_type = result;
+  send(m_ptr->m_source, m_ptr);
+}
+
+/*===========================================================================*
+ *				func_key				     *
+ *===========================================================================*/
+PRIVATE int func_key(scode)
+int scode;			/* scan code for a function key */
+{
+/* This procedure traps function keys for debugging purposes. Observers of 
+ * function keys are kept in a global array. If a subject (a key) is pressed
+ * the observer is notified of the event. Initialization of the arrays is done
+ * in kb_init, where NONE is set to indicate there is no interest in the key.
+ * Returns FALSE on a key release or if the key is not observable.
+ */
+  message m;
+  int key;
+  int proc_nr;
+  int i,s;
+
+  /* Ignore key releases. If this is a key press, get full key code. */
+  if (scode & KEY_RELEASE) return(FALSE);	/* key release */
+  key = map_key(scode);		 		/* include modifiers */
+
+  /* Key pressed, now see if there is an observer for the pressed key.
+   *	       F1-F12	observers are in fkey_obs array. 
+   *	SHIFT  F1-F12	observers are in sfkey_req array. 
+   *	CTRL   F1-F12	reserved (see kb_read)
+   *	ALT    F1-F12	reserved (see kb_read)
+   * Other combinations are not in use. Note that Alt+Shift+F1-F12 is yet
+   * defined in <minix/keymap.h>, and thus is easy for future extensions.
+   */
+  if (F1 <= key && key <= F12) {		/* F1-F12 */
+      proc_nr = fkey_obs[key - F1].proc_nr;	
+      fkey_obs[key - F1].events ++ ;	
+  } else if (SF1 <= key && key <= SF12) {	/* Shift F2-F12 */
+      proc_nr = sfkey_obs[key - SF1].proc_nr;	
+      sfkey_obs[key - SF1].events ++;	
+  }
+  else {
+      return(FALSE);				/* not observable */
+  }
+
+  /* See if an observer is registered and send it a message. */
+  if (proc_nr != NONE) { 
+      m.NOTIFY_TYPE = FKEY_PRESSED;
+      notify(proc_nr);
+  }
+  return(TRUE);
+}
+
+/*===========================================================================*
+ *				show_key_mappings			     *
+ *===========================================================================*/
+PRIVATE void show_key_mappings()
+{
+    int i,s;
+    struct proc proc;
+
+    printf("\n");
+    printf("System information.   Known function key mappings to request debug dumps:\n");
+    printf("-------------------------------------------------------------------------\n");
+    for (i=0; i<12; i++) {
+
+      printf(" %sF%d: ", i+1<10? " ":"", i+1);
+      if (fkey_obs[i].proc_nr != NONE) {
+          if ((s=sys_getproc(&proc, fkey_obs[i].proc_nr))!=OK)
+              printf("sys_getproc: %d\n", s);
+          printf("%-14.14s", proc.p_name);
+      } else {
+          printf("%-14.14s", "<none>");
+      }
+
+      printf("    %sShift-F%d: ", i+1<10? " ":"", i+1);
+      if (sfkey_obs[i].proc_nr != NONE) {
+          if ((s=sys_getproc(&proc, sfkey_obs[i].proc_nr))!=OK)
+              printf("sys_getproc: %d\n", s);
+          printf("%-14.14s", proc.p_name);
+      } else {
+          printf("%-14.14s", "<none>");
+      }
+      printf("\n");
+    }
+    printf("\n");
+    printf("Press one of the registered function keys to trigger a debug dump.\n");
+    printf("\n");
+}
+
+/*===========================================================================*
+ *				scan_keyboard				     *
+ *===========================================================================*/
+PRIVATE int scan_keyboard(bp, isauxp)
+unsigned char *bp;
+int *isauxp;
+{
+#if 0	/* Is this old XT code? It doesn't match the PS/2 hardware */
+/* Fetch the character from the keyboard hardware and acknowledge it. */
+  pvb_pair_t byte_in[2], byte_out[2];
+  
+  byte_in[0].port = KEYBD;	/* get the scan code for the key struck */
+  byte_in[1].port = PORT_B;	/* strobe the keyboard to ack the char */
+  sys_vinb(byte_in, 2);		/* request actual input */
+
+  pv_set(byte_out[0], PORT_B, byte_in[1].value | KBIT); /* strobe bit high */
+  pv_set(byte_out[1], PORT_B, byte_in[1].value);	/* then strobe low */
+  sys_voutb(byte_out, 2);	/* request actual output */
+
+  return(byte_in[0].value);		/* return scan code */
+#else
+  unsigned long b, sb;
+
+  sys_inb(KB_STATUS, &sb);
+  if (!(sb & KB_OUT_FULL))
+  {
+	if (kbdout.avail && !kbdout.expect_ack)
+		kbd_send();
+	return 0;
+  }
+  sys_inb(KEYBD, &b);
+#if 0
+  printf("got byte 0x%x from %s\n", b, (sb & KB_AUX_BYTE) ? "AUX" : "keyboard");
+#endif
+  if (!(sb & KB_AUX_BYTE) && b == KB_ACK && kbdout.expect_ack)
+  {
+#if 1
+	printf("got ACK from keyboard\n");
+#endif
+	kbdout.expect_ack= 0;
+	micro_delay(KBC_IN_DELAY);
+	kbd_send();
+	return 0;
+  }
+  if (bp)
+  	*bp= b;
+  if (isauxp)
+  	*isauxp= !!(sb & KB_AUX_BYTE);
+  if (kbdout.avail && !kbdout.expect_ack)
+  {
+	micro_delay(KBC_IN_DELAY);
+	kbd_send();
+  }
+  return 1;
+#endif
+}
+
+static void micro_delay(unsigned long usecs)
+{
+	tickdelay(MICROS_TO_TICKS(usecs));
+}
+
+/*===========================================================================*
+ *				kbd_watchdog 				     *
+ *===========================================================================*/
+PRIVATE void kbd_watchdog(tmrp)
+timer_t *tmrp;
+{
+	int r;
+	clock_t now;
+
+	kbd_watchdog_set= 0;
+	if (!kbdout.avail)
+		return;	/* Watchdog is no longer needed */
+	if (!kbd_alive)
+	{
+		printf("kbd_watchdog: should reset keyboard\n");
+	}
+	kbd_alive= 0;
+
+	if ((r= getuptime(&now)) != OK)
+		panic("TTY","Keyboard couldn't get clock's uptime.", r);
+	tmrs_settimer(&tty_timers, &tmr_kbd_wd, now+HZ, kbd_watchdog,
+		NULL);
+	if (tty_timers->tmr_exp_time != tty_next_timeout) {
+		tty_next_timeout = tty_timers->tmr_exp_time;
+		if ((r= sys_setalarm(tty_next_timeout, 1)) != OK)
+			panic("TTY","Keyboard couldn't set alarm.", r);
+	}
+	kbd_watchdog_set= 1;
+}
Index: /trunk/minix/drivers/tty/keymaps/Makefile
===================================================================
--- /trunk/minix/drivers/tty/keymaps/Makefile	(revision 9)
+++ /trunk/minix/drivers/tty/keymaps/Makefile	(revision 9)
@@ -0,0 +1,86 @@
+# Generate binary keymaps.
+
+LK =	/usr/lib/keymaps
+
+.SUFFIXES:	.src .map
+
+.src.map:
+	$(CC) -DKEYSRC=\"$<\" genmap.c
+	./a.out > $@
+	@rm -f a.out
+
+all:	\
+	dvorak.map \
+	french.map \
+	german.map \
+	italian.map \
+	japanese.map \
+	latin-america.map \
+	olivetti.map \
+	polish.map \
+	scandinavian.map \
+	spanish.map \
+	uk.map \
+	us-std.map \
+	us-swap.map \
+
+install:	\
+	$(LK) \
+	$(LK)/dvorak.map \
+	$(LK)/french.map \
+	$(LK)/german.map \
+	$(LK)/italian.map \
+	$(LK)/japanese.map \
+	$(LK)/latin-america.map \
+	$(LK)/olivetti.map \
+	$(LK)/polish.map \
+	$(LK)/scandinavian.map \
+	$(LK)/spanish.map \
+	$(LK)/uk.map \
+	$(LK)/us-std.map \
+	$(LK)/us-swap.map \
+
+clean:
+	rm -f a.out *.map
+
+$(LK):
+	install -d $@
+
+$(LK)/dvorak.map:	dvorak.map
+	install -c $? $@
+
+$(LK)/french.map:	french.map
+	install -c $? $@
+
+$(LK)/german.map:	german.map
+	install -c $? $@
+
+$(LK)/italian.map:	italian.map
+	install -c $? $@
+
+$(LK)/japanese.map:	japanese.map
+	install -c $? $@
+
+$(LK)/latin-america.map:	latin-america.map
+	install -c $? $@
+
+$(LK)/olivetti.map:	olivetti.map
+	install -c $? $@
+
+$(LK)/polish.map:	polish.map
+	install -c $? $@
+
+$(LK)/scandinavian.map:	scandinavian.map
+	install -c $? $@
+
+$(LK)/spanish.map:	spanish.map
+	install -c $? $@
+
+$(LK)/uk.map:	uk.map
+	install -c $? $@
+
+$(LK)/us-std.map:	us-std.map
+	install -c $? $@
+
+$(LK)/us-swap.map:	us-swap.map
+	install -c $? $@
Index: /trunk/minix/drivers/tty/keymaps/dvorak.src
===================================================================
--- /trunk/minix/drivers/tty/keymaps/dvorak.src	(revision 9)
+++ /trunk/minix/drivers/tty/keymaps/dvorak.src	(revision 9)
@@ -0,0 +1,139 @@
+
+/* Keymap for Dvorak keyboard. 
+ * Contributed by: Ulrich Hobelmann <u.hobelmann@web.de>
+ */
+
+u16_t keymap[NR_SCAN_CODES * MAP_COLS] = {
+
+/* scan-code		!Shift	Shift	Alt1	Alt2	Alt+Sh	Ctrl	*/
+/* ==================================================================== */
+/* 00 - none	*/	0,	0,	0,	0,	0,	0,	
+/* 01 - ESC	*/	C('['),	C('['),	CA('['),CA('['),CA('['),C('['),
+/* 02 - '1'	*/	'1',	'!',	A('1'),	A('1'),	A('!'),	C('A'),
+/* 03 - '2'	*/	'2',	'@',	A('2'),	A('2'),	A('@'),	C('@'),
+/* 04 - '3'	*/	'3',	'#',	A('3'),	A('3'),	A('#'),	C('C'),
+/* 05 - '4'	*/	'4',	'$',	A('4'),	A('4'),	A('$'),	C('D'),
+/* 06 - '5'	*/	'5',	'%',	A('5'),	A('5'),	A('%'),	C('E'),
+/* 07 - '6'	*/	'6',	'^',	A('6'),	A('6'),	A('^'),	C('^'),
+/* 08 - '7'	*/	'7',	'&',	A('7'),	A('7'),	A('&'),	C('G'),
+/* 09 - '8'	*/	'8',	'*',	A('8'),	A('8'),	A('*'),	C('H'),
+/* 10 - '9'	*/	'9',	'(',	A('9'),	A('9'),	A('('),	C('I'),
+/* 11 - '0'	*/	'0',	')',	A('0'),	A('0'),	A(')'),	C('@'),
+/* 12 - '-'	*/	'[',	'{',	A('['),	A('['),	A('}'),	C(']'),
+/* 13 - '='	*/	']',	'}',	A(']'),	A(']'),	A('}'),	C(']'),
+/* 14 - BS	*/	C('H'),	C('H'),	CA('H'),CA('H'),CA('H'),0177,	
+/* 15 - TAB	*/	C('I'),	C('I'),	CA('I'),CA('I'),CA('I'),C('I'),
+/* 16 - 'q'	*/	'\'',	'"',	A('\''),A('\''),A('"'),	C('@'),
+/* 17 - 'w'	*/	',',	'<',	A(','),	A(','),	A('<'),	C('@'),
+/* 18 - 'e'	*/	'.',	'>',	A('.'),	A('.'),	A('>'),	C('@'),
+/* 19 - 'r'	*/	L('p'),	'P',	A('p'),	A('p'),	A('P'),	C('P'),
+/* 20 - 't'	*/	L('y'),	'Y',	A('y'),	A('y'),	A('Y'),	C('Y'),
+/* 21 - 'y'	*/	L('f'),	'F',	A('f'),	A('f'),	A('F'),	C('F'),
+/* 22 - 'u'	*/	L('g'),	'G',	A('g'),	A('g'),	A('G'),	C('G'),
+/* 23 - 'i'	*/	L('c'),	'C',	A('c'),	A('c'),	A('C'),	C('C'),
+/* 24 - 'o'	*/	L('r'),	'R',	A('r'),	A('r'),	A('R'),	C('R'),
+/* 25 - 'p'	*/	L('l'),	'L',	A('l'),	A('l'),	A('L'),	C('L'),
+/* 26 - '['	*/	'/',	'?',	A('/'),	A('/'),	A('?'),	C('@'),
+/* 27 - ']'	*/	'=',	'+',	A('='),	A('='),	A('+'),	C('@'),
+/* 28 - CR/LF	*/	C('M'),	C('M'),	CA('M'),CA('M'),CA('M'),C('J'),
+/* 29 - Ctrl	*/	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,
+/* 30 - 'a'	*/	L('a'),	'A',	A('a'),	A('a'),	A('A'),	C('A'),
+/* 31 - 's'	*/	L('o'),	'O',	A('o'),	A('o'),	A('O'),	C('O'),
+/* 32 - 'd'	*/	L('e'),	'E',	A('e'),	A('e'),	A('E'),	C('E'),
+/* 33 - 'f'	*/	L('u'),	'U',	A('u'),	A('u'),	A('U'),	C('U'),
+/* 34 - 'g'	*/	L('i'),	'I',	A('i'),	A('i'),	A('I'),	C('I'),
+/* 35 - 'h'	*/	L('d'),	'D',	A('d'),	A('d'),	A('D'),	C('D'),
+/* 36 - 'j'	*/	L('h'),	'H',	A('h'),	A('h'),	A('H'),	C('H'),
+/* 37 - 'k'	*/	L('t'),	'T',	A('t'),	A('t'),	A('T'),	C('T'),
+/* 38 - 'l'	*/	L('n'),	'N',	A('n'),	A('n'),	A('N'),	C('N'),
+/* 39 - ';'	*/	L('s'),	'S',	A('s'),	A('s'),	A('S'),	C('S'),
+/* 40 - '\''	*/	'-',	'_',	A('-'),	A('-'),	A('_'),	C('_'),
+/* 41 - '`'	*/	'`',	'~',	A('`'),	A('`'),	A('~'),	C('@'),
+/* 42 - l. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 43 - '\\'	*/	'\\',	'|',	A('\\'),A('\\'),A('|'),	C('\\'),
+/* 44 - 'z'	*/	';',	':',	A(';'),	A(';'),	A(':'),	C('@'),
+/* 45 - 'x'	*/	L('q'),	'Q',	A('q'),	A('q'),	A('Q'),	C('Q'),
+/* 46 - 'c'	*/	L('j'),	'J',	A('j'),	A('j'),	A('J'),	C('J'),
+/* 47 - 'v'	*/	L('k'),	'K',	A('k'),	A('k'),	A('K'),	C('K'),
+/* 48 - 'b'	*/	L('x'),	'X',	A('x'),	A('x'),	A('X'),	C('X'),
+/* 49 - 'n'	*/	L('b'),	'B',	A('b'),	A('b'),	A('B'),	C('B'),
+/* 50 - 'm'	*/	L('m'),	'M',	A('m'),	A('m'),	A('M'),	C('M'),
+/* 51 - ','	*/	L('w'),	'W',	A('w'),	A('w'),	A('W'),	C('W'),
+/* 52 - '.'	*/	L('v'),	'V',	A('v'),	A('v'),	A('V'),	C('V'),
+/* 53 - '/'	*/	L('z'),	'Z',	A('z'),	A('z'),	A('Z'),	C('Z'),
+/* 54 - r. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 55 - '*'	*/	'*',	'*',	A('*'),	A('*'),	A('*'),	C('@'),
+/* 56 - ALT	*/	ALT,	ALT,	ALT,	ALT,	ALT,	ALT,
+/* 57 - ' '	*/	' ',	' ',	A(' '),	A(' '),	A(' '),	C('@'),
+/* 58 - CapsLck	*/	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,
+/* 59 - F1	*/	F1,	SF1,	AF1,	AF1,	ASF1,	CF1,
+/* 60 - F2	*/	F2,	SF2,	AF2,	AF2,	ASF2,	CF2,
+/* 61 - F3	*/	F3,	SF3,	AF3,	AF3,	ASF3,	CF3,
+/* 62 - F4	*/	F4,	SF4,	AF4,	AF4,	ASF4,	CF4,
+/* 63 - F5	*/	F5,	SF5,	AF5,	AF5,	ASF5,	CF5,
+/* 64 - F6	*/	F6,	SF6,	AF6,	AF6,	ASF6,	CF6,
+/* 65 - F7	*/	F7,	SF7,	AF7,	AF7,	ASF7,	CF7,
+/* 66 - F8	*/	F8,	SF8,	AF8,	AF8,	ASF8,	CF8,
+/* 67 - F9	*/	F9,	SF9,	AF9,	AF9,	ASF9,	CF9,
+/* 68 - F10	*/	F10,	SF10,	AF10,	AF10,	ASF10,	CF10,
+/* 69 - NumLock	*/	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,
+/* 70 - ScrLock */	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,
+/* 71 - Home	*/	HOME,	'7',	AHOME,	AHOME,	A('7'),	CHOME,	
+/* 72 - CurUp	*/	UP,	'8',	AUP,	AUP,	A('8'),	CUP,
+/* 73 - PgUp	*/	PGUP,	'9',	APGUP,	APGUP,	A('9'),	CPGUP,
+/* 74 - '-'	*/	NMIN,	'-',	ANMIN,	ANMIN,	A('-'),	CNMIN,
+/* 75 - Left	*/	LEFT,	'4',	ALEFT,	ALEFT,	A('4'),	CLEFT,
+/* 76 - MID	*/	MID,	'5',	AMID,	AMID,	A('5'),	CMID,
+/* 77 - Right	*/	RIGHT,	'6',	ARIGHT,	ARIGHT,	A('6'),	CRIGHT,
+/* 78 - '+'	*/	PLUS,	'+',	APLUS,	APLUS,	A('+'),	CPLUS,
+/* 79 - End	*/	END,	'1',	AEND,	AEND,	A('1'),	CEND,
+/* 80 - Down	*/	DOWN,	'2',	ADOWN,	ADOWN,	A('2'),	CDOWN,
+/* 81 - PgDown	*/	PGDN,	'3',	APGDN,	APGDN,	A('3'),	CPGDN,
+/* 82 - Insert	*/	INSRT,	'0',	AINSRT,	AINSRT,	A('0'),	CINSRT,
+/* 83 - Delete	*/	0177,	'.',	A(0177),A(0177),A('.'),	0177,
+/* 84 - Enter	*/	C('M'),	C('M'),	CA('M'),CA('M'),CA('M'),C('J'),
+/* 85 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 86 - ???	*/	'<',	'>',	A('<'),	A('|'),	A('>'),	C('@'),
+/* 87 - F11	*/	F11,	SF11,	AF11,	AF11,	ASF11,	CF11,
+/* 88 - F12	*/	F12,	SF12,	AF12,	AF12,	ASF12,	CF12,
+/* 89 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 90 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 91 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 92 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 93 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 94 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 95 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 96 - EXT_KEY	*/	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,
+/* 97 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 98 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 99 - ???	*/	0,	0,	0,	0,	0,	0,
+/*100 - ???	*/	0,	0,	0,	0,	0,	0,
+/*101 - ???	*/	0,	0,	0,	0,	0,	0,
+/*102 - ???	*/	0,	0,	0,	0,	0,	0,
+/*103 - ???	*/	0,	0,	0,	0,	0,	0,
+/*104 - ???	*/	0,	0,	0,	0,	0,	0,
+/*105 - ???	*/	0,	0,	0,	0,	0,	0,
+/*106 - ???	*/	0,	0,	0,	0,	0,	0,
+/*107 - ???	*/	0,	0,	0,	0,	0,	0,
+/*108 - ???	*/	0,	0,	0,	0,	0,	0,
+/*109 - ???	*/	0,	0,	0,	0,	0,	0,
+/*110 - ???	*/	0,	0,	0,	0,	0,	0,
+/*111 - ???	*/	0,	0,	0,	0,	0,	0,
+/*112 - ???	*/	0,	0,	0,	0,	0,	0,
+/*113 - ???	*/	0,	0,	0,	0,	0,	0,
+/*114 - ???	*/	0,	0,	0,	0,	0,	0,
+/*115 - ???	*/	0,	0,	0,	0,	0,	0,
+/*116 - ???	*/	0,	0,	0,	0,	0,	0,
+/*117 - ???	*/	0,	0,	0,	0,	0,	0,
+/*118 - ???	*/	0,	0,	0,	0,	0,	0,
+/*119 - ???	*/	0,	0,	0,	0,	0,	0,
+/*120 - ???	*/	0,	0,	0,	0,	0,	0,
+/*121 - ???	*/	0,	0,	0,	0,	0,	0,
+/*122 - ???	*/	0,	0,	0,	0,	0,	0,
+/*123 - ???	*/	0,	0,	0,	0,	0,	0,
+/*124 - ???	*/	0,	0,	0,	0,	0,	0,
+/*125 - ???	*/	0,	0,	0,	0,	0,	0,
+/*126 - ???	*/	0,	0,	0,	0,	0,	0,
+/*127 - ???	*/	0,	0,	0,	0,	0,	0
+};
+
Index: /trunk/minix/drivers/tty/keymaps/french.src
===================================================================
--- /trunk/minix/drivers/tty/keymaps/french.src	(revision 9)
+++ /trunk/minix/drivers/tty/keymaps/french.src	(revision 9)
@@ -0,0 +1,135 @@
+/* Keymap for the French keyboard. */
+
+u16_t keymap[NR_SCAN_CODES * MAP_COLS] = {
+
+/* scan-code		!Shift	Shift	Alt	AltGr	Alt+Sh	Ctrl	*/
+/* ==================================================================== */
+/* 00 - none	*/	0,	0,	0,	0,	0,	0,	
+/* 01 - ESC	*/	C('['),	C('['),	CA('['),C('['),	C('['),	C('['),
+/* 02 - '1'	*/	'&',	'1',	A('1'),	'&',	'1',	C('A'),
+/* 03 - '2'     */      0202,   '2',    A('2'), '~',    '2',    C('B'),
+/* 04 - '3'     */      '"',    '3',    A('3'), '#',    '3',    C('C'),
+/* 05 - '4'     */      '\'',   '4',    A('4'), '{',    '4',    C('D'),
+/* 06 - '5'     */      '(',    '5',    A('5'), '[',    '5',    C('E'),
+/* 07 - '6'     */      '-',    '6',    A('6'), '|',    '6',    C('F'),
+/* 08 - '7'     */      0212,   '7',    A('7'), '`',    '7',    C('G'),
+/* 09 - '8'     */      '_',    '8',    A('8'), '\\',   '8',    C('H'),
+/* 10 - '9'     */      0207,   '9',    A('9'), '^',    '9',    C('I'),
+/* 11 - '0'     */      0205,   '0',    A('0'), '@',    '0',    C('J'),
+/* 12 - '-'     */      ')',    0370,   A(')'), ']',    '-',    C('K'),
+/* 13 - '='     */      '=',    '+',    A('='), '}',    '=',    C('L'),
+/* 14 - BS	*/	C('H'),	C('H'),	CA('H'),C('H'),	C('H'),	0177,	
+/* 15 - TAB	*/	C('I'),	C('I'),	CA('I'),C('I'),	C('I'),	C('I'),
+/* 16 - 'q'	*/	L('a'),	'A',	A('a'),	'a',	'Q',	C('A'),
+/* 17 - 'w'	*/	L('z'),	'Z',	A('z'),	'z',	'W',	C('Z'),
+/* 18 - 'e'	*/	L('e'),	'E',	A('e'),	'e',	'E',	C('E'),
+/* 19 - 'r'	*/	L('r'),	'R',	A('r'),	'r',	'R',	C('R'),
+/* 20 - 't'	*/	L('t'),	'T',	A('t'),	't',	'T',	C('T'),
+/* 21 - 'y'	*/	L('y'),	'Y',	A('y'),	'y',	'Y',	C('Y'),
+/* 22 - 'u'	*/	L('u'),	'U',	A('u'),	'u',	'U',	C('U'),
+/* 23 - 'i'	*/	L('i'),	'I',	A('i'),	'i',	'I',	C('I'),
+/* 24 - 'o'	*/	L('o'),	'O',	A('o'),	'o',	'O',	C('O'),
+/* 25 - 'p'	*/	L('p'),	'P',	A('p'),	'p',	'P',	C('P'),
+/* 26 - '['     */      '^',    '"',    A('^'), '^',    '[',    C('^'),
+/* 27 - ']'     */      '$',    0234,   A('$'), '$',    ']',    C('$'),
+/* 28 - CR/LF	*/	C('M'),	C('M'),	CA('M'),C('M'),	C('M'),	C('J'),
+/* 29 - Ctrl	*/	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,
+/* 30 - 'a'	*/	L('q'),	'Q',	A('q'),	'q',	'A',	C('Q'),
+/* 31 - 's'	*/	L('s'),	'S',	A('s'),	's',	'S',	C('S'),
+/* 32 - 'd'	*/	L('d'),	'D',	A('d'),	'd',	'D',	C('D'),
+/* 33 - 'f'	*/	L('f'),	'F',	A('f'),	'f',	'F',	C('F'),
+/* 34 - 'g'	*/	L('g'),	'G',	A('g'),	'g',	'G',	C('G'),
+/* 35 - 'h'	*/	L('h'),	'H',	A('h'),	'h',	'H',	C('H'),
+/* 36 - 'j'	*/	L('j'),	'J',	A('j'),	'j',	'J',	C('J'),
+/* 37 - 'k'	*/	L('k'),	'K',	A('k'),	'k',	'K',	C('K'),
+/* 38 - 'l'	*/	L('l'),	'L',	A('l'),	'l',	'L',	C('L'),
+/* 39 - ';'	*/	L('m'),	'M',	A('m'),	'm',	'M',	C('M'),
+/* 40 - '\''    */      0227,   '%',    A('%'), 0227,   '\\',   C('G'),
+/* 41 - '`'     */      0375,   0375,   0375,   0375,   '`',    C('['),
+/* 42 - l. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 43 - '`'     */      '*',    0346,   A('*'), '*',    '`',    C('*'),
+/* 44 - 'z'	*/	L('w'),	'W',	A('w'),	'w',	'Z',	C('W'),
+/* 45 - 'x'	*/	L('x'),	'X',	A('x'),	'x',	'X',	C('X'),
+/* 46 - 'c'	*/	L('c'),	'C',	A('c'),	'c',	'C',	C('C'),
+/* 47 - 'v'	*/	L('v'),	'V',	A('v'),	'v',	'V',	C('V'),
+/* 48 - 'b'	*/	L('b'),	'B',	A('b'),	'b',	'B',	C('B'),
+/* 49 - 'n'	*/	L('n'),	'N',	A('n'),	'n',	'N',	C('N'),
+/* 50 - 'm'     */      ',',    '?',    A(','), ',',    'm',    C('@'),
+/* 51 - ','     */      ';',    '.',    A(';'), ';',    ',',    C('@'),
+/* 52 - '.'     */      ':',    '/',    A(':'), ':',    '.',    C('@'),
+/* 53 - '/'     */      '!', '$'/*025*/,A('!'), '!',    '/',    C('@'),
+/* 54 - r. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 55 - '*'	*/	'*',	'*',	A('*'),	'*',	'*',	C('@'),
+/* 56 - ALT	*/	ALT,	ALT,	ALT,	ALT,	ALT,	ALT,
+/* 57 - ' '	*/	' ',	' ',	A(' '),	' ',	' ',	C('@'),
+/* 58 - CapsLck	*/	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,
+/* 59 - F1	*/	F1,	SF1,	AF1,	AF1,	ASF1,	CF1,
+/* 60 - F2	*/	F2,	SF2,	AF2,	AF2,	ASF2,	CF2,
+/* 61 - F3	*/	F3,	SF3,	AF3,	AF3,	ASF3,	CF3,
+/* 62 - F4	*/	F4,	SF4,	AF4,	AF4,	ASF4,	CF4,
+/* 63 - F5	*/	F5,	SF5,	AF5,	AF5,	ASF5,	CF5,
+/* 64 - F6	*/	F6,	SF6,	AF6,	AF6,	ASF6,	CF6,
+/* 65 - F7	*/	F7,	SF7,	AF7,	AF7,	ASF7,	CF7,
+/* 66 - F8	*/	F8,	SF8,	AF8,	AF8,	ASF8,	CF8,
+/* 67 - F9	*/	F9,	SF9,	AF9,	AF9,	ASF9,	CF9,
+/* 68 - F10	*/	F10,	SF10,	AF10,	AF10,	ASF10,	CF10,
+/* 69 - NumLock	*/	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,
+/* 70 - ScrLock */	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,
+/* 71 - Home	*/	HOME,	'7',	AHOME,	AHOME,	'7',	CHOME,	
+/* 72 - CurUp	*/	UP,	'8',	AUP,	AUP,	'8',	CUP,
+/* 73 - PgUp	*/	PGUP,	'9',	APGUP,	APGUP,	'9',	CPGUP,
+/* 74 - '-'	*/	NMIN,	'-',	ANMIN,	ANMIN,	'-',	CNMIN,
+/* 75 - Left	*/	LEFT,	'4',	ALEFT,	ALEFT,	'4',	CLEFT,
+/* 76 - MID	*/	MID,	'5',	AMID,	AMID,	'5',	CMID,
+/* 77 - Right	*/	RIGHT,	'6',	ARIGHT,	ARIGHT,	'6',	CRIGHT,
+/* 78 - '+'	*/	PLUS,	'+',	APLUS,	APLUS,	'+',	CPLUS,
+/* 79 - End	*/	END,	'1',	AEND,	AEND,	'1',	CEND,
+/* 80 - Down	*/	DOWN,	'2',	ADOWN,	ADOWN,	'2',	CDOWN,
+/* 81 - PgDown	*/	PGDN,	'3',	APGDN,	APGDN,	'3',	CPGDN,
+/* 82 - Insert	*/	INSRT,	'0',	AINSRT,	AINSRT,	'0',	CINSRT,
+/* 83 - Delete	*/	0177,	'.',	A(0177),0177,	'.',	0177,
+/* 84 - Enter	*/	C('M'),	C('M'),	CA('M'),C('M'),	C('M'),	C('J'),
+/* 85 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 86 - ???	*/	'<',	'>',	A('<'),	'<',	'>',	C('@'),
+/* 87 - F11	*/	F11,	SF11,	AF11,	AF11,	ASF11,	CF11,
+/* 88 - F12	*/	F12,	SF12,	AF12,	AF12,	ASF12,	CF12,
+/* 89 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 90 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 91 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 92 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 93 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 94 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 95 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 96 - EXT_KEY	*/	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,
+/* 97 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 98 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 99 - ???	*/	0,	0,	0,	0,	0,	0,
+/*100 - ???	*/	0,	0,	0,	0,	0,	0,
+/*101 - ???	*/	0,	0,	0,	0,	0,	0,
+/*102 - ???	*/	0,	0,	0,	0,	0,	0,
+/*103 - ???	*/	0,	0,	0,	0,	0,	0,
+/*104 - ???	*/	0,	0,	0,	0,	0,	0,
+/*105 - ???	*/	0,	0,	0,	0,	0,	0,
+/*106 - ???	*/	0,	0,	0,	0,	0,	0,
+/*107 - ???	*/	0,	0,	0,	0,	0,	0,
+/*108 - ???	*/	0,	0,	0,	0,	0,	0,
+/*109 - ???	*/	0,	0,	0,	0,	0,	0,
+/*110 - ???	*/	0,	0,	0,	0,	0,	0,
+/*111 - ???	*/	0,	0,	0,	0,	0,	0,
+/*112 - ???	*/	0,	0,	0,	0,	0,	0,
+/*113 - ???	*/	0,	0,	0,	0,	0,	0,
+/*114 - ???	*/	0,	0,	0,	0,	0,	0,
+/*115 - ???	*/	0,	0,	0,	0,	0,	0,
+/*116 - ???	*/	0,	0,	0,	0,	0,	0,
+/*117 - ???	*/	0,	0,	0,	0,	0,	0,
+/*118 - ???	*/	0,	0,	0,	0,	0,	0,
+/*119 - ???	*/	0,	0,	0,	0,	0,	0,
+/*120 - ???	*/	0,	0,	0,	0,	0,	0,
+/*121 - ???	*/	0,	0,	0,	0,	0,	0,
+/*122 - ???	*/	0,	0,	0,	0,	0,	0,
+/*123 - ???	*/	0,	0,	0,	0,	0,	0,
+/*124 - ???	*/	0,	0,	0,	0,	0,	0,
+/*125 - ???	*/	0,	0,	0,	0,	0,	0,
+/*126 - ???	*/	0,	0,	0,	0,	0,	0,
+/*127 - ???	*/	0,	0,	0,	0,	0,	0
+};
Index: /trunk/minix/drivers/tty/keymaps/genmap.c
===================================================================
--- /trunk/minix/drivers/tty/keymaps/genmap.c	(revision 9)
+++ /trunk/minix/drivers/tty/keymaps/genmap.c	(revision 9)
@@ -0,0 +1,58 @@
+/*	genmap - output binary keymap			Author: Marcus Hampel
+ */
+#include <sys/types.h>
+#include <minix/keymap.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include KEYSRC
+
+u8_t comprmap[4 + NR_SCAN_CODES * MAP_COLS * 9/8 * 2 + 1];
+
+void tell(const char *s)
+{
+  write(2, s, strlen(s));
+}
+
+int main(void)
+{
+  u8_t *cm, *fb;
+  u16_t *km;
+  int n;
+
+  /* Compress the keymap. */
+  memcpy(comprmap, KEY_MAGIC, 4);
+  cm = comprmap + 4;
+  n = 8;
+  for (km = keymap; km < keymap + NR_SCAN_CODES * MAP_COLS; km++) {
+	if (n == 8) {
+		/* Allocate a new flag byte. */
+		fb = cm;
+		*cm++ = 0;
+		n= 0;
+	}
+	*cm++ = (*km & 0x00FF);		/* Low byte. */
+	if (*km & 0xFF00) {
+		*cm++ = (*km >> 8);	/* High byte only when set. */
+		*fb |= (1 << n);	/* Set a flag if so. */
+	}
+	n++;
+  }
+
+  /* Don't store trailing zeros. */
+  while (cm > comprmap && cm[-1] == 0) cm--;
+
+  /* Emit the compressed keymap. */
+  if (write(1, comprmap, cm - comprmap) < 0) {
+	int err = errno;
+
+	tell("genmap: ");
+	tell(strerror(err));
+	tell("\n");
+	exit(1);
+  }
+  exit(0);
+}
Index: /trunk/minix/drivers/tty/keymaps/german.src
===================================================================
--- /trunk/minix/drivers/tty/keymaps/german.src	(revision 9)
+++ /trunk/minix/drivers/tty/keymaps/german.src	(revision 9)
@@ -0,0 +1,135 @@
+/* Keymap for German MF-2 keyboard. */
+
+u16_t keymap[NR_SCAN_CODES * MAP_COLS] = {
+
+/* scan-code		unsh	Shift	Alt	AltGr	Alt+Sh	Strg	*/
+/* ==================================================================== */
+/* 00 - none	*/	0,	0,	0,	0,	0,	0,	
+/* 01 - ESC	*/	C('['),	C('['),	CA('['),C('['),	C('['),	C('['),
+/* 02 - '1'	*/	'1',	'!',	A('1'),	'1',	'!',	C('A'),
+/* 03 - '2'	*/	'2',	'"',	A('2'),	0375,	'@',	C('@'),
+/* 04 - '3'	*/	'3',	025,	A('3'),	0374,	'#',	C('C'),
+/* 05 - '4'	*/	'4',	'$',	A('4'),	'4',	'$',	C('D'),
+/* 06 - '5'	*/	'5',	'%',	A('5'),	'5',	'%',	C('E'),
+/* 07 - '6'	*/	'6',	'&',	A('6'),	'6',	'^',	C('^'),
+/* 08 - '7'	*/	'7',	'/',	A('7'),	'{',	'&',	C('G'),
+/* 09 - '8'	*/	'8',	'(',	A('8'),	'[',	'*',	C('H'),
+/* 10 - '9'	*/	'9',	')',	A('9'),	']',	'(',	C('I'),
+/* 11 - '0'	*/	'0',	'=',	A('0'),	'}',	')',	C('@'),
+/* 12 - '-'	*/	0341,	'?',	0341,	'\\',	'_',	C('_'),
+/* 13 - '='	*/	'\'',	'`',	A('\''),'=',	'+',	C('@'),
+/* 14 - BS	*/	C('H'),	C('H'),	CA('H'),C('H'),	C('H'),	0177,	
+/* 15 - TAB	*/	C('I'),	C('I'),	CA('I'),C('I'),	C('I'),	C('I'),
+/* 16 - 'q'	*/	L('q'),	'Q',	A('q'),	'@',	'Q',	C('Q'),
+/* 17 - 'w'	*/	L('w'),	'W',	A('w'),	'w',	'W',	C('W'),
+/* 18 - 'e'	*/	L('e'),	'E',	A('e'),	'e',	'E',	C('E'),
+/* 19 - 'r'	*/	L('r'),	'R',	A('r'),	'r',	'R',	C('R'),
+/* 20 - 't'	*/	L('t'),	'T',	A('t'),	't',	'T',	C('T'),
+/* 21 - 'y'	*/	L('z'),	'Z',	A('z'),	'z',	'Z',	C('Z'),
+/* 22 - 'u'	*/	L('u'),	'U',	A('u'),	'u',	'U',	C('U'),
+/* 23 - 'i'	*/	L('i'),	'I',	A('i'),	'i',	'I',	C('I'),
+/* 24 - 'o'	*/	L('o'),	'O',	A('o'),	'o',	'O',	C('O'),
+/* 25 - 'p'	*/	L('p'),	'P',	A('p'),	'p',	'P',	C('P'),
+/* 26 - '['	*/	L(0201),0232,	0201,	'[',	'{',	C('['),
+/* 27 - ']'	*/	'+',	'*',	A('+'),	'~',	']',	C(']'),
+/* 28 - CR/LF	*/	C('M'),	C('M'),	CA('M'),C('M'),	C('M'),	C('J'),
+/* 29 - Strg;-) */	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,
+/* 30 - 'a'	*/	L('a'),	'A',	A('a'),	'a',	'A',	C('A'),
+/* 31 - 's'	*/	L('s'),	'S',	A('s'),	's',	'S',	C('S'),
+/* 32 - 'd'	*/	L('d'),	'D',	A('d'),	'd',	'D',	C('D'),
+/* 33 - 'f'	*/	L('f'),	'F',	A('f'),	'f',	'F',	C('F'),
+/* 34 - 'g'	*/	L('g'),	'G',	A('g'),	'g',	'G',	C('G'),
+/* 35 - 'h'	*/	L('h'),	'H',	A('h'),	'h',	'H',	C('H'),
+/* 36 - 'j'	*/	L('j'),	'J',	A('j'),	'j',	'J',	C('J'),
+/* 37 - 'k'	*/	L('k'),	'K',	A('k'),	'k',	'K',	C('K'),
+/* 38 - 'l'	*/	L('l'),	'L',	A('l'),	'l',	'L',	C('L'),
+/* 39 - ';'	*/	L(0224),0231,	0224,	';',	':',	C('@'),
+/* 40 - '\''	*/	L(0204),0216,	0204,	'\'',	'"',	C('@'),
+/* 41 - '`'	*/	'^',	0370,	A('^'),	'`',	'~',	C('^'),
+/* 42 - SHIFT	*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 43 - '\\'	*/	'#',	'\'',	A('#'),	'\\',	'|',	C('\\'),
+/* 44 - 'z'	*/	L('y'),	'Y',	A('y'),	'y',	'Y',	C('Y'),
+/* 45 - 'x'	*/	L('x'),	'X',	A('x'),	'x',	'X',	C('X'),
+/* 46 - 'c'	*/	L('c'),	'C',	A('c'),	'c',	'C',	C('C'),
+/* 47 - 'v'	*/	L('v'),	'V',	A('v'),	'v',	'V',	C('V'),
+/* 48 - 'b'	*/	L('b'),	'B',	A('b'),	'b',	'B',	C('B'),
+/* 49 - 'n'	*/	L('n'),	'N',	A('n'),	'n',	'N',	C('N'),
+/* 50 - 'm'	*/	L('m'),	'M',	A('m'),	0346,	'M',	C('M'),
+/* 51 - ','	*/	',',	';',	A(','),	',',	'<',	C('@'),
+/* 52 - '.'	*/	'.',	':',	A('.'),	'.',	'>',	C('@'),
+/* 53 - '/'	*/	'-',	'_',	A('-'),	'/',	'?',	C('_'),
+/* 54 - SHIFT	*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 55 - '*'	*/	'*',	'*',	A('*'),	'*',	'*',	C('@'),
+/* 56 - ALT	*/	ALT,	ALT,	ALT,	ALT,	ALT,	ALT,
+/* 57 - ' '	*/	' ',	' ',	A(' '),	' ',	' ',	C('@'),
+/* 58 - CapsLck	*/	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,
+/* 59 - F1	*/	F1,	SF1,	AF1,	AF1,	ASF1,	CF1,
+/* 60 - F2	*/	F2,	SF2,	AF2,	AF2,	ASF2,	CF2,
+/* 61 - F3	*/	F3,	SF3,	AF3,	AF3,	ASF3,	CF3,
+/* 62 - F4	*/	F4,	SF4,	AF4,	AF4,	ASF4,	CF4,
+/* 63 - F5	*/	F5,	SF5,	AF5,	AF5,	ASF5,	CF5,
+/* 64 - F6	*/	F6,	SF6,	AF6,	AF6,	ASF6,	CF6,
+/* 65 - F7	*/	F7,	SF7,	AF7,	AF7,	ASF7,	CF7,
+/* 66 - F8	*/	F8,	SF8,	AF8,	AF8,	ASF8,	CF8,
+/* 67 - F9	*/	F9,	SF9,	AF9,	AF9,	ASF9,	CF9,
+/* 68 - F10	*/	F10,	SF10,	AF10,	AF10,	ASF10,	CF10,
+/* 69 - NumLock	*/	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,
+/* 70 - ScrLock */	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,
+/* 71 - Home	*/	HOME,	'7',	AHOME,	AHOME,	'7',	CHOME,	
+/* 72 - CurUp	*/	UP,	'8',	AUP,	AUP,	'8',	CUP,
+/* 73 - PgUp	*/	PGUP,	'9',	APGUP,	APGUP,	'9',	CPGUP,
+/* 74 - '-'	*/	NMIN,	'-',	ANMIN,	ANMIN,	'-',	CNMIN,
+/* 75 - Left	*/	LEFT,	'4',	ALEFT,	ALEFT,	'4',	CLEFT,
+/* 76 - MID	*/	MID,	'5',	AMID,	AMID,	'5',	CMID,
+/* 77 - Right	*/	RIGHT,	'6',	ARIGHT,	ARIGHT,	'6',	CRIGHT,
+/* 78 - '+'	*/	PLUS,	'+',	APLUS,	APLUS,	'+',	CPLUS,
+/* 79 - End	*/	END,	'1',	AEND,	AEND,	'1',	CEND,
+/* 80 - Down	*/	DOWN,	'2',	ADOWN,	ADOWN,	'2',	CDOWN,
+/* 81 - PgDown	*/	PGDN,	'3',	APGDN,	APGDN,	'3',	CPGDN,
+/* 82 - Insert	*/	INSRT,	'0',	AINSRT,	AINSRT,	'0',	CINSRT,
+/* 83 - Delete	*/	0177,	'.',	A(0177),0177,	'.',	0177,
+/* 84 - Enter	*/	C('M'),	C('M'),	CA('M'),C('M'),	C('M'),	C('J'),
+/* 85 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 86 - ???	*/	'<',	'>',	A('<'),	'|',	'>',	C('@'),
+/* 87 - F11	*/	F11,	SF11,	AF11,	AF11,	ASF11,	CF11,
+/* 88 - F12	*/	F12,	SF12,	AF12,	AF12,	ASF12,	CF12,
+/* 89 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 90 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 91 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 92 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 93 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 94 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 95 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 96 - EXT_KEY	*/	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,
+/* 97 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 98 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 99 - ???	*/	0,	0,	0,	0,	0,	0,
+/*100 - ???	*/	0,	0,	0,	0,	0,	0,
+/*101 - ???	*/	0,	0,	0,	0,	0,	0,
+/*102 - ???	*/	0,	0,	0,	0,	0,	0,
+/*103 - ???	*/	0,	0,	0,	0,	0,	0,
+/*104 - ???	*/	0,	0,	0,	0,	0,	0,
+/*105 - ???	*/	0,	0,	0,	0,	0,	0,
+/*106 - ???	*/	0,	0,	0,	0,	0,	0,
+/*107 - ???	*/	0,	0,	0,	0,	0,	0,
+/*108 - ???	*/	0,	0,	0,	0,	0,	0,
+/*109 - ???	*/	0,	0,	0,	0,	0,	0,
+/*110 - ???	*/	0,	0,	0,	0,	0,	0,
+/*111 - ???	*/	0,	0,	0,	0,	0,	0,
+/*112 - ???	*/	0,	0,	0,	0,	0,	0,
+/*113 - ???	*/	0,	0,	0,	0,	0,	0,
+/*114 - ???	*/	0,	0,	0,	0,	0,	0,
+/*115 - ???	*/	0,	0,	0,	0,	0,	0,
+/*116 - ???	*/	0,	0,	0,	0,	0,	0,
+/*117 - ???	*/	0,	0,	0,	0,	0,	0,
+/*118 - ???	*/	0,	0,	0,	0,	0,	0,
+/*119 - ???	*/	0,	0,	0,	0,	0,	0,
+/*120 - ???	*/	0,	0,	0,	0,	0,	0,
+/*121 - ???	*/	0,	0,	0,	0,	0,	0,
+/*122 - ???	*/	0,	0,	0,	0,	0,	0,
+/*123 - ???	*/	0,	0,	0,	0,	0,	0,
+/*124 - ???	*/	0,	0,	0,	0,	0,	0,
+/*125 - ???	*/	0,	0,	0,	0,	0,	0,
+/*126 - ???	*/	0,	0,	0,	0,	0,	0,
+/*127 - ???	*/	0,	0,	0,	0,	0,	0
+};
Index: /trunk/minix/drivers/tty/keymaps/italian.src
===================================================================
--- /trunk/minix/drivers/tty/keymaps/italian.src	(revision 9)
+++ /trunk/minix/drivers/tty/keymaps/italian.src	(revision 9)
@@ -0,0 +1,137 @@
+/* Keymap for Italian keyboard. */
+/* Modified by Ernesto Del Prete in October 1997 */
+/* ernesto@cclix1.polito.it or s84508@cclix1.polito.it */
+
+u16_t keymap[NR_SCAN_CODES * MAP_COLS] = {
+
+/* scan-code		!Shift	Shift	Alt	AltGr	Alt+Sh	Ctrl	*/
+/* ==================================================================== */
+/* 00 - none	*/	0,	0,	0,	0,	0,	0,	
+/* 01 - ESC	*/	C('['),	C('['),	CA('['),C('['),	C('['),	C('['),
+/* 02 - '1'	*/	'1',	'!',	A('1'),	'1',	'!',	C('A'),
+/* 03 - '2'	*/	'2',	'"',	A('2'),	'2',	'@',	C('@'),
+/* 04 - '3'	*/	'3',	0234,	A('3'),	'3',	0234,	C('C'),
+/* 05 - '4'	*/	'4',	'$',	A('4'),	'4',	'$',	C('D'),
+/* 06 - '5'	*/	'5',	'%',	A('5'),	'5',	'%',	C('E'),
+/* 07 - '6'	*/	'6',	'&',	A('6'),	'6',	'&',	C('F'),
+/* 08 - '7'	*/	'7',	'/',	A('7'),	'7',	'/',	C('G'),
+/* 09 - '8'	*/	'8',	'(',	A('8'),	'8',	'(',	C('H'),
+/* 10 - '9'	*/	'9',	')',	A('9'),	'8',	')',	C('I'),
+/* 11 - '0'	*/	'0',	'=',	A('0'),	'0',	'=',	C('@'),
+/* 12 - '-'	*/	'\'',	'?',	A('\''),'`',	'?',	C('@'),
+/* 13 - '='	*/	0215,	'^',	A('|'),	0215,	'^',	C('^'),
+/* 14 - BS	*/	C('H'),	C('H'),	CA('H'),C('H'),	C('H'),	0177,	
+/* 15 - TAB	*/	C('I'),	C('I'),	CA('I'),C('I'),	C('I'),	C('I'),
+/* 16 - 'q'	*/	L('q'),	'Q',	A('q'),	'q',	'Q',	C('Q'),
+/* 17 - 'w'	*/	L('w'),	'W',	A('w'),	'w',	'W',	C('W'),
+/* 18 - 'e'	*/	L('e'),	'E',	A('e'),	'e',	'E',	C('E'),
+/* 19 - 'r'	*/	L('r'),	'R',	A('r'),	'r',	'R',	C('R'),
+/* 20 - 't'	*/	L('t'),	'T',	A('t'),	't',	'T',	C('T'),
+/* 21 - 'y'	*/	L('y'),	'Y',	A('y'),	'y',	'Y',	C('Y'),
+/* 22 - 'u'	*/	L('u'),	'U',	A('u'),	'u',	'U',	C('U'),
+/* 23 - 'i'	*/	L('i'),	'I',	A('i'),	'i',	'I',	C('I'),
+/* 24 - 'o'	*/	L('o'),	'O',	A('o'),	'o',	'O',	C('O'),
+/* 25 - 'p'	*/	L('p'),	'P',	A('p'),	'p',	'P',	C('P'),
+/* 26 - '['	*/	0212,	0202,	0212,	'[',	'{',	C('['),
+/* 27 - ']'	*/	'+',	'*',	A('+'),	']',	'}',	C(']'),
+/* 28 - CR/LF	*/	C('M'),	C('M'),	CA('M'),C('M'),	C('M'),	C('J'),
+/* 29 - Ctrl	*/	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,
+/* 30 - 'a'	*/	L('a'),	'A',	A('a'),	'a',	'A',	C('A'),
+/* 31 - 's'	*/	L('s'),	'S',	A('s'),	's',	'S',	C('S'),
+/* 32 - 'd'	*/	L('d'),	'D',	A('d'),	'd',	'D',	C('D'),
+/* 33 - 'f'	*/	L('f'),	'F',	A('f'),	'f',	'F',	C('F'),
+/* 34 - 'g'	*/	L('g'),	'G',	A('g'),	'g',	'G',	C('G'),
+/* 35 - 'h'	*/	L('h'),	'H',	A('h'),	'h',	'H',	C('H'),
+/* 36 - 'j'	*/	L('j'),	'J',	A('j'),	'j',	'J',	C('J'),
+/* 37 - 'k'	*/	L('k'),	'K',	A('k'),	'k',	'K',	C('K'),
+/* 38 - 'l'	*/	L('l'),	'L',	A('l'),	'l',	'L',	C('L'),
+/* 39 - ';'	*/	0225,	0207,	0225,	'@',	'@',	C('@'),
+/* 40 - '\''	*/	0205,	0370,	0205,	'#',	0276,	C('@'),
+/* 41 - '`'	*/	'\\',	'|',	A('\\'),0176,	'|',	C('\\'),
+/* 42 - l. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 43 - '\\'	*/	0227,	025,	0227,	0227,	025,	C('@'),
+/* 44 - 'z'	*/	L('z'),	'Z',	A('z'),	'z',	'Z',	C('Z'),
+/* 45 - 'x'	*/	L('x'),	'X',	A('x'),	'x',	'X',	C('X'),
+/* 46 - 'c'	*/	L('c'),	'C',	A('c'),	'c',	'C',	C('C'),
+/* 47 - 'v'	*/	L('v'),	'V',	A('v'),	'v',	'V',	C('V'),
+/* 48 - 'b'	*/	L('b'),	'B',	A('b'),	'b',	'B',	C('B'),
+/* 49 - 'n'	*/	L('n'),	'N',	A('n'),	'n',	'N',	C('N'),
+/* 50 - 'm'	*/	L('m'),	'M',	A('m'),	'm',	'M',	C('M'),
+/* 51 - ','	*/	',',	';',	A(','),	',',	';',	C('@'),
+/* 52 - '.'	*/	'.',	':',	A('.'),	'.',	':',	C('@'),
+/* 53 - '/'	*/	'-',	'_',	A('-'),	'-',	'_',	C('_'),
+/* 54 - r. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 55 - '*'	*/	'*',	'*',	A('*'),	'*',	'*',	C('M'),
+/* 56 - ALT	*/	ALT,	ALT,	ALT,	ALT,	ALT,	ALT,
+/* 57 - ' '	*/	' ',	' ',	A(' '),	' ',	' ',	C('@'),
+/* 58 - CapsLck	*/	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,
+/* 59 - F1	*/	F1,	SF1,	AF1,	AF1,	ASF1,	CF1,
+/* 60 - F2	*/	F2,	SF2,	AF2,	AF2,	ASF2,	CF2,
+/* 61 - F3	*/	F3,	SF3,	AF3,	AF3,	ASF3,	CF3,
+/* 62 - F4	*/	F4,	SF4,	AF4,	AF4,	ASF4,	CF4,
+/* 63 - F5	*/	F5,	SF5,	AF5,	AF5,	ASF5,	CF5,
+/* 64 - F6	*/	F6,	SF6,	AF6,	AF6,	ASF6,	CF6,
+/* 65 - F7	*/	F7,	SF7,	AF7,	AF7,	ASF7,	CF7,
+/* 66 - F8	*/	F8,	SF8,	AF8,	AF8,	ASF8,	CF8,
+/* 67 - F9	*/	F9,	SF9,	AF9,	AF9,	ASF9,	CF9,
+/* 68 - F10	*/	F10,	SF10,	AF10,	AF10,	ASF10,	CF10,
+/* 69 - NumLock	*/	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,
+/* 70 - ScrLock */	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,
+/* 71 - Home	*/	HOME,	'7',	AHOME,	AHOME,	'7',	CHOME,	
+/* 72 - CurUp	*/	UP,	'8',	AUP,	AUP,	'8',	CUP,
+/* 73 - PgUp	*/	PGUP,	'9',	APGUP,	APGUP,	'9',	CPGUP,
+/* 74 - '-'	*/	NMIN,	'-',	ANMIN,	ANMIN,	'-',	CNMIN,
+/* 75 - Left	*/	LEFT,	'4',	ALEFT,	ALEFT,	'4',	CLEFT,
+/* 76 - MID	*/	MID,	'5',	AMID,	AMID,	'5',	CMID,
+/* 77 - Right	*/	RIGHT,	'6',	ARIGHT,	ARIGHT,	'6',	CRIGHT,
+/* 78 - '+'	*/	PLUS,	'+',	APLUS,	APLUS,	'+',	CPLUS,
+/* 79 - End	*/	END,	'1',	AEND,	AEND,	'1',	CEND,
+/* 80 - Down	*/	DOWN,	'2',	ADOWN,	ADOWN,	'2',	CDOWN,
+/* 81 - PgDown	*/	PGDN,	'3',	APGDN,	APGDN,	'3',	CPGDN,
+/* 82 - Insert	*/	INSRT,	'0',	AINSRT,	AINSRT,	'0',	CINSRT,
+/* 83 - Delete	*/	0177,	'.',	A(0177),0177,	'.',	0177,
+/* 84 - Enter	*/	C('M'),	C('M'),	CA('M'),C('M'),	C('M'),	C('J'),
+/* 85 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 86 - ???	*/	'<',	'>',	A('<'),	'|',	'>',	C('@'),
+/* 87 - F11	*/	F11,	SF11,	AF11,	AF11,	ASF11,	CF11,
+/* 88 - F12	*/	F12,	SF12,	AF12,	AF12,	ASF12,	CF12,
+/* 89 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 90 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 91 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 92 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 93 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 94 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 95 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 96 - EXT_KEY	*/	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,
+/* 97 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 98 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 99 - ???	*/	0,	0,	0,	0,	0,	0,
+/*100 - ???	*/	0,	0,	0,	0,	0,	0,
+/*101 - ???	*/	0,	0,	0,	0,	0,	0,
+/*102 - ???	*/	0,	0,	0,	0,	0,	0,
+/*103 - ???	*/	0,	0,	0,	0,	0,	0,
+/*104 - ???	*/	0,	0,	0,	0,	0,	0,
+/*105 - ???	*/	0,	0,	0,	0,	0,	0,
+/*106 - ???	*/	0,	0,	0,	0,	0,	0,
+/*107 - ???	*/	0,	0,	0,	0,	0,	0,
+/*108 - ???	*/	0,	0,	0,	0,	0,	0,
+/*109 - ???	*/	0,	0,	0,	0,	0,	0,
+/*110 - ???	*/	0,	0,	0,	0,	0,	0,
+/*111 - ???	*/	0,	0,	0,	0,	0,	0,
+/*112 - ???	*/	0,	0,	0,	0,	0,	0,
+/*113 - ???	*/	0,	0,	0,	0,	0,	0,
+/*114 - ???	*/	0,	0,	0,	0,	0,	0,
+/*115 - ???	*/	0,	0,	0,	0,	0,	0,
+/*116 - ???	*/	0,	0,	0,	0,	0,	0,
+/*117 - ???	*/	0,	0,	0,	0,	0,	0,
+/*118 - ???	*/	0,	0,	0,	0,	0,	0,
+/*119 - ???	*/	0,	0,	0,	0,	0,	0,
+/*120 - ???	*/	0,	0,	0,	0,	0,	0,
+/*121 - ???	*/	0,	0,	0,	0,	0,	0,
+/*122 - ???	*/	0,	0,	0,	0,	0,	0,
+/*123 - ???	*/	0,	0,	0,	0,	0,	0,
+/*124 - ???	*/	0,	0,	0,	0,	0,	0,
+/*125 - ???	*/	0,	0,	0,	0,	0,	0,
+/*126 - ???	*/	0,	0,	0,	0,	0,	0,
+/*127 - ???	*/	0,	0,	0,	0,	0,	0
+};
Index: /trunk/minix/drivers/tty/keymaps/japanese.src
===================================================================
--- /trunk/minix/drivers/tty/keymaps/japanese.src	(revision 9)
+++ /trunk/minix/drivers/tty/keymaps/japanese.src	(revision 9)
@@ -0,0 +1,157 @@
+/*
+ *	Keymap for Japanese 106 keyboard.
+ *		Dec. 31 1995
+ *	Toshiya Ogawa	<ogw@shizuokanet.or.jp>
+ *			<GCD02425@niftyserve.or.jp>
+ */
+
+/*
+ * Japanese 106 keyboard has following additional 5 scan codes
+ * compared to US standard 101 keyboard.
+ *
+ *	scan-code	keytop	     effect in this keymap
+ *	-------------------------------------------------------
+ *	112(0x70)	KANA		(ignored)
+ *	115(0x73)	BackSlash	mapped to '\\' and '_'
+ *	121(0x79)	HENKAN		(ignored)
+ *	123(0x7B)	MU-HENKAN	(ignored)
+ *	125(0x7D)	YEN		mapped to '\\' and '|'
+ */
+
+#if (NR_SCAN_CODES != 0x80) 
+#error NR_SCAN_CODES mis-match
+#endif
+
+u16_t keymap[NR_SCAN_CODES * MAP_COLS] = {
+
+/* scan-code		!Shift	Shift	Alt1	Alt2	Alt+Sh	Ctrl	*/
+/* ==================================================================== */
+/* 00 - none	*/	0,	0,	0,	0,	0,	0,	
+/* 01 - ESC	*/	C('['),	C('['),	CA('['),CA('['),CA('['),C('['),
+/* 02 - '1'	*/	'1',	'!',	A('1'),	A('1'),	A('!'),	C('A'),
+/* 03 - '2'	*/	'2',	'"',	A('2'),	A('2'),	A('"'),	C('B'),
+/* 04 - '3'	*/	'3',	'#',	A('3'),	A('3'),	A('#'),	C('C'),
+/* 05 - '4'	*/	'4',	'$',	A('4'),	A('4'),	A('$'),	C('D'),
+/* 06 - '5'	*/	'5',	'%',	A('5'),	A('5'),	A('%'),	C('E'),
+/* 07 - '6'	*/	'6',	'&',	A('6'),	A('6'),	A('&'),	C('F'),
+/* 08 - '7'	*/	'7',	'\'',	A('7'),	A('7'),	A('\''),C('G'),
+/* 09 - '8'	*/	'8',	'(',	A('8'),	A('8'),	A('('),	C('H'),
+/* 10 - '9'	*/	'9',	')',	A('9'),	A('9'),	A(')'),	C('I'),
+/* 11 - '0'	*/	'0',	'~',	A('0'),	A('0'),	A('~'),	C('@'),
+/* 12 - '-'	*/	'-',	'=',	A('-'),	A('-'),	A('='),	C('@'),
+/* 13 - '^'	*/	'^',	'~',	A('^'),	A('^'),	A('~'),	C('^'),
+/* 14 - BS	*/	C('H'),	C('H'),	CA('H'),CA('H'),CA('H'),0177,	
+/* 15 - TAB	*/	C('I'),	C('I'),	CA('I'),CA('I'),CA('I'),C('I'),
+/* 16 - 'q'	*/	L('q'),	'Q',	A('q'),	A('q'),	A('Q'),	C('Q'),
+/* 17 - 'w'	*/	L('w'),	'W',	A('w'),	A('w'),	A('W'),	C('W'),
+/* 18 - 'e'	*/	L('e'),	'E',	A('e'),	A('e'),	A('E'),	C('E'),
+/* 19 - 'r'	*/	L('r'),	'R',	A('r'),	A('r'),	A('R'),	C('R'),
+/* 20 - 't'	*/	L('t'),	'T',	A('t'),	A('t'),	A('T'),	C('T'),
+/* 21 - 'y'	*/	L('y'),	'Y',	A('y'),	A('y'),	A('Y'),	C('Y'),
+/* 22 - 'u'	*/	L('u'),	'U',	A('u'),	A('u'),	A('U'),	C('U'),
+/* 23 - 'i'	*/	L('i'),	'I',	A('i'),	A('i'),	A('I'),	C('I'),
+/* 24 - 'o'	*/	L('o'),	'O',	A('o'),	A('o'),	A('O'),	C('O'),
+/* 25 - 'p'	*/	L('p'),	'P',	A('p'),	A('p'),	A('P'),	C('P'),
+/* 26 - '@'	*/	'@',	'`',	A('@'),	A('@'),	A('`'),	C('@'),
+/* 27 - '['	*/	'[',	'{',	A('['),	A('['),	A('{'),	C('['),
+/* 28 - Enter	*/	C('M'),	C('M'),	CA('M'),CA('M'),CA('M'),C('J'),
+/* 29 - Ctrl	*/	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,
+/* 30 - 'a'	*/	L('a'),	'A',	A('a'),	A('a'),	A('A'),	C('A'),
+/* 31 - 's'	*/	L('s'),	'S',	A('s'),	A('s'),	A('S'),	C('S'),
+/* 32 - 'd'	*/	L('d'),	'D',	A('d'),	A('d'),	A('D'),	C('D'),
+/* 33 - 'f'	*/	L('f'),	'F',	A('f'),	A('f'),	A('F'),	C('F'),
+/* 34 - 'g'	*/	L('g'),	'G',	A('g'),	A('g'),	A('G'),	C('G'),
+/* 35 - 'h'	*/	L('h'),	'H',	A('h'),	A('h'),	A('H'),	C('H'),
+/* 36 - 'j'	*/	L('j'),	'J',	A('j'),	A('j'),	A('J'),	C('J'),
+/* 37 - 'k'	*/	L('k'),	'K',	A('k'),	A('k'),	A('K'),	C('K'),
+/* 38 - 'l'	*/	L('l'),	'L',	A('l'),	A('l'),	A('L'),	C('L'),
+/* 39 - ';'	*/	';',	'+',	A(';'),	A(';'),	A('+'),	C('@'),
+/* 40 - ':'	*/	':',	'*',	A(':'),	A(':'),	A('*'),	C('@'),
+/* 41 - KANJI	*/	0,	0,	0,	0,	0,	0,	
+/* 42 - l. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 43 - ']'	*/	']',	'}',	A(']'),	A(']'),	A('}'),	C(']'),
+/* 44 - 'z'	*/	L('z'),	'Z',	A('z'),	A('z'),	A('Z'),	C('Z'),
+/* 45 - 'x'	*/	L('x'),	'X',	A('x'),	A('x'),	A('X'),	C('X'),
+/* 46 - 'c'	*/	L('c'),	'C',	A('c'),	A('c'),	A('C'),	C('C'),
+/* 47 - 'v'	*/	L('v'),	'V',	A('v'),	A('v'),	A('V'),	C('V'),
+/* 48 - 'b'	*/	L('b'),	'B',	A('b'),	A('b'),	A('B'),	C('B'),
+/* 49 - 'n'	*/	L('n'),	'N',	A('n'),	A('n'),	A('N'),	C('N'),
+/* 50 - 'm'	*/	L('m'),	'M',	A('m'),	A('m'),	A('M'),	C('M'),
+/* 51 - ','	*/	',',	'<',	A(','),	A(','),	A('<'),	C('@'),
+/* 52 - '.'	*/	'.',	'>',	A('.'),	A('.'),	A('>'),	C('@'),
+/* 53 - '/'	*/	'/',	'?',	A('/'),	A('/'),	A('?'),	C('@'),
+/* 54 - r. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 55 - '*'	*/	'*',	'*',	A('*'),	A('*'),	A('*'),	C('@'),
+/* 56 - ALT	*/	ALT,	ALT,	ALT,	ALT,	ALT,	ALT,
+/* 57 - ' '	*/	' ',	' ',	A(' '),	A(' '),	A(' '),	C('@'),
+/* 58 - CapsLck	*/	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,
+/* 59 - F1	*/	F1,	SF1,	AF1,	AF1,	ASF1,	CF1,
+/* 60 - F2	*/	F2,	SF2,	AF2,	AF2,	ASF2,	CF2,
+/* 61 - F3	*/	F3,	SF3,	AF3,	AF3,	ASF3,	CF3,
+/* 62 - F4	*/	F4,	SF4,	AF4,	AF4,	ASF4,	CF4,
+/* 63 - F5	*/	F5,	SF5,	AF5,	AF5,	ASF5,	CF5,
+/* 64 - F6	*/	F6,	SF6,	AF6,	AF6,	ASF6,	CF6,
+/* 65 - F7	*/	F7,	SF7,	AF7,	AF7,	ASF7,	CF7,
+/* 66 - F8	*/	F8,	SF8,	AF8,	AF8,	ASF8,	CF8,
+/* 67 - F9	*/	F9,	SF9,	AF9,	AF9,	ASF9,	CF9,
+/* 68 - F10	*/	F10,	SF10,	AF10,	AF10,	ASF10,	CF10,
+/* 69 - NumLock	*/	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,
+/* 70 - ScrLock */	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,
+/* 71 - Home	*/	HOME,	'7',	AHOME,	AHOME,	A('7'),	CHOME,	
+/* 72 - CurUp	*/	UP,	'8',	AUP,	AUP,	A('8'),	CUP,
+/* 73 - PgUp	*/	PGUP,	'9',	APGUP,	APGUP,	A('9'),	CPGUP,
+/* 74 - '-'	*/	NMIN,	'-',	ANMIN,	ANMIN,	A('-'),	CNMIN,
+/* 75 - Left	*/	LEFT,	'4',	ALEFT,	ALEFT,	A('4'),	CLEFT,
+/* 76 - MID	*/	MID,	'5',	AMID,	AMID,	A('5'),	CMID,
+/* 77 - Right	*/	RIGHT,	'6',	ARIGHT,	ARIGHT,	A('6'),	CRIGHT,
+/* 78 - '+'	*/	PLUS,	'+',	APLUS,	APLUS,	A('+'),	CPLUS,
+/* 79 - End	*/	END,	'1',	AEND,	AEND,	A('1'),	CEND,
+/* 80 - Down	*/	DOWN,	'2',	ADOWN,	ADOWN,	A('2'),	CDOWN,
+/* 81 - PgDown	*/	PGDN,	'3',	APGDN,	APGDN,	A('3'),	CPGDN,
+/* 82 - Insert	*/	INSRT,	'0',	AINSRT,	AINSRT,	A('0'),	CINSRT,
+/* 83 - Delete	*/	0177,	'.',	A(0177),A(0177),A('.'),	0177,
+/* 84 - Enter	*/	C('M'),	C('M'),	CA('M'),CA('M'),CA('M'),C('J'),
+/* 85 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 86 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 87 - F11	*/	F11,	SF11,	AF11,	AF11,	ASF11,	CF11,
+/* 88 - F12	*/	F12,	SF12,	AF12,	AF12,	ASF12,	CF12,
+/* 89 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 90 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 91 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 92 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 93 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 94 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 95 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 96 - EXT_KEY	*/	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,
+/* 97 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 98 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 99 - ???	*/	0,	0,	0,	0,	0,	0,
+/*100 - ???	*/	0,	0,	0,	0,	0,	0,
+/*101 - ???	*/	0,	0,	0,	0,	0,	0,
+/*102 - ???	*/	0,	0,	0,	0,	0,	0,
+/*103 - ???	*/	0,	0,	0,	0,	0,	0,
+/*104 - ???	*/	0,	0,	0,	0,	0,	0,
+/*105 - ???	*/	0,	0,	0,	0,	0,	0,
+/*106 - ???	*/	0,	0,	0,	0,	0,	0,
+/*107 - ???	*/	0,	0,	0,	0,	0,	0,
+/*108 - ???	*/	0,	0,	0,	0,	0,	0,
+/*109 - ???	*/	0,	0,	0,	0,	0,	0,
+/*110 - ???	*/	0,	0,	0,	0,	0,	0,
+/*111 - ???	*/	0,	0,	0,	0,	0,	0,
+/*112 - KANA	*/	0,	0,	0,	0,	0,	0,
+/*113 - ???	*/	0,	0,	0,	0,	0,	0,
+/*114 - ???	*/	0,	0,	0,	0,	0,	0,
+/*115 - '\\'	*/	'\\',	'_',	A('\\'),A('\\'),A('_'),	C('_'),
+/*116 - ???	*/	0,	0,	0,	0,	0,	0,
+/*117 - ???	*/	0,	0,	0,	0,	0,	0,
+/*118 - ???	*/	0,	0,	0,	0,	0,	0,
+/*119 - ???	*/	0,	0,	0,	0,	0,	0,
+/*120 - ???	*/	0,	0,	0,	0,	0,	0,
+/*121 - HENKAN	*/	0,	0,	0,	0,	0,	0,
+/*122 - ???	*/	0,	0,	0,	0,	0,	0,
+/*123 - MU-HENKAN*/	0,	0,	0,	0,	0,	0,
+/*124 - ???	*/	0,	0,	0,	0,	0,	0,
+/*125 - YEN	*/	'\\',	'|',	A('\\'),A('\\'),A('|'),	C('\\'),
+/*126 - ???	*/	0,	0,	0,	0,	0,	0,
+/*127 - ???	*/	0,	0,	0,	0,	0,	0
+};
Index: /trunk/minix/drivers/tty/keymaps/latin-america.src
===================================================================
--- /trunk/minix/drivers/tty/keymaps/latin-america.src	(revision 9)
+++ /trunk/minix/drivers/tty/keymaps/latin-america.src	(revision 9)
@@ -0,0 +1,153 @@
+/***
+   Keymap for Latin American keyboard. v1.02
+   Victor A. Rodriguez - El bit Fantasma - Bit-Man@Tasa.Com.AR
+
+   The Latin American keyboard makes differences between the left and
+   right ALT keys (the right one is so called ALT GR), and uses accent.
+
+   Release History 
+   ===============
+   v1.00     Initial version 
+   v1.01     Extended ASCII characters replaced by hex. equivalents
+   v1.02     NR_SCAN_CODES has grown to 0x80, required by Toshiya Ogawa
+             (ogw@shizuokanet.or.jp) and added by Kees J.Bot (kjb@cs.vu.nl)
+             in MINIX 1.7.2
+***/
+
+#if (NR_SCAN_CODES != 0x80) 
+#error NR_SCAN_CODES mis-match
+#endif
+
+u16_t keymap[NR_SCAN_CODES * MAP_COLS] = {
+
+/* scan-code            !Shift  Shift   Alt1    Alt2    Alt+Sh  Ctrl    */
+/* ==================================================================== */
+/* 00 - none    */      0,      0,      0,      0,      0,      0,      
+/* 01 - ESC     */      C('['), C('['), CA('['),CA('['),CA('['),C('['),
+/* 02 - '1'     */      '1',    '!',    A('1'), A('1'), A('!'), C('A'),
+/* 03 - '2'     */      '2',    '"',    A('2'), A('2'), A('"'), C('@'),
+/* 04 - '3'     */      '3',    '#',    A('3'), A('3'), A('#'), C('C'),
+/* 05 - '4'     */      '4',    '$',    A('4'), A('4'), A('$'), C('D'),
+/* 06 - '5'     */      '5',    '%',    A('5'), A('5'), A('%'), C('E'),
+/* 07 - '6'     */      '6',    '&',    A('6'), A('6'), A('$'), C('^'),
+/* 08 - '7'     */      '7',    '/',    A('7'), A('7'), A('/'), C('G'),
+/* 09 - '8'     */      '8',    '(',    A('8'), A('8'), A('('), C('H'),
+/* 10 - '9'     */      '9',    ')',    A('9'), A('9'), A(')'), C('I'),
+/* 11 - '0'     */      '0',    '=',    A('0'), A('0'), A('='), C('@'),
+/* 12 - '-'     */      '\'',   '?',    A('\''), 0x5c,   A('?'), C('?'),
+/* 13 - 'š'     */      0xa8,   0xad,   A(0xa8),A(0xa8),A(0xad), C('@'),
+/* 14 - BS      */      C('H'), C('H'), CA('H'),CA('H'),CA('H'),0177,   
+/* 15 - TAB     */      C('I'), C('I'), CA('I'),CA('I'),CA('I'),C('I'),
+/* 16 - 'q'     */      L('q'), 'Q',    A('q'), 0x40,   A('Q'), C('Q'),
+/* 17 - 'w'     */      L('w'), 'W',    A('w'), A('w'), A('W'), C('W'),
+/* 18 - 'e'     */      L('e'), 'E',    A('e'), A('e'), A('E'), C('E'),
+/* 19 - 'r'     */      L('r'), 'R',    A('r'), A('r'), A('R'), C('R'),
+/* 20 - 't'     */      L('t'), 'T',    A('t'), A('t'), A('T'), C('T'),
+/* 21 - 'y'     */      L('y'), 'Y',    A('y'), A('y'), A('Y'), C('Y'),
+/* 22 - 'u'     */      L('u'), 'U',    A('u'), A('u'), A('U'), C('U'),
+/* 23 - 'i'     */      L('i'), 'I',    A('i'), A('i'), A('I'), C('I'),
+/* 24 - 'o'     */      L('o'), 'O',    A('o'), A('o'), A('O'), C('O'),
+/* 25 - 'p'     */      L('p'), 'P',    A('p'), A('p'), A('P'), C('P'),
+/* 26 - 'ï'     */      0xef,   0xf9,   A(0xef),A(0xef),A(0xf9),C(0xef),
+/* 27 - '+'     */      '+',    '*',    A('+'), 0x7e,   A('*'), C('+'),
+/* 28 - CR/LF   */      C('M'), C('M'), CA('M'),CA('M'),CA('M'),C('J'),
+/* 29 - Ctrl    */      CTRL,   CTRL,   CTRL,   CTRL,   CTRL,   CTRL,
+/* 30 - 'a'     */      L('a'), 'A',    A('a'), A('a'), A('A'), C('A'),
+/* 31 - 's'     */      L('s'), 'S',    A('s'), A('s'), A('S'), C('S'),
+/* 32 - 'd'     */      L('d'), 'D',    A('d'), A('d'), A('D'), C('D'),
+/* 33 - 'f'     */      L('f'), 'F',    A('f'), A('f'), A('F'), C('F'),
+/* 34 - 'g'     */      L('g'), 'G',    A('g'), A('g'), A('G'), C('G'),
+/* 35 - 'h'     */      L('h'), 'H',    A('h'), A('h'), A('H'), C('H'),
+/* 36 - 'j'     */      L('j'), 'J',    A('j'), A('j'), A('J'), C('J'),
+/* 37 - 'k'     */      L('k'), 'K',    A('k'), A('k'), A('K'), C('K'),
+/* 38 - 'l'     */      L('l'), 'L',    A('l'), A('l'), A('L'), C('L'),
+/* 39 - '€'     */      L(0xa4),0xa5,   A(0xa4),A(0xa4),A(0xa5),C('@'),
+/* 40 - '{'     */      '{',    '[',    A('{'), 0x5e,   A('['), C('@'),
+/* 41 - '|'     */      '|',    0xf8,   A('|'), 0xaa,   A('\''),C('@'),
+/* 42 - l. SHIFT*/      SHIFT,  SHIFT,  SHIFT,  SHIFT,  SHIFT,  SHIFT,
+/* 43 - '}'     */      0x7d,   0x5d,   A('<'), 0x60,   A('>'), C('<'),
+/* 44 - 'z'     */      L('z'), 'Z',    A('z'), A('z'), A('Z'), C('Z'),
+/* 45 - 'x'     */      L('x'), 'X',    A('x'), A('x'), A('X'), C('X'),
+/* 46 - 'c'     */      L('c'), 'C',    A('c'), A('c'), A('C'), C('C'),
+/* 47 - 'v'     */      L('v'), 'V',    A('v'), A('v'), A('V'), C('V'),
+/* 48 - 'b'     */      L('b'), 'B',    A('b'), A('b'), A('B'), C('B'),
+/* 49 - 'n'     */      L('n'), 'N',    A('n'), A('n'), A('N'), C('N'),
+/* 50 - 'm'     */      L('m'), 'M',    A('m'), A('m'), A('M'), C('M'),
+/* 51 - ','     */      ',',    ';',    A(','), A(','), A(';'), C('@'),
+/* 52 - '.'     */      '.',    ':',    A('.'), A('.'), A(':'), C('@'),
+/* 53 - '/'     */      '-',    '_',    A('-'), A('-'), A('_'), C('@'),
+/* 54 - r. SHIFT*/      SHIFT,  SHIFT,  SHIFT,  SHIFT,  SHIFT,  SHIFT,
+/* 55 - '*'     */      '*',    '*',    A('*'), A('*'), A('*'), C('@'),
+/* 56 - ALT     */      ALT,    ALT,    ALT,    ALT,    ALT,    ALT,
+/* 57 - ' '     */      ' ',    ' ',    A(' '), A(' '), A(' '), C('@'),
+/* 58 - CapsLck */      CALOCK, CALOCK, CALOCK, CALOCK, CALOCK, CALOCK,
+/* 59 - F1      */      F1,     SF1,    AF1,    AF1,    ASF1,   CF1,
+/* 60 - F2      */      F2,     SF2,    AF2,    AF2,    ASF2,   CF2,
+/* 61 - F3      */      F3,     SF3,    AF3,    AF3,    ASF3,   CF3,
+/* 62 - F4      */      F4,     SF4,    AF4,    AF4,    ASF4,   CF4,
+/* 63 - F5      */      F5,     SF5,    AF5,    AF5,    ASF5,   CF5,
+/* 64 - F6      */      F6,     SF6,    AF6,    AF6,    ASF6,   CF6,
+/* 65 - F7      */      F7,     SF7,    AF7,    AF7,    ASF7,   CF7,
+/* 66 - F8      */      F8,     SF8,    AF8,    AF8,    ASF8,   CF8,
+/* 67 - F9      */      F9,     SF9,    AF9,    AF9,    ASF9,   CF9,
+/* 68 - F10     */      F10,    SF10,   AF10,   AF10,   ASF10,  CF10,
+/* 69 - NumLock */      NLOCK,  NLOCK,  NLOCK,  NLOCK,  NLOCK,  NLOCK,
+/* 70 - ScrLock */      SLOCK,  SLOCK,  SLOCK,  SLOCK,  SLOCK,  SLOCK,
+/* 71 - Home    */      HOME,   '7',    AHOME,  AHOME,  A('7'), CHOME,  
+/* 72 - CurUp   */      UP,     '8',    AUP,    AUP,    A('8'), CUP,
+/* 73 - PgUp    */      PGUP,   '9',    APGUP,  APGUP,  A('9'), CPGUP,
+/* 74 - '-'     */      '-',    '-',    '-',    '-',    '-',    '-',
+/* 75 - Left    */      LEFT,   '4',    ALEFT,  ALEFT,  A('4'), CLEFT,
+/* 76 - MID     */      MID,    '5',    AMID,   AMID,   A('5'), CMID,
+/* 77 - Right   */      RIGHT,  '6',    ARIGHT, ARIGHT, A('6'), CRIGHT,
+/* 78 - '+'     */      '+',    '+',    '+',    '+',    '+',    '+',
+/* 79 - End     */      END,    '1',    AEND,   AEND,   A('1'), CEND,
+/* 80 - Down    */      DOWN,   '2',    ADOWN,  ADOWN,  A('2'), CDOWN,
+/* 81 - PgDown  */      PGDN,   '3',    APGDN,  APGDN,  A('3'), CPGDN,
+/* 82 - Insert  */      INSRT,  '0',    AINSRT, AINSRT, A('0'), CINSRT,
+/* 83 - Delete  */      0177,   '.',    A(0177),A(0177),A('.'), 0177,
+/* 84 - Enter   */      C('M'), C('M'), CA('M'),CA('M'),CA('M'),C('J'),
+/* 85 - ???     */      0,      0,      0,      0,      0,      0,
+/* 86 - ???     */      '<',    '>',   A('<'),  A('>'), A('>'), C('@'),
+/* 87 - F11     */      F11,    SF11,   AF11,   AF11,   ASF11,  CF11,
+/* 88 - F12     */      F12,    SF12,   AF12,   AF12,   ASF12,  CF12,
+/* 89 - ???     */      0,      0,      0,      0,      0,      0,
+/* 90 - ???     */      0,      0,      0,      0,      0,      0,
+/* 91 - ???     */      0,      0,      0,      0,      0,      0,
+/* 92 - ???     */      0,      0,      0,      0,      0,      0,
+/* 93 - ???     */      0,      0,      0,      0,      0,      0,
+/* 94 - ???     */      0,      0,      0,      0,      0,      0,
+/* 95 - ???     */      0,      0,      0,      0,      0,      0,
+/* 96 - EXT_KEY */      EXTKEY, EXTKEY, EXTKEY, EXTKEY, EXTKEY, EXTKEY,
+/* 97 - ???     */      0,      0,      0,      0,      0,      0,
+/* 98 - ???     */      0,      0,      0,      0,      0,      0,
+/* 99 - ???     */      0,      0,      0,      0,      0,      0,
+/*100 - ???     */      0,      0,      0,      0,      0,      0,
+/*101 - ???     */      0,      0,      0,      0,      0,      0,
+/*102 - ???     */      0,      0,      0,      0,      0,      0,
+/*103 - ???     */      0,      0,      0,      0,      0,      0,
+/*104 - ???     */      0,      0,      0,      0,      0,      0,
+/*105 - ???     */      0,      0,      0,      0,      0,      0,
+/*106 - ???     */      0,      0,      0,      0,      0,      0,
+/*107 - ???     */      0,      0,      0,      0,      0,      0,
+/*108 - ???     */      0,      0,      0,      0,      0,      0,
+/*109 - ???     */      0,      0,      0,      0,      0,      0,
+/*110 - ???     */      0,      0,      0,      0,      0,      0,
+/*111 - ???     */      0,      0,      0,      0,      0,      0,
+/*112 - ???     */      0,      0,      0,      0,      0,      0,
+/*113 - ???     */      0,      0,      0,      0,      0,      0,
+/*114 - ???     */      0,      0,      0,      0,      0,      0,
+/*115 - ???     */      0,      0,      0,      0,      0,      0,
+/*116 - ???     */      0,      0,      0,      0,      0,      0,
+/*117 - ???     */      0,      0,      0,      0,      0,      0,
+/*118 - ???     */      0,      0,      0,      0,      0,      0,
+/*119 - ???     */      0,      0,      0,      0,      0,      0,
+/*120 - ???     */      0,      0,      0,      0,      0,      0,
+/*121 - ???     */      0,      0,      0,      0,      0,      0,
+/*122 - ???     */      0,      0,      0,      0,      0,      0,
+/*123 - ???     */      0,      0,      0,      0,      0,      0,
+/*124 - ???     */      0,      0,      0,      0,      0,      0,
+/*125 - ???     */      0,      0,      0,      0,      0,      0,
+/*126 - ???     */      0,      0,      0,      0,      0,      0,
+/*127 - ???     */      0,      0,      0,      0,      0,      0
+};
Index: /trunk/minix/drivers/tty/keymaps/olivetti.src
===================================================================
--- /trunk/minix/drivers/tty/keymaps/olivetti.src	(revision 9)
+++ /trunk/minix/drivers/tty/keymaps/olivetti.src	(revision 9)
@@ -0,0 +1,135 @@
+/* Keymap for the Olivetti M24. */
+
+u16_t keymap[NR_SCAN_CODES * MAP_COLS] = {
+
+/* scan-code		!Shift	Shift	Alt1	Alt2	Alt+Sh	Ctrl	*/
+/* ==================================================================== */
+/* 00 - none	*/	0,	0,	0,	0,	0,	0,	
+/* 01 - ESC	*/	C('['),	C('['),	CA('['),CA('['),CA('['),C('['),
+/* 02 - '1'	*/	'1',	'!',	A('1'),	A('1'),	A('!'),	C('A'),
+/* 03 - '2'	*/	'2',	'"',	A('2'),	A('2'),	A('"'),	C('B'),
+/* 04 - '3'	*/	'3',	'#',	A('3'),	A('3'),	A('#'),	C('C'),
+/* 05 - '4'	*/	'4',	'$',	A('4'),	A('4'),	A('$'),	C('D'),
+/* 06 - '5'	*/	'5',	'%',	A('5'),	A('5'),	A('%'),	C('E'),
+/* 07 - '6'	*/	'6',	'&',	A('6'),	A('6'),	A('&'),	C('F'),
+/* 08 - '7'	*/	'7',	'\'',	A('7'),	A('7'),	A('\''),C('G'),
+/* 09 - '8'	*/	'8',	'(',	A('8'),	A('8'),	A('('),	C('H'),
+/* 10 - '9'	*/	'9',	')',	A('9'),	A('9'),	A(')'),	C('I'),
+/* 11 - '0'	*/	'0',	'_',	A('0'),	A('0'),	A('_'),	C('@'),
+/* 12 - '-'	*/	'-',	'=',	A('-'),	A('-'),	A('='),	C('@'),
+/* 13 - '='	*/	'^',	'~',	A('^'),	A('^'),	A('~'),	C('^'),
+/* 14 - BS	*/	C('H'),	C('H'),	CA('H'),CA('H'),CA('H'),0177,	
+/* 15 - TAB	*/	C('I'),	C('I'),	CA('I'),CA('I'),CA('I'),C('I'),
+/* 16 - 'q'	*/	L('q'),	'Q',	A('q'),	A('q'),	A('Q'),	C('Q'),
+/* 17 - 'w'	*/	L('w'),	'W',	A('w'),	A('w'),	A('W'),	C('W'),
+/* 18 - 'e'	*/	L('e'),	'E',	A('e'),	A('e'),	A('E'),	C('E'),
+/* 19 - 'r'	*/	L('r'),	'R',	A('r'),	A('r'),	A('R'),	C('R'),
+/* 20 - 't'	*/	L('t'),	'T',	A('t'),	A('t'),	A('T'),	C('T'),
+/* 21 - 'y'	*/	L('y'),	'Y',	A('y'),	A('y'),	A('Y'),	C('Y'),
+/* 22 - 'u'	*/	L('u'),	'U',	A('u'),	A('u'),	A('U'),	C('U'),
+/* 23 - 'i'	*/	L('i'),	'I',	A('i'),	A('i'),	A('I'),	C('I'),
+/* 24 - 'o'	*/	L('o'),	'O',	A('o'),	A('o'),	A('O'),	C('O'),
+/* 25 - 'p'	*/	L('p'),	'P',	A('p'),	A('p'),	A('P'),	C('P'),
+/* 26 - '['	*/	'@',	'`',	A('@'),	A('@'),	A('`'),	C('@'),
+/* 27 - ']'	*/	'[',	'{',	A('['),	A('['),	A('{'),	C('['),
+/* 28 - CR/LF	*/	C('M'),	C('M'),	CA('M'),CA('M'),CA('M'),C('J'),
+/* 29 - Ctrl	*/	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,
+/* 30 - 'a'	*/	L('a'),	'A',	A('a'),	A('a'),	A('A'),	C('A'),
+/* 31 - 's'	*/	L('s'),	'S',	A('s'),	A('s'),	A('S'),	C('S'),
+/* 32 - 'd'	*/	L('d'),	'D',	A('d'),	A('d'),	A('D'),	C('D'),
+/* 33 - 'f'	*/	L('f'),	'F',	A('f'),	A('f'),	A('F'),	C('F'),
+/* 34 - 'g'	*/	L('g'),	'G',	A('g'),	A('g'),	A('G'),	C('G'),
+/* 35 - 'h'	*/	L('h'),	'H',	A('h'),	A('h'),	A('H'),	C('H'),
+/* 36 - 'j'	*/	L('j'),	'J',	A('j'),	A('j'),	A('J'),	C('J'),
+/* 37 - 'k'	*/	L('k'),	'K',	A('k'),	A('k'),	A('K'),	C('K'),
+/* 38 - 'l'	*/	L('l'),	'L',	A('l'),	A('l'),	A('L'),	C('L'),
+/* 39 - ';'	*/	';',	'+',	A(';'),	A(';'),	A('+'),	C('@'),
+/* 40 - '\''	*/	':',	'*',	A(':'),	A(':'),	A('*'),	C('@'),
+/* 41 - '`'	*/	']',	'}',	A(']'),	A(']'),	A('}'),	C(']'),
+/* 42 - l. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 43 - '\\'	*/	'\\',	'|',	A('\\'),A('\\'),A('|'),	C('\\'),
+/* 44 - 'z'	*/	L('z'),	'Z',	A('z'),	A('z'),	A('Z'),	C('Z'),
+/* 45 - 'x'	*/	L('x'),	'X',	A('x'),	A('x'),	A('X'),	C('X'),
+/* 46 - 'c'	*/	L('c'),	'C',	A('c'),	A('c'),	A('C'),	C('C'),
+/* 47 - 'v'	*/	L('v'),	'V',	A('v'),	A('v'),	A('V'),	C('V'),
+/* 48 - 'b'	*/	L('b'),	'B',	A('b'),	A('b'),	A('B'),	C('B'),
+/* 49 - 'n'	*/	L('n'),	'N',	A('n'),	A('n'),	A('N'),	C('N'),
+/* 50 - 'm'	*/	L('m'),	'M',	A('m'),	A('m'),	A('M'),	C('M'),
+/* 51 - ','	*/	',',	'<',	A(','),	A(','),	A('<'),	C('@'),
+/* 52 - '.'	*/	'.',	'>',	A('.'),	A('.'),	A('>'),	C('@'),
+/* 53 - '/'	*/	'/',	'?',	A('/'),	A('/'),	A('?'),	C('@'),
+/* 54 - r. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 55 - '*'	*/	'*',	'*',	A('*'),	A('*'),	A('*'),	C('@'),
+/* 56 - ALT	*/	ALT,	ALT,	ALT,	ALT,	ALT,	ALT,
+/* 57 - ' '	*/	' ',	' ',	A(' '),	A(' '),	A(' '),	C('@'),
+/* 58 - CapsLck	*/	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,
+/* 59 - F1	*/	F1,	SF1,	AF1,	AF1,	ASF1,	CF1,
+/* 60 - F2	*/	F2,	SF2,	AF2,	AF2,	ASF2,	CF2,
+/* 61 - F3	*/	F3,	SF3,	AF3,	AF3,	ASF3,	CF3,
+/* 62 - F4	*/	F4,	SF4,	AF4,	AF4,	ASF4,	CF4,
+/* 63 - F5	*/	F5,	SF5,	AF5,	AF5,	ASF5,	CF5,
+/* 64 - F6	*/	F6,	SF6,	AF6,	AF6,	ASF6,	CF6,
+/* 65 - F7	*/	F7,	SF7,	AF7,	AF7,	ASF7,	CF7,
+/* 66 - F8	*/	F8,	SF8,	AF8,	AF8,	ASF8,	CF8,
+/* 67 - F9	*/	F9,	SF9,	AF9,	AF9,	ASF9,	CF9,
+/* 68 - F10	*/	F10,	SF10,	AF10,	AF10,	ASF10,	CF10,
+/* 69 - NumLock	*/	C('S'),	C('S'),	C('S'),	C('S'),	C('S'),	C('S'),
+/* 70 - ScrLock */	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,
+/* 71 - Home	*/	HOME,	'7',	AHOME,	AHOME,	A('7'),	CHOME,	
+/* 72 - CurUp	*/	UP,	'8',	AUP,	AUP,	A('8'),	CUP,
+/* 73 - PgUp	*/	PGUP,	'9',	APGUP,	APGUP,	A('9'),	CPGUP,
+/* 74 - '-'	*/	NMIN,	'-',	ANMIN,	ANMIN,	A('-'),	CNMIN,
+/* 75 - Left	*/	LEFT,	'4',	ALEFT,	ALEFT,	A('4'),	CLEFT,
+/* 76 - MID	*/	MID,	'5',	AMID,	AMID,	A('5'),	CMID,
+/* 77 - Right	*/	RIGHT,	'6',	ARIGHT,	ARIGHT,	A('6'),	CRIGHT,
+/* 78 - '+'	*/	PLUS,	'+',	APLUS,	APLUS,	A('+'),	CPLUS,
+/* 79 - End	*/	END,	'1',	AEND,	AEND,	A('1'),	CEND,
+/* 80 - Down	*/	DOWN,	'2',	ADOWN,	ADOWN,	A('2'),	CDOWN,
+/* 81 - PgDown	*/	PGDN,	'3',	APGDN,	APGDN,	A('3'),	CPGDN,
+/* 82 - Insert	*/	INSRT,	'0',	AINSRT,	AINSRT,	A('0'),	CINSRT,
+/* 83 - Delete	*/	0177,	'.',	A(0177),A(0177),A('.'),	0177,
+/* 84 - Enter	*/	' ',	' ',	A(' '),	A(' '),	A(' '),	C('@'),
+/* 85 - ???	*/	LEFT,	014,	A(014),	A(014),	A(014),	014,
+/* 86 - ???	*/	0212,	0212,	0212,	0212,	0212,	0212,
+/* 87 - F11	*/	C('M'),	C('M'),	CA('M'),CA('M'),CA('M'),C('J'),
+/* 88 - F12	*/	F12,	SF12,	AF12,	AF12,	ASF12,	CF12,
+/* 89 - ???	*/	DOWN,	DOWN,	DOWN,	DOWN,	DOWN,	DOWN,
+/* 90 - ???	*/	RIGHT,	RIGHT,	RIGHT,	RIGHT,	RIGHT,	RIGHT,
+/* 91 - ???	*/	UP,	UP,	UP,	UP,	UP,	UP,
+/* 92 - ???	*/	LEFT,	LEFT,	LEFT,	LEFT,	LEFT,	LEFT,
+/* 93 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 94 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 95 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 96 - EXT_KEY	*/	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,
+/* 97 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 98 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 99 - ???	*/	0,	0,	0,	0,	0,	0,
+/*100 - ???	*/	0,	0,	0,	0,	0,	0,
+/*101 - ???	*/	0,	0,	0,	0,	0,	0,
+/*102 - ???	*/	0,	0,	0,	0,	0,	0,
+/*103 - ???	*/	0,	0,	0,	0,	0,	0,
+/*104 - ???	*/	0,	0,	0,	0,	0,	0,
+/*105 - ???	*/	0,	0,	0,	0,	0,	0,
+/*106 - ???	*/	0,	0,	0,	0,	0,	0,
+/*107 - ???	*/	0,	0,	0,	0,	0,	0,
+/*108 - ???	*/	0,	0,	0,	0,	0,	0,
+/*109 - ???	*/	0,	0,	0,	0,	0,	0,
+/*110 - ???	*/	0,	0,	0,	0,	0,	0,
+/*111 - ???	*/	0,	0,	0,	0,	0,	0,
+/*112 - ???	*/	0,	0,	0,	0,	0,	0,
+/*113 - ???	*/	0,	0,	0,	0,	0,	0,
+/*114 - ???	*/	0,	0,	0,	0,	0,	0,
+/*115 - ???	*/	0,	0,	0,	0,	0,	0,
+/*116 - ???	*/	0,	0,	0,	0,	0,	0,
+/*117 - ???	*/	0,	0,	0,	0,	0,	0,
+/*118 - ???	*/	0,	0,	0,	0,	0,	0,
+/*119 - ???	*/	0,	0,	0,	0,	0,	0,
+/*120 - ???	*/	0,	0,	0,	0,	0,	0,
+/*121 - ???	*/	0,	0,	0,	0,	0,	0,
+/*122 - ???	*/	0,	0,	0,	0,	0,	0,
+/*123 - ???	*/	0,	0,	0,	0,	0,	0,
+/*124 - ???	*/	0,	0,	0,	0,	0,	0,
+/*125 - ???	*/	0,	0,	0,	0,	0,	0,
+/*126 - ???	*/	0,	0,	0,	0,	0,	0,
+/*127 - ???	*/	0,	0,	0,	0,	0,	0
+};
Index: /trunk/minix/drivers/tty/keymaps/polish.src
===================================================================
--- /trunk/minix/drivers/tty/keymaps/polish.src	(revision 9)
+++ /trunk/minix/drivers/tty/keymaps/polish.src	(revision 9)
@@ -0,0 +1,140 @@
+/*
+ * Keymap for US MF-2 keyboard. + Polish national letters.
+ * Modified by Antek Sawicki <tenox@tenox.tc>
+ * Charset: ISO-8859-2 - [Polska Norma PN-93 T-42118]
+ */
+
+
+u16_t keymap[NR_SCAN_CODES * MAP_COLS] = {
+
+/* scan-code		!Shift	Shift	Alt1	Alt2	Alt+Sh	Ctrl	*/
+/* ==================================================================== */
+/* 00 - none	*/	0,	0,	0,	0,	0,	0,	
+/* 01 - ESC	*/	C('['),	C('['),	CA('['),CA('['),CA('['),C('['),
+/* 02 - '1'	*/	'1',	'!',	A('1'),	A('1'),	A('!'),	C('A'),
+/* 03 - '2'	*/	'2',	'@',	A('2'),	A('2'),	A('@'),	C('@'),
+/* 04 - '3'	*/	'3',	'#',	A('3'),	A('3'),	A('#'),	C('C'),
+/* 05 - '4'	*/	'4',	'$',	A('4'),	A('4'),	A('$'),	C('D'),
+/* 06 - '5'	*/	'5',	'%',	A('5'),	A('5'),	A('%'),	C('E'),
+/* 07 - '6'	*/	'6',	'^',	A('6'),	A('6'),	A('^'),	C('^'),
+/* 08 - '7'	*/	'7',	'&',	A('7'),	A('7'),	A('&'),	C('G'),
+/* 09 - '8'	*/	'8',	'*',	A('8'),	A('8'),	A('*'),	C('H'),
+/* 10 - '9'	*/	'9',	'(',	A('9'),	A('9'),	A('('),	C('I'),
+/* 11 - '0'	*/	'0',	')',	A('0'),	A('0'),	A(')'),	C('@'),
+/* 12 - '-'	*/	'-',	'_',	A('-'),	A('-'),	A('_'),	C('_'),
+/* 13 - '='	*/	'=',	'+',	A('='),	A('='),	A('+'),	C('@'),
+/* 14 - BS	*/	C('H'),	C('H'),	CA('H'),CA('H'),CA('H'),0177,	
+/* 15 - TAB	*/	C('I'),	C('I'),	CA('I'),CA('I'),CA('I'),C('I'),
+/* 16 - 'q'	*/	L('q'),	'Q',	A('q'),	A('q'),	A('Q'),	C('Q'),
+/* 17 - 'w'	*/	L('w'),	'W',	A('w'),	A('w'),	A('W'),	C('W'),
+/* 18 - 'e'	*/	L('e'),	'E',	A(0xea),A(0xea),A(0xca),C('E'),
+/* 19 - 'r'	*/	L('r'),	'R',	A('r'),	A('r'),	A('R'),	C('R'),
+/* 20 - 't'	*/	L('t'),	'T',	A('t'),	A('t'),	A('T'),	C('T'),
+/* 21 - 'y'	*/	L('y'),	'Y',	A('y'),	A('y'),	A('Y'),	C('Y'),
+/* 22 - 'u'	*/	L('u'),	'U',	A('u'),	A('u'),	A('U'),	C('U'),
+/* 23 - 'i'	*/	L('i'),	'I',	A('i'),	A('i'),	A('I'),	C('I'),
+/* 24 - 'o'	*/	L('o'),	'O',	A(0xf3),A(0xf3),A(0xd3),C('O'),
+/* 25 - 'p'	*/	L('p'),	'P',	A('p'),	A('p'),	A('P'),	C('P'),
+/* 26 - '['	*/	'[',	'{',	A('['),	A('['),	A('{'),	C('['),
+/* 27 - ']'	*/	']',	'}',	A(']'),	A(']'),	A('}'),	C(']'),
+/* 28 - CR/LF	*/	C('M'),	C('M'),	CA('M'),CA('M'),CA('M'),C('J'),
+/* 29 - Ctrl	*/	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,
+/* 30 - 'a'	*/	L('a'),	'A',	A(0xb1),A(0xb1),A(0xa1),C('A'),
+/* 31 - 's'	*/	L('s'),	'S',	A(0xb6),A(0xb6),A(0xa6),C('S'),
+/* 32 - 'd'	*/	L('d'),	'D',	A('d'),	A('d'),	A('D'),	C('D'),
+/* 33 - 'f'	*/	L('f'),	'F',	A('f'),	A('f'),	A('F'),	C('F'),
+/* 34 - 'g'	*/	L('g'),	'G',	A('g'),	A('g'),	A('G'),	C('G'),
+/* 35 - 'h'	*/	L('h'),	'H',	A('h'),	A('h'),	A('H'),	C('H'),
+/* 36 - 'j'	*/	L('j'),	'J',	A('j'),	A('j'),	A('J'),	C('J'),
+/* 37 - 'k'	*/	L('k'),	'K',	A('k'),	A('k'),	A('K'),	C('K'),
+/* 38 - 'l'	*/	L('l'),	'L',	A(0xb3),A(0xb3),A(0xa3),C('L'),
+/* 39 - ';'	*/	';',	':',	A(';'),	A(';'),	A(':'),	C('@'),
+/* 40 - '\''	*/	'\'',	'"',	A('\''),A('\''),A('"'),	C('@'),
+/* 41 - '`'	*/	'`',	'~',	A('`'),	A('`'),	A('~'),	C('@'),
+/* 42 - l. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 43 - '\\'	*/	'\\',	'|',	A('\\'),A('\\'),A('|'),	C('\\'),
+/* 44 - 'z'	*/	L('z'),	'Z',	A(0xbf),A(0xbf),A(0xaf),C('Z'),
+/* 45 - 'x'	*/	L('x'),	'X',	A(0xbc),A(0xbc),A(0xac),C('X'),
+/* 46 - 'c'	*/	L('c'),	'C',	A(0xe6),A(0xe6),A(0xc6),C('C'),
+/* 47 - 'v'	*/	L('v'),	'V',	A('v'),	A('v'),	A('V'),	C('V'),
+/* 48 - 'b'	*/	L('b'),	'B',	A('b'),	A('b'),	A('B'),	C('B'),
+/* 49 - 'n'	*/	L('n'),	'N',	A(0xf1),A(0xf1),A(0xd1),C('N'),
+/* 50 - 'm'	*/	L('m'),	'M',	A('m'),	A('m'),	A('M'),	C('M'),
+/* 51 - ','	*/	',',	'<',	A(','),	A(','),	A('<'),	C('@'),
+/* 52 - '.'	*/	'.',	'>',	A('.'),	A('.'),	A('>'),	C('@'),
+/* 53 - '/'	*/	'/',	'?',	A('/'),	A('/'),	A('?'),	C('@'),
+/* 54 - r. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 55 - '*'	*/	'*',	'*',	A('*'),	A('*'),	A('*'),	C('@'),
+/* 56 - ALT	*/	ALT,	ALT,	ALT,	ALT,	ALT,	ALT,
+/* 57 - ' '	*/	' ',	' ',	A(' '),	A(' '),	A(' '),	C('@'),
+/* 58 - CapsLck	*/	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,
+/* 59 - F1	*/	F1,	SF1,	AF1,	AF1,	ASF1,	CF1,
+/* 60 - F2	*/	F2,	SF2,	AF2,	AF2,	ASF2,	CF2,
+/* 61 - F3	*/	F3,	SF3,	AF3,	AF3,	ASF3,	CF3,
+/* 62 - F4	*/	F4,	SF4,	AF4,	AF4,	ASF4,	CF4,
+/* 63 - F5	*/	F5,	SF5,	AF5,	AF5,	ASF5,	CF5,
+/* 64 - F6	*/	F6,	SF6,	AF6,	AF6,	ASF6,	CF6,
+/* 65 - F7	*/	F7,	SF7,	AF7,	AF7,	ASF7,	CF7,
+/* 66 - F8	*/	F8,	SF8,	AF8,	AF8,	ASF8,	CF8,
+/* 67 - F9	*/	F9,	SF9,	AF9,	AF9,	ASF9,	CF9,
+/* 68 - F10	*/	F10,	SF10,	AF10,	AF10,	ASF10,	CF10,
+/* 69 - NumLock	*/	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,
+/* 70 - ScrLock */	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,
+/* 71 - Home	*/	HOME,	'7',	AHOME,	AHOME,	A('7'),	CHOME,	
+/* 72 - CurUp	*/	UP,	'8',	AUP,	AUP,	A('8'),	CUP,
+/* 73 - PgUp	*/	PGUP,	'9',	APGUP,	APGUP,	A('9'),	CPGUP,
+/* 74 - '-'	*/	NMIN,	'-',	ANMIN,	ANMIN,	A('-'),	CNMIN,
+/* 75 - Left	*/	LEFT,	'4',	ALEFT,	ALEFT,	A('4'),	CLEFT,
+/* 76 - MID	*/	MID,	'5',	AMID,	AMID,	A('5'),	CMID,
+/* 77 - Right	*/	RIGHT,	'6',	ARIGHT,	ARIGHT,	A('6'),	CRIGHT,
+/* 78 - '+'	*/	PLUS,	'+',	APLUS,	APLUS,	A('+'),	CPLUS,
+/* 79 - End	*/	END,	'1',	AEND,	AEND,	A('1'),	CEND,
+/* 80 - Down	*/	DOWN,	'2',	ADOWN,	ADOWN,	A('2'),	CDOWN,
+/* 81 - PgDown	*/	PGDN,	'3',	APGDN,	APGDN,	A('3'),	CPGDN,
+/* 82 - Insert	*/	INSRT,	'0',	AINSRT,	AINSRT,	A('0'),	CINSRT,
+/* 83 - Delete	*/	0177,	'.',	A(0177),A(0177),A('.'),	0177,
+/* 84 - Enter	*/	C('M'),	C('M'),	CA('M'),CA('M'),CA('M'),C('J'),
+/* 85 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 86 - ???	*/	'<',	'>',	A('<'),	A('|'),	A('>'),	C('@'),
+/* 87 - F11	*/	F11,	SF11,	AF11,	AF11,	ASF11,	CF11,
+/* 88 - F12	*/	F12,	SF12,	AF12,	AF12,	ASF12,	CF12,
+/* 89 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 90 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 91 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 92 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 93 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 94 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 95 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 96 - EXT_KEY	*/	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,
+/* 97 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 98 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 99 - ???	*/	0,	0,	0,	0,	0,	0,
+/*100 - ???	*/	0,	0,	0,	0,	0,	0,
+/*101 - ???	*/	0,	0,	0,	0,	0,	0,
+/*102 - ???	*/	0,	0,	0,	0,	0,	0,
+/*103 - ???	*/	0,	0,	0,	0,	0,	0,
+/*104 - ???	*/	0,	0,	0,	0,	0,	0,
+/*105 - ???	*/	0,	0,	0,	0,	0,	0,
+/*106 - ???	*/	0,	0,	0,	0,	0,	0,
+/*107 - ???	*/	0,	0,	0,	0,	0,	0,
+/*108 - ???	*/	0,	0,	0,	0,	0,	0,
+/*109 - ???	*/	0,	0,	0,	0,	0,	0,
+/*110 - ???	*/	0,	0,	0,	0,	0,	0,
+/*111 - ???	*/	0,	0,	0,	0,	0,	0,
+/*112 - ???	*/	0,	0,	0,	0,	0,	0,
+/*113 - ???	*/	0,	0,	0,	0,	0,	0,
+/*114 - ???	*/	0,	0,	0,	0,	0,	0,
+/*115 - ???	*/	0,	0,	0,	0,	0,	0,
+/*116 - ???	*/	0,	0,	0,	0,	0,	0,
+/*117 - ???	*/	0,	0,	0,	0,	0,	0,
+/*118 - ???	*/	0,	0,	0,	0,	0,	0,
+/*119 - ???	*/	0,	0,	0,	0,	0,	0,
+/*120 - ???	*/	0,	0,	0,	0,	0,	0,
+/*121 - ???	*/	0,	0,	0,	0,	0,	0,
+/*122 - ???	*/	0,	0,	0,	0,	0,	0,
+/*123 - ???	*/	0,	0,	0,	0,	0,	0,
+/*124 - ???	*/	0,	0,	0,	0,	0,	0,
+/*125 - ???	*/	0,	0,	0,	0,	0,	0,
+/*126 - ???	*/	0,	0,	0,	0,	0,	0,
+/*127 - ???	*/	0,	0,	0,	0,	0,	0
+};
Index: /trunk/minix/drivers/tty/keymaps/scandinavian.src
===================================================================
--- /trunk/minix/drivers/tty/keymaps/scandinavian.src	(revision 9)
+++ /trunk/minix/drivers/tty/keymaps/scandinavian.src	(revision 9)
@@ -0,0 +1,138 @@
+/* Keymap for Scandinavian keyboard. 
+ * by Oliver Reitalu, nolx@nolx.tartu.ee 
+ * preliminary version, 8 Sept 1996  
+ */
+
+u16_t keymap[NR_SCAN_CODES * MAP_COLS] = {
+
+/* scan-code		unsh	Shift	Alt	AltGr	Alt+Sh	Ctrl	*/
+/* ==================================================================== */
+/* 00 - none	*/	0,	0,	0,	0,	0,	0,	
+/* 01 - ESC	*/	C('['),	C('['),	CA('['),C('['),	C('['),	C('['),
+/* 02 - '1'	*/	'1',	'!',	A('1'),	'1',	'!',	C('A'),
+/* 03 - '2'	*/	'2',	'"',	A('2'),	'@',	'@',	C('@'),
+/* 04 - '3'	*/	'3',	'#',	A('3'),	156,	'#',	C('C'),
+/* 05 - '4'	*/	'4',	' ',	A('4'),	'$',	'$',	C('D'),
+/* 06 - '5'	*/	'5',	'%',	A('5'),	'5',	'%',	C('E'),
+/* 07 - '6'	*/	'6',	'&',	A('6'),	'6',	'^',	C('^'),
+/* 08 - '7'	*/	'7',	'/',	A('7'),	'{',	'&',	C('G'),
+/* 09 - '8'	*/	'8',	'(',	A('8'),	'[',	'*',	C('H'),
+/* 10 - '9'	*/	'9',	')',	A('9'),	']',	'(',	C('I'),
+/* 11 - '0'	*/	'0',	'=',	A('0'),	'}',	')',	C('@'),
+/* 12 - '_'	*/	'+',	'?',	0341,	'\\',	'_',	C('_'),
+/* 13 - '='	*/	'\'',	'`',	A('\''),'=',	'+',	C('@'),
+/* 14 - BS	*/	C('H'),	C('H'),	CA('H'),C('H'),	C('H'),	0177,	
+/* 15 - TAB	*/	C('I'),	C('I'),	CA('I'),C('I'),	C('I'),	C('I'),
+/* 16 - 'q'	*/	L('q'),	'Q',	A('q'),	'@',	'Q',	C('Q'),
+/* 17 - 'w'	*/	L('w'),	'W',	A('w'),	'w',	'W',	C('W'),
+/* 18 - 'e'	*/	L('e'),	'E',	A('e'),	'e',	'E',	C('E'),
+/* 19 - 'r'	*/	L('r'),	'R',	A('r'),	'r',	'R',	C('R'),
+/* 20 - 't'	*/	L('t'),	'T',	A('t'),	't',	'T',	C('T'),
+/* 21 - 'y'	*/	L('y'),	'Y',	A('y'),	'y',	'Y',	C('Y'),
+/* 22 - 'u'	*/	L('u'),	'U',	A('u'),	'u',	'U',	C('U'),
+/* 23 - 'i'	*/	L('i'),	'I',	A('i'),	'i',	'I',	C('I'),
+/* 24 - 'o'	*/	L('o'),	'O',	A('o'),	'o',	'O',	C('O'),
+/* 25 - 'p'	*/	L('p'),	'P',	A('p'),	'p',	'P',	C('P'),
+/* 26 - '['	*/	L(134),  143,	0201,	'[',	'{',	C('['),
+/* 27 - ']'	*/	'\"',	'^',	A('+'),	'~',	']',	C(']'),
+/* 28 - CR/LF	*/	C('M'),	C('M'),	CA('M'),C('M'),	C('M'),	C('J'),
+/* 29 - Ctrl	*/	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,
+/* 30 - 'a'	*/	L('a'),	'A',	A('a'),	'a',	'A',	C('A'),
+/* 31 - 's'	*/	L('s'),	'S',	A('s'),	's',	'S',	C('S'),
+/* 32 - 'd'	*/	L('d'),	'D',	A('d'),	'd',	'D',	C('D'),
+/* 33 - 'f'	*/	L('f'),	'F',	A('f'),	'f',	'F',	C('F'),
+/* 34 - 'g'	*/	L('g'),	'G',	A('g'),	'g',	'G',	C('G'),
+/* 35 - 'h'	*/	L('h'),	'H',	A('h'),	'h',	'H',	C('H'),
+/* 36 - 'j'	*/	L('j'),	'J',	A('j'),	'j',	'J',	C('J'),
+/* 37 - 'k'	*/	L('k'),	'K',	A('k'),	'k',	'K',	C('K'),
+/* 38 - 'l'	*/	L('l'),	'L',	A('l'),	'l',	'L',	C('L'),
+/* 39 - ';'	*/	L(0224),0231,	0224,	';',	':',	C('@'),
+/* 40 - '\''	*/	L(0204),0216,	0204,	'\'',	'"',	C('@'),
+/* 41 - '`'	*/	L(21),	171,	A('^'),	'`',	'~',	C('^'),
+/* 42 - SHIFT	*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 43 - '\\'	*/	39,	'*',	A('#'),	'\\',	'|',	C('\\'),
+/* 44 - 'z'	*/	L('z'),	'Z',	A('z'),	'z',	'Z',	C('Z'),
+/* 45 - 'x'	*/	L('x'),	'X',	A('x'),	'x',	'X',	C('X'),
+/* 46 - 'c'	*/	L('c'),	'C',	A('c'),	'c',	'C',	C('C'),
+/* 47 - 'v'	*/	L('v'),	'V',	A('v'),	'v',	'V',	C('V'),
+/* 48 - 'b'	*/	L('b'),	'B',	A('b'),	'b',	'B',	C('B'),
+/* 49 - 'n'	*/	L('n'),	'N',	A('n'),	'n',	'N',	C('N'),
+/* 50 - 'm'	*/	L('m'),	'M',	A('m'),	0346,	'M',	C('M'),
+/* 51 - ','	*/	',',	';',	A(','),	',',	'<',	C('@'),
+/* 52 - '.'	*/	'.',	':',	A('.'),	'.',	'>',	C('@'),
+/* 53 - '/'	*/	'-',	'_',	A('-'),	'/',	'?',	C('_'),
+/* 54 - SHIFT	*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 55 - '*'	*/	'*',	'*',	A('*'),	'*',	'*',	C('@'),
+/* 56 - ALT	*/	ALT,	ALT,	ALT,	ALT,	ALT,	ALT,
+/* 57 - ' '	*/	' ',	' ',	A(' '),	' ',	' ',	C('@'),
+/* 58 - CapsLck	*/	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,
+/* 59 - F1	*/	F1,	SF1,	AF1,	AF1,	ASF1,	CF1,
+/* 60 - F2	*/	F2,	SF2,	AF2,	AF2,	ASF2,	CF2,
+/* 61 - F3	*/	F3,	SF3,	AF3,	AF3,	ASF3,	CF3,
+/* 62 - F4	*/	F4,	SF4,	AF4,	AF4,	ASF4,	CF4,
+/* 63 - F5	*/	F5,	SF5,	AF5,	AF5,	ASF5,	CF5,
+/* 64 - F6	*/	F6,	SF6,	AF6,	AF6,	ASF6,	CF6,
+/* 65 - F7	*/	F7,	SF7,	AF7,	AF7,	ASF7,	CF7,
+/* 66 - F8	*/	F8,	SF8,	AF8,	AF8,	ASF8,	CF8,
+/* 67 - F9	*/	F9,	SF9,	AF9,	AF9,	ASF9,	CF9,
+/* 68 - F10	*/	F10,	SF10,	AF10,	AF10,	ASF10,	CF10,
+/* 69 - NumLock	*/	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,
+/* 70 - ScrLock */	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,
+/* 71 - Home	*/	HOME,	'7',	AHOME,	AHOME,	'7',	CHOME,	
+/* 72 - CurUp	*/	UP,	'8',	AUP,	AUP,	'8',	CUP,
+/* 73 - PgUp	*/	PGUP,	'9',	APGUP,	APGUP,	'9',	CPGUP,
+/* 74 - '-'	*/	NMIN,	'-',	ANMIN,	ANMIN,	'-',	CNMIN,
+/* 75 - Left	*/	LEFT,	'4',	ALEFT,	ALEFT,	'4',	CLEFT,
+/* 76 - MID	*/	MID,	'5',	AMID,	AMID,	'5',	CMID,
+/* 77 - Right	*/	RIGHT,	'6',	ARIGHT,	ARIGHT,	'6',	CRIGHT,
+/* 78 - '+'	*/	PLUS,	'+',	APLUS,	APLUS,	'+',	CPLUS,
+/* 79 - End	*/	END,	'1',	AEND,	AEND,	'1',	CEND,
+/* 80 - Down	*/	DOWN,	'2',	ADOWN,	ADOWN,	'2',	CDOWN,
+/* 81 - PgDown	*/	PGDN,	'3',	APGDN,	APGDN,	'3',	CPGDN,
+/* 82 - Insert	*/	INSRT,	'0',	AINSRT,	AINSRT,	'0',	CINSRT,
+/* 83 - Delete	*/	0177,	'.',	A(0177),0177,	'.',	0177,
+/* 84 - Enter	*/	C('M'),	C('M'),	CA('M'),C('M'),	C('M'),	C('J'),
+/* 85 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 86 - ???	*/	'<',	'>',	A('<'),	'|',	'>',	C('@'),
+/* 87 - F11	*/	F11,	SF11,	AF11,	AF11,	ASF11,	CF11,
+/* 88 - F12	*/	F12,	SF12,	AF12,	AF12,	ASF12,	CF12,
+/* 89 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 90 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 91 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 92 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 93 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 94 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 95 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 96 - EXT_KEY	*/	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,
+/* 97 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 98 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 99 - ???	*/	0,	0,	0,	0,	0,	0,
+/*100 - ???	*/	0,	0,	0,	0,	0,	0,
+/*101 - ???	*/	0,	0,	0,	0,	0,	0,
+/*102 - ???	*/	0,	0,	0,	0,	0,	0,
+/*103 - ???	*/	0,	0,	0,	0,	0,	0,
+/*104 - ???	*/	0,	0,	0,	0,	0,	0,
+/*105 - ???	*/	0,	0,	0,	0,	0,	0,
+/*106 - ???	*/	0,	0,	0,	0,	0,	0,
+/*107 - ???	*/	0,	0,	0,	0,	0,	0,
+/*108 - ???	*/	0,	0,	0,	0,	0,	0,
+/*109 - ???	*/	0,	0,	0,	0,	0,	0,
+/*110 - ???	*/	0,	0,	0,	0,	0,	0,
+/*111 - ???	*/	0,	0,	0,	0,	0,	0,
+/*112 - ???	*/	0,	0,	0,	0,	0,	0,
+/*113 - ???	*/	0,	0,	0,	0,	0,	0,
+/*114 - ???	*/	0,	0,	0,	0,	0,	0,
+/*115 - ???	*/	0,	0,	0,	0,	0,	0,
+/*116 - ???	*/	0,	0,	0,	0,	0,	0,
+/*117 - ???	*/	0,	0,	0,	0,	0,	0,
+/*118 - ???	*/	0,	0,	0,	0,	0,	0,
+/*119 - ???	*/	0,	0,	0,	0,	0,	0,
+/*120 - ???	*/	0,	0,	0,	0,	0,	0,
+/*121 - ???	*/	0,	0,	0,	0,	0,	0,
+/*122 - ???	*/	0,	0,	0,	0,	0,	0,
+/*123 - ???	*/	0,	0,	0,	0,	0,	0,
+/*124 - ???	*/	0,	0,	0,	0,	0,	0,
+/*125 - ???	*/	0,	0,	0,	0,	0,	0,
+/*126 - ???	*/	0,	0,	0,	0,	0,	0,
+/*127 - ???	*/	0,	0,	0,	0,	0,	0
+};
Index: /trunk/minix/drivers/tty/keymaps/spanish.src
===================================================================
--- /trunk/minix/drivers/tty/keymaps/spanish.src	(revision 9)
+++ /trunk/minix/drivers/tty/keymaps/spanish.src	(revision 9)
@@ -0,0 +1,138 @@
+/* Keymap for Spanish MF-2 keyboard. */
+/* Modified by Javier Garcia Martin jawa@inf.deusto.es */
+
+u16_t keymap[NR_SCAN_CODES * MAP_COLS] = {
+
+/* scan-code		!Shift	Shift	Alt	AltGr	Alt+Sh	Ctrl	*/
+/* 
+==================================================================== 
+*/
+/* 00 - none	*/	0,	0,	0,	0,	0,	0,	
+/* 01 - ESC	*/	C('['),	C('['),	CA('['),C('['),	C('['),	C('['),
+/* 02 - '1'	*/	'1',	'!',	A('1'),	'|',	'!',	C('A'),
+/* 03 - '2'	*/	'2',	'"',	A('2'),	'@',	'"',	C('@'),
+/* 04 - '3'	*/	'3',	0372,	A('3'),	'#',	0372,	C('C'),
+/* 05 - '4'	*/	'4',	'$',	A('4'),	'4',	'$',	C('D'),
+/* 06 - '5'	*/	'5',	'%',	A('5'),	'5',	'%',	C('E'),
+/* 07 - '6'	*/	'6',	'&',	A('6'),	0252,	'&',	C('F'),
+/* 08 - '7'	*/	'7',	'/',	A('7'),	'{',	'/',	C('G'),
+/* 09 - '8'	*/	'8',	'(',	A('8'),	'(',	'(',	C('H'),
+/* 10 - '9'	*/	'9',	')',	A('9'),	')',	')',	C('I'),
+/* 11 - '0'	*/	'0',	'=',	A('0'),	'=',	'=',	C('@'),
+/* 12 - '-'	*/	'\'',	'?',	A('\''),'?',	'?',	C('_'),
+/* 13 - '='	*/	0255,	0250,	A(0255),0250,	0250,	C('@'),
+/* 14 - BS	*/	C('H'),	C('H'),	CA('H'),C('H'),	C('H'),	0177,	
+/* 15 - TAB	*/	C('I'),	C('I'),	CA('I'),C('I'),	C('I'),	C('I'),
+/* 16 - 'q'	*/	L('q'),	'Q',	A('q'),	'q',	'Q',	C('Q'),
+/* 17 - 'w'	*/	L('w'),	'W',	A('w'),	'w',	'W',	C('W'),
+/* 18 - 'e'	*/	L('e'),	'E',	A('e'),	'e',	'E',	C('E'),
+/* 19 - 'r'	*/	L('r'),	'R',	A('r'),	'r',	'R',	C('R'),
+/* 20 - 't'	*/	L('t'),	'T',	A('t'),	't',	'T',	C('T'),
+/* 21 - 'y'	*/	L('y'),	'Y',	A('y'),	'y',	'Y',	C('Y'),
+/* 22 - 'u'	*/	L('u'),	'U',	A('u'),	'u',	'U',	C('U'),
+/* 23 - 'i'	*/	L('i'),	'I',	A('i'),	'i',	'I',	C('I'),
+/* 24 - 'o'	*/	L('o'),	'O',	A('o'),	'o',	'O',	C('O'),
+/* 25 - 'p'	*/	L('p'),	'P',	A('p'),	'p',	'P',	C('P'),
+/* 26 - '['	*/	'`',	'^',	A('`'),'[',	'^',	C('['),
+/* 27 - ']'	*/	'+',	'*',	A('+'),	']',	'*',	C(']'),
+/* 28 - CR/LF	*/	C('M'),	C('M'),	CA('M'),C('M'),	C('M'),	C('J'),
+/* 29 - Ctrl	*/	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,
+/* 30 - 'a'	*/	L('a'),	'A',	A('a'),	'a',	'A',	C('A'),
+/* 31 - 's'	*/	L('s'),	'S',	A('s'),	's',	'S',	C('S'),
+/* 32 - 'd'	*/	L('d'),	'D',	A('d'),	'd',	'D',	C('D'),
+/* 33 - 'f'	*/	L('f'),	'F',	A('f'),	'f',	'F',	C('F'),
+/* 34 - 'g'	*/	L('g'),	'G',	A('g'),	'g',	'G',	C('G'),
+/* 35 - 'h'	*/	L('h'),	'H',	A('h'),	'h',	'H',	C('H'),
+/* 36 - 'j'	*/	L('j'),	'J',	A('j'),	'j',	'J',	C('J'),
+/* 37 - 'k'	*/	L('k'),	'K',	A('k'),	'k',	'K',	C('K'),
+/* 38 - 'l'	*/	L('l'),	'L',	A('l'),	'l',	'L',	C('L'),
+/* 39 - ';'	*/	L(0244),0245,	A(0244),0244,	0245,	C('@'),
+/* 40 - '\''	*/	'\'',	'"',	A('\''),'{',	'"',	C('@'),
+/* 41 - '`'	*/	0247,	0246,	A(0247),'\\',	0246,	C('@'),
+/* 42 - l. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 43 - '\\'	*/	L(0207),0200,	A(0207),'}',	0200,	C('@'),
+/* 44 - 'z'	*/	L('z'),	'Z',	A('z'),	'z',	'Z',	C('Z'),
+/* 45 - 'x'	*/	L('x'),	'X',	A('x'),	'x',	'X',	C('X'),
+/* 46 - 'c'	*/	L('c'),	'C',	A('c'),	'c',	'C',	C('C'),
+/* 47 - 'v'	*/	L('v'),	'V',	A('v'),	'v',	'V',	C('V'),
+/* 48 - 'b'	*/	L('b'),	'B',	A('b'),	'b',	'B',	C('B'),
+/* 49 - 'n'	*/	L('n'),	'N',	A('n'),	'n',	'N',	C('N'),
+/* 50 - 'm'	*/	L('m'),	'M',	A('m'),	'm',	'M',	C('M'),
+/* 51 - ','	*/	',',	';',	A(','),	',',	';',	C('@'),
+/* 52 - '.'	*/	'.',	':',	A('.'),	'.',	':',	C('@'),
+/* 53 - '/'	*/	'-',	'_',	A('-'), '-',	'_',	C('@'),
+/* 54 - r. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 55 - '*'	*/	'*',	'*',	A('*'),	'*',	'*',	C('M'),
+/* 56 - ALT	*/	ALT,	ALT,	ALT,	ALT,	ALT,	ALT,
+/* 57 - ' '	*/	' ',	' ',	A(' '),	' ',	' ',	C('@'),
+/* 58 - CapsLck	*/	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,
+/* 59 - F1	*/	F1,	SF1,	AF1,	AF1,	ASF1,	CF1,
+/* 60 - F2	*/	F2,	SF2,	AF2,	AF2,	ASF2,	CF2,
+/* 61 - F3	*/	F3,	SF3,	AF3,	AF3,	ASF3,	CF3,
+/* 62 - F4	*/	F4,	SF4,	AF4,	AF4,	ASF4,	CF4,
+/* 63 - F5	*/	F5,	SF5,	AF5,	AF5,	ASF5,	CF5,
+/* 64 - F6	*/	F6,	SF6,	AF6,	AF6,	ASF6,	CF6,
+/* 65 - F7	*/	F7,	SF7,	AF7,	AF7,	ASF7,	CF7,
+/* 66 - F8	*/	F8,	SF8,	AF8,	AF8,	ASF8,	CF8,
+/* 67 - F9	*/	F9,	SF9,	AF9,	AF9,	ASF9,	CF9,
+/* 68 - F10	*/	F10,	SF10,	AF10,	AF10,	ASF10,	CF10,
+/* 69 - NumLock	*/	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,
+/* 70 - ScrLock */	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,
+/* 71 - Home	*/	HOME,	'7',	AHOME,	AHOME,	'7',	CHOME,	
+/* 72 - CurUp	*/	UP,	'8',	AUP,	AUP,	'8',	CUP,
+/* 73 - PgUp	*/	PGUP,	'9',	APGUP,	APGUP,	'9',	CPGUP,
+/* 74 - '-'	*/	NMIN,	'-',	ANMIN,	ANMIN,	'-',	CNMIN,
+/* 75 - Left	*/	LEFT,	'4',	ALEFT,	ALEFT,	'4',	CLEFT,
+/* 76 - MID	*/	MID,	'5',	AMID,	AMID,	'5',	CMID,
+/* 77 - Right	*/	RIGHT,	'6',	ARIGHT,	ARIGHT,	'6',	CRIGHT,
+/* 78 - '+'	*/	PLUS,	'+',	APLUS,	APLUS,	'+',	CPLUS,
+/* 79 - End	*/	END,	'1',	AEND,	AEND,	'1',	CEND,
+/* 80 - Down	*/	DOWN,	'2',	ADOWN,	ADOWN,	'2',	CDOWN,
+/* 81 - PgDown	*/	PGDN,	'3',	APGDN,	APGDN,	'3',	CPGDN,
+/* 82 - Insert	*/	INSRT,	'0',	AINSRT,	AINSRT,	'0',	CINSRT,
+/* 83 - Delete	*/	0177,	'.',	A(0177),0177,	'.',	0177,
+/* 84 - Enter	*/	C('M'),	C('M'),	CA('M'),C('M'),	C('M'),	C('J'),
+/* 85 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 86 - ???	*/	'<',	'>',	A('<'),	'<',	'>',	C('@'),
+/* 87 - F11	*/	F11,	SF11,	AF11,	AF11,	ASF11,	CF11,
+/* 88 - F12	*/	F12,	SF12,	AF12,	AF12,	ASF12,	CF12,
+/* 89 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 90 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 91 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 92 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 93 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 94 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 95 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 96 - EXT_KEY	*/	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,
+/* 97 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 98 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 99 - ???	*/	0,	0,	0,	0,	0,	0,
+/*100 - ???	*/	0,	0,	0,	0,	0,	0,
+/*101 - ???	*/	0,	0,	0,	0,	0,	0,
+/*102 - ???	*/	0,	0,	0,	0,	0,	0,
+/*103 - ???	*/	0,	0,	0,	0,	0,	0,
+/*104 - ???	*/	0,	0,	0,	0,	0,	0,
+/*105 - ???	*/	0,	0,	0,	0,	0,	0,
+/*106 - ???	*/	0,	0,	0,	0,	0,	0,
+/*107 - ???	*/	0,	0,	0,	0,	0,	0,
+/*108 - ???	*/	0,	0,	0,	0,	0,	0,
+/*109 - ???	*/	0,	0,	0,	0,	0,	0,
+/*110 - ???	*/	0,	0,	0,	0,	0,	0,
+/*111 - ???	*/	0,	0,	0,	0,	0,	0,
+/*112 - ???	*/	0,	0,	0,	0,	0,	0,
+/*113 - ???	*/	0,	0,	0,	0,	0,	0,
+/*114 - ???	*/	0,	0,	0,	0,	0,	0,
+/*115 - ???	*/	0,	0,	0,	0,	0,	0,
+/*116 - ???	*/	0,	0,	0,	0,	0,	0,
+/*117 - ???	*/	0,	0,	0,	0,	0,	0,
+/*118 - ???	*/	0,	0,	0,	0,	0,	0,
+/*119 - ???	*/	0,	0,	0,	0,	0,	0,
+/*120 - ???	*/	0,	0,	0,	0,	0,	0,
+/*121 - ???	*/	0,	0,	0,	0,	0,	0,
+/*122 - ???	*/	0,	0,	0,	0,	0,	0,
+/*123 - ???	*/	0,	0,	0,	0,	0,	0,
+/*124 - ???	*/	0,	0,	0,	0,	0,	0,
+/*125 - ???	*/	0,	0,	0,	0,	0,	0,
+/*126 - ???	*/	0,	0,	0,	0,	0,	0,
+/*127 - ???	*/	0,	0,	0,	0,	0,	0
+};
Index: /trunk/minix/drivers/tty/keymaps/uk.src
===================================================================
--- /trunk/minix/drivers/tty/keymaps/uk.src	(revision 9)
+++ /trunk/minix/drivers/tty/keymaps/uk.src	(revision 9)
@@ -0,0 +1,135 @@
+/* Keymap for standard UK keyboard.			Author: Darren Mason */
+
+u16_t keymap[NR_SCAN_CODES * MAP_COLS] = {
+
+/* scan-code		!Shift	Shift	Alt1	Alt2	Alt+Sh	Ctrl	*/
+/* ==================================================================== */
+/* 00 - none	*/	0,	0,	0,	0,	0,	0,	
+/* 01 - ESC	*/	C('['),	C('['),	CA('['),CA('['),CA('['),C('['),
+/* 02 - '1'	*/	'1',	'!',	A('1'),	A('1'),	A('!'),	C('A'),
+/* 03 - '2'	*/	'2',	'"',	A('2'),	A('2'),	A('@'),	C('@'),
+/* 04 - '3'	*/	'3',	156,	A('3'),	A('3'),	A(156),	C('C'),
+/* 05 - '4'	*/	'4',	'$',	A('4'),	A('4'),	A('$'),	C('D'),
+/* 06 - '5'	*/	'5',	'%',	A('5'),	A('5'),	A('%'),	C('E'),
+/* 07 - '6'	*/	'6',	'^',	A('6'),	A('6'),	A('^'),	C('^'),
+/* 08 - '7'	*/	'7',	'&',	A('7'),	A('7'),	A('&'),	C('G'),
+/* 09 - '8'	*/	'8',	'*',	A('8'),	A('8'),	A('*'),	C('H'),
+/* 10 - '9'	*/	'9',	'(',	A('9'),	A('9'),	A('('),	C('I'),
+/* 11 - '0'	*/	'0',	')',	A('0'),	A('0'),	A(')'),	C('@'),
+/* 12 - '-'	*/	'-',	'_',	A('-'),	A('-'),	A('_'),	C('_'),
+/* 13 - '='	*/	'=',	'+',	A('='),	A('='),	A('+'),	C('@'),
+/* 14 - BS	*/	C('H'),	C('H'),	CA('H'),CA('H'),CA('H'),0177,	
+/* 15 - TAB	*/	C('I'),	C('I'),	CA('I'),CA('I'),CA('I'),C('I'),
+/* 16 - 'q'	*/	L('q'),	'Q',	A('q'),	A('q'),	A('Q'),	C('Q'),
+/* 17 - 'w'	*/	L('w'),	'W',	A('w'),	A('w'),	A('W'),	C('W'),
+/* 18 - 'e'	*/	L('e'),	'E',	A('e'),	A('e'),	A('E'),	C('E'),
+/* 19 - 'r'	*/	L('r'),	'R',	A('r'),	A('r'),	A('R'),	C('R'),
+/* 20 - 't'	*/	L('t'),	'T',	A('t'),	A('t'),	A('T'),	C('T'),
+/* 21 - 'y'	*/	L('y'),	'Y',	A('y'),	A('y'),	A('Y'),	C('Y'),
+/* 22 - 'u'	*/	L('u'),	'U',	A('u'),	A('u'),	A('U'),	C('U'),
+/* 23 - 'i'	*/	L('i'),	'I',	A('i'),	A('i'),	A('I'),	C('I'),
+/* 24 - 'o'	*/	L('o'),	'O',	A('o'),	A('o'),	A('O'),	C('O'),
+/* 25 - 'p'	*/	L('p'),	'P',	A('p'),	A('p'),	A('P'),	C('P'),
+/* 26 - '['	*/	'[',	'{',	A('['),	A('['),	A('{'),	C('['),
+/* 27 - ']'	*/	']',	'}',	A(']'),	A(']'),	A('}'),	C(']'),
+/* 28 - CR/LF	*/	C('M'),	C('M'),	CA('M'),CA('M'),CA('M'),C('J'),
+/* 29 - Ctrl	*/	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,
+/* 30 - 'a'	*/	L('a'),	'A',	A('a'),	A('a'),	A('A'),	C('A'),
+/* 31 - 's'	*/	L('s'),	'S',	A('s'),	A('s'),	A('S'),	C('S'),
+/* 32 - 'd'	*/	L('d'),	'D',	A('d'),	A('d'),	A('D'),	C('D'),
+/* 33 - 'f'	*/	L('f'),	'F',	A('f'),	A('f'),	A('F'),	C('F'),
+/* 34 - 'g'	*/	L('g'),	'G',	A('g'),	A('g'),	A('G'),	C('G'),
+/* 35 - 'h'	*/	L('h'),	'H',	A('h'),	A('h'),	A('H'),	C('H'),
+/* 36 - 'j'	*/	L('j'),	'J',	A('j'),	A('j'),	A('J'),	C('J'),
+/* 37 - 'k'	*/	L('k'),	'K',	A('k'),	A('k'),	A('K'),	C('K'),
+/* 38 - 'l'	*/	L('l'),	'L',	A('l'),	A('l'),	A('L'),	C('L'),
+/* 39 - ';'	*/	';',	':',	A(';'),	A(';'),	A(':'),	C('@'),
+/* 40 - '\''	*/	'\'',	'@',	A('\''),A('\''),A('"'),	C('@'),
+/* 41 - '`'	*/	'`',	'~',	A('`'),	A('`'),	A('~'),	C('@'),
+/* 42 - l. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 43 - '#'	*/	'#',	'~',	A('#'),	A('#'),	A('~'),	C('#'),
+/* 44 - 'z'	*/	L('z'),	'Z',	A('z'),	A('z'),	A('Z'),	C('Z'),
+/* 45 - 'x'	*/	L('x'),	'X',	A('x'),	A('x'),	A('X'),	C('X'),
+/* 46 - 'c'	*/	L('c'),	'C',	A('c'),	A('c'),	A('C'),	C('C'),
+/* 47 - 'v'	*/	L('v'),	'V',	A('v'),	A('v'),	A('V'),	C('V'),
+/* 48 - 'b'	*/	L('b'),	'B',	A('b'),	A('b'),	A('B'),	C('B'),
+/* 49 - 'n'	*/	L('n'),	'N',	A('n'),	A('n'),	A('N'),	C('N'),
+/* 50 - 'm'	*/	L('m'),	'M',	A('m'),	A('m'),	A('M'),	C('M'),
+/* 51 - ','	*/	',',	'<',	A(','),	A(','),	A('<'),	C('@'),
+/* 52 - '.'	*/	'.',	'>',	A('.'),	A('.'),	A('>'),	C('@'),
+/* 53 - '/'	*/	'/',	'?',	A('/'),	A('/'),	A('?'),	C('@'),
+/* 54 - r. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 55 - '*'	*/	'*',	'*',	A('*'),	A('*'),	A('*'),	C('@'),
+/* 56 - ALT	*/	ALT,	ALT,	ALT,	ALT,	ALT,	ALT,
+/* 57 - ' '	*/	' ',	' ',	A(' '),	A(' '),	A(' '),	C('@'),
+/* 58 - CapsLck	*/	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,
+/* 59 - F1	*/	F1,	SF1,	AF1,	AF1,	ASF1,	CF1,
+/* 60 - F2	*/	F2,	SF2,	AF2,	AF2,	ASF2,	CF2,
+/* 61 - F3	*/	F3,	SF3,	AF3,	AF3,	ASF3,	CF3,
+/* 62 - F4	*/	F4,	SF4,	AF4,	AF4,	ASF4,	CF4,
+/* 63 - F5	*/	F5,	SF5,	AF5,	AF5,	ASF5,	CF5,
+/* 64 - F6	*/	F6,	SF6,	AF6,	AF6,	ASF6,	CF6,
+/* 65 - F7	*/	F7,	SF7,	AF7,	AF7,	ASF7,	CF7,
+/* 66 - F8	*/	F8,	SF8,	AF8,	AF8,	ASF8,	CF8,
+/* 67 - F9	*/	F9,	SF9,	AF9,	AF9,	ASF9,	CF9,
+/* 68 - F10	*/	F10,	SF10,	AF10,	AF10,	ASF10,	CF10,
+/* 69 - NumLock	*/	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,
+/* 70 - ScrLock */	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,
+/* 71 - Home	*/	HOME,	'7',	AHOME,	AHOME,	A('7'),	CHOME,	
+/* 72 - CurUp	*/	UP,	'8',	AUP,	AUP,	A('8'),	CUP,
+/* 73 - PgUp	*/	PGUP,	'9',	APGUP,	APGUP,	A('9'),	CPGUP,
+/* 74 - '-'	*/	NMIN,	'-',	ANMIN,	ANMIN,	A('-'),	CNMIN,
+/* 75 - Left	*/	LEFT,	'4',	ALEFT,	ALEFT,	A('4'),	CLEFT,
+/* 76 - MID	*/	MID,	'5',	AMID,	AMID,	A('5'),	CMID,
+/* 77 - Right	*/	RIGHT,	'6',	ARIGHT,	ARIGHT,	A('6'),	CRIGHT,
+/* 78 - '+'	*/	PLUS,	'+',	APLUS,	APLUS,	A('+'),	CPLUS,
+/* 79 - End	*/	END,	'1',	AEND,	AEND,	A('1'),	CEND,
+/* 80 - Down	*/	DOWN,	'2',	ADOWN,	ADOWN,	A('2'),	CDOWN,
+/* 81 - PgDown	*/	PGDN,	'3',	APGDN,	APGDN,	A('3'),	CPGDN,
+/* 82 - Insert	*/	INSRT,	'0',	AINSRT,	AINSRT,	A('0'),	CINSRT,
+/* 83 - Delete	*/	0177,	'.',	A(0177),A(0177),A('.'),	0177,
+/* 84 - Enter	*/	C('M'),	C('M'),	CA('M'),CA('M'),CA('M'),C('J'),
+/* 85 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 86 - ???	*/	'\\',	'|',	A('\\'),A('|'),	A('|'),	C('@'),
+/* 87 - F11	*/	F11,	SF11,	AF11,	AF11,	ASF11,	CF11,
+/* 88 - F12	*/	F12,	SF12,	AF12,	AF12,	ASF12,	CF12,
+/* 89 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 90 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 91 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 92 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 93 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 94 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 95 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 96 - EXT_KEY	*/	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,
+/* 97 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 98 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 99 - ???	*/	0,	0,	0,	0,	0,	0,
+/*100 - ???	*/	0,	0,	0,	0,	0,	0,
+/*101 - ???	*/	0,	0,	0,	0,	0,	0,
+/*102 - ???	*/	0,	0,	0,	0,	0,	0,
+/*103 - ???	*/	0,	0,	0,	0,	0,	0,
+/*104 - ???	*/	0,	0,	0,	0,	0,	0,
+/*105 - ???	*/	0,	0,	0,	0,	0,	0,
+/*106 - ???	*/	0,	0,	0,	0,	0,	0,
+/*107 - ???	*/	0,	0,	0,	0,	0,	0,
+/*108 - ???	*/	0,	0,	0,	0,	0,	0,
+/*109 - ???	*/	0,	0,	0,	0,	0,	0,
+/*110 - ???	*/	0,	0,	0,	0,	0,	0,
+/*111 - ???	*/	0,	0,	0,	0,	0,	0,
+/*112 - ???	*/	0,	0,	0,	0,	0,	0,
+/*113 - ???	*/	0,	0,	0,	0,	0,	0,
+/*114 - ???	*/	0,	0,	0,	0,	0,	0,
+/*115 - ???	*/	0,	0,	0,	0,	0,	0,
+/*116 - ???	*/	0,	0,	0,	0,	0,	0,
+/*117 - ???	*/	0,	0,	0,	0,	0,	0,
+/*118 - ???	*/	0,	0,	0,	0,	0,	0,
+/*119 - ???	*/	0,	0,	0,	0,	0,	0,
+/*120 - ???	*/	0,	0,	0,	0,	0,	0,
+/*121 - ???	*/	0,	0,	0,	0,	0,	0,
+/*122 - ???	*/	0,	0,	0,	0,	0,	0,
+/*123 - ???	*/	0,	0,	0,	0,	0,	0,
+/*124 - ???	*/	0,	0,	0,	0,	0,	0,
+/*125 - ???	*/	0,	0,	0,	0,	0,	0,
+/*126 - ???	*/	0,	0,	0,	0,	0,	0,
+/*127 - ???	*/	0,	0,	0,	0,	0,	0
+};
Index: /trunk/minix/drivers/tty/keymaps/us-std.src
===================================================================
--- /trunk/minix/drivers/tty/keymaps/us-std.src	(revision 9)
+++ /trunk/minix/drivers/tty/keymaps/us-std.src	(revision 9)
@@ -0,0 +1,135 @@
+/* Keymap for US MF-2 keyboard. */
+
+u16_t keymap[NR_SCAN_CODES * MAP_COLS] = {
+
+/* scan-code		!Shift	Shift	Alt1	Alt2	Alt+Sh	Ctrl	*/
+/* ==================================================================== */
+/* 00 - none	*/	0,	0,	0,	0,	0,	0,	
+/* 01 - ESC	*/	C('['),	C('['),	CA('['),CA('['),CA('['),C('['),
+/* 02 - '1'	*/	'1',	'!',	A('1'),	A('1'),	A('!'),	C('A'),
+/* 03 - '2'	*/	'2',	'@',	A('2'),	A('2'),	A('@'),	C('@'),
+/* 04 - '3'	*/	'3',	'#',	A('3'),	A('3'),	A('#'),	C('C'),
+/* 05 - '4'	*/	'4',	'$',	A('4'),	A('4'),	A('$'),	C('D'),
+/* 06 - '5'	*/	'5',	'%',	A('5'),	A('5'),	A('%'),	C('E'),
+/* 07 - '6'	*/	'6',	'^',	A('6'),	A('6'),	A('^'),	C('^'),
+/* 08 - '7'	*/	'7',	'&',	A('7'),	A('7'),	A('&'),	C('G'),
+/* 09 - '8'	*/	'8',	'*',	A('8'),	A('8'),	A('*'),	C('H'),
+/* 10 - '9'	*/	'9',	'(',	A('9'),	A('9'),	A('('),	C('I'),
+/* 11 - '0'	*/	'0',	')',	A('0'),	A('0'),	A(')'),	C('@'),
+/* 12 - '-'	*/	'-',	'_',	A('-'),	A('-'),	A('_'),	C('_'),
+/* 13 - '='	*/	'=',	'+',	A('='),	A('='),	A('+'),	C('@'),
+/* 14 - BS	*/	C('H'),	C('H'),	CA('H'),CA('H'),CA('H'),0177,	
+/* 15 - TAB	*/	C('I'),	C('I'),	CA('I'),CA('I'),CA('I'),C('I'),
+/* 16 - 'q'	*/	L('q'),	'Q',	A('q'),	A('q'),	A('Q'),	C('Q'),
+/* 17 - 'w'	*/	L('w'),	'W',	A('w'),	A('w'),	A('W'),	C('W'),
+/* 18 - 'e'	*/	L('e'),	'E',	A('e'),	A('e'),	A('E'),	C('E'),
+/* 19 - 'r'	*/	L('r'),	'R',	A('r'),	A('r'),	A('R'),	C('R'),
+/* 20 - 't'	*/	L('t'),	'T',	A('t'),	A('t'),	A('T'),	C('T'),
+/* 21 - 'y'	*/	L('y'),	'Y',	A('y'),	A('y'),	A('Y'),	C('Y'),
+/* 22 - 'u'	*/	L('u'),	'U',	A('u'),	A('u'),	A('U'),	C('U'),
+/* 23 - 'i'	*/	L('i'),	'I',	A('i'),	A('i'),	A('I'),	C('I'),
+/* 24 - 'o'	*/	L('o'),	'O',	A('o'),	A('o'),	A('O'),	C('O'),
+/* 25 - 'p'	*/	L('p'),	'P',	A('p'),	A('p'),	A('P'),	C('P'),
+/* 26 - '['	*/	'[',	'{',	A('['),	A('['),	A('{'),	C('['),
+/* 27 - ']'	*/	']',	'}',	A(']'),	A(']'),	A('}'),	C(']'),
+/* 28 - CR/LF	*/	C('M'),	C('M'),	CA('M'),CA('M'),CA('M'),C('J'),
+/* 29 - Ctrl	*/	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,
+/* 30 - 'a'	*/	L('a'),	'A',	A('a'),	A('a'),	A('A'),	C('A'),
+/* 31 - 's'	*/	L('s'),	'S',	A('s'),	A('s'),	A('S'),	C('S'),
+/* 32 - 'd'	*/	L('d'),	'D',	A('d'),	A('d'),	A('D'),	C('D'),
+/* 33 - 'f'	*/	L('f'),	'F',	A('f'),	A('f'),	A('F'),	C('F'),
+/* 34 - 'g'	*/	L('g'),	'G',	A('g'),	A('g'),	A('G'),	C('G'),
+/* 35 - 'h'	*/	L('h'),	'H',	A('h'),	A('h'),	A('H'),	C('H'),
+/* 36 - 'j'	*/	L('j'),	'J',	A('j'),	A('j'),	A('J'),	C('J'),
+/* 37 - 'k'	*/	L('k'),	'K',	A('k'),	A('k'),	A('K'),	C('K'),
+/* 38 - 'l'	*/	L('l'),	'L',	A('l'),	A('l'),	A('L'),	C('L'),
+/* 39 - ';'	*/	';',	':',	A(';'),	A(';'),	A(':'),	C('@'),
+/* 40 - '\''	*/	'\'',	'"',	A('\''),A('\''),A('"'),	C('@'),
+/* 41 - '`'	*/	'`',	'~',	A('`'),	A('`'),	A('~'),	C('@'),
+/* 42 - l. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 43 - '\\'	*/	'\\',	'|',	A('\\'),A('\\'),A('|'),	C('\\'),
+/* 44 - 'z'	*/	L('z'),	'Z',	A('z'),	A('z'),	A('Z'),	C('Z'),
+/* 45 - 'x'	*/	L('x'),	'X',	A('x'),	A('x'),	A('X'),	C('X'),
+/* 46 - 'c'	*/	L('c'),	'C',	A('c'),	A('c'),	A('C'),	C('C'),
+/* 47 - 'v'	*/	L('v'),	'V',	A('v'),	A('v'),	A('V'),	C('V'),
+/* 48 - 'b'	*/	L('b'),	'B',	A('b'),	A('b'),	A('B'),	C('B'),
+/* 49 - 'n'	*/	L('n'),	'N',	A('n'),	A('n'),	A('N'),	C('N'),
+/* 50 - 'm'	*/	L('m'),	'M',	A('m'),	A('m'),	A('M'),	C('M'),
+/* 51 - ','	*/	',',	'<',	A(','),	A(','),	A('<'),	C('@'),
+/* 52 - '.'	*/	'.',	'>',	A('.'),	A('.'),	A('>'),	C('@'),
+/* 53 - '/'	*/	'/',	'?',	A('/'),	A('/'),	A('?'),	C('@'),
+/* 54 - r. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 55 - '*'	*/	'*',	'*',	A('*'),	A('*'),	A('*'),	C('@'),
+/* 56 - ALT	*/	ALT,	ALT,	ALT,	ALT,	ALT,	ALT,
+/* 57 - ' '	*/	' ',	' ',	A(' '),	A(' '),	A(' '),	C('@'),
+/* 58 - CapsLck	*/	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,
+/* 59 - F1	*/	F1,	SF1,	AF1,	AF1,	ASF1,	CF1,
+/* 60 - F2	*/	F2,	SF2,	AF2,	AF2,	ASF2,	CF2,
+/* 61 - F3	*/	F3,	SF3,	AF3,	AF3,	ASF3,	CF3,
+/* 62 - F4	*/	F4,	SF4,	AF4,	AF4,	ASF4,	CF4,
+/* 63 - F5	*/	F5,	SF5,	AF5,	AF5,	ASF5,	CF5,
+/* 64 - F6	*/	F6,	SF6,	AF6,	AF6,	ASF6,	CF6,
+/* 65 - F7	*/	F7,	SF7,	AF7,	AF7,	ASF7,	CF7,
+/* 66 - F8	*/	F8,	SF8,	AF8,	AF8,	ASF8,	CF8,
+/* 67 - F9	*/	F9,	SF9,	AF9,	AF9,	ASF9,	CF9,
+/* 68 - F10	*/	F10,	SF10,	AF10,	AF10,	ASF10,	CF10,
+/* 69 - NumLock	*/	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,
+/* 70 - ScrLock */	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,
+/* 71 - Home	*/	HOME,	'7',	AHOME,	AHOME,	A('7'),	CHOME,	
+/* 72 - CurUp	*/	UP,	'8',	AUP,	AUP,	A('8'),	CUP,
+/* 73 - PgUp	*/	PGUP,	'9',	APGUP,	APGUP,	A('9'),	CPGUP,
+/* 74 - '-'	*/	NMIN,	'-',	ANMIN,	ANMIN,	A('-'),	CNMIN,
+/* 75 - Left	*/	LEFT,	'4',	ALEFT,	ALEFT,	A('4'),	CLEFT,
+/* 76 - MID	*/	MID,	'5',	AMID,	AMID,	A('5'),	CMID,
+/* 77 - Right	*/	RIGHT,	'6',	ARIGHT,	ARIGHT,	A('6'),	CRIGHT,
+/* 78 - '+'	*/	PLUS,	'+',	APLUS,	APLUS,	A('+'),	CPLUS,
+/* 79 - End	*/	END,	'1',	AEND,	AEND,	A('1'),	CEND,
+/* 80 - Down	*/	DOWN,	'2',	ADOWN,	ADOWN,	A('2'),	CDOWN,
+/* 81 - PgDown	*/	PGDN,	'3',	APGDN,	APGDN,	A('3'),	CPGDN,
+/* 82 - Insert	*/	INSRT,	'0',	AINSRT,	AINSRT,	A('0'),	CINSRT,
+/* 83 - Delete	*/	0177,	'.',	A(0177),A(0177),A('.'),	0177,
+/* 84 - Enter	*/	C('M'),	C('M'),	CA('M'),CA('M'),CA('M'),C('J'),
+/* 85 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 86 - ???	*/	'<',	'>',	A('<'),	A('|'),	A('>'),	C('@'),
+/* 87 - F11	*/	F11,	SF11,	AF11,	AF11,	ASF11,	CF11,
+/* 88 - F12	*/	F12,	SF12,	AF12,	AF12,	ASF12,	CF12,
+/* 89 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 90 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 91 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 92 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 93 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 94 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 95 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 96 - EXT_KEY	*/	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,
+/* 97 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 98 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 99 - ???	*/	0,	0,	0,	0,	0,	0,
+/*100 - ???	*/	0,	0,	0,	0,	0,	0,
+/*101 - ???	*/	0,	0,	0,	0,	0,	0,
+/*102 - ???	*/	0,	0,	0,	0,	0,	0,
+/*103 - ???	*/	0,	0,	0,	0,	0,	0,
+/*104 - ???	*/	0,	0,	0,	0,	0,	0,
+/*105 - ???	*/	0,	0,	0,	0,	0,	0,
+/*106 - ???	*/	0,	0,	0,	0,	0,	0,
+/*107 - ???	*/	0,	0,	0,	0,	0,	0,
+/*108 - ???	*/	0,	0,	0,	0,	0,	0,
+/*109 - ???	*/	0,	0,	0,	0,	0,	0,
+/*110 - ???	*/	0,	0,	0,	0,	0,	0,
+/*111 - ???	*/	0,	0,	0,	0,	0,	0,
+/*112 - ???	*/	0,	0,	0,	0,	0,	0,
+/*113 - ???	*/	0,	0,	0,	0,	0,	0,
+/*114 - ???	*/	0,	0,	0,	0,	0,	0,
+/*115 - ???	*/	0,	0,	0,	0,	0,	0,
+/*116 - ???	*/	0,	0,	0,	0,	0,	0,
+/*117 - ???	*/	0,	0,	0,	0,	0,	0,
+/*118 - ???	*/	0,	0,	0,	0,	0,	0,
+/*119 - ???	*/	0,	0,	0,	0,	0,	0,
+/*120 - ???	*/	0,	0,	0,	0,	0,	0,
+/*121 - ???	*/	0,	0,	0,	0,	0,	0,
+/*122 - ???	*/	0,	0,	0,	0,	0,	0,
+/*123 - ???	*/	0,	0,	0,	0,	0,	0,
+/*124 - ???	*/	0,	0,	0,	0,	0,	0,
+/*125 - ???	*/	0,	0,	0,	0,	0,	0,
+/*126 - ???	*/	0,	0,	0,	0,	0,	0,
+/*127 - ???	*/	0,	0,	0,	0,	0,	0
+};
Index: /trunk/minix/drivers/tty/keymaps/us-swap.src
===================================================================
--- /trunk/minix/drivers/tty/keymaps/us-swap.src	(revision 9)
+++ /trunk/minix/drivers/tty/keymaps/us-swap.src	(revision 9)
@@ -0,0 +1,135 @@
+/* Keymap for US MF-2 keyboard with the Caps Lock and Control key swapped. */
+
+u16_t keymap[NR_SCAN_CODES * MAP_COLS] = {
+
+/* scan-code		!Shift	Shift	Alt1	Alt2	Alt+Sh	Ctrl	*/
+/* ==================================================================== */
+/* 00 - none	*/	0,	0,	0,	0,	0,	0,	
+/* 01 - ESC	*/	C('['),	C('['),	CA('['),CA('['),CA('['),C('['),
+/* 02 - '1'	*/	'1',	'!',	A('1'),	A('1'),	A('!'),	C('A'),
+/* 03 - '2'	*/	'2',	'@',	A('2'),	A('2'),	A('@'),	C('@'),
+/* 04 - '3'	*/	'3',	'#',	A('3'),	A('3'),	A('#'),	C('C'),
+/* 05 - '4'	*/	'4',	'$',	A('4'),	A('4'),	A('$'),	C('D'),
+/* 06 - '5'	*/	'5',	'%',	A('5'),	A('5'),	A('%'),	C('E'),
+/* 07 - '6'	*/	'6',	'^',	A('6'),	A('6'),	A('^'),	C('^'),
+/* 08 - '7'	*/	'7',	'&',	A('7'),	A('7'),	A('&'),	C('G'),
+/* 09 - '8'	*/	'8',	'*',	A('8'),	A('8'),	A('*'),	C('H'),
+/* 10 - '9'	*/	'9',	'(',	A('9'),	A('9'),	A('('),	C('I'),
+/* 11 - '0'	*/	'0',	')',	A('0'),	A('0'),	A(')'),	C('@'),
+/* 12 - '-'	*/	'-',	'_',	A('-'),	A('-'),	A('_'),	C('_'),
+/* 13 - '='	*/	'=',	'+',	A('='),	A('='),	A('+'),	C('@'),
+/* 14 - BS	*/	C('H'),	C('H'),	CA('H'),CA('H'),CA('H'),0177,	
+/* 15 - TAB	*/	C('I'),	C('I'),	CA('I'),CA('I'),CA('I'),C('I'),
+/* 16 - 'q'	*/	L('q'),	'Q',	A('q'),	A('q'),	A('Q'),	C('Q'),
+/* 17 - 'w'	*/	L('w'),	'W',	A('w'),	A('w'),	A('W'),	C('W'),
+/* 18 - 'e'	*/	L('e'),	'E',	A('e'),	A('e'),	A('E'),	C('E'),
+/* 19 - 'r'	*/	L('r'),	'R',	A('r'),	A('r'),	A('R'),	C('R'),
+/* 20 - 't'	*/	L('t'),	'T',	A('t'),	A('t'),	A('T'),	C('T'),
+/* 21 - 'y'	*/	L('y'),	'Y',	A('y'),	A('y'),	A('Y'),	C('Y'),
+/* 22 - 'u'	*/	L('u'),	'U',	A('u'),	A('u'),	A('U'),	C('U'),
+/* 23 - 'i'	*/	L('i'),	'I',	A('i'),	A('i'),	A('I'),	C('I'),
+/* 24 - 'o'	*/	L('o'),	'O',	A('o'),	A('o'),	A('O'),	C('O'),
+/* 25 - 'p'	*/	L('p'),	'P',	A('p'),	A('p'),	A('P'),	C('P'),
+/* 26 - '['	*/	'[',	'{',	A('['),	A('['),	A('{'),	C('['),
+/* 27 - ']'	*/	']',	'}',	A(']'),	A(']'),	A('}'),	C(']'),
+/* 28 - CR/LF	*/	C('M'),	C('M'),	CA('M'),CA('M'),CA('M'),C('J'),
+/* 29 - Ctrl	*/	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,	CALOCK,
+/* 30 - 'a'	*/	L('a'),	'A',	A('a'),	A('a'),	A('A'),	C('A'),
+/* 31 - 's'	*/	L('s'),	'S',	A('s'),	A('s'),	A('S'),	C('S'),
+/* 32 - 'd'	*/	L('d'),	'D',	A('d'),	A('d'),	A('D'),	C('D'),
+/* 33 - 'f'	*/	L('f'),	'F',	A('f'),	A('f'),	A('F'),	C('F'),
+/* 34 - 'g'	*/	L('g'),	'G',	A('g'),	A('g'),	A('G'),	C('G'),
+/* 35 - 'h'	*/	L('h'),	'H',	A('h'),	A('h'),	A('H'),	C('H'),
+/* 36 - 'j'	*/	L('j'),	'J',	A('j'),	A('j'),	A('J'),	C('J'),
+/* 37 - 'k'	*/	L('k'),	'K',	A('k'),	A('k'),	A('K'),	C('K'),
+/* 38 - 'l'	*/	L('l'),	'L',	A('l'),	A('l'),	A('L'),	C('L'),
+/* 39 - ';'	*/	';',	':',	A(';'),	A(';'),	A(':'),	C('@'),
+/* 40 - '\''	*/	'\'',	'"',	A('\''),A('\''),A('"'),	C('@'),
+/* 41 - '`'	*/	'`',	'~',	A('`'),	A('`'),	A('~'),	C('@'),
+/* 42 - l. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 43 - '\\'	*/	'\\',	'|',	A('\\'),A('\\'),A('|'),	C('\\'),
+/* 44 - 'z'	*/	L('z'),	'Z',	A('z'),	A('z'),	A('Z'),	C('Z'),
+/* 45 - 'x'	*/	L('x'),	'X',	A('x'),	A('x'),	A('X'),	C('X'),
+/* 46 - 'c'	*/	L('c'),	'C',	A('c'),	A('c'),	A('C'),	C('C'),
+/* 47 - 'v'	*/	L('v'),	'V',	A('v'),	A('v'),	A('V'),	C('V'),
+/* 48 - 'b'	*/	L('b'),	'B',	A('b'),	A('b'),	A('B'),	C('B'),
+/* 49 - 'n'	*/	L('n'),	'N',	A('n'),	A('n'),	A('N'),	C('N'),
+/* 50 - 'm'	*/	L('m'),	'M',	A('m'),	A('m'),	A('M'),	C('M'),
+/* 51 - ','	*/	',',	'<',	A(','),	A(','),	A('<'),	C('@'),
+/* 52 - '.'	*/	'.',	'>',	A('.'),	A('.'),	A('>'),	C('@'),
+/* 53 - '/'	*/	'/',	'?',	A('/'),	A('/'),	A('?'),	C('@'),
+/* 54 - r. SHIFT*/	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,	SHIFT,
+/* 55 - '*'	*/	'*',	'*',	A('*'),	A('*'),	A('*'),	C('@'),
+/* 56 - ALT	*/	ALT,	ALT,	ALT,	ALT,	ALT,	ALT,
+/* 57 - ' '	*/	' ',	' ',	A(' '),	A(' '),	A(' '),	C('@'),
+/* 58 - CapsLck	*/	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,	CTRL,
+/* 59 - F1	*/	F1,	SF1,	AF1,	AF1,	ASF1,	CF1,
+/* 60 - F2	*/	F2,	SF2,	AF2,	AF2,	ASF2,	CF2,
+/* 61 - F3	*/	F3,	SF3,	AF3,	AF3,	ASF3,	CF3,
+/* 62 - F4	*/	F4,	SF4,	AF4,	AF4,	ASF4,	CF4,
+/* 63 - F5	*/	F5,	SF5,	AF5,	AF5,	ASF5,	CF5,
+/* 64 - F6	*/	F6,	SF6,	AF6,	AF6,	ASF6,	CF6,
+/* 65 - F7	*/	F7,	SF7,	AF7,	AF7,	ASF7,	CF7,
+/* 66 - F8	*/	F8,	SF8,	AF8,	AF8,	ASF8,	CF8,
+/* 67 - F9	*/	F9,	SF9,	AF9,	AF9,	ASF9,	CF9,
+/* 68 - F10	*/	F10,	SF10,	AF10,	AF10,	ASF10,	CF10,
+/* 69 - NumLock	*/	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,	NLOCK,
+/* 70 - ScrLock */	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,	SLOCK,
+/* 71 - Home	*/	HOME,	'7',	AHOME,	AHOME,	A('7'),	CHOME,	
+/* 72 - CurUp	*/	UP,	'8',	AUP,	AUP,	A('8'),	CUP,
+/* 73 - PgUp	*/	PGUP,	'9',	APGUP,	APGUP,	A('9'),	CPGUP,
+/* 74 - '-'	*/	NMIN,	'-',	ANMIN,	ANMIN,	A('-'),	CNMIN,
+/* 75 - Left	*/	LEFT,	'4',	ALEFT,	ALEFT,	A('4'),	CLEFT,
+/* 76 - MID	*/	MID,	'5',	AMID,	AMID,	A('5'),	CMID,
+/* 77 - Right	*/	RIGHT,	'6',	ARIGHT,	ARIGHT,	A('6'),	CRIGHT,
+/* 78 - '+'	*/	PLUS,	'+',	APLUS,	APLUS,	A('+'),	CPLUS,
+/* 79 - End	*/	END,	'1',	AEND,	AEND,	A('1'),	CEND,
+/* 80 - Down	*/	DOWN,	'2',	ADOWN,	ADOWN,	A('2'),	CDOWN,
+/* 81 - PgDown	*/	PGDN,	'3',	APGDN,	APGDN,	A('3'),	CPGDN,
+/* 82 - Insert	*/	INSRT,	'0',	AINSRT,	AINSRT,	A('0'),	CINSRT,
+/* 83 - Delete	*/	0177,	'.',	A(0177),A(0177),A('.'),	0177,
+/* 84 - Enter	*/	C('M'),	C('M'),	CA('M'),CA('M'),CA('M'),C('J'),
+/* 85 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 86 - ???	*/	'<',	'>',	A('<'),	A('|'),	A('>'),	C('@'),
+/* 87 - F11	*/	F11,	SF11,	AF11,	AF11,	ASF11,	CF11,
+/* 88 - F12	*/	F12,	SF12,	AF12,	AF12,	ASF12,	CF12,
+/* 89 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 90 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 91 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 92 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 93 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 94 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 95 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 96 - EXT_KEY	*/	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,	EXTKEY,
+/* 97 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 98 - ???	*/	0,	0,	0,	0,	0,	0,
+/* 99 - ???	*/	0,	0,	0,	0,	0,	0,
+/*100 - ???	*/	0,	0,	0,	0,	0,	0,
+/*101 - ???	*/	0,	0,	0,	0,	0,	0,
+/*102 - ???	*/	0,	0,	0,	0,	0,	0,
+/*103 - ???	*/	0,	0,	0,	0,	0,	0,
+/*104 - ???	*/	0,	0,	0,	0,	0,	0,
+/*105 - ???	*/	0,	0,	0,	0,	0,	0,
+/*106 - ???	*/	0,	0,	0,	0,	0,	0,
+/*107 - ???	*/	0,	0,	0,	0,	0,	0,
+/*108 - ???	*/	0,	0,	0,	0,	0,	0,
+/*109 - ???	*/	0,	0,	0,	0,	0,	0,
+/*110 - ???	*/	0,	0,	0,	0,	0,	0,
+/*111 - ???	*/	0,	0,	0,	0,	0,	0,
+/*112 - ???	*/	0,	0,	0,	0,	0,	0,
+/*113 - ???	*/	0,	0,	0,	0,	0,	0,
+/*114 - ???	*/	0,	0,	0,	0,	0,	0,
+/*115 - ???	*/	0,	0,	0,	0,	0,	0,
+/*116 - ???	*/	0,	0,	0,	0,	0,	0,
+/*117 - ???	*/	0,	0,	0,	0,	0,	0,
+/*118 - ???	*/	0,	0,	0,	0,	0,	0,
+/*119 - ???	*/	0,	0,	0,	0,	0,	0,
+/*120 - ???	*/	0,	0,	0,	0,	0,	0,
+/*121 - ???	*/	0,	0,	0,	0,	0,	0,
+/*122 - ???	*/	0,	0,	0,	0,	0,	0,
+/*123 - ???	*/	0,	0,	0,	0,	0,	0,
+/*124 - ???	*/	0,	0,	0,	0,	0,	0,
+/*125 - ???	*/	0,	0,	0,	0,	0,	0,
+/*126 - ???	*/	0,	0,	0,	0,	0,	0,
+/*127 - ???	*/	0,	0,	0,	0,	0,	0
+};
Index: /trunk/minix/drivers/tty/pty.c
===================================================================
--- /trunk/minix/drivers/tty/pty.c	(revision 9)
+++ /trunk/minix/drivers/tty/pty.c	(revision 9)
@@ -0,0 +1,612 @@
+/*	pty.c - pseudo terminal driver			Author: Kees J. Bot
+ *								30 Dec 1995
+ * PTYs can be seen as a bidirectional pipe with TTY
+ * input and output processing.  For example a simple rlogin session:
+ *
+ *	keyboard -> rlogin -> in.rld -> /dev/ptypX -> /dev/ttypX -> shell
+ *	shell -> /dev/ttypX -> /dev/ptypX -> in.rld -> rlogin -> screen
+ *
+ * This file takes care of copying data between the tty/pty device pairs and
+ * the open/read/write/close calls on the pty devices.  The TTY task takes
+ * care of the input and output processing (interrupt, backspace, raw I/O,
+ * etc.) using the pty_read() and pty_write() functions as the "keyboard" and
+ * "screen" functions of the ttypX devices.
+ * Be careful when reading this code, the terms "reading" and "writing" are
+ * used both for the tty and the pty end of the pseudo tty.  Writes to one
+ * end are to be read at the other end and vice-versa.
+ */
+
+#include "../drivers.h"
+#include <assert.h>
+#include <termios.h>
+#include <signal.h>
+#include <minix/com.h>
+#include <minix/callnr.h>
+#include <sys/select.h>
+#include "tty.h"
+
+#if NR_PTYS > 0
+
+/* PTY bookkeeping structure, one per pty/tty pair. */
+typedef struct pty {
+  tty_t		*tty;		/* associated TTY structure */
+  char		state;		/* flags: busy, closed, ... */
+
+  /* Read call on /dev/ptypX. */
+  char		rdsendreply;	/* send a reply (instead of notify) */
+  int		rdcaller;	/* process making the call (usually FS) */
+  int		rdproc;		/* process that wants to read from the pty */
+  vir_bytes	rdvir;		/* virtual address in readers address space */
+  int		rdleft;		/* # bytes yet to be read */
+  int		rdcum;		/* # bytes written so far */
+
+  /* Write call to /dev/ptypX. */
+  char		wrsendreply;	/* send a reply (instead of notify) */
+  int		wrcaller;	/* process making the call (usually FS) */
+  int		wrproc;		/* process that wants to write to the pty */
+  vir_bytes	wrvir;		/* virtual address in writers address space */
+  int		wrleft;		/* # bytes yet to be written */
+  int		wrcum;		/* # bytes written so far */
+
+  /* Output buffer. */
+  int		ocount;		/* # characters in the buffer */
+  char		*ohead, *otail;	/* head and tail of the circular buffer */
+  char		obuf[128];	/* buffer for bytes going to the pty reader */
+
+  /* select() data. */
+  int		select_ops,	/* Which operations do we want to know about? */
+  		select_proc,	/* Who wants to know about it? */
+  		select_ready_ops;	/* For callback. */
+} pty_t;
+
+#define PTY_ACTIVE	0x01	/* pty is open/active */
+#define TTY_CLOSED	0x02	/* tty side has closed down */
+#define PTY_CLOSED	0x04	/* pty side has closed down */
+
+PRIVATE pty_t pty_table[NR_PTYS];	/* PTY bookkeeping */
+
+FORWARD _PROTOTYPE( int pty_write, (tty_t *tp, int try)			);
+FORWARD _PROTOTYPE( void pty_echo, (tty_t *tp, int c)			);
+FORWARD _PROTOTYPE( void pty_start, (pty_t *pp)				);
+FORWARD _PROTOTYPE( void pty_finish, (pty_t *pp)			);
+FORWARD _PROTOTYPE( int pty_read, (tty_t *tp, int try)			);
+FORWARD _PROTOTYPE( int pty_close, (tty_t *tp, int try)			);
+FORWARD _PROTOTYPE( int pty_icancel, (tty_t *tp, int try)		);
+FORWARD _PROTOTYPE( int pty_ocancel, (tty_t *tp, int try)		);
+FORWARD _PROTOTYPE( int pty_select, (tty_t *tp, message *m)		);
+
+/*===========================================================================*
+ *				do_pty					     *
+ *===========================================================================*/
+PUBLIC void do_pty(tp, m_ptr)
+tty_t *tp;
+message *m_ptr;
+{
+/* Perform an open/close/read/write call on a /dev/ptypX device. */
+  pty_t *pp = tp->tty_priv;
+  int r;
+  phys_bytes p;
+
+  switch (m_ptr->m_type) {
+    case DEV_READ:
+	/* Check, store information on the reader, do I/O. */
+	if (pp->state & TTY_CLOSED) {
+		r = 0;
+		break;
+	}
+	if (pp->rdleft != 0 || pp->rdcum != 0) {
+		r = EIO;
+		break;
+	}
+	if (m_ptr->COUNT <= 0) {
+		r = EINVAL;
+		break;
+	}
+#if DEAD_CODE
+	if (numap_local(m_ptr->IO_ENDPT, (vir_bytes) m_ptr->ADDRESS,
+							m_ptr->COUNT) == 0) {
+#else
+	if ((r = sys_umap(m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
+		m_ptr->COUNT, &p)) != OK) {
+#endif
+		break;
+	}
+	pp->rdsendreply = TRUE;
+	pp->rdcaller = m_ptr->m_source;
+	pp->rdproc = m_ptr->IO_ENDPT;
+	pp->rdvir = (vir_bytes) m_ptr->ADDRESS;
+	pp->rdleft = m_ptr->COUNT;
+	pty_start(pp);
+	handle_events(tp);
+	if (pp->rdleft == 0) return;			/* already done */
+
+	if (m_ptr->TTY_FLAGS & O_NONBLOCK) {
+		r = EAGAIN;				/* don't suspend */
+		pp->rdleft = pp->rdcum = 0;
+	} else {
+		r = SUSPEND;				/* do suspend */
+		pp->rdsendreply = FALSE;
+	}
+	break;
+
+    case DEV_WRITE:
+	/* Check, store information on the writer, do I/O. */
+	if (pp->state & TTY_CLOSED) {
+		r = EIO;
+		break;
+	}
+	if (pp->wrleft != 0 || pp->wrcum != 0) {
+		r = EIO;
+		break;
+	}
+	if (m_ptr->COUNT <= 0) {
+		r = EINVAL;
+		break;
+	}
+#if DEAD_CODE
+	if (numap_local(m_ptr->IO_ENDPT, (vir_bytes) m_ptr->ADDRESS,
+							m_ptr->COUNT) == 0) {
+		r = EFAULT;
+#else
+	if ((r = sys_umap(m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
+		m_ptr->COUNT, &p)) != OK) {
+#endif
+		break;
+	}
+	pp->wrsendreply = TRUE;
+	pp->wrcaller = m_ptr->m_source;
+	pp->wrproc = m_ptr->IO_ENDPT;
+	pp->wrvir = (vir_bytes) m_ptr->ADDRESS;
+	pp->wrleft = m_ptr->COUNT;
+	handle_events(tp);
+	if (pp->wrleft == 0) return;			/* already done */
+
+	if (m_ptr->TTY_FLAGS & O_NONBLOCK) {		/* don't suspend */
+		r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
+		pp->wrleft = pp->wrcum = 0;
+	} else {
+		pp->wrsendreply = FALSE;			/* do suspend */
+		r = SUSPEND;
+	}
+	break;
+
+    case DEV_OPEN:
+	r = pp->state != 0 ? EIO : OK;
+	pp->state |= PTY_ACTIVE;
+	pp->rdcum = 0;
+	pp->wrcum = 0;
+	break;
+
+    case DEV_CLOSE:
+	r = OK;
+	if (pp->state & TTY_CLOSED) {
+		pp->state = 0;
+	} else {
+		pp->state |= PTY_CLOSED;
+		sigchar(tp, SIGHUP);
+	}
+	break;
+
+    case DEV_SELECT:
+    	r = pty_select(tp, m_ptr);
+    	break;
+
+    case CANCEL:
+	if (m_ptr->IO_ENDPT == pp->rdproc) {
+		/* Cancel a read from a PTY. */
+		pp->rdleft = pp->rdcum = 0;
+	}
+	if (m_ptr->IO_ENDPT == pp->wrproc) {
+		/* Cancel a write to a PTY. */
+		pp->wrleft = pp->wrcum = 0;
+	}
+	r = EINTR;
+	break;
+
+    default:
+	r = EINVAL;
+  }
+  tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, r);
+}
+
+/*===========================================================================*
+ *				pty_write				     *
+ *===========================================================================*/
+PRIVATE int pty_write(tp, try)
+tty_t *tp;
+int try;
+{
+/* (*dev_write)() routine for PTYs.  Transfer bytes from the writer on
+ * /dev/ttypX to the output buffer.
+ */
+  pty_t *pp = tp->tty_priv;
+  int count, ocount, s;
+  phys_bytes user_phys;
+
+  /* PTY closed down? */
+  if (pp->state & PTY_CLOSED) {
+  	if (try) return 1;
+	if (tp->tty_outleft > 0) {
+		tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
+							tp->tty_outproc, EIO);
+		tp->tty_outleft = tp->tty_outcum = 0;
+	}
+	return;
+  }
+
+  /* While there is something to do. */
+  for (;;) {
+	ocount = buflen(pp->obuf) - pp->ocount;
+	if (try) return (ocount > 0);
+	count = bufend(pp->obuf) - pp->ohead;
+	if (count > ocount) count = ocount;
+	if (count > tp->tty_outleft) count = tp->tty_outleft;
+	if (count == 0 || tp->tty_inhibited)
+		break;
+
+	/* Copy from user space to the PTY output buffer. */
+	if ((s = sys_vircopy(tp->tty_outproc, D, (vir_bytes) tp->tty_out_vir,
+		SELF, D, (vir_bytes) pp->ohead, (phys_bytes) count)) != OK) {
+		printf("pty tty%d: copy failed (error %d)\n",  s);
+		break;
+	}
+
+	/* Perform output processing on the output buffer. */
+	out_process(tp, pp->obuf, pp->ohead, bufend(pp->obuf), &count, &ocount);
+	if (count == 0) break;
+
+	/* Assume echoing messed up by output. */
+	tp->tty_reprint = TRUE;
+
+	/* Bookkeeping. */
+	pp->ocount += ocount;
+	if ((pp->ohead += ocount) >= bufend(pp->obuf))
+		pp->ohead -= buflen(pp->obuf);
+	pty_start(pp);
+	tp->tty_out_vir += count;
+	tp->tty_outcum += count;
+	if ((tp->tty_outleft -= count) == 0) {
+		/* Output is finished, reply to the writer. */
+		tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
+					tp->tty_outproc, tp->tty_outcum);
+		tp->tty_outcum = 0;
+	}
+  }
+  pty_finish(pp);
+  return 1;
+}
+
+/*===========================================================================*
+ *				pty_echo				     *
+ *===========================================================================*/
+PRIVATE void pty_echo(tp, c)
+tty_t *tp;
+int c;
+{
+/* Echo one character.  (Like pty_write, but only one character, optionally.) */
+
+  pty_t *pp = tp->tty_priv;
+  int count, ocount;
+
+  ocount = buflen(pp->obuf) - pp->ocount;
+  if (ocount == 0) return;		/* output buffer full */
+  count = 1;
+  *pp->ohead = c;			/* add one character */
+
+  out_process(tp, pp->obuf, pp->ohead, bufend(pp->obuf), &count, &ocount);
+  if (count == 0) return;
+
+  pp->ocount += ocount;
+  if ((pp->ohead += ocount) >= bufend(pp->obuf)) pp->ohead -= buflen(pp->obuf);
+  pty_start(pp);
+}
+
+/*===========================================================================*
+ *				pty_start				     *
+ *===========================================================================*/
+PRIVATE void pty_start(pp)
+pty_t *pp;
+{
+/* Transfer bytes written to the output buffer to the PTY reader. */
+  int count;
+
+  /* While there are things to do. */
+  for (;;) {
+  	int s;
+	count = bufend(pp->obuf) - pp->otail;
+	if (count > pp->ocount) count = pp->ocount;
+	if (count > pp->rdleft) count = pp->rdleft;
+	if (count == 0) break;
+
+	/* Copy from the output buffer to the readers address space. */
+	if ((s = sys_vircopy(SELF, D, (vir_bytes)pp->otail,
+		(vir_bytes) pp->rdproc, D, (vir_bytes) pp->rdvir, (phys_bytes) count)) != OK) {
+		printf("pty tty%d: copy failed (error %d)\n",  s);
+		break;
+	}
+
+	/* Bookkeeping. */
+	pp->ocount -= count;
+	if ((pp->otail += count) == bufend(pp->obuf)) pp->otail = pp->obuf;
+	pp->rdvir += count;
+	pp->rdcum += count;
+	pp->rdleft -= count;
+  }
+}
+
+/*===========================================================================*
+ *				pty_finish				     *
+ *===========================================================================*/
+PRIVATE void pty_finish(pp)
+pty_t *pp;
+{
+/* Finish the read request of a PTY reader if there is at least one byte
+ * transferred.
+ */
+  if (pp->rdcum > 0) {
+        if (pp->rdsendreply) {
+		tty_reply(TASK_REPLY, pp->rdcaller, pp->rdproc, pp->rdcum);
+		pp->rdleft = pp->rdcum = 0;
+	}
+	else
+		notify(pp->rdcaller);
+  }
+
+}
+
+/*===========================================================================*
+ *				pty_read				     *
+ *===========================================================================*/
+PRIVATE int pty_read(tp, try)
+tty_t *tp;
+int try;
+{
+/* Offer bytes from the PTY writer for input on the TTY.  (Do it one byte at
+ * a time, 99% of the writes will be for one byte, so no sense in being smart.)
+ */
+  pty_t *pp = tp->tty_priv;
+  char c;
+
+  if (pp->state & PTY_CLOSED) {
+	if (try) return 1;
+	if (tp->tty_inleft > 0) {
+		tty_reply(tp->tty_inrepcode, tp->tty_incaller, tp->tty_inproc,
+								tp->tty_incum);
+		tp->tty_inleft = tp->tty_incum = 0;
+	}
+	return 1;
+  }
+
+  if (try) {
+  	if (pp->wrleft > 0)
+  		return 1;
+  	return 0;
+  }
+
+  while (pp->wrleft > 0) {
+  	int s;
+
+	/* Transfer one character to 'c'. */
+	if ((s = sys_vircopy(pp->wrproc, D, (vir_bytes) pp->wrvir,
+		SELF, D, (vir_bytes) &c, (phys_bytes) 1)) != OK) {
+		printf("pty: copy failed (error %d)\n", s);
+		break;
+	}
+
+	/* Input processing. */
+	if (in_process(tp, &c, 1) == 0) break;
+
+	/* PTY writer bookkeeping. */
+	pp->wrvir++;
+	pp->wrcum++;
+	if (--pp->wrleft == 0) {
+		if (pp->wrsendreply) {
+			tty_reply(TASK_REPLY, pp->wrcaller, pp->wrproc,
+				pp->wrcum);
+			pp->wrcum = 0;
+		}
+		else
+			notify(pp->wrcaller);
+	}
+  }
+}
+
+/*===========================================================================*
+ *				pty_close				     *
+ *===========================================================================*/
+PRIVATE int pty_close(tp, try)
+tty_t *tp;
+int try;
+{
+/* The tty side has closed, so shut down the pty side. */
+  pty_t *pp = tp->tty_priv;
+
+  if (!(pp->state & PTY_ACTIVE)) return;
+
+  if (pp->rdleft > 0) {
+  	assert(!pp->rdsendreply);
+  	notify(pp->rdcaller);
+  }
+
+  if (pp->wrleft > 0) {
+  	assert(!pp->wrsendreply);
+  	notify(pp->wrcaller);
+  }
+
+  if (pp->state & PTY_CLOSED) pp->state = 0; else pp->state |= TTY_CLOSED;
+}
+
+/*===========================================================================*
+ *				pty_icancel				     *
+ *===========================================================================*/
+PRIVATE int pty_icancel(tp, try)
+tty_t *tp;
+int try;
+{
+/* Discard waiting input. */
+  pty_t *pp = tp->tty_priv;
+
+  if (pp->wrleft > 0) {
+  	assert(!pp->wrsendreply);
+  	pp->wrcum += pp->wrleft;
+  	pp->wrleft= 0;
+  	notify(pp->wrcaller);
+  }
+}
+
+/*===========================================================================*
+ *				pty_ocancel				     *
+ *===========================================================================*/
+PRIVATE int pty_ocancel(tp, try)
+tty_t *tp;
+int try;
+{
+/* Drain the output buffer. */
+  pty_t *pp = tp->tty_priv;
+
+  pp->ocount = 0;
+  pp->otail = pp->ohead;
+}
+
+/*===========================================================================*
+ *				pty_init				     *
+ *===========================================================================*/
+PUBLIC void pty_init(tp)
+tty_t *tp;
+{
+  pty_t *pp;
+  int line;
+
+  /* Associate PTY and TTY structures. */
+  line = tp - &tty_table[NR_CONS + NR_RS_LINES];
+  pp = tp->tty_priv = &pty_table[line];
+  pp->tty = tp;
+  pp->select_ops = 0;
+
+  /* Set up output queue. */
+  pp->ohead = pp->otail = pp->obuf;
+
+  /* Fill in TTY function hooks. */
+  tp->tty_devread = pty_read;
+  tp->tty_devwrite = pty_write;
+  tp->tty_echo = pty_echo;
+  tp->tty_icancel = pty_icancel;
+  tp->tty_ocancel = pty_ocancel;
+  tp->tty_close = pty_close;
+  tp->tty_select_ops = 0;
+}
+
+/*===========================================================================*
+ *				pty_status				     *
+ *===========================================================================*/
+PUBLIC int pty_status(message *m_ptr)
+{
+	int i, event_found;
+	pty_t *pp;
+
+	event_found = 0;
+	for (i= 0, pp = pty_table; i<NR_PTYS; i++, pp++) {
+		if ((((pp->state & TTY_CLOSED) && pp->rdleft > 0) ||
+			pp->rdcum > 0) &&
+			pp->rdcaller == m_ptr->m_source)
+		{
+			m_ptr->m_type = DEV_REVIVE;
+			m_ptr->REP_ENDPT = pp->rdproc;
+			m_ptr->REP_STATUS = pp->rdcum;
+
+			pp->rdleft = pp->rdcum = 0;
+			event_found = 1;
+			break;
+		}
+
+		if ((((pp->state & TTY_CLOSED) && pp->wrleft > 0) ||
+			pp->wrcum > 0) &&
+			pp->wrcaller == m_ptr->m_source)
+		{
+			m_ptr->m_type = DEV_REVIVE;
+			m_ptr->REP_ENDPT = pp->wrproc;
+			if (pp->wrcum == 0)
+				m_ptr->REP_STATUS = EIO;
+			else
+				m_ptr->REP_STATUS = pp->wrcum;
+
+			pp->wrleft = pp->wrcum = 0;
+			event_found = 1;
+			break;
+		}
+
+		if (pp->select_ready_ops && pp->select_proc == m_ptr->m_source) {
+			m_ptr->m_type = DEV_IO_READY;
+			m_ptr->DEV_MINOR = PTYPX_MINOR + i;
+			m_ptr->DEV_SEL_OPS = pp->select_ready_ops;
+			pp->select_ready_ops = 0;
+			event_found = 1;
+			break;
+		}
+	}
+	return event_found;
+}
+
+/*===========================================================================*
+ *				select_try_pty				     *
+ *===========================================================================*/
+PRIVATE int select_try_pty(tty_t *tp, int ops)
+{
+  	pty_t *pp = tp->tty_priv;
+	int r = 0;
+
+	if (ops & SEL_WR)  {
+		/* Write won't block on error. */
+		if (pp->state & TTY_CLOSED) r |= SEL_WR;
+		else if (pp->wrleft != 0 || pp->wrcum != 0) r |= SEL_WR;
+		else r |= SEL_WR;
+	}
+
+	if (ops & SEL_RD) {
+		/* Read won't block on error. */
+		if (pp->state & TTY_CLOSED) r |= SEL_RD;
+		else if (pp->rdleft != 0 || pp->rdcum != 0) r |= SEL_RD;
+		else if (pp->ocount > 0) r |= SEL_RD;	/* Actual data. */
+	}
+
+	return r;
+}
+
+/*===========================================================================*
+ *				select_retry_pty			     *
+ *===========================================================================*/
+PUBLIC void select_retry_pty(tty_t *tp)
+{
+  	pty_t *pp = tp->tty_priv;
+  	int r;
+
+	/* See if the pty side of a pty is ready to return a select. */
+	if (pp->select_ops && (r=select_try_pty(tp, pp->select_ops))) {
+		pp->select_ops &= ~r;
+		pp->select_ready_ops |= r;
+		notify(pp->select_proc);
+	}
+}
+
+/*===========================================================================*
+ *				pty_select				     *
+ *===========================================================================*/
+PRIVATE int pty_select(tty_t *tp, message *m)
+{
+  	pty_t *pp = tp->tty_priv;
+	int ops, ready_ops = 0, watch;
+
+	ops = m->IO_ENDPT & (SEL_RD|SEL_WR|SEL_ERR);
+	watch = (m->IO_ENDPT & SEL_NOTIFY) ? 1 : 0;
+
+	ready_ops = select_try_pty(tp, ops);
+
+	if (!ready_ops && ops && watch) {
+		pp->select_ops |= ops;
+		pp->select_proc = m->m_source;
+	}
+
+	return ready_ops;
+}
+
+#endif /* NR_PTYS > 0 */
Index: /trunk/minix/drivers/tty/rs232.c
===================================================================
--- /trunk/minix/drivers/tty/rs232.c	(revision 9)
+++ /trunk/minix/drivers/tty/rs232.c	(revision 9)
@@ -0,0 +1,991 @@
+#include <minix/config.h>
+/*---------------------------------------------------------------------------*
+ *		rs232.c - serial driver for 8250 and 16450 UARTs	     *
+ *		Added support for Atari ST M68901 and YM-2149	--kub	     *
+ *---------------------------------------------------------------------------*/
+
+#include "../drivers.h"
+#include <termios.h>
+#include <signal.h>
+#include "tty.h"
+
+#if NR_RS_LINES > 0
+
+#if (MACHINE != IBM_PC) && (MACHINE != ATARI)
+#error				/* rs232.c only supports PC and Atari ST */
+#endif
+
+#if (MACHINE == ATARI)
+#include "staddr.h"
+#include "stsound.h"
+#include "stmfp.h"
+#if (NR_RS_LINES > 1)
+#error				/* Only one physical RS232 line available */
+#endif
+#endif
+
+#if (MACHINE == IBM_PC)		/* PC/AT 8250/16450 chip combination */
+
+/* 8250 constants. */
+#define UART_FREQ         115200L	/* timer frequency */
+
+/* Interrupt enable bits. */
+#define IE_RECEIVER_READY       1
+#define IE_TRANSMITTER_READY    2
+#define IE_LINE_STATUS_CHANGE   4
+#define IE_MODEM_STATUS_CHANGE  8
+
+/* Interrupt status bits. */
+#define IS_MODEM_STATUS_CHANGE  0
+#define IS_TRANSMITTER_READY    2
+#define IS_RECEIVER_READY       4
+#define IS_LINE_STATUS_CHANGE   6
+
+/* Line control bits. */
+#define LC_2STOP_BITS        0x04
+#define LC_PARITY            0x08
+#define LC_PAREVEN           0x10
+#define LC_BREAK             0x40
+#define LC_ADDRESS_DIVISOR   0x80
+
+/* Line status bits. */
+#define LS_OVERRUN_ERR          2
+#define LS_PARITY_ERR           4
+#define LS_FRAMING_ERR          8
+#define LS_BREAK_INTERRUPT   0x10
+#define LS_TRANSMITTER_READY 0x20
+
+/* Modem control bits. */
+#define MC_DTR                  1
+#define MC_RTS                  2
+#define MC_OUT2                 8	/* required for PC & AT interrupts */
+
+/* Modem status bits. */
+#define MS_CTS               0x10
+#define MS_RLSD              0x80       /* Received Line Signal Detect */
+#define MS_DRLSD             0x08       /* RLSD Delta */
+
+#else /* MACHINE == ATARI */		/* Atari ST 68901 USART */
+
+/* Most of the USART constants are already defined in stmfp.h . The local
+ * definitions made here are for keeping C code changes smaller.   --kub
+ */
+
+#define UART_FREQ          19200L	/* timer frequency */
+
+/* Line status bits. */
+#define LS_OVERRUN_ERR       R_OE
+#define LS_PARITY_ERR        R_PE
+#define LS_FRAMING_ERR       R_FE
+#define LS_BREAK_INTERRUPT   R_BREAK
+
+/* Modem status bits. */
+#define MS_CTS               IO_SCTS	/* 0x04 */
+
+#endif /* MACHINE == ATARI */
+
+#define DATA_BITS_SHIFT         8	/* amount data bits shifted in mode */
+#define DEF_BAUD             1200	/* default baud rate */
+
+#define RS_IBUFSIZE          1024	/* RS232 input buffer size */
+#define RS_OBUFSIZE          1024	/* RS232 output buffer size */
+
+/* Input buffer watermarks.
+ * The external device is asked to stop sending when the buffer
+ * exactly reaches high water, or when TTY requests it.  Sending restarts
+ * when the input buffer empties below the low watermark.
+ */
+#define RS_ILOWWATER	(1 * RS_IBUFSIZE / 4)
+#define RS_IHIGHWATER	(3 * RS_IBUFSIZE / 4)
+
+/* Output buffer low watermark.
+ * TTY is notified when the output buffer empties below the low watermark, so
+ * it may continue filling the buffer if doing a large write.
+ */
+#define RS_OLOWWATER	(1 * RS_OBUFSIZE / 4)
+
+#if (MACHINE == IBM_PC)
+
+/* Macros to handle flow control.
+ * Interrupts must be off when they are used.
+ * Time is critical - already the function call for outb() is annoying.
+ * If outb() can be done in-line, tests to avoid it can be dropped.
+ * istart() tells external device we are ready by raising RTS.
+ * istop() tells external device we are not ready by dropping RTS.
+ * DTR is kept high all the time (it probably should be raised by open and
+ * dropped by close of the device).
+ * OUT2 is also kept high all the time.
+ */
+#define istart(rs) \
+	(sys_outb((rs)->modem_ctl_port, MC_OUT2 | MC_RTS | MC_DTR), \
+		(rs)->idevready = TRUE)
+#define istop(rs) \
+	(sys_outb((rs)->modem_ctl_port, MC_OUT2 | MC_DTR), \
+		(rs)->idevready = FALSE)
+
+/* Macro to tell if device is ready.  The rs->cts field is set to MS_CTS if
+ * CLOCAL is in effect for a line without a CTS wire.
+ */
+#define devready(rs) ((my_inb(rs->modem_status_port) | rs->cts) & MS_CTS)
+
+/* Macro to tell if transmitter is ready. */
+#define txready(rs) (my_inb(rs->line_status_port) & LS_TRANSMITTER_READY)
+
+/* Macro to tell if carrier has dropped.
+ * The RS232 Carrier Detect (CD) line is usually connected to the 8250
+ * Received Line Signal Detect pin, reflected by bit MS_RLSD in the Modem
+ * Status Register.  The MS_DRLSD bit tells if MS_RLSD has just changed state.
+ * So if MS_DRLSD is set and MS_RLSD cleared, we know that carrier has just
+ * dropped.
+ */
+#define devhup(rs)	\
+	((my_inb(rs->modem_status_port) & (MS_RLSD|MS_DRLSD)) == MS_DRLSD)
+
+#else /* MACHINE == ATARI */
+
+/* Macros to handle flow control.
+ * Time is critical - already the function call for lock()/restore() is
+ * annoying.
+ * istart() tells external device we are ready by raising RTS.
+ * istop() tells external device we are not ready by dropping RTS.
+ * DTR is kept high all the time (it probably should be raised by open and
+ * dropped by close of the device). NOTE: The modem lines are active low.
+ */
+#define set_porta(msk,val) { register int s = lock();		\
+			     SOUND->sd_selr = YM_IOA;		\
+			     SOUND->sd_wdat =			\
+				SOUND->sd_rdat & (msk) | (val);	\
+			     restore(s);	}
+#define istart(rs)         { set_porta( ~(PA_SRTS|PA_SDTR),0 ); \
+			     (rs)->idevready = TRUE;	}
+#define istop(rs)          { set_porta( ~PA_SDTR, PA_SRTS );	\
+			     (rs)->idevready = FALSE;	}
+
+/* Macro to tell if device is ready.  The rs->cts field is set to MS_CTS if
+ * CLOCAL is in effect for a line without a CTS wire.
+ */
+#define devready(rs)         ((~MFP->mf_gpip | rs->cts) & MS_CTS)
+
+/* Transmitter ready test */
+#define txready(rs)          (MFP->mf_tsr & (T_EMPTY | T_UE))
+
+#endif /* MACHINE == ATARI */
+
+/* Types. */
+typedef unsigned char bool_t;	/* boolean */
+
+/* RS232 device structure, one per device. */
+typedef struct rs232 {
+  tty_t *tty;			/* associated TTY structure */
+
+  int icount;			/* number of bytes in the input buffer */
+  char *ihead;			/* next free spot in input buffer */
+  char *itail;			/* first byte to give to TTY */
+  bool_t idevready;		/* nonzero if we are ready to receive (RTS) */
+  char cts;			/* normally 0, but MS_CTS if CLOCAL is set */
+
+  unsigned char ostate;		/* combination of flags: */
+#define ODONE          1	/* output completed (< output enable bits) */
+#define ORAW           2	/* raw mode for xoff disable (< enab. bits) */
+#define OWAKEUP        4	/* tty_wakeup() pending (asm code only) */
+#define ODEVREADY MS_CTS	/* external device hardware ready (CTS) */
+#define OQUEUED     0x20	/* output buffer not empty */
+#define OSWREADY    0x40	/* external device software ready (no xoff) */
+#define ODEVHUP  MS_RLSD	/* external device has dropped carrier */
+#define OSOFTBITS  (ODONE | ORAW | OWAKEUP | OQUEUED | OSWREADY)
+				/* user-defined bits */
+#if (OSOFTBITS | ODEVREADY | ODEVHUP) == OSOFTBITS
+				/* a weak sanity check */
+#error				/* bits are not unique */
+#endif
+  unsigned char oxoff;		/* char to stop output */
+  bool_t inhibited;		/* output inhibited? (follows tty_inhibited) */
+  bool_t drain;			/* if set drain output and reconfigure line */
+  int ocount;			/* number of bytes in the output buffer */
+  char *ohead;			/* next free spot in output buffer */
+  char *otail;			/* next char to output */
+
+#if (MACHINE == IBM_PC)
+  port_t xmit_port;		/* i/o ports */
+  port_t recv_port;
+  port_t div_low_port;
+  port_t div_hi_port;
+  port_t int_enab_port;
+  port_t int_id_port;
+  port_t line_ctl_port;
+  port_t modem_ctl_port;
+  port_t line_status_port;
+  port_t modem_status_port;
+#endif
+
+  unsigned char lstatus;	/* last line status */
+  unsigned char pad;		/* ensure alignment for 16-bit ints */
+  unsigned framing_errors;	/* error counts (no reporting yet) */
+  unsigned overrun_errors;
+  unsigned parity_errors;
+  unsigned break_interrupts;
+
+  int irq;			/* irq for this line */
+  int irq_hook_id;		/* interrupt hook */
+
+  char ibuf[RS_IBUFSIZE];	/* input buffer */
+  char obuf[RS_OBUFSIZE];	/* output buffer */
+} rs232_t;
+
+PUBLIC rs232_t rs_lines[NR_RS_LINES];
+
+/* Table and macro to translate an RS232 line number to its rs_lines entry. */
+PRIVATE rs232_t *p_rs_addr[NR_RS_LINES];
+
+#define rs_addr(line)	(p_rs_addr[line])
+
+#if (MACHINE == IBM_PC)
+/* 8250 base addresses. */
+PRIVATE port_t addr_8250[] = {
+  0x3F8,	/* COM1 */
+  0x2F8,	/* COM2 */
+  0x3E8,	/* COM3 */
+  0x2E8,	/* COM4 */
+};
+#endif
+
+FORWARD _PROTOTYPE( void in_int, (rs232_t *rs)				);
+FORWARD _PROTOTYPE( void line_int, (rs232_t *rs)			);
+FORWARD _PROTOTYPE( void modem_int, (rs232_t *rs)			);
+FORWARD _PROTOTYPE( int rs_write, (tty_t *tp, int try)			);
+FORWARD _PROTOTYPE( void rs_echo, (tty_t *tp, int c)			);
+FORWARD _PROTOTYPE( int rs_ioctl, (tty_t *tp, int try)			);
+FORWARD _PROTOTYPE( void rs_config, (rs232_t *rs)			);
+FORWARD _PROTOTYPE( int rs_read, (tty_t *tp, int try)			);
+FORWARD _PROTOTYPE( int rs_icancel, (tty_t *tp, int try)		);
+FORWARD _PROTOTYPE( int rs_ocancel, (tty_t *tp, int try)		);
+FORWARD _PROTOTYPE( void rs_ostart, (rs232_t *rs)			);
+FORWARD _PROTOTYPE( int rs_break, (tty_t *tp, int try)			);
+FORWARD _PROTOTYPE( int rs_close, (tty_t *tp, int try)			);
+FORWARD _PROTOTYPE( void out_int, (rs232_t *rs)				);
+FORWARD _PROTOTYPE( void rs232_handler, (rs232_t *rs)			);
+
+/* XXX */
+PRIVATE void lock(void) {}
+PRIVATE void unlock(void) {}
+
+PRIVATE int my_inb(port_t port)
+{
+	int r;
+	unsigned long v = 0;
+	r = sys_inb(port, &v);
+	if (r != OK)
+		printf("RS232 warning: failed inb 0x%x\n", port);
+
+	return (int) v;
+}
+
+/*===========================================================================*
+ *				rs_write				     *
+ *===========================================================================*/
+PRIVATE int rs_write(tp, try)
+register tty_t *tp;
+int try;
+{
+/* (*devwrite)() routine for RS232. */
+
+  rs232_t *rs = tp->tty_priv;
+  int count, ocount;
+
+  if (rs->inhibited != tp->tty_inhibited) {
+	/* Inhibition state has changed. */
+	lock();
+	rs->ostate |= OSWREADY;
+	if (tp->tty_inhibited) rs->ostate &= ~OSWREADY;
+	unlock();
+	rs->inhibited = tp->tty_inhibited;
+  }
+
+  if (rs->drain) {
+	/* Wait for the line to drain then reconfigure and continue output. */
+	if (rs->ocount > 0) return 0;
+	rs->drain = FALSE;
+	rs_config(rs);
+  }
+
+  /* While there is something to do. */
+  for (;;) {
+	ocount = buflen(rs->obuf) - rs->ocount;
+	count = bufend(rs->obuf) - rs->ohead;
+	if (count > ocount) count = ocount;
+	if (count > tp->tty_outleft) count = tp->tty_outleft;
+	if (count == 0 || tp->tty_inhibited) {
+		if (try) return 0;
+		break;
+	}
+	if (try) return 1;
+
+	/* Copy from user space to the RS232 output buffer. */
+	sys_vircopy(tp->tty_outproc, D, (vir_bytes) tp->tty_out_vir, 
+		SELF, D, (vir_bytes) rs->ohead, (phys_bytes) count);
+
+	/* Perform output processing on the output buffer. */
+	out_process(tp, rs->obuf, rs->ohead, bufend(rs->obuf), &count, &ocount);
+	if (count == 0) break;
+
+	/* Assume echoing messed up by output. */
+	tp->tty_reprint = TRUE;
+
+	/* Bookkeeping. */
+	lock();			/* protect interrupt sensitive rs->ocount */
+	rs->ocount += ocount;
+	rs_ostart(rs);
+	unlock();
+	if ((rs->ohead += ocount) >= bufend(rs->obuf))
+		rs->ohead -= buflen(rs->obuf);
+	tp->tty_out_vir += count;
+	tp->tty_outcum += count;
+	if ((tp->tty_outleft -= count) == 0) {
+		/* Output is finished, reply to the writer. */
+		tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
+					tp->tty_outproc, tp->tty_outcum);
+		tp->tty_outcum = 0;
+	}
+  }
+  if (tp->tty_outleft > 0 && tp->tty_termios.c_ospeed == B0) {
+	/* Oops, the line has hung up. */
+	tty_reply(tp->tty_outrepcode, tp->tty_outcaller, tp->tty_outproc, EIO);
+	tp->tty_outleft = tp->tty_outcum = 0;
+  }
+
+  return 1;
+}
+
+/*===========================================================================*
+ *				rs_echo					     *
+ *===========================================================================*/
+PRIVATE void rs_echo(tp, c)
+tty_t *tp;			/* which TTY */
+int c;				/* character to echo */
+{
+/* Echo one character.  (Like rs_write, but only one character, optionally.) */
+
+  rs232_t *rs = tp->tty_priv;
+  int count, ocount;
+
+  ocount = buflen(rs->obuf) - rs->ocount;
+  if (ocount == 0) return;		/* output buffer full */
+  count = 1;
+  *rs->ohead = c;			/* add one character */
+
+  out_process(tp, rs->obuf, rs->ohead, bufend(rs->obuf), &count, &ocount);
+  if (count == 0) return;
+
+  lock();
+  rs->ocount += ocount;
+  rs_ostart(rs);
+  unlock();
+  if ((rs->ohead += ocount) >= bufend(rs->obuf)) rs->ohead -= buflen(rs->obuf);
+}
+
+/*===========================================================================*
+ *				rs_ioctl				     *
+ *===========================================================================*/
+PRIVATE int rs_ioctl(tp, dummy)
+tty_t *tp;			/* which TTY */
+int dummy;
+{
+/* Reconfigure the line as soon as the output has drained. */
+  rs232_t *rs = tp->tty_priv;
+
+  rs->drain = TRUE;
+  return 0;	/* dummy */
+}
+
+/*===========================================================================*
+ *				rs_config				     *
+ *===========================================================================*/
+PRIVATE void rs_config(rs)
+rs232_t *rs;			/* which line */
+{
+/* Set various line control parameters for RS232 I/O.
+ * If DataBits == 5 and StopBits == 2, 8250 will generate 1.5 stop bits.
+ * The 8250 can't handle split speed, so we use the input speed.
+ */
+
+  tty_t *tp = rs->tty;
+  int divisor;
+  int line_controls;
+  static struct speed2divisor {
+	speed_t	speed;
+	int	divisor;
+  } s2d[] = {
+#if (MACHINE == IBM_PC)
+	{ B50,		UART_FREQ / 50		},
+#endif
+	{ B75,		UART_FREQ / 75		},
+	{ B110,		UART_FREQ / 110		},
+	{ B134,		UART_FREQ * 10 / 1345	},
+	{ B150,		UART_FREQ / 150		},
+	{ B200,		UART_FREQ / 200		},
+	{ B300,		UART_FREQ / 300		},
+	{ B600,		UART_FREQ / 600		},
+	{ B1200,	UART_FREQ / 1200	},
+#if (MACHINE == IBM_PC)
+	{ B1800,	UART_FREQ / 1800	},
+#endif
+	{ B2400,	UART_FREQ / 2400	},
+	{ B4800,	UART_FREQ / 4800	},
+	{ B9600,	UART_FREQ / 9600	},
+	{ B19200,	UART_FREQ / 19200	},
+#if (MACHINE == IBM_PC)
+	{ B38400,	UART_FREQ / 38400	},
+	{ B57600,	UART_FREQ / 57600	},
+	{ B115200,	UART_FREQ / 115200L	},
+#endif
+  };
+  struct speed2divisor *s2dp;
+
+  /* RS232 needs to know the xoff character, and if CTS works. */
+  rs->oxoff = tp->tty_termios.c_cc[VSTOP];
+  rs->cts = (tp->tty_termios.c_cflag & CLOCAL) ? MS_CTS : 0;
+
+  /* Look up the 8250 rate divisor from the output speed. */
+  divisor = 0;
+  for (s2dp = s2d; s2dp < s2d + sizeof(s2d)/sizeof(s2d[0]); s2dp++) {
+	if (s2dp->speed == tp->tty_termios.c_ospeed) divisor = s2dp->divisor;
+  }
+  if (divisor == 0) return;	/* B0? */
+
+#if (MACHINE == IBM_PC)
+  /* Compute line control flag bits. */
+  line_controls = 0;
+  if (tp->tty_termios.c_cflag & PARENB) {
+	line_controls |= LC_PARITY;
+	if (!(tp->tty_termios.c_cflag & PARODD)) line_controls |= LC_PAREVEN;
+  }
+  if (divisor >= (UART_FREQ / 110)) line_controls |= LC_2STOP_BITS;
+  line_controls |= (tp->tty_termios.c_cflag & CSIZE) >> 2;
+
+  /* Lock out interrupts while setting the speed. The receiver register is
+   * going to be hidden by the div_low register, but the input interrupt
+   * handler relies on reading it to clear the interrupt and avoid looping
+   * forever.
+   */
+  lock();
+
+  /* Select the baud rate divisor registers and change the rate. */
+  sys_outb(rs->line_ctl_port, LC_ADDRESS_DIVISOR);
+  sys_outb(rs->div_low_port, divisor);
+  sys_outb(rs->div_hi_port, divisor >> 8);
+
+  /* Change the line controls and reselect the usual registers. */
+  sys_outb(rs->line_ctl_port, line_controls);
+
+  rs->ostate = devready(rs) | ORAW | OSWREADY;	/* reads modem_ctl_port */
+  if ((tp->tty_termios.c_lflag & IXON) && rs->oxoff != _POSIX_VDISABLE)
+	rs->ostate &= ~ORAW;
+
+  unlock();
+
+#else /* MACHINE == ATARI */
+
+  line_controls = U_Q16;
+  if (tp->tty_termios.c_cflag & PARENB) {
+	line_controls |= U_PAR;
+	if (!(tp->tty_termios.c_cflag & PARODD)) line_controls |= U_EVEN;
+  }
+  line_controls |= (divisor >= (UART_FREQ / 110)) ? U_ST2 : U_ST1;
+
+  switch (tp->tty_termios.c_cflag & CSIZE) {	/* XXX - are U_Dn like CSn? */
+	case CS5:	line_controls |= U_D5; break;
+	case CS5:	line_controls |= U_D6; break;
+	case CS5:	line_controls |= U_D7; break;
+	case CS5:	line_controls |= U_D8; break;
+  }
+  lock();
+  MFP->mf_ucr = line_controls;
+  MFP->mf_tddr = divisor;
+  unlock();
+#endif /* MACHINE == ATARI */
+}
+
+/*===========================================================================*
+ *				rs_init					     *
+ *===========================================================================*/
+PUBLIC void rs_init(tp)
+tty_t *tp;			/* which TTY */
+{
+  unsigned long dummy;
+/* Initialize RS232 for one line. */
+
+  register rs232_t *rs;
+  int line;
+#if (MACHINE == IBM_PC)
+  port_t this_8250;
+  int irq;
+  long v;
+#endif
+
+  /* Associate RS232 and TTY structures. */
+  line = tp - &tty_table[NR_CONS];
+  rs = tp->tty_priv = &rs_lines[line];
+  rs->tty = tp;
+
+  /* Set up input queue. */
+  rs->ihead = rs->itail = rs->ibuf;
+
+#if (MACHINE == IBM_PC)
+  /* Precalculate port numbers for speed. Magic numbers in the code (once). */
+  this_8250 = addr_8250[line];
+  rs->xmit_port = this_8250 + 0;
+  rs->recv_port = this_8250 + 0;
+  rs->div_low_port = this_8250 + 0;
+  rs->div_hi_port = this_8250 + 1;
+  rs->int_enab_port = this_8250 + 1;
+  rs->int_id_port = this_8250 + 2;
+  rs->line_ctl_port = this_8250 + 3;
+  rs->modem_ctl_port = this_8250 + 4;
+  rs->line_status_port = this_8250 + 5;
+  rs->modem_status_port = this_8250 + 6;
+#endif
+
+  /* Set up the hardware to a base state, in particular
+   *	o turn off DTR (MC_DTR) to try to stop the external device.
+   *	o be careful about the divisor latch.  Some BIOS's leave it enabled
+   *	  here and that caused trouble (no interrupts) in version 1.5 by
+   *	  hiding the interrupt enable port in the next step, and worse trouble
+   *	  (continual interrupts) in an old version by hiding the receiver
+   *	  port in the first interrupt.  Call rs_ioctl() early to avoid this.
+   *	o disable interrupts at the chip level, to force an edge transition
+   *	  on the 8259 line when interrupts are next enabled and active.
+   *	  RS232 interrupts are guaranteed to be disabled now by the 8259
+   *	  mask, but there used to be trouble if the mask was set without
+   *	  handling a previous interrupt.
+   */
+  istop(rs);			/* sets modem_ctl_port */
+  rs_config(rs);
+#if (MACHINE == IBM_PC)
+  sys_outb(rs->int_enab_port, 0);
+#endif
+
+  /* Clear any harmful leftover interrupts.  An output interrupt is harmless
+   * and will occur when interrupts are enabled anyway.  Set up the output
+   * queue using the status from clearing the modem status interrupt.
+   */
+#if (MACHINE == IBM_PC)
+  sys_inb(rs->line_status_port, &dummy);
+  sys_inb(rs->recv_port, &dummy);
+#endif
+  rs->ostate = devready(rs) | ORAW | OSWREADY;	/* reads modem_ctl_port */
+  rs->ohead = rs->otail = rs->obuf;
+
+#if (MACHINE == IBM_PC)
+  /* Enable interrupts for both interrupt controller and device. */
+  irq = (line & 1) == 0 ? RS232_IRQ : SECONDARY_IRQ;
+
+  rs->irq = irq;
+  rs->irq_hook_id = rs->irq;	/* call back with irq line number */
+  if (sys_irqsetpolicy(irq, IRQ_REENABLE, &rs->irq_hook_id) != OK) {
+  	printf("RS232: Couldn't obtain hook for irq %d\n", irq);
+  } else {
+  	if (sys_irqenable(&rs->irq_hook_id) != OK)  {
+  		printf("RS232: Couldn't enable irq %d (hooked)\n", irq);
+  	}
+  }
+
+  rs_irq_set |= (1 << irq);
+
+  sys_outb(rs->int_enab_port, IE_LINE_STATUS_CHANGE | IE_MODEM_STATUS_CHANGE
+				| IE_RECEIVER_READY | IE_TRANSMITTER_READY);
+#else /* MACHINE == ATARI */
+  /* Initialize the 68901 chip, then enable interrupts. */
+  MFP->mf_scr = 0x00;
+  MFP->mf_tcdcr |= T_Q004;
+  MFP->mf_rsr = R_ENA;
+  MFP->mf_tsr = T_ENA;
+  MFP->mf_aer = (MFP->mf_aer | (IO_SCTS|IO_SDCD)) ^
+		 (MFP->mf_gpip & (IO_SCTS|IO_SDCD));
+  MFP->mf_ddr = (MFP->mf_ddr & ~ (IO_SCTS|IO_SDCD));
+  MFP->mf_iera |= (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);
+  MFP->mf_imra |= (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);
+  MFP->mf_ierb |= (IB_SCTS|IB_SDCD);
+  MFP->mf_imrb |= (IB_SCTS|IB_SDCD);
+#endif /* MACHINE == ATARI */
+
+  /* Fill in TTY function hooks. */
+  tp->tty_devread = rs_read;
+  tp->tty_devwrite = rs_write;
+  tp->tty_echo = rs_echo;
+  tp->tty_icancel = rs_icancel;
+  tp->tty_ocancel = rs_ocancel;
+  tp->tty_ioctl = rs_ioctl;
+  tp->tty_break = rs_break;
+  tp->tty_close = rs_close;
+
+  /* Tell external device we are ready. */
+  istart(rs);
+
+}
+
+/*===========================================================================*
+ *				rs_interrupt				     *
+ *===========================================================================*/
+PUBLIC void rs_interrupt(m)
+message *m;			/* which TTY */
+{
+	unsigned long irq_set;
+	int i;
+	rs232_t *rs;
+
+	irq_set= m->NOTIFY_ARG;
+	for (i= 0, rs = rs_lines; i<NR_RS_LINES; i++, rs++)
+	{
+		if (irq_set & (1 << rs->irq))
+			rs232_handler(rs);
+	}
+}
+
+/*===========================================================================*
+ *				rs_icancel				     *
+ *===========================================================================*/
+PRIVATE int rs_icancel(tp, dummy)
+tty_t *tp;			/* which TTY */
+int dummy;
+{
+/* Cancel waiting input. */
+  rs232_t *rs = tp->tty_priv;
+
+  lock();
+  rs->icount = 0;
+  rs->itail = rs->ihead;
+  istart(rs);
+  unlock();
+
+  return 0;	/* dummy */
+}
+
+/*===========================================================================*
+ *				rs_ocancel				     *
+ *===========================================================================*/
+PRIVATE int rs_ocancel(tp, dummy)
+tty_t *tp;			/* which TTY */
+int dummy;
+{
+/* Cancel pending output. */
+  rs232_t *rs = tp->tty_priv;
+
+  lock();
+  rs->ostate &= ~(ODONE | OQUEUED);
+  rs->ocount = 0;
+  rs->otail = rs->ohead;
+  unlock();
+
+  return 0;	/* dummy */
+}
+
+/*===========================================================================*
+ *				rs_read					     *
+ *===========================================================================*/
+PRIVATE int rs_read(tp, try)
+tty_t *tp;			/* which tty */
+int try;
+{
+/* Process characters from the circular input buffer. */
+
+  rs232_t *rs = tp->tty_priv;
+  int icount, count, ostate;
+
+  if (!(tp->tty_termios.c_cflag & CLOCAL)) {
+  	if (try) return 1;
+	/* Send a SIGHUP if hangup detected. */
+	lock();
+	ostate = rs->ostate;
+	rs->ostate &= ~ODEVHUP;		/* save ostate, clear DEVHUP */
+	unlock();
+	if (ostate & ODEVHUP) {
+		sigchar(tp, SIGHUP);
+		tp->tty_termios.c_ospeed = B0;	/* Disable further I/O. */
+		return;
+	}
+  }
+
+  if (try) {
+  	if (rs->icount > 0)
+	  	return 1;
+	return 0;
+  }
+
+  while ((count = rs->icount) > 0) {
+	icount = bufend(rs->ibuf) - rs->itail;
+	if (count > icount) count = icount;
+
+	/* Perform input processing on (part of) the input buffer. */
+	if ((count = in_process(tp, rs->itail, count)) == 0) break;
+
+	lock();			/* protect interrupt sensitive variables */
+	rs->icount -= count;
+	if (!rs->idevready && rs->icount < RS_ILOWWATER) istart(rs);
+	unlock();
+	if ((rs->itail += count) == bufend(rs->ibuf)) rs->itail = rs->ibuf;
+  }
+}
+
+/*===========================================================================*
+ *				rs_ostart				     *
+ *===========================================================================*/
+PRIVATE void rs_ostart(rs)
+rs232_t *rs;			/* which rs line */
+{
+/* Tell RS232 there is something waiting in the output buffer. */
+
+  rs->ostate |= OQUEUED;
+  if (txready(rs)) out_int(rs);
+}
+
+/*===========================================================================*
+ *				rs_break				     *
+ *===========================================================================*/
+PRIVATE int rs_break(tp, dummy)
+tty_t *tp;			/* which tty */
+int dummy;
+{
+/* Generate a break condition by setting the BREAK bit for 0.4 sec. */
+  rs232_t *rs = tp->tty_priv;
+  unsigned long line_controls;
+
+  sys_inb(rs->line_ctl_port, &line_controls);
+  sys_outb(rs->line_ctl_port, line_controls | LC_BREAK);
+  /* XXX */
+  /* milli_delay(400); */				/* ouch */
+  printf("RS232 break\n");
+  sys_outb(rs->line_ctl_port, line_controls);
+  return 0;	/* dummy */
+}
+
+/*===========================================================================*
+ *				rs_close				     *
+ *===========================================================================*/
+PRIVATE int rs_close(tp, dummy)
+tty_t *tp;			/* which tty */
+int dummy;
+{
+/* The line is closed; optionally hang up. */
+  rs232_t *rs = tp->tty_priv;
+  int r;
+
+  if (tp->tty_termios.c_cflag & HUPCL) {
+	sys_outb(rs->modem_ctl_port, MC_OUT2 | MC_RTS);
+  }
+  return 0;	/* dummy */
+}
+
+/* Low level (interrupt) routines. */
+
+#if (MACHINE == IBM_PC)
+/*===========================================================================*
+ *				rs232_handler				     *
+ *===========================================================================*/
+PRIVATE void rs232_handler(rs)
+struct rs232 *rs;
+{
+/* Interrupt hander for RS232. */
+
+  while (TRUE) {
+  	unsigned long v;
+	/* Loop to pick up ALL pending interrupts for device.
+	 * This usually just wastes time unless the hardware has a buffer
+	 * (and then we have to worry about being stuck in the loop too long).
+	 * Unfortunately, some serial cards lock up without this.
+	 */
+	sys_inb(rs->int_id_port, &v);
+	switch (v) {
+	case IS_RECEIVER_READY:
+		in_int(rs);
+		continue;
+	case IS_TRANSMITTER_READY:
+		out_int(rs);
+		continue;
+	case IS_MODEM_STATUS_CHANGE:
+		modem_int(rs);
+		continue;
+	case IS_LINE_STATUS_CHANGE:
+		line_int(rs);
+		continue;
+	}
+	return;
+  }
+}
+#endif /* MACHINE == IBM_PC */
+
+#if (MACHINE == ATARI)
+/*===========================================================================*
+ *				siaint					     *
+ *===========================================================================*/
+PRIVATE void siaint(type)
+int    type;	       /* interrupt type */
+{
+/* siaint is the rs232 interrupt procedure for Atari ST's. For ST there are
+ * as much as 5 interrupt lines used for rs232. The trap type byte left on the
+ * stack by the assembler interrupt handler identifies the interrupt cause.
+ */
+
+  register unsigned char  code;
+  register rs232_t *rs = &rs_lines[0];
+  int s = lock();
+
+  switch (type & 0x00FF)
+  {
+	case 0x00:	       /* receive buffer full */
+		in_int(rs);
+		break;
+	case 0x01:	       /* receive error */
+		line_int(rs);
+		break;
+	case 0x02:	       /* transmit buffer empty */
+		out_int(rs);
+		break;
+	case 0x03:	       /* transmit error */
+		code = MFP->mf_tsr;
+		if (code & ~(T_ENA | T_UE | T_EMPTY))
+		{
+		    printf("sia: transmit error: status=%x\r\n", code);
+		    /* MFP->mf_udr = lastchar; */ /* retry */
+		}
+		break;
+	case 0x04:		/* modem lines change */
+		modem_int(rs);
+		break;
+  }
+  restore(s);
+}
+#endif /* MACHINE == ATARI */
+
+/*===========================================================================*
+ *				in_int					     *
+ *===========================================================================*/
+PRIVATE void in_int(rs)
+register rs232_t *rs;		/* line with input interrupt */
+{
+/* Read the data which just arrived.
+ * If it is the oxoff char, clear OSWREADY, else if OSWREADY was clear, set
+ * it and restart output (any char does this, not just xon).
+ * Put data in the buffer if room, otherwise discard it.
+ * Set a flag for the clock interrupt handler to eventually notify TTY.
+ */
+
+  unsigned long c;
+
+#if (MACHINE == IBM_PC)
+  sys_inb(rs->recv_port, &c);
+#else /* MACHINE == ATARI */
+  c = MFP->mf_udr;
+#endif
+
+  if (!(rs->ostate & ORAW)) {
+	if (c == rs->oxoff) {
+		rs->ostate &= ~OSWREADY;
+	} else
+	if (!(rs->ostate & OSWREADY)) {
+		rs->ostate |= OSWREADY;
+		if (txready(rs)) out_int(rs);
+	}
+  }
+
+  if (rs->icount == buflen(rs->ibuf))
+  {
+	printf("in_int: discarding byte\n");
+	return;	/* input buffer full, discard */
+  }
+
+  if (++rs->icount == RS_IHIGHWATER && rs->idevready) istop(rs);
+  *rs->ihead = c;
+  if (++rs->ihead == bufend(rs->ibuf)) rs->ihead = rs->ibuf;
+  if (rs->icount == 1) {
+	rs->tty->tty_events = 1;
+	force_timeout();
+  }
+  else
+	printf("in_int: icount = %d\n", rs->icount);
+}
+
+/*===========================================================================*
+ *				line_int				     *
+ *===========================================================================*/
+PRIVATE void line_int(rs)
+register rs232_t *rs;		/* line with line status interrupt */
+{
+/* Check for and record errors. */
+
+ unsigned long s;
+#if (MACHINE == IBM_PC)
+  sys_inb(rs->line_status_port, &s);
+  rs->lstatus = s;
+#else /* MACHINE == ATARI */
+  rs->lstatus = MFP->mf_rsr;
+  MFP->mf_rsr &= R_ENA;
+  rs->pad = MFP->mf_udr;	/* discard char in case of LS_OVERRUN_ERR */
+#endif /* MACHINE == ATARI */
+  if (rs->lstatus & LS_FRAMING_ERR) ++rs->framing_errors;
+  if (rs->lstatus & LS_OVERRUN_ERR) ++rs->overrun_errors;
+  if (rs->lstatus & LS_PARITY_ERR) ++rs->parity_errors;
+  if (rs->lstatus & LS_BREAK_INTERRUPT) ++rs->break_interrupts;
+}
+
+/*===========================================================================*
+ *				modem_int				     *
+ *===========================================================================*/
+PRIVATE void modem_int(rs)
+register rs232_t *rs;		/* line with modem interrupt */
+{
+/* Get possibly new device-ready status, and clear ODEVREADY if necessary.
+ * If the device just became ready, restart output.
+ */
+
+#if (MACHINE == ATARI)
+  /* Set active edge interrupt so that next change causes a new interrupt */
+  MFP->mf_aer = (MFP->mf_aer | (IO_SCTS|IO_SDCD)) ^
+		 (MFP->mf_gpip & (IO_SCTS|IO_SDCD));
+#endif
+
+  if (devhup(rs)) {
+	rs->ostate |= ODEVHUP;
+	rs->tty->tty_events = 1;
+	force_timeout();
+  }
+
+  if (!devready(rs))
+	rs->ostate &= ~ODEVREADY;
+  else if (!(rs->ostate & ODEVREADY)) {
+	rs->ostate |= ODEVREADY;
+	if (txready(rs)) out_int(rs);
+  }
+}
+
+/*===========================================================================*
+ *				out_int					    *
+ *===========================================================================*/
+PRIVATE void out_int(rs)
+register rs232_t *rs;		/* line with output interrupt */
+{
+/* If there is output to do and everything is ready, do it (local device is
+ * known ready).
+ * Notify TTY when the buffer goes empty.
+ */
+
+  if (rs->ostate >= (ODEVREADY | OQUEUED | OSWREADY)) {
+	/* Bit test allows ORAW and requires the others. */
+#if (MACHINE == IBM_PC)
+	sys_outb(rs->xmit_port, *rs->otail);
+#else /* MACHINE == ATARI */
+	MFP->mf_udr = *rs->otail;
+#endif
+	if (++rs->otail == bufend(rs->obuf)) rs->otail = rs->obuf;
+	if (--rs->ocount == 0) {
+		rs->ostate ^= (ODONE | OQUEUED);  /* ODONE on, OQUEUED off */
+		rs->tty->tty_events = 1;
+		force_timeout();
+	} else
+	if (rs->ocount == RS_OLOWWATER) {	/* running low? */
+		rs->tty->tty_events = 1;
+		force_timeout();
+	}
+  }
+}
+#endif /* NR_RS_LINES > 0 */
+
Index: /trunk/minix/drivers/tty/tty.c
===================================================================
--- /trunk/minix/drivers/tty/tty.c	(revision 9)
+++ /trunk/minix/drivers/tty/tty.c	(revision 9)
@@ -0,0 +1,2026 @@
+/* This file contains the terminal driver, both for the IBM console and regular
+ * ASCII terminals.  It handles only the device-independent part of a TTY, the
+ * device dependent parts are in console.c, rs232.c, etc.  This file contains
+ * two main entry points, tty_task() and tty_wakeup(), and several minor entry
+ * points for use by the device-dependent code.
+ *
+ * The device-independent part accepts "keyboard" input from the device-
+ * dependent part, performs input processing (special key interpretation),
+ * and sends the input to a process reading from the TTY.  Output to a TTY
+ * is sent to the device-dependent code for output processing and "screen"
+ * display.  Input processing is done by the device by calling 'in_process'
+ * on the input characters, output processing may be done by the device itself
+ * or by calling 'out_process'.  The TTY takes care of input queuing, the
+ * device does the output queuing.  If a device receives an external signal,
+ * like an interrupt, then it causes tty_wakeup() to be run by the CLOCK task
+ * to, you guessed it, wake up the TTY to check if input or output can
+ * continue.
+ *
+ * The valid messages and their parameters are:
+ *
+ *   HARD_INT:       output has been completed or input has arrived
+ *   SYS_SIG:      e.g., MINIX wants to shutdown; run code to cleanly stop
+ *   DEV_READ:       a process wants to read from a terminal
+ *   DEV_WRITE:      a process wants to write on a terminal
+ *   DEV_IOCTL:      a process wants to change a terminal's parameters
+ *   DEV_OPEN:       a tty line has been opened
+ *   DEV_CLOSE:      a tty line has been closed
+ *   DEV_SELECT:     start select notification request
+ *   DEV_STATUS:     FS wants to know status for SELECT or REVIVE
+ *   CANCEL:         terminate a previous incomplete system call immediately
+ *
+ *    m_type      TTY_LINE   IO_ENDPT    COUNT   TTY_SPEK  TTY_FLAGS  ADDRESS
+ * ---------------------------------------------------------------------------
+ * | HARD_INT    |         |         |         |         |         |         |
+ * |-------------+---------+---------+---------+---------+---------+---------|
+ * | SYS_SIG     | sig set |         |         |         |         |         |
+ * |-------------+---------+---------+---------+---------+---------+---------|
+ * | DEV_READ    |minor dev| proc nr |  count  |         O_NONBLOCK| buf ptr |
+ * |-------------+---------+---------+---------+---------+---------+---------|
+ * | DEV_WRITE   |minor dev| proc nr |  count  |         |         | buf ptr |
+ * |-------------+---------+---------+---------+---------+---------+---------|
+ * | DEV_IOCTL   |minor dev| proc nr |func code|erase etc|  flags  |         |
+ * |-------------+---------+---------+---------+---------+---------+---------|
+ * | DEV_OPEN    |minor dev| proc nr | O_NOCTTY|         |         |         |
+ * |-------------+---------+---------+---------+---------+---------+---------|
+ * | DEV_CLOSE   |minor dev| proc nr |         |         |         |         |
+ * |-------------+---------+---------+---------+---------+---------+---------|
+ * | DEV_STATUS  |         |         |         |         |         |         |
+ * |-------------+---------+---------+---------+---------+---------+---------|
+ * | CANCEL      |minor dev| proc nr |         |         |         |         |
+ * ---------------------------------------------------------------------------
+ *
+ * Changes:
+ *   Jan 20, 2004   moved TTY driver to user-space  (Jorrit N. Herder)
+ *   Sep 20, 2004   local timer management/ sync alarms  (Jorrit N. Herder)
+ *   Jul 13, 2004   support for function key observers  (Jorrit N. Herder)  
+ */
+
+#include "../drivers.h"
+#include "../drivers.h"
+#include <termios.h>
+#if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
+#include <sgtty.h>
+#endif
+#include <sys/ioc_tty.h>
+#include <signal.h>
+#include <minix/callnr.h>
+#if (CHIP == INTEL)
+#include <minix/keymap.h>
+#endif
+#include "tty.h"
+
+#include <sys/time.h>
+#include <sys/select.h>
+
+extern int irq_hook_id;
+
+unsigned long kbd_irq_set = 0;
+unsigned long rs_irq_set = 0;
+
+/* Address of a tty structure. */
+#define tty_addr(line)	(&tty_table[line])
+
+/* Macros for magic tty types. */
+#define isconsole(tp)	((tp) < tty_addr(NR_CONS))
+#define ispty(tp)	((tp) >= tty_addr(NR_CONS+NR_RS_LINES))
+
+/* Macros for magic tty structure pointers. */
+#define FIRST_TTY	tty_addr(0)
+#define END_TTY		tty_addr(sizeof(tty_table) / sizeof(tty_table[0]))
+
+/* A device exists if at least its 'devread' function is defined. */
+#define tty_active(tp)	((tp)->tty_devread != NULL)
+
+/* RS232 lines or pseudo terminals can be completely configured out. */
+#if NR_RS_LINES == 0
+#define rs_init(tp)	((void) 0)
+#endif
+#if NR_PTYS == 0
+#define pty_init(tp)	((void) 0)
+#define do_pty(tp, mp)	((void) 0)
+#endif
+
+struct kmessages kmess;
+
+FORWARD _PROTOTYPE( void tty_timed_out, (timer_t *tp)			);
+FORWARD _PROTOTYPE( void expire_timers, (void)				);
+FORWARD _PROTOTYPE( void settimer, (tty_t *tty_ptr, int enable)		);
+FORWARD _PROTOTYPE( void do_cancel, (tty_t *tp, message *m_ptr)		);
+FORWARD _PROTOTYPE( void do_ioctl, (tty_t *tp, message *m_ptr)		);
+FORWARD _PROTOTYPE( void do_open, (tty_t *tp, message *m_ptr)		);
+FORWARD _PROTOTYPE( void do_close, (tty_t *tp, message *m_ptr)		);
+FORWARD _PROTOTYPE( void do_read, (tty_t *tp, message *m_ptr)		);
+FORWARD _PROTOTYPE( void do_write, (tty_t *tp, message *m_ptr)		);
+FORWARD _PROTOTYPE( void do_select, (tty_t *tp, message *m_ptr)		);
+FORWARD _PROTOTYPE( void do_status, (message *m_ptr)			);
+FORWARD _PROTOTYPE( void in_transfer, (tty_t *tp)			);
+FORWARD _PROTOTYPE( int tty_echo, (tty_t *tp, int ch)			);
+FORWARD _PROTOTYPE( void rawecho, (tty_t *tp, int ch)			);
+FORWARD _PROTOTYPE( int back_over, (tty_t *tp)				);
+FORWARD _PROTOTYPE( void reprint, (tty_t *tp)				);
+FORWARD _PROTOTYPE( void dev_ioctl, (tty_t *tp)				);
+FORWARD _PROTOTYPE( void setattr, (tty_t *tp)				);
+FORWARD _PROTOTYPE( void tty_icancel, (tty_t *tp)			);
+FORWARD _PROTOTYPE( void tty_init, (void)				);
+#if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
+FORWARD _PROTOTYPE( int compat_getp, (tty_t *tp, struct sgttyb *sg)	);
+FORWARD _PROTOTYPE( int compat_getc, (tty_t *tp, struct tchars *sg)	);
+FORWARD _PROTOTYPE( int compat_setp, (tty_t *tp, struct sgttyb *sg)	);
+FORWARD _PROTOTYPE( int compat_setc, (tty_t *tp, struct tchars *sg)	);
+FORWARD _PROTOTYPE( int tspd2sgspd, (speed_t tspd)			);
+FORWARD _PROTOTYPE( speed_t sgspd2tspd, (int sgspd)			);
+#if ENABLE_BINCOMPAT
+FORWARD _PROTOTYPE( void do_ioctl_compat, (tty_t *tp, message *m_ptr)	);
+#endif
+#endif
+
+/* Default attributes. */
+PRIVATE struct termios termios_defaults = {
+  TINPUT_DEF, TOUTPUT_DEF, TCTRL_DEF, TLOCAL_DEF, TSPEED_DEF, TSPEED_DEF,
+  {
+	TEOF_DEF, TEOL_DEF, TERASE_DEF, TINTR_DEF, TKILL_DEF, TMIN_DEF,
+	TQUIT_DEF, TTIME_DEF, TSUSP_DEF, TSTART_DEF, TSTOP_DEF,
+	TREPRINT_DEF, TLNEXT_DEF, TDISCARD_DEF,
+  },
+};
+PRIVATE struct winsize winsize_defaults;	/* = all zeroes */
+
+/* Global variables for the TTY task (declared extern in tty.h). */
+PUBLIC tty_t tty_table[NR_CONS+NR_RS_LINES+NR_PTYS];
+PUBLIC int ccurrent;			/* currently active console */
+PUBLIC timer_t *tty_timers;		/* queue of TTY timers */
+PUBLIC clock_t tty_next_timeout;	/* time that the next alarm is due */
+PUBLIC struct machine machine;		/* kernel environment variables */
+
+/*===========================================================================*
+ *				tty_task				     *
+ *===========================================================================*/
+PUBLIC void main(void)
+{
+/* Main routine of the terminal task. */
+
+  message tty_mess;		/* buffer for all incoming messages */
+  unsigned line;
+  int r, s;
+  register struct proc *rp;
+  register tty_t *tp;
+
+#if DEBUG
+  kputc('H');
+  kputc('e');
+  kputc('l');
+  kputc('l');
+  kputc('o');
+  kputc(',');
+  kputc(' ');
+  printf("TTY\n");
+#endif
+
+  /* Get kernel environment (protected_mode, pc_at and ega are needed). */ 
+  if (OK != (s=sys_getmachine(&machine))) {
+    panic("TTY","Couldn't obtain kernel environment.", s);
+  }
+
+  /* Initialize the TTY driver. */
+  tty_init();
+
+  /* Final one-time keyboard initialization. */
+  kb_init_once();
+
+  printf("\n");
+
+  while (TRUE) {
+
+	/* Check for and handle any events on any of the ttys. */
+	for (tp = FIRST_TTY; tp < END_TTY; tp++) {
+		if (tp->tty_events) handle_events(tp);
+	}
+
+	/* Get a request message. */
+	r= receive(ANY, &tty_mess);
+	if (r != 0)
+		panic("TTY", "receive failed with %d", r);
+
+	/* First handle all kernel notification types that the TTY supports. 
+	 *  - An alarm went off, expire all timers and handle the events. 
+	 *  - A hardware interrupt also is an invitation to check for events. 
+	 *  - A new kernel message is available for printing.
+	 *  - Reset the console on system shutdown. 
+	 * Then see if this message is different from a normal device driver
+	 * request and should be handled separately. These extra functions
+	 * do not operate on a device, in constrast to the driver requests. 
+	 */
+	switch (tty_mess.m_type) { 
+	case SYN_ALARM: 		/* fall through */
+		expire_timers();	/* run watchdogs of expired timers */
+		continue;		/* contine to check for events */
+	case DEV_PING:
+		notify(tty_mess.m_source);
+		continue;
+	case HARD_INT: {		/* hardware interrupt notification */
+		if (tty_mess.NOTIFY_ARG & kbd_irq_set)
+			kbd_interrupt(&tty_mess);/* fetch chars from keyboard */
+#if NR_RS_LINES > 0
+		if (tty_mess.NOTIFY_ARG & rs_irq_set)
+			rs_interrupt(&tty_mess);/* serial I/O */
+#endif
+		expire_timers();	/* run watchdogs of expired timers */
+		continue;		/* contine to check for events */
+	}
+	case PROC_EVENT: {
+		cons_stop();		/* switch to primary console */
+		printf("TTY got PROC_EVENT, assuming SIGTERM\n");
+#if DEAD_CODE
+		if (irq_hook_id != -1) {
+			sys_irqdisable(&irq_hook_id);
+			sys_irqrmpolicy(KEYBOARD_IRQ, &irq_hook_id);
+		}
+#endif
+		continue;
+	}
+	case SYS_SIG: {			/* system signal */
+		sigset_t sigset = (sigset_t) tty_mess.NOTIFY_ARG;
+		if (sigismember(&sigset, SIGKMESS)) do_new_kmess(&tty_mess);
+		continue;
+	}
+	case DIAGNOSTICS: 		/* a server wants to print some */
+		do_diagnostics(&tty_mess);
+		continue;
+	case GET_KMESS:
+		do_get_kmess(&tty_mess);
+		continue;
+	case FKEY_CONTROL:		/* (un)register a fkey observer */
+		do_fkey_ctl(&tty_mess);
+		continue;
+	default:			/* should be a driver request */
+		;			/* do nothing; end switch */
+	}
+
+	/* Only device requests should get to this point. All requests, 
+	 * except DEV_STATUS, have a minor device number. Check this
+	 * exception and get the minor device number otherwise.
+	 */
+	if (tty_mess.m_type == DEV_STATUS) {
+		do_status(&tty_mess);
+		continue;
+	}
+	line = tty_mess.TTY_LINE;
+	if (line == KBD_MINOR) {
+		do_kbd(&tty_mess);
+		continue;
+	} else if (line == KBDAUX_MINOR) {
+		do_kbdaux(&tty_mess);
+		continue;
+	} else if (line == VIDEO_MINOR) {
+		do_video(&tty_mess);
+		continue;
+	} else if ((line - CONS_MINOR) < NR_CONS) {
+		tp = tty_addr(line - CONS_MINOR);
+	} else if (line == LOG_MINOR) {
+		tp = tty_addr(0);
+	} else if ((line - RS232_MINOR) < NR_RS_LINES) {
+		tp = tty_addr(line - RS232_MINOR + NR_CONS);
+	} else if ((line - TTYPX_MINOR) < NR_PTYS) {
+		tp = tty_addr(line - TTYPX_MINOR + NR_CONS + NR_RS_LINES);
+	} else if ((line - PTYPX_MINOR) < NR_PTYS) {
+		tp = tty_addr(line - PTYPX_MINOR + NR_CONS + NR_RS_LINES);
+		if (tty_mess.m_type != DEV_IOCTL) {
+			do_pty(tp, &tty_mess);
+			continue;
+		}
+	} else {
+		tp = NULL;
+	}
+
+	/* If the device doesn't exist or is not configured return ENXIO. */
+	if (tp == NULL || ! tty_active(tp)) {
+		printf("Warning, TTY got illegal request %d from %d\n",
+			tty_mess.m_type, tty_mess.m_source);
+		if (tty_mess.m_source != LOG_PROC_NR)
+		{
+			tty_reply(TASK_REPLY, tty_mess.m_source,
+						tty_mess.IO_ENDPT, ENXIO);
+		}
+		continue;
+	}
+
+	/* Execute the requested device driver function. */
+	switch (tty_mess.m_type) {
+	    case DEV_READ:	 do_read(tp, &tty_mess);	  break;
+	    case DEV_WRITE:	 do_write(tp, &tty_mess);	  break;
+	    case DEV_IOCTL:	 do_ioctl(tp, &tty_mess);	  break;
+	    case DEV_OPEN:	 do_open(tp, &tty_mess);	  break;
+	    case DEV_CLOSE:	 do_close(tp, &tty_mess);	  break;
+	    case DEV_SELECT:	 do_select(tp, &tty_mess);	  break;
+	    case CANCEL:	 do_cancel(tp, &tty_mess);	  break;
+	    default:		
+		printf("Warning, TTY got unexpected request %d from %d\n",
+			tty_mess.m_type, tty_mess.m_source);
+	    tty_reply(TASK_REPLY, tty_mess.m_source,
+						tty_mess.IO_ENDPT, EINVAL);
+	}
+  }
+}
+
+/*===========================================================================*
+ *				do_status				     *
+ *===========================================================================*/
+PRIVATE void do_status(m_ptr)
+message *m_ptr;
+{
+  register struct tty *tp;
+  int event_found;
+  int status;
+  int ops;
+  
+  /* Check for select or revive events on any of the ttys. If we found an, 
+   * event return a single status message for it. The FS will make another 
+   * call to see if there is more.
+   */
+  event_found = 0;
+  for (tp = FIRST_TTY; tp < END_TTY; tp++) {
+	if ((ops = select_try(tp, tp->tty_select_ops)) && 
+			tp->tty_select_proc == m_ptr->m_source) {
+
+		/* I/O for a selected minor device is ready. */
+		m_ptr->m_type = DEV_IO_READY;
+		m_ptr->DEV_MINOR = tp->tty_minor;
+		m_ptr->DEV_SEL_OPS = ops;
+
+		tp->tty_select_ops &= ~ops;	/* unmark select event */
+  		event_found = 1;
+		break;
+	}
+	else if (tp->tty_inrevived && tp->tty_incaller == m_ptr->m_source) {
+		
+		/* Suspended request finished. Send a REVIVE. */
+		m_ptr->m_type = DEV_REVIVE;
+  		m_ptr->REP_ENDPT = tp->tty_inproc;
+  		m_ptr->REP_STATUS = tp->tty_incum;
+
+		tp->tty_inleft = tp->tty_incum = 0;
+		tp->tty_inrevived = 0;		/* unmark revive event */
+  		event_found = 1;
+  		break;
+	}
+	else if (tp->tty_outrevived && tp->tty_outcaller == m_ptr->m_source) {
+		
+		/* Suspended request finished. Send a REVIVE. */
+		m_ptr->m_type = DEV_REVIVE;
+  		m_ptr->REP_ENDPT = tp->tty_outproc;
+  		m_ptr->REP_STATUS = tp->tty_outcum;
+
+		tp->tty_outcum = 0;
+		tp->tty_outrevived = 0;		/* unmark revive event */
+  		event_found = 1;
+  		break;
+	}
+  }
+
+#if NR_PTYS > 0
+  if (!event_found)
+  	event_found = pty_status(m_ptr);
+#endif
+  if (!event_found)
+	event_found= kbd_status(m_ptr);
+
+  if (! event_found) {
+	/* No events of interest were found. Return an empty message. */
+  	m_ptr->m_type = DEV_NO_STATUS;
+  }
+
+  /* Almost done. Send back the reply message to the caller. */
+  if ((status = send(m_ptr->m_source, m_ptr)) != OK) {
+	panic("TTY","send in do_status failed, status\n", status);
+  }
+}
+
+/*===========================================================================*
+ *				do_read					     *
+ *===========================================================================*/
+PRIVATE void do_read(tp, m_ptr)
+register tty_t *tp;		/* pointer to tty struct */
+register message *m_ptr;	/* pointer to message sent to the task */
+{
+/* A process wants to read from a terminal. */
+  int r, status;
+  phys_bytes phys_addr;
+  int more_verbose= (tp == tty_addr(NR_CONS));
+
+  /* Check if there is already a process hanging in a read, check if the
+   * parameters are correct, do I/O.
+   */
+  if (tp->tty_inleft > 0) {
+	if (more_verbose) printf("do_read: EIO\n");
+	r = EIO;
+  } else
+  if (m_ptr->COUNT <= 0) {
+	if (more_verbose) printf("do_read: EINVAL\n");
+	r = EINVAL;
+  } else
+  if (sys_umap(m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS, m_ptr->COUNT,
+		&phys_addr) != OK) {
+	if (more_verbose) printf("do_read: EFAULT\n");
+	r = EFAULT;
+  } else {
+	/* Copy information from the message to the tty struct. */
+	tp->tty_inrepcode = TASK_REPLY;
+	tp->tty_incaller = m_ptr->m_source;
+	tp->tty_inproc = m_ptr->IO_ENDPT;
+	tp->tty_in_vir = (vir_bytes) m_ptr->ADDRESS;
+	tp->tty_inleft = m_ptr->COUNT;
+
+	if (!(tp->tty_termios.c_lflag & ICANON)
+					&& tp->tty_termios.c_cc[VTIME] > 0) {
+		if (tp->tty_termios.c_cc[VMIN] == 0) {
+			/* MIN & TIME specify a read timer that finishes the
+			 * read in TIME/10 seconds if no bytes are available.
+			 */
+			settimer(tp, TRUE);
+			tp->tty_min = 1;
+		} else {
+			/* MIN & TIME specify an inter-byte timer that may
+			 * have to be cancelled if there are no bytes yet.
+			 */
+			if (tp->tty_eotct == 0) {
+				settimer(tp, FALSE);
+				tp->tty_min = tp->tty_termios.c_cc[VMIN];
+			}
+		}
+	}
+
+	/* Anything waiting in the input buffer? Clear it out... */
+	in_transfer(tp);
+	/* ...then go back for more. */
+	handle_events(tp);
+	if (tp->tty_inleft == 0)  {
+  		if (tp->tty_select_ops)
+  			select_retry(tp);
+		return;			/* already done */
+	}
+
+	/* There were no bytes in the input queue available, so either suspend
+	 * the caller or break off the read if nonblocking.
+	 */
+	if (m_ptr->TTY_FLAGS & O_NONBLOCK) {
+		r = EAGAIN;				/* cancel the read */
+		tp->tty_inleft = tp->tty_incum = 0;
+	} else {
+		r = SUSPEND;				/* suspend the caller */
+		tp->tty_inrepcode = REVIVE;
+	}
+  }
+  if (more_verbose) printf("do_read: replying %d\n", r);
+  tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, r);
+  if (tp->tty_select_ops)
+  	select_retry(tp);
+}
+
+/*===========================================================================*
+ *				do_write				     *
+ *===========================================================================*/
+PRIVATE void do_write(tp, m_ptr)
+register tty_t *tp;
+register message *m_ptr;	/* pointer to message sent to the task */
+{
+/* A process wants to write on a terminal. */
+  int r;
+  phys_bytes phys_addr;
+
+  /* Check if there is already a process hanging in a write, check if the
+   * parameters are correct, do I/O.
+   */
+  if (tp->tty_outleft > 0) {
+	r = EIO;
+  } else
+  if (m_ptr->COUNT <= 0) {
+	r = EINVAL;
+  } else
+  if (sys_umap(m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS, m_ptr->COUNT,
+		&phys_addr) != OK) {
+	r = EFAULT;
+  } else {
+	/* Copy message parameters to the tty structure. */
+	tp->tty_outrepcode = TASK_REPLY;
+	tp->tty_outcaller = m_ptr->m_source;
+	tp->tty_outproc = m_ptr->IO_ENDPT;
+	tp->tty_out_vir = (vir_bytes) m_ptr->ADDRESS;
+	tp->tty_outleft = m_ptr->COUNT;
+
+	/* Try to write. */
+	handle_events(tp);
+	if (tp->tty_outleft == 0) 
+		return;	/* already done */
+
+	/* None or not all the bytes could be written, so either suspend the
+	 * caller or break off the write if nonblocking.
+	 */
+	if (m_ptr->TTY_FLAGS & O_NONBLOCK) {		/* cancel the write */
+		r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN;
+		tp->tty_outleft = tp->tty_outcum = 0;
+	} else {
+		r = SUSPEND;				/* suspend the caller */
+		tp->tty_outrepcode = REVIVE;
+	}
+  }
+  tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, r);
+}
+
+/*===========================================================================*
+ *				do_ioctl				     *
+ *===========================================================================*/
+PRIVATE void do_ioctl(tp, m_ptr)
+register tty_t *tp;
+message *m_ptr;			/* pointer to message sent to task */
+{
+/* Perform an IOCTL on this terminal. Posix termios calls are handled
+ * by the IOCTL system call
+ */
+
+  int r;
+  union {
+	int i;
+#if ENABLE_SRCCOMPAT
+	struct sgttyb sg;
+	struct tchars tc;
+#endif
+  } param;
+  size_t size;
+
+  /* Size of the ioctl parameter. */
+  switch (m_ptr->TTY_REQUEST) {
+    case TCGETS:        /* Posix tcgetattr function */
+    case TCSETS:        /* Posix tcsetattr function, TCSANOW option */ 
+    case TCSETSW:       /* Posix tcsetattr function, TCSADRAIN option */
+    case TCSETSF:	/* Posix tcsetattr function, TCSAFLUSH option */
+        size = sizeof(struct termios);
+        break;
+
+    case TCSBRK:        /* Posix tcsendbreak function */
+    case TCFLOW:        /* Posix tcflow function */
+    case TCFLSH:        /* Posix tcflush function */
+    case TIOCGPGRP:     /* Posix tcgetpgrp function */
+    case TIOCSPGRP:	/* Posix tcsetpgrp function */
+        size = sizeof(int);
+        break;
+
+    case TIOCGWINSZ:    /* get window size (not Posix) */
+    case TIOCSWINSZ:	/* set window size (not Posix) */
+        size = sizeof(struct winsize);
+        break;
+
+#if ENABLE_SRCCOMPAT
+    case TIOCGETP:      /* BSD-style get terminal properties */
+    case TIOCSETP:	/* BSD-style set terminal properties */
+	size = sizeof(struct sgttyb);
+	break;
+
+    case TIOCGETC:      /* BSD-style get terminal special characters */ 
+    case TIOCSETC:	/* BSD-style get terminal special characters */ 
+	size = sizeof(struct tchars);
+	break;
+#endif
+#if (MACHINE == IBM_PC)
+    case KIOCSMAP:	/* load keymap (Minix extension) */
+        size = sizeof(keymap_t);
+        break;
+
+    case TIOCSFON:	/* load font (Minix extension) */
+        size = sizeof(u8_t [8192]);
+        break;
+
+#endif
+    case TCDRAIN:	/* Posix tcdrain function -- no parameter */
+    default:		size = 0;
+  }
+
+  r = OK;
+  switch (m_ptr->TTY_REQUEST) {
+    case TCGETS:
+	/* Get the termios attributes. */
+	r = sys_vircopy(SELF, D, (vir_bytes) &tp->tty_termios,
+		m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS, 
+		(vir_bytes) size);
+	break;
+
+    case TCSETSW:
+    case TCSETSF:
+    case TCDRAIN:
+	if (tp->tty_outleft > 0) {
+		/* Wait for all ongoing output processing to finish. */
+		tp->tty_iocaller = m_ptr->m_source;
+		tp->tty_ioproc = m_ptr->IO_ENDPT;
+		tp->tty_ioreq = m_ptr->REQUEST;
+		tp->tty_iovir = (vir_bytes) m_ptr->ADDRESS;
+		r = SUSPEND;
+		break;
+	}
+	if (m_ptr->TTY_REQUEST == TCDRAIN) break;
+	if (m_ptr->TTY_REQUEST == TCSETSF) tty_icancel(tp);
+	/*FALL THROUGH*/
+    case TCSETS:
+	/* Set the termios attributes. */
+	r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
+		SELF, D, (vir_bytes) &tp->tty_termios, (vir_bytes) size);
+	if (r != OK) break;
+	setattr(tp);
+	break;
+
+    case TCFLSH:
+	r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
+		SELF, D, (vir_bytes) &param.i, (vir_bytes) size);
+	if (r != OK) break;
+	switch (param.i) {
+	    case TCIFLUSH:	tty_icancel(tp);		 	    break;
+	    case TCOFLUSH:	(*tp->tty_ocancel)(tp, 0);		    break;
+	    case TCIOFLUSH:	tty_icancel(tp); (*tp->tty_ocancel)(tp, 0); break;
+	    default:		r = EINVAL;
+	}
+	break;
+
+    case TCFLOW:
+	r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
+		SELF, D, (vir_bytes) &param.i, (vir_bytes) size);
+	if (r != OK) break;
+	switch (param.i) {
+	    case TCOOFF:
+	    case TCOON:
+		tp->tty_inhibited = (param.i == TCOOFF);
+		tp->tty_events = 1;
+		break;
+	    case TCIOFF:
+		(*tp->tty_echo)(tp, tp->tty_termios.c_cc[VSTOP]);
+		break;
+	    case TCION:
+		(*tp->tty_echo)(tp, tp->tty_termios.c_cc[VSTART]);
+		break;
+	    default:
+		r = EINVAL;
+	}
+	break;
+
+    case TCSBRK:
+	if (tp->tty_break != NULL) (*tp->tty_break)(tp,0);
+	break;
+
+    case TIOCGWINSZ:
+	r = sys_vircopy(SELF, D, (vir_bytes) &tp->tty_winsize,
+		m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS, 
+		(vir_bytes) size);
+	break;
+
+    case TIOCSWINSZ:
+	r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
+		SELF, D, (vir_bytes) &tp->tty_winsize, (vir_bytes) size);
+	sigchar(tp, SIGWINCH);
+	break;
+
+#if ENABLE_SRCCOMPAT
+    case TIOCGETP:
+	compat_getp(tp, &param.sg);
+	r = sys_vircopy(SELF, D, (vir_bytes) &param.sg,
+		m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
+		(vir_bytes) size);
+	break;
+
+    case TIOCSETP:
+	r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
+		SELF, D, (vir_bytes) &param.sg, (vir_bytes) size);
+	if (r != OK) break;
+	compat_setp(tp, &param.sg);
+	break;
+
+    case TIOCGETC:
+	compat_getc(tp, &param.tc);
+	r = sys_vircopy(SELF, D, (vir_bytes) &param.tc,
+		m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS, 
+		(vir_bytes) size);
+	break;
+
+    case TIOCSETC:
+	r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
+		SELF, D, (vir_bytes) &param.tc, (vir_bytes) size);
+	if (r != OK) break;
+	compat_setc(tp, &param.tc);
+	break;
+#endif
+
+#if (MACHINE == IBM_PC)
+    case KIOCSMAP:
+	/* Load a new keymap (only /dev/console). */
+	if (isconsole(tp)) r = kbd_loadmap(m_ptr);
+	break;
+
+    case TIOCSFON:
+	/* Load a font into an EGA or VGA card (hs@hck.hr) */
+	if (isconsole(tp)) r = con_loadfont(m_ptr);
+	break;
+#endif
+
+#if (MACHINE == ATARI)
+    case VDU_LOADFONT:
+	r = vdu_loadfont(m_ptr);
+	break;
+#endif
+
+/* These Posix functions are allowed to fail if _POSIX_JOB_CONTROL is 
+ * not defined.
+ */
+    case TIOCGPGRP:     
+    case TIOCSPGRP:	
+    default:
+#if ENABLE_BINCOMPAT
+	do_ioctl_compat(tp, m_ptr);
+	return;
+#else
+	r = ENOTTY;
+#endif
+  }
+
+  /* Send the reply. */
+  tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, r);
+}
+
+/*===========================================================================*
+ *				do_open					     *
+ *===========================================================================*/
+PRIVATE void do_open(tp, m_ptr)
+register tty_t *tp;
+message *m_ptr;			/* pointer to message sent to task */
+{
+/* A tty line has been opened.  Make it the callers controlling tty if
+ * O_NOCTTY is *not* set and it is not the log device.  1 is returned if
+ * the tty is made the controlling tty, otherwise OK or an error code.
+ */
+  int r = OK;
+
+  if (m_ptr->TTY_LINE == LOG_MINOR) {
+	/* The log device is a write-only diagnostics device. */
+	if (m_ptr->COUNT & R_BIT) r = EACCES;
+  } else {
+	if (!(m_ptr->COUNT & O_NOCTTY)) {
+		tp->tty_pgrp = m_ptr->IO_ENDPT;
+		r = 1;
+	}
+	tp->tty_openct++;
+  }
+  tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, r);
+}
+
+/*===========================================================================*
+ *				do_close				     *
+ *===========================================================================*/
+PRIVATE void do_close(tp, m_ptr)
+register tty_t *tp;
+message *m_ptr;			/* pointer to message sent to task */
+{
+/* A tty line has been closed.  Clean up the line if it is the last close. */
+
+  if (m_ptr->TTY_LINE != LOG_MINOR && --tp->tty_openct == 0) {
+	tp->tty_pgrp = 0;
+	tty_icancel(tp);
+	(*tp->tty_ocancel)(tp, 0);
+	(*tp->tty_close)(tp, 0);
+	tp->tty_termios = termios_defaults;
+	tp->tty_winsize = winsize_defaults;
+	setattr(tp);
+  }
+  tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, OK);
+}
+
+/*===========================================================================*
+ *				do_cancel				     *
+ *===========================================================================*/
+PRIVATE void do_cancel(tp, m_ptr)
+register tty_t *tp;
+message *m_ptr;			/* pointer to message sent to task */
+{
+/* A signal has been sent to a process that is hanging trying to read or write.
+ * The pending read or write must be finished off immediately.
+ */
+
+  int proc_nr;
+  int mode;
+
+  /* Check the parameters carefully, to avoid cancelling twice. */
+  proc_nr = m_ptr->IO_ENDPT;
+  mode = m_ptr->COUNT;
+  if ((mode & R_BIT) && tp->tty_inleft != 0 && proc_nr == tp->tty_inproc) {
+	/* Process was reading when killed.  Clean up input. */
+	tty_icancel(tp);
+	tp->tty_inleft = tp->tty_incum = 0;
+  }
+  if ((mode & W_BIT) && tp->tty_outleft != 0 && proc_nr == tp->tty_outproc) {
+	/* Process was writing when killed.  Clean up output. */
+	(*tp->tty_ocancel)(tp, 0);
+	tp->tty_outleft = tp->tty_outcum = 0;
+  }
+  if (tp->tty_ioreq != 0 && proc_nr == tp->tty_ioproc) {
+	/* Process was waiting for output to drain. */
+	tp->tty_ioreq = 0;
+  }
+  tp->tty_events = 1;
+  tty_reply(TASK_REPLY, m_ptr->m_source, proc_nr, EINTR);
+}
+
+PUBLIC int select_try(struct tty *tp, int ops)
+{
+	int ready_ops = 0;
+
+	/* Special case. If line is hung up, no operations will block.
+	 * (and it can be seen as an exceptional condition.)
+	 */
+	if (tp->tty_termios.c_ospeed == B0) {
+		ready_ops |= ops;
+	}
+
+	if (ops & SEL_RD) {
+		/* will i/o not block on read? */
+		if (tp->tty_inleft > 0) {
+			ready_ops |= SEL_RD;	/* EIO - no blocking */
+		} else if (tp->tty_incount > 0) {
+			/* Is a regular read possible? tty_incount
+			 * says there is data. But a read will only succeed
+			 * in canonical mode if a newline has been seen.
+			 */
+			if (!(tp->tty_termios.c_lflag & ICANON) ||
+				tp->tty_eotct > 0) {
+				ready_ops |= SEL_RD;
+			}
+		}
+	}
+
+	if (ops & SEL_WR)  {
+  		if (tp->tty_outleft > 0)  ready_ops |= SEL_WR;
+		else if ((*tp->tty_devwrite)(tp, 1)) ready_ops |= SEL_WR;
+	}
+	return ready_ops;
+}
+
+PUBLIC int select_retry(struct tty *tp)
+{
+  	if (tp->tty_select_ops && select_try(tp, tp->tty_select_ops))
+		notify(tp->tty_select_proc);
+	return OK;
+}
+
+/*===========================================================================*
+ *				handle_events				     *
+ *===========================================================================*/
+PUBLIC void handle_events(tp)
+tty_t *tp;			/* TTY to check for events. */
+{
+/* Handle any events pending on a TTY.  These events are usually device
+ * interrupts.
+ *
+ * Two kinds of events are prominent:
+ *	- a character has been received from the console or an RS232 line.
+ *	- an RS232 line has completed a write request (on behalf of a user).
+ * The interrupt handler may delay the interrupt message at its discretion
+ * to avoid swamping the TTY task.  Messages may be overwritten when the
+ * lines are fast or when there are races between different lines, input
+ * and output, because MINIX only provides single buffering for interrupt
+ * messages (in proc.c).  This is handled by explicitly checking each line
+ * for fresh input and completed output on each interrupt.
+ */
+  char *buf;
+  unsigned count;
+  int status;
+
+  do {
+	tp->tty_events = 0;
+
+	/* Read input and perform input processing. */
+	(*tp->tty_devread)(tp, 0);
+
+	/* Perform output processing and write output. */
+	(*tp->tty_devwrite)(tp, 0);
+
+	/* Ioctl waiting for some event? */
+	if (tp->tty_ioreq != 0) dev_ioctl(tp);
+  } while (tp->tty_events);
+
+  /* Transfer characters from the input queue to a waiting process. */
+  in_transfer(tp);
+
+  /* Reply if enough bytes are available. */
+  if (tp->tty_incum >= tp->tty_min && tp->tty_inleft > 0) {
+	if (tp->tty_inrepcode == REVIVE) {
+		notify(tp->tty_incaller);
+		tp->tty_inrevived = 1;
+	} else {
+		tty_reply(tp->tty_inrepcode, tp->tty_incaller, 
+			tp->tty_inproc, tp->tty_incum);
+		tp->tty_inleft = tp->tty_incum = 0;
+	}
+  }
+  if (tp->tty_select_ops)
+  {
+  	select_retry(tp);
+  }
+#if NR_PTYS > 0
+  if (ispty(tp))
+  	select_retry_pty(tp);
+#endif
+}
+
+/*===========================================================================*
+ *				in_transfer				     *
+ *===========================================================================*/
+PRIVATE void in_transfer(tp)
+register tty_t *tp;		/* pointer to terminal to read from */
+{
+/* Transfer bytes from the input queue to a process reading from a terminal. */
+
+  int ch;
+  int count;
+  char buf[64], *bp;
+
+  /* Force read to succeed if the line is hung up, looks like EOF to reader. */
+  if (tp->tty_termios.c_ospeed == B0) tp->tty_min = 0;
+
+  /* Anything to do? */
+  if (tp->tty_inleft == 0 || tp->tty_eotct < tp->tty_min) return;
+
+  bp = buf;
+  while (tp->tty_inleft > 0 && tp->tty_eotct > 0) {
+	ch = *tp->tty_intail;
+
+	if (!(ch & IN_EOF)) {
+		/* One character to be delivered to the user. */
+		*bp = ch & IN_CHAR;
+		tp->tty_inleft--;
+		if (++bp == bufend(buf)) {
+			/* Temp buffer full, copy to user space. */
+			sys_vircopy(SELF, D, (vir_bytes) buf, 
+				tp->tty_inproc, D, tp->tty_in_vir,
+				(vir_bytes) buflen(buf));
+			tp->tty_in_vir += buflen(buf);
+			tp->tty_incum += buflen(buf);
+			bp = buf;
+		}
+	}
+
+	/* Remove the character from the input queue. */
+	if (++tp->tty_intail == bufend(tp->tty_inbuf))
+		tp->tty_intail = tp->tty_inbuf;
+	tp->tty_incount--;
+	if (ch & IN_EOT) {
+		tp->tty_eotct--;
+		/* Don't read past a line break in canonical mode. */
+		if (tp->tty_termios.c_lflag & ICANON) tp->tty_inleft = 0;
+	}
+  }
+
+  if (bp > buf) {
+	/* Leftover characters in the buffer. */
+	count = bp - buf;
+	sys_vircopy(SELF, D, (vir_bytes) buf, 
+		tp->tty_inproc, D, tp->tty_in_vir, (vir_bytes) count);
+	tp->tty_in_vir += count;
+	tp->tty_incum += count;
+  }
+
+  /* Usually reply to the reader, possibly even if incum == 0 (EOF). */
+  if (tp->tty_inleft == 0) {
+	if (tp->tty_inrepcode == REVIVE) {
+		notify(tp->tty_incaller);
+		tp->tty_inrevived = 1;
+	} else {
+		tty_reply(tp->tty_inrepcode, tp->tty_incaller, 
+			tp->tty_inproc, tp->tty_incum);
+		tp->tty_inleft = tp->tty_incum = 0;
+	}
+  }
+}
+
+/*===========================================================================*
+ *				in_process				     *
+ *===========================================================================*/
+PUBLIC int in_process(tp, buf, count)
+register tty_t *tp;		/* terminal on which character has arrived */
+char *buf;			/* buffer with input characters */
+int count;			/* number of input characters */
+{
+/* Characters have just been typed in.  Process, save, and echo them.  Return
+ * the number of characters processed.
+ */
+
+  int ch, sig, ct;
+  int timeset = FALSE;
+  static unsigned char csize_mask[] = { 0x1F, 0x3F, 0x7F, 0xFF };
+
+  for (ct = 0; ct < count; ct++) {
+	/* Take one character. */
+	ch = *buf++ & BYTE;
+
+	/* Strip to seven bits? */
+	if (tp->tty_termios.c_iflag & ISTRIP) ch &= 0x7F;
+
+	/* Input extensions? */
+	if (tp->tty_termios.c_lflag & IEXTEN) {
+
+		/* Previous character was a character escape? */
+		if (tp->tty_escaped) {
+			tp->tty_escaped = NOT_ESCAPED;
+			ch |= IN_ESC;	/* protect character */
+		}
+
+		/* LNEXT (^V) to escape the next character? */
+		if (ch == tp->tty_termios.c_cc[VLNEXT]) {
+			tp->tty_escaped = ESCAPED;
+			rawecho(tp, '^');
+			rawecho(tp, '\b');
+			continue;	/* do not store the escape */
+		}
+
+		/* REPRINT (^R) to reprint echoed characters? */
+		if (ch == tp->tty_termios.c_cc[VREPRINT]) {
+			reprint(tp);
+			continue;
+		}
+	}
+
+	/* _POSIX_VDISABLE is a normal character value, so better escape it. */
+	if (ch == _POSIX_VDISABLE) ch |= IN_ESC;
+
+	/* Map CR to LF, ignore CR, or map LF to CR. */
+	if (ch == '\r') {
+		if (tp->tty_termios.c_iflag & IGNCR) continue;
+		if (tp->tty_termios.c_iflag & ICRNL) ch = '\n';
+	} else
+	if (ch == '\n') {
+		if (tp->tty_termios.c_iflag & INLCR) ch = '\r';
+	}
+
+	/* Canonical mode? */
+	if (tp->tty_termios.c_lflag & ICANON) {
+
+		/* Erase processing (rub out of last character). */
+		if (ch == tp->tty_termios.c_cc[VERASE]) {
+			(void) back_over(tp);
+			if (!(tp->tty_termios.c_lflag & ECHOE)) {
+				(void) tty_echo(tp, ch);
+			}
+			continue;
+		}
+
+		/* Kill processing (remove current line). */
+		if (ch == tp->tty_termios.c_cc[VKILL]) {
+			while (back_over(tp)) {}
+			if (!(tp->tty_termios.c_lflag & ECHOE)) {
+				(void) tty_echo(tp, ch);
+				if (tp->tty_termios.c_lflag & ECHOK)
+					rawecho(tp, '\n');
+			}
+			continue;
+		}
+
+		/* EOF (^D) means end-of-file, an invisible "line break". */
+		if (ch == tp->tty_termios.c_cc[VEOF]) ch |= IN_EOT | IN_EOF;
+
+		/* The line may be returned to the user after an LF. */
+		if (ch == '\n') ch |= IN_EOT;
+
+		/* Same thing with EOL, whatever it may be. */
+		if (ch == tp->tty_termios.c_cc[VEOL]) ch |= IN_EOT;
+	}
+
+	/* Start/stop input control? */
+	if (tp->tty_termios.c_iflag & IXON) {
+
+		/* Output stops on STOP (^S). */
+		if (ch == tp->tty_termios.c_cc[VSTOP]) {
+			tp->tty_inhibited = STOPPED;
+			tp->tty_events = 1;
+			continue;
+		}
+
+		/* Output restarts on START (^Q) or any character if IXANY. */
+		if (tp->tty_inhibited) {
+			if (ch == tp->tty_termios.c_cc[VSTART]
+					|| (tp->tty_termios.c_iflag & IXANY)) {
+				tp->tty_inhibited = RUNNING;
+				tp->tty_events = 1;
+				if (ch == tp->tty_termios.c_cc[VSTART])
+					continue;
+			}
+		}
+	}
+
+	if (tp->tty_termios.c_lflag & ISIG) {
+		/* Check for INTR (^?) and QUIT (^\) characters. */
+		if (ch == tp->tty_termios.c_cc[VINTR]
+					|| ch == tp->tty_termios.c_cc[VQUIT]) {
+			sig = SIGINT;
+			if (ch == tp->tty_termios.c_cc[VQUIT]) sig = SIGQUIT;
+			sigchar(tp, sig);
+			(void) tty_echo(tp, ch);
+			continue;
+		}
+	}
+
+	/* Is there space in the input buffer? */
+	if (tp->tty_incount == buflen(tp->tty_inbuf)) {
+		/* No space; discard in canonical mode, keep in raw mode. */
+		if (tp->tty_termios.c_lflag & ICANON) continue;
+		break;
+	}
+
+	if (!(tp->tty_termios.c_lflag & ICANON)) {
+		/* In raw mode all characters are "line breaks". */
+		ch |= IN_EOT;
+
+		/* Start an inter-byte timer? */
+		if (!timeset && tp->tty_termios.c_cc[VMIN] > 0
+				&& tp->tty_termios.c_cc[VTIME] > 0) {
+			settimer(tp, TRUE);
+			timeset = TRUE;
+		}
+	}
+
+	/* Perform the intricate function of echoing. */
+	if (tp->tty_termios.c_lflag & (ECHO|ECHONL)) ch = tty_echo(tp, ch);
+
+	/* Save the character in the input queue. */
+	*tp->tty_inhead++ = ch;
+	if (tp->tty_inhead == bufend(tp->tty_inbuf))
+		tp->tty_inhead = tp->tty_inbuf;
+	tp->tty_incount++;
+	if (ch & IN_EOT) tp->tty_eotct++;
+
+	/* Try to finish input if the queue threatens to overflow. */
+	if (tp->tty_incount == buflen(tp->tty_inbuf)) in_transfer(tp);
+  }
+  return ct;
+}
+
+/*===========================================================================*
+ *				echo					     *
+ *===========================================================================*/
+PRIVATE int tty_echo(tp, ch)
+register tty_t *tp;		/* terminal on which to echo */
+register int ch;		/* pointer to character to echo */
+{
+/* Echo the character if echoing is on.  Some control characters are echoed
+ * with their normal effect, other control characters are echoed as "^X",
+ * normal characters are echoed normally.  EOF (^D) is echoed, but immediately
+ * backspaced over.  Return the character with the echoed length added to its
+ * attributes.
+ */
+  int len, rp;
+
+  ch &= ~IN_LEN;
+  if (!(tp->tty_termios.c_lflag & ECHO)) {
+	if (ch == ('\n' | IN_EOT) && (tp->tty_termios.c_lflag
+					& (ICANON|ECHONL)) == (ICANON|ECHONL))
+		(*tp->tty_echo)(tp, '\n');
+	return(ch);
+  }
+
+  /* "Reprint" tells if the echo output has been messed up by other output. */
+  rp = tp->tty_incount == 0 ? FALSE : tp->tty_reprint;
+
+  if ((ch & IN_CHAR) < ' ') {
+	switch (ch & (IN_ESC|IN_EOF|IN_EOT|IN_CHAR)) {
+	    case '\t':
+		len = 0;
+		do {
+			(*tp->tty_echo)(tp, ' ');
+			len++;
+		} while (len < TAB_SIZE && (tp->tty_position & TAB_MASK) != 0);
+		break;
+	    case '\r' | IN_EOT:
+	    case '\n' | IN_EOT:
+		(*tp->tty_echo)(tp, ch & IN_CHAR);
+		len = 0;
+		break;
+	    default:
+		(*tp->tty_echo)(tp, '^');
+		(*tp->tty_echo)(tp, '@' + (ch & IN_CHAR));
+		len = 2;
+	}
+  } else
+  if ((ch & IN_CHAR) == '\177') {
+	/* A DEL prints as "^?". */
+	(*tp->tty_echo)(tp, '^');
+	(*tp->tty_echo)(tp, '?');
+	len = 2;
+  } else {
+	(*tp->tty_echo)(tp, ch & IN_CHAR);
+	len = 1;
+  }
+  if (ch & IN_EOF) while (len > 0) { (*tp->tty_echo)(tp, '\b'); len--; }
+
+  tp->tty_reprint = rp;
+  return(ch | (len << IN_LSHIFT));
+}
+
+/*===========================================================================*
+ *				rawecho					     *
+ *===========================================================================*/
+PRIVATE void rawecho(tp, ch)
+register tty_t *tp;
+int ch;
+{
+/* Echo without interpretation if ECHO is set. */
+  int rp = tp->tty_reprint;
+  if (tp->tty_termios.c_lflag & ECHO) (*tp->tty_echo)(tp, ch);
+  tp->tty_reprint = rp;
+}
+
+/*===========================================================================*
+ *				back_over				     *
+ *===========================================================================*/
+PRIVATE int back_over(tp)
+register tty_t *tp;
+{
+/* Backspace to previous character on screen and erase it. */
+  u16_t *head;
+  int len;
+
+  if (tp->tty_incount == 0) return(0);	/* queue empty */
+  head = tp->tty_inhead;
+  if (head == tp->tty_inbuf) head = bufend(tp->tty_inbuf);
+  if (*--head & IN_EOT) return(0);		/* can't erase "line breaks" */
+  if (tp->tty_reprint) reprint(tp);		/* reprint if messed up */
+  tp->tty_inhead = head;
+  tp->tty_incount--;
+  if (tp->tty_termios.c_lflag & ECHOE) {
+	len = (*head & IN_LEN) >> IN_LSHIFT;
+	while (len > 0) {
+		rawecho(tp, '\b');
+		rawecho(tp, ' ');
+		rawecho(tp, '\b');
+		len--;
+	}
+  }
+  return(1);				/* one character erased */
+}
+
+/*===========================================================================*
+ *				reprint					     *
+ *===========================================================================*/
+PRIVATE void reprint(tp)
+register tty_t *tp;		/* pointer to tty struct */
+{
+/* Restore what has been echoed to screen before if the user input has been
+ * messed up by output, or if REPRINT (^R) is typed.
+ */
+  int count;
+  u16_t *head;
+
+  tp->tty_reprint = FALSE;
+
+  /* Find the last line break in the input. */
+  head = tp->tty_inhead;
+  count = tp->tty_incount;
+  while (count > 0) {
+	if (head == tp->tty_inbuf) head = bufend(tp->tty_inbuf);
+	if (head[-1] & IN_EOT) break;
+	head--;
+	count--;
+  }
+  if (count == tp->tty_incount) return;		/* no reason to reprint */
+
+  /* Show REPRINT (^R) and move to a new line. */
+  (void) tty_echo(tp, tp->tty_termios.c_cc[VREPRINT] | IN_ESC);
+  rawecho(tp, '\r');
+  rawecho(tp, '\n');
+
+  /* Reprint from the last break onwards. */
+  do {
+	if (head == bufend(tp->tty_inbuf)) head = tp->tty_inbuf;
+	*head = tty_echo(tp, *head);
+	head++;
+	count++;
+  } while (count < tp->tty_incount);
+}
+
+/*===========================================================================*
+ *				out_process				     *
+ *===========================================================================*/
+PUBLIC void out_process(tp, bstart, bpos, bend, icount, ocount)
+tty_t *tp;
+char *bstart, *bpos, *bend;	/* start/pos/end of circular buffer */
+int *icount;			/* # input chars / input chars used */
+int *ocount;			/* max output chars / output chars used */
+{
+/* Perform output processing on a circular buffer.  *icount is the number of
+ * bytes to process, and the number of bytes actually processed on return.
+ * *ocount is the space available on input and the space used on output.
+ * (Naturally *icount < *ocount.)  The column position is updated modulo
+ * the TAB size, because we really only need it for tabs.
+ */
+
+  int tablen;
+  int ict = *icount;
+  int oct = *ocount;
+  int pos = tp->tty_position;
+
+  while (ict > 0) {
+	switch (*bpos) {
+	case '\7':
+		break;
+	case '\b':
+		pos--;
+		break;
+	case '\r':
+		pos = 0;
+		break;
+	case '\n':
+		if ((tp->tty_termios.c_oflag & (OPOST|ONLCR))
+							== (OPOST|ONLCR)) {
+			/* Map LF to CR+LF if there is space.  Note that the
+			 * next character in the buffer is overwritten, so
+			 * we stop at this point.
+			 */
+			if (oct >= 2) {
+				*bpos = '\r';
+				if (++bpos == bend) bpos = bstart;
+				*bpos = '\n';
+				pos = 0;
+				ict--;
+				oct -= 2;
+			}
+			goto out_done;	/* no space or buffer got changed */
+		}
+		break;
+	case '\t':
+		/* Best guess for the tab length. */
+		tablen = TAB_SIZE - (pos & TAB_MASK);
+
+		if ((tp->tty_termios.c_oflag & (OPOST|XTABS))
+							== (OPOST|XTABS)) {
+			/* Tabs must be expanded. */
+			if (oct >= tablen) {
+				pos += tablen;
+				ict--;
+				oct -= tablen;
+				do {
+					*bpos = ' ';
+					if (++bpos == bend) bpos = bstart;
+				} while (--tablen != 0);
+			}
+			goto out_done;
+		}
+		/* Tabs are output directly. */
+		pos += tablen;
+		break;
+	default:
+		/* Assume any other character prints as one character. */
+		pos++;
+	}
+	if (++bpos == bend) bpos = bstart;
+	ict--;
+	oct--;
+  }
+out_done:
+  tp->tty_position = pos & TAB_MASK;
+
+  *icount -= ict;	/* [io]ct are the number of chars not used */
+  *ocount -= oct;	/* *[io]count are the number of chars that are used */
+}
+
+/*===========================================================================*
+ *				dev_ioctl				     *
+ *===========================================================================*/
+PRIVATE void dev_ioctl(tp)
+tty_t *tp;
+{
+/* The ioctl's TCSETSW, TCSETSF and TCDRAIN wait for output to finish to make
+ * sure that an attribute change doesn't affect the processing of current
+ * output.  Once output finishes the ioctl is executed as in do_ioctl().
+ */
+  int result;
+
+  if (tp->tty_outleft > 0) return;		/* output not finished */
+
+  if (tp->tty_ioreq != TCDRAIN) {
+	if (tp->tty_ioreq == TCSETSF) tty_icancel(tp);
+	result = sys_vircopy(tp->tty_ioproc, D, tp->tty_iovir,
+			SELF, D, (vir_bytes) &tp->tty_termios,
+			(vir_bytes) sizeof(tp->tty_termios));
+	setattr(tp);
+  }
+  tp->tty_ioreq = 0;
+  tty_reply(REVIVE, tp->tty_iocaller, tp->tty_ioproc, result);
+}
+
+/*===========================================================================*
+ *				setattr					     *
+ *===========================================================================*/
+PRIVATE void setattr(tp)
+tty_t *tp;
+{
+/* Apply the new line attributes (raw/canonical, line speed, etc.) */
+  u16_t *inp;
+  int count;
+
+  if (!(tp->tty_termios.c_lflag & ICANON)) {
+	/* Raw mode; put a "line break" on all characters in the input queue.
+	 * It is undefined what happens to the input queue when ICANON is
+	 * switched off, a process should use TCSAFLUSH to flush the queue.
+	 * Keeping the queue to preserve typeahead is the Right Thing, however
+	 * when a process does use TCSANOW to switch to raw mode.
+	 */
+	count = tp->tty_eotct = tp->tty_incount;
+	inp = tp->tty_intail;
+	while (count > 0) {
+		*inp |= IN_EOT;
+		if (++inp == bufend(tp->tty_inbuf)) inp = tp->tty_inbuf;
+		--count;
+	}
+  }
+
+  /* Inspect MIN and TIME. */
+  settimer(tp, FALSE);
+  if (tp->tty_termios.c_lflag & ICANON) {
+	/* No MIN & TIME in canonical mode. */
+	tp->tty_min = 1;
+  } else {
+	/* In raw mode MIN is the number of chars wanted, and TIME how long
+	 * to wait for them.  With interesting exceptions if either is zero.
+	 */
+	tp->tty_min = tp->tty_termios.c_cc[VMIN];
+	if (tp->tty_min == 0 && tp->tty_termios.c_cc[VTIME] > 0)
+		tp->tty_min = 1;
+  }
+
+  if (!(tp->tty_termios.c_iflag & IXON)) {
+	/* No start/stop output control, so don't leave output inhibited. */
+	tp->tty_inhibited = RUNNING;
+	tp->tty_events = 1;
+  }
+
+  /* Setting the output speed to zero hangs up the phone. */
+  if (tp->tty_termios.c_ospeed == B0) sigchar(tp, SIGHUP);
+
+  /* Set new line speed, character size, etc at the device level. */
+  (*tp->tty_ioctl)(tp, 0);
+}
+
+/*===========================================================================*
+ *				tty_reply				     *
+ *===========================================================================*/
+PUBLIC void tty_reply(code, replyee, proc_nr, status)
+int code;			/* TASK_REPLY or REVIVE */
+int replyee;			/* destination address for the reply */
+int proc_nr;			/* to whom should the reply go? */
+int status;			/* reply code */
+{
+/* Send a reply to a process that wanted to read or write data. */
+  message tty_mess;
+
+  tty_mess.m_type = code;
+  tty_mess.REP_ENDPT = proc_nr;
+  tty_mess.REP_STATUS = status;
+
+  if ((status = send(replyee, &tty_mess)) != OK) {
+	printf("TTY: couldn't reply to %d\n", replyee);
+	panic("TTY","tty_reply failed, status\n", status);
+  }
+}
+
+/*===========================================================================*
+ *				sigchar					     *
+ *===========================================================================*/
+PUBLIC void sigchar(tp, sig)
+register tty_t *tp;
+int sig;			/* SIGINT, SIGQUIT, SIGKILL or SIGHUP */
+{
+/* Process a SIGINT, SIGQUIT or SIGKILL char from the keyboard or SIGHUP from
+ * a tty close, "stty 0", or a real RS-232 hangup.  MM will send the signal to
+ * the process group (INT, QUIT), all processes (KILL), or the session leader
+ * (HUP).
+ */
+  int status;
+
+  if (tp->tty_pgrp != 0) 
+      if (OK != (status = sys_kill(tp->tty_pgrp, sig)))
+        panic("TTY","Error, call to sys_kill failed", status);
+
+  if (!(tp->tty_termios.c_lflag & NOFLSH)) {
+	tp->tty_incount = tp->tty_eotct = 0;	/* kill earlier input */
+	tp->tty_intail = tp->tty_inhead;
+	(*tp->tty_ocancel)(tp, 0);			/* kill all output */
+	tp->tty_inhibited = RUNNING;
+	tp->tty_events = 1;
+  }
+}
+
+/*===========================================================================*
+ *				tty_icancel				     *
+ *===========================================================================*/
+PRIVATE void tty_icancel(tp)
+register tty_t *tp;
+{
+/* Discard all pending input, tty buffer or device. */
+
+  tp->tty_incount = tp->tty_eotct = 0;
+  tp->tty_intail = tp->tty_inhead;
+  (*tp->tty_icancel)(tp, 0);
+}
+
+/*===========================================================================*
+ *				tty_init				     *
+ *===========================================================================*/
+PRIVATE void tty_init()
+{
+/* Initialize tty structure and call device initialization routines. */
+
+  register tty_t *tp;
+  int s;
+  struct sigaction sa;
+
+  /* Initialize the terminal lines. */
+  for (tp = FIRST_TTY,s=0; tp < END_TTY; tp++,s++) {
+
+  	tp->tty_index = s;
+
+  	tmr_inittimer(&tp->tty_tmr);
+
+  	tp->tty_intail = tp->tty_inhead = tp->tty_inbuf;
+  	tp->tty_min = 1;
+  	tp->tty_termios = termios_defaults;
+  	tp->tty_icancel = tp->tty_ocancel = tp->tty_ioctl = tp->tty_close =
+								tty_devnop;
+  	if (tp < tty_addr(NR_CONS)) {
+		scr_init(tp);
+
+		/* Initialize the keyboard driver. */
+		kb_init(tp);
+
+  		tp->tty_minor = CONS_MINOR + s;
+  	} else
+  	if (tp < tty_addr(NR_CONS+NR_RS_LINES)) {
+		rs_init(tp);
+  		tp->tty_minor = RS232_MINOR + s-NR_CONS;
+  	} else {
+		pty_init(tp);
+		tp->tty_minor = s - (NR_CONS+NR_RS_LINES) + TTYPX_MINOR;
+  	}
+  }
+
+#if DEAD_CODE
+  /* Install signal handlers. Ask PM to transform signal into message. */
+  sa.sa_handler = SIG_MESS;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = 0;
+  if (sigaction(SIGTERM,&sa,NULL)<0) panic("TTY","sigaction failed", errno);
+  if (sigaction(SIGKMESS,&sa,NULL)<0) panic("TTY","sigaction failed", errno);
+  if (sigaction(SIGKSTOP,&sa,NULL)<0) panic("TTY","sigaction failed", errno);
+#endif
+#if DEBUG
+	printf("end of tty_init\n");
+#endif
+}
+
+/*===========================================================================*
+ *				tty_timed_out				     *
+ *===========================================================================*/
+PRIVATE void tty_timed_out(timer_t *tp)
+{
+/* This timer has expired. Set the events flag, to force processing. */
+  tty_t *tty_ptr;
+  tty_ptr = &tty_table[tmr_arg(tp)->ta_int];
+  tty_ptr->tty_min = 0;			/* force read to succeed */
+  tty_ptr->tty_events = 1;		
+}
+
+/*===========================================================================*
+ *				expire_timers			    	     *
+ *===========================================================================*/
+PRIVATE void expire_timers(void)
+{
+/* A synchronous alarm message was received. Check if there are any expired 
+ * timers. Possibly set the event flag and reschedule another alarm.  
+ */
+  clock_t now;				/* current time */
+  int s;
+
+  /* Get the current time to compare the timers against. */
+  if ((s=getuptime(&now)) != OK)
+ 	panic("TTY","Couldn't get uptime from clock.", s);
+
+  /* Scan the queue of timers for expired timers. This dispatch the watchdog
+   * functions of expired timers. Possibly a new alarm call must be scheduled.
+   */
+  tmrs_exptimers(&tty_timers, now, NULL);
+  if (tty_timers == NULL) tty_next_timeout = TMR_NEVER;
+  else {  					  /* set new sync alarm */
+  	tty_next_timeout = tty_timers->tmr_exp_time;
+  	if ((s=sys_setalarm(tty_next_timeout, 1)) != OK)
+ 		panic("TTY","Couldn't set synchronous alarm.", s);
+  }
+}
+
+/*===========================================================================*
+ *				settimer				     *
+ *===========================================================================*/
+PRIVATE void settimer(tty_ptr, enable)
+tty_t *tty_ptr;			/* line to set or unset a timer on */
+int enable;			/* set timer if true, otherwise unset */
+{
+  clock_t now;				/* current time */
+  clock_t exp_time;
+  int s;
+
+  /* Get the current time to calculate the timeout time. */
+  if ((s=getuptime(&now)) != OK)
+ 	panic("TTY","Couldn't get uptime from clock.", s);
+  if (enable) {
+  	exp_time = now + tty_ptr->tty_termios.c_cc[VTIME] * (HZ/10);
+ 	/* Set a new timer for enabling the TTY events flags. */
+ 	tmrs_settimer(&tty_timers, &tty_ptr->tty_tmr, 
+ 		exp_time, tty_timed_out, NULL);  
+  } else {
+  	/* Remove the timer from the active and expired lists. */
+  	tmrs_clrtimer(&tty_timers, &tty_ptr->tty_tmr, NULL);
+  }
+  
+  /* Now check if a new alarm must be scheduled. This happens when the front
+   * of the timers queue was disabled or reinserted at another position, or
+   * when a new timer was added to the front.
+   */
+  if (tty_timers == NULL) tty_next_timeout = TMR_NEVER;
+  else if (tty_timers->tmr_exp_time != tty_next_timeout) { 
+  	tty_next_timeout = tty_timers->tmr_exp_time;
+  	if ((s=sys_setalarm(tty_next_timeout, 1)) != OK)
+ 		panic("TTY","Couldn't set synchronous alarm.", s);
+  }
+}
+
+/*===========================================================================*
+ *				tty_devnop				     *
+ *===========================================================================*/
+PUBLIC int tty_devnop(tp, try)
+tty_t *tp;
+int try;
+{
+  /* Some functions need not be implemented at the device level. */
+}
+
+/*===========================================================================*
+ *				do_select				     *
+ *===========================================================================*/
+PRIVATE void do_select(tp, m_ptr)
+register tty_t *tp;		/* pointer to tty struct */
+register message *m_ptr;	/* pointer to message sent to the task */
+{
+	int ops, ready_ops = 0, watch;
+
+	ops = m_ptr->IO_ENDPT & (SEL_RD|SEL_WR|SEL_ERR);
+	watch = (m_ptr->IO_ENDPT & SEL_NOTIFY) ? 1 : 0;
+
+	ready_ops = select_try(tp, ops);
+
+	if (!ready_ops && ops && watch) {
+		tp->tty_select_ops |= ops;
+		tp->tty_select_proc = m_ptr->m_source;
+	}
+
+        tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, ready_ops);
+
+        return;
+}
+
+#if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
+/*===========================================================================*
+ *				compat_getp				     *
+ *===========================================================================*/
+PRIVATE int compat_getp(tp, sg)
+tty_t *tp;
+struct sgttyb *sg;
+{
+/* Translate an old TIOCGETP to the termios equivalent. */
+  int flgs;
+
+  sg->sg_erase = tp->tty_termios.c_cc[VERASE];
+  sg->sg_kill = tp->tty_termios.c_cc[VKILL];
+  sg->sg_ospeed = tspd2sgspd(cfgetospeed(&tp->tty_termios));
+  sg->sg_ispeed = tspd2sgspd(cfgetispeed(&tp->tty_termios));
+
+  flgs = 0;
+
+  /* XTABS	- if OPOST and XTABS */
+  if ((tp->tty_termios.c_oflag & (OPOST|XTABS)) == (OPOST|XTABS))
+	flgs |= 0006000;
+
+  /* BITS5..BITS8  - map directly to CS5..CS8 */
+  flgs |= (tp->tty_termios.c_cflag & CSIZE) << (8-2);
+
+  /* EVENP	- if PARENB and not PARODD */
+  if ((tp->tty_termios.c_cflag & (PARENB|PARODD)) == PARENB)
+	flgs |= 0000200;
+
+  /* ODDP	- if PARENB and PARODD */
+  if ((tp->tty_termios.c_cflag & (PARENB|PARODD)) == (PARENB|PARODD))
+	flgs |= 0000100;
+
+  /* RAW	- if not ICANON and not ISIG */
+  if (!(tp->tty_termios.c_lflag & (ICANON|ISIG)))
+	flgs |= 0000040;
+
+  /* CRMOD	- if ICRNL */
+  if (tp->tty_termios.c_iflag & ICRNL)
+	flgs |= 0000020;
+
+  /* ECHO	- if ECHO */
+  if (tp->tty_termios.c_lflag & ECHO)
+	flgs |= 0000010;
+
+  /* CBREAK	- if not ICANON and ISIG */
+  if ((tp->tty_termios.c_lflag & (ICANON|ISIG)) == ISIG)
+	flgs |= 0000002;
+
+  sg->sg_flags = flgs;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				compat_getc				     *
+ *===========================================================================*/
+PRIVATE int compat_getc(tp, tc)
+tty_t *tp;
+struct tchars *tc;
+{
+/* Translate an old TIOCGETC to the termios equivalent. */
+
+  tc->t_intrc = tp->tty_termios.c_cc[VINTR];
+  tc->t_quitc = tp->tty_termios.c_cc[VQUIT];
+  tc->t_startc = tp->tty_termios.c_cc[VSTART];
+  tc->t_stopc = tp->tty_termios.c_cc[VSTOP];
+  tc->t_brkc = tp->tty_termios.c_cc[VEOL];
+  tc->t_eofc = tp->tty_termios.c_cc[VEOF];
+  return(OK);
+}
+
+/*===========================================================================*
+ *				compat_setp				     *
+ *===========================================================================*/
+PRIVATE int compat_setp(tp, sg)
+tty_t *tp;
+struct sgttyb *sg;
+{
+/* Translate an old TIOCSETP to the termios equivalent. */
+  struct termios termios;
+  int flags;
+
+  termios = tp->tty_termios;
+
+  termios.c_cc[VERASE] = sg->sg_erase;
+  termios.c_cc[VKILL] = sg->sg_kill;
+  cfsetispeed(&termios, sgspd2tspd(sg->sg_ispeed & BYTE));
+  cfsetospeed(&termios, sgspd2tspd(sg->sg_ospeed & BYTE));
+  flags = sg->sg_flags;
+
+  /* Input flags */
+
+  /* BRKINT	- not changed */
+  /* ICRNL	- set if CRMOD is set and not RAW */
+  /*		  (CRMOD also controls output) */
+  termios.c_iflag &= ~ICRNL;
+  if ((flags & 0000020) && !(flags & 0000040))
+	termios.c_iflag |= ICRNL;
+
+  /* IGNBRK	- not changed */
+  /* IGNCR	- forced off (ignoring cr's is not supported) */
+  termios.c_iflag &= ~IGNCR;
+
+  /* IGNPAR	- not changed */
+  /* INLCR	- forced off (mapping nl's to cr's is not supported) */
+  termios.c_iflag &= ~INLCR;
+
+  /* INPCK	- not changed */
+  /* ISTRIP	- not changed */
+  /* IXOFF	- not changed */
+  /* IXON	- forced on if not RAW */
+  termios.c_iflag &= ~IXON;
+  if (!(flags & 0000040))
+	termios.c_iflag |= IXON;
+
+  /* PARMRK	- not changed */
+
+  /* Output flags */
+
+  /* OPOST	- forced on if not RAW */
+  termios.c_oflag &= ~OPOST;
+  if (!(flags & 0000040))
+	termios.c_oflag |= OPOST;
+
+  /* ONLCR	- forced on if CRMOD */
+  termios.c_oflag &= ~ONLCR;
+  if (flags & 0000020)
+	termios.c_oflag |= ONLCR;
+
+  /* XTABS	- forced on if XTABS */
+  termios.c_oflag &= ~XTABS;
+  if (flags & 0006000)
+	termios.c_oflag |= XTABS;
+
+  /* CLOCAL	- not changed */
+  /* CREAD	- forced on (receiver is always enabled) */
+  termios.c_cflag |= CREAD;
+
+  /* CSIZE	- CS5-CS8 correspond directly to BITS5-BITS8 */
+  termios.c_cflag = (termios.c_cflag & ~CSIZE) | ((flags & 0001400) >> (8-2));
+
+  /* CSTOPB	- not changed */
+  /* HUPCL	- not changed */
+  /* PARENB	- set if EVENP or ODDP is set */
+  termios.c_cflag &= ~PARENB;
+  if (flags & (0000200|0000100))
+	termios.c_cflag |= PARENB;
+
+  /* PARODD	- set if ODDP is set */
+  termios.c_cflag &= ~PARODD;
+  if (flags & 0000100)
+	termios.c_cflag |= PARODD;
+
+  /* Local flags */
+
+  /* ECHO		- set if ECHO is set */
+  termios.c_lflag &= ~ECHO;
+  if (flags & 0000010)
+	termios.c_lflag |= ECHO;
+
+  /* ECHOE	- not changed */
+  /* ECHOK	- not changed */
+  /* ECHONL	- not changed */
+  /* ICANON	- set if neither CBREAK nor RAW */
+  termios.c_lflag &= ~ICANON;
+  if (!(flags & (0000002|0000040)))
+	termios.c_lflag |= ICANON;
+
+  /* IEXTEN	- set if not RAW */
+  /* ISIG	- set if not RAW */
+  termios.c_lflag &= ~(IEXTEN|ISIG);
+  if (!(flags & 0000040))
+	termios.c_lflag |= (IEXTEN|ISIG);
+
+  /* NOFLSH	- not changed */
+  /* TOSTOP	- not changed */
+
+  tp->tty_termios = termios;
+  setattr(tp);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				compat_setc				     *
+ *===========================================================================*/
+PRIVATE int compat_setc(tp, tc)
+tty_t *tp;
+struct tchars *tc;
+{
+/* Translate an old TIOCSETC to the termios equivalent. */
+  struct termios termios;
+
+  termios = tp->tty_termios;
+
+  termios.c_cc[VINTR] = tc->t_intrc;
+  termios.c_cc[VQUIT] = tc->t_quitc;
+  termios.c_cc[VSTART] = tc->t_startc;
+  termios.c_cc[VSTOP] = tc->t_stopc;
+  termios.c_cc[VEOL] = tc->t_brkc;
+  termios.c_cc[VEOF] = tc->t_eofc;
+
+  tp->tty_termios = termios;
+  setattr(tp);
+  return(OK);
+}
+
+/* Table of termios line speed to sgtty line speed translations.   All termios
+ * speeds are present even if sgtty didn't know about them.  (Now it does.)
+ */
+PRIVATE struct s2s {
+  speed_t	tspd;
+  u8_t		sgspd;
+} ts2sgs[] = {
+  { B0,		  0 },
+  { B50,	 50 },
+  { B75,	 75 },
+  { B110,	  1 },
+  { B134,	134 },
+  { B200,	  2 },
+  { B300,	  3 },
+  { B600,	  6 },
+  { B1200,	 12 },
+  { B1800,	 18 },
+  { B2400,	 24 },
+  { B4800,	 48 },
+  { B9600,	 96 },
+  { B19200,	192 },
+  { B38400,	195 },
+  { B57600,	194 },
+  { B115200,	193 },
+};
+
+/*===========================================================================*
+ *				tspd2sgspd				     *
+ *===========================================================================*/
+PRIVATE int tspd2sgspd(tspd)
+speed_t tspd;
+{
+/* Translate a termios speed to sgtty speed. */
+  struct s2s *s;
+
+  for (s = ts2sgs; s < ts2sgs + sizeof(ts2sgs)/sizeof(ts2sgs[0]); s++) {
+	if (s->tspd == tspd) return(s->sgspd);
+  }
+  return 96;
+}
+
+/*===========================================================================*
+ *				sgspd2tspd				     *
+ *===========================================================================*/
+PRIVATE speed_t sgspd2tspd(sgspd)
+int sgspd;
+{
+/* Translate a sgtty speed to termios speed. */
+  struct s2s *s;
+
+  for (s = ts2sgs; s < ts2sgs + sizeof(ts2sgs)/sizeof(ts2sgs[0]); s++) {
+	if (s->sgspd == sgspd) return(s->tspd);
+  }
+  return B9600;
+}
+
+#if ENABLE_BINCOMPAT
+/*===========================================================================*
+ *				do_ioctl_compat				     *
+ *===========================================================================*/
+PRIVATE void do_ioctl_compat(tp, m_ptr)
+tty_t *tp;
+message *m_ptr;
+{
+/* Handle the old sgtty ioctl's that packed the sgtty or tchars struct into
+ * the Minix message.  Efficient then, troublesome now.
+ */
+  int minor, proc, func, result, r;
+  long flags, erki, spek;
+  u8_t erase, kill, intr, quit, xon, xoff, brk, eof, ispeed, ospeed;
+  struct sgttyb sg;
+  struct tchars tc;
+  message reply_mess;
+
+  minor = m_ptr->TTY_LINE;
+  proc = m_ptr->IO_ENDPT;
+  func = m_ptr->REQUEST;
+  spek = m_ptr->m2_l1;
+  flags = m_ptr->m2_l2;
+
+  switch(func)
+  {
+    case (('t'<<8) | 8):	/* TIOCGETP */
+	r = compat_getp(tp, &sg);
+	erase = sg.sg_erase;
+	kill = sg.sg_kill;
+	ispeed = sg.sg_ispeed;
+	ospeed = sg.sg_ospeed;
+	flags = sg.sg_flags;
+	erki = ((long)ospeed<<24) | ((long)ispeed<<16) | ((long)erase<<8) |kill;
+	break;
+    case (('t'<<8) | 18):	/* TIOCGETC */
+	r = compat_getc(tp, &tc);
+	intr = tc.t_intrc;
+	quit = tc.t_quitc;
+	xon = tc.t_startc;
+	xoff = tc.t_stopc;
+	brk = tc.t_brkc;
+	eof = tc.t_eofc;
+	erki = ((long)intr<<24) | ((long)quit<<16) | ((long)xon<<8) | xoff;
+	flags = (eof << 8) | brk;
+	break;
+    case (('t'<<8) | 17):	/* TIOCSETC */
+	tc.t_stopc = (spek >> 0) & 0xFF;
+	tc.t_startc = (spek >> 8) & 0xFF;
+	tc.t_quitc = (spek >> 16) & 0xFF;
+	tc.t_intrc = (spek >> 24) & 0xFF;
+	tc.t_brkc = (flags >> 0) & 0xFF;
+	tc.t_eofc = (flags >> 8) & 0xFF;
+	r = compat_setc(tp, &tc);
+	break;
+    case (('t'<<8) | 9):	/* TIOCSETP */
+	sg.sg_erase = (spek >> 8) & 0xFF;
+	sg.sg_kill = (spek >> 0) & 0xFF;
+	sg.sg_ispeed = (spek >> 16) & 0xFF;
+	sg.sg_ospeed = (spek >> 24) & 0xFF;
+	sg.sg_flags = flags;
+	r = compat_setp(tp, &sg);
+	break;
+    default:
+	r = ENOTTY;
+  }
+  reply_mess.m_type = TASK_REPLY;
+  reply_mess.REP_ENDPT = m_ptr->IO_ENDPT;
+  reply_mess.REP_STATUS = r;
+  reply_mess.m2_l1 = erki;
+  reply_mess.m2_l2 = flags;
+  send(m_ptr->m_source, &reply_mess);
+}
+#endif /* ENABLE_BINCOMPAT */
+#endif /* ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT */
+
Index: /trunk/minix/drivers/tty/tty.h
===================================================================
--- /trunk/minix/drivers/tty/tty.h	(revision 9)
+++ /trunk/minix/drivers/tty/tty.h	(revision 9)
@@ -0,0 +1,195 @@
+/*	tty.h - Terminals	*/
+
+#include <timers.h>
+#include "../../kernel/const.h"
+#include "../../kernel/type.h"
+
+#undef lock
+#undef unlock
+
+/* First minor numbers for the various classes of TTY devices. */
+#define CONS_MINOR	   0
+#define LOG_MINOR	  15
+#define RS232_MINOR	  16
+#define KBD_MINOR	 127
+#define KBDAUX_MINOR	 126
+#define VIDEO_MINOR	 125
+#define TTYPX_MINOR	 128
+#define PTYPX_MINOR	 192
+
+#define LINEWRAP	   1	/* console.c - wrap lines at column 80 */
+
+#define TTY_IN_BYTES     256	/* tty input queue size */
+#define TAB_SIZE           8	/* distance between tab stops */
+#define TAB_MASK           7	/* mask to compute a tab stop position */
+
+#define ESC             '\33'	/* escape */
+
+#define O_NOCTTY       00400	/* from <fcntl.h>, or cc will choke */
+#define O_NONBLOCK     04000
+
+struct tty;
+typedef _PROTOTYPE( int (*devfun_t), (struct tty *tp, int try_only) );
+typedef _PROTOTYPE( void (*devfunarg_t), (struct tty *tp, int c) );
+
+typedef struct tty {
+  int tty_events;		/* set when TTY should inspect this line */
+  int tty_index;		/* index into TTY table */
+  int tty_minor;		/* device minor number */
+
+  /* Input queue.  Typed characters are stored here until read by a program. */
+  u16_t *tty_inhead;		/* pointer to place where next char goes */
+  u16_t *tty_intail;		/* pointer to next char to be given to prog */
+  int tty_incount;		/* # chars in the input queue */
+  int tty_eotct;		/* number of "line breaks" in input queue */
+  devfun_t tty_devread;		/* routine to read from low level buffers */
+  devfun_t tty_icancel;		/* cancel any device input */
+  int tty_min;			/* minimum requested #chars in input queue */
+  timer_t tty_tmr;		/* the timer for this tty */
+
+  /* Output section. */
+  devfun_t tty_devwrite;	/* routine to start actual device output */
+  devfunarg_t tty_echo;		/* routine to echo characters input */
+  devfun_t tty_ocancel;		/* cancel any ongoing device output */
+  devfun_t tty_break;		/* let the device send a break */
+
+  /* Terminal parameters and status. */
+  int tty_position;		/* current position on the screen for echoing */
+  char tty_reprint;		/* 1 when echoed input messed up, else 0 */
+  char tty_escaped;		/* 1 when LNEXT (^V) just seen, else 0 */
+  char tty_inhibited;		/* 1 when STOP (^S) just seen (stops output) */
+  int tty_pgrp;			/* slot number of controlling process */
+  char tty_openct;		/* count of number of opens of this tty */
+
+  /* Information about incomplete I/O requests is stored here. */
+  char tty_inrepcode;		/* reply code, TASK_REPLY or REVIVE */
+  char tty_inrevived;		/* set to 1 if revive callback is pending */
+  int tty_incaller;		/* process that made the call (usually FS) */
+  int tty_inproc;		/* process that wants to read from tty */
+  vir_bytes tty_in_vir;		/* virtual address where data is to go */
+  int tty_inleft;		/* how many chars are still needed */
+  int tty_incum;		/* # chars input so far */
+  int tty_outrepcode;		/* reply code, TASK_REPLY or REVIVE */
+  int tty_outrevived;		/* set to 1 if revive callback is pending */
+  int tty_outcaller;		/* process that made the call (usually FS) */
+  int tty_outproc;		/* process that wants to write to tty */
+  vir_bytes tty_out_vir;	/* virtual address where data comes from */
+  int tty_outleft;		/* # chars yet to be output */
+  int tty_outcum;		/* # chars output so far */
+  int tty_iocaller;		/* process that made the call (usually FS) */
+  int tty_ioproc;		/* process that wants to do an ioctl */
+  int tty_ioreq;		/* ioctl request code */
+  vir_bytes tty_iovir;		/* virtual address of ioctl buffer */
+
+  /* select() data */
+  int tty_select_ops;		/* which operations are interesting */
+  int tty_select_proc;		/* which process wants notification */
+
+  /* Miscellaneous. */
+  devfun_t tty_ioctl;		/* set line speed, etc. at the device level */
+  devfun_t tty_close;		/* tell the device that the tty is closed */
+  void *tty_priv;		/* pointer to per device private data */
+  struct termios tty_termios;	/* terminal attributes */
+  struct winsize tty_winsize;	/* window size (#lines and #columns) */
+
+  u16_t tty_inbuf[TTY_IN_BYTES];/* tty input buffer */
+
+} tty_t;
+
+/* Memory allocated in tty.c, so extern here. */
+extern tty_t tty_table[NR_CONS+NR_RS_LINES+NR_PTYS];
+extern int ccurrent;		/* currently visible console */
+extern int irq_hook_id;		/* hook id for keyboard irq */
+
+extern unsigned long kbd_irq_set;
+extern unsigned long rs_irq_set;
+
+extern int panicing;	/* From panic.c in sysutil */
+
+/* Values for the fields. */
+#define NOT_ESCAPED        0	/* previous character is not LNEXT (^V) */
+#define ESCAPED            1	/* previous character was LNEXT (^V) */
+#define RUNNING            0	/* no STOP (^S) has been typed to stop output */
+#define STOPPED            1	/* STOP (^S) has been typed to stop output */
+
+/* Fields and flags on characters in the input queue. */
+#define IN_CHAR       0x00FF	/* low 8 bits are the character itself */
+#define IN_LEN        0x0F00	/* length of char if it has been echoed */
+#define IN_LSHIFT          8	/* length = (c & IN_LEN) >> IN_LSHIFT */
+#define IN_EOT        0x1000	/* char is a line break (^D, LF) */
+#define IN_EOF        0x2000	/* char is EOF (^D), do not return to user */
+#define IN_ESC        0x4000	/* escaped by LNEXT (^V), no interpretation */
+
+/* Times and timeouts. */
+#define force_timeout()	((void) (0))
+
+/* Memory allocated in tty.c, so extern here. */
+extern timer_t *tty_timers;		/* queue of TTY timers */
+extern clock_t tty_next_timeout;	/* next TTY timeout */
+
+/* Number of elements and limit of a buffer. */
+#define buflen(buf)	(sizeof(buf) / sizeof((buf)[0]))
+#define bufend(buf)	((buf) + buflen(buf))
+
+/* Memory allocated in tty.c, so extern here. */
+extern struct machine machine;	/* machine information (a.o.: pc_at, ega) */
+
+/* The tty outputs diagnostic messages in a circular buffer. */
+extern struct kmessages kmess;
+
+/* Function prototypes for TTY driver. */
+/* tty.c */
+_PROTOTYPE( void handle_events, (struct tty *tp)			);
+_PROTOTYPE( void sigchar, (struct tty *tp, int sig)			);
+_PROTOTYPE( void tty_task, (void)					);
+_PROTOTYPE( int in_process, (struct tty *tp, char *buf, int count)	);
+_PROTOTYPE( void out_process, (struct tty *tp, char *bstart, char *bpos,
+				char *bend, int *icount, int *ocount)	);
+_PROTOTYPE( void tty_wakeup, (clock_t now)				);
+_PROTOTYPE( void tty_reply, (int code, int replyee, int proc_nr,
+							int status)	);
+_PROTOTYPE( int tty_devnop, (struct tty *tp, int try)			);
+_PROTOTYPE( int select_try, (struct tty *tp, int ops)			);
+_PROTOTYPE( int select_retry, (struct tty *tp)				);
+
+/* rs232.c */
+_PROTOTYPE( void rs_init, (struct tty *tp)				);
+_PROTOTYPE( void rs_interrupt, (message *m)				);
+
+#if (CHIP == INTEL)
+/* console.c */
+_PROTOTYPE( void kputc, (int c)						);
+_PROTOTYPE( void cons_stop, (void)					);
+_PROTOTYPE( void do_new_kmess, (message *m)				);
+_PROTOTYPE( void do_diagnostics, (message *m)				);
+_PROTOTYPE( void do_get_kmess, (message *m)				);
+_PROTOTYPE( void scr_init, (struct tty *tp)				);
+_PROTOTYPE( void toggle_scroll, (void)					);
+_PROTOTYPE( int con_loadfont, (message *m)				);
+_PROTOTYPE( void select_console, (int cons_line)			);
+_PROTOTYPE( void beep_x, ( unsigned freq, clock_t dur)			);
+_PROTOTYPE( void do_video, (message *m)					);
+
+/* keyboard.c */
+_PROTOTYPE( void kb_init, (struct tty *tp)				);
+_PROTOTYPE( void kb_init_once, (void)					);
+_PROTOTYPE( int kbd_loadmap, (message *m)				);
+_PROTOTYPE( void do_panic_dumps, (message *m)				);
+_PROTOTYPE( void do_fkey_ctl, (message *m)				);
+_PROTOTYPE( void kbd_interrupt, (message *m)				);
+_PROTOTYPE( void do_kbd, (message *m)					);
+_PROTOTYPE( void do_kbdaux, (message *m)				);
+_PROTOTYPE( int kbd_status, (message *m_ptr)				);
+
+/* pty.c */
+_PROTOTYPE( void do_pty, (struct tty *tp, message *m_ptr)		);
+_PROTOTYPE( void pty_init, (struct tty *tp)				);
+_PROTOTYPE( void select_retry_pty, (struct tty *tp)			);
+_PROTOTYPE( int pty_status, (message *m_ptr)				);
+
+/* vidcopy.s */
+_PROTOTYPE( void vid_vid_copy, (unsigned src, unsigned dst, unsigned count));
+_PROTOTYPE( void mem_vid_copy, (u16_t *src, unsigned dst, unsigned count));
+
+#endif /* (CHIP == INTEL) */
+
Index: /trunk/minix/drivers/tty/vidcopy.s
===================================================================
--- /trunk/minix/drivers/tty/vidcopy.s	(revision 9)
+++ /trunk/minix/drivers/tty/vidcopy.s	(revision 9)
@@ -0,0 +1,160 @@
+# 
+! This file contains two specialized assembly code routines to update the 
+! video memory. The routines can copy from user to video memory, or from
+! video to video memory.   
+
+! sections
+
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! exported functions
+
+.define	_mem_vid_copy	! copy data to video ram
+.define	_vid_vid_copy	! move data in video ram
+
+! The routines only guarantee to preserve the registers the C compiler
+! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
+! direction bit in the flags).
+
+.sect .text
+!*===========================================================================*
+!*				mem_vid_copy				     *
+!*===========================================================================*
+! PUBLIC void mem_vid_copy(u16 *src, unsigned dst, unsigned count);
+!
+! Copy count characters from kernel memory to video memory.  Src is an ordinary
+! pointer to a word, but dst and count are character (word) based video offset
+! and count.  If src is null then screen memory is blanked by filling it with
+! blank_color.
+
+_mem_vid_copy:
+	push	ebp
+	mov	ebp, esp
+	push	esi
+	push	edi
+	push	es
+	mov	esi, 8(ebp)		! source
+	mov	edi, 12(ebp)		! destination
+	mov	edx, 16(ebp)		! count
+	mov	es, (_vid_seg)		! segment containing video memory
+	cld				! make sure direction is up
+mvc_loop:
+	and	edi, (_vid_mask)	! wrap address
+	mov	ecx, edx		! one chunk to copy
+	mov	eax, (_vid_size)
+	sub	eax, edi
+	cmp	ecx, eax
+	jbe	0f
+	mov	ecx, eax		! ecx = min(ecx, vid_size - edi)
+0:	sub	edx, ecx		! count -= ecx
+	shl	edi, 1			! byte address
+	add	edi, (_vid_off)		! in video memory
+	test	esi, esi		! source == 0 means blank the screen
+	jz	mvc_blank
+mvc_copy:
+	rep				! copy words to video memory
+    o16	movs
+	jmp	mvc_test
+mvc_blank:
+	mov	eax, (_blank_color)	! ax = blanking character
+	rep
+    o16	stos				! copy blanks to video memory
+	!jmp	mvc_test
+mvc_test:
+	sub	edi, (_vid_off)
+	shr	edi, 1			! back to a word address
+	test	edx, edx
+	jnz	mvc_loop
+mvc_done:
+	pop	es
+	pop	edi
+	pop	esi
+	pop	ebp
+	ret
+
+
+!*===========================================================================*
+!*				vid_vid_copy				     *
+!*===========================================================================*
+! PUBLIC void vid_vid_copy(unsigned src, unsigned dst, unsigned count);
+!
+! Copy count characters from video memory to video memory.  Handle overlap.
+! Used for scrolling, line or character insertion and deletion.  Src, dst
+! and count are character (word) based video offsets and count.
+
+_vid_vid_copy:
+	push	ebp
+	mov	ebp, esp
+	push	esi
+	push	edi
+	push	es
+	mov	esi, 8(ebp)		! source
+	mov	edi, 12(ebp)		! destination
+	mov	edx, 16(ebp)		! count
+	mov	es, (_vid_seg)		! segment containing video memory
+	cmp	esi, edi		! copy up or down?
+	jb	vvc_down
+vvc_up:
+	cld				! direction is up
+vvc_uploop:
+	and	esi, (_vid_mask)	! wrap addresses
+	and	edi, (_vid_mask)
+	mov	ecx, edx		! one chunk to copy
+	mov	eax, (_vid_size)
+	sub	eax, esi
+	cmp	ecx, eax
+	jbe	0f
+	mov	ecx, eax		! ecx = min(ecx, vid_size - esi)
+0:	mov	eax, (_vid_size)
+	sub	eax, edi
+	cmp	ecx, eax
+	jbe	0f
+	mov	ecx, eax		! ecx = min(ecx, vid_size - edi)
+0:	sub	edx, ecx		! count -= ecx
+	call	vvc_copy		! copy video words
+	test	edx, edx
+	jnz	vvc_uploop		! again?
+	jmp	vvc_done
+vvc_down:
+	std				! direction is down
+	lea	esi, -1(esi)(edx*1)	! start copying at the top
+	lea	edi, -1(edi)(edx*1)
+vvc_downloop:
+	and	esi, (_vid_mask)	! wrap addresses
+	and	edi, (_vid_mask)
+	mov	ecx, edx		! one chunk to copy
+	lea	eax, 1(esi)
+	cmp	ecx, eax
+	jbe	0f
+	mov	ecx, eax		! ecx = min(ecx, esi + 1)
+0:	lea	eax, 1(edi)
+	cmp	ecx, eax
+	jbe	0f
+	mov	ecx, eax		! ecx = min(ecx, edi + 1)
+0:	sub	edx, ecx		! count -= ecx
+	call	vvc_copy
+	test	edx, edx
+	jnz	vvc_downloop		! again?
+	cld				! C compiler expects up
+	!jmp	vvc_done
+vvc_done:
+	pop	es
+	pop	edi
+	pop	esi
+	pop	ebp
+	ret
+
+! Copy video words.  (Inner code of both the up and downcopying loop.)
+vvc_copy:
+	shl	esi, 1
+	shl	edi, 1			! byte addresses
+	add	esi, (_vid_off)
+	add	edi, (_vid_off)		! in video memory
+	rep
+eseg o16 movs				! copy video words
+	sub	esi, (_vid_off)
+	sub	edi, (_vid_off)
+	shr	esi, 1
+	shr	edi, 1			! back to word addresses
+	ret
+
Index: /trunk/minix/etc/Makefile
===================================================================
--- /trunk/minix/etc/Makefile	(revision 9)
+++ /trunk/minix/etc/Makefile	(revision 9)
@@ -0,0 +1,28 @@
+
+ETC=/etc/
+USRETC=/usr/etc/
+FILES1=fstab group hostname.file inet.conf motd.install mtab passwd profile protocols rc services termcap ttytab utmp rc.cd binary_sizes binary_sizes.big binary_sizes.xxl rc.rescue syslog.conf rc.daemons.dist 
+FILES2=shadow
+FILES3=daily dhcptags.conf rc
+
+all::
+
+clean::
+
+install::
+	@echo "Installing /etc and /usr/etc.."
+	mkdir -p $(ETC)
+	@for f in $(FILES1); do if [ -f $(ETC)/$$f ]; then :; else cp $$f $(ETC)/$$f; chmod 755 $(ETC)/$$f; fi; done
+	@for f in $(FILES2); do if [ -f $(ETC)/$$f ]; then :; else cp $$f $(ETC)/$$f; chmod 600 $(ETC)/$$f; fi; done
+	@echo "Making hierarchy.."
+	sh mtree.sh mtree/minix.tree
+	@for f in $(FILES3); do if [ -f $(USRETC)/$$f ]; then :; else cp usr/$$f $(USRETC); chmod 755 $(USRETC)/$$f; fi; done
+	@echo "Making devices.."
+	p=`pwd` && cd /dev && sh $$p/../commands/scripts/MAKEDEV.sh null 
+	p=`pwd` && cd /dev && sh $$p/../commands/scripts/MAKEDEV.sh std  2>/dev/null
+	@echo "Making user homedirs.."
+	for u in /usr/ast ~root; do (cd ast && tar cf - .[a-z]* ) | (cd $$u && tar xf - ); done
+
+postinstall:
+	binsizes normal
+
Index: /trunk/minix/etc/ast/.ashrc
===================================================================
--- /trunk/minix/etc/ast/.ashrc	(revision 9)
+++ /trunk/minix/etc/ast/.ashrc	(revision 9)
@@ -0,0 +1,27 @@
+# Ash initialization.
+
+test -z "$EDITOR" && {  # Don't repeat in subshells.
+
+umask 022
+
+# Favourite editor and pager, search path for binaries, etc.
+export EDITOR=vi
+export PAGER=more
+export PATH=$HOME/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin
+
+} # End of no-repeat.
+
+# Let cd display the current directory on the status line.
+if [ "$-" : '.*i.*' -a -t 0 -a -f /usr/bin/tget ] && tget -flag hs
+then
+	hostname=$(expr $(uname -n) : '\([^.]*\)')
+	eval "cd()
+	{
+		chdir \"\$@\" &&
+		echo -n '$(tget -str ts \
+				"$USER@$hostname:'\"\`pwd\`\"'" \
+				-str fs)'
+	}"
+	unset hostname
+	cd .
+fi
Index: /trunk/minix/etc/ast/.ellepro.e
===================================================================
--- /trunk/minix/etc/ast/.ellepro.e	(revision 9)
+++ /trunk/minix/etc/ast/.ellepro.e	(revision 9)
@@ -0,0 +1,219 @@
+; This is the default user profile to emulate "mined" (MINIX editor),
+; as per Andy Tanenbaum.
+
+(keyallunbind)
+
+; Insert self
+(keybind A "Insert Self")
+(keybind B "Insert Self")
+(keybind C "Insert Self")
+(keybind D "Insert Self")
+(keybind E "Insert Self")
+(keybind F "Insert Self")
+(keybind G "Insert Self")
+(keybind H "Insert Self")
+(keybind I "Insert Self")
+(keybind J "Insert Self")
+(keybind K "Insert Self")
+(keybind L "Insert Self")
+(keybind M "Insert Self")
+(keybind N "Insert Self")
+(keybind O "Insert Self")
+(keybind P "Insert Self")
+(keybind Q "Insert Self")
+(keybind R "Insert Self")
+(keybind S "Insert Self")
+(keybind T "Insert Self")
+(keybind U "Insert Self")
+(keybind V "Insert Self")
+(keybind W "Insert Self")
+(keybind X "Insert Self")
+(keybind Y "Insert Self")
+(keybind Z "Insert Self")
+(keybind a "Insert Self")
+(keybind b "Insert Self")
+(keybind c "Insert Self")
+(keybind d "Insert Self")
+(keybind e "Insert Self")
+(keybind f "Insert Self")
+(keybind g "Insert Self")
+(keybind h "Insert Self")
+(keybind i "Insert Self")
+(keybind j "Insert Self")
+(keybind k "Insert Self")
+(keybind l "Insert Self")
+(keybind m "Insert Self")
+(keybind n "Insert Self")
+(keybind o "Insert Self")
+(keybind p "Insert Self")
+(keybind q "Insert Self")
+(keybind r "Insert Self")
+(keybind s "Insert Self")
+(keybind t "Insert Self")
+(keybind u "Insert Self")
+(keybind v "Insert Self")
+(keybind w "Insert Self")
+(keybind x "Insert Self")
+(keybind y "Insert Self")
+(keybind z "Insert Self")
+(keybind 0 "Insert Self")
+(keybind 1 "Insert Self")
+(keybind 2 "Insert Self")
+(keybind 3 "Insert Self")
+(keybind 4 "Insert Self")
+(keybind 5 "Insert Self")
+(keybind 6 "Insert Self")
+(keybind 7 "Insert Self")
+(keybind 8 "Insert Self")
+(keybind 9 "Insert Self")
+(keybind / "Insert Self")
+(keybind : "Insert Self")
+(keybind < "Insert Self")
+(keybind = "Insert Self")
+(keybind > "Insert Self")
+(keybind ? "Insert Self")
+(keybind @ "Insert Self")
+(keybind [ "Insert Self")
+(keybind ] "Insert Self")
+(keybind ^ "Insert Self")
+(keybind # "Insert Self")
+(keybind $ "Insert Self")
+(keybind % "Insert Self")
+(keybind & "Insert Self")
+(keybind ' "Insert Self")
+(keybind * "Insert Self")
+(keybind + "Insert Self")
+(keybind , "Insert Self")
+(keybind - "Insert Self")
+(keybind . "Insert Self")
+(keybind ! "Insert Self")
+(keybind " " "Insert Self")
+(keybind """" "Insert Self")
+(keybind "(" "Insert Self")
+(keybind ")" "Insert Self")
+(keybind ";" "Insert Self")
+(keybind "\" "Insert Self")
+(keybind _ "Insert Self")
+(keybind ` "Insert Self")
+(keybind { "Insert Self")
+(keybind | "Insert Self")
+(keybind } "Insert Self")
+(keybind ~ "Insert Self")
+
+; CTRL char
+(keybind ^A "Beginning of Line")
+(keybind ^B "Backward Word")
+(keybind ^C "Copy Region")
+(keybind ^D "Scroll Window Up")
+(keybind ^E "New Window")
+(keybind ^F "Forward Word")
+(keybind ^H "Backward Delete Character")
+(keybind ^I "Insert Self")
+; open
+(keybind ^K "Kill Region")
+(keybind ^L "Replace in Line")
+(keybind ^M "CRLF")
+(keybind ^N "Kill Word")
+(keybind ^O "Open Line")
+(keybind ^P "Backward Kill Word")
+(keybind ^Q "Write Last Kill")
+(keybind ^R "Replace String")
+(keybind ^S "Push to Inferior")
+(keybind ^T "Kill Line")
+(keybind ^U "Scroll Window Down")
+(keybind ^V "Find File")
+(keybind ^W "Save File")
+(keybind ^X "Prefix Extend")
+(keybind ^Y "Un-kill")
+(keybind ^Z "End of Line")
+(keybind "^\" "Quoted Insert")
+(keybind ^_ "Move to Window Bottom")
+(keybind ^^ "Set/Pop Mark")
+(keybind ^] "Goto Line")
+
+; ESC char
+(keybind ^[ "Prefix Meta")
+(keybind M-0 "Argument Digit")
+(keybind M-1 "Argument Digit")
+(keybind M-2 "Argument Digit")
+(keybind M-3 "Argument Digit")
+(keybind M-4 "Argument Digit")
+(keybind M-5 "Argument Digit")
+(keybind M-6 "Argument Digit")
+(keybind M-7 "Argument Digit")
+(keybind M-8 "Argument Digit")
+(keybind M-9 "Argument Digit")
+(keybind M-A "Append Next Kill")
+(keybind M-B "Select Buffer")
+(keybind M-C "Uppercase Word")
+(keybind M-E "Execute Kbd Macro")
+(keybind M-F "Find File")
+(keybind M-G "Insert File")
+(keybind M-H "Describe")
+(keybind M-I "Uppercase Initial")
+(keybind M-K "Kill Buffer")
+(keybind M-L "Lowercase Region")
+(keybind M-M "Mark Paragraph")
+(keybind M-N "Buffer Not Modified")
+(keybind M-O "Lowercase Word")
+(keybind M-P "Forward Paragraph")
+(keybind M-Q "Query Replace")
+(keybind M-R "Set Profile")
+(keybind M-S "Select Existing Buffer")
+(keybind M-T "Transpose Characters")
+(keybind M-U "Uppercase Region")
+(keybind M-W "Transpose Words")
+(keybind M-X "Return to Superior")
+(keybind M-Y "Un-kill Pop")
+(keybind M-Z "Incremental Search")
+(keybind M-^ "Exchange Point and Mark")
+(keybind M-* "View Kbd Macro")
+(keybind M-[ "Prefix Extend")
+(keybind M-] "Backward Paragraph")
+(keybind M-= "Delete Horizontal Space")
+(keybind M-| "Delete Blank Lines")
+(keybind "M-," "Move to Window Top")
+(keybind "M-;" "Indent for Comment")
+(keybind "M-." "Indent Relative")
+(keybind "M-/" "Start Kbd Macro")
+(keybind "M-\" "End Kbd Macro")
+
+
+; CTRL-X char
+(keybind X-1 "One Window")
+(keybind X-2 "Two Windows")
+(keybind X-A "Up Real Line")
+(keybind X-B "Down Real Line")
+(keybind X-C "Forward Character")
+(keybind X-D "Backward Character")
+(keybind X-G "List Buffers")
+(keybind X-H "Goto Beginning")
+(keybind X-L "Grow Window")
+(keybind X-N "Other Window")
+(keybind X-P "Shrink Window")
+(keybind X-S "Reverse String Search")
+(keybind X-T "String Search")
+(keybind X-U "Next Screen")
+(keybind X-V "Previous Screen")
+(keybind X-X "Return to Superior")
+(keybind X-Y "Goto End")
+
+(keybind X-^A "Up Real Line")
+(keybind X-^B "Down Real Line")
+(keybind X-^C "Forward Character")
+(keybind X-^D "Backward Character")
+(keybind X-^G "List Buffers")
+(keybind X-^H "Goto Beginning")
+(keybind X-^L "Grow Window")
+(keybind X-^N "Other Window")
+(keybind X-^P "Shrink Window")
+(keybind X-^S "Reverse String Search")
+(keybind X-^T "String Search")
+(keybind X-^U "Next Screen")
+(keybind X-^V "Previous Screen")
+(keybind X-^W "New Window")
+(keybind X-^X "Return to Superior")
+(keybind X-^Y "Goto End")
+
+
+(keybind DEL "Delete Character")
Index: /trunk/minix/etc/ast/.exrc
===================================================================
--- /trunk/minix/etc/ast/.exrc	(revision 9)
+++ /trunk/minix/etc/ast/.exrc	(revision 9)
@@ -0,0 +1,1 @@
+set autoindent autowrite report=2 showmatch
Index: /trunk/minix/etc/ast/.profile
===================================================================
--- /trunk/minix/etc/ast/.profile	(revision 9)
+++ /trunk/minix/etc/ast/.profile	(revision 9)
@@ -0,0 +1,15 @@
+# Login shell profile.
+
+# Erase character and erase line interrupt keys
+stty sane erase '^H' kill '^U'
+
+# Check terminal type.
+case $TERM in
+dialup|unknown|network)
+	echo -n "Terminal type? ($TERM) "; read term
+	TERM="${term:-$TERM}"
+	unset term
+esac
+
+# Shell configuration.
+unset EDITOR; . $HOME/.ashrc
Index: /trunk/minix/etc/ast/.vimrc
===================================================================
--- /trunk/minix/etc/ast/.vimrc	(revision 9)
+++ /trunk/minix/etc/ast/.vimrc	(revision 9)
@@ -0,0 +1,93 @@
+" An example for a vimrc file.
+"
+" Maintainer:	Bram Moolenaar <Bram@vim.org>
+" Last change:	2002 Sep 19
+"
+" To use it, copy it to
+"     for Unix and OS/2:  ~/.vimrc
+"	      for Amiga:  s:.vimrc
+"  for MS-DOS and Win32:  $VIM\_vimrc
+"	    for OpenVMS:  sys$login:.vimrc
+
+" When started as "evim", evim.vim will already have done these settings.
+if v:progname =~? "evim"
+  finish
+endif
+
+" Use Vim settings, rather then Vi settings (much better!).
+" This must be first, because it changes other options as a side effect.
+set nocompatible
+
+" allow backspacing over everything in insert mode
+set backspace=indent,eol,start
+
+if has("vms")
+  set nobackup		" do not keep a backup file, use versions instead
+else
+  set backup		" keep a backup file
+endif
+set history=50		" keep 50 lines of command line history
+set ruler		" show the cursor position all the time
+set showcmd		" display incomplete commands
+set incsearch		" do incremental searching
+
+" For Win32 GUI: remove 't' flag from 'guioptions': no tearoff menu entries
+" let &guioptions = substitute(&guioptions, "t", "", "g")
+
+" Don't use Ex mode, use Q for formatting
+map Q gq
+
+" This is an alternative that also works in block mode, but the deleted
+" text is lost and it only works for putting the current register.
+"vnoremap p "_dp
+
+   :if &term =~ "xterm" || &term =~ "minix"
+   :  if has("terminfo")
+   :    set t_Co=8
+   :    set t_Sf=[3%p1%dm
+   :    set t_Sb=[4%p1%dm
+   :  else
+   :    set t_Co=8
+   :    set t_Sf=[3%dm
+   :    set t_Sb=[4%dm
+   :  endif
+   :endif
+
+" Switch syntax highlighting on, when the terminal has colors
+" Also switch on highlighting the last used search pattern.
+if &t_Co > 2 || has("gui_running")
+  syntax on
+  set hlsearch
+endif
+
+" Only do this part when compiled with support for autocommands.
+if has("autocmd")
+
+  " Enable file type detection.
+  " Use the default filetype settings, so that mail gets 'tw' set to 72,
+  " 'cindent' is on in C files, etc.
+  " Also load indent files, to automatically do language-dependent indenting.
+  filetype plugin indent on
+
+  " Put these in an autocmd group, so that we can delete them easily.
+  augroup vimrcEx
+  au!
+
+  " For all text files set 'textwidth' to 78 characters.
+  autocmd FileType text setlocal textwidth=78
+
+  " When editing a file, always jump to the last known cursor position.
+  " Don't do it when the position is invalid or when inside an event handler
+  " (happens when dropping a file on gvim).
+  autocmd BufReadPost *
+    \ if line("'\"") > 0 && line("'\"") <= line("$") |
+    \   exe "normal g`\"" |
+    \ endif
+
+  augroup END
+
+else
+
+  set autoindent		" always set autoindenting on
+
+endif " has("autocmd")
Index: /trunk/minix/etc/binary_sizes
===================================================================
--- /trunk/minix/etc/binary_sizes	(revision 9)
+++ /trunk/minix/etc/binary_sizes	(revision 9)
@@ -0,0 +1,9 @@
+/usr/lib/cpp.ansi 216004
+/usr/lib/cv 1238570
+/usr/lib/em_cemcom.ansi 624004
+/usr/lib/em_led 538122
+/usr/lib/em_opt 208000
+/usr/lib/i386/as 45000
+/usr/lib/i386/cg 50655
+/bin/sh 102400
+/usr/bin/make 337920
Index: /trunk/minix/etc/binary_sizes.big
===================================================================
--- /trunk/minix/etc/binary_sizes.big	(revision 9)
+++ /trunk/minix/etc/binary_sizes.big	(revision 9)
@@ -0,0 +1,9 @@
+/usr/lib/cpp.ansi 1416004
+/usr/lib/cv 3738570
+/usr/lib/em_cemcom.ansi 10683676
+/usr/lib/em_led 4078088
+/usr/lib/em_opt 1370162
+/usr/lib/i386/as 1239922
+/usr/lib/i386/cg 1285513
+/bin/sh 102400
+/usr/bin/make 337920
Index: /trunk/minix/etc/binary_sizes.xxl
===================================================================
--- /trunk/minix/etc/binary_sizes.xxl	(revision 9)
+++ /trunk/minix/etc/binary_sizes.xxl	(revision 9)
@@ -0,0 +1,10 @@
+/usr/lib/cpp.ansi 1416004
+/usr/lib/cv 3738570
+/usr/lib/em_cemcom.ansi 10683676
+/usr/lib/em_led 4078088
+/usr/lib/em_opt 1370162
+/usr/lib/i386/as 1239922
+/usr/lib/i386/cg 1285513
+/usr/bin/make 2000000
+/bin/sh	1000000
+/usr/bin/lex 1000000
Index: /trunk/minix/etc/fstab
===================================================================
--- /trunk/minix/etc/fstab	(revision 9)
+++ /trunk/minix/etc/fstab	(revision 9)
@@ -0,0 +1,4 @@
+# Poor man's File System Table.
+
+root=/dev/ROOT
+usr=/dev/USR
Index: /trunk/minix/etc/group
===================================================================
--- /trunk/minix/etc/group	(revision 9)
+++ /trunk/minix/etc/group	(revision 9)
@@ -0,0 +1,14 @@
+operator:*:0:
+daemon:*:1:
+bin:*:2:
+other:*:3:
+tty:*:4:
+uucp:*:5:
+news:*:6:
+ftp:*:7:
+kmem:*:8:
+www:*:9:
+driver:*:10:
+server:*:11:
+smtpd:*:26:
+nogroup:*:99:
Index: /trunk/minix/etc/hostname.file
===================================================================
--- /trunk/minix/etc/hostname.file	(revision 9)
+++ /trunk/minix/etc/hostname.file	(revision 9)
@@ -0,0 +1,1 @@
+minix
Index: /trunk/minix/etc/inet.conf
===================================================================
--- /trunk/minix/etc/inet.conf	(revision 9)
+++ /trunk/minix/etc/inet.conf	(revision 9)
@@ -0,0 +1,1 @@
+psip0 { default; };
Index: /trunk/minix/etc/motd
===================================================================
--- /trunk/minix/etc/motd	(revision 9)
+++ /trunk/minix/etc/motd	(revision 9)
@@ -0,0 +1,12 @@
+
+To install X Windows, run 'packman' with the install CD still in the
+drive.  To start X Windows after you have installed it, login as root
+and type: 'xdm'. For more information about configuring X Windows, see
+www.minix3.org.
+
+If you do not have sufficient memory to run X Windows, standard MINIX 3
+supports multiple virtual terminals. Just use ALT+F1, F2, F3 and F4 to
+navigate among them.
+
+To get rid of this message, edit /etc/motd.
+
Index: /trunk/minix/etc/motd.install
===================================================================
--- /trunk/minix/etc/motd.install	(revision 9)
+++ /trunk/minix/etc/motd.install	(revision 9)
@@ -0,0 +1,12 @@
+
+To install X Windows, run 'packman' with the install CD still in the
+drive.  To start X Windows after you have installed it, login as root
+and type: 'xdm'. For more information about configuring X Windows, see
+www.minix3.org.
+
+If you do not have sufficient memory to run X Windows, standard MINIX 3
+supports multiple virtual terminals. Just use ALT+F1, F2, F3 and F4 to
+navigate among them.
+
+To get rid of this message, edit /etc/motd.
+
Index: /trunk/minix/etc/mtree.sh
===================================================================
--- /trunk/minix/etc/mtree.sh	(revision 9)
+++ /trunk/minix/etc/mtree.sh	(revision 9)
@@ -0,0 +1,4 @@
+#!/bin/sh
+cat $1 | while read line
+do	 echo $line | awk 'NF==4 { print "mkdir -p "$4" || exit 1; chmod "$1" "$4" || exit 1; chown "$2" "$4" || exit 1; chgrp "$3" "$4" || exit 1" } NF==3 { print "rm "$1" ; ln -s "$3" "$1" || exit 1" } ' | sh || exit 1
+done
Index: /trunk/minix/etc/mtree/minix.tree
===================================================================
--- /trunk/minix/etc/mtree/minix.tree	(revision 9)
+++ /trunk/minix/etc/mtree/minix.tree	(revision 9)
@@ -0,0 +1,147 @@
+755 root    operator /
+755 bin     operator /bin
+755 bin     operator /sbin
+755 root    operator /dev
+755 root    operator /etc
+755 root    operator /lib
+755 root    operator /lib/i386
+755 root    operator /boot
+755 root    operator /boot/image
+755 root    operator /boot/rescue
+555 root    operator /mnt
+700 root    operator /root
+1777 root   operator /tmp
+755 root    operator /usr
+755 root    operator /usr/adm
+755 root    operator /usr/adm/old
+755 ast     other    /usr/ast
+755 bin     operator /usr/bin
+755 root    operator /usr/etc
+755 root    operator /home
+755 bin     operator /usr/include
+755 root    operator /usr/lib
+755 root    operator /usr/lib/advent
+755 root    operator /usr/lib/cawf
+755 root    operator /usr/lib/dict
+755 root    operator /usr/lib/ego
+755 root    operator /usr/lib/flex
+755 root    operator /usr/lib/fonts
+755 root    operator /usr/lib/i86
+755 root    operator /usr/lib/keymaps
+755 root    operator /usr/lib/m2
+755 root    operator /usr/sbin
+775 bin     operator /usr/local
+775 bin     operator /usr/local/bin
+775 bin     operator /usr/local/etc
+775 bin     operator /usr/local/etc/rc.d
+775 bin     operator /usr/local/gnu
+775 bin     operator /usr/local/gnu/lib
+775 bin     operator /usr/local/include
+775 bin     operator /usr/local/info
+775 bin     operator /usr/local/lib
+775 bin     operator /usr/local/man
+755  bin    operator  /usr/local/man/man1
+755  bin    operator  /usr/local/man/man2
+755  bin    operator  /usr/local/man/man3
+755  bin    operator  /usr/local/man/man4
+755  bin    operator  /usr/local/man/man5
+755  bin    operator  /usr/local/man/man6
+755  bin    operator  /usr/local/man/man7
+755  bin    operator  /usr/local/man/man8
+755  bin    operator  /usr/local/man/man9
+775  bin     operator  /usr/local/packages
+775  bin     operator  /usr/local/share
+775  bin     operator  /usr/local/src
+755  bin     operator  /usr/man
+755  bin     operator  /usr/man/man1
+755  bin     operator  /usr/man/man2
+755  bin     operator  /usr/man/man3
+755  bin     operator  /usr/man/man4
+755  bin     operator  /usr/man/man5
+755  bin     operator  /usr/man/man6
+755  bin     operator  /usr/man/man7
+755  bin     operator  /usr/man/man8
+755  bin     operator  /usr/man/man9
+755  bin     operator  /usr/mdec
+700  root    operator  /usr/preserve
+755  root    operator  /usr/run
+755  root    operator  /usr/spool
+711  root    operator  /usr/spool/at
+711  root    operator  /usr/spool/at/past
+700  root    operator  /usr/spool/crontabs
+775  root    uucp      /usr/spool/locks
+700  daemon  daemon    /usr/spool/lpd
+755  root    operator  /usr/spool/mail
+755  bin     operator  /usr/src
+1777 root    operator  /usr/tmp
+755  root    operator  /var
+/var/log -> /usr/log
+755  root    operator  /usr/log
+755  root    operator  /var/run
+755	bin	operator	/usr/gnu/
+755	bin	operator	/usr/gnu/bin
+755	bin	operator	/usr/gnu/i386-pc-minix
+755	bin	operator	/usr/gnu/i386-pc-minix/bin
+755	bin	operator	/usr/gnu/i386-pc-minix/lib
+755	bin	operator	/usr/gnu/i386-pc-minix/lib/ldscripts
+755	bin	operator	/usr/gnu/include
+755	bin	operator	/usr/gnu/info
+755	bin	operator	/usr/gnu/lib
+755	bin	operator	/usr/gnu/lib/gcc
+755	bin	operator	/usr/gnu/lib/gcc/i386-pc-minix
+755	bin	operator	/usr/gnu/lib/gcc/i386-pc-minix/3.4.3
+755	bin	operator	/usr/gnu/lib/gcc/i386-pc-minix/3.4.3/include
+755	bin	operator	/usr/gnu/lib/gcc/i386-pc-minix/3.4.3/include/minix
+755	bin	operator	/usr/gnu/lib/gcc/i386-pc-minix/3.4.3/include/sys
+755	bin	operator	/usr/gnu/lib/gcc/i386-pc-minix/3.4.3/include/net
+755	bin	operator	/usr/gnu/lib/gcc/i386-pc-minix/3.4.3/install-tools
+755	bin	operator	/usr/gnu/lib/gcc/i386-pc-minix/3.4.3/install-tools/include
+755	bin	operator	/usr/gnu/libexec
+755	bin	operator	/usr/gnu/libexec/gcc
+755	bin	operator	/usr/gnu/libexec/gcc/i386-pc-minix
+755	bin	operator	/usr/gnu/libexec/gcc/i386-pc-minix/3.4.3
+755	bin	operator	/usr/gnu/libexec/gcc/i386-pc-minix/3.4.3/install-tools
+755	bin	operator	/usr/gnu/man
+755	bin	operator	/usr/gnu/man/man1
+755	bin	operator	/usr/gnu/man/man2
+755	bin	operator	/usr/gnu/man/man3
+755	bin	operator	/usr/gnu/man/man4
+755	bin	operator	/usr/gnu/man/man5
+755	bin	operator	/usr/gnu/man/man6
+755	bin	operator	/usr/gnu/man/man7
+755	bin	operator	/usr/gnu/share
+755	bin	operator	/usr/gnu/share/locale
+755	bin	operator	/usr/gnu/share/locale/fr
+755	bin	operator	/usr/gnu/share/locale/fr/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/tr
+755	bin	operator	/usr/gnu/share/locale/tr/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/ja
+755	bin	operator	/usr/gnu/share/locale/ja/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/es
+755	bin	operator	/usr/gnu/share/locale/es/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/sv
+755	bin	operator	/usr/gnu/share/locale/sv/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/da
+755	bin	operator	/usr/gnu/share/locale/da/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/zh_CN
+755	bin	operator	/usr/gnu/share/locale/zh_CN/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/ro
+755	bin	operator	/usr/gnu/share/locale/ro/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/de
+755	bin	operator	/usr/gnu/share/locale/de/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/id
+755	bin	operator	/usr/gnu/share/locale/id/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/pt_BR
+755	bin	operator	/usr/gnu/share/locale/pt_BR/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/nl
+755	bin	operator	/usr/gnu/share/locale/nl/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/ru
+755	bin	operator	/usr/gnu/share/locale/ru/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/vi
+755	bin	operator	/usr/gnu/share/locale/vi/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/be
+755	bin	operator	/usr/gnu/share/locale/be/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/ca
+755	bin	operator	/usr/gnu/share/locale/ca/LC_MESSAGES
+755	bin	operator	/usr/gnu/share/locale/el
+755	bin	operator	/usr/gnu/share/locale/el/LC_MESSAGES
Index: /trunk/minix/etc/passwd
===================================================================
--- /trunk/minix/etc/passwd	(revision 9)
+++ /trunk/minix/etc/passwd	(revision 9)
@@ -0,0 +1,14 @@
+root:##root:0:0:Big Brother:/root:
+daemon:*:1:1:The Deuce:/etc:
+bin:##root:2:0:Binaries:/home/bin:
+uucp:*:5:5:UNIX to UNIX copy:/usr/spool/uucp:/usr/bin/uucico
+news:*:6:6:Usenet news:/usr/spool/news:
+ftp:*:7:7:Anonymous FTP:/usr/ftp:
+ast:*:8:3:Andrew S. Tanenbaum:/home/ast:
+www:*:9:9:World Wide Web:/usr/www:
+driver:*:10:10:Device Drivers:/:
+server:*:11:11:OS Servers:/:
+sshd:*:22:22:sshd:/:
+smtpd:*:25:25:smtpd:/:
+games:*:9998:98::/:
+nobody:*:9999:99::/tmp:
Index: /trunk/minix/etc/profile
===================================================================
--- /trunk/minix/etc/profile	(revision 9)
+++ /trunk/minix/etc/profile	(revision 9)
@@ -0,0 +1,6 @@
+RC_TZ=/etc/rc.timezone
+export TZ=GMT0
+if [ -f "$RC_TZ" ]
+then . "$RC_TZ"
+fi
+export MANPATH=/usr/man:/usr/local/man:/usr/gnu/man:/usr/X11R6/man
Index: /trunk/minix/etc/protocols
===================================================================
--- /trunk/minix/etc/protocols	(revision 9)
+++ /trunk/minix/etc/protocols	(revision 9)
@@ -0,0 +1,19 @@
+#
+# Internet (IP) protocols
+#
+#	@(#)protocols	8.1 (Berkeley) 6/9/93
+#
+ip	0	IP		# internet protocol, pseudo protocol number
+icmp	1	ICMP		# internet control message protocol
+igmp	2	IGMP		# internet group management protocol
+ggp	3	GGP		# gateway-gateway protocol
+tcp	6	TCP		# transmission control protocol
+egp	8	EGP		# exterior gateway protocol
+pup	12	PUP		# PARC universal packet protocol
+udp	17	UDP		# user datagram protocol
+hmp	20	HMP		# host monitoring protocol
+xns-idp	22	XNS-IDP		# Xerox NS IDP
+rdp	27	RDP		# reliable data protocol
+iso-tp4	29	ISO-TP4		# ISO Transport Protocol Class 4
+iso-ip	80	ISO-IP		# ISO Internet Protocol
+encap	98	ENCAP		# RFC1241 encapsulation
Index: /trunk/minix/etc/rc
===================================================================
--- /trunk/minix/etc/rc	(revision 9)
+++ /trunk/minix/etc/rc	(revision 9)
@@ -0,0 +1,177 @@
+# /etc/rc - System startup script run by init before going multiuser.
+
+umask 022
+TERM="${TERM-minix}"
+PATH=/usr/local/bin:/bin:/usr/bin:/usr/sbin
+RC_TZ=/etc/rc.timezone
+export TERM PATH
+
+usage()
+{
+    echo >&2 "Usage: $0 [-saf] start|stop|down"
+    exec intr sh
+}
+
+up()
+{
+    service=$1
+    shift
+
+    # Function to dynamically start a system service
+    echo -n " $service"
+    service up /sbin/$service "$@"
+}
+
+while getopts 'saf' opt
+do
+    case $opt in
+    s)	sflag=t ;;	# Single user
+    a)	aflag=t ;;	# Ask for /usr
+    f)	fflag=t ;;	# Force a full file system check
+    *)	usage
+    esac
+done
+shift `expr $OPTIND - 1`
+
+case "$#:$1" in
+1:start|1:stop|1:down)
+    action=$1
+    ;;
+*)  usage
+esac
+
+case $action in
+start)
+    echo ""
+    echo -n "Multiuser startup in progress ...:"
+
+    # National keyboard?
+    test -f /etc/keymap && loadkeys /etc/keymap
+
+    up is -period 5HZ
+    up cmos -dev /dev/cmos -period 5HZ
+    echo .
+
+    # Set timezone.
+    export TZ=GMT0
+    if [ -f "$RC_TZ" ]
+    then . "$RC_TZ"
+    fi
+
+    # Try to read the hardware real-time clock, otherwise do it manually.
+    readclock || intr date -q
+
+    # Initialize files.
+    printroot >/etc/mtab		# /etc/mtab keeps track of mounts
+    >/etc/utmp				# /etc/utmp keeps track of logins
+
+    # /etc/fstab lists the root, tmp and usr devices.
+    . /etc/fstab
+
+    # Any swapspace on a device?
+    test "$swap" : '/dev/' && mount -s $swap
+
+    # Are we booting from CD?
+    bootcd="`/bin/sysenv bootcd`"
+
+    # If booting from CD, /usr has to be mounted readonly.
+    # Also, $usr won't be specified correctly in the
+    # fstab (the CD could be anywhere), so we decide
+    # where it is based on sysenv (set by FS when probing for CD).
+    if [ "$bootcd" = 1 ]
+    then	
+    		#imagedev="`/bin/sysenv cdproberoot`"
+    		#usrdev="`expr $imagedev + 1`"
+    		usr_roflag="-r"
+    		usr="$cddev"p2
+    		echo "Setting /usr on cd is $usr"
+    fi
+ 
+    # Mount the /usr partition unless this is a single floppy Minix.
+    if [ ! -d /usr/bin ]
+    then
+	if [ "$aflag" -o "$usr" = unknown ]
+	then
+	    # We need to ask what the /usr du jour is.
+	    intr sh -c '
+		echo -n "Finish the name of device to mount as /usr: /dev/"
+		read usr
+		echo "usr=/dev/$usr" >/tmp/usr'
+	    . /tmp/usr
+	fi
+	mount $usr_roflag $usr /usr || {
+	    echo "\
+Please try to mount something else as /usr, then hit CTRL-D to continue startup.
+Mount $usr /usr failed -- Single user."
+	    intr sh
+	}
+	rm -f /tmp/usr
+    fi
+
+    # Check if the system crashed.
+    if shutdown -C
+    then
+	echo
+	echo "The system was not properly shut down.  Checking file systems."
+	fflag=t
+    fi
+
+    if [ "$fflag" ]
+    then
+	umount $usr
+	echo "fsck / - $root"
+	intr fsck -r $root
+	echo "fsck /usr - $usr"
+	intr fsck -r $usr
+	if [ ! -z "$home" ]
+	then	echo "fsck /home - $home"
+		intr fsck -r $home
+	fi
+	mount $usr /usr
+    fi
+
+    if [ ! -z "$home" ]
+    then mount $home /home || echo "WARNING: couldn't mount $home on /home"
+    fi
+
+    # This file is necessary for above 'shutdown -C' check.
+    # (Silence stderr in case of running from cd.)
+    touch /usr/adm/wtmp 2>/dev/null
+
+    if [ "$sflag" ]
+    then
+	echo "Single user."
+	intr sh
+    fi
+
+    # Any swapspace on a file?
+    test -n "$swap" -a ! "$swap" : '/dev/' && mount -s $swap
+
+
+    case "`printroot -r`":$bootcd in
+    /dev/ram:)
+	# Remove boot-only things to make space,
+	# unless booting from CD, in which case we need them.
+	rm -rf /boot
+	# put the compiler on ram
+	cp /usr/lib/em* /usr/lib/cpp* /lib
+    esac
+
+    # Things should be alright now.
+    ;;
+down|stop)
+    sync
+    # Tell RS server we're going down.
+    service shutdown
+    ;;
+esac
+
+# Further initialization.
+test -f /usr/etc/rc && sh /usr/etc/rc $action
+test -f /usr/local/etc/rc && sh /usr/local/etc/rc $action
+test -f /etc/rc.rescue && sh /etc/rc.rescue $action
+
+# Any messages?
+test "$action" = start -a -f /etc/issue && cat /etc/issue
+
+exit 0
Index: /trunk/minix/etc/rc.cd
===================================================================
--- /trunk/minix/etc/rc.cd	(revision 9)
+++ /trunk/minix/etc/rc.cd	(revision 9)
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+# CD boottime initializations.
+
Index: /trunk/minix/etc/rc.daemons.dist
===================================================================
--- /trunk/minix/etc/rc.daemons.dist	(revision 9)
+++ /trunk/minix/etc/rc.daemons.dist	(revision 9)
@@ -0,0 +1,5 @@
+daemonize talkd
+daemonize tcpd shell in.rshd
+daemonize tcpd login in.rlogind
+daemonize tcpd telnet in.telnetd
+daemonize tcpd ftp in.ftpd
Index: /trunk/minix/etc/rc.rescue
===================================================================
--- /trunk/minix/etc/rc.rescue	(revision 9)
+++ /trunk/minix/etc/rc.rescue	(revision 9)
@@ -0,0 +1,15 @@
+#!/bin/sh
+DRIVERS=/sbin
+RESCUE=/boot/rescue
+
+if [ "$1" != start ]
+then	exit
+fi
+
+set -e
+service up $DRIVERS/rescue -dev /dev/rescue -args 128 -period 4HZ
+mkfs /dev/rescue
+mount /dev/rescue $RESCUE
+cd $DRIVERS
+cp -p at_wini floppy bios_wini $RESCUE
+service rescue $RESCUE 
Index: /trunk/minix/etc/services
===================================================================
--- /trunk/minix/etc/services	(revision 9)
+++ /trunk/minix/etc/services	(revision 9)
@@ -0,0 +1,92 @@
+#
+# Network services, Internet style
+#
+#	@(#)services	8.1 (Berkeley) 6/9/93
+#
+tcpmux		1/tcp				# TCP port multiplexer (RFC1078)
+echo		7/tcp
+echo		7/udp
+discard		9/tcp		sink null
+discard		9/udp		sink null
+systat		11/tcp		users
+daytime		13/tcp
+daytime		13/udp
+netstat		15/tcp
+qotd		17/tcp		quote
+chargen		19/tcp		ttytst source
+chargen		19/udp		ttytst source
+ftp		21/tcp
+ssh             22/tcp    #Secure Shell Login
+ssh             22/udp    #Secure Shell Login
+telnet		23/tcp
+smtp		25/tcp		mail
+time		37/tcp		timserver
+time		37/udp		timserver
+rlp		39/udp		resource	# resource location
+nameserver	42/tcp		name		# IEN 116
+whois		43/tcp		nicname
+domain		53/tcp		nameserver	# name-domain server
+domain		53/udp		nameserver
+mtp		57/tcp				# deprecated
+bootps		67/udp				# Bootstrap Protocol Server
+bootpc		68/udp				# Bootstrap Protocol Client
+tftp		69/udp
+rje		77/tcp		netrjs
+finger		79/tcp
+http		80/tcp				# World Wide Web
+link		87/tcp		ttylink
+supdup		95/tcp
+hostnames	101/tcp		hostname	# usually from sri-nic
+tsap		102/tcp				# part of ISODE.
+pop		110/tcp		postoffice
+sunrpc		111/tcp
+sunrpc		111/udp
+auth		113/tcp		authentication
+sftp		115/tcp
+uucp-path	117/tcp
+nntp		119/tcp		readnews untp	# USENET News Transfer Protocol
+ntp		123/udp
+netbios-ns	137/tcp				# NETBIOS Name Service
+netbios-ns	137/udp				# NETBIOS Name Service
+netbios-dgm	138/tcp				# NETBIOS Datagram Service
+netbios-dgm	138/udp				# NETBIOS Datagram Service
+netbios-ssn	139/tcp				# NETBIOS Session Service
+netbios-ssn	139/udp				# NETBIOS Session Service
+imap		143/tcp
+snmp		161/udp
+snmp-trap	162/udp
+#
+# UNIX specific services
+#
+exec		512/tcp
+biff		512/udp		comsat
+login		513/tcp
+who		513/udp		whod
+shell		514/tcp		cmd		# no passwords used
+syslog		514/udp
+printer		515/tcp		spooler		# line printer spooler
+talk		517/udp
+ntalk		518/udp
+route		520/udp		router routed
+timed		525/udp		timeserver
+tempo		526/tcp		newdate
+courier		530/tcp		rpc
+conference	531/tcp		chat
+netnews		532/tcp		readnews
+netwall		533/udp				# -for emergency broadcasts
+uucp		540/tcp		uucpd		# uucp daemon
+rdist		541/tcp		rdistd		# rdist daemon
+remotefs	556/tcp		rfs_server rfs	# Brunhoff remote filesystem
+ingreslock	1524/tcp
+#
+# Kerberos (Project Athena/MIT) services
+#
+kerberos	750/udp		kdc		# Kerberos (server) udp
+kerberos	750/tcp		kdc		# Kerberos (server) tcp
+krbupdate	760/tcp		kreg		# Kerberos registration
+kpasswd		761/tcp		kpwd		# Kerberos "passwd"
+klogin		543/tcp				# Kerberos rlogin
+rsync		873/tcp
+rsync		873/udp
+eklogin		2105/tcp			# Kerberos encrypted rlogin
+kshell		544/tcp		krcmd		# Kerberos remote shell
Index: /trunk/minix/etc/shadow
===================================================================
--- /trunk/minix/etc/shadow	(revision 9)
+++ /trunk/minix/etc/shadow	(revision 9)
@@ -0,0 +1,1 @@
+root::0:0:::
Index: /trunk/minix/etc/syslog.conf
===================================================================
--- /trunk/minix/etc/syslog.conf	(revision 9)
+++ /trunk/minix/etc/syslog.conf	(revision 9)
@@ -0,0 +1,21 @@
+##
+##  @(#)syslog.conf	1.0	Jan. 18, 2000
+##
+##  Use kill -HUP `cat /usr/run/syslogd.pid` to restart
+##  the server, forcing it to reread this file.
+
+##  Emergency messages (system may be unusable)
+*.emerg					*
+*.alert					/dev/log
+
+##  High severity errors
+*.alert;*.crit				/var/log/syslog
+
+##  Every other message (errors/warning and informational)
+*.info;*.notice;*.warning;*.err		/var/log/messages
+
+##  Debug informations (tracing programs)
+#*.debug					/var/log/debug
+
+##  $Id: syslog.conf,v 1.2 2006/04/05 14:25:21 beng Exp $
+##  end syslog.conf
Index: /trunk/minix/etc/termcap
===================================================================
--- /trunk/minix/etc/termcap	(revision 9)
+++ /trunk/minix/etc/termcap	(revision 9)
@@ -0,0 +1,121 @@
+mx|minix|minix console:\
+	:am:xn:bs:\
+	:co#80:li#25:\
+	:is=\E[0m:\
+	:cd=\E[0J:cl=\E[H\E[0J:\
+	:so=\E[7m:se=\E[0m:\
+	:us=\E[4m:ue=\E[0m:\
+	:mb=\E[5m:md=\E[1m:\
+	:mr=\E[7m:me=\E[0m:\
+	:sr=\EM:\
+	:cm=\E[%i%d;%dH:\
+	:ho=\E[H:\
+	:al=\E[L:AL=\E[%dL:\
+	:ce=\E[K:\
+	:DC=\E[%dP:dc=\E[P:\
+	:DL=\E[%dM:dl=\E[M:\
+	:DO=\E[%dB:do=\E[B:\
+	:IC=\E[%d@:ic=\E[@:\
+	:it#8:\
+	:le=^H:LE=\E[%dD:\
+	:nd=\E[C:RI=\E[%dC:\
+	:up=\E[A:UP=\E[%dA:\
+	:ku=\E[A:kd=\E[B:\
+	:kl=\E[D:kr=\E[C:\
+	:kh=\E[H:kb=^H:\
+	:kD=\177:kI=\E[@:\
+	:kN=\E[U:kP=\E[V:
+du|dialup|Dialup line:\
+	:bs:co#80:li#24:
+db|dumb|Really dumb terminal:\
+	:bs:co#80:li#24:
+lp|lp|Line Printer:\
+	:co#80:li#66:
+li|ansi|Ansi standard crt:\
+	:am:bs:cd=\E[J:ce=\E[K:cl=\E[2J\E[H:cm=\E[%i%d;%dH:co#80:\
+	:dn=\E[B:me=\E[0m:mb=\E[5m:mr=\E[7m:md=\E[1m:ho=\E[H:li#24:\
+	:nd=\E[C:ms:pt:so=\E[7m:se=\E[0m:us=\E[4m:ue=\E[0m:up=\E[A:\
+	:kb=^h:ku=\E[A:kd=\E[B:kl=\E[D:kr=\E[C:
+vs|xterm|xterms|vs100|xterm terminal emulator (X window system):\
+	:am:cr=^M:do=^J:nl=^J:bl=^G:le=^H:ho=\E[H:\
+	:co#80:li#24:cl=\E[H\E[2J:bs:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
+	:ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
+	:md=\E[1m:mr=\E[7m:me=\E[m:\
+	:ku=\E[A:kd=\E[B:kr=\E[C:kl=\E[D:kb=^H:kD=\177:\
+	:kI=\E[@:kN=\E[U:kP=\E[V:ta=^I:pt:sf=\n:sr=\EM:\
+	:al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:\
+	:MT:ks=\E[?1h\E=:ke=\E[?1l\E>:\
+	:is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l:\
+	:rs=\E[r\E<\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l:xn:\
+	:AL=\E[%dL:DL=\E[%dM:IC=\E[%d@:DC=\E[%dP:\
+	:hs:ts=\E]2;:fs=^G:ds=\E]2;^G:
+d0|vt100|vt100-am|vt100am|dec-vt100|dec vt100:\
+	:do=^J:co#80:li#24:cl=\E[;H\E[2J:sf=\ED:\
+	:le=^H:bs:am:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
+	:ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
+	:md=\E[1m:mr=\E[7m:mb=\E[5m:me=\E[m:is=\E[1;24r\E[24;1H:\
+	:rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:\
+	:ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\
+	:ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=\EM:vt#3:xn:\
+	:sc=\E7:rc=\E8:cs=\E[%i%d;%dr:
+
+# - copied the following screen* entries from
+# http://www.catb.org/terminfo/termtypes.tc.gz
+#	Version 11.0.1
+#	$Date: 2006/03/27 14:16:45 $
+# ("This file deliberately has no copyright.  It belongs to no one and
+# everyone.")
+#
+# Entries for use by the `screen' program by Juergen Weigert, 
+# Michael Schroeder, Oliver Laumann.  The screen and
+# screen-w entries came with version 3.7.1.  The screen2 and screen3 entries
+# come from University of Wisconsin and may be older.
+# (screen: added :ve: on ANSI model -- esr)
+# (screen: added <el1> -- TD)
+
+screen|VT 100/ANSI X3.64 virtual terminal:\
+	:am:km:mi:ms:xn:\
+	:Co#8:co#80:it#8:li#24:pa#64:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:F1=\E[23~:\
+	:F2=\E[24~:IC=\E[%d@:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:\
+	:ac=++\054\054--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=^O:al=\E[L:as=^N:bl=^G:bt=\E[Z:cb=\E[1K:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:eA=\E(B\E)0:ei=\E[4l:\
+	:ho=\E[H:im=\E[4h:is=\E)0:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+	:k5=\E[15~:k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:\
+	:k;=\E[21~:kD=\E[3~:kH=\E[4~:kI=\E[2~:kN=\E[6~:kP=\E[5~:\
+	:kb=^H:kd=\EOB:ke=\E[?1l\E>:kh=\E[1~:kl=\EOD:kr=\EOC:\
+	:ks=\E[?1h\E=:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:me=\E[m:\
+	:mr=\E[7m:nd=\E[C:nw=\EE:r2=\Ec:rc=\E8:sc=\E7:se=\E[23m:\
+	:sf=^J:so=\E[3m:sr=\EM:st=\EH:ta=^I:ue=\E[24m:up=\EM:\
+	:us=\E[4m:vb=\Eg:ve=\E[34h\E[?25h:vi=\E[?25l:vs=\E[34l:\
+	:tc=ecma+color:
+
+screen-w|VT 100/ANSI X3.64 virtual terminal with 132 cols:\
+	:co#132:tc=screen:
+
+screen2|old VT 100/ANSI X3.64 virtual terminal:\
+	:co#80:it#8:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:al=\E[L:bt=\E[Z:cd=\E[J:\
+	:ce=\E[K:cl=\E[2J\E[H:cm=\E[%i%d;%dH:cr=^M:ct=\E[3g:\
+	:dc=\E[P:dl=\E[M:do=\E[B:ei=\E[4l:ic=:im=\E[4h:k0=\E~:\
+	:k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:k6=\EP:k7=\EQ:k8=\ER:\
+	:k9=\E0I:kb=^H:kd=\EB:kh=\EH:kl=\ED:kr=\EC:ku=\EA:le=^H:\
+	:me=\E[m:nd=\E[C:nw=^M^J:r1=\Ec:rc=\E8:sc=\E7:se=\E[23m:\
+	:sf=^J:so=\E[3m:sr=\EM:st=\EH:ta=^I:ue=\E[24m:up=\E[A:\
+	:us=\E[4m:
+# (screen3: removed unknown ":xv:LP:G0:" -- esr)
+screen3|older VT 100/ANSI X3.64 virtual terminal:\
+	:km:mi:ms:\
+	:co#80:it#8:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:al=\E[L:bl=^G:bt=\E[Z:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:ei=\E[4l:\
+	:ho=\E[H:im=\E[4h:is=\E)0:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+	:kb=^H:kd=\EOB:ke=\E>:kl=\EOD:kr=\EOC:ks=\E=:ku=\EOA:le=^H:\
+	:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:nw=\EE:r1=\Ec:\
+	:rc=\E8:sc=\E7:se=\E[23m:sf=^J:so=\E[3m:sr=\EM:st=\EH:ta=^I:\
+	:ue=\E[24m:up=\EM:us=\E[4m:
Index: /trunk/minix/etc/termcap.big
===================================================================
--- /trunk/minix/etc/termcap.big	(revision 9)
+++ /trunk/minix/etc/termcap.big	(revision 9)
@@ -0,0 +1,16470 @@
+######## TERMINAL TYPE DESCRIPTIONS SOURCE FILE
+#
+#	Version 11.0.1
+#	$Date: 2006/03/27 14:16:45 $
+#	termcap syntax
+#
+#	Eric S. Raymond		(current maintainer)
+#	John Kunze, Berkeley
+#	Craig Leres, Berkeley
+#
+# Please e-mail changes to terminfo@thyrsus.com; the old termcap@berkeley.edu
+# address is no longer valid.  The latest version can always be found at
+# <http://www.tuxedo.org/terminfo>.
+#
+# PURPOSE OF THIS FILE:
+#
+# This file describes the capabilities of various character-cell terminals,
+# as needed by software such as screen-oriented editors.
+#
+# Other terminfo and termcap files exist, supported by various OS vendors
+# or as relics of various older versions of UNIX.  This one is the longest
+# and most comprehensive one in existence.  It subsumes not only the entirety
+# of the historical 4.4BSD, GNU, System V and SCO termcap files and the BRL
+# termcap file, but also large numbers of vendor-maintained termcap and
+# terminfo entries more complete and carefully tested than those in historical
+# termcap/terminfo versions.
+#
+# Pointers to related resources (including the ncurses distribution) may
+# be found at <http://www.tuxedo.org/terminfo>.
+#
+# INTERNATIONALIZATION:
+#
+# This file uses only the US-ASCII character set (no ISO8859 characters).
+#
+# This file assumes a US-ASCII character set. If you need to fix this, start
+# by global-replacing \E(B and \E)B with the appropriate ISO 6429 enablers
+# for your character set.  \E(A and \E)A enables the British character set
+# with the pound sign at position 2/3.  
+#
+# In a Japanese-processing environment using EUC/Japanese or Shift-JIS,
+# C1 characters are considered the first-byte set of the Japanese encodings,
+# so \E)0 should be avoided in <enacs> and initialization strings.
+#
+# FILE FORMAT:
+#
+# The version you are looking at may be in any of three formats: master
+# (terminfo with OT capabilities), stock terminfo, or termcap.  You can tell
+# which by the format given in the header above.
+#
+# The master format is accepted and generated by the terminfo tools in the
+# ncurses suite; it differs from stock (System V-compatible) terminfo only
+# in that it admits a group of capabilities (prefixed `OT') equivalent to
+# various obsolete termcap capabilities.  You can, thus, convert from master
+# to stock terminfo simply by filtering with `sed "/OT[^,]*,/s///"'; but if
+# you have ncurses `tic -I' is nicer (among other things, it automatically
+# outputs entries in a canonical form).
+#
+# The termcap version is generated automatically from the master version
+# using tic -C.  This filtering leaves in the OT capabilities under their
+# original termcap names.  All translated entries fit within the 1023-byte
+# string-table limit of archaic termcap libraries except where explicitly
+# noted below.  Note that the termcap translation assumes that your termcap
+# library can handle multiple tc capabilities in an entry. 4.4BSD has this
+# capability.  Older versions of GNU termcap, through 1.3, do not. 
+#
+# For details on these formats, see terminfo(5) in the ncurses distribution,
+# and termcap(5) in the 4.4BSD Unix Programmer's Manual.  Be aware that 4.4BSD
+# curses has been declared obsolete by the caretakers of the 4.4BSD sources
+# as of June 1995; they are encouraging everyone to migrate to ncurses.
+#
+# Note: unlike some other distributed terminfo files (Novell Unix & SCO's),
+# no entry in this file has embedded comments.  This is so source translation
+# to termcap only has to carry over leading comments.  Also, no name field
+# contains embedded whitespace (such whitespace confuses rdist).
+#
+# Further note: older versions of this file were often installed with an editor
+# script (reorder) that moved the most common terminal types to the front of
+# the file.  This should no longer be necessary, as the file is now ordered
+# roughly by type frequency with ANSI/VT100 and other common types up front.
+#
+# Some information has been merged in from terminfo files distributed by
+# USL and SCO (see COPYRIGHTS AND OTHER DELUSIONS below).  Much information
+# comes from vendors who maintain official terminfos for their hardware
+# (notably DEC and Wyse).
+#
+# A detailed change history is included at the end of this file.
+#
+# FILE ORGANIZATION:
+#
+# Comments in this file begin with # - they cannot appear in the middle
+# of a terminfo/termcap entry (this feature had to be sacrificed in order
+# to allow standard terminfo and termcap syntax to be generated cleanly from
+# the master format).  Individual capabilities are commented out by
+# placing a period between the colon and the capability name.
+#
+# The file is divided up into major sections (headed by lines beginning with 
+# the string "########") and minor sections (beginning with "####"); do
+#
+#	grep "^####" <file> | more
+#
+# to see a listing of section headings.  The intent of the divisions is
+# (a) to make it easier to find things, and (b) to order the database so
+# that important and frequently-encountered terminal types are near the
+# front (so that you'll get reasonable search efficiency from a linear
+# search of the termcap form even if you don't use reorder).  Minor sections
+# usually correspond to manufacturers or standard terminal classes. 
+# Parenthesized words following manufacturer names are type prefixes or
+# product line names used by that manufacturers.
+#
+# HOW TO READ THE ENTRIES:
+#
+# The first name in an entry is the canonical name for the model or
+# type, last entry is a verbose description.  Others are mnemonic synonyms for
+# the terminal.
+#
+# Terminal names look like <manufacturer> <model> - <modes/options>
+# The part to the left of the dash, if a dash is present, describes the
+# particular hardware of the terminal.  The part to the right may be used
+# for flags indicating special ROMs, extra memory, particular terminal modes,
+# or user preferences.
+#
+# All names should be in lower case, for consistency in typing.
+#
+# The following are conventionally used suffixes:
+#	-2p	Has two pages of memory.  Likewise 4p, 8p, etc.
+#	-am	Enable auto-margin.
+#	-m	Monochrome.  Suppress color support
+#	-mc	Magic-cookie.  Some terminals (notably older Wyses) can
+#		only support one attribute without magic-cookie lossage.
+#		Their base entry is usually paired with another that
+#		uses magic cookies to support multiple attributes.
+#	-nam	No auto-margin - suppress :am: capability
+#	-nl	No labels - suppress soft labels
+#	-ns	No status line - suppress status line
+#	-rv	Terminal in reverse video mode (black on white)
+#	-s	Enable status line.
+#	-vb	Use visible bell (:vb:) rather than :bl:.
+#	-w	Wide - in 132 column mode.
+# If a name has multiple suffixes and one is a line height, that one should 
+# go first.  Thus `aaa-30-s-rv' is recommended over `aaa-s-rv-30'.  
+# 
+# Entries with embedded plus signs are designed to be included through use/tc
+# capabilities, not used as standalone entries. 
+#
+# To avoid search clashes, some older all-numeric names for terminals have
+# been removed (i.e., "33" for the Model 33 Teletype, "2621" for the HP2621).
+# All primary names of terminals now have alphanumeric prefixes.
+#
+# Comments marked "esr" are mostly results of applying the termcap-compiler
+# code packaged with ncurses and contemplating the resulting error messages. 
+# In many cases, these indicated obvious fixes to syntax garbled by the
+# composers.  In a few cases, I was able to deduce corrected forms for garbled
+# capabilities by looking at context.  All the information in the original
+# entries is preserved in the comments.
+#
+# In the comments, terminfo capability names are bracketed with <> (angle
+# brackets).  Termcap capability names are bracketed with :: (colons).
+#
+# INTERPRETATION OF USER CAPABILITIES
+#
+# The System V Release 4 and XPG4 terminfo format defines ten string
+# capabilities for use by applications, <u0>...<u9>.   In this file, we use
+# certain of these capabilities to describe functions which are not covered
+# by terminfo.  The mapping is as follows:
+#
+#	u9	terminal enquire string (equiv. to ANSI/ECMA-48 DA)
+#	u8	terminal answerback description
+#	u7	cursor position request (equiv. to VT100/ANSI/ECMA-48 DSR 6)
+#	u6	cursor position report (equiv. to ANSI/ECMA-48 CPR)
+#
+# The terminal enquire string <u9> should elicit an answerback response
+# from the terminal.  Common values for <u9> will be ^E (on older ASCII
+# terminals) or \E[c (on newer VT100/ANSI/ECMA-48-compatible terminals).
+#
+# The cursor position request (<u7>) string should elicit a cursor position
+# report.  A typical value (for VT100 terminals) is \E[6n.
+#
+# The terminal answerback description (u8) must consist of an expected
+# answerback string.  The string may contain the following scanf(3)-like
+# escapes:
+#
+#	%c	Accept any character
+#	%[...]	Accept any number of characters in the given set
+#
+# The cursor position report (<u6>) string must contain two scanf(3)-style 
+# %d format elements.  The first of these must correspond to the Y coordinate
+# and the second to the %d.  If the string contains the sequence %i, it is
+# taken as an instruction to decrement each value after reading it (this is
+# the inverse sense from the cup string).  The typical CPR value is
+# \E[%i%d;%dR (on VT100/ANSI/ECMA-48-compatible terminals).
+#
+# These capabilities are used by tac(1m), the terminfo action checker
+# (distributed with ncurses 5.0).
+#
+# TABSET FILES
+#
+# All the entries in this file have been edited to assume that the tabset
+# files directory is /usr/share/tabset, in conformance with the File Hierarchy
+# Standard for Linux and open-source BSD systems.  Some vendors (notably Sun)
+# use /usr/lib/tabset or (more recently) /usr/share/lib/tabset.  
+#
+# No curses package we know of actually uses these files.  If their location
+# is an issue, you will have to hand-patch the file locations before compiling
+# this file.
+# 
+# REQUEST FOR CONTACT INFORMATION AND HISTORICAL MATERIAL
+#
+# As the ANSI/ECMA-48 standard and variants take firmer hold, and as
+# character-cell terminals are increasingly replaced by X displays, much of
+# this file is becoming a historical document (this is part of the reason for
+# the new organization, which puts ANSI types, xterm, Unix consoles,
+# and vt100 up front in confidence that this will catch 95% of new hardware).
+#
+# For the terminal types still alive, I'd like to have manufacturer's
+# contact data (Internet address and/or snail-mail + phone).
+#
+# I'm also interested in enriching the comments so that the latter portions of
+# the file do in fact become a potted history of VDT technology as seen by
+# UNIX hackers.  Ideally, I'd like the headers for each manufacturer to
+# include its live/dead/out-of-the-business status, and for as many
+# terminal types as possible to be tagged with information like years
+# of heaviest use, popularity, and interesting features.
+#
+# I'm especially interested in identifying the obscure entries listed under
+# `Miscellaneous obsolete terminals, manufacturers unknown' before the tribal
+# wisdom about them gets lost.  If you know a lot about obscure old terminals,
+# please go to the terminfo resource page, grab the UFO file (ufo.ti), and 
+# eyeball it for things you can identify and describe. 
+#
+# If you have been around long enough to contribute, please read the file
+# with this in mind and send me your annotations.
+#
+# COPYRIGHTS AND OTHER DELUSIONS
+#
+# The BSD ancestor of this file had a standard Regents of the University of
+# California copyright with dates from 1980 to 1993.
+#
+# Some information has been merged in from a terminfo file SCO distributes.
+# It has an obnoxious boilerplate copyright which I'm ignoring because they 
+# took so much of the content from the ancestral BSD versions of this file
+# and didn't attribute it, thereby violating the BSD Regents' copyright.
+#
+# Not that anyone should care.  However many valid functions copyrights may
+# serve, putting one on a termcap/terminfo file with hundreds of anonymous
+# contributors makes about as much sense as copyrighting a wall-full of
+# graffiti -- it's legally dubious, ethically bogus, and patently ridiculous.
+#
+# This file deliberately has no copyright.  It belongs to no one and everyone.
+# If you claim you own it, you will merely succeed in looking like a fool. 
+# Use it as you like.  Use it at your own risk.  Copy and redistribute freely.
+# There are no guarantees anywhere.  Svaha!
+#
+
+######## ANSI, UNIX CONSOLE, AND SPECIAL TYPES
+#
+# This section describes terminal classes and brands that are still
+# quite common.
+#
+
+#### Specials
+#
+# Special "terminals".  These are used to label tty lines when you don't
+# know what kind of terminal is on it.  The characteristics of an unknown
+# terminal are the lowest common denominator - they look about like a ti 700.
+#
+
+dumb|80-column dumb tty:\
+	:am:\
+	:co#80:\
+	:bl=^G:cr=^M:do=^J:sf=^J:
+unknown|unknown terminal type:\
+	:gn:tc=dumb:
+lpr|printer|line printer:\
+	:bs:hc:os:\
+	:co#132:li#66:\
+	:bl=^G:cr=^M:do=^J:ff=^L:le=^H:sf=^J:
+glasstty|classic glass tty interpreting ASCII control characters:\
+	:am:bs:\
+	:co#80:\
+	:bl=^G:cl=^L:cr=^M:do=^J:kd=^J:kl=^H:le=^H:nw=^M^J:ta=^I:
+vanilla:\
+	:bs:\
+	:bl=^G:cr=^M:do=^J:sf=^J:
+
+#### ANSI.SYS/ISO 6429/ECMA-48 Capabilities
+#
+# See the end-of-file comment for more on these.
+#
+
+# ANSI capabilities are broken up into pieces, so that a terminal
+# implementing some ANSI subset can use many of them.
+ansi+local1:\
+	:do=\E[B:le=\E[D:nd=\E[C:up=\E[A:
+ansi+local:\
+	:DO=\E[%dB:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:tc=ansi+local1:
+ansi+tabs:\
+	:bt=\E[Z:ct=\E[2g:st=\EH:ta=^I:
+ansi+inittabs:\
+	:it#8:tc=ansi+tabs:
+ansi+erase:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[J:
+ansi+rca:\
+	:ch=\E[%+^AG:cv=\E[%+^Ad:
+ansi+cup:\
+	:cm=\E[%i%d;%dH:ho=\E[H:
+ansi+rep:\
+	:..rp=%p1%c\E[%p2%{1}%-%db:
+ansi+idl1:\
+	:al=\E[L:dl=\E[M:
+ansi+idl:\
+	:AL=\E[%dL:DL=\E[%dM:tc=ansi+idl1:
+ansi+idc:\
+	:IC=\E[%d@:dc=\E[P:ei=\E6:ic=\E[@:im=\E6:
+ansi+arrows:\
+	:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:
+ansi+sgr|ansi graphic renditions:\
+	:mb=\E[5m:me=\E[0m:mk=\E[8m:mr=\E[7m:
+ansi+sgrso|ansi standout only:\
+	:se=\E[m:so=\E[7m:
+ansi+sgrul|ansi underline only:\
+	:ue=\E[m:us=\E[4m:
+ansi+sgrbold|ansi graphic renditions; assuming terminal has bold; not dim:\
+	:md=\E[1m:\
+	:..sa=\E[%?%p1%t7;%;%?%p2%t4;%;%?%p3%t7;%;%?%p4%t5;%;%?%p6%t1;%;m:tc=ansi+sgr:tc=ansi+sgrso:tc=ansi+sgrul:
+ansi+sgrdim|ansi graphic renditions; assuming terminal has dim; not bold:\
+	:mh=\E[2m:\
+	:..sa=\E[%?%p1%t7;%;%?%p2%t4;%;%?%p3%t7;%;%?%p4%t5;%;%?%p5%t2;%;m:tc=ansi+sgr:tc=ansi+sgrso:tc=ansi+sgrul:
+ansi+pp|ansi printer port:\
+	:pf=\E[4i:po=\E[5i:ps=\E[0i:
+ansi+csr|ansi scroll-region plus cursor save & restore:\
+	:cs=\E[%i%d;%dr:rc=\E8:sc=\E7:
+
+# The IBM PC alternate character set.  Plug this into any Intel console entry.
+# We use \E[11m for rmacs rather than \E[12m so the <acsc> string can use the
+# ROM graphics for control characters such as the diamond, up- and down-arrow.
+# This works with the System V, Linux, and BSDI consoles.  It's a safe bet this
+# will work with any Intel console, they all seem to have inherited \E[11m
+# from the ANSI.SYS de-facto standard.
+klone+acs|alternate character set for ansi.sys displays:\
+	:ac=+\020\054\021-\030.^Y0\333`\004a\261f\370g\361h\260j\331k\277l\332m\300n\305o~p\304q\304r\304s_t\303u\264v\301w\302x\263y\363z\362{\343|\330}\234~\376:\
+	:ae=\E[10m:as=\E[11m:
+
+# Highlight controls corresponding to the ANSI.SYS standard.  Most 
+# console drivers for Intel boxes obey these.  Makes the same assumption
+# about \E[11m as klone+acs.  True ANSI/ECMA-48 would have :se=\E[27m:,
+# :ue=\E[24m:, but this isn't a documented feature of ANSI.SYS.
+klone+sgr|attribute control for ansi.sys displays:\
+	:S2=\E[11m:S3=\E[10m:mb=\E[5m:md=\E[1m:me=\E[0;10m:\
+	:mk=\E[8m:mr=\E[7m:\
+	:..sa=\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m:\
+	:se=\E[m:so=\E[7m:ue=\E[m:us=\E[4m:\
+	:tc=klone+acs:
+
+# Highlight controls corresponding to the ANSI.SYS standard.  *All*
+# console drivers for Intel boxes obey these.  Does not assume \E[11m will
+# work; uses \E[12m instead, which is pretty bulletproof but loses you the ACS
+# diamond and arrow characters under curses.
+klone+sgr-dumb|attribute control for ansi.sys displays (no ESC [ 11 m):\
+	:as=\E[12m:mb=\E[5m:md=\E[1m:me=\E[0;10m:mk=\E[8m:\
+	:mr=\E[7m:\
+	:..sa=\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;12%;m:\
+	:se=\E[m:so=\E[7m:ue=\E[m:us=\E[4m:\
+	:tc=klone+acs:
+
+# KOI8-R (RFC1489) acs (alternate character set)
+# From: Qing Long <qinglong@Bolizm.ihep.su>, 24 Feb 1996.
+klone+koi8acs|alternate character set for ansi.sys displays with KOI8 charset:\
+	:ac=+\020\054\021-\036.^_0\215`\004a\237f\234g\232h\222i\220j\205k\203l\202m\204n\212o\213p\216q\0r\217s\214t\206u\207v\210w\211x\201y\230z\231{\267|\274}L~\225:\
+	:ae=\E[10m:as=\E[11m:
+
+# ANSI.SYS color control.  The setab/setaf caps depend on the coincidence
+# between SVr4/XPG4's color numbers and ANSI.SYS attributes.  Here are longer
+# but equivalent strings that don't rely on that coincidence:
+# setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m,
+# setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m,
+# The DOS 5 manual asserts that these sequences meet the ISO 6429 standard.
+# They match a subset of ECMA-48.
+klone+color|color control for ansi.sys and ISO6429-compatible displays:\
+	:Co#8:NC#3:pa#64:\
+	:AB=\E[4%p1%dm:AF=\E[3%p1%dm:op=\E[37;40m:
+
+# This is better than klone+color, it doesn't assume white-on-black as the
+# default color pair,  but many `ANSI' terminals don't grok the <op> cap.
+ecma+color|color control for ECMA-48-compatible terminals:\
+	:Co#8:NC#3:pa#64:\
+	:AB=\E[4%p1%dm:AF=\E[3%p1%dm:op=\E[39;49m:
+
+# Attribute control for ECMA-48-compatible terminals
+ecma+sgr|attribute capabilities for true ECMA-48 terminals:\
+	:se=\E[27m:ue=\E[24m:\
+	:tc=klone+sgr:
+
+# For comparison, here are all the capabilities implied by the Intel
+# Binary Compatibility Standard (level 2) that fit within terminfo.
+# For more detail on this rather pathetic standard, see the comments
+# near the end of this file.
+ibcs2|Intel Binary Compatibility Standard prescriptions:\
+	:AL=\E[%dL:DC=\E[%dP:DO=\E[%dB:IC=\E[%d@:LE=\E[%dD:\
+	:RA=\E[?7l:RI=\E[%dC:S1=\E=%p1%dg:SA=\E[?7h:SF=\E[%dS:\
+	:SR=\E[%dT:UP=\E[%dA:bt=\E[Z:ch=\E[%i%dG:cl=\Ec:\
+	:cm=\E[%i%d;%dH:ct=\E[g:cv=\E[%i%dd:ec=\E[%dX:ei=:im=:\
+	:rc=\E7:sc=\E7:st=\EH:
+
+#### ANSI/ECMA-48 terminals and terminal emulators
+#
+# See near the end of this file for details on ANSI conformance.
+# Don't mess with these entries!  Lots of other entries depend on them!
+#
+# This section lists entries in a least-capable to most-capable order.
+# if you're in doubt about what `ANSI' matches yours, try them in that
+# order and back off from the first that breaks.
+
+# ansi-mr is for ANSI terminals with ONLY relative cursor addressing
+# and more than one page of memory.  It uses local motions instead of
+# direct cursor addressing, and makes almost no assumptions. It does
+# assume auto margins, no padding and/or xon/xoff, and a 24x80 screen.
+ansi-mr|mem rel cup ansi:\
+	:am:xo:\
+	:co#80:li#24:tc=vanilla:tc=ansi+erase:tc=ansi+local1:
+
+# ansi-mini is a bare minimum ANSI terminal. This should work on anything, but 
+# beware of screen size problems and memory relative cursor addressing.
+ansi-mini|minimum ansi standard terminal:\
+	:am:xo:\
+	:co#80:li#24:tc=vanilla:tc=ansi+cup:tc=ansi+erase:
+
+# ansi-mtabs adds relative addressing and minimal tab support 
+ansi-mtabs|any ansi terminal with pessimistic assumptions:\
+	:it#8:\
+	:ta=^I:tc=ansi+local1:tc=ansi-mini:
+
+# ANSI X3.64 from emory!mlhhh (Hugh Hansard) via BRL
+#
+# The following is an entry for the full ANSI 3.64 (1977).  It lacks
+# padding, but most terminals using the standard are "fast" enough
+# not to require any -- even at 9600 bps.  If you encounter problems,
+# try including the padding specifications.
+#
+# Note: the :as: and :ae: specifications are not implemented here, for
+# the available termcap documentation does not make clear WHICH alternate
+# character set to specify.  ANSI 3.64 seems to make allowances for several.
+# Please make the appropriate adjustments to fit your needs -- that is
+# if you will be using alternate character sets.
+#
+# There are very few terminals running the full ANSI 3.64 standard,
+# so I could only test this entry on one verified terminal (Visual 102).
+# I would appreciate the results on other terminals sent to me.
+#
+# Please report comments, changes, and problems to:
+#
+# U.S. MAIL:   Hugh Hansard
+#              Box: 22830
+#              Emory University
+#              Atlanta, GA. 30322.
+#
+# USENET {akgua,msdc,sb1,sb6,gatech}!emory!mlhhh.
+#
+# (Added vt100 :rc:,:sc: to quiet a tic warning --esr)
+ansi77|ansi 3.64 standard 1977 version:\
+	:am:bs:mi:\
+	:co#80:it#8:li#24:\
+	:al=5*\E[L:bl=^G:cd=\E[J:ce=\E[K:cl=\E[;H\E[2J:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:dc=\E[P:dl=5*\E[M:\
+	:do=\E[B:ei=\E[4l:ho=\E[H:im=\E[4h:k1=\EOP:k2=\EOR:k4=\EOS:\
+	:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:\
+	:nd=\E[C:nw=^M\ED:rc=\E8:sc=\E7:se=\E[m:sf=\ED:so=\E[7m:\
+	:sr=\EM:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:
+
+# Procomm and some other ANSI emulations don't recognize all of the ANSI-
+# standard capabilities.  This entry deletes :UP:, :RI:, :DO:, :LE:, and 
+# <vpa>/<hpa> capabilities, forcing curses to use repetitions of :up:, 
+# :nd:, :do: and :le:.  Also deleted :IC: and :ic:, as QModem up to 
+# 5.03 doesn't recognize these.  Finally, we delete :rp: and :sr:, which seem
+# to confuse many emulators.  On the other hand, we can count on these programs
+# doing :ae:/:as:/:sa:. Older versions of this entry featured 
+# <invis=\E[9m>, but <invis=\E[8m> now seems to be more common under
+# ANSI.SYS influence.
+# From: Eric S. Raymond <esr@snark.thyrsus.com> Oct 30 1995
+pcansi-m|pcansi-mono|ibm-pc terminal programs claiming to be ansi (mono mode):\
+	:am:bs:mi:ms:\
+	:co#80:it#8:li#24:\
+	:al=\E[L:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:ct=\E[2g:dc=\E[P:dl=\E[M:do=\E[B:\
+	:ho=\E[H:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:le=\E[D:nd=\E[C:sf=^J:st=\EH:ta=^I:up=\E[A:\
+	:tc=klone+sgr-dumb:
+pcansi-25-m|pcansi25m|ibm-pc terminal programs with 25 lines (mono mode):\
+	:li#25:tc=pcansi-m:
+pcansi-33-m|pcansi33m|ibm-pc terminal programs with 33 lines (mono mode):\
+	:li#33:tc=pcansi-m:
+pcansi-43-m|ansi43m|ibm-pc terminal programs with 43 lines (mono mode):\
+	:li#43:tc=pcansi-m:
+# The color versions.  All PC emulators do color...
+pcansi|ibm-pc terminal programs claiming to be ansi:\
+	:tc=klone+color:tc=pcansi-m:
+pcansi-25|pcansi25|ibm-pc terminal programs with 25 lines:\
+	:li#25:tc=pcansi:
+pcansi-33|pcansi33|ibm-pc terminal programs with 33 lines:\
+	:li#33:tc=pcansi:
+pcansi-43|pcansi43|ibm-pc terminal programs with 43 lines:\
+	:li#43:tc=pcansi:
+
+# ansi-m -- full ANSI X3.64 with ANSI.SYS-compatible attributes, no color.
+# If you want pound signs rather than dollars, replace `B' with `A'
+# in the <s0ds>, <s1ds>, <s2ds>, and <s3ds> capabilities.
+# From: Eric S. Raymond <esr@snark.thyrsus.com> Nov 6 1995
+ansi-m|ansi-mono|ANSI X3.64-1979 terminal with ANSI.SYS compatible attributes:\
+	:5i:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:SF=\E[%dS:SR=\E[%dT:UP=\E[%dA:\
+	:cb=\E[1K:ch=\E[%i%dG:ct=\E[2g:cv=\E[%i%dd:ec=\E[%dX:ei=:\
+	:im=:kB=\E[Z:kI=\E[L:kb=^H:kd=\E[B:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:nw=\r\E[S:pf=\E[4i:po=\E[5i:..rp=%p1%c\E[%p2%{1}%-%db:\
+	:s0=\E(B:s1=\E)B:s2=\E*B:s3=\E+B:ta=\E[I:\
+	:tc=pcansi-m:
+
+# ansi -- this terminfo expresses the largest subset of X3.64 that will fit in
+# standard terminfo.  Assumes ANSI.SYS-compatible attributes and color.
+# From: Eric S. Raymond <esr@snark.thyrsus.com> Nov 6 1995
+ansi|ansi/pc-term compatible with color:\
+	:u6=\E[%i%d;%dR:u7=\E[6n:..u8=\E[?%[;0123456789]c:\
+	:u9=\E[c:\
+	:tc=ecma+color:tc=klone+sgr:tc=ansi-m:
+
+# ansi-generic is a vanilla ANSI terminal. This is assumed to implement 
+# all the normal ANSI stuff with no extensions. It assumes 
+# insert/delete line/char is there, so it won't work with 
+# vt100 clones. It assumes video attributes for bold, blink, 
+# underline, and reverse, which won't matter much if the terminal 
+# can't do some of those. Padding is assumed to be zero, which 
+# shouldn't hurt since xon/xoff is assumed.
+ansi-generic|generic ansi standard terminal:\
+	:am:xo:\
+	:co#80:li#24:tc=vanilla:tc=ansi+csr:tc=ansi+cup:\
+	:tc=ansi+rca:tc=ansi+erase:tc=ansi+tabs:tc=ansi+local:\
+	:tc=ansi+idc:tc=ansi+idl:tc=ansi+rep:tc=ansi+sgrbold:\
+	:tc=ansi+arrows:
+
+#### Linux consoles
+#
+
+# This entry is good for the 1.2.13 or later version of the Linux console.
+#
+# ***************************************************************************
+# *                                                                         *
+# *                           WARNING:                                      *
+# * Linuxes come with a default keyboard mapping kcbt=^I.  This entry, in   *
+# * response to user requests, assumes kcbt=\E[Z, the ANSI/ECMA reverse-tab *
+# * character. Here are the keymap replacement lines that will set this up: *
+# *                                                                         *
+#	keycode  15 = Tab             Tab
+#		alt     keycode  15 = Meta_Tab
+#		shift	keycode  15 = F26
+#	string F26 ="\033[Z"
+# *                                                                         *
+# * This has to use a key slot which is unfortunate (any unused one will    *
+# * do, F26 is the higher-numbered one).  The change ought to be built      *
+# * into the kernel tables.                                                 *
+# *                                                                         *
+# ***************************************************************************
+#
+# The 1.3.x kernels add color-change capabilities; if yours doesn't have this
+# and it matters, turn off <ccc>.  The %02x escape used to implement this is
+# not back-portable to SV curses and not supported in ncurses versions before
+# 1.9.9. All linux kernels since 1.2.13 (at least) set the screen size
+# themselves; this entry assumes that capability.
+#
+# This entry is good for the 1.2.13 or later version of the Linux console.
+#
+# ***************************************************************************
+# *                                                                         *
+# *                           WARNING:                                      *
+# * Linuxes come with a default keyboard mapping kcbt=^I.  This entry, in   *
+# * response to user requests, assumes kcbt=\E[Z, the ANSI/ECMA reverse-tab *
+# * character. Here are the keymap replacement lines that will set this up: *
+# *                                                                         *
+#	keycode  15 = Tab             Tab
+#		alt     keycode  15 = Meta_Tab
+#		shift	keycode  15 = F26
+#	string F26 ="\033[Z"
+# *                                                                         *
+# * This has to use a key slot which is unfortunate (any unused one will    *
+# * do, F26 is the higher-numbered one).  The change ought to be built      *
+# * into the kernel tables.                                                 *
+# *                                                                         *
+# ***************************************************************************
+#
+# The 1.3.x kernels add color-change capabilities; if yours doesn't have this
+# and it matters, turn off <ccc>.  The %02x escape used to implement this is
+# not back-portable to SV curses and not supported in ncurses versions before
+# 1.9.9. All linux kernels since 1.2.13 (at least) set the screen size
+# themselves; this entry assumes that capability.
+#
+# The 2.2.x kernels add a private mode that sets the cursor type; use that to
+# get a block cursor for cvvis.
+# reported by Frank Heckenbach <frank@g-n-u.de>.
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+linux|linux console:\
+	:am:eo:mi:ms:xn:xo:\
+	:it#8:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:IC=\E[%d@:K2=\E[G:al=\E[L:\
+	:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:ec=\E[%dX:\
+	:ei=\E[4l:ho=\E[H:ic=\E[@:im=\E[4h:k1=\E[[A:k2=\E[[B:\
+	:k3=\E[[C:k4=\E[[D:k5=\E[[E:k6=\E[17~:k7=\E[18~:k8=\E[19~:\
+	:k9=\E[20~:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:kb=\177:\
+	:kd=\E[B:kh=\E[1~:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mh=\E[2m:\
+	:mr=\E[7m:nd=\E[C:nw=^M^J:rc=\E8:sc=\E7:se=\E[27m:sf=^J:\
+	:sr=\EM:st=\EH:ta=^I:ue=\E[24m:up=\E[A:us=\E[4m:\
+	:vb=200\E[?5h\E[?5l:ve=\E[?25h\E[?0c:vi=\E[?25l\E[?1c:\
+	:vs=\E[?25h\E[?8c:\
+	:tc=klone+sgr:tc=ecma+color:
+linux-m|Linux console no color:\
+	:Co@:pa@:\
+	:AB@:AF@:Sb@:Sf@:tc=linux:
+linux-c-nc|linux console 1.3.x hack for ncurses only:\
+	:cc:\
+	:..Ic=\E]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x:\
+	:oc=\E]R:\
+	:tc=linux:
+# From: Dennis Henriksen <opus@osrl.dk>, 9 July 1996
+linux-c|linux console 1.3.6+ with private palette for each virtual console:\
+	:cc:\
+	:Co#8:pa#64:\
+	:..Ic=\E]P%?%p1%{9}%>%t%p1%{10}%-%'a'%+%c%e%p1%d%;%p2%{255}%&%Pr%gr%{16}%/%Px%?%gx%{9}%>%t%gx%{10}%-%'A'%+%c%e%gx%d%;%gr%{15}%&%Px%?%gx%{9}%>%t%gx%{10}%-%'A'%+%c%e%gx%d%;%p3%{255}%&%Pr%gr%{16}%/%Px%?%gx%{9}%>%t%gx%{10}%-%'A'%+%c%e%gx%d%;%gr%{15}%&%Px%?%gx%{9}%>%t%gx%{10}%-%'A'%+%c%e%gx%d%;%p4%{255}%&%Pr%gr%{16}%/%Px%?%gx%{9}%>%t%gx%{10}%-%'A'%+%c%e%gx%d%;%gr%{15}%&%Px%?%gx%{9}%>%t%gx%{10}%-%'A'%+%c%e%gx%d%;:\
+	:oc=\E]R:\
+	:tc=linux:
+
+# See the note on ICH/ICH1 VERSUS RMIR/SMIR near the end of file
+linux-nic|linux with ich/ich1 suppressed for non-curses programs:\
+	:IC@:ei=:ic@:im=:\
+	:tc=linux:
+
+# This assumes you have used setfont(8) to load one of the Linux koi8-r fonts.
+# acsc entry from Pavel Roskin" <pavel@absolute.spb.su>, 29 Sep 1997.
+linux-koi8|linux with koi8 alternate character set:\
+	:ac=+\020\054\021-\030.^Y0\215`\004a\221f\234g\237h\220i\276j\205k\203l\202m\204n\212o~p\0q\0r\0s_t\206u\207v\211w\210x\201y\230z\231{\267|\274~\224:tc=linux:\
+	:tc=klone+koi8acs:
+
+# Another entry for KOI8-r with Qing Long's acsc.
+# (which one better complies with the standard?)
+linux-koi8r|linux with koi8-r alternate character set:\
+	:tc=linux:tc=klone+koi8acs:
+
+# Entry for the latin1 and latin2 fonts
+linux-lat|linux with latin1 or latin2 alternate character set:\
+	:ac=+\020\054\021-\030.^Y0\333`\004a\013f\370g\361h\260i\316j\211k\214l\206m\203n\305o~p\304q\212r\304s_t\207u\215v\301w\302x\205y\363z\362{\343|\330}\234~\376:\
+	:tc=linux:
+
+#### NetBSD consoles
+#
+# pcvt termcap database entries (corresponding to release 3.31)
+# Author's last edit-date: [Fri Sep 15 20:29:10 1995]
+#
+# (For the terminfo master file, I translated these into terminfo syntax.
+# Then I dropped all the pseudo-HP entries. we don't want and can't use
+# the :Xs: flag. Then I split :is: into a size-independent :i1: and a
+# size-dependent :is:.  Finally, I added <rmam>/<smam> -- esr)
+
+# NOTE: :ic: has been taken out of this entry. for reference, it should
+# be <ich1=\E[@>.  For discussion, see ICH/ICH1 VERSUS RMIR/SMIR below.
+# (esr: added :vi: and :ve: to resolve NetBSD Problem Report #4583)
+pcvtXX|pcvt vt200 emulator (DEC VT220):\
+	:am:km:mi:ms:xn:\
+	:it#8:vt#3:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:SF=\E[%dS:\
+	:SR=\E[%dT:UP=\E[%dA:\
+	:ac=++\054\054--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~:\
+	:ae=\E(B:al=\E[L:as=\E(0:bl=^G:cb=\E[1K:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:ct=\E[3g:dc=\E[P:dl=\E[M:do=\E[B:ei=\E[4l:ho=\E[H:\
+	:i1=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:im=\E[4h:\
+	:k1=\E[17~:k2=\E[18~:k3=\E[19~:k4=\E[20~:k5=\E[21~:\
+	:k6=\E[23~:k7=\E[24~:k8=\E[25~:kD=\E[3~:kH=\E[4~:kI=\E[2~:\
+	:kN=\E[6~:kP=\E[5~:kb=\177:kd=\EOB:ke=\E[?1l\E>:kh=\E[1~:\
+	:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:mb=\E[5m:\
+	:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:nw=\EE:\
+	:r1=\Ec\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\E8:\
+	:rf=/usr/share/tabset/vt100:sc=\E7:se=\E[27m:sf=\ED:\
+	:so=\E[7m:sr=\EM:st=\EH:ta=^I:ue=\E[24m:up=\E[A:us=\E[4m:\
+	:ve=\E[?25h:vi=\E[?25l:
+
+#	NetBSD/FreeBSD vt220 terminal emulator console (pc keyboard & monitor)
+#	termcap entries for pure VT220-Emulation and 25, 28, 35, 40, 43 and
+#	50 lines entries; 80 columns
+pcvt25|dec vt220 emulation with 25 lines:\
+	:co#80:li#25:\
+	:is=\E[1;25r\E[25;1H:tc=pcvtXX:
+pcvt28|dec vt220 emulation with 28 lines:\
+	:co#80:li#28:\
+	:is=\E[1;28r\E[28;1H:tc=pcvtXX:
+pcvt35|dec vt220 emulation with 35 lines:\
+	:co#80:li#35:\
+	:is=\E[1;35r\E[35;1H:tc=pcvtXX:
+pcvt40|dec vt220 emulation with 40 lines:\
+	:co#80:li#40:\
+	:is=\E[1;40r\E[40;1H:tc=pcvtXX:
+pcvt43|dec vt220 emulation with 43 lines:\
+	:co#80:li#43:\
+	:is=\E[1;43r\E[43;1H:tc=pcvtXX:
+pcvt50|dec vt220 emulation with 50 lines:\
+	:co#80:li#50:\
+	:is=\E[1;50r\E[50;1H:tc=pcvtXX:
+
+#	NetBSD/FreeBSD vt220 terminal emulator console (pc keyboard & monitor)
+#	termcap entries for pure VT220-Emulation and 25, 28, 35, 40, 43 and
+#	50 lines entries; 132 columns
+pcvt25w|dec vt220 emulation with 25 lines and 132 cols:\
+	:co#132:li#25:\
+	:is=\E[1;25r\E[25;1H:tc=pcvtXX:
+pcvt28w|dec vt220 emulation with 28 lines and 132 cols:\
+	:co#132:li#28:\
+	:is=\E[1;28r\E[28;1H:tc=pcvtXX:
+pcvt35w|dec vt220 emulation with 35 lines and 132 cols:\
+	:co#132:li#35:\
+	:is=\E[1;35r\E[35;1H:tc=pcvtXX:
+pcvt40w|dec vt220 emulation with 40 lines and 132 cols:\
+	:co#132:li#40:\
+	:is=\E[1;40r\E[40;1H:tc=pcvtXX:
+pcvt43w|dec vt220 emulation with 43 lines and 132 cols:\
+	:co#132:li#43:\
+	:is=\E[1;43r\E[43;1H:tc=pcvtXX:
+pcvt50w|dec vt220 emulation with 50 lines and 132 cols:\
+	:co#132:li#50:\
+	:is=\E[1;50r\E[50;1H:tc=pcvtXX:
+
+# Terminfo entries to enable the use of the ncurses library in colour on a
+# NetBSD-arm32 console (only tested on a RiscPC).
+# Created by Dave Millen <dmill@globalnet.co.uk> 22.07.98
+# modified codes for setf/setb to setaf/setab, then to klone+color, corrected
+# typo in invis - TD
+arm100|arm100-am|Arm(RiscPC) ncurses compatible (for 640x480):\
+	:am:ms:ut:xn:xo:\
+	:co#80:it#8:li#30:\
+	:@8=\E[M:DO=\E[%dB:K1=\E[q:K2=\E[r:K3=\E[s:K4=\E[p:K5=\E[n:\
+	:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:UP=\E[%dA:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=^O:as=^N:bl=^G:cb=\E[1K:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:do=^J:\
+	:eA=\E(B\E)0:ho=\E[H:k0=\E[y:k1=\E[P:k2=\E[Q:k3=\E[R:\
+	:k4=\E[S:k5=\E[t:k6=\E[u:k7=\E[v:k8=\E[l:k9=\E[w:k;=\E[x:\
+	:kb=^H:kd=\E[B:ke=\E[?1l\E>:kl=\E[D:kr=\E[C:ks=\E[?1h\E=:\
+	:ku=\E[A:le=^H:mb=\E[5m:md=\E[1m:me=\E[m\017:mk=\E[8m:\
+	:mr=\E[6m:nd=\E[C:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:\
+	:rc=\E8:\
+	:..sa=\E[0%?%p1%p6%|%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t\016%e\017%;:\
+	:sc=\E7:se=\E[m:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:ue=\E[m:\
+	:up=\E[A:us=\E[4m:\
+	:tc=ecma+sgr:tc=klone+color:
+arm100-w|arm100-wam|Arm(RiscPC) ncurses compatible (for 1024x768):\
+	:co#132:li#50:tc=arm100:
+
+# NetBSD/x68k console vt200 emulator. This port runs on a 68K machine
+# manufactured by Sharp for the Japenese market.
+# From Minoura Makoto <minoura@netlaputa.or.jp>, 12 May 1996
+x68k|x68k-ite|NetBSD/x68k ITE:\
+	:co#96:li#32:\
+	:%1=\E[28~:kC=\E[9~:tc=vt220:
+
+# <tv@pobox.com>:
+# Entry for the DNARD OpenFirmware console, close to ANSI but not quite.
+#
+# (still unfinished, but good enough so far.)
+ofcons:\
+	:bw:\
+	:co#80:li#30:\
+	:AL=\233%dL:DC=\233%dP:DL=\233%dM:DO=\233%dB:IC=\233%d@:\
+	:LE=\233%dD:RI=\233%dC:UP=\233%dA:al=\233L:bl=^G:cd=\233J:\
+	:ce=\233K:cl=^L:cm=\233%i%d;%dH:cr=^M:dc=\233P:dl=\233M:\
+	:do=\233B:ei=:ic=\233@:im=:k1=\2330P:k2=\2330Q:k3=\2330W:\
+	:k4=\2330x:k5=\2330t:k6=\2330u:k7=\2330q:k8=\2330r:\
+	:k9=\2330p:k;=\2330M:kD=\233P:kN=\233/:kP=\233?:kb=^H:\
+	:kd=\233B:kl=\233D:kr=\233C:ku=\233A:le=\233D:mb=\2337;2m:\
+	:md=\2331m:me=\2330m:mh=\2332m:mk=\2338m:mr=\2337m:\
+	:nd=\233C:nw=^M^J:se=\2330m:sf=^J:ta=^I:ue=\2330m:up=\233A:\
+	:vb=^G:
+
+# NetBSD "wscons" emulator in vt220 mode
+# These are micro-minimal and probably need to be redone for real
+# after the manner of the pcvt entries.
+wsvt25|NetBSD wscons in 25 line DEC VT220 mode:\
+	:co#80:li#25:tc=vt220:
+
+wsvt25m|NetBSD wscons in 25 line DEC VT220 mode with Meta:\
+	:km:\
+	:co#80:li#25:tc=vt220:
+
+# `rasterconsole' provided by 4.4BSD, NetBSD and OpenBSD on SPARC, and 
+# DECstation/pmax.
+rcons|BSD rasterconsole:\
+	:tc=sun-il:
+# Color version of above. Color currenly only provided by NetBSD.
+rcons-color|BSD rasterconsole with ANSI color:\
+	:ut:\
+	:Co#8:pa#64:\
+	:AB=\E[4%dm:AF=\E[3%dm:op=\E[m:tc=rcons:
+
+#### FreeBSD console entries
+#
+# From: Andrey Chernov <ache@astral.msk.su> 29 Mar 1996
+# Andrey Chernov maintains the FreeBSD termcap distributions.
+#
+# Note: Users of FreeBSD 2.1.0 and older versions must either upgrade
+# or comment out the :cb: capability in the console entry.
+#
+# Alexander Lukyanov reports:
+# I have seen FreeBSD-2.1.5R... The old el1 bug changed, but it is still there.
+# Now el1 clears not only to the line beginning, but also a large chunk
+# of previous line. But there is another bug - ech does not work at all.
+#
+
+# for syscons
+# common entry without semigraphics
+# Bug: The <op> capability resets attributes.
+# Bug? The ech and el1 attributes appear to move the cursor in some cases; for
+# instance el1 does if the cursor is moved to the right margin first.  Removed
+# by T.Dickey 97/5/3 (ech=\E[%p1%dX, el1=\E[1K)
+#
+# Setting colors turns off reverse; we cannot guarantee order, so use ncv.
+# Note that this disables standout with color.
+cons25w|ansiw|ansi80x25-raw|freebsd console (25-line raw mode):\
+	:NP:am:bw:eo:ms:ut:\
+	:Co#8:NC#21:co#80:it#8:li#25:pa#64:\
+	:@7=\E[F:AB=\E[4%p1%dm:AF=\E[3%p1%dm:AL=\E[%dL:DC=\E[%dP:\
+	:DL=\E[%dM:DO=\E[%dB:F1=\E[W:F2=\E[X:IC=\E[%d@:K2=\E[E:\
+	:LE=\E[%dD:RI=\E[%dC:SF=\E[%dS:SR=\E[%dT:UP=\E[%dA:\
+	:al=\E[L:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:ch=\E[%i%d`:\
+	:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:cv=\E[%i%dd:dc=\E[P:\
+	:dl=\E[M:do=\E[B:ei=:ho=\E[H:ic=\E[@:im=:k1=\E[M:k2=\E[N:\
+	:k3=\E[O:k4=\E[P:k5=\E[Q:k6=\E[R:k7=\E[S:k8=\E[T:k9=\E[U:\
+	:k;=\E[V:kB=\E[Z:kD=\177:kI=\E[L:kN=\E[G:kP=\E[I:kb=^H:\
+	:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mb=\E[5m:\
+	:md=\E[1m:me=\E[m:mh=\E[30;1m:mr=\E[7m:nd=\E[C:nw=\E[E:\
+	:op=\E[x:r1=\E[x\E[m\Ec:se=\E[m:sf=\E[S:so=\E[7m:sr=\E[T:\
+	:ta=^I:up=\E[A:ve=\E[=0C:vs=\E[=1C:
+cons25|ansis|ansi80x25|freebsd console (25-line ansi mode):\
+	:ac=-\030.^Y0\333`\004a\260f\370g\361h\261i\025j\331k\277l\332m\300n\305q\304t\303u\264v\301w\302x\263y\363z\362~\371:\
+	:tc=cons25w:
+cons25-m|ansis-mono|ansi80x25-mono|freebsd console (25-line mono ansi mode):\
+	:Co@:pa@:\
+	:AB@:AF@:md@:mh@:op@:ue=\E[m:us=\E[4m:tc=cons25:
+cons30|ansi80x30|freebsd console (30-line ansi mode):\
+	:li#30:tc=cons25:
+cons30-m|ansi80x30-mono|freebsd console (30-line mono ansi mode):\
+	:li#30:tc=cons25-m:
+cons43|ansi80x43|freebsd console (43-line ansi mode):\
+	:li#43:tc=cons25:
+cons43-m|ansi80x43-mono|freebsd console (43-line mono ansi mode):\
+	:li#43:tc=cons25-m:
+cons50|ansil|ansi80x50|freebsd console (50-line ansi mode):\
+	:li#50:tc=cons25:
+cons50-m|ansil-mono|ansi80x50-mono|freebsd console (50-line mono ansi mode):\
+	:li#50:tc=cons25-m:
+cons60|ansi80x60|freebsd console (60-line ansi mode):\
+	:li#60:tc=cons25:
+cons60-m|ansi80x60-mono|freebsd console (60-line mono ansi mode):\
+	:li#60:tc=cons25-m:
+cons25r|pc3r|ibmpc3r|cons25-koi8-r|freebsd console w/koi8-r cyrillic:\
+	:ac=-\030.^Y0\215`\004a\220f\234h\221i\025j\205k\203l\202m\204n\212q\0t\206u\207v\211w\210x\201y\230z\231~\225:\
+	:tc=cons25w:
+cons25r-m|pc3r-m|ibmpc3r-mono|cons25-koi8r-m|freebsd console w/koi8-r cyrillic (mono):\
+	:Co@:pa@:\
+	:AB@:AF@:op@:ue=\E[m:us=\E[4m:tc=cons25r:
+cons50r|cons50-koi8r|freebsd console w/koi8-r cyrillic (50 lines):\
+	:li#50:tc=cons25r:
+cons50r-m|cons50-koi8r-m|freebsd console w/koi8-r cyrillic (50-line mono):\
+	:li#50:tc=cons25r-m:
+cons60r|cons60-koi8r|freebsd console w/koi8-r cyrillic (60 lines):\
+	:li#60:tc=cons25r:
+cons60r-m|cons60-koi8r-m|freebsd console w/koi8-r cyrillic (60-line mono):\
+	:li#60:tc=cons25r-m:
+# ISO 8859-1 FreeBSD console
+cons25l1|cons25-iso8859|freebsd console w/iso 8859-1 chars:\
+	:ac=+\253\054\273-\030.\031`\201a\202f\207g\210i\247j\213k\214l\215m\216n\217o\220p\221q\222r\223s\224t\225u\226v\227w\230x\231y\232z\233~\237:\
+	:tc=cons25w:
+cons25l1-m|cons25-iso-m|freebsd console w/iso 8859-1 chars (mono):\
+	:Co@:pa@:\
+	:AB@:AF@:md@:mh@:op@:ue=\E[m:us=\E[4m:tc=cons25l1:
+cons50l1|cons50-iso8859|freebsd console w/iso 8859-1 chars (50 lines):\
+	:li#50:tc=cons25l1:
+cons50l1-m|cons50-iso-m|freebsd console w/iso 8859-1 chars (50-line mono):\
+	:li#50:tc=cons25l1-m:
+cons60l1|cons60-iso|freebsd console w/iso 8859-1 chars (60 lines):\
+	:li#60:tc=cons25l1:
+cons60l1-m|cons60-iso-m|freebsd console w/iso 8859-1 chars (60-line mono):\
+	:li#60:tc=cons25l1-m:
+
+#### 386BSD and BSD/OS Consoles
+#
+
+# This was the original 386BSD console entry (I think).  
+# Some places it's named oldpc3|oldibmpc3.
+# From: Alex R.N. Wetmore <aw2t@andrew.cmu.edu>
+origpc3|origibmpc3|IBM PC 386BSD Console:\
+	:am:bw:eo:xo:\
+	:co#80:li#25:\
+	:ac=j\331k\277l\332m\300n\305q\304t\303u\264v\301w\302x\263:\
+	:cd=\E[J:ce=\E[K:cl=\Ec:cm=\E[%i%2;%2H:do=\E[B:ho=\E[H:\
+	:kd=\E[B:kh=\E[Y:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:md=\E[7m:\
+	:me=\E[m\E[1;0x\E[2;7x:nd=\E[C:se=\E[1;0x\E[2;7x:\
+	:sf=\E[S:so=\E[1;7x\E[2;0x:sr=\E[T:ue=\E[1;0x\E[2;7x:\
+	:up=\E[A:us=\E[1;7x\E[2;0x:
+
+# description of BSD/386 console emulator in version 1.0 (supplied by BSDI)
+oldpc3|oldibmpc3|old IBM PC BSD/386 Console:\
+	:km:\
+	:li#25:\
+	:al=\E[L:bl=^G:cr=^M:dl=\E[M:do=^J:kH=\E[F:kI=\E[L:kN=\E[G:\
+	:kP=\E[I:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:md=\E[=15F:me=\E[=R:mh=\E[=8F:nw=^M^J:sf=^J:ta=^I:
+
+# Description of BSD/OS console emulator in version 1.1, 2.0, 2.1
+# Note, the emulator supports many of the additional console features
+# listed in the iBCS2 (e.g. character-set selection) though not all
+# are described here.  This entry really ought to be upgraded.
+# Also note, the console will also work with fewer lines after doing
+# "stty rows NN", e.g. to use 24 lines.
+# (Color support from Kevin Rosenberg <kevin@cyberport.com>, 2 May 1996) 
+# Bug: The <op> capability resets attributes.
+bsdos-pc-nobold|BSD/OS PC console w/o bold:\
+	:am:eo:km:xo:\
+	:co#80:it#8:li#25:\
+	:AL=\E[%dL:DL=\E[%dM:DO=\E[%dB:LE=\E[%dD:RI=\E[%dC:\
+	:UP=\E[%dA:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:cl=\Ec:\
+	:cm=\E[%i%d;%dH:cr=^M:dl=\E[M:do=^J:ho=\E[H:kH=\E[F:\
+	:kI=\E[L:kN=\E[G:kP=\E[I:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:\
+	:kr=\E[C:ku=\E[A:le=^H:nd=\E[C:nw=^M^J:rc=\E8:\
+	:..sa=\E[0;10%?%p1%t;7%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m%?%p5%t\E[=8F%;:\
+	:sc=\E7:sf=^J:ta=^I:up=\E[A:\
+	:tc=klone+sgr:tc=klone+color:
+bsdos-pc|IBM PC BSD/OS Console:\
+	:..sa=\E[0;10%?%p1%t;7%;%?%p2%t;1%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m:tc=bsdos-pc-nobold:
+
+# Old names for BSD/OS PC console used in releases before 4.1. 
+pc3|BSD/OS on the PC Console:\
+	:tc=bsdos-pc-nobold:
+ibmpc3|pc3-bold|BSD/OS on the PC Console with bold instead of underline:\
+	:tc=bsdos-pc:
+ 
+# BSD/OS on the SPARC 
+bsdos-sparc|Sun SPARC BSD/OS Console:\
+	:tc=sun:
+	 
+# BSD/OS on the PowerPC 
+bsdos-ppc|PowerPC BSD/OS Console:\
+	:tc=bsdos-pc:
+
+#### DEC VT100 and compatibles
+#
+# DEC terminals from the vt100 forward are collected here. Older DEC terminals
+# and micro consoles can be found in the `obsolete' section.  More details on
+# the relationship between the VT100 and ANSI X3.64/ISO 6429/ECMA-48 may be
+# found near the end of this file.
+#
+# Except where noted, these entries are DEC's official terminfos.
+# Contact Bill Hedberg <hedberg@hannah.enet.dec.com> of Terminal Support
+# Engineering for more information.  Updated terminfos and termcaps 
+# are kept available at ftp://gatekeeper.dec.com/pub/DEC/termcaps.
+#
+# In October 1995 DEC sold its terminals business, including the VT and Dorio
+# line and trademark, to SunRiver Data Systems.  SunRiver has since changed
+# its name to Boundless Technologies; see http://www.boundless.com.
+#
+
+# NOTE:  Any VT100 emulation, whether in hardware or software, almost
+# certainly includes what DEC called the `Level 1 editing extension' codes;
+# only the very oldest VT100s lacked these and there probably aren't any of
+# those left alive.  To capture these, use one of the VT102 entries.
+#
+# Note that the :xn: glitch in vt100 is not quite the same as on the Concept,
+# since the cursor is left in a different position while in the
+# weird state (concept at beginning of next line, vt100 at end
+# of this line) so all versions of vi before 3.7 don't handle
+# :xn: right on vt100. The correct way to handle :xn: is when
+# you output the char in column 80, immediately output CR LF
+# and then assume you are in column 1 of the next line. If :xn:
+# is on, am should be on too.
+# 
+# I assume you have smooth scroll off or are at a slow enough baud
+# rate that it doesn't matter (1200? or less). Also this assumes
+# that you set auto-nl to "on", if you set it off use vt100-nam 
+# below.
+# 
+# The padding requirements listed here are guesses. It is strongly
+# recommended that xon/xoff be enabled, as this is assumed here.
+# 
+# The vt100 uses <rs2> and <rf> rather than :is:/:ct:/:st: because the 
+# tab settings are in non-volatile memory and don't need to be 
+# reset upon login. Also setting the number of columns glitches 
+# the screen annoyingly. You can type "reset" to get them set.
+#
+# The VT100 series terminals have cursor ("arrows") keys which can operate
+# in two different modes: Cursor Mode and Application Mode.  Cursor Mode
+# is the reset state, and is assumed to be the normal state.  Application
+# Mode is the "set" state.  In Cursor Mode, the cursor keys transmit
+# "Esc [ {code}" sequences, conforming to ANSI standards.  In Application
+# Mode, the cursor keys transmit "Esc O <code>" sequences.  Application Mode
+# was provided primarily as an aid to the porting of VT52 applications.  It is
+# assumed that the cursor keys are normally in Cursor Mode, and expected that
+# applications such as vi will always transmit the :ks: string.  Therefore,
+# the definitions for the cursor keys are made to match what the terminal
+# transmits after the :ks: string is transmitted.  If the :ks: string
+# is a null string or is not defined, then cursor keys are assumed to be in
+# "Cursor Mode", and the cursor keys definitions should match that assumption,
+# else the appication may fail.  It is also expected that applications will
+# always transmit the :ke: string to the terminal before they exit.
+#
+# The VT100 series terminals have an auxilliary keypad, commonly referred to as
+# the "Numeric Keypad", because it is a cluster of numeric and function keys.
+# The Numeric Keypad which can operate in two different modes: Numeric Mode and
+# Application Mode.  Numeric Mode is the reset state, and is assumed to be
+# the normal state.  Application Mode is the "set" state.  In Numeric Mode,
+# the numeric and punctuation keys transmit ASCII 7-bit characters, and the 
+# Enter key transmits the same as the Return key (Note: the Return key
+# can be configured to send either LF (\015) or CR LF).  In Application Mode,
+# all the keypad keys transmit "Esc O {code}" sequences.  The PF1 - PF4 keys
+# always send the same "Esc O {code}" sequences.  It is assumed that the keypad
+# is normally in Numeric Mode.  If an application requires that the keypad be
+# in Application Mode then it is expected that the user, or the application,
+# will set the TERM environment variable to point to a terminfo entry which has
+# defined the :ks: string to include the codes that switch the keypad into
+# Application Mode, and the terminfo entry will also define function key
+# fields to match the Application Mode control codes.  If the :ks: string
+# is a null string or is not defined, then the keypad is assumed to be in
+# Numeric Mode.  If the :ks: string switches the keypad into Application
+# Mode, it is expected that the :ke: string will contain the control codes
+# necessary to reset the keypad to "Normal" mode, and it is also expected that
+# applications which transmit the :ks: string will also always transmit the
+# :ke: string to the terminal before they exit.
+#
+# Here's a diagram of the VT100 keypad keys with their bindings.
+# The top line is the name of the key (some DEC keyboards have the keys
+# labelled somewhat differently, like GOLD instead of PF1, but this is
+# the most "official" name).  The second line is the escape sequence it
+# generates in Application Keypad mode (where "$" means the ESC
+# character).  The third line contains two items, first the mapping of
+# the key in terminfo, and then in termcap.
+#   _______________________________________
+#  |   PF1   |   PF2   |   PF3   |   PF4   |
+#  |   $OP   |   $OQ   |   $OR   |   $OS   |
+#  |_kf1__k1_|_kf2__k2_|_kf3__k3_|_kf4__k4_|
+#  |    7         8         9         -    |
+#  |   $Ow   |   $Ox   |   $Oy   |   $Om   |
+#  |_kf9__k9_|_kf10_k;_|_kf0__k0_|_________|
+#  |    4    |    5    |    6    |    ,    |
+#  |   $Ot   |   $Ou   |   $Ov   |   $Ol   |
+#  |_kf5__k5_|_kf6__k6_|_kf7__k7_|_kf8__k8_|
+#  |    1    |    2    |    3    |         |
+#  |   $Oq   |   $Or   |   $Os   |  enter  |
+#  |_ka1__K1_|_kb2__K2_|_ka3__K3_|  $OM    |
+#  |         0         |   .     |         |
+#  |        $Op        |  $On    |         |
+#  |___kc1_______K4____|_kc3__K5_|_kent_@8_|
+#
+# And here, for those of you with orphaned VT100s lacking documentation, is
+# a description of the soft switches invoked when you do `Set Up'.
+# 
+#  Scroll 0-Jump               Shifted 3   0-#
+#  |      1-Smooth             |           1-British pound sign
+#  | Autorepeat 0-Off          | Wrap Around 0-Off
+#  | |          1-On           | |           1-On
+#  | | Screen 0-Dark Bkg       | | New Line 0-Off
+#  | | |      1-Light Bkg      | | |        1-On
+#  | | | Cursor 0-Underline    | | | Interlace 0-Off
+#  | | | |      1-Block        | | | |         1-On
+#  | | | |                     | | | |
+#  1 1 0 1       1 1 1 1       0 1 0 0       0 0 1 0       <--Standard Settings
+#                | | | |                     | | | |
+#                | | | Auto XON/XOFF 0-Off   | | | Power 0-60 Hz
+#                | | |               1-On    | | |       1-50 Hz
+#                | | Ansi/VT52 0-VT52        | | Bits Per Char. 0-7 Bits
+#                | |           1-ANSI        | |                1-8 Bits
+#                | Keyclick 0-Off            | Parity 0-Off
+#                |          1-On             |        1-On
+#                Margin Bell 0-Off           Parity Sense 0-Odd
+#                            1-On                         1-Even
+#
+# The following SET-UP modes are assumed for normal operation:
+#	ANSI_MODE	AUTO_XON/XOFF_ON	NEWLINE_OFF	80_COLUMNS
+#	WRAP_AROUND_ON  JUMP_SCROLL_OFF
+# Other SET-UP modes may be set for operator convenience or communication
+# requirements; I recommend
+#	AUTOREPEAT_ON	BLOCK_CURSOR	MARGIN_BELL_OFF    SHIFTED_3_#
+# Unless you have a graphics add-on such as Digital Engineering's VT640
+# (and even then, whenever it can be arranged!) you should set
+#	INTERLACE_OFF
+#
+# (vt100: I added <rmam>/<smam> based on the init string, also :bs:. -- esr)
+vt100|vt100-am|dec vt100 (w/advanced video):\
+	:am:bs:ms:xn:xo:\
+	:co#80:it#8:li#24:vt#3:\
+	:@8=\EOM:DO=\E[%dB:K1=\EOq:K2=\EOr:K3=\EOs:K4=\EOp:K5=\EOn:\
+	:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:UP=\E[%dA:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=^O:as=^N:bl=^G:cb=\E[1K:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:do=^J:\
+	:eA=\E(B\E)0:ho=\E[H:k0=\EOy:k1=\EOP:k2=\EOQ:k3=\EOR:\
+	:k4=\EOS:k5=\EOt:k6=\EOu:k7=\EOv:k8=\EOl:k9=\EOw:k;=\EOx:\
+	:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:\
+	:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:me=\E[m\017:mr=\E[7m:\
+	:nd=\E[C:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\E8:\
+	:..sa=\E[0%?%p1%p6%|%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t\016%e\017%;:\
+	:sc=\E7:se=\E[m:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:ue=\E[m:\
+	:up=\E[A:us=\E[4m:
+vt100nam|vt100-nam|vt100 no automargins:\
+	:am@:xn@:tc=vt100-am:
+vt100-vb|dec vt100 (w/advanced video) & no beep:\
+	:bl@:vb=\E[?5h\E[?5l:tc=vt100:
+
+# Ordinary vt100 in 132 column ("wide") mode.
+vt100-w|vt100-w-am|dec vt100 132 cols (w/advanced video):\
+	:co#132:li#24:\
+	:r2=\E>\E[?3h\E[?4l\E[?5l\E[?8h:tc=vt100-am:
+vt100-w-nam|vt100-nam-w|dec vt100 132 cols (w/advanced video no automargin):\
+	:co#132:li#14:vt@:\
+	:r2=\E>\E[?3h\E[?4l\E[?5l\E[?8h:tc=vt100-nam:
+
+# vt100 with no advanced video.
+vt100-nav|vt100 without advanced video option:\
+	:sg#1:\
+	:mb@:md@:me@:mr@:sa@:se=\E[m:so=\E[7m:ue@:us@:tc=vt100:
+vt100-nav-w|vt100-w-nav|dec vt100 132 cols 14 lines (no advanced video option):\
+	:co#132:li#14:tc=vt100-nav:
+
+# vt100 with one of the 24 lines used as a status line.
+# We put the status line on the top.
+vt100-s|vt100-s-top|vt100-top-s|vt100 for use with top sysline:\
+	:es:hs:\
+	:li#23:\
+	:cl=\E[2;1H\E[J:cm=\E[%i%+^A;%dH:cs=\E[%i%i%d;%dr:\
+	:ds=\E7\E[1;24r\E8:fs=\E8:ho=\E[2;1H:is=\E7\E[2;24r\E8:\
+	:ts=\E7\E[1;%p1%dH\E[1K:\
+	:tc=vt100-am:
+
+# Status line at bottom. 
+# Clearing the screen will clobber status line.
+vt100-s-bot|vt100-bot-s|vt100 for use with bottom sysline:\
+	:es:hs:\
+	:li#23:\
+	:ds=\E7\E[1;24r\E8:fs=\E8:is=\E[1;23r\E[23;1H:\
+	:ts=\E7\E[24;%p1%dH\E[1K:\
+	:tc=vt100-am:
+
+# Most of the `vt100' emulators out there actually emulate a vt102
+# This entry (or vt102-nsgr) is probably the right thing to use for
+# these.  
+vt102|dec vt102:\
+	:mi:\
+	:al=\E[L:dc=\E[P:dl=\E[M:ei=\E[4l:im=\E[4h:tc=vt100:
+vt102-w|dec vt102 in wide mode:\
+	:co#132:\
+	:r3=\E[?3h:tc=vt102:
+
+# Many brain-dead PC comm programs that pretend to be `vt100-compatible'
+# fail to interpret the ^O and ^N escapes properly.  Symptom: the :me:
+# string in the canonical vt100 entry above leaves the screen littered
+# with little  snowflake or star characters (IBM PC ROM character \017 = ^O)
+# after highlight turnoffs.  This entry should fix that, and even leave
+# ACS support working, at the cost of making multiple-highlight changes 
+# slightly more expensive.
+# From: Eric S. Raymond <esr@snark.thyrsus.com> July 22 1995
+vt102-nsgr|vt102 no sgr (use if you see snowflakes after highlight changes):\
+	:me=\E[m:sa@:\
+	:tc=vt102:
+
+# VT125 Graphics CRT.  Clear screen also erases graphics
+vt125|vt125 graphics terminal:\
+	:cl=\E[H\E[2J\EPpS(E)\E\:tc=vt100:
+
+# This isn't a DEC entry, it came from University of Wisconsin.
+# (vt131: I added <rmam>/<smam> based on the init string, also :bs: -- esr)
+vt131|dec vt131:\
+	:am:bs:xn:\
+	:co#80:it#8:li#24:vt#3:\
+	:RA=\E[?7h:SA=\E[?7h:bl=^G:cd=50\E[J:ce=3\E[K:\
+	:cl=50\E[;H\E[2J:cm=5\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:do=^J:ho=\E[H:is=\E[1;24r\E[24;1H:k1=\EOP:k2=\EOQ:\
+	:k3=\EOR:k4=\EOS:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:\
+	:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:mb=2\E[5m:md=2\E[1m:\
+	:me=2\E[m:mr=2\E[7m:nd=2\E[C:nw=^M^J:\
+	:r1=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\E8:sc=\E7:\
+	:se=2\E[m:so=2\E[7m:sr=5\EM:ta=^I:ue=2\E[m:up=2\E[A:\
+	:us=2\E[4m:
+
+# vt132 - like vt100 but slower and has ins/del line and such.
+# I'm told that :im:/:ei: are backwards in the terminal from the
+# manual and from the ANSI standard, this describes the actual 
+# terminal. I've never actually used a vt132 myself, so this 
+# is untested.
+#
+vt132|DEC vt132:\
+	:xn:\
+	:al=\E[L:dc=\E[P:dl=\E[M:ei=\E[4h:im=\E[4l:ip=:sf=\n:tc=vt100:
+
+# This vt220 description maps F5--F9 to the second block of function keys
+# at the top of the keyboard.  The "DO" key is used as F10 to avoid conflict
+# with the key marked (ESC) on the vt220.  See vt220d for an alternate mapping.
+# PF1--PF4 are used as F1--F4.
+#
+vt220-old|vt200-old|DEC VT220 in vt100 emulation mode:\
+	:am:bs:mi:pt:xn:xo:\
+	:co#80:li#24:vt#3:\
+	:@7=\E[4~:RA=\E[?7l:SA=\E[?7h:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=\E(B:al=\E[L:as=\E(0:bl=^G:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:dc=\E[P:dl=\E[M:do=\E[B:ei=\E[4l:ho=\E[H:\
+	:if=/usr/share/tabset/vt100:im=\E[4h:\
+	:is=\E[1;24r\E[24;1H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+	:k5=\E[17~:k6=\E[18~:k7=\E[19~:k8=\E[20~:k9=\E[21~:\
+	:k;=\E[29~:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:kb=^H:\
+	:kd=\E[B:kh=\E[1~:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mb=\E[5m:\
+	:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:nl=^J:\
+	:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\E8:\
+	:rf=/usr/share/tabset/vt100:\
+	:..sa=\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p4%t;5%;%?%p1%p3%|%t;7%;m%?%p9%t\E(0%e\E(B%;:\
+	:sc=\E7:se=\E[27m:sf=20\ED:so=\E[7m:sr=14\EM:ta=^I:\
+	:ue=\E[24m:up=\E[A:us=\E[4m:ve=\E[?25h:vi=\E[?25l:
+
+# A much better description of the VT200/220; used to be vt220-8
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+vt220|vt200|dec vt220:\
+	:am:bs:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:vt#3:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:ec=\E[%dX:\
+	:ei=\E[4l:ho=\E[H:if=/usr/share/tabset/vt100:im=\E[4h:\
+	:is=\E[?7h\E[>\E[?1h\E F\E[?4l:k1=\EOP:k2=\EOQ:k3=\EOR:\
+	:k4=\EOS:k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:kI=\E[2~:\
+	:kN=\E[6~:kP=\E[5~:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:\
+	:ku=\E[A:le=^H:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:\
+	:nw=\EE:rc=\E8:sc=\E7:se=\E[27m:sf=\ED:so=\E[7m:sr=\EM:\
+	:st=\EH:ta=^I:ue=\E[24m:up=\E[A:us=\E[4m:vb=\E[?5h\E[?5l:
+vt220-w|vt200-w|DEC vt220 in wide mode:\
+	:co#132:\
+	:r3=\E[?3h:tc=vt220:
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+vt220-8bit|vt220-8|vt200-8bit|vt200-8|dec vt220/200 in 8-bit mode:\
+	:am:bs:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:vt#3:\
+	:AL=\233%dL:DC=\233%dP:DL=\233%dM:DO=\233%dB:IC=\233%d@:\
+	:LE=\233%dD:RI=\233%dC:UP=\233%dA:ae=^O:al=\233L:as=^N:\
+	:bl=^G:cd=\233J:ce=\233K:cl=\233H\233J:cm=\233%i%d;%dH:\
+	:cr=^M:cs=\233%i%d;%dr:ct=\2333g:dc=\233P:dl=\233M:do=^J:\
+	:ec=\233%dX:ei=\2334l:ho=\233H:\
+	:if=/usr/share/tabset/vt100:im=\2334h:\
+	:is=\233?7h\233>\233?1h\E F\233?4l:k1=\EOP:k2=\EOQ:\
+	:k3=\EOR:k4=\EOS:k6=\23317~:k7=\23318~:k8=\23319~:\
+	:k9=\23320~:kI=\2332~:kN=\2336~:kP=\2335~:kb=^H:kd=\233B:\
+	:kh=\233H:kl=\233D:kr=\233C:ku=\233A:le=^H:mb=\2335m:\
+	:md=\2331m:me=\233m:mr=\2337m:nd=\233C:nw=\EE:rc=\E8:\
+	:sc=\E7:se=\23327m:sf=\ED:so=\2337m:sr=\EM:st=\EH:ta=^I:\
+	:ue=\23324m:up=\233A:us=\2334m:vb=\233?5h\233?5l:
+
+#
+# vt220d:
+# This vt220 description regards F6--F10 as the second block of function keys
+# at the top of the keyboard.  This mapping follows the description given
+# in the VT220 Programmer Reference Manual and agrees with the labeling
+# on some terminals that emulate the vt220.  There is no support for an F5.
+# See vt220 for an alternate mapping. 
+#
+vt220d|DEC VT220 in vt100 mode with DEC function key labeling:\
+	:F1=\E[23~:F2=\E[24~:F3=\E[25~:F4=\E[26~:F5=\E[28~:\
+	:F6=\E[29~:F7=\E[31~:F8=\E[32~:F9=\E[33~:FA=\E[34~:k5@:\
+	:k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:k;=\E[21~:\
+	:tc=vt220-old:
+
+vt220-nam|v200-nam|VT220 in vt100 mode with no auto margins:\
+	:am@:\
+	:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7l\E[?8h:tc=vt220:
+
+# vt220 termcap written Tue Oct 25 20:41:10 1988 by Alex Latzko
+# (not an official DEC entry!)
+# The problem with real vt220 terminals is they don't send escapes when in
+# in vt220 mode.  This can be gotten around two ways.  1> don't send
+# escapes or 2> put the vt220 into vt100 mode and use all the nifty
+# features of vt100 advanced video which it then has.
+#
+# This entry takes the view of putting a vt220 into vt100 mode so
+# you can use the escape key in emacs and everything else which needs it.
+#
+# You probably don't want to use this on a VMS machine since VMS will think
+# it has a vt220 and will get fouled up coming out of emacs
+#
+# From: Alexander Latzko <latzko@marsenius.rutgers.edu>, 30 Dec 1996
+# (Added vt100 :rc:,:sc: to quiet a tic warning -- esr)
+vt200-js|vt220-js|dec vt200 series with jump scroll:\
+	:am:\
+	:co#80:\
+	:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:\
+	:cr=^M:cs=\E[%i%d;%dr:dc=\E[P:dl=\E[M:dm=:do=^J:ed=:\
+	:ei=\E[4l:ho=\E[H:im=\E[4h:\
+	:is=\E[61"p\E[H\E[?3l\E[?4l\E[?1l\E[?5l\E[?6l\E[?7h\E[?8h\E[?25h\E>\E[m:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:kb=^H:kd=\EOB:\
+	:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:\
+	:nw=^M\ED:r1=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\E8:\
+	:rf=/usr/lib/tabset/vt100:sc=\E7:se=5\E[27m:sf=\ED:\
+	:so=5\E[7m:sr=\EM:ta=^I:ue=\E[24m:up=\E[A:us=\E[4m:
+ 
+
+# This was DEC's vt320.  Use the purpose-built one below instead 
+#vt320|DEC VT320 in vt100 emulation mode,
+#	use=vt220,
+
+#
+# Use v320n for SCO's LYRIX.  Otherwise, use Adam Thompson's vt320-nam.
+#
+vt320nam|v320n|DEC VT320 in vt100 emul. mode with NO AUTO WRAP mode:\
+	:am@:\
+	:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7l\E[?8h:tc=vt220:
+
+# These entries are not DEC's official ones, they were purpose-built for the 
+# VT320.  Here are the designer's notes:
+# <kel> is end on a PC kbd.  Actually 'select' on a VT.  Mapped to 
+# 'Erase to End of Field'... since nothing seems to use 'end' anyways...
+# khome is Home on a PC kbd.  Actually 'FIND' on a VT.
+# Things that use <knxt> usually use tab anyways... and things that don't use
+# tab usually use <knxt> instead...
+# kprv is same as tab - Backtab is useless...
+# I left out :sa: because of its RIDICULOUS complexity,
+# and the resulting fact that it causes the termcap translation of the entry
+# to SMASH the 1k-barrier...
+# From: Adam Thompson <athompso@pangea.ca> Sept 10 1995
+# (vt320: uncommented :fs:, comnmmented out <kslt> to avoid a conflict --esr) 
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+vt320|vt300|dec vt320 7 bit terminal:\
+	:am:es:hs:mi:ms:xn:\
+	:co#80:li#24:ws#80:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:K1=\EOw:K2=\EOu:K3=\EOy:K4=\EOq:K5=\EOs:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=\E(B:al=\E[L:as=\E(0:bl=^G:cd=\E[J:\
+	:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:ec=\E[%dX:\
+	:ei=\E[4l:fs=\E[0$}:ho=\E[H:im=\E[4h:\
+	:is=\E>\E[?3l\E[?4l\E[5?l\E[?7h\E[?8h\E[1;24r\E[24;1H:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k6=\E[17~:k7=\E[18~:\
+	:k8=\E[19~:k9=\E[20~:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:\
+	:kb=\177:kd=\EOB:ke=\E[?1l\E>:kh=\E[1~:kl=\EOD:kr=\EOC:\
+	:ks=\E[?1h\E=:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:me=\E[m:\
+	:mr=\E[7m:nd=\E[C:nw=\EE:rc=\E8:sc=\E7:se=\E[m:sf=\ED:\
+	:so=\E[7m:sr=\EM:st=\EH:ta=^I:ts=\E[1$}\E[H\E[K:ue=\E[m:\
+	:up=\E[A:us=\E[4m:ve=\E[?25h:vi=\E[?25l:
+vt320-nam|vt300-nam|dec vt320 7 bit terminal with no am to make SAS happy:\
+	:am@:\
+	:is=\E>\E[?3l\E[?4l\E[5?l\E[?7l\E[?8h\E[1;24r\E[24;1H:\
+	:r2=\E>\E[?3l\E[?4l\E[5?l\E[?7l\E[?8h\E[1;24r\E[24;1H:\
+	:tc=vt320:
+# We have to init 132-col mode, not 80-col mode.
+vt320-w|vt300-w|dec vt320 wide 7 bit terminal:\
+	:co#132:ws#132:\
+	:is=\E>\E[?3h\E[?4l\E[5?l\E[?7h\E[?8h\E[1;24r\E[24;1H:\
+	:r2=\E>\E[?3h\E[?4l\E[5?l\E[?7h\E[?8h\E[1;24r\E[24;1H:\
+	:tc=vt320:
+vt320-w-nam|vt300-w-nam|dec vt320 wide 7 bit terminal with no am:\
+	:am@:\
+	:is=\E>\E[?3h\E[?4l\E[5?l\E[?7l\E[?8h\E[1;24r\E[24;1H:\
+	:r2=\E>\E[?3h\E[?4l\E[5?l\E[?7l\E[?8h\E[1;24r\E[24;1H:\
+	:tc=vt320-w:
+
+# VT330 and VT340 -- These are ReGIS and SIXEL graphics terminals
+#   which are pretty much a superset of the VT320.  They have the
+#   host writable status line, yet another different DRCS matrix size,
+#   and such, but they add the DEC Technical character set, Multiple text
+#   pages, selectable length pages, and the like.  The difference between
+#   the vt330 and vt340 is that the latter has only 2 planes and a monochrome
+#   monitor, the former has 4 planes and a color monitor.  These terminals
+#   support VT131 and ANSI block mode, but as with much of these things,
+#   termcap/terminfo doesn't deal with these features.
+#
+# Note that this entry is are set up in what was the standard way for GNU
+# Emacs v18 terminal modes to deal with the cursor keys in that the arrow
+# keys were switched into application mode at the same time the numeric pad
+# is switched into application mode.  This changes the definitions of the
+# arrow keys.  Emacs v19 is smarter and mines its keys directly out of 
+# your termcap or terminfo entry,
+#
+# From: Daniel Glasser <dag@persoft.persoft.com>, 13 Oct 1993
+# (vt340: string capability "sb=\E[M" corrected to "sr";
+# also, added <rmam>/<smam> based on the init string -- esr)
+vt340|dec-vt340|vt330|dec-vt330|dec vt340 graphics terminal with 24 line page:\
+	:am:es:hs:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:vt#3:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:UP=\E[%dA:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=^O:al=\E[L:as=^N:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:\
+	:dl=\E[M:do=^J:ds=\E[2$~\r\E[1$}\E[K\E[$}:ei=\E[4l:\
+	:fs=\E[$}:ho=\E[H:im=\E[4h:\
+	:is=\E<\E F\E>\E[?1h\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[1;24r\E[24;1H:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k6=\E[17~:k7=\E[18~:\
+	:k8=\E[19~:k9=\E[20~:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:\
+	:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:l1=pf1:l2=pf2:l3=pf3:l4=pf4:\
+	:le=^H:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:nw=^M\ED:\
+	:r1=\E[?3l:rc=\E8:rf=/usr/share/tabset/vt300:sc=\E7:\
+	:se=\E[27m:sf=\ED:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:ts=\E[2$~\E[1$}\E[1;%dH:ue=\E[24m:up=\E[A:us=\E[4m:\
+	:vb=200\E[?5h\E[?5l:ve=\E[?25h:vi=\E[?25l:vs=\E[?25h:
+
+# DEC doesn't supply a vt400 description, so we add Daniel Glasser's
+# (originally written with vt420 as its primary name, and usable for it).
+# 
+# VT400/420 -- This terminal is a superset of the vt320.  It adds the multiple 
+#    text pages and long text pages with selectable length of the vt340, along
+#    with left and right margins, rectangular area text copy, fill, and erase
+#    operations, selected region character attribute change operations,
+#    page memory and rectangle checksums, insert/delete column, reception
+#    macros, and other features too numerous to remember right now.  TERMCAP
+#    can only take advantage of a few of these added features.
+#
+# Note that this entry is are set up in what was the standard way for GNU
+# Emacs v18 terminal modes to deal with the cursor keys in that the arrow
+# keys were switched into application mode at the same time the numeric pad
+# is switched into application mode.  This changes the definitions of the
+# arrow keys.  Emacs v19 is smarter and mines its keys directly out of 
+# your termcap entry,
+#
+# From: Daniel Glasser <dag@persoft.persoft.com>, 13 Oct 1993
+# (vt400: string capability ":sb=\E[M:" corrected to ":sr=\E[M:";
+# also, added <rmam>/<smam> based on the init string -- esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+vt400|vt400-24|dec-vt400|dec vt400 24x80 column autowrap:\
+	:am:es:hs:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:vt#3:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:\
+	:cd=10\E[J:ce=4\E[K:cl=10\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:\
+	:ds=\E[2$~\r\E[1$}\E[K\E[$}:ei=\E[4l:fs=\E[$}:ho=\E[H:\
+	:ic=\E[@:im=\E[4h:\
+	:is=\E<\E F\E>\E[?1h\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[1;24r\E[24;1H:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k6=\E[17~:k7=\E[18~:\
+	:k8=\E[19~:k9=\E[20~:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:\
+	:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:\
+	:me=\E[m:mr=\E[7m:nd=\E[C:nw=^M\ED:rc=\E8:sc=\E7:se=\E[27m:\
+	:sf=\ED:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:ts=\E[2$~\E[1$}\E[1;%dH:ue=\E[24m:up=\E[A:us=\E[4m:\
+	:vb=200\E[?5h\E[?5l:ve=\E[?25h:vi=\E[?25l:vs=\E[?25h:
+
+# (vt420: I removed :k0:, it collided with <kf10>.  I also restored
+# a missing :sc: -- esr)
+vt420|DEC VT420:\
+	:am:mi:xn:xo:\
+	:co#80:li#24:vt#3:\
+	:*6=\E[4~:@0=\E[1~:RA=\E[?7l:\
+	:S5=\E[?0;0r\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:\
+	:SA=\E[?7h:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=\E(B:al=\E[L:as=\E(0:bl=^G:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:dc=\E[P:dl=\E[M:do=\E[B:ei=\E[4l:ho=\E[H:\
+	:i2=\E[?67h\E[64;1"p:if=/usr/share/tabset/vt300:\
+	:im=\E[4h:is=\E[1;24r\E[24;1H:k1=\EOP:k2=\EOQ:k3=\EOR:\
+	:k4=\EOS:k5=\E[17~:k6=\E[18~:k7=\E[19~:k8=\E[20~:\
+	:k9=\E[21~:k;=\E[29~:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:\
+	:kb=^H:kd=\E[B:ke=\E>:kl=\E[D:kr=\E[C:ks=\E=:ku=\E[A:le=^H:\
+	:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:\
+	:r3=\E[?67h\E[64;1"p:rc=\E8:rf=/usr/share/tabset/vt300:\
+	:..sa=\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p4%t;5%;%?%p1%p3%|%t;7%;m%?%p9%t\E(0%e\E(B%;:\
+	:sc=\E7:se=\E[m:sf=\ED:so=\E[7m:sr=\EM:ta=^I:ue=\E[m:\
+	:up=\E[A:us=\E[4m:
+
+#
+# DEC VT220 and up support DECUDK (user-defined keys).  DECUDK (i.e., pfx)
+# takes two parameters, the key and the string.  Translating the key is
+# straightforward (keys 1-5 are not defined on real terminals, though some
+# emulators define these):
+#
+#               if (key < 16) then  value = key;
+#               else if (key < 21) then value = key + 1; 
+#               else if (key < 25) then value = key + 2;
+#               else if (key < 27) then value = key + 3;
+#               else if (key < 30) then value = key + 4;
+#               else value = key + 5;
+#
+# The string must be the hexadecimal equivalent, e.g., "5052494E" for "PRINT". 
+# There's no provision in terminfo for emitting a string in this format, so the
+# application has to know it.
+#
+vt420pc|DEC VT420 w/PC keyboard:\
+	:@7=\E[4~:F1=\E[23~:F2=\E[24~:F3=\E[11;2~:F4=\E[12;2~:\
+	:F5=\E[13;2~:F6=\E[14;2~:F7=\E[15;2~:F8=\E[17;2~:\
+	:F9=\E[18;2~:FA=\E[19;2~:FB=\E[20;2~:FC=\E[21;2~:\
+	:FD=\E[23;2~:FE=\E[24;2~:FF=\E[23~:FG=\E[24~:FH=\E[25~:\
+	:FI=\E[26~:FJ=\E[28~:FK=\E[29~:FL=\E[31~:FM=\E[32~:\
+	:FN=\E[33~:FO=\E[34~:FP=\E[35~:FQ=\E[36~:FR=\E[23;2~:\
+	:FS=\E[24;2~:FT=\E[25;2~:FU=\E[26;2~:FV=\E[28;2~:\
+	:FW=\E[29;2~:FX=\E[31;2~:FY=\E[32;2~:FZ=\E[33;2~:\
+	:Fa=\E[34;2~:Fb=\E[35;2~:Fc=\E[36;2~:\
+	:S6=USR_TERM\072vt420pcdos\072:k1=\E[11~:k2=\E[12~:\
+	:k3=\E[13~:k4=\E[14~:k5=\E[15~:k6=\E[17~:k7=\E[18~:\
+	:k8=\E[19~:k9=\E[20~:k;=\E[21~:kD=\177:kh=\E[H:\
+	:..px=\EP1;1|%?%{16}%p1%>%t%{0}%e%{21}%p1%>%t%{1}%e%{25}%p1%>%t%{2}%e%{27}%p1%>%t%{3}%e%{30}%p1%>%t%{4}%e%{5}%;%p1%+%d/%p2%s\E\:tc=vt420:
+
+vt420pcdos|DEC VT420 w/PC for DOS Merge:\
+	:li#25:\
+	:S1=%?%p2%{19}%=%t\E\023\021%e%p2%{32}%<%t\E%p2%c%e%p2%{127}%=%t\E\177%e%p2%c%;:\
+	:S4=\E[?1;2r\E[34h:\
+	:S5=\E[?0;0r\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:S6@:\
+	:me=\E[m:sa@:\
+	:tc=vt420pc:
+
+vt420f|DEC VT420 with VT kbd; VT400 mode; F1-F5 used as Fkeys:\
+	:F1=\E[23~:F2=\E[24~:F3=\E[25~:F4=\E[26~:F5=\E[28~:\
+	:F6=\E[29~:F7=\E[31~:F8=\E[32~:F9=\E[33~:FA=\E[34~:\
+	:k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~:k5=\E[15~:\
+	:k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:k;=\E[21~:\
+	:kD=\177:kh=\E[H:l1=\EOP:l2=\EOQ:l3=\EOR:l4=\EOS:\
+	:tc=vt420:
+
+vt510|DEC VT510:\
+	:tc=vt420:
+vt510pc|DEC VT510 w/PC keyboard:\
+	:tc=vt420pc:
+vt510pcdos|DEC VT510 w/PC for DOS Merge:\
+	:tc=vt420pcdos:
+
+# VT520/VT525
+#
+# The VT520 is a monochrome text terminal capable of managing up to
+# four independent sessions in the terminal.  It has multiple ANSI
+# emulations (VT520, VT420, VT320, VT220, VT100, VT PCTerm, SCO Console)
+# and ASCII emulations (WY160/60, PCTerm, 50/50+, 150/120, TVI 950,
+# 925 910+, ADDS A2).  This terminfo data is for the ANSI emulations only.
+#
+# Terminal Set-Up is entered by pressing [F3], [Caps Lock]/[F3] or
+# [Alt]/[Print Screen] depending upon which keyboard and which
+# terminal mode is being used.  If Set-Up has been disabled or
+# assigned to an unknown key, Set-Up may be entered by pressing
+# [F3] as the first key after power up, regardless of keyboard type.
+# (vt520: I added <rmam>/<smam> based on the init string, also :sc: -- esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+vt520|DEC VT520:\
+	:am:mi:xn:xo:\
+	:co#80:li#24:vt#3:\
+	:*6=\E[4~:@0=\E[1~:RA=\E[?7l:\
+	:S5=\E[?0;0r\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:\
+	:SA=\E[?7h:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=\E(B:al=\E[L:as=\E(0:bl=^G:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:dc=\E[P:dl=\E[M:do=\E[B:ei=\E[4l:ho=\E[H:\
+	:i2=\E[?67h\E[64;1"p:if=/usr/share/tabset/vt300:\
+	:im=\E[4h:is=\E[1;24r\E[24;1H:k0=\E[29~:k1=\EOP:k2=\EOQ:\
+	:k3=\EOR:k4=\EOS:k5=\E[17~:k6=\E[18~:k7=\E[19~:k8=\E[20~:\
+	:k9=\E[21~:k;=\E[29~:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:\
+	:kb=^H:kd=\E[B:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mb=\E[5m:\
+	:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:r3=\E[?67h\E[64;1"p:\
+	:rc=\E8:rf=/usr/share/tabset/vt300:sc=\E7:se=\E[m:sf=\ED:\
+	:so=\E[7m:sr=\EM:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:
+
+# (vt525: I added <rmam>/<smam> based on the init string;
+# removed :se:=\E[m, :ue:=\E[m, added :sc: -- esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+vt525|DEC VT525:\
+	:am:mi:xn:xo:\
+	:co#80:li#24:vt#3:\
+	:*6=\E[4~:@0=\E[1~:RA=\E[?7l:\
+	:S5=\E[?0;0r\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:\
+	:SA=\E[?7h:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=\E(B:al=\E[L:as=\E(0:bl=^G:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:dc=\E[P:dl=\E[M:do=\E[B:ei=\E[4l:ho=\E[H:\
+	:i2=\E[?67h\E[64;1"p:if=/usr/share/tabset/vt300:\
+	:im=\E[4h:is=\E[1;24r\E[24;1H:k0=\E[29~:k1=\EOP:k2=\EOQ:\
+	:k3=\EOR:k4=\EOS:k5=\E[17~:k6=\E[18~:k7=\E[19~:k8=\E[20~:\
+	:k9=\E[21~:k;=\E[29~:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:\
+	:kb=^H:kd=\E[B:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mb=\E[5m:\
+	:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:r3=\E[?67h\E[64;1"p:\
+	:rc=\E8:rf=/usr/share/tabset/vt300:sc=\E7:se=\E[m:sf=\ED:\
+	:so=\E[7m:sr=\EM:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:
+
+#### VT100 emulations
+#
+
+# John Hawkinson <jhawk@MIT.EDU> tells us that the EWAN telnet for Windows
+# (the best Windows telnet as of September 1995) presents the name `dec-vt100'
+# to telnetd.   Michael Deutschmann <ldeutsch@mail.netshop.net> informs us
+# that this works best with a stock vt100 entry.
+dec-vt100|EWAN telnet's vt100 emulation:\
+	:tc=vt100:
+
+# From: Adrian Garside <94ajg2@eng.cam.ac.uk>, 19 Nov 1996
+dec-vt220|DOS tnvt200 terminal emulator:\
+	:am@:tc=vt220:
+
+# Zstem340 is an (IMHO) excellent VT emulator for PC's.  I recommend it to
+# anyone who needs PC VT340 emulation. (or anything below that level, for
+# that matter -- DEC's ALL-in-1 seems happy with it, as does INFOPLUS's
+# RDBM systems, it includes ReGIS and SiXel support!  I'm impressed...
+# I can send the address if requested.
+# (z340: changed garbled \E[5?l to \E[?5l, DEC smooth scroll off -- esr)
+# From: Adam Thompson <athompso@pangea.ca> Sept 10 1995
+z340|zstem vt340 terminal emulator 132col 42line:\
+	:li#42:\
+	:is=\E>\E[?3h\E[?4l\E[?5l\E[?7h\E[?8h\E[1;42r\E[42;1H:\
+	:r2=\E>\E[?3h\E[?4l\E[?5l\E[?7h\E[?8h\E[1;42r\E[42;1H:\
+	:tc=vt320-w:
+z340-nam|zstem vt340 terminal emulator 132col 42line (no automatic margins):\
+	:am@:\
+	:is=\E>\E[?3h\E[?4l\E[?5l\E[?7l\E[?8h\E[1;42r\E[42;1H:\
+	:r2=\E>\E[?3h\E[?4l\E[?5l\E[?7l\E[?8h\E[1;42r\E[42;1H:\
+	:tc=z340:
+
+# CRT is shareware.  It implements some xterm features, including mouse.
+crt|crt-vt220|CRT 2.3 emulating VT220:\
+	:ms:ut:\
+	:Co#8:pa#64:\
+	:AB=\E[4%p1%dm:AF=\E[3%p1%dm:Sb=\E[4%dm:Sf=\E[3%dm:\
+	:op=\E[39;49m:st=\EH:u6=\E[%i%d;%dR:u7=\E[6n:u8=\E[?1;2c:\
+	:u9=\E[c:\
+	:tc=vt220:
+
+# This entry is for Tera Term Pro version 2.3, for MS-Windows 95/NT written by
+# T. Teranishi dated Mar 10, 1998.  It is a free software terminal emulator
+# (communication program) which supports:
+#
+#	- Serial port connections.
+#	- TCP/IP (telnet) connections.
+#	- VT100 emulation, and selected VT200/300 emulation.
+#	- TEK4010 emulation.
+#	- File transfer protocols (Kermit, XMODEM, ZMODEM, B-PLUS and
+#	  Quick-VAN).
+#	- Scripts using the "Tera Term Language".
+#	- Japanese and Russian character sets.
+#
+# The program does not come with terminfo or termcap entries.  However, the
+# emulation (testing with vttest and ncurses) is reasonably close to vt100 (no
+# vt52 or doublesize character support; blinking is done with color).  Besides
+# the HPA, VPA extensions it also implements CPL and CNL.
+#
+# All of the function keys can be remapped.  This description shows the default
+# mapping, as installed.  Both vt100 PF1-PF4 keys and quasi-vt220 F1-F4 keys
+# are supported.  F13-F20 are obtained by shifting F3-F10.  The editing keypad
+# is laid out like vt220, rather than the face codes on the PC keyboard, i.e,
+#	kfnd	Insert
+#	kslt	Delete
+#	kich1	Home
+#	kdch1	PageUp
+#	kpp	End
+#	knp	PageDown
+#
+# ANSI colors are implemented, but cannot be combined with video attributes
+# except for reverse.
+#
+# No fonts are supplied with the program, so the acsc string is chosen to
+# correspond with the default Microsoft terminal font.
+#
+# Tera Term recognizes some xterm sequences, including those for setting and
+# retrieving the window title, and for setting the window size (i.e., using
+# "resize -s"), though it does not pass SIGWINCH to the application if the
+# user resizes the window with the mouse.
+teraterm|Tera Term Pro:\
+	:km:xo@:\
+	:NC#43:vt@:\
+	:*6=\E[4~:@0=\E[1~:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:\
+	:F1=\E[23~:F2=\E[24~:F3=\E[25~:F4=\E[26~:F5=\E[28~:\
+	:F6=\E[29~:F7=\E[31~:F8=\E[32~:F9=\E[33~:FA=\E[34~:\
+	:ac=+\020\054\021-\030.^Y0\333`\004a\261f\370g\361h\260i\316j\331k\277l\332m\300n\305o~p\304q\304r\304s_t\303u\264v\301w\302x\263y\363z\362{\343|\330}\234~\376:\
+	:al=\E[L:cb=\E[1K:cd=\E[J:ce=\E[K:ch=\E[%i%dG:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cv=\E[%i%dd:dc=\E[P:dl=\E[M:ec=\E[%dX:\
+	:k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~:k5=\E[15~:\
+	:k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:k;=\E[21~:\
+	:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:mb=\E[5m:md=\E[1m:\
+	:me=\E[m:mr=\E[7m:nd=\E[C:op=\E[100m:se=\E[27m:so=\E[7m:\
+	:sr=\EM:u6=\E[%i%d;%dR:u7=\E[6n:u8=\E[?1;2c:u9=\E[c:\
+	:ue=\E[24m:up=\E[A:us=\E[4m:vb=200\E[?5h\E[?5l:\
+	:ve=\E[?25h:vi=\E[?25l:\
+	:tc=klone+color:tc=vt100:
+
+# Tested with WinNT 4.0, the telnet application assumes the screensize is
+# 25x80.  This entry uses the 'Terminal' font, to get line-drawing characters.
+ms-vt100|MS telnet imitating dec vt100:\
+	:li#25:\
+	:ac=+\020\054\021-\030.^Y0\333`\004a\261f\370g\361h\260i\316j\331k\277l\332m\300n\305o~p\304q\304r\304s_t\303u\264v\301w\302x\263y\363z\362{\343|\330}\234~\376:\
+	:ct@:u6=\E[%i%d;%dR:u7=\E[6n:u8=\E[?6c:u9=\E[c:\
+	:tc=vt100:
+
+#### X terminal emulators
+#
+# You can add the following line to your .Xdefaults to change the terminal type
+# set by the xterms you start up to my-xterm:
+#
+# *termName:  my-xterm
+#
+# System administrators can change the default entry for xterm instances
+# by adding a similar line to /usr/X11/lib/X11/app-defaults/XTerm.  In either
+# case, xterm will detect and reject an invalid terminal type, falling back
+# to the default of xterm.
+#
+
+# X10/6.6	11/7/86, minus alternate screen, plus (csr)
+# (xterm: ":MT:" changed to ":km:"; added <smam>/<rmam> based on init string;
+# removed (hs, eslok, tsl=\E[?E\E[?%i%dT, fsl=\E[?F, dsl=\E[?E)
+# as these seem not to work -- esr)
+x10term|vs100-x10|xterm terminal emulator (X10 window system):\
+	:am:bs:km:mi:ms:xn:xo:\
+	:co#80:it#8:li#65:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:RA=\E[?7l:SA=\E[?7h:\
+	:al=\E[L:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:\
+	:cs=\E[%i%d;%dr:dc=\E[P:dl=\E[M:do=^J:ei=\E[4l:ho=\E[H:\
+	:im=\E[4h:is=\E\E[m\E[?7h\E[?1;4l:k1=\EOP:k2=\EOQ:\
+	:k3=\EOR:k4=\EOS:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:\
+	:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:md=\E[1m:me=\E[m:\
+	:mr=\E[7m:nd=\E[C:se=\E[m:sf=^J:so=\E[7m:sr=\EM:ta=^I:\
+	:ue=\E[m:up=\E[A:us=\E[4m:
+# Compatible with the R5 xterm 
+# (from the XFree86 3.2 distribution, <blink=@> removed)
+# added khome/kend, rmir/smir, rmul/smul based on the R5 xterm code - TD
+# corrected typos in rs2 string - TD
+xterm-r5|xterm R5 version:\
+	:am:bs:km:ms:xn:\
+	:co#80:it#8:li#24:\
+	:@7=\E[4~:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:\
+	:F1=\E[23~:F2=\E[24~:IC=\E[%d@:Km=\E[M:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:ei=\E[4l:ho=\E[H:ic=\E[@:\
+	:im=\E[4h:k0=\EOq:k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~:\
+	:k5=\E[15~:k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:\
+	:k;=\E[21~:kA=\E[30~:kD=\E[3~:kE=\E[8~:kI=\E[2~:kL=\E[31~:\
+	:kN=\E[6~:kP=\E[5~:kb=^H:kd=\EOB:ke=\E[?1l\E>:kh=\E[1~:\
+	:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:md=\E[1m:\
+	:me=\E[m:mr=\E[7m:nd=\E[C:\
+	:r2=\E>\E[?1;3;4;5;6l\E[4l\E[?7h\E[m\E[r\E[2J\E[H:\
+	:rc=\E8:\
+	:..sa=\E[%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;m:\
+	:sc=\E7:se=\E[m:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:ue=\E[m:\
+	:up=\E[A:us=\E[4m:
+# Compatible with the R6 xterm
+# (from XFree86 3.2 distribution, <acsc> and :it: added, <blink@> removed)
+# added khome/kend - TD
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+xterm-r6|xterm-old|xterm X11R6 version:\
+	:am:bs:km:mi:ms:xn:\
+	:co#80:it#8:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:cd=\E[J:\
+	:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:ei=\E[4l:\
+	:ho=\E[H:im=\E[4h:\
+	:is=\E7\E[r\E[m\E[?7h\E[?1;3;4;6l\E[4l\E8\E>:k1=\EOP:\
+	:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\E[15~:k6=\E[17~:k7=\E[18~:\
+	:k8=\E[19~:k9=\E[20~:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:\
+	:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:\
+	:ku=\EOA:le=^H:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:rc=\E8:\
+	:sc=\E7:se=\E[m:sf=^J:so=\E[7m:sr=\EM:ta=^I:\
+	:te=\E[2J\E[?47l\E8:ti=\E7\E[?47h:ue=\E[m:up=\E[A:\
+	:us=\E[4m:
+# This is the base xterm entry for the xterm supplied with XFree86 3.2 & up.
+# The name has been changed and some aliases have been removed.
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+xterm-xf86-v32|xterm terminal emulator (XFree86 3.2 Window System):\
+	:am:bs:km:mi:ms:xn:\
+	:co#80:it#8:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:K1=\EOw:K2=\EOy:K3=\EOu:K4=\EOq:K5=\EOs:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:bt=\E[Z:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:ec=\E[%dX:\
+	:ei=\E[4l:ho=\E[H:ic=\E[@:im=\E[4h:\
+	:is=\E7\E[r\E[m\E[?7h\E[?1;3;4;6l\E[4l\E8\E>:\
+	:k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~:k5=\E[15~:\
+	:k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:kD=\177:kI=\E[2~:\
+	:kN=\E[6~:kP=\E[5~:kb=^H:kd=\EOB:ke=\E[?1l\E>:kh=\EOH:\
+	:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:md=\E[1m:\
+	:me=\E[m\017:mr=\E[7m:nd=\E[C:rc=\E8:sc=\E7:se=\E[27m:\
+	:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:te=\E[2J\E[?47l\E8:\
+	:ti=\E7\E[?47h:ue=\E[24m:up=\E[A:us=\E[4m:\
+	:vb=\E[?5h\E[?5l:ve=\E[?25h:vi=\E[?25l:vs=\E[?25h:
+
+# This is the stock xterm entry supplied with XFree86 3.3, which uses VT100
+# codes for F1-F4 except while in VT220 mode.
+xterm-xf86-v33|xterm terminal emulator (XFree86 3.3 Window System):\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+	:tc=xterm-xf86-v32:
+
+# This version was released in XFree86 3.3.3 (November 1998).
+# Besides providing printer support, it exploits a new feature that allows
+# xterm to use terminfo-based descriptions with the titeInhibit resource.
+xterm-xf86-v333|xterm terminal emulator (XFree86 3.3.3 Window System):\
+	:5i:\
+	:*6@:@0@:@7=\E[4~:ei=:ic@:im=:is=\E[\041p\E[?3;4l\E[4l\E>:\
+	:kD=\E[3~:kh=\E[1~:mb=\E[5m:mk=\E[8m:pf=\E[4i:po=\E[5i:\
+	:ps=\E[i:r1=\Ec:r2=\E[\041p\E[?3;4l\E[4l\E>:\
+	:..sa=\E[0%?%p1%p6%|%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m%?%p9%t\016%e\017%;:\
+	:te=\E[?1047l\E[?1048l:ti=\E[?1048h\E[?1047h:\
+	:tc=xterm-xf86-v33:
+
+# This beta version will probably be released in XFree86 4.0.
+xterm-xf86-v40|xterm terminal emulator (XFree86 4.0 Window System):\
+	:@7=\EOF:K1=\EOH:K2=\EOE:K3=\E[5~:K4=\EOF:K5=\E[6~:kD=\177:\
+	:kh=\EOH:te=\E[?1049l:ti=\E[?1049h:\
+	:tc=xterm-xf86-v333:
+
+xterm-xfree86|xterm-new|xterm terminal emulator (XFree86 4.0 Window System):\
+	:tc=xterm-xf86-v40:
+
+# From: David J. MacKenzie <djm@va.pubnix.com>, 14 Nov 1997
+xterm-xi|xterm on XI Graphics Accelerated X under BSD/OS 3.1:\
+	:se=\E[m:ue=\E[m:\
+	:tc=xterm-xf86-v33:
+
+# This is one of the variants of XFree86 3.3 xterm, updated for 4.0 (T.Dickey)
+xterm-16color|xterm with 16 colors like aixterm:\
+	:Co#16:NC#32:pa#256:\
+	:AB=\E[%?%p1%{8}%<%t%p1%{40}%+%e%p1%{92}%+%;%dm:\
+	:AF=\E[%?%p1%{8}%<%t%p1%{30}%+%e%p1%{82}%+%;%dm:\
+	:..Sb=%p1%{8}%/%{6}%*%{4}%+\E[%d%p1%{8}%m%Pa%?%ga%{1}%=%t4%e%ga%{3}%=%t6%e%ga%{4}%=%t1%e%ga%{6}%=%t3%e%ga%d%;m:\
+	:..Sf=%p1%{8}%/%{6}%*%{3}%+\E[%d%p1%{8}%m%Pa%?%ga%{1}%=%t4%e%ga%{3}%=%t6%e%ga%{4}%=%t1%e%ga%{6}%=%t3%e%ga%d%;m:\
+	:tc=xterm-xf86-v40:
+
+# This is another variant, for XFree86 4.0 xterm (T.Dickey)
+# This is an 8-bit version of xterm, which emulates DEC vt220 with ANSI color.
+# To use it, your decTerminalID resource must be set to 200 or above.
+#
+#	HTS	\E H	\210
+#	RI	\E M	\215
+#	SS3	\E O	\217
+#	CSI	\E [	\233
+#
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+xterm-8bit|xterm terminal emulator 8-bit controls (X Window System):\
+	:am:bs:km:mi:ms:xn:\
+	:co#80:it#8:li#24:\
+	:AL=\233%dL:DC=\233%dP:DL=\233%dM:DO=\233%dB:IC=\233%d@:\
+	:K1=\217w:K2=\217y:K3=\217u:K4=\217q:K5=\217s:LE=\233%dD:\
+	:RI=\233%dC:UP=\233%dA:ae=^O:al=\233L:as=^N:bl=^G:bt=\233Z:\
+	:cd=\233J:ce=\233K:cl=\233H\2332J:cm=\233%i%d;%dH:cr=^M:\
+	:cs=\233%i%d;%dr:ct=\2333g:dc=\233P:dl=\233M:do=^J:\
+	:ec=\233%dX:ei=\2334l:ho=\233H:im=\2334h:\
+	:is=\E7\E G\233r\233m\233?7h\233?1;3;4;6l\2334l\E8\E>:\
+	:k1=\23311~:k2=\23312~:k3=\23313~:k4=\23314~:k5=\23315~:\
+	:k6=\23317~:k7=\23318~:k8=\23319~:k9=\23320~:kD=\2333~:\
+	:kI=\2332~:kN=\2336~:kP=\2335~:kb=^H:kd=\217B:\
+	:ke=\233?1l\E>:kh=\2331~:kl=\217D:kr=\217C:ks=\233?1h\E=:\
+	:ku=\217A:le=^H:mb=\2335m:md=\2331m:me=\233m^O:mr=\2337m:\
+	:nd=\233C:rc=\E8:sc=\E7:se=\23327m:sf=^J:so=\2337m:sr=\215:\
+	:st=\210:ta=^I:te=\233?1049l:ti=\233?1049h:ue=\23324m:\
+	:up=\233A:us=\2334m:vb=\233?5h\233?5l:ve=\233?25h:\
+	:vi=\233?25l:vs=\233?25h:
+
+xterm-24|vs100|xterms|xterm terminal emulator (X Window System):\
+	:li#24:tc=xterm:
+
+# This is xterm for ncurses.
+xterm|xterm terminal emulator (X Window System):\
+	:Km=\E[M:\
+	:ac=``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:u6=\E[%i%d;%dR:u7=\E[6n:u8=\E[?1;2c:u9=\E[c:\
+	:tc=xterm-r6:
+
+# These entries allow access to the X titlebar and icon name as a status line. 
+# Note that twm (and possibly window managers descended from it such as tvtwm, 
+# ctwm, and vtwm) track windows by icon-name; thus, you don't want to mess
+# with it.
+xterm+sl|access X title line and icon name:\
+	:hs:\
+	:ws#40:\
+	:ds=\E]0;\007:fs=^G:ts=\E]0;:tc=xterm:
+xterm+sl-twm|access X title line (pacify twm-descended window managers):\
+	:hs:\
+	:ws#40:\
+	:ds=\E]2;\007:fs=^G:ts=\E]2;:tc=xterm:
+
+#
+# The following xterm variants don't depend on your base version
+#
+# xterm with bold instead of underline
+xterm-bold|xterm terminal emulator (X11R6 Window System) standout w/bold:\
+	:so=\E[7m:us=\E[1m:\
+	:tc=xterm:
+# (kterm: this had extension capabilities ":KJ:TY=ascii:" -- esr)
+# (kterm should not invoke DEC Graphics as the alternate character set
+#  -- Kenji Rikitake)
+kterm|kterm kanji terminal emulator (X window system):\
+	:es:hs:\
+	:Km=\E[M:ac@:ae@:as@:cs=\E[%i%d;%dr:ds=\E[?H:eA@:fs=\E[?F:\
+	:op=\E[39;49m:rc=\E8:sc=\E7:ts=\E[?E\E[?%i%dT:\
+	:tc=xterm-r6:tc=klone+color:
+# See the note on ICH/ICH1 VERSUS RMIR/SMIR near the end of file
+xterm-nic|xterm with ich/ich1 suppressed for non-curses programs:\
+	:IC@:ei=:ic@:im=:\
+	:tc=xterm:
+# From: Mark Sheppard <kimble@mistral.co.uk>, 4 May 1996 
+xterm1|xterm terminal emulator ignoring the alternate screen buffer:\
+	:te@:ti@:\
+	:tc=xterm:
+
+# This describes the capabilities of color_xterm, an xterm variant from
+# before ECMA-64 color support was folded into the main-line xterm release.
+# This entry is straight from color_xterm's maintainer.
+# From: Jacob Mandelson <jlm@ugcs.caltech.edu>, 09 Nov 1996
+# The README's with the distribution also say that it supports SGR 21, 24, 25
+# and 27, but they are not present in the terminfo or termcap.
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+color_xterm|cx|cx100|color_xterm color terminal emulator for X:\
+	:am:bs:km:mi:ms:xn:\
+	:co#80:it#8:li#65:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:K1=\EOw:K2=\EOu:K3=\EOy:K4=\EOq:K5=\EOs:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:cd=\E[J:\
+	:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:dc=\E[P:dl=\E[M:do=^J:ei=\E[4l:ho=\E[H:\
+	:i1=\E[r\E[m\E[?7h\E[?4;6l\E[4l:im=\E[4h:k1=\E[11~:\
+	:k2=\E[12~:k3=\E[13~:k4=\E[14~:k5=\E[15~:k6=\E[17~:\
+	:k7=\E[18~:k8=\E[19~:k9=\E[20~:kI=\E[2~:kN=\E[6~:kP=\E[5~:\
+	:kb=^H:kd=\EOB:kh=\E[7~:kl=\EOD:kr=\EOC:ku=\EOA:le=^H:\
+	:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:rc=\E8:sc=\E7:se=\E[27m:\
+	:sf=^J:so=\E[7m:sr=\EM:ta=^I:te=\E>\E[?41;1r:\
+	:ti=\E[?1;41s\E[?1;41h\E=:ue=\E[24m:up=\E[A:us=\E[4m:
+
+# The 'nxterm' distributed with Redhat Linux is a slight rehack of
+# xterm-sb_right-ansi-3d, which implements ANSI colors, but does not support
+# SGR 39 or 49.  SGR 0 does reset colors (along with everything else).  This
+# description is "compatible" with color_xterm, rxvt and XFree86 xterm, except
+# that each of those implements the home, end, delete keys differently.
+nxterm|xterm-color|generic color xterm:\
+	:NC@:\
+	:op=\E[m:tc=xterm-r6:tc=klone+color:
+
+# From: Thomas Dickey <dickey@clark.net> 04 Oct 1997
+# Updated: Oezguer Kesim <kesim@math.fu-berlin.de> 02 Nov 1997
+# Notes:
+# rxvt 2.21b uses
+#	smacs=\E(B\E)U^N, rmacs=\E(B\E)0^O,
+# but some applications don't work with that.
+# It also has an AIX extension
+#	box2=lqkxjmwuvtn,
+# and
+#	ech=\E[%p1%dX,
+# but the latter does not work correctly.
+#
+# The distributed terminfo says it implements hpa and vpa, but they are not
+# implemented correctly, using relative rather than absolute positioning.
+#
+# rxvt is normally configured to look for "xterm" or "xterm-color" as $TERM.
+# Since rxvt is not really compatible with xterm, it should be configured as
+# "rxvt" (monochrome) and "rxvt-color". 
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+rxvt|rxvt terminal base (X Window System):\
+	:am:bs:eo:km:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:K1=\EOw:K2=\EOu:K3=\EOy:K4=\EOq:K5=\EOs:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:cd=\E[J:\
+	:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:ei=\E[4l:\
+	:ho=\E[H:i1=\E[?47l\E=\E[?1l:ic=\E[@:im=\E[4h:\
+	:is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l\E[4l:\
+	:k0=\E[21~:k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~:\
+	:k5=\E[15~:k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:\
+	:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:kb=^H:kd=\E[B:ke=\E>:\
+	:kh=\E[7~:kl=\E[D:kr=\E[C:ks=\E=:ku=\E[A:le=^H:mb=\E[5m:\
+	:md=\E[1m:me=\E[0m\017:mr=\E[7m:nd=\E[C:rc=\E8:sc=\E7:\
+	:se=\E[27m:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:te=\E[2J\E[?47l\E8:ti=\E7\E[?47h:ue=\E[24m:up=\E[A:\
+	:us=\E[4m:vb=\E[?5h\E[?5l:ve=\E[?25h:vi=\E[?25l:\
+	:vs=\E[?25h:
+rxvt-color|rxvt terminal emulator (X Window System):\
+	:Co#8:pa#64:\
+	:AB=\E[%p1%{40}%+%dm:AF=\E[%p1%{30}%+%dm:me=\E[m\017:\
+	:op=\E[39;49m:\
+	:tc=rxvt:
+
+# These (xtermc and xtermm) are distributed with Solaris.  They refer to a
+# variant of xterm which is apparently no longer supported, but are interesting
+# because they illustrate SVr4 curses mouse controls - T.Dickey
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+xtermm|xterm terminal emulator (monocrome):\
+	:am:bs:km:mi:ms:xn:\
+	:BT#3:co#80:it#8:li#24:\
+	:@7=\E[Y:@8=\EOM:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:\
+	:F1=\EOZ:F2=\EOA:Gm=\E[%p1%dY:IC=\E[%d@:K1=\EOq:K2=\EOr:\
+	:K3=\EOs:K4=\EOp:K5=\EOn:Km=\E[^_:LE=\E[%dD:RI=\E[%dC:\
+	:RQ=\E[492Z:UP=\E[%dA:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=^O:al=\E[L:as=^N:bl=^G:cb=\E[1K:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:eA=\E(B\E)0:ei=:ho=\E[H:\
+	:ic=\E[@:im=:k0=\EOy:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+	:k5=\EOT:k6=\EOU:k7=\EOV:k8=\EOW:k9=\EOX:k;=\EOY:kN=\E[U:\
+	:kP=\E[V:kb=^H:kd=\EOB:kh=\E[H:kl=\EOD:kr=\EOC:ku=\EOA:\
+	:le=\E[1D:mb=@:md=\E[1m:me=\E[m\017:mr=\E[7m:nd=\E[C:\
+	:r1=\E>\E[1;3;4;5;6l\E[?7h\E[m\E[r\E[2J\E[H:\
+	:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\E8:sc=\E7:\
+	:se=\E[m:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:te=\E@0\E[?4r:\
+	:ti=\E@0\E[?4s\E[?4h\E@1:up=\E[A:
+
+xtermc|xterm terminal emulator (color):\
+	:Co#8:NC#7:pa#64:\
+	:AB=\E[4%p1%dm:AF=\E[3%p1%dm:\
+	:..Sb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m:\
+	:..Sf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m:\
+	:op=\E[100m:\
+	:tc=xtermm:
+
+# From: David J. MacKenzie <djm@va.pubnix.com> 20 Apr 1995
+# Here's a termcap entry I've been using for xterm_color, which comes
+# with BSD/OS 2.0, and the X11R6 contrib tape too I think.  Besides the
+# color stuff, I also have a status line defined as the window manager
+# title bar. [I have translated it to terminfo -- ESR]
+xterm-pcolor|xterm with color used for highlights and status line:\
+	:md=\E[1m\E[43m:mr=\E[7m\E[34m:so=\E[7m\E[31m:\
+	:us=\E[4m\E[42m:\
+	:tc=xterm+sl:tc=xterm-r6:
+
+# HP ships this, except for the pb#9600 which was merged in from BSD termcap.
+# (hpterm: added empty <acsc>, we have no idea what ACS chars look like --esr)
+hpterm|X-hpterm|hp X11 terminal emulator:\
+	:am:da:db:mi:xs:\
+	:Nl#8:co#80:lh#2:li#24:lm#0:lw#8:pb#9600:sg#0:\
+	:LF=\E&j@:LO=\E&jB:ac=:ae=^O:al=\EL:as=^N:bl=^G:bt=\Ei:\
+	:cd=\EJ:ce=\EK:ch=\E&a%dC:cl=\E&a0y0C\EJ:cm=\E&a%dy%dC:\
+	:cr=^M:ct=\E3:cv=\E&a%dY:dc=\EP:dl=\EM:do=\EB:ei=\ER:im=\EQ:\
+	:k1=\Ep:k2=\Eq:k3=\Er:k4=\Es:k5=\Et:k6=\Eu:k7=\Ev:k8=\Ew:\
+	:kA=\EL:kC=\EJ:kD=\EP:kE=\EK:kF=\ES:kH=\EF:kI=\EQ:kL=\EM:\
+	:kM=\ER:kN=\EU:kP=\EV:kR=\ET:kS=\EJ:kT=\E1:ka=\E3:kb=^H:\
+	:kd=\EB:ke=\E&s0A:kh=\Eh:kl=\ED:kr=\EC:ks=\E&s1A:kt=\E2:\
+	:ku=\EA:le=^H:md=\E&dB:me=\E&d@:mh=\E&dH:ml=\El:mr=\E&dB:\
+	:mu=\Em:nd=\EC:..pk=\E&f%p1%dk%p2%l%dL%p2%s:\
+	:..pl=\E&f1a%p1%dk%p2%l%dL%p2%s:\
+	:..pn=\E&f%p1%dk%p2%l%dd0L%p2%s:\
+	:..px=\E&f2a%p1%dk%p2%l%dL%p2%s:\
+	:..sa=\E&d%?%p7%t%{115}%c%;%p1%p3%|%p6%|%{2}%*%p2%{4}%*%+%p4%+%p5%{8}%*%+%{64}%+%c%?%p9%t%'\016'%c%e%'\017'%c%;:\
+	:se=\E&d@:sf=^J:so=\E&dJ:sr=\ET:st=\E1:ta=^I:ue=\E&d@:\
+	:up=\EA:us=\E&dD:
+
+# This entry describes an xterm with Sun-style function keys enabled
+# via the X resource setting "xterm*sunFunctionKeys:true"
+# To understand <kf11>/<kf12> note that L1,L2 and F11,F12 are the same.
+# The <kf13>...<kf20> keys are L3-L10.  We don't set <kf16=\E[197z>
+# because we want it to be seen as <kcpy>. 
+# The <kf31>...<kf45> keys are R1-R15.  We treat some of these in accordance
+# with their Sun keyboard labels instead.
+# From: Simon J. Gerraty <sjg@zen.void.oz.au> 10 Jan 1996
+xterm-sun|xterm with sunFunctionKeys true:\
+	:%1=\E[196z:&8=\E[195z:@0=\E[200z:@5=\E[197z:@7=\E[220z:\
+	:F1=\E[192z:F2=\E[193z:F3=\E[194z:F4=\E[195z:F5=\E[196z:\
+	:F7=\E[198z:F8=\E[199z:F9=\E[200z:FA=\E[201z:FL=\E[208z:\
+	:FM=\E[209z:FN=\E[210z:FO=\E[211z:FP=\E[212z:FQ=\E[213z:\
+	:FS=\E[215z:FU=\E[217z:FW=\E[219z:FY=\E[221z:K2=\E[218z:\
+	:k1=\E[224z:k2=\E[225z:k3=\E[226z:k4=\E[227z:k5=\E[228z:\
+	:k6=\E[229z:k7=\E[230z:k8=\E[231z:k9=\E[232z:k;=\E[233z:\
+	:kI=\E[2z:kN=\E[222z:kP=\E[216z:kh=\E[214z:\
+	:tc=xterm:
+xterms-sun|small (80x24) xterm with sunFunctionKeys true:\
+	:co#80:li#24:tc=xterm-sun:
+
+# This is for the extensible terminal emulator on the X11R6 contrib tape.
+emu|emu native mode:\
+	:mi:ms:xo:\
+	:Co#15:co#80:it#8:li#24:pa#64:vt#200:\
+	:*6=\Esel:@0=\Efind:@8=^M:AB=\Es%i%p1%d;:AF=\Er%i%p1%d;:\
+	:AL=\EQ%d;:DC=\EI%d;:DL=\ER%d;:DO=\Ep%d;:F1=\EF11:\
+	:F2=\EF12:F3=\EF13:F4=\EF14:F5=\EF15:F6=\EF16:F7=\EF17:\
+	:F8=\EF18:F9=\EF19:FA=\EF20:LE=\Eq-%d;:RI=\Eq%d;:\
+	:UP=\Ep-%d;:\
+	:ac=61a\202f\260g2j\213k\214l\215m\216n\217o\220q\222s\224t\225u\226v\227w\230x\231~\244:\
+	:ae=\0:al=\EQ1;:as=\0:bl=^G:cb=\EL:cd=\EN:ce=\EK:\
+	:cl=\EP\EE0;0;:cm=\EE%d;%d;:cr=^M:cs=\Ek%d;%d;:ct=\Ej:\
+	:dc=\EI1;:dl=\ER1;:do=\EB:eA=\0:ec=\Ej%d;:ei=\EX:\
+	:ho=\EE0;0;:im=\EY:is=\ES\Er0;\Es0;:k0=\EF00:k1=\EF01:\
+	:k2=\EF02:k3=\EF03:k4=\EF04:k5=\EF05:k6=\EF06:k7=\EF07:\
+	:k8=\EF08:k9=\EF09:k;=\EF10:kD=\177:kI=\Eins:kN=\Enext:\
+	:kP=\Eprior:kb=^H:kd=\EB:kl=\EC:kr=\ED:ku=\EA:le=^H:\
+	:mb=\ES\EW:md=\ES\EU:me=\ES:mr=\ES\ET:nd=\ED:\
+	:oc=\Es0;\Er0;:r2=\ES\Es0;\Er0;:se=\ES:sf=\EG:so=\ES\ET:\
+	:sr=\EF:st=\Eh:ta=^I:ue=\ES:up=\EA:us=\ES\EV:ve=\Ea:vi=\EZ:\
+	:vs=\Ea:
+
+######## COMMERCIAL WORKSTATION CONSOLES
+#
+
+#### Alpha consoles
+#
+
+# This is from the OSF/1 Release 1.0 termcap file
+pccons|pcconsole|ANSI (mostly) Alpha PC console terminal emulation:\
+	:am:xo:\
+	:co#80:li#25:\
+	:al=\E[L:bl=^G:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:\
+	:dc=\E[P:dl=\E[M:do=^J:ei=:ho=\E[H:ic=\E[@:im=:kb=^H:kd=\E[B:\
+	:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:me=\E[m:mr=\E[7m:\
+	:nd=\E[C:nw=^M^J:se=\E[m:so=\E[7m:ta=^I:up=\E[A:
+
+#### AT&T consoles
+#
+
+# This actually describes the generic SVr4 display driver for Intel boxes.
+# The :mh=\E[2m: isn't documented and therefore may not be reliable.
+# From: Eric Raymond <esr@snark.thyrsus.com> Mon Nov 27 19:00:53 EST 1995
+att6386|at386|386at|AT&T WGS 6386 console:\
+	:am:bw:eo:xo:\
+	:co#80:it#8:li#25:\
+	:@7=\E[Y:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:F1=\EOZ:\
+	:F2=\EOA:IC=\E[%d@:LE=\E[%dD:RI=\E[%dC:SF=\E[%dS:\
+	:SR=\E[%dT:UP=\E[%dA:\
+	:ac=``a1fxgqh0jYk?lZm@nEooppqDrrsstCu4vAwBx3yyzz{{||}}~~:\
+	:ae=\E[10m:al=\E[1L:as=\E[12m:bl=^G:bt=\E[Z:cd=\E[J:\
+	:ce=\E[K:ch=\E[%i%dG:cl=\E[2J\E[H:cm=\E[%i%d;%dH:cr=^M:\
+	:ct=\E[2g:cv=\E[%i%dd:dc=\E[P:dl=\E[1M:do=\E[B:ec=\E[%dX:\
+	:ei=:ho=\E[H:ic=\E[1@:im=:is=\E[0;10;39m:k1=\EOP:k2=\EOQ:\
+	:k3=\EOR:k4=\EOS:k5=\EOT:k6=\EOU:k7=\EOV:k8=\EOW:k9=\EOX:\
+	:k;=\EOY:kB=^]:kD=\E[P:kI=\E[@:kM=\E0:kN=\E[U:kP=\E[V:kb=^H:\
+	:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=\E[D:mb=\E[5m:\
+	:md=\E[1m:me=\E[0;10m:mh=\E[2m:mk=\E[9m:mr=\E[7m:nd=\E[C:\
+	:nw=\r\E[S:rc=\E8:\
+	:..sa=\E[10m\E[0%?%p1%p3%|%t;7%;%?%p2%t;4%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p9%t;12%e;10%;%?%p7%t;9%;m:\
+	:sc=\E7:se=\E[m:sf=\E[S:so=\E[7m:sr=\E[T:st=\EH:ta=^I:\
+	:ue=\E[m:up=\E[A:us=\E[4m:ve=\E[=1C:vi=\E[=C:\
+	:tc=klone+color:
+# (pc6300plus: removed ":KM=/usr/lib/ua/kmap.s5:"; renamed BO/EE/CI/CV -- esr)
+pc6300plus|AT&T 6300 plus:\
+	:am:bs:xo:\
+	:co#80:li#24:\
+	:al=\E[1L:bl=^G:cd=\E[0J:ce=\E[0K:cl=\E[2J\E[H:\
+	:cm=\E[%i%2;%2H:cr=^M:ct=\E[3g:dc=\E[1P:dl=\E[1M:do=\E[B:\
+	:ei=:ho=\E[H:ic=\E[1@:im=:k1=\EOc:k2=\EOd:k3=\EOe:k4=\EOf:\
+	:k5=\EOg:k6=\EOh:k7=\EOi:k8=\EOj:k9=\EOk:k;=\EOu:kb=^H:\
+	:kd=\E[B:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mb=\E[5m:md=\E[1m:\
+	:me=\E[m:mh=\E[2m:mk=\E[9m:mr=\E[7m:nd=\E[C:nw=^M^J:\
+	:se=\E[m:sf=^J:so=\E[7m:st=\EH:ue=\E[m:up=\E[A:us=\E[4m:\
+	:ve=\E[=1C:vi=\E[=C:
+
+# From: Benjamin C. W. Sittler <bsittler@nmt.edu>
+#
+# I have a UNIX PC which I use as a terminal attached to my Linux PC.
+# Unfortunately, the UNIX PC terminfo entry that comes with ncurses
+# is broken. All the special key sequences are broken, making it unusable
+# with Emacs. The problem stems from the following:
+# 
+# The UNIX PC has a plethora of keys (103 of them, and there's no numeric
+# keypad!), loadable fonts, and strange highlighting modes ("dithered"
+# half-intensity, "smeared" bold, and real strike-out, for example.) It also
+# uses resizable terminal windows, but the bundled terminal program always
+# uses an 80x24 window (and doesn't support seem to support a 132-column
+# mode.) 
+# 
+# HISTORY: The UNIX PC was one of the first machines with a GUI, and used a
+# library which was a superset of SVr3.5 curses (called tam, for "terminal
+# access method".) tam includes support for real, overlapping windows,
+# onscreen function key labels, and bitmap graphics. But since the primary
+# user interface on the UNIX PC was a GUI program (ua, for "user
+# assistant",) and remote administration was considered important for the
+# machine, tam also supported VT100-compatible terminals attached to the
+# serial port or used across the StarLan network. To simulate the extra keys
+# not present on a VT100, users could press ESC and a two-letter sequence,
+# such as u d (Undo) or U D (Shift-Undo.) These two-letter sequences,
+# however, were not the same as those sent by the actual Undo key. The
+# actual Undo key sends ESC 0 s unshifted, and ESC 0 S shifted, for example.
+# (If you're interested in adding some of the tam calls to ncurses, btw, I
+# have the full documentation and several programs which use tam. It also
+# used an extended terminfo format to describe key sequences, special
+# highlighting modes, etc.) 
+# 
+# KEYS: This means that ncurses would quite painful on the UNIX PC, since
+# there are two sequences for every key-modifier combination (local keyboard
+# sequence and remote "VT100" sequence.) But I doubt many people are trying
+# to use ncurses on the UNIX PC, since ncurses doesn't properly handle the
+# GUI. Unfortunately, the terminfo entry (and the termcap, too, I presume) 
+# seem to have been built from the manual describing the VT100 sequences. 
+# This means it doesn't work for a real live UNIX PC. 
+# 
+# FONTS: The UNIX PC also has a strange interpretation of "alternate
+# character set". Rather than the VT100 graphics you might expect, it allows
+# up to 8 custom fonts to be loaded at any given time. This means that
+# programs expecting VT100 graphics will usually be disappointed. For this
+# reason I have disabled the smacs/rmacs sequences, but they could easily be
+# re-enabled. Here are the relevant control sequences (from the ESCAPE(7) 
+# manpage), should you wish to do so: 
+# 
+# SGR10 - Select font 0 - ESC [ 10 m or SO
+# SGR11 - Select font 1 - ESC [ 11 m or SI
+# SGR12 - Select font 2 - ESC [ 12 m
+# ... (etc.)
+# SGR17 - Select font 7 - ESC [ 17 m
+# 
+# Graphics for line drawing are not reliably found at *any* character
+# location because the UNIX PC has dynamically reloadable fonts. I use font
+# 0 for regular text and font 1 for italics, but this is by no means
+# universal. So ASCII line drawing is in order if smacs/rmacs are enabled.
+# 
+# MISC: The cursor visible/cursor invisible sequences were swapped in the
+# distributed terminfo.
+# 
+# To ameliorate these problems (and fix a few highlighting bugs) I rewrote
+# the UNIX PC terminfo entry. The modified version works great with Lynx,
+# Emacs, and XEmacs running on my Linux PC and displaying on the UNIX PC
+# attached by serial cable. In Emacs, even the Undo key works, and many
+# applications can now use the F1-F8 keys. 
+# 
+# esr's notes:
+#	Terminfo entry for the AT&T Unix PC 7300
+#	from escape(7) in Unix PC 7300 Manual.
+#	Somewhat similar to a vt100-am (but different enough
+#	to redo this from scratch.)
+#
+#	/***************************************************************
+#	*
+#	*           FONT LOADING PROGRAM FOR THE UNIX PC
+#	*
+#	*     This routine loads a font defined in the file ALTFONT
+#	*     into font memory slot #1.  Once the font has been loaded,
+#	*     it can be used as an alternative character set.
+#	*
+#	*     The call to ioctl with the argument WIOCLFONT is the key 
+#	*     to this routine.  For more information, see window(7) in 
+#	*     the PC 7300 documentation.
+#	***************************************************************/
+#	#include <string.h>		/* needed for strcpy call */
+#	#include <sys/window.h>         /* needed for ioctl call */
+#	#define FNSIZE	60		/* font name size */
+#	#define ALTFONT  "/usr/lib/wfont/special.8.ft"  /* font file */
+#	/*
+#	*     The file /usr/lib/wfont/special.8.ft comes with the
+#	*     standard PC software.  It defines a graphics character set
+#	*     similar to that of the Teletype 5425 terminal.  To view
+#	*     this or other fonts in /usr/lib/wfont, use the command
+#	*     cfont <filename>.  For further information on fonts see
+#	*     cfont(1) in the PC 7300 documentation.
+#	*/
+#	
+#	struct altfdata 	/* structure for alt font data */
+#	{
+#	short	altf_slot;		/* memory slot number */
+#	char	altf_name[FNSIZE];	/* font name (file name) */
+#	};
+#	ldfont()
+#	{
+#		int wd;		/* window in which altfont will be */
+#		struct altfdata altf;
+#		altf.altf_slot=1;
+#		strcpy(altf.altf_name,ALTFONT);
+#		for (wd =1; wd < 12; wd++) {
+#		     ioctl(wd, WIOCLFONT,&altf);
+#	        }
+#	}
+#
+# (att7300: added :vi:/:ve:/:ic:/<invis> from the BSDI entry,
+# they're confirmed by the man page for the System V display---esr)
+#
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+att7300|unixpc|pc7300|3b1|s4|AT&T UNIX PC Model 7300:\
+	:am:xo:\
+	:co#80:it#8:li#24:\
+	:AL=\E[%dL:DL=\E[%dM:DO=\E[%dB:LE=\E[%dD:RI=\E[%dC:\
+	:UP=\E[%dA:al=\E[L:bl=^G:bt=\E^I:cd=\E[0J:ce=\E[0K:\
+	:cl=\E[2J\E[H:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:dl=\E[M:\
+	:do=\E[B:ei=:ho=\E[H:i1=\017\E[=1w:ic=\E[@:im=:k1=\EOc:\
+	:k2=\EOd:k3=\EOe:k4=\EOf:k5=\EOg:k6=\EOh:k7=\EOi:k8=\EOj:\
+	:kD=\ENf:kI=\ENj:kN=\E[U:kP=\E[V:kb=^H:kd=\E[B:kh=\E[H:\
+	:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mb=\E[9m:md=\E[1m:\
+	:me=\E[0;10m:mh=\E[2m:mr=\E[7m:nd=\E[C:nw=\EE:se=\E[m:\
+	:sf=^J:so=\E[7m:sr=\EM:ue=\E[m:up=\E[A:us=\E[4m:ve=\E[=0C:\
+	:vi=\E[=1C:
+
+#### Hewlett-Packard consoles
+#
+# These are descriptions for the HP700 series, the workstations formerly
+# known as Apollos.  HP terminals are described elsewhere in the file
+#
+
+# From: Victor Duchovni <vic@fine.princeton.edu>
+# (hp700-wy: removed obsolete ":nl=^J:";
+# replaced /usr/share/tabset/hp700-wy with std because :it#8:,:st=\E1: -- esr)
+hp700-wy|HP700/41 emulating wyse30:\
+	:am:bs:bw:mi:ms:\
+	:co#80:it#8:li#24:sg#1:\
+	:al=0.7*\EE:bt=\EI:cd=\EY:ce=10\ET:cl=^Z:cm=\E=%+ %+ :\
+	:cr=^M:ct=\E0:cv=\E[%+ :dc=\EW:dl=\ER:do=^V:ei=\Er:ho=^^:\
+	:i1=\E~"\EC\Er\E(\EG0\003\E`9\E`1:\
+	:if=/usr/share/tabset/stdcrt:im=\Eq:kB=\EI:kC=^Z:kE=\ET:\
+	:kI=\Eq:kM=\Er:kS=\EY:kT=\EI:kb=\177:kd=^V:kh=^^:kl=^H:kr=^L:\
+	:ku=^K:le=^H:ll=^^^K:me=10\EG0:nd=^L:se=10\EG0:so=10\EG4:\
+	:sr=\Ej:st=\E1:ta=^I:ue=10\EG0:up=^K:us=10\EG8:
+hp70092|hp70092a|hp70092A|HP 700/92:\
+	:am:da:db:xs:\
+	:Nl#8:co#80:lh#2:li#24:lm#0:lw#8:\
+	:LF=\E&j@:LO=\E&jB:ac=0cjgktlrmfn/q\054t5u6v8w7x.:ae=^O:\
+	:al=\EL:as=^N:bl=^G:bt=\Ei:ce=\EK:ch=\E&a%dC:\
+	:cl=\E&a0y0C\EJ:cm=\E&a%dy%dC:cr=^M:ct=\E3:cv=\E&a%dY:\
+	:dc=\EP:dl=\EM:do=\EB:ei=\ER:im=\EQ:k1=\Ep:k2=\Eq:k3=\Er:\
+	:k4=\Es:k5=\Et:k6=\Eu:k7=\Ev:k8=\Ew:kA=\EL:kC=\EJ:kD=\EP:\
+	:kE=\EK:kF=\ES:kH=\EF:kI=\EQ:kL=\EM:kM=\ER:kN=\EU:kP=\EV:\
+	:kR=\ET:kS=\EJ:kT=\E1:ka=\E3:kb=^H:kd=\EB:ke=\E&s0A:kh=\Eh:\
+	:kl=\ED:kr=\EC:ks=\E&s1A:kt=\E2:ku=\EA:le=^H:mb=\E&dA:\
+	:md=\E&dB:me=\E&d@:mh=\E&dH:mr=\E&dB:nd=\EC:se=\E&d@:\
+	:so=\E&dJ:sr=\ET:st=\E1:ta=^I:ue=\E&d@:up=\EA:us=\E&dD:
+
+#  HP 700/44 Setup parameters:  
+# Terminal Mode		HP-PCterm
+# Inhibit Auto Wrap	NO
+# Status Line		Host Writable
+# PC Character Set	YES
+# Twenty-Five Line Mode	YES
+# XON/XOFF		@128 or 64 (sc)
+# Keycode Mode 		NO   or YES (sc)
+# Backspace Key		BS or BS/DEL
+#
+# :is: 	sets pcterm; autowrap; 25 lines; pc char set; prog DEL key; 
+# \E\\? does not turn off keycode mode
+# <smsc>	sets alternate start/stop; keycode on
+hpansi|hp700|hewlett packard 700/44 in HP-PCterm mode:\
+	:am:eo:xn:xo:\
+	:co#80:li#25:\
+	:@7=\E[4~:RA=\E[?7l:S4=\E[>11h\EPO**x0/65;1/67\E\:\
+	:S5=\E[>11l\EP1**x0/11;1/13\E[m\E\:SA=\E[?7h:XF=g:XN=e:\
+	:ac=j\331k\277l\332m\300n\305q\304t\303u\264v\301w\302x\263:\
+	:al=\E[L:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[2J\E[H:\
+	:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:dl=\E[M:do=\E[B:ei=:ho=\E[H:\
+	:ic=\E[@:im=:\
+	:is=\E[44"p\E[?7h\E[>10h\E[>12h\EP1;1|3/7F\E\:\
+	:k1=\E[17~:k2=\E[18~:k3=\E[19~:k4=\E[20~:k5=\E[21~:\
+	:k6=\E[23~:k7=\E[24~:k8=\E[25~:k9=\E[26~:k;=\E[28~:\
+	:kB=\E[Z:kN=\E[6~:kP=\E[5~:kb=^H:kd=\E[B:kh=\E[1~:kl=\E[D:\
+	:kr=\E[C:ku=\E[A:le=\E[D:me=\E[m:nd=\E[C:se=\E[m:sf=^J:\
+	:so=\E[7m:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:ve=\E[?25h:\
+	:vi=\E[?25l:
+
+#### Iris consoles
+#
+
+# Sent by Stefan Stapelberg <stefan@rent-a-guru.de>, 24 Feb 1997, this is
+# from SGI's terminfo database.  SGI's entry shows F9-F12 with the codes
+# for the application keypad mode.  We have added iris-ansi-ap rather than
+# change the original to keypad mode.
+#
+# (iris-ansi: added rmam/smam based on init string -- esr)
+#
+# This entry, and those derived from it, is used in xwsh (also known as
+# winterm).  Some capabilities that do not fit into the terminfo model
+# include the shift- and control-functionkeys:
+#
+# F1-F12 generate different codes when shift or control modifiers are used.
+# For example:
+#	F1      	\E[001q
+#	shift F1	\E[013q
+#	control-F1	\E[025q
+#
+# In application keypad mode, F9-F12 generate codes like vt100 PF1-PF4, i.e.,
+# \EOP to \EOS.  The shifted and control modifiers still do the same thing.
+#
+# The cursor keys also have different codes:
+#	control-up	\E[162q
+#	control-down	\E[165q
+#	control-left	\E[159q
+#	control-right	\E[168q
+#
+#	shift-up	\E[161q
+#	shift-down	\E[164q
+#	shift-left	\E[158q
+#	shift-right	\E[167q
+#
+#	control-tab	\[072q
+#
+# iris-ansi-net alias helps with IRIX does when you rsh to a remote system. 
+iris-ansi|iris-ansi-net|IRIS emulating 40 line ANSI terminal (almost VT100):\
+	:am:\
+	:co#80:it#8:li#40:\
+	:!2=\E[218q:#2=\E[143q:#4=\E[158q:%9=\E[209q:%f=\E[210q:\
+	:%i=\E[167q:&7=\E[217q:*4=\E[P:*7=\E[147q:@7=\E[146q:\
+	:@8=^M:AL=\E[%dL:DL=\E[%dM:DO=\E[%dB:F1=\E[011q:\
+	:F2=\E[012q:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:\
+	:UP=\E[%dA:al=\E[L:bl=^G:cb=\E[1K:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:ct=\E[3g:dl=\E[M:do=^J:\
+	:ho=\E[H:is=\E[?1l\E>\E[?7h\E[100g\E[0m\E7\E[r\E8:\
+	:k1=\E[001q:k2=\E[002q:k3=\E[003q:k4=\E[004q:k5=\E[005q:\
+	:k6=\E[006q:k7=\E[007q:k8=\E[008q:k9=\E[009q:k;=\E[010q:\
+	:kB=\E[Z:kD=\177:kI=\E[139q:kM=\E[146q:kN=\E[154q:\
+	:kP=\E[150q:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:le=\E[D:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:nw=\EE:\
+	:pk=\EP101;%d.y%s\E\:rc=\E8:sc=\E7:se=\E[m:sf=\ED:\
+	:so=\E[1;7m:sr=\EM:st=\EH:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:\
+	:ve=\E[9/y\E[12/y\E[=6l:vs=\E[10/y\E[=1h\E[=2l\E[=6h:
+iris-ansi-ap|IRIS ANSI in application-keypad mode:\
+	:@8=\EOM:F1=\E[011q:F2=\E[012q:is=\E[?1l\E=\E[?7h:\
+	:k9=\E[009q:k;=\E[010q:\
+	:tc=iris-ansi:
+
+# From the man-page, this is a quasi-vt100 emulator that runs on SGI's IRIX
+# (T.Dickey 98/1/24)
+iris-color|xwsh|IRIX ANSI with color:\
+	:NC#33:\
+	:DC=\E[%dP:IC=\E[%d@:ZH=\E[3m:ZR=\E[23m:cs=\E[%i%d;%dr:\
+	:ec=\E[%dX:ei=:im=:mh=\E[2m:r1=\Ec:\
+	:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\E8:sc=\E7:\
+	:u6=\E[%i%d;%dR:u7=\E[6n:u8=\E[?1;2c:u9=\E[c:ue=\E[24m:\
+	:tc=klone+color:tc=iris-ansi-ap:
+
+# (wsiris: this had extension capabilities
+#	:HS=\E7F2:HE=\E7F7:\
+#	:CT#2:CZ=*Bblack,red,green,yellow,blue,magenta,cyan,*Fwhite:
+# See the note on Iris extensions near the end of this file.  
+# Finally, removed suboptimal :cl:=\EH\EJ and added :do: & 
+# :vb: from BRL -- esr)
+wsiris|iris40|iris emulating a 40 line visual 50 (approximately):\
+	:am:bs:nc:pt:\
+	:co#80:it#8:kn#3:li#40:\
+	:al=\EL:bl=^G:cd=\EJ:ce=\EK:cl=\Ev:cm=\EY%+ %+ :dl=\EM:\
+	:do=\EB:ho=\EH:is=\E7B0\E7F7\E7C2\E7R3:k0=\E0:k1=\E1:\
+	:k2=\E2:k3=\E3:k4=\E4:k5=\E5:k6=\E6:k7=\E7:k8=\E8:k9=\E9:\
+	:kd=\EB:kl=\ED:kr=\EC:ku=\EA:le=^H:me=\E7F7:mh=\E7F2:nd=\EC:\
+	:nl=\EB:se=\E0@:sf=^J:so=\E9P:sr=\EI:ta=^I:ue=\E7R3\E0@:\
+	:up=\EA:us=\E7R2\E9P:vb=\E7F4\E7B1\013\E7F7\E7B0:ve=\E>:\
+	:vs=\E;:
+
+#### NeWS consoles
+#
+# Console terminal windows under the NeWS (Sun's Display Postscript windowing
+# environment).   Note: these have nothing to do with Sony's News workstation
+# line.
+#
+
+# Entry for NeWS's psterm from Eric Messick & Hugh Daniel
+# (psterm: unknown ":sl=\EOl:el=\ENl:" removed -- esr)
+psterm|psterm-basic|NeWS psterm-80x34:\
+	:am:bs:hs:km:ul:\
+	:co#80:it#8:li#34:\
+	:al=\EA:cd=\EB:ce=\EC:cl=^L:cm=\E%d;%d;:cs=\EE%d;%d;:\
+	:dc=\EF:dl=\EK:do=\EP:ei=\ENi:fs=\ENl:ho=\ER:i1=\EN*:\
+	:im=\EOi:kd=\E[B:kl=\E[D:kr=\E[C:ku=\E[A:le=\ET:ll=\EU:\
+	:mb=\EOb:md=\EOd:me=\EN*:mr=\EOr:nd=\EV:rc=^\:sc=^]:se=\ENo:\
+	:sf=\EW:so=\EOo:sr=\EX:ta=^I:te=\ENt:ti=\EOt:ts=\EOl:\
+	:ue=\ENu:up=\EY:us=\EOu:vb=\EZ:
+psterm-96x48|NeWS psterm 96x48:\
+	:co#96:li#48:tc=psterm:
+psterm-90x28|NeWS psterm 90x28:\
+	:co#90:li#28:tc=psterm:
+psterm-80x24|NeWS psterm 80x24:\
+	:co#80:li#24:tc=psterm:
+# This is a faster termcap for psterm.  Warning:  if you use this termcap,
+# some control characters you type will do strange things to the screen.
+# (psterm-fast: unknown ":sl=^Ol:el=^Nl:" -- esr)
+psterm-fast|NeWS psterm fast version (flaky ctrl chars):\
+	:am:bs:hs:km:ul:\
+	:co#80:it#8:li#34:\
+	:al=^A:cd=^B:ce=^C:cl=^L:cm=\004%d;%d;:cs=\005%d;%d;:dc=^F:\
+	:dl=^K:do=^P:ei=^Ni:fs=^Nl:ho=^R:i1=^N*:im=^Oi:kd=\E[B:\
+	:kl=\E[D:kr=\E[C:ku=\E[A:le=^T:ll=^U:mb=^Ob:md=^Od:me=^N*:\
+	:mr=^Or:nd=^V:rc=^\:sc=^]:se=^No:sf=^W:so=^Oo:sr=^X:ta=^I:\
+	:te=^Nt:ti=^Ot:ts=^Ol:ue=^Nu:up=^Y:us=^Ou:vb=^Z:
+
+#### NeXT consoles
+#
+# Use `glasstty' for the Workspace application
+#
+
+# From: Dave Wetzel <dave@turbocat.snafu.de> 22 Dec 1995
+next|NeXT console:\
+	:am:xt:\
+	:co#80:it#8:li#24:\
+	:bl=^G:ce=\E[K:cl=^L:cm=\E[%i%d;%dH:cr=^M:do=^J:ho=\E[H:\
+	:kb=^H:kd=^J:kl=^H:le=^H:me=\E[m:nd=\E[C:nw=^M^J:se=\E[4;1m:\
+	:sf=^J:so=\E[4;2m:ta=^I:up=\E[A:
+nextshell|NeXT Shell application:\
+	:am:\
+	:co#80:\
+	:bl=^G:cr=^M:do=^J:kb=^H:kd=^J:kl=^H:le=^H:nw=^M^J:ta=^I:
+
+#### SCO consoles
+#
+
+# SCO console and SOS-Syscons console for 386bsd
+# (scoansi: had unknown capabilities
+#	:Gc=N:Gd=K:Gh=M:Gl=L:Gu=J:Gv=\072:\
+#	:GC=E:GD=B:GH=D:GL=\64:GU=A:GV=\63:GR=C:
+#	:G1=?:G2=Z:G3=@:G4=Y:G5=;:G6=I:G7=H:G8=<:\
+#	:CW=\E[M:NU=\E[N:RF=\E[O:RC=\E[P:\
+#	:WL=\E[S:WR=\E[T:CL=\E[U:CR=\E[V:\
+# I renamed GS/GE/HM/EN/PU/PD/RT and added klone+sgr-dumb, based
+# on the :as:=\E[12m  -- esr)
+# SCO function keys and <acsc> corrected by Thomas Dickey.
+# In this description based on SCO's keyboard(HW) manpage list of default function key
+# values:
+#	F13-F24 are shifted F1-F12
+#	F25-F36 are control F1-F12
+#	F37-F48 are shift+control F1-F12
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+scoansi|SCO Extended ANSI standard crt:\
+	:am:eo:xo:\
+	:Co#8:co#80:it#8:li#25:pa#64:\
+	:@1=\E[E:@7=\E[F:AB=\E[4%p1%dm:AF=\E[3%p1%dm:F1=\E[W:\
+	:F2=\E[X:F3=\E[Y:F5=\E[a:F6=\E[b:F7=\E[c:F8=\E[d:F9=\E[e:\
+	:FA=\E[f:FB=\E[g:FC=\E[h:FD=\E[i:FE=\E[j:FF=\E[k:FG=\E[l:\
+	:FH=\E[m:FI=\E[n:FJ=\E[o:FK=\E[p:FL=\E[q:FM=\E[r:FN=\E[s:\
+	:FO=\E[t:FP=\E[u:FQ=\E[v:FR=\E[w:FS=\E[x:FT=\E[y:FU=\E[z:\
+	:FV=\E[@:FW=\E[[:FX=\E[\:FY=\E[]:FZ=\E[\136:Fa=\E[_:\
+	:Fb=\E[`:Fc=\E[{:\
+	:ac=0[5566778899\072\072;;<<==>>FFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX`ja0fxgqh2jYk?lZm@nEqDtCu4vAwBx3~y:\
+	:ae=\E[10m:al=\E[L:as=\E[12m:bt=\E[Z:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:dc=\E[P:dl=\E[M:do=\E[B:ei=:\
+	:ho=\E[H:ic=\E[@:im=:k1=\E[M:k2=\E[N:k3=\E[O:k4=\E[P:\
+	:k5=\E[Q:k6=\E[R:k7=\E[S:k8=\E[T:k9=\E[U:k;=\E[V:kB=\E[Z:\
+	:kI=\E[L:kN=\E[G:kP=\E[I:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:\
+	:kr=\E[C:ku=\E[A:le=\E[D:mb=\E[5m:md=\E[1m:me=\E[0;10m:\
+	:mk=\E[8m:mr=\E[7m:nd=\E[C:op=\E[37;40m:se=\E[m:sf=\E[S:\
+	:so=\E[7m:sr=\E[T:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:
+
+#### Sun consoles
+#
+
+# :is1: resets scrolling region in case a previous user had used "tset vt100"
+oldsun|Sun Microsystems Workstation console:\
+	:am:bs:km:mi:ms:\
+	:co#80:it#8:li#34:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:IC=\E[%d@:al=\E[L:bl=^G:\
+	:cd=\E[J:ce=\E[K:cl=^L:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:\
+	:dl=\E[M:do=\E[B:ei=:i1=\E[1r:ic=\E[@:im=:k1=\EOP:k2=\EOQ:\
+	:k3=\EOR:k4=\EOS:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:le=^H:me=\E[m:nd=\E[C:se=\E[m:sf=^J:so=\E[7m:ta=^I:up=\E[A:
+# From: Alexander Lukyanov <lav@video.yars.free.net>, 14 Nov 1995
+# :li: capability later corrected by J.T. Conklin <jtc@cygnus.com>
+# SGR 1, 4 aren't supported - removed bold/underline (T.Dickey 17 Jan 1998)
+sun-il|Sun Microsystems console with working insert-line:\
+	:am:km:ms:\
+	:co#80:li#34:\
+	:%7=\E[194z:&5=\E[193z:&8=\E[195z:@7=\E[220z:AL=\E[%dL:\
+	:DC=\E[%dP:DL=\E[%dM:F1=\E[234z:F2=\E[235z:IC=\E[%d@:\
+	:K2=\E[218z:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:cl=^L:\
+	:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:dl=\E[M:do=^J:ei=:ic=\E[@:im=:\
+	:k1=\E[224z:k2=\E[225z:k3=\E[226z:k4=\E[227z:k5=\E[228z:\
+	:k6=\E[229z:k7=\E[230z:k8=\E[231z:k9=\E[232z:k;=\E[233z:\
+	:kD=\177:kN=\E[222z:kP=\E[216z:kb=^H:kd=\E[B:kh=\E[214z:\
+	:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:md@:me=\E[m:mr=\E[7m:nd=\E[C:\
+	:r2=\E[s:\
+	:..sa=\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;m:\
+	:se=\E[m:sf=^J:so=\E[7m:ta=^I:u8=\E[1t:u9=\E[11t:ue@:\
+	:up=\E[A:us@:
+# On a SparcStation 5, :al:/:AL: flake out on the last line.
+# Unfortunately, without them the terminal has no way to scroll.
+sun-ss5|Sun SparcStation 5 console:\
+	:AL@:al@:tc=sun-il:
+# If you are using an SS5, change the sun definition to use sun-ss5.
+sun|sun1|sun2|Sun Microsystems Inc. workstation console:\
+	:tc=sun-il:
+
+# From: <john@ucbrenoir>  Tue Sep 24 13:14:44 1985
+sun-s|Sun Microsystems Workstation window with status line:\
+	:hs:\
+	:ds=\E]l\E\:fs=\E\:ts=\E]l:tc=sun:
+sun-e-s|sun-s-e|Sun Microsystems Workstation with status hacked for emacs:\
+	:hs:\
+	:ds=\E]l\E\:fs=\E\:ts=\E]l:tc=sun-e:
+sun-48|Sun 48-line window:\
+	:co#80:li#48:tc=sun:
+sun-34|Sun 34-line window:\
+	:co#80:li#34:tc=sun:
+sun-24|Sun 24-line window:\
+	:co#80:li#24:tc=sun:
+sun-17|Sun 17-line window:\
+	:co#80:li#17:tc=sun:
+sun-12|Sun 12-line window:\
+	:co#80:li#12:tc=sun:
+sun-1|Sun 1-line window for sysline:\
+	:es:hs:\
+	:co#80:li#1:\
+	:ds=^L:fs=\E[K:ts=^M:tc=sun:
+sun-e|sun-nic|sune|Sun Microsystems Workstation without insert character:\
+	:ei@:ic@:im@:\
+	:tc=sun:
+sun-c|sun-cmd|Sun Microsystems Workstation console with scrollable history:\
+	:li#35:\
+	:te=\E[>4h:ti=\E[>4l:tc=sun:
+
+#### Common Desktop Environment
+#
+
+# This ships with Sun's CDE in Solaris 2.5
+# Corrected Sun Aug 9 1998 by Alexander V. Lukyanov <lav@video.yars.free.net>
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+dtterm|CDE desktop terminal:\
+	:am:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:lm#0:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:ec=\E[%dX:\
+	:ei=\E[4l:ho=\E[H:im=\E[4h:\
+	:is=\E F\E>\E[?1l\E[?7h\E[?45l:k1=\E[11~:k2=\E[12~:\
+	:k3=\E[13~:k4=\E[14~:k5=\E[15~:k6=\E[17~:k7=\E[18~:\
+	:k8=\E[19~:k9=\E[20~:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:\
+	:kb=^H:kd=\E[B:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mb=\E[5m:\
+	:md=\E[1m:me=\E[m\017:mh=\E[2m:mr=\E[7m:nd=\E[C:nw=\EE:\
+	:rc=\E8:sc=\E7:se=\E[22;27m:sf=\ED:so=\E[2;7m:sr=\EM:\
+	:st=\EH:ta=^I:ue=\E[24m:up=\E[A:us=\E[4m:vb=\E[?5h\E[?5l:\
+	:ve=\E[?25h:vi=\E[?25l:
+
+#### Mach
+#
+
+# From: Matthew Vernon <mcv21@pick.sel.cam.ac.uk>
+mach|Mach Console:\
+	:am:km:\
+	:co#80:it#8:li#25:\
+	:@7=\E[Y:AL=\E[%dL:DL=\E[%dM:DO=\E[%dB:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:cl=\Ec:\
+	:cm=\E[%i%d;%dH:cr=^M:dl=\E[M:do=^J:ho=\E[H:k1=\EOP:\
+	:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\EOT:k6=\EOU:k7=\EOV:k8=\EOW:\
+	:k9=\EOX:k;=\EOY:kD=\E[9:kH=\E[F:kI=\E[@:kN=\E[U:kP=\E[V:\
+	:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:\
+	:mb=\E[5m:md=\E[1m:me=\E[0m:mr=\E[7m:nd=\E[C:nw=^M^J:\
+	:se=\E[0m:sf=^J:so=\E[7m:ta=^I:up=\E[A:
+mach-bold|Mach Console with bold instead of underline:\
+	:ue=\E[0m:us=\E[1m:\
+	:tc=mach:
+
+#### OSF Unix
+#
+
+# OSF/1 1.1 Snapshot 2
+pmcons|pmconsole|PMAX console:\
+	:am:\
+	:co#128:li#57:\
+	:bl=^G:cl=^L:cr=^M:do=^J:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+	:kd=\E[B:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:sf=^J:ta=^I:up=^K:
+
+######## UNIX VIRTUAL TERMINALS AND TELNET CLIENTS
+#
+
+#### FSF virtual terminal types
+#
+
+# The codes supported by the term.el terminal emulation in GNU Emacs 19.30 
+eterm|gnu emacs term.el terminal emulation:\
+	:am:mi:xn:\
+	:co#80:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:al=\E[L:bl=^G:cb=\E[1K:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:dc=\E[P:dl=\E[M:do=^J:ei=\E[4l:ho=\E[H:\
+	:im=\E[4h:le=^H:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:se=\E[m:\
+	:sf=^J:so=\E[7m:ta=^I:te=\E[2J\E[?47l\E8:ti=\E7\E[?47h:\
+	:ue=\E[m:up=\E[A:us=\E[4m:
+
+# Entries for use by the `screen' program by Juergen Weigert, 
+# Michael Schroeder, Oliver Laumann.  The screen and
+# screen-w entries came with version 3.7.1.  The screen2 and screen3 entries
+# come from University of Wisconsin and may be older.
+# (screen: added :ve: on ANSI model -- esr)
+# (screen: added <el1> -- TD)
+
+screen|VT 100/ANSI X3.64 virtual terminal:\
+	:am:km:mi:ms:xn:\
+	:Co#8:co#80:it#8:li#24:pa#64:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:F1=\E[23~:\
+	:F2=\E[24~:IC=\E[%d@:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:\
+	:ac=++\054\054--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=^O:al=\E[L:as=^N:bl=^G:bt=\E[Z:cb=\E[1K:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:eA=\E(B\E)0:ei=\E[4l:\
+	:ho=\E[H:im=\E[4h:is=\E)0:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+	:k5=\E[15~:k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:\
+	:k;=\E[21~:kD=\E[3~:kH=\E[4~:kI=\E[2~:kN=\E[6~:kP=\E[5~:\
+	:kb=^H:kd=\EOB:ke=\E[?1l\E>:kh=\E[1~:kl=\EOD:kr=\EOC:\
+	:ks=\E[?1h\E=:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:me=\E[m:\
+	:mr=\E[7m:nd=\E[C:nw=\EE:r2=\Ec:rc=\E8:sc=\E7:se=\E[23m:\
+	:sf=^J:so=\E[3m:sr=\EM:st=\EH:ta=^I:ue=\E[24m:up=\EM:\
+	:us=\E[4m:vb=\Eg:ve=\E[34h\E[?25h:vi=\E[?25l:vs=\E[34l:\
+	:tc=ecma+color:
+
+screen-w|VT 100/ANSI X3.64 virtual terminal with 132 cols:\
+	:co#132:tc=screen:
+
+screen2|old VT 100/ANSI X3.64 virtual terminal:\
+	:co#80:it#8:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:al=\E[L:bt=\E[Z:cd=\E[J:\
+	:ce=\E[K:cl=\E[2J\E[H:cm=\E[%i%d;%dH:cr=^M:ct=\E[3g:\
+	:dc=\E[P:dl=\E[M:do=\E[B:ei=\E[4l:ic=:im=\E[4h:k0=\E~:\
+	:k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:k6=\EP:k7=\EQ:k8=\ER:\
+	:k9=\E0I:kb=^H:kd=\EB:kh=\EH:kl=\ED:kr=\EC:ku=\EA:le=^H:\
+	:me=\E[m:nd=\E[C:nw=^M^J:r1=\Ec:rc=\E8:sc=\E7:se=\E[23m:\
+	:sf=^J:so=\E[3m:sr=\EM:st=\EH:ta=^I:ue=\E[24m:up=\E[A:\
+	:us=\E[4m:
+# (screen3: removed unknown ":xv:LP:G0:" -- esr)
+screen3|older VT 100/ANSI X3.64 virtual terminal:\
+	:km:mi:ms:\
+	:co#80:it#8:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:al=\E[L:bl=^G:bt=\E[Z:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:ei=\E[4l:\
+	:ho=\E[H:im=\E[4h:is=\E)0:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+	:kb=^H:kd=\EOB:ke=\E>:kl=\EOD:kr=\EOC:ks=\E=:ku=\EOA:le=^H:\
+	:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:nw=\EE:r1=\Ec:\
+	:rc=\E8:sc=\E7:se=\E[23m:sf=^J:so=\E[3m:sr=\EM:st=\EH:ta=^I:\
+	:ue=\E[24m:up=\EM:us=\E[4m:
+
+# Francesco Potorti <F.Potorti@cnuce.cnr.it>:
+# NCSA telnet is one of the most used telnet clients for the Macintosh.  It has
+# been maintained until recently by the National Center for Supercomputer
+# Applications, and it is feature rich, stable and free.  It can be downloaded
+# from www.ncsa.edu.  This terminfo description file is based on xterm-vt220,
+# xterm+sl, and the docs at NCSA.  It works well.
+#
+# NCSA Telnet 2.6 for Macintosh in vt220 8-bit emulation mode
+# The terminal options should be set as follows:
+#         Xterm sequences ON
+#         use VT wrap mode ON
+#         use Emacs arrow keys OFF
+#         CTRL-COMND is Emacs meta ON
+#         8 bit mode ON
+#         answerback string: "ncsa-vt220-8"
+#         setup keys: all disabled
+#
+# Application mode is not used.
+#
+# Other special mappings:
+#	Apple		VT220
+#	HELP 		Find
+#	HOME		Insert here
+#	PAGEUP		Remove
+#	DEL		Select
+#	END		Prev Screen
+#	PAGEDOWN	Next Screen
+#
+# Though it supports ANSI color, NCSA Telnet uses color to represent blinking
+# text.
+#
+# The status-line manipulation is a mapping of the xterm-compatible control
+# sequences for setting the window-title.  So you must use tsl and fsl in
+# pairs, since the latter ends the string that is loaded to the window-title.
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+ncsa-m|ncsa-vt220-8|NCSA Telnet 2.6 for Macintosh in vt220-8 mode:\
+	:am:hs:km:mi:ms:xn:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:\
+	:ds=\E]0;\007:ei=\E[4l:fs=^G:ho=\E[H:\
+	:if=/usr/share/tabset/vt100:im=\E[4h:\
+	:is=\E7\E[r\E[m\E[?7h\E[?1;4;6l\E[4l\E8\E>:k1=\E[17~:\
+	:k2=\E[18:k3=\E[19~:k4=\E[20~:k5=\E[21~:k6=\E23~:\
+	:k7=\E[24~:k8=\E[25~:k9=\E[26~:kD=\E[4~:kN=\E[6~:kP=\E[3~:\
+	:kb=^H:kd=\E[B:kh=\E[2~:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:\
+	:mb=\E[5m:md=\E[1m:me=\E[m\017:mr=\E[7m:nd=\E[C:rc=\E8:\
+	:sc=\E7:se=\E[27m:sf=\n:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:te=\E[2J\E8:ti=\E7:ts=\E]0;:ue=\E[24m:up=\E[A:us=\E[4m:\
+	:vb=\E[?5h\E[?5l:ve=\E[?25h:vi=\E[?25l:
+ncsa|NCSA Telnet 2.7 for Macintosh in vt220-8 mode:\
+	:tc=ncsa-m:tc=klone+color:
+ncsa-ns|NCSA Telnet 2.7 for Macintosh in vt220-8 mode:\
+	:hs@:\
+	:ds@:fs@:ts@:tc=ncsa:
+ncsa-m-ns|NCSA Telnet 2.6 for Macintosh in vt220-8 mode:\
+	:hs@:\
+	:ds@:fs@:ts@:tc=ncsa-m:
+# alternate -TD:
+# The documented function-key mapping refers to the Apple Extended Keyboard
+# (e.g., NCSA Telnet's F1 corresponds to a VT220 F6).  We use the VT220-style
+# codes, however, since the numeric keypad (VT100) PF1-PF4 are available on
+# some keyboards and many applications require these as F1-F4.
+#
+ncsa-vt220|NCSA Telnet using vt220-compatible function keys:\
+	:F1=\E[23~:F2=\E[24~:F3=\E[25~:F4=\E[26~:F5=\E[28~:\
+	:F6=\E[29~:F7=\E[31~:F8=\E[32~:F9=\E[33~:FA=\E[34~:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k6=\E[17~:k7=\E[18~:\
+	:k8=\E[19~:k9=\E[20~:k;=\E[21~:\
+	:tc=ncsa:
+
+#### Pilot Pro Palm-Top
+#
+
+# From: Jason Downs <downsj@downsj.com>, 15 Jun 1997 (Top Gun Telnet's author)
+pilot|tgtelnet|Top Gun Telnet on the Palm Pilot Professional:\
+	:am:xn:\
+	:co#39:li#16:\
+	:bl=^G:cl=\Ec:cm=\Em%+ %+ :cr=^M:do=^J:ho=\Em  :kN=^L:kP=^K:\
+	:kb=^H:kd=^J:kl=^H:le=^H:nw=\Em~ :se=\EB:sf=^J:so=\Eb:ta=^I:
+
+######## NON-UNIX CONSOLES
+#
+
+#### MGR
+#
+# MGR is a Bell Labs window system lighter-weight than X.
+# These entries describe MGR's xterm-equivalent. 
+# They are courtesy of Vincent Broman <broman@nosc.mil> 14 Jan 1997 
+#
+
+mgr|Bellcore MGR (non X) window system terminal emulation:\
+	:am:km:\
+	:AL=\E%da:DC=\E%dE:DL=\E%dd:IC=\E%dA:RA=\E5S:SA=\E5s:\
+	:al=\Ea:bl=^G:cd=\EC:ce=\Ec:cl=^L:cm=\E%r%d;%dM:cr=^M:\
+	:cs=\E%d;%dt:dc=\EE:dl=\Ed:do=\Ef:ei=:hd=\E1;2f:hu=\E1;2u:\
+	:ic=\EA:im=:kb=^H:kd=\E[B:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:\
+	:md=\E2n:me=\E0n:mr=\E1n:nd=\Er:nw=^M^J:se=\E0n:sf=^J:\
+	:so=\E1n:ta=^I:ue=\E0n:up=\Eu:us=\E4n:ve=\Eh:vi=\E9h:\
+	:vs=\E0h:
+mgr-sun|Mgr window with Sun keyboard:\
+	:%1=\E[207z:%6=\E[198z:&8=\E[195z:@0=\E[200z:@5=\E197z:\
+	:@7=\E[220z:@8=\E[250z:F1=\E[234z:F2=\E[235z:K1=\E[214z:\
+	:K2=\E[218z:K3=\E[216z:K4=\E[220z:K5=\E[222z:k1=\E[224z:\
+	:k2=\E[225z:k3=\E[226z:k4=\E[227z:k5=\E[228z:k6=\E[229z:\
+	:k7=\E[230z:k8=\E[231z:k9=\E[232z:k;=\E[233z:kN=\E[222z:\
+	:kP=\E[216z:kh=\E[214z:\
+	:tc=mgr:
+mgr-linux|Mgr window with Linux keyboard:\
+	:@7=\E[4~:F1=\E[23~:F2=\E[24~:K1=\E[H:K2=\E[G:K3=\E[5~:\
+	:K4=\E[Y:K5=\E[6~:k0=\E[[J:k1=\E[[A:k2=\E[[B:k3=\E[[C:\
+	:k4=\E[[D:k5=\E[[E:k6=\E[17~:k7=\E[18~:k8=\E[19~:\
+	:k9=\E[20~:k;=\E[21~:kD=\E[3~:kN=\E[6~:kP=\E[5~:kh=\E[1~:tc=mgr:
+
+#### BeOS
+#
+# BeOS entry for Terminal program Seems to be almost ANSI
+beterm|BeOS Terminal:\
+	:am:eo:mi:ms:xn:xo:\
+	:Co#8:NC#5:co#80:it#8:li#25:pa#64:\
+	:&7=^Z:@7=\E[4~:AB=\E[4%p1%dm:AF=\E[3%p1%dm:AL=\E[%dL:\
+	:DC=\E[%dP:DL=\E[%dM:F1=\E[21~:F2=\E[22~:IC=\E[%d@:\
+	:Sb=\E[%+(m:Sf=\E[%+^^m:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:\
+	:ch=\E[%i%dG:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:cv=\E[%i%dd:dc=\E[P:dl=\E[M:do=^J:\
+	:ei=\E[4l:ho=\E[H:ic=\E[@:im=\E[4h:k1=\E[11~:k2=\E[12~:\
+	:k3=\E[13~:k4=\E[14~:k5=\E[15~:k6=\E[16~:k7=\E[17~:\
+	:k8=\E[18~:k9=\E[19~:k;=\E[20~:kD=\E[3~:kI=\E[2~:kN=\E[6~:\
+	:kP=\E[5~:kb=^H:kd=\E[B:kh=\E[1~:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:le=^H:md=\E[1m:me=\E[0;10m:mr=\E[7m:nd=\E[C:nw=^M^J:\
+	:op=\E[m:r1=\Ec:rc=\E8:sc=\E7:se=\E[m:sf=^J:so=\E[7m:sr=\EM:\
+	:st=\EH:ta=^I:u6=\E[%i%d;%dR:u7=\E[6n:ue=\E[24m:up=\E[A:\
+	:us=\E[4m:
+
+#### QNX
+#
+
+# QNX 4.0 Console
+# Michael's original version of this entry had <am@>, :ti=\Ei:,
+# :te=\Eh\ER:; this was so terminfo applications could write the lower
+# right corner without triggering a scroll.  The ncurses terminfo library can
+# handle this case with the :ic: capability, and prefers :am: for better
+# optimization.  Bug: The <op> capability resets attributes.
+# From: Michael Hunter <mphunter@qnx.com> 30 Jul 1996
+# (removed: :sa=%?%p1%t\E<%;%p2%t\E[%;%p3%t\E(%;%p4%t\E{%;%p6%t\E<%;,:)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+qnx|qnx4|qnx console:\
+	:km:mi:ms:xt:\
+	:co#80:it#4:li#25:\
+	:al=\EE:bl=^G:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :cr=^M:\
+	:dc=\Ef:dl=\EF:do=^J:ei=:ho=\EH:ic=\Ee:im=:k1=\377\201:\
+	:k2=\377\202:k3=\377\203:k4=\377\204:k5=\377\205:\
+	:k6=\377\206:k7=\377\207:k8=\377\210:k9=\377\211:\
+	:kD=\377\254:kI=\377\253:kN=\377\252:kP=\377\242:\
+	:kd=\377\251:kh=\377\240:kl=\377\244:kr=\377\246:\
+	:ku=\377\241:le=^H:mb=\E{:md=\E<:me=\E}\E]\E>\E):mr=\E(:\
+	:nd=\EC:rp=\Eg%r%+ %.:se=\E):sf=^J:so=\E(:sr=\EI:ta=^I:\
+	:te=\Eh\ER:ti=\Ei:ue=\E]:up=\EA:us=\E[:ve=\Ey1:vi=\Ey0:\
+	:vs=\Ey2:
+
+# From: Federico Bianchi <bianchi@pc-arte2.arte.unipi.it>, 1 Jul 1998
+# (esr: commented out <scp> and :te: to avoid warnings.)
+# (TD: derive from original qnx4 entry)
+qnxt2|qnx 2.15 serial terminal:\
+	:am:\
+	:!3@:%h@:%j@:&7@:Sb@:Sf@:dc@:ei=:ic@:im=:rp@:se=\E>:so=\E<:te@:ti@:\
+	:ve@:vi@:vs@:\
+	:tc=qnx4:
+
+#### DOS ANSI.SYS variants
+#
+# This completely describes the sequences specified in the DOS 2.1 ANSI.SYS
+# documentation (except for the keyboard key reassignment feature, which
+# doen't fit the <pfkey> model well).  The klone+acs sequences were valid
+# though undocumented.  The <pfkey> capability is untested but should work for
+# keys F1-F10 (%p1 values outside this range will yield unpredictable results).
+# From: Eric S. Raymond <esr@snark.thyrsus.com> Nov 7 1995
+ansi.sys-old|ANSI.SYS under PC-DOS 2.1:\
+	:am:bs:mi:ms:xo:\
+	:co#80:li#25:\
+	:RA=\E[?7l:SA=\E[?7h:ce=\E[k:cl=\E[2J:cm=\E[%i%d;%dH:\
+	:do=\E[B:ho=\E[H:is=\E[m\E[?7h:kd=^J:kh=^^:kl=^H:kr=^L:\
+	:ku=^K:le=^H:nd=\E[C:pk=\E[0;%+:;"%s":rc=\E[u:sc=\E[s:\
+	:u6=\E[%i%d;%dR:u7=\E[6n:up=\E[A:\
+	:tc=klone+color:tc=klone+sgr:
+ansi.sys|ANSI.SYS 3.1 and later versions:\
+	:ce=\E[K:tc=ansi.sys-old:
+
+#
+# Define IBM PC keypad keys for vi as per MS-Kermit while using ANSI.SYS.
+# This should only be used when the terminal emulator cannot redefine the keys.
+# Since redefining keys with ansi.sys also affects PC-DOS programs, the key
+# definitions must be restored.  If the terminal emulator is quit while in vi
+# or others using :ks:/:ke:, the keypad will not be defined as per PC-DOS.
+# The PgUp and PgDn are prefixed with ESC so that tn3270 can be used on Unix
+# (^U and ^D are already defined for tn3270).  The ESC is safe for vi but it
+# does "beep".  ESC ESC i is used for Ins to avoid tn3270 ESC i for coltab.
+# Note that :kl: is always BS, because PC-dos can tolerate this change.
+# Caution: vi is limited to 256 string bytes, longer crashes or weirds out vi.
+# Consequently the End keypad key could not be set (it is relatively safe and
+# actually useful because it sends ^@ O, which beeps and opens a line above).
+ansi.sysk|ansisysk|PC-DOS 3.1 ANSI.SYS with keypad redefined for vi:\
+	:is=U2 PC-DOS 3.1 ANSI.SYS with keypad redefined for vi 9-29-86\n\E[;75;8p:\
+	:ke=\E[;71;0;71p\E[;72;0;72p\E[;73;0;73p\E[;77;0;77p\E[;80;0;80p\E[;81;0;81p\E[;82;0;82p\E[;83;0;83p:\
+	:ks=\E[;71;30p\E[;72;11p\E[;73;27;21p\E[;77;12p\E[;80;10p\E[;81;27;4p\E[;82;27;27;105p\E[;83;127p:\
+	:tc=ansi.sys:
+#
+# Adds ins/del line/character, hence vi reverse scrolls/inserts/deletes nicer.
+nansi.sys|nansisys|PC-DOS Public Domain NANSI.SYS:\
+	:al=\E[1L:dc=\E[1P:dl=\E[1M:ei=:ic=\E[1@:im=:\
+	:is=U3 PC-DOS Public Domain NANSI.SYS 9-23-86\n:tc=ansi.sys:
+#
+# See ansi.sysk and nansi.sys above.
+nansi.sysk|nansisysk|PC-DOS Public Domain NANSI.SYS with keypad redefined for vi:\
+	:al=\E[1L:dc=\E[1P:dl=\E[1M:ei=:ic=\E[1@:im=:\
+	:is=U4 PC-DOS Public Domain NANSI.SYS with keypad redefined for vi 9-29-86\n\E[;75;8p:tc=ansi.sysk:
+
+#### OS/2
+#
+
+# Except for the "-emx" suffixes, these are as distributed with EMX 0.9b,
+# a Unix-style environment used on OS/2.  (Note that the suffix makes some
+# names longer than 14 characters, the nominal maximum).
+#
+# Removed: rmacs=\E[10m, smacs=\E[11m, because OS/2 does not implement acs.
+ansi-emx|ANSI.SYS color:\
+	:am:eo:mi:ms:ut:xn:xo:\
+	:Co#16:co#80:it#8:li#25:pa#64:\
+	:&7=^Z:AB=\E[4%p1%dm:AF=\E[3%p1%dm:DC=\E[%dp:IC=\E[%d@:\
+	:K2=\E[G:S2=\E[11m:S3=\E[10m:bl=^G:cd=\E[J:ce=\E[K:\
+	:cl=\E[1;33;44m\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:ct=\E[3g:\
+	:do=^J:ei=\E[4l:ho=\E[H:ic=\E[@:im=\E[4h:k0=\0D:k1=\0;:\
+	:k2=\0<:k3=\0=:k4=\0>:k5=\0?:k6=\0@:k7=\0A:k8=\0B:k9=\0C:\
+	:kH=\0O:kI=\0R:kN=\0Q:kP=\0I:kb=^H:kd=\0P:kh=\0G:kl=\0K:\
+	:kr=\0M:ku=\0H:le=^H:mb=\E[5m:md=\E[1m:\
+	:me=\E[0m\E[1;33;44m:mr=\E[5;37;41m:nd=\E[C:nw=^M^J:\
+	:r1=\Ec:se=\E[0;44m\E[1;33m:sf=^J:so=\E[0;31;47m:st=\EH:\
+	:ta=^I:u8=\E[?6c:u9=\E[c:ue=\E[0;44m\E[1;33m:up=\E[A:\
+	:us=\E[1;31;44m:vb=\E[?5h\E[?5l:ve=\E[?25h:vi=\E[?25l:
+ansi-color-2-emx|ANSI.SYS color 2:\
+	:am:eo:mi:ms:ut:xn:xo:\
+	:Co#16:co#80:it#8:li#25:pa#64:\
+	:&7=^Z:AB=\E[4%p1%dm:AF=\E[3%p1%dm:DC=\E[%dp:IC=\E[%d@:\
+	:K2=\E[G:S2=\E[11m:S3=\E[10m:bl=^G:cd=\E[J:ce=\E[K:\
+	:cl=\E[0;37;44m\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:ct=\E[3g:\
+	:do=^J:ei=\E[4l:ho=\E[H:ic=\E[@:im=\E[4h:k0=\0D:k1=\0;:\
+	:k2=\0<:k3=\0=:k4=\0>:k5=\0?:k6=\0@:k7=\0A:k8=\0B:k9=\0C:\
+	:kH=\0O:kI=\0R:kN=\0Q:kP=\0I:kb=^H:kd=\0P:kh=\0G:kl=\0K:\
+	:kr=\0M:ku=\0H:le=^H:mb=\E[5m:md=\E[1m:me=\E[0;37;44m:\
+	:mr=\E[1;37;46m:nd=\E[C:nw=^M^J:r1=\Ec:se=\E[0;37;44m:\
+	:sf=^J:so=\E[1;37;46m:st=\EH:ta=^I:u8=\E[?6c:u9=\E[c:\
+	:ue=\E[0;37;44m:up=\E[A:us=\E[1;36;44m:vb=\E[?5h\E[?5l:\
+	:ve=\E[?25h:vi=\E[?25l:
+ansi-color-3-emx|ANSI.SYS color 3:\
+	:am:eo:mi:ms:ut:xn:xo:\
+	:Co#16:co#80:it#8:li#25:pa#64:\
+	:&7=^Z:AB=\E[4%p1%dm:AF=\E[3%p1%dm:DC=\E[%dp:IC=\E[%d@:\
+	:K2=\E[G:S2=\E[11m:S3=\E[10m:bl=^G:cd=\E[J:ce=\E[K:\
+	:cl=\E[0;37;40m\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:ct=\E[3g:\
+	:do=^J:ei=\E[4l:ho=\E[H:ic=\E[@:im=\E[4h:k0=\0D:k1=\0;:\
+	:k2=\0<:k3=\0=:k4=\0>:k5=\0?:k6=\0@:k7=\0A:k8=\0B:k9=\0C:\
+	:kH=\0O:kI=\0R:kN=\0Q:kP=\0I:kb=^H:kd=\0P:kh=\0G:kl=\0K:\
+	:kr=\0M:ku=\0H:le=^H:mb=\E[5m:md=\E[1m:me=\E[0;10m:\
+	:mr=\E[1;37;46m:nd=\E[C:nw=^M^J:r1=\Ec:se=\E[0;37;40m:\
+	:sf=^J:so=\E[1;37;46m:st=\EH:ta=^I:u8=\E[?6c:u9=\E[c:\
+	:ue=\E[0;37;40m:up=\E[A:us=\E[0;36;40m:vb=\E[?5h\E[?5l:\
+	:ve=\E[?25h:vi=\E[?25l:
+mono-emx|stupid monochrome ansi terminal with only one kind of emphasis:\
+	:am:\
+	:co#80:it#8:li#24:\
+	:K2=\E[G:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:do=\E[B:\
+	:ho=\E[H:k0=\0D:k1=\0;:k2=\0<:k3=\0=:k4=\0>:k5=\0?:k6=\0@:\
+	:k7=\0A:k8=\0B:k9=\0C:kH=\0O:kI=\0R:kN=\0Q:kP=\0I:kb=^H:\
+	:kd=\0P:kh=\0G:kl=\0K:kr=\0M:ku=\0H:le=\E[D:me=\E[0m:\
+	:mr=\E[7m:nd=\E[C:nw=^M^J:ta=^I:up=\E[A:
+
+# Use this for cygwin32 (tested with beta 19.1)
+# underline is colored bright magenta
+# shifted kf1-kf12 are kf11-kf22
+cygwin|ansi emulation for cygwin32:\
+	:@7=\E[4~:F1=\E[23~:F2=\E[24~:F3=\E[25~:F4=\E[26~:\
+	:F5=\E[28~:F6=\E[29~:F7=\E[31~:F8=\E[32~:F9=\E[33~:\
+	:FA=\E[34~:RA@:SA@:k1=\E[[A:k2=\E[[B:k3=\E[[C:k4=\E[[D:\
+	:k5=\E[[E:k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:\
+	:k;=\E[21~:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:kd=\E[B:\
+	:kh=\E[1~:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:tc=ansi.sys:
+
+
+#### Windows NT
+#
+# This entry fits the Windows NT console when the _POSIX_TERM environment
+# variable is set to 'on'.  While the Windows NT POSIX console is seldom used,
+# the Telnet client supplied with both the Windows for WorkGroup 3.11 TCP/IP
+# stack and the Win32 (i.e., Windows 95 and Windows NT 3.1 or later) operating
+# systems is not, and (surprise!) they match very well.
+#
+# See:  MS Knowledge Base item Q108581, dated 13-MAY-1997, titled "Setting Up
+# VI POSIX Editor for Windows NT 3.1".  True to Microsoft form, not only
+# are the installation instructions a pile of mind-numbing bureaucratese,
+# but the termcap entry is actually broken and unusable as given; the :do:
+# capability is misspelled "d".
+#
+# To use this, you need to a bunch of environment variables: 
+#
+# SET _POSIX_TERM=on
+# SET TERM=ansi
+# SET TERMCAP=location of termcap file in POSIX file format
+# which is case-sensitive.
+# e.g. SET TERMCAP=//D/RESKIT35/posix/termcap
+# SET TMP=//C/TEMP
+#
+# Important note: setting the TMP environment variable in POSIX style renders
+# it incompatible with a lot of other applications, including Visual C++. So
+# you should have a separate command window just for vi. All the other
+# variables may be permanently set in the Control Panel\System applet. 
+#
+# You can find out more about the restrictions of this facility at
+# <http://www.nentug.org/unix-to-nt/ntposix.htm>.
+#
+# From: Federico Bianchi <bianchi@magna.cisid.unipi.it>, 15 Jan 1997
+ansi-nt|psx_ansi|Microsoft Windows NT console POSIX ANSI mode:\
+	:am:bw:ms:\
+	:co#80:it#8:li#25:\
+	:bl=^G:cd=\E[J:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:cr=^M:do=^J:\
+	:ho=\E[H:kb=^H:kd=\E[V:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:\
+	:me=\E[0m:mr=\E[7m:nd=\E[C:nw=\r\E[S:rc=\E[u:sc=\E[s:\
+	:se=\E[m:sf=\E[S:so=\E[7m:sr=\E[T:ta=^I:up=\E[A:
+# From: jew@venus.sunquest.com
+# Date: 19 Feb 93 23:41:07 GMT
+# Here's  a  combination of  ansi and  vt100 termcap
+# entries   that  works  nearly   perfectly  for  me
+# (Gateway 2000 Handbook and Microsoft Works 3.0):
+pcmw|PC running Microsoft Works:\
+	:am:xn:\
+	:co#80:it#8:li#24:vt#3:\
+	:bl=^G:cd=50\E[J:ce=3\E[K:cl=50\E[;H\E[2J:\
+	:cm=5\E[%i%d;%dH:cr=^M:ct=2\E[3g:do=^J:ho=\E[H:\
+	:is=\E[1;24r\E[24;1H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+	:kb=^H:kd=\EOB:kl=\EOD:kr=\EOC:ku=\EOA:le=^H:mb=2\E[5m:\
+	:md=2\E[1m:me=2\E[m:mr=2\E[7m:nd=2\E[C:nw=5\r\ED:\
+	:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\E8:\
+	:rf=/usr/share/lib/tabset/vt100:sc=\E7:se=2\E[m:sf=5\ED:\
+	:so=2\E[7m:sr=5\EM:st=2\EH:ta=^I:ue=2\E[m:up=2\E[A:\
+	:us=2\E[4m:
+
+######## COMMON TERMINAL TYPES
+#
+# This section describes terminal classes and maker brands that are still
+# quite common, but have proprietary command sets not blessed by ANSI.
+#
+
+#### Lear-Siegler (adm)
+#
+# These guys are long since out of the terminals business, but
+# in 1995 many current terminals still have an adm type as one of their
+# emulations (usually their stupidest, and usually labeled adm3, though
+# these `adm3' emulations normally have adm3a+ capabilities).
+#
+# WARNING: Some early ADM terminals (including the ADM3 and ADM5) had a 
+# `diagnostic feature' that sending them a ^G while pin 22 (`Ring Indicator')
+# was being held to ground would trigger a send of the top line on the screen.
+# A quick fix might be to drop back to a cheesy 4-wire cable with pin 22
+# hanging in the air. (Thanks to Eric Fischer, <eric@fudge.uchicago.edu>,
+# for clearing up this point.)
+#
+
+adm1a|adm1|lsi adm1a:\
+	:am:\
+	:co#80:li#24:\
+	:bl=^G:cl=\E;:cm=\E=%+ %+ :cr=^M:do=^J:ho=^^:le=^H:nd=^L:\
+	:sf=^J:up=^K:
+adm2|lsi adm2:\
+	:am:bs:\
+	:co#80:li#24:\
+	:al=\EE:bl=^G:cd=\EY:ce=\ET:cl=\E;:cm=\E=%+ %+ :cr=^M:\
+	:dc=\EW:dl=\ER:do=^J:ei=:ho=^^:ic=\EQ:im=:kd=^J:kh=^^:kl=^H:\
+	:kr=^L:ku=^K:le=^H:nd=^L:sf=^J:up=^K:
+# (adm3: removed obsolete ":ma=^K^P:" -- esr)
+adm3|lsi adm3:\
+	:am:bs:\
+	:co#80:li#24:\
+	:bl=^G:cl=^Z:cr=^M:do=^J:le=^H:sf=^J:
+# The following ADM-3A switch settings are assumed for normal operation:
+#	SPACE		U/L_DISP	CLR_SCRN	24_LINE
+#	CUR_CTL		LC_EN		AUTO_NL		FDX
+# Other switches may be set for operator convenience or communication
+# requirements.  I recommend
+#	DISABLE_KB_LOCK	LOCAL_OFF	103		202_OFF
+#	ETX_OFF		EOT_OFF
+# Most of these terminals required an option ROM to support lower case display.
+# Open the case and look at the motherboard; if you see an open 24-pin DIP
+# socket, you may be out of luck.
+#
+# (adm3a: some capabilities merged in from BRl entry -- esr)
+adm3a|lsi adm3a:\
+	:am:bs:\
+	:co#80:li#24:\
+	:bl=^G:cl=1\032:cm=\E=%+ %+ :cr=^M:do=^J:ho=^^:kd=^J:kl=^H:\
+	:kr=^L:ku=^K:le=^H:ma=^K^P:nd=^L:nl=^J:r1=^N:rs=^N:sf=^J:\
+	:up=^K:
+adm3a+|adm3a plus:\
+	:kb=^H:tc=adm3a:
+# (adm5: removed obsolete ":ma=^Hh^Jj^Kk^Ll^^H:" & duplicate ":do=^J:" -- esr)
+adm5|lsi adm5:\
+	:sg#1:\
+	:bl=^G:cd=\EY:ce=\ET:cr=^M:do=^J:kb=^H:kh=^^:se=\EG:so=\EG:tc=adm3a+:
+# A lot of terminals other than adm11s use these.  Wherever you see
+# use=adm+sgr with some of its capabilities disabled, try the
+# disabled ones.  They may well work but not have been documented or
+# expressed in the using entry.  We'd like to cook up an :sa: but the
+# :ae:/:as: sequences of the using entries vary too much.
+adm+sgr|adm style highlight capabilities:\
+	:me=\EG0:mk=\EG1:mr=\EG4:se=\EG0:so=\EG4:ue=\EG0:us=\EG8:
+# LSI ADM-11 from George William Hartwig, Jr. <geo@BRL-TGR.ARPA> via BRL
+# Status line additions from Stephen J. Muir <stephen%comp.lancs.ac.uk@ucl-cs>
+# :kh: from <stephen%comp.lancs.ac.uk@ucl-cs.arpa>.  :cl: could also
+# be ^Z, according to his entry.
+# (adm11: :us:=\EG4 was obviously erroneous because it also said
+# :mr:=\EG4.  Looking at other ADMs confirms this -- esr)
+adm11|LSI ADM-11:\
+	:am:bs:hs:\
+	:co#80:kn#8:li#24:\
+	:bl=^G:cd=\EY:ce=\ET:cl=\E*:cm=\E=%+ %+ :cr=^M:do=^J:ds=\Eh:\
+	:fs=\E(\r:ho=^^:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:\
+	:k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:kb=^H:kd=^J:kh=^^:\
+	:kl=^H:kr=^L:ku=^K:le=^H:mb=\EG2:nd=^L:nl=^J:nw=^M^J:ta=^I:\
+	:ts=\EF\E):up=^K:\
+	:tc=adm+sgr:
+# From: Andrew Scott Beals <bandy@lll-crg.ARPA>
+# Corrected by Olaf Siebert <rhialto@polder.ubc.kun.nl>, 11 May 1995
+# Supervisor mode info by Ari Wuolle, <awuolle@delta.hut.fi>, 27 Aug 1996
+# (adm12: removed obsolete ":kn:ma=j^Jk^P^K^Pl ^R^L^L :".  This formerly had
+# :is:=\Eq but that looked wrong; this :is: is from Dave Yost <esquire!yost>
+# via BRL.  That entry asserted :sg#1:, but I've left that out because 
+# neither earlier nor later ADMSs have it -- esr)
+#
+# You will need to get into the supervisor setup before you can set
+# baudrate etc. for your ADM-12+. Press Shift-Ctrl-Setup and you should
+# see a lot more setup options.
+# 
+# While in supervisor setup you can also use following codes:
+# 
+# Ctrl-P Personality character selections (configure for example what
+#        arrow keys send, if I recall correctly)
+# Ctrl-T tabs 1-80   use left&right to move and up to set and
+# Ctrl-V tabs 81-158 down to clear tab. Shift-Ctrl-M sets right margin at cursor
+# Ctrl-B Binary setup (probably not needed. I think that everything can
+#        be set using normal setup)
+# Ctrl-A Answerback mode (enter answerback message)
+# Ctrl-U User friendly mode (normal setup)
+# Ctrl-D Defaults entire setup and function keys from EPROM tables
+# Ctrl-S Save both setup and functions keys. Takes from 6 to 10 seconds.
+# Ctrl-R Reads both setup and functions keys from NVM.
+# Shift-Ctrl-X Unlock keyboard and cancel received X-OFF status
+# 
+# ADM-12+ supports hardware handshaking, but it is DTR/CTS as opposed to
+# RTS/CTS used nowadays with virtually every modem and computer. 19200
+# bps works fine with hardware flow control.
+# 
+# The following null-modem cable should fix this and enable you to use
+# RTS/CTS handshaking (which Linux supports, use CRTSCTS setting). Also
+# set ADM-12+ for DTR handshaking from supervisor setup.
+# 
+# PC Serial   ADM-12+
+#  --------   -------
+#         2 - 3
+#         3 - 2
+#         4 - 5
+#         5 - 20
+#       6,8 - 4
+#         7 - 7
+#        20 - 6,8
+#
+adm12|lsi adm12:\
+	:am:bs:mi:pt:\
+	:co#80:it#8:li#24:\
+	:al=\EE:bl=^G:cd=\EY:ce=\ET:cl=^Z:cm=\E=%+ %+ :cr=^M:ct=\E0:\
+	:dc=\EW:dl=\ER:do=^J:ei=\Er:ho=^^:ic=\EQ:im=\Eq:\
+	:is=\E0        \E1        \E1        \E1        \E1        \E1        \E1        \E1        \E1:\
+	:k0=^A0\r:k1=^A1\r:k2=^A2\r:k3=^A3\r:k4=^A4\r:k5=^A5\r:\
+	:k6=^A6\r:k7=^A7\r:k8=^A8\r:k9=^A9\r:kd=^J:kl=^H:kr=^L:\
+	:ku=^K:le=^H:nd=^L:st=\E1:up=^K:\
+	:tc=adm+sgr:
+# (adm20: removed obsolete ":kn#7:" -- esr)
+adm20|lear siegler adm20:\
+	:am:bs:\
+	:co#80:it#8:li#24:\
+	:al=\EE:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=^Z:\
+	:cm=\E=%i%r%+^_%+^_:cr=^M:dc=\EW:dl=\ER:ei=:ho=^^:ic=\EQ:\
+	:im=:k1=^A:k2=^B:k3=^W:k4=^D:k5=^E:k6=^X:k7=^Z:le=^H:me=\E(:\
+	:nd=^L:se=\E(:so=\E):ta=^I:up=^K:
+adm21|lear siegler adm21:\
+	:sg#1:\
+	:al=30*\EE:bl=^G:cd=\EY:ce=\ET:cr=^M:dc=\EW:dl=30*\ER:do=^J:\
+	:ei=:ic=\EQ:im=:kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:mk@:sf=^J:\
+	:tc=adm+sgr:tc=adm3a:
+# (adm22: ":em=:" was an obvious typo for ":ei=:"; also,
+# removed obsolete ":kn#7:ma=j^Jk^P^K^Pl ^R^L^L :";
+# removed bogus-looking \200 from before :cm:. -- esr)
+adm22|lsi adm22:\
+	:am:bs:\
+	:co#80:li#24:\
+	:al=\EE:bl=^G:bt=\EI:cd=\Ey:ce=\Et:cl=\E+:cm=\E=%+ %+ :\
+	:cr=^M:dc=\EW:dl=\ER:do=^J:ei=:ho=^^:ic=\EQ:im=:\
+	:is=\E%\014\014\014\016\003\0\003\002\003\002\0\0\0\0\0\0\0\0\0\0\0:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:l1=F1:l2=F2:\
+	:l3=F3:l4=F4:l5=F5:l6=F6:l7=F7:le=^H:me=\E(:nd=^L:se=\E(:\
+	:so=\E):ta=\Ei:up=^K:
+# ADM 31 DIP Switches
+#
+# This information comes from two versions of the manual for the
+# Lear-Siegler ADM 31.
+#
+# Main board:
+#                  rear of case
+#   +-||||-------------------------------------+
+#   + S1S2                              ||S    +
+#   +                                   ||3    +
+#   +                                          +
+#   +                                ||S       +
+#   +                                ||4       +
+#   +                                          +
+#   +                                          +
+#   +                                          +
+#   +                                          +
+#   +                                          +
+# +-+                                          +-+
+# +                                              +
+# +                               S5 S6 S7       +   
+# +                               == == ==       +
+# +----------------------------------------------+
+#            front of case (keyboard)
+#
+#  S1 - Data Rate - Modem
+#  S2 - Data Rate - Printer
+# ------------------------
+# Data Rate   Setting
+# -------------------
+# 50          0 0 0 0
+# 75          1 0 0 0
+# 110         0 1 0 0
+# 134.5       1 1 0 0
+# 150         0 0 1 0
+# 300         1 0 1 0
+# 600         0 1 1 0
+# 1200        1 1 1 0
+# 1800        0 0 0 1
+# 2000        1 0 0 1
+# 2400        0 1 0 1
+# 3600        1 1 0 1
+# 4800        0 0 1 1
+# 7200        1 0 1 1
+# 9600        0 1 1 1
+# x           1 1 1 1
+#
+# S3 - Interface/Printer/Attributes
+# ---------------------------------
+# Printer Busy Control
+# sw1   sw2   sw3
+# ---------------
+# off   off   off   Busy not active, CD disabled
+# off   off   on    Busy not active, CD enabled
+# off   on    off   Busy active on J5-20, CD disabled
+# on    off   off   Busy active on J5-19, CD disabled - Factory Set.
+# on    off   on    Busy active on J5-19, CD enabled
+#
+# sw4   Used in conjuction with S4 for comm interface control - Fact 0
+#
+# sw5   Secondary Channel Control (Hardware implementation only) - Fact 0
+#
+# sw6   ON enables printer BUSY active LOW - Factory Setting
+#       OFF enables printer BUSY active HIGH - If set to this, ADM31 senses
+#
+# sw7   ON - steady cursor - Factory Setting
+#       OFF - blinking cursor
+#
+# sw8   ON causes selected attribute character to be displayed
+#       OFF causes SPACE to be displayed instead - Factory Setting
+#
+# S4 - Interface
+# --------------
+# Modem Interface
+# S3    S4    S4    S4    S4
+# sw4   sw1   sw2   sw3   sw4
+# ---------------------------
+# OFF   ON    OFF   ON    OFF   Enable RS-232C interface, Direct Connect and
+#                               Current Loop disabled - Factory Setting
+# ON    ON    OFF   ON    OFF   Enable Current Loop interface, Direct Connect
+#                               disabled
+# OFF   OFF   ON    OFF   ON    Enable Direct Connect interface, RS-232C and
+#                               Current Loop Disabled
+#
+# sw5   ON disables dot stretching mode - Factory Setting
+#       OFF enables dot stretching mode
+# sw6   ON enables blanking function
+#       OFF enables underline function - Factory Setting
+# sw7   ON causes NULLS to be displayed as NULLS
+#       OFF causes NULLS to be displayed as SPACES - Factory Setting
+#
+# S5 - Word Structure
+# -------------------
+# sw1   ON enables BREAK key - Factory Setting
+#       OFF disables BREAK key
+# sw2   ON selects 50Hz monitor refresh rate
+#       OFF selects 60Hz monitor refresh rate - Factory Setting
+#
+# Modem Port Selection
+# sw3   sw4   sw5
+# ---------------
+# ON    ON    ON    Selects 7 DATA bits, even parity, 2 STOP bits
+# OFF   ON    ON    Selects 7 DATA bits, odd  parity, 2 STOP bits
+# ON    OFF   ON    Selects 7 DATA bits, even parity, 1 STOP bit - Factory Set.
+# OFF   OFF   ON    Selects 7 DATA bits, odd  parity, 1 STOP bit
+# ON    ON    OFF   Selects 8 DATA bits, no   parity, 2 STOP bits
+# OFF   ON    OFF   Selects 8 DATA bits, no   parity, 1 STOP bit
+# ON    OFF   OFF   Selects 8 DATA bits, even parity, 1 STOP bit
+# OFF   OFF   OFF   Selects 8 DATA bits, odd  parity, 1 STOP bit
+#
+# sw6   ON  sends bit 8 a 1 (mark)
+#       OFF sends bit 8 as 0 (space) - Factory Setting
+# sw7   ON  selects Block Mode
+#       OFF selects Conversation Mode - Factory Setting
+# sw8   ON  selects Full Duplex operation
+#       OFF selects Half Duplex operation - Factory Setting
+#
+# S6 - Printer
+# ------------
+# sw1, sw2, sw6, sw7   Reserved - Factory 0
+#
+# Printer Port Selection
+# same as Modem above, bit 8 (when 8 DATA bits) is always = 0
+#
+# sw8   ON   enables Printer Port
+#       OFF disables Printer Port - Factory Setting
+#
+# S7 - Polling Address
+# --------------------
+# sw1-7 Establish ASCII character which designates terminal polling address
+#       ON  = logic 0
+#       OFF = logic 1 - Factory Setting
+# sw8   ON   enables Polling Option
+#       OFF disables Polling Option - Factory Setting
+#
+#
+# On some older adm31s, S4 does not exist, and S5-sw6 is not defined.
+#
+# This adm31 entry uses underline as the standout mode.
+# If the adm31 gives you trouble with standout mode, check the DIP switch in
+# position 6, bank @c11, 25% from back end of the circuit board.  Should be
+# OFF.  If there is no such switch, you have an old adm31 and must use oadm31.
+# (adm31: removed obsolete ":ma=j^Jk^P^K^Pl ^R^L^L :" -- esr)
+adm31|lsi adm31 with sw6 set for underline mode:\
+	:am:bs:mi:\
+	:co#80:li#24:\
+	:al=\EE:bl=^G:cd=\EY:ce=\ET:cl=\E*:cm=\E=%+ %+ :cr=^M:\
+	:dc=\EW:dl=\ER:do=^J:ei=\Er:ho=^^:im=\Eq:is=\Eu\E0:k0=^A0\r:\
+	:k1=^A1\r:k2=^A2\r:k3=^A3\r:k4=^A4\r:k5=^A5\r:k6=^A6\r:\
+	:k7=^A7\r:k8=^A8\r:k9=^A9\r:kd=^J:kl=^H:kr=^L:ku=^K:le=^H:\
+	:me=\EG0:nd=^L:se=\EG0:sf=^J:so=\EG1:ue=\EG0:up=^K:us=\EG1:
+adm31-old|o31|old adm31:\
+	:so=\EG4:ue@:us@:tc=adm31:
+# LSI ADM-36 from Col. George L. Sicherman <gloria!colonel> via BRL
+adm36|LSI ADM36:\
+	:bs:pt:\
+	:kn#4:\
+	:if=/usr/lib/tabset/vt100:\
+	:is=\E<\E>\E[6;?2;?7;?8h\E[4;20;?1;?3;?4;?5;?6;?18;?19l:tc=vt100:
+# (adm42: removed obsolete ":ma=^K^P:" -- esr)
+adm42|lsi adm42:\
+	:am:bs:\
+	:co#80:li#24:\
+	:al=\EE:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=\E;:cm=\E=%+ %+ :\
+	:cr=^M:dc=\EW:dl=\ER:do=^J:ei=\Er:im=\Eq:ip=:kd=^J:kh=^^:\
+	:kl=^H:kr=^L:ku=^K:le=^H:mk@:nd=^L:pc=\177:sf=^J:ta=^I:ue@:\
+	:up=^K:us@:vs=\EC\E3 \E3(:\
+	:tc=adm+sgr:
+# The following termcap for the Lear Siegler ADM-42 leaves the 
+# "system line" at the bottom of the screen blank (for those who 
+# find it distracting otherwise)
+adm42-ns|lsi adm-42 with no system line:\
+	:al=\EE\EF \011:bt=\EI\EF \011:cd=\EY\EF \011:\
+	:ce=\ET\EF \011:cl=\E;\EF \011:cm=\E=%+ %+ \EF \011:\
+	:dc=\EW\EF \011:dl=\ER\EF \011:ei=\Er\EF \011:\
+	:im=\Eq\EF \011:tc=adm42:
+# ADM 1178 terminal -- rather like an ADM-42.  Manual is dated March 1 1985.
+# The insert mode of this terminal is commented out because it's broken for our
+# purposes in that it will shift the position of every character on the page,
+# not just the cursor line!
+# From: Michael Driscoll <fenris@lightspeed.net> 10 July 1996
+adm1178|1178|lsi adm1178:\
+	:am:\
+	:co#80:li#24:sg#1:\
+	:al=\EE:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=\E+:cm=\E=%+ %+ :\
+	:cr=^M:dc=\EW:dl=\ER:do=^J:ho=^^:ip=6*:kb=^H:kd=^J:kl=^H:\
+	:le=^H:md=\E(:me=\E):mr=\EG4:nd=^L:nw=^M^J:pc=\177:se=\EG0:\
+	:sf=^J:so=\EG4:ta=^I:ue=\EG0:up=^K:us=\EG1:vs=\EC\E3 \E3(:
+
+#### Qume (qvt)
+#
+#	Qume, Inc.
+#	3475-A North 1st Street
+#	San Jose CA 95134
+#	Vox: (800)-457-4447
+#	Fax: (408)-473-1510
+#	Net: josed@techsupp.wyse.com (Jose D'Oliveira)
+#
+# Qume was bought by Wyse, but still (as of early 1995) has its own support
+# group and production division.
+#
+# Discontinued Qume models:
+#
+# The qvt101 and qvt102 listed here are long obsolete; so is the qvt101+
+# built to replace them, and a qvt119+ which was a 101+ with available wide
+# mode (132 columns).  There was a qvt103 which added vt100/vt131 emulations
+# and an ANSI-compatible qvt203 that replaced it.  Qume started producing
+# ANSI-compatible terminals with the qvt323 and qvt61.
+#
+# Current Qume models (as of February 1995):
+#
+# All current Qume terminals have ANSI-compatible operation modes.
+# Qume is still producing the qvt62, which features emulations for other
+# popular lines such as ADDS, and dual-host capabilities.  The qvt82 is
+# designed for use as a SCO ANSI terminal.  The qvt70 is a color terminal
+# with many emulations including Wyse370, Wyse 325, etc.  Their newest
+# model is the qvt520, which is vt420-compatible.
+#
+# There are some ancient printing Qume terminals under `Daisy Wheel Printers'
+#
+# If you inherit a Qume without docs, try Ctrl-Shift-Setup to enter its
+# setup mode.  Shift-s should be a configuration save to NVRAM.
+
+qvt101|qvt108|qume qvt 101 and QVT 108:\
+	:sg#1:tc=qvt101+:
+
+# This used to have :vs=\E.2: but no :ve: or :vi:.  The BSD termcap
+# file had :vs=\EM4 \200\200\200:.  I've done the safe thing and yanked 
+# both. The :mr: is from BSD, which also claimed bold=\E( and dim=\E).
+# What seems to be going on here is that this entry was designed so that
+# the normal highlight is bold and standout is dim plus something else
+# (reverse-video maybe?  But then, are there two :mr: sequences?)  
+qvt101+|qvt101p|qume qvt 101 PLUS product:\
+	:am:bw:hs:ul:\
+	:co#80:li#24:sg#0:\
+	:al=\EE:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=^Z:cm=\E=%+ %+ :cr=^M:\
+	:ct=\E3:dc=\EW:dl=\ER:do=^J:ds=\Eg\Ef\r:ei=:fs=^M:ho=^^:\
+	:ic=\EQ:im=:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:\
+	:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:k;=^AI\r:kA=\EE:\
+	:kB=\EI:kE=\ET:kI=\EQ:kL=\ER:kS=\EY:kb=^H:kd=^J:kh=^^:kl=^H:\
+	:kr=^L:ku=^K:le=^H:mk@:nd=^L:pf=\EA:po=\E@:se=\E(:sf=^J:\
+	:so=\E0P\E):st=\E1:ta=^I:ts=\Eg\Ef:up=^K:vb=\Eb\Ed:ve=\E.4:\
+	:tc=adm+sgr:
+qvt102|qume qvt 102:\
+	:ve=\E.:tc=qvt101:
+# (qvt103: added <rmam>/<smam> based on init string -- esr)
+qvt103|qume qvt 103:\
+	:am:xn:xo:\
+	:co#80:it#8:li#24:vt#3:\
+	:DO=\E[%dB:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:\
+	:UP=\E[%dA:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:do=^J:\
+	:ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:kb=^H:kd=\EOB:\
+	:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:\
+	:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:\
+	:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\E8:\
+	:..sa=\E[%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;m:\
+	:sc=\E7:se=\E[m:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:ue=\E[m:\
+	:up=\E[A:us=\E[4m:
+qvt103-w|qume qvt103 132 cols:\
+	:co#132:li#24:\
+	:r2=\E>\E[?3h\E[?4l\E[?5l\E[?8h:tc=qvt103:
+qvt119+|qvt119p|qvt119|qume qvt 119 and 119PLUS terminals:\
+	:am:hs:mi:ms:\
+	:co#80:li#24:sg#0:\
+	:al=\EE:bl=^G:bt=\EI:cd=\Ey:ce=\Et:cl=\E*1:cm=\E=%+ %+ :\
+	:cr=^M:ct=\E3:dc=\EW:dl=\ER:do=^J:ds=\Eg\Ef\r:ei=\Er:fs=^M:\
+	:ho=^^:im=\Eq:is=\EDF\EC\EG0\Er\E(\E%EX:k0=^AI\r:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:k9=^AH\r:kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:\
+	:ku=^K:le=^H:nd=^L:pf=\EA:po=\E@:sf=^J:sr=\EJ:st=\E1:ta=^I:\
+	:ts=\Eg\Ef:up=^K:us=\EG8:vb=\En0\En1:ve=\E.4:vs=\E.2:\
+	:tc=adm+sgr:
+qvt119+-25|qvt119p-25|QVT 119 PLUS with 25 data lines:\
+	:li#25:tc=qvt119+:
+qvt119+-w|qvt119p-w|qvt119-w|QVT 119 and 119 PLUS in 132 column mode:\
+	:co#132:\
+	:is=\EDF\EC\EG0\Er\E(\E%\EX\En4:tc=qvt119+:
+qvt119+-25-w|qvt119p-25-w|qvt119-25-w|QVT 119 and 119 PLUS 132 by 25:\
+	:li#25:tc=qvt119+:
+qvt203|qvt203+|qume qvt 203 Plus:\
+	:al=\E[L:dc=\E[P:dl=\E[M:ei=\E[4l:im=\E[4h:ip=:k0=\E[29~:\
+	:k1=\E[17~:k2=\E[18~:k3=\E[19~:k4=\E[20~:k5=\E[21~:\
+	:k6=\E[23~:k7=\E[24~:k8=\E[25~:k9=\E[28~:sf=\n:\
+	:tc=qvt103:
+qvt203-w|qvt203-w-am|qume qvt 203 PLUS in 132 cols (w/advanced video):\
+	:co#132:li#24:\
+	:r2=\E>\E[?3h\E[?4l\E[?5l\E[?8h:tc=qvt203:
+#
+#	Since a command is present for enabling 25 data lines,
+#	a specific terminfo entry may be generated for the 203.
+#	If one is desired for the QVT 119 PLUS then 25 lines must
+#	be selected in the status line (setup line 9).
+#
+qvt203-25|QVT 203 PLUS with 25 by 80 column mode:\
+	:co#80:li#25:\
+	:is=\E[=40h\E[?3l:tc=qvt203:
+qvt203-25-w|QVT 203 PLUS with 25 by 132 columns:\
+	:co#132:li#25:\
+	:r2=\E[?3h\E[=40h:tc=qvt203:
+
+#### Televideo (tvi)
+#
+#	TeleVideo
+#	550 East Brokaw Road
+#	PO Box 49048    95161
+#	San Jose CA 95112
+#	Vox: (408)-954-8333
+#	Fax: (408)-954-0623
+#
+#
+# There are some tvi terminals that require incredible amounts of padding and
+# some that don't.  I'm assuming tvi912 and tvi920 are the old slow ones, and
+# tvi912b, tvi912c, tvi920b, tvi920c are the new ones that don't need padding.
+#
+# All of these terminals (912 to 970 and the tvipt) are discontinued.  Newer
+# Televideo terminals are ANSI and PC-ANSI compatible.
+
+tvi803|televideo 803:\
+	:cl=\E*:tc=tvi950:
+
+# Vanilla tvi910 -- W. Gish <cswarren@violet> 10/29/86
+# Switch settings are:
+# 
+# S1  1 2 3 4
+#     D D D D  9600
+#     D D D U    50
+#     D D U D    75
+#     D D U U   110
+#     D U D D   135
+#     D U D U   150
+#     D U U D   300
+#     D U U U   600
+#     U D D D  1200
+#     U D D U  1800
+#     U D U D  2400
+#     U D U U  3600
+#     U U D D  4800
+#     U U D U  7200
+#     U U U D  9600
+#     U U U U 19200
+# 
+# S1  5 6 7 8
+#     U D X D  7N1 (data bits, parity, stop bits) (X means ignored)
+#     U D X U  7N2
+#     U U D D  7O1
+#     U U D U  7O2
+#     U U U D  7E1
+#     U U U U  7E2
+#     D D X D  8N1
+#     D D X U  8N2
+#     D U D D  8O1
+#     D U U U  8E2
+# 
+# S1  9  Autowrap
+#     U  on
+#     D  off
+# 
+# S1 10  CR/LF
+#     U  do CR/LF when CR received
+#     D  do CR when CR received
+# 
+# S2  1  Mode
+#     U  block
+#     D  conversational
+# 
+# S2  2  Duplex
+#     U  half
+#     D  full
+# 
+# S2  3  Hertz
+#     U  50
+#     D  60
+# 
+# S2  4  Edit mode
+#     U  local
+#     D  duplex
+# 
+# S2  5  Cursor type
+#     U  underline
+#     D  block
+# 
+# S2  6  Cursor down key
+#     U  send ^J
+#     D  send ^V
+# 
+# S2  7  Screen colour
+#     U  green on black
+#     D  black on green
+# 
+# S2  8  DSR status (pin 6)
+#     U  disconnected
+#     D  connected
+# 
+# S2  9  DCD status (pin 8)
+#     U  disconnected
+#     D  duplex
+# 
+# S2 10  DTR status (pin 20)
+#     U  disconnected
+#     D  duplex
+# (tvi910: removed obsolete ":ma=^Kk^Ll^R^L:"; added :kh:, :le:, :do:,
+# :sf:, <hpa>, <vpa>, :am:, :ms: from SCO entry -- esr)
+tvi910|televideo model 910:\
+	:am:bs:ms:\
+	:co#80:it#8:li#24:sg#1:\
+	:bl=^G:bt=\EI:cd=\EY:ce=\ET:ch=\E]%+ :cl=^Z:cm=\E=%+ %+ :\
+	:cr=^M:cv=\E[%+ :do=^J:ho=\E=\001\001:\
+	:if=/usr/share/tabset/stdcrt:k0=^AI\r:k1=^A@\r:k2=^AA\r:\
+	:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:\
+	:k9=^AH\r:kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:mk@:nd=^L:\
+	:sf=^J:ta=^I:up=^K:\
+	:tc=adm+sgr:
+# From: Alan R. Rogers <rogers%albany@csnet-relay>
+# as subsequently hacked over by someone at SCO
+# (tvi910+: removed obsolete ":ma=^K^P^L :" -- esr)
+#
+# Here are the 910+'s DIP switches (U = up, D = down, X = don't care):
+#
+# S1  1 2 3 4:
+#     D D D D  9600     D D D U    50     D D U D    75     D D U U   110
+#     D U D D   135     D U D U   150     D U U D   300     D U U U   600
+#     U D D D  1200     U D D U  1800     U D U D  2400     U D U U  3600
+#     U U D D  4800     U U D U  7200     U U U D  9600     U U U U 19200
+#
+# S1  5 6 7 8:
+#     U D X D  7N1     U D X U  7N2     U U D D  7O1     U U D U  7O2
+#     U U U D  7E1     U U U U  7E2     D D X D  8N1     D D X U  8N2
+#     D U D D  8O1     D U U U  8E2
+# 
+# S1  9  Autowrap            (U = on, D = off)
+# S1 10  CR/LF               (U = CR/LF on CR received, D = CR on CR received)
+# S2  1  Mode                (U = block, D = conversational)
+# S2  2  Duplex              (U =  half, D = full)
+# S2  3  Hertz               (U = 50, D = 60)
+# S2  4  Edit mode           (U = local, D = duplex)
+# S2  5  Cursor type         (U = underline, D = block)
+# S2  6  Cursor down key     (U = send ^J, D = send ^V)
+# S2  7  Screen colour       (U = green on black, D = black on green)
+# S2  8  DSR status (pin 6)  (U = disconnected, D = connected)
+# S2  9  DCD status (pin 8)  (U = disconnected, D = connected)
+# S2 10  DTR status (pin 20) (U = disconnected, D = connected)
+#
+tvi910+|televideo 910+:\
+	:al=\EE:dc=\EW:dl=\ER:ei=:ho=^^:ic=\EQ:im=:k0=^A@\r:k1=^AA\r:\
+	:k2=^AB\r:k3=^AC\r:k4=^AD\r:k5=^AE\r:k6=^AF\r:k7=^AG\r:\
+	:k8=^AH\r:k9=^AI\r:ll=\E=7 :\
+	:tc=tvi910:
+
+# (tvi912: removed obsolete ":ma=^K^P^L :", added  :vb: and
+# :kh: from BRL entry -- esr)
+tvi912|tvi914|tvi920|old televideo 912/914/920:\
+	:am:bs:ms:pt:\
+	:co#80:it#8:li#24:sg#1:\
+	:al=\EE:bl=^G:cd=\Ey:ce=\ET:cl=^Z:cm=\E=%+ %+ :cr=^M:ct=\E3:\
+	:dc=\EW:dl=\ER:do=^J:ei=:ho=^^:ic=\EQ:\
+	:if=/usr/share/tabset/stdcrt:im=:k0=^AI\r:k1=^A@\r:\
+	:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:k7=^AF\r:\
+	:k8=^AG\r:k9=^AH\r:kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:\
+	:nd=^L:se=\Ek:sf=^J:so=\Ej:st=\E1:ta=^I:ue=\Em:up=^K:us=\El:\
+	:vb=\Eb\Ed:
+# the 912 has a <funct> key that's like shift: <funct>8 xmits "^A8\r".
+# The 920 has this plus real function keys that xmit different things.
+# Terminfo makes you use the funct key on the 912 but the real keys on the 920.
+tvi912c|tvi912b|new televideo 912:\
+	:al=\EE:dl=\ER:tc=tvi912:
+# set to page 1 when entering curses application (\E-17 )
+# reset to page 0 when exiting curses application (\E-07 )
+tvi912-2p|tvi920-2p|tvi-2p|televideo w/2 pages:\
+	:te=\E-07 :ti=\E-17 :tc=tvi912:
+# We got some new tvi912c terminals that act really weird on the regular 
+# termcap, so one of our gurus worked this up. Seems that cursor 
+# addressing is broken.
+tvi912cc|tvi912 at cowell college:\
+	:cm@:tc=tvi912c:
+
+# Here are the switch settings for the tvi920c:
+#
+# S1 (Line), and S3 (Printer) baud rates -- put one, and only one, switch down:
+# 2: 9600	3: 4800		4: 2400		5: 1200
+# 6:  600	7:  300		8:  150		9:   75
+# 10: 110
+#
+# S2 UART/Terminal options:
+# 		Up			Down
+# 1:		Not used		Not allowed
+# 2:	Alternate character set	  Standard character set
+# 3:	    Full duplex		    Half duplex
+# 4:	    50 Hz refresh	    60 Hz refresh
+# 5:	      No parity		     Send parity
+# 6:	     2 stop bits	     1 stop bit
+# 7:	     8 data bits	     7 data bits
+# 8:		Not used		Not allowed on Rev E or lower
+# 9:	     Even parity	     Odd parity
+# 10:	    Steady cursor	    Blinking cursor
+# 	(On Rev E or lower, use W25 instead of switch 10.)
+# 
+# S5 UART/Terminal options:
+# 		Open			Closed
+# 1:	P3-6 Not connected	DSR received on P3-6
+# 2:	P3-8 Not connected	DCD received on P3-8
+#
+# 3 Open, 4 Open:		P3-20 Not connected
+# 3 Open, 4 Closed:	DTR on when terminal is on
+# 3 Closed, 4 Open:	DTR is connected to RTS
+# 3 Closed, 4 Closed:	Not allowed
+#
+# 5 Closed:	HDX printer (hardware control) Rev. K with extension port off,
+# 		all data transmitted out of the modem port (P3) will also be
+# 		transmitted out of the printer port (P4).
+#
+# 6 Open, 7 Open:		Not allowed
+# 6 Open, 7 Closed:	20ma current loop input
+# 6 Closed, 7 Open:	RS232 input
+# 6 Closed, 7 Closed:	Not allowed
+#
+# Jumper options:
+# If the jumper is installed, the effect will occur (the next time the terminal
+# is switched on).
+#
+# S4/W31:	Enables automatic LF upon receipt of CR from
+# 		remote or keyboard.
+# S4/W32:	Enables transmission of EOT at the end of Send.  If not 
+# 		installed, a carriage return is sent.
+# S4/W33:	Disables automatic carriage return in column 80.
+# S4/W34:	Selects Page Print Mode as initial condition.  If not 
+# 		installed, Extension Mode is selected.
+#
+tvi920b|tvi920c|new televideo 920:\
+	:al=\EE:dl=\ER:k0=^AI\r:k1=^A@\r:k2=^AA\r:k3=^AB\r:\
+	:k4=^AC\r:k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:\
+	:tc=tvi912:
+
+# Televideo 921 and variants
+# From: Tim Theisen <tim@cs.wisc.edu> 22 Sept 1995
+# (tvi921: removed :ko=bt: before translation, I see no backtab cap;
+# also added empty <acsc> to suppress tic warning -- esr)
+tvi921|televideo model 921 with sysline same as page & real vi function:\
+	:am:bs:hs:pt:xn:xs:\
+	:co#80:li#24:sg#0:\
+	:ac=:ae=\E%:al=\EE:as=\E$:cd=\EY:ce=\ET:cl=^Z:cm=3\E=%+ %+ :\
+	:cr=^M:dc=\EW:dl=1*\ER:do=^V:ds=\Ef\r\Eg:ei=:fs=\Eg:ho=^^:\
+	:ic=\EQ:if=/usr/share/tabset/stdcrt:im=:\
+	:is=\El\E"\EF1\E.3\017\EA\E<:kA=\EE:kC=^Z:kD=\EW:kE=\ET:\
+	:kI=\EQ:kL=1*\ER:kS=\EY:kb=^H:kd=^V:kl=^H:kr=^L:ku=^K:le=^H:\
+	:mk@:nd=^L:nw=^M^J:sf=^J:ta=^I:ts=\Ef\EG0:up=^K:ve=\E.3:\
+	:vs=\E.2:\
+	:tc=adm+sgr:
+# without the beeper
+# (tvi92B: removed :ko=bt: before translation, I see no backtab cap;
+# also added empty <acsc> to suppress tic warning -- esr)
+tvi92B|televideo model 921 with sysline same as page & real vi function & no beeper:\
+	:am:hs:xn:xs:\
+	:co#80:li#24:sg#0:\
+	:ac=:ae=\E%:al=\EE:as=\E$:cd=\EY:ce=\ET:cl=^Z:cm=3\E=%+ %+ :\
+	:cr=^M:dc=\EW:dl=1*\ER:do=^V:ds=\Ef\r\Eg:ei=:fs=\Eg:ho=^^:\
+	:ic=\EQ:if=/usr/share/tabset/stdcrt:im=:\
+	:is=\El\E"\EF1\E.3\017\EA\E<:kA=\EE:kC=^Z:kD=\EW:kE=\ET:\
+	:kI=\EQ:kL=1*\ER:kS=\EY:kb=^H:kd=^V:kl=^H:kr=^L:ku=^K:le=^H:\
+	:mk@:nd=^L:nw=^M^J:sf=^J:ta=^I:ts=\Ef\EG0:up=^K:vb=\Eb\Ed:\
+	:ve=\E.3:vs=\E.2:\
+	:tc=adm+sgr:
+# (tvi92D: removed :ko=bt: before translation, I see no backtab cap -- esr)
+tvi92D|tvi92B with DTR instead of XON/XOFF & better padding:\
+	:al=2*\EE:dl=2*\ER:is=\El\E"\EF1\E.3\016\EA\E<:kA=2*\EE:\
+	:kL=2*\ER:\
+	:tc=tvi92B:
+
+# (tvi924: This used to have :ds=\Es0:, :fs=\031:.  I put the new strings
+# in from a BSD termcap file because it looks like they do something the
+# old ones skip -- esr)
+tvi924|televideo tvi924:\
+	:am:bw:hs:in:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:sg#0:ws#80:\
+	:F1=^AK\r:F2=^AL\r:F3=^AM\r:F4=^AN\r:F5=^AO\r:al=\EE:bl=^G:\
+	:bt=\EI:cd=\Ey:ce=\Et:cl=\E*0:cm=\E=%+ %+ :cr=^M:\
+	:cs=\E_%+ %+ :ct=\E3:dc=\EW:dl=\ER:do=^V:ds=\Es0\Ef\031:\
+	:ei=:fs=\031\Es1:ho=^^:\
+	:i1=\017\E%\E'\E(\EDF\EC\EG0\EN0\Es0\Ev0:ic=\EQ:\
+	:if=/usr/share/tabset/stdcrt:im=:k0=^A@\r:k1=^AA\r:\
+	:k2=^AB\r:k3=^AC\r:k4=^AD\r:k5=^AE\r:k6=^AF\r:k7=^AG\r:\
+	:k8=^AH\r:k9=^AI\r:k;=^AJ\r:kA=\EE:kC=\E*0:kD=\EW:kE=\Et:\
+	:kI=\EQ:kL=\ER:kS=\Ey:kb=^H:kd=^V:kh=^^:kl=^H:kr=^L:ku=^K:\
+	:l0=F1:l1=F2:l2=F3:l3=F4:l4=F5:l5=F6:l6=F7:l7=F8:l8=F9:l9=F10:\
+	:la=F11:le=^H:mb=\EG2:mk@:nd=^L:pk=\E|%+1%s\031:sf=^J:\
+	:sr=\Ej:st=\E1:ta=^I:ts=\Ef:up=^K:vb=\Eb\Ed:ve=\E.3:vi=\E.0:\
+	:vs=\E.1:\
+	:tc=adm+sgr:
+
+# TVI925 DIP switches.  In each of these, D = Down and U = Up,
+#
+# Here are the settings for the external (baud) switches (S1):
+#
+#             Position		Baud
+# 7	8	9	10		[Printer]
+# 1	2	3	4		[Main RS232]
+# -----------------------------------------------------
+# D	D	D	D	9600
+# D	D	D	U	  50
+# D	D	U	D	  75
+# D	D	U	U	 110
+# D	U	D	D	 135
+# D	U	D	U	 150
+# D	U	U	D	 300
+# D	U	U	U	 600
+# U	D	D	D	1200
+# U	D	D	U	1800
+# U	D	U	D	2400
+# U	D	U	U	3600
+# U	U	D	D	4800
+# U	U	D	U	7200
+# U	U	U	D	9600
+# U	U	U	U	19200
+# 
+# 
+# Settings for word length and stop-bits (S1)
+#
+#  Position	Description
+# 5	6	
+# ---------------------------
+# U	-	7-bit word
+# D	-	8-bit word
+# -	U	2 stop bits
+# -	D	1 stop bit
+# 
+# 
+# S2 (external) settings
+#
+# Position	Up	Dn	Description
+# --------------------------------------------
+# 1		X		Local edit
+# 			X	Duplex edit (transmit editing keys)
+# --------------------------------------------
+# 2		X		912/920 emulation
+# 			X	925
+# --------------------------------------------
+# 3			X
+# 4			X	No parity
+# 5			X	
+# --------------------------------------------
+# 3			X
+# 4			X	Odd parity
+# 5		X	
+# --------------------------------------------
+# 3			X
+# 4		X		Even parity
+# 5		X	
+# --------------------------------------------
+# 3		X	
+# 4			X	Mark parity
+# 5		X		
+# --------------------------------------------
+# 3		X
+# 4		X		Space parity
+# 5		X
+# --------------------------------------------
+# 6		X		White on black display
+# 			X	Black on white display
+# --------------------------------------------
+# 7			X	Half Duplex
+# 8			X
+# --------------------------------------------
+# 7		X		Full Duplex
+# 8			X	
+# --------------------------------------------
+# 7			X	Block mode
+# 8		X	
+# --------------------------------------------
+# 9			X	50 Hz
+# 		X		60 Hz
+# --------------------------------------------
+# 10		X		CR/LF (Auto LF)
+# 			X	CR only
+# 
+# S3 (internal switch) settings:
+# 
+# Position	Up	Dn	Description
+# --------------------------------------------
+# 1		X		Keyclick off 
+# 			X	Keyclick on
+# --------------------------------------------
+# 2			X	English
+# 3			X	
+# --------------------------------------------
+# 2			X	German
+# 3		X		
+# --------------------------------------------
+# 2		X		French
+# 3			X	
+# --------------------------------------------
+# 2		X		Spanish
+# 3		X	
+# --------------------------------------------
+# 4			X	Blinking block cursor
+# 5			X	
+# --------------------------------------------
+# 4			X	Blinking underline cursor
+# 5		X		
+# --------------------------------------------
+# 4		X		Steady block cursor
+# 5			X	
+# --------------------------------------------
+# 4		X		Steady underline cursor
+# 5		X	
+# --------------------------------------------
+# 6		X		Screen blanking timer (ON)
+# 			X	Screen blanking timer (OFF)
+# --------------------------------------------
+# 7		X		Page attributes
+# 			X	Line attributes
+# --------------------------------------------
+# 8		X		DCD disconnected
+# 			X	DCD connected
+# --------------------------------------------
+# 9		X		DSR disconnected
+# 			X	DSR connected
+# --------------------------------------------
+# 10		X		DTR Disconnected
+# 			X	DTR connected
+# --------------------------------------------
+#
+# (tvi925: BSD has :cl=\E*:.  I got :is: and :sr: from there -- esr)
+tvi925|televideo 925:\
+	:am:bs:bw:hs:ul:\
+	:co#80:li#24:sg#1:\
+	:al=\EE:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=^Z:cm=\E=%+ %+ :cr=^M:\
+	:ct=\E3:dc=\EW:dl=\ER:do=^V:ds=\Eh:ei=:fs=^M\Eg:ho=^^:ic=\EQ:\
+	:im=:is=\El\E":k0=^AI\r:k1=^A@\r:k2=^AA\r:k3=^AB\r:\
+	:k4=^AC\r:k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:\
+	:kA=\EE:kC=^Z:kD=\EW:kE=\ET:kI=\EQ:kL=\ER:kS=\EY:kb=^H:kd=^V:\
+	:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:mk@:nd=^L:sf=^J:sr=\Ej:st=\E1:\
+	:ta=^I:ts=\Eh\Ef:up=^K:vb=\Eb\Ed:ve=\E.4:vs=\E.2:\
+	:tc=adm+sgr:
+# TeleVideo 925 from Mitch Bradley <sun!wmb> via BRL
+# to avoid "magic cookie" standout glitch:
+tvi925-hi|TeleVideo Model 925 with half intensity standout mode:\
+	:sg@:\
+	:kb=^H:kd=^J:kl=^H:se=\E(:so=\E):tc=tvi925:
+
+# From: Todd Litwin <litwin@litwin.jpl.nasa.gov> 28 May 1993
+# Originally Tim Curry, Univ. of Central Fla., <duke!ucf-cs!tim> 5/21/82
+# for additional capabilities, 
+# The following tvi descriptions from B:pjphar and virus!mike
+# is for all 950s.  It sets the following attributes:
+# full duplex (\EDF)		write protect off (\E()
+# conversation mode (\EC)	graphics mode off (\E%)
+# white on black (\Ed)		auto page flip off (\Ew)
+# turn off status line (\Eg)	clear status line (\Ef\r)
+# normal video (\E0)		monitor mode off (\EX or \Eu)
+# edit mode (\Er)		load blank char to space (\Ee\040)
+# line edit mode (\EO)		enable buffer control (^O)
+# protect mode off (\E\047)	duplex edit keys (\El)
+# program unshifted send key to send line all (\E016)
+# program shifted send key to send line unprotected (\E004)
+# set the following to nulls:
+#	field delimiter (\Ex0\200\200)
+#	line delimiter (\Ex1\200\200)
+#	start-protected field delimiter (\Ex2\200\200)
+#	end-protected field delimiter (\Ex3\200\200)
+# set end of text delimiter to carriage return/null (\Ex4\r\200)
+# 
+#                     TVI 950 Switch Setting Reference Charts
+# 
+#                                     TABLE 1:
+# 
+#      S1     1     2     3     4     5     6     7     8     9    10
+#          +-----------------------+-----+-----+-----------------------+
+#          | Computer Baud Rate    |Data |Stop | Printer Baud Rate     |
+#          |                       |Bits |Bits |                       |
+#   +------+-----------------------+-----+-----+-----------------------+
+#   |  Up  |        See            |  7  |  2  |        See            |
+#   +------+-----------------------+-----+-----+-----------------------+
+#   | Down |      TABLE 2          |  8  |  1  |      TABLE 2          |
+#   +------+-----------------------+-----+-----+-----------------------+
+# 
+# 
+#      S2     1     2     3     4     5     6     7     8     9    10
+#          +-----+-----+-----------------+-----+-----------+-----+-----+
+#          |Edit |Cursr|    Parity       |Video|Transmiss'n| Hz  |Click|
+#   +------+-----+-----+-----------------+-----+-----------+-----+-----+
+#   |  Up  | Dplx|Blink|      See        |GonBk|   See     | 60  | Off |
+#   +------+-----+-----+-----------------+-----+-----------+-----+-----+
+#   | Down |Local|St'dy|    TABLE 3      |BkonG|  CHART    | 50  | On  |
+#   +------+-----+-----+-----------------+-----+-----------+-----+-----+
+#  
+#                                    TABLE 2:
+# 
+#             +-----------+-----+-----+-----+-----+-----------+
+#             | Display   |  1  |  2  |  3  |  4  |   Baud    |
+#             +-----------+-----+-----+-----+-----+           |
+#             | Printer   |  7  |  8  |  9  | 10  |   Rate    |
+#             +-----------+-----+-----+-----+-----+-----------+
+#                         |  D  |  D  |  D  |  D  |   9600    |
+#                         |  U  |  D  |  D  |  D  |     50    |
+#                         |  D  |  U  |  D  |  D  |     75    |
+#                         |  U  |  U  |  D  |  D  |    110    |
+#                         |  D  |  D  |  U  |  D  |    135    |
+#                         |  U  |  D  |  U  |  D  |    150    |
+#                         |  D  |  U  |  U  |  D  |    300    |
+#                         |  U  |  U  |  U  |  D  |    600    |
+#                         |  D  |  D  |  D  |  U  |   1200    |
+#                         |  U  |  D  |  D  |  U  |   1800    |
+#                         |  D  |  U  |  D  |  U  |   2400    |
+#                         |  U  |  U  |  D  |  U  |   3600    |
+#                         |  D  |  D  |  U  |  U  |   4800    |
+#                         |  U  |  D  |  U  |  U  |   7200    |
+#                         |  D  |  U  |  U  |  U  |   9600    |
+#                         |  U  |  U  |  U  |  U  |  19200    |
+#                         +-----+-----+-----+-----+-----------+
+# 
+#                                    TABLE 3:
+#                         +-----+-----+-----+-----------+
+#                         |  3  |  4  |  5  |   Parity  |
+#                         +-----+-----+-----+-----------+
+#                         |  X  |  X  |  D  |    None   |
+#                         |  D  |  D  |  U  |     Odd   |
+#                         |  D  |  U  |  U  |    Even   |
+#                         |  U  |  D  |  U  |    Mark   |
+#                         |  U  |  U  |  U  |   Space   |
+#                         +-----+-----+-----+-----------+
+#                                 X = don't care
+# 
+#                                     CHART:
+#                         +-----+-----+-----------------+
+#                         |  7  |  8  | Communication   |
+#                         +-----+-----+-----------------+
+#                         |  D  |  D  |  Half Duplex    |
+#                         |  D  |  U  |  Full Duplex    |
+#                         |  U  |  D  |     Block       |
+#                         |  U  |  U  |     Local       |
+#                         +-----+-----+-----------------+
+# 
+# (tvi950: early versions had obsolete ":ma=^Vj^Kk^Hh^Ll^^H:". 
+# I also inserted :ic: and :kI:; the :ko: string indicated that :IC: 
+# should be present and all tvi native modes use the same string for this.
+# Finally, note that BSD has cud1=^V. -- esr) 
+tvi950|televideo 950:\
+	:am:bs:hs:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:sg#1:\
+	:ac=b\011c\014d\re\ni\013:ae=^X:al=\EE:as=^U:bl=^G:bt=\EI:\
+	:cd=\Ey:ce=\Et:cl=\E*:cm=\E=%+ %+ :cr=^M:ct=\E3:dc=\EW:\
+	:dl=\ER:do=^J:ds=\Eg\Ef\r:ei=\Er:fs=^M:ho=^^:ic=\EQ:im=\Eq:\
+	:is=\EDF\EC\Ed\EG0\Eg\Er\EO\E'\E(\E%\Ew\EX\Ee \017\011\El\E016\E004\Ex0\0\0\Ex1\0\0\Ex2\0\0\011\Ex3\0\0\Ex4\r\0\Ef\r:\
+	:k0=^A0\r:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:\
+	:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:kA=\EE:kB=\EI:kC=\E*:\
+	:kD=\EW:kE=\Et:kI=\EQ:kL=\ER:kS=\Ey:kb=^H:kd=^V:kh=^^:kl=^H:\
+	:kr=^L:ku=^K:le=^H:mk@:nd=^L:pf=\Ea:po=\E`:sf=^J:sr=\Ej:\
+	:st=\E1:ta=^I:ts=\Eg\Ef:up=^K:vb=\Eb\Ed:\
+	:tc=adm+sgr:
+#
+# is for 950 with two pages adds the following:
+#	set 48 line page (\E\\2)
+#	place cursor at page 0, line 24, column 1 (\E-07 )
+#	set local (no send) edit keys (\Ek)
+#
+# two page 950 adds the following:
+#	when entering ex, set 24 line page (\E\\1)
+#	when exiting ex, reset 48 line page (\E\\2)
+#			 place cursor at 0,24,1 (\E-07 )
+#	set duplex (send) edit keys (\El) when entering vi
+#	set local (no send) edit keys (\Ek) when exiting vi
+#
+tvi950-2p|televideo950 w/2 pages:\
+	:is=\EDF\EC\Ed\EG0\Eg\Er\EO\E'\E(\E%\Ew\EX\Ee \017\011\Ek\E016\E004\Ex0\0\0\Ex1\0\0\Ex2\0\0\011\Ex3\0\0\Ex4\r\0\E\2\E-07 \011:\
+	:ke=\Ek:ks=\El:te=\E\2\E-07 :ti=\E\1\E-07 :\
+	:tc=tvi950:
+#
+# is for 950 with four pages adds the following:
+#	set 96 line page (\E\\3)
+#	place cursor at page 0, line 24, column 1 (\E-07 )
+#
+# four page 950 adds the following:
+#	when entering ex, set 24 line page (\E\\1)
+#	when exiting ex, reset 96 line page (\E\\3)
+#			 place cursor at 0,24,1 (\E-07 )
+#
+tvi950-4p|televideo950 w/4 pages:\
+	:is=\EDF\EC\Ed\EG0\Eg\Er\EO\E'\E(\E%\Ew\EX\Ee \017\011\Ek\E016\E004\Ex0\0\0\Ex1\0\0\Ex2\0\0\011\Ex3\0\0\Ex4\r\0\E\3\E-07 \011:\
+	:ke=\Ek:ks=\El:te=\E\3\E-07 :ti=\E\1\E-07 :\
+	:tc=tvi950:
+#
+# :is: for reverse video 950 changes the following:
+#	set reverse video (\Ed)
+#
+# set vb accordingly (\Ed ...delay... \Eb)
+#
+tvi950-rv|televideo950 rev video:\
+	:is=\EDF\EC\Eb\EG0\Eg\Er\EO\E'\E(\E%\Ew\EX\Ee \017\011\El\E016\E004\Ex0\0\0\Ex1\0\0\Ex2\0\0\011\Ex3\0\0\Ex4\r\0:\
+	:vb=\Ed\Eb:\
+	:tc=tvi950:
+
+# tvi950-rv-2p uses the appropriate entries from 950-2p and 950-rv
+tvi950-rv-2p|televideo950 rev video w/2 pages:\
+	:is=\EDF\EC\Eb\EG0\Eg\Er\EO\E'\E(\E%\Ew\EX\Ee \017\011\Ek\E016\E004\Ex0\0\0\Ex1\0\0\Ex2\0\0\011\Ex3\0\0\Ex4\r\0\E\2\E-07 :\
+	:ke=\Ek:ks=\El:te=\E\2\E-07 :ti=\E\1\E-07 :vb=\Ed\Eb:\
+	:tc=tvi950:
+
+# tvi950-rv uses the appropriate entries from 950-4p and 950-rv
+tvi950-rv-4p|televideo950 rev video w/4 pages:\
+	:is=\EDF\EC\Eb\EG0\Er\EO\E'\E(\E%\Ew\EX\Ee \017\011\Ek\E016\E004\Ex0\0\0\Ex1\0\0\Ex2\0\0\011\Ex3\0\0\Ex4\r\0\E\3\E-07 :\
+	:ke=\Ek:ks=\El:te=\E\3\E-07 :ti=\E\1\E-07 :vb=\Ed\Eb:\
+	:tc=tvi950:
+# From: Andreas Stolcke <stolcke@icsi.berkeley.edu>
+# (tvi955: removed obsolete ":ma:=^Vj^Kk^Hh^Ll^^H";
+# removed incorrect (and overridden) ":do=^J:"; fixed broken continuations in
+# the :rs: string, inserted the :IC: implied by the termcap :ko: string.  Note
+# the :ko: string had :cl: in it, which means that one of the original
+# :cl=\E*:, <kclr=\EY> had to be wrong; set <kclr=\E*> because that's what
+# the 950 has.   Finally, corrected the <kel> string to match the 950 and what
+# ko implies -- esr)
+# If the BSD termcap file was right, :cm=\E=%p1%{32}%+%c%p2%{32}%+%c: would
+# also work.
+tvi955|televideo 955:\
+	:5i:bs:ms@:\
+	:it#8:sg@:\
+	:RA=\E[=7l:RX=^N:SA=\E[=7h:SX=^O:\
+	:ac=0_`RjHkGlFmEnIoPqKsQtMuLvOwNxJ:ae=\E%:as=\E$:\
+	:cm=\E[%i%d;%dH:do=^V:is=\E[=3l\EF1\Ed\EG0\E[=5l\E%\El:\
+	:kM=\EQ:kN=\EK:kP=\EJ:kT=\E1:ka=\E3:kt=\E2:mb=\EG2:\
+	:me=\EG0\E[=5l:mh=\E[=5h:mk=\EG1:ps=\EP:\
+	:r1=\EDF\EC\Eg\Er\EO\E'\E(\Ew\EX\Ee \017\E0P\E6\0\E0p\E4\0\Ef\r:\
+	:sf@:ve=\E.2:vi=\E.0:vs=\E.1:\
+	:tc=tvi950:
+tvi955-w|955-w|televideo955 w/132 cols:\
+	:co#132:\
+	:is=\E[=3h\EF1\Ed\EG0\E[=5l\E%\El:tc=tvi955:
+# use half-intensity as normal mode, full intensity as :md:
+tvi955-hb|955-hb|televideo955 half-bright:\
+	:is=\E[=3l\EF1\Ed\EG0\E[=5h\E%\El:md=\E[=5l:\
+	:me=\EG0\E[=5h:mh@:tc=tvi955:
+# From: Humberto Appleton <beto@cs.utexas.edu>, 880521 UT Austin
+# (tvi970: removed ":sg#0:"; removed :se:=\E[m, :ue:=\E[m;
+# added :am:/:cs:/:ho:/<hpa>/<vpa>/:ti:/:te: from BRL.
+# According to BRL we could have :ke:=\E>, :ks:=\E= but I'm not sure what
+# it does to the function keys.  I deduced <rmam>/<smam>.
+# also added empty <acsc> to suppress tic warning,  -- esr)
+tvi970|televideo 970:\
+	:am:bs:da:db:mi:ms:pt:\
+	:co#80:it#8:li#24:\
+	:RA=\E[?7h:SA=\E[?7l:ac=:ae=\E(B:al=\E[L:as=\E(B:bt=\E[Z:\
+	:cd=\E[J:ce=\E[K:ch=\E[%i%dG:cl=\E[H\E[2J:cm=\E[%i%d;%df:\
+	:cs=\E[%i%d;%dr:cv=\E[%i%dd:dc=\E[P:dl=\E[M:do=\ED:\
+	:ds=\Eg\Ef\r:ei=\E[4l:ho=\E[H:im=\E[4h:\
+	:is=\E<\E[?21l\E[19h\E[1Q\E[10l\E[7l\E[H\E[2J:k1=\E?a:\
+	:k2=\E?b:k3=\E?c:k4=\E?d:k5=\E?e:k6=\E?f:k7=\E?g:k8=\E?h:\
+	:k9=\E?i:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:le=^H:me=\E[m:nd=\E[C:se=\E[m:so=\E[7m:sr=\EM:ta=^I:te=:\
+	:ti=\E[?20l\E[?7h\E[1Q:ue=\E[m:up=\EM:us=\E[4m:\
+	:vb=\E[5m\E[m:vs=\E[1Q:
+tvi970-vb|televideo 970 with visual bell:\
+	:vb=\E[?5h\0\0\0\0\0\0\0\0\0\0\0\0\0\E[?5l:tc=tvi970:
+tvi970-2p|televideo 970 with using 2 pages of memory:\
+	:te=\E[H\E[J\E[V:ti=\E[U\E[?20l\E[?7h\E[1Q:\
+	:tc=tvi970:
+# Works with vi and rogue.  NOTE: Esc v sets autowrap on, Esc u sets 80 chars
+# per line (rather than 40), Esc K chooses the normal character set.  Not sure
+# padding is needed, but adapted from the tvi920c termcap.  The :so: and 
+# :us: strings are klutzy, but at least use no screen space.
+# (tvipt: removed obsolete ":ma=^Kk^Ll^R^L:".  I wish we knew <rmam>,
+# its absence means <smam>=\Ev isn't safe to use. -- esr)
+# From: Gene Rochlin <armsis@amber.berkeley.edu> 9/19/84. 
+# The :cd:/:k0:/:k1:/:kh:/<mc4>, and <mc5> caps are from BRL, which says:
+# F1 and F2 should be programmed as ^A and ^B; required for UNIFY.
+tvipt|televideo personal terminal:\
+	:am:bs:\
+	:co#80:li#24:\
+	:al=\EE:bt=\EI:cd=\EY:ce=\ET:cl=^Z:cm=\E=%+ %+ :dl=\ER:\
+	:ho=^^:if=/usr/share/tabset/stdcrt:is=\Ev\Eu\EK:k0=^A:\
+	:k1=^B:kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:nd=^L:pf=^T:\
+	:po=^R:se=\EF:so=\EG1@A\EH:ue=\EF:up=^K:us=\EG1B@\EH:
+# From: Nathan Peterson <nathan@sco.com>, 03 Sep 1996
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+tvi9065|televideo 9065:\
+	:am:bw:hs:mi:ms:xn:xo:\
+	:co#80:it#8:li#25:lm#0:ma#4:vt#0:ws#30:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:SF=\E[%dS:SR=\E[%dT:UP=\E[%dA:ae=\E%:\
+	:al=\EE:as=\E$:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=^Z:\
+	:cm=\E=%+ %+ :cr=^M:cs=\E[%i%d;%dr:ct=\E3:dc=\EW:dl=\ER:\
+	:dm=\Er:do=^V:ds=\E_30\r:ec=\E[%d@:ed=\0:ei=\Er:fs=^M:ho=^^:\
+	:i1=\E"\E%\E'\E(\EG@\EO\EX\E[=5l\E[=6l\E[=7h\Ed\Er:\
+	:i2=\E<\E[=4l\E[=8h:if=/usr/share/tabset/stdcrt:im=\Eq:\
+	:ip=:is=\EF2\EG0\E\L:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:\
+	:k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:kD=\EW:kb=^H:\
+	:kd=^V:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:ll=\E[25;1H:mb=\EG2:\
+	:md=\EG\054:me=\EG0:mh=\EGp:mr=\EG4:nd=^L:nw=^M^J:\
+	:rp=\E[%r%db%.:se=\EG0:sf=^J:so=\EGt:sr=\Ej:st=\E1:ta=^I:\
+	:te=\E.3\Er\E[1;25r\E[25;0H:ti=\E.2:ts=\E[4;1v\E_30:\
+	:uc=\EG8\EG0:ue=\EG0:up=^K:us=\EG8:vb=\Eb\Ed:ve=\E.3:\
+	:vi=\E.0:vs=\E.2:
+
+#### Visual (vi)
+#
+# In September 1993, Visual Technology of Westboro, Massachusetts,
+# merged with White Pine Software of Nashua, New Hampshire.
+#
+# White Pine Software may be contacted at +1 603/886-9050.
+# Or visit White Pine on the World Wide Web at URL http://www.wpine.com.
+#
+
+# Visual 50 from Beau Shekita, BTL-Whippany <whuxlb!ejs>
+# Recently I hacked together the following termcap for Visual
+# Technology's Visual 50 terminal. It's a slight modification of
+# the vt52 termcap. 
+# It's intended to run when the Visual 50 is in vt52 emulation mode
+# (I know what you're thinking; if it's emulating a vt52, then why
+# another termcap? Well, it turns out that the Visual 50 can handle
+# :dl: and db(?) among other things, which the vt52 can't)
+# The termcap works OK for the most part. The only problem is on
+# character inserts. The whole line gets painfully redrawn for each
+# character typed. Any suggestions?
+# Beau's entry is combined with the vi50 entry from University of Wisconsin.
+# Note especially the :al: function.  :k4:-:k6: are really l4-l6 in
+# disguise; :k7:-:k9: are really l1-l3.
+vi50|visual 50:\
+	:am:bs:da:db:ms:pt:\
+	:co#80:it#8:li#24:\
+	:al=\EL:bl=^G:bt=4\Ez:cd=\EJ:ce=16\EK:cl=\EH\EJ:\
+	:cm=\EY%+ %+ :cr=^M:dl=3*\EM:do=\EB:ho=\EH:k1=\EP:k2=\EQ:\
+	:k3=\ER:k4=\EV:k5=\EE:k6=\E]:k7=\EL:k8=\Ev:k9=\EM:kb=^H:\
+	:kd=\EB:kh=\EH:kl=\ED:kr=\EC:ku=\EA:le=^H:nd=\EC:nl=^J:\
+	:nw=^M^J:se=\ET:sf=^J:so=\EU:sr=\EI:ta=^I:ue=\EW:up=\EA:\
+	:us=\ES:
+# this one was BSD & SCO's vi50
+vi50adm|visual 50 in adm3a mode:\
+	:am:ms:\
+	:co#80:it#8:li#24:\
+	:al=\EL:bl=^G:cd=\Ek:ce=\EK:cl=^Z:cm=\E=%+ %+ :cr=^M:dl=\EM:\
+	:do=^J:ho=\EH:kb=^H:kd=\EB:kh=\EH:kl=\ED:kr=\EC:ku=\EA:le=^H:\
+	:nd=^L:se=\ET:sf=^J:so=\EU:ta=^I:up=^K:
+# From: Jeff Siegal <jbs@quiotix.com>
+vi55|Visual 55:\
+	:am:bs:mi:ms:\
+	:co#80:it#8:li#24:\
+	:al=\EL:cd=\EJ:ce=\EK:cl=\Ev:cm=\EY%+ %+ :cs=\E_%+A%+A:\
+	:dc=\Ew:dl=\EM:do=^J:ei=\Eb:ho=\EH:im=\Ea:\
+	:is=\Ev\E_AX\Eb\EW\E9P\ET:kb=^H:kd=\EB:kl=\ED:kr=\EC:\
+	:ku=\EA:le=^H:nd=\EC:se=\ET:so=\EU:sr=\EI:ta=^I:up=\EA:
+
+# Visual 200 from BRL
+# The following switch settings are assumed for normal operation:
+#	FULL_DUPLEX		SCROLL			CR
+#	AUTO_NEW_LINE_ON	VISUAL_200_EMULATION_MODE
+# Other switches may be set for operator convenience or communication
+# requirements.
+# Character insertion is kludged in order to get around the "beep" misfeature.
+# (This cap is commented out because :im:/:ei: is more efficient -- esr)
+# Supposedly "4*" delays should be used for :al:, :cd:, :cl:, :dc:,
+# and :dl: strings, but we seem to get along fine without them.
+vi200|visual 200:\
+	:am:bs:mi:ms:pt:\
+	:co#80:it#8:kn#10:li#24:\
+	:ac=:ae=\EG:al=\EL:as=\EF:bl=^G:bt=\Ez:cd=\Ey:ce=\Ex:cl=\Ev:\
+	:cm=\EY%+ %+ :cr=^M:ct=\Eg:dc=\EO:dl=\EM:do=^J:ho=\EH:\
+	:k0=\E?p:k1=\E?q:k2=\E?r:k3=\E?s:k4=\E?t:k5=\E?u:k6=\E?v:\
+	:k7=\E?w:k8=\E?x:k9=\E?y:kA=\EL:kC=\Ev:kD=\EO:kE=\Et:kI=\Ei:\
+	:kL=\EM:kM=\Ej:kS=\EJ:kT=\E1:kb=^H:kd=\EB:ke=\E>:kh=\EH:\
+	:kl=\ED:kr=\EC:ks=\E=:kt=\E2:ku=\EA:le=^H:me=\E3\Eb:mh=\E4:\
+	:mk=\Ea:nd=\EC:pf=\EX:po=\EW:ps=\EH\E]:\
+	:r1=\E3\Eb\Ej\E\El\EG\Ec\Ek\EX:se=\E3:sf=^J:so=\E4:\
+	:sr=\EI:st=\E1:ta=^I:up=\EA:ve=\Ec:vs=\Ed:
+# The older Visuals didn't come with function keys. This entry uses
+# :ks: and :ke: so that the keypad keys can be used as function keys.
+# If your version of vi doesn't support function keys you may want
+# to use vi200-f.
+vi200-f|visual 200 no function keys:\
+	:is=\E3\Eb\Ej\E\\El\EG\Ed\Ek:k0=\E?p:k1=\E?q:k2=\E?r:\
+	:k3=\E?s:k4=\E?t:k5=\E?u:k6=\E?v:k7=\E?w:k8=\E?x:k9=\E?y:\
+	:ke=\E>:ks=\E=:se@:so@:\
+	:tc=vi200:
+vi200-rv|visual 200 reverse video:\
+	:se=\E3:so=\E4:sr@:ve@:vs@:tc=vi200:
+
+# the function keys are programmable but we don't reprogram them to their
+# default values with :is: because programming them is very verbose. maybe
+# an initialization file should be made for the 300 and they could be stuck
+# in it.
+# (vi300: added <rmam>/<smam> based on init string -- esr)
+vi300|visual 300 ansi x3.64:\
+	:am:bw:mi:xn:\
+	:co#80:li#24:\
+	:RA=\E[?7l:SA=\E[?7h:al=\E[L:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:dl=\E[M:\
+	:do=\E[B:ei=\E[4l:ho=\E[H:im=\E[4h:\
+	:is=\E[7s\E[2;3;4;20;?5;?6l\E[12;?7h\E[1Q\E[0;1(D\E[8s:\
+	:k1=\E_A\E\:k2=\E_B\E\:k3=\E_C\E\:k4=\E_D\E\:k5=\E_E\E\:\
+	:k6=\E_F\E\:k7=\E_G\E\:k8=\E_H\E\:k9=\E_I\E\:kd=\E[B:\
+	:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:me=\E[m:nd=\E[C:\
+	:se=\E[m:sf=^J:so=\E[1m:sr=\EM:ta=^I:ue=\E[m:up=\E[A:\
+	:us=\E[4m:
+# some of the vi300s have older firmware that has the command
+# sequence for setting editing extent reversed.
+vi300-old|visual 300 with old firmware (set edit extent reversed):\
+	:is=\E[7s\E[2;3;4;20;?5;?6l\E[12;?7h\E[2Q\E[0;1(D\E[8s:\
+	:tc=vi300:
+
+# Visual 500 prototype entry from University of Wisconsin.
+# The best place to look for the escape sequences is page A1-1 of the
+# Visual 500 manual.  The initialization sequence given here may be
+# overkill, but it does leave out some of the initializations which can
+# be done with the menus in set-up mode.
+# The :xp: line below is so that emacs can understand the padding requirements
+# of this slow terminal.  :xp: is 10 time the padding factor.
+# (vi500: removed unknown :xp#4: termcap;
+# also added empty <acsc> to suppress tic warning -- esr)
+vi500|visual 500:\
+	:am:mi:ms:\
+	:co#80:it#8:li#33:\
+	:ac=:ae=^O:al=3*\EL\Ex:as=^N:bt=4\Ez:cd=3*\Ey:ce=16\Ex:\
+	:cl=6*\Ev:cm=\EY%+ %+ :cr=^M:cs=\E(%+ %+ :dc=3*\EO:\
+	:dl=3*\EM:do=\EB:ei=\Ej:ho=\EH:im=\Ei:\
+	:is=\E3\E\001\E\007\E\003\Ek\EG\Ed\EX\El\E>\Eb\E\:\
+	:kb=^H:kd=\EB:kh=\EH:kl=\ED:kr=\EC:ku=\EA:le=^H:nd=\EC:\
+	:nw=^M^J:se=\E^G:sf=^J:so=\E^H:ta=8\011:ue=\E^C:up=\EA:\
+	:us=\E^D:
+
+# The visual 550 is a visual 300 with tektronix graphics,
+# and with 33 lines. clear screen is modified here to
+# also clear the graphics.
+vi550|visual 550 ansi x3.64:\
+	:li#33:\
+	:cl=\030\E[H\E[2J:tc=vi300:
+
+vi603|visual603|visual 603:\
+	:hs:mi:\
+	:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:\
+	:cs=\E[%i%d;%dr:dc=\E[P:dl=\E[M:ds=\EP2;1~\E\:ei=\E[4l:\
+	:fs=\E\:i1=\E>\E[?3l\E[?4l\E[?7h\E[?8h\E[1;24r:\
+	:im=\E[4h:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:\
+	:se=\E[27m:sf=\ED:so=\E[7m:sr=\EM:ts=\EP2~:ue=\E[24m:\
+	:up=\E[A:us=\E[4m:\
+	:tc=vt100:
+
+#### Wyse (wy)
+#
+#	Wyse Technology
+#	3471 North First Street
+#	San Jose, CA 95134
+#	Vox: (408)-473-1200
+#	Fax: (408) 473-1222
+#	Web: http://www.wyse.com
+#
+# Wyse sales can be reached by phone at 1-800-GET-WYSE.  Tech support is at
+# (800)-800-WYSE (option 5 gets you a human).  There's a Web page at the
+# obvious address, <http://www.wyse.com>.  They keep terminfo entries at
+# <http://www.wyse.co.uk/support/appnotes/idxappnt.htm>.
+#
+# Wyse bought out Link Technology, Inc. in 1990 and closed it down in 1995.
+# They now own the Qume and Amdek brands, too.  So these are the people to
+# talk with about all Link, Qume, and Amdek terminals.
+#
+# These entries include a few small fixes.
+# I canceled the bel capacities in the vb entries.
+# I made two trivial syntax fixes in the wyse30 entry.
+# I made some entries relative to adm+sgr.
+#
+#
+# Note: The wyse75, wyse85, and wyse99 have been discontinued.
+
+#	   Although the Wyse 30 can support more than one attribute
+#	it requires magic cookies to do so.  Many applications do not
+#	function well with magic cookies.  The following terminfo uses
+#	the protect mode to support one attribute (dim) without cookies.
+#	If more than one attribute is needed then the wy30-mc terminfo
+#	should be used.
+#
+wy30|wyse30|Wyse 30:\
+	:5i:am:bw:hs:mi:ms:xo:\
+	:Nl#8:co#80:lh#1:li#24:lw#8:ma#1:ws#45:\
+	:#2=\E{:&3=\Er:@8=\E7:LF=\EA11:LO=\EA10:\
+	:ac=0wa_h[jukslrmqnxqzttuyv]wpxv:ae=\EH^C:al=\EE:\
+	:as=\EH^B:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=\E+:cm=\E=%+ %+ :\
+	:cr=^M:ct=\E0:dc=\EW:dl=\ER:do=^J:ds=\EF\r:ei=\Er:fs=^M:\
+	:ho=^^:im=\Eq:ip=:is=\E'\E(\E\1363\E`9\016\024:k1=^A@\r:\
+	:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:k7=^AF\r:\
+	:k8=^AG\r:kA=\EE:kB=\EI:kD=\EW:kE=\ET:kI=\EQ:kL=\ER:kN=\EK:\
+	:kP=\EJ:kS=\EY:kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:\
+	:ll=^^^K:me=\E(\EH\003:mh=\E`7\E):mp=\E`7\E):nd=^L:\
+	:nw=^M^J:pf=^T:pn=\Ez%+/%s\r:po=^X:ps=\EP:px=\Ez%+?%s\177:\
+	:..sa=%?%p1%p5%p8%|%|%t\E`7\E)%e\E(%;%?%p9%t\EH\002%e\EH\003%;:\
+	:se=\E(:sf=\n:so=\E`7\E):sr=\Ej:st=\E1:ta=\011:ts=\EF:up=^K:\
+	:vb=\E`8\E`9:ve=\E`1:vi=\E`0:
+#
+#	This terminal description uses the non-hidden attribute mode
+#	(with magic cookie).
+#
+# (wy30-mc: added :ti: to suppress tic warning --esr)
+wy30-mc|wyse30-mc|wyse 30 with magic cookies:\
+	:ms@:\
+	:ma@:sg#1:\
+	:ae=\EG0\EH\003:as=\EG0\EH\002:mb=\EG2:\
+	:me=\EG0\E(\EH\003:mh=\EGp:mp=\EG0\E):\
+	:..sa=\EG%{48}%?%p2%p6%|%t%{8}%|%;%?%p1%p3%|%p6%|%t%{4}%|%;%?%p4%t%{2}%|%;%?%p1%p5%|%t%{64}%|%;%?%p7%t%{1}%|%;%c%?%p8%t\E)%e\E(%;%?%p9%t\EH\002%e\EH\003%;:\
+	:se=\EG0:so=\EG4:te=\EG0:ti=:\
+	:tc=wy30:tc=adm+sgr:
+#	The mandatory pause used by :vb: does not work with
+#	older versions of terminfo.  If you see this effect then
+#	unset xon and delete the / from the delay.
+#	i.e. change $<100/> to $<100>
+wy30-vb|wyse30-vb|wyse 30 visible bell:\
+	:bl@:tc=wy30:
+#
+#	   The Wyse 50 can support one attribute (e.g. Dim, Inverse,
+#	Normal) without magic cookies by using the protect mode.
+#	The following description uses this feature, but when more
+#	than one attribute is put on the screen at once, all attributes
+#	will be changed to be the same as the last attribute given.
+#	   The Wyse 50 can support more attributes when used with magic
+#	cookies.  The wy50-mc terminal description uses magic cookies
+#	to correctly handle multiple attributes on a screen.
+#
+wy50|wyse50|Wyse 50:\
+	:5i:am:bw:hs:mi:ms:xo:\
+	:Nl#8:co#80:lh#1:li#24:lw#8:ma#1:ws#45:\
+	:#2=\E{:%9=\EP:&3=\Er:@8=\E7:F1=^AJ\r:F2=^AK\r:F3=^AL\r:\
+	:F4=^AM\r:F5=^AN\r:F6=^AO\r:LF=\EA11:LO=\EA10:\
+	:ac=0wa_h[jukslrmqnxqzttuyv]wpxv:ae=\EH^C:al=\EE:\
+	:as=\EH^B:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=\E+:cm=\E=%+ %+ :\
+	:cr=^M:ct=\E0:dc=\EW:dl=\ER:do=^J:ds=\EF\r:ei=\Er:fs=^M:\
+	:ho=^^:i1=\E`\072\E`9:im=\Eq:ip=:is=\016\024\E'\E(:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:k9=^AH\r:k;=^AI\r:kA=\EE:kB=\EI:kD=\EW:\
+	:kE=\ET:kI=\EQ:kL=\ER:kN=\EK:kP=\EJ:kS=\EY:kb=^H:kd=^J:kh=^^:\
+	:kl=^H:kr=^L:ku=^K:le=^H:ll=^^^K:me=\E(\EH\003:mh=\E`7\E):\
+	:mp=\E`7\E):mr=\E`6\E):nd=^L:nw=^M^J:pf=^T:pn=\Ez%+/%s\r:\
+	:po=^X:ps=\EP:px=\Ez%+?%s\177:\
+	:..sa=%?%p1%p3%|%t\E`6\E)%e%p5%p8%|%t\E`7\E)%e\E(%;%?%p9%t\EH\002%e\EH\003%;:\
+	:se=\E(:sf=\n:so=\E`6\E):sr=\Ej:st=\E1:ta=^I:ts=\EF:up=^K:\
+	:vb=\E`8\E`9:ve=\E`1:vi=\E`0:
+#
+#	This terminal description uses the non-hidden attribute mode
+#	(with magic cookie).
+#
+#	The mandatory pause used by flash does not work with some
+#	older versions of terminfo.  If you see this effect then
+#	unset :xo: and delete the / from the delay.
+#	i.e. change $<100/> to $<100>
+# (wy50-mc: added :ti: to suppress tic warning --esr)
+wy50-mc|wyse50-mc|wyse 50 with magic cookies:\
+	:ms@:\
+	:ma@:sg#1:\
+	:ae=\EG0\EH\003:as=\EG0\EH\002:mb=\EG2:\
+	:me=\EG0\E(\EH\003:mh=\EGp:mp=\EG0\E):mr=\EG4:\
+	:..sa=\EG%{48}%?%p2%p6%|%t%{8}%|%;%?%p1%p3%|%p6%|%t%{4}%|%;%?%p4%t%{2}%|%;%?%p1%p5%|%t%{64}%|%;%?%p7%t%{1}%|%;%c%?%p8%t\E)%e\E(%;%?%p9%t\EH\002%e\EH\003%;:\
+	:se=\EG0:so=\EGt:te=\EG0:ti=:\
+	:tc=wy50:tc=adm+sgr:
+wy50-vb|wyse50-vb|wyse 50 visible bell:\
+	:bl@:tc=wy50:
+wy50-w|wyse50-w|wyse 50 132-column:\
+	:Nl#16:co#132:lw#7:ws#97:\
+	:cm=\Ea%i%dR%dC:dc=\EW:i1=\E`;\E`9:tc=wy50:
+wy50-wvb|wyse50-wvb|wyse 50 132-column visible bell:\
+	:bl@:\
+	:tc=wy50-w:
+#
+#	The Wyse 350 is a Wyse 50 with color.
+#	Unfortunately this means that it has magic cookies.
+#	The color attributes are designed to overlap the reverse, dim and
+#	underline attributes.  This is nice for monochrome applications
+#	because you can make underline stuff green (or any other color)
+#	but for true color applications it's not so hot because you cannot
+#	mix color with reverse, dim or underline.
+#	    To further complicate things one of the attributes must be
+#	black (either the foreground or the background).  In reverse video
+#	the background changes color with black letters.  In normal video
+#	the foreground changes colors on a black background.  
+#	    This terminfo uses some of the more advanced features of curses
+#	to display both color and blink.  In the final analysis I am not
+#	sure that the wy350 runs better with this terminfo than it does
+#	with the wy50 terminfo (with user adjusted colors).
+#
+#	The mandatory pause used by flash does not work with
+#	older versions of terminfo.  If you see this effect then
+#	unset xon and delete the / from the delay.
+#	i.e. change $<100/> to $<100>
+#
+# Bug: The <op> capability resets attributes.
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+wy350|wyse350|Wyse 350:\
+	:5i:am:bw:hs:mi:xo:\
+	:Co#8:NC#55:Nl#8:co#80:lh#1:li#24:lw#8:pa#8:sg#1:ws#45:\
+	:#2=\E{:%9=\EP:&3=\Er:@8=\E7:F1=^AJ\r:F2=^AK\r:F3=^AL\r:\
+	:F4=^AM\r:F5=^AN\r:F6=^AO\r:LF=\EA11:LO=\EA10:Sb=:\
+	:ac=0wa_h[jukslrmqnxqzttuyv]wpxv:ae=\EG0\EH\003:al=\EE:\
+	:as=\EG0\EH\002:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=\E+:\
+	:cm=\E=%+ %+ :cr=^M:ct=\E0:dc=\EW:dl=\ER:do=^J:ds=\EF\r:\
+	:ei=\Er:fs=^M:ho=^^:i1=\E`\072\E`9:i2=\E%?:im=\Eq:ip=:\
+	:is=\016\024\E'\E(:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:\
+	:k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:k;=^AI\r:\
+	:kA=\EE:kB=\EI:kD=\EW:kE=\ET:kI=\EQ:kL=\ER:kN=\EK:kP=\EJ:\
+	:kS=\EY:kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:ll=^^^K:\
+	:mb=\EG2:me=\EG0\E(\EH\003%{0}%PA%{0}%PC:mh=\EGp:\
+	:mp=\EG0\E):nd=^L:nw=^M^J:oc=\E%?:op=\EG0:pf=^T:\
+	:pn=\Ez%+/%s\r:po=^X:ps=\EP:px=\Ez%+?%s\177:sf=\n:sr=\Ej:\
+	:st=\E1:ta=^I:ts=\EF:up=^K:vb=\E`8\E`9:ve=\E`1:vi=\E`0:\
+	:tc=adm+sgr:
+wy350-vb|wyse350-vb|wyse 350 visible bell:\
+	:bl@:tc=wy350:
+wy350-w|wyse350-w|wyse 350 132-column:\
+	:Nl#16:co#132:lw#7:ws#97:\
+	:cm=\Ea%i%dR%dC:dc=\EW:i1=\E`;\E`9:tc=wy350:
+wy350-wvb|wyse350-wvb|wyse 350 132-column visible bell:\
+	:bl@:\
+	:tc=wy350-w:
+#
+#	This terminfo description is untested.
+#	The wyse100 emulates an adm31, so the adm31 entry should work.
+#
+wy100|wyse 100:\
+	:hs:mi:\
+	:co#80:li#24:sg#1:\
+	:al=\EE:bl=^G:cd=\EY:ce=\ET:cl=\E;:cm=\E=%+ %+ :cr=^M:\
+	:dc=\EW:dl=\ER:do=^J:ds=\EA31:ei=\Er:fs=^M:im=\Eq:is=\Eu\E0:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:kb=^H:kd=^J:kh=\E{:kl=^H:kr=^L:ku=^K:\
+	:le=^H:mk@:nd=^L:sf=^J:ts=\EF:up=^K:\
+	:tc=adm+sgr:
+#
+#	The Wyse 120/150 has most of the features of the Wyse 60.
+#	This terminal does not need padding up to 9600 baud!
+#	:ms: should be set but the clear screen fails when in
+#	alt-charset mode.  Try \EcE\s\s\E+\s if the screen is really clear
+#	then set :ms:.
+#
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+wy120|wyse120|wy150|wyse150|Wyse 120/150:\
+	:am:bw:hs:km:mi:ms:xo:\
+	:co#80:it#8:li#24:pb#9601:ws#45:\
+	:ae=\EcD:al=\EE:as=\EcE:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=\E+:\
+	:cm=\E=%+ %+ :cr=^M:ct=\E0:dc=\EW:dl=\ER:do=^J:ds=\EF\r:\
+	:ei=\Er:fs=^M:ho=^^:i1=\EcB0\EcC1:i2=\EwJ\Ew1:im=\Eq:ip=:\
+	:is=\Ed$\EcD\E'\Er\EH\003\Ed/\EO\Ee1\Ed*\E`@\E`9\E`1\016\024\El:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:k9=^AH\r:kD=\EW:kI=\EQ:kN=\EK:kP=\EJ:\
+	:kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:ll=^^^K:mb=\EG2:\
+	:me=\E(\EH\003\EG0\EcD:mh=\EGp:nd=^L:nw=\r\n:sf=\n:\
+	:so=\EGt:sr=\Ej:st=\E1:ta=\011:te=\Ew1:ti=\Ew0:ts=\EF:up=^K:\
+	:vb=\E`8\E`9:ve=\E`1:vi=\E`0:\
+	:tc=adm+sgr:
+#
+wy120-w|wyse120-w|wy150-w|wyse150-w|wyse 120/150 132-column:\
+	:Nl#16:co#132:lw#7:ws#97:\
+	:cm=\Ea%i%dR%dC:dc=\EW:ip=:r2=\E`;:tc=wy120:
+#
+wy120-25|wyse120-25|wy150-25|wyse150-25|wyse 120/150 80-column 25-lines:\
+	:Nl@:lh@:li#25:lw@:\
+	:pn@:r3=\EwG\Ee):tc=wy120:
+#
+wy120-25-w|wyse120-25-w|wy150-25-w|wyse150-25-w|wyse 120/150 132-column 25-lines:\
+	:Nl@:lh@:li#25:lw@:\
+	:pn@:r3=\EwG\Ee):tc=wy120-w:
+#
+wy120-vb|wyse120-vb|wy150-vb|wyse150-vb|Wyse 120/150 visible bell:\
+	:bl@:\
+	:tc=wy120:
+#
+wy120-w-vb|wy120-wvb|wyse120-wvb|wy150-w-vb|wyse150-w-vb|Wyse 120/150 132-column visible bell:\
+	:bl@:\
+	:tc=wy120-w:
+#
+#	The Wyse 60 is like the Wyse 50 but with more padding.
+#	The reset strings are slow and the pad times very depending
+#	on other parameters such as font loading.  I have tried
+#	to follow the following outline:
+#
+#		<rs1> -> set personality
+#		<rs2> -> set number of columns
+#		<rs3> -> set number of lines
+#		:i1: -> select the proper font
+#		:is: -> do the initialization
+#		:i3: -> set up display memory (2 pages)
+#
+#	The Wyse 60's that have vt100 emulation are slower than the
+#	older Wyse 60's.  This change happened mid-1987.
+#	The capabilities effected are :dc: :dl: :al: :sf: :sr:
+#
+#	The meta key is only half right.  This terminal will return the
+#	high order bit set when you hit CTRL-function_key
+#
+#	It may be useful to assign two function keys with the
+#	values  \E=(\s  look at old data in page 1
+#	        \E=W,   look at bottom of page 1
+#	where \s is a space ( ).
+#
+#	Note:
+#	   The Wyse 60 runs faster when the XON/XOFF
+#	   handshake is turned off.
+#
+# (wy60: we use \E{ rather than ^^ for home (both are documented) to avoid
+# a bug reported by Robert Dunn, <rcdii@inlink.com> -- esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+wy60|wyse60|Wyse 60:\
+	:am:bw:hs:km:mi:ms:\
+	:co#80:li#24:ws#45:\
+	:ae=\EcD:al=\EE:as=\EcE:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=\E+:\
+	:cm=\E=%+ %+ :cr=^M:ct=\E0:dc=\EW:dl=\ER:do=^J:ds=\EF\r:\
+	:ei=\Er:fs=^M:ho=\E{:i1=\EcB0\EcC1:i2=\EwJ\Ew1:im=\Eq:ip=:\
+	:is=\Ed$\EcD\E'\Er\EH\003\Ed/\EO\Ee1\Ed*\E`@\E`9\E`1\016\024\El:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:k9=^AH\r:kD=\EW:kI=\EQ:kN=\EK:kP=\EJ:\
+	:kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:ll=\E{^K:mb=\EG2:\
+	:me=\E(\EH\003\EG0\EcD:mh=\EGp:nd=^L:nw=\r\n:sf=\n:\
+	:so=\EGt:sr=\Ej:st=\E1:ta=\011:te=\Ew1:ti=\Ew0:ts=\EF:up=^K:\
+	:vb=\E`8\E`9:ve=\E`1:vi=\E`0:\
+	:tc=adm+sgr:
+#
+wy60-w|wyse60-w|wyse 60 132-column:\
+	:Nl#16:co#132:lw#7:ws#97:\
+	:cm=\Ea%i%dR%dC:dc=\EW:ip=:r2=\EeF\E`;:tc=wy60:
+#
+wy60-25|wyse60-25|wyse 60 80-column 25-lines:\
+	:Nl@:lh@:li#25:lw@:\
+	:pn@:r3=\EwG\Ee):tc=wy60:
+wy60-25-w|wyse60-25-w|wyse 60 132-column 25-lines:\
+	:Nl@:lh@:li#25:lw@:\
+	:pn@:r3=\EwG\Ee):tc=wy60-w:
+#
+wy60-42|wyse60-42|wyse 60 80-column 42-lines:\
+	:li#42:\
+	:al=\EE:cd=\Ey:cl=\E+:cm=\E=%+ %+ :dc=\EW:dl=\ER:\
+	:i1=\EcB2\EcC3:ip=:nw=\r\n:r3=\Ee*:sf=\n:sr=\Ej:tc=wy60:
+wy60-42-w|wyse60-42-w|wyse 60 132-column 42-lines:\
+	:Nl#16:co#132:lw#7:ws#97:\
+	:cd=\Ey:cl=\E+:cm=\Ea%i%dR%dC:dc=\EW:ho=\036:ip=:nw=\r\n:\
+	:r2=\EeF\E`;:\
+	:tc=wy60-42:
+#
+wy60-43|wyse60-43|wyse 60 80-column 43-lines:\
+	:Nl@:lh@:li#43:lw@:\
+	:pn@:r3=\Ee+:tc=wy60-42:
+wy60-43-w|wyse60-43-w|wyse 60 132-column 43-lines:\
+	:Nl@:lh@:li#43:lw@:\
+	:pn@:r3=\Ee+:tc=wy60-42-w:
+#
+wy60-vb|wyse60-vb|Wyse 60 visible bell:\
+	:bl@:tc=wy60:
+wy60-w-vb|wy60-wvb|wyse60-wvb|Wyse 60 132-column visible bell:\
+	:bl@:\
+	:tc=wy60-w:
+
+#	The Wyse-99GT looks at lot like the Wyse 60 except that it
+#	does not have the 42/43 line mode.  In the Wyse-60 the "lines"
+#	setup parameter controls the number of lines on the screen.
+#	For the Wyse 99GT the "lines" setup parameter controls the
+#	number of lines in a page.  The screen can display 25 lines max.
+#	    The Wyse-99GT also has personalities for the VT220 and
+#	Tektronix 4014.  But this has no bearing on the native mode.
+#
+#	(msgr) should be set but the clear screen fails when in
+#	alt-charset mode.  Try \EcE\s\s\E+\s if the screen is really clear
+#	then set msgr, else use msgr@.
+#
+#	u0 -> enter Tektronix mode
+#	u1 -> exit Tektronix mode
+#
+wy99gt|wyse99gt|Wyse 99gt:\
+	:ms@:\
+	:al=\EE:cd=\Ey:ce=\Et:cl=\E+:dc=\EW:dl=\ER:i2=\Ew0:ip=:nw@:\
+	:r2=\E`\072:sf=\n:sr=\Ej:ta=\011:te=\Ew0:ti=\Ew1:\
+	:u0=\E~>\E8:u1=\E[42h:vb=\E`8\E`9:tc=wy60:
+#
+wy99gt-w|wyse99gt-w|wyse 99gt 132-column:\
+	:Nl#16:co#132:lw#7:ws#97:\
+	:cd=\Ey:cl=\E+:cm=\Ea%i%dR%dC:dc=\EW:ip=:r2=\E`;:tc=wy99gt:
+#
+wy99gt-25|wyse99gt-25|wyse 99gt 80-column 25-lines:\
+	:Nl@:lh@:li#25:lw@:\
+	:pn@:r2=\E`\072:r3=\EwG\Ee):tc=wy99gt:
+#
+wy99gt-25-w|wyse99gt-25-w|wyse 99gt 132-column 25-lines:\
+	:Nl@:lh@:li#25:lw@:\
+	:pn@:r2=\E`;:tc=wy99gt-w:
+#
+wy99gt-vb|wyse99gt-vb|Wyse 99gt visible bell:\
+	:bl@:tc=wy99gt:
+#
+wy99gt-w-vb|wy99gt-wvb|wyse99gt-wvb|Wyse 99gt 132-column visible bell:\
+	:bl@:\
+	:tc=wy99gt-w:
+#
+#	The Wyse 160 is combination of the WY-60 and the WY-99gt.
+#	The reset strings are slow and the pad times very depending
+#	on other parameters such as font loading.  I have tried
+#	to follow the following outline:
+#
+#		<rs1> -> set personality
+#		<rs2> -> set number of columns
+#		<rs3> -> set number of lines
+#		:i1: -> select the proper font
+#		:is: -> do the initialization
+#		:i3: -> set up display memory (2 pages)
+#
+#	The display memory may be used for either text or graphics.
+#	When "Display Memory = Shared" the terminal will have more pages
+#	but garbage may be left on the screen when you switch from
+#	graphics to text.  If "Display Memory = Unshared" then the
+#	text area will be only one page long.
+#
+# (wy160: we use \E{ rather than ^^ for home (both are documented) to avoid
+# a bug reported by Robert Dunn, <rcdii@inlink.com> -- esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+wy160|wyse160|Wyse 160:\
+	:am:bw:hs:km:mi:ms:\
+	:co#80:li#24:ws#38:\
+	:ae=\EcD:al=\EE:as=\EcE:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=\E+:\
+	:cm=\E=%+ %+ :cr=^M:ct=\E0:dc=\EW:dl=\ER:do=^J:ds=\EF\r:\
+	:ei=\Er:fs=^M:ho=\E{:i1=\EcB0\EcC1:i2=\Ew0:im=\Eq:ip=:\
+	:is=\Ed$\EcD\E'\Er\EH\003\Ed/\EO\Ee1\Ed*\E`@\E`9\E`1\016\024\El:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:k9=^AH\r:kD=\EW:kI=\EQ:kN=\EK:kP=\EJ:\
+	:kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:ll=\E{^K:mb=\EG2:\
+	:me=\E(\EH\003\EG0\EcD:mh=\EGp:nd=^L:nw=\r\n:sf=\n:\
+	:so=\EGt:sr=\Ej:st=\E1:ta=^I:te=\Ew0:ti=\Ew1:ts=\EF:up=^K:\
+	:vb=\E`8\E`9:ve=\E`1:vi=\E`0:\
+	:tc=adm+sgr:
+#
+wy160-w|wyse160-w|wyse 160 132-column:\
+	:Nl#16:co#132:lw#7:ws#90:\
+	:cm=\Ea%i%dR%dC:dc=\EW:r2=\EeF\E`;:tc=wy160:
+#
+wy160-25|wyse160-25|wyse 160 80-column 25-lines:\
+	:Nl@:lh@:li#25:lw@:\
+	:pn@:r3=\EwG\Ee):tc=wy160:
+wy160-25-w|wyse160-25-w|wyse 160 132-column 25-lines:\
+	:Nl@:lh@:li#25:lw@:\
+	:pn@:r3=\EwG\Ee):tc=wy160-w:
+#
+wy160-42|wyse160-42|wyse 160 80-column 42-lines:\
+	:li#42:\
+	:al=\EE:cd=\Ey:cl=\E+:dl=\ER:i1=\EcB2\EcC3:nw=\r\n:r3=\Ee*:\
+	:sf=\n:sr=\Ej:\
+	:tc=wy160:
+wy160-42-w|wyse160-42-w|wyse 160 132-column 42-lines:\
+	:Nl#16:co#132:lw#7:ws#90:\
+	:cm=\Ea%i%dR%dC:dc=\EW:ip=:r2=\EeF\E`;:tc=wy160-42:
+#
+wy160-43|wyse160-43|wyse 160 80-column 43-lines:\
+	:Nl@:lh@:li#43:lw@:\
+	:pn@:r3=\Ee+:tc=wy160-42:
+wy160-43-w|wyse160-43-w|wyse 160 132-column 43-lines:\
+	:Nl@:lh@:li#43:lw@:\
+	:pn@:r3=\Ee+:tc=wy160-42-w:
+#
+wy160-vb|wyse160-vb|Wyse 160 visible bell:\
+	:bl@:tc=wy160:
+wy160-w-vb|wy160-wvb|wyse160-wvb|Wyse 160 132-column visible bell:\
+	:bl@:\
+	:tc=wy160-w:
+#
+#	The Wyse 75 is a vt100 lookalike without advanced video.
+#
+#	   The Wyse 75 can support one attribute (e.g. Dim, Inverse,
+#	Underline) without magic cookies.  The following description
+#	uses this capability, but when more than one attribute is
+#	put on the screen at once, all attributes will be changed
+#	to be the same as the last attribute given.
+#	   The Wyse 75 can support more attributes when used with magic
+#	cookies.  The wy75-mc terminal description uses magic cookies
+#	to correctly handle multiple attributes on a screen.
+#
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+wy75|wyse75|wyse 75:\
+	:am:hs:mi:ms:xn:xo:\
+	:co#80:li#24:ma#1:pb#1201:ws#78:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:K1=\EOw:K2=\EOu:K3=\EOy:K4=\EOq:K5=\EOs:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:bt=\E[Z:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:\
+	:ds=\E[>\054\001\001\E[>-\001\001:ec=\E[%dX:ei=\E[4l:\
+	:fs=^A:ho=\E[H:\
+	:i1=\E[2;4;20;30l\E[?1;10l\E[12h\E[?7;8;25h:i2=\E[m:\
+	:im=\E[4h:ip=:is=\E>\E(B\E)0\017:k1=\E[?5i:k2=\E[?3i:\
+	:k3=\E[2i:k4=\E[@:k5=\E[M:k6=\E[17~:k7=\E[18~:k8=\E[19~:\
+	:k9=\E[20~:kI=\E[@:kN=\E[6~:kP=\E[5~:kb=^H:kd=\E[B:ke=\E>:\
+	:kh=\E[H:kl=\E[D:kr=\E[C:ks=\E[?1l\E[?7h\E=:ku=\E[A:le=^H:\
+	:me=\E[m\017:mh=\E[0t\E[2m:mr=\E[1t\E[7m:nd=\E[C:rc=\E8:\
+	:sc=\E7:se=\E[m:sf=\n:so=\E[1t\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:ts=\E[>\054\001:ue=\E[m:up=\E[A:us=\E[2t\E[4m:\
+	:vb=\E[30h\E\054\E[30l:ve=\E[?25h:vi=\E[?25l:
+#
+#	This terminal description uses the non-hidden attribute mode
+#	(with magic cookie).
+#
+wy75-mc|wyse75-mc|wyse 75 with magic cookies:\
+	:ms@:\
+	:ma@:sg#1:\
+	:ae=\E[0p\017:as=\E[0p\016:i2=\E[m\E[p:mb=\E[2p:\
+	:me=\E[0p\017:mh=\E[1p:mk=\E[4p:mr=\E[16p:\
+	:..sa=\E[%{0}%?%p2%p6%|%t%{8}%|%;%?%p1%p3%|%p6%|%t%{16}%|%;%?%p4%t%{2}%|%;%?%p1%p5%|%t%{1}%|%;%?%p7%t%{4}%|%;%dp%?%p9%t\016%e\017%;:\
+	:se=\E[0p:so=\E[17p:ue=\E[0p:us=\E[8p:\
+	:tc=wy75:
+wy75-vb|wyse75-vb|wyse 75 with visible bell:\
+	:pb@:\
+	:bl@:tc=wy75:
+wy75-w|wyse75-w|wyse 75 in 132 column mode:\
+	:co#132:ws#130:\
+	:r2=\E[35h\E[?3h:tc=wy75:
+wy75-wvb|wyse75-wvb|wyse 75 with visible bell 132 columns:\
+	:pb@:\
+	:bl@:tc=wy75-w:
+#
+#	Wyse 85 emulating a vt220 7 bit mode.
+#		24 line screen with status line.
+#
+#	The vt220 mode permits more function keys but it wipes out
+#	the escape key.  I strongly recommend that <f11> be set to
+#	escape (esc).
+#	The terminal may have to be set for 8 data bits and 2 stop
+#	bits for the arrow keys to work.
+#	The Wyse 85 runs faster with XON/XOFF enabled.  Also the
+#	:DC: and :IC: work best when XON/XOFF is set.  :IC: and
+#	:DC: leave trash on the screen when used without XON/XOFF.
+#
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+wy85|wyse85|wyse 85:\
+	:am:hs:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:ws#80:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:K1=\EOw:K2=\EOu:K3=\EOy:K4=\EOq:K5=\EOs:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:bt=\E[Z:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:ds=\E[40l:\
+	:ec=\E[%dX:ei=\E[4l:fs=\E[1;24r\E8:ho=\E[H:\
+	:i1=\E[62;1"p\E[?5W:i2=\E>\E(B\E)0\017\E[m:im=\E[4h:ip=:\
+	:is=\E[2;4;20;30l\E[?1;4;10;16l\E[12h\E[?7;8;25h:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k6=\E[17~:k7=\E[18~:\
+	:k8=\E[19~:k9=\E[20~:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:\
+	:kb=^H:kd=\E[B:ke=\E>:kh=\E[26~:kl=\E[D:kr=\E[C:\
+	:ks=\E[?1l\E=:ku=\E[A:le=^H:mb=\E[5m:md=\E[1m:me=\E[m\017:\
+	:mh=\E[2m:mr=\E[7m:nd=\E[C:rc=\E8:sc=\E7:se=\E[m:sf=\n:\
+	:so=\E[7m:sr=\EM:st=\EH:ta=\011:\
+	:ts=\E[40h\E7\E[25;%i%p1%dH:ue=\E[m:up=\E[A:us=\E[4m:\
+	:vb=\E[30h\E\054\E[30l:ve=\E[?25h:vi=\E[?25l:
+#
+#	Wyse 85 with visual bell.
+wy85-vb|wyse85-vb|wyse 85 with visible bell:\
+	:bl@:vb=\E[30h\E\054\E[30l:tc=wy85:
+#
+#	Wyse 85 in 132-column mode.
+wy85-w|wyse85-w|wyse 85 in 132-column mode:\
+	:co#132:ws#132:\
+	:r2=\E[35h\E[?3h:tc=wy85:
+#
+#	Wyse 85 in 132-column mode with visual bell.
+wy85-wvb|wyse85-wvb|wyse 85 with visible bell 132-columns:\
+	:bl@:\
+	:tc=wy85-w:
+#
+#	Wyse 185 emulating a vt320 7 bit mode.
+#
+#	This terminal always displays 25 lines.  These lines may be used
+#	as 24 data lines and a terminal status line (top or bottom) or
+#	25 data lines.  The 48 and 50 line modes change the page size
+#	and not the number of lines on the screen.
+#
+#	The Compose Character key can be used as a meta key if changed
+#	by set-up.
+#
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+wy185|wyse185|wyse 185:\
+	:am:hs:km:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:ws#80:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:K1=\EOw:K2=\EOu:K3=\EOy:K4=\EOq:K5=\EOs:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:bt=\E[Z:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:\
+	:ds=\E7\E[99;0H\E[K\E8:ec=\E[%dX:ei=\E[4l:\
+	:fs=\E[1;24r\E8:ho=\E[H:i1=\E[?5W:\
+	:i2=\E>\E(B\E)0\017\E[m:im=\E[4h:ip=:\
+	:is=\E[2;4;20;30l\E[?1;4;10;16l\E[12h\E[?7;8;25h:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k6=\E[17~:k7=\E[18~:\
+	:k8=\E[19~:k9=\E[20~:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:\
+	:kb=^H:kd=\E[B:ke=\E>:kh=\E[26~:kl=\E[D:kr=\E[C:\
+	:ks=\E[?1l\E=:ku=\E[A:le=^H:mb=\E[5m:md=\E[1m:me=\E[m\017:\
+	:mh=\E[2m:mr=\E[7m:nd=\E[C:rc=\E8:sc=\E7:se=\E[27m:sf=\n:\
+	:so=\E[7m:sr=\EM:st=\EH:ta=^I:te=\E[ R:ti=\E[ Q:\
+	:ts=\E7\E[99;%i%p1%dH:ue=\E[24m:up=\E[A:us=\E[4m:\
+	:vb=\E[30h\E\054\E[30l:ve=\E[34h\E[?25h:vi=\E[?25l:\
+	:vs=\E[?25h\E[34l:
+#
+#	Wyse 185 with 24 data lines and top status (terminal status)
+wy185-24|wyse185-24|wyse 185 with 24 data lines:\
+	:hs@:\
+	:ds@:fs@:r3=\E[?5l\E[47h\E[40l\E[1;24r:ts@:tc=wy185:
+#
+#	Wyse 185 with visual bell.
+wy185-vb|wyse185-vb|wyse 185+flash:\
+	:bl@:tc=wy185:
+#
+#	Wyse 185 in 132-column mode.
+wy185-w|wyse185-w|wyse 185 in 132-column mode:\
+	:co#132:ws#132:\
+	:DC=\E[%dP:IC=\E[%d@:dc=\E[P:ei=:im=:ip=:r2=\E[35h\E[?3h:tc=wy185:
+#
+#	Wyse 185 in 132-column mode with visual bell.
+wy185-wvb|wyse185-wvb|wyse 185+flash+132 cols:\
+	:bl@:tc=wy185-w:
+
+# wy325 terminfo entries
+# Done by Joe H. Davis        3-9-92
+
+# lines 25  columns 80
+#
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+wy325|wyse325|Wyse epc:\
+	:5i:am:bw:hs:mi:\
+	:Nl#8:co#80:lh#1:li#24:lw#8:pb#9601:ws#45:\
+	:#2=\E{:%9=\EP:&3=\Er:@8=\E7:F1=^AJ\r:F2=^AK\r:F3=^AL\r:\
+	:F4=^AM\r:F5=^AN\r:F6=^AO\r:LF=\EA11:LO=\EA10:RA=\Ed.:\
+	:SA=\Ed/:\
+	:ac=+/\054.0[Iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~:\
+	:ae=\EcD:al=\EE:as=\EcE:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=\E+:\
+	:cm=\E=%+ %+ :cr=^M:ct=\E0:dc=\EW:dl=\ER:do=^J:ds=\EF\r:\
+	:ei=\Er:fs=^M:ho=^^:i1=\EcB0\EcC1:i2=\Ew0:im=\Eq:ip=:\
+	:is=\EcD\E'\Er\EH\003\Ed/\EO\Ee1\Ed*\E`@\E`9\E`1\016\024\El:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:k9=^AH\r:k;=^AI\r:kA=\EE:kB=\EI:kD=\EW:\
+	:kE=\ET:kI=\Eq:kL=\ER:kN=\EK:kP=\EJ:kS=\EY:kb=^H:kd=^J:kh=^^:\
+	:kl=^H:kr=^L:ku=^K:le=^H:ll=^^^K:mb=\EG2:\
+	:me=\E(\EH\003\EG0\EcD:mh=\EGp:mp=\E):nd=^L:pf=^T:\
+	:pl=\EZ2%+?%s\177:pn=\Ez%+/%s\r:po=\Ed#:ps=\EP:\
+	:px=\EZ1%+?%s\177:r1=\E~\041\E~4:r2=\EeF\E`\072:\
+	:r3=\EwG\Ee(:sf=\n:so=\EGt:sr=\Ej:st=\E1:ta=^I:te=\Ew0:\
+	:ti=\Ew1:ts=\EF:up=^K:vb=\E`8\E`9:ve=\E`1:vi=\E`0:\
+	:tc=adm+sgr:
+
+#
+# lines 24  columns 80  vb 
+#
+wy325-vb|wyse325-vb|wyse-325 with visual bell:\
+	:bl@:tc=wy325:
+
+#
+# lines 24  columns 132
+#
+wy325-w|wyse325-w|wy325w-24|wyse-325 in wide mode:\
+	:Nl#16:co#132:lw#7:ws#97:\
+	:cm=\Ea%i%dR%dC:dc=\EW:ip=:r2=\E`;:tc=wy325:
+#
+# lines 25  columns 80
+#
+wy325-25|wyse325-25|wy325-80|wyse-325|wyse-325 25 lines:\
+	:Nl@:lh@:li#25:lw@:\
+	:pn@:r3=\EwG\Ee):tc=wy325:
+#
+# lines 25  columns 132
+#
+wy325-25w|wyse325-25w|wy325 132 columns:\
+	:Nl@:lh@:li#25:lw@:\
+	:pn@:r3=\EwG\Ee):tc=wy325-w:
+#
+# lines 25  columns 132  vb 
+#
+wy325-w-vb|wy325-wvb|wyse325-wvb|wyse-325 wide mode reverse video:\
+	:bl@:\
+	:tc=wy325-w:
+
+#
+# lines 42  columns 80
+#
+wy325-42|wyse325-42|wyse-325 42 lines:\
+	:Nl@:lh@:li#42:lw@:\
+	:pn@:r3=\EwG\Ee):tc=wy325:
+#
+# lines 42  columns 132
+#
+wy325-42w|wyse325-42w|wyse-325 42 lines wide mode:\
+	:Nl@:lh@:li#42:lw@:\
+	:pn@:r3=\EwG\Ee):tc=wy325-w:
+#
+# lines 42  columns 132  vb 
+#
+wy325-42w-vb|wy325-42wvb|wyse-325 42 lines wide mode visual bell:\
+	:bl@:\
+	:tc=wy325-w:
+#
+# lines 43  columns 80
+#
+wy325-43|wyse325-43|wyse-325 43 lines:\
+	:Nl@:lh@:li#43:lw@:\
+	:pn@:tc=wy325:
+#
+# lines 43  columns 132
+#
+wy325-43w|wyse325-43w|wyse-325 43 lines wide mode:\
+	:Nl@:lh@:li#43:lw@:\
+	:pn@:r3=\EwG\Ee):tc=wy325-w:
+#
+# lines 43  columns 132  vb 
+#
+wy325-43w-vb|wy325-43wvb|wyse-325 43 lines wide mode visual bell:\
+	:bl@:\
+	:tc=wy325-w:
+
+#	Wyse 370 -- 24 line screen with status line.
+#
+#	The terminal may have to be set for 8 data bits and 2 stop
+#	bits for the arrow keys to work.
+#
+#	If you change keyboards the terminal will send different
+#	escape sequences.
+#	The following definition is for the basic terminal without
+#	function keys.
+#
+#	<u0> -> enter Tektronix 4010/4014 mode
+#	<u1> -> exit  Tektronix 4010/4014 mode
+#	<u2> -> enter ASCII mode (from any ANSI mode)
+#	<u3> -> exit  ASCII mode (goto native ANSI mode)
+#	<u4> -> enter Tek 4207 ANSI mode (from any ANSI mode)
+#	<u5> -> exit  Tek 4207 mode (goto native ANSI mode)
+#
+# Bug: The <op> capability resets attributes.
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+wy370-nk|wyse 370 without function keys:\
+	:am:hs:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:ws#80:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:\
+	:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:ds=\E[40l:\
+	:ec=\E[%dX:ei=\E[4l:fs=\E[1;24r\E8:ho=\E[H:\
+	:i1=\E[90;1"p\E[?5W:i2=\E>\017\E)0\E(B\E[63;0w\E[m:\
+	:im=\E[4h:ip=:\
+	:is=\E[2;4;20;30;40l\E[?1;10;16l\E[12h\E[?7;8;25h:\
+	:ke=\E>:ks=\E[?1l\E=:le=^H:mb=\E[5m:md=\E[1m:me=\E[m\017:\
+	:mh=\E[2m:mr=\E[7m:nd=\E[C:rc=\E8:sc=\E7:se=\E[27m:sf=\n:\
+	:so=\E[7m:sr=\EM:st=\EH:ta=\011:te=\E[ R:ti=\E[ Q:\
+	:ts=\E[40l\E[40h\E7\E[99;%i%p1%dH:ue=\E[24m:up=\E[A:\
+	:us=\E[4m:vb=\E[30h\E\054\E[30l:ve=\E[34h\E[?25h:\
+	:vi=\E[?25l:vs=\E[?25h\E[34l:
+#
+#	Function key set for the ASCII (wy-50 compatible) keyboard
+#	This is the default 370.
+#
+wy370|wyse370|wy370-101k|Wyse 370 with 101 key keyboard:\
+	:@8=\EOM:F1=\E[23~:F2=\E[24~:F3=\E[25~:F4=\E[26~:\
+	:F5=\E[28~:F6=\E[29~:k1=\E[?4i:k2=\E[?3i:k3=\E[2i:k4=\E[@:\
+	:k5=\E[M:k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:\
+	:k;=\E[21~:kA=\EOP:kB=\E[Z:kD=\EOQ:kI=\EOP:kL=\EOQ:kN=\E[U:\
+	:kP=\E[V:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:tc=wy370-nk:
+#
+#	Function key set for the VT-320 (and wy85) compatible keyboard
+#
+wy370-105k|Wyse 370 with 105 key keyboard:\
+	:%1=\E[28~:*6=\E[4~:@0=\E[1~:@8=\EOM:F1=\E[23~:F2=\E[24~:\
+	:F3=\E[25~:F4=\E[26~:F5=\E[28~:F6=\E[29~:F7=\E[31~:\
+	:F8=\E[32~:F9=\E[33~:FA=\E[34~:K1=\EOw:K2=\EOu:K3=\EOy:\
+	:K4=\EOq:K5=\EOs:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k6=\E[17~:\
+	:k7=\E[18~:k8=\E[19~:k9=\E[20~:k;=\E[21~:kD=\E[3~:\
+	:kI=\E[2~:kN=\E[6~:kP=\E[5~:kb=^H:kd=\E[B:kh=\E[26~:\
+	:kl=\E[D:kr=\E[C:ku=\E[A:l1=PF1:l2=PF2:l3=PF3:l4=PF4:\
+	:tc=wy370-nk:
+#
+#	Function key set for the PC compatible keyboard
+#
+wy370-EPC|Wyse 370 with 102 key keyboard:\
+	:@7=\E[1~:@8=\EOM:F1=\E[23~:F2=\E[24~:k1=\EOP:k2=\EOQ:\
+	:k3=\EOR:k4=\EOS:k5=\E[M:k6=\E[17~:k7=\E[18~:k8=\E[19~:\
+	:k9=\E[20~:k;=\E[21~:kB=\E[Z:kI=\E[2~:kN=\E[U:kP=\E[V:\
+	:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:tc=wy370-nk:
+#
+#	Wyse 370 with visual bell.
+wy370-vb|Wyse 370 with visible bell:\
+	:bl@:tc=wy370:
+#
+#	Wyse 370 in 132-column mode.
+wy370-w|Wyse 370 in 132-column mode:\
+	:co#132:ws#132:\
+	:r2=\E[35h\E[?3h:tc=wy370:
+#
+#	Wyse 370 in 132-column mode with visual bell.
+wy370-wvb|Wyse 370 with visible bell 132-columns:\
+	:vb=\E[30h\E\054\E[30l:tc=wy370-w:
+wy370-rv|Wyse 370 reverse video:\
+	:r3=\E[32h\E[?5h:tc=wy370:
+#
+#	Wyse 99gt Tektronix 4010/4014 emulator,
+#
+wy99gt-tek|Wyse 99gt Tektronix 4010/4014 emulator:\
+	:am:os:\
+	:co#74:li#35:\
+	:bl=^G:cl=\E^L:\
+	:..cm=\035%{3040}%{89}%p1%*%-%Py%p2%{55}%*%Px%gy%{128}%/%{31}%&%{32}%+%c%gy%{3}%&%{4}%*%gx%{3}%&%+%{96}%+%c%gy%{004}%/%{31}%&%{96}%+%c%gx%{128}%/%{31}%&%{32}%+%c%gx%{004}%/%{31}%&%{64}%+%c\037:\
+	:cr=^M:do=^J:ff=^L:\
+	:hd=\036HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH\037:\
+	:ho=^]7`x @\037:\
+	:hu=\036DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\037:\
+	:is=\E8:le=^H:nd= :nw=^M^J:u0=\E~>\E8:u1=\E[42h:up=^K:
+#
+#	Wyse 160 Tektronix 4010/4014 emulator,
+#
+wy160-tek|Wyse 160 Tektronix 4010/4014 emulator:\
+	:..cm=\035%{3103}%{91}%p1%*%-%Py%p2%{55}%*%Px%gy%{128}%/%{31}%&%{32}%+%c%gy%{3}%&%{4}%*%gx%{3}%&%+%{96}%+%c%gy%{004}%/%{31}%&%{96}%+%c%gx%{128}%/%{31}%&%{32}%+%c%gx%{004}%/%{31}%&%{64}%+%c\037:\
+	:ho=^]8`g @\037:\
+	:tc=wy99gt-tek:
+#
+#	Wyse 370 Tektronix 4010/4014 emulator,
+#
+wy370-tek|Wyse 370 Tektronix 4010/4014 emulator:\
+	:am:os:\
+	:co#80:li#36:\
+	:bl=^G:cl=\E^L:\
+	:..cm=\035%{775}%{108}%p1%*%{5}%/%-%Py%p2%{64}%*%{4}%+%{5}%/%Px%gy%{32}%/%{31}%&%{32}%+%c%gy%{31}%&%{96}%+%c%gx%{32}%/%{31}%&%{32}%+%c%gx%{31}%&%{64}%+%c\037:\
+	:cr=^M:do=^J:ff=^L:\
+	:hd=\036HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH\037:\
+	:ho=^]8g @\037:\
+	:hu=\036DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\037:\
+	:is=\E8:kb=^H:kd=^J:kl=^H:kr=^I:ku=^K:le=^H:nd= :nw=^M^J:\
+	:u0=\E[?38h\E8:u1=\E[?38l\E)0:up=^K:
+
+# Vendor-supplied Wyse entries end here.
+
+# Can't set tabs! Other bugs (ANSI mode only):
+# - can't redefine function keys (anyway, key redefinition in ANSI mode
+#   is too much complex to be described);
+# - meta key can't be described (the terminal forgets it when reset);
+# The xon-xoff handshaking can't be disabled while in ansi personality, so
+# emacs can't work at speed greater than 9600 baud.  No padding is needed at
+# this speed.
+#   dch1 has been commented out because it causes annoying glittering when
+# vi deletes one character at the beginning of a line with tabs in it.
+#   dch makes sysgen(1M) have a horrible behaviour when deleting
+# a screen and makes screen(1) behave badly, so it is disabled too. The nice
+# thing is that vi goes crazy if smir-rmir are present and both dch-dch1 are
+# not, so smir and rmir are commented out as well.
+# From: Francesco Potorti` <F.Potorti@cnuce.cnr.it>, 24 Aug 1998
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+wy99-ansi|Wyse WY-99GT in ansi mode (int'l PC keyboard):\
+	:am:km:mi:ms:xn:\
+	:co#80:it#8:li#25:vt#3:\
+	:AL=\E[%dL:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:bt=\E[Z:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:dl=\E[M:do=\ED:ec=\E[%dX:ei=\E[4l:ho=\E[H:\
+	:im=\E[4h:\
+	:is=\E7\E[1r\E8\E[2;3;4;13;20;34;39;36l\E[12;16;34h\E[?1;3;4;5;10;18l\E[?7;8;25h\E>\E[?5W\E(B\017\E[4i:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\E[M:k6=\E[17~:\
+	:k7=\E[18~:k8=\E[19~:k9=\E[20~:kb=^H:kd=\EOB:ke=\E[?1l:\
+	:kl=\EOD:kr=\EOC:ks=\E[?1h:ku=\EOA:le=\010:ll=\E[24E:\
+	:mb=\E[5m:md=\E[1m:me=\E[m\017\E["q:mh=\E[2m:mr=\E[7m:\
+	:nd=\E[C:nw=\EE:rc=\E8:sc=\E7:se=\E[27m:sf=\n:so=\E[7m:\
+	:sr=\EM:ta=^I:ue=\E[24m:up=\EM:us=\E[4m:vb=\E[?5h\E[?5l:\
+	:ve=\E[34h\E[?25h:vi=\E[?25l:vs=\E[34l\E[?25h:
+
+#   This is the american terminal. Here tabs work fine.
+# From: Francesco Potorti` <F.Potorti@cnuce.cnr.it>, 24 Aug 1998
+wy99a-ansi|Wyse WY-99GT in ansi mode (US PC keyboard):\
+	:ct=\E[3g:i2=\E[?5l:r3=\E[?5l:st=\EH:\
+	:tc=wy99-ansi:
+
+# This terminal (firmware version 02) has a lot of bugs:
+# - can't set tabs;
+# - other bugs in ANSI modes (see above).
+# This description disables handshaking when using cup. This is because
+# GNU emacs doesn't like Xon-Xoff handshaking. This means the terminal
+# cannot be used at speeds greater than 9600 baud, because at greater
+# speeds handshaking is needed even for character sending. If you use
+# DTR handshaking, you can use even greater speeds.
+# From: Francesco Potorti` <F.Potorti@cnuce.cnr.it>, 24 Aug 1998
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+wy99f|wy99fgt|wy-99fgt|Wyse WY-99GT (int'l PC keyboard):\
+	:am:bw:hs:km:mi:ms:xo:\
+	:co#80:it#8:li#25:ws#46:\
+	:K1=^^:K3=\EJ:K4=\ET:K5=\EK:ae=\EcD:al=\EE:as=\EcE:bl=^G:\
+	:bt=\EI:cd=\EY:ce=\ET:cl=\E'\E(\032:cm=\E=%+ %+ :cr=^M:\
+	:dc=\EW:dl=\ER:do=\Ej:ds=\EF\r:ei=\Er:fs=^M:ho=^^:im=\Eq:\
+	:is=\Eu\Ee6\EC\EDF\Ec21\Ec31\Ec62\Ec72\Ee;\016\E'\EeL\E`9\E\1360\E`1\E`4\Ee.\E`\072\Ee1\EG0\E(\Ed/\Ee4\Ed*\EO\E`I\Er\Ee"\EcD\024:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:k9=^AH\r:kb=^H:kd=^J:kl=^H:kr=^L:ku=^K:\
+	:le=^H:mb=\EG2:me=\E(\EG0:mh=\EGp:mr=\EG4:nd=^L:nw=^_:\
+	:se=\EG0:sf=^J:so=\EG4:sr=\Ej:ta=^I:te=\Ec21\Ec31:\
+	:ti=\Ec20\Ec30:ts=\EF:up=^K:vb=\E\1361\E\1360:\
+	:ve=\E`4\E`1:vi=\E`0:vs=\E`2\E`1:
+
+# This is the american terminal. Here tabs work.
+# From: Francesco Potorti` <F.Potorti@cnuce.cnr.it>, 24 Aug 1998
+wy99fa|wy99fgta|wy-99fgta|Wyse WY-99GT (US PC keyboard):\
+	:ct=\E0:st=\E1:\
+	:tc=wy99f:
+
+#
+#TITLE:  TERMINFO ENTRY WY520
+#DATE:   8/5/93
+# The WY520 terminfo is based on the WY285 entry published on the WYSE 
+# BBS with the addition of more function keys and special keys.
+#
+#               rs1 -> set personality
+#               rs2 -> set number of columns
+#               rs3 -> set number of lines
+#               is1 -> select the proper font
+#               is2 -> do the initialization
+#               is3 -> If this string is empty then rs3 gets sent.
+#
+#       Wyse 520 emulating a vt420 7 bit mode with default ANSI keyboard
+#       - The BS key is programmed to generate BS in smcup since
+#         is2 doesn't seem to work.
+#       - Remove and shift/Remove: delete a character
+#       - Insert : enter insert mode
+#       - Find   : delete to end of file
+#       - Select : clear a line
+#       - F11, F12, F13: send default sequences (not ESC, BS, LF)
+#       - F14 : Home key
+#       - Bottom status line (host writable line) is used.
+#       - smkx,rmkx are removed because this would put the numeric
+#         keypad in Dec application mode which doesn't seem to work
+#         with SCO applications.
+#
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+wy520|wyse520|wyse 520:\
+	:am:hs:km:mi:xn:xo:\
+	:co#80:it#8:li#24:ws#80:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:K1=\EOw:K2=\EOy:K3=\EOu:K4=\EOq:K5=\EOs:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:bt=\E[Z:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:ds=\E[0$~:\
+	:ec=\E[%dX:ei=\E[4l:fs=\E[0$}:ho=\E[H:i1=\E[?5W:\
+	:i2=\E>\E(B\E)0\017\E[m:im=\E[4h:ip=:\
+	:is=\E[2;4;20;30l\E[?1;4;10;16l\E[12h\E[?7;8;25;67h:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k6=\E[17~:k7=\E[18~:\
+	:k8=\E[19~:k9=\E[20~:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:\
+	:kb=^H:kd=\E[B:kh=\E[26~:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:\
+	:mb=\E[5m:md=\E[1m:me=\E[m\017:mh=\E[2m:mr=\E[7m:nd=\E[C:\
+	:rc=\E8:sc=\E7:se=\E[m:sf=\n:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:te=\E[ R:ti=\E[ Q\E[?67;8h:ts=\E[2$~\E[1$}\E[%i%p1%d`:\
+	:ue=\E[24m:up=\E[A:us=\E[4m:ve=\E[34h\E[?25h:vi=\E[?25l:\
+	:vs=\E[?25h\E[34l:
+#
+#       Wyse 520 with 24 data lines and status (terminal status)
+wy520-24|wyse520-24|wyse 520 with 24 data lines:\
+	:hs@:\
+	:ds@:fs@:r3=\E[?5l\E[47h\E[40l\E[1;24r:ts@:tc=wy520:
+#
+#       Wyse 520 with visual bell.
+wy520-vb|wyse520-vb|wyse 520 with visible bell:\
+	:vb=\E[30h\E\054\E[30l:tc=wy520:
+#
+#       Wyse 520 in 132-column mode.
+wy520-w|wyse520-w|wyse 520 in 132-column mode:\
+	:co#132:ws#132:\
+	:DC=\E[%dP:IC=\E[%d@:dc=\E[P:ei=:im=:ip=:r2=\E[35h\E[?3h:tc=wy520:
+#
+#       Wyse 520 in 132-column mode with visual bell.
+wy520-wvb|wyse520-wvb|wyse 520 with visible bell 132-columns:\
+	:vb=\E[30h\E\054\E[30l:\
+	:tc=wy520-w:
+#
+#
+#       Wyse 520 emulating a vt420 7 bit mode.
+#       The DEL key is programmed to generate BS in is2.
+#       With EPC keyboard.
+#       - 'End' key will clear till end of line on EPC keyboard
+#       - Shift/End : ignored.
+#       - Insert : enter insert mode.
+#       - Delete : delete a character (have to change interrupt character
+#                  to CTRL-C: stty intr '^c') for it to work since the
+#                  Delete key sends 7FH.
+wy520-epc|wyse520-epc|wyse 520 with EPC keyboard:\
+	:@7=\E[4~:k0=\E[21~:k1=\E[11~:k2=\E[12~:k3=\E[13~:\
+	:k4=\E[14~:k5=\E[15~:kD=\177:kE=\E[4~:kh=\E[H:\
+	:tc=wy520:
+#
+#       Wyse 520 with 24 data lines and status (terminal status)
+#       with EPC keyboard.
+wy520-epc-24|wyse520-pc-24|wyse 520 with 24 data lines and EPC keyboard:\
+	:hs@:\
+	:ds@:fs@:r3=\E[?5l\E[47h\E[40l\E[1;24r:ts@:tc=wy520-epc:
+#
+#       Wyse 520 with visual bell.
+wy520-epc-vb|wyse520-pc-vb|wyse 520 with visible bell and EPC keyboard:\
+	:vb=\E[30h\E\054\E[30l:\
+	:tc=wy520-epc:
+#
+#       Wyse 520 in 132-column mode.
+wy520-epc-w|wyse520-epc-w|wyse 520 in 132-column mode with EPC keyboard:\
+	:co#132:ws#132:\
+	:DC=\E[%dP:IC=\E[%d@:dc=\E[P:ei=:im=:ip=:r2=\E[35h\E[?3h:tc=wy520-epc:
+#
+#       Wyse 520 in 132-column mode with visual bell.
+wy520-epc-wvb|wyse520-p-wvb|wyse 520 with visible bell 132-columns and EPC keyboard:\
+	:vb=\E[30h\E\054\E[30l:\
+	:tc=wy520-epc-w:
+#
+#       Wyse 520 in 80-column, 36 lines
+wy520-36|wyse520-36|wyse 520 with 36 data lines:\
+	:hs@:\
+	:li#36:\
+	:ds@:fs@:r3=\E[?5l\E[36*|\E[36t\E[40l\E[1;36r:ts@:tc=wy520:
+#
+#       Wyse 520 in 80-column, 48 lines
+wy520-48|wyse520-48|wyse 520 with 48 data lines:\
+	:hs@:\
+	:li#48:\
+	:ds@:fs@:r3=\E[?5l\E[48*|\E[48t\E[40l\E[1;48r:ts@:tc=wy520:
+#
+#       Wyse 520 in 132-column, 36 lines
+wy520-36w|wyse520-36w|wyse 520 with 132 columns and 36 data lines:\
+	:co#132:ws#132:\
+	:r2=\E[?3h:\
+	:r3=\E[?5l\E[36*|\E[36t\E[40l\E[1;36r\E[132$|:tc=wy520-36:
+#
+#       Wyse 520 in 132-column, 48 lines
+wy520-48w|wyse520-48w|wyse 520 with 48 data lines:\
+	:co#132:ws#132:\
+	:r2=\E[?3h:\
+	:r3=\E[?5l\E[48*|\E[48t\E[40l\E[1;48r\E[132$|:tc=wy520-48:
+#
+#
+#       Wyse 520 in 80-column, 36 lines with EPC keyboard
+wy520-36pc|wyse520-36pc|wyse 520 with 36 data lines and EPC keyboard:\
+	:hs@:\
+	:li#36:\
+	:ds@:fs@:r3=\E[?5l\E[36*|\E[36t\E[40l\E[1;36r:ts@:tc=wy520-epc:
+#
+#       Wyse 520 in 80-column, 48 lines with EPC keyboard
+wy520-48pc|wyse520-48pc|wyse 520 with 48 data lines and EPC keyboard:\
+	:hs@:\
+	:li#48:\
+	:ds@:fs@:r3=\E[?5l\E[48*|\E[48t\E[40l\E[1;48r:ts@:tc=wy520-epc:
+#
+#       Wyse 520 in 132-column, 36 lines with EPC keyboard
+wy520-36wpc|wyse520-36wpc|wyse 520 with 36 data lines and EPC keyboard:\
+	:co#132:ws#132:\
+	:r2=\E[?3h:\
+	:r3=\E[?5l\E[36*|\E[36t\E[40l\E[1;36r\E[132$|:tc=wy520-36pc:
+#
+#       Wyse 520 in 132-column, 48 lines with EPC keyboard
+wy520-48wpc|wyse520-48wpc|wyse 520 with 48 data lines and EPC keyboard:\
+	:co#132:ws#132:\
+	:r2=\E[?3h:\
+	:r3=\E[?5l\E[48*|\E[48t\E[40l\E[1;48r\E[132$|:tc=wy520-48pc:
+
+# From: John Gilmore <hoptoad!gnu@lll-crg.arpa>
+# (wyse-vp: removed :if=/usr/share/tabset/wyse-adds:, there's no such
+# file and we don't know what :st: is -- esr)
+wyse-vp|Wyse 50 in ADDS Viewpoint emulation mode with "enhance" on:\
+	:am:bs:\
+	:co#80:it#8:li#24:\
+	:al=\EM:bl=^G:cd=\Ek:ce=\EK:cl=^L:cm=\EY%+ %+ :cr=^M:dc=\EW:\
+	:dl=\El:do=^J:ei=\Er:ho=^A:im=\Eq:is=\E`\072\E`9\017\Er:\
+	:kb=^H:kd=^J:kh=^A:kl=^U:kr=^F:ku=^Z:le=^H:ll=^A^Z:me=^O:\
+	:nd=^F:nw=^M^J:r1=\E`\072\E`9\017\Er:se=^O:sf=^J:so=^N:\
+	:ta=^I:ue=^O:up=^Z:us=^N:
+
+wy75ap|wyse75ap|wy-75ap|wyse-75ap|Wyse WY-75 Applications and Cursor keypad:\
+	:is=\E[1;24r\E[?10;3l\E[?1;25h\E[4l\E[m\E(B\E=:kb=^H:\
+	:kd=\EOB:ke=10\E[?1l\E>:kh=\EOH:kl=\EOD:kr=\EOC:\
+	:ks=10\E[?1h\E=:ku=\EOA:tc=wy75:
+
+# From: Kevin Turner <kevint@aracnet.com>, 12 Jul 1998
+# This copes with an apparent firmware bug in the wy85.  He writes:
+# "What I did was change leave the terminal cursor keys set to Normal
+# (instead of application), and change \E[ to \233 for all the keys in
+# terminfo. At one point, I found some reference indicating that this
+# terminal bug (not sending \E[) was acknowledged by Wyse (so it's not just
+# me), but I can't find that and the server under my bookmark to "Wyse 
+# Technical" isn't responding.  So there's the question of wether the wy85
+# terminfo should reflect the manufactuer's intended behaviour of the terminal
+# or the actual."
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+wy85-8bit|wyse85-8bit|wyse 85 in 8-bit mode:\
+	:am:hs:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:ws#80:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:K1=\EOw:K2=\EOu:K3=\EOy:K4=\EOq:K5=\EOs:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:bt=\E[Z:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:ds=\E[40l:\
+	:ec=\E[%dX:ei=\E[4l:fs=\E[1;24r\E8:ho=\E[H:\
+	:i1=\E[62;1"p\E[?5W:i2=\E>\E(B\E)0\017\E[m:im=\E[4h:ip=:\
+	:is=\E[2;4;20;30l\E[?1;4;10;16l\E[12h\E[?7;8;25h:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k6=\23317~:k7=\23318~:\
+	:k8=\23319~:k9=\23320~:kD=\2333~:kI=\2332~:kN=\2336~:\
+	:kP=\2335~:kb=^H:kd=\233B:ke=\E>:kh=\23326~:kl=\233D:\
+	:kr=\233C:ks=\E[?1l\E=:ku=\233A:le=^H:mb=\E[5m:md=\E[1m:\
+	:me=\E[m\017:mh=\E[2m:mr=\E[7m:nd=\E[C:rc=\E8:sc=\E7:\
+	:se=\E[m:sf=\n:so=\E[7m:sr=\EM:st=\EH:ta=\011:\
+	:ts=\E[40h\E7\E[25;%i%p1%dH:ue=\E[m:up=\E[A:us=\E[4m:\
+	:vb=\E[30h\E\054\E[30l:ve=\E[?25h:vi=\E[?25l:
+
+# From: Eric Freudenthal <freudent@eric.ultra.nyu.edu>
+wy100q|Wyse 100 for Quotron:\
+	:bs:\
+	:co#80:li#24:sg#1:\
+	:al=\EE:bt=\EI:cd=\EY:ce=\ET:cl=^Z:cm=\E=%+ %+ :dc=\EW:\
+	:dl=\ER:do=^J:ei=\Er:ho=^^:im=\Eq:\
+	:is=\E`\072\0\EC\EDF\E0\E'\E(\EA21:kd=^J:kl=^H:kr=^L:\
+	:ku=^K:le=^H:mk@:nd=^L:sr=\Ej:up=^K:\
+	:tc=adm+sgr:
+
+#### Kermit terminal emulations
+#
+# Obsolete Kermit versions may be listed in the section describing obsolete
+# non-ANSI terminal emulators later in the file.
+#
+
+# KERMIT standard all versions.
+# Straight ascii keyboard. :sr=\EI: not avail. many versions + bug prone in vi.
+# (kermit: removed obsolete ":ma=^Hh^Jj^Kk^Ll^^H:" -- esr)
+# From: greg small <gts@populi.berkeley.edu> 9-25-84
+kermit|standard kermit:\
+	:bs:\
+	:co#80:li#24:\
+	:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :ho=\EH:\
+	:is=K0 Standard Kermit  9-25-84\n:kd=^J:kh=^^:kl=^H:\
+	:kr=^L:ku=^K:le=^H:nd=\EC:up=\EA:
+kermit-am|standard kermit plus auto-margin:\
+	:am:\
+	:is=K1 Standard Kermit plus Automatic Margins\n:tc=kermit:
+# IBMPC Kermit 1.2.
+# Bugs: :cd:, :ce:: do not work except at beginning of line!  :cl: does
+# not work, but fake with :cl=\EH\EJ (since :cd=\EJ: works at beginning of
+# line).
+# From: greg small <gts@populi.berkeley.edu> 8-30-84
+pckermit|pckermit12|UCB IBMPC Kermit 1.2:\
+	:am:\
+	:li#25:\
+	:cd@:ce@:cl=\EH\EJ:\
+	:is=K2 UCB IBMPC Kermit 1.2  8-30-84\n:tc=kermit:
+# IBMPC Kermit 1.20
+# Cannot use line 25, now acts funny like ansi special scrolling region.
+# Initialization must escape from that region by cursor position to line 24.
+# Cannot use character insert because 1.20 goes crazy if insert at col 80.
+# Does not use :am: because autowrap is lost when kermit dropped and restarted.
+# From: greg small <gts@populi.berkeley.edu> 12-19-84
+pckermit120|UCB IBMPC Kermit 1.20:\
+	:it#8:li#24:\
+	:al=\EL:dc=\EN:dl=\EM:do=\EB:ei@:im@:\
+	:is=\EO\Eq\EJ\EY7 K3 UCB IBMPC Kermit 1.20  12-19-84\n:\
+	:se=\Eq:so=\Ep:ta=^I:vs=\EO\Eq\EEK3:\
+	:tc=kermit:
+# MS-DOS Kermit 2.27 for the IBMPC
+# Straight ascii keyboard. :sr=\EI: not avail. many versions + bug prone in vi.
+# Cannot use line 25, now acts funny like ansi special scrolling region.
+# Initialization must escape from that region by cursor position to line 24.
+# Does not use am: because autowrap is lost when kermit dropped and restarted.
+# Reverse video for standout like H19.
+# (msk227: removed obsolete ":ma=^Hh^Jj^Kk^Ll^^H:" -- esr)
+# From: greg small <gts@populi.berkeley.edu> 3-17-85
+msk227|mskermit227|MS-DOS Kermit 2.27 for the IBMPC:\
+	:am@:bs:\
+	:co#80:it#8:li#24:\
+	:al=\EL:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :dc=\EN:dl=\EM:\
+	:do=\EB:ei=\EO:ho=\EH:im=\E@:\
+	:is=\EO\Eq\EG\Ew\EJ\EY7 K4 MS Kermit 2.27 for the IBMPC 3-17-85\n:\
+	:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:nd=\EC:rc=\Ek:sc=\Ej:\
+	:se=\Eq:so=\Ep:ta=^I:up=\EA:vs=\EO\Eq\EG\EwK4:
+# MS-DOS Kermit 2.27 with automatic margins
+# From:	greg small <gts@populi.berkeley.edu> 3-17-85
+msk227am|mskermit227am|UCB MS-DOS Kermit 2.27 with automatic margins:\
+	:am:\
+	:is=\EO\Eq\EG\Ev\EJ\EY7 K5 MS Kermit 2.27 +automatic margins 3-17-85\n:\
+	:vs=\EO\Eq\EG\EvK5:\
+	:tc=msk227:
+# MS-DOS Kermit 2.27 UCB 227.14 for the IBM PC
+# Automatic margins now default.  Use ansi :sa: for highlights.
+# Define function keys.
+# (msk22714: removed obsolete ":kn#10:" -- esr)
+# From: greg small <gts@populi.berkeley.edu> 3-17-85
+msk22714|mskermit22714|UCB MS-DOS Kermit 2.27 UCB 227.14 IBM PC:\
+	:am:\
+	:is=\EO\Eq\EG\Ev\EJ\EY7 K6 MS Kermit 2.27 UCB 227.14 IBM PC 3-17-85\n:\
+	:k0=\E0:k1=\E1:k2=\E2:k3=\E3:k4=\E4:k5=\E5:k6=\E6:k7=\E7:\
+	:k8=\E8:k9=\E9:md=\E[1m:me=\E[m:mr=\E[7m:se=\E[m:so=\E[1m:\
+	:ue=\E[m:us=\E[4m:vs=\EO\Eq\EG\EvK6:\
+	:tc=mskermit227:
+# This was designed for a VT320 emulator, but it is probably a good start
+# at support for the VT320 itself.
+# Please send changes with explanations to bug-gnu-emacs@prep.ai.mit.edu.
+# (vt320-k3: I added <rmam>/<smam> based on the init string -- esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+vt320-k3|MS-Kermit 3.00's vt320 emulation:\
+	:am:es:hs:km:mi:ms:xn:\
+	:co#80:it#8:li#49:pb#9600:vt#3:\
+	:AL=\E[%dL:CC=\E:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:SR=\E[%dL:UP=\E[%dA:ae=\E(B:al=\E[L:\
+	:as=\E(0:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:\
+	:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:\
+	:ds=\E[0$~:ec=\E[%dX:ei=\E[4l:fs=\E[0$}:ho=\E[H:im=\E[4h:\
+	:is=\E>\E F\E[?1l\E[?7h\E[r\E[2$~:k0=\E[21~:k1=\EOP:\
+	:k2=\EOQ:k3=\EOR:k4=\EOS:k6=\E[17~:k7=\E[18~:k8=\E[19~:\
+	:k9=\E[20~:kI=\E[2~:kN=\E[6~:kP=\E[5~:kb=^H:kd=\EOB:\
+	:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:\
+	:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:nw=^M^J:rc=\E8:\
+	:sc=\E7:se=\E[27m:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:ts=\E[1$}\r\E[K:ue=\E[24m:up=\E[A:us=\E[4m:\
+	:vb=\E[?5h\E[?5l\E[?5h\E[?5l\E[?5h\E[?5l:ve=\E[?25h:\
+	:vi=\E[?25l:
+# From: Joseph Gil <yogi@cs.ubc.ca> 13 Dec 1991
+# ACS capabilities from Philippe De Muyter  <phdm@info.ucl.ac.be> 30 May 1996
+# (I removed a bogus boolean :mo: and added :ms:, <smam>, <rmam> -- esr)
+vt320-k311|dec vt320 series as defined by kermit 3.11:\
+	:am:es:hs:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:vt#3:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:UP=\E[%dA:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=^O:al=3\E[L:as=^N:bl=^G:cd=\E[J:ce=\E[K:cl=\E[;H\E[2J:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:\
+	:dl=\E[M:do=^J:ds=\E[2$~\r\E[1$}\E[K\E[$}:ei=\E[4l:\
+	:fs=\E[$}:ho=\E[H:im=\E[4h:\
+	:is=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[1;24r\E[24;1H:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k6=\E[17~:k7=\E[18~:\
+	:k8=\E[19~:k9=\E[20~:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:\
+	:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:l1=pf1:l2=pf2:l3=pf3:l4=pf4:\
+	:le=^H:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:nw=^M\ED:\
+	:r1=\E[?3l:rc=\E8:rf=/usr/share/tabset/vt100:sc=\E7:\
+	:se=\E[27m:sf=\ED:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:ts=\E[2$~\E[1$}\E[1;%dH:ue=\E[24m:up=\E[A:us=\E[4m:\
+	:vb=\E[?5h\E[?5l:ve=\E[?25h:vi=\E[?25l:vs=\E[?25h:
+
+#
+######## ---------------- TERMINFO FILE CAN BE SPLIT HERE -------------------
+# This cut mark helps make life less painful for people running ncurses tic
+# on machines with relatively little RAM.  The file can be broken in half here
+# cleanly and compiled in sections -- no `use' references cross this cut
+# going forward.
+#
+
+######## OLDER TERMINAL TYPES
+#
+# This section is devoted to older commercial terminal brands that are now
+# discontinued, but known to be still in use or represented by emulations.
+#
+
+#### AT&T (att, tty)
+#
+# This section also includes Teletype-branded VDTs.
+#
+# The AT&T/Teletype terminals group was sold to SunRiver Data Systems (now
+# Boundless Technologies); for details, see the header comment on the ADDS
+# section.
+#
+# These are AT&T's official terminfo entries.  All-caps aliases have been
+# removed.
+#
+att2300|sv80|AT&T 2300 Video Information Terminal 80 column mode:\
+	:am:eo:mi:ms:xo:\
+	:co#80:it#8:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:F1=\E[11r:\
+	:F2=\E[12r:F3=\E[13r:F4=\E[14r:F5=\E[15r:F6=\E[16r:\
+	:IC=\E[%d@:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:al=\E[L:bl=^G:\
+	:cb=\E[1K:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:\
+	:cr=^M:dc=\E[P:dl=\E[M:do=^J:ei=\E[4l:ho=\E[H:im=\E[4h:\
+	:k1=\E[1r:k2=\E[2r:k3=\E[3r:k4=\E[4r:k5=\E[5r:k6=\E[6r:\
+	:k7=\E[7r:k8=\E[8r:k9=\E[9r:k;=\E[10r:kA=\E[L:kB=\E[Z:\
+	:kC=\E[J:kD=\E[P:kI=\E[@:kL=\E[M:kb=^H:kd=\E[B:kh=\E[H:\
+	:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:me=\E[m:mr=\E[7m:nd=\E[C:\
+	:pf=\E[4i:po=\E[5i:ps=\E[0i:se=\E[m:sf=^J:so=\E[7m:ta=^I:\
+	:up=\E[A:
+att2350|AT&T 2350 Video Information Terminal 80 column mode:\
+	:pf@:po@:ps@:\
+	:tc=att2300:
+
+# Must setup RETURN KEY - CR, REC'VD LF - INDEX.
+# Seems upward compatible with vt100, plus ins/del line/char.
+# On sgr, the protection parameter is ignored.
+# No check is made to make sure that only 3 parameters are output.
+# 	standout= reverse + half-intensity = 3 | 5.
+# 	bold= reverse + underline = 2 | 3.
+# note that half-bright blinking doesn't look different from normal blinking.
+# NOTE:you must program the function keys first, label second!
+# (att4410: a BSD entry has been seen with the following capabilities: 
+# :is=\E[?6l:, :k1=\EOc:, :k2=\EOd:, :k3=\EOe:, :k4=\EOg:,
+# :k6=\EOh:, :k7=\EOi:, :k8=\EOj:, -- esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+att5410v1|att4410v1|tty5410v1|AT&T 4410/5410 80 columns - version 1:\
+	:am:hs:mi:ms:xo:\
+	:Nl#8:co#80:it#8:lh#2:li#24:lw#8:ws#80:\
+	:ac=++\054\054--..00``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=^O:al=\E[L:as=^N:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:dc=\E[P:dl=\E[M:\
+	:do=\E[B:ei=:fs=\E8:ho=\E[H:i1=\E[?3l\E)0:\
+	:i2=\E[1;03q   f1           \EOP\E[2;03q   f2           \EOQ\E[3;03q   f3           \EOR\E[4;03q   f4           \EOS\E[5;03q   f5           \EOT\E[6;03q   f6           \EOU\E[7;03q   f7           \EOV\E[8;03q   f8           \EOW:\
+	:ic=\E[@:im=:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\EOT:\
+	:k6=\EOU:k7=\EOV:k8=\EOW:kC=\E[2J:kH=\E[24;1H:kb=^H:\
+	:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:ll=\E[24H:\
+	:mb=\E[5m:md=\E[2;7m:me=\E[m\017:mh=\E[2m:mk=\E[8m:\
+	:mr=\E[7m:nd=\E[C:nw=^M^J:r2=\Ec\E[?3l\E[2;0y:rc=\E8:\
+	:sc=\E7:se=\E[m:sf=^J:so=\E[7m:sr=\EM:ta=^I:\
+	:ts=\E7\E[25;%p1%{1}%+%dH:ue=\E[m:up=\E[A:us=\E[4m:
+
+att4410v1-w|att5410v1-w|tty5410v1-w|AT&T 4410/5410 132 columns - version 1:\
+	:co#132:ws#132:\
+	:i1=\E[?3h\E)0:r2=\Ec\E[?3h\E[2;0y:tc=att5410v1:
+
+att4410|att5410|tty5410|AT&T 4410/5410 80 columns - version 2:\
+	:bs:\
+	:..px=\E[%p1%d;%p2%l%02dq   f%p1%d           %p2%s:tc=att5410v1:
+
+att5410-w|att4410-w|4410-w|tty5410-w|5410-w|AT&T 4410/5410 in 132 column mode:\
+	:co#132:ws#132:\
+	:i1=\E[?3h\E)0:r2=\Ec\E[?3h\E[2;0y:tc=att4410:
+
+# 5410 in terms of a vt100
+# (v5410: added <rmam>/<smam> based on init string -- esr)
+v5410|att5410 in terms of a vt100:\
+	:am:mi:ms:xo:\
+	:co#80:it#8:li#24:vt#3:\
+	:@8=\EOM:K1=\EOq:K2=\EOr:K3=\EOs:K4=\EOp:K5=\EOn:RA=\E[?7l:\
+	:SA=\E[?7h:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=^O:al=\E[L:as=^N:bl=^G:cb=\E[1K:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:eA=\E(B\E)0:ei=:ho=\E[H:\
+	:ic=\E[@:im=:k0=\EOy:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+	:k5=\EOt:k6=\EOu:k7=\EOv:k8=\EOl:k9=\EOw:k;=\EOx:kb=^H:\
+	:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:\
+	:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:me=\E[m\017:mr=\E[7m:\
+	:nd=\E[C:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\E8:\
+	:..sa=\E[0%?%p1%p6%|%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t\016%e\017%;:\
+	:sc=\E7:se=\E[m:sf=^J:so=\E[1;7m:sr=\EM:st=\EH:ta=^I:\
+	:ue=\E[m:up=\E[A:us=\E[4m:
+
+# 
+# Teletype Model 5420 -- A souped up 5410, with multiple windows,
+# even! the 5420 has three modes: scroll, window or page mode
+# this terminfo should work in scroll or window mode, but doesn't
+# take advantage of any of the differences between them.
+#
+# Has memory below (2 lines!)
+# 3 pages of memory (plus some spare)
+# The 5410 sequences for :cm:, :vs:, :DC:, :DL:, :ec:, :vb:, :ho:,
+# <hpa>, :st: would work for these, but these work in both scroll and window
+# mode... Unset insert character so insert mode works
+# :i1: sets 80 column mode,
+# :is: escape sequence:
+# 1) turn off all fonts
+# 2) function keys off, keyboard lock off, control display off,
+#    insert mode off, erasure mode off,
+# 3) full duplex, monitor mode off, send graphics off, nl on lf off
+# 4) reset origin mode
+# 5) set line wraparound
+# 6) exit erasure mode, positional attribute mode, and erasure extent mode
+# 7) clear margins
+# 8) program ENTER to transmit ^J,
+# We use \212 to program the ^J because a bare ^J will get translated by
+# UNIX into a CR/LF. The enter key is needed for AT&T uOMS.
+#     1      2            3              4     5     6    7  8
+# :i3: set screen color to black,
+# No representation in terminfo for the delete word key: kdw1=\Ed
+# Key capabilities assume the power-up send sequence...
+# This :te: is not strictly necessary, but it helps maximize 
+# memory usefulness: :te=\Ez:,
+# Alternate sgr0:	:me=\E[m\EW^O:,
+# Alternate sgr:	:sa=\E[%?%p1%t2;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p7%t;8%;m%?%p8%t\EV%;%?%p9%t^N%e^O%;:,
+# smkx programs the SYS PF keys to send a set sequence.
+# It also sets up labels f1, f2, ..., f8, and sends edit keys.
+# This string causes them to send the strings :k1:-:k8:
+# when pressed in SYS PF mode.
+# (att4415: I added <rmam>/<smam> based on the init string -- esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+att4415|tty5420|att5420|AT&T 4415/5420 80 cols:\
+	:bs:db:mi:xo:\
+	:Nl#8:lh#2:lm#78:lw#8:ws#55:\
+	:@1=\Et:@7=\Ez:@8=\Eent:AL=\E[%dL:CM=\E[%i%p1%d;%p2%dt:\
+	:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:LE=\E[%dD:LF=\E|:\
+	:LO=\E~:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:SF=\E[%dE:SR=\E[%dF:\
+	:UP=\E[%dA:bt=\E[Z:ch=\E[%+^AG:cl=\E[x\E[J:\
+	:cm=\E[%i%d;%dx:ct=\E[3g:cv=\E[%+^Ad:ec=\E[%ds\E[%dD:\
+	:ei=\E[4l:ho=\E[x:i1=\E[?3l:i2=\E[?5l:ic@:im=\E[4h:\
+	:is=\E[m\017\E[1;2;3;4;6l\E[12;13;14;20l\E[?6;97;99l\E[?7h\E[4i\Ex\E[21;1j\212:\
+	:k1=\EOc:k2=\EOd:k3=\EOe:k4=\EOf:k5=\EOg:k6=\EOh:k7=\EOi:\
+	:k8=\EOj:kA=\E[L:kB=\E[Z:kD=\E[P:kE=\E[2K:kF=\E[T:kH=\Eu:\
+	:kI=\E[4h:kL=\E[M:kN=\E[U:kP=\E[V:kR=\E[S:\
+	:ke=\E[19;0j\E[21;1j\212:ks=\E[19;1j\E[21;4j\Eent:\
+	:l1=F1:l2=F2:l3=F3:l4=F4:l5=F5:l6=F6:l7=F7:l8=F8:ll=\Ew:\
+	:me=\E[m\017:mp=\EV:pf=\E[?9i:po=\E[?4i:ps=\E[?2i:st=\EH:\
+	:ts=\E7\E[25;%p1%{8}%+%dH:vb=\E[?5h\E[?5l:ve=\E[11;0j:\
+	:vs=\E[11;1j:\
+	:tc=att4410:
+
+att4415-w|tty5420-w|att5420-w|AT&T 4415/5420 132 cols:\
+	:co#132:lm#54:ws#97:\
+	:i1=\E[?3h:tc=att4415:
+
+att4415-rv|tty5420-rv|att5420-rv|AT&T 4415/5420 80 cols/rv:\
+	:i2=\E[?5h:vb=\E[?5l\E[?5h:\
+	:tc=att4415:
+
+att4415-w-rv|tty5420-w-rv|att5420-w-rv|AT&T 4415/5420 132 cols/rv:\
+	:co#132:lm#54:ws#97:\
+	:i1=\E[?3h:i2=\E[?5h:vb=\E[?5l\E[?5h:tc=att4415:
+
+# Note that this mode permits programming USER PF KEYS and labels
+# However, when you program user pf labels you have to reselect
+# user pf keys to make them appear! 
+att4415+nl|tty5420+nl|att5420+nl|generic AT&T 4415/5420 changes for not changing labels:\
+	:k1@:k2@:k3@:k4@:k5@:k6@:k7@:k8@:\
+	:..pn=\E[%p1%d;0;0;1q%p2%:-16.16s:\
+	:..px=\E[%p1%d;%p2%l%02d;0;1q   F%p1%d           %p2%s:
+
+att4415-nl|tty5420-nl|att5420-nl|AT&T 4415/5420 without changing labels:\
+	:k1@:k2@:k3@:k4@:k5@:k6@:k7@:k8@:\
+	:tc=att4415+nl:tc=att4415:
+
+att4415-rv-nl|tty5420-rv-nl|att5420-rv-nl|AT&T 4415/5420 reverse video without changing labels:\
+	:k1@:k2@:k3@:k4@:k5@:k6@:k7@:k8@:\
+	:tc=att4415+nl:tc=att4415-rv:
+
+att4415-w-nl|tty5420-w-nl|att5420-w-nl|AT&T 4415/5420 132 cols without changing labels:\
+	:k1@:k2@:k3@:k4@:k5@:k6@:k7@:k8@:\
+	:tc=att4415+nl:tc=att4415-w:
+
+att4415-w-rv-n|tty5420-w-rv-n|att5420-w-rv-n|AT&T 4415/5420 132 cols reverse without changing labels:\
+	:k1@:k2@:k3@:k4@:k5@:k6@:k7@:k8@:\
+	:tc=att4415+nl:tc=att4415-w-rv:
+
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+att5420_2|AT&T 5420 model 2 80 cols:\
+	:am:db:hs:mi:ms:xo:\
+	:co#80:it#8:li#24:lm#78:ws#55:\
+	:AL=\E[%dL:CM=\E[%i%p1%d;%p2%dt:DC=\E[%dP:DL=\E[%dM:\
+	:IC=\E[%d@:LE=\E[%dD:RI=\E[%dC:SF=\E[%dE:SR=\E[%dF:\
+	:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bt=\E[1Z:cd=\E[0J:ce=\E[0K:\
+	:cl=\EH\EJ:cm=\E[%i%d;%dH:cr=\EG:cs=\E[%i%d;%dr:ct=\E[3g:\
+	:dc=\E[P:dl=\E[M:do=\E[1B:ec=\E[%ds\E[%dD:ei=:fs=\E8:\
+	:ho=\E[H:\
+	:i1=\E[0;23r\Ex\Ey\E[2;0j\E[3;3j\E[4;0j\E[5;0j\E[6;0j\E[7;0j\E[8;0j\E[9;1j\E[10;0j\E[15;0j\E[16;1j\E[19;0j\E[20;1j\E[29;0j\E[1;24r:\
+	:ic=\E[@:im=:k1=\EOc:k2=\EOd:k3=\EOe:k4=\EOf:k5=\EOg:\
+	:k6=\EOh:k7=\EOi:k8=\EOj:kD=\E[P:kH=\Eu:kI=\E[4h:kN=\E[U:\
+	:kP=\E[V:kb=^H:kd=\E[B:ke=\E[19;0j:kh=\E[H:kl=\E[D:kr=\E[C:\
+	:ks=\E[19;1j:ku=\E[A:le=^H:ll=\Ew:mb=\E[5m:me=\E[m\017:\
+	:mh=\E[2m:mr=\E[7m:nd=\E[1C:nw=^M^J:rc=\E8:sc=\E7:se=\E[m:\
+	:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:ts=\E7\E[25;%p1%{8}%+%dH:ue=\E[m:us=\E[4m:\
+	:vb=\E[?5h\E[?5l:ve=\E[11;0j:vs=\E[11;1j:
+att5420_2-w|AT&T 5420 model 2 in 132 column mode:\
+	:co#132:\
+	:i1=\E[0;23r\Ex\Ey\E[2;0j\E[3;3j\E[4;0j\E[5;1j\E[6;0j\E[7;0j\E[8;0j\E[9;1j\E[10;0j\E[15;0j\E[16;1j\E[19;0j\E[20;1j\E[29;0j\E[1;24r:tc=att5420_2:
+
+att4418|att5418|AT&T 5418 80 cols:\
+	:am:xo:\
+	:co#80:li#24:\
+	:@8=\E[:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:F1=\E[n:\
+	:F2=\E[o:F3=\E[H:F4=\E[I:F5=\E[J:F8=\E[K:F9=\E[L:FA=\E[E:\
+	:FB=\E[_:FC=\E[M:FD=\E[N:FE=\E[O:IC=\E[%d@:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=^O:al=\E[1L:as=^N:bl=^G:cd=\E[0J:ce=\E[0K:cl=\E[H\E[2J:\
+	:cm=\E[%i%d;%dH:cr=^M:dc=\E[1P:dl=\E[M:do=\E[B:ei=:ho=\E[H:\
+	:i1=\E[?3l:ic=\E[1@:im=:is=\E)0\E?6l\E?5l:k1=\E[h:k2=\E[i:\
+	:k3=\E[j:k6=\E[k:k7=\E[l:k8=\E[f:k9=\E[w:k;=\E[m:kC=\E[%:\
+	:kd=\EU:kh=\Ec:kl=\E@:kr=\EA:ku=\ES:le=\E[D:mb=\E[5m:\
+	:me=\E[m\017:mh=\E[2m:mr=\E[7m:nd=\E[C:rc=\E8:sc=\E7:\
+	:se=\E[m:sf=^J:so=\E[7m:ue=\E[m:up=\E[A:us=\E[4m:
+att4418-w|att5418-w|AT&T 5418 132 cols:\
+	:co#132:\
+	:i1=\E[?3h:tc=att5418:
+
+att4420|tty4420|teletype 4420:\
+	:bs:da:db:eo:ms:ul:xo:\
+	:co#80:li#24:lm#72:\
+	:al=\EL:bl=^G:cd=\EJ:ce=\Ez:cl=\EH\EJ:cm=\EY%+ %+ :cr=\EG:\
+	:dc=\EP:dl=\EM:dm@:do=\EB:ed@:ho=\EH:k0=\EU:k3=\E@:kA=\EL:\
+	:kB=\EO:kC=\EJ:kD=\EP:kF=\ES:kI=\E\136:kL=\EM:kR=\ET:kd=\EB:\
+	:kh=\EH:kl=^H:kr=\EC:ku=\EA:l0=segment advance:\
+	:l3=cursor tab:le=\ED:nd=\EC:se=\E~:sf=\EH\EM\EY7 :so=\E}:\
+	:ue=\EZ:up=\EA:us=\E\:
+
+#  The following is a terminfo entry for the Teletype 4424
+#  asynchronous keyboard-display terminal.  It supports
+#  the vi editor.  The terminal must be set up as follows,
+# 	
+# 	HIGHLIGHT DEFINITION	3-TONE
+# 	DISPLAY FUNCTION	GROUP III
+# 	
+#  The second entry below provides limited (a la adm3a)
+#  operation under GROUP II.
+# 	
+#  This must be used with DISPLAY FUNCTION GROUP I or III
+# 	and HIGHLIGHT DEFINITION 3-TONE
+# The terminal has either bold or blink, depending on options
+#
+# (att4424: commented out :ti:=\E[1m, we don't need bright locked on -- esr)
+att4424|tty4424|teletype 4424:\
+	:am:bs:xo:\
+	:co#80:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=\E(B:al=\EL:as=\E(0:bl=^G:bt=\EO:cd=\EJ:ce=\Ez:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:ct=\EF:\
+	:dc=\EP:dl=\EM:do=\EB:ei=:ho=\E[H:ic=\E\136:im=:\
+	:is=\E[20l\E[?7h:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:kC=\EJ:\
+	:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mb=\E3:\
+	:md=\E3:me=\EX\E~\EZ\E4\E(B:mh=\EW:mr=\E}:nd=\EC:nw=\EE:\
+	:..sa=\E[%?%p1%t7%;%?%p2%t;4%;%?%p3%t;7%;%?%p6%t;1%;%?%p6%p4%|%t;5%;%?%p5%t;0%;m:\
+	:se=\E~:sf=^J:so=\E}:sr=\ET:st=\EH:ta=^I:ue=\EZ:up=\EA:\
+	:us=\E\:
+
+att4424-1|tty4424-1|teletype 4424 in display function group I:\
+	:kC@:kd=\EB:kh@:kl=\ED:kr=\EC:ku=\EA:\
+	:tc=att4424:
+
+# This entry is not one of AT&T's official ones, it was translated from the
+# 4.4BSD termcap file.  The highlight strings are different from att4424.
+# I have no idea why this is -- older firmware version, maybe?
+# The following two lines are the comment originally attached to the entry:
+# This entry appears to avoid the top line - I have no idea why.
+# From: jwb Wed Mar 31 13:25:09 1982 remote from ihuxp
+att4424m|tty4424m|teletype 4424M:\
+	:am:da:db:mi:\
+	:co#80:it#8:li#23:\
+	:al=\EL:bl=^G:ce=\E[K:cl=\E[2;H\E[J:cm=\E[%i%2;%2H\E[B:\
+	:cr=^M:dc=\EP:dl=\EM:do=^J:ei=:ic=\E\136:im=:ip=2:\
+	:is=\E[m\E[2;24r:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:kb=^H:\
+	:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:me=\E[m:\
+	:nd=\E[C:nw=^M^J:se=\E[m:sf=^J:so=\E[7m:sr=\ET:ta=^I:\
+	:ue=\E[m:up=\E[A:us=\E[4m:
+
+# The Teletype 5425 is really version 2 of the Teletype 5420. It 
+# is quite similar, except for some minor differences. No page 
+# mode, for example, so all of the :cm: sequences used above have 
+# to change back to what's being used for the 5410. Many of the 
+# option settings have changed their numbering as well.
+# 
+# This has been tested on a preliminary model.
+#
+# (att5425: added <rmam>/<smam> based on the init string -- esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+att5425|tty5425|att4425|AT&T 4425/5425:\
+	:am:da:db:hs:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:lm#78:ws#55:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:SF=\E[%dE:SR=\E[%dF:UP=\E[%dA:ae=^O:\
+	:al=\E[L:as=^N:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:\
+	:dl=\E[M:do=^J:ec=\E[%ds\E[%dD:ei=\E[4l:fs=\E8:ho=\E[H:\
+	:i1=\E<\E[?3l:i2=\E[?5l:im=\E[4h:\
+	:is=\E[m\017\E[1;2;3;4;6l\E[12;13;14;20l\E[?6;97;99l\E[?7h\E[4i\Ex\E[25;1j\212:\
+	:k1=\EOc:k2=\EOd:k3=\EOe:k4=\EOf:k5=\EOg:k6=\EOh:k7=\EOi:\
+	:k8=\EOj:kD=\E[P:kI=\E[4h:kb=^H:kd=\E[B:\
+	:ke=\E[21;0j\E[25;1j\212:kh=\E[H:kl=\E[D:kr=\E[C:\
+	:ks=\E[21;1j\E[25;4j\Eent\E~:ku=\E[A:le=^H:ll=\E[24H:\
+	:mb=\E[5m:md=\E[2;7m:me=\E[m\017:mh=\E[2m:mr=\E[7m:\
+	:nd=\E[C:nw=^M^J:rc=\E8:sc=\E7:se=\E[m:sf=^J:so=\E[7m:\
+	:sr=\EM:st=\EH:ta=^I:ts=\E7\E[25;%p1%{8}%+%dH:ue=\E[m:\
+	:up=\E[A:us=\E[4m:vb=\E[?5h\E[?5l:ve=\E[12;0j:\
+	:vs=\E[12;1j:
+
+att5425-nl|tty5425-nl|att4425-nl|AT&T 4425/5425 80 columns no labels:\
+	:ks=\E[21;1j\E[25;4j\Eent:\
+	:tc=att4425:
+
+att5425-w|att4425-w|tty5425-w|teletype 4425/5425 in 132 column mode:\
+	:co#132:lm#54:ws#97:\
+	:i1=\E[?3h:tc=tty5425:
+
+# (att4426: his had bogus capabilities: :ri=\EM:, :ri=\E[1U:. 
+# I also added <rmam>/<smam> -- esr)
+att4426|tty4426|teletype 4426S:\
+	:am:da:db:xo:\
+	:co#80:li#24:lm#48:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:SF=\E[%dS:\
+	:SR=\E[%dT:UP=\E[%dA:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=\E(B:al=\EL:as=\E(0:bl=^G:cd=\E[J:ce=\E[0K:ch=\E[%dG:\
+	:cl=\E[H\E[2J\E[1U\E[H\E[2J\E[1V:cm=\E[%i%d;%dH:cr=^M:\
+	:ct=\E[3g:cv=\E[%dd:dc=\EP:dl=\E[M:do=\E[B:ei=:ho=\E[H:\
+	:i1=\Ec\E[?7h:ic=\E\136:im=:is=\E[m\E[1;24r:k1=\EOP:\
+	:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\EOT:k6=\EOU:k7=\EOV:k8=\EOW:\
+	:kB=\EO:kC=\E[2J:kH=\E[24;1H:kb=^H:kd=\EB:kh=\E[H:kl=\ED:\
+	:kr=\EC:ku=\EA:le=\E[D:ll=\E[24H:md=\E[5m:me=\E[m\E(B:\
+	:mr=\E[7m:nd=\E[C:nw=^M^J:r2=\Ec\E[?3l\E[2;0y:rc=\E8:\
+	:sc=\E7:se=\E[m:sf=^J:so=\E[5m:sr=\ET:st=\E1:ta=^I:ue=\E[m:\
+	:up=\EA:us=\E[4m:
+
+# Terminfo entry for the AT&T 510 A Personal Terminal
+# Function keys 9 - 16 are available only after the 
+# screen labeled (soft keys/action blocks) are labeled.  Function key
+# 9 corresponds to the leftmost touch target on the screen,
+# function key 16 corresponds to the rightmost.
+#
+# This entry is based on one done by Ernie Rice at Summit, NJ and
+# changed by Anne Gallup, Skokie, IL, ttrdc!anne
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+att510a|bct510a|AT&T 510A Personal Terminal:\
+	:am:mi:ms:xn:xo:\
+	:Nl#8:co#80:lh#2:li#24:lw#7:\
+	:#4=\E[u:%i=\E[v:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:\
+	:F1=\EOe:F2=\EOf:F3=\EOg:F4=\EOh:F5=\EOi:F6=\EOj:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:\
+	:ac=+g\054h-f.e`bhrisjjkkllmmnnqqttuuvvwwxx{{||}}~~:\
+	:ae=^O:al=\E[L:as=^N:bl=^G:bt=\E[Z:cb=\E[1K:cd=\E[0J:\
+	:ce=\E[0K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:ct=\E[3g:\
+	:dc=\E[P:dl=\E[M:do=\E[1B:eA=\E(B\E)1:ff=^L:ho=\E[H:\
+	:i1=\E(B\E)1\E[2l:i2=\E[21;1|\212:k1=\EOm:k2=\EOV:\
+	:k3=\EOu:k4=\ENj:k5=\ENe:k6=\ENf:k7=\ENh:k8=\E[H:k9=\EOc:\
+	:k;=\EOd:kB=\E[Z:kF=\E[S:kR=\E[T:kb=^H:kd=\E[B:ke=\E[19;0|:\
+	:kl=\E[D:kr=\E[C:ks=\E[19;1|:ku=\E[A:le=^H:mb=\E[5m:\
+	:md=\E[2;7m:me=\E[m\017:mh=\E[2m:mr=\E[7m:nd=\E[C:nw=\EE:\
+	:pf=\E[?8i:po=\E[?4i:ps=\E[0i:rc=\E8:sc=\E7:se=\E[m:sf=^J:\
+	:so=\E[7m:sr=\EM:st=\EH:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:\
+	:ve=\E[11;3|:vi=\E[11;0|:vs=\E[11;2|:
+
+# Terminfo entry for the AT&T 510 D Personal Terminal
+# Function keys 9 through 16 are accessed by bringing up the
+# system blocks.
+# Function key 9 corresponds to the leftmost touch target on the screen,
+# function key 16 corresponds to the rightmost.
+#
+# There are problems with soft key labeling.  These are due to 
+# strangenesses in the native terminal that are impossible to
+# describe in a terminfo.  
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+att510d|bct510d|AT&T 510D Personal Terminal:\
+	:am:da:db:mi:ms:xn:xo:\
+	:co#80:li#24:lm#48:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:SF=\E[%dS:SR=\E[%dT:UP=\E[%dA:ae=^O:\
+	:al=\E[L:as=^N:bl=^G:bt=\E[Z:cd=\E[0J:ce=\E[0K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:ct=\E[3g:dc=\E[P:dl=\E[M:do=\E[1B:\
+	:ei=\E[4l:ff=^L:ho=\E[H:i1=\E(B\E)1\E[5;0|:\
+	:i2=\E[21;1|\212:im=\E[4h:k1=\EOm:k2=\EOV:k3=\EOu:k4=\ENj:\
+	:k5=\ENe:k6=\ENf:k7=\ENh:k8=\E[H:k9=\EOc:kb=^H:kd=\E[B:\
+	:ke=\E[19;0|:kl=\E[D:kr=\E[C:ks=\E[19;1|:ku=\E[A:le=^H:\
+	:ll=\E#2:mb=\E[5m:md=\E[2;7m:me=\E[m\017:mh=\E[2m:\
+	:mr=\E[7m:nd=\E[C:nw=\EE:rc=\E8:sc=\E7:se=\E[m:sf=^J:\
+	:so=\E[7m:sr=\EM:st=\EH:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:\
+	:ve=\E[11;3|:vs=\E[11;2|:
+
+# (att500: I merged this with the att513 entry, att500 just used att513 -- esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+att500|att513|AT&T 513 using page mode:\
+	:am:mi:ms:xn:xo:\
+	:co#80:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:SF=\E[%dE:SR=\E[%dF:UP=\E[%dA:ae=^O:\
+	:al=\E[L:as=^N:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=%i\E[%d;%dr:ct=\E[3g:dc=\E[P:\
+	:dl=\E[M:do=^J:ei=\E[4l:ho=\E[H:\
+	:i1=\E?\E[3;3|\E[10;0|\E[21;1|\212\E[6;1|\E[1{\E[?99l:\
+	:im=\E[4h:k1=\EOc:k2=\EOd:k3=\EOe:k4=\EOf:k5=\EOg:k6=\EOh:\
+	:k7=\EOi:k8=\EOj:kD=\ENf:kI=\ENj:kN=\E[U:kP=\E[V:kb=^H:\
+	:kd=\E[B:ke=\E[19;0|\E[21;1|\212:kh=\E[H:kl=\E[D:kr=\E[C:\
+	:ks=\E[19;1|\E[21;4|\Eent:ku=\E[A:le=^H:ll=\E#2:mb=\E[5m:\
+	:md=\E[2;7m:me=\E[m\017:mh=\E[2m:mr=\E[7m:nd=\E[C:nw=\EE:\
+	:rc=\E8:sc=\E7:se=\E[m:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:ue=\E[m:up=\E[A:us=\E[4m:ve=\E[11;0|:vs=\E[11;1|:
+
+# 01-07-88
+# printer must be set to EMUL ANSI to accept ESC codes
+# :up: stops at top margin
+# :i1: sets cpi 10,lpi 6,form 66,left 1,right 132,top 1,bottom 66,font
+#	and alt font ascii,wrap on,tabs cleared
+# :is: disables newline on LF,Emphasized off
+# The <u0> capability sets form length
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+att5310|att5320|AT&T Model 53210 or 5320 matrix printer:\
+	:co#132:it#8:li#66:\
+	:DO=\E[%de:RI=\E[%da:cr=^M:do=^J:ff=^L:i1=\Ec:is=\E[20l\r:\
+	:nd= :ta=^I:up=\EM:
+
+# Teletype 5620, firmware version 1.1 (8;7;3) or earlier from BRL
+# The following SET-UP modes are assumed for normal operation:
+#	CR_DEF=CR	NL_DEF=INDEX	DUPLEX=FULL
+# Other SET-UP modes may be set for operator convenience or communication
+# requirements.  This termcap description is for the Resident Terminal Mode.
+# No delays specified; use "stty ixon -ixany" to enable DC3/DC1 flow control!
+# The BRL entry also said: UNSAFE :ll=\E[70H:
+att5620-1|tty5620-1|dmd1|Teletype 5620 with old ROMs:\
+	:am:xo:\
+	:co#88:it#8:li#70:vt#3:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:IC=\E[%d@:SF=\E[%dS:\
+	:SR=\E[%dT:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:dl=\E[M:do=^J:ei=:ho=\E[H:\
+	:ic=\E[@:im=:kC=\E[2J:kH=\E[70;1H:kb=^H:kd=\E[B:kh=\E[H:\
+	:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:nd=\E[C:nw=^M^J:r1=\Ec:\
+	:rc=\E8:sc=\E7:sf=^J:sr=\E[T:ta=^I:up=\E[A:
+
+# 5620 terminfo  (2.0 or later ROMS with char attributes)
+# The following SET-UP modes are assumed for normal operation:
+#	DUPLEX=FULL	GEN_FLOW=ON	NEWLINE=INDEX	RETURN=CR
+# Other SET-UP modes may be set for operator convenience or communication
+# requirements.  This termcap description is for Resident Terminal Mode.  No
+# delays are specified; use "stty ixon -ixany" to enable DC3/DC1 flow control!
+# assumptions: :sf: (scroll forward one line) is only done at screen bottom
+# Be aware that older versions of the dmd have a firmware bug that affects
+# parameter defaulting; for this terminal, the 0 in \E[0m is not optional.
+# :ms: is from an otherwise inferior BRL for this terminal.  That entry
+# also has :ll:=\E[70H commented out and marked unsafe.
+# For more, see the 5620 FAQ maintained by David Breneman <daveb@dgtl.com>.
+att5620|dmd|tty5620|ttydmd|5620|5620 terminal 88 columns:\
+	:NL:NP:am:bs:ms:xo:\
+	:co#88:it#8:li#70:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:IC=\E[%d@:SF=\E[%dS:\
+	:SR=\E[%dT:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:dl=\E[M:do=\E[B:ei=:ho=\E[H:\
+	:ic=\E[@:im=:kC=\E[2J:kH=\E[70;1H:kb=^H:kd=\E[B:kh=\E[H:\
+	:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:md=\E[2m:me=\E[0m:mh=\E[2m:\
+	:mr=\E[7m:nd=\E[C:nw=^J:..px=\E[%p1%d;%p2%l%dq%p2%s:\
+	:r1=\Ec:rc=\E8:sc=\E7:se=\E[0m:sf=\E[S:so=\E[7m:sr=\E[T:\
+	:ta=^I:ue=\E[0m:up=\E[A:us=\E[4m:
+att5620-24|tty5620-24|dmd-24|teletype dmd 5620 in a 24x80 layer:\
+	:li#24:tc=att5620:
+att5620-34|tty5620-34|dmd-34|teletype dmd 5620 in a 34x80 layer:\
+	:li#34:tc=att5620:
+# 5620 layer running the "S" system's downloaded graphics handler:
+att5620-s|tty5620-s|layer|vitty|5620 S layer:\
+	:am:bs:pt:\
+	:co#80:it#8:li#72:\
+	:al=\EI:bl=^G:ce=\EK:cl=^L:cm=\EY%r%+ %+ :cr=^M:dl=\ED:\
+	:do=^J:kC=\E[2J:kH=\E[70;1H:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:\
+	:kr=\E[C:ku=\E[A:le=^H:sf=^J:ta=^I:up=^K:vb=\E^G:
+
+# Entries for <kf15> thru <kf28> refer to the shifted system pf keys.
+#
+# Entries for <kf29> thru <kf46> refer to the alternate keypad mode
+# keys:  = * / + 7 8 9 - 4 5 6 , 1 2 3 0 . ENTER
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+att605|AT&T 605 80 column 102key keyboard:\
+	:am:eo:xo:\
+	:co#80:li#24:ws#80:\
+	:DC=\E[%dP:DL=\E[%dM:IC=\E[%d@:ae=^O:al=\E[L:as=\E)0\016:\
+	:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:\
+	:cr=^M:dc=\E[P:dl=\E[M:do=\E[B:ei=\E[4l:fs=\E8:\
+	:i1=\E[8;0|\E[?\E[13;20l\E[?\E[12h:ic=\E[@:im=\E[4h:\
+	:is=\E[m\017:k1=\EOc:k2=\EOd:k3=\EOe:k4=\EOf:k5=\EOg:\
+	:k6=\EOh:k7=\EOi:k8=\EOj:k9=\ENo:kD=\E[P:kI=\E[@:kN=\E[U:\
+	:kP=\E[V:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:le=^H:ll=\E[24H:mb=\E[5m:md=\E[1m:me=\E[m\017:mh=\E[2m:\
+	:mr=\E[7m:nd=\E[C:nw=\EE:rc=\E8:sc=\E7:se=\E[m:sf=^J:\
+	:so=\E[7m:ta=^I:ts=\E7\E[25;%i%p1%dx:ue=\E[m:up=\E[A:\
+	:us=\E[4m:
+att605-pc|ATT 605 in pc term mode:\
+	:@7=\E[F:AL=\E[L:S4=250\E[?11l\E[50;1|:S5=400\E[50;0|:\
+	:XF=g:XN=e:\
+	:ac=j\331k\277l\332m\300n\305q\304t\303u\264v\301w\302x\263:\
+	:al=\E[L:bt=\E[Z:dc=\E[P:dl=\E[M:do=\E[B:ei=:ic=\E[@:im=:\
+	:k1=\E[M:k2=\E[N:k3=\E[O:k4=\E[P:k5=\E[Q:k6=\E[R:k7=\E[S:\
+	:k8=\E[T:k9=\E[U:k;=\E[V:kB=\E[Z:kD=\E[P:kI=\E[@:kL=\E[M:\
+	:kN=\E[G:kP=\E[I:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:le=\E[D:nd=\E[C:up=\E[A:\
+	:tc=att605:
+att605-w|AT&T 605-w 132 column 102 key keyboard:\
+	:co#132:ws#132:\
+	:i1=\E[8;0|\E[?4;5;13;15l\E[13;20l\E[?3;7h\E[12h\E(B\E)0:tc=att605:
+# (att610: I added <rmam>/<smam> based on the init string.  I also
+# added :SF: and :SR: because the BSD file says the att615s have them,
+# and the 615 is like a 610 with a big keyboard, and most of their other
+# smart terminals support the same sequence -- esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+att610|AT&T 610; 80 column; 98key keyboard:\
+	:am:es:hs:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:ws#80:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:SF=\E[%dS:SR=\E[%dT:UP=\E[%dA:ae=^O:\
+	:al=\E[L:as=^N:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:dc=\E[P:dl=\E[M:\
+	:do=\E[B:ei=\E[4l:fs=\E8:ho=\E[H:\
+	:i1=\E[8;0|\E[?3;4;5;13;15l\E[13;20l\E[?7h\E[12h\E(B\E)0:\
+	:i2=\E(B\E)0:im=\E[4h:is=\E[m\017:k1=\EOc:k2=\EOd:k3=\EOe:\
+	:k4=\EOf:k5=\EOg:k6=\EOh:k7=\EOi:k8=\EOj:k9=\ENo:kb=^H:\
+	:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:ll=\E[24H:\
+	:mb=\E[5m:md=\E[1m:me=\E[m\017:mh=\E[2m:mr=\E[7m:nd=\E[C:\
+	:nw=\EE:rc=\E8:sc=\E7:se=\E[m:sf=\ED:so=\E[7m:sr=\EM:ta=^I:\
+	:ts=\E7\E[25;%i%p1%dx:ue=\E[m:up=\E[A:us=\E[4m:\
+	:vb=\E[?5h\E[?5l:ve=\E[?25h\E[?12l:vi=\E[?25l:\
+	:vs=\E[?12;25h:
+att610-w|AT&T 610; 132 column; 98key keyboard:\
+	:co#132:ws#132:\
+	:i1=\E[8;0|\E[?4;5;13;15l\E[13;20l\E[?3;7h\E[12h:tc=att610:
+
+att610-103k|AT&T 610; 80 column; 103key keyboard:\
+	:!1=\EOO:!2=\EOP:!3=\EOS:#1=\EOM:%0=\EOt:%1=\EOm:%2=\ENi:\
+	:%3=\EOl:%4=\ENc:%5=\ENh:%6=\EOv:%7=\EOr:%8=\ENg:%9=\EOz:\
+	:%a=\EOL:%b=\ENC:%c=\ENH:%d=\EOR:%e=\ENG:%f=\EOZ:%g=\EOT:\
+	:%h=\EOY:%j=\EOQ:&0=\EOW:&1=\EOb:&2=\ENa:&3=\EOy:&4=\EOB:\
+	:&5=\EOq:&6=\EOo:&7=\EOp:&8=\EOs:&9=\ENB:*0=\EOX:*1=\EOU:\
+	:*2=\END:*3=\EON:*4=\ENF:*5=\ENE:*6=\ENI:*7=\ENN:*8=\EOA:\
+	:*9=\EOK:@0=\EOx:@1=\E9:@2=\EOw:@3=\EOV:@4=\EOu:@5=\ENd:\
+	:@6=\EOn:@7=\E0:@8=^M:@9=\EOk:F1@:F2@:F3@:F4@:k9@:k;@:kD=\ENf:\
+	:kE=\EOa:kI=\ENj:kL=\ENe:kM=\ENj:kN=\E[U:kP=\E[V:\
+	:tc=att610:
+att610-103k-w|AT&T 610; 132 column; 103key keyboard:\
+	:co#132:ws#132:\
+	:i1=\E[8;0|\E[?4;5;13;15l\E[13;20l\E[?3;7h\E[12h:tc=att610-103k:
+att615|AT&T 615; 80 column; 98key keyboard:\
+	:#4=\E[ A:%i=\E[ @:F5=\EOC:F6=\EOD:F7=\EOE:F8=\EOF:F9=\EOG:\
+	:FA=\EOH:FB=\EOI:FC=\EOJ:FD=\ENO:FE=\ENP:FF=\ENQ:FG=\ENR:\
+	:FH=\ENS:FI=\ENT:FJ=\EOP:FK=\EOQ:FL=\EOR:FM=\EOS:FN=\EOw:\
+	:FO=\EOx:FP=\EOy:FQ=\EOm:FR=\EOt:FS=\EOu:FT=\EOv:FU=\EOl:\
+	:FV=\EOq:FW=\EOr:FX=\EOs:FY=\EOp:FZ=\EOn:Fa=\EOM:\
+	:tc=att610:
+att615-w|AT&T 615; 132 column; 98key keyboard:\
+	:#4=\E[ A:%i=\E[ @:F5=\EOC:F6=\EOD:F7=\EOE:F8=\EOF:F9=\EOG:\
+	:FA=\EOH:FB=\EOI:FC=\EOJ:FD=\ENO:FE=\ENP:FF=\ENQ:FG=\ENR:\
+	:FH=\ENS:FI=\ENT:FJ=\EOP:FK=\EOQ:FL=\EOR:FM=\EOS:FN=\EOw:\
+	:FO=\EOx:FP=\EOy:FQ=\EOm:FR=\EOt:FS=\EOu:FT=\EOv:FU=\EOl:\
+	:FV=\EOq:FW=\EOr:FX=\EOs:FY=\EOp:FZ=\EOn:Fa=\EOM:\
+	:tc=att610-w:
+att615-103k|AT&T 615; 80 column; 103key keyboard:\
+	:#4=\E[ A:%i=\E[ @:\
+	:tc=att610-103k:
+att615-103k-w|AT&T 615; 132 column; 103key keyboard:\
+	:#4=\E[ A:%i=\E[ @:\
+	:tc=att610-103k-w:
+# (att620: I added <rmam>/<smam> based on the init string and
+# :SR:/:SF: from a BSD termcap -- esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+att620|AT&T 620; 80 column; 98key keyboard:\
+	:am:es:hs:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:ws#80:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:SF=\E[%dS:SR=\E[%dT:UP=\E[%dA:\
+	:ae=\E(B\017:al=\E[L:as=\E)0\016:bl=^G:bt=\E[Z:cd=\E[J:\
+	:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:dc=\E[P:dl=\E[M:do=\E[B:ei=\E[4l:fs=\E8:ho=\E[H:\
+	:i1=\E[8;0|\E[?3;4;5;13;15l\E[13;20l\E[?7h\E[12h:\
+	:i2=\E(B\E)0:im=\E[4h:is=\E[m\017:k1=\EOc:k2=\EOd:k3=\EOe:\
+	:k4=\EOf:k5=\EOg:k6=\EOh:k7=\EOi:k8=\EOj:k9=\ENo:kb=^H:\
+	:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:ll=\E[24H:\
+	:mb=\E[5m:md=\E[1m:me=\E[m\E(B\017:mh=\E[2m:mr=\E[7m:\
+	:nd=\E[C:nw=\EE:rc=\E8:sc=\E7:se=\E[m:sf=\ED:so=\E[7m:\
+	:sr=\EM:ta=^I:ts=\E7\E[25;%i%p1%dx:ue=\E[m:up=\E[A:\
+	:us=\E[4m:vb=\E[?5h\E[?5l:ve=\E[?25h\E[?12l:vi=\E[?25l:\
+	:vs=\E[?12;25h:
+att620-w|AT&T 620; 132 column; 98key keyboard:\
+	:co#132:ws#132:\
+	:i1=\E[8;0|\E[?4;5;13;15l\E[13;20l\E[?3;7h\E[12h:tc=att620:
+att620-103k|AT&T 620; 80 column; 103key keyboard:\
+	:!1=\EOO:!2=\EOP:!3=\EOS:#1=\EOM:%0=\EOt:%1=\EOm:%2=\ENi:\
+	:%3=\EOl:%4=\ENc:%5=\ENh:%6=\EOv:%7=\EOr:%8=\ENg:%9=\EOz:\
+	:%a=\EOL:%b=\ENC:%c=\ENH:%d=\EOR:%e=\ENG:%f=\EOZ:%g=\EOT:\
+	:%h=\EOY:%j=\EOQ:&0=\EOW:&1=\EOb:&2=\ENa:&3=\EOy:&4=\EOB:\
+	:&5=\EOq:&6=\EOo:&7=\EOp:&8=\EOs:&9=\ENB:*0=\EOX:*1=\EOU:\
+	:*2=\END:*3=\EON:*4=\ENF:*5=\ENE:*6=\ENI:*7=\ENN:*8=\EOA:\
+	:*9=\EOK:@0=\EOx:@1=\E9:@2=\EOw:@3=\EOV:@4=\EOu:@5=\ENd:\
+	:@6=\EOn:@7=\E0:@8=^M:@9=\EOk:F1@:F2@:F3@:F4@:F5@:F6@:F7@:F8@:\
+	:F9@:FA@:FB@:FC@:FD@:FE@:FF@:FG@:FH@:FI@:FJ@:FK@:FL@:FM@:FN@:FO@:FP@:\
+	:FQ@:FR@:FS@:FT@:FU@:FV@:FW@:FX@:FY@:FZ@:Fa@:k9@:k;@:kD=\ENf:\
+	:kE=\EOa:kI=\ENj:kL=\ENe:kM=\ENj:kN=\E[U:kP=\E[V:\
+	:tc=att620:
+
+att620-103k-w|AT&T 620; 132 column; 103key keyboard:\
+	:co#132:ws#132:\
+	:i1=\E[8;0|\E[?4;5;13;15l\E[13;20l\E[?3;7h\E[12h:tc=att620-103k:
+
+# AT&T (formerly Teletype) 630 Multi-Tasking Graphics terminal
+# The following SETUP modes are assumed for normal operation:
+#	Local_Echo=Off	Gen_Flow=On	Return=CR	Received_Newline=LF
+#	Font_Size=Large		Non-Layers_Window_Cols=80
+#				Non-Layers_Window_Rows=60
+# Other SETUP modes may be set for operator convenience or communication
+# requirements.  Some capabilities assume a printer attached to the Aux EIA
+# port.  This termcap description is for the Fixed Non-Layers Window.  No
+# delays are specified; use "stty ixon -ixany" to enable DC3/DC1 flow control!
+# (att630: added :ic:, :mb: and :mh: from a BSD termcap file -- esr)
+att630|AT&T 630 windowing terminal:\
+	:NP:am:bs:da:db:mi:ms:xo:\
+	:co#80:it#8:li#60:lm#0:\
+	:@8=^M:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:F1=\ENq:\
+	:F2=\ENr:F3=\ENs:F4=\ENt:F5=\ENu:F6=\ENv:F7=\ENw:F8=\ENx:\
+	:F9=\ENy:FA=\ENz:FB=\EN{:FC=\EN|:FD=\EN}:FE=\EN~:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:SF=\E[%dS:SR=\E[%dT:UP=\E[%dA:\
+	:al=\E[L:bl=^G:bt=\E[Z:cb=\E[1K:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:dl=\E[M:do=\E[B:\
+	:ei=\E[4l:ho=\E[H:ic=\E[@:im=\E[4h:is=\E[m:k9=\ENo:k;=\ENp:\
+	:kA=\E[L:kB=\E[Z:kC=\E[2J:kD=\E[P:kI=\E[@:kL=\E[M:kb=^H:\
+	:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mb=\E[5m:\
+	:me=\E[m:mh=\E[2m:mr=\E[7m:nd=\E[C:nw=^M^J:pf=\E[?4i:\
+	:po=\E[?5i:..px=\E[%p1%d;%p2%l%dq%p2%s:r2=\Ec:rc=\E8:\
+	:..sa=\E[0%?%p2%t;4%;%?%p1%p3%|%p4%|%p5%|%t;7%;m:\
+	:sc=\E7:se=\E[m:sf=\ED:so=\E[7m:sr=\EM:ta=^I:ue=\E[m:\
+	:up=\E[A:us=\E[4m:
+att630-24|5630-24|5630DMD-24|630MTG-24|AT&T 630 windowing terminal 24 lines:\
+	:li#24:tc=att630:
+
+# This is the att700 entry for 700 native emulation of the AT&T 700
+# terminal.  Comments are relative to changes from the 605V2 entry and
+# att730 on which the entry is based.  Comments show the terminfo
+# capability name, termcap name, and description.
+#
+# Here is what's going onm in the init string:
+#	ESC [ 50;4|	set 700 native mode (really is 605)
+# x	ESC [ 56;ps| 	set lines to 24: ps=0; 40: ps=1 (plus status line)
+#	ESC [ 53;0|	set GenFlow to Xon/Xoff
+#	ESC [ 8 ;0|	set CR on NL 
+# x	ESC [ ? 3 l/h	set workspace: 80 col(l); 132 col(h)
+#	ESC [ ? 4 l	jump scroll 
+#	ESC [ ? 5 l/h	video: normal (l); reverse (h)
+#	ESC [ ?13 l	Labels on
+#	ESC [ ?15 l	parity check = no
+#	ESC [ 13 l	monitor mode off
+#	ESC [ 20 l	LF on NL (not CRLF on NL)
+#	ESC [ ? 7 h	autowrap on
+#	ESC [ 12 h	local echo off
+#	ESC ( B		GO = ASCII
+#	ESC ) 0		G1 = Special Char & Line Drawing
+#	ESC [ ? 31 l	Set 7 bit controls
+#
+# Note: Most terminals, especially the 600 family use Reverse Video for
+# standout mode.  DEC also uses reverse video.  The VT100 uses bold in addition
+# Assume we should stay with reverse video for 70..  However, the 605V2 exits
+# standout mode with \E[m (all normal attributes).  The 730 entry simply
+# exits reverse video which would leave other current attributes intact.  It
+# was assumed the 730 entry to be more correct so rmso has changed.  The
+# 605V2 has no sequences to turn individual attributes off, thus its setting
+# and the rmso/smso settings from the 730.
+#
+# Note: For the same reason as above in rmso I changed exit under-score mode
+# to specifically turn off underscore, rather than return to all normal 
+# attributes
+#
+# Note: The following pkey_xmit is taken from the 605V2 which contained the
+# capability as pfxl.  It was changed here to pfx since pfxl
+# will only compile successfully with Unix 4.0 tic.  Also note that pfx only
+# allows strings to be parameters and label values must be programmed as
+# constant strings.  Supposedly the pfxl of Version 4.0 allows both labels
+# and strings to be parameters.  The 605V2 pfx entry should be examined later
+# in this regard. For reference the 730 pfxl entry is shown here for comparison
+# 730 pfx entry:
+#     pfxl=\E[%?%p1%{25}%<%t%p1%e%p1%{24}%-%;%d;%p2%l%02d%?%p1%{25}%<%tq\s\s\s
+# SYS\s\s\s\s\sF%p1%:-2d\s\s%e;0;3q%;%p2%s,
+#
+# (for 4.0 tic)
+#     pfxl=\E[%p1%d;%p2%l%02dq%?%p1%{9}%<%t   F%p1%1d           %;%p2%s,
+#
+# (for <4.0 tic)
+#     pfx=\E[%p1%d;%p2%l%02dq%?%p1%{9}%<%t   F%p1%1d           %;%p2%s,
+#
+# From the AT&T 705 Multi-tasking terminal user's guide Page 8-8,8-9
+#
+# Port1 Interface
+#
+# modular 10 pin Connector
+# Left side       Right side
+# Pin 1 2 3 4 5 6 7 8 9 10
+#
+#        Key (notch) at bottom
+#
+# Pin    1 DSR
+#        3 DCD
+#        4 DTR
+#        5 Sig Ground
+#        6 RD
+#        7 SD
+#        8 CTS
+#        9 RTS
+#        10 Frame Ground
+#
+# The manual is 189 pages and is loaded with details about the escape codes,
+# etc..... Available from AT&T CIC 800-432-6600...
+# ask for Document number 999-300-660..
+#
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+att700|AT&T 700 24x80 column display w/102key keyboard:\
+	:am:es:hs:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:ws#80:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:\
+	:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=\E[B:ei=\E[4l:\
+	:fs=\E8:ho=\E[H:i2=\E(B\E)0:im=\E[4h:\
+	:is=\E[50;4|\E[53;0|\E[8;0|\E[?4;13;15l\E[13;20l\E[?7h\E[12h\E(B\E)0\E[?31l\E[0m\017:\
+	:k1=\EOc:k2=\EOd:k3=\EOe:k4=\EOf:k5=\EOg:k6=\EOh:k7=\EOi:\
+	:k8=\EOj:k9=\ENo:kD=\E[P:kI=\E[@:kN=\E[U:kP=\E[V:kb=^H:\
+	:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:ll=\E[24H:\
+	:mb=\E[5m:md=\E[1m:me=\E[m\017:mh=\E[2m:mr=\E[7m:nd=\E[C:\
+	:nw=\EE:rc=\E8:sc=\E7:se=\E[27m:sf=\ED:so=\E[7m:sr=\EM:\
+	:st=\EH:ta=^I:ts=\E7\E[99;%i%p1%dx:ue=\E[24m:up=\E[A:\
+	:us=\E[4m:vb=\E[?5h\E[?5l:ve=\E[?25h\E[?12l:vi=\E[?25l:\
+	:vs=\E[?12;25h:
+
+# This entry was modified 3/13/90 by JWE.
+# fixes include additions of <enacs>, correcting :rp:, and modification
+# of <kHOM>.  (See comments below)
+# att730 has status line of 80 chars
+# These were commented out: :SF=\E[%p1%dS:, :SR=\E[%p1%dT:,
+# the <kf25> and up keys are used for shifted system Fkeys
+# NOTE: JWE 3/13/90 The 98 key keyboard translation for shift/HOME is 
+# currently the same as :kh: (unshifted HOME or \E[H).  On the 102, 102+1
+# and 122 key keyboards, the 730's translation is \E[2J.  For consistency
+# <kHOM> has been commented out.  The user can uncomment <kHOM> if using the
+# 102, 102+1, or 122 key keyboards
+#       kHOM=\E[2J,
+# (att730: I added <rmam>/<smam> based on the init string -- esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+att730|AT&T 730 windowing terminal:\
+	:am:da:db:es:hs:mi:ms:xn:xo:\
+	:co#80:it#8:li#60:lm#0:ws#80:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:\
+	:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:dc=\E[P:dl=\E[M:do=\E[B:ei=\E[4l:fs=\E8:\
+	:ho=\E[H:\
+	:i1=\E[8;0|\E[?3;4;5;13;15l\E[13;20l\E[?7h\E[12h\E(B\E)B:\
+	:i2=\E(B\E)0:im=\E[4h:is=\E[m\017:k1=\EOc:k2=\EOd:k3=\EOe:\
+	:k4=\EOf:k5=\EOg:k6=\EOh:k7=\EOi:k8=\EOj:k9=\ENo:kI=\E[@:\
+	:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:\
+	:mb=\E[5m:md=\E[1m:me=\E[m\017:mh=\E[2m:mr=\E[7m:nd=\E[C:\
+	:nw=\EE:rc=\E8:sc=\E7:se=\E[27m:sf=\ED:so=\E[7m:sr=\EM:\
+	:ta=^I:ts=\E7\E[;%i%p1%dx:ue=\E[24m:up=\E[A:us=\E[4m:\
+	:vb=\E[?5h\E[?5l:ve=\E[?25h\E[?12l:vi=\E[?25l:\
+	:vs=\E[?12;25h:
+att730-41|730MTG-41|AT&T 730-41 windowing terminal Version:\
+	:li#41:tc=att730:
+att730-24|730MTG-24|AT&T 730-24 windowing terminal Version:\
+	:li#24:tc=att730:
+att730r|730MTGr|AT&T 730 rev video windowing terminal Version:\
+	:i1=\E[8;0|\E[?3;4;13;15l\E[?5h\E[13;20l\E[?7h\E[12h\E(B\E)B:\
+	:vb=\E[?5l\E[?5h:\
+	:tc=att730:
+att730r-41|730MTG-41r|AT&T 730r-41 rev video windowing terminal Version:\
+	:li#41:tc=att730r:
+att730r-24|730MTGr-24|AT&T 730r-24 rev video windowing terminal Version:\
+	:li#24:tc=att730r:
+
+# The following represents the screen layout along with the associated
+# bezel buttons for the 5430/pt505 terminal. The "kf" designations do
+# not appear on the screen but are shown to reference the bezel buttons.
+# The "CMD", "MAIL", and "REDRAW" buttons are shown in their approximate
+# position relative to the screen.
+#
+#
+#
+#      +----------------------------------------------------------------+
+#      |                                                                |
+# XXXX | kf0                                                       kf24 | XXXX
+#      |                                                                |
+#      |                                                                |
+# XXXX | kf1                                                       kf23 | XXXX
+#      |                                                                |
+#      |                                                                |
+# XXXX | kf2                                                       kf22 | XXXX
+#      |                                                                |
+#      |                                                                |
+# XXXX | kf3                                                       kf21 | XXXX
+#      |                                                                |
+#      |                                                                |
+# XXXX | kf4                                                       kf20 | XXXX
+#      |                                                                |
+#      |                                                                |
+# XXXX | kf5                                                       kf19 | XXXX
+#      |                                                                |
+#      |                                                                |
+# XXXX | kf6                                                       kf18 | XXXX
+#      |                                                                |
+#      |                                                                |
+# XXXX |                                                                | XXXX
+#      |                                                                |
+#      |                                                                |
+#      +----------------------------------------------------------------+
+#
+#          XXXX  XXXX  XXXX  XXXX  XXXX  XXXX  XXXX  XXXX  XXXX  XXXX
+#
+# Note: XXXX represents the screen buttons
+#                                                          CMD   REDRAW
+#
+#                                                          MAIL
+#
+# version 1 note: 
+#	The character string sent by key 'kf26' may be user programmable
+#       to send either \E[16s, or \E[26s.
+#       The character string sent by key 'krfr' may be user programmable
+#       to send either \E[17s, or \E[27s.
+#
+# Depression of the "CMD" key sends    \E!    (kcmd)
+# Depression of the "MAIL" key sends   \E[26s (kf26)
+# "REDRAW" same as "REFRESH" (krfr)
+#
+# "kf" functions adds carriage return to output string if terminal is in
+# 'new line' mode.
+#
+# The following are functions not covered in the table above:
+#
+#       Set keyboard character (SKC): \EPn1;Pn2w
+#                       Pn1= 0 Back Space key
+#                       Pn1= 1 Break key
+#                       Pn2=   Program char (hex)
+#
+#       Screen Definition (SDF): \E[Pn1;Pn2;Pn3;Pn4;Pn5t
+#                       Pn1=     Window number (1-39)
+#                       Pn2-Pn5= Y;X;Y;X coordinates
+#
+#       Screen Selection (SSL): \E[Pnu
+#                       Pn= Window number
+#
+#       Set Terminal Modes (SM): \E[Pnh
+#                       Pn= 3 Graphics mode
+#                       Pn= > Cursor blink
+#                       Pn= < Enter new line mode
+#                       Pn= = Enter reverse insert/replace mode
+#                       Pn= ? Enter no scroll mode
+#
+#       Reset Terminal Mode (RM): \E[Pnl
+#                       Pn= 3 Exit graphics mode
+#                       Pn= > Exit cursor blink
+#                       Pn= < Exit new line mode
+#                       Pn= = Exit reverse insert/replace mode
+#                       Pn= ? Exit no scroll mode
+#
+#       Screen Status Report (SSR): \E[Pnp
+#                       Pn= 0 Request current window number
+#                       Pn= 1 Request current window dimensions
+#
+#       Device Status Report (DSR): \E[6n    Request cursor position
+#
+#       Call Status Report (CSR): \E[Pnv
+#                       Pn= 0 Call failed
+#                       Pn= 1 Call successful
+#
+#       Transparent Button String (TBS): \E[Pn1;Pn2;Pn3;{string
+#                       Pn1= Button number to be loaded
+#                       Pn2= Character count of "string"
+#                       Pn3= Key mode being loaded:
+#                               0= Unshifted
+#                               1= Shifted
+#                               2= Control
+#                       String= Text string (15 chars max)
+#
+#       Screen Number Report (SNR): \E[Pnp
+#                       Pn= Screen number
+#
+#       Screen Dimension Report (SDR): \E[Pn1;Pn2r
+#                       Pn1= Number of rows available in window
+#                       Pn2= Number of columns available in window
+#
+#       Cursor Position Report (CPR): \E[Pn1;Pn2R
+#                       Pn1= "Y" Position of cursor
+#                       Pn2= "X" Position of cursor
+#
+#       Request Answer Back (RAB): \E[c
+#
+#       Answer Back Response (ABR): \E[?;*;30;VSV
+#                       *=  0 No printer available
+#                       *=  2 Printer available
+#                       V=  Software version number
+#                       SV= Software sub version number
+#	(printer-available field not documented in v1)
+#
+#       Screen Alignment Aid: \En
+#
+#       Bell (lower pitch): \E[x
+#
+#       Dial Phone Number: \EPdstring\
+#                       string= Phone number to be dialed
+#
+#       Set Phone Labels: \EPpstring\
+#                       string= Label for phone buttons
+#
+#       Set Clock: \EPchour;minute;second\
+#
+#       Position Clock: \EPsY;X\
+#                       Y= "Y" coordinate
+#                       X= "X" coordinate
+#
+#       Delete Clock: \Epr\
+#
+#       Programming The Function Buttons: \EPfPn;string\
+#                       Pn= Button number (00-06, 18-24)
+#                                         (kf00-kf06, kf18-kf24)
+#                       string= Text to sent on button depression
+#
+# The following in version 2 only:
+#
+#       Request For Local Directory Data: \EPp12;\
+#
+#       Local Directory Data to host: \EPp11;LOCAL...DIRECTORY...DATA\
+#
+#	Request for Local Directory Data in print format: \EPp13;\
+#
+#	Enable 'Prt on Line' mode: \022 (DC2)
+#
+#	Disable 'Prt on Line' mode: \024 (DC4)
+#
+
+# 05-Aug-86:
+# The following Terminfo entry describes functions which are supported by
+# the AT&T 5430/pt505 terminal software version 2 and later.
+att505|pt505|att5430|gs5430|AT&T Personal Terminal 505 or 5430 GETSET terminal:\
+	:am:xo:\
+	:co#80:it#8:li#24:\
+	:&2=\E[27s:@4=\E\041:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:\
+	:DO=\E[%dB:F8=\E[18s:F9=\E[19s:FA=\E[20s:FB=\E[21s:\
+	:FC=\E[22s:FD=\E[23s:FE=\E24s:FG=\E26s:LE=\E[%dD:\
+	:RA=\E[11;1j:RI=\E[%dC:SA=\E[11;0j:UP=\E[%dA:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=\E[10m:al=\E[L:as=\E[11m:bl=^G:cb=\E2K:cd=\E[0J:\
+	:ce=\E[0K:cl=\E[2J\E[H:cm=\E[%d;%dH:cr=^M:dc=\E[P:dl=\E[M:\
+	:do=\E[B:ei=\E[4l:ho=\E[H:\
+	:i1=\EPr\E[0u\E[2J\E[0;0H\E[m\E[3l\E[<l\E[4l\E[>l\E[=l\E[?l:\
+	:im=\E[4h:k0=\E[00s:k1=\E[01s:k2=\E[02s:k3=\E[03s:\
+	:k4=\E[04s:k5=\E[05s:k6=\E[06s:kb=^H:kd=\E[B:kl=\E[D:\
+	:kr=\E[C:ku=\E[A:le=\E[D:mb=\E[5m:md=\E[1m:me=\E[m:\
+	:mr=\E[7m:nd=\E[C:pf=\E[4i:po=\E[5i:r1=\Ec:rc=\E8:sc=\E7:\
+	:se=\E[m:sf=^J:so=\E[1m:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:\
+	:ve=\E[>l:vs=\E[>h:
+
+# The following Terminfo entry describes functions which are supported by
+# the AT&T 5430/pt505 terminal software version 1.
+att505-24|pt505-24|gs5430-24|AT&T PT505 or 5430 GETSET version 1 24 lines:\
+	:li#24:\
+	:RA@:SA@:pf@:po@:rc@:sc@:tc=att505:
+tt505-22|pt505-22|gs5430-22|AT&T PT505 or 5430 GETSET version 1 22 lines:\
+	:li#22:tc=att505:
+
+#### Ampex (Dialogue)
+#
+# Yes, these are the same people who are better-known for making audio- and
+# videotape.  I'm told they are located in Redwood City, CA.
+#
+
+# From: <cbosg!ucbvax!SRC:george> Fri Sep 11 22:38:32 1981
+# (ampex80: some capabilities merged in from SCO's entry -- esr)
+ampex80|a80|d80|dialogue|dialogue80|ampex dialogue 80:\
+	:am:bs:bw:ul:\
+	:co#80:it#8:li#24:\
+	:al=\EE:bl=^G:bt=\EI:cd=\Ey:ce=\Et:cl=\E*:cm=\E=%+ %+ :\
+	:cr=^M:ct=\E3:dc=\EW:dl=\ER:do=^J:ei=:ic=\EQ:im=:is=\EA:le=^H:\
+	:nd=^L:se=\Ek:sf=^J:so=\Ej:st=\E1:ta=^I:ue=\Em:up=^K:us=\El:
+# This entry was from somebody anonymous, Tue Aug  9 20:11:37 1983, who wrote:
+ampex175|ampex d175:\
+	:am:\
+	:co#80:li#24:\
+	:al=\EE:bl=^G:cd=\Ey:ce=\Et:cl=\E+:cm=\E=%+ %+ :cr=^M:\
+	:dc=\EW:dl=\ER:do=^J:ei=:ho=^^:ic=\EQ:im=:is=\EX\EA\EF:\
+	:kA=\EE:kD=\EW:kI=\EQ:kL=\ER:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:\
+	:le=^H:ll=^^^K:nd=^L:se=\Ek:sf=^J:so=\Ej:te=\EF:ti=\EN:\
+	:ue=\Em:up=^K:us=\El:
+# No backspace key in the main QWERTY cluster. Fortunately, it has a
+# NEWLINE/PAGE key just above RETURN that sends a strange single-character
+# code.  Given a suitable Unix (one that lets you set an echo-erase-as-BS-SP-BS
+# mode), this key can be used as the erase key; I find I like this. Because
+# some people and some systems may not, there is another termcap ("ampex175")
+# that suppresses this little eccentricity by omitting the relevant capability.
+ampex175-b|ampex d175 using left arrow for erase:\
+	:kb=^_:\
+	:tc=ampex175:
+# From: Richard Bascove <atd!dsd!rcb@ucbvax.berkeley.edu>
+# (ampex210: removed obsolete ":kn#10:" -- esr)
+ampex210|a210|ampex a210:\
+	:am:bs:hs:xn:\
+	:co#80:it#8:li#24:sg#1:\
+	:al=\EE:bt=\EI:cd=\Ey:ce=\Et:cl=\E*:cm=\E=%+ %+ :dc=\EW:\
+	:dl=\ER:ei=:fs=\E.2:ho=^^:ic=\EQ:if=/usr/share/tabset/std:\
+	:im=:is=\EC\Eu\E'\E(\El\EA\E%\E{\E.2\EG0\Ed\En:\
+	:k0=^A0\r:k1=^A1\r:k2=^A2\r:k3=^A3\r:k4=^A4\r:k5=^A5\r:\
+	:k6=^A6\r:k7=^A7\r:k8=^A8\r:k9=^A9\r:kd=^V:kh=^^:kl=^H:\
+	:kr=^L:ku=^K:le=^H:mk@:nd=^L:ta=^I:ts=\E.0\Eg\E}\Ef:up=^K:\
+	:vb=\EU\EX\EU\EX\EU\EX\EU\EX:\
+	:tc=adm+sgr:
+# (ampex219: I added <rmam>/<smam> based on the init string, added :vs:
+# from ampex219w, added :ve:=\E[?3l, irresistibly suggested by :vs:,
+# and moved the padding to be *after* the caps -- esr)
+ampex219|ampex-219|amp219|Ampex with Automargins:\
+	:hs:xn:\
+	:co#80:it#8:li#24:\
+	:RA=\E[?7l:SA=\E[?7h:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:cs=%i\E[%2;%2r:\
+	:do=\E[B:ho=\E[H:\
+	:is=\E>\E[?1l\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:k0=\E[21~:\
+	:k1=\E[7~:k2=\E[8~:k3=\E[9~:k4=\E[10~:k5=\E[11~:k6=\E[17~:\
+	:k7=\E[18~:k8=\E[19~:k9=\E[20~:kd=\E[B:ke=\E>:kh=\E[H:\
+	:kl=\E[D:kr=\E[C:ks=\E=:ku=\E[A:le=^H:mb=\E[5m:md=\E[1m:\
+	:me=\E[m:mh=\E[1m:mr=\E[7m:nd=\E[C:se=\E[m:sf=^J:so=\E[7m:\
+	:sr=\EM:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:ve=\E[?3l:vs=\E[?3h:
+ampex219w|ampex-219w|amp219w|Ampex 132 cols:\
+	:co#132:li#24:\
+	:bl=^G:cr=^M:do=^J:is=\E>\E[?3h\E[?4l\E[?5l\E[?7h\E[?8h:\
+	:sf=^J:\
+	:tc=ampex219:
+# (ampex232: removed :if=/usr/share/tabset/ampex:, no file and no :st: --esr) 
+ampex232|ampex-232|Ampex Model 232:\
+	:am:\
+	:co#80:li#24:sg#1:\
+	:al=5*\EE:bt=\EI:cd=\EY:ce=\ET:cl=\E+:cm=\E=%+ %+ :dc=\EW:\
+	:dl=5*\ER:do=^V:ei=:ic=\EQ:im=:is=\Eg\El:k0=^A@\r:k1=^AA\r:\
+	:k2=^AB\r:k3=^AC\r:k4=^AD\r:k5=^AE\r:k6=^AF\r:k7=^AG\r:\
+	:k8=^AH\r:k9=^AI\r:kb=^H:kd=^V:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:\
+	:mk@:nd=^L:ta=^I:up=^K:vb=\Eb\Ed:ve=\E.4:vi=\E.0:\
+	:tc=adm+sgr:
+# (ampex: removed :if=/usr/share/tabset/amp-132:, no file and no :st: -- esr) 
+ampex232w|Ampex Model 232 / 132 columns:\
+	:co#132:li#24:\
+	:is=\E\034Eg\El:tc=ampex232:
+
+#### Ann Arbor (aa)
+#
+# Ann Arbor made dream terminals for hackers -- large screen sizes and huge
+# numbers of function keys.  At least some used monitors in portrait mode,
+# allowing up to 76-character screen heights!  They were reachable at:
+#
+#	Ann Arbor Terminals
+#	6175 Jackson Road
+#	Ann Arbor, MI 48103
+#	(313)-663-8000
+#
+# But in 1996 the phone number reaches some kitschy retail shop, and Ann Arbor
+# can't be found on the Web; I fear they're long dead.  R.I.P.
+#
+
+
+# Originally from Mike O'Brien@Rand and Howard Katseff at Bell Labs.
+# Highly modified 6/22 by Mike O'Brien.
+# split out into several for the various screen sizes by dave-yost@rand
+# Modifications made 3/82 by Mark Horton
+# Modified by Tom Quarles at UCB for greater efficiency and more diversity
+# status line moved to top of screen, :vb: removed 5/82
+# Some unknown person at SCO then hacked the init strings to make them more
+# efficient.
+#
+# assumes the following setup:
+#   A menu: 0000 1010  0001 0000
+#   B menu: 9600  0100 1000  0000 0000  1000 0000  17  19
+#   C menu: 56   66   0    0    9600  0110 1100
+#   D menu: 0110 1001   1   0
+#
+#	Briefly, the settings are for the following modes:
+#	   (values are for bit set/clear with * indicating our preference
+#	    and the value used to test these termcaps)
+#	Note that many of these settings are irrelevent to the terminfo
+#	and are just set to the default mode of the terminal as shipped
+#	by the factory.
+#
+# A menu: 0000 1010  0001 0000
+#	Block/underline cursor*
+#	blinking/nonblinking cursor*
+#	key click/no key click*
+#	bell/no bell at column 72*
+#
+#	key pad is cursor control*/key pad is numeric
+#	return and line feed/return for :cr: key *
+#	repeat after .5 sec*/no repeat
+#	repeat at 25/15 chars per sec. *
+#
+#	hold data until pause pressed/process data unless pause pressed*
+#	slow scroll/no slow scroll*
+#	Hold in area/don't hold in area*
+#	functions keys have default*/function keys disabled on powerup
+#
+#	show/don't show position of cursor during page transmit*
+#	unused
+#	unused
+#	unused
+#
+# B menu: 9600  0100 1000  0000 0000  1000 0000  17  19
+#	Baud rate (9600*)
+#
+#	2 bits of parity - 00=odd,01=even*,10=space,11=mark
+#	1 stop bit*/2 stop bits
+#	parity error detection off*/on
+#
+#	keyboard local/on line*
+#	half/full duplex*
+#	disable/do not disable keyboard after data transmission*
+#
+#	transmit entire page/stop transmission at cursor*
+#	transfer/do not transfer protected characters*
+#	transmit all characters/transmit only selected characters*
+#	transmit all selected areas/transmit only 1 selected area*
+#
+#	transmit/do not transmit line separators to host*
+#	transmit/do not transmit page tab stops tabs to host*
+#	transmit/do not transmit column tab stop tabs to host*
+#	transmit/do not transmit graphics control (underline,inverse..)*
+#
+#	enable*/disable auto XON/XOFF control
+#	require/do not require receipt of a DC1 from host after each LF*
+#	pause key acts as a meta key/pause key is pause*
+#	unused
+#
+#	unused
+#	unused
+#	unused
+#	unused
+#
+#	XON character (17*)
+#	XOFF character (19*)
+#
+# C menu: 56   66   0    0    9600  0110 1100
+#	number of lines to print data on (printer) (56*)
+#
+#	number of lines on a sheet of paper (printer) (66*)
+#
+#	left margin (printer) (0*)
+#
+#	number of pad chars on new line to printer (0*)
+#
+#	printer baud rate (9600*)
+#
+#	printer parity: 00=odd,01=even*,10=space,11=mark
+#	printer stop bits: 2*/1
+#	print/do not print guarded areas*
+#
+#	new line is: 01=LF,10=CR,11=CRLF*
+#	unused
+#	unused
+#
+# D menu: 0110 1001   1   0
+#	LF is newline/LF is down one line, same column*
+#	wrap to preceding line if move left from col 1*/don't wrap
+#	wrap to next line if move right from col 80*/don't wrap
+#	backspace is/is not destructive*
+#
+#	display*/ignore DEL character
+#	display will not/will scroll*
+#	page/column tab stops*
+#	erase everything*/erase unprotected only
+#
+#	editing extent: 0=display,1=line*,2=field,3=area
+#
+#	unused
+#
+
+annarbor4080|aa4080|ann arbor 4080:\
+	:am:bs:\
+	:co#80:li#40:\
+	:bl=^G:cl=\014:\
+	:..cm=\017%p2%{10}%/%{16}%*%p2%{10}%m%+%c%p1%?%p1%{19}%>%t%{12}%+%;%{64}%+%c:\
+	:cr=^M:ct=^^P^P:do=^J:ho=^K:kb=^^:kd=^J:kh=^K:kl=^H:kr=^_:\
+	:ku=^N:le=^H:nd=^_:sf=^J:st=^]^P1:ta=^I:up=^N:
+
+# Strange Ann Arbor terminal from BRL
+aas1901|Ann Arbor K4080 w/S1901 mod:\
+	:am:\
+	:co#80:li#40:\
+	:bl=^G:cl=^L:cr=^M:do=^J:ho=^K:kb=^H:kd=^J:kl=^H:le=^H:\
+	:ll=^O\0c:nd=^_:nw=^M^J:sf=^J:ta=^I:up=^N:
+
+# If you're using the GNU termcap library, add
+#	:cS=\E[%p1%d;%p2%d;%p3%d;%p4%dp:
+# to these capabilities.  This is the nonstandard GNU termcap scrolling
+# capability, arguments are:
+#   1. Total number of lines on the screen.
+#   2. Number of lines above desired scroll region.
+#   3. Number of lines below (outside of) desired scroll region.
+#   4. Total number of lines on the screen, the same as the first parameter.
+# The generic Ann Arbor entry is the only one that uses this.
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+aaa+unk|aaa-unk|ann arbor ambassador (internal - don't use this directly):\
+	:am:bs:km:mi:xo:\
+	:co#80:it#8:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:al=\E[L:bl=^G:bt=\E[Z:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:ct=\E[2g:dc=\E[P:dl=\E[M:do=^K:ei=:ho=\E[H:\
+	:i1=\E[m\E7\E[H\E9\E8:i2=\E[1Q\E[>20;30l\EP`+x~M\E\:\
+	:ic=\E[@:im=:k1=\EOA:k2=\EOB:k3=\EOC:k4=\EOD:k5=\EOE:\
+	:k6=\EOF:k7=\EOG:k8=\EOH:k9=\EOI:kD=\E[P:kI=\E[@:kb=^H:\
+	:kd=\E[B:\
+	:ke=\EP`>y~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\E\:\
+	:kh=\E[H:kl=\E[D:kr=\E[C:\
+	:ks=\EP`>z~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\E\:\
+	:ku=\E[A:le=^H:mb=\E[5m:md=\E[1m:me=\E[m:mm=\E[>52h:\
+	:mo=\E[>52l:mr=\E[7m:nd=\E[C:rc=\E8:sc=\E7:se=\E[m:sf=^K:\
+	:so=\E[7m:st=\EH:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:
+
+aaa+rv|ann arbor ambassador in reverse video:\
+	:i1=\E[7m\E7\E[H\E9\E8:mb=\E[5;7m:md=\E[1;7m:\
+	:me=\E[7m\016:mk=\E[7;8m:mr=\E[m:r1=\E[H\E[7m\E[J:\
+	:..sa=\E[%?%p1%p3%|%!%t7;%;%?%p2%t4;%;%?%p4%t5;%;%?%p6%t1;%;%?%p7%t8;%;m:\
+	:se=\E[7m:so=\E[m:ue=\E[7m:us=\E[4;7m:
+# Ambassador with the DEC option, for partial vt100 compatibility.
+aaa+dec|ann arbor ambassador in dec vt100 mode:\
+	:ac=aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}:\
+	:ae=^N:as=^O:cs=\E[%i%d;%dr:eA=\E(0:\
+	:..sa=\E[%?%p1%p3%|%!%t7;%;%?%p2%t4;%;%?%p4%t5;%;%?%p6%t1;%;%?%p7%t8;%;m%?%p9%t\017%e\016%;:
+aaa-18|ann arbor ambassador/18 lines:\
+	:li#18:\
+	:is=\E7\E[60;0;0;18p\E8:te=\E[60;0;0;18p\E[60;1H\E[K:\
+	:ti=\E[18;0;0;18p:\
+	:tc=aaa+unk:
+aaa-18-rv|ann arbor ambassador/18 lines+reverse video:\
+	:tc=aaa+rv:tc=aaa-18:
+aaa-20|ann arbor ambassador/20 lines:\
+	:li#20:\
+	:is=\E7\E[60;0;0;20p\E8:te=\E[60;0;0;20p\E[60;1H\E[K:\
+	:ti=\E[20;0;0;20p:\
+	:tc=aaa+unk:
+aaa-22|ann arbor ambassador/22 lines:\
+	:li#22:\
+	:is=\E7\E[60;0;0;22p\E8:te=\E[60;0;0;22p\E[60;1H\E[K:\
+	:ti=\E[22;0;0;22p:\
+	:tc=aaa+unk:
+aaa-24|ann arbor ambassador/24 lines:\
+	:li#24:\
+	:is=\E7\E[60;0;0;24p\E8:te=\E[60;0;0;24p\E[60;1H\E[K:\
+	:ti=\E[24;0;0;24p:\
+	:tc=aaa+unk:
+aaa-24-rv|ann arbor ambassador/24 lines+reverse video:\
+	:tc=aaa+rv:tc=aaa-24:
+aaa-26|ann arbor ambassador/26 lines:\
+	:li#26:\
+	:is=\E7\E[60;0;0;26p\E8:te=\E[60;0;0;26p\E[26;1H\E[K:\
+	:ti=\E[H\E[J\E[26;0;0;26p:\
+	:tc=aaa+unk:
+aaa-28|ann arbor ambassador/28 lines:\
+	:li#28:\
+	:is=\E7\E[60;0;0;28p\E8:te=\E[60;0;0;28p\E[28;1H\E[K:\
+	:ti=\E[H\E[J\E[28;0;0;28p:\
+	:tc=aaa+unk:
+aaa-30-s|aaa-s|ann arbor ambassador/30 lines w/status:\
+	:es:hs:\
+	:li#29:\
+	:ds=\E7\E[60;0;0;30p\E[1;1H\E[K\E[H\E8\r\n\E[K:\
+	:fs=\E[>51l:is=\r\n\E[A\E7\E[60;1;0;30p\E8:\
+	:te=\E[60;1;0;30p\E[29;1H\E[K:\
+	:ti=\E[H\E[J\E[30;1;0;30p\E[30;1H\E[K:\
+	:ts=\E[>51h\E[1;%p1%dH\E[2K:tc=aaa+unk:
+aaa-30-s-rv|aaa-s-rv|ann arbor ambassador/30 lines+status+reverse video:\
+	:tc=aaa+rv:tc=aaa-30-s:
+aaa-s-ctxt|aaa-30-s-ctxt|ann arbor ambassador/30 lines+status+save context:\
+	:te=\E[60;1;0;30p\E[59;1H\E[K:\
+	:ti=\E[30;1H\E[K\E[30;1;0;30p:tc=aaa-30-s:
+aaa-s-rv-ctxt|aaa-30-s-rv-ct|ann arbor ambassador/30 lines+status+save context+reverse video:\
+	:te=\E[60;1;0;30p\E[59;1H\E[K:\
+	:ti=\E[30;1H\E[K\E[30;1;0;30p:tc=aaa-30-s-rv:
+aaa|aaa-30|ambas|ambassador|ann arbor ambassador/30 lines:\
+	:li#30:\
+	:is=\E7\E[60;0;0;30p\E8:te=\E[60;0;0;30p\E[30;1H\E[K:\
+	:ti=\E[H\E[J\E[30;0;0;30p:\
+	:tc=aaa+unk:
+aaa-30-rv|aaa-rv|ann arbor ambassador/30 lines in reverse video:\
+	:tc=aaa+rv:tc=aaa-30:
+aaa-30-ctxt|aaa-ctxt|ann arbor ambassador/30 lines; saving context:\
+	:te=\E[60;0;0;30p\E[60;1H\E[K:ti=\E[30;0;0;30p:\
+	:tc=aaa-30:
+aaa-30-rv-ctxt|aaa-rv-ctxt|ann arbor ambassador/30 lines reverse video; saving context:\
+	:te=\E[60;0;0;30p\E[60;1H\E[K:ti=\E[30;0;0;30p:\
+	:tc=aaa+rv:tc=aaa-30:
+aaa-36|ann arbor ambassador/36 lines:\
+	:li#36:\
+	:is=\E7\E[60;0;0;36p\E8:te=\E[60;0;0;36p\E[36;1H\E[K:\
+	:ti=\E[H\E[J\E[36;0;0;36p:\
+	:tc=aaa+unk:
+aaa-36-rv|ann arbor ambassador/36 lines+reverse video:\
+	:tc=aaa+rv:tc=aaa-36:
+aaa-40|ann arbor ambassador/40 lines:\
+	:li#40:\
+	:is=\E7\E[60;0;0;40p\E8:te=\E[60;0;0;40p\E[40;1H\E[K:\
+	:ti=\E[H\E[J\E[40;0;0;40p:\
+	:tc=aaa+unk:
+aaa-40-rv|ann arbor ambassador/40 lines+reverse video:\
+	:tc=aaa+rv:tc=aaa-40:
+aaa-48|ann arbor ambassador/48 lines:\
+	:li#48:\
+	:is=\E7\E[60;0;0;48p\E8:te=\E[60;0;0;48p\E[48;1H\E[K:\
+	:ti=\E[H\E[J\E[48;0;0;48p:\
+	:tc=aaa+unk:
+aaa-48-rv|ann arbor ambassador/48 lines+reverse video:\
+	:tc=aaa+rv:tc=aaa-48:
+aaa-60-s|ann arbor ambassador/59 lines+status:\
+	:es:hs:\
+	:li#59:\
+	:ds=\E7\E[60;0;0;60p\E[1;1H\E[K\E[H\E8\r\n\E[K:\
+	:fs=\E[>51l:is=\r\n\E[A\E7\E[60;1;0;60p\E8:\
+	:ts=\E[>51h\E[1;%p1%dH\E[2K:tc=aaa+unk:
+aaa-60-s-rv|ann arbor ambassador/59 lines+status+reverse video:\
+	:tc=aaa+rv:tc=aaa-60-s:
+aaa-60-dec-rv|ann arbor ambassador/dec mode+59 lines+status+rev video:\
+	:tc=aaa+dec:tc=aaa+rv:tc=aaa-60-s:
+aaa-60|ann arbor ambassador/60 lines:\
+	:li#60:\
+	:is=\E7\E[60;0;0;60p\E[1Q\E[m\E[>20;30l\E8:tc=aaa+unk:
+aaa-60-rv|ann arbor ambassador/60 lines+reverse video:\
+	:tc=aaa+rv:tc=aaa-60:
+aaa-db|ann arbor ambassador 30/destructive backspace:\
+	:bs@:\
+	:i2=\E[1Q\E[m\E[>20l\E[>30h:le=\E[D:tc=aaa-30:
+
+guru|guru-33|guru+unk|ann arbor guru/33 lines 80 cols:\
+	:li#33:\
+	:i2=\E[>59l:is=\E7\E[255;0;0;33;80;80p\E8\E[J:\
+	:te=\E[255p\E[255;1H\E[K:ti=\E[33p:vb=\E[>59h\E[>59l:\
+	:tc=aaa+unk:
+guru+rv|guru changes for reverse video:\
+	:i2=\E[>59h:vb=\E[>59l\E[>59h:
+guru-rv|guru-33-rv|ann arbor guru/33 lines+reverse video:\
+	:tc=guru+rv:tc=guru-33:
+guru+s|guru status line:\
+	:es:hs:\
+	:ds=\E7\E[;0p\E[1;1H\E[K\E[H\E8\r\n\E[K:fs=\E[>51l:\
+	:te=\E[255;1p\E[255;1H\E[K:ti=:\
+	:ts=\E[>51h\E[1;%p1%dH\E[2K:
+guru-nctxt|guru with no saved context:\
+	:ti=\E[H\E[J\E[33p\E[255;1H\E[K:tc=guru:
+guru-s|guru-33-s|ann arbor guru/33 lines+status:\
+	:li#32:\
+	:is=\r\n\E[A\E7\E[255;1;0;33;80;80p\E8\E[J:\
+	:ti=\E[33;1p\E[255;1H\E[K:tc=guru+s:\
+	:tc=guru+unk:
+guru-24|ann arbor guru 24 lines:\
+	:co#80:li#24:\
+	:is=\E7\E[255;0;0;24;80;80p\E8\E[J:ti=\E[24p:tc=guru+unk:
+guru-44|ann arbor guru 44 lines:\
+	:co#97:li#44:\
+	:is=\E7\E[255;0;0;44;97;100p\E8\E[J:ti=\E[44p:tc=guru+unk:
+guru-44-s|ann arbor guru/44 lines+status:\
+	:li#43:\
+	:is=\r\n\E[A\E7\E[255;1;0;44;80;80p\E8\E[J:\
+	:ti=\E[44;1p\E[255;1H\E[K:tc=guru+s:\
+	:tc=guru+unk:
+guru-76|guru with 76 lines by 89 cols:\
+	:co#89:li#76:\
+	:is=\E7\E[255;0;0;76;89;100p\E8\E[J:ti=\E[76p:tc=guru+unk:
+guru-76-s|ann arbor guru/76 lines+status:\
+	:co#89:li#75:\
+	:is=\r\n\E[A\E7\E[255;1;0;76;89;100p\E8\E[J:\
+	:ti=\E[76;1p\E[255;1H\E[K:tc=guru+s:\
+	:tc=guru+unk:
+guru-76-lp|guru-lp|guru with page bigger than line printer:\
+	:co#134:li#76:\
+	:is=\E7\E[255;0;0;76;134;134p\E8\E[J:ti=\E[76p:tc=guru+unk:
+guru-76-w|guru 76 lines by 178 cols:\
+	:co#178:li#76:\
+	:is=\E7\E[255;0;0;76;178;178p\E8\E[J:ti=\E[76p:tc=guru+unk:
+guru-76-w-s|ann arbor guru/76 lines+status+wide:\
+	:co#178:li#75:\
+	:is=\r\n\E[A\E7\E[255;1;0;76;178;178p\E8\E[J:\
+	:ti=\E[76;1p\E[255;1H\E[K:\
+	:tc=guru+s:tc=guru+unk:
+guru-76-wm|guru 76 lines by 178 cols with 255 cols memory:\
+	:co#178:li#76:\
+	:is=\E7\E[255;0;0;76;178;255p\E8\E[J:ti=\E[76p:tc=guru+unk:
+aaa-rv-unk|ann arbor unknown type:\
+	:Nl#0:lh#0:lw#0:\
+	:ho=\E[H:i1=\E[7m\E7\E[H\E9\E8:mb=\E[5;7m:md=\E[1;7m:\
+	:me=\E[7m:mk=\E[7;8m:mr=\E[m:r1=\E[H\E[7m\E[J:\
+	:..sa=\E[%?%p1%!%t7;%;%?%p2%t4;%;%?%p3%t7;%;%?%p4%t5;%;%?%p6%t1;%;%?%p7%t8;%;m:\
+	:se=\E[7m:so=\E[m:ue=\E[7m:us=\E[4;7m:
+
+#### Applied Digital Data Systems (adds)
+#
+# ADDS itself is long gone.  ADDS was bought by NCR, and the same group made
+# ADDS and NCR terminals.  When AT&T and NCR merged, the engineering for
+# terminals was merged again.  Then AT&T sold the terminal business to
+# SunRiver, which later changed its  name to Boundless Technologies.  The
+# engineers from Teletype, AT&T terminals, ADDS, and NCR (who are still there
+# as of early 1995) are at:
+#
+#	Boundless Technologies
+#	100 Marcus Boulevard
+#	Hauppauge, NY 11788-3762
+#	Vox: (800)-231-5445
+#	Fax: (516)-342-7378
+#	Web: http://boundless.com
+#
+# Their voice mail used to describe the place as "SunRiver (formerly ADDS)". 
+# In 1995 Boundless acquired DEC's terminals business.  
+#
+
+# Regent: lowest common denominator, works on all regents.
+# (regent: renamed ":bc:" to ":le:" -- esr)
+regent|Adds Regent Series:\
+	:am:bs:\
+	:co#80:li#24:\
+	:bl=^G:cl=^L:cr=^M:do=^J:ho=\EY  :le=^U:ll=^A:nd=^F:sf=^J:\
+	:up=^Z:
+# Regent 100 has a bug where if computer sends escape when user is holding
+# down shift key it gets confused, so we avoid escape.
+regent100|Adds Regent 100:\
+	:sg#1:\
+	:bl=^G:cm=\013%+ %B\020%.:k0=^B1\r:k1=^B2\r:k2=^B3\r:\
+	:k3=^B4\r:k4=^B5\r:k5=^B6\r:k6=^B7\r:k7=^B8\r:l0=F1:l1=F2:\
+	:l2=F3:l3=F4:l4=F5:l5=F6:l6=F7:l7=F8:me=\E0@:se=\E0@:so=\E0P:\
+	:ue=\E0@:us=\E0`:\
+	:tc=regent:
+regent20|Adds Regent 20:\
+	:bl=^G:cd=\Ek:ce=\EK:cm=\EY%+ %+ :tc=regent:
+regent25|Adds Regent 25:\
+	:bl=^G:kd=^J:kh=^A:kl=^U:kr=^F:ku=^Z:tc=regent20:
+regent40|Adds Regent 40:\
+	:sg#1:\
+	:al=\EM:bl=^G:dl=\El:k0=^B1\r:k1=^B2\r:k2=^B3\r:k3=^B4\r:\
+	:k4=^B5\r:k5=^B6\r:k6=^B7\r:k7=^B8\r:l0=F1:l1=F2:l2=F3:\
+	:l3=F4:l4=F5:l5=F6:l6=F7:l7=F8:me=\E0@:se=\E0@:so=\E0P:\
+	:ue=\E0@:us=\E0`:\
+	:tc=regent25:
+regent40+|Adds Regent 40+:\
+	:is=\EB:tc=regent40:
+regent60|regent200|Adds Regent 60:\
+	:dc=\EE:ei=\EF:im=\EF:is=\EV\EB:kD=\EE:kI=\EF:kM=\EF:\
+	:se=\ER\E0@\EV:so=\ER\E0P\EV:\
+	:tc=regent40+:
+# From: <edward@onyx.berkeley.edu> Thu Jul  9 09:27:33 1981
+# (viewpoint: added :kr:, function key, and :dl: capabilities -- esr)
+viewpoint|addsviewpoint|adds viewpoint:\
+	:am:bs:\
+	:co#80:li#24:\
+	:bl=^G:cd=\Ek:ce=\EK:cl=^L:cm=\EY%+ %+ :cr=^M:dl=\El:do=^J:\
+	:is=\017\E0`:k0=^B1:k2=^B2:k3=^B\041:k4=^B":k5=^B#:kd=^J:\
+	:kh=^A:kl=^U:kr=^F:ku=^Z:le=^H:ll=^A:me=^O:nd=^F:se=^O:sf=^J:\
+	:so=^N:ue=^O:up=^Z:us=^N:ve=\017\E0`:vs=\017\E0P:
+# Some viewpoints have bad ROMs that foo up on ^O
+screwpoint|adds viewpoint with ^O bug:\
+	:se@:so@:ue@:us@:vs@:tc=viewpoint:
+
+# From: Jay S. Rouman <jsr@dexter.mi.org> 5 Jul 92
+# The :vi:/:ve:/:sa:/:me: strings were added by ESR from specs.  
+# Theory; the vp3a+ wants \E0%c to set highlights, where normal=01000000,
+# underline=01100000, rev=01010000, blink=01000010,dim=01000001,
+# invis=01000100 and %c is the logical or of desired attributes.
+# There is also a `tag bit' enabling attributes, set by \E) and unset by \E(.
+vp3a+|viewpoint3a+|adds viewpoint 3a+:\
+	:am:bw:\
+	:co#80:it#8:li#24:\
+	:cd=\EY:ce=\ET:cl=\E*:cm=\E=%+ %+ :cr=^M:do=^J:ho=^^:kb=^H:\
+	:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:me=\E(:nd=^L:nw=^M^J:\
+	:..sa=\E0%{64}%?%p1%tQ%|%;%?%p2%t%{96}%|%;%?%p3%tP%|%;%?%p4%t%{2}%|%;%?%p5%t%{1}%|%;%?%p7%tD%|%;%c\E):\
+	:se=\E(:sf=^J:so=\E0Q\E):ta=^I:up=^K:ve=^X:vi=^W:
+vp60|viewpoint60|addsvp60|adds viewpoint60:\
+	:tc=regent40:
+#
+# adds viewpoint 90 - from cornell
+# Note:  emacs sends ei occasionally to insure the terminal is out of
+#        insert mode. This unfortunately puts the viewpoint90 IN insert
+#        mode.  A hack to get around this is :ic=\EF\s\EF^U:.  (Also,
+#   -    :ei=:im=: must be present in the termcap translation.)
+#   -    :xs: indicates glitch that attributes stick to location
+#   -    :ms: means it's safe to move in standout mode
+#   -    :cl=\EG\Ek:: clears screen and visual attributes without affecting
+#               the status line
+# Function key and label capabilities merged in from SCO.
+vp90|viewpoint90|adds viewpoint 90:\
+	:bs:bw:ms:xs:\
+	:co#80:li#24:\
+	:cd=\Ek:ce=\EK:cl=\EG\Ek:cm=\EY%+ %+ :dc=\EE:dl=\El:do=^J:\
+	:ei=:ho=\EY  :ic=\EF \EF\025:im=:k0=^B1\r:k1=^B2\r:\
+	:k2=^B3\r:k3=^B4\r:k4=^B5\r:k5=^B6\r:k6=^B7\r:k7=^B8\r:\
+	:k8=^B9\r:k9=^B\072\r:k;=^B;\r:kb=^H:kd=^J:kh=^A:kl=^U:\
+	:kr=^F:ku=^Z:l0=F1:l1=F2:l2=F3:l3=F4:l4=F5:l5=F6:l6=F7:l7=F8:\
+	:l8=F9:l9=F10:la=F11:le=^H:ll=^A:me=\ER\E0@\EV:nd=^F:\
+	:se=\ER\E0@\EV:sf=^J:so=\ER\E0Q\EV:ta=^I:ue=\ER\E0@\EV:\
+	:up=^Z:us=\ER\E0`\EV:
+# Note: if return acts weird on a980, check internal switch #2
+# on the top chip on the CONTROL pc board.
+adds980|a980|adds consul 980:\
+	:am:bs:\
+	:co#80:li#24:\
+	:al=\E\016:bl=^G:cl=\014\013@:cm=\013%+@\E\005%2:cr=^M:\
+	:dl=\E\017:do=^J:k0=\E0:k1=\E1:k2=\E2:k3=\E3:k4=\E4:k5=\E5:\
+	:k6=\E6:k7=\E7:k8=\E8:k9=\E9:le=^H:me=^O:nd=\E^E01:se=^O:\
+	:sf=^J:so=^Y^^^N:
+
+# Beehive documentation is undated and marked Preliminary and has no figures
+# so we must have early Superbee2 (Model 600, according to phone conversation
+# with mfr.). It has proved reliable except for some missing padding
+# (notably after \EK and <nl> at bottom of screen).
+# 
+# The key idea is that AEP mode is poison for :cm: & that US's in 
+# the local memory should be avoided like the plague. That means 
+# that the 2048 character local buffer is used as 25 lines of 80 
+# characters, period. No scrolling local memory, folks. It also 
+# appears that we cannot use naked INS LINE feature since it uses
+# US. The sbi fakes :al: with an 80-space insert that may be too 
+# slow at low speeds; also spaces get converted to \040 which is 
+# too long for some programs (not vi).  DEL LINE is ok but slow.
+# 
+# The <nl> string is designed for last line of screen ONLY; cup to 
+# 25th line corrects the motion inherent in scrolling to Page 1.
+# 
+# There is one understood bug. It is that the screen appears to
+# pop to a new (blank) page after a :nw:, or leave a half-line 
+# ellipsis to a quad that is the extra 48 memory locations. The 
+# data received is dumped into memory but not displayed.  Not to 
+# worry if :cm: is being used; the lines not displayed will be, 
+# whenever the cursor is moved up there. Since :cm: is addressed 
+# relative to MEMORY of window, nothing is lost; but beware of 
+# relative cursor motion (:up:,:do:,:nd:,:le:). Recommended,
+# therefore, is setenv MORE -c .
+# 
+# WARNING: Not all features tested.
+# 
+# Timings are assembled from 3 sources. Some timings may reflect 
+# SB2/Model 300 that were used if more conservative.
+# Tested on a Model 600 at 1200 and 9600 bd.
+# 
+# The BACKSPACEkb option is cute. The NEWLINE key, so cleverly 
+# placed on the keyboard and useless because of AEP, is made 
+# into a backspace key. In use ESC must be pressed twice (to send)
+# and sending ^C must be prefixed by ESC to avoid that weird 
+# transmit mode associated with ENTER key.
+# 
+# IF TERMINAL EVER GOES CATATONIC with the cursor buzzing across 
+# the screen, then it has dropped into ENTER mode; hit 
+# RESET--ONLINE--!tset.
+# 
+# As delivered this machine has a FATAL feature that will throw 
+# it into that strange transmit state (SPOW) if the space bar is 
+# hit after a CR is received, but before receiving a LF (or a 
+# few others).
+# 
+# The circuits MUST be modified to eliminate the SPOW latch. 
+# This is done by strapping on chip A46 of the I/O board; cut 
+# the p.c. connection to Pin 5 and strap Pin 5 to Pin 8 of that 
+# chip. This mod has been checked out on a Mod 600 of Superbee II.
+# With this modification absurdly high timings on cr are 
+# unnecessary.
+# 
+# NOTE WELL that the rear panel switch should be set to CR/LF, 
+# not AEP!
+#
+sb1|beehive superbee:\
+	:am:bs:bw:da:db:mi:ul:xb:\
+	:co#80:li#25:sg#1:\
+	:al=\EN\EL\EQ                                                                                \EP \EO\ER\EA:\
+	:bl=^G:bt=\E`:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EF%r%03%03:cr=\r:\
+	:ct=\E3:dc=\EP:dl=\EM:do=^J:ei=\ER:ho=\EH:im=\EQ\EO:\
+	:is=\EE\EX\EZ\EO\Eb\Eg\ER:k0=\E2:k1=\Ep:k2=\Eq:k3=\Er:\
+	:k4=\Es:k5=\Et:k6=\Eu:k7=\Ev:k8=\Ew:k9=\E1:kE=\EK:kI=\EQ\EO:\
+	:kL=\EM:kM=\ER:kS=\EJ:kb=^_:kd=\EB:kh=\EH:kl=\ED:kr=\EC:\
+	:ku=\EA:l0=TAB CLEAR:l9=TAB SET:le=^H:me=\E_3:nd=\EC:\
+	:se=\E_3:sf=^J:so=\E_1:st=\E1:ta=^I:te=:ti=\EO:ue=\E_3:\
+	:up=\EA:us=\E_0:
+sbi|superbee|beehive superbee at Indiana U.:\
+	:xb:\
+	:al=1\EN\EL\EQ \EP \EO\ER\EA:cr=\r:tc=sb1:
+# Alternate (older) description of Superbee - f1=escape, f2=^C.
+# Note: there are at least 3 kinds of superbees in the world.  The sb1
+# holds onto escapes and botches ^C's.  The sb2 is the best of the 3.
+# The sb3 puts garbage on the bottom of the screen when you scroll with
+# the switch in the back set to CRLF instead of AEP.  This description
+# is tested on the sb2 but should work on all with either switch setting.
+# The f1/f2 business is for the sb1 and the :xb: can be taken out for
+# the other two if you want to try to hit that tiny escape key.
+# This description is tricky: being able to use cup depends on there being
+# 2048 bytes of memory and the hairy <nl> string.
+superbee-xsb|beehive super bee:\
+	:am:da:db:xb:\
+	:co#80:it#8:li#25:\
+	:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EF%r%3%3:cr=\r:ct=\E3:dc=\EP:\
+	:dl=\EM:do=^J:ho=\EH:is=\EH\EJ:k1=\Ep:k2=\Eq:k3=\Er:k4=\Es:\
+	:k5=\Et:k6=\Eu:k7=\Ev:k8=\Ew:kd=\EB:kh=\EH:kl=\ED:kr=\EC:\
+	:ku=\EA:le=^H:me=\E_3:nd=\EC:se=\E_3:\
+	:sf=\n\0\0\0\n\0\0\0\EA\EK\0\0\0\ET\ET:so=\E_1:st=\E1:\
+	:ta=^I:up=\EA:ve=^J:
+# This loses on lines > 80 chars long, use at your own risk
+superbeeic|super bee with insert char:\
+	:ei=\ER:ic=:im=\EQ:tc=superbee-xsb:
+sb2|sb3|fixed superbee:\
+	:xb@:tc=superbee:
+
+####  Beehive Medical Electronics
+#
+# Steve Seymour <srseymour@mindspring.com> writes (Wed, 03 Feb 1999):
+# Regarding your question though; Beehive terminals weren't made by Harris.
+# They were made by Beehive Medical Electronics in Utah. They went out of
+# business in the early '80s.
+#
+# (OK, then, I don't know why a couple of these say "harris beehive".)
+#
+
+# Reports are that most of these Beehive entries (except superbee) have not
+# been tested and do not work right.  :se: is a trouble spot.  Be warned.
+
+# (bee: :ic: was empty, which is obviously bogus -- esr)
+beehive|bee|harris beehive:\
+	:am:bs:mi:\
+	:co#80:li#24:\
+	:al=\EL:bt=\E>:cd=\EJ:ce=\EK:cl=\EE:cm=\EF%+ %+ :dc=\EP:\
+	:dl=\EM:do=\EB:ei=\E@:ho=\EH:im=\EQ:kA=\EL:kB=\E>:kC=\EE:\
+	:kD=\EP:kE=\EK:kI=\EQ:kL=\EM:kM=\E@:kb=^H:kd=\EB:kh=\EH:\
+	:kl=\ED:kr=\EC:ku=\EA:le=^H:me=\Ed@:nd=\EC:se=\Ed@:so=\EdP:\
+	:ue=\Ed@:up=\EA:us=\Ed`:
+# set tab is ^F, clear (one) tab is ^V, no way to clear all tabs.
+# good grief - does this entry make :sg:/:ug: when it doesn't have to?
+# look at those spaces in :se:/:so:.  Seems strange to me...
+# (beehive: :if=/usr/share/tabset/beehive: removed, no such file.  If you
+# really care, cook up one using ^F -- esr)
+beehive3|bh3m|beehiveIIIm|harris beehive 3m:\
+	:am:bs:\
+	:co#80:it#8:li#20:\
+	:al=\023:bl=^G:cd=^R:ce=^P:cl=^E^R:cr=^M:dl=\021:do=^J:ho=^E:\
+	:le=^H:ll=^E^K:nd=^L:se= ^_:sf=^J:so=^] :st=^F:ta=^I:up=^K:
+beehive4|bh4|beehive 4:\
+	:am:\
+	:co#80:li#24:\
+	:bl=^G:cd=\EJ:ce=\EK:cl=\EE:cr=^M:do=^J:ho=\EH:le=\ED:nd=\EC:\
+	:sf=^J:up=\EA:
+# There was an early Australian kit-built computer called a "Microbee".
+# It's not clear whether this is for one of those or for a relative
+# of the Beehive.
+microb|microbee|micro bee series:\
+	:am:bs:\
+	:co#80:it#8:li#24:\
+	:bl=^G:cd=\EJ:ce=\EK:cl=\EE:cm=\EF%+ %+ :cr=^M:do=^J:k1=\Ep:\
+	:k2=\Eq:k3=\Er:k4=\Es:k5=\Et:k6=\Eu:k7=\Ev:k8=\Ew:k9=\Ex:\
+	:kd=\EB:kh=\EH:kl=\ED:kr=\EC:ku=\EA:le=^H:me=\Ed@:nd=\EC:\
+	:se=\Ed@:sf=^J:so= \EdP:ta=^I:ue=\Ed@:up=\EA:us=\Ed`:
+
+#### C. Itoh Electronics
+#
+# As of 1995 these people no longer make terminals (they're still in the
+# printer business).  Their terminals were all clones of the DEC VT series.
+# They're located in Orange County, CA.
+#
+
+# CIT 80  - vt-52 emulator, the termcap has been modified to remove
+#           the delay times and do an auto tab set rather than the indirect
+#           file used in vt100.
+cit80|cit-80|citoh 80:\
+	:am:bs:\
+	:co#80:li#24:\
+	:cd=\EJ:ce=\EK:cl=\E[H\EJ:cm=\E[%i%2;%2H:cr=^M:ff=^L:\
+	:is=\E>:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:\
+	:ku=\EOA:le=^H:nd=\E[C:sf=^J:up=\E[A:
+# From: Tim Wood <mtxinu!sybase!tim> Fri Sep 27 09:39:12 PDT 1985
+# (cit101: added <rmam>/<smam> based on init string, merged this with c101 -- esr)
+cit101|citc|C.itoh fast vt100:\
+	:am:bs:xn:\
+	:co#80:li#24:\
+	:RA=\E[?7l:SA=\E[?7h:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:dc=\E[P:dl=\E[M:ei=:ic=\E[@:\
+	:im=:is=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[3g\E[>5g:\
+	:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:\
+	:ku=\EOA:le=^H:me=\E[m:nd=\E[C:se=\E[m:so=\E[7m:ue=\E[m:\
+	:up=\E[A:us=\E[4m:vb=\E[?5h\E[?5l:ve=\E[V\E8:vs=\E7\E[U:
+# CIE Terminals CIT-101e from Geoff Kuenning <callan!geoff> via BRL
+# The following termcap entry was created from the Callan cd100 entry.  The
+# last two lines (with the capabilities in caps) are used by RM-cobol to allow
+# full selection of combinations of reverse video, underline, and blink.
+# (cit101e: removed unknown :f0=\EOp:f1=\EOq:f2=\EOr:f3=\EOs:f4=\EOt:f5=\EOu:\
+# f6=\EOv:f7=\EOw:f8=\EOx:f9=\EOy:AB=\E[0;5m:AL=\E[m:AR=\E[0;7m:AS=\E[0;5;7m:\
+# :NB=\E[0;1;5m:NM=\E[0;1m:NR=\E[0;1;7m:NS=\E[0;1;5;7m: -- esr)
+cit101e|C. Itoh CIT-101e:\
+	:am:bs:mi:ms:pt:\
+	:co#80:it#8:li#24:\
+	:ac=:ae=^O:al=\E[L:as=^N:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%2;%2H:cs=\E[%i%2;%2r:dc=\E[P:dl=\E[M:do=\E[B:\
+	:ei=\E[4l:if=/usr/share/tabset/vt100:im=\E[4h:k0=\EOT:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\EOm:k6=\EOl:k7=\EOM:\
+	:k8=\EOn:kd=\E[B:ke=\E>:kl=\E[D:kr=\E[C:ks=\E=:ku=\E[A:\
+	:nd=\E[C:rc=\E8:sc=\E7:se=\E[m:so=\E[7m:sr=\EM:ue=\E[m:\
+	:up=\E[A:us=\E[4m:ve=:vs=\E[?1l\E[?4l\E[?7h:
+# From: David S. Lawyer, June 1997:
+# The CIT 101-e was made in Japan in 1983-4 and imported by CIE
+# Terminals in Irvine, CA.  It was part of CITOH Electronics.  In the
+# late 1980's CIT Terminals went out of business.
+# There is no need to use the initialization string is=... (by invoking
+# tset or setterm etc.) provided that the terminal has been manually set
+# up (and the setup saved with ^S) to be compatible with this termcap.  To be
+# compatible it should be in ANSI mode (not VT52).   A set-up that
+# works is to set all the manually setable stuff to factory defaults
+# by pressing ^D in set-up mode.  Then increse the brighness with the
+# up-arrow key since the factory default will likely be dim on an old
+# terminal.  Then change any options you want (provided that they are
+# compatible with the termcap).  For my terminal I set: Screen
+# Background: light; Keyclicks: silent; Auto wraparound: on; CRT saver:
+# on.  I also set up mine for parity (but you may not need it).  Then 
+# save the setup with ^S.
+# (cit101e-rv: added empty :te: to suppress a tic warning. --esr)
+cit101e-rv|Citoh CIT-101e (sets reverse video):\
+	:am:eo:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:SF=\E[%dS:SR=\E[%dT:UP=\E[%dA:\
+	:al=\E[L:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:ch=\E[%i%dG:\
+	:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:ct=\E[3g:dc=\E[P:dl=\E[M:do=\E[B:ei=\E[4l:ho=\E[H:ic=\E[@:\
+	:im=\E[4h:\
+	:is=\E<\E>\E[?1l\E[?3l\E[?4l\E[?5h\E[?7h\E[?8h\E[3g\E[>5g\E(B\E[m\E[20l\E[1;24r\E[24;1H:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:kb=\177:kd=\E[B:kl=\E[D:\
+	:kr=\E[C:ku=\E[A:le=^H:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:\
+	:nd=\E[C:nl=\EM:nw=\EE:r1=\Ec\E[?7h\E[>5g:rc=\E8:sc=\E7:\
+	:se=\E[m:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:te=:\
+	:ti=\E[>5g\E[?7h\E[?5h:u6=\E[%i%d;%dR:u7=\E[6n:\
+	:u8=\E[?6c:u9=\E[c:ue=\E[m:up=\E[A:us=\E[4m:\
+	:vb=200\E[?5l\E[?5h:ve=\E[0;3;4v:vi=\E[1v:vs=\E[3;5v:
+cit101e-n|CIT-101e w/o am:\
+	:am@:\
+	:kb=^H:kd=^J:kl=^H:vs=\E[?1l\E[?4l\E[?7l:tc=cit101e:
+cit101e-132|CIT-101e with 132 cols:\
+	:co#132:\
+	:kb=^H:kd=^J:kl=^H:tc=cit101e:
+cit101e-n132|CIT-101e with 132 cols w/o am:\
+	:am@:\
+	:co#132:\
+	:kb=^H:kd=^J:kl=^H:vs=\E[?1l\E[?4l\E[?7l:tc=cit101e:
+# CIE Terminals CIT-500 from BRL
+# The following SET-UP modes are assumed for normal operation:
+#	GENERATE_XON/XOFF:YES	DUPLEX:FULL		NEWLINE:OFF
+#	AUTOWRAP:ON		MODE:ANSI		SCREEN_LENGTH:64_LINES
+#	DSPLY_CNTRL_CODES?NO	PAGE_WIDTH:80		EDIT_MODE:OFF
+# Other SET-UP modes may be set for operator convenience or communication
+# requirements.
+# Hardware tabs are assumed to be set every 8 columns; they can be set up
+# by the "reset", "tset", or "tabs" utilities.  No delays are specified; use
+# "stty ixon -ixany" to enable DC3/DC1 flow control!
+# (cit500: I added <rmam>/<smam> based on the init string -- esr)
+cit500|CIE Terminals CIT-500:\
+	:bs:mi:ms:pt:xo:\
+	:co#80:it#8:kn#10:li#64:vt#3:\
+	:AL=\E[%dL:DL=\E[%dM:DO=\E[%dB:LE=\E[%dD:RA=\E[?7l:\
+	:RI=\E[%dC:SA=\E[?7h:UP=\E[%dA:ac=:ae=^O:al=\E[L:as=^N:\
+	:bl=^G:bt=\E[Z:cd=\EJ:ce=\EK:cl=\E[H\E[J:cm=\E[%i%d;%dH:\
+	:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=^J:\
+	:ei=\E[4l:ho=\E[H:im=\E[4h:is=\E<\E)0:k0=\EOP:k1=\EOQ:\
+	:k2=\EOR:k3=\EOS:k4=\EOU:k5=\EOV:k6=\EOW:k7=\EOX:k8=\EOY:\
+	:k9=\EOZ:kA=\E[L:kB=\E[Z:kD=\E[P:kE=\EK:kI=\E[4h:kL=\E[M:\
+	:kM=\E[4l:kS=\EJ:kb=^H:kd=\EOB:ke=\E[?1l\E>:kh=\E[H:\
+	:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:l0=PF1:l1=PF2:l2=PF3:\
+	:l3=PF4:l4=F15:l5=F16:l6=F17:l7=F18:l8=F19:l9=F20:le=^H:\
+	:ll=\E[64H:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:\
+	:nw=\EE:\
+	:r1=\E<\E2\E[20l\E[?6l\E[r\E[m\E[q\E(B\017\E)0\E>:\
+	:rc=\E8:sc=\E7:se=\E[m:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:ue=\E[m:up=\EM:us=\E[4m:
+
+# C. Itoh printers begin here
+citoh|ci8510|8510|c.itoh 8510a:\
+	:co#80:it#8:\
+	:is=\E(009\054017\054025\054033\054041\054049\054057\054065\054073.:\
+	:le@:md=\E\041:me=\E"\EY:rp=\ER%r%03%.:sr=\Er:ue=\EY:\
+	:us=\EX:\
+	:tc=lpr:
+citoh-pica|citoh in pica:\
+	:i1=\EN:tc=citoh:
+citoh-elite|citoh in elite:\
+	:co#96:\
+	:i1=\EE:\
+	:is=\E(009\054017\054025\054033\054041\054049\054057\054065\054073\054081\054089.:tc=citoh:
+citoh-comp|citoh in compressed:\
+	:co#136:\
+	:i1=\EQ:\
+	:is=\E(009\054017\054025\054033\054041\054049\054057\054065\054073\054081\054089\054097\054105\054113\054121\054129.:tc=citoh:
+# citoh has infinite cols because we don't want lp ever inserting \n\t**.
+citoh-prop|citoh-ps|ips|citoh in proportional spacing mode:\
+	:co#32767:\
+	:i1=\EP:tc=citoh:
+citoh-6lpi|citoh in 6 lines per inch mode:\
+	:i2=\EA:tc=citoh:
+citoh-8lpi|citoh in 8 lines per inch mode:\
+	:li#88:\
+	:i2=\EB:tc=citoh:
+
+#### Control Data (cdc)
+#
+
+cdc456|cdc 456 terminal:\
+	:am:bs:\
+	:co#80:li#24:\
+	:al=\EL:bl=^G:cd=^X:ce=^V:cl=^Y^X:cm=\E1%+ %+ :cr=^M:dl=\EJ:\
+	:do=^J:ho=^Y:le=^H:nd=^L:sf=^J:up=^Z:
+
+# Assorted CDC terminals from BRL (improvements by DAG & Ferd Brundick)
+cdc721|CDC Viking:\
+	:am:bs:\
+	:co#80:li#24:\
+	:ce=^K:cl=^L:cm=\002%r%+ %+ :ho=^Y:kd=^J:kh=^Y:kl=^H:kr=^I:\
+	:ku=^W:nd=^X:up=^W:
+cdc721ll|CDC Vikingll:\
+	:am:bs:\
+	:co#132:li#24:\
+	:ce=^K:cl=^L:cm=\002%r%+ %+ :ho=^Y:kd=^J:kh=^Y:kl=^H:kr=^I:\
+	:ku=^W:nd=^X:up=^W:
+# (cdc752: the BRL entry had :ll=\E1  ^Z: commented out
+cdc752|CDC 752:\
+	:am:bs:bw:xs:\
+	:co#80:li#24:\
+	:bl=^G:ce=^V:cl=\030\E1  :cm=\E1%r%+ %+ :cr=^M:do=^J:\
+	:ho=\E1  :le=^H:ll=^Y:nd=^U:r1=\E1  \030\002\003\017:\
+	:sf=^J:up=^Z:
+# CDC 756
+# The following switch/key settings are assumed for normal operation:
+#	96 chars	SCROLL		FULL duplex	not BLOCK
+# Other switches may be set according to communication requirements.
+# Insert/delete-character cannot be used, as the whole display is affected.
+# "so" & "se" are commented out until jove handles "sg" correctly.
+cdc756|CDC 756:\
+	:am:bs:bw:\
+	:co#80:kn#10:li#24:\
+	:al=6*\EL:bl=^G:cd=^X:ce=^V:cl=^Y^X:cm=\E1%r%+ %+ :cr=^M:\
+	:dl=6*\EJ:do=^J:ho=^Y:k0=\EA:k1=\EB:k2=\EC:k3=\ED:k4=\EE:\
+	:k5=\EF:k6=\EG:k7=\EH:k8=\Ea:k9=\Eb:kA=\EL:kD=\EI:kE=^V:\
+	:kI=\EK:kL=\EL:kS=^X:kT=^O:kb=^H:kd=^J:kh=^Y:kl=^H:kr=^U:\
+	:ku=^Z:l0=F1:l1=F2:l2=F3:l3=F4:l4=F5:l5=F6:l6=F7:l7=F8:l8=F9:\
+	:l9=F10:le=^H:ll=^Y^Z:nd=^U:r1=\031\030\002\003\017:sf=^J:\
+	:up=^Z:
+#
+# CDC 721 from Robert Viduya, Ga. Tech. <ihnp4!gatech!gitpyr!robert> via BRL.
+#
+# Part of the long initialization string defines the "DOWN" key to the left
+# of the tab key to send an ESC.  The real ESC key is positioned way out 
+# in right field.
+#
+# The termcap won't work in 132 column mode due to the way it it moves the
+# cursor.  Termcap doesn't have the capability (as far as I could tell) to
+# handle the 721 in 132 column mode.
+#
+# (cdc721: changed :ri: to :sr: -- esr)
+cdc721-esc|Control Data 721:\
+	:am:bs:bw:ms:pt:xo:\
+	:co#80:it#8:kn#10:li#30:\
+	:al=^^R:bl=^G:bt=^^^K:cd=^^P:ce=^K:cl=^L:cm=\002%r%+ %+ :\
+	:ct=^^^RY:dc=^^N:dl=^^Q:do=^Z:ei=:ho=^Y:ic=^^O:im=:\
+	:is=\036\022B\003\036\035\017\022\025\035\036E\036\022H\036\022J\036\022L\036\022N\036\022P\036\022Q\036\022\036\022\136\036\022b\036\022i\036W =\036\022Z\036\011C1-` `\041k/o:\
+	:k0=^^q:k1=^^r:k2=^^s:k3=^^t:k4=^^u:k5=^^v:k6=^^w:k7=^^x:\
+	:k8=^^y:k9=^^z:kb=^H:kd=^Z:ke=^^^Rl:kh=^Y:kl=^H:kr=^X:\
+	:ks=^^^Rk:ku=^W:le=^H:ll=^B =:mb=^N:\
+	:me=\017\025\035\036E\036\022\:mh=^\:mk=^^^R[:mr=^^D:\
+	:nd=^X:se=^^E:sf=\036W =\036U:so=^^D:sr=\036W =\036V:\
+	:st=^^^RW:ue=^]:up=^W:us=^\:
+
+#### Getronics
+#
+# Getronics is a Dutch electronics company that at one time was called 
+# `Geveke' and made async terminals; but (according to the company itself!)
+# they've lost all their documentation on the command set.  The hardware
+# documentation suggests the terminals were actually manufactured by a
+# Taiwanese electronics company named Cal-Comp.  There are known
+# to have been at least two models, the 33 and the 50.
+#
+
+# The 50 seems to be a top end vt220 clone, with the addition of a higher
+# screen resolution, a larger screen, at least 1 page of memory above and
+# below the screen, apparently pages of memory right and left of the screen
+# which can be panned, and about 75 function keys (15 function keys x normal,
+# shift, control, func A, func B). It also has more setup possibilities than
+# the vt220. The monitor case is dated November 1978 and the keyboard case is
+# May 1982.
+#
+# The vt100 emulation works as is.  The entry below describes the rather
+# non-conformant (but more featureful) ANSI mode.
+#
+# From: Stephen Peterson <stv@utrecht.ow.nl>, 27 May 1995
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+visa50|geveke visa 50 terminal in ansi 80 character mode:\
+	:bw:mi:ms:\
+	:co#80:li#25:\
+	:AL=\E[%dL:DC=\E[%dX:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:K1=\E[f:K2=\EOP:K3=\EOQ:K4=\EOR:K5=\EOS:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=\E[3l:al=\E[L:as=\E3h:bl=^G:\
+	:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:\
+	:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[X:dl=\E[M:do=\E[B:\
+	:ei=\E[4l:ho=\E[H:ic=\E[@:im=\E[4h:\
+	:is=\E0;2m\E[1;25r\E[25;1H\E[?3l\E[?7h\E[?8h:k0=\E010:\
+	:k1=\E001:k2=\E002:k3=\E003:k4=\E004:k5=\E005:k6=\E006:\
+	:k7=\E007:k8=\E008:k9=\E009:kD=\177:kb=^H:kd=\E[A:ke=\E>:\
+	:kh=\E[f:kl=\E[D:kr=\E[C:ks=\E=:ku=\E[A:le=\E[D:mb=\E[5m:\
+	:md=\E[1m:me=\E[0;2m:mh=\E[2m:mr=\E[7m:nd=\E[C:nw=^M^J:\
+	:se=\E[0;2m:sf=^J:so=\E[2;7m:ta=^I:ue=\E[0m:up=\E[A:\
+	:us=\E[4m:vb=\E[?5h\E[?5l:
+
+#### Human Designed Systems (Concept)
+#
+#	Human Designed Systems
+#	400 Fehley Drive
+#	King of Prussia, PA 19406
+#	Vox: (610)-277-8300
+#	Fax: (610)-275-5739
+#	Net: support@hds.com
+# 
+# John Martin <john@hds.com> is their termcap expert.  They're mostly out of
+# the character-terminal business now (1995) and making X terminals.  In
+# particular, the whole `Concept' line described here was discontinued long
+# ago.
+#
+
+# From: <vax135!hpk>  Sat Jun 27 07:41:20 1981
+# Extensive changes to c108 by arpavax:eric Feb 1982
+# Some unknown person at SCO then translated it to terminfo.
+#
+# There seem to be a number of different versions of the C108 PROMS
+# (with bug fixes in its Z-80 program).
+# 
+# The first one that we had would lock out the keyboard of you
+# sent lots of short lines (like /usr/dict/words) at 9600 baud.
+# Try that on your C108 and see if it sends a ^S when you type it.
+# If so, you have an old version of the PROMs.
+# 
+# You should configure the C108 to send ^S/^Q before running this.
+# It is much faster (at 9600 baud) than the c100 because the delays
+# are not fixed.
+# new status line display entries for c108-8p:
+# :i3: - init str #3 - setup term for status display - 
+# set programmer mode, select window 2, define window at last 
+# line of memory, set bkgnd stat mesg there, select window 0.
+# 
+# :ts: - to status line - select window 2, home cursor, erase to 
+# end-of-window, 1/2 bright on, goto(line#0, col#?)
+# 
+# :fs: - from status line - 1/2 bright off, select window 0
+# 
+# :ds: - disable status display - set bkgnd status mesg with 
+# illegal window #
+# 
+# There are probably more function keys that should be added but 
+# I don't know what they are.
+#
+# No delays needed on c108 because of ^S/^Q handshaking
+#
+c108|concept108|c108-8p|concept108-8p|concept 108 w/8 pages:\
+	:i2=\EU\E z"\Ev\001\177 \041p\E ;"\E z \Ev  \001\177p\Ep\n:\
+	:te=\Ev  \001\177p\Ep\r\n:\
+	:tc=c108-4p:
+c108-4p|concept108-4p|concept 108 w/4 pages:\
+	:bs:es:hs:xo:\
+	:pb@:\
+	:ac=jEkTl\mMqLxU:ae=\Ej :as=\Ej\041:\
+	:..cm=\Ea%p1%?%p1%{95}%>%t\001%{96}%-%;%{32}%+%c%p2%?%p2%{95}%>%t\001%{96}%-%;%{32}%+%c:\
+	:cr=^M:dc=\E 1:ds=\E ;\177:fs=\Ee\E z :i1=\EK\E\041\E F:\
+	:i2=\EU\E z"\Ev\177 \041p\E ;"\E z \Ev  \001 p\Ep\n:\
+	:sf=^J:te=\Ev  \001 p\Ep\r\n:ti=\EU\Ev  8p\Ep\r\E\025:\
+	:ts=\E z"\E?\E\005\EE\Ea %+ :ve=\Ew:vs=\EW:\
+	:tc=c100:
+c108-rv|c108-rv-8p|concept 108 w/8 pages in reverse video:\
+	:te=\Ev  \002 p\Ep\r\n:ti=\EU\Ev  8p\Ep\r:\
+	:tc=c108-rv-4p:
+c108-rv-4p|concept108rv4p|concept 108 w/4 pages in reverse video:\
+	:i1=\Ek:se=\Ee:so=\EE:vb=\EK\Ek:\
+	:tc=c108-4p:
+c108-w|c108-w-8p|concept108-w-8|concept108-w8p|concept 108 w/8 pages in wide mode:\
+	:co#132:\
+	:i1=\E F\E":te=\Ev  ^A0\001D\Ep\r\n:\
+	:ti=\EU\Ev  8\001D\Ep\r:tc=c108-8p:
+
+# Concept 100:
+# These have only window relative cursor addressing, not screen 
+# relative. To get it to work right here, smcup/rmcup (which 
+# were invented for the concept) lock you into a one page 
+# window for screen style programs.
+# 
+# To get out of the one page window, we use a clever trick:
+# we set the window size to zero ("\Ev    " in rmcup) which the 
+# terminal recognizes as an error and resets the window to all 
+# of memory.
+# 
+# This trick works on c100 but does not on c108, sigh.
+# 
+# Some tty drivers use cr3 for concept, others use nl3, hence 
+# the delays on cr and ind below. This padding is only needed at 
+# 9600 baud and up.  One or the other is commented out depending on 
+# local conventions.
+# 
+# 2 ms padding on :te: isn't always enough. 6 works fine. Maybe 
+# less than 6 but more than 2 will work.
+# 
+# Note: can't use function keys f7-f10 because they are 
+# indistinguishable from arrow keys (!), also, del char and 
+# clear eol use xon/xoff so they probably won't work very well.
+# 
+# Also note that we don't define insrt/del char/delline/eop/send 
+# because they don't transmit unless we reset them - I figured 
+# it was a bad idea to clobber their definitions.
+# 
+# The <mc5> sequence changes the escape character to ^^ so that 
+# escapes will be passed through to the printer. Only trouble 
+# is that ^^ won't be - ^^ was chosen to be unlikely. 
+# Unfortunately, if you're sending raster bits through to be 
+# plotted, any character you choose will be likely, so we lose.
+#
+# \EQ"\EY(^W (send anything from printer to host, for xon/xoff) 
+# cannot be # in is2 because it will hang a c100 with no printer 
+# if sent twice.
+c100|concept100|concept|c104|c100-4p|hds concept 100:\
+	:am:bs:eo:mi:ul:xn:\
+	:co#80:li#24:pb#9600:vt#8:\
+	:al=\E\022:bl=^G:cd=\E\005:ce=\E\025:cl=\E?\E\005:\
+	:cm=\Ea%+ %+ :cr=\r:dc=\E\021:dl=\E\002:do=^J:ei=\E  :\
+	:i1=\EK:i2=\Ev    \Ep\n:im=\E^P:ip=:\
+	:is=\EU\Ef\E7\E5\E8\El\ENH\E\0\Eo&\0\Eo'\E\Eo\041\0\E\007\041\E\010A@ \E4#\072"\E\072a\E4#;"\E\072b\E4#<"\E\072c:\
+	:k1=\E5:k2=\E6:k3=\E7:k4=\E8:k5=\E9:k6=\E\072a:k7=\E\072b:\
+	:k8=\E\072c:kA=\E^R:kB=\E':kD=\E^Q:kE=\E^S:kF=\E[:kI=\E^P:\
+	:kL=\E^B:kM=\E\0:kN=\E-:kP=\E.:kR=\E\:kS=\E^C:kT=\E]:kb=^H:\
+	:kd=\E<:ke=\Ex:kh=\E?:kl=\E>:kr=\E=:ks=\EX:kt=\E_:ku=\E;:\
+	:le=^H:mb=\EC:me=\EN@:mh=\EE:mk=\EH:mp=\EI:mr=\ED:nd=\E=:\
+	:pf=\036o \E\EQ\041\EYP\027:\
+	:po=\EQ"\EY(\027\EYD\Eo \036:rp=\Er%.%+ :se=\Ed:sf=^J:\
+	:so=\ED:ta=\011:te=\Ev    \Ep\r\n:\
+	:ti=\EU\Ev  8p\Ep\r\E\025:ue=\Eg:up=\E;:us=\EG:vb=\Ek\EK:
+c100-rv|c100-rv-4p|concept100-rv|c100 rev video:\
+	:i1=\Ek:se=\Ee:so=\EE:vb=\EK\Ek:ve@:vs@:tc=c100:
+oc100|oconcept|c100-1p|old 1 page concept 100:\
+	:in:\
+	:i3@:tc=c100:
+
+# From: Walter Skorski <walt@genetics1.JMP.TJU.EDU>, 16-oct-1996.
+# Lots of notes, originally inline, but ncurses doesn't grok that.
+#
+# am: 	not available in power on mode, but turned on with \E[=107;207h in
+#	is2=.  Also, \E=124l in is2= could have been used to prevent needing
+#	to specify xenl:, but that would have rendered the last space on the
+#	last line useless.
+# bw:	Not available in power on mode, but turned on with \E[=107;207h in
+#	is2=.
+# clear: Could be done with \E[2J alone, except that vi (and probably most
+#	other programs) assume that this also homes the cursor.
+# dsl:	Go to window 2, go to the beginning of the line, use a line feed to
+#	scroll the window, and go back to window 1.
+# is2:	the string may cause a warning to be issued by tic that it
+#	found a very long line and that it suspects that a comma is missing
+#	somewhere.  This warning can be ignored (unless it comes up more than
+#	once).  The initialization string contains the following commands:
+#
+#	 [Setup mode items changed from factory defaults:]
+#		\E)0			set alternate character set to
+#						graphics
+#		^O			set character set to default
+#	 [In case it wasn't]
+#		\E[m			turn off all attributes
+#	 [In case they weren't off]
+#		\E[=107;		cursor wrap and
+#			207h			character wrap on
+#		\E[90;3u		set Fkey definitions to "transmit"
+#						defaults
+#		\E[92;3u		set cursor key definitions to
+#						"transmit" defaults
+#		\E[43;1u		set shift F13 to transmit...
+#		\177\E$P\177
+#		\E[44;1u		set shift F14 to transmit...
+#			\177\E$Q\177
+#		\E[45;1u		set shift F15 to transmit...
+#			\177\E$R\177
+#		\E[46;1u		set shift F16 to transmit...
+#			\177\E$S\177
+#		\E[200;1u		set shift up to transmit...
+#			\177\E$A\177
+#		\E[201;1u		set shift down to transmit...
+#			\177\E$B\177
+#		\E[202;1u		set shift right to transmit...
+#			\177\E$C\177
+#		\E[203;1u		set shift left to transmit...
+#			\177\E$D\177
+#		\E[204;1u		set shift home to transmit...
+#			\177\E$H\177
+#		\E[212;1u		set backtab to transmit...
+#			\177\E$I\177
+#		\E[213;1u		set shift backspace to transmit...
+#			\177\E$^H\177
+#		\E[214;1u		set shift del to transmit...
+#			"\E$\177"
+#	 [Necessary items not mentioned in setup mode:]
+#		\E[2!w			move to window 2
+#		\E[25;25w		define window as line 25 of memory
+#		\E[!w			move to window 1
+#		\E[2*w			show current line of window 2 as
+#						status line
+#		\E[2+x			set meta key to use high bit
+#		\E[;3+}			move underline to bottom of character
+#
+#	All Fkeys are set to their default transmit definitions with \E[90;3u
+#	in is2=.  IMPORTANT:  to use this terminal definition, the "quit" stty
+#	setting MUST be redefined or deactivated, because the default is
+#	contained in almost all of this terminal's Fkey strings!  If for some
+#	reason "quit" cannot be altered, the Fkeys can, but it would be
+#	necessary to change ^| to ^] in all of these definitions, and add
+#	\E[2;029!t to is2.
+# lines: is set to 24 because this terminal refuses to treat the 25th
+#	line normally.
+# ll:	Not available in power on mode, but turned on with \E[=107;207h in
+#	is2=.
+# lm:	Pointless, given that this definition locks a single screen of
+#	memory into view, but what the hey...
+# rmso: Could use \E[1;7!{ to turn off only bold and reverse (leaving any
+#	other attributes alone), but some programs expect this to turn off
+#	everything.
+# rmul: Could use \E[4!{ to turn off only underline (leaving any other
+#	attributes alone), but some programs expect this to turn off
+#	everything.
+# sgr:	Attributes are set on this terminal with the string \E[ followed by
+#	a list of attribute code numbers (in decimal, separated by
+#	semicolons), followed by the character m.  The attribute code
+#	numbers are:
+#		  1 for bold;
+#		  2 for dim (which is ignored in power on mode);
+#		  4 for underline;
+#		  5 for blinking;
+#		  7 for inverse;
+#		  8 for not displayable; and
+#		=99 for protected (except that there are strange side
+#		effects to protected characters which make them inadvisable).
+#	 The mapping of terminfo parameters to attributes is as follows:
+#		%p1 (standout) = bold and inverse together;
+#		%p2 (underline) = underline;
+#		%p3 (reverse) = inverse;
+#		%p4 (blink) = blinking;
+#		%p5 (dim) is ignored;
+#		%p6 (bold) = bold;
+#		%p7 (invisible) = not displayable;
+#		%p8 (protected) is ignored; and
+#		%p9 (alt char set) = alt char set.
+#	 The code to do this is:
+#		\E[0		OUTPUT	\E[0
+#		%?%p1%p6%O	IF	(standout; bold) OR
+#		%t;1		THEN	OUTPUT	;1
+#		%;		ENDIF
+#		%?%p2		IF	underline
+#		%t;4		THEN	OUTPUT	;4
+#		%;		ENDIF
+#		%?%p4		IF	blink
+#		%t;5		THEN	OUTPUT	;5
+#		%;		ENDIF
+#		%?%p1%p3%O	IF	(standout; reverse) OR
+#		%t;7		THEN	OUTPUT	;7
+#		%;		ENDIF
+#		%?%p7		IF	invisible
+#		%t;8		THEN	OUTPUT	;8
+#		%;		ENDIF
+#		m		OUTPUT	m
+#		%?%p9		IF	altcharset
+#		%t^N		THEN	OUTPUT	^N
+#		%e^O		ELSE	OUTPUT	^O
+#		%;		ENDIF
+# sgr0: Everything is turned off (including alternate character set), since
+#	there is no way of knowing what it is that the program wants turned
+#	off.
+# smul: The "underline" attribute is reconfigurable to an overline or
+#	strikethru, or (as done with \E[;3+} in is2=), to a line at the true
+#	bottom of the character cell.  This was done to allow for more readable
+#	underlined characters, and to be able to distinguish between an
+#	underlined space, an underscore, and an underlined underscore.
+# xenl: Terminal can be configured to not need this, but this "glitch"
+#	behavior is actually preferable with autowrap terminals.
+#
+# Parameters kf31= thru kf53= actually contain the strings sent by the shifted
+# Fkeys.  There are no parameters for shifted Fkeys in terminfo.  The is2
+# string modifies the 'O' in kf43 to kf46 to a '$'.
+#
+# kcbt was originally ^I but redefined in is2=.
+# kHOM was \E[H originally but redefined in is2=, as were a number of
+# other keys.
+# kDC was originally \177 but redefined in is2=.
+#
+# kbs:	Shift was also ^H originally but redefined as \E$^H in is2=.
+# tsl:	Go to window 2, then do an hpa=.
+#
+#------- flash=\E[8;3!}^G\E[3;3!}
+#------- flash=\E[?5h$<100>\E[?5l
+# There are two ways to flash the screen, both of which have their drawbacks. 
+# The first is to set the bell mode to video, transmit a bell character, and
+# set the bell mode back - but to what?  There is no way of knowing what the
+# user's old bell setting was before we messed with it.  Worse, the command to
+# set the bell mode also sets the key click volume, and there is no way to say
+# "leave that alone", or to know what it's set to, either.
+# The second way to do a flash is to set the screen to inverse video, pad for a
+# tenth of a second, and set it back - but like before, there's no way to know
+# that the screen wasn't ALREADY in inverse video, or that the user may prefer
+# it that way.  The point is moot anyway, since vi (and probably other
+# programs) assume that by defining flash=, you want the computer to use it
+# INSTEAD of bel=, rather than as a secondary type of signal.
+#
+#------- cvvis=\E[+{
+# The is the power on setting, which is also as visible as the cursor
+# gets.
+#-------  wind=\E[%i%p1%d;%p2%d;%p3%{1}%+%d;%p4%{1}%+%dw
+# Windowing is possible, but not defined here because it is also used to
+# emulate status line functions.  Allowing a program to set a window could
+# clobber the status line or render it unusable.  There is additional memory,
+# but screen scroll functions are destructive and do not make use of it.
+#
+#-------   dim=			Not available in power on mode.
+# You have a choice of defining low intensity characters as "half bright" and
+# high intensity as "normal", or defining low as "normal" and high as "bold". 
+# No matter which you choose, only one of either "half bright" or "bold" is
+# available at any time, so taking the time to override the default is
+# pointless.
+#
+#-------  prot=\E[=0;99m
+# Not defined, because it appears to have some strange side effects.
+#------- pfkey=%?%p1%{24}%<%p1%{30}%>%p1%{54}%<%A%O%t\E[%p1%du\177%p2%s\177%;
+#------- pfloc=%?%p1%{24}%<%p1%{30}%>%p1%{54}%<%A%O%t\E[%p1%du\177%p2%s\177%;
+#-------   pfx=%?%p1%{24}%<%p1%{30}%>%p1%{54}%<%A%O%t\E[%p1%d;1u\177%p2%s\177%;
+#	 Available, but making them available to programs is inadvisable.
+#	 The code to do this is:
+#		%?%p1%{24}%<	IF	((key; 24) <;
+#		%p1%{30}%>		 ((key; 30) >;
+#		%p1%{54}%<		  (key; 54) <
+#		%A			 ) AND
+#		%O		  	) OR
+#	 [that is, "IF key < 24 OR (key > 30 AND key < 54)",]
+#		%t\E[		THEN	OUTPUT	\E[
+#		%p1%d			OUTPUT	(key) as decimal
+#	 [next line applies to pfx only]
+#		;1			OUTPUT	;1
+#		u			OUTPUT	u
+#		\177			OUTPUT	\177
+#		%p2%s			OUTPUT	(string) as string
+#		\177			OUTPUT	\177
+#	 [DEL chosen as delimiter, but could be any character]
+#	 [implied:		ELSE	do nothing]
+#		%;		ENDIF
+#	
+#-------   rs2=
+# Not defined since anything it might do could be done faster and easier with
+# either Meta-Shift-Reset or the main power switch.
+#
+#-------  smkx=\E[1!z
+#-------  rmkx=\E[!z
+# These sequences apply to the cursor and setup keys only, not to the
+# numeric keypad.  But it doesn't matter anyway, since making these
+# available to programs is inadvisable.
+# For the key definitions below, all sequences beginning with \E$ are
+# custom and programmed into the terminal via is2.  \E$ also has no
+# meaning to any other terminal.
+#
+#------- cmdch=\E[;%p1%d!t
+# Available, but making it available to programs is inadvisable.
+#------- smxon=\E[1*q
+# Available, but making it available to programs is inadvisable.
+# Terminal will send XON/XOFF on buffer overflow.
+#------- rmxon=\E[*q
+# Available, but making it available to programs is inadvisable.
+# Terminal will not notify on buffer overflow.
+#-------   smm=\E[2+x
+#-------   rmm=\E[+x
+# Available, but making them available to programs is inadvisable.
+#
+# Printing:
+#	 It's not made clear in the manuals, but based on other ansi/vt type
+#	 terminals, it's a good guess that this terminal is capable of both
+#	 "transparent print" (which doesn't copy data to the screen, and
+#	 therefore needs mc5i: specified to say so) and "auxilliary print"
+#	 (which does duplicate printed data on the screen, in which case mc4=
+#	 and mc5= should use the \E[?4i and \E[?5i strings instead).
+#
+# (esr: I have commented out is2 in order to avoid overflowing termcap's
+# 1024-byte limit.)
+
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+hds200|Human Designed Systems HDS200:\
+	:am:bw:es:hs:km:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:lm#0:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:\
+	:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:do=\E[B:\
+	:ds=\E[2\041w\r\n\E[\041w:ei=\E[4l:fs=\E[\041w:ho=\E[H:\
+	:im=\E[4h:k1=^\001\r:k2=^\002\r:k3=^\003\r:k4=^\004\r:\
+	:k5=^\005\r:k6=^\006\r:k7=^\007\r:k8=^\008\r:k9=^\009\r:\
+	:kD=\177:kN=\E[U:kP=\E[V:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:\
+	:kr=\E[C:ku=\E[A:le=\E[D:ll=\E[H\E[A:mb=\E[0;5m:\
+	:md=\E[0;1m:me=\E[m\017:mr=\E[0;7m:nd=\E[C:nw=\E[E:rc=\E8:\
+	:sc=\E7:se=\E[m\017:sf=\ED:so=\E[0;1;7m:sr=\EM:st=\EH:\
+	:ta=^I:ts=\E[2\041w\E[%i%p1%dG:ue=\E[m\017:up=\E[A:\
+	:us=\E[0;4m:ve=\E[+{:vi=\E[6+{:
+
+# :ta: through :ce: included to specify padding needed in raw mode.
+# (avt-ns: added empty <acsc> to suppress a tic warning --esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+avt-ns|concept avt no status line:\
+	:am:bs:eo:mi:ul:xn:xo:\
+	:co#80:it#8:li#24:lm#192:\
+	:AL=\E[%dL:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=\016:al=\E[L:as=\017:bl=^G:bt=\E[Z:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[2g:dc=\E[P:dl=\E[M:do=^J:ei=\E4l:\
+	:ho=\E[H:i1=\E[=103l\E[=205l:ic=\E[@:im=\E1:ip=:\
+	:is=\E[1*q\E[2\041t\E[7\041t\E[=4;101;119;122l\E[=107;118;207h\E)1\E[1Q\EW\E[\041y\E[\041z\E>\E[0\0720\07232\041r\E[0*w\E[w\E2\r\n\E[2;27\041t:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:kD=\E^B\r:kI=\E^A\r:kb=^H:\
+	:kd=\E[B:ke=\E[\041z\E[0;2u:kh=\E[H:kl=\E[D:kr=\E[C:\
+	:ks=\E[1\041z\E[0;3u:ku=\E[A:le=^H:ll=\E[24H:mb=\E[5m:\
+	:md=\E[1m:me=\E[m:mh=\E[1\041{:mr=\E[7m:nd=\E[C:rc=\E8:\
+	:sc=\E7:se=\E[7\041{:sf=\n:so=\E[7m:sr=\EM:st=\EH:ta=\011:\
+	:te=\E[w\E2\r\n:ti=\E[=4l\E[1;24w\E2\r:ue=\E[4\041{:\
+	:up=\E[A:us=\E[4m:ve=\E[=119l:vs=\E[=119h:
+avt-rv-ns|concept avt in reverse video mode/no status line:\
+	:i1=\E[=103l\E[=205h:vb=\E[=205l\E[=205h:\
+	:tc=avt-ns:
+avt-w-ns|concept avt in 132 column mode/no status line:\
+	:i1=\E[=103h\E[=205l:ti=\E[H\E[1;24;1;132w:\
+	:tc=avt-ns:
+avt-w-rv-ns|concept avt in 132 column mode/no status line/reverse video:\
+	:i1=\E[=103h\E[=205h:ti=\E[H\E[1;24;1;132w:\
+	:vb=\E[=205l\E[=205h:tc=avt-ns:
+
+# Concept AVT with status line. We get the status line using the
+# "Background status line" feature of the terminal. We swipe the
+# first line of memory in window 2 for the status line, keeping
+# 191 lines of memory and 24 screen lines for regular use.
+# The first line is used instead of the last so that this works
+# on both 4 and 8 page AVTs. (Note the lm#191 or 192 - this
+# assumes an 8 page AVT but lm isn't currently used anywhere.)
+#
+avt+s|concept avt status line changes:\
+	:es:hs:\
+	:lm#191:\
+	:ds=\E[0*w:fs=\E[1;1\041w:\
+	:i2=\E[2w\E[2\041w\E[1;1;1;80w\E[H\E[2*w\E[1\041w\E2\r\n:\
+	:te=\E[2w\E2\r\n:ti=\E[2;25w\E2\r:\
+	:ts=\E[2;1\041w\E[;%p1%dH\E[2K:
+avt|avt-s|concept-avt|avt w/80 columns:\
+	:tc=avt+s:tc=avt-ns:
+avt-rv|avt-rv-s|avt reverse video w/sl:\
+	:i1=\E[=103l\E[=205h:vb=\E[=205l\E[=205h:tc=avt+s:tc=avt-ns:
+avt-w|avt-w-s|concept avt 132 cols+status:\
+	:i1=\E[=103h\E[=205l:ti=\E[H\E[1;24;1;132w:tc=avt+s:tc=avt-ns:
+avt-w-rv|avt-w-rv-s|avt wide+status+rv:\
+	:i1=\E[=103h\E[=205h:ti=\E[H\E[1;24;1;132w:\
+	:vb=\E[=205l\E[=205h:tc=avt+s:\
+	:tc=avt-ns:
+
+#### Contel Business Systems. 
+#
+
+# Contel c300 and c320 terminals. 
+contel300|contel320|c300|Contel Business Systems C-300 or C-320:\
+	:am:in:xo:\
+	:co#80:li#24:sg#1:\
+	:al=\EL:bl=^G:cd=\EJ:ce=\EI:cl=\EK:cm=\EX%+ \EY%+ :cr=^M:\
+	:ct=\E3:dc=\EO:dl=\EM:do=^J:ei=:ho=\EH:ic=\EN:im=:ip=:k0=\ERJ:\
+	:k1=\ERA:k2=\ERB:k3=\ERC:k4=\ERD:k5=\ERE:k6=\ERF:k7=\ERG:\
+	:k8=\ERH:k9=\ERI:kb=^H:le=^H:ll=\EH\EA:me=\E\041\0:nd=\EC:\
+	:se=\E\041\0:sf=^J:so=\E\041\r:st=\E1:up=\EA:\
+	:vb=\020\002\020\003:
+# Contel c301 and c321 terminals.
+contel301|contel321|c301|c321|Contel Business Systems C-301 or C-321:\
+	:ei=:ic@:im=:ip@:se=\E\041\0:so=\E\041\r:vb@:\
+	:tc=contel300:
+
+#### Data General (dg)
+#
+# According to James Carlson <carlson@xylogics.com> writing in January 1995,
+# the terminals group at Data General was shut down in 1991; all these
+# terminals have thus been discontinued.
+#
+# DG terminals have function keys that respond to the SHIFT and CTRL keys,
+# e.g., SHIFT-F1 generates a different code from F1.  To number the keys
+# sequentially, first the unmodified key codes are listed as F1 through F15. 
+# Then their SHIFT versions are listed as F16 through F30, their CTRL versions
+# are listed as F31 through F45, and their CTRL-SHIFT versions are listed as
+# F46 through F60.  This is done in the private "includes" below whose names
+# start with "dgkeys+".
+#
+# DG terminals generally support 8 bit characters.  For each of these terminals
+# two descriptions are supplied:
+#	1) A default description for 8 bits/character communications, which
+#	   uses the default DG international character set and keyboard codes.
+#	2) A description with suffix "-7b" for 7 bits/character communications.
+#	   This description must use the NON-DEFAULT native keyboard language.
+
+# Unmodified fkeys (kf1-kf11), Shift fkeys (kf12-kf22), Ctrl fkeys (kf23-kf33),
+# Ctrl/Shift fdkeys (kf34-kf44).
+
+# Most of these entries are `official' and came from DG.  Others are marked.
+
+dgkeys+8b|Private entry describing DG terminal 8-bit ANSI mode special keys:\
+	:%9=\233i:F1=\233011z:F2=\233012z:F3=\233013z:\
+	:F4=\233014z:F5=\233000z:F6=\233101z:F7=\233102z:\
+	:F8=\233103z:F9=\233104z:FA=\233105z:FB=\233106z:\
+	:FC=\233107z:FD=\233108z:FE=\233109z:FF=\233110z:\
+	:FG=\233111z:FH=\233112z:FI=\233113z:FJ=\233114z:\
+	:FK=\233100z:FL=\233201z:FM=\233202z:FN=\233203z:\
+	:FO=\233204z:FP=\233205z:FQ=\233206z:FR=\233207z:\
+	:FS=\233208z:FT=\233209z:FU=\233210z:FV=\233211z:\
+	:FW=\233212z:FX=\233213z:FY=\233214z:FZ=\233200z:\
+	:Fa=\233301z:Fb=\233302z:Fc=\233303z:Fd=\233304z:\
+	:Fe=\233305z:Ff=\233306z:Fg=\233307z:Fh=\233308z:\
+	:Fi=\233309z:Fj=\233310z:Fk=\233311z:Fl=\233312z:\
+	:Fm=\233313z:Fn=\233314z:Fo=\233300z:K1=\233020z:\
+	:K3=\233021z:K4=\233022z:K5=\233023z:k1=\233001z:\
+	:k2=\233002z:k3=\233003z:k4=\233004z:k5=\233005z:\
+	:k6=\233006z:k7=\233007z:k8=\233008z:k9=\233009z:\
+	:k;=\233010z:kC=\2332J:kE=\233K:kd=\233B:kh=\233H:\
+	:kl=\233D:kr=\233C:ku=\233A:
+
+dgkeys+7b|Private entry describing DG terminal 7-bit ANSI mode special keys:\
+	:%9=\E[i:F1=\E[011z:F2=\E[012z:F3=\E[013z:F4=\E[014z:\
+	:F5=\E[000z:F6=\E[101z:F7=\E[102z:F8=\E[103z:F9=\E[104z:\
+	:FA=\E[105z:FB=\E[106z:FC=\E[107z:FD=\E[108z:FE=\E[109z:\
+	:FF=\E[110z:FG=\E[111z:FH=\E[112z:FI=\E[113z:FJ=\E[114z:\
+	:FK=\E[100z:FL=\E[201z:FM=\E[202z:FN=\E[203z:FO=\E[204z:\
+	:FP=\E[205z:FQ=\E[206z:FR=\E[207z:FS=\E[208z:FT=\E[209z:\
+	:FU=\E[210z:FV=\E[211z:FW=\E[212z:FX=\E[213z:FY=\E[214z:\
+	:FZ=\E[200z:Fa=\E[301z:Fb=\E[302z:Fc=\E[303z:Fd=\E[304z:\
+	:Fe=\E[305z:Ff=\E[306z:Fg=\E[307z:Fh=\E[308z:Fi=\E[309z:\
+	:Fj=\E[310z:Fk=\E[311z:Fl=\E[312z:Fm=\E[313z:Fn=\E[314z:\
+	:Fo=\E[300z:K1=\E[020z:K3=\E[021z:K4=\E[022z:K5=\E[023z:\
+	:k1=\E[001z:k2=\E[002z:k3=\E[003z:k4=\E[004z:k5=\E[005z:\
+	:k6=\E[006z:k7=\E[007z:k8=\E[008z:k9=\E[009z:k;=\E[010z:\
+	:kC=\E[2J:kE=\E[K:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:
+
+dgkeys+11|Private entry describing 11 minimal-subset DG mode special keys:\
+	:F1=^^{:F2=^^a:F3=^^b:F4=^^c:F5=^^d:F6=^^e:F7=^^f:F8=^^g:\
+	:F9=^^h:FA=^^i:FB=^^j:FC=^^k:FD=^^1:FE=^^2:FF=^^3:FG=^^4:\
+	:FH=^^5:FI=^^6:FJ=^^7:FK=^^8:FL=^^9:FM=^^\072:FN=^^;:\
+	:FO=^^\041:FP=^^":FQ=^^#:FR=^^$:FS=^^%:FT=^^&:FU=^^':FV=^^(:\
+	:FW=^^):FX=^^*:FY=^^+:k1=^^q:k2=^^r:k3=^^s:k4=^^t:k5=^^u:\
+	:k6=^^v:k7=^^w:k8=^^x:k9=^^y:k;=^^z:kC=^L:kE=^K:kd=^Z:kh=^H:\
+	:kl=^Y:kr=^X:ku=^W:
+
+dgkeys+15|Private entry describing 15 DG mode special keys:\
+	:#2=^^^H:#4=^^^Y:%i=^^^X:F1=^^{:F2=^^|:F3=^^}:F4=^^~:F5=^^p:\
+	:F6=^^a:F7=^^b:F8=^^c:F9=^^d:FA=^^e:FB=^^f:FC=^^g:FD=^^h:\
+	:FE=^^i:FF=^^j:FG=^^k:FH=^^l:FI=^^m:FJ=^^n:FK=^^`:FL=^^1:\
+	:FM=^^2:FN=^^3:FO=^^4:FP=^^5:FQ=^^6:FR=^^7:FS=^^8:FT=^^9:\
+	:FU=^^\072:FV=^^;:FW=^^<:FX=^^=:FY=^^>:FZ=^^0:Fa=^^\041:\
+	:Fb=^^":Fc=^^#:Fd=^^$:Fe=^^%:Ff=^^&:Fg=^^':Fh=^^(:Fi=^^):\
+	:Fj=^^*:Fk=^^+:Fl=^^\054:Fm=^^-:Fn=^^.:Fo=^^ :K1=^^\:K3=^^]:\
+	:K4=^^\136:K5=^^_:k1=^^q:k2=^^r:k3=^^s:k4=^^t:k5=^^u:k6=^^v:\
+	:k7=^^w:k8=^^x:k9=^^y:k;=^^z:
+
+# Data General color terminals use the "Tektronix" color model.  The total
+# number of colors varies with the terminal model, as does support for
+# attributes used in conjunction with color.
+
+# Removed u7, u8 definitions since they conflict with tack:
+#		Preserve user-defined colors in at least some cases.
+#	u7=^^Fh,
+#		Default is ACM mode.
+#	u8=^^F}20^^Fi^^F}21,
+#
+dgunix+fixed|Fixed color info for DG D430C terminals in DG-UNIX mode:\
+	:ut:\
+	:Co#16:NC#53:pa#256:\
+	:AB=\036B%p1%?%p1%{8}%<%t%{2}%&%?%p1%{1}%&%t%{4}%|%;%?%p1%{4}%&%t%{1}%|%;%;%{48}%+%c:\
+	:AF=\036A%p1%?%p1%{8}%<%t%{2}%&%?%p1%{1}%&%t%{4}%|%;%?%p1%{4}%&%t%{1}%|%;%;%{48}%+%c:\
+	:Sb=\036B%+0:Sf=\036A%+0:op=\036Ad\036Bd:
+
+dg+fixed|Fixed color info for DG D430C terminals in DG mode:\
+	:tc=dgunix+fixed:
+
+# Video attributes are coordinated using static variables set by "sgr", then
+# checked by "op", "seta[bf]", and "set[bf]" to refresh the attribute settings. 
+# (D=dim, U=underline, B=blink, R=reverse.)
+dg+color8|Color info for Data General D220 and D230C terminals in ANSI mode:\
+	:ut:\
+	:Co#8:NC#16:pa#64:\
+	:AB=\E[4%p1%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m:\
+	:AF=\E[3%p1%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m:\
+	:..Sb=\E[4%p1%{2}%&%?%p1%{1}%&%t%{4}%|%;%?%p1%{4}%&%t%{1}%|%;%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m:\
+	:..Sf=\E[3%p1%{2}%&%?%p1%{1}%&%t%{4}%|%;%?%p1%{4}%&%t%{1}%|%;%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m:\
+	:op=\E[%?%gD%t2;%;%?%gU%t4;%;%?%gB%t5;%;%?%gR%t7;%;m:
+
+dg+color|Color info for Data General D470C terminals in ANSI mode:\
+	:Co#16:NC#53:pa#256:\
+	:AB=\E[%?%p1%{8}%<%t4%p1%e=%p1%{2}%&%?%p1%{1}%&%t%{4}%|%;%?%p1%{4}%&%t%{1}%|%;%;%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m:\
+	:AF=\E[%?%p1%{8}%<%t3%p1%e<%p1%{2}%&%?%p1%{1}%&%t%{4}%|%;%?%p1%{4}%&%t%{1}%|%;%;%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m:\
+	:..Sb=\E[%?%p1%{8}%<%t4%e=%;%p1%{2}%&%?%p1%{1}%&%t%{4}%|%;%?%p1%{4}%&%t%{1}%|%;%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m:\
+	:..Sf=\E[%?%p1%{8}%<%t3%e<%;%p1%{2}%&%?%p1%{1}%&%t%{4}%|%;%?%p1%{4}%&%t%{1}%|%;%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m:\
+	:tc=dg+color8:
+
+dgmode+color8|Color info for Data General D220/D230C terminals in DG mode:\
+	:ut:\
+	:Co#8:NC#16:pa#64:\
+	:AB=\036B%p1%{2}%&%?%p1%{1}%&%t%{4}%|%;%?%p1%{4}%&%t%{1}%|%;%{48}%+%c:\
+	:AF=\036A%p1%{2}%&%?%p1%{1}%&%t%{4}%|%;%?%p1%{4}%&%t%{1}%|%;%{48}%+%c:\
+	:Sb=\036B%+0:Sf=\036A%+0:op=\036Ad\036Bd:
+
+dgmode+color|Color info for Data General D470C terminals in DG mode:\
+	:Co#16:pa#256:\
+	:AB=\036B%p1%?%p1%{8}%<%t%{2}%&%?%p1%{1}%&%t%{4}%|%;%?%p1%{4}%&%t%{1}%|%;%;%{48}%+%c:\
+	:AF=\036A%p1%?%p1%{8}%<%t%{2}%&%?%p1%{1}%&%t%{4}%|%;%?%p1%{4}%&%t%{1}%|%;%;%{48}%+%c:\
+	:tc=dgmode+color8:
+
+dgunix+ccc|Configurable color info for DG D430C terminals in DG-UNIX mode:\
+	:cc:ut:\
+	:Co#52:NC#53:pa#26:\
+	:..Ip=\036RG0%p1%02X%p2%{256}%*%{1001}%/%02X%p3%{256}%*%{1001}%/%02X%p4%{256}%*%{1001}%/%02X%p5%{256}%*%{1001}%/%02X%p6%{256}%*%{1001}%/%02X%p7%{256}%*%{1001}%/%02X:\
+	:oc=\036RG01A00FF00000000\036RG01B00000000FF00\036RG01C007F00000000\036RG01D000000007F00:\
+	:op=\036RF4831A\036RF2E31B\036RF1D31C\036RF3F31D:\
+	:..sp=\036RG2%p1%02X:
+
+# Colors are in the order:  normal, reverse, dim, dim + reverse.
+dg+ccc|Configurable color info for DG D430C terminals in DG mode:\
+	:cc:ut:\
+	:Co#52:NC#53:pa#26:\
+	:..Ip=\036RG0%p1%{16}%/%{48}%+%c%p1%{16}%m%{48}%+%c%p2%{256}%*%{1001}%/%Pa%ga%{16}%/%{48}%+%c%ga%{16}%m%{48}%+%c%p3%{256}%*%{1001}%/%Pa%ga%{16}%/%{48}%+%c%ga%{16}%m%{48}%+%c%p4%{256}%*%{1001}%/%Pa%ga%{16}%/%{48}%+%c%ga%{16}%m%{48}%+%c%p5%{256}%*%{1001}%/%Pa%ga%{16}%/%{48}%+%c%ga%{16}%m%{48}%+%c%p6%{256}%*%{1001}%/%Pa%ga%{16}%/%{48}%+%c%ga%{16}%m%{48}%+%c%p7%{256}%*%{1001}%/%Pa%ga%{16}%/%{48}%+%c%ga%{16}%m%{48}%+%c:\
+	:oc=\036RG01\07200??00000000\036RG01;00000000??00\036RG01<007?00000000\036RG01=000000007?00:\
+	:op=\036RF4831\072\036RF2>31;\036RF1=31<\036RF3?31=:\
+	:sp=\036RG2%+^P%+^P:
+
+# The generic DG terminal type (an 8-bit-clean subset of the 6053)
+# Initialization string 1 sets:
+#	^R		- vertical scrolling enabled
+#	^C		- blinking enabled
+dg-generic|Generic Data General terminal in DG mode:\
+	:NL:am:bw:ms:xo:\
+	:co#80:li#24:\
+	:bl=^G:ce=^K:cl=^L:cm=\020%r%.%.:cr=^M:do=^Z:i1=^R^C:le=^Y:\
+	:mb=^N:me=^O^U^]:mh=^\:nd=^X:nw=^J:ps=^Q:se=^]:sf=^J:so=^\:\
+	:ue=^U:up=^W:us=^T:\
+	:tc=dgkeys+11:
+
+# (Some performance can be gained over the generic DG terminal type)
+dg6053|6053|6053-dg|dg605x|605x|605x-dg|d2|d2-dg|Data General DASHER 6053:\
+	:xo@:\
+	:ho=^P\0\0:ll=^P\0^W:tc=dg-generic:
+
+# Like 6053, but adds reverse video and more keypad and function keys.
+d200|d200-dg|Data General DASHER D200:\
+	:ho@:ll@:md=^^D^T:me=\017\025\035\036E:mr=^^D:\
+	:..sa=\036%?%p1%p3%|%p6%|%tD%eE%;%?%p2%p6%|%t\024%e\025%;%?%p4%t\016%e\017%;%?%p1%p5%|%t\034%e\035%;:\
+	:se=^^E^]:so=^^D^\:\
+	:tc=dgkeys+15:tc=dg6053:
+
+# DASHER D210 series terminals in ANSI mode.
+#	Reverse video, no insert/delete character/line, 7 bits/character only.
+#
+# Initialization string 1 sets:
+#	<0		- scrolling enabled
+#	<1		- blink enabled
+#	<4		- print characters regardless of attributes
+d210|d214|Data General DASHER D210 series:\
+	:NL:am:bw:ms:xo:\
+	:co#80:li#24:\
+	:DO=\E[%dB:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:bl=^G:cb=\E[1K:\
+	:cd=\E[J:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:cr=^M:do=\E[B:\
+	:ho=\E[H:i1=\E[<0;<1;<4l:le=^H:ll=\E[H\E[A:mb=\E[5m:\
+	:md=\E[4;7m:me=\E[m:mh=\E[2m:mr=\E[7m:nd=\E[C:nw=^J:\
+	:..sa=\E[%?%p1%p3%|%p6%|%t7;%;%?%p4%t5;%;%?%p2%p6%|%t4;%;%?%p1%p5%|%t2;%;m:\
+	:se=\E[m:sf=^J:so=\E[2;7m:ue=\E[m:up=\E[A:us=\E[4m:\
+	:tc=dgkeys+7b:
+
+# DASHER D210 series terminals in DG mode.
+# Like D200, but adds clear to end-of-screen and needs XON/XOFF.
+d210-dg|d214-dg|Data General DASHER D210 series in DG mode:\
+	:xo:\
+	:cd=^^FF:tc=d200:
+
+# DASHER D211 series terminals in ANSI mode.
+# Like the D210, but with 8-bit characters and local printer support.
+#
+# Initialization string 2 sets:
+#	\E[2;1;1;1v
+#		2;1	- 8 bit operations
+#		1;1	- 8 bit (international) keyboard language
+#	\E(B		- default primary character set (U.S. ASCII)
+#	\E)4		- default secondary character set (international)
+#	^O		- primary character set
+#
+d211|d215|Data General DASHER D211 series:\
+	:km:\
+	:is=\E[2;1;1;1v\E(B\E)4\017:ps=\E[i:tc=dgkeys+8b:tc=d210:
+
+# Initialization string 2 sets:
+#	\E[2;0;1;0v
+#		2;0	- 7 bit operations
+#		1;0	- 7 bit (native) keyboard language
+#	\E(0		- default character set (the keyboard native language)
+#	^O		- primary character set
+d211-7b|d215-7b|Data General DASHER D211 series in 7 bit mode:\
+	:km@:\
+	:is=\E[2;0;1;0v\E(0\017:tc=dgkeys+7b:tc=d211:
+
+# Like the D210 series, but adds support for 8-bit characters.
+#
+# Reset string 2 sets:
+#	^^N	- secondary character set
+#	^^FS0>	- 8 bit international character set
+#	^^O	- primary character set
+#	^^FS00	- default character set (matching the native keyboard language)
+#
+d211-dg|d215-dg|Data General DASHER D211 series in DG mode:\
+	:km:\
+	:r2=\036N\036FS0>\036O\036FS00:tc=d210-dg:
+
+d216-dg|d216e-dg|d216+dg|d216e+dg|d217-dg|Data General DASHER D216 series in DG mode:\
+	:tc=d211-dg:
+
+# Enhanced DG mode with changes to be more UNIX compatible.
+d216-unix|d216e-unix|d216+|d216e+|Data General DASHER D216+ in DG-UNIX mode:\
+	:5i:\
+	:it#8:\
+	:#2=^^Pf:#4=^^Pd:%9=^^P0:%f=^^P1:%i=^^Pc:\
+	:ac=a\177j$k"l\041m#n)q+t'u&v(w%x*:ae=\036FS00:\
+	:as=\036FS11:ce=^^PE:ch=\020%.\177:cl=^^PH:cv=\020\177%.:\
+	:do=^^PB:ho=^^PF:i1=\022\003\036P@1:i2=\036Fz0:kC=^^PH:\
+	:kE=^^PE:kd=^^PB:kh=^^PF:kl=^^PD:kr=^^PC:ku=^^PA:le=^^PD:\
+	:mb=^^PI:me=\036PJ\025\035\036E\036FS00:nd=^^PC:pf=^^Fa:\
+	:po=^^F`:ps=\036F?9:r2=\036N\036FS0E\036O\036FS00:\
+	:..sa=\036%?%p1%p3%|%p6%|%tD%eE%;%?%p2%p6%|%t\024%e\025%;\036P%?%p4%tI%eJ%;%?%p1%p5%|%t\034%e\035%;\036FS%?%p9%t11%e00%;:\
+	:sf=^J:ta=^I:up=^^PA:\
+	:tc=dgkeys+15:tc=d216-dg:
+d216-unix-25|d216+25|Data General DASHER D216+ in DG-UNIX mode with 25 lines:\
+	:li#25:\
+	:i2=\036Fz2:tc=d216+:
+
+d217-unix|Data General DASHER D217 in DG-UNIX mode:\
+	:tc=d216-unix:
+d217-unix-25|Data General DASHER D217 in DG-UNIX mode with 25 lines:\
+	:tc=d216-unix-25:
+
+# DASHER D220 color terminal in ANSI mode.
+# Like the D470C but with fewer colors and screen editing features.
+#
+# Initialization string 1 sets:
+#	\E[<0;<1;<4l
+#		<0	- scrolling enabled
+#		<1	- blink enabled
+#		<4	- print characters regardless of attributes
+#	\E[m		- all attributes off
+# Reset string 1 sets:
+#	\Ec		- initial mode defaults (RIS)
+#
+d220|Data General DASHER D220:\
+	:5i@:\
+	:AL@:DL@:al@:dl@:i1=\E[<0;<1;<4l\E[m:pf@:po@:r1=\Ec:tc=dg+color8:tc=d470c:
+
+d220-7b|Data General DASHER D220 in 7 bit mode:\
+	:5i@:\
+	:AL@:DL@:al@:dl@:i1=\E[<0;<1;<4l\E[m:pf@:po@:r1=\Ec:tc=dg+color8:tc=d470c-7b:
+
+# Initialization string 3 sets:
+#	- default cursor (solid rectangle)
+# Reset string 2 sets:
+#	^^N     - secondary character set
+#	^^FS0>  - 8 bit international character set
+#	^^O     - primary character set
+#       ^^FS00  - default character set (matching the native keyboard language)
+#
+d220-dg|Data General DASHER D220 color terminal in DG mode:\
+	:5i@:\
+	:al@:dl@:ho@:i2=\036FQ2:is@:ll@:pf@:po@:r1@:\
+	:r2=\036N\036FS0>\036O\036FS00:tc=dgmode+color8:\
+	:tc=d470c-dg:
+
+# DASHER D230C color terminal in ANSI mode.
+# Like the D220 but with minor ANSI compatibility improvements.
+#
+d230c|d230|Data General DASHER D230C:\
+	:ke=\E[2;1v:ks=\E[2;0v:mb=\E[5;50m:md=\E[4;7;50m:\
+	:me=\E[50m\E)4\017:mh=\E[2;50m:mr=\E[7;50m:nw=^M^J:\
+	:..sa=\E[50%?%p1%p3%|%p6%|%t;7%{1}%e%{0}%;%PR%?%p4%t;5%{1}%e%{0}%;%PB%?%p2%p6%|%t;4%{1}%e%{0}%;%PU%?%p1%p5%|%t;2%{1}%e%{0}%;%PDm\E)%?%p9%t6\016%e4\017%;:\
+	:se=\E[50m:so=\E[2;7;50m:ue=\E[50m:us=\E[4;50m:\
+	:tc=dgkeys+7b:tc=d220:
+
+d230c-dg|d230-dg|Data General DASHER D230C in DG mode:\
+	:tc=d220-dg:
+
+# DASHER D400/D450 series terminals.
+# These add intelligent features like insert/delete to the D200 series.
+#
+# Initialization string 2 sets:
+#	^^FQ2		- default cursor (solid rectangle)
+#	^^FW		- character protection disabled
+#	^^FJ		- normal (80 column) mode
+#	^^F\^		- horizontal scrolling enabled (for alignment)
+#	^^FX004?	- margins at columns 0 and 79
+#	^^F]		- horizontal scrolling disabled
+#	^^O		- primary character set
+#	^^FS00		- default character set (the keyboard native language)
+#	- (should reset scrolling regions, but that glitches the screen)
+# Reset string 1 sets:
+#	^^FA		- all terminal defaults except scroll rate
+# Reset string 2 sets:
+#	^^F]		- horizontal scrolling disabled
+#	^^FT0		- jump scrolling
+#
+d400|d400-dg|d450|d450-dg|Data General DASHER D400/D450 series:\
+	:5i:\
+	:ac=j$k"l\041m#n)q+t'u&v(w%x*:ae=^^O:al=^^FH:as=^^N:\
+	:ch=\020%.\177:cv=\020\177%.:dc=^^K:dl=^^FI:\
+	:eA=\036N\036FS11\036O:ei=:ho=^^FG:ic=^^J:im=:\
+	:is=\036FQ2\036FW\036FJ\036F\136\036FX004?\036F]\036O\036FS00:\
+	:ll=\036FG\027:me=\017\025\035\036E\036O:pf=^^Fa:\
+	:po=^^F`:r1=^^FA:r2=\036F]\036FT0:\
+	:..sa=\036%?%p1%p3%|%p6%|%tD%eE%;%?%p2%p6%|%t\024%e\025%;%?%p4%t\016%e\017%;%?%p1%p5%|%t\034%e\035%;\036%?%p9%tN%eO%;:\
+	:sr=^^I:ve=\036FQ2:vi=\036FQ0:\
+	:tc=d210-dg:
+
+# DASHER D410/D460 series terminals in ANSI mode.
+# These add a large number of intelligent terminal features.
+#
+# Initialization string 1 sets:
+#	\E[<0;<1;<2;<4l
+#		<0	- scrolling enabled
+#		<1	- blink enabled
+#		<2	- horizontal scrolling enabled (for alignment)
+#		<4	- print characters regardless of attributes
+#	\E[5;0v		- normal (80 column) mode
+#	\E[1;1;80w	- margins at columns 1 and 80
+#	\E[1;6;<2h
+#		1	- print all characters even if protected
+#		6	- character protection disabled
+#		<2	- horizontal scrolling disabled
+#	- (should reset scrolling regions, but that glitches the screen)
+#
+# Initialization string 2 sets:
+#	\E[3;2;2;1;1;1v
+#		3;2	- default cursor (solid rectangle)
+#		2;1	- 8 bit operations
+#		1;1	- international keyboard language
+#	\E(B		- default primary character set (U.S. ASCII)
+#	\E)4		- default secondary character set (international)
+#	^O		- primary character set
+#
+#	Reset string 1 sets:
+#	\Ec		- initial mode defaults (RIS)
+#	\E[<2h		- horizontal scrolling disabled
+#
+# Reset string 2 sets:
+#	\E[4;0;2;1;1;1v
+#		4;0	- jump scrolling
+#		2;1	- 8 bit operations
+#		1;1	- 8 bit (international) keyboard language
+#	\E(B		- default primary character set (U.S. ASCII)
+#	\E)4		- default secondary character set (international)
+#
+d410|d411|d460|d461|Data General DASHER D410/D460 series:\
+	:5i:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:IC=\E[%d@:\
+	:ac=j$k"l\041m#n)q+t'u&v(w%x*:ae=\E)4\017:al=\E[L:\
+	:as=\E)6\016:dc=\E[P:dl=\E[M:ei=:\
+	:i1=\E[<0;<1;<2;<4l\E[5;0v\E[1;1;80w\E[1;6;<2h:\
+	:ic=\E[@:im=:is=\E[3;2;2;1;1;1v\E(B\E)4\017:\
+	:me=\E[m\E)4\017:pf=\E[4i:po=\E[5i:r1=\Ec\E[<2h:\
+	:r2=\E[4;0;2;1;1;1v\E(B\E)4:\
+	:..sa=\E[%?%p1%p3%|%p6%|%t7;%;%?%p4%t5;%;%?%p2%p6%|%t4;%;%?%p1%p5%|%t2;%;m\E)%?%p9%t6\016%e4\017%;:\
+	:sr=\EM:ve=\E[3;2v:vi=\E[3;0v:\
+	:tc=d211:
+
+# Initialization string 2 sets:
+#	\E[3;2;2;0;1;0v
+#		3;2	- default cursor (solid rectangle)
+#		2;0	- 7 bit operations
+#		1;0	- 7 bit (native) keyboard language
+#	\E(0		- default character set (the keyboard native language)
+#	^O		- primary character set
+#
+# Reset string 2 sets:
+#	\E[4;0;2;0;1;0v
+#		4;0	- jump scrolling
+#		2;0	- 7 bit operations
+#		1;0	- 7 bit (native) keyboard language
+#	\E(0		- default character set (the keyboard native language)
+#
+d410-7b|d411-7b|d460-7b|d461-7b|Data General DASHER D410/D460 series in 7 bit mode:\
+	:km@:\
+	:ae=^O:as=^N:eA=\E)6:is=\E[3;2;2;0;1;0v\E(0\017:\
+	:me=\E[m\017:r2=\E[4;0;2;0;1;0v\E(0:\
+	:..sa=\E[%?%p1%p3%|%p6%|%t7;%;%?%p4%t5;%;%?%p2%p6%|%t4;%;%?%p1%p5%|%t2;%;m%?%p9%t\016%e\017%;:tc=dgkeys+7b:\
+	:tc=d410:
+
+d410-dg|d460-dg|d411-dg|d461-dg|Data General DASHER D410/D460 series in DG mode:\
+	:km:\
+	:ae=\036FS00:as=\036FS11:eA@:\
+	:me=\017\025\035\036E\036FS00:\
+	:..sa=\036%?%p1%p3%|%p6%|%tD%eE%;%?%p2%p6%|%t\024%e\025%;%?%p4%t\016%e\017%;%?%p1%p5%|%t\034%e\035%;\036FS%?%p9%t11%e00%;:tc=d400-dg:
+
+# DASHER D410/D460 series terminals in wide (126 columns) ANSI mode.
+#
+# Initialization string 1 sets:
+#	\E[<0;<1;<2;<4l
+#		<0	- scrolling enabled
+#		<1	- blink enabled
+#		<2	- horizontal scrolling enabled (for alignment)
+#		<4	- print characters regardless of attributes
+#	\E[5;1v		- compressed (135 column) mode
+#	\E[1;1;126	- margins at columns 1 and 126
+#	\E[1;6;<2h
+#		1	- print all characters even if protected
+#		6	- character protection disabled
+#		<2	- horizontal scrolling disabled
+#	- (should reset scrolling regions, but that glitches the screen)
+#
+# Reset string 1 sets:
+#	\Ec		- initial mode defaults (RIS)
+#	\E[5;1v		- compressed (135 column) mode
+#	\E[1;1;126w	- margins at columns 1 and 126
+#	\E[<2h		- horizontal scrolling disabled
+#
+d410-w|d411-w|d460-w|d461-w|Data General DASHER D410/D460 series in wide mode:\
+	:co#126:\
+	:i1=\E[<0;<1;<2;<4l\E[5;1v\E[1;1;126w\E[1;6;<2h:\
+	:r1=\Ec\E[5;1v\E[1;1;126w\E[<2h:\
+	:tc=d410:
+
+d410-7b-w|d411-7b-w|d460-7b-w|d461-7b-w|Data General DASHER D410/D460 series in wide 7 bit mode:\
+	:co#126:\
+	:i1=\E[<0;<1;<2;<4l\E[5;1v\E[1;1;126w\E[1;6;<2h:\
+	:r1=\Ec\E[5;1v\E[1;1;126w\E[<2h:\
+	:tc=d410-7b:
+
+d412-dg|d462-dg|d462e-dg|d412+dg|d462+dg|d413-dg|d463-dg|Data General DASHER D412/D462 series in DG mode:\
+	:tc=d410-dg:
+
+# These add intelligent features like scrolling regions.
+d412-unix|d462-unix|d412+|d462+|Data General DASHER D412+/D462+ series in Unix mode:\
+	:al=^^FH:ch=\036FP%2.2XFF:cl=^^FE:cm=\036FP%r%2.2X%2.2X:\
+	:cv=\036FPFF%2.2X:dc=^^K:dl=^^FI:ei=:ho=^^FG:ic=^^J:im=:\
+	:is=\036FQ5\036FW\036FJ\036F\136\036FX004F\036O\036FS00:\
+	:ll=\036FG\036PA:ps=^A:r1=\036FA\036FT0:r2=\036P@1:\
+	:rc=\036F}11:sc=\036F}10:sr=^^I:ve=\036FQ5:vi=\036FQ0:\
+	:..wi=\036FB%?%p1%t%p1%2.2X0%;%p2%p1%-%{1}%+%2.2X0%?%{23}%p2%>%t000%;\036FX%p3%2.2X%p4%2.2X:\
+	:tc=d216+:
+d412-unix-w|d462-unix-w|d412+w|d462+w|Data General DASHER D412+/D462+ series in wide Unix mode:\
+	:co#132:\
+	:is=\036FQ5\036FW\036FK\036F\136\036FX0083\036O\036FS00:\
+	:r2=\036P@1\036FK\036FX0083:\
+	:..wi=\036FB%?%p1%t%p1%2.2X1%;%p2%p1%-%{1}%+%2.2X1%?%{23}%p2%>%t001%;\036FX%p3%2.2X%p4%2.2X:tc=d412-unix:
+d412-unix-25|d462-unix-25|d412+25|d462+25|Data General DASHER D412+/D462+ series in Unix mode with 25 lines:\
+	:li#25:\
+	:i2=\036Fz2:\
+	:..wi=\036FB%?%p1%t%p1%2.2X0%;%p2%p1%-%{1}%+%2.2X0%?%{24}%p2%>%t000%;\036FX%p3%2.2X%p4%2.2X:tc=d462+:
+d412-unix-s|d462-unix-s|d412+s|d462+s|Data General DASHER D412+/D462+ in Unix mode with status line:\
+	:es:hs:\
+	:cl=\036FG\036PH:fs=\036F}01\022:\
+	:i2=\036Fz2\036F}00\036FB180000\036F}01:ll@:\
+	:ts=\036F}00\036FP%p1%2.2X18\036PG:\
+	:..wi=\036FB%?%p1%t%p1%2.2X0%;%p2%p1%-%{1}%+%2.2X0%?%{23}%p2%>%t%{23}%p2%-%2.2X0%;000\036FX%p3%2.2X%p4%2.2X:tc=d462+:
+
+#	Relative cursor motions are confined to the current window,
+#	which is not what the scrolling region specification expects.
+#	Thus, relative vertical cursor positioning must be deleted.
+d412-unix-sr|d462-unix-sr|d412+sr|d462+sr|Data General DASHER D412+/D462+ in Unix mode with scrolling region:\
+	:..cs=\036FB%?%p1%t%p1%2.2X0%;%p2%p1%-%{1}%+%2.2X0%?%{23}%p2%>%t000%;:\
+	:do@:ll@:up@:\
+	:tc=d462+:
+
+d413-unix|d463-unix|Data General DASHER D413/D463 series in DG-UNIX mode:\
+	:tc=d412-unix:
+d413-unix-w|d463-unix-w|Data General DASHER D413/D463 series in wide DG-UNIX mode:\
+	:tc=d412-unix-w:
+d413-unix-25|d463-unix-25|Data General DASHER D413/D463 series in DG-UNIX mode with 25 lines:\
+	:tc=d412-unix-25:
+d413-unix-s|d463-unix-s|Data General DASHER D413/D463 in DG-UNIX mode with status line:\
+	:tc=d412-unix-s:
+d413-unix-sr|d463-unix-sr|Data General DASHER D413/D463 in DG-UNIX mode with scrolling region:\
+	:tc=d412-unix-sr:
+
+d414-unix|d464-unix|Data General D414/D464 in DG-UNIX mode:\
+	:tc=d413-unix:
+d414-unix-w|d464-unix-w|Data General D414/D464 in wide DG-UNIX mode:\
+	:tc=d413-unix-w:
+d414-unix-25|d464-unix-25|Data General D414/D464 in DG-UNIX mode with 25 lines:\
+	:tc=d413-unix-25:
+d414-unix-s|d464-unix-s|Data General D414/D464 in DG-UNIX mode with status line:\
+	:tc=d413-unix-s:
+d414-unix-sr|d464-unix-sr|Data General D414/D464 in DG-UNIX mode with scrolling region:\
+	:tc=d413-unix-sr:
+
+d430c-dg|d430-dg|Data General D430C in DG mode:\
+	:tc=d413-dg:tc=dg+fixed:
+d430c-dg-ccc|d430-dg-ccc|Data General D430C in DG mode with configurable colors:\
+	:tc=d413-dg:tc=dg+ccc:
+
+d430c-unix|d430-unix|Data General D430C in DG-UNIX mode:\
+	:tc=d413-unix:tc=dgunix+fixed:
+d430c-unix-w|d430-unix-w|Data General D430C in wide DG-UNIX mode:\
+	:tc=d413-unix-w:tc=dgunix+fixed:
+d430c-unix-25|d430-unix-25|Data General D430C in DG-UNIX mode with 25 lines:\
+	:tc=d413-unix-25:tc=dgunix+fixed:
+d430c-unix-s|d430-unix-s|Data General D430C in DG-UNIX mode with status line:\
+	:tc=d413-unix-s:tc=dgunix+fixed:
+d430c-unix-sr|d430-unix-sr|Data General D430C in DG-UNIX mode with scrolling region:\
+	:tc=d413-unix-sr:tc=dgunix+fixed:
+d430c-unix-ccc|d430-unix-ccc|Data General D430C in DG-UNIX mode with configurable colors:\
+	:tc=d413-unix:tc=dgunix+ccc:
+d430c-unix-w-ccc|d430-unix-w-ccc|Data General D430C in wide DG-UNIX mode with configurable colors:\
+	:tc=d413-unix-w:tc=dgunix+ccc:
+d430c-unix-25-ccc|d430-unix-25-ccc|Data General D430C in DG-UNIX mode with 25 lines and configurable colors:\
+	:tc=d413-unix-25:tc=dgunix+ccc:
+d430c-unix-s-ccc|d430-unix-s-ccc|Data General D430C in DG-UNIX mode with status line and configurable colors:\
+	:tc=d413-unix-s:tc=dgunix+ccc:
+d430c-unix-sr-ccc|d430-unix-sr-ccc|Data General D430C in DG-UNIX mode with scrolling region and configurable colors:\
+	:tc=d413-unix-sr:tc=dgunix+ccc:
+
+# dg450 from Cornell (not official)
+dg450|dg6134|data general 6134:\
+	:le@:nd=^X:tc=dg200:
+
+# Not official...
+# Note: lesser Dasher terminals will not work with vi because vi insists upon
+# having a command to move straight down from any position on the bottom line
+# and scroll the screen up, or a direct vertical scroll command.  The 460 and
+# above have both, the D210/211, for instance, has neither.  We must use ANSI
+# mode rather than DG mode because standard UNIX tty drivers assume that ^H is
+# backspace on all terminals.  This is not so in DG mode.
+# (dg460-ansi: removed obsolete ":kn#6:"; also removed ":mu=\EW:", on the
+# grounds that there is no matching ":ml:"
+# fixed garbled ":k9=\E[00\:z:" capability -- esr)
+dg460-ansi|Data General Dasher 460 in ANSI-mode:\
+	:am:bs:ms:ul:\
+	:co#80:it#8:li#24:\
+	:al=\E[L:cd=\E[J:ce=\E[K:cl=\E[2J:cm=\E[%i%2;%2H:dc=\E[P:\
+	:dl=\E[M:do=\E[B:ei=:ho=\E[H:ic=\E[@:im=:is=^^F@:k0=\E[001z:\
+	:k1=\E[002z:k2=\E[003z:k3=\E[004z:k4=\E[005z:k5=\E[006z:\
+	:k6=\E[007z:k7=\E[008z:k8=\E[009z:k9=\E[010z:kb=\E[D:\
+	:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:l0=f1:l1=f2:l2=f3:\
+	:l3=f4:l4=f5:l5=f6:l6=f7:l7=f8:l9=f10:le=^H:mb=\E[5m:me=\E[m:\
+	:mh=\E[2m:mr=\E[7m:nd=\E[C:nl=\ED:se=\E[m:sf=\E[S:so=\E[7m:\
+	:sr=\E[T:ta=^I:ue=\E[05:up=\E[A:us=\E[4m:
+
+# DASHER D470C color terminal in ANSI mode.
+# Like the D460 but with 16 colors and without a compressed mode.
+#
+# Initialization string 1 sets:
+#	\E[<0;<1;<2;<4l
+#		<0	- scrolling enabled
+#		<1	- blink enabled
+#		<2	- horizontal scrolling enabled (for alignment)
+#		<4	- print characters regardless of attributes
+#	\E[1;1;80w	- margins at columns 1 and 80
+#	\E[1;6;<2h
+#		1	- print all characters even if protected
+#		6	- character protection disabled
+#		<2	- horizontal scrolling disabled
+#	- (should reset scrolling regions, but that glitches the screen)
+#
+d470c|d470|Data General DASHER D470C:\
+	:i1=\E[<0;<1;<2;<4l\E[1;1;80w\E[1;6;<2h:\
+	:..sa=\E[%?%p1%p3%|%p6%|%t7;%{1}%e%{0}%;%PR%?%p4%t5;%{1}%e%{0}%;%PB%?%p2%p6%|%t4;%{1}%e%{0}%;%PU%?%p1%p5%|%t2;%{1}%e%{0}%;%PDm\E)%?%p9%t6\016%e4\017%;:tc=dg+color:\
+	:tc=d460:
+
+d470c-7b|d470-7b|Data General DASHER D470C in 7 bit mode:\
+	:i1=\E[<0;<1;<2;<4l\E[1;1;80w\E[1;6;<2h:\
+	:..sa=\E[%?%p1%p3%|%p6%|%t7;%{1}%e%{0}%;%PR%?%p4%t5;%{1}%e%{0}%;%PB%?%p2%p6%|%t4;%{1}%e%{0}%;%PU%?%p1%p5%|%t2;%{1}%e%{0}%;%PDm%?%p9%t\016%e\017%;:tc=dg+color:\
+	:tc=d460-7b:
+
+# Initialization string 2 sets:
+#	^^FQ2		- default cursor (solid rectangle)
+#	^^FW		- character protection disabled
+#	^^F\^		- horizontal scrolling enabled (for alignment)
+#	^^FX004?	- margins at columns 0 and 79
+#	^^F]		- horizontal scrolling disabled
+#	^^O		- primary character set
+#	^^FS00		- default character set (the keyboard native language)
+#	- (should reset scrolling regions, but that glitches the screen)
+#
+d470c-dg|d470-dg|Data General DASHER D470C in DG mode:\
+	:is=\036FQ2\036FW\036F\136\036FX004?\036F]\036O\036FS00:\
+	:tc=dgmode+color:tc=d460-dg:
+
+# DASHER D555 terminal in ANSI mode.
+# Like a D411, but has an integrated phone.
+d555|Data General DASHER D555:\
+	:tc=d411:
+d555-7b|Data General DASHER D555 in 7-bit mode:\
+	:tc=d411-7b:
+d555-w|Data General DASHER D555 in wide mode:\
+	:tc=d411-w:
+d555-7b-w|Data General DASHER D555 in wide 7-bit mode:\
+	:tc=d411-7b-w:
+d555-dg|Data General DASHER D555 series in DG mode:\
+	:tc=d411-dg:
+
+# DASHER D577 terminal in ANSI mode.
+# Like a D411, but acts as a keyboard for serial printers ("KSR" modes).
+d577|Data General DASHER D577:\
+	:tc=d411:
+d577-7b|Data General DASHER D577 in 7-bit mode:\
+	:tc=d411-7b:
+d577-w|Data General DASHER D577 in wide mode:\
+	:tc=d411-w:
+d577-7b-w|Data General DASHER D577 in wide 7-bit mode:\
+	:tc=d411-7b-w:
+
+d577-dg|d578-dg|Data General DASHER D577/D578 series in DG mode:\
+	:tc=d411-dg:
+
+# DASHER D578 terminal.
+# Like a D577, but without compressed mode; like a D470C in this respect.
+#
+# Initialization string 1 sets:
+#	\E[<0;<1;<2;<4l
+#		<0	- scrolling enabled
+#		<1	- blink enabled
+#		<2	- horizontal scrolling enabled (for alignment)
+#		<4	- print characters regardless of attributes
+#	\E[1;1;80w	- margins at columns 1 and 80
+#	\E[1;6;<2h
+#		1	- print all characters even if protected
+#		6	- character protection disabled
+#		<2	- horizontal scrolling disabled
+#	- (should reset scrolling regions, but that glitches the screen)
+#
+d578|Data General DASHER D578:\
+	:i1=\E[<0;<1;<2;<4l\E[1;1;80w\E[1;6;<2h:tc=d577:
+d578-7b|Data General DASHER D578 in 7-bit mode:\
+	:i1=\E[<0;<1;<2;<4l\E[1;1;80w\E[1;6;<2h:tc=d577-7b:
+
+# Here are some older Dasher entries from the Berkeley termcap file.
+
+# According to the 4.4BSD termcap file, the dg200 :cm: should be the
+# termcap equivalent of \020%p2%{128}%+%c%p1%{128}%+%c (in termcap
+# notation that's "^P%r%+\200%+\200").  Those \200s are suspicious,
+# maybe they were originally nuls (which would fit).
+dg200|data general dasher 200:\
+	:NL:am:bs:bw:\
+	:co#80:li#24:\
+	:bl=^G:ce=^K:cl=^L:cm=\020%r%.%.:cr=^M:do=^Z:ho=^H:k0=^^z:\
+	:k1=^^q:k2=^^r:k3=^^s:k4=^^t:k5=^^u:k6=^^v:k7=^^w:k8=^^x:\
+	:k9=^^y:kd=^Z:kh=^H:kl=^Y:kr=^X:ku=^W:l0=f10:le=^Y:nd=^X:\
+	:nw=^J:se=^^E:sf=^J:so=^^D:ue=^U:up=^W:us=^T:
+# Data General 210/211 (and 410?)	from Lee Pearson (umich!lp) via BRL
+dg210|dg-ansi|Data General 210/211:\
+	:am:\
+	:co#80:li#24:\
+	:cd=\E[J:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:do=\E[B:ho=\E[H:\
+	:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:nl=\E[B:\
+	:nw=\r\E[H\E[A\n:se=\E[0;m:so=\E[7;m:ue=\E[0;m:up=\E[A:\
+	:us=\E[4;m:
+# From: Peter N. Wan <ihnp4!gatech!gacsr!wan>
+# courtesy of Carlos Rucalde of Vantage Software, Inc.
+# (dg211: this had :cm=\020%r%.%:., which was an ancient termcap hangover.
+# I suspect the d200 function keys actually work on the dg211, check it out.)
+dg211|Data General d211:\
+	:k0@:k1@:k2@:k3@:k4@:k5@:k6@:k7@:k8@:k9@:kb=^Y:l0@:nw=^M^Z:\
+	:se=\036E\0/>:sf@:so=5\036D:ta=^I:te=^L:ti=^L^R:ve=^L:\
+	:vs=^L^R:\
+	:tc=dg200:
+
+# From: Wayne Throop <mcnc!rti-sel!rtp47!throopw> (not official)
+# Data General 605x     
+# Ought to work for a Model 6242, Type D210 as well as a 605x.
+# Note that the cursor-down key transmits ^Z.  Job control users, beware!
+# This also matches a posted description of something called a `Dasher 100'
+# so there's a dg100 alias here. 
+# (dg6053: the 4.4BSD file had :le=^H:, :do=^J:, :nd=^S:. -- esr) 
+dg6053-old|dg100|data general 6053:\
+	:am:bs:bw:ul:\
+	:co#80:li#24:\
+	:bc=^Y:bl=^G:ce=^K:cl=^L:cm=\020%r%.%.:cr=^M:do=^Z:ho=^H:\
+	:is=^R:k0=^^q:k1=^^r:k2=^^s:k3=^^t:k4=^^u:k5=^^v:k6=^^w:\
+	:k7=^^x:k8=^^y:k9=^^z:kb=^Y:kd=^Z:kh=^H:kl=^Y:kr=^X:ku=^W:\
+	:le=^Y:nd=^X:se=\0^^E:so=\0\0\0\0\0\036D:ta=^I:te=^L:\
+	:ti=^L^R:ue=^U:up=^W:us=^T:ve=^L:vs=^L^R:
+
+#### Datamedia (dm)
+#
+# Datamedia was headquartered in Nashua, New Hampshire until it went 
+# out of business in 1993, but the ID plates on the terminals referred
+# to the factory in Pennsauken, NJ.  The factory was sold to a PCB board
+# manufacturer which threw out all information about the terminals.
+#
+
+cs10|colorscan|Datamedia Color Scan 10:\
+	:ms:\
+	:co#80:li#24:\
+	:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%02;%02H:cr=^M:\
+	:do=^J:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:kd=\E[B:kl=\E[D:\
+	:kr=\E[C:ku=\E[A:le=^H:me=\E[m:nd=\E[C:se=\E[m:sf=^J:\
+	:so=\E[7m:ue=\E[m:up=\E[A:us=\E[4m:
+cs10-w|Datamedia Color Scan 10 with 132 columns:\
+	:co#132:\
+	:cm=\E[%i%02;%03H:tc=cs10:
+
+# (dm1520: removed obsolete ":ma=^\ ^_^P^YH:" -- esr)
+dm1520|dm1521|datamedia 1520:\
+	:am:bs:xn:\
+	:co#80:it#8:li#24:\
+	:bl=^G:cd=^K:ce=^]:cl=^L:cm=\036%r%+ %+ :cr=^M:do=^J:ho=^Y:\
+	:kd=^J:kh=^Y:kl=^H:kr=^\:ku=^_:le=^H:nd=^\:sf=^J:ta=^I:up=^_:
+# dm2500: this terminal has both :IC: and :im:. Applications using 
+# termcap/terminfo directly (rather than through ncurses) might be confused.
+dm2500|datamedia2500|datamedia 2500:\
+	:bs:nc:\
+	:co#80:li#24:\
+	:al=\020\n\030\035\030\035:bl=^G:ce=^W:cl=^^^^\177:\
+	:cm=\014%r%n%.%.:dc=\020\010\030\035:\
+	:dl=\020\032\030\035:dm=^P:do=^J:ed=^X^]:\
+	:ei=\377\377\030\035:ho=^B:ic=\020\034\030\035:im=^P:\
+	:le=^H:nd=^\:pc=\377:se=^X^]:sf=^J:so=^N:up=^Z:
+# dmchat is like DM2500, but DOES need "all that padding" (jcm 1/31/82)
+# also, has a meta-key.
+# From: <goldberger@su-csli.arpa>
+# (dmchat: ":MT:" changed to ":km:" -- esr)
+dmchat|dmchat version of datamedia 2500:\
+	:km:\
+	:al=1*\020\n\030\035\030\035:dl=2\020\032\030\035:tc=dm2500:
+# (dm3025: ":MT:" changed to ":km:" -- esr)
+dm3025|datamedia 3025a:\
+	:bs:km:\
+	:co#80:it#8:li#24:\
+	:al=\EP\n\EQ:bl=^G:cd=\EJ:ce=\EK:cl=\EM:cm=\EY%r%+ %+ :\
+	:cr=^M:dc=\010:dl=\EP\EA\EQ:dm=\EP:do=^J:ed=\EQ:ei=\EQ:\
+	:ho=\EH:im=\EP:ip=:is=\EQ\EU\EV:le=^H:nd=\EC:se=\EO0:sf=^J:\
+	:so=\EO1:ta=^I:up=\EA:
+dm3045|datamedia 3045a:\
+	:am:bs:eo:km@:ul:xn:\
+	:al@:dc=\EB:dl@:dm@:ed@:ei=\EP:is=\EU\EV:k0=\Ey\r:k1=\Ep\r:\
+	:k2=\Eq\r:k3=\Er\r:k4=\Es\r:k5=\Et\r:k6=\Eu\r:k7=\Ev\r:\
+	:k8=\Ew\r:k9=\Ex\r:kh=\EH:kr=\EC:ku=\EA:pc=\177:se@:so@:\
+	:tc=dm3025:
+# Datamedia DT80 soft switches:
+# 1	0=Jump  1=Smooth
+# 	Autorepeat 	0=off  1=on
+# 	Screen		0=Dark 1=light
+# 	Cursor		0=u/l  1=block
+# 
+# 2	Margin Bell	0=off  1=on
+# 	Keyclick	0=off  1=on
+# 	Ansi/VT52	0=VT52 1=Ansi
+# 	Xon/Xoff	0=Off  1=On
+# 
+# 3	Shift3		0=Hash 1=UK Pound
+# 	Wrap		0=Off  1=On
+# 	Newline		0=Off  1=On
+# 	Interlace	0=Off  1=On
+# 	
+# 4	Parity		0=Odd  1=Even
+# 	Parity		0=Off  1=On
+# 	Bits/Char	0=7    1=8
+# 	Power		0=60Hz 1=50Hz
+# 
+# 5	Line Interface  0=EIA  1=Loop
+# 	Aux Interface   0=EIA  1=Loop
+# 	Local Copy    	0=Off  1=On	
+# 	Spare
+# 
+# 6	Aux Parity	0=Odd  1=Even
+# 	Aux Parity	0=Off  1=On
+# 	Aux Bits/Char   0=7    1=8
+# 	CRT Saver	0=Off  1=On
+# dm80/1 is a vt100 lookalike, but it doesn't seem to need any padding.
+dm80|dmdt80|dt80|datamedia dt80/1:\
+	:cd=\E[J:ce=\E[K:cl=\E[2J\E[H:cm=%i\E[%d;%dH:do=^J:\
+	:ho=\E[H:me=\E[m:nd=\E[C:pf=\E[4i:po=\E[5i:ps=\E[0i:\
+	:se=\E[m:so=\E[7m:sr=\EM:ue=\E[m:up=\E[A:us=\E[4m:\
+	:tc=vt100:
+# except in 132 column mode, where it needs a little padding.
+# This is still less padding than the vt100, and you can always turn on
+# the ^S/^Q handshaking, so you can use vt100 flavors for things like
+# reverse video.
+dm80w|dmdt80w|dt80w|datamedia dt80/1 in 132 char mode:\
+	:co#132:\
+	:cd=20\E[0J:ce=20\E[0K:cl=50\E[H\E[2J:cm=5\E[%i%d;%dH:\
+	:do=^J:up=5\E[A:\
+	:tc=dm80:
+# From: Adam Thompson <athompso@pangea.ca> Sept 10 1995
+dt80-sas|Datamedia DT803/DTX for SAS usage:\
+	:am:bw:\
+	:co#80:li#24:\
+	:ac=``a1fxgqh0jYk?lZm@nEooppqDrrsstCu4vAwBx3yyzz{{||}}~~:\
+	:ae=\EG:al=\EL:as=\EF:bl=^G:cd=^K:ce=^]:cl=^L:\
+	:cm=\E=%r%+ %+ :cr=^M:\
+	:..cs=\E=%p1%{32}%+%c%{32}%c\E#1\E=%p2%{32}%+%c%{32}%c\E#2:\
+	:ct=\E'0:dl=\EM:do=\EB:ff=^L:ho=^Y:is=\E)0\E<\EP\E'0\E$2:\
+	:kC=^L:kE=^]:kS=^K:kd=^J:kh=^Y:kl=^H:kr=^\:ku=^_:le=^H:me=^X:\
+	:mr=\E$2\004:nd=^\:pf=^O:po=^N:se=^X:sf=\EB:so=\E$2\004:\
+	:sr=\EI:st=\E'1:ta=^I:up=^_:
+
+# Datamedia Excel 62, 64 from Gould/SEL UTX/32 via BRL
+# These aren't end-all Excel termcaps; but do insert/delete char/line
+# and name some of the extra function keys.  (Mike Feldman ccvaxa!feldman)
+# The naming convention has been bent somewhat, with the use of E? (where
+# E is for 'Excel') as # a name.  This was done to distinguish the entries
+# from the other Datamedias in use here, and yet to associate a model of
+# the Excel terminals with the regular datamedia terminals that share
+# major characteristics.
+excel62|excel64|datamedia Excel 62:\
+	:dc=\E[P:ei=\E[4l:im=\E[4h:k5=\EOu:k6=\EOv:k7=\EOw:k8=\EOx:\
+	:k9=\EOy:kb=^H:kd=^J:kl=^H:\
+	:tc=dt80:
+excel62-w|excel64-w|datamedia Excel 62 in 132 char mode:\
+	:dc=\E[P:ei=\E[4l:im=\E[4h:k5=\EOu:k6=\EOv:k7=\EOw:k8=\EOx:\
+	:k9=\EOy:kb=^H:kd=^J:kl=^H:\
+	:tc=dt80w:
+excel62-rv|excel64-rv|datamedia Excel 62 in reverse video mode:\
+	:dc=\E[P:ei=\E[4l:im=\E[4h:k5=\EOu:k6=\EOv:k7=\EOw:k8=\EOx:\
+	:k9=\EOy:kb=^H:kd=^J:kl=^H:vb=\E[?5l\E[?5h:\
+	:tc=dt80:
+
+#### Falco
+#
+#	Falco Data Products
+#	440 Potrero Avenue
+#	Sunnyvale, CA 940864-196
+#	Vox: (800)-325-2648
+#	Fax: (408)-745-7860
+#	Net: techsup@charm.sys.falco.com
+#
+# Current Falco models as of 1995 are generally ANSI-compatible and support
+# emulations of DEC VT-series, Wyse, and Televideo types.
+#
+
+# Test version for Falco ts-1. See <arpavax.hickman@ucb> for info
+# This terminal was released around 1983 and was discontinued long ago.
+# The standout and underline highlights are the same.
+falco|ts1|ts-1|falco ts-1:\
+	:am:bs:\
+	:co#80:it#8:li#24:\
+	:al=\EE:bl=^G:cd=\EY:ce=\ET\EG0\010:cl=\E*:cm=\E=%+ %+ :\
+	:cr=^M:dc=\EW:dl=\ER:do=^J:ei=\Er:ho=^^:im=\Eq:is=\Eu\E3:\
+	:k0=^A0\r:kd=^J:kl=^H:kr=^L:ku=^K:le=^H:me=\Eg0:nd=^L:\
+	:se=\Eg0:sf=^J:so=\Eg1:ta=^I:ue=\Eg0:up=^K:us=\Eg1:
+falco-p|ts1p|ts-1p|falco ts-1 with paging option:\
+	:am:bs:da:db:mi:ms:ul:\
+	:co#80:it#8:li#24:\
+	:al=\EE:bl=^G:bt=\EI:cd=\EY:ce=\ET\EG0\010\Eg0:cl=\E*:\
+	:cm=\E=%+ %+ :cr=^M:dc=\EW:dl=\ER:do=\E[B:ei=\Er:im=\Eq:\
+	:is=\EZ\E3\E_c:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:le=^H:me=\Eg0:nd=\E[C:se=\Eg0:sf=^J:so=\Eg4:ta=^I:te=\E_b:\
+	:ti=\E_d:ue=\Eg0:up=\E[A:us=\Eg1:
+# (ts100: I added <rmam>/<smam> based on the init string -- esr)
+ts100|ts100-sp|falco ts100-sp:\
+	:am:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:vt#3:\
+	:@8=\EOM:DO=\E[%dB:K1=\EOq:K2=\EOr:K3=\EOs:K4=\EOp:K5=\EOn:\
+	:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:UP=\E[%dA:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=^O:al=\E~E:as=^N:bl=^G:cb=\E[1K:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:ct=\E[3g:dc=\E~W:dl=\E~R:do=^J:eA=\E(B\E)0:ei=:ho=\E[H:\
+	:i1=\E~)\E~ea:ic=\E~Q:im=:k0=\EOy:k1=\EOP:k2=\EOQ:k3=\EOR:\
+	:k4=\EOS:k5=\EOt:k6=\EOu:k7=\EOv:k8=\EOl:k9=\EOw:k;=\EOx:\
+	:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:\
+	:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:me=\E[m\017:mr=\E[7m:\
+	:nd=\E[C:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\E8:\
+	:..sa=\E[0%?%p1%p6%|%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t\016%e\017%;:\
+	:sc=\E7:se=\E[m:sf=^J:so=\E[1;7m:sr=\EM:st=\EH:ta=^I:\
+	:ue=\E[m:up=\E[A:us=\E[4m:
+ts100-ctxt|falco ts-100 saving context:\
+	:te=\E~_b:ti=\E~_d\E[2J:tc=ts100:
+
+#### Florida Computer Graphics
+#
+
+# Florida Computer Graphics Beacon System, using terminal emulator program
+# "host.com", as provided by FCG.  This description is for an early release
+# of the "host" program.  Known bug: :cd: clears the whole screen, so it's
+# commented out.
+
+# From: David Bryant <cbosg!djb> 1/7/83
+beacon|FCG Beacon System:\
+	:am:da:db:\
+	:co#80:li#32:\
+	:al=\EE:bl=\ESTART\r\E37\r\EEND\r:ce=\ET:cl=\EZ:\
+	:cm=\E=%+ %+ :cr=^M:dc=\EW:dl=\ER:do=^J:ei=:ho=\EH:ic=\EQ:\
+	:im=:le=^H:mb=\ESTART\r\E61\0541\r\EEND\r:\
+	:me=\ESTART\r\E78\r\E70\0540\r\EEND\r:\
+	:mr=\ESTART\r\E59\0541\r\EEND\r:nd=\EV:\
+	:se=\ESTART\r\E70\0540\r\EEND\r:sf=^J:\
+	:so=\ESTART\r\E70\0546\r\EEND\r:te=:\
+	:ti=\ESTART\r\E2\0540\r\E12\r\EEND\r:\
+	:ue=\ESTART\r\E60\0540\r\EEND\r:up=\EU:\
+	:us=\ESTART\r\E60\0541\r\EEND\r:
+
+#### Fluke
+#
+
+# The f1720a differences from ANSI: no auto margin, destructive 
+# tabs, # of lines, funny highlighting and underlining
+f1720|f1720a|fluke 1720A:\
+	:xt:\
+	:co#80:li#16:sg#1:\
+	:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:\
+	:do=\E[B:is=\E[H\E[2J:kd=^]:kl=^_:kr=^^:ku=^\:le=^H:me=\E[m:\
+	:nd=\E[C:se=\E[m:sf=\ED:so=\E[7m:sr=\EM:ue=\E[m:up=\E[A:\
+	:us=\E[4m:
+
+#### Liberty Electronics (Freedom)
+#
+#	Liberty Electronics
+#	48089 Fremont Blvd
+#	Fremont CA 94538
+#	Vox: (510)-623-6000
+#	Fax: (510)-623-7021
+
+# From: <faletti@berkeley.edu>
+# (f100: added empty <acsc> to suppress a tic warning;
+# made this relative to adm+sgr -- note that <invis> isn't
+# known to work for f100 but does on the f110. --esr)
+f100|freedom|freedom100|freedom model 100:\
+	:am:bs:bw:hs:mi:ms:xo:\
+	:co#80:li#24:\
+	:ac=:ae=\E$:al=\EE:as=\E%:bl=^G:bt=\EI:cd=\EY:ce=\ET:\
+	:ch=\E]%+ :cl=^Z:cm=\E=%+ %+ :cr=^M:ct=\E3:cv=\E[%+ :\
+	:dc=\EW:dl=\ER:do=^J:ds=\Eg\Ef\r:ei=\Er:fs=^M:ho=^^:im=\Eq:\
+	:ip=:is=\Eg\Ef\r\Ed:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:\
+	:k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:k;=^AI\r:\
+	:kB=\EI:kb=^H:kd=^V:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:nd=^L:sf=^J:\
+	:sr=\Ej:st=\E1:ta=^I:ts=\Eg\Ef:up=^K:vb=\Eb\Ed:\
+	:tc=adm+sgr:
+f100-rv|freedom-rv|freedom 100 in reverse video:\
+	:is=\Eg\Ef\r\Eb:vb=\Ed\Eb:tc=f100:
+# The f110 and f200 have problems with vi(1).  They use the ^V
+# code for the down cursor key. When kcud1 is defined in terminfo
+# as ^V, the Control Character Quoting capability (^V in insert mode)
+# is lost! It cannot be remapped in vi because it is necessary to enter
+# a ^V to to quote the ^V that is being remapped!!!
+# 
+# f110/f200 users will have to decide whether
+# to lose the down cursor key or the quoting capability. We will opt
+# initially for leaving the quoting capability out, since use of VI
+# is not generally applicable to most interactive applications
+# (f110: added :ta:, :kh: & <kcbt> from f100 -- esr)
+f110|freedom110|Liberty Freedom 110:\
+	:bw@:es:\
+	:it#8:ws#80:\
+	:ae=\E%%:al=\EE:as=\E$:dl=\ER:do=^V:ds=\Ef\r:ei=\Er\EO:\
+	:im=\EO\Eq:ip@:is@:k0=^AI\r:k;@:kA=\EE:kC=^^:kD=\EW:kE=\ET:\
+	:kI=\EQ:kL=\ER:kS=\EY:mb=\EG2:md=\EG0:mh=\EG@:pf=\Ea:po=\E`:\
+	:so=\EG<:sr=\EJ:ts=\Ef:vb=\Eb\Ed:ve=\E.2:vi=\E.1:vs=\E.2:\
+	:tc=f100:
+f110-14|Liberty Freedom 110 14inch:\
+	:dc@:tc=f110:
+f110-w|Liberty Freedom 110 - 132 cols:\
+	:co#132:tc=f110:
+f110-14w|Liberty Freedom 110 14in/132 cols:\
+	:co#132:\
+	:dc@:tc=f110:
+# (f200: added <acsc> to suppress tic warnings re :as:/:ae: --esr)
+f200|freedom200|Liberty Freedom 200:\
+	:am:bs:es:hs:mi:ms:xo:\
+	:co#80:it#8:li#24:ws#80:\
+	:ac=:ae=\E%%:al=\EE:as=\E$:bl=^G:bt=\EI:cd=\EY:ce=\ET:\
+	:ch=\E]%+ :cl=^Z:cm=\E=%+ %+ :cr=^M:cs=\Em0%+ %+ :ct=\E3:\
+	:cv=\E[%+ :dc=\EW:dl=\ER:do=^V:ds=\Ef\r:ei=\Er:fs=^M:ho=^^:\
+	:im=\Eq:k0=^AI\r:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:\
+	:k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:kA=\EE:kC=^^:\
+	:kD=\EW:kE=\ET:kI=\EQ:kL=\ER:kS=\EY:kb=^H:kd=^V:kl=^H:kr=^L:\
+	:ku=^K:le=^H:mb=\EG2:md=\EG0:mh=\EG@:nd=^L:pf=\Ea:po=\E`:\
+	:sf=^J:so=\EG<:sr=\EJ:st=\E1:ts=\Ef:up=^K:vb=\Eo\En:ve=\E.1:\
+	:vi=\E.0:vs=\E.1:\
+	:tc=adm+sgr:
+f200-w|Liberty Freedom 200 - 132 cols:\
+	:co#132:tc=f200:
+# The f200 has the ability to reprogram the down cursor key. The key is
+# reprogrammed to ^J (linefeed). This value is remembered in non-volatile RAM,
+# so powering the terminal off and on will not cause the change to be lost.
+f200vi|Liberty Freedom 200 for vi:\
+	:kd=^J:vb=\Eb\Ed:tc=f200:
+f200vi-w|Liberty Freedom 200 - 132 cols for vi:\
+	:co#132:tc=f200vi:
+
+#### GraphOn (go)
+#
+#	Graphon Corporation
+#	544 Division Street
+#	Campbell, CA 95008
+#	Vox: (408)-370-4080
+#	Fax: (408)-370-5047
+#	Net: troy@graphon.com (Troy Morrison)
+#
+#
+# The go140 and go225 have been discontinued.  GraphOn now makes X terminals,
+# including one odd hybrid that starts out life on power-up as a character
+# terminal, than can be switched to X graphics mode (driven over the serial
+# line) by an escape sequence.  No info on this beast yet.
+# (go140: I added <rmam>/<smam> based on the init string -- esr)
+go140|graphon go-140:\
+	:bs:\
+	:co#80:it#8:li#24:\
+	:RA=\E[?7l:SA=\E[?7h:al=\E[L:cd=10\E[J:ce=\E[K:\
+	:cl=10\E[H\E[2J:cm=\E[%i%2;%2H:dc=\E[P:dl=\E[M:ei=\E[4l:\
+	:if=/usr/share/tabset/vt100:im=\E[4h:\
+	:is=\E<\E=\E[?3l\E[?7l\E(B\E[J\E7\E[;r\E8\E[m\E[q:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:kd=\EOB:ke=\E[?1l\E>:\
+	:kh=\E[H:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:\
+	:me=\E[m:nd=\E[C:se=\E[m:so=\E[7m:sr=\EM:ta=^I:ue=\E[m:\
+	:up=\E[A:us=\E[4m:
+go140w|graphon go-140 in 132 column mode:\
+	:am:\
+	:co#132:\
+	:is=\E<\E=\E[?3h\E[?7h\E(B\E[J\E7\E[;r\E8\E[m\E[q:tc=go140:
+# Hacked up vt200 termcap to handle GO-225/VT220
+# From: <edm@nwnexus.WA.COM>
+# (go225: I added <rmam>/<smam> based on the init string -- esr)
+go225|go-225|Graphon 225:\
+	:am:bs:mi:xn:\
+	:co#80:it#8:li#25:vt#3:\
+	:RA=\E[?7l:SA=\E[?7h:al=\E[L:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cs=\E[%i%d;%dr:dc=\E[P:dl=\E[M:do=^J:\
+	:ei=\E[4l:ho=\E[H:im=\E[4h:\
+	:is=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:k1=\EOP:k2=\EOQ:\
+	:k3=\EOR:k4=\EOS:kb=^H:kd=\E[B:ke=\E>:kh=\E[H:kl=\E[D:\
+	:kr=\E[C:ks=\E=:ku=\E[A:le=^H:mb=\E[5m:md=\E[1m:me=\E[m:\
+	:mr=\E[7m:nd=\E[C:r1=\E[\041p\E[?7h\E[2;1;1#w:rc=\E8:\
+	:rf=/usr/share/tabset/vt100:sc=\E7:se=\E[27m:sf=\ED:\
+	:so=\E[7m:sr=\EM:ta=^I:te=\E[\041p\E[?7h\E[2;1;1#w:\
+	:ti=\E[2;0#w\E[1;25r:ue=\E[24m:up=\E[A:us=\E[4m:
+
+#### Harris
+#
+# Bletch.  These guys shared the Terminal Brain Damage laurels with Hazeltine.
+# Their terminal group is ancient history now (1995) though the parent
+# company is still in business.
+#
+
+# 8675, 8686, and bee from Cyrus Rahman
+# (8675: changed k10, k11...k16 to k;, F1...F6 -- esr)
+ha8675|harris 8675:\
+	:F1=^W:F2=\ER:F3=\EE:F4=\EI:F5=\Ei:F6=\Eg:\
+	:is=\ES\E#\E*\Eh\Em\E?\E1\E9\E@\EX\EU:k1=^F:k2=^P:k3=^N:\
+	:k4=^V:k5=^J:k6=^T:k7=^H:k8=\177:k9=\Ee:k;=\Ed:\
+	:tc=bee:
+# (8686: changed k10, k11...k16 to k;, F1...F6; fixed broken continuation
+# in :is: -- esr)
+ha8686|harris 8686:\
+	:F1=\EW:F2=\002\E{\003:F3=\002\E|\003:F4=\002\E}\003:\
+	:F5=\002\E~\003:F6=\002\E\177\003:\
+	:is=\ES\E#\E*\Eh\Em\E?\E1\E9\E@\EX\EU\E"*Z01\E"8F35021B7C83#\E"8F45021B7D83#\E"8F55021B7E83#\E"8F65021B7F83#\E"8F75021B7383#\E"8F851BD7#\E"8F95021B7083#\E"8FA5021B7183#\E"8FB5021B7283#:\
+	:k1=\002\Ep\003:k2=\002\Eq\003:k3=\002\Er\003:\
+	:k4=\002\Es\003:k5=\E3:k6=\EI:k7=\ER:k8=\EJ:k9=\E(:k;=\Ej:tc=bee:
+
+#### Hazeltine
+#
+# Hazeltine appears to be out of the terminal business as of 1995.  These
+# guys were co-owners of the Terminal Brain Damage Hall Of Fame along with
+# Harris. They have a hazeltine.com domain (but no web page there ) and can
+# be reached at:
+#
+#	Hazeltine
+#	450 East Pulaski Road
+#	Greenlawn, New York 11740
+#
+# As late as 1993, manuals for the terminal product line could still be
+# purchased from:
+#
+#	TRW Customer Service Division
+#	15 Law Drive
+#	P.O. Box 2076
+#	Fairfield, NJ 07007-2078
+#
+# They're now (1998) a subsidiary of General Electric, operating under the
+# marque "GEC-Marconi Hazeltine" and doing military avionics.  Web page
+# at <http://www.gec.com/cpd/1ncpd.htm#1.55>.
+#
+
+# Since :nd: is blank, when you want to erase something you
+# are out of luck.  You will have to do ^L's a lot to
+# redraw the screen.  h1000 is untested.  It doesn't work in
+# vi - this terminal is too dumb for even vi.  (The code is
+# there but it isn't debugged for this case.)
+hz1000|hazeltine 1000:\
+	:bs:\
+	:co#80:li#12:\
+	:bl=^G:cl=^L:cr=^M:do=^J:ho=^K:le=^H:nd= :sf=^J:
+# From: <cbosg!ucbvax!pur-ee!cincy!chris> Thu Aug 20 09:09:18 1981
+hz1420|hazeltine 1420:\
+	:am:bs:\
+	:co#80:li#24:\
+	:al=\E^Z:bl=^G:cd=\E^X:ce=\E^O:cl=\E^\:cm=\E\021%r%.%+ :\
+	:cr=^M:dl=\E^S:do=^J:le=^H:nd=^P:se=\E^Y:sf=^J:so=\E^_:ta=^N:\
+	:up=\E^L:
+# New "safe" cursor movement (11/87) from <cgs@umd5.umd.edu>.  Prevents
+# freakout with out-of-range args and tn3270.  No hz since it needs to
+# receive tildes.
+hz1500|hazeltine 1500:\
+	:am:bs:hz:\
+	:co#80:li#24:\
+	:al=~\032:bl=^G:cd=~\030:ce=~^O:cl=~^\:\
+	:cm=~\021%r%>^^ %+`%+`:cr=^M:dl=~\023:do=~^K:ho=~^R:kd=^J:\
+	:kh=~^R:kl=^H:kr=^P:ku=~^L:le=^H:nd=^P:se=~^Y:sf=^J:so=~^_:\
+	:up=~^L:
+# h1510 assumed to be in sane escape mode.  Else use h1500.
+# (h1510: early versions of this entry apparently had ":se=\E^_:, 
+# :so=\E^Y:, but these caps were commented out in 8.3; also,
+# removed incorrect and overridden ":do=^J:" -- esr)
+hz1510|hazeltine 1510:\
+	:am:bs:\
+	:co#80:li#24:\
+	:al=\E^Z:bl=^G:cd=\E^X:ce=\E^O:cl=\E^\:cm=\E\021%r%.%.:\
+	:cr=^M:dl=\E^S:do=\E^K:le=^H:nd=^P:sf=^J:up=\E^L:
+# Hazeltine 1520
+# The following switch settings are assumed for normal operation:
+#	FULL		CR		U/L_CASE	ESCAPE
+#	FORMAT_OFF	EOM_A_OFF	EOM_B_OFF	WRAPAROUND_ON
+# Other switches may be set for operator convenience or communication
+# requirements.
+hz1520|Hazeltine 1520:\
+	:am:bs:bw:ms:\
+	:co#80:li#24:\
+	:al=\E^Z:bl=^G:cd=\E^X:ce=\E^O:cl=\E^\:cm=\E\021%r%.%.:\
+	:cr=^M:dl=\E^S:do=^J:ho=\E^R:kA=\E^Z:kC=\E^\:kE=\E^O:\
+	:kL=\E^S:kS=\E^X:kb=^H:kd=\E^K:kh=\E^R:kl=^H:kr=^P:ku=\E^L:\
+	:le=^H:md=\E^_:me=\E^Y:nd=^P:r1=\E$\E\005\E?\E\031:\
+	:se=\E^Y:sf=^J:so=\E^_:up=\E^L:
+# This version works with the escape switch off
+# (h1520: removed incorrect and overridden ":do=^J:" -- esr)
+hz1520-noesc|hazeltine 1520:\
+	:am:hz:\
+	:co#80:li#24:\
+	:al=~^Z:bl=^G:cd=~^X:ce=~^O:cl=~^\:cm=~\021%r%.%.:cr=^M:\
+	:dl=~^S:do=~^K:ho=~^R:le=^H:nd=^P:se=~^Y:sf=^J:so=~^_:up=~^L:
+# Note: the h1552 appears to be the first Hazeltine terminal which
+# is not braindamaged.  It has tildes and backprimes and everything!
+# Be sure the auto lf/cr switch is set to cr.
+hz1552|hazeltine 1552:\
+	:bs:\
+	:al=\EE:dl=\EO:do=^J:k1=\EP:k2=\EQ:k3=\ER:l1=blue:l2=red:\
+	:l3=green:\
+	:tc=vt52:
+hz1552-rv|hazeltine 1552 reverse video:\
+	:do=^J:se=\ET:so=\ES:tc=hz1552:
+# Note: h2000 won't work well because of a clash between upper case and ~'s.
+hz2000|hazeltine 2000:\
+	:am:bs:nc:\
+	:co#74:li#27:\
+	:al=~\032:bl=^G:cl=~\034:cm=~\021%r%.%.:dl=~\023:do=^J:\
+	:ho=~^R:le=^H:pc=\177:sf=^J:
+# Date: Fri Jul 23 10:27:53 1982.  Some unknown person wrote:
+# I tested this termcap entry for the Hazeltine Esprit with vi. It seems
+# to work ok. There is one problem though if one types a lot of garbage
+# characters very fast vi seems not able to keep up and hangs while trying
+# to insert. That's in insert mode while trying to insert in the middle of
+# a line. It might be because the Esprit doesn't have insert char and delete
+# char as a built in function. Vi has to delete to end of line and then 
+# redraw the rest of the line.
+esprit|Hazeltine Esprit I:\
+	:am:bs:bw:\
+	:co#80:li#24:\
+	:al=\E^Z:bl=^G:bt=\E^T:cd=\E^W:ce=\E^O:cl=\E^\:\
+	:cm=\E\021%r%.%.:cr=^M:dl=\E^S:do=\E^K:ho=\E^R:is=\E?:\
+	:k0=^B0^J:k1=^B1^J:k2=^B2^J:k3=^B3^J:k4=^B4^J:k5=^B5^J:\
+	:k6=^B6^J:k7=^B7^J:k8=^B8^J:k9=^B9^J:kb=^H:kd=\E^K:ke=\E>:\
+	:kh=\E^R:kl=^H:kr=^P:ks=\E<:ku=\E^L:l0=0:l1=1:l2=2:l3=3:l4=4:\
+	:l5=5:l6=6:l7=7:l8=8:l9=9:le=^H:nd=^P:se=\E^Y:sf=^J:so=\E^_:\
+	:up=\E^L:
+esprit-am|hazeltine esprit auto-margin:\
+	:am:tc=esprit:
+# Hazeltine Modular-1 from Cliff Shackelton <ittvax!ittral!shackelt> via BRL
+# Vi it seems always wants to send a control J for "do" and it turned out
+# that the terminal would work somewhat if the auto LF/CR was turned off.
+# (hmod1: removed :dn=~^K: -- esr)
+hmod1|Hazeltine Modular 1:\
+	:am:bs:hz:\
+	:co#80:li#24:\
+	:al=~^Z:bl=^G:bt=~^T:cl=~^\:cm=~\021%r%.%.:cr=^M:dl=~^S:\
+	:do=~^K:ho=~^R:kd=~^K:kh=~^R:kl=^H:kr=^P:ku=~^L:le=^H:me=~^Y:\
+	:nd=^P:rc=~^Q:sc=~^E:se=~^Y:sf=^J:so=~^_:up=~^L:
+#
+# Hazeltine Executive 80 Model 30 (1554?)
+#	from  Will Martin <control@ALMSA-1.ARPA> via BRL
+# Like VT100, except for different "am" behavior.
+hazel|exec80|h80|he80|Hazeltine Executive 80:\
+	:am:bs:pt:\
+	:co#80:it#8:li#24:vt#3:\
+	:bl=^G:cd=50\E[J:ce=3\E[K:cl=50\E[;H\E[2J:\
+	:cm=5\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:do=^J:ho=\E[H:\
+	:is=\E[1;24r\E[24;1H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+	:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:\
+	:ku=\EOA:le=^H:mb=2\E[5m:md=2\E[1m:me=2\E[m:mr=2\E[7m:\
+	:nd=2\E[C:nl=^J:r1=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:\
+	:rc=\E8:rf=/usr/share/tabset/vt100:sc=\E7:se=2\E[m:\
+	:so=2\E[7m:sr=5\EM:ta=^I:ue=2\E[m:up=2\E[A:us=2\E[4m:
+
+#### Hewlett-Packard (hp)
+#
+#	Hewlett-Packard
+#	8000 Foothills Blvd 
+#	Roseville, CA 95747
+#	Vox: 1-(916)-785-4363	(Technical response line for VDTs)
+#	     1-(800)-633-3600	(General customer support)
+#
+#
+# As of March 1998, HP no longer has any terminals in production.
+# The 700 series (22, 32, 41, 44, 92, 94, 96, 98) is still being 
+# supported (they still have parts). So are the 2392a and 2394a.
+# See the WORKSTATION CONSOLES section for the 700s.
+#
+
+# Generic HP terminal - this should (hopefully) work on any HP terminal.
+hpgeneric|hp|hewlett-packard generic terminal:\
+	:am:bs:da:db:mi:pt:xs:\
+	:co#80:li#24:lm#0:vt#6:\
+	:al=\EL:bl=^G:cd=\EJ:ce=\EK:ch=\E&a%dC:cl=\EH\EJ:\
+	:cm=\E&a%r%dc%dY:cr=^M:ct=\E3:cv=\E&a%dY:dc=\EP:dl=\EM:\
+	:do=^J:ei=\ER:im=\EQ:kB=\Ei:kb=^H:le=^H:me=\E&d@:nd=\EC:\
+	:se=\E&d@:sf=^J:so=\E&dJ:st=\E1:ta=^I:ue=\E&d@:up=\EA:\
+	:us=\E&dD:
+
+hp110|hewlett-packard model 110 portable:\
+	:li#16:tc=hpgeneric:
+
+hp+pfk+cr|hp function keys with CR:\
+	:k1=\Ep\r:k2=\Eq\r:k3=\Er\r:k4=\Es\r:k5=\Et\r:k6=\Eu\r:\
+	:k7=\Ev\r:k8=\Ew\r:
+
+hp+pfk-cr|hp function keys w/o CR:\
+	:k1=\Ep:k2=\Eq:k3=\Er:k4=\Es:k5=\Et:k6=\Eu:k7=\Ev:k8=\Ew:
+
+# The hp2621s use the same keys for the arrows and function keys, 
+# but not separate escape sequences. These definitions allow the 
+# user to use those keys as arrow keys rather than as function 
+# keys.
+hp+pfk+arrows|hp alternate arrow definitions:\
+	:k1@:k2@:k3@:k4@:k5@:k6@:k7@:k8@:kF=\Er\r:kH=\Eq\r:kR=\Es\r:\
+	:kd=\Ew\r:kh=\Ep\r:kl=\Eu\r:kr=\Ev\r:ku=\Et\r:
+
+hp+arrows|hp arrow definitions:\
+	:kF=\ES:kH=\EF:kR=\ET:kd=\EB:kh=\Eh:kl=\ED:kr=\EC:ku=\EA:
+
+# Generic stuff from the HP 262x series
+#
+hp262x|HP 262x terminals:\
+	:xs:\
+	:cd=\EJ:dc=\EP:ip=:kA=\EL:kD=\EP:kE=\EK:kF=\ES:kI=\EQ:kL=\EM:\
+	:kM=\ER:kN=\EU:kP=\EV:kR=\ET:kS=\EJ:kd=\EB:ke=\E&s0A:kh=\Eh:\
+	:kl=\ED:kr=\EC:ks=\E&s1A:ku=\EA:mb=\E&dA:me=\E&d@:mk=\E&dS:\
+	:mr=\E&dB:\
+	:..sa=\E&d%{64}%?%p1%t%{66}%|%;%?%p2%t%{68}%|%;%?%p3%t%{66}%|%;%?%p4%t%{65}%|%;%c:\
+	:se=\E&d@:sf=\ES:so=\E&dB:ta=\011:ue=\E&d@:us=\E&dD:
+
+# Note: no :ho: on HPs since that homes to top of memory, not screen.
+# Due to severe 2621 braindamage, the only way to get the arrow keys to
+# transmit anything at all is to turn on the function key labels
+# with :ks:, and even then the user has to hold down shift!
+# The default 2621 turns off the labels except when it has to to 
+# enable the function keys. If your installation prefers labels 
+# on all the time, or off all the time (at the "expense" of the 
+# function keys), use 2621-nl or 2621-wl.
+# 
+# Note: there are newer ROMs for 2621's that allow you to set 
+# strap A so the regular arrow keys xmit \EA, etc, as with the 
+# 2645. However, even with this strap set, the terminal stops 
+# xmitting if you reset it, until you unset and reset the strap!
+# Since there is no way to set/unset the strap with an escape 
+# sequence, we don't use it in the default.
+# If you like, you can use 2621-ba (brain-damaged arrow keys).
+hp2621-ba|2621 w/new rom and strap A set:\
+	:ke@:ks@:tc=hp+arrows:\
+	:tc=hp2621:
+
+# hp2621 with function labels. Most of the time they are off,
+# but inside vi, the function key labels appear. You have to
+# hold down shift to get them to xmit.
+hp2621|hp2621a|hp2621A|2621|2621a|2621A|hp2621-wl|2621-wl|hp 2621 w/labels:\
+	:is=\E&jA\r:ke=\E&jA:\
+	:tc=hp2621-fl:
+hp2621-fl|hp 2621:\
+	:xo:xs@:\
+	:pb#19200:\
+	:bt=\Ei:cm=\E&a%r%dc%dY:dc=\EP:ip=:is=\E&j@\r:ke=\E&j@:\
+	:ks=\E&jB:me=\E&d@:se=\E&d@:so=\E&dD:ta=\011:ue=\E&d@:\
+	:us=\E&dD:\
+	:tc=hp+pfk+cr:tc=hpgeneric:
+
+# To use hp2621p printer, setenv TERM=2621p, PRINTER=2612p
+hp2621p|hp 2621 with printer:\
+	:pf=\E&p13C:po=\E&p11C:tc=hp2621:
+
+hp2621p-a|hp2621p with fn as arrows:\
+	:tc=hp+pfk+arrows:tc=hp2621p:
+
+# hp2621 with k45 keyboard
+hp2621-k45|hp2621k45|k45|hp 2621 with 45 keyboard:\
+	:kb=^H:kd=\EB:ke=\E&s0A:kh=\Eh:kl=\ED:kr=\EC:ks=\E&s1A:\
+	:ku=\EA:\
+	:tc=hp2621:
+
+# 2621 using all 48 lines of memory, only 24 visible at any time.  
+hp2621-48|48 line 2621:\
+	:li#48:\
+	:cm=\E&a%r%dc%dR:cv=\E&a%dR:ho=\EH:tc=hp2621:
+
+# 2621 with no labels ever. Also prevents vi delays on escape.
+hp2621-nl|hp 2621 with no labels:\
+	:kd@:ke@:kh@:kl@:kr@:ks@:ku@:tc=hp2621-fl:
+
+# Needed for UCB ARPAVAX console, since lsi-11 expands tabs 
+# (wrong).
+#
+hp2621-nt|hp 2621 w/no tabs:\
+	:ta@:tc=hp2621:
+
+# Hp 2624 B with 4 or 10 pages of memory.
+# 
+# Some assumptions are made with this entry. These settings are 
+# NOT set up by the initialization strings.
+# 
+# Port Configuration
+# 	RecvPace=Xon/Xoff
+# 	XmitPace=Xon/Xoff
+# 	StripNulDel=Yes
+# 
+# Terminal Configuration
+# 	InhHndShk=Yes
+# 	InhDC2=Yes
+# 	XmitFnctn(A)=No
+# 	InhEolWrp=No
+# 
+# Note: the 2624 DOES have a true :ho:, believe it or not!
+# 
+# The 2624 has an "error line" to which messages can be sent. 
+# This is CLOSE to what is expected for a "status line". However,
+# after a message is sent to the "error line", the next carriage 
+# return is EATEN and the "error line" is turned back off again! 
+# So I guess we can't define :hs:, :es:, :ws:, :ds:, :fs:, :ts:.
+# 
+# This entry supports emacs (and any other program that uses raw 
+# mode) at 4800 baud and less. I couldn't get the padding right 
+# for 9600.
+#
+# (hp2624: replaced NUL sequences in flash with mandatory pauses -- esr)
+hp2624|hp2624a|hp2624b|hp2624b-4p|Hewlett Packard 2624 B:\
+	:da:db:\
+	:lm#96:\
+	:vb=\E&w13F\E&w12F\E&w13F\E&w12F:tc=hp+labels:tc=scrhp:
+
+# This hp2626 entry does not use any of the fancy windowing stuff 
+# of the 2626.
+# 
+# Indeed, terminfo does not yet handle such stuff. Since changing 
+# any window clears memory, it is probably not possible to use 
+# this for screen opt.
+# 
+# ed is incredibly slow most of the time - I am guessing at the 
+# exact padding. Since the terminal uses xoff/xon this is intended 
+# only for cost computation, so that the terminal will prefer el 
+# or even dl1 which is probably faster!
+# 
+# \ED\EJ\EC hack for ed from Ed Bradford - apparently ed is only 
+# extra slow on the last line of the window. 
+# 
+# The padding probably should be changed.
+#
+hp2626|hp2626a|hp2626p|hp 2626:\
+	:da:db:\
+	:lm#0:pb#19200:\
+	:SF=\E&r%dD:SR=\E&r%dU:cd=\ED\EJ\EC:ip=:is=\E&j@\r:tc=hp+pfk+cr:tc=hp+labels:tc=scrhp:
+
+# This entry is for sysline. It allocates a 23 line window with 
+# a 115 line workspace for regular use, and a 1 line window for 
+# the status line.
+# 
+# This assumes port 2 is being used.
+# Turn off horizontal line, Create ws #1 with 115 lines,
+# Create ws #2 with 1 line, Create window #1 lines 1-23,
+# Create window #2 lines 24-24, Attach cursor to workspace #1.
+# Note that this clears the tabs so it must be done by tset before
+# it sets the tabs.
+#
+hp2626-s|hp 2626 using only 23 lines:\
+	:es:hs:\
+	:li#23:\
+	:fs=\E&d@\E&w7f2p1I\E&w4f1I:\
+	:i1=\E&q3t0{0H \E&w0f115n1I \E&w0f1n2I \E&w2f1i0d0u22l0S \E&w2f2i0d23u23l0S \E&w7f2p1I \r:\
+	:ts=\E&w7f2p2I\E&w4f2I\r\EK\E&a%p1%dC:\
+	:tc=hp2626:
+# Force terminal back to 24 lines after being 23.
+hp2626-ns|hp 2626 using all 24 lines:\
+	:i1=\E&q3t0{0H \E&w0f118n1I \E&w0f1n2I \E&w2f1i0d0u23l0S \E&w3f2I \E&w7f2p1I \r:tc=hp2626:
+# Various entries useful for small windows on 2626.
+hp2626-12|hewlett-packard 2626 12 lines:\
+	:li#12:tc=hp2626:
+hp2626-12x40|hewlett-packard 2626 12 lines 40 columns:\
+	:co#40:li#12:tc=hp2626:
+hp2626-x40|hewlett-packard 2626 40 columns:\
+	:co#40:tc=hp2626:
+hp2626-12-s|hewlett-packard 2626 11 lines plus status:\
+	:li#11:tc=hp2626-s:
+
+#
+# hp2627 color tubes from University of Wisconsin
+#
+hp2627a-rev|hp 2627 with reverse video colors:\
+	:cr=^M:do=^J:\
+	:is=\E&v0m1a0b0c1x1y1z1i0a0b1c1x1y1z0i0S\E&j@\r\E3\r:\
+	:kb=^H:kd=^J:kl=^H:nw=^M^J:sf=^J:ta=^I:ue=\E&v0S\E&d@:\
+	:us=\E&dD\E&v1S:\
+	:tc=hp2621-nl:
+hp2627a|hp 2627 color terminal with no labels:\
+	:cr=^M:do=^J:\
+	:is=\E&v0m1a1b0c1i0a1b1c2i1a0b0c0i0S\E&j@\r\E3\r:\
+	:kb=^H:kd=^J:kl=^H:nw=^M^J:se=\E&v0S:sf=^J:so=\E&v2S:ta=^I:\
+	:ue=\E&v0S\E&d@:us=\E&dD\E&v1S:\
+	:tc=hp2621-nl:
+hp2627c|hp 2627 color (cyan) terminal with no labels:\
+	:cr=^M:do=^J:\
+	:is=\E&v0m1a0b0c2i1a1b0c1i0a1b1c0i0S\E&j@\r\E3\r:\
+	:kb=^H:kd=^J:kl=^H:nw=^M^J:sf=^J:ta=^I:\
+	:tc=hp2627a:
+
+# hp2640a doesn't have the Y cursor addressing feature, and C is 
+# memory relative instead of screen relative, as we need.
+#
+hp2640a|hp 2640a:\
+	:cm@:ke@:ks@:tc=hp2645:
+
+hp2640b|hp2644a|hp 264x series:\
+	:ke@:ks@:tc=hp2645:
+
+# (hp2641a: removed unknown :gu: -- esr)
+hp2641a|hp2645a|hp2647a|HP 264?A series BRL entry:\
+	:am:da:db:mi:xs:\
+	:co#80:li#24:\
+	:al=\EL:bl=^G:cd=\EJ:ce=\EK:ch=\E&a%2C:cl=\EH\EJ:\
+	:cm=\E&a%r%2c%2Y:cr=^M:cv=\E&a%2Y:dc=\EP:dl=\EM:do=^J:\
+	:ei=\ER:if=/usr/share/tabset/std:im=\EQ:is=500\EE:kb=^H:\
+	:kd=^J:kl=^H:le=^H:nd=\EC:nw=^M^J:se=\E&d@:sf=^J:so=\E&dB:\
+	:ta=^I:up=\EA:
+
+# This terminal should be used at 4800 baud or less. It needs padding for
+# plain characters at 9600, I guessed at an appropriate cr delay.  It really
+# wants ^E/^F handshaking, but that doesn't work well even if you write
+# software to support it.
+hp2645|hp45|HP 2645 series:\
+	:pb#9600:\
+	:cr=\r:kA=\EL:kD=\EP:kE=\EK:kF=\ES:kI=\EQ:kL=\EM:kM=\ER:\
+	:kN=\EU:kP=\EV:kR=\ET:kS=\EJ:kT=\E1:kd=\EB:ke=\E&s0A:kh=\Eh:\
+	:kl=\ED:kr=\EC:ks=\E&s1A:kt=\E2:ku=\EA:mb=\E&dA:me=\E&d@:\
+	:mh=\E&dH:mr=\E&dB:\
+	:..sa=\E&d%{64}%?%p1%t%{66}%|%;%?%p2%t%{68}%|%;%?%p3%t%{66}%|%;%?%p4%t%{65}%|%;%?%p5%t%{72}%|%;%?%p6%t%{66}%|%;%c:\
+	:us=\E&dD:\
+	:tc=hpgeneric:
+# You should use this terminal at 4800 baud or less.
+hp2648|hp2648a|HP 2648a graphics terminal:\
+	:cl=\EH\EJ:cm=\E&a%r%dc%dY:dc=\EP:ip=:tc=hp2645:
+
+# The HP 150 terminal is a fairly vanilla HP terminal, with the 
+# clreol standout problem. It also has graphics capabilities and 
+# a touch screen, which we don't describe here.
+hp150|hewlett packard Model 150:\
+	:bs:tc=hp2622:
+
+# HP 2382a terminals, "the little ones." They don't have any 
+# alternate character set support and sending out ^N/^O will 
+# leave the screen blank.
+hp2382a|hp2382|hewlett packard 2382a:\
+	:da:db:\
+	:lh#1:lm#48:\
+	:ac@:ae@:as@:me=\E&d@:\
+	:..pn=\E&f0a%p1%dk%p2%l%Pa%?%ga%t%ga%d%e1%;d0L%?%ga%!%t %;%p2%s:\
+	:..sa=\E&d%{0}%Pa%?%p4%t%{1}%ga%+%Pa%;%?%p1%p3%|%p6%|%t%{2}%ga%+%Pa%;%?%p2%p6%|%t%{4}%ga%+%Pa%;%?%p1%p5%|%t%{8}%ga%+%Pa%;%?%p7%t%?%ga%ts%ga%{64}%+%e%{83}%;%e%?%ga%t%ga%{64}%+%e%{64}%;%;%c:\
+	:tc=hp+labels:tc=scrhp:
+
+hp2621-a|hp2621a-a|hp2621 with fn as arrows:\
+	:tc=hp+pfk+arrows:tc=hp2621-fl:
+
+# newer hewlett packard terminals
+
+newhpkeyboard|generic entry for HP extended keyboard:\
+	:kA=\EL:kB=\Ei:kC=\EJ:kD=\EP:kE=\EK:kF=\ET:kH=\EF:kI=\EQ:\
+	:kL=\EM:kM=\ER:kN=\EU:kP=\EV:kR=\ES:kS=\EJ:kb=^H:kd=\EB:\
+	:ke=\E&s0A:kh=\Eh:kl=\ED:kr=\EC:ks=\E&s1A:ku=\EA:\
+	:tc=hp+pfk-cr:
+
+newhp|generic entry for new hewlett packard terminals:\
+	:am:bw:mi:xo:xs:\
+	:co#80:li#24:pb#4800:\
+	:ac=2[3@4>5I9(\072'JSKWLQMAO#P$Q;R\041S"T1U2V4W3X\072Y+Z*dHjGkTlRmFn/q\054t5u6v8w7x.:\
+	:ae=^O:al=\EL:as=^N:bl=^G:bt=\Ei:cd=\EJ:ce=\EK:cr=^M:ct=\E3:\
+	:dc=\EP:dl=\EM:do=^J:ei=\ER:i1=\E&jB:im=\EQ:ip=:le=^H:\
+	:mb=\E&dA:md=\E&dF:me=\E&d@\017:mh=\E&dH:mk=\E&dS:\
+	:mr=\E&dB:nd=\EC:nw=^M^J:\
+	:..pk=\E&f0a%p1%dk0d%p2%l%dL%p2%s:\
+	:..pl=\E&f1a%p1%dk0d%p2%l%dL%p2%s:\
+	:..px=\E&f2a%p1%dk0d%p2%l%dL%p2%s:r1=\Eg:\
+	:..sa=\E&d%{0}%Pa%?%p4%t%{1}%ga%+%Pa%;%?%p1%p3%|%p6%|%t%{2}%ga%+%Pa%;%?%p2%p6%|%t%{4}%ga%+%Pa%;%?%p1%p5%|%t%{8}%ga%+%Pa%;%?%p7%t%?%ga%ts%ga%{64}%+%e%{83}%;%e%?%ga%t%ga%{64}%+%e%{64}%;%;%c%?%p9%t\016%e\017%;:\
+	:se=\E&d@:sf=^J:so=\E&dJ:sr=\ET:st=\E1:ta=\011:ue=\E&d@:\
+	:up=\EA:us=\E&dD:\
+	:tc=newhpkeyboard:
+
+memhp|memory relative addressing for new HP ttys:\
+	:vt#6:\
+	:CM=\E&a%p1%dr%p2%dC:DO=\E&a+%dR:LE=\E&a-%dC:\
+	:RI=\E&a+%dC:UP=\E&a-%dR:ch=\E&a%dC:cl=\EH\EJ:\
+	:cm=\E&a%dr%dC:cv=\E&a%dR:ho=\EH:ll=\E&a23R\r:tc=newhp:
+
+scrhp|screen relative addressing for new HP ttys:\
+	:CM=\E&a%p1%dr%p2%dC:DO=\E&a+%dR:LE=\E&a-%dC:\
+	:RI=\E&a+%dC:UP=\E&a-%dR:ch=\E&a%dC:cl=\E&a0c0Y\EJ:\
+	:cm=\E&a%dy%dC:cv=\E&a%dY:ho=\E&a0y0C:ll=\E&a0y0C\EA:\
+	:tc=newhp:
+
+# (hp+labels: added label values from a BRL termcap -- esr)
+hp+labels|"standard" label info for new HP ttys:\
+	:Nl#8:lh#2:lw#8:\
+	:LF=\E&j@:LO=\E&jB:l0=f1:l1=f2:l2=f3:l3=f4:l4=f5:l5=f6:l6=f7:\
+	:l7=f8:\
+	:..pn=\E&f2a%p1%dk%p2%l%Pa%?%ga%t%ga%d%e1%;d0L%?%ga%!%t %;%p2%s:
+
+hp+printer|"standard" printer info for HP ttys:\
+	:ff=\E&p4u0C:pf=\E&p13C:po=\E&p11C:ps=\EH\E&p4dF:
+
+
+# The new hp2621b is kind of a cross between the old 2621 and the
+# new 262x series of machines. It has dip-switched options. 
+# The firmware has a bug in it such that if you give it a null 
+# length label, the following character is eaten!
+hp2621b|hp 2621b with old style keyboard:\
+	:Nl#8:lh#1:lm#48:lw#8:\
+	:LO=\E&jB:kF=\ET:kH=\EF:kR=\ES:kd=\EB:kh=\Eh:kl=\ED:kr=\EC:\
+	:ku=\EA:\
+	:..pn=\E&f0a%p1%dk%p2%l%Pa%?%ga%t%ga%d%e1%;d3L%?%ga%!%t%{32}%c%;%p2%s\E%{111}%p1%+%c\r:tc=hp2621:
+
+hp2621b-p|hp 2621b with printer:\
+	:tc=hp+printer:tc=hp2621b:
+
+# hp2621b - new 2621b with new extended keyboard
+# these are closer to the new 26xx series than the other 2621b
+hp2621b-kx|hp 2621b with extended keyboard:\
+	:tc=newhpkeyboard:tc=hp2621b:
+
+hp2621b-kx-p|hp 2621b with new keyboard & printer:\
+	:tc=hp+printer:tc=hp2621b-kx:
+
+# Some assumptions are made in the following entries.
+# These settings are NOT set up by the initialization strings.
+# 
+#    Port Configuration
+# RecvPace=Xon/Xoff	XmitPace=Xon/Xoff	StripNulDel=Yes
+# 
+#    Terminal Configuration
+# InhHndShk(G)=Yes	InhDC2(H)=Yes
+# XmitFnctn(A)=No		InhEolWrp=No
+#
+# 
+# Hp 2622a & hp2623a display and graphics terminals
+#
+hp2622|hp2622a|hp 2622:\
+	:da:db:\
+	:lm#0:pb#19200:\
+	:is=\E&dj@\r:tc=hp+pfk+cr:tc=hp+labels:tc=scrhp:
+
+# The 2623 is a 2622 with extra graphics hardware.
+hp2623|hp2623a|hp 2623:\
+	:tc=hp2622:
+
+hp2624b-p|hp2624b-4p-p|hewlett packard 2624 B with printer:\
+	:tc=hp+printer:tc=hp2624:
+
+# The hewlett packard B can have an optional extra 6 pages of memory.
+hp2624-10p|hp2624a-10p|hp2624b-10p|hewlett packard 2624 B w/ 10 pages of memory:\
+	:lm#240:tc=hp2624:
+
+hp2624b-10p-p|hewlett packard 2624 B w/ extra memory & printer:\
+	:lm#240:tc=hp2624b-p:
+
+# Color manipulations for HP terminals
+hp+color|hp with colors:\
+	:cc:\
+	:Co#16:NC#17:pa#7:\
+	:..Ip=\E&v%?%p2%{1000}%=%t1%e.%p2%d%;a%?%p3%{1000}%=%t1%e.%p3%d%;b%?%p4%{1000}%=%t1%e.%p4%d%;c%?%p5%{1000}%=%t1%e.%p5%d%;x%?%p6%{1000}%=%t1%e.%p6%d%;y%?%p7%{1000}%=%t1%e.%p7%d%;z%p1%dI:\
+	:oc=\E&v0m1a1b1c0I\E&v1a1I\E&v1b2I\E&v1a1b3I\E&v1c4I\E&v1a1c5I\E&v1b1c6I\E&v1x1y7I:\
+	:op=\E&v0S:sp=\E&v%dS:
+
+# :is: sets the screen to be 80 columns wide
+hp2397a|hp2397|hewlett packard 2397A color terminal:\
+	:is=\E&w6f80X:\
+	:tc=memhp:tc=hp+labels:tc=hp+color:
+
+#
+# (hp2392: copied :ei: here from hpex -- esr)
+hp2392|239x series:\
+	:co#80:\
+	:bt=\Ei:cm=\E&a%dy%dC:cv=\E&a%dY:ei=\ER:im=\EQ:k1=\Ep\r:\
+	:k2=\Eq\r:k3=\Er\r:k4=\Es\r:k5=\Et\r:k6=\Eu\r:k7=\Ev\r:\
+	:k8=\Ew\r:kF=\EU:kN=\Eu:kP=\Ev:kR=\EV:kh=\Eh:ue=\E&d@:\
+	:us=\E&dD:\
+	:tc=hpsub:
+
+hpsub|hp terminals -- capability subset:\
+	:am:da:db:mi:xo:xs:\
+	:li#24:\
+	:al=\EL:bl=^G:cd=\EJ:ce=\EK:ch=\E&a%dC:cl=\EH\EJ:cr=^M:\
+	:dc=\EP:dl=\EM:do=\EB:if=/usr/share/tabset/stdcrt:\
+	:is=\E&s1A\E<\E&k0\:kb=^H:kd=\EB:ke=\E&s0A:kh=\Eh:kl=\ED:\
+	:kr=\EC:ks=\E&s1A:ku=\EA:le=^H:me=\E&d@:nd=\EC:se=\E&d@:\
+	:sf=^J:so=\E&dB:ta=^I:up=\EA:
+
+# hpex:
+#	May be used for most 24 x 80 hp terminals,
+# but has no padding added, so may allow runover in some terminals at high 
+# baud rates.  Will not work for hp2640a or hp2640b terminals, hp98x6 and 
+# hp98x5 terminal emulators or hp98x6 consoles.  
+# 	Adds xy-cursor addressing, vertical cursor addressing, home, 
+# last line, and underline capabilities.
+#
+# (hpex: removed memory-lock capabilities ":ml=\El:mu=\Em:",
+# moved :ei: here from hpsub -- esr)
+hpex|hp extended capabilites:\
+	:cm=\E&a%dy%dC:cr=^M:cv=\E&a%dY:do=^J:ei=\ER:im=\EQ:kb=^H:\
+	:kd=^J:kl=^H:nw=^M^J:sf=^J:ta=^I:ue=\E&d@:us=\E&dD:\
+	:tc=hpsub:
+
+# From: Ville Sulko <Ville.Sulko@bip.atk.tpo.fi>, 05 Aug 1996
+hp2|hpex2|hewlett-packard extended capabilities newer version:\
+	:am:da:db:mi:xs:\
+	:Nl#8:co#80:lh#2:li#24:lm#0:lw#8:sg#0:\
+	:LF=\E&j@:LO=\E&jB:al=\EL:bl=^G:cd=\EJ:ce=\EK:ch=\E&a%dC:\
+	:cl=\E&a0y0C\EJ:cm=\E&a%dy%dC:cr=^M:ct=\E3:cv=\E&a%dY:\
+	:dc=\EP:dl=\EM:do=\EB:ei=\ER:im=\EQ:k1=\Ep:k2=\Eq:k3=\Er:\
+	:k4=\Es:k5=\Et:k6=\Eu:k7=\Ev:k8=\Ew:kA=\EL:kC=\EJ:kD=\EP:\
+	:kE=\EK:kF=\ES:kH=\EF:kI=\EQ:kL=\EM:kM=\ER:kN=\EU:kP=\EV:\
+	:kR=\ET:kS=\EJ:kT=\E1:ka=\E3:kb=^H:kd=\EB:ke=\E&s0A:kh=\Eh:\
+	:kl=\ED:kr=\EC:ks=\E&s1A:kt=\E2:ku=\EA:le=^H:me=\E&d@:\
+	:ml=\El:mu=\Em:nd=\EC:..pk=\E&f%p1%dk%p2%l%dL%p2%s:\
+	:..pl=\E&f1a%p1%dk%p2%l%dL%p2%s:\
+	:..pn=\E&f%p1%dk%p2%l%dd0L%p2%s:\
+	:..px=\E&f2a%p1%dk%p2%l%dL%p2%s:\
+	:..sa=\E&d%?%p7%t%{115}%c%;%p1%p3%|%p6%|%{2}%*%p2%{4}%*%+%p4%+%p5%{8}%*%+%{64}%+%c%?%p9%t%'\016'%c%e%'\017'%c%;:\
+	:se=\E&d@:sf=^J:so=\E&dB:st=\E1:ta=^I:ue=\E&d@:up=\EA:\
+	:us=\E&dD:
+
+# HP 236 console
+# From: <ddavis@ic.berkeley.edu>
+hp236|hp236 internal terminal emulator:\
+	:am:bs:\
+	:co#80:li#24:\
+	:al=\EG:ce=\EK:cl=\EF:cm=\EE%+ %+ :dc=\EJ:dl=\EH:ei=:ic=\EI:\
+	:im=:le=^H:me=\ECI:se=\ECI:so=\EBI:up=^K:ve=\EDE:vs=\EDB:
+
+# This works on a hp300 console running Utah 4.3 BSD
+# From: Craig Leres <leres@okeeffe.berkeley.edu>
+hp300h|HP Catseye console:\
+	:am:bs:da:db:mi:xs:\
+	:co#128:li#51:lm#0:sg#0:\
+	:al=\EL:bl=^G:bt=\Ei:cd=\EJ:ce=\EK:ch=\E&a%dC:\
+	:cl=\E&a0y0C\EJ:cm=\E&a%dy%dC:cr=^M:ct=\E3:cv=\E&a%dY:\
+	:dc=\EP:dl=\EM:do=\EB:ei=\ER:if=/usr/share/tabset/stdcrt:\
+	:im=\EQ:kb=^H:kd=\EB:ke=\E&s0A:kh=\Eh:kl=\ED:kr=\EC:\
+	:ks=\E&s1A:ku=\EA:le=^H:me=\E&d@:nd=\EC:se=\E&d@:sf=^J:\
+	:so=\E&dB:ta=^I:ue=\E&d@:up=\EA:us=\E&dD:
+# From: Greg Couch <gregc@ernie.berkeley.edu>
+hp9837|hp98720|hp98721|HP 9000/300 workstations:\
+	:am:bs:da:db:mi:xs:\
+	:co#128:it#8:li#46:lm#0:\
+	:al=\EL:bl=^G:bt=\Ei:cd=\EJ:ce=\EK:ch=\E&a%dC:\
+	:cl=\E&a0y0C\EJ:cm=\E&a%dy%dC:ct=\E3:cv=\E&a%dY:dc=\EP:\
+	:dl=\EM:do=\EB:ei=\ER:im=\EQ:is=\E&v0m1b0i&j@:kA=\EL:\
+	:kD=\EP:kE=\EK:kI=\EQ:kL=\EM:kN=\EU:kP=\EV:kS=\EJ:kb=^H:\
+	:kd=\EB:ke=\E&s0A:kh=\Eh:kl=\ED:kr=\EC:ks=\E&s1A:ku=\EA:\
+	:le=^H:me=\E&d@:nd=\EC:se=\E&v0S:sf=^J:so=\E&v5S:st=\E1:\
+	:ta=^I:ue=\E&d@:up=\EA:us=\E&dD:
+# HP 9845 desktop computer from BRL
+# (hp9845: removed unknown capability :gu: -- esr)
+hp9845|HP 9845:\
+	:am:bs:da:db:eo:mi:xs:\
+	:co#80:li#21:\
+	:al=\EL:bc=\ED:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\E&a%r%2c%2Y:\
+	:dc=\EP:dl=\EM:ei=\ER:if=/usr/share/tabset/std:im=\EQ:\
+	:nd=\EC:se=\E&d@:so=\E&dB:up=\EA:
+# From: Charles A. Finnell of MITRE <finnell@mitre.org>, developed 07SEP90
+# (hp98550: replaced /usr/share/tabset/9837 with std because :it#8:,:st=\E1:;
+# added empty <acsc> to avoid warnings re :as:/:ae: --esr)
+hp98550|hp98550a|HP 9000 Series 300 color console:\
+	:am:bs:da:db:mi:xs:\
+	:co#128:it#8:li#49:lm#0:\
+	:ac=:ae=^O:al=\EL:as=^N:bl=^G:bt=\Ei:cd=\EJ:ce=\EK:\
+	:ch=\E&a%dC:cl=\EH\EJ:cm=\E&a%dy%dC:cr=^M:ct=\E3:\
+	:cv=\E&a%dY:dc=\EP:dl=\EM:do=^J:ei=\ER:\
+	:if=/usr/share/tabset/std:im=\EQ:k1=\Ep:k2=\Eq:k3=\Er:\
+	:k4=\Es:k5=\Et:k6=\Eu:k7=\Ev:k8=\Ew:kA=\EL:kC=\EJ:kD=\EP:\
+	:kE=\EK:kF=\ES:kH=\EF:kI=\EQ:kL=\EM:kM=\ER:kN=\EU:kP=\EV:\
+	:kR=\ET:kS=\EJ:kT=\E1:ka=\E3:kb=^H:kd=\EB:ke=\E&s0A:kh=\Eh:\
+	:kl=\ED:kr=\EC:ks=\E&s1A:kt=\E2:ku=\EA:le=^H:mb=\E&dA:\
+	:md=\E&dJ:me=\E&d@:mh=\E&dH:mk=\E&ds:mr=\E&dJ:nd=\EC:\
+	:se=\E&d@:sf=^J:so=\E&dJ:st=\E1:ta=^I:ue=\E&d@:up=\EA:\
+	:us=\E&dD:ve=\E*dQ:vi=\E*dR:
+
+bobcat|sbobcat|HP 9000 model 300 console:\
+	:am:da:db:mi:xs:\
+	:co#128:it#8:li#47:sg#0:\
+	:al=10*\EL:bt=\Ei:cd=\EJ:ce=\EK:ch=6\E&a%dC:cl=\EH\EJ:\
+	:cm=6\E&a%dy%dC:cr=^M:cv=6\E&a%dY:dc=\EP:dl=10*\EM:do=\EB:\
+	:ei=\ER:im=\EQ:kb=^H:kd=\EB:ke=\E&s0A:kh=\Eh:kl=\ED:kr=\EC:\
+	:ks=\E&s1A:ku=\EA:le=^H:me=\E&d@:nd=\EC:nw=^M^J:se=\E&d@:\
+	:sf=^J:so=\E&dB:ta=^I:ue=\E&d@:up=\EA:us=\E&dD:
+gator-t|HP 9000 model 237 emulating extra-tall AAA:\
+	:li#94:tc=gator:
+gator|HP 9000 model 237 emulating AAA:\
+	:bw:km:mi:ul:\
+	:co#128:it#8:li#47:\
+	:AL=1*\E[%dL:DC=4\E[%dP:DL=1*\E[%dM:IC=4\E[%d@:al=\E[L:\
+	:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:ch=\E[%i%d`:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:dl=\E[M:do=^J:ei=:ho=\E[H:\
+	:ic=\E[@:im=:kb=^H:kd=^J:kl=^H:le=^H:me=\E[m:mr=\E[7m:\
+	:nd=\E[C:nw=^M^J:rp=1*%.\E[%db:se=\E[m:so=\E[7m:ta=^I:\
+	:ue=\E[m:up=\EM:us=\E[4m:
+gator-52|HP 9000 model 237 emulating VT52:\
+	:co#128:li#47:tc=vt52:
+gator-52t|HP 9000 model 237 emulating extra-tall VT52:\
+	:li#94:tc=gator-52:
+
+#### Honeywell-Bull
+#
+# From: Michael Haardt <michael@gandalf.moria> 11 Jan 93
+#
+
+# Honeywell Bull terminal.  Its cursor and function keys send single
+# control characters and it has standout/underline glitch.  Most programs
+# do not like these features/bugs.  Visual bell is realized by flashing the
+# "keyboard locked" LED.
+dku7003-dumb|Honeywell Bull DKU 7003 dumb mode:\
+	:co#80:li#25:\
+	:cd=^_:ce=\E[K:cl=^]^_:cm=\E[%i%d;%dH:cr=^M:do=^K:ho=^]:\
+	:kb=^H:kd=^K:kh=^]:kl=^Y:kr=^X:ku=^Z:le=^Y:nd=^X:nw=^M^J:\
+	:sf=^J:ta=^I:up=^Z:vb=\E[2h\E[2l:
+dku7003|Honeywell Bull DKU 7003 all features described:\
+	:ms:\
+	:sg#1:\
+	:mb=\E[5m:md=\E[7m:me=\E[m:mh=\E[2m:mr=\E[7m:se=\E[m:\
+	:so=\E[7m:ue=\E[m:us=\E[4m:\
+	:tc=dku7003-dumb:
+
+#### IBM
+#
+
+ibm327x|line mode IBM 3270 style:\
+	:gn:\
+	:ce=^M:cl=^M^J:ho=^M:
+
+# Beware! The 3101 entry IBM shipped with AIX 3 is *wrong*.  Losers...
+# From: J.B. Nicholson-Owens <jeffo@uiuc.edu> 8 Mar 94
+# (ibm3101: :if=/usr/share/tabset/ibm3101: removed, no such file -- esr)
+# Some versions of this that have :ct=\EH:; they may ort may not be broken.
+ibm3101|i3101|IBM 3101-10:\
+	:am:bs:xo:\
+	:co#80:li#24:\
+	:bl=^G:cd=\EJ:ce=\EI:cl=\EK:cm=\EY%+ %+ :cr=^M:ct=\E1:do=^J:\
+	:ho=\EH:kb=^H:kd=\EB:kl=\ED:kr=\EC:ku=\EA:le=^H:nd=\EC:\
+	:nw=^M^J:sf=^J:st=\E0:ta=^I:up=\EA:
+ibm3151|IBM 3151 display:\
+	:ae=\E>B:as=\E>A:is=\E S:me=\E4@\E>B:r2=\E S:s0=\E>B:\
+	:..sa=\E4%{64}%?%p1%t%{65}%|%;%?%p2%t%{66}%|%;%?%p3%t%{65}%|%;%?%p4%t%{68}%|%;%?%p5%t%{64}%|%;%?%p6%t%{72}%|%;%?%p7%t%{80}%|%;%c%?%p9%t\E>A%e\E>B%;:\
+	:te=\E>B:ti=\E>B:\
+	:tc=ibm3163:
+# From: Mark Easter <marke@fsi-ssd.csg.ssd.fsi.com> 29 Oct 1992 
+# I've commented out or translated some IBM extensions.
+# <kend>, :kN:, :kP:, <mc4>, <mc5> merged in from AIX 3.2.5  
+ibm3161|ibm3163|wy60-316X|wyse60-316X|IBM 3161/3163 display:\
+	:am:bs:mi:ms:\
+	:co#80:it#8:li#24:\
+	:@7=\E2:F1=\Ek\r:F2=\El\r:F3=\E\041a\r:F4=\E\041b\r:\
+	:F5=\E\041c\r:F6=\E\041d\r:F7=\E\041e\r:F8=\E\041f\r:\
+	:F9=\E\041g\r:FA=\E\041h\r:FB=\E\041i\r:FC=\E\041j\r:\
+	:FD=\E\041k\r:FE=\E\041l\r:\
+	:ac=j\352k\353l\354m\355n\356q\361t\364u\365v\366w\367x\370:\
+	:bl=^G:cd=\EJ:ce=\EI:cl=\EH\EJ:cm=\EY%+ %+ :cr=^M:dc=\EQ:\
+	:dl=\EO:do=\EB:ho=\EH:k1=\Ea\r:k2=\Eb\r:k3=\Ec\r:k4=\Ed\r:\
+	:k5=\Ee\r:k6=\Ef\r:k7=\Eg\r:k8=\Eh\r:k9=\Ei\r:k;=\Ej\r:\
+	:kA=\EN:kB=\E2:kC=\EL\r:kD=\EQ:kE=\EI:kI=\EP \010:kL=\EO:\
+	:kN=\EI:kP=\EL:kS=\EJ:kT=\E0:ka=\E 1:kb=^H:kd=\EB:kh=\EH:\
+	:kl=\ED:kr=\EC:kt=\E1:ku=\EA:le=\ED:mb=\E4D:md=\E4H:\
+	:me=\E4@\E<@:mk=\E4P:mr=\E4A:nd=\EC:pf=^P^T:po=^P^R:\
+	:..sa=\E4%{64}%?%p1%t%{65}%|%;%?%p2%t%{66}%|%;%?%p3%t%{65}%|%;%?%p4%t%{68}%|%;%?%p5%t%{64}%|%;%?%p6%t%{72}%|%;%?%p7%t%{80}%|%;%c%?%p9%t\E>A%e\E<@%;:\
+	:se=\E4@:sf=^J:so=\E4A:te=\E>A:ti=\E>A:ue=\E4@:up=\EA:\
+	:us=\E4B:
+
+ibm3161-C|IBM 3161-C NLS terminal using cartridge:\
+	:s0=\E>B:s1=\E>A:te=\E>B:ti=\E>B:\
+	:tc=ibm3161:
+ibm3162|IBM 3162 display:\
+	:al=\EN:mb=\E4$a:md=\E4(a:me=\E4@:mk=\E40a:mr=\E4\041a:\
+	:se=\E4>b:so=\E4\041a:ue=\E4=b:us=\E4"a:\
+	:tc=ibm3161-C:
+
+# How the 3164 sgr string works:
+#	%{32}	        # push space for no special video characteristics
+#	%?%p2%t%{1}%|%; # if p2 set, then OR the 1 bit for reverse
+#	%?%p3%t%{4}%|%; # if p3 set, then OR the 4 bit for blink
+#	%?%p4%t%{2}%|%; # if p4 set, then OR the 2 bit for underline
+#	%c              # pop Pa1
+#	%{39}%p1%-	# calculate 32 + (7 - p1) for foreground
+#	%c		# pop Pa2 
+#	%{64}		# use only black background for now
+#	%c		# pop Pa3
+# (ibm3164: merged :ms:,<colors>,<pairs>,<setb>,<setf> from AIX 3.2.5 -- esr)
+ibm3164|i3164|IBM 3164:\
+	:ms:\
+	:Co#8:pa#64:\
+	:Sb=\E4  %+@:..Sf=\E4%?%p1%t %p1%{32}%+%c%e\041'%;@:\
+	:mb=\E4D:md=\E4H:me=\E4@:\
+	:..sa=\E4%{32}%?%p2%t%{1}%|%;%?%p3%t%{4}%|%;%?%p4%t%{2}%|%;%c%{39}%p1%-%c%{64}%c:tc=ibm3163:
+
+# From: <pryor@math.berkeley.edu>
+# (ibm5081: merged acsc, s0ds, s1ds, sgr0 into ibm5081 from AIX 3.2.5. -- esr)
+ibm5081|ibmmpel|IBM 5081 1024x1024 256/4096 Megapel color display:\
+	:es:hs:\
+	:li#33:\
+	:ac=jjkkllmmnnqqttuuvvwwxx:ds=\Ej\EYA \EI\Ek:fs=\Ek:\
+	:me=\E[0m\E(B:s0=\E(B:s1=\E(0:ts=\Ej\EYA%+ \Eo:\
+	:tc=ibmmono:
+ibm5081-c|ibmmpel-c|IBM 5081 1024x1024 256/4096 Megapel enhanced color display:\
+	:es:hs:\
+	:li#33:\
+	:ds=\Ej\EYA \EI\Ek:fs=\Ek:ts=\Ej\EYA%+ \Eo:tc=ibmega-c:
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+ibm5151|wy60-AT|wyse60-AT|IBM 5151 Monochrome display:\
+	:am:bw:ms:xo:\
+	:co#80:it#8:li#25:\
+	:AL=\E[%dL:DL=\E[%dM:DO=\E[%dB:LE=\E[%dD:RI=\E[%dC:\
+	:SF=\E[%dS:SR=\E[%dT:UP=\E[%dA:al=\E[L:bl=^G:cd=\E[J:\
+	:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:\
+	:dl=\E[M:do=^J:ec=\E[%dX:ei=\E[4l:ho=\E[H:im=\E[4h:is=\Ec:\
+	:k0=\E[010q:k1=\E[001q:k2=\E[002q:k3=\E[003q:k4=\E[004q:\
+	:k5=\E[005q:k6=\E[006q:k7=\E[007q:k8=\E[008q:k9=\E[009q:\
+	:kD=\E[P:kI=\E[139q:kN=\E[154q:kP=\E[150q:kb=^H:kd=\E[B:\
+	:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mb=\E[5m:md=\E[1m:\
+	:me=\E[0m:mr=\E[7m:nd=\E[C:rc=\E[u:sc=\E[s:se=\E[m:sf=\E[S:\
+	:so=\E[7m:sr=\E[T:ue=\E[m:up=\E[A:us=\E[4m:
+ibm5154|IBM 5154 Color display:\
+	:Co#8:pa#64:\
+	:AB=\E[4%p1%dm:AF=\E[3%p1%dm:md@:tc=ibm5151:
+ibm6153|IBM 6153 Black & White display:\
+	:mb@:md=\E[12m:me=\E[0;10m:s0=\E[10m:s1=\E[11m:s2=\E[12m:\
+	:..sa=\E[%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;12%;m:\
+	:tc=ibm5151:
+ibm6153-90|IBM 6153 Black & White display:\
+	:co#90:li#36:\
+	:mb@:md@:tc=ibm5151:
+ibm6153-40|IBM 6153 Black & White display:\
+	:co#40:li#12:tc=ibm6153-90:
+ibm6154|IBM 6154 Color displays:\
+	:mb@:md=\E[12m:me=\E[0;10m:s0=\E[10m:s1=\E[11m:s2=\E[12m:\
+	:..sa=\E[%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;12%;m:\
+	:tc=ibm5154:
+ibm6155|IBM 6155 Black & White display:\
+	:mb@:md@:tc=ibm5151:
+ibm8503|ibm8507|ibm8604|IBM 8503 B & W VGA display:\
+	:tc=hft-c:
+ibm8512|ibm8513|IBM color VGA Terminal:\
+	:am:mi:ms:\
+	:co#80:it#8:li#25:\
+	:AL=\E[%dL:DL=\E[%dM:RA=\E[?7l:SA=\E[?7h:\
+	:ac=jjkkllmmnnqqttuuvvwwxx:ae=^O:al=\E[L:as=^N:cd=\E[J:\
+	:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:dl=\E[M:dm=\E[4h:\
+	:do=^J:ec=\E[%dX:ed=\E[4l:ei=\E[4l:ho=\E[H:im=\E[4h:\
+	:is=\Eb\E[m\017\E[?7h:k0=\E[010q:k1=\E[001q:k2=\E[002q:\
+	:k3=\E[003q:k4=\E[004q:k5=\E[005q:k6=\E[006q:k7=\E[007q:\
+	:k8=\E[008q:k9=\E[009q:kd=\E[B:kh=\E[H:ku=\E[A:le=\E[D:\
+	:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:\
+	:r1=\Eb\E[m\017\E[?7h\E[H\E[J:rc=\E[u:sc=\E[s:se=\E[m:\
+	:so=\E[7m:te=\E[20h:ti=\E[20;4l\E[?7h\Eb:ue=\E[m:up=\E[A:\
+	:us=\E[4m:\
+	:tc=ibm8503:
+ibm8514|IBM 8514 color display:\
+	:es:hs:\
+	:li#41:\
+	:cr=^M:do=^J:ds=\Ej\EYI \EI\Ek:fs=\Ek:kb=^H:kd=^J:kl=^H:\
+	:nw=^M^J:sf=^J:ta=^I:ts=\Ej\EYI%+ \Eo:\
+	:tc=ibmega:
+ibm8514-c|IBM 8514 color display with standout and underline:\
+	:es:hs:\
+	:li#41:\
+	:cr=^M:do=^J:ds=\Ej\EYI \EI\Ek:fs=\Ek:kb=^H:kd=^J:kl=^H:\
+	:nw=^M^J:sf=^J:ta=^I:ts=\Ej\EYI%+ \Eo:\
+	:tc=ibmega-c:
+
+ibmaed|IBM Experimental display:\
+	:am:bs:eo:ms:\
+	:co#80:it#8:li#52:\
+	:al=\EN:cd=\EJ:ce=\EI:cl=\EH\EK:cm=\EY%+ %+ :dc=\EQ:dl=\EO:\
+	:do=\EB:ei=:ho=\EH:ic=\EP:im=:kb=^H:kd=\EB:kl=\ED:kr=\EC:\
+	:ku=\EA:le=^H:me=\E0:nd=\EC:se=\E0:so=\E0:ta=^I:up=\EA:\
+	:vb=\EG:
+ibm-apl|apl|IBM apl terminal simulator:\
+	:li#25:tc=dm1520:
+# (ibmmono: this had an unknown `sb' boolean, I changed it to `bs'.  
+# Also it had ":I0=f10:" which pretty obviously should be "l0=f10" -- esr)
+ibmmono|IBM workstation monochrome:\
+	:es:hs:\
+	:al=\EL:dl=\EM:ds=\Ej\EY8 \EI\Ek:fs=\Ek:k0=\E<:k1=\ES:\
+	:k2=\ET:k3=\EU:k4=\EV:k5=\EW:k6=\EP:k7=\EQ:k8=\ER:k9=\EY:\
+	:kF=\EE:kI=\0:kN=\EE:kP=\Eg:kR=\EG:kb=^H:kh=\EH:l0=f10:\
+	:md=\EZ:me=\Ew\Eq\Ez\EB:mk=\EF\Ef0;\Eb0;:mr=\Ep:se=\Ez:\
+	:so=\EZ:sr=\EA:ts=\Ej\EY8%+ \Eo:ue=\Ew:us=\EW:\
+	:tc=ibm3101:
+ibmega|IBM Enhanced Color Display:\
+	:cr=^M:do=^J:kb=^H:kd=^J:kl=^H:nw=^M^J:sf=^J:ta=^I:tc=ibmmono:
+ibmega-c|ibm5154-c|IBM Enhanced Color Display with standout and underline:\
+	:se=\EB:so=\EF\Ef3;:ue=\EB:us=\EF\Ef2;:\
+	:tc=ibmmono:
+ibmvga-c|IBM VGA display color termcap:\
+	:cr=^M:do=^J:kb=^H:kd=^J:kl=^H:nw=^M^J:sf=^J:ta=^I:tc=ibmega-c:
+ibmvga|IBM VGA display:\
+	:cr=^M:do=^J:kb=^H:kd=^J:kl=^H:nw=^M^J:sf=^J:ta=^I:tc=ibmega:
+# ibmapa* and ibmmono entries come from ACIS 4.3 distribution
+rtpc|ibmapa16|IBM 6155 Extended Monochrome Graphics Display:\
+	:li#32:\
+	:ds=\Ej\EY@ \EI\Ek:ts=\Ej\EY@%+ \Eo:tc=ibmmono:
+# Advanced Monochrome (6153) and Color (6154) Graphics Display:
+ibmapa8c|ibmapa8|IBM 6153/4 Advanced Graphics Display:\
+	:li#31:\
+	:ds=\Ej\EY? \EI\Ek:ts=\Ej\EY?%+ \Eo:tc=ibmmono:
+ibmapa8c-c|ibm6154-c|IBM 6154 Advanced Color Graphics Display:\
+	:li#31:\
+	:ds=\Ej\EY? \EI\Ek:mh=\EF\Ef7;:ts=\Ej\EY?%+ \Eo:tc=ibmega-c:
+hft-c-old|HFT with Color PC850:\
+	:Co#8:pa#64:\
+	:AB=\E[4%p1%dm:AF=\E[3%p1%dm:tc=ibm5151:
+# From: Marc Pawliger <marc@ibminet.awdpa.ibm.com>
+# also in /usr/lpp/bos/bsdsysadmin.
+# (hft-c: this entry had :kb=\E[D:kf=\E[C: on the line with ku/kd/kh; this was
+# pretty obviously mislabeled for :le: and :nd:; also ":ul=\E[4m:" was clearly
+# a typo for ":us=\E[4m:"; also ":el=\E[K:" was a typo for ":ce=\E[K:".
+# I also added <rmam>/<smam> based on the terminal reset string.
+# There was an unknown boolean ":ht:" which I assume was meant to set hardware
+# tabs, so I have inserted it#8. Finally, :ac=^N: paired with the :ae: looked
+# like a typo for :as=^N:; finally, added empty <acsc> to quiet tic -- esr)
+hft-c|IBM High Function Terminal:\
+	:am:mi:ms:\
+	:co#80:it#8:li#25:\
+	:AL=\E[%dL:DL=\E[%dM:RA=\E[?7l:SA=\E[?7h:\
+	:ac=jjkkllmmnnqqttuuvvwwxx:ae=^O:al=\E[L:as=^N:cd=\E[J:\
+	:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:dl=\E[M:dm=\E[4h:\
+	:do=^J:ec=\E[%dX:ed=\E[4l:ei=\E[4l:ho=\E[H:im=\E[4h:\
+	:is=\Eb\E[m\017\E[?7h:k0=\E[010q:k1=\E[001q:k2=\E[002q:\
+	:k3=\E[003q:k4=\E[004q:k5=\E[005q:k6=\E[006q:k7=\E[007q:\
+	:k8=\E[008q:k9=\E[009q:kd=\E[B:kh=\E[H:ku=\E[A:le=\E[D:\
+	:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:\
+	:r1=\Eb\E[m\017\E[?7h\E[H\E[J:rc=\E[u:sc=\E[s:se=\E[m:\
+	:so=\E[7m:te=\E[20h:ti=\E[20;4l\E[?7h\Eb:ue=\E[m:up=\E[A:\
+	:us=\E[4m:
+hft|AIWS High Function Terminal:\
+	:am:xo:\
+	:co#80:li#25:\
+	:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:\
+	:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:dl=\E[M:do=^J:ei=\E6:ho=\E[H:\
+	:ic=\E[@:im=\E6:k1=\E[001q:k2=\E[002q:k3=\E[003q:\
+	:k4=\E[004q:k5=\E[005q:k6=\E[006q:k7=\E[007q:k8=\E[008q:\
+	:k9=\E[009q:kN=\E[153q:kP=\E[159q:ka=\E[010q:kb=^H:\
+	:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mb=\E[5m:\
+	:md=\E[1m:me=\E[m:mk=\E[8m:mr=\E[7m:nd=\E[C:se=\E[m:sf=^J:\
+	:so=\E[7m:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:
+ibm-system1|system1|ibm system/1 computer:\
+	:am:xt:\
+	:co#80:li#24:\
+	:bl=^G:cl=^Z:cm=\005%+ %+ :ho=^K:le=^H:nd=^\:sf=^J:up=^^:
+#       lft-pc850 : IBM Low Function Terminal Device
+#    lft "supports" underline, bold, and blink in the sense that the lft code
+#    sets all the right bits.  HOWEVER, depending upon the adapter, these
+#    attributes may or may not be supported by the device driver.
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+lft|lft-pc850|LFT-PC850|IBM LFT PC850 Device:\
+	:am:bw:ms:xo:\
+	:co#80:it#8:li#25:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:SF=\E[%dS:SR=\E[%dT:UP=\E[%dA:\
+	:ae=\E(B:al=\E[L:as=\E(0:bl=^G:bt=\E[Z:cd=\E[2J:ce=\E[0K:\
+	:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:ct=\E[3g:dc=\E[P:\
+	:dl=\E[M:do=^J:ec=\E[%dX:ei=\E[4l:ho=\E[H:im=\E[4h:is=\Ec:\
+	:k1=\E[001q:k2=\E[002q:k3=\E[003q:k4=\E[004q:k5=\E[005q:\
+	:k6=\E[006q:k7=\E[007q:k8=\E[008q:k9=\E[009q:kD=\E[P:\
+	:kI=\E[139q:kN=\E[154q:kP=\E[150q:kb=^H:kd=\E[B:kh=\E[H:\
+	:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mb=\E[5m:md=\E[1m:me=\E[0m:\
+	:mr=\E[7m:nd=\E[C:se=\E[0m:sf=\ED:so=\E[7m:sr=\EL:ue=\E[0m:\
+	:up=\E[A:us=\E[4m:
+
+#
+# AIX entries.  IBM ships these with AIX 3.2.5. 
+# AIX extension caps are commented out,
+# except for box1 which has been translated to an <acsc> string.
+#
+aixterm|IBM Aixterm Terminal Eemulator:\
+	:es:hs:\
+	:ac=jjkkllmmnnqqttuuvvwwxx:ds=\E[?E:fs=\E[?F:md=\E[1m:\
+	:me=\E[0;10m\E(B:s0=\E(B:s1=\E(0:\
+	:..sa=\E[%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;m:\
+	:sr@:ts=\E[?%p1%dT:\
+	:tc=ibm6154:
+aixterm-m|IBM AIXterm Monochrome Terminal Emulator:\
+	:es:hs:\
+	:ac=jjkkllmmnnqqttuuvvwwxx:ds=\E[?E:fs=\E[?F:md=\E[1m:\
+	:me=\E[0;10m\E(B:s0=\E(B:s1=\E(0:\
+	:..sa=\E[%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;m:\
+	:sr@:ts=\E[?%p1%dT:\
+	:tc=ibm6153:
+aixterm-m-old|old IBM AIXterm Monochrome Terminal Emulator:\
+	:es:hs:\
+	:ds=\E[?E:fs=\E[?F:md=\E[1m:\
+	:..sa=\E[%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;m:\
+	:sr@:ts=\E[?%p1%dT:\
+	:tc=ibm6153:
+jaixterm|IBM Kanji Aixterm Terminal Eemulator:\
+	:ac@:tc=aixterm:
+jaixterm-m|IBM Kanji AIXterm Monochrome Terminal Emulator:\
+	:ac@:\
+	:tc=aixterm-m:
+
+#### Infoton/General Terminal Corp.
+#
+
+# gt100 sounds like something DEC would come out with.  Let's hope they don't.
+i100|gt100|gt100a|General Terminal 100A (formerly Infoton 100):\
+	:am:bs:\
+	:co#80:li#24:\
+	:al=\EL:bl=^G:cd=\EJ:ce=\EK:cl=^L:cm=\Ef%r%+ %+ :cr=^M:\
+	:dl=\EM:do=^J:ho=\EH:le=^H:nd=\EC:se=\Ea:sf=^J:so=\Eb:up=\EA:\
+	:vb=\Eb\Ea:
+i400|infoton 400:\
+	:am:bs:\
+	:co#80:li#25:\
+	:al=\E[L:bl=^G:ce=\E[N:cl=\E[2J:cm=%i\E[%3;%3H:cr=^M:\
+	:dc=\E[4h\E[2Q\E[P\E[4l\E[0Q:dl=\E[M:do=^J:\
+	:ei=\E[4l\E[0Q:im=\E[4h\E[2Q:le=^H:nd=\E[C:sf=^J:up=\E[A:
+# (addrinfo: removed obsolete ":bc=^Z:" -- esr)
+addrinfo:\
+	:am:\
+	:co#80:li#24:\
+	:bl=^G:cd=^K:cl=^L:..cm=\037%p1%{1}%-%c%p2%{1}%-%c:cr=^M:\
+	:do=^J:ho=^H:le=^Z:ll=^H^\:nd=^Y:sf=^J:up=^\:
+# (infoton: used to have the no-ops <lh#0>, <lw#0>, <nlab#0> -- esr)
+infoton:\
+	:am:\
+	:co#80:li#24:\
+	:bl=^G:cd=^K:cl=^L:cr=^M:do=^J:le=^Z:ll=^H^\:nd=^Y:sf=^J:\
+	:up=^\:
+
+# The ICL6402 was actually the Kokusai Display System 6402.
+# The 6404 was the KDS7372 (color version of the 6402).
+# 
+# ICL6404 control codes follow:
+#
+#code            function
+#~~~~~~~~~~~     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#ctrl-A          set SOM position at cursor position
+#ctrl-G          Bell
+#ctrl-H          Backspace
+#ctrl-I          Horiz tab
+#ctrl-J          Linefeed
+#ctrl-K          Cursor up
+#ctrl-L          Cursor right
+#ctrl-M          Carriage return
+#ctrl-N          Disable xon/xoff to host
+#ctrl-O          Enable xon/xoff to host
+#ctrl-R          Enable bidirectional mode
+#ctrl-T          Disable bidirectional mode
+#ctrl-V          Cursor down
+#ctrl-Z          Clear unprotected data to insert char
+#ctrl-^          Cursor home
+#ctrl-_          Newline
+#
+#ESC             lead-in char for multiple character command
+#
+#ESC space R     execute power on sequence
+#ESC ! p1 p2     define scroll region:
+#                p1 = scroll top    line:  20h - 37h
+#                p1 = scroll bottom line:  20h - 37h
+#ESC "           unlock keyboard
+#ESC #           lock keyboard
+#ESC $           Semi-graphics mode on
+#ESC %           Semi-graphics mode off
+#ESC &           protect mode on
+#ESC '           protect mode off
+#ESC (           write protect mode off (full intensity)
+#ESC )           write protect mode on (half intensity)
+#
+#ESC *           clear screen
+#ESC +           clear unprotected data to insert char
+#ESC ,           clear unprotected data to half intensity spaces
+#ESC - p1 p2 p3 p4     address cursor to page, row, column:
+#                      p1 = page number  0 - 3
+#                      p2 = row          20h - 7fh
+#                      p3 = column (lo)  20h - 7fh
+#                      p4 = column (hi)  20h - 21h (only 132 col)
+#ESC . p1        set cursor style:
+#                p1 = 0  invisible cursor
+#                p1 = 1  block blinking cursor
+#                p1 = 2  block steady cursor
+#                p1 = 3  underline blinking cursor
+#                p1 = 4  underline steady cursor
+#ESC /           transmit cursor location (page, row, column)
+#ESC 0 p1 p2 p3 p4     program edit key:
+#                      p1 = edit key code: '@'-'S', '`'-'s'
+#                      p2 p3 p4 = program data (3 bytes)
+#
+#ESC 1           set tab
+#ESC 2           clear tab at cursor
+#ESC 3           clear all tabs
+#ESC 4           send unprotect line to cursor
+#ESC 5           send unprotect page to cursor
+#ESC 6           send line to cursor
+#ESC 7           send page to cursor
+#ESC 8 n         set scroll mode:
+#                n = 0   set jump scroll
+#                n = 1   set smooth scroll
+#ESC 9 n         control display:
+#                n = 0   display off
+#                n = 1   display on
+#ESC :           clear unprotected data to null
+#ESC ;           clear unprotected data to insert char
+#
+#ESC <           keyclick on
+#ESC = p1 p2     address cursor to row, column
+#                p1 = row          20h - 7fh
+#                p2 = column (lo)  20h - 7fh
+#                p3 = column (hi)  20h - 21h (only 132 col)
+#ESC >           keyclick off
+#ESC ?           transmit cursor location (row, column)
+#
+#ESC @           copy print mode on
+#ESC A           copy print mode off
+#ESC B           block mode on
+#ESC C           block mode off (conversation mode)
+#ESC D F         set full duplex
+#ESC D H         set half duplex
+#ESC E           line insert
+#ESC F p1 p2     set page colour (p1 = f/grnd, p2 = b/grnd)
+#                0 = black, 1 = red,     2 = green, 3 = yellow
+#                4 = blue,  5 = magenta, 6 = cyan,  7 = white
+#ESC G n         set serial field attribute (n = 30h - 3Fh)
+#ESC H n         full graphics mode:
+#                n = 0  exit full graphics mode
+#                n = 1  enter full graphics mode
+#ESC I           back tab
+#ESC J           back page
+#ESC K           forward page
+#
+#ESC L           unformatted page print
+#ESC M L         move window left  (132 col mode only)
+#ESC M R         move window right (132 col mode only)
+#ESC N           set page edit (clear line edit)
+#ESC O           set line edit (clear page edit)
+#ESC P           formatted page print
+#ESC Q           character insert
+#ESC R           line delete
+#ESC S           send message unprotected only
+#ESC T           erase line to insert char
+#ESC U           set monitor mode   (see ESC X, ESC u)
+#
+#ESC V n         select video attribute mode:
+#                n = 0   serial field attribute mode
+#                n = 1   parallel character attribute mode
+#ESC V 2 n       define line attribute:
+#                n = 0   single width single height
+#                n = 1   single width double height
+#                n = 2   double width single height
+#                n = 3   double width double height
+#ESC V 3 n       select character font:
+#                n = 0   system font
+#                n = 1   user defined font
+#ESC V 4 n       select screen mode:
+#                n = 0   page screen mode
+#                n = 1   virtual screen mode
+#ESC V 5 n       control mouse mode:
+#                n = 0   disable mouse
+#                n = 1   enable sample mode
+#                n = 2   send mouse information
+#                n = 3   enable request mode
+#ESC W           character delete
+#ESC X           clear monitor mode (see ESC U, ESC u)
+#ESC Y           erase page to insert char
+#
+#ESC Z n         send user/status line:
+#                n = 0   send user line
+#                n = 1   send status line
+#                n = 2   send terminal ID
+#ESC [ p1 p2 p3  set character attribute (parallel char mode):
+#                p1: 0 = normal
+#                    1 = blank
+#                    2 = blink
+#                    3 = blink blank (= blank)
+#                    4 = reverse
+#                    5 = reverse blank
+#                    6 = reverse blink
+#                    7 = reverse blink blank (= reverse blank)
+#                    8 = underline
+#                    9 = underline blank
+#                    : = underline blink
+#                    ; = underline blink blank
+#                    < = reverse underline
+#                    = = reverse underline blank
+#                    > = reverse underline blink
+#                    ? = reverse underline blink blank
+#                p2, p3: f/grnd, b/grnd colour
+#                (see ESC F for colours)
+#                use ZZ for mono, eg.
+#                    ESC [ 0 Z Z for normal
+#                    ESC [ 4 Z Z for inverse etc.
+#
+#ESC \ n         set page size:
+#                n = 1   24 lines/page
+#                n = 2   48 lines/page
+#                n = 3   72 lines/page
+#                n = 4   96 lines/page
+#ESC ] n         set Wordstar mode:
+#                n = 0   normal (KDS7372) mode
+#                n = 1   Wordstar mode
+#
+#ESC b           set foreground colour screen
+#
+#ESC c n         enter self-test mode:
+#                n = 0   exit self test mode
+#                n = 1   ROM test
+#                n = 2   RAM test
+#                n = 3   NVRAM test
+#                n = 4   screen display test
+#                n = 5   main/printer port test
+#                n = 6   mouse port test
+#                n = 7   graphics board test
+#                n = 8   graphics memory test
+#                n = 9   display all 'E'
+#                n = :   display all 'H'
+#ESC d           set background colour screen
+#
+#ESC e n         program insert char (n = insert char)
+#ESC f text CR   load user status line with 'text'
+#
+#ESC g           display user status line on 25th line
+#ESC h           display system status line on 25th line
+#ESC i           tab
+#ESC j           reverse linefeed
+#ESC k n         duplex/local edit mode:
+#                n = 0   duplex edit mode
+#                n = 1   local edit mode
+#ESC l n         select virtual screen:
+#                n = 0   screen 1
+#                n = 1   screen 2
+#ESC m           save current config to NVRAM
+#ESC n p1        select display screen:
+#                p1 = 0  screen 1
+#                p1 = 1  screen 2
+#                p1 = 2  screen 3
+#                p1 = 3  screen 4
+#ESC o p1 p2     set characters/line and attribute:
+#                p1 = 0  80 chars/line
+#
+#ESC o p1 p2     set characters/line and attribute:
+#                p1 = 0  80 chars/line
+#                p1 = 1  132 chars/line
+#                p2 = 0  single width single height
+#                p2 = 1  single width double height
+#                p2 = 2  double width single height
+#                p2 = 3  double width double height
+#
+#ESC q           insert mode on
+#ESC r           edit mode on
+#ESC s           send message all
+#ESC t           erase line to null
+#ESC u           clear monitor mode (see ESC U, ESC X)
+#ESC v           autopage mode on
+#ESC w           autopage mode off
+#ESC x p1 p2 p3  define delimiter code...
+#ESC y           erase page to null
+#
+#ESC z 2 p1 p2 p3 p4   draw quadrangle:
+#                      p1 = starting row
+#                      p2 = starting column
+#                      p3 = end row
+#                      p4 = end column
+#
+#ESC { p1 p2 p3 p4     configure main port
+#                      (baud, stop bits, parity, word length)
+#
+#ESC | p1 p2 text Ctrl-Y    program function key with 'text':
+#                        p1 = function key code:
+#                             '1' - ';'  normal f1- f11
+#                             '<' - 'F'  shifted f1 - f11
+#                        p2 = program mode:
+#                             1 = FDX
+#                             2 = LOC
+#                             3 = HDX
+#                        Ctrl-Y = terminator
+#                        (use Ctrl-P to escape ^P, ^Y )
+#
+#ESC } p1 p2 p3 p4     configure printer port
+#                      (baud, stop bits, parity, word length)
+#ESC ~           send system status
+#
+# Codes and info from Peter Disdale <pete@pdlmail.demon.co.uk> 12 May 1997
+#
+# Entry is by esr going solely on above information and is UNTESTED.
+# This actually looks a lot like a Televideo 9xx.
+# This entry uses page 0 and is monochrome; I'm not brave enough to try
+# to make color work without a test terminal.  The :am: capability is a guess.
+# The initialization string sets conversation mode, blinking underline cursor,
+# full duplex, parallel attribute mode, display user status line, white
+# foreground, black background, normal highlight.
+#
+icl6404|kds7372|icl6402|kds6402|ICL 6404 aka Kokusai Display Systems 7372:\
+	:am:bs:hs:\
+	:co#80:li#24:\
+	:DC=\EW:al=\EE:bl=^G:bt=\EI:cl=\E*:cm=\E=%+ %+P%+P:cr=^M:\
+	:..cs=\E\041%+%p1%{32}%+%p2%{32} cud1=\026:ct=\E3:\
+	:dl=\ER:ei=\Er:ho=^^:i1=\EC\E.3\EDF\EV1\Eg\E[0ZZ:im=\Eq:\
+	:mb=\E[2ZZ:me=\E[0ZZ:mk=\E[1ZZ:mr=\E[4ZZ:nd=^L:nw=^_:\
+	:r2=\Eo1:\
+	:..sa=\E[%{0}%?%p1%t%{4}%|%;%?%p2%t%{8}%|%;%?%p3%t%{4}%|%;%?%p4%t%{2}%|%;%?%p7%t%{1}%|%;ZZ:\
+	:se=\E[%gh%{4}%^%Ph%gh%dZZ:so=\E[8ZZ:st=\E1:ta=^I:\
+	:ue=\E[%gh%{8}%^%Ph%gh%dZZ:up=^K:us=\E[8ZZ:ve=\E.3:\
+	:vi=\E.0:vs=\E.1:
+icl6404-w|kds7372-w|ICL 6404 aka Kokusai Display Systems 7372 132 cols:\
+	:r2=\Eo1:\
+	:tc=icl6404:
+
+#### Interactive Systems Corp
+#
+# ISC used to sell OEMed and customized hardware to support ISC UNIX.
+# ISC UNIX still exists in 1995, but ISC itself is no more; they got
+# bought out by Sun.
+#
+
+# From: <cithep!eric>  Wed Sep 16 08:06:44 1981
+# (intext: removed obsolete ":ma=^K^P^R^L^L ::bc=^_:", also the
+# ":le=^_:" later overridden -- esr)
+intext|Interactive Systems Corporation modified owl 1200:\
+	:am:bs:\
+	:co#80:it#8:li#24:sg#1:\
+	:al=\020:bl=^G:bt=^Y:cd=\026J:ce=^Kp^R:cl=\014:\
+	:cm=\017%+ %+ :cr=^M:dc=\022:dl=\021:do=^J:ei=^V<:im=^V;:\
+	:ip=:k0=^VJ\r:k1=^VA\r:k2=^VB\r:k3=^VC\r:k4=^VD\r:k5=^VE\r:\
+	:k6=^VF\r:k7=^VG\r:k8=^VH\r:k9=^VI\r:kb=^H:kd=^J:ke=^V9:\
+	:kh=^Z:kl=^_:kr=^^:ks=\036\072\264\026%:ku=^\:le=^H:nd=^^:\
+	:se=^V# :sf=^J:so=^V$\054:ta=^I:up=^\:
+intext2|intextii|INTERACTIVE modified owl 1251:\
+	:am:bw:ul:\
+	:co#80:li#24:sg#0:\
+	:al=\E[L:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:ch=\E[%+^AG:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:dl=\E[M:\
+	:do=\E[B:ei=:ic=\E[@:im=:k0=\E@\r:k1=\EP\r:k2=\EQ\r:\
+	:k3=\ES\r:k4=\ET\r:k5=\EU\r:k6=\EV\r:k7=\EW\r:k8=\EX\r:\
+	:k9=\EY\r:kb=^H:kd=\EB\r:kh=\ER\r:kl=\ED\r:kr=\EC\r:\
+	:ku=\EA\r:l0=REFRSH:l1=DEL CH:l2=TABSET:l3=GOTO:l4=+PAGE:\
+	:l5=+SRCH:l6=-PAGE:l7=-SRCH:l8=LEFT:l9=RIGHT:nd=\E[C:\
+	:se=\E[2 D:sf=\E[S:so=\E[6 D:sr=\E[T:ta=^I:ue=\E[2 D:\
+	:up=\E[A:us=\E[18 D:\
+	:vb=\E[;;;;;;;;;2;;u\E[;;;;;;;;;1;;u:
+
+#### Kimtron (abm, kt)
+#
+# Kimtron seems to be history, but as March 1998 these people are still 
+# offering repair services for Kimtron equipment:
+#
+#    Com/Pair Monitor Service
+#    1105 N. Cliff Ave.
+#    Sioux Falls, South Dakota 57103
+#     
+#    WATS voice:  1-800/398-4946
+#    POTS   fax: +1 605/338-8709
+#    POTS voice: +1 605/338-9650
+#         Email: <compair@sd.cybernex.net>
+#  Internet/Web: <http://www.com-pair.com>
+#
+# Kimtron entries include (undocumented) codes for: enter dim mode,
+# enter bold mode, enter reverse mode, turn off all attributes.
+#
+
+# Kimtron ABM 85 added by Dual Systems
+# (abm85: removed duplicated ":kd=^J:" -- esr)
+abm85|Kimtron ABM 85:\
+	:am:bs:bw:ms:\
+	:co#80:it#8:li#24:sg#1:\
+	:al=\EE:bt=\EI:cd=\Ey:ce=\Et:cl=\E*:cm=\E=%+ %+ :dc=\EW:\
+	:dl=\ER:do=^J:ei=\Er:if=/usr/share/tabset/stdcrt:im=\EQ:\
+	:is=\EC\EX\Eg\En\E%\Er\E(\Ek\Em\Eq:kb=^H:kd=^J:kh=^^:\
+	:kl=^H:kr=^L:ku=^K:le=^H:nd=^L:se=\Ek:so=\Ej:ta=^I:ue=\Em:\
+	:up=^K:us=\El:
+# Kimtron ABM 85H added by Dual Systems.
+# Some notes about the abm85h entries:
+# 1) there are several firmware revs of 85H in the world. Use abm85h-old for
+#    firmware revs prior to SP51
+# 2) Make sure to use abm85h entry if the terminal is in 85h mode and the
+#    abm85e entry if it is in tvi920 emulation mode. They are incompatible
+#    in some places and NOT software settable i.e., :is: can't fix it)
+# 3) In 85h mode, the arrow keys and special functions transmit when
+#    the terminal is in dup-edit, and work only locally in local-edit.
+#    Vi won't swallow `del char' for instance, but :ti: turns on
+#    dup-edit anyway so that the arrow keys will work right. If the
+#    arrow keys don't work the way you like, change :ti:, :te:, and
+#    :is:.  Note that 920E mode does not have software commands to toggle
+#    between dup and local edit, so you get whatever was set last on the
+#    terminal.
+# 4) :vb: attribute is nice, but seems too slow to work correctly
+#    (\Eb:pc:\Ed)
+# 5) Make sure `hidden' attributes are selected. If `embedded' attributes
+#    are selected, the <xmc@> entry should be removed.
+# 6) auto new-line should be on (selectable from setup mode only)
+#
+# From: Erik Fair <fair@ucbarpa>  Sun Oct 27 07:21:05 1985
+abm85h|Kimtron ABM 85H native mode:\
+	:hs:\
+	:sg@:\
+	:bl=^G:ds=\Ee:fs=^M:im=\EZ:\
+	:is=\EC\EN\EX\024\016\EA\Ea\E%\E9\Ee\Er\En\E"\E}\E'\E(\Ef\r\EG0\Ed\E.4\El:\
+	:kd=^V:me=\E(\EG0:mh=\E):mk@:ts=\Eg\Ef:vb@:ve=\E.4:vs=\E.2:\
+	:tc=adm+sgr:tc=abm85:
+abm85e|Kimtron ABM 85H in 920E mode:\
+	:sg@:\
+	:bl=^G:im=\EZ:\
+	:is=\EC\EX\EA\E%\E9\Ee\Er\En\E"\E}\E'\E(\Ef\r\Ek\Eq\Em:\
+	:me=\E(\Ek:mh=\E):mr=\Ej:vb@:\
+	:tc=abm85:
+abm85h-old|oabm85h|o85h|Kimtron ABM 85H with old firmware rev.:\
+	:sg@:\
+	:bl=^G:im=\EZ:\
+	:is=\E}\EC\EX\Ee\En\E%\Er\E(\Ek\Em\Eq\Ed\ET\EC\E9\EF:\
+	:me=\E(\Ek:mh=\E):mr=\Ej:\
+	:tc=abm85:
+# From: <malman@bbn-vax.arpa>
+# (kt7: removed obsolete :ma=^V^J^L :" -- esr)
+kt7|kimtron model kt-7:\
+	:am:bs:\
+	:co#80:it#8:li#24:\
+	:al=\EE:bt=\EI:cd=\EY:ce=\ET:cl=^Z:cm=\E=%+ %+ :dc=\EW:\
+	:dl=\ER:do=^V:ei=:fs=\Eg:ho=^^:ic=\EQ:\
+	:if=/usr/share/tabset/stdcrt:im=:is=\El\E":k0=^AI\r:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:k9=^AH\r:kA=\EE:kB=\EI:kC=^Z:kD=\EW:\
+	:kE=\ET:kI=\EQ:kL=\ER:kS=\EY:kb=^H:kd=^V:kh=^^:kl=^H:kr=^L:\
+	:ku=^K:le=^H:mk@:nd=^L:ta=^I:ts=\Ef:up=^K:\
+	:tc=adm+sgr:
+# Renamed TB=^I to :ta:, BE=^G to :bl:, BS=^H to :kb:, N to :kS: (based on the
+# other kt7 entry and the adjacent key capabilities).  Removed EE which is
+# identical to :mh:.  Removed :ES=\EGD: which is some kind of highlight
+# but we can't figure out what.
+kt7ix|kimtron model kt-7 or 70 in IX mode:\
+	:am:bw:\
+	:co#80:it#8:li#25:\
+	:@7=\EY:PU=\EK:ac=jYk?lZm@nEqDt4uCvAwBx3:ae=\E%:al=\EE:\
+	:as=\E$:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=\E*:cm=\E=%+ %+ :\
+	:cr=^M:dc=\EW:dl=\ER:do=^V:ds=\Ef\r:ei=:fs=^M:ho=^^:ic=\EQ:\
+	:im=:is=\EG0\E s\017\E~:k0=^AI\r:k1=^A@\r:k2=^AA\r:\
+	:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:\
+	:k9=^AH\r:kA=\EE:kB=\EI:kC=\E*:kE=\ET:kI=\EQ:kL=\ER:kN=\EJ:\
+	:kS=\EY:kb=^H:kd=\E[B:kh=^^:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:\
+	:mb=\EG2:me=\EG0:mh=\EG@:nd=^L:nw=^M^J:se=\EG0:sf=^J:\
+	:so=\EG4:ta=^I:ts=\Ef:ue=\EG0:up=^K:us=\EG8:ve=\E.3:vi=\E.0:
+
+#### Microdata/MDIS
+#
+# This was a line of terminals made by McDonnell-Douglas Information Systems.
+# These entries come direct from MDIS documentation.  I have edited them only
+# to move primary names of the form p[0-9] * to aliases, and to comment out
+# :ae:/:as: in a couple of entries without <acsc> strings.  I have 
+# also removed the change history; the last version indicates this is
+# version 4.3 by A.Barkus, September 1990 (earliest entry is October 1989).
+#
+
+# McDonnell Information Systems Terminal Family History
+# =========================================
+#
+# Prism-1, Prism-2 and P99:
+#       Ancient Microdata and CMC terminals, vaguely like Adds Regent 25.
+#
+# Prism-4 and Prism-5:
+#       Slightly less ancient range of Microdata terminals. Follow-on from
+#       Prism-2, but with many enhancements. P5 has eight display pages.
+#
+# Prism-6:
+#       A special terminal for use with library systems, primarily in Germany.
+#       Limited numbers. Similar functionality to P5 (except attributes?).
+#
+# Prism-7, Prism-8 and Prism-9:
+#       More recent range of MDIS terminals, in which P7 and P8
+#       replace the P4 & P5, with added functionality, and P9 is the flagship.
+#       The P9 has two emulation modes - P8 and ANSI - and includes a
+#       large number of the DEC VT220 control sequences. Both
+#       P8 and P9 support 80c/24ln/8pg and 132cl/24li/4pg formats.
+#
+# Prism-12 and Prism-14:
+#       Latest range, functionally very similar to the P9.  The P14 has a
+#       black-on-white overscanning screen.
+#
+# The terminfo definitions given here are:
+#
+# p2      - Prism-2 (or Prism-1 or P99).
+#
+# p4      - Prism-4 (and older P7s & P8s).
+# p5      - Prism-5 (or Prism-6).
+#
+# p7      - Prism-7.
+# p8      - Prism-8 (in national or multinational mode).
+# p8-w    - 132 column version of p8.
+# p9      - Prism-9 in ANSI mode.
+# p9-w    - 132 column version of p9.
+# p9-8    - Prism-9 in Prism-8 emulation mode.
+# p9-8-w  - As p9-8, but with 132 columns.
+#
+# p12     - Prism-12 in ANSI mode.
+# p12-w   - 132 column version of p12.
+# p12-m   - Prism-12 in MDC emulation mode.
+# p12-m-w - As p12-m, but with 132 columns.
+# p14     - Prism-14 in ANSI mode.
+# p14-w   - 132 column version of p14.
+# p14-m   - Prism-14 in MDC emulation mode.
+# p14-m-w - As p14-m, but with 132 columns.
+#
+# p2: Prism-2
+# -----------
+#
+# Includes Prism-1 and basic P99 without SP or MP loaded.
+# The simplest form of Prism-type terminal.
+# Basic cursor movement and clearing operations only.
+# No video attributes.
+# Notes:
+#  Horizontal cursor qualifiers of NUL, XON and XOFF are mapped to the next
+#  value up, followed by backspace.
+#
+prism2|MDC Prism-2:\
+	:am:bw:ms:\
+	:co#80:li#24:\
+	:bl=^G:cd=\EJ:ce=\EK:\
+	:..ch=\020%p1%{10}%/%{16}%*%p1%{10}%m%+%Pc%?%{17}%gc%=%{19}%gc%=%|%gc%!%|%t%{1}%gc%+%c%{8}%e%gc%;%c:\
+	:cl=\014:\
+	:..cm=\013%p1%{32}%+%c\020%p2%{10}%/%{16}%*%p2%{10}%m%+%Pc%?%{17}%gc%=%{19}%gc%=%|%gc%!%|%t%{1}%gc%+%c%{8}%e%gc%;%c:\
+	:cr=^M:cv=\013%+ :do=^J:ho=^A:kb=^H:kh=^A:le=^H:nd=^F:sf=^J:\
+	:up=^Z:
+
+# p4: Prism-4
+# -----------
+#
+# Includes early versions of P7 & P8.
+# Basic family definition for most Prisms (except P2 and P9 ANSI).
+# Notes:
+#  Horizontal cursor qualifiers of NUL, XON and XOFF are mapped to the next
+#  value up, followed by backspace.
+#  Cursor key definitions removed because they interfere with vi and csh keys.
+#
+prism4|p4|P4|MDC Prism-4:\
+	:5i:am:bw:hs:ms:\
+	:co#80:li#24:sg#1:ws#72:\
+	:bl=^G:cd=\EJ:ce=\EK:\
+	:..ch=\020%p1%{10}%/%{16}%*%p1%{10}%m%+%Pc%?%{17}%gc%=%{19}%gc%=%|%gc%!%|%t%{1}%gc%+%c%{8}%e%gc%;%c:\
+	:cl=\014:\
+	:..cm=\013%p1%{32}%+%c\020%p2%{10}%/%{16}%*%p2%{10}%m%+%Pc%?%{17}%gc%=%{19}%gc%=%|%gc%!%|%t%{1}%gc%+%c%{8}%e%gc%;%c:\
+	:cr=^M:cv=\013%+ :do=^J:ds=\035\343\035\345:fs=^]\345:\
+	:ho=^A:kb=^H:kh=^A:le=^H:mb=^CB:me=^C :mh=^CA:mk=^CH:mr=^CD:\
+	:nd=^F:pf=\ET:po=\ER:ps=\EU:\
+	:..sa=\003%{64}%?%p1%p3%|%t%{4}%+%;%?%p2%t%{16}%+%;%?%p4%t%{2}%+%;%?%p5%t%{1}%+%;%?%p7%t%{8}%+%;%c%?%p9%t\016%e\017%;:\
+	:se=^C :sf=^J:so=^CD:ts=^]\343:ue=^C :up=^Z:us=^CP:\
+	:ve=^]\342:vi=^]\344:
+
+# p5: Prism-5
+# -----------
+#
+# Same definition as p4. Includes Prism-6 (not tested!).
+# Does not use any multi-page features.
+#
+prism5|p5|P5|MDC Prism-5:\
+	:tc=p4:
+
+# p7: Prism-7
+# -----------
+#
+# Similar definition to p4. Uses ANSI cursor motion to avoid network problems.
+# Notes:
+#  Use p4 for very early models of P7.
+#  Rev-index removed; can't send nulls to terminal in 8-bit modes.
+#
+prism7|p7|P7|MDC Prism-7:\
+	:ch@:cm=\E[%i%d;%dH:cv@:tc=p4:
+
+# p8: Prism-8
+# -----------
+#
+# Similar definition to p7. Uses ANSI cursor motion to avoid network problems.
+# Supports national and multinational character sets.
+# Notes:
+#  Alternate char set operations only work in multinational mode.
+#  Use p4 for very early models of P8.
+#  Rev-index removed; can't send nulls to terminal in 8-bit modes.
+# (esr: commented out :as:/:ae: because there's no <acsc>)
+#
+prism8|p8|P8|MDC Prism-8:\
+	:ch=\E[%i%d`:cm=\E[%i%d;%dH:cv=\E[%i%dd:is=\E[<12h:tc=p4:
+
+# p8-w: Prism-8 in 132 column mode
+# --------------------------------
+#
+# 'Wide' version of p8.
+# Notes:
+#  Rev-index removed; can't send nulls to terminal in 8-bit modes.
+#
+prism8-w|p8-w|P8-W|MDC Prism-8 in 132 column mode:\
+	:co#132:\
+	:is=\E[<12h\E[<14h:tc=p8:
+
+# p9: Prism-9 in ANSI mode
+# -------------------------
+#
+# The "flagship" model of this generation of terminals.
+# ANSI X3.64 (ISO 6429) standard sequences, plus many DEC VT220 ones.
+# Notes:
+#  Tabs only reset by "reset". Otherwise assumes default (8 cols).
+#  Fixes to deal with terminal firmware bugs:
+#  . 'ri' uses insert-line since rev index doesn't always
+#  . 'sgr0' has extra '0' since esc[m fails
+#  . 'fsl' & 'dsl' use illegal char since cr is actioned wrong on line 25
+#  Not covered in the current definition:
+#  . Labels
+#  . Programming Fn keys
+#  . Graphic characters (defaults correctly to vt100)
+#  . Padding values (sets xon)
+# (esr: commented out :as:/:ae: because there's no <acsc>)
+#
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+prism9|p9|P9|MDC Prism-9 in ANSII mode:\
+	:5i:am:bw:hs:ms:xn:xo:\
+	:co#80:it#8:li#24:vt#3:ws#72:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:F1=\E[23~:\
+	:F2=\E[24~:F3=\E[25~:F4=\E[26~:F5=\E[28~:F6=\E[29~:\
+	:F7=\E[31~:F8=\E[32~:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:\
+	:al=\E[L:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:ch=\E[%i%d`:cl=^L:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%d%v:ct=\E[2g:\
+	:cv=\E[%i%dd:dc=\E[P:dl=\E[M:do=^J:ds=\E[%}\024:ec=\E[%dX:\
+	:ei=\E[4l:fs=^T:ho=\E[H:im=\E[4h:is=\E[&p\E[<12l\E F:\
+	:k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~:k5=\E[15~:\
+	:k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:k;=\E[21~:kC=^L:\
+	:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:\
+	:mb=\E[5m:md=\E[1m:me=\E[0m:mp=\E[32%{:mr=\E[7m:nd=\E[C:\
+	:nw=^M^J:pf=\E[4i:po=\E[5i:ps=\E[i:\
+	:r2=\E[&p\E[<12l\E F\E[3g\E[9;17;25;33;41;49;57;65;73 N:\
+	:rc=\E[%z:rp=\E[%r%db%.:sc=\E[%y:se=\E[27m:sf=^J:so=\E[7m:\
+	:sr=\E[L:st=\EH:ta=^I:ts=\E[%i%p1%d%%}:ue=\E[24m:up=\E[A:\
+	:us=\E[4m:ve=\E[<4h:vi=\E[<4l:
+
+# p9-w: Prism-9 in 132 column mode
+# --------------------------------
+#
+# 'Wide' version of p9.
+#
+prism9-w|p9-w|P9-W|MDC Prism-9 in 132 column mode:\
+	:co#132:\
+	:is=\E[&p\E[<12l\E F\E[<14h:\
+	:r2=\E[&p\E[<12l\E F\E[<14h:tc=p9:
+
+# p9-8: Prism-9 in P8 mode
+# ------------------------
+#
+# P9 terminal in P8 emulation mode.
+# Similar to p8 definition.
+# Insertion and deletion operations possible.
+#
+prism9-8|p9-8|P9-8|MDC Prism-9 in P8 mode:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:IC=\E[%d@:al=\E[L:dc=\E[P:\
+	:dl=\E[M:ei=:ic=\E[@:im=:\
+	:tc=p8:
+
+# p9-8-w: Prism-9 in P8 and 132 column modes
+# ------------------------------------------
+#
+# P9 terminal in P8 emulation mode and 132 column mode.
+#
+prism9-8-w|p9-8-w|P9-8-W|MDC Prism-9 in Prism 8 emulation and 132 column mode:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:IC=\E[%d@:al=\E[L:dc=\E[P:\
+	:dl=\E[M:ei=:ic=\E[@:im=:\
+	:tc=p8-w:
+
+# p12: Prism-12 in ANSI mode
+# ---------------------------
+#
+# See p9 definition.
+#
+prism12|p12|P12|MDC Prism-12 in ANSI mode:\
+	:tc=p9:
+
+# p12-w: Prism-12 in 132 column mode
+# ----------------------------------
+#
+# 'Wide' version of p12.
+#
+prism12-w|p12-w|P12-W|MDC Prism-12 in 132 column mode:\
+	:tc=p9-w:
+
+# p12-m: Prism-12 in MDC emulation mode
+# -------------------------------------
+#
+# P12 terminal in MDC emulation mode.
+# Similar to p8 definition.
+# Insertion and deletion operations possible.
+#
+prism12-m|p12-m|P12-M|MDC Prism-12 in MDC emulation mode:\
+	:tc=p9-8:
+
+# p12-m-w: Prism-12 in MDC emulation and 132 column modes
+# -------------------------------------------------------
+#
+# P12 terminal in MDC emulation mode and 132 column mode.
+#
+prism12-m-w|p12-m-w|P12-M-W|MDC Prism-12 in MDC emulation and 132 column mode:\
+	:tc=p9-8-w:
+
+# p14: Prism-14 in ANSII mode
+# ---------------------------
+#
+# See p9 definition.
+#
+prism14|p14|P14|MDC Prism-14 in ANSII mode:\
+	:tc=p9:
+
+# p14-w: Prism-14 in 132 column mode
+# ----------------------------------
+#
+# 'Wide' version of p14.
+#
+prism14-w|p14-w|P14-W|MDC Prism-14 in 132 column mode:\
+	:tc=p9-w:
+
+# p14-m: Prism-14 in MDC emulation mode
+# -------------------------------------
+#
+# P14 terminal in MDC emulation mode.
+# Similar to p8 definition.
+# Insertion and deletion operations possible.
+#
+prism14-m|p14-m|P14-M|MDC Prism-14 in MDC emulation mode:\
+	:tc=p9-8:
+
+# p14-m-w: Prism-14 in MDC emulation and 132 column modes
+# -------------------------------------------------------
+#
+# P14 terminal in MDC emulation mode and 132 column mode.
+#
+prism14-m-w|p14-m-w|P14-M-W|MDC Prism-14 in MDC emulation and 132 column mode:\
+	:tc=p9-8-w:
+
+# End of McDonnell Information Systems Prism definitions
+
+# These things were popular in the Pick database community at one time
+# From: George Land <georgeland@aol.com> 24 Sep 1996
+p8gl|prism8gl|McDonnell-Douglas Prism-8 alternate definition:\
+	:am:bw:hs:mi:\
+	:co#80:li#24:ma#1:sg#1:ws#78:\
+	:F2=^AJ\r:F3=^AK\r:F4=^AL\r:F5=^AM\r:F6=^AN\r:F7=^AO\r:\
+	:bl=^G:cd=\EJ:ce=\EK:cl=^L:cm=\E[%i%d;%dH:cr=^M:dc= ^H:\
+	:dl=^P:do=^J:ho=^A:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:\
+	:k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:k;=^AI\r:\
+	:kD= ^H:kE=\EK:kL=^P:kS=\EJ:kb=^H:kd=^J:kh=^A:kl=^U:kr=^F:\
+	:ku=^Z:l1=F1:l2=F2:l3=F3:l4=F4:l5=F5:l6=F6:l7=F7:l8=F8:l9=F9:\
+	:la=F10:le=^U:mb=^CB:me=^C :mh=^CA:mk=^CH:mr=^CD:nd=^F:\
+	:nw=^J^M:pc=\0:se=^C :sf=^J:so=^CE:ue=^C :up=^Z:us=^C0:
+
+#### Microterm (act, mime)
+#
+# The mime1 entries refer to the Microterm Mime I or Mime II.
+# The default mime is assumed to be in enhanced act iv mode.
+#
+
+# New "safe" cursor movement (5/87) from <reuss@umd5.umd.edu>.  Prevents
+# freakout with out-of-range args on Sytek multiplexors.  No :so=^N: and
+# :se=^N: since  it gets confused and it's too dim anyway.  No :ic:
+# since Sytek insists ^S means xoff.
+# (act4: found ":ic=2^S:ei=:im=:ip=.1*^V:" commented out in 8.3 -- esr)
+act4|microterm|microterm act iv:\
+	:am:bs:\
+	:co#80:li#24:\
+	:al=2.3*\001<2.3*/>:bl=^G:cd=2.2*\037:ce=.1*\036:\
+	:cl=12\014:cm=\024%+^X%>/0%+P:cr=^M:dc=.1*\004:\
+	:dl=2.3*\027:do=^K:ho=^]:kd=^K:kl=^H:kr=^X:ku=^Z:le=^H:nd=^X:\
+	:sf=^J:up=^Z:
+# The padding on :sr: and :ta: for act5 and mime is a guess and not final.
+# The act 5 has hardware tabs, but they are in columns 8, 16, 24, 32, 41 (!)...
+# (microterm5: removed obsolete ":ma==^Z^P^Xl^Kj:" -- esr)
+act5|microterm5|microterm act v:\
+	:kd=^K:kl=^H:kr=^X:ku=^Z:sr=\EH:uc=^H\EA:tc=act4:
+# Mimes using brightness for standout.  Half bright is really dim unless
+# you turn up the brightness so far that lines show up on the screen.
+mime-fb|full bright mime1:\
+	:is=^S\E:se=^S:so=^Y:tc=mime:
+mime-hb|half bright mime1:\
+	:is=^Y\E:se=^Y:so=^S:tc=mime:
+# (mime: removed obsolete ":ma=^X ^K^J^Z^P:"; removed ":do=^K:" that overrode
+# the more plausible ":do=^J:" -- esr)
+# uc was at one time disabled to get around a curses bug, be wary of it
+mime|mime1|mime2|mimei|mimeii|microterm mime1:\
+	:am:bs:\
+	:co#80:it#8:li#24:vt#9:\
+	:al=\001:bl=^G:cd=^_:ce=^^:cl=^]^C:cm=\024%+^X%> 0%+P:\
+	:cr=^M:dl=\027:do=^J:ho=^]:is=^S\E^Q:kd=^K:kl=^H:kr=^X:ku=^Z:\
+	:le=^H:nd=^X:sf=^J:sr=\022:ta=\011:uc=^U:up=^Z:
+# These termcaps (for mime2a) put the terminal in low intensity mode
+# since high intensity mode is so obnoxious.
+mime2a-s|microterm mime2a (emulating an enhanced soroc iq120):\
+	:am:bs:\
+	:co#80:li#24:\
+	:al=\001:bl=^G:cd=\EJ:ce=\EK:cl=\EL:cm=\E=%+ %+ :cr=^M:\
+	:dc=\ED:dl=\027:do=^J:ei=^Z:ho=^^:im=\EE:ip=:is=\E):kd=^J:\
+	:kl=^H:kr=^L:ku=^K:le=^H:nd=^L:se=\E;:sf=^J:so=\E\072:sr=\EI:\
+	:ue=\E7:up=\EI:us=\E6:
+# This is the preferred mode (but ^X can't be used as a kill character)
+mime2a|mime2a-v|microterm mime2a (emulating an enhanced vt52):\
+	:bs:\
+	:co#80:it#8:li#24:\
+	:al=\001:bl=^G:cd=\EQ:ce=\EP:cl=\EL:cm=\EY%+ %+ :cr=^M:\
+	:dc=^N:dl=\027:do=^J:ei=^Z:ho=\EH:im=^O:ip=:is=^Y:kd=\EB:\
+	:kl=\ED:kr=\EC:ku=\EA:le=^H:nd=\EC:se=\E9:sf=^J:so=\E8:\
+	:sr=\EA:ta=^I:ue=\E5:up=\EA:us=\E4:
+# (mime3a: removed obsolete ":ma=^X ^K^J^Z^P:" -- esr)
+mime3a|mime1 emulating 3a:\
+	:am@:\
+	:kd=^K:kl=^H:kr=^X:ku=^Z:tc=adm3a:
+mime3ax|mime-3ax|mime1 emulating enhanced 3a:\
+	:it#8:\
+	:al=\001:cd=^_:ce=^X:dl=\027:ta=\011:tc=mime3a:
+# Wed Mar  9 18:53:21 1983
+# We run our terminals at 2400 baud, so there might be some timing problems at
+# higher speeds. The major improvements in this model are the terminal now 
+# scrolls down and insert mode works without redrawing the rest of the line
+# to the right of the cursor. This is done with a bit of a kludge using the
+# exit graphics mode to get out of insert, but it does not appear to hurt
+# anything when using vi at least. If you have some users using act4s with
+# programs that use curses and graphics mode this could be a problem.
+mime314|mm314|mime 314:\
+	:am:\
+	:co#80:li#24:\
+	:al=^A:cd=^_:ce=^^:cl=^L:cm=\024%.%.:dc=^D:dl=^W:ei=^V:ho=^]:\
+	:im=^S:kd=^K:kl=^H:kr=^X:ku=^Z:le=^H:nd=^X:ta=^I:up=^Z:
+# Microterm mime 340 from University of Wisconsin
+mm340|mime340|mime 340:\
+	:co#80:li#24:\
+	:al=46\EU:cd=2*\037:ce=2.1\EL:cl=12\032:cm=\E=%+ %+ :\
+	:cr=^M:dc=2.1*\E#:dl=49.6\EV:do=^J:is=\E\054:kb=^H:kd=^J:\
+	:kl=^H:ku=^K:le=^H:nd=^L:nw=^M^J:sf=^J:ta=^I:up=^K:
+# This came from University of Wisconsin marked "astro termcap for jooss".
+# (mt4520-rv: removed obsolete ":kn#4:" and incorrect ":ri=\E[C:";
+# also added <rmam>/<smam> based  on the init string -- esr)
+mt4520-rv|micro-term 4520 reverse video:\
+	:am:hs:ms:xn:xo:\
+	:co#80:it#8:li#24:ws#80:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:UP=\E[%dA:\
+	:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:\
+	:cr=^M:cs=\E[%i%d;%dr:ct=\E[g:dc=\E[P:dl=\E[M:do=\E[B:ei=:\
+	:fs=\E[?5l\E[?5h:ho=\E[H:ic=\E[@:im=:\
+	:is=\E(B\E[2l\E>\E[20l\E[?3l\E[?5h\E[?7h\E[1;24r\E[24;1H\E[H\E[J:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:kb=^H:kd=\E[B:kh=\E[H:\
+	:kl=\E[D:kr=\E[C:ku=\E[A:le=\E[D:ll=\E[24;1H:me=\E[m:\
+	:nd=\E[C:nw=\EE:\
+	:r1=\E(B\E[2l\E>\E[20l\E[?3l\E[?5h\E[?7h\E[H\E[J:\
+	:rc=\E8:rf=/usr/share/tabset/vt100:sc=\E7:se=\E[0m:\
+	:sf=\ED:so=\E[7m:sr=\EM:st=\EH:ta=^I:ts=\E[25;1H:ue=\E[24m:\
+	:up=\E[A:us=\E[4m:vb=\E[?5l\E[?5h:ve=\E[0V\E8:\
+	:vs=\E7\E[0U:
+
+# Fri Aug  5 08:11:57 1983
+# This entry works for the ergo 4000 with the following setups:
+# ansi,wraparound,newline disabled, xon/xoff disabled in both
+# setup a & c.
+#	
+# WARNING!!! There are multiple versions of ERGO 4000 microcode
+# Be advised that very early versions DO NOT WORK RIGHT !!  
+# Microterm does have a ROM exchange program- use it or lose big
+# (ergo400: added <rmam>/<smam> based on the init string -- esr)
+ergo4000|microterm ergo 4000:\
+	:da:db:ms:\
+	:co#80:li#66:\
+	:AL=\E[1L:RA=\E[?7l:SA=\E[?7m:bl=^G:cd=\E[0J:ce=\E[0K:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:dc=\E[1P:dl=\E[1M:\
+	:do=\E[B:ei=\E[4l:im=\E[4h:\
+	:is=\E<\E=\E[?1l\E[?4l\E[?5l\E[?7h\E[?8h:k1=\EOP:\
+	:k2=\EOQ:k3=\EOR:k4=\EOS:kd=\E[B:ke=\E=:kl=\E[D:kr=\E[C:\
+	:ks=\E=:ku=\E[A:l1=pf1:l2=pf2:l3=pf3:l4=pf4:le=^H:me=\E[m:\
+	:nd=\E[C:se=\E[m:sf=\ED:so=\E[7m:sr=\EM:ta=^I:up=\E[A:
+
+#### NCR 
+#
+# NCR's terminal group was merged with AT&T's when AT&T bought the company.
+# For what happened to that group, see the ADDS section.
+#
+# There is an NCR4103 terminal that's just a re-badged Wyse-50.
+#
+
+# The following vendor-supplied termcaps were captured from the Boundless
+# Technologies site, 8 March 1998.  I removed all-upper-case names that were
+# identical, except for case, to lower-case ones.  I also uncommented the acsc
+# capabilities.X
+#
+# The Intecolor emulation of the NCR 2900/260C color terminal is basically a
+# DEC vt200/300 with color capabilities added.
+ncr260intan|NCR Intecolor emulation of the 2900_260C with an ANSI keyboard:\
+	:Co#8:pa#64:\
+	:AB=\E[4%p1%dm:AF=\E[3%p1%dm:op=\E[0m:tc=ncr260vt300an:
+# The Intecolor emulation of the NCR 2900/260C color terminal is basically a
+# DEC vt200/300 with color capabilities added.
+ncr260intwan|NCR Intecolor emulation of the 2900_260C with an ANSI keyboard:\
+	:Co#8:pa#64:\
+	:AB=\E[4%p1%dm:AF=\E[3%p1%dm:op=\E[0m:tc=ncr260vt300wan:
+# The Intecolor emulation of the NCR 2900/260C color terminal is basically a
+# DEC vt200/300 with color capabilities added.
+ncr260intpp|NCR Intecolor emulation of the 2900_260C with a PC+ keyboard:\
+	:Co#8:pa#64:\
+	:AB=\E[4%p1%dm:AF=\E[3%p1%dm:op=\E[0m:tc=ncr260vt300pp:
+# The Intecolor emulation of the NCR 2900/260C color terminal is basicly a
+# DEC vt200/300 with color capabilities added.
+ncr260intwpp|NCR Intecolor emulation of the 2900_260C with a PC+ keyboard in 132 column mode:\
+	:Co#8:pa#64:\
+	:AB=\E[4%p1%dm:AF=\E[3%p1%dm:op=\E[0m:tc=ncr260vt300wpp:
+# This definition for ViewPoint supports several attributes.  This means
+# that it has magic cookies (extra spaces where the attributes begin).
+# Some applications do not function well with magic cookies.  The System
+# Administrator's Shell in NCR Unix SVR4 1.03 is one such application. 
+# If supporting various attributes is not vital, 'xmc#1' and the extra
+# attributes can be removed. 
+# Mapping to ASCII character set ('acsc' capability) can also be 
+# restored if needed.
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+ncr260vppp|NCR 2900_260 viewpoint:\
+	:am:bw:hs:km:mi:ms:xo:\
+	:co#80:li#24:sg#1:\
+	:CM=\Ew@%p1%{48}%+%c%p2%{32}%+%c%p3%{32}%+%c:K1=^A:\
+	:K3=\EJ:K4=\ET:K5=\EJ:ae=\EcB0\EH\003:al=\EM:\
+	:as=\EcB1\EH\002:bl=^G:bt=\EI:cd=\Ek:ce=\EK:cl=\014:\
+	:cm=\EY%+ %+ :cr=\r:dc=\EW:dl=\El:do=\n:ds=\E`c:ei=\Er:\
+	:fs=^M:ho=\036:im=\Eq:\
+	:is=\Ee6\E~%\E+\E`\072\Ed/\E`1\EO\Ee4\Ec@0@\Ec@1A\EcB0\EcC1\Ee7:\
+	:k1=^B1\r:k2=^B2\r:k3=^B3\r:k4=^B4\r:k5=^B5\r:k6=^B6\r:\
+	:k7=^B7\r:k8=^B8\r:k9=^B9\r:kD=\EW:kI=\Eq:kN=\EJ:kP=\EJ:\
+	:kb=^H:kd=^J:kh=^A:kl=^U:kr=^F:ku=^Z:le=\010:ll=\001:mb=\EG2:\
+	:me=\EG0\EH\003:mh=\EGp:mr=\EG4:nd=\006:nw=\037:se=\EG0:\
+	:sf=\n:so=\EG4:sr=\Ej:st=\E1:ta=^I:ts=\EF:ue=\EG0:up=\032:\
+	:us=\EG8:ve=\E`5:vi=\E`0:vs=\E`5:
+ncr260vpwpp|NCR 2900_260 viewpoint wide mode:\
+	:co#132:\
+	:cm=\Ea%i%dR%dC:\
+	:is=\Ee6\E~%\E+\E`;\Ed/\E`1\EO\Ee4\Ec@0@\Ec@1A\EcB0\EcC1\Ee7:\
+	:r2=\Ee6\E~%\E+\E`;\Ed/\E`1\EO\Ee4\Ec@0@\Ec@1A\EcB0\EcC1\Ee7:\
+	:tc=ncr260vppp:
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+ncr260vt100an|NCR 2900_260 vt100 with ansi kybd:\
+	:am:hs:mi:ms:xn:xo:\
+	:co#80:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:K1=\EOw:K2=\EOy:K3=\EOu:K4=\EOq:K5=\EOs:LE=\E[%dD:\
+	:RI=\E[%dC:SF=\E[%dE:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:\
+	:cd=\E[0J:ce=\E[0K:cl=\E[2J\E[1;1H:cm=\E[%i%d;%dH:cr=\r:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[1P:dl=\E[M:do=\E[B:\
+	:ds=\E[0$~\E[1$~:ec=\E[%dX:ei=\E[4l:fs=\E[0$}:ho=\E[H:\
+	:im=\E[4h:\
+	:is=\E[\041p\E[?7;19;67h\E[?1;3;4l\E(B\E)0\017\E[2J\E[1;1H\E>:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:kD=\E[3~:kI=\E[2~:\
+	:kN=\E[6~:kP=\E[5~:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:\
+	:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=\E[D:mb=\E[5m:md=\E[1m:\
+	:me=\E[0m\017:mr=\E[7m:nd=\E[C:nw=\EE:rc=\E8:sc=\E7:\
+	:se=\E[0m:sf=\ED:so=\E[1;7m:sr=\EM:st=\EH:ta=^I:\
+	:ts=\E[2$~\E[1$}:ue=\E[0m:up=\E[A:us=\E[4m:ve=\E[?25h:\
+	:vi=\E[?25l:
+ncr260vt100wan|NCR 2900_260 vt100 wide mode ansi kybd:\
+	:co#132:\
+	:cm=\E[%i%d;%dH:\
+	:is=\E[\041p\E[?3;7;19;67h\E[?1;4l\E(B\E)0\017\E[2J\E[1;1H\E>:\
+	:r2=\E[\041p\E[?3;7;19;67h\E[?1;4l\E(B\E)0\017\E[2J\E[1;1H\E>:\
+	:tc=ncr260vt100an:
+ncr260vt100pp|NCR 2900_260 vt100 with PC+ kybd:\
+	:@7=\E[5~:K1=\E[H:K2=\E[V:K3=\EOu:K5=\E[U:\
+	:is=\E[\041p\E[?7;19;67h\E[?1;3;4l\E(B\E)0\017\E[2J\E[1;1H\E>:\
+	:kD=\E[4~:kI=\E[1~:kN=\E[6~:kP=\E[3~:kd=\E[B:ke=\E>:\
+	:kh=\E[2~:kl=\E[D:kr=\E[C:ks=\E=:ku=\E[A:l1=pf1:l2=pf2:\
+	:l3=pf3:l4=pf4:\
+	:r2=\E[\041p\E[?7;19;67h\E[?1;3;4l\E(B\E)0\017\E[2J\E[1;1H\E>:tc=ncr260vt100an:
+ncr260vt100wpp|NCR 2900_260 vt100 wide mode pc+  kybd:\
+	:co#132:\
+	:cm=\E[%i%d;%dH:\
+	:is=\E[\041p\E[?3;7;19;67h\E[?1;4l\E(B\E)0\017\E[2J\E[1;1H\E>:\
+	:r2=\E[\041p\E[?3;7;19;67h\E[?1;4l\E(B\E)0\017\E[2J\E[1;1H\E>:\
+	:tc=ncr260vt100pp:
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+ncr260vt200an|NCR 2900_260 vt200 with ansi kybd:\
+	:am:hs:mi:ms:xn:xo:\
+	:co#80:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:K1=\EOw:K2=\EOy:K3=\EOu:K4=\EOq:K5=\EOs:LE=\E[%dD:\
+	:RI=\E[%dC:SF=\E[%dE:UP=\E[%dA:ae=\017:al=\E[L:as=\016:\
+	:bl=^G:cd=\E[0J:ce=\E[0K:cl=\E[2J\E[1;1H:cm=\E[%i%d;%dH:\
+	:cr=\r:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[1P:dl=\E[M:do=\E[B:\
+	:ds=\E[0$~\E[1$~:ec=\E[%dX:ei=\E[4l:fs=\E[0$}:ho=\E[H:\
+	:im=\E[4h:\
+	:is=\E[\041p\E[?7;19;67h\E[?1;3;4l\E(B\E)0\017\E[2J\E[1;1H\E>:\
+	:k0=\EOy:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\E[M:k6=\E[17~:\
+	:k7=\E[18~:k8=\E[19~:k9=\E[20~:kD=\E[3~:kI=\E[2~:kN=\E[6~:\
+	:kP=\E[5~:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:\
+	:ks=\E[?1h\E=:ku=\EOA:le=\E[D:mb=\E[5m:md=\E[1m:\
+	:me=\E[0m\017:mr=\E[7m:nd=\E[C:nw=\EE:rc=\E8:sc=\E7:\
+	:se=\E[27m:sf=\ED:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:ts=\E[2$~\E[1$}:ue=\E[24m:up=\E[A:us=\E[4m:ve=\E[?25h:\
+	:vi=\E[?25l:
+ncr260vt200wan|NCR 2900_260 vt200 wide mode ansi kybd:\
+	:co#132:\
+	:cm=\E[%i%d;%dH:\
+	:is=\E[\041p\E[?3;7;19;67h\E[?4l\E(B\E)0\017\E[2J\E[1;1H:\
+	:r2=\E[\041p\E[?3;7;19;67h\E[?4l\E(B\E)0\017\E[2J\E[1;1H:\
+	:tc=ncr260vt200an:
+ncr260vt200pp|NCR 2900_260 vt200 with pc+ kybd:\
+	:@7=\E[1~:K1=\E[H:K2=\E[V:K3=\EOu:K5=\E[U:kD=\E[4~:\
+	:kI=\E[2~:kN=\E[6~:kP=\E[5~:kd=\E[B:ke=\E>:kh=\E[H:kl=\E[D:\
+	:kr=\E[C:ks=\E=:ku=\E[A:l1=pf1:l2=pf2:l3=pf3:l4=pf4:\
+	:tc=ncr260vt200an:
+ncr260vt200wpp|NCR 2900_260 vt200 wide mode pc+  kybd:\
+	:co#132:\
+	:cm=\E[%i%d;%dH:\
+	:is=\E[\041p\E[?3;7;19;67h\E[?1;4l\E(B\E)0\017\E[2J\E[1;1H\E>:\
+	:r2=\E[\041p\E[?3;7;19;67h\E[?1;4l\E(B\E)0\017\E[2J\E[1;1H\E>:\
+	:tc=ncr260vt200pp:
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+ncr260vt300an|NCR 2900_260 vt300 with ansi kybd:\
+	:am:hs:mi:ms:xn:xo:\
+	:co#80:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:K1=\EOw:K2=\EOy:K3=\EOu:K4=\EOq:K5=\EOs:LE=\E[%dD:\
+	:RI=\E[%dC:SF=\E[%dE:UP=\E[%dA:ae=\017:al=\E[L:as=\016:\
+	:bl=^G:cd=\E[0J:ce=\E[0K:cl=\E[2J\E[1;1H:cm=\E[%i%d;%dH:\
+	:cr=\r:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[1P:dl=\E[M:do=\E[B:\
+	:ds=\E[0$~\E[1$~:ec=\E[%dX:ei=\E[4l:fs=\E[0$}:ho=\E[H:\
+	:im=\E[4h:\
+	:is=\E[\041p\E[?7;19;67h\E[?1;3;4l\E[1;0%w\E(B\E)0\017\E[2J\E[1;1H\E>:\
+	:k0=\EOy:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\E[M:k6=\E[17~:\
+	:k7=\E[18~:k8=\E[19~:k9=\E[20~:kD=\E[3~:kI=\E[2~:kN=\E[6~:\
+	:kP=\E[5~:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:\
+	:ks=\E[?1h\E=:ku=\EOA:le=\E[D:mb=\E[5m:md=\E[1m:\
+	:me=\E[0m\017:mr=\E[7m:nd=\E[C:nw=\EE:rc=\E8:sc=\E7:\
+	:se=\E[27m:sf=\ED:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:ts=\E[2$~\E[1$}:ue=\E[24m:up=\E[A:us=\E[4m:ve=\E[?25h:\
+	:vi=\E[?25l:
+ncr260vt300wan|NCR 2900_260 vt300 wide mode ansi kybd:\
+	:co#132:\
+	:cm=\E[%i%d;%dH:\
+	:is=\E[\041p\E[?3;7;19;67h\E[?4l\E[1;0%w\E(B\E)0\017\E[2J\E[1;1H:\
+	:r2=\E[\041p\E[?3;7;19;67h\E[?4l\E[1;0%w\E(B\E)0\017\E[2J\E[1;1H:\
+	:tc=ncr260vt300an:
+ncr260vt300pp|NCR 2900_260 vt300 with pc+ kybd:\
+	:@7=\E[1~:K1=\E[H:K2=\E[V:K3=\EOu:K5=\E[U:kD=\E[4~:\
+	:kI=\E[2~:kN=\E[6~:kP=\E[5~:kd=\E[B:ke=\E>:kh=\E[H:kl=\E[D:\
+	:kr=\E[C:ks=\E=:ku=\E[A:l1=pf1:l2=pf2:l3=pf3:l4=pf4:\
+	:tc=ncr260vt300an:
+NCR260VT300WPP|ncr260vt300wpp|NCR 2900_260 vt300 wide mode pc+  kybd:\
+	:co#132:\
+	:cm=\E[%i%d;%dH:\
+	:is=\E[\041p\E[?3;7;19;67h\E[?1;4l\E[1;0%w\E(B\E)0\017\E[2J\E[1;1H\E>:\
+	:r2=\E[\041p\E[?3;7;19;67h\E[?1;4l\E[1;0%w\E(B\E)0\017\E[2J\E[1;1H\E>:\
+	:tc=ncr260vt300pp:
+# This terminfo file contains color capabilities for the Wyse325 emulation of 
+# the NCR 2900/260C color terminal.  Because of the structure of the command
+# (escape sequence) used to set color attributes, one of the fore/background
+# colors must be preset to a given value. I have set the background color to
+# black.  The user can change this setup by altering the last section of the
+# 'setf' definition.  The escape sequence to set color attributes is 
+#		ESC d y <foreground_color> <background_color> 1  
+# In addition, the background color can be changed through the desk accessories.
+# The capablitiy 'op' sets colors to green on black (default combination).  
+#
+# NOTE:  The NCR Unix System Administrator's Shell will not function properly
+# 	    if the 'pairs' capability is defined. Un-Comment the 'pairs'
+#	    capability and recompile if you wish to have it included. 
+#
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+ncr260wy325pp|NCR 2900_260 wyse 325:\
+	:am:bw:hs:km:mi:ms:xo:\
+	:co#80:li#24:\
+	:CM=\Ew@%p1%{48}%+%c%p2%{32}%+%c%p3%{32}%+%c:K1=^^:\
+	:K2=\EJ:K4=\ET:K5=\EK:ae=\EH\003\EcB0:al=\EE:\
+	:as=\EH\002\EcB1:bl=^G:bt=\EI:cd=\Ey:ce=\Et:cl=\E*:\
+	:cm=\E=%+ %+ :cr=^M:ct=\E0:dc=\EW:dl=\ER:do=\n:ds=\E`c:\
+	:ei=\Er:fs=^M:ho=\036:im=\Eq:\
+	:is=\Ee6\Ed/\Ee1\Ed*\Er\EO\E`1\E`\072\E`@\E~\041\E"\Ee4\Ex@\E`9\Ee7:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:k9=^AH\r:kD=\EW:kI=\Eq:kN=\EK:kP=\EJ:\
+	:kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=\010:mb=\EG2:\
+	:me=\EG0\EcB0\EcD:mr=\EG4:nd=\014:nw=\037:se=\EG0:sf=\n:\
+	:so=\EGt:sr=\Ej:st=\E1:ta=^I:ts=\EF:ue=\EG0:up=\013:us=\EG8:\
+	:ve=\E`1:vi=\E`0:vs=\E`5:
+ncr260wy325wpp|NCR 2900_260 wyse 325 wide mode:\
+	:co#132:\
+	:cm=\Ea%i%dR%dC:\
+	:is=\Ee6\Ed/\Ee1\Ed*\Er\EO\E`1\E`;\E`@\E~\041\E"\Ee4\Ex@\E`9\Ee7:\
+	:r2=\Ee6\Ed/\Ee1\Ed*\Er\EO\E`1\E`;\E`@\E~\041\E"\Ee4\Ex@\E`9\Ee7:\
+	:tc=ncr260wy325pp:
+# This definition for Wyse 350 supports several attributes.  This means
+# that it has magic cookies (extra spaces where the attributes begin).
+# Some applications do not function well with magic cookies.  The System
+# Administrator's Shell in NCR Unix SVR4 1.03 is one such application. 
+# If supporting various attributes is not vital, 'xmc#1' and the extra
+# attributes can be removed. 
+# Mapping to ASCII character set ('acsc' capability) can also be 
+# restored if needed.
+# In addition, color capabilities have been added to this file.  The drawback,
+# however, is that the background color has to be black.  The foreground colors
+# are numbered 0 through 15.  
+#
+# NOTE:  The NCR Unix System Administrator's Shell does not function properly
+# 	    with the 'pairs' capability defined as below.  If you wish to
+#	    have it included, Un-comment it and recompile (using 'tic'). 
+#
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+ncr260wy350pp|NCR 2900_260 wyse 350:\
+	:am:bw:hs:km:mi:ms:xo:\
+	:co#80:li#24:sg#1:\
+	:CM=\Ew@%p1%{48}%+%c%p2%{32}%+%c%p3%{32}%+%c:K1=^^:\
+	:K4=\ET:K5=\EK:ae=\EH\003\EcB0:al=\EE:as=\EH\002\EcB1:\
+	:bl=^G:bt=\EI:cd=\Ey:ce=\Et:cl=\E+:cm=\E=%+ %+ :cr=^M:\
+	:ct=\E0:dc=\EW:dl=\ER:do=\n:ds=\E`c:ei=\Er:fs=^M:ho=\036:\
+	:im=\Eq:\
+	:is=\Ee6\Ed/\Ee1\Ed*\Er\EO\E`1\E`\072\E`@\E~\041\E"\Ee4\Ex@\E`9\Ee7:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:k9=^AH\r:kD=\EW:kI=\Eq:kN=\EK:kP=\EJ:\
+	:kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=\010:mb=\EG2:\
+	:me=\EG0\EH\003\EcD:mh=\EGp:mr=\EG4:nd=\014:nw=\037:\
+	:se=\EG0:sf=\n:so=\EGt:sr=\Ej:st=\E1:ta=^I:ts=\EF:ue=\EG0:\
+	:up=\013:us=\EG8:ve=\E`1:vi=\E`0:vs=\E`5:
+ncr260wy350wpp|NCR 2900_260 wyse 350 wide mode:\
+	:co#132:\
+	:cm=\Ea%i%dR%dC:\
+	:is=\Ee6\Ed/\Ee1\Ed*\Er\EO\E`1\E`;\E`@\E~\041\E"\Ee4\Ex@\E`9\Ee7:\
+	:r2=\Ee6\Ed/\Ee1\Ed*\Er\EO\E`1\E`;\E`@\E~\041\E"\Ee4\Ex@\E`9\Ee7:\
+	:tc=ncr260wy350pp:
+# This definition for Wyse 50+ supports several attributes.  This means
+# that it has magic cookies (extra spaces where the attributes begin).
+# Some applications do not function well with magic cookies.  The System
+# Administrator's Shell in NCR Unix SVR4 1.03 is one such application. 
+# If supporting various attributes is not vital, 'xmc#1' and the extra
+# attributes can be removed. 
+# Mapping to ASCII character set ('acsc' capability) can also be 
+# restored if needed.
+# (ncr260wy50+pp: originally contained commented-out 
+# <acsc=j5k3l2m1n8q:t4u9v=w0x6>, as well as the commented-out one there -- esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+ncr260wy50+pp|NCR 2900_260 wyse 50+:\
+	:am:bw:hs:km:mi:ms:xo:\
+	:co#80:li#24:sg#1:\
+	:CM=\Ew@%p1%{48}%+%c%p2%{32}%+%c%p3%{32}%+%c:K1=^^:\
+	:K4=\ET:K5=\EK:ae=\EH^C:al=\EE:as=\EH^B:bl=^G:bt=\EI:cd=\EY:\
+	:ce=\ET:cl=\E+:cm=\E=%+ %+ :cr=^M:ct=\E0:dc=\EW:dl=\ER:\
+	:do=\n:ds=\E`c:ei=\Er:fs=^M:ho=\036:im=\Eq:\
+	:is=\Ee6\E~"\E+\Ed/\Ee1\Ed*\Er\EO\E`1\E`\072\E`@\E~\041\E"\Ee4\Ex@\E`9\Ee7:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:k9=^AH\r:kD=\EW:kI=\Eq:kN=\EK:kP=\EJ:\
+	:kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=\010:mb=\EG2:\
+	:me=\EG0\EH\003:mh=\EGp:mr=\EG4:nd=\014:nw=\037:se=\EG0:\
+	:sf=\n:so=\EGt:sr=\Ej:st=\E1:ta=\011:ts=\EF:ue=\EG0:up=\013:\
+	:us=\EG8:ve=\E`1:vi=\E`0:vs=\E`5:
+ncr260wy50+wpp|NCR 2900_260 wyse 50+ wide mode:\
+	:co#132:\
+	:cm=\Ea%i%dR%dC:\
+	:is=\Ee6\E~"\E+\Ed/\Ee1\Ed*\Er\EO\E`1\E`;\E`@\E~\041\E"\Ee4\Ex@\E`9\Ee7:\
+	:r2=\Ee6\E~"\E+\Ed/\Ee1\Ed*\Er\EO\E`1\E`;\E`@\E~\041\E"\Ee4\Ex@\E`9\Ee7:\
+	:tc=ncr260wy50+pp:
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+ncr260wy60pp|NCR 2900_260 wyse 60:\
+	:am:bw:hs:km:mi:ms:xo:\
+	:co#80:li#24:\
+	:CM=\Ew@%p1%{48}%+%c%p2%{32}%+%c%p3%{32}%+%c:K1=^^:\
+	:K2=\EJ:K4=\ET:K5=\EK:ae=\EH^C:al=\EE:as=\EH^B:bl=^G:bt=\EI:\
+	:cd=\Ey:ce=\Et:cl=\E*:cm=\E=%+ %+ :cr=^M:ct=\E0:dc=\EW:\
+	:dl=\ER:do=\n:ds=\E`c:ei=\Er:fs=^M:ho=\036:im=\Eq:\
+	:is=\Ee6\E~4\E+\Ed/\Ee1\Ed*\Er\EO\E`1\E`\072\E`@\E~\041\E"\Ee4\Ex@\E`9\Ee7:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:k9=^AH\r:kD=\EW:kI=\Eq:kN=\EK:kP=\EJ:\
+	:kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=\010:mb=\EG2:\
+	:me=\EG0\EcB0\EcD:mr=\EG4:nd=\014:nw=\037:se=\EG0:sf=\n:\
+	:so=\EGt:sr=\Ej:st=\E1:ta=\011:ts=\EF:ue=\EG0:up=\013:\
+	:us=\EG8:ve=\E`1:vi=\E`0:vs=\E`5:
+ncr260wy60wpp|NCR 2900_260 wyse 60 wide mode:\
+	:co#132:\
+	:cm=\Ea%i%dR%dC:\
+	:is=\Ee6\E~4\E+\Ed/\Ee1\Ed*\Er\EO\E`1\E`;\E`@\E~\041\E"\Ee4\Ex@\E`9\Ee7:\
+	:r2=\Ee6\E~4\E+\Ed/\Ee1\Ed*\Er\EO\E`1\E`;\E`@\E~\041\E"\Ee4\Ex@\E`9\Ee7:\
+	:tc=ncr260wy60pp:
+ncr160vppp|NCR 2900_160 viewpoint:\
+	:tc=ncr260vppp:
+ncr160vpwpp|NCR 2900_160 viewpoint wide mode:\
+	:tc=ncr260vpwpp:
+ncr160vt100an|NCR 2900_160 vt100 with ansi kybd:\
+	:tc=ncr260vt100an:
+ncr160vt100pp|NCR 2900_160 vt100 with PC+ kybd:\
+	:tc=ncr260vt100pp:
+ncr160vt100wan|NCR 2900_160 vt100 wide mode ansi kybd:\
+	:tc=ncr260vt100wan:
+ncr160vt100wpp|NCR 2900_160 vt100 wide mode pc+  kybd:\
+	:tc=ncr260vt100wpp:
+ncr160vt200an|NCR 2900_160 vt200 with ansi kybd:\
+	:tc=ncr260vt200an:
+ncr160vt200pp|NCR 2900_160 vt200 with pc+ kybd:\
+	:tc=ncr260vt200pp:
+ncr160vt200wan|NCR 2900_160 vt200 wide mode ansi kybd:\
+	:tc=ncr260vt200wan:
+ncr160vt200wpp|NCR 2900_160 vt200 wide mode pc+  kybd:\
+	:tc=ncr260vt200wpp:
+ncr160vt300an|NCR 2900_160 vt300 with ansi kybd:\
+	:tc=ncr260vt300an:
+ncr160vt300pp|NCR 2900_160 vt300 with pc+ kybd:\
+	:tc=ncr260vt300pp:
+ncr160vt300wan|NCR 2900_160 vt300 wide mode ansi kybd:\
+	:tc=ncr260vt300wan:
+ncr160vt300wpp|NCR 2900_160 vt300 wide mode pc+  kybd:\
+	:tc=ncr260vt300wpp:
+ncr160wy50+pp|NCR 2900_160 wyse 50+:\
+	:tc=ncr260wy50+pp:
+ncr160wy50+wpp|NCR 2900_160 wyse 50+ wide mode:\
+	:tc=ncr260wy50+wpp:
+ncr160wy60pp|NCR 2900_160 wyse 60:\
+	:tc=ncr260wy60pp:
+ncr160wy60wpp|NCR 2900_160 wyse 60 wide mode:\
+	:tc=ncr260wy60wpp:
+ncrvt100an|ncrvt100pp|NCR vt100 for the 2900 terminal:\
+	:5i:am:hs:mi:ms:xo:\
+	:Nl#32:co#80:it#8:li#24:\
+	:#4=\E[D:%i=\E[C:@8=^M:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:\
+	:DO=\E[%dB:K1=\E[H:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:\
+	:ac=``aaffgghhiijjkkllmmnnqqttuuvvwwxxyyzz~~:ae=\017:\
+	:al=\E[B\E[L:as=\016:bl=^G:cb=\E[1K:cd=\E[0J:ce=\E[0K:\
+	:cl=\E[2J\E[1;1H:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:ct=\E[3g:dc=\E[1P:dl=\E[M:do=\E[B:ds=\E[31l:eA=\E(B\E)0:\
+	:ei=\E[4l:fs=1:ho=\E[H:im=\E[4h:\
+	:is=\E[12h\E[?10l\E%/0n\E[P\031\E[?3l\E(B\E)0:k1=\EOP:\
+	:k2=\EOQ:k3=\EOR:k4=\EOS:kb=^H:kd=\E[B:kl=\E[D:kr=\E[C:\
+	:ku=\E[A:le=\E[D:mb=\E[5m:md=\E[1m:me=\017\E[0m:mr=\E[7m:\
+	:nd=\E[C:nw=\EE:ps=\E[i:\
+	:r2=\Ec\E[12;31h\E[?3;4;5;10l\E[?6;7;19;25h\E[33;34l\E[0m\E(B\E)0\E%/0n\E[P\031:\
+	:rc=\E8:\
+	:..sa=\E[0%?%p1%p6%|%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t\016%e\017%;$<100>:\
+	:sc=\E7:se=\E[0m:sf=\ED:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:ts=\E[>+1:ue=\E[0m:up=\E[A:us=\E[4m:
+ncrvt100wan|NCRVT100WPP|ncrvt100wpp|NCR VT100 emulation of the 2900 terminal:\
+	:co#132:\
+	:is=\E[12h\E[?10l\E%/0n\E[P\031\E[?3h\E(B\E)0:\
+	:r2=\Ec\E[12;31h\E[?4;5;10l\E?3;6;7;19;25h\E[33;34l\E[0m\E(B\E)0\E%/0n\E[P\031:\
+	:tc=ncrvt100an:
+#
+# Vendor-supplied NCR termcaps end here
+
+# NCR7900 DIP switches:
+#
+# Switch A:
+# 1-4 - Baud Rate
+# 5   - Parity (Odd/Even)
+# 6   - Don't Send or Do Send Spaces
+# 7   - Parity Enable
+# 8   - Stop Bits (One/Two)
+# 
+# Switch B:
+# 1   - Upper/Lower Shift
+# 2   - Typewriter Shift
+# 3   - Half Duplex / Full Duplex
+# 4   - Light/Dark Background
+# 5-6 - Carriage Return Without / With Line Feed
+# 7   - Extended Mode
+# 8   - Suppress Keyboard Display
+# 
+# Switch C:
+# 1   - End of line entry disabled/enabled
+# 2   - Conversational mode / (Local?) Mode
+# 3   - Control characters displayed / not displayed
+# 4   - (2-wire?) / 4-wire communications
+# 5   - RTS on and off for each character
+# 6   - (50Hz?) / 60 Hz
+# 7   - Exit after level zero diagnostics
+# 8   - RS-232 interface
+# 
+# Switch D:
+# 1   - Reverse Channel (yes / no)
+# 2   - Manual answer (no / yes)
+# 3-4 - Cursor appearance
+# 5   - Communication Rate
+# 6   - Enable / Disable EXT turnoff
+# 7   - Enable / Disable CR turnoff
+# 8   - Enable / Disable backspace
+#
+# Since each attribute parameter is 0 or 1, we shift each attribute (standout,
+# reverse, blink, dim, and underline) the appropriate number of bits (by
+# multiplying the 0 or 1 by a correct factor to shift) so the bias character,
+# '@' is (effectively) "or"ed with each attribute to generate the proper third
+# character in the <ESC>0 sequence.  The :sa: string implements the following
+# equation:
+#
+# ((((('@' + P5) | (P4 << 1)) | (P3 << 3)) | (P2 << 4)) | (p1 * 17))    =>
+# ((((('@' + P5) + (P4 << 1)) + (P3 << 3)) + (P2 << 4)) + (p1 * 17))
+#
+#	Where:  P1 <==> Standout attribute parameter
+#		P2 <==> Underline attribute parameter
+#		P3 <==> Reverse attribute parameter
+#		P4 <==> Blink attribute parameter
+#		P5 <==> Dim attribute parameter
+# From <root@goliath.un.atlantaga.NCR.COM>, init string hacked by SCO.
+ncr7900i|ncr7900|ncr 7900 model 1:\
+	:am:bw:ul:\
+	:co#80:li#24:sg#1:\
+	:bl=^G:cd=\Ek:ce=\EK:cl=^L:cm=\E1%r%.%.:cr=^M:do=^J:\
+	:is=\E0@\010\E3\E4\E7:kd=^J:kh=^A:kl=^U:kr=^F:ku=^Z:le=^H:\
+	:ll=^A:mb=\E0B:me=\E0@:mh=\E0A:mr=\E0P:nd=^F:pf=^T:po=^R:\
+	:..sa=\E0%p5%{64}%+%p4%{2}%*%+%p3%{16}%*%+%p2%{32}%*%+%p1%{17}%*%+%c:\
+	:se=\E0@:sf=^J:so=\E0Q:ue=\E0@:up=^Z:us=\E0`:
+ncr7900iv|ncr 7900 model 4:\
+	:am:bw:es:hs:\
+	:co#80:li#24:\
+	:al=\E^N:bl=^G:cl=^L:cm=\013%+@\E\005%02:cr=^M:dl=\E^O:\
+	:do=^J:ds=\Ey1:fs=\Ek\Ey5:ho=\013@\E^E00:k1=\ES:k2=\ET:\
+	:k3=\EU:k4=\EV:k5=\EW:k6=\EP:k7=\EQ:k8=\ER:kb=^H:kd=\EB:\
+	:kh=\EH:kl=\ED:kr=\EC:ku=\EA:l6=blue:l7=red:l8=white:le=^H:\
+	:nw=^M^J:sf=^J:ts=\Ej\Ex5\Ex1\EY8%p1%{32}%+%c\Eo:
+# Warning: This terminal will lock out the keyboard when it receives a CTRL-D.
+#	   The user can enter a CTRL-B to get out of this locked state.
+# In <hpa>, we want to output the character given by the formula:
+#		((col / 10) * 16) + (col % 10)		where "col" is "p1"
+ncr7901|ncr 7901 model:\
+	:am:bw:ul:\
+	:co#80:li#24:\
+	:bl=^G:cd=\Ek:ce=\EK:ch=\020%+^J:cl=^L:cm=\EY%+ %+ :cr=^M:\
+	:cv=\013%+@:do=^J:is=\E4^O:kC=^L:kd=^J:kh=^H:kl=^U:kr=^F:\
+	:ku=^Z:le=^H:ll=^A:mb=\E0B:me=^O:mh=\E0A:mr=\E0P:nd=^F:pf=^T:\
+	:po=^R:\
+	:..sa=\E0%p5%{64}%+%p4%{2}%*%+%p3%{16}%*%+%p2%{32}%*%+%p1%{17}%*%+%c\016:\
+	:se=^O:sf=^J:so=\E0Q\016:ue=^O:up=^Z:us=\E0`\016:ve=^X:\
+	:vi=^W:
+
+#### Perkin-Elmer (Owl)
+#
+# These are official terminfo entries from within Perkin-Elmer.
+#
+
+bantam|pe550|pe6100|perkin elmer 550:\
+	:bs:\
+	:co#80:li#24:\
+	:bl=^G:ce=\EI:cl=\EK:cm=\EX%+ \EY%+ :cr=^M:do=^J:ho=\EH:\
+	:le=^H:ll=\EH\EA:nd=\EC:sf=^J:up=\EA:
+fox|pe1100|perkin elmer 1100:\
+	:am:bs:\
+	:co#80:li#24:\
+	:bl=^G:cd=\EJ:ce=\EI:cl=\EH\EJ:cm=\EX%+ \EY%+ :cr=^M:\
+	:ct=\E3:do=^J:ho=\EH:le=^H:ll=\EH\EA:nd=\EC:sf=^J:st=\E1:\
+	:up=\EA:vb=\020\002\020\003:
+owl|pe1200|perkin elmer 1200:\
+	:am:bs:in:\
+	:co#80:li#24:\
+	:al=\EL:bl=^G:cd=\EJ:ce=\EI:cl=\EH\EJ:cm=\EX%+ \EY%+ :\
+	:cr=^M:ct=\E3:dc=\EO:dl=\EM:do=^J:ei=:ho=\EH:ic=\EN:im=:ip=:\
+	:k0=\ERJ:k1=\ERA:k2=\ERB:k3=\ERC:k4=\ERD:k5=\ERE:k6=\ERF:\
+	:k7=\ERG:k8=\ERH:k9=\ERI:kb=^H:le=^H:ll=\EH\EA:me=\E\041\0:\
+	:nd=\EC:se=\E\041\0:sf=^J:so=\E\041^H:st=\E1:up=\EA:\
+	:vb=\020\002\020\003:
+pe1251|pe6300|pe6312|perkin elmer 1251:\
+	:am:\
+	:co#80:it#8:li#24:pb#300:sg#1:vt#8:\
+	:bl=^G:cd=\EJ:ce=\EI:cl=\EK:cm=\EX%+ \EY%+ :cr=^M:ct=\E3:\
+	:do=\EB:ho=\EH:k0=\ERA:k1=\ERB:k2=\ERC:k3=\ERD:k4=\ERE:\
+	:k5=\ERF:k6=\ERG:k7=\ERH:k8=\ERI:k9=\ERJ:k;=\ERK:le=\ED:\
+	:nd=\EC:sf=^J:st=\E1:up=\EA:
+# (pe7000m: this had
+# 	rmul=\E!\0, smul=\E!\040, 
+# which is probably wrong, it collides with kf0
+pe7000m|perkin elmer 7000 series monochrome monitor:\
+	:am:\
+	:co#80:li#24:\
+	:bl=^G:bt=\E\041Y:cd=\EJ:ce=\EI:cl=\EK:cm=\ES%+ %+ :cr=^M:\
+	:do=\EB:ho=\EH:i1=\E\041\0\EW  7o\Egf\ES7 :k0=\E\041\0:\
+	:k1=\E\041^A:k2=\E\041^B:k3=\E\041^C:k4=\E\041^D:\
+	:k5=\E\041^E:k6=\E\041^F:k7=\E\041^G:k8=\E\041^H:\
+	:k9=\E\041^I:k;=\E\041^J:kb=^H:kd=\E\041U:kh=\E\041S:\
+	:kl=\E\041V:kr=\E\041W:ku=\E\041T:le=\ED:ll=\ES7 :nd=\EC:\
+	:sf=^J:sr=\ER:up=\EA:
+pe7000c|perkin elmer 7000 series colour monitor:\
+	:i1=\E\041\0\EW  7o\Egf\Eb0\Ec7\ES7 :se=\Eb0:so=\Eb2:\
+	:ue=\E\041\0:us=\E\041 :\
+	:tc=pe7000m:
+
+#### Prime
+#
+# Yes, Prime made terminals.  These entries were posted by Kevin J. Cummings
+# <cummings@primerd.prime.com> on 14 Dec 1992 and lightly edited by esr.
+# Prime merged with ComputerVision in the late 1980s; you can reach them at:
+#
+#	ComputerVision Services
+#	500 Old Connecticut Path
+#	Framingham, Mass.
+#
+
+# Standout mode is dim reverse-video.
+pt100|pt200|wren|fenix|prime pt100/pt200:\
+	:am:bw:mi:ms:\
+	:co#80:it#8:li#24:\
+	:DC=\E[%dP:DL=\E[M:DO=\E[%dB:LE=\E[%dD:RI=\E[%dC:\
+	:UP=\E[%dA:al=\E[L\E[t:bt=\E[Z:cd=\E[J\E[r:ce=\E[K\E[t:\
+	:cl=\E?:cm=\E0%+!%+!:cr=^M:dc=\E[P:do=\ED:ei=\E[4l:ho=\E$B:\
+	:im=\E[4h:kb=^H:kd=\E[B:ke=\E[>13l:kh=\E$A:kl=\E[D:kr=\E[C:\
+	:ks=\E[>13h:ku=\E[A:le=^H:me=\E[m:mh=\E[2m:nd=\E[C:nw=^M^J:\
+	:se=\E[m:sf=^J:so=\E[2;7m:ta=^I:te=:\
+	:ti=\E[>1l\E[>2l\E[>16l\E[4l\E[>9l\E[20l\E[>3l\E[>7h\E[>12l\E[1Q:\
+	:ue=\E[m:up=\EM:us=\E[4m:vb=\E$\E$P:
+pt100w|pt200w|wrenw|fenixw|prime pt100/pt200 in 132-column mode:\
+	:co#132:\
+	:cm=\E[%i%d;%dH:tc=pt100:
+pt250|Prime PT250:\
+	:se@:so@:tc=pt100:
+pt250w|Prime PT250 in 132-column mode:\
+	:se@:so@:tc=pt100w:
+
+#### Sperry Univac
+#
+# Sperry Univac has merged with Burroughs to form Unisys.
+#
+
+# This entry is for the Sperry UTS30 terminal running the TTY 
+# utility under control of CP/M Plus 1R1. The functionality 
+# provided is comparable to the DEC vt100.
+# (uts30: I added <rmam>/<smam> based on the init string -- esr)
+uts30|sperry uts30 with cp/m@1R1:\
+	:am:bw:hs:\
+	:co#80:li#24:ws#40:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7m:SF=\E[%dB:\
+	:SR=\E[%dA:UP=\E[%dA:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=\Ed:al=\EN:as=\EF:bl=^G:cd=\E[J:ce=\E[K:cl=^L:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=\EU%+ %+ :dc=\EM:dl=\EL:do=\EB:\
+	:ei=:fs=^M:ho=\E[H:ic=\EO:im=:is=\E[U 7\E[24;1H:kb=^H:\
+	:kd=\EOB:kh=\E[H:kl=\EOD:kr=\EOC:ku=\EOA:le=^H:mb=\E[5m:\
+	:md=\E[1m:me=\E[m:mr=\E[7m:nd=\EC:\
+	:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\EX:\
+	:rf=/usr/share/tabset/vt100:sc=\EW:se=\E[m:sf=^J:\
+	:so=\E[7m:sr=\EI:ta=^I:ts=\E]:uc=\EPB:ue=\E[m:up=\E[A:\
+	:us=\E[4m:ve=\ES:vi=\ER:
+
+#### Tandem
+#
+# Tandem builds these things for use with its line of fault-tolerant
+# transaction-processing computers.  They aren't generally available
+# on the merchant market, and so are fairly uncommon.
+#
+
+tandem6510|adm3a repackaged by Tandem:\
+	:tc=adm3a:
+
+# A funny series of terminal that TANDEM uses.  The actual model numbers
+# have a fourth digit after 653 that designates minor variants.  These are
+# natively block-mode and rather ugly, but they have a character mode which
+# this doubtless(?) exploits.  There is a 6520 that is slightly dumber.
+# (tandem653: had ":sb=\ES:", probably someone's mistake for sf; also,
+# removed :if=/usr/share/tabset/tandem653:, no such file -- esr)
+tandem653|t653x|Tandem 653x multipage terminal:\
+	:am:bs:da:db:hs:\
+	:co#80:li#24:sg#1:ws#64:\
+	:cd=\EJ:ce=\EK:cl=\EI:cm=\023%+ %+ :do=^J:ds=\Eo\r:fs=^M:\
+	:ho=\EH:le=^H:me=\E6 :nd=\EC:se=\E6 :sf=\ES:so=\E6$:sr=\ET:\
+	:ts=\Eo:ue=\E6 :up=\EA:us=\E60:
+
+#### Tandy/Radio Shack
+#
+# Tandy has a line of VDTs distinct from its microcomputers.
+#
+
+dmterm|deskmate terminal:\
+	:am:bw:\
+	:co#80:li#24:\
+	:al=\EP:bl=^G:cd=\EJ:ce=\EK:cl=\Ej:cm=\EY%+ %+ :cr=^M:\
+	:dc=\ES:dl=\ER:do=\EB:ei=:ho=\EH:ic=\EQ:im=:k0=\E1:k1=\E2:\
+	:k2=\E3:k3=\E4:k4=\E5:k5=\E6:k6=\E7:k7=\E8:k8=\E9:k9=\E0:\
+	:kd=\EB:kh=\EH:kl=\ED:kr=\EC:ku=\EA:l0=f1:l1=f2:l2=f3:l3=f4:\
+	:l4=f5:l5=f6:l6=f7:l7=f8:l8=f9:l9=f10:le=^H:ll=\EE:mk@:nd=\EC:\
+	:sf=\EX:ta=^I:ue@:up=\EA:us@:ve=\EG6:vi=\EG5:\
+	:tc=adm+sgr:
+dt100|dt-100|Tandy DT-100 terminal:\
+	:xo:\
+	:co#80:li#24:sg#1:\
+	:ac=jjkkllmmnnqqttuuvvwwxx:ae=^O:al=\E[L:as=^N:bl=^G:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:cm=\010\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%2;%2r:dc=\E[P:dl=\E[M:do=\E[B:ei=:ho=\E[H:ic=\E[@:\
+	:im=:is=\E[?3l\E)0\E(B:k1=\E[?3i:k2=\E[2i:k3=\E[@:k4=\E[M:\
+	:k5=\E[17~:k6=\E[18~:k7=\E[19~:k8=\E[20~:k9=\E[21~:\
+	:k;=\E[?5i:kN=\E[29~:kP=\E[28~:kd=\E[B:kh=\E[H:kl=\E[D:\
+	:kr=\E[C:ku=\E[A:l1=f1:l2=f2:l3=f3:l4=f4:l5=f5:l6=f6:l7=f7:\
+	:l8=f8:le=^H:me=\E[m:nd=\E[C:se=\E[m:sf=^J:so=\E[7m:sr=\EM:\
+	:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:ve=\E[?25h:vi=\E[?25l:
+dt100w|dt-100w|Tandy DT-100 terminal (wide mode):\
+	:co#132:tc=dt100:
+dt110|Tandy DT-110 emulating ansi:\
+	:xo:\
+	:co#80:li#24:\
+	:@7=\E[K:ac=jjkkllmmnnqqttuuvvwwxx:ae=^O:al=\E[0L:as=^N:\
+	:bl=^G:cd=\E[0J:ce=\E[0K:cl=\E[H\E[2J:cm=\010\E[%i%d;%dH:\
+	:cr=^M:cs=\E[%i%d;%dr:dc=\E[0P:dl=\E[0M:do=\E[0B:\
+	:eA=\E(B\E)0:ei=:ho=\E[H:ic=\E[0@:im=:is=\E[?3l\E)0\E(B:\
+	:k1=\E[1~:k2=\E[2~:k3=\E[3~:k4=\E[4~:k5=\E[5~:k6=\E[6~:\
+	:k7=\E[7~:k8=\E[8~:k9=\E[9~:k;=\E[10~:kI=\E[@:kN=\E[26~:\
+	:kP=\E[25~:kd=\E[B:kh=\E[G:kl=\E[D:kr=\E[C:ku=\E[A:l0=f1:\
+	:l1=f2:l2=f3:l3=f4:l4=f5:l5=f6:l6=f7:l7=f8:l8=f9:l9=f10:le=^H:\
+	:me=\E[m:nd=\E[C:se=\E[m:sf=^J:so=\E[7m:sr=\EM:ta=^I:\
+	:ue=\E[m:up=\E[0A:us=\E[4m:ve=\E[?25h:vi=\E[?25l:
+pt210|TRS-80 PT-210 printing terminal:\
+	:hc:os:\
+	:co#80:\
+	:bl=^G:cr=^M:do=^J:sf=^J:
+
+#### Tektronix (tek)
+#
+# Tektronix tubes are graphics terminals.  Most of them use modified 
+# oscilloscope technology incorporating a long-persistence green phosphor,
+# and support vector graphics on a main screen with an attached "dialogue
+# area" for interactive text.
+#
+
+tek|tek4012|tektronix 4012:\
+	:bs:os:\
+	:co#75:li#35:\
+	:bl=^G:cl=\E\014:cr=^M:do=^J:ff=\014:is=\E^O:le=^H:
+# (tek4013: added <acsc> to suppress tic warnings re :as:/:ae: --esr)
+tek4013|tektronix 4013:\
+	:ac=:ae=\E^O:as=\E^N:tc=tek4012:
+tek4014|tektronix 4014:\
+	:co#81:li#38:\
+	:is=\E\017\E9:tc=tek4012:
+# (tek4015: added <acsc> to suppress tic warnings re :as:/:ae: --esr)
+tek4015|tektronix 4015:\
+	:ac=:ae=\E^O:as=\E^N:tc=tek4014:
+tek4014-sm|tektronix 4014 in small font:\
+	:co#121:li#58:\
+	:is=\E\017\E\072:tc=tek4014:
+# (tek4015-sm: added <acsc> to suppress tic warnings re :as:/:ae: --esr)
+tek4015-sm|tektronix 4015 in small font:\
+	:ac=:ae=\E^O:as=\E^N:tc=tek4014-sm:
+# Tektronix 4023 from Andrew Klossner <orca!andrew.tektronix@csnet-relay>
+#
+# You need to have "stty nl2" in effect.  Some versions of tset(1) know
+# how to set it for you.
+#
+# It's got the Magic Cookie problem around stand-out mode.  If you can't
+# live with Magic Cookie, remove the :so: and :se: fields and do without
+# reverse video.  If you like reverse video stand-out mode but don't want
+# it to flash, change the letter 'H' to 'P' in the :so: field.
+tek4023|tektronix 4023:\
+	:am:bs:\
+	:co#80:dN#4:li#24:sg#1:vt#4:\
+	:bl=^G:cl=4\E\014:cm=\034%r%+ %+ :cr=^M:do=^J:kb=^H:le=^H:\
+	:nd=^I:nl=^J:se=^_@:so=^_P:
+# It is recommended that you run the 4025 at 4800 baud or less;
+# various bugs in the terminal appear at 9600.  It wedges at the
+# bottom of memory (try "cat /usr/dict/words"); ^S and ^Q typed
+# on keyboard don't work.  You have to hit BREAK twice to get
+# one break at any speed - this is a documented feature.
+# Can't use cursor motion because it's memory relative, and 
+# because it only works in the workspace, not the monitor.  
+# Same for home. Likewise, standout only works in the workspace.
+# 
+# :ce: was commented out since vi and rogue seem to work better 
+# simulating it with lots of spaces!
+# 
+# :al: and :AL: had 145ms of padding, but that slowed down vi's ^U 
+# and didn't seem necessary.
+#
+tek4024|tek4025|tek4027|tektronix 4024/4025/4027:\
+	:am:bs:da:db:\
+	:co#80:it#8:li#34:lm#0:\
+	:AL=\037up\r\037ili %d\r:CC=^_:DL=\037dli %d\r\006:\
+	:DO=\037dow %d\r:LE=\037lef %d\r:RI=\037rig %d\r:\
+	:UP=\037up %d\r:al=\037up\r\037ili\r:bl=^G:\
+	:cd=\037dli 50\r:cl=\037era\r\n\n:cr=^M:dc=\037dch\r:\
+	:dl=\037dli\r\006:do=^F^J:ei=:ic=\037ich\r \010:im=:\
+	:is=\041com 31\r\n\037sto 9 17 25 33 41 49 57 65 73\r:\
+	:ke=\037lea p2\r\037lea p4\r\037lea p6\r\037lea p8\r\037lea f5\r:\
+	:ks=\037lea p4 /h/\r\037lea p8 /k/\r\037lea p6 / /\r\037lea p2 /j/\r\037lea f5 /H/\r:\
+	:le=^H:nd=\037rig\r:sf=^F^J:ta=^I:up=^K:
+tek4025-17|tek 4025 17 line window:\
+	:li#17:tc=tek4025:
+tek4025-17-ws|tek 4025 17 line window in workspace:\
+	:is=\041com 31\r\n\037sto 9 17 25 33 41 49 57 65 73\r\037wor 17\r\037mon 17\r:\
+	:se=\037att s\r:so=\037att e\r:te=\037mon h\r:\
+	:ti=\037wor h\r:\
+	:tc=tek4025-17:
+tek4025-ex|tek4027-ex|tek 4025/4027 w/!:\
+	:is=\037com 33\r\n\041sto 9 17 25 33 41 49 57 65 73\r:\
+	:te=\037com 33\r:ti=\041com 31\r:\
+	:tc=tek4025:
+# Tektronix 4025a
+# From: Doug Gwyn <gwyn@brl-smoke.ARPA>
+# The following status modes are assumed for normal operation (replace the
+# initial "!" by whatever the current command character is):
+#	!COM 29			# NOTE: changes command character to GS (^])
+#	^]DUP
+#	^]ECH R
+#	^]EOL
+#	^]RSS T
+#	^]SNO N
+#	^]STO 9 17 25 33 41 49 57 65 73
+# Other modes may be set according to communication requirements.
+# If the command character is inadvertently changed, termcap can't restore it.
+# Insert-character cannot be made to work on both top and bottom rows.
+# Clear-to-end-of-display emulation via !DLI 988 is too grotty to use, alas.
+# There also seems to be a problem with vertical motion, perhaps involving
+# delete/insert-line, following a typed carriage return.  This terminal sucks.
+# Delays not specified; use "stty ixon -ixany" to enable DC3/DC1 flow control!
+# (tek4025a: removed obsolete ":xx:". This may mean the tek4025a entry won't
+# work any more. -- esr)
+tek4025a|Tektronix 4025A:\
+	:am:bs:bw:da:db:pt:xo:\
+	:co#80:it#8:li#34:\
+	:CC=^]:DC=\035dch %d;:DL=\035dli %d;:DO=\035dow %d;:\
+	:LE=\035lef %d;:RI=\035rig %d;:SF=\035dow %d;:\
+	:UP=\035up %d;:al=\013\035ili;:bl=^G:bt=\035bac;:\
+	:ce=\035dch 80;:ch=\r\035rig %d;:cl=\035era;\n\035rup;:\
+	:cr=^M:ct=\035sto;:dc=\035dch;:dl=\035dli;:do=^J:le=^H:\
+	:nd=\035rig;:\
+	:rs=\041com 29\035del 0\035rss t\035buf\035buf n\035cle\035dis\035dup\035ech r\035eol\035era g\035for n\035pad 203\035pad 209\035sno n\035sto 9 17 25 33 41 49 57 65 73\035wor 0;:\
+	:sf=^J:ta=^I:up=^K:
+# From: cbosg!teklabs!davem Wed Sep 16 21:11:41 1981
+# Here's the command file that I use to get rogue to work on the 4025.
+# It should work with any program using the old curses (e.g. it better
+# not try to scroll, or cursor addressing won't work.  Also, you can't
+# see the cursor.)
+# (This "learns" the arrow keys for rogue. I have adapted it for termcap - mrh)
+tek4025-cr|tek 4025 for curses and rogue:\
+	:am:bs:\
+	:co#80:it#8:li#33:\
+	:cl=\037era;:cm=\037jum%i%d\054%d;:do=^F^J:\
+	:is=\041com 31\r\n\037sto 9 17 25 33 41 49 57 65 73\r:\
+	:le=^H:nd=\037rig;:sf=^F^J:ta=^I:te=\037wor 0:\
+	:ti=\037wor 33h:up=^K:
+# next two lines commented out since curses only allows 128 chars, sigh.
+#	:ti=\037lea p1/b/\037lea p2/j/\037lea p3/n/\037lea p4/h/\037lea p5/ /\037lea p6/l/\037lea p7/y/\037lea p8/k/\037lea p9/u/\037lea p./f/\037lea pt/`era w/13\037lea p0/s/\037wor 33h:\
+#	:te=\037lea p1\037lea p2\037lea p3\037lea p4\037lea pt\037lea p5\037lea p6\037lea p7\037lea p8\037lea p9/la/13\037lea p.\037lea p0\037wor 0:
+tek4025ex|4025ex|4027ex|tek 4025 w/!:\
+	:is=\037com 33\r\n\041sto 9\05417\05425\05433\05441\05449\05457\05465\05473\r:\
+	:te=\037com 33\r:ti=\041com 31\r:\
+	:tc=tek4025:
+tek4105|tektronix 4105:\
+	:am:bs:mi:ms:ul:xn:xt:\
+	:co#79:it#8:li#29:\
+	:ac=:ae=\E[m:al=\E[1L:as=\E[1m:bl=^G:bt=\E[Z:cd=\E[J:\
+	:ce=\E[K:cl=\E[2J\E[H:cm=\E[%i%2;%2H:cr=^M:ct=\E[1g:\
+	:dc=\E[1P:dl=\E[1M:do=\E[1B:ei=\E[4l:ho=\E[H:i1=\E%!1\E[m:\
+	:im=\E[4h:is=\E%!1\E[?6141\E[m:kb=^H:kd=\E[1B:kl=\E[1D:\
+	:kr=\E[1C:ku=\E[1A:mb=\E[=3;<7m:md=\E[=7;<4m:\
+	:me=\E[=0;<1m:mh=\E[=1;<6m:mk=\E[=6;<5:mr=\E[=1;<3m:\
+	:nd=\E[1C:se=\E[=0;<1m:sf=\E[S:so=\E[=2;<3m:sr=\E[T:ta=^I:\
+	:te=:ti=\E%!1\E[?6l\E[2J:ue=\E[=0;<1m:up=\E[1A:\
+	:us=\E[=5;<2m:
+
+# (tek4105-30: I added <rmam>/<smam> based on the init string -- esr)
+tek4105-30|4015 emulating 30 line vt100:\
+	:am:mi:ms:xn:xo:\
+	:co#80:it#8:li#30:vt#3:\
+	:@8=\EOM:DO=\E[%dB:K1=\EOq:K2=\EOr:K3=\EOs:K4=\EOp:K5=\EOn:\
+	:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:UP=\E[%dA:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=^O:as=^N:bl=^G:cb=\E[1K:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:do=^J:\
+	:eA=\E(B\E)0:ho=\E[H:k0=\EOy:k1=\EOP:k2=\EOQ:k3=\EOR:\
+	:k4=\EOS:k5=\EOt:k6=\EOu:k7=\EOv:k8=\EOl:k9=\EOw:k;=\EOx:\
+	:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:\
+	:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:me=\E[m\017:mr=\E[7m:\
+	:nd=\E[C:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\E8:\
+	:..sa=\E[0%?%p1%p6%|%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t\016%e\017%;:\
+	:sc=\E7:se=\E[m:sf=^J:so=\E[1;7m:sr=\EM:st=\EH:ta=^I:\
+	:ue=\E[m:up=\E[A:us=\E[4m:
+
+# Tektronix 4105 from BRL
+# The following setup modes are assumed for normal operation:
+#	CODE ansi		CRLF no			DABUFFER 141
+#	DAENABLE yes		DALINES 30		DAMODE replace
+#	DAVISIBILITY yes	ECHO no			EDITMARGINS 1 30
+#	FLAGGING input		INSERTREPLACE replace	LFCR no
+#	ORIGINMODE relative	PROMPTMODE no		SELECTCHARSET G0 B
+#	SELECTCHARSET G1 0	TABS -2
+# Other setup modes may be set for operator convenience or communication
+# requirements; I recommend
+#	ACURSOR 1 0		AUTOREPEAT yes		AUTOWRAP yes
+#	BYPASSCANCEL <LF>	CURSORKEYMODE no	DAINDEX 1 0 0
+#	EOFSTRING ''		EOLSTRING <CR>		EOMCHARS <CR> <NU>
+#	GAMODE overstrike	GCURSOR 0 100 0		GSPEED 10 1
+#	IGNOREDEL no		KEYEXCHAR <DL>		NVDEFINE -53 "<NU>"
+#	PROMPTSTRING ''		QUEUESIZE 2460		WINDOW 0 0 4095 3132
+#	XMTDELAY 0
+# and factory color maps.  After setting these modes, save them with NVSAVE. No
+# delays are specified; use "stty ixon -ixany" to enable DC3/DC1 flow control!
+# "IC" cannot be used in combination with "im" & "ei".
+# "tek4105a" is just a guess:
+tek4105a|Tektronix 4105:\
+	:bs:ms:pt:xo:\
+	:co#80:it#8:kn#8:li#30:vt#3:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:LE=\E[%dD:\
+	:RI=\E[%dC:SF=\E[%dS:SR=\E[%dT:UP=\E[%dA:ac=:ae=^O:al=\E[L:\
+	:as=^N:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:\
+	:dl=\E[M:do=^J:ec=\E[%dX:ei=\E[4l:ho=\E[H:im=\E[4h:\
+	:is=\E%!1:k0=\EOA:k1=\EOB:k2=\EOC:k3=\EOD:k4=\EOP:k5=\EOQ:\
+	:k6=\EOR:k7=\EOS:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:\
+	:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:l0=F1:l1=F2:l2=F3:l3=F4:l4=F5:\
+	:l5=F6:l6=F8:le=^H:ll=\E[30;H:mb=\E[5m:md=\E[1m:me=\E[m:\
+	:mr=\E[7m:nd=\E[C:nw=\EE:rc=\E8:\
+	:rs=\030\E%!0\EKC\E\014\EKR0\EKF0\ENM0\ELBH=\ETF8000010F40\ELI100\ELLA>\ELM0\EKE0\ENF1\EKS0\END0\E%!1\Ec\E[?3;5l\E[?7;8h\E[r\E[m\E>:\
+	:sc=\E7:se=\E[m:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:te=\E%!0\ELBH=\E%!1:ti=\E[?6l:ue=\E[m:up=\EM:us=\E[4m:\
+	:ve=\E%!0\ETD10\E%!1:vi=\E%!0\ETD00\E%!1:\
+	:vs=\E%!0\ETD70\E%!1:
+
+#
+# Tektronix 4106/4107/4109 from BRL
+# The following setup modes are assumed for normal operation:
+#	CODE ansi		COLUMNMODE 80		CRLF no
+#	DABUFFER 141		DAENABLE yes		DALINES 32
+#	DAMODE replace		DAVISIBILITY yes	ECHO no
+#	EDITMARGINS 1 32	FLAGGING input		INSERTREPLACE replace
+#	LFCR no			LOCKKEYBOARD no		ORIGINMODE relative
+#	PROMPTMODE no		SELECTCHARSET G0 B	SELECTCHARSET G1 0
+#	TABS -2
+# Other setup modes may be set for operator convenience or communication
+# requirements; I recommend
+#	ACURSOR 1 0		AUTOREPEAT yes		AUTOWRAP yes
+#	BYPASSCANCEL <LF>	CURSORKEYMODE no	DAINDEX 1 0 0
+#	EOFSTRING ''		EOLSTRING <CR>		EOMCHARS <CR> <NU>
+#	GAMODE overstrike	GCURSOR 0 100 0		GSPEED 9 3
+#	IGNOREDEL no		KEYEXCHAR <DL>		NVDEFINE -53 "<NU>"
+#	PROMPTSTRING ''		QUEUESIZE 2620		WINDOW 0 0 4095 3132
+#	XMTDELAY 0
+# and factory color maps.  After setting these modes, save them with NVSAVE.  No
+# delays are specified; use "stty ixon -ixany" to enable DC3/DC1 flow control!
+# "IC" cannot be used in combination with "im" & "ei".
+tek4106brl|tek4107brl|tek4109brl|Tektronix 4106 4107 or 4109:\
+	:ms:xo:\
+	:co#80:it#8:li#32:vt#3:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:LE=\E[%dD:\
+	:RI=\E[%dC:SF=\E[%dS:SR=\E[%dT:UP=\E[%dA:ac=:ae=^O:al=\E[L:\
+	:as=^N:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:\
+	:dl=\E[M:do=^J:ec=\E[%dX:ei=\E[4l:ho=\E[H:im=\E[4h:\
+	:is=\E%!1:k0=\EOA:k1=\EOB:k2=\EOC:k3=\EOD:k4=\EOP:k5=\EOQ:\
+	:k6=\EOR:k7=\EOS:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:\
+	:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:l0=F1:l1=F2:l2=F3:l3=F4:l4=F5:\
+	:l5=F6:l6=F8:le=^H:ll=\E[32;H:mb=\E[5m:md=\E[1m:me=\E[m:\
+	:mr=\E[7m:nd=\E[C:nw=\EE:\
+	:r1=\030\E%!0\EKC\E\014\EKR0\EKF0\ENM0\ELBH=\ETF8000010F40\ELI100\ELLB0\ELM0\EKE0\ENF1\EKS0\END0\ERE0\E%!1\Ec\E[?3;5l\E[?7;8h\E[r\E[m\E>:\
+	:rc=\E8:sc=\E7:se=\E[m:sf=^J:so=\E[7;42m:sr=\EM:st=\EH:\
+	:ta=^I:te=\E%!0\ELBH=\E%!1:ti=\E[?6l:ue=\E[m:up=\EM:\
+	:us=\E[4m:ve=\E%!0\ETD10\E%!1:vi=\E%!0\ETD00\E%!1:\
+	:vs=\E%!0\ETD70\E%!1:
+
+tek4107|tek4109|tektronix terminals 4107 4109:\
+	:am:bs:mi:ms:ul:xn:xt:\
+	:co#79:it#8:li#29:\
+	:bl=^G:cd=\EJ:ce=\EK:cl=\ELZ:cm=\EY%+ %+ :cr=^M:do=^J:kb=^H:\
+	:kd=\EB:kl=\ED:kr=\EC:ku=\EA:le=^H:mb=\E%!1\E[5m\E%!0:\
+	:md=\E%!1\E[1m\E%!0:me=\E%!1\E[m\E%!0:\
+	:mh=\E%!1\E[<0m\E%!0:mr=\E%!1\E[7m\E%0:nd=\EC:\
+	:..sa=\E%%\0411\E[%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;m\E%%\0410:\
+	:se=\E%!1\E[m\E%!0:sf=^J:so=\E%!1\E[7;5m\E%!0:sr=\EI:\
+	:ta=^I:ue=\E%!1\E[m\E%!0:up=\EA:us=\E%!1\E[4m\E%!0:\
+	:ve=\E%!0:vs=\E%!3:
+# Tektronix 4207 with sysline.  In the ancestral termcap file this was 4107-s;
+# see the note attached to tek4207.
+tek4207-s|Tektronix 4207 with sysline but no memory:\
+	:es:hs:\
+	:ds=\E7\E[?6l\E[2K\E[?6h\E8:fs=\E[?6h\E8:\
+	:i1=\E%!1\E[2;32r\E[132D\E[2g\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[J:\
+	:is=\E7\E[?6l\E[2K\E[?6h\E8:\
+	:ts=\E7\E[?6l\E[2K\E[;%i%df:tc=tek4107:
+
+# The 4110 series may be a wonderful graphics series, but they make the 4025
+# look good for screen editing.  In the dialog area, you can't move the cursor
+# off the bottom line.  Out of the dialog area, ^K moves it up, but there
+# is no way to scroll.
+# 
+# Note that there is a floppy for free from Tek that makes the 
+# 4112 emulate the vt52 (use the vt52 termcap). There is also
+# an expected enhancement that will use ANSI standard sequences.
+# 
+# 4112 in non-dialog area pretending to scroll. It really wraps 
+# but vi is said to work (more or less) in this mode.
+# 
+# 'vi' works reasonably well with this entry.
+#
+otek4112|o4112-nd|otek4113|otek4114|old tektronix 4110 series:\
+	:am:\
+	:co#80:li#34:\
+	:bl=^G:cl=\E^L:cr=^M:do=^J:le=^H:sf=^J:te=\EKA1\ELV1:\
+	:ti=\EKA0\ELV0\EMG0:up=^K:
+# The 4112 with the ANSI compatibility enhancement
+tek4112|tek4114|tektronix 4110 series:\
+	:am:bs:db:\
+	:co#80:li#34:\
+	:al=\E[L:bt=\E[Z:cd=\E[0J:ce=\E[0K:cl=\E[2J\E[0;0H:\
+	:cm=\E[%i%d;%dH:dc=\E[P:dl=\E[M:ei=:ic=\E[@:im=:\
+	:is=\E3\0411:le=^H:me=\E[m:nd=\E[C:se=\E[m:\
+	:sf=\E7\E[0;0H\E[M\E8:so=\E[7m:sr=\E7\E[0;0H\E[L\E8:\
+	:ue=\E[m:up=\EM:us=\E[4m:
+tek4112-nd|4112 not in dialog area:\
+	:ns:\
+	:up=^K:tc=tek4112:
+tek4112-5|4112 in 5 line dialog area:\
+	:li#5:tc=tek4112:
+# (tek4113: this used to have ":nd=\LM1\s\LM0:", someone's mistake;
+# removed ":as=\E^N:, :ae=\E^O:", which had been commented out in 8.3.
+# Note, the !0 and !1 sequences in :te:/:ti:/:ve:/:vi: were
+# previously \0410 and \0411 sequences...I don't *think* they were supposed
+# to be 4-digit octal -- esr)
+tek4113|tektronix 4113 color graphics with 5 line dialog area:\
+	:am:bs:da:eo:\
+	:co#80:li#5:\
+	:cl=\ELZ:do=^J:is=\EKA1\ELL5\ELV0\ELV1:le=^H:\
+	:nd=\ELM1 \ELM0:uc=\010\ELM1_\ELM0:\
+	:vb=\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERB0:
+tek4113-34|tektronix 4113 color graphics with 34 line dialog area:\
+	:li#34:\
+	:is=\EKA1\ELLB2\ELV0\ELV1:tc=tek4113:
+# :ns: left off to allow vi visual mode. APL font (:as=\E^N:/:ae=\E^O:) not 
+# supported here. :uc: is slow, but looks nice. Suggest setenv MORE -up .
+# :vb: needs enough delay to let you see the background color being toggled.
+tek4113-nd|tektronix 4113 color graphics with no dialog area:\
+	:am:bs:eo:\
+	:co#80:it#8:li#34:\
+	:cl=\E^L:do=^J:ho=\ELF7l\177 @:is=\ELZ\EKA0\ELF7l\177 @:\
+	:le=^H:ll=\ELF hl @:nd=^I:se=\EMT1:so=\EMT2:ta=^I:\
+	:uc=\010\EMG1_\EMG0:up=^K:\
+	:vb=\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERB0:\
+	:vs=\ELZ\EKA0:
+# This entry is from Tek. Inc.  (Brian Biehl)
+# (tek4115: :bc: renamed to :le:, <rmam>/<smam> added based on init string -- esr)
+otek4115|Tektronix 4115:\
+	:am:bs:da:db:eo:\
+	:co#80:it#8:li#34:\
+	:RA=\E[?7l:SA=\E[?7h:al=\E[L:bt=\E[Z:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:dc=\E[P:dl=\E[M:do=\E[B:\
+	:ei=\E[4l:ho=\E[H:if=/usr/share/tabset/vt100:im=\E[4h:\
+	:is=\E%!0\E%\014\ELV0\EKA1\ELBB2\ENU@=\ELLB2\ELM0\ELV1\EKYA?\E%!1\E[<1l\E[?7h\E[?8h\E[34;1H\E[34B\E[m:\
+	:kb=^H:ke=\E>:ks=\E=:le=\E[D:me=\E[m:nd=\E[C:se=\E[m:\
+	:so=\E[7m:sr=\EM:ta=^I:te=\E%!0\ELBG8\E%!1\E[34;1H\E[J:\
+	:ti=\E%!0\ELBB2\E%!1:ue=\E[m:up=\E[A:us=\E[4m:\
+	:ve=\E%!0\ELBG8\E%!1\E[34;1H:vs=\E%!0\ELBB2\E%!1:
+tek4115|newer tektronix 4115 entry with more ANSI capabilities:\
+	:am:xo:\
+	:co#80:li#34:\
+	:AL=\E[%dL:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:LE=\E[%dD:\
+	:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:UP=\E[%dA:al=\E[L:bl=^G:\
+	:bt=\E[Z:cd=\E[J:ce=\E[K:ch=\E[%+^AG:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:cr=^M:ct=\E[2g:cv=\E[%+^Ad:dc=\E[P:\
+	:dl=\E[M:do=^J:ei=:ho=\E[H:ic=\E[@:im=:kb=^H:kd=\E[B:kh=\E[H:\
+	:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mb=\E[5m:md=\E[1m:me=\E[m:\
+	:mk=\E[8m:mr=\E[7m:nd=\E[C:..rp=%p1%c\E[%p2%{1}%-%db:\
+	:..sa=\E[%?%p1%t7;%;%?%p2%t4;%;%?%p3%t7;%;%?%p4%t5;%;%?%p6%t1;%;m:\
+	:se=\E[m:sf=^J:so=\E[7m:st=\EH:ta=^I:ue=\E[m:up=\E[A:\
+	:us=\E[4m:
+# The tek4125 emulates a vt100 incorrectly - the scrolling region
+# command is ignored.  The following entry replaces :cs: with the needed
+# :AL:, :AL:, and :im:; removes some cursor pad commands that the tek4125
+# chokes on; and adds a lot of initialization for the tek dialog area.
+# Note that this entry uses all 34 lines and sets the cursor color to green.
+# Steve Jacobson 8/85
+# (tek4125: there were two "\!"s in the is that I replaced with "\E!";
+# commented out, :im:=\E1 because there's no :ei:  -- esr)
+tek4125|tektronix 4125:\
+	:li#34:\
+	:al=\E[1L:cs@:dl=\E[1M:\
+	:is=\E%\E\0410\EQD1\EUX03\EKA\ELBB2\ELCE0\ELI100\ELJ2\ELLB2\ELM0\ELS1\ELX00\ELV1\E%\E\0411\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:\
+	:ks=\E=:rc@:sc@:\
+	:tc=vt100:
+
+# From: <jcoker@ucbic>
+# (tek4207: This was the termcap file's entry for the 4107/4207, but SCO
+# supplied another, less capable 4107 entry.  So we'll use that for 4107 and
+# note that if jcoker wasn't confused you may be able to use this one.
+# I merged in :ms:,:sf:,:sr:,<invis>,:ct: from a BRL entry -- esr)
+tek4207|Tektronix 4207 graphics terminal with memory:\
+	:am:bw:mi:ms:ul:xn:\
+	:co#80:it#8:li#32:\
+	:al=3\E[L:bt=\E[Z:cd=\E[J:ce=5\E[K:cl=156\E[H\E[J:\
+	:cm=\E[%i%d;%dH:ct=\E[1g:dc=4\E[P:dl=3\E[M:do=^J:ei=:\
+	:ho=\E[H:ic=4\E[@:im=:\
+	:is=\E%!0\ELBP0\E%!1\E[H\E[2g\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[J:\
+	:kd=\ED:kh=\E[H:kl=\E[D:kr=\E[C:ku=\EM:le=^H:mb=\E[5m:\
+	:md=\E[1m:me=\E[m:mk=\E[=6;<5:mr=\E[7m:nd=\E[C:se=\E[m:\
+	:sf=\E[S:so=\E[7m:sr=\E[T:ta=^I:\
+	:te=\E[?6h\E%!0\ELBP0\E%!1\E[32;1f:ti=\E[?6l\E[H\E[J:\
+	:ue=\E[m:up=\EM:us=\E[4m:
+
+# From: <carolyn@dali.berkeley.edu>  Thu Oct 31 12:54:27 1985
+# (tek4404: There was a "\!" in :ti: that I replaced with "\E!".
+# Tab had been given as \E2I,that must be the tab-set capability -- esr)
+tek4404|tektronix 4404:\
+	:bs:\
+	:co#80:it#8:li#32:\
+	:al=\E[1L:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:\
+	:cs=\E[%i%d;%dr:dc=\E[P:dl=\E[1M:do=^J:ei=\E[4l:ho=\E[H:\
+	:im=\E[4h:kd=\E[B:ke=\E[?1h:kl=\E[D:kr=\E[C:ks=\E[?1l:\
+	:ku=\E[A:le=^H:mb=\E[5m:md=\E[1m:me=\E[m:nd=\E[C:rc=\E8:\
+	:sc=\E7:se=\E[27m:so=\E[7m:st=\E[2I:ta=^I:\
+	:te=\E[1;1H\E[0J\E[?6h\E[?1l:\
+	:ti=\E%\E\0411\E[1;32r\E[?6l\E>:ue=\E[m:up=\E[A:\
+	:us=\E[4m:
+# Some unknown person wrote:
+# I added the is string - straight Unix has ESC ; in the login 
+# string which sets a ct8500 into monitor mode (aka 4025 snoopy 
+# mode). The is string here cleans up a few things (but not 
+# everything).
+ct8500|tektronix ct8500:\
+	:am:bw:da:db:\
+	:co#80:li#25:\
+	:al=\E^L:bl=^G:bt=\E^I:cd=\E^U:ce=\E^T:cl=\E^E:\
+	:cm=\E|%+ %+ :cr=^M:dc=\E^]:dl=\E^M:do=^J:ei=:ic=\E^\:im=:\
+	:is=\037\EZ\Ek:le=^H:me=\E :nd=\ES:se=\E :sf=^J:so=\E$:\
+	:sr=\E^A:ta=^I:ue=\E :up=\ER:us=\E\041:
+
+# Tektronix 4205 terminal.
+#
+# am is not defined because the wrap around occurs not when the char.
+# is placed in the 80'th column, but when we are attempting to type
+# the 81'st character on the line.  (esr: hmm, this is like the vt100
+# version of xenl, perhaps am + xenl would work!)
+#
+# Bold, dim, and standout are simulated by colors and thus not allowed
+# with colors.  The tektronix color table is mapped into the RGB color
+# table by setf/setb. All colors are reset to factory specifications by oc.
+# The <initc> cap uses RGB notation to define colors.  for arguments 1-3 the 
+# interval (0-1000) is broken into 8 smaller sub-intervals (125).  Each sub-
+# interval then maps into pre-defined value.
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+tek4205|tektronix 4205:\
+	:cc:mi:ms:\
+	:Co#8:NC#49:co#80:it#8:li#30:pa#63:\
+	:AL=\E[%dL:DO=\E[%dB:IC=\E[%d@:LE=\E[%dD:RI=\E[%dC:\
+	:UP=\E[%dA:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=^O:al=\E[1L:as=^N:bl=^G:bt=\E[Z:cb=\E[1K:cd=\E[J:\
+	:ce=\E[K:cl=\E[2J\E[H:cm=\E[%i%d;%dH:cr=^M:ct=\E[1g:\
+	:dc=\E[1P:dl=\E[1M:do=\E[B:eA=\E)0:ec=\E%dX:ei=\E[4l:\
+	:ho=\E[H:i1=\E%!0\ETM1\E%!1\E[m:im=\E[4h:k0=\EOA:k1=\EOB:\
+	:k2=\EOC:k3=\EOD:k4=\EP:k5=\EQ:k6=\ER:k7=\ES:kb=^H:kd=\E[B:\
+	:kl=\E[D:kr=\E[C:ku=\E[A:le=\E[D:mb=\E[5m:md=\E[=7;<4m:\
+	:me=\E[=0;<1m\E[24;25;27m\017:mh=\E[=1;<6m:mk=\E[=6;<5:\
+	:mr=\E[7m:nd=\E[C:\
+	:oc=\E%!0\ETFB000001F4F4F42F40030F404A4C<F450F4F46F40F47F4F40\E%!1:\
+	:op=\E[39;40m:se=\E[=0;<1m:sf=\ED:so=\E[=2;<3m:sr=\EM:\
+	:ta=^I:te=:ti=\E%%\0411\E[?6l\E[2J:ue=\E[24m:up=\E[A:\
+	:us=\E[4m:
+
+#### Teletype (tty)
+#
+# These are the hardcopy Teletypes from before AT&T bought the company,
+# clattering electromechanical dinosaurs in Bakelite cases that printed on
+# pulpy yellow roll paper.  If you remember these you go back a ways.
+# Teletype-branded VDTs are listed in the AT&T section.
+#
+# The earliest UNIXes were designed to use these clunkers; nroff and a few
+# other programs still default to emitting codes for the Model 37.
+#
+
+tty33|tty35|model 33 or 35 teletype:\
+	:hc:os:xo:\
+	:co#72:\
+	:bl=^G:cr=^M:do=^J:sf=^J:
+tty37|model 37 teletype:\
+	:bs:hc:os:xo:\
+	:bl=^G:cr=^M:do=^J:hd=\E9:hu=\E8:le=^H:sf=^J:up=\E7:
+
+# There are known to be at least three flavors of the tty40, all seem more
+# like IBM half duplex forms fillers than ASCII terminals.  They have lots of
+# awful braindamage, such as printing a visible newline indicator after each
+# newline.  The 40-1 is a half duplex terminal and is hopeless.  The 40-2 is
+# braindamaged but has hope and is described here.  The 40-4 is a 3270
+# lookalike and beyond hope.  The terminal has visible bell but I don't know
+# it - it's null here to prevent it from showing the BL character.
+# There is an \EG in <nl> because of a bug in old vi (if stty says you have
+# a "newline" style terminal (-crmode) vi figures all it needs is nl
+# to get crlf, even if :cr: is not ^M.)
+# (tty40: removed obsolete ":nl=\EG\EB:", it's just do+cr -- esr)
+tty40|ds40|ds40-2|dataspeed40|teletype dataspeed 40/2:\
+	:bs:xo:\
+	:co#80:li#24:\
+	:al=\EL:cd=\EJ:cl=\EH\EJ:cr=\EG:ct=\EH\E2:dc=\EP:dl=\EM:\
+	:do=\EB:ei=:ho=\EH:ic=\E\136:im=:kb=^]:kl=^H:le=^H:nd=\EC:\
+	:pf=^T:po=\022:r2=\023\ER:se=\E4:sf=\ES:so=\E3:sr=\ET:\
+	:st=\E1:ta=\E@:up=\E7:
+tty43|model 43 teletype:\
+	:am:bs:hc:os:xo:\
+	:co#132:\
+	:bl=^G:cr=^M:do=^J:kb=^H:le=^H:sf=^J:
+
+#### Tymshare
+#
+
+# You can add :is=\E<: to put this 40-column mode, though I can't
+# for the life of me think why anyone would want to.
+scanset|sc410|sc415|Tymshare Scan Set:\
+	:am:bw:ms:\
+	:co#80:li#24:\
+	:ac=j%k4l<m-q\054x5:ae=^O:as=^N:bl=^G:cd=\EJ:ce=\EK:\
+	:cl=\EH\EJ:cm=\EY%+ %+ :cr=^M:do=^J:ho=\EH:kd=\EB:kl=\ED:\
+	:kr=\EC:ku=\EA:le=^H:nd=^I:pf=\E;0:po=\E;0:ps=\E;3:r1=\E>:\
+	:rc=^C:sc=^B:sf=^J:up=^K:
+
+#### Volker-Craig (vc)
+#
+# If you saw a Byte Magazine cover with a terminal on it during the early
+# 1980s, it was probably one of these.  Carl Helmers liked them because
+# they could crank 19.2 and were cheap (that is, he liked them until he tried
+# to program one...)
+#
+
+# Missing in vc303a and vc303 descriptions:  they scroll 2 lines at a time
+# every other linefeed.
+vc303|vc103|vc203|volker-craig 303:\
+	:am:bs:ns:\
+	:co#80:li#24:\
+	:bl=^G:cl=\014:cr=^M:do=^J:ho=\013:kd=^J:kl=^H:kr=^I:ku=^N:\
+	:le=^H:ll=\017W:nd=^I:up=^N:
+vc303a|vc403a|volker-craig 303a:\
+	:ce=\026:cl=\030:ho=\031:kr=^U:ku=^Z:ll=^P:nd=^U:up=^Z:tc=vc303:
+# (vc404: removed obsolete ":ma=^Z^P^U :" -- esr)
+vc404|volker-craig 404:\
+	:am:bs:\
+	:co#80:li#24:\
+	:bl=^G:cd=\027:ce=\026:cl=\030:cm=\020%+ %+ :cr=^M:do=^J:\
+	:ho=\031:kd=^J:kl=^H:kr=^U:ku=^Z:le=^H:nd=^U:sf=^J:up=^Z:
+vc404-s|volker-craig 404 w/standout mode:\
+	:do=^J:se=^O:so=^N:tc=vc404:
+# From: <wolfgang@cs.sfu.ca>
+# (vc414: merged in cup/dl1/home from an old vc414h-noxon)
+vc414|vc414h|Volker-Craig 414H in sane escape mode.:\
+	:am:bs:\
+	:co#80:li#24:\
+	:al=\E\032:cd=\E^X:ce=10\E\017:cl=\E\034:cm=\E\021%r%.%.:\
+	:dc=\E3:dl=\E\023:do=\E^K:ei=:ho=\E^R:ic=\E\072:im=:k0=\EA:\
+	:k1=\EB:k2=\EC:k3=\ED:k4=\EE:k5=\EF:k6=\EG:k7=\EH:kd=\E^K:\
+	:kh=\E^R:kl=^H:kr=^P:ku=\E^L:l0=PF1:l1=PF2:l2=PF3:l3=PF4:\
+	:l4=PF5:l5=PF6:l6=PF7:l7=PF8:nd=^P:se=\E^_:so=\E^Y:up=\E^L:
+vc415|volker-craig 415:\
+	:cl=^L:tc=vc404:
+
+######## OBSOLETE PERSONAL-MICRO CONSOLES AND EMULATIONS
+#
+
+#### IBM PC and clones
+#
+
+# The pcplot IBM-PC terminal emulation program is really messed up. It is
+# supposed to emulate a vt-100, but emulates the wraparound bug incorrectly,
+# doesn't support scrolling regions, ignores add line commands, and ignores
+# delete line commands. Consequently, the resulting behavior looks like a
+# crude adm3a-type terminal.
+# Steve Jacobson 8/85
+pcplot|pc-plot terminal emulation program:\
+	:xn@:\
+	:AL@:DL@:al@:cs@:dl@:rc@:sc@:tc=vt100:
+# KayPro II from Richard G Turner <rturner at Darcom-Hq.ARPA>
+# I've found that my KayPro II, running MDM730, continues to emulate an
+# ADM-3A terminal, just like I was running TERM.COM. On our 4.2 UNIX
+# system the following termcap entry works well:
+# I have noticed a couple of minor glitches, but nothing I can't work
+# around. (I added two capabilities from the BRL entry -- esr)
+kaypro|kaypro2|kaypro II:\
+	:am:bs:\
+	:co#80:li#24:\
+	:al=\EE:bl=^G:cd=^W:ce=^X:cl=1\032:cm=\E=%+ %+ :cr=^M:\
+	:dl=\ER:do=^J:ho=^^:kd=^J:kr=^L:ku=^K:nd=^L:sf=^J:up=^K:
+
+# From IBM, Thu May  5 19:35:27 1983
+# (ibmpc: commented out :im:=\200R because we don't know :ei: -- esr)
+ibm-pc|ibm5051|5051|IBM Personal Computer (no ANSI.SYS):\
+	:am:bs:\
+	:co#80:li#24:\
+	:bl=^G:cl=^L^K:cr=^M^^:do=^J:ho=^K:kd=^_:le=^]:nd=^\:sf=\n:\
+	:up=^^:
+
+ibmpc|wy60-PC|wyse60-PC|IBM PC/XT running PC/IX:\
+	:am:bw:eo:hs:km:ms:ul:\
+	:co#80:it#8:li#24:\
+	:@7=\E[Y:DO=\E[%dB:LE=\E[%dD:RI=\E[%dC:SF=\E[%dS\E[%dB:\
+	:SR=\E[%dT\E[%dA:UP=\E[%dA:\
+	:ac=j\331k\277l\332m\300n\305q\304t\303u\264v\301w\302x\263:\
+	:bl=^G:cd=\E[J:ce=\E[K:ch=\E[%i%dG:cl=\Ec:cm=\E[%i%d;%dH:\
+	:cr=^M:do=\E[B:ec=\E[%dX:ho=\E[H:k1=\240:k2=\241:k3=\242:\
+	:k4=\243:k5=\244:k6=\245:k7=\246:k8=\247:k9=\250:k;=\251:\
+	:kB=^]:kD=\177:kI=\E[^H:kN=\E[U:kb=^H:kd=\E[B:kh=\E[H:\
+	:kl=\E[D:kr=\E[C:ku=\E[A:le=\E[D:ll=\E[24;1H:mb=\E[5m:\
+	:md=\E[1m:me=\E[m:mk=\E[30;40m:mr=\E[7m:nd=\E[C:nw=^M:\
+	:..sa=\E[%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;m:\
+	:se=\E[m:sf=\E[S\E[B:so=\E[7m:sr=\E[T\E[A:ue=\E[m:up=\E[A:\
+	:us=\E[4m:
+
+#### Apple II
+#
+# Apple II firmware console first, then various 80-column cards and 
+# terminal emulators.  For two cents I'd toss all these in the UFO file
+# along with the 40-column apple entries.
+#
+
+# From: brsmith@umn-cs.cs.umn.edu (Brian R. Smith) via BRL
+#	'it#8' tells UNIX that you have tabs every 8 columns.  This is a
+#		function of TIC, not the firmware.
+#	The clear key on a IIgs will do something like clear-screen, 
+#		depending on what you're in.
+appleIIgs|appleIIe|appleIIc|Apple 80 column firmware interface:\
+	:am:bs:bw:eo:ms:\
+	:co#80:it#8:li#24:\
+	:bl=^G:cd=^K:ce=^]:cl=^L:cm=\036%r%+ %+ :cr=^M:do=^J:ho=^Y:\
+	:kC=^X:kD=\177:kb=^H:kd=^J:kl=^H:kr=^U:ku=^K:le=^H:nd=^\:\
+	:nw=^M^W:se=^N:sf=^W:so=^O:sr=^V:ta=^I:up=^_:
+# Apple //e with 80-column card, entry from BRL
+# The modem interface is permitted to discard LF (maybe DC1), otherwise
+# passing characters to the 80-column firmware via COUT (PR#3 assumed).
+# Auto-wrap does not work right due to newline scrolling delay, which also
+# requires that you set "stty cr2".
+# Note: Cursor addressing is only available via the Pascal V1.1 entry,
+# not via the BASIC PR#3 hook.  All this nonsense can be avoided only by
+# using a terminal emulation program instead of the built-in firmware.
+apple2e|Apple //e:\
+	:bw:ms:\
+	:co#80:li#24:\
+	:bl=^G:cd=4*\013:ce=4\035:cl=100\014:do=^J:ho=^Y:is=^R^N:\
+	:kb=^H:kd=^J:kl=^H:kr=^U:ku=^K:le=^H:me=^N:mr=^O:nw=100\r:\
+	:r1=^R^N:se=^N:sf=^W:so=^O:sr=^V:ta=^I:up=^_:
+# mcvax!vu44!vu45!wilcke uses the "ap" entry together with Ascii Express Pro
+# 4.20, with incoming and outgoing terminals both on 0, emulation On.
+apple2e-p|Apple //e via Pascal:\
+	:cm=\036%r%+ %+ :kb=^H:kd=^J:kl=^H:tc=apple2e:
+# (ASCII Express) MouseTalk "Standard Apple //" emulation from BRL
+# Enable DC3/DC1 flow control with "stty ixon -ixany".
+apple-ae|ASCII Express:\
+	:am:bs:bw:ms:nx:xo:\
+	:co#80:it#8:li#24:\
+	:bl=500\007:cd=^K:ce=^]:cl=^L:cm=\036%r%+ %+ :cr=^M:do=^J:\
+	:ho=^Y:is=^R^N:kC=^X:kd=^J:kl=^H:kr=^U:ku=^K:le=^H:me=^N:\
+	:mr=^O:nd=^U:r1=^R^N:se=^N:sf=^W:so=^O:sr=^V:up=^_:
+appleII|apple ii plus:\
+	:am:bs:\
+	:co#80:it#8:li#24:\
+	:cd=^K:ce=^]:cl=^L:cm=\036%r%+ %+ :do=^J:ho=\E^Y:\
+	:is=\024T1\016:kd=^J:kr=^U:le=^H:me=^N:nd=^\:se=^N:so=^O:\
+	:ta=^I:up=^_:vb=\024G1\024T1:ve=^TC2:vs=^TC6:
+# Originally by Gary Ford 21NOV83
+# From: <ee178aci%sdcc7@SDCSVAX.ARPA>  Fri Oct 11 21:27:00 1985
+apple-80|apple II with smarterm 80 col:\
+	:am:bs:bw:\
+	:co#80:li#24:\
+	:bt=^R:cd=10*\013:ce=10\035:cl=10*\014:cm=\036%r%+ %+ :\
+	:cr=10*\r:do=^J:ho=^Y:le=^H:nd=^\:up=^_:
+apple-soroc|apple emulating soroc 120:\
+	:am:\
+	:co#80:li#24:\
+	:bl=^G:cd=\EY:ce=\ET:cl=\E*:cm=\E=%+ %+ :cr=^M:do=^J:ho=^^:\
+	:kd=^J:kl=^H:kr=^L:ku=^K:le=^H:nd=^L:sf=^J:up=^K:
+# From Peter Harrison, Computer Graphics Lab, San Francisco
+#   ucbvax!ucsfmis!harrison  .....uucp
+#   ucbvax!ucsfmis!harrison@BERKELEY   .......ARPA
+# "These two work.  If you don't have the inverse video chip for the
+# Apple with videx then remove the :so: and :se: fields."
+# (apple-videx: this used to be called DaleApple -- esr)
+apple-videx|Apple with videx videoterm 80 column board with inverse video:\
+	:am:bs:xn:\
+	:co#80:it#8:li#24:\
+	:cd=^K:ce=^]:cl=300\014:cm=\036%r%+ %+ :do=^J:ho=^Y:kd=^J:\
+	:kh=^Y:kl=^H:kr=^U:le=^H:me=^Z2:nd=^\:se=^Z2:so=^Z3:ta=^I:\
+	:up=^_:
+# My system [for reference] : Apple ][+, 64K, Ultraterm display card,
+#			      Apple Cat ][ 212 modem, + more all
+#			      controlled by ASCII Express: Pro.
+# From Dave Shaver <isucs1!shaver>
+apple-uterm-vb|Videx Ultraterm for Apple micros with Visible Bell:\
+	:am:bs:eo:xt:\
+	:co#80:li#24:\
+	:ac=:cd=^K:ce=^]:cl=^L:cm=\036%r%+ %+ :ho=^Y:\
+	:is=^V4^W06\017\rVisible Bell Installed.\016\r\n:\
+	:nd=^\:se=^N:so=^O:up=^_:vb=^W35^W06:
+apple-uterm|Ultraterm for Apple micros:\
+	:am:bs:eo:xt:\
+	:co#80:li#24:\
+	:ac=:cd=^K:ce=^]:cl=^L:cm=\036%r%+ %+ :ho=^Y:\
+	:is=^V4^W06\016:nd=^\:se=^N:so=^O:up=^_:
+# from trwrba!bwong (Bradley W. Wong):
+#
+# This entry assumes that you are using an apple with the UCSD Pascal
+# language card.  SYSTEM.MISCINFO is assumed to be the same as that
+# supplied with the standard apple except that screenwidth should be set
+# using SETUP to 80 columns.  Note that the right arrow in not mapped in
+# this termcap entry.  This is because that key, on the Apple, transmits
+# a ^U and would thus preempt the more useful "up" function of vi.
+#
+# HMH 2/23/81
+apple80p|80-column apple with Pascal card:\
+	:am:bw:\
+	:co#80:li#24:\
+	:cd=^K:ce=^]:cl=^Y^L:cm=\036%r%+ %+ :ho=^Y:kl=^H:nd=^\\072:\
+	:up=^_:
+#
+# Apple II+ equipped with Videx 80 column card
+#
+# Terminfo from ihnp4!ihu1g!djc1 (Dave Christensen) via BRL;
+# manually converted by D A Gwyn
+#
+# DO NOT use any terminal emulation with this data base, it works directly
+# with the Videx card.  This has been tested with vi 1200 baud and works fine.
+#
+# This works great for vi, except I've noticed in pre-R2, ^U will scroll back
+# 1 screen, while in R2 ^U doesn't.
+# For inverse alternate character set add:
+#	:as:=^O::ae:=^N:
+# (apple-v: added it#8 -- esr)
+apple-videx2|Apple II+ w/ Videx card (similar to Datamedia h1520):\
+	:am:xn:\
+	:co#80:it#8:li#24:\
+	:bl=100\007:cd=16*\013:ce=^]:cl=16*\014:cm=\036%r%+ %+ :\
+	:cr=^M:do=^J:ho=^Y:kb=^H:kd=^J:kh=^Y:kl=^H:kr=^\:ku=^_:le=^H:\
+	:nd=^\:se=^Z2:sf=^J:so=^Z3:ta=8\011:up=^_:
+apple-videx3|vapple|Apple II with 80 col card:\
+	:am:bs:\
+	:co#80:li#24:\
+	:ce=\Ex:cl=\Ev:cm=\EY%+ %+ :ho=\EH:k0=\EP:k1=\EQ:k2=\ER:\
+	:k3=\E :k4=\E\041:k5=\E":k6=\E#:k7=\E$:k8=\E%:k9=\E&:kd=\EB:\
+	:kh=\EH:kl=\ED:kr=\EC:ku=\EA:nd=\EC:up=\EA:
+#From: decvax!cbosgd!cbdkc1!mww Mike Warren via BRL
+aepro|Apple II+ running ASCII Express Pro--vt52:\
+	:bs:\
+	:co#80:li#24:\
+	:cd=\EJ:ce=\EK:cl=300\014:cm=\EY%+ %+ :ho=\EH:nd=\EC:\
+	:up=\EA:
+# UCSD addition: Yet another termcap from Brian Kantor's Micro Munger Factory
+apple-vm80|ap-vm80|apple with viewmax-80:\
+	:bs:\
+	:co#80:li#24:\
+	:cd=300\013:ce=^]:cl=300\014:cm=100\036%+ %+ :ho=200\031:\
+	:nd=^\\072:up=^_:
+
+#### Apple Lisa & Macintosh
+#
+
+# (lisa: changed :vs: to :ve: -- esr)
+lisa|apple lisa console display (black on white):\
+	:am:bs:eo:ms:\
+	:co#88:it#8:li#32:\
+	:ac=jdkclfmenbqattuvvuwsx`:ae=\E[10m:al=\E[L:as=\E[11m:\
+	:cd=\E[J:ce=\E[K:cl=^L:cm=\E[%i%d;%dH:dc=\E[P:dl=\E[M:\
+	:do=\E[B:ei=:ho=\E[H:ic=\E[@:im=:is=\E>\E[m\014:kb=^H:\
+	:kd=\E[B:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:me=\E[m:nd=\E[C:\
+	:se=\E[m:so=\E[7m:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:ve=\E[5l:\
+	:vi=\E[5h:
+liswb|apple lisa console display (white on black):\
+	:is=\E>\E[0;7m\014:se=\E[0;7m:so=\E[m:ue=\E[0;7m:\
+	:us=\E[4m:tc=lisa:
+
+# lisaterm from ulysses!gamma!epsilon!mb2c!jed (John E. Duncan III) via BRL;
+# :is: revised by Ferd Brundick <fsbrn@BRL.ARPA>
+#
+# These entries assume that the 'Auto Wraparound' is enabled.
+# Xon-Xoff flow control should also be enabled.
+#
+# The vt100 uses :rs2: and :rf: rather than :is2:/:tbc:/:hts: because the tab
+# settings are in non-volatile memory and don't need to be reset upon login.
+# Also setting the number of columns glitches the screen annoyingly.
+# You can type "reset" to get them set.
+#
+lisaterm|Apple Lisa or Lisa/2 running LisaTerm vt100 emulation:\
+	:am:bs:pt:xn:xo:\
+	:co#80:it#8:kn#4:li#24:vt#3:\
+	:DO=\E[%dB:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:bl=^G:cd=\E[J:\
+	:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:do=^J:ho=\E[H:k0=\EOP:k1=\EOQ:\
+	:k2=\EOR:k3=\EOS:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:\
+	:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:l0=F1:l1=F2:l2=F3:l3=F4:le=^H:\
+	:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:\
+	:r1=\E>\E[?1l\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[1;24r:\
+	:rc=\E8:sc=\E7:se=\E[m:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:ue=\E[m:up=\E[A:us=\E[4m:
+# Lisaterm in 132 column ("wide") mode.
+lisaterm-w|Apple Lisa with Lisaterm in 132 column mode:\
+	:co#132:\
+	:kb=^H:kd=^J:kl=^H:tc=lisaterm:
+# Although MacTerminal has insert/delete line, it is commented out here
+# since it is much faster and cleaner to use the "lock scrolling region"
+# method of inserting and deleting lines due to the MacTerminal implementation.
+# Also, the "Insert/delete ch" strings have an extra character appended to them
+# due to a bug in MacTerminal V1.1.  Blink is disabled since it is not
+# supported by MacTerminal.
+mac|macintosh|Macintosh with MacTerminal:\
+	:xn:\
+	:dN#30:\
+	:dc=7\E[P:ei=:ic=9\E[@:im=:ip=7:mb@:tc=lisa:
+# Lisaterm in 132 column ("wide") mode.
+mac-w|macterminal-w|Apple Macintosh with Macterminal in 132 column mode:\
+	:co#132:tc=mac:
+
+#### Radio Shack/Tandy
+#
+
+# (coco3: This had "ta" used incorrectly as a boolean and bl given as "bl#7".
+# I read these as mistakes for ":it#8:" and ":bl=\007:" respectively -- esr)
+# From: <{pbrown,ctl}@ocf.berkeley.edu> 12 Mar 90
+coco3|os9LII|Tandy CoCo3 24*80 OS9 Level II:\
+	:am:bs:\
+	:co#80:it#8:li#24:\
+	:al=^_0:bl=^G:cd=^K:ce=^D:cl=5*\014:cm=2\002%r%+ %+ :\
+	:dl=^_1:do=^J:ho=^A:kd=^J:kl=^H:kr=^I:ku=^L:le=^H:mb=^_":\
+	:md=\E\072^A:me=\037\041\E\072\0:mr=^_ :nd=^F:se=^_\041:\
+	:so=^_ :ue=^_#:up=^I:us=^_":ve=^E\041:vi=^E :
+# (trs2: removed obsolete ":nl=^_:" -- esr)
+trs2|trsII|trs80II|Radio Shack Model II using P&T CP/M:\
+	:am:bs:ms:\
+	:co#80:it#8:li#24:\
+	:al=^D:bl=^G:cd=^B:ce=^A:cl=^L:cm=\EY%+ %+ :cr=^M:dl=^K:\
+	:do=^_:ho=^F:kb=^H:kd=^_:kl=^\:kr=^]:ku=^^:le=^H:me=^O:nd=^]:\
+	:se=^O:sf=^J:so=^N:ta=^I:up=^^:
+# From: Kevin Braunsdorf <ksb@mentor.cc.purdue.edu>
+# (This had extension capabilities
+#	:BN=\E[?33h:BF=\E[?33l:UC=\E[_ q:BC=\E[\177 q:\
+#	:CN=\ERC:CF=\ERc:NR=\ERD:NM=\ER@:
+# I also deleted the unnecessary ":kn#2:", ":sg#0:" -- esr)
+trs16|trs-80 model 16 console:\
+	:am:bs:\
+	:co#80:it#8:li#24:\
+	:ac=jak`l_mbquvewcxs:ae=\ERg:al=\EL:as=\ERG:bl=^G:cd=\EJ:\
+	:ce=\EK:cl=^L:cm=\EY%+ %+ :cr=^M:dc=\EQ:dl=\EM:do=\EB:ei=:\
+	:ho=\EH:ic=\EP:im=:k0=^A:k1=^B:k2=^D:k3=^L:k4=^U:k5=^P:k6=^N:\
+	:k7=^S:kb=^H:kd=\EB:kh=^W:kl=\ED:kr=\EC:ku=\EA:l0=f1:l1=f2:\
+	:l2=f3:l3=f4:l4=f5:l5=f6:l6=f7:l7=f8:le=^H:me=\ER@:nd=\EC:\
+	:pf=\E]+:po=\E]=:se=\ER@:sf=^J:so=\ERD:ta=^I:up=\EA:ve=\ERC:\
+	:vi=\ERc:
+
+#### Atari ST
+#
+
+# From: Simson L. Garfinkel <simsong@media-lab.mit.edu>
+atari|atari st:\
+	:am:bs:\
+	:co#80:it#8:li#25:\
+	:al=\EL:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :dl=\EM:do=\EB:\
+	:kd=\EB:kl=\ED:kr=\EC:ku=\EA:le=\ED:me=\Eq:nd=\EC:se=\Eq:\
+	:so=\Ep:sr=\EI:ta=^I:up=\EA:
+# UniTerm terminal program for the Atari ST:  49-line VT220 emulation mode
+# From: Paul M. Aoki <aoki@ucbvax.berkeley.edu>
+uniterm|uniterm49|UniTerm VT220 emulator with 49 lines:\
+	:li#49:\
+	:is=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[1;49r\E[49;1H:tc=vt220:
+# MiNT VT52 emulation. 80 columns, 25 rows.
+# MiNT is Now TOS, the operating system which comes with all Ataris now
+# (mainly Atari Falcon). This termcap is for the VT52 emulation you get
+# under tcsh/zsh/bash/sh/ksh/ash/csh when you run MiNT in `console' mode
+# From: Per Persson <pp@gnu.ai.mit.edu>, 27 Feb 1996
+st52|Atari ST with VT52 emulation:\
+	:am:km:\
+	:co#80:li#25:\
+	:K1=\E#7:K2=\E#9:K3=\E#5:K4=\E#1:K5=\E#3:al=\EL:bl=^G:\
+	:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :cr=^M:dl=\EM:do=\EB:\
+	:ho=\EH:k0=\E#D:k1=\E#;:k2=\E#<:k3=\E#=:k4=\E#>:k5=\E#?:\
+	:k6=\E#@:k7=\E#A:k8=\E#B:k9=\E#C:kA=\E#R:kC=\E#7:kF=\E#2:\
+	:kR=\E#8:kb=^H:kd=\E#P:kh=\E#G:kl=\E#K:kr=\E#M:ku=\E#H:\
+	:l0=f10:le=\ED:me=\Eq:nd=\EC:nw=^M^J:r1=\Ez_\Eb@\EcA:\
+	:rc=\Ek:sc=\Ej:se=\Eq:sf=^J:so=\Ep:sr=\EI:ta=^I:te=:ti=\Ee:\
+	:up=\EA:ve=\Ee:vi=\Ef:
+ 
+#### Commodore Business Machines
+#
+# Formerly located in West Chester, PA; went spectacularly bust in 1994
+# after years of shaky engineering and egregious mismanagement.  Made one
+# really nice machine (the Amiga) and boatloads of nasty ones (PET, C-64,
+# C-128, VIC-20).  The C-64 is said to have been the most popular machine
+# ever (most units sold); they can still be found gathering dust in closets
+# everywhere.
+#
+
+# From: Kent Polk <kent@swrinde.nde.swri.edu>, 30 May 90
+# Added a few more entries, converted caret-type control sequence (^x) entries
+# to '\0xx' entries since a couple of people mentioned losing '^x' sequences.
+# Corrections by Ty Sarna <tsarna@endicor.com>, Sat Feb 28 18:55:15 1998
+#
+# :as:, :ae:			Support for alternate character sets.
+# :ve=\E[\040p:vi=\E[\060\040p:	cursor visible/invisible.
+# :xn:  vt100 kludginess at column 80/NEWLINE ignore after 80 cols(Concept)
+#     This one appears to fix a problem I always had with a line ending
+#     at 'width+1' (I think) followed by a blank line in vi. The blank
+#     line tended to disappear and reappear depending on how the screen
+#     was refreshed. Note that this is probably needed only if you use
+#     something like a Dnet Fterm with the window sized to some peculiar
+#     dimension larger than 80 columns.
+# :k0=\E9~:	map F10 to k0 - could have F0-9 -> k0-9, but ... F10 was 'k;'
+# (amiga: removed obsolete :kn#10:,
+# also added empty <acsc> to suppress a warning --esr)
+amiga|Amiga ANSI:\
+	:am:bs:bw:xn:\
+	:co#80:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:SF=\E[%dS:SR=\E[%dT:UP=\E[%dA:ac=:\
+	:ae=^O:al=\E[L:as=^N:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[J:cm=\E[%i%d;%dH:dc=\E[P:dl=\E[M:do=\E[B:ei=:\
+	:ho=\E[H:ic=\E[@:im=:is=\E[20l:k0=\E[9~:k1=\E[0~:k2=\E[1~:\
+	:k3=\E[2~:k4=\E[3~:k5=\E[4~:k6=\E[5~:k7=\E[6~:k8=\E[7~:\
+	:k9=\E[8~:kb=^H:kd=\E[B:kl=\E[D:kr=\E[C:ku=\E[A:le=\E[D:\
+	:mb=\E[7;2m:md=\E[1m:me=\E[m:mh=\E[2m:mk=\E[8m:mr=\E[7m:\
+	:nd=\E[C:r1=\Ec:se=\E[m:sf=\E[S:so=\E[7m:sr=\E[T:ue=\E[m:\
+	:up=\E[A:us=\E[4m:ve=\E[ p:vi=\E[0 p:
+
+# From: Hans Verkuil <hans@wyst.hobby.nl>, 4 Dec 1995
+# (amiga: added empty <acsc> to suppress a warning.
+# I'm told this entry screws up badly with AS225, the Amiga
+# TCP/IP package once from Commodore, and now sold by InterWorks.--esr)
+amiga-h|Hans Verkuil's Amiga ANSI:\
+	:bs:bw:ms:\
+	:co#80:li#24:\
+	:DC=\233%dP:DO=\233%dB:IC=\233%d@:LE=\233%dD:RI=\233%dC:\
+	:SF=\233%dS:SR=\233%dT:UP=\233%dA:ac=:ae=^O:as=^N:bl=^G:\
+	:bt=\233Z:cd=\233J:ce=\233K:cl=\233H\233J:\
+	:cm=\233%i%d;%dH:cr=^M:dc=\233P:do=\233B:ec=\233%dP:ei=:\
+	:ho=\233H:ic=\233@:im=:is=\23320l:k0=\2339~:k1=\2330~:\
+	:k2=\2331~:k3=\2332~:k4=\2333~:k5=\2334~:k6=\2335~:\
+	:k7=\2336~:k8=\2337~:k9=\2338~:kD=\177:kb=^H:kd=\233B:\
+	:kl=\233D:kr=\233C:ku=\233A:le=\233D:mb=\2337;2m:\
+	:md=\2331m:me=\2330m:mh=\2332m:mk=\2338m:mr=\2337m:\
+	:nd=\233C:nw=\233B\r:r1=\Ec:se=\2330m:sf=\233S:so=\2337m:\
+	:sr=\233T:ta=^I:te=\233?7h:ti=\233?7l:ue=\2330m:up=\233A:\
+	:us=\2334m:vb=^G:ve=\233 p:vi=\2330 p:
+
+# From: Henning 'Faroul' Peters <Faroul@beyond.kn-bremen.de>, 25 Sep 1999
+amiga-8bit|Amiga ANSI using 8-bit controls:\
+	:AL=\233%dL:DL=\233%dM:SF@:SR@:ac=:al=\233L:dl=\233M:\
+	:sf=\204:sr=\215:\
+	:tc=amiga-h:
+
+# Commodore B-128 microcomputer from Doug Tyrol <det@HEL-ACE.ARPA>
+# 	I'm trying to write a termcap for a commodore b-128, and I'm
+# having a little trouble. I've had to map most of my control characters
+# to something that unix will accept (my delete-char is a ctrl-t, etc),
+# and create some functions (like cm), but thats life.
+# 	The problem is with the arrow keys - right, and up work fine, but
+# left deletes the previous character and down I just can't figure out.
+# Jove knows what I want, but I don't know what it's sending to me (it
+# isn't thats bound to next-line in jove).
+# 	Anybody got any ideas? Here's my termcap.
+# DAG -- I changed his "^n" entries to "\n"; see if that works.
+#
+commodore|b-128|Commodore B-128 micro:\
+	:am:bw:\
+	:co#80:dN#20:li#24:pb#150:\
+	:al=10\Ei:bc=^H:ce=10\Eq:cl=10\E\006:\
+	:cm=20\E\013%2\054%2\054:cr=^M:dc=10*\177:dl=10*\Ed:\
+	:do=^J:ei=:ho=\E^E:ic=5\E\n:im=:kd=^J:kh=\E^E:kl=^B:kr=^F:\
+	:ku=^P:nd=^F:nl=^M:ta=5\011:up=^P:
+
+#### North Star
+#
+# North Star Advantage from Lt. Fickie <brl-ibd!fickie> via BRL
+northstar|North Star Advantage:\
+	:bs:\
+	:co#80:li#24:\
+	:cd=200\017:ce=200\016:cl=200\004:cm=1\E=%+ %+ :\
+	:ho=200\034\032:
+
+#### Osborne
+#
+# Thu Jul  7 03:55:16 1983
+#	
+# As an aside, be careful; it may sound like an anomaly on the 
+# Osborne, but with the 80-column upgrade, it's too easy to 
+# enter lines >80 columns!
+#	
+# I've already had several comments...
+# The Osborne-1 with the 80-col option is capable of being 
+# 52, 80, or 104 characters wide; default to 80 for compatibility 
+# with most systems.
+#	
+# The tab is destructive on the Ozzie; make sure to 'stty -tabs'.
+osborne-w|osborne1-w|osborne I in 104-column mode:\
+	:ms:ul:xt:\
+	:co#104:li#24:\
+	:al=\EE:bl=^G:ce=\ET:cl=^Z:cm=\E=%+ %+ :cr=^M:dc=\EW:dl=\ER:\
+	:do=^J:ei=:ic=\EQ:im=:kd=^J:kl=^H:kr=^L:ku=^K:le=^H:nd=^L:\
+	:se=\E(:sf=^J:so=\E):ue=\Em:up=^K:us=\El:
+# Osborne I	from ptsfa!rhc (Robert Cohen) via BRL
+osborne|osborne1|osborne I in 80-column mode:\
+	:am:bs:mi:ms:ul:xs:\
+	:co#80:dB#4:li#24:\
+	:al=\EE:ce=\ET:cl=^Z:cm=\E=%+ %+ :dc=4\EW:dl=\ER:do=^J:ei=:\
+	:im=\EQ:is=^Z:kb=^H:kd=^J:kl=^H:kr=^L:ku=^K:le=\010:nd=^L:\
+	:se=\E):so=\E(:ue=\Em:up=^K:us=\El:
+#
+# Osborne Executive definition from BRL
+# Similar to tvi920
+# Added by David Milligan and Tom Smith (SMU)
+osexec|Osborne executive:\
+	:am:bs:\
+	:co#80:li#24:sg#1:\
+	:al=\EE:bl=^G:cd=\EY:ce=\ET:cl=^Z:cm=\E=%+ %+ :cr=^M:ct=\E3:\
+	:dc=\EW:dl=\ER:do=^J:ei=:ho=^^:ic=\EQ:im=:\
+	:is=\Eq\Ek\Em\EA\Ex0:k0=^A@\r:k1=^AA\r:k2=^AB\r:k3=^AC\r:\
+	:k4=^AD\r:k5=^AE\r:k6=^AF\r:k7=^AG\r:k8=^AH\r:k9=^AI\r:\
+	:kb=^H:kd=^J:kl=^H:kr=^L:ku=^K:le=^H:nd=^L:nl=^J:se=\Ek:\
+	:so=\Ej:st=\E1:ue=\Em:up=^K:us=\El:
+
+#### Console types for obsolete UNIX clones
+#
+# Coherent, Minix, Venix, and several lesser-known kin were OSs for 8088
+# machines that tried to emulate the UNIX look'n'feel.  Coherent and Venix
+# were commercial, Minix an educational tool sold in conjunction with a book.
+# Memory-segmentation limits and a strong tendency to look like V7 long after
+# it was obsolete made all three pretty lame.  Venix croaked early.  Coherent
+# and Minix were ported to 32-bit Intel boxes, only to be run over by a
+# steamroller named `Linux' (which, to be fair, traces some lineage to Minix). 
+# Coherent's vendor, the Mark Williams Company, went belly-up in 1994.  There
+# are also, I'm told, Minix ports that ran on Amiga and Atari machines and
+# even as single processes under SunOS and the Macintosh OS.
+#
+
+# This is the entry provided with minix 1.7.4, with bogus :ri: removed.
+minix|minix console (v1.7):\
+	:am:xn:\
+	:co#80:it#8:li#25:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:al=\E[L:bl=^G:cd=\E[0J:\
+	:ce=\E[K:cl=\E[H\E[0J:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:\
+	:dl=\E[M:do=\E[B:ei=:ho=\E[H:ic=\E[@:im=:is=\E[0m:k0=\E[Y:\
+	:k1=\E[V:k2=\E[U:k3=\E[T:k4=\E[S:k5=\E[G:kb=^H:kd=\E[B:\
+	:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:l0=End:l1=PgUp:l2=PgDn:\
+	:l3=Num +:l4=Num -:l5=Num 5:le=^H:mb=\E[5m:md=\E[1m:\
+	:me=\E[0m:mr=\E[7m:nd=\E[C:nw=^M^J:se=\E[0m:sf=^J:so=\E[7m:\
+	:sr=\EM:ta=^I:ue=\E[0m:up=\E[A:us=\E[4m:
+# Corrected Jan 14, 1997 by Vincent Broman <broman@nosc.mil>
+minix-old|minix console (v1.5):\
+	:xo:\
+	:co#80:it#8:li#25:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:al=\E[L:bl=^G:cd=\E[0J:\
+	:ce=\E[K:cl=\E[H\E[0J:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:\
+	:dl=\E[M:do=\E[B:ei=:ho=\E[H:ic=\E[@:im=:k0=\E[Y:k1=\E[V:\
+	:k2=\E[U:k3=\E[T:k4=\E[S:k5=\E[G:kb=^H:kd=\E[B:kh=\E[H:\
+	:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mb=\E[5m:md=\E[1m:me=\E[0m:\
+	:mr=\E[7m:nd=\E[C:nw=^M^J:se=\E[0m:sf=^J:so=\E[7m:sr=\EM:\
+	:ta=^I:ue=\E[0m:up=\E[A:us=\E[4m:
+# The linewrap option can be specified by editing /usr/include/minix/config.h
+# before recompiling the minix 1.5 kernel.
+minix-old-am|minix console with linewrap:\
+	:am:tc=minix-old:
+
+pc-minix|minix console on an Intel box:\
+	:tc=klone+acs:tc=minix:
+
+# According to the Coherent 2.3 manual, the PC console is similar
+# to a z19. The differences seem to be (1) 25 lines, (2) no status
+# line, (3) standout is broken, (4) ins/del line is broken, (5)
+# has blinking and bold.
+pc-coherent|pcz19|coherent|IBM PC console running Coherent:\
+	:am:mi:\
+	:co#80:it#8:li#25:\
+	:bl=^G:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :cr=^M:dc=\EN:\
+	:do=\EB:ei=\EO:ho=\EH:im=\E@:kb=^H:kd=\EB:kh=\EH:kl=\ED:\
+	:kr=\EC:ku=\EA:le=^H:me=\Eq:nd=\EC:se=\Eq:sf=^J:so=\Ep:\
+	:sr=\EI:ta=^I:up=\EA:
+
+# According to the Venix 1.1 manual, the PC console is similar
+# to a DEC vt52.  Differences seem to be (1) arrow keys send 
+# different strings, (2) enhanced standout, (3) added insert/delete line.
+# Note in particular that it doesn't have automatic margins.
+# There are other keys (f1-f10, kpp, knp, kcbt, kich1, kdch1) but they
+# not described here because this derives from an old termcap entry.
+pc-venix|venix|IBM PC console running Venix:\
+	:co#80:it#8:li#25:\
+	:al=\EL:bl=^G:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :cr=^M:\
+	:dl=\EM:do=^J:kb=^H:kd=\EP:kh=\EG:kl=\EK:kr=\EM:ku=\EH:le=^H:\
+	:nd=\EC:sf=^J:sr=\EI:ta=^I:up=\EA:
+
+#### Miscellaneous microcomputer consoles
+#
+# If you know anything more about any of these, please tell me.
+#
+
+# The MAI Basic Four computer was obsolete at the end of the 1980s.
+# It may be used as a terminal by putting it in "line" mode as seen on 
+# one of the status lines.
+# Initialization is similar to CIT80. :is: will set ANSI mode for you.  
+# Hardware tabs set by :if: at 8-spacing.  Auto line wrap causes glitches so
+# wrap mode is reset by :vs:.  Using :sf:=\E[S caused errors so I 
+# used \ED instead.
+# From: bf347@lafn.org (David Lawyer), 28 Jun 1997
+mai|basic4|MAI Basic Four in ansi mode:\
+	:am:da:db:mi:ms:\
+	:co#82:it#8:li#25:\
+	:al=\E[L:bl=^G:cd=^_:ce=^^:cl=^]^_:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:dc=\E[1P:dl=\E[M:do=^J:ei=\E[4l:ho=^]:\
+	:if=/usr/lib/tabset/vt100:im=\E[4h:\
+	:is=\E>\E[?1h\E[?7h\E[?5l\017\E(B\E[m\E[20l\E[1;24r\E[24;1H:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\EOT:k6=\EOU:k7=\EOV:\
+	:k8=\EOW:kb=^H:kd=\EOB:kl=\EOD:kr=\EOC:ku=\EOA:le=^H:\
+	:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=^X:nw=^M\ED:rc=\E8:\
+	:sc=\E7:se=\E[m:sf=\ED:so=\E[7m:sr=\E[T:ta=^I:ue=\E[m:up=^Z:\
+	:us=\E[4m:ve=\E[?7h:vs=\E[?7l:
+# basis from Peter Harrison, Computer Graphics Lab, San Francisco
+#   ucbvax!ucsfmis!harrison ...uucp / ucbvax!ucsfmis!harrison@BERKELEY ...ARPA
+#
+# On Sat, 7 Aug 1999, Torsten Jerzembeck <toje@nightingale.ms.sub.org> wrote:
+# The Basis 108 was a Apple II clone, manufactured by the "Basis
+# Mikrocomputer GmbH" in Munster, Germany (the company still exists today,  
+# about 1,5 km from where I live, but doesn't build own computers any
+# more). A Basis 108 featured a really heavy (cast aluminium?) case, was
+# equipped with one or two 5.25" disk drives, had a monochrome and colour
+# video output for a TV set or a dedicated monitor and several slots for
+# Apple II cards. Basis 108 were quite popular at german schools before
+# the advent of the IBM PC. They run, for example, the UCSD Pascal
+# development system (which I used even in 1993 to program the steering
+# and data recording for our school's experimental solar panel :), Apple DOS
+# or CP/M.
+# (basis: removed obsolete ":ma=^K^P^R^L^L :nl=5000*^J:" -- esr)
+basis|BASIS108 computer with terminal translation table active:\
+	:cd=\EY:ce=\ET:cl=300\E*:do=5000\n:kb=^H:kd=^J:kl=^H:kr=^L:\
+	:ku=^K:me=\E):se=\E):so=\E(:\
+	:tc=adm3a:
+# luna's BMC terminal emulator
+luna|luna68k|LUNA68K Bitmap console:\
+	:co#88:li#46:tc=ansi-mini:
+megatek|pegasus workstation terminal emulator:\
+	:am:os:\
+	:co#83:li#60:
+# The Xerox 820 was a Z80 micro with a snazzy XEROX PARC-derived 
+# interface (pre-Macintosh by several years) that went nowhere.
+xerox820|x820|Xerox 820:\
+	:am:\
+	:co#80:li#24:\
+	:bl=^G:cd=^Q:ce=^X:cl=1^Z:cm=\E=%+ %+ :cr=^M:do=^J:ho=^^:\
+	:le=^H:nd=^L:sf=^J:up=^K:
+
+#### Videotex and teletext
+#
+
+# From: Alexandre Montaron <canal@mygale.org>, 18 Jun 1998
+#
+minitel1|minitel 1:\
+	:am:bw:es:hs:hz:ms:\
+	:Co#8:co#40:li#24:pa#8:\
+	:..Sf=\E%?%p1%{1}%=%tD%e%p1%{3}%=%tF%e%p1%{4}%=%tA%e%p1%{6}%=%tC%e%p1%{64}%+%c%;:\
+	:ac=+.\054\054./f0g1:bl=^G:ce=^X:cl=^L:cm=\037%+A%+A:\
+	:cr=^M:do=^J:eA=^Y:fs=^J:ho=^^:\
+	:is=\E;`ZQ\E\072iC\E\072iE\021:le=^H:mb=\EH:me=\EI\E\:\
+	:mr=\E]:nd=^I:nw=^M^J:op=\EG:rp=%.\022%+?:\
+	:..sa=%?%p1%t\E]%;%?%p3%t\E]%;%?%p4%t\EH%;:se=\E\:\
+	:sf=^J:so=\E]:sr=^K:ts=\037@%p1%{65}%+%c:up=^K:ve=^Q:vi=^T:
+# is2=Fnct TE, Fnct MR, Fnct CM et pour finir: curseur ON.
+minitel1b|minitel 1-bistandard (in 40cols mode):\
+	:mi:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:al=\E[L:cb=\E[1K:cd=\E[J:dc=\E[P:\
+	:dl=\E[M:ei=\E[4l:i1=\E;iYA\E;jYC:im=\E[4h:kA=\E[L:\
+	:kC=\E[2J:kD=\E[P:kE=^X:kI=\E[4h:kL=\E[M:kd=\E[B:kh=\E[H:\
+	:kl=\E[D:kr=\E[C:ks=\E;iYA\E;jYC:kt=^I:ku=\E[A:\
+	:tc=minitel1:
+# :ke: posait des problemes (logout en sortant de vi).
+minitel1b-80|minitel 1-bistandard (standard teleinformatique):\
+	:am@:bw@:hz@:\
+	:Co@:co#80:it#8:pa@:\
+	:@8=\EOM:Sf@:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:ho=\E[H:\
+	:i1@:is@:k0=\EOp:k1=\EOq:k2=\EOr:k3=\EOs:k4=\EOt:k5=\EOu:\
+	:k6=\EOv:k7=\EOw:k8=\EOx:k9=\EOy:ke@:ks@:mb=\E[5m:md=\E[1m:\
+	:me=\E[m:mr=\E[7m:nd=\E[C:nw=\EE:op@:rc=\E8:rp@:\
+	:..sa=\E[%?%p1%t7;%;%?%p2%t4;%;%?%p3%t7;%;%?%p4%t5;%;%?%p6%t1;%;m:\
+	:sc=\E7:se=\E[27m:sf=\ED:so=\E[7m:sr=\EM:ta=^I:ue=\E[24m:\
+	:up=\E[A:us=\E[4m:ve=\037@A\021\n:vi=\037@A\024\n:\
+	:tc=minitel1b:
+# \E\:1}	switch to te'le'informatique mode (ascii terminal/ISO 6429)
+# \E[?3l	80 columns
+# \E[?4l	scrolling on
+# \E[12h	local echo off
+# \Ec		reset: G0 U.S. charset (to get #,@,{,},...), 80 cols, clear screen
+# \E)0		G1 DEC set (line graphics)
+#
+# From: Igor Tamitegama <igor@ppp1493-ft.teaser.fr>, 18 Jan 1997
+m2-nam|minitel|minitel-2|minitel-2-nam|France Telecom Minitel 2 mode te'le'informatique:\
+	:bs:es:hs:xn:\
+	:co#80:it#8:li#24:sg#0:ws#72:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:LE=\E[%dD:\
+	:RI=\E[%dC:SF=^J:SR=\EM:UP=\E[%dA:\
+	:ac=aaffggjjkkllmmnnooqqssttuuvvwwxx:ae=^O:al=\E[L:\
+	:as=^N:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:\
+	:cr=^M:cs=\E[%i%d;%dr:dc=\E[P:dl=\E[M:do=\E[B:ei=\E[4l:\
+	:fs=^J:ho=\E[H:i1=\E\0721}\Ec\E[?4l\E[12h:\
+	:i2=\E[?3l kbs=\010:im=\E[4h:ip=7:is=\Ec\E[12h\E)0:\
+	:k0=\EOp:k1=\EOq:k2=\EOr:k3=\EOs:k4=\EOt:k5=\EOu:k6=\EOv:\
+	:k7=\EOw:k8=\EOx:k9=\EOy:k;=\EOp:kA=\E[4l:kC=\E[2J:kD=\E[P:\
+	:kI=\E[4h:kL=\E[M:kN=\EOn:kP=\EOR:kd=\E[B:kh=\E[H:kl=\E[D:\
+	:kr=\E[C:ku=\E[A:le=\E[D:ll=\E[24;80H:mb=\E[5m:md=\E[1m:\
+	:me=\E[m:mr=\E[7m:nd=\E[C:nw=^M^J:ps=\E[i:\
+	:r1=\Ec\E[?4l\E[12h:r2=\Ec\E)0:rc=\E8:sc=\E7:se=\E[27m:\
+	:sf=^J:so=\E[7m:sr=\EM:ta=^I:ts=^_@A:u6=\E[%i%d;%dR:\
+	:u7=\E[6n:ue=\E[24m:up=\E[A:us=\E[4m:vb=^G:ve=\E[<1l:\
+	:vi=\E[<1h:
+
+######## OBSOLETE VDT TYPES
+#
+# These terminals are *long* dead -- these entries are retained for
+# historical interest only.
+
+#### Amtek Business Machines
+#
+
+# (abm80: early versions of this entry apparently had ":se=\E^_:so=\E^Y",
+# but these caps were commented out in 8.3; also, removed overridden
+# ":do=^J:" -- esr)
+abm80|amtek business machines 80:\
+	:am:bs:bw:\
+	:co#80:li#24:\
+	:al=\E^Z:bt=^T:cd=\E^X:ce=\E^O:cl=\E^\:cm=\E\021%r%+ %+ :\
+	:dl=\E^S:do=\E^K:ho=\E^R:le=^H:nd=^P:up=\E^L:
+
+#### Bell Labs blit terminals
+#
+# These were AT&T's official entries.  The 5620 FAQ maintained by 
+# David Breneman <daveb@dgtl.com> has this to say:
+#
+#  Actually, in the beginning was the Jerq, and the Jerq was white with a
+#  green face, and Locanthi and Pike looked upon the Jerq and said the Jerq
+#  was good.  But lo, upon the horizon loomed a mighty management-type person
+#  (known now only by the initials VP) who said, the mighty Jerq must stay
+#  alone, and could not go forth into the world. So Locanthi and Pike put the
+#  Jerq to sleep, cloned its parts, and the Blit was brought forth unto the
+#  world. And the Jerq lived the rest of its days in research, but never
+#  strayed from those paths.
+#
+#  In all seriousness, the Blit was originally known as the Jerq, but when
+#  it started to be shown outside of the halls of the Bell Labs Research
+#  organization, the management powers that be decided that the name could
+#  not remain. So it was renamed to be Blit. This was in late 1981.
+#
+# (The AT&T 5620 was the commercialized Blit.  Its successors were the 630,
+# 730, and 730+.)
+#
+
+blit|jerq|blit running teletype rom:\
+	:am:eo:ul:xo:\
+	:co#87:it#8:li#72:\
+	:AL=\EF%+ :DC=\Ee%+ :DL=\EE%+ :IC=\Ef%+ :al=\EF\041:bl=^G:\
+	:ce=\EK:cl=^L:cm=\EY%r%+ %+ :cr=^M:dc=\Ee\041:dl=\EE\041:\
+	:do=^J:ei=:ic=\Ef\041:im=:k1=\Ex:k2=\Ey:k3=\Ez:kb=^H:kd=\EB:\
+	:kl=\ED:kr=\EC:ku=\EA:le=\ED:nd=\EC:sf=^J:ta=^I:up=\EA:
+
+# (cbblit: here's a BSD termcap that says :do=\EG: -- esr)
+cbblit|fixterm|blit running columbus code:\
+	:co#88:\
+	:cd=\EJ:ei=\ER:ic@:im=\EQ:pO=\EP%03:pf=^T:po=^R:se=\EV\041:\
+	:so=\EU\041:ue=\EV":us=\EU":vb=\E^G:\
+	:tc=blit:
+
+oblit|ojerq|first version of blit rom:\
+	:am:da:db:eo:mi:ul:xo:\
+	:co#88:it#8:li#72:\
+	:AL=\Ef%+ :DL=\Ee%+ :al=\EF:bl=^G:cd=\EJ:ce=\EK:cl=^L:\
+	:cm=\EY%r%+ %+ :cr=^M:dc=\EO:dl=\EE:do=^J:ei=\ER:im=\EQ:\
+	:kb=^H:le=\ED:nd=\EC:sf=^J:ta=^I:up=\EA:vb=\E^G:
+
+#### Bolt, Beranek & Newman (bbn)
+#
+# The BitGraph was a product of the now-defunct BBN Computer Corporation.
+# The parent company, best known as the architects of the Internet, is
+# still around.
+#
+# Jeff DelPapa <dp@world.std.com> writes:
+# The bitgraph was a large white box that contained a monochrome bitmap
+# display, and a 68000 to run it.  You could download code and run it on
+# the cpu, it had 128kb (I think) of memory.  I used one in the late
+# 70's, sure beat a vt100.  It had one strange feature tho -- it used
+# the cpu to bitblt pixels to scroll, it took longer than the refresh
+# rate, and looked like a rubber sheet stretching, then snapping
+# upwards.  It had everything the early mac had, except a floppy drive a
+# small screen (it had a 17" crisp beauty) and a real OS. They (Bolt
+# Beranek and Neuman) sold at most a few hundred of them to the real
+# world.  DOD may have bought more...
+# 
+
+# Entries for the BitGraph terminals.  The problem 
+# with scrolling in vi can only be fixed by getting BBN to put 
+# smarter scroll logic in the terminal or changing vi or padding 
+# scrolls with about 500 ms delay.
+#	
+# I always thought the problem was related to the terminal 
+# counting newlines in its input buffer before scrolling and 
+# then moving the screen that much. Then vi comes along and 
+# paints lines in on the bottom line of the screen, so you get 
+# this big white gap.
+
+bitgraph|bg2.0nv|bg3.10nv|bbn bitgraph 2.0 or later (normal video):\
+	:is=\E>\E[?5l\E[?7h:vb=\E[?5h\E[?5l:\
+	:tc=bg2.0:
+bg2.0rv|bg3.10rv|bbn bitgraph 2.0 (reverse video):\
+	:is=\E>\E[?5h\E[?7h:vb=\E[?5l\E[?5h:tc=bg2.0:
+bg2.0|bg3.10|bbn bitgraph 2.0 or later (no init):\
+	:bs:xn:\
+	:co#85:li#64:\
+	:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=%i\E[%d;%dH:\
+	:cr=^M:cs=\E[%i%d;%dr:dl=\E[M:do=\E[B:k1=\EOP:k2=\EOQ:\
+	:k3=\EOR:k4=\EOS:kd=\E[B:ke=\E>:kl=\E[D:kr=\E[C:ks=\E=:\
+	:ku=\E[A:l1=PF1:l2=PF2:l3=PF3:l4=PF4:le=^H:me=\E[m:nd=\E[C:\
+	:rc=\E8:sc=\E7:se=\E[m:sf=\n:so=\E[7m:ta=^I:up=\E[A:
+
+bg1.25rv|bbn bitgraph 1.25 (reverse video):\
+	:is=\E>\E[?5h\E[?7h:vb=\E[?5l\E[?5h:tc=bg1.25:
+bg1.25nv|bbn bitgraph 1.25 (normal video):\
+	:is=\E>\E[?5l\E[?7h:vb=\E[?5h\E[?5l:tc=bg1.25:
+# (bg1.25: I added <rmam>/<smam> based on the init string -- esr)
+bg1.25|bbn bitgraph 1.25:\
+	:co#85:li#64:\
+	:RA=\E[?7l:SA=\E[?7h:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[J:cm=%i\E[%d;%dH:cr=^M:dl=\E[M:do=\E[B:k1=\EP:\
+	:k2=\EQ:k3=\ER:k4=\ES:kd=\EB:ke=\E>:kl=\ED:kr=\EC:ks=\E=:\
+	:ku=\EA:l1=PF1:l2=PF2:l3=PF3:l4=PF4:le=^H:ll=\E[64;1H:\
+	:me=\E[m:nd=\E[C:se=\E[m:sf=\n:so=\E[7m:ta=^I:up=\E[A:
+
+#### Bull (bq, dku, vip)
+#
+# (Adapted for terminfo; AIX extension capabilities translated -- esr)
+
+#============================================#
+# BULL QUESTAR 210 `SDP' terminals emulation #
+#============================================#
+#
+# Description written by R.K.Saunders (Bull Transac)
+#
+# Modifications written by F. Girard (Bull MTS)
+#		19-05-87 V02.00.01
+#		17-12-87 V02.00.02
+#		15-09-89 V02.00.05
+#
+#	Typical technical selections F1 (modes SDP/ROLL):
+# -------------------------------------------------------
+# |   01   02   03   04   05   06   07   08   09   10   |
+# |  1010 0011 1010 0110 0110 0001 0100 0000 0000 0000  |
+# |                                                     |
+# |   11   12   13   14   15   16   17   18   19   20   |
+# |  0000 0110 100? 0000 0000 0000 0001 0000 0000 0001  |
+# |                                                     |
+# |   21   22   23   24   25   26   27   28   29   30   |
+# |  0011 0000 0001 1000 0000 0000 0000 0000 0000 0000  |
+# |                                                     |
+# |   31   32   33   34   35   36   37   38   39   40   |
+# |  1010 0011 0000 0000 0000 0000 0000 0000 0000 0000  |
+# -------------------------------------------------------
+#	Typical firmware identification F5 "etat 6":
+#  P287.02.04b	(AZERTY)
+#  P297.11.04	(24-pin: 2732)	or P798.11.04	(28-pin: 2764)
+#  P298.03.03	(monochrome)	or P374.03.02	(colour)
+#
+#	SM SDP mode (VIP command):	^[[?=h
+#	RIS (erases screen):		^[c
+#	DMI disable keyboard:		^[`
+#	SM double rendition mode:	^[[?>h
+#	RM solicited status mode:	^[[5l
+#	RM character mode:		^[[>l
+#	RM echoplex mode:		^[[12l
+#	RM column tab mode:		^[[18l
+#	RM forbid SS2 keyboard mode:	^[[?<l
+#	SM scroll mode:			^[[=h
+#	FCF enable XON/XOFF:		^[P1s^[\
+#	MTL select end msg character:	^[[^Wp
+#	EMI enable keyboard:		^[b
+#	RIS retour etat initial:	^[c
+#	enable FC keypad:		^[[?<h,
+#	MPW map status line window:	^[PY99:98^[\
+#	SCP select status line:		^[[0;98v
+#	ED erase entire partition:	^[[2J
+#	SCP select main partition:	^[[v
+#	SM character insertion mode:	^[[4h
+#	RM character replacement mode:	^[[4l
+#	COO cursor on:			^[[r
+#	COO cursor off:			^[[1r
+#	SGR dim (turquoise) rev attr:	^[[2;7m
+#	SGR Data normal attr:		^[[m
+#	SO Line-graphic mode ON:	^N
+#	SI Line-graphic mode OFF:	^O
+#	MC start routing to printer:	^[[5i
+#	MC stop routing to printer:	^M^[[4i
+#
+
+# This entry covers the following terminals:
+# dku7102, tws2102, and tws models 2105 to 2112
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+tws-generic|dku7102|Bull Questar tws terminals:\
+	:am:es:hs:mi:ms:xn:xo:xs@:\
+	:co#80:it#8:li#24:ws#80:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:bt=\E[Z:\
+	:cd=\E[J:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%df:cr=^M:ct=\E[2g:\
+	:dc=\E[P:dl=\E[M:do=^J:\
+	:ds=\EPY99\07298\E\\E[0;98v\E[2J\E[v:ei=\E[4l:fs=\E[v:\
+	:ho=\E[H:i1=\E[?=h\Ec\E`\E[?>h\EPY99\07298\E\:\
+	:i2=\Eb\E[?<h:im=\E[4h:\
+	:is=\E[5;>;12;18;?<l\E[=h\EP1s\E\\E[\027p:\
+	:k1=\E[1u\027:k2=\E[2u\027:k3=\E[3u\027:k4=\E[4u\027:\
+	:k5=\E[5u\027:k6=\E[6u\027:k7=\E[7u\027:k8=\E[8u\027:\
+	:kD=\E[P:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:le=^H:ll=\E[H\E[A:mb=\E[0;5m:me=\E[m\017:mh=\E[0;2m:\
+	:mr=\E[0;7m:nd=\E[C:se=\E[m:sf=^J:so=\E[0;7m:st=\EH:\
+	:ta=\E[I:te=\E[0;98v\E[2J\E[v:ti=\E[?>h\EPY99\07298\E\:\
+	:ts=\EPY99\07298\E\\E[0;98v\E[2;7m:ue=\E[m:up=\E[A:\
+	:us=\E[0;4m:ve=\E[r:vi=\E[1r:
+tws2102-sna|dku7102-sna|BULL Questar tws2102 for SNA:\
+	:ds=\E[0;98v\E[2J\E[v:fs=\E[v:i2=\Eb:ts=\E[0;98v:\
+	:tc=tws-generic:
+tws2103|xdku|BULL Questar tws2103:\
+	:ta=^I:tc=tws-generic:
+tws2103-sna|dku7103-sna|BULL Questar tws2103 for SNA:\
+	:ta=^I:\
+	:tc=tws2102-sna:
+dku7102-old|BULL Questar 200 DKU7102 (microcode version < 6):\
+	:AL@:DL@:al@:ce=\E[K\E[m:cl=\E[2J\E[H:cm@:dl@:\
+	:ds=\EPY99\07298\E\\E[0;98v\E[2J\E[H\E[v:\
+	:ts=\EPY99\07298\E\\E[0;98v\E[H\E[2;7m:\
+	:tc=tws-generic:
+dku7202|BULL Questar 200 DKU7202 (colour/character attributes):\
+	:i2=\E[?3h\Eb:mb=\E[0;2;4m:mh=\E[0;5m:so=\E[0;4;5;7m:\
+	:ta=^I:us=\E[0;2m:\
+	:tc=tws-generic:
+
+#=========================================================#
+# BULL QUESTAR 303 & 310 `DEC VT 320' terminals emulation #
+#=========================================================#
+#
+# Description written by J. Staerck (BULL SA)
+#       Copyright (c) 1989 BULL SA
+#---------------------------------------------------------------------------
+#  This entry is used for terminals with vt320 emulation mode
+#  and following set-up : 
+#    8 bit ISO Latin Character Set (ISO 8859-1),
+#    7 bit Control Characters, 
+#    80 columns screen.    
+#  Hereafter are some DEC vt terminals' commands. (valid on vt200 and 300)
+#  They are used in string capabilities with vt220-320 emulation mode.
+#  In the following DEC definitions, two kinds of terminfo databases are
+#    provided :
+#    1. the first with Command Sequence Introducer starting with escape 
+#       sequence in 7 bits characters ex. ESC [ : 2 chars. in 7-bit mode.
+#    2. the second with Command Sequence Introducer starting with escape 
+#       sequence in 8 bits characters ex. ESC [ : 1 char. 'CSI' =x9B.
+#	Soft Terminal Reset		esc [ ! p
+#	RIS (erases screen):		esc c
+#	DECKPNM numeric keypad mode:	esc >
+#	DECKPAM applic. keypad mode:	esc =
+#	DECSTBM Scrolling region:	esc [ r
+#	SCS select G0 = US:		esc ( B
+#	SCS select G1 = line-graphic:	esc ) 0
+#	Select 7-bit C1 controls:	esc sp F
+#	Select 8-bit C1 controls:	esc sp G
+#	Select cursor home:		esc [  H
+#	Select erase screen:		esc [  J
+#	SM KAM lock keyboard:		esc [ 2 h
+#	RM KAM unlock keyboard:		esc [ 2 l
+#	SM SRM local echo off:		esc [ 1 2 h
+#	RM SRM local echo on:		esc [ 1 2 l
+#	SM LNM New line :		esc [ 2 0 h
+#	RM LNM return = CR only:	esc [ 2 0 l
+#	SM DECCKM cursor keys mode:	esc [ ? 1 h
+#	RM DECCKM appli. keys mode:	esc [ ? 1 l
+#	SM DECANM ANSI mode on:		esc [ ? 2 h
+#	RM DECANM ANSI mode off:	esc [ ? 2 l
+#	SM DECCOLM 132-column screen:	esc [ ? 3 h
+#	RM DECCOLM 80-column screen:	esc [ ? 3 l
+#	SM DECSCLM Smooth scroll:	esc [ ? 4 h
+#	RM DECSCLM Jump scroll:		esc [ ? 4 l
+#	SM DECSCNM screen light backgr.	esc [ ? 5 h
+#	RM DECSCNM screen dark backgr.	esc [ ? 5 l
+#	SM DECOM move within margins:	esc [ ? 6 h
+#	RM DECOM move outside margins:	esc [ ? 6 l
+#	SM DECAWM auto right margin:	esc [ ? 7 h
+#	RM DECAWM auto right margin:	esc [ ? 7 l
+#	SM DECARM auto repeat:		esc [ ? 8 h
+#	RM DECARM auto repeat:		esc [ ? 8 l
+#	DECSASD Select active main:	esc [ 0 $ } 
+#	DECSASD Select active status:	esc [ 1 $ } 
+#	DECSSDT Select status none:	esc [ 0 $ ~ 
+#	DECSSDT Select status indic.:	esc [ 1 $ ~ 
+#	DECSSDT Select status host-wr:	esc [ 2 $ ~ 
+#	SM DECTCEM Visible cursor:	esc [ ? 2 5 h
+#	RM DECTCEM Invisible cursor:	esc [ ? 2 5 l
+#	SM DECNCRM 7 bits NCR set:	esc [ ? 4 2 h
+#	RM DECNCRM Multi or ISO latin:	esc [ ? 4 2 l
+#	SM DECNKM numeric keypad mode:	esc [ ? 6 6 h
+#	RM DECNKM numeric keypad appl.:	esc [ ? 6 6 l
+#	SM DECKBUM clavier informatique	esc [ ? 6 8 h
+#	RM DECKBUM clavier bureautique:	esc [ ? 6 8 l
+#	DECSCL vt300 mode 8-bit ctrl:	esc [ 6 3 " p
+# or	DECSCL vt300 mode 8-bit ctrl:	esc [ 6 3 ; 0 " p
+# or	DECSCL vt300 mode 8-bit ctrl:	esc [ 6 3 ; 2 " p
+#	DECSCL vt300 mode 7-bit ctrl:	esc [ 6 3 ; 1 " p
+#	Char. and Line attributes:	esc [ Ps ... Ps m
+# with:  0 All off, 1 Bold, 4 Underline, 5 Blinking, 7 Reverse
+# and : 22 Bold off, 24 Underline off, 25 Blinking off, 27 Reverse off
+#
+
+# This entry covers BQ303, BQ306, BQ310, Q303, Q306, Q310
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+bq300|Bull vt320 ISO Latin 1 80 columns terminal:\
+	:am:eo:es:hs:km:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:vt#3:ws#80:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:K1=\EOw:K2=\EOu:K3=\EOy:K4=\EOq:K5=\EOs:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:cd=\E[J:\
+	:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:ct=\E[3g:dc=\E[P:dl=\E[M:do=\E[B:\
+	:ds=\E[1$}\E[2$~\n\E[0$}:ec=\E[%dX:ei=\E[4l:fs=\E[0$}:\
+	:ho=\E[H:i1=\E[63;1"p\E[2h:\
+	:i2=\E[0$}\E[?25h\E[2l\E[H\E[J:im=\E[4h:\
+	:is=\E[?2h\E[?3l\E[?5l\E[?7h\E[?8h\E>\E[?1l\E F\E[?42l\E[?4l:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k6=\E[17~:k7=\E[18~:\
+	:k8=\E[19~:k9=\E[20~:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:\
+	:kb=^H:kd=\E[B:ke=\E[?1l\E>:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:le=\E[D:mb=\E[5m:md=\E[1m:me=\E[0m\E(B:mr=\E[7m:nd=\E[C:\
+	:nw=\EE:rc=\E8:sc=\E7:se=\E[27m:sf=\ED:so=\E[7m:sr=\EM:\
+	:st=\EH:ta=^I:te=\E[?7h:ti=\E[?7l\E[?1l\E(B:\
+	:ts=\E[1$}\E[2$~:ue=\E[24m:up=\E[A:us=\E[4m:\
+	:vb=\E[?5h\E[?5l:ve=\E[?25h:vi=\E[?25l:vs=\E[?25h:
+bg300-rv|Bull vt320 reverse 80 columns:\
+	:is=\E[?2h\E[?3l\E[?5h\E[?7h\E[?8h\E>\E[?1l\E F\E[?42l\E[?4l:\
+	:vb=\E[?5l\E[?5h:\
+	:tc=bq300:
+bq300-w|Bull vt320 132 columns:\
+	:co#132:ws#132:\
+	:is=\E[?2h\E[?3h\E[?5l\E[?7h\E[?8h\E>\E[?1l\E F\E[?42l\E[?4l:\
+	:r2=\E[?3h:\
+	:tc=bq300:
+bq300-w-rv|Bull vt320 reverse mode 132 columns:\
+	:co#132:ws#132:\
+	:is=\E[?2h\E[?3h\E[?5h\E[?7h\E[?8h\E>\E[?1l\E F\E[?42l\E[?4l:\
+	:r2=\E[?3h:vb=\E[?5l\E[?5h:\
+	:tc=bq300:
+
+#  This entry is used for terminals with vt320 emulation mode
+#  and following set-up : 
+#    8 bit ISO Latin Character Set (ISO 8859-1),
+#    8 bit Control Characters, (CSI coded as x9B for ESC [)
+#    80 columns screen.    
+#	Soft Terminal Reset		csi ! p
+#	RIS (erases screen):		esc c
+#	DECKPNM numeric keypad mode:	esc >
+#	DECKPAM applic. keypad mode:	esc =
+#	DECSTBM Scrolling region:	esc [ r
+#	SCS select G0 = US:		esc ( B
+#	SCS select G1 = line-graphic:	esc ) 0
+#	Select 7-bit C1 controls:	esc sp F
+#	Select 8-bit C1 controls:	esc sp G
+#	Select cursor home:		csi H
+#	Select erase screen:		csi J
+#	SM KAM lock keyboard:		csi 2 h
+#	RM KAM unlock keyboard:		csi 2 l
+#	SM SRM local echo off:		csi 1 2 h
+#	RM SRM local echo on:		csi 1 2 l
+#	SM LNM New line :		csi 2 0 h
+#	RM LNM return = CR only:	csi 2 0 l
+#	SM DECCKM cursor keys mode:	csi ? 1 h
+#	RM DECCKM appli. keys mode:	csi ? 1 l
+#	SM DECANM ANSI mode on:		csi ? 2 h
+#	RM DECANM ANSI mode off:	csi ? 2 l
+#	SM DECCOLM 132-column screen:	csi ? 3 h
+#	RM DECCOLM 80-column screen:	csi ? 3 l
+#	SM DECSCLM Smooth scroll:	csi ? 4 h
+#	RM DECSCLM Jump scroll:		csi ? 4 l
+#	SM DECSCNM screen light backgr.	csi ? 5 h
+#	RM DECSCNM screen dark backgr.	csi ? 5 l
+#	SM DECOM move within margins:	csi ? 6 h
+#	RM DECOM move outside margins:	csi ? 6 l
+#	SM DECAWM auto right margin:	csi ? 7 h
+#	RM DECAWM auto right margin:	csi ? 7 l
+#	SM DECARM auto repeat:		csi ? 8 h
+#	RM DECARM auto repeat:		csi ? 8 l
+#	DECSASD Select active main:	csi 0 $ } 
+#	DECSASD Select active status:	csi 1 $ } 
+#	DECSSDT Select status none:	csi 0 $ ~ 
+#	DECSSDT Select status indic.:	csi 1 $ ~ 
+#	DECSSDT Select status host-wr:	csi 2 $ ~ 
+#	SM DECTCEM Visible cursor:	csi ? 2 5 h
+#	RM DECTCEM Invisible cursor:	csi ? 2 5 l
+#	SM DECNCRM 7 bits NCR set:	csi ? 4 2 h
+#	RM DECNCRM Multi or ISO latin:	csi ? 4 2 l
+#	DECSCL vt300 mode 8-bit ctrl:	csi 6 3 " p
+# or	DECSCL vt300 mode 8-bit ctrl:	csi 6 3 ; 0 " p
+#	DECSCL vt300 mode 7-bit ctrl:	csi 6 3 ; 1 " p
+#	Char. and Line attributes:	csi Ps ... Ps m
+# with:  0 All off, 1 Bold, 4 Underline, 5 Blinking, 7 Reverse
+# and : 22 Bold off, 24 Underline off, 25 Blinking off, 27 Reverse off
+# (bq300-8: :le:,:nd:,:up:,:do:,:dl:,:al: to get under 1024 --esr)
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+bq300-8|Bull vt320 full 8 bits 80 columns:\
+	:am:eo:es:hs:km:mi:ms:xn:xo:\
+	:co#80:it#8:li#24:vt#3:ws#80:\
+	:AL=\233%dL:DC=\233%dP:DL=\233%dM:DO=\233%dB:IC=\233%d@:\
+	:K1=\217w:K2=\217u:K3=\217y:K4=\217q:K5=\217s:LE=\233%dD:\
+	:RI=\233%dC:UP=\233%dA:ae=^O:as=^N:bl=^G:cd=\233J:ce=\233K:\
+	:cl=\233H\233J:cm=\233%i%d;%dH:cr=^M:cs=\233%i%d;%dr:\
+	:ct=\2333g:dc=\233P:ds=\2331$}\2332$~\n\2330$}:\
+	:ec=\233%dX:ei=\2334l:fs=\2330$}:ho=\233H:\
+	:i1=\E[63;2"p\E[2h:i2=\2330$}\233?25h\2332l\233H\233J:\
+	:im=\2334h:\
+	:is=\E[?2h\E[?3l\E[?5l\E[?7h\E[?8h\E>\E[?1l\E G\E[?42l\E[?4l:\
+	:k1=\217P:k2=\217Q:k3=\217R:k4=\217S:k6=\23317~:\
+	:k7=\23318~:k8=\23319~:k9=\23320~:kD=\2333~:kI=\2332~:\
+	:kN=\2336~:kP=\2335~:kb=^H:kd=\233B:ke=\233?1l\E>:\
+	:kl=\233D:kr=\233C:ku=\233A:mb=\2335m:md=\2331m:\
+	:me=\2330m\E(B:mr=\2337m:nw=\EE:rc=\E8:sc=\E7:se=\23327m:\
+	:sf=\ED:so=\2337m:sr=\EM:st=\EH:ta=^I:te=\233?7h:\
+	:ti=\233?7l\233?1l\E(B:ts=\2331$}\2332$~:ue=\23324m:\
+	:us=\2334m:vb=\233?5h\233?5l:ve=\233?25h:vi=\233?25l:\
+	:vs=\233?25h:
+bq300-8rv|Bull vt320 8-bit reverse mode 80 columns:\
+	:is=\E[?2h\E[?3l\E[?5h\E[?7h\E[?8h\E>\E[?1l\E G\E[?42l\E[?4l:\
+	:vb=\233?5l\233?5h:\
+	:tc=bq300-8:
+bq300-8w|Bull vt320 8-bit 132 columns:\
+	:co#132:ws#132:\
+	:is=\E[?2h\E[?3h\E[?5l\E[?7h\E[?8h\E>\E[?1l\E G\E[?42l\E[?4l:\
+	:r2=\233?3h:\
+	:tc=bq300-8:
+bq300-w-8rv|Bull vt320 8-bit reverse mode 132 columns:\
+	:co#132:ws#132:\
+	:is=\E[?2h\E[?3h\E[?5h\E[?7h\E[?8h\E>\E[?1l\E G\E[?42l\E[?4l:\
+	:r2=\233?3h:vb=\233?5l\233?5h:\
+	:tc=bq300-8:
+
+#  This entry is used for terminals with vt320 emulation mode
+#  a 102 keys keyboard (PC scancode !) and following set-up : 
+#    8 bit ISO Latin Character Set (ISO 8859-1),
+#    7 bit Control Characters, 
+#    80 columns screen.    
+bq300-pc|Questar 303 with PC keyboard ISO Latin 1 80 columns:\
+	:%0@:%1@:*6@:@0@:@7=\E[4~:F1=\E[29~:F2=\E[31~:F3@:F4@:F5@:F6@:\
+	:F7@:F8@:F9@:FA@:k1=\E[17~:k2=\E[18~:k3=\E[19~:k4=\E[20~:\
+	:k5=\E[21~:k6=\E[23~:k7=\E[24~:k8=\E[25~:k9=\E[26~:\
+	:k;=\E[28~:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:kb=^H:\
+	:kh=\E[1~:l1@:l2@:l3@:l4@:\
+	:tc=bq300:
+bq300-pc-rv|Questar 303 with PC keyboard reverse mode 80 columns:\
+	:is=\E[?2h\E[?3l\E[?5h\E[?7h\E[?8h\E>\E[?1l\E F\E[?42l\E[?4l:\
+	:vb=\E[?5l\E[?5h:\
+	:tc=bq300-pc:
+bq300-pc-w|Questar 303 with PC keyboard 132 columns terminal:\
+	:co#132:ws#132:\
+	:is=\E[?2h\E[?3h\E[?5l\E[?7h\E[?8h\E>\E[?1l\E F\E[?42l\E[?4l:\
+	:r2=\E[?3h:\
+	:tc=bq300-pc:
+bq300-pc-w-rv|Questar 303 with PC keyboard reverse mode 132 columns:\
+	:co#132:ws#132:\
+	:is=\E[?2h\E[?3h\E[?5h\E[?7h\E[?8h\E>\E[?1l\E F\E[?42l\E[?4l:\
+	:r2=\E[?3h:vb=\E[?5l\E[?5h:\
+	:tc=bq300-pc:
+#    8 bit ISO Latin Character Set (ISO 8859-1),
+#    8 bit Control Characters, 
+#    80 columns screen.    
+bq300-8-pc|Q306-8-pc|Questar 303 with PC keyboard in full 8 bits 80 columns:\
+	:%0@:%1@:*6@:@0@:@7=\2334~:F1=\23329~:F2=\23331~:F3@:F4@:F5@:\
+	:F6@:F7@:F8@:F9@:FA@:k1=\23317~:k2=\23318~:k3=\23319~:\
+	:k4=\23320~:k5=\23321~:k6=\23323~:k7=\23324~:k8=\23325~:\
+	:k9=\23326~:k;=\23328~:kD=\2333~:kI=\2332~:kN=\2336~:\
+	:kP=\2335~:kb=^H:kh=\2331~:l1@:l2@:l3@:l4@:\
+	:tc=bq300-8:
+bq300-8-pc-rv|Questar 303 with PC keyboard full 8 bits reverse mode 80 columns:\
+	:is=\E[?2h\E[?3l\E[?5h\E[?7h\E[?8h\E>\E[?1l\E G\E[?42l\E[?4l:\
+	:vb=\E[?5l\E[?5h:\
+	:tc=bq300-8-pc:
+bq300-8-pc-w|Questar 303 with PC keyboard full 8 bits 132 columns:\
+	:co#132:ws#132:\
+	:is=\E[?2h\E[?3h\E[?5l\E[?7h\E[?8h\E>\E[?1l\E G\E[?42l\E[?4l:\
+	:r2=\E[?3h:\
+	:tc=bq300-8-pc:
+bq300-8-pc-w-rv|Questar 303 with PC keyboard full 8 bits reverse 132 columns:\
+	:co#132:ws#132:\
+	:is=\E[?2h\E[?3h\E[?5h\E[?7h\E[?8h\E>\E[?1l\E G\E[?42l\E[?4l:\
+	:r2=\E[?3h:vb=\E[?5l\E[?5h:\
+	:tc=bq300-8-pc:
+
+#======================================================#
+# BULL QUESTAR 310 `VIP 7800/8800' terminals emulation #
+#======================================================#
+
+# normal mode, 8 bits, 80 columns terminal.
+#	RES reset :			^[e
+#	RIS reset initial state:	^[c
+#	BLE bell enable			^[h
+#	BLD bell disable		^[g
+#	CAMS char. attr. mode set	^[[D
+#	CAMR char. attr. mode reset	^[[G
+#	CLR clear			^[`
+#	KBU keyboard unlock (set)	^[[W
+#	KBL keyboard lock (reset)	^[[X
+#	CM  character mode (async.) 	^[k
+#	NEP non echoplex mode (by host)	^[l
+#	EP  echoplex mode (by host) 	^[m
+#	IM  insert mode set		^[[I
+#	IM  insert mode reset 		^[[J
+#	RMS roll mode set 		^[r
+#	RMR roll mode reset 		^[q
+#	SM78 set mode vip7800	 	^[[1q
+#	SD  scroll up  	(72 lines) 	^[[0s
+#	SD  scroll down	(72 lines) 	^[[1s
+#	RBM block mode reset		^[[E
+#	SLS status line set 		^[w
+#	SLR status line reset 		^[v
+#	SLL status line lock 		^[O
+#	LGS Line-graphic mode set 	^[G
+#	LGR Line-graphic mode reset 	^[F
+#	TBC tab clear (at cursor pos.)	^[[g
+#	TBI tab initialize 		^[[N
+#	TBS tab set (at cursor pos.)	^[p
+#	PDS  print data space		^[[0p
+#	PHD  print host data 		^[[3p
+#	PDT  print data terminator	^[[<p
+#	PRES print adapter reset	^[[2p
+#	SSPR multi-part. reset		^[[<>u
+#	SSP0 partition 0 set		^[[00u
+#	SSP1 partition n format 1 	^[[PnPnSTRINGu
+#	SSP2 partition n format 2 	^[[PnPnSTRINGu
+#	SSP3 partition n format 3 	^[[PnPnu
+#	ATR attribute (visual)
+#	    blink :			^[sB
+#	    dim :			^[sL
+#	    hide (blank) :		^[sH
+#	    restore :			^[sR
+#	    inverse video :		^[sI
+#	    prot. :			^[sP
+#	    underline :			^[s_
+#	    reset :			^{
+#
+# This covers the vip7800 and BQ3155-vip7800
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+vip|Bull Questar 3155-7800:\
+	:am:es:hs:km:ms:xn:xo:\
+	:co#80:it#8:li#24:vt#3:ws#80:\
+	:ae=\EF:as=\EG:bl=^G:bt=\E[Z:cd=\EJ:ce=\EK:cl=\E`:\
+	:cm=\E[%i%03%03f:cr=^M:ct=\E[N:dc=\E[P:dl=\E[M:do=^J:\
+	:ds=\Ev:ei=\E[J:fs=\EO:ho=\EH:i2=\Er\E[W\E`:ic=\E[I:\
+	:im=\E[I:is=\E[00u\E[<>001001024080024080u\E[01u:\
+	:k1=\E0:k2=\E2:k3=\E6:k4=\E8:k5=\E\072:k6=\E<:k7=\E>:k8=\EP:\
+	:k9=\ER:kD=\E[P:kH=\EH\EA:kI=\E[I:kb=^H:kd=\EB:kh=\EH:\
+	:kl=\ED:kr=\EC:ku=\EA:le=^H:ll=\EH\EA:mb=\EsB:\
+	:me=\EsR\EsU\EF:mh=\EsL:mr=\EsI:nd=\EC:nw=^M:se=\EsR:sf=^J:\
+	:so=\EsI:sr=\EA\EJ\EH\E[L:st=\Ep:ta=^I:ts=\Ew:ue=\EsR:\
+	:up=\EA:us=\Es_:vb=\007\007\007:
+# normal screen, 8 bits, 132 columns terminal.
+vip-w|vip7800-w|Q310-vip-w|Q310-vip-w-am|Questar 3155-vip7800 wide:\
+	:co#132:ws#132:\
+	:is=\E[00u\E[<>001001024132024132u\E[01u:tc=vip:
+vip-H|vip7800-H|Q310-vip-H|Q310-vip-H-am|Questar 3155-vip7800 72 lines:\
+	:li#72:\
+	:is=\E[00u\E[<>001001024080072080u\E[01u:tc=vip:
+vip-Hw|vip7800-Hw|Q310-vip-Hw|Questar 3155-vip7800 wide 72 lines:\
+	:co#132:li#72:ws#132:\
+	:is=\E[00u\E[<>001001024132072132u\E[01u:tc=vip:
+#### Chromatics
+#
+
+# I have put the long strings in :ti:/:te:. Ti sets up a window 
+# that is smaller than the screen, and puts up a warning message 
+# outside the window. Te erases the warning message, puts the 
+# window back to be the whole screen, and puts the cursor at just
+# below the small window. I defined :ve: and :vi: to really turn 
+# the cursor on and off, but I have taken this out since I don't 
+# like the cursor being turned off when vi exits.   
+cg7900|chromatics|chromatics 7900:\
+	:am:\
+	:co#80:li#40:\
+	:al=^A>2:bl=^G:cd=^Al:ce=^A`:cl=^L:cm=\001M%r%d\054%d\054:\
+	:cr=^M:dc=^A<1:dl=^A<2:do=^J:ei=:ho=^\:ic=^A>1:im=:le=^H:\
+	:ll=^A|:nd=^]:se=\001C1\054\001c2\054:sf=^J:\
+	:so=\001C4\054\001c7\054:\
+	:te=\001W0\05440\05485\05448\054\014\001W0\0540\05485\05448\054\001M0\05440\054:\
+	:ti=\001P0\001O1\001R1\001C4\054\001c0\054\014\001M0\05442\054WARNING DOUBLE ENTER ESCAPE and \025\001C1\054\001c2\054\001W0\0540\05479\05439\054:\
+	:uc=\001\001_\001\0:up=^K:
+
+#### Computer Automation
+#
+
+ca22851|computer automation 22851:\
+	:am:\
+	:co#80:li#24:\
+	:bl=^G:cd=^\:ce=^]:cl=\014:cm=\002%i%.%.:cr=^M:do=^J:ho=^^:\
+	:kd=^W:kh=^^:kl=^U:ku=^V:le=^U:nd=^I:sf=^J:up=^V:
+
+#### Cybernex
+#
+
+# This entry has correct padding and the undocumented "ri" capability
+cyb83|xl83|cybernex xl-83:\
+	:am:bs:\
+	:co#80:li#24:\
+	:bl=^G:cd=\020:ce=\017:cl=\014:cm=\027%+ %+ :cr=^M:do=^J:\
+	:ho=^K:kd=^J:kl=^H:kr=^I:ku=^N:le=^H:nd=^I:sf=^J:sr=^N:up=^N:
+# (mdl110: removed obsolete ":ma=^Z^P:" and overridden ":cd=145^NA^W:" -- esr)
+cyb110|mdl110|cybernex mdl-110:\
+	:am:bs:\
+	:co#80:li#24:\
+	:al=\016A\016\035:bl=^G:cd=\016@\026:ce=\016@\026:\
+	:cl=\030:cm=\020%+ %+ :cr=^M:dc=\016A\036:\
+	:dl=\016A\016\036:do=^J:ei=:ho=^Y:ic=\016A\035:im=:le=^H:\
+	:nd=^U:se=^NG:sf=^J:so=^NF:ta=\011:up=^Z:
+
+#### Datapoint
+#
+# Datapoint is gone.  They used to be headquartered in Texas.
+# They created ARCnet, an Ethernet competitor that flourished for a while
+# in the early 1980s before 3COM got wise and cut its prices.  The service
+# side of Datapoint still lives (1995) in the form of Intelogic Trace.
+#
+
+dp3360|datapoint|datapoint 3360:\
+	:am:bs:\
+	:co#82:li#25:\
+	:bl=^G:cd=^_:ce=^^:cl=^]^_:cr=^M:do=^J:ho=^]:le=^H:nd=^X:\
+	:sf=^J:up=^Z:
+
+# From: Jan Willem Stumpel <jw.stumpel@inter.nl.net>, 11 May 1997
+# The Datapoint 8242 Workstation was sold at least between 1985 
+# and 1989. To make the terminal work with this entry, press 
+# CONTROL-INT-INT to take the terminal off-line, and type (opt). 
+# Set the options AUTO ROLL, ROLL DN, and ESC KBD on, and AUTO 
+# CR/LF off. Use control-shift-[] as escape key, control-I as tab, 
+# shift-F1 to shift-F5 as F6 to F10 (unshifted F1 to F5 are in
+# fact unusable because the strings sent by the terminal conflict
+# with other keys).
+# The terminal is capable of displaying "box draw" characters.
+# For each graphic character you must send 2 ESC's (\E\E) followed 
+# by a control character as follows: 
+#         character        meaning
+#         =========        =======
+#         ctrl-E           top tee
+#         ctrl-F           right tee
+#         ctrl-G           bottom tee
+#         ctrl-H           left tee
+#         ctrl-I           cross
+#         ctrl-J           top left corner
+#         ctrl-K           top right corner
+#         ctrl-L           bottom left corner
+#         ctrl-M           bottom right corner
+#         ctrl-N           horizontal line
+#         ctrl-O           vertical line
+# Unfortunately this cannot be fitted into the termcap/terminfo 
+# description scheme. 
+dp8242|datapoint 8242:\
+	:ms:\
+	:co#80:li#25:\
+	:al=\E^T:bl=^G:cd=^W:ce=^V:cl=\025\E\004\027\030:\
+	:cm=\011%r%+\%+\:cr=^M:dl=\E^Z:do=^J:ho=^U:\
+	:i1=\E\014\E\016\0\230\0\317\025\027\030\E\004:\
+	:k1=^G\Ee:k2=^I\Ed:k3=^J\Ec:k4=^J\Eb:k5=^S\Ea:k6=\EO\Ee:\
+	:k7=\EN\Ed:k8=\EM\Ec:k9=\EL\Eb:k;=\EK\Ea:kb=^H:kd=^B:kl=^D:\
+	:kr=^F:ku=^E:le=^H:nw=^M^J:\
+	:r1=\E\014\E\016\0\230\0\317\025\027\030\E\004:\
+	:rp=\E\023%.%.:se=\E^D:sf=^C:so=\E^E:sr=^K:ta=^I:ue=\E^D:\
+	:us=\E^F:ve=^X:vi=^Y:\
+	:..wi=\E\014\E\016%p1%'\0'%+%c%p2%'\0'%+%c%p3%'\0'%+%c%p4%'\0'%+%c\025:
+
+#### DEC terminals (Obsolete types: DECwriter and vt40/42/50)
+#
+# These entries are DEC's official terminfos for its older terminals.
+# Contact Bill Hedberg <hedberg@hannah.enet.dec.com> of Terminal Support
+# Engineering for more information.  Updated terminfos and termcaps 
+# are kept available at ftp://gatekeeper.dec.com/pub/DEC/termcaps.
+#
+
+gt40|dec gt40:\
+	:bs:os:\
+	:co#72:li#30:\
+	:bl=^G:cr=^M:do=^J:le=^H:
+gt42|dec gt42:\
+	:bs:os:\
+	:co#72:li#40:\
+	:bl=^G:cr=^M:do=^J:le=^H:
+
+vt50|dec vt50:\
+	:bs:\
+	:co#80:li#12:\
+	:bl=^G:cd=\EJ:ce=\EK:cl=\EH\EJ:cr=^M:do=^J:le=^H:nd=\EC:\
+	:sf=^J:ta=^I:up=\EA:
+vt50h|dec vt50h:\
+	:bs:\
+	:co#80:li#12:\
+	:bl=^G:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :cr=^M:do=^J:\
+	:le=^H:nd=\EC:sf=^J:sr=\EI:ta=^I:up=\EA:
+# (<acsc>/:ae:/:as: capabilities aren't in DEC's official entry -- esr)
+vt52|dec vt52:\
+	:bs:\
+	:co#80:it#8:li#24:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=\EG:as=\EF:bl=^G:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :\
+	:cr=^M:do=\EB:ho=\EH:kb=^H:kd=\EB:kl=\ED:kr=\EC:ku=\EA:\
+	:le=\ED:nd=\EC:nw=^M^J:sf=^J:sr=\EI:ta=^I:up=\EA:
+
+# (vt61: there's a BSD termcap that claims :dl=\EPd:, :al=\EPf.: :kb=^H:)
+vt61|vt-61|vt61.5|dec vt61:\
+	:co#80:li#24:\
+	:bl=^G:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :cr=\r:do=^J:\
+	:kd=\EB:kl=\ED:kr=\EC:ku=\EA:le=^H:nd=\EC:sf=\n:sr=\EI:ta=^I:\
+	:up=\EA:
+
+# The gigi does standout with red!
+# (gigi: I added <rmam>/<smam> based on the init string, corrected cub1 -- esr)
+gigi|vk100|dec gigi graphics terminal:\
+	:am:bs:xn:\
+	:co#84:li#24:\
+	:DO=\E[%dB:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:\
+	:UP=\E[%dA:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:\
+	:cm=\E[%i%d;%dH:cr=^M:do=^J:\
+	:is=\E>\E[?3l\E[?4l\E[?5l\E[?20l\E[?7h\E[?8h:k1=\EOP:\
+	:k2=\EOQ:k3=\EOR:k4=\EOS:kd=\EOB:ke=\E[?1l\E>:kh=\E[H:\
+	:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:me=\E[m:\
+	:nd=\E[C:se=\E[m:sf=^J:so=\E[7;31m:sr=\EM:ta=^I:ue=\E[m:\
+	:up=\E[A:us=\E[4m:
+
+# DEC PRO-350 console (VT220-style).  The 350 was DEC's attempt to produce
+# a PC differentiated from the IBM clones.  It was a total, ludicrous,
+# grossly-overpriced failure (among other things, DEC's OS didn't include
+# a format program, so you had to buy pre-formatted floppies from DEC at
+# a hefty premium!).
+pro350|decpro|dec pro console:\
+	:bs:\
+	:co#80:it#8:li#24:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=\EG:as=\EF:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :do=\EB:\
+	:ho=\EH:k0=\EE:k1=\EF:k2=\EG:k3=\EH:k4=\EI:k5=\EJ:k6=\Ei:\
+	:k7=\Ej:kd=\EB:kh=\EH:kl=\ED:kr=\EC:ku=\EA:le=^H:nd=\EC:\
+	:se=\E^N:so=\E^H:sr=\EI:ta=^I:ue=\E^C:up=\EA:us=\E^D:
+
+dw1|decwriter I:\
+	:bs:hc:os:\
+	:co#72:\
+	:bl=^G:cr=^M:do=^J:le=^H:sf=^J:
+dw2|decwriter|dw|decwriter II:\
+	:bs:hc:os:\
+	:co#132:\
+	:bl=^G:cr=^M:do=^J:kb=^H:le=^H:sf=^J:
+# \E(B		Use U.S. character set (otherwise # => british pound !)
+# \E[20l	Disable "linefeed newline" mode (else puts \r after \n,\f,\v)
+# \E[w   	10 char/in pitch
+# \E[1;132	full width horizontal margins
+# \E[2g		clear all tab stops
+# \E[z		6 lines/in
+# \E[66t	66 lines/page (for \f)
+# \E[1;66r	full vertical page can be printed
+# \E[4g		clear vertical tab stops
+# \E>		disable alternate keypad mode (so it transmits numbers!)
+# \E[%i%p1%du	set tab stop at column %d (origin == 1)
+#		(Full syntax is \E[n;n;n;n;n;...;nu where each 'n' is 
+#		a tab stop)
+#
+#       The dw3 does standout with wide characters.
+#
+dw3|la120|decwriter III:\
+	:bs:hc:os:\
+	:co#132:\
+	:bl=^G:cr=^M:do=^J:\
+	:i1=\E(B\E[20l\E[w\E[0;132s\E[2g\E[z\E[66t\E[1;66r\E[4g\E>:\
+	:is=\E[9;17;25;33;41;49;57;65;73;81;89;97;105;113;121;129u\r:\
+	:kb=^H:le=^H:me=\E[w:se=\E[w:sf=^J:so=\E[6w:ta=^I:
+dw4|decwriter IV:\
+	:am:bs:hc:os:\
+	:co#132:\
+	:bl=^G:cr=^M:do=^J:is=\Ec:k0=\EOP:k1=\EOQ:k2=\EOR:k3=\EOS:\
+	:kb=^H:le=^H:sf=^J:ta=^I:
+
+# These aren't official
+ln03|dec ln03 laser printer:\
+	:hc:\
+	:co#80:li#66:\
+	:bl=^G:cr=^M:do=^J:hd=\EK:hu=\EL:me=\E[m:nw=^M^J:se=\E[22m:\
+	:sf=^J:so=\E[1m:ta=^I:ue=\E[24m:us=\E[4m:
+ln03-w|dec ln03 laser printer 132 cols:\
+	:co#132:\
+	:bl=^G:cr=^M:do=^J:kb=^H:kd=^J:kl=^H:nw=^M^J:sf=^J:ta=^I:tc=ln03:
+
+#### Delta Data (dd)
+#
+
+# Untested. The cup sequence is hairy enough that it probably needs work.
+# The idea is ctrl(O), dd(row), dd(col), where dd(x) is x - 2*(x%16) + '9'.
+# There are BSD-derived termcap entries floating around for this puppy
+# that are *certainly* wrong.
+delta|dd5000|delta data 5000:\
+	:am:bs:\
+	:co#80:li#27:\
+	:bl=^G:ce=^NU:cl=^NR:cm=\017%+^P%+^P:dc=^NV:do=^J:ho=^NQ:\
+	:le=^H:nd=^Y:sf=^J:up=^Z:
+
+#### Digital Data Research (ddr)
+#
+
+# (ddr: I added <rmam>/<smam> based on the init string -- esr)
+ddr|rebus3180|ddr3180|Rebus/DDR 3180 vt100 emulator:\
+	:am:bs:xn:\
+	:co#80:it#8:li#24:vt#3:\
+	:RA=\E[7l:SA=\E[7l:cd=50\E[J:ce=3\E[K:cl=50\E[H\E[2J:\
+	:cm=5\E[%i%d;%dH:cs=\E[%i%d;%dr:do=^J:ho=\E[H:\
+	:is=\E[1;24r\E[24;1H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+	:kb=^H:kd=\E[B:ke=\E[?1l\E>:kl=\E[D:kr=\E[C:ks=\E[?1h\E=:\
+	:ku=\E[A:le=^H:mb=2\E[5m:md=2\E[1m:me=2\E[m:mr=2\E[7m:\
+	:nd=2\E[C:r1=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\E8:\
+	:rf=/usr/share/tabset/vt100:sc=\E7:se=\E[m:sf=5\ED:\
+	:so=\E[7m:sr=5\EM:ta=^I:ue=2\E[m:up=2\E[A:us=2\E[4m:
+
+#### Evans & Sutherland
+#
+
+# Jon Leech <leech@cs.unc.edu> tells us:
+# The ps300 was the Evans & Sutherland Picture System 300, a high
+# performance 3D vector graphics system with a bunch of specialized hardware.
+# Approximate date of release was 1982 (early 80s, anyway), and it had several
+# evolutions including (limited) color versions such as the PS330C. PS300s
+# were effectively obsolete by the late 80s, replaced by raster graphics
+# systems, although specialized applications like molecular modelling
+# hung onto them for a while longer.  AFAIK all E&S vector graphics systems
+# are out of production, though of course E&S is very much alive (in 1996).
+# (ps300: changed ":pt@:" to "it@" -- esr)
+#
+ps300|Picture System 300:\
+	:xt:\
+	:it@:\
+	:se@:so@:ue@:us@:tc=vt100:
+
+#### General Electric (ge)
+#
+
+terminet1200|terminet300|tn1200|tn300|terminet|GE terminet 1200:\
+	:bs:hc:os:\
+	:co#120:\
+	:bl=^G:cr=^M:do=^J:sf=^J:
+
+#### Heathkit/Zenith
+#
+
+# Here is a description of the H19 DIP switches:
+#
+# S401
+# 0-3 = baud rate as follows:
+# 
+#         3       2       1       0
+#	---	---	---	--- 
+#         0       0       1       1       300 baud
+#         0       1       0       1       1200 baud
+#         1       0       0       0       2400 baud
+#         1       0       1       0       4800 baud
+#         1       1       0       0       9600 baud
+#         1       1       0       1       19.2K baud
+# 
+# 4 = parity (0 = no parity)
+# 5 = even parity (0 = odd parity)
+# 6 = stick parity (0 = normal parity)
+# 7 = full duplex (0 = half duplex)
+# 
+# S402 
+# 0 = block cursor (0 = underscore cursor)
+# 1 = no key click (0 = keyclick)
+# 2 = wrap at end of line (0 = no wrap)
+# 3 = auto LF on CR (0 = no LF on CR)
+# 4 = auto CR on LF (0 = no CR on LF)
+# 5 = ANSI mode (0 = VT52 mode)
+# 6 = keypad shifted (0 = keypad unshifted)
+# 7 = 50Hz refresh (1 = 60Hz refresh)
+# 
+# Factory Default settings are as follows:
+#          7 6 5 4 3 2 1 0
+# S401     1 0 0 0 1 1 0 0
+# S402     0 0 0 0 0 0 0 0
+# (h19: I added <rmam>/<smam> based on the init string;
+# also added empty <acsc> to suppress a tic warning -- esr)
+h19-a|h19a|heath-ansi|heathkit-a|heathkit h19 ansi mode:\
+	:am:bs:mi:ms:\
+	:co#80:it#8:li#24:\
+	:RA=\E[?7l:SA=\E[?7h:ac=:ae=\E[11m:al=\E[1L:as=\E[10m:\
+	:bl=^G:cd=\E[J:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:cr=^M:\
+	:dc=\E[1P:dl=\E[1M:do=\E[1B:ei=\E[4l:ho=\E[H:im=\E[4h:\
+	:is=\E<\E[>1;2;3;4;5;6;7;8;9l\E[m\E[11m\E[?7h:k1=\EOS:\
+	:k2=\EOT:k3=\EOU:k4=\EOV:k5=\EOW:k6=\EOP:k7=\EOQ:k8=\EOR:\
+	:kb=^H:kd=\E[1B:kh=\E[H:kl=\E[1D:kr=\E[1C:ku=\E[1A:l6=blue:\
+	:l7=red:l8=white:le=^H:nd=\E[1C:se=\E[m:sf=^J:so=\E[7m:\
+	:sr=\EM:ta=^I:up=\E[1A:ve=\E[>4l:vs=\E[>4h:
+h19-bs|heathkit w/keypad shifted:\
+	:ke=\Eu:ks=\Et:tc=h19-b:
+h19-us|h19us|h19-smul|heathkit w/keypad shifted/underscore cursor:\
+	:ke=\Eu:ks=\Et:\
+	:tc=h19-u:
+# (h19: merged in :ip: from BSDI hp19-e entry>;
+# also added empty <acsc> to suppress a tic warning --esr)
+# From: Tim Pierce <twp@skepsis.com>, 23 Feb 1998 
+# Tim tells us that:
+# I have an old Zenith-19 terminal at home that still gets a lot of use.
+# This terminal suffers from the same famous insert-mode padding lossage
+# that has been acknowledged for the Z29 terminal.  Emacs is nearly
+# unusable on this box, since even a half-scroll up or down the window
+# causes flaming terminal death.
+#   
+# On the Z19, the only way I have found around this problem is to remove
+# the :al: and :dl: entries entirely.  No amount of extra padding will
+# help (I have tried up to 20000).  Removing :al=\EL$: and :dl=\EM$:
+# makes Emacs a little slower, but it remains in the land of the living.
+# Big win.
+h19|heath|h19-b|heathkit|heath-19|z19|zenith|heathkit h19:\
+	:am:bs:es:hs:mi:ms:\
+	:co#80:it#8:li#24:\
+	:ac=:ae=\EG:as=\EF:bl=^G:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :\
+	:cr=^M:dc=\EN:do=\EB:ei=\EO:fs=\Ek\Ey5:ho=\EH:im=\E@:\
+	:ip=1.5<1.5/>:k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:k6=\EP:\
+	:k7=\EQ:k8=\ER:kb=^H:kd=\EB:kh=\EH:kl=\ED:kr=\EC:ku=\EA:\
+	:l6=blue:l7=red:l8=white:le=^H:nd=\EC:se=\Eq:sf=^J:so=\Ep:\
+	:sr=\EI:ta=^I:ts=\Ej\Ex5\EY8%p1%{32}%+%c\Eo\Eo:up=\EA:\
+	:ve=\Ey4:vs=\Ex4:
+h19-u|heathkit with underscore cursor:\
+	:ve@:vs@:tc=h19-b:
+h19-g|h19g|heathkit w/block cursor:\
+	:ve=\Ex4:tc=h19-b:
+alto-h19|altoh19|altoheath|alto-heath|alto emulating heathkit h19:\
+	:li#60:\
+	:al=\EL:dl=\EM:tc=h19:
+
+# The major problem with the Z29 is that it requires more padding than the Z19.
+#
+# The problem with declaring an H19 to be synonymous with a Z29 is that
+# it needs more padding. It especially loses if a program attempts
+# to put the Z29 into insert mode and insert text at 9600 baud. It
+# even loses worse if the program attempts to insert tabs at 9600
+# baud. Adding padding to text that is inserted loses because in 
+# order to make the Z29 not die, one must add so much padding that
+# whenever the program tries to use insert mode, the effective 
+# rate is about 110 baud.
+# 
+# What program would want to put the terminal into insert mode 
+# and shove stuff at it at 9600 baud you ask?  
+# 
+# Emacs. Emacs seems to want to do the mathematically optimal 
+# thing in doing a redisplay rather than the practical thing.
+# When it is about to output a line on top of a line that is 
+# already on the screen, instead of just killing to the end of 
+# the line and outputting the new line, it compares the old line 
+# and the new line and if there are any similarities, it 
+# constructs the new line by deleting the text on the old line 
+# on the terminal that is already there and then inserting new
+# text into the line to transform it into the new line that is 
+# to be displayed. The Z29 does not react kindly to this.
+# 
+# But don't cry for too long.... There is a solution. You can make
+# a termcap entry for the Z29 that says the Z29 has no insert mode.
+# Then Emacs cannot use it. "Oh, no, but now inserting into a 
+# line will be really slow", you say. Well there is a sort of a
+# solution to that too. There is an insert character option on 
+# the Z29 that will insert one character. Unfortunately, it 
+# involves putting the terminal into ansi mode, inserting the 
+# character, and changing it back to H19 mode. All this takes 12 
+# characters. Pretty expensive to insert one character, but it 
+# works. Either Emacs doesn't try to use its inserting hack when 
+# it's only given an insert character ability or the Z29 doesn't 
+# require padding with this (the former is probably more likely, 
+# but I haven't checked it out).
+# (z29: added empty <acsc> to suppress a tic warning, merged in
+# status line capabilities from BRL entry --esr)
+z29|zenith29|z29b|zenith z29b:\
+	:am:bs:es:hs:mi:ms:pt:\
+	:co#80:kn#10:li#24:\
+	:ac=:ae=\EF:al=1\EL:as=\EG:bc=\ED:bl=^G:bt=\E-:cd=\EJ:ce=\EK:\
+	:cl=\EE:cm=\EY%+ %+ :cr=^M:dc=\EN:dl=1\EM:do=\EB:ds=\Ey1:\
+	:ei=\EO:fs=\Ek\Ey5:ho=\EH:ic=\E<\E[1@\E[?2h:im=\E@:\
+	:is=\E<\E[?2h\Ev:k0=\E~:k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:\
+	:k6=\EP:k7=\EQ:k8=\ER:k9=\E0I:kb=^H:kd=\EB:kh=\EH:kl=\ED:\
+	:kr=\EC:ku=\EA:l0=home:le=^H:nd=\EC:se=\Eq:sf=\n:so=\Ep:\
+	:sr=2\EI:ta=^I:ts=\Ej\Ex5\Ex1\EY8%+ \Eo:ue=\Es0:up=\EA:\
+	:us=\Es8:ve=\Ey4:vs=\Ex4:
+# z29 in ansi mode. Assumes that the cursor is in the correct state, and that
+# the world is stable. <rs1> causes the terminal to be reset to the state
+# indicated by the name. kc -> key click, nkc -> no key click, uc -> underscore
+# cursor, bc -> block cursor.
+# From: Mike Meyers
+# (z29a: replaced nonexistent :if=/usr/share/tabset/zenith29: befause :st:
+# looks vt100-compatible -- esr)
+z29a|z29a-kc-bc|h29a-kc-bc|heath/zenith 29 in ansi mode:\
+	:am:bs:es:hs:mi:ms:pt:\
+	:co#80:it#8:kn#10:li#24:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:bc=\ED:bl=^G:cd=\E[J:ce=\E[K:cl=\E[2J:\
+	:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[1P:\
+	:do=^J:ds=\E[>1l:fs=\E[u\E[>5l:ho=\E[H:\
+	:if=/usr/share/tabset/vt100:k0=\E[~:k1=\EOS:k2=\EOT:\
+	:k3=\EOU:k4=\EOV:k5=\EOW:k6=\EOP:k7=\EOQ:k8=\EOR:k9=\EOX:\
+	:kC=\E[J:kS=\E[J:kb=^H:kd=\EOB:kh=\E[H:kl=\EOD:kr=\EOC:\
+	:ku=\EOA:l0=help:le=^H:mb=\E[5m:md=\E[2m:me=\E[m:mh=\E[2m:\
+	:mr=\E[7m:nd=\E[C:nw=^M\ED:ps=\E#7:\
+	:r1=\E<\E[1;24r\E[24;1H\E[?7h\E[>4h\E[>1;2;3;5;6;7;8;9l\E[m\E[11m:\
+	:rc=\E[r:sc=\E[s:se=\E[m:sf=\ED:so=\E[7;2m:sr=\EM:st=\EH:\
+	:ta=^I:te=\E[?7h:ti=\E[?7l:\
+	:ts=\E[s\E[>5;1h\E[25;%i%dH\E[1K:ue=\E[m:up=\E[A:\
+	:us=\E[4m:
+z29a-kc-uc|h29a-kc-uc|z29 ansi mode with keyckick and underscore cursor:\
+	:r1=\E<\E[1;24r\E[24;1H\E[?7h\E[>1;2;3;4;5;6;7;8;9l\E[m\E[11m:\
+	:tc=z29a:
+z29a-nkc-bc|h29a-nkc-bc|z29 ansi mode with block cursor and no keyclick:\
+	:r1=\E<\E[1;24r\E[24;1H\E[?7h\E[>2;4h\E[>1;3;5;6;7;8;9l\E[m\E[11m:\
+	:tc=z29a:
+z29a-nkc-uc|h29a-nkc-uc|z29 ansi mode with underscore cursor and no keyclick:\
+	:r1=\E<\E[1;24r\E[24;1H\E[?7h\E[>2h\E[>1;3;4;5;6;7;8;9l\E[m\E[11m:\
+	:tc=z29a:
+# From: Jeff Bartig <jeffb@dont.doit.wisc.edu> 31 Mar 1995
+z39-a|z39a|zenith39-a|zenith39-ansi|Zenith 39 in ANSI mode:\
+	:5i:am:es:hs:mi:ms:xo:\
+	:co#80:li#24:\
+	:%1=\E[~:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:K1=\EOw:\
+	:K2=\EOy:K3=\EOu:K4=\EOq:K5=\EOs:LE=\E[%dD:RI=\E[%dC:\
+	:UP=\E[%dA:ac=0a``aaffggjjkkllmmnnooqqssttuuvvwwxx~~:\
+	:ae=\E(B:al=\E[1L:as=\E(0:bl=^G:bt=\E[1Z:cb=\E[1K:cd=\E[0J:\
+	:ce=\E[0K:cl=\E[2J\E[H:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[1P:dl=\E[1M:do=\E[B:\
+	:ds=\E[>1l:ei=\E[4l:fs=\E[u:ho=\E[H:im=\E[4h:\
+	:is=\E<\E[>1;3;5;6;7l\E[0m\E[2J:k1=\EOS:k2=\EOT:k3=\EOU:\
+	:k4=\EOV:k5=\EOW:k6=\EOP:k7=\EOQ:k8=\EOR:k9=\EOX:kS=\E[J:\
+	:kb=^H:kd=\E[B:ke=\E[>7l:kh=\E[H:kl=\E[D:kr=\E[C:ks=\E[>7h:\
+	:ku=\E[A:le=^H:ll=\E[24;1H:mb=\E[5m:md=\E[1m:me=\E[0m:\
+	:mh=\E[2m:mr=\E[7m:nd=\E[C:pf=\E[4i:po=\E[5i:\
+	:ps=\E[?19h\E[i:r2=\E<\Ec\0:rc=\E[u:sc=\E[s:se=\E[0m:\
+	:sf=^J:so=\E[7m:st=\EH:ta=^I:ts=\E[s\E[>1h\E[25;%i%p1%dH:\
+	:ue=\E[0m:up=\E[A:us=\E[4m:ve=\E[>5l:vi=\E[>5h:
+
+# From: Brad Brahms <Brahms@USC-ECLC>
+z100|h100|z110|z-100|h-100|heath/zenith z-100 pc with color monitor:\
+	:ve=\Ey4\Em70:vs=\Ex4\Em71:\
+	:tc=z100bw:
+# (z100bw: removed obsolete ":kn#10:", added empty <acsc> -- esr)
+z100bw|h100bw|z110bw|z-100bw|h-100bw|heath/zenith z-100 pc:\
+	:bs:mi:ms:pt:\
+	:co#80:it#8:kn#10:li#24:\
+	:ac=:ae=\EG:al=5*\EL:as=\EF:cd=\EJ:ce=\EK:cl=5*\EE:\
+	:cm=1*\EY%+ %+ :dc=1*\EN:dl=5*\EM:do=\EB:ei=\EO:ho=\EH:\
+	:im=\E@:k0=\EJ:k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:k6=\EP:\
+	:k7=\EQ:k8=\ER:k9=\EOI:kb=^H:kd=\EB:kh=\EH:kl=\ED:kr=\EC:\
+	:ku=\EA:le=^H:nd=\EC:se=\Eq:so=\Ep:sr=\EI:ta=^I:up=\EA:\
+	:ve=\Ey4:vs=\Ex4:
+p19|h19-b with il1/dl1:\
+	:al=2*\EL:dl=2*\EM:tc=h19-b:
+# From: <ucscc!B.fiatlux@ucbvax.berkeley.edu>
+# (ztx: removed duplicate :sr: -- esr)
+ztx|ztx11|zt-1|htx11|ztx-1-a|ztx-10 or 11:\
+	:am:bs:es:hs:\
+	:co#80:it#8:li#24:\
+	:al=\EL:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :dl=\EM:do=^J:\
+	:ds=\Ey1:fs=\Ek\Ey5:ho=\EH:\
+	:is=\Ej\EH\Eq\Ek\Ev\Ey1\Ey5\EG\Ey8\Ey9\Ey>:k0=\ES:\
+	:k1=\EB:k2=\EU:k3=\EV:k4=\EW:k5=\EP:k6=\EQ:k7=\ER:kb=^H:\
+	:kd=\EB:kl=\ED:kr=\EC:ku=\EA:le=^H:nd=\EC:se=\Eq:so=\Es5:\
+	:sr=\EI:ta=^I:ts=\Ej\Ex5\Ex1\EY8%+ \Eo:ue=\Eq:up=\EA:\
+	:us=\Es2:
+
+#### IMS International (ims)
+#
+# There was a company called IMS International located in Carson City, 
+# Nevada, that flourished from the mid-70s to mid-80s.  They made S-100
+# bus/Z80 hardware and a line of terminals called Ultimas.  
+#
+
+# From: Erik Fair <fair@ucbarpa.berkeley.edu>  Sun Oct 27 07:21:05 1985
+ims950-b|bare ims950 no init string:\
+	:is@:tc=ims950:
+# (ims950: removed obsolete ":ko@:" -- esr)
+ims950|ims televideo 950 emulation:\
+	:xn@:\
+	:k0@:k1@:k2@:k3@:k4@:k5@:k6@:k7@:k8@:k9@:kb@:kd@:kh@:kl@:kr@:ku@:vb@:tc=tvi950:
+# (ims950-rv: removed obsolete ":ko@:" -- esr)
+ims950-rv|ims tvi950 rev video:\
+	:xn@:\
+	:k0@:k1@:k2@:k3@:k4@:k5@:k6@:k7@:k8@:k9@:kb@:kd@:kh@:kl@:kr@:ku@:vb@:tc=tvi950-rv:
+ims-ansi|ultima2|ultimaII|IMS Ultima II:\
+	:am:bs:\
+	:co#80:it#8:li#24:\
+	:cd=\E[0J:ce=\E[0K:cl=\E[H\E[2J:cm=\E[%i%2;%2H:do=\ED:\
+	:if=/usr/share/tabset/vt100:\
+	:is=\E[m\E[>14l\E[?1;?5;20l\E>\E[1m\r:kd=\E[B:kh=\E[H:\
+	:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:me=\E[m:se=\E[m\E[1m:\
+	:so=\E[7m:sr=\EM:ta=^I:ue=\E[m\E[1m:up=\EM:us=\E[4m:
+
+#### Intertec Data Systems
+#
+# I think this company is long dead as of 1995.  They made an early CP/M
+# micro called the "Intertec Superbrain" that was moderately popular,
+# then sank out of sight.
+#
+
+superbrain|intertec superbrain:\
+	:am:bs:bw:\
+	:co#80:li#24:\
+	:bc=^U:bl=^G:cd=\E~k<10*>:ce=\E~K:cl=\014:cm=\EY%+ %+ :\
+	:cr=^M:do=^J:kd=^J:kl=^U:kr=^F:ku=^K:le=^H:nd=^F:sf=^J:ta=^I:\
+	:te=^L:ti=^L:up=^K:
+# (intertube: a Gould entry via BRL asserted smul=\E0@$<200/>, 
+# rmul=\E0A$<200/>; my guess is the highlight letter is bit-coded like an ADM,
+# and the reverse is actually true.  Try it. -- esr)
+intertube|intertec|Intertec InterTube:\
+	:am:bs:\
+	:co#80:li#25:\
+	:bl=^G:cl=^L:cm=\EY%+ %+ :cr=^M:do=^J:ho=^A:le=^H:nd=^F:\
+	:se=\E0@:sf=^J:so=\E0P:up=^Z:
+# The intertube 2 has the "full duplex" problem like the tek 4025: if you
+# are typing and a command comes in, the keystrokes you type get interspersed
+# with the command and it messes up
+intertube2|intertec data systems intertube 2:\
+	:bs:\
+	:ce=\EK:ch=\020%+^J:cm=\016%.\020%+^J:cv=\013%.:\
+	:ll=^K^X\r:\
+	:tc=intertube:
+
+#### Ithaca Intersystems
+#
+# This company made S100-bus personal computers long ago in the pre-IBM-PC
+# past.  They used to be reachable at:
+#
+#	Ithaca Intersystems
+#	1650 Hanshaw Road
+#	Ithaca, New York 14850
+#
+# However, the outfit went bankrupt years ago.
+#
+
+# The Graphos III was a color graphics terminal from Ithaca Intersystems.
+# These entries were written (originally in termcap syntax) by Brian Yandell 
+# <yandell@stat.wisc.edu> and Mike Meyer <mikem@stat.wisc.edu> at the 
+# University of Wisconsin.
+
+# (graphos: removed obsolete and syntactically incorrect :kn=4:, 
+# removed :if=/usr/share/tabset/init.graphos: and 
+# <rf=/usr/share/tabset/init.graphos> no such file & no :st: -- esr)
+graphos|graphos III:\
+	:am:mi:\
+	:co#80:it#8:li#24:\
+	:AL=\E[%dL:DL=\E[%dM:DO=\E[%dB:LE=\E[%dD:RI=\E[%dC:\
+	:UP=\E[%dA:al=\E[L:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:\
+	:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:dl=\E[M:dm=\E[4h:do=\E[B:\
+	:ed=\E[4l:ei=\E[4l:ho=\E[H:im=\E[4h:k1=\EOP:k2=\EOQ:\
+	:k3=\EOR:k4=\EOS:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:\
+	:ku=\E[A:le=^H:me=\E[m:nd=\E[C:nw=^M\ED:rc=\E8:sc=\E7:\
+	:se=\E[m:sf=\ED:so=\E[7m:sr=\EM:ta=^I:up=\E[A:\
+	:ve=\Ez56;2;0;0z\Ez73z\Ez4;1;1z:\
+	:vs=\Ez4;2;1z\Ez56;2;80;24z:
+graphos-30|graphos III with 30 lines:\
+	:li#30:\
+	:vs=\Ez4;2;1z\Ez56;2;80;30z:tc=graphos:
+
+#### Modgraph
+#
+# These people used to be reachable at:
+#
+#	Modgraph, Inc
+#	1393 Main Street,
+#	Waltham, MA 02154
+#	Vox: (617)-890-5796.
+#
+# However, if you call that number today you'll get an insurance company.
+# I have mail from "Michael Berman, V.P. Sales, Modgraph" dated 
+# 26 Feb 1997 that says:
+#
+# Modgraph GX-1000, replaced by GX-2000.  Both are out of production, have been
+# for ~7 years.  Modgraph still in business.  Products are rugged laptop and
+# portable PC's and specialized CRT and LCD monitors (rugged, rack-mount
+# panel-mount etc).  I can be emailed at sonfour@aol.com
+#
+# Peter D. Smith <pdsmith@nbbn.com> notes that his modgraph manual was
+# dated 1984.  According to the manual, it featured Tek 4010/4014
+# graphics and DEC VT100/VT52 + ADM-3A emulation with a VT220-style keyboard.
+#
+
+modgraph|mod24|modgraph terminal emulating vt100:\
+	:xn@:\
+	:co#80:li#24:\
+	:is=\E\1369;0s\E\1367;1s\E[3g\E\13611;9s\E\13611;17s\E\13611;25s\E\13611;33s\E\13611;41s\E\13611;49s\E\13611;57s\E\13611;65s\E\13611;73s\E\13611;81s\E\13611;89s:\
+	:rf@:sr=5\EM\E[K:vs=\E\1369;0s\E\1367;1s:\
+	:tc=vt100:
+# The GX-1000 manual is dated 1984.  This looks rather like a VT-52.
+modgraph2|modgraph gx-1000 80x24 with keypad not enabled:\
+	:am:da:db:\
+	:co#80:it#8:li#24:\
+	:cd=50\EJ:ce=3\EK:cl=50\EH\EJ:cm=5\EY%+ %+ :\
+	:is=\E<\E\1365;2s\E\1367;1s\E[3g\E\13611;9s\E\13611;17s\E\13611;25s\E\13611;33s\E\13611;41s\E\13611;49s\E\13611;57s\E\13611;65s\E\13611;73s\E\13611;81s\E\13611;89s\E\13612;0s\E\13614;2s\E\13615;9s\E\13625;1s\E\1369;1s\E\13627;1:\
+	:le=^H:nd=2\EC:sr=5\EI:ta=^I:up=2\EA:
+#
+# Modgraph from Nancy L. Cider <nancyc@brl-tbd>
+# BUG NOTE from Barbara E. Ringers <barb@brl-tbd>:
+# If we set TERM=vt100, and set the Modgraph screen to 24 lines, setting a
+# mark and using delete-to-killbuffer work correctly.  However, we would
+# like normal mode of operation to be using a Modgraph with 48 line setting.
+# If we set TERM=mod (which is a valid entry in termcap with 48 lines)
+# the setting mark and delete-to-killbuffer results in the deletion of only
+# the line the mark is set on.
+# We've discovered that the delete-to-killbuffer works correctly
+# with TERM=mod and screen set to 80x48 but it's not obvious.  Only
+# the first line disappears but a ctrl-l shows that it did work
+# correctly.
+modgraph48|mod|Modgraph w/48 lines:\
+	:am:bs:pt:xn:\
+	:co#80:it#8:li#48:vt#3:\
+	:bl=^G:cd=\E[J:ce=\E[K:cl=\E[;H\E[2J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:do=^J:ho=\E[H:\
+	:is=\E<\E[1;48r\E[0q\E[3;4q\E=\E[?1h:k1=\EOP:k2=\EOQ:\
+	:k3=\EOR:k4=\EOS:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:\
+	:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:\
+	:me=\E[m:mr=\E[7m:nd=\E[C:nl=^J:r1=\E=\E[0q\E>:rc=\E8:\
+	:sc=\E7:se=\E[m:so=\E[7m:sr=\EM:ta=^I:ue=\E[m:up=\E[A:\
+	:us=\E[4m:vb=\E[?5h\E[0q\E[1;2q\E[?5l\E[0q\E[4;3q:
+
+#### Morrow Designs
+# 
+# This was George Morrow's company.  They started in the late 1970s making
+# S100-bus machines.  They used to be reachable at:
+#
+#        Morrow
+#        600 McCormick St.
+#        San Leandro, CA 94577
+#
+# but they're long gone now (1995).
+#
+
+# The mt70 terminal was shipped with the Morrow MD-3 microcomputer. 
+# Jeff's specimen was dated June 1984.
+# From: Jeff Wieland <wieland@acn.purdue.edu> 24 Feb 1995
+mt70|mt-70|Morrow MD-70; native Morrow mode:\
+	:am:mi:ms:xo:\
+	:co#80:it#8:li#24:\
+	:%1=^AO\r:F1=^A`\r:F2=^Aa\r:F3=^Ab\r:F4=^Ac\r:F5=^Ad\r:\
+	:F6=^Ae\r:F7=^Af\r:F8=^Ag\r:F9=^Ah\r:FA=^Ai\r:\
+	:ac=+z\054{-x.yOi`|jGkFlEmDnHqJtLuKvNwMxI:ae=\E%:\
+	:al=\EE:as=\E$:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=^Z:\
+	:cm=\E=%+ %+ :cr=^M:ct=\E0:dc=\EW:dl=\ER:do=^J:ei=:ho=^^:\
+	:i1=\E"2\EG0\E]:ic=\EQ:im=:k1=^A@\r:k2=^AA\r:k3=^AB\r:\
+	:k4=^AC\r:k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:\
+	:k;=^AI\r:kB=^A^Z\r:kC=^An\r:kD=\177:kb=^H:kd=^AK\r:\
+	:kh=^AN\r:kl=^AL\r:kr=^AM\r:ku=^AJ\r:le=^H:mh=\EG2:mk@:\
+	:nd=^L:nw=^_:sf=^J:ta=^I:te=:ti=\E"2\EG0\E]:up=^K:us=\EG1:\
+	:vb=\EK1\EK0:ve=\E"2:vi=\E"0:\
+	:tc=adm+sgr:
+
+#### Motorola
+#
+
+# Motorola EXORterm 155	from {decvax, ihnp4}!philabs!sbcs!megad!seth via BRL
+# (Seth H Zirin)
+ex155|Motorola Exorterm 155:\
+	:am:bs:bw:\
+	:co#80:kn#5:li#24:\
+	:bt=\E[:cd=\ET:ce=\EU:cl=\EX:cm=\EE%+ %+ :do=\EB:ho=\E@:\
+	:kB=\E[:kC=\EX:kE=\EU:kS=\ET:kb=^H:kd=^J:kh=\E@:kl=^H:kr=^L:\
+	:ku=^K:nd=\ED:se=\Ec\ED:so=\Eb\ED:ta=\EZ:ue=\Eg\ED:\
+	:us=\Ef\ED:
+
+#### Omron
+#
+# This company is still around in 1995, manufacturing point-of-sale systems.
+
+omron|Omron 8025AG:\
+	:am:bs:da:db:\
+	:co#80:li#24:\
+	:al=\EL:bl=^G:cd=\ER:ce=\EK:cl=\EJ:cr=^M:dc=\EP:dl=\EM:do=^J:\
+	:ho=\EH:le=^H:nd=\EC:se=\E4:sf=\ES:so=\Ef:sr=\ET:up=\EA:\
+	:vs=\EN:
+
+#### Ramtek
+#
+# Ramtek was a vendor of high-end graphics terminals around 1979-1983; they
+# were competition for things like the Tektronics 4025.
+#
+
+# Ramtek 6221 from BRL, probably by Doug Gwyn
+# The following SET-UP modes are assumed for normal operation:
+#	UNDERLINE_CURSOR	ANSI_MODE	AUTO_XON/XOFF_ON
+#	NEWLINE_OFF		80_COLUMNS
+# Other SET-UP modes may be set for operator convenience or communication
+# requirements; I recommend
+#	SMOOTH_SCROLL	AUTO_REPEAT_ON	3_#_SHIFTED	WRAP_AROUND_ON
+# Hardware tabs are assumed to be every 8 columns; they can be set up by the
+# "reset", "tset", or "tabs" utilities (use rt6221-w, 160 columns, for this).
+# Note that the Control-E key is useless on this brain-damaged terminal.  No
+# delays are specified; use "stty ixon -ixany" to enable DC3/DC1 flow control!
+rt6221|Ramtek 6221 80x24:\
+	:bs:ms:pt:xo:\
+	:co#80:it#8:kn#4:li#24:vt#3:\
+	:DO=\E[%dB:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:ac=:ae=^O:as=^N:\
+	:bl=^G:cd=\E[J:ce=\E[K:cl=\E[1;1H\E[J:cm=\E[%i%d;%dH:\
+	:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:do=^K:ho=\E[1;1H:is=\E)0:\
+	:k0=\EOP:k1=\EOQ:k2=\EOR:k3=\EOS:kb=^H:kd=\E[B:ke=\E>:\
+	:kl=\E[D:kr=\E[C:ks=\E=:ku=\E[A:l0=PF1:l1=PF2:l2=PF3:l3=PF4:\
+	:le=^H:ll=\E[24;1H:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:\
+	:nd=\E[C:nw=\EE:\
+	:r1=\E[1w\E[>37m\E[>39m\E[1v\E[20l\E[?3l\E[?6l\E[>5h\E[>6h\E[>7h\E[>8l\E[>9h\E[>10l\E[1;24r\E[m\E[q\E(B\017\E)0\E#5\E>:\
+	:rc=\E8:sc=\E7:se=\E[m:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:\
+	:ue=\E[m:up=\EM:us=\E[4m:ve=\E[>5h\E[>9h:vi=\E[>5l:\
+	:vs=\E[>7h\E[>9l:
+# [TO DO: Check out: short forms of ho/cl and ll; reset (\Ec)].
+rt6221-w|Ramtek 6221 160x48:\
+	:co#160:li#48:\
+	:ll=\E[48;1H:tc=rt6221:
+
+#### RCA
+#
+
+# RCA VP3301 or VP3501
+rca|rca vp3301/vp3501:\
+	:bs:\
+	:co#40:li#24:\
+	:cl=^L:cm=\EY%+ %+ :ho=^Z:nd=^U:se=\E\ES0:so=\E\ES1:up=^K:
+
+
+#### Selanar
+#
+
+# Selanar HiREZ-100 from BRL, probably by Doug Gwyn
+# The following SET-UP modes are assumed for normal operation:
+#	SET_DEFAULT_TABS	48_LINES		80_COLUMNS
+#	ONLINE			ANSI			CURSOR_VISIBLE
+#	VT102_AUTO_WRAP_ON	VT102_NEWLINE_OFF	VT102_MONITOR_MODE_OFF
+#	LOCAL_ECHO_OFF		US_CHAR_SET		WPS_TERMINAL_DISABLED
+#	CPU_AUTO_XON/XOFF_ENABLED			PRINT_FULL_SCREEN
+# For use with graphics software, all graphics modes should be set to factory
+# default.  Other SET-UP modes may be set for operator convenience or
+# communication requirements.  No delays are specified; use "stty ixon -ixany"
+# to enable DC3/DC1 flow control!
+# I commented out the scrolling capabilities since they are too slow.
+hirez100|Selanar HiREZ-100:\
+	:bs:mi:ms:pt:xo:\
+	:co#80:it#8:kn#4:li#48:vt#3:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ac=:ae=^O:al=\E[L:as=^N:bl=^G:cd=\E[J:\
+	:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:ct=\E[3g:\
+	:dc=\E[P:dl=\E[M:do=^J:ho=\E[H:is=\E<\E)0:k0=\EOP:k1=\EOQ:\
+	:k2=\EOR:k3=\EOS:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:\
+	:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:l0=PF1:l1=PF2:l2=PF3:l3=PF4:\
+	:le=^H:ll=\E[48H:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:\
+	:nd=\E[C:nw=\EE:pf=\E[4i\E[?4i:po=\E[?5i\E[5i:ps=\E[i:\
+	:r1=\030\E2\E<\E[4i\E[?4i\E[12h\E[2;4;20l\E[?0;7h\E[?1;3;6;19l\E[r\E[m\E(B\017\E)0\E>:\
+	:rc=\E8:sc=\E7:se=\E[m:so=\E[7m:st=\EH:ta=^I:ue=\E[m:up=\EM:\
+	:us=\E[4m:
+hirez100-w|Selanar HiREZ-100 in 132-column mode:\
+	:co#132:tc=hirez100:
+
+#### Signetics
+#
+
+# From University of Wisconsin
+vsc|Signetics Vsc Video driver by RMC:\
+	:am:ms:\
+	:co#80:it#8:li#26:\
+	:ce=\E[K:cl=50\E[;H\E[2J:cm=\E[%i%d;%dH:cr=^M:do=^J:\
+	:ho=\E[H:kb=^H:kd=^J:kl=^H:le=^H:me=^_\041:mr=^_ :nd=\E[C:\
+	:nw=^M^J:se=^_\041:sf=^J:so=^_ :ta=^I:ue=^_#:up=\E[A:us=^_":
+
+#### Soroc
+#
+# Alan Frisbie <frisbie@flying-disk.com> writes:
+#
+# As you may recall, the Soroc logo consisted of their name,
+# with the letter "S" superimposed over an odd design.   This
+# consisted of a circle with a slightly smaller 15 degree (approx.)
+# wedge with rounded corners inside it.   The color was sort of
+# a metallic gold/yellow.
+# 
+# If I had been more of a beer drinker it might have been obvious
+# to me, but it took a clue from their service department to make
+# me exclaim, "Of course!"   The circular object was the top of
+# a beer can (the old removable pop-top style) and "Soroc" was an
+# anagram for "Coors".
+# 
+# I can just imagine the founders of the company sitting around
+# one evening, tossing back a few and trying to decide what to
+# call their new company and what to use for a logo.
+# 
+
+# (soroc120: removed obsolete ":ma=^K^P^R^L^L :" -- esr)
+soroc120|iq120|soroc|soroc iq120:\
+	:cd=\EY:ce=\ET:cl=\E*:do=^J:kd=^J:kl=^H:kr=^L:ku=^K:tc=adm3a:
+soroc140|iq140|soroc iq140:\
+	:am:bs:mi:\
+	:co#80:li#24:\
+	:al=\Ee:bl=^G:bt=\EI:cd=\Ey:ce=\Et:cl=\E+:cm=\E=%+ %+ :\
+	:cr=^M:dc=\Ew:dl=\Er:do=^J:ei=\E8:ho=^^:im=\E9:k0=^A0\r:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:k9=^AH\r:kb=^H:kh=^^:kr=^L:ku=^K:le=^H:\
+	:ll=^^^K:nd=^L:se=\E\177:sf=^J:so=\E\177:ue=\E^A:up=^K:\
+	:us=\E^A:
+
+#### Synertek
+#
+# Bob Manson <manson@pattyr.acs.ohio-state.edu> writes (28 Apr 1995):
+#
+# Synertek used to make ICs, various 6502-based single-board process
+# control and hobbyist computers, and assorted peripherals including a
+# series of small inexpensive terminals (I think they were one of the
+# first to have a "terminal-on-a-keyboard", where the terminal itself
+# was only slightly larger than the keyboard).
+#
+# They apparently had a KTM-1 model, which I've never seen. The KTM-2/40
+# was a 40x24 terminal that could connect to a standard TV through a
+# video modulator.  The KTM-2/80 was the 80-column version (the 2/40
+# could be upgraded to the 2/80 by adding 2 2114 SRAMs and a new ROM).
+# I have a KTM-2/80 still in working order.  The KTM-2s had fully
+# socketed parts, used 2 6507s, a 6532 as keyboard scanner, a program
+# ROM and 2 ROMs as character generators. They were incredibly simple,
+# and I've never had any problems with mine (witness the fact that mine
+# was made in 1981 and is still working great... I've blown the video
+# output transistor a couple of times, but it's a 2N2222 :-)
+#
+# The KTM-3 (which is what is listed in the terminfo file) was their
+# attempt at putting a KTM-2 in a box (and some models came with a
+# CRT). It wasn't much different from the KTM-2 hardware-wise, but the
+# control and escape sequences are very different. The KTM-3 was always
+# real broken, at least according to the folks I've talked to about it.
+# 
+# The padding in the entry is probably off--these terminals were very
+# slow (it takes like 100ms for the KTM-2 to clear the screen...) And
+# anyone with any sanity replaced the ROMs with something that provided
+# a reasonable subset of VT100 functionality, since the usual ROMs were
+# obviously very primitive... oh, you could get an upgraded ROM from
+# Synertek for some incredible amount of money, but what hacker with an
+# EPROM burner would do that? :)
+# 
+# Sorry I don't have any contact info; I believe they were located in
+# Sunnyvale, and I'm fairly sure they are still manufacturing ICs
+# (they've gone to ASICs and FPGAs), but I doubt they're in the computer
+# business these days.
+#
+
+# Tested, seems to work fine with vi.
+synertek|ktm|synertek380|synertek ktm 3/80 tubeless terminal:\
+	:am:\
+	:co#80:li#24:\
+	:cd=\EJ:ce=\EK:cl=^Z:cm=\E=%+ %+ :le=^H:nd=^L:up=^K:
+
+#### Tab Office Products
+#
+#	TAB Products Co. - Palo Alto, California
+#	Electronic Office Products,
+#	1451 California Avenue 94304
+#
+# I think they're out of business.
+#
+
+# The tab 132 uses xon/xoff, so no padding needed.
+# :ks:/:ke: have nothing to do with arrow keys.
+# :is: sets 80 col mode, normal video, autowrap on (for :am:).
+# Seems to be no way to get rid of status line.
+# The manual for this puppy was dated June 1981.  It claims to be VT52-
+# compatible but looks more vt100-like.
+tab132|tab|tab132-15|tab 132/15:\
+	:da:db:\
+	:co#80:dN@:li#24:lm#96:\
+	:al=\E[L:cm=\E[%i%d;%dH:dc=\E[P:dl=\E[M:do=^J:ei=\E[4l:\
+	:im=\E[4h:is=\E[?7h\E[?3l\E[?5l:kd=\E[B:ke@:kl=\E[D:ks@:\
+	:ku=\E[A:\
+	:tc=vt100:
+tab132-w|tab132 in wide mode:\
+	:co#132:\
+	:is=\E[?7h\E[?3h\E[?5l:tc=tab132:
+tab132-rv|tab132 in reverse-video mode:\
+	:is=\E[?7h\E[?3l\E[?5h:tc=tab132:
+tab132-w-rv|tab132 in reverse-video/wide mode:\
+	:is=\E[?7h\E[?3h\E[?5h:tc=tab132-w:
+
+
+#### Teleray
+#
+#	Research Incorporated
+#	6425 Flying Cloud Drive
+#	Eden Prairie, MN 55344
+#	Vox: (612)-941-3300
+#
+# The Teleray terminals were all discontinued in 1992-93.  RI still services
+# and repairs these beasts, but no longer manufactures them.  The Teleray
+# people believe that all the types listed below are very rare now (1995).
+# There was a newer line of Telerays (Model 7, Model 20, Model 30, and
+# Model 100) that were ANSI-compatible.
+#
+# Note two things called "teleray".  Reorder should move the common one
+# to the front if you have either.  A dumb teleray with the cursor stuck
+# on the bottom and no obvious model number is probably a 3700.
+#
+
+t3700|dumb teleray 3700:\
+	:bs:\
+	:co#80:li#24:\
+	:bl=^G:cl=^L:cr=^M:do=^J:le=^H:sf=^J:
+t3800|teleray 3800 series:\
+	:bs:\
+	:co#80:it#8:li#24:\
+	:bl=^G:cd=\EJ:ce=\EK:cl=^L:cm=\EY%+ %+ :cr=^M:do=^J:ho=\EH:\
+	:le=^H:ll=\EY7 :nd=\EC:sf=^J:ta=^I:up=^K:
+t1061|teleray|teleray 1061:\
+	:am:bs:km:xs:xt:\
+	:co#80:it#8:li#24:sg#1:\
+	:al=\EL:bl=^G:cd=\EJ:ce=\EK:cl=\014:cm=\EY%+ %+ :cr=^M:\
+	:ct=\EG:dc=\EQ:dl=\EM:do=^J:ei=:ho=\EH:ic=\EP:im=:ip=:\
+	:is=\Ee\EU01^Z1\EV\EU02^Z2\EV\EU03^Z3\EV\EU04^Z4\EV\EU05^Z5\EV\EU06^Z6\EV\EU07^Z7\EV\EU08^Z8\EV\Ef:\
+	:k1=^Z1:k2=^Z2:k3=^Z3:k4=^Z4:k5=^Z5:k6=^Z6:k7=^Z7:k8=^Z8:\
+	:le=^H:nd=\EC:se=\ER@:sf=^J:so= \ERD:st=\EF:ta=^I:ue=\ER@:\
+	:up=\EA:us=\ERH:
+t1061f|teleray 1061 with fast PROMs:\
+	:al=\EL:dl=\EM:ip@:tc=t1061:
+# "Teleray Arpa Special", officially designated as
+# "Teleray Arpa network model 10" with "Special feature 720".
+# This is the new (1981) fast microcode updating the older "arpa" proms
+# (which gave meta-key and programmable-fxn keys).  720 is much much faster,
+# converts the keypad to programmable function keys, and has other goodies.
+# Standout mode is still broken (magic cookie, etc) so is suppressed as no
+# programs handle such lossage properly.
+# Note: this is NOT the old termcap's "t1061f with fast proms."
+# From: J. Lepreau <lepreau@utah-cs> Tue Feb  1 06:39:37 1983, Univ of Utah
+# (t10: removed overridden ":so@:se@:us@:ue@:" -- esr)
+t10|teleray 10 special:\
+	:bs:km:xs:xt:\
+	:co#80:it#8:li#24:sg#2:\
+	:al=\EL:cd=\EJ:ce=\EK:cl=30\Ej:cm=\EY%+ %+ :dc=\EQ:dl=\EM:\
+	:ei=:ho=\EH:ic=\EP:im=:le=^H:nd=\EC:pc=\0:se=\ER@:sf=\Eq:\
+	:so=\ERD:sr=\Ep:ta=^I:ue=\ER@:up=\EA:us=\ERH:
+# teleray 16 - map the arrow keys for vi/rogue, shifted to up/down page, and
+# back/forth words. Put the function keys (f1-f10) where they can be
+# found, and turn off the other magic keys along the top row, except
+# for line/local. Do the magic appropriate to make the page shifts work.
+# Also toggle ^S/^Q for those of us who use Emacs.
+t16|teleray 16:\
+	:am:da:db:mi:xs:xt:\
+	:co#80:li#24:\
+	:al=\E[L:bl=^G:cd=\E[0J:ce=\E[0K:cl=\E[H\E[2J:\
+	:cm=%i\E[%d;%df:cr=^M:dc=\E[P:dl=\E[M:do=\E[B:ei=\E[4l:\
+	:ho=\E[H:im=\E[4h:k1=^Z1:k2=^Z2:k3=^Z3:k4=^Z4:k5=^Z5:k6=^Z6:\
+	:k7=^Z7:k8=^Z8:k9=^Z9:k;=^Z0:le=^H:me=\E[m:nd=\E[C:se=\E[m:\
+	:sf=^J:so=\E[7m:sr=\E[T:ta=^I:te=\E[V\E[24;1f\E[?38h:\
+	:ti=\E[U\E[?38l:ue=\E[m:up=\E[A:us=\E[4m:
+
+#### Texas Instruments (ti)
+#
+
+# The Silent 700 was so called because it was built around a quiet thermal
+# printer.  It was portable, equipped with an acoustic coupler, and pretty
+# neat for its day.
+ti700|ti733|ti735|ti745|ti800|ti silent 700/733/735/745 or omni 800:\
+	:bs:hc:os:\
+	:co#80:\
+	:bl=^G:cr=\r:do=^J:le=^H:sf=^J:
+
+#
+# Texas Instruments 916 VDT 7 bit control mode
+#
+ti916|ti916-220-7|Texas Instruments 916 VDT 8859/1 vt220 mode 7 bit CTRL:\
+	:da:db:in:ms:\
+	:%9=^X:@4=\E[29~:@8=^J:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:\
+	:DO=\E[%dB:F1=\E[29~:F2=\E[31~:IC=\E[%d@:LE=\E[%dD:\
+	:RI=\E[%dC:UP=\E[%dA:ae=\017:as=\016:bt=\E[Z:cb=\E[1K:\
+	:cd=\E[J:ce=\E[0K:ch=\E[%+^AG:cl=\E[H\E[2J:\
+	:cm=\E[%i%d;%dH:ct=\E[3g:cv=\E[%+^Ad:dc=\E[P:eA=\E(B\E)0:\
+	:ec=\E[%dX:ei=:ff=^L:im=:ip=:is=\E[1;24r\E[24;1H:k1=\E[17~:\
+	:k2=\E[18~:k3=\E[19~:k4=\E[20~:k5=\E[21~:k6=\E[23~:\
+	:k7=\E[24~:k8=\E[25~:k9=\E[26~:k;=\E[28~:kD=\E[P:kI=\E[@:\
+	:kN=\E[S:kP=\E[T:kh=\E[H:mp=\E&:r2=\E[\041p:st=\E[0W:\
+	:vb=\E[?5h\E[?5l:ve=\E[?25h:vi=\E[?25l:vs=\E[?25h:\
+	:tc=vt220:
+#
+# Texas Instruments 916 VDT 8 bit control mode
+#
+ti916-8|ti916-220-8|Texas Instruments 916 VDT 8859/1 8 vt220 mode bit CTRL:\
+	:%9=^X:@4=\23329~:@8=^J:F1=\23329~:F2=\23331~:k1=\23317~:\
+	:k2=\23318~:k3=\23319~:k4=\23320~:k5=\23321~:k6=\23323~:\
+	:k7=\23324~:k8=\23325~:k9=\23326~:k;=\23328~:kD=\233P:\
+	:kI=\233@:kN=\233S:kP=\233T:kd=\233B:kh=\233H:kl=\233D:\
+	:kr=\233C:ku=\233A:\
+	:tc=ti916:
+#
+# Texas Instruments 916 VDT 8859/1 7 bit control 132 column mode
+#
+ti916-132|Texas Instruments 916 VDT vt220 132 column:\
+	:co#132:tc=ti916:
+#
+# Texas Instruments 916 VDT 8859/1 8 bit control 132 column mode
+#
+ti916-8-132|Texas Instruments 916 VDT 8-bit vt220 132 column:\
+	:co#132:tc=ti916-8:
+ti924|Texas Instruments 924 VDT 8859/1 7 bit CTRL:\
+	:am:bs:xo:\
+	:co#80:it#8:li#24:\
+	:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:cl=\E[2J\E[H:\
+	:cm=%i\E[%d;%dH:cr=^M:cs=%i\E[%d;%dr:ct=\E[3g:dl=\E[M:\
+	:do=\E[B:ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\E[16~:\
+	:k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:kD=\E[P:kI=\E[@:\
+	:kb=^H:kd=\E[B:kl=\E[D:kr=\E[C:ku=\E[A:le=\E[D:mb=\E[5m:\
+	:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:rc=\E8:sc=\E7:se=\E[m:\
+	:sf=\ED:so=\E[7m:sr=\EM:st=\EH:ta=^I:ue=\E[m:up=\E[A:\
+	:us=\E[4m:ve=\E[?25h:vi=\E[?25l:vs=\E[?31h:
+ti924-8|Texas Instruments 924 VDT 8859/1 8 bit CTRL:\
+	:am:xo:\
+	:co#80:it#8:li#24:\
+	:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:cl=\E[2J\E[H:\
+	:cm=%i\E[%d;%dH:cr=^M:cs=%i\E[%d;%dr:ct=\E[3g:dl=\E[M:\
+	:do=\E[B:ho=\E[H:k1=P\217>:k2=Q\217>:k3=R\217>:k4=S\217>:\
+	:k5=~\23316>:k6=~\23317>:k7=~\23318>:k8=~\23319>:\
+	:k9=~\23320>:kD=P\233>:kI=@\233>:kb=^H:kd=\E[B:kl=\E[D:\
+	:kr=\E[C:ku=\E[A:le=\E[D:mb=\E[5m:md=\E[1m:me=\E[m:\
+	:mr=\E[7m:nd=\E[C:rc=\E8:sc=\E7:se=\E[m:sf=\ED:so=\E[7m:\
+	:sr=\EM:st=\EH:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:ve=\E[?25h:\
+	:vi=\E[?25l:vs=\E[?31h:
+ti924w|Texas Instruments 924 VDT 7 bit - 132 column mode:\
+	:co#132:tc=ti924:
+ti924-8w|Texas Instruments 924 VDT 8 bit - 132 column mode:\
+	:co#132:tc=ti924-8:
+ti931|Texas Instruments 931 VDT:\
+	:am:bs:xo:\
+	:co#80:li#24:\
+	:al=\EN:bl=^G:cd=\EJ:ce=\EI:cl=\EL:cm=\EY%+ %+ :cr=^M:\
+	:dc=\EQ:dl=\EO:do=\EB:ei=:ho=\EH:ic=\ER\EP\EM:im=:\
+	:is=\EGB\E(@B@@\E):k1=\Ei1:k2=\Ei2:k3=\Ei3:k4=\Ei4:\
+	:k5=\Ei5:k6=\Ei6:k7=\Ei7:k8=\Ei8:k9=\Ei9:kA=\EN:kD=\EQ:\
+	:kI=\EP:kL=\EO:kd=\EB:kl=\ED:kr=\EC:ku=\EA:le=\ED:mb=\E4P:\
+	:me=\E4@:mk=\E4H:mr=\E4B:nd=\EC:se=\E4@:sf=\Ea:so=\E4A:\
+	:sr=\Eb:ue=\E4@:up=\EA:us=\E4D:ve=\E4@:
+ti926|Texas Instruments 926 VDT 8859/1 7 bit CTRL:\
+	:cs@:sf=\E[1S:sr=\E[1T:tc=ti924:
+# (ti926-8: I corrected this from the broken SCO entry -- esr)
+ti926-8|Texas Instruments 926 VDT 8859/1 8 bit CTRL:\
+	:cs@:sf=\2331S:sr=\2331T:\
+	:tc=ti924-8:
+ti_ansi|basic entry for ti928:\
+	:am:eo:ut:xn:xo:\
+	:Co#8:co#80:it#8:li#25:pa#64:\
+	:@7=\E[F:AB=\E[4%p1%dm:AF=\E[3%p1%dm:al=\E[L:bl=^G:\
+	:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[2J\E[H:cm=\E[%i%d;%dH:\
+	:cr=^M:cs=\E[%i%d;%dr:dc=\E[P:dl=\E[M:do=\E[B:ei=:ho=\E[H:\
+	:ic=\E[@:im=:k0=\E[V:k1=\E[M:k2=\E[N:k3=\E[O:k4=\E[P:\
+	:k5=\E[Q:k6=\E[R:k7=\E[S:k8=\E[T:k9=\E[U:kN=\E[G:kP=\E[I:\
+	:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:\
+	:mb=\E[5m:md=\E[1m:me=\E[m:nd=\E[C:op=\E[37;40m:se=\E[m:\
+	:sf=\E[S:so=\E[7m:sr=\E[T:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:
+#
+#       928 VDT 7 bit control mode
+#
+ti928|Texas Instruments 928 VDT 8859/1 7 bit CTRL:\
+	:%9=\E[35~:@7=\E_1\E\:@8=\E[8~:F1=\E[29~:F2=\E[31~:\
+	:F3=\E[32~:F5=\E[34~:k1=\E[17~:k2=\E[18~:k3=\E[19~:\
+	:k4=\E[20~:k5=\E[21~:k6=\E[23~:k7=\E[24~:k8=\E[25~:\
+	:k9=\E[26~:k;=\E[28~:kD=\E[P:kI=\E[@:kN=\E[S:kP=\E[T:\
+	:tc=ti_ansi:
+#
+#       928 VDT 8 bit control mode
+#
+ti928-8|Texas Instruments 928 VDT 8859/1 8 bit CTRL:\
+	:%9=\23335~:@7=\2371\234:@8=\2338~:F1=\23329~:F2=\23331~:\
+	:F3=\23332~:F5=\23334~:k1=\23317~:k2=\23318~:k3=\23319~:\
+	:k4=\23320~:k5=\23321~:k6=\23323~:k7=\23324~:k8=\23325~:\
+	:k9=\23326~:k;=\23328~:kD=\233P:kI=\233@:kN=\233S:\
+	:kP=\233T:kh=\233H:\
+	:tc=ti_ansi:
+
+#### Zentec (zen)
+#
+
+# (zen30: removed obsolete :ma=^L ^R^L^K^P:.  This entry originally
+# had just :so:=\EG6 which I think means standout was supposed to be 
+# dim-reverse using ADM12-style attributes. ADM12 :us:/:ue: and
+# <invis> might work-- esr)
+zen30|z30|zentec 30:\
+	:am:bs:mi:ul:\
+	:co#80:li#24:\
+	:al=\EE:bl=^G:cd=\EY:ce=\ET:cl=\E*:cm=\E=%+ %+ :cr=^M:\
+	:dc=\EW:dl=\ER:do=^J:ei=\Er:ho=^^:im=\Eq:le=^H:mh=\EG2:nd=^L:\
+	:sf=^J:so=\EG6:ue@:up=^K:us@:\
+	:tc=adm+sgr:
+# (zen50: this had extension capabilities
+#	:BS=^U:CL=^V:CR=^B:
+# UK/DK/RK/LK/HM were someone's aliases for ku/kd/kl/kr/kh,
+# which were also in the original entry -- esr)
+# (zen50: removed obsolete ":ma=^Hh^Ll^Jj^Kk:" -- esr)
+zen50|z50|zentec zephyr:\
+	:am:bs:\
+	:co#80:li#24:sg#1:\
+	:al=\EE:cd=\EY:ce=\ET:cl=\E+:cm=\E=%+ %+ :dc=\EW:dl=\ER:ei=:\
+	:ic=\EQ:im=:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:mk@:ue@:up=^K:\
+	:us@:\
+	:tc=adm+sgr:
+
+# CCI 4574 (Office Power) from Will Martin <wmartin@BRL.ARPA> via BRL
+cci|cci1|z8001|zen8001|CCI Custom Zentec 8001:\
+	:am:bs:bw:\
+	:co#80:li#24:\
+	:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :cs=\ER%+ %+ :do=^J:\
+	:ho=\EH:is=\EM \EF\ET\EP\ER 7:kb=^H:kd=\EB:kh=\EH:kl=\ED:\
+	:kr=\EC:ku=\EA:le=^H:mb=\EM":me=\EM :mh=\EM\041:mk=\EM(:\
+	:mr=\EM$:nd=\EC:pf=^T:po=^R:se=\EM :so=\EM$:sr=\EI:ue=\EM :\
+	:up=\EA:us=\EM0:ve=\EP:vs=\EF\EQ\EM \ER 7:
+
+######## OBSOLETE UNIX CONSOLES
+#
+
+#### Altos
+#
+# Altos made a moderately successful line of UNIX boxes.  In 1990 they were
+# bought out by Acer, a major Taiwanese manufacturer of PC-clones.
+# Acer has a web site at http://www.acer.com.
+#
+# Altos descriptions from Ted Mittelstaedt <tedm@agora.rain.com> 4 Sep 1993
+# His comments suggest they were shipped with the system.
+#
+
+# (altos2: had extension capabilities
+#	:c0=^A`\r:c1=^Aa\r:c2=^Ab\r:c3=^Ac\r:\
+#	:c4=^Ad\r:c5=^Ae\r:c6=^Af\r:c7=^Ag\r:\
+#	:c8=^Ah\r:c9=^Ai\r:cA=^Aj\r:cB=^Ak\r:\
+#	:cC=^Al\r:cD=^Am\r:cE=^An\r:cF=^Ao\r:
+#	:XU=^Aq\r:XD=^Ar\r:XR=^As\r:XL=^At\r:\
+#	:YU=^AQ\r:YD=^AR\r:YR=^AS\r:YL=^AT\r:\
+#	:HL=^AP\r:SP=\E[i:\
+#	:IS=\E[@:DE=\E[P:IL=\E[L:NS=\E[S:PS=\E[T:\
+#	:LO=\E[0q:LC=\E[5q:LL=\E[6q:\
+# Comparison with the k* capabilities makes it obvious that the c* things are
+# shift keys.  I have renamed them to keys 32 and up accordingly.  Also,
+# :sr: was given as a boolean-- esr)
+altos2|alt2|altos-2|altos II:\
+	:co#80:it#8:li#24:sg#0:\
+	:*5=^Am\r:*8=^An\r:DL=\E[M:FM=^A`\r:FN=^Aa\r:FO=^Ab\r:\
+	:FP=^Ac\r:FQ=^Ad\r:FR=^Ae\r:FS=^Af\r:FT=^Ag\r:FU=^Ah\r:\
+	:FV=^Ai\r:FW=^Aj\r:FX=^Ak\r:RA=\E[?7l:SA=\E[?7h:al=\E[L:\
+	:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:\
+	:dc=\E[P:do=\E[1B:ei=:ho=\E[H:ic=\E[@:\
+	:if=/usr/share/tabset/vt100:im=:\
+	:is=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:k0=^AI\r:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:k9=^AH\r:kA=^AJ\r:kB=^AK\r:kC=^AL\r:\
+	:kD=^AM\r:kE=^AN\r:kF=^AO\r:kb=^H:kd=\E[B:kh=\E[f:kl=\E[D:\
+	:kr=\E[C:ku=\E[A:le=^H:me=\E[m:nd=\E[1C:nw=^M^J:se=\E[m:\
+	:sf=^J:so=\E[7m:ta=^I:ue=\E[m:up=\E[1A:us=\E[4m:
+# (altos3: had extension capabilities
+#	:c0=^A`\r:c1=^Aa\r:c2=^Ab\r:c3=^Ac\r:\
+#	:c4=^Ad\r:c5=^Ae\r:c6=^Af\r:c7=^Ag\r:\
+#	:c8=^Ah\r:c9=^Ai\r:cA=^Aj\r:cB=^Ak\r:\
+#	:cC=^Al\r:cD=^Am\r:cE=^An\r:cF=^Ao\r:
+#	:XU=^Aq\r:XD=^Ar\r:XR=^As\r:XL=^At\r:\
+#	:HL=^AP\r:SP=\E[i:\
+#	:IS=\E[@:DE=\E[P:IL=\E[L:NS=\E[S:PS=\E[T:\
+altos3|altos5|alt3|alt5|altos-3|altos-5|altos III or V:\
+	:mb=\E[5p:me=\E[p:sr=\EM:\
+	:tc=altos2:
+altos4|alt4|altos-4|altos IV:\
+	:tc=wy50:
+# (altos7: had extension capabilities:
+#	:GG#0:GI=\EH8:GF=\EH7:\
+#	:c0=^A`\r:c1=^Aa\r:c2=^Ab\r:c3=^Ac\r:\
+#	:c4=^Ad\r:c5=^Ae\r:c6=^Af\r:c7=^Ag\r:\
+#	:c8=^Ah\r:c9=^Ai\r:cA=^Aj\r:cB=^Ak\r:\
+#	:cC=^Al\r:cD=^Am\r:cE=^An\r:cF=^Ao\r:
+# Comparison with the k* capabilities makes it obvious that the c* things are
+# shift keys.  I have renamed them to keys 32 and up accordingly.  I have
+# also made this entry relative to adm12 in order to give it an :sa:. The
+# <invis> imported by use=adm+sgr may work, let me know. -- esr)
+altos7|alt7|altos VII:\
+	:am:mi:\
+	:co#80:li#24:sg#0:\
+	:*5=^Am\r:*8=^An\r:DL=\ER:FM=^A`\r:FN=^Aa\r:FO=^Ab\r:\
+	:FP=^Ac\r:FQ=^Ad\r:FR=^Ae\r:FS=^Af\r:FT=^Ag\r:FU=^Ah\r:\
+	:FV=^Ai\r:FW=^Aj\r:FX=^Ak\r:\
+	:ac=j5k3l2m1n8q\072t4u9v=w0x6:al=\EE:cd=\EY:ce=\ET:\
+	:cl=\E+^^:cm=\E=%+ %+ :cr=^M:dc=\EW:do=^J:ei=\Er:ho=^^:\
+	:im=\Eq:is=\E`\072\Ee(\EO\Ee6\Ec41\E~4\Ec21\Eu\E~2:\
+	:k0=^AI\r:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:\
+	:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:kA=^AJ\r:kB=^AK\r:\
+	:kC=^AL\r:kD=^AM\r:kE=^AN\r:kF=^AO\r:kN=\EK:kP=\EJ:kb=^H:\
+	:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:le=^H:mb=\EG2:md=\EGt:mh=\EGp:\
+	:mk=\EG1:nd=^L:nw=^M^J:pf=\EJ:po=\Ed#:sf=^J:sr=\Ej:ta=^I:\
+	:up=^K:\
+	:tc=adm+sgr:
+altos7pc|alt7pc|altos PC VII:\
+	:@7=\ET:tc=altos7:
+
+#### Apollo consoles
+#
+# Apollo got bought by Hewlett-Packard.  The Apollo workstations are 
+# labeled HP700s now.
+#
+
+# From: Gary Darland <goodmanc@garnet.berkeley.edu>
+apollo|apollo console:\
+	:am:bs:mi:\
+	:co#88:li#53:\
+	:al=\EI:cd=\EJ:ce=\EK:ch=\EN%d:cl=^L:cm=\EM%+ %d):cv=\EO+ :\
+	:dc=\EP:dl=\EL:do=\EB:ei=\ER:im=\EQ:le=^H:nd=\EC:se=\ET:\
+	:sf=\EE:so=\ES:sr=\ED:te=\EX:ti=\EW:ue=\EV:up=\EA:us=\EU:
+
+# We don't know whether or not the apollo guys replicated DEC's firmware bug
+# in the VT132 that reversed :ei:/:im:.  To be on the safe side, disable
+# both these capabilities.
+apollo_15P|apollo 15 inch display:\
+	:ei@:im@:tc=vt132:
+apollo_19L|apollo 19 inch display:\
+	:ei@:im@:tc=vt132:
+apollo_color|apollo color display:\
+	:ei@:im@:tc=vt132:
+
+#### Convergent Technology
+#
+# Burroughs bought Convergent shortly before it merged with Univac.
+# CTOS is (I believe) dead.  Probably the aws is too (this entry dates
+# from 1991 or earlier).
+#
+
+# Convergent AWS workstation from Gould/SEL UTX/32 via BRL
+# (aws: removed unknown :dn=^K: -- esr)
+aws|Convergent Technologies AWS workstation under UTX and Xenix:\
+	:am:\
+	:co#80:li#28:sg#0:\
+	:ac=:ae=\EAAF:al=\EIL:as=\EAAN:bc=^H:cd=\EEF:ce=\EEL:\
+	:ch=\EH%.:cl=^L:cm=\EC%r%.%.:cv=\EV%.:dc=\EDC:dl=\EDL:\
+	:do=^K:ei=:ic=\EIC:im=:kb=^H:kd=^K:kl=^N:kr=^R:ku=^A:\
+	:ma=\016h\013j\001k\022l\002m:nd=^R:nl=^J:se=\EARF:\
+	:sf=\ESU:so=\EARN:sr=\ESD:ue=\EAUF:up=^A:us=\EAUN:
+awsc|Convergent Technologies AWS workstation under CTOS:\
+	:am:\
+	:co#80:li#24:sg#0:\
+	:ac=:ae=\EAAF:as=\EAAN:bc=^N:cd=\EEF:ce=\EEL:cl=^L:\
+	:cm=\EC%r%.%.:do=^K:kb=^H:kd=^K:kl=^N:kr=^R:ku=^A:\
+	:ma=\016h\013j\001k\022l\002m:nd=^R:se=\EAA:so=\EAE:\
+	:ue=\EAA:up=^A:us=\EAC:
+
+#### DEC consoles
+#
+
+# The MicroVax console.  Tim Theisen <tim@cs.wisc.edu> writes:
+# The digital uVax II's had a graphic display called a qdss.  It was
+# supposed to be a high performance graphic accelerator, but it was
+# late to market and barely appeared before faster dumb frame buffers
+# appeared.  I have only used this display while running X11.  However,
+# during bootup, it was in text mode, and probably had a terminal emulator
+# within it.  And that is what your termcap entry is for.  In graphics
+# mode the screen size is 1024x864 pixels.
+qdss|qdcons|qdss glass tty:\
+	:am:bs:\
+	:co#128:li#57:\
+	:cl=1\032:cm=\E=%.%.:do=^J:le=^H:nd=^L:up=^K:
+
+#### Fortune Systems consoles
+#
+# Fortune made a line of 68K-based UNIX boxes that were pretty nifty
+# in their day; I (esr) used one myself for a year or so around 1984.
+# They had no graphics, though, and couldn't compete against Suns and
+# the like.  R.I.P.
+#
+
+# From: Robert Nathanson <c160-3bp@Coral> via tut   Wed Oct 5, 1983
+# (This had extension capabilities
+#	:rv=\EH:re=\EI:rg=0:GG=0:\
+#	:CO=\E\\:WL=^Aa\r:WR=^Ab\r:CL=^Ac\r:CR=^Ad\r:DL=^Ae\r:RF=^Af\r:\
+#	:RC=^Ag\r:CW=^Ah\r:NU=^Aj\r:EN=^Ak\r:HM=^Al:PL=^Am\r:\
+#	:PU=^An\r:PD=^Ao\r:PR=^Ap\r:HP=^A@\r:RT=^Aq\r:TB=\r:CN=\177:MP=\E+F:
+# It had both ":bs:" and ":bs=^H:"; I removed the latter.  Also, it had
+# ":sg=0:" and ":ug=0:"; evidently the composer was trying (unnecessarily)
+# to force both magic cookie glitches off.  Once upon a time, I
+# used a Fortune myself, so I know the capabilities of the form ^A[a-z]\r are
+# function keys; thus the "Al" value for HM was certainly an error.  I renamed
+# EN/PD/PU/CO/CF/RT according to the XENIX/TC mappings, but not HM/DL/RF/RC.  
+# I think :rv: and :re: are start/end reverse video and :rg: is a nonexistent
+# "reverse-video-glitch" capability; I have put :rv: and :re: in with standard
+# names below.  I've removed obsolete ":nl=5^J:" as there is a :do: -- esr)
+fos|fortune|Fortune system:\
+	:am:bs:bw:\
+	:co#80:li#25:\
+	:@7=^Ak\r:@8=^Aq:ac=j*k(l m"q&v%w#x-:ae=^O:al=\034E:\
+	:as=\Eo:bl=^G:cd=\034Y:ce=^\Z:cl=\014:cm=\034C%+ %+ :cr=^M:\
+	:dc=\034W:dl=\034R:do=\n:ei=:ho=\036:ic=\034Q:im=:is=^_..:\
+	:k1=^Aa\r:k2=^Ab\r:k3=^Ac\r:k4=^Ad\r:k5=^Ae\r:k6=^Af\r:\
+	:k7=^Ag\r:k8=^Ah\r:kN=^Ao\r:kP=^An\r:kb=^H:kd=^Ay\r:\
+	:kh=^A?\r:kl=^Aw\r:kr=^Az\r:ku=^Ax\r:le=^H:mb=\EN:me=\EI:\
+	:mr=\EH:nw=^M^J:se=^\I`:sf=^J:so=^\H`:ta=^Z:ue=^\IP:up=\013:\
+	:us=^\HP:ve=\E\:vi=\E]:vs=\E\072:
+
+#### IBM Unix consoles
+#
+
+# The following is a version of the ibm-pc entry distributed with PC/IX,
+# (Interactive Systems' System 3 for the Big Blue), modified by Richard
+# McIntosh at UCB/CSM.  The :pt: and :uc: have been removed from the original,
+# (the former is untrue, and the latter failed under UCB/man); standout and
+# underline modes have been added.  Note: this entry describes the "native"
+# capabilities of the PC monochrome display, without ANY emulation; most
+# communications packages (but NOT PC/IX connect) do some kind of emulation.
+pcix|PC/IX console:\
+	:am:bw:eo:\
+	:co#80:li#24:\
+	:cd=\E[J:ce=\E[K:cl=\Ec:cm=\E[%i%2;%2H:do=\E[B:ho=\E[H:\
+	:le=^H:me=\E[m:nd=\E[C:se=\E[m:so=\E[7m:ue=\E[m:up=\E[A:\
+	:us=\E[4m:
+
+# (ibmpcx: this entry used to be known as ibmx.
+# It formerly included the following extension capabilities:
+#	:GC=b:GL=v:GR=t:RT=^J:\
+#	:GH=\E[196g:GV=\E[179g:\
+#	:GU=\E[193g:GD=\E[194g:\
+#	:G1=\E[191g:G2=\E[218g:G3=\E[192g:G4=\E[217g:\
+#	:CW=\E[E:NU=\E[F:RF=\E[G:RC=\E[H:\
+#	:WL=\E[K:WR=\E[L:CL=\E[M:CR=\E[N:\
+# I renamed GS/GE/WL/WR/CL/CR/PU/PD/HM/EN; also, removed a duplicate
+# ":kh=\E[Y:".  Added IBM-PC forms characters and highlights, they match
+# what was there before. -- esr)
+ibmpcx|xenix|ibmx|IBM PC xenix console display:\
+	:am:bs:ms:\
+	:co#80:li#25:\
+	:@7=\E[d:al=\E[L:cd=\E[J:ce=\E[K:cl=^L:cm=\E[%d;%dH:\
+	:dc=\E[P:dl=\E[M:do=\E[B:ei=:ho=\E[H:ic=\E[@:im=:k1=\E[K:\
+	:k2=\E[L:k3=\E[M:k4=\E[N:kN=\E[e:kP=\E[Z:kb=^H:kd=\E[B:\
+	:kh=\E[Y:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:nd=\E[C:up=\E[A:\
+	:tc=klone+acs:tc=klone+sgr:
+
+
+#### Masscomp consoles
+#
+# Masscomp has gone out of business.  Their product line was purchased by
+# comany in Georgia (US) called "XS International", parts and service may
+# still be available through them.
+#
+
+# (masscomp: ":MT:" changed to ":km:";  -- esr)
+masscomp|masscomp workstation console:\
+	:bs:km:mi:\
+	:co#80:it#8:li#24:\
+	:al=\E[L:cd=\E[J:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:dc=\E[P:\
+	:dl=\E[M:do=\E[B:ei=\E[4l:im=\E[4h:is=\EGc\EGb\EGw:kb=^H:\
+	:kd=\EOB:kl=\EOD:kr=\EOC:ku=\EOA:le=^H:nd=\E[C:se=\E[m:\
+	:so=\E[7m:ta=^I:ue=\EGau:up=\E[A:us=\EGu:
+masscomp1|masscomp large screen version 1:\
+	:co#104:li#36:tc=masscomp:
+masscomp2|masscomp large screen version 2:\
+	:co#64:li#21:tc=masscomp:
+
+#### Sony NEWS workstations
+#
+
+# (news-unk: this had :KB=news: -- esr)
+news-unk|SONY NEWS vt100 emulator old common entry:\
+	:am:bs:pt:xn:\
+	:co#80:\
+	:AL=\E[%dL:DL=\E[%dM:al=\E[L:bl=^G:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
+	:dl=\E[M:do=^J:ho=\E[H:if=/usr/lib/tabset/vt100:\
+	:is=\E[?7h\E[?1l\E[?3l\E7\E8:k0=\EOY:k1=\EOP:k2=\EOQ:\
+	:k3=\EOR:k4=\EOS:k5=\EOT:k6=\EOU:k7=\EOV:k8=\EOW:k9=\EOX:\
+	:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:\
+	:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:\
+	:nl=^J:rc=\E8:rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[r:\
+	:sc=\E7:se=\E[m:so=\E[7m:sr=\EM:ta=^I:ue=\E[m:up=\E[A:\
+	:us=\E[4m:
+#
+# (news-29: this had :TY=ascii: --esr)
+news-29:\
+	:li#29:tc=news-unk:
+# (news-29-euc: this had :TY=euc: --esr)
+news-29-euc:\
+	:tc=news-29:
+# (news-29-sjis: this had :TY=sjis: --esr)
+news-29-sjis:\
+	:tc=news-29:
+#
+# (news-33: this had :TY=ascii: --esr)
+news-33:\
+	:li#33:tc=news-unk:
+# (news-33-euc: this had :TY=euc: --esr)
+news-33-euc:\
+	:tc=news-33:
+# (news-33-sjis: this had :TY=sjis: --esr)
+news-33-sjis:\
+	:tc=news-33:
+#
+# (news-42: this had :TY=ascii: --esr)
+news-42:\
+	:li#42:tc=news-unk:
+# (news-42-euc: this had :TY=euc: --esr)
+news-42-euc:\
+	:tc=news-42:
+# (news-42-sjis: this had :TY=sjis: --esr)
+news-42-sjis:\
+	:tc=news-42:
+#
+#	NEWS-OS old termcap entry 
+#
+# (news-old-unk: this had :KB=news:TY=sjis: --esr)
+news-old-unk|SONY NEWS vt100 emulator common entry:\
+	:am:bs:pt:xn:\
+	:co#80:vt#3:\
+	:bl=^G:cd=\E[J:ce=\E[K:cl=\E[;H\E[2J:cm=\E[%i%d;%dH:cr=^M:\
+	:cs=\E[%i%d;%dr:do=^J:ho=\E[H:if=/usr/lib/tabset/vt100:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:kb=^H:kd=\EOB:\
+	:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:\
+	:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:nd=\E[C:nl=^J:rc=\E8:\
+	:rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:sc=\E7:se=\E[m:\
+	:so=\E[7m:sr=\EM:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:
+#
+# (nwp512: this had :DE=^H:, which I think means :bs: --esr)
+nwp512|news|nwp514|news40|vt100-bm|old sony vt100 emulator 40 lines:\
+	:bs:\
+	:li#40:\
+	:is=\E7\E[r\E8\EE\EE\EE\EM\EM\EM\E[?7h\E[?1l\E[?3l\E7\E[1;40r\E8:tc=news-old-unk:
+#
+# (nwp512-a: this had :TY=ascii: and the alias vt100-bm --esr)
+nwp512-a|nwp514-a|news-a|news42|news40-a|sony vt100 emulator 42 line:\
+	:li#42:\
+	:is=\E[?7h\E[?1l\E[?3l\E7\E[1;42r\E8:tc=news-old-unk:
+#
+# (nwp-512-o: this had :KB=nwp410:DE=^H:  I interpret the latter as :bs:. --esr)
+nwp512-o|nwp514-o|news-o|news40-o|vt100-bm-o|sony vt100 emulator 40 lines:\
+	:bs:\
+	:li#40:\
+	:is=\E7\E[r\E8\EE\EE\EE\EM\EM\EM\E[?7h\E[?1l\E[?3l\E7\E[1;40r\E8:tc=news-old-unk:
+#
+# (nwp513: this had :DE=^H: and the alias vt100-bm --esr)
+nwp513|nwp518|nwe501|newscbm|news31|sony vt100 emulator 33 lines:\
+	:bs:\
+	:li#31:\
+	:is=\E7\E[r\E8\EE\EE\EE\EM\EM\EM\E[?7h\E[?1l\E[?3l\E7\E[1;31r\E8:tc=news-old-unk:
+#
+# (nwp513-a: this had :TY=ascii: and :DE=^H:, which I interpret as :bs:; --esr)
+# also the alias vt100-bm.
+nwp513-a|nwp518-a|nwe501-a|nwp251-a|newscbm-a|news31-a|newscbm33|news33|old sony vt100 emulator 33 lines:\
+	:bs:\
+	:li#33:\
+	:is=\E7\E[r\E8\EE\EE\EE\EM\EM\EM\E[?7h\E[?1l\E[?3l\E7\E[1;33r\E8:tc=news-old-unk:
+#
+# (nwp513-o: had :DE=^H:, I think that's :bs:; also the alias vt100-bm --esr)
+nwp513-o|nwp518-o|nwe501-o|nwp251-o|newscbm-o|news31-o|old sony vt100 emulator 33 lines:\
+	:bs:\
+	:li#31:\
+	:is=\E7\E[r\E8\EE\EE\EE\EM\EM\EM\E[?7h\E[?1l\E[?3l\E7\E[1;31r\E8:tc=news-old-unk:
+#
+# (news28: this had :DE=^H:, I think that's :bs:, and :KB=nws1200: --esr)
+news28|sony vt100 emulator 28 lines:\
+	:bs:\
+	:li#28:\
+	:is=\E7\E[r\E8\EE\EE\EE\EM\EM\EM\E[?7h\E[?1l\E[?3l\E7\E[1;28r\E8:tc=news-old-unk:
+#
+# (news29: this had :TY=ascii:KB=nws1200:\ --esr)
+news29|news28-a|sony vt100 emulator 29 lines:\
+	:li#29:\
+	:is=\E7\E[r\E8\EE\EE\EE\EM\EM\EM\E[?7h\E[?1l\E[?3l\E7\E[1;29r\E8:tc=news-old-unk:
+#
+# (news511: this had :TY=sjis: --esr)
+nwp511|nwp-511|nwp-511 vt100:\
+	:am:bs:pt:xn:\
+	:co#80:li#24:\
+	:al=\E[L:cd=30\E[J:ce=3\E[K:cl=20\E[;H\E[2J:\
+	:cm=\E[%i%d;%dH:dl=\E[M:is=\E[?5l\E[?1l\E>\E[?7h\E[?8h:\
+	:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\EOT:k6=\E#W:kd=\E[B:\
+	:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:nd=\E[C:\
+	:rs=\E7\E[r\E8\E[?5l\E[?1l\E>\E[?7h\E[?8h:se=2\E[m:\
+	:so=2\E[7m:sr=5\EM:ue=2\E[m:up=2\E[A:us=2\E[4m:\
+	:vb=\E[?5h\0\0\0\0\0\0\0\0\0\0\0\0\0\E[?5l:
+# (news517: this had :TY=sjis:. --esr)
+nwp517|nwp-517|nwp-517 vt200 80 cols 30 rows:\
+	:es:hs:\
+	:co#80:li#30:\
+	:ds=\E[1$~:fs=\E[0$}:i2=\E[2$~\n:\
+	:is=\E7\E[r\E8\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:\
+	:ts=\E[1$}\E[;%df:\
+	:tc=vt200:
+# (news517-w: this had :TY=sjis:. --esr)
+nwp517-w|nwp-517-w|nwp-517 vt200 132 cols 50 rows:\
+	:es:hs:\
+	:co#132:li#50:\
+	:ds=\E[1$~:fs=\E[0$}:i2=\E[2$~\n:\
+	:is=\E7\E[r\E8\E>\E[?3h\E[?4l\E[?5l\E[?7h\E[?8h:\
+	:rs=\E>\E[?3h\E[?4l\E[?5l\E[?7h\E[?8h:\
+	:ts=\E[1$}\E[;%df:tc=vt200:
+
+#### Obsolete virtual-terminal types.
+#
+
+# Columbus UNIX virtual terminal. This terminal also appears in 
+# UNIX 4.0 and successors as line discipline 1 (?), but is 
+# undocumented and does not really work quite right.
+cbunix|cb unix virtual terminal:\
+	:am:bs:da:db:\
+	:co#80:li#24:lm#0:\
+	:al=\EP:bl=^G:cd=\EL:ce=\EK:cl=\EL:cm=\EG%r%.%.:cr=^M:\
+	:dc=\EM:dl=\EN:do=^J:ei=:ic=\EO:im=:kd=\EB:kh=\EE:kl=\ED:\
+	:kr=\EC:ku=\EA:le=^H:nd=\EC:se=\Eb^D:sf=^J:so=\Ea^D:\
+	:ue=\Eb^A:up=\EA:us=\Ea^A:
+# (vremote: removed obsolete ":nl@:" -- esr)
+vremote|virtual remote terminal:\
+	:am@:\
+	:co#79:tc=cbunix:
+
+pty|4bsd pseudo teletype:\
+	:cm=\EG%+ %+ :se=\Eb$:so=\Ea$:ue=\Eb\041:us=\Ea\041:tc=cbunix:
+
+######## OTHER OBSOLETE TYPES
+#
+# These terminals are *long* dead -- these entries are retained for
+# historical interest only.
+#
+
+#### Obsolete non-ANSI software emulations
+#
+
+#### Avatar
+#
+# These entries attempt to describe Avatar, a terminal emulation used with
+# MS-DOS bulletin-board systems.  It was designed to give ANSI-like
+# capabilities, but with cheaper (shorter) control sequences.  Messy design,
+# excessively dependent on PC idiosyncracies, but apparently rather popular
+# in the BBS world.
+#
+# No color support.  Avatar doesn't fit either of the Tektronix or HP color
+# models that terminfo knows about.  An Avatar color attribute is the
+# low 7 bits of the IBM-PC display-memory attribute.  Bletch.
+#
+# I wrote these entries while looking at the Avatar spec.  I don't have
+# the facilities to test them.  Let me know if they work, or don't.
+#
+# Avatar escapes not used by these entries (because maybe you're smarter
+# and more motivated than I am and can figure out how to wrap terminfo
+# around some of them, and because they are weird enough to be funny):
+#				level 0:
+# ^L		-- clear window/reset current attribute to default
+# ^V^A%p1%c	-- set current color attribute, parameter decodes as follows:
+# 
+#      bit:         6   5   4   3   2   1   0
+#                   |       |   |   |       |
+#                   +---+---+   |   +---+---+
+#                       |       |       |
+#                       |       |  foreground color
+#                       |  foreground intensity
+#                  background color
+#				level 0+:
+# ^V^J%p1%c%p2%c%p3%c%p4%c%p5%c	-- scroll (p2,p3) to (p4,p5) up by p1 lines
+# ^V^K%p1%c%p2%c%p3%c%p4%c%p5%c	-- scroll (p2,p3) to (p4,p5) down by p1 lines
+# ^V^L%p1%c%p2%c%p3%c		-- clear p2 lines and p3 cols w/attr %p1 
+# ^V^M%p1%c%p2%c%p3%c%p4%c	-- fill p3 lines & p4 cols w/char p2+attr %p1 
+# (^V^L and ^V^M set the current attribute as a side-effect.)
+# ^V ^Y <a> [...] <c>	-- repeat pattern. <a> specifies the number of bytes
+#			   in the pattern, <c> the number of times the pattern
+#		  	   should be repeated. If either value is 0, no-op.
+#			   The pattern can contain Avatar console codes,
+#			   including other ^V ^Y patterns.
+#				level 1:
+# ^V^O		-- clockwise mode on; turn print direction right each time you
+#		   hit a window edge (yes, really).  Turned off by CR
+# ^V^P		-- no-op
+# ^V^Q%c	-- query the driver
+# ^V^R		-- driver reset
+# ^V^S		-- Sound tone (PC-specific)
+# ^V^T			-- change highlight at current cursor poition to %c
+# ^V^U%p1%c%p2%c	-- highlight window <a> with attribute <b>
+# ^V^V%p1%c%p2%c%p3%c%p4%c%p5%c
+#			-- define window 
+#
+# From: Eric S. Raymond <esr@snark.thyrsus.com> 1 Nov 1995
+# (The :mb:/:md:/:mr:/:as:/:us:/:so: capabilities exist only to
+# tell ncurses that the corresponding highlights exist; it should use :sa:,
+# which is the only method that will actually work for multiple highlights.)
+avatar0|avatar terminal emulator level 0:\
+	:am:ms:ut:\
+	:co#80:it#8:li#25:\
+	:as=:ce=^V^G:cm=\026\010%.%.:cr=^M:do=^V^D:le=^V^E:\
+	:mb=^A^V\177:md=^V^A^P:me=^V^A^G:mk=^V^A\0:mr=^A^Vp:\
+	:nd=^V^F:r2=^L:rp=\031%.%d:\
+	:..sa=\026\001%{0}%?%p1%t%{112}%|%;%?%p2%t%{1}%|%;%?%p3%t%{112}%|%;%?%p4%t{128}%|%;%?%p6%t%{16}%|%;:\
+	:sf=^J:so=^A^Vp:up=^V^C:us=^V^A:\
+	:tc=klone+acs:
+# From: Eric S. Raymond <esr@snark.thyrsus.com> 1 Nov 1995
+avatar0+|avatar terminal emulator level 0+:\
+	:dc=^V^N:ei=\026\n\0\0\0\0:im=^V^I:tc=avatar0:
+# From: Eric S. Raymond <esr@snark.thyrsus.com> 1 Nov 1995
+avatar|avatar1|avatar terminal emulator level 1:\
+	:RA=^V":SA=^V$:al=^V+:dl=^V-:ei=^V^P:ve=^V'^A:vi=^V'^B:\
+	:vs=^V^C:\
+	:tc=avatar0+:
+
+#### RBcomm
+#
+# RBComm is a lean and mean terminal emulator written by the Interrupt List
+# maintainer, Ralf Brown. It was fairly popular in the late DOS years (early
+# '90s), especially in the BBS world, and still has some loyal users due to
+# its very small memory footprint and to a cute macro language.
+rbcomm|IBM PC with RBcomm and EMACS keybindings:\
+	:am:bw:mi:ms:xn:\
+	:co#80:it#8:li#25:\
+	:AL=\E[%dL:DL=\E[%dM:al=^K:bl=^G:bt=\E[Z:cd=^F5:ce=^P^P:\
+	:cl=^L:cm=\037%r%+ %+ :cr=^M:cs=\E[%i%d;%dr:dc=^W:dl=^Z:\
+	:dm=:do=^C:ec=\E[%dX:ed=:ei=^]:im=^\:\
+	:is=\017\035\E(B\E)0\E[?7h\E[?3l\E[>8g:kb=^H:kd=^N:\
+	:ke=\E>:kh=^A:kl=^B:kr=^F:ks=\E=:ku=^P:le=^H:mb=\E[5m:\
+	:md=\E[1m:me=\E[m:mk=\E[8m:mr=^R:nd=^B:nw=^M\ED:\
+	:r1=\017\E(B\E)0\025\E[?3l\E[>8g:rc=\E8:rp=\030%.%.:\
+	:sc=\E7:se=^U:sf=\ED:so=^R:sr=\EM:ta=^I:te=:ti=:ue=^U:up=^^:\
+	:us=^T:ve=\E[?25h:vi=\E[?25l:vs=\E[?25h:
+rbcomm-nam|IBM PC with RBcomm without autowrap:\
+	:am@:\
+	:bl=^G:cr=^M:do=^J:\
+	:is=\017\035\E(B\E)0\E[?7l\E[?3l\E[>8g:kb=^H:kd=^J:\
+	:kl=^H:nw=^M^J:sf=^J:ta=^I:\
+	:tc=rbcomm:
+rbcomm-w|IBM PC with RBcomm in 132 column mode:\
+	:co#132:\
+	:bl=^G:cr=^M:do=^J:\
+	:is=\017\035\E(B\E)0\E[?7h\E[?3h\E[>8g:kb=^H:kd=^J:\
+	:kl=^H:nw=^M^J:sf=^J:ta=^I:\
+	:tc=rbcomm:
+
+# CTRM terminal emulator
+# 1. underlining is not allowed with colors: first, is is simulated by 
+# black on white, second, it disables background color manipulations.
+# 2. BLINKING, REVERSE and BOLD are allowed with colors,
+# so we have to save their status in the static registers A, B and H
+# respectively, to be able to restore them when color changes
+# (because any color change turns off ALL attributes)
+# 3. :md: and :mr: sequences alternate modes,
+# rather then simply  entering them.  Thus we have to check the
+# static register B and H to determine the status, before sending the 
+# escape sequence.
+# 4. :me: now must set the status of all 3 register (A,B,H) to zero
+# and then reset colors
+# 5. implementation of the protect mode would badly penalize the performance.
+# we would have to use \E&bn sequence to turn off colors (as well as all
+# other attributes), and keep the status of protect mode in yet another
+# static variable.  If someone really needs this mode, they would have to
+# create another terminfo entry.
+# 6. original color-pair is white on black.
+# store the information about colors into static registers
+# 7. set foreground color.  it performs the following steps.
+#   1) turn off all attributes
+#   2) turn on the background and video attributes that have been turned
+#      on before (this information is stored in static registers X,Y,Z,A,B,H,D).
+#   3) turn on foreground attributes
+#   4) store information about foreground into U,V,W static registers
+# 8. turn on background: similar to turn on foreground above
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+ctrm|C terminal emulator:\
+	:am:ut:xo:\
+	:Co#8:NC#2:Nl#0:co#80:lh#0:li#24:lm#0:lw#0:pa#63:pb#19200:vt#6:\
+	:al=\EL:bl=^G:bt=\Ei:cd=\EJ:ce=\EK:ch=\E&a%dC:cl=\EH\EJ:\
+	:cm=\E&a%r%dc%dY:cr=^M:ct=\E3:cv=\E&a%dY:dc=\EP:dl=\EM:\
+	:do=^J:ei=\ER:im=\EQ:ip=:is=\E&jA\r:k1=\Ep\r:k2=\Eq\r:\
+	:k3=\Er\r:k4=\Es\r:k5=\Et\r:k6=\Eu\r:k7=\Ev\r:k8=\Ew\r:\
+	:kb=^H:kd=\Ew\r:ke=\E&jA:kh=\Ep\r:kl=\Eu\r:kr=\Ev\r:\
+	:ks=\E&jB:ku=\Et\r:le=^H:mb=\E&dA%{1}%PA:\
+	:md=%?%gH%{0}%=%t\E&dH%{1}%PH%;:\
+	:me=\E&d@%{0}%PA%{0}%PB%{0}%PH:\
+	:mr=%?%gB%{0}%=%t\E&dB%{1}%PB%;:nd=\EC:\
+	:op=\E&bn\E&bB\E&bG\E&bR%{0}%PX%{0}%PY%{0}%PZ%{1}%PW%{1}%PV%{1}%PU:\
+	:sf=^J:so=\E&dD:st=\E1:ta=\011:up=\EA:us=\E&dD:
+
+# gs6300 - can't use blue foreground, it clashes with underline;
+# it's simulated with cyan
+# Bug: The <op> capability probably resets attributes.
+# (gs6300: commented out <rmln> (no <smln>) --esr)
+gs6300|emots|AT&T PC6300 with EMOTS terminal emulator:\
+	:am:ms:ut:xo:\
+	:Co#8:co#80:it#8:li#24:pa#63:\
+	:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\
+	:LE=\E[%dD:RI=\E[%dC:Sb=\E[?;%dm:\
+	:..Sf=\E[?%?%p1%{0}%=%t0%e%p1%{1}%=%t2%e%p1%{1}%-%d%;m:\
+	:UP=\E[%dA:\
+	:ac=++\054\054--..``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=\E[10m:al=\E[L:as=\E[11m:bl=^G:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:dc=\E[P:dl=\E[M:do=^J:\
+	:ei=:ho=\E[H:ic=\E[@:im=:is=\E[m:k1=\E[0s:k2=\E[24s:\
+	:k3=\E[1s:k4=\E[23s:k5=\E[2s:k6=\E[22s:k7=\E[3s:k8=\E[21s:\
+	:kB=^R^I:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\
+	:le=^H:mb=\E[5m:md=\E[1m:me=\E[m\E[10m:mr=\E[7m:nd=\E[C:\
+	:op=\E[?;m:pf=\E[4i:po=\E[5i:r1=\Ec:sf=^J:so=\E[1m:sr=\E[L:\
+	:ta=^I:up=\E[A:us=\E[4m:
+
+# From: <earle@smeagol.UUCP> 29 Oct 85 05:40:18 GMT
+# MS-Kermit with Heath-19 emulation mode enabled
+# (h19k: changed ":pt@:" to ":it@"
+h19k|h19kermit|heathkit emulation provided by Kermit (no auto margin):\
+	:am@:da:db:xt:\
+	:it@:\
+	:ta@:tc=h19-u:
+
+# Apple Macintosh with Versaterm, a terminal emulator distributed by Synergy
+# Software (formerly Peripherals Computers & Supplies, Inc) of
+# 2457 Perkiomen Ave., Reading, PA 19606, 1-800-876-8376.  They can
+# also be reached at support@synergy.com.
+versaterm|versaterm vt100 emulator for the macintosh:\
+	:am:xn:\
+	:co#80:it#8:li#24:\
+	:al=9\E[1L:bl=^G:cd=50\E[J:ce=3\E[K:cl=50\E[;H\E[2J:\
+	:cm=5\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:dc=7\E[1P:\
+	:dl=9\E[1M:do=^J:ei=:ho=\E[H:ic=7\E[1@:im=:\
+	:is=\E[1;24r\E[24;1H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+	:kb=^H:kd=\EOB:ke=\E>\E[?1l:kl=\EOD:kr=\EOC:ks=\E=\E[?1h:\
+	:ku=\EOA:le=^H:mb=2\E[5m:md=2\E[1m:me=2\E[m:mr=2\E[7m:\
+	:nd=2\E[C:nw=^M^J:r1=\E>:rc=\E8:\
+	:rf=/usr/share/tabset/vt100:sc=\E7:se=2\E[m:so=2\E[7m:\
+	:sr=5\EM:ta=^I:ue=2\E[m:up=2\E[A:us=2\E[4m:
+
+# From: Rick Thomas <ihnp4!btlunix!rbt>
+# (xtalk: I added <rmam>/<smam> based on the init string.
+xtalk|IBM PC with xtalk communication program (versions up to 3.4):\
+	:am:mi:ms:xo:\
+	:co#80:it#8:li#24:sg#1:vt#3:\
+	:@8=\EOM:DO=\E[%dB:K1=\EOq:K2=\EOr:K3=\EOs:K4=\EOp:K5=\EOn:\
+	:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:UP=\E[%dA:\
+	:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
+	:ae=^O:al=\E[L:as=^N:bl=^G:cb=\E[1K:cd=\E[J:ce=\E[K:\
+	:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:ct=\E[3g:dl=\E[M:do=^J:\
+	:eA=\E(B\E)0:ho=\E[H:k0=\EOy:k1=\EOP:k2=\EOQ:k3=\EOR:\
+	:k4=\EOS:k5=\EOt:k6=\EOu:k7=\EOv:k8=\EOl:k9=\EOw:k;=\EOx:\
+	:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:\
+	:ku=\EOA:le=^H:me=\E[m:nd=\E[C:\
+	:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:se=\E[m :sf=^J:\
+	:so=\E[7m :sr=\EM:st=\EH:ta=^I:up=\E[A:
+
+# The official PC terminal emulator program of the AT&T Product Centers.
+# Note - insert mode commented out - doesn't seem to work on AT&T PC.
+simterm|attpc running simterm:\
+	:am:\
+	:co#80:li#24:\
+	:al=\EL:bl=^G:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\E=%+ %+ :cr=^M:\
+	:dc=\ER:dl=\EM:do=\EB:ho=\EH:le=^H:me=\E&d@:nd=\EC:se=\E&d@:\
+	:sf=^J:so=\E&dB:te=\EVE:ti=\EVS:up=\EA:
+
+#### Miscellaneous obsolete terminals, manufacturers unknown
+#
+# If you have any information about these (like, a manufacturer's name, 
+# and a date on the serial-number plate) please send it!
+
+cad68-3|cgc3|cad68 basic monitor transparent mode size 3 chars:\
+	:am:bs:\
+	:co#73:li#36:\
+	:cl=^Z:ho=^^:le=^H:nd=^L:up=^K:
+cad68-2|cgc2|cad68 basic monitor transparent mode size 2 chars:\
+	:am:bs:\
+	:co#85:li#39:\
+	:cl=^Z:ho=^^:k1=\E5:k2=\E6:k3=\E7:k4=\E8:kd=\E2:kl=\E3:\
+	:kr=\E4:ku=\E1:le=^H:nd=^L:se=\Em^C:so=\Em^L:up=^K:
+cops10|cops|cops-10|cops 10:\
+	:am:bw:\
+	:co#80:li#24:\
+	:bl=^G:cd=^W:ce=^V:cl=30\030:cm=\020%+ %+ :cr=^M:do=^J:\
+	:kb=^H:kd=^J:kh=^Y:kl=^H:kr=^L:ku=^K:le=^H:nd=^L:sf=^J:up=^K:
+# (d132: removed duplicate :ic=\E5:,
+# merged in capabilities from a BRL entry -- esr)
+d132|datagraphix|datagraphix 132a:\
+	:da:db:in:\
+	:co#80:li#30:\
+	:al=\E3:bl=^G:cl=^L:cm=\E8%i%3%3:cr=^M:dc=\E6:do=^J:ei=:\
+	:ho=\ET:ic=\E5:im=:kb=^H:kd=^J:kl=^H:le=^H:nd=\EL:nw=^M^J:\
+	:sf=^J:sr=\Ew:ta=^I:up=\EK:ve=\Em\En:vs=\Ex:
+# The d800 was an early portable terminal from c.1984-85 that looked a lot
+# like the original Compaq `lunchbox' portable (but no handle).  It had a vt220
+# mode (which is what this entry looks like) and several other lesser-known
+# emulations.
+d800|Direct 800/A:\
+	:am:bs:da:db:ms:xs:\
+	:co#80:it#8:li#24:\
+	:ac=``a1fxgqh0jYk?lZm@nEooppqDrrsstCu4vAwBx3yyzz{{||}}~~:\
+	:ae=\E[m:as=\E[1m:bl=^G:cd=\E[J:ce=\E[K:cl=\E[1;1H\E[2J:\
+	:cm=\E[%i%d;%dH:cr=^M:do=^J:k1=\EOP:k2=\EOQ:k3=\EOR:\
+	:k4=\EOS:k5=\EOT:k6=\EOU:k7=\EOV:k8=\EOW:kd=\E[B:kl=\E[D:\
+	:kr=\E[C:ku=\E[A:le=^H:me=\E[m:nd=\E[C:se=\E[m:sf=\ED:\
+	:so=\E[7m:sr=\EM:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:ve=\E[>12h:\
+	:vs=\E[>12l:
+digilog|digilog 333:\
+	:bs:\
+	:co#80:li#16:\
+	:bl=^G:ce=^X:cr=^M:do=^J:ho=^N:le=^H:nd=^I:sf=^J:up=^O:
+# The DWK was a terminal manufactured in the Soviet Union c.1986
+dwk|dwk-vt|dwk terminal:\
+	:am:\
+	:co#80:it#8:li#24:\
+	:ac=+\136\054Q-S.M0\177`+a\072f'g#h#i#jXkClJmFnNo~qUs_tEuPv\wKxW~_:\
+	:ae=\EG:as=\EF:bl=^G:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :\
+	:cr=^M:dc=\EP:do=^J:ei=:ho=\EH:ic=\EQ:im=:k1=\Ef1:k2=\Ef2:\
+	:k3=\Ef3:k4=\Ef4:k5=\Ef5:k6=\Ef6:k7=\Ef7:k8=\Ef8:k9=\Ef9:\
+	:k;=\Ef0:kD=\Ee:kI=\Ed:kN=\Eh:kP=\Eg:kb=\177:kd=\EB:kl=\ED:\
+	:kr=\EC:ku=\EA:le=^H:me=\EX:mr=\ET:nd=\EC:nw=^M^J:se=\EX:\
+	:sf=^J:so=\ET:sr=\ES:ta=^I:up=\EA:
+env230|envision230|envision 230 graphics terminal:\
+	:xn@:\
+	:pf=\E[4i:po=\E[5i:ps=\E[0i:\
+	:..sa=\E[%?%p1%t;1%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;m:tc=vt100:
+# These execuports were impact-printer ttys with a 30- or maybe 15-cps acoustic
+# coupler attached, the whole rig fitting in a suitcase and more or less
+# portable.  Hot stuff for c.1977 :-) -- esr
+ep48|ep4080|execuport 4080:\
+	:am:bs:os:\
+	:co#80:\
+	:bl=^G:cr=^M:do=^J:hd=^\:hu=^^:le=^H:sf=^J:
+ep40|ep4000|execuport 4000:\
+	:co#136:tc=ep4080:
+# Adam Thompson <athompso@pangea.ca> tells us:
+# Informer series - these are all portable units, resembling older
+# automatic bread-baking machines.  The terminal looks like a `clamshell'
+# design, but isn't.  The structure is similar to the Direct terminals,
+# but only half the width.  The entire unit is only about 10" wide.
+# It features an 8" screen (6" or 7" if you have color!), and an 9"x6"
+# keyboard.  All the keys are crammed together, much like some laptop
+# PCs today, but perhaps less well organized...all these units have a
+# bewildering array of plugs on the back, including a built-in modem.
+# The 305 was a color version of the 304; the 306 and 307 were mono and
+# color terminals built for IBM bisync protocols.
+# From: Paul Leondis <unllab@amber.berkeley.edu>
+ifmr|Informer D304:\
+	:am:bs:\
+	:co#80:li#24:\
+	:cd=\E/:ce=\EQ:cl=\EZ:cm=\EY%r%+ %+ :dc=\E\:do=^J:ei=:\
+	:ho=\EH:ic=\E[:im=:le=^H:me=\EK:nd=\EC:se=\EK:so=\EJ:sr=\En:\
+	:up=\EA:
+# Entry largely based on wy60 and has the features of wy60ak.
+# (untranslatable capabilities removed to fit entry within 1023 bytes)
+# (sgr removed to fit entry within 1023 bytes)
+# (terminfo-only capabilities suppressed to fit entry within 1023 bytes)
+opus3n1+|Esprit Opus3n1+ in wy60 mode with ANSI arrow keys:\
+	:am:bw:hs:km:mi:ms:ul:xo:\
+	:co#80:li#24:ws#80:\
+	:ae=\EH^C:al=\EE:as=\EH^B:bl=^G:bt=\EI:cd=\EY:ce=\ET:cl=\E*:\
+	:cm=\Ea%i%dR%dC:cr=^M:ct=\E0:dc=\EW:dl=\ER:do=^J:ds=\Ez(\r:\
+	:ei=\Er:fs=^M:ho=\036:if=/usr/share/tabset/std:im=\Eq:ip=:\
+	:is=\E`\072\Ee(\EO\Ee6\Ec41\E~4\Ec21\Ed/\Ezz&\E[A\177\Ezz'\E[B\177\Ezz(\E[D\177\Ezz)\E[C\177\Ezz<\E[Q\177\Ezz`\E[F\177\EA1*\EZH12:\
+	:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\
+	:k7=^AF\r:k8=^AG\r:k9=^AH\r:kD=\EW:kI=\EQ:kN=\EK:kP=\EJ:\
+	:kb=^H:kd=\E[B:kh=^^:kl=\E[D:kr=\E[C:ku=\E[A:le=^H:mb=\EG2:\
+	:me=\E(\EH\003\EG0\EcD:mh=\EGp:nd=^L:nw=\r\n:sf=^J:sr=\Ej:\
+	:st=\E1:ta=\011:te=:\
+	:ti=\Ezz&\E[A\177\Ezz'\E[B\177\Ezz(\E[D\177\Ezz)\E[C\177\Ezz<\E[Q\177:\
+	:ts=\Ez(:uc=\EG8%p1%c\EG0:up=^K:ve=\E`1:vi=\E`0:\
+	:tc=adm+sgr:
+teletec|Teletec Datascreen:\
+	:am:bs:\
+	:co#80:li#24:\
+	:bl=^G:cl=^L:cr=^M:do=^J:ho=^^:le=^H:nd=^_:sf=^J:up=^K:
+# From: Mark Dornfeld <romwa@ucbvax.berkeley.edu>
+# This description is for the LANPAR Technologies VISION 3220
+# terminal from 1984/85.  The function key definitions k0-k5 represent the
+# edit keypad: FIND, INSERT HERE, REMOVE, SELECT, PREV SCREEN,
+# NEXT SCREEN. The key definitions k6-k9 represent the PF1 to PF4 keys.
+#
+# Kenneth Randell <kenr@datametrics.com> writes on 31 Dec 1998:
+# I had a couple of scopes (3221) like this once where I used to work, around
+# the 1987 time frame if memory serves me correctly.  These scopes were made  
+# by an outfit called LANPAR Technologies, and were meant to me DEC VT 220
+# compatible.  The 3220 was a plain text terminal like the VT-220, the 3221
+# was a like the VT-240 (monochrome with Regis + Sixel graphics), and the 3222
+# was like the VT-241 (color with Regis + Sixel Graphics).  These terminals
+# (3221) cost about $1500 each, and one was always broken -- had to be sent
+# back to the shop for repairs.
+# The only real advantage these scopes had over the VT-240's were:
+# 1) They were faster in the Regis display, or at least the ones I did
+# 2) They had a handy debugging feature where you could split-screen the
+# scope, the graphics would appear on the top, and the REGIS commands would
+# appear on the bottom.  I don't remember the VT-240s being able to do that.
+# I would swear that LANPAR Technologies was in MA someplace, but since I
+# don't work at the same place anymore, and those terminals and manuals were
+# long since junked, I cannot be any more sure than that.
+#
+# (v3220: removed obsolete ":kn#10:",
+# I added <rmam>/<smam> based on the init string -- esr)
+v3220|LANPAR Vision II model 3220/3221/3222:\
+	:am:bs:mi:xn:\
+	:co#80:it#8:li#24:\
+	:RA=\E[?7l:SA=\E[?7h:al=\E[L:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
+	:cm=\E[%i%d;%dH:dc=\E[P:dl=\E[M:ei=\E[4l:im=\E[4h:\
+	:is=\E>\E[?3l\E[?7h\E[?8h\E[p:k0=\E[1~:k1=\E[2~:\
+	:k2=\E[3~:k3=\E[4~:k4=\E[5~:k5=\E[6~:k6=\E[OP:k7=\E[OQ:\
+	:k8=\E[OR:k9=\E[OS:kd=\E[B:ke=\E>:kh=\E[H:kl=\E[D:kr=\E[C:\
+	:ks=\E=:ku=\E[A:le=^H:me=\E[m:nd=\E[C:se=\E[m:so=\E[7m:\
+	:sr=\EM:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:
+######## ICH/ICH1 VERSUS RMIR/SMIR
+#
+# Some non-curses applications get confused if both ich/ich1 and rmir/smir
+# are present; the symptom is doubled characters in an update using insert.
+# These applications are technically correct; in both 4.3BSD termcap and
+# terminfo, you're not actually supposed to specify both ich/ich1 and rmir/smir
+# unless the terminal needs both.  To my knowledge, no terminal still in this
+# file requires both other than the very obsolete dm2500.
+#
+# For ncurses-based applications this is not a problem, as ncurses uses
+# one or the other as appropriate but never mixes the two.  Therefore we
+# have not corrected entries like `linux' and `xterm' that specify both.
+# If you see doubled characters from these, use the linux-nic and xterm-nic
+# entries that suppress ich/ich1.  And upgrade to ncurses!
+#
+
+######## VT100/ANSI/ISO 6429/ECMA-48/PC-TERM TERMINAL STANDARDS
+#
+# ANSI X3.64 has been withdrawn and replaced by ECMA-48.  The ISO 6429 and
+# ECMA-48 standards are said to be almost identical, but are not the same
+# as X3.64 (though for practical purposes they are close supersets of it).
+#
+# You can obtain ECMA-48 for free by sending email to helpdesk@ecma.ch
+# requesting the standard(s) you want (i.e. ECMA-48, "Control Functions for
+# Coded Character Sets"), include your snail-mail address, and you should
+# receive the document in due course.  Don't expect an email acknowledgement.
+#
+# Related standards include "X3.4-1977: American National Standard Code for
+# Information Interchange" (the ASCII standard) and "X3.41.1974: 
+# Code-Extension Techniques for Use with the 7-Bit Coded Character Set of
+# American National Standard for Information Interchange."  I believe (but
+# am not certain) that these are effectively identical to ECMA-6 and ECMA-35
+# respectively. 
+#
+
+#### VT100/ANSI/ECMA-48
+#
+# ANSI Standard (X3.64) Control Sequences for Video Terminals and Peripherals
+# and ECMA-48 Control Functions for Coded Character Sets.
+# 
+# Much of the content of this comment is adapted from a table prepared by
+# Richard Shuford, based on a 1984 Byte article.  Terminfo correspondences,
+# discussion of some terminfo-related issues, and updates to capture ECMA-48
+# have been added.  Control functions described in ECMA-48 only are tagged
+# with * after their names.
+#
+# The table is a complete list of the defined ANSI X3.64/ECMA-48 control
+# sequences.  In the main table, \E stands for an escape (\033) character,
+# SPC for space.  Pn stands for a single numeric parameter to be inserted
+# in decimal ASCII.  Ps stands for a list of such parameters separated by
+# semicolons.  Parameter meanings for most parametrized sequences are
+# decribed in the notes.
+#
+# Sequence     Sequence                             Parameter   or
+# Mnemonic     Name              Sequence           Value      Mode   terminfo
+# -----------------------------------------------------------------------------
+# APC  Applicatn Program Command \E _                -         Delim  -
+# BEL  Bell *                    ^G                  -         -      bel
+# BPH  Break Permitted Here *    \E B                -         *      -
+# BS   Backpace *                ^H                  -         EF     -
+# CAN  Cancel *                  ^X                  -         -      -   (A)
+# CBT  Cursor Backward Tab       \E [ Pn Z           1         eF     cbt
+# CCH  Cancel Previous Character \E T                -         -      -
+# CHA  Cursor Horizntal Absolute \E [ Pn G           1         eF     hpa (B)
+# CHT  Cursor Horizontal Tab     \E [ Pn I           1         eF     tab (C)
+# CMD  Coding Method Delimiter * \E
+# CNL  Cursor Next Line          \E [ Pn E           1         eF     nel (D)
+# CPL  Cursor Preceding Line     \E [ Pn F           1         eF     -
+# CPR  Cursor Position Report    \E [ Pn ; Pn R      1, 1      -      -   (E)
+# CSI  Control Sequence Intro    \E [                -         Intro  -
+# CTC  Cursor Tabulation Control \E [ Ps W           0         eF     -   (F)
+# CUB  Cursor Backward           \E [ Pn D           1         eF     cub
+# CUD  Cursor Down               \E [ Pn B           1         eF     cud
+# CUF  Cursor Forward            \E [ Pn C           1         eF     cuf
+# CUP  Cursor Position           \E [ Pn ; Pn H      1, 1      eF     cup (G)
+# CUU  Cursor Up                 \E [ Pn A           1         eF     cuu
+# CVT  Cursor Vertical Tab       \E [ Pn Y           -         eF     -   (H)
+# DA   Device Attributes         \E [ Pn c           0         -      -
+# DAQ  Define Area Qualification \E [ Ps o           0         -      -
+# DCH  Delete Character          \E [ Pn P           1         eF     dch
+# DCS  Device Control String     \E P                -         Delim  -
+# DL   Delete Line               \E [ Pn M           1         eF     dl
+# DLE  Data Link Escape *        ^P                  -         -      -
+# DMI  Disable Manual Input      \E \                -         Fs     -
+# DSR  Device Status Report      \E [ Ps n           0         -      -   (I)
+# DTA  Dimension Text Area *     \E [ Pn ; Pn SPC T  -         PC     -
+# EA   Erase in Area             \E [ Ps O           0         eF     -   (J)
+# ECH  Erase Character           \E [ Pn X           1         eF     ech
+# ED   Erase in Display          \E [ Ps J           0         eF     ed  (J)
+# EF   Erase in Field            \E [ Ps N           0         eF     -
+# EL   Erase in Line             \E [ Ps K           0         eF     el  (J)
+# EM   End of Medium *           ^Y                  -         -      -
+# EMI  Enable Manual Input       \E b                          Fs     -
+# ENQ  Enquire                   ^E                  -         -      -
+# EOT  End Of Transmission       ^D                  -         *      -
+# EPA  End of Protected Area     \E W                -         -      -   (K)
+# ESA  End of Selected Area      \E G                -         -      -
+# ESC  Escape                    ^[                  -         -      -
+# ETB  End Transmission Block    ^W                  -         -      -
+# ETX  End of Text               ^C                  -         -      -
+# FF   Form Feed                 ^L                  -         -      -
+# FNK  Function Key *            \E [ Pn SPC W       -         -      -
+# GCC  Graphic Char Combination* \E [ Pn ; Pn SPC B  -         -      -
+# FNT  Font Selection            \E [ Pn ; Pn SPC D  0, 0      FE     -
+# GSM  Graphic Size Modify       \E [ Pn ; Pn SPC B  100, 100  FE     -   (L)
+# GSS  Graphic Size Selection    \E [ Pn SPC C       none      FE     -
+# HPA  Horz Position Absolute    \E [ Pn `           1         FE     -   (B)
+# HPB  Char Position Backward    \E [ j              1         FE     -
+# HPR  Horz Position Relative    \E [ Pn a           1         FE     -   (M)
+# HT   Horizontal Tab *          ^I                  -         FE     -   (N)
+# HTJ  Horz Tab w/Justification  \E I                -         FE     -
+# HTS  Horizontal Tab Set        \E H                -         FE     hts
+# HVP  Horz & Vertical Position  \E [ Pn ; Pn f      1, 1      FE     -   (G)
+# ICH  Insert Character          \E [ Pn @           1         eF     ich
+# IDCS ID Device Control String  \E [ SPC O          -         *      -
+# IGS  ID Graphic Subrepertoire  \E [ SPC M          -         *      -
+# IL   Insert Line               \E [ Pn L           1         eF     il
+# IND  Index                     \E D                -         FE     -
+# INT  Interrupt                 \E a                -         Fs     -
+# JFY  Justify                   \E [ Ps SPC F       0         FE     -
+# IS1  Info Separator #1 *       ^_                  -         *      -
+# IS2  Info Separator #1 *       ^^                  -         *      -
+# IS3  Info Separator #1 *       ^]                  -         *      -
+# IS4  Info Separator #1 *       ^\                  -         *      -
+# LF   Line Feed                 ^J                  -         -      -
+# LS1R Locking Shift Right 1 *   \E ~                -         -      -
+# LS2  Locking Shift 2 *         \E n                -         -      -
+# LS2R Locking Shift Right 2 *   \E }                -         -      -
+# LS3  Locking Shift 3 *         \E o                -         -      -
+# LS3R Locking Shift Right 3 *   \E |                -         -      -
+# MC   Media Copy                \E [ Ps i           0         -      -   (S)
+# MW   Message Waiting           \E U                -         -      -
+# NAK  Negative Acknowledge *    ^U                  -         *      -
+# NBH  No Break Here *           \E C                -         -      -
+# NEL  Next Line                 \E E                -         FE     nel (D)
+# NP   Next Page                 \E [ Pn U           1         eF     -
+# NUL  Null *                    ^@                  -         -      -
+# OSC  Operating System Command  \E ]                -         Delim  -
+# PEC  Pres. Expand/Contract *   \E Pn SPC Z         0         -      -
+# PFS  Page Format Selection *   \E Pn SPC J         0         -      -
+# PLD  Partial Line Down         \E K                -         FE     -   (T)
+# PLU  Partial Line Up           \E L                -         FE     -   (U)
+# PM   Privacy Message           \E ^                -         Delim  -
+# PP   Preceding Page            \E [ Pn V           1         eF     -
+# PPA  Page Position Absolute *  \E [ Pn SPC P       1         FE     -
+# PPB  Page Position Backward *  \E [ Pn SPC R       1         FE     -
+# PPR  Page Position Forward *   \E [ Pn SPC Q       1         FE     -
+# PTX  Parallel Texts *          \E [ \              -         -      -
+# PU1  Private Use 1             \E Q                -         -      -
+# PU2  Private Use 2             \E R                -         -      -
+# QUAD Typographic Quadding      \E [ Ps SPC H       0         FE     -
+# REP  Repeat Char or Control    \E [ Pn b           1         -      rep
+# RI   Reverse Index             \E M                -         FE     -   (V)
+# RIS  Reset to Initial State    \E c                -         Fs     -
+# RM   Reset Mode *              \E [ Ps l           -         -      -   (W)
+# SACS Set Add. Char. Sep. *     \E [ Pn SPC /       0         -      -
+# SAPV Sel. Alt. Present. Var. * \E [ Ps SPC ]       0         -      -   (X)
+# SCI  Single-Char Introducer    \E Z                -         -      -
+# SCO  Sel. Char. Orientation *  \E [ Pn ; Pn SPC k  -         -      -
+# SCS  Set Char. Spacing *       \E [ Pn SPC g       -         -      -
+# SD   Scroll Down               \E [ Pn T           1         eF     rin
+# SDS  Start Directed String *   \E [ Pn ]           1         -      -
+# SEE  Select Editing Extent     \E [ Ps Q           0         -      -   (Y)
+# SEF  Sheet Eject & Feed *      \E [ Ps ; Ps SPC Y  0,0       -      -
+# SGR  Select Graphic Rendition  \E [ Ps m           0         FE     sgr (O)
+# SHS  Select Char. Spacing *    \E [ Ps SPC K       0         -      -
+# SI   Shift In                  ^O                  -         -      -   (P)
+# SIMD Sel. Imp. Move Direct. *  \E [ Ps ^           -         -      -
+# SL   Scroll Left               \E [ Pn SPC @       1         eF     -
+# SLH  Set Line Home *           \E [ Pn SPC U       -         -      -
+# SLL  Set Line Limit *          \E [ Pn SPC V       -         -      -
+# SLS  Set Line Spacing *        \E [ Pn SPC h       -         -      -
+# SM   Select Mode               \E [ Ps h           none      -      -   (W)
+# SO   Shift Out                 ^N                  -         -      -   (Q)
+# SOH  Start Of Heading *        ^A                  -         -      -
+# SOS  Start of String *         \E X                -         -      -
+# SPA  Start of Protected Area   \E V                -         -      -   (Z)
+# SPD  Select Pres. Direction *  \E [ Ps ; Ps SPC S  0,0       -      -
+# SPH  Set Page Home *           \E [ Ps SPC G       -         -      -
+# SPI  Spacing Increment         \E [ Pn ; Pn SPC G  none      FE     -
+# SPL  Set Page Limit *          \E [ Ps SPC j       -         -      -
+# SPQR Set Pr. Qual. & Rapid. *  \E [ Ps SPC X       0         -      -
+# SR   Scroll Right              \E [ Pn SPC A       1         eF     -
+# SRCS Set Reduced Char. Sep. *  \E [ Pn SPC f       0         -      -
+# SRS  Start Reversed String *   \E [ Ps [           0         -      -
+# SSA  Start of Selected Area    \E F                -         -      -
+# SSU  Select Size Unit *        \E [ Pn SPC I       0         -      -
+# SSW  Set Space Width *         \E [ Pn SPC [       none      -      -
+# SS2  Single Shift 2 (G2 set)   \E N                -         Intro  -
+# SS3  Single Shift 3 (G3 set)   \E O                -         Intro  -
+# ST   String Terminator         \E \                -         Delim  -
+# STAB Selective Tabulation *    \E [ Pn SPC ^       -         -      -
+# STS  Set Transmit State        \E S                -         -      -
+# STX  Start pf Text *           ^B                  -         -      -
+# SU   Scroll Up                 \E [ Pn S           1         eF     indn
+# SUB  Substitute *              ^Z                  -         -      -
+# SVS  Select Line Spacing *     \E [ Pn SPC \       1         -      -
+# SYN  Synchronous Idle *        ^F                  -         -      -
+# TAC  Tabul. Aligned Centered * \E [ Pn SPC b       -         -      -
+# TALE Tabul. Al. Leading Edge * \E [ Pn SPC a       -         -      -
+# TATE Tabul. Al. Trailing Edge* \E [ Pn SPC `       -         -      -
+# TBC  Tab Clear                 \E [ Ps g           0         FE     tbc
+# TCC  Tabul. Centered on Char * \E [ Pn SPC c       -         -      -
+# TSR  Tabulation Stop Remove  * \E [ Pn SPC d       -         FE     -
+# TSS  Thin Space Specification  \E [ Pn SC E        none      FE     -
+# VPA  Vert. Position Absolute   \E [ Pn d           1         FE     vpa
+# VPB  Line Position Backward *  \E [ Pn k           1         FE     -
+# VPR  Vert. Position Relative   \E [ Pn e           1         FE     -   (R)
+# VT   Vertical Tabulation *     ^K                  -         FE     -
+# VTS  Vertical Tabulation Set   \E J                -         FE     -
+# 
+# ---------------------------------------------------------------------------
+#
+# Notes:
+#
+# Some control characters are listed in the ECMA-48 standard without 
+# being assigned functions relevant to terminal control there (they 
+# referred to other standards such as ISO 1745 or ECMA-35).  They are listed
+# here anyway for completeness.
+#
+# (A) ECMA-48 calls this "CancelCharacter" but retains the CCH abbreviation.
+#
+# (B) There seems to be some confusion abroad between CHA and HPA.  Most
+# `ANSI' terminals accept the CHA sequence, not the HPA. but terminfo calls
+# the capability (hpa).  ECMA-48 calls this "Cursor Character Absolute" but
+# preserved the CHA abbreviation.
+#
+# (C) CHT corresponds to terminfo (tab).  Usually it has the value ^I.
+# Occasionally (as on, for example, certain HP terminals) this has the HTJ
+# value.  ECMA-48 calls this "Cursor Forward Tabulation" but preserved the
+# CHT abbreviation.
+#
+# (D) terminfo (nel) is usually \r\n rather than ANSI \EE.
+#
+# (E) ECMA-48 calls this "Active Position Report" but preserves the CPR 
+# abbreviation.
+# 
+# (F) CTC parameter values: 0 = set char tab, 1 = set line tab, 2 = clear
+# char tab, 3 = clear line tab, 4 = clear all char tabs on current line, 
+# 5 = clear all char tabs, 6 = clear all line tabs.
+#
+# (G) CUP and HVP are identical in effect.  Some ANSI.SYS versions accept
+# HVP, but always allow CUP as an alternate.  ECMA-48 calls HVP "Character
+# Position Absolute" but retains the HVP abbreviation.
+#
+# (H) ECMA calls this "Cursor Line Tabulation" but preserves the CVT
+# abbreviation.
+#
+# (I) DSR parameter values: 0 = ready, 1 = busy, 2 = busy, will send DSR
+# later, 3 = malfunction, 4 = malfunction, will send DSR later, 5 = request
+# DSR, 6 = request CPR response.
+#
+# (J) ECMA calls ED "Erase In Page". EA/ED/EL parameters: 0 = clear to end,
+# 1 = clear from beginning, 2 = clear.
+# 
+# (K) ECMA calls this "End of Guarded Area" but preserves the EPA abbreviation.
+#
+# (L) The GSM parameters are vertical and horizontal parameters to scale by.
+#
+# (M) Some ANSI.SYS versions accept HPR, but more commonly `ANSI' terminals
+# use CUF for this function and ignore HPR.  ECMA-48 calls this "Character
+# Position Relative" but retains the HPR abbreviation.
+#
+# (N) ECMA-48 calls this "Character Tabulation" but retains the HT
+# abbreviation.
+#
+# (O) SGR parameter values: 0 = default mode (attributes off), 1 = bold,
+# 2 = dim, 3 = italicized, 4 = underlined, 5 = slow blink, 6 = fast blink,
+# 7 = reverse video, 8 = invisible, 9 = crossed-out (marked for deletion),
+# 10 = primary font, 10 + n (n in 1..9) = nth alternative font, 20 = Fraktur,
+# 21 = double underline, 22 = turn off 2, 23 = turn off 3, 24 = turn off 4,
+# 25 = turn off 5, 26 = proportional spacing, 27 = turn off 7, 28 = turn off
+# 8, 29 = turn off 9, 30 = black fg, 31 = red fg, 32 = green fg, 33 = yellow
+# fg, 34 = blue fg, 35 = magenta fg, 36 = cyan fg, 37 = white fg, 38 = set
+# fg color as in CCIT T.416, 39 = set default fg color, 40 = black bg
+# 41 = red bg, 42 = green bg, 43 = yellow bg, 44 = blue bg, 45 = magenta bg,
+# 46 = cyan bg, 47 = white bg, 48 = set bg color as in CCIT T.416, 39 = set
+# default bg color, 50 = turn off 26, 51 = framed, 52 = encircled, 53 =
+# overlined, 54 = turn off 51 & 52, 55 = not overlined, 56-59 = reserved,
+# 61-65 = variable highlights for ideograms.
+#
+# (P) SI is also called LSO, Locking Shift Zero.
+#
+# (Q) SI is also called LS1, Locking Shift One.
+#
+# (R) Some ANSI.SYS versions accept VPR, but more commonly `ANSI' terminals
+# use CUD for this function and ignore VPR.  ECMA calls it `Line Position
+# Absolute' but retains the VPA abbreviation.
+#
+# (S) MC parameters: 0 = start xfer to primary aux device, 1 = start xfer from
+# primary aux device, 2 = start xfer to secondary aux device, 3 = start xfer
+# from secondary aux device, 4 = stop relay to primary aux device, 5 = 
+# start relay to primary aux device, 6 = stop relay to secondary aux device,
+# 7 = start relay to secondary aux device.
+#
+# (T) ECMA-48 calls this "Partial Line Forward" but retains the PLD
+# abbreviation.
+#
+# (U) ECMA-48 calls this "Partial Line Backward" but retains the PLD
+# abbreviation.
+#
+# (V) ECMA-48 calls this "Reverse Line Feed" but retains the RI abbreviation.
+#
+# (W) RM/SM modes are as follows: 1 = Guarder Area Transfer Mode (GATM), 
+# 2 = Keyboard Action Mode (KAM), 3 = Control Representation Mode (CRM), 
+# 4 = Insertion Replacement Mode, 5 = Status Report Transfer Mode (SRTM),
+# 6 = Erasure Mode (ERM), 7 = Line Editing Mode (LEM), 8 = Bi-Directional
+# Support Mode (BDSM), 9 = Device Component Select Mode (DCSM), 
+# 10 = Character Editing Mode (HEM), 11 = Positioning Unit Mode (PUM),
+# 12 = Send/Receive Mode, 13 = Format Effector Action Mode (FEAM), 
+# 14 = Format Effector Transfer Mode (FETM), 15 = Multiple Area Transfer
+# Mode (MATM), 16 = Transfer Termination Mode, 17 = Selected Area Transfer
+# Mode, 18 = Tabulation Stop Mode, 19 = Editing Boundary Mode, 20 = Line Feed
+# New Line Mode (LF/NL), Graphic Rendition Combination Mode (GRCM), 22 =
+# Zero Default Mode (ZDM).  The EBM and LF/NL modes have actually been removed
+# from ECMA-48's 5th edition but are listed here for reference.
+#
+# (X) Select Alternate Presentation Variants is used only for non-Latin
+# alphabets.
+#
+# (Y) "Select Editing Extent" (SEE) was ANSI "Select Edit Extent Mode" (SEM).
+#
+# (Z) ECMA-48 calls this "Start of Guarded Area" but retains the SPA
+# abbreviation.
+#
+# ---------------------------------------------------------------------------
+# 
+# Abbreviations:
+#
+# Intro  an Introducer of some kind of defined sequence; the normal 7-bit
+#        X3.64 Control Sequence Introducer is the two characters "Escape ["
+# 
+# Delim  a Delimiter
+# 
+# x/y    identifies a character by position in the ASCII table (column/row)
+# 
+# eF     editor function (see explanation)
+# 
+# FE     format effector (see explanation)
+#
+# F      is a Final character in
+#             an Escape sequence (F from 3/0 to 7/14 in the ASCII table)
+#             a control sequence (F from 4/0 to 7/14)
+# 
+# Gs     is a graphic character appearing in strings (Gs ranges from
+#        2/0 to 7/14) in the ASCII table
+# 
+# Ce     is a control represented as a single bit combination in the C1 set
+#        of controls in an 8-bit character set
+# 
+# C0     the familiar set of 7-bit ASCII control characters
+# 
+# C1     roughly, the set of control chars available only in 8-bit systems.
+#        This is too complicated to explain fully here, so read Jim Fleming's
+#        article in the February 1983 BYTE, especially pages 214 through 224.
+# 
+# Fe     is a Final character of a 2-character Escape sequence that has an
+#        equivalent representation in an 8-bit environment as a Ce-type
+#        (Fe ranges from 4/0 to 5/15)
+# 
+# Fs     is a Final character of a 2-character Escape sequence that is
+#        standardized internationally with identical representation in 7-bit
+#        and 8-bit environments and is independent of the currently
+#        designated C0 and C1 control sets (Fs ranges from 6/0 to 7/14)
+# 
+# I      is an Intermediate character from 2/0 to 2/15 (inclusive) in the
+#        ASCII table
+# 
+# P      is a parameter character from 3/0 to 3/15 (inclusive) in the ASCII
+#        table
+# 
+# Pn     is a numeric parameter in a control sequence, a string of zero or
+#        more characters ranging from 3/0 to 3/9 in the ASCII table
+# 
+# Ps     is a variable number of selective parameters in a control sequence
+#        with each selective parameter separated from the other by the code
+#        3/11 (which usually represents a semicolon); Ps ranges from
+#        3/0 to 3/9 and includes 3/11
+#
+# *      Not relevant to terminal control, listed for completeness only.
+# 
+# Format Effectors versus Editor Functions
+# 
+# A format effector specifies how following output is to be displayed.
+# An editor function allows you to modify the display.  Informally
+# format effectors may be destructive; format effectors should not be.
+# 
+# For instance, a format effector that moves the "active position" (the 
+# cursor or equivalent) one space to the left would be useful when you want to
+# create an overstrike, a compound character made of two standard characters
+# overlaid. Control-H, the Backspace character, is actually supposed to be a
+# format effector, so you can do this. But many systems use it in a
+# nonstandard fashion, as an editor function, deleting the character to the
+# left of the cursor and moving the cursor left. When Control-H is assumed to
+# be an editor function, you cannot predict whether its use will create an
+# overstrike unless you also know whether the output device is in an "insert
+# mode" or an "overwrite mode". When Control-H is used as a format effector,
+# its effect can always be predicted. The familiar characters carriage
+# return, linefeed, formfeed, etc., are defined as format effectors.
+#
+# NOTES ON THE DEC VT100 IMPLEMENTATION
+# 
+# Control sequences implemented in the VT100 are as follows:
+# 
+#      CPR, CUB, CUD, CUF, CUP, CUU, DA, DSR, ED, EL, HTS, HVP, IND,
+#      LNM, NEL, RI, RIS, RM, SGR, SM, TBC
+# 
+# plus several private DEC commands.
+# 
+# Erasing parts of the display (EL and ED) in the VT100 is performed thus:
+# 
+#      Erase from cursor to end of line           Esc [ 0 K    or Esc [ K
+#      Erase from beginning of line to cursor     Esc [ 1 K
+#      Erase line containing cursor               Esc [ 2 K
+#      Erase from cursor to end of screen         Esc [ 0 J    or Esc [ J
+#      Erase from beginning of screen to cursor   Esc [ 1 J
+#      Erase entire screen                        Esc [ 2 J
+#
+# Some brain-damaged terminal/emulators respond to Esc [ J as if it were
+# Esc [ 2 J, but this is wrong; the default is 0.
+# 
+# The VT100 responds to receiving the DA (Device Attributes) control
+# 
+#      Esc [ c    (or Esc [ 0 c)
+# 
+# by transmitting the sequence
+# 
+#      Esc [ ? l ; Ps c
+# 
+# where Ps is a character that describes installed options.
+# 
+# The VT100's cursor location can be read with the DSR (Device Status
+# Report) control
+# 
+#      Esc [ 6 n
+# 
+# The VT100 reports by transmitting the CPR sequence
+# 
+#      Esc [ Pl ; Pc R
+# 
+# where Pl is the line number and Pc is the column number (in decimal).
+# 
+# The specification for the DEC VT100 is document EK-VT100-UG-003.
+
+#### ANSI.SYS
+# 
+# Here is a description of the color and attribute controls supported in the
+# the ANSI.SYS driver under MS-DOS.  Most console drivers and ANSI
+# terminal emulators for Intel boxes obey these.  They are a proper subset
+# of the ECMA-48 escapes.
+#
+# 0	all attributes off
+# 1	foreground bright
+# 4	underscore on
+# 5	blink on/background bright (not reliable with brown)
+# 7	reverse-video
+# 8	set blank (non-display)
+# 10	set primary font
+# 11	set first alternate font (on PCs, display ROM characters 1-31)
+# 12	set second alternate font (on PCs, display IBM high-half chars)
+#
+#			Color attribute sets
+# 3n	set foreground color       / 0=black, 1=red,     2=green, 3=brown,
+# 4n	set background color       \ 4=blue,  5=magenta, 6=cyan,  7=white
+# Bright black becomes gray.  Bright brown becomes yellow,
+# These coincide with the prescriptions of the ISO 6429/ECMA-48 standard.
+#
+# * If the 5 attribute is on and you set a background color (40-47) it is
+#   supposed to enable bright background.
+#
+# * Many VGA cards (such as the Paradise and compatibles) do the wrong thing
+#   when you try to set a "bright brown" (yellow) background with attribute
+#   5 (you get a blinking yellow foreground instead).  A few displays
+#   (including the System V console) support an attribute 6 that undoes this
+#   braindamage (this is required by iBCS2).
+#
+# * Some older versions of ANSI.SYS have a bug that causes thems to require
+#   ESC [ Pn k as EL rather than the ANSI ESC [ Pn K.  (This is not ECMA-48
+#   compatible.)
+
+#### Intel Binary Compatibility Standard
+#
+# For comparison, here are the capabilities implied by the Intel Binary 
+# Compatibility Standard for UNIX systems (Intel order number 468366-001).
+# These recommendations are optional.  IBCS2 allows the leading escape to
+# be either the 7-bit \E[ or 8-bit \0233 introducer, in accordance with
+# the ANSI X.364/ISO 6429/ECMA-48 standard.  Here are the iBCS2 capabilities
+# (as described in figure 9-3 of the standard).  Those expressed in the ibcs2
+# terminfo entry are followed with the corresponding capability in parens:
+#
+#	CSI <n>k		disable (n=0) or enable (n=1) keyclick
+#	CSI 2h   		lock keyboard
+#	CSI 2i  		send screen as input
+#	CSI 2l  		unlock keyboard
+#	CSI 6m  		enable background color intensity
+#	CSI <0-2>c		reserved
+#	CSI <0-59>m		select graphic rendition
+#	CSI <n>;<m>H	(cup)	cursor to line n and column m
+#	CSI <n>;<m>f		cursor to line n and column m
+#	CSI <n>@	(ich)	insert characters
+#	CSI <n>A	(cuu)	cursor up n lines
+#	CSI <n>B	(cud)	cursor down n lines
+#	CSI <n>C	(cuu)	cursor right n characters
+#	CSI <n>D	(cud)	cursor left n characters
+#	CSI <n>E		cursor down n lines and in first column
+#	CSI <n>F		cursor up n lines and in first column
+#	CSI <n>G	(hpa)	position cursor at column n-1
+#	CSI <n>J	(ed)	erase in display
+#	CSI <n>K	(el)	erase in line
+#	CSI <n>L	(il)	insert line(s)
+#	CSI <n>P	(dch)	delete characters
+#	CSI <n>S	(indn)	scroll up n lines
+#	CSI <n>T	(rin)	scroll down n lines
+#	CSI <n>X	(ech)	erase characters
+#	CSI <n>Z	(cbt)	back up n tab stops
+#	CSI <n>`		cursor to column n on line
+#	CSI <n>a	(cuu)	cursor right n characters
+#	CSI <n>d	(vpa)	cursor to line n
+#	CSI <n>e		cursor down n lines and in first column
+#	CSI <n>g	(cbt)	clear all tabs
+#	CSI <n>z		make virtual terminal n active
+#	CSI ?7h 	(smam)	turn automargin on
+#	CSI ?7l 	(rmam)	turn automargin off
+#	CSI s     		save cursor position
+#	CSI u   		restore cursor position to saved value
+#	CSI =<c>A		set overscan color
+#	CSI =<c>F		set normal foreground color
+#	CSI =<c>G		set normal background color
+#	CSI =<c>H		set reverse foreground color
+#	CSI =<c>I		set reverse foreground color
+#	CSI =<c>J		set graphic foreground color
+#	CSI =<c>K		set graphic foreground color
+#	CSI =<n>g	(dispc) display n from alternate graphics character set
+#	CSI =<p>;<d>B		set bell parameters
+#	CSI =<s>;<e>C		set cursor parameters
+#	CSI =<x>D		enable/disable intensity of background color
+#	CSI =<x>E		set/clear blink vs. bold background
+#	CSI 7     	(sc)	(sc) save cursor position
+#	CSI 8   	(rc)	(rc) restore cursor position to saved value
+#	CSI H		(hts)	(hts) set tab stop
+#	CSI Q<n><string>	define function key string
+#				(string must begin and end with delimiter char)
+#	CSI c   	(clear) clear screen
+#
+# The lack of any specification for attributes in SGR (among other things)
+# makes this a wretchedly weak standard. The table above is literally 
+# everything iBSC2 has to say about terminal escape sequences; there is
+# no further discussion of their meaning or how to set the parameters
+# in these sequences at all.
+#
+
+######## NONSTANDARD CAPABILITY TRANSLATIONS USED IN THIS FILE
+#
+# The historical termcap file entries were written primarily in 4.4BSD termcap.
+# The 4.4BSD termcap set was substantially larger than the original 4.1BSD set,
+# with the extension names chosen for compatibility with the termcap names
+# assigned in System V terminfo.  There are some variant extension sets out
+# there.  We try to describe them here.
+#
+# XENIX extensions:
+#
+# The XENIX extensions include a set of function-key capabilities as follows:
+#
+#       code	XENIX variable name	terminfo name	name clashes?
+#	----	-------------------	-------------	-----------------------
+#	CL	key_char_left
+#	CR	key_char_right
+#	CW	key_change_window			create_window
+#	EN	key_end          	kend
+#	HM	key_home		khome
+#	HP	??
+#	LD	key_delete_line  	kdl1
+#	LF	key_linefeed     			label_off
+#	NU	key_next_unlocked_cell
+#	PD	key_page_down   	knp
+#	PL	??
+#	PN	start_print		mc5
+#	PR	??
+#	PS	stop_print		mc4
+#	PU	key_page_up     	kpp		pulse
+#	RC	key_recalc				remove_clock
+#	RF	key_toggle_ref				req_for_input
+#	RT	key_return      	kent
+#	UP	key_up_arrow           	kcuu1   	parm_up_cursor
+#	WL	key_word_left
+#	WR	key_word_right
+#
+# The XENIX extensions also include the following character-set and highlight
+# capabilities:
+#
+#	XENIX	terminfo	function
+#	-----	--------	------------------------------
+#	GS	smacs		start alternate character set
+#	GE	rmacs		end alternate character set
+#	GG			:as:/:ae: glitch (analogous to :sg:/:ug:)
+#	bo	blink		begin blink (not used in /etc/termcap)
+#	be			end blink (not used in /etc/termcap)
+#	bb			blink glitch  (not used in /etc/termcap)
+#	it	dim		begin dim (not used in /etc/termcap)
+#	ie			end dim (not used in /etc/termcap)
+#	ig			dim glitch  (not used in /etc/termcap)
+#
+# Finally, XENIX also used the following forms-drawing capabilities:
+#
+#	single	double  type             ASCII approximation 
+#	------	------	-------------    -------------------
+#	GV	Gv	vertical line             |
+#	GH	Gv	horizontal line       -   _
+#	G1	G5	top right corner       _   |
+#	G2	G6	top left corner       | 
+#	G3	G7	bottom left corner         |_
+#	G4	G8	bottom right corner   _|
+#	GD	Gd	down-tick character        T
+#	GL	Gl	left-tick character   -|
+#	GR	Gr	right-tick character       |-
+#	GC	Gc	middle intersection   -|-
+#	GU	Gu	up-tick character          _|_
+#
+# These were invented to take advantage of the IBM PC ROM character set.  One
+# can compose an acsc string from the single-width characters as follows
+#	"j{G4}k{G1}l{G2}m{G3}q{GH}x{GV}t{GR}u{GL}v{GU}w{GD}n{GC}"
+# When translating a termcap file, ncurses tic will do this automatically.
+# The double forms characters don't fit the SVr4 terminfo model.
+#
+# AT&T Extensions:
+#
+# The old AT&T 5410, 5420, 5425, pc6300plus, 610, and s4 entries used a set of
+# nonstandard capabilities.  Its signature is the KM capability, used to name
+# some sort of keymap file.  EE, BO, CI, CV, XS, DS, FL and FE are in this
+# set.  Comments in the original, and a little cross-checking with other AT&T
+# documentation, seem to establish that BO=:mr: (start reverse video), DS=:mh:
+# (start dim), XS=:mk: (secure/invisible mode), EE=:me: (end highlights),
+# FL=:LO: (enable soft labels), FE=:LF: (disable soft labels), CI=:vi: (make
+# cursor invisible), and CV=:ve: (make cursor normal).
+#
+# HP Extensions
+#
+# The HP library (as of mid-1995, their term.h file version 70.1) appears to
+# have the System V capabilities up to SVr1 level.  After that, it supports
+# two nonstandard caps meml and memu corresponding to the old termcap :ml:,
+# :mu: capabilities.  After that, it supports caps plab_norm, label_on,
+# label_off, and key_f11..key_f63 capabilities like SVr4's.  This makes the
+# HP binary format incompatible with SVr4's.
+#
+# IBM Extensions
+#
+# There is a set of nonstandard terminfos used by IBM's AIX operating system.
+# The AIX terminfo library diverged from SVr1 terminfo, and replaces all
+# capabilities following prtr_non with the following special capabilties:
+# box[12], batt[12], colb[0123456789], colf[0123456789], f[01234567], kbtab,
+# kdo, kcmd, kcpn, kend, khlp, knl, knpn, kppn, kppn, kquit, ksel, kscl, kscr,
+# ktab, kmpf[123456789], apstr, ksf1..ksf10, kf11...kf63, kact, topl, btml,
+# rvert, lvert.   Some of these are identical to XPG4/SVr4 equivalents:
+# kcmd, kend, khlp, and kf11...kf63.  Two others (kbtab and ksel) can be
+# renamed (to kcbt and kslt).  The places in the box[12] capabilities
+# correspond to acsc chars, here is the mapping:
+#
+#	box1[0]  = ACS_ULCORNER
+#	box1[1]  = ACS_HLINE	
+#	box1[2]  = ACS_URCORNER
+#	box1[3]  = ACS_VLINE
+#	box1[4]  = ACS_LRCORNER
+#	box1[5]  = ACS_LLCORNER
+#	box1[6]  = ACS_TTEE
+#	box1[7]  = ACS_RTEE
+#	box1[8]  = ACS_BTEE
+#	box1[9]  = ACS_LTEE
+#	box1[10] = ACS_PLUS
+#
+# The box2 characters are the double-line versions of these forms graphics.
+# The AIX binary terminfo format is incompatible with SVr4's.
+#
+# Iris console extensions:
+#
+# HS is half-intensity start; HE is half-intensity end
+# CT is color terminal type (for Curses & rogue)
+# CP is color change escape sequence
+# CZ are color names (for Curses & rogue)
+#
+# The ncurses tic utility recognizes HS as an alias for mh <dim>.
+#
+# TC Extensions:
+#
+# There is a set of extended termcaps associated with something
+# called the "Terminal Control" or TC package created by MainStream Systems,
+# Winfield Kansas.  This one also uses GS/GE for as/ae, and also uses
+# CF for civis and CO for cvvis.  Finally, they define a boolean :ct:
+# that flags color terminals.
+#
+######## CHANGE HISTORY
+#
+# The last /etc/termcap version maintained by John Kunze was 8.3, dated 8/5/94.
+# Releases 9 and up are maintained by Eric S. Raymond as part of the ncurses
+# project.
+#
+# This file contains all the capability information present in John Kunze's
+# last version of the termcap master file, except as noted in the change 
+# comments at end of file.  Some information about very ancient obsolete
+# capabilities has been moved to comments.  Some all-numeric names of older
+# terminals have been retired.
+#
+# I changed :MT: to :km: (the 4.4BSD name) everywhere.  I commented out some
+# capabilities (EP, dF, dT, dV, kn, ma, ml, mu, xr, xx) that are no longer
+# used by BSD curses.
+#
+# The 9.1.0 version of this file was translated from my lightly-edited copy of
+# 8.3, then mechanically checked against 8.3 using Emacs Lisp code written for
+# the purpose.  Unless the ncurses tic implementation and the Lisp code were
+# making perfectly synchronized mistakes which I then failed to catch by
+# eyeball, the translation was correct and perfectly information-preserving.
+#
+# Major version number bumps correspond to major version changes in ncurses.
+#
+# Here is a log of the changes since then:
+#
+# 9.1.0 (Wed Feb  1 04:50:32 EST 1995):
+#	* First terminfo master translated from 8.3.
+# 9.2.0 (Wed Feb  1 12:21:45 EST 1995):
+#	* Replaced Wyse entries with updated entries supplied by vendor.
+#
+# 9.3.0 (Mon Feb  6 19:14:40 EST 1995):
+#	* Added contact & status info from G. Clark Brown <clark@sssi.com>.
+# 9.3.1 (Tue Feb  7 12:00:24 EST 1995):
+#	* Better XENIX keycap translation.  Describe TC termcaps.
+#	* Contact and history info supplied by Qume.
+# 9.3.2 (Sat Feb 11 23:40:02 EST 1995):
+#	* Raided the Shuford FTP site for recent termcaps/terminfos.
+#	* Added information on X3.64 and VT100 standard escape sequences.
+# 9.3.3 (Mon Feb 13 12:26:15 EST 1995):
+#	* Added a correct X11R6 xterm entry.
+#	* Fixed terminfo translations of padding.
+# 9.3.4 (Wed Feb 22 19:27:34 EST 1995):
+#	* Added correct acsc/smacs/rmacs strings for vt100 and xterm.
+#	* Added u6/u7/u8/u9 capabilities.
+#	* Added PCVT entry.
+# 9.3.5 (Thu Feb 23 09:37:12 EST 1995):
+#	* Emacs uses :so:, not :mr:, for its mode line.  Fix linux entry
+#	  to use reverse-video standout so Emacs will look right.
+#	* Added el1 capability to ansi.
+#	* Added smacs/rmacs to ansi.sys.
+#
+# 9.4.0 (Sat Feb 25 16:43:25 EST 1995):
+#	* New mt70 entry.
+#	* Added COPYRIGHTS AND OTHER DELUSIONS.
+#	* Added AT&T 23xx & 500/513, vt220 and vt420, opus3n1+, netronics
+#	  smartvid & smarterm, ampex 175 & 219 & 232,
+#	  env230, falco ts100, fluke, intertube, superbrain, ncr7901, vic20,
+#	  ozzie, trs200, tr600, Tandy & Texas Instruments VDTs, intext2,
+#	  screwpoint, fviewpoint, Contel Business Systems, Datamedia Colorscan,
+#	  adm36, mime314, ergo4000, ca22851.  Replaced att7300, esprit, dd5500.
+#	* Replaced the Perkin-Elmer entries with vendor's official ones.
+#	* Restored the old minimal-ansi entry, luna needs it.
+#	* Fixed some incorrect ip and proportional-padding translations.
+# 9.4.1 (Mon Feb 27 14:18:33 EST 1995):
+#	* Fix linux & AT386 sgr strings to do A_ALTCHARSET turnoff correctly.
+#	* Make the xterm entry 65 lines again; create xterm25 and xterm24
+#	  to force a particular height.
+#	* Added beehive4 and reorganized other Harris entries.
+# 9.4.2 (Thu Mar  9 01:45:44 EST 1995):
+#	* Merged in DEC's official entries for its terminals.  The only old
+#	  entry I kept was Doug Gwyn's alternate vt100 (as vt100-avo).
+#	* Replaced the translated BBN Bitgraph entries with purpose-built
+#	  ones from AT&T's SVr3.
+#	* Replaced the AT&T entries with AT&T's official terminfos.
+#	* Added teleray 16, vc415, cops10. 
+#	* Merged in many individual capabilities from SCO terminfo files.
+# 9.4.3 (Mon Mar 13 02:37:53 EST 1995):
+#	* Typo fixes.
+#	* Change linux entry so A_PROTECT enables IBM-PC ROM characters.
+# 9.4.4 (Mon Mar 27 12:32:35 EST 1995):
+#	* Added tty35, Ann Arbor Guru series. vi300 and 550, cg7900, tvi803,
+#	  pt210, ibm3164, IBM System 1, ctrm, Tymshare scanset, dt200, adm21,
+#	  simterm, citoh and variants.
+#	* Replaced sol entry with sol1 and sol2.
+#	* Replaced Qume QVT and Freedom-series entries with purpose-built
+#	  terminfo entries.
+#	* Enhanced vt220, tvi910, tvi924, hpterm, hp2645, adm42, tek
+#	  and dg200 entries using caps from from SCO.
+#	* Added the usual set of function-key mappings to ANSI entry.
+#	* Corrected xterm's function-key capabilities.
+# 9.4.5 (Tue Mar 28 14:27:49 EST 1995):
+#	* Fix in xterm entry, cub and cud are not reliable under X11R6.
+# 9.4.6 (Thu Mar 30 14:52:15 EST 1995):
+#	* Fix in xterm entry, get the arrow keys right.
+#	* Change some \0 escapes to \200.
+# 9.4.7 (Tue Apr  4 11:27:11 EDT 1995)
+#	* Added apple (Videx card), adm1a, oadm31.
+#	* Fixed malformed ampex csr.
+#	* Fixed act4, cyb110; they had old-style prefix padding left in. 
+#	* Changed mandatory to advisory padding in many entries.
+#	* Replaced HP entries up to hpsub with purpose-built ones.
+#	* Blank rmir/smir/rmdc/smdc capabilities removed.
+#	* Small fixes merged in from SCO entries for lpr, fos, tvi910+, tvi924.
+# 9.4.8 (Fri Apr  7 09:36:34 EDT 199):
+#	* Replaced the Ann Arbor entries with SCO's, the init strings are
+#	  more efficient (but the entries otherwise identical).
+#	* Added dg211 from Shuford archive.
+#	* Added synertek, apple-soroc, ibmpc, pc-venix, pc-coherent, xtalk,
+#	  adm42-nl, pc52, gs6300, xerox820, uts30.
+#	* Pull SCO's padding into vi200 entry.
+#	* Improved capabilities for tvi4107 and other Televideo and Viewpoint
+#	  entries merged in from SCO's descriptions.
+#	* Fixed old-style prefix padding on zen50, h1500.
+#	* Moved old superbee entry to superbee-xsb, pulled in new superbee
+#	  entry from SCO's description.
+#	* Reorganized the special entries.
+#	* Added lm#0 to cbunix and virtual entries.
+#
+# 9.5.0 (Mon Apr 10 11:30:00 EDT 1995):
+#	* Restored cdc456tst.
+#	* Fixed sb1 entry, SCO erroneously left out the xsb glitch.
+#	* Added megatek, beacon, microkit.
+#	* Freeze for ncurses-1.9 release.
+# 9.5.1 (Fri Apr 21 12:46:42 EDT 1995):
+#	* Added historical data for TAB.
+#	* Comment fixes from David MacKenzie.
+#	* Added the new BSDI pc3 entry.
+# 9.5.2 (Tue Apr 25 17:27:52 EDT 1995)
+#	* A change in the tic -C logic now ensures that all entries in 
+#	  the termcap translation will fit in < 1024 bytes.
+#	* Added `bobcat' and `gator' HP consoles and the Nu machine entries
+#	  from GNU termcap file.  This merges in all their local information.
+# 9.5.3 (Tue Apr 25 22:28:13 EDT 1995)
+#	* Changed tic -C logic to dump all capabilities used by GNU termcap.
+#	* Added warnings about entries with long translations (restoring
+#	  all the GNU termcaps pushes a few over the edge).
+# 9.5.4 (Wed Apr 26 15:35:09 EDT 1995)
+#	* Yet another tic change, and a couple of entry tweaks, to reduce the
+#	  number of long (> 1024) termcap translations back to 0.
+#
+# 9.6.0 (Mon May  1 10:35:54 EDT 1995)
+#	* Added kf13-kf20 to Linux entry.
+#	* Regularize Prime terminal names.
+#	* Historical data on Synertek.
+#	* Freeze for ncurses-1.9.1.
+# 9.6.1 (Sat May  6 02:00:52 EDT 1995):
+#	* Added true xterm-color entry, renamed djm's pseudo-color entry.
+#	* Eliminate whitespace in short name fields, this tanks some scripts.
+#	* Name field changes to shorten some long entries.
+#	* Termcap translation now automatically generates empty rmir/smir
+#	  when ich1/ich is present (copes with an ancient vi bug).
+#	* Added `screen' entries from FSF's screen-3.6.2.
+#	* Added linux-nic and xterm-nic entries.
+# 9.6.2 (Sat May  6 17:00:55 EDT 1995):
+#	* Change linux entry to use smacs=\E[11m and have an explicit acsc,
+#	  eliminating some special-case code in ncurses.
+#
+# 9.7.0 (Tue May  9 18:03:12 EDT 1995):
+#	* Added vt320-k3, rsvidtx from the Emacs termcap.dat file.  I think
+#	  that captures everything unique from it.
+#	* Added reorder script generator.
+#	* Freeze for ncurses 1.9.2 release.
+# 9.7.1 (Thu Jun 29 09:35:22 EDT 1995):
+#	* Added Sean Farley's kspd, flash, rs1 capabilities for linux.
+#	* Added Olaf Siebert's corrections for adm12.
+#	* ansi-pc-color now includes the colors and pairs caps, so that
+#	  entries which use it will inherit them automatically.
+#	* The linux entry can now recognize the center (keypad 5) key.
+#	* Removed some junk that found its way into Linux acsc.
+#
+# 9.8.0 (Fri Jul  7 04:46:57 EDT 1995):
+#	* Add 50% cut mark as a desperate hack to reduce tic's core usage.
+#	* xterm doesn't try to use application keypad mode any more.
+#	* Freeze for ncurses-1.9.3 release.
+# 9.8.1 (Thu Jul 19 17:02:12 EDT 1995):
+#	* Added corrected sun entry from vendor.
+#	* Added csr capability to linux entry.
+#	* Peter Wemm says the at386 hpa should be \E[%i%p1%dG, not \E[%p1%dG.
+#	* Added vt102-nsgr to cope with stupid IBM PC `VT100' emulators.
+#	* Some commented-out caps in long entries come back in, my code 
+#	  for computing string-table lengths had a bug in it.
+#	* pcansi series modified to fit comm-program reality better.
+# 9.8.2 (Sat Sep  9 23:35:00 EDT 1995):
+#	* BSD/OS actually ships the ibmpc3 bold entry as its console.
+#	* Correct some bad aliases in the pcansi series
+#	* Added entry for QNX console.
+#	* Clean up duplicate long names for use with 4.4 library.
+#	* Change vt100 standout to be normal reverse vide, not bright reverse;
+#	  this makes the Emacs status line look better.
+# 9.8.3 (Sun Sep 10 13:07:34 EDT 1995):
+#	* Added Adam Thompson's VT320 entries, also his dtx-sas and z340.
+#	* Minor surgery, mostly on name strings, to shorten termcap version.
+#
+# 9.9.0 (Sat Sep 16 23:03:48 EDT 1995):
+#	* Added dec-vt100 for use with the EWAN emulator.
+#	* Added kmous to xterm for use with xterm's mouse-tracking facility.
+#	* Freeze for 1.9.5 alpha release.
+# 9.9.1 (Wed Sep 20 13:46:09 EDT 1995):
+#	* Changed xterm lines to 24, the X11R6 default.
+# 9.9.2 (Sat Sep 23 21:29:21 EDT 1995):
+#	* Added 7 newly discovered, undocumented acsc characters to linux
+#	  entry (the pryz{|} characters).
+#	* ncurses no longer steals A_PROTECT.  Simplify linux sgr accordingly.
+#	* Correct two typos in the xterm entries introduced in 9.9.1.
+#	* I finally figured out how to translate ko capabilities.  Done.
+#	* Added tvi921 entries from Tim Theisen.
+#	* Cleanup: dgd211 -> dg211, adm42-nl -> adm42-nsl.
+#	* Removed mystery tec entry, it was neither interesting nor useful.
+#	* shortened altos3, qvt203, tvi910+, tvi92D, tvi921-g, tvi955, vi200-f,
+#	  vi300-ss, att505-24, contel301, dm3045, f200vi, pe7000c, vc303a,
+#	  trs200, wind26, wind40, wind50, cdc456tst, dku7003, f110, dg211,
+#	  by making them relative to use capabilities
+#	* Added cuf1=^L to tvi925 from deleted variant tvi925a.
+#	* fixed cup in adm22 entry and parametrized strings in vt320-k3.
+#	* added it#8 to entries that used to have :pt: -- tvi912, vi200,
+#	  ampex80,
+#	* Translate all home=\E[;H capabilities to home=\E[H, they're 
+#	  equivalent.
+#	* Translate \E[0m -> \E[m in [rs]mso, [rs]mul, and init strings of
+#	  vt100 and ANSI-like terminals.
+# 9.9.3 (Tue Sep 26 20:11:15 EDT 1995):
+#	* Added it#8 and ht=\t to *all* entries with :pt:; the ncurses tic
+#	  does this now, too.
+#	* fviewpoint is gone, it duplicated screwpoint.
+#	* Added hp2627, graphos, graphos-30, hpex, ibmega, ibm8514, ibm8514-c,
+#	  ibmvga, ibmvga-c, minix, mm340, mt4520-rv, screen2, screen3, 
+#	  versaterm, vi500, vsc, vt131, vt340, vt400 entries from UW.
+#	  The UW vi50 replaces the old one, which becomes vi50adm,
+#	* No more embedded commas in name fields.
+#
+# 9.10.0 (Wed Oct  4 15:39:37 EDT 1995):
+#	* XENIX forms characters in fos, trs16, scoansi become acsc strings,
+#	* Introduced klone+* entries for describing Intel-console behavior.
+#	* Linux kbs is default-mapped to delete for some brain-dead reason.
+#	* -nsl -> -ns.  The -pp syntax is obsolete.
+#	* Eliminate [A-Z]* primaries in accordance with SVr4 terminfo docs.
+#	* Make xterm entry do application-keypad mode again.  I got complaints
+#	  that it was messing up someone's 3270 emulator.
+#	* Added some longname fields in order to avoid warning messages from
+#	  older tic implementations.
+#	* According to ctrlseqs.ms, xterm has a full vt100 graphics set.  Use
+#	  it! (This gives us pi, greater than, less than, and a few more.)
+#	* Freeze for ncurses-1.9.6 release.
+# 9.10.1 (Sat Oct 21 22:18:09 EDT 1995):
+#	* Add xon to a number of console entries, they're memory-mapped and
+#	  don't need padding.
+#	* Correct the use dependencies in the ansi series.
+#	* Hand-translate more XENIX capabilities.
+#	* Added hpterm entry for HP's X terminal emulator.
+#	* Added aixterm entries.
+#	* Shortened four names so everything fits in 14 chars.  
+#
+# 9.11.0 (Thu Nov  2 17:29:35 EST 1995):
+#	* Added ibcs2 entry and info on iBCS2 standard.
+#	* Corrected hpa/vpa in linux entry.  They still fail the worm test.
+#	* We can handle the HP meml/memu capability now.
+#	* Added smacs to klone entries, just as documentation.
+#	* Carrected ansi.sys and cit-500 entries.
+#	* Added z39, vt320-k311, v220c, and avatar entries.
+#	* Make pcansi use the ansi.sys invis capability.
+#	* Added DIP switch descriptions for vt100, adm31, tvi910, tvi920c,
+#	  tvi925, tvi950, dt80, ncr7900i, h19.
+#	* X3.64 has been withdrawn, change some references.
+#	* Removed function keys from ansi-m entry.
+#	* Corrected ansi.sys entry.
+#	* Freeze for ncurses-1.9.7 release.
+# 9.11.1 (Tue Nov  6 18:18:38 EST 1995):
+#	* Added rmam/smam capabilities to many entries based on init strings.
+#	* Added correct hpa/vpa to linux.
+#	* Reduced several entries relative to vt52.
+# 9.11.2 (Tue Nov  7 00:21:06 EST 1995):
+#	* Exiled some utterly unidentifiable custom and homebrew types to the
+#	  UFO file; also, obsolete small-screen hardware; also, entries which
+#	  look flat-out incorrect, garbled, or redundant.  These include the
+#	  following entries: carlock, cdc456tst, microkit, qdss, ramtek, tec, 
+#	  tec400, tec500, ubell, wind, wind16, wind40, wind50, plasma, agile,
+#	  apple, bch, daleblit, nucterm, ttywilliams, nuterminal, nu24, bnu,
+#	  fnu, nunix-30, nunix-61, exidy, ex3000, sexidy, pc52, sanyo55, 
+#	  yterm10, yterm11, yterm10nat, aed, aed-ucb, compucolor, compucolor2, 
+#	  vic20, dg1, act5s, netx, smartvid, smarterm, sol, sol2, dt200, 
+#	  trs80, trs100, trs200, trs600, xitex, rsvidtx, vid, att2300-x40, 
+#	  att2350-x40, att4410-nfk, att5410-ns, otty5410, att5425-nl-w, 
+#	  tty5425-fk, tty5425-w-fk, cita, c108-na, c108-rv-na, c100-rv-na, 
+#	  c108-na-acs, c108-rv-na-acs, ims950-ns, infotonKAS, ncr7900i-na, 
+#	  regent60na, scanset-n, tvi921-g, tvi925n, tvi925vbn, tvi925vb, 
+#	  vc404-na, vc404-s-na, vt420nam, vt420f-nam, vt420pc-nam, vt510nam, 
+#	  vt510pc-nam, vt520nam, vt525nam, xterm25, xterm50, xterm65, xterms.
+#	* Corrected pcvt25h as suggested by Brian C. Grayson
+#	  <bgrayson@pine.ece.utexas.edu>.
+# 9.11.3 (Thu Nov  9 12:14:40 EST 1995):
+#	* Added kspd=\E[P, kcbt=\E[Z, to linux entry, changed kbs back to ^H. 
+#	* Added kent=\EOM to xterm entry.
+#
+# 9.11.4 (Fri Nov 10 08:31:35 EST 1995):
+#	* Corrected gigi entry.
+#	* Restored cuf/cud1 to xterm, their apparent bugginess was due to
+#	  bad hpa/vpa capabilities.
+#	* Corrected flash strings to have a uniform delay of .2 sec.  No
+#	  more speed-dependent NUL-padding!
+#	* terminfo capabilities in comments bracketed with <>.
+# 9.11.5 (Fri Nov 10 15:35:02 EST 1995):
+#	* Replaced pcvt with the 3.31 pcvt entries.
+#	* Freeze for 1.9.7a.
+# 9.11.6 (Mon Nov 13 10:20:24 EST 1995):
+#	* Added emu entry from the X11R6 contrib tape sources.
+#
+# 9.12.0 (Wed Nov 29 04:22:25 EST 1995):
+#	* Improved iris-ansi and sun entries.
+#	* More flash string improvements.
+#	* Corrected wy160 & wy160 as suggested by Robert Dunn
+#	* Added dim to at386.  
+#	* Reconciled pc3 and ibmpc3 with the BSDI termcap file.  Keith says
+#	  he's ready to start using the termcap generated from this one.
+#	* Added vt102-w, vt220-w, xterm-bold, wyse-vp, wy75ap, att4424m,
+#	  ln03, lno3-w, h19-g, z29a*, qdss.  Made vt200 an alias of vt220.
+#	* Improved hpterm, apollo consoles, fos, qvt101, tvi924. tvi925,
+#	  att610, att620, att630, 
+#	* Changed hazeltine name prefix from h to hz.
+#	* Sent t500 to the UFI file.
+#	* I think we've sucked all the juice out of BSDI's termcap file now.
+#	* Freeze for ncurses 1.9.8 release
+# 9.12.1 (Thu Nov 30 03:14:06 EST 1995)
+#	* Unfreeze, linux kbs needed to be fixed.
+#	* Tim Theisen pinned down a bug in the DMD firmware.
+# 9.12.2 (Thu Nov 30 19:08:55 EST 1995):
+#	* Fixes to ansi and klone capabilities (thank you, Aaron Ucko).
+#	  (The broken ones had been shadowed by sgr.)
+# 9.12.3 (Thu Dec  7 17:47:22 EST 1995):
+#	* Added documentation on ECMA-48 standard.
+#	* New Amiga entry.
+# 9.12.4 (Thu Dec 14 04:16:39 EST 1995):
+#	* More ECMA-48 stuff
+#	* Corrected typo in minix entry, added pc-minix.
+#	* Corrected khome/kend in xterm (thank you again, Aaron Ucko).
+#	* Added rxvt entry.
+#	* Added 1.3.x color-change capabilities to linux entry.
+# 9.12.5 (Tue Dec 19 00:22:10 EST 1995):
+#	* Corrected rxvt entry khome/kend.
+#	* Corrected linux color change capabilities.
+#	* NeXT entries from Dave Wetzel.
+#	* Cleaned up if and rf file names (all in /usr/share now).
+#	* Changed linux op capability to avoid screwing up a background color
+#	  pair set by setterm.
+# 9.12.6 (Wed Feb  7 16:14:35 EST 1996):
+#	* Added xterm-sun.
+# 9.12.7 (Fri Feb  9 13:27:35 EST 1996):
+#	* Added visa50.
+#
+# 9.13.0 (Sun Mar 10 00:13:08 EST 1996):
+#	* Another sweep through the Shuford archive looking for new info.
+#	* Added dg100 alias to dg6053 based on a comp.terminals posting.
+# 	* Added st52 from Per Persson.
+#	* Added eterm from the GNU Emacs 19.30 distribution.
+#	* Freeze for 1.9.9.
+# 9.13.1 (Fri Mar 29 14:06:46 EST 1996):
+#	* FreeBSD console entries from Andrew Chernov.
+#	* Removed duplicate Atari st52 name.
+# 9.13.2 (Tue May  7 16:10:06 EDT 1996)
+#	* xterm doesn't actually have ACS_BLOCK.
+#	* Change klone+color setf/setb to simpler forms that can be
+#	  translated into termcap.
+#	* Added xterm1.
+#	* Removed mechanically-generated junk capabilities from cons* entries.
+#	* Added color support to bsdos.
+# 9.13.3 (Thu May  9 10:35:51 EDT 1996):
+#	* Added Wyse 520 entries from Wm. Randolph Franklin <wrf@ecse.rpi.edu>.
+#	* Created ecma+color, linux can use it.  Also added ech to linux.
+#	* Teach xterm about more keys. Add Thomas Dickey's 3.1.2E updates.
+#	* Add descriptions to FreeBSD console entries.  Also shorten
+#	  some aliases to <= 14 chars for portability.
+#	* Added x68k console
+#	* Added OTbs to several VT-series entries.
+# 9.13.4 (Wed May 22 10:54:09 EDT 1996):
+#	* screen entry update for 3.7.1 from Michael Alan Dorfman.
+# 9.13.5 (Wed Jun  5 11:22:41 EDT 1996):
+#	* kterm correction due to Kenji Rikitake.
+#	* ACS correction in vt320-kll due to Phillippe De Muyter.
+# 9.13.6 (Sun Jun 16 15:01:07 EDT 1996):
+#	* Sun console entry correction from J.T. Conklin.
+#	* Changed all DEC VT300 and up terminals to use VT300 tab set
+# 9.13.7 (Mon Jul  8 20:14:32 EDT 1996):
+#	* Added smul to linux entry (we never noticed it was missing 
+#	  because of sgr!).
+#	* Added rmln to hp+labels (deduced from other HP entries).
+#	* Added vt100 acsc capability to vt220, vt340, vt400, d800, dt80-sas,
+#	  pro350, att7300, 5420_2, att4418, att4424, att4426, att505, vt320-k3.
+#	* Corrected vt220 acsc.
+#	* The klone+sgr and klone+sgr-dumb entries now use klone+acs;
+#	  this corresponds to reality and helps prevent some tic warnings.
+#	* Added sgr0 to c101, pcix, vt100-nav, screen2, oldsun, next, altos2,
+#	  hpgeneric, hpansi, hpsub, hp236, hp700-wy, bobcat, dku7003, adm11,
+#	  adm12, adm20, adm21, adm22, adm31, adm36, adm42, pt100, pt200,
+#	  qvt101, tvi910, tvi921, tvi92B, tvi925, tvi950, tvi970, wy30-mc,
+#	  wy50-mc, wy100, wyse-vp, ampex232, regent100, viewpoint, vp90,
+#	  adds980, cit101, cit500, contel300, cs10, dm80, falco, falco-p, 
+#	  f1720a, go140, sb1, superbeeic, microb, ibm8512, kt7, ergo4000,
+#	  owl, uts30, dmterm, dt100, dt100, dt110, appleII, apple-videx,
+#	  lisa, trsII, atari, st52, pc-coherent, basis, m2-man, bg2.0, bg1.25,
+#	  dw3, ln03, ims-ansi, graphos, t16, zen30, xtalk, simterm, d800,
+#	  ifmr, v3220, wy100q, tandem653, ibmaed.
+#	* Added DWK terminal description.
+# 9.13.8 (Wed Jul 10 11:45:21 EDT 1996):
+#	* Many entries now have highlights inherited from adm+sgr.
+#	* xterm entry now corresponds to XFree86 3.1.2E, with color.
+#	* xtitle and xtitle-twm enable access to the X status line.
+#	* Added linux-1.3.6 color palette caps in conventional format.
+#	* Added adm1178 terminal.
+#	* Move fos and apollo terminals to obsolete category.
+#	* Aha! The BRL terminals file told us what the Iris extensions mean.
+#	* Added, from the BRL termcap file: rt6221, rt6221-w, northstar,
+#	  commodore, cdc721-esc, excel62, osexec.  Replaced from the BRL file:
+#	  cit500, adm11. 
+# 9.13.9 (Mon Jul 15 00:32:51 EDT 1996):
+#	* Added, from the BRL termcap file: cdc721, cdc721l, cdc752, cdc756,
+#	  aws, awsc, zentec8001, modgraph48, rca vp3301/vp3501, ex155.
+#	* Corrected, from BRL termcap file: vi50.
+#	* Better rxvt entry & corrected xterm entries from Thomas Dickey.
+# 9.13.10 (Mon Jul 15 12:20:13 EDT 1996):
+#	* Added from BRL: cit101e & variants, hmod1, vi200, ansi77, att5620-1,
+#	  att5620-s, att5620-s, dg210, aas1901, hz1520, hp9845, osborne
+#	  (old osborne moved to osborne-w), tvi970-vb, tvi970-2p, tvi925-hi,
+#	  tek4105brl, tek4106brl, tek4107brl,tek4109brl, hazel, aepro,
+#	  apple40p, apple80p, appleIIgs, apple2e, apple2e-p, apple-ae.
+#	* Paired-attribute fixes to various terminals.
+#	* Sun entry corrections from A. Lukyanov & Gert-Jan Vons.
+#	* xterm entry corrections from Thomas Dickey.
+# 9.13.11 (Tue Jul 30 16:42:58 EDT 1996):
+#	* Added t916 entry, translated from a termcap in SCO's support area.
+#	* New qnx entry from Michael Hunter.
+# 9.13.12 (Mon Aug  5 14:31:11 EDT 1996):
+#	* Added hpex2 from Ville Sulko.
+#	* Fixed a bug that ran the qnx and pcvtXX together.
+# 9.13.13 (Fri Aug  9 01:16:17 EDT 1996):
+#	* Added dtterm entry from Solaris CDE.
+# 9.13.14 (Tue Sep 10 15:31:56 EDT 1996):
+#	* corrected pairs#8 typo in dtterm entry.
+#	* added tvi9065.
+# 9.13.15 (Sun Sep 15 02:47:05 EDT 1996):
+#	* updated xterm entry to cover 3.1.2E's new features.  
+# 9.13.16 (Tue Sep 24 12:47:43 EDT 1996):
+#	* Added new minix entry
+#	* Removed aliases of the form ^[0-9]* for obsolete terminals.
+#	* Commented out linux-old, nobody's using pre-1.2 kernels now.
+# 9.13.17 (Fri Sep 27 13:25:38 EDT 1996):
+#	* Added Prism entries and kt7ix.
+#	* Caution notes about EWAN and tabset files.
+#	* Changed /usr/lib/tabset -> /usr/share/tabset.
+#	* Added acsc/rmacs/smacs to vt52.
+# 9.13.18 (Mon Oct 28 13:24:59 EST 1996):
+#	* Merged in Thomas Dickey's reorganization of the xterm entries;
+#	  added technical corrections to avoid warning messages.
+# 9.13.19 (Sat Nov 16 16:05:49 EST 1996):
+#	* Added rmso=\E[27m in Linux entry.
+#	* Added koi8-r support for Linux console.
+#	* Replace xterm entries with canonical ones from XFree86 3.2.
+# 9.13.20 (Sun Nov 17 23:02:51 EST 1996):
+#	* Added color_xterm from Jacob Mandelson
+# 9.13.21 (Mon Nov 18 12:43:42 EST 1996):
+#	* Back off the xterm entry to use r6 as a base.
+# 9.13.22 (Sat Nov 30 11:51:31 EST 1996):
+#	* Added dec-vt220 at Adrian Garside's request.
+# 9.13.23 (Fri Feb 21 16:36:06 EST 1997):
+#	* Replaced minitel-2 entry.
+#	* Added MGR, ansi-nt.
+#	* Minor corrections to xterm entries.
+#	* Replaced EWAN telnet entry.
+#	* Dropped the reorder script generator.  It was a fossil.
+# 9.13.24 (Sun Feb 23 20:55:23 EST 1997):
+#	* Thorsten Lockert added termcap `bs' to a lot of types, working from
+#	  the 4.4BSD Lite2 file.
+# 9.13.25 (Fri Jun 20 12:33:36 EDT 1997):
+#	* Added Datapoint 8242, pilot, ansi_psx, rbcomm, vt220js.
+#	* Updated iris-ansi; corrected vt102-w.
+#	* Switch base xterm entry to 3.3 level.
+# 9.13.26 (Mon Jun 30 22:45:45 EDT 1997)
+#	* Added basic4.
+#	* Removed rmir/smir from tv92B.
+#
+# 10.2.0 (Sat Feb 28 12:47:36 EST 1998):
+#	* add hds200 description (Walter Skorski)
+#	* add beterm entry (Fred Fish)
+#	* add Thomas Dickey's xterm-xf86-v40, xterm-8bit, xterm-16color,
+#	  iris-color entries.
+#	* add emx entries.
+#	* Replaced unixpc entry with Benjamin Sittler's corrected version.
+#	* Replaced xterm/rxvt/emu/syscons entries with Thomas Dickey's
+#	  versions.
+#	* remove sgr string from qnx based on report by Xiaodan Tang
+#	* Added u8/u9, removed rmul/smul from sun-il.
+#	* 4.2 tic displays \0 rather than \200.
+#	* add linux-koi8r to replace linux-koi8 (which uses a corrupt acsc,
+#	  apparently based on cp-866).
+#	* Merged in Pavel Roskin's acsc for linux-koi8
+#	* Corrected some erroneous \\\s to \.
+#	* 4.2 ncurses has been changed to use setaf/setab, consistent w/SysV.
+#	* II -> ii in pcvtXX, screen, xterm.
+#	* Removed \n chars following ANSI escapes in sgr & friends.
+#	* Updated Wyse entries.
+#	* h19 corrections from Tim Pierce.
+#	* Noted that the dm2500 has both ich and smir.
+#	* added pccons for the Alpha under OSF/1.
+#	* Added Sony NEWS workstation entries and cit101e-rv.
+#	* Reverted `amiga'; to Kent Polk's version, as I'm told
+#	  the Verkuil entry messes up with Amiga Telnet.
+# 10.2.1 (Sun Mar  8 18:32:04 EST 1998):
+#	* Corrected attributions in 10.2.0 release notes.
+#	* Scanned the Shuford archive for new terminfos and information.
+#	* Removed sgr from qnx entry (Thomas Dickey).
+#	* Added entries for ICL and Kokusai Data Systems terminals.
+#	* Incorporated NCR terminfos from the Boundless Technology FTP site.
+#	* Incorporated att700 from the Boundless Technology FTP site.
+#	* Miscellaneous contact-address and Web-page updates.
+# 10.2.2 (Thu May  7 12:18:04 EDT 1998):
+#	* Moved Altos to OBSOLETE UNIX CONSOLES
+#	* Moved Hewlett-Packard terminals to OLDER TERMINAL TYPES, except for
+#	  the 700s which go to WORKSTATION CONSOLES.
+#	* Major reorganization of ANSI/console/VT types.  Moved vt52 to the
+#	  obsolete section.
+#	* Daisy-wheel printers moved to UFO file.
+# 10.2.3 (Tue May 12 22:59:11 EDT 1998):
+#	* Commented out hds200 is2 to avoid overflowing terminfo length limit.
+#	* Restored OT capabilities to UFO file.
+#	* add nxterm and xterm-color terminfo description (request by Cristian
+#	  Gafton <gafton@redhat.com>).
+#	* Modify rxvt terminfo description to clear alternate screen before
+#	  switching back to normal screen, for compatibility with applications
+#	  which use xterm (reported by Manoj Kasichainula <manojk@io.com>).
+#	* Modify linux terminfo description to reset color palette (reported
+#	  by Telford Tendys <telford@eng.uts.edu.au>).
+# 10.2.4 (Thu Jul  2 18:13:26 EDT 1998):
+#	* Added minitel1 entries from Alexander Montaron.
+#	* Added qnxt2 from Federico Bianchi.
+# 10.2.5: (Mon Aug 24 07:32:34 EDT 1998):
+#	* Resolve NetBSD Problem Report #4583 by adding civis/cnorm to pcvtXX.
+#	* dtterm enacs correction from Alexander V. Lukyanov.
+#	* Added ncsa-telnet, resolving Debian bug report 25341.
+#	* Added Francesco Potorti's tuned Wyse 99 entries.
+# 10.2.6: (Mon Dec 21 00:49:43 EST 1998):
+#	* Home site has changed.
+# 10.2.7: (Wed Mar  3 15:53:04 EST 1999):
+#	* Documentation fixes, mainly from David J. Mackenzie.
+#
+# 11.0.0: (Wed Mar  1 22:02:03 EST 2000)
+#	* BSD/OS console fixes from Jeffrey Honig at BSDI.
+#       ** TD's branch changes up to his 1999/10/23 version begin here 
+#	* Added arm100 terminfo entries from Dave Millen.
+#	* Added Data General entries from Hasufin.
+#	* NCSA telnet entry from Francesco Potorti as modified by TD.
+#	* Added teraterm, crt, ms-vt100, mach, mach-bold, linux-lat,
+#	  ofcons, wsvt25, wsvt25m, rcons, rcons-color, cygwin, amiga-8bit,
+#	  ibm3161-C, ibm3162.
+#	* Updated xterm entries, BSD/OS entries, AIX entries.
+#	* Updated linux, iris-ansi, screen, beterm entries.
+#	* Added full function keys for scoansi.
+#	* Typo fixes for icl6404, osborne, eterm. att6386
+#	* Corrected hp70092 acsc.
+#	* Added ibmpc from AIX 3.2.5; ibm-pc is no longer a synonym.
+#	* Added ibm5151 from AIX 3.2.5; ibmmono is no longer a synonym.
+#	* Added ibm5154 from AIX 3.2.5; ibmega is no longer a synonym.
+#	* Merged acsc, s0ds, s1ds, sgr0 into ibm5081 from AIX 3.2.5.
+#	* Merged kend, knp, kpp, mc4, mc5 into ibm3161 in from AIX 3.2.5.
+#	* Merged acsc into hft-c from AIX 3.2.5.
+#	* Updated ibm3151 from AIX 3.2.5.
+#	* Errors in TD's branch not accepted: ibm3101, ibm3151, ibm8514
+#	* Merged msgr,colors,pairs,setb,setf into ibm3164 from AIX 3.2.5.
+#	** TD's branch changes end here
+#	* Address updates from various contributors.
+#	* Historical info on basis console.
+#	* Ty Sarna's corrections to the amiga entry.
+#	* Add Kevin Turner's entry for the Wyse 85 in 8-bit mode.
+#	* Added 22 Bull-Questar terminal variants from AIX 4.1.5
+#	* Added OSF/1 console and lft from AIX 4.1.5.
+#	* Move vt2220 to vt220-old, vt220-8 to vt220, introduce vt220-8bit
+#	  from AIX 4.1.5.
+#	* swtp moved to UFO file (only 20 lines).
+#	* Added pcmw.
+# 11.0.1: (Thu Mar  2 10:49:21 EST 2000):
+#	* Disabled hpa, vpa, in rxvt.
+#	* Incorporated ansi components and generic-ansi.
+#
+# The following sets edit modes for GNU EMACS.
+# Local Variables:
+# fill-prefix:"\t"
+# fill-column:75
+# comment-column:0
+# comment-start-skip:"^#+"
+# comment-start:"# "
+# compile-command:"tic -c termtypes.master"
+# End:
+######## SHANTIH!  SHANTIH!  SHANTIH!
Index: /trunk/minix/etc/ttytab
===================================================================
--- /trunk/minix/etc/ttytab	(revision 9)
+++ /trunk/minix/etc/ttytab	(revision 9)
@@ -0,0 +1,41 @@
+# ttytab - terminals
+#
+# Device	Type		Program		Init
+console		minix		getty
+ttyc1		minix		getty
+ttyc2		minix		getty
+ttyc3		minix		getty
+tty00		unknown
+tty01		unknown
+ttyp0		network
+ttyp1		network
+ttyp2		network
+ttyp3		network
+ttyp4		network
+ttyp5		network
+ttyp6		network
+ttyp7		network
+ttyp8		network
+ttyp9		network
+ttypa		network
+ttypb		network
+ttypc		network
+ttypd		network
+ttype		network
+ttypf		network
+ttyq0		network
+ttyq1		network
+ttyq2		network
+ttyq3		network
+ttyq4		network
+ttyq5		network
+ttyq6		network
+ttyq7		network
+ttyq8		network
+ttyq9		network
+ttyqa		network
+ttyqb		network
+ttyqc		network
+ttyqd		network
+ttyqe		network
+ttyqf		network
Index: /trunk/minix/etc/usr/daily
===================================================================
--- /trunk/minix/etc/usr/daily	(revision 9)
+++ /trunk/minix/etc/usr/daily	(revision 9)
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# daily - daily cleanup of the system.
+
+# Doesn't make sense when running from CD
+if [ -f /CD ]
+then	exit
+fi
+
+case "$#:$1" in
+1:cron|1:boot)
+    caller=$1
+    ;;
+*)  echo >&2 "Usage: $0 cron|boot"
+    exit 1
+esac
+
+test -d /usr/adm || exit
+cd /usr/adm || exit
+
+# Last run must have been on a previous day.
+timestamp=daily.lasttime
+if test -f $timestamp
+then
+    set -- `ls -lT $timestamp`
+    test "$6 $7 $9" = "$(date '+%b %d %Y')" && exit
+fi
+>$timestamp
+
+# Remove three day old files from various tmp dirs.
+cleantmp -3 /tmp /usr/tmp /usr/preserve /usr/spool/lpd /usr/spool/at/past
+
+# Truncate log files in /usr/adm.
+test -d old || mkdir old || exit
+
+cycle()
+{
+    # Cycle a log file if larger than a size in kilobytes.
+    local size="`expr "$1" + "$1"`"
+    local log="$2"
+
+    if test -f "$log" && test -n "$(find "$log" -size +"$size")"
+    then
+	test -f "old/$log.2" && cp -p "old/$log.2" "old/$log.3"
+	test -f "old/$log.1" && cp -p "old/$log.1" "old/$log.2"
+	cp -p "$log" "old/$log.1"
+	: > "$log"
+    fi
+}
+
+cycle 100 wtmp 
+cycle 100 log 
+cycle  20 ftplog
+cycle 200 aftplog
+
+# Make copies of /etc/passwd and /etc/shadow if they have been changed.
+for file in passwd shadow
+do
+    if cmp -s /etc/$file old/$file.1
+    then
+	# Fine.
+    else
+	test -f old/$file.2 && cp -p old/$file.2 old/$file.3
+	test -f old/$file.1 && cp -p old/$file.1 old/$file.2
+	test -f /etc/$file && cp -p /etc/$file old/$file.1
+    fi
+done
+
+# Continue with a local script if present.
+test -f /usr/local/etc/daily && sh /usr/local/etc/daily $caller
+exit 0
Index: /trunk/minix/etc/usr/dhcptags.conf
===================================================================
--- /trunk/minix/etc/usr/dhcptags.conf	(revision 9)
+++ /trunk/minix/etc/usr/dhcptags.conf	(revision 9)
@@ -0,0 +1,63 @@
+# A list of all tags mentioned in RFC-1533.
+
+tag 1 netmask ip 1 1;
+tag 2 zoneoffset number 4 1;
+tag 3 gateway ip 1 0;
+tag 4 timeserver ip 1 0;
+tag 5 nameserver ip 1 0;
+tag 6 DNSserver ip 1 0;
+tag 7 logserver ip 1 0;
+tag 8 cookieserver ip 1 0;
+tag 9 LPR ip 1 0;
+tag 10 impress ip 1 0;
+tag 11 resource ip 1 0;
+tag 12 hostname ascii 1 0;
+tag 13 bootfilesize number 2 1;
+tag 14 coredump ip 1 0;
+tag 15 domain ascii 1 0;
+tag 16 swapserver ip 1 1;
+tag 17 rootpath ascii 1 0;
+tag 18 extensions ascii 1 0;
+tag 19 IPforwarding boolean 1 1;
+tag 20 IPnonlocalsource boolean 1 1;
+tag 21 IPpolicyfilter ip 2 0;
+tag 22 IPmaxreassembly number 2 1;
+tag 23 IPTTL number 1 1;
+tag 24 IPMTUaging number 4 1;
+tag 25 IPMTUplateau number 2 0;
+tag 26 IPMTU number 2 1;
+tag 27 IPsublocal boolean 1 1;
+tag 28 IPbroadcast ip 1 1;
+tag 29 IPmaskdiscovery boolean 1 1;
+tag 30 IPmasksupplier boolean 1 1;
+tag 31 IPdiscovery boolean 1 1;
+tag 32 IPsolicitation ip 1 1;
+tag 33 IPstaticroute ip 2 0;
+tag 34 ARPtrailer boolean 1 1;
+tag 35 ARPtimeout number 4 1;
+tag 36 ETHencapsulation boolean 1 1;
+tag 37 TCPTTL number 1 1;
+tag 38 TCPkeepaliveinterval number 4 1;
+tag 39 TCPkeepalivegarbage boolean 1 1;
+tag 40 NISdomain ascii 1 0;
+tag 41 NISserver ip 1 0;
+tag 42 NTPserver ip 1 0;
+tag 43 VENDOR octet 1 0;
+tag 44 NetBIOSNS ip 1 0;
+tag 45 NetBIOSdgram ip 1 0;
+tag 46 NetBIOSnodetype number 1 1;
+tag 47 NetBIOSscope octet 1 0;
+tag 48 Xfontserver ip 1 0;
+tag 49 XDM ip 1 0;
+tag 50 DHCPreqip ip 1 1;
+tag 51 DHCPlease number 4 1;
+tag 52 DHCPoverload number 1 1;
+tag 53 DHCPtype number 1 1;
+tag 54 DHCPserverID ip 1 1;
+tag 55 DHCPreqpar number 1 0;
+tag 56 DHCPmessage ascii 1 0;
+tag 57 DHCPsize number 2 1;
+tag 58 DHCPrenewal number 4 1;
+tag 59 DHCPrebinding number 4 1;
+tag 60 DHCPclassID ascii 1 0;
+tag 61 DHCPclientID octet 1 0;
Index: /trunk/minix/etc/usr/rc
===================================================================
--- /trunk/minix/etc/usr/rc	(revision 9)
+++ /trunk/minix/etc/usr/rc	(revision 9)
@@ -0,0 +1,193 @@
+# /usr/etc/rc - continued system initialization.
+
+RANDOM_FILE=/usr/adm/random.dat
+LOCAL_FILE=/usr/etc/rc.local
+
+case "$#:$1" in
+1:start|1:stop|1:down)
+    action=$1
+    ;;
+*)  echo >&2 "Usage: $0 start|stop|down"
+    exit 1
+esac
+
+if [ -f "$LOCAL_FILE" ]
+then	. "$LOCAL_FILE" $1
+fi
+
+disabled()
+{
+    ifs="$IFS"; IFS=,
+    for skip in `sysenv disable`
+    do 
+        if [ "$skip" = "$1" ]
+	then 	 
+                IFS="$ifs"; unset ifs
+		return 0
+	fi
+    done
+    IFS="$ifs"; unset ifs
+    return 1
+}
+
+daemonize()
+{
+    # Function to start a daemon, if it exists.
+    local IFS=':'
+    local name="$1"
+    test "$1" = tcpd && name="$2"
+
+    for dir in $PATH
+    do
+	if [ -f "$dir/$1" ]
+	then
+
+            # check if this service is disabled at the boot monitor.
+            if disabled $name; then return; fi
+
+	    echo -n " $name"
+	    "$@" &
+	    return
+	fi
+    done
+}
+
+up()
+{
+    service=$1
+    shift
+
+    # Function to dynamically start a system service
+
+    # First check if this service is disabled at the boot monitor.
+    if disabled $service; then return; fi
+
+    # Service is not disabled. Try to bring it up.
+    echo -n " $service"
+    service up /usr/sbin/$service "$@" 
+}
+
+
+DAEMONS=/etc/rc.daemons
+
+case $action in
+start)
+    # Select console font.
+    test -f /etc/font && loadfont /etc/font </dev/console
+
+    # Cleanup.
+    rm -rf /tmp/. /usr/run/. /usr/spool/lpd/. /usr/spool/locks/.
+
+    # Start servers and drivers set at the boot monitor.
+    echo -n "Starting services:"
+    up random -dev /dev/random -period 3HZ
+
+    # load random number generator
+    if [ -f $RANDOM_FILE ]
+    then
+    	cat < $RANDOM_FILE >/dev/random
+    	# overwrite $RANDOM_FILE. We don't want to use this data again
+    	dd if=/dev/random of=$RANDOM_FILE bs=1024 count=1 2> /dev/null
+    fi
+
+    # start only network drivers that are in use
+    for driver in lance rtl8139 fxp dpeth dp8390
+    do
+        if grep " $driver " /etc/inet.conf > /dev/null  2>&1
+        then 
+            eval arg=\$${driver}_arg
+	    if [ ! -z "$arg" ]; then arg="-args \"$arg\""; fi
+            eval up $driver $arg -period 5HZ
+        fi
+    done
+    up inet 
+    up printer -dev /dev/lp -period 10HZ
+    echo .
+
+    # Network initialization.
+    (: </dev/tcp) 2>/dev/null && net=t	# Is there a TCP/IP server?
+
+    echo -n "Starting daemons:"
+    daemonize update
+
+    # Ugly error message when starting cron from CD.
+    # (and cron unnecessary then so..)
+    if [ ! -f /CD ]
+    then	daemonize cron
+    else	mkdir /tmp/log
+    		rm -f /var/log || true
+		ln -s /tmp/log /var/log || true
+		. /etc/rc.cd
+    fi
+    # syslogd has not been started yet
+    rm -f /var/run/syslogd.pid
+    daemonize syslogd
+    echo .
+
+    if [ "$net" ]
+    then
+	if [ -f /etc/rc.net ]
+	then
+	    # Let a customized TCP/IP initialization script figure it out.
+	    . /etc/rc.net
+	else
+	    # Standard network daemons.
+    	    echo -n "Starting networking:"
+	    if grep -s 'psip0.*default' /etc/inet.conf 
+	    then	ifconfig -h 10.0.0.1
+	    else	daemonize dhcpd
+	    fi
+	    daemonize nonamed -L
+	    if [ -f "$DAEMONS" ]
+	    then	. "$DAEMONS"
+	    fi
+	    # The last daemon has been started, so close the list:
+	    echo .
+	fi
+    fi
+
+    if [ "$net" ]
+    then
+	# Get the nodename from the DNS and set it.
+	trap '' 2
+	intr -t 20 hostaddr -h || echo "Unable to obtain an IP address."
+	trap 2
+    fi
+
+    # Recover files being edited when the system crashed.
+    test -f /usr/bin/elvprsv && elvprsv /usr/tmp/elv*
+
+    # Run the daily cleanup on systems that are not on at night.
+    test -f /usr/etc/daily && sh /usr/etc/daily boot &
+
+;;
+stop|down)
+    	# Save random data, if /usr is mounted rw.
+	if grep ' \/usr .*rw' /etc/mtab >/dev/null
+	then
+	  if dd if=/dev/random of=$RANDOM_FILE.new bs=1024 count=1 2>/dev/null
+    	  then
+    		mv $RANDOM_FILE.new $RANDOM_FILE
+	  else
+		echo 'Failed to save random data.'
+	  fi
+	fi
+esac
+
+d=/usr/local/etc/rc.d
+# Let packages run their own scripts
+if [ -d "$d" ]
+then	if cd $d
+	then
+		echo -n "Local packages ($action): "
+		for f in *
+		do
+			if [ -x "$f" ]
+			then	echo -n "$f "
+				sh "$f" "$action"
+			fi
+		done
+		echo " done."
+	fi
+fi
+
Index: /trunk/minix/include/Makefile
===================================================================
--- /trunk/minix/include/Makefile	(revision 9)
+++ /trunk/minix/include/Makefile	(revision 9)
@@ -0,0 +1,18 @@
+
+INC=/usr/include
+GCCVERSION=3.4.3
+MKHEADERS=/usr/gnu//libexec/gcc/i386-pc-minix/$(GCCVERSION)/install-tools/mkheaders
+
+all::
+
+clean::
+
+install::
+	-rm -rf $(INC)
+	mkdir -p $(INC)
+	cpdir . $(INC)
+	@chown -R bin $(INC)
+	@rm -f $(INC)/Makefile
+
+gcc: install
+	SHELL=/bin/sh; if [ -f $(MKHEADERS) ] ; then sh -e $(MKHEADERS) ; fi
Index: /trunk/minix/include/a.out.h
===================================================================
--- /trunk/minix/include/a.out.h	(revision 9)
+++ /trunk/minix/include/a.out.h	(revision 9)
@@ -0,0 +1,118 @@
+/* The <a.out> header file describes the format of executable files. */
+
+#ifndef _AOUT_H
+#define _AOUT_H
+
+struct	exec {			/* a.out header */
+  unsigned char	a_magic[2];	/* magic number */
+  unsigned char	a_flags;	/* flags, see below */
+  unsigned char	a_cpu;		/* cpu id */
+  unsigned char	a_hdrlen;	/* length of header */
+  unsigned char	a_unused;	/* reserved for future use */
+  unsigned short a_version;	/* version stamp (not used at present) */
+  long		a_text;		/* size of text segement in bytes */
+  long		a_data;		/* size of data segment in bytes */
+  long		a_bss;		/* size of bss segment in bytes */
+  long		a_entry;	/* entry point */
+  long		a_total;	/* total memory allocated */
+  long		a_syms;		/* size of symbol table */
+
+  /* SHORT FORM ENDS HERE */
+  long		a_trsize;	/* text relocation size */
+  long		a_drsize;	/* data relocation size */
+  long		a_tbase;	/* text relocation base */
+  long		a_dbase;	/* data relocation base */
+};
+
+#define A_MAGIC0      (unsigned char) 0x01
+#define A_MAGIC1      (unsigned char) 0x03
+#define BADMAG(X)     ((X).a_magic[0] != A_MAGIC0 ||(X).a_magic[1] != A_MAGIC1)
+
+/* CPU Id of TARGET machine (byte order coded in low order two bits) */
+#define A_NONE	0x00	/* unknown */
+#define A_I8086	0x04	/* intel i8086/8088 */
+#define A_M68K	0x0B	/* motorola m68000 */
+#define A_NS16K	0x0C	/* national semiconductor 16032 */
+#define A_I80386 0x10	/* intel i80386 */
+#define A_SPARC	0x17	/* Sun SPARC */
+
+#define A_BLR(cputype)	((cputype&0x01)!=0) /* TRUE if bytes left-to-right */
+#define A_WLR(cputype)	((cputype&0x02)!=0) /* TRUE if words left-to-right */
+
+/* Flags. */
+#define A_UZP	0x01	/* unmapped zero page (pages) */
+#define A_PAL	0x02	/* page aligned executable */
+#define A_NSYM	0x04	/* new style symbol table */
+#define A_IMG   0x08	/* image instead of executable (e.g. root FS) */
+#define A_EXEC	0x10	/* executable */
+#define A_SEP	0x20	/* separate I/D */
+#define A_PURE	0x40	/* pure text */		/* not used */
+#define A_TOVLY	0x80	/* text overlay */	/* not used */
+
+/* Offsets of various things. */
+#define A_MINHDR	32
+#define	A_TEXTPOS(X)	((long)(X).a_hdrlen)
+#define A_DATAPOS(X)	(A_TEXTPOS(X) + (X).a_text)
+#define	A_HASRELS(X)	((X).a_hdrlen > (unsigned char) A_MINHDR)
+#define A_HASEXT(X)	((X).a_hdrlen > (unsigned char) (A_MINHDR +  8))
+#define A_HASLNS(X)	((X).a_hdrlen > (unsigned char) (A_MINHDR + 16))
+#define A_HASTOFF(X)	((X).a_hdrlen > (unsigned char) (A_MINHDR + 24))
+#define A_TRELPOS(X)	(A_DATAPOS(X) + (X).a_data)
+#define A_DRELPOS(X)	(A_TRELPOS(X) + (X).a_trsize)
+#define A_SYMPOS(X)	(A_TRELPOS(X) + (A_HASRELS(X) ? \
+  			((X).a_trsize + (X).a_drsize) : 0))
+
+struct reloc {
+  long r_vaddr;			/* virtual address of reference */
+  unsigned short r_symndx;	/* internal segnum or extern symbol num */
+  unsigned short r_type;	/* relocation type */
+};
+
+/* r_tyep values: */
+#define R_ABBS		0
+#define R_RELLBYTE	2
+#define R_PCRBYTE	3
+#define R_RELWORD	4
+#define R_PCRWORD	5
+#define R_RELLONG	6
+#define R_PCRLONG	7
+#define R_REL3BYTE	8
+#define R_KBRANCHE	9
+
+/* r_symndx for internal segments */
+#define S_ABS		((unsigned short)-1)
+#define S_TEXT		((unsigned short)-2)
+#define S_DATA		((unsigned short)-3)
+#define S_BSS		((unsigned short)-4)
+
+struct nlist {			/* symbol table entry */
+  char n_name[8];		/* symbol name */
+  long n_value;			/* value */
+  unsigned char	n_sclass;	/* storage class */
+  unsigned char	n_numaux;	/* number of auxiliary entries (not used) */
+  unsigned short n_type;	/* language base and derived type (not used) */
+};
+
+/* Low bits of storage class (section). */
+#define	N_SECT		  07	/* section mask */
+#define N_UNDF		  00	/* undefined */
+#define N_ABS		  01	/* absolute */
+#define N_TEXT		  02	/* text */
+#define N_DATA		  03	/* data */
+#define	N_BSS		  04	/* bss */
+#define N_COMM		  05	/* (common) */
+
+/* High bits of storage class. */
+#define N_CLASS		0370	/* storage class mask */
+#define C_NULL
+#define C_EXT		0020	/* external symbol */
+#define C_STAT		0030	/* static */
+
+/* Function prototypes. */
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+_PROTOTYPE( int nlist, (char *_file, struct nlist *_nl)			);
+
+#endif /* _AOUT_H */
Index: /trunk/minix/include/alloca.h
===================================================================
--- /trunk/minix/include/alloca.h	(revision 9)
+++ /trunk/minix/include/alloca.h	(revision 9)
@@ -0,0 +1,24 @@
+/*	alloca.h - The dreaded alloca() function.
+ */
+
+#ifndef _ALLOCA_H
+#define _ALLOCA_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+#if __GNUC__
+
+/* The compiler recognizes this special keyword, and inlines the code. */
+#define alloca(size)	__builtin_alloca(size)
+
+#endif /* __GCC__ */
+
+#if __ACK__ || __CCC__
+
+_PROTOTYPE(void *alloca, (size_t _size)					);
+
+#endif /* __ACK__ || __CCC__ */
+
+#endif /* _ALLOCA_H */
Index: /trunk/minix/include/ansi.h
===================================================================
--- /trunk/minix/include/ansi.h	(revision 9)
+++ /trunk/minix/include/ansi.h	(revision 9)
@@ -0,0 +1,69 @@
+/* The <ansi.h> header attempts to decide whether the compiler has enough
+ * conformance to Standard C for Minix to take advantage of.  If so, the
+ * symbol _ANSI is defined (as 31459).  Otherwise _ANSI is not defined
+ * here, but it may be defined by applications that want to bend the rules.
+ * The magic number in the definition is to inhibit unnecessary bending
+ * of the rules.  (For consistency with the new '#ifdef _ANSI" tests in
+ * the headers, _ANSI should really be defined as nothing, but that would
+ * break many library routines that use "#if _ANSI".)
+
+ * If _ANSI ends up being defined, a macro
+ *
+ *	_PROTOTYPE(function, params)
+ *
+ * is defined.  This macro expands in different ways, generating either
+ * ANSI Standard C prototypes or old-style K&R (Kernighan & Ritchie)
+ * prototypes, as needed.  Finally, some programs use _CONST, _VOIDSTAR etc
+ * in such a way that they are portable over both ANSI and K&R compilers.
+ * The appropriate macros are defined here.
+ */
+
+#ifndef _ANSI_H
+#define _ANSI_H
+
+#if __STDC__ == 1
+#define _ANSI		31459	/* compiler claims full ANSI conformance */
+#endif
+
+#ifdef __GNUC__
+#define _ANSI		31459	/* gcc conforms enough even in non-ANSI mode */
+#endif
+
+#ifdef _ANSI
+
+/* Keep everything for ANSI prototypes. */
+#define	_PROTOTYPE(function, params)	function params
+#define	_ARGS(params)			params
+
+#define	_VOIDSTAR	void *
+#define	_VOID		void
+#define	_CONST		const
+#define	_VOLATILE	volatile
+#define _SIZET		size_t
+
+#else
+
+/* Throw away the parameters for K&R prototypes. */
+#define	_PROTOTYPE(function, params)	function()
+#define	_ARGS(params)			()
+
+#define	_VOIDSTAR	void *
+#define	_VOID		void
+#define	_CONST
+#define	_VOLATILE
+#define _SIZET		int
+
+#endif /* _ANSI */
+
+/* This should be defined as restrict when a C99 compiler is used. */
+#define _RESTRICT
+
+/* Setting any of _MINIX, _POSIX_C_SOURCE or _POSIX2_SOURCE implies
+ * _POSIX_SOURCE.  (Seems wrong to put this here in ANSI space.)
+ */
+#if defined(_MINIX) || _POSIX_C_SOURCE > 0 || defined(_POSIX2_SOURCE)
+#undef _POSIX_SOURCE
+#define _POSIX_SOURCE	1
+#endif
+
+#endif /* ANSI_H */
Index: /trunk/minix/include/arpa/inet.h
===================================================================
--- /trunk/minix/include/arpa/inet.h	(revision 9)
+++ /trunk/minix/include/arpa/inet.h	(revision 9)
@@ -0,0 +1,33 @@
+/*
+arpa/inet.h
+*/
+
+#ifndef _ARPA__INET_H
+#define _ARPA__INET_H
+
+#include <stdint.h>
+
+/* Open Group Base Specifications Issue 6 (not complete): */
+
+#ifndef _IN_ADDR_T
+#define _IN_ADDR_T
+/* Has to match corresponding declaration in <netinet/in.h> */
+typedef uint32_t	in_addr_t;
+#endif /* _IN_ADDR_T */
+
+#ifndef _STRUCT_IN_ADDR
+#define _STRUCT_IN_ADDR
+/* Has to match corresponding declaration in <netinet/in.h> */
+struct in_addr
+{
+	in_addr_t	s_addr;
+};
+#endif
+
+_PROTOTYPE( uint32_t htonl, (uint32_t _hostval)				);
+_PROTOTYPE( uint16_t htons, (uint16_t _hostval)				);
+_PROTOTYPE( char *inet_ntoa, (struct in_addr _in)			);
+_PROTOTYPE( uint32_t ntohl, (uint32_t _netval)				);
+_PROTOTYPE( uint16_t ntohs, (uint16_t _netval)				);
+
+#endif /* _ARPA__INET_H */
Index: /trunk/minix/include/assert.h
===================================================================
--- /trunk/minix/include/assert.h	(revision 9)
+++ /trunk/minix/include/assert.h	(revision 9)
@@ -0,0 +1,39 @@
+/* The <assert.h> header contains a macro called "assert" that allows 
+ * programmers to put assertions in the code.  These assertions can be verified
+ * at run time.  If an assertion fails, an error message is printed and the
+ * program aborts.
+ * Assertion checking can be disabled by adding the statement
+ *
+ *	#define NDEBUG
+ *
+ * to the program before the 
+ *
+ *	#include <assert.h>
+ *
+ * statement.
+ */
+
+#undef assert
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+#ifdef NDEBUG
+/* Debugging disabled -- do not evaluate assertions. */
+#define assert(expr)  ((void) 0)
+#else
+/* Debugging enabled -- verify assertions at run time. */
+#ifdef _ANSI
+#define	__makestr(x)	# x
+#define	__xstr(x)	__makestr(x)
+
+_PROTOTYPE( void __bad_assertion, (const char *_mess) );
+#define	assert(expr)	((expr)? (void)0 : \
+				__bad_assertion("Assertion \"" #expr \
+				    "\" failed, file " __xstr(__FILE__) \
+				    ", line " __xstr(__LINE__) "\n"))
+#else
+#define assert(expr) ((void) ((expr) ? 0 : __assert( __FILE__,  __LINE__)))
+#endif /* _ANSI */
+#endif
Index: /trunk/minix/include/configfile.h
===================================================================
--- /trunk/minix/include/configfile.h	(revision 9)
+++ /trunk/minix/include/configfile.h	(revision 9)
@@ -0,0 +1,44 @@
+/*	configfile.h - Generic configuration file format.
+ *							Author: Kees J. Bot
+ *								5 Jun 1999
+ */
+#ifndef _CONFIGFILE_H
+#define _CONFIGFILE_H
+
+/* Data can only be modified inside the library. */
+#ifndef _c
+#define _c	const
+#endif
+
+typedef _c struct config {	/* Contents of a generic configuration file. */
+_c	struct config	*next;		/* Next configuration file thing. */
+_c	struct config	*list;		/* For a { sublist }. */
+	const char	*file;		/* File and line where this is found. */
+	unsigned	line;
+	int		flags;		/* Special flags. */
+	char		word[1];	/* Payload. */
+} config_t;
+
+#define CFG_CLONG	0x0001		/* strtol(word, &end, 0) is valid. */
+#define CFG_OLONG	0x0002		/* strtol(word, &end, 010). */
+#define CFG_DLONG	0x0004		/* strtol(word, &end, 10). */
+#define CFG_XLONG	0x0008		/* strtol(word, &end, 0x10). */
+#define CFG_CULONG	0x0010		/* strtoul(word, &end, 0). */
+#define CFG_OULONG	0x0020		/* strtoul(word, &end, 010). */
+#define CFG_DULONG	0x0040		/* strtoul(word, &end, 10). */
+#define CFG_XULONG	0x0080		/* strtoul(word, &end, 0x10). */
+#define CFG_STRING	0x0100		/* The word is enclosed in quotes. */
+#define CFG_SUBLIST	0x0200		/* This is a sublist, so no word. */
+#define CFG_ESCAPED	0x0400		/* Escapes are still marked with \. */
+
+config_t *config_read(const char *_file, int flags, config_t *_cfg);
+void config_delete(config_t *_cfg);
+int config_renewed(config_t *_cfg);
+size_t config_length(config_t *_cfg);
+#define config_issub(cfg)	(!!((cfg)->flags & CFG_SUBLIST))
+#define config_isatom(cfg)	(!config_issub(cfg))
+#define config_isstring(cfg)	(!!((cfg)->flags & CFG_STRING))
+
+#undef _c
+
+#endif /* _CONFIGFILE_H */
Index: /trunk/minix/include/ctype.h
===================================================================
--- /trunk/minix/include/ctype.h	(revision 9)
+++ /trunk/minix/include/ctype.h	(revision 9)
@@ -0,0 +1,57 @@
+/* The <ctype.h> header file defines some macros used to identify characters.
+ * It works by using a table stored in chartab.c. When a character is presented
+ * to one of these macros, the character is used as an index into the table
+ * (__ctype) to retrieve a byte.  The relevant bit is then extracted.
+ */
+
+#ifndef _CTYPE_H
+#define _CTYPE_H
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+extern char	__ctype[];	/* property array defined in chartab.c */
+
+#define _U		0x01	/* this bit is for upper-case letters [A-Z] */
+#define _L		0x02	/* this bit is for lower-case letters [a-z] */
+#define _N		0x04	/* this bit is for numbers [0-9] */
+#define _S		0x08	/* this bit is for white space \t \n \f etc */
+#define _P		0x10	/* this bit is for punctuation characters */
+#define _C		0x20	/* this bit is for control characters */
+#define _X		0x40	/* this bit is for hex digits [a-f] and [A-F]*/
+
+/* Function Prototypes (have to go before the macros). */
+_PROTOTYPE( int isalnum, (int  _c)  );	/* alphanumeric [a-z], [A-Z], [0-9] */
+_PROTOTYPE( int isalpha, (int  _c)  );	/* alphabetic */
+_PROTOTYPE( int iscntrl, (int  _c)  );	/* control characters */
+_PROTOTYPE( int isdigit, (int  _c)  );	/* digit [0-9] */
+_PROTOTYPE( int isgraph, (int  _c)  );	/* graphic character */
+_PROTOTYPE( int islower, (int  _c)  );	/* lower-case letter [a-z] */
+_PROTOTYPE( int isprint, (int  _c)  );	/* printable character */
+_PROTOTYPE( int ispunct, (int  _c)  );	/* punctuation mark */
+_PROTOTYPE( int isspace, (int  _c)  );	/* white space sp, \f, \n, \r, \t, \v*/
+_PROTOTYPE( int isupper, (int  _c)  );	/* upper-case letter [A-Z] */
+_PROTOTYPE( int isxdigit,(int  _c)  );	/* hex digit [0-9], [a-f], [A-F] */
+_PROTOTYPE( int tolower, (int  _c)  );	/* convert to lower-case */
+_PROTOTYPE( int toupper, (int  _c)  );	/* convert to upper-case */
+_PROTOTYPE( int toascii, (int  _c)  );	/* convert to 7-bit ASCII */
+
+/* Macros for identifying character classes. */
+#define isalnum(c)	((__ctype+1)[c]&(_U|_L|_N))
+#define isalpha(c)	((__ctype+1)[c]&(_U|_L))
+#define iscntrl(c)	((__ctype+1)[c]&_C)
+#define isgraph(c)	((__ctype+1)[c]&(_P|_U|_L|_N))
+#define ispunct(c)	((__ctype+1)[c]&_P)
+#define isspace(c)	((__ctype+1)[c]&_S)
+#define isxdigit(c)	((__ctype+1)[c]&(_N|_X))
+
+#define isdigit(c)	((unsigned) ((c)-'0') < 10)
+#define islower(c)	((unsigned) ((c)-'a') < 26)
+#define isupper(c)	((unsigned) ((c)-'A') < 26)
+#define isprint(c)	((unsigned) ((c)-' ') < 95)
+#define isascii(c)	((unsigned) (c) < 128)
+
+#define toascii(c)	((c) & 0x7f)
+
+#endif /* _CTYPE_H */
Index: /trunk/minix/include/curses.h
===================================================================
--- /trunk/minix/include/curses.h	(revision 9)
+++ /trunk/minix/include/curses.h	(revision 9)
@@ -0,0 +1,226 @@
+/* curses.h - defines macros and prototypes for curses */
+
+#ifndef _CURSES_H
+#define _CURSES_H
+
+#include <termios.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+typedef int bool;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef ERR
+#define ERR (-1)	/* general error flag */
+#endif
+#ifndef OK
+#define OK 0		/* general OK flag */
+#endif
+
+/* Macros. */
+#define box(win,vc,hc) wbox(win,0,0,0,0,vc,hc)
+#define addch(ch) waddch(stdscr,ch)
+#define mvaddch(y,x,ch) (wmove(stdscr,y,x)==ERR?ERR:waddch(stdscr,ch))
+#define mvwaddch(win,y,x,ch) (wmove(win,y,x)==ERR?ERR:waddch(win,ch))
+#define getch() wgetch(stdscr)
+#define mvgetch(y,x) (wmove(stdscr,y,x)==ERR?ERR:wgetch(stdscr))
+#define mvwgetch(win,y,x) (wmove(win,y,x)==ERR?ERR:wgetch(win))
+#define addstr(str) waddstr(stdscr,str)
+#define mvaddstr(y,x,str) (wmove(stdscr,y,x)==ERR?ERR:waddstr(stdscr,str))
+#define mvwaddstr(win,y,x,str) (wmove(win,y,x)==ERR?ERR:waddstr(win,str))
+#define getstr(str) wgetstr(stdscr,str)
+#define mvgetstr(y,x,str) (wmove(stdscr,y,x)==ERR?ERR:wgetstr(stdscr,str))
+#define mvwgetstr(win,y,x,str) (wmove(win,y,x)==ERR?ERR:wgetstr(win,str))
+#define move(y,x) wmove(stdscr,y,x)
+#define clear() wclear(stdscr)
+#define erase() werase(stdscr)
+#define clrtobot() wclrtobot(stdscr)
+#define mvclrtobot(y,x) (wmove(stdscr,y,x)==ERR?ERR:wclrtobot(stdscr))
+#define mvwclrtobot(win,y,x) (wmove(win,y,x)==ERR?ERR:wclrtobot(win))
+#define clrtoeol() wclrtoeol(stdscr)
+#define mvclrtoeol(y,x) (wmove(stdscr,y,x)==ERR?ERR:wclrtoeol(stdscr))
+#define mvwclrtoeol(win,y,x) (wmove(win,y,x)==ERR?ERR:wclrtoeol(win))
+#define insertln() winsertln(stdscr)
+#define mvinsertln(y,x) (wmove(stdscr,y,x)==ERR?ERR:winsertln(stdscr))
+#define mvwinsertln(win,y,x) (wmove(win,y,x)==ERR?ERR:winsertln(win))
+#define deleteln() wdeleteln(stdscr)
+#define mvdeleteln(y,x) (wmove(stdscr,y,x)==ERR?ERR:wdeleteln(stdscr))
+#define mvwdeleteln(win,y,x) (wmove(win,y,x)==ERR?ERR:wdeleteln(win))
+#define refresh() wrefresh(stdscr)
+#define inch() winch(stdscr)
+#define insch(ch) winsch(stdscr,ch)
+#define mvinsch(y,x,ch) (wmove(stdscr,y,x)==ERR?ERR:winsch(stdscr,ch))
+#define mvwinsch(win,y,x,ch) (wmove(win,y,x)==ERR?ERR:winsch(win,ch))
+#define delch() wdelch(stdscr)
+#define mvdelch(y,x) (wmove(stdscr,y,x)==ERR?ERR:wdelch(stdscr))
+#define mvwdelch(win,y,x) (wmove(win,y,x)==ERR?ERR:wdelch(win))
+#define standout() wstandout(stdscr)
+#define wstandout(win) ((win)->_attrs |= A_STANDOUT)
+#define standend() wstandend(stdscr)
+#define wstandend(win) ((win)->_attrs &= ~A_STANDOUT)
+#define attrset(attrs) wattrset(stdscr, attrs)
+#define wattrset(win, attrs) ((win)->_attrs = (attrs))
+#define attron(attrs) wattron(stdscr, attrs)
+#define wattron(win, attrs) ((win)->_attrs |= (attrs))
+#define attroff(attrs) wattroff(stdscr,attrs)
+#define wattroff(win, attrs) ((win)->_attrs &= ~(attrs))
+#define resetty() tcsetattr(1, TCSANOW, &_orig_tty)
+#define getyx(win,y,x) (y = (win)->_cury, x = (win)->_curx)
+
+/* Video attribute definitions. */
+#define	A_BLINK        0x0100
+#define	A_BLANK        0
+#define	A_BOLD         0x0200
+#define	A_DIM          0
+#define	A_PROTECT      0
+#define	A_REVERSE      0x0400
+#define	A_STANDOUT     0x0800
+#define	A_UNDERLINE    0x1000
+#define	A_ALTCHARSET   0x2000
+
+/* Type declarations. */
+typedef struct {
+  int	   _cury;			/* current pseudo-cursor */
+  int	   _curx;
+  int      _maxy;			/* max coordinates */
+  int      _maxx;
+  int      _begy;			/* origin on screen */
+  int      _begx;
+  int	   _flags;			/* window properties */
+  int	   _attrs;			/* attributes of written characters */
+  int      _tabsize;			/* tab character size */
+  bool	   _clear;			/* causes clear at next refresh */
+  bool	   _leave;			/* leaves cursor as it happens */
+  bool	   _scroll;			/* allows window scrolling */
+  bool	   _nodelay;			/* input character wait flag */
+  bool	   _keypad;			/* flags keypad key mode active */
+  int    **_line;			/* pointer to line pointer array */
+  int	  *_minchng;			/* First changed character in line */
+  int	  *_maxchng;			/* Last changed character in line */
+  int	   _regtop;			/* Top/bottom of scrolling region */
+  int	   _regbottom;
+} WINDOW;
+
+/* External variables */
+extern int LINES;			/* terminal height */
+extern int COLS;			/* terminal width */
+extern bool NONL;			/* \n causes CR too ? */
+extern WINDOW *curscr;			/* the current screen image */
+extern WINDOW *stdscr;			/* the default screen window */
+extern struct termios _orig_tty, _tty;
+
+extern unsigned int ACS_ULCORNER;	/* terminal dependent block grafic */
+extern unsigned int ACS_LLCORNER;	/* charcters.  Forget IBM, we are */
+extern unsigned int ACS_URCORNER;	/* independent of their charset. :-) */
+extern unsigned int ACS_LRCORNER;
+extern unsigned int ACS_RTEE;
+extern unsigned int ACS_LTEE;
+extern unsigned int ACS_BTEE;
+extern unsigned int ACS_TTEE;
+extern unsigned int ACS_HLINE;
+extern unsigned int ACS_VLINE;
+extern unsigned int ACS_PLUS;
+extern unsigned int ACS_S1;
+extern unsigned int ACS_S9;
+extern unsigned int ACS_DIAMOND;
+extern unsigned int ACS_CKBOARD;
+extern unsigned int ACS_DEGREE;
+extern unsigned int ACS_PLMINUS;
+extern unsigned int ACS_BULLET;
+extern unsigned int ACS_LARROW;
+extern unsigned int ACS_RARROW;
+extern unsigned int ACS_DARROW;
+extern unsigned int ACS_UARROW;
+extern unsigned int ACS_BOARD;
+extern unsigned int ACS_LANTERN;
+extern unsigned int ACS_BLOCK;
+
+_PROTOTYPE( char *unctrl, (int _c) );
+_PROTOTYPE( int baudrate, (void));
+_PROTOTYPE( void beep, (void));
+_PROTOTYPE( void cbreak, (void));
+_PROTOTYPE( void clearok, (WINDOW *_win, bool _flag) );
+_PROTOTYPE( void clrscr, (void));
+_PROTOTYPE( void curs_set, (int _visibility) );
+_PROTOTYPE( void delwin, (WINDOW *_win) );
+_PROTOTYPE( void doupdate, (void));
+_PROTOTYPE( void echo, (void));
+_PROTOTYPE( int endwin, (void));
+_PROTOTYPE( int erasechar, (void));
+_PROTOTYPE( void fatal, (char *_s) );
+_PROTOTYPE( int fixterm, (void));
+_PROTOTYPE( void flash, (void));
+_PROTOTYPE( void gettmode, (void));
+_PROTOTYPE( void idlok, (WINDOW *_win, bool _flag) );
+_PROTOTYPE( WINDOW *initscr, (void));
+_PROTOTYPE( void keypad, (WINDOW *_win, bool _flag) );
+_PROTOTYPE( int killchar, (void));
+_PROTOTYPE( void leaveok, (WINDOW *_win, bool _flag) );
+_PROTOTYPE( char *longname, (void));
+_PROTOTYPE( void meta, (WINDOW *_win, bool _flag) );
+_PROTOTYPE( int mvcur, (int _oldy, int _oldx, int _newy, int _newx) );
+_PROTOTYPE( int mvinch, (int _y, int _x) );
+_PROTOTYPE( int mvprintw, (int _y, int _x, const char *_fmt, ...) );
+_PROTOTYPE( int mvscanw, (int _y, int _x, const char *_fmt, ...) );
+_PROTOTYPE( int mvwin, (WINDOW *_win, int _begy, int _begx) );
+_PROTOTYPE( int mvwinch, (WINDOW *_win, int _y, int _x) );
+_PROTOTYPE( int mvwprintw, (WINDOW *_win, int _y, int _x, const char *_fmt,
+									...) );
+_PROTOTYPE( int mvwscanw, (WINDOW *_win, int _y, int _x, const char *_fmt,
+									...) );
+_PROTOTYPE( WINDOW *newwin, (int _num_lines, int _num_cols, int _y, int _x));
+_PROTOTYPE( void nl, (void));
+_PROTOTYPE( void nocbreak, (void));
+_PROTOTYPE( void nodelay, (WINDOW *_win, bool _flag) );
+_PROTOTYPE( void noecho, (void));
+_PROTOTYPE( void nonl, (void));
+_PROTOTYPE( void noraw, (void));
+_PROTOTYPE( void outc, (int _c) );
+_PROTOTYPE( void  overlay, (WINDOW *_win1, WINDOW *_win2) );
+_PROTOTYPE( void  overwrite, (WINDOW *_win1, WINDOW *_win2) );
+_PROTOTYPE( void poscur, (int _r, int _c) );
+_PROTOTYPE( int printw, (const char *_fmt, ...) );
+_PROTOTYPE( void raw, (void));
+_PROTOTYPE( int resetterm, (void));
+_PROTOTYPE( int saveoldterm, (void));
+_PROTOTYPE( int saveterm, (void));
+_PROTOTYPE( int savetty, (void));
+_PROTOTYPE( int scanw, (const char *_fmt, ...) );
+_PROTOTYPE( void scroll, (WINDOW *_win) );
+_PROTOTYPE( void scrollok, (WINDOW *_win, bool _flag) );
+_PROTOTYPE( int setscrreg, (int _top, int _bottom) );
+_PROTOTYPE( int setterm, (char *_type) );
+_PROTOTYPE( int setupterm, (void));
+_PROTOTYPE( WINDOW *subwin, (WINDOW *_orig, int _nlines, int _ncols, int _y,
+					int _x));
+_PROTOTYPE( int tabsize, (int _ts) );
+_PROTOTYPE( void touchwin, (WINDOW *_win) );
+_PROTOTYPE( int waddch, (WINDOW *_win, int _c) );
+_PROTOTYPE( int waddstr, (WINDOW *_win, char *_str) );
+_PROTOTYPE( int wbox, (WINDOW *_win, int _ymin, int _xmin, int _ymax,
+				int _xmax, unsigned int _v, unsigned int _h) );
+_PROTOTYPE( void wclear, (WINDOW *_win) );
+_PROTOTYPE( int wclrtobot, (WINDOW *_win) );
+_PROTOTYPE( int wclrtoeol, (WINDOW *_win) );
+_PROTOTYPE( int wdelch, (WINDOW *_win) );
+_PROTOTYPE( int wdeleteln, (WINDOW *_win) );
+_PROTOTYPE( void werase, (WINDOW *_win) );
+_PROTOTYPE( int wgetch, (WINDOW *_win) );
+_PROTOTYPE( int wgetstr, (WINDOW *_win, char *_str) );
+_PROTOTYPE( int winch, (WINDOW *_win) );
+_PROTOTYPE( int winsch, (WINDOW *_win, int _c) );
+_PROTOTYPE( int winsertln, (WINDOW *_win) );
+_PROTOTYPE( int wmove, (WINDOW *_win, int _y, int _x) );
+_PROTOTYPE( void wnoutrefresh, (WINDOW *_win) );
+_PROTOTYPE( int wprintw, (WINDOW *_win, const char *_fmt, ...));
+_PROTOTYPE( void wrefresh, (WINDOW *_win) );
+_PROTOTYPE( int wscanw, (WINDOW *_win, const char *_fmt, ...));
+_PROTOTYPE( int wsetscrreg, (WINDOW *_win, int _top, int _bottom) );
+_PROTOTYPE( int wtabsize, (WINDOW *_win, int _ts) );
+
+#endif /* _CURSES_H */
Index: /trunk/minix/include/dirent.h
===================================================================
--- /trunk/minix/include/dirent.h	(revision 9)
+++ /trunk/minix/include/dirent.h	(revision 9)
@@ -0,0 +1,92 @@
+/*	dirent.h - Declarations for directory reading routines.
+ *							Author: Kees J. Bot
+ *								24 Apr 1989
+ * 
+ * Note: The V7 format directory entries used under Minix must be transformed
+ * into a struct dirent with a d_name of at least 15 characters.  Given that
+ * we have to transform V7 entries anyhow it is little trouble to let the
+ * routines understand the so-called "flex" directory format too.
+ */
+
+#ifndef _DIRENT_H
+#define _DIRENT_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <sys/dir.h>
+
+/* _fl_direct is a flexible directory entry.  Actually it's a union of 8
+ * characters and the 3 fields defined below. 
+ */
+
+/* Flexible directory entry: */
+struct _fl_direct {		/* First slot in an entry */
+	ino_t		d_ino;
+	unsigned char	d_extent;
+	char		d_name[3];  /* two characters for the shortest name */
+};
+
+	/* Name of length len needs _EXTENT(len) extra slots. */
+#define _EXTENT(len)	(((len) + 5) >> 3)
+
+/* Version 7 directory entry: */
+struct _v7_direct {		
+	ino_t		d_ino;
+	char		d_name[DIRSIZ];
+};
+
+/* The block size must be at least 1024 bytes, because otherwise
+ * the superblock (at 1024 bytes) overlaps with other filesystem data.
+ */
+#define _MIN_BLOCK_SIZE		 1024
+
+/* The below is allocated in some parts of the system as the largest
+ * a filesystem block can be. For instance, the boot monitor allocates
+ * 3 of these blocks and has to fit within 64kB, so this can't be
+ * increased without taking that into account.
+ */
+#define _MAX_BLOCK_SIZE		 4096
+
+/* This is the block size for the fixed versions of the filesystem (V1/V2) */
+#define _STATIC_BLOCK_SIZE	1024
+
+#define _STATIC_FLEX_PER_BLOCK (_STATIC_BLOCK_SIZE/sizeof(struct _fl_direct))
+#define _FLEX_PER_V7 (_EXTENT(DIRSIZ) + 1)
+#define _FLEX_PER_BLOCK (_STATIC_BLOCK_SIZE/sizeof(struct _fl_direct))
+
+/* Definitions for the directory(3) routines: */
+typedef struct {
+	char		_fd;	/* Filedescriptor of open directory */
+	char		_v7;	/* Directory is Version 7 */
+	short		_count;	/* This many objects in buf */
+	off_t		_pos;	/* Position in directory file */
+	struct _fl_direct  *_ptr;	/* Next slot in buf */
+	struct _fl_direct  _buf[_FLEX_PER_BLOCK]; /* One block of a directory file */
+	struct _fl_direct  _v7f[_FLEX_PER_V7];	 /* V7 entry transformed to flex */
+} DIR;
+
+#define _DIRENT_NAME_LEN 61
+
+struct dirent {		/* Largest entry (8 slots) */
+	ino_t		d_ino;		/* I-node number */
+	unsigned char	d_extent;	/* Extended with this many slots */
+	char		d_name[_DIRENT_NAME_LEN];	/* Null terminated name */
+};
+
+/* Function Prototypes. */
+_PROTOTYPE( int closedir, (DIR *_dirp)					);
+_PROTOTYPE( DIR *opendir, (const char *_dirname)			);
+_PROTOTYPE( struct dirent *readdir, (DIR *_dirp)			);
+_PROTOTYPE( void rewinddir, (DIR *_dirp)				);
+
+#ifdef _MINIX
+_PROTOTYPE( int seekdir, (DIR *_dirp, off_t _loc)			);
+_PROTOTYPE( off_t telldir, (DIR *_dirp)					);
+
+#define   dirfd(dirp)     ((dirp)->_fd)
+
+#endif
+
+#endif /* _DIRENT_H */
Index: /trunk/minix/include/env.h
===================================================================
--- /trunk/minix/include/env.h	(revision 9)
+++ /trunk/minix/include/env.h	(revision 9)
@@ -0,0 +1,4 @@
+_PROTOTYPE( int env_parse, (char *env, char *fmt, int field,
+			long *param, long min, long max)		);
+_PROTOTYPE( void env_panic, (char *env)					);
+_PROTOTYPE( int env_prefix, (char *env, char *prefix)			);
Index: /trunk/minix/include/errno.h
===================================================================
--- /trunk/minix/include/errno.h	(revision 9)
+++ /trunk/minix/include/errno.h	(revision 9)
@@ -0,0 +1,121 @@
+/* The <errno.h> header defines the numbers of the various errors that can
+ * occur during program execution.  They are visible to user programs and 
+ * should be small positive integers.  However, they are also used within 
+ * MINIX, where they must be negative.  For example, the READ system call is 
+ * executed internally by calling do_read().  This function returns either a 
+ * (negative) error number or a (positive) number of bytes actually read.
+ *
+ * To solve the problem of having the error numbers be negative inside the
+ * the system and positive outside, the following mechanism is used.  All the
+ * definitions are are the form:
+ *
+ *	#define EPERM		(_SIGN 1)
+ *
+ * If the macro _SYSTEM is defined, then  _SIGN is set to "-", otherwise it is
+ * set to "".  Thus when compiling the operating system, the  macro _SYSTEM
+ * will be defined, setting EPERM to (- 1), whereas when when this
+ * file is included in an ordinary user program, EPERM has the value ( 1).
+ */
+
+#ifndef _ERRNO_H		/* check if <errno.h> is already included */
+#define _ERRNO_H		/* it is not included; note that fact */
+
+/* Now define _SIGN as "" or "-" depending on _SYSTEM. */
+#ifdef _SYSTEM
+#   define _SIGN         -
+#   define OK            0
+#else
+#   define _SIGN         
+#endif
+
+extern int errno;		  /* place where the error numbers go */
+
+/* Here are the numerical values of the error numbers. */
+#define _NERROR               70  /* number of errors */  
+
+#define EGENERIC      (_SIGN 99)  /* generic error */
+#define EPERM         (_SIGN  1)  /* operation not permitted */
+#define ENOENT        (_SIGN  2)  /* no such file or directory */
+#define ESRCH         (_SIGN  3)  /* no such process */
+#define EINTR         (_SIGN  4)  /* interrupted function call */
+#define EIO           (_SIGN  5)  /* input/output error */
+#define ENXIO         (_SIGN  6)  /* no such device or address */
+#define E2BIG         (_SIGN  7)  /* arg list too long */
+#define ENOEXEC       (_SIGN  8)  /* exec format error */
+#define EBADF         (_SIGN  9)  /* bad file descriptor */
+#define ECHILD        (_SIGN 10)  /* no child process */
+#define EAGAIN        (_SIGN 11)  /* resource temporarily unavailable */
+#define ENOMEM        (_SIGN 12)  /* not enough space */
+#define EACCES        (_SIGN 13)  /* permission denied */
+#define EFAULT        (_SIGN 14)  /* bad address */
+#define ENOTBLK       (_SIGN 15)  /* Extension: not a block special file */
+#define EBUSY         (_SIGN 16)  /* resource busy */
+#define EEXIST        (_SIGN 17)  /* file exists */
+#define EXDEV         (_SIGN 18)  /* improper link */
+#define ENODEV        (_SIGN 19)  /* no such device */
+#define ENOTDIR       (_SIGN 20)  /* not a directory */
+#define EISDIR        (_SIGN 21)  /* is a directory */
+#define EINVAL        (_SIGN 22)  /* invalid argument */
+#define ENFILE        (_SIGN 23)  /* too many open files in system */
+#define EMFILE        (_SIGN 24)  /* too many open files */
+#define ENOTTY        (_SIGN 25)  /* inappropriate I/O control operation */
+#define ETXTBSY       (_SIGN 26)  /* no longer used */
+#define EFBIG         (_SIGN 27)  /* file too large */
+#define ENOSPC        (_SIGN 28)  /* no space left on device */
+#define ESPIPE        (_SIGN 29)  /* invalid seek */
+#define EROFS         (_SIGN 30)  /* read-only file system */
+#define EMLINK        (_SIGN 31)  /* too many links */
+#define EPIPE         (_SIGN 32)  /* broken pipe */
+#define EDOM          (_SIGN 33)  /* domain error    	(from ANSI C std) */
+#define ERANGE        (_SIGN 34)  /* result too large	(from ANSI C std) */
+#define EDEADLK       (_SIGN 35)  /* resource deadlock avoided */
+#define ENAMETOOLONG  (_SIGN 36)  /* file name too long */
+#define ENOLCK        (_SIGN 37)  /* no locks available */
+#define ENOSYS        (_SIGN 38)  /* function not implemented */
+#define ENOTEMPTY     (_SIGN 39)  /* directory not empty */
+#define ELOOP         (_SIGN 40)  /* too many levels of symlinks detected */
+
+/* The following errors relate to networking. */
+#define EPACKSIZE     (_SIGN 50)  /* invalid packet size for some protocol */
+#define EOUTOFBUFS    (_SIGN 51)  /* not enough buffers left */
+#define EBADIOCTL     (_SIGN 52)  /* illegal ioctl for device */
+#define EBADMODE      (_SIGN 53)  /* badmode in ioctl */
+#define EWOULDBLOCK   (_SIGN 54)
+#define EBADDEST      (_SIGN 55)  /* not a valid destination address */
+#define EDSTNOTRCH    (_SIGN 56)  /* destination not reachable */
+#define EISCONN	      (_SIGN 57)  /* all ready connected */
+#define EADDRINUSE    (_SIGN 58)  /* address in use */
+#define ECONNREFUSED  (_SIGN 59)  /* connection refused */
+#define ECONNRESET    (_SIGN 60)  /* connection reset */
+#define ETIMEDOUT     (_SIGN 61)  /* connection timed out */
+#define EURG	      (_SIGN 62)  /* urgent data present */
+#define ENOURG	      (_SIGN 63)  /* no urgent data present */
+#define ENOTCONN      (_SIGN 64)  /* no connection (yet or anymore) */
+#define ESHUTDOWN     (_SIGN 65)  /* a write call to a shutdown connection */
+#define ENOCONN       (_SIGN 66)  /* no such connection */
+#define EAFNOSUPPORT  (_SIGN 67)  /* address family not supported */
+#define EPROTONOSUPPORT (_SIGN 68) /* protocol not supported by AF */
+#define EPROTOTYPE    (_SIGN 69)  /* Protocol wrong type for socket */
+#define EINPROGRESS   (_SIGN 70)  /* Operation now in progress */
+#define EADDRNOTAVAIL (_SIGN 71)  /* Can't assign requested address */
+#define EALREADY      (_SIGN 72)  /* Connection already in progress */
+#define EMSGSIZE      (_SIGN 73)  /* Message too long */
+#define ENOTSOCK      (_SIGN 74)  /* Socket operation on non-socket */
+#define ENOPROTOOPT   (_SIGN 75)  /* Protocol not available */
+
+/* The following are not POSIX errors, but they can still happen. 
+ * All of these are generated by the kernel and relate to message passing.
+ */
+#define ELOCKED      (_SIGN 101)  /* can't send message due to deadlock */
+#define EBADCALL     (_SIGN 102)  /* illegal system call number */
+#define EBADSRCDST   (_SIGN 103)  /* bad source or destination process */
+#define ECALLDENIED  (_SIGN 104)  /* no permission for system call */
+#define EDEADSRCDST  (_SIGN 105)  /* source or destination is not alive */
+#define ENOTREADY    (_SIGN 106)  /* source or destination is not ready */
+#define EBADREQUEST  (_SIGN 107)  /* destination cannot handle request */
+#define ESRCDIED     (_SIGN 108)  /* source just died */
+#define EDSTDIED     (_SIGN 109)  /* destination just died */
+#define ETRAPDENIED  (_SIGN 110)  /* IPC trap not allowed */
+#define EDONTREPLY   (_SIGN 201)  /* pseudo-code: don't send a reply */
+
+#endif /* _ERRNO_H */
Index: /trunk/minix/include/fcntl.h
===================================================================
--- /trunk/minix/include/fcntl.h	(revision 9)
+++ /trunk/minix/include/fcntl.h	(revision 9)
@@ -0,0 +1,76 @@
+/* The <fcntl.h> header is needed by the open() and fcntl() system calls,
+ * which  have a variety of parameters and flags.  They are described here.  
+ * The formats of the calls to each of these are:
+ *
+ *	open(path, oflag [,mode])	open a file
+ *	fcntl(fd, cmd [,arg])		get or set file attributes
+ * 
+ */
+
+#ifndef _FCNTL_H
+#define _FCNTL_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+/* These values are used for cmd in fcntl().  POSIX Table 6-1.  */
+#define F_DUPFD            0	/* duplicate file descriptor */
+#define F_GETFD	           1	/* get file descriptor flags */
+#define F_SETFD            2	/* set file descriptor flags */
+#define F_GETFL            3	/* get file status flags */
+#define F_SETFL            4	/* set file status flags */
+#define F_GETLK            5	/* get record locking information */
+#define F_SETLK            6	/* set record locking information */
+#define F_SETLKW           7	/* set record locking info; wait if blocked */
+#define F_FREESP           8	/* free a section of a regular file */
+
+/* File descriptor flags used for fcntl().  POSIX Table 6-2. */
+#define FD_CLOEXEC         1	/* close on exec flag for third arg of fcntl */
+
+/* L_type values for record locking with fcntl().  POSIX Table 6-3. */
+#define F_RDLCK            1	/* shared or read lock */
+#define F_WRLCK            2	/* exclusive or write lock */
+#define F_UNLCK            3	/* unlock */
+
+/* Oflag values for open().  POSIX Table 6-4. */
+#define O_CREAT        00100	/* creat file if it doesn't exist */
+#define O_EXCL         00200	/* exclusive use flag */
+#define O_NOCTTY       00400	/* do not assign a controlling terminal */
+#define O_TRUNC        01000	/* truncate flag */
+
+/* File status flags for open() and fcntl().  POSIX Table 6-5. */
+#define O_APPEND       02000	/* set append mode */
+#define O_NONBLOCK     04000	/* no delay */
+
+/* File access modes for open() and fcntl().  POSIX Table 6-6. */
+#define O_RDONLY           0	/* open(name, O_RDONLY) opens read only */
+#define O_WRONLY           1	/* open(name, O_WRONLY) opens write only */
+#define O_RDWR             2	/* open(name, O_RDWR) opens read/write */
+
+/* Mask for use with file access modes.  POSIX Table 6-7. */
+#define O_ACCMODE         03	/* mask for file access modes */
+
+/* Struct used for locking.  POSIX Table 6-8. */
+struct flock {
+  short l_type;			/* type: F_RDLCK, F_WRLCK, or F_UNLCK */
+  short l_whence;		/* flag for starting offset */
+  off_t l_start;		/* relative offset in bytes */
+  off_t l_len;			/* size; if 0, then until EOF */
+  pid_t l_pid;			/* process id of the locks' owner */
+};
+
+/* Function Prototypes. */
+_PROTOTYPE( int creat, (const char *_path, _mnx_Mode_t _mode)		);
+_PROTOTYPE( int fcntl, (int _filedes, int _cmd, ...)	  		);
+_PROTOTYPE( int open,  (const char *_path, int _oflag, ...) 		);
+
+/* For locking files. */
+#define LOCK_SH		F_RDLCK		/* Shared lock */
+#define LOCK_EX		F_WRLCK		/* Exclusive lock */
+#define LOCK_NB		0x0080		/* Do not block when locking */
+#define LOCK_UN		F_UNLCK		/* Unlock */
+
+_PROTOTYPE(  int flock, (int fd, int mode)				);
+
+#endif /* _FCNTL_H */
Index: /trunk/minix/include/float.h
===================================================================
--- /trunk/minix/include/float.h	(revision 9)
+++ /trunk/minix/include/float.h	(revision 9)
@@ -0,0 +1,42 @@
+/* The <float.h> header defines some implementation limits for (IEEE) floating
+ * point. Application programs can use it to find out how big and small 
+ * floating-point numbers can be, what epsilon to use for iteration, etc.
+ */
+
+#ifndef _FLOAT_H
+#define _FLOAT_H
+
+#define FLT_DIG			6
+#define FLT_EPSILON		1.19209290e-07F
+#define FLT_MANT_DIG		24
+#define FLT_MAX			3.40282347e+38F
+#define FLT_MAX_10_EXP		38
+#define FLT_MAX_EXP		128
+#define FLT_MIN			1.17549435e-38F
+#define FLT_MIN_10_EXP		-37
+#define FLT_MIN_EXP		-125
+
+#define DBL_DIG			15
+#define DBL_EPSILON		2.2204460492503131e-16
+#define DBL_MANT_DIG		53
+#define DBL_MAX			1.7976931348623157e+308
+#define DBL_MAX_10_EXP		308
+#define DBL_MAX_EXP		1024
+#define DBL_MIN			2.2250738585072014e-308
+#define DBL_MIN_10_EXP		-307
+#define DBL_MIN_EXP		-1021
+
+#define LDBL_DIG		15
+#define LDBL_EPSILON		2.2204460492503131e-16L
+#define LDBL_MANT_DIG		53
+#define LDBL_MAX		1.7976931348623157e+308L
+#define LDBL_MAX_10_EXP		308
+#define LDBL_MAX_EXP		1024
+#define LDBL_MIN		2.2250738585072014e-308L
+#define LDBL_MIN_10_EXP		-307
+#define LDBL_MIN_EXP		-1021
+
+#define FLT_ROUNDS		1
+#define FLT_RADIX		2
+
+#endif /* _FLOAT_H */
Index: /trunk/minix/include/fts.h
===================================================================
--- /trunk/minix/include/fts.h	(revision 9)
+++ /trunk/minix/include/fts.h	(revision 9)
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)fts.h	8.3 (Berkeley) 8/14/94
+ * $FreeBSD: src/include/fts.h,v 1.11 2005/01/07 00:06:20 pjd Exp $
+ */
+
+#ifndef	_FTS_H_
+#define	_FTS_H_
+
+typedef struct {
+	struct _ftsent *fts_cur;	/* current node */
+	struct _ftsent *fts_child;	/* linked list of children */
+	struct _ftsent **fts_array;	/* sort array */
+	dev_t fts_dev;			/* starting device # */
+	char *fts_path;			/* path for this descent */
+	int fts_rfd;			/* fd for root */
+	int fts_pathlen;		/* sizeof(path) */
+	int fts_nitems;			/* elements in the sort array */
+	int (*fts_compar)		/* compare function */
+	    (const struct _ftsent * const *, const struct _ftsent * const *);
+
+#define	FTS_COMFOLLOW	0x001		/* follow command line symlinks */
+#define	FTS_LOGICAL	0x002		/* logical walk */
+#define	FTS_NOCHDIR	0x004		/* don't change directories */
+#define	FTS_NOSTAT	0x008		/* don't get stat info */
+#define	FTS_PHYSICAL	0x010		/* physical walk */
+#define	FTS_SEEDOT	0x020		/* return dot and dot-dot */
+#define	FTS_XDEV	0x040		/* don't cross devices */
+#define	FTS_OPTIONMASK	0x0ff		/* valid user option mask */
+
+#define	FTS_NAMEONLY	0x100		/* (private) child names only */
+#define	FTS_STOP	0x200		/* (private) unrecoverable error */
+	int fts_options;		/* fts_open options, global flags */
+	void *fts_clientptr;		/* thunk for sort function */
+} FTS;
+
+typedef struct _ftsent {
+	struct _ftsent *fts_cycle;	/* cycle node */
+	struct _ftsent *fts_parent;	/* parent directory */
+	struct _ftsent *fts_link;	/* next file in directory */
+	union {
+		struct {
+			long __fts_number;	/* local numeric value */
+			void *__fts_pointer;	/* local address value */
+		} __struct_ftsent;
+#if 0
+		int64_t __fts_bignum;
+#endif
+	} __union_ftsent;
+#define	fts_number	__union_ftsent.__struct_ftsent.__fts_number
+#define	fts_pointer	__union_ftsent.__struct_ftsent.__fts_pointer
+#define	fts_bignum	__union_ftsent.__fts_bignum
+	char *fts_accpath;		/* access path */
+	char *fts_path;			/* root path */
+	int fts_errno;			/* errno for this node */
+	int fts_symfd;			/* fd for symlink */
+	u_short fts_pathlen;		/* strlen(fts_path) */
+	u_short fts_namelen;		/* strlen(fts_name) */
+
+	ino_t fts_ino;			/* inode */
+	dev_t fts_dev;			/* device */
+	nlink_t fts_nlink;		/* link count */
+
+#define	FTS_ROOTPARENTLEVEL	-1
+#define	FTS_ROOTLEVEL		 0
+	short fts_level;		/* depth (-1 to N) */
+
+#define	FTS_D		 1		/* preorder directory */
+#define	FTS_DC		 2		/* directory that causes cycles */
+#define	FTS_DEFAULT	 3		/* none of the above */
+#define	FTS_DNR		 4		/* unreadable directory */
+#define	FTS_DOT		 5		/* dot or dot-dot */
+#define	FTS_DP		 6		/* postorder directory */
+#define	FTS_ERR		 7		/* error; errno is set */
+#define	FTS_F		 8		/* regular file */
+#define	FTS_INIT	 9		/* initialized only */
+#define	FTS_NS		10		/* stat(2) failed */
+#define	FTS_NSOK	11		/* no stat(2) requested */
+#define	FTS_SL		12		/* symbolic link */
+#define	FTS_SLNONE	13		/* symbolic link without target */
+#define	FTS_W		14		/* whiteout object */
+	u_short fts_info;		/* user flags for FTSENT structure */
+
+#define	FTS_DONTCHDIR	 0x01		/* don't chdir .. to the parent */
+#define	FTS_SYMFOLLOW	 0x02		/* followed a symlink to get here */
+#define	FTS_ISW		 0x04		/* this is a whiteout object */
+	u_short fts_flags;		/* private flags for FTSENT structure */
+
+#define	FTS_AGAIN	 1		/* read node again */
+#define	FTS_FOLLOW	 2		/* follow symbolic link */
+#define	FTS_NOINSTR	 3		/* no instructions */
+#define	FTS_SKIP	 4		/* discard node */
+	u_short fts_instr;		/* fts_set() instructions */
+
+	struct stat *fts_statp;		/* stat(2) information */
+	char *fts_name;			/* file name */
+	FTS *fts_fts;			/* back pointer to main FTS */
+} FTSENT;
+
+FTSENT	*fts_children(FTS *, int);
+int	 fts_close(FTS *);
+void	*fts_get_clientptr(FTS *);
+#define	 fts_get_clientptr(fts)	((fts)->fts_clientptr)
+FTS	*fts_get_stream(FTSENT *);
+#define	 fts_get_stream(ftsent)	((ftsent)->fts_fts)
+FTS	*fts_open(char * const *, int,
+	    int (*)(const FTSENT * const *, const FTSENT * const *));
+FTSENT	*fts_read(FTS *);
+int	 fts_set(FTS *, FTSENT *, int);
+void	 fts_set_clientptr(FTS *, void *);
+
+#endif /* !_FTS_H_ */
Index: /trunk/minix/include/grp.h
===================================================================
--- /trunk/minix/include/grp.h	(revision 9)
+++ /trunk/minix/include/grp.h	(revision 9)
@@ -0,0 +1,28 @@
+/* The <grp.h> header is used for the getgrid() and getgrnam() calls. */
+
+#ifndef _GRP_H
+#define _GRP_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+struct	group { 
+  char *gr_name;		/* the name of the group */
+  char *gr_passwd;		/* the group passwd */
+  gid_t gr_gid;			/* the numerical group ID */
+  char **gr_mem;		/* a vector of pointers to the members */
+};
+
+/* Function Prototypes. */
+_PROTOTYPE( struct group *getgrgid, (_mnx_Gid_t _gid)  			);
+_PROTOTYPE( struct group *getgrnam, (const char *_name)			);
+
+#ifdef _MINIX
+_PROTOTYPE( void endgrent, (void)					);
+_PROTOTYPE( struct group *getgrent, (void)				);
+_PROTOTYPE( int setgrent, (void)					);
+_PROTOTYPE( void setgrfile, (const char *_file)				);
+#endif
+
+#endif /* _GRP_H */
Index: /trunk/minix/include/ibm/bios.h
===================================================================
--- /trunk/minix/include/ibm/bios.h	(revision 9)
+++ /trunk/minix/include/ibm/bios.h	(revision 9)
@@ -0,0 +1,125 @@
+/* Definitions of several known BIOS addresses. The addresses listed here 
+ * are found in three memory areas that have been defined in <ibm/memory.h>.
+ *  - the BIOS interrupt vectors
+ *  - the BIOS data area
+ *  - the motherboard BIOS memory
+ * 
+ * Created: March 2005, Jorrit N. Herder	
+ */
+
+#ifndef _BIOS_H
+#define _BIOS_H
+
+/* PART I --
+ * The BIOS interrupt vector table (IVT) area (1024 B as of address 0x0000). 
+ * Although this area holds 256 interrupt vectors (with jump addresses), some 
+ * vectors actually contain important BIOS data. Some addresses are below. 
+ */
+#define BIOS_EQUIP_CHECK_ADDR      0x0044 
+#define BIOS_EQUIP_CHECK_SIZE      4L
+
+#define BIOS_VIDEO_PARAMS_ADDR     0x0074        
+#define BIOS_VIDEO_PARAMS_SIZE     4L
+
+#define BIOS_FLOP_PARAMS_ADDR      0x0078     
+#define BIOS_FLOP_PARAMS_SIZE      4L
+ 
+#define BIOS_HD0_PARAMS_ADDR       0x0104 /* disk 0 parameters */
+#define BIOS_HD0_PARAMS_SIZE       4L
+
+#define BIOS_HD1_PARAMS_ADDR       0x0118 /* disk 1 parameters */
+#define BIOS_HD1_PARAMS_SIZE       4L
+
+/* PART I -- 
+ * Addresses in the BIOS data area (256 B as of address 0x0400). The addresses 
+ * listed below are the most important ones, and the ones that are currently 
+ * used. Other addresses may be defined below when new features are added. 
+ */
+
+/* Serial ports (COM1-COM4). */
+#define COM1_IO_PORT_ADDR       0x400   /* COM1 port address */
+#define COM1_IO_PORT_SIZE       2L    
+#define COM2_IO_PORT_ADDR       0x402   /* COM2 port address */
+#define COM2_IO_PORT_SIZE       2L    
+#define COM3_IO_PORT_ADDR       0x404   /* COM3 port address */
+#define COM3_IO_PORT_SIZE       2L    
+#define COM4_IO_PORT_ADDR       0x406   /* COM4 port address */
+#define COM4_IO_PORT_SIZE       2L    
+        
+/* Parallel ports (LPT1-LPT4). */
+#define LPT1_IO_PORT_ADDR       0x408   /* LPT1 port address */
+#define LPT1_IO_PORT_SIZE       2L    
+#define LPT2_IO_PORT_ADDR       0x40A   /* LPT2 port address */
+#define LPT2_IO_PORT_SIZE       2L    
+#define LPT3_IO_PORT_ADDR       0x40C   /* LPT3 port address */
+#define LPT3_IO_PORT_SIZE       2L    
+#define LPT4_IO_PORT_ADDR       0x40E   /* LPT4 port (except on PS/2) */
+#define LPT4_IO_PORT_SIZE       2L    
+        
+/* Video controller (VDU). */
+#define VDU_SCREEN_COLS_ADDR    0x44A   /* VDU nr of screen columns */
+#define VDU_SCREEN_COLS_SIZE    2L  
+
+/* Base I/O port address for active 6845 CRT controller. */
+#define VDU_CRT_BASE_ADDR       0x463   /* 3B4h = mono, 3D4h = color */
+#define VDU_CRT_BASE_SIZE       2L
+
+/* Soft reset flags to control shutdown. */
+#define SOFT_RESET_FLAG_ADDR    0x472   /* soft reset flag on Ctl-Alt-Del */
+#define SOFT_RESET_FLAG_SIZE    2L  
+#define   STOP_MEM_CHECK        0x1234  /* bypass memory tests & CRT init */
+#define   PRESERVE_MEMORY       0x4321  /* preserve memory */
+#define   SYSTEM_SUSPEND        0x5678  /* system suspend */
+#define   MANUFACTURER_TEST     0x9ABC  /* manufacturer test */
+#define   CONVERTIBLE_POST      0xABCD  /* convertible POST loop */
+                            /* ... many other values are used during POST */
+
+/* Hard disk parameters. (Also see BIOS interrupt vector table above.) */
+#define NR_HD_DRIVES_ADDR       0x475  /* number of hard disk drives */ 
+#define NR_HD_DRIVES_SIZE       1L
+
+/* Parallel ports (LPT1-LPT4) timeout values. */
+#define LPT1_TIMEOUT_ADDR       0x478   /* time-out value for LPT1 */
+#define LPT1_TIMEOUT_SIZE       1L  
+#define LPT2_TIMEOUT_ADDR       0x479   /* time-out value for LPT2 */
+#define LPT2_TIMEOUT_SIZE       1L  
+#define LPT3_TIMEOUT_ADDR       0x47A   /* time-out value for LPT3 */
+#define LPT3_TIMEOUT_SIZE       1L  
+#define LPT4_TIMEOUT_ADDR       0x47B   /* time-out for LPT4 (except PS/2) */
+#define LPT4_TIMEOUT_SIZE       1L  
+
+/* Serial ports (COM1-COM4) timeout values. */
+#define COM1_TIMEOUT_ADDR       0x47C   /* time-out value for COM1 */
+#define COM1_TIMEOUT_SIZE       1L  
+#define COM2_TIMEOUT_ADDR       0x47D   /* time-out value for COM2 */
+#define COM2_TIMEOUT_SIZE       1L  
+#define COM3_TIMEOUT_ADDR       0x47E   /* time-out value for COM3 */
+#define COM3_TIMEOUT_SIZE       1L  
+#define COM4_TIMEOUT_ADDR       0x47F   /* time-out value for COM4 */
+#define COM4_TIMEOUT_SIZE       1L  
+
+/* Video controller (VDU). */
+#define VDU_SCREEN_ROWS_ADDR    0x484   /* screen rows (less 1, EGA+)*/
+#define VDU_SCREEN_ROWS_SIZE    1L  
+#define VDU_FONTLINES_ADDR      0x485   /* point height of char matrix */
+#define VDU_FONTLINES_SIZE      2L 
+
+/* Video controller (VDU). */
+#define VDU_VIDEO_MODE_ADDR     0x49A   /* current video mode */
+#define VDU_VIDEO_MODE_SIZE     1L  
+
+/* PART III --
+ * The motherboard BIOS memory contains some known values that are currently 
+ * in use. Other sections in the upper memory area (UMA) addresses vary in 
+ * size and locus and are not further defined here. A rough map is given in 
+ * <ibm/memory.h>. 
+ */
+
+/* Machine ID (we're interested in PS/2 and AT models). */
+#define MACHINE_ID_ADDR         0xFFFFE /* BIOS machine ID byte */
+#define MACHINE_ID_SIZE         1L
+#define   PS_386_MACHINE        0xF8    /* ID byte for PS/2 modela 70/80 */
+#define   PC_AT_MACHINE         0xFC    /* PC/AT, PC/XT286, PS/2 models 50/60 */
+
+#endif /* _BIOS_H */
+
Index: /trunk/minix/include/ibm/cmos.h
===================================================================
--- /trunk/minix/include/ibm/cmos.h	(revision 9)
+++ /trunk/minix/include/ibm/cmos.h	(revision 9)
@@ -0,0 +1,85 @@
+/*
+ibm/cmos.h
+
+Created:	Dec 1998 by Philip Homburg <philip@cs.vu.nl>
+
+Definitions for the CMOS/realtime clock. Based on the datasheet for the
+Dallas DS12887, compatible with the Motorola MC146818
+*/
+
+#define RTC_INDEX	0x70	/* Bit 7 = NMI enable (1) / disable (0)
+				 * bits 0..6 index
+				 */
+#define RTC_IO		0x71	/* Data register, 
+				 * Note: the operation following a write to
+				 * RTC_INDEX should an access (read or write)
+				 * to RTC_IO
+				 */
+
+#define RTC_SEC		0x0	/* Seconds register */
+#define RTC_SEC_ALRM	0x1	/* Seconds register for alarm */
+#define RTC_MIN		0x2	/* Minutes register */
+#define RTC_MIN_ALRM	0x3	/* Minutes register for alarm */
+#define RTC_HOUR	0x4	/* Hours register */
+#define RTC_HOUR_ALRM	0x5	/* Hours register for alarm */
+#define RTC_WDAY	0x6	/* Day of the week, 1..7, Sunday = 1 */
+#define RTC_MDAY	0x7	/* Day of the month, 1..31 */
+#define RTC_MONTH	0x8	/* Month, 1..12 */
+#define RTC_YEAR	0x9	/* Year, 0..99 */
+#define RTC_REG_A	0xA
+#define		RTC_A_UIP	0x80	/* Update in progress. When clear,
+					 * no update will occur for 244
+					 * micro seconds.
+					 */
+#define		RTC_A_DV	0x70	/* Divider bits, valid values are: */
+#define		    RTC_A_DV_OK	    0x20	/* Normal */
+#define		    RTC_A_DV_STOP   0x70	/* Stop, a re-start starts
+						 * halfway through a cycle,
+						 * i.e. the update occurs after
+						 * 500ms.
+						 */
+#define		RTC_A_RS	0x0F	/* Int. freq */
+				    /*  0	None 
+				     *  1	 256 Hz
+				     *  2	 128 Hz
+				     *  3	8192 Hz
+				     *  4	4096 Hz
+				     *  5	2048 Hz
+				     *  6	1024 Hz
+				     *  7	 512 Hz
+				     *  8	 256 Hz
+				     *  9	 128 Hz
+				     * 10	  64 Hz
+				     * 11	  32 Hz
+				     * 12	  16 Hz
+				     * 13	   8 Hz
+				     * 14	   4 Hz
+				     * 15	   2 Hz
+				     */
+#define		    RTC_A_RS_DEF    6	/* Default freq. */
+#define RTC_REG_B	0xB
+#define		RTC_B_SET	0x80	/* Inhibit updates */
+#define		RTC_B_PIE	0x40	/* Enable periodic interrupts */
+#define		RTC_B_AIE	0x20	/* Enable alarm interrupts */
+#define		RTC_B_UIE	0x10	/* Enable update ended interrupts */
+#define		RTC_B_SQWE	0x08	/* Enable square wave output */
+#define		RTC_B_DM_BCD	0x04	/* Data is in BCD (otherwise binary) */
+#define		RTC_B_24	0x02	/* Count hours in 24-hour mode */
+#define		RTC_B_DSE	0x01	/* Automatic (wrong) daylight savings
+					 * updates
+					 */
+#define RTC_REG_C	0xC
+
+/* Contents of the general purpose CMOS RAM (source IBM reference manual) */
+#define CMOS_STATUS	0xE
+#define		CS_LOST_POWER	0x80	/* Chip lost power */
+#define		CS_BAD_CHKSUM	0x40	/* Checksum is incorrect */
+#define		CS_BAD_CONFIG	0x20	/* Bad configuration info */
+#define		CS_BAD_MEMSIZE	0x10	/* Wrong memory size of CMOS */
+#define		CS_BAD_HD	0x08	/* Harddisk failed */
+#define		CS_BAD_TIME	0x04	/* CMOS time is invalid */
+					/* bits 0 and 1 are reserved */
+
+/*
+ * $PchId: cmos.h,v 1.1 1998/12/16 09:14:21 philip Exp $
+ */
Index: /trunk/minix/include/ibm/cpu.h
===================================================================
--- /trunk/minix/include/ibm/cpu.h	(revision 9)
+++ /trunk/minix/include/ibm/cpu.h	(revision 9)
@@ -0,0 +1,15 @@
+#ifndef _IBM_CPU_H
+#define _IBM_CPU_H 1
+
+#define X86_FLAG_C	(1L << 0)	/* Carry */
+#define X86_FLAG_P	(1L << 2)	/* Parity */
+#define X86_FLAG_A	(1L << 4)	/* Aux. carry */
+#define X86_FLAG_Z	(1L << 6)	/* Zero */
+#define X86_FLAG_S	(1L << 7)	/* Sign */
+
+#define X86_FLAG_T	(1L <<  8)	/* Trap */
+#define X86_FLAG_I	(1L <<  9)	/* Interrupt */
+#define X86_FLAG_D	(1L << 10)	/* Direction */
+#define X86_FLAG_O	(1L << 11)	/* Overflow */
+
+#endif
Index: /trunk/minix/include/ibm/diskparm.h
===================================================================
--- /trunk/minix/include/ibm/diskparm.h	(revision 9)
+++ /trunk/minix/include/ibm/diskparm.h	(revision 9)
@@ -0,0 +1,20 @@
+/* PC (and AT) BIOS structure to hold disk parameters.  Under Minix, it is
+ * used mainly for formatting.
+ */
+
+#ifndef _DISKPARM_H
+#define _DISKPARM_H
+struct disk_parameter_s {
+  char spec1;
+  char spec2;
+  char motor_turnoff_sec;
+  char sector_size_code;
+  char sectors_per_cylinder;
+  char gap_length;
+  char dtl;
+  char gap_length_for_format;
+  char fill_byte_for_format;
+  char head_settle_msec;
+  char motor_start_eigth_sec;
+};
+#endif /* _DISKPARM_H */
Index: /trunk/minix/include/ibm/int86.h
===================================================================
--- /trunk/minix/include/ibm/int86.h	(revision 9)
+++ /trunk/minix/include/ibm/int86.h	(revision 9)
@@ -0,0 +1,61 @@
+/*	int86.h - 8086 interrupt types			Author: Kees J. Bot
+ *								3 May 2000
+ */
+
+/* Registers used in an PC real mode call for BIOS or DOS services.  A
+ * driver is called through the vector if the interrupt number is zero.
+ */
+union reg86 {
+    struct l {
+	u32_t	ef;			/* 32 bit flags (output only) */
+	u32_t	vec;			/* Driver vector (input only) */
+	u32_t	_ds_es[1];
+	u32_t	eax;			/* 32 bit general registers */
+	u32_t	ebx;
+	u32_t	ecx;
+	u32_t	edx;
+	u32_t	esi;
+	u32_t	edi;
+	u32_t	ebp;
+    } l;
+    struct w {
+	u16_t	f, _ef[1];		/* 16 bit flags (output only) */
+	u16_t	off, seg;		/* Driver vector (input only) */
+	u16_t	ds, es;			/* DS and ES real mode segment regs */
+	u16_t	ax, _eax[1];		/* 16 bit general registers */
+	u16_t	bx, _ebx[1];
+	u16_t	cx, _ecx[1];
+	u16_t	dx, _edx[1];
+	u16_t	si, _esi[1];
+	u16_t	di, _edi[1];
+	u16_t	bp, _ebp[1];
+    } w;
+    struct b {
+	u8_t	intno, _intno[3];	/* Interrupt number (input only) */
+	u8_t	_vec[4];
+	u8_t	_ds_es[4];
+	u8_t	al, ah, _eax[2];	/* 8 bit general registers */
+	u8_t	bl, bh, _ebx[2];
+	u8_t	cl, ch, _ecx[2];
+	u8_t	dl, dh, _edx[2];
+	u8_t	_esi[4];
+	u8_t	_edi[4];
+	u8_t	_ebp[4];
+    } b;
+};
+
+struct reg86u { union reg86 u; };	/* Better for forward declarations */
+
+/* Parameters passed on ioctls to the memory task. */
+
+struct mio_int86 {		/* MIOCINT86 */
+	union reg86 reg86;		/* x86 registers as above */
+	u16_t	off, seg;		/* Address of kernel buffer */
+	void	*buf;			/* User data buffer */
+	size_t	len;			/* Size of user buffer */
+};
+
+struct mio_ldt86 {		/* MIOCGLDT86, MIOCSLDT86 */
+	size_t	idx;			/* Index in process' LDT */
+	u16_t	entry[4];		/* One LDT entry to get or set. */
+};
Index: /trunk/minix/include/ibm/interrupt.h
===================================================================
--- /trunk/minix/include/ibm/interrupt.h	(revision 9)
+++ /trunk/minix/include/ibm/interrupt.h	(revision 9)
@@ -0,0 +1,61 @@
+/* Interrupt numbers and hardware vectors. */
+
+#ifndef _INTERRUPT_H
+#define _INTERRUPT_H
+
+#if (CHIP == INTEL)
+
+/* 8259A interrupt controller ports. */
+#define INT_CTL         0x20	/* I/O port for interrupt controller */
+#define INT_CTLMASK     0x21	/* setting bits in this port disables ints */
+#define INT2_CTL        0xA0	/* I/O port for second interrupt controller */
+#define INT2_CTLMASK    0xA1	/* setting bits in this port disables ints */
+
+/* Magic numbers for interrupt controller. */
+#define END_OF_INT      0x20	/* code used to re-enable after an interrupt */
+
+/* Interrupt vectors defined/reserved by processor. */
+#define DIVIDE_VECTOR      0	/* divide error */
+#define DEBUG_VECTOR       1	/* single step (trace) */
+#define NMI_VECTOR         2	/* non-maskable interrupt */
+#define BREAKPOINT_VECTOR  3	/* software breakpoint */
+#define OVERFLOW_VECTOR    4	/* from INTO */
+
+/* Fixed system call vector. */
+#define SYS_VECTOR        32	/* system calls are made with int SYSVEC */
+#define SYS386_VECTOR     33	/* except 386 system calls use this */
+#define LEVEL0_VECTOR     34	/* for execution of a function at level 0 */
+
+/* Suitable irq bases for hardware interrupts.  Reprogram the 8259(s) from
+ * the PC BIOS defaults since the BIOS doesn't respect all the processor's
+ * reserved vectors (0 to 31).
+ */
+#define BIOS_IRQ0_VEC   0x08	/* base of IRQ0-7 vectors used by BIOS */
+#define BIOS_IRQ8_VEC   0x70	/* base of IRQ8-15 vectors used by BIOS */
+#define IRQ0_VECTOR     0x50	/* nice vectors to relocate IRQ0-7 to */
+#define IRQ8_VECTOR     0x70	/* no need to move IRQ8-15 */
+
+/* Hardware interrupt numbers. */
+#define NR_IRQ_VECTORS    16
+#define CLOCK_IRQ          0
+#define KEYBOARD_IRQ       1
+#define CASCADE_IRQ        2	/* cascade enable for 2nd AT controller */
+#define ETHER_IRQ          3	/* default ethernet interrupt vector */
+#define SECONDARY_IRQ      3	/* RS232 interrupt vector for port 2 */
+#define RS232_IRQ          4	/* RS232 interrupt vector for port 1 */
+#define XT_WINI_IRQ        5	/* xt winchester */
+#define FLOPPY_IRQ         6	/* floppy disk */
+#define PRINTER_IRQ        7
+#define KBD_AUX_IRQ       12	/* AUX (PS/2 mouse) port in kbd controller */
+#define AT_WINI_0_IRQ     14	/* at winchester controller 0 */
+#define AT_WINI_1_IRQ     15	/* at winchester controller 1 */
+
+/* Interrupt number to hardware vector. */
+#define BIOS_VECTOR(irq)	\
+	(((irq) < 8 ? BIOS_IRQ0_VEC : BIOS_IRQ8_VEC) + ((irq) & 0x07))
+#define VECTOR(irq)	\
+	(((irq) < 8 ? IRQ0_VECTOR : IRQ8_VECTOR) + ((irq) & 0x07))
+
+#endif /* (CHIP == INTEL) */
+
+#endif /* _INTERRUPT_H */
Index: /trunk/minix/include/ibm/memory.h
===================================================================
--- /trunk/minix/include/ibm/memory.h	(revision 9)
+++ /trunk/minix/include/ibm/memory.h	(revision 9)
@@ -0,0 +1,171 @@
+/* Physical memory layout on IBM compatible PCs. Only the major, fixed memory 
+ * areas are detailed here. Known addresses of the BIOS data area are defined
+ * in <ibm/bios.h>. The map upper memory area (UMA) is only roughly defined 
+ * since the UMA sections may vary in size and locus. 
+ *
+ * Created: March 2005, Jorrit N. Herder
+ */
+
+/* I/O-mapped peripherals. I/O addresses are different from memory addresses 
+ * due to the I/O signal on the ISA bus. Individual I/O ports are defined by 
+ * the drivers that use them or looked up with help of the BIOS. 
+ */
+#define IO_MEMORY_BEGIN             0x0000
+#define IO_MEMORY_END               0xFFFF  
+
+  
+/* Physical memory layout. Design decisions made for the earliest PCs, caused
+ * memory to be broken broken into the following four basic pieces:
+ *  - Conventional or base memory: first 640 KB (incl. BIOS data, see below);
+ *    The top of conventional memory is often used by the BIOS to store data.
+ *  - Upper Memory Area (UMA): upper 384 KB of the first megabyte of memory;
+ *  - High Memory Area (HMA): ~ first 64 KB of the second megabyte of memory;
+ *  - Extended Memory: all the memory above first megabyte of memory.
+ * The high memory area overlaps with the first 64 KB of extended memory, but
+ * is different from the rest of extended memory because it can be accessed 
+ * when the processor is in real mode. 
+ */
+#define BASE_MEM_BEGIN            0x000000
+#define BASE_MEM_TOP		  0x090000	
+#define BASE_MEM_END              0x09FFFF
+
+#define UPPER_MEM_BEGIN           0x0A0000
+#define UPPER_MEM_END             0x0FFFFF
+
+#define HIGH_MEM_BEGIN            0x100000
+#define HIGH_MEM_END              0x10FFEF
+
+#define EXTENDED_MEM_BEGIN        0x100000
+#define EXTENDED_MEM_END    ((unsigned) -1)
+  
+
+/* The logical memory map of the first 1.5 MB is as follows (hexadecimals): 
+ *
+ * offset [size]  (id) = memory usage
+ * ------------------------------------------------------------------------
+ * 000000 [00400] (I) = Real-Mode Interrupt Vector Table (1024 B)
+ * 000400 [00100] (B) = BIOS Data Area (256 B)
+ * 000800 [00066] (W) = 80286 Loadall workspace
+ * 010000 [10000] (c) = Real-Mode Compatibility Segment (64 KB)
+ * 020000 [70000] (.) = Program-accessible memory (free)
+ * 090000 [10000] (E) = BIOS Extension
+ * 0A0000 [10000] (G) = Graphics Mode Video RAM
+ * 0B0000 [08000] (M) = Monochrome Text Mode Video RAM
+ * 0B8000 [08000] (C) = Color Text Mode Video RAM
+ * 0C0000 [08000] (V) = Video ROM BIOS (would be "a" in PS/2)
+ * 0C8000 [18000] (a) = Adapter ROM + special-purpose RAM (free UMA space)
+ * 0E0000 [10000] (r) = PS/2 Motherboard ROM BIOS (free UMA in non-PS/2)
+ * 0F0000 [06000] (R) = Motherboard ROM BIOS
+ * 0F6000 [08000] (b) = IBM Cassette BASIC ROM ("R" in IBM compatibles)
+ * 0FD000 [02000] (R) = Motherboard ROM BIOS
+ * 100000 [.....] (.) = Extended memory, program-accessible (free) 
+ * 100000 [0FFEF] (h) = High Memory Area (HMA)
+ *
+ * 
+ * Conventional (Base) Memory:
+ *
+ *       : [~~~~~16 KB~~~~][~~~~~16 KB~~~~][~~~~~16 KB~~~~][~~~~~16 KB~~~~]
+ *       : 0---1---2---3---4---5---6---7---8---9---A---B---C---D---E---F---
+ * 000000: IBW.............................................................
+ * 010000: cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+ * 020000: ................................................................
+ * 030000: ................................................................
+ * 040000: ................................................................
+ * 050000: ................................................................
+ * 060000: ................................................................
+ * 070000: ................................................................
+ * 080000: ................................................................
+ * 090000: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
+ * 
+ * Upper Memory Area (UMA):
+ *
+ *       : 0---1---2---3---4---5---6---7---8---9---A---B---C---D---E---F---
+ * 0A0000: GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
+ * 0B0000: MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
+ * 0C0000: VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ * 0D0000: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ * 0E0000: rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
+ * 0F0000: RRRRRRRRRRRRRRRRRRRRRRRRbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbRRRRRRRR
+ *
+ * Extended Memory:
+ * 
+ *       : 0---1---2---3---4---5---6---7---8---9---A---B---C---D---E---F---
+ * 100000: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh.
+ * 110000: ................................................................
+ * 120000: ................................................................
+ * 130000: ................................................................
+ * 140000: ................................................................
+ * 150000: ................................................................
+ * 160000: ................................................................
+ * 170000: ................................................................
+ *
+ * Source: The logical memory map was partly taken from the book "Upgrading 
+ *         & Repairing PCs Eight Edition", Macmillan Computer Publishing.
+ */ 
+
+ 
+/* The bottom part of conventional or base memory is occupied by BIOS data. 
+ * The BIOS memory can be distinguished in two parts:
+ * o The first the first 1024 bytes of addressable memory contains the BIOS 
+ *   real-mode interrupt vector table (IVT). The table is used to access BIOS
+ *   hardware services in real-mode by loading a interrupt vector and issuing 
+ *   an INT instruction. Some vectors contain BIOS data that can be retrieved 
+ *   directly and are useful in protected-mode as well. 
+ * o The BIOS data area is located directly above the interrupt vectors. It
+ *   comprises 256 bytes of memory. These data are used by the device drivers
+ *   to retrieve hardware details, such as I/O ports to be used. 
+ */  
+#define BIOS_MEM_BEGIN             0x00000      /* all BIOS memory */
+#define BIOS_MEM_END               0x004FF
+#define   BIOS_IVT_BEGIN           0x00000      /* BIOS interrupt vectors */
+#define   BIOS_IVT_END             0x003FF
+#define   BIOS_DATA_BEGIN          0x00400      /* BIOS data area */
+#define   BIOS_DATA_END            0x004FF
+
+/* The base memory is followed by 384 KB reserved memory located at the top of
+ * the first MB of physical memory. This memory is known as the upper memory 
+ * area (UMA). It is used for memory-mapped peripherals, such as video RAM, 
+ * adapter BIOS (adapter ROM and special purpose RAM), and the motherboard 
+ * BIOS (I/O system, Power-On Self Test, bootstrap loader). The upper memory
+ * can roughly be distinguished in three parts:
+ * 
+ * o The first 128K of the upper memory area (A0000-BFFFF) is reserved for use 
+ *   by memory-mapped video adapters. Hence, it is also called Video RAM. The
+ *   display driver can directly write to this memory and request the hardware
+ *   to show the data on the screen.
+ */ 
+#define UMA_VIDEO_RAM_BEGIN        0xA0000      /* video RAM */
+#define UMA_VIDEO_RAM_END          0xBFFFF
+#define   UMA_GRAPHICS_RAM_BEGIN   0xA0000      /* graphics RAM */
+#define   UMA_GRAPHICS_RAM_END     0xAFFFF
+#define   UMA_MONO_TEXT_BEGIN      0xB0000      /* monochrome text */
+#define   UMA_MONO_TEXT_END        0xB7FFF
+#define   UMA_COLOR_TEXT_BEGIN     0xB8000      /* color text */
+#define   UMA_COLOR_TEXT_END       0xBFFFF
+
+/* o The next 128K (the memory range C0000-DFFFF) is reserved for the adapter 
+ *   BIOS that resides in the ROM on some adapter boards. Most VGA-compatible 
+ *   video adapters use the first 32 KB of this area for their on-board BIOS. 
+ *   The rest can be used by any other adapters. The IDE controller often 
+ *   occupies the second 32 KB. 
+ */
+#define UMA_ADAPTER_BIOS_BEGIN     0xC0000      /* adapter BIOS */
+#define UMA_ADAPTER_BIOS_END       0xDFFFF
+#define   UMA_VIDEO_BIOS_BEGIN     0xC0000      /* video adapter */
+#define   UMA_VIDEO_BIOS_END       0xC7FFF
+#define   UMA_IDE_HD_BIOS_BEGIN    0xC8000      /* IDE hard disk */
+#define   UMA_IDE_HD_BIOS_END      0xCBFFF
+
+/* o The last 128K of the upper memory area (E0000-FFFFF) is reserved for 
+ *   motherboard BIOS (Basic I/O System). The POST (Power-On Self Test) and 
+ *   bootstrap loader also reside in  this space. The memory falls apart in 
+ *   two areas: Plug & Play BIOS data and the system BIOS data. 
+ */ 
+#define UMA_MB_BIOS_BEGIN          0xE0000      /* motherboard BIOS */
+#define UMA_MB_BIOS_END            0xFFFFF
+#define   UMA_PNP_ESCD_BIOS_BEGIN  0xE0000      /* PnP extended data */
+#define   UMA_PNP_ESCD_BIOS_END    0xEFFFF
+#define   UMA_SYSTEM_BIOS_BEGIN    0xF0000      /* system BIOS */
+#define   UMA_SYSTEM_BIOS_END      0xFFFFF
+
+ 
Index: /trunk/minix/include/ibm/partition.h
===================================================================
--- /trunk/minix/include/ibm/partition.h	(revision 9)
+++ /trunk/minix/include/ibm/partition.h	(revision 9)
@@ -0,0 +1,26 @@
+/* Description of entry in partition table.  */
+#ifndef _PARTITION_H
+#define _PARTITION_H
+
+struct part_entry {
+  unsigned char bootind;	/* boot indicator 0/ACTIVE_FLAG	 */
+  unsigned char start_head;	/* head value for first sector	 */
+  unsigned char start_sec;	/* sector value + cyl bits for first sector */
+  unsigned char start_cyl;	/* track value for first sector	 */
+  unsigned char sysind;		/* system indicator		 */
+  unsigned char last_head;	/* head value for last sector	 */
+  unsigned char last_sec;	/* sector value + cyl bits for last sector */
+  unsigned char last_cyl;	/* track value for last sector	 */
+  unsigned long lowsec;		/* logical first sector		 */
+  unsigned long size;		/* size of partition in sectors	 */
+};
+
+#define ACTIVE_FLAG	0x80	/* value for active in bootind field (hd0) */
+#define NR_PARTITIONS	4	/* number of entries in partition table */
+#define	PART_TABLE_OFF	0x1BE	/* offset of partition table in boot sector */
+
+/* Partition types. */
+#define NO_PART		0x00	/* unused entry */
+#define MINIX_PART	0x81	/* Minix partition type */
+
+#endif /* _PARTITION_H */
Index: /trunk/minix/include/ibm/pci.h
===================================================================
--- /trunk/minix/include/ibm/pci.h	(revision 9)
+++ /trunk/minix/include/ibm/pci.h	(revision 9)
@@ -0,0 +1,132 @@
+/*
+pci.h
+
+Created:	Jan 2000 by Philip Homburg <philip@cs.vu.nl>
+*/
+
+/* Header type 00, normal PCI devices */
+#define PCI_VID		0x00	/* Vendor ID, 16-bit */
+#define PCI_DID		0x02	/* Device ID, 16-bit */
+#define PCI_CR		0x04	/* Command Register, 16-bit */
+#define		PCI_CR_MAST_EN	0x0004	/* Enable Busmaster Access */
+#define		PCI_CR_IO_EN	0x0001	/* Enable I/O Cycles */
+#define PCI_SR		0x06	/* PCI status, 16-bit */
+#define		 PSR_SSE	0x4000	/* Signaled System Error */
+#define		 PSR_RMAS	0x2000	/* Received Master Abort Status */
+#define		 PSR_RTAS	0x1000	/* Received Target Abort Status */
+#define		 PSR_CAPPTR	0x0010	/* Capabilities list */
+#define PCI_REV		0x08	/* Revision ID */
+#define PCI_PIFR	0x09	/* Prog. Interface Register */
+#define PCI_SCR		0x0A	/* Sub-Class Register */
+#define PCI_BCR		0x0B	/* Base-Class Register */
+#define PCI_CLS		0x0C	/* Cache Line Size */
+#define PCI_LT		0x0D	/* Latency Timer */
+#define PCI_HEADT	0x0E	/* Header type, 8-bit */
+#define	    PHT_MASK		0x7F	/* Header type mask */
+#define	    	PHT_NORMAL		0x00
+#define	    	PHT_BRIDGE		0x01
+#define	    	PHT_CARDBUS		0x02
+#define	    PHT_MULTIFUNC	0x80	/* Multiple functions */
+#define PCI_BIST	0x0F	/* Built-in Self Test */
+#define PCI_BAR		0x10	/* Base Address Register */
+#define	    PCI_BAR_IO		0x00000001	/* Reg. refers to I/O space */
+#define	    PCI_BAR_TYPE	0x00000006	/* Memory BAR type */
+#define	    PCI_BAR_PREFETCH	0x00000008	/* Memory is prefetchable */
+#define PCI_BAR_2	0x14	/* Base Address Register */
+#define PCI_BAR_3	0x18	/* Base Address Register */
+#define PCI_BAR_4	0x1C	/* Base Address Register */
+#define PCI_BAR_5	0x20	/* Base Address Register */
+#define PCI_BAR_6	0x24	/* Base Address Register */
+#define PCI_CBCISPTR	0x28	/* Cardbus CIS Pointer */
+#define PCI_SUBVID	0x2C	/* Subsystem Vendor ID */
+#define PCI_SUBDID	0x2E	/* Subsystem Device ID */
+#define PCI_EXPROM	0x30	/* Expansion ROM Base Address */
+#define PCI_CAPPTR	0x34	/* Capabilities Pointer */
+#define		PCI_CP_MASK	0xfc	/* Lower 2 bits should be ignored */
+#define PCI_ILR		0x3C	/* Interrupt Line Register */
+#define		PCI_ILR_UNKNOWN	0xFF	/* IRQ is unassigned or unknown */
+#define PCI_IPR		0x3D	/* Interrupt Pin Register */
+#define PCI_MINGNT	0x3E	/* Min Grant */
+#define PCI_MAXLAT	0x3F	/* Max Latency */
+
+/* Header type 01, PCI-to-PCI bridge devices */
+/* The following registers are in common with type 00:
+ * PCI_VID, PCI_DID, PCI_CR, PCI_SR, PCI_REV, PCI_PIFR, PCI_SCR, PCI_BCR,
+ * PCI_CLS, PCI_LT, PCI_HEADT, PCI_BIST, PCI_BAR, PCI_BAR2, PCI_CAPPTR,
+ * PCI_ILR, PCI_IPR.
+ */
+#define PPB_PRIMBN	0x18	/* Primary Bus Number */
+#define PPB_SECBN	0x19	/* Secondary Bus Number */
+#define PPB_SUBORDBN	0x1A	/* Subordinate Bus Number */
+#define PPB_SECBLT	0x1B	/* Secondary Bus Latency Timer */
+#define PPB_IOBASE	0x1C	/* I/O Base */
+#define		PPB_IOB_MASK	0xf0
+#define PPB_IOLIMIT	0x1D	/* I/O Limit */
+#define		PPB_IOL_MASK	0xf0
+#define PPB_SSTS	0x1E	/* Secondary Status Register */
+#define PPB_MEMBASE	0x20	/* Memory Base */
+#define		PPB_MEMB_MASK	0xfff0
+#define PPB_MEMLIMIT	0x22	/* Memory Limit */
+#define		PPB_MEML_MASK	0xfff0
+#define PPB_PFMEMBASE	0x24	/* Prefetchable Memory Base */
+#define		PPB_PFMEMB_MASK	0xfff0
+#define PPB_PFMEMLIMIT	0x26	/* Prefetchable Memory Limit */
+#define		PPB_PFMEML_MASK	0xfff0
+#define PPB_PFMBU32	0x28	/* Prefetchable Memory Base Upper 32 */
+#define PPB_PFMLU32	0x2C	/* Prefetchable Memory Limit Upper 32 */
+#define PPB_IOBASEU16	0x30	/* I/O Base Upper 16 */
+#define PPB_IOLIMITU16	0x32	/* I/O Limit Upper 16 */
+#define PPB_EXPROM	0x38	/* Expansion ROM Base Address */
+#define PPB_BRIDGECTRL	0x3E	/* Bridge Control */
+#define		PPB_BC_CRST	0x40	/* Assert reset line */
+
+/* Header type 02, Cardbus bridge devices */
+/* The following registers are in common with type 00:
+ * PCI_VID, PCI_DID, PCI_CR, PCI_SR, PCI_REV, PCI_PIFR, PCI_SCR, PCI_BCR,
+ * PCI_CLS, PCI_LT, PCI_HEADT, PCI_BIST, PCI_BAR, PCI_ILR, PCI_IPR.
+ */
+/* The following registers are in common with type 01:
+ * PPB_PRIMBN, PPB_SECBN, PPB_SUBORDBN, PPB_SECBLT.
+ */
+#define CBB_CAPPTR	0x14	/* Capability Pointer */
+#define CBB_SSTS	0x16	/* Secondary Status Register */
+#define CBB_MEMBASE_0	0x1C	/* Memory Base 0 */
+#define CBB_MEMLIMIT_0	0x20	/* Memory Limit 0 */
+#define 	CBB_MEML_MASK	0xfffff000	
+#define CBB_MEMBASE_1	0x24	/* Memory Base 1 */
+#define CBB_MEMLIMIT_1	0x28	/* Memory Limit 1 */
+#define CBB_IOBASE_0	0x2C	/* I/O Base 0 */
+#define CBB_IOLIMIT_0	0x30	/* I/O Limit 0 */
+#define 	CBB_IOL_MASK	0xfffffffc	
+#define CBB_IOBASE_1	0x34	/* I/O Base 1 */
+#define CBB_IOLIMIT_1	0x38	/* I/O Limit 1 */
+#define CBB_BRIDGECTRL	0x3E	/* Bridge Control */
+#define		CBB_BC_INTEXCA	0x80	/* Interrupt are routed to ExCAs */
+#define		CBB_BC_CRST	0x40	/* Assert reset line */
+
+#define CAP_TYPE	0x00	/* Type field in capability */
+#define CAP_NEXT	0x01	/* Next field in capability */
+
+#define PCI_BCR_MASS_STORAGE	0x01	/* Mass Storage class */
+#define 	PCI_MS_IDE		0x01	/* IDE storage class */
+#define			PCI_IDE_PRI_NATIVE	0x01	/* Primary channel is
+							 * in native mode.
+							 */
+#define			PCI_IDE_SEC_NATIVE	0x04	/* Secondary channel is
+							 * in native mode.
+							 */
+
+/* Device type values as ([PCI_BCR] << 16) | ([PCI_SCR] << 8) | [PCI_PIFR] */
+#define PCI_T3_VGA_OLD		0x000100	/* OLD VGA class code */
+#define	PCI_T3_RAID		0x010400	/* RAID controller */
+#define PCI_T3_VGA		0x030000	/* VGA-compatible video card */
+#define PCI_T3_ISA		0x060100	/* ISA bridge */
+#define	PCI_T3_PCI2PCI		0x060400	/* PCI-to-PCI Bridge device */
+#define	PCI_T3_PCI2PCI_SUBTR	0x060401	/* Subtr. PCI-to-PCI Bridge */
+#define	PCI_T3_CARDBUS		0x060700	/* Bardbus Bridge */
+
+#define NO_VID		0xffff	/* No PCI card present */
+
+/*
+ * $PchId: pci.h,v 1.4 2001/12/06 20:21:22 philip Exp $
+ */
Index: /trunk/minix/include/ibm/portio.h
===================================================================
--- /trunk/minix/include/ibm/portio.h	(revision 9)
+++ /trunk/minix/include/ibm/portio.h	(revision 9)
@@ -0,0 +1,29 @@
+/*
+ibm/portio.h
+
+Created:	Jan 15, 1992 by Philip Homburg
+*/
+
+#ifndef _PORTIO_H_
+#define _PORTIO_H_
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+unsigned inb(U16_t _port);
+unsigned inw(U16_t _port);
+unsigned inl(U32_t _port);
+void outb(U16_t _port, U8_t _value);
+void outw(U16_t _port, U16_t _value);
+void outl(U16_t _port, U32_t _value);
+void insb(U16_t _port, void *_buf, size_t _count);
+void insw(U16_t _port, void *_buf, size_t _count);
+void insl(U16_t _port, void *_buf, size_t _count);
+void outsb(U16_t _port, void *_buf, size_t _count);
+void outsw(U16_t _port, void *_buf, size_t _count);
+void outsl(U16_t _port, void *_buf, size_t _count);
+void intr_disable(void);
+void intr_enable(void);
+
+#endif /* _PORTIO_H_ */
Index: /trunk/minix/include/ibm/ports.h
===================================================================
--- /trunk/minix/include/ibm/ports.h	(revision 9)
+++ /trunk/minix/include/ibm/ports.h	(revision 9)
@@ -0,0 +1,17 @@
+/* Addresses and magic numbers for miscellaneous ports. */
+
+#ifndef _PORTS_H
+#define _PORTS_H
+
+#if (CHIP == INTEL)
+
+/* Miscellaneous ports. */
+#define PCR		0x65	/* Planar Control Register */
+#define PORT_B          0x61	/* I/O port for 8255 port B (kbd, beeper...) */
+#define TIMER0          0x40	/* I/O port for timer channel 0 */
+#define TIMER2          0x42	/* I/O port for timer channel 2 */
+#define TIMER_MODE      0x43	/* I/O port for timer mode control */
+
+#endif /* (CHIP == INTEL) */
+
+#endif /* _PORTS_H */
Index: /trunk/minix/include/ifaddrs.h
===================================================================
--- /trunk/minix/include/ifaddrs.h	(revision 9)
+++ /trunk/minix/include/ifaddrs.h	(revision 9)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1995, 1999
+ *	Berkeley Software Design, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
+ */
+
+#ifndef	_IFADDRS_H_
+#define	_IFADDRS_H_
+
+struct ifaddrs {
+	struct ifaddrs  *ifa_next;
+	char		*ifa_name;
+	u_int		 ifa_flags;
+	struct sockaddr	*ifa_addr;
+	struct sockaddr	*ifa_netmask;
+	struct sockaddr	*ifa_dstaddr;
+	void		*ifa_data;
+};
+
+/*
+ * This may have been defined in <net/if.h>.  Note that if <net/if.h> is
+ * to be included it must be included before this header file.
+ */
+#ifndef	ifa_broadaddr
+#define	ifa_broadaddr	ifa_dstaddr	/* broadcast address interface */
+#endif
+
+struct ifmaddrs {
+	struct ifmaddrs	*ifma_next;
+	struct sockaddr	*ifma_name;
+	struct sockaddr	*ifma_addr;
+	struct sockaddr	*ifma_lladdr;
+};
+
+extern int getifaddrs(struct ifaddrs **);
+extern void freeifaddrs(struct ifaddrs *);
+extern int getifmaddrs(struct ifmaddrs **);
+extern void freeifmaddrs(struct ifmaddrs *);
+
+#define IFF_UP	1	/* Interface is up. */
+
+#endif
Index: /trunk/minix/include/inttypes.h
===================================================================
--- /trunk/minix/include/inttypes.h	(revision 9)
+++ /trunk/minix/include/inttypes.h	(revision 9)
@@ -0,0 +1,236 @@
+/*	inttypes.h - Format conversions of integer types.
+ *							Author: Kees J. Bot
+ *								4 Oct 2003
+ * Assumptions and bugs the same as for <stdint.h>
+ * Bug: Wide character integer conversion functions missing.
+ */
+
+#ifndef _INTTYPES_H
+#define _INTTYPES_H
+
+#ifndef _STDINT_H
+#include <stdint.h>
+#endif
+
+#if !__cplusplus || defined(__STDC_FORMAT_MACROS)
+
+/* Macros to print integers defined in <stdint.h>.  The first group should
+ * not be used in code, they're merely here to build the second group.
+ * (The standard really went overboard here, only the first group is needed.)
+ */
+#define PRI8		""
+#define PRILEAST8	""
+#define PRIFAST8	""
+#define PRI16		""
+#define PRILEAST16	""
+#define PRIFAST16	""
+#if _WORD_SIZE == 2
+#define PRI32		"l"
+#define PRILEAST32	"l"
+#define PRIFAST32	"l"
+#else
+#define PRI32		""
+#define PRILEAST32	""
+#define PRIFAST32	""
+#endif
+#if _WORD_SIZE > 2 && __L64
+#define PRI64		"l"
+#define PRILEAST64	"l"
+#define PRIFAST64	"l"
+#endif
+
+/* Macros for fprintf, the ones defined by the standard. */
+#define PRId8		PRI8"d"
+#define PRIdLEAST8	PRILEAST8"d"
+#define PRIdFAST8	PRIFAST8"d"
+#define PRId16		PRI16"d"
+#define PRIdLEAST16	PRILEAST16"d"
+#define PRIdFAST16	PRIFAST16"d"
+#define PRId32		PRI32"d"
+#define PRIdLEAST32	PRILEAST32"d"
+#define PRIdFAST32	PRIFAST32"d"
+#if _WORD_SIZE > 2 && __L64
+#define PRId64		PRI64"d"
+#define PRIdLEAST64	PRILEAST64"d"
+#define PRIdFAST64	PRIFAST64"d"
+#endif
+
+#define PRIi8		PRI8"i"
+#define PRIiLEAST8	PRILEAST8"i"
+#define PRIiFAST8	PRIFAST8"i"
+#define PRIi16		PRI16"i"
+#define PRIiLEAST16	PRILEAST16"i"
+#define PRIiFAST16	PRIFAST16"i"
+#define PRIi32		PRI32"i"
+#define PRIiLEAST32	PRILEAST32"i"
+#define PRIiFAST32	PRIFAST32"i"
+#if _WORD_SIZE > 2 && __L64
+#define PRIi64		PRI64"i"
+#define PRIiLEAST64	PRILEAST64"i"
+#define PRIiFAST64	PRIFAST64"i"
+#endif
+
+#define PRIo8		PRI8"o"
+#define PRIoLEAST8	PRILEAST8"o"
+#define PRIoFAST8	PRIFAST8"o"
+#define PRIo16		PRI16"o"
+#define PRIoLEAST16	PRILEAST16"o"
+#define PRIoFAST16	PRIFAST16"o"
+#define PRIo32		PRI32"o"
+#define PRIoLEAST32	PRILEAST32"o"
+#define PRIoFAST32	PRIFAST32"o"
+#if _WORD_SIZE > 2 && __L64
+#define PRIo64		PRI64"o"
+#define PRIoLEAST64	PRILEAST64"o"
+#define PRIoFAST64	PRIFAST64"o"
+#endif
+
+#define PRIu8		PRI8"u"
+#define PRIuLEAST8	PRILEAST8"u"
+#define PRIuFAST8	PRIFAST8"u"
+#define PRIu16		PRI16"u"
+#define PRIuLEAST16	PRILEAST16"u"
+#define PRIuFAST16	PRIFAST16"u"
+#define PRIu32		PRI32"u"
+#define PRIuLEAST32	PRILEAST32"u"
+#define PRIuFAST32	PRIFAST32"u"
+#if _WORD_SIZE > 2 && __L64
+#define PRIu64		PRI64"u"
+#define PRIuLEAST64	PRILEAST64"u"
+#define PRIuFAST64	PRIFAST64"u"
+#endif
+
+#define PRIx8		PRI8"x"
+#define PRIxLEAST8	PRILEAST8"x"
+#define PRIxFAST8	PRIFAST8"x"
+#define PRIx16		PRI16"x"
+#define PRIxLEAST16	PRILEAST16"x"
+#define PRIxFAST16	PRIFAST16"x"
+#define PRIx32		PRI32"x"
+#define PRIxLEAST32	PRILEAST32"x"
+#define PRIxFAST32	PRIFAST32"x"
+#if _WORD_SIZE > 2 && __L64
+#define PRIx64		PRI64"x"
+#define PRIxLEAST64	PRILEAST64"x"
+#define PRIxFAST64	PRIFAST64"x"
+#endif
+
+#define PRIX8		PRI8"X"
+#define PRIXLEAST8	PRILEAST8"X"
+#define PRIXFAST8	PRIFAST8"X"
+#define PRIX16		PRI16"X"
+#define PRIXLEAST16	PRILEAST16"X"
+#define PRIXFAST16	PRIFAST16"X"
+#define PRIX32		PRI32"X"
+#define PRIXLEAST32	PRILEAST32"X"
+#define PRIXFAST32	PRIFAST32"X"
+#if _WORD_SIZE > 2 && __L64
+#define PRIX64		PRI64"X"
+#define PRIXLEAST64	PRILEAST64"X"
+#define PRIXFAST64	PRIFAST64"X"
+#endif
+
+/* Macros to scan integers with fscanf(), nonstandard first group. */
+#define SCN8		"hh"
+#define SCNLEAST8	"hh"
+#define SCNFAST8	""
+#define SCN16		"h"
+#define SCNLEAST16	"h"
+#define SCNFAST16	""
+#if _WORD_SIZE == 2
+#define SCN32		"l"
+#define SCNLEAST32	"l"
+#define SCNFAST32	"l"
+#else
+#define SCN32		""
+#define SCNLEAST32	""
+#define SCNFAST32	""
+#endif
+#if _WORD_SIZE > 2 && __L64
+#define SCN64		"l"
+#define SCNLEAST64	"l"
+#define SCNFAST64	"l"
+#endif
+
+/* Macros for fscanf, the ones defined by the standard. */
+#define SCNd8		SCN8"d"
+#define SCNdLEAST8	SCNLEAST8"d"
+#define SCNdFAST8	SCNFAST8"d"
+#define SCNd16		SCN16"d"
+#define SCNdLEAST16	SCNLEAST16"d"
+#define SCNdFAST16	SCNFAST16"d"
+#define SCNd32		SCN32"d"
+#define SCNdLEAST32	SCNLEAST32"d"
+#define SCNdFAST32	SCNFAST32"d"
+#if _WORD_SIZE > 2 && __L64
+#define SCNd64		SCN64"d"
+#define SCNdLEAST64	SCNLEAST64"d"
+#define SCNdFAST64	SCNFAST64"d"
+#endif
+
+#define SCNi8		SCN8"i"
+#define SCNiLEAST8	SCNLEAST8"i"
+#define SCNiFAST8	SCNFAST8"i"
+#define SCNi16		SCN16"i"
+#define SCNiLEAST16	SCNLEAST16"i"
+#define SCNiFAST16	SCNFAST16"i"
+#define SCNi32		SCN32"i"
+#define SCNiLEAST32	SCNLEAST32"i"
+#define SCNiFAST32	SCNFAST32"i"
+#if _WORD_SIZE > 2 && __L64
+#define SCNi64		SCN64"i"
+#define SCNiLEAST64	SCNLEAST64"i"
+#define SCNiFAST64	SCNFAST64"i"
+#endif
+
+#define SCNo8		SCN8"o"
+#define SCNoLEAST8	SCNLEAST8"o"
+#define SCNoFAST8	SCNFAST8"o"
+#define SCNo16		SCN16"o"
+#define SCNoLEAST16	SCNLEAST16"o"
+#define SCNoFAST16	SCNFAST16"o"
+#define SCNo32		SCN32"o"
+#define SCNoLEAST32	SCNLEAST32"o"
+#define SCNoFAST32	SCNFAST32"o"
+#if _WORD_SIZE > 2 && __L64
+#define SCNo64		SCN64"o"
+#define SCNoLEAST64	SCNLEAST64"o"
+#define SCNoFAST64	SCNFAST64"o"
+#endif
+
+#define SCNu8		SCN8"u"
+#define SCNuLEAST8	SCNLEAST8"u"
+#define SCNuFAST8	SCNFAST8"u"
+#define SCNu16		SCN16"u"
+#define SCNuLEAST16	SCNLEAST16"u"
+#define SCNuFAST16	SCNFAST16"u"
+#define SCNu32		SCN32"u"
+#define SCNuLEAST32	SCNLEAST32"u"
+#define SCNuFAST32	SCNFAST32"u"
+#if _WORD_SIZE > 2 && __L64
+#define SCNu64		SCN64"u"
+#define SCNuLEAST64	SCNLEAST64"u"
+#define SCNuFAST64	SCNFAST64"u"
+#endif
+
+#define SCNx8		SCN8"x"
+#define SCNxLEAST8	SCNLEAST8"x"
+#define SCNxFAST8	SCNFAST8"x"
+#define SCNx16		SCN16"x"
+#define SCNxLEAST16	SCNLEAST16"x"
+#define SCNxFAST16	SCNFAST16"x"
+#define SCNx32		SCN32"x"
+#define SCNxLEAST32	SCNLEAST32"x"
+#define SCNxFAST32	SCNFAST32"x"
+#if _WORD_SIZE > 2 && __L64
+#define SCNx64		SCN64"x"
+#define SCNxLEAST64	SCNLEAST64"x"
+#define SCNxFAST64	SCNFAST64"x"
+#endif
+#endif /* !__cplusplus || __STDC_FORMAT_MACROS */
+
+/* Integer conversion functions for [u]intmax_t. */
+#define stroimax(nptr, endptr, base)	strtol(nptr, endptr, base)
+#define stroumax(nptr, endptr, base)	strtoul(nptr, endptr, base)
+
+#endif /* _INTTYPES_H */
Index: /trunk/minix/include/lib.h
===================================================================
--- /trunk/minix/include/lib.h	(revision 9)
+++ /trunk/minix/include/lib.h	(revision 9)
@@ -0,0 +1,36 @@
+/* The <lib.h> header is the master header used by the library.
+ * All the C files in the lib subdirectories include it.
+ */
+
+#ifndef _LIB_H
+#define _LIB_H
+
+/* First come the defines. */
+#define _POSIX_SOURCE      1	/* tell headers to include POSIX stuff */
+#define _MINIX             1	/* tell headers to include MINIX stuff */
+
+/* The following are so basic, all the lib files get them automatically. */
+#include <minix/config.h>	/* must be first */
+#include <sys/types.h>
+#include <limits.h>
+#include <errno.h>
+#include <ansi.h>
+
+#include <minix/const.h>
+#include <minix/com.h>
+#include <minix/type.h>
+#include <minix/callnr.h>
+
+#include <minix/ipc.h>
+
+#define MM                 PM_PROC_NR
+#define FS                 FS_PROC_NR
+
+_PROTOTYPE( int __execve, (const char *_path, char *const _argv[], 
+			char *const _envp[], int _nargs, int _nenvps)	);
+_PROTOTYPE( int _syscall, (int _who, int _syscallnr, message *_msgptr)	);
+_PROTOTYPE( void _loadname, (const char *_name, message *_msgptr)	);
+_PROTOTYPE( int _len, (const char *_s)					);
+_PROTOTYPE( void _begsig, (int _dummy)					);
+
+#endif /* _LIB_H */
Index: /trunk/minix/include/libgen.h
===================================================================
--- /trunk/minix/include/libgen.h	(revision 9)
+++ /trunk/minix/include/libgen.h	(revision 9)
@@ -0,0 +1,9 @@
+/*
+libgen.h
+*/
+
+#include <ansi.h>
+
+/* Open Group Base Specifications Issue 6 (not complete) */
+_PROTOTYPE( char *basename, (char *_path)				);
+
Index: /trunk/minix/include/libutil.h
===================================================================
--- /trunk/minix/include/libutil.h	(revision 9)
+++ /trunk/minix/include/libutil.h	(revision 9)
@@ -0,0 +1,8 @@
+#ifndef _LIBUTIL_H
+#define _LIBUTIL_H 1
+
+#include <termios.h>
+
+int openpty(int *, int *, char *, struct termios *, struct winsize *);
+
+#endif
Index: /trunk/minix/include/limits.h
===================================================================
--- /trunk/minix/include/limits.h	(revision 9)
+++ /trunk/minix/include/limits.h	(revision 9)
@@ -0,0 +1,87 @@
+/* The <limits.h> header defines some basic sizes, both of the language types 
+ * (e.g., the number of bits in an integer), and of the operating system (e.g.
+ * the number of characters in a file name.
+ */
+
+#ifndef _LIMITS_H
+#define _LIMITS_H
+
+/* Definitions about chars (8 bits in MINIX, and signed). */
+#define CHAR_BIT           8	/* # bits in a char */
+#define CHAR_MIN        -128	/* minimum value of a char */
+#define CHAR_MAX         127	/* maximum value of a char */
+#define SCHAR_MIN       -128	/* minimum value of a signed char */
+#define SCHAR_MAX        127	/* maximum value of a signed char */
+#define UCHAR_MAX        255	/* maximum value of an unsigned char */
+#define MB_LEN_MAX         1	/* maximum length of a multibyte char */
+
+/* Definitions about shorts (16 bits in MINIX). */
+#define SHRT_MIN  (-32767-1)	/* minimum value of a short */
+#define SHRT_MAX       32767	/* maximum value of a short */
+#define USHRT_MAX     0xFFFF	/* maximum value of unsigned short */
+
+/* _EM_WSIZE is a compiler-generated symbol giving the word size in bytes. */
+#if _EM_WSIZE == 2
+#define INT_MIN   (-32767-1)	/* minimum value of a 16-bit int */
+#define INT_MAX        32767	/* maximum value of a 16-bit int */
+#define UINT_MAX      0xFFFF	/* maximum value of an unsigned 16-bit int */
+#endif
+
+#if _EM_WSIZE == 4
+#define INT_MIN (-2147483647-1)	/* minimum value of a 32-bit int */
+#define INT_MAX   2147483647	/* maximum value of a 32-bit int */
+#define UINT_MAX  0xFFFFFFFF	/* maximum value of an unsigned 32-bit int */
+#endif
+
+/*Definitions about longs (32 bits in MINIX). */
+#define LONG_MIN (-2147483647L-1)/* minimum value of a long */
+#define LONG_MAX  2147483647L	/* maximum value of a long */
+#define ULONG_MAX 0xFFFFFFFFL	/* maximum value of an unsigned long */
+
+#include <sys/dir.h>
+
+/* Minimum sizes required by the POSIX P1003.1 standard (Table 2-3). */
+#ifdef _POSIX_SOURCE		/* these are only visible for POSIX */
+#define _POSIX_ARG_MAX    4096	/* exec() may have 4K worth of args */
+#define _POSIX_CHILD_MAX     6	/* a process may have 6 children */
+#define _POSIX_LINK_MAX      8	/* a file may have 8 links */
+#define _POSIX_MAX_CANON   255	/* size of the canonical input queue */
+#define _POSIX_MAX_INPUT   255	/* you can type 255 chars ahead */
+#define _POSIX_NAME_MAX DIRSIZ	/* max. file name length */
+#define _POSIX_NGROUPS_MAX   0	/* supplementary group IDs are optional */
+#define _POSIX_OPEN_MAX     16	/* a process may have 16 files open */
+#define _POSIX_PATH_MAX    255	/* a pathname may contain 255 chars */
+#define _POSIX_PIPE_BUF    512	/* pipes writes of 512 bytes must be atomic */
+#define _POSIX_STREAM_MAX    8	/* at least 8 FILEs can be open at once */
+#define _POSIX_TZNAME_MAX    3	/* time zone names can be at least 3 chars */
+#define _POSIX_SSIZE_MAX 32767	/* read() must support 32767 byte reads */
+
+/* Values actually implemented by MINIX (Tables 2-4, 2-5, 2-6, and 2-7). */
+/* Some of these old names had better be defined when not POSIX. */
+#define _NO_LIMIT          100	/* arbitrary number; limit not enforced */
+
+#define NGROUPS_MAX          0	/* supplemental group IDs not available */
+#if _EM_WSIZE > 2
+#define ARG_MAX          16384	/* # bytes of args + environ for exec() */
+#else
+#define ARG_MAX           4096	/* args + environ on small machines */
+#endif
+#define CHILD_MAX    _NO_LIMIT	/* MINIX does not limit children */
+#define OPEN_MAX            30	/* # open files a process may have */
+#if 0			/* V1 file system */
+#define LINK_MAX      CHAR_MAX	/* # links a file may have */
+#else			/* V2 or better file system */
+#define LINK_MAX      SHRT_MAX	/* # links a file may have */
+#endif
+#define MAX_CANON          255	/* size of the canonical input queue */
+#define MAX_INPUT          255	/* size of the type-ahead buffer */
+#define NAME_MAX        DIRSIZ	/* # chars in a file name */
+#define PATH_MAX           255	/* # chars in a path name */
+#define PIPE_BUF          7168	/* # bytes in atomic write to a pipe */
+#define STREAM_MAX          20	/* must be the same as FOPEN_MAX in stdio.h */
+#define TZNAME_MAX           3	/* maximum bytes in a time zone name is 3 */
+#define SSIZE_MAX        32767	/* max defined byte count for read() */
+
+#endif /* _POSIX_SOURCE */
+
+#endif /* _LIMITS_H */
Index: /trunk/minix/include/locale.h
===================================================================
--- /trunk/minix/include/locale.h	(revision 9)
+++ /trunk/minix/include/locale.h	(revision 9)
@@ -0,0 +1,47 @@
+/* The <locale.h> header is used to custom tailor currency symbols, decimal 
+ * points, and other items to the local style.  It is ANSI's attempt at 
+ * avoiding cultural imperialism.  The locale given below is for C.
+ */
+
+#ifndef _LOCALE_H
+#define _LOCALE_H
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+struct lconv {
+  char *decimal_point;		/* "." */
+  char *thousands_sep;		/* ""  */
+  char *grouping;		/* ""  */
+  char *int_curr_symbol;	/* ""  */
+  char *currency_symbol;	/* ""  */
+  char *mon_decimal_point;	/* ""  */
+  char *mon_thousands_sep;	/* ""  */
+  char *mon_grouping;		/* ""  */
+  char *positive_sign;		/* ""  */
+  char *negative_sign;		/* ""  */
+  char int_frac_digits;		/* CHAR_MAX */
+  char frac_digits;		/* CHAR_MAX */
+  char p_cs_precedes;		/* CHAR_MAX */
+  char p_sep_by_space;		/* CHAR_MAX */
+  char n_cs_precedes;		/* CHAR_MAX */
+  char n_sep_by_space;		/* CHAR_MAX */
+  char p_sign_posn;		/* CHAR_MAX */
+  char n_sign_posn;		/* CHAR_MAX */
+};
+
+#define NULL    ((void *)0)
+
+#define LC_ALL             1
+#define LC_COLLATE         2
+#define LC_CTYPE           3
+#define LC_MONETARY        4
+#define LC_NUMERIC         5
+#define LC_TIME            6
+
+/* Function Prototypes. */
+_PROTOTYPE( char *setlocale, (int _category, const char *_locale)	);
+_PROTOTYPE( struct lconv *localeconv, (void)				);
+
+#endif /* _LOCALE_H */
Index: /trunk/minix/include/math.h
===================================================================
--- /trunk/minix/include/math.h	(revision 9)
+++ /trunk/minix/include/math.h	(revision 9)
@@ -0,0 +1,44 @@
+/* The <math.h> header contains prototypes for mathematical functions. */
+
+#ifndef _MATH_H
+#define _MATH_H
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+#define HUGE_VAL	(__huge_val())		/* may be infinity */
+
+/* Function Prototypes. */
+_PROTOTYPE( double __huge_val,	(void)					);
+_PROTOTYPE( int __IsNan,	(double _x)				);
+
+_PROTOTYPE( double acos,  (double _x)					);
+_PROTOTYPE( double asin,  (double _x)					);
+_PROTOTYPE( double atan,  (double _x)					);
+_PROTOTYPE( double atan2, (double _y, double _x)			);
+_PROTOTYPE( double ceil,  (double _x)					);
+_PROTOTYPE( double cos,   (double _x)					);
+_PROTOTYPE( double cosh,  (double _x)					);
+_PROTOTYPE( double exp,   (double _x)					);
+_PROTOTYPE( double fabs,  (double _x)					);
+_PROTOTYPE( double floor, (double _x)					);
+_PROTOTYPE( double fmod,  (double _x, double _y)			);
+_PROTOTYPE( double frexp, (double _x, int *_exp)			);
+_PROTOTYPE( double ldexp, (double _x, int _exp)				);
+_PROTOTYPE( double log,   (double _x)					);
+_PROTOTYPE( double log10, (double _x)					);
+_PROTOTYPE( double modf,  (double _x, double *_iptr)			);
+_PROTOTYPE( double pow,   (double _x, double _y)			);
+_PROTOTYPE( double sin,   (double _x)					);
+_PROTOTYPE( double sinh,  (double _x)					);
+_PROTOTYPE( double sqrt,  (double _x)					);
+_PROTOTYPE( double tan,   (double _x)					);
+_PROTOTYPE( double tanh,  (double _x)					);
+_PROTOTYPE( double hypot, (double _x, double _y)			);
+
+#ifdef _POSIX_SOURCE	/* STD-C? */
+#include <mathconst.h>
+#endif
+
+#endif /* _MATH_H */
Index: /trunk/minix/include/mathconst.h
===================================================================
--- /trunk/minix/include/mathconst.h	(revision 9)
+++ /trunk/minix/include/mathconst.h	(revision 9)
@@ -0,0 +1,29 @@
+/*
+ * mathconst.h - mathematic constants
+ */
+/* $Header: /cvsup/minix/src/include/mathconst.h,v 1.1.1.1 2005/04/21 14:55:50 beng Exp $ */
+
+#ifndef _MATHCONST_H
+#define	_MATHCONST_H
+
+/* Some constants (Hart & Cheney) */
+#define	M_PI		3.14159265358979323846264338327950288
+#define	M_2PI		6.28318530717958647692528676655900576
+#define	M_3PI_4		2.35619449019234492884698253745962716
+#define	M_PI_2		1.57079632679489661923132169163975144
+#define	M_3PI_8		1.17809724509617246442349126872981358
+#define	M_PI_4		0.78539816339744830961566084581987572
+#define	M_PI_8		0.39269908169872415480783042290993786
+#define	M_1_PI		0.31830988618379067153776752674502872
+#define	M_2_PI		0.63661977236758134307553505349005744
+#define	M_4_PI		1.27323954473516268615107010698011488
+#define	M_E		2.71828182845904523536028747135266250
+#define	M_LOG2E		1.44269504088896340735992468100189213
+#define	M_LOG10E	0.43429448190325182765112891891660508
+#define	M_LN2		0.69314718055994530941723212145817657
+#define	M_LN10		2.30258509299404568401799145468436421
+#define	M_SQRT2		1.41421356237309504880168872420969808
+#define	M_1_SQRT2	0.70710678118654752440084436210484904
+#define	M_EULER		0.57721566490153286060651209008240243
+
+#endif /* _MATHCONST_H */
Index: /trunk/minix/include/minix/bitmap.h
===================================================================
--- /trunk/minix/include/minix/bitmap.h	(revision 9)
+++ /trunk/minix/include/minix/bitmap.h	(revision 9)
@@ -0,0 +1,11 @@
+#ifndef _BITMAP_H
+#define _BITMAP_H
+
+/* Bit map operations to manipulate bits of a simple mask variable. */
+#define bit_set(mask, n)	((mask) |= (1 << (n)))
+#define bit_unset(mask, n)	((mask) &= ~(1 << (n)))
+#define bit_isset(mask, n)	((mask) & (1 << (n)))
+#define bit_empty(mask)		((mask) = 0)
+#define bit_fill(mask)		((mask) = ~0)
+
+#endif	/* _BITMAP_H */
Index: /trunk/minix/include/minix/callnr.h
===================================================================
--- /trunk/minix/include/minix/callnr.h	(revision 9)
+++ /trunk/minix/include/minix/callnr.h	(revision 9)
@@ -0,0 +1,88 @@
+#define NCALLS		  95	/* number of system calls allowed */
+
+#define EXIT		   1 
+#define FORK		   2 
+#define READ		   3 
+#define WRITE		   4 
+#define OPEN		   5 
+#define CLOSE		   6 
+#define WAIT		   7
+#define CREAT		   8 
+#define LINK		   9 
+#define UNLINK		  10 
+#define WAITPID		  11
+#define CHDIR		  12 
+#define TIME		  13
+#define MKNOD		  14 
+#define CHMOD		  15 
+#define CHOWN		  16 
+#define BRK		  17
+#define STAT		  18 
+#define LSEEK		  19
+#define GETPID		  20
+#define MOUNT		  21 
+#define UMOUNT		  22 
+#define SETUID		  23
+#define GETUID		  24
+#define STIME		  25
+#define PTRACE		  26
+#define ALARM		  27
+#define FSTAT		  28 
+#define PAUSE		  29
+#define UTIME		  30 
+#define ACCESS		  33 
+#define SYNC		  36 
+#define KILL		  37
+#define RENAME		  38
+#define MKDIR		  39
+#define RMDIR		  40
+#define DUP		  41 
+#define PIPE		  42 
+#define TIMES		  43
+#define SYMLINK		  45
+#define SETGID		  46
+#define GETGID		  47
+#define SIGNAL		  48
+#define RDLNK		  49
+#define LSTAT		  50
+#define IOCTL		  54
+#define FCNTL		  55
+#define EXEC		  59
+#define UMASK		  60 
+#define CHROOT		  61 
+#define SETSID		  62
+#define GETPGRP		  63
+
+/* The following are not system calls, but are processed like them. */
+#define UNPAUSE		  65	/* to MM or FS: check for EINTR */
+#define REVIVE	 	  67	/* to FS: revive a sleeping process */
+#define TASK_REPLY	  68	/* to FS: reply code from tty task */
+
+/* Posix signal handling. */
+#define SIGACTION	  71
+#define SIGSUSPEND	  72
+#define SIGPENDING	  73
+#define SIGPROCMASK	  74
+#define SIGRETURN	  75
+
+#define REBOOT		  76	/* to PM */
+
+/* MINIX specific calls, e.g., to support system services. */
+#define SVRCTL		  77
+#define PROCSTAT          78    /* to PM */
+#define GETSYSINFO	  79	/* to PM or FS */
+#define GETPROCNR         80    /* to PM */
+#define DEVCTL		  81    /* to FS */
+#define FSTATFS	 	  82	/* to FS */
+#define ALLOCMEM	  83	/* to PM */
+#define FREEMEM		  84	/* to PM */
+#define SELECT            85	/* to FS */
+#define FCHDIR            86	/* to FS */
+#define FSYNC             87	/* to FS */
+#define GETPRIORITY       88	/* to PM */
+#define SETPRIORITY       89	/* to PM */
+#define GETTIMEOFDAY      90	/* to PM */
+#define SETEUID		  91	/* to PM */
+#define SETEGID		  92	/* to PM */
+#define TRUNCATE	  93	/* to FS */
+#define FTRUNCATE	  94	/* to FS */
Index: /trunk/minix/include/minix/cdrom.h
===================================================================
--- /trunk/minix/include/minix/cdrom.h	(revision 9)
+++ /trunk/minix/include/minix/cdrom.h	(revision 9)
@@ -0,0 +1,39 @@
+/* This file contains some structures used by the Mitsumi cdrom driver.
+ *
+ *  Feb 13 1995			Author: Michel R. Prevenier 
+ */
+
+/* Index into the mss arrays */
+#define MINUTES	0
+#define SECONDS	1
+#define SECTOR	2
+
+struct cd_play_mss
+{
+	u8_t	begin_mss[3];
+	u8_t	end_mss[3];
+};
+
+struct cd_play_track
+{
+	u8_t 	begin_track;
+	u8_t 	end_track;
+};
+
+struct cd_disk_info
+{
+	u8_t	first_track;
+	u8_t 	last_track;
+	u8_t	disk_length_mss[3];
+	u8_t	first_track_mss[3];
+};
+
+struct cd_toc_entry
+{
+	u8_t	control_address;
+	u8_t	track_nr;
+	u8_t	index_nr;
+	u8_t	track_time_mss[3];
+        u8_t	reserved;
+	u8_t	position_mss[3];
+};
Index: /trunk/minix/include/minix/com.h
===================================================================
--- /trunk/minix/include/minix/com.h	(revision 9)
+++ /trunk/minix/include/minix/com.h	(revision 9)
@@ -0,0 +1,508 @@
+#ifndef _MINIX_COM_H
+#define _MINIX_COM_H 
+
+/*===========================================================================*
+ *          	    		Magic process numbers			     *
+ *===========================================================================*/
+
+/* These may not be any valid endpoint (see <minix/endpoint.h>). */
+#define ANY		0x7ace	/* used to indicate 'any process' */
+#define NONE 		0x6ace  /* used to indicate 'no process at all' */
+#define SELF		0x8ace 	/* used to indicate 'own process' */
+#define _MAX_MAGIC_PROC (SELF)	/* used by <minix/endpoint.h> 
+				   to determine generation size */
+
+/*===========================================================================*
+ *            	Process numbers of processes in the system image	     *
+ *===========================================================================*/
+
+/* The values of several task numbers depend on whether they or other tasks
+ * are enabled. They are defined as (PREVIOUS_TASK - ENABLE_TASK) in general.
+ * ENABLE_TASK is either 0 or 1, so a task either gets a new number, or gets
+ * the same number as the previous task and is further unused. Note that the
+ * order should correspond to the order in the task table defined in table.c. 
+ */
+
+/* Kernel tasks. These all run in the same address space. */
+#define IDLE             -4	/* runs when no one else can run */
+#define CLOCK  		 -3	/* alarms and other clock functions */
+#define SYSTEM           -2	/* request system functionality */
+#define KERNEL           -1	/* pseudo-process for IPC and scheduling */
+#define HARDWARE     KERNEL	/* for hardware interrupt handlers */
+
+/* Number of tasks. Note that NR_PROCS is defined in <minix/config.h>. */
+#define NR_TASKS	  4 
+
+/* User-space processes, that is, device drivers, servers, and INIT. */
+#define PM_PROC_NR	  0	/* process manager */
+#define FS_PROC_NR 	  1	/* file system */
+#define RS_PROC_NR 	  2	/* reincarnation server */
+#define MEM_PROC_NR 	  3  	/* memory driver (RAM disk, null, etc.) */
+#define LOG_PROC_NR	  4	/* log device driver */
+#define TTY_PROC_NR	  5	/* terminal (TTY) driver */
+#define DS_PROC_NR	  6    	/* data store server */
+#define INIT_PROC_NR	  7    	/* init -- goes multiuser */
+
+/* Number of processes contained in the system image. */
+#define NR_BOOT_PROCS 	(NR_TASKS + INIT_PROC_NR + 1)
+
+/*===========================================================================*
+ *                	   Kernel notification types                         *
+ *===========================================================================*/
+
+/* Kernel notification types. In principle, these can be sent to any process,
+ * so make sure that these types do not interfere with other message types.
+ * Notifications are prioritized because of the way they are unhold() and
+ * blocking notifications are delivered. The lowest numbers go first. The
+ * offset are used for the per-process notification bit maps. 
+ */
+#define NOTIFY_MESSAGE		  0x1000
+#define NOTIFY_FROM(p_nr)	 (NOTIFY_MESSAGE | ((p_nr) + NR_TASKS)) 
+#  define PROC_EVENT	NOTIFY_FROM(PM_PROC_NR) /* process status change */
+#  define SYN_ALARM	NOTIFY_FROM(CLOCK) 	/* synchronous alarm */
+#  define SYS_SIG	NOTIFY_FROM(SYSTEM) 	/* system signal */
+#  define HARD_INT	NOTIFY_FROM(HARDWARE) 	/* hardware interrupt */
+#  define NEW_KSIG	NOTIFY_FROM(HARDWARE)  	/* new kernel signal */
+#  define FKEY_PRESSED	NOTIFY_FROM(TTY_PROC_NR)/* function key press */
+#  define DEV_PING	NOTIFY_FROM(RS_PROC_NR) /* driver liveness ping */
+
+/* Shorthands for message parameters passed with notifications. */
+#define NOTIFY_SOURCE		m_source
+#define NOTIFY_TYPE		m_type
+#define NOTIFY_ARG		m2_l1
+#define NOTIFY_TIMESTAMP	m2_l2
+#define NOTIFY_FLAGS		m2_i1
+
+/*===========================================================================*
+ *                Messages for BUS controller drivers 			     *
+ *===========================================================================*/
+#define BUSC_RQ_BASE	0x300	/* base for request types */
+#define BUSC_RS_BASE	0x380	/* base for response types */
+
+#define BUSC_PCI_INIT		(BUSC_RQ_BASE + 0)	/* First message to
+							 * PCI driver
+							 */
+#define BUSC_PCI_FIRST_DEV	(BUSC_RQ_BASE + 1)	/* Get index (and
+							 * vid/did) of the
+							 * first PCI device
+							 */
+#define BUSC_PCI_NEXT_DEV	(BUSC_RQ_BASE + 2)	/* Get index (and
+							 * vid/did) of the
+							 * next PCI device
+							 */
+#define BUSC_PCI_FIND_DEV	(BUSC_RQ_BASE + 3)	/* Get index of a
+							 * PCI device based on
+							 * bus/dev/function
+							 */
+#define BUSC_PCI_IDS		(BUSC_RQ_BASE + 4)	/* Get vid/did from an
+							 * index
+							 */
+#define BUSC_PCI_DEV_NAME	(BUSC_RQ_BASE + 5)	/* Get the name of a
+							 * PCI device
+							 */
+#define BUSC_PCI_SLOT_NAME	(BUSC_RQ_BASE + 6)	/* Get the name of a
+							 * PCI slot
+							 */
+#define BUSC_PCI_RESERVE	(BUSC_RQ_BASE + 7)	/* Reserve a PCI dev */
+#define BUSC_PCI_ATTR_R8	(BUSC_RQ_BASE + 8)	/* Read 8-bit
+							 * attribute value
+							 */
+#define BUSC_PCI_ATTR_R16	(BUSC_RQ_BASE + 9)	/* Read 16-bit
+							 * attribute value
+							 */
+#define BUSC_PCI_ATTR_R32	(BUSC_RQ_BASE + 10)	/* Read 32-bit
+							 * attribute value
+							 */
+#define BUSC_PCI_ATTR_W8	(BUSC_RQ_BASE + 11)	/* Write 8-bit
+							 * attribute value
+							 */
+#define BUSC_PCI_ATTR_W16	(BUSC_RQ_BASE + 12)	/* Write 16-bit
+							 * attribute value
+							 */
+#define BUSC_PCI_ATTR_W32	(BUSC_RQ_BASE + 13)	/* Write 32-bit
+							 * attribute value
+							 */
+#define BUSC_PCI_RESCAN		(BUSC_RQ_BASE + 14)	/* Rescan bus */
+
+/*===========================================================================*
+ *                Messages for BLOCK and CHARACTER device drivers	     *
+ *===========================================================================*/
+
+/* Message types for device drivers. */
+#define DEV_RQ_BASE   0x400	/* base for device request types */
+#define DEV_RS_BASE   0x500	/* base for device response types */
+
+#define CANCEL       	(DEV_RQ_BASE +  0) /* force a task to cancel */
+#define DEV_READ	(DEV_RQ_BASE +  3) /* read from minor device */
+#define DEV_WRITE   	(DEV_RQ_BASE +  4) /* write to minor device */
+#define DEV_IOCTL    	(DEV_RQ_BASE +  5) /* I/O control code */
+#define DEV_OPEN     	(DEV_RQ_BASE +  6) /* open a minor device */
+#define DEV_CLOSE    	(DEV_RQ_BASE +  7) /* close a minor device */
+#define DEV_SCATTER  	(DEV_RQ_BASE +  8) /* write from a vector */
+#define DEV_GATHER   	(DEV_RQ_BASE +  9) /* read into a vector */
+#define TTY_SETPGRP 	(DEV_RQ_BASE + 10) /* set process group */
+#define TTY_EXIT	(DEV_RQ_BASE + 11) /* process group leader exited */	
+#define DEV_SELECT	(DEV_RQ_BASE + 12) /* request select() attention */
+#define DEV_STATUS   	(DEV_RQ_BASE + 13) /* request driver status */
+
+#define DEV_REPLY       (DEV_RS_BASE + 0) /* general task reply */
+#define DEV_CLONED      (DEV_RS_BASE + 1) /* return cloned minor */
+#define DEV_REVIVE      (DEV_RS_BASE + 2) /* driver revives process */
+#define DEV_IO_READY    (DEV_RS_BASE + 3) /* selected device ready */
+#define DEV_NO_STATUS   (DEV_RS_BASE + 4) /* empty status reply */
+
+/* Field names for messages to block and character device drivers. */
+#define DEVICE    	m2_i1	/* major-minor device */
+#define IO_ENDPT	m2_i2	/* which (proc/endpoint) wants I/O? */
+#define COUNT   	m2_i3	/* how many bytes to transfer */
+#define REQUEST 	m2_i3	/* ioctl request code */
+#define POSITION	m2_l1	/* file offset */
+#define ADDRESS 	m2_p1	/* core buffer address */
+
+/* Field names for DEV_SELECT messages to device drivers. */
+#define DEV_MINOR	m2_i1	/* minor device */
+#define DEV_SEL_OPS	m2_i2	/* which select operations are requested */
+#define DEV_SEL_WATCH	m2_i3	/* request notify if no operations are ready */
+
+/* Field names used in reply messages from tasks. */
+#define REP_ENDPT	m2_i1	/* # of proc on whose behalf I/O was done */
+#define REP_STATUS	m2_i2	/* bytes transferred or error number */
+#  define SUSPEND 	 -998 	/* status to suspend caller, reply later */
+
+/* Field names for messages to TTY driver. */
+#define TTY_LINE	DEVICE	/* message parameter: terminal line */
+#define TTY_REQUEST	COUNT	/* message parameter: ioctl request code */
+#define TTY_SPEK	POSITION/* message parameter: ioctl speed, erasing */
+#define TTY_FLAGS	m2_l2	/* message parameter: ioctl tty mode */
+#define TTY_PGRP 	m2_i3	/* message parameter: process group */	
+
+/* Field names for the QIC 02 status reply from tape driver */
+#define TAPE_STAT0	m2_l1
+#define TAPE_STAT1	m2_l2
+
+/*===========================================================================*
+ *                  	   Messages for networking layer		     *
+ *===========================================================================*/
+
+/* Message types for network layer requests. This layer acts like a driver. */
+#define NW_OPEN		DEV_OPEN
+#define NW_CLOSE	DEV_CLOSE
+#define NW_READ		DEV_READ
+#define NW_WRITE	DEV_WRITE
+#define NW_IOCTL	DEV_IOCTL
+#define NW_CANCEL	CANCEL
+
+/* Base type for data link layer requests and responses. */
+#define DL_RQ_BASE	0x800		
+#define DL_RS_BASE	0x900		
+
+/* Message types for data link layer requests. */
+#define DL_WRITE	(DL_RQ_BASE + 3)
+#define DL_WRITEV	(DL_RQ_BASE + 4)
+#define DL_READ		(DL_RQ_BASE + 5)
+#define DL_READV	(DL_RQ_BASE + 6)
+#define DL_INIT		(DL_RQ_BASE + 7)
+#define DL_STOP		(DL_RQ_BASE + 8)
+#define DL_GETSTAT	(DL_RQ_BASE + 9)
+#define DL_GETNAME	(DL_RQ_BASE +10)
+
+/* Message type for data link layer replies. */
+#define DL_INIT_REPLY	(DL_RS_BASE + 20)
+#define DL_TASK_REPLY	(DL_RS_BASE + 21)
+#define DL_NAME_REPLY	(DL_RS_BASE + 22)
+
+/* Field names for data link layer messages. */
+#define DL_PORT		m2_i1
+#define DL_PROC		m2_i2	/* endpoint */
+#define DL_COUNT	m2_i3
+#define DL_MODE		m2_l1
+#define DL_CLCK		m2_l2
+#define DL_ADDR		m2_p1
+#define DL_STAT		m2_l1
+#define DL_NAME		m3_ca1
+
+/* Bits in 'DL_STAT' field of DL replies. */
+#  define DL_PACK_SEND		0x01
+#  define DL_PACK_RECV		0x02
+#  define DL_READ_IP		0x04
+
+/* Bits in 'DL_MODE' field of DL requests. */
+#  define DL_NOMODE		0x0
+#  define DL_PROMISC_REQ	0x2
+#  define DL_MULTI_REQ		0x4
+#  define DL_BROAD_REQ		0x8
+
+/*===========================================================================*
+ *                  SYSTASK request types and field names                    *
+ *===========================================================================*/
+
+/* System library calls are dispatched via a call vector, so be careful when 
+ * modifying the system call numbers. The numbers here determine which call
+ * is made from the call vector.
+ */ 
+#define KERNEL_CALL	0x600	/* base for kernel calls to SYSTEM */ 
+
+#  define SYS_FORK       (KERNEL_CALL + 0)	/* sys_fork() */
+#  define SYS_EXEC       (KERNEL_CALL + 1)	/* sys_exec() */
+#  define SYS_EXIT	 (KERNEL_CALL + 2)	/* sys_exit() */
+#  define SYS_NICE       (KERNEL_CALL + 3)	/* sys_nice() */
+#  define SYS_PRIVCTL    (KERNEL_CALL + 4)	/* sys_privctl() */
+#  define SYS_TRACE      (KERNEL_CALL + 5)	/* sys_trace() */
+#  define SYS_KILL       (KERNEL_CALL + 6)	/* sys_kill() */
+
+#  define SYS_GETKSIG    (KERNEL_CALL + 7)	/* sys_getsig() */
+#  define SYS_ENDKSIG    (KERNEL_CALL + 8)	/* sys_endsig() */
+#  define SYS_SIGSEND    (KERNEL_CALL + 9)	/* sys_sigsend() */
+#  define SYS_SIGRETURN  (KERNEL_CALL + 10)	/* sys_sigreturn() */
+
+#  define SYS_NEWMAP     (KERNEL_CALL + 11)	/* sys_newmap() */
+#  define SYS_SEGCTL     (KERNEL_CALL + 12)	/* sys_segctl() */
+#  define SYS_MEMSET     (KERNEL_CALL + 13)	/* sys_memset() */
+
+#  define SYS_UMAP       (KERNEL_CALL + 14)	/* sys_umap() */
+#  define SYS_VIRCOPY    (KERNEL_CALL + 15)	/* sys_vircopy() */
+#  define SYS_PHYSCOPY   (KERNEL_CALL + 16) 	/* sys_physcopy() */
+#  define SYS_VIRVCOPY   (KERNEL_CALL + 17)	/* sys_virvcopy() */
+#  define SYS_PHYSVCOPY  (KERNEL_CALL + 18)	/* sys_physvcopy() */
+
+#  define SYS_IRQCTL     (KERNEL_CALL + 19)	/* sys_irqctl() */
+#  define SYS_INT86      (KERNEL_CALL + 20)	/* sys_int86() */
+#  define SYS_DEVIO      (KERNEL_CALL + 21)	/* sys_devio() */
+#  define SYS_SDEVIO     (KERNEL_CALL + 22)	/* sys_sdevio() */
+#  define SYS_VDEVIO     (KERNEL_CALL + 23)	/* sys_vdevio() */
+
+#  define SYS_SETALARM	 (KERNEL_CALL + 24)	/* sys_setalarm() */
+#  define SYS_TIMES	 (KERNEL_CALL + 25)	/* sys_times() */
+#  define SYS_GETINFO    (KERNEL_CALL + 26) 	/* sys_getinfo() */
+#  define SYS_ABORT      (KERNEL_CALL + 27)	/* sys_abort() */
+#  define SYS_IOPENABLE  (KERNEL_CALL + 28)	/* sys_enable_iop() */
+#  define SYS_VM_SETBUF  (KERNEL_CALL + 29)	/* sys_vm_setbuf() */
+#  define SYS_VM_MAP  	 (KERNEL_CALL + 30)	/* sys_vm_map() */
+
+#define NR_SYS_CALLS	31	/* number of system calls */ 
+
+/* Subfunctions for SYS_PRIVCTL */
+#define SYS_PRIV_INIT		1	/* Initialize a privilege structure */
+#define SYS_PRIV_ADD_IO		2	/* Add I/O range (struct io_range) */
+#define SYS_PRIV_ADD_MEM	3	/* Add memory range (struct mem_range)
+					 */
+#define SYS_PRIV_ADD_IRQ	4	/* Add IRQ */
+
+/* Field names for SYS_MEMSET, SYS_SEGCTL. */
+#define MEM_PTR		m2_p1	/* base */
+#define MEM_COUNT	m2_l1	/* count */
+#define MEM_PATTERN	m2_l2   /* pattern to write */
+#define MEM_CHUNK_BASE	m4_l1	/* physical base address */
+#define MEM_CHUNK_SIZE	m4_l2	/* size of mem chunk */
+#define MEM_TOT_SIZE	m4_l3	/* total memory size */
+#define MEM_CHUNK_TAG	m4_l4	/* tag to identify chunk of mem */
+
+/* Field names for SYS_DEVIO, SYS_VDEVIO, SYS_SDEVIO. */
+#define DIO_REQUEST	m2_i3	/* device in or output */
+#   define DIO_INPUT	    0	/* input */
+#   define DIO_OUTPUT	    1	/* output */
+#define DIO_TYPE	m2_i1   /* flag indicating byte, word, or long */ 
+#   define DIO_BYTE	  'b'	/* byte type values */
+#   define DIO_WORD	  'w'	/* word type values */
+#   define DIO_LONG	  'l'	/* long type values */
+#define DIO_PORT	m2_l1	/* single port address */
+#define DIO_VALUE	m2_l2	/* single I/O value */
+#define DIO_VEC_ADDR	m2_p1   /* address of buffer or (p,v)-pairs */
+#define DIO_VEC_SIZE	m2_l2   /* number of elements in vector */
+#define DIO_VEC_ENDPT	m2_i2   /* number of process where vector is */
+
+/* Field names for SYS_SIGNARLM, SYS_FLAGARLM, SYS_SYNCALRM. */
+#define ALRM_EXP_TIME   m2_l1	/* expire time for the alarm call */
+#define ALRM_ABS_TIME   m2_i2	/* set to 1 to use absolute alarm time */
+#define ALRM_TIME_LEFT  m2_l1	/* how many ticks were remaining */
+#define ALRM_ENDPT      m2_i1	/* which process wants the alarm? */
+#define ALRM_FLAG_PTR	m2_p1   /* virtual address of timeout flag */ 	
+
+/* Field names for SYS_IRQCTL. */
+#define IRQ_REQUEST     m5_c1	/* what to do? */
+#  define IRQ_SETPOLICY     1	/* manage a slot of the IRQ table */
+#  define IRQ_RMPOLICY      2	/* remove a slot of the IRQ table */
+#  define IRQ_ENABLE        3	/* enable interrupts */
+#  define IRQ_DISABLE       4	/* disable interrupts */
+#define IRQ_VECTOR	m5_c2   /* irq vector */
+#define IRQ_POLICY	m5_i1   /* options for IRQCTL request */
+#  define IRQ_REENABLE  0x001	/* reenable IRQ line after interrupt */
+#  define IRQ_BYTE      0x100	/* byte values */      
+#  define IRQ_WORD      0x200	/* word values */
+#  define IRQ_LONG      0x400	/* long values */
+#define IRQ_ENDPT	m5_i2   /* endpoint number, SELF, NONE */
+#define IRQ_HOOK_ID	m5_l3   /* id of irq hook at kernel */
+
+/* Field names for SYS_SEGCTL. */
+#define SEG_SELECT	m4_l1   /* segment selector returned */ 
+#define SEG_OFFSET	m4_l2	/* offset in segment returned */
+#define SEG_PHYS	m4_l3	/* physical address of segment */
+#define SEG_SIZE	m4_l4	/* segment size */
+#define SEG_INDEX	m4_l5	/* segment index in remote map */
+
+/* Field names for SYS_VIDCOPY. */
+#define VID_REQUEST	m4_l1	/* what to do? */
+#  define VID_VID_COPY	   1	/* request vid_vid_copy() */
+#  define MEM_VID_COPY     2	/* request mem_vid_copy() */
+#define VID_SRC_ADDR	m4_l2	/* virtual address in memory */
+#define VID_SRC_OFFSET	m4_l3	/* offset in video memory */
+#define VID_DST_OFFSET	m4_l4	/* offset in video memory */
+#define VID_CP_COUNT	m4_l5	/* number of words to be copied */
+
+/* Field names for SYS_ABORT. */
+#define ABRT_HOW	m1_i1	/* RBT_REBOOT, RBT_HALT, etc. */
+#define ABRT_MON_ENDPT  m1_i2	/* process where monitor params are */
+#define ABRT_MON_LEN	m1_i3	/* length of monitor params */
+#define ABRT_MON_ADDR   m1_p1	/* virtual address of monitor params */
+
+/* Field names for _UMAP, _VIRCOPY, _PHYSCOPY. */
+#define CP_SRC_SPACE 	m5_c1	/* T or D space (stack is also D) */
+#define CP_SRC_ENDPT	m5_i1	/* process to copy from */
+#define CP_SRC_ADDR	m5_l1	/* address where data come from */
+#define CP_DST_SPACE	m5_c2	/* T or D space (stack is also D) */
+#define CP_DST_ENDPT	m5_i2	/* process to copy to */
+#define CP_DST_ADDR	m5_l2	/* address where data go to */
+#define CP_NR_BYTES	m5_l3	/* number of bytes to copy */
+
+/* Field names for SYS_VCOPY and SYS_VVIRCOPY. */
+#define VCP_NR_OK	m1_i2	/* number of successfull copies */
+#define VCP_VEC_SIZE	m1_i3	/* size of copy vector */
+#define VCP_VEC_ADDR	m1_p1	/* pointer to copy vector */
+
+/* Field names for SYS_GETINFO. */
+#define I_REQUEST      m7_i3	/* what info to get */
+#   define GET_KINFO	   0	/* get kernel information structure */
+#   define GET_IMAGE	   1	/* get system image table */
+#   define GET_PROCTAB	   2	/* get kernel process table */
+#   define GET_RANDOMNESS  3	/* get randomness buffer */
+#   define GET_MONPARAMS   4	/* get monitor parameters */
+#   define GET_KENV	   5	/* get kernel environment string */
+#   define GET_IRQHOOKS	   6	/* get the IRQ table */
+#   define GET_KMESSAGES   7	/* get kernel messages */
+#   define GET_PRIVTAB	   8	/* get kernel privileges table */
+#   define GET_KADDRESSES  9	/* get various kernel addresses */
+#   define GET_SCHEDINFO  10	/* get scheduling queues */
+#   define GET_PROC 	  11	/* get process slot if given process */
+#   define GET_MACHINE 	  12	/* get machine information */
+#   define GET_LOCKTIMING 13	/* get lock()/unlock() latency timing */
+#   define GET_BIOSBUFFER 14	/* get a buffer for BIOS calls */
+#   define GET_LOADINFO   15	/* get load average information */
+#define I_ENDPT      m7_i4	/* calling process */
+#define I_VAL_PTR      m7_p1	/* virtual address at caller */ 
+#define I_VAL_LEN      m7_i1	/* max length of value */
+#define I_VAL_PTR2     m7_p2	/* second virtual address */ 
+#define I_VAL_LEN2_E   m7_i2	/* second length, or proc nr */
+#   define GET_IRQACTIDS  16	/* get the IRQ masks */
+
+/* Field names for SYS_TIMES. */
+#define T_ENDPT      m4_l1	/* process to request time info for */
+#define T_USER_TIME    m4_l1	/* user time consumed by process */
+#define T_SYSTEM_TIME  m4_l2	/* system time consumed by process */
+#define T_CHILD_UTIME  m4_l3	/* user time consumed by process' children */
+#define T_CHILD_STIME  m4_l4	/* sys time consumed by process' children */
+#define T_BOOT_TICKS   m4_l5	/* number of clock ticks since boot time */
+
+/* vm_map */
+#define VM_MAP_ENDPT		m4_l1
+#define VM_MAP_MAPUNMAP		m4_l2
+#define VM_MAP_BASE		m4_l3
+#define VM_MAP_SIZE		m4_l4
+#define VM_MAP_ADDR		m4_l5
+
+/* Field names for SYS_TRACE, SYS_PRIVCTL. */
+#define CTL_ENDPT    m2_i1	/* process number of the caller */
+#define CTL_REQUEST    m2_i2	/* server control request */
+#define CTL_MM_PRIV    m2_i3	/* privilege as seen by PM */
+#define CTL_ARG_PTR    m2_p1	/* pointer to argument */
+#define CTL_ADDRESS    m2_l1	/* address at traced process' space */
+#define CTL_DATA       m2_l2	/* data field for tracing */
+
+/* Field names for SYS_KILL, SYS_SIGCTL */
+#define SIG_REQUEST    m2_l2	/* PM signal control request */
+#define S_GETSIG 	   0	/* get pending kernel signal */
+#define S_ENDSIG 	   1	/* finish a kernel signal */
+#define S_SENDSIG   	   2	/* POSIX style signal handling */
+#define S_SIGRETURN	   3 	/* return from POSIX handling */
+#define S_KILL		   4 	/* servers kills process with signal */
+#define SIG_ENDPT       m2_i1	/* process number for inform */
+#define SIG_NUMBER     m2_i2	/* signal number to send */
+#define SIG_FLAGS      m2_i3	/* signal flags field */
+#define SIG_MAP        m2_l1	/* used by kernel to pass signal bit map */
+#define SIG_CTXT_PTR   m2_p1	/* pointer to info to restore signal context */
+
+/* Field names for SYS_FORK, _EXEC, _EXIT, _NEWMAP. */
+#define PR_ENDPT       m1_i1	/* indicates a process */
+#define PR_PRIORITY    m1_i2	/* process priority */
+#define PR_SLOT        m1_i2	/* indicates a process slot */
+#define PR_PID	       m1_i3	/* process id at process manager */
+#define PR_STACK_PTR   m1_p1	/* used for stack ptr in sys_exec, sys_getsp */
+#define PR_TRACING     m1_i3	/* flag to indicate tracing is on/ off */
+#define PR_NAME_PTR    m1_p2	/* tells where program name is for dmp */
+#define PR_IP_PTR      m1_p3	/* initial value for ip after exec */
+#define PR_MEM_PTR     m1_p1	/* tells where memory map is for sys_newmap */
+
+/* Field names for SYS_INT86 */
+#define INT86_REG86    m1_p1	/* pointer to registers */
+
+/* Field names for SELECT (FS). */
+#define SEL_NFDS       m8_i1
+#define SEL_READFDS    m8_p1
+#define SEL_WRITEFDS   m8_p2
+#define SEL_ERRORFDS   m8_p3
+#define SEL_TIMEOUT    m8_p4
+
+/*===========================================================================*
+ *                Messages for the Reincarnation Server 		     *
+ *===========================================================================*/
+
+#define RS_RQ_BASE		0x700
+
+#define RS_UP		(RS_RQ_BASE + 0)	/* start system service */
+#define RS_DOWN		(RS_RQ_BASE + 1)	/* stop system service */
+#define RS_REFRESH	(RS_RQ_BASE + 2)	/* restart system service */
+#define RS_RESCUE	(RS_RQ_BASE + 3)	/* set rescue directory */
+#define RS_SHUTDOWN	(RS_RQ_BASE + 4)	/* alert about shutdown */
+
+#  define RS_CMD_ADDR		m1_p1		/* command string */
+#  define RS_CMD_LEN		m1_i1		/* length of command */
+#  define RS_PID		m1_i1		/* pid of system service */
+#  define RS_PERIOD 	        m1_i2		/* heartbeat period */
+#  define RS_DEV_MAJOR          m1_i3           /* major device number */
+
+/*===========================================================================*
+ *                Messages for the Data Store Server			     *
+ *===========================================================================*/
+
+#define DS_RQ_BASE		0x800
+
+#define DS_PUBLISH	(DS_RQ_BASE + 0)	/* publish information */
+#define DS_RETRIEVE	(DS_RQ_BASE + 1)	/* retrieve information */
+#define DS_SUBSCRIBE	(DS_RQ_BASE + 2)	/* subscribe to information */
+
+#  define DS_KEY		m2_i1		/* key for the information */
+#  define DS_FLAGS		m2_i2		/* flags provided by caller */
+#  define DS_AUTH		m2_p1		/* authorization of caller */
+#  define DS_VAL_L1		m2_l1		/* first long data value */
+#  define DS_VAL_L2		m2_l2		/* second long data value */
+
+/*===========================================================================*
+ *                Miscellaneous messages used by TTY			     *
+ *===========================================================================*/
+
+/* Miscellaneous request types and field names, e.g. used by IS server. */
+#define FKEY_CONTROL 		98  	/* control a function key at the TTY */
+#  define FKEY_REQUEST	     m2_i1	/* request to perform at TTY */
+#  define    FKEY_MAP		10	/* observe function key */
+#  define    FKEY_UNMAP		11	/* stop observing function key */
+#  define    FKEY_EVENTS	12	/* request open key presses */
+#  define FKEY_FKEYS	      m2_l1	/* F1-F12 keys pressed */
+#  define FKEY_SFKEYS	      m2_l2	/* Shift-F1-F12 keys pressed */
+#define DIAGNOSTICS 	100 	/* output a string without FS in between */
+#  define DIAG_PRINT_BUF      m1_p1
+#  define DIAG_BUF_COUNT      m1_i1
+#  define DIAG_ENDPT          m1_i2
+#define GET_KMESS	101	/* get kmess from TTY */
+#  define GETKM_PTR	      m1_p1
+
+
+#endif /* _MINIX_COM_H */ 
Index: /trunk/minix/include/minix/config.h
===================================================================
--- /trunk/minix/include/minix/config.h	(revision 9)
+++ /trunk/minix/include/minix/config.h	(revision 9)
@@ -0,0 +1,131 @@
+#ifndef _CONFIG_H
+#define _CONFIG_H
+
+/* Minix release and version numbers. */
+#define OS_RELEASE "3"
+#define OS_VERSION "1.2a"
+
+/* This file sets configuration parameters for the MINIX kernel, FS, and PM.
+ * It is divided up into two main sections.  The first section contains
+ * user-settable parameters.  In the second section, various internal system
+ * parameters are set based on the user-settable parameters.
+ *
+ * Parts of config.h have been moved to sys_config.h, which can be included
+ * by other include files that wish to get at the configuration data, but
+ * don't want to pollute the users namespace. Some editable values have
+ * gone there.
+ *
+ */
+
+/* The MACHINE (called _MINIX_MACHINE) setting can be done
+ * in <minix/machine.h>.
+ */
+#include <minix/sys_config.h>
+
+#define MACHINE      _MINIX_MACHINE
+
+#define IBM_PC       _MACHINE_IBM_PC
+#define SUN_4        _MACHINE_SUN_4
+#define SUN_4_60     _MACHINE_SUN_4_60
+#define ATARI        _MACHINE_ATARI
+#define MACINTOSH    _MACHINE_MACINTOSH
+
+/* Number of slots in the process table for non-kernel processes. The number
+ * of system processes defines how many processes with special privileges 
+ * there can be. User processes share the same properties and count for one. 
+ *
+ * These can be changed in sys_config.h.
+ */
+#define NR_PROCS 	  _NR_PROCS 
+#define NR_SYS_PROCS      _NR_SYS_PROCS
+
+#if _MINIX_SMALL
+
+#define NR_BUFS	100
+#define NR_BUF_HASH 128
+
+#else
+
+/* The buffer cache should be made as large as you can afford. */
+#if (MACHINE == IBM_PC && _WORD_SIZE == 2)
+#define NR_BUFS           40	/* # blocks in the buffer cache */
+#define NR_BUF_HASH       64	/* size of buf hash table; MUST BE POWER OF 2*/
+#endif
+
+#if (MACHINE == IBM_PC && _WORD_SIZE == 4)
+#define NR_BUFS         1200	/* # blocks in the buffer cache */
+#define NR_BUF_HASH     2048	/* size of buf hash table; MUST BE POWER OF 2*/
+#endif
+
+#if (MACHINE == SUN_4_60)
+#define NR_BUFS		 512	/* # blocks in the buffer cache (<=1536) */
+#define NR_BUF_HASH	 512	/* size of buf hash table; MUST BE POWER OF 2*/
+#endif
+
+#endif	/* _MINIX_SMALL */
+
+/* Number of controller tasks (/dev/cN device classes). */
+#define NR_CTRLRS          2
+
+/* Enable or disable the second level file system cache on the RAM disk. */
+#define ENABLE_CACHE2      0
+
+/* Enable or disable swapping processes to disk. */
+#define ENABLE_SWAP	   1
+
+/* Include or exclude an image of /dev/boot in the boot image. 
+ * Please update the makefile in /usr/src/tools/ as well.
+ */
+#define ENABLE_BOOTDEV	   0	/* load image of /dev/boot at boot time */
+
+/* DMA_SECTORS may be increased to speed up DMA based drivers. */
+#define DMA_SECTORS        1	/* DMA buffer size (must be >= 1) */
+
+/* Include or exclude backwards compatibility code. */
+#define ENABLE_BINCOMPAT   0	/* for binaries using obsolete calls */
+#define ENABLE_SRCCOMPAT   0	/* for sources using obsolete calls */
+
+/* Which processes should receive diagnostics from the kernel and system? 
+ * Directly sending it to TTY only displays the output. Sending it to the
+ * log driver will cause the diagnostics to be buffered and displayed.
+ * Messages are sent by src/lib/sysutil/kputc.c to these processes, in
+ * the order of this array, which must be terminated by NONE. This is used
+ * by drivers and servers that printf().
+ * The kernel does this for its own kprintf() in kernel/utility.c, also using
+ * this array, but a slightly different mechanism.
+ */
+#define OUTPUT_PROCS_ARRAY	{ TTY_PROC_NR, LOG_PROC_NR, NONE }
+
+/* NR_CONS, NR_RS_LINES, and NR_PTYS determine the number of terminals the
+ * system can handle.
+ */
+#define NR_CONS            4	/* # system consoles (1 to 8) */
+#define	NR_RS_LINES	   4	/* # rs232 terminals (0 to 4) */
+#define	NR_PTYS		   32	/* # pseudo terminals (0 to 64) */
+
+/*===========================================================================*
+ *	There are no user-settable parameters after this line		     *
+ *===========================================================================*/
+/* Set the CHIP type based on the machine selected. The symbol CHIP is actually
+ * indicative of more than just the CPU.  For example, machines for which
+ * CHIP == INTEL are expected to have 8259A interrrupt controllers and the
+ * other properties of IBM PC/XT/AT/386 types machines in general. */
+#define INTEL             _CHIP_INTEL	/* CHIP type for PC, XT, AT, 386 and clones */
+#define M68000            _CHIP_M68000	/* CHIP type for Atari, Amiga, Macintosh    */
+#define SPARC             _CHIP_SPARC	/* CHIP type for SUN-4 (e.g. SPARCstation)  */
+
+/* Set the FP_FORMAT type based on the machine selected, either hw or sw    */
+#define FP_NONE	 _FP_NONE	/* no floating point support                */
+#define FP_IEEE	 _FP_IEEE	/* conform IEEE floating point standard     */
+
+/* _MINIX_CHIP is defined in sys_config.h. */
+#define CHIP	_MINIX_CHIP
+
+/* _MINIX_FP_FORMAT is defined in sys_config.h. */
+#define FP_FORMAT	_MINIX_FP_FORMAT
+
+/* _ASKDEV and _FASTLOAD are defined in sys_config.h. */
+#define ASKDEV _ASKDEV
+#define FASTLOAD _FASTLOAD
+
+#endif /* _CONFIG_H */
Index: /trunk/minix/include/minix/const.h
===================================================================
--- /trunk/minix/include/minix/const.h	(revision 9)
+++ /trunk/minix/include/minix/const.h	(revision 9)
@@ -0,0 +1,118 @@
+
+#ifndef CHIP
+#error CHIP is not defined
+#endif
+
+#define EXTERN        extern	/* used in *.h files */
+#define PRIVATE       static	/* PRIVATE x limits the scope of x */
+#define PUBLIC			/* PUBLIC is the opposite of PRIVATE */
+#define FORWARD       static	/* some compilers require this to be 'static'*/
+
+#define TRUE               1	/* used for turning integers into Booleans */
+#define FALSE              0	/* used for turning integers into Booleans */
+
+#define HZ	          60	/* clock freq (software settable on IBM-PC) */
+
+#define SUPER_USER (uid_t) 0	/* uid_t of superuser */
+
+#define NULL     ((void *)0)	/* null pointer */
+#define CPVEC_NR          16	/* max # of entries in a SYS_VCOPY request */
+#define CPVVEC_NR         64	/* max # of entries in a SYS_VCOPY request */
+#define NR_IOREQS	MIN(NR_BUFS, 64)
+				/* maximum number of entries in an iorequest */
+
+/* Message passing constants. */
+#define MESS_SIZE (sizeof(message))	/* might need usizeof from FS here */
+#define NIL_MESS ((message *) 0)	/* null pointer */
+
+/* Memory related constants. */
+#define SEGMENT_TYPE  0xFF00	/* bit mask to get segment type */
+#define SEGMENT_INDEX 0x00FF	/* bit mask to get segment index */
+
+#define LOCAL_SEG     0x0000	/* flags indicating local memory segment */
+#define NR_LOCAL_SEGS      3	/* # local segments per process (fixed) */
+#define T                  0	/* proc[i].mem_map[T] is for text */
+#define D                  1	/* proc[i].mem_map[D] is for data */
+#define S                  2	/* proc[i].mem_map[S] is for stack */
+
+#define REMOTE_SEG    0x0100	/* flags indicating remote memory segment */
+#define NR_REMOTE_SEGS     3    /* # remote memory regions (variable) */
+
+#define BIOS_SEG      0x0200	/* flags indicating BIOS memory segment */
+#define NR_BIOS_SEGS       3    /* # BIOS memory regions (variable) */
+
+#define PHYS_SEG      0x0400	/* flag indicating entire physical memory */
+
+/* Labels used to disable code sections for different reasons. */
+#define DEAD_CODE	   0	/* unused code in normal configuration */
+#define FUTURE_CODE	   0	/* new code to be activated + tested later */
+#define TEMP_CODE	   1	/* active code to be removed later */
+
+/* Process name length in the PM process table, including '\0'. */
+#define PROC_NAME_LEN	16
+
+/* Miscellaneous */
+#define BYTE            0377	/* mask for 8 bits */
+#define READING            0	/* copy data to user */
+#define WRITING            1	/* copy data from user */
+#define NO_NUM        0x8000	/* used as numerical argument to panic() */
+#define NIL_PTR   (char *) 0	/* generally useful expression */
+#define HAVE_SCATTERED_IO  1	/* scattered I/O is now standard */
+
+/* Macros. */
+#define MAX(a, b)   ((a) > (b) ? (a) : (b))
+#define MIN(a, b)   ((a) < (b) ? (a) : (b))
+
+/* Memory is allocated in clicks. */
+#if (CHIP == INTEL)
+#define CLICK_SIZE      4096	/* unit in which memory is allocated */
+#define CLICK_SHIFT       12	/* log2 of CLICK_SIZE */
+#endif
+
+#if (CHIP == SPARC) || (CHIP == M68000)
+#define CLICK_SIZE	4096	/* unit in which memory is allocated */
+#define CLICK_SHIFT	  12	/* log2 of CLICK_SIZE */
+#endif
+
+/* Click to byte conversions (and vice versa). */
+#define HCLICK_SHIFT       4	/* log2 of HCLICK_SIZE */
+#define HCLICK_SIZE       16	/* hardware segment conversion magic */
+#if CLICK_SIZE >= HCLICK_SIZE
+#define click_to_hclick(n) ((n) << (CLICK_SHIFT - HCLICK_SHIFT))
+#else
+#define click_to_hclick(n) ((n) >> (HCLICK_SHIFT - CLICK_SHIFT))
+#endif
+#define hclick_to_physb(n) ((phys_bytes) (n) << HCLICK_SHIFT)
+#define physb_to_hclick(n) ((n) >> HCLICK_SHIFT)
+
+#define ABS             -999	/* this process means absolute memory */
+
+/* Flag bits for i_mode in the inode. */
+#define I_TYPE          0170000	/* this field gives inode type */
+#define I_SYMBOLIC_LINK 0120000	/* file is a symbolic link */
+#define I_REGULAR       0100000	/* regular file, not dir or special */
+#define I_BLOCK_SPECIAL 0060000	/* block special file */
+#define I_DIRECTORY     0040000	/* file is a directory */
+#define I_CHAR_SPECIAL  0020000	/* character special file */
+#define I_NAMED_PIPE	0010000 /* named pipe (FIFO) */
+#define I_SET_UID_BIT   0004000	/* set effective uid_t on exec */
+#define I_SET_GID_BIT   0002000	/* set effective gid_t on exec */
+#define ALL_MODES       0006777	/* all bits for user, group and others */
+#define RWX_MODES       0000777	/* mode bits for RWX only */
+#define R_BIT           0000004	/* Rwx protection bit */
+#define W_BIT           0000002	/* rWx protection bit */
+#define X_BIT           0000001	/* rwX protection bit */
+#define I_NOT_ALLOC     0000000	/* this inode is free */
+
+/* Some limits. */
+#define MAX_BLOCK_NR  ((block_t) 077777777)	/* largest block number */
+#define HIGHEST_ZONE   ((zone_t) 077777777)	/* largest zone number */
+#define MAX_INODE_NR ((ino_t) 037777777777)	/* largest inode number */
+#define MAX_FILE_POS ((off_t) 037777777777)	/* largest legal file offset */
+
+#define MAX_SYM_LOOPS	8	/* how many symbolic links are recursed */
+
+#define NO_BLOCK              ((block_t) 0)	/* absence of a block number */
+#define NO_ENTRY                ((ino_t) 0)	/* absence of a dir entry */
+#define NO_ZONE                ((zone_t) 0)	/* absence of a zone number */
+#define NO_DEV                  ((dev_t) 0)	/* absence of a device numb */
Index: /trunk/minix/include/minix/devio.h
===================================================================
--- /trunk/minix/include/minix/devio.h	(revision 9)
+++ /trunk/minix/include/minix/devio.h	(revision 9)
@@ -0,0 +1,60 @@
+/* This file provides basic types and some constants for the 
+ * SYS_DEVIO and SYS_VDEVIO system calls, which allow user-level 
+ * processes to perform device I/O. 
+ *
+ * Created: 
+ *	Apr 08, 2004 by Jorrit N. Herder
+ */
+
+#ifndef _DEVIO_H
+#define _DEVIO_H
+
+#include <minix/sys_config.h>     /* needed to include <minix/type.h> */
+#include <sys/types.h>        /* u8_t, u16_t, u32_t needed */
+
+typedef u16_t port_t;
+typedef U16_t Port_t;
+
+/* We have different granularities of port I/O: 8, 16, 32 bits.
+ * Also see <ibm/portio.h>, which has functions for bytes, words,  
+ * and longs. Hence, we need different (port,value)-pair types. 
+ */
+typedef struct { u16_t port;  u8_t value; } pvb_pair_t;
+typedef struct { u16_t port; u16_t value; } pvw_pair_t;
+typedef struct { u16_t port; u32_t value; } pvl_pair_t;
+
+/* Macro shorthand to set (port,value)-pair. */
+#define pv_set(pv, p, v) ((pv).port = (p), (pv).value = (v))
+#define pv_ptr_set(pv_ptr, p, v) ((pv_ptr)->port = (p), (pv_ptr)->value = (v))
+
+#if 0	/* no longer in use !!! */
+/* Define a number of flags to indicate granularity we are using. */
+#define MASK_GRANULARITY 0x000F  /* not in use! does not match flags */
+#define PVB_FLAG 'b'
+#define PVW_FLAG 'w'
+#define PVL_FLAG 'l'
+
+/* Flags indicating whether request wants to do input or output. */
+#define MASK_IN_OR_OUT 0x00F0
+#define DEVIO_INPUT 0x0010
+#define DEVIO_OUTPUT 0x0020
+#endif	/* 0 */
+
+#if 0	/* no longer used !!! */
+/* Define how large the (port,value)-pair buffer in the kernel is. 
+ * This buffer is used to copy the (port,value)-pairs in kernel space.
+ */
+#define PV_BUF_SIZE  64      /* creates char pv_buf[PV_BUF_SIZE] */
+
+/* Note that SYS_VDEVIO sends a pointer to a vector of (port,value)-pairs, 
+ * whereas SYS_DEVIO includes a single (port,value)-pair in the messages.
+ * Calculate maximum number of (port,value)-pairs that can be handled 
+ * in a single SYS_VDEVIO system call with above struct definitions. 
+ */
+#define MAX_PVB_PAIRS ((PV_BUF_SIZE * sizeof(char)) / sizeof(pvb_pair_t))
+#define MAX_PVW_PAIRS ((PV_BUF_SIZE * sizeof(char)) / sizeof(pvw_pair_t))
+#define MAX_PVL_PAIRS ((PV_BUF_SIZE * sizeof(char)) / sizeof(pvl_pair_t))
+#endif /* 0 */
+	
+
+#endif  /* _DEVIO_H */
Index: /trunk/minix/include/minix/dl_eth.h
===================================================================
--- /trunk/minix/include/minix/dl_eth.h	(revision 9)
+++ /trunk/minix/include/minix/dl_eth.h	(revision 9)
@@ -0,0 +1,26 @@
+/* The eth_stat struct is used in a DL_GETSTAT request the the ehw_task. */
+
+#ifndef _ETH_HW_H
+#define _ETH_HW_H
+
+typedef struct eth_stat
+{
+  unsigned long ets_recvErr,	/* # receive errors */
+	ets_sendErr,		/* # send error */
+	ets_OVW,		/* # buffer overwrite warnings */
+	ets_CRCerr,		/* # crc errors of read */
+	ets_frameAll,		/* # frames not alligned (# bits % 8 != 0) */
+	ets_missedP,		/* # packets missed due to slow processing */
+	ets_packetR,		/* # packets received */
+	ets_packetT,		/* # packets transmitted */
+	ets_transDef,		/* # transmission defered (Tx was busy) */
+	ets_collision,		/* # collissions */
+	ets_transAb,		/* # Tx aborted due to excess collisions */
+	ets_carrSense,		/* # carrier sense lost */
+	ets_fifoUnder,		/* # FIFO underruns (processor too busy) */
+	ets_fifoOver,		/* # FIFO overruns (processor too busy) */
+	ets_CDheartbeat,	/* # times unable to transmit collision sig*/
+	ets_OWC;		/* # times out of window collision */
+} eth_stat_t;
+
+#endif /* _ETH_HW_H */
Index: /trunk/minix/include/minix/dmap.h
===================================================================
--- /trunk/minix/include/minix/dmap.h	(revision 9)
+++ /trunk/minix/include/minix/dmap.h	(revision 9)
@@ -0,0 +1,64 @@
+#ifndef _DMAP_H
+#define _DMAP_H
+
+#include <minix/sys_config.h>
+#include <minix/ipc.h>
+
+/*===========================================================================*
+ *               	 Device <-> Driver Table  			     *
+ *===========================================================================*/
+
+/* Device table.  This table is indexed by major device number.  It provides
+ * the link between major device numbers and the routines that process them.
+ * The table can be update dynamically. The field 'dmap_flags' describe an 
+ * entry's current status and determines what control options are possible. 
+ */
+#define DMAP_MUTABLE		0x01	/* mapping can be overtaken */
+#define DMAP_BUSY		0x02	/* driver busy with request */
+#define DMAP_BABY		0x04	/* driver exec() not done yet */
+
+enum dev_style { STYLE_DEV, STYLE_NDEV, STYLE_TTY, STYLE_CLONE };
+
+extern struct dmap {
+  int _PROTOTYPE ((*dmap_opcl), (int, Dev_t, int, int) );
+  int _PROTOTYPE ((*dmap_io), (int, message *) );
+  int dmap_driver;
+  int dmap_flags;
+} dmap[];
+
+/*===========================================================================*
+ *               	 Major and minor device numbers  		     *
+ *===========================================================================*/
+
+/* Total number of different devices. */
+#define NR_DEVICES   		  32			/* number of (major) devices */
+
+/* Major and minor device numbers for MEMORY driver. */
+#define MEMORY_MAJOR  		   1	/* major device for memory devices */
+#  define RAM_DEV     		   0	/* minor device for /dev/ram */
+#  define MEM_DEV     		   1	/* minor device for /dev/mem */
+#  define KMEM_DEV    		   2	/* minor device for /dev/kmem */
+#  define NULL_DEV    		   3	/* minor device for /dev/null */
+#  define BOOT_DEV    		   4	/* minor device for /dev/boot */
+#  define ZERO_DEV    		   5	/* minor device for /dev/zero */
+#  define IMGRD_DEV   		   6	/* minor device for /dev/imgrd */
+
+#define CTRLR(n) ((n)==0 ? 3 : (8 + 2*((n)-1)))	/* magic formula */
+
+/* Full device numbers that are special to the boot monitor and FS. */
+#  define DEV_RAM	      0x0100	/* device number of /dev/ram */
+#  define DEV_BOOT	      0x0104	/* device number of /dev/boot */
+#  define DEV_IMGRD	      0x0106	/* device number of /dev/imgrd */
+
+#define FLOPPY_MAJOR	           2	/* major device for floppy disks */
+#define TTY_MAJOR		   4	/* major device for ttys */
+#define CTTY_MAJOR		   5	/* major device for /dev/tty */
+
+#define INET_MAJOR		   7	/* major device for inet */
+
+#define RESCUE_MAJOR		   9    /* major device for rescue */
+
+#define LOG_MAJOR		  15	/* major device for log driver */
+#  define IS_KLOG_DEV		   0	/* minor device for /dev/klog */
+
+#endif /* _DMAP_H */
Index: /trunk/minix/include/minix/endpoint.h
===================================================================
--- /trunk/minix/include/minix/endpoint.h	(revision 9)
+++ /trunk/minix/include/minix/endpoint.h	(revision 9)
@@ -0,0 +1,26 @@
+
+#ifndef _MINIX_ENDPOINT_H
+#define _MINIX_ENDPOINT_H 1
+
+#include <minix/sys_config.h>
+#include <minix/com.h>
+#include <limits.h>
+
+/* The point of the padding in 'generation size' is to 
+ * allow for certain bogus endpoint numbers such as NONE, ANY, etc.
+ *
+ * The _MAX_MAGIC_PROC is defined by <minix/com.h>. That include
+ * file defines some magic process numbers such as ANY and NONE,
+ * and must never be a valid endpoint number. Therefore we make sure
+ * the generation size is big enough to start the next generation
+ * above the highest magic number.
+ */
+#define _ENDPOINT_GENERATION_SIZE (NR_TASKS+_MAX_MAGIC_PROC+1)
+#define _ENDPOINT_MAX_GENERATION  (INT_MAX/_ENDPOINT_GENERATION_SIZE-1)
+
+/* Generation + Process slot number <-> endpoint. */
+#define _ENDPOINT(g, p) ((g) * _ENDPOINT_GENERATION_SIZE + (p))
+#define _ENDPOINT_G(e) (((e)+NR_TASKS) / _ENDPOINT_GENERATION_SIZE)
+#define _ENDPOINT_P(e) ((((e)+NR_TASKS) % _ENDPOINT_GENERATION_SIZE) - NR_TASKS)
+
+#endif
Index: /trunk/minix/include/minix/fslib.h
===================================================================
--- /trunk/minix/include/minix/fslib.h	(revision 9)
+++ /trunk/minix/include/minix/fslib.h	(revision 9)
@@ -0,0 +1,11 @@
+/* V1 and V2 file system disk to/from memory support functions. */
+
+_PROTOTYPE( int bitmapsize, (bit_t _nr_bits, int block_size)				);
+_PROTOTYPE( unsigned conv2, (int _norm, int _w)				);
+_PROTOTYPE( long conv4, (int _norm, long _x)				);
+_PROTOTYPE( void conv_inode, (struct inode *_rip, d1_inode *_dip,
+			     d2_inode *_dip2, int _rw_flag, int _magic)	);
+_PROTOTYPE( void old_icopy, (struct inode *_rip, d1_inode *_dip,
+					      int _direction, int _norm));
+_PROTOTYPE( void new_icopy, (struct inode *_rip, d2_inode *_dip,
+					      int _direction, int _norm));
Index: /trunk/minix/include/minix/ioctl.h
===================================================================
--- /trunk/minix/include/minix/ioctl.h	(revision 9)
+++ /trunk/minix/include/minix/ioctl.h	(revision 9)
@@ -0,0 +1,44 @@
+/*	minix/ioctl.h - Ioctl helper definitions.	Author: Kees J. Bot
+ *								23 Nov 2002
+ *
+ * This file is included by every header file that defines ioctl codes.
+ */
+
+#ifndef _M_IOCTL_H
+#define _M_IOCTL_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+#if _EM_WSIZE >= 4
+/* Ioctls have the command encoded in the low-order word, and the size
+ * of the parameter in the high-order word. The 3 high bits of the high-
+ * order word are used to encode the in/out/void status of the parameter.
+ */
+#define _IOCPARM_MASK	0x1FFF
+#define _IOC_VOID	0x20000000
+#define _IOCTYPE_MASK	0xFFFF
+#define _IOC_IN		0x40000000
+#define _IOC_OUT	0x80000000
+#define _IOC_INOUT	(_IOC_IN | _IOC_OUT)
+
+#define _IO(x,y)	((x << 8) | y | _IOC_VOID)
+#define _IOR(x,y,t)	((x << 8) | y | ((sizeof(t) & _IOCPARM_MASK) << 16) |\
+				_IOC_OUT)
+#define _IOW(x,y,t)	((x << 8) | y | ((sizeof(t) & _IOCPARM_MASK) << 16) |\
+				_IOC_IN)
+#define _IORW(x,y,t)	((x << 8) | y | ((sizeof(t) & _IOCPARM_MASK) << 16) |\
+				_IOC_INOUT)
+#else
+/* No fancy encoding on a 16-bit machine. */
+
+#define _IO(x,y)	((x << 8) | y)
+#define _IOR(x,y,t)	_IO(x,y)
+#define _IOW(x,y,t)	_IO(x,y)
+#define _IORW(x,y,t)	_IO(x,y)
+#endif
+
+int ioctl(int _fd, int _request, void *_data);
+
+#endif /* _M_IOCTL_H */
Index: /trunk/minix/include/minix/ipc.h
===================================================================
--- /trunk/minix/include/minix/ipc.h	(revision 9)
+++ /trunk/minix/include/minix/ipc.h	(revision 9)
@@ -0,0 +1,111 @@
+#ifndef _IPC_H
+#define _IPC_H
+
+/*==========================================================================* 
+ * Types relating to messages. 						    *
+ *==========================================================================*/ 
+
+#define M1                 1
+#define M3                 3
+#define M4                 4
+#define M3_STRING         14
+
+typedef struct {int m1i1, m1i2, m1i3; char *m1p1, *m1p2, *m1p3;} mess_1;
+typedef struct {int m2i1, m2i2, m2i3; long m2l1, m2l2; char *m2p1;} mess_2;
+typedef struct {int m3i1, m3i2; char *m3p1; char m3ca1[M3_STRING];} mess_3;
+typedef struct {long m4l1, m4l2, m4l3, m4l4, m4l5;} mess_4;
+typedef struct {short m5c1, m5c2; int m5i1, m5i2; long m5l1, m5l2, m5l3;}mess_5;
+typedef struct {int m7i1, m7i2, m7i3, m7i4; char *m7p1, *m7p2;} mess_7;
+typedef struct {int m8i1, m8i2; char *m8p1, *m8p2, *m8p3, *m8p4;} mess_8;
+
+typedef struct {
+  int m_source;			/* who sent the message */
+  int m_type;			/* what kind of message is it */
+  union {
+	mess_1 m_m1;
+	mess_2 m_m2;
+	mess_3 m_m3;
+	mess_4 m_m4;
+	mess_5 m_m5;
+	mess_7 m_m7;
+	mess_8 m_m8;
+  } m_u;
+} message;
+
+/* The following defines provide names for useful members. */
+#define m1_i1  m_u.m_m1.m1i1
+#define m1_i2  m_u.m_m1.m1i2
+#define m1_i3  m_u.m_m1.m1i3
+#define m1_p1  m_u.m_m1.m1p1
+#define m1_p2  m_u.m_m1.m1p2
+#define m1_p3  m_u.m_m1.m1p3
+
+#define m2_i1  m_u.m_m2.m2i1
+#define m2_i2  m_u.m_m2.m2i2
+#define m2_i3  m_u.m_m2.m2i3
+#define m2_l1  m_u.m_m2.m2l1
+#define m2_l2  m_u.m_m2.m2l2
+#define m2_p1  m_u.m_m2.m2p1
+
+#define m3_i1  m_u.m_m3.m3i1
+#define m3_i2  m_u.m_m3.m3i2
+#define m3_p1  m_u.m_m3.m3p1
+#define m3_ca1 m_u.m_m3.m3ca1
+
+#define m4_l1  m_u.m_m4.m4l1
+#define m4_l2  m_u.m_m4.m4l2
+#define m4_l3  m_u.m_m4.m4l3
+#define m4_l4  m_u.m_m4.m4l4
+#define m4_l5  m_u.m_m4.m4l5
+
+#define m5_c1  m_u.m_m5.m5c1
+#define m5_c2  m_u.m_m5.m5c2
+#define m5_i1  m_u.m_m5.m5i1
+#define m5_i2  m_u.m_m5.m5i2
+#define m5_l1  m_u.m_m5.m5l1
+#define m5_l2  m_u.m_m5.m5l2
+#define m5_l3  m_u.m_m5.m5l3
+
+#define m7_i1  m_u.m_m7.m7i1
+#define m7_i2  m_u.m_m7.m7i2
+#define m7_i3  m_u.m_m7.m7i3
+#define m7_i4  m_u.m_m7.m7i4
+#define m7_p1  m_u.m_m7.m7p1
+#define m7_p2  m_u.m_m7.m7p2
+
+#define m8_i1  m_u.m_m8.m8i1
+#define m8_i2  m_u.m_m8.m8i2
+#define m8_p1  m_u.m_m8.m8p1
+#define m8_p2  m_u.m_m8.m8p2
+#define m8_p3  m_u.m_m8.m8p3
+#define m8_p4  m_u.m_m8.m8p4
+
+/*==========================================================================* 
+ * Minix run-time system (IPC). 					    *
+ *==========================================================================*/ 
+
+/* Hide names to avoid name space pollution. */
+#define echo		_echo
+#define notify		_notify
+#define sendrec		_sendrec
+#define receive		_receive
+#define send		_send
+
+_PROTOTYPE( int echo, (message *m_ptr)					);
+_PROTOTYPE( int notify, (int dest)					);
+_PROTOTYPE( int sendrec, (int src_dest, message *m_ptr)			);
+_PROTOTYPE( int receive, (int src, message *m_ptr)			);
+_PROTOTYPE( int send, (int dest, message *m_ptr)			);
+
+#define ipc_request	_ipc_request
+#define ipc_reply	_ipc_reply
+#define ipc_notify	_ipc_notify
+#define ipc_select	_ipc_select
+
+_PROTOTYPE( int ipc_request, (int dst, message *m_ptr)			);
+_PROTOTYPE( int ipc_reply, (int dst, message *m_ptr)			);
+_PROTOTYPE( int ipc_notify, (int dst, long event_set)			);
+_PROTOTYPE( int ipc_receive, (int src, long events, message *m_ptr)	);
+
+
+#endif /* _IPC_H */
Index: /trunk/minix/include/minix/jmp_buf.h
===================================================================
--- /trunk/minix/include/minix/jmp_buf.h	(revision 9)
+++ /trunk/minix/include/minix/jmp_buf.h	(revision 9)
@@ -0,0 +1,87 @@
+/* This file is intended for use by assembly language programs that
+ * need to manipulate a jmp_buf.  It may only be used by those systems
+ * for which a jmp_buf is identical to a struct sigcontext.
+ */
+
+#ifndef _JMP_BUF_H
+#define _JMP_BUF_H
+
+#if !defined(CHIP)
+#include "error, configuration is not known"
+#endif
+
+#if (CHIP == INTEL)
+#if _WORD_SIZE == 4
+#define JB_FLAGS	 0
+#define JB_MASK		 4
+#define JB_GS		 8
+#define JB_FS		10
+#define JB_ES		12
+#define JB_DS		14
+#define JB_DI		16
+#define JB_SI		20
+#define JB_BP		24
+#define JB_ST		28
+#define JB_BX		32
+#define JB_DX		36
+#define JB_CX		40
+#define JB_AX		44
+#define JB_RETADR	48
+#define JB_IP		52
+#define JB_CS		56
+#define JB_PSW		60
+#define JB_SP		64
+#define JB_SS		68
+#else /* _WORD_SIZE == 2 */
+#define JB_FLAGS	 0
+#define JB_MASK		 2
+#define JB_ES		 6
+#define JB_DS		 8 
+#define JB_DI		10
+#define JB_SI		12
+#define JB_BP		14
+#define JB_ST		16
+#define JB_BX		18
+#define JB_DX		20
+#define JB_CX		22
+#define JB_AX		24
+#define JB_RETADR	26
+#define JB_IP		28
+#define JB_CS		30
+#define JB_PSW		32
+#define JB_SP		34
+#define JB_SS		36
+#endif /* _WORD_SIZE == 2 */
+#else /* !(CHIP == INTEL) */
+#if (CHIP == M68000)
+#define JB_FLAGS	 0
+#define JB_MASK		 2
+#define JB_RETREG	 6
+#define JB_D1		10
+#define JB_D2		14
+#define JB_D3		18
+#define JB_D4		22
+#define JB_D5		26
+#define JB_D6		20
+#define JB_D7		34
+#define JB_A0		38
+#define JB_A1		42
+#define JB_A2		46
+#define JB_A3		50
+#define JB_A4		54
+#define JB_A5		58
+#define JB_A6		62
+#define JB_SP		66
+#define JB_PC		70
+#define JB_PSW		74
+#else /* !(CHIP == INTEL) && !(CHIP == M68000) */
+#include "error, CHIP is not supported"
+#endif /* (CHIP == INTEL) */
+
+/* Defines from C headers needed in assembly code.  The headers have too
+ * much C stuff to used directly.
+ */
+#define SIG_BLOCK	0	/* must agree with <signal.h> */
+#define SC_SIGCONTEXT	2	/* must agree with <sys/sigcontext.h> */
+#define SC_NOREGLOCALS	4	/* must agree with <sys/sigcontext.h> */
+#endif /* _JMP_BUF_H */
Index: /trunk/minix/include/minix/keymap.h
===================================================================
--- /trunk/minix/include/minix/keymap.h	(revision 9)
+++ /trunk/minix/include/minix/keymap.h	(revision 9)
@@ -0,0 +1,146 @@
+/*	keymap.h - defines for keymapping		Author: Marcus Hampel
+ */
+#ifndef _SYS__KEYMAP_H
+#define _SYS__KEYMAP_H
+
+#define	C(c)	((c) & 0x1F)	/* Map to control code		*/
+#define A(c)	((c) | 0x80)	/* Set eight bit (ALT)		*/
+#define CA(c)	A(C(c))		/* Control-Alt			*/
+#define	L(c)	((c) | HASCAPS)	/* Add "Caps Lock has effect" attribute */
+
+#define EXT	0x0100		/* Normal function keys		*/
+#define CTRL	0x0200		/* Control key			*/
+#define SHIFT	0x0400		/* Shift key			*/
+#define ALT	0x0800		/* Alternate key		*/
+#define EXTKEY	0x1000		/* extended keycode		*/
+#define HASCAPS	0x8000		/* Caps Lock has effect		*/
+
+/* Scan code conversion. */
+#define KEY_RELEASE 	0200
+#define ASCII_MASK	0177
+
+/* Numeric keypad */
+#define HOME	(0x01 + EXT)
+#define END	(0x02 + EXT)
+#define UP	(0x03 + EXT)
+#define DOWN	(0x04 + EXT)
+#define LEFT	(0x05 + EXT)
+#define RIGHT	(0x06 + EXT)
+#define PGUP	(0x07 + EXT)
+#define PGDN	(0x08 + EXT)
+#define MID	(0x09 + EXT)
+#define NMIN	(0x0A + EXT)
+#define PLUS	(0x0B + EXT)
+#define INSRT	(0x0C + EXT)
+
+/* Alt + Numeric keypad */
+#define AHOME	(0x01 + ALT)
+#define AEND	(0x02 + ALT)
+#define AUP	(0x03 + ALT)
+#define ADOWN	(0x04 + ALT)
+#define ALEFT	(0x05 + ALT)
+#define ARIGHT	(0x06 + ALT)
+#define APGUP	(0x07 + ALT)
+#define APGDN	(0x08 + ALT)
+#define AMID	(0x09 + ALT)
+#define ANMIN	(0x0A + ALT)
+#define APLUS	(0x0B + ALT)
+#define AINSRT	(0x0C + ALT)
+
+/* Ctrl + Numeric keypad */
+#define CHOME	(0x01 + CTRL)
+#define CEND	(0x02 + CTRL)
+#define CUP	(0x03 + CTRL)
+#define CDOWN	(0x04 + CTRL)
+#define CLEFT	(0x05 + CTRL)
+#define CRIGHT	(0x06 + CTRL)
+#define CPGUP	(0x07 + CTRL)
+#define CPGDN	(0x08 + CTRL)
+#define CMID	(0x09 + CTRL)
+#define CNMIN	(0x0A + CTRL)
+#define CPLUS	(0x0B + CTRL)
+#define CINSRT	(0x0C + CTRL)
+
+/* Lock keys */
+#define CALOCK	(0x0D + EXT)	/* caps lock	*/
+#define	NLOCK	(0x0E + EXT)	/* number lock	*/
+#define SLOCK	(0x0F + EXT)	/* scroll lock	*/
+
+/* Function keys */
+#define F1	(0x10 + EXT)
+#define F2	(0x11 + EXT)
+#define F3	(0x12 + EXT)
+#define F4	(0x13 + EXT)
+#define F5	(0x14 + EXT)
+#define F6	(0x15 + EXT)
+#define F7	(0x16 + EXT)
+#define F8	(0x17 + EXT)
+#define F9	(0x18 + EXT)
+#define F10	(0x19 + EXT)
+#define F11	(0x1A + EXT)
+#define F12	(0x1B + EXT)
+
+/* Alt+Fn */
+#define AF1	(0x10 + ALT)
+#define AF2	(0x11 + ALT)
+#define AF3	(0x12 + ALT)
+#define AF4	(0x13 + ALT)
+#define AF5	(0x14 + ALT)
+#define AF6	(0x15 + ALT)
+#define AF7	(0x16 + ALT)
+#define AF8	(0x17 + ALT)
+#define AF9	(0x18 + ALT)
+#define AF10	(0x19 + ALT)
+#define AF11	(0x1A + ALT)
+#define AF12	(0x1B + ALT)
+
+/* Ctrl+Fn */
+#define CF1	(0x10 + CTRL)
+#define CF2	(0x11 + CTRL)
+#define CF3	(0x12 + CTRL)
+#define CF4	(0x13 + CTRL)
+#define CF5	(0x14 + CTRL)
+#define CF6	(0x15 + CTRL)
+#define CF7	(0x16 + CTRL)
+#define CF8	(0x17 + CTRL)
+#define CF9	(0x18 + CTRL)
+#define CF10	(0x19 + CTRL)
+#define CF11	(0x1A + CTRL)
+#define CF12	(0x1B + CTRL)
+
+/* Shift+Fn */
+#define SF1	(0x10 + SHIFT)
+#define SF2	(0x11 + SHIFT)
+#define SF3	(0x12 + SHIFT)
+#define SF4	(0x13 + SHIFT)
+#define SF5	(0x14 + SHIFT)
+#define SF6	(0x15 + SHIFT)
+#define SF7	(0x16 + SHIFT)
+#define SF8	(0x17 + SHIFT)
+#define SF9	(0x18 + SHIFT)
+#define SF10	(0x19 + SHIFT)
+#define SF11	(0x1A + SHIFT)
+#define SF12	(0x1B + SHIFT)
+
+/* Alt+Shift+Fn */
+#define ASF1	(0x10 + ALT + SHIFT)
+#define ASF2	(0x11 + ALT + SHIFT)
+#define ASF3	(0x12 + ALT + SHIFT)
+#define ASF4	(0x13 + ALT + SHIFT)
+#define ASF5	(0x14 + ALT + SHIFT)
+#define ASF6	(0x15 + ALT + SHIFT)
+#define ASF7	(0x16 + ALT + SHIFT)
+#define ASF8	(0x17 + ALT + SHIFT)
+#define ASF9	(0x18 + ALT + SHIFT)
+#define ASF10	(0x19 + ALT + SHIFT)
+#define ASF11	(0x1A + ALT + SHIFT)
+#define ASF12	(0x1B + ALT + SHIFT)
+
+#define MAP_COLS	6	/* Number of columns in keymap */
+#define NR_SCAN_CODES	0x80	/* Number of scan codes (rows in keymap) */
+
+typedef unsigned short keymap_t[NR_SCAN_CODES * MAP_COLS];
+
+#define KEY_MAGIC	"KMAZ"	/* Magic number of keymap file */
+
+#endif /* _SYS__KEYMAP_H */
Index: /trunk/minix/include/minix/minlib.h
===================================================================
--- /trunk/minix/include/minix/minlib.h	(revision 9)
+++ /trunk/minix/include/minix/minlib.h	(revision 9)
@@ -0,0 +1,23 @@
+#ifndef _MINLIB
+#define _MINLIB
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+/* Miscellaneous BSD. */
+_PROTOTYPE(void swab, (char *_from, char *_to, int _count));
+_PROTOTYPE(char *itoa, (int _n));
+_PROTOTYPE(char *getpass, (const char *_prompt));
+
+/* Miscellaneous MINIX. */
+_PROTOTYPE(void std_err, (char *_s));
+_PROTOTYPE(void prints, (const char *_s, ...));
+_PROTOTYPE(int fsversion, (char *_dev, char *_prog));
+_PROTOTYPE(int getprocessor, (void));
+_PROTOTYPE(int load_mtab, (char *_prog_name));
+_PROTOTYPE(int rewrite_mtab, (char *_prog_name));
+_PROTOTYPE(int get_mtab_entry, (char *_s1, char *_s2, char *_s3, char *_s4));
+_PROTOTYPE(int put_mtab_entry, (char *_s1, char *_s2, char *_s3, char *_s4));
+
+#endif
Index: /trunk/minix/include/minix/partition.h
===================================================================
--- /trunk/minix/include/minix/partition.h	(revision 9)
+++ /trunk/minix/include/minix/partition.h	(revision 9)
@@ -0,0 +1,21 @@
+/*	minix/partition.h				Author: Kees J. Bot
+ *								7 Dec 1995
+ * Place of a partition on disk and the disk geometry,
+ * for use with the DIOCGETP and DIOCSETP ioctl's.
+ */
+#ifndef _MINIX__PARTITION_H
+#define _MINIX__PARTITION_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+struct partition {
+  u64_t base;		/* byte offset to the partition start */
+  u64_t size;		/* number of bytes in the partition */
+  unsigned cylinders;	/* disk geometry */
+  unsigned heads;
+  unsigned sectors;
+};
+
+#endif /* _MINIX__PARTITION_H */
Index: /trunk/minix/include/minix/paths.h
===================================================================
--- /trunk/minix/include/minix/paths.h	(revision 9)
+++ /trunk/minix/include/minix/paths.h	(revision 9)
@@ -0,0 +1,21 @@
+#ifndef _MINIX_PATHS_H
+#define _MINIX_PATHS_H 1
+
+#define _PATH_DHCPCONF	"/etc/dhcp.conf"
+#define _PATH_DHCPPID	"/usr/run/dhcpd.pid"
+#define _PATH_DHCPCACHE	"/usr/adm/dhcp.cache"
+#define _PATH_DHCPPOOL	"/usr/adm/dhcp.pool"
+
+#define _PATH_WTMP	"/usr/adm/wtmp"
+#define _PATH_UTMP	"/etc/utmp"
+#define _PATH_LASTLOG	"/usr/adm/lastlog"
+#define _PATH_MOTD	"/etc/motd"
+#define _PATH_HOSTS	"/etc/hosts"
+
+#define    _PATH_DEFTAPE   "/dev/sa0"
+#define    _PATH_RAMDISK   "/dev/ram"
+#define    _PATH_TMP       "/tmp"
+
+#define _PATH_BSHELL	"/bin/sh"
+
+#endif
Index: /trunk/minix/include/minix/queryparam.h
===================================================================
--- /trunk/minix/include/minix/queryparam.h	(revision 9)
+++ /trunk/minix/include/minix/queryparam.h	(revision 9)
@@ -0,0 +1,45 @@
+/*	queryparam.h - query program parameters		Author: Kees J. Bot
+ *								22 Apr 1994
+ */
+#ifndef _MINIX__QUERYPARAM_H
+#define _MINIX__QUERYPARAM_H
+
+#include <ansi.h>
+
+typedef size_t _mnx_size_t;
+
+struct export_param_list {
+	char	*name;		/* "variable", "[", ".field", or NULL. */
+	void	*offset;	/* Address of a variable or field offset. */
+	size_t	size;		/* Size of the resulting object. */
+};
+
+struct export_params {
+	struct export_param_list *list;	/* List of exported parameters. */
+	struct export_params	 *next;	/* Link several sets of parameters. */
+};
+
+#ifdef __STDC__
+#define qp_stringize(var)	#var
+#define qp_dotstringize(var)	"." #var
+#else
+#define qp_stringize(var)	"var"
+#define qp_dotstringize(var)	".var"
+#endif
+#define QP_VARIABLE(var)	{ qp_stringize(var), &(var), sizeof(var) }
+#define QP_ARRAY(var)		{ "[", 0, sizeof((var)[0]) }
+#define QP_VECTOR(var,ptr,len)	{ qp_stringize(var), &(ptr), -1 },\
+				{ "[", &(len), sizeof(*(ptr)) }
+#define QP_FIELD(field, type)	{ qp_dotstringize(field), \
+					(void *)offsetof(type, field), \
+					sizeof(((type *)0)->field) }
+#define QP_END()		{ 0, 0, 0 }
+
+void qp_export _ARGS((struct export_params *_ex_params));
+int queryparam _ARGS((int (*_qgetc) _ARGS((void)), void **_paddress,
+							_mnx_size_t *_psize));
+_mnx_size_t paramvalue _ARGS((char **_value, void *_address,
+							_mnx_size_t _size));
+#endif /* _MINIX__QUERYPARAM_H */
+
+/* $PchId: queryparam.h,v 1.1 2005/06/28 14:31:26 philip Exp $ */
Index: /trunk/minix/include/minix/sound.h
===================================================================
--- /trunk/minix/include/minix/sound.h	(revision 9)
+++ /trunk/minix/include/minix/sound.h	(revision 9)
@@ -0,0 +1,45 @@
+/* Definitions used by /dev/audio and /dev/mixer.
+ *
+ *  Feb 13 1995			Author: Michel R. Prevenier 
+ */
+
+#ifndef SOUND_H
+#define SOUND_H
+
+/* ------- Mixer stuff ------- */
+
+/* Available devices */
+enum Device
+{
+  Master,     /* Master volume */
+  Dac,        /* DSP, digitized sound */
+  Fm,         /* Fm synthesized sound */
+  Cd,         /* Compact */
+  Line,       /* Line in */
+  Mic,        /* Microphone */
+  Speaker,    /* Pc speaker */
+  Treble,     /* Treble */
+  Bass        /* Bass */
+};
+
+enum InputState
+{
+  ON, OFF
+};
+
+/* Volume levels range from 0 to 31, bass & treble range from 0 to 15 */
+struct volume_level
+{
+  enum Device	device; 
+  int 	 	left;   	
+  int 	 	right;
+};
+
+struct inout_ctrl
+{
+  enum Device   	device;
+  enum InputState 	left;
+  enum InputState 	right;
+};
+
+#endif /* SOUND_H */
Index: /trunk/minix/include/minix/swap.h
===================================================================
--- /trunk/minix/include/minix/swap.h	(revision 9)
+++ /trunk/minix/include/minix/swap.h	(revision 9)
@@ -0,0 +1,48 @@
+/*
+minix/swap.h
+
+Defines the super block of swap partitions and some useful constants.
+
+Created:	Aug 2, 1992 by Philip Homburg
+*/
+
+#ifndef _MINIX__SWAP_H
+#define _MINIX__SWAP_H
+
+/* Two possible layouts for a partition with swapspace:
+ *
+ *	Sector		Swap partition		FS+swap partition
+ *
+ *       0 - 1		bootblock		bootblock
+ *	     2		swap header		FS header
+ *	     3		blank			swap header
+ *	 4 - m		swapspace		file system
+ *	m+1 - n		-			swapspace
+ */
+ 
+#define SWAP_MAGIC0	0x9D
+#define SWAP_MAGIC1	0xC3
+#define SWAP_MAGIC2	0x01
+#define SWAP_MAGIC3	0x82
+
+typedef struct swap_hdr
+{
+	u8_t sh_magic[4];
+	u8_t sh_version;
+	u8_t sh_dummy[3];
+	u32_t sh_offset;
+	u32_t sh_swapsize;
+	i32_t sh_priority;
+} swap_hdr_t;
+
+#define SWAP_BOOTOFF	 1024
+#define SWAP_OFFSET	 2048
+#define OPTSWAP_BOOTOFF	(1024+512)
+#define SH_VERSION	    1
+#define SH_PRIORITY	    0
+
+#endif /* _MINIX__SWAP_H */
+
+/*
+ * $PchId: swap.h,v 1.6 1996/04/10 20:25:48 philip Exp $
+ */
Index: /trunk/minix/include/minix/sys_config.h
===================================================================
--- /trunk/minix/include/minix/sys_config.h	(revision 9)
+++ /trunk/minix/include/minix/sys_config.h	(revision 9)
@@ -0,0 +1,74 @@
+#ifndef _MINIX_SYS_CONFIG_H
+#define _MINIX_SYS_CONFIG_H 1
+
+/*===========================================================================*
+ *		This section contains user-settable parameters		     *
+ *===========================================================================*/
+#define _MINIX_MACHINE       _MACHINE_IBM_PC
+
+#define _MACHINE_IBM_PC             1	/* any  8088 or 80x86-based system */
+#define _MACHINE_SUN_4             40	/* any Sun SPARC-based system */
+#define _MACHINE_SUN_4_60	   40	/* Sun-4/60 (aka SparcStation 1 or Campus) */
+#define _MACHINE_ATARI             60	/* ATARI ST/STe/TT (68000/68030) */
+#define _MACHINE_MACINTOSH         62	/* Apple Macintosh (68000) */
+
+/* Word size in bytes (a constant equal to sizeof(int)). */
+#if __ACK__ || __GNUC__
+#define _WORD_SIZE	_EM_WSIZE
+#define _PTR_SIZE	_EM_WSIZE
+#endif
+
+#define _NR_PROCS	100
+#define _NR_SYS_PROCS	32
+#define _NR_HOLES (2*_NR_PROCS+4)  /* No. of memory holes maintained by PM */
+
+/* Set the CHIP type based on the machine selected. The symbol CHIP is actually
+ * indicative of more than just the CPU.  For example, machines for which
+ * CHIP == INTEL are expected to have 8259A interrrupt controllers and the
+ * other properties of IBM PC/XT/AT/386 types machines in general. */
+#define _CHIP_INTEL             1	/* CHIP type for PC, XT, AT, 386 and clones */
+#define _CHIP_M68000            2	/* CHIP type for Atari, Amiga, Macintosh    */
+#define _CHIP_SPARC             3	/* CHIP type for SUN-4 (e.g. SPARCstation)  */
+
+/* Set the FP_FORMAT type based on the machine selected, either hw or sw    */
+#define _FP_NONE		  0	/* no floating point support                */
+#define _FP_IEEE		  1	/* conform IEEE floating point standard     */
+
+#if (_MINIX_MACHINE == _MACHINE_IBM_PC)
+#define _MINIX_CHIP          _CHIP_INTEL
+#endif
+
+#if (_MINIX_MACHINE == _MACHINE_ATARI) || (_MINIX_MACHINE == _MACHINE_MACINTOSH)
+#define _MINIX_CHIP         _CHIP_M68000
+#endif
+
+#if (_MINIX_MACHINE == _MACHINE_SUN_4) || (_MINIX_MACHINE == _MACHINE_SUN_4_60)
+#define _MINIX_CHIP          _CHIP_SPARC
+#define _MINIX_FP_FORMAT   _FP_IEEE
+#endif
+
+#if (_MINIX_MACHINE == _MACHINE_ATARI) || (_MINIX_MACHINE == _MACHINE_SUN_4)
+#define _ASKDEV            1	/* ask for boot device */
+#define _FASTLOAD          1	/* use multiple block transfers to init ram */
+#endif
+
+#ifndef _MINIX_FP_FORMAT
+#define _MINIX_FP_FORMAT   _FP_NONE
+#endif
+
+#ifndef _MINIX_MACHINE
+error "In <minix/sys_config.h> please define _MINIX_MACHINE"
+#endif
+
+#ifndef _MINIX_CHIP
+error "In <minix/sys_config.h> please define _MINIX_MACHINE to have a legal value"
+#endif
+
+#if (_MINIX_MACHINE == 0)
+error "_MINIX_MACHINE has incorrect value (0)"
+#endif
+
+/* Kernel debug checks */
+#define DEBUG_LOCK_CHECK 0	/* Interrupt Lock/unlock sanity checking. */
+
+#endif /* _MINIX_SYS_CONFIG_H */
Index: /trunk/minix/include/minix/syslib.h
===================================================================
--- /trunk/minix/include/minix/syslib.h	(revision 9)
+++ /trunk/minix/include/minix/syslib.h	(revision 9)
@@ -0,0 +1,176 @@
+/* Prototypes for system library functions. */
+
+#ifndef _SYSLIB_H
+#define _SYSLIB_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifndef _IPC_H
+#include <minix/ipc.h>
+#endif
+
+#ifndef _DEVIO_H
+#include <minix/devio.h>
+#endif
+
+/* Forward declaration */
+struct reg86u;
+
+#define SYSTASK SYSTEM
+
+/*==========================================================================* 
+ * Minix system library. 						    *
+ *==========================================================================*/ 
+_PROTOTYPE( int _taskcall, (int who, int syscallnr, message *msgptr));
+
+_PROTOTYPE( int sys_abort, (int how, ...));
+_PROTOTYPE( int sys_enable_iop, (int proc));
+_PROTOTYPE( int sys_exec, (int proc, char *ptr,  
+				char *aout, vir_bytes initpc));
+_PROTOTYPE( int sys_fork, (int parent, int child, int *));
+_PROTOTYPE( int sys_newmap, (int proc, struct mem_map *ptr));
+_PROTOTYPE( int sys_exit, (int proc));
+_PROTOTYPE( int sys_trace, (int req, int proc, long addr, long *data_p));
+
+_PROTOTYPE( int sys_privctl, (int proc, int req, int i, void *p));
+_PROTOTYPE( int sys_nice, (int proc, int priority));
+
+_PROTOTYPE( int sys_int86, (struct reg86u *reg86p));
+_PROTOTYPE( int sys_vm_setbuf, (phys_bytes base, phys_bytes size,
+							phys_bytes high));
+_PROTOTYPE( int sys_vm_map, (int proc_nr, int do_map,
+	phys_bytes base, phys_bytes size, phys_bytes offset));
+
+/* Shorthands for sys_sdevio() system call. */
+#define sys_insb(port, proc_nr, buffer, count) \
+	sys_sdevio(DIO_INPUT, port, DIO_BYTE, proc_nr, buffer, count)
+#define sys_insw(port, proc_nr, buffer, count) \
+	sys_sdevio(DIO_INPUT, port, DIO_WORD, proc_nr, buffer, count)
+#define sys_outsb(port, proc_nr, buffer, count) \
+	sys_sdevio(DIO_OUTPUT, port, DIO_BYTE, proc_nr, buffer, count)
+#define sys_outsw(port, proc_nr, buffer, count) \
+	sys_sdevio(DIO_OUTPUT, port, DIO_WORD, proc_nr, buffer, count)
+_PROTOTYPE( int sys_sdevio, (int req, long port, int type, int proc_nr,
+	void *buffer, int count));
+
+/* Clock functionality: get system times or (un)schedule an alarm call. */
+_PROTOTYPE( int sys_times, (int proc_nr, clock_t *ptr));
+_PROTOTYPE(int sys_setalarm, (clock_t exp_time, int abs_time));
+
+/* Shorthands for sys_irqctl() system call. */
+#define sys_irqdisable(hook_id) \
+    sys_irqctl(IRQ_DISABLE, 0, 0, hook_id) 
+#define sys_irqenable(hook_id) \
+    sys_irqctl(IRQ_ENABLE, 0, 0, hook_id) 
+#define sys_irqsetpolicy(irq_vec, policy, hook_id) \
+    sys_irqctl(IRQ_SETPOLICY, irq_vec, policy, hook_id)
+#define sys_irqrmpolicy(irq_vec, hook_id) \
+    sys_irqctl(IRQ_RMPOLICY, irq_vec, 0, hook_id)
+_PROTOTYPE ( int sys_irqctl, (int request, int irq_vec, int policy,
+    int *irq_hook_id) );
+
+/* Shorthands for sys_vircopy() and sys_physcopy() system calls. */
+#define sys_biosin(bios_vir, dst_vir, bytes) \
+	sys_vircopy(SELF, BIOS_SEG, bios_vir, SELF, D, dst_vir, bytes)
+#define sys_biosout(src_vir, bios_vir, bytes) \
+	sys_vircopy(SELF, D, src_vir, SELF, BIOS_SEG, bios_vir, bytes)
+#define sys_datacopy(src_proc, src_vir, dst_proc, dst_vir, bytes) \
+	sys_vircopy(src_proc, D, src_vir, dst_proc, D, dst_vir, bytes)
+#define sys_textcopy(src_proc, src_vir, dst_proc, dst_vir, bytes) \
+	sys_vircopy(src_proc, T, src_vir, dst_proc, T, dst_vir, bytes)
+#define sys_stackcopy(src_proc, src_vir, dst_proc, dst_vir, bytes) \
+	sys_vircopy(src_proc, S, src_vir, dst_proc, S, dst_vir, bytes)
+_PROTOTYPE(int sys_vircopy, (int src_proc, int src_seg, vir_bytes src_vir,
+	int dst_proc, int dst_seg, vir_bytes dst_vir, phys_bytes bytes));
+
+#define sys_abscopy(src_phys, dst_phys, bytes) \
+	sys_physcopy(NONE, PHYS_SEG, src_phys, NONE, PHYS_SEG, dst_phys, bytes)
+_PROTOTYPE(int sys_physcopy, (int src_proc, int src_seg, vir_bytes src_vir,
+	int dst_proc, int dst_seg, vir_bytes dst_vir, phys_bytes bytes));
+_PROTOTYPE(int sys_memset, (unsigned long pattern, 
+		phys_bytes base, phys_bytes bytes));
+
+/* Vectored virtual / physical copy calls. */
+#if DEAD_CODE		/* library part not yet implemented */
+_PROTOTYPE(int sys_virvcopy, (phys_cp_req *vec_ptr,int vec_size,int *nr_ok));
+_PROTOTYPE(int sys_physvcopy, (phys_cp_req *vec_ptr,int vec_size,int *nr_ok));
+#endif
+
+_PROTOTYPE(int sys_umap, (int proc_nr, int seg, vir_bytes vir_addr,
+	 vir_bytes bytes, phys_bytes *phys_addr));
+_PROTOTYPE(int sys_segctl, (int *index, u16_t *seg, vir_bytes *off,
+	phys_bytes phys, vir_bytes size));
+
+/* Shorthands for sys_getinfo() system call. */
+#define sys_getkmessages(dst)	sys_getinfo(GET_KMESSAGES, dst, 0,0,0)
+#define sys_getkinfo(dst)	sys_getinfo(GET_KINFO, dst, 0,0,0)
+#define sys_getloadinfo(dst)	sys_getinfo(GET_LOADINFO, dst, 0,0,0)
+#define sys_getmachine(dst)	sys_getinfo(GET_MACHINE, dst, 0,0,0)
+#define sys_getproctab(dst)	sys_getinfo(GET_PROCTAB, dst, 0,0,0)
+#define sys_getprivtab(dst)	sys_getinfo(GET_PRIVTAB, dst, 0,0,0)
+#define sys_getproc(dst,nr)	sys_getinfo(GET_PROC, dst, 0,0, nr)
+#define sys_getrandomness(dst)	sys_getinfo(GET_RANDOMNESS, dst, 0,0,0)
+#define sys_getimage(dst)	sys_getinfo(GET_IMAGE, dst, 0,0,0)
+#define sys_getirqhooks(dst)	sys_getinfo(GET_IRQHOOKS, dst, 0,0,0)
+#define sys_getirqactids(dst)	sys_getinfo(GET_IRQACTIDS, dst, 0,0,0)
+#define sys_getmonparams(v,vl)	sys_getinfo(GET_MONPARAMS, v,vl, 0,0)
+#define sys_getschedinfo(v1,v2)	sys_getinfo(GET_SCHEDINFO, v1,0, v2,0)
+#define sys_getlocktimings(dst)	sys_getinfo(GET_LOCKTIMING, dst, 0,0,0)
+#define sys_getbiosbuffer(virp, sizep) sys_getinfo(GET_BIOSBUFFER, virp, \
+	sizeof(*virp), sizep, sizeof(*sizep))
+_PROTOTYPE(int sys_getinfo, (int request, void *val_ptr, int val_len,
+				 void *val_ptr2, int val_len2)		);
+
+/* Signal control. */
+_PROTOTYPE(int sys_kill, (int proc, int sig) );
+_PROTOTYPE(int sys_sigsend, (int proc_nr, struct sigmsg *sig_ctxt) ); 
+_PROTOTYPE(int sys_sigreturn, (int proc_nr, struct sigmsg *sig_ctxt) );
+_PROTOTYPE(int sys_getksig, (int *k_proc_nr, sigset_t *k_sig_map) ); 
+_PROTOTYPE(int sys_endksig, (int proc_nr) );
+
+/* NOTE: two different approaches were used to distinguish the device I/O
+ * types 'byte', 'word', 'long': the latter uses #define and results in a
+ * smaller implementation, but looses the static type checking.
+ */
+_PROTOTYPE(int sys_voutb, (pvb_pair_t *pvb_pairs, int nr_ports)		);
+_PROTOTYPE(int sys_voutw, (pvw_pair_t *pvw_pairs, int nr_ports)		);
+_PROTOTYPE(int sys_voutl, (pvl_pair_t *pvl_pairs, int nr_ports)		);
+_PROTOTYPE(int sys_vinb, (pvb_pair_t *pvb_pairs, int nr_ports)		);
+_PROTOTYPE(int sys_vinw, (pvw_pair_t *pvw_pairs, int nr_ports)		);
+_PROTOTYPE(int sys_vinl, (pvl_pair_t *pvl_pairs, int nr_ports)		);
+
+/* Shorthands for sys_out() system call. */
+#define sys_outb(p,v)	sys_out((p), (unsigned long) (v), DIO_BYTE)
+#define sys_outw(p,v)	sys_out((p), (unsigned long) (v), DIO_WORD)
+#define sys_outl(p,v)	sys_out((p), (unsigned long) (v), DIO_LONG)
+_PROTOTYPE(int sys_out, (int port, unsigned long value, int type)	); 
+
+/* Shorthands for sys_in() system call. */
+#define sys_inb(p,v)	sys_in((p), (v), DIO_BYTE)
+#define sys_inw(p,v)	sys_in((p), (v), DIO_WORD)
+#define sys_inl(p,v)	sys_in((p), (v), DIO_LONG)
+_PROTOTYPE(int sys_in, (int port, unsigned long *value, int type)	);
+
+/* pci.c */
+_PROTOTYPE( void pci_init, (void)					);
+_PROTOTYPE( void pci_init1, (char *name)				);
+_PROTOTYPE( int pci_first_dev, (int *devindp, u16_t *vidp, u16_t *didp)	);
+_PROTOTYPE( int pci_next_dev, (int *devindp, u16_t *vidp, u16_t *didp)	);
+_PROTOTYPE( int pci_find_dev, (U8_t bus, U8_t dev, U8_t func,
+							int *devindp)	);
+_PROTOTYPE( void pci_reserve, (int devind)				);
+_PROTOTYPE( void pci_ids, (int devind, u16_t *vidp, u16_t *didp)	);
+_PROTOTYPE( void pci_rescan_bus, (U8_t busnr)				);
+_PROTOTYPE( u8_t pci_attr_r8, (int devind, int port)			);
+_PROTOTYPE( u16_t pci_attr_r16, (int devind, int port)			);
+_PROTOTYPE( u32_t pci_attr_r32, (int devind, int port)			);
+_PROTOTYPE( void pci_attr_w8, (int devind, int port, U8_t value)	);
+_PROTOTYPE( void pci_attr_w16, (int devind, int port, U16_t value)	);
+_PROTOTYPE( void pci_attr_w32, (int devind, int port, u32_t value)	);
+_PROTOTYPE( char *pci_dev_name, (U16_t vid, U16_t did)			);
+_PROTOTYPE( char *pci_slot_name, (int devind)				);
+
+#endif /* _SYSLIB_H */
+
Index: /trunk/minix/include/minix/sysutil.h
===================================================================
--- /trunk/minix/include/minix/sysutil.h	(revision 9)
+++ /trunk/minix/include/minix/sysutil.h	(revision 9)
@@ -0,0 +1,51 @@
+#ifndef _EXTRALIB_H
+#define _EXTRALIB_H
+
+/* Extra system library definitions to support device drivers and servers.
+ *
+ * Created:
+ *	Mar 15, 2004 by Jorrit N. Herder
+ *
+ * Changes:
+ *	May 31, 2005: added printf, kputc (relocated from syslib)
+ *	May 31, 2005: added getuptime
+ *	Mar 18, 2005: added tickdelay
+ *	Oct 01, 2004: added env_parse, env_prefix, env_panic
+ *	Jul 13, 2004: added fkey_ctl
+ *	Apr 28, 2004: added report, panic 
+ *	Mar 31, 2004: setup like other libraries, such as syslib
+ */
+
+/*==========================================================================* 
+ * Miscellaneous helper functions.
+ *==========================================================================*/ 
+
+/* Environment parsing return values. */
+#define EP_BUF_SIZE   128	/* local buffer for env value */
+#define EP_UNSET	0	/* variable not set */
+#define EP_OFF		1	/* var = off */
+#define EP_ON		2	/* var = on (or field left blank) */
+#define EP_SET		3	/* var = 1:2:3 (nonblank field) */
+#define EP_EGETKENV	4	/* sys_getkenv() failed ... */
+
+_PROTOTYPE( void env_setargs, (int argc, char *argv[])		        );
+_PROTOTYPE( int env_get_param, (char *key, char *value, int max_size)	);
+_PROTOTYPE( int env_prefix, (char *env, char *prefix)			);
+_PROTOTYPE( void env_panic, (char *key)					);
+_PROTOTYPE( int env_parse, (char *env, char *fmt, int field, long *param,
+				long min, long max)			);
+
+#define fkey_map(fkeys, sfkeys) fkey_ctl(FKEY_MAP, (fkeys), (sfkeys))
+#define fkey_unmap(fkeys, sfkeys) fkey_ctl(FKEY_UNMAP, (fkeys), (sfkeys))
+#define fkey_events(fkeys, sfkeys) fkey_ctl(FKEY_EVENTS, (fkeys), (sfkeys))
+_PROTOTYPE( int fkey_ctl, (int req, int *fkeys, int *sfkeys)		);
+
+_PROTOTYPE( int printf, (const char *fmt, ...));
+_PROTOTYPE( void kputc, (int c));
+_PROTOTYPE( void report, (char *who, char *mess, int num));
+_PROTOTYPE( void panic, (char *who, char *mess, int num));
+_PROTOTYPE( int getuptime, (clock_t *ticks));
+_PROTOTYPE( int tickdelay, (clock_t ticks));
+
+#endif /* _EXTRALIB_H */
+
Index: /trunk/minix/include/minix/type.h
===================================================================
--- /trunk/minix/include/minix/type.h	(revision 9)
+++ /trunk/minix/include/minix/type.h	(revision 9)
@@ -0,0 +1,150 @@
+#ifndef _TYPE_H
+#define _TYPE_H
+
+#ifndef _MINIX_SYS_CONFIG_H
+#include <minix/sys_config.h>
+#endif
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+/* Type definitions. */
+typedef unsigned int vir_clicks; 	/*  virtual addr/length in clicks */
+typedef unsigned long phys_bytes;	/* physical addr/length in bytes */
+typedef unsigned int phys_clicks;	/* physical addr/length in clicks */
+
+#if (_MINIX_CHIP == _CHIP_INTEL)
+typedef unsigned int vir_bytes;	/* virtual addresses and lengths in bytes */
+#endif
+
+#if (_MINIX_CHIP == _CHIP_M68000)
+typedef unsigned long vir_bytes;/* virtual addresses and lengths in bytes */
+#endif
+
+#if (_MINIX_CHIP == _CHIP_SPARC)
+typedef unsigned long vir_bytes;/* virtual addresses and lengths in bytes */
+#endif
+
+/* Memory map for local text, stack, data segments. */
+struct mem_map {
+  vir_clicks mem_vir;		/* virtual address */
+  phys_clicks mem_phys;		/* physical address */
+  vir_clicks mem_len;		/* length */
+};
+
+/* Memory map for remote memory areas, e.g., for the RAM disk. */
+struct far_mem {
+  int in_use;			/* entry in use, unless zero */
+  phys_clicks mem_phys;		/* physical address */
+  vir_clicks mem_len;		/* length */
+};
+
+/* Structure for virtual copying by means of a vector with requests. */
+struct vir_addr {
+  int proc_nr_e;
+  int segment;
+  vir_bytes offset;
+};
+
+/* Memory allocation by PM. */
+struct hole {
+  struct hole *h_next;          /* pointer to next entry on the list */
+  phys_clicks h_base;           /* where does the hole begin? */
+  phys_clicks h_len;            /* how big is the hole? */
+};
+
+/* Memory info from PM. */
+struct pm_mem_info {
+	struct hole pmi_holes[_NR_HOLES];/* memory (un)allocations */
+	u32_t pmi_hi_watermark;		 /* highest ever-used click + 1 */
+};
+
+#define phys_cp_req vir_cp_req 
+struct vir_cp_req {
+  struct vir_addr src;
+  struct vir_addr dst;
+  phys_bytes count;
+};
+
+typedef struct {
+  vir_bytes iov_addr;		/* address of an I/O buffer */
+  vir_bytes iov_size;		/* sizeof an I/O buffer */
+} iovec_t;
+
+/* PM passes the address of a structure of this type to KERNEL when
+ * sys_sendsig() is invoked as part of the signal catching mechanism.
+ * The structure contain all the information that KERNEL needs to build
+ * the signal stack.
+ */
+struct sigmsg {
+  int sm_signo;			/* signal number being caught */
+  unsigned long sm_mask;	/* mask to restore when handler returns */
+  vir_bytes sm_sighandler;	/* address of handler */
+  vir_bytes sm_sigreturn;	/* address of _sigreturn in C library */
+  vir_bytes sm_stkptr;		/* user stack pointer */
+};
+
+/* This is used to obtain system information through SYS_GETINFO. */
+struct kinfo {
+  phys_bytes code_base;		/* base of kernel code */
+  phys_bytes code_size;		
+  phys_bytes data_base;		/* base of kernel data */
+  phys_bytes data_size;
+  vir_bytes proc_addr;		/* virtual address of process table */
+  phys_bytes kmem_base;		/* kernel memory layout (/dev/kmem) */
+  phys_bytes kmem_size;
+  phys_bytes bootdev_base;	/* boot device from boot image (/dev/boot) */
+  phys_bytes bootdev_size;
+  phys_bytes ramdev_base;	/* boot device from boot image (/dev/boot) */
+  phys_bytes ramdev_size;
+  phys_bytes params_base;	/* parameters passed by boot monitor */
+  phys_bytes params_size;
+  int nr_procs;			/* number of user processes */
+  int nr_tasks;			/* number of kernel tasks */
+  char release[6];		/* kernel release number */
+  char version[6];		/* kernel version number */
+#if DEBUG_LOCK_CHECK
+  int relocking;		/* interrupt locking depth (should be 0) */
+#endif
+};
+
+/* Load data accounted every this no. of seconds. */
+#define _LOAD_UNIT_SECS		 6 
+
+/* Load data history is kept for this long. */
+#define _LOAD_HISTORY_MINUTES	15
+#define _LOAD_HISTORY_SECONDS	(60*_LOAD_HISTORY_MINUTES)
+
+/* We need this many slots to store the load history. */
+#define _LOAD_HISTORY	(_LOAD_HISTORY_SECONDS/_LOAD_UNIT_SECS)
+
+/* Runnable processes and other load-average information. */
+struct loadinfo {
+  u16_t proc_load_history[_LOAD_HISTORY];	/* history of proc_s_cur */
+  u16_t proc_last_slot;
+  clock_t last_clock;
+};
+
+struct machine {
+  int pc_at;
+  int ps_mca;
+  int processor;
+  int prot;
+  int vdu_ega;
+  int vdu_vga;
+};
+
+struct io_range
+{
+	unsigned ior_base;	/* Lowest I/O port in range */
+	unsigned ior_limit;	/* Highest I/O port in range */
+};
+
+struct mem_range
+{
+	phys_bytes mr_base;	/* Lowest memory address in range */
+	phys_bytes mr_limit;	/* Highest memory address in range */
+};
+
+#endif /* _TYPE_H */
Index: /trunk/minix/include/minix/u64.h
===================================================================
--- /trunk/minix/include/minix/u64.h	(revision 9)
+++ /trunk/minix/include/minix/u64.h	(revision 9)
@@ -0,0 +1,33 @@
+/*	minix/u64.h					Author: Kees J. Bot
+ *								7 Dec 1995
+ * Functions to manipulate 64 bit disk addresses.
+ */
+#ifndef _MINIX__U64_H
+#define _MINIX__U64_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+u64_t add64(u64_t i, u64_t j);
+u64_t add64u(u64_t i, unsigned j);
+u64_t add64ul(u64_t i, unsigned long j);
+u64_t sub64(u64_t i, u64_t j);
+u64_t sub64u(u64_t i, unsigned j);
+u64_t sub64ul(u64_t i, unsigned long j);
+unsigned diff64(u64_t i, u64_t j);
+u64_t cvu64(unsigned i);
+u64_t cvul64(unsigned long i);
+unsigned cv64u(u64_t i);
+unsigned long cv64ul(u64_t i);
+unsigned long div64u(u64_t i, unsigned j);
+unsigned rem64u(u64_t i, unsigned j);
+u64_t mul64u(unsigned long i, unsigned j);
+int cmp64(u64_t i, u64_t j);
+int cmp64u(u64_t i, unsigned j);
+int cmp64ul(u64_t i, unsigned long j);
+unsigned long ex64lo(u64_t i);
+unsigned long ex64hi(u64_t i);
+u64_t make64(unsigned long lo, unsigned long hi);
+
+#endif /* _MINIX__U64_H */
Index: /trunk/minix/include/net/gen/arp_io.h
===================================================================
--- /trunk/minix/include/net/gen/arp_io.h	(revision 9)
+++ /trunk/minix/include/net/gen/arp_io.h	(revision 9)
@@ -0,0 +1,23 @@
+/*
+net/gen/arp_io.h
+
+Created:	Jan 2001 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+typedef struct nwio_arp
+{
+	int nwa_entno;
+	u32_t nwa_flags;
+	ipaddr_t nwa_ipaddr;
+	ether_addr_t nwa_ethaddr;
+} nwio_arp_t;
+
+#define NWAF_EMPTY	0
+#define NWAF_INCOMPLETE	1
+#define NWAF_DEAD	2
+#define NWAF_PERM	4
+#define NWAF_PUB	8
+
+/*
+ * $PchId: arp_io.h,v 1.2 2004/08/03 11:01:59 philip Exp $
+ */
Index: /trunk/minix/include/net/gen/dhcp.h
===================================================================
--- /trunk/minix/include/net/gen/dhcp.h	(revision 9)
+++ /trunk/minix/include/net/gen/dhcp.h	(revision 9)
@@ -0,0 +1,73 @@
+/*	net/gen/dhcp.h - DHCP packet format		Author: Kees J. Bot
+ *								1 Dec 2000
+ */
+
+#ifndef __NET__GEN__DHCP_H__
+#define __NET__GEN__DHCP_H__
+
+typedef struct dhcp {
+	u8_t		op;		/* Message opcode/type. */
+	u8_t		htype;		/* Hardware address type. */
+	u8_t		hlen;		/* Hardware address length. */
+	u8_t		hops;		/* Hop count when relaying. */
+	u32_t		xid;		/* Transaction ID. */
+	u16_t		secs;		/* Seconds past since client began. */
+	u16_t		flags;		/* Flags. */
+	ipaddr_t	ciaddr;		/* Client IP address. */
+	ipaddr_t	yiaddr;		/* "Your" IP address. */
+	ipaddr_t	siaddr;		/* Boot server IP address. */
+	ipaddr_t	giaddr;		/* Relay agent (gateway) IP address. */
+	u8_t		chaddr[16];	/* Client hardware address. */
+	u8_t		sname[64];	/* Server host name. */
+	u8_t		file[128];	/* Boot file. */
+	u32_t		magic;		/* Magic number. */
+	u8_t		options[308];	/* Optional parameters. */
+} dhcp_t;
+
+/* DHCP operations and stuff: */
+#define DHCP_BOOTREQUEST	 1	/* Boot request message. */
+#define DHCP_BOOTREPLY		 2	/* Boot reply message. */
+#define DHCP_HTYPE_ETH		 1	/* Ethernet hardware type. */
+#define DHCP_HLEN_ETH		 6	/* Ethernet hardware address length. */
+#define DHCP_FLAGS_BCAST    0x8000U	/* Reply must be broadcast to client. */
+
+					/* "Magic" first four option bytes. */
+#define DHCP_MAGIC	HTONL(0x63825363UL)
+
+/* DHCP common tags: */
+#define DHCP_TAG_NETMASK	 1	/* Netmask. */
+#define DHCP_TAG_GATEWAY	 3	/* Gateway list. */
+#define DHCP_TAG_DNS		 6	/* DNS Nameserver list. */
+#define DHCP_TAG_HOSTNAME	12	/* Host name. */
+#define DHCP_TAG_DOMAIN		15	/* Domain. */
+#define DHCP_TAG_IPMTU		26	/* Interface MTU. */
+
+/* DHCP protocol tags: */
+#define DHCP_TAG_REQIP		50	/* Request this IP. */
+#define DHCP_TAG_LEASE		51	/* Lease time requested/offered. */
+#define DHCP_TAG_OVERLOAD	52	/* Options continued in file/sname. */
+#define DHCP_TAG_TYPE		53	/* DHCP message (values below). */
+#define DHCP_TAG_SERVERID	54	/* Server identifier. */
+#define DHCP_TAG_REQPAR		55	/* Parameters requested. */
+#define DHCP_TAG_MESSAGE	56	/* Error message. */
+#define DHCP_TAG_MAXDHCP	57	/* Max DHCP packet size. */
+#define DHCP_TAG_RENEWAL	58	/* Time to go into renewal state. */
+#define DHCP_TAG_REBINDING	59	/* Time to go into rebinding state. */
+#define DHCP_TAG_CLASSID	60	/* Class identifier. */
+#define DHCP_TAG_CLIENTID	61	/* Client identifier. */
+
+/* DHCP messages: */
+#define DHCP_DISCOVER		 1	/* Locate available servers. */
+#define DHCP_OFFER		 2	/* Parameters offered to client. */
+#define DHCP_REQUEST		 3	/* (Re)request offered parameters. */
+#define DHCP_DECLINE		 4	/* Client declines offer. */
+#define DHCP_ACK		 5	/* Server acknowlegdes request. */
+#define DHCP_NAK		 6	/* Server denies request. */
+#define DHCP_RELEASE		 7	/* Client relinguishes address. */
+#define DHCP_INFORM		 8	/* Client requests just local config. */
+
+void dhcp_init(dhcp_t *_dp);
+int dhcp_settag(dhcp_t *_dp, int _tag, void *_data, size_t _len);
+int dhcp_gettag(dhcp_t *_dp, int _searchtag, u8_t **_pdata, size_t *_plen);
+
+#endif /* __NET__GEN__DHCP_H__ */
Index: /trunk/minix/include/net/gen/eth_hdr.h
===================================================================
--- /trunk/minix/include/net/gen/eth_hdr.h	(revision 9)
+++ /trunk/minix/include/net/gen/eth_hdr.h	(revision 9)
@@ -0,0 +1,15 @@
+/*
+server/ip/gen/eth_hdr.h
+*/
+
+#ifndef __SERVER__IP__GEN__ETH_HDR_H__
+#define __SERVER__IP__GEN__ETH_HDR_H__
+
+typedef struct eth_hdr
+{
+	ether_addr_t eh_dst;
+	ether_addr_t eh_src;
+	ether_type_t eh_proto;
+} eth_hdr_t;
+
+#endif /* __SERVER__IP__GEN__ETH_HDR_H__ */
Index: /trunk/minix/include/net/gen/eth_io.h
===================================================================
--- /trunk/minix/include/net/gen/eth_io.h	(revision 9)
+++ /trunk/minix/include/net/gen/eth_io.h	(revision 9)
@@ -0,0 +1,79 @@
+/*
+server/gen/ip/eth_io.h
+*/
+
+#ifndef __SERVER__IP__GEN__ETH_IO_H__
+#define __SERVER__IP__GEN__ETH_IO_H__
+
+typedef struct nwio_ethopt
+{
+	u32_t nweo_flags;
+	ether_addr_t nweo_multi, nweo_rem;
+	ether_type_t nweo_type;
+} nwio_ethopt_t;
+
+#define NWEO_NOFLAGS	0x0000L
+#define NWEO_ACC_MASK	0x0003L
+#	define NWEO_EXCL	0x00000001L
+#	define NWEO_SHARED	0x00000002L
+#	define NWEO_COPY	0x00000003L
+#define NWEO_LOC_MASK	0x0010L
+#	define NWEO_EN_LOC	0x00000010L
+#	define NWEO_DI_LOC	0x00100000L
+#define NWEO_BROAD_MASK	0x0020L
+#	define NWEO_EN_BROAD	0x00000020L
+#	define NWEO_DI_BROAD	0x00200000L
+#define NWEO_MULTI_MASK 0x0040L
+#	define NWEO_EN_MULTI	0x00000040L
+#	define NWEO_DI_MULTI	0x00400000L
+#define NWEO_PROMISC_MASK 0x0080L
+#	define NWEO_EN_PROMISC	0x00000080L
+#	define NWEO_DI_PROMISC	0x00800000L
+#define NWEO_REM_MASK	0x0100L
+#	define NWEO_REMSPEC	0x00000100L
+#	define NWEO_REMANY	0x01000000L
+#define NWEO_TYPE_MASK	0x0200L
+#	define NWEO_TYPESPEC	0x00000200L
+#	define NWEO_TYPEANY	0x02000000L
+#define NWEO_RW_MASK	0x1000L
+#	define NWEO_RWDATONLY	0x00001000L
+#	define NWEO_RWDATALL	0x10000000L
+
+typedef struct eth_stat
+{
+	unsigned long ets_recvErr,	/* # receive errors */
+		ets_sendErr,		/* # send error */
+		ets_OVW,		/* # buffer overwrite warnings,
+					   (packets arrive faster than
+					   can be processed) */
+		ets_CRCerr,		/* # crc errors of read */
+		ets_frameAll,		/* # frames not alligned (# bits
+					   not a mutiple of 8) */
+		ets_missedP,		/* # packets missed due to too
+					   slow packet processing */
+		ets_packetR,		/* # packets received */
+		ets_packetT,		/* # packets transmitted */
+		ets_transDef,		/* # transmission defered (there
+					   was a transmission of an
+					   other station in progress */
+		ets_collision,		/* # collissions */
+		ets_transAb,		/* # transmissions aborted due
+					   to accesive collisions */
+		ets_carrSense,		/* # carrier sense lost */
+		ets_fifoUnder,		/* # fifo underruns (processor
+					   is too busy) */
+		ets_fifoOver,		/* # fifo overruns (processor is
+					   too busy) */
+		ets_CDheartbeat,	/* # times unable to transmit
+					   collision signal */
+		ets_OWC;		/* # times out of window
+					   collision */
+} eth_stat_t;
+
+typedef struct nwio_ethstat
+{
+	ether_addr_t nwes_addr;
+	eth_stat_t nwes_stat;
+} nwio_ethstat_t;
+
+#endif /* __SERVER__IP__GEN__ETH_IO_H__ */
Index: /trunk/minix/include/net/gen/ether.h
===================================================================
--- /trunk/minix/include/net/gen/ether.h	(revision 9)
+++ /trunk/minix/include/net/gen/ether.h	(revision 9)
@@ -0,0 +1,35 @@
+/*
+server/ip/gen/ether.h
+*/
+
+#ifndef __SERVER__IP__GEN__ETHER_H__
+#define __SERVER__IP__GEN__ETHER_H__
+
+#define ETH_MIN_PACK_SIZE		  60
+#define ETH_MAX_PACK_SIZE		1514
+#define ETH_MAX_PACK_SIZE_TAGGED	1518
+#define ETH_HDR_SIZE			  14
+#define ETH_CRC_SIZE			   4
+
+typedef struct ether_addr
+{
+	u8_t ea_addr[6];
+} ether_addr_t;
+
+typedef u16_t ether_type_t;
+typedef U16_t Ether_type_t;
+
+#define ETH_ARP_PROTO	 0x806
+#define ETH_IP_PROTO	 0x800
+#define ETH_VLAN_PROTO	0x8100
+
+/* Tag Control Information field for VLAN and Priority tagging */
+#define ETH_TCI_PRIO_MASK	0xe000
+#define ETH_TCI_CFI		0x1000	/* Canonical Formal Indicator */
+#define ETH_TCI_VLAN_MASK	0x0fff	/* 12-bit vlan number */
+
+#endif /* __SERVER__IP__GEN__ETHER_H__ */
+
+/*
+ * $PchId: ether.h,v 1.6 2005/01/27 17:33:35 philip Exp $
+ */
Index: /trunk/minix/include/net/gen/icmp.h
===================================================================
--- /trunk/minix/include/net/gen/icmp.h	(revision 9)
+++ /trunk/minix/include/net/gen/icmp.h	(revision 9)
@@ -0,0 +1,49 @@
+/*
+server/ip/gen/icmp.h
+*/
+
+#ifndef __SERVER__IP__GEN__ICMP_H__
+#define __SERVER__IP__GEN__ICMP_H__
+
+#define ICMP_MIN_HDR_SIZE	4
+
+#define ICMP_TYPE_ECHO_REPL	0
+#define ICMP_TYPE_DST_UNRCH	3
+#	define ICMP_NET_UNRCH			0
+#	define ICMP_HOST_UNRCH			1
+#	define ICMP_PROTOCOL_UNRCH		2
+#	define ICMP_PORT_UNRCH			3
+#	define ICMP_FRAGM_AND_DF		4
+#	define ICMP_SOURCE_ROUTE_FAILED		5
+#define ICMP_TYPE_SRC_QUENCH	4
+#define ICMP_TYPE_REDIRECT	5
+#	define ICMP_REDIRECT_NET		0
+#	define ICMP_REDIRECT_HOST		1
+#	define ICMP_REDIRECT_TOS_AND_NET	2
+#	define ICMP_REDIRECT_TOS_AND_HOST	3
+#define ICMP_TYPE_ECHO_REQ	8
+#define ICMP_TYPE_ROUTER_ADVER	9
+#define ICMP_TYPE_ROUTE_SOL	10
+#define ICMP_TYPE_TIME_EXCEEDED	11
+#	define ICMP_TTL_EXC			0
+#	define ICMP_FRAG_REASSEM		1
+#define ICMP_TYPE_PARAM_PROBLEM	12
+#define ICMP_TYPE_TS_REQ	13
+#define ICMP_TYPE_TS_REPL	14
+#define ICMP_TYPE_INFO_REQ	15
+#define ICMP_TYPE_INFO_REPL	16
+
+/* Preferences for router advertisements. A router daemon installs itself
+ * as the default router in the router's interfaces by sending router
+ * advertisements to localhost with preference ICMP_RA_LOCAL_PREF.
+ */
+#define ICMP_RA_DEFAULT_PREF	0x00000000
+#define ICMP_RA_INVAL_PREF	0x80000000
+#define ICMP_RA_MAX_PREF	0x7fffffff
+#define ICMP_RA_LOCAL_PREF	0x10000000
+
+#endif /* __SERVER__IP__GEN__ICMP_H__ */
+
+/*
+ * $PchId: icmp.h,v 1.6 2002/06/10 07:10:26 philip Exp $
+ */
Index: /trunk/minix/include/net/gen/icmp_hdr.h
===================================================================
--- /trunk/minix/include/net/gen/icmp_hdr.h	(revision 9)
+++ /trunk/minix/include/net/gen/icmp_hdr.h	(revision 9)
@@ -0,0 +1,62 @@
+/*
+server/ip/gen/icmp_hdr.h
+*/
+
+#ifndef __SERVER__IP__GEN__ICMP_HDR_H__
+#define __SERVER__IP__GEN__ICMP_HDR_H__
+
+typedef struct icmp_id_seq
+{
+	u16_t	iis_id, iis_seq;
+} icmp_id_seq_t;
+
+typedef struct icmp_ip_id
+{
+	ip_hdr_t iii_hdr;
+	/* ip_hdr_options and 64 bytes of data */
+} icmp_ip_id_t;
+
+typedef struct icmp_ram		/* RFC 1256 */
+{
+	u8_t	iram_na;
+	u8_t	iram_aes;
+	u16_t	iram_lt;
+} icmp_ram_t;
+
+typedef struct icmp_pp
+{
+	u8_t	ipp_ptr;
+	u8_t	ipp_unused[3];
+} icmp_pp_t;
+
+typedef struct icmp_mtu		/* RFC 1191 */
+{
+	u16_t	im_unused;
+	u16_t	im_mtu;
+} icmp_mtu_t;
+
+typedef struct icmp_hdr
+{
+	u8_t ih_type, ih_code;
+	u16_t ih_chksum;
+	union
+	{
+		u32_t ihh_unused;
+		icmp_id_seq_t ihh_idseq;
+		ipaddr_t ihh_gateway;
+		icmp_ram_t ihh_ram;
+		icmp_pp_t ihh_pp;
+		icmp_mtu_t ihh_mtu;
+	} ih_hun;
+	union
+	{
+		icmp_ip_id_t ihd_ipid;
+		u8_t uhd_data[1];
+	} ih_dun;
+} icmp_hdr_t;
+
+#endif /* __SERVER__IP__GEN__ICMP_HDR_H__ */
+
+/*
+ * $PchId: icmp_hdr.h,v 1.5 2002/06/10 07:10:48 philip Exp $
+ */
Index: /trunk/minix/include/net/gen/if_ether.h
===================================================================
--- /trunk/minix/include/net/gen/if_ether.h	(revision 9)
+++ /trunk/minix/include/net/gen/if_ether.h	(revision 9)
@@ -0,0 +1,18 @@
+/*
+server/ip/gen/if_ether.h
+*/
+
+#ifndef __SERVER__IP__GEN__IF_ETHER_H__
+#define __SERVER__IP__GEN__IF_ETHER_H__
+
+struct ether_addr;
+
+#define _PATH_ETHERS	"/etc/ethers"
+
+char *ether_ntoa _ARGS(( struct ether_addr *e ));
+struct ether_addr *ether_aton _ARGS(( const char *s ));
+int ether_ntohost _ARGS(( char *hostname, struct ether_addr *e ));
+int ether_hostton _ARGS(( char *hostname, struct ether_addr *e ));
+int ether_line _ARGS(( char *l, struct ether_addr *e, char *hostname ));
+
+#endif /* __SERVER__IP__GEN__IF_ETHER_H__ */
Index: /trunk/minix/include/net/gen/in.h
===================================================================
--- /trunk/minix/include/net/gen/in.h	(revision 9)
+++ /trunk/minix/include/net/gen/in.h	(revision 9)
@@ -0,0 +1,37 @@
+/*
+server/ip/gen/in.h
+*/
+
+#ifndef __SERVER__IP__GEN__IN_H__
+#define __SERVER__IP__GEN__IN_H__
+
+#define IP_MIN_HDR_SIZE		20
+#define IP_MAX_HDR_SIZE		60		/* 15 * 4 */
+#define IP_VERSION		4
+#define IP_DEF_TTL		64
+#define IP_MAX_TTL		255
+#define IP_DEF_MTU		576
+#define IP_MIN_MTU		(IP_MAX_HDR_SIZE+8)
+#define IP_MAX_PACKSIZE		40000
+	/* Note: this restriction is not part of the IP-protocol but
+	   introduced by this implementation. */
+
+#define IPPROTO_ICMP		1
+#define IPPROTO_TCP		6
+#define IPPROTO_UDP		17
+
+#define IP_MC_ALL_SYSTEMS	0xE0000001	/* 224.0.0.1 */
+
+typedef u32_t ipaddr_t;
+typedef u8_t ipproto_t;
+typedef struct ip_hdropt
+{
+	u8_t iho_opt_siz;
+	u8_t iho_data[IP_MAX_HDR_SIZE-IP_MIN_HDR_SIZE];
+} ip_hdropt_t;
+
+#endif /* __SERVER__IP__GEN__IN_H__ */
+
+/*
+ * $PchId: in.h,v 1.6 2002/06/10 07:11:15 philip Exp $
+ */
Index: /trunk/minix/include/net/gen/inet.h
===================================================================
--- /trunk/minix/include/net/gen/inet.h	(revision 9)
+++ /trunk/minix/include/net/gen/inet.h	(revision 9)
@@ -0,0 +1,13 @@
+/*
+server/ip/gen/inet.h
+*/
+
+#ifndef __SERVER__IP__GEN__INET_H__
+#define __SERVER__IP__GEN__INET_H__
+
+ipaddr_t inet_addr _ARGS(( const char *addr ));
+ipaddr_t inet_network _ARGS(( const char *addr ));
+char *inet_ntoa _ARGS(( ipaddr_t addr ));
+int inet_aton _ARGS(( const char *cp, ipaddr_t *pin ));
+
+#endif /* __SERVER__IP__GEN__INET_H__ */
Index: /trunk/minix/include/net/gen/ip_hdr.h
===================================================================
--- /trunk/minix/include/net/gen/ip_hdr.h	(revision 9)
+++ /trunk/minix/include/net/gen/ip_hdr.h	(revision 9)
@@ -0,0 +1,47 @@
+/*
+server/ip/gen/ip_hdr.h
+*/
+
+#ifndef __SERVER__IP__GEN__HDR_H__
+#define __SERVER__IP__GEN__HDR_H__
+
+typedef struct ip_hdr
+{
+	u8_t ih_vers_ihl,
+		ih_tos;
+	u16_t ih_length,
+		ih_id,
+		ih_flags_fragoff;
+	u8_t ih_ttl,
+		ih_proto;
+	u16_t ih_hdr_chk;
+	ipaddr_t ih_src,
+		ih_dst;
+} ip_hdr_t;
+
+#define IH_IHL_MASK	0xf
+#define IH_VERSION_MASK	0xf
+#define IH_FRAGOFF_MASK	0x1fff
+#define IH_MORE_FRAGS	0x2000
+#define IH_DONT_FRAG	0x4000
+#define IH_FLAGS_UNUSED	0x8000
+
+#define IP_OPT_COPIED	0x80
+#define IP_OPT_NUMBER	0x1f
+
+#define IP_OPT_EOL	0x00	/* End of Options List, RFC-791 */
+#define IP_OPT_NOP	0x01	/* No Operation, RFC-791 */
+#define IP_OPT_RR	0x07	/* Record Route, RFC-791 */
+#define IP_OPT_TS	0x44	/* Timestamp, RFC-791 */
+#define IP_OPT_SEC	0x82	/* Security, RFC-1108 */
+#define IP_OPT_LSRR	0x83	/* Loose Source Route, RFC-791 */
+#define IP_OPT_SSRR	0x89	/* Strict Source Route, RFC-791 */
+#define IP_OPT_RTRALT	0x94	/* Router Alert, RFC-2113 */
+
+#define IP_OPT_RR_MIN		4
+
+#endif /* __SERVER__IP__GEN__HDR_H__ */
+
+/*
+ * $PchId: ip_hdr.h,v 1.5 2002/06/10 07:11:46 philip Exp $
+ */
Index: /trunk/minix/include/net/gen/ip_io.h
===================================================================
--- /trunk/minix/include/net/gen/ip_io.h	(revision 9)
+++ /trunk/minix/include/net/gen/ip_io.h	(revision 9)
@@ -0,0 +1,68 @@
+/*
+server/ip/gen/ip_io.h
+*/
+
+#ifndef __SERVER__IP__GEN__IP_IO_H__
+#define __SERVER__IP__GEN__IP_IO_H__
+
+typedef struct nwio_ipconf2
+{
+	u32_t	nwic_flags;
+	ipaddr_t nwic_ipaddr;
+	ipaddr_t nwic_netmask;
+} nwio_ipconf2_t;
+
+typedef struct nwio_ipconf
+{
+	u32_t	nwic_flags;
+	ipaddr_t nwic_ipaddr;
+	ipaddr_t nwic_netmask;
+	u16_t nwic_mtu;
+} nwio_ipconf_t;
+
+#define NWIC_NOFLAGS		0x0
+#define NWIC_FLAGS		0x7
+#	define NWIC_IPADDR_SET		0x1
+#	define NWIC_NETMASK_SET		0x2
+#	define NWIC_MTU_SET		0x4
+
+typedef struct nwio_ipopt
+{
+	u32_t nwio_flags;
+	ipaddr_t nwio_rem;
+	ip_hdropt_t nwio_hdropt;
+	u8_t nwio_tos;
+	u8_t nwio_ttl;
+	u8_t nwio_df;
+	ipproto_t nwio_proto;
+} nwio_ipopt_t;
+
+#define NWIO_NOFLAGS	0x0000l
+#define NWIO_ACC_MASK	0x0003l
+#	define NWIO_EXCL	0x00000001l
+#	define NWIO_SHARED	0x00000002l
+#	define NWIO_COPY	0x00000003l
+#define NWIO_LOC_MASK	0x0010l
+#	define NWIO_EN_LOC	0x00000010l
+#	define NWIO_DI_LOC	0x00100000l
+#define NWIO_BROAD_MASK	0x0020l
+#	define NWIO_EN_BROAD	0x00000020l
+#	define NWIO_DI_BROAD	0x00200000l
+#define NWIO_REM_MASK	0x0100l
+#	define NWIO_REMSPEC	0x00000100l
+#	define NWIO_REMANY	0x01000000l
+#define NWIO_PROTO_MASK	0x0200l
+#	define NWIO_PROTOSPEC	0x00000200l
+#	define NWIO_PROTOANY	0x02000000l
+#define NWIO_HDR_O_MASK	0x0400l
+#	define NWIO_HDR_O_SPEC	0x00000400l
+#	define NWIO_HDR_O_ANY	0x04000000l
+#define NWIO_RW_MASK	0x1000l
+#	define NWIO_RWDATONLY	0x00001000l
+#	define NWIO_RWDATALL	0x10000000l
+
+#endif /* __SERVER__IP__GEN__IP_IO_H__ */
+
+/*
+ * $PchId: ip_io.h,v 1.5 2001/03/12 22:17:25 philip Exp $
+ */
Index: /trunk/minix/include/net/gen/nameser.h
===================================================================
--- /trunk/minix/include/net/gen/nameser.h	(revision 9)
+++ /trunk/minix/include/net/gen/nameser.h	(revision 9)
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 1983, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *	@(#)nameser.h	5.24 (Berkeley) 6/1/90
+ */
+
+/*
+server/ip/gen/nameser.h
+
+Created Sept 18, 1991 by Philip Homburg
+*/
+
+#ifndef __SERVER__IP__GEN__NAEMSER_H__
+#define __SERVER__IP__GEN__NAEMSER_H__
+
+typedef struct dns_hdr
+{
+	u16_t dh_id;
+	u8_t dh_flag1;
+	u8_t dh_flag2;
+	u16_t dh_qdcount;
+	u16_t dh_ancount;
+	u16_t dh_nscount;
+	u16_t dh_arcount;
+} dns_hdr_t;
+
+typedef dns_hdr_t HEADER;
+
+#define DHF_QR		0x80
+#define DHF_OPCODE	0x78
+#define DHF_AA		0x04
+#define DHF_TC		0x02
+#define DHF_RD		0x01
+
+#define DHF_RA		0x80
+#define DHF_PR		0x40
+#define DHF_UNUSED	0x30
+#define DHF_RCODE	0x0F
+
+/*
+Define constants based on rfc883
+*/
+#define PACKETSZ	512		/* maximum packet size */
+#define MAXDNAME	256		/* maximum domain name */
+#define MAXCDNAME	255		/* maximum compressed domain name */
+#define MAXLABEL	63		/* maximum length of domain label */
+	/* Number of bytes of fixed size data in query structure */
+#define QFIXEDSZ	4
+	/* number of bytes of fixed size data in resource record */
+#define RRFIXEDSZ	10
+#define INDIR_MASK	0xc0
+			/* Defines for handling compressed domain names */
+
+/*
+Opcodes for DNS
+*/
+
+#define QUERY		0x0			/* standard query */
+#define IQUERY		0x1			/* inverse query */
+
+/*
+Error codes
+*/
+#define NOERROR		0			/* no error */
+#define FORMERR		1			/* format error */
+#define SERVFAIL	2			/* server failure */
+#define NXDOMAIN	3			/* non existent domain */
+#define NOTIMP		4			/* not implemented */
+#define REFUSED		5			/* query refused */
+	/* non standard */
+#define NOCHANGE	0xf			/* update failed to change db */
+
+/* Valid types */
+
+#define T_A		1		/* host address */
+#define T_NS		2		/* authoritative server */
+#define T_MD		3		/* mail destination */
+#define T_MF		4		/* mail forwarder */
+#define T_CNAME		5		/* connonical name */
+#define T_SOA		6		/* start of authority zone */
+#define T_MB		7		/* mailbox domain name */
+#define T_MG		8		/* mail group member */
+#define T_MR		9		/* mail rename name */
+#define T_NULL		10		/* null resource record */
+#define T_WKS		11		/* well known service */
+#define T_PTR		12		/* domain name pointer */
+#define T_HINFO		13		/* host information */
+#define T_MINFO		14		/* mailbox information */
+#define T_MX		15		/* mail routing information */
+#define T_TXT		16		/* text strings */
+	/* non standard */
+#define T_UINFO		100		/* user (finger) information */
+#define T_UID		101		/* user ID */
+#define T_GID		102		/* group ID */
+#define T_UNSPEC	103		/* Unspecified format (binary data) */
+	/* Query type values which do not appear in resource records */
+#define T_AXFR		252		/* transfer zone of authority */
+#define T_MAILB		253		/* transfer mailbox records */
+#define T_MAILA		254		/* transfer mail agent records */
+#define T_ANY		255		/* wildcard match */
+
+/* Valid classes */
+
+#define C_IN		1			/* the internet */
+#define C_CHAOS		3			/* for chaos net (MIT) */
+#define C_HS		4		/* for Hesiod name server at MIT */
+
+#define C_ANY		255			/* wildcard */
+
+#endif /* __SERVER__IP__GEN__NAEMSER_H__ */
Index: /trunk/minix/include/net/gen/netdb.h
===================================================================
--- /trunk/minix/include/net/gen/netdb.h	(revision 9)
+++ /trunk/minix/include/net/gen/netdb.h	(revision 9)
@@ -0,0 +1,128 @@
+/*-
+ * Copyright (c) 1980, 1983, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)netdb.h	5.15 (Berkeley) 4/3/91
+ */
+
+#ifndef _NETDB_H_
+#define _NETDB_H_
+
+#define	_PATH_HEQUIV	"/etc/hosts.equiv"
+#define	_PATH_HOSTS	"/etc/hosts"
+#define	_PATH_NETWORKS	"/etc/networks"
+#define	_PATH_PROTOCOLS	"/etc/protocols"
+#define	_PATH_SERVICES	"/etc/services"
+#define	_PATH_SERVACCES	"/etc/serv.access"
+
+/*
+ * Structures returned by network data base library.  All addresses are
+ * supplied in host order, and returned in network order (suitable for
+ * use in system calls).
+ */
+struct	hostent {
+	char	*h_name;	/* official name of host */
+	char	**h_aliases;	/* alias list */
+	int	h_addrtype;	/* host address type */
+	int	h_length;	/* length of address */
+	char	**h_addr_list;	/* list of addresses from name server */
+#define	h_addr	h_addr_list[0]	/* address, for backward compatiblity */
+};
+
+/*
+ * Assumption here is that a network number
+ * fits in 32 bits -- probably a poor one.
+ */
+struct	netent {
+	char		*n_name;	/* official name of net */
+	char		**n_aliases;	/* alias list */
+	int		n_addrtype;	/* net address type */
+	unsigned long	n_net;		/* network # */
+};
+
+struct	servent {
+	char	*s_name;	/* official service name */
+	char	**s_aliases;	/* alias list */
+	int	s_port;		/* port # */
+	char	*s_proto;	/* protocol to use */
+};
+
+struct	protoent {
+	char	*p_name;	/* official protocol name */
+	char	**p_aliases;	/* alias list */
+	int	p_proto;	/* protocol # */
+};
+
+/*
+ * Error return codes from gethostbyname() and gethostbyaddr()
+ * (left in extern int h_errno).
+ */
+extern int h_errno;
+
+#define	HOST_NOT_FOUND	1 /* Authoritative Answer Host not found */
+#define	TRY_AGAIN	2 /* Non-Authoritive Host not found, or SERVERFAIL */
+#define	NO_RECOVERY	3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
+#define	NO_DATA		4 /* Valid name, no data record of requested type */
+#define	NO_ADDRESS	NO_DATA		/* no address, look for MX record */
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+void		endhostent _ARGS((void));
+void		endnetent _ARGS((void));
+void		endprotoent _ARGS((void));
+void		endservent _ARGS((void));
+struct hostent	*gethostbyaddr _ARGS((const char *, int, int));
+struct hostent	*gethostbyname _ARGS((const char *));
+struct hostent	*gethostent _ARGS((void));
+struct netent	*getnetbyaddr _ARGS((long, int)); /* u_long? */
+struct netent	*getnetbyname _ARGS((const char *));
+struct netent	*getnetent _ARGS((void));
+struct protoent	*getprotobyname _ARGS((const char *));
+struct protoent	*getprotobynumber _ARGS((int));
+struct protoent	*getprotoent _ARGS((void));
+struct servent	*getservbyname _ARGS((const char *, const char *));
+struct servent	*getservbyport _ARGS((int, const char *));
+struct servent	*getservent _ARGS((void));
+void		herror _ARGS((const char *));
+void		sethostent _ARGS((int));
+/* void		sethostfile _ARGS((const char *)); */
+void		setnetent _ARGS((int));
+void		setprotoent _ARGS((int));
+void		setservent _ARGS((int));
+#ifdef _MINIX
+int		servxcheck _ARGS((unsigned long _peer, const char *_service,
+			void (*_logf) _ARGS((int _pass, const char *_name))));
+char		*servxfile _ARGS((const char *_file));
+#endif
+
+#endif /* !_NETDB_H_ */
Index: /trunk/minix/include/net/gen/oneCsum.h
===================================================================
--- /trunk/minix/include/net/gen/oneCsum.h	(revision 9)
+++ /trunk/minix/include/net/gen/oneCsum.h	(revision 9)
@@ -0,0 +1,10 @@
+/*
+server/ip/gen/oneCsum.h
+*/
+
+#ifndef __SERVER__IP__GEN__ONECSUM_H__
+#define __SERVER__IP__GEN__ONECSUM_H__
+
+u16_t oneC_sum _ARGS(( U16_t prev, void *data, size_t data_len ));
+
+#endif /* __SERVER__IP__GEN__ONECSUM_H__ */
Index: /trunk/minix/include/net/gen/psip_hdr.h
===================================================================
--- /trunk/minix/include/net/gen/psip_hdr.h	(revision 9)
+++ /trunk/minix/include/net/gen/psip_hdr.h	(revision 9)
@@ -0,0 +1,23 @@
+/*
+server/ip/gen/psip_hdr.h
+*/
+
+#ifndef __SERVER__IP__GEN__PSIP_HDR_H__
+#define __SERVER__IP__GEN__PSIP_HDR_H__
+
+typedef struct psip_io_hdr
+{
+	u8_t pih_flags;
+	u8_t pih_dummy[3];
+	u32_t pih_nexthop;
+} psip_io_hdr_t;
+
+#define PF_LOC_REM_MASK	1
+#define PF_LOC2REM		0
+#define PF_REM2LOC		1
+
+#endif /* __SERVER__IP__GEN__PSIP_HDR_H__ */
+
+/*
+ * $PchId: psip_hdr.h,v 1.3 2001/02/19 07:35:38 philip Exp $
+ */
Index: /trunk/minix/include/net/gen/psip_io.h
===================================================================
--- /trunk/minix/include/net/gen/psip_io.h	(revision 9)
+++ /trunk/minix/include/net/gen/psip_io.h	(revision 9)
@@ -0,0 +1,24 @@
+/*
+server/ip/gen/psip_io.h
+*/
+
+#ifndef __SERVER__IP__GEN__PSIP_IO_H__
+#define __SERVER__IP__GEN__PSIP_IO_H__
+
+typedef struct nwio_psipopt
+{
+	unsigned long nwpo_flags;
+} nwio_psipopt_t;
+
+#define NWPO_PROMISC_MASK	0x0001L
+#define		NWPO_EN_PROMISC		0x00000001L
+#define		NWUO_DI_PROMISC		0x00010000L
+#define NWPO_NEXTHOP_MASK	0x0002L
+#define		NWPO_EN_NEXTHOP		0x00000002L
+#define		NWUO_DI_NEXTHOP		0x00020000L
+
+#endif /* __SERVER__IP__GEN__PSIP_IO_H__ */
+
+/*
+ * $PchId: psip_io.h,v 1.3 2001/02/19 07:35:58 philip Exp $
+ */
Index: /trunk/minix/include/net/gen/resolv.h
===================================================================
--- /trunk/minix/include/net/gen/resolv.h	(revision 9)
+++ /trunk/minix/include/net/gen/resolv.h	(revision 9)
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1983, 1987, 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *	@(#)resolv.h	5.10 (Berkeley) 6/1/90
+ */
+#ifndef _NET__GEN__RESOLV_H
+#define _NET__GEN__RESOLV_H
+
+/*
+ * Resolver configuration file.
+ * Normally not present, but may contain the address of the
+ * inital name server(s) to query and the domain search list.
+ */
+
+#ifndef _PATH_RESCONF
+#define _PATH_RESCONF        "/etc/resolv.conf"
+#endif
+
+/*
+ * Global defines and variables for resolver stub.
+ */
+#define	MAXNS		3		/* max # name servers we'll track */
+#define	MAXDFLSRCH	3		/* # default domain levels to try */
+#define	MAXDNSRCH	6		/* max # domains in search path */
+#define	LOCALDOMAINPARTS 2		/* min levels in name that is "local" */
+
+#define	RES_TIMEOUT	5		/* min. seconds between retries */
+
+#define NAMESERVER_PORT	53
+
+struct state {
+	int	retrans;	 	/* retransmition time interval */
+	int	retry;			/* number of times to retransmit */
+	long	options;		/* option flags - see below. */
+	int	nscount;		/* number of name servers */
+	ipaddr_t nsaddr_list[MAXNS];	/* address of name server */
+#define	nsaddr	nsaddr_list[0]		/* for backward compatibility */
+	u16_t	nsport_list[MAXNS];	/* port of name server */
+	u16_t	id;			/* current packet id */
+	char	defdname[MAXDNAME];	/* default domain */
+	char	*dnsrch[MAXDNSRCH+1];	/* components of domain to search */
+};
+
+/*
+ * Resolver options
+ */
+#define RES_INIT	0x0001		/* address initialized */
+#define RES_DEBUG	0x0002		/* print debug messages */
+#define RES_AAONLY	0x0004		/* authoritative answers only */
+#define RES_USEVC	0x0008		/* use virtual circuit */
+#define RES_PRIMARY	0x0010		/* query primary server only */
+#define RES_IGNTC	0x0020		/* ignore trucation errors */
+#define RES_RECURSE	0x0040		/* recursion desired */
+#define RES_DEFNAMES	0x0080		/* use default domain name */
+#define RES_STAYOPEN	0x0100		/* Keep TCP socket open */
+#define RES_DNSRCH	0x0200		/* search up local domain tree */
+
+#define RES_DEFAULT	(RES_RECURSE | RES_DEFNAMES | RES_DNSRCH )
+
+extern struct state _res;
+
+struct rrec;
+
+int res_init _ARGS(( void ));
+int res_mkquery _ARGS(( int op, const char *dname, int class, int type,
+	const char *data, int datalen, const struct rrec *newrr,
+	char *buf, int buflen ));
+int res_query _ARGS(( char *name, int class, int type, u8_t *answer, 
+	int anslen ));
+int res_querydomain _ARGS(( char *name, char *domain, int class, int type, 
+	u8_t *answer, int anslen ));
+int res_search _ARGS(( char *name, int class, int type, u8_t *answer, 
+	int anslen ));
+int res_send _ARGS(( const char *buf, int buflen, char *answer, int anslen ));
+void _res_close _ARGS(( void ));
+
+int dn_comp _ARGS(( const u8_t *exp_dn, u8_t *comp_dn, int length, 
+	u8_t **dnptrs, u8_t **lastdnptr ));
+int dn_expand  _ARGS(( const u8_t *msg, const u8_t *eomorig,
+	const u8_t *comp_dn, u8_t *exp_dn, int length ));
+int dn_skipname _ARGS(( const u8_t *comp_dn, const u8_t *eom ));
+
+char *__hostalias _ARGS(( const char *name ));
+
+u16_t _getshort _ARGS(( const u8_t *msgp ));
+u32_t _getlong _ARGS(( const u8_t *msgp ));
+void __putshort _ARGS(( U16_t s, u8_t *msgp ));
+void __putlong _ARGS(( u32_t l, u8_t *msgp ));
+
+void p_query _ARGS(( char *msg ));
+
+#endif /* _NET__GEN__RESOLV_H */
Index: /trunk/minix/include/net/gen/rip.h
===================================================================
--- /trunk/minix/include/net/gen/rip.h	(revision 9)
+++ /trunk/minix/include/net/gen/rip.h	(revision 9)
@@ -0,0 +1,77 @@
+/*
+net/gen/rip.h
+
+Definitions for the Routing Information Protocol (RFC-1058).
+
+Created:	Aug 16, 1993 by Philip Homburg <philip@cs.vu.nl>
+*/
+
+#ifndef NET__GEN__RIP_H
+#define NET__GEN__RIP_H
+
+typedef struct rip_hdr
+{
+	u8_t rh_command;
+	u8_t rh_version;
+	u16_t rh_zero;
+} rip_hdr_t;
+
+#define RHC_REQUEST	1
+#define RHC_RESPONSE	2
+
+#define RIP_ENTRY_MAX	25
+
+typedef struct rip_entry
+{
+	union
+	{
+		struct rip_entry_v1
+		{
+			u16_t re_family;
+			u16_t re_zero0;
+			u32_t re_address;
+			u32_t re_zero1;
+			u32_t re_zero2;
+			u32_t re_metric;
+		} v1;
+		struct rip_entry_v2
+		{
+			u16_t re_family;
+			u16_t re_tag;
+			u32_t re_address;
+			u32_t re_mask;
+			u32_t re_nexthop;
+			u32_t re_metric;
+		} v2;
+	} u;
+} rip_entry_t;
+
+#define RIP_FAMILY_IP	2
+#define RIP_INFINITY	16
+
+#define RIP_UDP_PORT	520
+#define RIP_PERIOD	 30	/* A responce is sent once every
+				 * RIP_PERIOD seconds
+				 */
+#define RIP_FUZZ	 10	/* The actual value used is RIP_FREQUENCE -
+				 * a random number of at most RIP_FUZZ.
+				 */
+#define RIP_TIMEOUT	180	/* A route is dead after RIP_TIMEOUT seconds */
+#define RIP_DELETE_TO	120	/* A dead route is removed after RIP_DELETE_TO
+				 * seconds
+				 */
+
+#ifdef __RIP_DEBUG
+#undef RIP_PERIOD
+#define RIP_PERIOD	15
+#undef RIP_TIMEOUT
+#define RIP_TIMEOUT	10
+#undef RIP_DELETE_TO
+#define RIP_DELETE_TO	10
+#endif /* __RIP_DEBUG */
+
+#endif /* NET__GEN__RIP_H */
+
+/*
+ * $PchId: rip.h,v 1.3 1995/11/17 22:21:16 philip Exp $
+ */
Index: /trunk/minix/include/net/gen/route.h
===================================================================
--- /trunk/minix/include/net/gen/route.h	(revision 9)
+++ /trunk/minix/include/net/gen/route.h	(revision 9)
@@ -0,0 +1,31 @@
+/*
+server/ip/gen/route.h
+*/
+
+#ifndef __SERVER__IP__GEN__ROUTE_H__
+#define __SERVER__IP__GEN__ROUTE_H__
+
+typedef struct nwio_route
+{
+	u32_t nwr_ent_no;
+	u32_t nwr_ent_count;
+	ipaddr_t nwr_dest;
+	ipaddr_t nwr_netmask;
+	ipaddr_t nwr_gateway;
+	u32_t nwr_dist;
+	u32_t nwr_flags;
+	u32_t nwr_pref;
+	u32_t nwr_mtu;		/* Ignored, compatibility with VMD */
+	ipaddr_t nwr_ifaddr;
+} nwio_route_t;
+
+#define NWRF_EMPTY		0
+#define NWRF_INUSE		1
+#define NWRF_STATIC		2
+#define NWRF_UNREACHABLE	4
+
+#endif /* __SERVER__IP__GEN__ROUTE_H__ */
+
+/*
+ * $PchId: route.h,v 1.3 1995/11/17 22:19:50 philip Exp $
+ */
Index: /trunk/minix/include/net/gen/socket.h
===================================================================
--- /trunk/minix/include/net/gen/socket.h	(revision 9)
+++ /trunk/minix/include/net/gen/socket.h	(revision 9)
@@ -0,0 +1,41 @@
+/*
+server/ip/gen/socket.h
+*/
+
+#ifndef __SERVER__IP__GEN__SOCKET_H__
+#define __SERVER__IP__GEN__SOCKET_H__
+
+/* From SunOS: /usr/include/sys/socketh */
+
+/*
+ * Address families.
+ */
+#define	AF_UNSPEC	0		/* unspecified */
+#define	AF_UNIX		1		/* local to host (pipes, portals) */
+#define	AF_INET		2		/* internetwork: UDP, TCP, etc. */
+#define	AF_IMPLINK	3		/* arpanet imp addresses */
+#define	AF_PUP		4		/* pup protocols: e.g. BSP */
+#define	AF_CHAOS	5		/* mit CHAOS protocols */
+#define	AF_NS		6		/* XEROX NS protocols */
+#define	AF_NBS		7		/* nbs protocols */
+#define	AF_ECMA		8		/* european computer manufacturers */
+#define	AF_DATAKIT	9		/* datakit protocols */
+#define	AF_CCITT	10		/* CCITT protocols, X.25 etc */
+#define	AF_SNA		11		/* IBM SNA */
+#define	AF_DECnet	12		/* DECnet */
+#define	AF_DLI		13		/* Direct data link interface */
+#define	AF_LAT		14		/* LAT */
+#define	AF_HYLINK	15		/* NSC Hyperchannel */
+#define	AF_APPLETALK	16		/* Apple Talk */
+
+#define	AF_NIT		17		/* Network Interface Tap */
+#define	AF_802		18		/* IEEE 802.2, also ISO 8802 */
+#define	AF_OSI		19		/* umbrella for all families used
+					 * by OSI (e.g. protosw lookup) */
+#define	AF_X25		20		/* CCITT X.25 in particular */
+#define	AF_OSINET	21		/* AFI = 47, IDI = 4 */
+#define	AF_GOSIP	22		/* U.S. Government OSI */
+
+#define	AF_MAX		21
+
+#endif /* __SERVER__IP__GEN__SOCKET_H__ */
Index: /trunk/minix/include/net/gen/tcp.h
===================================================================
--- /trunk/minix/include/net/gen/tcp.h	(revision 9)
+++ /trunk/minix/include/net/gen/tcp.h	(revision 9)
@@ -0,0 +1,19 @@
+/*
+server/ip/gen/tcp.h
+*/
+
+#ifndef __SERVER__IP__GEN__TCP_H__
+#define __SERVER__IP__GEN__TCP_H__
+
+#define TCP_MIN_HDR_SIZE	20
+#define TCP_MAX_HDR_SIZE	60
+
+#define TCPPORT_TELNET		23
+#define TCPPORT_FINGER		79
+
+#define TCPPORT_RESERVED	1024
+
+typedef u16_t tcpport_t;
+typedef U16_t Tcpport_t;	/* for use in prototypes */
+
+#endif /* __SERVER__IP__GEN__TCP_H__ */
Index: /trunk/minix/include/net/gen/tcp_hdr.h
===================================================================
--- /trunk/minix/include/net/gen/tcp_hdr.h	(revision 9)
+++ /trunk/minix/include/net/gen/tcp_hdr.h	(revision 9)
@@ -0,0 +1,49 @@
+/*
+server/ip/gen/tcp_hdr.h
+*/
+
+#ifndef __SERVER__IP__GEN__TCP_HDR_H__
+#define __SERVER__IP__GEN__TCP_HDR_H__
+
+typedef struct tcp_hdr
+{
+	tcpport_t th_srcport;
+	tcpport_t th_dstport;
+	u32_t th_seq_nr;
+	u32_t th_ack_nr;
+	u8_t th_data_off;
+	u8_t th_flags;
+	u16_t th_window;
+	u16_t th_chksum;
+	u16_t th_urgptr;
+} tcp_hdr_t;
+
+#define TH_DO_MASK	0xf0
+
+#define TH_FLAGS_MASK	0x3f
+#define THF_FIN		0x1
+#define THF_SYN		0x2
+#define THF_RST		0x4
+#define THF_PSH		0x8
+#define THF_ACK		0x10
+#define THF_URG		0x20
+
+typedef struct tcp_hdropt
+{
+	int tho_opt_siz;
+	u8_t tho_data[TCP_MAX_HDR_SIZE-TCP_MIN_HDR_SIZE];
+} tcp_hdropt_t;
+
+#define TCP_OPT_EOL	 0
+#define TCP_OPT_NOP	 1
+#define TCP_OPT_MSS	 2
+#define TCP_OPT_WSOPT	 3	/* RFC-1323, window scale option */
+#define TCP_OPT_SACKOK	 4	/* RFC-2018, SACK permitted */
+#define TCP_OPT_TS	 8	/* RFC-1323, Timestamps option */
+#define TCP_OPT_CCNEW	12	/* RFC-1644, new connection count */
+
+#endif /* __SERVER__IP__GEN__TCP_HDR_H__ */
+
+/*
+ * $PchId: tcp_hdr.h,v 1.4 2002/06/10 07:12:22 philip Exp $
+ */
Index: /trunk/minix/include/net/gen/tcp_io.h
===================================================================
--- /trunk/minix/include/net/gen/tcp_io.h	(revision 9)
+++ /trunk/minix/include/net/gen/tcp_io.h	(revision 9)
@@ -0,0 +1,82 @@
+/*
+server/ip/gen/tcp_io.h
+*/
+
+#ifndef __SERVER__IP__GEN__TCP_IO_H__
+#define __SERVER__IP__GEN__TCP_IO_H__
+
+typedef struct nwio_tcpconf
+{
+	u32_t nwtc_flags;
+	ipaddr_t nwtc_locaddr;
+	ipaddr_t nwtc_remaddr;
+	tcpport_t nwtc_locport;
+	tcpport_t nwtc_remport;
+} nwio_tcpconf_t;
+
+#define NWTC_NOFLAGS	0x0000L
+#define NWTC_ACC_MASK	0x0003L
+#	define NWTC_EXCL	0x00000001L
+#	define NWTC_SHARED	0x00000002L
+#	define NWTC_COPY	0x00000003L
+#define NWTC_LOCPORT_MASK	0x0030L
+#	define NWTC_LP_UNSET	0x00000010L
+#	define NWTC_LP_SET	0x00000020L
+#	define NWTC_LP_SEL	0x00000030L
+#define NWTC_REMADDR_MASK	0x0100L
+#	define NWTC_SET_RA	0x00000100L
+#	define NWTC_UNSET_RA	0x01000000L
+#define NWTC_REMPORT_MASK	0x0200L
+#	define NWTC_SET_RP	0x00000200L
+#	define NWTC_UNSET_RP	0x02000000L
+
+typedef struct nwio_tcpcl
+{
+	long nwtcl_flags;
+	long nwtcl_ttl;
+} nwio_tcpcl_t;
+
+#define TCF_DEFAULT	0	/* Default parameters */
+#define TCF_ASYNCH	1	/* Asynchronous connect for non-blocking
+				 * socket emulation.
+				 */
+
+typedef struct nwio_tcpatt
+{
+	long nwta_flags;
+} nwio_tcpatt_t;
+
+typedef struct nwio_tcpopt
+{
+	u32_t nwto_flags;
+} nwio_tcpopt_t;
+
+#define NWTO_NOFLAG		0x0000L
+#define NWTO_SND_URG_MASK	0x0001L
+#	define NWTO_SND_URG	0x00000001L
+#	define NWTO_SND_NOTURG	0x00010000L
+#define NWTO_RCV_URG_MASK	0x0002L
+#	define NWTO_RCV_URG	0x00000002L
+#	define NWTO_RCV_NOTURG	0x00020000L
+#define NWTO_BSD_URG_MASK	0x0004L
+#	define NWTO_BSD_URG	0x00000004L
+#	define NWTO_NOTBSD_URG	0x00040000L
+#define NWTO_DEL_RST_MASK	0x0008L
+#	define NWTO_DEL_RST	0x00000008L
+#define NWTO_BULK_MASK		0x0010L
+#	define NWTO_BULK	0x00000010L
+#	define NWTO_NOBULK	0x00100000L
+
+#define TC_SECRET_SIZE	12
+
+typedef struct tcp_cookie
+{
+	u32_t tc_ref;
+	u8_t tc_secret[TC_SECRET_SIZE];
+} tcp_cookie_t;
+
+#endif /* __SERVER__IP__GEN__TCP_IO_H__ */
+
+/*
+ * $PchId: tcp_io.h,v 1.5 2001/02/19 07:36:55 philip Exp $
+ */
Index: /trunk/minix/include/net/gen/udp.h
===================================================================
--- /trunk/minix/include/net/gen/udp.h	(revision 9)
+++ /trunk/minix/include/net/gen/udp.h	(revision 9)
@@ -0,0 +1,14 @@
+/*
+server/ip/gen/udp.h
+*/
+
+#ifndef __SERVER__IP__GEN__UDP_H__
+#define __SERVER__IP__GEN__UDP_H__
+
+typedef u16_t udpport_t;
+typedef U16_t Udpport_t;
+
+#define UDP_HDR_SIZE	8
+#define UDP_IO_HDR_SIZE	16
+
+#endif /* __SERVER__IP__GEN__UDP_H__ */
Index: /trunk/minix/include/net/gen/udp_hdr.h
===================================================================
--- /trunk/minix/include/net/gen/udp_hdr.h	(revision 9)
+++ /trunk/minix/include/net/gen/udp_hdr.h	(revision 9)
@@ -0,0 +1,26 @@
+/*
+server/ip/gen/udp_hdr.h
+*/
+
+#ifndef __SERVER__IP__GEN__UDP_HDR_H__
+#define __SERVER__IP__GEN__UDP_HDR_H__
+
+typedef struct udp_hdr
+{
+	udpport_t uh_src_port;
+	udpport_t uh_dst_port;
+	u16_t uh_length;
+	u16_t uh_chksum;
+} udp_hdr_t;
+
+typedef struct udp_io_hdr
+{
+	ipaddr_t uih_src_addr;
+	ipaddr_t uih_dst_addr;
+	udpport_t uih_src_port;
+	udpport_t uih_dst_port;
+	u16_t uih_ip_opt_len;
+	u16_t uih_data_len;
+} udp_io_hdr_t;
+
+#endif /* __SERVER__IP__GEN__UDP_HDR_H__ */
Index: /trunk/minix/include/net/gen/udp_io.h
===================================================================
--- /trunk/minix/include/net/gen/udp_io.h	(revision 9)
+++ /trunk/minix/include/net/gen/udp_io.h	(revision 9)
@@ -0,0 +1,45 @@
+/*
+server/ip/gen/udp_io.h
+*/
+
+#ifndef __SERVER__IP__GEN__UDP_IO_H__
+#define __SERVER__IP__GEN__UDP_IO_H__
+
+typedef struct nwio_udpopt
+{
+	unsigned long nwuo_flags;
+	udpport_t nwuo_locport;
+	udpport_t nwuo_remport;
+	ipaddr_t nwuo_locaddr;
+	ipaddr_t nwuo_remaddr;
+} nwio_udpopt_t;
+
+#define NWUO_NOFLAGS		0x0000L
+#define NWUO_ACC_MASK		0x0003L
+#define 	NWUO_EXCL		0x00000001L
+#define		NWUO_SHARED		0x00000002L
+#define		NWUO_COPY		0x00000003L
+#define NWUO_LOCPORT_MASK	0x000CL
+#define		NWUO_LP_SEL		0x00000004L
+#define		NWUO_LP_SET		0x00000008L
+#define		NWUO_LP_ANY		0x0000000CL
+#define NWUO_LOCADDR_MASK	0x0010L
+#define		NWUO_EN_LOC		0x00000010L
+#define		NWUO_DI_LOC		0x00100000L
+#define NWUO_BROAD_MASK		0x0020L
+#define 	NWUO_EN_BROAD		0x00000020L
+#define		NWUO_DI_BROAD		0x00200000L
+#define NWUO_REMPORT_MASK	0x0100L
+#define		NWUO_RP_SET		0x00000100L
+#define		NWUO_RP_ANY		0x01000000L
+#define NWUO_REMADDR_MASK	0x0200L
+#define 	NWUO_RA_SET		0x00000200L
+#define		NWUO_RA_ANY		0x02000000L
+#define NWUO_RW_MASK		0x1000L
+#define		NWUO_RWDATONLY		0x00001000L
+#define		NWUO_RWDATALL		0x10000000L
+#define NWUO_IPOPT_MASK		0x2000L
+#define		NWUO_EN_IPOPT		0x00002000L
+#define		NWUO_DI_IPOPT		0x20000000L
+
+#endif /* __SERVER__IP__GEN__UDP_IO_H__ */
Index: /trunk/minix/include/net/gen/vjhc.h
===================================================================
--- /trunk/minix/include/net/gen/vjhc.h	(revision 9)
+++ /trunk/minix/include/net/gen/vjhc.h	(revision 9)
@@ -0,0 +1,85 @@
+/*
+net/gen/vjhc.h
+
+Defines for Van Jacobson TCP/IP Header Compression as defined in RFC-1144
+
+Created:	Nov 15, 1993 by Philip Homburg <philip@cs.vu.nl>
+*/
+
+#ifndef __NET__GEN__VJHC_H__
+#define __NET__GEN__VJHC_H__
+
+#define VJHC_FLAG_U	0x01
+#define VJHC_FLAG_W	0x02
+#define VJHC_FLAG_A	0x04
+#define VJHC_FLAG_S	0x08
+#define VJHC_FLAG_P	0x10
+#define VJHC_FLAG_I	0x20
+#define VJHC_FLAG_C	0x40
+
+#define VJHC_SPEC_I	(VJHC_FLAG_S | VJHC_FLAG_W | VJHC_FLAG_U)
+#define VJHC_SPEC_D	(VJHC_FLAG_S | VJHC_FLAG_A | VJHC_FLAG_W | VJHC_FLAG_U)
+#define VJHC_SPEC_MASK	(VJHC_FLAG_S | VJHC_FLAG_A | VJHC_FLAG_W | VJHC_FLAG_U)
+
+#define VJHC_ENCODE(cp, n) \
+{ \
+	if ((u16_t)(n) >= 256) \
+	{ \
+		*(cp)++= 0; \
+		*(cp)++= (n >> 8); \
+		*(cp)++= (n); \
+	} \
+	else \
+		*(cp)++= (n); \
+}
+
+#define VJHC_ENCODEZ(cp, n) \
+{ \
+	if ((u16_t)(n) == 0 || (u16_t)(n) >= 256) \
+	{ \
+		*(cp)++= 0; \
+		*(cp)++= (n >> 8); \
+		*(cp)++= (n); \
+	} \
+	else \
+		*(cp)++= (n); \
+}
+
+#define VJHC_DECODEL(cp, l) \
+{ \
+	if (*(cp) == 0) \
+	{ \
+		(l)= htonl(ntohl((l)) + (((cp)[1] << 8) | (cp)[2])); \
+		(cp) += 3; \
+	} \
+	else \
+		(l)= htonl(ntohl((l)) + (u32_t)*(cp)++); \
+}
+
+#define VJHC_DECODES(cp, s) \
+{ \
+	if (*(cp) == 0) \
+	{ \
+		(s)= htons(ntohs((s)) + (((cp)[1] << 8) | (cp)[2])); \
+		(cp) += 3; \
+	} \
+	else \
+		(s)= htons(ntohs((s)) + (u16_t)*(cp)++); \
+}
+
+#define VJHC_DECODEU(cp, s) \
+{ \
+	if (*(cp) == 0) \
+	{ \
+		(s)= htons(((cp)[1] << 8) | (cp)[2]); \
+		(cp) += 3; \
+	} \
+	else \
+		(s)= htons((u16_t)*(cp)++); \
+}
+
+#endif /* __NET__GEN__VJHC_H__ */
+
+/*
+ * $PchId: vjhc.h,v 1.2 1995/11/17 22:14:46 philip Exp $
+ */
Index: /trunk/minix/include/net/hton.h
===================================================================
--- /trunk/minix/include/net/hton.h	(revision 9)
+++ /trunk/minix/include/net/hton.h	(revision 9)
@@ -0,0 +1,82 @@
+/*
+The following macro definitions convert to and from the network standard byte
+order. The macros with their name in lower case guarantee to evaluate their
+argument exactly once. The function of the macros is encoded in their names;
+htons means convert a (unsigned) short in host byte order to network byte order.
+*/
+
+#ifndef _NET__HTON_H
+#define _NET__HTON_H
+
+#include <minix/sys_config.h>
+
+extern u16_t _tmp;
+extern u32_t _tmp_l;
+
+/* Find out about the byte order. */
+
+/* assume <minix/config.h> is included, let's check */
+#if (_MINIX_CHIP == 0)
+#include "_MINIX_CHIP macro not set, include <minix/config.h>"
+#endif
+
+#if (_MINIX_CHIP == _CHIP_INTEL)
+#define LITTLE_ENDIAN	1
+#endif
+
+#if (_MINIX_CHIP == _CHIP_M68000 || _MINIX_CHIP == _CHIP_SPARC)
+#define BIG_ENDIAN	1
+#endif
+
+#if (LITTLE_ENDIAN) && (BIG_ENDIAN)
+#include "both LITTLE_ENDIAN and BIG_ENDIAN are defined"
+			/* LITTLE_ENDIAN and BIG_ENDIAN are both defined */
+#endif
+
+#if !(LITTLE_ENDIAN) && !(BIG_ENDIAN)
+#include "neither LITTLE_ENDIAN nor BIG_ENDIAN is defined"
+			/* LITTLE_ENDIAN and BIG_ENDIAN are both NOT defined */
+#endif
+
+#if LITTLE_ENDIAN
+#define HTONS(x) ( ( (((unsigned short)(x)) >>8) & 0xff) | \
+		((((unsigned short)(x)) & 0xff)<<8) )
+#define NTOHS(x) ( ( (((unsigned short)(x)) >>8) & 0xff) | \
+		((((unsigned short)(x)) & 0xff)<<8) )
+#define HTONL(x) ((((x)>>24) & 0xffL) | (((x)>>8) & 0xff00L) | \
+		(((x)<<8) & 0xff0000L) | (((x)<<24) & 0xff000000L))
+#define NTOHL(x) ((((x)>>24) & 0xffL) | (((x)>>8) & 0xff00L) | \
+		(((x)<<8) & 0xff0000L) | (((x)<<24) & 0xff000000L))
+
+#if _WORD_SIZE > 2
+#define htons(x) (_tmp=(x), ((_tmp>>8) & 0xff) | ((_tmp<<8) & 0xff00))
+#define ntohs(x) (_tmp=(x), ((_tmp>>8) & 0xff) | ((_tmp<<8) & 0xff00))
+#define htonl(x) (_tmp_l=(x), ((_tmp_l>>24) & 0xffL) | \
+		((_tmp_l>>8) & 0xff00L) | \
+		((_tmp_l<<8) & 0xff0000L) | ((_tmp_l<<24) & 0xff000000L))
+#define ntohl(x) (_tmp_l=(x), ((_tmp_l>>24) & 0xffL) \
+		| ((_tmp_l>>8) & 0xff00L) | \
+		((_tmp_l<<8) & 0xff0000L) | ((_tmp_l<<24) & 0xff000000L))
+
+#else /* _WORD_SIZE == 2 */
+/* The above macros are too unwieldy for a 16-bit machine. */
+u16_t htons(u16_t x);
+u16_t ntohs(u16_t x);
+u32_t htonl(u32_t x);
+u32_t ntohl(u32_t x);
+#endif /* _WORD_SIZE == 2 */
+
+#endif /* LITTLE_ENDIAN */
+
+#if BIG_ENDIAN
+#define htons(x) (x)
+#define HTONS(x) (x)
+#define ntohs(x) (x)
+#define NTOHS(x) (x)
+#define htonl(x) (x)
+#define HTONL(x) (x)
+#define ntohl(x) (x)
+#define NTOHL(x) (x)
+#endif /* BIG_ENDIAN */
+
+#endif /* _NET__HTON_H */
Index: /trunk/minix/include/net/if.h
===================================================================
--- /trunk/minix/include/net/if.h	(revision 9)
+++ /trunk/minix/include/net/if.h	(revision 9)
@@ -0,0 +1,3 @@
+/*
+net/if.h
+*/
Index: /trunk/minix/include/net/ioctl.h
===================================================================
--- /trunk/minix/include/net/ioctl.h	(revision 9)
+++ /trunk/minix/include/net/ioctl.h	(revision 9)
@@ -0,0 +1,62 @@
+/*	net/ioctl.h - Network ioctl() command codes.	Author: Kees J. Bot
+ *								23 Nov 2002
+ *
+ */
+
+#ifndef _NET__IOCTL_H
+#define _NET__IOCTL_H
+
+#include <minix/ioctl.h>
+
+/* Network ioctls. */
+#define NWIOSETHOPT	_IOW('n', 16, struct nwio_ethopt)
+#define NWIOGETHOPT	_IOR('n', 17, struct nwio_ethopt)
+#define NWIOGETHSTAT	_IOR('n', 18, struct nwio_ethstat)
+
+#define NWIOARPGIP	_IORW('n',20, struct nwio_arp)
+#define NWIOARPGNEXT	_IORW('n',21, struct nwio_arp)
+#define NWIOARPSIP	_IOW ('n',22, struct nwio_arp)
+#define NWIOARPDIP	_IOW ('n',23, struct nwio_arp)
+
+#define NWIOSIPCONF2	_IOW('n', 32, struct nwio_ipconf2)
+#define NWIOSIPCONF	_IOW('n', 32, struct nwio_ipconf)
+#define NWIOGIPCONF2	_IOR('n', 33, struct nwio_ipconf2)
+#define NWIOGIPCONF	_IOR('n', 33, struct nwio_ipconf)
+#define NWIOSIPOPT	_IOW('n', 34, struct nwio_ipopt)
+#define NWIOGIPOPT	_IOR('n', 35, struct nwio_ipopt)
+
+#define NWIOGIPOROUTE	_IORW('n', 40, struct nwio_route)
+#define NWIOSIPOROUTE	_IOW ('n', 41, struct nwio_route)
+#define NWIODIPOROUTE	_IOW ('n', 42, struct nwio_route)
+#define NWIOGIPIROUTE	_IORW('n', 43, struct nwio_route)
+#define NWIOSIPIROUTE	_IOW ('n', 44, struct nwio_route)
+#define NWIODIPIROUTE	_IOW ('n', 45, struct nwio_route)
+
+#define NWIOSTCPCONF	_IOW('n', 48, struct nwio_tcpconf)
+#define NWIOGTCPCONF	_IOR('n', 49, struct nwio_tcpconf)
+#define NWIOTCPCONN	_IOW('n', 50, struct nwio_tcpcl)
+#define NWIOTCPLISTEN	_IOW('n', 51, struct nwio_tcpcl)
+#define NWIOTCPATTACH	_IOW('n', 52, struct nwio_tcpatt)
+#define NWIOTCPSHUTDOWN	_IO ('n', 53)
+#define NWIOSTCPOPT	_IOW('n', 54, struct nwio_tcpopt)
+#define NWIOGTCPOPT	_IOR('n', 55, struct nwio_tcpopt)
+#define NWIOTCPPUSH	_IO ('n', 56)
+#define NWIOTCPLISTENQ	_IOW('n', 57, int)
+#define NWIOGTCPCOOKIE	_IOR('n', 58, struct tcp_cookie)
+#define NWIOTCPACCEPTTO	_IOW('n', 59, struct tcp_cookie)
+#define NWIOTCPGERROR	_IOR('n', 60, int)
+
+#define NWIOSUDPOPT	_IOW('n', 64, struct nwio_udpopt)
+#define NWIOGUDPOPT	_IOR('n', 65, struct nwio_udpopt)
+#define NWIOUDPPEEK	_IOR('n', 66, struct udp_io_hdr)
+
+#define NWIOSPSIPOPT	_IOW('n', 80, struct nwio_psipopt)
+#define NWIOGPSIPOPT	_IOR('n', 81, struct nwio_psipopt)
+
+#define NWIOQUERYPARAM	_IORW('n',96, struct svrqueryparam)
+
+#endif /* _NET__IOCTL_H */
+
+/*
+ * $PchId: ioctl.h,v 1.2 2003/07/25 14:34:03 philip Exp $
+ */
Index: /trunk/minix/include/net/netlib.h
===================================================================
--- /trunk/minix/include/net/netlib.h	(revision 9)
+++ /trunk/minix/include/net/netlib.h	(revision 9)
@@ -0,0 +1,22 @@
+/*
+net/netlib.h
+*/
+
+#ifndef _NET__NETLIB_H_
+#define _NET__NETLIB_H_
+
+#ifndef _ANSI
+#include <ansi.h>
+#endif
+
+_PROTOTYPE (int iruserok, (unsigned long raddr, int superuser,
+		const char *ruser, const char *luser) );
+_PROTOTYPE (int rcmd, (char **ahost, int rport, const char *locuser, 
+		const char *remuser, const char *cmd, int *fd2p) );
+
+#define ETH_DEVICE	"/dev/eth"
+#define IP_DEVICE	"/dev/ip"
+#define TCP_DEVICE	"/dev/tcp"
+#define UDP_DEVICE	"/dev/udp"
+
+#endif /* _NET__NETLIB_H_ */
Index: /trunk/minix/include/netdb.h
===================================================================
--- /trunk/minix/include/netdb.h	(revision 9)
+++ /trunk/minix/include/netdb.h	(revision 9)
@@ -0,0 +1,6 @@
+/*
+netdb.h
+*/
+
+/* Open Group Base Specifications Issue 6 (not complete) */
+#include <net/gen/netdb.h>
Index: /trunk/minix/include/netinet/in.h
===================================================================
--- /trunk/minix/include/netinet/in.h	(revision 9)
+++ /trunk/minix/include/netinet/in.h	(revision 9)
@@ -0,0 +1,83 @@
+/*
+netinet/in.h
+*/
+
+#ifndef _NETINET__IN_H
+#define _NETINET__IN_H
+
+/* Can we include <stdint.h> here or do we need an additional header that is
+ * safe to include?
+ */
+#include <stdint.h>
+
+/* Open Group Base Specifications Issue 6 (not complete) */
+#define    INADDR_ANY              (uint32_t)0x00000000
+#define    INADDR_BROADCAST        (uint32_t)0xFFFFFFFF
+
+#define    IN_LOOPBACKNET          127
+
+#define       IPPORT_RESERVED         1024
+
+typedef uint16_t	in_port_t;
+
+#ifndef _IN_ADDR_T
+#define _IN_ADDR_T
+typedef uint32_t	in_addr_t;
+#endif /* _IN_ADDR_T */
+
+#ifndef _SA_FAMILY_T
+#define _SA_FAMILY_T
+/* Should match corresponding typedef in <sys/socket.h> */
+typedef uint8_t		sa_family_t;
+#endif /* _SA_FAMILY_T */
+
+/* Protocols */
+#define IPPROTO_IP	0	/* Dummy protocol */
+#define IPPROTO_ICMP	1	/* ICMP */
+#define IPPROTO_TCP	6	/* TCP */
+#define IPPROTO_EGP	8	/* exterior gateway protocol */
+#define IPPROTO_UDP	17	/* UDP */
+
+/* setsockopt options at IP level */
+#define IP_ADD_MEMBERSHIP	12
+#define IP_DROP_MEMBERSHIP	13
+
+#ifndef _STRUCT_IN_ADDR
+#define _STRUCT_IN_ADDR
+struct in_addr
+{
+	in_addr_t	s_addr;
+};
+#endif
+
+struct sockaddr_in
+{
+	sa_family_t	sin_family;
+	in_port_t	sin_port;
+	struct in_addr	sin_addr;
+};
+
+struct ip_mreq
+{
+	struct  in_addr imr_multiaddr;
+	struct  in_addr imr_interface;
+};
+
+/* Definitions that are not part of the Open Group Base Specifications */
+#define IN_CLASSA(i)	(((uint32_t)(i) & 0x80000000) == 0)
+#define IN_CLASSA_NET	0xff000000
+#define IN_CLASSA_NSHIFT 24
+
+#define IN_CLASSB(i)	(((uint32_t)(i) & 0xc0000000) == 0x80000000)
+#define IN_CLASSB_NET	0xffff0000
+#define IN_CLASSB_NSHIFT 16
+
+#define IN_CLASSC(i)	(((uint32_t)(i) & 0xe0000000) == 0xc0000000)
+#define IN_CLASSC_NET	0xffffff00
+#define IN_CLASSC_NSHIFT 8
+
+#define IN_CLASSD(i)	(((uint32_t)(i) & 0xf0000000) == 0xe0000000)
+#define IN_CLASSD_NET	0xf0000000
+#define IN_CLASSD_NSHIFT 28
+
+#endif /* _NETINET__IN_H */
Index: /trunk/minix/include/netinet/tcp.h
===================================================================
--- /trunk/minix/include/netinet/tcp.h	(revision 9)
+++ /trunk/minix/include/netinet/tcp.h	(revision 9)
@@ -0,0 +1,5 @@
+/*
+netinet/tcp.h
+*/
+
+#define TCP_NODELAY	0x01	/* Avoid coalescing of small segments */
Index: /trunk/minix/include/pwd.h
===================================================================
--- /trunk/minix/include/pwd.h	(revision 9)
+++ /trunk/minix/include/pwd.h	(revision 9)
@@ -0,0 +1,33 @@
+/* The <pwd.h> header defines the items in the password file. */
+
+#ifndef _PWD_H
+#define _PWD_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+struct passwd {
+  char *pw_name;		/* login name */
+  uid_t pw_uid;			/* uid corresponding to the name */
+  gid_t pw_gid;			/* gid corresponding to the name */
+  char *pw_dir;			/* user's home directory */
+  char *pw_shell;		/* name of the user's shell */
+
+  /* The following members are not defined by POSIX. */
+  char *pw_passwd;		/* password information */
+  char *pw_gecos;		/* just in case you have a GE 645 around */
+};
+
+/* Function Prototypes. */
+_PROTOTYPE( struct passwd *getpwnam, (const char *_name)		);
+_PROTOTYPE( struct passwd *getpwuid, (_mnx_Uid_t _uid)			);
+
+#ifdef _MINIX
+_PROTOTYPE( void endpwent, (void)					);
+_PROTOTYPE( struct passwd *getpwent, (void)				);
+_PROTOTYPE( int setpwent, (void)					);
+_PROTOTYPE( void setpwfile, (const char *_file)				);
+#endif
+
+#endif /* _PWD_H */
Index: /trunk/minix/include/regex.h
===================================================================
--- /trunk/minix/include/regex.h	(revision 9)
+++ /trunk/minix/include/regex.h	(revision 9)
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 1992 Henry Spencer.
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer of the University of Toronto.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)regex.h	8.2 (Berkeley) 1/3/94
+ */
+
+#ifndef _REGEX_H_
+#define	_REGEX_H_
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+/* types */
+typedef off_t regoff_t;
+
+typedef struct {
+	int re_magic;
+	size_t re_nsub;		/* number of parenthesized subexpressions */
+	const char *re_endp;	/* end pointer for REG_PEND */
+	struct re_guts *re_g;	/* none of your business :-) */
+} regex_t;
+
+typedef struct {
+	regoff_t rm_so;		/* start of match */
+	regoff_t rm_eo;		/* end of match */
+} regmatch_t;
+
+/* regcomp() flags */
+#define	REG_BASIC	0000
+#define	REG_EXTENDED	0001
+#define	REG_ICASE	0002
+#define	REG_NOSUB	0004
+#define	REG_NEWLINE	0010
+#define	REG_NOSPEC	0020
+#define	REG_PEND	0040
+#define	REG_DUMP	0200
+
+/* regerror() flags */
+#define	REG_NOMATCH	 1
+#define	REG_BADPAT	 2
+#define	REG_ECOLLATE	 3
+#define	REG_ECTYPE	 4
+#define	REG_EESCAPE	 5
+#define	REG_ESUBREG	 6
+#define	REG_EBRACK	 7
+#define	REG_EPAREN	 8
+#define	REG_EBRACE	 9
+#define	REG_BADBR	10
+#define	REG_ERANGE	11
+#define	REG_ESPACE	12
+#define	REG_BADRPT	13
+#define	REG_EMPTY	14
+#define	REG_ASSERT	15
+#define	REG_INVARG	16
+#define	REG_ATOI	255	/* convert name to number (!) */
+#define	REG_ITOA	0400	/* convert number to name (!) */
+
+/* regexec() flags */
+#define	REG_NOTBOL	00001
+#define	REG_NOTEOL	00002
+#define	REG_STARTEND	00004
+#define	REG_TRACE	00400	/* tracing of execution */
+#define	REG_LARGE	01000	/* force large representation */
+#define	REG_BACKR	02000	/* force use of backref code */
+
+int regcomp(regex_t *, const char *, int);
+size_t regerror(int, const regex_t *, char *, size_t);
+int regexec(const regex_t *, const char *, size_t, regmatch_t [], int);
+void regfree(regex_t *);
+
+#endif /* !_REGEX_H_ */
Index: /trunk/minix/include/regexp.h
===================================================================
--- /trunk/minix/include/regexp.h	(revision 9)
+++ /trunk/minix/include/regexp.h	(revision 9)
@@ -0,0 +1,39 @@
+/* The <regexp.h> header is used by the (V8-compatible) regexp(3) routines. */
+/* NOTE: Obsoleted by the POSIX regex(3) library. */
+
+#ifndef _REGEXP_H
+#define _REGEXP_H
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+#define CHARBITS 0377
+#define NSUBEXP  10
+typedef struct regexp {
+	const char *startp[NSUBEXP];
+	const char *endp[NSUBEXP];
+	char regstart;		/* Internal use only. */
+	char reganch;		/* Internal use only. */
+	char *regmust;		/* Internal use only. */
+	int regmlen;		/* Internal use only. */
+	char program[1];	/* Unwarranted chumminess with compiler. */
+} regexp;
+
+/* Keep these functions away from the POSIX versions. */
+#define regcomp _v8_regcomp
+#define regexec _v8_regexec
+#define regsub _v8_regsub
+#define regerror _v8_regerror
+
+/* Function Prototypes. */
+regexp *regcomp(const char *_exp);
+int regexec(regexp *_prog, const char *_string, int _bolflag);
+void regsub(regexp *_prog, char *_source, char *_dest);
+void regerror(const char *_message) ;
+
+#endif /* _REGEXP_H */
+
+/*
+ * $PchId: regexp.h,v 1.4 1996/04/10 21:43:17 philip Exp $
+ */
Index: /trunk/minix/include/setjmp.h
===================================================================
--- /trunk/minix/include/setjmp.h	(revision 9)
+++ /trunk/minix/include/setjmp.h	(revision 9)
@@ -0,0 +1,152 @@
+/* The <setjmp.h> header relates to the C phenomenon known as setjmp/longjmp.
+ * It is used to escape out of the current situation into a previous one.
+ * A typical example is in an editor, where hitting DEL breaks off the current
+ * command and puts the editor back in the main loop, though care has to be
+ * taken when the DEL occurs while executing a library function, since
+ * some of them are not reentrant.
+ *
+ * POSIX does not require the process signal mask to be saved and restored
+ * during setjmp/longjmp.  However, the current implementation does this
+ * in order to agree with OSF/1 and other BSD derived systems.
+ *
+ * The pair of functions _setjmp/_longjmp may be used when the signal
+ * mask is not to be saved/restored.  These functions are traditional
+ * in BSD systems.
+ *
+ * There are different ways of implementing setjmp/longjmp.  Probably
+ * the best way is to unify it with signal handling.  This is true for the
+ * following reasons:  Both setjmp/longjmp and signal delivery must save 
+ * a context so that it may be restored later.  The jmp_buf necessarily 
+ * contains signal information, namely the signal mask to restore.  Both
+ * longjmp and the return of a signal handler must trap to the operating
+ * system to restore the previous signal mask.  Finally, the jmp_buf
+ * and the sigcontext structure contain the registers to restore.
+ *
+ * Some compilers, namely ACK, will not enregister any variables inside a
+ * function containing a call to setjmp, even if those variables are
+ * explicitly declared as register variables.  Thus for ACK, the
+ * identification of the jmp_buf with a sigcontext structure would cause
+ * unnecessary overhead: the jmp_buf has room for all the registers, but
+ * the only registers that need to be saved are the stack pointer, 
+ * frame pointer, and program counter.
+ *
+ * So, for ACK a jmp_buf is much smaller than a sigcontext structure, and
+ * longjmp does not directly call sigreturn.  Instead, longjmp calls a
+ * front-end function which initializes the appropriate fields of a
+ * sigcontext structure, marks this structure as containing no valid
+ * general purpose registers, and then calls sigreturn.
+ *
+ * The POSIX sigjmp_buf is identical to the jmp_buf in all cases.
+ *
+ * Different compilers have different symbols that they recognize as
+ * setjmp symbols.  ACK recognizes __setjmp, the GNU C compiler
+ * recognizes setjmp and _setjmp, and BCC recognizes all three.
+ * When these symbols occur within a function, the compiler may keep 
+ * all local variables on the stack, avoid certain optimizations, or
+ * pass hidden arguments to the setjmp function.
+ *  
+ * Thus, setjmp implementations vary in two independent ways which may
+ * be identified through the following preprocessor tokens:
+ *
+ * _SETJMP_SYMBOL -- If 0, this means the compiler treats setjmp and _setjmp
+ * specially.  If 1, this means the compiler treats __setjmp specially.
+ *
+ * _SETJMP_SAVES_REGS -- If 1, this means setjmp/longjmp must explicitly
+ * save and restore all registers.  This also implies that a jmp_buf is
+ * different than a sigcontext structure.  If 0, this means that the compiler
+ * will not use register variables within a function that calls one of 
+ * its SETJMP_SYMBOLs. 
+ * 
+ * When _SETJMP_SYMBOL = 1, the implementation has a few dozen bytes of
+ * unnecessary overhead.  This happens in the following manner:  a program uses
+ * _setjmp/_longjmp because it is not interested in saving and restoring the
+ * signal mask. Nevertheless, because _setjmp expands to the general purpose
+ * function __setjmp, code for sigprocmask(2) is linked into the program.  
+ */
+
+#ifndef _SETJMP_H
+#define _SETJMP_H
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+#if !defined(__ACK__) && !defined(__BCC__) && !defined(__GNUC__)
+#define __ACK__
+#endif
+
+#ifdef __ACK__
+#define _SETJMP_SYMBOL 1
+#define _SETJMP_SAVES_REGS 0
+#endif
+#ifdef __BCC__
+#define _SETJMP_SYMBOL 0
+#define _SETJMP_SAVES_REGS 1
+#endif
+#ifdef __GNUC__
+#define _SETJMP_SYMBOL 1
+#define _SETJMP_SAVES_REGS 1
+#endif
+
+/* The jmp_buf data type.  Do not change the order of these fields -- some
+ * C library code refers to these fields by name.  When _SETJMP_SAVES_REGS
+ * is 1, the file <sys/jmp_buf.h> gives the usage of the sixteen registers.
+ */
+typedef struct {
+  int __flags;			/* XXX - long might give better alignment */
+  long __mask;			/* must have size >= sizeof(sigset_t) */
+#if (_SETJMP_SAVES_REGS == 0)
+  _PROTOTYPE(void (*__pc),(void));	/* program counter */
+  void *__sp;			/* stack pointer */
+  void *__lb;			/* local base (ACKspeak for frame pointer) */
+#else
+  void *__regs[16];		/* size is machine dependent */
+#endif
+} jmp_buf[1];
+
+#if (_SETJMP_SYMBOL == 1)
+
+_PROTOTYPE( int __setjmp, (jmp_buf _env, int _savemask)			);
+_PROTOTYPE( void longjmp, (jmp_buf _env, int _val)			);
+_PROTOTYPE(int sigjmp, (jmp_buf _jb, int _retval)			);
+
+#define setjmp(env)	__setjmp((env), 1)
+
+#ifdef _MINIX
+#define _setjmp(env)	__setjmp((env), 0)
+_PROTOTYPE(void _longjmp, (jmp_buf _env, int _val)			);
+#endif
+
+#ifdef _POSIX_SOURCE
+typedef jmp_buf sigjmp_buf;
+#ifdef __GNUC__
+#define siglongjmp longjmp
+#else
+_PROTOTYPE( void siglongjmp, (sigjmp_buf _env, int _val)		);
+#endif
+
+#define sigsetjmp(env, savemask) __setjmp((env), (savemask))
+#endif /* _POSIX_SOURCE */
+
+#endif /* _SETJMP_SYMBOL == 1 */
+
+#if (_SETJMP_SYMBOL == 0)
+
+_PROTOTYPE( int setjmp, (jmp_buf _env)					);
+_PROTOTYPE( void longjmp, (jmp_buf _env, int _val)			);
+
+#ifdef _MINIX
+_PROTOTYPE( int _setjmp, (jmp_buf _env)					);
+_PROTOTYPE( void _longjmp, (jmp_buf _env, int _val)			);
+#endif
+
+#ifdef _POSIX_SOURCE
+#define sigjmp_buf jmp_buf
+_PROTOTYPE( void siglongjmp, (sigjmp_buf _env, int _val)		);
+/* XXX - the name _setjmp is no good - that's why ACK used __setjmp. */
+#define sigsetjmp(env, savemask) ((savemask) ? setjmp(env) : _setjmp(env))
+#endif /* _POSIX_SOURCE */
+
+#endif /* _SETJMP_SYMBOL == 0 */
+
+#endif /* _SETJMP_H */
Index: /trunk/minix/include/sgtty.h
===================================================================
--- /trunk/minix/include/sgtty.h	(revision 9)
+++ /trunk/minix/include/sgtty.h	(revision 9)
@@ -0,0 +1,92 @@
+/* The <sgtty.h> header contains data structures for ioctl(). */
+
+#ifndef _SGTTY_H
+#define _SGTTY_H
+
+/* Should not be used, nor extended. Termios.h is the replacement for
+ * sgtty.h for tty functions, and ioctl replaced code should be moved to
+ * sys/ioctl.h and specific header files in the sys, or minix directory.
+ */
+#include <sys/ioctl.h>		/* Ouch. */
+
+struct sgttyb {
+  char sg_ispeed;		/* input speed */
+  char sg_ospeed;		/* output speed */
+  char sg_erase;		/* erase character */
+  char sg_kill;			/* kill character */
+  int  sg_flags;		/* mode flags */
+};
+
+struct tchars {
+  char t_intrc;			/* SIGINT char */
+  char t_quitc;			/* SIGQUIT char */
+  char t_startc;		/* start output (initially CTRL-Q) */
+  char t_stopc;			/* stop output	(initially CTRL-S) */
+  char t_eofc;			/* EOF (initially CTRL-D) */
+  char t_brkc;			/* input delimiter (like nl) */
+};
+
+#if !_SYSTEM			/* the kernel doesn't want to see the rest */
+
+/* Field names */
+#define XTABS	     0006000	/* do tab expansion */
+#define BITS8        0001400	/* 8 bits/char */
+#define BITS7        0001000	/* 7 bits/char */
+#define BITS6        0000400	/* 6 bits/char */
+#define BITS5        0000000	/* 5 bits/char */
+#define EVENP        0000200	/* even parity */
+#define ODDP         0000100	/* odd parity */
+#define RAW	     0000040	/* enable raw mode */
+#define CRMOD	     0000020	/* map lf to cr + lf */
+#define ECHO	     0000010	/* echo input */
+#define CBREAK	     0000002	/* enable cbreak mode */
+#define COOKED       0000000	/* neither CBREAK nor RAW */
+
+#define DCD          0100000	/* Data Carrier Detect */
+
+/* Line speeds */
+#define B0		   0	/* code for line-hangup */
+#define B110		   1
+#define B300		   3
+#define B1200		  12
+#define B2400		  24
+#define B4800		  48
+#define B9600 		  96
+#define B19200		 192
+#define B38400		 195
+#define B57600		 194
+#define B115200		 193
+
+/* Things Minix supports but not properly */
+/* the divide-by-100 encoding ain't too hot */
+#define ANYP         0000300
+#define B50                0
+#define B75                0
+#define B134               0
+#define B150               0
+#define B200               2
+#define B600               6
+#define B1800             18
+#define B3600             36
+#define B7200             72
+#define EXTA             192
+#define EXTB               0
+
+/* Things Minix doesn't support but are fairly harmless if used */
+#define NLDELAY      0001400
+#define TBDELAY      0006000
+#define CRDELAY      0030000
+#define VTDELAY      0040000
+#define BSDELAY      0100000
+#define ALLDELAY     0177400
+
+/* Copied from termios.h: */
+struct winsize
+{
+	unsigned short	ws_row;		/* rows, in characters */
+	unsigned short	ws_col;		/* columns, in characters */
+	unsigned short	ws_xpixel;	/* horizontal size, pixels */
+	unsigned short	ws_ypixel;	/* vertical size, pixels */
+};
+#endif /* !_SYSTEM */
+#endif /* _SGTTY_H */
Index: /trunk/minix/include/signal.h
===================================================================
--- /trunk/minix/include/signal.h	(revision 9)
+++ /trunk/minix/include/signal.h	(revision 9)
@@ -0,0 +1,124 @@
+/* The <signal.h> header defines all the ANSI and POSIX signals.
+ * MINIX supports all the signals required by POSIX. They are defined below.
+ * Some additional signals are also supported.
+ */
+
+#ifndef _SIGNAL_H
+#define _SIGNAL_H
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+#ifdef _POSIX_SOURCE
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+#endif
+
+/* Here are types that are closely associated with signal handling. */
+typedef int sig_atomic_t;
+
+#ifdef _POSIX_SOURCE
+#ifndef _SIGSET_T
+#define _SIGSET_T
+typedef unsigned long sigset_t;
+#endif
+#endif
+
+/* Regular signals. */
+#define SIGHUP             1	/* hangup */
+#define SIGINT             2	/* interrupt (DEL) */
+#define SIGQUIT            3	/* quit (ASCII FS) */
+#define SIGILL             4	/* illegal instruction */
+#define SIGTRAP            5	/* trace trap (not reset when caught) */
+#define SIGABRT            6	/* IOT instruction */
+#define SIGBUS             7	/* bus error */
+#define SIGFPE             8	/* floating point exception */
+#define SIGKILL            9	/* kill (cannot be caught or ignored) */
+#define SIGUSR1           10	/* user defined signal # 1 */
+#define SIGSEGV           11	/* segmentation violation */
+#define SIGUSR2           12	/* user defined signal # 2 */
+#define SIGPIPE           13	/* write on a pipe with no one to read it */
+#define SIGALRM           14	/* alarm clock */
+#define SIGTERM           15	/* software termination signal from kill */
+#define SIGEMT		  16	/* EMT instruction */
+#define SIGCHLD           17	/* child process terminated or stopped */
+#define SIGWINCH    	  21	/* window size has changed */
+
+/* POSIX requires the following signals to be defined, even if they are
+ * not supported.  Here are the definitions, but they are not supported.
+ */
+#define SIGCONT           18	/* continue if stopped */
+#define SIGSTOP           19	/* stop signal */
+#define SIGTSTP           20	/* interactive stop signal */
+#define SIGTTIN           22	/* background process wants to read */
+#define SIGTTOU           23	/* background process wants to write */
+
+#define _NSIG             23	/* number of signals used */
+
+#ifdef _MINIX
+#define SIGIOT             SIGABRT /* for people who speak PDP-11 */
+
+/* MINIX specific signals. These signals are not used by user proceses, 
+ * but meant to inform system processes, like the PM, about system events.
+ */
+#define SIGKMESS   	  29	/* new kernel message */
+#define SIGKSIG    	  30	/* kernel signal pending */
+#define SIGKSTOP    	  31	/* kernel shutting down */
+
+#endif
+
+/* The sighandler_t type is not allowed unless _POSIX_SOURCE is defined. */
+typedef void _PROTOTYPE( (*__sighandler_t), (int) );
+
+/* Macros used as function pointers. */
+#define SIG_ERR    ((__sighandler_t) -1)	/* error return */
+#define SIG_DFL	   ((__sighandler_t)  0)	/* default signal handling */
+#define SIG_IGN	   ((__sighandler_t)  1)	/* ignore signal */
+#define SIG_HOLD   ((__sighandler_t)  2)	/* block signal */
+#define SIG_CATCH  ((__sighandler_t)  3)	/* catch signal */
+#define SIG_MESS   ((__sighandler_t)  4)	/* pass as message (MINIX) */
+
+#ifdef _POSIX_SOURCE
+struct sigaction {
+  __sighandler_t sa_handler;	/* SIG_DFL, SIG_IGN, or pointer to function */
+  sigset_t sa_mask;		/* signals to be blocked during handler */
+  int sa_flags;			/* special flags */
+};
+
+/* Fields for sa_flags. */
+#define SA_ONSTACK   0x0001	/* deliver signal on alternate stack */
+#define SA_RESETHAND 0x0002	/* reset signal handler when signal caught */
+#define SA_NODEFER   0x0004	/* don't block signal while catching it */
+#define SA_RESTART   0x0008	/* automatic system call restart */
+#define SA_SIGINFO   0x0010	/* extended signal handling */
+#define SA_NOCLDWAIT 0x0020	/* don't create zombies */
+#define SA_NOCLDSTOP 0x0040	/* don't receive SIGCHLD when child stops */
+
+/* POSIX requires these values for use with sigprocmask(2). */
+#define SIG_BLOCK          0	/* for blocking signals */
+#define SIG_UNBLOCK        1	/* for unblocking signals */
+#define SIG_SETMASK        2	/* for setting the signal mask */
+#define SIG_INQUIRE        4	/* for internal use only */
+#endif	/* _POSIX_SOURCE */
+
+/* POSIX and ANSI function prototypes. */
+_PROTOTYPE( int raise, (int _sig)					);
+_PROTOTYPE( __sighandler_t signal, (int _sig, __sighandler_t _func)	);
+
+#ifdef _POSIX_SOURCE
+_PROTOTYPE( int kill, (pid_t _pid, int _sig)				);
+_PROTOTYPE( int sigaction,
+    (int _sig, const struct sigaction *_act, struct sigaction *_oact)	);
+_PROTOTYPE( int sigaddset, (sigset_t *_set, int _sig)			);
+_PROTOTYPE( int sigdelset, (sigset_t *_set, int _sig)			);
+_PROTOTYPE( int sigemptyset, (sigset_t *_set)				);
+_PROTOTYPE( int sigfillset, (sigset_t *_set)				);
+_PROTOTYPE( int sigismember, (const sigset_t *_set, int _sig)		);
+_PROTOTYPE( int sigpending, (sigset_t *_set)				);
+_PROTOTYPE( int sigprocmask,
+	    (int _how, const sigset_t *_set, sigset_t *_oset)		);
+_PROTOTYPE( int sigsuspend, (const sigset_t *_sigmask)			);
+#endif
+
+#endif /* _SIGNAL_H */
Index: /trunk/minix/include/stdarg.h
===================================================================
--- /trunk/minix/include/stdarg.h	(revision 9)
+++ /trunk/minix/include/stdarg.h	(revision 9)
@@ -0,0 +1,87 @@
+/* The <stdarg.h> header is ANSI's way to handle variable numbers of params.
+ * Some programming languages require a function that is declared with n
+ * parameters to be called with n parameters.  C does not.  A function may
+ * called with more parameters than it is declared with.  The well-known
+ * printf function, for example, may have arbitrarily many parameters.
+ * The question arises how one can access all the parameters in a portable
+ * way.  The C standard defines three macros that programs can use to
+ * advance through the parameter list.  The definition of these macros for
+ * MINIX are given in this file.  The three macros are:
+ *
+ *	va_start(ap, parmN)	prepare to access parameters
+ *	va_arg(ap, type)	get next parameter value and type
+ *	va_end(ap)		access is finished
+ *
+ * Ken Thompson's famous line from V6 UNIX is equally applicable to this file:
+ *
+ *	"You are not expected to understand this"
+ *
+ */
+
+#ifndef _STDARG_H
+#define _STDARG_H
+
+#ifdef __GNUC__
+/* The GNU C-compiler uses its own, but similar varargs mechanism. */
+
+typedef char *va_list;
+
+/* Amount of space required in an argument list for an arg of type TYPE.
+ * TYPE may alternatively be an expression whose type is used.
+ */
+
+#define __va_rounded_size(TYPE)  \
+  (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
+
+#if __GNUC__ < 2
+
+#ifndef __sparc__
+#define va_start(AP, LASTARG)                                           \
+ (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
+#else
+#define va_start(AP, LASTARG)                                           \
+ (__builtin_saveregs (),                                                \
+  AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
+#endif
+
+void va_end (va_list);          /* Defined in gnulib */
+#define va_end(AP)
+
+#define va_arg(AP, TYPE)                                                \
+ (AP += __va_rounded_size (TYPE),                                       \
+  *((TYPE *) (AP - __va_rounded_size (TYPE))))
+
+#else	/* __GNUC__ >= 2 */
+
+#ifndef __sparc__
+#define va_start(AP, LASTARG) 						\
+ (AP = ((char *) __builtin_next_arg ()))
+#else
+#define va_start(AP, LASTARG)					\
+  (__builtin_saveregs (), AP = ((char *) __builtin_next_arg ()))
+#endif
+
+void va_end (va_list);		/* Defined in libgcc.a */
+#define va_end(AP)
+
+#define va_arg(AP, TYPE)						\
+ (AP = ((char *) (AP)) += __va_rounded_size (TYPE),			\
+  *((TYPE *) ((char *) (AP) - __va_rounded_size (TYPE))))
+
+#endif	/* __GNUC__ >= 2 */
+
+#else	/* not __GNUC__ */
+
+typedef char *va_list;
+
+#define __vasz(x)		((sizeof(x)+sizeof(int)-1) & ~(sizeof(int) -1))
+
+#define va_start(ap, parmN)	((ap) = (va_list)&parmN + __vasz(parmN))
+#define va_arg(ap, type)      \
+  (*((type *)((va_list)((ap) = (void *)((va_list)(ap) + __vasz(type))) \
+						    - __vasz(type))))
+#define va_end(ap)
+
+#endif /* __GNUC__ */
+
+#endif /* _STDARG_H */
Index: /trunk/minix/include/stddef.h
===================================================================
--- /trunk/minix/include/stddef.h	(revision 9)
+++ /trunk/minix/include/stddef.h	(revision 9)
@@ -0,0 +1,27 @@
+/* The <stddef.h> header defines certain commonly used macros. */
+
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+#define NULL   ((void *)0)
+
+/* The following is not portable, but the compiler accepts it. */
+#define offsetof(type, ident)	((size_t) (unsigned long) &((type *)0)->ident)
+
+#if _EM_PSIZE == _EM_WSIZE
+typedef int ptrdiff_t;		/* result of subtracting two pointers */
+#else	/* _EM_PSIZE == _EM_LSIZE */
+typedef long ptrdiff_t;
+#endif
+
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef unsigned int size_t;	/* type returned by sizeof */
+#endif
+
+#ifndef _WCHAR_T
+#define _WCHAR_T
+typedef char wchar_t;		/* type expanded character set */
+#endif
+
+#endif /* _STDDEF_H */
Index: /trunk/minix/include/stdint.h
===================================================================
--- /trunk/minix/include/stdint.h	(revision 9)
+++ /trunk/minix/include/stdint.h	(revision 9)
@@ -0,0 +1,222 @@
+/*	stdint.h - Standard sized integer types.	Author: Kees J. Bot
+ *								4 Oct 2003
+ *
+ * Assumption:	Long is the biggest type.
+ * Bug:		C99 requires a 64 bit type, and long isn't 64 bits yet, and
+ *		will never be 64 bits under 16-bits Minix.
+ * Omission:	Limits like PTR_DIFF_MAX not here yet, maybe <limits.h>?
+ */
+
+#ifndef _STDINT_H
+#define _STDINT_H
+
+#ifndef _MINIX__TYPES_H
+#include <sys/types.h>
+#endif
+#include <minix/sys_config.h>
+
+#if (_WORD_SIZE != 2 && _WORD_SIZE != 4) || \
+	(_PTR_SIZE != _WORD_SIZE && _PTR_SIZE != 2*_WORD_SIZE)
+#error Odd word or pointer sizes
+#endif
+
+/* Integer types of precisely the given bitsize. */
+typedef i8_t	int8_t;
+typedef i16_t	int16_t;
+typedef i32_t	int32_t;
+#if _WORD_SIZE > 2 && __L64
+typedef i64_t	int64_t;
+#endif
+
+typedef u8_t	uint8_t;
+typedef u16_t	uint16_t;
+typedef u32_t	uint32_t;
+#if _WORD_SIZE > 2 && __L64
+typedef u64_t	uint64_t;
+#endif
+
+/* Integer types of at least the given bitsize. */
+typedef int8_t		int_least8_t;
+typedef int16_t		int_least16_t;
+typedef int32_t		int_least32_t;
+#if _WORD_SIZE > 2 && __L64
+typedef int64_t		int_least64_t;
+#endif
+
+typedef uint8_t		uint_least8_t;
+typedef uint16_t	uint_least16_t;
+typedef uint32_t	uint_least32_t;
+#if _WORD_SIZE > 2 && __L64
+typedef uint64_t	uint_least64_t;
+#endif
+
+/* Fast integer types of at least the given bitsize. */
+#if _WORD_SIZE == 2
+typedef int16_t		int_fast8_t;
+typedef int16_t		int_fast16_t;
+#else
+typedef int32_t		int_fast8_t;
+typedef int32_t		int_fast16_t;
+#endif
+typedef int32_t		int_fast32_t;
+#if _WORD_SIZE > 2 && __L64
+typedef int64_t		int_fast64_t;
+#endif
+
+#if _WORD_SIZE == 2
+typedef uint16_t	uint_fast8_t;
+typedef uint16_t	uint_fast16_t;
+#else
+typedef uint32_t	uint_fast8_t;
+typedef uint32_t	uint_fast16_t;
+#endif
+typedef uint32_t	uint_fast32_t;
+#if _WORD_SIZE > 2 && __L64
+typedef uint64_t	uint_fast64_t;
+#endif
+
+/* Integer type capable of holding a pointer and the largest integer type. */
+#if _PTR_SIZE == _WORD_SIZE
+typedef int		intptr_t;
+typedef unsigned	uintptr_t;
+#elif _PTR_SIZE == 2*_WORD_SIZE
+typedef long		intptr_t;
+typedef unsigned long	uintptr_t;
+#endif
+typedef long		intmax_t;
+typedef unsigned long	uintmax_t;
+
+#if !__cplusplus || defined(__STDC_LIMIT_MACROS)
+#ifndef _LIMITS_H
+#include <limits.h>
+#endif
+
+/* Range definitions for each of the above types conform <limits.h>. */
+#define INT8_MIN		(-INT8_MAX-1)
+#define INT16_MIN		(-INT16_MAX-1)
+#define INT32_MIN		(-INT32_MAX-1)
+#if _WORD_SIZE > 2 && __L64
+#define INT64_MIN		(-INT64_MAX-1)
+#endif
+
+#define INT8_MAX		127
+#define INT16_MAX		32767
+#define INT32_MAX		2147483647
+#if _WORD_SIZE > 2 && __L64
+#define INT64_MAX		9223372036854775807
+#endif
+
+#define UINT8_MAX		255
+#define UINT16_MAX		65535
+#define UINT32_MAX		4294967295
+#if _WORD_SIZE > 2 && __L64
+#define UINT64_MAX		18446744073709551615
+#endif
+
+#define INT_LEAST8_MIN		INT8_MIN
+#define INT_LEAST16_MIN		INT16_MIN
+#define INT_LEAST32_MIN		INT32_MIN
+#if _WORD_SIZE > 2 && __L64
+#define INT_LEAST64_MIN		INT64_MIN
+#endif
+
+#define INT_LEAST8_MAX		INT8_MAX
+#define INT_LEAST16_MAX		INT16_MAX
+#define INT_LEAST32_MAX		INT32_MAX
+#if _WORD_SIZE > 2 && __L64
+#define INT_LEAST64_MAX		INT64_MAX
+#endif
+
+#define UINT_LEAST8_MAX		UINT8_MAX
+#define UINT_LEAST16_MAX	UINT16_MAX
+#define UINT_LEAST32_MAX	UINT32_MAX
+#if _WORD_SIZE > 2 && __L64
+#define UINT_LEAST64_MAX	UINT64_MAX
+#endif
+
+#define INT_FAST8_MIN		(-INT_FAST8_MAX-1)
+#define INT_FAST16_MIN		(-INT_FAST16_MAX-1)
+#define INT_FAST32_MIN		INT32_MIN
+#if _WORD_SIZE > 2 && __L64
+#define INT_FAST64_MIN		INT64_MIN
+#endif
+
+#if _WORD_SIZE == 2
+#define INT_FAST8_MAX		INT16_MAX
+#define INT_FAST16_MAX		INT16_MAX
+#else
+#define INT_FAST8_MAX		INT32_MAX
+#define INT_FAST16_MAX		INT32_MAX
+#endif
+#define INT_FAST32_MAX		INT32_MAX
+#if _WORD_SIZE > 2 && __L64
+#define INT_FAST64_MAX		INT64_MAX
+#endif
+
+#if _WORD_SIZE == 2
+#define UINT_FAST8_MAX		UINT16_MAX
+#define UINT_FAST16_MAX		UINT16_MAX
+#else
+#define UINT_FAST8_MAX		UINT32_MAX
+#define UINT_FAST16_MAX		UINT32_MAX
+#endif
+#define UINT_FAST32_MAX		UINT32_MAX
+#if _WORD_SIZE > 2 && __L64
+#define UINT_FAST64_MAX		UINT64_MAX
+#endif
+
+#if _PTR_SIZE == _WORD_SIZE
+#define INTPTR_MIN		INT_MIN
+#define INTPTR_MAX		INT_MAX
+#define UINTPTR_MAX		UINT_MAX
+#elif _PTR_SIZE > _WORD_SIZE
+#define INTPTR_MIN		LONG_MIN
+#define INTPTR_MAX		LONG_MAX
+#define UINTPTR_MAX		ULONG_MAX
+#endif
+#define INTMAX_MIN		LONG_MIN
+#define INTMAX_MAX		LONG_MAX
+#define UINTMAX_MAX		ULONG_MAX
+
+#endif /* !__cplusplus || __STDC_LIMIT_MACROS */
+
+#ifndef __CONCAT
+#define __CONCAT(x,y)	x ## y
+#endif
+
+/* Constants of the proper type. */
+#define INT8_C(c)	c
+#define INT16_C(c)	c
+#if _WORD_SIZE == 2
+#define INT32_C(c)	__CONCAT(c,l)
+#else
+#define INT32_C(c)	c
+#endif
+#if _WORD_SIZE > 2 && __L64
+#define INT64_C(c)	__CONCAT(c,l)
+#endif
+
+#define UINT8_C(c)	__CONCAT(c,u)
+#define UINT16_C(c)	__CONCAT(c,u)
+#if _WORD_SIZE == 2
+#define UINT32_C(c)	__CONCAT(c,lu)
+#else
+#define UINT32_C(c)	__CONCAT(c,u)
+#endif
+#if _WORD_SIZE > 2 && __L64
+#define UINT64_C(c)	__CONCAT(c,lu)
+#endif
+
+#if _WORD_SIZE == 2 || !__L64
+#define INTMAX_C(c)	INT32_C(c)
+#define UINTMAX_C(c)	UINT32_C(c)
+#else
+#define INTMAX_C(c)	INT64_C(c)
+#define UINTMAX_C(c)	UINT64_C(c)
+#endif
+
+#endif /* _STDINT_H */
+
+/*
+ * $PchId: stdint.h,v 1.2 2005/01/27 17:32:00 philip Exp $
+ */
Index: /trunk/minix/include/stdio.h
===================================================================
--- /trunk/minix/include/stdio.h	(revision 9)
+++ /trunk/minix/include/stdio.h	(revision 9)
@@ -0,0 +1,156 @@
+/*
+ * stdio.h - input/output definitions
+ *
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/include/stdio.h,v 1.2 2005/09/01 13:07:08 beng Exp $ */
+
+#ifndef _STDIO_H
+#define	_STDIO_H
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+/*
+ * Focus point of all stdio activity.
+ */
+typedef struct __iobuf {
+	int		_count;
+	int		_fd;
+	int		_flags;
+	int		_bufsiz;
+	unsigned char	*_buf;
+	unsigned char	*_ptr;
+} FILE;
+
+#define	_IOFBF		0x000
+#define	_IOREAD		0x001
+#define	_IOWRITE	0x002
+#define	_IONBF		0x004
+#define	_IOMYBUF	0x008
+#define	_IOEOF		0x010
+#define	_IOERR		0x020
+#define	_IOLBF		0x040
+#define	_IOREADING	0x080
+#define	_IOWRITING	0x100
+#define	_IOAPPEND	0x200
+#define _IOFIFO		0x400
+
+/* The following definitions are also in <unistd.h>. They should not
+ * conflict.
+ */
+#define	SEEK_SET	0
+#define	SEEK_CUR	1
+#define	SEEK_END	2
+
+#define	stdin		(&__stdin)
+#define	stdout		(&__stdout)
+#define	stderr		(&__stderr)
+
+#define	BUFSIZ		1024
+#define	NULL		((void *)0)
+#define	EOF		(-1)
+
+#define	FOPEN_MAX	20
+
+#include <sys/dir.h>
+#define	FILENAME_MAX	DIRSIZ
+
+#define	TMP_MAX		999
+#define	L_tmpnam	(sizeof("/tmp/") + FILENAME_MAX)
+#define __STDIO_VA_LIST__	void *
+
+typedef long int	fpos_t;
+
+#ifndef _SIZE_T
+#define	_SIZE_T
+typedef unsigned int	size_t;		/* type returned by sizeof */
+#endif /* _SIZE_T */
+
+extern FILE	*__iotab[FOPEN_MAX];
+extern FILE	__stdin, __stdout, __stderr;
+
+_PROTOTYPE( int remove, (const char *_filename)				);
+_PROTOTYPE( int rename, (const char *_old, const char *_new)		);
+_PROTOTYPE( FILE *tmpfile, (void)					);
+_PROTOTYPE( char *tmpnam, (char *_s)					);
+_PROTOTYPE( int fclose, (FILE *_stream)					);
+_PROTOTYPE( int fflush, (FILE *_stream)					);
+_PROTOTYPE( FILE *fopen, (const char *_filename, const char *_mode)	);
+_PROTOTYPE( FILE *freopen,
+	    (const char *_filename, const char *_mode, FILE *_stream)	);
+_PROTOTYPE( void setbuf, (FILE *_stream, char *_buf)			);
+_PROTOTYPE( int setvbuf,
+		(FILE *_stream, char *_buf, int _mode, size_t _size)	);
+_PROTOTYPE( int fprintf, (FILE *_stream, const char *_format, ...)	);
+_PROTOTYPE( int printf, (const char *_format, ...)			);
+_PROTOTYPE( int sprintf, (char *_s, const char *_format, ...)		);
+_PROTOTYPE( int vfprintf,
+		(FILE *_stream, const char *_format, char *_arg)	);
+_PROTOTYPE( int vprintf, (const char *_format, char *_arg)		);
+_PROTOTYPE( int vsprintf, (char *_s, const char *_format, char *_arg)	);
+_PROTOTYPE( int fscanf, (FILE *_stream, const char *_format, ...)	);
+_PROTOTYPE( int scanf, (const char *_format, ...)			);
+_PROTOTYPE( int sscanf, (const char *_s, const char *_format, ...)	);
+#define vfscanf _doscan
+_PROTOTYPE( int vfscanf, (FILE *_stream, const char *_format, char *_arg));
+_PROTOTYPE( int vscanf, (const char *_format, char *_arg)		);
+_PROTOTYPE( int vsscanf, (const char *_s, const char *_format, char *_arg));
+_PROTOTYPE( int fgetc, (FILE *_stream)					);
+_PROTOTYPE( char *fgets, (char *_s, int _n, FILE *_stream)		);
+_PROTOTYPE( int fputc, (int _c, FILE *_stream)				);
+_PROTOTYPE( int fputs, (const char *_s, FILE *_stream)			);
+_PROTOTYPE( int getc, (FILE *_stream)					);
+_PROTOTYPE( int getchar, (void)						);
+_PROTOTYPE( char *gets, (char *_s)					);
+_PROTOTYPE( int putc, (int _c, FILE *_stream)				);
+_PROTOTYPE( int putchar, (int _c)					);
+_PROTOTYPE( int puts, (const char *_s)					);
+_PROTOTYPE( int ungetc, (int _c, FILE *_stream)				);
+_PROTOTYPE( size_t fread,
+	    (void *_ptr, size_t _size, size_t _nmemb, FILE *_stream)	);
+_PROTOTYPE( size_t fwrite,
+	(const void *_ptr, size_t _size, size_t _nmemb, FILE *_stream)	);
+_PROTOTYPE( int fgetpos, (FILE *_stream, fpos_t *_pos)			);
+_PROTOTYPE( int fseek, (FILE *_stream, long _offset, int _whence)	);
+_PROTOTYPE( int fsetpos, (FILE *_stream, fpos_t *_pos)			);
+_PROTOTYPE( long ftell, (FILE *_stream)					);
+_PROTOTYPE( void rewind, (FILE *_stream)				);
+_PROTOTYPE( void clearerr, (FILE *_stream)				);
+_PROTOTYPE( int feof, (FILE *_stream)					);
+_PROTOTYPE( int ferror, (FILE *_stream)					);
+_PROTOTYPE( void perror, (const char *_s)				);
+_PROTOTYPE( int __fillbuf, (FILE *_stream)				);
+_PROTOTYPE( int __flushbuf, (int _c, FILE *_stream)			);
+
+#define	getchar()	getc(stdin)
+#define	putchar(c)	putc(c,stdout)
+#define	getc(p)		(--(p)->_count >= 0 ? (int) (*(p)->_ptr++) : \
+				__fillbuf(p))
+#define	putc(c, p)	(--(p)->_count >= 0 ? \
+			 (int) (*(p)->_ptr++ = (c)) : \
+			 __flushbuf((c),(p)))
+
+#define	feof(p)		(((p)->_flags & _IOEOF) != 0)
+#define	ferror(p)	(((p)->_flags & _IOERR) != 0)
+#define clearerr(p)     ((p)->_flags &= ~(_IOERR|_IOEOF))
+
+#ifdef _POSIX_SOURCE
+_PROTOTYPE( int fileno, (FILE *_stream)					);
+_PROTOTYPE (FILE *fdopen, (int _fildes, const char *_types) );
+#define	fileno(stream)		((stream)->_fd)
+#define L_ctermid 255	/* required by POSIX */
+#define L_cuserid 255	/* required by POSIX */
+#endif
+
+#ifdef _MINIX
+_PROTOTYPE(FILE *popen, (const char *_command, const char *_type));
+_PROTOTYPE(int pclose, (FILE *_stream));
+_PROTOTYPE(int snprintf, (char *_s, size_t _n, const char *_format, ...));
+_PROTOTYPE(int vsnprintf, (char *_s, size_t _n, const char *_format,
+							char *_arg)	);
+#endif
+
+#endif /* _STDIO_H */
Index: /trunk/minix/include/stdlib.h
===================================================================
--- /trunk/minix/include/stdlib.h	(revision 9)
+++ /trunk/minix/include/stdlib.h	(revision 9)
@@ -0,0 +1,89 @@
+/* The <stdlib.h> header defines certain common macros, types, and functions.*/
+
+#ifndef _STDLIB_H
+#define _STDLIB_H
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+/* The macros are NULL, EXIT_FAILURE, EXIT_SUCCESS, RAND_MAX, and MB_CUR_MAX.*/
+#define NULL    ((void *)0)
+
+#define EXIT_FAILURE       1	/* standard error return using exit() */
+#define EXIT_SUCCESS       0	/* successful return using exit() */
+#define RAND_MAX       32767	/* largest value generated by rand() */
+#define MB_CUR_MAX         1	/* max value of multibyte character in MINIX */
+
+typedef struct { int quot, rem; } div_t;
+typedef struct { long quot, rem; } ldiv_t;
+
+/* The types are size_t, wchar_t, div_t, and ldiv_t. */
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef unsigned int size_t;	/* type returned by sizeof */
+#endif
+
+#ifndef _WCHAR_T
+#define _WCHAR_T
+typedef char wchar_t;		/* type expanded character set */
+#endif
+
+/* Function Prototypes. */
+_PROTOTYPE( void abort, (void)						);
+_PROTOTYPE( int abs, (int _j)						);
+_PROTOTYPE( int atexit, (void (*_func)(void))				);
+_PROTOTYPE( double atof, (const char *_nptr)				);
+_PROTOTYPE( int atoi, (const char *_nptr)				);
+_PROTOTYPE( long atol, (const char *_nptr)				);
+_PROTOTYPE( void *calloc, (size_t _nmemb, size_t _size)			);
+_PROTOTYPE( div_t div, (int _numer, int _denom)				);
+_PROTOTYPE( void exit, (int _status)					);
+_PROTOTYPE( void free, (void *_ptr)					);
+_PROTOTYPE( char *getenv, (const char *_name)				);
+_PROTOTYPE( long labs, (long _j)					);
+_PROTOTYPE( ldiv_t ldiv, (long _numer, long _denom)			);
+_PROTOTYPE( void *malloc, (size_t _size)				);
+_PROTOTYPE( int mblen, (const char *_s, size_t _n)			);
+_PROTOTYPE( size_t mbstowcs, (wchar_t *_pwcs, const char *_s, size_t _n));
+_PROTOTYPE( int mbtowc, (wchar_t *_pwc, const char *_s, size_t _n)	);
+_PROTOTYPE( int rand, (void)						);
+_PROTOTYPE( void *realloc, (void *_ptr, size_t _size)			);
+_PROTOTYPE( void srand, (unsigned int _seed)				);
+_PROTOTYPE( double strtod, (const char *_nptr, char **_endptr)		);
+_PROTOTYPE( long strtol, (const char *_nptr, char **_endptr, int _base)	);
+_PROTOTYPE( int system, (const char *_string)				);
+_PROTOTYPE( size_t wcstombs, (char *_s, const wchar_t *_pwcs, size_t _n));
+_PROTOTYPE( int wctomb, (char *_s, wchar_t _wchar)			);
+_PROTOTYPE( void *bsearch, (const void *_key, const void *_base, 
+	size_t _nmemb, size_t _size, 
+	int (*compar) (const void *, const void *))			);
+_PROTOTYPE( void qsort, (void *_base, size_t _nmemb, size_t _size,
+	int (*compar) (const void *, const void *))			);
+_PROTOTYPE( unsigned long int strtoul,
+			(const char *_nptr, char **_endptr, int _base)	);
+
+#ifdef _POSIX_SOURCE
+/* Open Group Base Specifications Issue 6 */
+_PROTOTYPE( int mkstemp, (char *_fmt)					);
+_PROTOTYPE( char *initstate, (unsigned _seed, char *_state,
+							size_t _size)	);
+_PROTOTYPE( long random, (void)						);
+_PROTOTYPE( char *setstate, (const char *state)				);
+_PROTOTYPE( void srandom, (unsigned seed)				);
+_PROTOTYPE( int getloadavg, (double *, int)				);
+#endif
+
+#ifdef _MINIX
+_PROTOTYPE( int putenv, (char *_name)					);
+_PROTOTYPE( int setenv, (const char *name, const char *val, const int f));
+
+/* According to POSIX, getopt should be in unistd.h. What do we do with
+ * this?
+ */
+_PROTOTYPE(int getopt, (int _argc, char * const _argv[], const char *_opts));
+extern char *optarg;
+extern int optind, opterr, optopt;
+#endif /* _MINIX */
+
+#endif /* STDLIB_H */
Index: /trunk/minix/include/string.h
===================================================================
--- /trunk/minix/include/string.h	(revision 9)
+++ /trunk/minix/include/string.h	(revision 9)
@@ -0,0 +1,65 @@
+/* The <string.h> header contains prototypes for the string handling 
+ * functions.
+ */
+
+#ifndef _STRING_H
+#define _STRING_H
+
+#define NULL    ((void *)0)
+
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef unsigned int size_t;	/* type returned by sizeof */
+#endif /*_SIZE_T */
+
+/* Function Prototypes. */
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+_PROTOTYPE( void *memchr, (const void *_s, int _c, size_t _n)		);
+_PROTOTYPE( int memcmp, (const void *_s1, const void *_s2, size_t _n)	);
+_PROTOTYPE( void *memcpy, (void *_s1, const void *_s2, size_t _n)	);
+_PROTOTYPE( void *memmove, (void *_s1, const void *_s2, size_t _n)	);
+_PROTOTYPE( void *memset, (void *_s, int _c, size_t _n)			);
+_PROTOTYPE( char *strcat, (char *_s1, const char *_s2)			);
+_PROTOTYPE( char *strchr, (const char *_s, int _c)			);
+_PROTOTYPE( int strncmp, (const char *_s1, const char *_s2, size_t _n)	);
+_PROTOTYPE( int strcmp, (const char *_s1, const char *_s2)		);
+_PROTOTYPE( int strcoll, (const char *_s1, const char *_s2)		);
+_PROTOTYPE( char *strcpy, (char *_s1, const char *_s2)			);
+_PROTOTYPE( size_t strcspn, (const char *_s1, const char *_s2)		);
+_PROTOTYPE( char *strerror, (int _errnum)				);
+_PROTOTYPE( size_t strlen, (const char *_s)				);
+_PROTOTYPE( char *strncat, (char *_s1, const char *_s2, size_t _n)	);
+_PROTOTYPE( char *strncpy, (char *_s1, const char *_s2, size_t _n)	);
+_PROTOTYPE( char *strpbrk, (const char *_s1, const char *_s2)		);
+_PROTOTYPE( char *strrchr, (const char *_s, int _c)			);
+_PROTOTYPE( size_t strspn, (const char *_s1, const char *_s2)		);
+_PROTOTYPE( char *strstr, (const char *_s1, const char *_s2)		);
+_PROTOTYPE( char *strtok, (char *_s1, const char *_s2)			);
+_PROTOTYPE( size_t strxfrm, (char *_s1, const char *_s2, size_t _n)	);
+
+#ifdef _POSIX_SOURCE
+/* Open Group Base Specifications Issue 6 (not complete) */
+ char *strdup(const char *_s1);
+#endif
+
+#ifdef _MINIX
+/* For backward compatibility. */
+_PROTOTYPE( char *index, (const char *_s, int _charwanted)		);
+_PROTOTYPE( char *rindex, (const char *_s, int _charwanted)		);
+_PROTOTYPE( void bcopy, (const void *_src, void *_dst, size_t _length)	);
+_PROTOTYPE( int bcmp, (const void *_s1, const void *_s2, size_t _length));
+_PROTOTYPE( void bzero, (void *_dst, size_t _length)			);
+_PROTOTYPE( void *memccpy, (char *_dst, const char *_src, int _ucharstop,
+						    size_t _size)	);
+
+/* Misc. extra functions */
+_PROTOTYPE( int strcasecmp, (const char *_s1, const char *_s2)		);
+_PROTOTYPE( int strncasecmp, (const char *_s1, const char *_s2,
+							size_t _len)	);
+_PROTOTYPE( size_t strnlen, (const char *_s, size_t _n)			);
+#endif
+
+#endif /* _STRING_H */
Index: /trunk/minix/include/strings.h
===================================================================
--- /trunk/minix/include/strings.h	(revision 9)
+++ /trunk/minix/include/strings.h	(revision 9)
@@ -0,0 +1,10 @@
+/*
+strings.h
+*/
+
+/* Open Group Base Specifications Issue 6 (not complete) */
+_PROTOTYPE( char *index, (const char *_s, int _charwanted)		);
+_PROTOTYPE( int strcasecmp, (const char *_s1, const char *_s2)		);
+_PROTOTYPE( int strncasecmp, (const char *_s1, const char *_s2,
+							size_t _len)	);
+_PROTOTYPE( int ffs, (int i)						);
Index: /trunk/minix/include/sys/asynchio.h
===================================================================
--- /trunk/minix/include/sys/asynchio.h	(revision 9)
+++ /trunk/minix/include/sys/asynchio.h	(revision 9)
@@ -0,0 +1,39 @@
+/*	asynchio.h - Asynchronous I/O			Author: Kees J. Bot
+ *								26 Jan 1995
+ * This is just a fake async I/O library to be used for programs
+ * written for Minix-vmd that must also run under standard Minix.
+ * This limits the number of ugly #ifdefs somewhat.  The programs must
+ * be restricted to performing just one service, of course.
+ */
+#ifndef _SYS__ASYNCHIO_H
+#define _SYS__ASYNCHIO_H
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+#include <sys/time.h>
+
+typedef struct {
+	char	state;
+	char	op;
+	char	fd;
+	char	req;
+	void	*data;
+	ssize_t	count;
+	int	errno;
+} asynchio_t;
+
+#define ASYN_NONBLOCK	0x01
+
+#define ASYN_INPROGRESS	EINPROGRESS
+
+void asyn_init(asynchio_t *_asyn);
+ssize_t asyn_read(asynchio_t *_asyn, int _fd, void *_buf, size_t _len);
+ssize_t asyn_write(asynchio_t *_asyn, int _fd, const void *_buf, size_t _len);
+int asyn_ioctl(asynchio_t *_asyn, int _fd, unsigned long _request, void *_data);
+int asyn_wait(asynchio_t *_asyn, int _flags, struct timeval *to);
+int asyn_synch(asynchio_t *_asyn, int _fd);
+int asyn_close(asynchio_t *_asyn, int _fd);
+
+#endif /* _SYS__ASYNCHIO_H */
Index: /trunk/minix/include/sys/dir.h
===================================================================
--- /trunk/minix/include/sys/dir.h	(revision 9)
+++ /trunk/minix/include/sys/dir.h	(revision 9)
@@ -0,0 +1,19 @@
+/* The <dir.h> header gives the layout of a directory. */
+
+#ifndef _DIR_H
+#define _DIR_H
+
+#include <sys/types.h>
+
+#define	DIRBLKSIZ	512	/* size of directory block */
+
+#ifndef DIRSIZ
+#define DIRSIZ	60
+#endif
+
+struct direct {
+  ino_t d_ino;
+  char d_name[DIRSIZ];
+};
+
+#endif /* _DIR_H */
Index: /trunk/minix/include/sys/ioc_cmos.h
===================================================================
--- /trunk/minix/include/sys/ioc_cmos.h	(revision 9)
+++ /trunk/minix/include/sys/ioc_cmos.h	(revision 9)
@@ -0,0 +1,15 @@
+/*	sys/ioc_cmos.h - CMOS ioctl() command codes.
+ */
+
+#ifndef _S_I_CMOS_H
+#define _S_I_CMOS_H
+
+#include <minix/ioctl.h>
+
+#define CIOCGETTIME	_IOR('c', 1, u32_t)
+#define CIOCGETTIMEY2K	_IOR('c', 2, u32_t)
+#define CIOCSETTIME	_IOW('c', 3, u32_t)
+#define CIOCSETTIMEY2K	_IOW('c', 4, u32_t)
+
+#endif /* _S_I_CMOS_H */
+
Index: /trunk/minix/include/sys/ioc_disk.h
===================================================================
--- /trunk/minix/include/sys/ioc_disk.h	(revision 9)
+++ /trunk/minix/include/sys/ioc_disk.h	(revision 9)
@@ -0,0 +1,17 @@
+/*	sys/ioc_disk.h - Disk ioctl() command codes.	Author: Kees J. Bot
+ *								23 Nov 2002
+ *
+ */
+
+#ifndef _S_I_DISK_H
+#define _S_I_DISK_H
+
+#include <minix/ioctl.h>
+
+#define DIOCSETP	_IOW('d', 3, struct partition)
+#define DIOCGETP	_IOR('d', 4, struct partition)
+#define DIOCEJECT	_IO ('d', 5)
+#define DIOCTIMEOUT	_IOW('d', 6, int)
+#define DIOCOPENCT	_IOR('d', 7, int)
+
+#endif /* _S_I_DISK_H */
Index: /trunk/minix/include/sys/ioc_file.h
===================================================================
--- /trunk/minix/include/sys/ioc_file.h	(revision 9)
+++ /trunk/minix/include/sys/ioc_file.h	(revision 9)
@@ -0,0 +1,11 @@
+/*	sys/ioc_file.h - File ioctl() command codes.
+ */
+
+#ifndef _SYS_IOC_FILE_H
+#define _SYS_IOC_FILE_H
+
+#include <minix/ioctl.h>
+
+#define FIONREAD	_IOR('f', 1, int)
+
+#endif /* _SYS_IOC_FILE_H */
Index: /trunk/minix/include/sys/ioc_memory.h
===================================================================
--- /trunk/minix/include/sys/ioc_memory.h	(revision 9)
+++ /trunk/minix/include/sys/ioc_memory.h	(revision 9)
@@ -0,0 +1,16 @@
+/*	sys/ioc_memory.h - Memory ioctl() command codes.
+ *							Author: Kees J. Bot
+ *								23 Nov 2002
+ *
+ */
+
+#ifndef _S_I_MEMORY_H
+#define _S_I_MEMORY_H
+
+#include <minix/ioctl.h>
+
+#define MIOCRAMSIZE	_IOW('m', 3, u32_t)
+#define MIOCMAP		_IOR('m', 4, struct mapreq)
+#define MIOCUNMAP	_IOR('m', 5, struct mapreq)
+
+#endif /* _S_I_MEMORY_H */
Index: /trunk/minix/include/sys/ioc_scsi.h
===================================================================
--- /trunk/minix/include/sys/ioc_scsi.h	(revision 9)
+++ /trunk/minix/include/sys/ioc_scsi.h	(revision 9)
@@ -0,0 +1,13 @@
+/*	sys/ioc_scsi.h - SCSI ioctl() command codes.	Author: Kees J. Bot
+ *								23 Nov 2002
+ *
+ */
+
+#ifndef _S_I_SCSI_H
+#define _S_I_SCSI_H
+
+#include <minix/ioctl.h>
+
+#define SCIOCCMD	_IOW('S', 1, struct scsicmd)
+
+#endif /* _S_I_SCSI_H */
Index: /trunk/minix/include/sys/ioc_sound.h
===================================================================
--- /trunk/minix/include/sys/ioc_sound.h	(revision 9)
+++ /trunk/minix/include/sys/ioc_sound.h	(revision 9)
@@ -0,0 +1,30 @@
+/*	sys/ioc_sound.h - Sound ioctl() command codes.	Author: Kees J. Bot
+ *								23 Nov 2002
+ *
+ */
+
+#ifndef _S_I_SOUND_H
+#define _S_I_SOUND_H
+
+#include <minix/ioctl.h>
+
+/* Soundcard DSP ioctls. */
+#define	DSPIORATE	_IOR('s', 1, unsigned int)
+#define DSPIOSTEREO	_IOR('s', 2, unsigned int)
+#define DSPIOSIZE	_IOR('s', 3, unsigned int)
+#define DSPIOBITS	_IOR('s', 4, unsigned int)
+#define DSPIOSIGN	_IOR('s', 5, unsigned int)
+#define DSPIOMAX	_IOW('s', 6, unsigned int)
+#define DSPIORESET	_IO ('s', 7)
+
+/* Soundcard mixer ioctls. */
+#define MIXIOGETVOLUME		_IORW('s', 10, struct volume_level)
+#define MIXIOGETINPUTLEFT	_IORW('s', 11, struct inout_ctrl)
+#define MIXIOGETINPUTRIGHT	_IORW('s', 12, struct inout_ctrl)
+#define MIXIOGETOUTPUT		_IORW('s', 13, struct inout_ctrl)
+#define MIXIOSETVOLUME		_IORW('s', 20, struct volume_level)
+#define MIXIOSETINPUTLEFT	_IORW('s', 21, struct inout_ctrl)
+#define MIXIOSETINPUTRIGHT	_IORW('s', 22, struct inout_ctrl)
+#define MIXIOSETOUTPUT		_IORW('s', 23, struct inout_ctrl)
+
+#endif /* _S_I_SOUND_H */
Index: /trunk/minix/include/sys/ioc_tape.h
===================================================================
--- /trunk/minix/include/sys/ioc_tape.h	(revision 9)
+++ /trunk/minix/include/sys/ioc_tape.h	(revision 9)
@@ -0,0 +1,15 @@
+/*	sys/ioc_tape.h - Magnetic Tape ioctl() command codes.
+ *							Author: Kees J. Bot
+ *								23 Nov 2002
+ *
+ */
+
+#ifndef _S_I_TAPE_H
+#define _S_I_TAPE_H
+
+#include <minix/ioctl.h>
+
+#define MTIOCTOP	_IOW('M', 1, struct mtop)
+#define MTIOCGET	_IOR('M', 2, struct mtget)
+
+#endif /* _S_I_TAPE_H */
Index: /trunk/minix/include/sys/ioc_tty.h
===================================================================
--- /trunk/minix/include/sys/ioc_tty.h	(revision 9)
+++ /trunk/minix/include/sys/ioc_tty.h	(revision 9)
@@ -0,0 +1,38 @@
+/*	sys/ioc_tty.h - Terminal ioctl() command codes.
+ *							Author: Kees J. Bot
+ *								23 Nov 2002
+ *
+ */
+
+#ifndef _S_I_TTY_H
+#define _S_I_TTY_H
+
+#include <minix/ioctl.h>
+
+/* Terminal ioctls. */
+#define TCGETS		_IOR('T',  8, struct termios) /* tcgetattr */
+#define TCSETS		_IOW('T',  9, struct termios) /* tcsetattr, TCSANOW */
+#define TCSETSW		_IOW('T', 10, struct termios) /* tcsetattr, TCSADRAIN */
+#define TCSETSF		_IOW('T', 11, struct termios) /* tcsetattr, TCSAFLUSH */
+#define TCSBRK		_IOW('T', 12, int)	      /* tcsendbreak */
+#define TCDRAIN		_IO ('T', 13)		      /* tcdrain */
+#define TCFLOW		_IOW('T', 14, int)	      /* tcflow */
+#define TCFLSH		_IOW('T', 15, int)	      /* tcflush */
+#define	TIOCGWINSZ	_IOR('T', 16, struct winsize)
+#define	TIOCSWINSZ	_IOW('T', 17, struct winsize)
+#define	TIOCGPGRP	_IOW('T', 18, int)
+#define	TIOCSPGRP	_IOW('T', 19, int)
+#define TIOCSFON	_IOW('T', 20, u8_t [8192])
+
+/* Legacy <sgtty.h> */
+#define TIOCGETP	_IOR('t',  1, struct sgttyb)
+#define TIOCSETP	_IOW('t',  2, struct sgttyb)
+#define TIOCGETC	_IOR('t',  3, struct tchars)
+#define TIOCSETC	_IOW('t',  4, struct tchars)
+
+/* Keyboard ioctls. */
+#define KIOCBELL        _IOW('k', 1, struct kio_bell)
+#define KIOCSLEDS       _IOW('k', 2, struct kio_leds)
+#define KIOCSMAP	_IOW('k', 3, keymap_t)
+
+#endif /* _S_I_TTY_H */
Index: /trunk/minix/include/sys/ioctl.h
===================================================================
--- /trunk/minix/include/sys/ioctl.h	(revision 9)
+++ /trunk/minix/include/sys/ioctl.h	(revision 9)
@@ -0,0 +1,26 @@
+/*	sys/ioctl.h - All ioctl() command codes.	Author: Kees J. Bot
+ *								23 Nov 2002
+ *
+ * This header file includes all other ioctl command code headers.
+ */
+
+#ifndef _S_IOCTL_H
+#define _S_IOCTL_H
+
+/* A driver that uses ioctls claims a character for its series of commands.
+ * For instance:  #define TCGETS  _IOR('T',  8, struct termios)
+ * This is a terminal ioctl that uses the character 'T'.  The character(s)
+ * used in each header file are shown in the comment following.
+ */
+
+#include <sys/ioc_tty.h>	/* 'T' 't' 'k'		*/
+#include <net/ioctl.h>		/* 'n'			*/
+#include <sys/ioc_disk.h>	/* 'd'			*/
+#include <sys/ioc_file.h>	/* 'f'			*/
+#include <sys/ioc_memory.h>	/* 'm'			*/
+#include <sys/ioc_cmos.h>	/* 'c'			*/
+#include <sys/ioc_tape.h>	/* 'M'			*/
+#include <sys/ioc_scsi.h>	/* 'S'			*/
+#include <sys/ioc_sound.h>	/* 's'			*/
+
+#endif /* _S_IOCTL_H */
Index: /trunk/minix/include/sys/kbdio.h
===================================================================
--- /trunk/minix/include/sys/kbdio.h	(revision 9)
+++ /trunk/minix/include/sys/kbdio.h	(revision 9)
@@ -0,0 +1,22 @@
+#ifndef _SYS__KBDIO_H
+#define _SYS__KBDIO_H
+
+#include <sys/time.h>
+
+typedef struct kio_bell
+{
+	unsigned kb_pitch;		/* Bell frequency in HZ */
+	unsigned long kb_volume;	/* Volume in micro volts */
+	struct timeval kb_duration;
+} kio_bell_t;
+
+typedef struct kio_leds
+{
+	unsigned kl_bits;
+} kio_leds_t;
+
+#define KBD_LEDS_NUM	0x1
+#define KBD_LEDS_CAPS	0x2
+#define KBD_LEDS_SCROLL	0x4
+
+#endif /* _SYS__KBDIO_H */
Index: /trunk/minix/include/sys/mtio.h
===================================================================
--- /trunk/minix/include/sys/mtio.h	(revision 9)
+++ /trunk/minix/include/sys/mtio.h	(revision 9)
@@ -0,0 +1,45 @@
+/* <sys/mtio.h> magnetic tape commands			Author: Kees J. Bot
+ */
+
+#ifndef _SYS__MTIO_H
+#define _SYS__MTIO_H
+
+/* Tape operations: ioctl(fd, MTIOCTOP, &struct mtop) */
+
+struct mtop {
+	short	mt_op;		/* Operation (MTWEOF, etc.) */
+	int	mt_count;	/* Repeat count. */
+};
+
+#define MTWEOF	 0	/* Write End-Of-File Marker */
+#define MTFSF	 1	/* Forward Space File mark */
+#define MTBSF	 2	/* Backward Space File mark */
+#define MTFSR	 3	/* Forward Space Record */
+#define MTBSR	 4	/* Backward Space Record */
+#define MTREW	 5	/* Rewind tape */
+#define MTOFFL	 6	/* Rewind and take Offline */
+#define MTNOP	 7	/* No-Operation, set status only */
+#define MTRETEN	 8	/* Retension (completely wind and rewind) */
+#define MTERASE	 9	/* Erase the tape and rewind */
+#define MTEOM	10	/* Position at End-Of-Media */
+#define MTMODE	11	/* Select tape density */
+#define MTBLKZ	12	/* Select tape block size */
+
+/* Tape status: ioctl(fd, MTIOCGET, &struct mtget) */
+
+struct mtget {
+	short	mt_type;	/* Type of tape device. */
+
+	/* Device dependent "registers". */
+	short	mt_dsreg;	/* Drive status register. */
+	short	mt_erreg;	/* Error register. */
+	short	dummy;		/* (alignment) */
+
+	/* Misc info. */
+	off_t	mt_resid;	/* Residual count. */
+	off_t	mt_fileno;	/* Current File Number. */
+	off_t	mt_blkno;	/* Current Block Number within file. */
+	off_t	mt_blksize;	/* Current block size. */
+};
+
+#endif /* _SYS__MTIO_H */
Index: /trunk/minix/include/sys/param.h
===================================================================
--- /trunk/minix/include/sys/param.h	(revision 9)
+++ /trunk/minix/include/sys/param.h	(revision 9)
@@ -0,0 +1,5 @@
+/*
+sys/param.h
+*/
+
+#define MAXHOSTNAMELEN  256	/* max hostname size */
Index: /trunk/minix/include/sys/ptrace.h
===================================================================
--- /trunk/minix/include/sys/ptrace.h	(revision 9)
+++ /trunk/minix/include/sys/ptrace.h	(revision 9)
@@ -0,0 +1,27 @@
+/* <sys/ptrace.h>
+ * definitions for ptrace(2) 
+ */
+
+#ifndef _PTRACE_H
+#define _PTRACE_H
+
+#define T_STOP	       -1	/* stop the process */
+#define T_OK		0	/* enable tracing by parent for this process */
+#define T_GETINS	1	/* return value from instruction space */
+#define T_GETDATA	2	/* return value from data space */
+#define T_GETUSER	3	/* return value from user process table */
+#define	T_SETINS	4	/* set value from instruction space */
+#define T_SETDATA	5	/* set value from data space */
+#define T_SETUSER	6	/* set value in user process table */
+#define T_RESUME	7	/* resume execution */
+#define T_EXIT		8	/* exit */
+#define T_STEP		9	/* set trace bit */
+
+/* Function Prototypes. */
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+_PROTOTYPE( long ptrace, (int _req, pid_t _pid, long _addr, long _data) );
+
+#endif /* _PTRACE_H */
Index: /trunk/minix/include/sys/resource.h
===================================================================
--- /trunk/minix/include/sys/resource.h	(revision 9)
+++ /trunk/minix/include/sys/resource.h	(revision 9)
@@ -0,0 +1,21 @@
+#ifndef _SYS_RESOURCE_H
+#define _SYS_RESOURCE_H
+
+/* Priority range for the get/setpriority() interface.
+ * It isn't a mapping on the internal minix scheduling
+ * priority.
+ */
+#define PRIO_MIN	-20
+#define PRIO_MAX	 20
+
+/* Magic, invalid priority to stop the process. */
+#define PRIO_STOP	 76
+
+#define PRIO_PROCESS	0
+#define PRIO_PGRP	1
+#define PRIO_USER	2
+
+int getpriority(int, int);
+int setpriority(int, int, int);
+
+#endif
Index: /trunk/minix/include/sys/select.h
===================================================================
--- /trunk/minix/include/sys/select.h	(revision 9)
+++ /trunk/minix/include/sys/select.h	(revision 9)
@@ -0,0 +1,50 @@
+#ifndef _SYS_SELECT_H
+#define _SYS_SELECT_H 1
+
+#ifndef _POSIX_SOURCE
+#define _POSIX_SOURCE 1
+#endif
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <string.h>
+
+/* Use this datatype as basic storage unit in fd_set */
+typedef u32_t fd_mask;	
+
+/* This many bits fit in an fd_set word. */
+#define _FDSETBITSPERWORD	(sizeof(fd_mask)*8)
+
+/* Bit manipulation macros */
+#define _FD_BITMASK(b)	(1L << ((b) % _FDSETBITSPERWORD))
+#define _FD_BITWORD(b)	((b)/_FDSETBITSPERWORD)
+
+/* Default FD_SETSIZE is OPEN_MAX. */
+#ifndef FD_SETSIZE
+#define FD_SETSIZE		OPEN_MAX
+#endif
+
+/* We want to store FD_SETSIZE bits. */
+#define _FDSETWORDS	((FD_SETSIZE+_FDSETBITSPERWORD-1)/_FDSETBITSPERWORD)
+
+typedef struct {
+	fd_mask	fds_bits[_FDSETWORDS];
+} fd_set;
+
+_PROTOTYPE( int select, (int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout) );
+
+#define FD_ZERO(s) do { int _i; for(_i = 0; _i < _FDSETWORDS; _i++) { (s)->fds_bits[_i] = 0; } } while(0)
+#define FD_SET(f, s) do { (s)->fds_bits[_FD_BITWORD(f)] |= _FD_BITMASK(f); } while(0)
+#define FD_CLR(f, s) do { (s)->fds_bits[_FD_BITWORD(f)] &= ~(_FD_BITMASK(f)); } while(0)
+#define FD_ISSET(f, s) ((s)->fds_bits[_FD_BITWORD(f)] & _FD_BITMASK(f))
+
+/* possible select() operation types; read, write, errors */
+/* (FS/driver internal use only) */
+#define SEL_RD		(1 << 0)
+#define SEL_WR		(1 << 1)
+#define SEL_ERR		(1 << 2)
+#define SEL_NOTIFY	(1 << 3) /* not a real select operation */
+
+#endif /* _SYS_SELECT_H */
+
Index: /trunk/minix/include/sys/sigcontext.h
===================================================================
--- /trunk/minix/include/sys/sigcontext.h	(revision 9)
+++ /trunk/minix/include/sys/sigcontext.h	(revision 9)
@@ -0,0 +1,146 @@
+#ifndef _SIGCONTEXT_H
+#define _SIGCONTEXT_H
+
+/* The sigcontext structure is used by the sigreturn(2) system call.
+ * sigreturn() is seldom called by user programs, but it is used internally
+ * by the signal catching mechanism.
+ */
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+#ifndef _MINIX_SYS_CONFIG_H
+#include <minix/sys_config.h>
+#endif
+
+#if !defined(_MINIX_CHIP)
+#include "error, configuration is not known"
+#endif
+
+/* The following structure should match the stackframe_s structure used
+ * by the kernel's context switching code.  Floating point registers should
+ * be added in a different struct.
+ */
+#if (_MINIX_CHIP == _CHIP_INTEL)
+struct sigregs {  
+#if _WORD_SIZE == 4
+  short sr_gs;
+  short sr_fs;
+#endif /* _WORD_SIZE == 4 */
+  short sr_es;
+  short sr_ds;
+  int sr_di;
+  int sr_si;
+  int sr_bp;
+  int sr_st;			/* stack top -- used in kernel */
+  int sr_bx;
+  int sr_dx;
+  int sr_cx;
+  int sr_retreg;
+  int sr_retadr;		/* return address to caller of save -- used
+  				 * in kernel */
+  int sr_pc;
+  int sr_cs;
+  int sr_psw;
+  int sr_sp;
+  int sr_ss;
+};
+
+struct sigframe {		/* stack frame created for signalled process */
+  _PROTOTYPE( void (*sf_retadr), (void) );
+  int sf_signo;
+  int sf_code;
+  struct sigcontext *sf_scp;
+  int sf_fp;
+  _PROTOTYPE( void (*sf_retadr2), (void) );
+  struct sigcontext *sf_scpcopy;
+};
+
+#else
+#if (_MINIX_CHIP == _CHIP_M68000)
+struct sigregs {  
+  long sr_retreg;			/* d0 */
+  long sr_d1;
+  long sr_d2;
+  long sr_d3;
+  long sr_d4;
+  long sr_d5;
+  long sr_d6;
+  long sr_d7;
+  long sr_a0;
+  long sr_a1;
+  long sr_a2;
+  long sr_a3;
+  long sr_a4;
+  long sr_a5;
+  long sr_a6;
+  long sr_sp;			/* also known as a7 */
+  long sr_pc;
+  short sr_psw;
+  short sr_dummy;		/* make size multiple of 4 for system.c */
+};
+#else
+#include "error, _MINIX_CHIP is not supported"
+#endif
+#endif /* _MINIX_CHIP == _CHIP_INTEL */
+
+struct sigcontext {
+  int sc_flags;			/* sigstack state to restore */
+  long sc_mask;			/* signal mask to restore */
+  struct sigregs sc_regs;	/* register set to restore */
+};
+
+#if (_MINIX_CHIP == _CHIP_INTEL)
+#if _WORD_SIZE == 4
+#define sc_gs sc_regs.sr_gs
+#define sc_fs sc_regs.sr_fs
+#endif /* _WORD_SIZE == 4 */
+#define sc_es sc_regs.sr_es
+#define sc_ds sc_regs.sr_ds
+#define sc_di sc_regs.sr_di
+#define sc_si sc_regs.sr_si 
+#define sc_fp sc_regs.sr_bp
+#define sc_st sc_regs.sr_st		/* stack top -- used in kernel */
+#define sc_bx sc_regs.sr_bx
+#define sc_dx sc_regs.sr_dx
+#define sc_cx sc_regs.sr_cx
+#define sc_retreg sc_regs.sr_retreg
+#define sc_retadr sc_regs.sr_retadr	/* return address to caller of 
+					save -- used in kernel */
+#define sc_pc sc_regs.sr_pc
+#define sc_cs sc_regs.sr_cs
+#define sc_psw sc_regs.sr_psw
+#define sc_sp sc_regs.sr_sp
+#define sc_ss sc_regs.sr_ss
+#endif /* _MINIX_CHIP == _CHIP_INTEL */
+
+#if (_MINIX_CHIP == M68000)
+#define sc_retreg sc_regs.sr_retreg
+#define sc_d1 sc_regs.sr_d1
+#define sc_d2 sc_regs.sr_d2
+#define sc_d3 sc_regs.sr_d3
+#define sc_d4 sc_regs.sr_d4
+#define sc_d5 sc_regs.sr_d5
+#define sc_d6 sc_regs.sr_d6
+#define sc_d7 sc_regs.sr_d7
+#define sc_a0 sc_regs.sr_a0
+#define sc_a1 sc_regs.sr_a1
+#define sc_a2 sc_regs.sr_a2
+#define sc_a3 sc_regs.sr_a3
+#define sc_a4 sc_regs.sr_a4
+#define sc_a5 sc_regs.sr_a5
+#define sc_fp sc_regs.sr_a6
+#define sc_sp sc_regs.sr_sp
+#define sc_pc sc_regs.sr_pc
+#define sc_psw sc_regs.sr_psw
+#endif /* _MINIX_CHIP == M68000 */
+
+/* Values for sc_flags.  Must agree with <minix/jmp_buf.h>. */
+#define SC_SIGCONTEXT	2	/* nonzero when signal context is included */
+#define SC_NOREGLOCALS	4	/* nonzero when registers are not to be
+					saved and restored */
+
+_PROTOTYPE( int sigreturn, (struct sigcontext *_scp)			);
+
+#endif /* _SIGCONTEXT_H */
Index: /trunk/minix/include/sys/socket.h
===================================================================
--- /trunk/minix/include/sys/socket.h	(revision 9)
+++ /trunk/minix/include/sys/socket.h	(revision 9)
@@ -0,0 +1,77 @@
+/*
+sys/socket.h
+*/
+
+#ifndef SYS_SOCKET_H
+#define SYS_SOCKET_H
+
+/* Can we include <stdint.h> here or do we need an additional header that is
+ * safe to include?
+ */
+#include <stdint.h>
+
+/* Open Group Base Specifications Issue 6 (not complete) */
+#include <net/gen/socket.h>
+
+#define SOCK_STREAM	1
+#define SOCK_DGRAM	2
+#define SOCK_RAW	3
+#define SOCK_RDM	4
+#define SOCK_SEQPACKET	5
+
+#define SOL_SOCKET	0xFFFF
+
+#define SO_DEBUG	0x0001
+#define SO_REUSEADDR	0x0004
+#define SO_KEEPALIVE	0x0008
+
+#define SO_SNDBUF	0x1001	/* send buffer size */
+#define SO_RCVBUF	0x1002	/* receive buffer size */
+#define SO_ERROR	0x1007	/* get and clear error status */
+
+/* The how argument to shutdown */
+#define SHUT_RD		0	/* No further reads */
+#define SHUT_WR		1	/* No further writes */
+#define SHUT_RDWR	2	/* No further reads and writes */
+
+#ifndef _SA_FAMILY_T
+#define _SA_FAMILY_T
+typedef uint8_t		sa_family_t;
+#endif /* _SA_FAMILY_T */
+
+typedef int32_t socklen_t;
+
+struct sockaddr
+{
+	sa_family_t	sa_family;
+	char		sa_data[8];	/* Big enough for sockaddr_in */
+};
+
+_PROTOTYPE( int accept, (int _socket,
+				struct sockaddr *_RESTRICT _address,
+				socklen_t *_RESTRICT _address_len)	);
+_PROTOTYPE( int bind, (int _socket, const struct sockaddr *_address,
+						socklen_t _address_len)	);
+_PROTOTYPE( int connect, (int _socket, const struct sockaddr *_address,
+						socklen_t _address_len)	);
+_PROTOTYPE( int getpeername, (int _socket,
+				struct sockaddr *_RESTRICT _address,
+				socklen_t *_RESTRICT _address_len)	);
+_PROTOTYPE( int getsockname, (int _socket,
+				struct sockaddr *_RESTRICT _address,
+				socklen_t *_RESTRICT _address_len)	);
+_PROTOTYPE( int setsockopt,(int _socket, int _level, int _option_name,
+		const void *_option_value, socklen_t _option_len)	);
+_PROTOTYPE( int getsockopt, (int _socket, int _level, int _option_name,
+        void *_RESTRICT _option_value, socklen_t *_RESTRICT _option_len));
+_PROTOTYPE( int listen, (int _socket, int _backlog)			);
+_PROTOTYPE( ssize_t recvfrom, (int _socket, void *_RESTRICT _buffer,
+	size_t _length, int _flags, struct sockaddr *_RESTRICT _address,
+				socklen_t *_RESTRICT _address_len)	);
+_PROTOTYPE( ssize_t sendto, (int _socket, const void *_message,
+	size_t _length, int _flags, const struct sockaddr *_dest_addr,
+						socklen_t _dest_len)	);
+_PROTOTYPE( int shutdown, (int _socket, int _how)			);
+_PROTOTYPE( int socket, (int _domain, int _type, int _protocol)		);
+
+#endif /* SYS_SOCKET_H */
Index: /trunk/minix/include/sys/stat.h
===================================================================
--- /trunk/minix/include/sys/stat.h	(revision 9)
+++ /trunk/minix/include/sys/stat.h	(revision 9)
@@ -0,0 +1,80 @@
+/* The <sys/stat.h> header defines a struct that is used in the stat() and
+ * fstat functions.  The information in this struct comes from the i-node of
+ * some file.  These calls are the only approved way to inspect i-nodes.
+ */
+
+#ifndef _STAT_H
+#define _STAT_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+struct stat {
+  dev_t st_dev;			/* major/minor device number */
+  ino_t st_ino;			/* i-node number */
+  mode_t st_mode;		/* file mode, protection bits, etc. */
+  short int st_nlink;		/* # links; TEMPORARY HACK: should be nlink_t*/
+  uid_t st_uid;			/* uid of the file's owner */
+  short int st_gid;		/* gid; TEMPORARY HACK: should be gid_t */
+  dev_t st_rdev;
+  off_t st_size;		/* file size */
+  time_t st_atime;		/* time of last access */
+  time_t st_mtime;		/* time of last data modification */
+  time_t st_ctime;		/* time of last file status change */
+};
+
+/* Traditional mask definitions for st_mode. */
+#define S_IFMT  0170000	/* type of file */
+#define S_IFLNK 0120000	/* symbolic link */
+#define S_IFREG 0100000	/* regular */
+#define S_IFBLK 0060000	/* block special */
+#define S_IFDIR 0040000	/* directory */
+#define S_IFCHR 0020000	/* character special */
+#define S_IFIFO 0010000	/* this is a FIFO */
+#define S_ISUID 0004000	/* set user id on execution */
+#define S_ISGID 0002000	/* set group id on execution */
+				/* next is reserved for future use */
+#define S_ISVTX   01000		/* save swapped text even after use */
+
+/* POSIX masks for st_mode. */
+#define S_IRWXU   00700		/* owner:  rwx------ */
+#define S_IRUSR   00400		/* owner:  r-------- */
+#define S_IWUSR   00200		/* owner:  -w------- */
+#define S_IXUSR   00100		/* owner:  --x------ */
+
+#define S_IRWXG   00070		/* group:  ---rwx--- */
+#define S_IRGRP   00040		/* group:  ---r----- */
+#define S_IWGRP   00020		/* group:  ----w---- */
+#define S_IXGRP   00010		/* group:  -----x--- */
+
+#define S_IRWXO   00007		/* others: ------rwx */
+#define S_IROTH   00004		/* others: ------r-- */ 
+#define S_IWOTH   00002		/* others: -------w- */
+#define S_IXOTH   00001		/* others: --------x */
+
+/* Synonyms for above. */
+#define S_IEXEC		S_IXUSR
+#define S_IWRITE	S_IWUSR
+#define S_IREAD		S_IRUSR
+
+/* The following macros test st_mode (from POSIX Sec. 5.6.1.1). */
+#define S_ISREG(m)	(((m) & S_IFMT) == S_IFREG)	/* is a reg file */
+#define S_ISDIR(m)	(((m) & S_IFMT) == S_IFDIR)	/* is a directory */
+#define S_ISCHR(m)	(((m) & S_IFMT) == S_IFCHR)	/* is a char spec */
+#define S_ISBLK(m)	(((m) & S_IFMT) == S_IFBLK)	/* is a block spec */
+#define S_ISLNK(m)	(((m) & S_IFMT) == S_IFLNK)	/* is a symlink */
+#define S_ISFIFO(m)	(((m) & S_IFMT) == S_IFIFO)	/* is a pipe/FIFO */
+
+/* Function Prototypes. */
+_PROTOTYPE( int chmod, (const char *_path, _mnx_Mode_t _mode)		);
+_PROTOTYPE( int fstat, (int _fildes, struct stat *_buf)			);
+_PROTOTYPE( int mkdir, (const char *_path, _mnx_Mode_t _mode)		);
+_PROTOTYPE( int mkfifo, (const char *_path, _mnx_Mode_t _mode)		);
+_PROTOTYPE( int stat, (const char *_path, struct stat *_buf)		);
+_PROTOTYPE( mode_t umask, (_mnx_Mode_t _cmask)				);
+
+/* Open Group Base Specifications Issue 6 (not complete) */
+_PROTOTYPE( int lstat, (const char *_path, struct stat *_buf)		);
+
+#endif /* _STAT_H */
Index: /trunk/minix/include/sys/statfs.h
===================================================================
--- /trunk/minix/include/sys/statfs.h	(revision 9)
+++ /trunk/minix/include/sys/statfs.h	(revision 9)
@@ -0,0 +1,16 @@
+/* Data for fstatfs() call. */
+
+#ifndef _STATFS_H
+#define _STATFS_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+struct statfs {
+  off_t f_bsize;		/* file system block size */
+};
+
+_PROTOTYPE( int fstatfs, (int fd, struct statfs *st)		);
+
+#endif /* _STATFS_H */
Index: /trunk/minix/include/sys/svrctl.h
===================================================================
--- /trunk/minix/include/sys/svrctl.h	(revision 9)
+++ /trunk/minix/include/sys/svrctl.h	(revision 9)
@@ -0,0 +1,71 @@
+/*
+sys/svrctl.h
+
+Created:	Feb 15, 1994 by Philip Homburg <philip@cs.vu.nl>
+*/
+
+#ifndef _SYS__SVRCTL_H
+#define _SYS__SVRCTL_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+/* Server control commands have the same encoding as the commands for ioctls. */
+#include <minix/ioctl.h>
+
+/* MM controls. */
+#define MMSIGNON	_IO ('M',  4)
+#define MMSWAPON	_IOW('M',  5, struct mmswapon)
+#define MMSWAPOFF	_IO ('M',  6)
+#define MMGETPARAM	_IOW('M',  5, struct sysgetenv)
+#define MMSETPARAM	_IOR('M',  7, struct sysgetenv)
+
+/* FS controls. */
+#define FSSIGNON	_IOW('F',  2, struct fssignon)
+#define FSDEVMAP	_IORW('F', 5, struct fsdevmap)
+#define FSDEVUNMAP	_IOW('F',  6, struct fsdevunmap)
+
+/* Kernel controls. */
+#define SYSSENDMASK	_IO ('S',  4)
+#define SYSSIGNON	_IOR('S',  2, struct systaskinfo)
+#define SYSGETENV	_IOW('S',  1, struct sysgetenv)
+
+struct mmswapon {
+	u32_t		offset;		/* Starting offset within file. */
+	u32_t		size;		/* Size of swap area. */
+	char		file[128];	/* Name of swap file/device. */
+};
+
+struct svrqueryparam {
+	char		*param;		/* Names of parameters to query. */
+	size_t		psize;		/* Length of param[]. */
+	char		*value;		/* To return values. */
+	size_t		vsize;
+};
+
+/* A proper system call must be created later. */
+#include <minix/dmap.h>
+struct fssignon {
+	dev_t		dev;		/* Device to manage. */
+	enum dev_style	style;		/* Management style. */
+};
+
+struct fsdevunmap {
+	dev_t		dev;		/* Device to unmap. */
+};
+
+struct systaskinfo {
+	int		proc_nr;	/* Process number of caller. */
+};
+
+struct sysgetenv {
+	char		*key;		/* Name requested. */
+	size_t		keylen;		/* Length of name including \0. */
+	char		*val;		/* Buffer for returned data. */
+	size_t		vallen;		/* Size of return data buffer. */
+};
+
+_PROTOTYPE( int svrctl, (int _request, void *_data)			);
+
+#endif /* _SYS__SVRCTL_H */
Index: /trunk/minix/include/sys/time.h
===================================================================
--- /trunk/minix/include/sys/time.h	(revision 9)
+++ /trunk/minix/include/sys/time.h	(revision 9)
@@ -0,0 +1,22 @@
+/*
+sys/time.h
+*/
+
+#ifndef _SYS__TIME_H
+#define _SYS__TIME_H
+
+#include <ansi.h>
+
+/* Open Group Base Specifications Issue 6 (not complete) */
+struct timeval
+{
+	long /*time_t*/ tv_sec;
+	long /*useconds_t*/ tv_usec;
+};
+
+int gettimeofday(struct timeval *_RESTRICT tp, void *_RESTRICT tzp);
+
+/* Compatibility with other Unix systems */
+int settimeofday(const struct timeval *tp, const void *tzp);
+
+#endif /* _SYS__TIME_H */
Index: /trunk/minix/include/sys/times.h
===================================================================
--- /trunk/minix/include/sys/times.h	(revision 9)
+++ /trunk/minix/include/sys/times.h	(revision 9)
@@ -0,0 +1,25 @@
+/* The <times.h> header is for time times() system call. */
+
+#ifndef _TIMES_H
+#define _TIMES_H
+
+#ifndef _CLOCK_T
+#define _CLOCK_T
+typedef long clock_t;		/* unit for system accounting */
+#endif
+
+struct tms {
+  clock_t tms_utime;
+  clock_t tms_stime;
+  clock_t tms_cutime;
+  clock_t tms_cstime;
+};
+
+/* Function Prototypes. */
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+_PROTOTYPE( clock_t times, (struct tms *_buffer)			);
+
+#endif /* _TIMES_H */
Index: /trunk/minix/include/sys/types.h
===================================================================
--- /trunk/minix/include/sys/types.h	(revision 9)
+++ /trunk/minix/include/sys/types.h	(revision 9)
@@ -0,0 +1,146 @@
+/* The <sys/types.h> header contains important data type definitions.
+ * It is considered good programming practice to use these definitions, 
+ * instead of the underlying base type.  By convention, all type names end 
+ * with _t.
+ */
+
+#ifndef _TYPES_H
+#define _TYPES_H
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+/* The type size_t holds all results of the sizeof operator.  At first glance,
+ * it seems obvious that it should be an unsigned int, but this is not always 
+ * the case. For example, MINIX-ST (68000) has 32-bit pointers and 16-bit
+ * integers. When one asks for the size of a 70K struct or array, the result 
+ * requires 17 bits to express, so size_t must be a long type.  The type 
+ * ssize_t is the signed version of size_t.
+ */
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef unsigned int size_t;
+#endif
+
+#ifndef _SSIZE_T
+#define _SSIZE_T
+typedef int ssize_t;
+#endif
+
+#ifndef _TIME_T
+#define _TIME_T
+typedef long time_t;		   /* time in sec since 1 Jan 1970 0000 GMT */
+#endif
+
+#ifndef _CLOCK_T
+#define _CLOCK_T
+typedef long clock_t;		   /* unit for system accounting */
+#endif
+
+#ifndef _SIGSET_T
+#define _SIGSET_T
+typedef unsigned long sigset_t;
+#endif
+
+/* Open Group Base Specifications Issue 6 (not complete) */
+typedef long useconds_t;	/* Time in microseconds */
+
+/* Types used in disk, inode, etc. data structures. */
+typedef short          dev_t;	   /* holds (major|minor) device pair */
+typedef char           gid_t;	   /* group id */
+typedef unsigned long  ino_t; 	   /* i-node number (V3 filesystem) */
+typedef unsigned short mode_t;	   /* file type and permissions bits */
+typedef short        nlink_t;	   /* number of links to a file */
+typedef unsigned long  off_t;	   /* offset within a file */
+typedef int            pid_t;	   /* process id (must be signed) */
+typedef short          uid_t;	   /* user id */
+typedef unsigned long zone_t;	   /* zone number */
+typedef unsigned long block_t;	   /* block number */
+typedef unsigned long  bit_t;	   /* bit number in a bit map */
+typedef unsigned short zone1_t;	   /* zone number for V1 file systems */
+typedef unsigned short bitchunk_t; /* collection of bits in a bitmap */
+
+typedef unsigned char   u8_t;	   /* 8 bit type */
+typedef unsigned short u16_t;	   /* 16 bit type */
+typedef unsigned long  u32_t;	   /* 32 bit type */
+
+typedef char            i8_t;      /* 8 bit signed type */
+typedef short          i16_t;      /* 16 bit signed type */
+typedef long           i32_t;      /* 32 bit signed type */
+
+typedef struct { u32_t _[2]; } u64_t;
+
+/* The following types are needed because MINIX uses K&R style function
+ * definitions (for maximum portability).  When a short, such as dev_t, is
+ * passed to a function with a K&R definition, the compiler automatically
+ * promotes it to an int.  The prototype must contain an int as the parameter,
+ * not a short, because an int is what an old-style function definition
+ * expects.  Thus using dev_t in a prototype would be incorrect.  It would be
+ * sufficient to just use int instead of dev_t in the prototypes, but Dev_t
+ * is clearer.
+ */
+typedef int            Dev_t;
+typedef int 	  _mnx_Gid_t;
+typedef int 	     Nlink_t;
+typedef int 	  _mnx_Uid_t;
+typedef int             U8_t;
+typedef unsigned long  U32_t;
+typedef int             I8_t;
+typedef int            I16_t;
+typedef long           I32_t;
+
+/* ANSI C makes writing down the promotion of unsigned types very messy.  When
+ * sizeof(short) == sizeof(int), there is no promotion, so the type stays
+ * unsigned.  When the compiler is not ANSI, there is usually no loss of
+ * unsignedness, and there are usually no prototypes so the promoted type
+ * doesn't matter.  The use of types like Ino_t is an attempt to use ints
+ * (which are not promoted) while providing information to the reader.
+ */
+
+typedef unsigned long  Ino_t;
+
+#if _EM_WSIZE == 2
+/*typedef unsigned int      Ino_t; Ino_t is now 32 bits */
+typedef unsigned int    Zone1_t;
+typedef unsigned int Bitchunk_t;
+typedef unsigned int      U16_t;
+typedef unsigned int  _mnx_Mode_t;
+
+#else /* _EM_WSIZE == 4, or _EM_WSIZE undefined */
+/*typedef int	          Ino_t; Ino_t is now 32 bits */
+typedef int 	        Zone1_t;
+typedef int	     Bitchunk_t;
+typedef int	          U16_t;
+typedef int         _mnx_Mode_t;
+
+#endif /* _EM_WSIZE == 2, etc */
+ 
+/* Signal handler type, e.g. SIG_IGN */
+typedef void _PROTOTYPE( (*sighandler_t), (int) );
+
+/* Compatibility with other systems */
+typedef unsigned char	u_char;
+typedef unsigned short	u_short;
+typedef unsigned int	u_int;
+typedef unsigned long	u_long;
+typedef char		*caddr_t;
+
+/* Devices. */   
+#define MAJOR              8    /* major device = (dev>>MAJOR) & 0377 */
+#define MINOR              0    /* minor device = (dev>>MINOR) & 0377 */
+
+#ifndef minor
+#define minor(dev)      (((dev) >> MINOR) & 0xff)
+#endif
+
+#ifndef major
+#define major(dev)      (((dev) >> MAJOR) & 0xff)
+#endif
+
+#ifndef makedev
+#define makedev(major, minor)   \
+                        ((dev_t) (((major) << MAJOR) | ((minor) << MINOR)))
+#endif
+
+#endif /* _TYPES_H */
Index: /trunk/minix/include/sys/uio.h
===================================================================
--- /trunk/minix/include/sys/uio.h	(revision 9)
+++ /trunk/minix/include/sys/uio.h	(revision 9)
@@ -0,0 +1,23 @@
+/*
+sys/uio.h
+
+definitions for vector I/O operations
+*/
+
+#ifndef _SYS_UIO_H
+#define _SYS_UIO_H
+
+/* Open Group Base Specifications Issue 6 (not complete) */
+
+struct iovec
+{
+	void	*iov_base;
+	size_t	iov_len;
+};
+
+_PROTOTYPE(ssize_t readv, (int _fildes, const struct iovec *_iov,
+							int _iovcnt)	);
+_PROTOTYPE(ssize_t writev, (int _fildes, const struct iovec *_iov,
+							int iovcnt)	);
+
+#endif /* _SYS_UIO_H */
Index: /trunk/minix/include/sys/un.h
===================================================================
--- /trunk/minix/include/sys/un.h	(revision 9)
+++ /trunk/minix/include/sys/un.h	(revision 9)
@@ -0,0 +1,19 @@
+/*
+sys/un.h
+*/
+
+/* Open Group Base Specifications Issue 6 */
+
+#ifndef _SA_FAMILY_T
+#define _SA_FAMILY_T
+/* Should match corresponding typedef in <sys/socket.h> */
+typedef uint8_t		sa_family_t;
+#endif /* _SA_FAMILY_T */
+
+struct sockaddr_un
+{
+	sa_family_t	sun_family;
+	char		sun_path[127];
+};
+
+/* Note: UNIX domain sockets are not implemented! */
Index: /trunk/minix/include/sys/utsname.h
===================================================================
--- /trunk/minix/include/sys/utsname.h	(revision 9)
+++ /trunk/minix/include/sys/utsname.h	(revision 9)
@@ -0,0 +1,22 @@
+/* The <sys/utsname.h> header gives the system name. */
+
+#ifndef _UTSNAME_H
+#define _UTSNAME_H
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+struct utsname {
+  char sysname[15+1];
+  char nodename[255+1];
+  char release[11+1];
+  char version[7+1];
+  char machine[11+1];
+  char arch[11+1];
+};
+
+/* Function Prototypes. */
+_PROTOTYPE( int uname, (struct utsname *_name)				);
+
+#endif /* _UTSNAME_H */
Index: /trunk/minix/include/sys/vm.h
===================================================================
--- /trunk/minix/include/sys/vm.h	(revision 9)
+++ /trunk/minix/include/sys/vm.h	(revision 9)
@@ -0,0 +1,30 @@
+/*
+sys/vm.h
+*/
+
+#define PAGE_SIZE	4096
+
+/* MIOCMAP */
+struct mapreq
+{
+	void *base;
+	size_t size;
+	off_t offset;
+	int readonly;
+};
+
+/* i386 paging constants */
+#define I386_VM_PRESENT	0x001	/* Page is present */
+#define I386_VM_WRITE	0x002	/* Read/write access allowed */
+#define I386_VM_USER	0x004	/* User access allowed */
+#define I386_VM_PWT	0x008	/* Write through */
+#define I386_VM_PCD	0x010	/* Cache disable */
+#define I386_VM_ADDR_MASK 0xFFFFF000 /* physical address */
+
+#define I386_VM_PT_ENT_SIZE	4	/* Size of a page table entry */
+#define I386_VM_DIR_ENTRIES	1024	/* Number of entries in a page dir */
+#define I386_VM_DIR_ENT_SHIFT	22	/* Shift to get entry in page dir. */
+#define I386_VM_PT_ENT_SHIFT	12	/* Shift to get entry in page table */
+#define I386_VM_PT_ENT_MASK	0x3FF	/* Mask to get entry in page table */
+
+#define I386_CR0_PG		0x80000000	/* Enable paging */		
Index: /trunk/minix/include/sys/wait.h
===================================================================
--- /trunk/minix/include/sys/wait.h	(revision 9)
+++ /trunk/minix/include/sys/wait.h	(revision 9)
@@ -0,0 +1,40 @@
+/* The <sys/wait.h> header contains macros related to wait(). The value
+ * returned by wait() and waitpid() depends on whether the process 
+ * terminated by an exit() call, was killed by a signal, or was stopped
+ * due to job control, as follows:
+ *
+ *				 High byte   Low byte
+ *				+---------------------+
+ *	exit(status)		|  status  |    0     |
+ *				+---------------------+
+ *      killed by signal	|    0     |  signal  |
+ *				+---------------------+
+ *	stopped (job control)	|  signal  |   0177   |
+ *				+---------------------+
+ */
+
+#ifndef _WAIT_H
+#define _WAIT_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+#define _LOW(v)		( (v) & 0377)
+#define _HIGH(v)	( ((v) >> 8) & 0377)
+
+#define WNOHANG         1	/* do not wait for child to exit */
+#define WUNTRACED       2	/* for job control; not implemented */
+
+#define WIFEXITED(s)	(_LOW(s) == 0)			    /* normal exit */
+#define WEXITSTATUS(s)	(_HIGH(s))			    /* exit status */
+#define WTERMSIG(s)	(_LOW(s) & 0177)		    /* sig value */
+#define WIFSIGNALED(s)	(((unsigned int)(s)-1 & 0xFFFF) < 0xFF) /* signaled */
+#define WIFSTOPPED(s)	(_LOW(s) == 0177)		    /* stopped */
+#define WSTOPSIG(s)	(_HIGH(s) & 0377)		    /* stop signal */
+
+/* Function Prototypes. */
+_PROTOTYPE( pid_t wait, (int *_stat_loc)			   	   );
+_PROTOTYPE( pid_t waitpid, (pid_t _pid, int *_stat_loc, int _options)	   );
+
+#endif /* _WAIT_H */
Index: /trunk/minix/include/sysexits.h
===================================================================
--- /trunk/minix/include/sysexits.h	(revision 9)
+++ /trunk/minix/include/sysexits.h	(revision 9)
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1987, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)sysexits.h	8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef	_SYSEXITS_H_
+#define	_SYSEXITS_H_
+
+/*
+ *  SYSEXITS.H -- Exit status codes for system programs.
+ *
+ *	This include file attempts to categorize possible error
+ *	exit statuses for system programs, notably delivermail
+ *	and the Berkeley network.
+ *
+ *	Error numbers begin at EX__BASE to reduce the possibility of
+ *	clashing with other exit statuses that random programs may
+ *	already return.  The meaning of the codes is approximately
+ *	as follows:
+ *
+ *	EX_USAGE -- The command was used incorrectly, e.g., with
+ *		the wrong number of arguments, a bad flag, a bad
+ *		syntax in a parameter, or whatever.
+ *	EX_DATAERR -- The input data was incorrect in some way.
+ *		This should only be used for user's data & not
+ *		system files.
+ *	EX_NOINPUT -- An input file (not a system file) did not
+ *		exist or was not readable.  This could also include
+ *		errors like "No message" to a mailer (if it cared
+ *		to catch it).
+ *	EX_NOUSER -- The user specified did not exist.  This might
+ *		be used for mail addresses or remote logins.
+ *	EX_NOHOST -- The host specified did not exist.  This is used
+ *		in mail addresses or network requests.
+ *	EX_UNAVAILABLE -- A service is unavailable.  This can occur
+ *		if a support program or file does not exist.  This
+ *		can also be used as a catchall message when something
+ *		you wanted to do doesn't work, but you don't know
+ *		why.
+ *	EX_SOFTWARE -- An internal software error has been detected.
+ *		This should be limited to non-operating system related
+ *		errors as possible.
+ *	EX_OSERR -- An operating system error has been detected.
+ *		This is intended to be used for such things as "cannot
+ *		fork", "cannot create pipe", or the like.  It includes
+ *		things like getuid returning a user that does not
+ *		exist in the passwd file.
+ *	EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp,
+ *		etc.) does not exist, cannot be opened, or has some
+ *		sort of error (e.g., syntax error).
+ *	EX_CANTCREAT -- A (user specified) output file cannot be
+ *		created.
+ *	EX_IOERR -- An error occurred while doing I/O on some file.
+ *	EX_TEMPFAIL -- temporary failure, indicating something that
+ *		is not really an error.  In sendmail, this means
+ *		that a mailer (e.g.) could not create a connection,
+ *		and the request should be reattempted later.
+ *	EX_PROTOCOL -- the remote system returned something that
+ *		was "not possible" during a protocol exchange.
+ *	EX_NOPERM -- You did not have sufficient permission to
+ *		perform the operation.  This is not intended for
+ *		file system problems, which should use NOINPUT or
+ *		CANTCREAT, but rather for higher level permissions.
+ */
+
+#define EX_OK		0	/* successful termination */
+
+#define EX__BASE	64	/* base value for error messages */
+
+#define EX_USAGE	64	/* command line usage error */
+#define EX_DATAERR	65	/* data format error */
+#define EX_NOINPUT	66	/* cannot open input */
+#define EX_NOUSER	67	/* addressee unknown */
+#define EX_NOHOST	68	/* host name unknown */
+#define EX_UNAVAILABLE	69	/* service unavailable */
+#define EX_SOFTWARE	70	/* internal software error */
+#define EX_OSERR	71	/* system error (e.g., can't fork) */
+#define EX_OSFILE	72	/* critical OS file missing */
+#define EX_CANTCREAT	73	/* can't create (user) output file */
+#define EX_IOERR	74	/* input/output error */
+#define EX_TEMPFAIL	75	/* temp failure; user is invited to retry */
+#define EX_PROTOCOL	76	/* remote error in protocol */
+#define EX_NOPERM	77	/* permission denied */
+#define EX_CONFIG	78	/* configuration error */
+
+#define EX__MAX	78	/* maximum listed value */
+
+#endif /* !_SYSEXITS_H_ */
Index: /trunk/minix/include/syslog.h
===================================================================
--- /trunk/minix/include/syslog.h	(revision 9)
+++ /trunk/minix/include/syslog.h	(revision 9)
@@ -0,0 +1,156 @@
+/* Copyright (c) 1983, 1986, 1988
+ * The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from  @(#)syslog.h	7.20 (Berkeley) 2/23/91
+ * Porting to Minix by G. Falzoni <gfalzoni@inwind.it>
+ * $Id: syslog.h,v 1.1 2005/10/31 14:07:07 beng Exp $
+ */
+
+/*
+** Priorities/facilities are encoded into a single 16/32-bit quantity, where
+** the bottom 3 bits are the priority (0-7) and the top 13/28 bits are the
+** facility (0-big number).  Both the priorities and the facilities map
+** roughly one-to-one to strings in the syslogd(8) source code.
+** This mapping is included in this file.
+*/
+
+/* Priorities codes (these are ordered) */
+#define	LOG_EMERG	0	/* system is unusable */
+#define	LOG_ALERT	1	/* action must be taken immediately */
+#define	LOG_CRIT	2	/* critical conditions */
+#define	LOG_ERR		3	/* error conditions */
+#define	LOG_WARNING	4	/* warning conditions */
+#define	LOG_NOTICE	5	/* normal but significant condition */
+#define	LOG_INFO	6	/* informational */
+#define	LOG_DEBUG	7	/* debug-level messages */
+
+/* Extract priority */
+#define	LOG_PRIMASK	0x07	/* mask to extract priority part (internal) */
+#define	LOG_PRI(p)	((p)&LOG_PRIMASK)
+
+/* Facility codes */
+#define	LOG_KERN	(0<<3)	/* kernel messages */
+#define	LOG_USER	(1<<3)	/* random user-level messages */
+#define	LOG_MAIL	(2<<3)	/* mail system */
+#define	LOG_DAEMON	(3<<3)	/* system daemons */
+#define	LOG_AUTH	(4<<3)	/* security/authorization messages */
+#define	LOG_SYSLOG	(5<<3)	/* messages generated internally by syslogd */
+#define	LOG_LPR		(6<<3)	/* line printer subsystem */
+#define	LOG_NEWS	(7<<3)	/* network news subsystem */
+#define	LOG_UUCP	(8<<3)	/* UUCP subsystem */
+#define	LOG_CRON	(9<<3)	/* clock daemon */
+#define	LOG_AUTHPRIV	(10<<3)	/* security/authorization messages (private) */
+
+ /* Other codes through 15 reserved for system use */
+#define	LOG_LOCAL0	(16<<3)	/* reserved for local use */
+#define	LOG_LOCAL1	(17<<3)	/* reserved for local use */
+#define	LOG_LOCAL2	(18<<3)	/* reserved for local use */
+#define	LOG_LOCAL3	(19<<3)	/* reserved for local use */
+#define	LOG_LOCAL4	(20<<3)	/* reserved for local use */
+#define	LOG_LOCAL5	(21<<3)	/* reserved for local use */
+#define	LOG_LOCAL6	(22<<3)	/* reserved for local use */
+#define	LOG_LOCAL7	(23<<3)	/* reserved for local use */
+#define	LOG_NFACILITIES	24	/* current number of facilities */
+
+/* Extract Facility */
+#define	LOG_FACMASK	0x03f8	/* mask to extract facility part */
+#define	LOG_FAC(p)	(((p)&LOG_FACMASK)>>3)
+
+/* Option flags for openlog */
+#define	LOG_PID		0x01	/* log the pid with each message */
+#define	LOG_CONS	0x02	/* log on the console if errors in sending */
+#define	LOG_ODELAY	0x04	/* delay open until first syslog() (default) */
+#define	LOG_NDELAY	0x08	/* don't delay open */
+#define	LOG_PERROR	0x20	/* log to stderr as well */
+
+void closelog(void);
+void openlog(const char *, int, int);
+void syslog(int, const char *,...);
+
+#ifdef SYSLOG_NAMES
+
+#define	LOG_MAKEPRI(fac,pri) (((fac)<<3)|(pri))
+#define TABLE_NOPRI     0       /* Value to indicate no priority */
+#define TABLE_ALLPRI	0xFF	/* Value to indicate all priorities */
+#define	INTERNAL_NOPRI	0x10	/* the "no priority" priority */
+#define	INTERNAL_MARK	LOG_MAKEPRI(LOG_NFACILITIES, 0)	/* Mark "facility" */
+
+struct _code {
+  char *c_name;
+  int c_val;
+};
+
+static const struct _code PriNames[] =
+{
+ "alert", LOG_ALERT,
+ "crit", LOG_CRIT,
+ "debug", LOG_DEBUG,
+ "emerg", LOG_EMERG,
+ "err", LOG_ERR,
+ "error", LOG_ERR,		/* DEPRECATED */
+ "info", LOG_INFO,
+ "none", INTERNAL_NOPRI,	/* INTERNAL */
+ "notice", LOG_NOTICE,
+ "panic", LOG_EMERG,		/* DEPRECATED */
+ "warn", LOG_WARNING,		/* DEPRECATED */
+ "warning", LOG_WARNING,
+ "*", TABLE_ALLPRI,		/* INTERNAL */
+ NULL, -1,
+};
+
+static const struct _code FacNames[] =
+{
+ "auth", LOG_AUTH,
+ "authpriv", LOG_AUTHPRIV,
+ "cron", LOG_CRON,
+ "daemon", LOG_DAEMON,
+ "kern", LOG_KERN,
+ "lpr", LOG_LPR,
+ "mail", LOG_MAIL,
+ "mark", INTERNAL_MARK,		/* INTERNAL */
+ "news", LOG_NEWS,
+ "security", LOG_AUTH,		/* DEPRECATED */
+ "syslog", LOG_SYSLOG,
+ "user", LOG_USER,
+ "uucp", LOG_UUCP,
+ "local0", LOG_LOCAL0,
+ "local1", LOG_LOCAL1,
+ "local2", LOG_LOCAL2,
+ "local3", LOG_LOCAL3,
+ "local4", LOG_LOCAL4,
+ "local5", LOG_LOCAL5,
+ "local6", LOG_LOCAL6,
+ "local7", LOG_LOCAL7,
+ NULL, -1,
+};
+#endif
+
+/** syslog.h **/
Index: /trunk/minix/include/tar.h
===================================================================
--- /trunk/minix/include/tar.h	(revision 9)
+++ /trunk/minix/include/tar.h	(revision 9)
@@ -0,0 +1,71 @@
+/* The <tar.h> header is used with the tape archiver, tar. */
+
+#ifndef _TAR_H
+#define _TAR_H
+
+#define TBLOCK 		512
+#define NAMSIZ		100
+#define PFXSIZ		155
+
+#define TMODLEN 	8
+#define TUIDLEN		8
+#define TGIDLEN		8
+#define TSIZLEN		12
+#define TMTMLEN		12
+#define TCKSLEN		8
+
+#define TMAGIC		"ustar"
+#define TMAGLEN		6
+#define TVERSION	"00"
+#define TVERSLEN	2
+#define TUNMLEN		32
+#define TGNMLEN		32
+#define TDEVLEN		8
+
+#define REGTYPE		'0'
+#define AREGTYPE	'\0'
+#define LNKTYPE		'1'
+#define SYMTYPE		'2'
+#define CHRTYPE		'3'
+#define BLKTYPE		'4'
+#define DIRTYPE		'5'
+#define FIFOTYPE	'6'
+#define CONTTYPE	'7'
+
+#define TSUID		04000
+#define TSGID		02000
+#define TSVTX		01000
+
+#define TUREAD		00400
+#define TUWRITE		00200
+#define TUEXEC		00100
+#define TGREAD		00040
+#define TGWRITE		00020
+#define TGEXEC		00010
+#define TOREAD		00004
+#define TOWRITE		00002
+#define TOEXEC		00001
+
+union hblock {
+  char dummy[TBLOCK];
+  struct header {
+	char name[NAMSIZ];
+	char mode[TMODLEN];
+	char uid[TUIDLEN];
+	char gid[TGIDLEN];
+	char size[TSIZLEN];
+	char mtime[TMTMLEN];
+	char chksum[TCKSLEN];
+	char typeflag;
+	char linkname[NAMSIZ];
+	char magic[TMAGLEN];
+	char version[TVERSLEN];
+	char uname[TUNMLEN];
+	char gname[TGNMLEN];
+	char devmajor[TDEVLEN];
+	char devminor[TDEVLEN];
+	char prefix[PFXSIZ];
+  } dbuf;
+};
+
+#endif /* _TAR_H */
Index: /trunk/minix/include/termcap.h
===================================================================
--- /trunk/minix/include/termcap.h	(revision 9)
+++ /trunk/minix/include/termcap.h	(revision 9)
@@ -0,0 +1,13 @@
+#ifndef _TERMCAP_H
+#define _TERMCAP_H
+
+#include <ansi.h>
+
+_PROTOTYPE( int tgetent, (char *_bp, char *_name)			);
+_PROTOTYPE( int tgetflag, (char *_id)					);
+_PROTOTYPE( int tgetnum, (char *_id)					);
+_PROTOTYPE( char *tgetstr, (char *_id, char **_area)			);
+_PROTOTYPE( char *tgoto, (char *_cm, int _destcol, int _destline)	);
+_PROTOTYPE( int tputs, (char *_cp, int _affcnt, void (*_outc)(int))	);
+
+#endif /* _TERMCAP_H */
Index: /trunk/minix/include/termios.h
===================================================================
--- /trunk/minix/include/termios.h	(revision 9)
+++ /trunk/minix/include/termios.h	(revision 9)
@@ -0,0 +1,206 @@
+/* The <termios.h> header is used for controlling tty modes. */
+
+#ifndef _TERMIOS_H
+#define _TERMIOS_H
+
+typedef unsigned short tcflag_t;
+typedef unsigned char cc_t;
+typedef unsigned int speed_t;
+
+#define NCCS		   20	/* size of cc_c array, some extra space
+				 * for extensions. */
+
+/* Primary terminal control structure. POSIX Table 7-1. */
+struct termios {
+  tcflag_t c_iflag;		/* input modes */
+  tcflag_t c_oflag;		/* output modes */
+  tcflag_t c_cflag;		/* control modes */
+  tcflag_t c_lflag;		/* local modes */
+  speed_t  c_ispeed;		/* input speed */
+  speed_t  c_ospeed;		/* output speed */
+  cc_t c_cc[NCCS];		/* control characters */
+};
+
+/* Values for termios c_iflag bit map.  POSIX Table 7-2. */
+#define BRKINT		0x0001	/* signal interrupt on break */
+#define ICRNL		0x0002	/* map CR to NL on input */
+#define IGNBRK		0x0004	/* ignore break */
+#define IGNCR		0x0008	/* ignore CR */
+#define IGNPAR		0x0010	/* ignore characters with parity errors */
+#define INLCR		0x0020	/* map NL to CR on input */
+#define INPCK		0x0040	/* enable input parity check */
+#define ISTRIP		0x0080	/* mask off 8th bit */
+#define IXOFF		0x0100	/* enable start/stop input control */
+#define IXON		0x0200	/* enable start/stop output control */
+#define PARMRK		0x0400	/* mark parity errors in the input queue */
+
+/* Values for termios c_oflag bit map.  POSIX Sec. 7.1.2.3. */
+#define OPOST		0x0001	/* perform output processing */
+
+/* Values for termios c_cflag bit map.  POSIX Table 7-3. */
+#define CLOCAL		0x0001	/* ignore modem status lines */
+#define CREAD		0x0002	/* enable receiver */
+#define CSIZE		0x000C	/* number of bits per character */
+#define		CS5	0x0000	/* if CSIZE is CS5, characters are 5 bits */
+#define		CS6	0x0004	/* if CSIZE is CS6, characters are 6 bits */
+#define		CS7	0x0008	/* if CSIZE is CS7, characters are 7 bits */
+#define		CS8	0x000C	/* if CSIZE is CS8, characters are 8 bits */
+#define CSTOPB		0x0010	/* send 2 stop bits if set, else 1 */
+#define HUPCL		0x0020	/* hang up on last close */
+#define PARENB		0x0040	/* enable parity on output */
+#define PARODD		0x0080	/* use odd parity if set, else even */
+
+/* Values for termios c_lflag bit map.  POSIX Table 7-4. */
+#define ECHO		0x0001	/* enable echoing of input characters */
+#define ECHOE		0x0002	/* echo ERASE as backspace */
+#define ECHOK		0x0004	/* echo KILL */
+#define ECHONL		0x0008	/* echo NL */
+#define ICANON		0x0010	/* canonical input (erase and kill enabled) */
+#define IEXTEN		0x0020	/* enable extended functions */
+#define ISIG		0x0040	/* enable signals */
+#define NOFLSH		0x0080	/* disable flush after interrupt or quit */
+#define TOSTOP		0x0100	/* send SIGTTOU (job control, not implemented*/
+
+/* Indices into c_cc array.  Default values in parentheses. POSIX Table 7-5. */
+#define VEOF                 0	/* cc_c[VEOF] = EOF char (^D) */
+#define VEOL                 1	/* cc_c[VEOL] = EOL char (undef) */
+#define VERASE               2	/* cc_c[VERASE] = ERASE char (^H) */
+#define VINTR                3	/* cc_c[VINTR] = INTR char (DEL) */
+#define VKILL                4	/* cc_c[VKILL] = KILL char (^U) */
+#define VMIN                 5	/* cc_c[VMIN] = MIN value for timer */
+#define VQUIT                6	/* cc_c[VQUIT] = QUIT char (^\) */
+#define VTIME                7	/* cc_c[VTIME] = TIME value for timer */
+#define VSUSP                8	/* cc_c[VSUSP] = SUSP (^Z, ignored) */
+#define VSTART               9	/* cc_c[VSTART] = START char (^S) */
+#define VSTOP               10	/* cc_c[VSTOP] = STOP char (^Q) */
+
+#define _POSIX_VDISABLE	  (cc_t)0xFF	/* You can't even generate this 
+					 * character with 'normal' keyboards.
+					 * But some language specific keyboards
+					 * can generate 0xFF. It seems that all
+					 * 256 are used, so cc_t should be a
+					 * short...
+					 */
+
+/* Values for the baud rate settings.  POSIX Table 7-6. */
+#define B0		0x0000	/* hang up the line */
+#define B50		0x1000	/* 50 baud */
+#define B75		0x2000	/* 75 baud */
+#define B110		0x3000	/* 110 baud */
+#define B134		0x4000	/* 134.5 baud */
+#define B150		0x5000	/* 150 baud */
+#define B200		0x6000	/* 200 baud */
+#define B300		0x7000	/* 300 baud */
+#define B600		0x8000	/* 600 baud */
+#define B1200		0x9000	/* 1200 baud */
+#define B1800		0xA000	/* 1800 baud */
+#define B2400		0xB000	/* 2400 baud */
+#define B4800		0xC000	/* 4800 baud */
+#define B9600		0xD000	/* 9600 baud */
+#define B19200		0xE000	/* 19200 baud */
+#define B38400		0xF000	/* 38400 baud */
+
+/* Optional actions for tcsetattr().  POSIX Sec. 7.2.1.2. */
+#define TCSANOW            1	/* changes take effect immediately */
+#define TCSADRAIN          2	/* changes take effect after output is done */
+#define TCSAFLUSH          3	/* wait for output to finish and flush input */
+
+/* Queue_selector values for tcflush().  POSIX Sec. 7.2.2.2. */
+#define TCIFLUSH           1	/* flush accumulated input data */
+#define TCOFLUSH           2	/* flush accumulated output data */
+#define TCIOFLUSH          3	/* flush accumulated input and output data */
+
+/* Action values for tcflow().  POSIX Sec. 7.2.2.2. */
+#define TCOOFF             1	/* suspend output */
+#define TCOON              2	/* restart suspended output */
+#define TCIOFF             3	/* transmit a STOP character on the line */
+#define TCION              4	/* transmit a START character on the line */
+
+/* Function Prototypes. */
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+_PROTOTYPE( int tcsendbreak, (int _fildes, int _duration)		     );
+_PROTOTYPE( int tcdrain, (int _filedes)				   	     );
+_PROTOTYPE( int tcflush, (int _filedes, int _queue_selector)		     );
+_PROTOTYPE( int tcflow, (int _filedes, int _action)			     );
+_PROTOTYPE( speed_t cfgetispeed, (const struct termios *_termios_p)	     );
+_PROTOTYPE( speed_t cfgetospeed, (const struct termios *_termios_p)	     );
+_PROTOTYPE( int cfsetispeed, (struct termios *_termios_p, speed_t _speed)    );
+_PROTOTYPE( int cfsetospeed, (struct termios *_termios_p, speed_t _speed)    );
+_PROTOTYPE( int tcgetattr, (int _filedes, struct termios *_termios_p)        );
+_PROTOTYPE( int tcsetattr, \
+	(int _filedes, int _opt_actions, const struct termios *_termios_p)   );
+
+#define cfgetispeed(termios_p)		((termios_p)->c_ispeed)
+#define cfgetospeed(termios_p)		((termios_p)->c_ospeed)
+#define cfsetispeed(termios_p, speed)	((termios_p)->c_ispeed = (speed), 0)
+#define cfsetospeed(termios_p, speed)	((termios_p)->c_ospeed = (speed), 0)
+
+#ifdef _MINIX
+/* Here are the local extensions to the POSIX standard for Minix. Posix
+ * conforming programs are not able to access these, and therefore they are
+ * only defined when a Minix program is compiled.
+ */
+
+/* Extensions to the termios c_iflag bit map.  */
+#define IXANY		0x0800	/* allow any key to continue ouptut */
+
+/* Extensions to the termios c_oflag bit map. They are only active iff
+ * OPOST is enabled. */
+#define ONLCR		0x0002	/* Map NL to CR-NL on output */
+#define XTABS		0x0004	/* Expand tabs to spaces */
+#define ONOEOT		0x0008	/* discard EOT's (^D) on output) */
+
+/* Extensions to the termios c_lflag bit map.  */
+#define LFLUSHO		0x0200	/* Flush output. */
+
+/* Extensions to the c_cc array. */
+#define VREPRINT	  11	/* cc_c[VREPRINT] (^R) */
+#define VLNEXT            12    /* cc_c[VLNEXT] (^V) */
+#define VDISCARD          13    /* cc_c[VDISCARD] (^O) */
+
+/* Extensions to baud rate settings. */
+#define B57600		0x0100	/* 57600 baud */
+#define B115200		0x0200	/* 115200 baud */
+
+/* These are the default settings used by the kernel and by 'stty sane' */
+
+#define TCTRL_DEF	(CREAD | CS8 | HUPCL)
+#define TINPUT_DEF	(BRKINT | ICRNL | IXON | IXANY)
+#define TOUTPUT_DEF	(OPOST | ONLCR)
+#define TLOCAL_DEF	(ISIG | IEXTEN | ICANON | ECHO | ECHOE)
+#define TSPEED_DEF	B9600
+
+#define TEOF_DEF	'\4'	/* ^D */
+#define TEOL_DEF	_POSIX_VDISABLE
+#define TERASE_DEF	'\10'	/* ^H */
+#define TINTR_DEF	'\3'	/* ^C */
+#define TKILL_DEF	'\25'	/* ^U */
+#define TMIN_DEF	1
+#define TQUIT_DEF	'\34'	/* ^\ */
+#define TSTART_DEF	'\21'	/* ^Q */
+#define TSTOP_DEF	'\23'	/* ^S */
+#define TSUSP_DEF	'\32'	/* ^Z */
+#define TTIME_DEF	0
+#define	TREPRINT_DEF	'\22'	/* ^R */
+#define	TLNEXT_DEF	'\26'	/* ^V */
+#define	TDISCARD_DEF	'\17'	/* ^O */
+
+/* Window size. This information is stored in the TTY driver but not used.
+ * This can be used for screen based applications in a window environment. 
+ * The ioctls TIOCGWINSZ and TIOCSWINSZ can be used to get and set this 
+ * information.
+ */
+
+struct winsize
+{
+	unsigned short	ws_row;		/* rows, in characters */
+	unsigned short	ws_col;		/* columns, in characters */
+	unsigned short	ws_xpixel;	/* horizontal size, pixels */
+	unsigned short	ws_ypixel;	/* vertical size, pixels */
+};
+#endif /* _MINIX */
+
+#endif /* _TERMIOS_H */
Index: /trunk/minix/include/time.h
===================================================================
--- /trunk/minix/include/time.h	(revision 9)
+++ /trunk/minix/include/time.h	(revision 9)
@@ -0,0 +1,75 @@
+/* The <time.h> header is used by the procedures that deal with time.
+ * Handling time is surprisingly complicated, what with GMT, local time
+ * and other factors.  Although the Bishop of Ussher (1581-1656) once
+ * calculated that based on the Bible, the world began on 12 Oct. 4004 BC
+ * at 9 o'clock in the morning, in the UNIX world time begins at midnight, 
+ * 1 Jan. 1970 GMT.  Before that, all was NULL and (void).
+ */
+
+#ifndef _TIME_H
+#define _TIME_H
+
+#define CLOCKS_PER_SEC    60	/* MINIX always uses 60 Hz, even in Europe */
+
+#ifdef _POSIX_SOURCE
+#define CLK_TCK CLOCKS_PER_SEC	/* obsolescent mame for CLOCKS_PER_SEC */
+#endif
+
+#define NULL    ((void *)0)
+
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef unsigned int size_t;
+#endif
+
+#ifndef _TIME_T
+#define _TIME_T
+typedef long time_t;		/* time in sec since 1 Jan 1970 0000 GMT */
+#endif
+
+#ifndef _CLOCK_T
+#define _CLOCK_T
+typedef long clock_t;		/* time in ticks since process started */
+#endif
+
+struct tm {
+  int tm_sec;			/* seconds after the minute [0, 59] */
+  int tm_min;			/* minutes after the hour [0, 59] */
+  int tm_hour;			/* hours since midnight [0, 23] */
+  int tm_mday;			/* day of the month [1, 31] */
+  int tm_mon;			/* months since January [0, 11] */
+  int tm_year;			/* years since 1900 */
+  int tm_wday;			/* days since Sunday [0, 6] */
+  int tm_yday;			/* days since January 1 [0, 365] */
+  int tm_isdst;			/* Daylight Saving Time flag */
+};
+
+extern char *tzname[];
+
+/* Function Prototypes. */
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+_PROTOTYPE( clock_t clock, (void)					);
+_PROTOTYPE( double difftime, (time_t _time1, time_t _time0)		);
+_PROTOTYPE( time_t mktime, (struct tm *_timeptr)			);
+_PROTOTYPE( time_t time, (time_t *_timeptr)				);
+_PROTOTYPE( char *asctime, (const struct tm *_timeptr)			);
+_PROTOTYPE( char *ctime, (const time_t *_timer)			);
+_PROTOTYPE( struct tm *gmtime, (const time_t *_timer)			);
+_PROTOTYPE( struct tm *localtime, (const time_t *_timer)		);
+_PROTOTYPE( size_t strftime, (char *_s, size_t _max, const char *_fmt,
+				const struct tm *_timep)		);
+
+#ifdef _POSIX_SOURCE
+_PROTOTYPE( void tzset, (void)						);
+#endif
+
+#ifdef _MINIX
+_PROTOTYPE( int stime, (time_t *_top)					);
+#endif
+
+extern long timezone;
+
+#endif /* _TIME_H */
Index: /trunk/minix/include/timers.h
===================================================================
--- /trunk/minix/include/timers.h	(revision 9)
+++ /trunk/minix/include/timers.h	(revision 9)
@@ -0,0 +1,63 @@
+/* This library provides generic watchdog timer management functionality.
+ * The functions operate on a timer queue provided by the caller. Note that
+ * the timers must use absolute time to allow sorting. The library provides:
+ *
+ *    tmrs_settimer:     (re)set a new watchdog timer in the timers queue 
+ *    tmrs_clrtimer:     remove a timer from both the timers queue 
+ *    tmrs_exptimers:    check for expired timers and run watchdog functions
+ *
+ * Author:
+ *    Jorrit N. Herder <jnherder@cs.vu.nl>
+ *    Adapted from tmr_settimer and tmr_clrtimer in src/kernel/clock.c. 
+ *    Last modified: September 30, 2004.
+ */
+
+#ifndef _TIMERS_H
+#define _TIMERS_H
+
+#include <limits.h>
+#include <sys/types.h>
+
+struct timer;
+typedef void (*tmr_func_t)(struct timer *tp);
+typedef union { int ta_int; long ta_long; void *ta_ptr; } tmr_arg_t;
+
+/* A timer_t variable must be declare for each distinct timer to be used.
+ * The timers watchdog function and expiration time are automatically set
+ * by the library function tmrs_settimer, but its argument is not.
+ */
+typedef struct timer
+{
+  struct timer	*tmr_next;	/* next in a timer chain */
+  clock_t 	tmr_exp_time;	/* expiration time */
+  tmr_func_t	tmr_func;	/* function to call when expired */
+  tmr_arg_t	tmr_arg;	/* random argument */
+} timer_t;
+
+/* Used when the timer is not active. */
+#define TMR_NEVER    ((clock_t) -1 < 0) ? ((clock_t) LONG_MAX) : ((clock_t) -1)
+#undef TMR_NEVER
+#define TMR_NEVER	((clock_t) LONG_MAX)
+
+/* These definitions can be used to set or get data from a timer variable. */ 
+#define tmr_arg(tp) (&(tp)->tmr_arg)
+#define tmr_exp_time(tp) (&(tp)->tmr_exp_time)
+
+/* Timers should be initialized once before they are being used. Be careful
+ * not to reinitialize a timer that is in a list of timers, or the chain
+ * will be broken.
+ */
+#define tmr_inittimer(tp) (void)((tp)->tmr_exp_time = TMR_NEVER, \
+	(tp)->tmr_next = NULL)
+
+/* The following generic timer management functions are available. They
+ * can be used to operate on the lists of timers. Adding a timer to a list 
+ * automatically takes care of removing it.
+ */
+_PROTOTYPE( clock_t tmrs_clrtimer, (timer_t **tmrs, timer_t *tp, clock_t *new_head)		);
+_PROTOTYPE( void tmrs_exptimers, (timer_t **tmrs, clock_t now, clock_t *new_head)		);
+_PROTOTYPE( clock_t tmrs_settimer, (timer_t **tmrs, timer_t *tp, 
+	clock_t exp_time, tmr_func_t watchdog, clock_t *new_head)				);
+
+#endif /* _TIMERS_H */
+
Index: /trunk/minix/include/tools.h
===================================================================
--- /trunk/minix/include/tools.h	(revision 9)
+++ /trunk/minix/include/tools.h	(revision 9)
@@ -0,0 +1,123 @@
+/* Constants describing the disk */
+#define SECTOR_SIZE	512
+#define SECTOR_SHIFT	9
+#define RATIO(b)	((b)/SECTOR_SIZE)
+#define ISO_SECTOR_SIZE	2048
+#define ISO_PVD_OFFSET	16
+#define HRATIO		(SECTOR_SIZE / HCLICK_SIZE)
+#define PARAMSEC	1	/* sector containing boot parameters */
+#define DSKBASE		0x1E	/* floppy disk parameter vector */
+#define DSKPARSIZE	11	/* there are this many bytes of parameters */
+#define ESC		'\33'	/* escape key */
+#define HEADERSEG	0x0060	/* place for an array of struct exec's */
+#define MINIXSEG	0x0080	/* MINIX loaded here (rounded up to a click) */
+#define BOOTSEG		0x07C0	/* bootstraps are loaded here */
+#define SIGNATURE	0xAA55	/* proper bootstraps have this signature */
+#define SIGNATPOS	510	/* offset within bootblock */
+#define FREESEG		0x0800	/* Memory from FREESEG to cseg is free */
+#define MSEC_PER_TICK	55	/* 18.2 ticks per second */
+
+/* Scan codes for four different keyboards (from kernel/keyboard.c) */
+#define DUTCH_EXT_SCAN	  32	/* 'd' */
+#define OLIVETTI_SCAN	  12	/* '=' key on olivetti */
+#define STANDARD_SCAN	  13	/* '=' key on IBM */
+#define US_EXT_SCAN	  22	/* 'u' */
+
+/* Other */
+#define ROOT_INO ((ino_t) 1)	/* Inode nr of root dir. */
+#define IM_NAME_MAX       63
+
+/* Variables */
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+typedef struct vector {
+  u16_t offset;
+  u16_t segment;
+} vector;
+
+struct image_header {
+  char name[IM_NAME_MAX + 1];	/* Null terminated. */
+  struct exec process;
+};
+
+EXTERN vector rem_part;		/* boot partition table entry */
+EXTERN u16_t cseg, dseg;	/* code and data segment of the boot program */
+EXTERN u32_t runsize;		/* size of this program */
+EXTERN u16_t device;		/* drive being booted from */
+EXTERN u16_t heads, sectors;	/* the drive's number of heads and sectors */
+extern u16_t eqscancode;	/* Set by peek/getch() if they see a '=' */
+
+/* Sticky attributes */
+#define E_SPECIAL	0x01	/* These are known to the program */
+#define E_DEV		0x02	/* The value is a device name */
+#define E_RESERVED	0x04	/* May not be set by user, e.g. scancode */
+#define E_STICKY	0x07	/* Don't go once set */
+
+/* Volatile attributes */
+#define E_VAR		0x08	/* Variable */
+#define E_FUNCTION	0x10	/* Function definition */
+
+typedef struct environment {
+  struct environment *next;
+  char flags;
+  char *name;			/* name = value */
+  char *arg;			/* name(arg) {value} */
+  char *value;
+  char *defval;			/* Safehouse for default values */
+} environment;
+
+/* External variables */
+EXTERN environment *env;	/* Lists the environment */
+EXTERN int fsok;		/* True if the boot device contains an FS */
+EXTERN u32_t lowsec;		/* Offset to the file system on the boot dev */
+
+/* Prototypes */
+_PROTOTYPE( off_t r_super, (void));
+_PROTOTYPE( void r_stat, (Ino_t _inum, struct stat *_stp ));
+_PROTOTYPE( ino_t r_readdir, (char *_name ));
+_PROTOTYPE( off_t r_vir2abs, (off_t _virblk ));
+_PROTOTYPE( ino_t r_lookup, (Ino_t _cwd, char *_path ));
+
+#ifdef _MONHEAD
+_PROTOTYPE( void readerr, (off_t _sec, int _err ));
+_PROTOTYPE( int numprefix, (char *_s, char **_ps ));
+_PROTOTYPE( int numeric, (char *_s ));
+_PROTOTYPE( dev_t name2dev, (char *_name ));
+_PROTOTYPE( int delay, (char *_msec ));
+_PROTOTYPE( char *unix_err, (int _err ));
+_PROTOTYPE( void init_cache, (void));
+_PROTOTYPE( void invalidate_cache, (void));
+_PROTOTYPE( char *b_value, (char *_name ));
+_PROTOTYPE( void raw_copy, (int _doff, int _dseg, int _soff, int _sseg,
+						int _count));
+_PROTOTYPE( void raw_clear, (int _off, int _seg, int _count));
+_PROTOTYPE( void bootstrap, (int _device, int _partoff, int _partseg));
+
+_PROTOTYPE( long a2l, (char *_a ));
+_PROTOTYPE( char *ul2a, (u32_t _n ));
+_PROTOTYPE( char *u2a, (int _n1 ));
+
+/* Functions defined in monhead.s and usable by other files. */
+_PROTOTYPE( void reset_video, (int color));
+_PROTOTYPE( int dev_geometry, (void));
+_PROTOTYPE( u16_t get_ext_memsize, (void));
+_PROTOTYPE( u16_t get_low_memsize, (void));
+_PROTOTYPE( u16_t get_processor, (void));
+_PROTOTYPE( u32_t get_tick, (void));
+_PROTOTYPE( u16_t get_video, (void));
+_PROTOTYPE( u16_t get_word, (int _off, int _seg));
+_PROTOTYPE( int getchar, (void));
+_PROTOTYPE( void minix, (void));
+_PROTOTYPE( void minix86, (int _kcs, int _kds, char *_bpar, int _psize));
+_PROTOTYPE( void minix386, (int _kcs, int _kds, char *_bpar, int _psize));
+_PROTOTYPE( int peekchar, (void));
+_PROTOTYPE( void put_word, (int _off, int _seg, int _word));
+_PROTOTYPE( int putchar, (char _c));
+_PROTOTYPE( int readsectors, (int _off, int _seg, off_t _adr, int _ct));
+_PROTOTYPE( void reboot, (void));
+_PROTOTYPE( void relocate, (void));
+_PROTOTYPE( int writesectors, (int _off, int _seg, off_t _adr, int _ct));
+#endif
+
Index: /trunk/minix/include/ttyent.h
===================================================================
--- /trunk/minix/include/ttyent.h	(revision 9)
+++ /trunk/minix/include/ttyent.h	(revision 9)
@@ -0,0 +1,23 @@
+/* <ttyent.h> is used by getttyent(3).			Author: Kees J. Bot
+ *								28 Oct 1995
+ */
+#ifndef _TTYENT_H
+#define _TTYENT_H
+
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+struct ttyent {
+	char	*ty_name;	/* Name of the terminal device. */
+	char	*ty_type;	/* Terminal type name (termcap(3)). */
+	char	**ty_getty;	/* Program to run, normally getty. */
+	char	**ty_init;	/* Initialization command, normally stty. */
+};
+
+_PROTOTYPE( struct ttyent *getttyent, (void)				);
+_PROTOTYPE( struct ttyent *getttynam, (const char *_name)		);
+_PROTOTYPE( int setttyent, (void)					);
+_PROTOTYPE( void endttyent, (void)					);
+
+#endif /* _TTYENT_H */
Index: /trunk/minix/include/unistd.h
===================================================================
--- /trunk/minix/include/unistd.h	(revision 9)
+++ /trunk/minix/include/unistd.h	(revision 9)
@@ -0,0 +1,199 @@
+/* The <unistd.h> header contains a few miscellaneous manifest constants. */
+
+#ifndef _UNISTD_H
+#define _UNISTD_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+/* Values used by access().  POSIX Table 2-8. */
+#define F_OK               0	/* test if file exists */
+#define X_OK               1	/* test if file is executable */
+#define W_OK               2	/* test if file is writable */
+#define R_OK               4	/* test if file is readable */
+
+/* Values used for whence in lseek(fd, offset, whence).  POSIX Table 2-9. */
+#define SEEK_SET           0	/* offset is absolute  */
+#define SEEK_CUR           1	/* offset is relative to current position */
+#define SEEK_END           2	/* offset is relative to end of file */
+
+/* This value is required by POSIX Table 2-10. */
+#define _POSIX_VERSION 199009L	/* which standard is being conformed to */
+
+/* These three definitions are required by POSIX Sec. 8.2.1.2. */
+#define STDIN_FILENO       0	/* file descriptor for stdin */
+#define STDOUT_FILENO      1	/* file descriptor for stdout */
+#define STDERR_FILENO      2	/* file descriptor for stderr */
+
+#ifdef _MINIX
+/* How to exit the system or stop a server process. */
+#define RBT_HALT	   0	/* shutdown and return to monitor */
+#define RBT_REBOOT	   1	/* reboot the system through the monitor */
+#define RBT_PANIC	   2	/* a server panics */
+#define RBT_MONITOR	   3	/* let the monitor do this */
+#define RBT_RESET	   4	/* hard reset the system */
+#define RBT_INVALID	   5	/* first invalid reboot flag */
+
+#define _PM_SEG_FLAG (1L << 30)	/* for read() and write() to FS by PM */
+#endif
+
+/* What system info to retrieve with sysgetinfo(). */
+#define SI_KINFO	   0	/* get kernel info via PM */
+#define SI_PROC_ADDR	   1	/* address of process table */
+#define SI_PROC_TAB	   2	/* copy of entire process table */
+#define SI_DMAP_TAB	   3	/* get device <-> driver mappings */
+#define SI_MEM_ALLOC	   4	/* get memory allocation data */
+#define SI_DATA_STORE	   5	/* get copy of data store */
+#define SI_LOADINFO	   6	/* get copy of load average structure */
+#define SI_KPROC_TAB	   7	/* copy of kernel process table */
+
+/* NULL must be defined in <unistd.h> according to POSIX Sec. 2.7.1. */
+#define NULL    ((void *)0)
+
+/* The following relate to configurable system variables. POSIX Table 4-2. */
+#define _SC_ARG_MAX	   1
+#define _SC_CHILD_MAX	   2
+#define _SC_CLOCKS_PER_SEC 3
+#define _SC_CLK_TCK	   3
+#define _SC_NGROUPS_MAX	   4
+#define _SC_OPEN_MAX	   5
+#define _SC_JOB_CONTROL	   6
+#define _SC_SAVED_IDS	   7
+#define _SC_VERSION	   8
+#define _SC_STREAM_MAX	   9
+#define _SC_TZNAME_MAX    10
+#define _SC_PAGESIZE	  11
+#define _SC_PAGE_SIZE	  _SC_PAGESIZE
+
+/* The following relate to configurable pathname variables. POSIX Table 5-2. */
+#define _PC_LINK_MAX	   1	/* link count */
+#define _PC_MAX_CANON	   2	/* size of the canonical input queue */
+#define _PC_MAX_INPUT	   3	/* type-ahead buffer size */
+#define _PC_NAME_MAX	   4	/* file name size */
+#define _PC_PATH_MAX	   5	/* pathname size */
+#define _PC_PIPE_BUF	   6	/* pipe size */
+#define _PC_NO_TRUNC	   7	/* treatment of long name components */
+#define _PC_VDISABLE	   8	/* tty disable */
+#define _PC_CHOWN_RESTRICTED 9	/* chown restricted or not */
+
+/* POSIX defines several options that may be implemented or not, at the
+ * implementer's whim.  This implementer has made the following choices:
+ *
+ * _POSIX_JOB_CONTROL	    not defined:	no job control
+ * _POSIX_SAVED_IDS 	    not defined:	no saved uid/gid
+ * _POSIX_NO_TRUNC	    defined as -1:	long path names are truncated
+ * _POSIX_CHOWN_RESTRICTED  defined:		you can't give away files
+ * _POSIX_VDISABLE	    defined:		tty functions can be disabled
+ */
+#define _POSIX_NO_TRUNC       (-1)
+#define _POSIX_CHOWN_RESTRICTED  1
+
+/* Function Prototypes. */
+_PROTOTYPE( void _exit, (int _status)					);
+_PROTOTYPE( int access, (const char *_path, int _amode)			);
+_PROTOTYPE( unsigned int alarm, (unsigned int _seconds)			);
+_PROTOTYPE( int chdir, (const char *_path)				);
+_PROTOTYPE( int fchdir, (int fd)					);
+_PROTOTYPE( int chown, (const char *_path, _mnx_Uid_t _owner, _mnx_Gid_t _group)	);
+_PROTOTYPE( int close, (int _fd)					);
+_PROTOTYPE( char *ctermid, (char *_s)					);
+_PROTOTYPE( char *cuserid, (char *_s)					);
+_PROTOTYPE( int dup, (int _fd)						);
+_PROTOTYPE( int dup2, (int _fd, int _fd2)				);
+_PROTOTYPE( int execl, (const char *_path, const char *_arg, ...)	);
+_PROTOTYPE( int execle, (const char *_path, const char *_arg, ...)	);
+_PROTOTYPE( int execlp, (const char *_file, const char *arg, ...)	);
+_PROTOTYPE( int execv, (const char *_path, char *const _argv[])		);
+_PROTOTYPE( int execve, (const char *_path, char *const _argv[], 
+						char *const _envp[])	);
+_PROTOTYPE( int execvp, (const char *_file, char *const _argv[])	);
+_PROTOTYPE( pid_t fork, (void)						);
+_PROTOTYPE( long fpathconf, (int _fd, int _name)			);
+_PROTOTYPE( char *getcwd, (char *_buf, size_t _size)			);
+_PROTOTYPE( gid_t getegid, (void)					);
+_PROTOTYPE( uid_t geteuid, (void)					);
+_PROTOTYPE( gid_t getgid, (void)					);
+_PROTOTYPE( int getgroups, (int _gidsetsize, gid_t _grouplist[])	);
+_PROTOTYPE( char *getlogin, (void)					);
+_PROTOTYPE( pid_t getpgrp, (void)					);
+_PROTOTYPE( pid_t getpid, (void)					);
+_PROTOTYPE( pid_t getnpid, (int proc_nr)				);
+_PROTOTYPE( pid_t getppid, (void)					);
+_PROTOTYPE( uid_t getuid, (void)					);
+_PROTOTYPE( int isatty, (int _fd)					);
+_PROTOTYPE( int link, (const char *_existing, const char *_new)		);
+_PROTOTYPE( off_t lseek, (int _fd, off_t _offset, int _whence)		);
+_PROTOTYPE( long pathconf, (const char *_path, int _name)		);
+_PROTOTYPE( int pause, (void)						);
+_PROTOTYPE( int pipe, (int _fildes[2])					);
+_PROTOTYPE( ssize_t read, (int _fd, void *_buf, size_t _n)		);
+_PROTOTYPE( int rmdir, (const char *_path)				);
+_PROTOTYPE( int setgid, (_mnx_Gid_t _gid)				);
+_PROTOTYPE( int setegid, (_mnx_Gid_t _gid)				);
+_PROTOTYPE( int setpgid, (pid_t _pid, pid_t _pgid)			);
+_PROTOTYPE( pid_t setsid, (void)					);
+_PROTOTYPE( int setuid, (_mnx_Uid_t _uid)				);
+_PROTOTYPE( int seteuid, (_mnx_Uid_t _uid)				);
+_PROTOTYPE( unsigned int sleep, (unsigned int _seconds)			);
+_PROTOTYPE( long sysconf, (int _name)					);
+_PROTOTYPE( pid_t tcgetpgrp, (int _fd)					);
+_PROTOTYPE( int tcsetpgrp, (int _fd, pid_t _pgrp_id)			);
+_PROTOTYPE( char *ttyname, (int _fd)					);
+_PROTOTYPE( int unlink, (const char *_path)				);
+_PROTOTYPE( ssize_t write, (int _fd, const void *_buf, size_t _n)	);
+_PROTOTYPE( int truncate, (const char *_path, off_t _length)		);
+_PROTOTYPE( int ftruncate, (int _fd, off_t _length)			);
+
+/* Open Group Base Specifications Issue 6 (not complete) */
+_PROTOTYPE( int symlink, (const char *path1, const char *path2)		);
+_PROTOTYPE( int readlink, (const char *, char *, size_t)		);
+_PROTOTYPE( int getopt, (int _argc, char * const _argv[], char const *_opts)		);
+extern char *optarg;
+extern int optind, opterr, optopt;
+_PROTOTYPE( int usleep, (useconds_t _useconds)				);
+
+#ifdef _MINIX
+#ifndef _TYPE_H
+#include <minix/type.h>
+#endif
+_PROTOTYPE( int brk, (char *_addr)					);
+_PROTOTYPE( int chroot, (const char *_name)				);
+_PROTOTYPE( int mknod, (const char *_name, _mnx_Mode_t _mode, Dev_t _addr)	);
+_PROTOTYPE( int mknod4, (const char *_name, _mnx_Mode_t _mode, Dev_t _addr,
+	    long _size)							);
+_PROTOTYPE( char *mktemp, (char *_template)				);
+_PROTOTYPE( int mount, (char *_spec, char *_name, int _flag)		);
+_PROTOTYPE( long ptrace, (int _req, pid_t _pid, long _addr, long _data)	);
+_PROTOTYPE( char *sbrk, (int _incr)					);
+_PROTOTYPE( int sync, (void)						);
+_PROTOTYPE( int fsync, (int fd)						);
+_PROTOTYPE( int umount, (const char *_name)				);
+_PROTOTYPE( int reboot, (int _how, ...)					);
+_PROTOTYPE( int gethostname, (char *_hostname, size_t _len)		);
+_PROTOTYPE( int getdomainname, (char *_domain, size_t _len)		);
+_PROTOTYPE( int ttyslot, (void)						);
+_PROTOTYPE( int fttyslot, (int _fd)					);
+_PROTOTYPE( char *crypt, (const char *_key, const char *_salt)		);
+_PROTOTYPE( int getsysinfo, (int who, int what, void *where)		);
+_PROTOTYPE( int getsigset, (sigset_t *sigset)				);
+_PROTOTYPE( int getprocnr, (void)					);
+_PROTOTYPE( int getnprocnr, (pid_t pid)					);
+_PROTOTYPE( int getpprocnr, (void)					);
+_PROTOTYPE( int _pm_findproc, (char *proc_name, int *proc_nr)		);
+_PROTOTYPE( int allocmem, (phys_bytes size, phys_bytes *base)		);
+_PROTOTYPE( int freemem, (phys_bytes size, phys_bytes base)		);
+#define DEV_MAP 1
+#define DEV_UNMAP 2
+#define mapdriver(driver, device, style) devctl(DEV_MAP, driver, device, style)
+#define unmapdriver(device) devctl(DEV_UNMAP, 0, device, 0)
+_PROTOTYPE( int devctl, (int ctl_req, int driver, int device, int style));
+
+/* For compatibility with other Unix systems */
+_PROTOTYPE( int getpagesize, (void)					);
+_PROTOTYPE( int setgroups, (int ngroups, const gid_t *gidset)		);
+_PROTOTYPE( int initgroups, (const char *name, gid_t basegid)		);
+
+#endif
+
+#endif /* _UNISTD_H */
Index: /trunk/minix/include/utime.h
===================================================================
--- /trunk/minix/include/utime.h	(revision 9)
+++ /trunk/minix/include/utime.h	(revision 9)
@@ -0,0 +1,18 @@
+/* The <utime.h> header is used for the utime() system call. */
+
+#ifndef _UTIME_H
+#define _UTIME_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+struct utimbuf {
+  time_t actime;		/* access time */
+  time_t modtime;		/* modification time */
+};
+
+/* Function Prototypes. */
+_PROTOTYPE( int utime, (const char *_path, const struct utimbuf *_times)     );
+
+#endif /* _UTIME_H */
Index: /trunk/minix/include/utmp.h
===================================================================
--- /trunk/minix/include/utmp.h	(revision 9)
+++ /trunk/minix/include/utmp.h	(revision 9)
@@ -0,0 +1,30 @@
+/* The <utmp.h> header is used by init, login, who, etc. */
+
+#ifndef _UTMP_H
+#define _UTMP_H
+
+#define WTMP  "/usr/adm/wtmp"	/* the login history file */
+#define BTMP  "/usr/adm/btmp"	/* the bad-login history file */
+#define UTMP  "/etc/utmp"	/* the user accouting file */
+
+struct utmp {
+  char ut_user[8];		/* user name */
+  char ut_id[4];		/* /etc/inittab ID */
+  char ut_line[12];		/* terminal name */
+  char ut_host[16];		/* host name, when remote */
+  short ut_pid;			/* process id */
+  short int ut_type;		/* type of entry */
+  long ut_time;			/* login/logout time */
+};
+
+#define ut_name ut_user		/* for compatibility with other systems */
+
+/* Definitions for ut_type. */
+#define RUN_LVL            1	/* this is a RUN_LEVEL record */
+#define BOOT_TIME          2	/* this is a REBOOT record */
+#define INIT_PROCESS       5	/* this process was spawned by INIT */
+#define LOGIN_PROCESS      6	/* this is a 'getty' process waiting */
+#define USER_PROCESS       7	/* any other user process */
+#define DEAD_PROCESS       8	/* this process has died (wtmp only) */
+
+#endif /* _UTMP_H */
Index: /trunk/minix/kernel/.depend
===================================================================
--- /trunk/minix/kernel/.depend	(revision 9)
+++ /trunk/minix/kernel/.depend	(revision 9)
@@ -0,0 +1,443 @@
+
+clock.o:	/usr/include/ansi.h
+clock.o:	/usr/include/errno.h
+clock.o:	/usr/include/ibm/bios.h
+clock.o:	/usr/include/ibm/cpu.h
+clock.o:	/usr/include/ibm/interrupt.h
+clock.o:	/usr/include/ibm/portio.h
+clock.o:	/usr/include/ibm/ports.h
+clock.o:	/usr/include/limits.h
+clock.o:	/usr/include/minix/com.h
+clock.o:	/usr/include/minix/config.h
+clock.o:	/usr/include/minix/const.h
+clock.o:	/usr/include/minix/ipc.h
+clock.o:	/usr/include/minix/sys_config.h
+clock.o:	/usr/include/minix/type.h
+clock.o:	/usr/include/signal.h
+clock.o:	/usr/include/sys/dir.h
+clock.o:	/usr/include/sys/types.h
+clock.o:	/usr/include/timers.h
+clock.o:	clock.c
+clock.o:	config.h
+clock.o:	const.h
+clock.o:	debug.h
+clock.o:	glo.h
+clock.o:	ipc.h
+clock.o:	kernel.h
+clock.o:	priv.h
+clock.o:	proc.h
+clock.o:	protect.h
+clock.o:	proto.h
+clock.o:	type.h
+
+debug.o:	/usr/include/ansi.h
+debug.o:	/usr/include/errno.h
+debug.o:	/usr/include/ibm/bios.h
+debug.o:	/usr/include/ibm/cpu.h
+debug.o:	/usr/include/ibm/interrupt.h
+debug.o:	/usr/include/ibm/portio.h
+debug.o:	/usr/include/ibm/ports.h
+debug.o:	/usr/include/limits.h
+debug.o:	/usr/include/minix/com.h
+debug.o:	/usr/include/minix/config.h
+debug.o:	/usr/include/minix/const.h
+debug.o:	/usr/include/minix/ipc.h
+debug.o:	/usr/include/minix/sys_config.h
+debug.o:	/usr/include/minix/type.h
+debug.o:	/usr/include/sys/dir.h
+debug.o:	/usr/include/sys/types.h
+debug.o:	/usr/include/timers.h
+debug.o:	config.h
+debug.o:	const.h
+debug.o:	debug.c
+debug.o:	debug.h
+debug.o:	glo.h
+debug.o:	ipc.h
+debug.o:	kernel.h
+debug.o:	priv.h
+debug.o:	proc.h
+debug.o:	protect.h
+debug.o:	proto.h
+debug.o:	type.h
+
+exception.o:	/usr/include/ansi.h
+exception.o:	/usr/include/errno.h
+exception.o:	/usr/include/ibm/bios.h
+exception.o:	/usr/include/ibm/cpu.h
+exception.o:	/usr/include/ibm/interrupt.h
+exception.o:	/usr/include/ibm/portio.h
+exception.o:	/usr/include/ibm/ports.h
+exception.o:	/usr/include/limits.h
+exception.o:	/usr/include/minix/com.h
+exception.o:	/usr/include/minix/config.h
+exception.o:	/usr/include/minix/const.h
+exception.o:	/usr/include/minix/ipc.h
+exception.o:	/usr/include/minix/sys_config.h
+exception.o:	/usr/include/minix/type.h
+exception.o:	/usr/include/signal.h
+exception.o:	/usr/include/sys/dir.h
+exception.o:	/usr/include/sys/types.h
+exception.o:	/usr/include/timers.h
+exception.o:	config.h
+exception.o:	const.h
+exception.o:	debug.h
+exception.o:	exception.c
+exception.o:	glo.h
+exception.o:	ipc.h
+exception.o:	kernel.h
+exception.o:	priv.h
+exception.o:	proc.h
+exception.o:	protect.h
+exception.o:	proto.h
+exception.o:	type.h
+
+i8259.o:	/usr/include/ansi.h
+i8259.o:	/usr/include/errno.h
+i8259.o:	/usr/include/ibm/bios.h
+i8259.o:	/usr/include/ibm/cpu.h
+i8259.o:	/usr/include/ibm/interrupt.h
+i8259.o:	/usr/include/ibm/portio.h
+i8259.o:	/usr/include/ibm/ports.h
+i8259.o:	/usr/include/limits.h
+i8259.o:	/usr/include/minix/com.h
+i8259.o:	/usr/include/minix/config.h
+i8259.o:	/usr/include/minix/const.h
+i8259.o:	/usr/include/minix/ipc.h
+i8259.o:	/usr/include/minix/sys_config.h
+i8259.o:	/usr/include/minix/type.h
+i8259.o:	/usr/include/sys/dir.h
+i8259.o:	/usr/include/sys/types.h
+i8259.o:	/usr/include/timers.h
+i8259.o:	config.h
+i8259.o:	const.h
+i8259.o:	debug.h
+i8259.o:	glo.h
+i8259.o:	i8259.c
+i8259.o:	ipc.h
+i8259.o:	kernel.h
+i8259.o:	priv.h
+i8259.o:	proc.h
+i8259.o:	protect.h
+i8259.o:	proto.h
+i8259.o:	type.h
+
+kprintf.o:	../lib/sysutil/kprintf.c
+kprintf.o:	/usr/include/ansi.h
+kprintf.o:	/usr/include/errno.h
+kprintf.o:	/usr/include/ibm/bios.h
+kprintf.o:	/usr/include/ibm/cpu.h
+kprintf.o:	/usr/include/ibm/interrupt.h
+kprintf.o:	/usr/include/ibm/portio.h
+kprintf.o:	/usr/include/ibm/ports.h
+kprintf.o:	/usr/include/limits.h
+kprintf.o:	/usr/include/minix/com.h
+kprintf.o:	/usr/include/minix/config.h
+kprintf.o:	/usr/include/minix/const.h
+kprintf.o:	/usr/include/minix/ipc.h
+kprintf.o:	/usr/include/minix/sys_config.h
+kprintf.o:	/usr/include/minix/type.h
+kprintf.o:	/usr/include/signal.h
+kprintf.o:	/usr/include/stdarg.h
+kprintf.o:	/usr/include/stddef.h
+kprintf.o:	/usr/include/sys/dir.h
+kprintf.o:	/usr/include/sys/types.h
+kprintf.o:	/usr/include/timers.h
+kprintf.o:	config.h
+kprintf.o:	const.h
+kprintf.o:	debug.h
+kprintf.o:	glo.h
+kprintf.o:	ipc.h
+kprintf.o:	kernel.h
+kprintf.o:	kprintf.c
+kprintf.o:	priv.h
+kprintf.o:	proc.h
+kprintf.o:	protect.h
+kprintf.o:	proto.h
+kprintf.o:	type.h
+
+main.o:	/usr/include/a.out.h
+main.o:	/usr/include/ansi.h
+main.o:	/usr/include/errno.h
+main.o:	/usr/include/ibm/bios.h
+main.o:	/usr/include/ibm/cpu.h
+main.o:	/usr/include/ibm/interrupt.h
+main.o:	/usr/include/ibm/portio.h
+main.o:	/usr/include/ibm/ports.h
+main.o:	/usr/include/limits.h
+main.o:	/usr/include/minix/callnr.h
+main.o:	/usr/include/minix/com.h
+main.o:	/usr/include/minix/config.h
+main.o:	/usr/include/minix/const.h
+main.o:	/usr/include/minix/endpoint.h
+main.o:	/usr/include/minix/ipc.h
+main.o:	/usr/include/minix/sys_config.h
+main.o:	/usr/include/minix/type.h
+main.o:	/usr/include/signal.h
+main.o:	/usr/include/string.h
+main.o:	/usr/include/sys/dir.h
+main.o:	/usr/include/sys/types.h
+main.o:	/usr/include/timers.h
+main.o:	/usr/include/unistd.h
+main.o:	config.h
+main.o:	const.h
+main.o:	debug.h
+main.o:	glo.h
+main.o:	ipc.h
+main.o:	kernel.h
+main.o:	main.c
+main.o:	priv.h
+main.o:	proc.h
+main.o:	protect.h
+main.o:	proto.h
+main.o:	type.h
+
+proc.o:	/usr/include/ansi.h
+proc.o:	/usr/include/errno.h
+proc.o:	/usr/include/ibm/bios.h
+proc.o:	/usr/include/ibm/cpu.h
+proc.o:	/usr/include/ibm/interrupt.h
+proc.o:	/usr/include/ibm/portio.h
+proc.o:	/usr/include/ibm/ports.h
+proc.o:	/usr/include/limits.h
+proc.o:	/usr/include/minix/callnr.h
+proc.o:	/usr/include/minix/com.h
+proc.o:	/usr/include/minix/config.h
+proc.o:	/usr/include/minix/const.h
+proc.o:	/usr/include/minix/endpoint.h
+proc.o:	/usr/include/minix/ipc.h
+proc.o:	/usr/include/minix/sys_config.h
+proc.o:	/usr/include/minix/type.h
+proc.o:	/usr/include/signal.h
+proc.o:	/usr/include/sys/dir.h
+proc.o:	/usr/include/sys/types.h
+proc.o:	/usr/include/timers.h
+proc.o:	config.h
+proc.o:	const.h
+proc.o:	debug.h
+proc.o:	glo.h
+proc.o:	ipc.h
+proc.o:	kernel.h
+proc.o:	priv.h
+proc.o:	proc.c
+proc.o:	proc.h
+proc.o:	protect.h
+proc.o:	proto.h
+proc.o:	type.h
+
+protect.o:	/usr/include/ansi.h
+protect.o:	/usr/include/errno.h
+protect.o:	/usr/include/ibm/bios.h
+protect.o:	/usr/include/ibm/cpu.h
+protect.o:	/usr/include/ibm/interrupt.h
+protect.o:	/usr/include/ibm/portio.h
+protect.o:	/usr/include/ibm/ports.h
+protect.o:	/usr/include/limits.h
+protect.o:	/usr/include/minix/com.h
+protect.o:	/usr/include/minix/config.h
+protect.o:	/usr/include/minix/const.h
+protect.o:	/usr/include/minix/ipc.h
+protect.o:	/usr/include/minix/sys_config.h
+protect.o:	/usr/include/minix/type.h
+protect.o:	/usr/include/sys/dir.h
+protect.o:	/usr/include/sys/types.h
+protect.o:	/usr/include/timers.h
+protect.o:	config.h
+protect.o:	const.h
+protect.o:	debug.h
+protect.o:	glo.h
+protect.o:	ipc.h
+protect.o:	kernel.h
+protect.o:	priv.h
+protect.o:	proc.h
+protect.o:	protect.c
+protect.o:	protect.h
+protect.o:	proto.h
+protect.o:	type.h
+
+start.o:	/usr/include/ansi.h
+start.o:	/usr/include/errno.h
+start.o:	/usr/include/ibm/bios.h
+start.o:	/usr/include/ibm/cpu.h
+start.o:	/usr/include/ibm/interrupt.h
+start.o:	/usr/include/ibm/portio.h
+start.o:	/usr/include/ibm/ports.h
+start.o:	/usr/include/limits.h
+start.o:	/usr/include/minix/com.h
+start.o:	/usr/include/minix/config.h
+start.o:	/usr/include/minix/const.h
+start.o:	/usr/include/minix/ipc.h
+start.o:	/usr/include/minix/sys_config.h
+start.o:	/usr/include/minix/type.h
+start.o:	/usr/include/stdlib.h
+start.o:	/usr/include/string.h
+start.o:	/usr/include/sys/dir.h
+start.o:	/usr/include/sys/types.h
+start.o:	/usr/include/timers.h
+start.o:	config.h
+start.o:	const.h
+start.o:	debug.h
+start.o:	glo.h
+start.o:	ipc.h
+start.o:	kernel.h
+start.o:	priv.h
+start.o:	proc.h
+start.o:	protect.h
+start.o:	proto.h
+start.o:	start.c
+start.o:	type.h
+
+system.o:	/usr/include/ansi.h
+system.o:	/usr/include/errno.h
+system.o:	/usr/include/ibm/bios.h
+system.o:	/usr/include/ibm/cpu.h
+system.o:	/usr/include/ibm/interrupt.h
+system.o:	/usr/include/ibm/memory.h
+system.o:	/usr/include/ibm/portio.h
+system.o:	/usr/include/ibm/ports.h
+system.o:	/usr/include/limits.h
+system.o:	/usr/include/minix/com.h
+system.o:	/usr/include/minix/config.h
+system.o:	/usr/include/minix/const.h
+system.o:	/usr/include/minix/endpoint.h
+system.o:	/usr/include/minix/ipc.h
+system.o:	/usr/include/minix/sys_config.h
+system.o:	/usr/include/minix/type.h
+system.o:	/usr/include/signal.h
+system.o:	/usr/include/stdlib.h
+system.o:	/usr/include/sys/dir.h
+system.o:	/usr/include/sys/sigcontext.h
+system.o:	/usr/include/sys/types.h
+system.o:	/usr/include/timers.h
+system.o:	/usr/include/unistd.h
+system.o:	config.h
+system.o:	const.h
+system.o:	debug.h
+system.o:	glo.h
+system.o:	ipc.h
+system.o:	kernel.h
+system.o:	priv.h
+system.o:	proc.h
+system.o:	protect.h
+system.o:	proto.h
+system.o:	system.c
+system.o:	system.h
+system.o:	type.h
+
+table.o:	/usr/include/ansi.h
+table.o:	/usr/include/errno.h
+table.o:	/usr/include/ibm/bios.h
+table.o:	/usr/include/ibm/cpu.h
+table.o:	/usr/include/ibm/int86.h
+table.o:	/usr/include/ibm/interrupt.h
+table.o:	/usr/include/ibm/portio.h
+table.o:	/usr/include/ibm/ports.h
+table.o:	/usr/include/limits.h
+table.o:	/usr/include/minix/com.h
+table.o:	/usr/include/minix/config.h
+table.o:	/usr/include/minix/const.h
+table.o:	/usr/include/minix/ipc.h
+table.o:	/usr/include/minix/sys_config.h
+table.o:	/usr/include/minix/type.h
+table.o:	/usr/include/sys/dir.h
+table.o:	/usr/include/sys/types.h
+table.o:	/usr/include/timers.h
+table.o:	config.h
+table.o:	const.h
+table.o:	debug.h
+table.o:	glo.h
+table.o:	ipc.h
+table.o:	kernel.h
+table.o:	priv.h
+table.o:	proc.h
+table.o:	protect.h
+table.o:	proto.h
+table.o:	table.c
+table.o:	type.h
+
+utility.o:	/usr/include/ansi.h
+utility.o:	/usr/include/errno.h
+utility.o:	/usr/include/ibm/bios.h
+utility.o:	/usr/include/ibm/cpu.h
+utility.o:	/usr/include/ibm/interrupt.h
+utility.o:	/usr/include/ibm/portio.h
+utility.o:	/usr/include/ibm/ports.h
+utility.o:	/usr/include/limits.h
+utility.o:	/usr/include/minix/com.h
+utility.o:	/usr/include/minix/config.h
+utility.o:	/usr/include/minix/const.h
+utility.o:	/usr/include/minix/ipc.h
+utility.o:	/usr/include/minix/sys_config.h
+utility.o:	/usr/include/minix/type.h
+utility.o:	/usr/include/sys/dir.h
+utility.o:	/usr/include/sys/types.h
+utility.o:	/usr/include/timers.h
+utility.o:	/usr/include/unistd.h
+utility.o:	config.h
+utility.o:	const.h
+utility.o:	debug.h
+utility.o:	glo.h
+utility.o:	ipc.h
+utility.o:	kernel.h
+utility.o:	proto.h
+utility.o:	type.h
+utility.o:	utility.c
+
+klib.o:	/usr/include/ibm/bios.h
+klib.o:	/usr/include/ibm/cpu.h
+klib.o:	/usr/include/ibm/interrupt.h
+klib.o:	/usr/include/ibm/ports.h
+klib.o:	/usr/include/minix/config.h
+klib.o:	/usr/include/minix/const.h
+klib.o:	/usr/include/minix/sys_config.h
+klib.o:	config.h
+klib.o:	const.h
+klib.o:	klib.s
+klib.o:	klib386.s
+klib.o:	protect.h
+klib.o:	sconst.h
+
+klib386.o:	/usr/include/ibm/bios.h
+klib386.o:	/usr/include/ibm/cpu.h
+klib386.o:	/usr/include/ibm/interrupt.h
+klib386.o:	/usr/include/ibm/ports.h
+klib386.o:	/usr/include/minix/config.h
+klib386.o:	/usr/include/minix/const.h
+klib386.o:	/usr/include/minix/sys_config.h
+klib386.o:	config.h
+klib386.o:	const.h
+klib386.o:	klib386.s
+klib386.o:	protect.h
+klib386.o:	sconst.h
+
+klib88.o:	klib88.s
+
+mpx.o:	/usr/include/ibm/bios.h
+mpx.o:	/usr/include/ibm/cpu.h
+mpx.o:	/usr/include/ibm/interrupt.h
+mpx.o:	/usr/include/ibm/ports.h
+mpx.o:	/usr/include/minix/com.h
+mpx.o:	/usr/include/minix/config.h
+mpx.o:	/usr/include/minix/const.h
+mpx.o:	/usr/include/minix/sys_config.h
+mpx.o:	config.h
+mpx.o:	const.h
+mpx.o:	mpx.s
+mpx.o:	mpx386.s
+mpx.o:	protect.h
+mpx.o:	sconst.h
+
+mpx386.o:	/usr/include/ibm/bios.h
+mpx386.o:	/usr/include/ibm/cpu.h
+mpx386.o:	/usr/include/ibm/interrupt.h
+mpx386.o:	/usr/include/ibm/ports.h
+mpx386.o:	/usr/include/minix/com.h
+mpx386.o:	/usr/include/minix/config.h
+mpx386.o:	/usr/include/minix/const.h
+mpx386.o:	/usr/include/minix/sys_config.h
+mpx386.o:	config.h
+mpx386.o:	const.h
+mpx386.o:	mpx386.s
+mpx386.o:	protect.h
+mpx386.o:	sconst.h
+
+mpx88.o:	mpx88.s
Index: /trunk/minix/kernel/Makefile
===================================================================
--- /trunk/minix/kernel/Makefile	(revision 9)
+++ /trunk/minix/kernel/Makefile	(revision 9)
@@ -0,0 +1,51 @@
+# Makefile for kernel
+
+# Directories
+u = /usr
+i = $u/include
+l = $u/lib
+s = system
+
+# Programs, flags, etc.
+CC =	exec cc
+CPP =	$l/cpp
+LD =	$(CC) -.o
+CFLAGS = -I$i 
+LDFLAGS = -i 
+
+HEAD =	mpx.o
+OBJS =	start.o protect.o klib.o table.o kprintf.o main.o proc.o \
+	i8259.o exception.o system.o clock.o utility.o debug.o
+SYSTEM = system.a
+LIBS = -ltimers 
+
+
+# What to make.
+all: build 
+kernel build install: $(HEAD) $(OBJS) 
+	cd system && $(MAKE) -$(MAKEFLAGS) $@
+	$(LD) $(CFLAGS) $(LDFLAGS) -o kernel \
+	$(HEAD) $(OBJS) \
+	$(SYSTEM) $(LIBS)
+	install -S 0 kernel
+
+clean:
+	cd system && $(MAKE) -$(MAKEFLAGS) $@
+	rm -f *.a *.o *~ *.bak kernel
+
+depend: 
+	cd system && $(MAKE) -$(MAKEFLAGS) $@
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c *.s > .depend
+
+# How to build it
+.s.o:
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+.c.o:
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+# Include generated dependencies.
+klib.o:	klib386.s klib88.s
+mpx.o:	mpx386.s mpx88.s
+include .depend
+
Index: /trunk/minix/kernel/clock.c
===================================================================
--- /trunk/minix/kernel/clock.c	(revision 9)
+++ /trunk/minix/kernel/clock.c	(revision 9)
@@ -0,0 +1,316 @@
+/* This file contains the clock task, which handles time related functions.
+ * Important events that are handled by the CLOCK include setting and 
+ * monitoring alarm timers and deciding when to (re)schedule processes. 
+ * The CLOCK offers a direct interface to kernel processes. System services 
+ * can access its services through system calls, such as sys_setalarm(). The
+ * CLOCK task thus is hidden from the outside world.  
+ *
+ * Changes:
+ *   Oct 08, 2005   reordering and comment editing (A. S. Woodhull)
+ *   Mar 18, 2004   clock interface moved to SYSTEM task (Jorrit N. Herder) 
+ *   Sep 30, 2004   source code documentation updated  (Jorrit N. Herder)
+ *   Sep 24, 2004   redesigned alarm timers  (Jorrit N. Herder)
+ *
+ * The function do_clocktick() is triggered by the clock's interrupt 
+ * handler when a watchdog timer has expired or a process must be scheduled. 
+ *
+ * In addition to the main clock_task() entry point, which starts the main 
+ * loop, there are several other minor entry points:
+ *   clock_stop:	called just before MINIX shutdown
+ *   get_uptime:	get realtime since boot in clock ticks
+ *   set_timer:		set a watchdog timer (+)
+ *   reset_timer:	reset a watchdog timer (+)
+ *   read_clock:	read the counter of channel 0 of the 8253A timer
+ *
+ * (+) The CLOCK task keeps tracks of watchdog timers for the entire kernel.
+ * The watchdog functions of expired timers are executed in do_clocktick(). 
+ * It is crucial that watchdog functions not block, or the CLOCK task may
+ * be blocked. Do not send() a message when the receiver is not expecting it.
+ * Instead, notify(), which always returns, should be used. 
+ */
+
+#include "kernel.h"
+#include "proc.h"
+#include <signal.h>
+#include <minix/com.h>
+
+/* Function prototype for PRIVATE functions. */ 
+FORWARD _PROTOTYPE( void init_clock, (void) );
+FORWARD _PROTOTYPE( int clock_handler, (irq_hook_t *hook) );
+FORWARD _PROTOTYPE( int do_clocktick, (message *m_ptr) );
+FORWARD _PROTOTYPE( void load_update, (void));
+
+/* Clock parameters. */
+#define COUNTER_FREQ (2*TIMER_FREQ) /* counter frequency using square wave */
+#define LATCH_COUNT     0x00	/* cc00xxxx, c = channel, x = any */
+#define SQUARE_WAVE     0x36	/* ccaammmb, a = access, m = mode, b = BCD */
+				/*   11x11, 11 = LSB then MSB, x11 = sq wave */
+#define TIMER_COUNT ((unsigned) (TIMER_FREQ/HZ)) /* initial value for counter*/
+#define TIMER_FREQ  1193182L	/* clock frequency for timer in PC and AT */
+
+#define CLOCK_ACK_BIT	0x80	/* PS/2 clock interrupt acknowledge bit */
+
+/* The CLOCK's timers queue. The functions in <timers.h> operate on this. 
+ * Each system process possesses a single synchronous alarm timer. If other 
+ * kernel parts want to use additional timers, they must declare their own 
+ * persistent (static) timer structure, which can be passed to the clock
+ * via (re)set_timer().
+ * When a timer expires its watchdog function is run by the CLOCK task. 
+ */
+PRIVATE timer_t *clock_timers;		/* queue of CLOCK timers */
+PRIVATE clock_t next_timeout;		/* realtime that next timer expires */
+
+/* The time is incremented by the interrupt handler on each clock tick. */
+PRIVATE clock_t realtime;		/* real time clock */
+PRIVATE irq_hook_t clock_hook;		/* interrupt handler hook */
+
+/*===========================================================================*
+ *				clock_task				     *
+ *===========================================================================*/
+PUBLIC void clock_task()
+{
+/* Main program of clock task. If the call is not HARD_INT it is an error.
+ */
+  message m;			/* message buffer for both input and output */
+  int result;			/* result returned by the handler */
+
+  init_clock();			/* initialize clock task */
+
+  /* Main loop of the clock task.  Get work, process it. Never reply. */
+  while (TRUE) {
+
+      /* Go get a message. */
+      receive(ANY, &m);	
+
+      /* Handle the request. Only clock ticks are expected. */
+      switch (m.m_type) {
+      case HARD_INT:
+          result = do_clocktick(&m);	/* handle clock tick */
+          break;
+      default:				/* illegal request type */
+          kprintf("CLOCK: illegal request %d from %d.\n", m.m_type,m.m_source);
+      }
+  }
+}
+
+/*===========================================================================*
+ *				do_clocktick				     *
+ *===========================================================================*/
+PRIVATE int do_clocktick(m_ptr)
+message *m_ptr;				/* pointer to request message */
+{
+/* Despite its name, this routine is not called on every clock tick. It
+ * is called on those clock ticks when a lot of work needs to be done.
+ */
+
+  /* A process used up a full quantum. The interrupt handler stored this
+   * process in 'prev_ptr'.  First make sure that the process is not on the 
+   * scheduling queues.  Then announce the process ready again. Since it has 
+   * no more time left, it gets a new quantum and is inserted at the right 
+   * place in the queues.  As a side-effect a new process will be scheduled.
+   */ 
+  if (prev_ptr->p_ticks_left <= 0 && priv(prev_ptr)->s_flags & PREEMPTIBLE) {
+      lock_dequeue(prev_ptr);		/* take it off the queues */
+      lock_enqueue(prev_ptr);		/* and reinsert it again */ 
+  }
+
+  /* Check if a clock timer expired and run its watchdog function. */
+  if (next_timeout <= realtime) { 
+  	tmrs_exptimers(&clock_timers, realtime, NULL);
+  	next_timeout = clock_timers == NULL ? 
+		TMR_NEVER : clock_timers->tmr_exp_time;
+  }
+
+  /* Inhibit sending a reply. */
+  return(EDONTREPLY);
+}
+
+/*===========================================================================*
+ *				init_clock				     *
+ *===========================================================================*/
+PRIVATE void init_clock()
+{
+  /* Initialize the CLOCK's interrupt hook. */
+  clock_hook.proc_nr_e = CLOCK;
+
+  /* Initialize channel 0 of the 8253A timer to, e.g., 60 Hz, and register
+   * the CLOCK task's interrupt handler to be run on every clock tick. 
+   */
+  outb(TIMER_MODE, SQUARE_WAVE);	/* set timer to run continuously */
+  outb(TIMER0, TIMER_COUNT);		/* load timer low byte */
+  outb(TIMER0, TIMER_COUNT >> 8);	/* load timer high byte */
+  put_irq_handler(&clock_hook, CLOCK_IRQ, clock_handler);
+  enable_irq(&clock_hook);		/* ready for clock interrupts */
+
+  /* Set a watchdog timer to periodically balance the scheduling queues. */
+  balance_queues(NULL);			/* side-effect sets new timer */
+}
+
+/*===========================================================================*
+ *				clock_stop				     *
+ *===========================================================================*/
+PUBLIC void clock_stop()
+{
+/* Reset the clock to the BIOS rate. (For rebooting.) */
+  outb(TIMER_MODE, 0x36);
+  outb(TIMER0, 0);
+  outb(TIMER0, 0);
+}
+
+/*===========================================================================*
+ *				clock_handler				     *
+ *===========================================================================*/
+PRIVATE int clock_handler(hook)
+irq_hook_t *hook;
+{
+/* This executes on each clock tick (i.e., every time the timer chip generates 
+ * an interrupt). It does a little bit of work so the clock task does not have 
+ * to be called on every tick.  The clock task is called when:
+ *
+ *	(1) the scheduling quantum of the running process has expired, or
+ *	(2) a timer has expired and the watchdog function should be run.
+ *
+ * Many global global and static variables are accessed here.  The safety of
+ * this must be justified. All scheduling and message passing code acquires a 
+ * lock by temporarily disabling interrupts, so no conflicts with calls from 
+ * the task level can occur. Furthermore, interrupts are not reentrant, the 
+ * interrupt handler cannot be bothered by other interrupts.
+ * 
+ * Variables that are updated in the clock's interrupt handler:
+ *	lost_ticks:
+ *		Clock ticks counted outside the clock task. This for example
+ *		is used when the boot monitor processes a real mode interrupt.
+ * 	realtime:
+ * 		The current uptime is incremented with all outstanding ticks.
+ *	proc_ptr, bill_ptr:
+ *		These are used for accounting.  It does not matter if proc.c
+ *		is changing them, provided they are always valid pointers,
+ *		since at worst the previous process would be billed.
+ */
+  register unsigned ticks;
+
+  /* Acknowledge the PS/2 clock interrupt. */
+  if (machine.ps_mca) outb(PORT_B, inb(PORT_B) | CLOCK_ACK_BIT);
+
+  /* Get number of ticks and update realtime. */
+  ticks = lost_ticks + 1;
+  lost_ticks = 0;
+  realtime += ticks;
+
+  /* Update user and system accounting times. Charge the current process for
+   * user time. If the current process is not billable, that is, if a non-user
+   * process is running, charge the billable process for system time as well.
+   * Thus the unbillable process' user time is the billable user's system time.
+   */
+  proc_ptr->p_user_time += ticks;
+  if (priv(proc_ptr)->s_flags & PREEMPTIBLE) {
+      proc_ptr->p_ticks_left -= ticks;
+  }
+  if (! (priv(proc_ptr)->s_flags & BILLABLE)) {
+      bill_ptr->p_sys_time += ticks;
+      bill_ptr->p_ticks_left -= ticks;
+  }
+
+  /* Update load average. */
+  load_update();
+
+  /* Check if do_clocktick() must be called. Done for alarms and scheduling.
+   * Some processes, such as the kernel tasks, cannot be preempted. 
+   */ 
+  if ((next_timeout <= realtime) || (proc_ptr->p_ticks_left <= 0)) {
+      prev_ptr = proc_ptr;			/* store running process */
+      lock_notify(HARDWARE, CLOCK);		/* send notification */
+  } 
+  return(1);					/* reenable interrupts */
+}
+
+/*===========================================================================*
+ *				get_uptime				     *
+ *===========================================================================*/
+PUBLIC clock_t get_uptime()
+{
+/* Get and return the current clock uptime in ticks. */
+  return(realtime);
+}
+
+/*===========================================================================*
+ *				set_timer				     *
+ *===========================================================================*/
+PUBLIC void set_timer(tp, exp_time, watchdog)
+struct timer *tp;		/* pointer to timer structure */
+clock_t exp_time;		/* expiration realtime */
+tmr_func_t watchdog;		/* watchdog to be called */
+{
+/* Insert the new timer in the active timers list. Always update the 
+ * next timeout time by setting it to the front of the active list.
+ */
+  tmrs_settimer(&clock_timers, tp, exp_time, watchdog, NULL);
+  next_timeout = clock_timers->tmr_exp_time;
+}
+
+/*===========================================================================*
+ *				reset_timer				     *
+ *===========================================================================*/
+PUBLIC void reset_timer(tp)
+struct timer *tp;		/* pointer to timer structure */
+{
+/* The timer pointed to by 'tp' is no longer needed. Remove it from both the
+ * active and expired lists. Always update the next timeout time by setting
+ * it to the front of the active list.
+ */
+  tmrs_clrtimer(&clock_timers, tp, NULL);
+  next_timeout = (clock_timers == NULL) ? 
+	TMR_NEVER : clock_timers->tmr_exp_time;
+}
+
+/*===========================================================================*
+ *				read_clock				     *
+ *===========================================================================*/
+PUBLIC unsigned long read_clock()
+{
+/* Read the counter of channel 0 of the 8253A timer.  This counter counts
+ * down at a rate of TIMER_FREQ and restarts at TIMER_COUNT-1 when it
+ * reaches zero. A hardware interrupt (clock tick) occurs when the counter
+ * gets to zero and restarts its cycle.  
+ */
+  unsigned count;
+
+  outb(TIMER_MODE, LATCH_COUNT);
+  count = inb(TIMER0);
+  count |= (inb(TIMER0) << 8);
+  
+  return count;
+}
+
+/*===========================================================================*
+ *				load_update				     * 
+ *===========================================================================*/
+PRIVATE void load_update(void)
+{
+	u16_t slot;
+	int enqueued = -1, q;	/* -1: special compensation for IDLE. */
+	struct proc *p;
+
+	/* Load average data is stored as a list of numbers in a circular
+	 * buffer. Each slot accumulates _LOAD_UNIT_SECS of samples of
+	 * the number of runnable processes. Computations can then
+	 * be made of the load average over variable periods, in the
+	 * user library (see getloadavg(3)).
+	 */
+	slot = (realtime / HZ / _LOAD_UNIT_SECS) % _LOAD_HISTORY;
+	if(slot != kloadinfo.proc_last_slot) {
+		kloadinfo.proc_load_history[slot] = 0;
+		kloadinfo.proc_last_slot = slot;
+	}
+
+	/* Cumulation. How many processes are ready now? */
+	for(q = 0; q < NR_SCHED_QUEUES; q++)
+		for(p = rdy_head[q]; p != NIL_PROC; p = p->p_nextready)
+			enqueued++;
+
+	kloadinfo.proc_load_history[slot] += enqueued;
+
+	/* Up-to-dateness. */
+	kloadinfo.last_clock = realtime;
+}
+
Index: /trunk/minix/kernel/config.h
===================================================================
--- /trunk/minix/kernel/config.h	(revision 9)
+++ /trunk/minix/kernel/config.h	(revision 9)
@@ -0,0 +1,82 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+
+/* This file defines the kernel configuration. It allows to set sizes of some
+ * kernel buffers and to enable or disable debugging code, timing features, 
+ * and individual kernel calls.
+ *
+ * Changes:
+ *   Jul 11, 2005	Created.  (Jorrit N. Herder)
+ */
+
+/* In embedded and sensor applications, not all the kernel calls may be
+ * needed. In this section you can specify which kernel calls are needed
+ * and which are not. The code for unneeded kernel calls is not included in
+ * the system binary, making it smaller. If you are not sure, it is best
+ * to keep all kernel calls enabled.
+ */
+#define USE_FORK       	   1	/* fork a new process */
+#define USE_NEWMAP     	   1	/* set a new memory map */
+#define USE_EXEC       	   1	/* update process after execute */
+#define USE_EXIT	   1	/* clean up after process exit */
+#define USE_TRACE      	   1	/* process information and tracing */
+#define USE_GETKSIG    	   1	/* retrieve pending kernel signals */
+#define USE_ENDKSIG    	   1	/* finish pending kernel signals */
+#define USE_KILL       	   1 	/* send a signal to a process */
+#define USE_SIGSEND    	   1	/* send POSIX-style signal */
+#define USE_SIGRETURN  	   1	/* sys_sigreturn(proc_nr, ctxt_ptr, flags) */
+#define USE_ABORT      	   1	/* shut down MINIX */
+#define USE_GETINFO    	   1 	/* retrieve a copy of kernel data */
+#define USE_TIMES 	   1	/* get process and system time info */
+#define USE_SETALARM	   1	/* schedule a synchronous alarm */
+#define USE_DEVIO      	   1	/* read or write a single I/O port */
+#define USE_VDEVIO     	   1	/* process vector with I/O requests */
+#define USE_SDEVIO     	   1	/* perform I/O request on a buffer */
+#define USE_IRQCTL     	   1	/* set an interrupt policy */
+#define USE_SEGCTL     	   1	/* set up a remote segment */
+#define USE_PRIVCTL    	   1	/* system privileges control */
+#define USE_NICE 	   1	/* change scheduling priority */
+#define USE_UMAP       	   1	/* map virtual to physical address */
+#define USE_VIRCOPY   	   1	/* copy using virtual addressing */ 
+#define USE_VIRVCOPY  	   1	/* vector with virtual copy requests */
+#define USE_PHYSCOPY  	   1 	/* copy using physical addressing */
+#define USE_PHYSVCOPY  	   1	/* vector with physical copy requests */
+#define USE_MEMSET  	   1	/* write char to a given memory area */
+
+/* Length of program names stored in the process table. This is only used
+ * for the debugging dumps that can be generated with the IS server. The PM
+ * server keeps its own copy of the program name.  
+ */
+#define P_NAME_LEN	   8
+
+/* Kernel diagnostics are written to a circular buffer. After each message, 
+ * a system server is notified and a copy of the buffer can be retrieved to 
+ * display the message. The buffers size can safely be reduced.  
+ */
+#define KMESS_BUF_SIZE   256   	
+
+/* Buffer to gather randomness. This is used to generate a random stream by 
+ * the MEMORY driver when reading from /dev/random. 
+ */
+#define RANDOM_ELEMENTS   32
+
+/* This section contains defines for valuable system resources that are used
+ * by device drivers. The number of elements of the vectors is determined by 
+ * the maximum needed by any given driver. The number of interrupt hooks may
+ * be incremented on systems with many device drivers. 
+ */
+#define NR_IRQ_HOOKS	  16		/* number of interrupt hooks */
+#define VDEVIO_BUF_SIZE   64		/* max elements per VDEVIO request */
+#define VCOPY_VEC_SIZE    16		/* max elements per VCOPY request */
+
+/* How many bytes for the kernel stack. Space allocated in mpx.s. */
+#define K_STACK_BYTES   1024	
+
+/* This section allows to enable kernel debugging and timing functionality.
+ * For normal operation all options should be disabled.
+ */
+#define DEBUG_SCHED_CHECK  0	/* sanity check of scheduling queues */
+#define DEBUG_TIME_LOCKS   0	/* measure time spent in locks */
+
+#endif /* CONFIG_H */
+
Index: /trunk/minix/kernel/const.h
===================================================================
--- /trunk/minix/kernel/const.h	(revision 9)
+++ /trunk/minix/kernel/const.h	(revision 9)
@@ -0,0 +1,91 @@
+/* General macros and constants used by the kernel. */
+#ifndef CONST_H
+#define CONST_H
+
+#include <ibm/interrupt.h>	/* interrupt numbers and hardware vectors */
+#include <ibm/ports.h>		/* port addresses and magic numbers */
+#include <ibm/bios.h>		/* BIOS addresses, sizes and magic numbers */
+#include <ibm/cpu.h>		/* BIOS addresses, sizes and magic numbers */
+#include <minix/config.h>
+#include "config.h"
+
+/* To translate an address in kernel space to a physical address.  This is
+ * the same as umap_local(proc_ptr, D, vir, sizeof(*vir)), but less costly.
+ */
+#define vir2phys(vir)	(kinfo.data_base + (vir_bytes) (vir))
+
+/* Map a process number to a privilege structure id. */
+#define s_nr_to_id(n)	(NR_TASKS + (n) + 1)
+
+/* Translate a pointer to a field in a structure to a pointer to the structure
+ * itself. So it translates '&struct_ptr->field' back to 'struct_ptr'.
+ */
+#define structof(type, field, ptr) \
+	((type *) (((char *) (ptr)) - offsetof(type, field)))
+
+/* Translate an endpoint number to a process number, return success. */
+#define isokendpt(e,p) isokendpt_d((e),(p),0)
+#define okendpt(e,p)   isokendpt_d((e),(p),1)
+
+/* Constants used in virtual_copy(). Values must be 0 and 1, respectively. */
+#define _SRC_	0
+#define _DST_	1
+
+/* Number of random sources */
+#define RANDOM_SOURCES	16
+
+/* Constants and macros for bit map manipulation. */
+#define BITCHUNK_BITS   (sizeof(bitchunk_t) * CHAR_BIT)
+#define BITMAP_CHUNKS(nr_bits) (((nr_bits)+BITCHUNK_BITS-1)/BITCHUNK_BITS)  
+#define MAP_CHUNK(map,bit) (map)[((bit)/BITCHUNK_BITS)]
+#define CHUNK_OFFSET(bit) ((bit)%BITCHUNK_BITS))
+#define GET_BIT(map,bit) ( MAP_CHUNK(map,bit) & (1 << CHUNK_OFFSET(bit) )
+#define SET_BIT(map,bit) ( MAP_CHUNK(map,bit) |= (1 << CHUNK_OFFSET(bit) )
+#define UNSET_BIT(map,bit) ( MAP_CHUNK(map,bit) &= ~(1 << CHUNK_OFFSET(bit) )
+
+#define get_sys_bit(map,bit) \
+	( MAP_CHUNK(map.chunk,bit) & (1 << CHUNK_OFFSET(bit) )
+#define set_sys_bit(map,bit) \
+	( MAP_CHUNK(map.chunk,bit) |= (1 << CHUNK_OFFSET(bit) )
+#define unset_sys_bit(map,bit) \
+	( MAP_CHUNK(map.chunk,bit) &= ~(1 << CHUNK_OFFSET(bit) )
+#define NR_SYS_CHUNKS	BITMAP_CHUNKS(NR_SYS_PROCS)
+
+#if (CHIP == INTEL)
+
+/* Program stack words and masks. */
+#define INIT_PSW      0x0200	/* initial psw */
+#define INIT_TASK_PSW 0x1200	/* initial psw for tasks (with IOPL 1) */
+#define TRACEBIT      0x0100	/* OR this with psw in proc[] for tracing */
+#define SETPSW(rp, new)		/* permits only certain bits to be set */ \
+	((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xCD5 | (new) & 0xCD5)
+#define IF_MASK 0x00000200
+#define IOPL_MASK 0x003000
+
+#if DEBUG_LOCK_CHECK
+#define reallock(c, v)	{ if (!(read_cpu_flags() & X86_FLAG_I)) { kinfo.relocking++; } else { intr_disable(); } }
+#else
+#define reallock(c, v)	intr_disable()
+#endif
+
+#define realunlock(c)	intr_enable()
+
+/* Disable/ enable hardware interrupts. The parameters of lock() and unlock()
+ * are used when debugging is enabled. See debug.h for more information.
+ */
+#define lock(c, v)	reallock(c, v)
+#define unlock(c)	realunlock(c) 
+
+/* Sizes of memory tables. The boot monitor distinguishes three memory areas, 
+ * namely low mem below 1M, 1M-16M, and mem after 16M. More chunks are needed
+ * for DOS MINIX.
+ */
+#define NR_MEMS            8	
+
+#endif /* (CHIP == INTEL) */
+
+#if (CHIP == M68000)
+/* M68000 specific constants go here. */
+#endif /* (CHIP == M68000) */
+
+#endif /* CONST_H */
Index: /trunk/minix/kernel/debug.c
===================================================================
--- /trunk/minix/kernel/debug.c	(revision 9)
+++ /trunk/minix/kernel/debug.c	(revision 9)
@@ -0,0 +1,166 @@
+/* This file implements kernel debugging functionality that is not included
+ * in the standard kernel. Available functionality includes timing of lock
+ * functions and sanity checking of the scheduling queues.
+ */
+
+#include "kernel.h"
+#include "proc.h"
+#include "debug.h"
+#include <limits.h>
+
+#if DEBUG_TIME_LOCKS		/* only include code if enabled */
+
+/* Data structures to store lock() timing data. */
+struct lock_timingdata timingdata[TIMING_CATEGORIES];
+static unsigned long starttimes[TIMING_CATEGORIES][2];
+
+#define HIGHCOUNT	0
+#define LOWCOUNT	1
+
+void timer_start(int cat, char *name)
+{
+	static int init = 0;
+	unsigned long h, l;
+	int i;
+
+	if (cat < 0 || cat >= TIMING_CATEGORIES) return;
+
+	for(i = 0; i < sizeof(timingdata[0].names) && *name; i++)
+		timingdata[cat].names[i] = *name++;
+	timingdata[0].names[sizeof(timingdata[0].names)-1] = '\0';
+
+	if (starttimes[cat][HIGHCOUNT]) {  return; }
+
+	if (!init) {
+		int t, f;
+		init = 1;
+		for(t = 0; t < TIMING_CATEGORIES; t++) {
+			timingdata[t].lock_timings_range[0] = 0;
+			timingdata[t].resets = timingdata[t].misses = 
+				timingdata[t].measurements = 0;
+		}
+	}
+
+	read_tsc(&starttimes[cat][HIGHCOUNT], &starttimes[cat][LOWCOUNT]);
+}
+
+void timer_end(int cat)
+{
+	unsigned long h, l, d = 0, binsize;
+	int bin;
+
+	read_tsc(&h, &l);
+	if (cat < 0 || cat >= TIMING_CATEGORIES) return;
+	if (!starttimes[cat][HIGHCOUNT]) {
+		timingdata[cat].misses++;
+		return;
+	}
+	if (starttimes[cat][HIGHCOUNT] == h) {
+		d = (l - starttimes[cat][1]);
+	} else if (starttimes[cat][HIGHCOUNT] == h-1 &&
+		starttimes[cat][LOWCOUNT] > l) {
+		d = ((ULONG_MAX - starttimes[cat][LOWCOUNT]) + l);
+	} else {
+		timingdata[cat].misses++;
+		return;
+	}
+	starttimes[cat][HIGHCOUNT] = 0;
+	if (!timingdata[cat].lock_timings_range[0] ||
+		d < timingdata[cat].lock_timings_range[0] ||
+		d > timingdata[cat].lock_timings_range[1]) {
+		int t;
+		if (!timingdata[cat].lock_timings_range[0] ||
+			d < timingdata[cat].lock_timings_range[0])
+			timingdata[cat].lock_timings_range[0] = d;
+		if (!timingdata[cat].lock_timings_range[1] ||
+			d > timingdata[cat].lock_timings_range[1])
+			timingdata[cat].lock_timings_range[1] = d;
+		for(t = 0; t < TIMING_POINTS; t++)
+			timingdata[cat].lock_timings[t] = 0;
+		timingdata[cat].binsize =
+			(timingdata[cat].lock_timings_range[1] -
+			timingdata[cat].lock_timings_range[0])/(TIMING_POINTS+1);
+		if (timingdata[cat].binsize < 1)
+		  timingdata[cat].binsize = 1;
+		timingdata[cat].resets++;
+	}
+	bin = (d-timingdata[cat].lock_timings_range[0]) /
+		timingdata[cat].binsize;
+	if (bin < 0 || bin >= TIMING_POINTS) {
+		int t;
+		/* this indicates a bug, but isn't really serious */
+		for(t = 0; t < TIMING_POINTS; t++)
+			timingdata[cat].lock_timings[t] = 0;
+		timingdata[cat].misses++;
+	} else {
+		timingdata[cat].lock_timings[bin]++;
+		timingdata[cat].measurements++;
+	}
+
+	return;
+}
+
+#endif /* DEBUG_TIME_LOCKS */
+
+#if DEBUG_SCHED_CHECK		/* only include code if enabled */
+
+#define PROCLIMIT 10000
+
+PUBLIC void
+check_runqueues(char *when)
+{
+  int q, l = 0;
+  register struct proc *xp;
+
+  for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
+	xp->p_found = 0;
+	if (l++ > PROCLIMIT) {  panic("check error", NO_NUM); }
+  }
+
+  for (q=0; q < NR_SCHED_QUEUES; q++) {
+    if (rdy_head[q] && !rdy_tail[q]) {
+	kprintf("head but no tail: %s", when);
+		 panic("scheduling error", NO_NUM);
+    }
+    if (!rdy_head[q] && rdy_tail[q]) {
+	kprintf("tail but no head: %s", when);
+		 panic("scheduling error", NO_NUM);
+    }
+    if (rdy_tail[q] && rdy_tail[q]->p_nextready != NIL_PROC) {
+	kprintf("tail and tail->next not null; %s", when);
+		 panic("scheduling error", NO_NUM);
+    }
+    for(xp = rdy_head[q]; xp != NIL_PROC; xp = xp->p_nextready) {
+        if (!xp->p_ready) {
+		kprintf("scheduling error: unready on runq: %s\n", when);
+		
+  		panic("found unready process on run queue", NO_NUM);
+        }
+        if (xp->p_priority != q) {
+		kprintf("scheduling error: wrong priority: %s\n", when);
+		
+		panic("wrong priority", NO_NUM);
+	}
+	if (xp->p_found) {
+		kprintf("scheduling error: double scheduling: %s\n", when);
+		panic("proc more than once on scheduling queue", NO_NUM);
+	}
+	xp->p_found = 1;
+	if (xp->p_nextready == NIL_PROC && rdy_tail[q] != xp) {
+		kprintf("scheduling error: last element not tail: %s\n", when);
+		panic("scheduling error", NO_NUM);
+	}
+	if (l++ > PROCLIMIT) panic("loop in schedule queue?", NO_NUM);
+    }
+  }	
+
+  for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
+	if (! isemptyp(xp) && xp->p_ready && ! xp->p_found) {
+		kprintf("scheduling error: ready not on queue: %s\n", when);
+		panic("ready proc not on scheduling queue", NO_NUM);
+		if (l++ > PROCLIMIT) { panic("loop in proc.t?", NO_NUM); }
+	}
+  }
+}
+
+#endif /* DEBUG_SCHED_CHECK */
Index: /trunk/minix/kernel/debug.h
===================================================================
--- /trunk/minix/kernel/debug.h	(revision 9)
+++ /trunk/minix/kernel/debug.h	(revision 9)
@@ -0,0 +1,72 @@
+#ifndef DEBUG_H
+#define DEBUG_H
+
+/* This header file defines all debugging constants and macros, and declares
+ * some variables. Certain debugging features redefine standard constants
+ * and macros. Therefore, this header file should be included after the
+ * other kernel headers.
+ */
+
+#include "config.h"
+
+/* Enable prints such as
+ *  . send/receive failed due to deadlock or dead source or dead destination
+ *  . trap not allowed
+ *  . bogus message pointer
+ *  . kernel call number not allowed by this process
+ *
+ * Of course the call still fails, but nothing is printed if these warnings
+ * are disabled.
+ */
+#define DEBUG_ENABLE_IPC_WARNINGS	0
+
+/* It's interesting to measure the time spent withing locked regions, because
+ * this is the time that the system is deaf to interrupts.
+ */
+#if DEBUG_TIME_LOCKS
+
+#define TIMING_POINTS		20	/* timing resolution */
+#define TIMING_CATEGORIES	20
+#define TIMING_NAME		10
+
+/* Definition of the data structure to store lock() timing data. */ 
+struct lock_timingdata {
+	char names[TIMING_NAME];
+	unsigned long lock_timings[TIMING_POINTS];
+	unsigned long lock_timings_range[2];
+	unsigned long binsize, resets, misses, measurements;
+};
+
+/* The data is declared here, but allocated in debug.c. */
+extern struct lock_timingdata timingdata[TIMING_CATEGORIES];
+
+/* Prototypes for the timing functionality. */
+_PROTOTYPE( void timer_start, (int cat, char *name) );
+_PROTOTYPE( void timer_end, (int cat) );
+
+#define locktimestart(c, v) timer_start(c, v)
+#define locktimeend(c) timer_end(c)
+#else
+#define locktimestart(c, v)
+#define locktimeend(c)
+#endif /* DEBUG_TIME_LOCKS */
+
+/* This check makes sure that the scheduling queues are in a consistent state.
+ * The check is run when the queues are updated with ready() and unready().
+ */ 
+#if DEBUG_SCHED_CHECK 					
+_PROTOTYPE( void check_runqueues, (char *when) );
+#endif /* DEBUG_SCHED_CHECK */
+
+/* The timing and checking of kernel locking requires a redefine of the lock()
+ * and unlock() macros. That's done here. This redefine requires that this 
+ * header is included after the other kernel headers.
+ */
+#if (DEBUG_TIME_LOCKS || DEBUG_LOCK_CHECK)
+#  undef lock
+#  define lock(c, v)	do { reallock(c, v); locktimestart(c, v); } while(0)
+#  undef unlock
+#  define unlock(c)	do { locktimeend(c); realunlock(c); } while(0)
+#endif
+
+#endif /* DEBUG_H */
Index: /trunk/minix/kernel/exception.c
===================================================================
--- /trunk/minix/kernel/exception.c	(revision 9)
+++ /trunk/minix/kernel/exception.c	(revision 9)
@@ -0,0 +1,76 @@
+/* This file contains a simple exception handler.  Exceptions in user
+ * processes are converted to signals. Exceptions in a kernel task cause
+ * a panic.
+ */
+
+#include "kernel.h"
+#include <signal.h>
+#include "proc.h"
+
+/*===========================================================================*
+ *				exception				     *
+ *===========================================================================*/
+PUBLIC void exception(vec_nr)
+unsigned vec_nr;
+{
+/* An exception or unexpected interrupt has occurred. */
+
+  struct ex_s {
+	char *msg;
+	int signum;
+	int minprocessor;
+  };
+  static struct ex_s ex_data[] = {
+	{ "Divide error", SIGFPE, 86 },
+	{ "Debug exception", SIGTRAP, 86 },
+	{ "Nonmaskable interrupt", SIGBUS, 86 },
+	{ "Breakpoint", SIGEMT, 86 },
+	{ "Overflow", SIGFPE, 86 },
+	{ "Bounds check", SIGFPE, 186 },
+	{ "Invalid opcode", SIGILL, 186 },
+	{ "Coprocessor not available", SIGFPE, 186 },
+	{ "Double fault", SIGBUS, 286 },
+	{ "Copressor segment overrun", SIGSEGV, 286 },
+	{ "Invalid TSS", SIGSEGV, 286 },
+	{ "Segment not present", SIGSEGV, 286 },
+	{ "Stack exception", SIGSEGV, 286 },	/* STACK_FAULT already used */
+	{ "General protection", SIGSEGV, 286 },
+	{ "Page fault", SIGSEGV, 386 },		/* not close */
+	{ NIL_PTR, SIGILL, 0 },			/* probably software trap */
+	{ "Coprocessor error", SIGFPE, 386 },
+  };
+  register struct ex_s *ep;
+  struct proc *saved_proc;
+
+  /* Save proc_ptr, because it may be changed by debug statements. */
+  saved_proc = proc_ptr;	
+
+  ep = &ex_data[vec_nr];
+
+  if (vec_nr == 2) {		/* spurious NMI on some machines */
+	kprintf("got spurious NMI\n");
+	return;
+  }
+
+  /* If an exception occurs while running a process, the k_reenter variable 
+   * will be zero. Exceptions in interrupt handlers or system traps will make 
+   * k_reenter larger than zero.
+   */
+  if (k_reenter == 0 && ! iskernelp(saved_proc)) {
+	cause_sig(proc_nr(saved_proc), ep->signum);
+	return;
+  }
+
+  /* Exception in system code. This is not supposed to happen. */
+  if (ep->msg == NIL_PTR || machine.processor < ep->minprocessor)
+	kprintf("\nIntel-reserved exception %d\n", vec_nr);
+  else
+	kprintf("\n%s\n", ep->msg);
+  kprintf("k_reenter = %d ", k_reenter);
+  kprintf("process %d (%s), ", proc_nr(saved_proc), saved_proc->p_name);
+  kprintf("pc = %u:0x%x", (unsigned) saved_proc->p_reg.cs,
+  (unsigned) saved_proc->p_reg.pc);
+
+  panic("exception in a kernel task", NO_NUM);
+}
+
Index: /trunk/minix/kernel/glo.h
===================================================================
--- /trunk/minix/kernel/glo.h	(revision 9)
+++ /trunk/minix/kernel/glo.h	(revision 9)
@@ -0,0 +1,68 @@
+#ifndef GLO_H
+#define GLO_H
+
+/* Global variables used in the kernel. This file contains the declarations;
+ * storage space for the variables is allocated in table.c, because EXTERN is
+ * defined as extern unless the _TABLE definition is seen. We rely on the 
+ * compiler's default initialization (0) for several global variables. 
+ */
+#ifdef _TABLE
+#undef EXTERN
+#define EXTERN
+#endif
+
+#include <minix/config.h>
+#include "config.h"
+
+/* Variables relating to shutting down MINIX. */
+EXTERN char kernel_exception;		/* TRUE after system exceptions */
+EXTERN char shutdown_started;		/* TRUE after shutdowns / reboots */
+
+/* Kernel information structures. This groups vital kernel information. */
+EXTERN phys_bytes aout;			/* address of a.out headers */
+EXTERN struct kinfo kinfo;		/* kernel information for users */
+EXTERN struct machine machine;		/* machine information for users */
+EXTERN struct kmessages kmess;  	/* diagnostic messages in kernel */
+EXTERN struct randomness krandom;	/* gather kernel random information */
+EXTERN struct loadinfo kloadinfo;	/* status of load average */
+
+/* Process scheduling information and the kernel reentry count. */
+EXTERN struct proc *prev_ptr;	/* previously running process */
+EXTERN struct proc *proc_ptr;	/* pointer to currently running process */
+EXTERN struct proc *next_ptr;	/* next process to run after restart() */
+EXTERN struct proc *bill_ptr;	/* process to bill for clock ticks */
+EXTERN char k_reenter;		/* kernel reentry count (entry count less 1) */
+EXTERN unsigned lost_ticks;	/* clock ticks counted outside clock task */
+
+#if (CHIP == INTEL)
+
+/* Interrupt related variables. */
+EXTERN irq_hook_t irq_hooks[NR_IRQ_HOOKS];	/* hooks for general use */
+EXTERN irq_hook_t *irq_handlers[NR_IRQ_VECTORS];/* list of IRQ handlers */
+EXTERN int irq_actids[NR_IRQ_VECTORS];		/* IRQ ID bits active */
+EXTERN int irq_use;				/* map of all in-use irq's */
+
+/* Miscellaneous. */
+EXTERN reg_t mon_ss, mon_sp;		/* boot monitor stack */
+EXTERN int mon_return;			/* true if we can return to monitor */
+EXTERN int do_serial_debug;
+EXTERN int who_e, who_p;		/* message source endpoint and proc */
+
+/* VM */
+EXTERN phys_bytes vm_base;
+EXTERN phys_bytes vm_size;
+EXTERN phys_bytes vm_mem_high;
+
+/* Variables that are initialized elsewhere are just extern here. */
+extern struct boot_image image[]; 	/* system image processes */
+extern char *t_stack[];			/* task stack space */
+extern struct segdesc_s gdt[];		/* global descriptor table */
+
+EXTERN _PROTOTYPE( void (*level0_func), (void) );
+#endif /* (CHIP == INTEL) */
+
+#if (CHIP == M68000)
+/* M68000 specific variables go here. */
+#endif
+
+#endif /* GLO_H */
Index: /trunk/minix/kernel/i8259.c
===================================================================
--- /trunk/minix/kernel/i8259.c	(revision 9)
+++ /trunk/minix/kernel/i8259.c	(revision 9)
@@ -0,0 +1,193 @@
+/* This file contains routines for initializing the 8259 interrupt controller:
+ *	put_irq_handler: register an interrupt handler
+ *	rm_irq_handler: deregister an interrupt handler
+ *	intr_handle:	handle a hardware interrupt
+ *	intr_init:	initialize the interrupt controller(s)
+ */
+
+#include "kernel.h"
+#include "proc.h"
+#include <minix/com.h>
+
+#define ICW1_AT         0x11	/* edge triggered, cascade, need ICW4 */
+#define ICW1_PC         0x13	/* edge triggered, no cascade, need ICW4 */
+#define ICW1_PS         0x19	/* level triggered, cascade, need ICW4 */
+#define ICW4_AT_SLAVE   0x01	/* not SFNM, not buffered, normal EOI, 8086 */
+#define ICW4_AT_MASTER  0x05	/* not SFNM, not buffered, normal EOI, 8086 */
+#define ICW4_PC_SLAVE   0x09	/* not SFNM, buffered, normal EOI, 8086 */
+#define ICW4_PC_MASTER  0x0D	/* not SFNM, buffered, normal EOI, 8086 */
+
+#if _WORD_SIZE == 2
+typedef _PROTOTYPE( void (*vecaddr_t), (void) );
+
+FORWARD _PROTOTYPE( void set_vec, (int vec_nr, vecaddr_t addr) );
+
+PRIVATE vecaddr_t int_vec[] = {
+  int00, int01, int02, int03, int04, int05, int06, int07,
+};
+
+PRIVATE vecaddr_t irq_vec[] = {
+  hwint00, hwint01, hwint02, hwint03, hwint04, hwint05, hwint06, hwint07,
+  hwint08, hwint09, hwint10, hwint11, hwint12, hwint13, hwint14, hwint15,
+};
+#else
+#define set_vec(nr, addr)	((void)0)
+#endif
+
+/*===========================================================================*
+ *				intr_init				     *
+ *===========================================================================*/
+PUBLIC void intr_init(mine)
+int mine;
+{
+/* Initialize the 8259s, finishing with all interrupts disabled.  This is
+ * only done in protected mode, in real mode we don't touch the 8259s, but
+ * use the BIOS locations instead.  The flag "mine" is set if the 8259s are
+ * to be programmed for MINIX, or to be reset to what the BIOS expects.
+ */
+  int i;
+
+  intr_disable();
+
+  if (machine.prot) {
+      /* The AT and newer PS/2 have two interrupt controllers, one master,
+       * one slaved at IRQ 2.  (We don't have to deal with the PC that
+       * has just one controller, because it must run in real mode.)
+       */
+      outb(INT_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
+      outb(INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC);
+							/* ICW2 for master */
+      outb(INT_CTLMASK, (1 << CASCADE_IRQ));		/* ICW3 tells slaves */
+      outb(INT_CTLMASK, ICW4_AT_MASTER);
+      outb(INT_CTLMASK, ~(1 << CASCADE_IRQ));		/* IRQ 0-7 mask */
+      outb(INT2_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
+      outb(INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC);
+							/* ICW2 for slave */
+      outb(INT2_CTLMASK, CASCADE_IRQ);		/* ICW3 is slave nr */
+      outb(INT2_CTLMASK, ICW4_AT_SLAVE);
+      outb(INT2_CTLMASK, ~0);				/* IRQ 8-15 mask */
+
+      /* Copy the BIOS vectors from the BIOS to the Minix location, so we
+       * can still make BIOS calls without reprogramming the i8259s.
+       */
+#if IRQ0_VECTOR != BIOS_IRQ0_VEC
+      phys_copy(BIOS_VECTOR(0) * 4L, VECTOR(0) * 4L, 8 * 4L);
+#endif
+#if IRQ8_VECTOR != BIOS_IRQ8_VEC
+      phys_copy(BIOS_VECTOR(8) * 4L, VECTOR(8) * 4L, 8 * 4L);
+#endif
+  } else {
+      /* Use the BIOS interrupt vectors in real mode.  We only reprogram the
+       * exceptions here, the interrupt vectors are reprogrammed on demand.
+       * SYS_VECTOR is the Minix system call for message passing.
+       */
+      for (i = 0; i < 8; i++) set_vec(i, int_vec[i]);
+      set_vec(SYS_VECTOR, s_call);
+  }
+}
+
+/*===========================================================================*
+ *				put_irq_handler				     *
+ *===========================================================================*/
+PUBLIC void put_irq_handler(hook, irq, handler)
+irq_hook_t *hook;
+int irq;
+irq_handler_t handler;
+{
+/* Register an interrupt handler. */
+  int id;
+  irq_hook_t **line;
+
+  if (irq < 0 || irq >= NR_IRQ_VECTORS)
+      panic("invalid call to put_irq_handler", irq);
+
+  line = &irq_handlers[irq];
+  id = 1;
+  while (*line != NULL) {
+      if (hook == *line) return;	/* extra initialization */
+      line = &(*line)->next;
+      id <<= 1;
+  }
+  if (id == 0) panic("Too many handlers for irq", irq);
+
+  hook->next = NULL;
+  hook->handler = handler;
+  hook->irq = irq;
+  hook->id = id;
+  *line = hook;
+
+  irq_use |= 1 << irq;
+}
+
+/*===========================================================================*
+ *				rm_irq_handler				     *
+ *===========================================================================*/
+PUBLIC void rm_irq_handler(hook)
+irq_hook_t *hook;
+{
+/* Unregister an interrupt handler. */
+  int irq = hook->irq; 
+  int id = hook->id;
+  irq_hook_t **line;
+
+  if (irq < 0 || irq >= NR_IRQ_VECTORS) 
+      panic("invalid call to rm_irq_handler", irq);
+
+  line = &irq_handlers[irq];
+  while (*line != NULL) {
+      if ((*line)->id == id) {
+          (*line) = (*line)->next;
+          if (! irq_handlers[irq]) irq_use &= ~(1 << irq);
+          return;
+      }
+      line = &(*line)->next;
+  }
+  /* When the handler is not found, normally return here. */
+}
+
+/*===========================================================================*
+ *				intr_handle				     *
+ *===========================================================================*/
+PUBLIC void intr_handle(hook)
+irq_hook_t *hook;
+{
+/* Call the interrupt handlers for an interrupt with the given hook list.
+ * The assembly part of the handler has already masked the IRQ, reenabled the
+ * controller(s) and enabled interrupts.
+ */
+
+  /* Call list of handlers for an IRQ. */
+  while (hook != NULL) {
+      /* For each handler in the list, mark it active by setting its ID bit,
+       * call the function, and unmark it if the function returns true.
+       */
+      irq_actids[hook->irq] |= hook->id;
+      if ((*hook->handler)(hook)) irq_actids[hook->irq] &= ~hook->id;
+      hook = hook->next;
+  }
+
+  /* The assembly code will now disable interrupts, unmask the IRQ if and only
+   * if all active ID bits are cleared, and restart a process.
+   */
+}
+
+#if _WORD_SIZE == 2
+/*===========================================================================*
+ *				set_vec                                      *
+ *===========================================================================*/
+PRIVATE void set_vec(vec_nr, addr)
+int vec_nr;			/* which vector */
+vecaddr_t addr;			/* where to start */
+{
+/* Set up a real mode interrupt vector. */
+
+  u16_t vec[2];
+
+  /* Build the vector in the array 'vec'. */
+  vec[0] = (u16_t) addr;
+  vec[1] = (u16_t) physb_to_hclick(code_base);
+
+  /* Copy the vector into place. */
+  phys_copy(vir2phys(vec), vec_nr * 4L, 4L);
+}
+#endif /* _WORD_SIZE == 2 */
Index: /trunk/minix/kernel/ipc.h
===================================================================
--- /trunk/minix/kernel/ipc.h	(revision 9)
+++ /trunk/minix/kernel/ipc.h	(revision 9)
@@ -0,0 +1,34 @@
+#ifndef IPC_H
+#define IPC_H
+
+/* This header file defines constants for MINIX inter-process communication.
+ * These definitions are used in the file proc.c.
+ */
+#include <minix/com.h>
+
+/* Masks and flags for system calls. */
+#define SYSCALL_FUNC	0x000F	/* mask for system call function */
+#define SYSCALL_FLAGS   0x00F0  /* mask for system call flags */
+#define NON_BLOCKING    0x0010  /* do not block if target not ready */
+
+/* System call numbers that are passed when trapping to the kernel. The 
+ * numbers are carefully defined so that it can easily be seen (based on 
+ * the bits that are on) which checks should be done in sys_call().
+ */
+#define SEND		   1	/* 0001 : blocking send */
+#define RECEIVE		   2	/* 0010 : blocking receive */
+#define SENDREC	 	   3  	/* 0011 : SEND + RECEIVE */
+#define NOTIFY		   4	/* 0100 : nonblocking notify */
+#define ECHO		   8	/* 1000 : echo a message */
+
+#define IPC_REQUEST	   5	/* 0101 : blocking request */
+#define IPC_REPLY	   6    /* 0110 : nonblocking reply */
+#define IPC_NOTIFY	   7    /* 0111 : nonblocking notification */
+#define IPC_RECEIVE	   9	/* 1001 : blocking receive */
+
+/* The following bit masks determine what checks that should be done. */
+#define CHECK_PTR       0xBB	/* 1011 1011 : validate message buffer */
+#define CHECK_DST       0x55	/* 0101 0101 : validate message destination */
+#define CHECK_DEADLOCK  0x93	/* 1001 0011 : check for deadlock */
+
+#endif /* IPC_H */
Index: /trunk/minix/kernel/kernel.h
===================================================================
--- /trunk/minix/kernel/kernel.h	(revision 9)
+++ /trunk/minix/kernel/kernel.h	(revision 9)
@@ -0,0 +1,34 @@
+#ifndef KERNEL_H
+#define KERNEL_H
+
+/* This is the master header for the kernel.  It includes some other files
+ * and defines the principal constants.
+ */
+#define _POSIX_SOURCE      1	/* tell headers to include POSIX stuff */
+#define _MINIX             1	/* tell headers to include MINIX stuff */
+#define _SYSTEM            1	/* tell headers that this is the kernel */
+
+/* The following are so basic, all the *.c files get them automatically. */
+#include <minix/config.h>	/* global configuration, MUST be first */
+#include <ansi.h>		/* C style: ANSI or K&R, MUST be second */
+#include <sys/types.h>		/* general system types */
+#include <minix/const.h>	/* MINIX specific constants */
+#include <minix/type.h>		/* MINIX specific types, e.g. message */
+#include <minix/ipc.h>		/* MINIX run-time system */
+#include <timers.h>		/* watchdog timer management */
+#include <errno.h>		/* return codes and error numbers */
+
+#if (CHIP == INTEL)
+#include <ibm/portio.h>		/* device I/O and toggle interrupts */ 
+#endif
+
+/* Important kernel header files. */
+#include "config.h"		/* configuration, MUST be first */
+#include "const.h"		/* constants, MUST be second */
+#include "type.h"		/* type definitions, MUST be third */
+#include "proto.h"		/* function prototypes */
+#include "glo.h"		/* global variables */
+#include "ipc.h"		/* IPC constants */
+#include "debug.h"		/* debugging, MUST be last kernel header */
+
+#endif /* KERNEL_H */
Index: /trunk/minix/kernel/klib.s
===================================================================
--- /trunk/minix/kernel/klib.s	(revision 9)
+++ /trunk/minix/kernel/klib.s	(revision 9)
@@ -0,0 +1,9 @@
+#
+! Chooses between the 8086 and 386 versions of the low level kernel code.
+
+#include <minix/config.h>
+#if _WORD_SIZE == 2
+#include "klib88.s"
+#else
+#include "klib386.s"
+#endif
Index: /trunk/minix/kernel/klib386.s
===================================================================
--- /trunk/minix/kernel/klib386.s	(revision 9)
+++ /trunk/minix/kernel/klib386.s	(revision 9)
@@ -0,0 +1,615 @@
+# 
+! sections
+
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+#include <minix/config.h>
+#include <minix/const.h>
+#include "const.h"
+#include "sconst.h"
+#include "protect.h"
+
+! This file contains a number of assembly code utility routines needed by the
+! kernel.  They are:
+
+.define	_monitor	! exit Minix and return to the monitor
+.define	_int86		! let the monitor make an 8086 interrupt call
+.define	_cp_mess	! copies messages from source to destination
+.define	_exit		! dummy for library routines
+.define	__exit		! dummy for library routines
+.define	___exit		! dummy for library routines
+.define	___main		! dummy for GCC
+.define	_phys_insw	! transfer data from (disk controller) port to memory
+.define	_phys_insb	! likewise byte by byte
+.define	_phys_outsw	! transfer data from memory to (disk controller) port
+.define	_phys_outsb	! likewise byte by byte
+.define	_enable_irq	! enable an irq at the 8259 controller
+.define	_disable_irq	! disable an irq
+.define	_phys_copy	! copy data from anywhere to anywhere in memory
+.define	_phys_memset	! write pattern anywhere in memory
+.define	_mem_rdw	! copy one word from [segment:offset]
+.define	_reset		! reset the system
+.define	_idle_task	! task executed when there is no work
+.define	_level0		! call a function at level 0
+.define	_read_tsc	! read the cycle counter (Pentium and up)
+.define	_read_cpu_flags	! read the cpu flags
+.define	_read_cr0	! read cr0
+.define	_write_cr0	! write a value in cr0
+.define	_write_cr3	! write a value in cr3 (root of the page table)
+
+! The routines only guarantee to preserve the registers the C compiler
+! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
+! direction bit in the flags).
+
+.sect .text
+!*===========================================================================*
+!*				monitor					     *
+!*===========================================================================*
+! PUBLIC void monitor();
+! Return to the monitor.
+
+_monitor:
+	mov	esp, (_mon_sp)		! restore monitor stack pointer
+    o16 mov	dx, SS_SELECTOR		! monitor data segment
+	mov	ds, dx
+	mov	es, dx
+	mov	fs, dx
+	mov	gs, dx
+	mov	ss, dx
+	pop	edi
+	pop	esi
+	pop	ebp
+    o16 retf				! return to the monitor
+
+
+!*===========================================================================*
+!*				int86					     *
+!*===========================================================================*
+! PUBLIC void int86();
+_int86:
+	cmpb	(_mon_return), 0	! is the monitor there?
+	jnz	0f
+	movb	ah, 0x01		! an int 13 error seems appropriate
+	movb	(_reg86+ 0), ah		! reg86.w.f = 1 (set carry flag)
+	movb	(_reg86+13), ah		! reg86.b.ah = 0x01 = "invalid command"
+	ret
+0:	push	ebp			! save C registers
+	push	esi
+	push	edi
+	push	ebx
+	pushf				! save flags
+	cli				! no interruptions
+
+	inb	INT2_CTLMASK
+	movb	ah, al
+	inb	INT_CTLMASK
+	push	eax			! save interrupt masks
+	mov	eax, (_irq_use)		! map of in-use IRQ's
+	and	eax, ~[1<<CLOCK_IRQ]	! keep the clock ticking
+	outb	INT_CTLMASK		! enable all unused IRQ's and vv.
+	movb	al, ah
+	outb	INT2_CTLMASK
+
+	mov	eax, SS_SELECTOR	! monitor data segment
+	mov	ss, ax
+	xchg	esp, (_mon_sp)		! switch stacks
+	push	(_reg86+36)		! parameters used in INT call
+	push	(_reg86+32)
+	push	(_reg86+28)
+	push	(_reg86+24)
+	push	(_reg86+20)
+	push	(_reg86+16)
+	push	(_reg86+12)
+	push	(_reg86+ 8)
+	push	(_reg86+ 4)
+	push	(_reg86+ 0)
+	mov	ds, ax			! remaining data selectors
+	mov	es, ax
+	mov	fs, ax
+	mov	gs, ax
+	push	cs
+	push	return			! kernel return address and selector
+    o16	jmpf	20+2*4+10*4+2*4(esp)	! make the call
+return:
+	pop	(_reg86+ 0)
+	pop	(_reg86+ 4)
+	pop	(_reg86+ 8)
+	pop	(_reg86+12)
+	pop	(_reg86+16)
+	pop	(_reg86+20)
+	pop	(_reg86+24)
+	pop	(_reg86+28)
+	pop	(_reg86+32)
+	pop	(_reg86+36)
+	lgdt	(_gdt+GDT_SELECTOR)	! reload global descriptor table
+	jmpf	CS_SELECTOR:csinit	! restore everything
+csinit:	mov	eax, DS_SELECTOR
+	mov	ds, ax
+	mov	es, ax
+	mov	fs, ax
+	mov	gs, ax
+	mov	ss, ax
+	xchg	esp, (_mon_sp)		! unswitch stacks
+	lidt	(_gdt+IDT_SELECTOR)	! reload interrupt descriptor table
+	andb	(_gdt+TSS_SELECTOR+DESC_ACCESS), ~0x02  ! clear TSS busy bit
+	mov	eax, TSS_SELECTOR
+	ltr	ax			! set TSS register
+
+	pop	eax
+	outb	INT_CTLMASK		! restore interrupt masks
+	movb	al, ah
+	outb	INT2_CTLMASK
+
+	add	(_lost_ticks), ecx	! record lost clock ticks
+
+	popf				! restore flags
+	pop	ebx			! restore C registers
+	pop	edi
+	pop	esi
+	pop	ebp
+	ret
+
+
+!*===========================================================================*
+!*				cp_mess					     *
+!*===========================================================================*
+! PUBLIC void cp_mess(int src, phys_clicks src_clicks, vir_bytes src_offset,
+!		      phys_clicks dst_clicks, vir_bytes dst_offset);
+! This routine makes a fast copy of a message from anywhere in the address
+! space to anywhere else.  It also copies the source address provided as a
+! parameter to the call into the first word of the destination message.
+!
+! Note that the message size, "Msize" is in DWORDS (not bytes) and must be set
+! correctly.  Changing the definition of message in the type file and not
+! changing it here will lead to total disaster.
+
+CM_ARGS	=	4 + 4 + 4 + 4 + 4	! 4 + 4 + 4 + 4 + 4
+!		es  ds edi esi eip	proc scl sof dcl dof
+
+	.align	16
+_cp_mess:
+	cld
+	push	esi
+	push	edi
+	push	ds
+	push	es
+
+	mov	eax, FLAT_DS_SELECTOR
+	mov	ds, ax
+	mov	es, ax
+
+	mov	esi, CM_ARGS+4(esp)		! src clicks
+	shl	esi, CLICK_SHIFT
+	add	esi, CM_ARGS+4+4(esp)		! src offset
+	mov	edi, CM_ARGS+4+4+4(esp)		! dst clicks
+	shl	edi, CLICK_SHIFT
+	add	edi, CM_ARGS+4+4+4+4(esp)	! dst offset
+
+	mov	eax, CM_ARGS(esp)	! process number of sender
+	stos				! copy number of sender to dest message
+	add	esi, 4			! do not copy first word
+	mov	ecx, Msize - 1		! remember, first word does not count
+	rep
+	movs				! copy the message
+
+	pop	es
+	pop	ds
+	pop	edi
+	pop	esi
+	ret				! that is all folks!
+
+
+!*===========================================================================*
+!*				exit					     *
+!*===========================================================================*
+! PUBLIC void exit();
+! Some library routines use exit, so provide a dummy version.
+! Actual calls to exit cannot occur in the kernel.
+! GNU CC likes to call ___main from main() for nonobvious reasons.
+
+_exit:
+__exit:
+___exit:
+	sti
+	jmp	___exit
+
+___main:
+	ret
+
+
+!*===========================================================================*
+!*				phys_insw				     *
+!*===========================================================================*
+! PUBLIC void phys_insw(Port_t port, phys_bytes buf, size_t count);
+! Input an array from an I/O port.  Absolute address version of insw().
+
+_phys_insw:
+	push	ebp
+	mov	ebp, esp
+	cld
+	push	edi
+	push	es
+	mov	ecx, FLAT_DS_SELECTOR
+	mov	es, cx
+	mov	edx, 8(ebp)		! port to read from
+	mov	edi, 12(ebp)		! destination addr
+	mov	ecx, 16(ebp)		! byte count
+	shr	ecx, 1			! word count
+rep o16	ins				! input many words
+	pop	es
+	pop	edi
+	pop	ebp
+	ret
+
+
+!*===========================================================================*
+!*				phys_insb				     *
+!*===========================================================================*
+! PUBLIC void phys_insb(Port_t port, phys_bytes buf, size_t count);
+! Input an array from an I/O port.  Absolute address version of insb().
+
+_phys_insb:
+	push	ebp
+	mov	ebp, esp
+	cld
+	push	edi
+	push	es
+	mov	ecx, FLAT_DS_SELECTOR
+	mov	es, cx
+	mov	edx, 8(ebp)		! port to read from
+	mov	edi, 12(ebp)		! destination addr
+	mov	ecx, 16(ebp)		! byte count
+!	shr	ecx, 1			! word count
+   rep	insb				! input many bytes
+	pop	es
+	pop	edi
+	pop	ebp
+	ret
+
+
+!*===========================================================================*
+!*				phys_outsw				     *
+!*===========================================================================*
+! PUBLIC void phys_outsw(Port_t port, phys_bytes buf, size_t count);
+! Output an array to an I/O port.  Absolute address version of outsw().
+
+	.align	16
+_phys_outsw:
+	push	ebp
+	mov	ebp, esp
+	cld
+	push	esi
+	push	ds
+	mov	ecx, FLAT_DS_SELECTOR
+	mov	ds, cx
+	mov	edx, 8(ebp)		! port to write to
+	mov	esi, 12(ebp)		! source addr
+	mov	ecx, 16(ebp)		! byte count
+	shr	ecx, 1			! word count
+rep o16	outs				! output many words
+	pop	ds
+	pop	esi
+	pop	ebp
+	ret
+
+
+!*===========================================================================*
+!*				phys_outsb				     *
+!*===========================================================================*
+! PUBLIC void phys_outsb(Port_t port, phys_bytes buf, size_t count);
+! Output an array to an I/O port.  Absolute address version of outsb().
+
+	.align	16
+_phys_outsb:
+	push	ebp
+	mov	ebp, esp
+	cld
+	push	esi
+	push	ds
+	mov	ecx, FLAT_DS_SELECTOR
+	mov	ds, cx
+	mov	edx, 8(ebp)		! port to write to
+	mov	esi, 12(ebp)		! source addr
+	mov	ecx, 16(ebp)		! byte count
+   rep	outsb				! output many bytes
+	pop	ds
+	pop	esi
+	pop	ebp
+	ret
+
+
+!*==========================================================================*
+!*				enable_irq				    *
+!*==========================================================================*/
+! PUBLIC void enable_irq(irq_hook_t *hook)
+! Enable an interrupt request line by clearing an 8259 bit.
+! Equivalent C code for hook->irq < 8:
+!   if ((irq_actids[hook->irq] &= ~hook->id) == 0)
+!	outb(INT_CTLMASK, inb(INT_CTLMASK) & ~(1 << irq));
+
+	.align	16
+_enable_irq:
+	push	ebp
+	mov	ebp, esp
+	pushf
+	cli
+	mov	eax, 8(ebp)		! hook
+	mov	ecx, 8(eax)		! irq
+	mov	eax, 12(eax)		! id bit
+	not	eax
+	and	_irq_actids(ecx*4), eax	! clear this id bit
+	jnz	en_done			! still masked by other handlers?
+	movb	ah, ~1
+	rolb	ah, cl			! ah = ~(1 << (irq % 8))
+	mov	edx, INT_CTLMASK	! enable irq < 8 at the master 8259
+	cmpb	cl, 8
+	jb	0f
+	mov	edx, INT2_CTLMASK	! enable irq >= 8 at the slave 8259
+0:	inb	dx
+	andb	al, ah
+	outb	dx			! clear bit at the 8259
+en_done:popf
+	leave
+	ret
+
+
+!*==========================================================================*
+!*				disable_irq				    *
+!*==========================================================================*/
+! PUBLIC int disable_irq(irq_hook_t *hook)
+! Disable an interrupt request line by setting an 8259 bit.
+! Equivalent C code for irq < 8:
+!   irq_actids[hook->irq] |= hook->id;
+!   outb(INT_CTLMASK, inb(INT_CTLMASK) | (1 << irq));
+! Returns true iff the interrupt was not already disabled.
+
+	.align	16
+_disable_irq:
+	push	ebp
+	mov	ebp, esp
+	pushf
+	cli
+	mov	eax, 8(ebp)		! hook
+	mov	ecx, 8(eax)		! irq
+	mov	eax, 12(eax)		! id bit
+	or	_irq_actids(ecx*4), eax	! set this id bit
+	movb	ah, 1
+	rolb	ah, cl			! ah = (1 << (irq % 8))
+	mov	edx, INT_CTLMASK	! disable irq < 8 at the master 8259
+	cmpb	cl, 8
+	jb	0f
+	mov	edx, INT2_CTLMASK	! disable irq >= 8 at the slave 8259
+0:	inb	dx
+	testb	al, ah
+	jnz	dis_already		! already disabled?
+	orb	al, ah
+	outb	dx			! set bit at the 8259
+	mov	eax, 1			! disabled by this function
+	popf
+	leave
+	ret
+dis_already:
+	xor	eax, eax		! already disabled
+	popf
+	leave
+	ret
+
+
+!*===========================================================================*
+!*				phys_copy				     *
+!*===========================================================================*
+! PUBLIC void phys_copy(phys_bytes source, phys_bytes destination,
+!			phys_bytes bytecount);
+! Copy a block of physical memory.
+
+PC_ARGS	=	4 + 4 + 4 + 4	! 4 + 4 + 4
+!		es edi esi eip	 src dst len
+
+	.align	16
+_phys_copy:
+	cld
+	push	esi
+	push	edi
+	push	es
+
+	mov	eax, FLAT_DS_SELECTOR
+	mov	es, ax
+
+	mov	esi, PC_ARGS(esp)
+	mov	edi, PC_ARGS+4(esp)
+	mov	eax, PC_ARGS+4+4(esp)
+
+	cmp	eax, 10			! avoid align overhead for small counts
+	jb	pc_small
+	mov	ecx, esi		! align source, hope target is too
+	neg	ecx
+	and	ecx, 3			! count for alignment
+	sub	eax, ecx
+	rep
+   eseg	movsb
+	mov	ecx, eax
+	shr	ecx, 2			! count of dwords
+	rep
+   eseg	movs
+	and	eax, 3
+pc_small:
+	xchg	ecx, eax		! remainder
+	rep
+   eseg	movsb
+
+	pop	es
+	pop	edi
+	pop	esi
+	ret
+
+!*===========================================================================*
+!*				phys_memset				     *
+!*===========================================================================*
+! PUBLIC void phys_memset(phys_bytes source, unsigned long pattern,
+!	phys_bytes bytecount);
+! Fill a block of physical memory with pattern.
+
+	.align	16
+_phys_memset:
+	push	ebp
+	mov	ebp, esp
+	push	esi
+	push	ebx
+	push	ds
+	mov	esi, 8(ebp)
+	mov	eax, 16(ebp)
+	mov	ebx, FLAT_DS_SELECTOR
+	mov	ds, bx
+	mov	ebx, 12(ebp)
+	shr	eax, 2
+fill_start:
+   	mov     (esi), ebx
+	add	esi, 4
+	dec	eax
+	jnz	fill_start
+	! Any remaining bytes?
+	mov	eax, 16(ebp)
+	and	eax, 3
+remain_fill:
+	cmp	eax, 0
+	jz	fill_done
+	movb	bl, 12(ebp)
+   	movb    (esi), bl
+	add	esi, 1
+	inc	ebp
+	dec	eax
+	jmp	remain_fill
+fill_done:
+	pop	ds
+	pop	ebx
+	pop	esi
+	pop	ebp
+	ret
+
+!*===========================================================================*
+!*				mem_rdw					     *
+!*===========================================================================*
+! PUBLIC u16_t mem_rdw(U16_t segment, u16_t *offset);
+! Load and return word at far pointer segment:offset.
+
+	.align	16
+_mem_rdw:
+	mov	cx, ds
+	mov	ds, 4(esp)		! segment
+	mov	eax, 4+4(esp)		! offset
+	movzx	eax, (eax)		! word to return
+	mov	ds, cx
+	ret
+
+
+!*===========================================================================*
+!*				reset					     *
+!*===========================================================================*
+! PUBLIC void reset();
+! Reset the system by loading IDT with offset 0 and interrupting.
+
+_reset:
+	lidt	(idt_zero)
+	int	3		! anything goes, the 386 will not like it
+.sect .data
+idt_zero:	.data4	0, 0
+.sect .text
+
+
+!*===========================================================================*
+!*				idle_task				     *
+!*===========================================================================*
+_idle_task:
+! This task is called when the system has nothing else to do.  The HLT
+! instruction puts the processor in a state where it draws minimum power.
+	push	halt
+	call	_level0		! level0(halt)
+	pop	eax
+	jmp	_idle_task
+halt:
+	sti
+	hlt
+	cli
+	ret
+
+!*===========================================================================*
+!*			      level0					     *
+!*===========================================================================*
+! PUBLIC void level0(void (*func)(void))
+! Call a function at permission level 0.  This allows kernel tasks to do
+! things that are only possible at the most privileged CPU level.
+!
+_level0:
+	mov	eax, 4(esp)
+	mov	(_level0_func), eax
+	int	LEVEL0_VECTOR
+	ret
+
+
+!*===========================================================================*
+!*			      read_tsc					     *
+!*===========================================================================*
+! PUBLIC void read_tsc(unsigned long *high, unsigned long *low);
+! Read the cycle counter of the CPU. Pentium and up. 
+.align 16
+_read_tsc:
+.data1 0x0f		! this is the RDTSC instruction 
+.data1 0x31		! it places the TSC in EDX:EAX
+	push ebp
+	mov ebp, 8(esp)
+	mov (ebp), edx
+	mov ebp, 12(esp)
+	mov (ebp), eax
+	pop ebp
+	ret
+
+!*===========================================================================*
+!*			      read_flags					     *
+!*===========================================================================*
+! PUBLIC unsigned long read_cpu_flags(void);
+! Read CPU status flags from C.
+.align 16
+_read_cpu_flags:
+	pushf
+	mov eax, (esp)
+	popf
+	ret
+
+
+!*===========================================================================*
+!*			      read_cr0					     *
+!*===========================================================================*
+! PUBLIC unsigned long read_cr0(void);
+_read_cr0:
+	push	ebp
+	mov	ebp, esp
+	mov	eax, cr0
+	pop	ebp
+	ret
+
+!*===========================================================================*
+!*			      write_cr0					     *
+!*===========================================================================*
+! PUBLIC void write_cr0(unsigned long value);
+_write_cr0:
+	push	ebp
+	mov	ebp, esp
+	mov	eax, 8(ebp)
+	mov	cr0, eax
+	jmp	0f		! A jump is required for some flags
+0:
+	pop	ebp
+	ret
+
+!*===========================================================================*
+!*			      write_cr3					     *
+!*===========================================================================*
+! PUBLIC void write_cr3(unsigned long value);
+_write_cr3:
+	push	ebp
+	mov	ebp, esp
+	mov	eax, 8(ebp)
+	mov	cr3, eax
+	pop	ebp
+	ret
+
Index: /trunk/minix/kernel/kprintf.c
===================================================================
--- /trunk/minix/kernel/kprintf.c	(revision 9)
+++ /trunk/minix/kernel/kprintf.c	(revision 9)
@@ -0,0 +1,71 @@
+/*
+ * printf for the kernel
+ *
+ * Changes:
+ *   Dec 10, 2004   kernel printing to circular buffer  (Jorrit N. Herder)
+ * 
+ * This file contains the routines that take care of kernel messages, i.e.,
+ * diagnostic output within the kernel. Kernel messages are not directly
+ * displayed on the console, because this must be done by the output driver. 
+ * Instead, the kernel accumulates characters in a buffer and notifies the
+ * output driver when a new message is ready. 
+ */
+
+#include "kernel.h"
+#include "proc.h"
+#include <signal.h>
+
+#define printf kprintf
+
+#include "../lib/sysutil/kprintf.c"
+
+#define END_OF_KMESS 	0
+FORWARD _PROTOTYPE( void ser_putc, (char c));
+
+/*===========================================================================*
+ *				kputc				     	     *
+ *===========================================================================*/
+PUBLIC void kputc(c)
+int c;					/* character to append */
+{
+/* Accumulate a single character for a kernel message. Send a notification
+ * to the output driver if an END_OF_KMESS is encountered. 
+ */
+  if (c != END_OF_KMESS) {
+      if (do_serial_debug)
+      	ser_putc(c);
+      kmess.km_buf[kmess.km_next] = c;	/* put normal char in buffer */
+      if (kmess.km_size < KMESS_BUF_SIZE)
+          kmess.km_size += 1;		
+      kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
+  } else {
+      int p, outprocs[] = OUTPUT_PROCS_ARRAY;
+      for(p = 0; outprocs[p] != NONE; p++) {
+	 if(isokprocn(outprocs[p]) && !isemptyn(outprocs[p])) {
+           send_sig(outprocs[p], SIGKMESS);
+	 }
+      }
+  }
+}
+
+#define COM1_BASE	0x3F8
+#define COM1_THR	(COM1_BASE + 0)
+#define	  LSR_THRE	0x20
+#define COM1_LSR	(COM1_BASE + 5)
+
+PRIVATE void ser_putc(char c)
+{
+	int i;
+	int lsr, thr;
+
+	return;
+
+	lsr= COM1_LSR;
+	thr= COM1_THR;
+	for (i= 0; i<100000; i++)
+	{
+		if (inb(lsr) & LSR_THRE)
+			break;
+	}
+	outb(thr, c);
+}
Index: /trunk/minix/kernel/main.c
===================================================================
--- /trunk/minix/kernel/main.c	(revision 9)
+++ /trunk/minix/kernel/main.c	(revision 9)
@@ -0,0 +1,255 @@
+/* This file contains the main program of MINIX as well as its shutdown code.
+ * The routine main() initializes the system and starts the ball rolling by
+ * setting up the process table, interrupt vectors, and scheduling each task 
+ * to run to initialize itself.
+ * The routine shutdown() does the opposite and brings down MINIX. 
+ *
+ * The entries into this file are:
+ *   main:	    	MINIX main program
+ *   prepare_shutdown:	prepare to take MINIX down
+ *
+ * Changes:
+ *   Nov 24, 2004   simplified main() with system image  (Jorrit N. Herder)
+ *   Aug 20, 2004   new prepare_shutdown() and shutdown()  (Jorrit N. Herder)
+ */
+#include "kernel.h"
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <a.out.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/endpoint.h>
+#include "proc.h"
+
+/* Prototype declarations for PRIVATE functions. */
+FORWARD _PROTOTYPE( void announce, (void));	
+FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
+
+/*===========================================================================*
+ *				main                                         *
+ *===========================================================================*/
+PUBLIC void main()
+{
+/* Start the ball rolling. */
+  struct boot_image *ip;	/* boot image pointer */
+  register struct proc *rp;	/* process pointer */
+  register struct priv *sp;	/* privilege structure pointer */
+  register int i, s;
+  int hdrindex;			/* index to array of a.out headers */
+  phys_clicks text_base;
+  vir_clicks text_clicks, data_clicks;
+  reg_t ktsb;			/* kernel task stack base */
+  struct exec e_hdr;		/* for a copy of an a.out header */
+
+  /* Initialize the interrupt controller. */
+  intr_init(1);
+
+  /* Clear the process table. Anounce each slot as empty and set up mappings 
+   * for proc_addr() and proc_nr() macros. Do the same for the table with 
+   * privilege structures for the system processes. 
+   */
+  for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) {
+  	rp->p_rts_flags = SLOT_FREE;		/* initialize free slot */
+	rp->p_nr = i;				/* proc number from ptr */
+	rp->p_endpoint = _ENDPOINT(0, rp->p_nr); /* generation no. 0 */
+        (pproc_addr + NR_TASKS)[i] = rp;        /* proc ptr from number */
+  }
+  for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) {
+	sp->s_proc_nr = NONE;			/* initialize as free */
+	sp->s_id = i;				/* priv structure index */
+	ppriv_addr[i] = sp;			/* priv ptr from number */
+  }
+
+  /* Set up proc table entries for processes in boot image.  The stacks of the
+   * kernel tasks are initialized to an array in data space.  The stacks
+   * of the servers have been added to the data segment by the monitor, so
+   * the stack pointer is set to the end of the data segment.  All the
+   * processes are in low memory on the 8086.  On the 386 only the kernel
+   * is in low memory, the rest is loaded in extended memory.
+   */
+
+  /* Task stacks. */
+  ktsb = (reg_t) t_stack;
+
+  for (i=0; i < NR_BOOT_PROCS; ++i) {
+	ip = &image[i];				/* process' attributes */
+	rp = proc_addr(ip->proc_nr);		/* get process pointer */
+	ip->endpoint = rp->p_endpoint;		/* ipc endpoint */
+	rp->p_max_priority = ip->priority;	/* max scheduling priority */
+	rp->p_priority = ip->priority;		/* current priority */
+	rp->p_quantum_size = ip->quantum;	/* quantum size in ticks */
+	rp->p_ticks_left = ip->quantum;		/* current credit */
+	strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set process name */
+	(void) get_priv(rp, (ip->flags & SYS_PROC));    /* assign structure */
+	priv(rp)->s_flags = ip->flags;			/* process flags */
+	priv(rp)->s_trap_mask = ip->trap_mask;		/* allowed traps */
+	priv(rp)->s_call_mask = ip->call_mask;		/* kernel call mask */
+	priv(rp)->s_ipc_to.chunk[0] = ip->ipc_to;	/* restrict targets */
+	if (iskerneln(proc_nr(rp))) {		/* part of the kernel? */ 
+		if (ip->stksize > 0) {		/* HARDWARE stack size is 0 */
+			rp->p_priv->s_stack_guard = (reg_t *) ktsb;
+			*rp->p_priv->s_stack_guard = STACK_GUARD;
+		}
+		ktsb += ip->stksize;	/* point to high end of stack */
+		rp->p_reg.sp = ktsb;	/* this task's initial stack ptr */
+		text_base = kinfo.code_base >> CLICK_SHIFT;
+					/* processes that are in the kernel */
+		hdrindex = 0;		/* all use the first a.out header */
+	} else {
+		hdrindex = 1 + i-NR_TASKS;	/* servers, drivers, INIT */
+	}
+
+	/* The bootstrap loader created an array of the a.out headers at
+	 * absolute address 'aout'. Get one element to e_hdr.
+	 */
+	phys_copy(aout + hdrindex * A_MINHDR, vir2phys(&e_hdr),
+						(phys_bytes) A_MINHDR);
+	/* Convert addresses to clicks and build process memory map */
+	text_base = e_hdr.a_syms >> CLICK_SHIFT;
+	text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT;
+	if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0;	   /* common I&D */
+	data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT;
+	rp->p_memmap[T].mem_phys = text_base;
+	rp->p_memmap[T].mem_len  = text_clicks;
+	rp->p_memmap[D].mem_phys = text_base + text_clicks;
+	rp->p_memmap[D].mem_len  = data_clicks;
+	rp->p_memmap[S].mem_phys = text_base + text_clicks + data_clicks;
+	rp->p_memmap[S].mem_vir  = data_clicks;	/* empty - stack is in data */
+
+	/* Set initial register values.  The processor status word for tasks 
+	 * is different from that of other processes because tasks can
+	 * access I/O; this is not allowed to less-privileged processes 
+	 */
+	rp->p_reg.pc = (reg_t) ip->initial_pc;
+	rp->p_reg.psw = (iskernelp(rp)) ? INIT_TASK_PSW : INIT_PSW;
+
+	/* Initialize the server stack pointer. Take it down one word
+	 * to give crtso.s something to use as "argc".
+	 */
+	if (isusern(proc_nr(rp))) {		/* user-space process? */ 
+		rp->p_reg.sp = (rp->p_memmap[S].mem_vir +
+				rp->p_memmap[S].mem_len) << CLICK_SHIFT;
+		rp->p_reg.sp -= sizeof(reg_t);
+	}
+	
+	/* Set ready. The HARDWARE task is never ready. */
+	if (rp->p_nr != HARDWARE) {
+		rp->p_rts_flags = 0;		/* runnable if no flags */
+		lock_enqueue(rp);		/* add to scheduling queues */
+	} else {
+		rp->p_rts_flags = NO_MAP;	/* prevent from running */
+	}
+
+	/* Code and data segments must be allocated in protected mode. */
+	alloc_segments(rp);
+  }
+
+#if ENABLE_BOOTDEV 
+  /* Expect an image of the boot device to be loaded into memory as well. 
+   * The boot device is the last module that is loaded into memory, and, 
+   * for example, can contain the root FS (useful for embedded systems). 
+   */
+  hdrindex ++;
+  phys_copy(aout + hdrindex * A_MINHDR,vir2phys(&e_hdr),(phys_bytes) A_MINHDR);
+  if (e_hdr.a_flags & A_IMG) {
+  	kinfo.bootdev_base = e_hdr.a_syms; 
+  	kinfo.bootdev_size = e_hdr.a_data; 
+  }
+#endif
+
+  /* MINIX is now ready. All boot image processes are on the ready queue.
+   * Return to the assembly code to start running the current process. 
+   */
+  bill_ptr = proc_addr(IDLE);		/* it has to point somewhere */
+  announce();				/* print MINIX startup banner */
+  restart();
+}
+
+/*===========================================================================*
+ *				announce				     *
+ *===========================================================================*/
+PRIVATE void announce(void)
+{
+  /* Display the MINIX startup banner. */
+  kprintf("\nMINIX %s.%s. "
+      "Copyright 2006, Vrije Universiteit, Amsterdam, The Netherlands\n",
+      OS_RELEASE, OS_VERSION);
+#if (CHIP == INTEL)
+  /* Real mode, or 16/32-bit protected mode? */
+  kprintf("Executing in %s mode.\n\n",
+      machine.prot ? "32-bit protected" : "real");
+#endif
+}
+
+/*===========================================================================*
+ *				prepare_shutdown			     *
+ *===========================================================================*/
+PUBLIC void prepare_shutdown(how)
+int how;
+{
+/* This function prepares to shutdown MINIX. */
+  static timer_t shutdown_timer;
+  register struct proc *rp; 
+  message m;
+
+  /* Send a signal to all system processes that are still alive to inform 
+   * them that the MINIX kernel is shutting down. A proper shutdown sequence
+   * should be implemented by a user-space server. This mechanism is useful
+   * as a backup in case of system panics, so that system processes can still
+   * run their shutdown code, e.g, to synchronize the FS or to let the TTY
+   * switch to the first console. 
+   */
+#if DEAD_CODE
+  kprintf("Sending SIGKSTOP to system processes ...\n"); 
+  for (rp=BEG_PROC_ADDR; rp<END_PROC_ADDR; rp++) {
+      if (!isemptyp(rp) && (priv(rp)->s_flags & SYS_PROC) && !iskernelp(rp))
+          send_sig(proc_nr(rp), SIGKSTOP);
+  }
+#endif
+
+  /* Continue after 1 second, to give processes a chance to get scheduled to 
+   * do shutdown work.  Set a watchog timer to call shutdown(). The timer 
+   * argument passes the shutdown status. 
+   */
+  kprintf("MINIX will now be shut down ...\n");
+  tmr_arg(&shutdown_timer)->ta_int = how;
+  set_timer(&shutdown_timer, get_uptime() + HZ, shutdown);
+}
+/*===========================================================================*
+ *				shutdown 				     *
+ *===========================================================================*/
+PRIVATE void shutdown(tp)
+timer_t *tp;
+{
+/* This function is called from prepare_shutdown or stop_sequence to bring 
+ * down MINIX. How to shutdown is in the argument: RBT_HALT (return to the
+ * monitor), RBT_MONITOR (execute given code), RBT_RESET (hard reset). 
+ */
+  int how = tmr_arg(tp)->ta_int;
+  u16_t magic; 
+
+  /* Now mask all interrupts, including the clock, and stop the clock. */
+  outb(INT_CTLMASK, ~0); 
+  clock_stop();
+
+  if (mon_return && how != RBT_RESET) {
+	/* Reinitialize the interrupt controllers to the BIOS defaults. */
+	intr_init(0);
+	outb(INT_CTLMASK, 0);
+	outb(INT2_CTLMASK, 0);
+
+	/* Return to the boot monitor. Set the program if not already done. */
+	if (how != RBT_MONITOR) phys_copy(vir2phys(""), kinfo.params_base, 1); 
+	level0(monitor);
+  }
+
+  /* Reset the system by jumping to the reset address (real mode), or by
+   * forcing a processor shutdown (protected mode). First stop the BIOS 
+   * memory test by setting a soft reset flag. 
+   */
+  magic = STOP_MEM_CHECK;
+  phys_copy(vir2phys(&magic), SOFT_RESET_FLAG_ADDR, SOFT_RESET_FLAG_SIZE);
+  level0(reset);
+}
+
Index: /trunk/minix/kernel/mpx.s
===================================================================
--- /trunk/minix/kernel/mpx.s	(revision 9)
+++ /trunk/minix/kernel/mpx.s	(revision 9)
@@ -0,0 +1,9 @@
+#
+! Chooses between the 8086 and 386 versions of the Minix startup code.
+
+#include <minix/config.h>
+#if _WORD_SIZE == 2
+#include "mpx88.s"
+#else
+#include "mpx386.s"
+#endif
Index: /trunk/minix/kernel/mpx386.s
===================================================================
--- /trunk/minix/kernel/mpx386.s	(revision 9)
+++ /trunk/minix/kernel/mpx386.s	(revision 9)
@@ -0,0 +1,535 @@
+# 
+! This file, mpx386.s, is included by mpx.s when Minix is compiled for 
+! 32-bit Intel CPUs. The alternative mpx88.s is compiled for 16-bit CPUs.
+
+! This file is part of the lowest layer of the MINIX kernel.  (The other part
+! is "proc.c".)  The lowest layer does process switching and message handling.
+! Furthermore it contains the assembler startup code for Minix and the 32-bit
+! interrupt handlers.  It cooperates with the code in "start.c" to set up a 
+! good environment for main().
+
+! Every transition to the kernel goes through this file.  Transitions to the 
+! kernel may be nested.  The initial entry may be with a system call (i.e., 
+! send or receive a message), an exception or a hardware interrupt;  kernel 
+! reentries may only be made by hardware interrupts.  The count of reentries 
+! is kept in "k_reenter". It is important for deciding whether to switch to 
+! the kernel stack and for protecting the message passing code in "proc.c".
+
+! For the message passing trap, most of the machine state is saved in the
+! proc table.  (Some of the registers need not be saved.)  Then the stack is
+! switched to "k_stack", and interrupts are reenabled.  Finally, the system
+! call handler (in C) is called.  When it returns, interrupts are disabled
+! again and the code falls into the restart routine, to finish off held-up
+! interrupts and run the process or task whose pointer is in "proc_ptr".
+
+! Hardware interrupt handlers do the same, except  (1) The entire state must
+! be saved.  (2) There are too many handlers to do this inline, so the save
+! routine is called.  A few cycles are saved by pushing the address of the
+! appropiate restart routine for a return later.  (3) A stack switch is
+! avoided when the stack is already switched.  (4) The (master) 8259 interrupt
+! controller is reenabled centrally in save().  (5) Each interrupt handler
+! masks its interrupt line using the 8259 before enabling (other unmasked)
+! interrupts, and unmasks it after servicing the interrupt.  This limits the
+! nest level to the number of lines and protects the handler from itself.
+
+! For communication with the boot monitor at startup time some constant
+! data are compiled into the beginning of the text segment. This facilitates 
+! reading the data at the start of the boot process, since only the first
+! sector of the file needs to be read.
+
+! Some data storage is also allocated at the end of this file. This data 
+! will be at the start of the data segment of the kernel and will be read
+! and modified by the boot monitor before the kernel starts.
+
+! sections
+
+.sect .text
+begtext:
+.sect .rom
+begrom:
+.sect .data
+begdata:
+.sect .bss
+begbss:
+
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/com.h>
+#include <ibm/interrupt.h>
+#include "const.h"
+#include "protect.h"
+#include "sconst.h"
+
+/* Selected 386 tss offsets. */
+#define TSS3_S_SP0	4
+
+! Exported functions
+! Note: in assembly language the .define statement applied to a function name 
+! is loosely equivalent to a prototype in C code -- it makes it possible to
+! link to an entity declared in the assembly code but does not create
+! the entity.
+
+.define	_restart
+.define	save
+
+.define	_divide_error
+.define	_single_step_exception
+.define	_nmi
+.define	_breakpoint_exception
+.define	_overflow
+.define	_bounds_check
+.define	_inval_opcode
+.define	_copr_not_available
+.define	_double_fault
+.define	_copr_seg_overrun
+.define	_inval_tss
+.define	_segment_not_present
+.define	_stack_exception
+.define	_general_protection
+.define	_page_fault
+.define	_copr_error
+
+.define	_hwint00	! handlers for hardware interrupts
+.define	_hwint01
+.define	_hwint02
+.define	_hwint03
+.define	_hwint04
+.define	_hwint05
+.define	_hwint06
+.define	_hwint07
+.define	_hwint08
+.define	_hwint09
+.define	_hwint10
+.define	_hwint11
+.define	_hwint12
+.define	_hwint13
+.define	_hwint14
+.define	_hwint15
+
+.define	_s_call
+.define	_p_s_call
+.define	_level0_call
+
+! Exported variables.
+.define	begbss
+.define	begdata
+
+.sect .text
+!*===========================================================================*
+!*				MINIX					     *
+!*===========================================================================*
+MINIX:				! this is the entry point for the MINIX kernel
+	jmp	over_flags	! skip over the next few bytes
+	.data2	CLICK_SHIFT	! for the monitor: memory granularity
+flags:
+	.data2	0x01FD		! boot monitor flags:
+				!	call in 386 mode, make bss, make stack,
+				!	load high, don't patch, will return,
+				!	uses generic INT, memory vector,
+				!	new boot code return
+	nop			! extra byte to sync up disassembler
+over_flags:
+
+! Set up a C stack frame on the monitor stack.  (The monitor sets cs and ds
+! right.  The ss descriptor still references the monitor data segment.)
+	movzx	esp, sp		! monitor stack is a 16 bit stack
+	push	ebp
+	mov	ebp, esp
+	push	esi
+	push	edi
+	cmp	4(ebp), 0	! monitor return vector is
+	jz	noret		! nonzero if return possible
+	inc	(_mon_return)
+noret:	mov	(_mon_sp), esp	! save stack pointer for later return
+
+! Copy the monitor global descriptor table to the address space of kernel and
+! switch over to it.  Prot_init() can then update it with immediate effect.
+
+	sgdt	(_gdt+GDT_SELECTOR)		! get the monitor gdtr
+	mov	esi, (_gdt+GDT_SELECTOR+2)	! absolute address of GDT
+	mov	ebx, _gdt			! address of kernel GDT
+	mov	ecx, 8*8			! copying eight descriptors
+copygdt:
+ eseg	movb	al, (esi)
+	movb	(ebx), al
+	inc	esi
+	inc	ebx
+	loop	copygdt
+	mov	eax, (_gdt+DS_SELECTOR+2)	! base of kernel data
+	and	eax, 0x00FFFFFF			! only 24 bits
+	add	eax, _gdt			! eax = vir2phys(gdt)
+	mov	(_gdt+GDT_SELECTOR+2), eax	! set base of GDT
+	lgdt	(_gdt+GDT_SELECTOR)		! switch over to kernel GDT
+
+! Locate boot parameters, set up kernel segment registers and stack.
+	mov	ebx, 8(ebp)	! boot parameters offset
+	mov	edx, 12(ebp)	! boot parameters length
+	mov	eax, 16(ebp)	! address of a.out headers
+	mov	(_aout), eax
+	mov	ax, ds		! kernel data
+	mov	es, ax
+	mov	fs, ax
+	mov	gs, ax
+	mov	ss, ax
+	mov	esp, k_stktop	! set sp to point to the top of kernel stack
+
+! Call C startup code to set up a proper environment to run main().
+	push	edx
+	push	ebx
+	push	SS_SELECTOR
+	push	DS_SELECTOR
+	push	CS_SELECTOR
+	call	_cstart		! cstart(cs, ds, mds, parmoff, parmlen)
+	add	esp, 5*4
+
+! Reload gdtr, idtr and the segment registers to global descriptor table set
+! up by prot_init().
+
+	lgdt	(_gdt+GDT_SELECTOR)
+	lidt	(_gdt+IDT_SELECTOR)
+
+	jmpf	CS_SELECTOR:csinit
+csinit:
+    o16	mov	ax, DS_SELECTOR
+	mov	ds, ax
+	mov	es, ax
+	mov	fs, ax
+	mov	gs, ax
+	mov	ss, ax
+    o16	mov	ax, TSS_SELECTOR	! no other TSS is used
+	ltr	ax
+	push	0			! set flags to known good state
+	popf				! esp, clear nested task and int enable
+
+	jmp	_main			! main()
+
+
+!*===========================================================================*
+!*				interrupt handlers			     *
+!*		interrupt handlers for 386 32-bit protected mode	     *
+!*===========================================================================*
+
+!*===========================================================================*
+!*				hwint00 - 07				     *
+!*===========================================================================*
+! Note this is a macro, it just looks like a subroutine.
+#define hwint_master(irq)	\
+	call	save			/* save interrupted process state */;\
+	push	(_irq_handlers+4*irq)	/* irq_handlers[irq]		  */;\
+	call	_intr_handle		/* intr_handle(irq_handlers[irq]) */;\
+	pop	ecx							    ;\
+	cmp	(_irq_actids+4*irq), 0	/* interrupt still active?	  */;\
+	jz	0f							    ;\
+	inb	INT_CTLMASK		/* get current mask */		    ;\
+	orb	al, [1<<irq]		/* mask irq */			    ;\
+	outb	INT_CTLMASK		/* disable the irq		  */;\
+0:	movb	al, END_OF_INT						    ;\
+	outb	INT_CTL			/* reenable master 8259		  */;\
+	ret				/* restart (another) process      */
+
+! Each of these entry points is an expansion of the hwint_master macro
+	.align	16
+_hwint00:		! Interrupt routine for irq 0 (the clock).
+	hwint_master(0)
+
+	.align	16
+_hwint01:		! Interrupt routine for irq 1 (keyboard)
+	hwint_master(1)
+
+	.align	16
+_hwint02:		! Interrupt routine for irq 2 (cascade!)
+	hwint_master(2)
+
+	.align	16
+_hwint03:		! Interrupt routine for irq 3 (second serial)
+	hwint_master(3)
+
+	.align	16
+_hwint04:		! Interrupt routine for irq 4 (first serial)
+	hwint_master(4)
+
+	.align	16
+_hwint05:		! Interrupt routine for irq 5 (XT winchester)
+	hwint_master(5)
+
+	.align	16
+_hwint06:		! Interrupt routine for irq 6 (floppy)
+	hwint_master(6)
+
+	.align	16
+_hwint07:		! Interrupt routine for irq 7 (printer)
+	hwint_master(7)
+
+!*===========================================================================*
+!*				hwint08 - 15				     *
+!*===========================================================================*
+! Note this is a macro, it just looks like a subroutine.
+#define hwint_slave(irq)	\
+	call	save			/* save interrupted process state */;\
+	push	(_irq_handlers+4*irq)	/* irq_handlers[irq]		  */;\
+	call	_intr_handle		/* intr_handle(irq_handlers[irq]) */;\
+	pop	ecx							    ;\
+	cmp	(_irq_actids+4*irq), 0	/* interrupt still active?	  */;\
+	jz	0f							    ;\
+	inb	INT2_CTLMASK						    ;\
+	orb	al, [1<<[irq-8]]					    ;\
+	outb	INT2_CTLMASK		/* disable the irq		  */;\
+0:	movb	al, END_OF_INT						    ;\
+	outb	INT_CTL			/* reenable master 8259		  */;\
+	outb	INT2_CTL		/* reenable slave 8259		  */;\
+	ret				/* restart (another) process      */
+
+! Each of these entry points is an expansion of the hwint_slave macro
+	.align	16
+_hwint08:		! Interrupt routine for irq 8 (realtime clock)
+	hwint_slave(8)
+
+	.align	16
+_hwint09:		! Interrupt routine for irq 9 (irq 2 redirected)
+	hwint_slave(9)
+
+	.align	16
+_hwint10:		! Interrupt routine for irq 10
+	hwint_slave(10)
+
+	.align	16
+_hwint11:		! Interrupt routine for irq 11
+	hwint_slave(11)
+
+	.align	16
+_hwint12:		! Interrupt routine for irq 12
+	hwint_slave(12)
+
+	.align	16
+_hwint13:		! Interrupt routine for irq 13 (FPU exception)
+	hwint_slave(13)
+
+	.align	16
+_hwint14:		! Interrupt routine for irq 14 (AT winchester)
+	hwint_slave(14)
+
+	.align	16
+_hwint15:		! Interrupt routine for irq 15
+	hwint_slave(15)
+
+!*===========================================================================*
+!*				save					     *
+!*===========================================================================*
+! Save for protected mode.
+! This is much simpler than for 8086 mode, because the stack already points
+! into the process table, or has already been switched to the kernel stack.
+
+	.align	16
+save:
+	cld			! set direction flag to a known value
+	pushad			! save "general" registers
+    o16	push	ds		! save ds
+    o16	push	es		! save es
+    o16	push	fs		! save fs
+    o16	push	gs		! save gs
+	mov	dx, ss		! ss is kernel data segment
+	mov	ds, dx		! load rest of kernel segments
+	mov	es, dx		! kernel does not use fs, gs
+	mov	eax, esp	! prepare to return
+	incb	(_k_reenter)	! from -1 if not reentering
+	jnz	set_restart1	! stack is already kernel stack
+	mov	esp, k_stktop
+	push	_restart	! build return address for int handler
+	xor	ebp, ebp	! for stacktrace
+	jmp	RETADR-P_STACKBASE(eax)
+
+	.align	4
+set_restart1:
+	push	restart1
+	jmp	RETADR-P_STACKBASE(eax)
+
+!*===========================================================================*
+!*				_s_call					     *
+!*===========================================================================*
+	.align	16
+_s_call:
+_p_s_call:
+	cld			! set direction flag to a known value
+	sub	esp, 6*4	! skip RETADR, eax, ecx, edx, ebx, est
+	push	ebp		! stack already points into proc table
+	push	esi
+	push	edi
+    o16	push	ds
+    o16	push	es
+    o16	push	fs
+    o16	push	gs
+	mov	si, ss		! ss is kernel data segment
+	mov	ds, si		! load rest of kernel segments
+	mov	es, si		! kernel does not use fs, gs
+	incb	(_k_reenter)	! increment kernel entry count
+	mov	esi, esp	! assumes P_STACKBASE == 0
+	mov	esp, k_stktop
+	xor	ebp, ebp	! for stacktrace
+				! end of inline save
+				! now set up parameters for sys_call()
+	push	edx		! event set or flags bit map 
+	push	ebx		! pointer to user message
+	push	eax		! source / destination
+	push	ecx		! call number (ipc primitive to use)
+	call	_sys_call	! sys_call(call_nr, src_dst, m_ptr, bit_map)
+				! caller is now explicitly in proc_ptr
+	mov	AXREG(esi), eax	! sys_call MUST PRESERVE si
+
+! Fall into code to restart proc/task running.
+
+!*===========================================================================*
+!*				restart					     *
+!*===========================================================================*
+_restart:
+
+! Restart the current process or the next process if it is set. 
+
+	cmp	(_next_ptr), 0		! see if another process is scheduled
+	jz	0f
+	mov 	eax, (_next_ptr)
+	mov	(_proc_ptr), eax	! schedule new process 
+	mov	(_next_ptr), 0
+0:	mov	esp, (_proc_ptr)	! will assume P_STACKBASE == 0
+	lldt	P_LDT_SEL(esp)		! enable process' segment descriptors 
+	lea	eax, P_STACKTOP(esp)	! arrange for next interrupt
+	mov	(_tss+TSS3_S_SP0), eax	! to save state in process table
+restart1:
+	decb	(_k_reenter)
+    o16	pop	gs
+    o16	pop	fs
+    o16	pop	es
+    o16	pop	ds
+	popad
+	add	esp, 4		! skip return adr
+	iretd			! continue process
+
+!*===========================================================================*
+!*				exception handlers			     *
+!*===========================================================================*
+_divide_error:
+	push	DIVIDE_VECTOR
+	jmp	exception
+
+_single_step_exception:
+	push	DEBUG_VECTOR
+	jmp	exception
+
+_nmi:
+	push	NMI_VECTOR
+	jmp	exception
+
+_breakpoint_exception:
+	push	BREAKPOINT_VECTOR
+	jmp	exception
+
+_overflow:
+	push	OVERFLOW_VECTOR
+	jmp	exception
+
+_bounds_check:
+	push	BOUNDS_VECTOR
+	jmp	exception
+
+_inval_opcode:
+	push	INVAL_OP_VECTOR
+	jmp	exception
+
+_copr_not_available:
+	push	COPROC_NOT_VECTOR
+	jmp	exception
+
+_double_fault:
+	push	DOUBLE_FAULT_VECTOR
+	jmp	errexception
+
+_copr_seg_overrun:
+	push	COPROC_SEG_VECTOR
+	jmp	exception
+
+_inval_tss:
+	push	INVAL_TSS_VECTOR
+	jmp	errexception
+
+_segment_not_present:
+	push	SEG_NOT_VECTOR
+	jmp	errexception
+
+_stack_exception:
+	push	STACK_FAULT_VECTOR
+	jmp	errexception
+
+_general_protection:
+	push	PROTECTION_VECTOR
+	jmp	errexception
+
+_page_fault:
+	push	PAGE_FAULT_VECTOR
+	jmp	errexception
+
+_copr_error:
+	push	COPROC_ERR_VECTOR
+	jmp	exception
+
+!*===========================================================================*
+!*				exception				     *
+!*===========================================================================*
+! This is called for all exceptions which do not push an error code.
+
+	.align	16
+exception:
+ sseg	mov	(trap_errno), 0		! clear trap_errno
+ sseg	pop	(ex_number)
+	jmp	exception1
+
+!*===========================================================================*
+!*				errexception				     *
+!*===========================================================================*
+! This is called for all exceptions which push an error code.
+
+	.align	16
+errexception:
+ sseg	pop	(ex_number)
+ sseg	pop	(trap_errno)
+exception1:				! Common for all exceptions.
+	push	eax			! eax is scratch register
+	mov	eax, 0+4(esp)		! old eip
+ sseg	mov	(old_eip), eax
+	movzx	eax, 4+4(esp)		! old cs
+ sseg	mov	(old_cs), eax
+	mov	eax, 8+4(esp)		! old eflags
+ sseg	mov	(old_eflags), eax
+	pop	eax
+	call	save
+	push	(old_eflags)
+	push	(old_cs)
+	push	(old_eip)
+	push	(trap_errno)
+	push	(ex_number)
+	call	_exception		! (ex_number, trap_errno, old_eip,
+					!	old_cs, old_eflags)
+	add	esp, 5*4
+	ret
+
+!*===========================================================================*
+!*				level0_call				     *
+!*===========================================================================*
+_level0_call:
+	call	save
+	jmp	(_level0_func)
+
+!*===========================================================================*
+!*				data					     *
+!*===========================================================================*
+
+.sect .rom	! Before the string table please
+	.data2	0x526F		! this must be the first data entry (magic #)
+
+.sect .bss
+k_stack:
+	.space	K_STACK_BYTES	! kernel stack
+k_stktop:			! top of kernel stack
+	.comm	ex_number, 4
+	.comm	trap_errno, 4
+	.comm	old_eip, 4
+	.comm	old_cs, 4
+	.comm	old_eflags, 4
Index: /trunk/minix/kernel/priv.h
===================================================================
--- /trunk/minix/kernel/priv.h	(revision 9)
+++ /trunk/minix/kernel/priv.h	(revision 9)
@@ -0,0 +1,100 @@
+#ifndef PRIV_H
+#define PRIV_H
+
+/* Declaration of the system privileges structure. It defines flags, system 
+ * call masks, an synchronous alarm timer, I/O privileges, pending hardware 
+ * interrupts and notifications, and so on.
+ * System processes each get their own structure with properties, whereas all 
+ * user processes share one structure. This setup provides a clear separation
+ * between common and privileged process fields and is very space efficient. 
+ *
+ * Changes:
+ *   Jul 01, 2005	Created.  (Jorrit N. Herder)	
+ */
+#include <minix/com.h>
+#include "protect.h"
+#include "const.h"
+#include "type.h"
+
+/* Max. number of I/O ranges that can be assigned to a process */
+#define NR_IO_RANGE	10
+
+/* Max. number of device memory ranges that can be assigned to a process */
+#define NR_MEM_RANGE	10
+
+/* Max. number of IRQs that can be assigned to a process */
+#define NR_IRQ	4
+ 
+struct priv {
+  proc_nr_t s_proc_nr;		/* number of associated process */
+  sys_id_t s_id;		/* index of this system structure */
+  short s_flags;		/* PREEMTIBLE, BILLABLE, etc. */
+
+  short s_trap_mask;		/* allowed system call traps */
+  sys_map_t s_ipc_from;		/* allowed callers to receive from */
+  sys_map_t s_ipc_to;		/* allowed destination processes */
+  long s_call_mask;		/* allowed kernel calls */
+
+  sys_map_t s_notify_pending;  	/* bit map with pending notifications */
+  irq_id_t s_int_pending;	/* pending hardware interrupts */
+  sigset_t s_sig_pending;	/* pending signals */
+
+  timer_t s_alarm_timer;	/* synchronous alarm timer */ 
+  struct far_mem s_farmem[NR_REMOTE_SEGS];  /* remote memory map */
+  reg_t *s_stack_guard;		/* stack guard word for kernel tasks */
+
+  int s_nr_io_range;		/* allowed I/O ports */
+  struct io_range s_io_tab[NR_IO_RANGE];
+
+  int s_nr_mem_range;		/* allowed memory ranges */
+  struct mem_range s_mem_tab[NR_MEM_RANGE];
+
+  int s_nr_irq;			/* allowed IRQ lines */
+  int s_irq_tab[NR_IRQ];
+};
+
+/* Guard word for task stacks. */
+#define STACK_GUARD	((reg_t) (sizeof(reg_t) == 2 ? 0xBEEF : 0xDEADBEEF))
+
+/* Bits for the system property flags. */
+#define PREEMPTIBLE	0x02	/* kernel tasks are not preemptible */
+#define BILLABLE	0x04	/* some processes are not billable */
+
+#define SYS_PROC	0x10	/* system processes have own priv structure */
+#define CHECK_IO_PORT	0x20	/* check if I/O request is allowed */
+#define CHECK_IRQ	0x40	/* check if IRQ can be used */
+#define CHECK_MEM	0x80	/* check if (VM) mem map request is allowed */
+
+/* Magic system structure table addresses. */
+#define BEG_PRIV_ADDR (&priv[0])
+#define END_PRIV_ADDR (&priv[NR_SYS_PROCS])
+
+#define priv_addr(i)      (ppriv_addr)[(i)]
+#define priv_id(rp)	  ((rp)->p_priv->s_id)
+#define priv(rp)	  ((rp)->p_priv)
+
+#define id_to_nr(id)	priv_addr(id)->s_proc_nr
+#define nr_to_id(nr)    priv(proc_addr(nr))->s_id
+
+/* The system structures table and pointers to individual table slots. The 
+ * pointers allow faster access because now a process entry can be found by 
+ * indexing the psys_addr array, while accessing an element i requires a 
+ * multiplication with sizeof(struct sys) to determine the address. 
+ */
+EXTERN struct priv priv[NR_SYS_PROCS];		/* system properties table */
+EXTERN struct priv *ppriv_addr[NR_SYS_PROCS];	/* direct slot pointers */
+
+/* Unprivileged user processes all share the same privilege structure.
+ * This id must be fixed because it is used to check send mask entries.
+ */
+#define USER_PRIV_ID	0
+
+/* Make sure the system can boot. The following sanity check verifies that
+ * the system privileges table is large enough for the number of processes
+ * in the boot image. 
+ */
+#if (NR_BOOT_PROCS > NR_SYS_PROCS)
+#error NR_SYS_PROCS must be larger than NR_BOOT_PROCS
+#endif
+
+#endif /* PRIV_H */
Index: /trunk/minix/kernel/proc.c
===================================================================
--- /trunk/minix/kernel/proc.c	(revision 9)
+++ /trunk/minix/kernel/proc.c	(revision 9)
@@ -0,0 +1,790 @@
+/* This file contains essentially all of the process and message handling.
+ * Together with "mpx.s" it forms the lowest layer of the MINIX kernel.
+ * There is one entry point from the outside:
+ *
+ *   sys_call: 	      a system call, i.e., the kernel is trapped with an INT
+ *
+ * As well as several entry points used from the interrupt and task level:
+ *
+ *   lock_notify:     notify a process of a system event
+ *   lock_send:	      send a message to a process
+ *   lock_enqueue:    put a process on one of the scheduling queues 
+ *   lock_dequeue:    remove a process from the scheduling queues
+ *
+ * Changes:
+ *   Aug 19, 2005     rewrote scheduling code  (Jorrit N. Herder)
+ *   Jul 25, 2005     rewrote system call handling  (Jorrit N. Herder)
+ *   May 26, 2005     rewrote message passing functions  (Jorrit N. Herder)
+ *   May 24, 2005     new notification system call  (Jorrit N. Herder)
+ *   Oct 28, 2004     nonblocking send and receive calls  (Jorrit N. Herder)
+ *
+ * The code here is critical to make everything work and is important for the
+ * overall performance of the system. A large fraction of the code deals with
+ * list manipulation. To make this both easy to understand and fast to execute 
+ * pointer pointers are used throughout the code. Pointer pointers prevent
+ * exceptions for the head or tail of a linked list. 
+ *
+ *  node_t *queue, *new_node;	// assume these as global variables
+ *  node_t **xpp = &queue; 	// get pointer pointer to head of queue 
+ *  while (*xpp != NULL) 	// find last pointer of the linked list
+ *      xpp = &(*xpp)->next;	// get pointer to next pointer 
+ *  *xpp = new_node;		// now replace the end (the NULL pointer) 
+ *  new_node->next = NULL;	// and mark the new end of the list
+ * 
+ * For example, when adding a new node to the end of the list, one normally 
+ * makes an exception for an empty list and looks up the end of the list for 
+ * nonempty lists. As shown above, this is not required with pointer pointers.
+ */
+
+#include <minix/com.h>
+#include <minix/callnr.h>
+#include <minix/endpoint.h>
+#include "debug.h"
+#include "kernel.h"
+#include "proc.h"
+#include <signal.h>
+
+/* Scheduling and message passing functions. The functions are available to 
+ * other parts of the kernel through lock_...(). The lock temporarily disables 
+ * interrupts to prevent race conditions. 
+ */
+FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dst_e,
+		message *m_ptr, unsigned flags));
+FORWARD _PROTOTYPE( int mini_receive, (struct proc *caller_ptr, int src,
+		message *m_ptr, unsigned flags));
+FORWARD _PROTOTYPE( int mini_notify, (struct proc *caller_ptr, int dst));
+FORWARD _PROTOTYPE( int deadlock, (int function,
+		register struct proc *caller, int src_dst));
+FORWARD _PROTOTYPE( void enqueue, (struct proc *rp));
+FORWARD _PROTOTYPE( void dequeue, (struct proc *rp));
+FORWARD _PROTOTYPE( void sched, (struct proc *rp, int *queue, int *front));
+FORWARD _PROTOTYPE( void pick_proc, (void));
+
+#define BuildMess(m_ptr, src, dst_ptr) \
+	(m_ptr)->m_source = proc_addr(src)->p_endpoint;		\
+	(m_ptr)->m_type = NOTIFY_FROM(src);				\
+	(m_ptr)->NOTIFY_TIMESTAMP = get_uptime();			\
+	switch (src) {							\
+	case HARDWARE:							\
+		(m_ptr)->NOTIFY_ARG = priv(dst_ptr)->s_int_pending;	\
+		priv(dst_ptr)->s_int_pending = 0;			\
+		break;							\
+	case SYSTEM:							\
+		(m_ptr)->NOTIFY_ARG = priv(dst_ptr)->s_sig_pending;	\
+		priv(dst_ptr)->s_sig_pending = 0;			\
+		break;							\
+	}
+
+#if (CHIP == INTEL)
+#define CopyMess(s,sp,sm,dp,dm) \
+	cp_mess(proc_addr(s)->p_endpoint, \
+		(sp)->p_memmap[D].mem_phys,	\
+		(vir_bytes)sm, (dp)->p_memmap[D].mem_phys, (vir_bytes)dm)
+#endif /* (CHIP == INTEL) */
+
+#if (CHIP == M68000)
+/* M68000 does not have cp_mess() in assembly like INTEL. Declare prototype
+ * for cp_mess() here and define the function below. Also define CopyMess. 
+ */
+#endif /* (CHIP == M68000) */
+
+/*===========================================================================*
+ *				sys_call				     * 
+ *===========================================================================*/
+PUBLIC int sys_call(call_nr, src_dst_e, m_ptr, bit_map)
+int call_nr;			/* system call number and flags */
+int src_dst_e;			/* src to receive from or dst to send to */
+message *m_ptr;			/* pointer to message in the caller's space */
+long bit_map;			/* notification event set or flags */
+{
+/* System calls are done by trapping to the kernel with an INT instruction.
+ * The trap is caught and sys_call() is called to send or receive a message
+ * (or both). The caller is always given by 'proc_ptr'.
+ */
+  register struct proc *caller_ptr = proc_ptr;	/* get pointer to caller */
+  int function = call_nr & SYSCALL_FUNC;	/* get system call function */
+  unsigned flags = call_nr & SYSCALL_FLAGS;	/* get flags */
+  int mask_entry;				/* bit to check in send mask */
+  int group_size;				/* used for deadlock check */
+  int result;					/* the system call's result */
+  int src_dst;
+  vir_clicks vlo, vhi;		/* virtual clicks containing message to send */
+
+#if 0
+  if (caller_ptr->p_rts_flags & SLOT_FREE)
+  {
+	kprintf("called by the dead?!?\n");
+	return EINVAL;
+  }
+#endif
+  
+  /* Require a valid source and/ or destination process, unless echoing. */
+  if (src_dst_e != ANY && function != ECHO) {
+      if(!isokendpt(src_dst_e, &src_dst)) {
+#if DEBUG_ENABLE_IPC_WARNINGS
+          kprintf("sys_call: trap %d by %d with bad endpoint %d\n", 
+              function, proc_nr(caller_ptr), src_dst_e);
+#endif
+	  return EDEADSRCDST;
+      }
+  } else src_dst = src_dst_e;
+
+  /* Check if the process has privileges for the requested call. Calls to the 
+   * kernel may only be SENDREC, because tasks always reply and may not block 
+   * if the caller doesn't do receive(). 
+   */
+  if (! (priv(caller_ptr)->s_trap_mask & (1 << function)) || 
+          (iskerneln(src_dst) && function != SENDREC
+           && function != RECEIVE)) {
+#if DEBUG_ENABLE_IPC_WARNINGS
+      kprintf("sys_call: trap %d not allowed, caller %d, src_dst %d\n", 
+          function, proc_nr(caller_ptr), src_dst);
+#endif
+      return(ETRAPDENIED);		/* trap denied by mask or kernel */
+  }
+
+  /* If the call involves a message buffer, i.e., for SEND, RECEIVE, SENDREC, 
+   * or ECHO, check the message pointer. This check allows a message to be 
+   * anywhere in data or stack or gap. It will have to be made more elaborate 
+   * for machines which don't have the gap mapped. 
+   */
+  if (function & CHECK_PTR) {
+      vlo = (vir_bytes) m_ptr >> CLICK_SHIFT;		
+      vhi = ((vir_bytes) m_ptr + MESS_SIZE - 1) >> CLICK_SHIFT;
+      if (vlo < caller_ptr->p_memmap[D].mem_vir || vlo > vhi ||
+              vhi >= caller_ptr->p_memmap[S].mem_vir + 
+              caller_ptr->p_memmap[S].mem_len) {
+#if DEBUG_ENABLE_IPC_WARNINGS
+          kprintf("sys_call: invalid message pointer, trap %d, caller %d\n",
+          	function, proc_nr(caller_ptr));
+#endif
+          return(EFAULT); 		/* invalid message pointer */
+      }
+  }
+
+  /* If the call is to send to a process, i.e., for SEND, SENDREC or NOTIFY,
+   * verify that the caller is allowed to send to the given destination. 
+   */
+  if (function & CHECK_DST) {
+      if (! get_sys_bit(priv(caller_ptr)->s_ipc_to, nr_to_id(src_dst))) {
+#if DEBUG_ENABLE_IPC_WARNINGS
+          kprintf("sys_call: ipc mask denied trap %d from %d to %d\n",
+          	function, proc_nr(caller_ptr), src_dst);
+#endif
+          return(ECALLDENIED);		/* call denied by ipc mask */
+      }
+  }
+
+  /* Check for a possible deadlock for blocking SEND(REC) and RECEIVE. */
+  if (function & CHECK_DEADLOCK) {
+      if (group_size = deadlock(function, caller_ptr, src_dst)) {
+#if DEBUG_ENABLE_IPC_WARNINGS
+          kprintf("sys_call: trap %d from %d to %d deadlocked, group size %d\n",
+              function, proc_nr(caller_ptr), src_dst, group_size);
+#endif
+          return(ELOCKED);
+      }
+  }
+
+  /* Now check if the call is known and try to perform the request. The only
+   * system calls that exist in MINIX are sending and receiving messages.
+   *   - SENDREC: combines SEND and RECEIVE in a single system call
+   *   - SEND:    sender blocks until its message has been delivered
+   *   - RECEIVE: receiver blocks until an acceptable message has arrived
+   *   - NOTIFY:  nonblocking call; deliver notification or mark pending
+   *   - ECHO:    nonblocking call; directly echo back the message 
+   */
+  switch(function) {
+  case SENDREC:
+      /* A flag is set so that notifications cannot interrupt SENDREC. */
+      caller_ptr->p_misc_flags |= REPLY_PENDING;
+      /* fall through */
+  case SEND:			
+      result = mini_send(caller_ptr, src_dst_e, m_ptr, flags);
+      if (function == SEND || result != OK) {	
+          break;				/* done, or SEND failed */
+      }						/* fall through for SENDREC */
+  case RECEIVE:			
+      if (function == RECEIVE)
+          caller_ptr->p_misc_flags &= ~REPLY_PENDING;
+      result = mini_receive(caller_ptr, src_dst_e, m_ptr, flags);
+      break;
+  case NOTIFY:
+      result = mini_notify(caller_ptr, src_dst);
+      break;
+  case ECHO:
+      CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, caller_ptr, m_ptr);
+      result = OK;
+      break;
+  default:
+      result = EBADCALL;			/* illegal system call */
+  }
+
+  /* Now, return the result of the system call to the caller. */
+  return(result);
+}
+
+/*===========================================================================*
+ *				deadlock				     * 
+ *===========================================================================*/
+PRIVATE int deadlock(function, cp, src_dst) 
+int function;					/* trap number */
+register struct proc *cp;			/* pointer to caller */
+int src_dst;					/* src or dst process */
+{
+/* Check for deadlock. This can happen if 'caller_ptr' and 'src_dst' have
+ * a cyclic dependency of blocking send and receive calls. The only cyclic 
+ * depency that is not fatal is if the caller and target directly SEND(REC)
+ * and RECEIVE to each other. If a deadlock is found, the group size is 
+ * returned. Otherwise zero is returned. 
+ */
+  register struct proc *xp;			/* process pointer */
+  int group_size = 1;				/* start with only caller */
+  int trap_flags;
+
+  while (src_dst != ANY) { 			/* check while process nr */
+      int src_dst_e;
+      xp = proc_addr(src_dst);			/* follow chain of processes */
+      group_size ++;				/* extra process in group */
+
+      /* Check whether the last process in the chain has a dependency. If it 
+       * has not, the cycle cannot be closed and we are done.
+       */
+      if (xp->p_rts_flags & RECEIVING) {	/* xp has dependency */
+	  if(xp->p_getfrom_e == ANY) src_dst = ANY;
+	  else okendpt(xp->p_getfrom_e, &src_dst);
+      } else if (xp->p_rts_flags & SENDING) {	/* xp has dependency */
+	  okendpt(xp->p_sendto_e, &src_dst);
+      } else {
+	  return(0);				/* not a deadlock */
+      }
+
+      /* Now check if there is a cyclic dependency. For group sizes of two,  
+       * a combination of SEND(REC) and RECEIVE is not fatal. Larger groups
+       * or other combinations indicate a deadlock.  
+       */
+      if (src_dst == proc_nr(cp)) {		/* possible deadlock */
+	  if (group_size == 2) {		/* caller and src_dst */
+	      /* The function number is magically converted to flags. */
+	      if ((xp->p_rts_flags ^ (function << 2)) & SENDING) { 
+	          return(0);			/* not a deadlock */
+	      }
+	  }
+          return(group_size);			/* deadlock found */
+      }
+  }
+  return(0);					/* not a deadlock */
+}
+
+/*===========================================================================*
+ *				mini_send				     * 
+ *===========================================================================*/
+PRIVATE int mini_send(caller_ptr, dst_e, m_ptr, flags)
+register struct proc *caller_ptr;	/* who is trying to send a message? */
+int dst_e;				/* to whom is message being sent? */
+message *m_ptr;				/* pointer to message buffer */
+unsigned flags;				/* system call flags */
+{
+/* Send a message from 'caller_ptr' to 'dst'. If 'dst' is blocked waiting
+ * for this message, copy the message to it and unblock 'dst'. If 'dst' is
+ * not waiting at all, or is waiting for another source, queue 'caller_ptr'.
+ */
+  register struct proc *dst_ptr;
+  register struct proc **xpp;
+  int dst_p;
+
+  dst_p = _ENDPOINT_P(dst_e);
+  dst_ptr = proc_addr(dst_p);
+
+  if (dst_ptr->p_rts_flags & NO_ENDPOINT) return EDSTDIED;
+
+  /* Check if 'dst' is blocked waiting for this message. The destination's 
+   * SENDING flag may be set when its SENDREC call blocked while sending.  
+   */
+  if ( (dst_ptr->p_rts_flags & (RECEIVING | SENDING)) == RECEIVING &&
+       (dst_ptr->p_getfrom_e == ANY
+         || dst_ptr->p_getfrom_e == caller_ptr->p_endpoint)) {
+	/* Destination is indeed waiting for this message. */
+	CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, dst_ptr,
+		 dst_ptr->p_messbuf);
+	if ((dst_ptr->p_rts_flags &= ~RECEIVING) == 0) enqueue(dst_ptr);
+  } else if ( ! (flags & NON_BLOCKING)) {
+	/* Destination is not waiting.  Block and dequeue caller. */
+	caller_ptr->p_messbuf = m_ptr;
+	if (caller_ptr->p_rts_flags == 0) dequeue(caller_ptr);
+	caller_ptr->p_rts_flags |= SENDING;
+	caller_ptr->p_sendto_e = dst_e;
+
+	/* Process is now blocked.  Put in on the destination's queue. */
+	xpp = &dst_ptr->p_caller_q;		/* find end of list */
+	while (*xpp != NIL_PROC) xpp = &(*xpp)->p_q_link;	
+	*xpp = caller_ptr;			/* add caller to end */
+	caller_ptr->p_q_link = NIL_PROC;	/* mark new end of list */
+  } else {
+	return(ENOTREADY);
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *				mini_receive				     * 
+ *===========================================================================*/
+PRIVATE int mini_receive(caller_ptr, src_e, m_ptr, flags)
+register struct proc *caller_ptr;	/* process trying to get message */
+int src_e;				/* which message source is wanted */
+message *m_ptr;				/* pointer to message buffer */
+unsigned flags;				/* system call flags */
+{
+/* A process or task wants to get a message.  If a message is already queued,
+ * acquire it and deblock the sender.  If no message from the desired source
+ * is available block the caller, unless the flags don't allow blocking.  
+ */
+  register struct proc **xpp;
+  register struct notification **ntf_q_pp;
+  message m;
+  int bit_nr;
+  sys_map_t *map;
+  bitchunk_t *chunk;
+  int i, src_id, src_proc_nr, src_p;
+
+  if(src_e == ANY) src_p = ANY;
+  else
+  {
+	okendpt(src_e, &src_p);
+	if (proc_addr(src_p)->p_rts_flags & NO_ENDPOINT) return ESRCDIED;
+  }
+
+
+  /* Check to see if a message from desired source is already available.
+   * The caller's SENDING flag may be set if SENDREC couldn't send. If it is
+   * set, the process should be blocked.
+   */
+  if (!(caller_ptr->p_rts_flags & SENDING)) {
+
+    /* Check if there are pending notifications, except for SENDREC. */
+    if (! (caller_ptr->p_misc_flags & REPLY_PENDING)) {
+
+        map = &priv(caller_ptr)->s_notify_pending;
+        for (chunk=&map->chunk[0]; chunk<&map->chunk[NR_SYS_CHUNKS]; chunk++) {
+
+            /* Find a pending notification from the requested source. */ 
+            if (! *chunk) continue; 			/* no bits in chunk */
+            for (i=0; ! (*chunk & (1<<i)); ++i) {} 	/* look up the bit */
+            src_id = (chunk - &map->chunk[0]) * BITCHUNK_BITS + i;
+            if (src_id >= NR_SYS_PROCS) break;		/* out of range */
+            src_proc_nr = id_to_nr(src_id);		/* get source proc */
+#if DEBUG_ENABLE_IPC_WARNINGS
+	    if(src_proc_nr == NONE) {
+		kprintf("mini_receive: sending notify from NONE\n");
+	    }
+#endif
+            if (src_e!=ANY && src_p != src_proc_nr) continue;/* source not ok */
+            *chunk &= ~(1 << i);			/* no longer pending */
+
+            /* Found a suitable source, deliver the notification message. */
+	    BuildMess(&m, src_proc_nr, caller_ptr);	/* assemble message */
+            CopyMess(src_proc_nr, proc_addr(HARDWARE), &m, caller_ptr, m_ptr);
+            return(OK);					/* report success */
+        }
+    }
+
+    /* Check caller queue. Use pointer pointers to keep code simple. */
+    xpp = &caller_ptr->p_caller_q;
+    while (*xpp != NIL_PROC) {
+        if (src_e == ANY || src_p == proc_nr(*xpp)) {
+#if 0
+	    if ((*xpp)->p_rts_flags & SLOT_FREE)
+	    {
+		kprintf("listening to the dead?!?\n");
+		return EINVAL;
+	    }
+#endif
+
+	    /* Found acceptable message. Copy it and update status. */
+	    CopyMess((*xpp)->p_nr, *xpp, (*xpp)->p_messbuf, caller_ptr, m_ptr);
+            if (((*xpp)->p_rts_flags &= ~SENDING) == 0) enqueue(*xpp);
+            *xpp = (*xpp)->p_q_link;		/* remove from queue */
+            return(OK);				/* report success */
+	}
+	xpp = &(*xpp)->p_q_link;		/* proceed to next */
+    }
+  }
+
+  /* No suitable message is available or the caller couldn't send in SENDREC. 
+   * Block the process trying to receive, unless the flags tell otherwise.
+   */
+  if ( ! (flags & NON_BLOCKING)) {
+      caller_ptr->p_getfrom_e = src_e;		
+      caller_ptr->p_messbuf = m_ptr;
+      if (caller_ptr->p_rts_flags == 0) dequeue(caller_ptr);
+      caller_ptr->p_rts_flags |= RECEIVING;		
+      return(OK);
+  } else {
+      return(ENOTREADY);
+  }
+}
+
+/*===========================================================================*
+ *				mini_notify				     * 
+ *===========================================================================*/
+PRIVATE int mini_notify(caller_ptr, dst)
+register struct proc *caller_ptr;	/* sender of the notification */
+int dst;				/* which process to notify */
+{
+  register struct proc *dst_ptr = proc_addr(dst);
+  int src_id;				/* source id for late delivery */
+  message m;				/* the notification message */
+
+  /* Check to see if target is blocked waiting for this message. A process 
+   * can be both sending and receiving during a SENDREC system call.
+   */
+  if ((dst_ptr->p_rts_flags & (RECEIVING|SENDING)) == RECEIVING &&
+      ! (dst_ptr->p_misc_flags & REPLY_PENDING) &&
+      (dst_ptr->p_getfrom_e == ANY || 
+      dst_ptr->p_getfrom_e == caller_ptr->p_endpoint)) {
+
+      /* Destination is indeed waiting for a message. Assemble a notification 
+       * message and deliver it. Copy from pseudo-source HARDWARE, since the
+       * message is in the kernel's address space.
+       */ 
+      BuildMess(&m, proc_nr(caller_ptr), dst_ptr);
+      CopyMess(proc_nr(caller_ptr), proc_addr(HARDWARE), &m, 
+          dst_ptr, dst_ptr->p_messbuf);
+      dst_ptr->p_rts_flags &= ~RECEIVING;	/* deblock destination */
+      if (dst_ptr->p_rts_flags == 0) enqueue(dst_ptr);
+      return(OK);
+  } 
+
+  /* Destination is not ready to receive the notification. Add it to the 
+   * bit map with pending notifications. Note the indirectness: the system id 
+   * instead of the process number is used in the pending bit map.
+   */ 
+  src_id = priv(caller_ptr)->s_id;
+  set_sys_bit(priv(dst_ptr)->s_notify_pending, src_id); 
+  return(OK);
+}
+
+/*===========================================================================*
+ *				lock_notify				     *
+ *===========================================================================*/
+PUBLIC int lock_notify(src_e, dst_e)
+int src_e;			/* (endpoint) sender of the notification */
+int dst_e;			/* (endpoint) who is to be notified */
+{
+/* Safe gateway to mini_notify() for tasks and interrupt handlers. The sender
+ * is explicitely given to prevent confusion where the call comes from. MINIX 
+ * kernel is not reentrant, which means to interrupts are disabled after 
+ * the first kernel entry (hardware interrupt, trap, or exception). Locking
+ * is done by temporarily disabling interrupts. 
+ */
+  int result, src, dst;
+
+  if(!isokendpt(src_e, &src) || !isokendpt(dst_e, &dst))
+	return EDEADSRCDST;
+
+  /* Exception or interrupt occurred, thus already locked. */
+  if (k_reenter >= 0) {
+      result = mini_notify(proc_addr(src), dst); 
+  }
+
+  /* Call from task level, locking is required. */
+  else {
+      lock(0, "notify");
+      result = mini_notify(proc_addr(src), dst); 
+      unlock(0);
+  }
+  return(result);
+}
+
+/*===========================================================================*
+ *				enqueue					     * 
+ *===========================================================================*/
+PRIVATE void enqueue(rp)
+register struct proc *rp;	/* this process is now runnable */
+{
+/* Add 'rp' to one of the queues of runnable processes.  This function is 
+ * responsible for inserting a process into one of the scheduling queues. 
+ * The mechanism is implemented here.   The actual scheduling policy is
+ * defined in sched() and pick_proc().
+ */
+  int q;	 				/* scheduling queue to use */
+  int front;					/* add to front or back */
+
+#if DEBUG_SCHED_CHECK
+  check_runqueues("enqueue");
+  if (rp->p_ready) kprintf("enqueue() already ready process\n");
+#endif
+
+  /* Determine where to insert to process. */
+  sched(rp, &q, &front);
+
+  /* Now add the process to the queue. */
+  if (rdy_head[q] == NIL_PROC) {		/* add to empty queue */
+      rdy_head[q] = rdy_tail[q] = rp; 		/* create a new queue */
+      rp->p_nextready = NIL_PROC;		/* mark new end */
+  } 
+  else if (front) {				/* add to head of queue */
+      rp->p_nextready = rdy_head[q];		/* chain head of queue */
+      rdy_head[q] = rp;				/* set new queue head */
+  } 
+  else {					/* add to tail of queue */
+      rdy_tail[q]->p_nextready = rp;		/* chain tail of queue */	
+      rdy_tail[q] = rp;				/* set new queue tail */
+      rp->p_nextready = NIL_PROC;		/* mark new end */
+  }
+
+  /* Now select the next process to run. */
+  pick_proc();			
+
+#if DEBUG_SCHED_CHECK
+  rp->p_ready = 1;
+  check_runqueues("enqueue");
+#endif
+}
+
+/*===========================================================================*
+ *				dequeue					     * 
+ *===========================================================================*/
+PRIVATE void dequeue(rp)
+register struct proc *rp;	/* this process is no longer runnable */
+{
+/* A process must be removed from the scheduling queues, for example, because
+ * it has blocked.  If the currently active process is removed, a new process
+ * is picked to run by calling pick_proc().
+ */
+  register int q = rp->p_priority;		/* queue to use */
+  register struct proc **xpp;			/* iterate over queue */
+  register struct proc *prev_xp;
+
+  /* Side-effect for kernel: check if the task's stack still is ok? */
+  if (iskernelp(rp)) { 				
+	if (*priv(rp)->s_stack_guard != STACK_GUARD)
+		panic("stack overrun by task", proc_nr(rp));
+  }
+
+#if DEBUG_SCHED_CHECK
+  check_runqueues("dequeue");
+  if (! rp->p_ready) kprintf("dequeue() already unready process\n");
+#endif
+
+  /* Now make sure that the process is not in its ready queue. Remove the 
+   * process if it is found. A process can be made unready even if it is not 
+   * running by being sent a signal that kills it.
+   */
+  prev_xp = NIL_PROC;				
+  for (xpp = &rdy_head[q]; *xpp != NIL_PROC; xpp = &(*xpp)->p_nextready) {
+
+      if (*xpp == rp) {				/* found process to remove */
+          *xpp = (*xpp)->p_nextready;		/* replace with next chain */
+          if (rp == rdy_tail[q])		/* queue tail removed */
+              rdy_tail[q] = prev_xp;		/* set new tail */
+          if (rp == proc_ptr || rp == next_ptr)	/* active process removed */
+              pick_proc();			/* pick new process to run */
+          break;
+      }
+      prev_xp = *xpp;				/* save previous in chain */
+  }
+
+#if DEBUG_SCHED_CHECK
+  rp->p_ready = 0;
+  check_runqueues("dequeue");
+#endif
+}
+
+/*===========================================================================*
+ *				sched					     * 
+ *===========================================================================*/
+PRIVATE void sched(rp, queue, front)
+register struct proc *rp;			/* process to be scheduled */
+int *queue;					/* return: queue to use */
+int *front;					/* return: front or back */
+{
+/* This function determines the scheduling policy.  It is called whenever a
+ * process must be added to one of the scheduling queues to decide where to
+ * insert it.  As a side-effect the process' priority may be updated.  
+ */
+  int time_left = (rp->p_ticks_left > 0);	/* quantum fully consumed */
+
+  /* Check whether the process has time left. Otherwise give a new quantum 
+   * and lower the process' priority, unless the process already is in the 
+   * lowest queue.  
+   */
+  if (! time_left) {				/* quantum consumed ? */
+      rp->p_ticks_left = rp->p_quantum_size; 	/* give new quantum */
+      if (rp->p_priority < (IDLE_Q-1)) {  	 
+          rp->p_priority += 1;			/* lower priority */
+      }
+  }
+
+  /* If there is time left, the process is added to the front of its queue, 
+   * so that it can immediately run. The queue to use simply is always the
+   * process' current priority. 
+   */
+  *queue = rp->p_priority;
+  *front = time_left;
+}
+
+/*===========================================================================*
+ *				pick_proc				     * 
+ *===========================================================================*/
+PRIVATE void pick_proc()
+{
+/* Decide who to run now.  A new process is selected by setting 'next_ptr'.
+ * When a billable process is selected, record it in 'bill_ptr', so that the 
+ * clock task can tell who to bill for system time.
+ */
+  register struct proc *rp;			/* process to run */
+  int q;					/* iterate over queues */
+
+  /* Check each of the scheduling queues for ready processes. The number of
+   * queues is defined in proc.h, and priorities are set in the task table.
+   * The lowest queue contains IDLE, which is always ready.
+   */
+  for (q=0; q < NR_SCHED_QUEUES; q++) {	
+      if ( (rp = rdy_head[q]) != NIL_PROC) {
+          next_ptr = rp;			/* run process 'rp' next */
+          if (priv(rp)->s_flags & BILLABLE)	 	
+              bill_ptr = rp;			/* bill for system time */
+          return;				 
+      }
+  }
+}
+
+/*===========================================================================*
+ *				balance_queues				     *
+ *===========================================================================*/
+#define Q_BALANCE_TICKS	 100
+PUBLIC void balance_queues(tp)
+timer_t *tp;					/* watchdog timer pointer */
+{
+/* Check entire process table and give all process a higher priority. This
+ * effectively means giving a new quantum. If a process already is at its 
+ * maximum priority, its quantum will be renewed.
+ */
+  static timer_t queue_timer;			/* timer structure to use */
+  register struct proc* rp;			/* process table pointer  */
+  clock_t next_period;				/* time of next period  */
+  int ticks_added = 0;				/* total time added */
+
+  for (rp=BEG_PROC_ADDR; rp<END_PROC_ADDR; rp++) {
+      if (! isemptyp(rp)) {				/* check slot use */
+	  lock(5,"balance_queues");
+	  if (rp->p_priority > rp->p_max_priority) {	/* update priority? */
+	      if (rp->p_rts_flags == 0) dequeue(rp);	/* take off queue */
+	      ticks_added += rp->p_quantum_size;	/* do accounting */
+	      rp->p_priority -= 1;			/* raise priority */
+	      if (rp->p_rts_flags == 0) enqueue(rp);	/* put on queue */
+	  }
+	  else {
+	      ticks_added += rp->p_quantum_size - rp->p_ticks_left;
+              rp->p_ticks_left = rp->p_quantum_size; 	/* give new quantum */
+	  }
+	  unlock(5);
+      }
+  }
+#if DEBUG
+  kprintf("ticks_added: %d\n", ticks_added);
+#endif
+
+  /* Now schedule a new watchdog timer to balance the queues again.  The 
+   * period depends on the total amount of quantum ticks added.
+   */
+  next_period = MAX(Q_BALANCE_TICKS, ticks_added);	/* calculate next */
+  set_timer(&queue_timer, get_uptime() + next_period, balance_queues);
+}
+
+/*===========================================================================*
+ *				lock_send				     *
+ *===========================================================================*/
+PUBLIC int lock_send(dst_e, m_ptr)
+int dst_e;			/* to whom is message being sent? */
+message *m_ptr;			/* pointer to message buffer */
+{
+/* Safe gateway to mini_send() for tasks. */
+  int result;
+  lock(2, "send");
+  result = mini_send(proc_ptr, dst_e, m_ptr, NON_BLOCKING);
+  unlock(2);
+  return(result);
+}
+
+/*===========================================================================*
+ *				lock_enqueue				     *
+ *===========================================================================*/
+PUBLIC void lock_enqueue(rp)
+struct proc *rp;		/* this process is now runnable */
+{
+/* Safe gateway to enqueue() for tasks. */
+  lock(3, "enqueue");
+  enqueue(rp);
+  unlock(3);
+}
+
+/*===========================================================================*
+ *				lock_dequeue				     *
+ *===========================================================================*/
+PUBLIC void lock_dequeue(rp)
+struct proc *rp;		/* this process is no longer runnable */
+{
+/* Safe gateway to dequeue() for tasks. */
+  if (k_reenter >= 0) {
+	/* We're in an exception or interrupt, so don't lock (and ... 
+	 * don't unlock).
+	 */
+	dequeue(rp);
+  } else {
+	lock(4, "dequeue");
+	dequeue(rp);
+	unlock(4);
+  }
+}
+
+/*===========================================================================*
+ *				isokendpt_f				     *
+ *===========================================================================*/
+#if DEBUG_ENABLE_IPC_WARNINGS
+PUBLIC int isokendpt_f(file, line, e, p, fatalflag)
+char *file;
+int line;
+#else
+PUBLIC int isokendpt_f(e, p, fatalflag)
+#endif
+int e, *p, fatalflag;
+{
+	int ok = 0;
+	/* Convert an endpoint number into a process number.
+	 * Return nonzero if the process is alive with the corresponding
+	 * generation number, zero otherwise.
+	 *
+	 * This function is called with file and line number by the
+	 * isokendpt_d macro if DEBUG_ENABLE_IPC_WARNINGS is defined,
+	 * otherwise without. This allows us to print the where the
+	 * conversion was attempted, making the errors verbose without
+	 * adding code for that at every call.
+	 * 
+	 * If fatalflag is nonzero, we must panic if the conversion doesn't
+	 * succeed.
+	 */
+	*p = _ENDPOINT_P(e);
+	if(!isokprocn(*p)) {
+#if DEBUG_ENABLE_IPC_WARNINGS
+		kprintf("kernel:%s:%d: bad endpoint %d: proc %d out of range\n",
+		file, line, e, *p);
+#endif
+	} else if(isemptyn(*p)) {
+#if DEBUG_ENABLE_IPC_WARNINGS
+	kprintf("kernel:%s:%d: bad endpoint %d: proc %d empty\n", file, line, e, *p);
+#endif
+	} else if(proc_addr(*p)->p_endpoint != e) {
+#if DEBUG_ENABLE_IPC_WARNINGS
+		kprintf("kernel:%s:%d: bad endpoint %d: proc %d has ept %d (generation %d vs. %d)\n", file, line,
+		e, *p, proc_addr(*p)->p_endpoint,
+		_ENDPOINT_G(e), _ENDPOINT_G(proc_addr(*p)->p_endpoint));
+#endif
+	} else ok = 1;
+	if(!ok && fatalflag) {
+		panic("invalid endpoint ", e);
+	}
+	return ok;
+}
+
Index: /trunk/minix/kernel/proc.h
===================================================================
--- /trunk/minix/kernel/proc.h	(revision 9)
+++ /trunk/minix/kernel/proc.h	(revision 9)
@@ -0,0 +1,119 @@
+#ifndef PROC_H
+#define PROC_H
+
+/* Here is the declaration of the process table.  It contains all process
+ * data, including registers, flags, scheduling priority, memory map, 
+ * accounting, message passing (IPC) information, and so on. 
+ *
+ * Many assembly code routines reference fields in it.  The offsets to these
+ * fields are defined in the assembler include file sconst.h.  When changing
+ * struct proc, be sure to change sconst.h to match.
+ */
+#include <minix/com.h>
+#include "protect.h"
+#include "const.h"
+#include "priv.h"
+ 
+struct proc {
+  struct stackframe_s p_reg;	/* process' registers saved in stack frame */
+
+#if (CHIP == INTEL)
+  reg_t p_ldt_sel;		/* selector in gdt with ldt base and limit */
+  struct segdesc_s p_ldt[2+NR_REMOTE_SEGS]; /* CS, DS and remote segments */
+#endif 
+
+#if (CHIP == M68000)
+/* M68000 specific registers and FPU details go here. */
+#endif 
+
+  proc_nr_t p_nr;		/* number of this process (for fast access) */
+  struct priv *p_priv;		/* system privileges structure */
+  short p_rts_flags;		/* process is runnable only if zero */
+  short p_misc_flags;		/* flags that do suspend the process */
+
+  char p_priority;		/* current scheduling priority */
+  char p_max_priority;		/* maximum scheduling priority */
+  char p_ticks_left;		/* number of scheduling ticks left */
+  char p_quantum_size;		/* quantum size in ticks */
+
+  struct mem_map p_memmap[NR_LOCAL_SEGS];   /* memory map (T, D, S) */
+
+  clock_t p_user_time;		/* user time in ticks */
+  clock_t p_sys_time;		/* sys time in ticks */
+
+  struct proc *p_nextready;	/* pointer to next ready process */
+  struct proc *p_caller_q;	/* head of list of procs wishing to send */
+  struct proc *p_q_link;	/* link to next proc wishing to send */
+  message *p_messbuf;		/* pointer to passed message buffer */
+  int p_getfrom_e;		/* from whom does process want to receive? */
+  int p_sendto_e;		/* to whom does process want to send? */
+
+  sigset_t p_pending;		/* bit map for pending kernel signals */
+
+  char p_name[P_NAME_LEN];	/* name of the process, including \0 */
+
+  int p_endpoint;		/* endpoint number, generation-aware */
+
+#if DEBUG_SCHED_CHECK
+  int p_ready, p_found;
+#endif
+};
+
+/* Bits for the runtime flags. A process is runnable iff p_rts_flags == 0. */
+#define SLOT_FREE	0x01	/* process slot is free */
+#define NO_MAP		0x02	/* keeps unmapped forked child from running */
+#define SENDING		0x04	/* process blocked trying to send */
+#define RECEIVING	0x08	/* process blocked trying to receive */
+#define SIGNALED	0x10	/* set when new kernel signal arrives */
+#define SIG_PENDING	0x20	/* unready while signal being processed */
+#define P_STOP		0x40	/* set when process is being traced */
+#define NO_PRIV		0x80	/* keep forked system process from running */
+#define NO_PRIORITY    0x100	/* process has been stopped */
+#define NO_ENDPOINT    0x200	/* process cannot send or receive messages */
+
+/* Misc flags */
+#define REPLY_PENDING	0x01	/* reply to IPC_REQUEST is pending */
+#define MF_VM		0x08	/* process uses VM */
+
+/* Scheduling priorities for p_priority. Values must start at zero (highest
+ * priority) and increment.  Priorities of the processes in the boot image 
+ * can be set in table.c. IDLE must have a queue for itself, to prevent low 
+ * priority user processes to run round-robin with IDLE. 
+ */
+#define NR_SCHED_QUEUES   16	/* MUST equal minimum priority + 1 */
+#define TASK_Q		   0	/* highest, used for kernel tasks */
+#define MAX_USER_Q  	   0    /* highest priority for user processes */   
+#define USER_Q  	   7    /* default (should correspond to nice 0) */   
+#define MIN_USER_Q	  14	/* minimum priority for user processes */
+#define IDLE_Q		  15    /* lowest, only IDLE process goes here */
+
+/* Magic process table addresses. */
+#define BEG_PROC_ADDR (&proc[0])
+#define BEG_USER_ADDR (&proc[NR_TASKS])
+#define END_PROC_ADDR (&proc[NR_TASKS + NR_PROCS])
+
+#define NIL_PROC          ((struct proc *) 0)		
+#define NIL_SYS_PROC      ((struct proc *) 1)		
+#define cproc_addr(n)     (&(proc + NR_TASKS)[(n)])
+#define proc_addr(n)      (pproc_addr + NR_TASKS)[(n)]
+#define proc_nr(p) 	  ((p)->p_nr)
+
+#define isokprocn(n)      ((unsigned) ((n) + NR_TASKS) < NR_PROCS + NR_TASKS)
+#define isemptyn(n)       isemptyp(proc_addr(n)) 
+#define isemptyp(p)       ((p)->p_rts_flags == SLOT_FREE)
+#define iskernelp(p)	  iskerneln((p)->p_nr)
+#define iskerneln(n)	  ((n) < 0)
+#define isuserp(p)        isusern((p)->p_nr)
+#define isusern(n)        ((n) >= 0)
+
+/* The process table and pointers to process table slots. The pointers allow
+ * faster access because now a process entry can be found by indexing the
+ * pproc_addr array, while accessing an element i requires a multiplication
+ * with sizeof(struct proc) to determine the address. 
+ */
+EXTERN struct proc proc[NR_TASKS + NR_PROCS];	/* process table */
+EXTERN struct proc *pproc_addr[NR_TASKS + NR_PROCS];
+EXTERN struct proc *rdy_head[NR_SCHED_QUEUES]; /* ptrs to ready list headers */
+EXTERN struct proc *rdy_tail[NR_SCHED_QUEUES]; /* ptrs to ready list tails */
+
+#endif /* PROC_H */
Index: /trunk/minix/kernel/protect.c
===================================================================
--- /trunk/minix/kernel/protect.c	(revision 9)
+++ /trunk/minix/kernel/protect.c	(revision 9)
@@ -0,0 +1,382 @@
+/* This file contains code for initialization of protected mode, to initialize
+ * code and data segment descriptors, and to initialize global descriptors
+ * for local descriptors in the process table.
+ */
+
+#include "kernel.h"
+#include "proc.h"
+#include "protect.h"
+
+#if _WORD_SIZE == 4
+#define INT_GATE_TYPE	(INT_286_GATE | DESC_386_BIT)
+#define TSS_TYPE	(AVL_286_TSS  | DESC_386_BIT)
+#else
+#define INT_GATE_TYPE	INT_286_GATE
+#define TSS_TYPE	AVL_286_TSS
+#endif
+
+struct desctableptr_s {
+  char limit[sizeof(u16_t)];
+  char base[sizeof(u32_t)];		/* really u24_t + pad for 286 */
+};
+
+struct gatedesc_s {
+  u16_t offset_low;
+  u16_t selector;
+  u8_t pad;			/* |000|XXXXX| ig & trpg, |XXXXXXXX| task g */
+  u8_t p_dpl_type;		/* |P|DL|0|TYPE| */
+  u16_t offset_high;
+};
+
+struct tss_s {
+  reg_t backlink;
+  reg_t sp0;                    /* stack pointer to use during interrupt */
+  reg_t ss0;                    /*   "   segment  "  "    "        "     */
+  reg_t sp1;
+  reg_t ss1;
+  reg_t sp2;
+  reg_t ss2;
+#if _WORD_SIZE == 4
+  reg_t cr3;
+#endif
+  reg_t ip;
+  reg_t flags;
+  reg_t ax;
+  reg_t cx;
+  reg_t dx;
+  reg_t bx;
+  reg_t sp;
+  reg_t bp;
+  reg_t si;
+  reg_t di;
+  reg_t es;
+  reg_t cs;
+  reg_t ss;
+  reg_t ds;
+#if _WORD_SIZE == 4
+  reg_t fs;
+  reg_t gs;
+#endif
+  reg_t ldt;
+#if _WORD_SIZE == 4
+  u16_t trap;
+  u16_t iobase;
+/* u8_t iomap[0]; */
+#endif
+};
+
+PUBLIC struct segdesc_s gdt[GDT_SIZE];		/* used in klib.s and mpx.s */
+PRIVATE struct gatedesc_s idt[IDT_SIZE];	/* zero-init so none present */
+PUBLIC struct tss_s tss;			/* zero init */
+
+FORWARD _PROTOTYPE( void int_gate, (unsigned vec_nr, vir_bytes offset,
+		unsigned dpl_type) );
+FORWARD _PROTOTYPE( void sdesc, (struct segdesc_s *segdp, phys_bytes base,
+		vir_bytes size) );
+
+/*===========================================================================*
+ *				prot_init				     *
+ *===========================================================================*/
+PUBLIC void prot_init()
+{
+/* Set up tables for protected mode.
+ * All GDT slots are allocated at compile time.
+ */
+  struct gate_table_s *gtp;
+  struct desctableptr_s *dtp;
+  unsigned ldt_index;
+  register struct proc *rp;
+
+  static struct gate_table_s {
+	_PROTOTYPE( void (*gate), (void) );
+	unsigned char vec_nr;
+	unsigned char privilege;
+  }
+  gate_table[] = {
+	{ divide_error, DIVIDE_VECTOR, INTR_PRIVILEGE },
+	{ single_step_exception, DEBUG_VECTOR, INTR_PRIVILEGE },
+	{ nmi, NMI_VECTOR, INTR_PRIVILEGE },
+	{ breakpoint_exception, BREAKPOINT_VECTOR, USER_PRIVILEGE },
+	{ overflow, OVERFLOW_VECTOR, USER_PRIVILEGE },
+	{ bounds_check, BOUNDS_VECTOR, INTR_PRIVILEGE },
+	{ inval_opcode, INVAL_OP_VECTOR, INTR_PRIVILEGE },
+	{ copr_not_available, COPROC_NOT_VECTOR, INTR_PRIVILEGE },
+	{ double_fault, DOUBLE_FAULT_VECTOR, INTR_PRIVILEGE },
+	{ copr_seg_overrun, COPROC_SEG_VECTOR, INTR_PRIVILEGE },
+	{ inval_tss, INVAL_TSS_VECTOR, INTR_PRIVILEGE },
+	{ segment_not_present, SEG_NOT_VECTOR, INTR_PRIVILEGE },
+	{ stack_exception, STACK_FAULT_VECTOR, INTR_PRIVILEGE },
+	{ general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE },
+#if _WORD_SIZE == 4
+	{ page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE },
+	{ copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE },
+#endif
+	{ hwint00, VECTOR( 0), INTR_PRIVILEGE },
+	{ hwint01, VECTOR( 1), INTR_PRIVILEGE },
+	{ hwint02, VECTOR( 2), INTR_PRIVILEGE },
+	{ hwint03, VECTOR( 3), INTR_PRIVILEGE },
+	{ hwint04, VECTOR( 4), INTR_PRIVILEGE },
+	{ hwint05, VECTOR( 5), INTR_PRIVILEGE },
+	{ hwint06, VECTOR( 6), INTR_PRIVILEGE },
+	{ hwint07, VECTOR( 7), INTR_PRIVILEGE },
+	{ hwint08, VECTOR( 8), INTR_PRIVILEGE },
+	{ hwint09, VECTOR( 9), INTR_PRIVILEGE },
+	{ hwint10, VECTOR(10), INTR_PRIVILEGE },
+	{ hwint11, VECTOR(11), INTR_PRIVILEGE },
+	{ hwint12, VECTOR(12), INTR_PRIVILEGE },
+	{ hwint13, VECTOR(13), INTR_PRIVILEGE },
+	{ hwint14, VECTOR(14), INTR_PRIVILEGE },
+	{ hwint15, VECTOR(15), INTR_PRIVILEGE },
+#if _WORD_SIZE == 2
+	{ p_s_call, SYS_VECTOR, USER_PRIVILEGE },	/* 286 system call */
+#else
+	{ s_call, SYS386_VECTOR, USER_PRIVILEGE },	/* 386 system call */
+#endif
+	{ level0_call, LEVEL0_VECTOR, TASK_PRIVILEGE },
+  };
+
+  /* Build gdt and idt pointers in GDT where the BIOS expects them. */
+  dtp= (struct desctableptr_s *) &gdt[GDT_INDEX];
+  * (u16_t *) dtp->limit = (sizeof gdt) - 1;
+  * (u32_t *) dtp->base = vir2phys(gdt);
+
+  dtp= (struct desctableptr_s *) &gdt[IDT_INDEX];
+  * (u16_t *) dtp->limit = (sizeof idt) - 1;
+  * (u32_t *) dtp->base = vir2phys(idt);
+
+  /* Build segment descriptors for tasks and interrupt handlers. */
+  init_codeseg(&gdt[CS_INDEX],
+  	 kinfo.code_base, kinfo.code_size, INTR_PRIVILEGE);
+  init_dataseg(&gdt[DS_INDEX],
+  	 kinfo.data_base, kinfo.data_size, INTR_PRIVILEGE);
+  init_dataseg(&gdt[ES_INDEX], 0L, 0, TASK_PRIVILEGE);
+
+  /* Build scratch descriptors for functions in klib88. */
+  init_dataseg(&gdt[DS_286_INDEX], 0L, 0, TASK_PRIVILEGE);
+  init_dataseg(&gdt[ES_286_INDEX], 0L, 0, TASK_PRIVILEGE);
+
+  /* Build local descriptors in GDT for LDT's in process table.
+   * The LDT's are allocated at compile time in the process table, and
+   * initialized whenever a process' map is initialized or changed.
+   */
+  for (rp = BEG_PROC_ADDR, ldt_index = FIRST_LDT_INDEX;
+       rp < END_PROC_ADDR; ++rp, ldt_index++) {
+	init_dataseg(&gdt[ldt_index], vir2phys(rp->p_ldt),
+				     sizeof(rp->p_ldt), INTR_PRIVILEGE);
+	gdt[ldt_index].access = PRESENT | LDT;
+	rp->p_ldt_sel = ldt_index * DESC_SIZE;
+  }
+
+  /* Build main TSS.
+   * This is used only to record the stack pointer to be used after an
+   * interrupt.
+   * The pointer is set up so that an interrupt automatically saves the
+   * current process's registers ip:cs:f:sp:ss in the correct slots in the
+   * process table.
+   */
+  tss.ss0 = DS_SELECTOR;
+  init_dataseg(&gdt[TSS_INDEX], vir2phys(&tss), sizeof(tss), INTR_PRIVILEGE);
+  gdt[TSS_INDEX].access = PRESENT | (INTR_PRIVILEGE << DPL_SHIFT) | TSS_TYPE;
+
+  /* Build descriptors for interrupt gates in IDT. */
+  for (gtp = &gate_table[0];
+       gtp < &gate_table[sizeof gate_table / sizeof gate_table[0]]; ++gtp) {
+	int_gate(gtp->vec_nr, (vir_bytes) gtp->gate,
+		 PRESENT | INT_GATE_TYPE | (gtp->privilege << DPL_SHIFT));
+  }
+
+#if _WORD_SIZE == 4
+  /* Complete building of main TSS. */
+  tss.iobase = sizeof tss;	/* empty i/o permissions map */
+#endif
+}
+
+/*===========================================================================*
+ *				init_codeseg				     *
+ *===========================================================================*/
+PUBLIC void init_codeseg(segdp, base, size, privilege)
+register struct segdesc_s *segdp;
+phys_bytes base;
+vir_bytes size;
+int privilege;
+{
+/* Build descriptor for a code segment. */
+  sdesc(segdp, base, size);
+  segdp->access = (privilege << DPL_SHIFT)
+	        | (PRESENT | SEGMENT | EXECUTABLE | READABLE);
+		/* CONFORMING = 0, ACCESSED = 0 */
+}
+
+/*===========================================================================*
+ *				init_dataseg				     *
+ *===========================================================================*/
+PUBLIC void init_dataseg(segdp, base, size, privilege)
+register struct segdesc_s *segdp;
+phys_bytes base;
+vir_bytes size;
+int privilege;
+{
+/* Build descriptor for a data segment. */
+  sdesc(segdp, base, size);
+  segdp->access = (privilege << DPL_SHIFT) | (PRESENT | SEGMENT | WRITEABLE);
+		/* EXECUTABLE = 0, EXPAND_DOWN = 0, ACCESSED = 0 */
+}
+
+/*===========================================================================*
+ *				sdesc					     *
+ *===========================================================================*/
+PRIVATE void sdesc(segdp, base, size)
+register struct segdesc_s *segdp;
+phys_bytes base;
+vir_bytes size;
+{
+/* Fill in the size fields (base, limit and granularity) of a descriptor. */
+  segdp->base_low = base;
+  segdp->base_middle = base >> BASE_MIDDLE_SHIFT;
+  segdp->base_high = base >> BASE_HIGH_SHIFT;
+
+#if _WORD_SIZE == 4
+  --size;			/* convert to a limit, 0 size means 4G */
+  if (size > BYTE_GRAN_MAX) {
+	segdp->limit_low = size >> PAGE_GRAN_SHIFT;
+	segdp->granularity = GRANULAR | (size >>
+				     (PAGE_GRAN_SHIFT + GRANULARITY_SHIFT));
+  } else {
+	segdp->limit_low = size;
+	segdp->granularity = size >> GRANULARITY_SHIFT;
+  }
+  segdp->granularity |= DEFAULT;	/* means BIG for data seg */
+#else
+  segdp->limit_low = size - 1;
+#endif
+}
+
+/*===========================================================================*
+ *				seg2phys				     *
+ *===========================================================================*/
+PUBLIC phys_bytes seg2phys(seg)
+U16_t seg;
+{
+/* Return the base address of a segment, with seg being either a 8086 segment
+ * register, or a 286/386 segment selector.
+ */
+  phys_bytes base;
+  struct segdesc_s *segdp;
+
+  if (! machine.prot) {
+	base = hclick_to_physb(seg);
+  } else {
+	segdp = &gdt[seg >> 3];
+	base =    ((u32_t) segdp->base_low << 0)
+		| ((u32_t) segdp->base_middle << 16)
+		| ((u32_t) segdp->base_high << 24);
+  }
+  return base;
+}
+
+/*===========================================================================*
+ *				phys2seg				     *
+ *===========================================================================*/
+PUBLIC void phys2seg(seg, off, phys)
+u16_t *seg;
+vir_bytes *off;
+phys_bytes phys;
+{
+/* Return a segment selector and offset that can be used to reach a physical
+ * address, for use by a driver doing memory I/O in the A0000 - DFFFF range.
+ */
+#if _WORD_SIZE == 2
+  if (! machine.prot) {
+	*seg = phys / HCLICK_SIZE;
+	*off = phys % HCLICK_SIZE;
+  } else {
+	unsigned bank = phys >> 16;
+	unsigned index = bank - 0xA + A_INDEX;
+	init_dataseg(&gdt[index], (phys_bytes) bank << 16, 0, TASK_PRIVILEGE);
+	*seg = (index * 0x08) | TASK_PRIVILEGE;
+	*off = phys & 0xFFFF;
+  }
+#else
+  *seg = FLAT_DS_SELECTOR;
+  *off = phys;
+#endif
+}
+
+/*===========================================================================*
+ *				int_gate				     *
+ *===========================================================================*/
+PRIVATE void int_gate(vec_nr, offset, dpl_type)
+unsigned vec_nr;
+vir_bytes offset;
+unsigned dpl_type;
+{
+/* Build descriptor for an interrupt gate. */
+  register struct gatedesc_s *idp;
+
+  idp = &idt[vec_nr];
+  idp->offset_low = offset;
+  idp->selector = CS_SELECTOR;
+  idp->p_dpl_type = dpl_type;
+#if _WORD_SIZE == 4
+  idp->offset_high = offset >> OFFSET_HIGH_SHIFT;
+#endif
+}
+
+/*===========================================================================*
+ *				enable_iop				     * 
+ *===========================================================================*/
+PUBLIC void enable_iop(pp)
+struct proc *pp;
+{
+/* Allow a user process to use I/O instructions.  Change the I/O Permission
+ * Level bits in the psw. These specify least-privileged Current Permission
+ * Level allowed to execute I/O instructions. Users and servers have CPL 3. 
+ * You can't have less privilege than that. Kernel has CPL 0, tasks CPL 1.
+ */
+  pp->p_reg.psw |= 0x3000;
+}
+
+/*===========================================================================*
+ *				alloc_segments				     *
+ *===========================================================================*/
+PUBLIC void alloc_segments(rp)
+register struct proc *rp;
+{
+/* This is called at system initialization from main() and by do_newmap(). 
+ * The code has a separate function because of all hardware-dependencies.
+ * Note that IDLE is part of the kernel and gets TASK_PRIVILEGE here.
+ */
+  phys_bytes code_bytes;
+  phys_bytes data_bytes;
+  int privilege;
+
+  if (machine.prot) {
+      data_bytes = (phys_bytes) (rp->p_memmap[S].mem_vir + 
+          rp->p_memmap[S].mem_len) << CLICK_SHIFT;
+      if (rp->p_memmap[T].mem_len == 0)
+          code_bytes = data_bytes;	/* common I&D, poor protect */
+      else
+          code_bytes = (phys_bytes) rp->p_memmap[T].mem_len << CLICK_SHIFT;
+      privilege = (iskernelp(rp)) ? TASK_PRIVILEGE : USER_PRIVILEGE;
+      init_codeseg(&rp->p_ldt[CS_LDT_INDEX],
+          (phys_bytes) rp->p_memmap[T].mem_phys << CLICK_SHIFT,
+          code_bytes, privilege);
+      init_dataseg(&rp->p_ldt[DS_LDT_INDEX],
+          (phys_bytes) rp->p_memmap[D].mem_phys << CLICK_SHIFT,
+          data_bytes, privilege);
+      rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege;
+#if _WORD_SIZE == 4
+      rp->p_reg.gs =
+      rp->p_reg.fs =
+#endif
+      rp->p_reg.ss =
+      rp->p_reg.es =
+      rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
+  } else {
+      rp->p_reg.cs = click_to_hclick(rp->p_memmap[T].mem_phys);
+      rp->p_reg.ss =
+      rp->p_reg.es =
+      rp->p_reg.ds = click_to_hclick(rp->p_memmap[D].mem_phys);
+  }
+}
+
Index: /trunk/minix/kernel/protect.h
===================================================================
--- /trunk/minix/kernel/protect.h	(revision 9)
+++ /trunk/minix/kernel/protect.h	(revision 9)
@@ -0,0 +1,124 @@
+/* Constants for protected mode. */
+
+/* Table sizes. */
+#define GDT_SIZE (FIRST_LDT_INDEX + NR_TASKS + NR_PROCS) 
+					/* spec. and LDT's */
+#define IDT_SIZE (IRQ8_VECTOR + 8)	/* only up to the highest vector */
+#define LDT_SIZE (2 + NR_REMOTE_SEGS) 	/* CS, DS and remote segments */
+
+/* Fixed global descriptors.  1 to 7 are prescribed by the BIOS. */
+#define GDT_INDEX            1	/* GDT descriptor */
+#define IDT_INDEX            2	/* IDT descriptor */
+#define DS_INDEX             3	/* kernel DS */
+#define ES_INDEX             4	/* kernel ES (386: flag 4 Gb at startup) */
+#define SS_INDEX             5	/* kernel SS (386: monitor SS at startup) */
+#define CS_INDEX             6	/* kernel CS */
+#define MON_CS_INDEX         7	/* temp for BIOS (386: monitor CS at startup) */
+#define TSS_INDEX            8	/* kernel TSS */
+#define DS_286_INDEX         9	/* scratch 16-bit source segment */
+#define ES_286_INDEX        10	/* scratch 16-bit destination segment */
+#define A_INDEX             11	/* 64K memory segment at A0000 */
+#define B_INDEX             12	/* 64K memory segment at B0000 */
+#define C_INDEX             13	/* 64K memory segment at C0000 */
+#define D_INDEX             14	/* 64K memory segment at D0000 */
+#define FIRST_LDT_INDEX     15	/* rest of descriptors are LDT's */
+
+#define GDT_SELECTOR      0x08	/* (GDT_INDEX * DESC_SIZE) bad for asld */
+#define IDT_SELECTOR      0x10	/* (IDT_INDEX * DESC_SIZE) */
+#define DS_SELECTOR       0x18	/* (DS_INDEX * DESC_SIZE) */
+#define ES_SELECTOR       0x20	/* (ES_INDEX * DESC_SIZE) */
+#define FLAT_DS_SELECTOR  0x21	/* less privileged ES */
+#define SS_SELECTOR       0x28	/* (SS_INDEX * DESC_SIZE) */
+#define CS_SELECTOR       0x30	/* (CS_INDEX * DESC_SIZE) */
+#define MON_CS_SELECTOR   0x38	/* (MON_CS_INDEX * DESC_SIZE) */
+#define TSS_SELECTOR      0x40	/* (TSS_INDEX * DESC_SIZE) */
+#define DS_286_SELECTOR   0x49	/* (DS_286_INDEX*DESC_SIZE+TASK_PRIVILEGE) */
+#define ES_286_SELECTOR   0x51	/* (ES_286_INDEX*DESC_SIZE+TASK_PRIVILEGE) */
+
+/* Fixed local descriptors. */
+#define CS_LDT_INDEX         0	/* process CS */
+#define DS_LDT_INDEX         1	/* process DS=ES=FS=GS=SS */
+#define EXTRA_LDT_INDEX      2	/* first of the extra LDT entries */
+
+/* Privileges. */
+#define INTR_PRIVILEGE       0	/* kernel and interrupt handlers */
+#define TASK_PRIVILEGE       1	/* kernel tasks */
+#define USER_PRIVILEGE       3	/* servers and user processes */
+
+/* 286 hardware constants. */
+
+/* Exception vector numbers. */
+#define BOUNDS_VECTOR        5	/* bounds check failed */
+#define INVAL_OP_VECTOR      6	/* invalid opcode */
+#define COPROC_NOT_VECTOR    7	/* coprocessor not available */
+#define DOUBLE_FAULT_VECTOR  8
+#define COPROC_SEG_VECTOR    9	/* coprocessor segment overrun */
+#define INVAL_TSS_VECTOR    10	/* invalid TSS */
+#define SEG_NOT_VECTOR      11	/* segment not present */
+#define STACK_FAULT_VECTOR  12	/* stack exception */
+#define PROTECTION_VECTOR   13	/* general protection */
+
+/* Selector bits. */
+#define TI                0x04	/* table indicator */
+#define RPL               0x03	/* requester privilege level */
+
+/* Descriptor structure offsets. */
+#define DESC_BASE            2	/* to base_low */
+#define DESC_BASE_MIDDLE     4	/* to base_middle */
+#define DESC_ACCESS          5	/* to access byte */
+#define DESC_SIZE            8	/* sizeof (struct segdesc_s) */
+
+/* Base and limit sizes and shifts. */
+#define BASE_MIDDLE_SHIFT   16	/* shift for base --> base_middle */
+
+/* Access-byte and type-byte bits. */
+#define PRESENT           0x80	/* set for descriptor present */
+#define DPL               0x60	/* descriptor privilege level mask */
+#define DPL_SHIFT            5
+#define SEGMENT           0x10	/* set for segment-type descriptors */
+
+/* Access-byte bits. */
+#define EXECUTABLE        0x08	/* set for executable segment */
+#define CONFORMING        0x04	/* set for conforming segment if executable */
+#define EXPAND_DOWN       0x04	/* set for expand-down segment if !executable*/
+#define READABLE          0x02	/* set for readable segment if executable */
+#define WRITEABLE         0x02	/* set for writeable segment if !executable */
+#define TSS_BUSY          0x02	/* set if TSS descriptor is busy */
+#define ACCESSED          0x01	/* set if segment accessed */
+
+/* Special descriptor types. */
+#define AVL_286_TSS          1	/* available 286 TSS */
+#define LDT                  2	/* local descriptor table */
+#define BUSY_286_TSS         3	/* set transparently to the software */
+#define CALL_286_GATE        4	/* not used */
+#define TASK_GATE            5	/* only used by debugger */
+#define INT_286_GATE         6	/* interrupt gate, used for all vectors */
+#define TRAP_286_GATE        7	/* not used */
+
+/* Extra 386 hardware constants. */
+
+/* Exception vector numbers. */
+#define PAGE_FAULT_VECTOR   14
+#define COPROC_ERR_VECTOR   16	/* coprocessor error */
+
+/* Descriptor structure offsets. */
+#define DESC_GRANULARITY     6	/* to granularity byte */
+#define DESC_BASE_HIGH       7	/* to base_high */
+
+/* Base and limit sizes and shifts. */
+#define BASE_HIGH_SHIFT     24	/* shift for base --> base_high */
+#define BYTE_GRAN_MAX   0xFFFFFL   /* maximum size for byte granular segment */
+#define GRANULARITY_SHIFT   16	/* shift for limit --> granularity */
+#define OFFSET_HIGH_SHIFT   16	/* shift for (gate) offset --> offset_high */
+#define PAGE_GRAN_SHIFT     12	/* extra shift for page granular limits */
+
+/* Type-byte bits. */
+#define DESC_386_BIT  0x08 /* 386 types are obtained by ORing with this */
+				/* LDT's and TASK_GATE's don't need it */
+
+/* Granularity byte. */
+#define GRANULAR  	  0x80	/* set for 4K granularilty */
+#define DEFAULT   	  0x40	/* set for 32-bit defaults (executable seg) */
+#define BIG       	  0x40	/* set for "BIG" (expand-down seg) */
+#define AVL        	  0x10	/* 0 for available */
+#define LIMIT_HIGH   	  0x0F	/* mask for high bits of limit */
Index: /trunk/minix/kernel/proto.h
===================================================================
--- /trunk/minix/kernel/proto.h	(revision 9)
+++ /trunk/minix/kernel/proto.h	(revision 9)
@@ -0,0 +1,167 @@
+/* Function prototypes. */
+
+#ifndef PROTO_H
+#define PROTO_H
+
+/* Struct declarations. */
+struct proc;
+struct timer;
+
+/* clock.c */
+_PROTOTYPE( void clock_task, (void)					);
+_PROTOTYPE( void clock_stop, (void)					);
+_PROTOTYPE( clock_t get_uptime, (void)					);
+_PROTOTYPE( unsigned long read_clock, (void)				);
+_PROTOTYPE( void set_timer, (struct timer *tp, clock_t t, tmr_func_t f)	);
+_PROTOTYPE( void reset_timer, (struct timer *tp)			);
+
+/* main.c */
+_PROTOTYPE( void main, (void)						);
+_PROTOTYPE( void prepare_shutdown, (int how)				);
+
+/* utility.c */
+_PROTOTYPE( int kprintf, (const char *fmt, ...)				);
+_PROTOTYPE( void panic, (_CONST char *s, int n)				);
+
+/* proc.c */
+_PROTOTYPE( int sys_call, (int call_nr, int src_dst, 
+					message *m_ptr, long bit_map)	);
+_PROTOTYPE( int lock_notify, (int src, int dst)				);
+_PROTOTYPE( int lock_send, (int dst, message *m_ptr)			);
+_PROTOTYPE( void lock_enqueue, (struct proc *rp)			);
+_PROTOTYPE( void lock_dequeue, (struct proc *rp)			);
+_PROTOTYPE( void balance_queues, (struct timer *tp)			);
+#if DEBUG_ENABLE_IPC_WARNINGS
+_PROTOTYPE( int isokendpt_f, (char *file, int line, int e, int *p, int f));
+#define isokendpt_d(e, p, f) isokendpt_f(__FILE__, __LINE__, (e), (p), (f))
+#else
+_PROTOTYPE( int isokendpt_f, (int e, int *p, int f)			);
+#define isokendpt_d(e, p, f) isokendpt_f((e), (p), (f))
+#endif
+
+/* start.c */
+_PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mds,
+				U16_t parmoff, U16_t parmsize)		);
+
+/* system.c */
+_PROTOTYPE( int get_priv, (register struct proc *rc, int proc_type)	);
+_PROTOTYPE( void send_sig, (int proc_nr, int sig_nr)			);
+_PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr)			);
+_PROTOTYPE( void sys_task, (void)					);
+_PROTOTYPE( void get_randomness, (int source)				);
+_PROTOTYPE( int virtual_copy, (struct vir_addr *src, struct vir_addr *dst, 
+				vir_bytes bytes) 			);
+#define numap_local(proc_nr, vir_addr, bytes) \
+	umap_local(proc_addr(proc_nr), D, (vir_addr), (bytes))
+_PROTOTYPE( phys_bytes umap_local, (struct proc *rp, int seg, 
+		vir_bytes vir_addr, vir_bytes bytes)			);
+_PROTOTYPE( phys_bytes umap_remote, (struct proc *rp, int seg, 
+		vir_bytes vir_addr, vir_bytes bytes)			);
+_PROTOTYPE( phys_bytes umap_bios, (struct proc *rp, vir_bytes vir_addr,
+		vir_bytes bytes)					);
+_PROTOTYPE( void clear_endpoint, (struct proc *rc)			);
+
+#if (CHIP == INTEL)
+
+/* exception.c */
+_PROTOTYPE( void exception, (unsigned vec_nr)				);
+
+/* i8259.c */
+_PROTOTYPE( void intr_init, (int mine)					);
+_PROTOTYPE( void intr_handle, (irq_hook_t *hook)			);
+_PROTOTYPE( void put_irq_handler, (irq_hook_t *hook, int irq,
+						irq_handler_t handler)	);
+_PROTOTYPE( void rm_irq_handler, (irq_hook_t *hook)			);
+
+/* klib*.s */
+_PROTOTYPE( void int86, (void)						);
+_PROTOTYPE( void cp_mess, (int src,phys_clicks src_clicks,vir_bytes src_offset,
+		phys_clicks dst_clicks, vir_bytes dst_offset)		);
+_PROTOTYPE( void enable_irq, (irq_hook_t *hook)				);
+_PROTOTYPE( int disable_irq, (irq_hook_t *hook)				);
+_PROTOTYPE( u16_t mem_rdw, (U16_t segm, vir_bytes offset)		);
+_PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest,
+		phys_bytes count)					);
+_PROTOTYPE( void phys_memset, (phys_bytes source, unsigned long pattern,
+		phys_bytes count)					);
+_PROTOTYPE( void phys_insb, (U16_t port, phys_bytes buf, size_t count)	);
+_PROTOTYPE( void phys_insw, (U16_t port, phys_bytes buf, size_t count)	);
+_PROTOTYPE( void phys_outsb, (U16_t port, phys_bytes buf, size_t count)	);
+_PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count)	);
+_PROTOTYPE( void reset, (void)						);
+_PROTOTYPE( void level0, (void (*func)(void))				);
+_PROTOTYPE( void monitor, (void)					);
+_PROTOTYPE( void read_tsc, (unsigned long *high, unsigned long *low)	);
+_PROTOTYPE( unsigned long read_cr0, (void)				);
+_PROTOTYPE( void write_cr0, (unsigned long value)			);
+_PROTOTYPE( void write_cr3, (unsigned long value)			);
+_PROTOTYPE( unsigned long read_cpu_flags, (void)			);
+
+/* mpx*.s */
+_PROTOTYPE( void idle_task, (void)					);
+_PROTOTYPE( void restart, (void)					);
+
+/* The following are never called from C (pure asm procs). */
+
+/* Exception handlers (real or protected mode), in numerical order. */
+void _PROTOTYPE( int00, (void) ), _PROTOTYPE( divide_error, (void) );
+void _PROTOTYPE( int01, (void) ), _PROTOTYPE( single_step_exception, (void) );
+void _PROTOTYPE( int02, (void) ), _PROTOTYPE( nmi, (void) );
+void _PROTOTYPE( int03, (void) ), _PROTOTYPE( breakpoint_exception, (void) );
+void _PROTOTYPE( int04, (void) ), _PROTOTYPE( overflow, (void) );
+void _PROTOTYPE( int05, (void) ), _PROTOTYPE( bounds_check, (void) );
+void _PROTOTYPE( int06, (void) ), _PROTOTYPE( inval_opcode, (void) );
+void _PROTOTYPE( int07, (void) ), _PROTOTYPE( copr_not_available, (void) );
+void				  _PROTOTYPE( double_fault, (void) );
+void				  _PROTOTYPE( copr_seg_overrun, (void) );
+void				  _PROTOTYPE( inval_tss, (void) );
+void				  _PROTOTYPE( segment_not_present, (void) );
+void				  _PROTOTYPE( stack_exception, (void) );
+void				  _PROTOTYPE( general_protection, (void) );
+void				  _PROTOTYPE( page_fault, (void) );
+void				  _PROTOTYPE( copr_error, (void) );
+
+/* Hardware interrupt handlers. */
+_PROTOTYPE( void hwint00, (void) );
+_PROTOTYPE( void hwint01, (void) );
+_PROTOTYPE( void hwint02, (void) );
+_PROTOTYPE( void hwint03, (void) );
+_PROTOTYPE( void hwint04, (void) );
+_PROTOTYPE( void hwint05, (void) );
+_PROTOTYPE( void hwint06, (void) );
+_PROTOTYPE( void hwint07, (void) );
+_PROTOTYPE( void hwint08, (void) );
+_PROTOTYPE( void hwint09, (void) );
+_PROTOTYPE( void hwint10, (void) );
+_PROTOTYPE( void hwint11, (void) );
+_PROTOTYPE( void hwint12, (void) );
+_PROTOTYPE( void hwint13, (void) );
+_PROTOTYPE( void hwint14, (void) );
+_PROTOTYPE( void hwint15, (void) );
+
+/* Software interrupt handlers, in numerical order. */
+_PROTOTYPE( void trp, (void) );
+_PROTOTYPE( void s_call, (void) ), _PROTOTYPE( p_s_call, (void) );
+_PROTOTYPE( void level0_call, (void) );
+
+/* protect.c */
+_PROTOTYPE( void prot_init, (void)					);
+_PROTOTYPE( void init_codeseg, (struct segdesc_s *segdp, phys_bytes base,
+		vir_bytes size, int privilege)				);
+_PROTOTYPE( void init_dataseg, (struct segdesc_s *segdp, phys_bytes base,
+		vir_bytes size, int privilege)				);
+_PROTOTYPE( phys_bytes seg2phys, (U16_t seg)				);
+_PROTOTYPE( void phys2seg, (u16_t *seg, vir_bytes *off, phys_bytes phys));
+_PROTOTYPE( void enable_iop, (struct proc *pp)				);
+_PROTOTYPE( void alloc_segments, (struct proc *rp)			);
+
+/* system/do_vm.c */
+_PROTOTYPE( void vm_map_default, (struct proc *pp)			);
+
+#endif /* (CHIP == INTEL) */
+
+#if (CHIP == M68000)
+/* M68000 specific prototypes go here. */
+#endif /* (CHIP == M68000) */
+
+#endif /* PROTO_H */
Index: /trunk/minix/kernel/sconst.h
===================================================================
--- /trunk/minix/kernel/sconst.h	(revision 9)
+++ /trunk/minix/kernel/sconst.h	(revision 9)
@@ -0,0 +1,36 @@
+! Miscellaneous constants used in assembler code.
+W		=	_WORD_SIZE	! Machine word size.
+
+! Offsets in struct proc. They MUST match proc.h.
+P_STACKBASE	=	0
+#if _WORD_SIZE == 2
+ESREG		=	P_STACKBASE
+#else
+GSREG		=	P_STACKBASE
+FSREG		=	GSREG + 2	! 386 introduces FS and GS segments
+ESREG		=	FSREG + 2
+#endif
+DSREG		=	ESREG + 2
+DIREG		=	DSREG + 2
+SIREG		=	DIREG + W
+BPREG		=	SIREG + W
+STREG		=	BPREG + W	! hole for another SP
+BXREG		=	STREG + W
+DXREG		=	BXREG + W
+CXREG		=	DXREG + W
+AXREG		=	CXREG + W
+RETADR		=	AXREG + W	! return address for save() call
+PCREG		=	RETADR + W
+CSREG		=	PCREG + W
+PSWREG		=	CSREG + W
+SPREG		=	PSWREG + W
+SSREG		=	SPREG + W
+P_STACKTOP	=	SSREG + W
+P_LDT_SEL	=	P_STACKTOP
+P_LDT		=	P_LDT_SEL + W
+
+#if _WORD_SIZE == 2
+Msize		=	12		! size of a message in 16-bit words
+#else
+Msize		=	9		! size of a message in 32-bit words
+#endif
Index: /trunk/minix/kernel/start.c
===================================================================
--- /trunk/minix/kernel/start.c	(revision 9)
+++ /trunk/minix/kernel/start.c	(revision 9)
@@ -0,0 +1,122 @@
+/* This file contains the C startup code for Minix on Intel processors.
+ * It cooperates with mpx.s to set up a good environment for main().
+ *
+ * This code runs in real mode for a 16 bit kernel and may have to switch
+ * to protected mode for a 286.
+ * For a 32 bit kernel this already runs in protected mode, but the selectors
+ * are still those given by the BIOS with interrupts disabled, so the
+ * descriptors need to be reloaded and interrupt descriptors made.
+ */
+
+#include "kernel.h"
+#include "protect.h"
+#include "proc.h"
+#include <stdlib.h>
+#include <string.h>
+
+FORWARD _PROTOTYPE( char *get_value, (_CONST char *params, _CONST char *key));
+/*===========================================================================*
+ *				cstart					     *
+ *===========================================================================*/
+PUBLIC void cstart(cs, ds, mds, parmoff, parmsize)
+U16_t cs, ds;			/* kernel code and data segment */
+U16_t mds;			/* monitor data segment */
+U16_t parmoff, parmsize;	/* boot parameters offset and length */
+{
+/* Perform system initializations prior to calling main(). Most settings are
+ * determined with help of the environment strings passed by MINIX' loader.
+ */
+  char params[128*sizeof(char *)];		/* boot monitor parameters */
+  register char *value;				/* value in key=value pair */
+  extern int etext, end;
+  int h;
+
+  /* Decide if mode is protected; 386 or higher implies protected mode.
+   * This must be done first, because it is needed for, e.g., seg2phys().
+   * For 286 machines we cannot decide on protected mode, yet. This is 
+   * done below. 
+   */
+#if _WORD_SIZE != 2
+  machine.prot = 1;	
+#endif
+
+  /* Record where the kernel and the monitor are. */
+  kinfo.code_base = seg2phys(cs);
+  kinfo.code_size = (phys_bytes) &etext;	/* size of code segment */
+  kinfo.data_base = seg2phys(ds);
+  kinfo.data_size = (phys_bytes) &end;		/* size of data segment */
+
+  /* Initialize protected mode descriptors. */
+  prot_init();
+
+  /* Copy the boot parameters to the local buffer. */
+  kinfo.params_base = seg2phys(mds) + parmoff;
+  kinfo.params_size = MIN(parmsize,sizeof(params)-2);
+  phys_copy(kinfo.params_base, vir2phys(params), kinfo.params_size);
+
+  /* Record miscellaneous information for user-space servers. */
+  kinfo.nr_procs = NR_PROCS;
+  kinfo.nr_tasks = NR_TASKS;
+  strncpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release));
+  kinfo.release[sizeof(kinfo.release)-1] = '\0';
+  strncpy(kinfo.version, OS_VERSION, sizeof(kinfo.version));
+  kinfo.version[sizeof(kinfo.version)-1] = '\0';
+  kinfo.proc_addr = (vir_bytes) proc;
+  kinfo.kmem_base = vir2phys(0);
+  kinfo.kmem_size = (phys_bytes) &end;	
+
+  /* Load average data initialization. */
+  kloadinfo.proc_last_slot = 0;
+  for(h = 0; h < _LOAD_HISTORY; h++)
+	kloadinfo.proc_load_history[h] = 0;
+
+  /* Processor?  86, 186, 286, 386, ... 
+   * Decide if mode is protected for older machines. 
+   */
+  machine.processor=atoi(get_value(params, "processor")); 
+#if _WORD_SIZE == 2
+  machine.prot = machine.processor >= 286;		
+#endif
+  if (! machine.prot) mon_return = 0;
+
+  /* XT, AT or MCA bus? */
+  value = get_value(params, "bus");
+  if (value == NIL_PTR || strcmp(value, "at") == 0) {
+      machine.pc_at = TRUE;			/* PC-AT compatible hardware */
+  } else if (strcmp(value, "mca") == 0) {
+      machine.pc_at = machine.ps_mca = TRUE;	/* PS/2 with micro channel */
+  }
+
+  /* Type of VDU: */
+  value = get_value(params, "video");		/* EGA or VGA video unit */
+  if (strcmp(value, "ega") == 0) machine.vdu_ega = TRUE;
+  if (strcmp(value, "vga") == 0) machine.vdu_vga = machine.vdu_ega = TRUE;
+
+  /* Return to assembler code to switch to protected mode (if 286), 
+   * reload selectors and call main().
+   */
+}
+
+/*===========================================================================*
+ *				get_value				     *
+ *===========================================================================*/
+
+PRIVATE char *get_value(params, name)
+_CONST char *params;				/* boot monitor parameters */
+_CONST char *name;				/* key to look up */
+{
+/* Get environment value - kernel version of getenv to avoid setting up the
+ * usual environment array.
+ */
+  register _CONST char *namep;
+  register char *envp;
+
+  for (envp = (char *) params; *envp != 0;) {
+	for (namep = name; *namep != 0 && *namep == *envp; namep++, envp++)
+		;
+	if (*namep == '\0' && *envp == '=') return(envp + 1);
+	while (*envp++ != 0)
+		;
+  }
+  return(NIL_PTR);
+}
Index: /trunk/minix/kernel/system.c
===================================================================
--- /trunk/minix/kernel/system.c	(revision 9)
+++ /trunk/minix/kernel/system.c	(revision 9)
@@ -0,0 +1,547 @@
+/* This task handles the interface between the kernel and user-level servers.
+ * System services can be accessed by doing a system call. System calls are 
+ * transformed into request messages, which are handled by this task. By 
+ * convention, a sys_call() is transformed in a SYS_CALL request message that
+ * is handled in a function named do_call(). 
+ *
+ * A private call vector is used to map all system calls to the functions that
+ * handle them. The actual handler functions are contained in separate files
+ * to keep this file clean. The call vector is used in the system task's main
+ * loop to handle all incoming requests.  
+ *
+ * In addition to the main sys_task() entry point, which starts the main loop,
+ * there are several other minor entry points:
+ *   get_priv:		assign privilege structure to user or system process
+ *   send_sig:		send a signal directly to a system process
+ *   cause_sig:		take action to cause a signal to occur via PM
+ *   umap_local:	map virtual address in LOCAL_SEG to physical 
+ *   umap_remote:	map virtual address in REMOTE_SEG to physical 
+ *   umap_bios:		map virtual address in BIOS_SEG to physical 
+ *   virtual_copy:	copy bytes from one virtual address to another 
+ *   get_randomness:	accumulate randomness in a buffer
+ *   clear_endpoint:	remove a process' ability to send and receive messages
+ *
+ * Changes:
+ *   Aug 04, 2005   check if system call is allowed  (Jorrit N. Herder)
+ *   Jul 20, 2005   send signal to services with message  (Jorrit N. Herder) 
+ *   Jan 15, 2005   new, generalized virtual copy function  (Jorrit N. Herder)
+ *   Oct 10, 2004   dispatch system calls from call vector  (Jorrit N. Herder)
+ *   Sep 30, 2004   source code documentation updated  (Jorrit N. Herder)
+ */
+
+#include "debug.h"
+#include "kernel.h"
+#include "system.h"
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/sigcontext.h>
+#include <minix/endpoint.h>
+#if (CHIP == INTEL)
+#include <ibm/memory.h>
+#include "protect.h"
+#endif
+
+/* Declaration of the call vector that defines the mapping of system calls 
+ * to handler functions. The vector is initialized in sys_init() with map(), 
+ * which makes sure the system call numbers are ok. No space is allocated, 
+ * because the dummy is declared extern. If an illegal call is given, the 
+ * array size will be negative and this won't compile. 
+ */
+PUBLIC int (*call_vec[NR_SYS_CALLS])(message *m_ptr);
+
+#define map(call_nr, handler) \
+    {extern int dummy[NR_SYS_CALLS>(unsigned)(call_nr-KERNEL_CALL) ? 1:-1];} \
+    call_vec[(call_nr-KERNEL_CALL)] = (handler)  
+
+FORWARD _PROTOTYPE( void initialize, (void));
+
+/*===========================================================================*
+ *				sys_task				     *
+ *===========================================================================*/
+PUBLIC void sys_task()
+{
+/* Main entry point of sys_task.  Get the message and dispatch on type. */
+  static message m;
+  register int result;
+  register struct proc *caller_ptr;
+  unsigned int call_nr;
+  int s;
+
+  /* Initialize the system task. */
+  initialize();
+
+  while (TRUE) {
+      /* Get work. Block and wait until a request message arrives. */
+      receive(ANY, &m);			
+      call_nr = (unsigned) m.m_type - KERNEL_CALL;	
+      who_e = m.m_source;
+      okendpt(who_e, &who_p);
+      caller_ptr = proc_addr(who_p);
+
+      /* See if the caller made a valid request and try to handle it. */
+      if (! (priv(caller_ptr)->s_call_mask & (1<<call_nr))) {
+#if DEBUG_ENABLE_IPC_WARNINGS
+	  kprintf("SYSTEM: request %d from %d denied.\n", call_nr,m.m_source);
+#endif
+	  result = ECALLDENIED;			/* illegal message type */
+      } else if (call_nr >= NR_SYS_CALLS) {		/* check call number */
+#if DEBUG_ENABLE_IPC_WARNINGS
+	  kprintf("SYSTEM: illegal request %d from %d.\n", call_nr,m.m_source);
+#endif
+	  result = EBADREQUEST;			/* illegal message type */
+      } 
+      else {
+          result = (*call_vec[call_nr])(&m);	/* handle the system call */
+      }
+
+      /* Send a reply, unless inhibited by a handler function. Use the kernel
+       * function lock_send() to prevent a system call trap. The destination
+       * is known to be blocked waiting for a message.
+       */
+      if (result != EDONTREPLY) {
+  	  m.m_type = result;			/* report status of call */
+          if (OK != (s=lock_send(m.m_source, &m))) {
+              kprintf("SYSTEM, reply to %d failed: %d\n", m.m_source, s);
+          }
+      }
+  }
+}
+
+/*===========================================================================*
+ *				initialize				     *
+ *===========================================================================*/
+PRIVATE void initialize(void)
+{
+  register struct priv *sp;
+  int i;
+
+  /* Initialize IRQ handler hooks. Mark all hooks available. */
+  for (i=0; i<NR_IRQ_HOOKS; i++) {
+      irq_hooks[i].proc_nr_e = NONE;
+  }
+
+  /* Initialize all alarm timers for all processes. */
+  for (sp=BEG_PRIV_ADDR; sp < END_PRIV_ADDR; sp++) {
+    tmr_inittimer(&(sp->s_alarm_timer));
+  }
+
+  /* Initialize the call vector to a safe default handler. Some system calls 
+   * may be disabled or nonexistant. Then explicitely map known calls to their
+   * handler functions. This is done with a macro that gives a compile error
+   * if an illegal call number is used. The ordering is not important here.
+   */
+  for (i=0; i<NR_SYS_CALLS; i++) {
+      call_vec[i] = do_unused;
+  }
+
+  /* Process management. */
+  map(SYS_FORK, do_fork); 		/* a process forked a new process */
+  map(SYS_EXEC, do_exec);		/* update process after execute */
+  map(SYS_EXIT, do_exit);		/* clean up after process exit */
+  map(SYS_NICE, do_nice);		/* set scheduling priority */
+  map(SYS_PRIVCTL, do_privctl);		/* system privileges control */
+  map(SYS_TRACE, do_trace);		/* request a trace operation */
+
+  /* Signal handling. */
+  map(SYS_KILL, do_kill); 		/* cause a process to be signaled */
+  map(SYS_GETKSIG, do_getksig);		/* PM checks for pending signals */
+  map(SYS_ENDKSIG, do_endksig);		/* PM finished processing signal */
+  map(SYS_SIGSEND, do_sigsend);		/* start POSIX-style signal */
+  map(SYS_SIGRETURN, do_sigreturn);	/* return from POSIX-style signal */
+
+  /* Device I/O. */
+  map(SYS_IRQCTL, do_irqctl);  		/* interrupt control operations */ 
+  map(SYS_DEVIO, do_devio);   		/* inb, inw, inl, outb, outw, outl */ 
+  map(SYS_SDEVIO, do_sdevio);		/* phys_insb, _insw, _outsb, _outsw */
+  map(SYS_VDEVIO, do_vdevio);  		/* vector with devio requests */ 
+  map(SYS_INT86, do_int86);  		/* real-mode BIOS calls */ 
+
+  /* Memory management. */
+  map(SYS_NEWMAP, do_newmap);		/* set up a process memory map */
+  map(SYS_SEGCTL, do_segctl);		/* add segment and get selector */
+  map(SYS_MEMSET, do_memset);		/* write char to memory area */
+  map(SYS_VM_SETBUF, do_vm_setbuf); 	/* PM passes buffer for page tables */
+  map(SYS_VM_MAP, do_vm_map); 		/* Map/unmap physical (device) memory */
+
+  /* Copying. */
+  map(SYS_UMAP, do_umap);		/* map virtual to physical address */
+  map(SYS_VIRCOPY, do_vircopy); 	/* use pure virtual addressing */
+  map(SYS_PHYSCOPY, do_physcopy); 	/* use physical addressing */
+  map(SYS_VIRVCOPY, do_virvcopy);	/* vector with copy requests */
+  map(SYS_PHYSVCOPY, do_physvcopy);	/* vector with copy requests */
+
+  /* Clock functionality. */
+  map(SYS_TIMES, do_times);		/* get uptime and process times */
+  map(SYS_SETALARM, do_setalarm);	/* schedule a synchronous alarm */
+
+  /* System control. */
+  map(SYS_ABORT, do_abort);		/* abort MINIX */
+  map(SYS_GETINFO, do_getinfo); 	/* request system information */ 
+  map(SYS_IOPENABLE, do_iopenable); 	/* Enable I/O */
+}
+
+/*===========================================================================*
+ *				get_priv				     *
+ *===========================================================================*/
+PUBLIC int get_priv(rc, proc_type)
+register struct proc *rc;		/* new (child) process pointer */
+int proc_type;				/* system or user process flag */
+{
+/* Get a privilege structure. All user processes share the same privilege 
+ * structure. System processes get their own privilege structure. 
+ */
+  register struct priv *sp;			/* privilege structure */
+
+  if (proc_type == SYS_PROC) {			/* find a new slot */
+      for (sp = BEG_PRIV_ADDR; sp < END_PRIV_ADDR; ++sp) 
+          if (sp->s_proc_nr == NONE && sp->s_id != USER_PRIV_ID) break;	
+      if (sp->s_proc_nr != NONE) return(ENOSPC);
+      rc->p_priv = sp;				/* assign new slot */
+      rc->p_priv->s_proc_nr = proc_nr(rc);	/* set association */
+      rc->p_priv->s_flags = SYS_PROC;		/* mark as privileged */
+  } else {
+      rc->p_priv = &priv[USER_PRIV_ID];		/* use shared slot */
+      rc->p_priv->s_proc_nr = INIT_PROC_NR;	/* set association */
+      rc->p_priv->s_flags = 0;			/* no initial flags */
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *				get_randomness				     *
+ *===========================================================================*/
+PUBLIC void get_randomness(source)
+int source;
+{
+/* On machines with the RDTSC (cycle counter read instruction - pentium
+ * and up), use that for high-resolution raw entropy gathering. Otherwise,
+ * use the realtime clock (tick resolution).
+ *
+ * Unfortunately this test is run-time - we don't want to bother with
+ * compiling different kernels for different machines.
+ *
+ * On machines without RDTSC, we use read_clock().
+ */
+  int r_next;
+  unsigned long tsc_high, tsc_low;
+
+  source %= RANDOM_SOURCES;
+  r_next= krandom.bin[source].r_next;
+  if (machine.processor > 486) {
+      read_tsc(&tsc_high, &tsc_low);
+      krandom.bin[source].r_buf[r_next] = tsc_low;
+  } else {
+      krandom.bin[source].r_buf[r_next] = read_clock();
+  }
+  if (krandom.bin[source].r_size < RANDOM_ELEMENTS) {
+  	krandom.bin[source].r_size ++;
+  }
+  krandom.bin[source].r_next = (r_next + 1 ) % RANDOM_ELEMENTS;
+}
+
+/*===========================================================================*
+ *				send_sig				     *
+ *===========================================================================*/
+PUBLIC void send_sig(int proc_nr, int sig_nr)
+{
+/* Notify a system process about a signal. This is straightforward. Simply
+ * set the signal that is to be delivered in the pending signals map and 
+ * send a notification with source SYSTEM.
+ *
+ * Process number is verified to avoid writing in random places, but we
+ * don't kprintf() or panic() because that causes send_sig() invocations.
+ */ 
+  register struct proc *rp;
+  static int n;
+
+  if(!isokprocn(proc_nr) || isemptyn(proc_nr))
+	return;
+
+  rp = proc_addr(proc_nr);
+  sigaddset(&priv(rp)->s_sig_pending, sig_nr);
+  lock_notify(SYSTEM, rp->p_endpoint); 
+}
+
+/*===========================================================================*
+ *				cause_sig				     *
+ *===========================================================================*/
+PUBLIC void cause_sig(proc_nr, sig_nr)
+int proc_nr;			/* process to be signalled */
+int sig_nr;			/* signal to be sent, 1 to _NSIG */
+{
+/* A system process wants to send a signal to a process.  Examples are:
+ *  - HARDWARE wanting to cause a SIGSEGV after a CPU exception
+ *  - TTY wanting to cause SIGINT upon getting a DEL
+ *  - FS wanting to cause SIGPIPE for a broken pipe 
+ * Signals are handled by sending a message to PM.  This function handles the 
+ * signals and makes sure the PM gets them by sending a notification. The 
+ * process being signaled is blocked while PM has not finished all signals 
+ * for it. 
+ * Race conditions between calls to this function and the system calls that
+ * process pending kernel signals cannot exist. Signal related functions are
+ * only called when a user process causes a CPU exception and from the kernel 
+ * process level, which runs to completion.
+ */
+  register struct proc *rp;
+
+  /* Check if the signal is already pending. Process it otherwise. */
+  rp = proc_addr(proc_nr);
+  if (! sigismember(&rp->p_pending, sig_nr)) {
+      sigaddset(&rp->p_pending, sig_nr);
+      if (! (rp->p_rts_flags & SIGNALED)) {		/* other pending */
+          if (rp->p_rts_flags == 0) lock_dequeue(rp);	/* make not ready */
+          rp->p_rts_flags |= SIGNALED | SIG_PENDING;	/* update flags */
+          send_sig(PM_PROC_NR, SIGKSIG);
+      }
+  }
+}
+
+/*===========================================================================*
+ *				umap_bios				     *
+ *===========================================================================*/
+PUBLIC phys_bytes umap_bios(rp, vir_addr, bytes)
+register struct proc *rp;	/* pointer to proc table entry for process */
+vir_bytes vir_addr;		/* virtual address in BIOS segment */
+vir_bytes bytes;		/* # of bytes to be copied */
+{
+/* Calculate the physical memory address at the BIOS. Note: currently, BIOS
+ * address zero (the first BIOS interrupt vector) is not considered, as an 
+ * error here, but since the physical address will be zero as well, the 
+ * calling function will think an error occurred. This is not a problem,
+ * since no one uses the first BIOS interrupt vector.  
+ */
+
+  /* Check all acceptable ranges. */
+  if (vir_addr >= BIOS_MEM_BEGIN && vir_addr + bytes <= BIOS_MEM_END)
+  	return (phys_bytes) vir_addr;
+  else if (vir_addr >= BASE_MEM_TOP && vir_addr + bytes <= UPPER_MEM_END)
+  	return (phys_bytes) vir_addr;
+
+#if DEAD_CODE	/* brutal fix, if the above is too restrictive */
+  if (vir_addr >= BIOS_MEM_BEGIN && vir_addr + bytes <= UPPER_MEM_END)
+  	return (phys_bytes) vir_addr;
+#endif
+
+  kprintf("Warning, error in umap_bios, virtual address 0x%x\n", vir_addr);
+  return 0;
+}
+
+/*===========================================================================*
+ *				umap_local				     *
+ *===========================================================================*/
+PUBLIC phys_bytes umap_local(rp, seg, vir_addr, bytes)
+register struct proc *rp;	/* pointer to proc table entry for process */
+int seg;			/* T, D, or S segment */
+vir_bytes vir_addr;		/* virtual address in bytes within the seg */
+vir_bytes bytes;		/* # of bytes to be copied */
+{
+/* Calculate the physical memory address for a given virtual address. */
+  vir_clicks vc;		/* the virtual address in clicks */
+  phys_bytes pa;		/* intermediate variables as phys_bytes */
+#if (CHIP == INTEL)
+  phys_bytes seg_base;
+#endif
+
+  /* If 'seg' is D it could really be S and vice versa.  T really means T.
+   * If the virtual address falls in the gap,  it causes a problem. On the
+   * 8088 it is probably a legal stack reference, since "stackfaults" are
+   * not detected by the hardware.  On 8088s, the gap is called S and
+   * accepted, but on other machines it is called D and rejected.
+   * The Atari ST behaves like the 8088 in this respect.
+   */
+
+  if (bytes <= 0) return( (phys_bytes) 0);
+  if (vir_addr + bytes <= vir_addr) return 0;	/* overflow */
+  vc = (vir_addr + bytes - 1) >> CLICK_SHIFT;	/* last click of data */
+
+#if (CHIP == INTEL) || (CHIP == M68000)
+  if (seg != T)
+	seg = (vc < rp->p_memmap[D].mem_vir + rp->p_memmap[D].mem_len ? D : S);
+#else
+  if (seg != T)
+	seg = (vc < rp->p_memmap[S].mem_vir ? D : S);
+#endif
+
+  if ((vir_addr>>CLICK_SHIFT) >= rp->p_memmap[seg].mem_vir + 
+  	rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 );
+
+  if (vc >= rp->p_memmap[seg].mem_vir + 
+  	rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 );
+
+#if (CHIP == INTEL)
+  seg_base = (phys_bytes) rp->p_memmap[seg].mem_phys;
+  seg_base = seg_base << CLICK_SHIFT;	/* segment origin in bytes */
+#endif
+  pa = (phys_bytes) vir_addr;
+#if (CHIP != M68000)
+  pa -= rp->p_memmap[seg].mem_vir << CLICK_SHIFT;
+  return(seg_base + pa);
+#endif
+#if (CHIP == M68000)
+  pa -= (phys_bytes)rp->p_memmap[seg].mem_vir << CLICK_SHIFT;
+  pa += (phys_bytes)rp->p_memmap[seg].mem_phys << CLICK_SHIFT;
+  return(pa);
+#endif
+}
+
+/*===========================================================================*
+ *				umap_remote				     *
+ *===========================================================================*/
+PUBLIC phys_bytes umap_remote(rp, seg, vir_addr, bytes)
+register struct proc *rp;	/* pointer to proc table entry for process */
+int seg;			/* index of remote segment */
+vir_bytes vir_addr;		/* virtual address in bytes within the seg */
+vir_bytes bytes;		/* # of bytes to be copied */
+{
+/* Calculate the physical memory address for a given virtual address. */
+  struct far_mem *fm;
+
+  if (bytes <= 0) return( (phys_bytes) 0);
+  if (seg < 0 || seg >= NR_REMOTE_SEGS) return( (phys_bytes) 0);
+
+  fm = &rp->p_priv->s_farmem[seg];
+  if (! fm->in_use) return( (phys_bytes) 0);
+  if (vir_addr + bytes > fm->mem_len) return( (phys_bytes) 0);
+
+  return(fm->mem_phys + (phys_bytes) vir_addr); 
+}
+
+/*===========================================================================*
+ *				virtual_copy				     *
+ *===========================================================================*/
+PUBLIC int virtual_copy(src_addr, dst_addr, bytes)
+struct vir_addr *src_addr;	/* source virtual address */
+struct vir_addr *dst_addr;	/* destination virtual address */
+vir_bytes bytes;		/* # of bytes to copy  */
+{
+/* Copy bytes from virtual address src_addr to virtual address dst_addr. 
+ * Virtual addresses can be in ABS, LOCAL_SEG, REMOTE_SEG, or BIOS_SEG.
+ */
+  struct vir_addr *vir_addr[2];	/* virtual source and destination address */
+  phys_bytes phys_addr[2];	/* absolute source and destination */ 
+  int seg_index;
+  int i;
+
+  /* Check copy count. */
+  if (bytes <= 0) return(EDOM);
+
+  /* Do some more checks and map virtual addresses to physical addresses. */
+  vir_addr[_SRC_] = src_addr;
+  vir_addr[_DST_] = dst_addr;
+  for (i=_SRC_; i<=_DST_; i++) {
+	int proc_nr, type;
+	struct proc *p;
+
+ 	type = vir_addr[i]->segment & SEGMENT_TYPE;
+	if(type != PHYS_SEG && isokendpt(vir_addr[i]->proc_nr_e, &proc_nr))
+	   p = proc_addr(proc_nr);
+	else
+	   p = NULL;
+
+      /* Get physical address. */
+      switch(type) {
+      case LOCAL_SEG:
+	  if(!p) return EDEADSRCDST;
+          seg_index = vir_addr[i]->segment & SEGMENT_INDEX;
+          phys_addr[i] = umap_local(p, seg_index, vir_addr[i]->offset, bytes);
+          break;
+      case REMOTE_SEG:
+	  if(!p) return EDEADSRCDST;
+          seg_index = vir_addr[i]->segment & SEGMENT_INDEX;
+          phys_addr[i] = umap_remote(p, seg_index, vir_addr[i]->offset, bytes);
+          break;
+      case BIOS_SEG:
+	  if(!p) return EDEADSRCDST;
+          phys_addr[i] = umap_bios(p, vir_addr[i]->offset, bytes );
+          break;
+      case PHYS_SEG:
+          phys_addr[i] = vir_addr[i]->offset;
+          break;
+      default:
+          return(EINVAL);
+      }
+
+      /* Check if mapping succeeded. */
+      if (phys_addr[i] <= 0 && vir_addr[i]->segment != PHYS_SEG) 
+          return(EFAULT);
+  }
+
+  /* Now copy bytes between physical addresseses. */
+  phys_copy(phys_addr[_SRC_], phys_addr[_DST_], (phys_bytes) bytes);
+  return(OK);
+}
+
+
+/*===========================================================================*
+ *			         clear_endpoint				     *
+ *===========================================================================*/
+PUBLIC void clear_endpoint(rc)
+register struct proc *rc;		/* slot of process to clean up */
+{
+  register struct proc *rp;		/* iterate over process table */
+  register struct proc **xpp;		/* iterate over caller queue */
+  int i;
+  int sys_id;
+
+  if(isemptyp(rc)) panic("clear_proc: empty process", proc_nr(rc));
+
+  /* Make sure that the exiting process is no longer scheduled. */
+  if (rc->p_rts_flags == 0) lock_dequeue(rc);
+  rc->p_rts_flags |= NO_ENDPOINT;
+
+  /* If the process happens to be queued trying to send a
+   * message, then it must be removed from the message queues.
+   */
+  if (rc->p_rts_flags & SENDING) {
+      int target_proc;
+
+      okendpt(rc->p_sendto_e, &target_proc);
+      xpp = &proc_addr(target_proc)->p_caller_q; /* destination's queue */
+      while (*xpp != NIL_PROC) {		/* check entire queue */
+          if (*xpp == rc) {			/* process is on the queue */
+              *xpp = (*xpp)->p_q_link;		/* replace by next process */
+#if DEBUG_ENABLE_IPC_WARNINGS
+	      kprintf("Proc %d removed from queue at %d\n",
+	          proc_nr(rc), rc->p_sendto_e);
+#endif
+              break;				/* can only be queued once */
+          }
+          xpp = &(*xpp)->p_q_link;		/* proceed to next queued */
+      }
+      rc->p_rts_flags &= ~SENDING;
+  }
+  rc->p_rts_flags &= ~RECEIVING;
+
+  /* Likewise, if another process was sending or receive a message to or from 
+   * the exiting process, it must be alerted that process no longer is alive.
+   * Check all processes. 
+   */
+  for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
+      if(isemptyp(rp))
+	continue;
+
+      /* Unset pending notification bits. */
+      unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id);
+
+      /* Check if process is receiving from exiting process. */
+      if ((rp->p_rts_flags & RECEIVING) && rp->p_getfrom_e == rc->p_endpoint) {
+          rp->p_reg.retreg = ESRCDIED;		/* report source died */
+	  rp->p_rts_flags &= ~RECEIVING;	/* no longer receiving */
+#if DEBUG_ENABLE_IPC_WARNINGS
+	  kprintf("Proc %d receive dead src %d\n", proc_nr(rp), proc_nr(rc));
+#endif
+  	  if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */
+      } 
+      if ((rp->p_rts_flags & SENDING) && rp->p_sendto_e == rc->p_endpoint) {
+          rp->p_reg.retreg = EDSTDIED;		/* report destination died */
+	  rp->p_rts_flags &= ~SENDING;		/* no longer sending */
+#if DEBUG_ENABLE_IPC_WARNINGS
+	  kprintf("Proc %d send dead dst %d\n", proc_nr(rp), proc_nr(rc));
+#endif
+  	  if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */
+      } 
+  }
+}
+
+
Index: /trunk/minix/kernel/system.h
===================================================================
--- /trunk/minix/kernel/system.h	(revision 9)
+++ /trunk/minix/kernel/system.h	(revision 9)
@@ -0,0 +1,179 @@
+/* Function prototypes for the system library.  The prototypes in this file 
+ * are undefined to do_unused if the kernel call is not enabled in config.h. 
+ * The implementation is contained in src/kernel/system/.  
+ *
+ * The system library allows to access system services by doing a kernel call.
+ * System calls are transformed into request messages to the SYS task that is 
+ * responsible for handling the call. By convention, sys_call() is transformed 
+ * into a message with type SYS_CALL that is handled in a function do_call(). 
+ * 
+ * Changes:
+ *   Jul 30, 2005   created SYS_INT86 to support BIOS driver  (Philip Homburg) 
+ *   Jul 13, 2005   created SYS_PRIVCTL to manage services  (Jorrit N. Herder) 
+ *   Jul 09, 2005   updated SYS_KILL to signal services  (Jorrit N. Herder) 
+ *   Jun 21, 2005   created SYS_NICE for nice(2) kernel call  (Ben J. Gras)
+ *   Jun 21, 2005   created SYS_MEMSET to speed up exec(2)  (Ben J. Gras)
+ *   Apr 12, 2005   updated SYS_VCOPY for virtual_copy()  (Jorrit N. Herder)
+ *   Jan 20, 2005   updated SYS_COPY for virtual_copy()  (Jorrit N. Herder)
+ *   Oct 24, 2004   created SYS_GETKSIG to support PM  (Jorrit N. Herder) 
+ *   Oct 10, 2004   created handler for unused calls  (Jorrit N. Herder) 
+ *   Sep 09, 2004   updated SYS_EXIT to let services exit  (Jorrit N. Herder) 
+ *   Aug 25, 2004   rewrote SYS_SETALARM to clean up code  (Jorrit N. Herder)
+ *   Jul 13, 2004   created SYS_SEGCTL to support drivers  (Jorrit N. Herder) 
+ *   May 24, 2004   created SYS_SDEVIO to support drivers  (Jorrit N. Herder) 
+ *   May 24, 2004   created SYS_GETINFO to retrieve info  (Jorrit N. Herder) 
+ *   Apr 18, 2004   created SYS_VDEVIO to support drivers  (Jorrit N. Herder) 
+ *   Feb 24, 2004   created SYS_IRQCTL to support drivers  (Jorrit N. Herder) 
+ *   Feb 02, 2004   created SYS_DEVIO to support drivers  (Jorrit N. Herder) 
+ */ 
+
+#ifndef SYSTEM_H
+#define SYSTEM_H
+
+/* Common includes for the system library. */
+#include "debug.h"
+#include "kernel.h"
+#include "proto.h"
+#include "proc.h"
+
+/* Default handler for unused kernel calls. */
+_PROTOTYPE( int do_unused, (message *m_ptr) );
+
+_PROTOTYPE( int do_exec, (message *m_ptr) );		
+#if ! USE_EXEC
+#define do_exec do_unused
+#endif
+
+_PROTOTYPE( int do_fork, (message *m_ptr) );
+#if ! USE_FORK
+#define do_fork do_unused
+#endif
+
+_PROTOTYPE( int do_newmap, (message *m_ptr) );
+#if ! USE_NEWMAP
+#define do_newmap do_unused
+#endif
+
+_PROTOTYPE( int do_exit, (message *m_ptr) );
+#if ! USE_EXIT
+#define do_exit do_unused
+#endif
+
+_PROTOTYPE( int do_trace, (message *m_ptr) );	
+#if ! USE_TRACE
+#define do_trace do_unused
+#endif
+
+_PROTOTYPE( int do_nice, (message *m_ptr) );
+#if ! USE_NICE
+#define do_nice do_unused
+#endif
+
+_PROTOTYPE( int do_copy, (message *m_ptr) );	
+#define do_vircopy 	do_copy
+#define do_physcopy 	do_copy
+#if ! (USE_VIRCOPY || USE_PHYSCOPY)
+#define do_copy do_unused
+#endif
+
+_PROTOTYPE( int do_vcopy, (message *m_ptr) );		
+#define do_virvcopy 	do_vcopy
+#define do_physvcopy 	do_vcopy
+#if ! (USE_VIRVCOPY || USE_PHYSVCOPY)
+#define do_vcopy do_unused
+#endif
+
+_PROTOTYPE( int do_umap, (message *m_ptr) );
+#if ! USE_UMAP
+#define do_umap do_unused
+#endif
+
+_PROTOTYPE( int do_memset, (message *m_ptr) );
+#if ! USE_MEMSET
+#define do_memset do_unused
+#endif
+
+_PROTOTYPE( int do_vm_setbuf, (message *m_ptr) );
+_PROTOTYPE( int do_vm_map, (message *m_ptr) );
+
+_PROTOTYPE( int do_abort, (message *m_ptr) );
+#if ! USE_ABORT
+#define do_abort do_unused
+#endif
+
+_PROTOTYPE( int do_getinfo, (message *m_ptr) );
+#if ! USE_GETINFO
+#define do_getinfo do_unused
+#endif
+
+_PROTOTYPE( int do_privctl, (message *m_ptr) );	
+#if ! USE_PRIVCTL
+#define do_privctl do_unused
+#endif
+
+_PROTOTYPE( int do_segctl, (message *m_ptr) );
+#if ! USE_SEGCTL
+#define do_segctl do_unused
+#endif
+
+_PROTOTYPE( int do_irqctl, (message *m_ptr) );
+#if ! USE_IRQCTL
+#define do_irqctl do_unused
+#endif
+
+_PROTOTYPE( int do_devio, (message *m_ptr) );
+#if ! USE_DEVIO
+#define do_devio do_unused
+#endif
+
+_PROTOTYPE( int do_vdevio, (message *m_ptr) );
+#if ! USE_VDEVIO
+#define do_vdevio do_unused
+#endif
+
+_PROTOTYPE( int do_int86, (message *m_ptr) );
+
+_PROTOTYPE( int do_sdevio, (message *m_ptr) );
+#if ! USE_SDEVIO
+#define do_sdevio do_unused
+#endif
+
+_PROTOTYPE( int do_kill, (message *m_ptr) );
+#if ! USE_KILL
+#define do_kill do_unused
+#endif
+
+_PROTOTYPE( int do_getksig, (message *m_ptr) );
+#if ! USE_GETKSIG
+#define do_getksig do_unused
+#endif
+
+_PROTOTYPE( int do_endksig, (message *m_ptr) );
+#if ! USE_ENDKSIG
+#define do_endksig do_unused
+#endif
+
+_PROTOTYPE( int do_sigsend, (message *m_ptr) );
+#if ! USE_SIGSEND
+#define do_sigsend do_unused
+#endif
+
+_PROTOTYPE( int do_sigreturn, (message *m_ptr) );
+#if ! USE_SIGRETURN
+#define do_sigreturn do_unused
+#endif
+
+_PROTOTYPE( int do_times, (message *m_ptr) );		
+#if ! USE_TIMES
+#define do_times do_unused
+#endif
+
+_PROTOTYPE( int do_setalarm, (message *m_ptr) );	
+#if ! USE_SETALARM
+#define do_setalarm do_unused
+#endif
+
+_PROTOTYPE( int do_iopenable, (message *m_ptr) );	
+
+#endif	/* SYSTEM_H */
+
Index: /trunk/minix/kernel/system/.depend
===================================================================
--- /trunk/minix/kernel/system/.depend	(revision 9)
+++ /trunk/minix/kernel/system/.depend	(revision 9)
@@ -0,0 +1,966 @@
+
+do_abort.o:	../config.h
+do_abort.o:	../const.h
+do_abort.o:	../debug.h
+do_abort.o:	../glo.h
+do_abort.o:	../ipc.h
+do_abort.o:	../kernel.h
+do_abort.o:	../priv.h
+do_abort.o:	../proc.h
+do_abort.o:	../protect.h
+do_abort.o:	../proto.h
+do_abort.o:	../system.h
+do_abort.o:	../type.h
+do_abort.o:	/usr/include/ansi.h
+do_abort.o:	/usr/include/errno.h
+do_abort.o:	/usr/include/ibm/bios.h
+do_abort.o:	/usr/include/ibm/cpu.h
+do_abort.o:	/usr/include/ibm/interrupt.h
+do_abort.o:	/usr/include/ibm/portio.h
+do_abort.o:	/usr/include/ibm/ports.h
+do_abort.o:	/usr/include/limits.h
+do_abort.o:	/usr/include/minix/com.h
+do_abort.o:	/usr/include/minix/config.h
+do_abort.o:	/usr/include/minix/const.h
+do_abort.o:	/usr/include/minix/ipc.h
+do_abort.o:	/usr/include/minix/sys_config.h
+do_abort.o:	/usr/include/minix/type.h
+do_abort.o:	/usr/include/sys/dir.h
+do_abort.o:	/usr/include/sys/types.h
+do_abort.o:	/usr/include/timers.h
+do_abort.o:	/usr/include/unistd.h
+do_abort.o:	do_abort.c
+
+do_copy.o:	../config.h
+do_copy.o:	../const.h
+do_copy.o:	../debug.h
+do_copy.o:	../glo.h
+do_copy.o:	../ipc.h
+do_copy.o:	../kernel.h
+do_copy.o:	../priv.h
+do_copy.o:	../proc.h
+do_copy.o:	../protect.h
+do_copy.o:	../proto.h
+do_copy.o:	../system.h
+do_copy.o:	../type.h
+do_copy.o:	/usr/include/ansi.h
+do_copy.o:	/usr/include/errno.h
+do_copy.o:	/usr/include/ibm/bios.h
+do_copy.o:	/usr/include/ibm/cpu.h
+do_copy.o:	/usr/include/ibm/interrupt.h
+do_copy.o:	/usr/include/ibm/portio.h
+do_copy.o:	/usr/include/ibm/ports.h
+do_copy.o:	/usr/include/limits.h
+do_copy.o:	/usr/include/minix/com.h
+do_copy.o:	/usr/include/minix/config.h
+do_copy.o:	/usr/include/minix/const.h
+do_copy.o:	/usr/include/minix/ipc.h
+do_copy.o:	/usr/include/minix/sys_config.h
+do_copy.o:	/usr/include/minix/type.h
+do_copy.o:	/usr/include/sys/dir.h
+do_copy.o:	/usr/include/sys/types.h
+do_copy.o:	/usr/include/timers.h
+do_copy.o:	do_copy.c
+
+do_devio.o:	../config.h
+do_devio.o:	../const.h
+do_devio.o:	../debug.h
+do_devio.o:	../glo.h
+do_devio.o:	../ipc.h
+do_devio.o:	../kernel.h
+do_devio.o:	../priv.h
+do_devio.o:	../proc.h
+do_devio.o:	../protect.h
+do_devio.o:	../proto.h
+do_devio.o:	../system.h
+do_devio.o:	../type.h
+do_devio.o:	/usr/include/ansi.h
+do_devio.o:	/usr/include/errno.h
+do_devio.o:	/usr/include/ibm/bios.h
+do_devio.o:	/usr/include/ibm/cpu.h
+do_devio.o:	/usr/include/ibm/interrupt.h
+do_devio.o:	/usr/include/ibm/portio.h
+do_devio.o:	/usr/include/ibm/ports.h
+do_devio.o:	/usr/include/limits.h
+do_devio.o:	/usr/include/minix/com.h
+do_devio.o:	/usr/include/minix/config.h
+do_devio.o:	/usr/include/minix/const.h
+do_devio.o:	/usr/include/minix/devio.h
+do_devio.o:	/usr/include/minix/endpoint.h
+do_devio.o:	/usr/include/minix/ipc.h
+do_devio.o:	/usr/include/minix/sys_config.h
+do_devio.o:	/usr/include/minix/type.h
+do_devio.o:	/usr/include/sys/dir.h
+do_devio.o:	/usr/include/sys/types.h
+do_devio.o:	/usr/include/timers.h
+do_devio.o:	do_devio.c
+
+do_endksig.o:	../config.h
+do_endksig.o:	../const.h
+do_endksig.o:	../debug.h
+do_endksig.o:	../glo.h
+do_endksig.o:	../ipc.h
+do_endksig.o:	../kernel.h
+do_endksig.o:	../priv.h
+do_endksig.o:	../proc.h
+do_endksig.o:	../protect.h
+do_endksig.o:	../proto.h
+do_endksig.o:	../system.h
+do_endksig.o:	../type.h
+do_endksig.o:	/usr/include/ansi.h
+do_endksig.o:	/usr/include/errno.h
+do_endksig.o:	/usr/include/ibm/bios.h
+do_endksig.o:	/usr/include/ibm/cpu.h
+do_endksig.o:	/usr/include/ibm/interrupt.h
+do_endksig.o:	/usr/include/ibm/portio.h
+do_endksig.o:	/usr/include/ibm/ports.h
+do_endksig.o:	/usr/include/limits.h
+do_endksig.o:	/usr/include/minix/com.h
+do_endksig.o:	/usr/include/minix/config.h
+do_endksig.o:	/usr/include/minix/const.h
+do_endksig.o:	/usr/include/minix/ipc.h
+do_endksig.o:	/usr/include/minix/sys_config.h
+do_endksig.o:	/usr/include/minix/type.h
+do_endksig.o:	/usr/include/signal.h
+do_endksig.o:	/usr/include/sys/dir.h
+do_endksig.o:	/usr/include/sys/sigcontext.h
+do_endksig.o:	/usr/include/sys/types.h
+do_endksig.o:	/usr/include/timers.h
+do_endksig.o:	do_endksig.c
+
+do_exec.o:	../config.h
+do_exec.o:	../const.h
+do_exec.o:	../debug.h
+do_exec.o:	../glo.h
+do_exec.o:	../ipc.h
+do_exec.o:	../kernel.h
+do_exec.o:	../priv.h
+do_exec.o:	../proc.h
+do_exec.o:	../protect.h
+do_exec.o:	../proto.h
+do_exec.o:	../system.h
+do_exec.o:	../type.h
+do_exec.o:	/usr/include/ansi.h
+do_exec.o:	/usr/include/errno.h
+do_exec.o:	/usr/include/ibm/bios.h
+do_exec.o:	/usr/include/ibm/cpu.h
+do_exec.o:	/usr/include/ibm/interrupt.h
+do_exec.o:	/usr/include/ibm/portio.h
+do_exec.o:	/usr/include/ibm/ports.h
+do_exec.o:	/usr/include/limits.h
+do_exec.o:	/usr/include/minix/com.h
+do_exec.o:	/usr/include/minix/config.h
+do_exec.o:	/usr/include/minix/const.h
+do_exec.o:	/usr/include/minix/endpoint.h
+do_exec.o:	/usr/include/minix/ipc.h
+do_exec.o:	/usr/include/minix/sys_config.h
+do_exec.o:	/usr/include/minix/type.h
+do_exec.o:	/usr/include/signal.h
+do_exec.o:	/usr/include/string.h
+do_exec.o:	/usr/include/sys/dir.h
+do_exec.o:	/usr/include/sys/types.h
+do_exec.o:	/usr/include/timers.h
+do_exec.o:	do_exec.c
+
+do_exit.o:	../config.h
+do_exit.o:	../const.h
+do_exit.o:	../debug.h
+do_exit.o:	../glo.h
+do_exit.o:	../ipc.h
+do_exit.o:	../kernel.h
+do_exit.o:	../priv.h
+do_exit.o:	../proc.h
+do_exit.o:	../protect.h
+do_exit.o:	../proto.h
+do_exit.o:	../system.h
+do_exit.o:	../type.h
+do_exit.o:	/usr/include/ansi.h
+do_exit.o:	/usr/include/errno.h
+do_exit.o:	/usr/include/ibm/bios.h
+do_exit.o:	/usr/include/ibm/cpu.h
+do_exit.o:	/usr/include/ibm/interrupt.h
+do_exit.o:	/usr/include/ibm/portio.h
+do_exit.o:	/usr/include/ibm/ports.h
+do_exit.o:	/usr/include/limits.h
+do_exit.o:	/usr/include/minix/com.h
+do_exit.o:	/usr/include/minix/config.h
+do_exit.o:	/usr/include/minix/const.h
+do_exit.o:	/usr/include/minix/endpoint.h
+do_exit.o:	/usr/include/minix/ipc.h
+do_exit.o:	/usr/include/minix/sys_config.h
+do_exit.o:	/usr/include/minix/type.h
+do_exit.o:	/usr/include/sys/dir.h
+do_exit.o:	/usr/include/sys/types.h
+do_exit.o:	/usr/include/timers.h
+do_exit.o:	do_exit.c
+
+do_fork.o:	../config.h
+do_fork.o:	../const.h
+do_fork.o:	../debug.h
+do_fork.o:	../glo.h
+do_fork.o:	../ipc.h
+do_fork.o:	../kernel.h
+do_fork.o:	../priv.h
+do_fork.o:	../proc.h
+do_fork.o:	../protect.h
+do_fork.o:	../proto.h
+do_fork.o:	../system.h
+do_fork.o:	../type.h
+do_fork.o:	/usr/include/ansi.h
+do_fork.o:	/usr/include/errno.h
+do_fork.o:	/usr/include/ibm/bios.h
+do_fork.o:	/usr/include/ibm/cpu.h
+do_fork.o:	/usr/include/ibm/interrupt.h
+do_fork.o:	/usr/include/ibm/portio.h
+do_fork.o:	/usr/include/ibm/ports.h
+do_fork.o:	/usr/include/limits.h
+do_fork.o:	/usr/include/minix/com.h
+do_fork.o:	/usr/include/minix/config.h
+do_fork.o:	/usr/include/minix/const.h
+do_fork.o:	/usr/include/minix/endpoint.h
+do_fork.o:	/usr/include/minix/ipc.h
+do_fork.o:	/usr/include/minix/sys_config.h
+do_fork.o:	/usr/include/minix/type.h
+do_fork.o:	/usr/include/signal.h
+do_fork.o:	/usr/include/sys/dir.h
+do_fork.o:	/usr/include/sys/types.h
+do_fork.o:	/usr/include/timers.h
+do_fork.o:	do_fork.c
+
+do_getinfo.o:	../config.h
+do_getinfo.o:	../const.h
+do_getinfo.o:	../debug.h
+do_getinfo.o:	../glo.h
+do_getinfo.o:	../ipc.h
+do_getinfo.o:	../kernel.h
+do_getinfo.o:	../priv.h
+do_getinfo.o:	../proc.h
+do_getinfo.o:	../protect.h
+do_getinfo.o:	../proto.h
+do_getinfo.o:	../system.h
+do_getinfo.o:	../type.h
+do_getinfo.o:	/usr/include/ansi.h
+do_getinfo.o:	/usr/include/errno.h
+do_getinfo.o:	/usr/include/ibm/bios.h
+do_getinfo.o:	/usr/include/ibm/cpu.h
+do_getinfo.o:	/usr/include/ibm/interrupt.h
+do_getinfo.o:	/usr/include/ibm/portio.h
+do_getinfo.o:	/usr/include/ibm/ports.h
+do_getinfo.o:	/usr/include/limits.h
+do_getinfo.o:	/usr/include/minix/com.h
+do_getinfo.o:	/usr/include/minix/config.h
+do_getinfo.o:	/usr/include/minix/const.h
+do_getinfo.o:	/usr/include/minix/ipc.h
+do_getinfo.o:	/usr/include/minix/sys_config.h
+do_getinfo.o:	/usr/include/minix/type.h
+do_getinfo.o:	/usr/include/sys/dir.h
+do_getinfo.o:	/usr/include/sys/types.h
+do_getinfo.o:	/usr/include/timers.h
+do_getinfo.o:	do_getinfo.c
+
+do_getksig.o:	../config.h
+do_getksig.o:	../const.h
+do_getksig.o:	../debug.h
+do_getksig.o:	../glo.h
+do_getksig.o:	../ipc.h
+do_getksig.o:	../kernel.h
+do_getksig.o:	../priv.h
+do_getksig.o:	../proc.h
+do_getksig.o:	../protect.h
+do_getksig.o:	../proto.h
+do_getksig.o:	../system.h
+do_getksig.o:	../type.h
+do_getksig.o:	/usr/include/ansi.h
+do_getksig.o:	/usr/include/errno.h
+do_getksig.o:	/usr/include/ibm/bios.h
+do_getksig.o:	/usr/include/ibm/cpu.h
+do_getksig.o:	/usr/include/ibm/interrupt.h
+do_getksig.o:	/usr/include/ibm/portio.h
+do_getksig.o:	/usr/include/ibm/ports.h
+do_getksig.o:	/usr/include/limits.h
+do_getksig.o:	/usr/include/minix/com.h
+do_getksig.o:	/usr/include/minix/config.h
+do_getksig.o:	/usr/include/minix/const.h
+do_getksig.o:	/usr/include/minix/endpoint.h
+do_getksig.o:	/usr/include/minix/ipc.h
+do_getksig.o:	/usr/include/minix/sys_config.h
+do_getksig.o:	/usr/include/minix/type.h
+do_getksig.o:	/usr/include/signal.h
+do_getksig.o:	/usr/include/sys/dir.h
+do_getksig.o:	/usr/include/sys/sigcontext.h
+do_getksig.o:	/usr/include/sys/types.h
+do_getksig.o:	/usr/include/timers.h
+do_getksig.o:	do_getksig.c
+
+do_int86.o:	../config.h
+do_int86.o:	../const.h
+do_int86.o:	../debug.h
+do_int86.o:	../glo.h
+do_int86.o:	../ipc.h
+do_int86.o:	../kernel.h
+do_int86.o:	../priv.h
+do_int86.o:	../proc.h
+do_int86.o:	../protect.h
+do_int86.o:	../proto.h
+do_int86.o:	../system.h
+do_int86.o:	../type.h
+do_int86.o:	/usr/include/ansi.h
+do_int86.o:	/usr/include/errno.h
+do_int86.o:	/usr/include/ibm/bios.h
+do_int86.o:	/usr/include/ibm/cpu.h
+do_int86.o:	/usr/include/ibm/int86.h
+do_int86.o:	/usr/include/ibm/interrupt.h
+do_int86.o:	/usr/include/ibm/portio.h
+do_int86.o:	/usr/include/ibm/ports.h
+do_int86.o:	/usr/include/limits.h
+do_int86.o:	/usr/include/minix/com.h
+do_int86.o:	/usr/include/minix/config.h
+do_int86.o:	/usr/include/minix/const.h
+do_int86.o:	/usr/include/minix/endpoint.h
+do_int86.o:	/usr/include/minix/ipc.h
+do_int86.o:	/usr/include/minix/sys_config.h
+do_int86.o:	/usr/include/minix/type.h
+do_int86.o:	/usr/include/sys/dir.h
+do_int86.o:	/usr/include/sys/types.h
+do_int86.o:	/usr/include/timers.h
+do_int86.o:	do_int86.c
+
+do_iopenable.o:	../config.h
+do_iopenable.o:	../const.h
+do_iopenable.o:	../debug.h
+do_iopenable.o:	../glo.h
+do_iopenable.o:	../ipc.h
+do_iopenable.o:	../kernel.h
+do_iopenable.o:	../priv.h
+do_iopenable.o:	../proc.h
+do_iopenable.o:	../protect.h
+do_iopenable.o:	../proto.h
+do_iopenable.o:	../system.h
+do_iopenable.o:	../type.h
+do_iopenable.o:	/usr/include/ansi.h
+do_iopenable.o:	/usr/include/errno.h
+do_iopenable.o:	/usr/include/ibm/bios.h
+do_iopenable.o:	/usr/include/ibm/cpu.h
+do_iopenable.o:	/usr/include/ibm/interrupt.h
+do_iopenable.o:	/usr/include/ibm/portio.h
+do_iopenable.o:	/usr/include/ibm/ports.h
+do_iopenable.o:	/usr/include/limits.h
+do_iopenable.o:	/usr/include/minix/com.h
+do_iopenable.o:	/usr/include/minix/config.h
+do_iopenable.o:	/usr/include/minix/const.h
+do_iopenable.o:	/usr/include/minix/ipc.h
+do_iopenable.o:	/usr/include/minix/sys_config.h
+do_iopenable.o:	/usr/include/minix/type.h
+do_iopenable.o:	/usr/include/sys/dir.h
+do_iopenable.o:	/usr/include/sys/types.h
+do_iopenable.o:	/usr/include/timers.h
+do_iopenable.o:	do_iopenable.c
+
+do_irqctl.o:	../config.h
+do_irqctl.o:	../const.h
+do_irqctl.o:	../debug.h
+do_irqctl.o:	../glo.h
+do_irqctl.o:	../ipc.h
+do_irqctl.o:	../kernel.h
+do_irqctl.o:	../priv.h
+do_irqctl.o:	../proc.h
+do_irqctl.o:	../protect.h
+do_irqctl.o:	../proto.h
+do_irqctl.o:	../system.h
+do_irqctl.o:	../type.h
+do_irqctl.o:	/usr/include/ansi.h
+do_irqctl.o:	/usr/include/errno.h
+do_irqctl.o:	/usr/include/ibm/bios.h
+do_irqctl.o:	/usr/include/ibm/cpu.h
+do_irqctl.o:	/usr/include/ibm/interrupt.h
+do_irqctl.o:	/usr/include/ibm/portio.h
+do_irqctl.o:	/usr/include/ibm/ports.h
+do_irqctl.o:	/usr/include/limits.h
+do_irqctl.o:	/usr/include/minix/com.h
+do_irqctl.o:	/usr/include/minix/config.h
+do_irqctl.o:	/usr/include/minix/const.h
+do_irqctl.o:	/usr/include/minix/endpoint.h
+do_irqctl.o:	/usr/include/minix/ipc.h
+do_irqctl.o:	/usr/include/minix/sys_config.h
+do_irqctl.o:	/usr/include/minix/type.h
+do_irqctl.o:	/usr/include/sys/dir.h
+do_irqctl.o:	/usr/include/sys/types.h
+do_irqctl.o:	/usr/include/timers.h
+do_irqctl.o:	do_irqctl.c
+
+do_kill.o:	../config.h
+do_kill.o:	../const.h
+do_kill.o:	../debug.h
+do_kill.o:	../glo.h
+do_kill.o:	../ipc.h
+do_kill.o:	../kernel.h
+do_kill.o:	../priv.h
+do_kill.o:	../proc.h
+do_kill.o:	../protect.h
+do_kill.o:	../proto.h
+do_kill.o:	../system.h
+do_kill.o:	../type.h
+do_kill.o:	/usr/include/ansi.h
+do_kill.o:	/usr/include/errno.h
+do_kill.o:	/usr/include/ibm/bios.h
+do_kill.o:	/usr/include/ibm/cpu.h
+do_kill.o:	/usr/include/ibm/interrupt.h
+do_kill.o:	/usr/include/ibm/portio.h
+do_kill.o:	/usr/include/ibm/ports.h
+do_kill.o:	/usr/include/limits.h
+do_kill.o:	/usr/include/minix/com.h
+do_kill.o:	/usr/include/minix/config.h
+do_kill.o:	/usr/include/minix/const.h
+do_kill.o:	/usr/include/minix/ipc.h
+do_kill.o:	/usr/include/minix/sys_config.h
+do_kill.o:	/usr/include/minix/type.h
+do_kill.o:	/usr/include/signal.h
+do_kill.o:	/usr/include/sys/dir.h
+do_kill.o:	/usr/include/sys/sigcontext.h
+do_kill.o:	/usr/include/sys/types.h
+do_kill.o:	/usr/include/timers.h
+do_kill.o:	do_kill.c
+
+do_memset.o:	../config.h
+do_memset.o:	../const.h
+do_memset.o:	../debug.h
+do_memset.o:	../glo.h
+do_memset.o:	../ipc.h
+do_memset.o:	../kernel.h
+do_memset.o:	../priv.h
+do_memset.o:	../proc.h
+do_memset.o:	../protect.h
+do_memset.o:	../proto.h
+do_memset.o:	../system.h
+do_memset.o:	../type.h
+do_memset.o:	/usr/include/ansi.h
+do_memset.o:	/usr/include/errno.h
+do_memset.o:	/usr/include/ibm/bios.h
+do_memset.o:	/usr/include/ibm/cpu.h
+do_memset.o:	/usr/include/ibm/interrupt.h
+do_memset.o:	/usr/include/ibm/portio.h
+do_memset.o:	/usr/include/ibm/ports.h
+do_memset.o:	/usr/include/limits.h
+do_memset.o:	/usr/include/minix/com.h
+do_memset.o:	/usr/include/minix/config.h
+do_memset.o:	/usr/include/minix/const.h
+do_memset.o:	/usr/include/minix/ipc.h
+do_memset.o:	/usr/include/minix/sys_config.h
+do_memset.o:	/usr/include/minix/type.h
+do_memset.o:	/usr/include/sys/dir.h
+do_memset.o:	/usr/include/sys/types.h
+do_memset.o:	/usr/include/timers.h
+do_memset.o:	do_memset.c
+
+do_newmap.o:	../config.h
+do_newmap.o:	../const.h
+do_newmap.o:	../debug.h
+do_newmap.o:	../glo.h
+do_newmap.o:	../ipc.h
+do_newmap.o:	../kernel.h
+do_newmap.o:	../priv.h
+do_newmap.o:	../proc.h
+do_newmap.o:	../protect.h
+do_newmap.o:	../proto.h
+do_newmap.o:	../system.h
+do_newmap.o:	../type.h
+do_newmap.o:	/usr/include/ansi.h
+do_newmap.o:	/usr/include/errno.h
+do_newmap.o:	/usr/include/ibm/bios.h
+do_newmap.o:	/usr/include/ibm/cpu.h
+do_newmap.o:	/usr/include/ibm/interrupt.h
+do_newmap.o:	/usr/include/ibm/portio.h
+do_newmap.o:	/usr/include/ibm/ports.h
+do_newmap.o:	/usr/include/limits.h
+do_newmap.o:	/usr/include/minix/com.h
+do_newmap.o:	/usr/include/minix/config.h
+do_newmap.o:	/usr/include/minix/const.h
+do_newmap.o:	/usr/include/minix/endpoint.h
+do_newmap.o:	/usr/include/minix/ipc.h
+do_newmap.o:	/usr/include/minix/sys_config.h
+do_newmap.o:	/usr/include/minix/type.h
+do_newmap.o:	/usr/include/sys/dir.h
+do_newmap.o:	/usr/include/sys/types.h
+do_newmap.o:	/usr/include/timers.h
+do_newmap.o:	do_newmap.c
+
+do_nice.o:	../config.h
+do_nice.o:	../const.h
+do_nice.o:	../debug.h
+do_nice.o:	../glo.h
+do_nice.o:	../ipc.h
+do_nice.o:	../kernel.h
+do_nice.o:	../priv.h
+do_nice.o:	../proc.h
+do_nice.o:	../protect.h
+do_nice.o:	../proto.h
+do_nice.o:	../system.h
+do_nice.o:	../type.h
+do_nice.o:	/usr/include/ansi.h
+do_nice.o:	/usr/include/errno.h
+do_nice.o:	/usr/include/ibm/bios.h
+do_nice.o:	/usr/include/ibm/cpu.h
+do_nice.o:	/usr/include/ibm/interrupt.h
+do_nice.o:	/usr/include/ibm/portio.h
+do_nice.o:	/usr/include/ibm/ports.h
+do_nice.o:	/usr/include/limits.h
+do_nice.o:	/usr/include/minix/com.h
+do_nice.o:	/usr/include/minix/config.h
+do_nice.o:	/usr/include/minix/const.h
+do_nice.o:	/usr/include/minix/ipc.h
+do_nice.o:	/usr/include/minix/sys_config.h
+do_nice.o:	/usr/include/minix/type.h
+do_nice.o:	/usr/include/sys/dir.h
+do_nice.o:	/usr/include/sys/resource.h
+do_nice.o:	/usr/include/sys/types.h
+do_nice.o:	/usr/include/timers.h
+do_nice.o:	do_nice.c
+
+do_privctl.o:	../config.h
+do_privctl.o:	../const.h
+do_privctl.o:	../debug.h
+do_privctl.o:	../glo.h
+do_privctl.o:	../ipc.h
+do_privctl.o:	../kernel.h
+do_privctl.o:	../priv.h
+do_privctl.o:	../proc.h
+do_privctl.o:	../protect.h
+do_privctl.o:	../proto.h
+do_privctl.o:	../system.h
+do_privctl.o:	../type.h
+do_privctl.o:	/usr/include/ansi.h
+do_privctl.o:	/usr/include/errno.h
+do_privctl.o:	/usr/include/ibm/bios.h
+do_privctl.o:	/usr/include/ibm/cpu.h
+do_privctl.o:	/usr/include/ibm/interrupt.h
+do_privctl.o:	/usr/include/ibm/portio.h
+do_privctl.o:	/usr/include/ibm/ports.h
+do_privctl.o:	/usr/include/limits.h
+do_privctl.o:	/usr/include/minix/com.h
+do_privctl.o:	/usr/include/minix/config.h
+do_privctl.o:	/usr/include/minix/const.h
+do_privctl.o:	/usr/include/minix/ipc.h
+do_privctl.o:	/usr/include/minix/sys_config.h
+do_privctl.o:	/usr/include/minix/type.h
+do_privctl.o:	/usr/include/signal.h
+do_privctl.o:	/usr/include/sys/dir.h
+do_privctl.o:	/usr/include/sys/types.h
+do_privctl.o:	/usr/include/timers.h
+do_privctl.o:	do_privctl.c
+
+do_sdevio.o:	../config.h
+do_sdevio.o:	../const.h
+do_sdevio.o:	../debug.h
+do_sdevio.o:	../glo.h
+do_sdevio.o:	../ipc.h
+do_sdevio.o:	../kernel.h
+do_sdevio.o:	../priv.h
+do_sdevio.o:	../proc.h
+do_sdevio.o:	../protect.h
+do_sdevio.o:	../proto.h
+do_sdevio.o:	../system.h
+do_sdevio.o:	../type.h
+do_sdevio.o:	/usr/include/ansi.h
+do_sdevio.o:	/usr/include/errno.h
+do_sdevio.o:	/usr/include/ibm/bios.h
+do_sdevio.o:	/usr/include/ibm/cpu.h
+do_sdevio.o:	/usr/include/ibm/interrupt.h
+do_sdevio.o:	/usr/include/ibm/portio.h
+do_sdevio.o:	/usr/include/ibm/ports.h
+do_sdevio.o:	/usr/include/limits.h
+do_sdevio.o:	/usr/include/minix/com.h
+do_sdevio.o:	/usr/include/minix/config.h
+do_sdevio.o:	/usr/include/minix/const.h
+do_sdevio.o:	/usr/include/minix/devio.h
+do_sdevio.o:	/usr/include/minix/endpoint.h
+do_sdevio.o:	/usr/include/minix/ipc.h
+do_sdevio.o:	/usr/include/minix/sys_config.h
+do_sdevio.o:	/usr/include/minix/type.h
+do_sdevio.o:	/usr/include/sys/dir.h
+do_sdevio.o:	/usr/include/sys/types.h
+do_sdevio.o:	/usr/include/timers.h
+do_sdevio.o:	do_sdevio.c
+
+do_segctl.o:	../config.h
+do_segctl.o:	../const.h
+do_segctl.o:	../debug.h
+do_segctl.o:	../glo.h
+do_segctl.o:	../ipc.h
+do_segctl.o:	../kernel.h
+do_segctl.o:	../priv.h
+do_segctl.o:	../proc.h
+do_segctl.o:	../protect.h
+do_segctl.o:	../proto.h
+do_segctl.o:	../system.h
+do_segctl.o:	../type.h
+do_segctl.o:	/usr/include/ansi.h
+do_segctl.o:	/usr/include/errno.h
+do_segctl.o:	/usr/include/ibm/bios.h
+do_segctl.o:	/usr/include/ibm/cpu.h
+do_segctl.o:	/usr/include/ibm/interrupt.h
+do_segctl.o:	/usr/include/ibm/portio.h
+do_segctl.o:	/usr/include/ibm/ports.h
+do_segctl.o:	/usr/include/limits.h
+do_segctl.o:	/usr/include/minix/com.h
+do_segctl.o:	/usr/include/minix/config.h
+do_segctl.o:	/usr/include/minix/const.h
+do_segctl.o:	/usr/include/minix/ipc.h
+do_segctl.o:	/usr/include/minix/sys_config.h
+do_segctl.o:	/usr/include/minix/type.h
+do_segctl.o:	/usr/include/sys/dir.h
+do_segctl.o:	/usr/include/sys/types.h
+do_segctl.o:	/usr/include/timers.h
+do_segctl.o:	do_segctl.c
+
+do_setalarm.o:	../config.h
+do_setalarm.o:	../const.h
+do_setalarm.o:	../debug.h
+do_setalarm.o:	../glo.h
+do_setalarm.o:	../ipc.h
+do_setalarm.o:	../kernel.h
+do_setalarm.o:	../priv.h
+do_setalarm.o:	../proc.h
+do_setalarm.o:	../protect.h
+do_setalarm.o:	../proto.h
+do_setalarm.o:	../system.h
+do_setalarm.o:	../type.h
+do_setalarm.o:	/usr/include/ansi.h
+do_setalarm.o:	/usr/include/errno.h
+do_setalarm.o:	/usr/include/ibm/bios.h
+do_setalarm.o:	/usr/include/ibm/cpu.h
+do_setalarm.o:	/usr/include/ibm/interrupt.h
+do_setalarm.o:	/usr/include/ibm/portio.h
+do_setalarm.o:	/usr/include/ibm/ports.h
+do_setalarm.o:	/usr/include/limits.h
+do_setalarm.o:	/usr/include/minix/com.h
+do_setalarm.o:	/usr/include/minix/config.h
+do_setalarm.o:	/usr/include/minix/const.h
+do_setalarm.o:	/usr/include/minix/endpoint.h
+do_setalarm.o:	/usr/include/minix/ipc.h
+do_setalarm.o:	/usr/include/minix/sys_config.h
+do_setalarm.o:	/usr/include/minix/type.h
+do_setalarm.o:	/usr/include/sys/dir.h
+do_setalarm.o:	/usr/include/sys/types.h
+do_setalarm.o:	/usr/include/timers.h
+do_setalarm.o:	do_setalarm.c
+
+do_sigreturn.o:	../config.h
+do_sigreturn.o:	../const.h
+do_sigreturn.o:	../debug.h
+do_sigreturn.o:	../glo.h
+do_sigreturn.o:	../ipc.h
+do_sigreturn.o:	../kernel.h
+do_sigreturn.o:	../priv.h
+do_sigreturn.o:	../proc.h
+do_sigreturn.o:	../protect.h
+do_sigreturn.o:	../proto.h
+do_sigreturn.o:	../system.h
+do_sigreturn.o:	../type.h
+do_sigreturn.o:	/usr/include/ansi.h
+do_sigreturn.o:	/usr/include/errno.h
+do_sigreturn.o:	/usr/include/ibm/bios.h
+do_sigreturn.o:	/usr/include/ibm/cpu.h
+do_sigreturn.o:	/usr/include/ibm/interrupt.h
+do_sigreturn.o:	/usr/include/ibm/portio.h
+do_sigreturn.o:	/usr/include/ibm/ports.h
+do_sigreturn.o:	/usr/include/limits.h
+do_sigreturn.o:	/usr/include/minix/com.h
+do_sigreturn.o:	/usr/include/minix/config.h
+do_sigreturn.o:	/usr/include/minix/const.h
+do_sigreturn.o:	/usr/include/minix/ipc.h
+do_sigreturn.o:	/usr/include/minix/sys_config.h
+do_sigreturn.o:	/usr/include/minix/type.h
+do_sigreturn.o:	/usr/include/signal.h
+do_sigreturn.o:	/usr/include/string.h
+do_sigreturn.o:	/usr/include/sys/dir.h
+do_sigreturn.o:	/usr/include/sys/sigcontext.h
+do_sigreturn.o:	/usr/include/sys/types.h
+do_sigreturn.o:	/usr/include/timers.h
+do_sigreturn.o:	do_sigreturn.c
+
+do_sigsend.o:	../config.h
+do_sigsend.o:	../const.h
+do_sigsend.o:	../debug.h
+do_sigsend.o:	../glo.h
+do_sigsend.o:	../ipc.h
+do_sigsend.o:	../kernel.h
+do_sigsend.o:	../priv.h
+do_sigsend.o:	../proc.h
+do_sigsend.o:	../protect.h
+do_sigsend.o:	../proto.h
+do_sigsend.o:	../system.h
+do_sigsend.o:	../type.h
+do_sigsend.o:	/usr/include/ansi.h
+do_sigsend.o:	/usr/include/errno.h
+do_sigsend.o:	/usr/include/ibm/bios.h
+do_sigsend.o:	/usr/include/ibm/cpu.h
+do_sigsend.o:	/usr/include/ibm/interrupt.h
+do_sigsend.o:	/usr/include/ibm/portio.h
+do_sigsend.o:	/usr/include/ibm/ports.h
+do_sigsend.o:	/usr/include/limits.h
+do_sigsend.o:	/usr/include/minix/com.h
+do_sigsend.o:	/usr/include/minix/config.h
+do_sigsend.o:	/usr/include/minix/const.h
+do_sigsend.o:	/usr/include/minix/ipc.h
+do_sigsend.o:	/usr/include/minix/sys_config.h
+do_sigsend.o:	/usr/include/minix/type.h
+do_sigsend.o:	/usr/include/signal.h
+do_sigsend.o:	/usr/include/string.h
+do_sigsend.o:	/usr/include/sys/dir.h
+do_sigsend.o:	/usr/include/sys/sigcontext.h
+do_sigsend.o:	/usr/include/sys/types.h
+do_sigsend.o:	/usr/include/timers.h
+do_sigsend.o:	do_sigsend.c
+
+do_times.o:	../config.h
+do_times.o:	../const.h
+do_times.o:	../debug.h
+do_times.o:	../glo.h
+do_times.o:	../ipc.h
+do_times.o:	../kernel.h
+do_times.o:	../priv.h
+do_times.o:	../proc.h
+do_times.o:	../protect.h
+do_times.o:	../proto.h
+do_times.o:	../system.h
+do_times.o:	../type.h
+do_times.o:	/usr/include/ansi.h
+do_times.o:	/usr/include/errno.h
+do_times.o:	/usr/include/ibm/bios.h
+do_times.o:	/usr/include/ibm/cpu.h
+do_times.o:	/usr/include/ibm/interrupt.h
+do_times.o:	/usr/include/ibm/portio.h
+do_times.o:	/usr/include/ibm/ports.h
+do_times.o:	/usr/include/limits.h
+do_times.o:	/usr/include/minix/com.h
+do_times.o:	/usr/include/minix/config.h
+do_times.o:	/usr/include/minix/const.h
+do_times.o:	/usr/include/minix/endpoint.h
+do_times.o:	/usr/include/minix/ipc.h
+do_times.o:	/usr/include/minix/sys_config.h
+do_times.o:	/usr/include/minix/type.h
+do_times.o:	/usr/include/sys/dir.h
+do_times.o:	/usr/include/sys/types.h
+do_times.o:	/usr/include/timers.h
+do_times.o:	do_times.c
+
+do_trace.o:	../config.h
+do_trace.o:	../const.h
+do_trace.o:	../debug.h
+do_trace.o:	../glo.h
+do_trace.o:	../ipc.h
+do_trace.o:	../kernel.h
+do_trace.o:	../priv.h
+do_trace.o:	../proc.h
+do_trace.o:	../protect.h
+do_trace.o:	../proto.h
+do_trace.o:	../system.h
+do_trace.o:	../type.h
+do_trace.o:	/usr/include/ansi.h
+do_trace.o:	/usr/include/errno.h
+do_trace.o:	/usr/include/ibm/bios.h
+do_trace.o:	/usr/include/ibm/cpu.h
+do_trace.o:	/usr/include/ibm/interrupt.h
+do_trace.o:	/usr/include/ibm/portio.h
+do_trace.o:	/usr/include/ibm/ports.h
+do_trace.o:	/usr/include/limits.h
+do_trace.o:	/usr/include/minix/com.h
+do_trace.o:	/usr/include/minix/config.h
+do_trace.o:	/usr/include/minix/const.h
+do_trace.o:	/usr/include/minix/ipc.h
+do_trace.o:	/usr/include/minix/sys_config.h
+do_trace.o:	/usr/include/minix/type.h
+do_trace.o:	/usr/include/sys/dir.h
+do_trace.o:	/usr/include/sys/ptrace.h
+do_trace.o:	/usr/include/sys/types.h
+do_trace.o:	/usr/include/timers.h
+do_trace.o:	do_trace.c
+
+do_umap.o:	../config.h
+do_umap.o:	../const.h
+do_umap.o:	../debug.h
+do_umap.o:	../glo.h
+do_umap.o:	../ipc.h
+do_umap.o:	../kernel.h
+do_umap.o:	../priv.h
+do_umap.o:	../proc.h
+do_umap.o:	../protect.h
+do_umap.o:	../proto.h
+do_umap.o:	../system.h
+do_umap.o:	../type.h
+do_umap.o:	/usr/include/ansi.h
+do_umap.o:	/usr/include/errno.h
+do_umap.o:	/usr/include/ibm/bios.h
+do_umap.o:	/usr/include/ibm/cpu.h
+do_umap.o:	/usr/include/ibm/interrupt.h
+do_umap.o:	/usr/include/ibm/portio.h
+do_umap.o:	/usr/include/ibm/ports.h
+do_umap.o:	/usr/include/limits.h
+do_umap.o:	/usr/include/minix/com.h
+do_umap.o:	/usr/include/minix/config.h
+do_umap.o:	/usr/include/minix/const.h
+do_umap.o:	/usr/include/minix/ipc.h
+do_umap.o:	/usr/include/minix/sys_config.h
+do_umap.o:	/usr/include/minix/type.h
+do_umap.o:	/usr/include/sys/dir.h
+do_umap.o:	/usr/include/sys/types.h
+do_umap.o:	/usr/include/timers.h
+do_umap.o:	do_umap.c
+
+do_unused.o:	../config.h
+do_unused.o:	../const.h
+do_unused.o:	../debug.h
+do_unused.o:	../glo.h
+do_unused.o:	../ipc.h
+do_unused.o:	../kernel.h
+do_unused.o:	../priv.h
+do_unused.o:	../proc.h
+do_unused.o:	../protect.h
+do_unused.o:	../proto.h
+do_unused.o:	../system.h
+do_unused.o:	../type.h
+do_unused.o:	/usr/include/ansi.h
+do_unused.o:	/usr/include/errno.h
+do_unused.o:	/usr/include/ibm/bios.h
+do_unused.o:	/usr/include/ibm/cpu.h
+do_unused.o:	/usr/include/ibm/interrupt.h
+do_unused.o:	/usr/include/ibm/portio.h
+do_unused.o:	/usr/include/ibm/ports.h
+do_unused.o:	/usr/include/limits.h
+do_unused.o:	/usr/include/minix/com.h
+do_unused.o:	/usr/include/minix/config.h
+do_unused.o:	/usr/include/minix/const.h
+do_unused.o:	/usr/include/minix/ipc.h
+do_unused.o:	/usr/include/minix/sys_config.h
+do_unused.o:	/usr/include/minix/type.h
+do_unused.o:	/usr/include/sys/dir.h
+do_unused.o:	/usr/include/sys/types.h
+do_unused.o:	/usr/include/timers.h
+do_unused.o:	do_unused.c
+
+do_vcopy.o:	../config.h
+do_vcopy.o:	../const.h
+do_vcopy.o:	../debug.h
+do_vcopy.o:	../glo.h
+do_vcopy.o:	../ipc.h
+do_vcopy.o:	../kernel.h
+do_vcopy.o:	../priv.h
+do_vcopy.o:	../proc.h
+do_vcopy.o:	../protect.h
+do_vcopy.o:	../proto.h
+do_vcopy.o:	../system.h
+do_vcopy.o:	../type.h
+do_vcopy.o:	/usr/include/ansi.h
+do_vcopy.o:	/usr/include/errno.h
+do_vcopy.o:	/usr/include/ibm/bios.h
+do_vcopy.o:	/usr/include/ibm/cpu.h
+do_vcopy.o:	/usr/include/ibm/interrupt.h
+do_vcopy.o:	/usr/include/ibm/portio.h
+do_vcopy.o:	/usr/include/ibm/ports.h
+do_vcopy.o:	/usr/include/limits.h
+do_vcopy.o:	/usr/include/minix/com.h
+do_vcopy.o:	/usr/include/minix/config.h
+do_vcopy.o:	/usr/include/minix/const.h
+do_vcopy.o:	/usr/include/minix/ipc.h
+do_vcopy.o:	/usr/include/minix/sys_config.h
+do_vcopy.o:	/usr/include/minix/type.h
+do_vcopy.o:	/usr/include/sys/dir.h
+do_vcopy.o:	/usr/include/sys/types.h
+do_vcopy.o:	/usr/include/timers.h
+do_vcopy.o:	do_vcopy.c
+
+do_vdevio.o:	../config.h
+do_vdevio.o:	../const.h
+do_vdevio.o:	../debug.h
+do_vdevio.o:	../glo.h
+do_vdevio.o:	../ipc.h
+do_vdevio.o:	../kernel.h
+do_vdevio.o:	../priv.h
+do_vdevio.o:	../proc.h
+do_vdevio.o:	../protect.h
+do_vdevio.o:	../proto.h
+do_vdevio.o:	../system.h
+do_vdevio.o:	../type.h
+do_vdevio.o:	/usr/include/ansi.h
+do_vdevio.o:	/usr/include/errno.h
+do_vdevio.o:	/usr/include/ibm/bios.h
+do_vdevio.o:	/usr/include/ibm/cpu.h
+do_vdevio.o:	/usr/include/ibm/interrupt.h
+do_vdevio.o:	/usr/include/ibm/portio.h
+do_vdevio.o:	/usr/include/ibm/ports.h
+do_vdevio.o:	/usr/include/limits.h
+do_vdevio.o:	/usr/include/minix/com.h
+do_vdevio.o:	/usr/include/minix/config.h
+do_vdevio.o:	/usr/include/minix/const.h
+do_vdevio.o:	/usr/include/minix/devio.h
+do_vdevio.o:	/usr/include/minix/endpoint.h
+do_vdevio.o:	/usr/include/minix/ipc.h
+do_vdevio.o:	/usr/include/minix/sys_config.h
+do_vdevio.o:	/usr/include/minix/type.h
+do_vdevio.o:	/usr/include/sys/dir.h
+do_vdevio.o:	/usr/include/sys/types.h
+do_vdevio.o:	/usr/include/timers.h
+do_vdevio.o:	do_vdevio.c
+
+do_vm.o:	../config.h
+do_vm.o:	../const.h
+do_vm.o:	../debug.h
+do_vm.o:	../glo.h
+do_vm.o:	../ipc.h
+do_vm.o:	../kernel.h
+do_vm.o:	../priv.h
+do_vm.o:	../proc.h
+do_vm.o:	../protect.h
+do_vm.o:	../proto.h
+do_vm.o:	../system.h
+do_vm.o:	../type.h
+do_vm.o:	/usr/include/ansi.h
+do_vm.o:	/usr/include/errno.h
+do_vm.o:	/usr/include/ibm/bios.h
+do_vm.o:	/usr/include/ibm/cpu.h
+do_vm.o:	/usr/include/ibm/interrupt.h
+do_vm.o:	/usr/include/ibm/portio.h
+do_vm.o:	/usr/include/ibm/ports.h
+do_vm.o:	/usr/include/limits.h
+do_vm.o:	/usr/include/minix/com.h
+do_vm.o:	/usr/include/minix/config.h
+do_vm.o:	/usr/include/minix/const.h
+do_vm.o:	/usr/include/minix/ipc.h
+do_vm.o:	/usr/include/minix/sys_config.h
+do_vm.o:	/usr/include/minix/type.h
+do_vm.o:	/usr/include/sys/dir.h
+do_vm.o:	/usr/include/sys/types.h
+do_vm.o:	/usr/include/sys/vm.h
+do_vm.o:	/usr/include/timers.h
+do_vm.o:	do_vm.c
+
+do_vm_setbuf.o:	../config.h
+do_vm_setbuf.o:	../const.h
+do_vm_setbuf.o:	../debug.h
+do_vm_setbuf.o:	../glo.h
+do_vm_setbuf.o:	../ipc.h
+do_vm_setbuf.o:	../kernel.h
+do_vm_setbuf.o:	../priv.h
+do_vm_setbuf.o:	../proc.h
+do_vm_setbuf.o:	../protect.h
+do_vm_setbuf.o:	../proto.h
+do_vm_setbuf.o:	../system.h
+do_vm_setbuf.o:	../type.h
+do_vm_setbuf.o:	/usr/include/ansi.h
+do_vm_setbuf.o:	/usr/include/errno.h
+do_vm_setbuf.o:	/usr/include/ibm/bios.h
+do_vm_setbuf.o:	/usr/include/ibm/cpu.h
+do_vm_setbuf.o:	/usr/include/ibm/interrupt.h
+do_vm_setbuf.o:	/usr/include/ibm/portio.h
+do_vm_setbuf.o:	/usr/include/ibm/ports.h
+do_vm_setbuf.o:	/usr/include/limits.h
+do_vm_setbuf.o:	/usr/include/minix/com.h
+do_vm_setbuf.o:	/usr/include/minix/config.h
+do_vm_setbuf.o:	/usr/include/minix/const.h
+do_vm_setbuf.o:	/usr/include/minix/ipc.h
+do_vm_setbuf.o:	/usr/include/minix/sys_config.h
+do_vm_setbuf.o:	/usr/include/minix/type.h
+do_vm_setbuf.o:	/usr/include/sys/dir.h
+do_vm_setbuf.o:	/usr/include/sys/types.h
+do_vm_setbuf.o:	/usr/include/timers.h
+do_vm_setbuf.o:	do_vm_setbuf.c
Index: /trunk/minix/kernel/system/Makefile
===================================================================
--- /trunk/minix/kernel/system/Makefile	(revision 9)
+++ /trunk/minix/kernel/system/Makefile	(revision 9)
@@ -0,0 +1,153 @@
+# Makefile for system library implementation
+
+# Directories
+u = /usr
+i = $u/include
+
+# Programs, flags, etc.
+CC =	exec cc $(CFLAGS) -c
+CPP =	$l/cpp
+LD =	$(CC) -.o
+CFLAGS = -I$i
+LDFLAGS = -i
+
+SYSTEM	= ../system.a
+
+# What to make.
+all build install: $(SYSTEM)
+
+OBJECTS	= \
+	$(SYSTEM)(do_unused.o) \
+	$(SYSTEM)(do_fork.o) \
+	$(SYSTEM)(do_exec.o) \
+	$(SYSTEM)(do_newmap.o) \
+	$(SYSTEM)(do_exit.o) \
+	$(SYSTEM)(do_trace.o) \
+	$(SYSTEM)(do_nice.o) \
+	$(SYSTEM)(do_times.o) \
+	$(SYSTEM)(do_setalarm.o) \
+	$(SYSTEM)(do_irqctl.o) \
+	$(SYSTEM)(do_devio.o) \
+	$(SYSTEM)(do_vdevio.o) \
+	$(SYSTEM)(do_int86.o) \
+	$(SYSTEM)(do_sdevio.o) \
+	$(SYSTEM)(do_copy.o) \
+	$(SYSTEM)(do_vcopy.o) \
+	$(SYSTEM)(do_umap.o) \
+	$(SYSTEM)(do_memset.o) \
+	$(SYSTEM)(do_privctl.o) \
+	$(SYSTEM)(do_segctl.o) \
+	$(SYSTEM)(do_getksig.o) \
+	$(SYSTEM)(do_endksig.o) \
+	$(SYSTEM)(do_kill.o) \
+	$(SYSTEM)(do_sigsend.o) \
+	$(SYSTEM)(do_sigreturn.o) \
+	$(SYSTEM)(do_abort.o) \
+	$(SYSTEM)(do_getinfo.o) \
+	$(SYSTEM)(do_iopenable.o) \
+	$(SYSTEM)(do_vm.o) \
+	$(SYSTEM)(do_vm_setbuf.o) \
+
+$(SYSTEM):	$(OBJECTS)
+	aal cr $@ *.o
+
+clean:
+	rm -f $(SYSTEM) *.o *~ *.bak 
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
+
+$(SYSTEM)(do_unused.o):	do_unused.c
+	$(CC) do_unused.c
+
+$(SYSTEM)(do_fork.o):	do_fork.c
+	$(CC) do_fork.c
+
+$(SYSTEM)(do_exec.o):	do_exec.c
+	$(CC) do_exec.c
+
+$(SYSTEM)(do_newmap.o):	do_newmap.c
+	$(CC) do_newmap.c
+
+$(SYSTEM)(do_exit.o):	do_exit.c
+	$(CC) do_exit.c
+
+$(SYSTEM)(do_trace.o):	do_trace.c
+	$(CC) do_trace.c
+
+$(SYSTEM)(do_nice.o):	do_nice.c
+	$(CC) do_nice.c
+
+$(SYSTEM)(do_times.o):	do_times.c
+	$(CC) do_times.c
+
+$(SYSTEM)(do_setalarm.o):	do_setalarm.c
+	$(CC) do_setalarm.c
+
+$(SYSTEM)(do_irqctl.o):	do_irqctl.c
+	$(CC) do_irqctl.c
+
+$(SYSTEM)(do_devio.o):	do_devio.c
+	$(CC) do_devio.c
+
+$(SYSTEM)(do_sdevio.o):	do_sdevio.c
+	$(CC) do_sdevio.c
+
+$(SYSTEM)(do_vdevio.o):	do_vdevio.c
+	$(CC) do_vdevio.c
+
+$(SYSTEM)(do_int86.o):	do_int86.c
+	$(CC) do_int86.c
+
+$(SYSTEM)(do_copy.o):	do_copy.c
+	$(CC) do_copy.c
+
+$(SYSTEM)(do_vcopy.o):	do_vcopy.c
+	$(CC) do_vcopy.c
+
+$(SYSTEM)(do_umap.o):	do_umap.c
+	$(CC) do_umap.c
+
+$(SYSTEM)(do_memset.o):	do_memset.c
+	$(CC) do_memset.c
+
+$(SYSTEM)(do_getksig.o):	do_getksig.c
+	$(CC) do_getksig.c
+
+$(SYSTEM)(do_endksig.o):	do_endksig.c
+	$(CC) do_endksig.c
+
+$(SYSTEM)(do_kill.o):	do_kill.c
+	$(CC) do_kill.c
+
+$(SYSTEM)(do_sigsend.o):	do_sigsend.c
+	$(CC) do_sigsend.c
+
+$(SYSTEM)(do_sigreturn.o):	do_sigreturn.c
+	$(CC) do_sigreturn.c
+
+$(SYSTEM)(do_getinfo.o):	do_getinfo.c
+	$(CC) do_getinfo.c
+
+$(SYSTEM)(do_abort.o):	do_abort.c
+	$(CC) do_abort.c
+
+$(SYSTEM)(do_privctl.o):	do_privctl.c
+	$(CC) do_privctl.c
+
+$(SYSTEM)(do_segctl.o):	do_segctl.c
+	$(CC) do_segctl.c
+
+$(SYSTEM)(do_iopenable.o):	do_iopenable.c
+	$(CC) do_iopenable.c
+
+$(SYSTEM)(do_vm.o):	do_vm.o
+do_vm.o:	do_vm.c
+	$(CC) do_vm.c
+
+$(SYSTEM)(do_vm_setbuf.o):	do_vm_setbuf.c
+	$(CC) do_vm_setbuf.c
Index: /trunk/minix/kernel/system/do_abort.c
===================================================================
--- /trunk/minix/kernel/system/do_abort.c	(revision 9)
+++ /trunk/minix/kernel/system/do_abort.c	(revision 9)
@@ -0,0 +1,49 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_ABORT
+ *
+ * The parameters for this kernel call are:
+ *    m1_i1:	ABRT_HOW 	(how to abort, possibly fetch monitor params)	
+ *    m1_i2:	ABRT_MON_PROC 	(proc nr to get monitor params from)	
+ *    m1_i3:	ABRT_MON_LEN	(length of monitor params)
+ *    m1_p1:	ABRT_MON_ADDR 	(virtual address of params)	
+ */
+
+#include "../system.h"
+#include <unistd.h>
+
+#if USE_ABORT
+
+/*===========================================================================*
+ *				do_abort				     *
+ *===========================================================================*/
+PUBLIC int do_abort(m_ptr)
+message *m_ptr;			/* pointer to request message */
+{
+/* Handle sys_abort. MINIX is unable to continue. This can originate e.g.
+ * in the PM (normal abort or panic) or TTY (after CTRL-ALT-DEL).
+ */
+  int how = m_ptr->ABRT_HOW;
+  int proc_nr;
+  int length;
+  phys_bytes src_phys;
+
+  /* See if the monitor is to run the specified instructions. */
+  if (how == RBT_MONITOR) {
+
+      if(!isokendpt(m_ptr->ABRT_MON_ENDPT, &proc_nr)) return(EDEADSRCDST);
+      length = m_ptr->ABRT_MON_LEN + 1;
+      if (length > kinfo.params_size) return(E2BIG);
+      src_phys = numap_local(proc_nr,(vir_bytes)m_ptr->ABRT_MON_ADDR,length);
+      if (! src_phys) return(EFAULT);
+
+      /* Parameters seem ok, copy them and prepare shutting down. */
+      phys_copy(src_phys, kinfo.params_base, (phys_bytes) length);
+  }
+
+  /* Now prepare to shutdown MINIX. */
+  prepare_shutdown(how);
+  return(OK);				/* pro-forma (really EDISASTER) */
+}
+
+#endif /* USE_ABORT */
+
Index: /trunk/minix/kernel/system/do_copy.c
===================================================================
--- /trunk/minix/kernel/system/do_copy.c	(revision 9)
+++ /trunk/minix/kernel/system/do_copy.c	(revision 9)
@@ -0,0 +1,68 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_VIRCOPY, SYS_PHYSCOPY
+ *
+ * The parameters for this kernel call are:
+ *    m5_c1:	CP_SRC_SPACE		source virtual segment
+ *    m5_l1:	CP_SRC_ADDR		source offset within segment
+ *    m5_i1:	CP_SRC_PROC_NR		source process number
+ *    m5_c2:	CP_DST_SPACE		destination virtual segment
+ *    m5_l2:	CP_DST_ADDR		destination offset within segment
+ *    m5_i2:	CP_DST_PROC_NR		destination process number
+ *    m5_l3:	CP_NR_BYTES		number of bytes to copy
+ */
+
+#include "../system.h"
+#include <minix/type.h>
+
+#if (USE_VIRCOPY || USE_PHYSCOPY)
+
+/*===========================================================================*
+ *				do_copy					     *
+ *===========================================================================*/
+PUBLIC int do_copy(m_ptr)
+register message *m_ptr;	/* pointer to request message */
+{
+/* Handle sys_vircopy() and sys_physcopy().  Copy data using virtual or
+ * physical addressing. Although a single handler function is used, there 
+ * are two different kernel calls so that permissions can be checked. 
+ */
+  struct vir_addr vir_addr[2];	/* virtual source and destination address */
+  phys_bytes bytes;		/* number of bytes to copy */
+  int i;
+
+  /* Dismember the command message. */
+  vir_addr[_SRC_].proc_nr_e = m_ptr->CP_SRC_ENDPT;
+  vir_addr[_SRC_].segment = m_ptr->CP_SRC_SPACE;
+  vir_addr[_SRC_].offset = (vir_bytes) m_ptr->CP_SRC_ADDR;
+  vir_addr[_DST_].proc_nr_e = m_ptr->CP_DST_ENDPT;
+  vir_addr[_DST_].segment = m_ptr->CP_DST_SPACE;
+  vir_addr[_DST_].offset = (vir_bytes) m_ptr->CP_DST_ADDR;
+  bytes = (phys_bytes) m_ptr->CP_NR_BYTES;
+
+  /* Now do some checks for both the source and destination virtual address.
+   * This is done once for _SRC_, then once for _DST_. 
+   */
+  for (i=_SRC_; i<=_DST_; i++) {
+	int p;
+      /* Check if process number was given implictly with SELF and is valid. */
+      if (vir_addr[i].proc_nr_e == SELF)
+	vir_addr[i].proc_nr_e = m_ptr->m_source;
+      if (vir_addr[i].segment != PHYS_SEG &&
+	! isokendpt(vir_addr[i].proc_nr_e, &p))
+          return(EINVAL); 
+
+      /* Check if physical addressing is used without SYS_PHYSCOPY. */
+      if ((vir_addr[i].segment & PHYS_SEG) &&
+          m_ptr->m_type != SYS_PHYSCOPY) return(EPERM);
+  }
+
+  /* Check for overflow. This would happen for 64K segments and 16-bit 
+   * vir_bytes. Especially copying by the PM on do_fork() is affected. 
+   */
+  if (bytes != (vir_bytes) bytes) return(E2BIG);
+
+  /* Now try to make the actual virtual copy. */
+  return( virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes) );
+}
+#endif /* (USE_VIRCOPY || USE_PHYSCOPY) */
+
Index: /trunk/minix/kernel/system/do_devio.c
===================================================================
--- /trunk/minix/kernel/system/do_devio.c	(revision 9)
+++ /trunk/minix/kernel/system/do_devio.c	(revision 9)
@@ -0,0 +1,82 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_DEVIO
+ *
+ * The parameters for this kernel call are:
+ *   m2_i3:	DIO_REQUEST	(request input or output)	
+ *   m2_i1:	DIO_TYPE	(flag indicating byte, word, or long)
+ *   m2_l1:	DIO_PORT	(port to read/ write)	
+ *   m2_l2:	DIO_VALUE	(value to write/ return value read)	
+ */
+
+#include "../system.h"
+#include <minix/devio.h>
+#include <minix/endpoint.h>
+
+#if USE_DEVIO
+
+/*===========================================================================*
+ *			        do_devio                                     *
+ *===========================================================================*/
+PUBLIC int do_devio(m_ptr)
+register message *m_ptr;	/* pointer to request message */
+{
+    struct proc *rp;
+    struct priv *privp;
+    port_t port;
+    struct io_range *iorp;
+    int i, size, nr_io_range;
+
+    rp= proc_addr(who_p);
+    privp= priv(rp);
+    if (!privp)
+    {
+	kprintf("no priv structure!\n");
+	goto doit;
+    }
+    if (privp->s_flags & CHECK_IO_PORT)
+    {
+	switch (m_ptr->DIO_TYPE)
+	{
+	case DIO_BYTE: size= 1; break;
+	case DIO_WORD: size= 2; break;
+	case DIO_LONG: size= 4; break;
+	default: size= 4; break;	/* Be conservative */
+	}
+	port= m_ptr->DIO_PORT;
+	nr_io_range= privp->s_nr_io_range;
+	for (i= 0, iorp= privp->s_io_tab; i<nr_io_range; i++, iorp++)
+	{
+		if (port >= iorp->ior_base && port+size-1 <= iorp->ior_limit)
+			break;
+	}
+	if (i >= nr_io_range)
+	{
+		kprintf(
+		"do_devio: I/O port check failed for proc %d, port 0x%x\n",
+			m_ptr->m_source, port);
+		return EPERM;
+	}
+    }
+
+doit:
+
+/* Process a single I/O request for byte, word, and long values. */
+    if (m_ptr->DIO_REQUEST == DIO_INPUT) { 
+      switch (m_ptr->DIO_TYPE) {
+        case DIO_BYTE: m_ptr->DIO_VALUE = inb(m_ptr->DIO_PORT); break; 
+        case DIO_WORD: m_ptr->DIO_VALUE = inw(m_ptr->DIO_PORT); break; 
+        case DIO_LONG: m_ptr->DIO_VALUE = inl(m_ptr->DIO_PORT); break; 
+    	default: return(EINVAL);
+      } 
+    } else { 
+      switch (m_ptr->DIO_TYPE) {
+        case DIO_BYTE: outb(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;  
+        case DIO_WORD: outw(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;  
+        case DIO_LONG: outl(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;  
+    	default: return(EINVAL);
+      } 
+    }
+    return(OK);
+}
+
+#endif /* USE_DEVIO */
Index: /trunk/minix/kernel/system/do_endksig.c
===================================================================
--- /trunk/minix/kernel/system/do_endksig.c	(revision 9)
+++ /trunk/minix/kernel/system/do_endksig.c	(revision 9)
@@ -0,0 +1,44 @@
+/* The kernel call that is implemented in this file:
+ *   m_type:	SYS_ENDKSIG
+ *
+ * The parameters for this kernel call are:
+ *     m2_i1:	SIG_ENDPT  	# process for which PM is done
+ */
+
+#include "../system.h"
+#include <signal.h>
+#include <sys/sigcontext.h>
+
+#if USE_ENDKSIG 
+
+/*===========================================================================*
+ *			      do_endksig				     *
+ *===========================================================================*/
+PUBLIC int do_endksig(m_ptr)
+message *m_ptr;			/* pointer to request message */
+{
+/* Finish up after a kernel type signal, caused by a SYS_KILL message or a 
+ * call to cause_sig by a task. This is called by the PM after processing a
+ * signal it got with SYS_GETKSIG.
+ */
+  register struct proc *rp;
+  int proc;
+
+  /* Get process pointer and verify that it had signals pending. If the 
+   * process is already dead its flags will be reset. 
+   */
+  if(!isokendpt(m_ptr->SIG_ENDPT, &proc))
+    return EINVAL;
+
+  rp = proc_addr(proc);
+  if (! (rp->p_rts_flags & SIG_PENDING)) return(EINVAL);
+
+  /* PM has finished one kernel signal. Perhaps process is ready now? */
+  if (! (rp->p_rts_flags & SIGNALED)) 		/* new signal arrived */
+     if ((rp->p_rts_flags &= ~SIG_PENDING)==0)	/* remove pending flag */
+         lock_enqueue(rp);			/* ready if no flags */
+  return(OK);
+}
+
+#endif /* USE_ENDKSIG */
+
Index: /trunk/minix/kernel/system/do_exec.c
===================================================================
--- /trunk/minix/kernel/system/do_exec.c	(revision 9)
+++ /trunk/minix/kernel/system/do_exec.c	(revision 9)
@@ -0,0 +1,63 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_EXEC
+ *
+ * The parameters for this kernel call are:
+ *    m1_i1:	PR_ENDPT  		(process that did exec call)
+ *    m1_p1:	PR_STACK_PTR		(new stack pointer)
+ *    m1_p2:	PR_NAME_PTR		(pointer to program name)
+ *    m1_p3:	PR_IP_PTR		(new instruction pointer)
+ */
+#include "../system.h"
+#include <string.h>
+#include <signal.h>
+#include <minix/endpoint.h>
+
+#if USE_EXEC
+
+/*===========================================================================*
+ *				do_exec					     *
+ *===========================================================================*/
+PUBLIC int do_exec(m_ptr)
+register message *m_ptr;	/* pointer to request message */
+{
+/* Handle sys_exec().  A process has done a successful EXEC. Patch it up. */
+  register struct proc *rp;
+  reg_t sp;			/* new sp */
+  phys_bytes phys_name;
+  char *np;
+  int proc;
+
+  if(!isokendpt(m_ptr->PR_ENDPT, &proc))
+	return EINVAL;
+
+  rp = proc_addr(proc);
+  sp = (reg_t) m_ptr->PR_STACK_PTR;
+  rp->p_reg.sp = sp;		/* set the stack pointer */
+#if (CHIP == M68000)
+  rp->p_splow = sp;		/* set the stack pointer low water */
+#ifdef FPP
+  /* Initialize fpp for this process */
+  fpp_new_state(rp);
+#endif
+#endif
+#if (CHIP == INTEL)		/* wipe extra LDT entries */
+  phys_memset(vir2phys(&rp->p_ldt[EXTRA_LDT_INDEX]), 0,
+	(LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0]));
+#endif
+  rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR;	/* set pc */
+  rp->p_rts_flags &= ~RECEIVING;	/* PM does not reply to EXEC call */
+  if (rp->p_rts_flags == 0) lock_enqueue(rp);
+  /* Save command name for debugging, ps(1) output, etc. */
+  phys_name = numap_local(who_p, (vir_bytes) m_ptr->PR_NAME_PTR,
+					(vir_bytes) P_NAME_LEN - 1);
+  if (phys_name != 0) {
+	phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) P_NAME_LEN - 1);
+	for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
+	*np = 0;					/* mark end */
+  } else {
+  	strncpy(rp->p_name, "<unset>", P_NAME_LEN);
+  }
+  return(OK);
+}
+#endif /* USE_EXEC */
+
Index: /trunk/minix/kernel/system/do_exit.c
===================================================================
--- /trunk/minix/kernel/system/do_exit.c	(revision 9)
+++ /trunk/minix/kernel/system/do_exit.c	(revision 9)
@@ -0,0 +1,93 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_EXIT
+ *
+ * The parameters for this kernel call are:
+ *    m1_i1:	PR_ENDPT		(slot number of exiting process)
+ */
+
+#include "../system.h"
+
+#include <minix/endpoint.h>
+
+#if USE_EXIT
+
+FORWARD _PROTOTYPE( void clear_proc, (register struct proc *rc));
+
+/*===========================================================================*
+ *				do_exit					     *
+ *===========================================================================*/
+PUBLIC int do_exit(m_ptr)
+message *m_ptr;			/* pointer to request message */
+{
+/* Handle sys_exit. A user process has exited or a system process requests 
+ * to exit. Only the PM can request other process slots to be cleared.
+ * The routine to clean up a process table slot cancels outstanding timers, 
+ * possibly removes the process from the message queues, and resets certain 
+ * process table fields to the default values.
+ */
+  int exit_e;				
+
+  /* Determine what process exited. User processes are handled here. */
+  if (PM_PROC_NR == who_p) {
+      if (m_ptr->PR_ENDPT != SELF) { 		/* PM tries to exit self */
+          if(!isokendpt(m_ptr->PR_ENDPT, &exit_e)) /* get exiting process */
+	     return EINVAL;
+          clear_proc(proc_addr(exit_e));	/* exit a user process */
+          return(OK);				/* report back to PM */
+      }
+  } 
+
+  /* The PM or some other system process requested to be exited. */
+  clear_proc(proc_addr(who_p));
+  return(EDONTREPLY);
+}
+
+/*===========================================================================*
+ *			         clear_proc				     *
+ *===========================================================================*/
+PRIVATE void clear_proc(rc)
+register struct proc *rc;		/* slot of process to clean up */
+{
+  register struct proc *rp;		/* iterate over process table */
+  register struct proc **xpp;		/* iterate over caller queue */
+  int i;
+  int sys_id;
+  char saved_rts_flags;
+
+  /* Don't clear if already cleared. */
+  if(isemptyp(rc)) return;
+
+  /* Remove the process' ability to send and receive messages */
+  clear_endpoint(rc);
+
+  /* Turn off any alarm timers at the clock. */   
+  reset_timer(&priv(rc)->s_alarm_timer);
+
+  /* Make sure that the exiting process is no longer scheduled. */
+  if (rc->p_rts_flags == 0) lock_dequeue(rc);
+
+  /* Check the table with IRQ hooks to see if hooks should be released. */
+  for (i=0; i < NR_IRQ_HOOKS; i++) {
+      int proc;
+      if (rc->p_endpoint == irq_hooks[i].proc_nr_e) { 
+        rm_irq_handler(&irq_hooks[i]);	/* remove interrupt handler */
+        irq_hooks[i].proc_nr_e = NONE;	/* mark hook as free */
+      }
+  }
+
+  /* Release the process table slot. If this is a system process, also
+   * release its privilege structure.  Further cleanup is not needed at
+   * this point. All important fields are reinitialized when the 
+   * slots are assigned to another, new process. 
+   */
+  saved_rts_flags = rc->p_rts_flags;
+  rc->p_rts_flags = SLOT_FREE;		
+  if (priv(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE;
+
+  /* Clean up virtual memory */
+  if (rc->p_misc_flags & MF_VM)
+  	vm_map_default(rc);
+}
+
+#endif /* USE_EXIT */
+
Index: /trunk/minix/kernel/system/do_fork.c
===================================================================
--- /trunk/minix/kernel/system/do_fork.c	(revision 9)
+++ /trunk/minix/kernel/system/do_fork.c	(revision 9)
@@ -0,0 +1,86 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_FORK
+ *
+ * The parameters for this kernel call are:
+ *    m1_i1:	PR_SLOT	 (child's process table slot)	
+ *    m1_i2:	PR_ENDPT (parent, process that forked)	
+ */
+
+#include "../system.h"
+#include <signal.h>
+#if (CHIP == INTEL)
+#include "../protect.h"
+#endif
+
+#include <minix/endpoint.h>
+
+#if USE_FORK
+
+/*===========================================================================*
+ *				do_fork					     *
+ *===========================================================================*/
+PUBLIC int do_fork(m_ptr)
+register message *m_ptr;	/* pointer to request message */
+{
+/* Handle sys_fork().  PR_ENDPT has forked.  The child is PR_SLOT. */
+#if (CHIP == INTEL)
+  reg_t old_ldt_sel;
+#endif
+  register struct proc *rpc;		/* child process pointer */
+  struct proc *rpp;			/* parent process pointer */
+  int i, gen;
+  int p_proc;
+
+  if(!isokendpt(m_ptr->PR_ENDPT, &p_proc))
+	return EINVAL;
+  rpp = proc_addr(p_proc);
+  rpc = proc_addr(m_ptr->PR_SLOT);
+  if (isemptyp(rpp) || ! isemptyp(rpc)) return(EINVAL);
+
+  /* Copy parent 'proc' struct to child. And reinitialize some fields. */
+  gen = _ENDPOINT_G(rpc->p_endpoint);
+#if (CHIP == INTEL)
+  old_ldt_sel = rpc->p_ldt_sel;		/* backup local descriptors */
+  *rpc = *rpp;				/* copy 'proc' struct */
+  rpc->p_ldt_sel = old_ldt_sel;		/* restore descriptors */
+#else
+  *rpc = *rpp;				/* copy 'proc' struct */
+#endif
+  if(++gen >= _ENDPOINT_MAX_GENERATION)	/* increase generation */
+	gen = 1;			/* generation number wraparound */
+  rpc->p_nr = m_ptr->PR_SLOT;		/* this was obliterated by copy */
+  rpc->p_endpoint = _ENDPOINT(gen, rpc->p_nr);	/* new endpoint of slot */
+
+  /* Only one in group should have SIGNALED, child doesn't inherit tracing. */
+  rpc->p_rts_flags |= NO_MAP;		/* inhibit process from running */
+  rpc->p_rts_flags &= ~(SIGNALED | SIG_PENDING | P_STOP);
+  sigemptyset(&rpc->p_pending);
+
+  rpc->p_reg.retreg = 0;	/* child sees pid = 0 to know it is child */
+  rpc->p_user_time = 0;		/* set all the accounting times to 0 */
+  rpc->p_sys_time = 0;
+
+  /* Parent and child have to share the quantum that the forked process had,
+   * so that queued processes do not have to wait longer because of the fork.
+   * If the time left is odd, the child gets an extra tick.
+   */
+  rpc->p_ticks_left = (rpc->p_ticks_left + 1) / 2;
+  rpp->p_ticks_left =  rpp->p_ticks_left / 2;	
+
+  /* If the parent is a privileged process, take away the privileges from the 
+   * child process and inhibit it from running by setting the NO_PRIV flag.
+   * The caller should explicitely set the new privileges before executing.
+   */
+  if (priv(rpp)->s_flags & SYS_PROC) {
+      rpc->p_priv = priv_addr(USER_PRIV_ID);
+      rpc->p_rts_flags |= NO_PRIV;
+  }
+
+  /* Calculate endpoint identifier, so caller knows what it is. */
+  m_ptr->PR_ENDPT = rpc->p_endpoint;
+
+  return(OK);
+}
+
+#endif /* USE_FORK */
+
Index: /trunk/minix/kernel/system/do_getinfo.c
===================================================================
--- /trunk/minix/kernel/system/do_getinfo.c	(revision 9)
+++ /trunk/minix/kernel/system/do_getinfo.c	(revision 9)
@@ -0,0 +1,160 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_GETINFO
+ *
+ * The parameters for this kernel call are:
+ *    m1_i3:	I_REQUEST	(what info to get)	
+ *    m1_p1:	I_VAL_PTR 	(where to put it)	
+ *    m1_i1:	I_VAL_LEN 	(maximum length expected, optional)	
+ *    m1_p2:	I_VAL_PTR2	(second, optional pointer)	
+ *    m1_i2:	I_VAL_LEN2_E	(second length or process nr)	
+ */
+
+#include "../system.h"
+
+static unsigned long bios_buf[1024];	/* 4K, what about alignment */
+static vir_bytes bios_buf_vir, bios_buf_len;
+
+#if USE_GETINFO
+
+/*===========================================================================*
+ *			        do_getinfo				     *
+ *===========================================================================*/
+PUBLIC int do_getinfo(m_ptr)
+register message *m_ptr;	/* pointer to request message */
+{
+/* Request system information to be copied to caller's address space. This
+ * call simply copies entire data structures to the caller.
+ */
+  size_t length;
+  phys_bytes src_phys; 
+  phys_bytes dst_phys; 
+  int proc_nr, nr_e, nr;
+
+  /* Set source address and length based on request type. */
+  switch (m_ptr->I_REQUEST) {	
+    case GET_MACHINE: {
+        length = sizeof(struct machine);
+        src_phys = vir2phys(&machine);
+        break;
+    }
+    case GET_KINFO: {
+        length = sizeof(struct kinfo);
+        src_phys = vir2phys(&kinfo);
+        break;
+    }
+    case GET_LOADINFO: {
+        length = sizeof(struct loadinfo);
+        src_phys = vir2phys(&kloadinfo);
+        break;
+    }
+    case GET_IMAGE: {
+        length = sizeof(struct boot_image) * NR_BOOT_PROCS;
+        src_phys = vir2phys(image);
+        break;
+    }
+    case GET_IRQHOOKS: {
+        length = sizeof(struct irq_hook) * NR_IRQ_HOOKS;
+        src_phys = vir2phys(irq_hooks);
+        break;
+    }
+    case GET_SCHEDINFO: {
+        /* This is slightly complicated because we need two data structures
+         * at once, otherwise the scheduling information may be incorrect.
+         * Copy the queue heads and fall through to copy the process table. 
+         */
+        length = sizeof(struct proc *) * NR_SCHED_QUEUES;
+        src_phys = vir2phys(rdy_head);
+	okendpt(m_ptr->m_source, &proc_nr);
+        dst_phys = numap_local(proc_nr, (vir_bytes) m_ptr->I_VAL_PTR2,
+                length); 
+        if (src_phys == 0 || dst_phys == 0) return(EFAULT);
+        phys_copy(src_phys, dst_phys, length);
+        /* fall through */
+    }
+    case GET_PROCTAB: {
+        length = sizeof(struct proc) * (NR_PROCS + NR_TASKS);
+        src_phys = vir2phys(proc);
+        break;
+    }
+    case GET_PRIVTAB: {
+        length = sizeof(struct priv) * (NR_SYS_PROCS);
+        src_phys = vir2phys(priv);
+        break;
+    }
+    case GET_PROC: {
+        nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ?
+		m_ptr->m_source : m_ptr->I_VAL_LEN2_E;
+	if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
+        length = sizeof(struct proc);
+        src_phys = vir2phys(proc_addr(nr));
+        break;
+    }
+    case GET_MONPARAMS: {
+        src_phys = kinfo.params_base;		/* already is a physical */
+        length = kinfo.params_size;
+        break;
+    }
+    case GET_RANDOMNESS: {		
+        static struct randomness copy;		/* copy to keep counters */
+	int i;
+
+        copy = krandom;
+        for (i= 0; i<RANDOM_SOURCES; i++) {
+  		krandom.bin[i].r_size = 0;	/* invalidate random data */
+  		krandom.bin[i].r_next = 0;
+	}
+    	length = sizeof(struct randomness);
+    	src_phys = vir2phys(&copy);
+    	break;
+    }
+    case GET_KMESSAGES: {
+        length = sizeof(struct kmessages);
+        src_phys = vir2phys(&kmess);
+        break;
+    }
+#if DEBUG_TIME_LOCKS
+    case GET_LOCKTIMING: {
+    length = sizeof(timingdata);
+    src_phys = vir2phys(timingdata);
+    break;
+    }
+#endif
+    case GET_BIOSBUFFER:
+    	bios_buf_vir = (vir_bytes)bios_buf;
+    	bios_buf_len = sizeof(bios_buf);
+
+    	length = sizeof(bios_buf_len);
+    	src_phys = vir2phys(&bios_buf_len);
+	if (length != m_ptr->I_VAL_LEN2_E) return (EINVAL);
+	if(!isokendpt(m_ptr->m_source, &proc_nr))
+		panic("bogus source", m_ptr->m_source);
+	dst_phys = numap_local(proc_nr, (vir_bytes) m_ptr->I_VAL_PTR2, length); 
+	if (src_phys == 0 || dst_phys == 0) return(EFAULT);
+	phys_copy(src_phys, dst_phys, length);
+
+    	length = sizeof(bios_buf_vir);
+    	src_phys = vir2phys(&bios_buf_vir);
+    	break;
+
+    case GET_IRQACTIDS: {
+        length = sizeof(irq_actids);
+        src_phys = vir2phys(irq_actids);
+        break;
+    }
+
+    default:
+        return(EINVAL);
+  }
+
+  /* Try to make the actual copy for the requested data. */
+  if (m_ptr->I_VAL_LEN > 0 && length > m_ptr->I_VAL_LEN) return (E2BIG);
+  if(!isokendpt(m_ptr->m_source, &proc_nr)) 
+	panic("bogus source", m_ptr->m_source);
+  dst_phys = numap_local(proc_nr, (vir_bytes) m_ptr->I_VAL_PTR, length); 
+  if (src_phys == 0 || dst_phys == 0) return(EFAULT);
+  phys_copy(src_phys, dst_phys, length);
+  return(OK);
+}
+
+#endif /* USE_GETINFO */
+
Index: /trunk/minix/kernel/system/do_getksig.c
===================================================================
--- /trunk/minix/kernel/system/do_getksig.c	(revision 9)
+++ /trunk/minix/kernel/system/do_getksig.c	(revision 9)
@@ -0,0 +1,47 @@
+/* The kernel call that is implemented in this file:
+ *   m_type:	SYS_GETKSIG
+ *
+ * The parameters for this kernel call are:
+ *     m2_i1:	SIG_ENDPT  	# process with pending signals
+ *     m2_l1:	SIG_MAP		# bit map with pending signals
+ */
+
+#include "../system.h"
+#include <signal.h>
+#include <sys/sigcontext.h>
+#include <minix/endpoint.h>
+
+#if USE_GETKSIG
+
+/*===========================================================================*
+ *			      do_getksig				     *
+ *===========================================================================*/
+PUBLIC int do_getksig(m_ptr)
+message *m_ptr;			/* pointer to request message */
+{
+/* PM is ready to accept signals and repeatedly does a kernel call to get 
+ * one. Find a process with pending signals. If no signals are available, 
+ * return NONE in the process number field.
+ * It is not sufficient to ready the process when PM is informed, because 
+ * PM can block waiting for FS to do a core dump.
+ */
+  register struct proc *rp;
+
+  /* Find the next process with pending signals. */
+  for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) {
+      if (rp->p_rts_flags & SIGNALED) {
+	  /* store signaled process' endpoint */
+          m_ptr->SIG_ENDPT = rp->p_endpoint;
+          m_ptr->SIG_MAP = rp->p_pending;	/* pending signals map */
+          sigemptyset(&rp->p_pending); 		/* ball is in PM's court */
+          rp->p_rts_flags &= ~SIGNALED;		/* blocked by SIG_PENDING */
+          return(OK);
+      }
+  }
+
+  /* No process with pending signals was found. */
+  m_ptr->SIG_ENDPT = NONE; 
+  return(OK);
+}
+#endif /* USE_GETKSIG */
+
Index: /trunk/minix/kernel/system/do_int86.c
===================================================================
--- /trunk/minix/kernel/system/do_int86.c	(revision 9)
+++ /trunk/minix/kernel/system/do_int86.c	(revision 9)
@@ -0,0 +1,45 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_INT86
+ *
+ * The parameters for this kernel call are:
+ *    m1_p1:	INT86_REG86     
+ */
+
+#include "../system.h"
+#include <minix/type.h>
+#include <minix/endpoint.h>
+#include <ibm/int86.h>
+
+struct reg86u reg86;
+
+/*===========================================================================*
+ *				do_int86					     *
+ *===========================================================================*/
+PUBLIC int do_int86(m_ptr)
+register message *m_ptr;	/* pointer to request message */
+{
+  vir_bytes caller_vir;
+  phys_bytes caller_phys, kernel_phys;
+
+  caller_vir = (vir_bytes) m_ptr->INT86_REG86;
+  caller_phys = umap_local(proc_addr(who_p), D, caller_vir, sizeof(reg86));
+  if (0 == caller_phys) return(EFAULT);
+  kernel_phys = vir2phys(&reg86);
+  phys_copy(caller_phys, kernel_phys, (phys_bytes) sizeof(reg86));
+
+  level0(int86);
+
+  /* Copy results back to the caller */
+  phys_copy(kernel_phys, caller_phys, (phys_bytes) sizeof(reg86));
+
+  /* The BIOS call eats interrupts. Call get_randomness to generate some
+   * entropy. Normally, get_randomness is called from an interrupt handler.
+   * Figuring out the exact source is too complicated. CLOCK_IRQ is normally
+   * not very random.
+   */
+  lock(0, "do_int86");
+  get_randomness(CLOCK_IRQ);
+  unlock(0);
+
+  return(OK);
+}
Index: /trunk/minix/kernel/system/do_iopenable.c
===================================================================
--- /trunk/minix/kernel/system/do_iopenable.c	(revision 9)
+++ /trunk/minix/kernel/system/do_iopenable.c	(revision 9)
@@ -0,0 +1,34 @@
+/* The system call implemented in this file:
+ *   m_type:	SYS_IOPENABLE
+ *
+ * The parameters for this system call are:
+ *    m2_i2:	IO_ENDPT	(process to give I/O Protection Level bits)
+ *
+ * Author:
+ *    Jorrit N. Herder <jnherder@cs.vu.nl>
+ */
+
+#include "../system.h"
+#include "../kernel.h"
+
+/*===========================================================================*
+ *			        do_iopenable				     *
+ *===========================================================================*/
+PUBLIC int do_iopenable(m_ptr)
+register message *m_ptr;	/* pointer to request message */
+{
+  int proc_nr;
+
+#if 1 /* ENABLE_USERPRIV && ENABLE_USERIOPL */
+  if (m_ptr->IO_ENDPT == SELF) {
+	proc_nr = who_p;
+  } else if(!isokendpt(m_ptr->IO_ENDPT, &proc_nr))
+	return(EINVAL);
+  enable_iop(proc_addr(proc_nr));
+  return(OK);
+#else
+  return(EPERM);
+#endif
+}
+
+
Index: /trunk/minix/kernel/system/do_irqctl.c
===================================================================
--- /trunk/minix/kernel/system/do_irqctl.c	(revision 9)
+++ /trunk/minix/kernel/system/do_irqctl.c	(revision 9)
@@ -0,0 +1,167 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_IRQCTL
+ *
+ * The parameters for this kernel call are:
+ *    m5_c1:	IRQ_REQUEST	(control operation to perform)	
+ *    m5_c2:	IRQ_VECTOR	(irq line that must be controlled)
+ *    m5_i1:	IRQ_POLICY	(irq policy allows reenabling interrupts)
+ *    m5_l3:	IRQ_HOOK_ID	(provides index to be returned on interrupt)
+ *      ,,          ,,          (returns index of irq hook assigned at kernel)
+ */
+
+#include "../system.h"
+
+#include <minix/endpoint.h>
+
+#if USE_IRQCTL
+
+FORWARD _PROTOTYPE(int generic_handler, (irq_hook_t *hook));
+
+/*===========================================================================*
+ *				do_irqctl				     *
+ *===========================================================================*/
+PUBLIC int do_irqctl(m_ptr)
+register message *m_ptr;	/* pointer to request message */
+{
+  /* Dismember the request message. */
+  int irq_vec;
+  int irq_hook_id;
+  int notify_id;
+  int r = OK;
+  int i;
+  irq_hook_t *hook_ptr;
+  struct proc *rp;
+  struct priv *privp;
+
+  /* Hook identifiers start at 1 and end at NR_IRQ_HOOKS. */
+  irq_hook_id = (unsigned) m_ptr->IRQ_HOOK_ID - 1;
+  irq_vec = (unsigned) m_ptr->IRQ_VECTOR; 
+
+  /* See what is requested and take needed actions. */
+  switch(m_ptr->IRQ_REQUEST) {
+
+  /* Enable or disable IRQs. This is straightforward. */
+  case IRQ_ENABLE:           
+  case IRQ_DISABLE: 
+      if (irq_hook_id >= NR_IRQ_HOOKS || irq_hook_id < 0 ||
+          irq_hooks[irq_hook_id].proc_nr_e == NONE) return(EINVAL);
+      if (irq_hooks[irq_hook_id].proc_nr_e != m_ptr->m_source) return(EPERM);
+      if (m_ptr->IRQ_REQUEST == IRQ_ENABLE)
+          enable_irq(&irq_hooks[irq_hook_id]);	
+      else 
+          disable_irq(&irq_hooks[irq_hook_id]);	
+      break;
+
+  /* Control IRQ policies. Set a policy and needed details in the IRQ table.
+   * This policy is used by a generic function to handle hardware interrupts. 
+   */
+  case IRQ_SETPOLICY:  
+
+      /* Check if IRQ line is acceptable. */
+      if (irq_vec < 0 || irq_vec >= NR_IRQ_VECTORS) return(EINVAL);
+
+      rp= proc_addr(who_p);
+      privp= priv(rp);
+      if (!privp)
+      {
+	kprintf("no priv structure!\n");
+	return EPERM;
+      }
+      if (privp->s_flags & CHECK_IRQ)
+      {
+	for (i= 0; i<privp->s_nr_irq; i++)
+	{
+		if (irq_vec == privp->s_irq_tab[i])
+			break;
+	}
+	if (i >= privp->s_nr_irq)
+	{
+		kprintf(
+		"do_irqctl: IRQ check failed for proc %d, IRQ %d\n",
+			m_ptr->m_source, irq_vec);
+		return EPERM;
+	}
+    }
+
+      /* Find a free IRQ hook for this mapping. */
+      hook_ptr = NULL;
+      for (irq_hook_id=0; irq_hook_id<NR_IRQ_HOOKS; irq_hook_id++) {
+          if (irq_hooks[irq_hook_id].proc_nr_e == NONE) {	
+              hook_ptr = &irq_hooks[irq_hook_id];	/* free hook */
+              break;
+          }
+      }
+      if (hook_ptr == NULL) return(ENOSPC);
+
+      /* When setting a policy, the caller must provide an identifier that
+       * is returned on the notification message if a interrupt occurs.
+       */
+      notify_id = (unsigned) m_ptr->IRQ_HOOK_ID;
+      if (notify_id > CHAR_BIT * sizeof(irq_id_t) - 1) return(EINVAL);
+
+      /* Install the handler. */
+      hook_ptr->proc_nr_e = m_ptr->m_source;	/* process to notify */   	
+      hook_ptr->notify_id = notify_id;		/* identifier to pass */   	
+      hook_ptr->policy = m_ptr->IRQ_POLICY;	/* policy for interrupts */
+      put_irq_handler(hook_ptr, irq_vec, generic_handler);
+
+      /* Return index of the IRQ hook in use. */
+      m_ptr->IRQ_HOOK_ID = irq_hook_id + 1;
+      break;
+
+  case IRQ_RMPOLICY:
+      if (irq_hook_id < 0 || irq_hook_id >= NR_IRQ_HOOKS ||
+               irq_hooks[irq_hook_id].proc_nr_e == NONE) {
+           return(EINVAL);
+      } else if (m_ptr->m_source != irq_hooks[irq_hook_id].proc_nr_e) {
+           return(EPERM);
+      }
+      /* Remove the handler and return. */
+      rm_irq_handler(&irq_hooks[irq_hook_id]);
+      break;
+
+  default:
+      r = EINVAL;				/* invalid IRQ_REQUEST */
+  }
+  return(r);
+}
+
+/*===========================================================================*
+ *			       generic_handler				     *
+ *===========================================================================*/
+PRIVATE int generic_handler(hook)
+irq_hook_t *hook;	
+{
+/* This function handles hardware interrupt in a simple and generic way. All
+ * interrupts are transformed into messages to a driver. The IRQ line will be
+ * reenabled if the policy says so.
+ */
+  int proc;
+
+  /* As a side-effect, the interrupt handler gathers random information by 
+   * timestamping the interrupt events. This is used for /dev/random.
+   */
+  get_randomness(hook->irq);
+
+  /* Check if the handler is still alive. If not, forget about the
+   * interrupt. This should never happen, as processes that die 
+   * automatically get their interrupt hooks unhooked.
+   */
+  if(!isokendpt(hook->proc_nr_e, &proc)) {
+     hook->proc_nr_e = NONE;
+     return 0;
+  }
+
+  /* Add a bit for this interrupt to the process' pending interrupts. When 
+   * sending the notification message, this bit map will be magically set
+   * as an argument. 
+   */
+  priv(proc_addr(proc))->s_int_pending |= (1 << hook->notify_id);
+
+  /* Build notification message and return. */
+  lock_notify(HARDWARE, hook->proc_nr_e);
+  return(hook->policy & IRQ_REENABLE);
+}
+
+#endif /* USE_IRQCTL */
+
Index: /trunk/minix/kernel/system/do_kill.c
===================================================================
--- /trunk/minix/kernel/system/do_kill.c	(revision 9)
+++ /trunk/minix/kernel/system/do_kill.c	(revision 9)
@@ -0,0 +1,50 @@
+/* The kernel call that is implemented in this file:
+ *   m_type:	SYS_KILL
+ *
+ * The parameters for this kernel call are:
+ *     m2_i1:	SIG_ENDPT  	# process to signal/ pending		
+ *     m2_i2:	SIG_NUMBER	# signal number to send to process
+ */
+
+#include "../system.h"
+#include <signal.h>
+#include <sys/sigcontext.h>
+
+#if USE_KILL
+
+/*===========================================================================*
+ *			          do_kill				     *
+ *===========================================================================*/
+PUBLIC int do_kill(m_ptr)
+message *m_ptr;			/* pointer to request message */
+{
+/* Handle sys_kill(). Cause a signal to be sent to a process. The PM is the
+ * central server where all signals are processed and handler policies can
+ * be registered. Any request, except for PM requests, is added to the map
+ * of pending signals and the PM is informed about the new signal.
+ * Since system servers cannot use normal POSIX signal handlers (because they
+ * are usually blocked on a RECEIVE), they can request the PM to transform 
+ * signals into messages. This is done by the PM with a call to sys_kill(). 
+ */
+  proc_nr_t proc_nr, proc_nr_e;
+  int sig_nr = m_ptr->SIG_NUMBER;
+
+  proc_nr_e= m_ptr->SIG_ENDPT;
+	
+  if (proc_nr_e == SELF)
+	proc_nr_e= m_ptr->m_source;
+
+  if (!isokendpt(proc_nr_e, &proc_nr)) return(EINVAL);
+
+  if (sig_nr > _NSIG) return(EINVAL);
+  if (iskerneln(proc_nr)) return(EPERM);
+
+  /* Set pending signal to be processed by the PM. */
+  cause_sig(proc_nr, sig_nr);
+  if (sig_nr == SIGKILL)
+	clear_endpoint(proc_addr(proc_nr));
+  return(OK);
+}
+
+#endif /* USE_KILL */
+
Index: /trunk/minix/kernel/system/do_memset.c
===================================================================
--- /trunk/minix/kernel/system/do_memset.c	(revision 9)
+++ /trunk/minix/kernel/system/do_memset.c	(revision 9)
@@ -0,0 +1,29 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_MEMSET
+ *
+ * The parameters for this kernel call are:
+ *    m2_p1:	MEM_PTR		(virtual address)	
+ *    m2_l1:	MEM_COUNT	(returns physical address)	
+ *    m2_l2:	MEM_PATTERN	(size of datastructure) 	
+ */
+
+#include "../system.h"
+
+#if USE_MEMSET
+
+/*===========================================================================*
+ *				do_memset				     *
+ *===========================================================================*/
+PUBLIC int do_memset(m_ptr)
+register message *m_ptr;
+{
+/* Handle sys_memset(). This writes a pattern into the specified memory. */
+  unsigned long p;
+  unsigned char c = m_ptr->MEM_PATTERN;
+  p = c | (c << 8) | (c << 16) | (c << 24);
+  phys_memset((phys_bytes) m_ptr->MEM_PTR, p, (phys_bytes) m_ptr->MEM_COUNT);
+  return(OK);
+}
+
+#endif /* USE_MEMSET */
+
Index: /trunk/minix/kernel/system/do_newmap.c
===================================================================
--- /trunk/minix/kernel/system/do_newmap.c	(revision 9)
+++ /trunk/minix/kernel/system/do_newmap.c	(revision 9)
@@ -0,0 +1,49 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_NEWMAP
+ *
+ * The parameters for this kernel call are:
+ *    m1_i1:	PR_ENDPT		(install new map for this process)
+ *    m1_p1:	PR_MEM_PTR		(pointer to the new memory map)
+ */
+#include "../system.h"
+#include <minix/endpoint.h>
+
+#if USE_NEWMAP
+
+/*===========================================================================*
+ *				do_newmap				     *
+ *===========================================================================*/
+PUBLIC int do_newmap(m_ptr)
+message *m_ptr;			/* pointer to request message */
+{
+/* Handle sys_newmap().  Fetch the memory map from PM. */
+  register struct proc *rp;	/* process whose map is to be loaded */
+  struct mem_map *map_ptr;	/* virtual address of map inside caller (PM) */
+  phys_bytes src_phys;		/* physical address of map at the PM */
+  int old_flags;		/* value of flags before modification */
+  int proc;
+
+  map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR;
+  if (! isokendpt(m_ptr->PR_ENDPT, &proc)) return(EINVAL);
+  if (iskerneln(proc)) return(EPERM);
+  rp = proc_addr(proc);
+
+  /* Copy the map from PM. */
+  src_phys = umap_local(proc_addr(who_p), D, (vir_bytes) map_ptr, 
+      sizeof(rp->p_memmap));
+  if (src_phys == 0) return(EFAULT);
+  phys_copy(src_phys,vir2phys(rp->p_memmap),(phys_bytes)sizeof(rp->p_memmap));
+
+#if (CHIP != M68000)
+  alloc_segments(rp);
+#else
+  pmmu_init_proc(rp);
+#endif
+  old_flags = rp->p_rts_flags;	/* save the previous value of the flags */
+  rp->p_rts_flags &= ~NO_MAP;
+  if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp);
+
+  return(OK);
+}
+#endif /* USE_NEWMAP */
+
Index: /trunk/minix/kernel/system/do_nice.c
===================================================================
--- /trunk/minix/kernel/system/do_nice.c	(revision 9)
+++ /trunk/minix/kernel/system/do_nice.c	(revision 9)
@@ -0,0 +1,61 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_NICE
+ *
+ * The parameters for this kernel call are:
+ *    m1_i1:	PR_ENDPT   	process number to change priority
+ *    m1_i2:	PR_PRIORITY	the new priority
+ */
+
+#include "../system.h"
+#include <minix/type.h>
+#include <sys/resource.h>
+
+#if USE_NICE
+
+/*===========================================================================*
+ *				  do_nice				     *
+ *===========================================================================*/
+PUBLIC int do_nice(message *m_ptr)
+{
+/* Change process priority or stop the process. */
+  int proc_nr, pri, new_q ;
+  register struct proc *rp;
+
+  /* Extract the message parameters and do sanity checking. */
+  if(!isokendpt(m_ptr->PR_ENDPT, &proc_nr)) return EINVAL;
+  if (iskerneln(proc_nr)) return(EPERM);
+  pri = m_ptr->PR_PRIORITY;
+  rp = proc_addr(proc_nr);
+
+  if (pri == PRIO_STOP) {
+
+      /* Take process off the scheduling queues. */
+      lock_dequeue(rp);
+      rp->p_rts_flags |= NO_PRIORITY;
+      return(OK);
+  }
+  else if (pri >= PRIO_MIN && pri <= PRIO_MAX) {
+
+      /* The value passed in is currently between PRIO_MIN and PRIO_MAX. 
+       * We have to scale this between MIN_USER_Q and MAX_USER_Q to match 
+       * the kernel's scheduling queues.
+       */
+      new_q = MAX_USER_Q + (pri-PRIO_MIN) * (MIN_USER_Q-MAX_USER_Q+1) / 
+          (PRIO_MAX-PRIO_MIN+1);
+      if (new_q < MAX_USER_Q) new_q = MAX_USER_Q;	/* shouldn't happen */
+      if (new_q > MIN_USER_Q) new_q = MIN_USER_Q;	/* shouldn't happen */
+
+      /* Make sure the process is not running while changing its priority. 
+       * Put the process back in its new queue if it is runnable.
+       */
+      lock_dequeue(rp);
+      rp->p_max_priority = rp->p_priority = new_q;
+      if (! rp->p_rts_flags) lock_enqueue(rp);
+
+      return(OK);
+  }
+  return(EINVAL);
+}
+
+#endif /* USE_NICE */
+
Index: /trunk/minix/kernel/system/do_privctl.c
===================================================================
--- /trunk/minix/kernel/system/do_privctl.c	(revision 9)
+++ /trunk/minix/kernel/system/do_privctl.c	(revision 9)
@@ -0,0 +1,171 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_PRIVCTL
+ *
+ * The parameters for this kernel call are:
+ *    m1_i1:	PR_ENDPT 	(process number of caller)	
+ */
+
+#include "../system.h"
+#include "../ipc.h"
+#include <signal.h>
+
+#if USE_PRIVCTL
+
+#define FILLED_MASK	(~0)
+
+/*===========================================================================*
+ *				do_privctl				     *
+ *===========================================================================*/
+PUBLIC int do_privctl(m_ptr)
+message *m_ptr;			/* pointer to request message */
+{
+/* Handle sys_privctl(). Update a process' privileges. If the process is not
+ * yet a system process, make sure it gets its own privilege structure.
+ */
+  register struct proc *caller_ptr;
+  register struct proc *rp;
+  register struct priv *sp;
+  int proc_nr;
+  int priv_id;
+  int old_flags;
+  int i;
+  phys_bytes caller_phys, kernel_phys;
+  struct io_range io_range;
+  struct mem_range mem_range;
+
+  /* Check whether caller is allowed to make this call. Privileged proceses 
+   * can only update the privileges of processes that are inhibited from 
+   * running by the NO_PRIV flag. This flag is set when a privileged process
+   * forks. 
+   */
+  caller_ptr = proc_addr(who_p);
+  if (! (priv(caller_ptr)->s_flags & SYS_PROC)) return(EPERM); 
+  if(!isokendpt(m_ptr->PR_ENDPT, &proc_nr)) return(EINVAL);
+  rp = proc_addr(proc_nr);
+
+  switch(m_ptr->CTL_REQUEST)
+  {
+  case SYS_PRIV_INIT:
+	if (! (rp->p_rts_flags & NO_PRIV)) return(EPERM);
+
+	/* Make sure this process has its own privileges structure. This may
+	 * fail, since there are only a limited number of system processes.
+	 * Then copy the privileges from the caller and restore some defaults.
+	 */
+	if ((i=get_priv(rp, SYS_PROC)) != OK) return(i);
+	priv_id = priv(rp)->s_id;		/* backup privilege id */
+	*priv(rp) = *priv(caller_ptr);		/* copy from caller */
+	priv(rp)->s_id = priv_id;		/* restore privilege id */
+	priv(rp)->s_proc_nr = proc_nr;		/* reassociate process nr */
+
+	for (i=0; i< BITMAP_CHUNKS(NR_SYS_PROCS); i++)	/* remove pending: */
+	      priv(rp)->s_notify_pending.chunk[i] = 0;	/* - notifications */
+	priv(rp)->s_int_pending = 0;			/* - interrupts */
+	sigemptyset(&priv(rp)->s_sig_pending);		/* - signals */
+
+	/* Now update the process' privileges as requested. */
+	rp->p_priv->s_trap_mask = FILLED_MASK;
+	for (i=0; i<BITMAP_CHUNKS(NR_SYS_PROCS); i++) {
+		rp->p_priv->s_ipc_to.chunk[i] = FILLED_MASK;
+	}
+	unset_sys_bit(rp->p_priv->s_ipc_to, USER_PRIV_ID);
+
+	/* All process that this process can send to must be able to reply. 
+	 * Therefore, their send masks should be updated as well. 
+	 */
+	for (i=0; i<NR_SYS_PROCS; i++) {
+	    if (get_sys_bit(rp->p_priv->s_ipc_to, i)) {
+		  set_sys_bit(priv_addr(i)->s_ipc_to, priv_id(rp));
+	    }
+	}
+
+	/* No I/O resources, no memory resources, no IRQs */
+	priv(rp)->s_nr_io_range= 0;
+	priv(rp)->s_nr_mem_range= 0;
+	priv(rp)->s_nr_irq= 0;
+
+	/* Done. Privileges have been set. Allow process to run again. */
+	old_flags = rp->p_rts_flags;		/* save value of the flags */
+	rp->p_rts_flags &= ~NO_PRIV; 		
+	if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp);
+	return(OK);
+  case SYS_PRIV_ADD_IO:
+	if (rp->p_rts_flags & NO_PRIV)
+		return(EPERM);
+
+	/* Only system processes get I/O resources? */
+	if (!(priv(rp)->s_flags & SYS_PROC))
+		return EPERM;
+
+	/* Get the I/O range */
+	caller_phys = umap_local(caller_ptr, D, (vir_bytes) m_ptr->CTL_ARG_PTR,
+		sizeof(io_range));
+	if (caller_phys == 0)
+		return EFAULT;
+	kernel_phys = vir2phys(&io_range);
+	phys_copy(caller_phys, kernel_phys, sizeof(io_range));
+	priv(rp)->s_flags |= CHECK_IO_PORT;	/* Check I/O accesses */
+	i= priv(rp)->s_nr_io_range;
+	if (i >= NR_IO_RANGE)
+		return ENOMEM;
+
+	priv(rp)->s_io_tab[i].ior_base= io_range.ior_base;
+	priv(rp)->s_io_tab[i].ior_limit= io_range.ior_limit;
+	priv(rp)->s_nr_io_range++;
+
+	return OK;
+
+  case SYS_PRIV_ADD_MEM:
+	if (rp->p_rts_flags & NO_PRIV)
+		return(EPERM);
+
+	/* Only system processes get memory resources? */
+	if (!(priv(rp)->s_flags & SYS_PROC))
+		return EPERM;
+
+	/* Get the memory range */
+	caller_phys = umap_local(caller_ptr, D, (vir_bytes) m_ptr->CTL_ARG_PTR,
+		sizeof(mem_range));
+	if (caller_phys == 0)
+		return EFAULT;
+	kernel_phys = vir2phys(&mem_range);
+	phys_copy(caller_phys, kernel_phys, sizeof(mem_range));
+	priv(rp)->s_flags |= CHECK_MEM;	/* Check I/O accesses */
+	i= priv(rp)->s_nr_mem_range;
+	if (i >= NR_MEM_RANGE)
+		return ENOMEM;
+
+#if 0
+	priv(rp)->s_mem_tab[i].mr_base= mem_range.mr_base;
+	priv(rp)->s_mem_tab[i].mr_limit= mem_range.mr_limit;
+	priv(rp)->s_nr_mem_range++;
+#endif
+
+	return OK;
+
+  case SYS_PRIV_ADD_IRQ:
+	if (rp->p_rts_flags & NO_PRIV)
+		return(EPERM);
+
+	/* Only system processes get IRQs? */
+	if (!(priv(rp)->s_flags & SYS_PROC))
+		return EPERM;
+
+	priv(rp)->s_flags |= CHECK_IRQ;	/* Check IRQs */
+
+	i= priv(rp)->s_nr_irq;
+	if (i >= NR_IRQ)
+		return ENOMEM;
+	priv(rp)->s_irq_tab[i]= m_ptr->CTL_MM_PRIV;
+	priv(rp)->s_nr_irq++;
+
+	return OK;
+
+  default:
+	kprintf("do_privctl: bad request %d\n", m_ptr->CTL_REQUEST);
+	return EINVAL;
+  }
+}
+
+#endif /* USE_PRIVCTL */
+
Index: /trunk/minix/kernel/system/do_sdevio.c
===================================================================
--- /trunk/minix/kernel/system/do_sdevio.c	(revision 9)
+++ /trunk/minix/kernel/system/do_sdevio.c	(revision 9)
@@ -0,0 +1,66 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_SDEVIO
+ *
+ * The parameters for this kernel call are:
+ *    m2_i3:	DIO_REQUEST	(request input or output)	
+ *    m2_i1:	DIO_TYPE	(flag indicating byte, word, or long)
+ *    m2_l1:	DIO_PORT	(port to read/ write)	
+ *    m2_p1:	DIO_VEC_ADDR	(virtual address of buffer)	
+ *    m2_l2:	DIO_VEC_SIZE	(number of elements)	
+ *    m2_i2:	DIO_VEC_PROC	(process where buffer is)	
+ */
+
+#include "../system.h"
+#include <minix/devio.h>
+#include <minix/endpoint.h>
+
+#if USE_SDEVIO
+
+/*===========================================================================*
+ *			        do_sdevio                                    *
+ *===========================================================================*/
+PUBLIC int do_sdevio(m_ptr)
+register message *m_ptr;	/* pointer to request message */
+{
+  int proc_nr, proc_nr_e = m_ptr->DIO_VEC_ENDPT;
+  int count = m_ptr->DIO_VEC_SIZE;
+  long port = m_ptr->DIO_PORT;
+  phys_bytes phys_buf;
+
+  /* Check if process endpoint is OK. 
+   * A driver may directly provide a pointer to a buffer at the user-process
+   * that initiated the device I/O. Kernel processes, of course, are denied.
+   */
+  if (proc_nr_e == SELF)
+	proc_nr = who_p;
+  else
+	if(!isokendpt(proc_nr_e, &proc_nr))
+		return(EINVAL);
+  if (iskerneln(proc_nr)) return(EPERM);
+
+  /* Get and check physical address. */
+  if ((phys_buf = numap_local(proc_nr, (vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0)
+      return(EFAULT);
+
+  /* Perform device I/O for bytes and words. Longs are not supported. */
+  if (m_ptr->DIO_REQUEST == DIO_INPUT) { 
+      switch (m_ptr->DIO_TYPE) {
+      case DIO_BYTE: phys_insb(port, phys_buf, count); break; 
+      case DIO_WORD: phys_insw(port, phys_buf, count); break; 
+      default: return(EINVAL);
+      } 
+  } else if (m_ptr->DIO_REQUEST == DIO_OUTPUT) { 
+      switch (m_ptr->DIO_TYPE) {
+      case DIO_BYTE: phys_outsb(port, phys_buf, count); break; 
+      case DIO_WORD: phys_outsw(port, phys_buf, count); break; 
+      default: return(EINVAL);
+      } 
+  }
+  else {
+      return(EINVAL);
+  }
+  return(OK);
+}
+
+#endif /* USE_SDEVIO */
+
Index: /trunk/minix/kernel/system/do_segctl.c
===================================================================
--- /trunk/minix/kernel/system/do_segctl.c	(revision 9)
+++ /trunk/minix/kernel/system/do_segctl.c	(revision 9)
@@ -0,0 +1,80 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_SEGCTL
+ *
+ * The parameters for this kernel call are:
+ *    m4_l3:	SEG_PHYS	(physical base address)
+ *    m4_l4:	SEG_SIZE	(size of segment)
+ *    m4_l1:	SEG_SELECT	(return segment selector here)
+ *    m4_l2:	SEG_OFFSET	(return offset within segment here)
+ *    m4_l5:	SEG_INDEX	(return index into remote memory map here)
+ */
+#include "../system.h"
+#include "../protect.h"
+
+#if USE_SEGCTL
+
+/*===========================================================================*
+ *			        do_segctl				     *
+ *===========================================================================*/
+PUBLIC int do_segctl(m_ptr)
+register message *m_ptr;	/* pointer to request message */
+{
+/* Return a segment selector and offset that can be used to reach a physical
+ * address, for use by a driver doing memory I/O in the A0000 - DFFFF range.
+ */
+  u16_t selector;
+  vir_bytes offset;
+  int i, index;
+  register struct proc *rp;
+  phys_bytes phys = (phys_bytes) m_ptr->SEG_PHYS;
+  vir_bytes size = (vir_bytes) m_ptr->SEG_SIZE;
+  int result;
+
+  /* First check if there is a slot available for this segment. */
+  rp = proc_addr(who_p);
+  index = -1;
+  for (i=0; i < NR_REMOTE_SEGS; i++) {
+      if (! rp->p_priv->s_farmem[i].in_use) {
+          index = i; 
+          rp->p_priv->s_farmem[i].in_use = TRUE;
+          rp->p_priv->s_farmem[i].mem_phys = phys;
+          rp->p_priv->s_farmem[i].mem_len = size;
+          break;
+      }
+  }
+  if (index < 0) return(ENOSPC);
+
+  if (! machine.prot) {
+      selector = phys / HCLICK_SIZE;
+      offset = phys % HCLICK_SIZE;
+      result = OK;
+  } else {
+      /* Check if the segment size can be recorded in bytes, that is, check
+       * if descriptor's limit field can delimited the allowed memory region
+       * precisely. This works up to 1MB. If the size is larger, 4K pages
+       * instead of bytes are used.
+       */
+      if (size < BYTE_GRAN_MAX) {
+          init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys, size, 
+          	USER_PRIVILEGE);
+          selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
+          offset = 0;
+          result = OK;
+      } else {
+          init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys & ~0xFFFF, 0, 
+          	USER_PRIVILEGE);
+          selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
+          offset = phys & 0xFFFF;
+          result = OK;
+      }
+  }
+
+  /* Request successfully done. Now return the result. */
+  m_ptr->SEG_INDEX = index | REMOTE_SEG;
+  m_ptr->SEG_SELECT = selector;
+  m_ptr->SEG_OFFSET = offset;
+  return(result);
+}
+
+#endif /* USE_SEGCTL */
+
Index: /trunk/minix/kernel/system/do_setalarm.c
===================================================================
--- /trunk/minix/kernel/system/do_setalarm.c	(revision 9)
+++ /trunk/minix/kernel/system/do_setalarm.c	(revision 9)
@@ -0,0 +1,74 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_SETALARM 
+ *
+ * The parameters for this kernel call are:
+ *    m2_l1:	ALRM_EXP_TIME		(alarm's expiration time)
+ *    m2_i2:	ALRM_ABS_TIME		(expiration time is absolute?)
+ *    m2_l1:	ALRM_TIME_LEFT		(return seconds left of previous)
+ */
+
+#include "../system.h"
+
+#include <minix/endpoint.h>
+
+#if USE_SETALARM
+
+FORWARD _PROTOTYPE( void cause_alarm, (timer_t *tp) );
+
+/*===========================================================================*
+ *				do_setalarm				     *
+ *===========================================================================*/
+PUBLIC int do_setalarm(m_ptr)
+message *m_ptr;			/* pointer to request message */
+{
+/* A process requests a synchronous alarm, or wants to cancel its alarm. */
+  register struct proc *rp;	/* pointer to requesting process */
+  long exp_time;		/* expiration time for this alarm */
+  int use_abs_time;		/* use absolute or relative time */
+  timer_t *tp;			/* the process' timer structure */
+  clock_t uptime;		/* placeholder for current uptime */
+
+  /* Extract shared parameters from the request message. */
+  exp_time = m_ptr->ALRM_EXP_TIME;	/* alarm's expiration time */
+  use_abs_time = m_ptr->ALRM_ABS_TIME;	/* flag for absolute time */
+  rp = proc_addr(who_p);
+  if (! (priv(rp)->s_flags & SYS_PROC)) return(EPERM);
+
+  /* Get the timer structure and set the parameters for this alarm. */
+  tp = &(priv(rp)->s_alarm_timer);	
+  tmr_arg(tp)->ta_int = m_ptr->m_source;
+  tp->tmr_func = cause_alarm; 
+
+  /* Return the ticks left on the previous alarm. */
+  uptime = get_uptime(); 
+  if ((tp->tmr_exp_time != TMR_NEVER) && (uptime < tp->tmr_exp_time) ) {
+      m_ptr->ALRM_TIME_LEFT = (tp->tmr_exp_time - uptime);
+  } else {
+      m_ptr->ALRM_TIME_LEFT = 0;
+  }
+
+  /* Finally, (re)set the timer depending on the expiration time. */
+  if (exp_time == 0) {
+      reset_timer(tp);
+  } else {
+      tp->tmr_exp_time = (use_abs_time) ? exp_time : exp_time + get_uptime();
+      set_timer(tp, tp->tmr_exp_time, tp->tmr_func);
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *				cause_alarm				     *
+ *===========================================================================*/
+PRIVATE void cause_alarm(tp)
+timer_t *tp;
+{
+/* Routine called if a timer goes off and the process requested a synchronous
+ * alarm. The process number is stored in timer argument 'ta_int'. Notify that
+ * process with a notification message from CLOCK.
+ */
+  int proc_nr_e = tmr_arg(tp)->ta_int;		/* get process number */
+  lock_notify(CLOCK, proc_nr_e);		/* notify process */
+}
+
+#endif /* USE_SETALARM */
Index: /trunk/minix/kernel/system/do_sigreturn.c
===================================================================
--- /trunk/minix/kernel/system/do_sigreturn.c	(revision 9)
+++ /trunk/minix/kernel/system/do_sigreturn.c	(revision 9)
@@ -0,0 +1,72 @@
+/* The kernel call that is implemented in this file:
+ *   m_type:	SYS_SIGRETURN
+ *
+ * The parameters for this kernel call are:
+ *     m2_i1:	SIG_ENDPT  	# process returning from handler
+ *     m2_p1:	SIG_CTXT_PTR 	# pointer to sigcontext structure
+ *
+ */
+
+#include "../system.h"
+#include <string.h>
+#include <signal.h>
+#include <sys/sigcontext.h>
+
+#if USE_SIGRETURN 
+
+/*===========================================================================*
+ *			      do_sigreturn				     *
+ *===========================================================================*/
+PUBLIC int do_sigreturn(m_ptr)
+message *m_ptr;			/* pointer to request message */
+{
+/* POSIX style signals require sys_sigreturn to put things in order before 
+ * the signalled process can resume execution
+ */
+  struct sigcontext sc;
+  register struct proc *rp;
+  phys_bytes src_phys;
+  int proc;
+
+  if (! isokendpt(m_ptr->SIG_ENDPT, &proc)) return(EINVAL);
+  if (iskerneln(proc)) return(EPERM);
+  rp = proc_addr(proc);
+
+  /* Copy in the sigcontext structure. */
+  src_phys = umap_local(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
+      (vir_bytes) sizeof(struct sigcontext));
+  if (src_phys == 0) return(EFAULT);
+  phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext));
+
+  /* Make sure that this is not just a jump buffer. */
+  if ((sc.sc_flags & SC_SIGCONTEXT) == 0) return(EINVAL);
+
+  /* Fix up only certain key registers if the compiler doesn't use
+   * register variables within functions containing setjmp.
+   */
+  if (sc.sc_flags & SC_NOREGLOCALS) {
+      rp->p_reg.retreg = sc.sc_retreg;
+      rp->p_reg.fp = sc.sc_fp;
+      rp->p_reg.pc = sc.sc_pc;
+      rp->p_reg.sp = sc.sc_sp;
+      return(OK);
+  }
+  sc.sc_psw  = rp->p_reg.psw;
+
+#if (CHIP == INTEL)
+  /* Don't panic kernel if user gave bad selectors. */
+  sc.sc_cs = rp->p_reg.cs;
+  sc.sc_ds = rp->p_reg.ds;
+  sc.sc_es = rp->p_reg.es;
+#if _WORD_SIZE == 4
+  sc.sc_fs = rp->p_reg.fs;
+  sc.sc_gs = rp->p_reg.gs;
+#endif
+#endif
+
+  /* Restore the registers. */
+  memcpy(&rp->p_reg, &sc.sc_regs, sizeof(struct sigregs));
+  return(OK);
+}
+#endif /* USE_SIGRETURN */
+
Index: /trunk/minix/kernel/system/do_sigsend.c
===================================================================
--- /trunk/minix/kernel/system/do_sigsend.c	(revision 9)
+++ /trunk/minix/kernel/system/do_sigsend.c	(revision 9)
@@ -0,0 +1,84 @@
+/* The kernel call that is implemented in this file:
+ *   m_type:	SYS_SIGSEND
+ *
+ * The parameters for this kernel call are:
+ *     m2_i1:	SIG_ENDPT  	# process to call signal handler
+ *     m2_p1:	SIG_CTXT_PTR 	# pointer to sigcontext structure
+ *     m2_i3:	SIG_FLAGS    	# flags for S_SIGRETURN call	
+ *
+ */
+
+#include "../system.h"
+#include <signal.h>
+#include <string.h>
+#include <sys/sigcontext.h>
+
+#if USE_SIGSEND
+
+/*===========================================================================*
+ *			      do_sigsend				     *
+ *===========================================================================*/
+PUBLIC int do_sigsend(m_ptr)
+message *m_ptr;			/* pointer to request message */
+{
+/* Handle sys_sigsend, POSIX-style signal handling. */
+
+  struct sigmsg smsg;
+  register struct proc *rp;
+  phys_bytes src_phys, dst_phys;
+  struct sigcontext sc, *scp;
+  struct sigframe fr, *frp;
+  int proc;
+
+  if (!isokendpt(m_ptr->SIG_ENDPT, &proc)) return(EINVAL);
+  if (iskerneln(proc)) return(EPERM);
+  rp = proc_addr(proc);
+
+  /* Get the sigmsg structure into our address space.  */
+  src_phys = umap_local(proc_addr(PM_PROC_NR), D, (vir_bytes) 
+      m_ptr->SIG_CTXT_PTR, (vir_bytes) sizeof(struct sigmsg));
+  if (src_phys == 0) return(EFAULT);
+  phys_copy(src_phys,vir2phys(&smsg),(phys_bytes) sizeof(struct sigmsg));
+
+  /* Compute the user stack pointer where sigcontext will be stored. */
+  scp = (struct sigcontext *) smsg.sm_stkptr - 1;
+
+  /* Copy the registers to the sigcontext structure. */
+  memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(struct sigregs));
+
+  /* Finish the sigcontext initialization. */
+  sc.sc_flags = SC_SIGCONTEXT;
+  sc.sc_mask = smsg.sm_mask;
+
+  /* Copy the sigcontext structure to the user's stack. */
+  dst_phys = umap_local(rp, D, (vir_bytes) scp,
+      (vir_bytes) sizeof(struct sigcontext));
+  if (dst_phys == 0) return(EFAULT);
+  phys_copy(vir2phys(&sc), dst_phys, (phys_bytes) sizeof(struct sigcontext));
+
+  /* Initialize the sigframe structure. */
+  frp = (struct sigframe *) scp - 1;
+  fr.sf_scpcopy = scp;
+  fr.sf_retadr2= (void (*)()) rp->p_reg.pc;
+  fr.sf_fp = rp->p_reg.fp;
+  rp->p_reg.fp = (reg_t) &frp->sf_fp;
+  fr.sf_scp = scp;
+  fr.sf_code = 0;	/* XXX - should be used for type of FP exception */
+  fr.sf_signo = smsg.sm_signo;
+  fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
+
+  /* Copy the sigframe structure to the user's stack. */
+  dst_phys = umap_local(rp, D, (vir_bytes) frp, 
+      (vir_bytes) sizeof(struct sigframe));
+  if (dst_phys == 0) return(EFAULT);
+  phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe));
+
+  /* Reset user registers to execute the signal handler. */
+  rp->p_reg.sp = (reg_t) frp;
+  rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
+
+  return(OK);
+}
+
+#endif /* USE_SIGSEND */
+
Index: /trunk/minix/kernel/system/do_times.c
===================================================================
--- /trunk/minix/kernel/system/do_times.c	(revision 9)
+++ /trunk/minix/kernel/system/do_times.c	(revision 9)
@@ -0,0 +1,42 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_TIMES
+ *
+ * The parameters for this kernel call are:
+ *    m4_l1:	T_ENDPT		(get info for this process)	
+ *    m4_l1:	T_USER_TIME		(return values ...)	
+ *    m4_l2:	T_SYSTEM_TIME	
+ *    m4_l5:	T_BOOT_TICKS	
+ */
+
+#include "../system.h"
+
+#include <minix/endpoint.h>
+
+#if USE_TIMES
+
+/*===========================================================================*
+ *				do_times				     *
+ *===========================================================================*/
+PUBLIC int do_times(m_ptr)
+register message *m_ptr;	/* pointer to request message */
+{
+/* Handle sys_times().  Retrieve the accounting information. */
+  register struct proc *rp;
+  int proc_nr, e_proc_nr;
+
+  /* Insert the times needed by the SYS_TIMES kernel call in the message. 
+   * The clock's interrupt handler may run to update the user or system time
+   * while in this code, but that cannot do any harm.
+   */
+  e_proc_nr = (m_ptr->T_ENDPT == SELF) ? m_ptr->m_source : m_ptr->T_ENDPT;
+  if(e_proc_nr != NONE && isokendpt(e_proc_nr, &proc_nr)) {
+      rp = proc_addr(proc_nr);
+      m_ptr->T_USER_TIME   = rp->p_user_time;
+      m_ptr->T_SYSTEM_TIME = rp->p_sys_time;
+  }
+  m_ptr->T_BOOT_TICKS = get_uptime();  
+  return(OK);
+}
+
+#endif /* USE_TIMES */
+
Index: /trunk/minix/kernel/system/do_trace.c
===================================================================
--- /trunk/minix/kernel/system/do_trace.c	(revision 9)
+++ /trunk/minix/kernel/system/do_trace.c	(revision 9)
@@ -0,0 +1,146 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_TRACE
+ *
+ * The parameters for this kernel call are:
+ *    m2_i1:	CTL_ENDPT	process that is traced
+ *    m2_i2:    CTL_REQUEST	trace request
+ *    m2_l1:    CTL_ADDRESS     address at traced process' space
+ *    m2_l2:    CTL_DATA        data to be written or returned here
+ */
+
+#include "../system.h"
+#include <sys/ptrace.h>
+
+#if USE_TRACE
+
+/*==========================================================================*
+ *				do_trace				    *
+ *==========================================================================*/
+#define TR_VLSIZE	((vir_bytes) sizeof(long))
+
+PUBLIC int do_trace(m_ptr)
+register message *m_ptr;
+{
+/* Handle the debugging commands supported by the ptrace system call
+ * The commands are:
+ * T_STOP	stop the process
+ * T_OK		enable tracing by parent for this process
+ * T_GETINS	return value from instruction space
+ * T_GETDATA	return value from data space
+ * T_GETUSER	return value from user process table
+ * T_SETINS	set value from instruction space
+ * T_SETDATA	set value from data space
+ * T_SETUSER	set value in user process table
+ * T_RESUME	resume execution
+ * T_EXIT	exit
+ * T_STEP	set trace bit
+ *
+ * The T_OK and T_EXIT commands are handled completely by the process manager,
+ * all others come here.
+ */
+
+  register struct proc *rp;
+  phys_bytes src, dst;
+  vir_bytes tr_addr = (vir_bytes) m_ptr->CTL_ADDRESS;
+  long tr_data = m_ptr->CTL_DATA;
+  int tr_request = m_ptr->CTL_REQUEST;
+  int tr_proc_nr_e = m_ptr->CTL_ENDPT, tr_proc_nr;
+  int i;
+
+  if(!isokendpt(tr_proc_nr_e, &tr_proc_nr)) return(EINVAL);
+  if (iskerneln(tr_proc_nr)) return(EPERM);
+
+  rp = proc_addr(tr_proc_nr);
+  if (isemptyp(rp)) return(EIO);
+  switch (tr_request) {
+  case T_STOP:			/* stop process */
+	if (rp->p_rts_flags == 0) lock_dequeue(rp);
+	rp->p_rts_flags |= P_STOP;
+	rp->p_reg.psw &= ~TRACEBIT;	/* clear trace bit */
+	return(OK);
+
+  case T_GETINS:		/* return value from instruction space */
+	if (rp->p_memmap[T].mem_len != 0) {
+		if ((src = umap_local(rp, T, tr_addr, TR_VLSIZE)) == 0) return(EIO);
+		phys_copy(src, vir2phys(&tr_data), (phys_bytes) sizeof(long));
+		m_ptr->CTL_DATA = tr_data;
+		break;
+	}
+	/* Text space is actually data space - fall through. */
+
+  case T_GETDATA:		/* return value from data space */
+	if ((src = umap_local(rp, D, tr_addr, TR_VLSIZE)) == 0) return(EIO);
+	phys_copy(src, vir2phys(&tr_data), (phys_bytes) sizeof(long));
+	m_ptr->CTL_DATA= tr_data;
+	break;
+
+  case T_GETUSER:		/* return value from process table */
+	if ((tr_addr & (sizeof(long) - 1)) != 0 ||
+	    tr_addr > sizeof(struct proc) - sizeof(long))
+		return(EIO);
+	m_ptr->CTL_DATA = *(long *) ((char *) rp + (int) tr_addr);
+	break;
+
+  case T_SETINS:		/* set value in instruction space */
+	if (rp->p_memmap[T].mem_len != 0) {
+		if ((dst = umap_local(rp, T, tr_addr, TR_VLSIZE)) == 0) return(EIO);
+		phys_copy(vir2phys(&tr_data), dst, (phys_bytes) sizeof(long));
+		m_ptr->CTL_DATA = 0;
+		break;
+	}
+	/* Text space is actually data space - fall through. */
+
+  case T_SETDATA:			/* set value in data space */
+	if ((dst = umap_local(rp, D, tr_addr, TR_VLSIZE)) == 0) return(EIO);
+	phys_copy(vir2phys(&tr_data), dst, (phys_bytes) sizeof(long));
+	m_ptr->CTL_DATA = 0;
+	break;
+
+  case T_SETUSER:			/* set value in process table */
+	if ((tr_addr & (sizeof(reg_t) - 1)) != 0 ||
+	     tr_addr > sizeof(struct stackframe_s) - sizeof(reg_t))
+		return(EIO);
+	i = (int) tr_addr;
+#if (CHIP == INTEL)
+	/* Altering segment registers might crash the kernel when it
+	 * tries to load them prior to restarting a process, so do
+	 * not allow it.
+	 */
+	if (i == (int) &((struct proc *) 0)->p_reg.cs ||
+	    i == (int) &((struct proc *) 0)->p_reg.ds ||
+	    i == (int) &((struct proc *) 0)->p_reg.es ||
+#if _WORD_SIZE == 4
+	    i == (int) &((struct proc *) 0)->p_reg.gs ||
+	    i == (int) &((struct proc *) 0)->p_reg.fs ||
+#endif
+	    i == (int) &((struct proc *) 0)->p_reg.ss)
+		return(EIO);
+#endif
+	if (i == (int) &((struct proc *) 0)->p_reg.psw)
+		/* only selected bits are changeable */
+		SETPSW(rp, tr_data);
+	else
+		*(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) tr_data;
+	m_ptr->CTL_DATA = 0;
+	break;
+
+  case T_RESUME:		/* resume execution */
+	rp->p_rts_flags &= ~P_STOP;
+	if (rp->p_rts_flags == 0) lock_enqueue(rp);
+	m_ptr->CTL_DATA = 0;
+	break;
+
+  case T_STEP:			/* set trace bit */
+	rp->p_reg.psw |= TRACEBIT;
+	rp->p_rts_flags &= ~P_STOP;
+	if (rp->p_rts_flags == 0) lock_enqueue(rp);
+	m_ptr->CTL_DATA = 0;
+	break;
+
+  default:
+	return(EIO);
+  }
+  return(OK);
+}
+
+#endif /* USE_TRACE */
Index: /trunk/minix/kernel/system/do_umap.c
===================================================================
--- /trunk/minix/kernel/system/do_umap.c	(revision 9)
+++ /trunk/minix/kernel/system/do_umap.c	(revision 9)
@@ -0,0 +1,56 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_UMAP
+ *
+ * The parameters for this kernel call are:
+ *    m5_i1:	CP_SRC_PROC_NR	(process number)	
+ *    m5_c1:	CP_SRC_SPACE	(segment where address is: T, D, or S)
+ *    m5_l1:	CP_SRC_ADDR	(virtual address)	
+ *    m5_l2:	CP_DST_ADDR	(returns physical address)	
+ *    m5_l3:	CP_NR_BYTES	(size of datastructure) 	
+ */
+
+#include "../system.h"
+
+#if USE_UMAP
+
+/*==========================================================================*
+ *				do_umap					    *
+ *==========================================================================*/
+PUBLIC int do_umap(m_ptr)
+register message *m_ptr;	/* pointer to request message */
+{
+/* Map virtual address to physical, for non-kernel processes. */
+  int seg_type = m_ptr->CP_SRC_SPACE & SEGMENT_TYPE;
+  int seg_index = m_ptr->CP_SRC_SPACE & SEGMENT_INDEX;
+  vir_bytes offset = m_ptr->CP_SRC_ADDR;
+  int count = m_ptr->CP_NR_BYTES;
+  int endpt = (int) m_ptr->CP_SRC_ENDPT;
+  int proc_nr;
+  phys_bytes phys_addr;
+
+  /* Verify process number. */
+  if (endpt == SELF)
+	proc_nr = who_p;
+  else
+	if (! isokendpt(endpt, &proc_nr))
+		return(EINVAL);
+
+  /* See which mapping should be made. */
+  switch(seg_type) {
+  case LOCAL_SEG:
+      phys_addr = umap_local(proc_addr(proc_nr), seg_index, offset, count); 
+      break;
+  case REMOTE_SEG:
+      phys_addr = umap_remote(proc_addr(proc_nr), seg_index, offset, count); 
+      break;
+  case BIOS_SEG:
+      phys_addr = umap_bios(proc_addr(proc_nr), offset, count); 
+      break;
+  default:
+      return(EINVAL);
+  }
+  m_ptr->CP_DST_ADDR = phys_addr;
+  return (phys_addr == 0) ? EFAULT: OK;
+}
+
+#endif /* USE_UMAP */
Index: /trunk/minix/kernel/system/do_unused.c
===================================================================
--- /trunk/minix/kernel/system/do_unused.c	(revision 9)
+++ /trunk/minix/kernel/system/do_unused.c	(revision 9)
@@ -0,0 +1,16 @@
+/* This file provides a catch-all handler for unused kernel calls. A kernel 
+ * call may be unused when it is not defined or when it is disabled in the
+ * kernel's configuration.
+ */
+#include "../system.h"
+
+/*===========================================================================*
+ *			          do_unused				     *
+ *===========================================================================*/
+PUBLIC int do_unused(m)
+message *m;				/* pointer to request message */
+{
+  kprintf("SYSTEM: got unused request %d from %d", m->m_type, m->m_source);
+  return(EBADREQUEST);			/* illegal message type */
+}
+
Index: /trunk/minix/kernel/system/do_vcopy.c
===================================================================
--- /trunk/minix/kernel/system/do_vcopy.c	(revision 9)
+++ /trunk/minix/kernel/system/do_vcopy.c	(revision 9)
@@ -0,0 +1,65 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_VIRVCOPY, SYS_PHYSVCOPY 
+ *
+ * The parameters for this kernel call are:
+ *    m1_i3:	VCP_VEC_SIZE		size of copy request vector 
+ *    m1_p1:	VCP_VEC_ADDR		address of vector at caller 
+ *    m1_i2:	VCP_NR_OK		number of successfull copies	
+ */
+
+#include "../system.h"
+#include <minix/type.h>
+
+#if (USE_VIRVCOPY || USE_PHYSVCOPY)
+
+/* Buffer to hold copy request vector from user. */
+PRIVATE struct vir_cp_req vir_cp_req[VCOPY_VEC_SIZE];
+
+/*===========================================================================*
+ *				do_vcopy					     *
+ *===========================================================================*/
+PUBLIC int do_vcopy(m_ptr)
+register message *m_ptr;	/* pointer to request message */
+{
+/* Handle sys_virvcopy() and sys_physvcopy() that pass a vector with copy
+ * requests. Although a single handler function is used, there are two
+ * different kernel calls so that permissions can be checked.
+ */
+  int nr_req;
+  vir_bytes caller_vir;
+  phys_bytes caller_phys;
+  phys_bytes kernel_phys;
+  phys_bytes bytes;
+  int i,s;
+  struct vir_cp_req *req;
+
+  /* Check if request vector size is ok. */
+  nr_req = (unsigned) m_ptr->VCP_VEC_SIZE;
+  if (nr_req > VCOPY_VEC_SIZE) return(EINVAL);
+  bytes = nr_req * sizeof(struct vir_cp_req);
+
+  /* Calculate physical addresses and copy (port,value)-pairs from user. */
+  caller_vir = (vir_bytes) m_ptr->VCP_VEC_ADDR;
+  caller_phys = umap_local(proc_addr(who_p), D, caller_vir, bytes);
+  if (0 == caller_phys) return(EFAULT);
+  kernel_phys = vir2phys(vir_cp_req);
+  phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
+
+  /* Assume vector with requests is correct. Try to copy everything. */
+  m_ptr->VCP_NR_OK = 0;
+  for (i=0; i<nr_req; i++) {
+
+      req = &vir_cp_req[i];
+
+      /* Check if physical addressing is used without SYS_PHYSVCOPY. */
+      if (((req->src.segment | req->dst.segment) & PHYS_SEG) &&
+              m_ptr->m_type != SYS_PHYSVCOPY) return(EPERM);
+      if ((s=virtual_copy(&req->src, &req->dst, req->count)) != OK) 
+          return(s);
+      m_ptr->VCP_NR_OK ++;
+  }
+  return(OK);
+}
+
+#endif /* (USE_VIRVCOPY || USE_PHYSVCOPY) */
+
Index: /trunk/minix/kernel/system/do_vdevio.c
===================================================================
--- /trunk/minix/kernel/system/do_vdevio.c	(revision 9)
+++ /trunk/minix/kernel/system/do_vdevio.c	(revision 9)
@@ -0,0 +1,87 @@
+/* The kernel call implemented in this file:
+ *   m_type:	SYS_VDEVIO
+ *
+ * The parameters for this kernel call are:
+ *    m2_i3:	DIO_REQUEST	(request input or output)	
+ *    m2_i1:	DIO_TYPE	(flag indicating byte, word, or long)
+ *    m2_p1:	DIO_VEC_ADDR	(pointer to port/ value pairs)	
+ *    m2_i2:	DIO_VEC_SIZE	(number of ports to read or write) 
+ */
+
+#include "../system.h"
+#include <minix/devio.h>
+#include <minix/endpoint.h>
+
+#if USE_VDEVIO
+
+/* Buffer for SYS_VDEVIO to copy (port,value)-pairs from/ to user. */
+PRIVATE char vdevio_buf[VDEVIO_BUF_SIZE];      
+PRIVATE pvb_pair_t *pvb = (pvb_pair_t *) vdevio_buf;           
+PRIVATE pvw_pair_t *pvw = (pvw_pair_t *) vdevio_buf;      
+PRIVATE pvl_pair_t *pvl = (pvl_pair_t *) vdevio_buf;     
+
+/*===========================================================================*
+ *			        do_vdevio                                    *
+ *===========================================================================*/
+PUBLIC int do_vdevio(m_ptr)
+register message *m_ptr;	/* pointer to request message */
+{
+/* Perform a series of device I/O on behalf of a non-kernel process. The 
+ * I/O addresses and I/O values are fetched from and returned to some buffer
+ * in user space. The actual I/O is wrapped by lock() and unlock() to prevent
+ * that I/O batch from being interrrupted.
+ * This is the counterpart of do_devio, which performs a single device I/O. 
+ */ 
+  int vec_size;               /* size of vector */
+  int io_in;                  /* true if input */
+  size_t bytes;               /* # bytes to be copied */
+  vir_bytes caller_vir;       /* virtual address at caller */
+  phys_bytes caller_phys;     /* physical address at caller */
+  int i;
+    
+  /* Get the request, size of the request vector, and check the values. */
+  if (m_ptr->DIO_REQUEST == DIO_INPUT) io_in = TRUE;
+  else if (m_ptr->DIO_REQUEST == DIO_OUTPUT) io_in = FALSE;
+  else return(EINVAL);
+  if ((vec_size = m_ptr->DIO_VEC_SIZE) <= 0) return(EINVAL);
+  switch (m_ptr->DIO_TYPE) {
+      case DIO_BYTE: bytes = vec_size * sizeof(pvb_pair_t); break;
+      case DIO_WORD: bytes = vec_size * sizeof(pvw_pair_t); break;
+      case DIO_LONG: bytes = vec_size * sizeof(pvl_pair_t); break;
+      default:  return(EINVAL);   /* check type once and for all */
+  }
+  if (bytes > sizeof(vdevio_buf))  return(E2BIG);
+
+  /* Calculate physical addresses and copy (port,value)-pairs from user. */
+  caller_vir = (vir_bytes) m_ptr->DIO_VEC_ADDR;
+  caller_phys = umap_local(proc_addr(who_p), D, caller_vir, bytes);
+  if (0 == caller_phys) return(EFAULT);
+  phys_copy(caller_phys, vir2phys(vdevio_buf), (phys_bytes) bytes);
+
+  /* Perform actual device I/O for byte, word, and long values. Note that 
+   * the entire switch is wrapped in lock() and unlock() to prevent the I/O
+   * batch from being interrupted. 
+   */  
+  lock(13, "do_vdevio");
+  switch (m_ptr->DIO_TYPE) {
+  case DIO_BYTE: 					 /* byte values */
+      if (io_in) for (i=0; i<vec_size; i++)  pvb[i].value = inb(pvb[i].port); 
+      else       for (i=0; i<vec_size; i++)  outb(pvb[i].port, pvb[i].value); 
+      break; 
+  case DIO_WORD:					  /* word values */
+      if (io_in) for (i=0; i<vec_size; i++)  pvw[i].value = inw(pvw[i].port);  
+      else       for (i=0; i<vec_size; i++)  outw(pvw[i].port, pvw[i].value); 
+      break; 
+  default:            					  /* long values */
+      if (io_in) for (i=0; i<vec_size; i++) pvl[i].value = inl(pvl[i].port);  
+      else       for (i=0; i<vec_size; i++) outl(pvb[i].port, pvl[i].value); 
+  }
+  unlock(13);
+    
+  /* Almost done, copy back results for input requests. */
+  if (io_in) phys_copy(vir2phys(vdevio_buf), caller_phys, (phys_bytes) bytes);
+  return(OK);
+}
+
+#endif /* USE_VDEVIO */
+
Index: /trunk/minix/kernel/system/do_vm.c
===================================================================
--- /trunk/minix/kernel/system/do_vm.c	(revision 9)
+++ /trunk/minix/kernel/system/do_vm.c	(revision 9)
@@ -0,0 +1,224 @@
+/* The system call implemented in this file:
+ *   m_type:	SYS_VM_MAP
+ *
+ * The parameters for this system call are:
+ *    m4_l1:	Process that requests map (VM_MAP_ENDPT)
+ *    m4_l2:	Map (TRUE) or unmap (FALSE) (VM_MAP_MAPUNMAP)
+ *    m4_l3:	Base address (VM_MAP_BASE)
+ *    m4_l4:	Size  (VM_MAP_SIZE)
+ *    m4_l5:	Memory address  (VM_MAP_ADDR)
+ */
+#include "../system.h"
+
+#include <sys/vm.h>
+
+PRIVATE int vm_needs_init= 1;
+PRIVATE u32_t vm_cr3;
+
+FORWARD _PROTOTYPE( void vm_init, (void)				);
+FORWARD _PROTOTYPE( void phys_put32, (phys_bytes addr, u32_t value)	);
+FORWARD _PROTOTYPE( u32_t phys_get32, (phys_bytes addr)			);
+FORWARD _PROTOTYPE( void vm_set_cr3, (u32_t value)			);
+FORWARD _PROTOTYPE( void set_cr3, (void)				);
+FORWARD _PROTOTYPE( void vm_enable_paging, (void)			);
+FORWARD _PROTOTYPE( void map_range, (u32_t base, u32_t size,
+							u32_t offset)	);
+
+/*===========================================================================*
+ *				do_vm_map				     *
+ *===========================================================================*/
+PUBLIC int do_vm_map(m_ptr)
+message *m_ptr;			/* pointer to request message */
+{
+	int proc_nr, do_map;
+	phys_bytes base, size, offset, p_phys;
+	struct proc *pp;
+
+	/* do_serial_debug= 1; */
+
+	if (vm_needs_init)
+	{
+		vm_needs_init= 0;
+		vm_init();
+	}
+
+	if (m_ptr->VM_MAP_ENDPT == SELF) {
+		proc_nr = who_p;
+	} else {
+		if(!isokendpt(m_ptr->VM_MAP_ENDPT, &proc_nr))
+			return EINVAL;
+	}
+
+	do_map= m_ptr->VM_MAP_MAPUNMAP;
+	base= m_ptr->VM_MAP_BASE;
+	size= m_ptr->VM_MAP_SIZE;
+	offset= m_ptr->VM_MAP_ADDR;
+
+	pp= proc_addr(proc_nr);
+	p_phys= umap_local(pp, D, base, size);
+	if (p_phys == 0)
+		return EFAULT;
+
+	if (do_map)
+	{
+		pp->p_misc_flags |= MF_VM;
+
+		map_range(p_phys, size, offset);
+	}
+	else
+	{
+		map_range(p_phys, size, p_phys);
+	}
+	vm_set_cr3(vm_cr3);
+
+	return OK;
+}
+
+/*===========================================================================*
+ *				vm_map_default				     *
+ *===========================================================================*/
+PUBLIC void vm_map_default(pp)
+struct proc *pp;
+{
+	phys_bytes base_clicks, size_clicks;
+
+	if (vm_needs_init)
+		panic("vm_map_default: VM not initialized?", NO_NUM);
+	pp->p_misc_flags &= ~MF_VM;
+	base_clicks= pp->p_memmap[D].mem_phys;
+	size_clicks= pp->p_memmap[S].mem_phys+pp->p_memmap[S].mem_len -
+		base_clicks;
+	map_range(base_clicks << CLICK_SHIFT, size_clicks << CLICK_SHIFT,
+		base_clicks << CLICK_SHIFT);
+	vm_set_cr3(vm_cr3);
+}
+
+PRIVATE void vm_init(void)
+{
+	int o;
+	phys_bytes p, pt_size;
+	phys_bytes vm_dir_base, vm_pt_base, phys_mem;
+	u32_t entry;
+	unsigned pages;
+
+	if (!vm_size)
+		panic("vm_init: no space for page tables", NO_NUM);
+
+	/* Align page directory */
+	o= (vm_base % PAGE_SIZE);
+	if (o != 0)
+		o= PAGE_SIZE-o;
+	vm_dir_base= vm_base+o;
+
+	/* Page tables start after the page directory */
+	vm_pt_base= vm_dir_base+PAGE_SIZE;
+
+	pt_size= (vm_base+vm_size)-vm_pt_base;
+	pt_size -= (pt_size % PAGE_SIZE);
+
+	/* Compute the number of pages based on vm_mem_high */
+	pages= (vm_mem_high-1)/PAGE_SIZE + 1;
+
+	if (pages * I386_VM_PT_ENT_SIZE > pt_size)
+		panic("vm_init: page table too small", NO_NUM);
+
+	for (p= 0; p*I386_VM_PT_ENT_SIZE < pt_size; p++)
+	{
+		phys_mem= p*PAGE_SIZE;
+		entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
+			I386_VM_PRESENT;
+		if (phys_mem >= vm_mem_high)
+			entry= 0;
+		phys_put32(vm_pt_base + p*I386_VM_PT_ENT_SIZE, entry);
+	}
+
+	for (p= 0; p < I386_VM_DIR_ENTRIES; p++)
+	{
+		phys_mem= vm_pt_base + p*PAGE_SIZE;
+		entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
+			I386_VM_PRESENT;
+		if (phys_mem >= vm_pt_base + pt_size)
+			entry= 0;
+		phys_put32(vm_dir_base + p*I386_VM_PT_ENT_SIZE, entry);
+	}
+	vm_set_cr3(vm_dir_base);
+	level0(vm_enable_paging);
+}
+
+PRIVATE void phys_put32(addr, value)
+phys_bytes addr;
+u32_t value;
+{
+	phys_copy(vir2phys((vir_bytes)&value), addr, sizeof(value));
+}
+
+PRIVATE u32_t phys_get32(addr)
+phys_bytes addr;
+{
+	u32_t value;
+
+	phys_copy(addr, vir2phys((vir_bytes)&value), sizeof(value));
+
+	return value;
+}
+
+PRIVATE void vm_set_cr3(value)
+u32_t value;
+{
+	vm_cr3= value;
+	level0(set_cr3);
+}
+
+PRIVATE void set_cr3()
+{
+	write_cr3(vm_cr3);
+}
+
+PRIVATE void vm_enable_paging(void)
+{
+	u32_t cr0;
+
+	cr0= read_cr0();
+	write_cr0(cr0 | I386_CR0_PG);
+}
+
+PRIVATE void map_range(base, size, offset)
+u32_t base;
+u32_t size;
+u32_t offset;
+{
+	u32_t curr_pt, curr_pt_addr, entry;
+	int dir_ent, pt_ent;
+
+	if (base % PAGE_SIZE != 0)
+		panic("map_range: bad base", base);
+	if (size % PAGE_SIZE != 0)
+		panic("map_range: bad size", size);
+	if (offset % PAGE_SIZE != 0)
+		panic("map_range: bad offset", offset);
+
+	curr_pt= -1;
+	curr_pt_addr= 0;
+	while (size != 0)
+	{
+		dir_ent= (base >> I386_VM_DIR_ENT_SHIFT);
+		pt_ent= (base >> I386_VM_PT_ENT_SHIFT) & I386_VM_PT_ENT_MASK;
+		if (dir_ent != curr_pt)
+		{
+			/* Get address of page table */
+			curr_pt= dir_ent;
+			curr_pt_addr= phys_get32(vm_cr3 +
+				dir_ent * I386_VM_PT_ENT_SIZE);
+			curr_pt_addr &= I386_VM_ADDR_MASK;
+		}
+		entry= offset | I386_VM_USER | I386_VM_WRITE |
+			I386_VM_PRESENT;
+#if 0	/* Do we need this for memory mapped I/O? */
+		entry |= I386_VM_PCD | I386_VM_PWT;
+#endif
+		phys_put32(curr_pt_addr + pt_ent * I386_VM_PT_ENT_SIZE, entry);
+		offset += PAGE_SIZE;
+		base += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+}
Index: /trunk/minix/kernel/system/do_vm_setbuf.c
===================================================================
--- /trunk/minix/kernel/system/do_vm_setbuf.c	(revision 9)
+++ /trunk/minix/kernel/system/do_vm_setbuf.c	(revision 9)
@@ -0,0 +1,29 @@
+/* The system call implemented in this file:
+ *   m_type:	SYS_VM_SETBUF
+ *
+ * The parameters for this system call are:
+ *    m4_l1:	Start of the buffer
+ *    m4_l2:	Length of the buffer
+ *    m4_l3:	End of main memory
+ */
+#include "../system.h"
+
+#define VM_DEBUG 0		/* enable/ disable debug output */
+
+/*===========================================================================*
+ *				do_vm_setbuf				     *
+ *===========================================================================*/
+PUBLIC int do_vm_setbuf(m_ptr)
+message *m_ptr;			/* pointer to request message */
+{
+	vm_base= m_ptr->m4_l1;
+	vm_size= m_ptr->m4_l2;
+	vm_mem_high= m_ptr->m4_l3;
+
+#if VM_DEBUG
+	kprintf("do_vm_setbuf: got 0x%x @ 0x%x for 0x%x\n",
+		vm_size, vm_base, vm_mem_high);
+#endif
+
+	return OK;
+}
Index: /trunk/minix/kernel/table.c
===================================================================
--- /trunk/minix/kernel/table.c	(revision 9)
+++ /trunk/minix/kernel/table.c	(revision 9)
@@ -0,0 +1,125 @@
+/* The object file of "table.c" contains most kernel data. Variables that 
+ * are declared in the *.h files appear with EXTERN in front of them, as in
+ *
+ *    EXTERN int x;
+ *
+ * Normally EXTERN is defined as extern, so when they are included in another
+ * file, no storage is allocated.  If EXTERN were not present, but just say,
+ *
+ *    int x;
+ *
+ * then including this file in several source files would cause 'x' to be
+ * declared several times.  While some linkers accept this, others do not,
+ * so they are declared extern when included normally.  However, it must be
+ * declared for real somewhere.  That is done here, by redefining EXTERN as
+ * the null string, so that inclusion of all *.h files in table.c actually
+ * generates storage for them.  
+ *
+ * Various variables could not be declared EXTERN, but are declared PUBLIC
+ * or PRIVATE. The reason for this is that extern variables cannot have a  
+ * default initialization. If such variables are shared, they must also be
+ * declared in one of the *.h files without the initialization.  Examples 
+ * include 'boot_image' (this file) and 'idt' and 'gdt' (protect.c). 
+ *
+ * Changes:
+ *    Aug 02, 2005   set privileges and minimal boot image (Jorrit N. Herder)
+ *    Oct 17, 2004   updated above and tasktab comments  (Jorrit N. Herder)
+ *    May 01, 2004   changed struct for system image  (Jorrit N. Herder)
+ */
+#define _TABLE
+
+#include "kernel.h"
+#include "proc.h"
+#include "ipc.h"
+#include <minix/com.h>
+#include <ibm/int86.h>
+
+/* Define stack sizes for the kernel tasks included in the system image. */
+#define NO_STACK	0
+#define SMALL_STACK	(128 * sizeof(char *))
+#define IDL_S	SMALL_STACK	/* 3 intr, 3 temps, 4 db for Intel */
+#define	HRD_S	NO_STACK	/* dummy task, uses kernel stack */
+#define	TSK_S	SMALL_STACK	/* system and clock task */
+
+/* Stack space for all the task stacks.  Declared as (char *) to align it. */
+#define	TOT_STACK_SPACE	(IDL_S + HRD_S + (2 * TSK_S))
+PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
+	
+/* Define flags for the various process types. */
+#define IDL_F 	(SYS_PROC | PREEMPTIBLE | BILLABLE)	/* idle task */
+#define TSK_F 	(SYS_PROC)				/* kernel tasks */
+#define SRV_F 	(SYS_PROC | PREEMPTIBLE)		/* system services */
+#define USR_F	(BILLABLE | PREEMPTIBLE)		/* user processes */
+
+/* Define system call traps for the various process types. These call masks
+ * determine what system call traps a process is allowed to make.
+ */
+#define TSK_T	(1 << RECEIVE)			/* clock and system */
+#define SRV_T	(~0)				/* system services */
+#define USR_T   ((1 << SENDREC) | (1 << ECHO))	/* user processes */
+
+/* Send masks determine to whom processes can send messages or notifications. 
+ * The values here are used for the processes in the boot image. We rely on 
+ * the initialization code in main() to match the s_nr_to_id() mapping for the
+ * processes in the boot image, so that the send mask that is defined here 
+ * can be directly copied onto map[0] of the actual send mask. Privilege
+ * structure 0 is shared by user processes. 
+ */
+#define s(n)		(1 << s_nr_to_id(n))
+#define SRV_M	(~0)
+#define SYS_M	(~0)
+#define USR_M (s(PM_PROC_NR) | s(FS_PROC_NR) | s(RS_PROC_NR) | s(SYSTEM))
+#define DRV_M (USR_M | s(SYSTEM) | s(CLOCK) | s(DS_PROC_NR) | s(LOG_PROC_NR) | s(TTY_PROC_NR))
+
+/* Define kernel calls that processes are allowed to make. This is not looking
+ * very nice, but we need to define the access rights on a per call basis. 
+ * Note that the reincarnation server has all bits on, because it should
+ * be allowed to distribute rights to services that it starts. 
+ */
+#define c(n)	(1 << ((n)-KERNEL_CALL))
+#define RS_C	~0	
+#define DS_C	~0	
+#define PM_C	~(c(SYS_DEVIO) | c(SYS_SDEVIO) | c(SYS_VDEVIO) | c(SYS_IRQCTL) | c(SYS_INT86))
+#define FS_C	(c(SYS_KILL) | c(SYS_VIRCOPY) | c(SYS_VIRVCOPY) | c(SYS_UMAP) | c(SYS_GETINFO) | c(SYS_EXIT) | c(SYS_TIMES) | c(SYS_SETALARM))
+#define DRV_C (FS_C | c(SYS_SEGCTL) | c(SYS_IRQCTL) | c(SYS_INT86) | c(SYS_DEVIO) | c(SYS_SDEVIO) | c(SYS_VDEVIO))
+#define TTY_C (DRV_C | c(SYS_ABORT) | c(SYS_VM_MAP) | c(SYS_IOPENABLE))
+#define MEM_C	(DRV_C | c(SYS_PHYSCOPY) | c(SYS_PHYSVCOPY) | c(SYS_VM_MAP) | \
+	c(SYS_IOPENABLE))
+
+/* The system image table lists all programs that are part of the boot image. 
+ * The order of the entries here MUST agree with the order of the programs
+ * in the boot image and all kernel tasks must come first.
+ *
+ * Each entry provides the process number, flags, quantum size, scheduling
+ * queue, allowed traps, ipc mask, and a name for the process table. The 
+ * initial program counter and stack size is also provided for kernel tasks.
+ *
+ * Note: the quantum size must be positive in all cases! 
+ */
+PUBLIC struct boot_image image[] = {
+/* process nr,   pc, flags, qs,  queue, stack, traps, ipcto, call,  name */ 
+ { IDLE,  idle_task, IDL_F,  8, IDLE_Q, IDL_S,     0,     0,     0, "idle"  },
+ { CLOCK,clock_task, TSK_F,  8, TASK_Q, TSK_S, TSK_T,     0,     0, "clock" },
+ { SYSTEM, sys_task, TSK_F,  8, TASK_Q, TSK_S, TSK_T,     0,     0, "system"},
+ { HARDWARE,      0, TSK_F,  8, TASK_Q, HRD_S,     0,     0,     0, "kernel"},
+ { PM_PROC_NR,    0, SRV_F, 32,      3, 0,     SRV_T, SRV_M,  PM_C, "pm"    },
+ { FS_PROC_NR,    0, SRV_F, 32,      4, 0,     SRV_T, SRV_M,  FS_C, "fs"    },
+ { RS_PROC_NR,    0, SRV_F,  4,      3, 0,     SRV_T, SYS_M,  RS_C, "rs"    },
+ { DS_PROC_NR,    0, SRV_F,  4,      3, 0,     SRV_T, SYS_M,  DS_C, "ds"    },
+ { TTY_PROC_NR,   0, SRV_F,  4,      1, 0,     SRV_T, SYS_M, TTY_C, "tty"   },
+ { MEM_PROC_NR,   0, SRV_F,  4,      2, 0,     SRV_T, SYS_M, MEM_C, "mem"   },
+ { LOG_PROC_NR,   0, SRV_F,  4,      2, 0,     SRV_T, SYS_M, DRV_C, "log"   },
+ { INIT_PROC_NR,  0, USR_F,  8, USER_Q, 0,     USR_T, USR_M,     0, "init"  },
+};
+
+/* Verify the size of the system image table at compile time. Also verify that 
+ * the first chunk of the ipc mask has enough bits to accommodate the processes
+ * in the image.  
+ * If a problem is detected, the size of the 'dummy' array will be negative, 
+ * causing a compile time error. Note that no space is actually allocated 
+ * because 'dummy' is declared extern.
+ */
+extern int dummy[(NR_BOOT_PROCS==sizeof(image)/
+	sizeof(struct boot_image))?1:-1];
+extern int dummy[(BITCHUNK_BITS > NR_BOOT_PROCS - 1) ? 1 : -1];
+
Index: /trunk/minix/kernel/type.h
===================================================================
--- /trunk/minix/kernel/type.h	(revision 9)
+++ /trunk/minix/kernel/type.h	(revision 9)
@@ -0,0 +1,111 @@
+#ifndef TYPE_H
+#define TYPE_H
+
+typedef _PROTOTYPE( void task_t, (void) );
+
+/* Process table and system property related types. */ 
+typedef int proc_nr_t;			/* process table entry number */
+typedef short sys_id_t;			/* system process index */
+typedef struct {			/* bitmap for system indexes */
+  bitchunk_t chunk[BITMAP_CHUNKS(NR_SYS_PROCS)];
+} sys_map_t;
+
+struct boot_image {
+  proc_nr_t proc_nr;			/* process number to use */
+  task_t *initial_pc;			/* start function for tasks */
+  int flags;				/* process flags */
+  unsigned char quantum;		/* quantum (tick count) */
+  int priority;				/* scheduling priority */
+  int stksize;				/* stack size for tasks */
+  short trap_mask;			/* allowed system call traps */
+  bitchunk_t ipc_to;			/* send mask protection */
+  long call_mask;			/* system call protection */
+  char proc_name[P_NAME_LEN];		/* name in process table */
+  int endpoint;				/* endpoint number when started */
+};
+
+struct memory {
+  phys_clicks base;			/* start address of chunk */
+  phys_clicks size;			/* size of memory chunk */
+};
+
+/* The kernel outputs diagnostic messages in a circular buffer. */
+struct kmessages {
+  int km_next;				/* next index to write */
+  int km_size;				/* current size in buffer */
+  char km_buf[KMESS_BUF_SIZE];		/* buffer for messages */
+};
+
+struct randomness {
+  struct {
+	int r_next;				/* next index to write */
+	int r_size;				/* number of random elements */
+	unsigned short r_buf[RANDOM_ELEMENTS]; /* buffer for random info */
+  } bin[RANDOM_SOURCES];
+};
+
+#if (CHIP == INTEL)
+typedef unsigned reg_t;		/* machine register */
+
+/* The stack frame layout is determined by the software, but for efficiency
+ * it is laid out so the assembly code to use it is as simple as possible.
+ * 80286 protected mode and all real modes use the same frame, built with
+ * 16-bit registers.  Real mode lacks an automatic stack switch, so little
+ * is lost by using the 286 frame for it.  The 386 frame differs only in
+ * having 32-bit registers and more segment registers.  The same names are
+ * used for the larger registers to avoid differences in the code.
+ */
+struct stackframe_s {           /* proc_ptr points here */
+#if _WORD_SIZE == 4
+  u16_t gs;                     /* last item pushed by save */
+  u16_t fs;                     /*  ^ */
+#endif
+  u16_t es;                     /*  | */
+  u16_t ds;                     /*  | */
+  reg_t di;			/* di through cx are not accessed in C */
+  reg_t si;			/* order is to match pusha/popa */
+  reg_t fp;			/* bp */
+  reg_t st;			/* hole for another copy of sp */
+  reg_t bx;                     /*  | */
+  reg_t dx;                     /*  | */
+  reg_t cx;                     /*  | */
+  reg_t retreg;			/* ax and above are all pushed by save */
+  reg_t retadr;			/* return address for assembly code save() */
+  reg_t pc;			/*  ^  last item pushed by interrupt */
+  reg_t cs;                     /*  | */
+  reg_t psw;                    /*  | */
+  reg_t sp;                     /*  | */
+  reg_t ss;                     /* these are pushed by CPU during interrupt */
+};
+
+struct segdesc_s {		/* segment descriptor for protected mode */
+  u16_t limit_low;
+  u16_t base_low;
+  u8_t base_middle;
+  u8_t access;			/* |P|DL|1|X|E|R|A| */
+  u8_t granularity;		/* |G|X|0|A|LIMT| */
+  u8_t base_high;
+};
+
+typedef unsigned long irq_policy_t;	
+typedef unsigned long irq_id_t;	
+
+typedef struct irq_hook {
+  struct irq_hook *next;		/* next hook in chain */
+  int (*handler)(struct irq_hook *);	/* interrupt handler */
+  int irq;				/* IRQ vector number */ 
+  int id;				/* id of this hook */
+  int proc_nr_e;			/* (endpoint) NONE if not in use */
+  irq_id_t notify_id;			/* id to return on interrupt */
+  irq_policy_t policy;			/* bit mask for policy */
+} irq_hook_t;
+
+typedef int (*irq_handler_t)(struct irq_hook *);
+
+#endif /* (CHIP == INTEL) */
+
+#if (CHIP == M68000)
+/* M68000 specific types go here. */
+#endif /* (CHIP == M68000) */
+
+#endif /* TYPE_H */
Index: /trunk/minix/kernel/utility.c
===================================================================
--- /trunk/minix/kernel/utility.c	(revision 9)
+++ /trunk/minix/kernel/utility.c	(revision 9)
@@ -0,0 +1,27 @@
+/* This file contains a collection of miscellaneous procedures:
+ *   panic:	    abort MINIX due to a fatal error
+ */
+
+#include "kernel.h"
+#include <unistd.h>
+
+/*===========================================================================*
+ *				panic                                        *
+ *===========================================================================*/
+PUBLIC void panic(mess,nr)
+_CONST char *mess;
+int nr;
+{
+/* The system has run aground of a fatal kernel error. Terminate execution. */
+  static int panicking = 0;
+  if (panicking ++) return;		/* prevent recursive panics */
+
+  if (mess != NULL) {
+	kprintf("\nKernel panic: %s", mess);
+	if (nr != NO_NUM) kprintf(" %d", nr);
+	kprintf("\n",NO_NUM);
+  }
+
+  /* Abort MINIX. */
+  prepare_shutdown(RBT_PANIC);
+}
Index: /trunk/minix/lib/Makefile
===================================================================
--- /trunk/minix/lib/Makefile	(revision 9)
+++ /trunk/minix/lib/Makefile	(revision 9)
@@ -0,0 +1,203 @@
+#Generated from ./Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh generate.sh . obj-ack/ obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh generate.sh . obj-ack/ obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+all-ack: makefiles
+	mkdir -p obj-ack//./ansi
+	cd ansi && $(MAKE) $@
+	mkdir -p obj-ack//./curses
+	cd curses && $(MAKE) $@
+	mkdir -p obj-ack//./dummy
+	cd dummy && $(MAKE) $@
+	mkdir -p obj-ack//./editline
+	cd editline && $(MAKE) $@
+	mkdir -p obj-ack//./end
+	cd end && $(MAKE) $@
+	mkdir -p obj-ack//./ip
+	cd ip && $(MAKE) $@
+	mkdir -p obj-ack//./math
+	cd math && $(MAKE) $@
+	mkdir -p obj-ack//./other
+	cd other && $(MAKE) $@
+	mkdir -p obj-ack//./posix
+	cd posix && $(MAKE) $@
+	mkdir -p obj-ack//./regex
+	cd regex && $(MAKE) $@
+	mkdir -p obj-ack//./stdio
+	cd stdio && $(MAKE) $@
+	mkdir -p obj-ack//./syscall
+	cd syscall && $(MAKE) $@
+	mkdir -p obj-ack//./syslib
+	cd syslib && $(MAKE) $@
+	mkdir -p obj-ack//./util
+	cd util && $(MAKE) $@
+	mkdir -p obj-ack//./sysutil
+	cd sysutil && $(MAKE) $@
+	mkdir -p obj-ack//./timers
+	cd timers && $(MAKE) $@
+	mkdir -p obj-ack//./i386
+	cd i386 && $(MAKE) $@
+	mkdir -p obj-ack//./zlib-1.2.3
+	cd zlib-1.2.3 && $(MAKE) $@
+	mkdir -p obj-ack//./ack
+	cd ack && $(MAKE) $@
+	mkdir -p obj-ack//./gnu
+	cd gnu && $(MAKE) $@
+
+all-gnu: makefiles
+	mkdir -p obj-gnu/./ansi
+	cd ansi && $(MAKE) $@
+	mkdir -p obj-gnu/./curses
+	cd curses && $(MAKE) $@
+	mkdir -p obj-gnu/./dummy
+	cd dummy && $(MAKE) $@
+	mkdir -p obj-gnu/./editline
+	cd editline && $(MAKE) $@
+	mkdir -p obj-gnu/./end
+	cd end && $(MAKE) $@
+	mkdir -p obj-gnu/./ip
+	cd ip && $(MAKE) $@
+	mkdir -p obj-gnu/./math
+	cd math && $(MAKE) $@
+	mkdir -p obj-gnu/./other
+	cd other && $(MAKE) $@
+	mkdir -p obj-gnu/./posix
+	cd posix && $(MAKE) $@
+	mkdir -p obj-gnu/./regex
+	cd regex && $(MAKE) $@
+	mkdir -p obj-gnu/./stdio
+	cd stdio && $(MAKE) $@
+	mkdir -p obj-gnu/./syscall
+	cd syscall && $(MAKE) $@
+	mkdir -p obj-gnu/./syslib
+	cd syslib && $(MAKE) $@
+	mkdir -p obj-gnu/./util
+	cd util && $(MAKE) $@
+	mkdir -p obj-gnu/./sysutil
+	cd sysutil && $(MAKE) $@
+	mkdir -p obj-gnu/./timers
+	cd timers && $(MAKE) $@
+	mkdir -p obj-gnu/./i386
+	cd i386 && $(MAKE) $@
+	mkdir -p obj-gnu/./zlib-1.2.3
+	cd zlib-1.2.3 && $(MAKE) $@
+	mkdir -p obj-gnu/./ack
+	cd ack && $(MAKE) $@
+	mkdir -p obj-gnu/./gnu
+	cd gnu && $(MAKE) $@
+
+clean depend depend-ack depend-gnu:: makefiles
+	cd ansi && $(MAKE) $@
+	cd curses && $(MAKE) $@
+	cd dummy && $(MAKE) $@
+	cd editline && $(MAKE) $@
+	cd end && $(MAKE) $@
+	cd ip && $(MAKE) $@
+	cd math && $(MAKE) $@
+	cd other && $(MAKE) $@
+	cd posix && $(MAKE) $@
+	cd regex && $(MAKE) $@
+	cd stdio && $(MAKE) $@
+	cd syscall && $(MAKE) $@
+	cd syslib && $(MAKE) $@
+	cd util && $(MAKE) $@
+	cd sysutil && $(MAKE) $@
+	cd timers && $(MAKE) $@
+	cd i386 && $(MAKE) $@
+	cd zlib-1.2.3 && $(MAKE) $@
+	cd ack && $(MAKE) $@
+	cd gnu && $(MAKE) $@
+
+makefiles: ansi/Makefile
+makefiles: curses/Makefile
+makefiles: dummy/Makefile
+makefiles: editline/Makefile
+makefiles: end/Makefile
+makefiles: ip/Makefile
+makefiles: math/Makefile
+makefiles: other/Makefile
+makefiles: posix/Makefile
+makefiles: regex/Makefile
+makefiles: stdio/Makefile
+makefiles: syscall/Makefile
+makefiles: syslib/Makefile
+makefiles: util/Makefile
+makefiles: sysutil/Makefile
+makefiles: timers/Makefile
+makefiles: i386/Makefile
+makefiles: zlib-1.2.3/Makefile
+makefiles: ack/Makefile
+makefiles: gnu/Makefile
+
+ansi/Makefile: ansi/Makefile.in
+	cd ansi && sh ../generate.sh ./ansi ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+curses/Makefile: curses/Makefile.in
+	cd curses && sh ../generate.sh ./curses ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+dummy/Makefile: dummy/Makefile.in
+	cd dummy && sh ../generate.sh ./dummy ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+editline/Makefile: editline/Makefile.in
+	cd editline && sh ../generate.sh ./editline ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+end/Makefile: end/Makefile.in
+	cd end && sh ../generate.sh ./end ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+ip/Makefile: ip/Makefile.in
+	cd ip && sh ../generate.sh ./ip ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+math/Makefile: math/Makefile.in
+	cd math && sh ../generate.sh ./math ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+other/Makefile: other/Makefile.in
+	cd other && sh ../generate.sh ./other ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+posix/Makefile: posix/Makefile.in
+	cd posix && sh ../generate.sh ./posix ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+regex/Makefile: regex/Makefile.in
+	cd regex && sh ../generate.sh ./regex ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+stdio/Makefile: stdio/Makefile.in
+	cd stdio && sh ../generate.sh ./stdio ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+syscall/Makefile: syscall/Makefile.in
+	cd syscall && sh ../generate.sh ./syscall ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+syslib/Makefile: syslib/Makefile.in
+	cd syslib && sh ../generate.sh ./syslib ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+util/Makefile: util/Makefile.in
+	cd util && sh ../generate.sh ./util ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+sysutil/Makefile: sysutil/Makefile.in
+	cd sysutil && sh ../generate.sh ./sysutil ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+timers/Makefile: timers/Makefile.in
+	cd timers && sh ../generate.sh ./timers ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+i386/Makefile: i386/Makefile.in
+	cd i386 && sh ../generate.sh ./i386 ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+zlib-1.2.3/Makefile: zlib-1.2.3/Makefile.in
+	cd zlib-1.2.3 && sh ../generate.sh ./zlib-1.2.3 ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+ack/Makefile: ack/Makefile.in
+	cd ack && sh ../generate.sh ./ack ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+gnu/Makefile: gnu/Makefile.in
+	cd gnu && sh ../generate.sh ./gnu ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
+
+clean::
+	rm -f obj-ack//./*
+	rm -f obj-gnu/./*
+
+install: install-ack
+
+install-ack: all-ack
+	cp obj-ack//*.[ao] /usr/lib/i386
+
+install-gnu: all-gnu
+	cp obj-gnu/*.[ao] /usr/gnu/lib
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/Makefile.in
===================================================================
--- /trunk/minix/lib/Makefile.in	(revision 9)
+++ /trunk/minix/lib/Makefile.in	(revision 9)
@@ -0,0 +1,28 @@
+
+#ACKBASE=$(CURDIR)/obj-ack
+#GNUBASE=$(CURDIR)/obj-gnu
+
+#OBJDIR=.
+
+SUBDIRS="ansi \
+	curses \
+	dummy \
+	editline \
+	end \
+	ip \
+	math \
+	other \
+	posix \
+	regex \
+	stdio \
+	syscall \
+	syslib \
+	util \
+	sysutil \
+	timers \
+	i386 \
+	zlib-1.2.3 \
+	ack
+	gnu"
+	
+TYPE=both
Index: /trunk/minix/lib/README
===================================================================
--- /trunk/minix/lib/README	(revision 9)
+++ /trunk/minix/lib/README	(revision 9)
@@ -0,0 +1,7 @@
+make depend  - find dependencies of ack libraries
+make all     - compile ack libraries
+make install - compile and install ack libraries
+
+make depend-gnu  - find dependencies of gnu libraries
+make all-gnu     - compile gnu libraries
+make install-gnu - compile and install gnu libraries
Index: /trunk/minix/lib/ack/Makefile
===================================================================
--- /trunk/minix/lib/ack/Makefile	(revision 9)
+++ /trunk/minix/lib/ack/Makefile	(revision 9)
@@ -0,0 +1,90 @@
+#Generated from ./ack/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./ack ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./ack ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+all-ack: makefiles
+	mkdir -p ../obj-ack//./ack/float
+	cd float && $(MAKE) $@
+	mkdir -p ../obj-ack//./ack/fphook
+	cd fphook && $(MAKE) $@
+	mkdir -p ../obj-ack//./ack/i386
+	cd i386 && $(MAKE) $@
+	mkdir -p ../obj-ack//./ack/libm2
+	cd libm2 && $(MAKE) $@
+	mkdir -p ../obj-ack//./ack/libp
+	cd libp && $(MAKE) $@
+	mkdir -p ../obj-ack//./ack/liby
+	cd liby && $(MAKE) $@
+	mkdir -p ../obj-ack//./ack/math
+	cd math && $(MAKE) $@
+	mkdir -p ../obj-ack//./ack/rts
+	cd rts && $(MAKE) $@
+
+all-gnu: makefiles
+	cd float && $(MAKE) $@
+	cd fphook && $(MAKE) $@
+	cd i386 && $(MAKE) $@
+	cd libm2 && $(MAKE) $@
+	cd libp && $(MAKE) $@
+	cd liby && $(MAKE) $@
+	cd math && $(MAKE) $@
+	cd rts && $(MAKE) $@
+
+clean depend depend-ack depend-gnu:: makefiles
+	cd float && $(MAKE) $@
+	cd fphook && $(MAKE) $@
+	cd i386 && $(MAKE) $@
+	cd libm2 && $(MAKE) $@
+	cd libp && $(MAKE) $@
+	cd liby && $(MAKE) $@
+	cd math && $(MAKE) $@
+	cd rts && $(MAKE) $@
+
+makefiles: float/Makefile
+makefiles: fphook/Makefile
+makefiles: i386/Makefile
+makefiles: libm2/Makefile
+makefiles: libp/Makefile
+makefiles: liby/Makefile
+makefiles: math/Makefile
+makefiles: rts/Makefile
+
+float/Makefile: float/Makefile.in
+	cd float && sh ../../generate.sh ./ack/float ../../obj-ack/ ../../obj-gnu && $(MAKE) makefiles
+fphook/Makefile: fphook/Makefile.in
+	cd fphook && sh ../../generate.sh ./ack/fphook ../../obj-ack/ ../../obj-gnu && $(MAKE) makefiles
+i386/Makefile: i386/Makefile.in
+	cd i386 && sh ../../generate.sh ./ack/i386 ../../obj-ack/ ../../obj-gnu && $(MAKE) makefiles
+libm2/Makefile: libm2/Makefile.in
+	cd libm2 && sh ../../generate.sh ./ack/libm2 ../../obj-ack/ ../../obj-gnu && $(MAKE) makefiles
+libp/Makefile: libp/Makefile.in
+	cd libp && sh ../../generate.sh ./ack/libp ../../obj-ack/ ../../obj-gnu && $(MAKE) makefiles
+liby/Makefile: liby/Makefile.in
+	cd liby && sh ../../generate.sh ./ack/liby ../../obj-ack/ ../../obj-gnu && $(MAKE) makefiles
+math/Makefile: math/Makefile.in
+	cd math && sh ../../generate.sh ./ack/math ../../obj-ack/ ../../obj-gnu && $(MAKE) makefiles
+rts/Makefile: rts/Makefile.in
+	cd rts && sh ../../generate.sh ./ack/rts ../../obj-ack/ ../../obj-gnu && $(MAKE) makefiles
+
+clean::
+	rm -f ../obj-ack//./ack/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/ack/Makefile.in
===================================================================
--- /trunk/minix/lib/ack/Makefile.in	(revision 9)
+++ /trunk/minix/lib/ack/Makefile.in	(revision 9)
@@ -0,0 +1,12 @@
+
+SUBDIRS=" \
+	float \
+	fphook \
+	i386 \
+	libm2 \
+	libp \
+	liby \
+	math \
+	rts"
+
+TYPE=ack
Index: /trunk/minix/lib/ack/float/FP.compile
===================================================================
--- /trunk/minix/lib/ack/float/FP.compile	(revision 9)
+++ /trunk/minix/lib/ack/float/FP.compile	(revision 9)
@@ -0,0 +1,22 @@
+#!/bin/sh
+#							Author: Kees J. Bot
+# Compile one soft FP source file.
+# (These files shouldn't be optimized normally, but the 16-bit C compiler
+# only optimizes scratch register allocation a bit with -O.  To the 32-bit
+# compiler -O is a no-op.)
+
+case $#:$2 in
+2:*.fc)	;;
+*)	echo "$0: $1: not a FC file" >&2; exit 1
+esac
+
+dst=$1
+src=$2
+base="`basename "$src" .fc`"
+trap 'rm -f tmp.c tmp.s"; exit 1' 2
+
+cp "$src" tmp.c &&
+cc -O -I. -D_MINIX -D_POSIX_SOURCE -S tmp.c &&
+sed -f FP.script tmp.s > "$base.s" &&
+cc -c -o $dst "$base.s" &&
+rm tmp.c tmp.s
Index: /trunk/minix/lib/ack/float/FP.script
===================================================================
--- /trunk/minix/lib/ack/float/FP.script	(revision 9)
+++ /trunk/minix/lib/ack/float/FP.script	(revision 9)
@@ -0,0 +1,39 @@
+s/_adf4/.adf4/
+s/_adf8/.adf8/
+s/_cff4/.cff4/
+s/_cff8/.cff8/
+s/_cfi/.cfi/
+s/_cfu/.cfu/
+s/_cif4/.cif4/
+s/_cif8/.cif8/
+s/_cmf4/.cmf4/
+s/_cmf8/.cmf8/
+s/_cuf4/.cuf4/
+s/_cuf8/.cuf8/
+s/_dvf4/.dvf4/
+s/_dvf8/.dvf8/
+s/_fef4/.fef4/
+s/_fef8/.fef8/
+s/_fif4/.fif4/
+s/_fif8/.fif8/
+s/_mlf4/.mlf4/
+s/_mlf8/.mlf8/
+s/_ngf4/.ngf4/
+s/_ngf8/.ngf8/
+s/_sbf4/.sbf4/
+s/_sbf8/.sbf8/
+s/_zrf4/.zrf4/
+s/_zrf8/.zrf8/
+s/_add_ext/.add_ext/
+s/_div_ext/.div_ext/
+s/_mul_ext/.mul_ext/
+s/_nrm_ext/.nrm_ext/
+s/_sft_ext/.sft_ext/
+s/_sub_ext/.sub_ext/
+s/_zrf_ext/.zrf_ext/
+s/_compact/.compact/
+s/_extend/.extend/
+s/_b64_add/.b64_add/
+s/_b64_sft/.b64_sft/
+s/_b64_rsft/.b64_rsft/
+s/_b64_lsft/.b64_lsft/
Index: /trunk/minix/lib/ack/float/FP_bias.h
===================================================================
--- /trunk/minix/lib/ack/float/FP_bias.h	(revision 9)
+++ /trunk/minix/lib/ack/float/FP_bias.h	(revision 9)
@@ -0,0 +1,28 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/FP_bias.h,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	include file for floating point package
+*/
+
+		/*	FLOAT FORMAT EXPONENT BIAS	*/
+
+#define	SGL_BIAS	 127	/* excess  128 notation used	*/
+#define	DBL_BIAS	1023	/* excess 1024 notation used	*/
+#define	EXT_BIAS	   0	/* 2s-complement notation used	*/
+				/* this is possible because the	*/
+				/* sign is in a seperate word	*/
+		
+		/*	VARIOUS MAX AND MIN VALUES	*/
+		/*	1) FOR THE DIFFERENT FORMATS	*/
+
+#define	SGL_MAX		   254	/*	standard definition	*/
+#define	SGL_MIN		     1	/*	standard definition	*/
+#define	DBL_MAX		  2046	/*	standard definition	*/
+#define	DBL_MIN		     1	/*	standard definition	*/
+#define EXT_MAX		 16383	/*	standard minimum	*/
+#define EXT_MIN		-16382	/*	standard minimum	*/
Index: /trunk/minix/lib/ack/float/FP_shift.h
===================================================================
--- /trunk/minix/lib/ack/float/FP_shift.h	(revision 9)
+++ /trunk/minix/lib/ack/float/FP_shift.h	(revision 9)
@@ -0,0 +1,49 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/FP_shift.h,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	include file for floating point package
+*/
+
+# define	CARRYBIT	0x80000000L
+# define	NORMBIT		0x80000000L
+# define	EXP_STORE	16
+
+
+				/* parameters for Single Precision */
+#define SGL_EXPSHIFT	7
+#define SGL_M1LEFT	8
+#define SGL_ZERO	0xffffff80L
+#define SGL_EXACT	0xff
+#define SGL_RUNPACK	SGL_M1LEFT
+
+#define SGL_ROUNDUP	0x80
+#define	SGL_CARRYOUT	0x01000000L
+#define	SGL_MASK	0x007fffffL
+
+				/* parameters for Double Precision */
+				/* used in extend.c */
+
+#define DBL_EXPSHIFT	4
+
+#define DBL_M1LEFT	11
+
+#define	DBL_RPACK	(32-DBL_M1LEFT)
+#define	DBL_LPACK	DBL_M1LEFT
+
+				/* used in compact.c */
+
+#define DBL_ZERO	0xfffffd00L
+
+#define DBL_EXACT	0x7ff
+
+#define DBL_RUNPACK	DBL_M1LEFT
+#define DBL_LUNPACK	(32-DBL_RUNPACK)
+
+#define DBL_ROUNDUP	0x400
+#define	DBL_CARRYOUT	0x00200000L
+#define	DBL_MASK	0x000fffffL
Index: /trunk/minix/lib/ack/float/FP_trap.h
===================================================================
--- /trunk/minix/lib/ack/float/FP_trap.h	(revision 9)
+++ /trunk/minix/lib/ack/float/FP_trap.h	(revision 9)
@@ -0,0 +1,22 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/FP_trap.h,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	include file for floating point package
+*/
+
+			/*	EM TRAPS	*/
+
+#define	EIOVFL	3	/* Integer  Overflow		*/
+#define	EFOVFL	4	/* Floating Overflow		*/
+#define	EFUNFL	5	/* Floating Underflow		*/
+#define	EIDIVZ	6	/* Integer  Divide by 0		*/
+#define	EFDIVZ	7	/* Floating Divide by 0.0	*/
+#define	EIUND	8	/* Integer  Undefined Number	*/
+#define	EFUND	9	/* Floating Undefined Number	*/
+#define	ECONV	10	/* Conversion Error		*/
+# define trap(x) _fptrp(x)
Index: /trunk/minix/lib/ack/float/FP_types.h
===================================================================
--- /trunk/minix/lib/ack/float/FP_types.h	(revision 9)
+++ /trunk/minix/lib/ack/float/FP_types.h	(revision 9)
@@ -0,0 +1,113 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/FP_types.h,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/********************************************************/
+/*
+	Type definitions for C Floating Point Package
+	include file for floating point package
+*/
+/********************************************************/
+/*
+	THESE STRUCTURES ARE USED TO ADDRESS THE INDIVIDUAL
+	PARTS OF THE FLOATING POINT NUMBER REPRESENTATIONS.
+
+	THREE STRUCTURES ARE DEFINED:
+		SINGLE:	single precision floating format
+		DOUBLE:	double precision floating format
+		EXTEND:	double precision extended format
+*/
+/********************************************************/
+
+#ifndef __FPTYPES
+#define __FPTYPES
+
+typedef	struct	{
+	unsigned long	h_32;	/* higher 32 bits of 64 */
+	unsigned long	l_32;	/* lower  32 bits of 64 */
+}	B64;
+
+typedef	unsigned long	SINGLE;
+
+typedef	struct	{
+	unsigned long	d[2];
+}	DOUBLE;
+
+typedef	struct	{	/* expanded float format	*/
+	short	sign;
+	short	exp;
+	B64	mantissa;
+#define m1 mantissa.h_32
+#define m2 mantissa.l_32
+} EXTEND;
+
+struct	fef4_returns {
+	int	e;
+	SINGLE	f;
+};
+
+struct	fef8_returns {
+	int	e;
+	DOUBLE	f;
+};
+
+struct fif4_returns {
+	SINGLE ipart;
+	SINGLE fpart;
+};
+
+struct fif8_returns {
+	DOUBLE ipart;
+	DOUBLE fpart;
+};
+
+#if __STDC__
+#define _PROTOTYPE(function, params)	function params
+#else
+#define _PROTOTYPE(function, params)	function()
+#endif
+_PROTOTYPE( void add_ext, (EXTEND *e1, EXTEND *e2));
+_PROTOTYPE( void mul_ext, (EXTEND *e1, EXTEND *e2));
+_PROTOTYPE( void div_ext, (EXTEND *e1, EXTEND *e2));
+_PROTOTYPE( void sub_ext, (EXTEND *e1, EXTEND *e2));
+_PROTOTYPE( void sft_ext, (EXTEND *e1, EXTEND *e2));
+_PROTOTYPE( void nrm_ext, (EXTEND *e1));
+_PROTOTYPE( void zrf_ext, (EXTEND *e1));
+_PROTOTYPE( void extend, (unsigned long *from, EXTEND *to, int size));
+_PROTOTYPE( void compact, (EXTEND *from, unsigned long *to, int size));
+_PROTOTYPE( void _fptrp, (int));
+_PROTOTYPE( void adf4, (SINGLE s2, SINGLE s1));
+_PROTOTYPE( void adf8, (DOUBLE s2, DOUBLE s1));
+_PROTOTYPE( void sbf4, (SINGLE s2, SINGLE s1));
+_PROTOTYPE( void sbf8, (DOUBLE s2, DOUBLE s1));
+_PROTOTYPE( void dvf4, (SINGLE s2, SINGLE s1));
+_PROTOTYPE( void dvf8, (DOUBLE s2, DOUBLE s1));
+_PROTOTYPE( void mlf4, (SINGLE s2, SINGLE s1));
+_PROTOTYPE( void mlf8, (DOUBLE s2, DOUBLE s1));
+_PROTOTYPE( void ngf4, (SINGLE f));
+_PROTOTYPE( void ngf8, (DOUBLE f));
+_PROTOTYPE( void zrf4, (SINGLE *l));
+_PROTOTYPE( void zrf8, (DOUBLE *z));
+_PROTOTYPE( void cff4, (DOUBLE src));
+_PROTOTYPE( void cff8, (SINGLE src));
+_PROTOTYPE( void cif4, (int ss, long src));
+_PROTOTYPE( void cif8, (int ss, long src));
+_PROTOTYPE( void cuf4, (int ss, long src));
+_PROTOTYPE( void cuf8, (int ss, long src));
+_PROTOTYPE( long cfu, (int ds, int ss, DOUBLE src));
+_PROTOTYPE( long cfi, (int ds, int ss, DOUBLE src));
+_PROTOTYPE( int cmf4, (SINGLE s2, SINGLE s1));
+_PROTOTYPE( int cmf8, (DOUBLE d1, DOUBLE d2));
+_PROTOTYPE( void fef4, (struct fef4_returns *r, SINGLE s1));
+_PROTOTYPE( void fef8, (struct fef8_returns *r, DOUBLE s1));
+_PROTOTYPE( void fif4, (struct fif4_returns *p, SINGLE x, SINGLE y));
+_PROTOTYPE( void fif8, (struct fif8_returns *p, DOUBLE x, DOUBLE y));
+
+_PROTOTYPE( void b64_sft, (B64 *, int));
+_PROTOTYPE( void b64_lsft, (B64 *));
+_PROTOTYPE( void b64_rsft, (B64 *));
+_PROTOTYPE( int b64_add, (B64 *, B64 *));
+#endif
Index: /trunk/minix/lib/ack/float/Makedepend-ack
===================================================================
--- /trunk/minix/lib/ack/float/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/ack/float/Makedepend-ack	(revision 9)
@@ -0,0 +1,41 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -E' add_ext.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' adder.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' adf4.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' adf8.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' cff4.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' cff8.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' cfi.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' cfu.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' cif4.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' cif8.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' cmf4.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' cmf8.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' compact.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' cuf4.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' cuf8.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' div_ext.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' dvf4.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' dvf8.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' extend.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' fef4.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' fef8.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' fif4.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' fif8.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc  -E' fptrp.s | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' mlf4.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' mlf8.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' mul_ext.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' ngf4.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' ngf8.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' nrm_ext.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' sbf4.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' sbf8.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' sft_ext.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' shifter.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' sub_ext.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' zrf4.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' zrf8.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
+	mkdep 'cc -E' zrf_ext.fc | sed -e 's:^\(.\):../../obj-ack//./ack/float/\1:' >> .depend-ack
Index: /trunk/minix/lib/ack/float/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/ack/float/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/ack/float/Makedepend-gnu	(revision 9)
@@ -0,0 +1,3 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
Index: /trunk/minix/lib/ack/float/Makefile
===================================================================
--- /trunk/minix/lib/ack/float/Makefile	(revision 9)
+++ /trunk/minix/lib/ack/float/Makefile	(revision 9)
@@ -0,0 +1,151 @@
+#Generated from ./ack/float/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../generate.sh ./ack/float ../../obj-ack/ ../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../generate.sh ./ack/float ../../obj-ack/ ../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../../obj-ack//libfp.a
+
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(add_ext.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(adder.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(adf4.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(adf8.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(cff4.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(cff8.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(cfi.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(cfu.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(cif4.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(cif8.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(cmf4.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(cmf8.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(compact.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(cuf4.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(cuf8.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(div_ext.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(dvf4.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(dvf8.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(extend.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(fef4.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(fef8.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(fif4.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(fif8.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(fptrp.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(mlf4.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(mlf8.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(mul_ext.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(ngf4.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(ngf8.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(nrm_ext.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(sbf4.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(sbf8.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(sft_ext.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(shifter.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(sub_ext.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(zrf4.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(zrf8.o)
+../../obj-ack//libfp.a: ../../obj-ack//libfp.a(zrf_ext.o)
+
+../../obj-ack//libfp.a:
+	ar cr ../../obj-ack//libfp.a ../../obj-ack//./ack/float/*.o
+	rm ../../obj-ack//./ack/float/*.o
+
+../../obj-ack//libfp.a(add_ext.o): add_ext.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/add_ext.o add_ext.fc
+../../obj-ack//libfp.a(adder.o): adder.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/adder.o adder.fc
+../../obj-ack//libfp.a(adf4.o): adf4.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/adf4.o adf4.fc
+../../obj-ack//libfp.a(adf8.o): adf8.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/adf8.o adf8.fc
+../../obj-ack//libfp.a(cff4.o): cff4.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/cff4.o cff4.fc
+../../obj-ack//libfp.a(cff8.o): cff8.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/cff8.o cff8.fc
+../../obj-ack//libfp.a(cfi.o): cfi.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/cfi.o cfi.fc
+../../obj-ack//libfp.a(cfu.o): cfu.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/cfu.o cfu.fc
+../../obj-ack//libfp.a(cif4.o): cif4.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/cif4.o cif4.fc
+../../obj-ack//libfp.a(cif8.o): cif8.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/cif8.o cif8.fc
+../../obj-ack//libfp.a(cmf4.o): cmf4.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/cmf4.o cmf4.fc
+../../obj-ack//libfp.a(cmf8.o): cmf8.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/cmf8.o cmf8.fc
+../../obj-ack//libfp.a(compact.o): compact.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/compact.o compact.fc
+../../obj-ack//libfp.a(cuf4.o): cuf4.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/cuf4.o cuf4.fc
+../../obj-ack//libfp.a(cuf8.o): cuf8.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/cuf8.o cuf8.fc
+../../obj-ack//libfp.a(div_ext.o): div_ext.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/div_ext.o div_ext.fc
+../../obj-ack//libfp.a(dvf4.o): dvf4.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/dvf4.o dvf4.fc
+../../obj-ack//libfp.a(dvf8.o): dvf8.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/dvf8.o dvf8.fc
+../../obj-ack//libfp.a(extend.o): extend.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/extend.o extend.fc
+../../obj-ack//libfp.a(fef4.o): fef4.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/fef4.o fef4.fc
+../../obj-ack//libfp.a(fef8.o): fef8.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/fef8.o fef8.fc
+../../obj-ack//libfp.a(fif4.o): fif4.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/fif4.o fif4.fc
+../../obj-ack//libfp.a(fif8.o): fif8.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/fif8.o fif8.fc
+../../obj-ack//libfp.a(fptrp.o): fptrp.s
+	cc  -c -o ../../obj-ack//./ack/float/fptrp.o fptrp.s
+../../obj-ack//libfp.a(mlf4.o): mlf4.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/mlf4.o mlf4.fc
+../../obj-ack//libfp.a(mlf8.o): mlf8.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/mlf8.o mlf8.fc
+../../obj-ack//libfp.a(mul_ext.o): mul_ext.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/mul_ext.o mul_ext.fc
+../../obj-ack//libfp.a(ngf4.o): ngf4.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/ngf4.o ngf4.fc
+../../obj-ack//libfp.a(ngf8.o): ngf8.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/ngf8.o ngf8.fc
+../../obj-ack//libfp.a(nrm_ext.o): nrm_ext.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/nrm_ext.o nrm_ext.fc
+../../obj-ack//libfp.a(sbf4.o): sbf4.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/sbf4.o sbf4.fc
+../../obj-ack//libfp.a(sbf8.o): sbf8.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/sbf8.o sbf8.fc
+../../obj-ack//libfp.a(sft_ext.o): sft_ext.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/sft_ext.o sft_ext.fc
+../../obj-ack//libfp.a(shifter.o): shifter.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/shifter.o shifter.fc
+../../obj-ack//libfp.a(sub_ext.o): sub_ext.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/sub_ext.o sub_ext.fc
+../../obj-ack//libfp.a(zrf4.o): zrf4.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/zrf4.o zrf4.fc
+../../obj-ack//libfp.a(zrf8.o): zrf8.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/zrf8.o zrf8.fc
+../../obj-ack//libfp.a(zrf_ext.o): zrf_ext.fc
+	sh ./FP.compile ../../obj-ack//./ack/float/zrf_ext.o zrf_ext.fc
+
+
+
+clean::
+	rm -f ../../obj-ack//./ack/float/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/ack/float/Makefile.in
===================================================================
--- /trunk/minix/lib/ack/float/Makefile.in	(revision 9)
+++ /trunk/minix/lib/ack/float/Makefile.in	(revision 9)
@@ -0,0 +1,61 @@
+# Makefile for lib/float.
+
+#CC1	= /bin/sh ./FP.compile
+
+LIBRARIES=libfp
+
+libfp_FILES=" \
+	add_ext.fc \
+	adder.fc \
+	adf4.fc \
+	adf8.fc \
+	cff4.fc \
+	cff8.fc \
+	cfi.fc \
+	cfu.fc \
+	cif4.fc \
+	cif8.fc \
+	cmf4.fc \
+	cmf8.fc \
+	compact.fc \
+	cuf4.fc \
+	cuf8.fc \
+	div_ext.fc \
+	dvf4.fc \
+	dvf8.fc \
+	extend.fc \
+	fef4.fc \
+	fef8.fc \
+	fif4.fc \
+	fif8.fc \
+	fptrp.s \
+	mlf4.fc \
+	mlf8.fc \
+	mul_ext.fc \
+	ngf4.fc \
+	ngf8.fc \
+	nrm_ext.fc \
+	sbf4.fc \
+	sbf8.fc \
+	sft_ext.fc \
+	shifter.fc \
+	sub_ext.fc \
+	zrf4.fc \
+	zrf8.fc \
+	zrf_ext.fc"
+
+TYPE=ack
+
+#extra commands to convert the c files to the correct assembler files
+
+#%.s: %.fc
+#	/bin/sh ./FP.compile $<
+
+#1. make a assembler file of the c file
+#%.fs: %.fc
+#	-cp $< $(<:.fc=.c) && cc -O -I. -D_MINIX -D_POSIX_SOURCE -S $(<:.fc=.c) && cp $(<:.fc=.s) $(<:.fc=.fs)
+#	@rm $(<:.fc=.c) $(<:.fc=.s)
+
+#2. modify the assembler file
+#%.s: %.fs
+#	sed -f FP.script $< > $@
Index: /trunk/minix/lib/ack/float/add_ext.fc
===================================================================
--- /trunk/minix/lib/ack/float/add_ext.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/add_ext.fc	(revision 9)
@@ -0,0 +1,56 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/add_ext.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	ADD TWO EXTENDED FORMAT NUMBERS
+*/
+
+#include "FP_types.h"
+
+void
+add_ext(e1,e2)
+register EXTEND	*e1,*e2;
+{
+	if ((e2->m1 | e2->m2) == 0L) {
+		return;
+	}
+	if ((e1->m1 | e1->m2) == 0L) {
+		*e1 = *e2;
+		return;
+	}
+	sft_ext(e1, e2);	/* adjust mantissas to equal powers */
+	if (e1->sign != e2->sign) {
+		/* e1 + e2 = e1 - (-e2) */
+		if (e2->m1 > e1->m1 ||
+                    (e2->m1 == e1->m1 && e2->m2 > e1->m2)) {
+                	/*      abs(e2) > abs(e1) */
+			EXTEND x;
+
+			x = *e1;
+			*e1 = *e2;
+                	if (x.m2 > e1->m2) {
+                        	e1->m1 -= 1;    /* carry in */
+                	}
+                	e1->m1 -= x.m1;
+                	e1->m2 -= x.m2;
+        	}
+        	else {
+                	if (e2->m2 > e1->m2)
+                        	e1->m1 -= 1;    /* carry in */
+                	e1->m1 -= e2->m1;
+                	e1->m2 -= e2->m2;
+        	}
+	}
+	else {
+		if (b64_add(&e1->mantissa,&e2->mantissa)) {	/* addition carry */
+			b64_rsft(&e1->mantissa);	/* shift mantissa one bit RIGHT */
+			e1->m1 |= 0x80000000L;	/* set max bit	*/
+			e1->exp++;		/* increase the exponent */
+		}
+	}
+	nrm_ext(e1);
+}
Index: /trunk/minix/lib/ack/float/add_ext.s
===================================================================
--- /trunk/minix/lib/ack/float/add_ext.s	(revision 9)
+++ /trunk/minix/lib/ack/float/add_ext.s	(revision 9)
@@ -0,0 +1,107 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .add_ext
+.sect .text
+.add_ext:
+push ebp
+mov ebp,esp
+sub	esp,12
+push esi
+push edi
+mov esi,8(ebp)
+mov edi,12(ebp)
+mov edx,8(edi)
+or edx,4(edi)
+je I1_1
+mov edx,8(esi)
+or edx,4(esi)
+jne I1_7
+push edi
+push esi
+mov ecx,3
+call .blm
+jmp I1_1
+I1_7:
+push edi
+push esi
+call .sft_ext
+pop ecx
+pop ecx
+movsx eax,(esi)
+movsx ebx,(edi)
+cmp eax,ebx
+je I1_10
+mov edx,4(esi)
+cmp 4(edi),edx
+ja I1_12
+cmp 4(edi),edx
+jne I1_13
+mov edx,8(esi)
+cmp 8(edi),edx
+jbe I1_13
+I1_12:
+push esi
+lea eax,-12(ebp)
+push eax
+mov ecx,3
+call .blm
+push edi
+push esi
+mov ecx,3
+call .blm
+mov edx,-4(ebp)
+cmp 8(esi),edx
+jae I1_18
+mov edx,4(esi)
+sub edx,1
+mov 4(esi),edx
+I1_18:
+mov edx,4(esi)
+sub edx,-8(ebp)
+mov 4(esi),edx
+mov edx,8(esi)
+sub edx,-4(ebp)
+mov 8(esi),edx
+jmp I1_11
+I1_13:
+mov edx,8(esi)
+cmp 8(edi),edx
+jbe I1_21
+mov edx,4(esi)
+sub edx,1
+mov 4(esi),edx
+I1_21:
+mov edx,4(esi)
+sub edx,4(edi)
+mov 4(esi),edx
+mov edx,8(esi)
+sub edx,8(edi)
+mov 8(esi),edx
+jmp I1_11
+I1_10:
+lea eax,4(edi)
+push eax
+lea eax,4(esi)
+push eax
+call .b64_add
+pop ecx
+pop ecx
+test eax,eax
+je I1_11
+lea eax,4(esi)
+push eax
+call .b64_rsft
+pop ecx
+or 4(esi),-2147483648
+movsx eax,2(esi)
+inc eax
+movsx eax,eax
+o16 mov 2(esi),eax
+I1_11:
+push esi
+call .nrm_ext
+pop ecx
+I1_1:
+pop edi
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/adder.fc
===================================================================
--- /trunk/minix/lib/ack/float/adder.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/adder.fc	(revision 9)
@@ -0,0 +1,50 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/adder.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+ *	these are the routines the routines to do 32 and  64-bit addition
+ */
+
+# ifdef	EXT_DEBUG
+# include <stdio.h>
+# endif
+
+# include "FP_types.h"
+# define	UNKNOWN -1
+# define	TRUE	 1
+# define	FALSE	 0
+# define	MAXBIT	0x80000000L
+
+	/*
+	 *	add 64 bits
+	 */
+int
+b64_add(e1,e2)
+		/*
+		 * pointers to 64 bit 'registers'
+		 */
+register	B64	*e1,*e2;
+{
+		register	int	overflow;
+				int	carry;
+
+			/* add higher pair of 32 bits */
+	overflow = ((unsigned long) 0xFFFFFFFF - e1->h_32 < e2->h_32);
+	e1->h_32 += e2->h_32;
+
+			/* add lower pair of 32 bits */
+	carry = ((unsigned long) 0xFFFFFFFF - e1->l_32 < e2->l_32);
+	e1->l_32 += e2->l_32;
+# ifdef	EXT_DEBUG
+	printf("\t\t\t\t\tb64_add: overflow (%d); internal carry(%d)\n",
+					overflow,carry);
+	fflush(stdout);
+# endif
+	if ((carry) && (++e1->h_32 == 0))
+		return(TRUE);		/* had a 64 bit overflow */
+	return(overflow);		/* return status from higher add */
+}
Index: /trunk/minix/lib/ack/float/adder.h
===================================================================
--- /trunk/minix/lib/ack/float/adder.h	(revision 9)
+++ /trunk/minix/lib/ack/float/adder.h	(revision 9)
@@ -0,0 +1,15 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/adder.h,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+ *	include file for 32 & 64 bit addition
+ */
+
+typedef	struct	B64 {
+	unsigned long	h_32;	/* higher 32 bits of 64 */
+	unsigned long	l_32;	/* lower  32 bits of 64 */
+}	B64;
Index: /trunk/minix/lib/ack/float/adder.s
===================================================================
--- /trunk/minix/lib/ack/float/adder.s	(revision 9)
+++ /trunk/minix/lib/ack/float/adder.s	(revision 9)
@@ -0,0 +1,46 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .b64_add
+.sect .text
+.b64_add:
+push ebp
+mov ebp,esp
+sub	esp,8
+push esi
+push edi
+mov esi,8(ebp)
+mov edi,12(ebp)
+mov edx,-1
+sub edx,(esi)
+xor eax,eax
+cmp (edi),edx
+jbe 1f
+inc eax
+1:
+mov -4(ebp),eax
+mov edx,(edi)
+add (esi),edx
+mov edx,-1
+sub edx,4(esi)
+xor eax,eax
+cmp 4(edi),edx
+jbe 1f
+inc eax
+1:
+mov -8(ebp),eax
+mov edx,4(edi)
+add 4(esi),edx
+cmp -8(ebp),0
+je I1_4
+mov edx,(esi)
+inc edx
+mov (esi),edx
+jne I1_4
+mov eax,1
+jmp I1_1
+I1_4:
+mov eax,-4(ebp)
+I1_1:
+pop edi
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/adf4.fc
===================================================================
--- /trunk/minix/lib/ack/float/adf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/adf4.fc	(revision 9)
@@ -0,0 +1,32 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/adf4.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	ADD TWO FLOATS - SINGLE (ADF 4)
+*/
+
+#include	"FP_types.h"
+
+void
+adf4(s2,s1)
+SINGLE	s1,s2;
+{
+	EXTEND	e1,e2;
+	int	swap = 0;
+
+	if (s1 == (SINGLE) 0) {
+		s1 = s2;
+		return;
+	}
+	if (s2 == (SINGLE) 0) {
+		return;
+	}
+	extend(&s1,&e1,sizeof(SINGLE));
+	extend(&s2,&e2,sizeof(SINGLE));
+	add_ext(&e1,&e2);
+	compact(&e1,&s1,sizeof(SINGLE));
+}
Index: /trunk/minix/lib/ack/float/adf4.s
===================================================================
--- /trunk/minix/lib/ack/float/adf4.s	(revision 9)
+++ /trunk/minix/lib/ack/float/adf4.s	(revision 9)
@@ -0,0 +1,47 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .adf4
+.sect .text
+.adf4:
+push ebp
+mov ebp,esp
+sub	esp,28
+mov -28(ebp),0
+cmp 12(ebp),0
+jne I1_4
+mov edx,8(ebp)
+mov 12(ebp),edx
+jmp I1_1
+I1_4:
+cmp 8(ebp),0
+je I1_1
+push 4
+lea eax,-12(ebp)
+push eax
+lea eax,12(ebp)
+push eax
+call .extend
+add esp,12
+push 4
+lea eax,-24(ebp)
+push eax
+lea eax,8(ebp)
+push eax
+call .extend
+add esp,12
+lea eax,-24(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .add_ext
+pop ecx
+pop ecx
+push 4
+lea eax,12(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+I1_1:
+leave
+ret
Index: /trunk/minix/lib/ack/float/adf8.fc
===================================================================
--- /trunk/minix/lib/ack/float/adf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/adf8.fc	(revision 9)
@@ -0,0 +1,32 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/adf8.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	ADD TWO FLOATS - DOUBLE (ADF 8)
+*/
+
+#include	"FP_types.h"
+
+void
+adf8(s2,s1)
+DOUBLE	s1,s2;
+{
+	EXTEND	e1,e2;
+
+	if (s1.d[0] == 0 && s1.d[1] == 0) {
+		s1 = s2;
+		return;
+	}
+	if (s2.d[0] == 0 && s2.d[1] == 0) {
+		return;
+	}
+
+	extend(&s1.d[0],&e1,sizeof(DOUBLE));
+	extend(&s2.d[0],&e2,sizeof(DOUBLE));
+	add_ext(&e1,&e2);
+	compact(&e1,&s1.d[0],sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/ack/float/adf8.s
===================================================================
--- /trunk/minix/lib/ack/float/adf8.s	(revision 9)
+++ /trunk/minix/lib/ack/float/adf8.s	(revision 9)
@@ -0,0 +1,53 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .adf8
+.sect .text
+.adf8:
+push ebp
+mov ebp,esp
+sub	esp,24
+cmp 16(ebp),0
+jne I1_4
+cmp 20(ebp),0
+jne I1_4
+mov edx,8(ebp)
+mov ecx,12(ebp)
+mov 16(ebp),edx
+mov 20(ebp),ecx
+jmp I1_1
+I1_4:
+cmp 8(ebp),0
+jne I1_8
+cmp 12(ebp),0
+je I1_1
+I1_8:
+push 8
+lea eax,-12(ebp)
+push eax
+lea eax,16(ebp)
+push eax
+call .extend
+add esp,12
+push 8
+lea eax,-24(ebp)
+push eax
+lea eax,8(ebp)
+push eax
+call .extend
+add esp,12
+lea eax,-24(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .add_ext
+pop ecx
+pop ecx
+push 8
+lea eax,16(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+I1_1:
+leave
+ret
Index: /trunk/minix/lib/ack/float/byte_order.h
===================================================================
--- /trunk/minix/lib/ack/float/byte_order.h	(revision 9)
+++ /trunk/minix/lib/ack/float/byte_order.h	(revision 9)
@@ -0,0 +1,6 @@
+#define CHAR_UNSIGNED	0
+#define MSB_AT_LOW_ADDRESS	0
+#define MSW_AT_LOW_ADDRESS	0
+#define FL_MSB_AT_LOW_ADDRESS	0
+#define FL_MSW_AT_LOW_ADDRESS	0
+#define FL_MSL_AT_LOW_ADDRESS	0
Index: /trunk/minix/lib/ack/float/cff4.fc
===================================================================
--- /trunk/minix/lib/ack/float/cff4.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/cff4.fc	(revision 9)
@@ -0,0 +1,28 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/cff4.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+		CONVERT DOUBLE TO SINGLE (CFF 8 4)
+
+	This routine works quite simply. A floating point
+	of size 08 is converted to extended format.
+	This extended variable is converted back to
+	a floating point of size 04.
+
+*/
+
+#include	"FP_types.h"
+
+void
+cff4(src)
+DOUBLE	src;	/* the source itself -	THIS TIME it's DOUBLE */
+{
+	EXTEND	buf;
+
+	extend(&src.d[0],&buf,sizeof(DOUBLE));	/* no matter what */
+	compact(&buf,&(src.d[1]),sizeof(SINGLE));
+}
Index: /trunk/minix/lib/ack/float/cff4.s
===================================================================
--- /trunk/minix/lib/ack/float/cff4.s	(revision 9)
+++ /trunk/minix/lib/ack/float/cff4.s	(revision 9)
@@ -0,0 +1,23 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .cff4
+.sect .text
+.cff4:
+push ebp
+mov ebp,esp
+sub	esp,12
+push 8
+lea eax,-12(ebp)
+push eax
+lea eax,8(ebp)
+push eax
+call .extend
+add esp,12
+push 4
+lea eax,12(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+leave
+ret
Index: /trunk/minix/lib/ack/float/cff8.fc
===================================================================
--- /trunk/minix/lib/ack/float/cff8.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/cff8.fc	(revision 9)
@@ -0,0 +1,28 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/cff8.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+		CONVERT SINGLE TO DOUBLE (CFF 4 8)
+
+	This routine works quite simply. A floating point
+	of size 04 is converted to extended format.
+	This extended variable is converted back to
+	a floating point of size 08.
+
+*/
+
+#include "FP_types.h"
+
+void
+cff8(src)
+SINGLE	src;
+{
+	EXTEND	buf;
+
+	extend(&src,&buf,sizeof(SINGLE));	/* no matter what */
+	compact(&buf, &src,sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/ack/float/cff8.s
===================================================================
--- /trunk/minix/lib/ack/float/cff8.s	(revision 9)
+++ /trunk/minix/lib/ack/float/cff8.s	(revision 9)
@@ -0,0 +1,23 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .cff8
+.sect .text
+.cff8:
+push ebp
+mov ebp,esp
+sub	esp,12
+push 4
+lea eax,-12(ebp)
+push eax
+lea eax,8(ebp)
+push eax
+call .extend
+add esp,12
+push 8
+lea eax,8(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+leave
+ret
Index: /trunk/minix/lib/ack/float/cfi.fc
===================================================================
--- /trunk/minix/lib/ack/float/cfi.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/cfi.fc	(revision 9)
@@ -0,0 +1,52 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/cfi.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+		CONVERT FLOAT TO SIGNED (CFI m n)
+
+		N.B. The caller must know what it is getting.
+		     A LONG is always returned. If it is an
+		     integer the high byte is cleared first.
+*/
+
+#include "FP_trap.h"
+#include "FP_types.h"
+#include "FP_shift.h"
+
+long
+cfi(ds,ss,src)
+int	ds;	/* destination size (2 or 4) */
+int	ss;	/* source size	    (4 or 8) */
+DOUBLE	src;	/* assume worst case */
+{
+	EXTEND	buf;
+	long	new;
+	short	max_exp;
+
+	extend(&src.d[0],&buf,ss);	/* get extended format */
+	if (buf.exp < 0) {	/* no conversion needed */
+		src.d[ss == 8] = 0L;
+		return(0L);
+	}
+	max_exp = (ds << 3) - 2;	/* signed numbers */
+				/* have more limited max_exp */
+	if (buf.exp > max_exp) {
+		if (buf.exp == max_exp+1 && buf.sign && buf.m1 == NORMBIT &&
+		    buf.m2 == 0L) {
+		}
+		else {
+			trap(EIOVFL);	/* integer overflow	*/
+			buf.exp %= max_exp; /* truncate	*/
+		}
+	}
+	new = buf.m1 >> (31-buf.exp);
+	if (buf.sign)
+		new = -new;
+done:
+	src.d[ss == 8] = new;
+	return(new);
+}
Index: /trunk/minix/lib/ack/float/cfi.s
===================================================================
--- /trunk/minix/lib/ack/float/cfi.s	(revision 9)
+++ /trunk/minix/lib/ack/float/cfi.s	(revision 9)
@@ -0,0 +1,80 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .cfi
+.sect .text
+.cfi:
+push ebp
+mov ebp,esp
+sub	esp,20
+push esi
+push 12(ebp)
+lea eax,-12(ebp)
+push eax
+lea eax,16(ebp)
+push eax
+call .extend
+add esp,12
+movsx eax,-10(ebp)
+test eax,eax
+jns I1_4
+xor eax,eax
+cmp 12(ebp),8
+jne 1f
+inc eax
+1:
+mov 16(ebp)(eax*4),0
+xor eax,eax
+jmp I1_1
+I1_4:
+mov edx,8(ebp)
+sal edx,3
+sub edx,2
+o16 mov -18(ebp),edx
+movsx eax,-10(ebp)
+movsx ebx,-18(ebp)
+cmp eax,ebx
+jle I1_7
+movsx eax,-18(ebp)
+inc eax
+movsx ebx,-10(ebp)
+cmp eax,ebx
+jne I1_10
+movzx edx,-12(ebp)
+test edx,edx
+je I1_10
+cmp -8(ebp),-2147483648
+jne I1_10
+cmp -4(ebp),0
+je I1_7
+I1_10:
+push 3
+call __fptrp
+pop ecx
+movsx eax,-10(ebp)
+movsx ebx,-18(ebp)
+cdq
+idiv ebx
+o16 mov -10(ebp),edx
+I1_7:
+movsx eax,-10(ebp)
+sub eax,31
+neg eax
+mov ecx,eax
+mov edx,-8(ebp)
+shr edx,cl
+mov esi,edx
+movzx edx,-12(ebp)
+test edx,edx
+je I1_18
+neg esi
+I1_18:
+xor eax,eax
+cmp 12(ebp),8
+jne 1f
+inc eax
+1:
+mov 16(ebp)(eax*4),esi
+mov eax,esi
+I1_1:
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/cfu.fc
===================================================================
--- /trunk/minix/lib/ack/float/cfu.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/cfu.fc	(revision 9)
@@ -0,0 +1,43 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/cfu.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+		CONVERT FLOAT TO UNSIGNED (CFU m n)
+
+		N.B. The caller must know what it is getting.
+		     A LONG is always returned. If it is an
+		     integer the high byte is cleared first.
+*/
+
+#include "FP_trap.h"
+#include "FP_types.h"
+
+long
+cfu(ds,ss,src)
+int	ds;	/* destination size (2 or 4) */
+int	ss;	/* source size	    (4 or 8) */
+DOUBLE	src;	/* assume worst case */
+{
+	EXTEND	buf;
+	long	new;
+	short	newint, max_exp;
+
+	extend(&src.d[0],&buf,ss);	/* get extended format	*/
+	if (buf.exp < 0) {	/* no conversion needed	*/
+		src.d[ss == 8] = 0L;
+		return(0L);
+	}
+	max_exp = (ds << 3) - 1;
+	if (buf.exp > max_exp) {
+		trap(EIOVFL);	/* integer overflow	*/
+		buf.exp %= max_exp;
+	}
+	new = buf.m1 >> (31-buf.exp);
+done:
+	src.d[ss == 8] = new;
+	return(new);
+}
Index: /trunk/minix/lib/ack/float/cfu.s
===================================================================
--- /trunk/minix/lib/ack/float/cfu.s	(revision 9)
+++ /trunk/minix/lib/ack/float/cfu.s	(revision 9)
@@ -0,0 +1,62 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .cfu
+.sect .text
+.cfu:
+push ebp
+mov ebp,esp
+sub	esp,20
+push esi
+push 12(ebp)
+lea eax,-12(ebp)
+push eax
+lea eax,16(ebp)
+push eax
+call .extend
+add esp,12
+movsx eax,-10(ebp)
+test eax,eax
+jns I1_4
+xor eax,eax
+cmp 12(ebp),8
+jne 1f
+inc eax
+1:
+mov 16(ebp)(eax*4),0
+xor eax,eax
+jmp I1_1
+I1_4:
+mov edx,8(ebp)
+sal edx,3
+dec edx
+o16 mov -20(ebp),edx
+movsx eax,-10(ebp)
+movsx ebx,-20(ebp)
+cmp eax,ebx
+jle I1_7
+push 3
+call __fptrp
+pop ecx
+movsx eax,-10(ebp)
+movsx ebx,-20(ebp)
+cdq
+idiv ebx
+o16 mov -10(ebp),edx
+I1_7:
+movsx eax,-10(ebp)
+sub eax,31
+neg eax
+mov ecx,eax
+mov edx,-8(ebp)
+shr edx,cl
+mov esi,edx
+xor eax,eax
+cmp 12(ebp),8
+jne 1f
+inc eax
+1:
+mov 16(ebp)(eax*4),esi
+mov eax,esi
+I1_1:
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/cif4.fc
===================================================================
--- /trunk/minix/lib/ack/float/cif4.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/cif4.fc	(revision 9)
@@ -0,0 +1,56 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/cif4.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	CONVERT INTEGER TO SINGLE (CIF n 4)
+
+	THIS ROUTINE WORKS BY FILLING AN EXTENDED
+	WITH THE INTEGER VALUE IN EXTENDED FORMAT
+	AND USES COMPACT() TO PUT IT INTO THE PROPER
+	FLOATING POINT PRECISION.
+*/
+
+#include "FP_types.h"
+
+void
+cif4(ss,src)
+int	ss;	/* source size */
+long	src;	/* largest possible integer to convert */
+{
+	EXTEND	buf;
+	short	*ipt;
+	long	i_src;
+	SINGLE	*result;
+
+	zrf_ext(&buf);
+	if (ss == sizeof(long))	{
+		buf.exp = 31;
+		i_src = src;
+		result = (SINGLE *) &src;
+	}
+	else	{
+		ipt = (short *) &src;
+		i_src = (long) *ipt;
+		buf.exp = 15;
+		result = (SINGLE *) &ss;
+	}
+	if (i_src == 0)	{
+		*result = (SINGLE) 0L;
+		return;
+	}
+			/* ESTABLISHED THAT src != 0	*/
+			/* adjust exponent field	*/
+	buf.sign = (i_src < 0) ? 0x8000 : 0;
+			/* clear sign bit of integer	*/
+			/* move to mantissa field	*/
+	buf.m1 = (i_src < 0) ? -i_src : i_src;
+			/* adjust mantissa field	*/
+	if (ss != sizeof(long))
+		buf.m1 <<= 16;
+	nrm_ext(&buf);		/* adjust mantissa field	*/
+	compact(&buf, result,sizeof(SINGLE));	/* put on stack */
+}
Index: /trunk/minix/lib/ack/float/cif4.s
===================================================================
--- /trunk/minix/lib/ack/float/cif4.s	(revision 9)
+++ /trunk/minix/lib/ack/float/cif4.s	(revision 9)
@@ -0,0 +1,69 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .cif4
+.sect .text
+.cif4:
+push ebp
+mov ebp,esp
+sub	esp,16
+push esi
+push edi
+lea eax,-12(ebp)
+push eax
+call .zrf_ext
+pop ecx
+cmp 8(ebp),4
+jne I1_4
+o16 mov -10(ebp),31
+mov esi,12(ebp)
+lea edi,12(ebp)
+jmp I1_5
+I1_4:
+lea edx,12(ebp)
+mov -16(ebp),edx
+movsx eax,(edx)
+mov esi,eax
+o16 mov -10(ebp),15
+lea edi,8(ebp)
+I1_5:
+test esi,esi
+jne I1_7
+mov (edi),0
+jmp I1_1
+I1_7:
+test esi,esi
+jns I1_10
+mov eax,32768
+jmp I1_11
+I1_10:
+xor eax,eax
+I1_11:
+o16 mov -12(ebp),eax
+test esi,esi
+jns I1_13
+mov edx,esi
+neg edx
+mov eax,edx
+jmp I1_14
+I1_13:
+mov eax,esi
+I1_14:
+mov -8(ebp),eax
+cmp 8(ebp),4
+je I1_16
+sal -8(ebp),16
+I1_16:
+lea eax,-12(ebp)
+push eax
+call .nrm_ext
+pop ecx
+push 4
+push edi
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+I1_1:
+pop edi
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/cif8.fc
===================================================================
--- /trunk/minix/lib/ack/float/cif8.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/cif8.fc	(revision 9)
@@ -0,0 +1,55 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/cif8.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	CONVERT INTEGER TO FLOAT (CIF n 8)
+
+	THIS ROUTINE WORKS BY FILLING AN EXTENDED
+	WITH THE INTEGER VALUE IN EXTENDED FORMAT
+	AND USES COMPACT() TO PUT IT INTO THE PROPER
+	FLOATING POINT PRECISION.
+*/
+
+#include "FP_types.h"
+
+void
+cif8(ss,src)
+int	ss;	/* source size */
+long	src;	/* largest possible integer to convert */
+{
+	EXTEND	buf;
+	DOUBLE	*result;	/* for return value */
+	short	*ipt;
+	long	i_src;
+
+	result = (DOUBLE *) ((void *) &ss);	/* always */
+	zrf_ext(&buf);
+	if (ss == sizeof(long))	{
+		buf.exp = 31;
+		i_src = src;
+	}
+	else	{
+		ipt = (short *) &src;
+		i_src = (long) *ipt;
+		buf.exp = 15;
+	}
+	if (i_src == 0)	{
+		zrf8(result);
+		return;
+	}
+			/* ESTABLISHED THAT src != 0	*/
+			/* adjust exponent field	*/
+	buf.sign = (i_src < 0) ? 0x8000 : 0;
+			/* clear sign bit of integer	*/
+			/* move to mantissa field	*/
+	buf.m1 = (i_src < 0) ? -i_src : i_src;
+			/* adjust mantissa field	*/
+	if (ss != sizeof(long))
+		buf.m1 <<= 16;
+	nrm_ext(&buf);
+	compact(&buf,&result->d[0],8);
+}
Index: /trunk/minix/lib/ack/float/cif8.s
===================================================================
--- /trunk/minix/lib/ack/float/cif8.s	(revision 9)
+++ /trunk/minix/lib/ack/float/cif8.s	(revision 9)
@@ -0,0 +1,70 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .cif8
+.sect .text
+.cif8:
+push ebp
+mov ebp,esp
+sub	esp,20
+push esi
+push edi
+lea edi,8(ebp)
+lea eax,-12(ebp)
+push eax
+call .zrf_ext
+pop ecx
+cmp 8(ebp),4
+jne I1_4
+o16 mov -10(ebp),31
+mov esi,12(ebp)
+jmp I1_5
+I1_4:
+lea edx,12(ebp)
+mov -20(ebp),edx
+movsx eax,(edx)
+mov esi,eax
+o16 mov -10(ebp),15
+I1_5:
+test esi,esi
+jne I1_7
+push edi
+call .zrf8
+pop ecx
+jmp I1_1
+I1_7:
+test esi,esi
+jns I1_10
+mov eax,32768
+jmp I1_11
+I1_10:
+xor eax,eax
+I1_11:
+o16 mov -12(ebp),eax
+test esi,esi
+jns I1_13
+mov edx,esi
+neg edx
+mov eax,edx
+jmp I1_14
+I1_13:
+mov eax,esi
+I1_14:
+mov -8(ebp),eax
+cmp 8(ebp),4
+je I1_16
+sal -8(ebp),16
+I1_16:
+lea eax,-12(ebp)
+push eax
+call .nrm_ext
+pop ecx
+push 8
+push edi
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+I1_1:
+pop edi
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/cmf4.fc
===================================================================
--- /trunk/minix/lib/ack/float/cmf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/cmf4.fc	(revision 9)
@@ -0,0 +1,40 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/cmf4.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	COMPARE	SINGLES (CMF 4)
+*/
+
+#include	"FP_types.h"
+#include	"get_put.h"
+
+int
+cmf4(f1,f2)
+SINGLE	f1,f2;
+{
+		/*
+		 * return ((f1 < f2) ? 1 : (f1 - f2))
+		 */
+#define SIGN(x) (((x) < 0) ? -1 : 1)
+        int	sign1,sign2;
+	long	l1,l2;
+
+	l1 = get4((char *) &f1);
+	l2 = get4((char *) &f2);
+
+	if (l1 == l2) return 0;
+
+        sign1 = SIGN(l1);
+        sign2 = SIGN(l2);
+        if (sign1 != sign2) {
+		if ((l1 & 0x7fffffff) == 0 &&
+		    (l2 & 0x7fffffff) == 0) return 0;
+                return ((sign1 > 0) ? -1 : 1);
+	}
+
+	return (sign1 * ((l1 < l2) ? 1 : -1));
+}
Index: /trunk/minix/lib/ack/float/cmf4.s
===================================================================
--- /trunk/minix/lib/ack/float/cmf4.s	(revision 9)
+++ /trunk/minix/lib/ack/float/cmf4.s	(revision 9)
@@ -0,0 +1,63 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .cmf4
+.sect .text
+.cmf4:
+push ebp
+mov ebp,esp
+sub	esp,8
+push esi
+push edi
+mov edi,8(ebp)
+mov esi,12(ebp)
+cmp edi,esi
+jne I1_4
+xor eax,eax
+jmp I1_1
+I1_4:
+test edi,edi
+jns I1_7
+mov eax,-1
+jmp I1_8
+I1_7:
+mov eax,1
+I1_8:
+mov -4(ebp),eax
+test esi,esi
+jns I1_10
+mov eax,-1
+jmp I1_11
+I1_10:
+mov eax,1
+I1_11:
+mov -8(ebp),eax
+cmp -4(ebp),eax
+je I1_13
+test edi,2147483647
+jne I1_16
+test esi,2147483647
+jne I1_16
+xor eax,eax
+jmp I1_1
+I1_16:
+! kill cc
+cmp -4(ebp),0
+jle I1_20
+mov eax,-1
+jmp I1_1
+I1_20:
+mov eax,1
+jmp I1_1
+I1_13:
+cmp edi,esi
+jge I1_23
+mov eax,1
+jmp I1_24
+I1_23:
+mov eax,-1
+I1_24:
+imul eax,-4(ebp)
+I1_1:
+pop edi
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/cmf8.fc
===================================================================
--- /trunk/minix/lib/ack/float/cmf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/cmf8.fc	(revision 9)
@@ -0,0 +1,61 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/cmf8.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	COMPARE	DOUBLES (CMF 8)
+*/
+
+#include	"FP_types.h"
+#include	"get_put.h"
+
+int
+cmf8(d1,d2)
+DOUBLE	d1,d2;
+{
+#define	SIGN(x)	(((x) < 0) ? -1 : 1)
+		/*
+		 * return ((d1 < d2) ? 1 : (d1 > d2) ? -1 : 0))
+		 */
+	long	l1,l2;
+	int	sign1,sign2;
+	int	rv;
+
+#if FL_MSL_AT_LOW_ADDRESS
+	l1 = get4((char *)&d1);
+	l2 = get4((char *)&d2);
+#else
+	l1 = get4(((char *)&d1+4));
+	l2 = get4(((char *)&d2+4));
+#endif
+	sign1 = SIGN(l1);
+	sign2 = SIGN(l2);
+	if (sign1 != sign2) {
+		l1 &= 0x7fffffff;
+		l2 &= 0x7fffffff;
+		if (l1 != 0 || l2 != 0) {
+			return ((sign1 > 0) ? -1 : 1);
+		}
+	}
+	if (l1 != l2)	{	/* we can decide here */
+		rv = l1 < l2 ? 1 : -1;
+	}
+	else	{ 		/* decide in 2nd half */
+		unsigned long u1, u2;
+#if FL_MSL_AT_LOW_ADDRESS
+		u1 = get4(((char *)&d1 + 4));
+		u2 = get4(((char *)&d2 + 4));
+#else
+		u1 = get4((char *)&d1);
+		u2 = get4((char *)&d2);
+#endif
+		if (u1 == u2)
+			return(0);
+		if (u1 < u2) rv = 1;
+		else rv = -1;
+	}
+	return sign1 * rv;
+}
Index: /trunk/minix/lib/ack/float/cmf8.s
===================================================================
--- /trunk/minix/lib/ack/float/cmf8.s	(revision 9)
+++ /trunk/minix/lib/ack/float/cmf8.s	(revision 9)
@@ -0,0 +1,82 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .cmf8
+.sect .text
+.cmf8:
+push ebp
+mov ebp,esp
+sub	esp,28
+push esi
+push edi
+mov edi,12(ebp)
+mov esi,20(ebp)
+test edi,edi
+jns I1_4
+mov eax,-1
+jmp I1_5
+I1_4:
+mov eax,1
+I1_5:
+mov -12(ebp),eax
+test esi,esi
+jns I1_7
+mov eax,-1
+jmp I1_8
+I1_7:
+mov eax,1
+I1_8:
+mov -16(ebp),eax
+cmp -12(ebp),eax
+je I1_10
+and edi,2147483647
+and esi,2147483647
+test edi,edi
+jne I1_12
+test esi,esi
+je I1_10
+I1_12:
+! kill cc
+cmp -12(ebp),0
+jle I1_17
+mov eax,-1
+jmp I1_1
+I1_17:
+mov eax,1
+jmp I1_1
+I1_10:
+cmp edi,esi
+je I1_20
+cmp edi,esi
+jge I1_23
+mov eax,1
+jmp I1_24
+I1_23:
+mov eax,-1
+I1_24:
+mov -20(ebp),eax
+jmp I1_21
+I1_20:
+mov edx,8(ebp)
+mov -24(ebp),edx
+mov edx,16(ebp)
+mov -28(ebp),edx
+cmp -24(ebp),edx
+jne I1_26
+xor eax,eax
+jmp I1_1
+I1_26:
+mov edx,-28(ebp)
+cmp -24(ebp),edx
+jae I1_29
+mov -20(ebp),1
+jmp I1_21
+I1_29:
+mov -20(ebp),-1
+I1_21:
+mov edx,-12(ebp)
+imul edx,-20(ebp)
+mov eax,edx
+I1_1:
+pop edi
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/compact.fc
===================================================================
--- /trunk/minix/lib/ack/float/compact.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/compact.fc	(revision 9)
@@ -0,0 +1,202 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/compact.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	COMPACT EXTEND FORMAT INTO FLOAT OF PROPER SIZE
+*/
+
+# include "FP_bias.h"
+# include "FP_shift.h"
+# include "FP_trap.h"
+# include "FP_types.h"
+# include "get_put.h"
+
+void
+compact(f,to,size)
+EXTEND	*f;
+unsigned long	*to;
+int	size;
+{
+	int	error = 0;
+
+	if (size == sizeof(DOUBLE)) {
+	/*
+	 * COMPACT EXTENDED INTO DOUBLE
+	 */
+		DOUBLE *DBL = (DOUBLE *) (void *) to;
+
+		if ((f->m1|(f->m2 & DBL_ZERO)) == 0L)	{
+			zrf8(DBL);
+			return;
+		}
+		f->exp += DBL_BIAS;	/* restore proper bias	*/
+		if (f->exp > DBL_MAX)	{
+dbl_over:			trap(EFOVFL);
+			f->exp = DBL_MAX+1;
+			f->m1 = 0;
+			f->m2 = 0;
+			if (error++)
+				return;
+		}
+		else if (f->exp < DBL_MIN)	{
+			b64_rsft(&(f->mantissa));
+			if (f->exp < 0) {
+				b64_sft(&(f->mantissa), -f->exp);
+				f->exp = 0;
+			}
+			/* underflow ??? */
+		}
+			
+		/* local CAST conversion		*/
+
+		/* because of special format shift only 10 bits */
+		/* bit shift mantissa 10 bits		*/
+
+		/* first align within words, then do store operation */
+
+		DBL->d[0] = f->m1 >> DBL_RUNPACK;   /* plus 22 == 32 */
+		DBL->d[1] = f->m2 >> DBL_RUNPACK;   /* plus 22 == 32 */
+		DBL->d[1] |= (f->m1 << DBL_LUNPACK); /* plus 10 == 32 */
+
+		/* if not exact then round to nearest	*/
+		/* on a tie, round to even */
+
+#ifdef EXCEPTION_INEXACT
+		if ((f->m2 & DBL_EXACT) != 0) {
+		    INEXACT();
+#endif
+		    if (((f->m2 & DBL_EXACT) > DBL_ROUNDUP)
+			|| ((f->m2 & DBL_EXACT) == DBL_ROUNDUP
+			    && (f->m2 & (DBL_ROUNDUP << 1)))) {
+			DBL->d[1]++;	/* rounding up	*/
+			if (DBL->d[1] == 0L) { /* carry out	*/
+			    DBL->d[0]++;
+
+			    if (f->exp == 0 && (DBL->d[0] & ~DBL_MASK)) {
+					f->exp++;
+				}
+			    if (DBL->d[0] & DBL_CARRYOUT) { /* carry out */
+				if (DBL->d[0] & 01)
+				    DBL->d[1] = CARRYBIT;
+				DBL->d[0] >>= 1;
+				f->exp++;
+			    }
+			}
+			/*	check for overflow			*/
+			if (f->exp > DBL_MAX)
+		    		goto dbl_over;
+		    }
+#ifdef EXCEPTION_INEXACT
+		}
+#endif
+
+		/*
+		 * STORE EXPONENT AND SIGN:
+		 *
+		 * 1) clear leading bits (B4-B15)
+		 * 2) shift and store exponent
+		 */
+
+		DBL->d[0] &= DBL_MASK;
+		DBL->d[0] |= 
+			((long) (f->exp << DBL_EXPSHIFT) << EXP_STORE);
+		if (f->sign)
+			DBL->d[0] |= CARRYBIT;
+
+		/*
+		 * STORE MANTISSA
+		 */
+
+#if FL_MSL_AT_LOW_ADDRESS
+		put4(DBL->d[0], (char *) &DBL->d[0]);
+		put4(DBL->d[1], (char *) &DBL->d[1]);
+#else
+		{ unsigned long l;
+		  put4(DBL->d[1], (char *) &l);
+		  put4(DBL->d[0], (char *) &DBL->d[1]);
+		  DBL->d[0] = l;
+		}
+#endif
+	}
+	else {
+		/*
+		 * COMPACT EXTENDED INTO FLOAT
+		 */
+		SINGLE	*SGL;
+
+		/* local CAST conversion		*/
+		SGL = (SINGLE *) (void *) to;
+		if ((f->m1 & SGL_ZERO) == 0L)	{
+			*SGL = 0L;
+			return;
+		}
+		f->exp += SGL_BIAS;	/* restore bias	*/
+		if (f->exp > SGL_MAX)	{
+sgl_over:			trap(EFOVFL);
+			f->exp = SGL_MAX+1;
+			f->m1 = 0L;
+			f->m2 = 0L;
+			if (error++)
+				return;
+		}
+		else if (f->exp < SGL_MIN)	{
+			b64_rsft(&(f->mantissa));
+			if (f->exp < 0) {
+				b64_sft(&(f->mantissa), -f->exp);
+				f->exp = 0;
+			}
+			/* underflow ??? */
+		}
+
+		/* shift mantissa and store	*/
+		*SGL = (f->m1 >> SGL_RUNPACK);
+
+		/* check for rounding to nearest	*/
+		/* on a tie, round to even		*/
+#ifdef EXCEPTION_INEXACT
+		if (f->m2 != 0 ||
+		    (f->m1 & SGL_EXACT) != 0L) {
+			INEXACT();
+#endif
+		        if (((f->m1 & SGL_EXACT) > SGL_ROUNDUP)
+			    || ((f->m1 & SGL_EXACT) == SGL_ROUNDUP
+			        && (f->m1 & (SGL_ROUNDUP << 1)))) {
+				(*SGL)++;
+				if (f->exp == 0 && (*SGL & ~SGL_MASK)) {
+					f->exp++;
+				}
+			/* check normal */
+				if (*SGL & SGL_CARRYOUT)	{
+					*SGL >>= 1;
+					f->exp++;
+				}
+				if (f->exp > SGL_MAX)
+					goto sgl_over;
+			}
+#ifdef EXCEPTION_INEXACT
+		}
+#endif
+
+		/*
+		 * STORE EXPONENT AND SIGN:
+		 *
+		 * 1) clear leading bit of fraction
+		 * 2) shift and store exponent
+		 */
+
+		*SGL &= SGL_MASK; /* B23-B31 are 0 */
+		*SGL |= ((long) (f->exp << SGL_EXPSHIFT) << EXP_STORE);
+		if (f->sign)
+			*SGL |= CARRYBIT;
+
+		/*
+		 * STORE MANTISSA
+		 */
+
+		put4(*SGL, (char *) &SGL);
+	}
+}
Index: /trunk/minix/lib/ack/float/compact.s
===================================================================
--- /trunk/minix/lib/ack/float/compact.s	(revision 9)
+++ /trunk/minix/lib/ack/float/compact.s	(revision 9)
@@ -0,0 +1,270 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .compact
+.sect .text
+.compact:
+push ebp
+mov ebp,esp
+sub	esp,16
+push esi
+push edi
+mov esi,8(ebp)
+mov -4(ebp),0
+cmp 16(ebp),8
+jne I1_4
+mov edi,12(ebp)
+mov edx,-768
+and edx,8(esi)
+or edx,4(esi)
+jne I1_7
+push edi
+call .zrf8
+pop ecx
+jmp I1_1
+I1_7:
+movsx eax,2(esi)
+add eax,1023
+movsx eax,eax
+o16 mov 2(esi),eax
+movsx ebx,2(esi)
+cmp ebx,2046
+jle I1_10
+I1_12:
+push 4
+call __fptrp
+pop ecx
+o16 mov 2(esi),2047
+mov 4(esi),0
+mov 8(esi),0
+mov edx,-4(ebp)
+mov ecx,edx
+inc ecx
+mov -4(ebp),ecx
+test edx,edx
+je I1_11
+jmp I1_1
+I1_10:
+movsx eax,2(esi)
+! kill cc
+test eax,eax
+jg I1_11
+lea eax,4(esi)
+push eax
+call .b64_rsft
+pop ecx
+movsx eax,2(esi)
+test eax,eax
+jns I1_11
+movsx eax,2(esi)
+neg eax
+push eax
+lea eax,4(esi)
+push eax
+call .b64_sft
+pop ecx
+pop ecx
+o16 mov 2(esi),0
+I1_11:
+mov edx,4(esi)
+shr edx,11
+mov (edi),edx
+mov edx,8(esi)
+shr edx,11
+mov 4(edi),edx
+lea edx,4(edi)
+mov -12(ebp),edx
+mov ecx,4(esi)
+sal ecx,21
+or ecx,(edx)
+mov eax,-12(ebp)
+mov (eax),ecx
+! kill eax
+mov edx,2047
+and edx,8(esi)
+cmp edx,1024
+ja I1_22
+mov edx,2047
+and edx,8(esi)
+cmp edx,1024
+jne I1_23
+test 8(esi),2048
+je I1_23
+I1_22:
+lea edx,4(edi)
+mov -12(ebp),edx
+mov ecx,1
+add ecx,(edx)
+mov eax,-12(ebp)
+mov (eax),ecx
+! kill eax
+cmp 4(edi),0
+jne I1_28
+mov -12(ebp),edi
+mov edx,1
+add edx,(edi)
+mov eax,-12(ebp)
+mov (eax),edx
+! kill eax
+movzx edx,2(esi)
+test edx,edx
+jne I1_31
+test (edi),-1048576
+je I1_31
+movsx eax,2(esi)
+inc eax
+movsx eax,eax
+o16 mov 2(esi),eax
+I1_31:
+test (edi),2097152
+je I1_28
+mov edx,(edi)
+testb dl,1
+je I1_38
+mov 4(edi),-2147483648
+I1_38:
+mov -12(ebp),edi
+mov edx,(edi)
+shr edx,1
+mov eax,-12(ebp)
+mov (eax),edx
+! kill eax
+movsx eax,2(esi)
+inc eax
+movsx eax,eax
+o16 mov 2(esi),eax
+I1_28:
+movsx eax,2(esi)
+cmp eax,2046
+jg I1_12
+I1_23:
+mov -12(ebp),edi
+mov edx,1048575
+and edx,(edi)
+mov eax,-12(ebp)
+mov (eax),edx
+! kill eax
+mov -12(ebp),edi
+movsx eax,2(esi)
+sal eax,4
+sal eax,16
+or eax,(edi)
+mov ebx,-12(ebp)
+mov (ebx),eax
+! kill ebx
+movzx edx,(esi)
+test edx,edx
+je I1_44
+mov -12(ebp),edi
+mov edx,-2147483648
+or edx,(edi)
+mov eax,-12(ebp)
+mov (eax),edx
+! kill eax
+I1_44:
+mov edx,4(edi)
+mov -16(ebp),edx
+mov edx,(edi)
+mov 4(edi),edx
+mov edx,-16(ebp)
+mov (edi),edx
+jmp I1_1
+I1_4:
+mov edi,12(ebp)
+test 4(esi),-128
+jne I1_47
+mov (edi),0
+jmp I1_1
+I1_47:
+movsx eax,2(esi)
+add eax,127
+movsx eax,eax
+o16 mov 2(esi),eax
+movsx ebx,2(esi)
+cmp ebx,254
+jle I1_50
+I1_52:
+push 4
+call __fptrp
+pop ecx
+o16 mov 2(esi),255
+mov 4(esi),0
+mov 8(esi),0
+mov edx,-4(ebp)
+mov ecx,edx
+inc ecx
+mov -4(ebp),ecx
+test edx,edx
+je I1_51
+jmp I1_1
+I1_50:
+movsx eax,2(esi)
+! kill cc
+test eax,eax
+jg I1_51
+lea eax,4(esi)
+push eax
+call .b64_rsft
+pop ecx
+movsx eax,2(esi)
+test eax,eax
+jns I1_51
+movsx eax,2(esi)
+neg eax
+push eax
+lea eax,4(esi)
+push eax
+call .b64_sft
+pop ecx
+pop ecx
+o16 mov 2(esi),0
+I1_51:
+mov edx,4(esi)
+shr edx,8
+mov (edi),edx
+mov edx,4(esi)
+movzxb ecx,dl
+cmp ecx,128
+ja I1_62
+cmpb dl,128
+jne I1_63
+test 4(esi),256
+je I1_63
+I1_62:
+inc (edi)
+movzx edx,2(esi)
+test edx,edx
+jne I1_68
+test (edi),-8388608
+je I1_68
+movsx eax,2(esi)
+inc eax
+movsx eax,eax
+o16 mov 2(esi),eax
+I1_68:
+test (edi),16777216
+je I1_72
+shr (edi),1
+movsx eax,2(esi)
+inc eax
+movsx eax,eax
+o16 mov 2(esi),eax
+I1_72:
+movsx eax,2(esi)
+cmp eax,254
+jg I1_52
+I1_63:
+and (edi),8388607
+movsx eax,2(esi)
+sal eax,7
+sal eax,16
+or (edi),eax
+movzx edx,(esi)
+test edx,edx
+je I1_78
+or (edi),-2147483648
+I1_78:
+mov edi,(edi)
+I1_1:
+pop edi
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/cuf4.fc
===================================================================
--- /trunk/minix/lib/ack/float/cuf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/cuf4.fc	(revision 9)
@@ -0,0 +1,57 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/cuf4.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	CONVERT INTEGER TO SINGLE (CUF n 4)
+
+	THIS ROUTINE WORKS BY FILLING AN EXTENDED
+	WITH THE INTEGER VALUE IN EXTENDED FORMAT
+	AND USES COMPACT() TO PUT IT INTO THE PROPER
+	FLOATING POINT PRECISION.
+*/
+
+#include "FP_types.h"
+
+void
+cuf4(ss,src)
+int	ss;	/* source size */
+long	src;	/* largest possible integer to convert */
+{
+	EXTEND	buf;
+	short	*ipt;
+	SINGLE	*result;
+	long	i_src;
+
+	zrf_ext(&buf);
+	if (ss == sizeof(long))	{
+		buf.exp = 31;
+		i_src = src;
+		result = (SINGLE *) &src;
+	}
+	else	{
+		ipt = (short *) &src;
+		i_src = (long) *ipt;
+		buf.exp = 15;
+		result = (SINGLE *) ((void *) &ss);
+	}
+	if (i_src == 0)	{
+		*result = (SINGLE) 0L;
+		return;
+	}
+			/* ESTABLISHED THAT src != 0	*/
+
+			/* adjust exponent field	*/
+	if (ss != sizeof(long))
+		i_src <<= 16;
+
+			/* move to mantissa field	*/
+	buf.m1 = i_src;
+
+			/* adjust mantissa field	*/
+	nrm_ext(&buf);
+	compact(&buf,result,4);
+}
Index: /trunk/minix/lib/ack/float/cuf4.s
===================================================================
--- /trunk/minix/lib/ack/float/cuf4.s	(revision 9)
+++ /trunk/minix/lib/ack/float/cuf4.s	(revision 9)
@@ -0,0 +1,52 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .cuf4
+.sect .text
+.cuf4:
+push ebp
+mov ebp,esp
+sub	esp,16
+push esi
+push edi
+lea eax,-12(ebp)
+push eax
+call .zrf_ext
+pop ecx
+cmp 8(ebp),4
+jne I1_4
+o16 mov -10(ebp),31
+mov esi,12(ebp)
+lea edi,12(ebp)
+jmp I1_5
+I1_4:
+lea edx,12(ebp)
+mov -16(ebp),edx
+movsx eax,(edx)
+mov esi,eax
+o16 mov -10(ebp),15
+lea edi,8(ebp)
+I1_5:
+test esi,esi
+jne I1_7
+mov (edi),0
+jmp I1_1
+I1_7:
+cmp 8(ebp),4
+je I1_10
+sal esi,16
+I1_10:
+mov -8(ebp),esi
+lea eax,-12(ebp)
+push eax
+call .nrm_ext
+pop ecx
+push 4
+push edi
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+I1_1:
+pop edi
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/cuf8.fc
===================================================================
--- /trunk/minix/lib/ack/float/cuf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/cuf8.fc	(revision 9)
@@ -0,0 +1,54 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/cuf8.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	CONVERT INTEGER TO FLOAT (CUF n 8)
+
+	THIS ROUTINE WORKS BY FILLING AN EXTENDED
+	WITH THE INTEGER VALUE IN EXTENDED FORMAT
+	AND USES COMPACT() TO PUT IT INTO THE PROPER
+	FLOATING POINT PRECISION.
+*/
+
+#include "FP_types.h"
+
+void
+cuf8(ss,src)
+int	ss;	/* source size */
+long	src;	/* largest possible integer to convert */
+{
+	EXTEND	buf;
+	short	*ipt;
+	long	i_src;
+
+	zrf_ext(&buf);
+	if (ss == sizeof(long))	{
+		buf.exp = 31;
+		i_src = src;
+	}
+	else	{
+		ipt = (short *) &src;
+		i_src = (long) *ipt;
+		buf.exp = 15;
+	}
+	if (i_src == 0)	{
+		zrf8((DOUBLE *)((void *)&ss));
+		return;
+	}
+			/* ESTABLISHED THAT src != 0	*/
+
+			/* adjust exponent field	*/
+	if (ss != sizeof(long))
+		i_src <<= 16;
+
+			/* move to mantissa field	*/
+	buf.m1 = i_src;
+
+			/* adjust mantissa field	*/
+	nrm_ext(&buf);
+	compact(&buf,(unsigned long *) (void *)&ss,8);
+}
Index: /trunk/minix/lib/ack/float/cuf8.s
===================================================================
--- /trunk/minix/lib/ack/float/cuf8.s	(revision 9)
+++ /trunk/minix/lib/ack/float/cuf8.s	(revision 9)
@@ -0,0 +1,52 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .cuf8
+.sect .text
+.cuf8:
+push ebp
+mov ebp,esp
+sub	esp,16
+push esi
+lea eax,-12(ebp)
+push eax
+call .zrf_ext
+pop ecx
+cmp 8(ebp),4
+jne I1_4
+o16 mov -10(ebp),31
+mov esi,12(ebp)
+jmp I1_5
+I1_4:
+lea edx,12(ebp)
+mov -16(ebp),edx
+movsx eax,(edx)
+mov esi,eax
+o16 mov -10(ebp),15
+I1_5:
+test esi,esi
+jne I1_7
+lea eax,8(ebp)
+push eax
+call .zrf8
+pop ecx
+jmp I1_1
+I1_7:
+cmp 8(ebp),4
+je I1_10
+sal esi,16
+I1_10:
+mov -8(ebp),esi
+lea eax,-12(ebp)
+push eax
+call .nrm_ext
+pop ecx
+push 8
+lea eax,8(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+I1_1:
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/div_ext.fc
===================================================================
--- /trunk/minix/lib/ack/float/div_ext.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/div_ext.fc	(revision 9)
@@ -0,0 +1,266 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/div_ext.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	DIVIDE EXTENDED FORMAT
+*/
+
+#include "FP_bias.h"
+#include "FP_trap.h"
+#include "FP_types.h"
+
+/*
+	November 15, 1984
+
+	This is a routine to do the work.
+	There are two versions: 
+	One is based on the partial products method
+	and makes no use possible machine instructions
+	to divide (hardware dividers).
+	The other is used when USE_DIVIDE is defined. It is much faster on
+	machines with fast 4 byte operations.
+*/
+/********************************************************/
+
+void
+div_ext(e1,e2)
+EXTEND	*e1,*e2;
+{
+	short	error = 0;
+	B64		result;
+	register	unsigned long	*lp;
+#ifndef USE_DIVIDE
+	short	count;
+#else
+	unsigned short u[9], v[5];
+	register int j;
+	register unsigned short *u_p = u;
+	int maxv = 4;
+#endif
+
+	if ((e2->m1 | e2->m2) == 0) {
+                /*
+                 * Exception 8.2 - Divide by zero
+                 */
+		trap(EFDIVZ);
+		e1->m1 = e1->m2 = 0L;
+		e1->exp = EXT_MAX;
+		return;
+	}
+	if ((e1->m1 | e1->m2) == 0) {	/* 0 / anything == 0 */
+		e1->exp = 0;	/* make sure */
+		return;
+	}
+#ifndef USE_DIVIDE
+	/*
+	 * numbers are right shifted one bit to make sure
+	 * that m1 is quaranteed to be larger if its
+	 * maximum bit is set
+	 */
+	b64_rsft(&e1->mantissa);	/* 64 bit shift right */
+	b64_rsft(&e2->mantissa);	/* 64 bit shift right */
+	e1->exp++;
+	e2->exp++;
+#endif
+	/*	check for underflow, divide by zero, etc	*/
+	e1->sign ^= e2->sign;
+	e1->exp -= e2->exp;
+
+#ifndef USE_DIVIDE
+		/* do division of mantissas	*/
+		/* uses partial product method	*/
+		/* init control variables	*/
+
+	count = 64;
+	result.h_32 = 0L;
+	result.l_32 = 0L;
+
+		/* partial product division loop */
+
+	while (count--)	{
+		/* first left shift result 1 bit	*/
+		/* this is ALWAYS done			*/
+
+		b64_lsft(&result);
+
+		/* compare dividend and divisor		*/
+		/* if dividend >= divisor add a bit	*/
+		/* and subtract divisior from dividend	*/
+
+		if ( (e1->m1 < e2->m1) ||
+			((e1->m1 == e2->m1) && (e1->m2 < e2->m2) ))
+			;	/* null statement */
+				/* i.e., don't add or subtract */
+		else	{
+			result.l_32++;	/* ADD	*/
+			if (e2->m2 > e1->m2)
+				e1->m1 -= 1;	/* carry in */
+			e1->m1 -= e2->m1;	/* do SUBTRACTION */
+			e1->m2 -= e2->m2;	/*    SUBTRACTION */
+		}
+
+		/*	shift dividend left one bit OR	*/
+		/*	IF it equals ZERO we can break out	*/
+		/*	of the loop, but still must shift	*/
+		/*	the quotient the remaining count bits	*/
+		/* NB	save the results of this test in error	*/
+		/*	if not zero, then the result is inexact. */
+		/* 	this would be reported in IEEE standard	*/
+
+		/*	lp points to dividend			*/
+		lp = &e1->m1;
+
+		error = ((*lp | *(lp+1)) != 0L) ? 1 : 0;
+		if (error)	{	/* more work */
+			/*	assume max bit == 0 (see above)	*/
+			b64_lsft(&e1->mantissa);
+			continue;
+		}
+		else
+			break;	/* leave loop	*/
+	}	/* end of divide by subtraction loop	*/
+
+	if (count > 0)	{
+		lp = &result.h_32;
+		if (count > 31) {	/* move to higher word */
+			*lp = *(lp+1);
+			count -= 32;
+			*(lp+1) = 0L;	/* clear low word	*/
+		}
+		if (*lp)
+			*lp <<= count;	/* shift rest of way	*/
+		lp++;	/*  == &result.l_32	*/
+		if (*lp) {
+			result.h_32 |= (*lp >> 32-count);
+			*lp <<= count;
+		}
+	}
+#else /* USE_DIVIDE */
+
+	u[4] = (e1->m2 & 1) << 15;
+	b64_rsft(&(e1->mantissa));
+	u[0] = e1->m1 >> 16;
+	u[1] = e1->m1;
+	u[2] = e1->m2 >> 16;
+	u[3] = e1->m2;
+	u[5] = 0; u[6] = 0; u[7] = 0;
+	v[1] = e2->m1 >> 16;
+	v[2] = e2->m1;
+	v[3] = e2->m2 >> 16;
+	v[4] = e2->m2;
+	while (! v[maxv]) maxv--;
+	result.h_32 = 0;
+	result.l_32 = 0;
+	lp = &result.h_32;
+
+	/*
+	 * Use an algorithm of Knuth (The art of programming, Seminumerical
+	 * algorithms), to divide u by v. u and v are both seen as numbers
+	 * with base 65536. 
+	 */
+	for (j = 0; j <= 3; j++, u_p++) {
+		unsigned long q_est, temp;
+
+		if (j == 2) lp++;
+		if (u_p[0] == 0 && u_p[1] < v[1]) continue;
+		temp = ((unsigned long)u_p[0] << 16) + u_p[1];
+		if (u_p[0] >= v[1]) {
+			q_est = 0x0000FFFFL;
+		}
+		else {
+			q_est = temp / v[1];
+		}
+		temp -= q_est * v[1];
+		while (temp < 0x10000 && v[2]*q_est > ((temp<<16)+u_p[2])) {
+			q_est--;
+			temp += v[1];
+		}
+		/*	Now, according to Knuth, we have an estimate of the
+			quotient, that is either correct or one too big, but
+			almost always correct.
+		*/
+		if (q_est != 0)  {
+			int i;
+			unsigned long k = 0;
+			int borrow = 0;
+
+			for (i = maxv; i > 0; i--) {
+				unsigned long tmp = q_est * v[i] + k + borrow;
+				unsigned short md = tmp;
+
+				borrow = (md > u_p[i]);
+				u_p[i] -= md;
+				k = tmp >> 16;
+			}
+			k += borrow;
+			borrow = u_p[0] < k;
+			u_p[0] -= k;
+
+			if (borrow) {
+				/* So, this does not happen often; the estimate
+				   was one too big; correct this
+				*/
+				*lp |= (j & 1) ? (q_est - 1) : ((q_est-1)<<16);
+				borrow = 0;
+				for (i = maxv; i > 0; i--) {
+					unsigned long tmp 
+					    = v[i]+(unsigned long)u_p[i]+borrow;
+					
+					u_p[i] = tmp;
+					borrow = tmp >> 16;
+				}
+				u_p[0] += borrow;
+			}
+			else *lp |= (j & 1) ? q_est : (q_est<<16);
+		}
+	}
+#ifdef	EXCEPTION_INEXACT
+	u_p = &u[0];
+	for (j = 7; j >= 0; j--) {
+		if (*u_p++) {
+			error = 1;
+			break;
+		}
+	}
+#endif
+#endif
+
+#ifdef  EXCEPTION_INEXACT
+        if (error)      {
+                /*
+                 * report here exception 8.5 - Inexact
+                 * from Draft 8.0 of IEEE P754:
+                 * In the absence of an invalid operation exception,
+                 * if the rounded result of an operation is not exact or if
+                 * it overflows without a trap, then the inexact exception
+                 * shall be assigned. The rounded or overflowed result
+                 * shall be delivered to the destination.
+                 */
+                INEXACT();
+#endif
+	e1->mantissa = result;
+
+	nrm_ext(e1);
+	if (e1->exp < EXT_MIN)	{
+		/*
+		 * Exception 8.4 - Underflow
+		 */
+		trap(EFUNFL);	/* underflow */
+		e1->exp = EXT_MIN;
+		e1->m1 = e1->m2 = 0L;
+		return;
+	}
+	if (e1->exp >= EXT_MAX) {
+                /*
+                 * Exception 8.3 - Overflow
+                 */
+                trap(EFOVFL);   /* overflow */
+                e1->exp = EXT_MAX;
+                e1->m1 = e1->m2 = 0L;
+                return;
+        }
+}
Index: /trunk/minix/lib/ack/float/div_ext.s
===================================================================
--- /trunk/minix/lib/ack/float/div_ext.s	(revision 9)
+++ /trunk/minix/lib/ack/float/div_ext.s	(revision 9)
@@ -0,0 +1,211 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .div_ext
+.sect .text
+.div_ext:
+push ebp
+mov ebp,esp
+sub	esp,20
+push esi
+push edi
+mov esi,8(ebp)
+o16 mov -2(ebp),0
+mov edx,12(ebp)
+mov ecx,12(ebp)
+mov ecx,8(ecx)
+or ecx,4(edx)
+jne I1_4
+push 7
+call __fptrp
+pop ecx
+xor edx,edx
+mov 8(esi),edx
+mov 4(esi),edx
+o16 mov 2(esi),16383
+jmp I1_1
+I1_4:
+mov edx,8(esi)
+or edx,4(esi)
+jne I1_7
+o16 mov 2(esi),0
+jmp I1_1
+I1_7:
+lea eax,4(esi)
+push eax
+call .b64_rsft
+pop ecx
+mov edx,12(ebp)
+! kill edx
+add edx,4
+push edx
+call .b64_rsft
+pop ecx
+movsx eax,2(esi)
+inc eax
+movsx eax,eax
+o16 mov 2(esi),eax
+mov edx,12(ebp)
+! kill edx
+movsx ebx,2(edx)
+inc ebx
+mov eax,ebx
+movsx eax,eax
+mov edx,12(ebp)
+! kill edx
+o16 mov 2(edx),eax
+mov edx,12(ebp)
+movsx eax,(edx)
+movsx ebx,(esi)
+xor ebx,eax
+o16 mov (esi),ebx
+movsx eax,2(esi)
+mov edx,12(ebp)
+! kill edx
+movsx ecx,2(edx)
+sub ecx,eax
+neg ecx
+mov eax,ecx
+movsx eax,eax
+o16 mov 2(esi),eax
+o16 mov -18(ebp),64
+mov -12(ebp),0
+mov -8(ebp),0
+I1_10:
+movzx edx,-18(ebp)
+mov eax,edx
+movsx eax,eax
+dec eax
+o16 mov -18(ebp),eax
+mov eax,edx
+movsx eax,eax
+test eax,eax
+je I1_9
+lea eax,-12(ebp)
+push eax
+call .b64_lsft
+pop ecx
+mov edx,12(ebp)
+mov edx,4(edx)
+cmp 4(esi),edx
+jb I1_14
+mov edx,12(ebp)
+mov edx,4(edx)
+cmp 4(esi),edx
+jne I1_13
+mov edx,12(ebp)
+mov edx,8(edx)
+cmp 8(esi),edx
+jb I1_14
+I1_13:
+inc -8(ebp)
+mov edx,12(ebp)
+mov ecx,8(esi)
+cmp 8(edx),ecx
+jbe I1_18
+mov edx,4(esi)
+sub edx,1
+mov 4(esi),edx
+I1_18:
+mov edx,12(ebp)
+mov ecx,4(esi)
+sub ecx,4(edx)
+mov 4(esi),ecx
+mov edx,12(ebp)
+mov ecx,8(esi)
+sub ecx,8(edx)
+mov 8(esi),ecx
+I1_14:
+mov edi,esi
+add edi,4
+mov edx,(edi)
+or edx,4(edi)
+je I1_21
+mov eax,1
+jmp I1_22
+I1_21:
+xor eax,eax
+I1_22:
+o16 mov -2(ebp),eax
+movzx edx,-2(ebp)
+test edx,edx
+je I1_9
+lea eax,4(esi)
+push eax
+call .b64_lsft
+pop ecx
+jmp I1_10
+I1_9:
+movsx eax,-18(ebp)
+! kill cc
+test eax,eax
+jle I1_27
+lea edi,-12(ebp)
+movsx eax,-18(ebp)
+cmp eax,31
+jle I1_30
+mov edx,4(edi)
+mov (edi),edx
+movsx eax,-18(ebp)
+sub eax,32
+o16 mov -18(ebp),eax
+mov 4(edi),0
+I1_30:
+cmp (edi),0
+je I1_33
+movsx eax,-18(ebp)
+mov ecx,eax
+mov edx,(edi)
+sal edx,cl
+mov (edi),edx
+I1_33:
+add edi,4
+cmp (edi),0
+je I1_27
+movsx eax,-18(ebp)
+sub eax,32
+neg eax
+mov ecx,eax
+mov edx,(edi)
+shr edx,cl
+or -12(ebp),edx
+movsx eax,-18(ebp)
+mov ecx,eax
+mov edx,(edi)
+sal edx,cl
+mov (edi),edx
+I1_27:
+lea eax,-12(ebp)
+push eax
+lea eax,4(esi)
+push eax
+mov ecx,2
+call .blm
+push esi
+call .nrm_ext
+pop ecx
+movsx eax,2(esi)
+cmp eax,-16382
+jge I1_39
+push 5
+call __fptrp
+pop ecx
+o16 mov 2(esi),-16382
+xor edx,edx
+mov 8(esi),edx
+mov 4(esi),edx
+jmp I1_1
+I1_39:
+movsx eax,2(esi)
+cmp eax,16383
+jl I1_1
+push 4
+call __fptrp
+pop ecx
+o16 mov 2(esi),16383
+xor edx,edx
+mov 8(esi),edx
+mov 4(esi),edx
+I1_1:
+pop edi
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/dvf4.fc
===================================================================
--- /trunk/minix/lib/ack/float/dvf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/dvf4.fc	(revision 9)
@@ -0,0 +1,26 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/dvf4.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	DIVIDE TWO SINGLES - SINGLE Precision (dvf 4)
+*/
+
+#include	"FP_types.h"
+
+void
+dvf4(s2,s1)
+SINGLE	s1,s2;
+{
+	EXTEND	e1,e2;
+
+	extend(&s1,&e1,sizeof(SINGLE));
+	extend(&s2,&e2,sizeof(SINGLE));
+
+		/* do a divide */
+	div_ext(&e1,&e2);
+	compact(&e1,&s1,sizeof(SINGLE));
+}
Index: /trunk/minix/lib/ack/float/dvf4.s
===================================================================
--- /trunk/minix/lib/ack/float/dvf4.s	(revision 9)
+++ /trunk/minix/lib/ack/float/dvf4.s	(revision 9)
@@ -0,0 +1,37 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .dvf4
+.sect .text
+.dvf4:
+push ebp
+mov ebp,esp
+sub	esp,24
+push 4
+lea eax,-12(ebp)
+push eax
+lea eax,12(ebp)
+push eax
+call .extend
+add esp,12
+push 4
+lea eax,-24(ebp)
+push eax
+lea eax,8(ebp)
+push eax
+call .extend
+add esp,12
+lea eax,-24(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .div_ext
+pop ecx
+pop ecx
+push 4
+lea eax,12(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+leave
+ret
Index: /trunk/minix/lib/ack/float/dvf8.fc
===================================================================
--- /trunk/minix/lib/ack/float/dvf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/dvf8.fc	(revision 9)
@@ -0,0 +1,26 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/dvf8.fc,v 1.1 2005/10/10 15:27:42 beng Exp $ */
+
+/*
+	DIVIDE TWO FLOATS - DOUBLE Precision (DVF 8)
+*/
+
+#include	"FP_types.h"
+
+void
+dvf8(s2,s1)
+DOUBLE	s1,s2;
+{
+	EXTEND	e1,e2;
+
+	extend(&s1.d[0],&e1,sizeof(DOUBLE));
+	extend(&s2.d[0],&e2,sizeof(DOUBLE));
+
+		/* do a divide */
+	div_ext(&e1,&e2);
+	compact(&e1,&s1.d[0],sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/ack/float/dvf8.s
===================================================================
--- /trunk/minix/lib/ack/float/dvf8.s	(revision 9)
+++ /trunk/minix/lib/ack/float/dvf8.s	(revision 9)
@@ -0,0 +1,37 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .dvf8
+.sect .text
+.dvf8:
+push ebp
+mov ebp,esp
+sub	esp,24
+push 8
+lea eax,-12(ebp)
+push eax
+lea eax,16(ebp)
+push eax
+call .extend
+add esp,12
+push 8
+lea eax,-24(ebp)
+push eax
+lea eax,8(ebp)
+push eax
+call .extend
+add esp,12
+lea eax,-24(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .div_ext
+pop ecx
+pop ecx
+push 8
+lea eax,16(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+leave
+ret
Index: /trunk/minix/lib/ack/float/extend.fc
===================================================================
--- /trunk/minix/lib/ack/float/extend.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/extend.fc	(revision 9)
@@ -0,0 +1,111 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/extend.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	CONVERTS FLOATING POINT TO EXTENDED FORMAT
+
+	Two sizes of FLOATING Point are known:
+		SINGLE and DOUBLE
+*/
+/********************************************************/
+/*
+	It is not required to normalize in extended
+	format, but it has been chosen to do so.
+	Extended Format is as follows (at exit):
+
+->sign	S000 0000 | 0000 0000		<SIGN>
+->exp	0EEE EEEE | EEEE EEEE		<EXPONENT>
+->m1	LFFF FFFF | FFFF FFFF		<L.Fraction>
+	FFFF FFFF | FFFF FFFF		<Fraction>
+->m2	FFFF FFFF | FFFF FFFF		<Fraction>
+	FFFF F000 | 0000 0000		<Fraction>
+*/
+/********************************************************/
+
+#include "FP_bias.h"
+#include "FP_shift.h"
+#include "FP_types.h"
+#include "get_put.h"
+/********************************************************/
+
+void
+extend(from,to,size)
+unsigned long	*from;
+EXTEND	*to;
+int	size;
+{
+	register char *cpt1;
+	unsigned long	tmp;
+	int	leadbit = 0;
+
+	cpt1 = (char *) from;
+
+#if FL_MSL_AT_LOW_ADDRESS
+#if FL_MSW_AT_LOW_ADDRESS
+	to->exp = uget2(cpt1);
+#else
+	to->exp = uget2(cpt1+2);
+#endif
+#else
+#if FL_MSW_AT_LOW_ADDRESS
+	to->exp = uget2(cpt1+(size == sizeof(DOUBLE) ? 4 : 0));
+#else
+	to->exp = uget2(cpt1+(size == sizeof(DOUBLE) ? 6 : 2));
+#endif
+#endif
+	to->sign = (to->exp & 0x8000);	/* set sign bit */
+	to->exp ^= to->sign;
+	if (size == sizeof(DOUBLE))
+		to->exp >>= DBL_EXPSHIFT;
+	else
+		to->exp >>= SGL_EXPSHIFT;
+	if (to->exp > 0)
+		leadbit++;	/* will set Lead bit later	*/
+	else to->exp++;
+
+	if (size == sizeof(DOUBLE))	{
+#if FL_MSL_AT_LOW_ADDRESS
+		to->m1 = get4(cpt1);
+		cpt1 += 4;
+		tmp = get4(cpt1);
+#else
+		tmp = get4(cpt1);
+		cpt1 += 4;
+		to->m1 = get4(cpt1);
+#endif
+		if (to->exp == 1 && to->m1 == 0 && tmp == 0) {
+			to->exp = 0;
+			to->sign = 0;
+			to->m1 = 0;
+			to->m2 = 0;
+			return;
+		}
+		to->m1 <<= DBL_M1LEFT;		/* shift	*/
+		to->exp -= DBL_BIAS;		/* remove bias	*/
+		to->m1 |= (tmp>>DBL_RPACK);	/* plus 10 == 32	*/
+		to->m2 = (tmp<<DBL_LPACK);	/* plus 22 == 32	*/
+	}
+	else	{	/* size == sizeof(SINGLE)		*/
+		to->m1 = get4(cpt1);
+		to->m1  <<= SGL_M1LEFT;	/* shift	*/
+		if (to->exp == 1 && to->m1 == 0) {
+			to->exp = 0;
+			to->sign = 0;
+			to->m1 = 0;
+			to->m2 = 0;
+			return;
+		}
+		to->exp -= SGL_BIAS;		/* remove bias	*/
+		to->m2 = 0L;
+	}
+
+	to->m1 |= NORMBIT;				/* set bit L	*/
+	if (leadbit == 0) {		/* set or clear Leading Bit	*/
+		to->m1 &= ~NORMBIT;			/* clear bit L	*/
+		nrm_ext(to);				/* and normalize */
+	}
+}
Index: /trunk/minix/lib/ack/float/extend.s
===================================================================
--- /trunk/minix/lib/ack/float/extend.s	(revision 9)
+++ /trunk/minix/lib/ack/float/extend.s	(revision 9)
@@ -0,0 +1,127 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .extend
+.sect .text
+.extend:
+push ebp
+mov ebp,esp
+sub	esp,12
+push esi
+push edi
+mov esi,12(ebp)
+mov -12(ebp),0
+mov edi,8(ebp)
+push edi
+cmp 16(ebp),8
+jne I1_4
+mov eax,6
+jmp I1_5
+I1_4:
+mov eax,2
+I1_5:
+pop edx
+add edx,eax
+movsx eax,(edx)
+o16 mov 2(esi),eax
+movsx ebx,2(esi)
+and ebx,32768
+o16 mov (esi),ebx
+movsx eax,(esi)
+movsx ecx,2(esi)
+xor ecx,eax
+mov eax,ecx
+movsx eax,eax
+o16 mov 2(esi),eax
+cmp 16(ebp),8
+jne I1_7
+movsx ebx,2(esi)
+sar ebx,4
+mov eax,ebx
+movsx eax,eax
+o16 mov 2(esi),eax
+jmp I1_8
+I1_7:
+movsx eax,2(esi)
+sar eax,7
+movsx eax,eax
+o16 mov 2(esi),eax
+I1_8:
+movsx eax,2(esi)
+! kill cc
+test eax,eax
+jle I1_10
+inc -12(ebp)
+jmp I1_11
+I1_10:
+movsx eax,2(esi)
+inc eax
+movsx eax,eax
+o16 mov 2(esi),eax
+I1_11:
+cmp 16(ebp),8
+jne I1_13
+mov edx,(edi)
+mov -8(ebp),edx
+add edi,4
+mov edx,(edi)
+mov 4(esi),edx
+movsx eax,2(esi)
+cmp eax,1
+jne I1_16
+cmp 4(esi),0
+jne I1_16
+cmp -8(ebp),0
+jne I1_16
+o16 mov 2(esi),0
+o16 mov (esi),0
+mov 4(esi),0
+mov 8(esi),0
+jmp I1_1
+I1_16:
+mov edx,4(esi)
+sal edx,11
+mov 4(esi),edx
+movsx eax,2(esi)
+sub eax,1023
+movsx eax,eax
+o16 mov 2(esi),eax
+mov edx,-8(ebp)
+shr edx,21
+or 4(esi),edx
+mov edx,-8(ebp)
+sal edx,11
+mov 8(esi),edx
+jmp I1_14
+I1_13:
+mov edx,(edi)
+mov 4(esi),edx
+sal edx,8
+mov 4(esi),edx
+movsx eax,2(esi)
+cmp eax,1
+jne I1_21
+cmp 4(esi),0
+jne I1_21
+o16 mov 2(esi),0
+o16 mov (esi),0
+mov 4(esi),0
+mov 8(esi),0
+jmp I1_1
+I1_21:
+movsx eax,2(esi)
+sub eax,127
+movsx eax,eax
+o16 mov 2(esi),eax
+mov 8(esi),0
+I1_14:
+or 4(esi),-2147483648
+cmp -12(ebp),0
+jne I1_1
+and 4(esi),2147483647
+push esi
+call .nrm_ext
+pop ecx
+I1_1:
+pop edi
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/fef4.fc
===================================================================
--- /trunk/minix/lib/ack/float/fef4.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/fef4.fc	(revision 9)
@@ -0,0 +1,33 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/fef4.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	SEPERATE INTO EXPONENT AND FRACTION (FEF 4)
+*/
+
+#include	"FP_types.h"
+
+void
+fef4(r,s1)
+SINGLE	s1;
+struct fef4_returns	*r;
+{
+	EXTEND	buf;
+	register struct fef4_returns	*p = r;	/* make copy; r might refer
+						   to itself (see table)
+						*/
+
+	extend(&s1,&buf,sizeof(SINGLE));
+	if (buf.exp == 0 && buf.m1 == 0 && buf.m2 == 0) {
+		p->e = 0;
+	}
+	else {
+		p->e = buf.exp+1;
+		buf.exp = -1;
+	}
+	compact(&buf,&p->f,sizeof(SINGLE));
+}
Index: /trunk/minix/lib/ack/float/fef4.s
===================================================================
--- /trunk/minix/lib/ack/float/fef4.s	(revision 9)
+++ /trunk/minix/lib/ack/float/fef4.s	(revision 9)
@@ -0,0 +1,41 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .fef4
+.sect .text
+.fef4:
+push ebp
+mov ebp,esp
+sub	esp,12
+push esi
+mov esi,8(ebp)
+push 4
+lea eax,-12(ebp)
+push eax
+lea eax,12(ebp)
+push eax
+call .extend
+add esp,12
+movzx edx,-10(ebp)
+test edx,edx
+jne I1_4
+cmp -8(ebp),0
+jne I1_4
+cmp -4(ebp),0
+jne I1_4
+mov (esi),0
+jmp I1_5
+I1_4:
+movsx eax,-10(ebp)
+inc eax
+mov (esi),eax
+o16 mov -10(ebp),-1
+I1_5:
+push 4
+lea eax,4(esi)
+push eax
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/fef8.fc
===================================================================
--- /trunk/minix/lib/ack/float/fef8.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/fef8.fc	(revision 9)
@@ -0,0 +1,33 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/fef8.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	SEPERATE DOUBLE INTO EXPONENT AND FRACTION (FEF 8)
+*/
+
+#include	"FP_types.h"
+
+void
+fef8(r, s1)
+DOUBLE	s1;
+struct fef8_returns *r;
+{
+	EXTEND	buf;
+	register struct fef8_returns *p = r;	/* make copy, r might refer
+						   to itself (see table)
+						*/
+
+	extend(&s1.d[0],&buf,sizeof(DOUBLE));
+	if (buf.exp == 0 && buf.m1 == 0 && buf.m2 == 0) {
+		p->e = 0;
+	}
+	else {
+		p->e = buf.exp + 1;
+		buf.exp = -1;
+	}
+	compact(&buf,&p->f.d[0],sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/ack/float/fef8.s
===================================================================
--- /trunk/minix/lib/ack/float/fef8.s	(revision 9)
+++ /trunk/minix/lib/ack/float/fef8.s	(revision 9)
@@ -0,0 +1,41 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .fef8
+.sect .text
+.fef8:
+push ebp
+mov ebp,esp
+sub	esp,12
+push esi
+mov esi,8(ebp)
+push 8
+lea eax,-12(ebp)
+push eax
+lea eax,12(ebp)
+push eax
+call .extend
+add esp,12
+movzx edx,-10(ebp)
+test edx,edx
+jne I1_4
+cmp -8(ebp),0
+jne I1_4
+cmp -4(ebp),0
+jne I1_4
+mov (esi),0
+jmp I1_5
+I1_4:
+movsx eax,-10(ebp)
+inc eax
+mov (esi),eax
+o16 mov -10(ebp),-1
+I1_5:
+push 8
+lea eax,4(esi)
+push eax
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/fif4.fc
===================================================================
--- /trunk/minix/lib/ack/float/fif4.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/fif4.fc	(revision 9)
@@ -0,0 +1,46 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/fif4.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	MULTIPLY AND DISMEMBER PARTS (FIF 4)
+*/
+
+#include "FP_types.h"
+#include "FP_shift.h"
+
+void
+fif4(p,x,y)
+SINGLE	x,y;
+struct fif4_returns *p;
+{
+
+	EXTEND	e1,e2;
+
+	extend(&y,&e1,sizeof(SINGLE));
+	extend(&x,&e2,sizeof(SINGLE));
+		/* do a multiply */
+	mul_ext(&e1,&e2);
+	e2 = e1;
+	compact(&e2,&y,sizeof(SINGLE));
+	if (e1.exp < 0) {
+		p->ipart = 0;
+		p->fpart = y;
+		return;
+	}
+	if (e1.exp > 30 - SGL_M1LEFT) {
+		p->ipart = y;
+		p->fpart = 0;
+		return;
+	}
+	b64_sft(&e1.mantissa, 63 - e1.exp);
+	b64_sft(&e1.mantissa, e1.exp - 63);	/* "loose" low order bits */
+	compact(&e1,&(p->ipart),sizeof(SINGLE));
+	extend(&(p->ipart), &e2, sizeof(SINGLE));
+	extend(&y, &e1, sizeof(SINGLE));
+	sub_ext(&e1, &e2);
+	compact(&e1, &(p->fpart), sizeof(SINGLE));
+}
Index: /trunk/minix/lib/ack/float/fif4.s
===================================================================
--- /trunk/minix/lib/ack/float/fif4.s	(revision 9)
+++ /trunk/minix/lib/ack/float/fif4.s	(revision 9)
@@ -0,0 +1,113 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .fif4
+.sect .text
+.fif4:
+push ebp
+mov ebp,esp
+sub	esp,24
+push esi
+mov esi,8(ebp)
+push 4
+lea eax,-12(ebp)
+push eax
+lea eax,16(ebp)
+push eax
+call .extend
+add esp,12
+push 4
+lea eax,-24(ebp)
+push eax
+lea eax,12(ebp)
+push eax
+call .extend
+add esp,12
+lea eax,-24(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .mul_ext
+pop ecx
+pop ecx
+lea eax,-12(ebp)
+push eax
+lea eax,-24(ebp)
+push eax
+mov ecx,3
+call .blm
+push 4
+lea eax,16(ebp)
+push eax
+lea eax,-24(ebp)
+push eax
+call .compact
+add esp,12
+movsx eax,-10(ebp)
+test eax,eax
+jns I1_4
+mov (esi),0
+mov edx,16(ebp)
+mov 4(esi),edx
+jmp I1_1
+I1_4:
+movsx eax,-10(ebp)
+cmp eax,22
+jle I1_7
+mov edx,16(ebp)
+mov (esi),edx
+mov 4(esi),0
+jmp I1_1
+I1_7:
+movsx eax,-10(ebp)
+sub eax,63
+neg eax
+push eax
+lea eax,-8(ebp)
+push eax
+call .b64_sft
+pop ecx
+pop ecx
+movsx eax,-10(ebp)
+sub eax,63
+push eax
+lea eax,-8(ebp)
+push eax
+call .b64_sft
+pop ecx
+pop ecx
+push 4
+push esi
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+push 4
+lea eax,-24(ebp)
+push eax
+push esi
+call .extend
+add esp,12
+push 4
+lea eax,-12(ebp)
+push eax
+lea eax,16(ebp)
+push eax
+call .extend
+add esp,12
+lea eax,-24(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .sub_ext
+pop ecx
+pop ecx
+push 4
+lea eax,4(esi)
+push eax
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+I1_1:
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/fif8.fc
===================================================================
--- /trunk/minix/lib/ack/float/fif8.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/fif8.fc	(revision 9)
@@ -0,0 +1,48 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/fif8.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	MULTIPLY AND DISMEMBER PARTS (FIF 8)
+*/
+
+#include "FP_types.h"
+#include "FP_shift.h"
+
+void
+fif8(p,x,y)
+DOUBLE	x,y;
+struct fif8_returns *p;
+{
+
+	EXTEND	e1,e2;
+
+	extend(&y.d[0],&e1,sizeof(DOUBLE));
+	extend(&x.d[0],&e2,sizeof(DOUBLE));
+		/* do a multiply */
+	mul_ext(&e1,&e2);
+	e2 = e1;
+	compact(&e2, &y.d[0], sizeof(DOUBLE));
+	if (e1.exp < 0) {
+		p->ipart.d[0] = 0;
+		p->ipart.d[1] = 0;
+		p->fpart = y;
+		return;
+	}
+	if (e1.exp > 62 - DBL_M1LEFT) {
+		p->ipart = y;
+		p->fpart.d[0] = 0;
+		p->fpart.d[1] = 0;
+		return;
+	}
+	b64_sft(&e1.mantissa, 63 - e1.exp);
+	b64_sft(&e1.mantissa, e1.exp - 63);	/* "loose" low order bits */
+	compact(&e1, &(p->ipart.d[0]), sizeof(DOUBLE));
+	extend(&(p->ipart.d[0]), &e2, sizeof(DOUBLE));
+	extend(&y.d[0], &e1, sizeof(DOUBLE));
+	sub_ext(&e1, &e2);
+	compact(&e1, &(p->fpart.d[0]), sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/ack/float/fif8.s
===================================================================
--- /trunk/minix/lib/ack/float/fif8.s	(revision 9)
+++ /trunk/minix/lib/ack/float/fif8.s	(revision 9)
@@ -0,0 +1,122 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .fif8
+.sect .text
+.fif8:
+push ebp
+mov ebp,esp
+sub	esp,24
+push esi
+mov esi,8(ebp)
+push 8
+lea eax,-12(ebp)
+push eax
+lea eax,20(ebp)
+push eax
+call .extend
+add esp,12
+push 8
+lea eax,-24(ebp)
+push eax
+lea eax,12(ebp)
+push eax
+call .extend
+add esp,12
+lea eax,-24(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .mul_ext
+pop ecx
+pop ecx
+lea eax,-12(ebp)
+push eax
+lea eax,-24(ebp)
+push eax
+mov ecx,3
+call .blm
+push 8
+lea eax,20(ebp)
+push eax
+lea eax,-24(ebp)
+push eax
+call .compact
+add esp,12
+movsx eax,-10(ebp)
+test eax,eax
+jns I1_4
+mov (esi),0
+mov 4(esi),0
+lea eax,20(ebp)
+push eax
+lea eax,8(esi)
+push eax
+mov ecx,2
+call .blm
+jmp I1_1
+I1_4:
+movsx eax,-10(ebp)
+cmp eax,51
+jle I1_7
+lea eax,20(ebp)
+push eax
+push esi
+mov ecx,2
+call .blm
+mov 8(esi),0
+mov 12(esi),0
+jmp I1_1
+I1_7:
+movsx eax,-10(ebp)
+sub eax,63
+neg eax
+push eax
+lea eax,-8(ebp)
+push eax
+call .b64_sft
+pop ecx
+pop ecx
+movsx eax,-10(ebp)
+sub eax,63
+push eax
+lea eax,-8(ebp)
+push eax
+call .b64_sft
+pop ecx
+pop ecx
+push 8
+push esi
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+push 8
+lea eax,-24(ebp)
+push eax
+push esi
+call .extend
+add esp,12
+push 8
+lea eax,-12(ebp)
+push eax
+lea eax,20(ebp)
+push eax
+call .extend
+add esp,12
+lea eax,-24(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .sub_ext
+pop ecx
+pop ecx
+push 8
+lea eax,8(esi)
+push eax
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+I1_1:
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/fptrp.s
===================================================================
--- /trunk/minix/lib/ack/float/fptrp.s	(revision 9)
+++ /trunk/minix/lib/ack/float/fptrp.s	(revision 9)
@@ -0,0 +1,19 @@
+#
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define __fptrp
+.sect .text
+__fptrp:
+#if __i386
+	push	ebp
+	mov	ebp, esp
+	mov	eax, 8(bp)
+	call	.Xtrp
+	leave
+	ret
+#else /* i86 */
+	push	bp
+	mov	bp, sp
+	mov	ax, 4(bp)
+	call	.Xtrp
+	jmp	.cret
+#endif
Index: /trunk/minix/lib/ack/float/get_put.h
===================================================================
--- /trunk/minix/lib/ack/float/get_put.h	(revision 9)
+++ /trunk/minix/lib/ack/float/get_put.h	(revision 9)
@@ -0,0 +1,41 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/get_put.h,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+#include <byte_order.h>
+
+#if CHAR_UNSIGNED
+#define Xchar(ch)	(ch)
+#else
+#define Xchar(ch)	((ch) & 0377)
+#endif
+
+#define BYTES_REVERSED (MSB_AT_LOW_ADDRESS != FL_MSB_AT_LOW_ADDRESS)
+#define WORDS_REVERSED (MSW_AT_LOW_ADDRESS != FL_MSW_AT_LOW_ADDRESS)
+#define LONGS_REVERSED (FL_MSL_AT_LOW_ADDRESS)
+
+#if BYTES_REVERSED
+#define uget2(c)	(Xchar((c)[1]) | ((unsigned) Xchar((c)[0]) << 8))
+#define Xput2(i, c)	(((c)[1] = (i)), ((c)[0] = (i) >> 8))
+#define put2(i, c)	{ register int j = (i); Xput2(j, c); }
+#else
+#define uget2(c)	(* ((unsigned short *) (c)))
+#define Xput2(i, c)	(* ((short *) (c)) = (i))
+#define put2(i, c)	Xput2(i, c)
+#endif
+
+#define get2(c)		((short) uget2(c))
+
+#if WORDS_REVERSED || BYTES_REVERSED
+#define get4(c)		(uget2((c)+2) | ((long) uget2(c) << 16))
+#define put4(l, c)	{ register long x=(l); \
+			  Xput2((int)x,(c)+2); \
+			  Xput2((int)(x>>16),(c)); \
+			}
+#else
+#define get4(c)		(* ((long *) (c)))
+#define put4(l, c)	(* ((long *) (c)) = (l))
+#endif
Index: /trunk/minix/lib/ack/float/mlf4.fc
===================================================================
--- /trunk/minix/lib/ack/float/mlf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/mlf4.fc	(revision 9)
@@ -0,0 +1,25 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/mlf4.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+ * Multiply Single Precesion Float (MLF 4)
+ */
+
+#include	"FP_types.h"
+
+void
+mlf4(s2,s1)
+SINGLE	s1,s2;
+{
+	EXTEND	e1,e2;
+
+	extend(&s1,&e1,sizeof(SINGLE));
+	extend(&s2,&e2,sizeof(SINGLE));
+		/* do a multiply */
+	mul_ext(&e1,&e2);
+	compact(&e1,&s1,sizeof(SINGLE));
+}
Index: /trunk/minix/lib/ack/float/mlf4.s
===================================================================
--- /trunk/minix/lib/ack/float/mlf4.s	(revision 9)
+++ /trunk/minix/lib/ack/float/mlf4.s	(revision 9)
@@ -0,0 +1,37 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .mlf4
+.sect .text
+.mlf4:
+push ebp
+mov ebp,esp
+sub	esp,24
+push 4
+lea eax,-12(ebp)
+push eax
+lea eax,12(ebp)
+push eax
+call .extend
+add esp,12
+push 4
+lea eax,-24(ebp)
+push eax
+lea eax,8(ebp)
+push eax
+call .extend
+add esp,12
+lea eax,-24(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .mul_ext
+pop ecx
+pop ecx
+push 4
+lea eax,12(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+leave
+ret
Index: /trunk/minix/lib/ack/float/mlf8.fc
===================================================================
--- /trunk/minix/lib/ack/float/mlf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/mlf8.fc	(revision 9)
@@ -0,0 +1,25 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/mlf8.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+ * Multiply Double Precision Float (MLF 8)
+ */
+
+#include	"FP_types.h"
+
+void
+mlf8(s2,s1)
+DOUBLE	s1,s2;
+{
+	EXTEND	e1,e2;
+
+	extend(&s1.d[0],&e1,sizeof(DOUBLE));
+	extend(&s2.d[0],&e2,sizeof(DOUBLE));
+		/* do a multiply */
+	mul_ext(&e1,&e2);
+	compact(&e1,&s1.d[0],sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/ack/float/mlf8.s
===================================================================
--- /trunk/minix/lib/ack/float/mlf8.s	(revision 9)
+++ /trunk/minix/lib/ack/float/mlf8.s	(revision 9)
@@ -0,0 +1,37 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .mlf8
+.sect .text
+.mlf8:
+push ebp
+mov ebp,esp
+sub	esp,24
+push 8
+lea eax,-12(ebp)
+push eax
+lea eax,16(ebp)
+push eax
+call .extend
+add esp,12
+push 8
+lea eax,-24(ebp)
+push eax
+lea eax,8(ebp)
+push eax
+call .extend
+add esp,12
+lea eax,-24(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .mul_ext
+pop ecx
+pop ecx
+push 8
+lea eax,16(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+leave
+ret
Index: /trunk/minix/lib/ack/float/mul_ext.fc
===================================================================
--- /trunk/minix/lib/ack/float/mul_ext.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/mul_ext.fc	(revision 9)
@@ -0,0 +1,98 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/mul_ext.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	ROUTINE TO MULTIPLY TWO EXTENDED FORMAT NUMBERS
+*/
+
+# include "FP_bias.h"
+# include "FP_trap.h"
+# include "FP_types.h"
+# include "FP_shift.h"
+
+void
+mul_ext(e1,e2)
+EXTEND	*e1,*e2;
+{
+	register int	i,j;		/* loop control	*/
+	unsigned short	mp[4];		/* multiplier */
+	unsigned short	mc[4];		/* multipcand */
+	unsigned short	result[8];	/* result */
+	register unsigned short *pres;
+
+	/* first save the sign (XOR)			*/
+	e1->sign ^= e2->sign;
+
+	/* compute new exponent */
+	e1->exp += e2->exp + 1;
+	/* 128 bit multiply of mantissas			*/
+
+		/* assign unknown long formats		*/
+		/* to known unsigned word formats	*/
+	mp[0] = e1->m1 >> 16;
+	mp[1] = (unsigned short) e1->m1;
+	mp[2] = e1->m2 >> 16;
+	mp[3] = (unsigned short) e1->m2;
+	mc[0] = e2->m1 >> 16;
+	mc[1] = (unsigned short) e2->m1;
+	mc[2] = e2->m2 >> 16;
+	mc[3] = (unsigned short) e2->m2;
+	for (i = 8; i--;) {
+		result[i] = 0;
+	}
+	/*
+	 *	fill registers with their components
+	 */
+	for(i=4, pres = &result[4];i--;pres--) if (mp[i]) {
+		unsigned short k = 0;
+		unsigned long mpi = mp[i];
+		for(j=4;j--;) {
+			unsigned long tmp = (unsigned long)pres[j] + k;
+			if (mc[j]) tmp += mpi * mc[j];
+			pres[j] = tmp;
+			k = tmp >> 16;
+		}
+		pres[-1] = k;
+	}
+        if (! (result[0] & 0x8000)) {
+                e1->exp--;
+                for (i = 0; i <= 3; i++) {
+                        result[i] <<= 1;
+                        if (result[i+1]&0x8000) result[i] |= 1;
+                }
+                result[4] <<= 1;
+        }
+
+	/*
+	 *	combine the registers to a total
+	 */
+	e1->m1 = ((unsigned long)(result[0]) << 16) + result[1];
+	e1->m2 = ((unsigned long)(result[2]) << 16) + result[3];
+	if (result[4] & 0x8000) {
+		if (++e1->m2 == 0)
+			if (++e1->m1 == 0) {
+				e1->m1 = NORMBIT;
+				e1->exp++;
+			}
+	}
+
+					/* check for overflow	*/
+	if (e1->exp >= EXT_MAX)	{
+		trap(EFOVFL);
+			/* if caught 			*/
+			/* return signed infinity	*/
+		e1->exp = EXT_MAX;
+infinity:	e1->m1 = e1->m2 =0L;
+		return;
+	}
+				/* check for underflow	*/
+	if (e1->exp < EXT_MIN)	{
+		trap(EFUNFL);
+		e1->exp = EXT_MIN;
+		goto infinity;
+	}
+}
Index: /trunk/minix/lib/ack/float/mul_ext.s
===================================================================
--- /trunk/minix/lib/ack/float/mul_ext.s	(revision 9)
+++ /trunk/minix/lib/ack/float/mul_ext.s	(revision 9)
@@ -0,0 +1,209 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .mul_ext
+.sect .text
+.mul_ext:
+push ebp
+mov ebp,esp
+sub	esp,60
+push esi
+push edi
+mov esi,8(ebp)
+mov edx,12(ebp)
+movsx eax,(edx)
+movsx ebx,(esi)
+xor ebx,eax
+o16 mov (esi),ebx
+mov edx,12(ebp)
+! kill edx
+movsx eax,2(edx)
+inc eax
+movsx ecx,2(esi)
+add ecx,eax
+mov eax,ecx
+movsx eax,eax
+o16 mov 2(esi),eax
+mov edx,4(esi)
+shr edx,16
+and edx,65535
+o16 mov -16(ebp),edx
+mov edx,65535
+and edx,4(esi)
+o16 mov -14(ebp),edx
+mov edx,8(esi)
+shr edx,16
+and edx,65535
+o16 mov -12(ebp),edx
+mov edx,65535
+and edx,8(esi)
+o16 mov -10(ebp),edx
+mov edx,12(ebp)
+mov edx,4(edx)
+shr edx,16
+and edx,65535
+o16 mov -24(ebp),edx
+mov edx,12(ebp)
+mov ecx,65535
+and ecx,4(edx)
+o16 mov -22(ebp),ecx
+mov edx,8(edx)
+shr edx,16
+and edx,65535
+o16 mov -20(ebp),edx
+mov edx,12(ebp)
+mov ecx,65535
+and ecx,8(edx)
+o16 mov -18(ebp),ecx
+mov edi,8
+I1_6:
+mov edx,edi
+dec edx
+push edi
+mov edi,edx
+pop edx
+test edx,edx
+je I1_3
+o16 mov -40(ebp)(edi*2),0
+jmp I1_6
+I1_3:
+mov edi,4
+lea edx,-32(ebp)
+mov -44(ebp),edx
+I1_10:
+mov edx,edi
+dec edx
+push edi
+mov edi,edx
+pop edx
+test edx,edx
+je I1_7
+movzx edx,-16(ebp)(edi*2)
+test edx,edx
+je I1_8
+o16 mov -46(ebp),0
+movzx edx,-16(ebp)(edi*2)
+mov -52(ebp),edx
+mov -8(ebp),4
+I1_17:
+mov edx,-8(ebp)
+mov ecx,edx
+dec ecx
+mov -8(ebp),ecx
+test edx,edx
+je I1_14
+mov edx,-44(ebp)
+movzx ebx,-46(ebp)
+movzx eax,0(edx)(ecx*2)
+add ebx,eax
+mov -56(ebp),ebx
+movzx edx,-24(ebp)(ecx*2)
+test edx,edx
+je I1_19
+movzx edx,-24(ebp)(ecx*2)
+imul edx,-52(ebp)
+add -56(ebp),edx
+I1_19:
+mov edx,65535
+and edx,-56(ebp)
+mov ecx,-8(ebp)
+mov ebx,-44(ebp)
+o16 mov 0(ebx)(ecx*2),edx
+mov edx,-56(ebp)
+shr edx,16
+and edx,65535
+o16 mov -46(ebp),edx
+jmp I1_17
+I1_14:
+mov edx,-44(ebp)
+! kill edx
+o16 mov cx,-46(ebp)
+o16 mov -2(edx),cx
+I1_8:
+add -44(ebp),-2
+jmp I1_10
+I1_7:
+movzx edx,-40(ebp)
+test edx,32768
+jne I1_22
+movsx eax,2(esi)
+dec eax
+movsx eax,eax
+o16 mov 2(esi),eax
+xor edi,edi
+I1_27:
+cmp edi,3
+jg I1_24
+lea edx,-40(ebp)(edi*2)
+mov -60(ebp),edx
+movzx ecx,(edx)
+sal ecx,1
+and ecx,65535
+o16 mov (edx),ecx
+mov edx,edi
+inc edx
+movzx ecx,-40(ebp)(edx*2)
+test ecx,32768
+je I1_25
+lea edx,-40(ebp)(edi*2)
+mov -60(ebp),edx
+movzx ecx,(edx)
+or ecx,1
+and ecx,65535
+o16 mov (edx),ecx
+I1_25:
+inc edi
+jmp I1_27
+I1_24:
+movzx edx,-32(ebp)
+sal edx,1
+and edx,65535
+o16 mov -32(ebp),edx
+I1_22:
+movzx edx,-40(ebp)
+sal edx,16
+movzx ecx,-38(ebp)
+add ecx,edx
+mov 4(esi),ecx
+movzx edx,-36(ebp)
+sal edx,16
+movzx ecx,-34(ebp)
+add ecx,edx
+mov 8(esi),ecx
+movzx edx,-32(ebp)
+test edx,32768
+je I1_32
+add 8(esi),1
+jne I1_32
+add 4(esi),1
+jne I1_32
+mov 4(esi),-2147483648
+movsx eax,2(esi)
+inc eax
+movsx eax,eax
+o16 mov 2(esi),eax
+I1_32:
+movsx eax,2(esi)
+cmp eax,16383
+jl I1_41
+push 4
+call __fptrp
+pop ecx
+o16 mov 2(esi),16383
+I1_43:
+xor edx,edx
+mov 8(esi),edx
+mov 4(esi),edx
+jmp I1_1
+I1_41:
+movsx eax,2(esi)
+cmp eax,-16382
+jge I1_1
+push 5
+call __fptrp
+pop ecx
+o16 mov 2(esi),-16382
+jmp I1_43
+I1_1:
+pop edi
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/ngf4.fc
===================================================================
--- /trunk/minix/lib/ack/float/ngf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/ngf4.fc	(revision 9)
@@ -0,0 +1,27 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/ngf4.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+		NEGATE A FLOATING POINT (NGF 4)
+*/
+/********************************************************/
+
+#include "FP_types.h"
+#include "get_put.h"
+
+#define OFF ((FL_MSW_AT_LOW_ADDRESS ? 0 : 2) + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1))
+void
+ngf4(f)
+SINGLE	f;
+{
+	unsigned char *p;
+
+	if (f != (SINGLE) 0) {
+		p = (unsigned char *) &f + OFF;
+		*p ^= 0x80;
+	}
+}
Index: /trunk/minix/lib/ack/float/ngf4.s
===================================================================
--- /trunk/minix/lib/ack/float/ngf4.s	(revision 9)
+++ /trunk/minix/lib/ack/float/ngf4.s	(revision 9)
@@ -0,0 +1,17 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .ngf4
+.sect .text
+.ngf4:
+push ebp
+mov ebp,esp
+push esi
+cmp 8(ebp),0
+je I1_1
+lea esi,11(ebp)
+movzxb edx,(esi)
+xor edx,128
+movb (esi),dl
+I1_1:
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/ngf8.fc
===================================================================
--- /trunk/minix/lib/ack/float/ngf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/ngf8.fc	(revision 9)
@@ -0,0 +1,28 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/ngf8.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+		NEGATE A FLOATING POINT (NGF 8)
+*/
+/********************************************************/
+
+#include "FP_types.h"
+#include "get_put.h"
+
+#define OFF ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1))
+
+void
+ngf8(f)
+DOUBLE	f;
+{
+	unsigned char	*p;
+
+	if (f.d[0] != 0 || f.d[1] != 0) {
+		p = (unsigned char *) &f + OFF;
+		*p ^= 0x80;
+	}
+}
Index: /trunk/minix/lib/ack/float/ngf8.s
===================================================================
--- /trunk/minix/lib/ack/float/ngf8.s	(revision 9)
+++ /trunk/minix/lib/ack/float/ngf8.s	(revision 9)
@@ -0,0 +1,20 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .ngf8
+.sect .text
+.ngf8:
+push ebp
+mov ebp,esp
+push esi
+cmp 8(ebp),0
+jne I1_3
+cmp 12(ebp),0
+je I1_1
+I1_3:
+lea esi,15(ebp)
+movzxb edx,(esi)
+xor edx,128
+movb (esi),dl
+I1_1:
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/nrm_ext.fc
===================================================================
--- /trunk/minix/lib/ack/float/nrm_ext.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/nrm_ext.fc	(revision 9)
@@ -0,0 +1,50 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/nrm_ext.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/********************************************************/
+/*
+	NORMALIZE an EXTENDED FORMAT NUMBER
+*/
+/********************************************************/
+
+#include "FP_shift.h"
+#include "FP_types.h"
+
+void
+nrm_ext(e1)
+EXTEND	*e1;
+{
+		/* we assume that the mantissa != 0	*/
+		/* if it is then just return		*/
+		/* to let it be a problem elsewhere	*/
+		/* THAT IS, The exponent is not set to	*/
+		/* zero. If we don't test here an	*/
+		/* infinite loop is generated when	*/
+		/* mantissa is zero			*/
+
+	if ((e1->m1 | e1->m2) == 0L)
+		return;
+
+		/* if top word is zero mov low word	*/
+		/* to top word, adjust exponent value	*/
+	if (e1->m1 == 0L)	{
+		e1->m1 = e1->m2;
+		e1->m2 = 0L;
+		e1->exp -= 32;
+	}
+	if ((e1->m1 & NORMBIT) == 0) {
+		unsigned long l = ((unsigned long)NORMBIT >> 1);
+		int cnt = -1;
+
+		while (! (l & e1->m1)) {
+			l >>= 1;
+			cnt--;
+		}
+		e1->exp += cnt;
+		b64_sft(&(e1->mantissa), cnt);
+	}
+}
Index: /trunk/minix/lib/ack/float/nrm_ext.s
===================================================================
--- /trunk/minix/lib/ack/float/nrm_ext.s	(revision 9)
+++ /trunk/minix/lib/ack/float/nrm_ext.s	(revision 9)
@@ -0,0 +1,50 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .nrm_ext
+.sect .text
+.nrm_ext:
+push ebp
+mov ebp,esp
+sub	esp,4
+push esi
+push edi
+mov esi,8(ebp)
+mov edx,8(esi)
+or edx,4(esi)
+je I1_1
+cmp 4(esi),0
+jne I1_7
+mov edx,8(esi)
+mov 4(esi),edx
+mov 8(esi),0
+movsx eax,2(esi)
+sub eax,32
+movsx eax,eax
+o16 mov 2(esi),eax
+I1_7:
+test 4(esi),-2147483648
+jne I1_1
+mov -4(ebp),1073741824
+mov edi,-1
+I1_13:
+mov edx,-4(ebp)
+test 4(esi),edx
+jne I1_12
+shr -4(ebp),1
+dec edi
+jmp I1_13
+I1_12:
+movsx eax,2(esi)
+add eax,edi
+movsx eax,eax
+o16 mov 2(esi),eax
+push edi
+lea eax,4(esi)
+push eax
+call .b64_sft
+pop ecx
+pop ecx
+I1_1:
+pop edi
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/sbf4.fc
===================================================================
--- /trunk/minix/lib/ack/float/sbf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/sbf4.fc	(revision 9)
@@ -0,0 +1,27 @@
+/*
+ (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/sbf4.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	SUBTRACT TWO FLOATS - SINGLE Precision (SBF 4)
+*/
+
+#include	"FP_types.h"
+
+void
+sbf4(s2,s1)
+SINGLE	s1,s2;
+{
+	EXTEND e1,e2;
+
+	if (s2 == (SINGLE) 0) {
+		return;
+	}
+	extend(&s1,&e1,sizeof(SINGLE));
+	extend(&s2,&e2,sizeof(SINGLE));
+	sub_ext(&e1,&e2);
+	compact(&e1,&s1,sizeof(SINGLE));
+}
Index: /trunk/minix/lib/ack/float/sbf4.s
===================================================================
--- /trunk/minix/lib/ack/float/sbf4.s	(revision 9)
+++ /trunk/minix/lib/ack/float/sbf4.s	(revision 9)
@@ -0,0 +1,40 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .sbf4
+.sect .text
+.sbf4:
+push ebp
+mov ebp,esp
+sub	esp,24
+cmp 8(ebp),0
+je I1_1
+push 4
+lea eax,-12(ebp)
+push eax
+lea eax,12(ebp)
+push eax
+call .extend
+add esp,12
+push 4
+lea eax,-24(ebp)
+push eax
+lea eax,8(ebp)
+push eax
+call .extend
+add esp,12
+lea eax,-24(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .sub_ext
+pop ecx
+pop ecx
+push 4
+lea eax,12(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+I1_1:
+leave
+ret
Index: /trunk/minix/lib/ack/float/sbf8.fc
===================================================================
--- /trunk/minix/lib/ack/float/sbf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/sbf8.fc	(revision 9)
@@ -0,0 +1,27 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/sbf8.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	SUBTRACT TWO FLOATS - DOUBLE Precision (SBF 8)
+*/
+
+#include	"FP_types.h"
+
+void
+sbf8(s2,s1)
+DOUBLE	s1,s2;
+{
+	EXTEND e1, e2;
+
+	if (s2.d[0] == 0 && s2.d[1] == 0) {
+		return;
+	}
+	extend(&s1.d[0],&e1,sizeof(DOUBLE));
+	extend(&s2.d[0],&e2,sizeof(DOUBLE));
+	sub_ext(&e1,&e2);
+	compact(&e1,&s1.d[0],sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/ack/float/sbf8.s
===================================================================
--- /trunk/minix/lib/ack/float/sbf8.s	(revision 9)
+++ /trunk/minix/lib/ack/float/sbf8.s	(revision 9)
@@ -0,0 +1,43 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .sbf8
+.sect .text
+.sbf8:
+push ebp
+mov ebp,esp
+sub	esp,24
+cmp 8(ebp),0
+jne I1_4
+cmp 12(ebp),0
+je I1_1
+I1_4:
+push 8
+lea eax,-12(ebp)
+push eax
+lea eax,16(ebp)
+push eax
+call .extend
+add esp,12
+push 8
+lea eax,-24(ebp)
+push eax
+lea eax,8(ebp)
+push eax
+call .extend
+add esp,12
+lea eax,-24(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .sub_ext
+pop ecx
+pop ecx
+push 8
+lea eax,16(ebp)
+push eax
+lea eax,-12(ebp)
+push eax
+call .compact
+add esp,12
+I1_1:
+leave
+ret
Index: /trunk/minix/lib/ack/float/sft_ext.fc
===================================================================
--- /trunk/minix/lib/ack/float/sft_ext.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/sft_ext.fc	(revision 9)
@@ -0,0 +1,39 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/sft_ext.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	SHIFT TWO EXTENDED NUMBERS INTO PROPER
+	ALIGNMENT FOR ADDITION (exponents are equal)
+	Numbers should not be zero on entry.
+*/
+
+#include "FP_types.h"
+
+void
+sft_ext(e1,e2)
+EXTEND	*e1,*e2;
+{
+	register	EXTEND	*s;
+	register	int	diff;
+
+	diff = e1->exp - e2->exp;
+
+	if (!diff)
+		return;	/* exponents are equal	*/
+
+	if (diff < 0)	{ /* e2 is larger	*/
+			/* shift e1		*/
+		diff = -diff;
+		s = e1;
+	}
+	else		/* e1 is larger		*/
+			/* shift e2		*/
+		s = e2;
+
+	s->exp += diff;
+	b64_sft(&(s->mantissa), diff);
+}
Index: /trunk/minix/lib/ack/float/sft_ext.s
===================================================================
--- /trunk/minix/lib/ack/float/sft_ext.s	(revision 9)
+++ /trunk/minix/lib/ack/float/sft_ext.s	(revision 9)
@@ -0,0 +1,42 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .sft_ext
+.sect .text
+.sft_ext:
+push ebp
+mov ebp,esp
+push esi
+push edi
+mov edx,8(ebp)
+! kill edx
+movsx eax,2(edx)
+mov edx,12(ebp)
+! kill edx
+movsx ebx,2(edx)
+sub ebx,eax
+neg ebx
+mov edi,ebx
+test edi,edi
+je I1_1
+test edi,edi
+jns I1_7
+neg edi
+mov esi,8(ebp)
+jmp I1_8
+I1_7:
+mov esi,12(ebp)
+I1_8:
+movsx eax,2(esi)
+add eax,edi
+movsx eax,eax
+o16 mov 2(esi),eax
+push edi
+lea eax,4(esi)
+push eax
+call .b64_sft
+pop ecx
+pop ecx
+I1_1:
+pop edi
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/shifter.fc
===================================================================
--- /trunk/minix/lib/ack/float/shifter.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/shifter.fc	(revision 9)
@@ -0,0 +1,75 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/shifter.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+# include "FP_types.h"
+
+void
+b64_sft(e1,n)
+B64	*e1;
+int	n;
+{
+	if (n > 0) {
+		if (n > 63) {
+			e1->l_32 = 0;
+			e1->h_32 = 0;
+			return;
+		}
+		if (n >= 32) {
+			e1->l_32 = e1->h_32;
+			e1->h_32 = 0;
+			n -= 32;
+		}
+		if (n > 0) {
+			e1->l_32 >>= n;
+			if (e1->h_32 != 0) {
+				e1->l_32 |= (e1->h_32 << (32 - n));
+				e1->h_32 >>= n;
+			}
+		}
+		return;
+	}
+	n = -n;
+	if (n > 0) {
+		if (n > 63) {
+			e1->l_32 = 0;
+			e1->h_32 = 0;
+			return;
+		}
+		if (n >= 32) {
+			e1->h_32 = e1->l_32;
+			e1->l_32 = 0;
+			n -= 32;
+		}
+		if (n > 0) {
+			e1->h_32 <<= n;
+			if (e1->l_32 != 0) {
+				e1->h_32 |= (e1->l_32 >> (32 - n));
+				e1->l_32 <<= n;
+			}
+		}
+	}
+}
+
+void
+b64_lsft(e1)
+B64	*e1;
+{
+	/*	shift left 1 bit */
+	e1->h_32 <<= 1;
+	if (e1->l_32 & 0x80000000L) e1->h_32 |= 1;
+	e1->l_32 <<= 1;
+}
+
+void
+b64_rsft(e1)
+B64	*e1;
+{
+	/*	shift right 1 bit */
+	e1->l_32 >>= 1;
+	if (e1->h_32 & 1) e1->l_32 |= 0x80000000L;
+	e1->h_32 >>= 1;
+}
Index: /trunk/minix/lib/ack/float/shifter.s
===================================================================
--- /trunk/minix/lib/ack/float/shifter.s	(revision 9)
+++ /trunk/minix/lib/ack/float/shifter.s	(revision 9)
@@ -0,0 +1,123 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .b64_sft
+.sect .text
+.b64_sft:
+push ebp
+mov ebp,esp
+push esi
+push edi
+mov esi,8(ebp)
+mov edi,12(ebp)
+! kill cc
+test edi,edi
+jle I1_4
+cmp edi,63
+jle I1_7
+mov 4(esi),0
+mov (esi),0
+jmp I1_1
+I1_7:
+cmp edi,32
+jl I1_10
+mov edx,(esi)
+mov 4(esi),edx
+mov (esi),0
+sub edi,32
+I1_10:
+! kill cc
+test edi,edi
+jle I1_1
+mov ecx,edi
+mov edx,4(esi)
+shr edx,cl
+mov 4(esi),edx
+cmp (esi),0
+je I1_1
+mov edx,32
+sub edx,edi
+mov ecx,edx
+mov edx,(esi)
+sal edx,cl
+or 4(esi),edx
+mov ecx,edi
+mov edx,(esi)
+shr edx,cl
+mov (esi),edx
+jmp I1_1
+I1_4:
+neg edi
+! kill cc
+test edi,edi
+jle I1_1
+cmp edi,63
+jle I1_22
+mov 4(esi),0
+mov (esi),0
+jmp I1_1
+I1_22:
+cmp edi,32
+jl I1_25
+mov edx,4(esi)
+mov (esi),edx
+mov 4(esi),0
+sub edi,32
+I1_25:
+! kill cc
+test edi,edi
+jle I1_1
+mov ecx,edi
+mov edx,(esi)
+sal edx,cl
+mov (esi),edx
+cmp 4(esi),0
+je I1_1
+mov edx,32
+sub edx,edi
+mov ecx,edx
+mov edx,4(esi)
+shr edx,cl
+or (esi),edx
+mov ecx,edi
+mov edx,4(esi)
+sal edx,cl
+mov 4(esi),edx
+I1_1:
+pop edi
+pop esi
+leave
+ret
+.extern .b64_lsft
+.b64_lsft:
+push ebp
+mov ebp,esp
+push esi
+mov esi,8(ebp)
+sal (esi),1
+test 4(esi),-2147483648
+je I2_4
+or (esi),1
+I2_4:
+mov edx,4(esi)
+sal edx,1
+mov 4(esi),edx
+pop esi
+leave
+ret
+.extern .b64_rsft
+.b64_rsft:
+push ebp
+mov ebp,esp
+push esi
+mov esi,8(ebp)
+mov edx,4(esi)
+shr edx,1
+mov 4(esi),edx
+mov edx,(esi)
+testb dl,1
+je I3_4
+or 4(esi),-2147483648
+I3_4:
+shr (esi),1
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/sub_ext.fc
===================================================================
--- /trunk/minix/lib/ack/float/sub_ext.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/sub_ext.fc	(revision 9)
@@ -0,0 +1,53 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/sub_ext.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	SUBTRACT 2 EXTENDED FORMAT NUMBERS
+*/
+
+#include "FP_types.h"
+
+void
+sub_ext(e1,e2)
+EXTEND	*e1,*e2;
+{
+	if ((e2->m1 | e2->m2) == 0L) {
+		return;
+	}
+	if ((e1->m1 | e1->m2) == 0L) {
+		*e1 = *e2;
+		e1->sign = e2->sign ? 0 : 1;
+		return;
+	}
+	sft_ext(e1, e2);
+	if (e1->sign != e2->sign) {
+		/* e1 - e2 = e1 + (-e2) */
+		if (b64_add(&e1->mantissa,&e2->mantissa)) { /* addition carry */
+                	b64_rsft(&e1->mantissa);      /* shift mantissa one bit RIGHT */
+                	e1->m1 |= 0x80000000L;  /* set max bit  */
+                	e1->exp++;              /* increase the exponent */
+        	}
+	}
+        else if (e2->m1 > e1->m1 ||
+                 (e2->m1 == e1->m1 && e2->m2 > e1->m2)) {
+		/*	abs(e2) > abs(e1) */
+		if (e1->m2 > e2->m2) {
+			e2->m1 -= 1;	/* carry in */
+		}
+		e2->m1 -= e1->m1;
+		e2->m2 -= e1->m2;
+		*e1 = *e2;
+		e1->sign = e2->sign ? 0 : 1;
+	}
+	else {
+		if (e2->m2 > e1->m2)
+			e1->m1 -= 1;	/* carry in */
+		e1->m1 -= e2->m1;
+		e1->m2 -= e2->m2;
+	}
+	nrm_ext(e1);
+}
Index: /trunk/minix/lib/ack/float/sub_ext.s
===================================================================
--- /trunk/minix/lib/ack/float/sub_ext.s	(revision 9)
+++ /trunk/minix/lib/ack/float/sub_ext.s	(revision 9)
@@ -0,0 +1,119 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .sub_ext
+.sect .text
+.sub_ext:
+push ebp
+mov ebp,esp
+push esi
+push edi
+mov esi,8(ebp)
+mov edi,12(ebp)
+mov edx,8(edi)
+or edx,4(edi)
+je I1_1
+mov edx,8(esi)
+or edx,4(esi)
+jne I1_7
+push edi
+push esi
+mov ecx,3
+call .blm
+movzx edx,(edi)
+test edx,edx
+je I1_10
+xor eax,eax
+jmp I1_11
+I1_10:
+mov eax,1
+I1_11:
+o16 mov (esi),eax
+jmp I1_1
+I1_7:
+push edi
+push esi
+call .sft_ext
+pop ecx
+pop ecx
+movsx eax,(esi)
+movsx ebx,(edi)
+cmp eax,ebx
+je I1_13
+lea eax,4(edi)
+push eax
+lea eax,4(esi)
+push eax
+call .b64_add
+pop ecx
+pop ecx
+test eax,eax
+je I1_14
+lea eax,4(esi)
+push eax
+call .b64_rsft
+pop ecx
+or 4(esi),-2147483648
+movsx eax,2(esi)
+inc eax
+movsx eax,eax
+o16 mov 2(esi),eax
+jmp I1_14
+I1_13:
+mov edx,4(esi)
+cmp 4(edi),edx
+ja I1_18
+cmp 4(edi),edx
+jne I1_19
+mov edx,8(esi)
+cmp 8(edi),edx
+jbe I1_19
+I1_18:
+mov edx,8(edi)
+cmp 8(esi),edx
+jbe I1_24
+mov edx,4(edi)
+sub edx,1
+mov 4(edi),edx
+I1_24:
+mov edx,4(edi)
+sub edx,4(esi)
+mov 4(edi),edx
+mov edx,8(edi)
+sub edx,8(esi)
+mov 8(edi),edx
+push edi
+push esi
+mov ecx,3
+call .blm
+movzx edx,(edi)
+test edx,edx
+je I1_27
+xor eax,eax
+jmp I1_28
+I1_27:
+mov eax,1
+I1_28:
+o16 mov (esi),eax
+jmp I1_14
+I1_19:
+mov edx,8(esi)
+cmp 8(edi),edx
+jbe I1_30
+mov edx,4(esi)
+sub edx,1
+mov 4(esi),edx
+I1_30:
+mov edx,4(esi)
+sub edx,4(edi)
+mov 4(esi),edx
+mov edx,8(esi)
+sub edx,8(edi)
+mov 8(esi),edx
+I1_14:
+push esi
+call .nrm_ext
+pop ecx
+I1_1:
+pop edi
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/float/zrf4.fc
===================================================================
--- /trunk/minix/lib/ack/float/zrf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/zrf4.fc	(revision 9)
@@ -0,0 +1,19 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/zrf4.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	return a zero float (ZRF 4)
+*/
+
+#include "FP_types.h"
+
+void
+zrf4(l)
+SINGLE	*l;
+{
+	*l = 0L;
+}
Index: /trunk/minix/lib/ack/float/zrf4.s
===================================================================
--- /trunk/minix/lib/ack/float/zrf4.s	(revision 9)
+++ /trunk/minix/lib/ack/float/zrf4.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .zrf4
+.sect .text
+.zrf4:
+push ebp
+mov ebp,esp
+mov eax,8(ebp)
+mov (eax),0
+! kill eax
+leave
+ret
Index: /trunk/minix/lib/ack/float/zrf8.fc
===================================================================
--- /trunk/minix/lib/ack/float/zrf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/zrf8.fc	(revision 9)
@@ -0,0 +1,21 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/zrf8.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	return a zero double (ZRF 8)
+*/
+
+#include "FP_types.h"
+
+void
+zrf8(z)
+DOUBLE	*z;
+{
+
+	z->d[0] = 0L;
+	z->d[1] = 0L;
+}
Index: /trunk/minix/lib/ack/float/zrf8.s
===================================================================
--- /trunk/minix/lib/ack/float/zrf8.s	(revision 9)
+++ /trunk/minix/lib/ack/float/zrf8.s	(revision 9)
@@ -0,0 +1,13 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .zrf8
+.sect .text
+.zrf8:
+push ebp
+mov ebp,esp
+mov eax,8(ebp)
+mov (eax),0
+! kill eax
+mov edx,8(ebp)
+mov 4(edx),0
+leave
+ret
Index: /trunk/minix/lib/ack/float/zrf_ext.fc
===================================================================
--- /trunk/minix/lib/ack/float/zrf_ext.fc	(revision 9)
+++ /trunk/minix/lib/ack/float/zrf_ext.fc	(revision 9)
@@ -0,0 +1,22 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/float/zrf_ext.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	ZERO and return EXTEND FORMAT FLOAT
+*/
+
+#include "FP_types.h"
+
+void
+zrf_ext(e)
+EXTEND	*e;
+{
+	e->m1 = 0;
+	e->m2 = 0;
+	e->exp = 0;
+	e->sign = 0;
+}
Index: /trunk/minix/lib/ack/float/zrf_ext.s
===================================================================
--- /trunk/minix/lib/ack/float/zrf_ext.s	(revision 9)
+++ /trunk/minix/lib/ack/float/zrf_ext.s	(revision 9)
@@ -0,0 +1,15 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern .zrf_ext
+.sect .text
+.zrf_ext:
+push ebp
+mov ebp,esp
+push esi
+mov esi,8(ebp)
+mov 4(esi),0
+mov 8(esi),0
+o16 mov 2(esi),0
+o16 mov (esi),0
+pop esi
+leave
+ret
Index: /trunk/minix/lib/ack/fphook/FP.compile
===================================================================
--- /trunk/minix/lib/ack/fphook/FP.compile	(revision 9)
+++ /trunk/minix/lib/ack/fphook/FP.compile	(revision 9)
@@ -0,0 +1,19 @@
+#!/bin/sh
+#							Author: Kees J. Bot
+# Compile one soft FP source file.
+# (These files shouldn't be optimized normally, but the 16-bit C compiler
+# only optimizes scratch register allocation a bit with -O.  To the 32-bit
+# compiler -O is a no-op.)
+
+case $#:$1 in
+1:*.fc)	;;
+*)	echo "$0: $1: not a FC file" >&2; exit 1
+esac
+
+base="`basename "$1" .fc`"
+trap 'rm -f tmp.c tmp.s"; exit 1' 2
+
+cp "$1" tmp.c &&
+cc -O -I. -D_MINIX -D_POSIX_SOURCE -S tmp.c &&
+sed -f FP.script tmp.s > "$base.s" &&
+rm tmp.c tmp.s
Index: /trunk/minix/lib/ack/fphook/FP.script
===================================================================
--- /trunk/minix/lib/ack/fphook/FP.script	(revision 9)
+++ /trunk/minix/lib/ack/fphook/FP.script	(revision 9)
@@ -0,0 +1,39 @@
+s/_adf4/.adf4/
+s/_adf8/.adf8/
+s/_cff4/.cff4/
+s/_cff8/.cff8/
+s/_cfi/.cfi/
+s/_cfu/.cfu/
+s/_cif4/.cif4/
+s/_cif8/.cif8/
+s/_cmf4/.cmf4/
+s/_cmf8/.cmf8/
+s/_cuf4/.cuf4/
+s/_cuf8/.cuf8/
+s/_dvf4/.dvf4/
+s/_dvf8/.dvf8/
+s/_fef4/.fef4/
+s/_fef8/.fef8/
+s/_fif4/.fif4/
+s/_fif8/.fif8/
+s/_mlf4/.mlf4/
+s/_mlf8/.mlf8/
+s/_ngf4/.ngf4/
+s/_ngf8/.ngf8/
+s/_sbf4/.sbf4/
+s/_sbf8/.sbf8/
+s/_zrf4/.zrf4/
+s/_zrf8/.zrf8/
+s/_add_ext/.add_ext/
+s/_div_ext/.div_ext/
+s/_mul_ext/.mul_ext/
+s/_nrm_ext/.nrm_ext/
+s/_sft_ext/.sft_ext/
+s/_sub_ext/.sub_ext/
+s/_zrf_ext/.zrf_ext/
+s/_compact/.compact/
+s/_extend/.extend/
+s/_b64_add/.b64_add/
+s/_b64_sft/.b64_sft/
+s/_b64_rsft/.b64_rsft/
+s/_b64_lsft/.b64_lsft/
Index: /trunk/minix/lib/ack/fphook/FP_bias.h
===================================================================
--- /trunk/minix/lib/ack/fphook/FP_bias.h	(revision 9)
+++ /trunk/minix/lib/ack/fphook/FP_bias.h	(revision 9)
@@ -0,0 +1,28 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/FP_bias.h,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	include file for floating point package
+*/
+
+		/*	FLOAT FORMAT EXPONENT BIAS	*/
+
+#define	SGL_BIAS	 127	/* excess  128 notation used	*/
+#define	DBL_BIAS	1023	/* excess 1024 notation used	*/
+#define	EXT_BIAS	   0	/* 2s-complement notation used	*/
+				/* this is possible because the	*/
+				/* sign is in a seperate word	*/
+		
+		/*	VARIOUS MAX AND MIN VALUES	*/
+		/*	1) FOR THE DIFFERENT FORMATS	*/
+
+#define	SGL_MAX		   254	/*	standard definition	*/
+#define	SGL_MIN		     1	/*	standard definition	*/
+#define	DBL_MAX		  2046	/*	standard definition	*/
+#define	DBL_MIN		     1	/*	standard definition	*/
+#define EXT_MAX		 16383	/*	standard minimum	*/
+#define EXT_MIN		-16382	/*	standard minimum	*/
Index: /trunk/minix/lib/ack/fphook/FP_shift.h
===================================================================
--- /trunk/minix/lib/ack/fphook/FP_shift.h	(revision 9)
+++ /trunk/minix/lib/ack/fphook/FP_shift.h	(revision 9)
@@ -0,0 +1,49 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/FP_shift.h,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	include file for floating point package
+*/
+
+# define	CARRYBIT	0x80000000L
+# define	NORMBIT		0x80000000L
+# define	EXP_STORE	16
+
+
+				/* parameters for Single Precision */
+#define SGL_EXPSHIFT	7
+#define SGL_M1LEFT	8
+#define SGL_ZERO	0xffffff80L
+#define SGL_EXACT	0xff
+#define SGL_RUNPACK	SGL_M1LEFT
+
+#define SGL_ROUNDUP	0x80
+#define	SGL_CARRYOUT	0x01000000L
+#define	SGL_MASK	0x007fffffL
+
+				/* parameters for Double Precision */
+				/* used in extend.c */
+
+#define DBL_EXPSHIFT	4
+
+#define DBL_M1LEFT	11
+
+#define	DBL_RPACK	(32-DBL_M1LEFT)
+#define	DBL_LPACK	DBL_M1LEFT
+
+				/* used in compact.c */
+
+#define DBL_ZERO	0xfffffd00L
+
+#define DBL_EXACT	0x7ff
+
+#define DBL_RUNPACK	DBL_M1LEFT
+#define DBL_LUNPACK	(32-DBL_RUNPACK)
+
+#define DBL_ROUNDUP	0x400
+#define	DBL_CARRYOUT	0x00200000L
+#define	DBL_MASK	0x000fffffL
Index: /trunk/minix/lib/ack/fphook/FP_trap.h
===================================================================
--- /trunk/minix/lib/ack/fphook/FP_trap.h	(revision 9)
+++ /trunk/minix/lib/ack/fphook/FP_trap.h	(revision 9)
@@ -0,0 +1,22 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/FP_trap.h,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	include file for floating point package
+*/
+
+			/*	EM TRAPS	*/
+
+#define	EIOVFL	3	/* Integer  Overflow		*/
+#define	EFOVFL	4	/* Floating Overflow		*/
+#define	EFUNFL	5	/* Floating Underflow		*/
+#define	EIDIVZ	6	/* Integer  Divide by 0		*/
+#define	EFDIVZ	7	/* Floating Divide by 0.0	*/
+#define	EIUND	8	/* Integer  Undefined Number	*/
+#define	EFUND	9	/* Floating Undefined Number	*/
+#define	ECONV	10	/* Conversion Error		*/
+# define trap(x) _fptrp(x)
Index: /trunk/minix/lib/ack/fphook/FP_types.h
===================================================================
--- /trunk/minix/lib/ack/fphook/FP_types.h	(revision 9)
+++ /trunk/minix/lib/ack/fphook/FP_types.h	(revision 9)
@@ -0,0 +1,113 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/FP_types.h,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/********************************************************/
+/*
+	Type definitions for C Floating Point Package
+	include file for floating point package
+*/
+/********************************************************/
+/*
+	THESE STRUCTURES ARE USED TO ADDRESS THE INDIVIDUAL
+	PARTS OF THE FLOATING POINT NUMBER REPRESENTATIONS.
+
+	THREE STRUCTURES ARE DEFINED:
+		SINGLE:	single precision floating format
+		DOUBLE:	double precision floating format
+		EXTEND:	double precision extended format
+*/
+/********************************************************/
+
+#ifndef __FPTYPES
+#define __FPTYPES
+
+typedef	struct	{
+	unsigned long	h_32;	/* higher 32 bits of 64 */
+	unsigned long	l_32;	/* lower  32 bits of 64 */
+}	B64;
+
+typedef	unsigned long	SINGLE;
+
+typedef	struct	{
+	unsigned long	d[2];
+}	DOUBLE;
+
+typedef	struct	{	/* expanded float format	*/
+	short	sign;
+	short	exp;
+	B64	mantissa;
+#define m1 mantissa.h_32
+#define m2 mantissa.l_32
+} EXTEND;
+
+struct	fef4_returns {
+	int	e;
+	SINGLE	f;
+};
+
+struct	fef8_returns {
+	int	e;
+	DOUBLE	f;
+};
+
+struct fif4_returns {
+	SINGLE ipart;
+	SINGLE fpart;
+};
+
+struct fif8_returns {
+	DOUBLE ipart;
+	DOUBLE fpart;
+};
+
+#if __STDC__
+#define _PROTOTYPE(function, params)	function params
+#else
+#define _PROTOTYPE(function, params)	function()
+#endif
+_PROTOTYPE( void add_ext, (EXTEND *e1, EXTEND *e2));
+_PROTOTYPE( void mul_ext, (EXTEND *e1, EXTEND *e2));
+_PROTOTYPE( void div_ext, (EXTEND *e1, EXTEND *e2));
+_PROTOTYPE( void sub_ext, (EXTEND *e1, EXTEND *e2));
+_PROTOTYPE( void sft_ext, (EXTEND *e1, EXTEND *e2));
+_PROTOTYPE( void nrm_ext, (EXTEND *e1));
+_PROTOTYPE( void zrf_ext, (EXTEND *e1));
+_PROTOTYPE( void extend, (unsigned long *from, EXTEND *to, int size));
+_PROTOTYPE( void compact, (EXTEND *from, unsigned long *to, int size));
+_PROTOTYPE( void _fptrp, (int));
+_PROTOTYPE( void adf4, (SINGLE s2, SINGLE s1));
+_PROTOTYPE( void adf8, (DOUBLE s2, DOUBLE s1));
+_PROTOTYPE( void sbf4, (SINGLE s2, SINGLE s1));
+_PROTOTYPE( void sbf8, (DOUBLE s2, DOUBLE s1));
+_PROTOTYPE( void dvf4, (SINGLE s2, SINGLE s1));
+_PROTOTYPE( void dvf8, (DOUBLE s2, DOUBLE s1));
+_PROTOTYPE( void mlf4, (SINGLE s2, SINGLE s1));
+_PROTOTYPE( void mlf8, (DOUBLE s2, DOUBLE s1));
+_PROTOTYPE( void ngf4, (SINGLE f));
+_PROTOTYPE( void ngf8, (DOUBLE f));
+_PROTOTYPE( void zrf4, (SINGLE *l));
+_PROTOTYPE( void zrf8, (DOUBLE *z));
+_PROTOTYPE( void cff4, (DOUBLE src));
+_PROTOTYPE( void cff8, (SINGLE src));
+_PROTOTYPE( void cif4, (int ss, long src));
+_PROTOTYPE( void cif8, (int ss, long src));
+_PROTOTYPE( void cuf4, (int ss, long src));
+_PROTOTYPE( void cuf8, (int ss, long src));
+_PROTOTYPE( long cfu, (int ds, int ss, DOUBLE src));
+_PROTOTYPE( long cfi, (int ds, int ss, DOUBLE src));
+_PROTOTYPE( int cmf4, (SINGLE s2, SINGLE s1));
+_PROTOTYPE( int cmf8, (DOUBLE d1, DOUBLE d2));
+_PROTOTYPE( void fef4, (struct fef4_returns *r, SINGLE s1));
+_PROTOTYPE( void fef8, (struct fef8_returns *r, DOUBLE s1));
+_PROTOTYPE( void fif4, (struct fif4_returns *p, SINGLE x, SINGLE y));
+_PROTOTYPE( void fif8, (struct fif8_returns *p, DOUBLE x, DOUBLE y));
+
+_PROTOTYPE( void b64_sft, (B64 *, int));
+_PROTOTYPE( void b64_lsft, (B64 *));
+_PROTOTYPE( void b64_rsft, (B64 *));
+_PROTOTYPE( int b64_add, (B64 *, B64 *));
+#endif
Index: /trunk/minix/lib/ack/fphook/Makedepend-ack
===================================================================
--- /trunk/minix/lib/ack/fphook/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/ack/fphook/Makedepend-ack	(revision 9)
@@ -0,0 +1,6 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I.. -E' fphook.c | sed -e 's:^\(.\):../../obj-ack//./ack/fphook/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I.. -E' fltpr.c | sed -e 's:^\(.\):../../obj-ack//./ack/fphook/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I.. -E' strtod.c | sed -e 's:^\(.\):../../obj-ack//./ack/fphook/\1:' >> .depend-ack
Index: /trunk/minix/lib/ack/fphook/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/ack/fphook/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/ack/fphook/Makedepend-gnu	(revision 9)
@@ -0,0 +1,3 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
Index: /trunk/minix/lib/ack/fphook/Makefile
===================================================================
--- /trunk/minix/lib/ack/fphook/Makefile	(revision 9)
+++ /trunk/minix/lib/ack/fphook/Makefile	(revision 9)
@@ -0,0 +1,54 @@
+#Generated from ./ack/fphook/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../generate.sh ./ack/fphook ../../obj-ack/ ../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../generate.sh ./ack/fphook ../../obj-ack/ ../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../../obj-ack//libd.a
+
+../../obj-ack//libd.a: ../../obj-ack//libd.a(fphook.o)
+
+../../obj-ack//libd.a:
+	ar cr ../../obj-ack//libd.a ../../obj-ack//./ack/fphook/*.o
+	rm ../../obj-ack//./ack/fphook/*.o
+
+../../obj-ack//libd.a(fphook.o): fphook.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I.. -c -o ../../obj-ack//./ack/fphook/fphook.o fphook.c
+
+all-ack: ../../obj-ack//libc.a
+
+../../obj-ack//libc.a: ../../obj-ack//libc.a(fltpr.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(strtod.o)
+
+../../obj-ack//libc.a:
+	ar cr ../../obj-ack//libc.a ../../obj-ack//./ack/fphook/*.o
+	rm ../../obj-ack//./ack/fphook/*.o
+
+../../obj-ack//libc.a(fltpr.o): fltpr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I.. -c -o ../../obj-ack//./ack/fphook/fltpr.o fltpr.c
+../../obj-ack//libc.a(strtod.o): strtod.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I.. -c -o ../../obj-ack//./ack/fphook/strtod.o strtod.c
+
+
+
+clean::
+	rm -f ../../obj-ack//./ack/fphook/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/ack/fphook/Makefile.in
===================================================================
--- /trunk/minix/lib/ack/fphook/Makefile.in	(revision 9)
+++ /trunk/minix/lib/ack/fphook/Makefile.in	(revision 9)
@@ -0,0 +1,19 @@
+# Makefile for lib/ack/fphook.
+
+# The ACK ANSI C compiler has an nice trick to reduce the size of programs
+# that do not use floating point.  If a program uses floating point then the
+# compiler generates an external reference to the label '_fp_hook'.  This makes
+# the loader bring in the floating point printing and conversion routines
+# '_f_print' and 'strtod' from the library libd.a.  Otherwise two dummy
+# routines are found in libc.a.  (The printf and scanf need floating point
+# for the %f formats, whether you use them or not.)
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE -I.."
+
+LIBRARIES="libd libc"
+
+libd_FILES=fphook.c
+
+libc_FILES="fltpr.c strtod.c"
+
+TYPE=ack
Index: /trunk/minix/lib/ack/fphook/add_ext.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/add_ext.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/add_ext.fc	(revision 9)
@@ -0,0 +1,56 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/add_ext.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	ADD TWO EXTENDED FORMAT NUMBERS
+*/
+
+#include "FP_types.h"
+
+void
+add_ext(e1,e2)
+register EXTEND	*e1,*e2;
+{
+	if ((e2->m1 | e2->m2) == 0L) {
+		return;
+	}
+	if ((e1->m1 | e1->m2) == 0L) {
+		*e1 = *e2;
+		return;
+	}
+	sft_ext(e1, e2);	/* adjust mantissas to equal powers */
+	if (e1->sign != e2->sign) {
+		/* e1 + e2 = e1 - (-e2) */
+		if (e2->m1 > e1->m1 ||
+                    (e2->m1 == e1->m1 && e2->m2 > e1->m2)) {
+                	/*      abs(e2) > abs(e1) */
+			EXTEND x;
+
+			x = *e1;
+			*e1 = *e2;
+                	if (x.m2 > e1->m2) {
+                        	e1->m1 -= 1;    /* carry in */
+                	}
+                	e1->m1 -= x.m1;
+                	e1->m2 -= x.m2;
+        	}
+        	else {
+                	if (e2->m2 > e1->m2)
+                        	e1->m1 -= 1;    /* carry in */
+                	e1->m1 -= e2->m1;
+                	e1->m2 -= e2->m2;
+        	}
+	}
+	else {
+		if (b64_add(&e1->mantissa,&e2->mantissa)) {	/* addition carry */
+			b64_rsft(&e1->mantissa);	/* shift mantissa one bit RIGHT */
+			e1->m1 |= 0x80000000L;	/* set max bit	*/
+			e1->exp++;		/* increase the exponent */
+		}
+	}
+	nrm_ext(e1);
+}
Index: /trunk/minix/lib/ack/fphook/adder.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/adder.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/adder.fc	(revision 9)
@@ -0,0 +1,50 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/adder.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+ *	these are the routines the routines to do 32 and  64-bit addition
+ */
+
+# ifdef	EXT_DEBUG
+# include <stdio.h>
+# endif
+
+# include "FP_types.h"
+# define	UNKNOWN -1
+# define	TRUE	 1
+# define	FALSE	 0
+# define	MAXBIT	0x80000000L
+
+	/*
+	 *	add 64 bits
+	 */
+int
+b64_add(e1,e2)
+		/*
+		 * pointers to 64 bit 'registers'
+		 */
+register	B64	*e1,*e2;
+{
+		register	int	overflow;
+				int	carry;
+
+			/* add higher pair of 32 bits */
+	overflow = ((unsigned long) 0xFFFFFFFF - e1->h_32 < e2->h_32);
+	e1->h_32 += e2->h_32;
+
+			/* add lower pair of 32 bits */
+	carry = ((unsigned long) 0xFFFFFFFF - e1->l_32 < e2->l_32);
+	e1->l_32 += e2->l_32;
+# ifdef	EXT_DEBUG
+	printf("\t\t\t\t\tb64_add: overflow (%d); internal carry(%d)\n",
+					overflow,carry);
+	fflush(stdout);
+# endif
+	if ((carry) && (++e1->h_32 == 0))
+		return(TRUE);		/* had a 64 bit overflow */
+	return(overflow);		/* return status from higher add */
+}
Index: /trunk/minix/lib/ack/fphook/adder.h
===================================================================
--- /trunk/minix/lib/ack/fphook/adder.h	(revision 9)
+++ /trunk/minix/lib/ack/fphook/adder.h	(revision 9)
@@ -0,0 +1,15 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/adder.h,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+ *	include file for 32 & 64 bit addition
+ */
+
+typedef	struct	B64 {
+	unsigned long	h_32;	/* higher 32 bits of 64 */
+	unsigned long	l_32;	/* lower  32 bits of 64 */
+}	B64;
Index: /trunk/minix/lib/ack/fphook/adf4.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/adf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/adf4.fc	(revision 9)
@@ -0,0 +1,32 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/adf4.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	ADD TWO FLOATS - SINGLE (ADF 4)
+*/
+
+#include	"FP_types.h"
+
+void
+adf4(s2,s1)
+SINGLE	s1,s2;
+{
+	EXTEND	e1,e2;
+	int	swap = 0;
+
+	if (s1 == (SINGLE) 0) {
+		s1 = s2;
+		return;
+	}
+	if (s2 == (SINGLE) 0) {
+		return;
+	}
+	extend(&s1,&e1,sizeof(SINGLE));
+	extend(&s2,&e2,sizeof(SINGLE));
+	add_ext(&e1,&e2);
+	compact(&e1,&s1,sizeof(SINGLE));
+}
Index: /trunk/minix/lib/ack/fphook/adf8.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/adf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/adf8.fc	(revision 9)
@@ -0,0 +1,32 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/adf8.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	ADD TWO FLOATS - DOUBLE (ADF 8)
+*/
+
+#include	"FP_types.h"
+
+void
+adf8(s2,s1)
+DOUBLE	s1,s2;
+{
+	EXTEND	e1,e2;
+
+	if (s1.d[0] == 0 && s1.d[1] == 0) {
+		s1 = s2;
+		return;
+	}
+	if (s2.d[0] == 0 && s2.d[1] == 0) {
+		return;
+	}
+
+	extend(&s1.d[0],&e1,sizeof(DOUBLE));
+	extend(&s2.d[0],&e2,sizeof(DOUBLE));
+	add_ext(&e1,&e2);
+	compact(&e1,&s1.d[0],sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/ack/fphook/byte_order.h
===================================================================
--- /trunk/minix/lib/ack/fphook/byte_order.h	(revision 9)
+++ /trunk/minix/lib/ack/fphook/byte_order.h	(revision 9)
@@ -0,0 +1,6 @@
+#define CHAR_UNSIGNED	0
+#define MSB_AT_LOW_ADDRESS	0
+#define MSW_AT_LOW_ADDRESS	0
+#define FL_MSB_AT_LOW_ADDRESS	0
+#define FL_MSW_AT_LOW_ADDRESS	0
+#define FL_MSL_AT_LOW_ADDRESS	0
Index: /trunk/minix/lib/ack/fphook/cff4.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/cff4.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/cff4.fc	(revision 9)
@@ -0,0 +1,28 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/cff4.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+		CONVERT DOUBLE TO SINGLE (CFF 8 4)
+
+	This routine works quite simply. A floating point
+	of size 08 is converted to extended format.
+	This extended variable is converted back to
+	a floating point of size 04.
+
+*/
+
+#include	"FP_types.h"
+
+void
+cff4(src)
+DOUBLE	src;	/* the source itself -	THIS TIME it's DOUBLE */
+{
+	EXTEND	buf;
+
+	extend(&src.d[0],&buf,sizeof(DOUBLE));	/* no matter what */
+	compact(&buf,&(src.d[1]),sizeof(SINGLE));
+}
Index: /trunk/minix/lib/ack/fphook/cff8.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/cff8.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/cff8.fc	(revision 9)
@@ -0,0 +1,28 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/cff8.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+		CONVERT SINGLE TO DOUBLE (CFF 4 8)
+
+	This routine works quite simply. A floating point
+	of size 04 is converted to extended format.
+	This extended variable is converted back to
+	a floating point of size 08.
+
+*/
+
+#include "FP_types.h"
+
+void
+cff8(src)
+SINGLE	src;
+{
+	EXTEND	buf;
+
+	extend(&src,&buf,sizeof(SINGLE));	/* no matter what */
+	compact(&buf, &src,sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/ack/fphook/cfi.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/cfi.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/cfi.fc	(revision 9)
@@ -0,0 +1,52 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/cfi.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+		CONVERT FLOAT TO SIGNED (CFI m n)
+
+		N.B. The caller must know what it is getting.
+		     A LONG is always returned. If it is an
+		     integer the high byte is cleared first.
+*/
+
+#include "FP_trap.h"
+#include "FP_types.h"
+#include "FP_shift.h"
+
+long
+cfi(ds,ss,src)
+int	ds;	/* destination size (2 or 4) */
+int	ss;	/* source size	    (4 or 8) */
+DOUBLE	src;	/* assume worst case */
+{
+	EXTEND	buf;
+	long	new;
+	short	max_exp;
+
+	extend(&src.d[0],&buf,ss);	/* get extended format */
+	if (buf.exp < 0) {	/* no conversion needed */
+		src.d[ss == 8] = 0L;
+		return(0L);
+	}
+	max_exp = (ds << 3) - 2;	/* signed numbers */
+				/* have more limited max_exp */
+	if (buf.exp > max_exp) {
+		if (buf.exp == max_exp+1 && buf.sign && buf.m1 == NORMBIT &&
+		    buf.m2 == 0L) {
+		}
+		else {
+			trap(EIOVFL);	/* integer overflow	*/
+			buf.exp %= max_exp; /* truncate	*/
+		}
+	}
+	new = buf.m1 >> (31-buf.exp);
+	if (buf.sign)
+		new = -new;
+done:
+	src.d[ss == 8] = new;
+	return(new);
+}
Index: /trunk/minix/lib/ack/fphook/cfu.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/cfu.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/cfu.fc	(revision 9)
@@ -0,0 +1,43 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/cfu.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+		CONVERT FLOAT TO UNSIGNED (CFU m n)
+
+		N.B. The caller must know what it is getting.
+		     A LONG is always returned. If it is an
+		     integer the high byte is cleared first.
+*/
+
+#include "FP_trap.h"
+#include "FP_types.h"
+
+long
+cfu(ds,ss,src)
+int	ds;	/* destination size (2 or 4) */
+int	ss;	/* source size	    (4 or 8) */
+DOUBLE	src;	/* assume worst case */
+{
+	EXTEND	buf;
+	long	new;
+	short	newint, max_exp;
+
+	extend(&src.d[0],&buf,ss);	/* get extended format	*/
+	if (buf.exp < 0) {	/* no conversion needed	*/
+		src.d[ss == 8] = 0L;
+		return(0L);
+	}
+	max_exp = (ds << 3) - 1;
+	if (buf.exp > max_exp) {
+		trap(EIOVFL);	/* integer overflow	*/
+		buf.exp %= max_exp;
+	}
+	new = buf.m1 >> (31-buf.exp);
+done:
+	src.d[ss == 8] = new;
+	return(new);
+}
Index: /trunk/minix/lib/ack/fphook/cif4.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/cif4.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/cif4.fc	(revision 9)
@@ -0,0 +1,56 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/cif4.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	CONVERT INTEGER TO SINGLE (CIF n 4)
+
+	THIS ROUTINE WORKS BY FILLING AN EXTENDED
+	WITH THE INTEGER VALUE IN EXTENDED FORMAT
+	AND USES COMPACT() TO PUT IT INTO THE PROPER
+	FLOATING POINT PRECISION.
+*/
+
+#include "FP_types.h"
+
+void
+cif4(ss,src)
+int	ss;	/* source size */
+long	src;	/* largest possible integer to convert */
+{
+	EXTEND	buf;
+	short	*ipt;
+	long	i_src;
+	SINGLE	*result;
+
+	zrf_ext(&buf);
+	if (ss == sizeof(long))	{
+		buf.exp = 31;
+		i_src = src;
+		result = (SINGLE *) &src;
+	}
+	else	{
+		ipt = (short *) &src;
+		i_src = (long) *ipt;
+		buf.exp = 15;
+		result = (SINGLE *) &ss;
+	}
+	if (i_src == 0)	{
+		*result = (SINGLE) 0L;
+		return;
+	}
+			/* ESTABLISHED THAT src != 0	*/
+			/* adjust exponent field	*/
+	buf.sign = (i_src < 0) ? 0x8000 : 0;
+			/* clear sign bit of integer	*/
+			/* move to mantissa field	*/
+	buf.m1 = (i_src < 0) ? -i_src : i_src;
+			/* adjust mantissa field	*/
+	if (ss != sizeof(long))
+		buf.m1 <<= 16;
+	nrm_ext(&buf);		/* adjust mantissa field	*/
+	compact(&buf, result,sizeof(SINGLE));	/* put on stack */
+}
Index: /trunk/minix/lib/ack/fphook/cif8.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/cif8.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/cif8.fc	(revision 9)
@@ -0,0 +1,55 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/cif8.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	CONVERT INTEGER TO FLOAT (CIF n 8)
+
+	THIS ROUTINE WORKS BY FILLING AN EXTENDED
+	WITH THE INTEGER VALUE IN EXTENDED FORMAT
+	AND USES COMPACT() TO PUT IT INTO THE PROPER
+	FLOATING POINT PRECISION.
+*/
+
+#include "FP_types.h"
+
+void
+cif8(ss,src)
+int	ss;	/* source size */
+long	src;	/* largest possible integer to convert */
+{
+	EXTEND	buf;
+	DOUBLE	*result;	/* for return value */
+	short	*ipt;
+	long	i_src;
+
+	result = (DOUBLE *) ((void *) &ss);	/* always */
+	zrf_ext(&buf);
+	if (ss == sizeof(long))	{
+		buf.exp = 31;
+		i_src = src;
+	}
+	else	{
+		ipt = (short *) &src;
+		i_src = (long) *ipt;
+		buf.exp = 15;
+	}
+	if (i_src == 0)	{
+		zrf8(result);
+		return;
+	}
+			/* ESTABLISHED THAT src != 0	*/
+			/* adjust exponent field	*/
+	buf.sign = (i_src < 0) ? 0x8000 : 0;
+			/* clear sign bit of integer	*/
+			/* move to mantissa field	*/
+	buf.m1 = (i_src < 0) ? -i_src : i_src;
+			/* adjust mantissa field	*/
+	if (ss != sizeof(long))
+		buf.m1 <<= 16;
+	nrm_ext(&buf);
+	compact(&buf,&result->d[0],8);
+}
Index: /trunk/minix/lib/ack/fphook/cmf4.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/cmf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/cmf4.fc	(revision 9)
@@ -0,0 +1,40 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/cmf4.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	COMPARE	SINGLES (CMF 4)
+*/
+
+#include	"FP_types.h"
+#include	"get_put.h"
+
+int
+cmf4(f1,f2)
+SINGLE	f1,f2;
+{
+		/*
+		 * return ((f1 < f2) ? 1 : (f1 - f2))
+		 */
+#define SIGN(x) (((x) < 0) ? -1 : 1)
+        int	sign1,sign2;
+	long	l1,l2;
+
+	l1 = get4((char *) &f1);
+	l2 = get4((char *) &f2);
+
+	if (l1 == l2) return 0;
+
+        sign1 = SIGN(l1);
+        sign2 = SIGN(l2);
+        if (sign1 != sign2) {
+		if ((l1 & 0x7fffffff) == 0 &&
+		    (l2 & 0x7fffffff) == 0) return 0;
+                return ((sign1 > 0) ? -1 : 1);
+	}
+
+	return (sign1 * ((l1 < l2) ? 1 : -1));
+}
Index: /trunk/minix/lib/ack/fphook/cmf8.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/cmf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/cmf8.fc	(revision 9)
@@ -0,0 +1,61 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/cmf8.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	COMPARE	DOUBLES (CMF 8)
+*/
+
+#include	"FP_types.h"
+#include	"get_put.h"
+
+int
+cmf8(d1,d2)
+DOUBLE	d1,d2;
+{
+#define	SIGN(x)	(((x) < 0) ? -1 : 1)
+		/*
+		 * return ((d1 < d2) ? 1 : (d1 > d2) ? -1 : 0))
+		 */
+	long	l1,l2;
+	int	sign1,sign2;
+	int	rv;
+
+#if FL_MSL_AT_LOW_ADDRESS
+	l1 = get4((char *)&d1);
+	l2 = get4((char *)&d2);
+#else
+	l1 = get4(((char *)&d1+4));
+	l2 = get4(((char *)&d2+4));
+#endif
+	sign1 = SIGN(l1);
+	sign2 = SIGN(l2);
+	if (sign1 != sign2) {
+		l1 &= 0x7fffffff;
+		l2 &= 0x7fffffff;
+		if (l1 != 0 || l2 != 0) {
+			return ((sign1 > 0) ? -1 : 1);
+		}
+	}
+	if (l1 != l2)	{	/* we can decide here */
+		rv = l1 < l2 ? 1 : -1;
+	}
+	else	{ 		/* decide in 2nd half */
+		unsigned long u1, u2;
+#if FL_MSL_AT_LOW_ADDRESS
+		u1 = get4(((char *)&d1 + 4));
+		u2 = get4(((char *)&d2 + 4));
+#else
+		u1 = get4((char *)&d1);
+		u2 = get4((char *)&d2);
+#endif
+		if (u1 == u2)
+			return(0);
+		if (u1 < u2) rv = 1;
+		else rv = -1;
+	}
+	return sign1 * rv;
+}
Index: /trunk/minix/lib/ack/fphook/compact.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/compact.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/compact.fc	(revision 9)
@@ -0,0 +1,202 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/compact.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	COMPACT EXTEND FORMAT INTO FLOAT OF PROPER SIZE
+*/
+
+# include "FP_bias.h"
+# include "FP_shift.h"
+# include "FP_trap.h"
+# include "FP_types.h"
+# include "get_put.h"
+
+void
+compact(f,to,size)
+EXTEND	*f;
+unsigned long	*to;
+int	size;
+{
+	int	error = 0;
+
+	if (size == sizeof(DOUBLE)) {
+	/*
+	 * COMPACT EXTENDED INTO DOUBLE
+	 */
+		DOUBLE *DBL = (DOUBLE *) (void *) to;
+
+		if ((f->m1|(f->m2 & DBL_ZERO)) == 0L)	{
+			zrf8(DBL);
+			return;
+		}
+		f->exp += DBL_BIAS;	/* restore proper bias	*/
+		if (f->exp > DBL_MAX)	{
+dbl_over:			trap(EFOVFL);
+			f->exp = DBL_MAX+1;
+			f->m1 = 0;
+			f->m2 = 0;
+			if (error++)
+				return;
+		}
+		else if (f->exp < DBL_MIN)	{
+			b64_rsft(&(f->mantissa));
+			if (f->exp < 0) {
+				b64_sft(&(f->mantissa), -f->exp);
+				f->exp = 0;
+			}
+			/* underflow ??? */
+		}
+			
+		/* local CAST conversion		*/
+
+		/* because of special format shift only 10 bits */
+		/* bit shift mantissa 10 bits		*/
+
+		/* first align within words, then do store operation */
+
+		DBL->d[0] = f->m1 >> DBL_RUNPACK;   /* plus 22 == 32 */
+		DBL->d[1] = f->m2 >> DBL_RUNPACK;   /* plus 22 == 32 */
+		DBL->d[1] |= (f->m1 << DBL_LUNPACK); /* plus 10 == 32 */
+
+		/* if not exact then round to nearest	*/
+		/* on a tie, round to even */
+
+#ifdef EXCEPTION_INEXACT
+		if ((f->m2 & DBL_EXACT) != 0) {
+		    INEXACT();
+#endif
+		    if (((f->m2 & DBL_EXACT) > DBL_ROUNDUP)
+			|| ((f->m2 & DBL_EXACT) == DBL_ROUNDUP
+			    && (f->m2 & (DBL_ROUNDUP << 1)))) {
+			DBL->d[1]++;	/* rounding up	*/
+			if (DBL->d[1] == 0L) { /* carry out	*/
+			    DBL->d[0]++;
+
+			    if (f->exp == 0 && (DBL->d[0] & ~DBL_MASK)) {
+					f->exp++;
+				}
+			    if (DBL->d[0] & DBL_CARRYOUT) { /* carry out */
+				if (DBL->d[0] & 01)
+				    DBL->d[1] = CARRYBIT;
+				DBL->d[0] >>= 1;
+				f->exp++;
+			    }
+			}
+			/*	check for overflow			*/
+			if (f->exp > DBL_MAX)
+		    		goto dbl_over;
+		    }
+#ifdef EXCEPTION_INEXACT
+		}
+#endif
+
+		/*
+		 * STORE EXPONENT AND SIGN:
+		 *
+		 * 1) clear leading bits (B4-B15)
+		 * 2) shift and store exponent
+		 */
+
+		DBL->d[0] &= DBL_MASK;
+		DBL->d[0] |= 
+			((long) (f->exp << DBL_EXPSHIFT) << EXP_STORE);
+		if (f->sign)
+			DBL->d[0] |= CARRYBIT;
+
+		/*
+		 * STORE MANTISSA
+		 */
+
+#if FL_MSL_AT_LOW_ADDRESS
+		put4(DBL->d[0], (char *) &DBL->d[0]);
+		put4(DBL->d[1], (char *) &DBL->d[1]);
+#else
+		{ unsigned long l;
+		  put4(DBL->d[1], (char *) &l);
+		  put4(DBL->d[0], (char *) &DBL->d[1]);
+		  DBL->d[0] = l;
+		}
+#endif
+	}
+	else {
+		/*
+		 * COMPACT EXTENDED INTO FLOAT
+		 */
+		SINGLE	*SGL;
+
+		/* local CAST conversion		*/
+		SGL = (SINGLE *) (void *) to;
+		if ((f->m1 & SGL_ZERO) == 0L)	{
+			*SGL = 0L;
+			return;
+		}
+		f->exp += SGL_BIAS;	/* restore bias	*/
+		if (f->exp > SGL_MAX)	{
+sgl_over:			trap(EFOVFL);
+			f->exp = SGL_MAX+1;
+			f->m1 = 0L;
+			f->m2 = 0L;
+			if (error++)
+				return;
+		}
+		else if (f->exp < SGL_MIN)	{
+			b64_rsft(&(f->mantissa));
+			if (f->exp < 0) {
+				b64_sft(&(f->mantissa), -f->exp);
+				f->exp = 0;
+			}
+			/* underflow ??? */
+		}
+
+		/* shift mantissa and store	*/
+		*SGL = (f->m1 >> SGL_RUNPACK);
+
+		/* check for rounding to nearest	*/
+		/* on a tie, round to even		*/
+#ifdef EXCEPTION_INEXACT
+		if (f->m2 != 0 ||
+		    (f->m1 & SGL_EXACT) != 0L) {
+			INEXACT();
+#endif
+		        if (((f->m1 & SGL_EXACT) > SGL_ROUNDUP)
+			    || ((f->m1 & SGL_EXACT) == SGL_ROUNDUP
+			        && (f->m1 & (SGL_ROUNDUP << 1)))) {
+				(*SGL)++;
+				if (f->exp == 0 && (*SGL & ~SGL_MASK)) {
+					f->exp++;
+				}
+			/* check normal */
+				if (*SGL & SGL_CARRYOUT)	{
+					*SGL >>= 1;
+					f->exp++;
+				}
+				if (f->exp > SGL_MAX)
+					goto sgl_over;
+			}
+#ifdef EXCEPTION_INEXACT
+		}
+#endif
+
+		/*
+		 * STORE EXPONENT AND SIGN:
+		 *
+		 * 1) clear leading bit of fraction
+		 * 2) shift and store exponent
+		 */
+
+		*SGL &= SGL_MASK; /* B23-B31 are 0 */
+		*SGL |= ((long) (f->exp << SGL_EXPSHIFT) << EXP_STORE);
+		if (f->sign)
+			*SGL |= CARRYBIT;
+
+		/*
+		 * STORE MANTISSA
+		 */
+
+		put4(*SGL, (char *) &SGL);
+	}
+}
Index: /trunk/minix/lib/ack/fphook/cuf4.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/cuf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/cuf4.fc	(revision 9)
@@ -0,0 +1,57 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/cuf4.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	CONVERT INTEGER TO SINGLE (CUF n 4)
+
+	THIS ROUTINE WORKS BY FILLING AN EXTENDED
+	WITH THE INTEGER VALUE IN EXTENDED FORMAT
+	AND USES COMPACT() TO PUT IT INTO THE PROPER
+	FLOATING POINT PRECISION.
+*/
+
+#include "FP_types.h"
+
+void
+cuf4(ss,src)
+int	ss;	/* source size */
+long	src;	/* largest possible integer to convert */
+{
+	EXTEND	buf;
+	short	*ipt;
+	SINGLE	*result;
+	long	i_src;
+
+	zrf_ext(&buf);
+	if (ss == sizeof(long))	{
+		buf.exp = 31;
+		i_src = src;
+		result = (SINGLE *) &src;
+	}
+	else	{
+		ipt = (short *) &src;
+		i_src = (long) *ipt;
+		buf.exp = 15;
+		result = (SINGLE *) ((void *) &ss);
+	}
+	if (i_src == 0)	{
+		*result = (SINGLE) 0L;
+		return;
+	}
+			/* ESTABLISHED THAT src != 0	*/
+
+			/* adjust exponent field	*/
+	if (ss != sizeof(long))
+		i_src <<= 16;
+
+			/* move to mantissa field	*/
+	buf.m1 = i_src;
+
+			/* adjust mantissa field	*/
+	nrm_ext(&buf);
+	compact(&buf,result,4);
+}
Index: /trunk/minix/lib/ack/fphook/cuf8.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/cuf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/cuf8.fc	(revision 9)
@@ -0,0 +1,54 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/cuf8.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	CONVERT INTEGER TO FLOAT (CUF n 8)
+
+	THIS ROUTINE WORKS BY FILLING AN EXTENDED
+	WITH THE INTEGER VALUE IN EXTENDED FORMAT
+	AND USES COMPACT() TO PUT IT INTO THE PROPER
+	FLOATING POINT PRECISION.
+*/
+
+#include "FP_types.h"
+
+void
+cuf8(ss,src)
+int	ss;	/* source size */
+long	src;	/* largest possible integer to convert */
+{
+	EXTEND	buf;
+	short	*ipt;
+	long	i_src;
+
+	zrf_ext(&buf);
+	if (ss == sizeof(long))	{
+		buf.exp = 31;
+		i_src = src;
+	}
+	else	{
+		ipt = (short *) &src;
+		i_src = (long) *ipt;
+		buf.exp = 15;
+	}
+	if (i_src == 0)	{
+		zrf8((DOUBLE *)((void *)&ss));
+		return;
+	}
+			/* ESTABLISHED THAT src != 0	*/
+
+			/* adjust exponent field	*/
+	if (ss != sizeof(long))
+		i_src <<= 16;
+
+			/* move to mantissa field	*/
+	buf.m1 = i_src;
+
+			/* adjust mantissa field	*/
+	nrm_ext(&buf);
+	compact(&buf,(unsigned long *) (void *)&ss,8);
+}
Index: /trunk/minix/lib/ack/fphook/div_ext.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/div_ext.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/div_ext.fc	(revision 9)
@@ -0,0 +1,266 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/div_ext.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	DIVIDE EXTENDED FORMAT
+*/
+
+#include "FP_bias.h"
+#include "FP_trap.h"
+#include "FP_types.h"
+
+/*
+	November 15, 1984
+
+	This is a routine to do the work.
+	There are two versions: 
+	One is based on the partial products method
+	and makes no use possible machine instructions
+	to divide (hardware dividers).
+	The other is used when USE_DIVIDE is defined. It is much faster on
+	machines with fast 4 byte operations.
+*/
+/********************************************************/
+
+void
+div_ext(e1,e2)
+EXTEND	*e1,*e2;
+{
+	short	error = 0;
+	B64		result;
+	register	unsigned long	*lp;
+#ifndef USE_DIVIDE
+	short	count;
+#else
+	unsigned short u[9], v[5];
+	register int j;
+	register unsigned short *u_p = u;
+	int maxv = 4;
+#endif
+
+	if ((e2->m1 | e2->m2) == 0) {
+                /*
+                 * Exception 8.2 - Divide by zero
+                 */
+		trap(EFDIVZ);
+		e1->m1 = e1->m2 = 0L;
+		e1->exp = EXT_MAX;
+		return;
+	}
+	if ((e1->m1 | e1->m2) == 0) {	/* 0 / anything == 0 */
+		e1->exp = 0;	/* make sure */
+		return;
+	}
+#ifndef USE_DIVIDE
+	/*
+	 * numbers are right shifted one bit to make sure
+	 * that m1 is quaranteed to be larger if its
+	 * maximum bit is set
+	 */
+	b64_rsft(&e1->mantissa);	/* 64 bit shift right */
+	b64_rsft(&e2->mantissa);	/* 64 bit shift right */
+	e1->exp++;
+	e2->exp++;
+#endif
+	/*	check for underflow, divide by zero, etc	*/
+	e1->sign ^= e2->sign;
+	e1->exp -= e2->exp;
+
+#ifndef USE_DIVIDE
+		/* do division of mantissas	*/
+		/* uses partial product method	*/
+		/* init control variables	*/
+
+	count = 64;
+	result.h_32 = 0L;
+	result.l_32 = 0L;
+
+		/* partial product division loop */
+
+	while (count--)	{
+		/* first left shift result 1 bit	*/
+		/* this is ALWAYS done			*/
+
+		b64_lsft(&result);
+
+		/* compare dividend and divisor		*/
+		/* if dividend >= divisor add a bit	*/
+		/* and subtract divisior from dividend	*/
+
+		if ( (e1->m1 < e2->m1) ||
+			((e1->m1 == e2->m1) && (e1->m2 < e2->m2) ))
+			;	/* null statement */
+				/* i.e., don't add or subtract */
+		else	{
+			result.l_32++;	/* ADD	*/
+			if (e2->m2 > e1->m2)
+				e1->m1 -= 1;	/* carry in */
+			e1->m1 -= e2->m1;	/* do SUBTRACTION */
+			e1->m2 -= e2->m2;	/*    SUBTRACTION */
+		}
+
+		/*	shift dividend left one bit OR	*/
+		/*	IF it equals ZERO we can break out	*/
+		/*	of the loop, but still must shift	*/
+		/*	the quotient the remaining count bits	*/
+		/* NB	save the results of this test in error	*/
+		/*	if not zero, then the result is inexact. */
+		/* 	this would be reported in IEEE standard	*/
+
+		/*	lp points to dividend			*/
+		lp = &e1->m1;
+
+		error = ((*lp | *(lp+1)) != 0L) ? 1 : 0;
+		if (error)	{	/* more work */
+			/*	assume max bit == 0 (see above)	*/
+			b64_lsft(&e1->mantissa);
+			continue;
+		}
+		else
+			break;	/* leave loop	*/
+	}	/* end of divide by subtraction loop	*/
+
+	if (count > 0)	{
+		lp = &result.h_32;
+		if (count > 31) {	/* move to higher word */
+			*lp = *(lp+1);
+			count -= 32;
+			*(lp+1) = 0L;	/* clear low word	*/
+		}
+		if (*lp)
+			*lp <<= count;	/* shift rest of way	*/
+		lp++;	/*  == &result.l_32	*/
+		if (*lp) {
+			result.h_32 |= (*lp >> 32-count);
+			*lp <<= count;
+		}
+	}
+#else /* USE_DIVIDE */
+
+	u[4] = (e1->m2 & 1) << 15;
+	b64_rsft(&(e1->mantissa));
+	u[0] = e1->m1 >> 16;
+	u[1] = e1->m1;
+	u[2] = e1->m2 >> 16;
+	u[3] = e1->m2;
+	u[5] = 0; u[6] = 0; u[7] = 0;
+	v[1] = e2->m1 >> 16;
+	v[2] = e2->m1;
+	v[3] = e2->m2 >> 16;
+	v[4] = e2->m2;
+	while (! v[maxv]) maxv--;
+	result.h_32 = 0;
+	result.l_32 = 0;
+	lp = &result.h_32;
+
+	/*
+	 * Use an algorithm of Knuth (The art of programming, Seminumerical
+	 * algorithms), to divide u by v. u and v are both seen as numbers
+	 * with base 65536. 
+	 */
+	for (j = 0; j <= 3; j++, u_p++) {
+		unsigned long q_est, temp;
+
+		if (j == 2) lp++;
+		if (u_p[0] == 0 && u_p[1] < v[1]) continue;
+		temp = ((unsigned long)u_p[0] << 16) + u_p[1];
+		if (u_p[0] >= v[1]) {
+			q_est = 0x0000FFFFL;
+		}
+		else {
+			q_est = temp / v[1];
+		}
+		temp -= q_est * v[1];
+		while (temp < 0x10000 && v[2]*q_est > ((temp<<16)+u_p[2])) {
+			q_est--;
+			temp += v[1];
+		}
+		/*	Now, according to Knuth, we have an estimate of the
+			quotient, that is either correct or one too big, but
+			almost always correct.
+		*/
+		if (q_est != 0)  {
+			int i;
+			unsigned long k = 0;
+			int borrow = 0;
+
+			for (i = maxv; i > 0; i--) {
+				unsigned long tmp = q_est * v[i] + k + borrow;
+				unsigned short md = tmp;
+
+				borrow = (md > u_p[i]);
+				u_p[i] -= md;
+				k = tmp >> 16;
+			}
+			k += borrow;
+			borrow = u_p[0] < k;
+			u_p[0] -= k;
+
+			if (borrow) {
+				/* So, this does not happen often; the estimate
+				   was one too big; correct this
+				*/
+				*lp |= (j & 1) ? (q_est - 1) : ((q_est-1)<<16);
+				borrow = 0;
+				for (i = maxv; i > 0; i--) {
+					unsigned long tmp 
+					    = v[i]+(unsigned long)u_p[i]+borrow;
+					
+					u_p[i] = tmp;
+					borrow = tmp >> 16;
+				}
+				u_p[0] += borrow;
+			}
+			else *lp |= (j & 1) ? q_est : (q_est<<16);
+		}
+	}
+#ifdef	EXCEPTION_INEXACT
+	u_p = &u[0];
+	for (j = 7; j >= 0; j--) {
+		if (*u_p++) {
+			error = 1;
+			break;
+		}
+	}
+#endif
+#endif
+
+#ifdef  EXCEPTION_INEXACT
+        if (error)      {
+                /*
+                 * report here exception 8.5 - Inexact
+                 * from Draft 8.0 of IEEE P754:
+                 * In the absence of an invalid operation exception,
+                 * if the rounded result of an operation is not exact or if
+                 * it overflows without a trap, then the inexact exception
+                 * shall be assigned. The rounded or overflowed result
+                 * shall be delivered to the destination.
+                 */
+                INEXACT();
+#endif
+	e1->mantissa = result;
+
+	nrm_ext(e1);
+	if (e1->exp < EXT_MIN)	{
+		/*
+		 * Exception 8.4 - Underflow
+		 */
+		trap(EFUNFL);	/* underflow */
+		e1->exp = EXT_MIN;
+		e1->m1 = e1->m2 = 0L;
+		return;
+	}
+	if (e1->exp >= EXT_MAX) {
+                /*
+                 * Exception 8.3 - Overflow
+                 */
+                trap(EFOVFL);   /* overflow */
+                e1->exp = EXT_MAX;
+                e1->m1 = e1->m2 = 0L;
+                return;
+        }
+}
Index: /trunk/minix/lib/ack/fphook/dvf4.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/dvf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/dvf4.fc	(revision 9)
@@ -0,0 +1,26 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/dvf4.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	DIVIDE TWO SINGLES - SINGLE Precision (dvf 4)
+*/
+
+#include	"FP_types.h"
+
+void
+dvf4(s2,s1)
+SINGLE	s1,s2;
+{
+	EXTEND	e1,e2;
+
+	extend(&s1,&e1,sizeof(SINGLE));
+	extend(&s2,&e2,sizeof(SINGLE));
+
+		/* do a divide */
+	div_ext(&e1,&e2);
+	compact(&e1,&s1,sizeof(SINGLE));
+}
Index: /trunk/minix/lib/ack/fphook/dvf8.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/dvf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/dvf8.fc	(revision 9)
@@ -0,0 +1,26 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/dvf8.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	DIVIDE TWO FLOATS - DOUBLE Precision (DVF 8)
+*/
+
+#include	"FP_types.h"
+
+void
+dvf8(s2,s1)
+DOUBLE	s1,s2;
+{
+	EXTEND	e1,e2;
+
+	extend(&s1.d[0],&e1,sizeof(DOUBLE));
+	extend(&s2.d[0],&e2,sizeof(DOUBLE));
+
+		/* do a divide */
+	div_ext(&e1,&e2);
+	compact(&e1,&s1.d[0],sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/ack/fphook/extend.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/extend.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/extend.fc	(revision 9)
@@ -0,0 +1,111 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/extend.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	CONVERTS FLOATING POINT TO EXTENDED FORMAT
+
+	Two sizes of FLOATING Point are known:
+		SINGLE and DOUBLE
+*/
+/********************************************************/
+/*
+	It is not required to normalize in extended
+	format, but it has been chosen to do so.
+	Extended Format is as follows (at exit):
+
+->sign	S000 0000 | 0000 0000		<SIGN>
+->exp	0EEE EEEE | EEEE EEEE		<EXPONENT>
+->m1	LFFF FFFF | FFFF FFFF		<L.Fraction>
+	FFFF FFFF | FFFF FFFF		<Fraction>
+->m2	FFFF FFFF | FFFF FFFF		<Fraction>
+	FFFF F000 | 0000 0000		<Fraction>
+*/
+/********************************************************/
+
+#include "FP_bias.h"
+#include "FP_shift.h"
+#include "FP_types.h"
+#include "get_put.h"
+/********************************************************/
+
+void
+extend(from,to,size)
+unsigned long	*from;
+EXTEND	*to;
+int	size;
+{
+	register char *cpt1;
+	unsigned long	tmp;
+	int	leadbit = 0;
+
+	cpt1 = (char *) from;
+
+#if FL_MSL_AT_LOW_ADDRESS
+#if FL_MSW_AT_LOW_ADDRESS
+	to->exp = uget2(cpt1);
+#else
+	to->exp = uget2(cpt1+2);
+#endif
+#else
+#if FL_MSW_AT_LOW_ADDRESS
+	to->exp = uget2(cpt1+(size == sizeof(DOUBLE) ? 4 : 0));
+#else
+	to->exp = uget2(cpt1+(size == sizeof(DOUBLE) ? 6 : 2));
+#endif
+#endif
+	to->sign = (to->exp & 0x8000);	/* set sign bit */
+	to->exp ^= to->sign;
+	if (size == sizeof(DOUBLE))
+		to->exp >>= DBL_EXPSHIFT;
+	else
+		to->exp >>= SGL_EXPSHIFT;
+	if (to->exp > 0)
+		leadbit++;	/* will set Lead bit later	*/
+	else to->exp++;
+
+	if (size == sizeof(DOUBLE))	{
+#if FL_MSL_AT_LOW_ADDRESS
+		to->m1 = get4(cpt1);
+		cpt1 += 4;
+		tmp = get4(cpt1);
+#else
+		tmp = get4(cpt1);
+		cpt1 += 4;
+		to->m1 = get4(cpt1);
+#endif
+		if (to->exp == 1 && to->m1 == 0 && tmp == 0) {
+			to->exp = 0;
+			to->sign = 0;
+			to->m1 = 0;
+			to->m2 = 0;
+			return;
+		}
+		to->m1 <<= DBL_M1LEFT;		/* shift	*/
+		to->exp -= DBL_BIAS;		/* remove bias	*/
+		to->m1 |= (tmp>>DBL_RPACK);	/* plus 10 == 32	*/
+		to->m2 = (tmp<<DBL_LPACK);	/* plus 22 == 32	*/
+	}
+	else	{	/* size == sizeof(SINGLE)		*/
+		to->m1 = get4(cpt1);
+		to->m1  <<= SGL_M1LEFT;	/* shift	*/
+		if (to->exp == 1 && to->m1 == 0) {
+			to->exp = 0;
+			to->sign = 0;
+			to->m1 = 0;
+			to->m2 = 0;
+			return;
+		}
+		to->exp -= SGL_BIAS;		/* remove bias	*/
+		to->m2 = 0L;
+	}
+
+	to->m1 |= NORMBIT;				/* set bit L	*/
+	if (leadbit == 0) {		/* set or clear Leading Bit	*/
+		to->m1 &= ~NORMBIT;			/* clear bit L	*/
+		nrm_ext(to);				/* and normalize */
+	}
+}
Index: /trunk/minix/lib/ack/fphook/fef4.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/fef4.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/fef4.fc	(revision 9)
@@ -0,0 +1,33 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/fef4.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	SEPERATE INTO EXPONENT AND FRACTION (FEF 4)
+*/
+
+#include	"FP_types.h"
+
+void
+fef4(r,s1)
+SINGLE	s1;
+struct fef4_returns	*r;
+{
+	EXTEND	buf;
+	register struct fef4_returns	*p = r;	/* make copy; r might refer
+						   to itself (see table)
+						*/
+
+	extend(&s1,&buf,sizeof(SINGLE));
+	if (buf.exp == 0 && buf.m1 == 0 && buf.m2 == 0) {
+		p->e = 0;
+	}
+	else {
+		p->e = buf.exp+1;
+		buf.exp = -1;
+	}
+	compact(&buf,&p->f,sizeof(SINGLE));
+}
Index: /trunk/minix/lib/ack/fphook/fef8.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/fef8.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/fef8.fc	(revision 9)
@@ -0,0 +1,33 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/fef8.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	SEPERATE DOUBLE INTO EXPONENT AND FRACTION (FEF 8)
+*/
+
+#include	"FP_types.h"
+
+void
+fef8(r, s1)
+DOUBLE	s1;
+struct fef8_returns *r;
+{
+	EXTEND	buf;
+	register struct fef8_returns *p = r;	/* make copy, r might refer
+						   to itself (see table)
+						*/
+
+	extend(&s1.d[0],&buf,sizeof(DOUBLE));
+	if (buf.exp == 0 && buf.m1 == 0 && buf.m2 == 0) {
+		p->e = 0;
+	}
+	else {
+		p->e = buf.exp + 1;
+		buf.exp = -1;
+	}
+	compact(&buf,&p->f.d[0],sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/ack/fphook/fif4.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/fif4.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/fif4.fc	(revision 9)
@@ -0,0 +1,46 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/fif4.fc,v 1.1 2005/10/10 15:27:43 beng Exp $ */
+
+/*
+	MULTIPLY AND DISMEMBER PARTS (FIF 4)
+*/
+
+#include "FP_types.h"
+#include "FP_shift.h"
+
+void
+fif4(p,x,y)
+SINGLE	x,y;
+struct fif4_returns *p;
+{
+
+	EXTEND	e1,e2;
+
+	extend(&y,&e1,sizeof(SINGLE));
+	extend(&x,&e2,sizeof(SINGLE));
+		/* do a multiply */
+	mul_ext(&e1,&e2);
+	e2 = e1;
+	compact(&e2,&y,sizeof(SINGLE));
+	if (e1.exp < 0) {
+		p->ipart = 0;
+		p->fpart = y;
+		return;
+	}
+	if (e1.exp > 30 - SGL_M1LEFT) {
+		p->ipart = y;
+		p->fpart = 0;
+		return;
+	}
+	b64_sft(&e1.mantissa, 63 - e1.exp);
+	b64_sft(&e1.mantissa, e1.exp - 63);	/* "loose" low order bits */
+	compact(&e1,&(p->ipart),sizeof(SINGLE));
+	extend(&(p->ipart), &e2, sizeof(SINGLE));
+	extend(&y, &e1, sizeof(SINGLE));
+	sub_ext(&e1, &e2);
+	compact(&e1, &(p->fpart), sizeof(SINGLE));
+}
Index: /trunk/minix/lib/ack/fphook/fif8.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/fif8.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/fif8.fc	(revision 9)
@@ -0,0 +1,48 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/fif8.fc,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+/*
+	MULTIPLY AND DISMEMBER PARTS (FIF 8)
+*/
+
+#include "FP_types.h"
+#include "FP_shift.h"
+
+void
+fif8(p,x,y)
+DOUBLE	x,y;
+struct fif8_returns *p;
+{
+
+	EXTEND	e1,e2;
+
+	extend(&y.d[0],&e1,sizeof(DOUBLE));
+	extend(&x.d[0],&e2,sizeof(DOUBLE));
+		/* do a multiply */
+	mul_ext(&e1,&e2);
+	e2 = e1;
+	compact(&e2, &y.d[0], sizeof(DOUBLE));
+	if (e1.exp < 0) {
+		p->ipart.d[0] = 0;
+		p->ipart.d[1] = 0;
+		p->fpart = y;
+		return;
+	}
+	if (e1.exp > 62 - DBL_M1LEFT) {
+		p->ipart = y;
+		p->fpart.d[0] = 0;
+		p->fpart.d[1] = 0;
+		return;
+	}
+	b64_sft(&e1.mantissa, 63 - e1.exp);
+	b64_sft(&e1.mantissa, e1.exp - 63);	/* "loose" low order bits */
+	compact(&e1, &(p->ipart.d[0]), sizeof(DOUBLE));
+	extend(&(p->ipart.d[0]), &e2, sizeof(DOUBLE));
+	extend(&y.d[0], &e1, sizeof(DOUBLE));
+	sub_ext(&e1, &e2);
+	compact(&e1, &(p->fpart.d[0]), sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/ack/fphook/fltpr.c
===================================================================
--- /trunk/minix/lib/ack/fphook/fltpr.c	(revision 9)
+++ /trunk/minix/lib/ack/fphook/fltpr.c	(revision 9)
@@ -0,0 +1,12 @@
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	"../stdio/loc_incl.h"
+
+int _fp_hook = 1;
+
+char *
+_f_print(va_list *ap, int flags, char *s, char c, int precision)
+{
+	fprintf(stderr,"cannot print floating point\n");
+	exit(EXIT_FAILURE);
+}
Index: /trunk/minix/lib/ack/fphook/fphook.c
===================================================================
--- /trunk/minix/lib/ack/fphook/fphook.c	(revision 9)
+++ /trunk/minix/lib/ack/fphook/fphook.c	(revision 9)
@@ -0,0 +1,195 @@
+/*
+ * fltpr.c - print floating point numbers
+ */
+/* $Header: /cvsup/minix/src/lib/ack/fphook/fphook.c,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+#ifndef	NOFLOAT
+#include	<string.h>
+#include	<stdarg.h>
+#include	"../stdio/loc_incl.h"
+int _fp_hook = 1;
+
+static char *
+_pfloat(long double r, register char *s, int n, int flags)
+{
+	register char *s1;
+	int sign, dp;
+	register int i;
+
+	s1 = _fcvt(r, n, &dp, &sign);
+	if (sign)
+		*s++ = '-';
+	else if (flags & FL_SIGN)
+		*s++ = '+';
+	else if (flags & FL_SPACE)
+		*s++ = ' ';
+
+	if (dp<=0)
+		*s++ = '0';
+	for (i=dp; i>0; i--)
+		if (*s1) *s++ = *s1++;
+		else *s++ = '0';
+	if (((i=n) > 0) || (flags & FL_ALT))
+		*s++ = '.';
+	while (++dp <= 0) {
+		if (--i<0)
+			break;
+		*s++ = '0';
+	}
+	while (--i >= 0)
+		if (*s1) *s++ = *s1++;
+		else *s++ = '0';
+	return s;
+}
+
+static char *
+_pscien(long double r, register char *s, int n, int flags)
+{
+	int sign, dp; 
+	register char *s1;
+
+	s1 = _ecvt(r, n + 1, &dp, &sign);
+	if (sign)
+		*s++ = '-';
+	else if (flags & FL_SIGN)
+		*s++ = '+';
+	else if (flags & FL_SPACE)
+		*s++ = ' ';
+
+	*s++ = *s1++;
+	if ((n > 0) || (flags & FL_ALT))
+		*s++ = '.';
+	while (--n >= 0)
+		if (*s1) *s++ = *s1++;
+		else *s++ = '0';
+	*s++ = 'e';
+	if ( r != 0 ) --dp ;
+	if ( dp<0 ) {
+		*s++ = '-' ; dp= -dp ;
+	} else {
+		*s++ = '+' ;
+	}
+	if (dp >= 100) {
+		*s++ = '0' + (dp / 100);
+		dp %= 100;
+	}
+	*s++ = '0' + (dp/10);
+	*s++ = '0' + (dp%10);
+	return s;
+}
+
+#define	NDIGINEXP(exp)		(((exp) >= 100 || (exp) <= -100) ? 3 : 2)
+#define	LOW_EXP			-4
+#define	USE_EXP(exp, ndigits)	(((exp) < LOW_EXP + 1) || (exp >= ndigits + 1))
+
+static char *
+_gcvt(long double value, int ndigit, char *s, int flags)
+{
+	int sign, dp;
+	register char *s1, *s2;
+	register int i;
+	register int nndigit = ndigit;
+
+	s1 = _ecvt(value, ndigit, &dp, &sign);
+	s2 = s;
+	if (sign) *s2++ = '-';
+	else if (flags & FL_SIGN)
+		*s2++ = '+';
+	else if (flags & FL_SPACE)
+		*s2++ = ' ';
+
+	if (!(flags & FL_ALT))
+		for (i = nndigit - 1; i > 0 && s1[i] == '0'; i--)
+			nndigit--;
+
+	if (USE_EXP(dp,ndigit))	{
+		/* Use E format */
+		dp--;
+		*s2++ = *s1++;
+		if ((nndigit > 1) || (flags & FL_ALT)) *s2++ = '.';
+		while (--nndigit > 0) *s2++ = *s1++;
+		*s2++ = 'e';
+		if (dp < 0) {
+			*s2++ = '-';
+			dp = -dp;
+		}
+		else	 *s2++ = '+';
+		s2 += NDIGINEXP(dp);
+		*s2 = 0;
+		for (i = NDIGINEXP(dp); i > 0; i--) {
+			*--s2 = dp % 10 + '0';
+			dp /= 10;
+		}
+		return s;
+	}
+	/* Use f format */
+	if (dp <= 0) {
+		if (*s1 != '0')	{
+			/* otherwise the whole number is 0 */
+			*s2++ = '0';
+			*s2++ = '.';
+		}
+		while (dp < 0) {
+			dp++;
+			*s2++ = '0';
+		}
+	}
+	for (i = 1; i <= nndigit; i++) {
+		*s2++ = *s1++;
+		if (i == dp) *s2++ = '.';
+	}
+	if (i <= dp) {
+		while (i++ <= dp) *s2++ = '0';
+		*s2++ = '.';
+	}
+	if ((s2[-1]=='.') && !(flags & FL_ALT)) s2--;
+	*s2 = '\0';
+	return s;
+}
+
+char *
+_f_print(va_list *ap, int flags, char *s, char c, int precision)
+{
+	register char *old_s = s;
+	long double ld_val;
+
+	if (flags & FL_LONGDOUBLE) ld_val = va_arg(*ap, long double);
+	else ld_val = (long double) va_arg(*ap, double);
+
+	switch(c) {
+	case 'f':
+		s = _pfloat(ld_val, s, precision, flags);
+		break;
+	case 'e':
+	case 'E':
+		s = _pscien(ld_val, s, precision , flags);
+		break;
+	case 'g':
+	case 'G':
+		s = _gcvt(ld_val, precision, s, flags);
+		s += strlen(s);
+		break;
+	}
+	if ( c == 'E' || c == 'G') {
+		while (*old_s && *old_s != 'e') old_s++;
+		if (*old_s == 'e') *old_s = 'E';
+	}
+	return s;
+}
+#endif	/* NOFLOAT */
+/* $Header: /cvsup/minix/src/lib/ack/fphook/fphook.c,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+#include <stdlib.h>
+#include "../ansi/ext_fmt.h"
+
+void _str_ext_cvt(const char *s, char **ss, struct EXTEND *e);
+double _ext_dbl_cvt(struct EXTEND *e);
+
+double
+strtod(const char *p, char **pp)
+{
+	struct EXTEND e;
+
+	_str_ext_cvt(p, pp, &e);
+	return _ext_dbl_cvt(&e);
+}
Index: /trunk/minix/lib/ack/fphook/fptrp.s
===================================================================
--- /trunk/minix/lib/ack/fphook/fptrp.s	(revision 9)
+++ /trunk/minix/lib/ack/fphook/fptrp.s	(revision 9)
@@ -0,0 +1,19 @@
+#
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define __fptrp
+.sect .text
+__fptrp:
+#if __i386
+	push	ebp
+	mov	ebp, esp
+	mov	eax, 8(bp)
+	call	.Xtrp
+	leave
+	ret
+#else /* i86 */
+	push	bp
+	mov	bp, sp
+	mov	ax, 4(bp)
+	call	.Xtrp
+	jmp	.cret
+#endif
Index: /trunk/minix/lib/ack/fphook/get_put.h
===================================================================
--- /trunk/minix/lib/ack/fphook/get_put.h	(revision 9)
+++ /trunk/minix/lib/ack/fphook/get_put.h	(revision 9)
@@ -0,0 +1,41 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/get_put.h,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+#include <byte_order.h>
+
+#if CHAR_UNSIGNED
+#define Xchar(ch)	(ch)
+#else
+#define Xchar(ch)	((ch) & 0377)
+#endif
+
+#define BYTES_REVERSED (MSB_AT_LOW_ADDRESS != FL_MSB_AT_LOW_ADDRESS)
+#define WORDS_REVERSED (MSW_AT_LOW_ADDRESS != FL_MSW_AT_LOW_ADDRESS)
+#define LONGS_REVERSED (FL_MSL_AT_LOW_ADDRESS)
+
+#if BYTES_REVERSED
+#define uget2(c)	(Xchar((c)[1]) | ((unsigned) Xchar((c)[0]) << 8))
+#define Xput2(i, c)	(((c)[1] = (i)), ((c)[0] = (i) >> 8))
+#define put2(i, c)	{ register int j = (i); Xput2(j, c); }
+#else
+#define uget2(c)	(* ((unsigned short *) (c)))
+#define Xput2(i, c)	(* ((short *) (c)) = (i))
+#define put2(i, c)	Xput2(i, c)
+#endif
+
+#define get2(c)		((short) uget2(c))
+
+#if WORDS_REVERSED || BYTES_REVERSED
+#define get4(c)		(uget2((c)+2) | ((long) uget2(c) << 16))
+#define put4(l, c)	{ register long x=(l); \
+			  Xput2((int)x,(c)+2); \
+			  Xput2((int)(x>>16),(c)); \
+			}
+#else
+#define get4(c)		(* ((long *) (c)))
+#define put4(l, c)	(* ((long *) (c)) = (l))
+#endif
Index: /trunk/minix/lib/ack/fphook/mlf4.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/mlf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/mlf4.fc	(revision 9)
@@ -0,0 +1,25 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/mlf4.fc,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+/*
+ * Multiply Single Precesion Float (MLF 4)
+ */
+
+#include	"FP_types.h"
+
+void
+mlf4(s2,s1)
+SINGLE	s1,s2;
+{
+	EXTEND	e1,e2;
+
+	extend(&s1,&e1,sizeof(SINGLE));
+	extend(&s2,&e2,sizeof(SINGLE));
+		/* do a multiply */
+	mul_ext(&e1,&e2);
+	compact(&e1,&s1,sizeof(SINGLE));
+}
Index: /trunk/minix/lib/ack/fphook/mlf8.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/mlf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/mlf8.fc	(revision 9)
@@ -0,0 +1,25 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/mlf8.fc,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+/*
+ * Multiply Double Precision Float (MLF 8)
+ */
+
+#include	"FP_types.h"
+
+void
+mlf8(s2,s1)
+DOUBLE	s1,s2;
+{
+	EXTEND	e1,e2;
+
+	extend(&s1.d[0],&e1,sizeof(DOUBLE));
+	extend(&s2.d[0],&e2,sizeof(DOUBLE));
+		/* do a multiply */
+	mul_ext(&e1,&e2);
+	compact(&e1,&s1.d[0],sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/ack/fphook/mul_ext.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/mul_ext.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/mul_ext.fc	(revision 9)
@@ -0,0 +1,98 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/mul_ext.fc,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+/*
+	ROUTINE TO MULTIPLY TWO EXTENDED FORMAT NUMBERS
+*/
+
+# include "FP_bias.h"
+# include "FP_trap.h"
+# include "FP_types.h"
+# include "FP_shift.h"
+
+void
+mul_ext(e1,e2)
+EXTEND	*e1,*e2;
+{
+	register int	i,j;		/* loop control	*/
+	unsigned short	mp[4];		/* multiplier */
+	unsigned short	mc[4];		/* multipcand */
+	unsigned short	result[8];	/* result */
+	register unsigned short *pres;
+
+	/* first save the sign (XOR)			*/
+	e1->sign ^= e2->sign;
+
+	/* compute new exponent */
+	e1->exp += e2->exp + 1;
+	/* 128 bit multiply of mantissas			*/
+
+		/* assign unknown long formats		*/
+		/* to known unsigned word formats	*/
+	mp[0] = e1->m1 >> 16;
+	mp[1] = (unsigned short) e1->m1;
+	mp[2] = e1->m2 >> 16;
+	mp[3] = (unsigned short) e1->m2;
+	mc[0] = e2->m1 >> 16;
+	mc[1] = (unsigned short) e2->m1;
+	mc[2] = e2->m2 >> 16;
+	mc[3] = (unsigned short) e2->m2;
+	for (i = 8; i--;) {
+		result[i] = 0;
+	}
+	/*
+	 *	fill registers with their components
+	 */
+	for(i=4, pres = &result[4];i--;pres--) if (mp[i]) {
+		unsigned short k = 0;
+		unsigned long mpi = mp[i];
+		for(j=4;j--;) {
+			unsigned long tmp = (unsigned long)pres[j] + k;
+			if (mc[j]) tmp += mpi * mc[j];
+			pres[j] = tmp;
+			k = tmp >> 16;
+		}
+		pres[-1] = k;
+	}
+        if (! (result[0] & 0x8000)) {
+                e1->exp--;
+                for (i = 0; i <= 3; i++) {
+                        result[i] <<= 1;
+                        if (result[i+1]&0x8000) result[i] |= 1;
+                }
+                result[4] <<= 1;
+        }
+
+	/*
+	 *	combine the registers to a total
+	 */
+	e1->m1 = ((unsigned long)(result[0]) << 16) + result[1];
+	e1->m2 = ((unsigned long)(result[2]) << 16) + result[3];
+	if (result[4] & 0x8000) {
+		if (++e1->m2 == 0)
+			if (++e1->m1 == 0) {
+				e1->m1 = NORMBIT;
+				e1->exp++;
+			}
+	}
+
+					/* check for overflow	*/
+	if (e1->exp >= EXT_MAX)	{
+		trap(EFOVFL);
+			/* if caught 			*/
+			/* return signed infinity	*/
+		e1->exp = EXT_MAX;
+infinity:	e1->m1 = e1->m2 =0L;
+		return;
+	}
+				/* check for underflow	*/
+	if (e1->exp < EXT_MIN)	{
+		trap(EFUNFL);
+		e1->exp = EXT_MIN;
+		goto infinity;
+	}
+}
Index: /trunk/minix/lib/ack/fphook/ngf4.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/ngf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/ngf4.fc	(revision 9)
@@ -0,0 +1,27 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/ngf4.fc,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+/*
+		NEGATE A FLOATING POINT (NGF 4)
+*/
+/********************************************************/
+
+#include "FP_types.h"
+#include "get_put.h"
+
+#define OFF ((FL_MSW_AT_LOW_ADDRESS ? 0 : 2) + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1))
+void
+ngf4(f)
+SINGLE	f;
+{
+	unsigned char *p;
+
+	if (f != (SINGLE) 0) {
+		p = (unsigned char *) &f + OFF;
+		*p ^= 0x80;
+	}
+}
Index: /trunk/minix/lib/ack/fphook/ngf8.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/ngf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/ngf8.fc	(revision 9)
@@ -0,0 +1,28 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/ngf8.fc,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+/*
+		NEGATE A FLOATING POINT (NGF 8)
+*/
+/********************************************************/
+
+#include "FP_types.h"
+#include "get_put.h"
+
+#define OFF ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1))
+
+void
+ngf8(f)
+DOUBLE	f;
+{
+	unsigned char	*p;
+
+	if (f.d[0] != 0 || f.d[1] != 0) {
+		p = (unsigned char *) &f + OFF;
+		*p ^= 0x80;
+	}
+}
Index: /trunk/minix/lib/ack/fphook/nrm_ext.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/nrm_ext.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/nrm_ext.fc	(revision 9)
@@ -0,0 +1,50 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/nrm_ext.fc,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+/********************************************************/
+/*
+	NORMALIZE an EXTENDED FORMAT NUMBER
+*/
+/********************************************************/
+
+#include "FP_shift.h"
+#include "FP_types.h"
+
+void
+nrm_ext(e1)
+EXTEND	*e1;
+{
+		/* we assume that the mantissa != 0	*/
+		/* if it is then just return		*/
+		/* to let it be a problem elsewhere	*/
+		/* THAT IS, The exponent is not set to	*/
+		/* zero. If we don't test here an	*/
+		/* infinite loop is generated when	*/
+		/* mantissa is zero			*/
+
+	if ((e1->m1 | e1->m2) == 0L)
+		return;
+
+		/* if top word is zero mov low word	*/
+		/* to top word, adjust exponent value	*/
+	if (e1->m1 == 0L)	{
+		e1->m1 = e1->m2;
+		e1->m2 = 0L;
+		e1->exp -= 32;
+	}
+	if ((e1->m1 & NORMBIT) == 0) {
+		unsigned long l = ((unsigned long)NORMBIT >> 1);
+		int cnt = -1;
+
+		while (! (l & e1->m1)) {
+			l >>= 1;
+			cnt--;
+		}
+		e1->exp += cnt;
+		b64_sft(&(e1->mantissa), cnt);
+	}
+}
Index: /trunk/minix/lib/ack/fphook/sbf4.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/sbf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/sbf4.fc	(revision 9)
@@ -0,0 +1,27 @@
+/*
+ (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/sbf4.fc,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+/*
+	SUBTRACT TWO FLOATS - SINGLE Precision (SBF 4)
+*/
+
+#include	"FP_types.h"
+
+void
+sbf4(s2,s1)
+SINGLE	s1,s2;
+{
+	EXTEND e1,e2;
+
+	if (s2 == (SINGLE) 0) {
+		return;
+	}
+	extend(&s1,&e1,sizeof(SINGLE));
+	extend(&s2,&e2,sizeof(SINGLE));
+	sub_ext(&e1,&e2);
+	compact(&e1,&s1,sizeof(SINGLE));
+}
Index: /trunk/minix/lib/ack/fphook/sbf8.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/sbf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/sbf8.fc	(revision 9)
@@ -0,0 +1,27 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/sbf8.fc,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+/*
+	SUBTRACT TWO FLOATS - DOUBLE Precision (SBF 8)
+*/
+
+#include	"FP_types.h"
+
+void
+sbf8(s2,s1)
+DOUBLE	s1,s2;
+{
+	EXTEND e1, e2;
+
+	if (s2.d[0] == 0 && s2.d[1] == 0) {
+		return;
+	}
+	extend(&s1.d[0],&e1,sizeof(DOUBLE));
+	extend(&s2.d[0],&e2,sizeof(DOUBLE));
+	sub_ext(&e1,&e2);
+	compact(&e1,&s1.d[0],sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/ack/fphook/sft_ext.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/sft_ext.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/sft_ext.fc	(revision 9)
@@ -0,0 +1,39 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/sft_ext.fc,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+/*
+	SHIFT TWO EXTENDED NUMBERS INTO PROPER
+	ALIGNMENT FOR ADDITION (exponents are equal)
+	Numbers should not be zero on entry.
+*/
+
+#include "FP_types.h"
+
+void
+sft_ext(e1,e2)
+EXTEND	*e1,*e2;
+{
+	register	EXTEND	*s;
+	register	int	diff;
+
+	diff = e1->exp - e2->exp;
+
+	if (!diff)
+		return;	/* exponents are equal	*/
+
+	if (diff < 0)	{ /* e2 is larger	*/
+			/* shift e1		*/
+		diff = -diff;
+		s = e1;
+	}
+	else		/* e1 is larger		*/
+			/* shift e2		*/
+		s = e2;
+
+	s->exp += diff;
+	b64_sft(&(s->mantissa), diff);
+}
Index: /trunk/minix/lib/ack/fphook/shifter.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/shifter.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/shifter.fc	(revision 9)
@@ -0,0 +1,75 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/shifter.fc,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+# include "FP_types.h"
+
+void
+b64_sft(e1,n)
+B64	*e1;
+int	n;
+{
+	if (n > 0) {
+		if (n > 63) {
+			e1->l_32 = 0;
+			e1->h_32 = 0;
+			return;
+		}
+		if (n >= 32) {
+			e1->l_32 = e1->h_32;
+			e1->h_32 = 0;
+			n -= 32;
+		}
+		if (n > 0) {
+			e1->l_32 >>= n;
+			if (e1->h_32 != 0) {
+				e1->l_32 |= (e1->h_32 << (32 - n));
+				e1->h_32 >>= n;
+			}
+		}
+		return;
+	}
+	n = -n;
+	if (n > 0) {
+		if (n > 63) {
+			e1->l_32 = 0;
+			e1->h_32 = 0;
+			return;
+		}
+		if (n >= 32) {
+			e1->h_32 = e1->l_32;
+			e1->l_32 = 0;
+			n -= 32;
+		}
+		if (n > 0) {
+			e1->h_32 <<= n;
+			if (e1->l_32 != 0) {
+				e1->h_32 |= (e1->l_32 >> (32 - n));
+				e1->l_32 <<= n;
+			}
+		}
+	}
+}
+
+void
+b64_lsft(e1)
+B64	*e1;
+{
+	/*	shift left 1 bit */
+	e1->h_32 <<= 1;
+	if (e1->l_32 & 0x80000000L) e1->h_32 |= 1;
+	e1->l_32 <<= 1;
+}
+
+void
+b64_rsft(e1)
+B64	*e1;
+{
+	/*	shift right 1 bit */
+	e1->l_32 >>= 1;
+	if (e1->h_32 & 1) e1->l_32 |= 0x80000000L;
+	e1->h_32 >>= 1;
+}
Index: /trunk/minix/lib/ack/fphook/strtod.c
===================================================================
--- /trunk/minix/lib/ack/fphook/strtod.c	(revision 9)
+++ /trunk/minix/lib/ack/fphook/strtod.c	(revision 9)
@@ -0,0 +1,9 @@
+#include	<stdio.h>
+#include	<stdlib.h>
+
+double
+strtod(const char *p, char **pp)
+{
+	fprintf(stderr,"cannot print floating point\n");
+	exit(EXIT_FAILURE);
+}
Index: /trunk/minix/lib/ack/fphook/sub_ext.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/sub_ext.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/sub_ext.fc	(revision 9)
@@ -0,0 +1,53 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/sub_ext.fc,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+/*
+	SUBTRACT 2 EXTENDED FORMAT NUMBERS
+*/
+
+#include "FP_types.h"
+
+void
+sub_ext(e1,e2)
+EXTEND	*e1,*e2;
+{
+	if ((e2->m1 | e2->m2) == 0L) {
+		return;
+	}
+	if ((e1->m1 | e1->m2) == 0L) {
+		*e1 = *e2;
+		e1->sign = e2->sign ? 0 : 1;
+		return;
+	}
+	sft_ext(e1, e2);
+	if (e1->sign != e2->sign) {
+		/* e1 - e2 = e1 + (-e2) */
+		if (b64_add(&e1->mantissa,&e2->mantissa)) { /* addition carry */
+                	b64_rsft(&e1->mantissa);      /* shift mantissa one bit RIGHT */
+                	e1->m1 |= 0x80000000L;  /* set max bit  */
+                	e1->exp++;              /* increase the exponent */
+        	}
+	}
+        else if (e2->m1 > e1->m1 ||
+                 (e2->m1 == e1->m1 && e2->m2 > e1->m2)) {
+		/*	abs(e2) > abs(e1) */
+		if (e1->m2 > e2->m2) {
+			e2->m1 -= 1;	/* carry in */
+		}
+		e2->m1 -= e1->m1;
+		e2->m2 -= e1->m2;
+		*e1 = *e2;
+		e1->sign = e2->sign ? 0 : 1;
+	}
+	else {
+		if (e2->m2 > e1->m2)
+			e1->m1 -= 1;	/* carry in */
+		e1->m1 -= e2->m1;
+		e1->m2 -= e2->m2;
+	}
+	nrm_ext(e1);
+}
Index: /trunk/minix/lib/ack/fphook/zrf4.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/zrf4.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/zrf4.fc	(revision 9)
@@ -0,0 +1,19 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/zrf4.fc,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+/*
+	return a zero float (ZRF 4)
+*/
+
+#include "FP_types.h"
+
+void
+zrf4(l)
+SINGLE	*l;
+{
+	*l = 0L;
+}
Index: /trunk/minix/lib/ack/fphook/zrf8.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/zrf8.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/zrf8.fc	(revision 9)
@@ -0,0 +1,21 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/zrf8.fc,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+/*
+	return a zero double (ZRF 8)
+*/
+
+#include "FP_types.h"
+
+void
+zrf8(z)
+DOUBLE	*z;
+{
+
+	z->d[0] = 0L;
+	z->d[1] = 0L;
+}
Index: /trunk/minix/lib/ack/fphook/zrf_ext.fc
===================================================================
--- /trunk/minix/lib/ack/fphook/zrf_ext.fc	(revision 9)
+++ /trunk/minix/lib/ack/fphook/zrf_ext.fc	(revision 9)
@@ -0,0 +1,22 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/ack/fphook/zrf_ext.fc,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+/*
+	ZERO and return EXTEND FORMAT FLOAT
+*/
+
+#include "FP_types.h"
+
+void
+zrf_ext(e)
+EXTEND	*e;
+{
+	e->m1 = 0;
+	e->m2 = 0;
+	e->exp = 0;
+	e->sign = 0;
+}
Index: /trunk/minix/lib/ack/h/em_abs.h
===================================================================
--- /trunk/minix/lib/ack/h/em_abs.h	(revision 9)
+++ /trunk/minix/lib/ack/h/em_abs.h	(revision 9)
@@ -0,0 +1,35 @@
+/* $Header: /cvsup/minix/src/lib/ack/h/em_abs.h,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#define LINO_AD         0
+#define FILN_AD         4
+
+#define LINO            (*(int    *)(_hol0()+LINO_AD))
+#define FILN            (*(char  **)(_hol0()+FILN_AD))
+
+#define EARRAY          0
+#define ERANGE          1
+#define ESET            2
+#define EIOVFL          3
+#define EFOVFL          4
+#define EFUNFL          5
+#define EIDIVZ          6
+#define EFDIVZ          7
+#define EIUND           8
+#define EFUND           9
+#define ECONV           10
+
+#define ESTACK          16
+#define EHEAP           17
+#define EILLINS         18
+#define EODDZ           19
+#define ECASE           20
+#define EMEMFLT         21
+#define EBADPTR         22
+#define EBADPC          23
+#define EBADLAE         24
+#define EBADMON         25
+#define EBADLIN         26
+#define EBADGTO         27
Index: /trunk/minix/lib/ack/h/m2_traps.h
===================================================================
--- /trunk/minix/lib/ack/h/m2_traps.h	(revision 9)
+++ /trunk/minix/lib/ack/h/m2_traps.h	(revision 9)
@@ -0,0 +1,16 @@
+/* $Header: /cvsup/minix/src/lib/ack/h/m2_traps.h,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+/*
+ * (c) copyright 1990 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+
+/* Modula-2 runtime errors */
+
+#define M2_TOOLARGE	64	/* stack of process too large */
+#define M2_TOOMANY	65	/* too many nested traps & handlers */
+#define M2_NORESULT	66	/* no RETURN from procedure function */
+#define M2_UOVFL	67	/* cardinal overflow */
+#define M2_FORCH	68	/* FOR-loop control variable changed */
+#define M2_UUVFL	69	/* cardinal underflow */
+#define M2_INTERNAL	70	/* internal error, should not happen */
+#define M2_UNIXSIG	71	/* unix signal */
Index: /trunk/minix/lib/ack/h/pc_err.h
===================================================================
--- /trunk/minix/lib/ack/h/pc_err.h	(revision 9)
+++ /trunk/minix/lib/ack/h/pc_err.h	(revision 9)
@@ -0,0 +1,29 @@
+/* $Header: /cvsup/minix/src/lib/ack/h/pc_err.h,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#define	EARGC	64
+#define	EEXP	65
+#define	ELOG	66
+#define	ESQT	67
+#define	EASS	68
+#define	EPACK	69
+#define	EUNPACK	70
+#define	EMOD	71
+#define	EBADF	72
+#define	EFREE	73
+#define EFUNASS	74
+#define EWIDTH	75
+
+#define	EWRITEF	96
+#define	EREADF	97
+#define	EEOF	98
+#define	EFTRUNC	99
+#define	ERESET	100
+#define	EREWR	101
+#define	ECLOSE	102
+#define	EREAD	103
+#define	EWRITE	104
+#define	EDIGIT	105
+#define	EASCII	106
Index: /trunk/minix/lib/ack/h/pc_file.h
===================================================================
--- /trunk/minix/lib/ack/h/pc_file.h	(revision 9)
+++ /trunk/minix/lib/ack/h/pc_file.h	(revision 9)
@@ -0,0 +1,24 @@
+/* $Header: /cvsup/minix/src/lib/ack/h/pc_file.h,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#define	WRBIT	0100000
+#define	TXTBIT	040000
+#define	EOFBIT	020000
+#define	ELNBIT	010000
+#define	WINDOW	04000
+#define	MAGIC	0252
+
+#define	PC_BUFLEN	1024
+
+struct file {
+	char	*ptr;
+	unsigned flags;
+	char	*fname;
+	int	ufd;
+	int	size;
+	int	count;
+	int	buflen;
+	char	bufadr[PC_BUFLEN];
+};
Index: /trunk/minix/lib/ack/h/pc_math.h
===================================================================
--- /trunk/minix/lib/ack/h/pc_math.h	(revision 9)
+++ /trunk/minix/lib/ack/h/pc_math.h	(revision 9)
@@ -0,0 +1,42 @@
+/*
+ * localmath.h - This header is used by the mathematical library.
+ */
+/* $Header: /cvsup/minix/src/lib/ack/h/pc_math.h,v 1.1 2005/10/10 15:27:44 beng Exp $ */
+
+/* some constants (Hart & Cheney) */
+#define	M_PI		3.14159265358979323846264338327950288
+#define	M_2PI		6.28318530717958647692528676655900576
+#define	M_3PI_4		2.35619449019234492884698253745962716
+#define	M_PI_2		1.57079632679489661923132169163975144
+#define	M_3PI_8		1.17809724509617246442349126872981358
+#define	M_PI_4		0.78539816339744830961566084581987572
+#define	M_PI_8		0.39269908169872415480783042290993786
+#define	M_1_PI		0.31830988618379067153776752674502872
+#define	M_2_PI		0.63661977236758134307553505349005744
+#define	M_4_PI		1.27323954473516268615107010698011488
+#define	M_E		2.71828182845904523536028747135266250
+#define	M_LOG2E		1.44269504088896340735992468100189213
+#define	M_LOG10E	0.43429448190325182765112891891660508
+#define	M_LN2		0.69314718055994530941723212145817657
+#define	M_LN10		2.30258509299404568401799145468436421
+#define	M_SQRT2		1.41421356237309504880168872420969808
+#define	M_1_SQRT2	0.70710678118654752440084436210484904
+#define	M_EULER		0.57721566490153286060651209008240243
+
+/* macros for constructing polynomials */
+#define	POLYNOM1(x, a)	((a)[1]*(x)+(a)[0])
+#define	POLYNOM2(x, a)	(POLYNOM1((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM3(x, a)	(POLYNOM2((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM4(x, a)	(POLYNOM3((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM5(x, a)	(POLYNOM4((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM6(x, a)	(POLYNOM5((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM7(x, a)	(POLYNOM6((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM8(x, a)	(POLYNOM7((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM9(x, a)	(POLYNOM8((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM10(x, a)	(POLYNOM9((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM11(x, a)	(POLYNOM10((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM12(x, a)	(POLYNOM11((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM13(x, a)	(POLYNOM12((x),(a)+1)*(x)+(a)[0])
+
+#define	M_LN_MAX_D	(M_LN2 * DBL_MAX_EXP)
+#define	M_LN_MIN_D	(M_LN2 * (DBL_MIN_EXP - 1))
Index: /trunk/minix/lib/ack/i386/Makefile
===================================================================
--- /trunk/minix/lib/ack/i386/Makefile	(revision 9)
+++ /trunk/minix/lib/ack/i386/Makefile	(revision 9)
@@ -0,0 +1,48 @@
+#Generated from ./ack/i386/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../generate.sh ./ack/i386 ../../obj-ack/ ../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../generate.sh ./ack/i386 ../../obj-ack/ ../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+all-ack: makefiles
+	mkdir -p ../../obj-ack//./ack/i386/em
+	cd em && $(MAKE) $@
+	mkdir -p ../../obj-ack//./ack/i386/head
+	cd head && $(MAKE) $@
+
+all-gnu: makefiles
+	cd em && $(MAKE) $@
+	cd head && $(MAKE) $@
+
+clean depend depend-ack depend-gnu:: makefiles
+	cd em && $(MAKE) $@
+	cd head && $(MAKE) $@
+
+makefiles: em/Makefile
+makefiles: head/Makefile
+
+em/Makefile: em/Makefile.in
+	cd em && sh ../../../generate.sh ./ack/i386/em ../../../obj-ack/ ../../../obj-gnu && $(MAKE) makefiles
+head/Makefile: head/Makefile.in
+	cd head && sh ../../../generate.sh ./ack/i386/head ../../../obj-ack/ ../../../obj-gnu && $(MAKE) makefiles
+
+clean::
+	rm -f ../../obj-ack//./ack/i386/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/ack/i386/Makefile.in
===================================================================
--- /trunk/minix/lib/ack/i386/Makefile.in	(revision 9)
+++ /trunk/minix/lib/ack/i386/Makefile.in	(revision 9)
@@ -0,0 +1,4 @@
+
+SUBDIRS="em head"
+
+TYPE=ack
Index: /trunk/minix/lib/ack/i386/em/Makedepend-ack
===================================================================
--- /trunk/minix/lib/ack/i386/em/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/Makedepend-ack	(revision 9)
@@ -0,0 +1,72 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_adf4.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_adf8.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_adi.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_and.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_blm.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_cff4.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_cff8.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_cfi.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_cfu.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_cif4.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_cif8.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_cii.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_cmf4.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_cmf8.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_cms.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_com.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_csa4.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_csb4.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_cuf4.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_cuf8.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_cuu.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_dup.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_dvf4.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_dvf8.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_dvi.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_dvu.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_error.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_exg.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_fat.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_fef4.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_fef8.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_fif4.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_fif8.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_fp8087.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_gto.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_hol0.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_iaar.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_ilar.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_inn.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_ior.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_isar.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_lar4.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_loi.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_mlf4.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_mlf8.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_mli.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_mon.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_ngf4.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_ngf8.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_ngi.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_nop.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_print.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_rck.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_rmi.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_rmu.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_rol.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_ror.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_sar4.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_sbf4.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_sbf8.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_sbi.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_set.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_sli.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_sri.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_sti.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_stop.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_trp.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_unknown.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -E' em_xor.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/em/\1:' >> .depend-ack
Index: /trunk/minix/lib/ack/i386/em/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/ack/i386/em/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/Makedepend-gnu	(revision 9)
@@ -0,0 +1,3 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
Index: /trunk/minix/lib/ack/i386/em/Makefile
===================================================================
--- /trunk/minix/lib/ack/i386/em/Makefile	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/Makefile	(revision 9)
@@ -0,0 +1,244 @@
+#Generated from ./ack/i386/em/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../../generate.sh ./ack/i386/em ../../../obj-ack/ ../../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../../generate.sh ./ack/i386/em ../../../obj-ack/ ../../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../../../obj-ack//libe.a
+
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_adf4.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_adf8.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_adi.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_and.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_blm.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_cff4.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_cff8.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_cfi.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_cfu.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_cif4.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_cif8.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_cii.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_cmf4.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_cmf8.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_cms.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_com.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_csa4.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_csb4.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_cuf4.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_cuf8.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_cuu.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_dup.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_dvf4.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_dvf8.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_dvi.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_dvu.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_error.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_exg.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_fat.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_fef4.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_fef8.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_fif4.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_fif8.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_fp8087.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_gto.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_hol0.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_iaar.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_ilar.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_inn.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_ior.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_isar.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_lar4.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_loi.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_mlf4.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_mlf8.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_mli.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_mon.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_ngf4.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_ngf8.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_ngi.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_nop.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_print.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_rck.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_rmi.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_rmu.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_rol.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_ror.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_sar4.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_sbf4.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_sbf8.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_sbi.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_set.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_sli.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_sri.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_sti.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_stop.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_trp.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_unknown.o)
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_xor.o)
+
+../../../obj-ack//libe.a:
+	ar cr ../../../obj-ack//libe.a ../../../obj-ack//./ack/i386/em/*.o
+	rm ../../../obj-ack//./ack/i386/em/*.o
+
+../../../obj-ack//libe.a(em_adf4.o): em_adf4.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_adf4.o em_adf4.s
+../../../obj-ack//libe.a(em_adf8.o): em_adf8.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_adf8.o em_adf8.s
+../../../obj-ack//libe.a(em_adi.o): em_adi.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_adi.o em_adi.s
+../../../obj-ack//libe.a(em_and.o): em_and.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_and.o em_and.s
+../../../obj-ack//libe.a(em_blm.o): em_blm.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_blm.o em_blm.s
+../../../obj-ack//libe.a(em_cff4.o): em_cff4.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_cff4.o em_cff4.s
+../../../obj-ack//libe.a(em_cff8.o): em_cff8.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_cff8.o em_cff8.s
+../../../obj-ack//libe.a(em_cfi.o): em_cfi.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_cfi.o em_cfi.s
+../../../obj-ack//libe.a(em_cfu.o): em_cfu.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_cfu.o em_cfu.s
+../../../obj-ack//libe.a(em_cif4.o): em_cif4.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_cif4.o em_cif4.s
+../../../obj-ack//libe.a(em_cif8.o): em_cif8.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_cif8.o em_cif8.s
+../../../obj-ack//libe.a(em_cii.o): em_cii.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_cii.o em_cii.s
+../../../obj-ack//libe.a(em_cmf4.o): em_cmf4.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_cmf4.o em_cmf4.s
+../../../obj-ack//libe.a(em_cmf8.o): em_cmf8.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_cmf8.o em_cmf8.s
+../../../obj-ack//libe.a(em_cms.o): em_cms.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_cms.o em_cms.s
+../../../obj-ack//libe.a(em_com.o): em_com.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_com.o em_com.s
+../../../obj-ack//libe.a(em_csa4.o): em_csa4.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_csa4.o em_csa4.s
+../../../obj-ack//libe.a(em_csb4.o): em_csb4.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_csb4.o em_csb4.s
+../../../obj-ack//libe.a(em_cuf4.o): em_cuf4.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_cuf4.o em_cuf4.s
+../../../obj-ack//libe.a(em_cuf8.o): em_cuf8.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_cuf8.o em_cuf8.s
+../../../obj-ack//libe.a(em_cuu.o): em_cuu.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_cuu.o em_cuu.s
+../../../obj-ack//libe.a(em_dup.o): em_dup.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_dup.o em_dup.s
+../../../obj-ack//libe.a(em_dvf4.o): em_dvf4.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_dvf4.o em_dvf4.s
+../../../obj-ack//libe.a(em_dvf8.o): em_dvf8.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_dvf8.o em_dvf8.s
+../../../obj-ack//libe.a(em_dvi.o): em_dvi.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_dvi.o em_dvi.s
+../../../obj-ack//libe.a(em_dvu.o): em_dvu.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_dvu.o em_dvu.s
+../../../obj-ack//libe.a(em_error.o): em_error.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_error.o em_error.s
+../../../obj-ack//libe.a(em_exg.o): em_exg.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_exg.o em_exg.s
+../../../obj-ack//libe.a(em_fat.o): em_fat.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_fat.o em_fat.s
+../../../obj-ack//libe.a(em_fef4.o): em_fef4.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_fef4.o em_fef4.s
+../../../obj-ack//libe.a(em_fef8.o): em_fef8.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_fef8.o em_fef8.s
+../../../obj-ack//libe.a(em_fif4.o): em_fif4.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_fif4.o em_fif4.s
+../../../obj-ack//libe.a(em_fif8.o): em_fif8.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_fif8.o em_fif8.s
+../../../obj-ack//libe.a(em_fp8087.o): em_fp8087.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_fp8087.o em_fp8087.s
+../../../obj-ack//libe.a(em_gto.o): em_gto.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_gto.o em_gto.s
+../../../obj-ack//libe.a(em_hol0.o): em_hol0.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_hol0.o em_hol0.s
+../../../obj-ack//libe.a(em_iaar.o): em_iaar.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_iaar.o em_iaar.s
+../../../obj-ack//libe.a(em_ilar.o): em_ilar.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_ilar.o em_ilar.s
+../../../obj-ack//libe.a(em_inn.o): em_inn.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_inn.o em_inn.s
+../../../obj-ack//libe.a(em_ior.o): em_ior.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_ior.o em_ior.s
+../../../obj-ack//libe.a(em_isar.o): em_isar.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_isar.o em_isar.s
+../../../obj-ack//libe.a(em_lar4.o): em_lar4.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_lar4.o em_lar4.s
+../../../obj-ack//libe.a(em_loi.o): em_loi.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_loi.o em_loi.s
+../../../obj-ack//libe.a(em_mlf4.o): em_mlf4.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_mlf4.o em_mlf4.s
+../../../obj-ack//libe.a(em_mlf8.o): em_mlf8.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_mlf8.o em_mlf8.s
+../../../obj-ack//libe.a(em_mli.o): em_mli.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_mli.o em_mli.s
+../../../obj-ack//libe.a(em_mon.o): em_mon.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_mon.o em_mon.s
+../../../obj-ack//libe.a(em_ngf4.o): em_ngf4.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_ngf4.o em_ngf4.s
+../../../obj-ack//libe.a(em_ngf8.o): em_ngf8.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_ngf8.o em_ngf8.s
+../../../obj-ack//libe.a(em_ngi.o): em_ngi.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_ngi.o em_ngi.s
+../../../obj-ack//libe.a(em_nop.o): em_nop.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_nop.o em_nop.s
+../../../obj-ack//libe.a(em_print.o): em_print.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_print.o em_print.s
+../../../obj-ack//libe.a(em_rck.o): em_rck.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_rck.o em_rck.s
+../../../obj-ack//libe.a(em_rmi.o): em_rmi.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_rmi.o em_rmi.s
+../../../obj-ack//libe.a(em_rmu.o): em_rmu.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_rmu.o em_rmu.s
+../../../obj-ack//libe.a(em_rol.o): em_rol.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_rol.o em_rol.s
+../../../obj-ack//libe.a(em_ror.o): em_ror.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_ror.o em_ror.s
+../../../obj-ack//libe.a(em_sar4.o): em_sar4.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_sar4.o em_sar4.s
+../../../obj-ack//libe.a(em_sbf4.o): em_sbf4.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_sbf4.o em_sbf4.s
+../../../obj-ack//libe.a(em_sbf8.o): em_sbf8.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_sbf8.o em_sbf8.s
+../../../obj-ack//libe.a(em_sbi.o): em_sbi.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_sbi.o em_sbi.s
+../../../obj-ack//libe.a(em_set.o): em_set.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_set.o em_set.s
+../../../obj-ack//libe.a(em_sli.o): em_sli.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_sli.o em_sli.s
+../../../obj-ack//libe.a(em_sri.o): em_sri.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_sri.o em_sri.s
+../../../obj-ack//libe.a(em_sti.o): em_sti.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_sti.o em_sti.s
+../../../obj-ack//libe.a(em_stop.o): em_stop.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_stop.o em_stop.s
+../../../obj-ack//libe.a(em_trp.o): em_trp.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_trp.o em_trp.s
+../../../obj-ack//libe.a(em_unknown.o): em_unknown.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_unknown.o em_unknown.s
+../../../obj-ack//libe.a(em_xor.o): em_xor.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -Was-ack -c -o ../../../obj-ack//./ack/i386/em/em_xor.o em_xor.s
+
+
+
+clean::
+	rm -f ../../../obj-ack//./ack/i386/em/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/ack/i386/em/Makefile.in
===================================================================
--- /trunk/minix/lib/ack/i386/em/Makefile.in	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/Makefile.in	(revision 9)
@@ -0,0 +1,78 @@
+# Makefile for lib/ack/i386/em.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE -Was-ack"
+
+LIBRARIES=libe
+
+libe_FILES=" \
+	em_adf4.s \
+	em_adf8.s \
+	em_adi.s \
+	em_and.s \
+	em_blm.s \
+	em_cff4.s \
+	em_cff8.s \
+	em_cfi.s \
+	em_cfu.s \
+	em_cif4.s \
+	em_cif8.s \
+	em_cii.s \
+	em_cmf4.s \
+	em_cmf8.s \
+	em_cms.s \
+	em_com.s \
+	em_csa4.s \
+	em_csb4.s \
+	em_cuf4.s \
+	em_cuf8.s \
+	em_cuu.s \
+	em_dup.s \
+	em_dvf4.s \
+	em_dvf8.s \
+	em_dvi.s \
+	em_dvu.s \
+	em_error.s \
+	em_exg.s \
+	em_fat.s \
+	em_fef4.s \
+	em_fef8.s \
+	em_fif4.s \
+	em_fif8.s \
+	em_fp8087.s \
+	em_gto.s \
+	em_hol0.s \
+	em_iaar.s \
+	em_ilar.s \
+	em_inn.s \
+	em_ior.s \
+	em_isar.s \
+	em_lar4.s \
+	em_loi.s \
+	em_mlf4.s \
+	em_mlf8.s \
+	em_mli.s \
+	em_mon.s \
+	em_ngf4.s \
+	em_ngf8.s \
+	em_ngi.s \
+	em_nop.s \
+	em_print.s \
+	em_rck.s \
+	em_rmi.s \
+	em_rmu.s \
+	em_rol.s \
+	em_ror.s \
+	em_sar4.s \
+	em_sbf4.s \
+	em_sbf8.s \
+	em_sbi.s \
+	em_set.s \
+	em_sli.s \
+	em_sri.s \
+	em_sti.s \
+	em_stop.s \
+	em_trp.s \
+	em_unknown.s \
+	em_xor.s"
+
+TYPE=ack
Index: /trunk/minix/lib/ack/i386/em/byte_order.h
===================================================================
--- /trunk/minix/lib/ack/i386/em/byte_order.h	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/byte_order.h	(revision 9)
@@ -0,0 +1,6 @@
+#define CHAR_UNSIGNED	0
+#define MSB_AT_LOW_ADDRESS	0
+#define MSW_AT_LOW_ADDRESS	0
+#define FL_MSB_AT_LOW_ADDRESS	0
+#define FL_MSW_AT_LOW_ADDRESS	0
+#define FL_MSL_AT_LOW_ADDRESS	0
Index: /trunk/minix/lib/ack/i386/em/em_adf4.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_adf4.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_adf4.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .adf4
+
+	.sect .text
+.adf4:
+	mov	bx,sp
+	flds	4(bx)
+	fadds	8(bx)
+	fstps	8(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_adf8.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_adf8.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_adf8.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .adf8
+
+	.sect .text
+.adf8:
+	mov	bx,sp
+	fldd	4(bx)
+	faddd	12(bx)
+	fstpd	12(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_adi.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_adi.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_adi.s	(revision 9)
@@ -0,0 +1,18 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .adi
+
+	! #bytes in ecx , top of stack in eax
+	.sect .text
+.adi:
+	pop     ebx              ! return address
+	cmp     ecx,4
+	jne     9f
+	pop     ecx
+	add     eax,ecx
+	jmp     ebx
+9:
+.extern	EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push	ebx
+	jmp     .trp
Index: /trunk/minix/lib/ack/i386/em/em_and.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_and.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_and.s	(revision 9)
@@ -0,0 +1,20 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define	.and
+
+	! #bytes in ecx
+	! save edi; it might be a register variable
+
+	.sect .text
+.and:
+	pop	ebx		! return address
+	mov	edx,edi
+	mov	edi,esp
+	add	edi,ecx
+	sar	ecx,2
+1:
+	pop	eax
+	and	eax,(edi)
+	stos
+	loop	1b
+	mov	edi,edx
+	jmp	ebx
Index: /trunk/minix/lib/ack/i386/em/em_blm.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_blm.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_blm.s	(revision 9)
@@ -0,0 +1,16 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .blm
+
+	! ecx: count in words
+.blm:
+	mov	ebx,esp
+	mov	eax,esi
+	mov	edx,edi
+	mov	edi,4(ebx)
+	mov	esi,8(ebx)
+	rep	movs
+	mov	esi,eax
+	mov	edi,edx
+	ret	8
+
Index: /trunk/minix/lib/ack/i386/em/em_cff4.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_cff4.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_cff4.s	(revision 9)
@@ -0,0 +1,19 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cff4
+
+	.sect .text
+.cff4:
+	mov	bx,sp
+	fldd	4(bx)
+	fstcw	4(bx)
+	wait
+	mov	dx,4(bx)
+	and	4(bx),0xf3ff	! set to rounding mode
+	wait
+	fldcw	4(bx)
+	fstps	8(bx)
+	mov	4(bx),dx
+	wait
+	fldcw	4(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_cff8.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_cff8.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_cff8.s	(revision 9)
@@ -0,0 +1,10 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cff8
+
+	.sect .text
+.cff8:
+	mov	bx,sp
+	flds	4(bx)
+	fstpd	4(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_cfi.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_cfi.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_cfi.s	(revision 9)
@@ -0,0 +1,27 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cfi
+
+	.sect .text
+.cfi:
+	mov	bx,sp
+	fstcw	4(bx)
+	wait
+	mov	dx,4(bx)
+	or	4(bx),0xc00	! truncating mode
+	wait
+	fldcw	4(bx)
+	cmp	8(bx),4
+	jne	2f
+				! loc 4 loc ? cfi
+	flds	12(bx)
+	fistpl	12(bx)
+1:
+	mov	4(bx),dx
+	wait
+	fldcw	4(bx)
+	ret
+2:
+				! loc 8 loc ? cfi
+	fldd	12(bx)
+	fistpl	16(bx)
+	jmp	1b
Index: /trunk/minix/lib/ack/i386/em/em_cfu.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_cfu.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_cfu.s	(revision 9)
@@ -0,0 +1,38 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cfu
+
+	.sect .text
+.cfu:
+	mov	bx,sp
+	fstcw	4(bx)
+	wait
+	mov	dx,4(bx)
+	or	4(bx),0xc00	! truncating mode
+	wait
+	fldcw	4(bx)
+	cmp	8(bx),4
+	jne	2f
+				! loc 4 loc ? cfu
+	flds	12(bx)
+	fabs			! ???
+	fiaddl	(bigmin)
+	fistpl	12(bx)
+	wait
+	mov	ax,12(bx)
+	sub	ax,(bigmin)
+	mov	12(bx),ax
+1:
+	mov	4(bx),dx
+	wait
+	fldcw	4(bx)
+	ret
+2:
+				! loc 8 loc ? cfu
+	fldd	12(bx)
+	fabs			! ???
+	fiaddl	(bigmin)
+	fistpl	16(bx)
+	mov	ax,16(bx)
+	sub	ax,(bigmin)
+	mov	16(bx),ax
+	jmp	1b
Index: /trunk/minix/lib/ack/i386/em/em_cif4.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_cif4.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_cif4.s	(revision 9)
@@ -0,0 +1,10 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cif4
+
+	.sect .text
+.cif4:
+	mov	bx,sp
+	fildl	8(bx)
+	fstps	8(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_cif8.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_cif8.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_cif8.s	(revision 9)
@@ -0,0 +1,10 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cif8
+
+	.sect .text
+.cif8:
+	mov	bx,sp
+	fildl	8(bx)
+	fstpd	4(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_cii.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_cii.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_cii.s	(revision 9)
@@ -0,0 +1,31 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cii
+
+.sect .text
+.cii:
+	pop     ebx              ! return address
+				! pop     ecx, dest. size
+				! pop     edx, src. size
+				! eax is source
+	cmp	edx,1
+	jne	2f
+	movsxb	eax,al
+	mov	edx,4
+	jmp	1f
+2:
+	cmp	edx,2
+	jne	1f
+	cwde			! convert from 2 to 4 bytes
+	mov	edx,4
+1:
+	cmp     edx,ecx
+	jne     9f
+	cmp	edx,4
+	jne	9f
+	jmp     ebx
+9:
+.extern EILLINS
+.extern .fat
+	mov     eax,EILLINS
+	push    eax
+	jmp     .fat
Index: /trunk/minix/lib/ack/i386/em/em_cmf4.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_cmf4.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_cmf4.s	(revision 9)
@@ -0,0 +1,22 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cmf4
+
+	.sect .text
+.cmf4:
+	mov	bx,sp
+	xor	cx,cx
+	flds	8(bx)
+	flds	4(bx)
+	fcompp			! compare and pop operands
+	fstsw	ax
+	wait
+	sahf
+	je	1f
+	jb	2f
+	dec	cx
+	jmp	1f
+2:
+	inc	cx
+1:
+	mov	ax,cx
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_cmf8.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_cmf8.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_cmf8.s	(revision 9)
@@ -0,0 +1,22 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cmf8
+
+	.sect .text
+.cmf8:
+	mov	bx,sp
+	xor	cx,cx
+	fldd	12(bx)
+	fldd	4(bx)
+	fcompp			! compare and pop operands
+	fstsw	ax
+	wait
+	sahf
+	je	1f
+	jb	2f
+	dec	cx
+	jmp	1f
+2:
+	inc	cx
+1:
+	mov	ax,cx
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_cms.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_cms.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_cms.s	(revision 9)
@@ -0,0 +1,23 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cms
+
+	! #bytes in ecx
+	.sect .text
+.cms:
+	pop     ebx              ! return address
+	mov     edx,esp
+	push	esi
+	push	edi
+	mov     esi,edx
+	add     edx,ecx
+	mov     edi,edx
+	add     edx,ecx
+	sar     ecx,2
+	repe cmps
+	je      1f
+	inc     ecx
+1:
+	pop	edi
+	pop	esi
+	mov     esp,edx
+	jmp     ebx
Index: /trunk/minix/lib/ack/i386/em/em_com.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_com.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_com.s	(revision 9)
@@ -0,0 +1,14 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define	.com
+
+	! #bytes in ecx
+	.sect .text
+.com:
+	mov	ebx,esp
+	add	ebx,4
+	sar	ecx,2
+1:
+	not	(ebx)
+	add	ebx,4
+	loop	1b
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_csa4.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_csa4.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_csa4.s	(revision 9)
@@ -0,0 +1,27 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .csa4
+
+.sect .text
+.csa4:
+				! ebx, descriptor address
+				! eax, index
+	mov     edx,(ebx)         ! default
+	sub     eax,4(ebx)
+	cmp     eax,8(ebx)
+	ja      1f
+	sal     eax,2
+	add	ebx,eax
+	mov     ebx,12(ebx)
+	test    ebx,ebx
+	jnz     2f
+1:
+	mov     ebx,edx
+	test    ebx,ebx
+	jnz     2f
+.extern ECASE
+.extern .fat
+	mov     eax,ECASE
+	push    eax
+	jmp     .fat
+2:
+	jmp     ebx
Index: /trunk/minix/lib/ack/i386/em/em_csb4.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_csb4.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_csb4.s	(revision 9)
@@ -0,0 +1,29 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .csb4
+
+.sect .text
+.csb4:
+				!ebx, descriptor address
+				!eax,  index
+	mov	edx,(ebx)
+	mov	ecx,4(ebx)
+1:
+	add	ebx,8
+	dec     ecx
+	jl      4f
+	cmp     eax,(ebx)
+	jne     1b
+	mov	ebx,4(ebx)
+2:
+	test    ebx,ebx
+	jnz     3f
+.extern ECASE
+.extern .fat
+	mov     eax,ECASE
+	push    eax
+	jmp     .fat
+3:
+	jmp     ebx
+4:
+	mov	ebx,edx
+	jmp	2b
Index: /trunk/minix/lib/ack/i386/em/em_cuf4.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_cuf4.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_cuf4.s	(revision 9)
@@ -0,0 +1,15 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cuf4
+
+	.sect .text
+.cuf4:
+	mov	bx,sp
+	fildl	8(bx)
+	cmp	8(bx),0
+	jge	1f
+	fisubl	(bigmin)
+	fisubl	(bigmin)
+1:
+	fstps	8(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_cuf8.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_cuf8.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_cuf8.s	(revision 9)
@@ -0,0 +1,15 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cuf8
+
+	.sect .text
+.cuf8:
+	mov	bx,sp
+	fildl	8(bx)
+	cmp	8(bx),0
+	jge	1f
+	fisubl	(bigmin)
+	fisubl	(bigmin)
+1:
+	fstpd	4(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_cuu.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_cuu.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_cuu.s	(revision 9)
@@ -0,0 +1,22 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .ciu
+.define .cui
+.define .cuu
+
+.sect .text
+.ciu:
+.cui:
+.cuu:
+	pop     ebx              ! return address
+				! pop     ecx, dest. size
+				! pop     edx, source size
+				! eax is source
+	cmp     edx,ecx
+	jne     8f
+	jmp     ebx
+8:
+.extern EILLINS
+.extern .fat
+	mov     eax,EILLINS
+	push    eax
+	jmp     .fat
Index: /trunk/minix/lib/ack/i386/em/em_dup.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_dup.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_dup.s	(revision 9)
@@ -0,0 +1,17 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define	.dup
+
+	! #bytes in ecx
+	.sect .text
+.dup:
+	pop	ebx		! return address
+	mov	eax,esi
+	mov	edx,edi
+	mov	esi,esp
+	sub	esp,ecx
+	mov	edi,esp
+	sar	ecx,2
+	rep movs
+	mov	esi,eax
+	mov	edi,edx
+	jmp	ebx
Index: /trunk/minix/lib/ack/i386/em/em_dvf4.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_dvf4.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_dvf4.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .dvf4
+
+	.sect .text
+.dvf4:
+	mov	bx,sp
+	flds	8(bx)
+	fdivs	4(bx)
+	fstps	8(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_dvf8.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_dvf8.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_dvf8.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .dvf8
+
+	.sect .text
+.dvf8:
+	mov	bx,sp
+	fldd	12(bx)
+	fdivd	4(bx)
+	fstpd	12(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_dvi.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_dvi.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_dvi.s	(revision 9)
@@ -0,0 +1,21 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .dvi
+
+        ! #bytes in eax
+	.sect .text
+.dvi:
+        pop     ebx              ! return address
+        cmp     eax,4
+        jne     1f
+        pop     eax
+        cwd
+        pop     ecx
+        idiv    ecx
+        push    eax
+        jmp     ebx
+1:
+.extern EODDZ
+.extern .trp
+        mov     eax,EODDZ
+        push    ebx
+        jmp     .trp
Index: /trunk/minix/lib/ack/i386/em/em_dvu.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_dvu.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_dvu.s	(revision 9)
@@ -0,0 +1,21 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .dvu
+
+	! #bytes in eax
+	.sect .text
+.dvu:
+	pop     ebx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	xor     edx,edx
+	pop     ecx
+	div     ecx
+	push    eax
+	jmp     ebx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    ebx
+	jmp     .trp
Index: /trunk/minix/lib/ack/i386/em/em_error.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_error.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_error.s	(revision 9)
@@ -0,0 +1,32 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .error
+.define .Xtrp
+
+	! eax is trap number
+	! all registers must be saved
+	! because return is possible
+	! May only be called with error no's <16
+.sect .text
+.error:
+	mov  ecx,eax
+	mov  ebx,1
+	sal  ebx,cl
+.extern .ignmask
+.extern .trp
+	test ebx,(.ignmask)
+	jne  2f
+	call    .trp
+2:
+	ret
+
+.Xtrp:
+	pusha
+	cmp	eax,16
+	jge	1f
+	call	.error
+	popa
+	ret
+1:
+	call	.trp
+	popa
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_exg.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_exg.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_exg.s	(revision 9)
@@ -0,0 +1,22 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .exg
+
+	! #bytes in ecx
+.sect .text
+.exg:
+	push	edi
+	mov	edi,esp
+	add	edi,8
+	mov	ebx,edi
+	add	ebx,ecx
+	sar     ecx,2
+1:
+	mov	eax,(ebx)
+	xchg	eax,(edi)
+	mov	(ebx),eax
+	add	edi,4
+	add	ebx,4
+	loop	1b
+2:
+	pop	edi
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_fat.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_fat.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_fat.s	(revision 9)
@@ -0,0 +1,10 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .fat
+
+.fat:
+.extern .trp
+.extern .stop
+	call    .trp
+	call    .stop
+	! no return
Index: /trunk/minix/lib/ack/i386/em/em_fef4.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_fef4.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_fef4.s	(revision 9)
@@ -0,0 +1,49 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .fef4
+
+	.sect .text
+.fef4:
+				! this could be simpler, if only the
+				! fxtract instruction was emulated properly
+	mov	bx,sp
+	mov	ax,8(bx)
+	and	ax,0x7f800000
+	je	1f		! zero exponent
+	shr	ax,23
+	sub	ax,126
+	mov	cx,ax		! exponent in cx
+	mov	ax,8(bx)
+	and	ax,0x807fffff
+	or	ax,0x3f000000	! load -1 exponent
+	mov	bx,4(bx)
+	mov	4(bx),ax
+	mov	(bx),cx
+	ret
+1:				! we get here on zero exp
+	mov	ax,8(bx)
+	and	ax,0x007fffff
+	jne	1f		! zero result
+	mov	bx,4(bx)
+	mov	(bx),ax
+	mov	4(bx),ax
+	ret
+1:				! otherwise unnormalized number
+	mov	cx,8(bx)
+	and	cx,0x807fffff
+	mov	dx,cx
+	and	cx,0x80000000
+	mov	ax,-125
+2:
+	test	dx,0x800000
+	jne	1f
+	dec	ax
+	shl	dx,1
+	or	dx,cx
+	jmp	2b
+1:
+	mov	bx,4(bx)
+	mov	(bx),ax
+	and	dx,0x807fffff
+	or	dx,0x3f000000	! load -1 exponent
+	mov	4(bx),dx
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_fef8.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_fef8.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_fef8.s	(revision 9)
@@ -0,0 +1,56 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .fef8
+
+	.sect .text
+.fef8:
+				! this could be simpler, if only the
+				! fxtract instruction was emulated properly
+	mov	bx,sp
+	mov	ax,12(bx)
+	and	ax,0x7ff00000
+	je	1f		! zero exponent
+	shr	ax,20
+	sub	ax,1022
+	mov	cx,ax		! exponent in cx
+	mov	ax,12(bx)
+	and	ax,0x800fffff
+	or	ax,0x3fe00000	! load -1 exponent
+	mov	dx,8(bx)
+	mov	bx,4(bx)
+	mov	4(bx),dx
+	mov	8(bx),ax
+	mov	(bx),cx
+	ret
+1:				! we get here on zero exp
+	mov	ax,12(bx)
+	and	ax,0xfffff
+	or	ax,8(bx)
+	jne	1f		! zero result
+	mov	bx,4(bx)
+	mov	(bx),ax
+	mov	4(bx),ax
+	mov	8(bx),ax
+	ret
+1:				! otherwise unnormalized number
+	mov	cx,12(bx)
+	and	cx,0x800fffff
+	mov	dx,cx
+	and	cx,0x80000000
+	mov	ax,-1021
+2:
+	test	dx,0x100000
+	jne	1f
+	dec	ax
+	shl	8(bx),1
+	rcl	dx,1
+	or	dx,cx
+	jmp	2b
+1:
+	and	dx,0x800fffff
+	or	dx,0x3fe00000	! load -1 exponent
+	mov	cx,8(bx)
+	mov	bx,4(bx)
+	mov	(bx),ax
+	mov	8(bx),dx
+	mov	4(bx),cx
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_fif4.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_fif4.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_fif4.s	(revision 9)
@@ -0,0 +1,37 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .fif4
+
+	.sect .text
+.fif4:
+	mov	bx,sp
+	flds	8(bx)
+	fmuls	12(bx)		! multiply
+	fld	st		! copy result
+	ftst			! test sign; handle negative separately
+	fstsw	ax
+	wait
+	sahf			! result of test in condition codes
+	jb	1f
+	frndint			! this one rounds (?)
+	fcom	st(1)		! compare with original; if <=, then OK
+	fstsw	ax
+	wait
+	sahf
+	jbe	2f
+	fisubs	(one)		! else subtract 1
+	jmp	2f
+1:				! here, negative case
+	frndint			! this one rounds (?)
+	fcom	st(1)		! compare with original; if >=, then OK
+	fstsw	ax
+	wait
+	sahf
+	jae	2f
+	fiadds	(one)		! else add 1
+2:
+	fsub	st(1),st	! subtract integer part
+	mov	bx,4(bx)
+	fstps	(bx)
+	fstps	4(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_fif8.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_fif8.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_fif8.s	(revision 9)
@@ -0,0 +1,37 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .fif8
+
+	.sect .text
+.fif8:
+	mov	bx,sp
+	fldd	8(bx)
+	fmuld	16(bx)		! multiply
+	fld	st		! and copy result
+	ftst			! test sign; handle negative separately
+	fstsw	ax
+	wait
+	sahf			! result of test in condition codes
+	jb	1f
+	frndint			! this one rounds (?)
+	fcom	st(1)		! compare with original; if <=, then OK
+	fstsw	ax
+	wait
+	sahf
+	jbe	2f
+	fisubs	(one)		! else subtract 1
+	jmp	2f
+1:				! here, negative case
+	frndint			! this one rounds (?)
+	fcom	st(1)		! compare with original; if >=, then OK
+	fstsw	ax
+	wait
+	sahf
+	jae	2f
+	fiadds	(one)		! else add 1
+2:
+	fsub	st(1),st	! subtract integer part
+	mov	bx,4(bx)
+	fstpd	(bx)
+	fstpd	8(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_fp8087.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_fp8087.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_fp8087.s	(revision 9)
@@ -0,0 +1,10 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define one, bigmin
+
+	.sect .rom
+one:
+	.data2	1
+two:
+	.data2	2
+bigmin:
+	.data4 	-2147483648
Index: /trunk/minix/lib/ack/i386/em/em_gto.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_gto.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_gto.s	(revision 9)
@@ -0,0 +1,8 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .gto
+
+.gto:
+	mov     ebp,8(ebx)
+	mov     esp,4(ebx)
+	jmp     (ebx)
Index: /trunk/minix/lib/ack/i386/em/em_hol0.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_hol0.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_hol0.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+.define hol0
+.sect .data
+hol0:
+	.data4	0, 0
+	.data4	0, 0
Index: /trunk/minix/lib/ack/i386/em/em_iaar.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_iaar.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_iaar.s	(revision 9)
@@ -0,0 +1,18 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .iaar
+
+.iaar:
+	pop     ecx
+	pop     edx
+	cmp     edx,4
+.extern .unknown
+	jne     .unknown
+	pop     ebx     ! descriptor address
+	pop     eax     ! index
+	sub     eax,(ebx)
+	mul     8(ebx)
+	pop	ebx	! array base
+	add     ebx,eax
+	push	ecx
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_ilar.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_ilar.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_ilar.s	(revision 9)
@@ -0,0 +1,15 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .ilar
+
+.ilar:
+	pop     ecx
+	pop     edx
+.extern .unknown
+	cmp     edx,4
+	jne     .unknown
+	pop     ebx      ! descriptor address
+	pop     eax      ! index
+	push    ecx
+.extern .lar4
+	jmp    .lar4
Index: /trunk/minix/lib/ack/i386/em/em_inn.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_inn.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_inn.s	(revision 9)
@@ -0,0 +1,32 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .inn
+
+	! #bytes in ecx
+	! bit # in eax
+.inn:
+	xor     edx,edx
+	mov     ebx,8
+	div     ebx
+	mov     ebx,esp
+	add	ebx,4
+	add     ebx,eax
+	cmp     eax,ecx
+	jae     1f
+	movb	al,(ebx)
+	mov	ebx,edx
+	testb   al,bits(ebx)
+	jz      1f
+	mov	eax,1
+	jmp	2f
+1:
+	xor	eax,eax
+2:
+	pop	ebx
+	add     esp,ecx
+	! eax is result
+	jmp     ebx
+
+	.sect .rom
+bits:
+	.data1 1,2,4,8,16,32,64,128
Index: /trunk/minix/lib/ack/i386/em/em_ior.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_ior.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_ior.s	(revision 9)
@@ -0,0 +1,18 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define	.ior
+
+	! #bytes in ecx
+.ior:
+	pop	ebx		! return address
+	mov	edx,edi
+	mov	edi,esp
+	add	edi,ecx
+	sar	ecx,2
+1:
+	pop	eax
+	or	eax,(edi)
+	stos
+	loop	1b
+	mov	edi,edx
+	jmp	ebx
Index: /trunk/minix/lib/ack/i386/em/em_isar.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_isar.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_isar.s	(revision 9)
@@ -0,0 +1,15 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .isar
+
+.isar:
+	pop     ecx
+	pop     eax
+	cmp     eax,4
+.extern .unknown
+	jne     .unknown
+	pop     ebx      ! descriptor address
+	pop     eax      ! index
+	push    ecx
+.extern .sar4
+	jmp    .sar4
Index: /trunk/minix/lib/ack/i386/em/em_lar4.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_lar4.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_lar4.s	(revision 9)
@@ -0,0 +1,37 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .lar4
+
+.lar4:
+				! ebx, descriptor address
+				! eax, index
+	sub     eax,(ebx)
+	mov     ecx,8(ebx)
+	imul    ecx
+	pop	ebx
+	pop	edx		! base address
+	add     edx,eax
+	sar     ecx,1
+	jnb     1f
+	xor     eax,eax
+	movb	al,(edx)
+	push    eax
+	jmp     ebx
+1:
+	sar     ecx,1
+	jnb     1f
+	xor     eax,eax
+	o16 mov	ax,(edx)
+	push    eax
+	jmp     ebx
+1:
+	xchg	edx,esi		! saved esi
+	mov	eax,ecx
+	sal	eax,2
+	sub     esp,eax
+	mov	eax,edi		! save edi
+	mov     edi,esp
+	rep movs
+	mov	edi,eax
+	mov	esi,edx
+	jmp     ebx
Index: /trunk/minix/lib/ack/i386/em/em_loi.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_loi.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_loi.s	(revision 9)
@@ -0,0 +1,44 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .loi
+.define .los
+
+	! #bytes in ecx
+	! address in ebx
+	! save esi/edi. they might be register variables
+.los:
+	pop	edx
+	mov     eax,ecx
+	sar     ecx,1
+	jnb     1f
+	movsxb	eax,(ebx)
+	push    eax
+	jmp     edx
+1:
+	sar     ecx,1
+	jnb     1f
+	movsx	eax,(ebx)
+	push    eax
+	jmp     edx
+1:
+	push	edx
+	mov	edx,esi
+	mov	esi,ebx
+	pop	ebx
+	sub     esp,eax
+	jmp	1f
+
+.loi:
+	! only called with size >= 4
+	mov	edx,esi
+	mov	esi,ebx
+	pop	ebx
+	sub	esp,ecx
+	sar	ecx,2
+1:
+	mov	eax,edi
+	mov     edi,esp
+	rep movs
+	mov	esi,edx
+	mov	edi,eax
+	jmp     ebx
Index: /trunk/minix/lib/ack/i386/em/em_mlf4.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_mlf4.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_mlf4.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .mlf4
+
+	.sect .text
+.mlf4:
+	mov	bx,sp
+	flds	4(bx)
+	fmuls	8(bx)
+	fstps	8(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_mlf8.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_mlf8.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_mlf8.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .mlf8
+
+	.sect .text
+.mlf8:
+	mov	bx,sp
+	fldd	4(bx)
+	fmuld	12(bx)
+	fstpd	12(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_mli.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_mli.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_mli.s	(revision 9)
@@ -0,0 +1,20 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .mli
+
+	! #bytes in eax
+.mli:
+	pop     ebx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	pop     ecx
+	mul     ecx
+	push    eax
+	jmp     ebx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    ebx
+	jmp     .trp
Index: /trunk/minix/lib/ack/i386/em/em_mon.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_mon.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_mon.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .mon
+
+.mon:
+.extern .stop
+	call    .stop
Index: /trunk/minix/lib/ack/i386/em/em_ngf4.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_ngf4.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_ngf4.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .ngf4
+
+	.sect .text
+.ngf4:
+	mov	bx,sp
+	flds	4(bx)
+	fchs
+	fstps	4(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_ngf8.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_ngf8.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_ngf8.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .ngf8
+
+	.sect .text
+.ngf8:
+	mov	bx,sp
+	fldd	4(bx)
+	fchs
+	fstpd	4(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_ngi.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_ngi.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_ngi.s	(revision 9)
@@ -0,0 +1,19 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .ngi
+
+	! #bytes in eax
+.ngi:
+	pop     ebx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     ecx
+	neg     ecx
+	push    ecx
+	jmp     ebx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    ebx
+	jmp     .trp
Index: /trunk/minix/lib/ack/i386/em/em_nop.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_nop.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_nop.s	(revision 9)
@@ -0,0 +1,10 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .nop
+.extern printd, printc, hol0
+
+.nop:
+	mov     eax,(hol0)
+	call    printd
+	movb    al,'\n'
+	jmp     printc
Index: /trunk/minix/lib/ack/i386/em/em_print.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_print.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_print.s	(revision 9)
@@ -0,0 +1,47 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define	printc,printd,prints
+
+	! argument in eax
+	! uses ebx
+prints:
+	xchg	eax,ebx
+1:
+	movb	al,(ebx)
+	inc	ebx
+	testb	al,al
+	jz	2f
+	call	printc
+	jmp	1b
+2:
+	ret
+
+	! argument in eax
+	! uses ecx and edx
+printd:
+	xor	edx,edx
+	mov	ecx,10
+	div	ecx
+	test	eax,eax
+	jz	1f
+	push	edx
+	call	printd
+	pop	edx
+1:
+	xchg	eax,edx
+	addb	al,'0'
+
+	! argument in eax
+printc:
+	push	eax
+	mov	ebx,esp
+	mov	eax,1
+	push	eax
+	push	ebx
+	push	eax
+	call	__write
+	pop	ebx
+	pop	ebx
+	pop	ebx
+	pop	ebx
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_rck.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_rck.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_rck.s	(revision 9)
@@ -0,0 +1,20 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .rck
+
+	! descriptor address in ebx
+	! value in eax, must be left there
+.rck:
+	cmp     eax,(ebx)
+	jl      2f
+	cmp     eax,4(ebx)
+	jg      2f
+	ret
+2:
+	push    eax
+.extern ERANGE
+.extern .error
+	mov     eax,ERANGE
+	call    .error
+	pop     eax
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_rmi.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_rmi.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_rmi.s	(revision 9)
@@ -0,0 +1,21 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .rmi
+
+	! #bytes in eax
+.rmi:
+	pop     ebx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	cwd
+	pop     ecx
+	idiv    ecx
+	push    edx
+	jmp     ebx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    ebx
+	jmp     .trp
Index: /trunk/minix/lib/ack/i386/em/em_rmu.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_rmu.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_rmu.s	(revision 9)
@@ -0,0 +1,21 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .rmu
+
+	! #bytes in eax
+.rmu:
+	pop     ebx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	xor     edx,edx
+	pop     ecx
+	idiv    ecx
+	push    edx
+	jmp     ebx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    ebx
+	jmp     .trp
Index: /trunk/minix/lib/ack/i386/em/em_rol.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_rol.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_rol.s	(revision 9)
@@ -0,0 +1,20 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .rol
+
+	! #bytes in eax
+.rol:
+	pop     edx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	pop     ecx
+	rol     eax,cl
+	push    eax
+	jmp     edx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    edx
+	jmp     .trp
Index: /trunk/minix/lib/ack/i386/em/em_ror.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_ror.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_ror.s	(revision 9)
@@ -0,0 +1,20 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .ror
+
+	! #bytes in eax
+.ror:
+	pop     edx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	pop     ecx
+	ror     eax,cl
+	push    eax
+	jmp     edx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    edx
+	jmp     .trp
Index: /trunk/minix/lib/ack/i386/em/em_sar4.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_sar4.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_sar4.s	(revision 9)
@@ -0,0 +1,33 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .sar4
+
+.sar4:
+				! ebx, descriptor address
+				! eax, index
+	sub     eax,(ebx)
+	mov     ecx,8(ebx)
+	imul    ecx
+	pop	ebx
+	pop	edx		! base address
+	add     edx,eax
+	sar     ecx,1
+	jnb     1f
+	pop     eax
+	movb	(edx),al
+	jmp     ebx
+1:
+	sar     ecx,1
+	jnb     1f
+	pop     eax
+	o16 mov (edx),ax
+	jmp     ebx
+1:
+	xchg	edi,edx		! edi = base address, edx is saved edi
+	mov	eax,esi
+	mov     esi,esp
+	rep movs
+	mov     esp,esi
+	mov	esi,eax
+	mov	edi,edx
+	jmp     ebx
Index: /trunk/minix/lib/ack/i386/em/em_sbf4.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_sbf4.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_sbf4.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .sbf4
+
+	.sect .text
+.sbf4:
+	mov	bx,sp
+	flds	8(bx)
+	fsubs	4(bx)
+	fstps	8(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_sbf8.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_sbf8.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_sbf8.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .sbf8
+
+	.sect .text
+.sbf8:
+	mov	bx,sp
+	fldd	12(bx)
+	fsubd	4(bx)
+	fstpd	12(bx)
+	wait
+	ret
Index: /trunk/minix/lib/ack/i386/em/em_sbi.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_sbi.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_sbi.s	(revision 9)
@@ -0,0 +1,19 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .sbi
+
+	! #bytes in ecx , top of stack in eax
+.sbi:
+	pop     ebx              ! return subress
+	cmp     ecx,4
+	jne     1f
+	pop     ecx
+	sub     eax,ecx
+	neg     eax
+	jmp     ebx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    ebx
+	jmp     .trp
Index: /trunk/minix/lib/ack/i386/em/em_set.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_set.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_set.s	(revision 9)
@@ -0,0 +1,42 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .set
+
+	! #bytes in ecx
+	! bit # in eax
+.set:
+	pop     ebx              ! return address
+	xor     edx,edx
+!ifdef create set
+	sub	esp,ecx
+	push	ebx
+	push	edi
+	mov     ebx,esp
+	xor	edi,edi
+	sar	ecx,2
+1:
+	mov     8(ebx)(edi),edx
+	add	edi,4
+	loop	1b
+!endif
+	mov     ebx,8
+	div     ebx
+	cmp     eax,edi
+	jae     2f
+	mov	edi,edx
+	movb	dl,bits(edi)
+	mov     edi,esp
+	add     edi,eax
+	orb     8(edi),dl
+	pop	edi
+	ret
+2:
+.extern ESET
+.extern .trp
+	pop	edi
+	mov     eax,ESET
+	jmp     .trp
+
+	.sect .rom
+bits:
+	.data1   1,2,4,8,16,32,64,128
Index: /trunk/minix/lib/ack/i386/em/em_sli.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_sli.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_sli.s	(revision 9)
@@ -0,0 +1,20 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .sli
+
+	! #bytes in eax
+.sli:
+	pop     edx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	pop     ecx
+	sal     eax,cl
+	push    eax
+	jmp     edx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    edx
+	jmp     .trp
Index: /trunk/minix/lib/ack/i386/em/em_sri.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_sri.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_sri.s	(revision 9)
@@ -0,0 +1,20 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .sri
+
+	! #bytes in eax
+.sri:
+	pop     edx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	pop     ecx
+	sar     eax,cl
+	push    eax
+	jmp     edx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    edx
+	jmp     .trp
Index: /trunk/minix/lib/ack/i386/em/em_sti.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_sti.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_sti.s	(revision 9)
@@ -0,0 +1,41 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .sti
+.define .sts
+
+	! #bytes in ecx
+	! address in ebx
+	! save edi/esi. they might be register variables
+.sts:
+	pop	edx
+	sar     ecx,1
+	jnb     1f
+	pop     eax
+	movb	(ebx),al
+	jmp     edx
+1:
+	sar     ecx,1
+	jnb     1f
+	pop     eax
+	o16 mov	(ebx),ax
+	jmp     edx
+1:
+	push	edx
+	mov	edx,edi
+	mov	edi,ebx
+	pop	ebx
+	jmp	1f
+.sti:
+	! only called with count >> 4
+	mov	edx,edi
+	mov	edi,ebx
+	pop	ebx
+	sar	ecx,2
+1:
+	mov	eax,esi
+	mov     esi,esp
+	rep movs
+	mov     esp,esi
+	mov	edi,edx
+	mov	esi,eax
+	jmp     ebx
Index: /trunk/minix/lib/ack/i386/em/em_stop.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_stop.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_stop.s	(revision 9)
@@ -0,0 +1,5 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .stop
+.stop:
+	jmp	___exit
Index: /trunk/minix/lib/ack/i386/em/em_trp.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_trp.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_trp.s	(revision 9)
@@ -0,0 +1,18 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .trp
+.extern .trppc, .stop
+
+		! eax is trap number
+.trp:
+	xor     ebx,ebx
+	xchg    ebx,(.trppc)
+	test    ebx,ebx
+	jz      2f
+	push    eax
+	call    ebx
+	pop     eax
+	ret
+2:
+	push	eax
+	call    .stop
Index: /trunk/minix/lib/ack/i386/em/em_unknown.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_unknown.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_unknown.s	(revision 9)
@@ -0,0 +1,9 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .unknown
+.extern EILLINS, .fat
+
+.unknown:
+	mov  eax,EILLINS
+	push eax
+	jmp  .fat
Index: /trunk/minix/lib/ack/i386/em/em_xor.s
===================================================================
--- /trunk/minix/lib/ack/i386/em/em_xor.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/em/em_xor.s	(revision 9)
@@ -0,0 +1,18 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define	.xor
+
+	! #bytes in ecx
+.xor:
+	pop	ebx		! return address
+	mov	edx,edi
+	mov	edi,esp
+	add	edi,ecx
+	sar	ecx,2
+1:
+	pop	eax
+	xor	eax,(edi)
+	stos
+	loop	1b
+	mov	edi,edx
+	jmp	ebx
Index: /trunk/minix/lib/ack/i386/head/Makedepend-ack
===================================================================
--- /trunk/minix/lib/ack/i386/head/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/ack/i386/head/Makedepend-ack	(revision 9)
@@ -0,0 +1,4 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc  -E' em_head.s | sed -e 's:^\(.\):../../../obj-ack//./ack/i386/head/\1:' >> .depend-ack
Index: /trunk/minix/lib/ack/i386/head/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/ack/i386/head/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/ack/i386/head/Makedepend-gnu	(revision 9)
@@ -0,0 +1,3 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
Index: /trunk/minix/lib/ack/i386/head/Makefile
===================================================================
--- /trunk/minix/lib/ack/i386/head/Makefile	(revision 9)
+++ /trunk/minix/lib/ack/i386/head/Makefile	(revision 9)
@@ -0,0 +1,40 @@
+#Generated from ./ack/i386/head/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../../generate.sh ./ack/i386/head ../../../obj-ack/ ../../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../../generate.sh ./ack/i386/head ../../../obj-ack/ ../../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../../../obj-ack//libe.a
+
+../../../obj-ack//libe.a: ../../../obj-ack//libe.a(em_head.o)
+
+../../../obj-ack//libe.a:
+	ar cr ../../../obj-ack//libe.a ../../../obj-ack//./ack/i386/head/*.o
+	rm ../../../obj-ack//./ack/i386/head/*.o
+
+../../../obj-ack//libe.a(em_head.o): em_head.s
+	cc  -c -o ../../../obj-ack//./ack/i386/head/em_head.o em_head.s
+
+
+
+clean::
+	rm -f ../../../obj-ack//./ack/i386/head/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/ack/i386/head/Makefile.in
===================================================================
--- /trunk/minix/lib/ack/i386/head/Makefile.in	(revision 9)
+++ /trunk/minix/lib/ack/i386/head/Makefile.in	(revision 9)
@@ -0,0 +1,9 @@
+# Makefile for lib/ack/i386/head.
+
+#ASFLAGS = -I.
+
+LIBRARIES=libe
+
+libe_FILES=em_head.s
+
+TYPE=ack
Index: /trunk/minix/lib/ack/i386/head/em_abs.h
===================================================================
--- /trunk/minix/lib/ack/i386/head/em_abs.h	(revision 9)
+++ /trunk/minix/lib/ack/i386/head/em_abs.h	(revision 9)
@@ -0,0 +1,35 @@
+/* $Header: /cvsup/minix/src/lib/ack/i386/head/em_abs.h,v 1.1 2005/10/10 15:27:45 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#define LINO_AD         0
+#define FILN_AD         4
+
+#define LINO            (*(int    *)(_hol0()+LINO_AD))
+#define FILN            (*(char  **)(_hol0()+FILN_AD))
+
+#define EARRAY          0
+#define ERANGE          1
+#define ESET            2
+#define EIOVFL          3
+#define EFOVFL          4
+#define EFUNFL          5
+#define EIDIVZ          6
+#define EFDIVZ          7
+#define EIUND           8
+#define EFUND           9
+#define ECONV           10
+
+#define ESTACK          16
+#define EHEAP           17
+#define EILLINS         18
+#define EODDZ           19
+#define ECASE           20
+#define EMEMFLT         21
+#define EBADPTR         22
+#define EBADPC          23
+#define EBADLAE         24
+#define EBADMON         25
+#define EBADLIN         26
+#define EBADGTO         27
Index: /trunk/minix/lib/ack/i386/head/em_head.s
===================================================================
--- /trunk/minix/lib/ack/i386/head/em_head.s	(revision 9)
+++ /trunk/minix/lib/ack/i386/head/em_head.s	(revision 9)
@@ -0,0 +1,20 @@
+#
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define ERANGE,ESET,EHEAP,ECASE,EILLINS,EIDIVZ,EODDZ
+.define .trppc, .ignmask
+
+ERANGE		= 1
+ESET		= 2
+EIDIVZ		= 6
+EHEAP		= 17
+EILLINS		= 18
+EODDZ		= 19
+ECASE		= 20
+
+#include "em_abs.h"
+
+.sect .data
+.trppc:
+	.data4	0
+.ignmask:
+	.data4	EIOVFL | EIUND | ECONV | EFOVFL | EFUNFL
Index: /trunk/minix/lib/ack/libm2/Arguments.c
===================================================================
--- /trunk/minix/lib/ack/libm2/Arguments.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/Arguments.c	(revision 9)
@@ -0,0 +1,73 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	Access to program arguments and environment
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/Arguments.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+
+extern char **argv, ***_penviron;
+extern int argc;
+unsigned int _Arguments__Argc;
+
+static char *
+findname(s1, s2)
+register char *s1, *s2;
+{
+
+	while (*s1 == *s2++) s1++;
+	if (*s1 == '\0' && *(s2-1) == '=') return s2;
+	return 0;
+}
+
+static unsigned int
+scopy(src, dst, max)
+	register char *src, *dst;
+	unsigned int max;
+{
+	register unsigned int i = 0;
+
+	while (*src && i <= max) {
+		i++;
+		*dst++ = *src++;
+	}
+	if (i <= max) {
+		*dst = '\0';
+		return i+1;
+	}
+	while (*src++) i++;
+	return i + 1;
+}
+
+_Arguments_()
+{
+	_Arguments__Argc = argc;
+}
+
+unsigned
+_Arguments__Argv(n, argument, l, u, s)
+	unsigned int u;
+	char *argument;
+{
+
+	if (n >= argc) return 0;
+	return scopy(argv[n], argument, u);
+}
+
+unsigned
+_Arguments__GetEnv(name, nn, nu, ns, value, l, u, s)
+	char *name, *value;
+	unsigned int nu, u;
+{
+	register char **p = *_penviron;
+	register char *v = 0;
+
+	while (*p && !(v = findname(name, *p++))) {
+		/* nothing */
+	}
+	if (!v) return 0;
+	return scopy(v, value, u);
+}
Index: /trunk/minix/lib/ack/libm2/ArraySort.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/ArraySort.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/ArraySort.mod	(revision 9)
@@ -0,0 +1,155 @@
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE ArraySort;
+(* 
+  Module:	Array sorting module.
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/ArraySort.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+*)
+  FROM	SYSTEM IMPORT	ADDRESS, BYTE;	(* no generics in Modula-2, sorry *)
+
+  TYPE BytePtr = POINTER TO BYTE;
+
+  VAR compareproc: CompareProc;
+
+  PROCEDURE Sort(base: ADDRESS;		(* address of array *)
+		 nel: CARDINAL;		(* number of elements in array *)
+		 size: CARDINAL;	(* size of each element *)
+		 compar: CompareProc);	(* the comparison procedure *)
+  BEGIN
+	compareproc := compar;
+	qsort(base, base+(nel-1)*size, size);
+  END Sort;
+
+  PROCEDURE qsort(a1, a2: ADDRESS; size: CARDINAL);
+  (* Implemented with quick-sort, with some extra's *)
+    VAR	left, right, lefteq, righteq: ADDRESS;
+	cmp: CompareResult;
+	mainloop: BOOLEAN;
+  BEGIN
+	WHILE a2 > a1 DO
+		left := a1;
+		right := a2;
+		lefteq := a1 + size * (((a2 - a1) + size) DIV (2 * size));
+		righteq := lefteq;
+		(*
+                   Pick an element in the middle of the array.
+                   We will collect the equals around it.
+                   "lefteq" and "righteq" indicate the left and right
+                   bounds of the equals respectively.
+                   Smaller elements end up left of it, larger elements end
+                   up right of it.
+		*)
+		LOOP
+			LOOP
+				IF left >= lefteq THEN EXIT END;
+			      	cmp := compareproc(left, lefteq);
+				IF cmp = greater THEN EXIT END;
+				IF cmp = less THEN
+					left := left + size;
+				ELSE
+					(* equal, so exchange with the element
+					   to the left of the "equal"-interval.
+					*)
+					lefteq := lefteq - size;
+					exchange(left, lefteq, size);
+				END;
+			END;
+			mainloop := FALSE;
+			LOOP
+				IF right <= righteq THEN EXIT END;
+				cmp := compareproc(right, righteq);
+				IF cmp = less THEN
+					IF left < lefteq THEN
+						(* larger one at the left,
+						   so exchange
+						*)
+						exchange(left,right,size);
+						left := left + size;
+						right := right - size;
+						mainloop := TRUE;
+						EXIT;
+					END;
+                                (*
+ 				   no more room at the left part, so we
+                                   move the "equal-interval" one place to the
+                                   right, and the smaller element to the
+                                   left of it.
+                                   This is best expressed as a three-way
+                                   exchange.
+                                *)
+					righteq := righteq + size;
+					threewayexchange(left, righteq, right,
+						size);
+					lefteq := lefteq + size;
+					left := lefteq;
+				ELSIF cmp = equal THEN
+					(* equal, zo exchange with the element
+					   to the right of the "equal"
+					   interval
+					*)
+					righteq := righteq + size;
+					exchange(right, righteq, size);
+				ELSE
+					(* leave it where it is *)
+					right := right - size;
+				END;
+			END;
+			IF (NOT mainloop) THEN
+				IF left >= lefteq THEN
+					(* sort "smaller" part *)
+					qsort(a1, lefteq - size, size);
+					(* and now the "larger" part, saving a
+					   procedure call, because of this big
+					   WHILE loop
+					*)
+					a1 := righteq + size;
+					EXIT;	(* from the LOOP *)
+				END;
+                        	(* larger element to the left, but no more room,
+                      	     	   so move the "equal-interval" one place to the
+                           	   left, and the larger element to the right
+                           	   of it.
+                         	*)
+				lefteq := lefteq - size;
+				threewayexchange(right, lefteq, left, size);
+				righteq := righteq - size;
+				right := righteq;
+			END;
+		END;
+	END;
+  END qsort;
+
+  PROCEDURE exchange(a,b: BytePtr; size : CARDINAL);
+    VAR c: BYTE;
+  BEGIN
+	WHILE size > 0 DO
+		DEC(size);
+		c := a^;
+		a^ := b^;
+		a := ADDRESS(a) + 1;
+		b^ := c;
+		b := ADDRESS(b) + 1;
+	END;
+  END exchange;
+
+  PROCEDURE threewayexchange(p,q,r: BytePtr; size: CARDINAL);
+    VAR c: BYTE;
+  BEGIN
+	WHILE size > 0 DO
+		DEC(size);
+		c := p^;
+		p^ := r^;
+		p := ADDRESS(p) + 1;
+		r^ := q^;
+		r := ADDRESS(r) + 1;
+		q^ := c;
+		q := ADDRESS(q) + 1;
+	END;
+  END threewayexchange;
+
+END ArraySort.
Index: /trunk/minix/lib/ack/libm2/CSP.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/CSP.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/CSP.mod	(revision 9)
@@ -0,0 +1,347 @@
+(*$R-*)
+IMPLEMENTATION MODULE CSP;
+(*
+  Module:	Communicating Sequential Processes
+  From:		"A Modula-2 Implementation of CSP",
+		M. Collado, R. Morales, J.J. Moreno,
+		SIGPlan Notices, Volume 22, Number 6, June 1987.
+		Some modifications by Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/CSP.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+
+   See this article for an explanation of the use of this module.
+*)
+
+  FROM random	IMPORT	Uniform;
+  FROM SYSTEM	IMPORT	BYTE, ADDRESS, NEWPROCESS, TRANSFER;
+  FROM Storage	IMPORT	Allocate, Deallocate;
+  FROM Traps	IMPORT	Message;
+
+  CONST	WorkSpaceSize = 2000;
+
+  TYPE	ByteAddress =	POINTER TO BYTE;
+	Channel =	POINTER TO ChannelDescriptor;
+	ProcessType =	POINTER TO ProcessDescriptor;
+	ProcessDescriptor = RECORD
+				next: ProcessType;
+				father: ProcessType;
+				cor: ADDRESS;
+				wsp: ADDRESS;
+				guardindex: INTEGER;
+				guardno: CARDINAL;
+				guardcount: CARDINAL;
+				opened: Channel;
+				sons: CARDINAL;
+				msgadr: ADDRESS;
+				msglen: CARDINAL;
+			    END;
+
+	Queue =	RECORD
+		    head, tail: ProcessType;
+		END;
+
+	ChannelDescriptor = RECORD
+				senders: Queue;
+				owner: ProcessType;
+				guardindex: INTEGER;
+				next: Channel;
+			    END;
+
+  VAR	cp: ProcessType;
+	free, ready: Queue;
+
+(* ------------ Private modules and procedures ------------- *)
+
+  MODULE ProcessQueue;
+
+    IMPORT	ProcessType, Queue;
+    EXPORT	Push, Pop, InitQueue, IsEmpty;
+
+    PROCEDURE InitQueue(VAR q: Queue);
+    BEGIN
+	WITH q DO
+		head := NIL;
+		tail := NIL
+	END
+    END InitQueue;
+
+    PROCEDURE Push(p: ProcessType; VAR q: Queue);
+    BEGIN
+	p^.next := NIL;
+	WITH q DO
+		IF head = NIL THEN
+			tail := p
+		ELSE
+			head^.next := p
+		END;
+		head := p
+	END
+    END Push;
+
+    PROCEDURE Pop(VAR q: Queue; VAR p: ProcessType);
+    BEGIN
+	WITH q DO
+		p := tail;
+		IF p # NIL THEN
+			tail := tail^.next;
+			IF head = p THEN
+				head := NIL
+			END
+		END
+	END
+    END Pop;
+
+    PROCEDURE IsEmpty(q: Queue): BOOLEAN;
+    BEGIN
+	RETURN q.head = NIL
+    END IsEmpty;
+
+  END ProcessQueue;
+
+
+  PROCEDURE DoTransfer;
+    VAR	aux: ProcessType;
+  BEGIN
+	aux := cp;
+	Pop(ready, cp);
+	IF cp = NIL THEN
+		HALT
+	ELSE
+		TRANSFER(aux^.cor, cp^.cor)
+	END
+  END DoTransfer;
+
+  PROCEDURE OpenChannel(ch: Channel; n: INTEGER);
+  BEGIN
+	WITH ch^ DO
+		IF guardindex = 0 THEN
+			guardindex := n;
+			next := cp^.opened;
+			cp^.opened := ch
+		END
+	END
+  END OpenChannel;
+
+  PROCEDURE CloseChannels(p: ProcessType);
+  BEGIN
+	WITH p^ DO
+		WHILE opened # NIL DO
+			opened^.guardindex := 0;
+			opened := opened^.next
+		END
+	END
+  END CloseChannels;
+
+  PROCEDURE ThereAreOpenChannels(): BOOLEAN;
+  BEGIN
+	RETURN cp^.opened # NIL;
+  END ThereAreOpenChannels;
+
+  PROCEDURE Sending(ch: Channel): BOOLEAN;
+  BEGIN
+	RETURN NOT IsEmpty(ch^.senders)
+  END Sending;
+
+(* -------------- Public Procedures ----------------- *)
+
+  PROCEDURE COBEGIN;
+  (* Beginning of a COBEGIN .. COEND structure *)
+  BEGIN
+  END COBEGIN;
+
+  PROCEDURE COEND;
+  (* End of a COBEGIN .. COEND structure *)
+    (* VAR	aux: ProcessType; *)
+  BEGIN
+	IF cp^.sons > 0 THEN
+		DoTransfer
+	END
+  END COEND;
+
+  PROCEDURE StartProcess(P: PROC);
+  (* Start an anonimous process that executes the procedure P *)
+    VAR newprocess: ProcessType;
+  BEGIN
+	Pop(free, newprocess);
+	IF newprocess = NIL THEN
+		Allocate(newprocess,SIZE(ProcessDescriptor));
+		Allocate(newprocess^.wsp, WorkSpaceSize)
+	END;
+	WITH newprocess^ DO
+		father := cp;
+		sons := 0;
+		msglen := 0;
+		NEWPROCESS(P, wsp, WorkSpaceSize, cor)
+	END;
+	cp^.sons := cp^.sons + 1;
+	Push(newprocess, ready)
+  END StartProcess;
+
+  PROCEDURE StopProcess;
+  (* Terminate a Process (itself) *)
+    VAR aux: ProcessType;
+  BEGIN
+	aux := cp^.father;
+	aux^.sons := aux^.sons - 1;
+	IF aux^.sons = 0 THEN
+		Push(aux, ready)
+	END;
+	aux := cp;
+	Push(aux, free);
+	Pop(ready, cp);
+	IF cp = NIL THEN
+		HALT
+	ELSE
+		TRANSFER(aux^.cor, cp^.cor)
+	END
+  END StopProcess;
+
+  PROCEDURE InitChannel(VAR ch: Channel);
+  (* Initialize the channel ch *)
+  BEGIN
+	Allocate(ch, SIZE(ChannelDescriptor));
+	WITH ch^ DO
+		InitQueue(senders);
+		owner := NIL;
+		next := NIL;
+		guardindex := 0
+	END
+  END InitChannel;
+
+  PROCEDURE GetChannel(ch: Channel);
+  (* Assign the channel ch to the process that gets it *)
+  BEGIN
+	WITH ch^ DO
+		IF owner # NIL THEN
+			Message("Channel already has an owner");
+			HALT
+		END;
+		owner := cp
+	END
+  END GetChannel;
+
+  PROCEDURE Send(data: ARRAY OF BYTE; VAR ch: Channel);
+  (* Send a message with the data to the cvhannel ch *)
+    VAR	m: ByteAddress;
+	(* aux: ProcessType; *)
+	i: CARDINAL;
+  BEGIN
+	WITH ch^ DO
+		Push(cp, senders);
+		Allocate(cp^.msgadr, SIZE(data));
+		m := cp^.msgadr;
+		cp^.msglen := HIGH(data);
+		FOR i := 0 TO HIGH(data) DO
+			m^ := data[i];
+			m := ADDRESS(m) + 1
+		END;
+		IF guardindex # 0 THEN
+			owner^.guardindex := guardindex;
+			CloseChannels(owner);
+			Push(owner, ready)
+		END
+	END;
+	DoTransfer
+  END Send;
+
+  PROCEDURE Receive(VAR ch: Channel; VAR dest: ARRAY OF BYTE);
+  (* Receive a message from the channel ch into the dest variable *)
+    VAR	aux: ProcessType;
+	m: ByteAddress;
+	i: CARDINAL;
+  BEGIN
+	WITH ch^ DO
+		IF cp # owner THEN
+			Message("Only owner of channel can receive from it");
+			HALT
+		END;
+		IF Sending(ch) THEN
+			Pop(senders, aux);
+			m := aux^.msgadr;
+			FOR i := 0 TO aux^.msglen DO
+				dest[i] := m^;
+				m := ADDRESS(m) + 1
+			END;
+			Push(aux, ready);
+			Push(cp, ready);
+			CloseChannels(cp)
+		ELSE
+			OpenChannel(ch, -1);
+			DoTransfer;
+			Pop(senders, aux);
+			m := aux^.msgadr;
+			FOR i := 0 TO aux^.msglen DO
+				dest[i] := m^;
+				m := ADDRESS(m) + 1
+			END;
+			Push(cp, ready);
+			Push(aux, ready)
+		END;
+		Deallocate(aux^.msgadr, aux^.msglen+1);
+		DoTransfer
+	END
+  END Receive;
+
+  PROCEDURE SELECT(n: CARDINAL);
+  (* Beginning of a SELECT structure with n guards *)
+  BEGIN
+	cp^.guardindex := Uniform(1,n);
+	cp^.guardno := n;
+	cp^.guardcount := n
+  END SELECT;
+
+  PROCEDURE NEXTGUARD(): CARDINAL;
+  (* Returns an index to the next guard to be evaluated in a SELECT *)
+  BEGIN
+	RETURN cp^.guardindex
+  END NEXTGUARD;
+
+  PROCEDURE GUARD(cond: BOOLEAN; ch: Channel;
+		  VAR dest: ARRAY OF BYTE): BOOLEAN;
+  (* Evaluates a guard, including reception management *)
+    (* VAR	aux: ProcessType; *)
+  BEGIN
+	IF NOT cond THEN
+		RETURN FALSE
+	ELSIF ch = NIL THEN
+		CloseChannels(cp);
+		cp^.guardindex := 0;
+		RETURN TRUE
+	ELSIF Sending(ch) THEN
+		Receive(ch, dest);
+		cp^.guardindex := 0;
+		RETURN TRUE
+	ELSE
+		OpenChannel(ch, cp^.guardindex);
+		RETURN FALSE
+	END
+  END GUARD;
+
+  PROCEDURE ENDSELECT(): BOOLEAN;
+  (* End of a SELECT structure *)
+  BEGIN
+	WITH cp^ DO
+		IF guardindex <= 0 THEN
+			RETURN TRUE
+		END;
+		guardcount := guardcount - 1;
+		IF guardcount # 0 THEN
+			guardindex := (guardindex MOD INTEGER(guardno)) + 1
+		ELSIF ThereAreOpenChannels() THEN
+			DoTransfer
+		ELSE
+			guardindex := 0
+		END
+	END;
+	RETURN FALSE
+  END ENDSELECT;
+
+BEGIN
+	InitQueue(free);
+	InitQueue(ready);
+	Allocate(cp,SIZE(ProcessDescriptor));
+	WITH cp^ DO
+		sons := 0;
+		father := NIL
+	END
+END CSP.
+
Index: /trunk/minix/lib/ack/libm2/Conversion.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/Conversion.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/Conversion.mod	(revision 9)
@@ -0,0 +1,73 @@
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE Conversions;
+(*
+  Module:	numeric-to-string conversions
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/Conversion.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+*)
+
+  PROCEDURE ConvertNum(num, len, base: CARDINAL;
+		       neg: BOOLEAN;
+		       VAR str: ARRAY OF CHAR);
+    VAR i: CARDINAL;
+	r: CARDINAL;
+	tmp: ARRAY [0..20] OF CHAR;
+    BEGIN
+	i := 0;
+	REPEAT
+		r := num MOD base;
+		num := num DIV base;
+		IF r <= 9 THEN
+			tmp[i] := CHR(r + ORD('0'));
+		ELSE
+			tmp[i] := CHR(r - 10 + ORD('A'));
+		END;
+		INC(i);
+	UNTIL num = 0;
+	IF neg THEN
+		tmp[i] := '-';
+		INC(i)
+	END;
+	IF len > HIGH(str) + 1 THEN len := HIGH(str) + 1; END;
+	IF i > HIGH(str) + 1 THEN i := HIGH(str) + 1; END;
+	r := 0;
+	WHILE len > i DO str[r] := ' '; INC(r); DEC(len); END;
+	WHILE i > 0 DO str[r] := tmp[i-1]; DEC(i); INC(r); END;
+	WHILE r <= HIGH(str) DO
+		str[r] := 0C;
+		INC(r);
+	END;
+    END ConvertNum;
+
+  PROCEDURE ConvertOctal(num, len: CARDINAL; VAR str: ARRAY OF CHAR);
+  BEGIN   
+	ConvertNum(num, len, 8, FALSE, str);
+  END ConvertOctal;   
+
+  PROCEDURE ConvertHex(num, len: CARDINAL; VAR str: ARRAY OF CHAR);
+  BEGIN   
+	ConvertNum(num, len, 16, FALSE, str);
+  END ConvertHex;   
+
+  PROCEDURE ConvertCardinal(num, len: CARDINAL; VAR str: ARRAY OF CHAR);   
+  BEGIN   
+	ConvertNum(num, len, 10, FALSE, str);
+  END ConvertCardinal;   
+
+  PROCEDURE ConvertInteger(num: INTEGER;
+			   len: CARDINAL;   
+                           VAR str: ARRAY OF CHAR); 
+  BEGIN 
+	IF (num < 0) AND (num >= -MAX(INTEGER)) THEN
+		ConvertNum(-num, len, 10, TRUE, str);
+	ELSE
+		ConvertNum(CARDINAL(num), len, 10, num < 0, str);
+	END;
+  END ConvertInteger; 
+
+END Conversions.
Index: /trunk/minix/lib/ack/libm2/EM.e
===================================================================
--- /trunk/minix/lib/ack/libm2/EM.e	(revision 9)
+++ /trunk/minix/lib/ack/libm2/EM.e	(revision 9)
@@ -0,0 +1,100 @@
+#
+;
+; (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+; See the copyright notice in the ACK home directory, in the file "Copyright".
+;
+;
+; Module:	Interface to some EM instructions and data
+; Author:	Ceriel J.H. Jacobs
+; Version:	$Header: /cvsup/minix/src/lib/ack/libm2/EM.e,v 1.1 2005/10/10 15:27:46 beng Exp $
+;
+ mes 2,_EM_WSIZE,_EM_PSIZE
+
+#define ARG1    0
+#define ARG2    _EM_DSIZE
+#define IRES    2*_EM_DSIZE
+
+; FIF is called with three parameters:
+;       - address of integer part result (IRES)
+;       - float two (ARG2)
+;       - float one (ARG1)
+; and returns an _EM_DSIZE-byte floating point number
+; Definition:
+;	PROCEDURE FIF(ARG1, ARG2: LONGREAL; VAR IRES: LONGREAL) : LONGREAL;
+
+ exp $FIF
+ pro $FIF,0
+ lal 0
+ loi 2*_EM_DSIZE
+ fif _EM_DSIZE
+ lal IRES
+ loi _EM_PSIZE
+ sti _EM_DSIZE
+ ret _EM_DSIZE
+ end ?
+
+#define FARG    0
+#define ERES    _EM_DSIZE
+
+; FEF is called with two parameters:
+;       - address of base 2 exponent result (ERES)
+;       - floating point number to be split (FARG)
+; and returns an _EM_DSIZE-byte floating point number (the mantissa)
+; Definition:
+;	PROCEDURE FEF(FARG: LONGREAL; VAR ERES: integer): LONGREAL;
+
+ exp $FEF
+ pro $FEF,0
+ lal FARG
+ loi _EM_DSIZE
+ fef _EM_DSIZE
+ lal ERES
+ loi _EM_PSIZE
+ sti _EM_WSIZE
+ ret _EM_DSIZE
+ end ?
+
+#define TRAP    0
+
+; TRP is called with one parameter:
+;       - trap number (TRAP)
+; Definition:
+; PROCEDURE TRP(trapno: INTEGER);
+
+ exp $TRP
+ pro $TRP, 0
+ lol TRAP
+ trp
+ ret 0
+ end ?
+
+#define PROC    0
+
+; SIG is called with one parameter:
+;       - procedure instance identifier (PROC)
+; and returns the old traphandler.
+
+ exa handler
+ exp $SIG
+ pro $SIG, 0
+ lae handler
+ loi _EM_PSIZE
+ lal PROC
+ loi _EM_PSIZE
+ lae handler
+ sti _EM_PSIZE
+ ret _EM_PSIZE
+ end ?
+
+ exp $LINO
+ pro $LINO,0
+ loe 0
+ ret _EM_WSIZE
+ end ?
+
+ exp $FILN
+ pro $FILN,0
+ lae 4
+ loi _EM_PSIZE
+ ret _EM_PSIZE
+ end ?
Index: /trunk/minix/lib/ack/libm2/InOut.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/InOut.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/InOut.mod	(revision 9)
@@ -0,0 +1,371 @@
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE InOut ;
+(*
+  Module:	Wirth's Input/Output module
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/InOut.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+*)
+
+  IMPORT	Streams;
+  FROM	Conversions IMPORT
+			ConvertCardinal, ConvertInteger,
+			ConvertOctal, ConvertHex;
+  FROM	Traps IMPORT	Message;
+
+  CONST	TAB = 11C;
+
+  TYPE	numbuf = ARRAY[0..255] OF CHAR;
+
+  VAR	unread: BOOLEAN;
+	unreadch: CHAR;
+	CurrIn, CurrOut: Streams.Stream;
+	result: Streams.StreamResult;
+
+  PROCEDURE Read(VAR c : CHAR);
+
+  BEGIN
+	IF unread THEN
+		unread := FALSE;
+		c := unreadch;
+		Done := TRUE;
+	ELSE
+		Streams.Read(CurrIn, c, result);
+		Done := result = Streams.succeeded;
+	END;
+  END Read;
+
+  PROCEDURE UnRead(ch: CHAR);
+  BEGIN
+	unread := TRUE;
+	unreadch := ch;
+  END UnRead;
+
+  PROCEDURE Write(c: CHAR);
+  BEGIN
+	Streams.Write(CurrOut, c, result);
+  END Write;
+
+  PROCEDURE OpenInput(defext: ARRAY OF CHAR);
+  VAR namebuf : ARRAY [1..128] OF CHAR;
+  BEGIN
+	IF CurrIn # Streams.InputStream THEN
+		Streams.CloseStream(CurrIn, result);
+	END;
+	MakeFileName("Name of input file: ", defext, namebuf);
+	IF NOT Done THEN RETURN; END;
+	openinput(namebuf);
+  END OpenInput;
+
+  PROCEDURE OpenInputFile(filename: ARRAY OF CHAR);
+  BEGIN
+	IF CurrIn # Streams.InputStream THEN
+		Streams.CloseStream(CurrIn, result);
+	END;
+	openinput(filename);
+  END OpenInputFile;
+
+  PROCEDURE openinput(namebuf: ARRAY OF CHAR);
+  BEGIN
+	IF (namebuf[0] = '-') AND (namebuf[1] = 0C) THEN
+		CurrIn := Streams.InputStream;
+		Done := TRUE;
+	ELSE
+		Streams.OpenStream(CurrIn, namebuf, Streams.text,
+				   Streams.reading, result);
+		Done := result = Streams.succeeded;
+	END;
+  END openinput;
+
+  PROCEDURE CloseInput;
+  BEGIN
+	IF CurrIn # Streams.InputStream THEN
+		Streams.CloseStream(CurrIn, result);
+	END;
+	CurrIn := Streams.InputStream;
+  END CloseInput;
+
+  PROCEDURE OpenOutput(defext: ARRAY OF CHAR);
+  VAR namebuf : ARRAY [1..128] OF CHAR;
+  BEGIN
+	IF CurrOut # Streams.OutputStream THEN
+		Streams.CloseStream(CurrOut, result);
+	END;
+	MakeFileName("Name of output file: ", defext, namebuf);
+	IF NOT Done THEN RETURN; END;
+	openoutput(namebuf);
+  END OpenOutput;
+
+  PROCEDURE OpenOutputFile(filename: ARRAY OF CHAR);
+  BEGIN
+	IF CurrOut # Streams.OutputStream THEN
+		Streams.CloseStream(CurrOut, result);
+	END;
+	openoutput(filename);
+  END OpenOutputFile;
+
+  PROCEDURE openoutput(namebuf: ARRAY OF CHAR);
+  BEGIN
+	IF (namebuf[1] = '-') AND (namebuf[2] = 0C) THEN
+		CurrOut := Streams.OutputStream;
+		Done := TRUE;
+	ELSE
+		Streams.OpenStream(CurrOut, namebuf, Streams.text,
+				   Streams.writing, result);
+		Done := result = Streams.succeeded;
+	END;
+  END openoutput;
+
+  PROCEDURE CloseOutput;
+  BEGIN
+	IF CurrOut # Streams.OutputStream THEN
+		Streams.CloseStream(CurrOut, result);
+	END;
+	CurrOut := Streams.OutputStream;
+  END CloseOutput;
+
+  PROCEDURE MakeFileName(prompt, defext : ARRAY OF CHAR;
+		       VAR buf : ARRAY OF CHAR);
+  VAR	i : INTEGER;
+	j : CARDINAL;
+  BEGIN
+	Done := TRUE;
+	IF Streams.isatty(Streams.InputStream, result) THEN
+		XWriteString(prompt);
+	END;
+	XReadString(buf);
+	i := 0;
+	WHILE buf[i] # 0C DO i := i + 1 END;
+	IF i # 0 THEN
+		i := i - 1;
+		IF buf[i] = '.' THEN
+	    		FOR j := 0 TO HIGH(defext) DO
+				i := i + 1;
+				buf[i] := defext[j];
+	    		END;
+	    		buf[i+1] := 0C;
+		END;
+		RETURN;
+	END;
+	Done := FALSE;
+  END MakeFileName;
+
+  PROCEDURE ReadInt(VAR integ : INTEGER);
+  CONST
+    	SAFELIMITDIV10 = MAX(INTEGER) DIV 10;
+    	SAFELIMITREM10 = MAX(INTEGER) MOD 10;
+  TYPE
+	itype = [0..31];
+	ibuf =  ARRAY itype OF CHAR;
+  VAR
+    	int : INTEGER;
+    	neg : BOOLEAN;
+    	safedigit: [0 .. 9];
+    	chvalue: CARDINAL;
+	buf : ibuf;
+	index : itype;
+  BEGIN
+    	ReadString(buf);
+	IF NOT Done THEN
+		RETURN
+	END;
+	index := 0;
+    	IF buf[index] = '-' THEN
+		neg := TRUE;
+		INC(index);
+    	ELSIF buf[index] = '+' THEN
+		neg := FALSE;
+		INC(index);
+    	ELSE
+		neg := FALSE
+    	END;
+
+    	safedigit := SAFELIMITREM10;
+    	IF neg THEN safedigit := safedigit + 1 END;
+    	int := 0;
+	WHILE (buf[index] >= '0') & (buf[index] <= '9') DO
+  		chvalue := ORD(buf[index]) - ORD('0');
+	   	IF (int > SAFELIMITDIV10) OR 
+		   ( (int = SAFELIMITDIV10) AND
+		     (chvalue > safedigit)) THEN
+			Message("integer too large");
+			HALT;
+	    	ELSE
+			int := 10*int + VAL(INTEGER, chvalue);
+			INC(index)
+	    	END;
+	END;
+	IF neg THEN
+   		integ := -int
+	ELSE
+		integ := int
+	END;
+	IF buf[index] > " " THEN
+		Message("illegal integer");
+		HALT;
+	END;
+	Done := TRUE;
+  END ReadInt;
+
+  PROCEDURE ReadCard(VAR card : CARDINAL);
+  CONST
+    	SAFELIMITDIV10 = MAX(CARDINAL) DIV 10;
+    	SAFELIMITREM10 = MAX(CARDINAL) MOD 10;
+
+  TYPE
+	itype = [0..31];
+	ibuf =  ARRAY itype OF CHAR;
+    
+  VAR
+    	int : CARDINAL;
+    	index  : itype;
+	buf : ibuf;
+    	safedigit: [0 .. 9];
+    	chvalue: CARDINAL;
+  BEGIN
+    	ReadString(buf);
+	IF NOT Done THEN RETURN; END;
+	index := 0;
+    	safedigit := SAFELIMITREM10;
+    	int := 0;
+	WHILE (buf[index] >= '0') & (buf[index] <= '9') DO
+  		chvalue := ORD(buf[index]) - ORD('0');
+	    	IF (int > SAFELIMITDIV10) OR 
+		   ( (int = SAFELIMITDIV10) AND
+		     (chvalue > safedigit)) THEN
+			Message("cardinal too large");
+			HALT;
+	    	ELSE
+			int := 10*int + chvalue;
+			INC(index);
+	    	END;
+	END;
+	IF buf[index] > " " THEN
+		Message("illegal cardinal");
+		HALT;
+	END;
+	card := int;
+	Done := TRUE;
+  END ReadCard;
+
+  PROCEDURE ReadString(VAR s : ARRAY OF CHAR);
+  TYPE charset = SET OF CHAR;
+  VAR	i : CARDINAL;
+    	ch : CHAR;
+
+  BEGIN
+    	i := 0;
+	REPEAT
+		Read(ch);
+	UNTIL NOT (ch IN charset{' ', TAB, 12C, 15C});
+	IF NOT Done THEN
+		RETURN;
+	END;
+	UnRead(ch);
+    	REPEAT
+		Read(ch);
+		termCH := ch;
+		IF i <= HIGH(s) THEN
+			s[i] := ch;
+			IF (NOT Done) OR (ch <= " ") THEN
+				s[i] := 0C;
+			END;
+		END;
+		INC(i);
+    	UNTIL (NOT Done) OR (ch <= " ");
+	IF Done THEN UnRead(ch); END;
+  END ReadString;
+
+  PROCEDURE XReadString(VAR s : ARRAY OF CHAR);
+  VAR	j : CARDINAL;
+    	ch : CHAR;
+
+  BEGIN
+	j := 0;
+	LOOP
+		Streams.Read(Streams.InputStream, ch, result);
+		IF result # Streams.succeeded THEN
+			EXIT;
+		END;
+		IF ch <= " " THEN
+			s[j] := 0C;
+			EXIT;
+		END;
+		IF j < HIGH(s) THEN
+			s[j] := ch;
+			INC(j);
+		END;
+	END;
+  END XReadString;
+
+  PROCEDURE XWriteString(s: ARRAY OF CHAR);
+  VAR i: CARDINAL;
+  BEGIN
+	i := 0;
+	LOOP
+		IF (i <= HIGH(s)) AND (s[i] # 0C) THEN
+			Streams.Write(Streams.OutputStream, s[i], result);
+			INC(i);
+		ELSE
+			EXIT;
+		END;
+	END;
+  END XWriteString;
+
+  PROCEDURE WriteCard(card, width : CARDINAL);
+  VAR
+    	buf : numbuf;
+  BEGIN
+	ConvertCardinal(card, width, buf);
+	WriteString(buf);
+  END WriteCard;
+
+  PROCEDURE WriteInt(int : INTEGER; width : CARDINAL);
+  VAR
+    	buf : numbuf;
+  BEGIN
+    	ConvertInteger(int, width, buf);
+	WriteString(buf);
+  END WriteInt;
+
+  PROCEDURE WriteHex(card, width : CARDINAL);
+  VAR
+    	buf : numbuf;
+  BEGIN
+	ConvertHex(card, width, buf);
+	WriteString(buf);
+  END WriteHex;
+
+  PROCEDURE WriteLn;
+  BEGIN
+    	Write(EOL)
+  END WriteLn;
+
+  PROCEDURE WriteOct(card, width : CARDINAL);
+  VAR
+    	buf : numbuf;
+  BEGIN
+    	ConvertOctal(card, width, buf);
+	WriteString(buf);
+  END WriteOct;
+
+  PROCEDURE WriteString(str : ARRAY OF CHAR);
+  VAR
+    	nbytes : CARDINAL;
+  BEGIN
+    	nbytes := 0;
+    	WHILE (nbytes <= HIGH(str)) AND (str[nbytes] # 0C) DO
+		Write(str[nbytes]);
+		INC(nbytes)
+    	END;
+  END WriteString;
+
+BEGIN	(* InOut initialization *)
+	CurrIn := Streams.InputStream;
+	CurrOut := Streams.OutputStream;
+	unread := FALSE;
+END InOut.
Index: /trunk/minix/lib/ack/libm2/LtoUset.e
===================================================================
--- /trunk/minix/lib/ack/libm2/LtoUset.e	(revision 9)
+++ /trunk/minix/lib/ack/libm2/LtoUset.e	(revision 9)
@@ -0,0 +1,61 @@
+#
+;
+; (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+; See the copyright notice in the ACK home directory, in the file "Copyright".
+;
+;
+; Module:	Compute non-constant set displays
+; Author:	Ceriel J.H. Jacobs
+; Version:	$Header: /cvsup/minix/src/lib/ack/libm2/LtoUset.e,v 1.1 2005/10/10 15:27:46 beng Exp $
+;
+ mes 2,_EM_WSIZE,_EM_PSIZE
+
+ ; LtoUset is called for set displays containing { expr1 .. expr2 }.
+ ; It has six parameters, of which the caller must pop five:
+ ; - The set in which bits must be set.
+ ; - the lower bound of the set type.
+ ; - The set size in bytes.
+ ; - The upper bound of set elements, specified by the set-type.
+ ; - "expr2", the upper bound
+ ; - "expr1", the lower bound
+
+#define SETBASE	5*_EM_WSIZE
+#define SETLOW	4*_EM_WSIZE
+#define SETSIZE 3*_EM_WSIZE
+#define USETSIZ 2*_EM_WSIZE
+#define LWB	_EM_WSIZE
+#define UPB	0
+ exp $LtoUset
+ pro $LtoUset,0
+ lal SETBASE	; address of initial set
+ lol SETSIZE
+ los _EM_WSIZE	; load initial set
+ lol LWB	; low bound
+ lol SETLOW
+ sbu _EM_WSIZE
+ stl LWB
+ lol UPB	; high bound
+ lol SETLOW
+ sbu _EM_WSIZE
+ stl UPB
+1
+ lol LWB
+ lol UPB
+ cmu _EM_WSIZE
+ zgt *2		; while low <= high
+ lol LWB
+ lol SETSIZE
+ set ?		; create [low]
+ lol SETSIZE
+ ior ?		; merge with initial set
+ lol LWB
+ loc 1
+ adu _EM_WSIZE
+ stl LWB
+ bra *1		; loop back
+2
+ lal SETBASE
+ lol SETSIZE
+ sts _EM_WSIZE	; store result over initial set
+ ret 0
+ end 0
Index: /trunk/minix/lib/ack/libm2/Makedepend-ack
===================================================================
--- /trunk/minix/lib/ack/libm2/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/ack/libm2/Makedepend-ack	(revision 9)
@@ -0,0 +1,50 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -I../h -wo -E' Arguments.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' ArraySort.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' CSP.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' Conversion.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' EM.e | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' InOut.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' LtoUset.e | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' MathLib0.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' Mathlib.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' PascalIO.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' Processes.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' RealConver.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' RealInOut.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' SYSTEM.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' Semaphores.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' Storage.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' StrAss.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' Streams.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' Strings.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' Termcap.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' Terminal.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' Traps.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' XXTermcap.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' absd.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' absf.e | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' absi.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' absl.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' blockmove.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' cap.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' catch.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' confarray.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' dvi.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' halt.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' head_m2.e | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' init.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' load.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' par_misc.e | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'm2 -O -ws -n -E' random.mod | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' rcka.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' rcki.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' rckil.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' rcku.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' rckul.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' sigtrp.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' stackprio.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' store.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' ucheck.c | sed -e 's:^\(.\):../../obj-ack//./ack/libm2/\1:' >> .depend-ack
Index: /trunk/minix/lib/ack/libm2/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/ack/libm2/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/ack/libm2/Makedepend-gnu	(revision 9)
@@ -0,0 +1,3 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
Index: /trunk/minix/lib/ack/libm2/Makefile
===================================================================
--- /trunk/minix/lib/ack/libm2/Makefile	(revision 9)
+++ /trunk/minix/lib/ack/libm2/Makefile	(revision 9)
@@ -0,0 +1,178 @@
+#Generated from ./ack/libm2/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../generate.sh ./ack/libm2 ../../obj-ack/ ../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../generate.sh ./ack/libm2 ../../obj-ack/ ../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../../obj-ack//libm2.a
+
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(Arguments.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(ArraySort.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(CSP.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(Conversion.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(EM.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(InOut.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(LtoUset.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(MathLib0.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(Mathlib.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(PascalIO.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(Processes.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(RealConver.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(RealInOut.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(SYSTEM.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(Semaphores.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(Storage.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(StrAss.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(Streams.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(Strings.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(Termcap.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(Terminal.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(Traps.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(XXTermcap.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(absd.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(absf.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(absi.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(absl.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(blockmove.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(cap.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(catch.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(confarray.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(dvi.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(halt.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(head_m2.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(init.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(load.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(par_misc.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(random.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(rcka.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(rcki.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(rckil.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(rcku.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(rckul.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(sigtrp.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(stackprio.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(store.o)
+../../obj-ack//libm2.a: ../../obj-ack//libm2.a(ucheck.o)
+
+../../obj-ack//libm2.a:
+	ar cr ../../obj-ack//libm2.a ../../obj-ack//./ack/libm2/*.o
+	rm ../../obj-ack//./ack/libm2/*.o
+
+../../obj-ack//libm2.a(Arguments.o): Arguments.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/Arguments.o Arguments.c
+../../obj-ack//libm2.a(ArraySort.o): ArraySort.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/ArraySort.o ArraySort.mod
+../../obj-ack//libm2.a(CSP.o): CSP.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/CSP.o CSP.mod
+../../obj-ack//libm2.a(Conversion.o): Conversion.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/Conversion.o Conversion.mod
+../../obj-ack//libm2.a(EM.o): EM.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/EM.o EM.e
+../../obj-ack//libm2.a(InOut.o): InOut.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/InOut.o InOut.mod
+../../obj-ack//libm2.a(LtoUset.o): LtoUset.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/LtoUset.o LtoUset.e
+../../obj-ack//libm2.a(MathLib0.o): MathLib0.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/MathLib0.o MathLib0.mod
+../../obj-ack//libm2.a(Mathlib.o): Mathlib.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/Mathlib.o Mathlib.mod
+../../obj-ack//libm2.a(PascalIO.o): PascalIO.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/PascalIO.o PascalIO.mod
+../../obj-ack//libm2.a(Processes.o): Processes.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/Processes.o Processes.mod
+../../obj-ack//libm2.a(RealConver.o): RealConver.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/RealConver.o RealConver.mod
+../../obj-ack//libm2.a(RealInOut.o): RealInOut.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/RealInOut.o RealInOut.mod
+../../obj-ack//libm2.a(SYSTEM.o): SYSTEM.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/SYSTEM.o SYSTEM.c
+../../obj-ack//libm2.a(Semaphores.o): Semaphores.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/Semaphores.o Semaphores.mod
+../../obj-ack//libm2.a(Storage.o): Storage.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/Storage.o Storage.mod
+../../obj-ack//libm2.a(StrAss.o): StrAss.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/StrAss.o StrAss.c
+../../obj-ack//libm2.a(Streams.o): Streams.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/Streams.o Streams.mod
+../../obj-ack//libm2.a(Strings.o): Strings.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/Strings.o Strings.mod
+../../obj-ack//libm2.a(Termcap.o): Termcap.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/Termcap.o Termcap.mod
+../../obj-ack//libm2.a(Terminal.o): Terminal.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/Terminal.o Terminal.mod
+../../obj-ack//libm2.a(Traps.o): Traps.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/Traps.o Traps.mod
+../../obj-ack//libm2.a(XXTermcap.o): XXTermcap.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/XXTermcap.o XXTermcap.c
+../../obj-ack//libm2.a(absd.o): absd.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/absd.o absd.c
+../../obj-ack//libm2.a(absf.o): absf.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/absf.o absf.e
+../../obj-ack//libm2.a(absi.o): absi.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/absi.o absi.c
+../../obj-ack//libm2.a(absl.o): absl.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/absl.o absl.c
+../../obj-ack//libm2.a(blockmove.o): blockmove.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/blockmove.o blockmove.c
+../../obj-ack//libm2.a(cap.o): cap.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/cap.o cap.c
+../../obj-ack//libm2.a(catch.o): catch.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/catch.o catch.c
+../../obj-ack//libm2.a(confarray.o): confarray.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/confarray.o confarray.c
+../../obj-ack//libm2.a(dvi.o): dvi.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/dvi.o dvi.c
+../../obj-ack//libm2.a(halt.o): halt.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/halt.o halt.c
+../../obj-ack//libm2.a(head_m2.o): head_m2.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/head_m2.o head_m2.e
+../../obj-ack//libm2.a(init.o): init.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/init.o init.c
+../../obj-ack//libm2.a(load.o): load.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/load.o load.c
+../../obj-ack//libm2.a(par_misc.o): par_misc.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/par_misc.o par_misc.e
+../../obj-ack//libm2.a(random.o): random.mod
+	m2 -O -ws -n -c -o ../../obj-ack//./ack/libm2/random.o random.mod
+../../obj-ack//libm2.a(rcka.o): rcka.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/rcka.o rcka.c
+../../obj-ack//libm2.a(rcki.o): rcki.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/rcki.o rcki.c
+../../obj-ack//libm2.a(rckil.o): rckil.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/rckil.o rckil.c
+../../obj-ack//libm2.a(rcku.o): rcku.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/rcku.o rcku.c
+../../obj-ack//libm2.a(rckul.o): rckul.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/rckul.o rckul.c
+../../obj-ack//libm2.a(sigtrp.o): sigtrp.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/sigtrp.o sigtrp.c
+../../obj-ack//libm2.a(stackprio.o): stackprio.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/stackprio.o stackprio.c
+../../obj-ack//libm2.a(store.o): store.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/store.o store.c
+../../obj-ack//libm2.a(ucheck.o): ucheck.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libm2/ucheck.o ucheck.c
+
+
+
+clean::
+	rm -f ../../obj-ack//./ack/libm2/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/ack/libm2/Makefile.in
===================================================================
--- /trunk/minix/lib/ack/libm2/Makefile.in	(revision 9)
+++ /trunk/minix/lib/ack/libm2/Makefile.in	(revision 9)
@@ -0,0 +1,57 @@
+# Makefile for lib/ack/libm2.
+
+CFLAGS="-O -I../h -wo"
+M2FLAGS="-O -ws -n"
+
+LIBRARIES=libm2
+
+libm2_FILES=" \
+	Arguments.c \
+	ArraySort.mod \
+	CSP.mod \
+	Conversion.mod \
+	EM.e \
+	InOut.mod \
+	LtoUset.e \
+	MathLib0.mod \
+	Mathlib.mod \
+	PascalIO.mod \
+	Processes.mod \
+	RealConver.mod \
+	RealInOut.mod \
+	SYSTEM.c \
+	Semaphores.mod \
+	Storage.mod \
+	StrAss.c \
+	Streams.mod \
+	Strings.mod \
+	Termcap.mod \
+	Terminal.mod \
+	Traps.mod \
+	XXTermcap.c \
+	absd.c \
+	absf.e \
+	absi.c \
+	absl.c \
+	blockmove.c \
+	cap.c \
+	catch.c \
+	confarray.c \
+	dvi.c \
+	halt.c \
+	head_m2.e \
+	init.c \
+	load.c \
+	par_misc.e \
+	random.mod \
+	rcka.c \
+	rcki.c \
+	rckil.c \
+	rcku.c \
+	rckul.c \
+	sigtrp.c \
+	stackprio.c \
+	store.c \
+	ucheck.c" 
+	
+TYPE=ack
Index: /trunk/minix/lib/ack/libm2/MathLib0.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/MathLib0.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/MathLib0.mod	(revision 9)
@@ -0,0 +1,69 @@
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE MathLib0;
+(*
+  Module:	Some mathematical functions
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/MathLib0.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+*)
+
+  IMPORT	Mathlib;
+
+  PROCEDURE cos(arg: REAL): REAL;
+  BEGIN
+	RETURN Mathlib.cos(arg);
+  END cos;
+
+  PROCEDURE sin(arg: REAL): REAL;
+  BEGIN
+	RETURN Mathlib.sin(arg);
+  END sin;
+
+  PROCEDURE arctan(arg: REAL): REAL;
+  BEGIN
+	RETURN Mathlib.arctan(arg);
+  END arctan;
+
+  PROCEDURE sqrt(arg: REAL): REAL;
+  BEGIN
+	RETURN Mathlib.sqrt(arg);
+  END sqrt;
+
+  PROCEDURE ln(arg: REAL): REAL;
+  BEGIN
+	RETURN Mathlib.ln(arg);
+  END ln;
+
+  PROCEDURE exp(arg: REAL): REAL;
+  BEGIN
+	RETURN Mathlib.exp(arg);
+  END exp;
+
+  PROCEDURE entier(x: REAL): INTEGER;
+  VAR i: INTEGER;
+  BEGIN
+	IF x < 0.0 THEN
+		i := TRUNC(-x);
+		IF FLOAT(i) = -x THEN
+			RETURN -i;
+		ELSE
+			RETURN -i -1;
+		END;
+	END;
+	RETURN TRUNC(x);
+  END entier;
+
+  PROCEDURE real(x: INTEGER): REAL;
+  BEGIN
+	IF x < 0 THEN
+		RETURN - FLOAT(-x);
+	END;
+	RETURN FLOAT(x);
+  END real;
+
+BEGIN
+END MathLib0.
Index: /trunk/minix/lib/ack/libm2/Mathlib.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/Mathlib.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/Mathlib.mod	(revision 9)
@@ -0,0 +1,576 @@
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE Mathlib;
+(*
+  Module:	Mathematical functions
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/Mathlib.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+*)
+
+  FROM	EM IMPORT	FIF, FEF;
+  FROM	Traps IMPORT	Message;
+
+  CONST
+	OneRadianInDegrees	= 57.295779513082320876798155D;
+	OneDegreeInRadians	=  0.017453292519943295769237D;
+	OneOverSqrt2		= 0.70710678118654752440084436210484904D;
+
+  (* basic functions *)
+
+  PROCEDURE pow(x: REAL; i: INTEGER): REAL;
+  BEGIN
+	RETURN SHORT(longpow(LONG(x), i));
+  END pow;
+
+  PROCEDURE longpow(x: LONGREAL; i: INTEGER): LONGREAL;
+    VAR	val: LONGREAL;
+	ri: LONGREAL;
+  BEGIN
+	ri := FLOATD(i);
+	IF x < 0.0D THEN
+		val := longexp(longln(-x) * ri);
+		IF ODD(i) THEN RETURN -val;
+		ELSE RETURN val;
+		END;
+	ELSIF x = 0.0D THEN
+		RETURN 0.0D;
+	ELSE
+		RETURN longexp(longln(x) * ri);
+	END;
+  END longpow;
+
+  PROCEDURE sqrt(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longsqrt(LONG(x)));
+  END sqrt;
+
+  PROCEDURE longsqrt(x: LONGREAL): LONGREAL;
+    VAR
+	temp: LONGREAL;
+	exp, i: INTEGER;
+  BEGIN
+	IF x <= 0.0D THEN
+		IF x < 0.0D THEN
+			Message("sqrt: negative argument");
+			HALT
+		END;
+		RETURN 0.0D;
+	END;
+	temp := FEF(x,exp);
+	(*
+	 * NOTE
+	 * this wont work on 1's comp
+	 *)
+	IF ODD(exp) THEN
+		temp := 2.0D * temp;
+		DEC(exp);
+	END;
+	temp := 0.5D*(1.0D + temp);
+
+	WHILE exp > 28 DO
+		temp := temp * 16384.0D;
+		exp := exp - 28;
+	END;
+	WHILE exp < -28 DO
+		temp := temp / 16384.0D;
+		exp := exp + 28;
+	END;
+	WHILE exp >= 2 DO
+		temp := temp * 2.0D;
+		exp := exp - 2;
+	END;
+	WHILE exp <= -2 DO
+		temp := temp / 2.0D;
+		exp := exp + 2;
+	END;
+	FOR i := 0 TO 5 DO
+		temp := 0.5D*(temp + x/temp);
+	END;
+	RETURN temp;
+  END longsqrt;
+
+  PROCEDURE ldexp(x:LONGREAL; n: INTEGER): LONGREAL;
+  BEGIN
+	WHILE n >= 16 DO
+		x := x * 65536.0D;
+		n := n - 16;
+	END;
+	WHILE n > 0 DO
+		x := x * 2.0D;
+		DEC(n);
+	END;
+	WHILE n <= -16 DO
+		x := x / 65536.0D;
+		n := n + 16;
+	END;
+	WHILE n < 0 DO
+		x := x / 2.0D;
+		INC(n);
+	END;
+	RETURN x;
+  END ldexp;
+
+  PROCEDURE exp(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longexp(LONG(x)));
+  END exp;
+
+  PROCEDURE longexp(x: LONGREAL): LONGREAL;
+  (*	Algorithm and coefficients from:
+		"Software manual for the elementary functions"
+		by W.J. Cody and W. Waite, Prentice-Hall, 1980
+  *)
+    CONST
+	p0 = 0.25000000000000000000D+00;
+	p1 = 0.75753180159422776666D-02;
+	p2 = 0.31555192765684646356D-04;
+	q0 = 0.50000000000000000000D+00;
+	q1 = 0.56817302698551221787D-01;
+	q2 = 0.63121894374398503557D-03;
+	q3 = 0.75104028399870046114D-06;
+
+    VAR
+	neg: BOOLEAN;
+	n: INTEGER;
+	xn, g, x1, x2: LONGREAL;
+  BEGIN
+	neg := x < 0.0D;
+	IF neg THEN
+		x := -x;
+	END;
+	n := TRUNC(x/longln2 + 0.5D);
+	xn := FLOATD(n);
+	x1 := FLOATD(TRUNCD(x));
+	x2 := x - x1;
+	g := ((x1 - xn * 0.693359375D)+x2) - xn * (-2.1219444005469058277D-4);
+	IF neg THEN
+		g := -g;
+		n := -n;
+	END;
+	xn := g*g;
+	x := g*((p2*xn+p1)*xn+p0);
+	INC(n);
+	RETURN ldexp(0.5D + x/((((q3*xn+q2)*xn+q1)*xn+q0) - x), n);
+  END longexp;
+
+  PROCEDURE ln(x: REAL): REAL;	(* natural log *)
+  BEGIN
+	RETURN SHORT(longln(LONG(x)));
+  END ln;
+
+  PROCEDURE longln(x: LONGREAL): LONGREAL;	(* natural log *)
+  (*	Algorithm and coefficients from:
+		"Software manual for the elementary functions"
+		by W.J. Cody and W. Waite, Prentice-Hall, 1980
+   *)
+    CONST
+	p0 = -0.64124943423745581147D+02;
+	p1 =  0.16383943563021534222D+02;
+	p2 = -0.78956112887491257267D+00;
+	q0 = -0.76949932108494879777D+03;
+	q1 =  0.31203222091924532844D+03;
+	q2 = -0.35667977739034646171D+02;
+	q3 =  1.0D;
+    VAR
+	exp: INTEGER;
+	z, znum, zden, w: LONGREAL;
+
+  BEGIN
+	IF x <= 0.0D THEN
+		Message("ln: argument <= 0");
+		HALT
+	END;
+	x := FEF(x, exp);
+	IF x > OneOverSqrt2 THEN
+		znum := (x - 0.5D) - 0.5D;
+		zden := x * 0.5D + 0.5D;
+	ELSE
+		znum := x - 0.5D;
+		zden := znum * 0.5D + 0.5D;
+		DEC(exp);
+	END;
+	z := znum / zden;
+	w := z * z;
+	x := z + z * w * (((p2*w+p1)*w+p0)/(((q3*w+q2)*w+q1)*w+q0));
+	z := FLOATD(exp);
+	x := x + z * (-2.121944400546905827679D-4);
+	RETURN x + z * 0.693359375D;
+  END longln;
+
+  PROCEDURE log(x: REAL): REAL;	(* log with base 10 *)
+  BEGIN
+	RETURN SHORT(longlog(LONG(x)));
+  END log;
+
+  PROCEDURE longlog(x: LONGREAL): LONGREAL;	(* log with base 10 *)
+  BEGIN
+	RETURN longln(x)/longln10;
+  END longlog;
+
+  (* trigonometric functions; arguments in radians *)
+
+  PROCEDURE sin(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longsin(LONG(x)));
+  END sin;
+
+  PROCEDURE sinus(x: LONGREAL; cosflag: BOOLEAN) : LONGREAL;
+  (*	Algorithm and coefficients from:
+		"Software manual for the elementary functions"
+		by W.J. Cody and W. Waite, Prentice-Hall, 1980
+  *)
+    CONST
+	r0 = -0.16666666666666665052D+00;
+	r1 =  0.83333333333331650314D-02;
+	r2 = -0.19841269841201840457D-03;
+	r3 =  0.27557319210152756119D-05;
+	r4 = -0.25052106798274584544D-07;
+	r5 =  0.16058936490371589114D-09;
+	r6 = -0.76429178068910467734D-12;
+	r7 =  0.27204790957888846175D-14;
+	A1 =  3.1416015625D;
+	A2 = -8.908910206761537356617D-6;
+    VAR
+	x1, x2, y : LONGREAL;
+	neg : BOOLEAN;
+  BEGIN
+	IF x < 0.0D THEN
+		neg := TRUE;
+		x := -x
+	ELSE	neg := FALSE
+	END;
+	IF cosflag THEN
+		neg := FALSE;
+		y := longhalfpi + x
+	ELSE
+		y := x
+	END;
+	y := y / longpi + 0.5D;
+
+	IF FIF(y, 1.0D, y) < 0.0D THEN ; END;
+	IF FIF(y, 0.5D, x1) # 0.0D THEN neg := NOT neg END;
+	IF cosflag THEN y := y - 0.5D END;
+	x2 := FIF(x, 1.0, x1);
+	x := x1 - y * A1;
+	x := x + x2;
+	x := x - y * A2;
+
+	IF x < 0.0D THEN
+		neg := NOT neg;
+		x := -x
+	END;
+	y := x * x;
+	x := x + x * y * (((((((r7*y+r6)*y+r5)*y+r4)*y+r3)*y+r2)*y+r1)*y+r0);
+	IF neg THEN RETURN -x END;
+	RETURN x;
+  END sinus;
+
+  PROCEDURE longsin(x: LONGREAL): LONGREAL;
+  BEGIN
+	RETURN sinus(x, FALSE);
+  END longsin;
+
+  PROCEDURE cos(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longcos(LONG(x)));
+  END cos;
+
+  PROCEDURE longcos(x: LONGREAL): LONGREAL;
+  BEGIN
+	IF x < 0.0D THEN x := -x; END;
+	RETURN sinus(x, TRUE);	
+  END longcos;
+
+  PROCEDURE tan(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longtan(LONG(x)));
+  END tan;
+
+  PROCEDURE longtan(x: LONGREAL): LONGREAL;
+  (*	Algorithm and coefficients from:
+		"Software manual for the elementary functions"
+		by W.J. Cody and W. Waite, Prentice-Hall, 1980
+  *)
+
+    CONST
+	p1 = -0.13338350006421960681D+00;
+	p2 =  0.34248878235890589960D-02;
+	p3 = -0.17861707342254426711D-04;
+
+	q0 =  1.0D;
+	q1 = -0.46671683339755294240D+00;
+	q2 =  0.25663832289440112864D-01;
+	q3 = -0.31181531907010027307D-03;
+	q4 =  0.49819433993786512270D-06;
+
+	A1 =  1.57080078125D;
+	A2 = -4.454455103380768678308D-06;
+
+    VAR y, x1, x2: LONGREAL;
+	negative: BOOLEAN;
+	invert: BOOLEAN;
+  BEGIN
+	negative := x < 0.0D;
+	y := x / longhalfpi + 0.5D;
+
+        (*      Use extended precision to calculate reduced argument.
+                Here we used 12 bits of the mantissa for a1.
+                Also split x in integer part x1 and fraction part x2.
+        *)
+	IF FIF(y, 1.0D, y) < 0.0D THEN ; END;
+	invert := FIF(y, 0.5D, x1) # 0.0D;
+	x2 := FIF(x, 1.0D, x1);
+	x := x1 - y * A1;
+	x := x + x2;
+	x := x - y * A2;
+
+	y := x * x;
+	x := x + x * y * ((p3*y+p2)*y+p1);
+	y := (((q4*y+q3)*y+q2)*y+q1)*y+q0;
+	IF negative THEN x := -x END;
+	IF invert THEN RETURN -y/x END;
+	RETURN x/y;
+  END longtan;
+
+  PROCEDURE arcsin(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longarcsin(LONG(x)));
+  END arcsin;
+
+  PROCEDURE arcsincos(x: LONGREAL; cosfl: BOOLEAN): LONGREAL;
+    CONST
+	p0 = -0.27368494524164255994D+02;
+	p1 =  0.57208227877891731407D+02;
+	p2 = -0.39688862997540877339D+02;
+	p3 =  0.10152522233806463645D+02;
+	p4 = -0.69674573447350646411D+00;
+
+	q0 = -0.16421096714498560795D+03;
+	q1 =  0.41714430248260412556D+03;
+	q2 = -0.38186303361750149284D+03;
+	q3 =  0.15095270841030604719D+03;
+	q4 = -0.23823859153670238830D+02;
+	q5 =  1.0D;
+    VAR
+	negative : BOOLEAN;
+	big: BOOLEAN;
+	g: LONGREAL;
+  BEGIN
+	negative := x < 0.0D;
+	IF negative THEN x := -x; END;
+	IF x > 0.5D THEN
+		big := TRUE;
+		IF x > 1.0D THEN
+			Message("arcsin or arccos: argument > 1");
+			HALT
+		END;
+		g := 0.5D - 0.5D * x;
+		x := -longsqrt(g);
+		x := x + x;
+	ELSE
+		big := FALSE;
+		g := x * x;
+	END;
+	x := x + x * g *
+	  ((((p4*g+p3)*g+p2)*g+p1)*g+p0)/(((((q5*g+q4)*g+q3)*g+q2)*g+q1)*g+q0);
+	IF cosfl AND NOT negative THEN x := -x END;
+	IF cosfl = NOT big THEN
+		x := (x + longquartpi) + longquartpi;
+	ELSIF cosfl AND negative AND big THEN
+		x := (x + longhalfpi) + longhalfpi;
+	END;
+	IF negative AND NOT cosfl THEN x := -x END;
+	RETURN x;
+  END arcsincos;	
+
+  PROCEDURE longarcsin(x: LONGREAL): LONGREAL;
+  BEGIN
+	RETURN arcsincos(x, FALSE);
+  END longarcsin;
+
+  PROCEDURE arccos(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longarccos(LONG(x)));
+  END arccos;
+
+  PROCEDURE longarccos(x: LONGREAL): LONGREAL;
+  BEGIN
+	RETURN arcsincos(x, TRUE);
+  END longarccos;
+
+  PROCEDURE arctan(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longarctan(LONG(x)));
+  END arctan;
+
+  VAR A: ARRAY[0..3] OF LONGREAL;
+      arctaninit: BOOLEAN;
+
+  PROCEDURE longarctan(x: LONGREAL): LONGREAL;
+  (*	Algorithm and coefficients from:
+		"Software manual for the elementary functions"
+		by W.J. Cody and W. Waite, Prentice-Hall, 1980
+  *)
+    CONST
+	p0 = -0.13688768894191926929D+02;
+	p1 = -0.20505855195861651981D+02;
+	p2 = -0.84946240351320683534D+01;
+	p3 = -0.83758299368150059274D+00;
+	q0 =  0.41066306682575781263D+02;
+	q1 =  0.86157349597130242515D+02;
+	q2 =  0.59578436142597344465D+02;
+	q3 =  0.15024001160028576121D+02;
+	q4 =  1.0D;
+    VAR
+	g: LONGREAL;
+	neg: BOOLEAN;
+	n: INTEGER;
+  BEGIN
+	IF NOT arctaninit THEN
+		arctaninit := TRUE;
+		A[0] := 0.0D;
+		A[1] := 0.52359877559829887307710723554658381D;	(* p1/6 *)
+		A[2] := longhalfpi;
+		A[3] := 1.04719755119659774615421446109316763D; (* pi/3 *)
+	END;
+	neg := FALSE;
+	IF x < 0.0D THEN
+		neg := TRUE;
+		x := -x;
+	END;
+	IF x > 1.0D THEN
+		x := 1.0D/x;
+		n := 2
+	ELSE
+		n := 0
+	END;
+	IF x > 0.26794919243112270647D (* 2-sqrt(3) *) THEN
+		INC(n);
+		x := (((0.73205080756887729353D*x-0.5D)-0.5D)+x)/
+			(1.73205080756887729353D + x);
+	END;
+	g := x*x;
+	x := x + x * g * (((p3*g+p2)*g+p1)*g+p0) / ((((q4*g+q3)*g+q2)*g+q1)*g+q0);
+	IF n > 1 THEN x := -x END;
+	x := x + A[n];
+	IF neg THEN RETURN -x; END;
+	RETURN x;
+  END longarctan;
+
+  (* hyperbolic functions *)
+  (* The C math library has better implementations for some of these, but
+     they depend on some properties of the floating point implementation,
+     and, for now, we don't want that in the Modula-2 system.
+  *)
+
+  PROCEDURE sinh(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longsinh(LONG(x)));
+  END sinh;
+
+  PROCEDURE longsinh(x: LONGREAL): LONGREAL;
+    VAR expx: LONGREAL;
+  BEGIN
+	expx := longexp(x);
+	RETURN (expx - 1.0D/expx)/2.0D;
+  END longsinh;
+
+  PROCEDURE cosh(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longcosh(LONG(x)));
+  END cosh;
+
+  PROCEDURE longcosh(x: LONGREAL): LONGREAL;
+    VAR expx: LONGREAL;
+  BEGIN
+	expx := longexp(x);
+	RETURN (expx + 1.0D/expx)/2.0D;
+  END longcosh;
+
+  PROCEDURE tanh(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longtanh(LONG(x)));
+  END tanh;
+
+  PROCEDURE longtanh(x: LONGREAL): LONGREAL;
+    VAR expx: LONGREAL;
+  BEGIN
+	expx := longexp(x);
+	RETURN (expx - 1.0D/expx) / (expx + 1.0D/expx);
+  END longtanh;
+
+  PROCEDURE arcsinh(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longarcsinh(LONG(x)));
+  END arcsinh;
+
+  PROCEDURE longarcsinh(x: LONGREAL): LONGREAL;
+    VAR neg: BOOLEAN;
+  BEGIN
+	neg := FALSE;
+	IF x < 0.0D THEN
+		neg := TRUE;
+		x := -x;
+	END;
+	x := longln(x + longsqrt(x*x+1.0D));
+	IF neg THEN RETURN -x; END;
+	RETURN x;
+  END longarcsinh;
+
+  PROCEDURE arccosh(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longarccosh(LONG(x)));
+  END arccosh;
+
+  PROCEDURE longarccosh(x: LONGREAL): LONGREAL;
+  BEGIN
+	IF x < 1.0D THEN
+		Message("arccosh: argument < 1");
+		HALT
+	END;
+	RETURN longln(x + longsqrt(x*x - 1.0D));
+  END longarccosh;
+
+  PROCEDURE arctanh(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longarctanh(LONG(x)));
+  END arctanh;
+
+  PROCEDURE longarctanh(x: LONGREAL): LONGREAL;
+  BEGIN
+	IF (x <= -1.0D) OR (x >= 1.0D) THEN
+		Message("arctanh: ABS(argument) >= 1");
+		HALT
+	END;
+	RETURN longln((1.0D + x)/(1.0D - x)) / 2.0D;
+  END longarctanh;
+
+  (* conversions *)
+
+  PROCEDURE RadianToDegree(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longRadianToDegree(LONG(x)));
+  END RadianToDegree;
+
+  PROCEDURE longRadianToDegree(x: LONGREAL): LONGREAL;
+  BEGIN
+	RETURN x * OneRadianInDegrees;
+  END longRadianToDegree;
+
+  PROCEDURE DegreeToRadian(x: REAL): REAL;
+  BEGIN
+	RETURN SHORT(longDegreeToRadian(LONG(x)));
+  END DegreeToRadian;
+
+  PROCEDURE longDegreeToRadian(x: LONGREAL): LONGREAL;
+  BEGIN
+	RETURN x * OneDegreeInRadians;
+  END longDegreeToRadian;
+
+BEGIN
+	arctaninit := FALSE;
+END Mathlib.
Index: /trunk/minix/lib/ack/libm2/PascalIO.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/PascalIO.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/PascalIO.mod	(revision 9)
@@ -0,0 +1,437 @@
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE PascalIO;
+(*
+  Module:	Pascal-like Input/Output
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/PascalIO.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+*)
+
+  FROM	Conversions IMPORT
+			ConvertInteger, ConvertCardinal;
+  FROM	RealConversions IMPORT
+			LongRealToString, StringToLongReal;
+  FROM	Traps IMPORT	Message;
+  FROM	Streams IMPORT	Stream, StreamKind, StreamMode, StreamResult,
+			InputStream, OutputStream, OpenStream, CloseStream, 
+			EndOfStream, Read, Write, StreamBuffering;
+  FROM	Storage IMPORT	Allocate;
+  FROM	SYSTEM IMPORT	ADR;
+
+  TYPE	charset = SET OF CHAR;
+	btype = (Preading, Pwriting, free);
+
+  CONST	spaces = charset{11C, 12C, 13C, 14C, 15C, ' '};
+
+  TYPE	IOstream = RECORD
+			type: btype;
+			done, eof : BOOLEAN;
+			ch: CHAR;
+			next: Text;
+			stream: Stream;
+		END;
+	Text =	POINTER TO IOstream;
+	numbuf = ARRAY[0..255] OF CHAR;
+
+  VAR	ibuf, obuf: IOstream;
+	head: Text;
+	result: StreamResult;
+
+  PROCEDURE Reset(VAR InputText: Text; Filename: ARRAY OF CHAR);
+  BEGIN
+	doclose(InputText);
+	getstruct(InputText);
+	WITH InputText^ DO
+		OpenStream(stream, Filename, text, reading, result);
+		IF result # succeeded THEN
+			Message("could not open input file");
+			HALT;
+		END;
+		type := Preading;
+		done := FALSE;
+		eof := FALSE;
+	END;
+  END Reset;
+
+  PROCEDURE Rewrite(VAR OutputText: Text; Filename: ARRAY OF CHAR);
+  BEGIN
+	doclose(OutputText);
+	getstruct(OutputText);
+	WITH OutputText^ DO
+		OpenStream(stream, Filename, text, writing, result);
+		IF result # succeeded THEN
+			Message("could not open output file");
+			HALT;
+		END;
+		type := Pwriting;
+	END;
+  END Rewrite;
+
+  PROCEDURE CloseOutput();
+  VAR p: Text;
+  BEGIN
+	p := head;
+	WHILE p # NIL DO
+		doclose(p);
+		p := p^.next;
+	END;
+  END CloseOutput;
+
+  PROCEDURE doclose(Xtext: Text);
+  BEGIN
+	IF Xtext # Notext THEN
+		WITH Xtext^ DO
+			IF type # free THEN
+				CloseStream(stream, result);
+				type := free;
+			END;
+		END;
+	END;
+  END doclose;
+
+  PROCEDURE getstruct(VAR Xtext: Text);
+  BEGIN
+	Xtext := head;
+	WHILE (Xtext # NIL) AND (Xtext^.type # free) DO
+		Xtext := Xtext^.next;
+	END;
+	IF Xtext = NIL THEN
+		Allocate(Xtext,SIZE(IOstream));
+		Xtext^.next := head;
+		head := Xtext;
+	END;
+  END getstruct;
+
+  PROCEDURE Error(tp: btype);
+  BEGIN
+	IF tp = Preading THEN
+		Message("input text expected");
+	ELSE
+		Message("output text expected");
+	END;
+	HALT;
+  END Error;
+
+  PROCEDURE ReadChar(InputText: Text; VAR ch : CHAR);
+  BEGIN
+	ch := NextChar(InputText);
+	IF InputText^.eof THEN
+		Message("unexpected EOF");
+		HALT;
+	END;
+	InputText^.done := FALSE;
+  END ReadChar;
+
+  PROCEDURE NextChar(InputText: Text): CHAR;
+  BEGIN
+	WITH InputText^ DO
+		IF type # Preading THEN Error(Preading); END;
+		IF NOT done THEN
+			IF EndOfStream(stream, result) THEN
+				eof := TRUE;
+				ch := 0C;
+			ELSE
+				Read(stream, ch, result);
+				done := TRUE;
+			END;
+		END;
+		RETURN ch;
+	END;
+  END NextChar;
+
+  PROCEDURE Get(InputText: Text);
+  VAR dummy: CHAR;
+  BEGIN
+	ReadChar(InputText, dummy);
+  END Get;
+
+  PROCEDURE Eoln(InputText: Text): BOOLEAN;
+  BEGIN
+	RETURN NextChar(InputText) = 12C;
+  END Eoln;
+
+  PROCEDURE Eof(InputText: Text): BOOLEAN;
+  BEGIN
+	RETURN (NextChar(InputText) = 0C) AND InputText^.eof;
+  END Eof;
+
+  PROCEDURE ReadLn(InputText: Text);
+  VAR ch: CHAR;
+  BEGIN
+	REPEAT
+		ReadChar(InputText, ch)
+	UNTIL ch = 12C;
+  END ReadLn;
+
+  PROCEDURE WriteChar(OutputText: Text; char: CHAR);
+  BEGIN
+	WITH OutputText^ DO
+		IF type # Pwriting THEN Error(Pwriting); END;
+		Write(stream, char, result);
+	END;
+  END WriteChar;
+
+  PROCEDURE WriteLn(OutputText: Text);
+  BEGIN
+	WriteChar(OutputText, 12C);
+  END WriteLn;
+
+  PROCEDURE Page(OutputText: Text);
+  BEGIN
+	WriteChar(OutputText, 14C);
+  END Page;
+
+  PROCEDURE ReadInteger(InputText: Text; VAR int : INTEGER);
+  CONST
+    	SAFELIMITDIV10 = MAX(INTEGER) DIV 10;
+    	SAFELIMITREM10 = MAX(INTEGER) MOD 10;
+  VAR
+    	neg : BOOLEAN;
+    	safedigit: CARDINAL;
+	ch: CHAR;
+    	chvalue: CARDINAL;
+  BEGIN
+    	WHILE NextChar(InputText) IN spaces DO
+		Get(InputText);
+	END;
+	ch := NextChar(InputText);
+    	IF ch = '-' THEN
+		Get(InputText);
+		ch := NextChar(InputText);
+		neg := TRUE;
+    	ELSIF ch = '+' THEN
+		Get(InputText);
+		ch := NextChar(InputText);
+		neg := FALSE;
+    	ELSE
+		neg := FALSE
+    	END;
+
+    	safedigit := SAFELIMITREM10;
+    	IF neg THEN safedigit := safedigit + 1 END;
+    	int := 0;
+	IF (ch >= '0') AND (ch <= '9') THEN
+		WHILE (ch >= '0') & (ch <= '9') DO
+  			chvalue := ORD(ch) - ORD('0');
+	   		IF (int < -SAFELIMITDIV10) OR 
+		   	   ( (int = -SAFELIMITDIV10) AND
+		     	     (chvalue > safedigit)) THEN
+				Message("integer too large");
+				HALT;
+	    		ELSE
+				int := 10*int - VAL(INTEGER, chvalue);
+				Get(InputText);
+				ch := NextChar(InputText);
+	    		END;
+		END;
+		IF NOT neg THEN
+   			int := -int
+		END;
+	ELSE
+		Message("integer expected");
+		HALT;
+	END;
+  END ReadInteger;
+
+  PROCEDURE ReadCardinal(InputText: Text; VAR card : CARDINAL);
+  CONST
+    	SAFELIMITDIV10 = MAX(CARDINAL) DIV 10;
+    	SAFELIMITREM10 = MAX(CARDINAL) MOD 10;
+
+  VAR
+    	ch : CHAR;
+    	safedigit: CARDINAL;
+    	chvalue: CARDINAL;
+  BEGIN
+    	WHILE NextChar(InputText) IN spaces DO
+		Get(InputText);
+	END;
+	ch := NextChar(InputText);
+    	safedigit := SAFELIMITREM10;
+    	card := 0;
+	IF (ch >= '0') AND (ch <= '9') THEN
+		WHILE (ch >= '0') & (ch <= '9') DO
+  			chvalue := ORD(ch) - ORD('0');
+	    		IF (card > SAFELIMITDIV10) OR 
+			   ( (card = SAFELIMITDIV10) AND
+			     (chvalue > safedigit)) THEN
+				Message("cardinal too large");
+				HALT;
+		    	ELSE
+				card := 10*card + chvalue;
+				Get(InputText);
+				ch := NextChar(InputText);
+		    	END;
+		END;
+	ELSE
+		Message("cardinal expected");
+		HALT;
+	END;
+  END ReadCardinal;
+
+  PROCEDURE ReadReal(InputText: Text; VAR real: REAL);
+  VAR x1: LONGREAL;
+  BEGIN
+	ReadLongReal(InputText, x1);
+	real := x1
+  END ReadReal;
+
+  PROCEDURE ReadLongReal(InputText: Text; VAR real: LONGREAL);
+  VAR
+	buf: numbuf;
+	ch: CHAR;
+	ok: BOOLEAN;
+	index: INTEGER;
+
+    PROCEDURE inch(): CHAR;
+    BEGIN
+	buf[index] := ch;
+	INC(index);
+	Get(InputText);
+	RETURN NextChar(InputText);
+    END inch;
+
+  BEGIN
+	index := 0;
+	ok := TRUE;
+    	WHILE NextChar(InputText) IN spaces DO
+		Get(InputText);
+	END;
+	ch := NextChar(InputText);
+	IF (ch ='+') OR (ch = '-') THEN
+		ch := inch();
+	END;
+	IF (ch >= '0') AND (ch <= '9') THEN
+		WHILE (ch >= '0') AND (ch <= '9') DO
+			ch := inch();
+		END;
+		IF (ch = '.') THEN
+			ch := inch();
+			IF (ch >= '0') AND (ch <= '9') THEN
+				WHILE (ch >= '0') AND (ch <= '9') DO
+					ch := inch();
+				END;
+			ELSE
+				ok := FALSE;
+			END;
+		END;
+		IF ok AND (ch = 'E') THEN
+			ch := inch();
+			IF (ch ='+') OR (ch = '-') THEN
+				ch := inch();
+			END;
+			IF (ch >= '0') AND (ch <= '9') THEN
+				WHILE (ch >= '0') AND (ch <= '9') DO
+					ch := inch();
+				END;
+			ELSE
+				ok := FALSE;
+			END;
+		END;
+	ELSE
+		ok := FALSE;
+	END;
+	IF ok THEN
+		buf[index] := 0C;
+		StringToLongReal(buf, real, ok);
+	END;
+	IF NOT ok THEN
+		Message("Illegal real");
+		HALT;
+	END;
+  END ReadLongReal;
+
+  PROCEDURE WriteCardinal(OutputText: Text; card: CARDINAL; width: CARDINAL);
+  VAR
+    	buf : numbuf;
+  BEGIN
+	ConvertCardinal(card, 1, buf);
+	WriteString(OutputText, buf, width);
+  END WriteCardinal;
+
+  PROCEDURE WriteInteger(OutputText: Text; int: INTEGER; width: CARDINAL);
+  VAR
+    	buf : numbuf;
+  BEGIN
+    	ConvertInteger(int, 1, buf);
+	WriteString(OutputText, buf, width);
+  END WriteInteger;
+
+  PROCEDURE WriteBoolean(OutputText: Text; bool: BOOLEAN; width: CARDINAL);
+  BEGIN
+	IF bool THEN
+		WriteString(OutputText, " TRUE", width);
+	ELSE
+		WriteString(OutputText, "FALSE", width);
+	END;
+  END WriteBoolean;
+
+  PROCEDURE WriteReal(OutputText: Text; real: REAL; width, nfrac: CARDINAL);
+  BEGIN
+	WriteLongReal(OutputText, LONG(real), width, nfrac)
+  END WriteReal;
+
+  PROCEDURE WriteLongReal(OutputText: Text; real: LONGREAL; width, nfrac: CARDINAL);
+  VAR
+	buf: numbuf;
+	ok: BOOLEAN;
+	digits: INTEGER;
+  BEGIN
+	IF width > SIZE(buf) THEN
+		width := SIZE(buf);
+	END;
+	IF nfrac > 0 THEN
+		LongRealToString(real, width, nfrac, buf, ok);
+	ELSE
+		IF width < 9 THEN width := 9; END;
+		IF real < 0.0D THEN
+			digits := 7 - INTEGER(width);
+		ELSE
+			digits := 6 - INTEGER(width);
+		END;
+		LongRealToString(real, width, digits, buf, ok);
+	END;
+	WriteString(OutputText, buf, 0);
+  END WriteLongReal;
+
+  PROCEDURE WriteString(OutputText: Text; str: ARRAY OF CHAR; width: CARDINAL);
+  VAR index: CARDINAL;
+  BEGIN
+	index := 0;
+	WHILE (index <= HIGH(str)) AND (str[index] # Eos) DO
+		INC(index);
+	END;
+	WHILE index < width DO
+		WriteChar(OutputText, " ");
+		INC(index);
+	END;
+	index := 0;
+	WHILE (index <= HIGH(str)) AND (str[index] # Eos) DO
+		WriteChar(OutputText, str[index]);
+		INC(index);
+	END;
+  END WriteString;
+
+BEGIN	(* PascalIO initialization *)
+	WITH ibuf DO
+		stream := InputStream;
+		eof := FALSE;
+		type := Preading;
+		done := FALSE;
+	END;
+	WITH obuf DO
+		stream := OutputStream;
+		eof := FALSE;
+		type := Pwriting;
+	END;
+	Notext := NIL;
+	Input := ADR(ibuf);
+	Output := ADR(obuf);
+	Input^.next := Output;
+	Output^.next := NIL;
+	head := Input;
+END PascalIO.
Index: /trunk/minix/lib/ack/libm2/Processes.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/Processes.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/Processes.mod	(revision 9)
@@ -0,0 +1,101 @@
+(*$R-*)
+IMPLEMENTATION MODULE Processes [1];
+(*
+  Module:       Processes
+  From:         "Programming in Modula-2", 3rd, corrected edition, by N. Wirth
+  Version:      $Header: /cvsup/minix/src/lib/ack/libm2/Processes.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+*)
+
+  FROM	SYSTEM IMPORT	ADDRESS, TSIZE, NEWPROCESS, TRANSFER;
+  FROM	Storage IMPORT	Allocate;
+  FROM	Traps IMPORT	Message;
+
+  TYPE	SIGNAL = POINTER TO ProcessDescriptor;
+
+	ProcessDescriptor =
+		RECORD	next: SIGNAL;	(* ring *)
+			queue: SIGNAL;	(* queue of waiting processes *)
+			cor: ADDRESS;
+			ready: BOOLEAN;
+		END;
+
+  VAR	cp: SIGNAL;			(* current process *)
+
+  PROCEDURE StartProcess(P: PROC; n: CARDINAL);
+    VAR	s0: SIGNAL;
+	wsp: ADDRESS;
+  BEGIN
+	s0 := cp;
+	Allocate(wsp, n);
+	Allocate(cp, TSIZE(ProcessDescriptor));
+	WITH cp^ DO
+		next := s0^.next;
+		s0^.next := cp;
+		ready := TRUE;
+		queue := NIL
+	END;
+	NEWPROCESS(P, wsp, n, cp^.cor);
+	TRANSFER(s0^.cor, cp^.cor);
+  END StartProcess;
+
+  PROCEDURE SEND(VAR s: SIGNAL);
+    VAR	s0: SIGNAL;
+  BEGIN
+	IF s # NIL THEN
+		s0 := cp;
+		cp := s;
+		WITH cp^ DO
+			s := queue;
+			ready := TRUE;
+			queue := NIL
+		END;
+		TRANSFER(s0^.cor, cp^.cor);
+	END
+  END SEND;
+
+  PROCEDURE WAIT(VAR s: SIGNAL);
+    VAR	s0, s1: SIGNAL;
+  BEGIN
+	(* insert cp in queue s *)
+	IF s = NIL THEN
+		s := cp
+	ELSE
+		s0 := s;
+		s1 := s0^.queue;
+		WHILE s1 # NIL DO
+			s0 := s1;
+			s1 := s0^.queue
+		END;
+		s0^.queue := cp
+	END;
+	s0 := cp;
+	REPEAT
+		cp := cp^.next
+	UNTIL cp^.ready;
+	IF cp = s0 THEN
+		(* deadlock *)
+		Message("deadlock");
+		HALT
+	END;
+	s0^.ready := FALSE;
+	TRANSFER(s0^.cor, cp^.cor)
+  END WAIT;
+
+  PROCEDURE Awaited(s: SIGNAL): BOOLEAN;
+  BEGIN
+	RETURN s # NIL
+  END Awaited;
+
+  PROCEDURE Init(VAR s: SIGNAL);
+  BEGIN
+	s := NIL
+  END Init;
+
+BEGIN
+	Allocate(cp, TSIZE(ProcessDescriptor));
+	WITH cp^ DO
+		next := cp;
+		ready := TRUE;
+		queue := NIL
+	END
+END Processes.
Index: /trunk/minix/lib/ack/libm2/RealConver.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/RealConver.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/RealConver.mod	(revision 9)
@@ -0,0 +1,337 @@
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE RealConversions;
+(*
+  Module:       string-to-real and real-to-string conversions
+  Author:       Ceriel J.H. Jacobs
+  Version:      $Header: /cvsup/minix/src/lib/ack/libm2/RealConver.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+*)
+
+
+  PROCEDURE RealToString(arg: REAL;
+		width, digits: INTEGER;
+		VAR str: ARRAY OF CHAR;
+		VAR ok: BOOLEAN);
+  BEGIN
+	LongRealToString(LONG(arg), width, digits, str, ok);
+  END RealToString;
+
+  TYPE
+	Powers = RECORD
+		pval: LONGREAL;
+		rpval: LONGREAL;
+		exp: INTEGER
+	END;
+
+  VAR Powers10: ARRAY[1..6] OF Powers;
+
+  PROCEDURE LongRealToString(arg: LONGREAL;
+		width, digits: INTEGER;
+		VAR str: ARRAY OF CHAR;
+		VAR ok: BOOLEAN);
+    VAR	pointpos: INTEGER;
+	i: CARDINAL;
+	ecvtflag: BOOLEAN;
+	r: LONGREAL;
+	ind1, ind2 : CARDINAL;
+	sign: BOOLEAN;
+	ndigits: CARDINAL;
+
+  BEGIN
+	r := arg;
+	IF digits < 0 THEN
+		ecvtflag := TRUE;
+		ndigits := -digits;
+	ELSE
+		ecvtflag := FALSE;
+		ndigits := digits;
+	END;
+	IF (HIGH(str) < ndigits + 3) THEN
+		str[0] := 0C; ok := FALSE; RETURN
+	END;
+	pointpos := 0;
+	sign := r < 0.0D;
+	IF sign THEN r := -r END;
+	ok := TRUE;
+	IF NOT (r / 10.0D < r) THEN
+		(* assume Nan or Infinity *)
+		r := 0.0D;
+		ok := FALSE;
+	END;
+	IF r # 0.0D THEN
+		IF r >= 10.0D THEN
+			FOR i := 1 TO 6 DO
+				WITH Powers10[i] DO
+					WHILE r >= pval DO
+						r := r * rpval;
+						INC(pointpos, exp)
+					END;
+				END;
+			END;
+		END;
+		IF r < 1.0D THEN
+			FOR i := 1 TO 6 DO
+				WITH Powers10[i] DO
+					WHILE r*pval < 10.0D DO
+						r := r * pval;
+						DEC(pointpos, exp)
+					END;
+				END;
+			END;
+		END;
+		(* Now, we have r in [1.0, 10.0) *)
+		INC(pointpos);
+	END;
+	ind1 := 0;
+	ind2 := ndigits+1;
+
+	IF NOT ecvtflag THEN 
+		IF INTEGER(ind2) + pointpos <= 0 THEN
+			ind2 := 1;
+		ELSE
+			ind2 := INTEGER(ind2) + pointpos
+		END;
+	END;
+	IF ind2 > HIGH(str) THEN
+		ok := FALSE;
+		str[0] := 0C;
+		RETURN;
+	END;
+	WHILE ind1 < ind2 DO
+		str[ind1] := CHR(TRUNC(r)+ORD('0'));
+		r := 10.0D * (r - FLOATD(TRUNC(r)));
+		INC(ind1);
+	END;
+	IF ind2 > 0 THEN
+		DEC(ind2);
+		ind1 := ind2;
+		str[ind2] := CHR(ORD(str[ind2])+5);
+		WHILE str[ind2] > '9' DO
+			str[ind2] := '0';
+			IF ind2 > 0 THEN
+				DEC(ind2);
+				str[ind2] := CHR(ORD(str[ind2])+1);
+			ELSE
+				str[ind2] := '1';
+				INC(pointpos);
+				IF NOT ecvtflag THEN
+					IF ind1 > 0 THEN str[ind1] := '0'; END;
+					INC(ind1);
+				END;
+			END;
+		END;
+		IF (NOT ecvtflag) AND (ind1 = 0) THEN
+			str[0] := CHR(ORD(str[0])-5);
+			INC(ind1);
+		END;
+	END;
+	IF ecvtflag THEN
+		FOR i := ind1 TO 2 BY -1 DO
+			str[i] := str[i-1];
+		END;
+		str[1] := '.';
+		INC(ind1);
+		IF sign THEN
+			FOR i := ind1 TO 1 BY -1 DO
+				str[i] := str[i-1];
+			END;
+			INC(ind1);
+			str[0] := '-';
+		END;
+		IF (ind1 + 4) > HIGH(str) THEN
+			str[0] := 0C;
+			ok := FALSE;
+			RETURN;
+		END;
+		str[ind1] := 'E'; INC(ind1);
+		IF arg # 0.0D THEN DEC(pointpos); END;
+		IF pointpos < 0 THEN
+			pointpos := -pointpos;
+			str[ind1] := '-';
+		ELSE
+			str[ind1] := '+';
+		END;
+		INC(ind1);
+		str[ind1] := CHR(ORD('0') + CARDINAL(pointpos DIV 100));
+		pointpos := pointpos MOD 100;
+		INC(ind1);
+		str[ind1] := CHR(ORD('0') + CARDINAL(pointpos DIV 10));
+		INC(ind1);
+		str[ind1] := CHR(ORD('0') + CARDINAL(pointpos MOD 10));
+	ELSE
+		IF pointpos <= 0 THEN
+			FOR i := ind1 TO 1 BY -1 DO
+				str[i+CARDINAL(-pointpos)] := str[i-1];
+			END;
+			FOR i := 0 TO CARDINAL(-pointpos) DO
+				str[i] := '0';
+			END;
+			ind1 := ind1 + CARDINAL(1 - pointpos);
+			pointpos := 1;
+		END;
+		FOR i := ind1 TO CARDINAL(pointpos+1) BY -1 DO
+			str[i] := str[i-1];
+		END;
+		IF ndigits = 0 THEN
+			str[pointpos] := 0C;
+			ind1 := pointpos - 1;
+		ELSE
+			str[pointpos] := '.';
+			IF INTEGER(ind1) > pointpos+INTEGER(ndigits) THEN
+				ind1 := pointpos+INTEGER(ndigits);
+			END;
+			str[pointpos+INTEGER(ndigits)+1] := 0C;
+		END;
+		IF sign THEN
+			FOR i := ind1 TO 0 BY -1 DO
+				str[i+1] := str[i];
+			END;
+			str[0] := '-';
+			INC(ind1);
+		END;
+	END;
+	IF (ind1+1) <= HIGH(str) THEN str[ind1+1] := 0C; END;
+	IF ind1 >= CARDINAL(width) THEN
+		ok := FALSE;
+		RETURN;
+	END;
+	IF width > 0 THEN
+		DEC(width);
+	END;
+	IF (width > 0) AND (ind1 < CARDINAL(width)) THEN
+		FOR i := ind1 TO 0 BY -1 DO
+			str[i + CARDINAL(width) - ind1] := str[i];
+		END;
+		FOR i := 0 TO CARDINAL(width)-(ind1+1) DO
+			str[i] := ' ';
+		END;
+		ind1 := CARDINAL(width);
+		IF (ind1+1) <= HIGH(str) THEN
+			FOR ind1 := ind1+1 TO HIGH(str) DO
+				str[ind1] := 0C;
+			END;
+		END;
+	END;
+
+  END LongRealToString;
+
+	
+  PROCEDURE StringToReal(str: ARRAY OF CHAR;
+			 VAR r: REAL; VAR ok: BOOLEAN);
+    VAR x: LONGREAL;
+  BEGIN
+	StringToLongReal(str, x, ok);
+	IF ok THEN
+		r := x;
+	END;
+  END StringToReal;
+
+  PROCEDURE StringToLongReal(str: ARRAY OF CHAR;
+			 VAR r: LONGREAL; VAR ok: BOOLEAN);
+    CONST	BIG = 1.0D17;
+    TYPE	SETOFCHAR = SET OF CHAR;
+    VAR		pow10 : INTEGER;
+		i : INTEGER;
+		e : LONGREAL;
+		ch : CHAR;
+		signed: BOOLEAN;
+		signedexp: BOOLEAN;
+		iB: CARDINAL;
+
+  BEGIN
+	r := 0.0D;
+	pow10 := 0;
+	iB := 0;
+	ok := TRUE;
+	signed := FALSE;
+	WHILE (str[iB] = ' ') OR (str[iB] = CHR(9)) DO
+		INC(iB);
+		IF iB > HIGH(str) THEN
+			ok := FALSE;
+			RETURN;
+		END;
+	END;
+	IF str[iB] = '-' THEN signed := TRUE; INC(iB)
+	ELSIF str[iB] = '+' THEN INC(iB)
+	END;
+	ch := str[iB]; INC(iB);
+	IF NOT (ch IN SETOFCHAR{'0'..'9'}) THEN ok := FALSE; RETURN END;
+	REPEAT
+		IF r>BIG THEN INC(pow10) ELSE r:= 10.0D*r+FLOATD(ORD(ch)-ORD('0')) END;
+		IF iB <= HIGH(str) THEN
+			ch := str[iB]; INC(iB);
+		END;
+	UNTIL (iB > HIGH(str)) OR NOT (ch IN SETOFCHAR{'0'..'9'});
+	IF (ch = '.') AND (iB <= HIGH(str)) THEN
+		ch := str[iB]; INC(iB);
+		IF NOT (ch IN SETOFCHAR{'0'..'9'}) THEN ok := FALSE; RETURN END;
+		REPEAT
+			IF r < BIG THEN
+				r := 10.0D * r + FLOATD(ORD(ch)-ORD('0'));
+				DEC(pow10);
+			END;
+			IF iB <= HIGH(str) THEN
+				ch := str[iB]; INC(iB);
+			END;
+		UNTIL (iB > HIGH(str)) OR NOT (ch IN SETOFCHAR{'0'..'9'});
+	END;
+	IF (ch = 'E') THEN
+		IF iB > HIGH(str) THEN
+			ok := FALSE;
+			RETURN;
+		ELSE
+			ch := str[iB]; INC(iB);
+		END;
+		i := 0;
+		signedexp := FALSE;
+		IF (ch = '-') OR (ch = '+') THEN
+			signedexp := ch = '-';
+			IF iB > HIGH(str) THEN
+				ok := FALSE;
+				RETURN;
+			ELSE
+				ch := str[iB]; INC(iB);
+			END;
+		END;
+		IF NOT (ch IN SETOFCHAR{'0'..'9'}) THEN ok := FALSE; RETURN END;
+		REPEAT
+			i := i*10 + INTEGER(ORD(ch) - ORD('0'));
+			IF iB <= HIGH(str) THEN
+				ch := str[iB]; INC(iB);
+			END;
+		UNTIL (iB > HIGH(str)) OR NOT (ch IN SETOFCHAR{'0'..'9'});
+		IF signedexp THEN i := -i END;
+		pow10 := pow10 + i;
+	END;
+	IF pow10 < 0 THEN i := -pow10; ELSE i := pow10; END;
+	e := 1.0D;
+	DEC(i);
+	WHILE i >= 10 DO
+		e := e * 10000000000.0D;
+		DEC(i,10);
+	END;
+	WHILE i >= 0 DO
+		e := e * 10.0D;
+		DEC(i)
+	END;
+	IF pow10<0 THEN
+		r := r / e;
+	ELSE
+		r := r * e;
+	END;
+	IF signed THEN r := -r; END;
+	IF (iB <= HIGH(str)) AND (ORD(ch) > ORD(' ')) THEN ok := FALSE; END
+  END StringToLongReal;
+
+BEGIN
+	WITH Powers10[1] DO pval := 1.0D32; rpval := 1.0D-32; exp := 32 END;
+	WITH Powers10[2] DO pval := 1.0D16; rpval := 1.0D-16; exp := 16 END;
+	WITH Powers10[3] DO pval := 1.0D8; rpval := 1.0D-8; exp := 8 END;
+	WITH Powers10[4] DO pval := 1.0D4; rpval := 1.0D-4; exp := 4 END;
+	WITH Powers10[5] DO pval := 1.0D2; rpval := 1.0D-2; exp := 2 END;
+	WITH Powers10[6] DO pval := 1.0D1; rpval := 1.0D-1; exp := 1 END;
+END RealConversions.
Index: /trunk/minix/lib/ack/libm2/RealInOut.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/RealInOut.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/RealInOut.mod	(revision 9)
@@ -0,0 +1,97 @@
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE RealInOut;
+(*
+  Module:       InOut for REAL numbers
+  Author:	Ceriel J.H. Jacobs
+  Version:      $Header: /cvsup/minix/src/lib/ack/libm2/RealInOut.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+*)
+
+  FROM	InOut IMPORT	ReadString, WriteString, WriteOct;
+  FROM	Traps IMPORT	Message;
+  FROM	SYSTEM IMPORT	WORD;
+  FROM	RealConversions IMPORT
+			LongRealToString, StringToLongReal;
+
+  CONST	MAXNDIG = 32;
+	MAXWIDTH = MAXNDIG+7;
+  TYPE	RBUF = ARRAY [0..MAXWIDTH+1] OF CHAR;
+
+  PROCEDURE WriteReal(arg: REAL; ndigits: CARDINAL);
+  BEGIN
+	WriteLongReal(LONG(arg), ndigits)
+  END WriteReal;
+
+  PROCEDURE WriteLongReal(arg: LONGREAL; ndigits: CARDINAL);
+    VAR buf : RBUF;
+	ok : BOOLEAN;
+
+  BEGIN
+	IF ndigits > MAXWIDTH THEN ndigits := MAXWIDTH; END;
+	IF ndigits < 10 THEN ndigits := 10; END;
+	LongRealToString(arg, ndigits, -INTEGER(ndigits - 7), buf, ok);
+	WriteString(buf);
+  END WriteLongReal;
+
+  PROCEDURE WriteFixPt(arg: REAL; n, k: CARDINAL);
+  BEGIN
+	WriteLongFixPt(LONG(arg), n, k)
+  END WriteFixPt;
+
+  PROCEDURE WriteLongFixPt(arg: LONGREAL; n, k: CARDINAL);
+  VAR buf: RBUF;
+      ok : BOOLEAN;
+
+  BEGIN
+	IF n > MAXWIDTH THEN n := MAXWIDTH END;
+	LongRealToString(arg, n, k, buf, ok);
+	WriteString(buf);
+  END WriteLongFixPt;
+
+  PROCEDURE ReadReal(VAR x: REAL);
+  VAR x1: LONGREAL;
+  BEGIN
+	ReadLongReal(x1);
+	x := x1
+  END ReadReal;
+
+  PROCEDURE ReadLongReal(VAR x: LONGREAL);
+    VAR	Buf: ARRAY[0..512] OF CHAR;
+	ok: BOOLEAN;
+
+  BEGIN
+	ReadString(Buf);
+	StringToLongReal(Buf, x, ok);
+	IF NOT ok THEN
+		Message("real expected");
+		HALT;
+	END;
+	Done := TRUE;
+  END ReadLongReal;
+
+  PROCEDURE wroct(x: ARRAY OF WORD);
+  VAR	i: CARDINAL;
+  BEGIN
+	FOR i := 0 TO HIGH(x) DO
+		WriteOct(CARDINAL(x[i]), 0);
+		WriteString("  ");
+	END;
+  END wroct;
+
+  PROCEDURE WriteRealOct(x: REAL);
+  BEGIN
+	wroct(x);
+  END WriteRealOct;
+
+  PROCEDURE WriteLongRealOct(x: LONGREAL);
+  BEGIN
+	wroct(x);
+  END WriteLongRealOct;
+
+BEGIN
+	Done := FALSE;
+END RealInOut.
Index: /trunk/minix/lib/ack/libm2/SYSTEM.c
===================================================================
--- /trunk/minix/lib/ack/libm2/SYSTEM.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/SYSTEM.c	(revision 9)
@@ -0,0 +1,115 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	SYSTEM
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/SYSTEM.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+
+/*
+	An implementation of the Modula-2 NEWPROCESS and TRANSFER facilities
+	using the topsize, topsave, and topload facilities.
+	For each coroutine, a proc structure is built. For the main routine,
+	a static space is declared to save its stack. For the other coroutines,
+	the user specifies this space.
+*/
+
+#include <m2_traps.h>
+
+#define MAXMAIN	2048
+
+struct proc {
+	unsigned size;		/* size of saved stackframe(s) */
+	int (*proc)();		/* address of coroutine procedure */
+	char *brk;		/* stack break of this coroutine */
+};
+
+extern unsigned topsize();
+
+static struct proc mainproc[MAXMAIN/sizeof(struct proc) + 1];
+
+static struct proc *curproc = 0;/* current coroutine */
+extern char *MainLB;		/* stack break of main routine */
+
+_SYSTEM__NEWPROCESS(p, a, n, p1)
+	int (*p)();		/* coroutine procedure */
+	struct proc *a;		/* pointer to area for saved stack-frame */
+	unsigned n;		/* size of this area */
+	struct proc **p1;	/* where to leave coroutine descriptor,
+				   in this implementation the address of
+				   the area for saved stack-frame(s) */
+{
+	/*	This procedure creates a new coroutine, but does not
+		transfer control to it. The routine "topsize" will compute the
+		stack break, which will be the local base of this routine.
+		Notice that we can do this because we do not need the stack
+		above this point for this coroutine. In Modula-2, coroutines
+		must be level 0 procedures without parameters.
+	*/
+	char *brk = 0;
+	unsigned sz = topsize(&brk);
+
+	if (sz + sizeof(struct proc) > n) {
+		/* not enough space */
+		TRP(M2_TOOLARGE);
+	}
+	a->size = n;
+	a->proc = p;
+	a->brk = brk;
+	*p1 = a;
+	if (topsave(brk, a+1))
+		/* stack frame saved; now just return */
+		;
+	else {
+		/* We get here through the first transfer to the coroutine
+		   created above.
+		   This also means that curproc is now set to this coroutine.
+		   We cannot trust the parameters anymore.
+		   Just call the coroutine procedure.
+		*/
+		(*(curproc->proc))();
+		_cleanup();
+		_exit(0);
+	}
+}
+
+_SYSTEM__TRANSFER(a, b)
+	struct proc **a, **b;
+{
+	/*	transfer from one coroutine to another, saving the current
+		descriptor in the space indicated by "a", and transfering to
+		the coroutine in descriptor "b".
+	*/
+	unsigned size;
+
+	if (! curproc) {
+		/* the current coroutine is the main process;
+		   initialize a coroutine descriptor for it ...
+		*/
+		mainproc[0].brk = MainLB;
+		mainproc[0].size = sizeof(mainproc);
+		curproc = &mainproc[0];
+	}
+	*a = curproc;		/* save current descriptor in "a" */
+	if (*b == curproc) {
+		/* transfer to itself is a no-op */
+		return;
+	}
+	size = topsize(&(curproc->brk));
+	if (size + sizeof(struct proc) > curproc->size) {
+		TRP(M2_TOOLARGE);
+	}
+	if (topsave(curproc->brk, curproc+1)) {
+		/* stack top saved. Now restore context of target
+		   coroutine
+		*/
+		curproc = *b;
+		topload(curproc+1);
+		/* we never get here ... */
+	}
+	/* but we do get here, when a transfer is done to the coroutine in "a".
+	*/
+}
Index: /trunk/minix/lib/ack/libm2/Semaphores.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/Semaphores.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/Semaphores.mod	(revision 9)
@@ -0,0 +1,118 @@
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE Semaphores [1];
+(*
+  Module:       Processes with semaphores
+  Author:       Ceriel J.H. Jacobs
+  Version:      $Header: /cvsup/minix/src/lib/ack/libm2/Semaphores.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+
+  Quasi-concurrency implementation
+*)
+
+  FROM	SYSTEM IMPORT	ADDRESS, NEWPROCESS, TRANSFER;
+  FROM	Storage IMPORT	Allocate;
+  FROM	random IMPORT	Uniform;
+  FROM	Traps IMPORT	Message;
+
+  TYPE	Sema = POINTER TO Semaphore;
+	Processes = POINTER TO Process;
+	Semaphore =
+		RECORD
+			level: CARDINAL;
+		END;
+	Process =
+		RECORD	next: Processes;
+			proc: ADDRESS;
+			waiting: Sema;
+		END;
+
+  VAR	cp: Processes;			(* current process *)
+
+  PROCEDURE StartProcess(P: PROC; n: CARDINAL);
+    VAR	s0: Processes;
+	wsp: ADDRESS;
+  BEGIN
+	s0 := cp;
+	Allocate(wsp, n);
+	Allocate(cp, SIZE(Process));
+	WITH cp^ DO
+		next := s0^.next;
+		s0^.next := cp;
+		waiting := NIL;
+	END;
+	NEWPROCESS(P, wsp, n, cp^.proc);
+	TRANSFER(s0^.proc, cp^.proc);
+  END StartProcess;
+
+  PROCEDURE Up(VAR s: Sema);
+  BEGIN
+	s^.level := s^.level + 1;
+	ReSchedule;
+  END Up;
+
+  PROCEDURE Down(VAR s: Sema);
+  BEGIN
+	IF s^.level = 0 THEN
+		cp^.waiting := s;
+	ELSE
+		s^.level := s^.level - 1;
+	END;
+	ReSchedule;
+  END Down;
+
+  PROCEDURE NewSema(n: CARDINAL): Sema;
+  VAR	s: Sema;
+  BEGIN
+	Allocate(s, SIZE(Semaphore));
+	s^.level := n;
+	RETURN s;
+  END NewSema;
+
+  PROCEDURE Level(s: Sema): CARDINAL;
+  BEGIN
+	RETURN s^.level;
+  END Level;
+
+  PROCEDURE ReSchedule;
+  VAR s0: Processes;
+      i, j: CARDINAL;
+  BEGIN
+	s0 := cp;
+	i := Uniform(1, 5);
+	j := i;
+	LOOP
+		cp := cp^.next;
+		IF Runnable(cp) THEN
+			DEC(i);
+			IF i = 0 THEN EXIT END;
+		END;
+		IF (cp = s0) AND (j = i) THEN
+			(* deadlock *)
+			Message("deadlock");
+			HALT
+		END;
+	END;
+	IF cp # s0 THEN TRANSFER(s0^.proc, cp^.proc); END;
+  END ReSchedule;
+
+  PROCEDURE Runnable(p: Processes): BOOLEAN;
+  BEGIN
+	IF p^.waiting = NIL THEN RETURN TRUE; END;
+	IF p^.waiting^.level > 0 THEN
+		p^.waiting^.level := p^.waiting^.level - 1;
+		p^.waiting := NIL;
+		RETURN TRUE;
+	END;
+	RETURN FALSE;
+  END Runnable;
+BEGIN
+	Allocate(cp, SIZE(Process));
+	WITH cp^ DO
+		next := cp;
+		waiting := NIL;
+	END
+END Semaphores.
Index: /trunk/minix/lib/ack/libm2/Storage.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/Storage.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/Storage.mod	(revision 9)
@@ -0,0 +1,353 @@
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE Storage;
+(*
+  Module:	Dynamic Storage Allocation
+  Author:	Ceriel J.H. Jacobs
+		Adapted from a version in C by Hans Tebra
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/Storage.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+*)
+(* This storage manager maintains an array of lists of objects with the
+   same size. Commonly used sizes have their own bucket. The larger ones
+   are put in a single list.
+*)
+  FROM	Unix IMPORT	sbrk, ILLBREAK;
+  FROM	SYSTEM IMPORT	ADDRESS, ADR;
+  FROM	Traps IMPORT	Message;
+
+  CONST
+	NLISTS = 20;
+	MAGICW = 0A5A5H;
+	MAGICC = 175C;
+
+  TYPE
+	ALIGNTYPE = 
+	  RECORD
+		CASE : INTEGER OF
+		  1: l: LONGINT |
+		  2: p: ADDRESS |
+		  3: d: LONGREAL
+		END
+	  END;			(* A type with high alignment requirements *)
+	BucketPtr = POINTER TO Bucket;
+	Bucket =
+	  RECORD
+		CASE : BOOLEAN OF
+		   FALSE:
+			  BNEXT: BucketPtr; 	(* next free Bucket *)
+			  BSIZE: CARDINAL; |	(* size of user part in UNITs *)
+		   TRUE: BXX: ALIGNTYPE
+		END;
+		BSTORE: ALIGNTYPE;
+	  END;
+
+  CONST
+	UNIT = SIZE(ALIGNTYPE);
+
+  VAR
+	FreeLists: ARRAY[0..NLISTS] OF BucketPtr;	(* small blocks *)
+	Llist: BucketPtr;				(* others *)
+	Compacted: BOOLEAN;		(* avoid recursive reorganization *)
+	FirstBlock: BucketPtr;
+	USED: ADDRESS;
+
+  PROCEDURE MyAllocate(size: CARDINAL) : ADDRESS;
+    VAR	nu : CARDINAL;
+	b : CARDINAL;
+	p, q: BucketPtr;
+	pc: POINTER TO CHAR;
+	brk : ADDRESS;
+  BEGIN
+	IF size > CARDINAL(MAX(INTEGER)-2*UNIT + 1) THEN
+		RETURN NIL;
+	END;
+	nu := (size + (UNIT-1)) DIV UNIT;
+	IF nu = 0 THEN
+		nu := 1;
+	END;
+	IF nu <= NLISTS THEN
+		b := nu;
+		IF FreeLists[b] # NIL THEN
+			(* Exact fit *)
+			p := FreeLists[b];
+			FreeLists[b] := p^.BNEXT;
+			p^.BNEXT := USED;
+			IF p^.BSIZE * UNIT # size THEN
+				pc := ADR(p^.BSTORE) + size;
+				pc^ := MAGICC;
+			END;
+			p^.BSIZE := size;
+			RETURN ADR(p^.BSTORE);
+		END;
+
+		(* Search for a block with >= 2 units more than requested.
+		   We pay for an additional header when the block is split.
+		*)
+		FOR b := b+2 TO NLISTS DO
+			IF FreeLists[b] # NIL THEN
+				q := FreeLists[b];
+				FreeLists[b] := q^.BNEXT;
+				p := ADDRESS(q) + (nu+1)*UNIT;
+				(* p indicates the block that must be given
+				   back
+				*)
+				p^.BSIZE := q^.BSIZE - nu - 1;
+				p^.BNEXT := FreeLists[p^.BSIZE];
+				FreeLists[p^.BSIZE] := p;
+				q^.BSIZE := nu;
+				q^.BNEXT := USED;
+				IF q^.BSIZE * UNIT # size THEN
+					pc := ADR(q^.BSTORE) + size;
+					pc^ := MAGICC;
+				END;
+				q^.BSIZE := size;
+				RETURN ADR(q^.BSTORE);
+			END;
+		END;
+	END;
+
+	p := Llist;
+	IF p # NIL THEN
+		q := NIL;
+		WHILE (p # NIL) AND (p^.BSIZE < nu) DO
+			q := p;
+			p := p^.BNEXT;
+		END;
+
+		IF p # NIL THEN
+			(* p^.BSIZE >= nu *)
+			IF p^.BSIZE <= nu + NLISTS + 1 THEN
+				(* Remove p from this list *)
+				IF q # NIL THEN q^.BNEXT := p^.BNEXT
+				ELSE Llist := p^.BNEXT;
+				END;
+				p^.BNEXT := USED;
+				IF p^.BSIZE > nu + 1 THEN
+					(* split block,
+					   tail goes to FreeLists area
+					*)
+					q := ADDRESS(p) + (nu+1)*UNIT;
+					q^.BSIZE := p^.BSIZE -nu -1;
+					q^.BNEXT := FreeLists[q^.BSIZE];
+					FreeLists[q^.BSIZE] := q;
+					p^.BSIZE := nu;
+				END;
+				IF p^.BSIZE * UNIT # size THEN
+					pc := ADR(p^.BSTORE) + size;
+					pc^ := MAGICC;
+				END;
+				p^.BSIZE := size;
+				RETURN ADR(p^.BSTORE);
+			END;
+			(* Give part of tail of original block.
+			   Block stays in this list.
+			*)
+			q := ADDRESS(p) + (p^.BSIZE-nu)*UNIT;
+			q^.BSIZE := nu;
+			p^.BSIZE := p^.BSIZE - nu - 1;
+			q^.BNEXT := USED;
+			IF q^.BSIZE * UNIT # size THEN
+				pc := ADR(q^.BSTORE) + size;
+				pc^ := MAGICC;
+			END;
+			q^.BSIZE := size;
+			RETURN ADR(q^.BSTORE);
+		END;
+	END;
+
+	IF Compacted THEN
+		(* reorganization did not yield sufficient memory *)
+		RETURN NIL;
+	END;
+
+	brk := sbrk(UNIT * (nu + 1));
+	IF brk = ILLBREAK THEN
+		ReOrganize();
+		Compacted := TRUE;
+		brk := MyAllocate(size);
+		Compacted := FALSE;
+		RETURN brk;
+	END;
+
+	p := brk;
+	p^.BSIZE := nu;
+	p^.BNEXT := USED;
+	IF p^.BSIZE * UNIT # size THEN
+		pc := ADR(p^.BSTORE) + size;
+		pc^ := MAGICC;
+	END;
+	p^.BSIZE := size;
+	RETURN ADR(p^.BSTORE);
+  END MyAllocate;
+
+  PROCEDURE ALLOCATE(VAR a: ADDRESS; size: CARDINAL);
+  BEGIN
+	Allocate(a, size);
+  END ALLOCATE;
+
+  PROCEDURE Allocate(VAR a: ADDRESS; size: CARDINAL);
+  BEGIN
+	a := MyAllocate(size);
+	IF a = NIL THEN
+		Message("out of core");
+		HALT;
+	END;
+  END Allocate;
+
+  PROCEDURE Available(size: CARDINAL): BOOLEAN;
+    VAR	a: ADDRESS;
+  BEGIN
+	a:= MyAllocate(size);
+	IF a # NIL THEN
+		Deallocate(a, size);
+		RETURN TRUE;
+	END;
+	RETURN FALSE;
+  END Available;
+
+  PROCEDURE DEALLOCATE(VAR a: ADDRESS; size: CARDINAL);
+  BEGIN
+	Deallocate(a, size);
+  END DEALLOCATE;
+
+  PROCEDURE Deallocate(VAR a: ADDRESS; size: CARDINAL);
+    VAR	p: BucketPtr;
+	pc: POINTER TO CHAR;
+  BEGIN
+	IF (a = NIL) THEN 
+		Message("(Warning) Deallocate: NIL pointer deallocated");
+		RETURN;
+	END;
+	p := a - UNIT;
+	IF (p^.BNEXT # BucketPtr(USED)) THEN
+		Message("(Warning) Deallocate: area already deallocated or heap corrupted");
+		a := NIL;
+		RETURN;
+	END;
+	WITH p^ DO
+		IF BSIZE # size THEN
+			Message("(Warning) Deallocate: wrong size or heap corrupted");
+		END;
+		BSIZE := (size + (UNIT - 1)) DIV UNIT;
+		IF (BSIZE*UNIT # size) THEN
+			pc := a + size;
+			IF pc^ # MAGICC THEN
+				Message("(Warning) Deallocate: heap corrupted");
+			END;
+		END;	
+		IF BSIZE <= NLISTS THEN
+			BNEXT := FreeLists[BSIZE];
+			FreeLists[BSIZE] := p;
+		ELSE
+			BNEXT := Llist;
+			Llist := p;
+		END;
+	END;
+	a := NIL
+  END Deallocate;
+
+  PROCEDURE ReOrganize();
+    VAR lastblock: BucketPtr;
+	b, be: BucketPtr;
+	i: CARDINAL;
+  BEGIN
+	lastblock := NIL;
+	FOR i := 1 TO NLISTS DO
+		b := FreeLists[i];
+		WHILE b # NIL DO
+			IF ADDRESS(b) > ADDRESS(lastblock) THEN
+				lastblock := b;
+			END;
+			be := b^.BNEXT;
+			b^.BNEXT := NIL;	(* temporary free mark *)
+			b := be;
+		END;
+	END;
+
+	b := Llist;
+	WHILE b # NIL DO
+		IF ADDRESS(b) > ADDRESS(lastblock) THEN
+			lastblock := b;
+		END;
+		be := b^.BNEXT;
+		b^.BNEXT := NIL;
+		b := be;
+	END;
+
+	(* Now, all free blocks have b^.BNEXT = NIL *)
+
+	b := FirstBlock;
+	WHILE ADDRESS(b) < ADDRESS(lastblock) DO
+		LOOP
+			be := ADDRESS(b)+(b^.BSIZE+1)*UNIT;
+			IF b^.BNEXT # NIL THEN	
+				(* this block is not free *)
+				EXIT;
+			END;
+			IF ADDRESS(be) > ADDRESS(lastblock) THEN
+				(* no next block *)
+				EXIT;
+			END;
+			IF be^.BNEXT # NIL THEN
+				(* next block is not free *)
+				EXIT;
+			END;
+			(* this block and the next one are free,
+			   so merge them, but only if it is not too big
+			*)
+			IF MAX(CARDINAL) - b^.BSIZE > be^.BSIZE THEN
+				b^.BSIZE := b^.BSIZE + be^.BSIZE + 1;
+			ELSE
+				EXIT;
+			END;
+		END;
+		b := be;
+	END;
+
+	(* clear all free lists *)
+	FOR i := 1 TO NLISTS DO FreeLists[i] := NIL; END;
+	Llist := NIL;
+
+	(* collect free blocks in them again *)
+	b := FirstBlock;
+	WHILE ADDRESS(b) <= ADDRESS(lastblock) DO
+		WITH b^ DO
+			IF BNEXT = NIL THEN
+				IF BSIZE <= NLISTS THEN
+					BNEXT := FreeLists[BSIZE];
+					FreeLists[BSIZE] := b;
+				ELSE
+					BNEXT := Llist;
+					Llist := b;
+				END;
+				b := ADDRESS(b) + (BSIZE+1) * UNIT;
+			ELSE
+				b := ADDRESS(b) + 
+					((BSIZE + (UNIT - 1)) DIV UNIT + 1) * UNIT;
+			END;
+		END;
+	END;
+  END ReOrganize;
+
+  PROCEDURE InitStorage();
+    VAR	i: CARDINAL;
+	brk: ADDRESS;
+  BEGIN
+	FOR i := 1 TO NLISTS DO
+		FreeLists[i] := NIL;
+	END;
+	Llist := NIL;
+	brk := sbrk(0);
+	brk := sbrk(UNIT - brk MOD UNIT);
+	FirstBlock := sbrk(0);
+	Compacted := FALSE;
+	USED := MAGICW;
+  END InitStorage;
+
+BEGIN
+	InitStorage();
+END Storage.
Index: /trunk/minix/lib/ack/libm2/StrAss.c
===================================================================
--- /trunk/minix/lib/ack/libm2/StrAss.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/StrAss.c	(revision 9)
@@ -0,0 +1,23 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	assign string to character array, with possible 0-byte
+		extension
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/StrAss.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+StringAssign(dstsiz, srcsiz, dstaddr, srcaddr)
+	register char *dstaddr, *srcaddr;
+{
+	while (srcsiz > 0) {
+		*dstaddr++ = *srcaddr++;
+		srcsiz--;
+		dstsiz--;
+	}
+	if (dstsiz > 0) {
+		*dstaddr = 0;
+	}
+}
Index: /trunk/minix/lib/ack/libm2/Streams.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/Streams.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/Streams.mod	(revision 9)
@@ -0,0 +1,443 @@
+#
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE Streams;
+(*
+  Module:       Stream Input/Output
+  Author:       Ceriel J.H. Jacobs
+  Version:      $Header: /cvsup/minix/src/lib/ack/libm2/Streams.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+
+  Implementation for Unix
+*)
+
+  FROM	SYSTEM IMPORT	BYTE, ADR;
+  FROM	Epilogue IMPORT	CallAtEnd;
+  FROM	Storage IMPORT	Allocate, Available;
+  FROM	StripUnix IMPORT
+			open, close, lseek, read, write, creat;
+  IMPORT StripUnix;
+
+  CONST BUFSIZ = 1024;	(* tunable *)
+  TYPE	IOB = RECORD
+		kind: StreamKind;
+		mode: StreamMode;
+		eof: BOOLEAN;
+		buffering: StreamBuffering;
+		next : Stream;
+		fildes: INTEGER;
+		cnt, maxcnt: INTEGER;
+		bufferedcnt: INTEGER;
+		buf: ARRAY[1..BUFSIZ] OF BYTE;
+	      END;
+	Stream = POINTER TO IOB;
+  VAR
+	ibuf, obuf, ebuf: IOB;
+	head: Stream;
+
+  PROCEDURE getstruct(VAR stream: Stream);
+  BEGIN
+        stream := head;
+        WHILE (stream # NIL) AND (stream^.kind # none) DO
+                stream := stream^.next;
+        END;
+        IF stream = NIL THEN
+		IF NOT Available(SIZE(IOB)) THEN
+			RETURN;
+		END;
+                Allocate(stream,SIZE(IOB));
+                stream^.next := head;
+                head := stream;
+        END;
+  END getstruct;
+ 
+  PROCEDURE freestruct(stream: Stream);
+  BEGIN
+	stream^.kind := none;
+  END freestruct;
+
+  PROCEDURE OpenStream(VAR stream: Stream;
+		       filename: ARRAY OF CHAR; 
+		       kind: StreamKind;
+		       mode: StreamMode;
+		       VAR result: StreamResult);
+    VAR fd: INTEGER;
+	i: CARDINAL;
+  BEGIN
+	IF kind = none THEN
+		result := illegaloperation;
+		RETURN;
+	END;
+	getstruct(stream);
+	IF stream = NIL THEN
+		result := nomemory;
+		RETURN;
+	END;
+        WITH stream^ DO
+                FOR i := 0 TO HIGH(filename) DO
+                        buf[i+1] := BYTE(filename[i]);
+                END;
+                buf[HIGH(filename)+2] := BYTE(0C);
+	END;
+	IF (mode = reading) THEN
+		fd := open(ADR(stream^.buf), 0);
+	ELSE
+		fd := -1;
+		IF (mode = appending) THEN
+			fd := open(ADR(stream^.buf), 1);
+			IF fd >= 0 THEN
+				IF (lseek(fd, 0D , 2) < 0D) THEN ; END;
+			END;
+		END;
+		IF fd < 0 THEN
+			fd := creat(ADR(stream^.buf), 666B);
+		END;
+	END;
+	IF fd < 0 THEN
+		result := openfailed;
+		freestruct(stream);
+		stream := NIL;
+		RETURN;
+	END;
+	result := succeeded;
+	stream^.fildes := fd;
+	stream^.kind := kind;
+	stream^.mode := mode;
+	stream^.buffering := blockbuffered;
+	stream^.bufferedcnt := BUFSIZ;
+	stream^.maxcnt := 0;
+	stream^.eof := FALSE;
+	IF mode = reading THEN
+		stream^.cnt := 1;
+	ELSE
+		stream^.cnt := 0;
+	END;
+  END OpenStream;
+
+  PROCEDURE SetStreamBuffering( stream: Stream;
+				b: StreamBuffering;
+				VAR result: StreamResult);
+  BEGIN
+	result := succeeded;
+	IF (stream = NIL) OR (stream^.kind = none) THEN
+		result := nostream;
+		RETURN;
+	END;
+	IF (stream^.mode = reading) OR
+	   ((b = linebuffered) AND (stream^.kind = binary)) THEN
+		result := illegaloperation;
+		RETURN;
+	END;
+	FlushStream(stream, result);
+	IF b = unbuffered THEN
+		stream^.bufferedcnt := 1;
+	END;
+	stream^.buffering := b;
+  END SetStreamBuffering;
+
+  PROCEDURE FlushStream(stream: Stream; VAR result: StreamResult);
+  VAR cnt1: INTEGER;
+  BEGIN
+	result := succeeded;
+	IF (stream = NIL) OR (stream^.kind = none) THEN
+		result := nostream;
+		RETURN;
+	END;
+	WITH stream^ DO
+		IF mode = reading THEN
+			result := illegaloperation;
+			RETURN;
+		END;
+		IF (cnt > 0) THEN
+			cnt1 := cnt;
+			cnt := 0;
+			IF write(fildes, ADR(buf), cnt1) < 0 THEN END;
+		END;
+	END;
+  END FlushStream;
+
+  PROCEDURE CloseStream(VAR stream: Stream; VAR result: StreamResult);
+  BEGIN
+	IF (stream # NIL) AND (stream^.kind # none) THEN
+		result := succeeded;
+		IF stream^.mode # reading THEN
+			FlushStream(stream, result);
+		END;
+		IF close(stream^.fildes) < 0 THEN ; END;
+		freestruct(stream);
+	ELSE
+		result := nostream;
+	END;
+	stream := NIL;
+  END CloseStream;
+	
+  PROCEDURE EndOfStream(stream: Stream; VAR result: StreamResult): BOOLEAN;
+  BEGIN
+	result := succeeded;
+	IF (stream = NIL) OR (stream^.kind = none) THEN
+		result := nostream;
+		RETURN FALSE;
+	END;
+	IF stream^.mode # reading THEN
+		result := illegaloperation;
+		RETURN FALSE;
+	END;
+	IF stream^.eof THEN RETURN TRUE; END;
+	RETURN (CHAR(NextByte(stream)) = 0C) AND stream^.eof;
+  END EndOfStream;
+
+  PROCEDURE FlushLineBuffers();
+  VAR	s: Stream;
+	result: StreamResult;
+  BEGIN
+	s := head;
+	WHILE s # NIL DO
+		IF (s^.kind # none) AND (s^.buffering = linebuffered) THEN
+			FlushStream(s, result);
+		END;
+		s := s^.next;
+	END;
+  END FlushLineBuffers;
+
+  PROCEDURE NextByte(stream: Stream): BYTE;
+  VAR c: BYTE;
+  BEGIN
+	WITH stream^ DO
+		IF cnt <= maxcnt THEN
+			c := buf[cnt];
+		ELSE
+			IF eof THEN RETURN BYTE(0C); END;
+			IF stream = InputStream THEN
+				FlushLineBuffers();
+			END;
+			maxcnt := read(fildes, ADR(buf), bufferedcnt);
+			cnt := 1;
+			IF maxcnt <= 0 THEN
+				eof := TRUE;
+				c := BYTE(0C);
+			ELSE
+				c := buf[1];
+			END;
+		END;
+	END;
+	RETURN c;
+  END NextByte;
+
+  PROCEDURE Read(stream: Stream; VAR ch: CHAR; VAR result: StreamResult);
+  VAR EoF: BOOLEAN;
+  BEGIN
+	ch := 0C;
+	EoF := EndOfStream(stream, result);
+	IF result # succeeded THEN RETURN; END;
+	IF EoF THEN
+		result := endoffile;
+		RETURN;
+	END;
+	WITH stream^ DO
+		ch := CHAR(buf[cnt]);
+		INC(cnt);
+	END;
+  END Read;
+
+  PROCEDURE ReadByte(stream: Stream; VAR byte: BYTE; VAR result: StreamResult);
+  VAR EoF: BOOLEAN;
+  BEGIN
+	byte := BYTE(0C);
+	EoF := EndOfStream(stream, result);
+	IF result # succeeded THEN RETURN; END;
+	IF EoF THEN
+		result := endoffile;
+		RETURN;
+	END;
+	WITH stream^ DO
+		byte := buf[cnt];
+		INC(cnt);
+	END;
+  END ReadByte;
+
+  PROCEDURE ReadBytes(stream: Stream;
+		      VAR bytes: ARRAY OF BYTE;
+		      VAR result: StreamResult);
+  VAR i: CARDINAL;
+  BEGIN
+	FOR i := 0 TO HIGH(bytes) DO
+		ReadByte(stream, bytes[i], result);
+	END;
+  END ReadBytes;
+
+  PROCEDURE Write(stream: Stream; ch: CHAR; VAR result: StreamResult);
+  BEGIN
+	IF (stream = NIL) OR (stream^.kind = none) THEN
+		result := nostream;
+		RETURN;
+	END;
+	IF (stream^.kind # text) OR (stream^.mode = reading) THEN
+		result := illegaloperation;
+		RETURN;
+	END;
+	WITH stream^ DO
+		INC(cnt);
+		buf[cnt] := BYTE(ch);
+		IF (cnt >= bufferedcnt) OR
+		   ((ch = 12C) AND (buffering = linebuffered))
+		THEN
+			FlushStream(stream, result);
+		END;
+	END;
+  END Write;
+
+  PROCEDURE WriteByte(stream: Stream; byte: BYTE; VAR result: StreamResult);
+  BEGIN
+	IF (stream = NIL) OR (stream^.kind = none) THEN
+		result := nostream;
+		RETURN;
+	END;
+	IF (stream^.kind # binary) OR (stream^.mode = reading) THEN
+		result := illegaloperation;
+		RETURN;
+	END;
+	WITH stream^ DO
+		INC(cnt);
+		buf[cnt] := byte;
+		IF cnt >= bufferedcnt THEN
+			FlushStream(stream, result);
+		END;
+	END;
+  END WriteByte;
+
+  PROCEDURE WriteBytes(stream: Stream; bytes: ARRAY OF BYTE; VAR result: StreamResult);
+  VAR i: CARDINAL;
+  BEGIN
+	FOR i := 0 TO HIGH(bytes) DO
+		WriteByte(stream, bytes[i], result);
+	END;
+  END WriteBytes;
+
+  PROCEDURE EndIt;
+  VAR h, h1 : Stream;
+      result: StreamResult;
+  BEGIN
+	h := head;
+	WHILE h # NIL DO
+		h1 := h;
+		CloseStream(h1, result);
+		h := h^.next;
+	END;
+  END EndIt;
+
+  PROCEDURE GetPosition(s: Stream; VAR position: LONGINT;
+			VAR result: StreamResult);
+  BEGIN
+	IF (s = NIL) OR (s^.kind = none) THEN
+		result := illegaloperation;
+		RETURN;
+	END;
+	IF (s^.mode # reading) THEN FlushStream(s, result); END;
+	position := lseek(s^.fildes, 0D, 1);
+	IF position < 0D THEN
+		result := illegaloperation;
+		RETURN;
+	END;
+	IF s^.mode = reading THEN
+		position := position + LONG(s^.maxcnt - s^.cnt + 1);
+	END;
+  END GetPosition;
+
+  PROCEDURE SetPosition(s: Stream; position: LONGINT; VAR result: StreamResult);
+  VAR currpos: LONGINT;
+  BEGIN
+	currpos := 0D;
+	IF (s = NIL) OR (s^.kind = none) THEN
+		result := nostream;
+		RETURN;
+	END;
+	IF (s^.mode # reading) THEN
+		FlushStream(s, result);
+	ELSE
+		s^.maxcnt := 0;
+		s^.eof := FALSE;
+	END;
+	IF s^.mode = appending THEN
+		currpos := lseek(s^.fildes, 0D, 1);
+		IF currpos < 0D THEN
+			result := illegaloperation;
+			RETURN;
+		END;
+	END;
+	IF position < currpos THEN
+		result := illegaloperation;
+		RETURN;
+	END;
+	currpos := lseek(s^.fildes, position, 0);
+	IF currpos < 0D THEN
+		result := illegaloperation;
+		RETURN;
+	END;
+	result := succeeded;
+  END SetPosition;
+
+  PROCEDURE isatty(stream: Stream; VAR result: StreamResult): BOOLEAN;
+  BEGIN
+	IF (stream = NIL) OR (stream^.kind = none) THEN
+		result := nostream;
+		RETURN FALSE;
+	END;
+	RETURN StripUnix.isatty(stream^.fildes);
+  END isatty;
+
+  PROCEDURE InitStreams;
+  VAR result: StreamResult;
+  BEGIN
+	InputStream := ADR(ibuf);
+	OutputStream := ADR(obuf);
+	ErrorStream := ADR(ebuf);
+	WITH ibuf DO
+		kind := text;
+		mode := reading;
+		eof := FALSE;
+		next := ADR(obuf);
+		fildes := 0;
+		maxcnt := 0;
+		cnt := 1;
+		bufferedcnt := BUFSIZ;
+	END;
+	WITH obuf DO
+		kind := text;
+		mode := writing;
+		eof := TRUE;
+		next := ADR(ebuf);
+		fildes := 1;
+		maxcnt := 0;
+		cnt := 0;
+		bufferedcnt := BUFSIZ;
+		IF isatty(OutputStream, result) THEN
+			buffering := linebuffered;
+		ELSE
+			buffering := blockbuffered;
+		END;
+	END;
+	WITH ebuf DO
+		kind := text;
+		mode := writing;
+		eof := TRUE;
+		next := NIL;
+		fildes := 2;
+		maxcnt := 0;
+		cnt := 0;
+		bufferedcnt := BUFSIZ;
+		IF isatty(ErrorStream, result) THEN
+			buffering := linebuffered;
+		ELSE
+			buffering := blockbuffered;
+		END;
+	END;
+	head := InputStream;
+	IF CallAtEnd(EndIt) THEN ; END;
+  END InitStreams;
+
+BEGIN
+	InitStreams
+END Streams.
Index: /trunk/minix/lib/ack/libm2/Strings.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/Strings.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/Strings.mod	(revision 9)
@@ -0,0 +1,171 @@
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE Strings;
+(*
+  Module:       String manipulations
+  Author:       Ceriel J.H. Jacobs
+  Version:      $Header: /cvsup/minix/src/lib/ack/libm2/Strings.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+*)
+
+  PROCEDURE Assign(source: ARRAY OF CHAR; VAR dest: ARRAY OF CHAR);
+  (* Assign string source to dest
+  *)
+  VAR	i: CARDINAL;
+	max: CARDINAL;
+  BEGIN
+	max := HIGH(source);
+	IF HIGH(dest) < max THEN max := HIGH(dest); END;
+	i := 0;
+	WHILE (i <= max) AND (source[i] # 0C) DO
+		dest[i] := source[i];
+		INC(i);
+	END;
+	IF i < HIGH(dest) THEN dest[i] := 0C; END;
+  END Assign;
+
+  PROCEDURE Insert(substr: ARRAY OF CHAR; VAR str: ARRAY OF CHAR; inx: CARDINAL);
+  (* Insert the string substr into str, starting at str[inx].
+     If inx is equal to or greater than Length(str) then substr is appended
+     to the end of str.
+  *)
+  VAR	sublen, length, i: CARDINAL;
+  BEGIN
+	sublen := Length(substr);
+	IF sublen = 0 THEN RETURN; END;
+	length := Length(str);
+	IF inx > length THEN inx := length; END;
+	i := length;
+	IF i + sublen  - 1 > HIGH(str) THEN i := HIGH(str); END;
+	WHILE i > inx DO
+		str[i+sublen-1] := str[i-1];
+		DEC(i);
+	END;
+	FOR i := 0 TO sublen - 1 DO
+		IF i + inx <= HIGH(str) THEN
+			str[i + inx] := substr[i];
+		ELSE
+			RETURN;
+		END;
+	END;
+	IF length + sublen <= HIGH(str) THEN
+		str[length + sublen] := 0C;
+	END;
+  END Insert;
+
+  PROCEDURE Delete(VAR str: ARRAY OF CHAR; inx, len: CARDINAL);
+  (* Delete len characters from str, starting at str[inx].
+     If inx >= Length(str) then nothing happens.
+     If there are not len characters to delete, characters to the end of the
+     string are deleted.
+  *)
+  VAR	length: CARDINAL;
+  BEGIN
+	IF len = 0 THEN RETURN; END;
+	length := Length(str);
+	IF inx >= length THEN RETURN; END;
+	WHILE inx + len < length DO
+		str[inx] := str[inx + len];
+		INC(inx);
+	END;
+	str[inx] := 0C;
+  END Delete;
+
+  PROCEDURE Pos(substr, str: ARRAY OF CHAR): CARDINAL;
+  (* Return the index into str of the first occurrence of substr.
+     Pos returns a value greater than HIGH(str) of no occurrence is found.
+  *)
+  VAR	i, j, max, subl: CARDINAL;
+  BEGIN
+	max := Length(str);
+	subl := Length(substr);
+	IF subl > max THEN RETURN HIGH(str) + 1; END;
+	IF subl = 0 THEN RETURN 0; END;
+	max := max - subl;
+	FOR i := 0 TO max DO
+		j := 0;
+		WHILE (j <= subl-1) AND (str[i+j] = substr[j]) DO
+			INC(j);
+		END;
+		IF j = subl THEN RETURN i; END;
+	END;
+	RETURN HIGH(str) + 1;
+  END Pos;
+
+  PROCEDURE Copy(str: ARRAY OF CHAR;
+	         inx, len: CARDINAL;
+	         VAR result: ARRAY OF CHAR);
+  (* Copy at most len characters from str into result, starting at str[inx].
+  *)
+  VAR	i: CARDINAL;
+  BEGIN
+	IF Length(str) <= inx THEN RETURN END;
+	i := 0;
+	LOOP
+		IF i > HIGH(result) THEN RETURN; END;
+		IF len = 0 THEN EXIT; END;
+		IF inx > HIGH(str) THEN EXIT; END;
+		result[i] := str[inx];
+		INC(i); INC(inx); DEC(len);
+	END;
+	IF i <= HIGH(result) THEN result[i] := 0C; END;
+  END Copy;
+
+  PROCEDURE Concat(s1, s2: ARRAY OF CHAR; VAR result: ARRAY OF CHAR);
+  (* Concatenate two strings.
+  *)
+  VAR	i, j: CARDINAL;
+  BEGIN
+	i := 0;
+	WHILE (i <= HIGH(s1)) AND (s1[i] # 0C) DO
+		IF i > HIGH(result) THEN RETURN END;
+		result[i] := s1[i];
+		INC(i);
+	END;
+	j := 0;
+	WHILE (j <= HIGH(s2)) AND (s2[j] # 0C) DO
+		IF i > HIGH(result) THEN RETURN END;
+		result[i] := s2[j];
+		INC(i);
+		INC(j);
+	END;
+	IF i <= HIGH(result) THEN result[i] := 0C; END;
+  END Concat;
+
+  PROCEDURE Length(str: ARRAY OF CHAR): CARDINAL;
+  (* Return number of characters in str.
+  *)
+  VAR i: CARDINAL;
+  BEGIN
+	i := 0;
+	WHILE (i <= HIGH(str)) DO
+		IF str[i] = 0C THEN RETURN i; END;
+		INC(i);
+	END;
+	RETURN i;
+  END Length;
+
+  PROCEDURE CompareStr(s1, s2: ARRAY OF CHAR): INTEGER;
+  (* Compare two strings, return -1 if s1 < s2, 0 if s1 = s2, and 1 if s1 > s2.
+  *)
+  VAR	i: CARDINAL;
+	max: CARDINAL;
+  BEGIN
+	max := HIGH(s1);
+	IF HIGH(s2) < max THEN max := HIGH(s2); END;
+	i := 0;
+	WHILE (i <= max) DO
+		IF s1[i] < s2[i] THEN RETURN -1; END;
+		IF s1[i] > s2[i] THEN RETURN 1; END;
+		IF s1[i] = 0C THEN RETURN 0; END;
+		INC(i);
+	END;
+	IF (i <= HIGH(s1)) AND (s1[i] # 0C) THEN RETURN 1; END;
+	IF (i <= HIGH(s2)) AND (s2[i] # 0C) THEN RETURN -1; END;
+	RETURN 0;
+  END CompareStr;
+
+END Strings.
Index: /trunk/minix/lib/ack/libm2/Termcap.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/Termcap.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/Termcap.mod	(revision 9)
@@ -0,0 +1,99 @@
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+ 
+(* 
+  Module:       Interface to termcap database
+  From:         Unix manual chapter 3 
+  Version:      $Header: /cvsup/minix/src/lib/ack/libm2/Termcap.mod,v 1.1 2005/10/10 15:27:46 beng Exp $ 
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE Termcap;
+
+  IMPORT XXTermcap;
+  FROM	SYSTEM IMPORT	ADR, ADDRESS;
+  FROM	Unix IMPORT	isatty;
+  FROM	Arguments IMPORT
+			GetEnv;
+
+  TYPE	STR = ARRAY[1..32] OF CHAR;
+	STRCAP = POINTER TO STR;
+
+  VAR	Buf, Buf1 : ARRAY [1..1024] OF CHAR;
+	BufCnt : INTEGER;
+
+  PROCEDURE Tgetent(name: ARRAY OF CHAR) : INTEGER;
+  VAR i: INTEGER;
+      x: STRCAP;
+  BEGIN
+	i := XXTermcap.tgetent(ADR(Buf), ADR(name));
+	BufCnt := 1;
+	IF isatty(1) THEN
+	ELSE
+		(* This used to be something returned by gtty().  To increase
+		 * portability we forget about old terminals needing delays.
+		 * (kjb)
+		 *)
+		XXTermcap.ospeed := 0;
+	END;
+	IF i > 0 THEN
+		IF Tgetstr("pc", x) THEN
+			XXTermcap.PC := x^[1];
+		ELSE	XXTermcap.PC := 0C;
+		END;
+		IF Tgetstr("up", x) THEN ; END; XXTermcap.UP := x;
+		IF Tgetstr("bc", x) THEN ; END; XXTermcap.BC := x;
+	END;
+	RETURN i;
+  END Tgetent;
+
+  PROCEDURE Tgetnum(id: ARRAY OF CHAR): INTEGER;
+  BEGIN
+	RETURN XXTermcap.tgetnum(ADR(id));
+  END Tgetnum;
+
+  PROCEDURE Tgetflag(id: ARRAY OF CHAR): BOOLEAN;
+  BEGIN
+	RETURN XXTermcap.tgetflag(ADR(id)) = 1;
+  END Tgetflag;
+
+  PROCEDURE Tgoto(cm: STRCAP; col, line: INTEGER): STRCAP;
+  BEGIN
+	RETURN XXTermcap.tgoto(cm, col, line);
+  END Tgoto;
+
+  PROCEDURE Tgetstr(id: ARRAY OF CHAR; VAR res: STRCAP) : BOOLEAN;
+  VAR a, a2: ADDRESS;
+      b: CARDINAL;
+  BEGIN
+	a := ADR(Buf1[BufCnt]);
+	a2 := XXTermcap.tgetstr(ADR(id), ADR(a));
+	res := a2;
+	IF a2 = NIL THEN
+		RETURN FALSE;
+	END;
+	b := a - a2;
+	INC(BufCnt, b);
+	RETURN TRUE;
+  END Tgetstr;
+
+  PROCEDURE Tputs(cp: STRCAP; affcnt: INTEGER; p: PUTPROC);
+  BEGIN
+	XXTermcap.tputs(cp, affcnt, XXTermcap.PUTPROC(p));
+  END Tputs;
+
+  PROCEDURE InitTermcap;
+  VAR Bf: STR;
+  BEGIN
+	IF GetEnv("TERM", Bf) = 0 THEN
+		Bf := "dumb";
+	END;
+	IF Tgetent(Bf) <= 0 THEN
+	END;
+  END InitTermcap;
+
+BEGIN
+	InitTermcap;
+END Termcap.
Index: /trunk/minix/lib/ack/libm2/Terminal.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/Terminal.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/Terminal.mod	(revision 9)
@@ -0,0 +1,114 @@
+#
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE Terminal;
+(*
+  Module:       Input/Output to/from terminals
+  Author:	Ceriel J.H. Jacobs
+  Version:      $Header: /cvsup/minix/src/lib/ack/libm2/Terminal.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+
+  Implementation for Unix.
+*)
+  FROM	SYSTEM IMPORT	ADR;
+#ifdef __USG
+  FROM	Unix IMPORT	read, write, open, fcntl;
+#else
+  FROM	Unix IMPORT	read, write, open, ioctl;
+#endif
+  VAR fildes: INTEGER;
+      unreadch: CHAR;
+      unread: BOOLEAN;
+      tty: ARRAY[0..8] OF CHAR;
+
+  PROCEDURE Read(VAR ch: CHAR);
+  BEGIN
+	IF unread THEN
+		ch := unreadch;
+		unread := FALSE
+	ELSE
+		IF read(fildes, ADR(ch), 1) < 0 THEN
+			;
+		END;
+	END;
+	unreadch := ch;
+  END Read;
+
+  PROCEDURE BusyRead(VAR ch: CHAR);
+    VAR l: INTEGER;
+  BEGIN
+	IF unread THEN
+		ch := unreadch;
+		unread := FALSE
+	ELSE
+#ifdef __USG
+		l := fcntl(fildes, (*FGETFL*) 3, 0);
+		IF fcntl(fildes,
+			      (* FSETFL *) 4,
+			      l + (*ONDELAY*) 2) < 0 THEN
+			;
+		END;
+		IF read(fildes, ADR(ch), 1) = 0 THEN
+			ch := 0C;
+		ELSE
+			unreadch := ch;
+		END;
+		IF fcntl(fildes, (*FSETFL*)4, l) < 0 THEN
+			;
+		END;
+#else
+#ifdef __BSD4_2
+		IF ioctl(fildes, INTEGER(ORD('f')*256+127+4*65536+40000000H), ADR(l)) < 0 THEN
+#else
+		IF ioctl(fildes, INTEGER(ORD('f')*256+127), ADR(l)) < 0 THEN
+#endif
+			;
+		END;
+
+		IF l = 0 THEN
+			ch := 0C;
+		ELSE
+			IF read(fildes, ADR(ch), 1) < 0 THEN
+				;
+			END;
+			unreadch := ch;
+		END;
+#endif
+  	END;
+  END BusyRead;	
+
+  PROCEDURE ReadAgain;
+  BEGIN
+	unread := TRUE;
+  END ReadAgain;
+
+  PROCEDURE Write(ch: CHAR);
+  BEGIN
+	IF write(fildes, ADR(ch), 1) < 0 THEN
+		;
+	END;
+  END Write;
+
+  PROCEDURE WriteLn;
+  BEGIN
+	Write(12C);
+  END WriteLn;
+
+  PROCEDURE WriteString(s: ARRAY OF CHAR);
+    VAR i: CARDINAL;
+  BEGIN
+	i := 0;
+	WHILE (i <= HIGH(s)) & (s[i] # 0C) DO
+		Write(s[i]);
+		INC(i)
+	END
+  END WriteString;
+
+BEGIN
+	tty := "/dev/tty";
+	fildes := open(ADR(tty), 2);
+	unread := FALSE;
+END Terminal.
Index: /trunk/minix/lib/ack/libm2/Traps.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/Traps.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/Traps.mod	(revision 9)
@@ -0,0 +1,96 @@
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE Traps;
+(*
+  Module:       Facility for handling traps
+  Author:       Ceriel J.H. Jacobs
+  Version:      $Header: /cvsup/minix/src/lib/ack/libm2/Traps.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+*)
+
+  FROM	EM IMPORT	SIG, LINO, FILN, TRP;
+  FROM	Unix IMPORT	write;
+  FROM	SYSTEM IMPORT	ADDRESS, ADR;
+  FROM	Arguments IMPORT
+			Argv;
+
+  PROCEDURE InstallTrapHandler(t: TrapHandler): TrapHandler;
+  (* Install a new trap handler, and return the previous one.
+     Parameter of trap handler is the trap number.
+  *)
+  BEGIN
+	RETURN SIG(t);
+  END InstallTrapHandler;
+
+  PROCEDURE Message(str: ARRAY OF CHAR);
+  (* Write message "str" on standard error, preceeded by filename and
+     linenumber if possible
+  *)
+  VAR 	p: POINTER TO CHAR;
+	l: CARDINAL;
+	lino: INTEGER;
+	buf, buf2: ARRAY [0..255] OF CHAR;
+	i, j: CARDINAL;
+  BEGIN
+	p := FILN();
+	IF p # NIL THEN
+		i := 1;
+		buf[0] := '"';
+		WHILE p^ # 0C DO
+			buf[i] := p^;
+			INC(i);
+			p := ADDRESS(p) + 1;
+		END;
+		buf[i] := '"';
+		INC(i);
+		IF write(2, ADR(buf), i) < 0 THEN END;
+	ELSE
+		l := Argv(0, buf);
+		IF write(2, ADR(buf), l-1) < 0 THEN END;
+	END;
+	lino := LINO();
+	i := 0;
+	IF lino # 0 THEN
+		i := 7;
+		buf[0] := ','; buf[1] := ' ';
+		buf[2] := 'l'; buf[3] := 'i'; buf[4] := 'n'; buf[5] := 'e';
+		buf[6] := ' ';
+		IF lino < 0 THEN
+			buf[7] := '-';
+			i := 8;
+			lino := - lino;
+		END;
+		j := 0;
+		REPEAT
+			buf2[j] := CHR(CARDINAL(lino) MOD 10 + ORD('0'));
+			lino := lino DIV 10;
+			INC(j);
+		UNTIL lino = 0;
+		WHILE j > 0 DO
+			DEC(j);
+			buf[i] := buf2[j];
+			INC(i);
+		END;
+	END;
+	buf[i] := ':';
+	buf[i+1] := ' ';
+	IF write(2, ADR(buf), i+2) < 0 THEN END;
+	i := 0;
+	WHILE (i <= HIGH(str)) AND (str[i] # 0C) DO
+		INC(i);
+	END;
+	IF write(2, ADR(str), i) < 0 THEN END;
+	buf[0] := 12C;
+	IF write(2, ADR(buf), 1) < 0 THEN END;
+  END Message;
+
+  PROCEDURE Trap(n: INTEGER);
+  (* cause trap number "n" to occur *)
+  BEGIN
+	TRP(n);
+  END Trap;
+
+END Traps.
Index: /trunk/minix/lib/ack/libm2/XXTermcap.c
===================================================================
--- /trunk/minix/lib/ack/libm2/XXTermcap.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/XXTermcap.c	(revision 9)
@@ -0,0 +1,573 @@
+/*
+ *	termcap.c	1.1	20/7/87		agc	Joypace Ltd
+ *
+ *	Copyright Joypace Ltd, London, UK, 1987. All rights reserved.
+ *	This file may be freely distributed provided that this notice
+ *	remains attached.
+ *
+ *	A public domain implementation of the termcap(3) routines.
+ *
+ *	Made fully functional by Ceriel J.H. Jacobs.
+ *
+ * BUGS:
+ *	- does not check termcap entry sizes
+ *	- not fully tested
+ */
+
+#define CAPABLEN	2
+
+#define ISSPACE(c)	((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
+#define ISDIGIT(x)	((x) >= '0' && (x) <= '9')
+
+short	ospeed = 0;		/* output speed */
+char	PC = 0;			/* padding character */
+char	*BC = 0;		/* back cursor movement */
+char	*UP = 0;		/* up cursor movement */
+
+static char	*capab = 0;		/* the capability itself */
+static int	check_for_tc();
+static int	match_name();
+
+#define NULL	0
+
+/* Some things from C-library, needed here because the C-library is not
+   loaded with Modula-2 programs
+*/
+
+static char *
+strcat(s1, s2)
+register char *s1, *s2;
+{
+  /* Append s2 to the end of s1. */
+
+  char *original = s1;
+
+  /* Find the end of s1. */
+  while (*s1 != 0) s1++;
+
+  /* Now copy s2 to the end of s1. */
+  while (*s1++ = *s2++) /* nothing */ ;
+  return(original);
+}
+
+static char *
+strcpy(s1, s2)
+register char *s1, *s2;
+{
+/* Copy s2 to s1. */
+  char *original = s1;
+
+  while (*s1++ = *s2++) /* nothing */;
+  return(original);
+}
+
+static int
+strlen(s)
+char *s;
+{
+/* Return length of s. */
+
+  char *original = s;
+
+  while (*s != 0) s++;
+  return(s - original);
+}
+
+static int
+strcmp(s1, s2)
+register char *s1, *s2;
+{
+/* Compare 2 strings. */
+
+  for(;;) {
+	if (*s1 != *s2) {
+		if (!*s1) return -1;
+		if (!*s2) return 1;
+		return(*s1 - *s2);
+	}
+	if (*s1++ == 0) return(0);
+	s2++;
+  }
+}
+
+static int
+strncmp(s1, s2, n)
+	register char *s1, *s2;
+	int n;
+{
+/* Compare two strings, but at most n characters. */
+
+  while (n-- > 0) {
+	if (*s1 != *s2) {
+		if (!*s1) return -1;
+		if (!*s2) return 1;
+		return(*s1 - *s2);
+	}
+	if (*s1++ == 0) break;
+	s2++;
+  }
+  return 0;
+}
+
+static char *
+getenv(name)
+register char *name;
+{
+  extern char ***_penviron;
+  register char **v = *_penviron, *p, *q;
+
+  if (v == 0 || name == 0) return 0;
+  while ((p = *v++) != 0) {
+	q = name;
+	while (*q && *q++ == *p++) /* nothing */ ;
+	if (*q || *p != '=') continue;
+	return(p+1);
+  }
+  return(0);
+}
+
+static char *
+fgets(buf, count, fd)
+	char *buf;
+{
+	static char bf[1024];
+	static int cnt = 0;
+	static char *pbf = &bf[0];
+	register char *c = buf;
+
+
+	while (--count) {
+		if (pbf >= &bf[cnt]) {
+			if ((cnt = read(fd, bf, 1024)) <= 0) {
+				if (c == buf) return (char *) NULL;
+				*c = 0;
+				return buf;
+			}
+			pbf = &bf[0];
+		}
+		*c = *pbf++;
+		if (*c++ == '\n') {
+			*c = 0;
+			return buf;
+		}
+	}
+	*c = 0;
+	return buf;
+}
+
+/*
+ *	tgetent - get the termcap entry for terminal name, and put it
+ *	in bp (which must be an array of 1024 chars). Returns 1 if
+ *	termcap entry found, 0 if not found, and -1 if file not found.
+ */
+int
+tgetent(bp, name)
+char	*bp;
+char	*name;
+{
+	int	fp;
+	char	*file;
+	char	*cp;
+	short	len = strlen(name);
+	char	buf[1024];
+
+	capab = bp;
+	if ((file = getenv("TERMCAP")) != (char *) NULL) {
+		if (*file != '/' &&
+		    (cp = getenv("TERM")) != NULL && strcmp(name, cp) == 0) {
+			(void) strcpy(bp, file);
+			return(1);
+		}
+		else file = "/etc/termcap";
+	} else
+		file = "/etc/termcap";
+	if ((fp = open(file, 0)) < 0) {
+		capab = 0;
+		return(-1); 
+	}
+	while (fgets(buf, 1024, fp) != NULL) {
+		if (buf[0] == '#') continue;
+		while (*(cp = &buf[strlen(buf) - 2]) == '\\')
+			if (fgets(cp, 1024, fp) == NULL)
+				return (0);
+		if (match_name(buf, name)) {
+			strcpy(bp, buf);
+			close(fp);
+			if(check_for_tc() == 0) {
+				capab = 0;
+				return 0;
+			}
+			return 1;
+		}
+	}
+	capab = 0;
+	close(fp);
+	return(0);
+}
+
+/*
+ *	Compare the terminal name with each termcap entry name; Return 1 if a
+ *	match is found.
+ */
+static int
+match_name(buf, name)
+	char	*buf;
+	char	*name;
+{
+	register char	*tp = buf;
+	register char	*np;
+
+	for (;;) {
+		for (np = name; *np && *tp == *np; np++, tp++) { }
+		if (*np == 0 && (*tp == '|' || *tp == ':' || *tp == 0))
+			return(1);
+		while (*tp != 0 && *tp != '|' && *tp != ':') tp++;
+		if (*tp++ != '|') return (0);
+	}
+}
+
+/*
+ *	Handle tc= definitions recursively.
+ */
+static int
+check_for_tc()
+{
+	static int	count = 0;
+	char		*savcapab = capab;
+	char		buf[1024];
+	char		terminalname[128];
+	register char	*p = capab + strlen(capab) - 2, *q;
+
+	while (*p != ':')
+		if (--p < capab)
+			return(0);	/* no : in termcap entry */
+	if (p[1] != 't' || p[2] != 'c')
+		return(1);
+	if (count > 16) {
+		return(0);	/* recursion in tc= definitions */
+	}
+	count++;
+	strcpy(terminalname, &p[4]);
+	q = terminalname;
+	while (*q && *q != ':') q++;
+	*q = 0;
+	if (tgetent(buf, terminalname) != 1) {
+		--count;
+		return(0);
+	}
+	--count;
+	for (q = buf; *q && *q != ':'; q++) { }
+	strcpy(p, q);
+	capab = savcapab;
+	return(1);
+}
+
+/*
+ *	tgetnum - get the numeric terminal capability corresponding
+ *	to id. Returns the value, -1 if invalid.
+ */
+int
+tgetnum(id)
+char	*id;
+{
+	char	*cp;
+	int	ret;
+
+	if ((cp = capab) == NULL || id == NULL || *cp == 0)
+		return(-1);
+	while (*++cp && *cp != ':')
+		;
+	while (*cp) {
+		cp++;
+		while (ISSPACE(*cp))
+			cp++;
+		if (strncmp(cp, id, CAPABLEN) == 0) {
+			while (*cp && *cp != ':' && *cp != '#')
+				cp++;
+			if (*cp != '#')
+				return(-1);
+			for (ret = 0, cp++ ; *cp && ISDIGIT(*cp) ; cp++)
+				ret = ret * 10 + *cp - '0';
+			return(ret);
+		}
+		while (*cp && *cp != ':')
+			cp++;
+	}
+	return(-1);
+}
+
+/*
+ *	tgetflag - get the boolean flag corresponding to id. Returns -1
+ *	if invalid, 0 if the flag is not in termcap entry, or 1 if it is
+ *	present.
+ */
+int
+tgetflag(id)
+char	*id;
+{
+	char	*cp;
+
+	if ((cp = capab) == NULL || id == NULL || *cp == 0)
+		return(-1);
+	while (*++cp && *cp != ':')
+		;
+	while (*cp) {
+		cp++;
+		while (ISSPACE(*cp))
+			cp++;
+		if (strncmp(cp, id, CAPABLEN) == 0)
+			return(1);
+		while (*cp && *cp != ':')
+			cp++;
+	}
+	return(0);
+}
+
+/*
+ *	tgetstr - get the string capability corresponding to id and place
+ *	it in area (advancing area at same time). Expand escape sequences
+ *	etc. Returns the string, or NULL if it can't do it.
+ */
+char *
+tgetstr(id, area)
+char	*id;
+char	**area;
+{
+	char	*cp;
+	char	*ret;
+	int	i;
+
+	if ((cp = capab) == NULL || id == NULL || *cp == 0)
+		return(NULL);
+	while (*++cp != ':')
+		;
+	while (*cp) {
+		cp++;
+		while (ISSPACE(*cp))
+			cp++;
+		if (strncmp(cp, id, CAPABLEN) == 0) {
+			while (*cp && *cp != ':' && *cp != '=')
+				cp++;
+			if (*cp != '=')
+				return(NULL);
+			for (ret = *area, cp++; *cp && *cp != ':' ; (*area)++, cp++)
+				switch(*cp) {
+				case '^' :
+					**area = *++cp - 'A' + 1;
+					break;
+				case '\\' :
+					switch(*++cp) {
+					case 'E' :
+						**area = '\033';
+						break;
+					case 'n' :
+						**area = '\n';
+						break;
+					case 'r' :
+						**area = '\r';
+						break;
+					case 't' :
+						**area = '\t';
+						break;
+					case 'b' :
+						**area = '\b';
+						break;
+					case 'f' :
+						**area = '\f';
+						break;
+					case '0' :
+					case '1' :
+					case '2' :
+					case '3' :
+						for (i=0 ; *cp && ISDIGIT(*cp) ; cp++)
+							i = i * 8 + *cp - '0';
+						**area = i;
+						cp--;
+						break;
+					case '^' :
+					case '\\' :
+						**area = *cp;
+						break;
+					}
+					break;
+				default :
+					**area = *cp;
+				}
+			*(*area)++ = '\0';
+			return(ret);
+		}
+		while (*cp && *cp != ':')
+			cp++;
+	}
+	return(NULL);
+}
+
+/*
+ *	tgoto - given the cursor motion string cm, make up the string
+ *	for the cursor to go to (destcol, destline), and return the string.
+ *	Returns "OOPS" if something's gone wrong, or the string otherwise.
+ */
+char *
+tgoto(cm, destcol, destline)
+char	*cm;
+int	destcol;
+int	destline;
+{
+	register char	*rp;
+	static char	ret[32];
+	char		added[16];
+	int		*dp = &destline;
+	int 		numval;
+	int		swapped = 0;
+
+	added[0] = 0;
+	for (rp = ret ; *cm ; cm++) {
+		if (*cm == '%') {
+			switch(*++cm) {
+			case '>' :
+				if (dp == NULL)
+					return("OOPS");
+				cm++;
+				if (*dp > *cm++) {
+					*dp += *cm;
+				}
+				break;
+			case '+' :
+			case '.' :
+				if (dp == NULL)
+					return("OOPS");
+				if (*cm == '+') *dp = *dp + *++cm;
+				for (;;) {
+				    switch(*dp) {
+				    case 0:
+				    case 04:
+				    case '\t':
+				    case '\n':
+					/* filter these out */
+					if (dp == &destcol || swapped || UP) {
+						strcat(added, dp == &destcol || swapped ?
+							(BC ? BC : "\b") :
+							UP);
+						(*dp)++;
+						continue;
+					}
+				    }
+				    break;
+				}
+				*rp++ = *dp;
+				dp = (dp == &destline) ? &destcol : NULL;
+				break;
+
+			case 'r' : {
+				int tmp = destline;
+
+				destline = destcol;
+				destcol = tmp;
+				swapped = 1 - swapped;
+				break;
+			}
+			case 'n' :
+				destcol ^= 0140;
+				destline ^= 0140;
+				break;
+
+			case '%' :
+				*rp++ = '%';
+				break;
+
+			case 'i' :
+				destcol++;
+				destline++;
+				break;
+
+			case 'B' :
+				if (dp == NULL)
+					return("OOPS");
+				*dp = 16 * (*dp / 10) + *dp % 10;
+				break;
+
+			case 'D' :
+				if (dp == NULL)
+					return("OOPS");
+				*dp = *dp - 2 * (*dp % 16);
+				break;
+
+			case 'd' :
+			case '2' :
+			case '3' :
+				if (dp == NULL)
+					return("OOPS");
+				numval = *dp;
+				dp = (dp == &destline) ? &destcol : NULL;
+				if (numval >= 100) {
+					*rp++ = '0' + numval / 100;
+				}
+				else if (*cm == '3') {
+					*rp++ = ' ';
+				}
+				if (numval >= 10) {
+					*rp++ = '0' + ((numval%100)/10);
+				}
+				else if (*cm == '3' || *cm == '2') {
+					*rp++ = ' ';
+				}
+				*rp++ = '0' + (numval%10);
+				break;
+			default :
+				return("OOPS");
+			}
+		}
+		else *rp++ = *cm;
+	}
+	*rp = '\0';
+	strcpy(rp, added);
+	return(ret);
+}
+
+static int tens_of_ms_p_char[] = {	/* index as returned by gtty */
+					/* assume 10 bits per char */
+	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 2
+};
+/*
+ *	tputs - put the string cp out onto the terminal, using the function
+ *	outc. Also handle padding.
+ */
+int
+tputs(cp, affcnt, outc)
+register char	*cp;
+int		affcnt;
+int		(*outc)();
+{
+	int delay = 0;
+	if (cp == NULL)
+		return(1);
+	while (ISDIGIT(*cp)) {
+		delay = delay * 10 + (*cp++ - '0');
+	}
+	delay *= 10;
+	if (*cp == '.') {
+		cp++;
+		if (ISDIGIT(*cp)) {
+			delay += *cp++ - '0';
+		}
+		while (ISDIGIT(*cp)) cp++;
+	}
+	if (*cp == '*') {
+		delay *= affcnt;
+		cp++;
+	}
+	while (*cp)
+		(*outc)(*cp++);
+	if (delay != 0 &&
+	    ospeed > 0 &&
+	    ospeed < (sizeof tens_of_ms_p_char / sizeof tens_of_ms_p_char[0])) {
+		delay = (delay + tens_of_ms_p_char[ospeed] - 1) / 
+				  tens_of_ms_p_char[ospeed];
+		while (delay--) (*outc)(PC);
+	}
+	return(1);
+}
+
+/*
+ *	That's all, folks...
+ */
Index: /trunk/minix/lib/ack/libm2/absd.c
===================================================================
--- /trunk/minix/lib/ack/libm2/absd.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/absd.c	(revision 9)
@@ -0,0 +1,18 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	double abs function
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/absd.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+#ifndef NOFLOAT
+double
+absd(i)
+	double i;
+{
+	return i >= 0 ? i : -i;
+}
+#endif
Index: /trunk/minix/lib/ack/libm2/absf.e
===================================================================
--- /trunk/minix/lib/ack/libm2/absf.e	(revision 9)
+++ /trunk/minix/lib/ack/libm2/absf.e	(revision 9)
@@ -0,0 +1,30 @@
+#
+;
+; (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+; See the copyright notice in the ACK home directory, in the file "Copyright".
+;
+;
+; Module:	REAL abs function
+; Author:	Ceriel J.H. Jacobs
+; Version:	$Header: /cvsup/minix/src/lib/ack/libm2/absf.e,v 1.1 2005/10/10 15:27:46 beng Exp $
+;
+ mes 2,_EM_WSIZE,_EM_PSIZE
+ exp $absf
+ pro $absf,0
+ mes 5
+ mes 9,8
+ lal 0
+ loi _EM_FSIZE
+ zrf _EM_FSIZE
+ cmf _EM_FSIZE
+ zlt *3
+ lal 0
+ loi _EM_FSIZE
+ bra *4
+3
+ lal 0
+ loi _EM_FSIZE
+ ngf _EM_FSIZE
+4
+ ret _EM_FSIZE
+ end 0
Index: /trunk/minix/lib/ack/libm2/absi.c
===================================================================
--- /trunk/minix/lib/ack/libm2/absi.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/absi.c	(revision 9)
@@ -0,0 +1,15 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	integer abs function
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/absi.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+
+absi(i)
+{
+	return i >= 0 ? i : -i;
+}
Index: /trunk/minix/lib/ack/libm2/absl.c
===================================================================
--- /trunk/minix/lib/ack/libm2/absl.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/absl.c	(revision 9)
@@ -0,0 +1,16 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	longint abs function
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/absl.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+long
+absl(i)
+	long i;
+{
+	return i >= 0 ? i : -i;
+}
Index: /trunk/minix/lib/ack/libm2/blockmove.c
===================================================================
--- /trunk/minix/lib/ack/libm2/blockmove.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/blockmove.c	(revision 9)
@@ -0,0 +1,23 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	block moves
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/blockmove.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+
+#if _EM_WSIZE==_EM_PSIZE
+typedef unsigned pcnt;
+#else
+typedef unsigned long pcnt;
+#endif
+
+blockmove(siz, dst, src)
+	pcnt siz;
+	register char *dst, *src;
+{
+	while (siz--) *dst++ = *src++;
+}
Index: /trunk/minix/lib/ack/libm2/cap.c
===================================================================
--- /trunk/minix/lib/ack/libm2/cap.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/cap.c	(revision 9)
@@ -0,0 +1,18 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	cap; implementation of CAP
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/cap.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+
+cap(u)
+	unsigned u;
+{
+	register unsigned *p = &u;
+
+	if (*p >= 'a' && *p <= 'z') *p += 'A'-'a';
+}
Index: /trunk/minix/lib/ack/libm2/catch.c
===================================================================
--- /trunk/minix/lib/ack/libm2/catch.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/catch.c	(revision 9)
@@ -0,0 +1,99 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	default modula-2 trap handler
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/catch.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+#include <em_abs.h>
+#include <m2_traps.h>
+#include <signal.h>
+
+static struct errm {
+	int errno;
+	char *errmes;
+} errors[] = {
+	{ EARRAY,	"array bound error"},
+	{ ERANGE,	"range bound error"},
+	{ ESET,		"set bound error"},
+	{ EIOVFL,	"integer overflow"},
+	{ EFOVFL,	"real overflow"},
+	{ EFUNFL,	"real underflow"},
+	{ EIDIVZ,	"divide by 0"},
+	{ EFDIVZ,	"divide by 0.0"},
+	{ EIUND,	"undefined integer"},
+	{ EFUND,	"undefined real"},
+	{ ECONV,	"conversion error"},
+
+	{ ESTACK,	"stack overflow"},
+	{ EHEAP,	"heap overflow"},
+	{ EILLINS,	"illegal instruction"},
+	{ EODDZ,	"illegal size argument"},
+	{ ECASE,	"case error"},
+	{ EMEMFLT,	"addressing non existent memory"},
+	{ EBADPTR,	"bad pointer used"},
+	{ EBADPC,	"program counter out of range"},
+	{ EBADLAE,	"bad argument of lae"},
+	{ EBADMON,	"bad monitor call"},
+	{ EBADLIN,	"argument if LIN too high"},
+	{ EBADGTO,	"GTO descriptor error"},
+
+	{ M2_TOOLARGE,	"stack size of process too large"},
+	{ M2_TOOMANY,	"too many nested traps + handlers"},
+	{ M2_NORESULT,	"no RETURN from function procedure"},
+	{ M2_UOVFL,	"cardinal overflow"},
+	{ M2_FORCH,	"(warning) FOR-loop control variable was changed in the body"},
+	{ M2_UUVFL,	"cardinal underflow"},
+	{ M2_INTERNAL,	"internal error; ask an expert for help"},
+	{ M2_UNIXSIG,	"got a unix signal"},
+	{ -1,		0}
+};
+
+catch(trapno)
+	int trapno;
+{
+	register struct errm *ep = &errors[0];
+	char *errmessage;
+	char buf[20];
+	register char *p, *s;
+
+	while (ep->errno != trapno && ep->errmes != 0) ep++;
+	if (p = ep->errmes) {
+		while (*p) p++;
+		_Traps__Message(ep->errmes, 0, (int) (p - ep->errmes), 1);
+	}
+	else {
+		int i = trapno;
+		static char q[] = "error number xxxxxxxxxxxxx";
+
+		p = &q[13];
+		s = buf;
+		if (i < 0) {
+			i = -i;
+			*p++ = '-';
+		}
+		do
+			*s++ = i % 10 + '0';
+		while (i /= 10);
+		while (s > buf) *p++ = *--s;
+		*p = 0;
+		_Traps__Message(q, 0, (int) (p - q), 1);
+	}
+#if !defined(__em24) && !defined(__em44) && !defined(__em22)
+	if (trapno == M2_UNIXSIG) {
+		extern int __signo;
+		signal(__signo, SIG_DFL);
+		_cleanup();
+		kill(getpid(), __signo);
+		_exit(trapno);
+	}
+#endif
+	if (trapno != M2_FORCH) {
+		_cleanup();
+		_exit(trapno);
+	}
+	SIG(catch);
+}
Index: /trunk/minix/lib/ack/libm2/confarray.c
===================================================================
--- /trunk/minix/lib/ack/libm2/confarray.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/confarray.c	(revision 9)
@@ -0,0 +1,72 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	runtime support for conformant arrays
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/confarray.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+#include <m2_traps.h>
+
+#ifndef EM_WSIZE
+#define EM_WSIZE _EM_WSIZE
+#define EM_PSIZE _EM_PSIZE
+#endif
+
+#if EM_WSIZE==EM_PSIZE
+typedef unsigned pcnt;
+#else
+typedef unsigned long pcnt;
+#endif
+
+struct descr {
+	char *addr;
+	int low;
+	unsigned int highminlow;
+	unsigned int size;
+};
+
+static struct descr *descrs[10];
+static struct descr **ppdescr = descrs;
+
+pcnt
+new_stackptr(pdscr, a)
+	struct descr *pdscr;
+{
+	register struct descr *pdescr = pdscr;
+	pcnt size = (((pdescr->highminlow + 1) * pdescr->size +
+				(EM_WSIZE - 1)) & ~(EM_WSIZE - 1));
+
+	if (ppdescr >= &descrs[10]) {
+		/* to many nested traps + handlers ! */
+		TRP(M2_TOOMANY);
+	}
+	*ppdescr++ = pdescr;
+	if ((char *) &a - (char *) &pdscr > 0) {
+		/* stack grows downwards */
+		return - size;
+	}
+	return size;
+}
+
+copy_array(pp, a)
+	char *pp;
+{
+	register char *p = pp;
+	register char *q;
+	register pcnt sz;
+	char dummy;
+
+	ppdescr--;
+	sz = ((*ppdescr)->highminlow + 1) * (*ppdescr)->size;
+	
+	if ((char *) &a - (char *) &pp > 0) {
+		(*ppdescr)->addr = q = (char *) &a;
+	}
+	else	(*ppdescr)->addr = q = (char *) &a - 
+			((sz + (EM_WSIZE - 1)) & ~ (EM_WSIZE - 1));
+
+	while (sz--) *q++ = *p++;
+}
Index: /trunk/minix/lib/ack/libm2/dvi.c
===================================================================
--- /trunk/minix/lib/ack/libm2/dvi.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/dvi.c	(revision 9)
@@ -0,0 +1,68 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	implementation of DIV and MOD
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/dvi.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+  Reason:	We cannot use DVI and RMI, because DVI rounds towards 0
+		and Modula-2 requires truncation
+*/
+
+#include <em_abs.h>
+
+int
+dvi(j,i)
+	int j,i;
+{
+	if (j == 0) TRP(EIDIVZ);
+	if ((i < 0) != (j < 0)) {
+		if (i < 0) i = -i;
+		else j = -j;
+		return -((i+j-1)/j);
+	}
+	else return i/j;
+}
+
+long
+dvil(j,i)
+	long j,i;
+{
+	if (j == 0) TRP(EIDIVZ);
+	if ((i < 0) != (j < 0)) {
+		if (i < 0) i = -i;
+		else j = -j;
+		return -((i+j-1)/j);
+	}
+	else return i/j;
+}
+
+int
+rmi(j,i)
+	int j,i;
+{
+	if (j == 0) TRP(EIDIVZ);
+	if (i == 0) return 0;
+	if ((i < 0) != (j < 0)) {
+		if (i < 0) i = -i;
+		else j = -j;
+		return j*((i+j-1)/j)-i;
+	}
+	else return i%j;
+}
+
+long
+rmil(j,i)
+	long j,i;
+{
+	if (j == 0) TRP(EIDIVZ);
+	if (i == 0) return 0L;
+	if ((i < 0) != (j < 0)) {
+		if (i < 0) i = -i;
+		else j = -j;
+		return j*((i+j-1)/j)-i;
+	}
+	else return i%j;
+}
Index: /trunk/minix/lib/ack/libm2/halt.c
===================================================================
--- /trunk/minix/lib/ack/libm2/halt.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/halt.c	(revision 9)
@@ -0,0 +1,37 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	program termination routines
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/halt.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+#define MAXPROCS 32
+
+static int callindex = 0;
+static int (*proclist[MAXPROCS])();
+
+_cleanup()
+{
+	while (--callindex >= 0)
+		(*proclist[callindex])();
+	callindex = 0;
+}
+
+CallAtEnd(p)
+	int (*p)();
+{
+	if (callindex >= MAXPROCS) {
+		return 0;
+	}
+	proclist[callindex++] = p;
+	return 1;
+}
+
+halt()
+{
+	_cleanup();
+	_exit(0);
+}
Index: /trunk/minix/lib/ack/libm2/head_m2.e
===================================================================
--- /trunk/minix/lib/ack/libm2/head_m2.e	(revision 9)
+++ /trunk/minix/lib/ack/libm2/head_m2.e	(revision 9)
@@ -0,0 +1,63 @@
+#
+;
+; (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+; See the copyright notice in the ACK home directory, in the file "Copyright".
+;
+;
+; Module:	Modula-2 runtime startoff
+; Author:	Ceriel J.H. Jacobs
+; Version:	$Header: /cvsup/minix/src/lib/ack/libm2/head_m2.e,v 1.1 2005/10/10 15:27:46 beng Exp $
+;
+
+ mes 2,_EM_WSIZE,_EM_PSIZE
+
+ exa handler
+ exa argv
+ exa argc
+ exa MainLB
+ exa bkillbss
+ exp $catch
+ exp $init
+ inp $trap_handler
+
+bkillbss
+ bss _EM_PSIZE,0,0
+
+ exp $_m_a_i_n
+ pro $_m_a_i_n, 0
+
+ lor 0
+ lae MainLB
+ sti _EM_PSIZE
+
+ lal _EM_WSIZE
+ loi _EM_PSIZE
+ lae argv		; save argument pointer
+ sti _EM_PSIZE
+
+ lol 0
+ ste argc		; save argument count
+
+ lpi $trap_handler
+ sig
+ asp _EM_PSIZE
+ cal $init
+ cal $__M2M_
+ cal $halt
+ loc 0			; should not get here
+ ret _EM_WSIZE
+ end
+
+ pro $trap_handler,0
+ lpi $trap_handler
+ sig
+ lol 0	; trap number
+ lae handler
+ loi _EM_PSIZE
+ lpi $catch
+ lae handler
+ sti _EM_PSIZE
+ cai
+ asp _EM_PSIZE+_EM_WSIZE
+ rtt
+ end 0
Index: /trunk/minix/lib/ack/libm2/init.c
===================================================================
--- /trunk/minix/lib/ack/libm2/init.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/init.c	(revision 9)
@@ -0,0 +1,51 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	initialization and some global vars
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/init.c,v 1.2 2006/02/17 14:12:47 philip Exp $
+*/
+
+#include <signal.h>
+#include <em_abs.h>
+#include <m2_traps.h>
+
+/* map unix signals onto EM traps */
+init()
+{
+	sigtrp(M2_UNIXSIG, SIGHUP);
+	sigtrp(M2_UNIXSIG, SIGINT);
+	sigtrp(M2_UNIXSIG, SIGQUIT);
+	sigtrp(EILLINS, SIGILL);
+	sigtrp(M2_UNIXSIG, SIGTRAP);
+#ifdef SIGIOT
+	sigtrp(M2_UNIXSIG, SIGIOT);
+#endif
+#if SIGEMT
+	sigtrp(M2_UNIXSIG, SIGEMT);
+#endif
+	sigtrp(M2_UNIXSIG, SIGFPE);
+	sigtrp(M2_UNIXSIG, SIGBUS);
+	sigtrp(M2_UNIXSIG, SIGSEGV);
+#ifdef SIGSYS
+	sigtrp(EBADMON, SIGSYS);
+#endif
+	sigtrp(M2_UNIXSIG, SIGPIPE);
+	sigtrp(M2_UNIXSIG, SIGALRM);
+	sigtrp(M2_UNIXSIG, SIGTERM);
+}
+
+killbss()
+{
+	/* Fill bss with junk?  Make lots of VM pages dirty?  No way! */
+}
+
+extern int catch();
+
+int (*handler)() = catch;
+char **argv;
+int argc;
+char *MainLB;
Index: /trunk/minix/lib/ack/libm2/load.c
===================================================================
--- /trunk/minix/lib/ack/libm2/load.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/load.c	(revision 9)
@@ -0,0 +1,45 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	get value on stack, byte by byte
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/load.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+
+#include <m2_traps.h>
+
+#ifndef EM_WSIZE
+#define EM_WSIZE _EM_WSIZE
+#define EM_PSIZE _EM_PSIZE
+#endif
+
+#if EM_WSIZE==EM_PSIZE
+typedef unsigned pcnt;
+#else
+typedef long pcnt;
+#endif
+
+load(siz, addr, p)
+	register char *addr;
+	register pcnt siz;
+{
+	/*	Make sure, that a value with a size that could have been
+		handled by the LOI instruction ends up at the same place,
+		where it would, were the LOI instruction used.
+	*/
+	register char *q = (char *) &p;
+	char t[4];
+
+	if (siz < EM_WSIZE && EM_WSIZE % siz == 0) {
+		/* as long as EM_WSIZE <= 4 ... */
+		if (siz != 2) TRP(M2_INTERNAL);	/* internal error */
+		q = &t[0];
+	}
+	while (siz--) *q++ = *addr++;
+	if (q - t == 2) {
+		*((unsigned *)(&p)) = *((unsigned short *) (&t[0]));
+	}
+}
Index: /trunk/minix/lib/ack/libm2/par_misc.e
===================================================================
--- /trunk/minix/lib/ack/libm2/par_misc.e	(revision 9)
+++ /trunk/minix/lib/ack/libm2/par_misc.e	(revision 9)
@@ -0,0 +1,175 @@
+#
+;
+; (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+; See the copyright notice in the ACK home directory, in the file "Copyright".
+;
+
+;
+; Module:	coroutine primitives
+; Author:	Kees Bot, Edwin Scheffer, Ceriel Jacobs
+; Version:	$Header: /cvsup/minix/src/lib/ack/libm2/par_misc.e,v 1.1 2005/10/10 15:27:46 beng Exp $
+;
+
+ mes 2,_EM_WSIZE,_EM_PSIZE
+
+ ; topsize takes care of two things:
+ ; - given a stack-break,
+ ;   it computes the size of the chunk of memory needed to save the stack;
+ ; - also, if this stack-break = 0, it creates one, assuming that caller is
+ ;   the stack-break.
+ ;
+ ; This implementation assumes a continuous stack growing downwards
+
+ exp $topsize
+#ifdef __sparc
+ inp $topsize2
+ pro $topsize, 0
+ mes 11
+ zer _EM_PSIZE
+ lal 0
+ loi _EM_PSIZE
+ cal $topsize2
+ asp 2*_EM_PSIZE
+ lfr _EM_WSIZE
+ ret _EM_WSIZE
+ end 0
+ pro $topsize2, (3*_EM_WSIZE+3*_EM_PSIZE)
+#else
+ pro $topsize, (3*_EM_WSIZE+3*_EM_PSIZE)
+#endif
+ ; local space for line-number, ignoremask, filename, stack-break, size,
+ ; and stack-pointer (see the topsave routine)
+ mes 11
+ lal 0
+ loi _EM_PSIZE
+ loi _EM_PSIZE		; stack-break or 0
+ zer _EM_PSIZE
+ cmp
+ zne *1
+ lxl 0
+ dch			; local base of caller
+#ifdef __sparc
+ dch			; because of the extra layer
+#endif
+ lal 0
+ loi _EM_PSIZE
+ sti _EM_PSIZE
+1
+ lal 0
+ loi _EM_PSIZE
+ loi _EM_PSIZE
+ lpb			; convert this local base to an argument base.
+			; An implementation of a sort of "topsize" EM
+			; instruction should take a local base, and save
+			; the whole frame.
+
+ lor 1			; stack-break  SP
+ sbs _EM_WSIZE		; stack-break-SP
+ ret _EM_WSIZE		; return size of block to be saved
+ end 3*_EM_WSIZE+3*_EM_PSIZE
+
+ exp $topsave
+#ifdef __sparc
+ inp $topsave2
+ pro $topsave,0
+ mes 11
+ lal 0
+ loi 2*_EM_PSIZE
+ cal $topsave2
+ asp 2*_EM_PSIZE
+ lfr _EM_WSIZE
+ ret _EM_WSIZE
+ end 0
+ pro $topsave2,0
+#else
+ pro $topsave, 0
+#endif
+ mes 11
+ loe 0
+ lae 4			; load line number and file name
+ loi _EM_PSIZE
+ lim			; ignore mask
+ lor 0			; LB
+ lal 0
+ loi _EM_PSIZE		; stack-break
+ lpb
+ lor 1
+ sbs _EM_WSIZE
+ loc _EM_WSIZE
+ adu _EM_WSIZE		; gives size
+ dup _EM_WSIZE
+ stl 0			; save size
+ lor 1			; SP (the SP BEFORE pushing)
+ lor 1			; SP (address of stack top to save)
+ lal _EM_PSIZE		; area
+ loi _EM_PSIZE
+ lol 0			; size
+ bls _EM_WSIZE		; move whole block
+ asp 3*_EM_PSIZE+3*_EM_WSIZE	; remove the lot from the stack
+ loc 1
+ ret _EM_WSIZE			; return 1
+ end 0
+
+sv
+ bss _EM_PSIZE,0,0
+
+ exp $topload
+#ifdef __sparc
+ inp $topload1
+ pro $topload,0
+ lal 0
+ loi _EM_PSIZE
+ cal $topload1
+ asp _EM_PSIZE
+ lfr _EM_WSIZE
+ ret _EM_WSIZE
+ end 0
+ pro $topload1, 0
+#else
+ pro $topload, 0
+#endif
+ mes 11
+
+ lal 0
+ loi _EM_PSIZE
+ lae sv
+ sti _EM_PSIZE		; saved parameter
+
+ lxl 0
+2
+ dup _EM_PSIZE
+ adp -3*_EM_PSIZE
+ lal 0
+ loi _EM_PSIZE		; compare target SP with current LB to see if we must
+ loi _EM_PSIZE
+ cmp			; find another LB first
+ zgt *1
+ dch			; just follow dynamic chain to make sure we find
+			; a legal one
+ bra *2
+1
+ str 0
+
+ lae sv
+ loi _EM_PSIZE
+ loi _EM_PSIZE		; load indirect to
+ str 1			; restore SP
+ asp 0-_EM_PSIZE	; to stop int from complaining about non-existent memory
+ lae sv
+ loi _EM_PSIZE		; source address
+ lor 1
+ adp _EM_PSIZE		; destination address
+ lae sv
+ loi _EM_PSIZE
+ adp _EM_PSIZE
+ loi _EM_WSIZE		; size of block
+ bls _EM_WSIZE
+ asp _EM_PSIZE+_EM_WSIZE	; drop size + SP
+ str 0			; restore local base
+ sim			; ignore mask
+ lae 4
+ sti _EM_PSIZE
+ ste 0			; line and file
+ loc 0
+ ret _EM_WSIZE
+ end 0
Index: /trunk/minix/lib/ack/libm2/random.mod
===================================================================
--- /trunk/minix/lib/ack/libm2/random.mod	(revision 9)
+++ /trunk/minix/lib/ack/libm2/random.mod	(revision 9)
@@ -0,0 +1,58 @@
+(*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*)
+
+(*$R-*)
+IMPLEMENTATION MODULE random;
+(*
+  Module:       random numbers
+  Author:       Ceriel J.H. Jacobs
+  Version:      $Header: /cvsup/minix/src/lib/ack/libm2/random.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
+*)
+
+  FROM	Unix IMPORT	getpid, time;
+  TYPE index = [1..55];
+
+  VAR	X: ARRAY index OF CARDINAL;
+	j, k: index;
+	tm: LONGINT;
+
+  PROCEDURE Random(): CARDINAL;
+  BEGIN
+	IF k-1 <= 0 THEN k := 55; ELSE DEC(k) END;
+	IF j-1 <= 0 THEN j := 55; ELSE DEC(j) END;
+	X[k] := X[k] + X[j];
+	RETURN X[k]
+  END Random;
+
+  PROCEDURE Uniform (lwb, upb: CARDINAL): CARDINAL;
+  BEGIN
+    	IF upb <= lwb THEN RETURN lwb; END;
+    	RETURN lwb + (Random() MOD (upb - lwb + 1));
+  END Uniform;
+
+  PROCEDURE StartSeed(seed: CARDINAL);
+  VAR v: CARDINAL;
+  BEGIN
+	FOR k := 1 TO 55 DO
+		seed := 1297 * seed + 123;
+		X[k] := seed;
+	END;
+	FOR k := 1 TO 15 DO
+		j := tm MOD 55D + 1D;
+		v := X[j];
+		tm := tm DIV 7D;
+		j := tm MOD 55D + 1D;
+		X[j] := v;
+		tm := tm * 3D;
+	END;
+	k := 1;
+	j := 25;
+  END StartSeed;
+
+BEGIN
+ 	tm := time(NIL);
+	X[1] := tm;
+	StartSeed(CARDINAL(getpid()) * X[1]);
+END random.
Index: /trunk/minix/lib/ack/libm2/rcka.c
===================================================================
--- /trunk/minix/lib/ack/libm2/rcka.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/rcka.c	(revision 9)
@@ -0,0 +1,25 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ *
+ * Module:	range checks for INTEGER, now for array indexing
+ * Author:	Ceriel J.H. Jacobs
+ * Version:	$Header: /cvsup/minix/src/lib/ack/libm2/rcka.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+
+#include <em_abs.h>
+
+extern TRP();
+
+struct array_descr {
+  int	lbound;
+  int	n_elts_min_one;
+  unsigned size;
+};
+
+rcka(descr, indx)
+  struct array_descr *descr;
+{
+  if (indx < 0 || indx > descr->n_elts_min_one) TRP(EARRAY);
+}
Index: /trunk/minix/lib/ack/libm2/rcki.c
===================================================================
--- /trunk/minix/lib/ack/libm2/rcki.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/rcki.c	(revision 9)
@@ -0,0 +1,23 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ *
+ * Module:	range checks for INTEGER
+ * Author:	Ceriel J.H. Jacobs
+ * Version:	$Header: /cvsup/minix/src/lib/ack/libm2/rcki.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+
+#include <em_abs.h>
+
+extern TRP();
+
+struct range_descr {
+  int	low, high;
+};
+
+rcki(descr, val)
+  struct range_descr *descr;
+{
+  if (val < descr->low || val > descr->high) TRP(ERANGE);
+}
Index: /trunk/minix/lib/ack/libm2/rckil.c
===================================================================
--- /trunk/minix/lib/ack/libm2/rckil.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/rckil.c	(revision 9)
@@ -0,0 +1,24 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ *
+ * Module:	range checks for LONGINT
+ * Author:	Ceriel J.H. Jacobs
+ * Version:	$Header: /cvsup/minix/src/lib/ack/libm2/rckil.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+
+#include <em_abs.h>
+
+extern TRP();
+
+struct range_descr {
+  long	low, high;
+};
+
+rckil(descr, val)
+  struct range_descr *descr;
+  long val;
+{
+  if (val < descr->low || val > descr->high) TRP(ERANGE);
+}
Index: /trunk/minix/lib/ack/libm2/rcku.c
===================================================================
--- /trunk/minix/lib/ack/libm2/rcku.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/rcku.c	(revision 9)
@@ -0,0 +1,24 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ *
+ * Module:	range checks for CARDINAL
+ * Author:	Ceriel J.H. Jacobs
+ * Version:	$Header: /cvsup/minix/src/lib/ack/libm2/rcku.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+
+#include <em_abs.h>
+
+extern TRP();
+
+struct range_descr {
+  unsigned	low, high;
+};
+
+rcku(descr, val)
+  struct range_descr *descr;
+  unsigned val;
+{
+  if (val < descr->low || val > descr->high) TRP(ERANGE);
+}
Index: /trunk/minix/lib/ack/libm2/rckul.c
===================================================================
--- /trunk/minix/lib/ack/libm2/rckul.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/rckul.c	(revision 9)
@@ -0,0 +1,24 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ *
+ * Module:	range checks for LONGCARD
+ * Author:	Ceriel J.H. Jacobs
+ * Version:	$Header: /cvsup/minix/src/lib/ack/libm2/rckul.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+
+#include <em_abs.h>
+
+extern TRP();
+
+struct range_descr {
+  unsigned long	low, high;
+};
+
+rckul(descr, val)
+  struct range_descr *descr;
+  unsigned long val;
+{
+  if (val < descr->low || val > descr->high) TRP(ERANGE);
+}
Index: /trunk/minix/lib/ack/libm2/sigtrp.c
===================================================================
--- /trunk/minix/lib/ack/libm2/sigtrp.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/sigtrp.c	(revision 9)
@@ -0,0 +1,82 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	Mapping of Unix signals to EM traps
+		(only when not using the MON instruction)
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/sigtrp.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+
+#if !defined(__em22) && !defined(__em24) && !defined(__em44)
+
+#define EM_trap(n) TRP(n)	/* define to whatever is needed to cause the trap */
+
+#include <signal.h>
+#include <errno.h>
+
+int __signo;
+
+static int __traps[] = {
+ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+};
+
+static void
+__ctchsig(signo)
+{
+	signal(signo,__ctchsig);
+#ifdef __BSD4_2
+	sigsetmask(sigblock(0) & ~(1<<(signo - 1)));
+#endif
+	__signo = signo;
+	EM_trap(__traps[signo]);
+}
+
+int
+sigtrp(trapno, signo)
+{
+	/*	Let Unix signal signo cause EM trap trapno to occur.
+		If trapno = -2, restore default,
+		If trapno = -3, ignore.
+		Return old trapnumber.
+		Careful, this could be -2 or -3; But return value of -1
+		indicates failure, with error number in errno.
+	*/
+	extern int errno;
+	void (*ctch)() = __ctchsig;
+	void (*oldctch)();
+	int oldtrap;
+
+	if (signo <= 0 || signo >= sizeof(__traps)/sizeof(__traps[0])) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (trapno == -3)
+		ctch = SIG_IGN;
+	else if (trapno == -2)
+		ctch = SIG_DFL;
+	else if (trapno >= 0 && trapno <= 252)
+		;
+	else {
+		errno = EINVAL;
+		return -1;
+	}
+
+	oldtrap = __traps[signo];
+
+	if ((oldctch = signal(signo, ctch)) == (void (*)())-1)  /* errno set by signal */
+		return -1;
+	
+	else if (oldctch == SIG_IGN) {
+		signal(signo, SIG_IGN);
+	}
+	else __traps[signo] = trapno;
+
+	return oldtrap;
+}
+#endif
Index: /trunk/minix/lib/ack/libm2/stackprio.c
===================================================================
--- /trunk/minix/lib/ack/libm2/stackprio.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/stackprio.c	(revision 9)
@@ -0,0 +1,27 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	Dummy priority routines
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/stackprio.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+
+static unsigned prio = 0;
+
+stackprio(n)
+	unsigned n;
+{
+	unsigned old = prio;
+
+	if (n > prio) prio = n;
+	return old;
+}
+
+unstackprio(n)
+	unsigned n;
+{
+	prio = n;
+}
Index: /trunk/minix/lib/ack/libm2/store.c
===================================================================
--- /trunk/minix/lib/ack/libm2/store.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/store.c	(revision 9)
@@ -0,0 +1,43 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/*
+  Module:	store values from stack, byte by byte
+  Author:	Ceriel J.H. Jacobs
+  Version:	$Header: /cvsup/minix/src/lib/ack/libm2/store.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+
+#include <m2_traps.h>
+
+#ifndef EM_WSIZE
+#define EM_WSIZE _EM_WSIZE
+#define EM_PSIZE _EM_PSIZE
+#endif
+
+#if EM_WSIZE==EM_PSIZE
+typedef unsigned pcnt;
+#else
+typedef long pcnt;
+#endif
+
+store(siz, addr, p)
+	register char *addr;
+	register pcnt siz;
+{
+	/*	Make sure, that a value with a size that could have been
+		handled by the LOI instruction is handled as if it was
+		loaded with the LOI instruction.
+	*/
+	register char *q = (char *) &p;
+	char t[4];
+
+	if (siz < EM_WSIZE && EM_WSIZE % siz == 0) {
+		/* as long as EM_WSIZE <= 4 ... */
+		if (siz != 2) TRP(M2_INTERNAL);	/* internal error */
+		*((unsigned short *) (&t[0])) = *((unsigned *) q);
+		q = &t[0];
+	}
+	while (siz--) *addr++ = *q++;
+}
Index: /trunk/minix/lib/ack/libm2/ucheck.c
===================================================================
--- /trunk/minix/lib/ack/libm2/ucheck.c	(revision 9)
+++ /trunk/minix/lib/ack/libm2/ucheck.c	(revision 9)
@@ -0,0 +1,65 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ *
+ * Module:	CARDINAL operations with overflow checking
+ * Author:	Ceriel J.H. Jacobs
+ * Version:	$Header: /cvsup/minix/src/lib/ack/libm2/ucheck.c,v 1.1 2005/10/10 15:27:46 beng Exp $
+*/
+
+#ifndef EM_WSIZE
+#define EM_WSIZE _EM_WSIZE
+#endif
+#ifndef EM_LSIZE
+#define EM_LSIZE _EM_LSIZE
+#endif
+
+#include <m2_traps.h>
+
+#define MAXCARD	((unsigned)-1)
+#if EM_WSIZE < EM_LSIZE
+#define MAXLONGCARD	((unsigned long) -1L)
+#endif
+
+adduchk(a,b)
+  unsigned	a,b;
+{
+  if (MAXCARD - a < b) TRP(M2_UOVFL);
+}
+
+#if EM_WSIZE < EM_LSIZE
+addulchk(a,b)
+  unsigned long	a,b;
+{
+  if (MAXLONGCARD - a < b) TRP(M2_UOVFL);
+}
+#endif
+
+muluchk(a,b)
+  unsigned	a,b;
+{
+  if (a != 0 && MAXCARD/a < b) TRP(M2_UOVFL);
+}
+
+#if EM_WSIZE < EM_LSIZE
+mululchk(a,b)
+  unsigned long	a,b;
+{
+  if (a != 0 && MAXLONGCARD/a < b) TRP(M2_UOVFL);
+}
+#endif
+
+subuchk(a,b)
+  unsigned	a,b;
+{
+  if (b < a) TRP(M2_UUVFL);
+}
+
+#if EM_WSIZE < EM_LSIZE
+subulchk(a,b)
+  unsigned long	a,b;
+{
+  if (b < a) TRP(M2_UUVFL);
+}
+#endif
Index: /trunk/minix/lib/ack/libp/Makedepend-ack
===================================================================
--- /trunk/minix/lib/ack/libp/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/ack/libp/Makedepend-ack	(revision 9)
@@ -0,0 +1,76 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -I../h -wo -E' abi.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' abl.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' abr.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' arg.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' ass.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' asz.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' atn.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' bcp.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' bts.e | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' buff.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' catch.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' clock.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' cls.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' cvt.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' diag.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' dis.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' efl.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' eln.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' encaps.e | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' exp.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' fef.e | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' fif.e | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' get.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' gto.e | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' head_pc.e | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' hlt.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' hol0.e | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' incpt.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' ini.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' log.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' mdi.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' mdl.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' new.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' nfa.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' nobuff.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' notext.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' opn.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' outcpt.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' pac.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' pclose.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' pcreat.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' pentry.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' perrno.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' pexit.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' popen.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' put.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' rcka.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' rdc.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' rdi.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' rdl.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' rdr.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' rf.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' rln.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' rnd.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' sav.e | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' sig.e | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' sin.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' sqt.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' string.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' trap.e | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' trp.e | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' unp.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' uread.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' uwrite.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' wdw.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' wf.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' wrc.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' wrf.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' wri.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' wrl.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' wrr.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' wrs.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
+	mkdep 'cc -O -I../h -wo -E' wrz.c | sed -e 's:^\(.\):../../obj-ack//./ack/libp/\1:' >> .depend-ack
Index: /trunk/minix/lib/ack/libp/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/ack/libp/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/ack/libp/Makedepend-gnu	(revision 9)
@@ -0,0 +1,3 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
Index: /trunk/minix/lib/ack/libp/Makefile
===================================================================
--- /trunk/minix/lib/ack/libp/Makefile	(revision 9)
+++ /trunk/minix/lib/ack/libp/Makefile	(revision 9)
@@ -0,0 +1,256 @@
+#Generated from ./ack/libp/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../generate.sh ./ack/libp ../../obj-ack/ ../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../generate.sh ./ack/libp ../../obj-ack/ ../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../../obj-ack//libp.a
+
+../../obj-ack//libp.a: ../../obj-ack//libp.a(abi.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(abl.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(abr.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(arg.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(ass.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(asz.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(atn.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(bcp.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(bts.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(buff.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(catch.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(clock.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(cls.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(cvt.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(diag.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(dis.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(efl.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(eln.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(encaps.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(exp.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(fef.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(fif.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(get.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(gto.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(head_pc.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(hlt.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(hol0.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(incpt.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(ini.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(log.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(mdi.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(mdl.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(new.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(nfa.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(nobuff.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(notext.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(opn.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(outcpt.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(pac.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(pclose.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(pcreat.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(pentry.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(perrno.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(pexit.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(popen.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(put.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(rcka.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(rdc.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(rdi.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(rdl.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(rdr.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(rf.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(rln.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(rnd.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(sav.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(sig.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(sin.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(sqt.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(string.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(trap.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(trp.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(unp.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(uread.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(uwrite.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(wdw.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(wf.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(wrc.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(wrf.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(wri.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(wrl.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(wrr.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(wrs.o)
+../../obj-ack//libp.a: ../../obj-ack//libp.a(wrz.o)
+
+../../obj-ack//libp.a:
+	ar cr ../../obj-ack//libp.a ../../obj-ack//./ack/libp/*.o
+	rm ../../obj-ack//./ack/libp/*.o
+
+../../obj-ack//libp.a(abi.o): abi.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/abi.o abi.c
+../../obj-ack//libp.a(abl.o): abl.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/abl.o abl.c
+../../obj-ack//libp.a(abr.o): abr.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/abr.o abr.c
+../../obj-ack//libp.a(arg.o): arg.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/arg.o arg.c
+../../obj-ack//libp.a(ass.o): ass.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/ass.o ass.c
+../../obj-ack//libp.a(asz.o): asz.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/asz.o asz.c
+../../obj-ack//libp.a(atn.o): atn.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/atn.o atn.c
+../../obj-ack//libp.a(bcp.o): bcp.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/bcp.o bcp.c
+../../obj-ack//libp.a(bts.o): bts.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/bts.o bts.e
+../../obj-ack//libp.a(buff.o): buff.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/buff.o buff.c
+../../obj-ack//libp.a(catch.o): catch.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/catch.o catch.c
+../../obj-ack//libp.a(clock.o): clock.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/clock.o clock.c
+../../obj-ack//libp.a(cls.o): cls.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/cls.o cls.c
+../../obj-ack//libp.a(cvt.o): cvt.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/cvt.o cvt.c
+../../obj-ack//libp.a(diag.o): diag.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/diag.o diag.c
+../../obj-ack//libp.a(dis.o): dis.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/dis.o dis.c
+../../obj-ack//libp.a(efl.o): efl.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/efl.o efl.c
+../../obj-ack//libp.a(eln.o): eln.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/eln.o eln.c
+../../obj-ack//libp.a(encaps.o): encaps.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/encaps.o encaps.e
+../../obj-ack//libp.a(exp.o): exp.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/exp.o exp.c
+../../obj-ack//libp.a(fef.o): fef.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/fef.o fef.e
+../../obj-ack//libp.a(fif.o): fif.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/fif.o fif.e
+../../obj-ack//libp.a(get.o): get.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/get.o get.c
+../../obj-ack//libp.a(gto.o): gto.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/gto.o gto.e
+../../obj-ack//libp.a(head_pc.o): head_pc.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/head_pc.o head_pc.e
+../../obj-ack//libp.a(hlt.o): hlt.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/hlt.o hlt.c
+../../obj-ack//libp.a(hol0.o): hol0.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/hol0.o hol0.e
+../../obj-ack//libp.a(incpt.o): incpt.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/incpt.o incpt.c
+../../obj-ack//libp.a(ini.o): ini.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/ini.o ini.c
+../../obj-ack//libp.a(log.o): log.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/log.o log.c
+../../obj-ack//libp.a(mdi.o): mdi.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/mdi.o mdi.c
+../../obj-ack//libp.a(mdl.o): mdl.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/mdl.o mdl.c
+../../obj-ack//libp.a(new.o): new.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/new.o new.c
+../../obj-ack//libp.a(nfa.o): nfa.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/nfa.o nfa.c
+../../obj-ack//libp.a(nobuff.o): nobuff.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/nobuff.o nobuff.c
+../../obj-ack//libp.a(notext.o): notext.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/notext.o notext.c
+../../obj-ack//libp.a(opn.o): opn.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/opn.o opn.c
+../../obj-ack//libp.a(outcpt.o): outcpt.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/outcpt.o outcpt.c
+../../obj-ack//libp.a(pac.o): pac.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/pac.o pac.c
+../../obj-ack//libp.a(pclose.o): pclose.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/pclose.o pclose.c
+../../obj-ack//libp.a(pcreat.o): pcreat.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/pcreat.o pcreat.c
+../../obj-ack//libp.a(pentry.o): pentry.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/pentry.o pentry.c
+../../obj-ack//libp.a(perrno.o): perrno.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/perrno.o perrno.c
+../../obj-ack//libp.a(pexit.o): pexit.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/pexit.o pexit.c
+../../obj-ack//libp.a(popen.o): popen.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/popen.o popen.c
+../../obj-ack//libp.a(put.o): put.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/put.o put.c
+../../obj-ack//libp.a(rcka.o): rcka.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/rcka.o rcka.c
+../../obj-ack//libp.a(rdc.o): rdc.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/rdc.o rdc.c
+../../obj-ack//libp.a(rdi.o): rdi.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/rdi.o rdi.c
+../../obj-ack//libp.a(rdl.o): rdl.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/rdl.o rdl.c
+../../obj-ack//libp.a(rdr.o): rdr.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/rdr.o rdr.c
+../../obj-ack//libp.a(rf.o): rf.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/rf.o rf.c
+../../obj-ack//libp.a(rln.o): rln.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/rln.o rln.c
+../../obj-ack//libp.a(rnd.o): rnd.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/rnd.o rnd.c
+../../obj-ack//libp.a(sav.o): sav.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/sav.o sav.e
+../../obj-ack//libp.a(sig.o): sig.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/sig.o sig.e
+../../obj-ack//libp.a(sin.o): sin.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/sin.o sin.c
+../../obj-ack//libp.a(sqt.o): sqt.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/sqt.o sqt.c
+../../obj-ack//libp.a(string.o): string.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/string.o string.c
+../../obj-ack//libp.a(trap.o): trap.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/trap.o trap.e
+../../obj-ack//libp.a(trp.o): trp.e
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/trp.o trp.e
+../../obj-ack//libp.a(unp.o): unp.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/unp.o unp.c
+../../obj-ack//libp.a(uread.o): uread.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/uread.o uread.c
+../../obj-ack//libp.a(uwrite.o): uwrite.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/uwrite.o uwrite.c
+../../obj-ack//libp.a(wdw.o): wdw.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/wdw.o wdw.c
+../../obj-ack//libp.a(wf.o): wf.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/wf.o wf.c
+../../obj-ack//libp.a(wrc.o): wrc.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/wrc.o wrc.c
+../../obj-ack//libp.a(wrf.o): wrf.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/wrf.o wrf.c
+../../obj-ack//libp.a(wri.o): wri.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/wri.o wri.c
+../../obj-ack//libp.a(wrl.o): wrl.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/wrl.o wrl.c
+../../obj-ack//libp.a(wrr.o): wrr.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/wrr.o wrr.c
+../../obj-ack//libp.a(wrs.o): wrs.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/wrs.o wrs.c
+../../obj-ack//libp.a(wrz.o): wrz.c
+	cc -O -I../h -wo -c -o ../../obj-ack//./ack/libp/wrz.o wrz.c
+
+
+
+clean::
+	rm -f ../../obj-ack//./ack/libp/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/ack/libp/Makefile.in
===================================================================
--- /trunk/minix/lib/ack/libp/Makefile.in	(revision 9)
+++ /trunk/minix/lib/ack/libp/Makefile.in	(revision 9)
@@ -0,0 +1,83 @@
+# Makefile for lib/ack/libp.
+
+CFLAGS="-O -I../h -wo"
+#CC1	= $(CC) $(CFLAGS) -c
+
+LIBRARIES=libp
+
+libp_FILES=" \
+	abi.c \
+	abl.c \
+	abr.c \
+	arg.c \
+	ass.c \
+	asz.c \
+	atn.c \
+	bcp.c \
+	bts.e \
+	buff.c \
+	catch.c \
+	clock.c \
+	cls.c \
+	cvt.c \
+	diag.c \
+	dis.c \
+	efl.c \
+	eln.c \
+	encaps.e \
+	exp.c \
+	fef.e \
+	fif.e \
+	get.c \
+	gto.e \
+	head_pc.e \
+	hlt.c \
+	hol0.e \
+	incpt.c \
+	ini.c \
+	log.c \
+	mdi.c \
+	mdl.c \
+	new.c \
+	nfa.c \
+	nobuff.c \
+	notext.c \
+	opn.c \
+	outcpt.c \
+	pac.c \
+	pclose.c \
+	pcreat.c \
+	pentry.c \
+	perrno.c \
+	pexit.c \
+	popen.c \
+	put.c \
+	rcka.c \
+	rdc.c \
+	rdi.c \
+	rdl.c \
+	rdr.c \
+	rf.c \
+	rln.c \
+	rnd.c \
+	sav.e \
+	sig.e \
+	sin.c \
+	sqt.c \
+	string.c \
+	trap.e \
+	trp.e \
+	unp.c \
+	uread.c \
+	uwrite.c \
+	wdw.c \
+	wf.c \
+	wrc.c \
+	wrf.c \
+	wri.c \
+	wrl.c \
+	wrr.c \
+	wrs.c \
+	wrz.c"
+
+TYPE=ack
Index: /trunk/minix/lib/ack/libp/abi.c
===================================================================
--- /trunk/minix/lib/ack/libp/abi.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/abi.c	(revision 9)
@@ -0,0 +1,23 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/abi.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+int _abi(i) int i; {
+	return(i>=0 ? i : -i);
+}
Index: /trunk/minix/lib/ack/libp/abl.c
===================================================================
--- /trunk/minix/lib/ack/libp/abl.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/abl.c	(revision 9)
@@ -0,0 +1,23 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/abl.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+long _abl(i) long i; {
+	return(i>=0 ? i : -i);
+}
Index: /trunk/minix/lib/ack/libp/abr.c
===================================================================
--- /trunk/minix/lib/ack/libp/abr.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/abr.c	(revision 9)
@@ -0,0 +1,23 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/abr.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+double _abr(r) double r; {
+	return(r>=0 ? r : -r);
+}
Index: /trunk/minix/lib/ack/libp/arg.c
===================================================================
--- /trunk/minix/lib/ack/libp/arg.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/arg.c	(revision 9)
@@ -0,0 +1,56 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/arg.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+/* function argc:integer; extern; */
+/* function argv(i:integer):string; extern; */
+/* procedure argshift; extern; */
+/* function environ(i:integer):string; extern; */
+
+extern int	_pargc;
+extern char	**_pargv;
+extern char	***_penviron;
+
+int argc() {
+	return(_pargc);
+}
+
+char *argv(i) {
+	if (i >= _pargc)
+		return(0);
+	return(_pargv[i]);
+}
+
+argshift() {
+
+	if (_pargc > 1) {
+		--_pargc;
+		_pargv++;
+	}
+}
+
+char *environ(i) {
+	char **p; char *q;
+
+	if (p = *_penviron)
+		while (q = *p++)
+			if (i-- < 0)
+				return(q);
+	return(0);
+}
Index: /trunk/minix/lib/ack/libp/ass.c
===================================================================
--- /trunk/minix/lib/ack/libp/ass.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/ass.c	(revision 9)
@@ -0,0 +1,33 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/ass.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<em_abs.h>
+#include	<pc_err.h>
+
+extern char	*_hol0();
+extern		_trp();
+
+_ass(line,bool) int line,bool; {
+
+	if (bool==0) {
+		LINO = line;
+		_trp(EASS);
+	}
+}
Index: /trunk/minix/lib/ack/libp/asz.c
===================================================================
--- /trunk/minix/lib/ack/libp/asz.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/asz.c	(revision 9)
@@ -0,0 +1,29 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/asz.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+struct descr {
+	int	low;
+	int	diff;
+	int	size;
+};
+
+int _asz(dp) struct descr *dp; {
+	return(dp->size * (dp->diff + 1));
+}
Index: /trunk/minix/lib/ack/libp/atn.c
===================================================================
--- /trunk/minix/lib/ack/libp/atn.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/atn.c	(revision 9)
@@ -0,0 +1,72 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+
+/* $Header: /cvsup/minix/src/lib/ack/libp/atn.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+
+#define __NO_DEFS
+#include <math.h>
+
+#if __STDC__
+#include <pc_math.h>
+#endif
+
+double
+_atn(x)
+	double x;
+{
+	/*	Algorithm and coefficients from:
+			"Software manual for the elementary functions"
+			by W.J. Cody and W. Waite, Prentice-Hall, 1980
+	*/
+
+	static double p[] = {
+		-0.13688768894191926929e+2,
+		-0.20505855195861651981e+2,
+		-0.84946240351320683534e+1,
+		-0.83758299368150059274e+0
+	};
+	static double q[] = {
+		 0.41066306682575781263e+2,
+		 0.86157349597130242515e+2,
+		 0.59578436142597344465e+2,
+		 0.15024001160028576121e+2,
+		 1.0
+	};
+	static double a[] = {
+		0.0,
+		0.52359877559829887307710723554658381,	/* pi/6 */
+		M_PI_2,
+		1.04719755119659774615421446109316763	/* pi/3 */
+	};
+
+	int	neg = x < 0;
+	int	n;
+	double	g;
+
+	if (neg) {
+		x = -x;
+	}
+	if (x > 1.0) {
+		x = 1.0/x;
+		n = 2;
+	}
+	else	n = 0;
+
+	if (x > 0.26794919243112270647) {	/* 2-sqtr(3) */
+		n = n + 1;
+		x = (((0.73205080756887729353*x-0.5)-0.5)+x)/
+			(1.73205080756887729353+x);
+	}
+
+	/* ??? avoid underflow ??? */
+
+	g = x * x;
+	x += x * g * POLYNOM3(g, p) / POLYNOM4(g, q);
+	if (n > 1) x = -x;
+	x += a[n];
+	return neg ? -x : x;
+}
Index: /trunk/minix/lib/ack/libp/bcp.c
===================================================================
--- /trunk/minix/lib/ack/libp/bcp.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/bcp.c	(revision 9)
@@ -0,0 +1,30 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/bcp.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+int _bcp(sz,y,x) int sz; unsigned char *y,*x; {
+
+	while (--sz >= 0) {
+		if (*x < *y)
+			return(-1);
+		if (*x++ > *y++)
+			return(1);
+	}
+	return(0);
+}
Index: /trunk/minix/lib/ack/libp/bts.e
===================================================================
--- /trunk/minix/lib/ack/libp/bts.e	(revision 9)
+++ /trunk/minix/lib/ack/libp/bts.e	(revision 9)
@@ -0,0 +1,56 @@
+#
+; $Header: /cvsup/minix/src/lib/ack/libp/bts.e,v 1.1 2005/10/10 15:27:46 beng Exp $
+;
+; (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+;
+;          This product is part of the Amsterdam Compiler Kit.
+;
+; Permission to use, sell, duplicate or disclose this software must be
+; obtained in writing. Requests for such permissions may be sent to
+;
+;      Dr. Andrew S. Tanenbaum
+;      Wiskundig Seminarium
+;      Vrije Universiteit
+;      Postbox 7161
+;      1007 MC Amsterdam
+;      The Netherlands
+;
+; 
+
+; Author: J.W. Stevenson */
+
+ mes 2,_EM_WSIZE,_EM_PSIZE
+
+#define	SIZE	0
+#define	HIGH	_EM_WSIZE
+#define	LOWB	2*_EM_WSIZE
+#define	BASE	3*_EM_WSIZE
+
+; _bts is called with four parameters:
+;	- the initial set (BASE)
+;	- low bound of range of bits (LOWB)
+;	- high bound of range of bits (HIGH)
+;	- set size in bytes (SIZE)
+
+ exp $_bts
+ pro $_bts,0
+ lal BASE	; address of initial set
+ lol SIZE
+ los _EM_WSIZE	; load initial set
+1
+ lol LOWB	; low bound
+ lol HIGH	; high bound
+ bgt *2		; while low <= high
+ lol LOWB
+ lol SIZE
+ set ?		; create [low]
+ lol SIZE
+ ior ?		; merge with initial set
+ inl LOWB	; increment low bound
+ bra *1		; loop back
+2
+ lal BASE
+ lol SIZE
+ sts _EM_WSIZE	; store result over initial set
+ ret 0
+ end ?
Index: /trunk/minix/lib/ack/libp/buff.c
===================================================================
--- /trunk/minix/lib/ack/libp/buff.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/buff.c	(revision 9)
@@ -0,0 +1,35 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/buff.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+
+extern		_flush();
+
+/* procedure buff(var f:file of ?); */
+
+buff(f) struct file *f; {
+	int sz;
+
+	if ((f->flags & (0377|WRBIT)) != (MAGIC|WRBIT))
+		return;
+	_flush(f);
+	sz = f->size;
+	f->count = f->buflen = (sz>PC_BUFLEN ? sz : PC_BUFLEN-PC_BUFLEN%sz);
+}
Index: /trunk/minix/lib/ack/libp/catch.c
===================================================================
--- /trunk/minix/lib/ack/libp/catch.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/catch.c	(revision 9)
@@ -0,0 +1,154 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/catch.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include	<em_abs.h>
+#include	<pc_err.h>
+#include	<pc_file.h>
+
+/* to make it easier to patch ... */
+extern struct file	*_curfil;
+
+static struct errm {
+	int errno;
+	char *errmes;
+} errors[] = {
+	{ EARRAY,	"array bound error"},
+	{ ERANGE,	"range bound error"},
+	{ ESET,		"set bound error"},
+	{ EIOVFL,	"integer overflow"},
+	{ EFOVFL,	"real overflow"},
+	{ EFUNFL,	"real underflow"},
+	{ EIDIVZ,	"divide by 0"},
+	{ EFDIVZ,	"divide by 0.0"},
+	{ EIUND,	"undefined integer"},
+	{ EFUND,	"undefined real"},
+	{ ECONV,	"conversion error"},
+
+	{ ESTACK,	"stack overflow"},
+	{ EHEAP,	"heap overflow"},
+	{ EILLINS,	"illegal instruction"},
+	{ EODDZ,	"illegal size argument"},
+	{ ECASE,	"case error"},
+	{ EMEMFLT,	"addressing non existent memory"},
+	{ EBADPTR,	"bad pointer used"},
+	{ EBADPC,	"program counter out of range"},
+	{ EBADLAE,	"bad argument of lae"},
+	{ EBADMON,	"bad monitor call"},
+	{ EBADLIN,	"argument if LIN too high"},
+	{ EBADGTO,	"GTO descriptor error"},
+
+	{ EARGC,	"more args expected" },
+	{ EEXP,		"error in exp" },
+	{ ELOG,		"error in ln" },
+	{ ESQT,		"error in sqrt" },
+	{ EASS,		"assertion failed" },
+	{ EPACK,	"array bound error in pack" },
+	{ EUNPACK,	"array bound error in unpack" },
+	{ EMOD,		"only positive j in 'i mod j'" },
+	{ EBADF,	"file not yet open" },
+	{ EFREE,	"dispose error" },
+	{ EFUNASS,	"function not assigned" },
+	{ EWIDTH,	"illegal field width" },
+
+	{ EWRITEF,	"not writable" },
+	{ EREADF,	"not readable" },
+	{ EEOF,		"end of file" },
+	{ EFTRUNC,	"truncated" },
+	{ ERESET,	"reset error" },
+	{ EREWR,	"rewrite error" },
+	{ ECLOSE,	"close error" },
+	{ EREAD,	"read error" },
+	{ EWRITE,	"write error" },
+	{ EDIGIT,	"digit expected" },
+	{ EASCII,	"non-ASCII char read" },
+	{ -1,		0}
+};
+
+extern int		_pargc;
+extern char		**_pargv;
+extern char		***_penviron;
+
+extern char		*_hol0();
+extern			_trp();
+extern			_exit();
+extern int		_write();
+
+_catch(erno) unsigned erno; {
+	register struct errm *ep = &errors[0];
+	char *p,*q,*s,**qq;
+	char buf[20];
+	unsigned i;
+	int j = erno;
+	char *pp[11];
+	char xbuf[100];
+
+	qq = pp;
+	if (p = FILN)
+		*qq++ = p;
+	else
+		*qq++ = _pargv[0];
+
+	while (ep->errno != erno && ep->errmes != 0) ep++;
+	p = buf;
+	s = xbuf;
+	if (i = LINO) {
+		*qq++ = ", ";
+		do
+			*p++ = i % 10 + '0';
+		while (i /= 10);
+		while (p > buf) *s++ = *--p;
+	}
+	*s++ = ':';
+	*s++ = ' ';
+	*s++ = '\0';
+	*qq++ = xbuf;
+	if ((erno & ~037) == 0140 && (_curfil->flags&0377)==MAGIC) { 
+		/* file error */
+		*qq++ = "file ";
+		*qq++ = _curfil->fname;
+		*qq++ = ": ";
+	}
+	if (ep->errmes) *qq++ = ep->errmes;
+	else {
+		*qq++ = "error number ";
+		*qq++ = s;
+		p = buf;
+		if (j < 0) {
+			j = -j;
+			*s++ = '-';
+		}
+		do
+			*p++ = j % 10 + '0';
+		while (j /= 10);
+		while (p > buf) *s++ = *--p;
+		*s = 0;
+	}
+	*qq++ = "\n";
+	*qq = 0;
+	qq = pp;
+	while (q = *qq++) {
+		p = q;
+		while (*p)
+			p++;
+		if (_write(2,q,(int)(p-q)) < 0)
+			;
+	}
+	_exit(erno);
+error:
+	_trp(erno);
+}
Index: /trunk/minix/lib/ack/libp/clock.c
===================================================================
--- /trunk/minix/lib/ack/libp/clock.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/clock.c	(revision 9)
@@ -0,0 +1,47 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/clock.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+/* function clock:integer; extern; */
+
+extern int	_times();
+
+struct tbuf {
+	long	utime;
+	long	stime;
+	long	cutime;
+	long	cstime;
+};
+
+#ifndef EM_WSIZE
+#define EM_WSIZE _EM_WSIZE
+#endif
+
+int clock() {
+	struct tbuf t;
+
+	_times(&t);
+	return( (int)(t.utime + t.stime) &
+#if EM_WSIZE <= 2
+	077777
+#else
+	0x7fffffffL
+#endif
+	);
+}
Index: /trunk/minix/lib/ack/libp/cls.c
===================================================================
--- /trunk/minix/lib/ack/libp/cls.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/cls.c	(revision 9)
@@ -0,0 +1,67 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/cls.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+#include	<pc_err.h>
+
+extern struct file	*_curfil;
+extern			_trp();
+extern			_flush();
+extern			_outcpt();
+extern int		_close();
+
+_xcls(f) struct file *f; {
+
+	if ((f->flags & WRBIT) == 0)
+		return;
+	if ((f->flags & (TXTBIT|ELNBIT)) == TXTBIT) {
+#ifdef CPM
+		*f->ptr = '\r';
+		_outcpt(f);
+#endif
+		*f->ptr = '\n';
+		_outcpt(f);
+	}
+	_flush(f);
+}
+
+_cls(f) struct file *f; {
+#ifdef MAYBE
+	char *p;
+#endif
+
+	_curfil = f;
+	if ((f->flags&0377) != MAGIC)
+		return;
+#ifdef MAYBE
+	p = f->bufadr;
+	if (f->ptr < p)
+		return;
+	if (f->buflen <= 0)
+		return;
+	p += f->buflen;
+	if (f->ptr >= p)
+		return;
+#endif
+	_xcls(f);
+	if (_close(f->ufd) != 0)
+		_trp(ECLOSE);
+	f->flags = 0;
+}
Index: /trunk/minix/lib/ack/libp/cvt.c
===================================================================
--- /trunk/minix/lib/ack/libp/cvt.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/cvt.c	(revision 9)
@@ -0,0 +1,119 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/cvt.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+#ifndef NOFLOAT
+
+#if __STDC__
+#include <float.h>
+#else
+#include <math.h>
+#define DBL_MAX	M_MAX_D
+#endif
+
+static char *cvt();
+#define NDIGITS	128
+
+char *
+_ecvt(value, ndigit, decpt, sign)
+	double value;
+	int ndigit, *decpt, *sign;
+{
+	return cvt(value, ndigit, decpt, sign, 1);
+}
+
+char *
+_fcvt(value, ndigit, decpt, sign)
+	double value;
+	int ndigit, *decpt, *sign;
+{
+	return cvt(value, ndigit, decpt, sign, 0);
+}
+
+static struct powers_of_10 {
+	double pval;
+	double rpval;
+	int exp;
+} p10[] = {
+	1.0e32, 1.0e-32, 32,
+	1.0e16, 1.0e-16, 16,
+	1.0e8, 1.0e-8, 8,
+	1.0e4, 1.0e-4, 4,
+	1.0e2, 1.0e-2, 2,
+	1.0e1, 1.0e-1, 1,
+	1.0e0, 1.0e0, 0
+};
+
+static char *
+cvt(value, ndigit, decpt, sign, ecvtflag)
+	double value;
+	int ndigit, *decpt, *sign;
+{
+	static char buf[NDIGITS+1];
+	register char *p = buf;
+	register char *pe;
+
+	if (ndigit < 0) ndigit = 0;
+	if (ndigit > NDIGITS) ndigit = NDIGITS;
+	pe = &buf[ndigit];
+	buf[0] = '\0';
+
+	*sign = 0;
+	if (value < 0) {
+		*sign = 1;
+		value = -value;
+	}
+
+	*decpt = 0;
+	if (value >= DBL_MAX) {
+		value = DBL_MAX;
+	}
+	if (value != 0.0) {
+		register struct powers_of_10 *pp = &p10[0];
+
+		if (value >= 10.0) do {
+			while (value >= pp->pval) {
+				value *= pp->rpval;
+				*decpt += pp->exp;
+			}
+		} while ((++pp)->exp > 0);
+
+		pp = &p10[0];
+		if (value < 1.0) do {
+			while (value * pp->pval < 10.0) {
+				value *= pp->pval;
+				*decpt -= pp->exp;
+			}
+		} while ((++pp)->exp > 0);
+
+		(*decpt)++;	/* because now value in [1.0, 10.0) */
+	}
+	if (! ecvtflag) {
+		/* for fcvt() we need ndigit digits behind the dot */
+		pe += *decpt;
+		if (pe > &buf[NDIGITS]) pe = &buf[NDIGITS];
+	}
+	while (p <= pe) {
+		*p++ = (int)value + '0';
+		value = 10.0 * (value - (int)value);
+	}
+	if (pe >= buf) {
+		p = pe;
+		*p += 5;	/* round of at the end */
+		while (*p > '9') {
+			*p = '0';
+			if (p > buf) ++*--p;
+			else {
+				*p = '1';
+				++*decpt;
+				if (! ecvtflag) {
+					/* maybe add another digit at the end,
+					   because the point was shifted right
+					*/
+					if (pe > buf) *pe = '0';
+					pe++;
+				}
+			}
+		}
+		*pe = '\0';
+	}
+	return buf;
+}
+#endif
Index: /trunk/minix/lib/ack/libp/diag.c
===================================================================
--- /trunk/minix/lib/ack/libp/diag.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/diag.c	(revision 9)
@@ -0,0 +1,34 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/diag.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+
+/* procedure diag(var f:text); */
+
+diag(f) struct file *f; {
+
+	f->ptr = f->bufadr;
+	f->flags = WRBIT|EOFBIT|ELNBIT|TXTBIT|MAGIC;
+	f->fname = "DIAG";
+	f->ufd = 2;
+	f->size = 1;
+	f->count = 1;
+	f->buflen = 1;
+}
Index: /trunk/minix/lib/ack/libp/dis.c
===================================================================
--- /trunk/minix/lib/ack/libp/dis.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/dis.c	(revision 9)
@@ -0,0 +1,87 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/dis.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_err.h>
+
+#define assert()	/* nothing */
+
+/*
+ * use circular list of free blocks from low to high addresses
+ * _highp points to free block with highest address
+ */
+struct adm {
+	struct adm	*next;
+	int		size;
+};
+
+extern struct adm	*_lastp;
+extern struct adm	*_highp;
+extern			_trp();
+
+static int merge(p1,p2) struct adm *p1,*p2; {
+	struct adm *p;
+
+	p = (struct adm *)((char *)p1 + p1->size);
+	if (p > p2)
+		_trp(EFREE);
+	if (p != p2)
+		return(0);
+	p1->size += p2->size;
+	p1->next = p2->next;
+	return(1);
+}
+
+_dis(n,pp) int n; struct adm **pp; {
+	struct adm *p1,*p2;
+
+	/*
+	 * NOTE: dispose only objects whose size is a multiple of sizeof(*pp).
+	 *       this is always true for objects allocated by _new()
+	 */
+	n = ((n+sizeof(*p1)-1) / sizeof(*p1)) * sizeof(*p1);
+	if (n == 0)
+		return;
+	if ((p1= *pp) == (struct adm *) 0)
+		_trp(EFREE);
+	p1->size = n;
+	if ((p2 = _highp) == 0)  /*p1 is the only free block*/
+		p1->next = p1;
+	else {
+		if (p2 > p1) {
+			/*search for the preceding free block*/
+			if (_lastp < p1)  /*reduce search*/
+				p2 = _lastp;
+			while (p2->next < p1)
+				p2 = p2->next;
+		}
+		/* if p2 preceeds p1 in the circular list,
+		 * try to merge them			*/
+		p1->next = p2->next; p2->next = p1;
+		if (p2 <= p1 && merge(p2,p1))
+			p1 = p2;
+		p2 = p1->next;
+		/* p1 preceeds p2 in the circular list */
+		if (p2 > p1) merge(p1,p2);
+	}
+	if (p1 >= p1->next)
+		_highp = p1;
+	_lastp = p1;
+	*pp = (struct adm *) 0;
+}
Index: /trunk/minix/lib/ack/libp/efl.c
===================================================================
--- /trunk/minix/lib/ack/libp/efl.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/efl.c	(revision 9)
@@ -0,0 +1,36 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/efl.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+#include	<pc_err.h>
+
+extern struct file	*_curfil;
+extern			_trp();
+extern			_incpt();
+
+int _efl(f) struct file *f; {
+
+	_curfil = f;
+	if ((f->flags & 0377) != MAGIC)
+		_trp(EBADF);
+	if ((f->flags & (WINDOW|WRBIT|EOFBIT)) == 0)
+		_incpt(f);
+	return((f->flags & EOFBIT) != 0);
+}
Index: /trunk/minix/lib/ack/libp/eln.c
===================================================================
--- /trunk/minix/lib/ack/libp/eln.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/eln.c	(revision 9)
@@ -0,0 +1,33 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/eln.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+#include	<pc_err.h>
+
+extern		_trp();
+extern		_rf();
+
+int _eln(f) struct file *f; {
+
+	_rf(f);
+	if (f->flags & EOFBIT)
+		_trp(EEOF);
+	return((f->flags & ELNBIT) != 0);
+}
Index: /trunk/minix/lib/ack/libp/encaps.e
===================================================================
--- /trunk/minix/lib/ack/libp/encaps.e	(revision 9)
+++ /trunk/minix/lib/ack/libp/encaps.e	(revision 9)
@@ -0,0 +1,144 @@
+#
+
+
+; $Header: /cvsup/minix/src/lib/ack/libp/encaps.e,v 1.1 2005/10/10 15:27:46 beng Exp $
+;  (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+; 
+;           This product is part of the Amsterdam Compiler Kit.
+; 
+;  Permission to use, sell, duplicate or disclose this software must be
+;  obtained in writing. Requests for such permissions may be sent to
+; 
+;       Dr. Andrew S. Tanenbaum
+;       Wiskundig Seminarium
+;       Vrije Universiteit
+;       Postbox 7161
+;       1007 MC Amsterdam
+;       The Netherlands
+; 
+
+ mes 2,_EM_WSIZE,_EM_PSIZE
+
+; procedure encaps(procedure p; procedure(q(n:integer));
+; {call q if a trap occurs during the execution of p}
+; {if q returns, continue execution of p}
+
+
+ inp $handler
+
+#define PIISZ   2*_EM_PSIZE
+
+#define PARG    0
+#define QARG    PIISZ
+#define E_ELB   0-_EM_PSIZE
+#define E_EHA   -2*_EM_PSIZE
+
+; encaps is called with two parameters:
+;       - procedure instance identifier of q (QARG)
+;       - procedure instance identifier of p (PARG)
+; and two local variables:
+;       - the lb of the previous encaps      (E_ELB)
+;       - the procedure identifier of the previous handler (E_EHA)
+;
+; One static variable:
+;       - the lb of the currently active encaps (enc_lb)
+
+enc_lb
+        bss _EM_PSIZE,0,0
+
+ exp $encaps
+ pro $encaps,PIISZ
+ ; save lb of previous encaps
+ lae enc_lb
+ loi _EM_PSIZE
+ lal E_ELB
+ sti _EM_PSIZE
+ ; set new lb
+ lxl 0
+ lae enc_lb
+ sti _EM_PSIZE
+ ; save old handler id while setting up the new handler
+ lpi $handler
+ sig
+ lal E_EHA
+ sti _EM_PSIZE
+ ; handler is ready, p can be called
+ ; p doesn't expect parameters except possibly the static link
+ ; always passing the link won't hurt
+ lal PARG
+ loi PIISZ
+ cai
+ asp _EM_PSIZE
+ ; reinstate old handler
+ lal E_ELB
+ loi _EM_PSIZE
+ lae enc_lb
+ sti _EM_PSIZE
+ lal E_EHA
+ loi _EM_PSIZE
+ sig
+ asp _EM_PSIZE
+ ret 0
+ end ?
+
+#define TRAP    0
+#define H_ELB   0-_EM_PSIZE
+
+; handler is called with one parameter:
+;       - trap number (TRAP)
+; one local variable
+;       - the current LB of the enclosing encaps (H_ELB)
+
+
+ pro $handler,_EM_PSIZE
+ ; save LB of nearest encaps
+ lae enc_lb
+ loi _EM_PSIZE
+ lal H_ELB
+ sti _EM_PSIZE
+ ; fetch setting for previous encaps via LB of nearest
+ lal H_ELB
+ loi _EM_PSIZE
+ adp E_ELB
+ loi _EM_PSIZE   ; LB of previous encaps
+ lae enc_lb
+ sti _EM_PSIZE
+ lal H_ELB
+ loi _EM_PSIZE
+ adp E_EHA
+ loi _EM_PSIZE   ; previous handler
+ sig
+ asp _EM_PSIZE
+ ; previous handler is re-instated, time to call Q
+ lol TRAP       ; the one and only real parameter
+ lal H_ELB
+ loi _EM_PSIZE
+ lpb            ; argument base of enclosing encaps
+ adp QARG
+ loi PIISZ
+ exg _EM_PSIZE
+ dup _EM_PSIZE   ; The static link is now on top
+ zer _EM_PSIZE
+ cmp
+ zeq *1
+ ; non-zero LB
+ exg _EM_PSIZE
+ cai
+ asp _EM_WSIZE+_EM_PSIZE
+ bra *2
+1
+ ; zero LB
+ asp _EM_PSIZE
+ cai
+ asp _EM_WSIZE
+2
+ ; now reinstate handler for continued execution of p
+ lal H_ELB
+ loi _EM_PSIZE
+ lae enc_lb
+ sti _EM_PSIZE
+ lpi $handler
+ sig
+ asp _EM_PSIZE
+ rtt
+ end ?
Index: /trunk/minix/lib/ack/libp/exp.c
===================================================================
--- /trunk/minix/lib/ack/libp/exp.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/exp.c	(revision 9)
@@ -0,0 +1,118 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+
+/* $Header: /cvsup/minix/src/lib/ack/libp/exp.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+#define __NO_DEFS
+#include <math.h>
+#include <pc_err.h>
+extern	_trp();
+
+#if __STDC__
+#include <float.h>
+#include <pc_math.h>
+#define M_MIN_D	DBL_MIN
+#define M_MAX_D	DBL_MAX
+#define M_DMINEXP DBL_MIN_EXP
+#endif
+#undef HUGE
+#define HUGE	1e1000
+
+static double
+Ldexp(fl,exp)
+	double fl;
+	int exp;
+{
+	extern double _fef();
+	int sign = 1;
+	int currexp;
+
+	if (fl<0) {
+		fl = -fl;
+		sign = -1;
+	}
+	fl = _fef(fl,&currexp);
+	exp += currexp;
+	if (exp > 0) {
+		while (exp>30) {
+			fl *= (double) (1L << 30);
+			exp -= 30;
+		}
+		fl *= (double) (1L << exp);
+	}
+	else	{
+		while (exp<-30) {
+			fl /= (double) (1L << 30);
+			exp += 30;
+		}
+		fl /= (double) (1L << -exp);
+	}
+	return sign * fl;
+}
+
+double
+_exp(x)
+	double x;
+{
+	/*	Algorithm and coefficients from:
+			"Software manual for the elementary functions"
+			by W.J. Cody and W. Waite, Prentice-Hall, 1980
+	*/
+
+	static double p[] = {
+	        0.25000000000000000000e+0,
+	        0.75753180159422776666e-2,
+		0.31555192765684646356e-4
+	};
+
+	static double q[] = {
+	        0.50000000000000000000e+0,
+	        0.56817302698551221787e-1,
+	        0.63121894374398503557e-3,
+		0.75104028399870046114e-6
+	};
+	double	xn, g;
+	int	n;
+	int	negative = x < 0;
+
+	if (x <= M_LN_MIN_D) {
+		g = M_MIN_D/4.0;
+
+		if (g != 0.0) {
+			/* unnormalized numbers apparently exist */
+			if (x < (M_LN2 * (M_DMINEXP - 53))) return 0.0;
+		}
+		else {
+			if (x < M_LN_MIN_D) return 0.0;
+			return M_MIN_D;
+		}
+	}
+	if (x >= M_LN_MAX_D) {
+		if (x > M_LN_MAX_D) {
+			_trp(EEXP);
+			return HUGE;
+		}
+		return M_MAX_D;
+	}
+	if (negative) x = -x;
+
+	n = x * M_LOG2E + 0.5;	/* 1/ln(2) = log2(e), 0.5 added for rounding */
+	xn = n;
+	{
+		double	x1 = (long) x;
+		double	x2 = x - x1;
+
+		g = ((x1-xn*0.693359375)+x2) - xn*(-2.1219444005469058277e-4);
+	}
+	if (negative) {
+		g = -g;
+		n = -n;
+	}
+	xn = g * g;
+	x = g * POLYNOM2(xn, p);
+	n += 1;
+	return (Ldexp(0.5 + x/(POLYNOM3(xn, q) - x), n));
+}
Index: /trunk/minix/lib/ack/libp/fef.e
===================================================================
--- /trunk/minix/lib/ack/libp/fef.e	(revision 9)
+++ /trunk/minix/lib/ack/libp/fef.e	(revision 9)
@@ -0,0 +1,39 @@
+#
+; $Header: /cvsup/minix/src/lib/ack/libp/fef.e,v 1.1 2005/10/10 15:27:46 beng Exp $
+;
+; (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+;
+;          This product is part of the Amsterdam Compiler Kit.
+;
+; Permission to use, sell, duplicate or disclose this software must be
+; obtained in writing. Requests for such permissions may be sent to
+;
+;      Dr. Andrew S. Tanenbaum
+;      Wiskundig Seminarium
+;      Vrije Universiteit
+;      Postbox 7161
+;      1007 MC Amsterdam
+;      The Netherlands
+;
+;
+
+ mes 2,_EM_WSIZE,_EM_PSIZE
+
+#define FARG    0
+#define ERES    _EM_DSIZE
+
+; _fef is called with two parameters:
+;       - address of exponent result (ERES)
+;       - floating point number to be split (FARG)
+; and returns an _EM_DSIZE-byte floating point number
+
+ exp $_fef
+ pro $_fef,0
+ lal FARG
+ loi _EM_DSIZE
+ fef _EM_DSIZE
+ lal ERES
+ loi _EM_PSIZE
+ sti _EM_WSIZE
+ ret _EM_DSIZE
+ end ?
Index: /trunk/minix/lib/ack/libp/fif.e
===================================================================
--- /trunk/minix/lib/ack/libp/fif.e	(revision 9)
+++ /trunk/minix/lib/ack/libp/fif.e	(revision 9)
@@ -0,0 +1,41 @@
+#
+; $Header: /cvsup/minix/src/lib/ack/libp/fif.e,v 1.1 2005/10/10 15:27:46 beng Exp $
+;
+; (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+;
+;          This product is part of the Amsterdam Compiler Kit.
+;
+; Permission to use, sell, duplicate or disclose this software must be
+; obtained in writing. Requests for such permissions may be sent to
+;
+;      Dr. Andrew S. Tanenbaum
+;      Wiskundig Seminarium
+;      Vrije Universiteit
+;      Postbox 7161
+;      1007 MC Amsterdam
+;      The Netherlands
+;
+;
+
+ mes 2,_EM_WSIZE,_EM_PSIZE
+
+#define ARG1    0
+#define ARG2    _EM_DSIZE
+#define IRES    2*_EM_DSIZE
+
+; _fif is called with three parameters:
+;       - address of integer part result (IRES)
+;       - float two (ARG2)
+;       - float one (ARG1)
+; and returns an _EM_DSIZE-byte floating point number
+
+ exp $_fif
+ pro $_fif,0
+ lal 0
+ loi 2*_EM_DSIZE
+ fif _EM_DSIZE
+ lal IRES
+ loi _EM_PSIZE
+ sti _EM_DSIZE
+ ret _EM_DSIZE
+ end ?
Index: /trunk/minix/lib/ack/libp/get.c
===================================================================
--- /trunk/minix/lib/ack/libp/get.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/get.c	(revision 9)
@@ -0,0 +1,31 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/get.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include	<pc_file.h>
+#include	<pc_err.h>
+
+extern		_rf();
+extern		_trp();
+
+_get(f) struct file *f; {
+
+	_rf(f);
+	if (f->flags&EOFBIT)
+		_trp(EEOF);
+	f->flags &= ~WINDOW;
+}
Index: /trunk/minix/lib/ack/libp/gto.e
===================================================================
--- /trunk/minix/lib/ack/libp/gto.e	(revision 9)
+++ /trunk/minix/lib/ack/libp/gto.e	(revision 9)
@@ -0,0 +1,85 @@
+#
+; $Header: /cvsup/minix/src/lib/ack/libp/gto.e,v 1.1 2005/10/10 15:27:46 beng Exp $
+;  (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+; 
+;           This product is part of the Amsterdam Compiler Kit.
+; 
+;  Permission to use, sell, duplicate or disclose this software must be
+;  obtained in writing. Requests for such permissions may be sent to
+; 
+;       Dr. Andrew S. Tanenbaum
+;       Wiskundig Seminarium
+;       Vrije Universiteit
+;       Postbox 7161
+;       1007 MC Amsterdam
+;       The Netherlands
+; 
+
+/* Author: J.W. Stevenson */
+
+
+ mes 2,_EM_WSIZE,_EM_PSIZE
+
+#define TARLB   0
+#define DESCR   _EM_PSIZE
+
+#define NEWPC   0
+#define SAVSP   _EM_PSIZE
+
+#define D_PC    0
+#define D_SP    _EM_PSIZE
+#define D_LB    _EM_PSIZE+_EM_PSIZE
+
+#define LOCLB   0-_EM_PSIZE
+
+; _gto is called with two arguments:
+;       - pointer to the label descriptor (DESCR)
+;       - local base (LB) of target procedure (TARLB)
+; the label descriptor contains two items:
+;       - label address i.e. new PC (NEWPC)
+;       - offset in target procedure frame (SAVSP)
+; using this offset and the LB of the target procedure, the address of
+; of local variable of the target procedure is constructed.
+; the target procedure must have stored the correct target SP there.
+
+descr
+ bss 3*_EM_PSIZE,0,0
+
+ exp $_gto
+ pro $_gto,_EM_PSIZE
+ lal DESCR
+ loi _EM_PSIZE
+ adp NEWPC
+ loi _EM_PSIZE
+ lae descr+D_PC
+ sti _EM_PSIZE
+ lal TARLB
+ loi _EM_PSIZE
+ zer _EM_PSIZE
+ cmp
+ zeq *1
+ lal TARLB
+ loi _EM_PSIZE
+ bra *2
+1
+ lae _m_lb
+ loi _EM_PSIZE
+2
+ lal LOCLB
+ sti _EM_PSIZE
+ lal LOCLB
+ loi _EM_PSIZE
+ lal DESCR
+ loi _EM_PSIZE
+ adp SAVSP
+ loi _EM_WSIZE           ; or _EM_PSIZE ?
+ ads _EM_WSIZE           ; or _EM_PSIZE ?
+ loi _EM_PSIZE
+ lae descr+D_SP
+ sti _EM_PSIZE
+ lal LOCLB
+ loi _EM_PSIZE
+ lae descr+D_LB
+ sti _EM_PSIZE
+ gto descr
+ end ?
Index: /trunk/minix/lib/ack/libp/head_pc.e
===================================================================
--- /trunk/minix/lib/ack/libp/head_pc.e	(revision 9)
+++ /trunk/minix/lib/ack/libp/head_pc.e	(revision 9)
@@ -0,0 +1,3 @@
+#
+; $Header: /cvsup/minix/src/lib/ack/libp/head_pc.e,v 1.1 2005/10/10 15:27:46 beng Exp $
+ mes 2,_EM_WSIZE,_EM_PSIZE
Index: /trunk/minix/lib/ack/libp/hlt.c
===================================================================
--- /trunk/minix/lib/ack/libp/hlt.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/hlt.c	(revision 9)
@@ -0,0 +1,35 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/hlt.c,v 1.1 2005/10/10 15:27:46 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+
+extern struct file	**_extfl;
+extern int		_extflc;
+extern			_cls();
+extern			_exit();
+
+_hlt(ecode) int ecode; {
+	int i;
+
+	for (i = 0; i < _extflc; i++)
+		if (_extfl[i] != (struct file *) 0)
+			_cls(_extfl[i]);
+	_exit(ecode);
+}
Index: /trunk/minix/lib/ack/libp/hol0.e
===================================================================
--- /trunk/minix/lib/ack/libp/hol0.e	(revision 9)
+++ /trunk/minix/lib/ack/libp/hol0.e	(revision 9)
@@ -0,0 +1,29 @@
+#
+
+; $Header: /cvsup/minix/src/lib/ack/libp/hol0.e,v 1.1 2005/10/10 15:27:46 beng Exp $
+;
+; (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+;
+;          This product is part of the Amsterdam Compiler Kit.
+;
+; Permission to use, sell, duplicate or disclose this software must be
+; obtained in writing. Requests for such permissions may be sent to
+;
+;      Dr. Andrew S. Tanenbaum
+;      Wiskundig Seminarium
+;      Vrije Universiteit
+;      Postbox 7161
+;      1007 MC Amsterdam
+;      The Netherlands
+;
+;
+
+ mes 2,_EM_WSIZE,_EM_PSIZE
+
+; _hol0 return the address of the ABS block (hol0)
+
+ exp $_hol0
+ pro $_hol0,0
+ lae 0
+ ret _EM_PSIZE
+ end ?
Index: /trunk/minix/lib/ack/libp/incpt.c
===================================================================
--- /trunk/minix/lib/ack/libp/incpt.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/incpt.c	(revision 9)
@@ -0,0 +1,75 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/incpt.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+#include	<pc_err.h>
+
+#define EINTR	4
+
+extern int	errno;
+extern		_trp();
+extern int	_read();
+
+_incpt(f) struct file *f; {
+
+	if (f->flags & EOFBIT)
+		_trp(EEOF);
+	f->flags |= WINDOW;
+	f->flags &= ~ELNBIT;
+#ifdef CPM
+	do {
+#endif
+	f->ptr += f->size;
+	if (f->count == 0) {
+		f->ptr = f->bufadr;
+		for(;;) {
+			f->count=_read(f->ufd,f->bufadr,f->buflen);
+			if ( f->count<0 ) {
+				if (errno != EINTR) _trp(EREAD) ;
+				continue ;
+			}
+			break ;
+		}
+		if (f->count == 0) {
+			f->flags |= EOFBIT;
+			*f->ptr = '\0';
+			return;
+		}
+	}
+	if ((f->count -= f->size) < 0)
+		_trp(EFTRUNC);
+#ifdef CPM
+	} while ((f->flags&TXTBIT) && *f->ptr == '\r');
+#endif
+	if (f->flags & TXTBIT) {
+		if (*f->ptr & 0200)
+			_trp(EASCII);
+		if (*f->ptr == '\n') {
+			f->flags |= ELNBIT;
+			*f->ptr = ' ';
+		}
+#ifdef CPM
+		if (*f->ptr == 26) {
+			f->flags |= EOFBIT;
+			*f->ptr = 0;
+		}
+#endif
+	}
+}
Index: /trunk/minix/lib/ack/libp/ini.c
===================================================================
--- /trunk/minix/lib/ack/libp/ini.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/ini.c	(revision 9)
@@ -0,0 +1,72 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/ini.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include        <pc_file.h>
+#include        <pc_err.h>
+
+extern          (*_sig())();
+extern          _catch();
+#ifndef CPM
+extern int      _isatty();
+#endif
+
+struct file     **_extfl;
+int		_extflc;	/* number of external files */
+char            *_m_lb;         /* LB of _m_a_i_n */
+struct file     *_curfil;       /* points to file struct in case of errors */
+int             _pargc;
+char            **_pargv;
+char            ***_penviron;
+int		_fp_hook = 1;	/* This is for Minix, but does not harm others */
+
+_ini(args,c,p,mainlb) char *args,*mainlb; int c; struct file **p; {
+	struct file *f;
+	char buf[128];
+
+	_pargc= *(int *)args; args += sizeof (int);
+	_pargv= *(char ***)args;
+	_sig(_catch);
+	_extfl = p;
+	_extflc = c;
+	if( !c ) return;
+	_m_lb = mainlb;
+	if ( (f = _extfl[0]) != (struct file *) 0) {
+		f->ptr = f->bufadr;
+		f->flags = MAGIC|TXTBIT;
+		f->fname = "INPUT";
+		f->ufd = 0;
+		f->size = 1;
+		f->count = 0;
+		f->buflen = PC_BUFLEN;
+	}
+	if ( (f = _extfl[1]) != (struct file *) 0) {
+		f->ptr = f->bufadr;
+		f->flags = MAGIC|TXTBIT|WRBIT|EOFBIT|ELNBIT;
+		f->fname = "OUTPUT";
+		f->ufd = 1;
+		f->size = 1;
+#ifdef CPM
+		f->count = 1;
+#else
+		f->count = (_isatty(1) ? 1 : PC_BUFLEN);
+#endif
+		f->buflen = f->count;
+	}
+}
Index: /trunk/minix/lib/ack/libp/log.c
===================================================================
--- /trunk/minix/lib/ack/libp/log.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/log.c	(revision 9)
@@ -0,0 +1,65 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+
+/* $Header: /cvsup/minix/src/lib/ack/libp/log.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+
+#define __NO_DEFS
+#include <math.h>
+#include <pc_err.h>
+
+#if __STDC__
+#include <pc_math.h>
+#include <float.h>
+#endif
+#undef HUGE
+#define HUGE	1e1000
+
+double
+_log(x)
+	double	x;
+{
+	/*	Algorithm and coefficients from:
+			"Software manual for the elementary functions"
+			by W.J. Cody and W. Waite, Prentice-Hall, 1980
+	*/
+	static double a[] = {
+		-0.64124943423745581147e2,
+		 0.16383943563021534222e2,
+		-0.78956112887491257267e0
+	};
+	static double b[] = {
+		-0.76949932108494879777e3,
+		 0.31203222091924532844e3,
+		-0.35667977739034646171e2,
+		 1.0
+	};
+
+	extern double	_fef();
+	double	znum, zden, z, w;
+	int	exponent;
+
+	if (x <= 0) {
+		_trp(ELOG);
+		return -HUGE;
+	}
+
+	x = _fef(x, &exponent);
+	if (x > M_1_SQRT2) {
+		znum = (x - 0.5) - 0.5;
+		zden = x * 0.5 + 0.5;
+	}
+	else {
+		znum = x - 0.5;
+		zden = znum * 0.5 + 0.5;
+		exponent--;
+	}
+	z = znum/zden; w = z * z;
+	x = z + z * w * (POLYNOM2(w,a)/POLYNOM3(w,b));
+	z = exponent;
+	x += z * (-2.121944400546905827679e-4);
+	return x + z * 0.693359375;
+}
Index: /trunk/minix/lib/ack/libp/mdi.c
===================================================================
--- /trunk/minix/lib/ack/libp/mdi.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/mdi.c	(revision 9)
@@ -0,0 +1,71 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/mdi.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_err.h>
+
+extern		_trp();
+
+int _mdi(j,i) int j,i; {
+
+        if (j <= 0)
+                _trp(EMOD);
+        i = i % j;
+        if (i < 0)
+                i += j;
+        return(i);
+}
+
+long _mdil(j,i) long j,i; {
+
+	if (j <= 0)
+		_trp(EMOD);
+	i = i % j;
+	if (i < 0)
+		i += j;
+	return(i);
+}
+
+int _dvi(j, i) unsigned int j,i; {
+	int neg = 0;
+
+	if ((int)j < 0) {
+		j = -(int)j; neg = 1;
+	}
+	if ((int)i < 0) {
+		i = -(int)i; neg = !neg;
+	}
+	i = i / j;
+	if (neg) return -(int)i;
+	return i;
+}
+
+long _dvil(j, i) unsigned long j,i; {
+	int neg = 0;
+
+	if ((long)j < 0) {
+		j = -(long)j; neg = 1;
+	}
+	if ((long)i < 0) {
+		i = -(long)i; neg = !neg;
+	}
+	i = i / j;
+	if (neg) return -(long)i;
+	return i;
+}
Index: /trunk/minix/lib/ack/libp/mdl.c
===================================================================
--- /trunk/minix/lib/ack/libp/mdl.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/mdl.c	(revision 9)
@@ -0,0 +1,33 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/mdl.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_err.h>
+
+extern		_trp();
+
+long _mdl(j,i) long j,i; {
+
+	if (j <= 0)
+		_trp(EMOD);
+	i = i % j;
+	if (i < 0)
+		i += j;
+	return(i);
+}
Index: /trunk/minix/lib/ack/libp/new.c
===================================================================
--- /trunk/minix/lib/ack/libp/new.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/new.c	(revision 9)
@@ -0,0 +1,69 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/new.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+extern		_sav();
+extern		_rst();
+
+#define assert(x)	/* nothing */
+#define	UNDEF		0x8000
+
+struct adm {
+	struct adm	*next;
+	int		size;
+};
+
+struct adm	*_lastp = 0;
+struct adm	*_highp = 0;
+
+_new(n,pp) int n; struct adm **pp; {
+	struct adm *p,*q;
+	int *ptmp;
+
+	n = ((n+sizeof(*p)-1) / sizeof(*p)) * sizeof(*p);
+	if ((p = _lastp) != 0)
+		do {
+			q = p->next;
+			if (q->size >= n) {
+				assert(q->size%sizeof(adm) == 0);
+				if ((q->size -= n) == 0) {
+					if (p == q)
+						p = 0;
+					else
+						p->next = q->next;
+					if (q == _highp)
+						_highp = p;
+				}
+				_lastp = p;
+				p = (struct adm *)((char *)q + q->size);
+				q = (struct adm *)((char *)p + n);
+				goto initialize;
+			}
+			p = q;
+		} while (p != _lastp);
+	/*no free block big enough*/
+	_sav(&p);
+	q = (struct adm *)((char *)p + n);
+	_rst(&q);
+initialize:
+	*pp = p;
+	ptmp = (int *)p;
+	while (ptmp < (int *)q)
+		*ptmp++ = UNDEF;
+}
Index: /trunk/minix/lib/ack/libp/nfa.c
===================================================================
--- /trunk/minix/lib/ack/libp/nfa.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/nfa.c	(revision 9)
@@ -0,0 +1,16 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/nfa.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1990 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+
+/* Author: Hans van Eck */
+
+#include	<pc_err.h>
+
+extern _trp();
+
+_nfa(bool)
+{
+	if (! bool) _trp(EFUNASS);
+}
Index: /trunk/minix/lib/ack/libp/nobuff.c
===================================================================
--- /trunk/minix/lib/ack/libp/nobuff.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/nobuff.c	(revision 9)
@@ -0,0 +1,33 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/nobuff.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+
+extern		_flush();
+
+/* procedure nobuff(var f:file of ?); */
+
+nobuff(f) struct file *f; {
+
+	if ((f->flags & (0377|WRBIT)) != (MAGIC|WRBIT))
+		return;
+	_flush(f);
+	f->count = f->buflen = f->size;
+}
Index: /trunk/minix/lib/ack/libp/notext.c
===================================================================
--- /trunk/minix/lib/ack/libp/notext.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/notext.c	(revision 9)
@@ -0,0 +1,23 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/notext.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include	<pc_file.h>
+
+notext(f) struct file *f; {
+	f->flags &= ~TXTBIT;
+}
Index: /trunk/minix/lib/ack/libp/opn.c
===================================================================
--- /trunk/minix/lib/ack/libp/opn.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/opn.c	(revision 9)
@@ -0,0 +1,118 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/opn.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+#include	<pc_err.h>
+
+extern struct file	**_extfl;
+extern int		_extflc;
+extern struct file	*_curfil;
+extern int		_pargc;
+extern char		**_pargv;
+extern char		***_penviron;
+
+extern			_cls();
+extern			_xcls();
+extern			_trp();
+extern int		_getpid();
+extern int		_creat();
+extern int		_open();
+extern int		_close();
+extern int		_unlink();
+extern long		_lseek();
+
+static int tmpfil() {
+	static char namebuf[] = "/usr/tmp/plf.xxxxx";
+	int i; char *p,*q;
+
+	i = _getpid();
+	p = namebuf;
+	q = p + 13;
+	do
+		*q++ = (i & 07) + '0';
+	while (i >>= 3);
+	*q = '\0';
+	if ((i = _creat(p,0644)) < 0)
+		if ((i = _creat(p += 4,0644)) < 0)
+			if ((i = _creat(p += 5,0644)) < 0)
+				goto error;
+	if (_close(i) != 0)
+		goto error;
+	if ((i = _open(p,2)) < 0)
+		goto error;
+	if (_unlink(p) != 0)
+error:		_trp(EREWR);
+	return(i);
+}
+
+static int initfl(descr,sz,f) int descr; int sz; struct file *f; {
+	int i;
+
+	_curfil = f;
+	if (sz == 0) {
+		sz++;
+		descr |= TXTBIT;
+	}
+	for (i=0; i<_extflc; i++)
+		if (f == _extfl[i])
+			break;
+	if (i >= _extflc) {		/* local file */
+		f->fname = "LOCAL";
+		if ((descr & WRBIT) == 0 && (f->flags & 0377) == MAGIC) {
+			_xcls(f);
+			if (_lseek(f->ufd,(long)0,0) == -1)
+				_trp(ERESET);
+		} else {
+			_cls(f);
+			f->ufd = tmpfil();
+		}
+	} else {	/* external file */
+		if (--i <= 0)
+			return(0);
+		if (i >= _pargc)
+			_trp(EARGC);
+		f->fname = _pargv[i];
+		_cls(f);
+		if ((descr & WRBIT) == 0) {
+			if ((f->ufd = _open(f->fname,0)) < 0)
+				_trp(ERESET);
+		} else {
+			if ((f->ufd = _creat(f->fname,0644)) < 0)
+				_trp(EREWR);
+		}
+	}
+	f->buflen = (sz>PC_BUFLEN ? sz : PC_BUFLEN-PC_BUFLEN%sz);
+	f->size = sz;
+	f->ptr = f->bufadr;
+	f->flags = descr;
+	return(1);
+}
+
+_opn(sz,f) int sz; struct file *f; {
+
+	if (initfl(MAGIC,sz,f))
+		f->count = 0;
+}
+
+_cre(sz,f) int sz; struct file *f; {
+
+	if (initfl(WRBIT|EOFBIT|ELNBIT|MAGIC,sz,f))
+		f->count = f->buflen;
+}
Index: /trunk/minix/lib/ack/libp/outcpt.c
===================================================================
--- /trunk/minix/lib/ack/libp/outcpt.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/outcpt.c	(revision 9)
@@ -0,0 +1,50 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/outcpt.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+#include	<pc_err.h>
+
+#define EINTR	4
+
+extern int	errno;
+extern		_trp();
+extern int	_write();
+
+_flush(f) struct file *f; {
+	int i,n;
+
+	f->ptr = f->bufadr;
+	n = f->buflen - f->count;
+	if (n <= 0)
+		return;
+	f->count = f->buflen;
+	if ((i = _write(f->ufd,f->bufadr,n)) < 0 && errno == EINTR)
+		return;
+	if (i != n)
+		_trp(EWRITE);
+}
+
+_outcpt(f) struct file *f; {
+
+	f->flags &= ~ELNBIT;
+	f->ptr += f->size;
+	if ((f->count -= f->size) <= 0)
+		_flush(f);
+}
Index: /trunk/minix/lib/ack/libp/pac.c
===================================================================
--- /trunk/minix/lib/ack/libp/pac.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/pac.c	(revision 9)
@@ -0,0 +1,63 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/pac.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_err.h>
+
+extern		_trp();
+
+#define	assert(x)	/* nothing */
+
+#ifndef EM_WSIZE
+#define EM_WSIZE _EM_WSIZE
+#endif
+
+struct descr {
+	int	low;
+	int	diff;
+	int	size;
+};
+
+_pac(ad,zd,zp,i,ap) int i; struct descr *ad,*zd; char *zp,*ap; {
+
+	if (zd->diff > ad->diff ||
+			(i -= ad->low) < 0 ||
+			(i+zd->diff) > ad->diff)
+		_trp(EPACK);
+	ap += (i * ad->size);
+	i = (zd->diff + 1) * zd->size;
+	if (zd->size == 1) {
+		int *aptmp = (int *)ap;
+		assert(ad->size == EM_WSIZE);
+		while (--i >= 0)
+			*zp++ = *aptmp++;
+#if EM_WSIZE > 2
+	} else if (zd->size == 2) {
+		int *aptmp = (int *)ap;
+		short *zptmp = (short *) zp;
+		assert(ad->size == EM_WSIZE);
+		while (--i >= 0)
+			*zptmp++ = *aptmp++;
+#endif
+	} else {
+		assert(ad->size == zd->size);
+		while (--i >= 0)
+			*zp++ = *ap++;
+	}
+}
Index: /trunk/minix/lib/ack/libp/pclose.c
===================================================================
--- /trunk/minix/lib/ack/libp/pclose.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/pclose.c	(revision 9)
@@ -0,0 +1,27 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/pclose.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include	<pc_file.h>
+
+extern		_cls();
+
+/* procedure pclose(var f:file of ??); */
+
+pclose(f) struct file *f; {
+	_cls(f);
+}
Index: /trunk/minix/lib/ack/libp/pcreat.c
===================================================================
--- /trunk/minix/lib/ack/libp/pcreat.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/pcreat.c	(revision 9)
@@ -0,0 +1,41 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/pcreat.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+#include	<pc_err.h>
+
+extern		_cls();
+extern		_trp();
+extern int	_creat();
+
+/* procedure pcreat(var f:text; s:string); */
+
+pcreat(f,s) struct file *f; char *s; {
+
+	_cls(f);	/* initializes _curfil */
+	f->ptr = f->bufadr;
+	f->flags = WRBIT|EOFBIT|ELNBIT|TXTBIT|MAGIC;
+	f->fname = s;
+	f->size = 1;
+	f->count = PC_BUFLEN;
+	f->buflen = PC_BUFLEN;
+	if ((f->ufd = _creat(s,0644)) < 0)
+		_trp(EREWR);
+}
Index: /trunk/minix/lib/ack/libp/pentry.c
===================================================================
--- /trunk/minix/lib/ack/libp/pentry.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/pentry.c	(revision 9)
@@ -0,0 +1,35 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/pentry.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+
+extern struct file	**_extfl;
+extern			_wrs();
+extern			_wrz();
+extern			_wln();
+
+procentry(name) char *name; {
+	struct file *f;
+
+	f = _extfl[1];
+	_wrs(5,"call ",f);
+	_wrz(name,f);
+	_wln(f);
+}
Index: /trunk/minix/lib/ack/libp/perrno.c
===================================================================
--- /trunk/minix/lib/ack/libp/perrno.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/perrno.c	(revision 9)
@@ -0,0 +1,25 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/perrno.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* function perrno:integer; extern; */
+
+extern int	errno;
+
+int perrno() {
+	return(errno);
+}
Index: /trunk/minix/lib/ack/libp/pexit.c
===================================================================
--- /trunk/minix/lib/ack/libp/pexit.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/pexit.c	(revision 9)
@@ -0,0 +1,33 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/pexit.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include	<pc_file.h>
+
+extern struct file	**_extfl;
+extern			_wrs();
+extern			_wrz();
+extern			_wln();
+
+procexit(name) char *name; {
+	struct file *f;
+
+	f = _extfl[1];
+	_wrs(5,"exit ",f);
+	_wrz(name,f);
+	_wln(f);
+}
Index: /trunk/minix/lib/ack/libp/popen.c
===================================================================
--- /trunk/minix/lib/ack/libp/popen.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/popen.c	(revision 9)
@@ -0,0 +1,41 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/popen.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+#include	<pc_err.h>
+
+extern		_cls();
+extern		_trp();
+extern int	_open();
+
+/* procedure popen(var f:text; s:string); */
+
+popen(f,s) struct file *f; char *s; {
+
+	_cls(f);	/* initializes _curfil */
+	f->ptr = f->bufadr;
+	f->flags = TXTBIT|MAGIC;
+	f->fname = s;
+	f->size = 1;
+	f->count = 0;
+	f->buflen = PC_BUFLEN;
+	if ((f->ufd = _open(s,0)) < 0)
+		_trp(ERESET);
+}
Index: /trunk/minix/lib/ack/libp/put.c
===================================================================
--- /trunk/minix/lib/ack/libp/put.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/put.c	(revision 9)
@@ -0,0 +1,27 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/put.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include	<pc_file.h>
+
+extern		_wf();
+extern		_outcpt();
+
+_put(f) struct file *f; {
+	_wf(f);
+	_outcpt(f);
+}
Index: /trunk/minix/lib/ack/libp/rcka.c
===================================================================
--- /trunk/minix/lib/ack/libp/rcka.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/rcka.c	(revision 9)
@@ -0,0 +1,25 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/rcka.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1990 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+
+/* Author: Hans van Eck */
+
+#include	<em_abs.h>
+
+extern _trp();
+
+struct array_descr	{
+		int		lbound;
+		unsigned	n_elts_min_one;
+		unsigned	size;		/* doesn't really matter */
+	    };
+
+_rcka(descr, index)
+struct array_descr *descr;
+{
+	if( index < descr->lbound ||
+	    index > (int) descr->n_elts_min_one + descr->lbound )
+		_trp(EARRAY);
+}
Index: /trunk/minix/lib/ack/libp/rdc.c
===================================================================
--- /trunk/minix/lib/ack/libp/rdc.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/rdc.c	(revision 9)
@@ -0,0 +1,31 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/rdc.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include	<pc_file.h>
+
+extern		_rf();
+extern		_incpt();
+
+int _rdc(f) struct file *f; {
+	int c;
+
+	_rf(f);
+	c = *f->ptr;
+	_incpt(f);
+	return(c);
+}
Index: /trunk/minix/lib/ack/libp/rdi.c
===================================================================
--- /trunk/minix/lib/ack/libp/rdi.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/rdi.c	(revision 9)
@@ -0,0 +1,78 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/rdi.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+#include	<pc_err.h>
+
+extern		_trp();
+extern		_rf();
+extern		_incpt();
+
+_skipsp(f) struct file *f; {
+	while ((*f->ptr == ' ') || (*f->ptr == '\t'))
+		_incpt(f);
+}
+
+int _getsig(f) struct file *f; {
+	int sign;
+
+	if ((sign = (*f->ptr == '-')) || *f->ptr == '+')
+		_incpt(f);
+	return(sign);
+}
+
+int _fstdig(f) struct file *f; {
+	int ch;
+
+	ch = *f->ptr - '0';
+	if ((unsigned) ch > 9) {
+		_trp(EDIGIT);
+		ch = 0;
+	}
+	return(ch);
+}
+
+int _nxtdig(f) struct file *f; {
+	int ch;
+
+	_incpt(f);
+	ch = *f->ptr - '0';
+	if ((unsigned) ch > 9)
+		return(-1);
+	return(ch);
+}
+
+int _getint(f) struct file *f; {
+	int is_signed,i,ch;
+
+	is_signed = _getsig(f);
+	ch = _fstdig(f);
+	i = 0;
+	do
+		i = i*10 - ch;
+	while ((ch = _nxtdig(f)) >= 0);
+	return(is_signed ? i : -i);
+}
+
+int _rdi(f) struct file *f; {
+	_rf(f);
+	_skipsp(f);
+	return(_getint(f));
+}
Index: /trunk/minix/lib/ack/libp/rdl.c
===================================================================
--- /trunk/minix/lib/ack/libp/rdl.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/rdl.c	(revision 9)
@@ -0,0 +1,41 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/rdl.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+
+extern		_rf();
+extern		_skipsp();
+extern int	_getsig();
+extern int	_fstdig();
+extern int	_nxtdig();
+
+long _rdl(f) struct file *f; {
+	int is_signed,ch; long l;
+
+	_rf(f);
+	_skipsp(f);
+	is_signed = _getsig(f);
+	ch = _fstdig(f);
+	l = 0;
+	do
+		l = l*10 - ch;
+	while ((ch = _nxtdig(f)) >= 0);
+	return(is_signed ? l : -l);
+}
Index: /trunk/minix/lib/ack/libp/rdr.c
===================================================================
--- /trunk/minix/lib/ack/libp/rdr.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/rdr.c	(revision 9)
@@ -0,0 +1,78 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/rdr.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_file.h>
+
+#define	BIG	1e17
+
+extern		_rf();
+extern		_incpt();
+extern		_skipsp();
+extern int	_getsig();
+extern int	_getint();
+extern int	_fstdig();
+extern int	_nxtdig();
+
+static double		r;
+static int		pow10;
+
+static dig(ch) int ch; {
+
+	if (r>BIG)
+		pow10++;
+	else
+		r = r*10.0 + ch;
+}
+
+double _rdr(f) struct file *f; {
+	int i; double e; int is_signed,ch;
+
+	r = 0;
+	pow10 = 0;
+	_rf(f);
+	_skipsp(f);
+	is_signed = _getsig(f);
+	ch = _fstdig(f);
+	do
+		dig(ch);
+	while ((ch = _nxtdig(f)) >= 0);
+	if (*f->ptr == '.') {
+		_incpt(f);
+		ch = _fstdig(f);
+		do {
+			dig(ch);
+			pow10--;
+		} while ((ch = _nxtdig(f)) >= 0);
+	}
+	if ((*f->ptr == 'e') || (*f->ptr == 'E')) {
+		_incpt(f);
+		pow10 += _getint(f);
+	}
+	if ((i = pow10) < 0)
+		i = -i;
+	e = 1.0;
+	while (--i >= 0)
+		e *= 10.0;
+	if (pow10<0)
+		r /= e;
+	else
+		r *= e;
+	return(is_signed? -r : r);
+}
Index: /trunk/minix/lib/ack/libp/rf.c
===================================================================
--- /trunk/minix/lib/ack/libp/rf.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/rf.c	(revision 9)
@@ -0,0 +1,35 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/rf.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include	<pc_file.h>
+#include	<pc_err.h>
+
+extern struct file	*_curfil;
+extern			_trp();
+extern			_incpt();
+
+_rf(f) struct file *f; {
+
+	_curfil = f;
+	if ((f->flags&0377) != MAGIC)
+		_trp(EBADF);
+	if (f->flags & WRBIT)
+		_trp(EREADF);
+	if ((f->flags & WINDOW) == 0)
+		_incpt(f);
+}
Index: /trunk/minix/lib/ack/libp/rln.c
===================================================================
--- /trunk/minix/lib/ack/libp/rln.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/rln.c	(revision 9)
@@ -0,0 +1,30 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/rln.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include	<pc_file.h>
+
+extern		_rf();
+extern		_incpt();
+
+_rln(f) struct file *f; {
+
+	_rf(f);
+	while ((f->flags & ELNBIT) == 0)
+		_incpt(f);
+	f->flags &= ~WINDOW;
+}
Index: /trunk/minix/lib/ack/libp/rnd.c
===================================================================
--- /trunk/minix/lib/ack/libp/rnd.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/rnd.c	(revision 9)
@@ -0,0 +1,21 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/rnd.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+double _rnd(r) double r; {
+	return(r + (r<0 ? -0.5 : 0.5));
+}
Index: /trunk/minix/lib/ack/libp/sav.e
===================================================================
--- /trunk/minix/lib/ack/libp/sav.e	(revision 9)
+++ /trunk/minix/lib/ack/libp/sav.e	(revision 9)
@@ -0,0 +1,49 @@
+#
+; $Header: /cvsup/minix/src/lib/ack/libp/sav.e,v 1.1 2005/10/10 15:27:47 beng Exp $
+;  (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+; 
+;           This product is part of the Amsterdam Compiler Kit.
+; 
+;  Permission to use, sell, duplicate or disclose this software must be
+;  obtained in writing. Requests for such permissions may be sent to
+; 
+;       Dr. Andrew S. Tanenbaum
+;       Wiskundig Seminarium
+;       Vrije Universiteit
+;       Postbox 7161
+;       1007 MC Amsterdam
+;       The Netherlands
+; 
+
+/* Author: J.W. Stevenson */
+
+
+ mes 2,_EM_WSIZE,_EM_PSIZE
+
+#define	PTRAD	0
+
+#define	HP	2
+
+; _sav called with one parameter:
+;	- address of pointer variable (PTRAD)
+
+ exp $_sav
+ pro $_sav,0
+ lor HP
+ lal PTRAD
+ loi _EM_PSIZE
+ sti _EM_PSIZE
+ ret 0
+ end ?
+
+; _rst is called with one parameter:
+;	- address of pointer variable (PTRAD)
+
+ exp $_rst
+ pro $_rst,0
+ lal PTRAD
+ loi _EM_PSIZE
+ loi _EM_PSIZE
+ str HP
+ ret 0
+ end ?
Index: /trunk/minix/lib/ack/libp/sig.e
===================================================================
--- /trunk/minix/lib/ack/libp/sig.e	(revision 9)
+++ /trunk/minix/lib/ack/libp/sig.e	(revision 9)
@@ -0,0 +1,35 @@
+#define PROC    0
+
+; $Header: /cvsup/minix/src/lib/ack/libp/sig.e,v 1.1 2005/10/10 15:27:47 beng Exp $
+;
+; (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+;
+;          This product is part of the Amsterdam Compiler Kit.
+;
+; Permission to use, sell, duplicate or disclose this software must be
+; obtained in writing. Requests for such permissions may be sent to
+;
+;      Dr. Andrew S. Tanenbaum
+;      Wiskundig Seminarium
+;      Vrije Universiteit
+;      Postbox 7161
+;      1007 MC Amsterdam
+;      The Netherlands
+;
+;
+
+ mes 2,_EM_WSIZE,_EM_PSIZE
+
+; _sig is called with one parameter:
+;       - procedure instance identifier (PROC)
+; and returns nothing.
+; only the procedure identifier inside the PROC is used.
+
+ exp $_sig
+ pro $_sig,0
+ lal PROC
+ loi _EM_PSIZE
+ sig
+ asp _EM_PSIZE
+ ret 0                  ; ignore the result of sig
+ end ?
Index: /trunk/minix/lib/ack/libp/sin.c
===================================================================
--- /trunk/minix/lib/ack/libp/sin.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/sin.c	(revision 9)
@@ -0,0 +1,101 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+
+/* $Header: /cvsup/minix/src/lib/ack/libp/sin.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+
+#define __NO_DEFS
+#include <math.h>
+
+#if __STDC__
+#include <pc_math.h>
+#endif
+
+static double
+sinus(x, cos_flag)
+	double x;
+{
+	/*	Algorithm and coefficients from:
+			"Software manual for the elementary functions"
+			by W.J. Cody and W. Waite, Prentice-Hall, 1980
+	*/
+
+	static double r[] = {
+		-0.16666666666666665052e+0,
+		 0.83333333333331650314e-2,
+		-0.19841269841201840457e-3,
+		 0.27557319210152756119e-5,
+		-0.25052106798274584544e-7,
+		 0.16058936490371589114e-9,
+		-0.76429178068910467734e-12,
+		 0.27204790957888846175e-14
+	};
+
+	double	xsqr;
+	double	y;
+	int	neg = 0;
+
+	if (x < 0) {
+		x = -x;
+		neg = 1;
+	}
+	if (cos_flag) {
+		neg = 0;
+		y = M_PI_2 + x;
+	}
+	else	y = x;
+
+	/* ??? avoid loss of significance, if y is too large, error ??? */
+
+	y = y * M_1_PI + 0.5;
+
+	/*	Use extended precision to calculate reduced argument.
+		Here we used 12 bits of the mantissa for a1.
+		Also split x in integer part x1 and fraction part x2.
+	*/
+#define A1 3.1416015625
+#define A2 -8.908910206761537356617e-6
+	{
+		double x1, x2;
+		extern double	_fif();
+
+		_fif(y, 1.0,  &y);
+		if (_fif(y, 0.5, &x1)) neg = !neg;
+		if (cos_flag) y -= 0.5;
+		x2 = _fif(x, 1.0, &x1);
+		x = x1 - y * A1;
+		x += x2;
+		x -= y * A2;
+#undef A1
+#undef A2
+	}
+
+	if (x < 0) {
+		neg = !neg;
+		x = -x;
+	}
+
+	/* ??? avoid underflow ??? */
+
+	y = x * x;
+	x += x * y * POLYNOM7(y, r);
+	return neg ? -x : x;
+}
+
+double
+_sin(x)
+	double x;
+{
+	return sinus(x, 0);
+}
+
+double
+_cos(x)
+	double x;
+{
+	if (x < 0) x = -x;
+	return sinus(x, 1);
+}
Index: /trunk/minix/lib/ack/libp/sqt.c
===================================================================
--- /trunk/minix/lib/ack/libp/sqt.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/sqt.c	(revision 9)
@@ -0,0 +1,72 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+
+/* $Header: /cvsup/minix/src/lib/ack/libp/sqt.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+#define __NO_DEFS
+#include <math.h>
+#include <pc_err.h>
+extern	_trp();
+
+#define NITER	5
+
+static double
+Ldexp(fl,exp)
+	double fl;
+	int exp;
+{
+	extern double _fef();
+	int sign = 1;
+	int currexp;
+
+	if (fl<0) {
+		fl = -fl;
+		sign = -1;
+	}
+	fl = _fef(fl,&currexp);
+	exp += currexp;
+	if (exp > 0) {
+		while (exp>30) {
+			fl *= (double) (1L << 30);
+			exp -= 30;
+		}
+		fl *= (double) (1L << exp);
+	}
+	else	{
+		while (exp<-30) {
+			fl /= (double) (1L << 30);
+			exp += 30;
+		}
+		fl /= (double) (1L << -exp);
+	}
+	return sign * fl;
+}
+
+double
+_sqt(x)
+	double x;
+{
+	extern double _fef();
+	int exponent;
+	double val;
+
+	if (x <= 0) {
+		if (x < 0) _trp(ESQT);
+		return 0;
+	}
+
+	val = _fef(x, &exponent);
+	if (exponent & 1) {
+		exponent--;
+		val *= 2;
+	}
+	val = Ldexp(val + 1.0, exponent/2 - 1);
+	/* was: val = (val + 1.0)/2.0; val = Ldexp(val, exponent/2); */
+	for (exponent = NITER - 1; exponent >= 0; exponent--) {
+		val = (val + x / val) / 2.0;
+	}
+	return val;
+}
Index: /trunk/minix/lib/ack/libp/string.c
===================================================================
--- /trunk/minix/lib/ack/libp/string.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/string.c	(revision 9)
@@ -0,0 +1,60 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/string.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* function strbuf(var b:charbuf):string; */
+
+char *strbuf(s) char *s; {
+	return(s);
+}
+
+/* function strtobuf(s:string; var b:charbuf; blen:integer):integer; */
+
+int strtobuf(s,b,l) char *s,*b; {
+	int i;
+
+	i = 0;
+	while (--l>=0) {
+		if ((*b++ = *s++) == 0)
+			break;
+		i++;
+	}
+	return(i);
+}
+
+/* function strlen(s:string):integer; */
+
+int strlen(s) char *s; {
+	int i;
+
+	i = 0;
+	while (*s++)
+		i++;
+	return(i);
+}
+
+/* function strfetch(s:string; i:integer):char; */
+
+int strfetch(s,i) char *s; {
+	return(s[i-1]);
+}
+
+/* procedure strstore(s:string; i:integer; c:char); */
+
+strstore(s,i,c) char *s; {
+	s[i-1] = c;
+}
Index: /trunk/minix/lib/ack/libp/trap.e
===================================================================
--- /trunk/minix/lib/ack/libp/trap.e	(revision 9)
+++ /trunk/minix/lib/ack/libp/trap.e	(revision 9)
@@ -0,0 +1,33 @@
+#
+
+; $Header: /cvsup/minix/src/lib/ack/libp/trap.e,v 1.1 2005/10/10 15:27:47 beng Exp $
+;
+; (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+;
+;          This product is part of the Amsterdam Compiler Kit.
+;
+; Permission to use, sell, duplicate or disclose this software must be
+; obtained in writing. Requests for such permissions may be sent to
+;
+;      Dr. Andrew S. Tanenbaum
+;      Wiskundig Seminarium
+;      Vrije Universiteit
+;      Postbox 7161
+;      1007 MC Amsterdam
+;      The Netherlands
+;
+;
+
+ mes 2,_EM_WSIZE,_EM_PSIZE
+
+#define	TRAP	0
+
+; trap is called with one parameter:
+;	- trap number (TRAP)
+
+ exp $trap
+ pro $trap,0
+ lol TRAP
+ trp
+ ret 0
+ end ?
Index: /trunk/minix/lib/ack/libp/trp.e
===================================================================
--- /trunk/minix/lib/ack/libp/trp.e	(revision 9)
+++ /trunk/minix/lib/ack/libp/trp.e	(revision 9)
@@ -0,0 +1,38 @@
+#
+
+; $Header: /cvsup/minix/src/lib/ack/libp/trp.e,v 1.1 2005/10/10 15:27:47 beng Exp $
+;
+; (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+;
+;          This product is part of the Amsterdam Compiler Kit.
+;
+; Permission to use, sell, duplicate or disclose this software must be
+; obtained in writing. Requests for such permissions may be sent to
+;
+;      Dr. Andrew S. Tanenbaum
+;      Wiskundig Seminarium
+;      Vrije Universiteit
+;      Postbox 7161
+;      1007 MC Amsterdam
+;      The Netherlands
+;
+;
+
+ mes 2,_EM_WSIZE,_EM_PSIZE
+
+#define TRAP    0
+
+; _trp() and trap() perform the same function,
+; but have to be separate. trap exists to facilitate the user.
+; _trp is there for the system, trap cannot be used for that purpose
+; because a user might define its own Pascal routine called trap.
+
+; _trp is called with one parameter:
+;       - trap number (TRAP)
+
+ exp $_trp
+ pro $_trp,0
+ lol TRAP
+ trp
+ ret 0
+ end ?
Index: /trunk/minix/lib/ack/libp/unp.c
===================================================================
--- /trunk/minix/lib/ack/libp/unp.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/unp.c	(revision 9)
@@ -0,0 +1,65 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/unp.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_err.h>
+
+extern		_trp();
+
+#define	assert(x)	/* nothing */
+
+#ifndef EM_WSIZE
+#define EM_WSIZE _EM_WSIZE
+#endif
+
+struct descr {
+	int	low;
+	int	diff;
+	int	size;
+};
+
+_unp(ad,zd,i,ap,zp,noext) int i; struct descr *ad,*zd; char *ap,*zp; int noext; {
+
+	if (zd->diff > ad->diff ||
+			(i -= ad->low) < 0 ||
+			(i+zd->diff) > ad->diff)
+		_trp(EUNPACK);
+	ap += (i * ad->size);
+	i = (zd->diff + 1) * zd->size;
+	if (zd->size == 1) {
+		int *aptmp = (int *) ap;
+		assert(ad->size == EM_WSIZE);
+		while (--i >= 0)
+			if (noext) *aptmp++ = *zp++ & 0377;
+			else *aptmp++ = *zp++;
+#if EM_WSIZE > 2
+	} else if (zd->size == 2) {
+		int *aptmp = (int *) ap;
+		short *zptmp = (short *) zp;
+		assert(ad->size == EM_WSIZE);
+		while (--i >= 0)
+			if (noext) *aptmp++ = *zptmp++ & 0177777;
+			else *aptmp++ = *zptmp++;
+#endif
+	} else {
+		assert(ad->size == zd->size);
+		while (--i >= 0)
+			*ap++ = *zp++;
+	}
+}
Index: /trunk/minix/lib/ack/libp/uread.c
===================================================================
--- /trunk/minix/lib/ack/libp/uread.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/uread.c	(revision 9)
@@ -0,0 +1,25 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/uread.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* function uread(fd:integer; var b:buf; n:integer):integer; */
+
+extern int	_read();
+
+int uread(fd,b,n) char *b; int fd,n; {
+	return(_read(fd,b,n));
+}
Index: /trunk/minix/lib/ack/libp/uwrite.c
===================================================================
--- /trunk/minix/lib/ack/libp/uwrite.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/uwrite.c	(revision 9)
@@ -0,0 +1,25 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/uwrite.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* function uwrite(fd:integer; var b:buf; n:integer):integer; */
+
+extern int	_write();
+
+int uwrite(fd,b,n) char *b; int fd,n; {
+	return(_write(fd,b,n));
+}
Index: /trunk/minix/lib/ack/libp/wdw.c
===================================================================
--- /trunk/minix/lib/ack/libp/wdw.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/wdw.c	(revision 9)
@@ -0,0 +1,30 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/wdw.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include	<pc_file.h>
+
+extern struct file	*_curfil;
+extern			_incpt();
+
+char *_wdw(f) struct file *f; {
+
+	_curfil = f;
+	if ((f->flags & (WINDOW|WRBIT|0377)) == MAGIC)
+		_incpt(f);
+	return(f->ptr);
+}
Index: /trunk/minix/lib/ack/libp/wf.c
===================================================================
--- /trunk/minix/lib/ack/libp/wf.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/wf.c	(revision 9)
@@ -0,0 +1,32 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/wf.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include	<pc_file.h>
+#include	<pc_err.h>
+
+extern struct file	*_curfil;
+extern			_trp();
+
+_wf(f) struct file *f; {
+
+	_curfil = f;
+	if ((f->flags&0377) != MAGIC)
+		_trp(EBADF);
+	if ((f->flags & WRBIT) == 0)
+		_trp(EWRITEF);
+}
Index: /trunk/minix/lib/ack/libp/wrc.c
===================================================================
--- /trunk/minix/lib/ack/libp/wrc.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/wrc.c	(revision 9)
@@ -0,0 +1,41 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/wrc.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include	<pc_file.h>
+
+extern		_wf();
+extern		_outcpt();
+
+_wrc(c,f) int c; struct file *f; {
+	*f->ptr = c;
+	_wf(f);
+	_outcpt(f);
+}
+
+_wln(f) struct file *f; {
+#ifdef CPM
+	_wrc('\r',f);
+#endif
+	_wrc('\n',f);
+	f->flags |= ELNBIT;
+}
+
+_pag(f) struct file *f; {
+	_wrc('\014',f);
+	f->flags |= ELNBIT;
+}
Index: /trunk/minix/lib/ack/libp/wrf.c
===================================================================
--- /trunk/minix/lib/ack/libp/wrf.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/wrf.c	(revision 9)
@@ -0,0 +1,68 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/wrf.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_err.h>
+#include	<pc_file.h>
+
+extern		_wstrin();
+extern char	*_fcvt();
+
+#define	assert(x)	/* nothing */
+
+#if __STDC__
+#include <float.h>
+#define	HUGE_DIG	DBL_MAX_10_EXP	/* log10(maxreal) */
+#else
+#define	HUGE_DIG	400	/* log10(maxreal) */
+#endif
+#define	PREC_DIG	80	/* the maximum digits returned by _fcvt() */
+#define	FILL_CHAR	'0'	/* char printed if all of _fcvt() used */
+#define	BUFSIZE		HUGE_DIG + PREC_DIG + 3
+
+_wrf(n,w,r,f) int n,w; double r; struct file *f; {
+	char *p,*b; int s,d; char buf[BUFSIZE];
+
+	if ( n < 0 || w < 0) _trp(EWIDTH);
+	p = buf;
+	if (n > PREC_DIG)
+		n = PREC_DIG;
+	b = _fcvt(r,n,&d,&s);
+	assert(abs(d) <= HUGE_DIG);
+	if (s)
+		*p++ = '-';
+	if (d<=0)
+		*p++ = '0';
+	else
+		do
+			*p++ = (*b ? *b++ : FILL_CHAR);
+		while (--d > 0);
+	if (n > 0)
+		*p++ = '.';
+	while (++d <= 0) {
+		if (--n < 0)
+			break;
+		*p++ = '0';
+	}
+	while (--n >= 0) {
+		*p++ = (*b ? *b++ : FILL_CHAR);
+		assert(p <= buf+BUFSIZE);
+	}
+	_wstrin(w,(int)(p-buf),buf,f);
+}
Index: /trunk/minix/lib/ack/libp/wri.c
===================================================================
--- /trunk/minix/lib/ack/libp/wri.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/wri.c	(revision 9)
@@ -0,0 +1,72 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/wri.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include	<pc_err.h>
+#include	<pc_file.h>
+
+extern		_wstrin();
+
+#ifndef EM_WSIZE
+#ifdef _EM_WSIZE
+#define EM_WSIZE _EM_WSIZE
+#endif
+#endif
+
+#if EM_WSIZE==4
+#define SZ 11
+#define MININT -2147483648
+#define STRMININT "-2147483648"
+#endif
+#if EM_WSIZE==2
+#define SZ 6
+#define MININT -32768
+#define STRMININT "-32768"
+#endif
+#if EM_WSIZE==1
+#define SZ 4
+#define MININT -128
+#define STRMININT "-128"
+#endif
+
+#ifndef STRMININT
+Something wrong here!
+#endif
+
+_wsi(w,i,f) int w,i; struct file *f; {
+	char *p; int j; char buf[SZ];
+
+	if (w < 0) _trp(EWIDTH);
+	p = &buf[SZ];
+	if ((j=i) < 0) {
+		if (i == MININT) {
+			_wstrin(w,SZ,STRMININT,f);
+			return;
+		}
+		j = -j;
+	}
+	do
+		*--p = '0' + j%10;
+	while (j /= 10);
+	if (i<0)
+		*--p = '-';
+	_wstrin(w,(int)(&buf[SZ]-p),p,f);
+}
+
+_wri(i,f) int i; struct file *f; {
+	_wsi(SZ,i,f);
+}
Index: /trunk/minix/lib/ack/libp/wrl.c
===================================================================
--- /trunk/minix/lib/ack/libp/wrl.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/wrl.c	(revision 9)
@@ -0,0 +1,51 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/wrl.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_err.h>
+#include	<pc_file.h>
+
+extern		_wstrin();
+
+#define	MAXNEGLONG	-2147483648
+
+_wsl(w,l,f) int w; long l; struct file *f; {
+	char *p,c; long j; char buf[11];
+
+	if (w < 0) _trp(EWIDTH);
+	p = &buf[11];
+	if ((j=l) < 0) {
+		if (l == MAXNEGLONG) {
+			_wstrin(w,11,"-2147483648",f);
+			return;
+		}
+		j = -j;
+	}
+	do {
+		c = j%10;
+		*--p = c + '0';
+	} while (j /= 10);
+	if (l<0)
+		*--p = '-';
+	_wstrin(w,(int)(&buf[11]-p),p,f);
+}
+
+_wrl(l,f) long l; struct file *f; {
+	_wsl(11,l,f);
+}
Index: /trunk/minix/lib/ack/libp/wrr.c
===================================================================
--- /trunk/minix/lib/ack/libp/wrr.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/wrr.c	(revision 9)
@@ -0,0 +1,67 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/wrr.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_err.h>
+#include	<pc_file.h>
+
+extern		_wstrin();
+extern char	*_ecvt();
+
+#define	PREC_DIG	80	/* maximum digits produced by _ecvt() */
+
+_wsr(w,r,f) int w; double r; struct file *f; {
+	char *p,*b; int s,d,i; char buf[PREC_DIG+7];
+
+	if (w < 0) _trp(EWIDTH);
+	p = buf;
+	if ((i = w-6) < 2)
+		i = 2;
+	b = _ecvt(r,i,&d,&s);
+	*p++ = s? '-' : ' ';
+	if (*b == '0')
+		d++;
+	*p++ = *b++;
+	*p++ = '.';
+	while (--i > 0)
+		*p++ = *b++;
+	*p++ = 'e';
+	d--;
+	if (d < 0) {
+		d = -d;
+		*p++ = '-';
+	} else
+		*p++ = '+';
+
+	if (d >= 1000) {
+		*p++ = '*';
+		*p++ = '*';
+		*p++ = '*';
+	}
+	else {
+		*p++ = '0' + d/100;
+		*p++ = '0' + (d/10) % 10;
+		*p++ = '0' + d%10;
+	}
+	_wstrin(w,(int)(p-buf),buf,f);
+}
+
+_wrr(r,f) double r; struct file *f; {
+	_wsr(13,r,f);
+}
Index: /trunk/minix/lib/ack/libp/wrs.c
===================================================================
--- /trunk/minix/lib/ack/libp/wrs.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/wrs.c	(revision 9)
@@ -0,0 +1,68 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/wrs.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+/* Author: J.W. Stevenson */
+
+#include	<pc_err.h>
+#include	<pc_file.h>
+
+extern		_wf();
+extern		_outcpt();
+
+_wstrin(width,len,buf,f) int width,len; char *buf; struct file *f; {
+
+	_wf(f);
+	for (width -= len; width>0; width--) {
+		*f->ptr = ' ';
+		_outcpt(f);
+	}
+	while (--len >= 0) {
+		*f->ptr = *buf++;
+		_outcpt(f);
+	}
+}
+
+_wsc(w,c,f) int w; char c; struct file *f; {
+
+	if (w < 0) _trp(EWIDTH);
+	_wss(w,1,&c,f);
+}
+
+_wss(w,len,s,f) int w,len; char *s; struct file *f; {
+
+	if (w < 0 || len < 0) _trp(EWIDTH);
+	if (w < len)
+		len = w;
+	_wstrin(w,len,s,f);
+}
+
+_wrs(len,s,f) int len; char *s; struct file *f; {
+	if (len < 0) _trp(EWIDTH);
+	_wss(len,len,s,f);
+}
+
+_wsb(w,b,f) int w,b; struct file *f; {
+	if (b)
+		_wss(w,4,"true",f);
+	else
+		_wss(w,5,"false",f);
+}
+
+_wrb(b,f) int b; struct file *f; {
+	_wsb(5,b,f);
+}
Index: /trunk/minix/lib/ack/libp/wrz.c
===================================================================
--- /trunk/minix/lib/ack/libp/wrz.c	(revision 9)
+++ /trunk/minix/lib/ack/libp/wrz.c	(revision 9)
@@ -0,0 +1,38 @@
+/* $Header: /cvsup/minix/src/lib/ack/libp/wrz.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include	<pc_err.h>
+#include	<pc_file.h>
+
+extern		_wss();
+extern		_wrs();
+
+_wsz(w,s,f) int w; char *s; struct file *f; {
+	char *p;
+
+	if (w < 0) _trp(EWIDTH);
+	for (p=s; *p; p++);
+	_wss(w,(int)(p-s),s,f);
+}
+
+_wrz(s,f) char *s; struct file *f; {
+	char *p;
+
+	for (p=s; *p; p++);
+	_wrs((int)(p-s),s,f);
+}
Index: /trunk/minix/lib/ack/liby/Makedepend-ack
===================================================================
--- /trunk/minix/lib/ack/liby/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/ack/liby/Makedepend-ack	(revision 9)
@@ -0,0 +1,5 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -wo -E' main.c | sed -e 's:^\(.\):../../obj-ack//./ack/liby/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -wo -E' yyerror.c | sed -e 's:^\(.\):../../obj-ack//./ack/liby/\1:' >> .depend-ack
Index: /trunk/minix/lib/ack/liby/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/ack/liby/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/ack/liby/Makedepend-gnu	(revision 9)
@@ -0,0 +1,3 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
Index: /trunk/minix/lib/ack/liby/Makefile
===================================================================
--- /trunk/minix/lib/ack/liby/Makefile	(revision 9)
+++ /trunk/minix/lib/ack/liby/Makefile	(revision 9)
@@ -0,0 +1,43 @@
+#Generated from ./ack/liby/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../generate.sh ./ack/liby ../../obj-ack/ ../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../generate.sh ./ack/liby ../../obj-ack/ ../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../../obj-ack//liby.a
+
+../../obj-ack//liby.a: ../../obj-ack//liby.a(main.o)
+../../obj-ack//liby.a: ../../obj-ack//liby.a(yyerror.o)
+
+../../obj-ack//liby.a:
+	ar cr ../../obj-ack//liby.a ../../obj-ack//./ack/liby/*.o
+	rm ../../obj-ack//./ack/liby/*.o
+
+../../obj-ack//liby.a(main.o): main.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -wo -c -o ../../obj-ack//./ack/liby/main.o main.c
+../../obj-ack//liby.a(yyerror.o): yyerror.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -wo -c -o ../../obj-ack//./ack/liby/yyerror.o yyerror.c
+
+
+
+clean::
+	rm -f ../../obj-ack//./ack/liby/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/ack/liby/Makefile.in
===================================================================
--- /trunk/minix/lib/ack/liby/Makefile.in	(revision 9)
+++ /trunk/minix/lib/ack/liby/Makefile.in	(revision 9)
@@ -0,0 +1,11 @@
+# Makefile for lib/liby.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE -wo"
+
+LIBRARIES=liby
+
+liby_FILES=" \
+	main.c \
+	yyerror.c"
+
+TYPE=ack
Index: /trunk/minix/lib/ack/liby/main.c
===================================================================
--- /trunk/minix/lib/ack/liby/main.c	(revision 9)
+++ /trunk/minix/lib/ack/liby/main.c	(revision 9)
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)main.c	5.3 (Berkeley) 1/13/91";
+#endif /* not lint */
+
+main()
+{
+	exit(yyparse());
+}
Index: /trunk/minix/lib/ack/liby/yyerror.c
===================================================================
--- /trunk/minix/lib/ack/liby/yyerror.c	(revision 9)
+++ /trunk/minix/lib/ack/liby/yyerror.c	(revision 9)
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)yyerror.c	5.2 (Berkeley) 5/15/90";
+#endif /* not lint */
+
+#include <stdio.h>
+
+yyerror(msg)
+char *msg;
+{
+	(void)fprintf(stderr, "%s\n", msg);
+	return(0);
+}
Index: /trunk/minix/lib/ack/math/Makedepend-ack
===================================================================
--- /trunk/minix/lib/ack/math/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/ack/math/Makedepend-ack	(revision 9)
@@ -0,0 +1,7 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' frexp.s | sed -e 's:^\(.\):../../obj-ack//./ack/math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' modf.s | sed -e 's:^\(.\):../../obj-ack//./ack/math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' isnan.c | sed -e 's:^\(.\):../../obj-ack//./ack/math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' ldexp.c | sed -e 's:^\(.\):../../obj-ack//./ack/math/\1:' >> .depend-ack
Index: /trunk/minix/lib/ack/math/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/ack/math/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/ack/math/Makedepend-gnu	(revision 9)
@@ -0,0 +1,3 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
Index: /trunk/minix/lib/ack/math/Makefile
===================================================================
--- /trunk/minix/lib/ack/math/Makefile	(revision 9)
+++ /trunk/minix/lib/ack/math/Makefile	(revision 9)
@@ -0,0 +1,49 @@
+#Generated from ./ack/math/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../generate.sh ./ack/math ../../obj-ack/ ../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../generate.sh ./ack/math ../../obj-ack/ ../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../../obj-ack//libc.a
+
+../../obj-ack//libc.a: ../../obj-ack//libc.a(frexp.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(modf.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(isnan.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(ldexp.o)
+
+../../obj-ack//libc.a:
+	ar cr ../../obj-ack//libc.a ../../obj-ack//./ack/math/*.o
+	rm ../../obj-ack//./ack/math/*.o
+
+../../obj-ack//libc.a(frexp.o): frexp.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./ack/math/frexp.o frexp.s
+../../obj-ack//libc.a(modf.o): modf.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./ack/math/modf.o modf.s
+../../obj-ack//libc.a(isnan.o): isnan.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./ack/math/isnan.o isnan.c
+../../obj-ack//libc.a(ldexp.o): ldexp.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./ack/math/ldexp.o ldexp.c
+
+
+
+clean::
+	rm -f ../../obj-ack//./ack/math/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/ack/math/Makefile.in
===================================================================
--- /trunk/minix/lib/ack/math/Makefile.in	(revision 9)
+++ /trunk/minix/lib/ack/math/Makefile.in	(revision 9)
@@ -0,0 +1,13 @@
+# Makefile for lib/ack/math.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
+
+LIBRARIES=libc
+
+libc_FILES=" \
+	frexp.s \
+	modf.s \
+	isnan.c \
+	ldexp.c"
+
+TYPE=ack
Index: /trunk/minix/lib/ack/math/frexp.s
===================================================================
--- /trunk/minix/lib/ack/math/frexp.s	(revision 9)
+++ /trunk/minix/lib/ack/math/frexp.s	(revision 9)
@@ -0,0 +1,35 @@
+#
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern _frexp
+.sect .text
+_frexp:
+#if __i386
+	push	ebp
+	mov	ebp, esp
+	push	12(ebp)
+	push	8(ebp)
+	mov	eax, esp
+	add	eax, -4
+	push	eax
+	call	.fef8
+	mov	eax, 16(ebp)
+	pop	(eax)
+	pop	eax
+	pop	edx
+	leave
+	ret
+#else /* i86 */
+	push	bp
+	mov	bp, sp
+	lea	bx, 4(bp)
+	mov	cx, #8
+	call	.loi
+	mov	ax, sp
+	add	ax, #-2
+	push	ax
+	call	.fef8
+	mov	bx, 12(bp)
+	pop	(bx)
+	call	.ret8
+	jmp	.cret
+#endif
Index: /trunk/minix/lib/ack/math/isnan.c
===================================================================
--- /trunk/minix/lib/ack/math/isnan.c	(revision 9)
+++ /trunk/minix/lib/ack/math/isnan.c	(revision 9)
@@ -0,0 +1,11 @@
+int __IsNan(double d)
+{
+#if defined(vax) || defined(pdp)
+#else
+	float f = d;
+
+	if ((*((long *) &f) & 0x7f800000) == 0x7f800000 &&
+	    (*((long *) &f) & 0x007fffff) != 0) return 1;
+#endif
+	return 0;
+}
Index: /trunk/minix/lib/ack/math/ldexp.c
===================================================================
--- /trunk/minix/lib/ack/math/ldexp.c	(revision 9)
+++ /trunk/minix/lib/ack/math/ldexp.c	(revision 9)
@@ -0,0 +1,55 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ack/math/ldexp.c,v 1.1 2005/10/10 15:27:47 beng Exp $ */
+
+#include	<math.h>
+#include	<float.h>
+#include	<errno.h>
+
+double
+ldexp(double fl, int exp)
+{
+	int sign = 1;
+	int currexp;
+
+	if (__IsNan(fl)) {
+		errno = EDOM;
+		return fl;
+	}
+	if (fl == 0.0) return 0.0;
+	if (fl<0) {
+		fl = -fl;
+		sign = -1;
+	}
+	if (fl > DBL_MAX) {		/* for infinity */
+		errno = ERANGE;
+		return sign * fl;
+	}
+	fl = frexp(fl,&currexp);
+	exp += currexp;
+	if (exp > 0) {
+		if (exp > DBL_MAX_EXP) {
+			errno = ERANGE;
+			return sign * HUGE_VAL;
+		}
+		while (exp>30) {
+			fl *= (double) (1L << 30);
+			exp -= 30;
+		}
+		fl *= (double) (1L << exp);
+	}
+	else	{
+		/* number need not be normalized */
+		if (exp < DBL_MIN_EXP - DBL_MANT_DIG) {
+			return 0.0;
+		}
+		while (exp<-30) {
+			fl /= (double) (1L << 30);
+			exp += 30;
+		}
+		fl /= (double) (1L << -exp);
+	}
+	return sign * fl;
+}
Index: /trunk/minix/lib/ack/math/modf.s
===================================================================
--- /trunk/minix/lib/ack/math/modf.s	(revision 9)
+++ /trunk/minix/lib/ack/math/modf.s	(revision 9)
@@ -0,0 +1,49 @@
+#
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.extern _modf
+.sect .text
+_modf:
+#if __i386
+	push	ebp
+	mov	ebp, esp
+	push	12(ebp)
+	push	8(ebp)
+	push	1
+	push	4
+	call	.cif8
+	mov	eax, esp
+	push	eax
+	call	.fif8
+	pop	ecx
+	mov	edx, 16(ebp)
+	pop	ecx
+	pop	ebx
+	mov	0(edx), ecx
+	mov	4(edx), ebx
+	pop	eax
+	pop	edx
+	leave
+	ret
+#else /* i86 */
+	push	bp
+	mov	bp, sp
+	lea	bx, 4(bp)
+	mov	cx, #8
+	call	.loi
+	mov	dx, #1
+	push	dx
+	push	dx
+	push	dx
+	mov	ax, #2
+	push	ax
+	call	.cif8
+	mov	ax, sp
+	push	ax
+	call	.fif8
+	pop	bx
+	mov	bx, 12(bp)
+	mov	cx, #8
+	call	.sti
+	call	.ret8
+	jmp	.cret
+#endif
Index: /trunk/minix/lib/ack/rts/Makedepend-ack
===================================================================
--- /trunk/minix/lib/ack/rts/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/ack/rts/Makedepend-ack	(revision 9)
@@ -0,0 +1,4 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' setjmp.e | sed -e 's:^\(.\):../../obj-ack//./ack/rts/\1:' >> .depend-ack
Index: /trunk/minix/lib/ack/rts/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/ack/rts/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/ack/rts/Makedepend-gnu	(revision 9)
@@ -0,0 +1,3 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
Index: /trunk/minix/lib/ack/rts/Makefile
===================================================================
--- /trunk/minix/lib/ack/rts/Makefile	(revision 9)
+++ /trunk/minix/lib/ack/rts/Makefile	(revision 9)
@@ -0,0 +1,40 @@
+#Generated from ./ack/rts/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../generate.sh ./ack/rts ../../obj-ack/ ../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../generate.sh ./ack/rts ../../obj-ack/ ../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../../obj-ack//libc.a
+
+../../obj-ack//libc.a: ../../obj-ack//libc.a(setjmp.o)
+
+../../obj-ack//libc.a:
+	ar cr ../../obj-ack//libc.a ../../obj-ack//./ack/rts/*.o
+	rm ../../obj-ack//./ack/rts/*.o
+
+../../obj-ack//libc.a(setjmp.o): setjmp.e
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./ack/rts/setjmp.o setjmp.e
+
+
+
+clean::
+	rm -f ../../obj-ack//./ack/rts/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/ack/rts/Makefile.in
===================================================================
--- /trunk/minix/lib/ack/rts/Makefile.in	(revision 9)
+++ /trunk/minix/lib/ack/rts/Makefile.in	(revision 9)
@@ -0,0 +1,9 @@
+# Makefile for lib/ack/rts.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
+
+LIBRARIES=libc
+
+libc_FILES=setjmp.e
+
+TYPE=ack
Index: /trunk/minix/lib/ack/rts/setjmp.e
===================================================================
--- /trunk/minix/lib/ack/rts/setjmp.e	(revision 9)
+++ /trunk/minix/lib/ack/rts/setjmp.e	(revision 9)
@@ -0,0 +1,112 @@
+#
+ mes 2,_EM_WSIZE,_EM_PSIZE
+;
+; layout of a setjmp buffer:
+;
+;  -----------------
+; |      flag       |		(!0 when blocked signals saved (POSIX))
+;  -----------------
+; | signal mask/set |		(for Berkeley 4.[2-] / POSIX)
+;  -----------------
+; |                 |
+; |  GTO descriptor |
+; |   (SP, LB, PC)  |
+; |                 |
+;  -----------------
+;
+; setjmp saves the signalmask, PC, SP, and LB of caller, and creates a
+; GTO descriptor from this.
+; The big problem here is how to get the return address, i.e. the PC of
+; the caller; This problem is solved by the front-end, which must pass
+; it as an extra parameter to setjmp.
+
+; a GTO descriptor must be in the global data area
+gtobuf
+ bss 3*_EM_PSIZE,0,0
+
+ inp $fill_ret_area
+ exp $__setjmp
+ pro $__setjmp,0
+#if	defined(_POSIX_SOURCE)
+; save mask of currently blocked signals. 
+; longjmp must restore this mask
+ lol _EM_PSIZE			; the flag integer at offset _EM_PSIZE
+ lal 0
+ loi _EM_PSIZE
+ stf 3*_EM_PSIZE+_EM_LSIZE
+ lol _EM_PSIZE			; the flag integer at offset _EM_PSIZE
+ zeq *1
+ lal 0
+ loi _EM_PSIZE
+ adp 3*_EM_PSIZE
+ cal $__newsigset
+ asp _EM_PSIZE
+1
+#elif	defined(__BSD4_2)
+ loc 0
+ cal $sigblock
+ asp _EM_WSIZE
+ lfr _EM_WSIZE
+ lal 0
+ loi _EM_PSIZE
+ stf 3*_EM_PSIZE
+#endif
+; create GTO descriptor for longjmp
+ lxl 0
+ dch		; Local Base of caller
+ lxa 0		; Stackpointer of caller
+ lal _EM_PSIZE+_EM_WSIZE
+ loi _EM_PSIZE	; Return address of caller
+ lal 0
+ loi _EM_PSIZE	; address of jmpbuf
+ sti 3*_EM_PSIZE	; LB, SP, and PC stored in jmpbuf
+ loc 0
+ ret _EM_WSIZE	; setjmp must return 0
+ end 0
+
+ pro $fill_ret_area,0
+; put argument in function result area
+ lol 0
+ ret _EM_WSIZE
+ end 0
+
+ exp $longjmp
+ pro $longjmp,?
+#if	defined(_POSIX_SOURCE)
+; restore blocked mask
+ lal 0
+ loi _EM_PSIZE
+ lof 3*_EM_PSIZE+_EM_LSIZE
+ zeq *2
+ lal 0
+ loi _EM_PSIZE
+ adp 3*_EM_PSIZE
+ cal $__oldsigset
+ asp _EM_PSIZE
+2
+#elif	defined(__BSD4_2)
+; restore signal mask
+ lal 0
+ loi _EM_PSIZE
+ lof 3*_EM_PSIZE
+ cal $_sigsetmask
+ asp _EM_WSIZE
+ lfr _EM_WSIZE
+ asp _EM_WSIZE
+#endif
+ lal 0
+ loi _EM_PSIZE	; address of jmpbuf
+ lae gtobuf
+ blm 3*_EM_PSIZE	; fill GTO descriptor from jmpbuf
+ lol _EM_PSIZE	; second parameter of longjmp: the return value
+ dup _EM_WSIZE
+ zne *3
+; of course, longjmp may not return 0!
+ inc
+3
+; put return value in function result area
+ cal $fill_ret_area
+ asp _EM_WSIZE
+ gto gtobuf	; there we go ...
+; ASP and GTO do not damage function result area
+ end 0
Index: /trunk/minix/lib/ansi/Makedepend-ack
===================================================================
--- /trunk/minix/lib/ansi/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/ansi/Makedepend-ack	(revision 9)
@@ -0,0 +1,67 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' abort.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' abs.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' asctime.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' assert.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' atexit.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' atof.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' atoi.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' atol.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' bsearch.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' calloc.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' chartab.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' clock.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' ctime.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' difftime.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' div.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' errlist.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' exit.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' ext_comp.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' getenv.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' gmtime.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isalnum.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isalpha.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isascii.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' iscntrl.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isdigit.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isgraph.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' islower.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isprint.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' ispunct.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isspace.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isupper.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isxdigit.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' labs.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' ldiv.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' localeconv.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' localtime.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' malloc.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' mblen.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' mbstowcs.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' mbtowc.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' misc.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' mktime.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' qsort.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' raise.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' rand.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' setlocale.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' sigmisc.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' signal.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strcoll.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strcspn.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strerror.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strftime.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strpbrk.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strspn.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strstr.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strtok.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strtol.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strxfrm.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' system.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' tolower.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' toupper.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' tzset.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' wcstombs.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' wctomb.c | sed -e 's:^\(.\):../obj-ack//./ansi/\1:' >> .depend-ack
Index: /trunk/minix/lib/ansi/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/ansi/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/ansi/Makedepend-gnu	(revision 9)
@@ -0,0 +1,67 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' abort.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' abs.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' asctime.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' assert.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' atexit.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' atof.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' atoi.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' atol.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' bsearch.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' calloc.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' chartab.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' clock.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' ctime.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' difftime.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' div.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' errlist.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' exit.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' ext_comp.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' getenv.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' gmtime.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isalnum.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isalpha.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isascii.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' iscntrl.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isdigit.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isgraph.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' islower.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isprint.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' ispunct.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isspace.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isupper.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' isxdigit.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' labs.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' ldiv.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' localeconv.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' localtime.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' malloc.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' mblen.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' mbstowcs.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' mbtowc.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' misc.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' mktime.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' qsort.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' raise.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' rand.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' setlocale.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' sigmisc.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' signal.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strcoll.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strcspn.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strerror.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strftime.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strpbrk.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strspn.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strstr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strtok.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strtol.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' strxfrm.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' system.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' tolower.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' toupper.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' tzset.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' wcstombs.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -E' wctomb.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ansi/\1:' >> .depend-gnu
Index: /trunk/minix/lib/ansi/Makefile
===================================================================
--- /trunk/minix/lib/ansi/Makefile	(revision 9)
+++ /trunk/minix/lib/ansi/Makefile	(revision 9)
@@ -0,0 +1,493 @@
+#Generated from ./ansi/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./ansi ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./ansi ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libc.a
+
+../obj-ack//libc.a: ../obj-ack//libc.a(abort.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(abs.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(asctime.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(assert.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(atexit.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(atof.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(atoi.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(atol.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(bsearch.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(calloc.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(chartab.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(clock.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ctime.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(difftime.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(div.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(errlist.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(exit.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ext_comp.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getenv.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(gmtime.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(isalnum.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(isalpha.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(isascii.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(iscntrl.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(isdigit.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(isgraph.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(islower.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(isprint.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ispunct.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(isspace.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(isupper.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(isxdigit.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(labs.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ldiv.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(localeconv.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(localtime.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(malloc.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(mblen.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(mbstowcs.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(mbtowc.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(misc.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(mktime.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(qsort.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(raise.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(rand.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(setlocale.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sigmisc.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(signal.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(strcoll.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(strcspn.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(strerror.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(strftime.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(strpbrk.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(strspn.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(strstr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(strtok.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(strtol.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(strxfrm.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(system.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(tolower.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(toupper.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(tzset.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(wcstombs.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(wctomb.o)
+
+../obj-ack//libc.a:
+	ar cr ../obj-ack//libc.a ../obj-ack//./ansi/*.o
+	rm ../obj-ack//./ansi/*.o
+
+../obj-ack//libc.a(abort.o): abort.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/abort.o abort.c
+../obj-ack//libc.a(abs.o): abs.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/abs.o abs.c
+../obj-ack//libc.a(asctime.o): asctime.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/asctime.o asctime.c
+../obj-ack//libc.a(assert.o): assert.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/assert.o assert.c
+../obj-ack//libc.a(atexit.o): atexit.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/atexit.o atexit.c
+../obj-ack//libc.a(atof.o): atof.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/atof.o atof.c
+../obj-ack//libc.a(atoi.o): atoi.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/atoi.o atoi.c
+../obj-ack//libc.a(atol.o): atol.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/atol.o atol.c
+../obj-ack//libc.a(bsearch.o): bsearch.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/bsearch.o bsearch.c
+../obj-ack//libc.a(calloc.o): calloc.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/calloc.o calloc.c
+../obj-ack//libc.a(chartab.o): chartab.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/chartab.o chartab.c
+../obj-ack//libc.a(clock.o): clock.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/clock.o clock.c
+../obj-ack//libc.a(ctime.o): ctime.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/ctime.o ctime.c
+../obj-ack//libc.a(difftime.o): difftime.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/difftime.o difftime.c
+../obj-ack//libc.a(div.o): div.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/div.o div.c
+../obj-ack//libc.a(errlist.o): errlist.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/errlist.o errlist.c
+../obj-ack//libc.a(exit.o): exit.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/exit.o exit.c
+../obj-ack//libc.a(ext_comp.o): ext_comp.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/ext_comp.o ext_comp.c
+../obj-ack//libc.a(getenv.o): getenv.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/getenv.o getenv.c
+../obj-ack//libc.a(gmtime.o): gmtime.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/gmtime.o gmtime.c
+../obj-ack//libc.a(isalnum.o): isalnum.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/isalnum.o isalnum.c
+../obj-ack//libc.a(isalpha.o): isalpha.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/isalpha.o isalpha.c
+../obj-ack//libc.a(isascii.o): isascii.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/isascii.o isascii.c
+../obj-ack//libc.a(iscntrl.o): iscntrl.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/iscntrl.o iscntrl.c
+../obj-ack//libc.a(isdigit.o): isdigit.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/isdigit.o isdigit.c
+../obj-ack//libc.a(isgraph.o): isgraph.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/isgraph.o isgraph.c
+../obj-ack//libc.a(islower.o): islower.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/islower.o islower.c
+../obj-ack//libc.a(isprint.o): isprint.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/isprint.o isprint.c
+../obj-ack//libc.a(ispunct.o): ispunct.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/ispunct.o ispunct.c
+../obj-ack//libc.a(isspace.o): isspace.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/isspace.o isspace.c
+../obj-ack//libc.a(isupper.o): isupper.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/isupper.o isupper.c
+../obj-ack//libc.a(isxdigit.o): isxdigit.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/isxdigit.o isxdigit.c
+../obj-ack//libc.a(labs.o): labs.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/labs.o labs.c
+../obj-ack//libc.a(ldiv.o): ldiv.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/ldiv.o ldiv.c
+../obj-ack//libc.a(localeconv.o): localeconv.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/localeconv.o localeconv.c
+../obj-ack//libc.a(localtime.o): localtime.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/localtime.o localtime.c
+../obj-ack//libc.a(malloc.o): malloc.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/malloc.o malloc.c
+../obj-ack//libc.a(mblen.o): mblen.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/mblen.o mblen.c
+../obj-ack//libc.a(mbstowcs.o): mbstowcs.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/mbstowcs.o mbstowcs.c
+../obj-ack//libc.a(mbtowc.o): mbtowc.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/mbtowc.o mbtowc.c
+../obj-ack//libc.a(misc.o): misc.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/misc.o misc.c
+../obj-ack//libc.a(mktime.o): mktime.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/mktime.o mktime.c
+../obj-ack//libc.a(qsort.o): qsort.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/qsort.o qsort.c
+../obj-ack//libc.a(raise.o): raise.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/raise.o raise.c
+../obj-ack//libc.a(rand.o): rand.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/rand.o rand.c
+../obj-ack//libc.a(setlocale.o): setlocale.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/setlocale.o setlocale.c
+../obj-ack//libc.a(sigmisc.o): sigmisc.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/sigmisc.o sigmisc.c
+../obj-ack//libc.a(signal.o): signal.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/signal.o signal.c
+../obj-ack//libc.a(strcoll.o): strcoll.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/strcoll.o strcoll.c
+../obj-ack//libc.a(strcspn.o): strcspn.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/strcspn.o strcspn.c
+../obj-ack//libc.a(strerror.o): strerror.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/strerror.o strerror.c
+../obj-ack//libc.a(strftime.o): strftime.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/strftime.o strftime.c
+../obj-ack//libc.a(strpbrk.o): strpbrk.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/strpbrk.o strpbrk.c
+../obj-ack//libc.a(strspn.o): strspn.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/strspn.o strspn.c
+../obj-ack//libc.a(strstr.o): strstr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/strstr.o strstr.c
+../obj-ack//libc.a(strtok.o): strtok.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/strtok.o strtok.c
+../obj-ack//libc.a(strtol.o): strtol.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/strtol.o strtol.c
+../obj-ack//libc.a(strxfrm.o): strxfrm.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/strxfrm.o strxfrm.c
+../obj-ack//libc.a(system.o): system.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/system.o system.c
+../obj-ack//libc.a(tolower.o): tolower.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/tolower.o tolower.c
+../obj-ack//libc.a(toupper.o): toupper.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/toupper.o toupper.c
+../obj-ack//libc.a(tzset.o): tzset.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/tzset.o tzset.c
+../obj-ack//libc.a(wcstombs.o): wcstombs.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/wcstombs.o wcstombs.c
+../obj-ack//libc.a(wctomb.o): wctomb.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-ack//./ansi/wctomb.o wctomb.c
+
+all-gnu: ../obj-gnu/libc.a
+
+../obj-gnu/libc.a: ../obj-gnu/./ansi/abort.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/abs.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/asctime.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/assert.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/atexit.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/atof.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/atoi.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/atol.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/bsearch.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/calloc.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/chartab.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/clock.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/ctime.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/difftime.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/div.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/errlist.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/exit.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/ext_comp.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/getenv.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/gmtime.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/isalnum.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/isalpha.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/isascii.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/iscntrl.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/isdigit.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/isgraph.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/islower.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/isprint.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/ispunct.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/isspace.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/isupper.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/isxdigit.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/labs.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/ldiv.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/localeconv.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/localtime.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/malloc.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/mblen.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/mbstowcs.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/mbtowc.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/misc.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/mktime.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/qsort.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/raise.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/rand.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/setlocale.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/sigmisc.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/signal.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/strcoll.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/strcspn.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/strerror.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/strftime.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/strpbrk.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/strspn.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/strstr.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/strtok.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/strtol.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/strxfrm.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/system.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/tolower.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/toupper.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/tzset.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/wcstombs.o
+../obj-gnu/libc.a: ../obj-gnu/./ansi/wctomb.o
+
+../obj-gnu/libc.a:
+	gar cr ../obj-gnu/libc.a $?
+
+../obj-gnu/./ansi/abort.o: abort.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/abort.o abort.c
+
+../obj-gnu/./ansi/abs.o: abs.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/abs.o abs.c
+
+../obj-gnu/./ansi/asctime.o: asctime.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/asctime.o asctime.c
+
+../obj-gnu/./ansi/assert.o: assert.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/assert.o assert.c
+
+../obj-gnu/./ansi/atexit.o: atexit.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/atexit.o atexit.c
+
+../obj-gnu/./ansi/atof.o: atof.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/atof.o atof.c
+
+../obj-gnu/./ansi/atoi.o: atoi.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/atoi.o atoi.c
+
+../obj-gnu/./ansi/atol.o: atol.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/atol.o atol.c
+
+../obj-gnu/./ansi/bsearch.o: bsearch.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/bsearch.o bsearch.c
+
+../obj-gnu/./ansi/calloc.o: calloc.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/calloc.o calloc.c
+
+../obj-gnu/./ansi/chartab.o: chartab.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/chartab.o chartab.c
+
+../obj-gnu/./ansi/clock.o: clock.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/clock.o clock.c
+
+../obj-gnu/./ansi/ctime.o: ctime.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/ctime.o ctime.c
+
+../obj-gnu/./ansi/difftime.o: difftime.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/difftime.o difftime.c
+
+../obj-gnu/./ansi/div.o: div.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/div.o div.c
+
+../obj-gnu/./ansi/errlist.o: errlist.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/errlist.o errlist.c
+
+../obj-gnu/./ansi/exit.o: exit.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/exit.o exit.c
+
+../obj-gnu/./ansi/ext_comp.o: ext_comp.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/ext_comp.o ext_comp.c
+
+../obj-gnu/./ansi/getenv.o: getenv.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/getenv.o getenv.c
+
+../obj-gnu/./ansi/gmtime.o: gmtime.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/gmtime.o gmtime.c
+
+../obj-gnu/./ansi/isalnum.o: isalnum.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/isalnum.o isalnum.c
+
+../obj-gnu/./ansi/isalpha.o: isalpha.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/isalpha.o isalpha.c
+
+../obj-gnu/./ansi/isascii.o: isascii.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/isascii.o isascii.c
+
+../obj-gnu/./ansi/iscntrl.o: iscntrl.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/iscntrl.o iscntrl.c
+
+../obj-gnu/./ansi/isdigit.o: isdigit.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/isdigit.o isdigit.c
+
+../obj-gnu/./ansi/isgraph.o: isgraph.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/isgraph.o isgraph.c
+
+../obj-gnu/./ansi/islower.o: islower.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/islower.o islower.c
+
+../obj-gnu/./ansi/isprint.o: isprint.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/isprint.o isprint.c
+
+../obj-gnu/./ansi/ispunct.o: ispunct.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/ispunct.o ispunct.c
+
+../obj-gnu/./ansi/isspace.o: isspace.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/isspace.o isspace.c
+
+../obj-gnu/./ansi/isupper.o: isupper.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/isupper.o isupper.c
+
+../obj-gnu/./ansi/isxdigit.o: isxdigit.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/isxdigit.o isxdigit.c
+
+../obj-gnu/./ansi/labs.o: labs.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/labs.o labs.c
+
+../obj-gnu/./ansi/ldiv.o: ldiv.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/ldiv.o ldiv.c
+
+../obj-gnu/./ansi/localeconv.o: localeconv.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/localeconv.o localeconv.c
+
+../obj-gnu/./ansi/localtime.o: localtime.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/localtime.o localtime.c
+
+../obj-gnu/./ansi/malloc.o: malloc.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/malloc.o malloc.c
+
+../obj-gnu/./ansi/mblen.o: mblen.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/mblen.o mblen.c
+
+../obj-gnu/./ansi/mbstowcs.o: mbstowcs.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/mbstowcs.o mbstowcs.c
+
+../obj-gnu/./ansi/mbtowc.o: mbtowc.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/mbtowc.o mbtowc.c
+
+../obj-gnu/./ansi/misc.o: misc.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/misc.o misc.c
+
+../obj-gnu/./ansi/mktime.o: mktime.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/mktime.o mktime.c
+
+../obj-gnu/./ansi/qsort.o: qsort.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/qsort.o qsort.c
+
+../obj-gnu/./ansi/raise.o: raise.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/raise.o raise.c
+
+../obj-gnu/./ansi/rand.o: rand.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/rand.o rand.c
+
+../obj-gnu/./ansi/setlocale.o: setlocale.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/setlocale.o setlocale.c
+
+../obj-gnu/./ansi/sigmisc.o: sigmisc.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/sigmisc.o sigmisc.c
+
+../obj-gnu/./ansi/signal.o: signal.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/signal.o signal.c
+
+../obj-gnu/./ansi/strcoll.o: strcoll.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/strcoll.o strcoll.c
+
+../obj-gnu/./ansi/strcspn.o: strcspn.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/strcspn.o strcspn.c
+
+../obj-gnu/./ansi/strerror.o: strerror.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/strerror.o strerror.c
+
+../obj-gnu/./ansi/strftime.o: strftime.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/strftime.o strftime.c
+
+../obj-gnu/./ansi/strpbrk.o: strpbrk.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/strpbrk.o strpbrk.c
+
+../obj-gnu/./ansi/strspn.o: strspn.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/strspn.o strspn.c
+
+../obj-gnu/./ansi/strstr.o: strstr.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/strstr.o strstr.c
+
+../obj-gnu/./ansi/strtok.o: strtok.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/strtok.o strtok.c
+
+../obj-gnu/./ansi/strtol.o: strtol.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/strtol.o strtol.c
+
+../obj-gnu/./ansi/strxfrm.o: strxfrm.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/strxfrm.o strxfrm.c
+
+../obj-gnu/./ansi/system.o: system.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/system.o system.c
+
+../obj-gnu/./ansi/tolower.o: tolower.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/tolower.o tolower.c
+
+../obj-gnu/./ansi/toupper.o: toupper.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/toupper.o toupper.c
+
+../obj-gnu/./ansi/tzset.o: tzset.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/tzset.o tzset.c
+
+../obj-gnu/./ansi/wcstombs.o: wcstombs.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/wcstombs.o wcstombs.c
+
+../obj-gnu/./ansi/wctomb.o: wctomb.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -D__USG -c -o ../obj-gnu/./ansi/wctomb.o wctomb.c
+
+
+
+
+clean::
+	rm -f ../obj-ack//./ansi/*
+	rm -f ../obj-gnu/./ansi/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/ansi/Makefile.in
===================================================================
--- /trunk/minix/lib/ansi/Makefile.in	(revision 9)
+++ /trunk/minix/lib/ansi/Makefile.in	(revision 9)
@@ -0,0 +1,91 @@
+# Makefile for lib/ansi.
+
+# This Makefile compiles part of the C library, the functions required by the
+# ANSI C standard.  This Makefile, and those in the other subdirectories use
+# a little known feature of make, the ability to refer to a file within a
+# library.  The construct abs.o' names the file 'abs.o' contained
+# in 'libc.a'.  So the rule
+#
+#	abs.o:	abs.c
+#		cc -c abs.c
+#		aal cr libc.a abs.o
+#		rm abs.o
+#
+# compiles abs.c and installs the result abs.o in libc.a if abs.c is newer
+# than the abs.o in the library.  This Makefile does not work like this
+# precisely, it first compiles all changed source files and than installs
+# them all in one 'aal' command.
+
+# Many of the string functions in this directory are not used, because the
+# have fast assembly implementations.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE -D__USG"
+
+LIBRARIES=libc
+libc_FILES=" \
+	abort.c \
+	abs.c \
+	asctime.c \
+	assert.c \
+	atexit.c \
+	atof.c \
+	atoi.c \
+	atol.c \
+	bsearch.c \
+	calloc.c \
+	chartab.c \
+	clock.c \
+	ctime.c \
+	difftime.c \
+	div.c \
+	errlist.c \
+	exit.c \
+	ext_comp.c \
+	getenv.c \
+	gmtime.c \
+	isalnum.c \
+	isalpha.c \
+	isascii.c \
+	iscntrl.c \
+	isdigit.c \
+	isgraph.c \
+	islower.c \
+	isprint.c \
+	ispunct.c \
+	isspace.c \
+	isupper.c \
+	isxdigit.c \
+	labs.c \
+	ldiv.c \
+	localeconv.c \
+	localtime.c \
+	malloc.c \
+	mblen.c \
+	mbstowcs.c \
+	mbtowc.c \
+	misc.c \
+	mktime.c \
+	qsort.c \
+	raise.c \
+	rand.c \
+	setlocale.c \
+	sigmisc.c \
+	signal.c \
+	strcoll.c \
+	strcspn.c \
+	strerror.c \
+	strftime.c \
+	strpbrk.c \
+	strspn.c \
+	strstr.c \
+	strtok.c \
+	strtol.c \
+	strxfrm.c \
+	system.c \
+	tolower.c \
+	toupper.c \
+	tzset.c \
+	wcstombs.c \
+	wctomb.c"
+		
+TYPE=both
Index: /trunk/minix/lib/ansi/abort.c
===================================================================
--- /trunk/minix/lib/ansi/abort.c	(revision 9)
+++ /trunk/minix/lib/ansi/abort.c	(revision 9)
@@ -0,0 +1,21 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/abort.c,v 1.1.1.1 2005/04/21 14:56:04 beng Exp $ */
+
+#if	defined(_POSIX_SOURCE)
+#include	<sys/types.h>
+#endif
+#include	<signal.h>
+#include	<stdlib.h>
+
+extern void (*_clean)(void);
+
+void
+abort(void)
+{
+	if (_clean) _clean();		/* flush all output files */
+	raise(SIGABRT);
+}
+
Index: /trunk/minix/lib/ansi/abs.c
===================================================================
--- /trunk/minix/lib/ansi/abs.c	(revision 9)
+++ /trunk/minix/lib/ansi/abs.c	(revision 9)
@@ -0,0 +1,13 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/abs.c,v 1.1.1.1 2005/04/21 14:56:04 beng Exp $ */
+
+#include	<stdlib.h>
+
+int
+abs(register int i)
+{
+	return i >= 0 ? i : -i;
+}
Index: /trunk/minix/lib/ansi/asctime.c
===================================================================
--- /trunk/minix/lib/ansi/asctime.c	(revision 9)
+++ /trunk/minix/lib/ansi/asctime.c	(revision 9)
@@ -0,0 +1,60 @@
+/*
+ * asctime - print a date
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/asctime.c,v 1.1.1.1 2005/04/21 14:56:04 beng Exp $ */
+
+#include	<string.h>
+#include	<time.h>
+#include	"loc_time.h"
+
+#define	DATE_STR	"??? ??? ?? ??:??:?? ????\n"
+
+static char *
+two_digits(register char *pb, int i, int nospace)
+{
+	*pb = (i / 10) % 10 + '0';
+	if (!nospace && *pb == '0') *pb = ' ';
+	pb++;
+	*pb++ = (i % 10) + '0';
+	return ++pb;
+}
+
+static char *
+four_digits(register char *pb, int i)
+{
+	i %= 10000;
+	*pb++ = (i / 1000) + '0';
+	i %= 1000;
+	*pb++ = (i / 100) + '0';
+	i %= 100;
+	*pb++ = (i / 10) + '0';
+	*pb++ = (i % 10) + '0';
+	return ++pb;
+}
+
+char *asctime(const struct tm *timeptr)
+{
+	static char buf[26];
+	register char *pb = buf;
+	register const char *ps;
+	register int n;
+
+	strcpy(pb, DATE_STR);
+	ps = _days[timeptr->tm_wday];
+	n = ABB_LEN;
+	while(--n >= 0) *pb++ = *ps++;
+	pb++;
+	ps = _months[timeptr->tm_mon];
+	n = ABB_LEN;
+	while(--n >= 0) *pb++ = *ps++;
+	pb++;
+	pb = two_digits(
+		    two_digits(
+			    two_digits(two_digits(pb, timeptr->tm_mday, 0)
+					, timeptr->tm_hour, 1)
+			    , timeptr->tm_min, 1)
+		    , timeptr->tm_sec, 1);
+
+	four_digits(pb, timeptr->tm_year + 1900);
+	return buf;
+}
Index: /trunk/minix/lib/ansi/assert.c
===================================================================
--- /trunk/minix/lib/ansi/assert.c	(revision 9)
+++ /trunk/minix/lib/ansi/assert.c	(revision 9)
@@ -0,0 +1,14 @@
+/*
+ * assert.c - diagnostics
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/assert.c,v 1.1.1.1 2005/04/21 14:56:04 beng Exp $ */
+
+#include	<assert.h>
+#include	<stdio.h>
+#include	<stdlib.h>
+
+void __bad_assertion(const char *mess) {
+
+	fputs(mess, stderr);
+	abort();
+}
Index: /trunk/minix/lib/ansi/atexit.c
===================================================================
--- /trunk/minix/lib/ansi/atexit.c	(revision 9)
+++ /trunk/minix/lib/ansi/atexit.c	(revision 9)
@@ -0,0 +1,17 @@
+/* $Header: /cvsup/minix/src/lib/ansi/atexit.c,v 1.1.1.1 2005/04/21 14:56:04 beng Exp $ */
+
+#include	<stdlib.h>
+
+#define	NEXITS	32
+
+extern void (*__functab[NEXITS])(void);
+extern int __funccnt;
+
+int
+atexit(void (*func)(void))
+{
+	if (__funccnt >= NEXITS)
+		return 1;
+	__functab[__funccnt++] = func;
+	return 0;
+}
Index: /trunk/minix/lib/ansi/atof.c
===================================================================
--- /trunk/minix/lib/ansi/atof.c	(revision 9)
+++ /trunk/minix/lib/ansi/atof.c	(revision 9)
@@ -0,0 +1,19 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/atof.c,v 1.1.1.1 2005/04/21 14:56:04 beng Exp $ */
+
+#include	<stdlib.h>
+#include	<errno.h>
+
+double
+atof(const char *nptr)
+{
+	double d;
+	int e = errno;
+
+	d = strtod(nptr, (char **) NULL);
+	errno = e;
+	return d;
+}
Index: /trunk/minix/lib/ansi/atoi.c
===================================================================
--- /trunk/minix/lib/ansi/atoi.c	(revision 9)
+++ /trunk/minix/lib/ansi/atoi.c	(revision 9)
@@ -0,0 +1,14 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/atoi.c,v 1.1.1.1 2005/04/21 14:56:04 beng Exp $ */
+
+#include	<ctype.h>
+#include	<stdlib.h>
+
+int
+atoi(register const char *nptr)
+{
+	return strtol(nptr, (char **) NULL, 10);
+}
Index: /trunk/minix/lib/ansi/atol.c
===================================================================
--- /trunk/minix/lib/ansi/atol.c	(revision 9)
+++ /trunk/minix/lib/ansi/atol.c	(revision 9)
@@ -0,0 +1,30 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/atol.c,v 1.1.1.1 2005/04/21 14:56:04 beng Exp $ */
+
+#include	<ctype.h>
+#include	<stdlib.h>
+
+/* We do not use strtol here for backwards compatibility in behaviour on
+   overflow.
+*/
+long
+atol(register const char *nptr)
+{
+	long total = 0;
+	int minus = 0;
+
+	while (isspace(*nptr)) nptr++;
+	if (*nptr == '+') nptr++;
+	else if (*nptr == '-') {
+		minus = 1;
+		nptr++;
+	}
+	while (isdigit(*nptr)) {
+		total *= 10;
+		total += (*nptr++ - '0');
+	}
+	return minus ? -total : total;
+}
Index: /trunk/minix/lib/ansi/bsearch.c
===================================================================
--- /trunk/minix/lib/ansi/bsearch.c	(revision 9)
+++ /trunk/minix/lib/ansi/bsearch.c	(revision 9)
@@ -0,0 +1,28 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/bsearch.c,v 1.1.1.1 2005/04/21 14:56:04 beng Exp $ */
+
+#include	<stdlib.h>
+
+void *
+bsearch(register const void *key, register const void *base,
+	register size_t nmemb, register size_t size,
+	int (*compar)(const void *, const void *))
+{
+	register const void *mid_point;
+	register int  cmp;
+
+	while (nmemb > 0) {
+		mid_point = (char *)base + size * (nmemb >> 1);
+		if ((cmp = (*compar)(key, mid_point)) == 0)
+			return (void *)mid_point;
+		if (cmp >= 0) {
+			base  = (char *)mid_point + size;
+			nmemb = (nmemb - 1) >> 1;
+		} else
+			nmemb >>= 1;
+	}
+	return (void *)NULL;
+}
Index: /trunk/minix/lib/ansi/calloc.c
===================================================================
--- /trunk/minix/lib/ansi/calloc.c	(revision 9)
+++ /trunk/minix/lib/ansi/calloc.c	(revision 9)
@@ -0,0 +1,19 @@
+/* $Header: /cvsup/minix/src/lib/ansi/calloc.c,v 1.1.1.1 2005/04/21 14:56:04 beng Exp $ */
+#include	<stdlib.h>
+
+#define ALIGN(x)	(((x) + (sizeof(size_t) - 1)) & ~(sizeof(size_t) - 1))
+
+void *
+calloc(size_t nelem, size_t elsize)
+{
+	register char *p;
+	register size_t *q;
+	size_t size = ALIGN(nelem * elsize);
+
+	p = malloc(size);
+	if (p == NULL) return NULL;
+	q = (size_t *) (p + size);
+	while ((char *) q > p) *--q = 0;
+	return p;
+}
+
Index: /trunk/minix/lib/ansi/chartab.c
===================================================================
--- /trunk/minix/lib/ansi/chartab.c	(revision 9)
+++ /trunk/minix/lib/ansi/chartab.c	(revision 9)
@@ -0,0 +1,261 @@
+#include	<ctype.h>
+
+char __ctype[] = {
+0,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C|_S,
+_C|_S,
+_C|_S,
+_C|_S,
+_C|_S,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_C,
+_S,
+_P,
+_P,
+_P,
+_P,
+_P,
+_P,
+_P,
+_P,
+_P,
+_P,
+_P,
+_P,
+_P,
+_P,
+_P,
+_N,
+_N,
+_N,
+_N,
+_N,
+_N,
+_N,
+_N,
+_N,
+_N,
+_P,
+_P,
+_P,
+_P,
+_P,
+_P,
+_P,
+_U|_X,
+_U|_X,
+_U|_X,
+_U|_X,
+_U|_X,
+_U|_X,
+_U,
+_U,
+_U,
+_U,
+_U,
+_U,
+_U,
+_U,
+_U,
+_U,
+_U,
+_U,
+_U,
+_U,
+_U,
+_U,
+_U,
+_U,
+_U,
+_U,
+_P,
+_P,
+_P,
+_P,
+_P,
+_P,
+_L|_X,
+_L|_X,
+_L|_X,
+_L|_X,
+_L|_X,
+_L|_X,
+_L,
+_L,
+_L,
+_L,
+_L,
+_L,
+_L,
+_L,
+_L,
+_L,
+_L,
+_L,
+_L,
+_L,
+_L,
+_L,
+_L,
+_L,
+_L,
+_L,
+_P,
+_P,
+_P,
+_P,
+_C,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+};
Index: /trunk/minix/lib/ansi/clock.c
===================================================================
--- /trunk/minix/lib/ansi/clock.c	(revision 9)
+++ /trunk/minix/lib/ansi/clock.c	(revision 9)
@@ -0,0 +1,15 @@
+/*
+ * clock - determine the processor time used
+ */
+
+#define times _times
+#include <time.h>
+#include <sys/times.h>
+
+clock_t clock(void)
+{
+	struct tms tms;
+
+	times(&tms);
+	return tms.tms_utime;
+}
Index: /trunk/minix/lib/ansi/ctime.c
===================================================================
--- /trunk/minix/lib/ansi/ctime.c	(revision 9)
+++ /trunk/minix/lib/ansi/ctime.c	(revision 9)
@@ -0,0 +1,12 @@
+/*
+ * ctime - convers the calendar time to a string
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/ctime.c,v 1.1.1.1 2005/04/21 14:56:04 beng Exp $ */
+
+#include	<time.h>
+
+char *
+ctime(const time_t *timer)
+{
+	return asctime(localtime(timer));
+}
Index: /trunk/minix/lib/ansi/difftime.c
===================================================================
--- /trunk/minix/lib/ansi/difftime.c	(revision 9)
+++ /trunk/minix/lib/ansi/difftime.c	(revision 9)
@@ -0,0 +1,17 @@
+/*
+ * difftime - compute the difference between two calendar times
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/difftime.c,v 1.1.1.1 2005/04/21 14:56:04 beng Exp $ */
+
+#include	<time.h>
+
+double
+difftime(time_t time1, time_t time0)
+{
+	/* be careful: time_t may be unsigned */
+	if ((time_t)-1 > 0 && time0 > time1) {
+		return - (double) (time0 - time1);
+	} else {
+		return (double)(time1 - time0);
+	}
+}
Index: /trunk/minix/lib/ansi/div.c
===================================================================
--- /trunk/minix/lib/ansi/div.c	(revision 9)
+++ /trunk/minix/lib/ansi/div.c	(revision 9)
@@ -0,0 +1,31 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/div.c,v 1.1.1.1 2005/04/21 14:56:04 beng Exp $ */
+
+#include	<stdlib.h>
+
+static int tmp = -1;
+
+div_t
+div(register int numer, register int denom)
+{
+	div_t r;
+
+	/* The assignment of tmp should not be optimized !! */
+	if (tmp == -1) {
+		tmp = (tmp / 2 == 0);
+	}
+	if (numer == 0) {
+		r.quot = numer / denom;		/* might trap if denom == 0 */
+		r.rem = numer % denom;
+	} else if ( !tmp && ((numer < 0) != (denom < 0))) {
+		r.quot = (numer / denom) + 1;
+		r.rem = numer - (numer / denom + 1) * denom;
+	} else {
+		r.quot = numer / denom;
+		r.rem = numer % denom;
+	}
+	return r;
+}
Index: /trunk/minix/lib/ansi/errlist.c
===================================================================
--- /trunk/minix/lib/ansi/errlist.c	(revision 9)
+++ /trunk/minix/lib/ansi/errlist.c	(revision 9)
@@ -0,0 +1,90 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/errlist.c,v 1.4 2006/02/17 13:44:48 philip Exp $ */
+
+#include	<errno.h>
+
+static const char unknown[] = "Unknown error";
+
+const char *_sys_errlist[] = {
+        "Error 0",			/* EGENERIC */
+        "Not owner",			/* EPERM */
+        "No such file or directory",	/* ENOENT */
+        "No such process",		/* ESRCH */
+        "Interrupted system call",	/* EINTR */
+        "I/O error",			/* EIO */
+        "No such device or address",	/* ENXIO */
+        "Arg list too long",		/* E2BIG */
+        "Exec format error",		/* ENOEXEC */
+        "Bad file number",		/* EBADF */
+        "No children",			/* ECHILD */
+        "Resource temporarily unavailable",/* EAGAIN */
+        "Not enough core",		/* ENOMEM */
+        "Permission denied",		/* EACCES */
+        "Bad address",			/* EFAULT */
+        "Block device required",	/* ENOTBLK */
+        "Resource busy",		/* EBUSY */
+        "File exists",			/* EEXIST */
+        "Cross-device link",		/* EXDEV */
+        "No such device",		/* ENODEV */
+        "Not a directory",		/* ENOTDIR */
+        "Is a directory",		/* EISDIR */
+        "Invalid argument",		/* EINVAL */
+        "File table overflow",		/* ENFILE */
+        "Too many open files",		/* EMFILE */
+        "Not a typewriter",		/* ENOTTY */
+        "Text file busy",		/* ETXTBSY */
+        "File too large",		/* EFBIG */
+        "No space left on device",	/* ENOSPC */
+        "Illegal seek",			/* ESPIPE */
+        "Read-only file system",	/* EROFS */
+        "Too many links",		/* EMLINK */
+        "Broken pipe",			/* EPIPE */
+        "Math argument",		/* EDOM */
+        "Result too large",		/* ERANGE */
+	"Resource deadlock avoided",	/* EDEADLK */
+	"File name too long",		/* ENAMETOOLONG */
+	"No locks available",		/* ENOLCK */
+	"Function not implemented",	/* ENOSYS */
+	"Directory not empty",		/* ENOTEMPTY */
+	"Too many levels of symbolic links",	/* ELOOP */
+	unknown,			/* 41 */
+	unknown,			/* 42 */
+	unknown,			/* 43 */
+	unknown,			/* 44 */
+	unknown,			/* 45 */
+	unknown,			/* 46 */
+	unknown,			/* 47 */
+	unknown,			/* 48 */
+	unknown,			/* 49 */
+	"Invalid packet size",		/* EPACKSIZE */
+	"Not enough buffers left",	/* EOUTOFBUFS */
+	"Illegal ioctl for device",	/* EBADIOCTL */
+	"Bad mode for ioctl",		/* EBADMODE */
+	"Would block",			/* EWOULDBLOCK */
+	"Bad destination address",	/* EBADDEST */
+	"Destination not reachable",	/* EDSTNOTRCH */
+	"Already connected",		/* EISCONN */
+	"Address in use",		/* EADDRINUSE */
+	"Connection refused",		/* ECONNREFUSED */
+	"Connection reset",		/* ECONNRESET */
+	"Connection timed out",		/* ETIMEDOUT */
+	"Urgent data present",		/* EURG */
+	"No urgent data present",	/* ENOURG */
+	"No connection",		/* ENOTCONN */
+	"Already shutdown",		/* ESHUTDOWN */
+	"No such connection",		/* ENOCONN */
+	"Address family not supported",	/* EAFNOSUPPORT */
+	"Protocol not supported by AF",	/* EPROTONOSUPPORT */
+	"Protocol wrong type for socket", /* EPROTOTYPE */
+	"Operation in progress",	/* EINPROGRESS */
+	"Address not available",	/* EADDRNOTAVAIL */
+	"Connection already in progress", /* EALREADY */
+	"Message too long",		/* EMSGSIZE */
+	"Socket operation on non-socket", /* ENOTSOCK */
+	"Protocol not available",	/* ENOPROTOOPT */
+};
+
+const int _sys_nerr = sizeof(_sys_errlist) / sizeof(_sys_errlist[0]);
Index: /trunk/minix/lib/ansi/exit.c
===================================================================
--- /trunk/minix/lib/ansi/exit.c	(revision 9)
+++ /trunk/minix/lib/ansi/exit.c	(revision 9)
@@ -0,0 +1,36 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/exit.c,v 1.1.1.1 2005/04/21 14:56:04 beng Exp $ */
+
+#include	<stdio.h>
+#include	<stdlib.h>
+
+#define	NEXITS	32
+
+void (*__functab[NEXITS])(void);
+int __funccnt = 0;
+
+extern void _exit(int);
+
+/* only flush output buffers when necessary */
+int (*_clean)(void) = NULL;
+
+static void
+_calls(void)
+{
+	register int i = __funccnt;
+	
+	/* "Called in reversed order of their registration" */
+	while (--i >= 0)
+		(*__functab[i])();
+}
+
+void
+exit(int status)
+{
+	_calls();
+	if (_clean) _clean();
+	_exit(status) ;
+}
Index: /trunk/minix/lib/ansi/ext_comp.c
===================================================================
--- /trunk/minix/lib/ansi/ext_comp.c	(revision 9)
+++ /trunk/minix/lib/ansi/ext_comp.c	(revision 9)
@@ -0,0 +1,743 @@
+/*
+  (c) copyright 1989 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Id: ext_comp.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+/* extended precision arithmetic for the strtod() and cvt() routines */
+
+/* This may require some more work when long doubles get bigger than 8
+   bytes. In this case, these routines may become obsolete. ???
+*/
+
+#include	"ext_fmt.h"
+#include	<float.h>
+#include	<errno.h>
+#include	<ctype.h>
+
+static int b64_add(struct mantissa *e1, struct mantissa *e2);
+static b64_sft(struct mantissa *e1, int n);
+
+static
+mul_ext(struct EXTEND *e1, struct EXTEND *e2, struct EXTEND *e3)
+{
+	/*	Multiply the extended numbers e1 and e2, and put the
+		result in e3.
+	*/
+	register int	i,j;		/* loop control	*/
+	unsigned short	mp[4];
+	unsigned short	mc[4];
+	unsigned short	result[8];	/* result */
+
+	register unsigned short *pres;
+
+	/* first save the sign (XOR)			*/
+	e3->sign = e1->sign ^ e2->sign;
+
+	/* compute new exponent */
+	e3->exp = e1->exp + e2->exp + 1;
+
+	/* check for overflow/underflow	??? */
+
+	/* 128 bit multiply of mantissas	*/
+
+	/* assign unknown long formats		*/
+	/* to known unsigned word formats	*/
+	mp[0] = e1->m1 >> 16;
+	mp[1] = (unsigned short) e1->m1;
+	mp[2] = e1->m2 >> 16;
+	mp[3] = (unsigned short) e1->m2;
+	mc[0] = e2->m1 >> 16;
+	mc[1] = (unsigned short) e2->m1;
+	mc[2] = e2->m2 >> 16;
+	mc[3] = (unsigned short) e2->m2;
+	for (i = 8; i--;) {
+		result[i] = 0;
+	}
+	/*
+	 *	fill registers with their components
+	 */
+	for(i=4, pres = &result[4];i--;pres--) if (mp[i]) {
+		unsigned short k = 0;
+		unsigned long mpi = mp[i];
+		for(j=4;j--;) {
+			unsigned long tmp = (unsigned long)pres[j] + k;
+			if (mc[j]) tmp += mpi * mc[j];
+			pres[j] = tmp;
+			k = tmp >> 16;
+		}
+		pres[-1] = k;
+	}
+
+	if (! (result[0] & 0x8000)) {
+		e3->exp--;
+		for (i = 0; i <= 3; i++) {
+			result[i] <<= 1;
+			if (result[i+1]&0x8000) result[i] |= 1;
+		}
+		result[4] <<= 1;
+	}	
+	/*
+	 *	combine the registers to a total
+	 */
+	e3->m1 = ((unsigned long)(result[0]) << 16) + result[1];
+	e3->m2 = ((unsigned long)(result[2]) << 16) + result[3];
+	if (result[4] & 0x8000) {
+		if (++e3->m2 == 0) {
+			if (++e3->m1 == 0) {
+				e3->m1 = 0x80000000;
+				e3->exp++;
+			}
+		}
+	}
+}
+
+static
+add_ext(struct EXTEND *e1, struct EXTEND *e2, struct EXTEND *e3)
+{
+	/*	Add two extended numbers e1 and e2, and put the result
+		in e3
+	*/
+	struct EXTEND ce2;
+	int diff;
+
+	if ((e2->m1 | e2->m2) == 0L) {
+		*e3 = *e1;
+		return;
+	}
+	if ((e1->m1 | e1->m2) == 0L) {
+		*e3 = *e2;
+		return;
+	}
+	ce2 = *e2;
+	*e3 = *e1;
+	e1 = &ce2;
+
+	/* adjust mantissas to equal power */
+	diff = e3->exp - e1->exp;
+	if (diff < 0) {
+		diff = -diff;
+		e3->exp += diff;
+		b64_sft(&(e3->mantissa), diff);
+	}
+	else if (diff > 0) {
+		e1->exp += diff;
+		b64_sft(&(e1->mantissa), diff);
+	}
+	if (e1->sign != e3->sign) {
+		/* e3 + e1 = e3 - (-e1) */
+		if (e1->m1 > e3->m1 ||
+                    (e1->m1 == e3->m1 && e1->m2 > e3->m2)) {
+                	/*      abs(e1) > abs(e3) */
+                	if (e3->m2 > e1->m2) {
+                        	e1->m1 -= 1;    /* carry in */
+                	}
+                	e1->m1 -= e3->m1;
+                	e1->m2 -= e3->m2;
+                	*e3 = *e1;
+        	}
+        	else {
+                	if (e1->m2 > e3->m2)
+                        	e3->m1 -= 1;    /* carry in */
+                	e3->m1 -= e1->m1;
+                	e3->m2 -= e1->m2;
+        	}
+	}
+	else {
+		if (b64_add(&e3->mantissa,&e1->mantissa)) {/* addition carry */
+			b64_sft(&e3->mantissa,1);/* shift mantissa one bit RIGHT */
+			e3->m1 |= 0x80000000L;	/* set max bit	*/
+			e3->exp++;		/* increase the exponent */
+		}
+	}
+	if ((e3->m2 | e3->m1) != 0L) {
+		/* normalize */
+		if (e3->m1 == 0L) {
+			e3->m1 = e3->m2; e3->m2 = 0L; e3->exp -= 32;
+		}
+		if (!(e3->m1 & 0x80000000)) {
+			unsigned long l = 0x40000000;
+			int cnt = -1;
+
+			while (! (l & e3->m1)) {
+				l >>= 1; cnt--;
+			}
+			e3->exp += cnt;
+			b64_sft(&(e3->mantissa), cnt);
+		}
+	}
+}
+
+static int
+cmp_ext(struct EXTEND *e1, struct EXTEND *e2)
+{
+        struct EXTEND tmp; 
+         
+        e2->sign = ! e2->sign; 
+        add_ext(e1, e2, &tmp);  
+        e2->sign = ! e2->sign;
+        if (tmp.m1 == 0 && tmp.m2 == 0) return 0; 
+        if (tmp.sign) return -1;
+        return 1;
+}
+
+static
+b64_sft(struct mantissa *e1, int n)
+{
+	if (n > 0) {
+		if (n > 63) {
+			e1->l_32 = 0;
+			e1->h_32 = 0;
+			return;
+		}
+		if (n >= 32) {
+			e1->l_32 = e1->h_32;
+			e1->h_32 = 0;
+			n -= 32;
+		}
+		if (n > 0) {
+			e1->l_32 >>= n;
+			if (e1->h_32 != 0) {
+				e1->l_32 |= (e1->h_32 << (32 - n));
+				e1->h_32 >>= n;
+			}
+		}
+		return;
+	}
+	n = -n;
+	if (n > 0) {
+		if (n > 63) {
+			e1->l_32 = 0;
+			e1->h_32 = 0;
+			return;
+		}
+		if (n >= 32) {
+			e1->h_32 = e1->l_32;
+			e1->l_32 = 0;
+			n -= 32;
+		}
+		if (n > 0) {
+			e1->h_32 <<= n;
+			if (e1->l_32 != 0) {
+				e1->h_32 |= (e1->l_32 >> (32 - n));
+				e1->l_32 <<= n;
+			}
+		}
+	}
+}
+
+static int
+b64_add(struct mantissa *e1, struct mantissa *e2)
+		/*
+		 * pointers to 64 bit 'registers'
+		 */
+{
+	register int	overflow;
+	int		carry;
+
+			/* add higher pair of 32 bits */
+	overflow = ((unsigned long) 0xFFFFFFFF - e1->h_32 < e2->h_32);
+	e1->h_32 += e2->h_32;
+
+			/* add lower pair of 32 bits */
+	carry = ((unsigned long) 0xFFFFFFFF - e1->l_32 < e2->l_32);
+	e1->l_32 += e2->l_32;
+	if ((carry) && (++e1->h_32 == 0))
+		return(1);		/* had a 64 bit overflow */
+	else
+		return(overflow);	/* return status from higher add */
+}
+
+/* The following tables can be computed with the following bc(1)
+   program:
+
+obase=16
+scale=0
+define t(x){
+	auto a, b, c
+	a=2;b=1;c=2^32;n=1
+	while(a<x) {
+		b=a;n+=n;a*=a
+	}
+	n/=2
+	a=b
+	while(b<x) {
+		a=b;b*=c;n+=32
+	}
+	n-=32
+	b=a
+	while(a<x) {
+		b=a;a+=a;n+=1
+	}
+	n-=1
+	x*=16^16
+	b=x%a
+	x/=a
+	if(a<=(2*b)) x+=1
+	obase=10
+	n
+	obase=16
+	return(x)
+}
+for (i=1;i<28;i++) {
+	t(10^i)
+}
+0
+for (i=1;i<20;i++) {
+	t(10^(28*i))
+}
+0
+define r(x){
+	auto a, b, c
+	a=2;b=1;c=2^32;n=1
+	while(a<x) {
+		b=a;n+=n;a*=a
+	}
+	n/=2
+	a=b
+	while(b<x) {
+		a=b;b*=c;n+=32
+	}
+	n-=32
+	b=a
+	while(a<x) {
+		b=a;a+=a;n+=1
+	}
+	a=b
+	a*=16^16
+	b=a%x
+	a/=x
+	if(x<=(2*b)) a+=1
+	obase=10
+	-n
+	obase=16
+	return(a)
+}
+for (i=1;i<28;i++) {
+	r(10^i)
+}
+0
+for (i=1;i<20;i++) {
+	r(10^(28*i))
+}
+0
+
+*/
+static struct EXTEND ten_powers[] = {	/* representation of 10 ** i */
+	{ 0,	0,	0x80000000,	0 },
+	{ 0,	3,	0xA0000000,	0 },
+	{ 0,	6,	0xC8000000,	0 },
+	{ 0,	9,	0xFA000000,	0 },
+	{ 0,	13,	0x9C400000,	0 },
+	{ 0,	16,	0xC3500000,	0 },
+	{ 0,	19,	0xF4240000,	0 },
+	{ 0,	23,	0x98968000,	0 },
+	{ 0,	26,	0xBEBC2000,	0 },
+	{ 0,	29,	0xEE6B2800,	0 },
+	{ 0,	33,	0x9502F900,	0 },
+	{ 0,	36,	0xBA43B740,	0 },
+	{ 0,	39,	0xE8D4A510,	0 },
+	{ 0,	43,	0x9184E72A,	0 },
+	{ 0,	46,	0xB5E620F4,	0x80000000 },
+	{ 0,	49,	0xE35FA931,	0xA0000000 },
+	{ 0,	53,	0x8E1BC9BF,	0x04000000 },
+	{ 0,	56,	0xB1A2BC2E,	0xC5000000 },
+	{ 0,	59,	0xDE0B6B3A,	0x76400000 },
+	{ 0,	63,	0x8AC72304,	0x89E80000 },
+	{ 0,	66,	0xAD78EBC5,	0xAC620000 },
+	{ 0,	69,	0xD8D726B7,	0x177A8000 },
+	{ 0,	73,	0x87867832,	0x6EAC9000 },
+	{ 0,	76,	0xA968163F,	0x0A57B400 },
+	{ 0,	79,	0xD3C21BCE,	0xCCEDA100 },
+	{ 0,	83,	0x84595161,	0x401484A0 },
+	{ 0,	86,	0xA56FA5B9,	0x9019A5C8 },
+	{ 0,	89,	0xCECB8F27,	0xF4200F3A }
+};
+static struct EXTEND big_ten_powers[] = {  /* representation of 10 ** (28*i) */
+	{ 0,	0,	0x80000000,	0 },
+	{ 0,	93,	0x813F3978,	0xF8940984 },
+	{ 0,	186,	0x82818F12,	0x81ED44A0 },
+	{ 0,	279,	0x83C7088E,	0x1AAB65DB },
+	{ 0,	372,	0x850FADC0,	0x9923329E },
+	{ 0,	465,	0x865B8692,	0x5B9BC5C2 },
+	{ 0,	558,	0x87AA9AFF,	0x79042287 },
+	{ 0,	651,	0x88FCF317,	0xF22241E2 },
+	{ 0,	744,	0x8A5296FF,	0xE33CC930 },
+	{ 0,	837,	0x8BAB8EEF,	0xB6409C1A },
+	{ 0,	930,	0x8D07E334,	0x55637EB3 },
+	{ 0,	1023,	0x8E679C2F,	0x5E44FF8F },
+	{ 0,	1116,	0x8FCAC257,	0x558EE4E6 },
+	{ 0,	1209,	0x91315E37,	0xDB165AA9 },
+	{ 0,	1302,	0x929B7871,	0xDE7F22B9 },
+	{ 0,	1395,	0x940919BB,	0xD4620B6D },
+	{ 0,	1488,	0x957A4AE1,	0xEBF7F3D4 },
+	{ 0,	1581,	0x96EF14C6,	0x454AA840 },
+	{ 0,	1674,	0x98678061,	0x27ECE4F5 },
+	{ 0,	1767,	0x99E396C1,	0x3A3ACFF2 }
+};
+
+static struct EXTEND r_ten_powers[] = { /* representation of 10 ** -i */
+	{ 0,	0,	0x80000000,	0 },
+	{ 0,	-4,	0xCCCCCCCC,	0xCCCCCCCD },
+	{ 0,	-7,	0xA3D70A3D,	0x70A3D70A },
+	{ 0,	-10,	0x83126E97,	0x8D4FDF3B },
+	{ 0,	-14,	0xD1B71758,	0xE219652C },
+	{ 0,	-17,	0xA7C5AC47,	0x1B478423 },
+	{ 0,	-20,	0x8637BD05,	0xAF6C69B6 },
+	{ 0,	-24,	0xD6BF94D5,	0xE57A42BC },
+	{ 0,	-27,	0xABCC7711,	0x8461CEFD },
+	{ 0,	-30,	0x89705F41,	0x36B4A597 },
+	{ 0,	-34,	0xDBE6FECE,	0xBDEDD5BF },
+	{ 0,	-37,	0xAFEBFF0B,	0xCB24AAFF },
+	{ 0,	-40,	0x8CBCCC09,	0x6F5088CC },
+	{ 0,	-44,	0xE12E1342,	0x4BB40E13 },
+	{ 0,	-47,	0xB424DC35,	0x095CD80F },
+	{ 0,	-50,	0x901D7CF7,	0x3AB0ACD9 },
+	{ 0,	-54,	0xE69594BE,	0xC44DE15B },
+	{ 0,	-57,	0xB877AA32,	0x36A4B449 },
+	{ 0,	-60,	0x9392EE8E,	0x921D5D07 },
+	{ 0,	-64,	0xEC1E4A7D,	0xB69561A5 },
+	{ 0,	-67,	0xBCE50864,	0x92111AEB },
+	{ 0,	-70,	0x971DA050,	0x74DA7BEF },
+	{ 0,	-74,	0xF1C90080,	0xBAF72CB1 },
+	{ 0,	-77,	0xC16D9A00,	0x95928A27 },
+	{ 0,	-80,	0x9ABE14CD,	0x44753B53 },
+	{ 0,	-84,	0xF79687AE,	0xD3EEC551 },
+	{ 0,	-87,	0xC6120625,	0x76589DDB },
+	{ 0,	-90,	0x9E74D1B7,	0x91E07E48 }
+};
+
+static struct EXTEND r_big_ten_powers[] = { /* representation of 10 ** -(28*i) */
+	{ 0,	0,	0x80000000,	0 },
+	{ 0,	-94,	0xFD87B5F2,	0x8300CA0E },
+	{ 0,	-187,	0xFB158592,	0xBE068D2F },
+	{ 0,	-280,	0xF8A95FCF,	0x88747D94 },
+	{ 0,	-373,	0xF64335BC,	0xF065D37D },
+	{ 0,	-466,	0xF3E2F893,	0xDEC3F126 },
+	{ 0,	-559,	0xF18899B1,	0xBC3F8CA2 },
+	{ 0,	-652,	0xEF340A98,	0x172AACE5 },
+	{ 0,	-745,	0xECE53CEC,	0x4A314EBE },
+	{ 0,	-838,	0xEA9C2277,	0x23EE8BCB },
+	{ 0,	-931,	0xE858AD24,	0x8F5C22CA },
+	{ 0,	-1024,	0xE61ACF03,	0x3D1A45DF },
+	{ 0,	-1117,	0xE3E27A44,	0x4D8D98B8 },
+	{ 0,	-1210,	0xE1AFA13A,	0xFBD14D6E },
+	{ 0,	-1303,	0xDF82365C,	0x497B5454 },
+	{ 0,	-1396,	0xDD5A2C3E,	0xAB3097CC },
+	{ 0,	-1489,	0xDB377599,	0xB6074245 },
+	{ 0,	-1582,	0xD91A0545,	0xCDB51186 },
+	{ 0,	-1675,	0xD701CE3B,	0xD387BF48 },
+	{ 0,	-1768,	0xD4EEC394,	0xD6258BF8 }
+};
+
+#define	TP	(int)(sizeof(ten_powers)/sizeof(ten_powers[0]))
+#define BTP	(int)(sizeof(big_ten_powers)/sizeof(big_ten_powers[0]))
+#define MAX_EXP	(TP * BTP - 1)
+
+static
+add_exponent(struct EXTEND *e, int exp)
+{
+	int neg = exp < 0;
+	int divsz, modsz;
+	struct EXTEND x;
+
+	if (neg) exp = -exp;
+	divsz = exp / TP;
+	modsz = exp % TP;
+	if (neg) {
+		mul_ext(e, &r_ten_powers[modsz], &x);
+		mul_ext(&x, &r_big_ten_powers[divsz], e);
+	}
+	else {
+		mul_ext(e, &ten_powers[modsz], &x);
+		mul_ext(&x, &big_ten_powers[divsz], e);
+	}
+}
+
+_str_ext_cvt(const char *s, char **ss, struct EXTEND *e)
+{
+	/*	Like strtod, but for extended precision */
+	register int	c;
+	int		dotseen = 0;
+	int		digitseen = 0;
+	int		exp = 0;
+
+	if (ss) *ss = (char *)s;
+	while (isspace(*s)) s++;
+
+	e->sign = 0;
+	e->exp = 0;
+	e->m1 = e->m2 = 0;
+
+	c = *s;
+	switch(c) {
+	case '-':
+		e->sign = 1;
+	case '+':
+		s++;
+	}
+	while (c = *s++, isdigit(c) || (c == '.' && ! dotseen++)) {
+		if (c == '.') continue;
+		digitseen = 1;
+		if (e->m1 <= (unsigned long)(0xFFFFFFFF)/10) {
+			struct mantissa	a1;
+
+			a1 = e->mantissa;
+			b64_sft(&(e->mantissa), -3);
+			b64_sft(&a1, -1);
+			b64_add(&(e->mantissa), &a1);
+			a1.h_32 = 0;
+			a1.l_32 = c - '0';
+			b64_add(&(e->mantissa), &a1);
+		}
+		else exp++;
+		if (dotseen) exp--;
+	}
+	if (! digitseen) return;
+
+	if (ss) *ss = (char *)s - 1;
+
+	if (c == 'E' || c == 'e') {
+		int	exp1 = 0;
+		int	sign = 1;
+		int	exp_overflow = 0;
+
+		switch(*s) {
+		case '-':
+			sign = -1;
+		case '+':
+			s++;
+		}
+		if (c = *s, isdigit(c)) {
+			do {
+				int tmp;
+
+				exp1 = 10 * exp1 + (c - '0');
+				if ((tmp = sign * exp1 + exp) > MAX_EXP ||
+				     tmp < -MAX_EXP) {
+					exp_overflow = 1;
+				}
+			} while (c = *++s, isdigit(c));
+			if (ss) *ss = (char *)s;
+		}
+		exp += sign * exp1;
+		if (exp_overflow) {
+			exp = sign * MAX_EXP;
+			if (e->m1 != 0 || e->m2 != 0) errno = ERANGE;
+		}
+	}
+	if (e->m1 == 0 && e->m2 == 0) return;
+	e->exp = 63;
+	while (! (e->m1 & 0x80000000)) {
+		b64_sft(&(e->mantissa),-1);
+		e->exp--;
+	}
+	add_exponent(e, exp);
+}
+
+#include	<math.h>
+
+static
+ten_mult(struct EXTEND *e)
+{
+	struct EXTEND e1 = *e;
+
+	e1.exp++;
+	e->exp += 3;
+	add_ext(e, &e1, e);
+}
+
+#define NDIGITS 128
+#define NSIGNIFICANT 19
+
+char *
+_ext_str_cvt(struct EXTEND *e, int ndigit, int *decpt, int *sign, int ecvtflag)
+{
+	/*	Like cvt(), but for extended precision */
+
+	static char buf[NDIGITS+1];
+	struct EXTEND m;
+	register char *p = buf;
+	register char *pe;
+	int findex = 0;
+
+	if (ndigit < 0) ndigit = 0;
+	if (ndigit > NDIGITS) ndigit = NDIGITS;
+	pe = &buf[ndigit];
+	buf[0] = '\0';
+
+	*sign = 0;
+	if (e->sign) {
+		*sign = 1;
+		e->sign = 0;
+	}
+
+	*decpt = 0;
+	if (e->m1 != 0) {
+		register struct EXTEND *pp = &big_ten_powers[1];
+
+		while(cmp_ext(e,pp) >= 0) {
+			pp++;
+			findex = pp - big_ten_powers;
+			if (findex >= BTP) break;
+		}
+		pp--;
+		findex = pp - big_ten_powers;
+		mul_ext(e,&r_big_ten_powers[findex],e);
+		*decpt += findex * TP;
+		pp = &ten_powers[1];
+		while(pp < &ten_powers[TP] && cmp_ext(e, pp) >= 0) pp++;
+		pp--;
+		findex = pp - ten_powers;
+		*decpt += findex;
+
+		if (cmp_ext(e, &ten_powers[0]) < 0) {
+			pp = &r_big_ten_powers[1];
+			while(cmp_ext(e,pp) < 0) pp++;
+			pp--;
+			findex = pp - r_big_ten_powers;
+			mul_ext(e, &big_ten_powers[findex], e);
+			*decpt -= findex * TP;
+			/* here, value >= 10 ** -28 */
+			ten_mult(e);
+			(*decpt)--;
+			pp = &r_ten_powers[0];
+			while(cmp_ext(e, pp) < 0) pp++;
+			findex = pp - r_ten_powers;
+			mul_ext(e, &ten_powers[findex], e);
+			*decpt -= findex;
+			findex = 0;
+		}
+		(*decpt)++;	/* because now value in [1.0, 10.0) */
+	}
+	if (! ecvtflag) {
+		/* for fcvt() we need ndigit digits behind the dot */
+		pe += *decpt;
+		if (pe > &buf[NDIGITS]) pe = &buf[NDIGITS];
+	}
+	m.exp = -62;
+	m.sign = 0;
+	m.m1 = 0xA0000000;
+	m.m2 = 0;
+	while (p <= pe) {
+		struct EXTEND oneminm;
+
+		if (p - pe > NSIGNIFICANT) {
+			findex = 0;
+			e->m1 = 0;
+		}
+		if (findex) {
+			struct EXTEND tc, oldtc;
+			int count = 0;
+
+			oldtc.exp = 0;
+			oldtc.sign = 0;
+			oldtc.m1 = 0;
+			oldtc.m2 = 0;
+			tc = ten_powers[findex];
+			while (cmp_ext(e, &tc) >= 0) {
+				oldtc = tc;
+				add_ext(&tc, &ten_powers[findex], &tc);
+				count++;
+			}
+			*p++ = count + '0';
+			oldtc.sign = 1;
+			add_ext(e, &oldtc, e);
+			findex--;
+			continue;
+		}
+		if (e->m1) {
+			m.sign = 1;
+			add_ext(&ten_powers[0], &m, &oneminm);
+			m.sign = 0;
+			if (e->exp >= 0) {
+				struct EXTEND x;
+
+				x.m2 = 0; x.exp = e->exp;
+				x.sign = 1;
+				x.m1 = e->m1>>(31-e->exp);
+				*p++ = (x.m1) + '0';
+				x.m1 = x.m1 << (31-e->exp);
+				add_ext(e, &x, e);
+			}
+			else *p++ = '0';
+			/* Check that remainder is still significant */
+			if (cmp_ext(&m, e) > 0 || cmp_ext(e, &oneminm) > 0) {
+				if (e->m1 && e->exp >= -1) *(p-1) += 1;
+				e->m1 = 0;
+				continue;
+			}
+			ten_mult(&m);
+			ten_mult(e);
+		}
+		else *p++ = '0';
+	}
+	if (pe >= buf) {
+		p = pe;
+		*p += 5;	/* round of at the end */
+		while (*p > '9') {
+			*p = '0';
+			if (p > buf) ++*--p;
+			else {
+				*p = '1';
+				++*decpt;
+				if (! ecvtflag) {
+					/* maybe add another digit at the end,
+					   because the point was shifted right
+					*/
+					if (pe > buf) *pe = '0';
+					pe++;
+				}
+			}
+		}
+		*pe = '\0';
+	}
+	return buf;
+}
+
+_dbl_ext_cvt(double value, struct EXTEND *e)
+{
+	/*	Convert double to extended
+	*/
+	int exponent;
+
+	value = frexp(value, &exponent);
+	e->sign = value < 0.0;
+	if (e->sign) value = -value;
+	e->exp = exponent - 1;
+	value *= 4294967296.0;
+	e->m1 = value;
+	value -= e->m1;
+	value *= 4294967296.0;
+	e->m2 = value;
+}
+
+static struct EXTEND max_d;
+
+double
+_ext_dbl_cvt(struct EXTEND *e)
+{
+	/*	Convert extended to double
+	*/
+	double f;
+	int sign = e->sign;
+
+	e->sign = 0;
+	if (e->m1 == 0 && e->m2 == 0) {
+		return 0.0;
+	}
+	if (max_d.exp == 0) {
+		_dbl_ext_cvt(DBL_MAX, &max_d);
+	}
+	if (cmp_ext(&max_d, e) < 0) {
+		f = HUGE_VAL;
+		errno = ERANGE;
+	}
+	else	f = ldexp((double)e->m1*4294967296.0 + (double)e->m2, e->exp-63);
+	if (sign) f = -f;
+	if (f == 0.0 && (e->m1 != 0 || e->m2 != 0)) {
+		errno = ERANGE;
+	}
+	return f;
+}
Index: /trunk/minix/lib/ansi/ext_fmt.h
===================================================================
--- /trunk/minix/lib/ansi/ext_fmt.h	(revision 9)
+++ /trunk/minix/lib/ansi/ext_fmt.h	(revision 9)
@@ -0,0 +1,13 @@
+struct mantissa {
+	unsigned long h_32;
+	unsigned long l_32;
+};
+
+struct EXTEND {
+	short	sign;
+	short	exp;
+	struct mantissa mantissa;
+#define m1 mantissa.h_32
+#define m2 mantissa.l_32
+};
+	
Index: /trunk/minix/lib/ansi/getenv.c
===================================================================
--- /trunk/minix/lib/ansi/getenv.c	(revision 9)
+++ /trunk/minix/lib/ansi/getenv.c	(revision 9)
@@ -0,0 +1,28 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/getenv.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+#include	<stdlib.h>
+
+extern const char ***_penviron;
+
+char *
+getenv(const char *name)
+{
+	register const char **v = *_penviron;
+	register const char *p, *q;
+
+	if (v == NULL || name == NULL)
+		return (char *)NULL;
+	while ((p = *v++) != NULL) {
+		q = name;
+		while (*q && (*q == *p++))
+			q++;
+		if (*q || (*p != '='))
+			continue;
+		return (char *)p + 1;
+	}
+	return (char *)NULL;
+}
Index: /trunk/minix/lib/ansi/gmtime.c
===================================================================
--- /trunk/minix/lib/ansi/gmtime.c	(revision 9)
+++ /trunk/minix/lib/ansi/gmtime.c	(revision 9)
@@ -0,0 +1,41 @@
+/*
+ * gmtime - convert the calendar time into broken down time
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/gmtime.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+#include	<time.h>
+#include	<limits.h>
+#include	"loc_time.h"
+
+struct tm *
+gmtime(register const time_t *timer)
+{
+	static struct tm br_time;
+	register struct tm *timep = &br_time;
+	time_t time = *timer;
+	register unsigned long dayclock, dayno;
+	int year = EPOCH_YR;
+
+	dayclock = (unsigned long)time % SECS_DAY;
+	dayno = (unsigned long)time / SECS_DAY;
+
+	timep->tm_sec = dayclock % 60;
+	timep->tm_min = (dayclock % 3600) / 60;
+	timep->tm_hour = dayclock / 3600;
+	timep->tm_wday = (dayno + 4) % 7;	/* day 0 was a thursday */
+	while (dayno >= YEARSIZE(year)) {
+		dayno -= YEARSIZE(year);
+		year++;
+	}
+	timep->tm_year = year - YEAR0;
+	timep->tm_yday = dayno;
+	timep->tm_mon = 0;
+	while (dayno >= _ytab[LEAPYEAR(year)][timep->tm_mon]) {
+		dayno -= _ytab[LEAPYEAR(year)][timep->tm_mon];
+		timep->tm_mon++;
+	}
+	timep->tm_mday = dayno + 1;
+	timep->tm_isdst = 0;
+
+	return timep;
+}
Index: /trunk/minix/lib/ansi/isalnum.c
===================================================================
--- /trunk/minix/lib/ansi/isalnum.c	(revision 9)
+++ /trunk/minix/lib/ansi/isalnum.c	(revision 9)
@@ -0,0 +1,5 @@
+#include	<ctype.h>
+
+int (isalnum)(int c) {
+	return isalnum(c);
+}
Index: /trunk/minix/lib/ansi/isalpha.c
===================================================================
--- /trunk/minix/lib/ansi/isalpha.c	(revision 9)
+++ /trunk/minix/lib/ansi/isalpha.c	(revision 9)
@@ -0,0 +1,5 @@
+#include	<ctype.h>
+
+int (isalpha)(int c) {
+	return isalpha(c);
+}
Index: /trunk/minix/lib/ansi/isascii.c
===================================================================
--- /trunk/minix/lib/ansi/isascii.c	(revision 9)
+++ /trunk/minix/lib/ansi/isascii.c	(revision 9)
@@ -0,0 +1,5 @@
+#include	<ctype.h>
+
+int (isascii)(int c) {
+	return isascii(c);
+}
Index: /trunk/minix/lib/ansi/iscntrl.c
===================================================================
--- /trunk/minix/lib/ansi/iscntrl.c	(revision 9)
+++ /trunk/minix/lib/ansi/iscntrl.c	(revision 9)
@@ -0,0 +1,5 @@
+#include	<ctype.h>
+
+int (iscntrl)(int c) {
+	return iscntrl(c);
+}
Index: /trunk/minix/lib/ansi/isdigit.c
===================================================================
--- /trunk/minix/lib/ansi/isdigit.c	(revision 9)
+++ /trunk/minix/lib/ansi/isdigit.c	(revision 9)
@@ -0,0 +1,5 @@
+#include	<ctype.h>
+
+int (isdigit)(int c) {
+	return isdigit(c);
+}
Index: /trunk/minix/lib/ansi/isgraph.c
===================================================================
--- /trunk/minix/lib/ansi/isgraph.c	(revision 9)
+++ /trunk/minix/lib/ansi/isgraph.c	(revision 9)
@@ -0,0 +1,5 @@
+#include	<ctype.h>
+
+int (isgraph)(int c) {
+	return isgraph(c);
+}
Index: /trunk/minix/lib/ansi/islower.c
===================================================================
--- /trunk/minix/lib/ansi/islower.c	(revision 9)
+++ /trunk/minix/lib/ansi/islower.c	(revision 9)
@@ -0,0 +1,5 @@
+#include	<ctype.h>
+
+int (islower)(int c) {
+	return islower(c);
+}
Index: /trunk/minix/lib/ansi/isprint.c
===================================================================
--- /trunk/minix/lib/ansi/isprint.c	(revision 9)
+++ /trunk/minix/lib/ansi/isprint.c	(revision 9)
@@ -0,0 +1,5 @@
+#include	<ctype.h>
+
+int (isprint)(int c) {
+	return isprint(c);
+}
Index: /trunk/minix/lib/ansi/ispunct.c
===================================================================
--- /trunk/minix/lib/ansi/ispunct.c	(revision 9)
+++ /trunk/minix/lib/ansi/ispunct.c	(revision 9)
@@ -0,0 +1,5 @@
+#include	<ctype.h>
+
+int (ispunct)(int c) {
+	return ispunct(c);
+}
Index: /trunk/minix/lib/ansi/isspace.c
===================================================================
--- /trunk/minix/lib/ansi/isspace.c	(revision 9)
+++ /trunk/minix/lib/ansi/isspace.c	(revision 9)
@@ -0,0 +1,5 @@
+#include	<ctype.h>
+
+int (isspace)(int c) {
+	return isspace(c);
+}
Index: /trunk/minix/lib/ansi/isupper.c
===================================================================
--- /trunk/minix/lib/ansi/isupper.c	(revision 9)
+++ /trunk/minix/lib/ansi/isupper.c	(revision 9)
@@ -0,0 +1,5 @@
+#include	<ctype.h>
+
+int (isupper)(int c) {
+	return isupper(c);
+}
Index: /trunk/minix/lib/ansi/isxdigit.c
===================================================================
--- /trunk/minix/lib/ansi/isxdigit.c	(revision 9)
+++ /trunk/minix/lib/ansi/isxdigit.c	(revision 9)
@@ -0,0 +1,5 @@
+#include	<ctype.h>
+
+int (isxdigit)(int c) {
+	return isxdigit(c);
+}
Index: /trunk/minix/lib/ansi/labs.c
===================================================================
--- /trunk/minix/lib/ansi/labs.c	(revision 9)
+++ /trunk/minix/lib/ansi/labs.c	(revision 9)
@@ -0,0 +1,13 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/labs.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+#include	<stdlib.h>
+
+long
+labs(register long l)
+{
+	return l >= 0 ? l : -l;
+}
Index: /trunk/minix/lib/ansi/ldiv.c
===================================================================
--- /trunk/minix/lib/ansi/ldiv.c	(revision 9)
+++ /trunk/minix/lib/ansi/ldiv.c	(revision 9)
@@ -0,0 +1,31 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/ldiv.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+#include	<stdlib.h>
+
+static long tmp = -1;
+
+ldiv_t
+ldiv(register long numer, register long denom)
+{
+	ldiv_t r;
+
+	/* The assignment of tmp should not be optimized !! */
+	if (tmp == -1) {
+		tmp = (tmp / 2 == 0);
+	}
+	if (numer == 0) {
+		r.quot = numer / denom;		/* might trap if denom == 0 */
+		r.rem = numer % denom;
+	} else if ( !tmp && ((numer < 0) != (denom < 0))) {
+		r.quot = (numer / denom) + 1;
+		r.rem = numer - (numer / denom + 1) * denom;
+	} else {
+		r.quot = numer / denom;
+		r.rem = numer % denom;
+	}
+	return r;
+}
Index: /trunk/minix/lib/ansi/loc_time.h
===================================================================
--- /trunk/minix/lib/ansi/loc_time.h	(revision 9)
+++ /trunk/minix/lib/ansi/loc_time.h	(revision 9)
@@ -0,0 +1,26 @@
+/*
+ * loc_time.h - some local definitions
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/loc_time.h,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+#define	YEAR0		1900			/* the first year */
+#define	EPOCH_YR	1970		/* EPOCH = Jan 1 1970 00:00:00 */
+#define	SECS_DAY	(24L * 60L * 60L)
+#define	LEAPYEAR(year)	(!((year) % 4) && (((year) % 100) || !((year) % 400)))
+#define	YEARSIZE(year)	(LEAPYEAR(year) ? 366 : 365)
+#define	FIRSTSUNDAY(timp)	(((timp)->tm_yday - (timp)->tm_wday + 420) % 7)
+#define	FIRSTDAYOF(timp)	(((timp)->tm_wday - (timp)->tm_yday + 420) % 7)
+#define	TIME_MAX	ULONG_MAX
+#define	ABB_LEN		3
+
+extern const int _ytab[2][12];
+extern const char *_days[];
+extern const char *_months[];
+
+void _tzset(void);
+unsigned _dstget(struct tm *timep);
+
+extern long _timezone;
+extern long _dst_off;
+extern int _daylight;
+extern char *_tzname[2];
Index: /trunk/minix/lib/ansi/localeconv.c
===================================================================
--- /trunk/minix/lib/ansi/localeconv.c	(revision 9)
+++ /trunk/minix/lib/ansi/localeconv.c	(revision 9)
@@ -0,0 +1,36 @@
+/*
+ * localeconv - set components of a struct according to current locale
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/localeconv.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+#include	<limits.h>
+#include	<locale.h>
+
+extern struct lconv _lc;
+
+struct lconv *
+localeconv(void)
+{
+	register struct lconv *lcp = &_lc;
+
+	lcp->decimal_point = ".";
+	lcp->thousands_sep = "";
+	lcp->grouping = "";
+	lcp->int_curr_symbol = "";
+	lcp->currency_symbol = "";
+	lcp->mon_decimal_point = "";
+	lcp->mon_thousands_sep = "";
+	lcp->mon_grouping = "";
+	lcp->positive_sign = "";
+	lcp->negative_sign = "";
+	lcp->int_frac_digits = CHAR_MAX;
+	lcp->frac_digits = CHAR_MAX;
+	lcp->p_cs_precedes = CHAR_MAX;
+	lcp->p_sep_by_space = CHAR_MAX;
+	lcp->n_cs_precedes = CHAR_MAX;
+	lcp->n_sep_by_space = CHAR_MAX;
+	lcp->p_sign_posn = CHAR_MAX;
+	lcp->n_sign_posn = CHAR_MAX;
+
+	return lcp;
+}
Index: /trunk/minix/lib/ansi/localtime.c
===================================================================
--- /trunk/minix/lib/ansi/localtime.c	(revision 9)
+++ /trunk/minix/lib/ansi/localtime.c	(revision 9)
@@ -0,0 +1,34 @@
+/*
+ * localtime - convert a calendar time into broken down time
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/localtime.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+#include	<time.h>
+#include	"loc_time.h"
+
+/* We must be careful, since an int can't represent all the seconds in a day.
+ * Hence the adjustment of minutes when adding timezone and dst information.
+ * This assumes that both must be expressable in multiples of a minute.
+ * Furthermore, it is assumed that both fit into an integer when expressed as
+ * minutes (this is about 22 days, so this should not cause any problems). 
+ */
+struct tm *
+localtime(const time_t *timer)
+{
+	struct tm *timep;
+	unsigned dst;
+
+	_tzset();
+	timep = gmtime(timer);			/* tm->tm_isdst == 0 */
+	timep->tm_min -= _timezone / 60;
+	timep->tm_sec -= _timezone % 60;
+	mktime(timep);
+
+	dst = _dstget(timep);
+	if (dst) {
+		timep->tm_min += dst / 60;
+		timep->tm_sec += dst % 60;
+		mktime(timep);
+	}
+	return timep;
+}
Index: /trunk/minix/lib/ansi/malloc.c
===================================================================
--- /trunk/minix/lib/ansi/malloc.c	(revision 9)
+++ /trunk/minix/lib/ansi/malloc.c	(revision 9)
@@ -0,0 +1,205 @@
+/* $Header: /cvsup/minix/src/lib/ansi/malloc.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+/* replace undef by define */
+#undef	 DEBUG		/* check assertions */
+#undef	 SLOWDEBUG	/* some extra test loops (requires DEBUG) */
+
+#ifndef DEBUG
+#define NDEBUG
+#endif
+
+#include	<stdlib.h>
+#include	<string.h>
+#include	<errno.h>
+#include	<assert.h>
+
+#if _EM_WSIZE == _EM_PSIZE
+#define	ptrint		int
+#else
+#define	ptrint		long
+#endif
+
+#if	_EM_PSIZE == 2
+#define BRKSIZE		1024
+#else
+#define BRKSIZE		4096
+#endif
+#define	PTRSIZE		((int) sizeof(void *))
+#define Align(x,a)	(((x) + (a - 1)) & ~(a - 1))
+#define NextSlot(p)	(* (void **) ((p) - PTRSIZE))
+#define NextFree(p)	(* (void **) (p))
+
+/*
+ * A short explanation of the data structure and algorithms.
+ * An area returned by malloc() is called a slot. Each slot
+ * contains the number of bytes requested, but preceeded by
+ * an extra pointer to the next the slot in memory.
+ * '_bottom' and '_top' point to the first/last slot.
+ * More memory is asked for using brk() and appended to top.
+ * The list of free slots is maintained to keep malloc() fast.
+ * '_empty' points the the first free slot. Free slots are
+ * linked together by a pointer at the start of the
+ * user visable part, so just after the next-slot pointer.
+ * Free slots are merged together by free().
+ */
+
+extern void *_sbrk(int);
+extern int _brk(void *);
+static void *_bottom, *_top, *_empty;
+
+static int grow(size_t len)
+{
+  register char *p;
+
+  assert(NextSlot((char *)_top) == 0);
+  if ((char *) _top + len < (char *) _top
+      || (p = (char *)Align((ptrint)_top + len, BRKSIZE)) < (char *) _top ) {
+	errno = ENOMEM;
+	return(0);
+  }
+  if (_brk(p) != 0)
+	return(0);
+  NextSlot((char *)_top) = p;
+  NextSlot(p) = 0;
+  free(_top);
+  _top = p;
+  return 1;
+}
+
+void *
+malloc(size_t size)
+{
+  register char *prev, *p, *next, *new;
+  register unsigned len, ntries;
+
+  if (size == 0)
+	return NULL;
+
+  for (ntries = 0; ntries < 2; ntries++) {
+	if ((len = Align(size, PTRSIZE) + PTRSIZE) < 2 * PTRSIZE) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	if (_bottom == 0) {
+		if ((p = _sbrk(2 * PTRSIZE)) == (char *) -1)
+			return NULL;
+		p = (char *) Align((ptrint)p, PTRSIZE);
+		p += PTRSIZE;
+		_top = _bottom = p;
+		NextSlot(p) = 0;
+	}
+#ifdef SLOWDEBUG
+	for (p = _bottom; (next = NextSlot(p)) != 0; p = next)
+		assert(next > p);
+	assert(p == _top);
+#endif
+	for (prev = 0, p = _empty; p != 0; prev = p, p = NextFree(p)) {
+		next = NextSlot(p);
+		new = p + len;	/* easily overflows!! */
+		if (new > next || new <= p)
+			continue;		/* too small */
+		if (new + PTRSIZE < next) {	/* too big, so split */
+			/* + PTRSIZE avoids tiny slots on free list */
+			NextSlot(new) = next;
+			NextSlot(p) = new;
+			NextFree(new) = NextFree(p);
+			NextFree(p) = new;
+		}
+		if (prev)
+			NextFree(prev) = NextFree(p);
+		else
+			_empty = NextFree(p);
+		return p;
+	}
+	if (grow(len) == 0)
+		break;
+  }
+  assert(ntries != 2);
+  return NULL;
+}
+
+void *
+realloc(void *oldp, size_t size)
+{
+  register char *prev, *p, *next, *new;
+  char *old = oldp;
+  register size_t len, n;
+
+  if (old == 0)
+	return malloc(size);
+  if (size == 0) {
+	free(old);
+	return NULL;
+  }
+  len = Align(size, PTRSIZE) + PTRSIZE;
+  next = NextSlot(old);
+  n = (int)(next - old);			/* old length */
+  /*
+   * extend old if there is any free space just behind it
+   */
+  for (prev = 0, p = _empty; p != 0; prev = p, p = NextFree(p)) {
+	if (p > next)
+		break;
+	if (p == next) {	/* 'next' is a free slot: merge */
+		NextSlot(old) = NextSlot(p);
+		if (prev)
+			NextFree(prev) = NextFree(p);
+		else
+			_empty = NextFree(p);
+		next = NextSlot(old);
+		break;
+	}
+  }
+  new = old + len;
+  /*
+   * Can we use the old, possibly extended slot?
+   */
+  if (new <= next && new >= old) {		/* it does fit */
+	if (new + PTRSIZE < next) {		/* too big, so split */
+		/* + PTRSIZE avoids tiny slots on free list */
+		NextSlot(new) = next;
+		NextSlot(old) = new;
+		free(new);
+	}
+	return old;
+  }
+  if ((new = malloc(size)) == NULL)		/* it didn't fit */
+	return NULL;
+  memcpy(new, old, n);				/* n < size */
+  free(old);
+  return new;
+}
+
+void
+free(void *ptr)
+{
+  register char *prev, *next;
+  char *p = ptr;
+
+  if (p == 0)
+	return;
+
+  assert(NextSlot(p) > p);
+  for (prev = 0, next = _empty; next != 0; prev = next, next = NextFree(next))
+	if (p < next)
+		break;
+  NextFree(p) = next;
+  if (prev)
+	NextFree(prev) = p;
+  else
+	_empty = p;
+  if (next) {
+	assert(NextSlot(p) <= next);
+	if (NextSlot(p) == next) {		/* merge p and next */
+		NextSlot(p) = NextSlot(next);
+		NextFree(p) = NextFree(next);
+	}
+  }
+  if (prev) {
+	assert(NextSlot(prev) <= p);
+	if (NextSlot(prev) == p) {		/* merge prev and p */
+		NextSlot(prev) = NextSlot(p);
+		NextFree(prev) = NextFree(p);
+	}
+  }
+}
Index: /trunk/minix/lib/ansi/mblen.c
===================================================================
--- /trunk/minix/lib/ansi/mblen.c	(revision 9)
+++ /trunk/minix/lib/ansi/mblen.c	(revision 9)
@@ -0,0 +1,18 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/mblen.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+#include	<stdlib.h>
+#include	<limits.h>
+
+#define	CHAR_SHIFT	8
+
+int
+mblen(const char *s, size_t n)
+{
+	if (s == (const char *)NULL) return 0;	/* no state dependent codings */
+	if (n <= 0) return 0;
+	return (*s != 0);
+}
Index: /trunk/minix/lib/ansi/mbstowcs.c
===================================================================
--- /trunk/minix/lib/ansi/mbstowcs.c	(revision 9)
+++ /trunk/minix/lib/ansi/mbstowcs.c	(revision 9)
@@ -0,0 +1,20 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/mbstowcs.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+#include	<stdlib.h>
+
+size_t
+mbstowcs(register wchar_t *pwcs, register const char *s, size_t n)
+{
+	register int i = n;
+
+	while (--i >= 0) {
+		if (!(*pwcs++ = *s++))
+			return n - i - 1;
+	}
+	return n - i;
+}
+
Index: /trunk/minix/lib/ansi/mbtowc.c
===================================================================
--- /trunk/minix/lib/ansi/mbtowc.c	(revision 9)
+++ /trunk/minix/lib/ansi/mbtowc.c	(revision 9)
@@ -0,0 +1,17 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/mbtowc.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+#include	<stdlib.h>
+#include	<limits.h>
+
+int
+mbtowc(wchar_t *pwc, register const char *s, size_t n)
+{
+	if (s == (const char *)NULL) return 0;
+	if (n <= 0) return 0;
+	if (pwc) *pwc = *s;
+	return (*s != 0);
+}
Index: /trunk/minix/lib/ansi/memchr.c
===================================================================
--- /trunk/minix/lib/ansi/memchr.c	(revision 9)
+++ /trunk/minix/lib/ansi/memchr.c	(revision 9)
@@ -0,0 +1,23 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/memchr.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+#include	<string.h>
+
+void *
+memchr(const void *s, register int c, register size_t n)
+{
+	register const unsigned char *s1 = s;
+
+	c = (unsigned char) c;
+	if (n) {
+		n++;
+		while (--n > 0) {
+			if (*s1++ != c) continue;
+			return (void *) --s1;
+		}
+	}
+	return NULL;
+}
Index: /trunk/minix/lib/ansi/memcmp.c
===================================================================
--- /trunk/minix/lib/ansi/memcmp.c	(revision 9)
+++ /trunk/minix/lib/ansi/memcmp.c	(revision 9)
@@ -0,0 +1,22 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Id: memcmp.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+#include	<string.h>
+
+int
+memcmp(const void *s1, const void *s2, size_t n)
+{
+	register const unsigned char *p1 = s1, *p2 = s2;
+
+	if (n) {
+		n++;
+		while (--n > 0) {
+			if (*p1++ == *p2++) continue;
+			return *--p1 - *--p2;
+		}
+	}
+	return 0;
+}
Index: /trunk/minix/lib/ansi/memcpy.c
===================================================================
--- /trunk/minix/lib/ansi/memcpy.c	(revision 9)
+++ /trunk/minix/lib/ansi/memcpy.c	(revision 9)
@@ -0,0 +1,23 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/memcpy.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+#include	<string.h>
+
+void *
+memcpy(void *s1, const void *s2, register size_t n)
+{
+	register char *p1 = s1;
+	register const char *p2 = s2;
+
+
+	if (n) {
+		n++;
+		while (--n > 0) {
+			*p1++ = *p2++;
+		}
+	}
+	return s1;
+}
Index: /trunk/minix/lib/ansi/memmove.c
===================================================================
--- /trunk/minix/lib/ansi/memmove.c	(revision 9)
+++ /trunk/minix/lib/ansi/memmove.c	(revision 9)
@@ -0,0 +1,32 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/memmove.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+#include	<string.h>
+
+void *
+memmove(void *s1, const void *s2, register size_t n)
+{
+	register char *p1 = s1;
+	register const char *p2 = s2;
+
+	if (n>0) {
+		if (p2 <= p1 && p2 + n > p1) {
+			/* overlap, copy backwards */
+			p1 += n;
+			p2 += n;
+			n++;
+			while (--n > 0) {
+				*--p1 = *--p2;
+			}
+		} else {
+			n++;
+			while (--n > 0) {
+				*p1++ = *p2++;
+			}
+		}
+	}
+	return s1;
+}
Index: /trunk/minix/lib/ansi/memset.c
===================================================================
--- /trunk/minix/lib/ansi/memset.c	(revision 9)
+++ /trunk/minix/lib/ansi/memset.c	(revision 9)
@@ -0,0 +1,21 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/memset.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
+
+#include	<string.h>
+
+void *
+memset(void *s, register int c, register size_t n)
+{
+	register char *s1 = s;
+
+	if (n>0) {
+		n++;
+		while (--n > 0) {
+			*s1++ = c;
+		}
+	}
+	return s;
+}
Index: /trunk/minix/lib/ansi/misc.c
===================================================================
--- /trunk/minix/lib/ansi/misc.c	(revision 9)
+++ /trunk/minix/lib/ansi/misc.c	(revision 9)
@@ -0,0 +1,410 @@
+/*
+ * misc - data and miscellaneous routines
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/misc.c,v 1.2 2005/06/17 13:00:04 jnherder Exp $ */
+
+#include	<ctype.h>
+#include	<time.h>
+#include	<stdlib.h>
+#include	<string.h>
+
+#if	defined(__BSD4_2)
+
+struct timeval {
+	long	tv_sec;		/* seconds */
+	long	tv_usec;	/* and microseconds */
+};
+
+struct timezone {
+	int	tz_minuteswest;	/* minutes west of Greenwich */
+	int	tz_dsttime;	/* type of dst correction */
+};
+
+int _gettimeofday(struct timeval *tp, struct timezone *tzp);
+
+#elif	!defined(_POSIX_SOURCE) && !defined(__USG)
+#if	!defined(_MINIX)		/* MINIX has no ftime() */
+struct timeb {
+	long	time;
+	unsigned short millitm;
+	short	timezone;
+	short	dstflag;
+};
+void _ftime(struct timeb *bp);
+#endif
+#endif
+
+#include	"loc_time.h"
+
+#define	RULE_LEN	120
+#define	TZ_LEN		10
+
+/* Make sure that the strings do not end up in ROM.
+ * These strings probably contain the wrong value, and we cannot obtain the
+ * right value from the system. TZ is the only help.
+ */
+static char ntstr[TZ_LEN + 1] = "GMT";	/* string for normal time */
+static char dststr[TZ_LEN + 1] = "GDT";	/* string for daylight saving */
+
+long	_timezone = 0;
+long	_dst_off = 60 * 60;
+int	_daylight = 0;
+char	*_tzname[2] = {ntstr, dststr};
+
+#if	defined(__USG) || defined(_POSIX_SOURCE)
+char	*tzname[2] = {ntstr, dststr};
+
+#if	defined(__USG)
+long	timezone = 0;
+int	daylight = 0;
+#endif
+#endif
+
+static struct dsttype {
+	char ds_type;		/* Unknown, Julian, Zero-based or M */
+	int ds_date[3];		/* months, weeks, days */
+	long ds_sec;		/* usually 02:00:00 */
+}	dststart = { 'U', { 0, 0, 0 }, 2 * 60 * 60 }
+	, dstend = { 'U', { 0, 0, 0 }, 2 * 60 * 60 };
+
+const char *_days[] = {
+			"Sunday", "Monday", "Tuesday", "Wednesday",
+			"Thursday", "Friday", "Saturday"
+		};
+
+const char *_months[] = {
+			"January", "February", "March",
+			"April", "May", "June",
+			"July", "August", "September",
+			"October", "November", "December"
+		};
+
+const int _ytab[2][12] = {
+		{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+		{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+	};
+
+static const char *
+parseZoneName(register char *buf, register const char *p)
+{
+	register int n = 0;
+
+	if (*p == ':') return NULL;
+	while (*p && !isdigit(*p) && *p != ',' && *p != '-' && *p != '+') {
+		if (n < TZ_LEN)
+			*buf++ = *p;
+		p++;
+		n++;
+	}
+	if (n < 3) return NULL;				/* error */
+	*buf = '\0';
+	return p;
+}
+
+static const char *
+parseTime(register long *tm, const char *p, register struct dsttype *dst)
+{
+	register int n = 0;
+	register const char *q = p;
+	char ds_type = (dst ? dst->ds_type : '\0');
+
+	if (dst) dst->ds_type = 'U';
+
+	*tm = 0;
+	while(*p >= '0' && *p <= '9') {
+		n = 10 * n + (*p++ - '0');
+	}
+	if (q == p) return NULL;	/* "The hour shall be required" */
+	if (n < 0 || n >= 24)	return NULL;
+	*tm = n * 60 * 60;
+	if (*p == ':') {
+		p++;
+		n = 0;
+		while(*p >= '0' && *p <= '9') {
+			n = 10 * n + (*p++ - '0');
+		}
+		if (q == p) return NULL;	/* format error */
+		if (n < 0 || n >= 60)	return NULL;
+		*tm += n * 60;
+		if (*p == ':') {
+			p++;
+			n = 0;
+			while(*p >= '0' && *p <= '9') {
+				n = 10 * n + (*p++ - '0');
+			}
+			if (q == p) return NULL;	/* format error */
+			if (n < 0 || n >= 60)	return NULL;
+			*tm += n;
+		}
+	}
+	if (dst) {
+		dst->ds_type = ds_type;
+		dst->ds_sec = *tm;
+	}
+	return p;
+}
+
+static const char *
+parseDate(register char *buf, register const char *p, struct dsttype *dstinfo)
+{
+	register const char *q;
+	register int n = 0;
+	int cnt = 0;
+	const int bnds[3][2] =	{	{ 1, 12 },
+					{ 1, 5 },
+					{ 0, 6}
+				 };
+	char ds_type;
+
+	if (*p != 'M') {
+		if (*p == 'J') {
+			*buf++ = *p++;
+			ds_type = 'J';
+		}
+		else	ds_type = 'Z';
+		q = p;
+		while(*p >= '0' && *p <= '9') {
+			n = 10 * n + (*p - '0');
+			*buf++ = *p++;
+		}
+		if (q == p) return NULL;	/* format error */
+		if (n < (ds_type == 'J') || n > 365) return NULL;
+		dstinfo->ds_type = ds_type;
+		dstinfo->ds_date[0] = n;
+		return p;
+	}
+	ds_type = 'M';
+	do {
+		*buf++ = *p++;
+		q = p;
+		n = 0;
+		while(*p >= '0' && *p <= '9') {
+			n = 10 * n + (*p - '0');
+			*buf++ = *p++;
+		}
+		if (q == p) return NULL;	/* format error */
+		if (n < bnds[cnt][0] || n > bnds[cnt][1]) return NULL;
+		dstinfo->ds_date[cnt] = n;
+		cnt++;
+	} while (cnt < 3 && *p == '.');
+	if (cnt != 3) return NULL;
+	*buf = '\0';
+	dstinfo->ds_type = ds_type;
+	return p;
+}
+
+static const char *
+parseRule(register char *buf, register const char *p)
+{
+	long time;
+	register const char *q;
+
+	if (!(p = parseDate(buf, p, &dststart))) return NULL;
+	buf += strlen(buf);
+	if (*p == '/') {
+		q = ++p;
+		if (!(p = parseTime(&time, p, &dststart))) return NULL;
+		while( p != q) *buf++ = *q++;
+	}
+	if (*p != ',') return NULL;
+	p++;
+	if (!(p = parseDate(buf, p, &dstend))) return NULL;
+	buf += strlen(buf);
+	if (*p == '/') {
+		q = ++p;
+		if (!(p = parseTime(&time, p, &dstend))) return NULL;
+		while(*buf++ = *q++);
+	}
+	if (*p) return NULL;
+	return p;
+}
+
+/* The following routine parses timezone information in POSIX-format. For
+ * the requirements, see IEEE Std 1003.1-1988 section 8.1.1.
+ * The function returns as soon as it spots an error.
+ */
+static void
+parseTZ(const char *p)
+{
+	long tz, dst = 60 * 60, sign = 1;
+	static char lastTZ[2 * RULE_LEN];
+	static char buffer[RULE_LEN];
+
+	if (!p) return;
+
+	if (*p == ':') {
+		/*
+		 * According to POSIX, this is implementation defined.
+		 * Since it depends on the particular operating system, we
+		 * can do nothing.
+		 */
+		return;
+	}
+
+	if (!strcmp(lastTZ, p)) return;		/* nothing changed */
+
+	*_tzname[0] = '\0';
+	*_tzname[1] = '\0';
+	dststart.ds_type = 'U';
+	dststart.ds_sec = 2 * 60 * 60;
+	dstend.ds_type = 'U';
+	dstend.ds_sec = 2 * 60 * 60;
+
+	if (strlen(p) > 2 * RULE_LEN) return;
+	strcpy(lastTZ, p);
+
+	if (!(p = parseZoneName(buffer, p))) return;
+
+	if (*p == '-') {
+		sign = -1;
+		p++;
+	} else if (*p == '+') p++;
+
+	if (!(p = parseTime(&tz, p, NULL))) return;
+	tz *= sign;
+	_timezone = tz;
+	strncpy(_tzname[0], buffer, TZ_LEN);
+
+	if (!(_daylight = (*p != '\0'))) return;
+
+	buffer[0] = '\0';
+	if (!(p = parseZoneName(buffer, p))) return;
+	strncpy(_tzname[1], buffer, TZ_LEN);
+
+	buffer[0] = '\0';
+	if (*p && (*p != ','))
+		if (!(p = parseTime(&dst, p, NULL))) return;
+	_dst_off = dst;			/* dst was initialized to 1 hour */
+	if (*p) {
+		if (*p != ',') return;
+		p++;
+		if (strlen(p) > RULE_LEN) return;
+		if (!(p = parseRule(buffer, p))) return;
+	}
+}
+
+void
+_tzset(void)
+{
+#if	defined(__BSD4_2)
+
+	struct timeval tv;
+	struct timezone tz;
+
+	_gettimeofday(&tv, &tz);
+	_daylight = tz.tz_dsttime;
+	_timezone = tz.tz_minuteswest * 60L;
+
+#elif	!defined(_POSIX_SOURCE) && !defined(__USG)
+
+#if	!defined(_MINIX)		/* MINIX has no ftime() */
+	struct timeb time;
+
+	_ftime(&time);
+	_timezone = time.timezone * 60L;
+	_daylight = time.dstflag;
+#endif
+
+#endif	/* !_POSIX_SOURCE && !__USG */
+
+	parseTZ(getenv("TZ"));		/* should go inside #if */
+
+#if	defined(__USG) || defined(_POSIX_SOURCE)
+	tzname[0] = _tzname[0];
+	tzname[1] = _tzname[1];
+#if	defined(__USG)
+	timezone = _timezone;
+	daylight = _daylight;
+#endif
+#endif	/* __USG || _POSIX_SOURCE */
+}
+
+static int
+last_sunday(register int day, register struct tm *timep)
+{
+	int first = FIRSTSUNDAY(timep);
+
+	if (day >= 58 && LEAPYEAR(YEAR0 + timep->tm_year)) day++;
+	if (day < first) return first;
+	return day - (day - first) % 7;
+}
+
+static int
+date_of(register struct dsttype *dst, struct tm *timep)
+{
+	int leap = LEAPYEAR(YEAR0 + timep->tm_year);
+	int firstday, tmpday;
+	register int day, month;
+
+	if (dst->ds_type != 'M') {
+		return dst->ds_date[0] -
+			    (dst->ds_type == 'J'
+				&& leap
+				&& dst->ds_date[0] < 58);
+	}
+	day = 0;
+	month = 1;
+	while (month < dst->ds_date[0]) {
+		day += _ytab[leap][month - 1];
+		month++;
+	}
+	firstday = (day + FIRSTDAYOF(timep)) % 7;
+	tmpday = day;
+	day += (dst->ds_date[2] - firstday + 7) % 7
+		+ 7 * (dst->ds_date[1] - 1);
+	if (day >= tmpday + _ytab[leap][month-1]) day -= 7;
+	return day;
+}
+
+/*
+ * The default dst transitions are those for Western Europe (except Great
+ * Britain). 
+ */
+unsigned
+_dstget(register struct tm *timep)
+{
+	int begindst, enddst;
+	register struct dsttype *dsts = &dststart, *dste = &dstend;
+	int do_dst = 0;
+
+	if (_daylight == -1)
+		_tzset();
+
+	timep->tm_isdst = _daylight;
+	if (!_daylight) return 0;
+
+	if (dsts->ds_type != 'U')
+		begindst = date_of(dsts, timep);
+	else begindst = last_sunday(89, timep);	/* last Sun before Apr */
+	if (dste->ds_type != 'U')
+		enddst = date_of(dste, timep);
+	else enddst = last_sunday(272, timep);	/* last Sun in Sep */
+
+	/* assume begindst != enddst (otherwise it would be no use) */
+	if (begindst < enddst) {		/* northern hemisphere */
+		if (timep->tm_yday > begindst && timep->tm_yday < enddst)
+			do_dst = 1;
+	} else {				/* southern hemisphere */
+		if (timep->tm_yday > begindst || timep->tm_yday < enddst)
+			do_dst = 1;
+	}
+
+	if (!do_dst
+	    && (timep->tm_yday == begindst || timep->tm_yday == enddst)) {
+		long dsttranssec;	/* transition when day is this old */
+		long cursec;
+
+		if (timep->tm_yday == begindst)
+			dsttranssec = dsts->ds_sec;
+		else	dsttranssec = dste->ds_sec;
+		cursec = ((timep->tm_hour * 60) + timep->tm_min) * 60L
+			    + timep->tm_sec;
+
+		if ((timep->tm_yday == begindst && cursec >= dsttranssec)
+		    || (timep->tm_yday == enddst && cursec < dsttranssec))
+			do_dst = 1;
+	}
+	if (do_dst) return _dst_off;
+	timep->tm_isdst = 0;
+	return 0;
+}
Index: /trunk/minix/lib/ansi/mktime.c
===================================================================
--- /trunk/minix/lib/ansi/mktime.c	(revision 9)
+++ /trunk/minix/lib/ansi/mktime.c	(revision 9)
@@ -0,0 +1,132 @@
+/*
+ * mktime - convert local time into calendar time
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/mktime.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+/* Michael A. Temari <temari@ix.netcom.com>   03/01/96    */
+/*   -  fixed bug is structure fixup code                 */
+
+#include	<time.h>
+#include	<limits.h>
+#include	"loc_time.h"
+
+/* The code assumes that unsigned long can be converted to time_t.
+ * A time_t should not be wider than unsigned long, since this would mean
+ * that the check for overflow at the end could fail.
+ */
+time_t
+mktime(register struct tm *timep)
+{
+	register long day, year;
+	register int tm_year;
+	int yday, month;
+	register unsigned long seconds;
+	int overflow;
+	unsigned dst;
+
+	timep->tm_min += timep->tm_sec / 60;
+	timep->tm_sec %= 60;
+	if (timep->tm_sec < 0) {
+		timep->tm_sec += 60;
+		timep->tm_min--;
+	}
+	timep->tm_hour += timep->tm_min / 60;
+	timep->tm_min = timep->tm_min % 60;
+	if (timep->tm_min < 0) {
+		timep->tm_min += 60;
+		timep->tm_hour--;
+	}
+	day = timep->tm_hour / 24;
+	timep->tm_hour= timep->tm_hour % 24;
+	if (timep->tm_hour < 0) {
+		timep->tm_hour += 24;
+		day--;
+	}
+	timep->tm_year += timep->tm_mon / 12;
+	timep->tm_mon %= 12;
+	if (timep->tm_mon < 0) {
+		timep->tm_mon += 12;
+		timep->tm_year--;
+	}
+	day += (timep->tm_mday - 1);
+	while (day < 0) {
+		if(--timep->tm_mon < 0) {
+			timep->tm_year--;
+			timep->tm_mon = 11;
+		}
+		day += _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon];
+	}
+	while (day >= _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon]) {
+		day -= _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon];
+		if (++(timep->tm_mon) == 12) {
+			timep->tm_mon = 0;
+			timep->tm_year++;
+		}
+	}
+	timep->tm_mday = day + 1;
+	_tzset();			/* set timezone and dst info  */
+	year = EPOCH_YR;
+	if (timep->tm_year < year - YEAR0) return (time_t)-1;
+	seconds = 0;
+	day = 0;			/* means days since day 0 now */
+	overflow = 0;
+
+	/* Assume that when day becomes negative, there will certainly
+	 * be overflow on seconds.
+	 * The check for overflow needs not to be done for leapyears
+	 * divisible by 400.
+	 * The code only works when year (1970) is not a leapyear.
+	 */
+#if	EPOCH_YR != 1970
+#error	EPOCH_YR != 1970
+#endif
+	tm_year = timep->tm_year + YEAR0;
+
+	if (LONG_MAX / 365 < tm_year - year) overflow++;
+	day = (tm_year - year) * 365;
+	if (LONG_MAX - day < (tm_year - year) / 4 + 1) overflow++;
+	day += (tm_year - year) / 4
+		+ ((tm_year % 4) && tm_year % 4 < year % 4);
+	day -= (tm_year - year) / 100
+		+ ((tm_year % 100) && tm_year % 100 < year % 100);
+	day += (tm_year - year) / 400
+		+ ((tm_year % 400) && tm_year % 400 < year % 400);
+
+	yday = month = 0;
+	while (month < timep->tm_mon) {
+		yday += _ytab[LEAPYEAR(tm_year)][month];
+		month++;
+	}
+	yday += (timep->tm_mday - 1);
+	if (day + yday < 0) overflow++;
+	day += yday;
+
+	timep->tm_yday = yday;
+	timep->tm_wday = (day + 4) % 7;		/* day 0 was thursday (4) */
+
+	seconds = ((timep->tm_hour * 60L) + timep->tm_min) * 60L + timep->tm_sec;
+
+	if ((TIME_MAX - seconds) / SECS_DAY < day) overflow++;
+	seconds += day * SECS_DAY;
+
+	/* Now adjust according to timezone and daylight saving time */
+
+	if (((_timezone > 0) && (TIME_MAX - _timezone < seconds))
+	    || ((_timezone < 0) && (seconds < -_timezone)))
+		overflow++;
+	seconds += _timezone;
+
+	if (timep->tm_isdst < 0)
+		dst = _dstget(timep);
+	else if (timep->tm_isdst)
+		dst = _dst_off;
+	else dst = 0;
+
+	if (dst > seconds) overflow++;	/* dst is always non-negative */
+	seconds -= dst;
+
+	if (overflow) return (time_t)-1;
+
+	if ((time_t)seconds != seconds) return (time_t)-1;
+	return (time_t)seconds;
+}
Index: /trunk/minix/lib/ansi/qsort.c
===================================================================
--- /trunk/minix/lib/ansi/qsort.c	(revision 9)
+++ /trunk/minix/lib/ansi/qsort.c	(revision 9)
@@ -0,0 +1,139 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/qsort.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<stdlib.h>
+
+static	void qsort1(char *, char *, size_t);
+static	int (*qcompar)(const char *, const char *);
+static	void qexchange(char *, char *, size_t);
+static	void q3exchange(char *, char *, char *, size_t);
+
+void
+qsort(void *base, size_t nel, size_t width,
+      int (*compar)(const void *, const void *))
+{
+	/* when nel is 0, the expression '(nel - 1) * width' is wrong */
+	if (!nel) return;
+	qcompar = (int (*)(const char *, const char *)) compar;
+	qsort1(base, (char *)base + (nel - 1) * width, width);
+}
+
+static void
+qsort1(char *a1, char *a2, register size_t width)
+{
+	register char *left, *right;
+	register char *lefteq, *righteq;
+	int cmp;
+
+	for (;;) {
+		if (a2 <= a1) return;
+		left = a1;
+		right = a2;
+		lefteq = righteq = a1 + width * (((a2-a1)+width)/(2*width));
+		/*
+		   Pick an element in the middle of the array.
+		   We will collect the equals around it.
+		   "lefteq" and "righteq" indicate the left and right
+		   bounds of the equals respectively.
+		   Smaller elements end up left of it, larger elements end
+		   up right of it.
+		*/
+again:
+		while (left < lefteq && (cmp = (*qcompar)(left, lefteq)) <= 0) {
+			if (cmp < 0) {
+				/* leave it where it is */
+				left += width;
+			}
+			else {
+				/* equal, so exchange with the element to
+				   the left of the "equal"-interval.
+				*/
+				lefteq -= width;
+				qexchange(left, lefteq, width);
+			}
+		}
+		while (right > righteq) {
+			if ((cmp = (*qcompar)(right, righteq)) < 0) {
+				/* smaller, should go to left part
+				*/
+				if (left < lefteq) {
+					/* yes, we had a larger one at the
+					   left, so we can just exchange
+					*/
+					qexchange(left, right, width);
+					left += width;
+					right -= width;
+					goto again;
+				}
+				/* no more room at the left part, so we
+				   move the "equal-interval" one place to the
+				   right, and the smaller element to the
+				   left of it.
+				   This is best expressed as a three-way
+				   exchange.
+				*/
+				righteq += width;
+				q3exchange(left, righteq, right, width);
+				lefteq += width;
+				left = lefteq;
+			}
+			else if (cmp == 0) {
+				/* equal, so exchange with the element to
+				   the right of the "equal-interval"
+				*/
+				righteq += width;
+				qexchange(right, righteq, width);
+			}
+			else	/* just leave it */ right -= width;
+		}
+		if (left < lefteq) {
+			/* larger element to the left, but no more room,
+			   so move the "equal-interval" one place to the
+			   left, and the larger element to the right
+			   of it.
+			*/
+			lefteq -= width;
+			q3exchange(right, lefteq, left, width);
+			righteq -= width;
+			right = righteq;
+			goto again;
+		}
+		/* now sort the "smaller" part */
+		qsort1(a1, lefteq - width, width);
+		/* and now the larger, saving a subroutine call
+		   because of the for(;;)
+		*/
+		a1 = righteq + width;
+	}
+	/*NOTREACHED*/
+}
+
+static void
+qexchange(register char *p, register char *q,
+	  register size_t n)
+{
+	register int c;
+
+	while (n-- > 0) {
+		c = *p;
+		*p++ = *q;
+		*q++ = c;
+	}
+}
+
+static void
+q3exchange(register char *p, register char *q, register char *r,
+	   register size_t n)
+{
+	register int c;
+
+	while (n-- > 0) {
+		c = *p;
+		*p++ = *r;
+		*r++ = *q;
+		*q++ = c;
+	}
+}
Index: /trunk/minix/lib/ansi/raise.c
===================================================================
--- /trunk/minix/lib/ansi/raise.c	(revision 9)
+++ /trunk/minix/lib/ansi/raise.c	(revision 9)
@@ -0,0 +1,21 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/raise.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#if	defined(_POSIX_SOURCE)
+#include	<sys/types.h>
+#endif
+#include	<signal.h>
+
+int _kill(int pid, int sig);
+pid_t _getpid(void);
+
+int
+raise(int sig)
+{
+	if (sig < 0 || sig > _NSIG)
+		return -1;
+	return _kill(_getpid(), sig);
+}
Index: /trunk/minix/lib/ansi/rand.c
===================================================================
--- /trunk/minix/lib/ansi/rand.c	(revision 9)
+++ /trunk/minix/lib/ansi/rand.c	(revision 9)
@@ -0,0 +1,20 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/rand.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<stdlib.h>
+
+static unsigned long int next = 1;
+
+int rand(void)
+{
+	next = next * 1103515245 + 12345;
+	return (unsigned int)(next/(2 * (RAND_MAX +1L)) % (RAND_MAX+1L));
+}
+
+void srand(unsigned int seed)
+{
+	next = seed;
+}
Index: /trunk/minix/lib/ansi/setlocale.c
===================================================================
--- /trunk/minix/lib/ansi/setlocale.c	(revision 9)
+++ /trunk/minix/lib/ansi/setlocale.c	(revision 9)
@@ -0,0 +1,28 @@
+/*
+ * setlocale - set the programs locale
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/setlocale.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<locale.h>
+#include	<string.h>
+
+struct lconv _lc;
+
+char *
+setlocale(int category, const char *locale)
+{
+	if (!locale) return "C";
+	if (*locale && strcmp(locale, "C")) return (char *)NULL;
+	
+	switch(category) {
+	case LC_ALL:
+	case LC_CTYPE:
+	case LC_COLLATE:
+	case LC_TIME:
+	case LC_NUMERIC:
+	case LC_MONETARY:
+		return *locale ? (char *)locale : "C";
+	default:
+		return (char *)NULL;
+	}
+}
Index: /trunk/minix/lib/ansi/sigmisc.c
===================================================================
--- /trunk/minix/lib/ansi/sigmisc.c	(revision 9)
+++ /trunk/minix/lib/ansi/sigmisc.c	(revision 9)
@@ -0,0 +1,39 @@
+/*
+ * sigmisc.c - used to get a signal mask
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/sigmisc.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#if	defined(_POSIX_SOURCE)
+
+/* This can't be done in setjmp.e, since SIG_SETMASK is defined in
+ * <signal.h>. This is a C-file, which can't be included.
+ */
+
+#include	<sys/types.h>
+#include	<signal.h>
+#include	<stddef.h>
+
+int _sigprocmask(int, sigset_t *, sigset_t *);
+
+static void
+__testsigset(void) {
+	/* This switch compiles when a sigset_t has the right size. */
+	switch(0) {
+	case 0: 
+	case sizeof(sigset_t) <= sizeof(long): break;
+	}
+}
+
+void
+__newsigset(sigset_t *p)
+{
+	/* The SIG_SETMASK is not significant */
+	_sigprocmask(SIG_SETMASK, NULL, p);
+}
+
+void
+__oldsigset(sigset_t *p)
+{
+	_sigprocmask(SIG_SETMASK, p, NULL);
+}
+#endif	/* _POSIX_SOURCE */
Index: /trunk/minix/lib/ansi/signal.c
===================================================================
--- /trunk/minix/lib/ansi/signal.c	(revision 9)
+++ /trunk/minix/lib/ansi/signal.c	(revision 9)
@@ -0,0 +1,35 @@
+/* SYSVR4 and ANSI compatible signal(2). */
+
+#include <lib.h>
+#define sigaction	_sigaction
+#define sigemptyset	_sigemptyset
+#include <signal.h>
+
+PUBLIC sighandler_t signal(sig, disp)
+int sig;			/* signal number */
+sighandler_t disp;		/* signal handler, or SIG_DFL, or SIG_IGN */
+{
+  struct sigaction sa, osa;
+
+  if (sig <= 0 || sig > _NSIG || sig == SIGKILL) {
+	errno = EINVAL;
+	return(SIG_ERR);
+  }
+  sigemptyset(&sa.sa_mask);
+
+#ifdef WANT_UNRELIABLE_SIGNALS
+  /* Allow the signal being handled to interrupt the signal handler. */
+  sa.sa_flags = SA_NODEFER;
+
+  /* When signal is caught, reset signal handler to SIG_DFL for all but
+   * SIGILL and SIGTRAP.
+   */
+  if (sig != SIGILL && sig != SIGTRAP) sa.sa_flags |= SA_RESETHAND;
+#else
+  sa.sa_flags = 0;
+#endif
+
+  sa.sa_handler = disp;
+  if (sigaction(sig, &sa, &osa) < 0) return(SIG_ERR);
+  return(osa.sa_handler);
+}
Index: /trunk/minix/lib/ansi/strcat.c
===================================================================
--- /trunk/minix/lib/ansi/strcat.c	(revision 9)
+++ /trunk/minix/lib/ansi/strcat.c	(revision 9)
@@ -0,0 +1,20 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strcat.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+char *
+strcat(char *ret, register const char *s2)
+{
+	register char *s1 = ret;
+
+	while (*s1++ != '\0')
+		/* EMPTY */ ;
+	s1--;
+	while (*s1++ = *s2++)
+		/* EMPTY */ ;
+	return ret;
+}
Index: /trunk/minix/lib/ansi/strchr.c
===================================================================
--- /trunk/minix/lib/ansi/strchr.c	(revision 9)
+++ /trunk/minix/lib/ansi/strchr.c	(revision 9)
@@ -0,0 +1,18 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strchr.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+char *
+strchr(register const char *s, register int c)
+{
+	c = (char) c;
+
+	while (c != *s) {
+		if (*s++ == '\0') return NULL;
+	}
+	return (char *)s;
+}
Index: /trunk/minix/lib/ansi/strcmp.c
===================================================================
--- /trunk/minix/lib/ansi/strcmp.c	(revision 9)
+++ /trunk/minix/lib/ansi/strcmp.c	(revision 9)
@@ -0,0 +1,20 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Id: strcmp.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+int
+strcmp(register const char *s1, register const char *s2)
+{
+	while (*s1 == *s2++) {
+		if (*s1++ == '\0') {
+			return 0;
+		}
+	}
+	if (*s1 == '\0') return -1;
+	if (*--s2 == '\0') return 1;
+	return (unsigned char) *s1 - (unsigned char) *s2;
+}
Index: /trunk/minix/lib/ansi/strcoll.c
===================================================================
--- /trunk/minix/lib/ansi/strcoll.c	(revision 9)
+++ /trunk/minix/lib/ansi/strcoll.c	(revision 9)
@@ -0,0 +1,19 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strcoll.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+#include	<locale.h>
+
+int
+strcoll(register const char *s1, register const char *s2)
+{
+	while (*s1 == *s2++) {
+		if (*s1++ == '\0') {
+			return 0;
+		}
+	}
+	return *s1 - *--s2;
+}
Index: /trunk/minix/lib/ansi/strcpy.c
===================================================================
--- /trunk/minix/lib/ansi/strcpy.c	(revision 9)
+++ /trunk/minix/lib/ansi/strcpy.c	(revision 9)
@@ -0,0 +1,18 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strcpy.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+char *
+strcpy(char *ret, register const char *s2)
+{
+	register char *s1 = ret;
+
+	while (*s1++ = *s2++)
+		/* EMPTY */ ;
+
+	return ret;
+}
Index: /trunk/minix/lib/ansi/strcspn.c
===================================================================
--- /trunk/minix/lib/ansi/strcspn.c	(revision 9)
+++ /trunk/minix/lib/ansi/strcspn.c	(revision 9)
@@ -0,0 +1,21 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strcspn.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+size_t
+strcspn(const char *string, const char *notin)
+{
+	register const char *s1, *s2;
+
+	for (s1 = string; *s1; s1++) {
+		for(s2 = notin; *s2 != *s1 && *s2; s2++)
+			/* EMPTY */ ;
+		if (*s2)
+			break;
+	}
+	return s1 - string;
+}
Index: /trunk/minix/lib/ansi/strerror.c
===================================================================
--- /trunk/minix/lib/ansi/strerror.c	(revision 9)
+++ /trunk/minix/lib/ansi/strerror.c	(revision 9)
@@ -0,0 +1,22 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strerror.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+/*
+ * I don't know why, but X3J11 says that strerror() should be in declared
+ * in <string.h>.  That is why the function is defined here.
+ */
+char *
+strerror(register int errnum)
+{
+	extern const char *_sys_errlist[];
+	extern const int _sys_nerr;
+
+  	if (errnum < 0 || errnum >= _sys_nerr)
+		return "unknown error";
+	return (char *)_sys_errlist[errnum];
+}
Index: /trunk/minix/lib/ansi/strftime.c
===================================================================
--- /trunk/minix/lib/ansi/strftime.c	(revision 9)
+++ /trunk/minix/lib/ansi/strftime.c	(revision 9)
@@ -0,0 +1,172 @@
+/*
+ * strftime - convert a structure to a string, controlled by an argument
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strftime.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<time.h>
+#include	"loc_time.h"
+
+/* The width can be -1 in both s_prnt() as in u_prnt(). This
+ * indicates that as many characters as needed should be printed.
+ */
+static char *
+s_prnt(char *s, size_t maxsize, const char *str, int width)
+{
+	while (width > 0 || (width < 0 && *str)) {
+		if (!maxsize) break;
+		*s++ = *str++;
+		maxsize--;
+		width--;
+	}
+	return s;
+}
+
+static char *
+u_prnt(char *s, size_t maxsize, unsigned val, int width)
+{
+	int c;
+
+	c = val % 10;
+	val = val / 10;
+	if (--width > 0 || (width < 0 && val != 0))
+		s = u_prnt(s, (maxsize ? maxsize - 1 : 0), val, width);
+	if (maxsize) *s++ = c + '0';
+	return s;
+}
+
+size_t
+strftime(char *s, size_t maxsize,
+		const char *format, const struct tm *timeptr)
+{
+	size_t n;
+	char *firsts, *olds;
+
+	if (!format) return 0;
+
+	_tzset();	/* for %Z conversion */
+	firsts = s;
+	while (maxsize && *format) {
+		while (maxsize && *format && *format != '%') {
+			*s++ = *format++;
+			maxsize--;
+		}
+		if (!maxsize || !*format) break;
+		format++;
+
+		olds = s;
+		switch (*format++) {
+		case 'a':
+			s = s_prnt(s, maxsize,
+					_days[timeptr->tm_wday], ABB_LEN);
+			maxsize -= s - olds;
+			break;
+		case 'A':
+			s = s_prnt(s, maxsize, _days[timeptr->tm_wday], -1);
+			maxsize -= s - olds;
+			break;
+		case 'b':
+			s = s_prnt(s, maxsize,
+					_months[timeptr->tm_mon], ABB_LEN);
+			maxsize -= s - olds;
+			break;
+		case 'B':
+			s = s_prnt(s, maxsize, _months[timeptr->tm_mon], -1);
+			maxsize -= s - olds;
+			break;
+		case 'c':
+			n = strftime(s, maxsize,
+					"%a %b %d %H:%M:%S %Y", timeptr);
+			if (n) maxsize -= n;
+			else maxsize = 0;
+			s += n;
+			break;
+		case 'd':
+			s = u_prnt(s, maxsize, timeptr->tm_mday, 2);
+			maxsize -= s - olds;
+			break;
+		case 'H':
+			s = u_prnt(s, maxsize, timeptr->tm_hour, 2);
+			maxsize -= s - olds;
+			break;
+		case 'I':
+			s = u_prnt(s, maxsize,
+					(timeptr->tm_hour + 11) % 12 + 1, 2);
+			maxsize -= s - olds;
+			break;
+		case 'j':
+			s = u_prnt(s, maxsize, timeptr->tm_yday + 1, 3);
+			maxsize -= s - olds;
+			break;
+		case 'm':
+			s = u_prnt(s, maxsize, timeptr->tm_mon + 1, 2);
+			maxsize -= s - olds;
+			break;
+		case 'M':
+			s = u_prnt(s, maxsize, timeptr->tm_min, 2);
+			maxsize -= s - olds;
+			break;
+		case 'p':
+			s = s_prnt(s, maxsize,
+				    (timeptr->tm_hour < 12) ? "AM" : "PM", 2);
+			maxsize -= s - olds;
+			break;
+		case 'S':
+			s = u_prnt(s, maxsize, timeptr->tm_sec, 2);
+			maxsize -= s - olds;
+			break;
+		case 'U':
+			s = u_prnt(s, maxsize,		/* ??? */
+			    (timeptr->tm_yday + 7 - timeptr->tm_wday) / 7, 2);
+			maxsize -= s - olds;
+			break;
+		case 'w':
+			s = u_prnt(s, maxsize, timeptr->tm_wday, 1);
+			maxsize -= s - olds;
+			break;
+		case 'W':
+			s = u_prnt(s, maxsize,		/* ??? */
+			    (timeptr->tm_yday+7-(timeptr->tm_wday+6)%7)/7,2);
+			maxsize -= s - olds;
+			break;
+		case 'x':
+			n = strftime(s, maxsize, "%a %b %d %Y", timeptr);
+			if (n) maxsize -= n;
+			else maxsize = 0;
+			s += n;
+			break;
+		case 'X':
+			n = strftime(s, maxsize, "%H:%M:%S", timeptr);
+			if (n) maxsize -= n;
+			else maxsize = 0;
+			s += n;
+			break;
+		case 'y':
+			s = u_prnt(s, maxsize, timeptr->tm_year % 100, 2);
+			maxsize -= s - olds;
+			break;
+		case 'Y':
+			s = u_prnt(s, maxsize, timeptr->tm_year + YEAR0, -1);
+			maxsize -= s - olds;
+			break;
+		case 'Z':
+			s = s_prnt(s, maxsize,
+					_tzname[(timeptr->tm_isdst > 0)], -1);
+			maxsize -= s - olds;
+			break;
+		case '%':
+			*s++ = '%';
+			maxsize--;
+			break;
+		default:
+			/* A conversion error. Leave the loop. */
+			while (*format) format++;
+			break;
+		}
+
+	}
+	if (maxsize) {
+		*s = '\0';
+		return s - firsts;
+	}
+	return 0;	/* The buffer is full */
+}
Index: /trunk/minix/lib/ansi/strlen.c
===================================================================
--- /trunk/minix/lib/ansi/strlen.c	(revision 9)
+++ /trunk/minix/lib/ansi/strlen.c	(revision 9)
@@ -0,0 +1,18 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strlen.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+size_t
+strlen(const char *org)
+{
+	register const char *s = org;
+
+	while (*s++)
+		/* EMPTY */ ;
+
+	return --s - org;
+}
Index: /trunk/minix/lib/ansi/strncat.c
===================================================================
--- /trunk/minix/lib/ansi/strncat.c	(revision 9)
+++ /trunk/minix/lib/ansi/strncat.c	(revision 9)
@@ -0,0 +1,25 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strncat.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+char *
+strncat(char *ret, register const char *s2, size_t n)
+{
+	register char *s1 = ret;
+
+	if (n > 0) {
+		while (*s1++)
+			/* EMPTY */ ;
+		s1--;
+		while (*s1++ = *s2++)  {
+			if (--n > 0) continue;
+			*s1 = '\0';
+			break;
+		}
+		return ret;
+	} else return s1;
+}
Index: /trunk/minix/lib/ansi/strncmp.c
===================================================================
--- /trunk/minix/lib/ansi/strncmp.c	(revision 9)
+++ /trunk/minix/lib/ansi/strncmp.c	(revision 9)
@@ -0,0 +1,26 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Id: strncmp.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+int
+strncmp(register const char *s1, register const char *s2, register size_t n)
+{
+	if (n) {
+		do {
+			if (*s1 != *s2++)
+				break;
+			if (*s1++ == '\0')
+				return 0;
+		} while (--n > 0);
+		if (n > 0) {
+			if (*s1 == '\0') return -1;
+			if (*--s2 == '\0') return 1;
+			return (unsigned char) *s1 - (unsigned char) *s2;
+		}
+	}
+	return 0;
+}
Index: /trunk/minix/lib/ansi/strncpy.c
===================================================================
--- /trunk/minix/lib/ansi/strncpy.c	(revision 9)
+++ /trunk/minix/lib/ansi/strncpy.c	(revision 9)
@@ -0,0 +1,24 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strncpy.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+char *
+strncpy(char *ret, register const char *s2, register size_t n)
+{
+	register char *s1 = ret;
+
+	if (n>0) {
+		while((*s1++ = *s2++) && --n > 0)
+			/* EMPTY */ ;
+		if ((*--s2 == '\0') && --n > 0) {
+			do {
+				*s1++ = '\0';
+			} while(--n > 0);
+		}
+	}
+	return ret;
+}
Index: /trunk/minix/lib/ansi/strpbrk.c
===================================================================
--- /trunk/minix/lib/ansi/strpbrk.c	(revision 9)
+++ /trunk/minix/lib/ansi/strpbrk.c	(revision 9)
@@ -0,0 +1,22 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strpbrk.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+char *
+strpbrk(register const char *string, register const char *brk)
+{
+	register const char *s1;
+
+	while (*string) {
+		for (s1 = brk; *s1 && *s1 != *string; s1++)
+			/* EMPTY */ ;
+		if (*s1)
+			return (char *)string;
+		string++;
+	}
+	return (char *)NULL;
+}
Index: /trunk/minix/lib/ansi/strrchr.c
===================================================================
--- /trunk/minix/lib/ansi/strrchr.c	(revision 9)
+++ /trunk/minix/lib/ansi/strrchr.c	(revision 9)
@@ -0,0 +1,22 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strrchr.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+char *
+strrchr(register const char *s, int c)
+{
+	register const char *result = NULL;
+
+	c = (char) c;
+
+	do {
+		if (c == *s)
+			result = s;
+	} while (*s++ != '\0');
+
+	return (char *)result;
+}
Index: /trunk/minix/lib/ansi/strspn.c
===================================================================
--- /trunk/minix/lib/ansi/strspn.c	(revision 9)
+++ /trunk/minix/lib/ansi/strspn.c	(revision 9)
@@ -0,0 +1,21 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strspn.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+size_t
+strspn(const char *string, const char *in)
+{
+	register const char *s1, *s2;
+
+	for (s1 = string; *s1; s1++) {
+		for (s2 = in; *s2 && *s2 != *s1; s2++)
+			/* EMPTY */ ;
+		if (*s2 == '\0')
+			break;
+	}
+	return s1 - string;
+}
Index: /trunk/minix/lib/ansi/strstr.c
===================================================================
--- /trunk/minix/lib/ansi/strstr.c	(revision 9)
+++ /trunk/minix/lib/ansi/strstr.c	(revision 9)
@@ -0,0 +1,19 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strstr.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+char *
+strstr(register const char *s, register const char *wanted)
+{
+	register const size_t len = strlen(wanted);
+
+	if (len == 0) return (char *)s;
+	while (*s != *wanted || strncmp(s, wanted, len))
+		if (*s++ == '\0')
+			return (char *)NULL;
+	return (char *)s;
+}
Index: /trunk/minix/lib/ansi/strtok.c
===================================================================
--- /trunk/minix/lib/ansi/strtok.c	(revision 9)
+++ /trunk/minix/lib/ansi/strtok.c	(revision 9)
@@ -0,0 +1,31 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strtok.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+char *
+strtok(register char *string, const char *separators)
+{
+	register char *s1, *s2;
+	static char *savestring;
+
+	if (string == NULL) {
+		string = savestring;
+		if (string == NULL) return (char *)NULL;
+	}
+
+	s1 = string + strspn(string, separators);
+	if (*s1 == '\0') {
+		savestring = NULL;
+		return (char *)NULL;
+	}
+
+	s2 = strpbrk(s1, separators);
+	if (s2 != NULL)
+		*s2++ = '\0';
+	savestring = s2;
+	return s1;
+}
Index: /trunk/minix/lib/ansi/strtol.c
===================================================================
--- /trunk/minix/lib/ansi/strtol.c	(revision 9)
+++ /trunk/minix/lib/ansi/strtol.c	(revision 9)
@@ -0,0 +1,101 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strtol.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<ctype.h>
+#include	<errno.h>
+#include	<limits.h>
+#include	<stdlib.h>
+
+static unsigned long
+string2long(register const char *nptr, char **endptr,
+			int base, int is_signed);
+
+long int
+strtol(register const char *nptr, char **endptr, int base)
+{
+	return (signed long)string2long(nptr, endptr, base, 1);
+}
+
+unsigned long int
+strtoul(register const char *nptr, char **endptr, int base)
+{
+	return (unsigned long)string2long(nptr, endptr, base, 0);
+}
+
+#define between(a, c, z)  ((unsigned) ((c) - (a)) <= (unsigned) ((z) - (a)))
+
+static unsigned long
+string2long(register const char *nptr, char ** const endptr,
+			int base, int is_signed)
+{
+	register unsigned int v;
+	register unsigned long val = 0;
+	register int c;
+	int ovfl = 0, sign = 1;
+	const char *startnptr = nptr, *nrstart;
+
+	if (endptr) *endptr = (char *)nptr;
+	while (isspace(*nptr)) nptr++;
+	c = *nptr;
+
+	if (c == '-' || c == '+') {
+		if (c == '-') sign = -1;
+		nptr++;
+	}
+	nrstart = nptr;			/* start of the number */
+
+	/* When base is 0, the syntax determines the actual base */
+	if (base == 0)
+		if (*nptr == '0')
+			if (*++nptr == 'x' || *nptr == 'X') {
+				base = 16;
+				nptr++;
+			}
+			else	base = 8;
+		else	base = 10;
+	else if (base==16 && *nptr=='0' && (*++nptr =='x' || *nptr =='X'))
+		nptr++;
+
+	for (;;) {
+		c = *nptr;
+		if (between('0', c, '9')) {
+			v = c - '0';
+		} else
+		if (between('a', c, 'z')) {
+			v = c - 'a' + 0xa;
+		} else
+		if (between('A', c, 'Z')) {
+			v = c - 'A' + 0xA;
+		} else {
+			break;
+		}
+		if (v >= base) break;
+		if (val > (ULONG_MAX - v) / base) ovfl++;
+		val = (val * base) + v;
+		nptr++;
+	}
+	if (endptr) {
+		if (nrstart == nptr) *endptr = (char *)startnptr;
+		else *endptr = (char *)nptr;
+	}
+
+	if (!ovfl) {
+		/* Overflow is only possible when converting a signed long. */
+		if (is_signed
+		    && (   (sign < 0 && val > -(unsigned long)LONG_MIN)
+			|| (sign > 0 && val > LONG_MAX)))
+		    ovfl++;
+	}
+
+	if (ovfl) {
+		errno = ERANGE;
+		if (is_signed)
+			if (sign < 0) return LONG_MIN;
+			else return LONG_MAX;
+		else return ULONG_MAX;
+	}
+	return (long) sign * val;
+}
Index: /trunk/minix/lib/ansi/strxfrm.c
===================================================================
--- /trunk/minix/lib/ansi/strxfrm.c	(revision 9)
+++ /trunk/minix/lib/ansi/strxfrm.c	(revision 9)
@@ -0,0 +1,24 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/strxfrm.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<string.h>
+
+size_t
+strxfrm(register char *s1, register const char *save, register size_t n)
+{
+	register const char *s2 = save;
+
+	while (*s2) {
+		if (n > 1) {
+			n--;
+			*s1++ = *s2++;
+		} else
+			s2++;
+	}
+	if (n > 0)
+		*s1++ = '\0';
+	return s2 - save;
+}
Index: /trunk/minix/lib/ansi/system.c
===================================================================
--- /trunk/minix/lib/ansi/system.c	(revision 9)
+++ /trunk/minix/lib/ansi/system.c	(revision 9)
@@ -0,0 +1,59 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/system.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#if	defined(_POSIX_SOURCE)
+#include	<sys/types.h>
+#endif
+#include	<stdlib.h>
+#include	<signal.h>
+
+extern pid_t _fork(void);
+extern pid_t _wait(int *);
+extern void _exit(int);
+extern void _execve(const char *path, const char ** argv, const char ** envp);
+extern int _close(int);
+
+#define	FAIL	127
+
+extern const char ***_penviron;
+static const char *exec_tab[] = {
+	"sh",			/* argv[0] */
+	"-c",			/* argument to the shell */
+	NULL,			/* to be filled with user command */
+	NULL			/* terminating NULL */
+	};
+
+int
+system(const char *str)
+{
+	int pid, exitstatus, waitval;
+	int i;
+
+	if ((pid = _fork()) < 0) return str ? -1 : 0;
+
+	if (pid == 0) {
+		for (i = 3; i <= 20; i++)
+			_close(i);
+		if (!str) str = "cd .";		/* just testing for a shell */
+		exec_tab[2] = str;		/* fill in command */
+		_execve("/bin/sh", exec_tab, *_penviron);
+		/* get here if execve fails ... */
+		_exit(FAIL);	/* see manual page */
+	}
+	while ((waitval = _wait(&exitstatus)) != pid) {
+		if (waitval == -1) break;
+	}
+	if (waitval == -1) {
+		/* no child ??? or maybe interrupted ??? */
+		exitstatus = -1;
+	}
+	if (!str) {
+		if (exitstatus == FAIL << 8)		/* execve() failed */
+			exitstatus = 0;
+		else exitstatus = 1;			/* /bin/sh exists */
+	}
+	return exitstatus;
+}
Index: /trunk/minix/lib/ansi/tolower.c
===================================================================
--- /trunk/minix/lib/ansi/tolower.c	(revision 9)
+++ /trunk/minix/lib/ansi/tolower.c	(revision 9)
@@ -0,0 +1,5 @@
+#include	<ctype.h>
+
+int tolower(int c) {
+	return isupper(c) ? c - 'A' + 'a' : c ;
+}
Index: /trunk/minix/lib/ansi/toupper.c
===================================================================
--- /trunk/minix/lib/ansi/toupper.c	(revision 9)
+++ /trunk/minix/lib/ansi/toupper.c	(revision 9)
@@ -0,0 +1,5 @@
+#include	<ctype.h>
+
+int toupper(int c) {
+	return islower(c) ? c - 'a' + 'A' : c ;
+}
Index: /trunk/minix/lib/ansi/tzset.c
===================================================================
--- /trunk/minix/lib/ansi/tzset.c	(revision 9)
+++ /trunk/minix/lib/ansi/tzset.c	(revision 9)
@@ -0,0 +1,15 @@
+/*
+ * tzset - set timezone information
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/tzset.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+/* This function is present for System V && POSIX */
+
+#include	<time.h>
+#include	"loc_time.h"
+
+void
+tzset(void)
+{
+	_tzset();	/* does the job */
+}
Index: /trunk/minix/lib/ansi/wcstombs.c
===================================================================
--- /trunk/minix/lib/ansi/wcstombs.c	(revision 9)
+++ /trunk/minix/lib/ansi/wcstombs.c	(revision 9)
@@ -0,0 +1,21 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/wcstombs.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<stdlib.h>
+#include	<locale.h>
+#include	<limits.h>
+
+size_t
+wcstombs(register char *s, register const wchar_t *pwcs, size_t n)
+{
+	register int i = n;
+
+	while (--i >= 0) {
+		if (!(*s++ = *pwcs++))
+			break;
+	}
+	return n - i - 1;
+}
Index: /trunk/minix/lib/ansi/wctomb.c
===================================================================
--- /trunk/minix/lib/ansi/wctomb.c	(revision 9)
+++ /trunk/minix/lib/ansi/wctomb.c	(revision 9)
@@ -0,0 +1,20 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ansi/wctomb.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
+
+#include	<stdlib.h>
+#include	<limits.h>
+
+int
+/* was: wctomb(char *s, wchar_t wchar) 
+ * This conflicts with prototype, so it was changed to:
+ */
+wctomb(char *s, wchar_t wchar)
+{
+	if (!s) return 0;		/* no state dependent codings */
+
+	*s = wchar;
+	return 1;
+}
Index: /trunk/minix/lib/curses/Makedepend-ack
===================================================================
--- /trunk/minix/lib/curses/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/curses/Makedepend-ack	(revision 9)
@@ -0,0 +1,41 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' beep.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' charpick.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' curs_set.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' cursesio.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' endwin.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' flash.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' initscr.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' longname.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' move.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' mvcursor.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' newwin.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' options.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' overlay.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' prntscan.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' refresh.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' scrreg.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' setterm.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' tabsize.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' termmisc.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' unctrl.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' update.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' waddch.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' waddstr.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' wbox.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' wclear.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' wclrtobot.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' wclrtoeol.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' wdelch.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' wdeleteln.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' werase.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' wgetch.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' wgetstr.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' windel.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' winmove.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' winsch.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' winscrol.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' winsertln.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' wintouch.c | sed -e 's:^\(.\):../obj-ack//./curses/\1:' >> .depend-ack
Index: /trunk/minix/lib/curses/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/curses/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/curses/Makedepend-gnu	(revision 9)
@@ -0,0 +1,41 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' beep.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' charpick.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' curs_set.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' cursesio.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' endwin.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' flash.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' initscr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' longname.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' move.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' mvcursor.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' newwin.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' options.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' overlay.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' prntscan.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' refresh.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' scrreg.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' setterm.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' tabsize.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' termmisc.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' unctrl.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' update.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' waddch.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' waddstr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' wbox.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' wclear.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' wclrtobot.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' wclrtoeol.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' wdelch.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' wdeleteln.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' werase.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' wgetch.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' wgetstr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' windel.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' winmove.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' winsch.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' winscrol.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' winsertln.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' wintouch.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./curses/\1:' >> .depend-gnu
Index: /trunk/minix/lib/curses/Makefile
===================================================================
--- /trunk/minix/lib/curses/Makefile	(revision 9)
+++ /trunk/minix/lib/curses/Makefile	(revision 9)
@@ -0,0 +1,311 @@
+#Generated from ./curses/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./curses ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./curses ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libcurses.a
+
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(beep.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(charpick.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(curs_set.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(cursesio.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(endwin.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(flash.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(initscr.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(longname.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(move.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(mvcursor.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(newwin.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(options.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(overlay.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(prntscan.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(refresh.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(scrreg.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(setterm.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(tabsize.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(termmisc.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(unctrl.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(update.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(waddch.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(waddstr.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(wbox.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(wclear.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(wclrtobot.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(wclrtoeol.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(wdelch.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(wdeleteln.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(werase.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(wgetch.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(wgetstr.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(windel.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(winmove.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(winsch.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(winscrol.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(winsertln.o)
+../obj-ack//libcurses.a: ../obj-ack//libcurses.a(wintouch.o)
+
+../obj-ack//libcurses.a:
+	ar cr ../obj-ack//libcurses.a ../obj-ack//./curses/*.o
+	rm ../obj-ack//./curses/*.o
+
+../obj-ack//libcurses.a(beep.o): beep.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/beep.o beep.c
+../obj-ack//libcurses.a(charpick.o): charpick.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/charpick.o charpick.c
+../obj-ack//libcurses.a(curs_set.o): curs_set.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/curs_set.o curs_set.c
+../obj-ack//libcurses.a(cursesio.o): cursesio.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/cursesio.o cursesio.c
+../obj-ack//libcurses.a(endwin.o): endwin.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/endwin.o endwin.c
+../obj-ack//libcurses.a(flash.o): flash.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/flash.o flash.c
+../obj-ack//libcurses.a(initscr.o): initscr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/initscr.o initscr.c
+../obj-ack//libcurses.a(longname.o): longname.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/longname.o longname.c
+../obj-ack//libcurses.a(move.o): move.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/move.o move.c
+../obj-ack//libcurses.a(mvcursor.o): mvcursor.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/mvcursor.o mvcursor.c
+../obj-ack//libcurses.a(newwin.o): newwin.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/newwin.o newwin.c
+../obj-ack//libcurses.a(options.o): options.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/options.o options.c
+../obj-ack//libcurses.a(overlay.o): overlay.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/overlay.o overlay.c
+../obj-ack//libcurses.a(prntscan.o): prntscan.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/prntscan.o prntscan.c
+../obj-ack//libcurses.a(refresh.o): refresh.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/refresh.o refresh.c
+../obj-ack//libcurses.a(scrreg.o): scrreg.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/scrreg.o scrreg.c
+../obj-ack//libcurses.a(setterm.o): setterm.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/setterm.o setterm.c
+../obj-ack//libcurses.a(tabsize.o): tabsize.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/tabsize.o tabsize.c
+../obj-ack//libcurses.a(termmisc.o): termmisc.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/termmisc.o termmisc.c
+../obj-ack//libcurses.a(unctrl.o): unctrl.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/unctrl.o unctrl.c
+../obj-ack//libcurses.a(update.o): update.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/update.o update.c
+../obj-ack//libcurses.a(waddch.o): waddch.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/waddch.o waddch.c
+../obj-ack//libcurses.a(waddstr.o): waddstr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/waddstr.o waddstr.c
+../obj-ack//libcurses.a(wbox.o): wbox.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/wbox.o wbox.c
+../obj-ack//libcurses.a(wclear.o): wclear.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/wclear.o wclear.c
+../obj-ack//libcurses.a(wclrtobot.o): wclrtobot.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/wclrtobot.o wclrtobot.c
+../obj-ack//libcurses.a(wclrtoeol.o): wclrtoeol.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/wclrtoeol.o wclrtoeol.c
+../obj-ack//libcurses.a(wdelch.o): wdelch.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/wdelch.o wdelch.c
+../obj-ack//libcurses.a(wdeleteln.o): wdeleteln.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/wdeleteln.o wdeleteln.c
+../obj-ack//libcurses.a(werase.o): werase.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/werase.o werase.c
+../obj-ack//libcurses.a(wgetch.o): wgetch.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/wgetch.o wgetch.c
+../obj-ack//libcurses.a(wgetstr.o): wgetstr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/wgetstr.o wgetstr.c
+../obj-ack//libcurses.a(windel.o): windel.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/windel.o windel.c
+../obj-ack//libcurses.a(winmove.o): winmove.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/winmove.o winmove.c
+../obj-ack//libcurses.a(winsch.o): winsch.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/winsch.o winsch.c
+../obj-ack//libcurses.a(winscrol.o): winscrol.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/winscrol.o winscrol.c
+../obj-ack//libcurses.a(winsertln.o): winsertln.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/winsertln.o winsertln.c
+../obj-ack//libcurses.a(wintouch.o): wintouch.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./curses/wintouch.o wintouch.c
+
+all-gnu: ../obj-gnu/libcurses.a
+
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/beep.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/charpick.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/curs_set.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/cursesio.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/endwin.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/flash.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/initscr.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/longname.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/move.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/mvcursor.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/newwin.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/options.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/overlay.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/prntscan.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/refresh.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/scrreg.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/setterm.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/tabsize.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/termmisc.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/unctrl.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/update.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/waddch.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/waddstr.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/wbox.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/wclear.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/wclrtobot.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/wclrtoeol.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/wdelch.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/wdeleteln.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/werase.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/wgetch.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/wgetstr.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/windel.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/winmove.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/winsch.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/winscrol.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/winsertln.o
+../obj-gnu/libcurses.a: ../obj-gnu/./curses/wintouch.o
+
+../obj-gnu/libcurses.a:
+	gar cr ../obj-gnu/libcurses.a $?
+
+../obj-gnu/./curses/beep.o: beep.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/beep.o beep.c
+
+../obj-gnu/./curses/charpick.o: charpick.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/charpick.o charpick.c
+
+../obj-gnu/./curses/curs_set.o: curs_set.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/curs_set.o curs_set.c
+
+../obj-gnu/./curses/cursesio.o: cursesio.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/cursesio.o cursesio.c
+
+../obj-gnu/./curses/endwin.o: endwin.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/endwin.o endwin.c
+
+../obj-gnu/./curses/flash.o: flash.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/flash.o flash.c
+
+../obj-gnu/./curses/initscr.o: initscr.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/initscr.o initscr.c
+
+../obj-gnu/./curses/longname.o: longname.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/longname.o longname.c
+
+../obj-gnu/./curses/move.o: move.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/move.o move.c
+
+../obj-gnu/./curses/mvcursor.o: mvcursor.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/mvcursor.o mvcursor.c
+
+../obj-gnu/./curses/newwin.o: newwin.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/newwin.o newwin.c
+
+../obj-gnu/./curses/options.o: options.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/options.o options.c
+
+../obj-gnu/./curses/overlay.o: overlay.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/overlay.o overlay.c
+
+../obj-gnu/./curses/prntscan.o: prntscan.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/prntscan.o prntscan.c
+
+../obj-gnu/./curses/refresh.o: refresh.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/refresh.o refresh.c
+
+../obj-gnu/./curses/scrreg.o: scrreg.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/scrreg.o scrreg.c
+
+../obj-gnu/./curses/setterm.o: setterm.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/setterm.o setterm.c
+
+../obj-gnu/./curses/tabsize.o: tabsize.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/tabsize.o tabsize.c
+
+../obj-gnu/./curses/termmisc.o: termmisc.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/termmisc.o termmisc.c
+
+../obj-gnu/./curses/unctrl.o: unctrl.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/unctrl.o unctrl.c
+
+../obj-gnu/./curses/update.o: update.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/update.o update.c
+
+../obj-gnu/./curses/waddch.o: waddch.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/waddch.o waddch.c
+
+../obj-gnu/./curses/waddstr.o: waddstr.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/waddstr.o waddstr.c
+
+../obj-gnu/./curses/wbox.o: wbox.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/wbox.o wbox.c
+
+../obj-gnu/./curses/wclear.o: wclear.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/wclear.o wclear.c
+
+../obj-gnu/./curses/wclrtobot.o: wclrtobot.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/wclrtobot.o wclrtobot.c
+
+../obj-gnu/./curses/wclrtoeol.o: wclrtoeol.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/wclrtoeol.o wclrtoeol.c
+
+../obj-gnu/./curses/wdelch.o: wdelch.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/wdelch.o wdelch.c
+
+../obj-gnu/./curses/wdeleteln.o: wdeleteln.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/wdeleteln.o wdeleteln.c
+
+../obj-gnu/./curses/werase.o: werase.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/werase.o werase.c
+
+../obj-gnu/./curses/wgetch.o: wgetch.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/wgetch.o wgetch.c
+
+../obj-gnu/./curses/wgetstr.o: wgetstr.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/wgetstr.o wgetstr.c
+
+../obj-gnu/./curses/windel.o: windel.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/windel.o windel.c
+
+../obj-gnu/./curses/winmove.o: winmove.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/winmove.o winmove.c
+
+../obj-gnu/./curses/winsch.o: winsch.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/winsch.o winsch.c
+
+../obj-gnu/./curses/winscrol.o: winscrol.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/winscrol.o winscrol.c
+
+../obj-gnu/./curses/winsertln.o: winsertln.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/winsertln.o winsertln.c
+
+../obj-gnu/./curses/wintouch.o: wintouch.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./curses/wintouch.o wintouch.c
+
+
+
+
+clean::
+	rm -f ../obj-ack//./curses/*
+	rm -f ../obj-gnu/./curses/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/curses/Makefile.in
===================================================================
--- /trunk/minix/lib/curses/Makefile.in	(revision 9)
+++ /trunk/minix/lib/curses/Makefile.in	(revision 9)
@@ -0,0 +1,47 @@
+# Makefile for lib/curses.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
+
+LIBRARIES=libcurses
+
+libcurses_FILES=" \
+	beep.c \
+	charpick.c \
+	curs_set.c \
+	cursesio.c \
+	endwin.c \
+	flash.c \
+	initscr.c \
+	longname.c \
+	move.c \
+	mvcursor.c \
+	newwin.c \
+	options.c \
+	overlay.c \
+	prntscan.c \
+	refresh.c \
+	scrreg.c \
+	setterm.c \
+	tabsize.c \
+	termmisc.c \
+	unctrl.c \
+	update.c \
+	waddch.c \
+	waddstr.c \
+	wbox.c \
+	wclear.c \
+	wclrtobot.c \
+	wclrtoeol.c \
+	wdelch.c \
+	wdeleteln.c \
+	werase.c \
+	wgetch.c \
+	wgetstr.c \
+	windel.c \
+	winmove.c \
+	winsch.c \
+	winscrol.c \
+	winsertln.c \
+	wintouch.c"
+
+TYPE=both
Index: /trunk/minix/lib/curses/beep.c
===================================================================
--- /trunk/minix/lib/curses/beep.c	(revision 9)
+++ /trunk/minix/lib/curses/beep.c	(revision 9)
@@ -0,0 +1,14 @@
+#include <curses.h>
+#include "curspriv.h"
+#include <termcap.h>
+
+extern char *bl, *vb;
+
+/* Beep() sounds the terminal bell. */
+void beep()
+{
+  if (bl)
+	tputs(bl, 1, outc);
+  else if (vb)
+	tputs(vb, 1, outc);
+}
Index: /trunk/minix/lib/curses/charpick.c
===================================================================
--- /trunk/minix/lib/curses/charpick.c	(revision 9)
+++ /trunk/minix/lib/curses/charpick.c	(revision 9)
@@ -0,0 +1,40 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Winch(win) returns the character at the current position in	*/
+/* Window 'win'.						*/
+/****************************************************************/
+
+int winch(win)
+WINDOW *win;
+{
+  return((win->_line[win->_cury][win->_curx]) & 0xff);
+}				/* winch */
+
+/****************************************************************/
+/* Mvinch() moves the stdscr cursor to a new position, then	*/
+/* Returns the character at that position.			*/
+/****************************************************************/
+
+int mvinch(y, x)
+int y;
+int x;
+{
+  if (wmove(stdscr, y, x) == ERR) return(ERR);
+  return((stdscr->_line[stdscr->_cury][stdscr->_curx]) & 0xff);
+}
+
+/****************************************************************/
+/* Mvwinch() moves the cursor of window 'win' to a new posi-	*/
+/* Tion, then returns the character at that position.		*/
+/****************************************************************/
+
+int mvwinch(win, y, x)
+WINDOW *win;
+int y;
+int x;
+{
+  if (wmove(win, y, x) == ERR) return(ERR);
+  return((win->_line[win->_cury][win->_curx]) & 0xff);
+}
Index: /trunk/minix/lib/curses/curs_set.c
===================================================================
--- /trunk/minix/lib/curses/curs_set.c	(revision 9)
+++ /trunk/minix/lib/curses/curs_set.c	(revision 9)
@@ -0,0 +1,26 @@
+#include <curses.h>
+#include "curspriv.h"
+#include <termcap.h>
+
+extern char *vi, *ve, *vs;
+
+/* Sets cursor visibility to unvisible=0; normal visible=1 or very good
+ * visible=2. 
+*/
+void curs_set(visibility)
+int visibility;
+{
+  switch (visibility) {
+      case 0:
+	if (vi) tputs(vi, 1, outc);
+	break;
+      case 1:
+	if (ve) tputs(ve, 1, outc);
+	break;
+      case 2:
+	if (vs)
+		tputs(vs, 1, outc);
+	else if (ve)
+		tputs(ve, 1, outc);
+  }
+}
Index: /trunk/minix/lib/curses/cursesio.c
===================================================================
--- /trunk/minix/lib/curses/cursesio.c	(revision 9)
+++ /trunk/minix/lib/curses/cursesio.c	(revision 9)
@@ -0,0 +1,223 @@
+#include <stdlib.h>
+#include <termcap.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <curses.h>
+#include "curspriv.h"
+
+struct termios _orig_tty, _tty;
+cursv _cursvar;
+
+WINDOW *stdscr, *curscr;
+int LINES, COLS;
+bool NONL;
+
+char termcap[1024];		/* termcap buffer */
+char tc[200];			/* area to hold string capabilities */
+char *ttytype;			/* terminal type from env */
+static char *arp;		/* pointer for use in tgetstr */
+char *cp;			/* character pointer */
+
+char *cl;			/* clear screen capability */
+char *cm;			/* cursor motion capability */
+char *so;			/* start standout capability */
+char *se;			/* end standout capability */
+char *mr;			/* start of reverse */
+char *me;			/* revert to normal */
+char *mb;			/* start of blink */
+char *md;			/* start of bold */
+char *us;			/* start of underscore */
+char *ue;			/* end of underscore */
+char *vi;			/* cursor invisible */
+char *ve;			/* cursor normal */
+char *vs;			/* cursor good visible */
+char *as;			/* alternative charset start */
+char *ae;			/* alternative charset end */
+char *bl;			/* ring the bell */
+char *vb;			/* visual bell */
+
+/* fatal - report error and die. Never returns */
+void fatal(s)
+char *s;
+{
+  (void) fprintf(stderr, "curses: %s\n", s);
+  exit(1);
+}
+
+/* Outc - call putchar, necessary because putchar is a macro. */
+void outc(c)
+int c;
+{
+  putchar(c);
+}
+
+/* Move cursor to r,c */
+void poscur(r, c)
+int r, c;
+{
+  tputs(tgoto(cm, c, r), 1, outc);
+}
+
+/* Clear the screen */
+void clrscr()
+{
+  tputs(cl, 1, outc);
+}
+
+/* This are terminal independent characters which can be used in curses */
+
+unsigned int ACS_ULCORNER;
+unsigned int ACS_LLCORNER;
+unsigned int ACS_URCORNER;
+unsigned int ACS_LRCORNER;
+unsigned int ACS_RTEE;
+unsigned int ACS_LTEE;
+unsigned int ACS_BTEE;
+unsigned int ACS_TTEE;
+unsigned int ACS_HLINE;
+unsigned int ACS_VLINE;
+unsigned int ACS_PLUS;
+unsigned int ACS_S1;
+unsigned int ACS_S9;
+unsigned int ACS_DIAMOND;
+unsigned int ACS_CKBOARD;
+unsigned int ACS_DEGREE;
+unsigned int ACS_PLMINUS;
+unsigned int ACS_BULLET;
+unsigned int ACS_LARROW;
+unsigned int ACS_RARROW;
+unsigned int ACS_DARROW;
+unsigned int ACS_UARROW;
+unsigned int ACS_BOARD;
+unsigned int ACS_LANTERN;
+unsigned int ACS_BLOCK;
+
+/* These defines describe the full set of grafic block characters which
+ * can be defined via termcap.
+ */
+
+#define RIGHTARROW  0
+#define LEFTARROW   1
+#define DOWNARROW   2
+#define UPARROW     3
+#define FULLSQUARE  4
+#define GREYSQUARE  5
+#define EMPTYSQUARE 6
+#define LATERN      7
+#define DIAMOND     8
+#define DEGREE      9
+#define PLUSMINUS  10
+#define DOWNRIGHT  11
+#define UPRIGHT    12
+#define UPLEFT     13
+#define DOWNLEFT   14
+#define CROSS      15
+#define UPLINE     16
+#define UPMIDLINE  17
+#define MIDLINE    18
+#define DOMIDLINE  19
+#define DOWNLINE   20
+#define TEELEFT    21
+#define TEERIGHT   22
+#define TEEHEAD    23
+#define TEENORMAL  24
+#define VERTLINE   25
+#define PARAGRAPH  26
+
+unsigned int _cursgraftable[27] =
+{
+ '>', '<', 'v', '^', '#', ':', ' ', '#', '+', '\'', '#', '+', '+',
+ '+', '+', '+', '-', ' ', '-', ' ', '_', '+', '+', '+', '+', '|'
+};
+char _cursident[28] = "+,.-0ahI`fgjklmnopqrstuvwx~";
+
+int setterm(type)
+char *type;
+{
+  unsigned char *ac;
+  int i;
+#ifdef TIOCGWINSZ
+  struct winsize wsize;
+#endif
+
+  if (tgetent(termcap, type) != 1) return ERR;
+
+#ifdef TIOCGWINSZ
+  if (ioctl(0, TIOCGWINSZ, &wsize) == 0) {
+	LINES = wsize.ws_row != 0 ? wsize.ws_row : tgetnum("li");
+	COLS = wsize.ws_col != 0 ? wsize.ws_col : tgetnum("co");
+  } else {
+#endif
+	LINES = tgetnum("li");
+	COLS = tgetnum("co");
+#ifdef TIOCGWINSZ
+  }
+#endif
+  arp = tc;
+  cl = tgetstr("cl", &arp);
+  so = tgetstr("so", &arp);
+  se = tgetstr("se", &arp);
+  cm = tgetstr("cm", &arp);
+  mr = tgetstr("mr", &arp);
+  me = tgetstr("me", &arp);
+  mb = tgetstr("mb", &arp);
+  md = tgetstr("md", &arp);
+  us = tgetstr("us", &arp);
+  ue = tgetstr("ue", &arp);
+  vi = tgetstr("vi", &arp);
+  ve = tgetstr("ve", &arp);
+  vs = tgetstr("vs", &arp);
+  as = tgetstr("as", &arp);
+  ae = tgetstr("ae", &arp);
+  ac = (unsigned char *) tgetstr("ac", &arp);
+  bl = tgetstr("bl", &arp);
+  vb = tgetstr("vb", &arp);
+
+  if (ac) {
+	while (*ac) {
+		i = 0;
+		while (*ac != _cursident[i]) i++;
+		_cursgraftable[i] = *++ac | A_ALTCHARSET;
+		ac++;
+	}
+  }
+
+  ACS_ULCORNER = _cursgraftable[UPLEFT];
+  ACS_LLCORNER = _cursgraftable[DOWNLEFT];
+  ACS_URCORNER = _cursgraftable[UPRIGHT];
+  ACS_LRCORNER = _cursgraftable[DOWNRIGHT];
+  ACS_RTEE = _cursgraftable[TEERIGHT];
+  ACS_LTEE = _cursgraftable[TEELEFT];
+  ACS_BTEE = _cursgraftable[TEEHEAD];
+  ACS_TTEE = _cursgraftable[TEENORMAL];
+  ACS_HLINE = _cursgraftable[MIDLINE];
+  ACS_VLINE = _cursgraftable[VERTLINE];
+  ACS_PLUS = _cursgraftable[CROSS];
+  ACS_S1 = _cursgraftable[UPLINE];
+  ACS_S9 = _cursgraftable[DOWNLINE];
+  ACS_DIAMOND = _cursgraftable[DIAMOND];
+  ACS_CKBOARD = _cursgraftable[GREYSQUARE];
+  ACS_DEGREE = _cursgraftable[DEGREE];
+  ACS_PLMINUS = _cursgraftable[PLUSMINUS];
+  ACS_BULLET = 'o';		/* where the hell is a bullet defined in
+			 * termcap ??? */
+  ACS_LARROW = _cursgraftable[LEFTARROW];
+  ACS_RARROW = _cursgraftable[RIGHTARROW];
+  ACS_DARROW = _cursgraftable[DOWNARROW];
+  ACS_UARROW = _cursgraftable[UPARROW];
+  ACS_BOARD = _cursgraftable[EMPTYSQUARE];
+  ACS_LANTERN = _cursgraftable[LATERN];
+  ACS_BLOCK = _cursgraftable[FULLSQUARE];
+  /* Wow, I got it! */
+  return OK;
+}
+
+void gettmode()
+{
+  tcgetattr(0, &_orig_tty);
+  tcgetattr(0, &_tty);
+  _cursvar.echoit = (_tty.c_lflag & ECHO) != 0;
+  _cursvar.rawmode = (_tty.c_lflag & (ICANON|ISIG)) == 0;
+  _cursvar.cbrkmode = (_tty.c_lflag & (ICANON|ISIG)) == ISIG;
+  NONL = (_tty.c_iflag & ICRNL) != 0;
+}
Index: /trunk/minix/lib/curses/curspriv.h
===================================================================
--- /trunk/minix/lib/curses/curspriv.h	(revision 9)
+++ /trunk/minix/lib/curses/curspriv.h	(revision 9)
@@ -0,0 +1,36 @@
+/* Constants */
+#define	_SUBWIN		1		/* window is a subwindow */
+#define	_ENDLINE	2		/* last winline is last screen line */
+#define	_FULLWIN	4		/* window fills screen */
+#define	_SCROLLWIN	8		/* window lwr rgt is screen lwr rgt */
+
+#define	_NO_CHANGE	-1		/* flags line edge unchanged */
+#define	_BREAKCHAR	0x03		/* ^C character */
+#define _DCCHAR		0x08		/* Delete Char char (BS) */
+#define _DLCHAR		0x1b		/* Delete Line char (ESC) */
+#define	_GOCHAR		0x11		/* ^Q character */
+#define	_PRINTCHAR	0x10		/* ^P character */
+#define	_STOPCHAR	0x13		/* ^S character */
+#define	 NUNGETCH	10		/* max # chars to ungetch() */
+
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+
+/* Character mask definitions. */
+#define CHR_MSK	((int) 0x00ff)		/* ASCIIZ character mask */
+#define	ATR_MSK	((int) 0xff00)		/* attribute mask */
+#define ATR_NRM	((int) 0x0000)		/* no special attributes */
+
+/* Type declarations. */
+
+typedef	struct {
+  WINDOW  *tmpwin;			/* window used for updates */
+  int	   cursrow;			/* position of physical cursor */
+  int	   curscol;
+  bool     rawmode;
+  bool     cbrkmode;
+  bool     echoit;
+} cursv;
+
+/* External variables */
+extern	cursv   _cursvar;		/* curses variables */
Index: /trunk/minix/lib/curses/endwin.c
===================================================================
--- /trunk/minix/lib/curses/endwin.c	(revision 9)
+++ /trunk/minix/lib/curses/endwin.c	(revision 9)
@@ -0,0 +1,18 @@
+#include <curses.h>
+#include "curspriv.h"
+#include <termcap.h>
+
+int endwin()
+{
+  extern char *me;
+
+  curs_set(1);
+  poscur(LINES - 1, 0);
+  refresh();
+  tputs(me, 1, outc);
+  delwin(stdscr);
+  delwin(curscr);
+  delwin(_cursvar.tmpwin);
+  resetty();
+  return(OK);
+}
Index: /trunk/minix/lib/curses/flash.c
===================================================================
--- /trunk/minix/lib/curses/flash.c	(revision 9)
+++ /trunk/minix/lib/curses/flash.c	(revision 9)
@@ -0,0 +1,14 @@
+#include <curses.h>
+#include "curspriv.h"
+#include <termcap.h>
+
+extern char *bl, *vb;
+
+/* Flash() flashes the terminal screen. */
+void flash()
+{
+  if (vb)
+	tputs(vb, 1, outc);
+  else if (bl)
+	tputs(bl, 1, outc);
+}
Index: /trunk/minix/lib/curses/initscr.c
===================================================================
--- /trunk/minix/lib/curses/initscr.c	(revision 9)
+++ /trunk/minix/lib/curses/initscr.c	(revision 9)
@@ -0,0 +1,19 @@
+/* initscr.c - initialize the curses library */
+
+#include <stdlib.h>
+#include <curses.h>
+#include "curspriv.h"
+
+WINDOW *initscr()
+{
+  char *term;
+
+  if ((term = getenv("TERM")) == NULL) return NULL;
+  setterm(term);
+  gettmode();
+  if ((_cursvar.tmpwin = newwin(LINES, COLS, 0, 0)) == NULL) return NULL;
+  if ((curscr = newwin(LINES, COLS, 0, 0)) == NULL) return NULL;
+  if ((stdscr = newwin(LINES, COLS, 0, 0)) == NULL) return NULL;
+  clearok(curscr, TRUE);
+  return(stdscr);
+}
Index: /trunk/minix/lib/curses/longname.c
===================================================================
--- /trunk/minix/lib/curses/longname.c	(revision 9)
+++ /trunk/minix/lib/curses/longname.c	(revision 9)
@@ -0,0 +1,12 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Longname() returns a pointer to a string describing the	*/
+/* User terminal.						*/
+/****************************************************************/
+
+char *longname()
+{
+  return("not implemented");
+}
Index: /trunk/minix/lib/curses/move.c
===================================================================
--- /trunk/minix/lib/curses/move.c	(revision 9)
+++ /trunk/minix/lib/curses/move.c	(revision 9)
@@ -0,0 +1,18 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Wmove() moves the cursor in window 'win' to position (x,y).	*/
+/****************************************************************/
+
+int wmove(win, y, x)
+WINDOW *win;
+int y;
+int x;
+{
+  if ((x<0) || (x>win->_maxx) || (y<win->_regtop) || (y>win->_regbottom)) 
+	return(ERR);
+  win->_curx = x;
+  win->_cury = y;
+  return(OK);
+}
Index: /trunk/minix/lib/curses/mvcursor.c
===================================================================
--- /trunk/minix/lib/curses/mvcursor.c	(revision 9)
+++ /trunk/minix/lib/curses/mvcursor.c	(revision 9)
@@ -0,0 +1,20 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Mvcur(oldy,oldx,newy,newx) the display cursor to <newy,newx>	*/
+/****************************************************************/
+
+int mvcur(oldy, oldx, newy, newx)
+int oldy;
+int oldx;
+int newy;
+int newx;
+{
+  if ((newy >= LINES) || (newx >= COLS) || (newy < 0) || (newx < 0))
+	return(ERR);
+  poscur(newy, newx);
+  _cursvar.cursrow = newy;
+  _cursvar.curscol = newx;
+  return(OK);
+}
Index: /trunk/minix/lib/curses/newwin.c
===================================================================
--- /trunk/minix/lib/curses/newwin.c	(revision 9)
+++ /trunk/minix/lib/curses/newwin.c	(revision 9)
@@ -0,0 +1,144 @@
+#include <stdlib.h>
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Makenew() allocates all data for a new window except the	*/
+/* Actual lines themselves.					*/
+/****************************************************************/
+
+_PROTOTYPE(static WINDOW *makenew, (int nlines, int ncols, int begy,int begx));
+
+static WINDOW *makenew(num_lines, num_columns, begy, begx)
+int num_lines, num_columns, begy, begx;
+{
+  int i;
+  WINDOW *win;
+
+  /* Allocate the window structure itself */
+  if ((win = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) 
+	return((WINDOW *) ERR);
+
+  /* Allocate the line pointer array */
+  if ((win->_line = (int **) calloc(num_lines, sizeof(int *))) == NULL) {
+	free(win);
+	return((WINDOW *) ERR);
+  }
+
+  /* Allocate the minchng and maxchng arrays */
+  if ((win->_minchng = (int *) calloc(num_lines, sizeof(int))) == NULL) {
+	free(win);
+	free(win->_line);
+	return((WINDOW *) ERR);
+  }
+  if ((win->_maxchng = (int *) calloc(num_lines, sizeof(int))) == NULL) {
+	free(win);
+	free(win->_line);
+	free(win->_minchng);
+	return((WINDOW *) ERR);
+  }
+
+  /* Initialize window variables */
+  win->_curx = 0;
+  win->_cury = 0;
+  win->_maxy = num_lines - 1;
+  win->_maxx = num_columns - 1;
+  win->_begy = begy;
+  win->_begx = begx;
+  win->_flags = 0;
+  win->_attrs = ATR_NRM;
+  win->_tabsize = 8;
+  win->_clear = FALSE;
+  win->_leave = FALSE;
+  win->_scroll = FALSE;
+  win->_nodelay = FALSE;
+  win->_keypad = FALSE;
+  win->_regtop = 0;
+  win->_regbottom = num_lines - 1;
+
+  /* Init to say window unchanged */
+  for (i = 0; i < num_lines; i++) {
+	win->_minchng[i] = 0;
+	win->_maxchng[i] = num_columns - 1;
+  }
+
+  /* Set flags for window properties */
+  if ((begy + num_lines) == LINES) {
+	win->_flags |= _ENDLINE;
+	if ((begx == 0) && (num_columns == COLS) && (begy == 0))
+		win->_flags |= _FULLWIN;
+  }				/* if */
+  if (((begy + num_lines) == LINES) && ((begx + num_columns) == COLS))
+	win->_flags |= _SCROLLWIN;
+  return(win);
+}
+
+
+/****************************************************************/
+/* Newwin() creates a new window with size num_lines * num_co-	*/
+/* Lumns, and origin begx,begy relative to the SCREEN. Special	*/
+/* Case: if num_lines and/or num_columns is 0, the remainder of	*/
+/* The screen is used.						*/
+/****************************************************************/
+WINDOW *newwin(num_lines, num_columns, begy, begx)
+int num_lines, num_columns, begy, begx;
+{
+  WINDOW *win;
+  int *ptr;
+  int i, j;
+
+  if (num_lines == 0) num_lines = LINES - begy;
+  if (num_columns == 0) num_columns = COLS - begx;
+  if ((win = makenew(num_lines, num_columns, begy, begx)) == (WINDOW *) ERR)
+	return((WINDOW *) ERR);
+  for (i = 0; i < num_lines; i++) {	/* make and clear the lines */
+	if ((win->_line[i] = (int *)calloc(num_columns, sizeof(int))) == NULL){
+		for (j = 0; j < i; j++)	/* if error, free all the data */
+			free(win->_line[j]);
+		free(win->_minchng);
+		free(win->_maxchng);
+		free(win->_line);
+		free(win);
+		return((WINDOW *) ERR);
+	} else {
+		for (ptr = win->_line[i]; ptr < win->_line[i] + num_columns;)
+			*ptr++ = ' ' | ATR_NRM;
+	}
+  }
+  return(win);
+}
+
+
+/****************************************************************/
+/* Subwin() creates a sub-window in the 'orig' window, with	*/
+/* Size num_lines * num_columns, and with origin begx, begy	*/
+/* Relative to the SCREEN. Special case: if num_lines and/or	*/
+/* Num_columns is 0, the remainder of the original window is	*/
+/* Used. The subwindow uses the original window's line buffers	*/
+/* To store it's own lines.					*/
+/****************************************************************/
+WINDOW *subwin(orig, num_lines, num_columns, begy, begx)
+WINDOW *orig;
+int num_lines, num_columns, begy, begx;
+{
+  WINDOW *win;
+  int i, j, k;
+
+  /* Make sure window fits inside the original one */
+  if (begy < orig->_begy || begx < orig->_begx ||
+		      (begy + num_lines) > (orig->_begy + orig->_maxy) ||
+		      (begx + num_columns) > (orig->_begx + orig->_maxx) )
+	return((WINDOW *) ERR);
+
+  if (num_lines == 0) num_lines = orig->_maxy - (begy - orig->_begy);
+  if (num_columns == 0) num_columns = orig->_maxx - (begx - orig->_begx);
+  if ((win = makenew(num_lines, num_columns, begy, begx)) == (WINDOW *) ERR)
+	return((WINDOW *) ERR);
+
+  /* Set line pointers the same as in the original window */
+  j = begy - orig->_begy;
+  k = begx - orig->_begx;
+  for (i = 0; i < num_lines; i++) win->_line[i] = (orig->_line[j++]) + k;
+  win->_flags |= _SUBWIN;
+  return(win);
+}
Index: /trunk/minix/lib/curses/options.c
===================================================================
--- /trunk/minix/lib/curses/options.c	(revision 9)
+++ /trunk/minix/lib/curses/options.c	(revision 9)
@@ -0,0 +1,87 @@
+#include <curses.h>
+#include "curspriv.h"
+
+static bool hasold = FALSE;	/* for remembering old cursor type */
+static int oldmode;
+
+/****************************************************************/
+/* Idlok() is used to set  flag for using the terminal insert/	*/
+/* Delete line capabilities. This is not relevant for the PC	*/
+/* Version of curses, and thus nothing is done.			*/
+/****************************************************************/
+void idlok(win, flag)
+WINDOW *win;
+bool flag;
+{
+}
+
+/****************************************************************/
+/* Clearok() marks window 'win' to cause screen clearing and	*/
+/* Redraw the next time a refresh is done.			*/
+/****************************************************************/
+void clearok(win, flag)
+WINDOW *win;
+bool flag;
+{
+  if (win == curscr)
+	_cursvar.tmpwin->_clear = flag;
+  else
+	win->_clear = flag;
+}
+
+/****************************************************************/
+/* Leaveok() marks window 'win' to allow the update routines	*/
+/* To leave the hardware cursor where it happens to be at the	*/
+/* End of update. Usually used in combination with cursoff().	*/
+/****************************************************************/
+
+void leaveok(win, flag)
+WINDOW *win;
+bool flag;
+{
+  win->_leave = flag;
+}
+
+/****************************************************************/
+/* Scrollok() marks window 'win' to allow the scrolling region	*/
+/* Of it to actually scroll.					*/
+/****************************************************************/
+void scrollok(win, flag)
+WINDOW *win;
+bool flag;
+{
+  win->_scroll = flag;
+}
+
+/****************************************************************/
+/* Nodelay() marks the window to make character input non-	*/
+/* Waiting, i.e. if there is no character to get, -1 will be	*/
+/* Returned.							*/
+/****************************************************************/
+void nodelay(win, flag)
+WINDOW *win;
+bool flag;
+{
+  win->_nodelay = flag;
+}
+
+/****************************************************************/
+/* Keypad() marks window 'win' to use the special keypad mode.	*/
+/****************************************************************/
+void keypad(win, flag)
+WINDOW *win;
+bool flag;
+{
+  win->_keypad = flag;
+}
+
+/****************************************************************/
+/* Meta() allows use of any alternate character set allowed by	*/
+/* The terminal. We always allow this on the PC, so this one	*/
+/* Does nothing.						*/
+/****************************************************************/
+void meta(win, flag)
+WINDOW *win;
+bool flag;
+{
+}
Index: /trunk/minix/lib/curses/overlay.c
===================================================================
--- /trunk/minix/lib/curses/overlay.c	(revision 9)
+++ /trunk/minix/lib/curses/overlay.c	(revision 9)
@@ -0,0 +1,124 @@
+/****************************************************************/
+/* Overlay() and overwrite() functions of the PCcurses package	*/
+/*								*/
+/****************************************************************/
+/* This version of curses is based on ncurses, a curses version	*/
+/* Originally written by Pavel Curtis at Cornell University.	*/
+/* I have made substantial changes to make it run on IBM PC's,	*/
+/* And therefore consider myself free to make it public domain.	*/
+/*		Bjorn Larsson (...mcvax!enea!infovax!bl)	*/
+/****************************************************************/
+/* 1.0:	Release:					870515	*/
+/****************************************************************/
+/* Modified to run under the MINIX operating system by Don Cope */
+/* These changes are also released into the public domain.      */
+/* 							900906  */
+/****************************************************************/
+
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Overlay() overwrites 'win1' upon 'win2', with origins alig-	*/
+/* Ned. Overlay is transparent; blanks from 'win1' are not	*/
+/* Copied to 'win2'.						*/
+/****************************************************************/
+void overlay(win1, win2)
+WINDOW *win1, *win2;
+{
+  int *minchng;
+  int *maxchng;
+  int *w1ptr;
+  int *w2ptr;
+  int attrs;
+  int col;
+  int line;
+  int last_line;
+  int last_col;
+
+  last_col = min(win1->_maxx, win2->_maxx);
+  last_line = min(win1->_maxy, win2->_maxy);
+  attrs = win2->_attrs & ATR_MSK;
+  minchng = win2->_minchng;
+  maxchng = win2->_maxchng;
+
+  for (line = 0; line <= last_line; line++) {
+	register short fc, lc = 0;
+	w1ptr = win1->_line[line];
+	w2ptr = win2->_line[line];
+	fc = _NO_CHANGE;
+	for (col = 0; col <= last_col; col++) {
+		if ((*w1ptr & CHR_MSK) != ' ') {
+			*w2ptr = (*w1ptr & CHR_MSK) | attrs;
+			if (fc == _NO_CHANGE) fc = col;
+			lc = col;
+		}
+		w1ptr++;
+		w2ptr++;
+	}
+
+	if (*minchng == _NO_CHANGE) {
+		*minchng = fc;
+		*maxchng = lc;
+	} else if (fc != _NO_CHANGE) {
+		if (fc < *minchng) *minchng = fc;
+		if (lc > *maxchng) *maxchng = lc;
+	}
+	minchng++;
+	maxchng++;
+  }				/* for */
+}				/* overlay */
+
+/****************************************************************/
+/* Overwrite() overwrites 'win1' upon 'win2', with origins	*/
+/* Aligned. Overwrite is non-transparent; blanks from 'win1'	*/
+/* Are copied to 'win2'.					*/
+/****************************************************************/
+void overwrite(win1, win2)
+WINDOW *win1, *win2;
+{
+  int *minchng;
+  int *maxchng;
+  int *w1ptr;
+  int *w2ptr;
+  int attrs;
+  int col;
+  int line;
+  int last_line;
+  int last_col;
+
+  last_col = min(win1->_maxx, win2->_maxx);
+  last_line = min(win1->_maxy, win2->_maxy);
+  attrs = win2->_attrs & ATR_MSK;
+  minchng = win2->_minchng;
+  maxchng = win2->_maxchng;
+
+  for (line = 0; line <= last_line; line++) {
+	register short fc, lc = 0;
+
+	w1ptr = win1->_line[line];
+	w2ptr = win2->_line[line];
+	fc = _NO_CHANGE;
+
+	for (col = 0; col <= last_col; col++) {
+		if ((*w1ptr & CHR_MSK) != (*w2ptr & CHR_MSK)) {
+			*w2ptr = (*w1ptr & CHR_MSK) | attrs;
+
+			if (fc == _NO_CHANGE) fc = col;
+			lc = col;
+		}
+		w1ptr++;
+		w2ptr++;
+	}			/* for */
+
+	if (*minchng == _NO_CHANGE) {
+		*minchng = fc;
+		*maxchng = lc;
+	} else if (fc != _NO_CHANGE) {
+		if (fc < *minchng) *minchng = fc;
+		if (lc > *maxchng) *maxchng = lc;
+	}
+	minchng++;
+	maxchng++;
+  }
+}
Index: /trunk/minix/lib/curses/prntscan.c
===================================================================
--- /trunk/minix/lib/curses/prntscan.c	(revision 9)
+++ /trunk/minix/lib/curses/prntscan.c	(revision 9)
@@ -0,0 +1,129 @@
+#include <string.h>
+#include <curses.h>
+#include "curspriv.h"
+
+static char printscanbuf[513];	/* buffer used during I/O */
+
+/****************************************************************/
+/* Wprintw(win,fmt,args) does a printf() in window 'win'.	*/
+/****************************************************************/
+int wprintw(WINDOW *win, const char *fmt, ...)
+{
+  va_list args;
+
+  va_start(args, fmt);
+  vsprintf(printscanbuf, fmt, args);
+  if (waddstr(win, printscanbuf) == ERR) return(ERR);
+  return(strlen(printscanbuf));
+}
+
+/****************************************************************/
+/* Printw(fmt,args) does a printf() in stdscr.			*/
+/****************************************************************/
+int printw(const char *fmt, ...)
+{
+  va_list args;
+
+  va_start(args, fmt);
+  vsprintf(printscanbuf, fmt, args);
+  if (waddstr(stdscr, printscanbuf) == ERR) return(ERR);
+  return(strlen(printscanbuf));
+}				/* printw */
+
+/****************************************************************/
+/* Mvprintw(fmt,args) moves the stdscr cursor to a new posi-	*/
+/* tion, then does a printf() in stdscr.			*/
+/****************************************************************/
+int mvprintw(int y, int x, const char *fmt, ...)
+{
+  va_list args;
+
+  va_start(args, fmt);
+  if (wmove(stdscr, y, x) == ERR) return(ERR);
+  vsprintf(printscanbuf, fmt, args);
+  if (waddstr(stdscr, printscanbuf) == ERR) return(ERR);
+  return(strlen(printscanbuf));
+}
+
+/****************************************************************/
+/* Mvwprintw(win,fmt,args) moves the window 'win's cursor to	*/
+/* A new position, then does a printf() in window 'win'.	*/
+/****************************************************************/
+int mvwprintw(WINDOW *win, int y, int x, const char *fmt, ...)
+{
+  va_list args;
+
+  va_start(args, fmt);
+  if (wmove(win, y, x) == ERR) return(ERR);
+  vsprintf(printscanbuf, fmt, args);
+  if (waddstr(win, printscanbuf) == ERR) return(ERR);
+  return(strlen(printscanbuf));
+}				/* mvwprintw */
+
+/****************************************************************/
+/* Wscanw(win,fmt,args) gets a string via window 'win', then	*/
+/* Scans the string using format 'fmt' to extract the values	*/
+/* And put them in the variables pointed to the arguments.	*/
+/****************************************************************/
+int wscanw(WINDOW *win, const char *fmt, ...)
+{
+  va_list args;
+
+  va_start(args, fmt);
+  wrefresh(win);		/* set cursor */
+  if (wgetstr(win, printscanbuf) == ERR)	/* get string */
+	return(ERR);
+  return(vsscanf(printscanbuf, fmt, args));
+}				/* wscanw */
+
+/****************************************************************/
+/* Scanw(fmt,args) gets a string via stdscr, then scans the	*/
+/* String using format 'fmt' to extract the values and put them	*/
+/* In the variables pointed to the arguments.			*/
+/****************************************************************/
+int scanw(const char *fmt, ...)
+{
+  va_list args;
+
+  va_start(args, fmt);
+  wrefresh(stdscr);		/* set cursor */
+  if (wgetstr(stdscr, printscanbuf) == ERR)	/* get string */
+	return(ERR);
+  return(vsscanf(printscanbuf, fmt, args));
+}				/* scanw */
+
+/****************************************************************/
+/* Mvscanw(y,x,fmt,args) moves stdscr's cursor to a new posi-	*/
+/* Tion, then gets a string via stdscr and scans the string	*/
+/* Using format 'fmt' to extract the values and put them in the	*/
+/* Variables pointed to the arguments.				*/
+/****************************************************************/
+int mvscanw(int y, int x, const char *fmt, ...)
+{
+  va_list args;
+
+  va_start(args, fmt);
+  if (wmove(stdscr, y, x) == ERR) return(ERR);
+  wrefresh(stdscr);		/* set cursor */
+  if (wgetstr(stdscr, printscanbuf) == ERR)	/* get string */
+	return(ERR);
+  return(vsscanf(printscanbuf, fmt, args));
+}				/* mvscanw */
+
+/****************************************************************/
+/* Mvwscanw(win,y,x,fmt,args) moves window 'win's cursor to a	*/
+/* New position, then gets a string via 'win' and scans the	*/
+/* String using format 'fmt' to extract the values and put them	*/
+/* In the variables pointed to the arguments.			*/
+/****************************************************************/
+int mvwscanw(WINDOW *win, int y, int x, const char *fmt, ...)
+{
+  va_list args;
+
+  va_start(args, fmt);
+  if (wmove(win, y, x) == ERR) return(ERR);
+  wrefresh(win);		/* set cursor */
+  if (wgetstr(win, printscanbuf) == ERR)	/* get string */
+	return(ERR);
+  return(vsscanf(printscanbuf, fmt, args));
+}				/* mvwscanw */
Index: /trunk/minix/lib/curses/refresh.c
===================================================================
--- /trunk/minix/lib/curses/refresh.c	(revision 9)
+++ /trunk/minix/lib/curses/refresh.c	(revision 9)
@@ -0,0 +1,72 @@
+/* refresh.c */
+
+#include <curses.h>
+#include "curspriv.h"
+
+/* Wrefresh() updates window win's area of the physical screen.	*/
+void wrefresh(win)
+WINDOW *win;
+{
+  if (win == curscr)
+	curscr->_clear = TRUE;
+  else
+	wnoutrefresh(win);
+  doupdate();
+}
+
+/****************************************************************/
+/* Wnoutrefresh() updates the image of the desired screen,	*/
+/* Without doing physical update (copies window win's image to	*/
+/* The _cursvar.tmpwin window, which is hidden from the user).	*/
+/****************************************************************/
+
+void wnoutrefresh(win)
+register WINDOW *win;
+{
+  register int *dst;		/* start destination in temp window */
+  register int *end;		/* end destination in temp window */
+  register int *src;		/* source in user window */
+  register int first;		/* first changed char on line */
+  register int last;		/* last changed char on line */
+  WINDOW *nscr;
+  int begy;			/* window's place on screen */
+  int begx;
+  int i;
+  int j;
+
+  nscr = _cursvar.tmpwin;
+  begy = win->_begy;
+  begx = win->_begx;
+
+  for (i = 0, j = begy; i <= win->_maxy; i++, j++) {
+	if (win->_minchng[i] != _NO_CHANGE) {
+		first = win->_minchng[i];
+		last = win->_maxchng[i];
+		dst = &(nscr->_line[j][begx + first]);
+		end = &(nscr->_line[j][begx + last]);
+		src = &(win->_line[i][first]);
+
+		while (dst <= end)	/* copy user line to temp window */
+			*dst++ = *src++;
+
+		first += begx;	/* nscr's min/max change positions */
+		last += begx;
+
+		if ((nscr->_minchng[j] == _NO_CHANGE) || (nscr->_minchng[j] > first))
+			nscr->_minchng[j] = first;
+		if (last > nscr->_maxchng[j]) nscr->_maxchng[j] = last;
+
+		win->_minchng[i] = _NO_CHANGE;	/* updated now */
+	}			/* if */
+	win->_maxchng[i] = _NO_CHANGE;	/* updated now */
+  }				/* for */
+
+  if (win->_clear) {
+	win->_clear = FALSE;
+	nscr->_clear = TRUE;
+  }				/* if */
+  if (!win->_leave) {
+	nscr->_cury = win->_cury + begy;
+	nscr->_curx = win->_curx + begx;
+  }				/* if */
+}				/* wnoutrefresh */
Index: /trunk/minix/lib/curses/scrreg.c
===================================================================
--- /trunk/minix/lib/curses/scrreg.c	(revision 9)
+++ /trunk/minix/lib/curses/scrreg.c	(revision 9)
@@ -0,0 +1,58 @@
+/****************************************************************/
+/* Wsetscrreg() routine of the PCcurses package			*/
+/*								*/
+/****************************************************************/
+/* This version of curses is based on ncurses, a curses version	*/
+/* Originally written by Pavel Curtis at Cornell University.	*/
+/* I have made substantial changes to make it run on IBM PC's,	*/
+/* And therefore consider myself free to make it public domain.	*/
+/*		Bjorn Larsson (...mcvax!enea!infovax!bl)	*/
+/****************************************************************/
+/* 1.0:	Release:					870515	*/
+/****************************************************************/
+/* Modified to run under the MINIX operating system by Don Cope */
+/* These changes are also released into the public domain.      */
+/* 							900906  */
+/****************************************************************/
+
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Wsetscrreg() set the scrolling region of window 'win' to in-	*/
+/* Clude all lines between 'top' and 'bottom'.			*/
+/****************************************************************/
+
+int wsetscrreg(win, top, bottom)
+WINDOW *win;
+int top;
+int bottom;
+{
+  if ((0 <= top) &&
+      (top <= win->_cury)
+      &&
+      (win->_cury <= bottom)
+      &&
+      (bottom <= win->_maxy)
+	) {
+	win->_regtop = top;
+	win->_regbottom = bottom;
+	return(OK);
+  }
+
+   /* If */ 
+  else
+	return(ERR);
+}				/* wsetscrreg */
+
+/****************************************************************/
+/* Setscrreg() set the scrolling region of stdscr to include	*/
+/* All lines between 'top' and 'bottom'.			*/
+/****************************************************************/
+
+int setscrreg(top, bottom)
+int top;
+int bottom;
+{
+  return(wsetscrreg(stdscr, top, bottom));
+}				/* setscrreg */
Index: /trunk/minix/lib/curses/setterm.c
===================================================================
--- /trunk/minix/lib/curses/setterm.c	(revision 9)
+++ /trunk/minix/lib/curses/setterm.c	(revision 9)
@@ -0,0 +1,76 @@
+#include <curses.h>
+#include "curspriv.h"
+
+_PROTOTYPE( static void ttysetflags, (void) );
+
+static void ttysetflags()
+{
+  _tty.c_iflag |= ICRNL | IXON;
+  _tty.c_oflag |= OPOST | ONLCR;
+  _tty.c_lflag |= ECHO | ICANON | IEXTEN | ISIG;
+
+  if (_cursvar.rawmode) {
+	_tty.c_iflag &= ~(ICRNL | IXON);
+	_tty.c_oflag &= ~(OPOST);
+	_tty.c_lflag &= ~(ICANON | IEXTEN | ISIG);
+  }
+  if (_cursvar.cbrkmode) {
+	_tty.c_lflag &= ~(ICANON);
+  }
+  if (!_cursvar.echoit) {
+	_tty.c_lflag &= ~(ECHO | ECHONL);
+  }
+  if (NONL) {
+	_tty.c_iflag &= ~(ICRNL);
+	_tty.c_oflag &= ~(ONLCR);
+  }
+  tcsetattr(0, TCSANOW, &_tty);
+}				/* ttysetflags */
+
+void raw()
+{
+  _cursvar.rawmode = TRUE;
+  ttysetflags();
+}				/* raw */
+
+void noraw()
+{
+  _cursvar.rawmode = FALSE;
+  ttysetflags();
+}				/* noraw */
+
+void echo()
+{
+  _cursvar.echoit = TRUE;
+  ttysetflags();
+}
+
+void noecho()
+{
+  _cursvar.echoit = FALSE;
+  ttysetflags();
+}
+
+void nl()
+{
+  NONL = FALSE;
+  ttysetflags();
+}				/* nl */
+
+void nonl()
+{
+  NONL = TRUE;
+  ttysetflags();
+}				/* nonl */
+
+void cbreak()
+{
+  _cursvar.cbrkmode = TRUE;
+  ttysetflags();
+}				/* cbreak */
+
+void nocbreak()
+{
+  _cursvar.cbrkmode = FALSE;
+  ttysetflags();
+}				/* nocbreak */
Index: /trunk/minix/lib/curses/tabsize.c
===================================================================
--- /trunk/minix/lib/curses/tabsize.c	(revision 9)
+++ /trunk/minix/lib/curses/tabsize.c	(revision 9)
@@ -0,0 +1,50 @@
+/****************************************************************/
+/* Tabsize() routines of the PCcurses package			*/
+/*								*/
+/****************************************************************/
+/* This version of curses is based on ncurses, a curses version	*/
+/* Originally written by Pavel Curtis at Cornell University.	*/
+/* I have made substantial changes to make it run on IBM PC's,	*/
+/* And therefore consider myself free to make it public domain.	*/
+/*		Bjorn Larsson (...mcvax!enea!infovax!bl)	*/
+/****************************************************************/
+/* 1.0:	Release:					870515	*/
+/****************************************************************/
+/* Modified to run under the MINIX operating system by Don Cope */
+/* These changes are also released into the public domain.      */
+/* 							900906  */
+/****************************************************************/
+
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Wtabsize(win,ts) sets the tabsize of window 'win' to 'ts',	*/
+/* And returns the original value.				*/
+/****************************************************************/
+
+int wtabsize(win, ts)
+WINDOW *win;
+int ts;
+{
+  int origval;
+
+  origval = win->_tabsize;
+  win->_tabsize = ts;
+  return(origval);
+}				/* wtabsize */
+
+/****************************************************************/
+/* Tabsize(ts) sets the tabsize of stdscr to 'ts', and returns	*/
+/* The original value.						*/
+/****************************************************************/
+
+int tabsize(ts)
+int ts;
+{
+  int origval;
+
+  origval = stdscr->_tabsize;
+  stdscr->_tabsize = ts;
+  return(origval);
+}				/* tabsize */
Index: /trunk/minix/lib/curses/termmisc.c
===================================================================
--- /trunk/minix/lib/curses/termmisc.c	(revision 9)
+++ /trunk/minix/lib/curses/termmisc.c	(revision 9)
@@ -0,0 +1,63 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/* Static variables or saving terminal modes */
+
+int fixterm()
+{
+  return(OK);
+}				/* fixterm */
+
+int resetterm()
+{
+  return(OK);
+}
+
+int saveoldterm()
+{
+  return(OK);
+}				/* saveoldterm */
+
+int saveterm()
+{
+  return(OK);
+}				/* saveterm */
+
+int baudrate()
+{
+  return(19200);
+}				/* baudrate */
+
+/****************************************************************/
+/* Erasechar(), killchar() returns std MSDOS erase chars.	*/
+/****************************************************************/
+
+int erasechar()
+{
+  return(_DCCHAR);		/* character delete char */
+}				/* erasechar */
+
+int killchar()
+{
+  return(_DLCHAR);		/* line delete char */
+}				/* killchar */
+
+/****************************************************************/
+/* Savetty() and resetty() saves and restores the terminal I/O	*/
+/* Settings.							*/
+/****************************************************************/
+
+int savetty()
+{
+  return(OK);
+}				/* savetty */
+
+/****************************************************************/
+/* Setupterm() sets up the terminal. On a PC, it is always suc-	*/
+/* Cessful, and returns 1.					*/
+/****************************************************************/
+
+int setupterm()
+{
+  return(1);
+}				/* setupterm */
Index: /trunk/minix/lib/curses/unctrl.c
===================================================================
--- /trunk/minix/lib/curses/unctrl.c	(revision 9)
+++ /trunk/minix/lib/curses/unctrl.c	(revision 9)
@@ -0,0 +1,45 @@
+/****************************************************************/
+/* Unctrl() routines of the PCcurses package			*/
+/*								*/
+/****************************************************************/
+/* This version of curses is based on ncurses, a curses version	*/
+/* Originally written by Pavel Curtis at Cornell University.	*/
+/* I have made substantial changes to make it run on IBM PC's,	*/
+/* And therefore consider myself free to make it public domain.	*/
+/*		Bjorn Larsson (...mcvax!enea!infovax!bl)	*/
+/****************************************************************/
+/* 1.0:	Release:					870515	*/
+/****************************************************************/
+/* Modified to run under the MINIX operating system by Don Cope */
+/* These changes are also released into the public domain.      */
+/* 							900906  */
+/****************************************************************/
+
+#include <curses.h>
+#include "curspriv.h"
+
+static char strbuf[3] = {0, 0, 0};
+
+/****************************************************************/
+/* Unctrl() returns a char pointer to a string corresponding to	*/
+/* Argument character 'c'.					*/
+/****************************************************************/
+
+char *unctrl(c)
+char c;
+{
+  int ic = c;
+  ic &= 0xff;
+
+  if ((ic >= ' ') && (ic != 0x7f)) {	/* normal characters */
+	strbuf[0] = ic;
+	strbuf[1] = '\0';
+	return(strbuf);
+  }				/* if */
+  strbuf[0] = '^';		/* '^' prefix */
+  if (c == 0x7f)		/* DEL */
+	strbuf[1] = '?';
+  else				/* other control */
+	strbuf[1] = ic + '@';
+  return(strbuf);
+}				/* unctrl */
Index: /trunk/minix/lib/curses/update.c
===================================================================
--- /trunk/minix/lib/curses/update.c	(revision 9)
+++ /trunk/minix/lib/curses/update.c	(revision 9)
@@ -0,0 +1,173 @@
+#include <curses.h>
+#include "curspriv.h"
+#include <termcap.h>
+
+static WINDOW *twin;		/* used by many routines */
+
+/****************************************************************/
+/* Gotoxy() moves the physical cursor to the desired address on */
+/* The screen. We don't optimize here - on a PC, it takes more  */
+/* Time to optimize than to do things directly.                 */
+/****************************************************************/
+
+_PROTOTYPE(static void gotoxy, (int row, int col ));
+_PROTOTYPE(static void newattr, (int ch ));
+_PROTOTYPE(static void Putchar, (int ch ));
+_PROTOTYPE(static void clrupdate, (WINDOW *scr ));
+_PROTOTYPE(static void transformline, (int lineno ));
+
+static void gotoxy(row, col)
+int row, col;
+{
+  poscur(row, col);
+  _cursvar.cursrow = row;
+  _cursvar.curscol = col;
+}
+
+/* Update attributes */
+static void newattr(ch)
+int ch;
+{
+  extern char *me, *as, *ae, *mb, *md, *mr, *so, *us;
+  static int lastattr = 0;
+
+  if (lastattr != (ch &= ATR_MSK)) {
+	lastattr = ch;
+
+	tputs(me, 1, outc);
+	if (ae) tputs(ae, 1, outc);
+
+	if (ch & A_ALTCHARSET)
+		if (as) tputs(as, 1, outc);
+	if (ch & A_BLINK) tputs(mb, 1, outc);
+	if (ch & A_BOLD) tputs(md, 1, outc);
+	if (ch & A_REVERSE) tputs(mr, 1, outc);
+	if (ch & A_STANDOUT) tputs(so, 1, outc);
+	if (ch & A_UNDERLINE) tputs(us, 1, outc);
+  }
+}
+
+/* Putchar() writes a character, with attributes, to the physical
+   screen, but avoids writing to the lower right screen position.
+   Should it care about am?
+*/
+
+/* Output char with attribute */
+static void Putchar(ch)
+int ch;
+{
+  if ((_cursvar.cursrow < LINES) || (_cursvar.curscol < COLS)) {
+	newattr(ch);
+	putchar(ch);
+  }
+}
+
+/****************************************************************/
+/* Clrupdate(scr) updates the screen by clearing it and then    */
+/* Redraw it in it's entirety.					*/
+/****************************************************************/
+
+static void clrupdate(scr)
+WINDOW *scr;
+{
+  register int *src;
+  register int *dst;
+  register int i;
+  register int j;
+  WINDOW *w;
+
+  w = curscr;
+
+  if (scr != w) {		/* copy scr to curscr */
+	for (i = 0; i < LINES; i++) {
+		src = scr->_line[i];
+		dst = w->_line[i];
+		for (j = 0; j < COLS; j++) *dst++ = *src++;
+	}			/* for */
+  }				/* if */
+  newattr(scr->_attrs);
+  clrscr();
+  scr->_clear = FALSE;
+  for (i = 0; i < LINES; i++) {	/* update physical screen */
+	src = w->_line[i];
+	j = 0;
+	while (j < COLS) {
+		if (*src != (' ' | ATR_NRM)) {
+			gotoxy(i, j);
+			while (j < COLS && (*src != (' ' | ATR_NRM))) {
+				Putchar(*src++);
+				j++;
+			}
+		} else {
+			src++;
+			j++;
+		}
+	}			/* for */
+  }				/* for */
+  fflush(stdout);
+}				/* clrupdate */
+
+/****************************************************************/
+/* Transformline() updates the given physical line to look      */
+/* Like the corresponding line in _cursvar.tmpwin.		*/
+/****************************************************************/
+
+static void transformline(lineno)
+register int lineno;
+{
+  register int *dstp;
+  register int *srcp;
+  register int dstc;
+  register int srcc;
+  int x;
+  int endx;
+
+  x = twin->_minchng[lineno];
+  endx = twin->_maxchng[lineno];
+  dstp = curscr->_line[lineno] + x;
+  srcp = twin->_line[lineno] + x;
+
+  while (x <= endx) {
+	if ((*dstp != *srcp) || (dstc != srcc)) {
+		gotoxy(lineno, x);
+		while (x <= endx && ((*dstp != *srcp) || (dstc != srcc))) {
+			Putchar(*srcp);
+			*dstp++ = *srcp++;
+			x++;
+		}
+	} else {
+		*dstp++ = *srcp++;
+		x++;
+	}
+  }				/* for */
+  twin->_minchng[lineno] = _NO_CHANGE;
+  twin->_maxchng[lineno] = _NO_CHANGE;
+}				/* transformline */
+
+/****************************************************************/
+/* Doupdate() updates the physical screen to look like _curs-   */
+/* Var.tmpwin if curscr is not 'Clear-marked'. Otherwise it     */
+/* Updates the screen to look like curscr.                      */
+/****************************************************************/
+
+void doupdate()
+{
+  int i;
+
+  twin = _cursvar.tmpwin;
+  if (curscr->_clear)
+	clrupdate(curscr);
+  else {
+	if (twin->_clear)
+		clrupdate(twin);
+	else {
+		for (i = 0; i < LINES; i++)
+			if (twin->_minchng[i] != _NO_CHANGE)
+				transformline(i);
+	}
+  }
+  curscr->_curx = twin->_curx;
+  curscr->_cury = twin->_cury;
+  gotoxy(curscr->_cury, curscr->_curx);
+  fflush(stdout);
+}				/* doupdate */
Index: /trunk/minix/lib/curses/waddch.c
===================================================================
--- /trunk/minix/lib/curses/waddch.c	(revision 9)
+++ /trunk/minix/lib/curses/waddch.c	(revision 9)
@@ -0,0 +1,95 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Newline() does line advance and returns the new cursor line.	*/
+/* If error, return -1.						*/
+/****************************************************************/
+
+_PROTOTYPE( static short newline, (WINDOW *win, int lin));
+
+static short newline(win, lin)
+WINDOW *win;
+int lin;
+{
+  if (++lin > win->_regbottom) {
+	lin--;
+	if (win->_scroll)
+		scroll(win);
+	else
+		return(-1);
+  }				/* if */
+  return(lin);
+}				/* newline */
+
+/****************************************************************/
+/* Waddch() inserts character 'c' at the current cursor posi-	*/
+/* Tion in window 'win', and takes any actions as dictated by	*/
+/* The character.						*/
+/****************************************************************/
+
+int waddch(win, c)
+WINDOW *win;
+int c;
+{
+  int x = win->_curx;
+  int y = win->_cury;
+  int newx;
+  int ch = c;
+  int ts = win->_tabsize;
+
+  ch &= (A_ALTCHARSET | 0xff);
+  if (y > win->_maxy || x > win->_maxx || y < 0 || x < 0) return(ERR);
+  switch (ch) {
+      case '\t':
+	for (newx = ((x / ts) + 1) * ts; x < newx; x++) {
+		if (waddch(win, ' ') == ERR) return(ERR);
+		if (win->_curx == 0)	/* if tab to next line */
+			return(OK);	/* exit the loop */
+	}
+	return(OK);
+
+      case '\n':
+	if (NONL) x = 0;
+	if ((y = newline(win, y)) < 0) return (ERR);
+	break;
+
+      case '\r':	x = 0;	break;
+
+      case '\b':
+	if (--x < 0)		/* no back over left margin */
+		x = 0;
+	break;
+
+      case 0x7f:
+	{
+		if (waddch(win, '^') == ERR) return(ERR);
+		return(waddch(win, '?'));
+	}
+
+      default:
+	if (ch < ' ') {		/* handle control chars */
+		if (waddch(win, '^') == ERR) return(ERR);
+		return(waddch(win, c + '@'));
+	}
+	ch |= (win->_attrs & ATR_MSK);
+	if (win->_line[y][x] != ch) {	/* only if data change */
+		if (win->_minchng[y] == _NO_CHANGE)
+			win->_minchng[y] = win->_maxchng[y] = x;
+		else if (x < win->_minchng[y])
+			win->_minchng[y] = x;
+		else if (x > win->_maxchng[y])
+			win->_maxchng[y] = x;
+	}			/* if */
+	win->_line[y][x++] = ch;
+	if (x > win->_maxx) {	/* wrap around test */
+		x = 0;
+		if ((y = newline(win, y)) < 0) return(ERR);
+	}
+	break;
+
+  }				/* switch */
+  win->_curx = x;
+  win->_cury = y;
+  return(OK);
+}
Index: /trunk/minix/lib/curses/waddstr.c
===================================================================
--- /trunk/minix/lib/curses/waddstr.c	(revision 9)
+++ /trunk/minix/lib/curses/waddstr.c	(revision 9)
@@ -0,0 +1,18 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Waddstr() inserts string 'str' at the current cursor posi-	*/
+/* Tion in window 'win', and takes any actions as dictated by	*/
+/* The characters.						*/
+/****************************************************************/
+
+int waddstr(win, str)
+WINDOW *win;
+char *str;
+{
+  while (*str) {
+	if (waddch(win, *str++) == ERR) return(ERR);
+  }
+  return(OK);
+}
Index: /trunk/minix/lib/curses/wbox.c
===================================================================
--- /trunk/minix/lib/curses/wbox.c	(revision 9)
+++ /trunk/minix/lib/curses/wbox.c	(revision 9)
@@ -0,0 +1,65 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Wbox(win,ymin,xmin,ymax,xmax,v,h) draws a box in window	*/
+/* 'win', enclosing the area xmin-xmax and ymin-xmax. If	*/
+/* Xmax and/or ymax is 0, the window max value is used. 'v' and	*/
+/* 'h' are the vertical and horizontal characters to use. If	*/
+/* 'v' and 'h' are 0, wbox will use the alternate character set */
+/* In a pretty way.						*/
+/****************************************************************/
+
+int wbox(win, ymin, xmin, ymax, xmax, v, h)
+WINDOW *win;
+int ymin, xmin, ymax, xmax;
+unsigned int v;
+unsigned int h;
+{
+  unsigned int vc, hc, ulc, urc, llc, lrc;	/* corner chars */
+  int i;
+
+  if (ymax == 0) ymax = win->_maxy;
+  if (xmax == 0) xmax = win->_maxx;
+
+  if (ymin >= win->_maxy || ymax > win->_maxy ||
+      xmin >= win->_maxx || xmax > win->_maxx ||
+      ymin >= ymax || xmin >= xmax)
+	return(ERR);
+
+  vc = v;
+  hc = h;
+  ulc = urc = llc = lrc = vc;	/* default same as vertical */
+
+  if (v == 0 && h == 0) {
+	ulc = ACS_ULCORNER;
+	urc = ACS_URCORNER;
+	llc = ACS_LLCORNER;
+	lrc = ACS_LRCORNER;
+	hc = ACS_HLINE;
+	vc = ACS_VLINE;
+  }
+  for (i = xmin + 1; i <= xmax - 1; i++) {
+	win->_line[ymin][i] = hc | win->_attrs;
+	win->_line[ymax][i] = hc | win->_attrs;
+  }
+  for (i = ymin + 1; i <= ymax - 1; i++) {
+	win->_line[i][xmin] = vc | win->_attrs;
+	win->_line[i][xmax] = vc | win->_attrs;
+  }
+  win->_line[ymin][xmin] = ulc | win->_attrs;
+  win->_line[ymin][xmax] = urc | win->_attrs;
+  win->_line[ymax][xmin] = llc | win->_attrs;
+  win->_line[ymax][xmax] = lrc | win->_attrs;
+
+  for (i = ymin; i <= ymax; i++) {
+	if (win->_minchng[i] == _NO_CHANGE) {
+		win->_minchng[i] = xmin;
+		win->_maxchng[i] = xmax;
+	} else {
+		win->_minchng[i] = min(win->_minchng[i], xmin);
+		win->_maxchng[i] = max(win->_maxchng[i], xmax);
+	}
+  }
+  return(OK);
+}
Index: /trunk/minix/lib/curses/wclear.c
===================================================================
--- /trunk/minix/lib/curses/wclear.c	(revision 9)
+++ /trunk/minix/lib/curses/wclear.c	(revision 9)
@@ -0,0 +1,14 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Wclear() fills all lines of window 'win' with blanks, and	*/
+/* Marks the window to be cleared at next refresh operation.	*/
+/****************************************************************/
+
+void wclear(win)
+WINDOW *win;
+{
+  werase(win);
+  win->_clear = TRUE;
+}				/* wclear */
Index: /trunk/minix/lib/curses/wclrtobot.c
===================================================================
--- /trunk/minix/lib/curses/wclrtobot.c	(revision 9)
+++ /trunk/minix/lib/curses/wclrtobot.c	(revision 9)
@@ -0,0 +1,35 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Wclrtobot() fills the right half of the cursor line of	*/
+/* Window 'win', and all lines below it with blanks.		*/
+/****************************************************************/
+
+int wclrtobot(win)
+WINDOW *win;
+{
+  int y, minx, startx, *ptr, *end, *maxx, blank;
+
+  blank = ' ' | (win->_attrs & ATR_MSK);
+  startx = win->_curx;
+  for (y = win->_cury; y <= win->_regbottom; y++) {
+	minx = _NO_CHANGE;
+	end = &win->_line[y][win->_maxx];
+	for (ptr = &win->_line[y][startx]; ptr <= end; ptr++) {
+		if (*ptr != blank) {
+			maxx = ptr;
+			if (minx == _NO_CHANGE) minx = ptr - win->_line[y];
+			*ptr = blank;
+		}		/* if */
+	}			/* for */
+	if (minx != _NO_CHANGE) {
+		if ((win->_minchng[y] > minx) || (win->_minchng[y] == _NO_CHANGE))
+			win->_minchng[y] = minx;
+		if (win->_maxchng[y] < maxx - win->_line[y])
+			win->_maxchng[y] = maxx - win->_line[y];
+	}			/* if */
+	startx = 0;
+  }
+  return(OK);
+}
Index: /trunk/minix/lib/curses/wclrtoeol.c
===================================================================
--- /trunk/minix/lib/curses/wclrtoeol.c	(revision 9)
+++ /trunk/minix/lib/curses/wclrtoeol.c	(revision 9)
@@ -0,0 +1,36 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Wclrtoeol() fills the half of the cursor line to the right	*/
+/* Of the cursor in window 'win' with blanks.			*/
+/****************************************************************/
+
+int wclrtoeol(win)
+WINDOW *win;
+{
+  int *maxx, *ptr, *end, y, x, minx, blank;
+
+  y = win->_cury;
+  x = win->_curx;
+  blank = ' ' | (win->_attrs & ATR_MSK);
+
+  end = &win->_line[y][win->_maxx];
+  minx = _NO_CHANGE;
+  maxx = &win->_line[y][x];
+  for (ptr = maxx; ptr <= end; ptr++) {
+	if (*ptr != blank) {
+		maxx = ptr;
+		if (minx == _NO_CHANGE) minx = ptr - win->_line[y];
+		*ptr = blank;
+	}			/* if */
+  }				/* for */
+
+  if (minx != _NO_CHANGE) {
+	if (win->_minchng[y] > minx || win->_minchng[y] == _NO_CHANGE)
+		win->_minchng[y] = minx;
+	if (win->_maxchng[y] < maxx - win->_line[y])
+		win->_maxchng[y] = maxx - win->_line[y];
+  }
+  return(OK);
+}
Index: /trunk/minix/lib/curses/wdelch.c
===================================================================
--- /trunk/minix/lib/curses/wdelch.c	(revision 9)
+++ /trunk/minix/lib/curses/wdelch.c	(revision 9)
@@ -0,0 +1,28 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/* Wdelch() deletes the character at the window cursor, and the
+   characters to the right of it are shifted left, inserting a
+   space at the last position of the line.
+*/
+
+int wdelch(win)
+WINDOW *win;
+{
+  int *temp1;
+  int *temp2;
+  int *end;
+  int y = win->_cury;
+  int x = win->_curx;
+  int maxx = win->_maxx;
+
+  end = &win->_line[y][maxx];
+  temp1 = &win->_line[y][x];
+  temp2 = temp1 + 1;
+  while (temp1 < end) *temp1++ = *temp2++;
+  *temp1 = ' ' | (win->_attrs & ATR_MSK);
+  win->_maxchng[y] = maxx;
+  if (win->_minchng[y] == _NO_CHANGE || win->_minchng[y] > x)
+	win->_minchng[y] = x;
+  return(OK);
+}
Index: /trunk/minix/lib/curses/wdeleteln.c
===================================================================
--- /trunk/minix/lib/curses/wdeleteln.c	(revision 9)
+++ /trunk/minix/lib/curses/wdeleteln.c	(revision 9)
@@ -0,0 +1,28 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Wdeleteln() deletes the line at the window cursor, and the	*/
+/* Lines below it are shifted up, inserting a blank line at	*/
+/* The bottom of the window.					*/
+/****************************************************************/
+
+int wdeleteln(win)
+WINDOW *win;
+{
+  int *end, *temp, y, blank;
+
+  blank = ' ' | (win->_attrs & ATR_MSK);
+
+  temp = win->_line[win->_cury];
+  for (y = win->_cury; y < win->_regbottom; y++) {
+	win->_line[y] = win->_line[y + 1];
+	win->_minchng[y] = 0;
+	win->_maxchng[y] = win->_maxx;
+  }
+  win->_minchng[y] = 0;
+  win->_maxchng[y] = win->_maxx;
+  win->_line[win->_regbottom] = temp;
+  for (end = &(temp[win->_maxx]); temp <= end;) *temp++ = blank;
+  return(OK);
+}
Index: /trunk/minix/lib/curses/werase.c
===================================================================
--- /trunk/minix/lib/curses/werase.c	(revision 9)
+++ /trunk/minix/lib/curses/werase.c	(revision 9)
@@ -0,0 +1,26 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Werase() fills all lines of window 'win' with blanks and po-	*/
+/* Sitions the cursor at home in the scroll region.		*/
+/****************************************************************/
+
+void werase(win)
+WINDOW *win;
+{
+  int *end, *start, y, blank;
+
+  blank = ' ' | (win->_attrs & ATR_MSK);
+
+  for (y = win->_regtop; y <= win->_regbottom; y++) {	/* clear all lines */
+	start = win->_line[y];
+	end = &start[win->_maxx];
+	while (start <= end)	/* clear all line */
+		*start++ = blank;
+	win->_minchng[y] = 0;
+	win->_maxchng[y] = win->_maxx;
+  }
+  win->_cury = win->_regtop;	/* cursor home */
+  win->_curx = 0;
+}
Index: /trunk/minix/lib/curses/wgetch.c
===================================================================
--- /trunk/minix/lib/curses/wgetch.c	(revision 9)
+++ /trunk/minix/lib/curses/wgetch.c	(revision 9)
@@ -0,0 +1,26 @@
+#include <curses.h>
+#include <stdio.h>
+#include "curspriv.h"
+
+int wgetch(win)
+WINDOW *win;
+{
+  bool weset = FALSE;
+  char inp;
+
+  if (!win->_scroll && (win->_flags & _FULLWIN)
+      && win->_curx == win->_maxx - 1 && win->_cury == win->_maxy - 1)
+	return ERR;
+  if (_cursvar.echoit && !_cursvar.rawmode) {
+	cbreak();
+	weset++;
+  }
+  inp = getchar();
+  if (_cursvar.echoit) {
+	mvwaddch(curscr, win->_cury + win->_begy,
+		 win->_curx + win->_begx, inp);
+	waddch(win, inp);
+  }
+  if (weset) nocbreak();
+  return inp;
+}
Index: /trunk/minix/lib/curses/wgetstr.c
===================================================================
--- /trunk/minix/lib/curses/wgetstr.c	(revision 9)
+++ /trunk/minix/lib/curses/wgetstr.c	(revision 9)
@@ -0,0 +1,22 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Wgetstr(win,str) reads in a string (terminated by \n or \r)	*/
+/* To the buffer pointed to by 'str', and displays the input	*/
+/* In window 'win'. The user's erase and kill characters are	*/
+/* Active.							*/
+/****************************************************************/
+
+int wgetstr(win, str)
+WINDOW *win;
+char *str;
+{
+  while ((*str = wgetch(win)) != ERR && *str != '\n') str++;
+  if (*str == ERR) {
+	*str = '\0';
+	return ERR;
+  }
+  *str = '\0';
+  return OK;
+}
Index: /trunk/minix/lib/curses/windel.c
===================================================================
--- /trunk/minix/lib/curses/windel.c	(revision 9)
+++ /trunk/minix/lib/curses/windel.c	(revision 9)
@@ -0,0 +1,41 @@
+/****************************************************************/
+/* Delwin() routine of the PCcurses package.			*/
+/*								*/
+/****************************************************************/
+/* This version of curses is based on ncurses, a curses version	*/
+/* Originally written by Pavel Curtis at Cornell University.	*/
+/* I have made substantial changes to make it run on IBM PC's,	*/
+/* And therefore consider myself free to make it public domain.	*/
+/*		Bjorn Larsson (...mcvax!enea!infovax!bl)	*/
+/****************************************************************/
+/* 1.0:	Release:					870515	*/
+/****************************************************************/
+/* Modified to run under the MINIX operating system by Don Cope */
+/* These changes are also released into the public domain.      */
+/* 							900906  */
+/****************************************************************/
+
+#include <stdlib.h>
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Delwin() deallocates all data allocated by 'win'. If 'win'	*/
+/* Is a subwindow, it uses the original window's lines for sto-	*/
+/* Rage, and thus the line arrays are not deallocated.		*/
+/****************************************************************/
+
+void delwin(win)
+WINDOW *win;
+{
+  int i;
+
+  if (!(win->_flags & _SUBWIN)) {	/* subwindow uses 'parent's' lines */
+	for (i = 0; i <= win->_maxy && win->_line[i]; i++)
+		free(win->_line[i]);
+  }
+  free(win->_minchng);
+  free(win->_maxchng);
+  free(win->_line);
+  free(win);
+}				/* delwin */
Index: /trunk/minix/lib/curses/winmove.c
===================================================================
--- /trunk/minix/lib/curses/winmove.c	(revision 9)
+++ /trunk/minix/lib/curses/winmove.c	(revision 9)
@@ -0,0 +1,36 @@
+/****************************************************************/
+/* Mvwin() routine of the PCcurses package			*/
+/*								*/
+/****************************************************************/
+/* This version of curses is based on ncurses, a curses version	*/
+/* Originally written by Pavel Curtis at Cornell University.	*/
+/* I have made substantial changes to make it run on IBM PC's,	*/
+/* And therefore consider myself free to make it public domain.	*/
+/*		Bjorn Larsson (...mcvax!enea!infovax!bl)	*/
+/****************************************************************/
+/* 1.0:	Release:					870515	*/
+/****************************************************************/
+/* Modified to run under the MINIX operating system by Don Cope */
+/* These changes are also released into the public domain.      */
+/* 							900906  */
+/****************************************************************/
+
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Mvwin() moves window 'win' to position (begx, begy) on the	*/
+/* Screen.							*/
+/****************************************************************/
+
+int mvwin(win, begy, begx)
+WINDOW *win;
+int begy, begx;
+{
+  if ((begy + win->_maxy) > (LINES - 1) || (begx + win->_maxx) > (COLS - 1))
+	return(ERR);
+  win->_begy = begy;
+  win->_begx = begx;
+  touchwin(win);
+  return(OK);
+}				/* mvwin */
Index: /trunk/minix/lib/curses/winsch.c
===================================================================
--- /trunk/minix/lib/curses/winsch.c	(revision 9)
+++ /trunk/minix/lib/curses/winsch.c	(revision 9)
@@ -0,0 +1,31 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/* Winsch() inserts character 'c' at the cursor position in
+   window 'win'. The cursor is advanced.
+*/
+
+int winsch(win, c)
+WINDOW *win;
+char c;
+{
+  int *temp1;
+  int *temp2;
+  int *end;
+  int x = win->_curx;
+  int y = win->_cury;
+  int maxx = win->_maxx;
+
+  if ((c < ' ') && (c == '\n' || c == '\r' || c == '\t' || c == '\b'))
+	return(waddch(win, c));
+  end = &win->_line[y][x];
+  temp1 = &win->_line[y][maxx];
+  temp2 = temp1 - 1;
+  if (c < ' ')			/* if CTRL-char make space for 2 */
+	temp2--;
+  while (temp1 > end) *temp1-- = *temp2--;
+  win->_maxchng[y] = maxx;
+  if ((win->_minchng[y] == _NO_CHANGE) || (win->_minchng[y] > x))
+	win->_minchng[y] = x;
+  return(waddch(win, c));	/* fixes CTRL-chars too */
+}				/* winsch */
Index: /trunk/minix/lib/curses/winscrol.c
===================================================================
--- /trunk/minix/lib/curses/winscrol.c	(revision 9)
+++ /trunk/minix/lib/curses/winscrol.c	(revision 9)
@@ -0,0 +1,55 @@
+/****************************************************************/
+/* Scroll() routine of the PCcurses package			*/
+/*								*/
+/****************************************************************/
+/* This version of curses is based on ncurses, a curses version	*/
+/* Originally written by Pavel Curtis at Cornell University.	*/
+/* I have made substantial changes to make it run on IBM PC's,	*/
+/* And therefore consider myself free to make it public domain.	*/
+/*		Bjorn Larsson (...mcvax!enea!infovax!bl)	*/
+/****************************************************************/
+/* 1.0:	Release:					870515	*/
+/****************************************************************/
+/* Modified to run under the MINIX operating system by Don Cope */
+/* These changes are also released into the public domain.      */
+/* 							900906  */
+/****************************************************************/
+
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Scroll() scrolls the scrolling region of 'win', but only if	*/
+/* Scrolling is allowed and if the cursor is inside the scrol-	*/
+/* Ling region.							*/
+/****************************************************************/
+
+void scroll(win)
+WINDOW *win;
+{
+  int i;
+  int *ptr;
+  int *temp;
+  static int blank;
+
+  blank = ' ' | (win->_attrs & ATR_MSK);
+  if ((!win->_scroll)		/* check if window scrolls */
+      ||(win->_cury < win->_regtop)	/* and cursor in region */
+      ||(win->_cury > win->_regbottom)
+	)
+	return;
+
+  temp = win->_line[win->_regtop];
+  for (i = win->_regtop; i < win->_regbottom; i++) {
+	win->_line[i] = win->_line[i + 1];	/* re-arrange line pointers */
+	win->_minchng[i] = 0;
+	win->_maxchng[i] = win->_maxx;
+  }
+  for (ptr = temp; ptr - temp <= win->_maxx; ptr++)
+	*ptr = blank;		/* make a blank line */
+  win->_line[win->_regbottom] = temp;
+  if (win->_cury > win->_regtop)/* if not on top line */
+	win->_cury--;		/* cursor scrolls too */
+  win->_minchng[win->_regbottom] = 0;
+  win->_maxchng[win->_regbottom] = win->_maxx;
+}				/* scroll */
Index: /trunk/minix/lib/curses/winsertln.c
===================================================================
--- /trunk/minix/lib/curses/winsertln.c	(revision 9)
+++ /trunk/minix/lib/curses/winsertln.c	(revision 9)
@@ -0,0 +1,26 @@
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Winsertln() inserts a blank line instead of the cursor line	*/
+/* In window 'win' and pushes other lines down.			*/
+/****************************************************************/
+
+int winsertln(win)
+WINDOW *win;
+{
+  int *temp, *end, y, blank;
+
+  blank = ' ' | (win->_attrs & ATR_MSK);
+  temp = win->_line[win->_regbottom];
+  for (y = win->_regbottom; y > win->_cury; y--) {
+	win->_line[y] = win->_line[y - 1];
+	win->_minchng[y] = 0;
+	win->_maxchng[y] = win->_maxx;
+  }
+  win->_line[win->_cury] = temp;
+  for (end = &temp[win->_maxx]; temp <= end; temp++) *temp = blank;
+  win->_minchng[win->_cury] = 0;
+  win->_maxchng[win->_cury] = win->_maxx;
+  return(OK);
+}
Index: /trunk/minix/lib/curses/wintouch.c
===================================================================
--- /trunk/minix/lib/curses/wintouch.c	(revision 9)
+++ /trunk/minix/lib/curses/wintouch.c	(revision 9)
@@ -0,0 +1,40 @@
+/****************************************************************/
+/* Touchwin() routine of the PCcurses package			*/
+/*								*/
+/****************************************************************/
+/* This version of curses is based on ncurses, a curses version	*/
+/* Originally written by Pavel Curtis at Cornell University.	*/
+/* I have made substantial changes to make it run on IBM PC's,	*/
+/* And therefore consider myself free to make it public domain.	*/
+/*		Bjorn Larsson (...mcvax!enea!infovax!bl)	*/
+/****************************************************************/
+/* 1.0:	Release:					870515	*/
+/****************************************************************/
+/* Modified to run under the MINIX operating system by Don Cope */
+/* These changes are also released into the public domain.      */
+/* 							900906  */
+/****************************************************************/
+
+#include <curses.h>
+#include "curspriv.h"
+
+/****************************************************************/
+/* Touchwin() marks all lines of window 'win' as changed, from	*/
+/* The first to the last character on the line.			*/
+/****************************************************************/
+
+void touchwin(win)
+WINDOW *win;
+{
+  int y;
+  int maxy;
+  int maxx;
+
+  maxy = win->_maxy;
+  maxx = win->_maxx;
+
+  for (y = 0; y <= maxy; y++) {
+	win->_minchng[y] = 0;
+	win->_maxchng[y] = maxx;
+  }				/* for */
+}				/* touchwin */
Index: /trunk/minix/lib/dummy/Makedepend-ack
===================================================================
--- /trunk/minix/lib/dummy/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/dummy/Makedepend-ack	(revision 9)
@@ -0,0 +1,4 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc  -E' dummy.c | sed -e 's:^\(.\):../obj-ack//./dummy/\1:' >> .depend-ack
Index: /trunk/minix/lib/dummy/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/dummy/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/dummy/Makedepend-gnu	(revision 9)
@@ -0,0 +1,4 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc  -E' dummy.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./dummy/\1:' >> .depend-gnu
Index: /trunk/minix/lib/dummy/Makefile
===================================================================
--- /trunk/minix/lib/dummy/Makefile	(revision 9)
+++ /trunk/minix/lib/dummy/Makefile	(revision 9)
@@ -0,0 +1,52 @@
+#Generated from ./dummy/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./dummy ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./dummy ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libm.a
+
+../obj-ack//libm.a: ../obj-ack//libm.a(dummy.o)
+
+../obj-ack//libm.a:
+	ar cr ../obj-ack//libm.a ../obj-ack//./dummy/*.o
+	rm ../obj-ack//./dummy/*.o
+
+../obj-ack//libm.a(dummy.o): dummy.c
+	cc  -c -o ../obj-ack//./dummy/dummy.o dummy.c
+
+all-gnu: ../obj-gnu/libm.a
+
+../obj-gnu/libm.a: ../obj-gnu/./dummy/dummy.o
+
+../obj-gnu/libm.a:
+	gar cr ../obj-gnu/libm.a $?
+
+../obj-gnu/./dummy/dummy.o: dummy.c
+	gcc  -c -o ../obj-gnu/./dummy/dummy.o dummy.c
+
+
+
+
+clean::
+	rm -f ../obj-ack//./dummy/*
+	rm -f ../obj-gnu/./dummy/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/dummy/Makefile.in
===================================================================
--- /trunk/minix/lib/dummy/Makefile.in	(revision 9)
+++ /trunk/minix/lib/dummy/Makefile.in	(revision 9)
@@ -0,0 +1,13 @@
+# Makefile for lib/dummy.
+
+# Make a dummy libm library so that -lm works.
+
+
+LIBRARIES=libm
+
+libm_FILES=dummy.c
+
+TYPE=both
+
+#dummy.c:
+#	echo "int __dummy__;" > $@
Index: /trunk/minix/lib/dummy/dummy.c
===================================================================
--- /trunk/minix/lib/dummy/dummy.c	(revision 9)
+++ /trunk/minix/lib/dummy/dummy.c	(revision 9)
@@ -0,0 +1,1 @@
+int __dummy__;
Index: /trunk/minix/lib/editline/Makedepend-ack
===================================================================
--- /trunk/minix/lib/editline/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/editline/Makedepend-ack	(revision 9)
@@ -0,0 +1,6 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -DANSI_ARROWS -DHAVE_STDLIB -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT 	-DHIST_SIZE=100 -DUSE_TERMCAP -DSYS_UNIX -wo -E' editline.c | sed -e 's:^\(.\):../obj-ack//./editline/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -DANSI_ARROWS -DHAVE_STDLIB -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT 	-DHIST_SIZE=100 -DUSE_TERMCAP -DSYS_UNIX -wo -E' complete.c | sed -e 's:^\(.\):../obj-ack//./editline/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -DANSI_ARROWS -DHAVE_STDLIB -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT 	-DHIST_SIZE=100 -DUSE_TERMCAP -DSYS_UNIX -wo -E' sysunix.c | sed -e 's:^\(.\):../obj-ack//./editline/\1:' >> .depend-ack
Index: /trunk/minix/lib/editline/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/editline/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/editline/Makedepend-gnu	(revision 9)
@@ -0,0 +1,6 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -DANSI_ARROWS -DHAVE_STDLIB -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT 	-DHIST_SIZE=100 -DUSE_TERMCAP -DSYS_UNIX -wo -E' editline.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./editline/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -DANSI_ARROWS -DHAVE_STDLIB -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT 	-DHIST_SIZE=100 -DUSE_TERMCAP -DSYS_UNIX -wo -E' complete.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./editline/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -DANSI_ARROWS -DHAVE_STDLIB -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT 	-DHIST_SIZE=100 -DUSE_TERMCAP -DSYS_UNIX -wo -E' sysunix.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./editline/\1:' >> .depend-gnu
Index: /trunk/minix/lib/editline/Makefile
===================================================================
--- /trunk/minix/lib/editline/Makefile	(revision 9)
+++ /trunk/minix/lib/editline/Makefile	(revision 9)
@@ -0,0 +1,66 @@
+#Generated from ./editline/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./editline ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./editline ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libedit.a
+
+../obj-ack//libedit.a: ../obj-ack//libedit.a(editline.o)
+../obj-ack//libedit.a: ../obj-ack//libedit.a(complete.o)
+../obj-ack//libedit.a: ../obj-ack//libedit.a(sysunix.o)
+
+../obj-ack//libedit.a:
+	ar cr ../obj-ack//libedit.a ../obj-ack//./editline/*.o
+	rm ../obj-ack//./editline/*.o
+
+../obj-ack//libedit.a(editline.o): editline.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -DANSI_ARROWS -DHAVE_STDLIB -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT 	-DHIST_SIZE=100 -DUSE_TERMCAP -DSYS_UNIX -wo -c -o ../obj-ack//./editline/editline.o editline.c
+../obj-ack//libedit.a(complete.o): complete.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -DANSI_ARROWS -DHAVE_STDLIB -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT 	-DHIST_SIZE=100 -DUSE_TERMCAP -DSYS_UNIX -wo -c -o ../obj-ack//./editline/complete.o complete.c
+../obj-ack//libedit.a(sysunix.o): sysunix.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -DANSI_ARROWS -DHAVE_STDLIB -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT 	-DHIST_SIZE=100 -DUSE_TERMCAP -DSYS_UNIX -wo -c -o ../obj-ack//./editline/sysunix.o sysunix.c
+
+all-gnu: ../obj-gnu/libedit.a
+
+../obj-gnu/libedit.a: ../obj-gnu/./editline/editline.o
+../obj-gnu/libedit.a: ../obj-gnu/./editline/complete.o
+../obj-gnu/libedit.a: ../obj-gnu/./editline/sysunix.o
+
+../obj-gnu/libedit.a:
+	gar cr ../obj-gnu/libedit.a $?
+
+../obj-gnu/./editline/editline.o: editline.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -DANSI_ARROWS -DHAVE_STDLIB -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT 	-DHIST_SIZE=100 -DUSE_TERMCAP -DSYS_UNIX -wo -c -o ../obj-gnu/./editline/editline.o editline.c
+
+../obj-gnu/./editline/complete.o: complete.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -DANSI_ARROWS -DHAVE_STDLIB -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT 	-DHIST_SIZE=100 -DUSE_TERMCAP -DSYS_UNIX -wo -c -o ../obj-gnu/./editline/complete.o complete.c
+
+../obj-gnu/./editline/sysunix.o: sysunix.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -DANSI_ARROWS -DHAVE_STDLIB -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT 	-DHIST_SIZE=100 -DUSE_TERMCAP -DSYS_UNIX -wo -c -o ../obj-gnu/./editline/sysunix.o sysunix.c
+
+
+
+
+clean::
+	rm -f ../obj-ack//./editline/*
+	rm -f ../obj-gnu/./editline/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/editline/Makefile.in
===================================================================
--- /trunk/minix/lib/editline/Makefile.in	(revision 9)
+++ /trunk/minix/lib/editline/Makefile.in	(revision 9)
@@ -0,0 +1,44 @@
+##  $Revision: 1.2 $
+##
+##  Unix makefile for editline library.
+##
+
+
+##  Set your options:
+##	-DANSI_ARROWS		ANSI arrows keys work like emacs.
+##	-DHAVE_STDLIB		Have <stdlib.h>.
+##	-DHAVE_TCGETATTR	Have , .
+##	-DHAVE_TERMIO		Have "struct termio" and <termio.h>
+##	(If neither of above two, we use <sgttyb.h> and BSD ioctl's)
+##	-DHIDE			Make static functions static (non debug).
+##	-DHIST_SIZE=n		History size.
+##	-DNEED_STRDUP		Don't have .
+##	-DUNIQUE_HISTORY	Don't save command if same as last one.
+##	-DUSE_DIRENT		Use <dirent.h>, not <sys/dir.h>?
+##	-DUSE_TERMCAP		Use the termcap library for terminal size
+##				see LDFLAGS, below, if you set this.
+##	-DNEED_PERROR		Don't have  (used in testit)
+DEFS="-DANSI_ARROWS -DHAVE_STDLIB -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT \
+	-DHIST_SIZE=100 -DUSE_TERMCAP -DSYS_UNIX"
+#-DNEED_STRDUP
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE $DEFS -wo"
+#CC1	= $(CC) $(CFLAGS) -c
+
+##  If you have -DUSE_TERMCAP, set this as appropriate:
+#LDFLAGS = -ltermlib
+#LDFLAGS = -ltermcap
+
+##  End of configuration.
+
+#SOURCES	= editline.c complete.c sysunix.c
+#LIBRARY = ../libedit.a
+LIBRARIES=libedit
+#OBJECTS	= editline.o complete.o sysunix.o
+libedit_FILES="editline.c complete.c sysunix.c"
+#SHARFILES =	README Makefile editline.3 editline.h unix.h editline.c \
+
+TYPE=both
+#include ../Makefile.inc
+
+#$(call ADDDEPENDENCIES,$(libedit_OBJECTS),editline.h)
Index: /trunk/minix/lib/editline/README
===================================================================
--- /trunk/minix/lib/editline/README	(revision 9)
+++ /trunk/minix/lib/editline/README	(revision 9)
@@ -0,0 +1,59 @@
+$Revision: 1.1.1.1 $
+
+This is a line-editing library.  It can be linked into almost any
+program to provide command-line editing and recall.
+
+It is call-compatible with the FSF readline library, but it is a
+fraction of the size (and offers fewer features).  It does not use
+standard I/O.  It is distributed under a "C News-like" copyright.
+
+Configuration is done in the Makefile.  Type "make testit" to get
+a small slow shell for testing.
+
+An earlier version was distributed with Byron's rc.  Principal
+changes over that version include:
+	Faster.
+	Is eight-bit clean (thanks to brendan@cs.widener.edu)
+	Written in K&R C, but ANSI compliant (gcc all warnings)
+	Propagates EOF properly; rc trip test now passes
+	Doesn't need or use or provide memmove.
+	More robust
+	Calling sequence changed to be compatible with readline.
+	Test program, new manpage, better configuration
+	More system-independant; includes Unix and OS-9 support.
+
+This contains some changes since the posting to comp.sources.misc:
+	Bugfix for completion on absolute pathnames.
+	Better handling of M-n versus showing raw 8bit chars.
+	Better signal handling.
+	Now supports termios/termio/sgttyb ioctl's.
+	Add M-m command to toggle how 8bit data is displayed.
+
+There is one known bug:
+	History-searching redraws the line wrong if the text
+	retrieved is shorter then the prompt.
+
+Enjoy,
+	Rich $alz
+	<rsalz@osf.org>
+
+ Copyright 1992,1993 Simmule Turner and Rich Salz.  All rights reserved.
+
+ This software is not subject to any license of the American Telephone
+ and Telegraph Company or of the Regents of the University of California.
+
+ Permission is granted to anyone to use this software for any purpose on
+ any computer system, and to alter it and redistribute it freely, subject
+ to the following restrictions:
+ 1. The authors are not responsible for the consequences of use of this
+    software, no matter how awful, even if they arise from flaws in it.
+ 2. The origin of this software must not be misrepresented, either by
+    explicit claim or by omission.  Since few users ever read sources,
+    credits must appear in the documentation.
+ 3. Altered versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.  Since few users
+    ever read sources, credits must appear in the documentation.
+ 4. This notice may not be removed or altered.
+
+--
+$PchId: README,v 1.3 1996/02/22 21:18:51 philip Exp $
Index: /trunk/minix/lib/editline/complete.c
===================================================================
--- /trunk/minix/lib/editline/complete.c	(revision 9)
+++ /trunk/minix/lib/editline/complete.c	(revision 9)
@@ -0,0 +1,254 @@
+/*  $Revision: 1.1.1.1 $
+**
+**  History and file completion functions for editline library.
+*/
+#include "editline.h"
+
+
+#if	defined(NEED_STRDUP)
+/*
+**  Return an allocated copy of a string.
+*/
+char *
+strdup(p)
+    char	*p;
+{
+    char	*new;
+
+    if ((new = NEW(char, strlen(p) + 1)) != NULL)
+	(void)strcpy(new, p);
+    return new;
+}
+#endif	/* defined(NEED_STRDUP) */
+
+/*
+**  strcmp-like sorting predicate for qsort.
+*/
+STATIC int
+compare(p1, p2)
+    CONST void	*p1;
+    CONST void	*p2;
+{
+    CONST char	**v1;
+    CONST char	**v2;
+
+    v1 = (CONST char **)p1;
+    v2 = (CONST char **)p2;
+    return strcmp(*v1, *v2);
+}
+
+/*
+**  Fill in *avp with an array of names that match file, up to its length.
+**  Ignore . and .. .
+*/
+STATIC int
+FindMatches(dir, file, avp)
+    char	*dir;
+    char	*file;
+    char	***avp;
+{
+    char	**av;
+    char	**new;
+    char	*p;
+    DIR		*dp;
+    DIRENTRY	*ep;
+    SIZE_T	ac;
+    SIZE_T	len;
+    SIZE_T	choices;
+    SIZE_T	total;
+#define MAX_TOTAL	(256 << sizeof(char *))
+
+    if ((dp = opendir(dir)) == NULL)
+	return 0;
+
+    av = NULL;
+    ac = 0;
+    len = strlen(file);
+    choices = 0;
+    total = 0;
+    while ((ep = readdir(dp)) != NULL) {
+	p = ep->d_name;
+	if (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')))
+	    continue;
+	if (len && strncmp(p, file, len) != 0)
+	    continue;
+
+	choices++;
+	if ((total += strlen(p)) > MAX_TOTAL) {
+	    /* This is a bit too much. */
+	    while (ac > 0) DISPOSE(av[--ac]);
+	    continue;
+	}
+
+	if ((ac % MEM_INC) == 0) {
+	    if ((new = NEW(char*, ac + MEM_INC)) == NULL) {
+		total = 0;
+		break;
+	    }
+	    if (ac) {
+		COPYFROMTO(new, av, ac * sizeof (char **));
+		DISPOSE(av);
+	    }
+	    *avp = av = new;
+	}
+
+	if ((av[ac] = strdup(p)) == NULL) {
+	    if (ac == 0)
+		DISPOSE(av);
+	    total = 0;
+	    break;
+	}
+	ac++;
+    }
+
+    /* Clean up and return. */
+    (void)closedir(dp);
+    if (total > MAX_TOTAL) {
+	char many[sizeof(total) * 3];
+	p = many + sizeof(many);
+	*--p = '\0';
+	while (choices > 0) {
+	   *--p = '0' + choices % 10;
+	   choices /= 10;
+	}
+	while (p > many + sizeof(many) - 8) *--p = ' ';
+	if ((p = strdup(p)) != NULL) av[ac++] = p;
+	if ((p = strdup("choices")) != NULL) av[ac++] = p;
+    } else {
+	if (ac)
+	    qsort(av, ac, sizeof (char **), compare);
+    }
+    return ac;
+}
+
+/*
+**  Split a pathname into allocated directory and trailing filename parts.
+*/
+STATIC int
+SplitPath(path, dirpart, filepart)
+    char	*path;
+    char	**dirpart;
+    char	**filepart;
+{
+    static char	DOT[] = ".";
+    char	*dpart;
+    char	*fpart;
+
+    if ((fpart = strrchr(path, '/')) == NULL) {
+	if ((dpart = strdup(DOT)) == NULL)
+	    return -1;
+	if ((fpart = strdup(path)) == NULL) {
+	    DISPOSE(dpart);
+	    return -1;
+	}
+    }
+    else {
+	if ((dpart = strdup(path)) == NULL)
+	    return -1;
+	dpart[fpart - path + 1] = '\0';
+	if ((fpart = strdup(++fpart)) == NULL) {
+	    DISPOSE(dpart);
+	    return -1;
+	}
+    }
+    *dirpart = dpart;
+    *filepart = fpart;
+    return 0;
+}
+
+/*
+**  Attempt to complete the pathname, returning an allocated copy.
+**  Fill in *unique if we completed it, or set it to 0 if ambiguous.
+*/
+char *
+rl_complete(pathname, unique)
+    char	*pathname;
+    int		*unique;
+{
+    char	**av;
+    char	*dir;
+    char	*file;
+    char	*new;
+    char	*p;
+    SIZE_T	ac;
+    SIZE_T	end;
+    SIZE_T	i;
+    SIZE_T	j;
+    SIZE_T	len;
+
+    if (SplitPath(pathname, &dir, &file) < 0)
+	return NULL;
+    if ((ac = FindMatches(dir, file, &av)) == 0) {
+	DISPOSE(dir);
+	DISPOSE(file);
+	return NULL;
+    }
+
+    p = NULL;
+    len = strlen(file);
+    if (ac == 1) {
+	/* Exactly one match -- finish it off. */
+	*unique = 1;
+	j = strlen(av[0]) - len + 2;
+	if ((p = NEW(char, j + 1)) != NULL) {
+	    COPYFROMTO(p, av[0] + len, j);
+	    if ((new = NEW(char, strlen(dir) + strlen(av[0]) + 2)) != NULL) {
+		(void)strcpy(new, dir);
+		(void)strcat(new, "/");
+		(void)strcat(new, av[0]);
+		rl_add_slash(new, p);
+		DISPOSE(new);
+	    }
+	}
+    }
+    else {
+	*unique = 0;
+	if (len) {
+	    /* Find largest matching substring. */
+	    for (i = len, end = strlen(av[0]); i < end; i++)
+		for (j = 1; j < ac; j++)
+		    if (av[0][i] != av[j][i])
+			goto breakout;
+  breakout:
+	    if (i > len) {
+		j = i - len + 1;
+		if ((p = NEW(char, j)) != NULL) {
+		    COPYFROMTO(p, av[0] + len, j);
+		    p[j - 1] = '\0';
+		}
+	    }
+	}
+    }
+
+    /* Clean up and return. */
+    DISPOSE(dir);
+    DISPOSE(file);
+    for (i = 0; i < ac; i++)
+	DISPOSE(av[i]);
+    DISPOSE(av);
+    return p;
+}
+
+/*
+**  Return all possible completions.
+*/
+int
+rl_list_possib(pathname, avp)
+    char	*pathname;
+    char	***avp;
+{
+    char	*dir;
+    char	*file;
+    int		ac;
+
+    if (SplitPath(pathname, &dir, &file) < 0)
+	return 0;
+    ac = FindMatches(dir, file, avp);
+    DISPOSE(dir);
+    DISPOSE(file);
+    return ac;
+}
+
+/*
+ * $PchId: complete.c,v 1.3 1996/02/22 21:18:51 philip Exp $
+ */
Index: /trunk/minix/lib/editline/editline.c
===================================================================
--- /trunk/minix/lib/editline/editline.c	(revision 9)
+++ /trunk/minix/lib/editline/editline.c	(revision 9)
@@ -0,0 +1,1469 @@
+/*  $Revision: 1.1.1.1 $
+**
+**  Main editing routines for editline library.
+*/
+#include "editline.h"
+#include <signal.h>
+#include <ctype.h>
+
+/*
+**  Manifest constants.
+*/
+#define SCREEN_WIDTH	80
+#define SCREEN_ROWS	24
+#define NO_ARG		(-1)
+#define DEL		127
+#define CTL(x)		((x) & 0x1F)
+#define ISCTL(x)	((x) && (x) < ' ')
+#define UNCTL(x)	((x) + 64)
+#define META(x)		((x) | 0x80)
+#define ISMETA(x)	((x) & 0x80)
+#define UNMETA(x)	((x) & 0x7F)
+#if	!defined(HIST_SIZE)
+#define HIST_SIZE	20
+#endif	/* !defined(HIST_SIZE) */
+
+/*
+**  Command status codes.
+*/
+typedef enum _STATUS {
+    CSdone, CSeof, CSmove, CSdispatch, CSstay, CSsignal
+} STATUS;
+
+/*
+**  The type of case-changing to perform.
+*/
+typedef enum _CASE {
+    TOupper, TOlower
+} CASE;
+
+/*
+**  Key to command mapping.
+*/
+typedef struct _KEYMAP {
+    CHAR	Key;
+    STATUS	(*Function)();
+} KEYMAP;
+
+/*
+**  Command history structure.
+*/
+typedef struct _HISTORY {
+    int		Size;
+    int		Pos;
+    CHAR	*Lines[HIST_SIZE];
+} HISTORY;
+
+/*
+**  Globals.
+*/
+int		rl_eof;
+int		rl_erase;
+int		rl_intr;
+int		rl_kill;
+int		rl_quit;
+
+STATIC CHAR		NIL[] = "";
+STATIC CONST CHAR	*Input = NIL;
+STATIC CHAR		*Line;
+STATIC CONST char	*Prompt;
+STATIC CHAR		*Yanked;
+STATIC char		*Screen;
+STATIC char		NEWLINE[]= CRLF;
+STATIC HISTORY		H;
+STATIC int		Repeat;
+STATIC int		End;
+STATIC int		Mark;
+STATIC int		OldPoint;
+STATIC int		Point;
+STATIC int		PushBack;
+STATIC int		Pushed;
+STATIC int		Signal;
+FORWARD KEYMAP		Map[33];
+FORWARD KEYMAP		MetaMap[17];
+STATIC SIZE_T		Length;
+STATIC SIZE_T		ScreenCount;
+STATIC SIZE_T		ScreenSize;
+STATIC char		*backspace;
+STATIC int		TTYwidth;
+STATIC int		TTYrows;
+
+/* Display print 8-bit chars as `M-x' or as the actual 8-bit char? */
+int		rl_meta_chars = 0;
+
+/*
+**  Declarations.
+*/
+STATIC CHAR	*editinput();
+extern int	read();
+extern int	write();
+#if	defined(USE_TERMCAP)
+extern char	*getenv();
+extern char	*tgetstr();
+extern int	tgetent();
+#endif	/* defined(USE_TERMCAP) */
+
+
+/*
+**  TTY input/output functions.
+*/
+
+STATIC void
+TTYflush()
+{
+    if (ScreenCount) {
+	(void)write(1, Screen, ScreenCount);
+	ScreenCount = 0;
+    }
+}
+
+STATIC void
+TTYput(c)
+    CHAR	c;
+{
+    Screen[ScreenCount] = c;
+    if (++ScreenCount >= ScreenSize - 1) {
+	ScreenSize += SCREEN_INC;
+	RENEW(Screen, char, ScreenSize);
+    }
+}
+
+STATIC void
+TTYputs(p)
+    CHAR	*p;
+{
+    while (*p)
+	TTYput(*p++);
+}
+
+STATIC void
+TTYshow(c)
+    CHAR	c;
+{
+    if (c == DEL) {
+	TTYput('^');
+	TTYput('?');
+    }
+    else if (ISCTL(c)) {
+	TTYput('^');
+	TTYput(UNCTL(c));
+    }
+    else if (rl_meta_chars && ISMETA(c)) {
+	TTYput('M');
+	TTYput('-');
+	TTYput(UNMETA(c));
+    }
+    else
+	TTYput(c);
+}
+
+STATIC void
+TTYstring(p)
+    CHAR	*p;
+{
+    while (*p)
+	TTYshow(*p++);
+}
+
+STATIC unsigned int
+TTYget()
+{
+    CHAR	c;
+
+    TTYflush();
+    if (Pushed) {
+	Pushed = 0;
+	return PushBack;
+    }
+    if (*Input)
+	return *Input++;
+    return read(0, &c, (SIZE_T)1) == 1 ? c : EOF;
+}
+
+#define TTYback()	(backspace ? TTYputs((CHAR *)backspace) : TTYput('\b'))
+
+STATIC void
+TTYbackn(n)
+    int		n;
+{
+    while (--n >= 0)
+	TTYback();
+}
+
+STATIC void
+TTYinfo()
+{
+    static int		init;
+#if	defined(USE_TERMCAP)
+    char		*term;
+    char		buff[2048];
+    char		*bp;
+#endif	/* defined(USE_TERMCAP) */
+#if	defined(TIOCGWINSZ)
+    struct winsize	W;
+#endif	/* defined(TIOCGWINSZ) */
+
+    if (init) {
+#if	defined(TIOCGWINSZ)
+	/* Perhaps we got resized. */
+	if (ioctl(0, TIOCGWINSZ, &W) >= 0
+	 && W.ws_col > 0 && W.ws_row > 0) {
+	    TTYwidth = (int)W.ws_col;
+	    TTYrows = (int)W.ws_row;
+	}
+#endif	/* defined(TIOCGWINSZ) */
+	return;
+    }
+    init++;
+
+    TTYwidth = TTYrows = 0;
+#if	defined(USE_TERMCAP)
+    bp = &buff[0];
+    if ((term = getenv("TERM")) == NULL)
+	term = "dumb";
+    if (tgetent(buff, term) < 0) {
+       TTYwidth = SCREEN_WIDTH;
+       TTYrows = SCREEN_ROWS;
+       return;
+    }
+    if ((backspace = tgetstr("le", &bp)) != NULL)
+	backspace = strdup(backspace);
+    TTYwidth = tgetnum("co");
+    TTYrows = tgetnum("li");
+#endif	/* defined(USE_TERMCAP) */
+
+#if	defined(TIOCGWINSZ)
+    if (ioctl(0, TIOCGWINSZ, &W) >= 0) {
+	TTYwidth = (int)W.ws_col;
+	TTYrows = (int)W.ws_row;
+    }
+#endif	/* defined(TIOCGWINSZ) */
+
+    if (TTYwidth <= 0 || TTYrows <= 0) {
+	TTYwidth = SCREEN_WIDTH;
+	TTYrows = SCREEN_ROWS;
+    }
+}
+
+
+
+/*
+**  Print an array of words in columns.
+*/
+STATIC void
+columns(ac, av)
+    int		ac;
+    CHAR	**av;
+{
+    CHAR	*p;
+    int		i;
+    int		j;
+    int		k;
+    int		len;
+    int		skip;
+    int		longest;
+    int		cols;
+
+    /* Find longest name, determine column count from that. */
+    for (longest = 0, i = 0; i < ac; i++)
+	if ((j = strlen((char *)av[i])) > longest)
+	    longest = j;
+    cols = TTYwidth / (longest + 3);
+
+    TTYputs((CHAR *)NEWLINE);
+    for (skip = ac / cols + 1, i = 0; i < skip; i++) {
+	for (j = i; j < ac; j += skip) {
+	    for (p = av[j], len = strlen((char *)p), k = len; --k >= 0; p++)
+		TTYput(*p);
+	    if (j + skip < ac)
+		while (++len < longest + 3)
+		    TTYput(' ');
+	}
+	TTYputs((CHAR *)NEWLINE);
+    }
+}
+
+STATIC void
+reposition()
+{
+    int		i;
+    CHAR	*p;
+
+    TTYput('\r');
+    TTYputs((CONST CHAR *)Prompt);
+    for (i = Point, p = Line; --i >= 0; p++)
+	TTYshow(*p);
+}
+
+STATIC void
+left(Change)
+    STATUS	Change;
+{
+    TTYback();
+    if (Point) {
+	if (ISCTL(Line[Point - 1]))
+	    TTYback();
+        else if (rl_meta_chars && ISMETA(Line[Point - 1])) {
+	    TTYback();
+	    TTYback();
+	}
+    }
+    if (Change == CSmove)
+	Point--;
+}
+
+STATIC void
+right(Change)
+    STATUS	Change;
+{
+    TTYshow(Line[Point]);
+    if (Change == CSmove)
+	Point++;
+}
+
+STATIC STATUS
+ring_bell()
+{
+    TTYput('\07');
+    TTYflush();
+    return CSstay;
+}
+
+STATIC STATUS
+do_macro(c)
+    unsigned int	c;
+{
+    CHAR		name[4];
+
+    name[0] = '_';
+    name[1] = c;
+    name[2] = '_';
+    name[3] = '\0';
+
+    if ((Input = (CHAR *)getenv((char *)name)) == NULL) {
+	Input = NIL;
+	return ring_bell();
+    }
+    return CSstay;
+}
+
+STATIC STATUS
+do_forward(move)
+    STATUS	move;
+{
+    int		i;
+    CHAR	*p;
+
+    i = 0;
+    do {
+	p = &Line[Point];
+	for ( ; Point < End && (*p == ' ' || !isalnum(*p)); Point++, p++)
+	    if (move == CSmove)
+		right(CSstay);
+
+	for (; Point < End && isalnum(*p); Point++, p++)
+	    if (move == CSmove)
+		right(CSstay);
+
+	if (Point == End)
+	    break;
+    } while (++i < Repeat);
+
+    return CSstay;
+}
+
+STATIC STATUS
+do_case(type)
+    CASE	type;
+{
+    int		i;
+    int		end;
+    int		count;
+    CHAR	*p;
+
+    (void)do_forward(CSstay);
+    if (OldPoint != Point) {
+	if ((count = Point - OldPoint) < 0)
+	    count = -count;
+	Point = OldPoint;
+	if ((end = Point + count) > End)
+	    end = End;
+	for (i = Point, p = &Line[i]; i < end; i++, p++) {
+	    if (type == TOupper) {
+		if (islower(*p))
+		    *p = toupper(*p);
+	    }
+	    else if (isupper(*p))
+		*p = tolower(*p);
+	    right(CSmove);
+	}
+    }
+    return CSstay;
+}
+
+STATIC STATUS
+case_down_word()
+{
+    return do_case(TOlower);
+}
+
+STATIC STATUS
+case_up_word()
+{
+    return do_case(TOupper);
+}
+
+STATIC void
+ceol()
+{
+    int		extras;
+    int		i;
+    CHAR	*p;
+
+    for (extras = 0, i = Point, p = &Line[i]; i <= End; i++, p++) {
+	TTYput(' ');
+	if (ISCTL(*p)) {
+	    TTYput(' ');
+	    extras++;
+	}
+	else if (rl_meta_chars && ISMETA(*p)) {
+	    TTYput(' ');
+	    TTYput(' ');
+	    extras += 2;
+	}
+    }
+
+    for (i += extras; i > Point; i--)
+	TTYback();
+}
+
+STATIC void
+clear_line()
+{
+    Point = -strlen(Prompt);
+    TTYput('\r');
+    ceol();
+    Point = 0;
+    End = 0;
+    Line[0] = '\0';
+}
+
+STATIC STATUS
+insert_string(p)
+    CHAR	*p;
+{
+    SIZE_T	len;
+    int		i;
+    CHAR	*new;
+    CHAR	*q;
+
+    len = strlen((char *)p);
+    if (End + len >= Length) {
+	if ((new = NEW(CHAR, Length + len + MEM_INC)) == NULL)
+	    return CSstay;
+	if (Length) {
+	    COPYFROMTO(new, Line, Length);
+	    DISPOSE(Line);
+	}
+	Line = new;
+	Length += len + MEM_INC;
+    }
+
+    for (q = &Line[Point], i = End - Point; --i >= 0; )
+	q[len + i] = q[i];
+    COPYFROMTO(&Line[Point], p, len);
+    End += len;
+    Line[End] = '\0';
+    TTYstring(&Line[Point]);
+    Point += len;
+
+    return Point == End ? CSstay : CSmove;
+}
+
+STATIC STATUS
+redisplay()
+{
+    TTYputs((CONST CHAR *)NEWLINE);
+    TTYputs((CONST CHAR *)Prompt);
+    TTYstring(Line);
+    return CSmove;
+}
+
+STATIC STATUS
+toggle_meta_mode()
+{
+    rl_meta_chars = ! rl_meta_chars;
+    return redisplay();
+}
+
+
+
+STATIC CHAR *
+next_hist()
+{
+    return H.Pos >= H.Size - 1 ? NULL : H.Lines[++H.Pos];
+}
+
+STATIC CHAR *
+prev_hist()
+{
+    return H.Pos == 0 ? NULL : H.Lines[--H.Pos];
+}
+
+STATIC STATUS
+do_insert_hist(p)
+    CHAR	*p;
+{
+    if (p == NULL)
+	return ring_bell();
+    Point = 0;
+    reposition();
+    ceol();
+    End = 0;
+    return insert_string(p);
+}
+
+STATIC STATUS
+do_hist(move)
+    CHAR	*(*move)();
+{
+    CHAR	*p;
+    int		i;
+
+    i = 0;
+    do {
+	if ((p = (*move)()) == NULL)
+	    return ring_bell();
+    } while (++i < Repeat);
+    return do_insert_hist(p);
+}
+
+STATIC STATUS
+h_next()
+{
+    return do_hist(next_hist);
+}
+
+STATIC STATUS
+h_prev()
+{
+    return do_hist(prev_hist);
+}
+
+STATIC STATUS
+h_first()
+{
+    return do_insert_hist(H.Lines[H.Pos = 0]);
+}
+
+STATIC STATUS
+h_last()
+{
+    return do_insert_hist(H.Lines[H.Pos = H.Size - 1]);
+}
+
+/*
+**  Return zero if pat appears as a substring in text.
+*/
+STATIC int
+substrcmp(text, pat, len)
+    char	*text;
+    char	*pat;
+    int		len;
+{
+    char	c;
+
+    if ((c = *pat) == '\0')
+        return *text == '\0';
+    for ( ; *text; text++)
+        if (*text == c && strncmp(text, pat, len) == 0)
+            return 0;
+    return 1;
+}
+
+STATIC CHAR *
+search_hist(search, move)
+    CHAR	*search;
+    CHAR	*(*move)();
+{
+    static CHAR	*old_search;
+    int		len;
+    int		pos;
+    int		(*match)();
+    char	*pat;
+
+    /* Save or get remembered search pattern. */
+    if (search && *search) {
+	if (old_search)
+	    DISPOSE(old_search);
+	old_search = (CHAR *)strdup((char *)search);
+    }
+    else {
+	if (old_search == NULL || *old_search == '\0')
+            return NULL;
+	search = old_search;
+    }
+
+    /* Set up pattern-finder. */
+    if (*search == '^') {
+	match = strncmp;
+	pat = (char *)(search + 1);
+    }
+    else {
+	match = substrcmp;
+	pat = (char *)search;
+    }
+    len = strlen(pat);
+
+    for (pos = H.Pos; (*move)() != NULL; )
+	if ((*match)((char *)H.Lines[H.Pos], pat, len) == 0)
+            return H.Lines[H.Pos];
+    H.Pos = pos;
+    return NULL;
+}
+
+STATIC STATUS
+h_search()
+{
+    static int	Searching;
+    CONST char	*old_prompt;
+    CHAR	*(*move)();
+    CHAR	*p;
+
+    if (Searching)
+	return ring_bell();
+    Searching = 1;
+
+    clear_line();
+    old_prompt = Prompt;
+    Prompt = "Search: ";
+    TTYputs((CONST CHAR *)Prompt);
+    move = Repeat == NO_ARG ? prev_hist : next_hist;
+    p = editinput();
+    Prompt = old_prompt;
+    Searching = 0;
+    TTYputs((CONST CHAR *)Prompt);
+    if (p == NULL && Signal > 0) {
+	Signal = 0;
+	clear_line();
+	return redisplay();
+    }
+    p = search_hist(p, move);
+    clear_line();
+    if (p == NULL) {
+	(void)ring_bell();
+	return redisplay();
+    }
+    return do_insert_hist(p);
+}
+
+STATIC STATUS
+fd_char()
+{
+    int		i;
+
+    i = 0;
+    do {
+	if (Point >= End)
+	    break;
+	right(CSmove);
+    } while (++i < Repeat);
+    return CSstay;
+}
+
+STATIC void
+save_yank(begin, i)
+    int		begin;
+    int		i;
+{
+    if (Yanked) {
+	DISPOSE(Yanked);
+	Yanked = NULL;
+    }
+
+    if (i < 1)
+	return;
+
+    if ((Yanked = NEW(CHAR, (SIZE_T)i + 1)) != NULL) {
+	COPYFROMTO(Yanked, &Line[begin], i);
+	Yanked[i] = '\0';
+    }
+}
+
+STATIC STATUS
+delete_string(count)
+    int		count;
+{
+    int		i;
+    CHAR	*p;
+
+    if (count <= 0 || End == Point)
+	return ring_bell();
+
+    if (count == 1 && Point == End - 1) {
+	/* Optimize common case of delete at end of line. */
+	End--;
+	p = &Line[Point];
+	i = 1;
+	TTYput(' ');
+	if (ISCTL(*p)) {
+	    i = 2;
+	    TTYput(' ');
+	}
+	else if (rl_meta_chars && ISMETA(*p)) {
+	    i = 3;
+	    TTYput(' ');
+	    TTYput(' ');
+	}
+	TTYbackn(i);
+	*p = '\0';
+	return CSmove;
+    }
+    if (Point + count > End && (count = End - Point) <= 0)
+	return CSstay;
+
+    if (count > 1)
+	save_yank(Point, count);
+
+    for (p = &Line[Point], i = End - (Point + count) + 1; --i >= 0; p++)
+	p[0] = p[count];
+    ceol();
+    End -= count;
+    TTYstring(&Line[Point]);
+    return CSmove;
+}
+
+STATIC STATUS
+bk_char()
+{
+    int		i;
+
+    i = 0;
+    do {
+	if (Point == 0)
+	    break;
+	left(CSmove);
+    } while (++i < Repeat);
+
+    return CSstay;
+}
+
+STATIC STATUS
+bk_del_char()
+{
+    int		i;
+
+    i = 0;
+    do {
+	if (Point == 0)
+	    break;
+	left(CSmove);
+    } while (++i < Repeat);
+
+    return delete_string(i);
+}
+
+STATIC STATUS
+kill_line()
+{
+    int		i;
+
+    if (Repeat != NO_ARG) {
+	if (Repeat < Point) {
+	    i = Point;
+	    Point = Repeat;
+	    reposition();
+	    (void)delete_string(i - Point);
+	}
+	else if (Repeat > Point) {
+	    right(CSmove);
+	    (void)delete_string(Repeat - Point - 1);
+	}
+	return CSmove;
+    }
+
+    save_yank(Point, End - Point);
+    Line[Point] = '\0';
+    ceol();
+    End = Point;
+    return CSstay;
+}
+
+STATIC STATUS
+insert_char(c)
+    int		c;
+{
+    STATUS	s;
+    CHAR	buff[2];
+    CHAR	*p;
+    CHAR	*q;
+    int		i;
+
+    if (Repeat == NO_ARG || Repeat < 2) {
+	buff[0] = c;
+	buff[1] = '\0';
+	return insert_string(buff);
+    }
+
+    if ((p = NEW(CHAR, Repeat + 1)) == NULL)
+	return CSstay;
+    for (i = Repeat, q = p; --i >= 0; )
+	*q++ = c;
+    *q = '\0';
+    Repeat = 0;
+    s = insert_string(p);
+    DISPOSE(p);
+    return s;
+}
+
+STATIC STATUS
+meta()
+{
+    unsigned int	c;
+    KEYMAP		*kp;
+
+    if ((c = TTYget()) == EOF)
+	return CSeof;
+#if	defined(ANSI_ARROWS)
+    /* Also include VT-100 arrows. */
+    if (c == '[' || c == 'O')
+	switch (c = TTYget()) {
+	default:	return ring_bell();
+	case EOF:	return CSeof;
+	case 'A':	return h_prev();
+	case 'B':	return h_next();
+	case 'C':	return fd_char();
+	case 'D':	return bk_char();
+	}
+#endif	/* defined(ANSI_ARROWS) */
+
+    if (isdigit(c)) {
+	for (Repeat = c - '0'; (c = TTYget()) != EOF && isdigit(c); )
+	    Repeat = Repeat * 10 + c - '0';
+	Pushed = 1;
+	PushBack = c;
+	return CSstay;
+    }
+
+    if (isupper(c))
+	return do_macro(c);
+    for (kp = MetaMap; kp->Function; kp++)
+	if (kp->Key == c)
+	    return (*kp->Function)();
+
+    return ring_bell();
+}
+
+STATIC STATUS
+emacs(c)
+    unsigned int	c;
+{
+    STATUS		s;
+    KEYMAP		*kp;
+
+    OldPoint = Point;
+    if (rl_meta_chars && ISMETA(c)) {
+	Pushed = 1;
+	PushBack = UNMETA(c);
+	return meta();
+    }
+    for (kp = Map; kp->Function; kp++)
+	if (kp->Key == c)
+	    break;
+    s = kp->Function ? (*kp->Function)() : insert_char((int)c);
+    if (!Pushed)
+	/* No pushback means no repeat count; hacky, but true. */
+	Repeat = NO_ARG;
+    return s;
+}
+
+STATIC STATUS
+TTYspecial(c)
+    unsigned int	c;
+{
+    if (ISMETA(c))
+	return CSdispatch;
+
+    if (c == rl_erase || c == DEL)
+	return bk_del_char();
+    if (c == rl_kill) {
+	if (Point != 0) {
+	    Point = 0;
+	    reposition();
+	}
+	Repeat = NO_ARG;
+	return kill_line();
+    }
+    if (c == rl_eof && Point == 0 && End == 0)
+	return CSeof;
+    if (c == rl_intr) {
+	Signal = SIGINT;
+	return CSsignal;
+    }
+    if (c == rl_quit) {
+	Signal = SIGQUIT;
+	return CSeof;
+    }
+
+    return CSdispatch;
+}
+
+STATIC CHAR *
+editinput()
+{
+    unsigned int	c;
+
+    Repeat = NO_ARG;
+    OldPoint = Point = Mark = End = 0;
+    Line[0] = '\0';
+
+    Signal = -1;
+    while ((c = TTYget()) != EOF)
+	switch (TTYspecial(c)) {
+	case CSdone:
+	    return Line;
+	case CSeof:
+	    return NULL;
+	case CSsignal:
+	    return (CHAR *)"";
+	case CSmove:
+	    reposition();
+	    break;
+	case CSdispatch:
+	    switch (emacs(c)) {
+	    case CSdone:
+		return Line;
+	    case CSeof:
+		return NULL;
+	    case CSsignal:
+		return (CHAR *)"";
+	    case CSmove:
+		reposition();
+		break;
+	    case CSdispatch:
+	    case CSstay:
+		break;
+	    }
+	    break;
+	case CSstay:
+	    break;
+	}
+    return NULL;
+}
+
+STATIC void
+hist_add(p)
+    CHAR	*p;
+{
+    int		i;
+
+    if ((p = (CHAR *)strdup((char *)p)) == NULL)
+	return;
+    if (H.Size < HIST_SIZE)
+	H.Lines[H.Size++] = p;
+    else {
+	DISPOSE(H.Lines[0]);
+	for (i = 0; i < HIST_SIZE - 1; i++)
+	    H.Lines[i] = H.Lines[i + 1];
+	H.Lines[i] = p;
+    }
+    H.Pos = H.Size - 1;
+}
+
+/*
+**  For compatibility with FSF readline.
+*/
+/* ARGSUSED0 */
+void
+rl_reset_terminal(p)
+    char	*p;
+{
+}
+
+void
+rl_initialize()
+{
+}
+
+char *
+readline(prompt)
+    CONST char	*prompt;
+{
+    CHAR	*line;
+    int		s;
+
+    if (Line == NULL) {
+	Length = MEM_INC;
+	if ((Line = NEW(CHAR, Length)) == NULL)
+	    return NULL;
+    }
+
+    TTYinfo();
+    rl_ttyset(0);
+    hist_add(NIL);
+    ScreenSize = SCREEN_INC;
+    Screen = NEW(char, ScreenSize);
+    Prompt = prompt ? prompt : (char *)NIL;
+    TTYputs((CONST CHAR *)Prompt);
+    if ((line = editinput()) != NULL) {
+	line = (CHAR *)strdup((char *)line);
+	TTYputs((CHAR *)NEWLINE);
+	TTYflush();
+    }
+    rl_ttyset(1);
+    DISPOSE(Screen);
+    DISPOSE(H.Lines[--H.Size]);
+
+    if (line != NULL && *line != '\0'
+#if	defined(UNIQUE_HISTORY)
+	&& !(H.Pos && strcmp((char *) line, (char *) H.Lines[H.Pos - 1]) == 0)
+#endif	/* defined(UNIQUE_HISTORY) */
+	&& !(H.Size && strcmp((char *) line, (char *) H.Lines[H.Size - 1]) == 0)
+    ) {
+	hist_add(line);
+    }
+
+    if (Signal > 0) {
+	s = Signal;
+	Signal = 0;
+	(void)kill(getpid(), s);
+    }
+    return (char *)line;
+}
+
+void
+add_history(p)
+    char	*p;
+{
+#ifdef obsolete		/* Made part of readline(). -- kjb */
+    if (p == NULL || *p == '\0')
+	return;
+
+#if	defined(UNIQUE_HISTORY)
+    if (H.Pos && strcmp(p, (char *) H.Lines[H.Pos - 1]) == 0)
+        return;
+#endif	/* defined(UNIQUE_HISTORY) */
+    if (H.Size && strcmp(p, (char *) H.Lines[H.Size - 1]) == 0)
+	return;
+    hist_add((CHAR *)p);
+#endif
+}
+
+
+
+STATIC STATUS
+beg_line()
+{
+    if (Point) {
+	Point = 0;
+	return CSmove;
+    }
+    return CSstay;
+}
+
+STATIC STATUS
+del_char()
+{
+    return delete_string(Repeat == NO_ARG ? 1 : Repeat);
+}
+
+STATIC STATUS
+end_line()
+{
+    if (Point != End) {
+	Point = End;
+	return CSmove;
+    }
+    return CSstay;
+}
+
+STATIC char	SEPS[] = "\"#$&'()*:;<=>?[\\]^`{|}~\n\t ";
+
+/*
+**  Move back to the beginning of the current word and return an
+**  allocated copy of it.
+*/
+STATIC CHAR *
+find_word()
+{
+    CHAR	*p, *q;
+    CHAR	*new;
+    SIZE_T	len;
+
+    p = &Line[Point];
+    while (p > Line) {
+	p--;
+	if (p > Line && p[-1] == '\\') {
+	    p--;
+	} else {
+	    if (strchr(SEPS, (char) *p) != NULL) {
+		p++;
+		break;
+	    }
+	}
+    }
+    len = Point - (p - Line) + 1;
+    if ((new = NEW(CHAR, len)) == NULL)
+	return NULL;
+    q = new;
+    while (p < &Line[Point]) {
+	if (*p == '\\') {
+	    if (++p == &Line[Point]) break;
+	}
+	*q++ = *p++;
+    }
+    *q = '\0';
+    return new;
+}
+
+STATIC STATUS
+c_possible()
+{
+    CHAR	**av;
+    CHAR	*word;
+    int		ac;
+
+    word = find_word();
+    ac = rl_list_possib((char *)word, (char ***)&av);
+    if (word)
+	DISPOSE(word);
+    if (ac) {
+	columns(ac, av);
+	while (--ac >= 0)
+	    DISPOSE(av[ac]);
+	DISPOSE(av);
+	return CSmove;
+    }
+    return ring_bell();
+}
+
+STATIC STATUS
+c_complete()
+{
+    CHAR	*p, *q;
+    CHAR	*word, *new;
+    SIZE_T	len;
+    int		unique;
+    STATUS	s;
+
+    word = find_word();
+    p = (CHAR *)rl_complete((char *)word, &unique);
+    if (word)
+	DISPOSE(word);
+    if (p) {
+	len = strlen((char *)p);
+	word = p;
+	new = q = NEW(CHAR, 2 * len + 1);
+	while (*p) {
+	    if ((*p < ' ' || strchr(SEPS, (char) *p) != NULL)
+				&& (!unique || p[1] != 0)) {
+		*q++ = '\\';
+	    }
+	    *q++ = *p++;
+	}
+	*q = '\0';
+	DISPOSE(word);
+	if (len > 0) {
+	    s = insert_string(new);
+#if ANNOYING_NOISE
+	    if (!unique)
+		(void)ring_bell();
+#endif
+	}
+	DISPOSE(new);
+	if (len > 0) return s;
+    }
+    return c_possible();
+}
+
+STATIC STATUS
+accept_line()
+{
+    Line[End] = '\0';
+    return CSdone;
+}
+
+STATIC STATUS
+transpose()
+{
+    CHAR	c;
+
+    if (Point) {
+	if (Point == End)
+	    left(CSmove);
+	c = Line[Point - 1];
+	left(CSstay);
+	Line[Point - 1] = Line[Point];
+	TTYshow(Line[Point - 1]);
+	Line[Point++] = c;
+	TTYshow(c);
+    }
+    return CSstay;
+}
+
+STATIC STATUS
+quote()
+{
+    unsigned int	c;
+
+    return (c = TTYget()) == EOF ? CSeof : insert_char((int)c);
+}
+
+STATIC STATUS
+wipe()
+{
+    int		i;
+
+    if (Mark > End)
+	return ring_bell();
+
+    if (Point > Mark) {
+	i = Point;
+	Point = Mark;
+	Mark = i;
+	reposition();
+    }
+
+    return delete_string(Mark - Point);
+}
+
+STATIC STATUS
+mk_set()
+{
+    Mark = Point;
+    return CSstay;
+}
+
+STATIC STATUS
+exchange()
+{
+    unsigned int	c;
+
+    if ((c = TTYget()) != CTL('X'))
+	return c == EOF ? CSeof : ring_bell();
+
+    if ((c = Mark) <= End) {
+	Mark = Point;
+	Point = c;
+	return CSmove;
+    }
+    return CSstay;
+}
+
+STATIC STATUS
+yank()
+{
+    if (Yanked && *Yanked)
+	return insert_string(Yanked);
+    return CSstay;
+}
+
+STATIC STATUS
+copy_region()
+{
+    if (Mark > End)
+	return ring_bell();
+
+    if (Point > Mark)
+	save_yank(Mark, Point - Mark);
+    else
+	save_yank(Point, Mark - Point);
+
+    return CSstay;
+}
+
+STATIC STATUS
+move_to_char()
+{
+    unsigned int	c;
+    int			i;
+    CHAR		*p;
+
+    if ((c = TTYget()) == EOF)
+	return CSeof;
+    for (i = Point + 1, p = &Line[i]; i < End; i++, p++)
+	if (*p == c) {
+	    Point = i;
+	    return CSmove;
+	}
+    return CSstay;
+}
+
+STATIC STATUS
+fd_word()
+{
+    return do_forward(CSmove);
+}
+
+STATIC STATUS
+fd_kill_word()
+{
+    int		i;
+
+    (void)do_forward(CSstay);
+    if (OldPoint != Point) {
+	i = Point - OldPoint;
+	Point = OldPoint;
+	return delete_string(i);
+    }
+    return CSstay;
+}
+
+STATIC STATUS
+bk_word()
+{
+    int		i;
+    CHAR	*p;
+
+    i = 0;
+    do {
+	for (p = &Line[Point]; p > Line && !isalnum(p[-1]); p--)
+	    left(CSmove);
+
+	for (; p > Line && p[-1] != ' ' && isalnum(p[-1]); p--)
+	    left(CSmove);
+
+	if (Point == 0)
+	    break;
+    } while (++i < Repeat);
+
+    return CSstay;
+}
+
+STATIC STATUS
+bk_kill_word()
+{
+    (void)bk_word();
+    if (OldPoint != Point)
+	return delete_string(OldPoint - Point);
+    return CSstay;
+}
+
+STATIC int
+argify(line, avp)
+    CHAR	*line;
+    CHAR	***avp;
+{
+    CHAR	*c;
+    CHAR	**p;
+    CHAR	**new;
+    int		ac;
+    int		i;
+
+    i = MEM_INC;
+    if ((*avp = p = NEW(CHAR*, i))== NULL)
+	 return 0;
+
+    for (c = line; isspace(*c); c++)
+	continue;
+    if (*c == '\n' || *c == '\0')
+	return 0;
+
+    for (ac = 0, p[ac++] = c; *c && *c != '\n'; ) {
+	if (isspace(*c)) {
+	    *c++ = '\0';
+	    if (*c && *c != '\n') {
+		if (ac + 1 == i) {
+		    new = NEW(CHAR*, i + MEM_INC);
+		    if (new == NULL) {
+			p[ac] = NULL;
+			return ac;
+		    }
+		    COPYFROMTO(new, p, i * sizeof (char **));
+		    i += MEM_INC;
+		    DISPOSE(p);
+		    *avp = p = new;
+		}
+		p[ac++] = c;
+	    }
+	}
+	else
+	    c++;
+    }
+    *c = '\0';
+    p[ac] = NULL;
+    return ac;
+}
+
+STATIC STATUS
+last_argument()
+{
+    CHAR	**av;
+    CHAR	*p;
+    STATUS	s;
+    int		ac;
+
+    if (H.Size == 1 || (p = H.Lines[H.Size - 2]) == NULL)
+	return ring_bell();
+
+    if ((p = (CHAR *)strdup((char *)p)) == NULL)
+	return CSstay;
+    ac = argify(p, &av);
+
+    if (Repeat != NO_ARG)
+	s = Repeat < ac ? insert_string(av[Repeat]) : ring_bell();
+    else
+	s = ac ? insert_string(av[ac - 1]) : CSstay;
+
+    if (ac)
+	DISPOSE(av);
+    DISPOSE(p);
+    return s;
+}
+
+STATIC KEYMAP	Map[33] = {
+    {	CTL('@'),	mk_set		},
+    {	CTL('A'),	beg_line	},
+    {	CTL('B'),	bk_char		},
+    {	CTL('D'),	del_char	},
+    {	CTL('E'),	end_line	},
+    {	CTL('F'),	fd_char		},
+    {	CTL('G'),	ring_bell	},
+    {	CTL('H'),	bk_del_char	},
+    {	CTL('I'),	c_complete	},
+    {	CTL('J'),	accept_line	},
+    {	CTL('K'),	kill_line	},
+    {	CTL('L'),	redisplay	},
+    {	CTL('M'),	accept_line	},
+    {	CTL('N'),	h_next		},
+    {	CTL('O'),	ring_bell	},
+    {	CTL('P'),	h_prev		},
+    {	CTL('Q'),	ring_bell	},
+    {	CTL('R'),	h_search	},
+    {	CTL('S'),	ring_bell	},
+    {	CTL('T'),	transpose	},
+    {	CTL('U'),	ring_bell	},
+    {	CTL('V'),	quote		},
+    {	CTL('W'),	bk_kill_word	},
+    {	CTL('X'),	exchange	},
+    {	CTL('Y'),	yank		},
+    {	CTL('Z'),	end_line	},
+    {	CTL('['),	meta		},
+    {	CTL(']'),	move_to_char	},
+    {	CTL('^'),	ring_bell	},
+    {	CTL('_'),	ring_bell	},
+    {	0,		NULL		}
+};
+
+STATIC KEYMAP	MetaMap[17]= {
+    {	CTL('H'),	wipe		},
+    {	DEL,		wipe		},
+    {	' ',		mk_set		},
+    {	'.',		last_argument	},
+    {	'<',		h_first		},
+    {	'>',		h_last		},
+    {	'?',		c_possible	},
+    {	'b',		bk_word		},
+    {	'd',		fd_kill_word	},
+    {	'f',		fd_word		},
+    {	'l',		case_down_word	},
+    {	'm',		toggle_meta_mode },
+    {	'u',		case_up_word	},
+    {	'y',		yank		},
+    {	'w',		copy_region	},
+    {	0,		NULL		}
+};
+
+/*
+ * $PchId: editline.c,v 1.4 1996/02/22 21:16:56 philip Exp $
+ */
Index: /trunk/minix/lib/editline/editline.h
===================================================================
--- /trunk/minix/lib/editline/editline.h	(revision 9)
+++ /trunk/minix/lib/editline/editline.h	(revision 9)
@@ -0,0 +1,79 @@
+/*  $Revision: 1.1.1.1 $
+**
+**  Internal header file for editline library.
+*/
+#include <stdio.h>
+#if	defined(HAVE_STDLIB)
+#include <stdlib.h>
+#include <string.h>
+#endif	/* defined(HAVE_STDLIB) */
+#if	defined(SYS_UNIX)
+#include "unix.h"
+#endif	/* defined(SYS_UNIX) */
+#if	defined(SYS_OS9)
+#include "os9.h"
+#endif	/* defined(SYS_OS9) */
+
+#if	!defined(SIZE_T)
+#define SIZE_T	unsigned int
+#endif	/* !defined(SIZE_T) */
+
+typedef unsigned char	CHAR;
+
+#if	defined(HIDE)
+#define STATIC	static
+#else
+#define STATIC	/* NULL */
+#endif	/* !defined(HIDE) */
+
+#if	!defined(CONST)
+#if	defined(__STDC__)
+#define CONST	const
+#else
+#define CONST
+#endif	/* defined(__STDC__) */
+#endif	/* !defined(CONST) */
+
+
+#define MEM_INC		64
+#define SCREEN_INC	256
+
+#define DISPOSE(p)	free((char *)(p))
+#define NEW(T, c)	\
+	((T *)malloc((unsigned int)(sizeof (T) * (c))))
+#define RENEW(p, T, c)	\
+	(p = (T *)realloc((char *)(p), (unsigned int)(sizeof (T) * (c))))
+#define COPYFROMTO(new, p, len)	\
+	(void)memcpy((char *)(new), (char *)(p), (int)(len))
+
+
+/*
+**  Variables and routines internal to this package.
+*/
+extern int	rl_eof;
+extern int	rl_erase;
+extern int	rl_intr;
+extern int	rl_kill;
+extern int	rl_quit;
+extern char	*rl_complete();
+extern int	rl_list_possib();
+extern void	rl_ttyset();
+extern void	rl_add_slash();
+
+#if	!defined(HAVE_STDLIB)
+extern char	*getenv();
+extern char	*malloc();
+extern char	*realloc();
+extern char	*memcpy();
+extern char	*strcat();
+extern char	*strchr();
+extern char	*strrchr();
+extern char	*strcpy();
+extern int	strcmp();
+extern int	strlen();
+extern int	strncmp();
+#endif	/* !defined(HAVE_STDLIB) */
+
+#if	defined(NEED_STRDUP)
+extern char	*strdup();
+#endif
Index: /trunk/minix/lib/editline/sysunix.c
===================================================================
--- /trunk/minix/lib/editline/sysunix.c	(revision 9)
+++ /trunk/minix/lib/editline/sysunix.c	(revision 9)
@@ -0,0 +1,120 @@
+/*  $Revision: 1.1.1.1 $
+**
+**  Unix system-dependant routines for editline library.
+*/
+#include "editline.h"
+
+#if	defined(HAVE_TCGETATTR)
+#include <termios.h>
+
+void
+rl_ttyset(Reset)
+    int				Reset;
+{
+    static struct termios	old;
+    struct termios		new;
+
+    if (Reset == 0) {
+	(void)tcgetattr(0, &old);
+	rl_erase = old.c_cc[VERASE];
+	rl_kill = old.c_cc[VKILL];
+	rl_eof = old.c_cc[VEOF];
+	rl_intr = old.c_cc[VINTR];
+	rl_quit = old.c_cc[VQUIT];
+
+	new = old;
+	new.c_lflag &= ~(ECHO | ICANON | ISIG | IEXTEN);
+	new.c_iflag &= ~(ICRNL);
+	new.c_cc[VMIN] = 1;
+	new.c_cc[VTIME] = 0;
+	(void)tcsetattr(0, TCSADRAIN, &new);
+    }
+    else
+	(void)tcsetattr(0, TCSADRAIN, &old);
+}
+
+#else
+#if	defined(HAVE_TERMIO)
+#include <termio.h>
+
+void
+rl_ttyset(Reset)
+    int				Reset;
+{
+    static struct termio	old;
+    struct termio		new;
+
+    if (Reset == 0) {
+	(void)ioctl(0, TCGETA, &old);
+	rl_erase = old.c_cc[VERASE];
+	rl_kill = old.c_cc[VKILL];
+	rl_eof = old.c_cc[VEOF];
+	rl_intr = old.c_cc[VINTR];
+	rl_quit = old.c_cc[VQUIT];
+
+	new = old;
+	new.c_cc[VINTR] = -1;
+	new.c_cc[VQUIT] = -1;
+	new.c_lflag &= ~(ECHO | ICANON);
+	new.c_cc[VMIN] = 1;
+	new.c_cc[VTIME] = 0;
+	(void)ioctl(0, TCSETAW, &new);
+    }
+    else
+	(void)ioctl(0, TCSETAW, &old);
+}
+
+#else
+#include <sgtty.h>
+
+void
+rl_ttyset(Reset)
+    int				Reset;
+{
+    static struct sgttyb	old_sgttyb;
+    static struct tchars	old_tchars;
+    struct sgttyb		new_sgttyb;
+    struct tchars		new_tchars;
+
+    if (Reset == 0) {
+	(void)ioctl(0, TIOCGETP, &old_sgttyb);
+	rl_erase = old_sgttyb.sg_erase;
+	rl_kill = old_sgttyb.sg_kill;
+
+	(void)ioctl(0, TIOCGETC, &old_tchars);
+	rl_eof = old_tchars.t_eofc;
+	rl_intr = old_tchars.t_intrc;
+	rl_quit = old_tchars.t_quitc;
+
+	new_sgttyb = old_sgttyb;
+	new_sgttyb.sg_flags &= ~ECHO;
+	new_sgttyb.sg_flags |= RAW;
+	(void)ioctl(0, TIOCSETP, &new_sgttyb);
+
+	new_tchars = old_tchars;
+	new_tchars.t_intrc = -1;
+	new_tchars.t_quitc = -1;
+	(void)ioctl(0, TIOCSETC, &new_tchars);
+    }
+    else {
+	(void)ioctl(0, TIOCSETP, &old_sgttyb);
+	(void)ioctl(0, TIOCSETC, &old_tchars);
+    }
+}
+#endif	/* defined(HAVE_TERMIO) */
+#endif	/* defined(HAVE_TCGETATTR) */
+
+void
+rl_add_slash(path, p)
+    char	*path;
+    char	*p;
+{
+    struct stat	Sb;
+
+    if (stat(path, &Sb) >= 0)
+	(void)strcat(p, S_ISDIR(Sb.st_mode) ? "/" : " ");
+}
+
+/*
+ * $PchId: sysunix.c,v 1.4 1996/02/22 21:16:56 philip Exp $
+ */
Index: /trunk/minix/lib/editline/testit.c
===================================================================
--- /trunk/minix/lib/editline/testit.c	(revision 9)
+++ /trunk/minix/lib/editline/testit.c	(revision 9)
@@ -0,0 +1,68 @@
+/*  $Revision: 1.1.1.1 $
+**
+**  A "micro-shell" to test editline library.
+**  If given any arguments, commands aren't executed.
+*/
+#include <stdio.h>
+#if	defined(HAVE_STDLIB)
+#include <stdlib.h>
+#endif	/* defined(HAVE_STDLIB) */
+
+extern char	*readline();
+extern void	add_history();
+
+#if	!defined(HAVE_STDLIB)
+extern int	chdir();
+extern int	free();
+extern int	strncmp();
+extern int	system();
+extern void	exit();
+extern char	*getenv();
+#endif	/* !defined(HAVE_STDLIB) */
+
+
+#if	defined(NEED_PERROR)
+void
+perror(s)
+    char	*s;
+{
+    extern int	errno;
+
+    (voidf)printf(stderr, "%s: error %d\n", s, errno);
+}
+#endif	/* defined(NEED_PERROR) */
+
+
+/* ARGSUSED1 */
+int
+main(ac, av)
+    int		ac;
+    char	*av[];
+{
+    char	*prompt;
+    char	*p;
+    int		doit;
+
+    doit = ac == 1;
+    if ((prompt = getenv("TESTPROMPT")) == NULL)
+	prompt = "testit>  ";
+
+    while ((p = readline(prompt)) != NULL) {
+	(void)printf("\t\t\t|%s|\n", p);
+	if (doit)
+	    if (strncmp(p, "cd ", 3) == 0) {
+		if (chdir(&p[3]) < 0)
+		    perror(&p[3]);
+	    }
+	    else if (system(p) != 0)
+		perror(p);
+	add_history(p);
+	free(p);
+    }
+    exit(0);
+    /* NOTREACHED */
+}
+
+/*
+ * $PchId: testit.c,v 1.3 1996/02/22 21:18:51 philip Exp $
+ */
Index: /trunk/minix/lib/editline/unix.h
===================================================================
--- /trunk/minix/lib/editline/unix.h	(revision 9)
+++ /trunk/minix/lib/editline/unix.h	(revision 9)
@@ -0,0 +1,26 @@
+/*  $Revision: 1.1.1.1 $
+**
+**  Editline system header file for Unix.
+*/
+
+#define CRLF		"\r\n"
+#define FORWARD		STATIC
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if	defined(USE_DIRENT)
+#include <dirent.h>
+typedef struct dirent	DIRENTRY;
+#else
+#include <sys/dir.h>
+typedef struct direct	DIRENTRY;
+#endif	/* defined(USE_DIRENT) */
+
+#if	!defined(S_ISDIR)
+#define S_ISDIR(m)		(((m) & S_IFMT) == S_IFDIR)
+#endif	/* !defined(S_ISDIR) */
+
+/*
+ * $PchId: unix.h,v 1.3 1996/02/22 21:18:51 philip Exp $
+ */
Index: /trunk/minix/lib/end/Makedepend-ack
===================================================================
--- /trunk/minix/lib/end/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/end/Makedepend-ack	(revision 9)
@@ -0,0 +1,7 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc  -E' edata.s | sed -e 's:^\(.\):../obj-ack//./end/\1:' >> .depend-ack
+	mkdep 'cc  -E' em_end.s | sed -e 's:^\(.\):../obj-ack//./end/\1:' >> .depend-ack
+	mkdep 'cc  -E' end.s | sed -e 's:^\(.\):../obj-ack//./end/\1:' >> .depend-ack
+	mkdep 'cc  -E' etext.s | sed -e 's:^\(.\):../obj-ack//./end/\1:' >> .depend-ack
Index: /trunk/minix/lib/end/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/end/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/end/Makedepend-gnu	(revision 9)
@@ -0,0 +1,7 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' edata.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./end/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' em_end.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./end/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' end.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./end/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' etext.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./end/\1:' >> .depend-gnu
Index: /trunk/minix/lib/end/Makefile
===================================================================
--- /trunk/minix/lib/end/Makefile	(revision 9)
+++ /trunk/minix/lib/end/Makefile	(revision 9)
@@ -0,0 +1,77 @@
+#Generated from ./end/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./end ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./end ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//end.a
+
+../obj-ack//end.a: ../obj-ack//end.a(edata.o)
+../obj-ack//end.a: ../obj-ack//end.a(em_end.o)
+../obj-ack//end.a: ../obj-ack//end.a(end.o)
+../obj-ack//end.a: ../obj-ack//end.a(etext.o)
+
+../obj-ack//end.a:
+	ar cr ../obj-ack//end.a ../obj-ack//./end/*.o
+	rm ../obj-ack//./end/*.o
+
+../obj-ack//end.a(edata.o): edata.s
+	cc  -c -o ../obj-ack//./end/edata.o edata.s
+../obj-ack//end.a(em_end.o): em_end.s
+	cc  -c -o ../obj-ack//./end/em_end.o em_end.s
+../obj-ack//end.a(end.o): end.s
+	cc  -c -o ../obj-ack//./end/end.o end.s
+../obj-ack//end.a(etext.o): etext.s
+	cc  -c -o ../obj-ack//./end/etext.o etext.s
+
+all-gnu: ../obj-gnu/end.a
+
+../obj-gnu/end.a: ../obj-gnu/./end/edata.o
+../obj-gnu/end.a: ../obj-gnu/./end/em_end.o
+../obj-gnu/end.a: ../obj-gnu/./end/end.o
+../obj-gnu/end.a: ../obj-gnu/./end/etext.o
+
+../obj-gnu/end.a:
+	gar cr ../obj-gnu/end.a $?
+
+../obj-gnu/./end/edata.o: edata.s
+	gcc  -E -x assembler-with-cpp -I. edata.s | asmconv -mi386 ack gnu > ../obj-gnu/./end/edata.s.gnu || true
+	gas -o ../obj-gnu/./end/edata.o ../obj-gnu/./end/edata.s.gnu
+
+../obj-gnu/./end/em_end.o: em_end.s
+	gcc  -E -x assembler-with-cpp -I. em_end.s | asmconv -mi386 ack gnu > ../obj-gnu/./end/em_end.s.gnu || true
+	gas -o ../obj-gnu/./end/em_end.o ../obj-gnu/./end/em_end.s.gnu
+
+../obj-gnu/./end/end.o: end.s
+	gcc  -E -x assembler-with-cpp -I. end.s | asmconv -mi386 ack gnu > ../obj-gnu/./end/end.s.gnu || true
+	gas -o ../obj-gnu/./end/end.o ../obj-gnu/./end/end.s.gnu
+
+../obj-gnu/./end/etext.o: etext.s
+	gcc  -E -x assembler-with-cpp -I. etext.s | asmconv -mi386 ack gnu > ../obj-gnu/./end/etext.s.gnu || true
+	gas -o ../obj-gnu/./end/etext.o ../obj-gnu/./end/etext.s.gnu
+
+
+
+
+clean::
+	rm -f ../obj-ack//./end/*
+	rm -f ../obj-gnu/./end/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/end/Makefile.in
===================================================================
--- /trunk/minix/lib/end/Makefile.in	(revision 9)
+++ /trunk/minix/lib/end/Makefile.in	(revision 9)
@@ -0,0 +1,11 @@
+# Makefile for lib/end.
+
+LIBRARIES=end
+
+end_FILES=" \
+	edata.s \
+	em_end.s \
+	end.s \
+	etext.s"
+
+TYPE=both
Index: /trunk/minix/lib/end/edata.s
===================================================================
--- /trunk/minix/lib/end/edata.s	(revision 9)
+++ /trunk/minix/lib/end/edata.s	(revision 9)
@@ -0,0 +1,7 @@
+#
+.sect .text
+.sect .rom
+.sect .data
+.align _EM_WSIZE
+.define _edata
+_edata:
Index: /trunk/minix/lib/end/em_end.s
===================================================================
--- /trunk/minix/lib/end/em_end.s	(revision 9)
+++ /trunk/minix/lib/end/em_end.s	(revision 9)
@@ -0,0 +1,21 @@
+#
+.sect .text
+.align _EM_WSIZE
+.define __etext, endtext
+__etext:
+endtext:
+.sect .rom
+.align _EM_WSIZE
+.define endrom
+endrom:
+.sect .data
+.align _EM_WSIZE
+.define __edata, enddata
+__edata:
+enddata:
+.sect .bss
+.align _EM_WSIZE
+.sect .end	! only for declaration of _end, __end or endbss.
+.define __end, endbss
+__end:
+endbss:
Index: /trunk/minix/lib/end/end.s
===================================================================
--- /trunk/minix/lib/end/end.s	(revision 9)
+++ /trunk/minix/lib/end/end.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+.sect .end	! only for declaration of _end, __end or endbss.
+.define _end
+_end:
Index: /trunk/minix/lib/end/etext.s
===================================================================
--- /trunk/minix/lib/end/etext.s	(revision 9)
+++ /trunk/minix/lib/end/etext.s	(revision 9)
@@ -0,0 +1,5 @@
+#
+.sect .text
+.align _EM_WSIZE
+.define _etext
+_etext:
Index: /trunk/minix/lib/float/FP.compile
===================================================================
--- /trunk/minix/lib/float/FP.compile	(revision 9)
+++ /trunk/minix/lib/float/FP.compile	(revision 9)
@@ -0,0 +1,20 @@
+#!/bin/sh
+#							Author: Kees J. Bot
+# Compile one soft FP source file.
+# (These files shouldn't be optimized normally, but the 16-bit C compiler
+# only optimizes scratch register allocation a bit with -O.  To the 32-bit
+# compiler -O is a no-op.)
+
+case $#:$1 in
+1:*.c)	;;
+*)	echo "$0: $1: not a C file" >&2; exit 1
+esac
+
+base="`basename "$1" .c`"
+trap 'rm -f tmp.s "$base.s"; exit 1' 2
+
+cc -O -I. -D_MINIX -D_POSIX_SOURCE -S "$1" &&
+mv "$base.s" tmp.s &&
+sed -f FP.script tmp.s > "$base.s" &&
+cc -c "$base.s" &&
+rm tmp.s "$base.s"
Index: /trunk/minix/lib/float/FP.script
===================================================================
--- /trunk/minix/lib/float/FP.script	(revision 9)
+++ /trunk/minix/lib/float/FP.script	(revision 9)
@@ -0,0 +1,39 @@
+s/_adf4/.adf4/
+s/_adf8/.adf8/
+s/_cff4/.cff4/
+s/_cff8/.cff8/
+s/_cfi/.cfi/
+s/_cfu/.cfu/
+s/_cif4/.cif4/
+s/_cif8/.cif8/
+s/_cmf4/.cmf4/
+s/_cmf8/.cmf8/
+s/_cuf4/.cuf4/
+s/_cuf8/.cuf8/
+s/_dvf4/.dvf4/
+s/_dvf8/.dvf8/
+s/_fef4/.fef4/
+s/_fef8/.fef8/
+s/_fif4/.fif4/
+s/_fif8/.fif8/
+s/_mlf4/.mlf4/
+s/_mlf8/.mlf8/
+s/_ngf4/.ngf4/
+s/_ngf8/.ngf8/
+s/_sbf4/.sbf4/
+s/_sbf8/.sbf8/
+s/_zrf4/.zrf4/
+s/_zrf8/.zrf8/
+s/_add_ext/.add_ext/
+s/_div_ext/.div_ext/
+s/_mul_ext/.mul_ext/
+s/_nrm_ext/.nrm_ext/
+s/_sft_ext/.sft_ext/
+s/_sub_ext/.sub_ext/
+s/_zrf_ext/.zrf_ext/
+s/_compact/.compact/
+s/_extend/.extend/
+s/_b64_add/.b64_add/
+s/_b64_sft/.b64_sft/
+s/_b64_rsft/.b64_rsft/
+s/_b64_lsft/.b64_lsft/
Index: /trunk/minix/lib/float/FP_bias.h
===================================================================
--- /trunk/minix/lib/float/FP_bias.h	(revision 9)
+++ /trunk/minix/lib/float/FP_bias.h	(revision 9)
@@ -0,0 +1,28 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/FP_bias.h,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	include file for floating point package
+*/
+
+		/*	FLOAT FORMAT EXPONENT BIAS	*/
+
+#define	SGL_BIAS	 127	/* excess  128 notation used	*/
+#define	DBL_BIAS	1023	/* excess 1024 notation used	*/
+#define	EXT_BIAS	   0	/* 2s-complement notation used	*/
+				/* this is possible because the	*/
+				/* sign is in a seperate word	*/
+		
+		/*	VARIOUS MAX AND MIN VALUES	*/
+		/*	1) FOR THE DIFFERENT FORMATS	*/
+
+#define	SGL_MAX		   254	/*	standard definition	*/
+#define	SGL_MIN		     1	/*	standard definition	*/
+#define	DBL_MAX		  2046	/*	standard definition	*/
+#define	DBL_MIN		     1	/*	standard definition	*/
+#define EXT_MAX		 16383	/*	standard minimum	*/
+#define EXT_MIN		-16382	/*	standard minimum	*/
Index: /trunk/minix/lib/float/FP_shift.h
===================================================================
--- /trunk/minix/lib/float/FP_shift.h	(revision 9)
+++ /trunk/minix/lib/float/FP_shift.h	(revision 9)
@@ -0,0 +1,49 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/FP_shift.h,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	include file for floating point package
+*/
+
+# define	CARRYBIT	0x80000000L
+# define	NORMBIT		0x80000000L
+# define	EXP_STORE	16
+
+
+				/* parameters for Single Precision */
+#define SGL_EXPSHIFT	7
+#define SGL_M1LEFT	8
+#define SGL_ZERO	0xffffff80L
+#define SGL_EXACT	0xff
+#define SGL_RUNPACK	SGL_M1LEFT
+
+#define SGL_ROUNDUP	0x80
+#define	SGL_CARRYOUT	0x01000000L
+#define	SGL_MASK	0x007fffffL
+
+				/* parameters for Double Precision */
+				/* used in extend.c */
+
+#define DBL_EXPSHIFT	4
+
+#define DBL_M1LEFT	11
+
+#define	DBL_RPACK	(32-DBL_M1LEFT)
+#define	DBL_LPACK	DBL_M1LEFT
+
+				/* used in compact.c */
+
+#define DBL_ZERO	0xfffffd00L
+
+#define DBL_EXACT	0x7ff
+
+#define DBL_RUNPACK	DBL_M1LEFT
+#define DBL_LUNPACK	(32-DBL_RUNPACK)
+
+#define DBL_ROUNDUP	0x400
+#define	DBL_CARRYOUT	0x00200000L
+#define	DBL_MASK	0x000fffffL
Index: /trunk/minix/lib/float/FP_trap.h
===================================================================
--- /trunk/minix/lib/float/FP_trap.h	(revision 9)
+++ /trunk/minix/lib/float/FP_trap.h	(revision 9)
@@ -0,0 +1,22 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/FP_trap.h,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	include file for floating point package
+*/
+
+			/*	EM TRAPS	*/
+
+#define	EIOVFL	3	/* Integer  Overflow		*/
+#define	EFOVFL	4	/* Floating Overflow		*/
+#define	EFUNFL	5	/* Floating Underflow		*/
+#define	EIDIVZ	6	/* Integer  Divide by 0		*/
+#define	EFDIVZ	7	/* Floating Divide by 0.0	*/
+#define	EIUND	8	/* Integer  Undefined Number	*/
+#define	EFUND	9	/* Floating Undefined Number	*/
+#define	ECONV	10	/* Conversion Error		*/
+# define trap(x) _fptrp(x)
Index: /trunk/minix/lib/float/FP_types.h
===================================================================
--- /trunk/minix/lib/float/FP_types.h	(revision 9)
+++ /trunk/minix/lib/float/FP_types.h	(revision 9)
@@ -0,0 +1,113 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/FP_types.h,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/********************************************************/
+/*
+	Type definitions for C Floating Point Package
+	include file for floating point package
+*/
+/********************************************************/
+/*
+	THESE STRUCTURES ARE USED TO ADDRESS THE INDIVIDUAL
+	PARTS OF THE FLOATING POINT NUMBER REPRESENTATIONS.
+
+	THREE STRUCTURES ARE DEFINED:
+		SINGLE:	single precision floating format
+		DOUBLE:	double precision floating format
+		EXTEND:	double precision extended format
+*/
+/********************************************************/
+
+#ifndef __FPTYPES
+#define __FPTYPES
+
+typedef	struct	{
+	unsigned long	h_32;	/* higher 32 bits of 64 */
+	unsigned long	l_32;	/* lower  32 bits of 64 */
+}	B64;
+
+typedef	unsigned long	SINGLE;
+
+typedef	struct	{
+	unsigned long	d[2];
+}	DOUBLE;
+
+typedef	struct	{	/* expanded float format	*/
+	short	sign;
+	short	exp;
+	B64	mantissa;
+#define m1 mantissa.h_32
+#define m2 mantissa.l_32
+} EXTEND;
+
+struct	fef4_returns {
+	int	e;
+	SINGLE	f;
+};
+
+struct	fef8_returns {
+	int	e;
+	DOUBLE	f;
+};
+
+struct fif4_returns {
+	SINGLE ipart;
+	SINGLE fpart;
+};
+
+struct fif8_returns {
+	DOUBLE ipart;
+	DOUBLE fpart;
+};
+
+#if __STDC__
+#define _PROTOTYPE(function, params)	function params
+#else
+#define _PROTOTYPE(function, params)	function()
+#endif
+_PROTOTYPE( void add_ext, (EXTEND *e1, EXTEND *e2));
+_PROTOTYPE( void mul_ext, (EXTEND *e1, EXTEND *e2));
+_PROTOTYPE( void div_ext, (EXTEND *e1, EXTEND *e2));
+_PROTOTYPE( void sub_ext, (EXTEND *e1, EXTEND *e2));
+_PROTOTYPE( void sft_ext, (EXTEND *e1, EXTEND *e2));
+_PROTOTYPE( void nrm_ext, (EXTEND *e1));
+_PROTOTYPE( void zrf_ext, (EXTEND *e1));
+_PROTOTYPE( void extend, (unsigned long *from, EXTEND *to, int size));
+_PROTOTYPE( void compact, (EXTEND *from, unsigned long *to, int size));
+_PROTOTYPE( void _fptrp, (int));
+_PROTOTYPE( void adf4, (SINGLE s2, SINGLE s1));
+_PROTOTYPE( void adf8, (DOUBLE s2, DOUBLE s1));
+_PROTOTYPE( void sbf4, (SINGLE s2, SINGLE s1));
+_PROTOTYPE( void sbf8, (DOUBLE s2, DOUBLE s1));
+_PROTOTYPE( void dvf4, (SINGLE s2, SINGLE s1));
+_PROTOTYPE( void dvf8, (DOUBLE s2, DOUBLE s1));
+_PROTOTYPE( void mlf4, (SINGLE s2, SINGLE s1));
+_PROTOTYPE( void mlf8, (DOUBLE s2, DOUBLE s1));
+_PROTOTYPE( void ngf4, (SINGLE f));
+_PROTOTYPE( void ngf8, (DOUBLE f));
+_PROTOTYPE( void zrf4, (SINGLE *l));
+_PROTOTYPE( void zrf8, (DOUBLE *z));
+_PROTOTYPE( void cff4, (DOUBLE src));
+_PROTOTYPE( void cff8, (SINGLE src));
+_PROTOTYPE( void cif4, (int ss, long src));
+_PROTOTYPE( void cif8, (int ss, long src));
+_PROTOTYPE( void cuf4, (int ss, long src));
+_PROTOTYPE( void cuf8, (int ss, long src));
+_PROTOTYPE( long cfu, (int ds, int ss, DOUBLE src));
+_PROTOTYPE( long cfi, (int ds, int ss, DOUBLE src));
+_PROTOTYPE( int cmf4, (SINGLE s2, SINGLE s1));
+_PROTOTYPE( int cmf8, (DOUBLE d1, DOUBLE d2));
+_PROTOTYPE( void fef4, (struct fef4_returns *r, SINGLE s1));
+_PROTOTYPE( void fef8, (struct fef8_returns *r, DOUBLE s1));
+_PROTOTYPE( void fif4, (struct fif4_returns *p, SINGLE x, SINGLE y));
+_PROTOTYPE( void fif8, (struct fif8_returns *p, DOUBLE x, DOUBLE y));
+
+_PROTOTYPE( void b64_sft, (B64 *, int));
+_PROTOTYPE( void b64_lsft, (B64 *));
+_PROTOTYPE( void b64_rsft, (B64 *));
+_PROTOTYPE( int b64_add, (B64 *, B64 *));
+#endif
Index: /trunk/minix/lib/float/add_ext.c
===================================================================
--- /trunk/minix/lib/float/add_ext.c	(revision 9)
+++ /trunk/minix/lib/float/add_ext.c	(revision 9)
@@ -0,0 +1,56 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/add_ext.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	ADD TWO EXTENDED FORMAT NUMBERS
+*/
+
+#include "FP_types.h"
+
+void
+add_ext(e1,e2)
+register EXTEND	*e1,*e2;
+{
+	if ((e2->m1 | e2->m2) == 0L) {
+		return;
+	}
+	if ((e1->m1 | e1->m2) == 0L) {
+		*e1 = *e2;
+		return;
+	}
+	sft_ext(e1, e2);	/* adjust mantissas to equal powers */
+	if (e1->sign != e2->sign) {
+		/* e1 + e2 = e1 - (-e2) */
+		if (e2->m1 > e1->m1 ||
+                    (e2->m1 == e1->m1 && e2->m2 > e1->m2)) {
+                	/*      abs(e2) > abs(e1) */
+			EXTEND x;
+
+			x = *e1;
+			*e1 = *e2;
+                	if (x.m2 > e1->m2) {
+                        	e1->m1 -= 1;    /* carry in */
+                	}
+                	e1->m1 -= x.m1;
+                	e1->m2 -= x.m2;
+        	}
+        	else {
+                	if (e2->m2 > e1->m2)
+                        	e1->m1 -= 1;    /* carry in */
+                	e1->m1 -= e2->m1;
+                	e1->m2 -= e2->m2;
+        	}
+	}
+	else {
+		if (b64_add(&e1->mantissa,&e2->mantissa)) {	/* addition carry */
+			b64_rsft(&e1->mantissa);	/* shift mantissa one bit RIGHT */
+			e1->m1 |= 0x80000000L;	/* set max bit	*/
+			e1->exp++;		/* increase the exponent */
+		}
+	}
+	nrm_ext(e1);
+}
Index: /trunk/minix/lib/float/adder.c
===================================================================
--- /trunk/minix/lib/float/adder.c	(revision 9)
+++ /trunk/minix/lib/float/adder.c	(revision 9)
@@ -0,0 +1,50 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/adder.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+ *	these are the routines the routines to do 32 and  64-bit addition
+ */
+
+# ifdef	EXT_DEBUG
+# include <stdio.h>
+# endif
+
+# include "FP_types.h"
+# define	UNKNOWN -1
+# define	TRUE	 1
+# define	FALSE	 0
+# define	MAXBIT	0x80000000L
+
+	/*
+	 *	add 64 bits
+	 */
+int
+b64_add(e1,e2)
+		/*
+		 * pointers to 64 bit 'registers'
+		 */
+register	B64	*e1,*e2;
+{
+		register	int	overflow;
+				int	carry;
+
+			/* add higher pair of 32 bits */
+	overflow = ((unsigned long) 0xFFFFFFFF - e1->h_32 < e2->h_32);
+	e1->h_32 += e2->h_32;
+
+			/* add lower pair of 32 bits */
+	carry = ((unsigned long) 0xFFFFFFFF - e1->l_32 < e2->l_32);
+	e1->l_32 += e2->l_32;
+# ifdef	EXT_DEBUG
+	printf("\t\t\t\t\tb64_add: overflow (%d); internal carry(%d)\n",
+					overflow,carry);
+	fflush(stdout);
+# endif
+	if ((carry) && (++e1->h_32 == 0))
+		return(TRUE);		/* had a 64 bit overflow */
+	return(overflow);		/* return status from higher add */
+}
Index: /trunk/minix/lib/float/adder.h
===================================================================
--- /trunk/minix/lib/float/adder.h	(revision 9)
+++ /trunk/minix/lib/float/adder.h	(revision 9)
@@ -0,0 +1,15 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/adder.h,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+ *	include file for 32 & 64 bit addition
+ */
+
+typedef	struct	B64 {
+	unsigned long	h_32;	/* higher 32 bits of 64 */
+	unsigned long	l_32;	/* lower  32 bits of 64 */
+}	B64;
Index: /trunk/minix/lib/float/adf4.c
===================================================================
--- /trunk/minix/lib/float/adf4.c	(revision 9)
+++ /trunk/minix/lib/float/adf4.c	(revision 9)
@@ -0,0 +1,32 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/adf4.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	ADD TWO FLOATS - SINGLE (ADF 4)
+*/
+
+#include	"FP_types.h"
+
+void
+adf4(s2,s1)
+SINGLE	s1,s2;
+{
+	EXTEND	e1,e2;
+	int	swap = 0;
+
+	if (s1 == (SINGLE) 0) {
+		s1 = s2;
+		return;
+	}
+	if (s2 == (SINGLE) 0) {
+		return;
+	}
+	extend(&s1,&e1,sizeof(SINGLE));
+	extend(&s2,&e2,sizeof(SINGLE));
+	add_ext(&e1,&e2);
+	compact(&e1,&s1,sizeof(SINGLE));
+}
Index: /trunk/minix/lib/float/adf8.c
===================================================================
--- /trunk/minix/lib/float/adf8.c	(revision 9)
+++ /trunk/minix/lib/float/adf8.c	(revision 9)
@@ -0,0 +1,32 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/adf8.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	ADD TWO FLOATS - DOUBLE (ADF 8)
+*/
+
+#include	"FP_types.h"
+
+void
+adf8(s2,s1)
+DOUBLE	s1,s2;
+{
+	EXTEND	e1,e2;
+
+	if (s1.d[0] == 0 && s1.d[1] == 0) {
+		s1 = s2;
+		return;
+	}
+	if (s2.d[0] == 0 && s2.d[1] == 0) {
+		return;
+	}
+
+	extend(&s1.d[0],&e1,sizeof(DOUBLE));
+	extend(&s2.d[0],&e2,sizeof(DOUBLE));
+	add_ext(&e1,&e2);
+	compact(&e1,&s1.d[0],sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/float/byte_order.h
===================================================================
--- /trunk/minix/lib/float/byte_order.h	(revision 9)
+++ /trunk/minix/lib/float/byte_order.h	(revision 9)
@@ -0,0 +1,6 @@
+#define CHAR_UNSIGNED	0
+#define MSB_AT_LOW_ADDRESS	0
+#define MSW_AT_LOW_ADDRESS	0
+#define FL_MSB_AT_LOW_ADDRESS	0
+#define FL_MSW_AT_LOW_ADDRESS	0
+#define FL_MSL_AT_LOW_ADDRESS	0
Index: /trunk/minix/lib/float/cff4.c
===================================================================
--- /trunk/minix/lib/float/cff4.c	(revision 9)
+++ /trunk/minix/lib/float/cff4.c	(revision 9)
@@ -0,0 +1,28 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/cff4.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+		CONVERT DOUBLE TO SINGLE (CFF 8 4)
+
+	This routine works quite simply. A floating point
+	of size 08 is converted to extended format.
+	This extended variable is converted back to
+	a floating point of size 04.
+
+*/
+
+#include	"FP_types.h"
+
+void
+cff4(src)
+DOUBLE	src;	/* the source itself -	THIS TIME it's DOUBLE */
+{
+	EXTEND	buf;
+
+	extend(&src.d[0],&buf,sizeof(DOUBLE));	/* no matter what */
+	compact(&buf,&(src.d[1]),sizeof(SINGLE));
+}
Index: /trunk/minix/lib/float/cff8.c
===================================================================
--- /trunk/minix/lib/float/cff8.c	(revision 9)
+++ /trunk/minix/lib/float/cff8.c	(revision 9)
@@ -0,0 +1,28 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/cff8.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+		CONVERT SINGLE TO DOUBLE (CFF 4 8)
+
+	This routine works quite simply. A floating point
+	of size 04 is converted to extended format.
+	This extended variable is converted back to
+	a floating point of size 08.
+
+*/
+
+#include "FP_types.h"
+
+void
+cff8(src)
+SINGLE	src;
+{
+	EXTEND	buf;
+
+	extend(&src,&buf,sizeof(SINGLE));	/* no matter what */
+	compact(&buf, &src,sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/float/cfi.c
===================================================================
--- /trunk/minix/lib/float/cfi.c	(revision 9)
+++ /trunk/minix/lib/float/cfi.c	(revision 9)
@@ -0,0 +1,52 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/cfi.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+		CONVERT FLOAT TO SIGNED (CFI m n)
+
+		N.B. The caller must know what it is getting.
+		     A LONG is always returned. If it is an
+		     integer the high byte is cleared first.
+*/
+
+#include "FP_trap.h"
+#include "FP_types.h"
+#include "FP_shift.h"
+
+long
+cfi(ds,ss,src)
+int	ds;	/* destination size (2 or 4) */
+int	ss;	/* source size	    (4 or 8) */
+DOUBLE	src;	/* assume worst case */
+{
+	EXTEND	buf;
+	long	new;
+	short	max_exp;
+
+	extend(&src.d[0],&buf,ss);	/* get extended format */
+	if (buf.exp < 0) {	/* no conversion needed */
+		src.d[ss == 8] = 0L;
+		return(0L);
+	}
+	max_exp = (ds << 3) - 2;	/* signed numbers */
+				/* have more limited max_exp */
+	if (buf.exp > max_exp) {
+		if (buf.exp == max_exp+1 && buf.sign && buf.m1 == NORMBIT &&
+		    buf.m2 == 0L) {
+		}
+		else {
+			trap(EIOVFL);	/* integer overflow	*/
+			buf.exp %= max_exp; /* truncate	*/
+		}
+	}
+	new = buf.m1 >> (31-buf.exp);
+	if (buf.sign)
+		new = -new;
+done:
+	src.d[ss == 8] = new;
+	return(new);
+}
Index: /trunk/minix/lib/float/cfu.c
===================================================================
--- /trunk/minix/lib/float/cfu.c	(revision 9)
+++ /trunk/minix/lib/float/cfu.c	(revision 9)
@@ -0,0 +1,43 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/cfu.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+		CONVERT FLOAT TO UNSIGNED (CFU m n)
+
+		N.B. The caller must know what it is getting.
+		     A LONG is always returned. If it is an
+		     integer the high byte is cleared first.
+*/
+
+#include "FP_trap.h"
+#include "FP_types.h"
+
+long
+cfu(ds,ss,src)
+int	ds;	/* destination size (2 or 4) */
+int	ss;	/* source size	    (4 or 8) */
+DOUBLE	src;	/* assume worst case */
+{
+	EXTEND	buf;
+	long	new;
+	short	newint, max_exp;
+
+	extend(&src.d[0],&buf,ss);	/* get extended format	*/
+	if (buf.exp < 0) {	/* no conversion needed	*/
+		src.d[ss == 8] = 0L;
+		return(0L);
+	}
+	max_exp = (ds << 3) - 1;
+	if (buf.exp > max_exp) {
+		trap(EIOVFL);	/* integer overflow	*/
+		buf.exp %= max_exp;
+	}
+	new = buf.m1 >> (31-buf.exp);
+done:
+	src.d[ss == 8] = new;
+	return(new);
+}
Index: /trunk/minix/lib/float/cif4.c
===================================================================
--- /trunk/minix/lib/float/cif4.c	(revision 9)
+++ /trunk/minix/lib/float/cif4.c	(revision 9)
@@ -0,0 +1,56 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/cif4.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	CONVERT INTEGER TO SINGLE (CIF n 4)
+
+	THIS ROUTINE WORKS BY FILLING AN EXTENDED
+	WITH THE INTEGER VALUE IN EXTENDED FORMAT
+	AND USES COMPACT() TO PUT IT INTO THE PROPER
+	FLOATING POINT PRECISION.
+*/
+
+#include "FP_types.h"
+
+void
+cif4(ss,src)
+int	ss;	/* source size */
+long	src;	/* largest possible integer to convert */
+{
+	EXTEND	buf;
+	short	*ipt;
+	long	i_src;
+	SINGLE	*result;
+
+	zrf_ext(&buf);
+	if (ss == sizeof(long))	{
+		buf.exp = 31;
+		i_src = src;
+		result = (SINGLE *) &src;
+	}
+	else	{
+		ipt = (short *) &src;
+		i_src = (long) *ipt;
+		buf.exp = 15;
+		result = (SINGLE *) &ss;
+	}
+	if (i_src == 0)	{
+		*result = (SINGLE) 0L;
+		return;
+	}
+			/* ESTABLISHED THAT src != 0	*/
+			/* adjust exponent field	*/
+	buf.sign = (i_src < 0) ? 0x8000 : 0;
+			/* clear sign bit of integer	*/
+			/* move to mantissa field	*/
+	buf.m1 = (i_src < 0) ? -i_src : i_src;
+			/* adjust mantissa field	*/
+	if (ss != sizeof(long))
+		buf.m1 <<= 16;
+	nrm_ext(&buf);		/* adjust mantissa field	*/
+	compact(&buf, result,sizeof(SINGLE));	/* put on stack */
+}
Index: /trunk/minix/lib/float/cif8.c
===================================================================
--- /trunk/minix/lib/float/cif8.c	(revision 9)
+++ /trunk/minix/lib/float/cif8.c	(revision 9)
@@ -0,0 +1,55 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/cif8.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	CONVERT INTEGER TO FLOAT (CIF n 8)
+
+	THIS ROUTINE WORKS BY FILLING AN EXTENDED
+	WITH THE INTEGER VALUE IN EXTENDED FORMAT
+	AND USES COMPACT() TO PUT IT INTO THE PROPER
+	FLOATING POINT PRECISION.
+*/
+
+#include "FP_types.h"
+
+void
+cif8(ss,src)
+int	ss;	/* source size */
+long	src;	/* largest possible integer to convert */
+{
+	EXTEND	buf;
+	DOUBLE	*result;	/* for return value */
+	short	*ipt;
+	long	i_src;
+
+	result = (DOUBLE *) ((void *) &ss);	/* always */
+	zrf_ext(&buf);
+	if (ss == sizeof(long))	{
+		buf.exp = 31;
+		i_src = src;
+	}
+	else	{
+		ipt = (short *) &src;
+		i_src = (long) *ipt;
+		buf.exp = 15;
+	}
+	if (i_src == 0)	{
+		zrf8(result);
+		return;
+	}
+			/* ESTABLISHED THAT src != 0	*/
+			/* adjust exponent field	*/
+	buf.sign = (i_src < 0) ? 0x8000 : 0;
+			/* clear sign bit of integer	*/
+			/* move to mantissa field	*/
+	buf.m1 = (i_src < 0) ? -i_src : i_src;
+			/* adjust mantissa field	*/
+	if (ss != sizeof(long))
+		buf.m1 <<= 16;
+	nrm_ext(&buf);
+	compact(&buf,&result->d[0],8);
+}
Index: /trunk/minix/lib/float/cmf4.c
===================================================================
--- /trunk/minix/lib/float/cmf4.c	(revision 9)
+++ /trunk/minix/lib/float/cmf4.c	(revision 9)
@@ -0,0 +1,40 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/cmf4.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	COMPARE	SINGLES (CMF 4)
+*/
+
+#include	"FP_types.h"
+#include	"get_put.h"
+
+int
+cmf4(f1,f2)
+SINGLE	f1,f2;
+{
+		/*
+		 * return ((f1 < f2) ? 1 : (f1 - f2))
+		 */
+#define SIGN(x) (((x) < 0) ? -1 : 1)
+        int	sign1,sign2;
+	long	l1,l2;
+
+	l1 = get4((char *) &f1);
+	l2 = get4((char *) &f2);
+
+	if (l1 == l2) return 0;
+
+        sign1 = SIGN(l1);
+        sign2 = SIGN(l2);
+        if (sign1 != sign2) {
+		if ((l1 & 0x7fffffff) == 0 &&
+		    (l2 & 0x7fffffff) == 0) return 0;
+                return ((sign1 > 0) ? -1 : 1);
+	}
+
+	return (sign1 * ((l1 < l2) ? 1 : -1));
+}
Index: /trunk/minix/lib/float/cmf8.c
===================================================================
--- /trunk/minix/lib/float/cmf8.c	(revision 9)
+++ /trunk/minix/lib/float/cmf8.c	(revision 9)
@@ -0,0 +1,61 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/cmf8.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	COMPARE	DOUBLES (CMF 8)
+*/
+
+#include	"FP_types.h"
+#include	"get_put.h"
+
+int
+cmf8(d1,d2)
+DOUBLE	d1,d2;
+{
+#define	SIGN(x)	(((x) < 0) ? -1 : 1)
+		/*
+		 * return ((d1 < d2) ? 1 : (d1 > d2) ? -1 : 0))
+		 */
+	long	l1,l2;
+	int	sign1,sign2;
+	int	rv;
+
+#if FL_MSL_AT_LOW_ADDRESS
+	l1 = get4((char *)&d1);
+	l2 = get4((char *)&d2);
+#else
+	l1 = get4(((char *)&d1+4));
+	l2 = get4(((char *)&d2+4));
+#endif
+	sign1 = SIGN(l1);
+	sign2 = SIGN(l2);
+	if (sign1 != sign2) {
+		l1 &= 0x7fffffff;
+		l2 &= 0x7fffffff;
+		if (l1 != 0 || l2 != 0) {
+			return ((sign1 > 0) ? -1 : 1);
+		}
+	}
+	if (l1 != l2)	{	/* we can decide here */
+		rv = l1 < l2 ? 1 : -1;
+	}
+	else	{ 		/* decide in 2nd half */
+		unsigned long u1, u2;
+#if FL_MSL_AT_LOW_ADDRESS
+		u1 = get4(((char *)&d1 + 4));
+		u2 = get4(((char *)&d2 + 4));
+#else
+		u1 = get4((char *)&d1);
+		u2 = get4((char *)&d2);
+#endif
+		if (u1 == u2)
+			return(0);
+		if (u1 < u2) rv = 1;
+		else rv = -1;
+	}
+	return sign1 * rv;
+}
Index: /trunk/minix/lib/float/compact.c
===================================================================
--- /trunk/minix/lib/float/compact.c	(revision 9)
+++ /trunk/minix/lib/float/compact.c	(revision 9)
@@ -0,0 +1,202 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/compact.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	COMPACT EXTEND FORMAT INTO FLOAT OF PROPER SIZE
+*/
+
+# include "FP_bias.h"
+# include "FP_shift.h"
+# include "FP_trap.h"
+# include "FP_types.h"
+# include "get_put.h"
+
+void
+compact(f,to,size)
+EXTEND	*f;
+unsigned long	*to;
+int	size;
+{
+	int	error = 0;
+
+	if (size == sizeof(DOUBLE)) {
+	/*
+	 * COMPACT EXTENDED INTO DOUBLE
+	 */
+		DOUBLE *DBL = (DOUBLE *) (void *) to;
+
+		if ((f->m1|(f->m2 & DBL_ZERO)) == 0L)	{
+			zrf8(DBL);
+			return;
+		}
+		f->exp += DBL_BIAS;	/* restore proper bias	*/
+		if (f->exp > DBL_MAX)	{
+dbl_over:			trap(EFOVFL);
+			f->exp = DBL_MAX+1;
+			f->m1 = 0;
+			f->m2 = 0;
+			if (error++)
+				return;
+		}
+		else if (f->exp < DBL_MIN)	{
+			b64_rsft(&(f->mantissa));
+			if (f->exp < 0) {
+				b64_sft(&(f->mantissa), -f->exp);
+				f->exp = 0;
+			}
+			/* underflow ??? */
+		}
+			
+		/* local CAST conversion		*/
+
+		/* because of special format shift only 10 bits */
+		/* bit shift mantissa 10 bits		*/
+
+		/* first align within words, then do store operation */
+
+		DBL->d[0] = f->m1 >> DBL_RUNPACK;   /* plus 22 == 32 */
+		DBL->d[1] = f->m2 >> DBL_RUNPACK;   /* plus 22 == 32 */
+		DBL->d[1] |= (f->m1 << DBL_LUNPACK); /* plus 10 == 32 */
+
+		/* if not exact then round to nearest	*/
+		/* on a tie, round to even */
+
+#ifdef EXCEPTION_INEXACT
+		if ((f->m2 & DBL_EXACT) != 0) {
+		    INEXACT();
+#endif
+		    if (((f->m2 & DBL_EXACT) > DBL_ROUNDUP)
+			|| ((f->m2 & DBL_EXACT) == DBL_ROUNDUP
+			    && (f->m2 & (DBL_ROUNDUP << 1)))) {
+			DBL->d[1]++;	/* rounding up	*/
+			if (DBL->d[1] == 0L) { /* carry out	*/
+			    DBL->d[0]++;
+
+			    if (f->exp == 0 && (DBL->d[0] & ~DBL_MASK)) {
+					f->exp++;
+				}
+			    if (DBL->d[0] & DBL_CARRYOUT) { /* carry out */
+				if (DBL->d[0] & 01)
+				    DBL->d[1] = CARRYBIT;
+				DBL->d[0] >>= 1;
+				f->exp++;
+			    }
+			}
+			/*	check for overflow			*/
+			if (f->exp > DBL_MAX)
+		    		goto dbl_over;
+		    }
+#ifdef EXCEPTION_INEXACT
+		}
+#endif
+
+		/*
+		 * STORE EXPONENT AND SIGN:
+		 *
+		 * 1) clear leading bits (B4-B15)
+		 * 2) shift and store exponent
+		 */
+
+		DBL->d[0] &= DBL_MASK;
+		DBL->d[0] |= 
+			((long) (f->exp << DBL_EXPSHIFT) << EXP_STORE);
+		if (f->sign)
+			DBL->d[0] |= CARRYBIT;
+
+		/*
+		 * STORE MANTISSA
+		 */
+
+#if FL_MSL_AT_LOW_ADDRESS
+		put4(DBL->d[0], (char *) &DBL->d[0]);
+		put4(DBL->d[1], (char *) &DBL->d[1]);
+#else
+		{ unsigned long l;
+		  put4(DBL->d[1], (char *) &l);
+		  put4(DBL->d[0], (char *) &DBL->d[1]);
+		  DBL->d[0] = l;
+		}
+#endif
+	}
+	else {
+		/*
+		 * COMPACT EXTENDED INTO FLOAT
+		 */
+		SINGLE	*SGL;
+
+		/* local CAST conversion		*/
+		SGL = (SINGLE *) (void *) to;
+		if ((f->m1 & SGL_ZERO) == 0L)	{
+			*SGL = 0L;
+			return;
+		}
+		f->exp += SGL_BIAS;	/* restore bias	*/
+		if (f->exp > SGL_MAX)	{
+sgl_over:			trap(EFOVFL);
+			f->exp = SGL_MAX+1;
+			f->m1 = 0L;
+			f->m2 = 0L;
+			if (error++)
+				return;
+		}
+		else if (f->exp < SGL_MIN)	{
+			b64_rsft(&(f->mantissa));
+			if (f->exp < 0) {
+				b64_sft(&(f->mantissa), -f->exp);
+				f->exp = 0;
+			}
+			/* underflow ??? */
+		}
+
+		/* shift mantissa and store	*/
+		*SGL = (f->m1 >> SGL_RUNPACK);
+
+		/* check for rounding to nearest	*/
+		/* on a tie, round to even		*/
+#ifdef EXCEPTION_INEXACT
+		if (f->m2 != 0 ||
+		    (f->m1 & SGL_EXACT) != 0L) {
+			INEXACT();
+#endif
+		        if (((f->m1 & SGL_EXACT) > SGL_ROUNDUP)
+			    || ((f->m1 & SGL_EXACT) == SGL_ROUNDUP
+			        && (f->m1 & (SGL_ROUNDUP << 1)))) {
+				(*SGL)++;
+				if (f->exp == 0 && (*SGL & ~SGL_MASK)) {
+					f->exp++;
+				}
+			/* check normal */
+				if (*SGL & SGL_CARRYOUT)	{
+					*SGL >>= 1;
+					f->exp++;
+				}
+				if (f->exp > SGL_MAX)
+					goto sgl_over;
+			}
+#ifdef EXCEPTION_INEXACT
+		}
+#endif
+
+		/*
+		 * STORE EXPONENT AND SIGN:
+		 *
+		 * 1) clear leading bit of fraction
+		 * 2) shift and store exponent
+		 */
+
+		*SGL &= SGL_MASK; /* B23-B31 are 0 */
+		*SGL |= ((long) (f->exp << SGL_EXPSHIFT) << EXP_STORE);
+		if (f->sign)
+			*SGL |= CARRYBIT;
+
+		/*
+		 * STORE MANTISSA
+		 */
+
+		put4(*SGL, (char *) &SGL);
+	}
+}
Index: /trunk/minix/lib/float/cuf4.c
===================================================================
--- /trunk/minix/lib/float/cuf4.c	(revision 9)
+++ /trunk/minix/lib/float/cuf4.c	(revision 9)
@@ -0,0 +1,57 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/cuf4.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	CONVERT INTEGER TO SINGLE (CUF n 4)
+
+	THIS ROUTINE WORKS BY FILLING AN EXTENDED
+	WITH THE INTEGER VALUE IN EXTENDED FORMAT
+	AND USES COMPACT() TO PUT IT INTO THE PROPER
+	FLOATING POINT PRECISION.
+*/
+
+#include "FP_types.h"
+
+void
+cuf4(ss,src)
+int	ss;	/* source size */
+long	src;	/* largest possible integer to convert */
+{
+	EXTEND	buf;
+	short	*ipt;
+	SINGLE	*result;
+	long	i_src;
+
+	zrf_ext(&buf);
+	if (ss == sizeof(long))	{
+		buf.exp = 31;
+		i_src = src;
+		result = (SINGLE *) &src;
+	}
+	else	{
+		ipt = (short *) &src;
+		i_src = (long) *ipt;
+		buf.exp = 15;
+		result = (SINGLE *) ((void *) &ss);
+	}
+	if (i_src == 0)	{
+		*result = (SINGLE) 0L;
+		return;
+	}
+			/* ESTABLISHED THAT src != 0	*/
+
+			/* adjust exponent field	*/
+	if (ss != sizeof(long))
+		i_src <<= 16;
+
+			/* move to mantissa field	*/
+	buf.m1 = i_src;
+
+			/* adjust mantissa field	*/
+	nrm_ext(&buf);
+	compact(&buf,result,4);
+}
Index: /trunk/minix/lib/float/cuf8.c
===================================================================
--- /trunk/minix/lib/float/cuf8.c	(revision 9)
+++ /trunk/minix/lib/float/cuf8.c	(revision 9)
@@ -0,0 +1,54 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/cuf8.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	CONVERT INTEGER TO FLOAT (CUF n 8)
+
+	THIS ROUTINE WORKS BY FILLING AN EXTENDED
+	WITH THE INTEGER VALUE IN EXTENDED FORMAT
+	AND USES COMPACT() TO PUT IT INTO THE PROPER
+	FLOATING POINT PRECISION.
+*/
+
+#include "FP_types.h"
+
+void
+cuf8(ss,src)
+int	ss;	/* source size */
+long	src;	/* largest possible integer to convert */
+{
+	EXTEND	buf;
+	short	*ipt;
+	long	i_src;
+
+	zrf_ext(&buf);
+	if (ss == sizeof(long))	{
+		buf.exp = 31;
+		i_src = src;
+	}
+	else	{
+		ipt = (short *) &src;
+		i_src = (long) *ipt;
+		buf.exp = 15;
+	}
+	if (i_src == 0)	{
+		zrf8((DOUBLE *)((void *)&ss));
+		return;
+	}
+			/* ESTABLISHED THAT src != 0	*/
+
+			/* adjust exponent field	*/
+	if (ss != sizeof(long))
+		i_src <<= 16;
+
+			/* move to mantissa field	*/
+	buf.m1 = i_src;
+
+			/* adjust mantissa field	*/
+	nrm_ext(&buf);
+	compact(&buf,(unsigned long *) (void *)&ss,8);
+}
Index: /trunk/minix/lib/float/div_ext.c
===================================================================
--- /trunk/minix/lib/float/div_ext.c	(revision 9)
+++ /trunk/minix/lib/float/div_ext.c	(revision 9)
@@ -0,0 +1,266 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/div_ext.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	DIVIDE EXTENDED FORMAT
+*/
+
+#include "FP_bias.h"
+#include "FP_trap.h"
+#include "FP_types.h"
+
+/*
+	November 15, 1984
+
+	This is a routine to do the work.
+	There are two versions: 
+	One is based on the partial products method
+	and makes no use possible machine instructions
+	to divide (hardware dividers).
+	The other is used when USE_DIVIDE is defined. It is much faster on
+	machines with fast 4 byte operations.
+*/
+/********************************************************/
+
+void
+div_ext(e1,e2)
+EXTEND	*e1,*e2;
+{
+	short	error = 0;
+	B64		result;
+	register	unsigned long	*lp;
+#ifndef USE_DIVIDE
+	short	count;
+#else
+	unsigned short u[9], v[5];
+	register int j;
+	register unsigned short *u_p = u;
+	int maxv = 4;
+#endif
+
+	if ((e2->m1 | e2->m2) == 0) {
+                /*
+                 * Exception 8.2 - Divide by zero
+                 */
+		trap(EFDIVZ);
+		e1->m1 = e1->m2 = 0L;
+		e1->exp = EXT_MAX;
+		return;
+	}
+	if ((e1->m1 | e1->m2) == 0) {	/* 0 / anything == 0 */
+		e1->exp = 0;	/* make sure */
+		return;
+	}
+#ifndef USE_DIVIDE
+	/*
+	 * numbers are right shifted one bit to make sure
+	 * that m1 is quaranteed to be larger if its
+	 * maximum bit is set
+	 */
+	b64_rsft(&e1->mantissa);	/* 64 bit shift right */
+	b64_rsft(&e2->mantissa);	/* 64 bit shift right */
+	e1->exp++;
+	e2->exp++;
+#endif
+	/*	check for underflow, divide by zero, etc	*/
+	e1->sign ^= e2->sign;
+	e1->exp -= e2->exp;
+
+#ifndef USE_DIVIDE
+		/* do division of mantissas	*/
+		/* uses partial product method	*/
+		/* init control variables	*/
+
+	count = 64;
+	result.h_32 = 0L;
+	result.l_32 = 0L;
+
+		/* partial product division loop */
+
+	while (count--)	{
+		/* first left shift result 1 bit	*/
+		/* this is ALWAYS done			*/
+
+		b64_lsft(&result);
+
+		/* compare dividend and divisor		*/
+		/* if dividend >= divisor add a bit	*/
+		/* and subtract divisior from dividend	*/
+
+		if ( (e1->m1 < e2->m1) ||
+			((e1->m1 == e2->m1) && (e1->m2 < e2->m2) ))
+			;	/* null statement */
+				/* i.e., don't add or subtract */
+		else	{
+			result.l_32++;	/* ADD	*/
+			if (e2->m2 > e1->m2)
+				e1->m1 -= 1;	/* carry in */
+			e1->m1 -= e2->m1;	/* do SUBTRACTION */
+			e1->m2 -= e2->m2;	/*    SUBTRACTION */
+		}
+
+		/*	shift dividend left one bit OR	*/
+		/*	IF it equals ZERO we can break out	*/
+		/*	of the loop, but still must shift	*/
+		/*	the quotient the remaining count bits	*/
+		/* NB	save the results of this test in error	*/
+		/*	if not zero, then the result is inexact. */
+		/* 	this would be reported in IEEE standard	*/
+
+		/*	lp points to dividend			*/
+		lp = &e1->m1;
+
+		error = ((*lp | *(lp+1)) != 0L) ? 1 : 0;
+		if (error)	{	/* more work */
+			/*	assume max bit == 0 (see above)	*/
+			b64_lsft(&e1->mantissa);
+			continue;
+		}
+		else
+			break;	/* leave loop	*/
+	}	/* end of divide by subtraction loop	*/
+
+	if (count > 0)	{
+		lp = &result.h_32;
+		if (count > 31) {	/* move to higher word */
+			*lp = *(lp+1);
+			count -= 32;
+			*(lp+1) = 0L;	/* clear low word	*/
+		}
+		if (*lp)
+			*lp <<= count;	/* shift rest of way	*/
+		lp++;	/*  == &result.l_32	*/
+		if (*lp) {
+			result.h_32 |= (*lp >> 32-count);
+			*lp <<= count;
+		}
+	}
+#else /* USE_DIVIDE */
+
+	u[4] = (e1->m2 & 1) << 15;
+	b64_rsft(&(e1->mantissa));
+	u[0] = e1->m1 >> 16;
+	u[1] = e1->m1;
+	u[2] = e1->m2 >> 16;
+	u[3] = e1->m2;
+	u[5] = 0; u[6] = 0; u[7] = 0;
+	v[1] = e2->m1 >> 16;
+	v[2] = e2->m1;
+	v[3] = e2->m2 >> 16;
+	v[4] = e2->m2;
+	while (! v[maxv]) maxv--;
+	result.h_32 = 0;
+	result.l_32 = 0;
+	lp = &result.h_32;
+
+	/*
+	 * Use an algorithm of Knuth (The art of programming, Seminumerical
+	 * algorithms), to divide u by v. u and v are both seen as numbers
+	 * with base 65536. 
+	 */
+	for (j = 0; j <= 3; j++, u_p++) {
+		unsigned long q_est, temp;
+
+		if (j == 2) lp++;
+		if (u_p[0] == 0 && u_p[1] < v[1]) continue;
+		temp = ((unsigned long)u_p[0] << 16) + u_p[1];
+		if (u_p[0] >= v[1]) {
+			q_est = 0x0000FFFFL;
+		}
+		else {
+			q_est = temp / v[1];
+		}
+		temp -= q_est * v[1];
+		while (temp < 0x10000 && v[2]*q_est > ((temp<<16)+u_p[2])) {
+			q_est--;
+			temp += v[1];
+		}
+		/*	Now, according to Knuth, we have an estimate of the
+			quotient, that is either correct or one too big, but
+			almost always correct.
+		*/
+		if (q_est != 0)  {
+			int i;
+			unsigned long k = 0;
+			int borrow = 0;
+
+			for (i = maxv; i > 0; i--) {
+				unsigned long tmp = q_est * v[i] + k + borrow;
+				unsigned short md = tmp;
+
+				borrow = (md > u_p[i]);
+				u_p[i] -= md;
+				k = tmp >> 16;
+			}
+			k += borrow;
+			borrow = u_p[0] < k;
+			u_p[0] -= k;
+
+			if (borrow) {
+				/* So, this does not happen often; the estimate
+				   was one too big; correct this
+				*/
+				*lp |= (j & 1) ? (q_est - 1) : ((q_est-1)<<16);
+				borrow = 0;
+				for (i = maxv; i > 0; i--) {
+					unsigned long tmp 
+					    = v[i]+(unsigned long)u_p[i]+borrow;
+					
+					u_p[i] = tmp;
+					borrow = tmp >> 16;
+				}
+				u_p[0] += borrow;
+			}
+			else *lp |= (j & 1) ? q_est : (q_est<<16);
+		}
+	}
+#ifdef	EXCEPTION_INEXACT
+	u_p = &u[0];
+	for (j = 7; j >= 0; j--) {
+		if (*u_p++) {
+			error = 1;
+			break;
+		}
+	}
+#endif
+#endif
+
+#ifdef  EXCEPTION_INEXACT
+        if (error)      {
+                /*
+                 * report here exception 8.5 - Inexact
+                 * from Draft 8.0 of IEEE P754:
+                 * In the absence of an invalid operation exception,
+                 * if the rounded result of an operation is not exact or if
+                 * it overflows without a trap, then the inexact exception
+                 * shall be assigned. The rounded or overflowed result
+                 * shall be delivered to the destination.
+                 */
+                INEXACT();
+#endif
+	e1->mantissa = result;
+
+	nrm_ext(e1);
+	if (e1->exp < EXT_MIN)	{
+		/*
+		 * Exception 8.4 - Underflow
+		 */
+		trap(EFUNFL);	/* underflow */
+		e1->exp = EXT_MIN;
+		e1->m1 = e1->m2 = 0L;
+		return;
+	}
+	if (e1->exp >= EXT_MAX) {
+                /*
+                 * Exception 8.3 - Overflow
+                 */
+                trap(EFOVFL);   /* overflow */
+                e1->exp = EXT_MAX;
+                e1->m1 = e1->m2 = 0L;
+                return;
+        }
+}
Index: /trunk/minix/lib/float/dvf4.c
===================================================================
--- /trunk/minix/lib/float/dvf4.c	(revision 9)
+++ /trunk/minix/lib/float/dvf4.c	(revision 9)
@@ -0,0 +1,26 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/dvf4.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	DIVIDE TWO SINGLES - SINGLE Precision (dvf 4)
+*/
+
+#include	"FP_types.h"
+
+void
+dvf4(s2,s1)
+SINGLE	s1,s2;
+{
+	EXTEND	e1,e2;
+
+	extend(&s1,&e1,sizeof(SINGLE));
+	extend(&s2,&e2,sizeof(SINGLE));
+
+		/* do a divide */
+	div_ext(&e1,&e2);
+	compact(&e1,&s1,sizeof(SINGLE));
+}
Index: /trunk/minix/lib/float/dvf8.c
===================================================================
--- /trunk/minix/lib/float/dvf8.c	(revision 9)
+++ /trunk/minix/lib/float/dvf8.c	(revision 9)
@@ -0,0 +1,26 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/dvf8.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	DIVIDE TWO FLOATS - DOUBLE Precision (DVF 8)
+*/
+
+#include	"FP_types.h"
+
+void
+dvf8(s2,s1)
+DOUBLE	s1,s2;
+{
+	EXTEND	e1,e2;
+
+	extend(&s1.d[0],&e1,sizeof(DOUBLE));
+	extend(&s2.d[0],&e2,sizeof(DOUBLE));
+
+		/* do a divide */
+	div_ext(&e1,&e2);
+	compact(&e1,&s1.d[0],sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/float/extend.c
===================================================================
--- /trunk/minix/lib/float/extend.c	(revision 9)
+++ /trunk/minix/lib/float/extend.c	(revision 9)
@@ -0,0 +1,111 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/extend.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	CONVERTS FLOATING POINT TO EXTENDED FORMAT
+
+	Two sizes of FLOATING Point are known:
+		SINGLE and DOUBLE
+*/
+/********************************************************/
+/*
+	It is not required to normalize in extended
+	format, but it has been chosen to do so.
+	Extended Format is as follows (at exit):
+
+->sign	S000 0000 | 0000 0000		<SIGN>
+->exp	0EEE EEEE | EEEE EEEE		<EXPONENT>
+->m1	LFFF FFFF | FFFF FFFF		<L.Fraction>
+	FFFF FFFF | FFFF FFFF		<Fraction>
+->m2	FFFF FFFF | FFFF FFFF		<Fraction>
+	FFFF F000 | 0000 0000		<Fraction>
+*/
+/********************************************************/
+
+#include "FP_bias.h"
+#include "FP_shift.h"
+#include "FP_types.h"
+#include "get_put.h"
+/********************************************************/
+
+void
+extend(from,to,size)
+unsigned long	*from;
+EXTEND	*to;
+int	size;
+{
+	register char *cpt1;
+	unsigned long	tmp;
+	int	leadbit = 0;
+
+	cpt1 = (char *) from;
+
+#if FL_MSL_AT_LOW_ADDRESS
+#if FL_MSW_AT_LOW_ADDRESS
+	to->exp = uget2(cpt1);
+#else
+	to->exp = uget2(cpt1+2);
+#endif
+#else
+#if FL_MSW_AT_LOW_ADDRESS
+	to->exp = uget2(cpt1+(size == sizeof(DOUBLE) ? 4 : 0));
+#else
+	to->exp = uget2(cpt1+(size == sizeof(DOUBLE) ? 6 : 2));
+#endif
+#endif
+	to->sign = (to->exp & 0x8000);	/* set sign bit */
+	to->exp ^= to->sign;
+	if (size == sizeof(DOUBLE))
+		to->exp >>= DBL_EXPSHIFT;
+	else
+		to->exp >>= SGL_EXPSHIFT;
+	if (to->exp > 0)
+		leadbit++;	/* will set Lead bit later	*/
+	else to->exp++;
+
+	if (size == sizeof(DOUBLE))	{
+#if FL_MSL_AT_LOW_ADDRESS
+		to->m1 = get4(cpt1);
+		cpt1 += 4;
+		tmp = get4(cpt1);
+#else
+		tmp = get4(cpt1);
+		cpt1 += 4;
+		to->m1 = get4(cpt1);
+#endif
+		if (to->exp == 1 && to->m1 == 0 && tmp == 0) {
+			to->exp = 0;
+			to->sign = 0;
+			to->m1 = 0;
+			to->m2 = 0;
+			return;
+		}
+		to->m1 <<= DBL_M1LEFT;		/* shift	*/
+		to->exp -= DBL_BIAS;		/* remove bias	*/
+		to->m1 |= (tmp>>DBL_RPACK);	/* plus 10 == 32	*/
+		to->m2 = (tmp<<DBL_LPACK);	/* plus 22 == 32	*/
+	}
+	else	{	/* size == sizeof(SINGLE)		*/
+		to->m1 = get4(cpt1);
+		to->m1  <<= SGL_M1LEFT;	/* shift	*/
+		if (to->exp == 1 && to->m1 == 0) {
+			to->exp = 0;
+			to->sign = 0;
+			to->m1 = 0;
+			to->m2 = 0;
+			return;
+		}
+		to->exp -= SGL_BIAS;		/* remove bias	*/
+		to->m2 = 0L;
+	}
+
+	to->m1 |= NORMBIT;				/* set bit L	*/
+	if (leadbit == 0) {		/* set or clear Leading Bit	*/
+		to->m1 &= ~NORMBIT;			/* clear bit L	*/
+		nrm_ext(to);				/* and normalize */
+	}
+}
Index: /trunk/minix/lib/float/fef4.c
===================================================================
--- /trunk/minix/lib/float/fef4.c	(revision 9)
+++ /trunk/minix/lib/float/fef4.c	(revision 9)
@@ -0,0 +1,33 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/fef4.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
+
+/*
+	SEPERATE INTO EXPONENT AND FRACTION (FEF 4)
+*/
+
+#include	"FP_types.h"
+
+void
+fef4(r,s1)
+SINGLE	s1;
+struct fef4_returns	*r;
+{
+	EXTEND	buf;
+	register struct fef4_returns	*p = r;	/* make copy; r might refer
+						   to itself (see table)
+						*/
+
+	extend(&s1,&buf,sizeof(SINGLE));
+	if (buf.exp == 0 && buf.m1 == 0 && buf.m2 == 0) {
+		p->e = 0;
+	}
+	else {
+		p->e = buf.exp+1;
+		buf.exp = -1;
+	}
+	compact(&buf,&p->f,sizeof(SINGLE));
+}
Index: /trunk/minix/lib/float/fef8.c
===================================================================
--- /trunk/minix/lib/float/fef8.c	(revision 9)
+++ /trunk/minix/lib/float/fef8.c	(revision 9)
@@ -0,0 +1,33 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/fef8.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/*
+	SEPERATE DOUBLE INTO EXPONENT AND FRACTION (FEF 8)
+*/
+
+#include	"FP_types.h"
+
+void
+fef8(r, s1)
+DOUBLE	s1;
+struct fef8_returns *r;
+{
+	EXTEND	buf;
+	register struct fef8_returns *p = r;	/* make copy, r might refer
+						   to itself (see table)
+						*/
+
+	extend(&s1.d[0],&buf,sizeof(DOUBLE));
+	if (buf.exp == 0 && buf.m1 == 0 && buf.m2 == 0) {
+		p->e = 0;
+	}
+	else {
+		p->e = buf.exp + 1;
+		buf.exp = -1;
+	}
+	compact(&buf,&p->f.d[0],sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/float/fif4.c
===================================================================
--- /trunk/minix/lib/float/fif4.c	(revision 9)
+++ /trunk/minix/lib/float/fif4.c	(revision 9)
@@ -0,0 +1,46 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/fif4.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/*
+	MULTIPLY AND DISMEMBER PARTS (FIF 4)
+*/
+
+#include "FP_types.h"
+#include "FP_shift.h"
+
+void
+fif4(p,x,y)
+SINGLE	x,y;
+struct fif4_returns *p;
+{
+
+	EXTEND	e1,e2;
+
+	extend(&y,&e1,sizeof(SINGLE));
+	extend(&x,&e2,sizeof(SINGLE));
+		/* do a multiply */
+	mul_ext(&e1,&e2);
+	e2 = e1;
+	compact(&e2,&y,sizeof(SINGLE));
+	if (e1.exp < 0) {
+		p->ipart = 0;
+		p->fpart = y;
+		return;
+	}
+	if (e1.exp > 30 - SGL_M1LEFT) {
+		p->ipart = y;
+		p->fpart = 0;
+		return;
+	}
+	b64_sft(&e1.mantissa, 63 - e1.exp);
+	b64_sft(&e1.mantissa, e1.exp - 63);	/* "loose" low order bits */
+	compact(&e1,&(p->ipart),sizeof(SINGLE));
+	extend(&(p->ipart), &e2, sizeof(SINGLE));
+	extend(&y, &e1, sizeof(SINGLE));
+	sub_ext(&e1, &e2);
+	compact(&e1, &(p->fpart), sizeof(SINGLE));
+}
Index: /trunk/minix/lib/float/fif8.c
===================================================================
--- /trunk/minix/lib/float/fif8.c	(revision 9)
+++ /trunk/minix/lib/float/fif8.c	(revision 9)
@@ -0,0 +1,48 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/fif8.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/*
+	MULTIPLY AND DISMEMBER PARTS (FIF 8)
+*/
+
+#include "FP_types.h"
+#include "FP_shift.h"
+
+void
+fif8(p,x,y)
+DOUBLE	x,y;
+struct fif8_returns *p;
+{
+
+	EXTEND	e1,e2;
+
+	extend(&y.d[0],&e1,sizeof(DOUBLE));
+	extend(&x.d[0],&e2,sizeof(DOUBLE));
+		/* do a multiply */
+	mul_ext(&e1,&e2);
+	e2 = e1;
+	compact(&e2, &y.d[0], sizeof(DOUBLE));
+	if (e1.exp < 0) {
+		p->ipart.d[0] = 0;
+		p->ipart.d[1] = 0;
+		p->fpart = y;
+		return;
+	}
+	if (e1.exp > 62 - DBL_M1LEFT) {
+		p->ipart = y;
+		p->fpart.d[0] = 0;
+		p->fpart.d[1] = 0;
+		return;
+	}
+	b64_sft(&e1.mantissa, 63 - e1.exp);
+	b64_sft(&e1.mantissa, e1.exp - 63);	/* "loose" low order bits */
+	compact(&e1, &(p->ipart.d[0]), sizeof(DOUBLE));
+	extend(&(p->ipart.d[0]), &e2, sizeof(DOUBLE));
+	extend(&y.d[0], &e1, sizeof(DOUBLE));
+	sub_ext(&e1, &e2);
+	compact(&e1, &(p->fpart.d[0]), sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/float/fptrp.s
===================================================================
--- /trunk/minix/lib/float/fptrp.s	(revision 9)
+++ /trunk/minix/lib/float/fptrp.s	(revision 9)
@@ -0,0 +1,19 @@
+#
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define __fptrp
+.sect .text
+__fptrp:
+#if __i386
+	push	ebp
+	mov	ebp, esp
+	mov	eax, 8(bp)
+	call	.Xtrp
+	leave
+	ret
+#else /* i86 */
+	push	bp
+	mov	bp, sp
+	mov	ax, 4(bp)
+	call	.Xtrp
+	jmp	.cret
+#endif
Index: /trunk/minix/lib/float/get_put.h
===================================================================
--- /trunk/minix/lib/float/get_put.h	(revision 9)
+++ /trunk/minix/lib/float/get_put.h	(revision 9)
@@ -0,0 +1,41 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/get_put.h,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+#include <byte_order.h>
+
+#if CHAR_UNSIGNED
+#define Xchar(ch)	(ch)
+#else
+#define Xchar(ch)	((ch) & 0377)
+#endif
+
+#define BYTES_REVERSED (MSB_AT_LOW_ADDRESS != FL_MSB_AT_LOW_ADDRESS)
+#define WORDS_REVERSED (MSW_AT_LOW_ADDRESS != FL_MSW_AT_LOW_ADDRESS)
+#define LONGS_REVERSED (FL_MSL_AT_LOW_ADDRESS)
+
+#if BYTES_REVERSED
+#define uget2(c)	(Xchar((c)[1]) | ((unsigned) Xchar((c)[0]) << 8))
+#define Xput2(i, c)	(((c)[1] = (i)), ((c)[0] = (i) >> 8))
+#define put2(i, c)	{ register int j = (i); Xput2(j, c); }
+#else
+#define uget2(c)	(* ((unsigned short *) (c)))
+#define Xput2(i, c)	(* ((short *) (c)) = (i))
+#define put2(i, c)	Xput2(i, c)
+#endif
+
+#define get2(c)		((short) uget2(c))
+
+#if WORDS_REVERSED || BYTES_REVERSED
+#define get4(c)		(uget2((c)+2) | ((long) uget2(c) << 16))
+#define put4(l, c)	{ register long x=(l); \
+			  Xput2((int)x,(c)+2); \
+			  Xput2((int)(x>>16),(c)); \
+			}
+#else
+#define get4(c)		(* ((long *) (c)))
+#define put4(l, c)	(* ((long *) (c)) = (l))
+#endif
Index: /trunk/minix/lib/float/mlf4.c
===================================================================
--- /trunk/minix/lib/float/mlf4.c	(revision 9)
+++ /trunk/minix/lib/float/mlf4.c	(revision 9)
@@ -0,0 +1,25 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/mlf4.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/*
+ * Multiply Single Precesion Float (MLF 4)
+ */
+
+#include	"FP_types.h"
+
+void
+mlf4(s2,s1)
+SINGLE	s1,s2;
+{
+	EXTEND	e1,e2;
+
+	extend(&s1,&e1,sizeof(SINGLE));
+	extend(&s2,&e2,sizeof(SINGLE));
+		/* do a multiply */
+	mul_ext(&e1,&e2);
+	compact(&e1,&s1,sizeof(SINGLE));
+}
Index: /trunk/minix/lib/float/mlf8.c
===================================================================
--- /trunk/minix/lib/float/mlf8.c	(revision 9)
+++ /trunk/minix/lib/float/mlf8.c	(revision 9)
@@ -0,0 +1,25 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/mlf8.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/*
+ * Multiply Double Precision Float (MLF 8)
+ */
+
+#include	"FP_types.h"
+
+void
+mlf8(s2,s1)
+DOUBLE	s1,s2;
+{
+	EXTEND	e1,e2;
+
+	extend(&s1.d[0],&e1,sizeof(DOUBLE));
+	extend(&s2.d[0],&e2,sizeof(DOUBLE));
+		/* do a multiply */
+	mul_ext(&e1,&e2);
+	compact(&e1,&s1.d[0],sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/float/mul_ext.c
===================================================================
--- /trunk/minix/lib/float/mul_ext.c	(revision 9)
+++ /trunk/minix/lib/float/mul_ext.c	(revision 9)
@@ -0,0 +1,98 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/mul_ext.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/*
+	ROUTINE TO MULTIPLY TWO EXTENDED FORMAT NUMBERS
+*/
+
+# include "FP_bias.h"
+# include "FP_trap.h"
+# include "FP_types.h"
+# include "FP_shift.h"
+
+void
+mul_ext(e1,e2)
+EXTEND	*e1,*e2;
+{
+	register int	i,j;		/* loop control	*/
+	unsigned short	mp[4];		/* multiplier */
+	unsigned short	mc[4];		/* multipcand */
+	unsigned short	result[8];	/* result */
+	register unsigned short *pres;
+
+	/* first save the sign (XOR)			*/
+	e1->sign ^= e2->sign;
+
+	/* compute new exponent */
+	e1->exp += e2->exp + 1;
+	/* 128 bit multiply of mantissas			*/
+
+		/* assign unknown long formats		*/
+		/* to known unsigned word formats	*/
+	mp[0] = e1->m1 >> 16;
+	mp[1] = (unsigned short) e1->m1;
+	mp[2] = e1->m2 >> 16;
+	mp[3] = (unsigned short) e1->m2;
+	mc[0] = e2->m1 >> 16;
+	mc[1] = (unsigned short) e2->m1;
+	mc[2] = e2->m2 >> 16;
+	mc[3] = (unsigned short) e2->m2;
+	for (i = 8; i--;) {
+		result[i] = 0;
+	}
+	/*
+	 *	fill registers with their components
+	 */
+	for(i=4, pres = &result[4];i--;pres--) if (mp[i]) {
+		unsigned short k = 0;
+		unsigned long mpi = mp[i];
+		for(j=4;j--;) {
+			unsigned long tmp = (unsigned long)pres[j] + k;
+			if (mc[j]) tmp += mpi * mc[j];
+			pres[j] = tmp;
+			k = tmp >> 16;
+		}
+		pres[-1] = k;
+	}
+        if (! (result[0] & 0x8000)) {
+                e1->exp--;
+                for (i = 0; i <= 3; i++) {
+                        result[i] <<= 1;
+                        if (result[i+1]&0x8000) result[i] |= 1;
+                }
+                result[4] <<= 1;
+        }
+
+	/*
+	 *	combine the registers to a total
+	 */
+	e1->m1 = ((unsigned long)(result[0]) << 16) + result[1];
+	e1->m2 = ((unsigned long)(result[2]) << 16) + result[3];
+	if (result[4] & 0x8000) {
+		if (++e1->m2 == 0)
+			if (++e1->m1 == 0) {
+				e1->m1 = NORMBIT;
+				e1->exp++;
+			}
+	}
+
+					/* check for overflow	*/
+	if (e1->exp >= EXT_MAX)	{
+		trap(EFOVFL);
+			/* if caught 			*/
+			/* return signed infinity	*/
+		e1->exp = EXT_MAX;
+infinity:	e1->m1 = e1->m2 =0L;
+		return;
+	}
+				/* check for underflow	*/
+	if (e1->exp < EXT_MIN)	{
+		trap(EFUNFL);
+		e1->exp = EXT_MIN;
+		goto infinity;
+	}
+}
Index: /trunk/minix/lib/float/ngf4.c
===================================================================
--- /trunk/minix/lib/float/ngf4.c	(revision 9)
+++ /trunk/minix/lib/float/ngf4.c	(revision 9)
@@ -0,0 +1,27 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/ngf4.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/*
+		NEGATE A FLOATING POINT (NGF 4)
+*/
+/********************************************************/
+
+#include "FP_types.h"
+#include "get_put.h"
+
+#define OFF ((FL_MSW_AT_LOW_ADDRESS ? 0 : 2) + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1))
+void
+ngf4(f)
+SINGLE	f;
+{
+	unsigned char *p;
+
+	if (f != (SINGLE) 0) {
+		p = (unsigned char *) &f + OFF;
+		*p ^= 0x80;
+	}
+}
Index: /trunk/minix/lib/float/ngf8.c
===================================================================
--- /trunk/minix/lib/float/ngf8.c	(revision 9)
+++ /trunk/minix/lib/float/ngf8.c	(revision 9)
@@ -0,0 +1,28 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/ngf8.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/*
+		NEGATE A FLOATING POINT (NGF 8)
+*/
+/********************************************************/
+
+#include "FP_types.h"
+#include "get_put.h"
+
+#define OFF ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1))
+
+void
+ngf8(f)
+DOUBLE	f;
+{
+	unsigned char	*p;
+
+	if (f.d[0] != 0 || f.d[1] != 0) {
+		p = (unsigned char *) &f + OFF;
+		*p ^= 0x80;
+	}
+}
Index: /trunk/minix/lib/float/nrm_ext.c
===================================================================
--- /trunk/minix/lib/float/nrm_ext.c	(revision 9)
+++ /trunk/minix/lib/float/nrm_ext.c	(revision 9)
@@ -0,0 +1,50 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/nrm_ext.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/********************************************************/
+/*
+	NORMALIZE an EXTENDED FORMAT NUMBER
+*/
+/********************************************************/
+
+#include "FP_shift.h"
+#include "FP_types.h"
+
+void
+nrm_ext(e1)
+EXTEND	*e1;
+{
+		/* we assume that the mantissa != 0	*/
+		/* if it is then just return		*/
+		/* to let it be a problem elsewhere	*/
+		/* THAT IS, The exponent is not set to	*/
+		/* zero. If we don't test here an	*/
+		/* infinite loop is generated when	*/
+		/* mantissa is zero			*/
+
+	if ((e1->m1 | e1->m2) == 0L)
+		return;
+
+		/* if top word is zero mov low word	*/
+		/* to top word, adjust exponent value	*/
+	if (e1->m1 == 0L)	{
+		e1->m1 = e1->m2;
+		e1->m2 = 0L;
+		e1->exp -= 32;
+	}
+	if ((e1->m1 & NORMBIT) == 0) {
+		unsigned long l = ((unsigned long)NORMBIT >> 1);
+		int cnt = -1;
+
+		while (! (l & e1->m1)) {
+			l >>= 1;
+			cnt--;
+		}
+		e1->exp += cnt;
+		b64_sft(&(e1->mantissa), cnt);
+	}
+}
Index: /trunk/minix/lib/float/sbf4.c
===================================================================
--- /trunk/minix/lib/float/sbf4.c	(revision 9)
+++ /trunk/minix/lib/float/sbf4.c	(revision 9)
@@ -0,0 +1,27 @@
+/*
+ (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/sbf4.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/*
+	SUBTRACT TWO FLOATS - SINGLE Precision (SBF 4)
+*/
+
+#include	"FP_types.h"
+
+void
+sbf4(s2,s1)
+SINGLE	s1,s2;
+{
+	EXTEND e1,e2;
+
+	if (s2 == (SINGLE) 0) {
+		return;
+	}
+	extend(&s1,&e1,sizeof(SINGLE));
+	extend(&s2,&e2,sizeof(SINGLE));
+	sub_ext(&e1,&e2);
+	compact(&e1,&s1,sizeof(SINGLE));
+}
Index: /trunk/minix/lib/float/sbf8.c
===================================================================
--- /trunk/minix/lib/float/sbf8.c	(revision 9)
+++ /trunk/minix/lib/float/sbf8.c	(revision 9)
@@ -0,0 +1,27 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/sbf8.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/*
+	SUBTRACT TWO FLOATS - DOUBLE Precision (SBF 8)
+*/
+
+#include	"FP_types.h"
+
+void
+sbf8(s2,s1)
+DOUBLE	s1,s2;
+{
+	EXTEND e1, e2;
+
+	if (s2.d[0] == 0 && s2.d[1] == 0) {
+		return;
+	}
+	extend(&s1.d[0],&e1,sizeof(DOUBLE));
+	extend(&s2.d[0],&e2,sizeof(DOUBLE));
+	sub_ext(&e1,&e2);
+	compact(&e1,&s1.d[0],sizeof(DOUBLE));
+}
Index: /trunk/minix/lib/float/sft_ext.c
===================================================================
--- /trunk/minix/lib/float/sft_ext.c	(revision 9)
+++ /trunk/minix/lib/float/sft_ext.c	(revision 9)
@@ -0,0 +1,39 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/sft_ext.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/*
+	SHIFT TWO EXTENDED NUMBERS INTO PROPER
+	ALIGNMENT FOR ADDITION (exponents are equal)
+	Numbers should not be zero on entry.
+*/
+
+#include "FP_types.h"
+
+void
+sft_ext(e1,e2)
+EXTEND	*e1,*e2;
+{
+	register	EXTEND	*s;
+	register	int	diff;
+
+	diff = e1->exp - e2->exp;
+
+	if (!diff)
+		return;	/* exponents are equal	*/
+
+	if (diff < 0)	{ /* e2 is larger	*/
+			/* shift e1		*/
+		diff = -diff;
+		s = e1;
+	}
+	else		/* e1 is larger		*/
+			/* shift e2		*/
+		s = e2;
+
+	s->exp += diff;
+	b64_sft(&(s->mantissa), diff);
+}
Index: /trunk/minix/lib/float/shifter.c
===================================================================
--- /trunk/minix/lib/float/shifter.c	(revision 9)
+++ /trunk/minix/lib/float/shifter.c	(revision 9)
@@ -0,0 +1,75 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/shifter.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+# include "FP_types.h"
+
+void
+b64_sft(e1,n)
+B64	*e1;
+int	n;
+{
+	if (n > 0) {
+		if (n > 63) {
+			e1->l_32 = 0;
+			e1->h_32 = 0;
+			return;
+		}
+		if (n >= 32) {
+			e1->l_32 = e1->h_32;
+			e1->h_32 = 0;
+			n -= 32;
+		}
+		if (n > 0) {
+			e1->l_32 >>= n;
+			if (e1->h_32 != 0) {
+				e1->l_32 |= (e1->h_32 << (32 - n));
+				e1->h_32 >>= n;
+			}
+		}
+		return;
+	}
+	n = -n;
+	if (n > 0) {
+		if (n > 63) {
+			e1->l_32 = 0;
+			e1->h_32 = 0;
+			return;
+		}
+		if (n >= 32) {
+			e1->h_32 = e1->l_32;
+			e1->l_32 = 0;
+			n -= 32;
+		}
+		if (n > 0) {
+			e1->h_32 <<= n;
+			if (e1->l_32 != 0) {
+				e1->h_32 |= (e1->l_32 >> (32 - n));
+				e1->l_32 <<= n;
+			}
+		}
+	}
+}
+
+void
+b64_lsft(e1)
+B64	*e1;
+{
+	/*	shift left 1 bit */
+	e1->h_32 <<= 1;
+	if (e1->l_32 & 0x80000000L) e1->h_32 |= 1;
+	e1->l_32 <<= 1;
+}
+
+void
+b64_rsft(e1)
+B64	*e1;
+{
+	/*	shift right 1 bit */
+	e1->l_32 >>= 1;
+	if (e1->h_32 & 1) e1->l_32 |= 0x80000000L;
+	e1->h_32 >>= 1;
+}
Index: /trunk/minix/lib/float/sub_ext.c
===================================================================
--- /trunk/minix/lib/float/sub_ext.c	(revision 9)
+++ /trunk/minix/lib/float/sub_ext.c	(revision 9)
@@ -0,0 +1,53 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/sub_ext.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/*
+	SUBTRACT 2 EXTENDED FORMAT NUMBERS
+*/
+
+#include "FP_types.h"
+
+void
+sub_ext(e1,e2)
+EXTEND	*e1,*e2;
+{
+	if ((e2->m1 | e2->m2) == 0L) {
+		return;
+	}
+	if ((e1->m1 | e1->m2) == 0L) {
+		*e1 = *e2;
+		e1->sign = e2->sign ? 0 : 1;
+		return;
+	}
+	sft_ext(e1, e2);
+	if (e1->sign != e2->sign) {
+		/* e1 - e2 = e1 + (-e2) */
+		if (b64_add(&e1->mantissa,&e2->mantissa)) { /* addition carry */
+                	b64_rsft(&e1->mantissa);      /* shift mantissa one bit RIGHT */
+                	e1->m1 |= 0x80000000L;  /* set max bit  */
+                	e1->exp++;              /* increase the exponent */
+        	}
+	}
+        else if (e2->m1 > e1->m1 ||
+                 (e2->m1 == e1->m1 && e2->m2 > e1->m2)) {
+		/*	abs(e2) > abs(e1) */
+		if (e1->m2 > e2->m2) {
+			e2->m1 -= 1;	/* carry in */
+		}
+		e2->m1 -= e1->m1;
+		e2->m2 -= e1->m2;
+		*e1 = *e2;
+		e1->sign = e2->sign ? 0 : 1;
+	}
+	else {
+		if (e2->m2 > e1->m2)
+			e1->m1 -= 1;	/* carry in */
+		e1->m1 -= e2->m1;
+		e1->m2 -= e2->m2;
+	}
+	nrm_ext(e1);
+}
Index: /trunk/minix/lib/float/zrf4.c
===================================================================
--- /trunk/minix/lib/float/zrf4.c	(revision 9)
+++ /trunk/minix/lib/float/zrf4.c	(revision 9)
@@ -0,0 +1,19 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/zrf4.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/*
+	return a zero float (ZRF 4)
+*/
+
+#include "FP_types.h"
+
+void
+zrf4(l)
+SINGLE	*l;
+{
+	*l = 0L;
+}
Index: /trunk/minix/lib/float/zrf8.c
===================================================================
--- /trunk/minix/lib/float/zrf8.c	(revision 9)
+++ /trunk/minix/lib/float/zrf8.c	(revision 9)
@@ -0,0 +1,21 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/zrf8.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/*
+	return a zero double (ZRF 8)
+*/
+
+#include "FP_types.h"
+
+void
+zrf8(z)
+DOUBLE	*z;
+{
+
+	z->d[0] = 0L;
+	z->d[1] = 0L;
+}
Index: /trunk/minix/lib/float/zrf_ext.c
===================================================================
--- /trunk/minix/lib/float/zrf_ext.c	(revision 9)
+++ /trunk/minix/lib/float/zrf_ext.c	(revision 9)
@@ -0,0 +1,22 @@
+/*
+  (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+  See the copyright notice in the ACK home directory, in the file "Copyright".
+*/
+
+/* $Header: /cvsup/minix/src/lib/float/zrf_ext.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+/*
+	ZERO and return EXTEND FORMAT FLOAT
+*/
+
+#include "FP_types.h"
+
+void
+zrf_ext(e)
+EXTEND	*e;
+{
+	e->m1 = 0;
+	e->m2 = 0;
+	e->exp = 0;
+	e->sign = 0;
+}
Index: /trunk/minix/lib/fphook/fltpr.c
===================================================================
--- /trunk/minix/lib/fphook/fltpr.c	(revision 9)
+++ /trunk/minix/lib/fphook/fltpr.c	(revision 9)
@@ -0,0 +1,12 @@
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	"../stdio/loc_incl.h"
+
+int _fp_hook = 1;
+
+char *
+_f_print(va_list *ap, int flags, char *s, char c, int precision)
+{
+	fprintf(stderr,"cannot print floating point\n");
+	exit(EXIT_FAILURE);
+}
Index: /trunk/minix/lib/fphook/fphook.c
===================================================================
--- /trunk/minix/lib/fphook/fphook.c	(revision 9)
+++ /trunk/minix/lib/fphook/fphook.c	(revision 9)
@@ -0,0 +1,195 @@
+/*
+ * fltpr.c - print floating point numbers
+ */
+/* $Header: /cvsup/minix/src/lib/fphook/fphook.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+#ifndef	NOFLOAT
+#include	<string.h>
+#include	<stdarg.h>
+#include	"../stdio/loc_incl.h"
+int _fp_hook = 1;
+
+static char *
+_pfloat(long double r, register char *s, int n, int flags)
+{
+	register char *s1;
+	int sign, dp;
+	register int i;
+
+	s1 = _fcvt(r, n, &dp, &sign);
+	if (sign)
+		*s++ = '-';
+	else if (flags & FL_SIGN)
+		*s++ = '+';
+	else if (flags & FL_SPACE)
+		*s++ = ' ';
+
+	if (dp<=0)
+		*s++ = '0';
+	for (i=dp; i>0; i--)
+		if (*s1) *s++ = *s1++;
+		else *s++ = '0';
+	if (((i=n) > 0) || (flags & FL_ALT))
+		*s++ = '.';
+	while (++dp <= 0) {
+		if (--i<0)
+			break;
+		*s++ = '0';
+	}
+	while (--i >= 0)
+		if (*s1) *s++ = *s1++;
+		else *s++ = '0';
+	return s;
+}
+
+static char *
+_pscien(long double r, register char *s, int n, int flags)
+{
+	int sign, dp; 
+	register char *s1;
+
+	s1 = _ecvt(r, n + 1, &dp, &sign);
+	if (sign)
+		*s++ = '-';
+	else if (flags & FL_SIGN)
+		*s++ = '+';
+	else if (flags & FL_SPACE)
+		*s++ = ' ';
+
+	*s++ = *s1++;
+	if ((n > 0) || (flags & FL_ALT))
+		*s++ = '.';
+	while (--n >= 0)
+		if (*s1) *s++ = *s1++;
+		else *s++ = '0';
+	*s++ = 'e';
+	if ( r != 0 ) --dp ;
+	if ( dp<0 ) {
+		*s++ = '-' ; dp= -dp ;
+	} else {
+		*s++ = '+' ;
+	}
+	if (dp >= 100) {
+		*s++ = '0' + (dp / 100);
+		dp %= 100;
+	}
+	*s++ = '0' + (dp/10);
+	*s++ = '0' + (dp%10);
+	return s;
+}
+
+#define	NDIGINEXP(exp)		(((exp) >= 100 || (exp) <= -100) ? 3 : 2)
+#define	LOW_EXP			-4
+#define	USE_EXP(exp, ndigits)	(((exp) < LOW_EXP + 1) || (exp >= ndigits + 1))
+
+static char *
+_gcvt(long double value, int ndigit, char *s, int flags)
+{
+	int sign, dp;
+	register char *s1, *s2;
+	register int i;
+	register int nndigit = ndigit;
+
+	s1 = _ecvt(value, ndigit, &dp, &sign);
+	s2 = s;
+	if (sign) *s2++ = '-';
+	else if (flags & FL_SIGN)
+		*s2++ = '+';
+	else if (flags & FL_SPACE)
+		*s2++ = ' ';
+
+	if (!(flags & FL_ALT))
+		for (i = nndigit - 1; i > 0 && s1[i] == '0'; i--)
+			nndigit--;
+
+	if (USE_EXP(dp,ndigit))	{
+		/* Use E format */
+		dp--;
+		*s2++ = *s1++;
+		if ((nndigit > 1) || (flags & FL_ALT)) *s2++ = '.';
+		while (--nndigit > 0) *s2++ = *s1++;
+		*s2++ = 'e';
+		if (dp < 0) {
+			*s2++ = '-';
+			dp = -dp;
+		}
+		else	 *s2++ = '+';
+		s2 += NDIGINEXP(dp);
+		*s2 = 0;
+		for (i = NDIGINEXP(dp); i > 0; i--) {
+			*--s2 = dp % 10 + '0';
+			dp /= 10;
+		}
+		return s;
+	}
+	/* Use f format */
+	if (dp <= 0) {
+		if (*s1 != '0')	{
+			/* otherwise the whole number is 0 */
+			*s2++ = '0';
+			*s2++ = '.';
+		}
+		while (dp < 0) {
+			dp++;
+			*s2++ = '0';
+		}
+	}
+	for (i = 1; i <= nndigit; i++) {
+		*s2++ = *s1++;
+		if (i == dp) *s2++ = '.';
+	}
+	if (i <= dp) {
+		while (i++ <= dp) *s2++ = '0';
+		*s2++ = '.';
+	}
+	if ((s2[-1]=='.') && !(flags & FL_ALT)) s2--;
+	*s2 = '\0';
+	return s;
+}
+
+char *
+_f_print(va_list *ap, int flags, char *s, char c, int precision)
+{
+	register char *old_s = s;
+	long double ld_val;
+
+	if (flags & FL_LONGDOUBLE) ld_val = va_arg(*ap, long double);
+	else ld_val = (long double) va_arg(*ap, double);
+
+	switch(c) {
+	case 'f':
+		s = _pfloat(ld_val, s, precision, flags);
+		break;
+	case 'e':
+	case 'E':
+		s = _pscien(ld_val, s, precision , flags);
+		break;
+	case 'g':
+	case 'G':
+		s = _gcvt(ld_val, precision, s, flags);
+		s += strlen(s);
+		break;
+	}
+	if ( c == 'E' || c == 'G') {
+		while (*old_s && *old_s != 'e') old_s++;
+		if (*old_s == 'e') *old_s = 'E';
+	}
+	return s;
+}
+#endif	/* NOFLOAT */
+/* $Header: /cvsup/minix/src/lib/fphook/fphook.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
+
+#include <stdlib.h>
+#include "../ansi/ext_fmt.h"
+
+void _str_ext_cvt(const char *s, char **ss, struct EXTEND *e);
+double _ext_dbl_cvt(struct EXTEND *e);
+
+double
+strtod(const char *p, char **pp)
+{
+	struct EXTEND e;
+
+	_str_ext_cvt(p, pp, &e);
+	return _ext_dbl_cvt(&e);
+}
Index: /trunk/minix/lib/fphook/strtod.c
===================================================================
--- /trunk/minix/lib/fphook/strtod.c	(revision 9)
+++ /trunk/minix/lib/fphook/strtod.c	(revision 9)
@@ -0,0 +1,9 @@
+#include	<stdio.h>
+#include	<stdlib.h>
+
+double
+strtod(const char *p, char **pp)
+{
+	fprintf(stderr,"cannot print floating point\n");
+	exit(EXIT_FAILURE);
+}
Index: /trunk/minix/lib/generate.sh
===================================================================
--- /trunk/minix/lib/generate.sh	(revision 9)
+++ /trunk/minix/lib/generate.sh	(revision 9)
@@ -0,0 +1,257 @@
+#!/bin/sh
+# called with parameters: 1:dir 2:ackbase 3:gnubase
+
+exec  >Makefile
+exec 3>Makedepend-ack
+exec 4>Makedepend-gnu
+touch  .depend-ack
+touch  .depend-gnu
+
+echo "#Generated from $1/Makefile.in"
+
+ACKBASE=$2
+GNUBASE=$3
+OBJDIR=$1
+
+RECURSIVE_TARGETS="clean depend depend-ack depend-gnu"
+
+if [ -z $ACKBASE ]; then echo ACKBASE is not set!; exit 1; fi
+if [ -z $GNUBASE ]; then echo GNUBASE is not set!; exit 1; fi
+
+. Makefile.in
+
+#to enable library debugging, enable the next line
+#CFLAGS=$CFLAGS" -g"
+
+echo "all: all-ack"
+echo
+echo "all-ack:"
+echo "all-gnu:"
+echo
+echo "makefiles: Makefile"
+echo "Makedepend-ack Makedepend-gnu: "
+echo "	sh $0 $OBJDIR $ACKBASE $GNUBASE"
+echo
+echo "Makefile: Makefile.in Makedepend-ack Makedepend-gnu"
+echo "	sh $0 $OBJDIR $ACKBASE $GNUBASE"
+echo "	@echo"
+echo "	@echo *Attention*"
+echo "	@echo Makefile is regenerated... rerun command to see changes"
+echo "	@echo *Attention*"
+echo "	@echo"
+echo
+if [ ! -z "$SUBDIRS" ]; then
+	echo "all-ack: makefiles"
+	for dir in $SUBDIRS
+	{
+		if [ $TYPE = "both" -o $TYPE = "ack" ]; then
+			echo "	mkdir -p $ACKBASE/$OBJDIR/$dir"
+		fi
+		echo "	cd $dir && \$(MAKE) \$@"
+	}
+	echo
+	echo "all-gnu: makefiles"
+	for dir in $SUBDIRS
+	{
+		if [ $TYPE = "both" -o $TYPE = "gnu" ]; then
+			echo "	mkdir -p $GNUBASE/$OBJDIR/$dir"
+		fi
+		
+		echo "	cd $dir && \$(MAKE) \$@"
+	}
+	echo
+	echo "$RECURSIVE_TARGETS:: makefiles"
+	for dir in $SUBDIRS
+	{
+		#if [ $TYPE = "both" -o $TYPE = "ack" ]; then
+			#echo "	mkdir -p $ACKBASE/$OBJDIR/$dir"
+		#fi
+		#if [ $TYPE = "both" -o $TYPE = "gnu" ]; then
+			#echo "	mkdir -p $GNUBASE/$OBJDIR/$dir"
+		#fi
+		
+		echo "	cd $dir && \$(MAKE) \$@"
+	}
+	echo
+	for dir in $SUBDIRS
+	{
+		echo "makefiles: $dir/Makefile"
+	}
+	echo
+	for dir in $SUBDIRS
+	{
+		echo "$dir/Makefile: $dir/Makefile.in"
+		echo "	cd $dir && sh ../$0 $OBJDIR/$dir ../$ACKBASE ../$GNUBASE && \$(MAKE) makefiles"
+	}
+else
+
+echo "depend: depend-ack"
+
+echo "depend-ack:" >&3
+echo "	rm .depend-ack" >&3
+echo "	touch .depend-ack" >&3
+
+echo "depend-gnu:" >&4
+echo "	rm .depend-gnu" >&4
+echo "	touch .depend-gnu" >&4
+
+ackCommands()
+{
+	dstfile=$1
+	srcfile=$2
+	dstdir=`dirname $dstfile`
+	
+	case $srcfile in
+	*.s | *.c | *.e )
+		echo "	cc $CFLAGS -c -o $dstfile $srcfile"
+		
+		echo "	mkdep 'cc $CFLAGS -E' $srcfile | sed -e 's:^\(.\):$dstdir/\1:' >> .depend-ack" >&3
+		;;
+	*.mod )
+		echo "	m2 $M2FLAGS -c -o $dstfile $srcfile"
+		
+		echo "	mkdep 'm2 $M2FLAGS -E' $srcfile | sed -e 's:^\(.\):$dstdir/\1:' >> .depend-ack" >&3
+		;;
+	*.fc )
+		echo "	sh ./FP.compile $dstfile $srcfile"
+		
+		echo "	mkdep 'cc -E' $srcfile | sed -e 's:^\(.\):$dstdir/\1:' >> .depend-ack" >&3
+		;;
+	esac
+}
+
+gnuCommands()
+{
+	dstfile=$1
+	srcfile=$2
+	dstdir=`dirname $dstfile`
+	sedcmd="sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):$dstdir/\1:'"
+	
+	case $srcfile in
+	*.s )
+		echo "	gcc $CFLAGS -E -x assembler-with-cpp -I. $srcfile | asmconv -mi386 ack gnu > $GNUBASE/$OBJDIR/$srcfile.gnu || true"
+		echo "	gas -o $dstfile $GNUBASE/$OBJDIR/$srcfile.gnu"
+		
+		echo "	mkdep 'gcc $CFLAGS -E -x assembler-with-cpp -I.' $srcfile | $sedcmd >> .depend-gnu" >&4
+		;;
+	*.gs )
+		echo "	gas -o $dstfile $srcfile"
+		
+		echo "	mkdep 'gcc $CFLAGS -E -x assembler-with-cpp -I.' $srcfile | $sedcmd >> .depend-gnu" >&4
+		;;
+	*.c )
+		echo "	gcc $CFLAGS -c -o $dstfile $srcfile"
+		
+		echo "	mkdep 'gcc $CFLAGS -E' $srcfile | $sedcmd >> .depend-gnu" >&4
+		;;
+	#*.mod )
+	#	echo "	\$(M2C) -o $dstfile $srcfile"
+	#	;;
+	#*.fc )
+	#	echo "	sh ./FP.COMPILE $srcfile"
+	#	;;
+	esac
+	echo
+}
+
+#libraries
+for lib in $LIBRARIES
+{
+	if [ $TYPE = "both" -o $TYPE = "ack" ]; then
+		echo "all-ack: $ACKBASE/$lib.a"
+		eval "FILES=\$${lib}_FILES" 
+		echo
+		for f in $FILES
+		{
+			o=`echo $f | sed -e 's/\\..*\$/\.o/'`
+			echo "$ACKBASE/$lib.a: $ACKBASE/$lib.a($o)"
+		}
+		echo
+		echo "$ACKBASE/$lib.a:"
+		echo "	ar cr $ACKBASE/$lib.a $ACKBASE/$OBJDIR/*.o"
+		echo "	rm $ACKBASE/$OBJDIR/*.o"
+		echo
+		for f in $FILES
+		{
+			o=`echo $f | sed -e 's/\\..*\$/\.o/'`
+			echo "$ACKBASE/$lib.a($o): $f"
+			
+			ackCommands $ACKBASE/$OBJDIR/$o $f
+		}
+		echo
+	fi
+	
+	if [ $TYPE = "both" -o $TYPE = "gnu" ]; then
+		echo "all-gnu: $GNUBASE/$lib.a"
+		eval "FILES=\$${lib}_FILES" 
+		echo
+		for f in $FILES
+		{
+			o=`echo $f | sed -e 's/\\..*\$/\.o/'`
+			echo "$GNUBASE/$lib.a: $GNUBASE/$OBJDIR/$o"
+		}
+		echo
+		echo "$GNUBASE/$lib.a:"
+		echo "	gar cr $GNUBASE/$lib.a \$?"
+		echo
+		for f in $FILES
+		{
+			o=`echo $f | sed -e 's/\\..*\$/\.o/'`
+			
+			echo "$GNUBASE/$OBJDIR/$o: $f"
+			
+			gnuCommands $GNUBASE/$OBJDIR/$o $f
+		}
+		echo
+	fi
+}
+echo
+
+#start files
+for f in $STARTFILES
+{
+	o=`echo $f | sed -e 's/\\..*\$/\.o/'`
+	
+	if [ $TYPE = "both" -o $TYPE = "ack" ]; then
+		echo "all-ack: $ACKBASE/$o"
+		echo
+		echo "$ACKBASE/$o: $f"
+		ackCommands $ACKBASE/$o $f
+		echo
+	fi
+	if [ $TYPE = "both" -o $TYPE = "gnu" ]; then
+		echo "all-gnu: $GNUBASE/$o"
+		echo
+		echo "$GNUBASE/$o: $f"
+		gnuCommands $GNUBASE/$o $f
+		echo
+	fi
+}
+
+fi # elif of if [ -n "$SUBDIRS" ]
+echo
+echo "clean::"
+if [ $TYPE = "both" -o $TYPE = "ack" ]; then
+	echo "	rm -f $ACKBASE/$OBJDIR/*"
+fi
+if [ $TYPE = "both" -o $TYPE = "gnu" ]; then
+	echo "	rm -f $GNUBASE/$OBJDIR/*"
+fi
+
+if [ $OBJDIR = "." ]; then
+	echo
+	echo "install: install-ack"
+	echo
+	echo "install-ack: all-ack"
+	echo "	cp $ACKBASE/*.[ao] /usr/lib/i386"
+	echo
+	echo "install-gnu: all-gnu"
+	echo "	cp $GNUBASE/*.[ao] /usr/gnu/lib"
+fi
+
+echo
+echo "include Makedepend-ack"
+echo "include .depend-ack"
+echo
+echo "include Makedepend-gnu"
+echo "include .depend-gnu"
Index: /trunk/minix/lib/gnu/Makefile
===================================================================
--- /trunk/minix/lib/gnu/Makefile	(revision 9)
+++ /trunk/minix/lib/gnu/Makefile	(revision 9)
@@ -0,0 +1,55 @@
+#Generated from ./gnu/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./gnu ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./gnu ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+all-ack: makefiles
+	cd end && $(MAKE) $@
+	cd ieee_float && $(MAKE) $@
+	cd rts && $(MAKE) $@
+
+all-gnu: makefiles
+	mkdir -p ../obj-gnu/./gnu/end
+	cd end && $(MAKE) $@
+	mkdir -p ../obj-gnu/./gnu/ieee_float
+	cd ieee_float && $(MAKE) $@
+	mkdir -p ../obj-gnu/./gnu/rts
+	cd rts && $(MAKE) $@
+
+clean depend depend-ack depend-gnu:: makefiles
+	cd end && $(MAKE) $@
+	cd ieee_float && $(MAKE) $@
+	cd rts && $(MAKE) $@
+
+makefiles: end/Makefile
+makefiles: ieee_float/Makefile
+makefiles: rts/Makefile
+
+end/Makefile: end/Makefile.in
+	cd end && sh ../../generate.sh ./gnu/end ../../obj-ack/ ../../obj-gnu && $(MAKE) makefiles
+ieee_float/Makefile: ieee_float/Makefile.in
+	cd ieee_float && sh ../../generate.sh ./gnu/ieee_float ../../obj-ack/ ../../obj-gnu && $(MAKE) makefiles
+rts/Makefile: rts/Makefile.in
+	cd rts && sh ../../generate.sh ./gnu/rts ../../obj-ack/ ../../obj-gnu && $(MAKE) makefiles
+
+clean::
+	rm -f ../obj-gnu/./gnu/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/gnu/Makefile.in
===================================================================
--- /trunk/minix/lib/gnu/Makefile.in	(revision 9)
+++ /trunk/minix/lib/gnu/Makefile.in	(revision 9)
@@ -0,0 +1,7 @@
+
+SUBDIRS=" \
+	end \
+	ieee_float \
+	rts"
+
+TYPE=gnu
Index: /trunk/minix/lib/gnu/end/Makedepend-ack
===================================================================
--- /trunk/minix/lib/gnu/end/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/gnu/end/Makedepend-ack	(revision 9)
@@ -0,0 +1,3 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
Index: /trunk/minix/lib/gnu/end/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/gnu/end/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/gnu/end/Makedepend-gnu	(revision 9)
@@ -0,0 +1,4 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' gnu_end.gs | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./gnu/end/\1:' >> .depend-gnu
Index: /trunk/minix/lib/gnu/end/Makefile
===================================================================
--- /trunk/minix/lib/gnu/end/Makefile	(revision 9)
+++ /trunk/minix/lib/gnu/end/Makefile	(revision 9)
@@ -0,0 +1,40 @@
+#Generated from ./gnu/end/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../generate.sh ./gnu/end ../../obj-ack/ ../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../generate.sh ./gnu/end ../../obj-ack/ ../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-gnu: ../../obj-gnu/end.a
+
+../../obj-gnu/end.a: ../../obj-gnu/./gnu/end/gnu_end.o
+
+../../obj-gnu/end.a:
+	gar cr ../../obj-gnu/end.a $?
+
+../../obj-gnu/./gnu/end/gnu_end.o: gnu_end.gs
+	gas -o ../../obj-gnu/./gnu/end/gnu_end.o gnu_end.gs
+
+
+
+
+clean::
+	rm -f ../../obj-gnu/./gnu/end/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/gnu/end/Makefile.in
===================================================================
--- /trunk/minix/lib/gnu/end/Makefile.in	(revision 9)
+++ /trunk/minix/lib/gnu/end/Makefile.in	(revision 9)
@@ -0,0 +1,7 @@
+
+LIBRARIES=end
+
+end_FILES=gnu_end.gs
+
+TYPE=gnu
+
Index: /trunk/minix/lib/gnu/end/gnu_end.gs
===================================================================
--- /trunk/minix/lib/gnu/end/gnu_end.gs	(revision 9)
+++ /trunk/minix/lib/gnu/end/gnu_end.gs	(revision 9)
@@ -0,0 +1,5 @@
+
+.stabs "endbss",11,0,0,0
+.stabs "__end",1,0,0,0
+
+
Index: /trunk/minix/lib/gnu/ieee_float/Makedepend-ack
===================================================================
--- /trunk/minix/lib/gnu/ieee_float/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/gnu/ieee_float/Makedepend-ack	(revision 9)
@@ -0,0 +1,3 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
Index: /trunk/minix/lib/gnu/ieee_float/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/gnu/ieee_float/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/gnu/ieee_float/Makedepend-gnu	(revision 9)
@@ -0,0 +1,9 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -I.. -E' frexp.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./gnu/ieee_float/\1:' >> .depend-gnu
+	mkdep 'gcc -O -I.. -E' isinf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./gnu/ieee_float/\1:' >> .depend-gnu
+	mkdep 'gcc -O -I.. -E' isnan.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./gnu/ieee_float/\1:' >> .depend-gnu
+	mkdep 'gcc -O -I.. -E' ldexp.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./gnu/ieee_float/\1:' >> .depend-gnu
+	mkdep 'gcc -O -I.. -E' modf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./gnu/ieee_float/\1:' >> .depend-gnu
+	mkdep 'gcc -O -I.. -E' fphook.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./gnu/ieee_float/\1:' >> .depend-gnu
Index: /trunk/minix/lib/gnu/ieee_float/Makefile
===================================================================
--- /trunk/minix/lib/gnu/ieee_float/Makefile	(revision 9)
+++ /trunk/minix/lib/gnu/ieee_float/Makefile	(revision 9)
@@ -0,0 +1,60 @@
+#Generated from ./gnu/ieee_float/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../generate.sh ./gnu/ieee_float ../../obj-ack/ ../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../generate.sh ./gnu/ieee_float ../../obj-ack/ ../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-gnu: ../../obj-gnu/libc.a
+
+../../obj-gnu/libc.a: ../../obj-gnu/./gnu/ieee_float/frexp.o
+../../obj-gnu/libc.a: ../../obj-gnu/./gnu/ieee_float/isinf.o
+../../obj-gnu/libc.a: ../../obj-gnu/./gnu/ieee_float/isnan.o
+../../obj-gnu/libc.a: ../../obj-gnu/./gnu/ieee_float/ldexp.o
+../../obj-gnu/libc.a: ../../obj-gnu/./gnu/ieee_float/modf.o
+../../obj-gnu/libc.a: ../../obj-gnu/./gnu/ieee_float/fphook.o
+
+../../obj-gnu/libc.a:
+	gar cr ../../obj-gnu/libc.a $?
+
+../../obj-gnu/./gnu/ieee_float/frexp.o: frexp.c
+	gcc -O -I.. -c -o ../../obj-gnu/./gnu/ieee_float/frexp.o frexp.c
+
+../../obj-gnu/./gnu/ieee_float/isinf.o: isinf.c
+	gcc -O -I.. -c -o ../../obj-gnu/./gnu/ieee_float/isinf.o isinf.c
+
+../../obj-gnu/./gnu/ieee_float/isnan.o: isnan.c
+	gcc -O -I.. -c -o ../../obj-gnu/./gnu/ieee_float/isnan.o isnan.c
+
+../../obj-gnu/./gnu/ieee_float/ldexp.o: ldexp.c
+	gcc -O -I.. -c -o ../../obj-gnu/./gnu/ieee_float/ldexp.o ldexp.c
+
+../../obj-gnu/./gnu/ieee_float/modf.o: modf.c
+	gcc -O -I.. -c -o ../../obj-gnu/./gnu/ieee_float/modf.o modf.c
+
+../../obj-gnu/./gnu/ieee_float/fphook.o: fphook.c
+	gcc -O -I.. -c -o ../../obj-gnu/./gnu/ieee_float/fphook.o fphook.c
+
+
+
+
+clean::
+	rm -f ../../obj-gnu/./gnu/ieee_float/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/gnu/ieee_float/Makefile.in
===================================================================
--- /trunk/minix/lib/gnu/ieee_float/Makefile.in	(revision 9)
+++ /trunk/minix/lib/gnu/ieee_float/Makefile.in	(revision 9)
@@ -0,0 +1,14 @@
+
+CFLAGS="-O -I.."
+
+LIBRARIES=libc
+
+libc_FILES=" \
+	frexp.c \
+	isinf.c \
+	isnan.c \
+	ldexp.c \
+	modf.c \
+	fphook.c"
+
+TYPE=gnu
Index: /trunk/minix/lib/gnu/ieee_float/fphook.c
===================================================================
--- /trunk/minix/lib/gnu/ieee_float/fphook.c	(revision 9)
+++ /trunk/minix/lib/gnu/ieee_float/fphook.c	(revision 9)
@@ -0,0 +1,195 @@
+/*
+ * fltpr.c - print floating point numbers
+ */
+/* $Header: /cvsup/minix/src/lib/gnu/ieee_float/fphook.c,v 1.1 2005/10/10 15:28:15 beng Exp $ */
+
+#ifndef	NOFLOAT
+#include	<string.h>
+#include	<stdarg.h>
+#include	"../stdio/loc_incl.h"
+int _fp_hook = 1;
+
+static char *
+_pfloat(long double r, register char *s, int n, int flags)
+{
+	register char *s1;
+	int sign, dp;
+	register int i;
+
+	s1 = _fcvt(r, n, &dp, &sign);
+	if (sign)
+		*s++ = '-';
+	else if (flags & FL_SIGN)
+		*s++ = '+';
+	else if (flags & FL_SPACE)
+		*s++ = ' ';
+
+	if (dp<=0)
+		*s++ = '0';
+	for (i=dp; i>0; i--)
+		if (*s1) *s++ = *s1++;
+		else *s++ = '0';
+	if (((i=n) > 0) || (flags & FL_ALT))
+		*s++ = '.';
+	while (++dp <= 0) {
+		if (--i<0)
+			break;
+		*s++ = '0';
+	}
+	while (--i >= 0)
+		if (*s1) *s++ = *s1++;
+		else *s++ = '0';
+	return s;
+}
+
+static char *
+_pscien(long double r, register char *s, int n, int flags)
+{
+	int sign, dp; 
+	register char *s1;
+
+	s1 = _ecvt(r, n + 1, &dp, &sign);
+	if (sign)
+		*s++ = '-';
+	else if (flags & FL_SIGN)
+		*s++ = '+';
+	else if (flags & FL_SPACE)
+		*s++ = ' ';
+
+	*s++ = *s1++;
+	if ((n > 0) || (flags & FL_ALT))
+		*s++ = '.';
+	while (--n >= 0)
+		if (*s1) *s++ = *s1++;
+		else *s++ = '0';
+	*s++ = 'e';
+	if ( r != 0 ) --dp ;
+	if ( dp<0 ) {
+		*s++ = '-' ; dp= -dp ;
+	} else {
+		*s++ = '+' ;
+	}
+	if (dp >= 100) {
+		*s++ = '0' + (dp / 100);
+		dp %= 100;
+	}
+	*s++ = '0' + (dp/10);
+	*s++ = '0' + (dp%10);
+	return s;
+}
+
+#define	NDIGINEXP(exp)		(((exp) >= 100 || (exp) <= -100) ? 3 : 2)
+#define	LOW_EXP			-4
+#define	USE_EXP(exp, ndigits)	(((exp) < LOW_EXP + 1) || (exp >= ndigits + 1))
+
+static char *
+_gcvt(long double value, int ndigit, char *s, int flags)
+{
+	int sign, dp;
+	register char *s1, *s2;
+	register int i;
+	register int nndigit = ndigit;
+
+	s1 = _ecvt(value, ndigit, &dp, &sign);
+	s2 = s;
+	if (sign) *s2++ = '-';
+	else if (flags & FL_SIGN)
+		*s2++ = '+';
+	else if (flags & FL_SPACE)
+		*s2++ = ' ';
+
+	if (!(flags & FL_ALT))
+		for (i = nndigit - 1; i > 0 && s1[i] == '0'; i--)
+			nndigit--;
+
+	if (USE_EXP(dp,ndigit))	{
+		/* Use E format */
+		dp--;
+		*s2++ = *s1++;
+		if ((nndigit > 1) || (flags & FL_ALT)) *s2++ = '.';
+		while (--nndigit > 0) *s2++ = *s1++;
+		*s2++ = 'e';
+		if (dp < 0) {
+			*s2++ = '-';
+			dp = -dp;
+		}
+		else	 *s2++ = '+';
+		s2 += NDIGINEXP(dp);
+		*s2 = 0;
+		for (i = NDIGINEXP(dp); i > 0; i--) {
+			*--s2 = dp % 10 + '0';
+			dp /= 10;
+		}
+		return s;
+	}
+	/* Use f format */
+	if (dp <= 0) {
+		if (*s1 != '0')	{
+			/* otherwise the whole number is 0 */
+			*s2++ = '0';
+			*s2++ = '.';
+		}
+		while (dp < 0) {
+			dp++;
+			*s2++ = '0';
+		}
+	}
+	for (i = 1; i <= nndigit; i++) {
+		*s2++ = *s1++;
+		if (i == dp) *s2++ = '.';
+	}
+	if (i <= dp) {
+		while (i++ <= dp) *s2++ = '0';
+		*s2++ = '.';
+	}
+	if ((s2[-1]=='.') && !(flags & FL_ALT)) s2--;
+	*s2 = '\0';
+	return s;
+}
+
+char *
+_f_print(va_list *ap, int flags, char *s, char c, int precision)
+{
+	register char *old_s = s;
+	long double ld_val;
+
+	if (flags & FL_LONGDOUBLE) ld_val = va_arg(*ap, long double);
+	else ld_val = (long double) va_arg(*ap, double);
+
+	switch(c) {
+	case 'f':
+		s = _pfloat(ld_val, s, precision, flags);
+		break;
+	case 'e':
+	case 'E':
+		s = _pscien(ld_val, s, precision , flags);
+		break;
+	case 'g':
+	case 'G':
+		s = _gcvt(ld_val, precision, s, flags);
+		s += strlen(s);
+		break;
+	}
+	if ( c == 'E' || c == 'G') {
+		while (*old_s && *old_s != 'e') old_s++;
+		if (*old_s == 'e') *old_s = 'E';
+	}
+	return s;
+}
+#endif	/* NOFLOAT */
+/* $Header: /cvsup/minix/src/lib/gnu/ieee_float/fphook.c,v 1.1 2005/10/10 15:28:15 beng Exp $ */
+
+#include <stdlib.h>
+#include "../ansi/ext_fmt.h"
+
+void _str_ext_cvt(const char *s, char **ss, struct EXTEND *e);
+double _ext_dbl_cvt(struct EXTEND *e);
+
+double
+strtod(const char *p, char **pp)
+{
+	struct EXTEND e;
+
+	_str_ext_cvt(p, pp, &e);
+	return _ext_dbl_cvt(&e);
+}
Index: /trunk/minix/lib/gnu/ieee_float/frexp.c
===================================================================
--- /trunk/minix/lib/gnu/ieee_float/frexp.c	(revision 9)
+++ /trunk/minix/lib/gnu/ieee_float/frexp.c	(revision 9)
@@ -0,0 +1,60 @@
+/*
+libc/ieee_float/frexp.c
+
+Created:	Oct 14, 1993 by Philip Homburg <philip@cs.vu.nl>
+
+Implementation of frexp that directly manipulates the exponent bits in an
+ieee float
+*/
+
+#include <sys/types.h>
+#include <math.h>
+
+#include "ieee_float.h"
+
+double frexp(value, eptr)
+double value;
+int *eptr;
+{
+	struct f64 *f64p;
+	int exp, exp_bias;
+	double factor;
+
+	f64p= (struct f64 *)&value;
+	exp_bias= 0;
+
+	exp= F64_GET_EXP(f64p);
+	if (exp == F64_EXP_MAX)
+	{	/* Either infinity or Nan */
+		*eptr= 0;
+		return value;
+	}
+	if (exp == 0)
+	{
+		/* Either 0 or denormal */
+		if (F64_GET_MANT_LOW(f64p) == 0 &&
+			F64_GET_MANT_HIGH(f64p) == 0)
+		{
+			*eptr= 0;
+			return value;
+		}
+
+		/* Multiply by 2^64 */
+		factor= 65536.0;	/* 2^16 */
+		factor *= factor;	/* 2^32 */
+		factor *= factor;	/* 2^64 */
+		value *= factor;
+		exp_bias= 64;
+		exp= F64_GET_EXP(f64p);
+	}
+
+	exp= exp - F64_EXP_BIAS - exp_bias + 1;
+	*eptr= exp;
+	F64_SET_EXP(f64p, F64_EXP_BIAS-1);
+
+	return value;
+}
+
+/*
+ * $PchId: frexp.c,v 1.3 1996/02/22 21:01:39 philip Exp $
+ */
Index: /trunk/minix/lib/gnu/ieee_float/ieee_float.h
===================================================================
--- /trunk/minix/lib/gnu/ieee_float/ieee_float.h	(revision 9)
+++ /trunk/minix/lib/gnu/ieee_float/ieee_float.h	(revision 9)
@@ -0,0 +1,51 @@
+/*
+libc/ieee_float/ieee_float.h
+
+Created:	Oct 14, 1993 by Philip Homburg <philip@cs.vu.nl>
+
+Define structures and macros for manipulating IEEE floats
+*/
+
+#ifndef IEEE_FLOAT_H
+#define IEEE_FLOAT_H
+
+#define isnan __IsNan
+
+struct f64
+{
+	u32_t low_word;
+	u32_t high_word;
+};
+
+#define F64_SIGN_SHIFT	31
+#define F64_SIGN_MASK	1
+
+#define F64_EXP_SHIFT	20
+#define F64_EXP_MASK	0x7ff
+#define F64_EXP_BIAS	1023
+#define F64_EXP_MAX	2047
+
+#define F64_MANT_SHIFT	0
+#define F64_MANT_MASK	0xfffff
+
+#define F64_GET_SIGN(fp)	(((fp)->high_word >> F64_SIGN_SHIFT) & \
+					F64_SIGN_MASK)
+#define F64_GET_EXP(fp)		(((fp)->high_word >> F64_EXP_SHIFT) & \
+					F64_EXP_MASK)
+#define F64_SET_EXP(fp, val)	((fp)->high_word= ((fp)->high_word &	\
+				~(F64_EXP_MASK << F64_EXP_SHIFT)) | 	\
+				(((val) & F64_EXP_MASK) << F64_EXP_SHIFT))
+
+#define F64_GET_MANT_LOW(fp)		((fp)->low_word)
+#define F64_SET_MANT_LOW(fp, val)	((fp)->low_word= (val))
+#define F64_GET_MANT_HIGH(fp)	(((fp)->high_word >> F64_MANT_SHIFT) & \
+					F64_MANT_MASK)
+#define F64_SET_MANT_HIGH(fp, val)	((fp)->high_word= ((fp)->high_word & \
+				~(F64_MANT_MASK << F64_MANT_SHIFT)) |	\
+				(((val) & F64_MANT_MASK) << F64_MANT_SHIFT))
+
+#endif /* IEEE_FLOAT_H */
+
+/*
+ * $PchId: ieee_float.h,v 1.3 1996/02/22 21:01:39 philip Exp $
+ */
Index: /trunk/minix/lib/gnu/ieee_float/isinf.c
===================================================================
--- /trunk/minix/lib/gnu/ieee_float/isinf.c	(revision 9)
+++ /trunk/minix/lib/gnu/ieee_float/isinf.c	(revision 9)
@@ -0,0 +1,31 @@
+/*
+libc/ieee_float/isinf.c
+
+Created:	Oct 14, 1993 by Philip Homburg <philip@cs.vu.nl>
+
+Implementation of isinf that directly tests the bits in an ieee float
+*/
+
+#define _MINIX_SOURCE
+
+#include <sys/types.h>
+#include <math.h>
+
+#include "ieee_float.h"
+
+int isinf(value)
+double value;
+{
+	struct f64 *f64p;
+	int exp;
+
+	f64p= (struct f64 *)&value;
+	exp= F64_GET_EXP(f64p);
+	if (exp != F64_EXP_MAX)
+		return 0;
+	return F64_GET_MANT_LOW(f64p) == 0 && F64_GET_MANT_HIGH(f64p) == 0;
+}
+
+/*
+ * $PchId: isinf.c,v 1.3 1996/02/22 21:01:39 philip Exp $
+ */
Index: /trunk/minix/lib/gnu/ieee_float/isnan.c
===================================================================
--- /trunk/minix/lib/gnu/ieee_float/isnan.c	(revision 9)
+++ /trunk/minix/lib/gnu/ieee_float/isnan.c	(revision 9)
@@ -0,0 +1,31 @@
+/*
+libc/ieee_float/isnan.c
+
+Created:	Oct 14, 1993 by Philip Homburg <philip@cs.vu.nl>
+
+Implementation of isnan that directly tests the bits in an ieee float
+*/
+
+#define _MINIX_SOURCE
+
+#include <sys/types.h>
+#include <math.h>
+
+#include "ieee_float.h"
+
+int isnan(value)
+double value;
+{
+	struct f64 *f64p;
+	int exp;
+
+	f64p= (struct f64 *)&value;
+	exp= F64_GET_EXP(f64p);
+	if (exp != F64_EXP_MAX)
+		return 0;
+	return F64_GET_MANT_LOW(f64p) != 0 || F64_GET_MANT_HIGH(f64p) != 0;
+}
+
+/*
+ * $PchId: isnan.c,v 1.3 1996/02/22 21:01:39 philip Exp $
+ */
Index: /trunk/minix/lib/gnu/ieee_float/ldexp.c
===================================================================
--- /trunk/minix/lib/gnu/ieee_float/ldexp.c	(revision 9)
+++ /trunk/minix/lib/gnu/ieee_float/ldexp.c	(revision 9)
@@ -0,0 +1,99 @@
+/*
+libc/ieee_float/ldexp.c
+
+Created:	Oct 14, 1993 by Philip Homburg <philip@cs.vu.nl>
+
+Implementation of ldexp that directly manipulates the exponent bits in an
+ieee float
+*/
+
+#include <sys/types.h>
+#include <errno.h>
+#include <math.h>
+
+#include "ieee_float.h"
+
+double ldexp(value, exp)
+double value;
+int exp;
+{
+	struct f64 *f64p;
+	int oldexp, exp_bias;
+	double factor;
+
+	f64p= (struct f64 *)&value;
+	exp_bias= 0;
+
+	oldexp= F64_GET_EXP(f64p);
+	if (oldexp == F64_EXP_MAX)
+	{	/* Either infinity or Nan */
+		return value;
+	}
+	if (oldexp == 0)
+	{
+		/* Either 0 or denormal */
+		if (F64_GET_MANT_LOW(f64p) == 0 &&
+			F64_GET_MANT_HIGH(f64p) == 0)
+		{
+			return value;
+		}
+	}
+
+	/* If exp is too large (> 2*F64_EXP_MAX) or too small
+	 * (< -2*F64_EXP_MAX) return HUGE_VAL or 0. This prevents overflows
+	 * in exp if exp is really weird
+	 */
+	if (exp >= 2*F64_EXP_MAX)
+	{
+		errno= ERANGE;
+		return HUGE_VAL;
+	}
+	if (exp <= -2*F64_EXP_MAX)
+	{
+		errno= ERANGE;
+		return 0;
+	}
+	
+	/* Normalize a denormal */
+	if (oldexp == 0)
+	{
+		/* Multiply by 2^64 */
+		factor= 65536.0;	/* 2^16 */
+		factor *= factor;	/* 2^32 */
+		factor *= factor;	/* 2^64 */
+		value *= factor;
+		exp= -64;
+		oldexp= F64_GET_EXP(f64p);
+	}
+
+	exp= oldexp + exp;
+	if (exp >= F64_EXP_MAX)
+	{	/* Overflow */
+		errno= ERANGE;
+		return HUGE_VAL;
+	}
+	if (exp > 0)
+	{
+		/* Normal */
+		F64_SET_EXP(f64p, exp);
+		return value;
+	}
+	/* Denormal, or underflow. */
+	exp += 64;
+	F64_SET_EXP(f64p, exp);
+	/* Divide by 2^64 */
+	factor= 65536.0;	/* 2^16 */
+	factor *= factor;	/* 2^32 */
+	factor *= factor;	/* 2^64 */
+	value /= factor;
+	if (value == 0.0)
+	{
+		/* Underflow */
+		errno= ERANGE;
+	}
+	return value;
+}
+
+/*
+ * $PchId: ldexp.c,v 1.3 1996/02/22 21:01:39 philip Exp $
+ */
Index: /trunk/minix/lib/gnu/ieee_float/modf.c
===================================================================
--- /trunk/minix/lib/gnu/ieee_float/modf.c	(revision 9)
+++ /trunk/minix/lib/gnu/ieee_float/modf.c	(revision 9)
@@ -0,0 +1,61 @@
+/*
+libc/ieee_float/modf.c
+
+Created:	Oct 14, 1993 by Philip Homburg <philip@cs.vu.nl>
+
+Implementation of modf that directly manipulates the exponent bits in an
+ieee float
+*/
+
+#include <sys/types.h>
+#include <math.h>
+
+#include "ieee_float.h"
+
+double modf(value, iptr)
+double value;
+double *iptr;
+{
+	struct f64 *f64p;
+	double tmp;
+	int exp;
+	int mask_bits;
+	u32_t mant;
+
+	f64p= (struct f64 *)&value;
+
+	exp= F64_GET_EXP(f64p);
+	exp -= F64_EXP_BIAS;
+	if (exp < 0)
+	{
+		*iptr= 0;
+		return value;
+	}
+	mask_bits= 52-exp;
+	if (mask_bits <= 0)
+	{
+		*iptr= value;
+		return 0;
+	}
+	tmp= value;
+	if (mask_bits >= 32)
+	{
+		F64_SET_MANT_LOW(f64p, 0);
+		mask_bits -= 32;
+		mant= F64_GET_MANT_HIGH(f64p);
+		mant &= ~((1 << mask_bits)-1);
+		F64_SET_MANT_HIGH(f64p, mant);
+	}
+	else
+	{
+		mant= F64_GET_MANT_LOW(f64p);
+		mant &= ~((1 << mask_bits)-1);
+		F64_SET_MANT_LOW(f64p, mant);
+	}
+	*iptr= value;
+	return tmp-value;
+}
+
+/*
+ * $PchId: modf.c,v 1.3 1996/02/22 21:01:39 philip Exp $
+ */
Index: /trunk/minix/lib/gnu/rts/Makedepend-ack
===================================================================
--- /trunk/minix/lib/gnu/rts/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/gnu/rts/Makedepend-ack	(revision 9)
@@ -0,0 +1,3 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
Index: /trunk/minix/lib/gnu/rts/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/gnu/rts/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/gnu/rts/Makedepend-gnu	(revision 9)
@@ -0,0 +1,7 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' _longjmp.gs | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./gnu/rts/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' _setjmp.gs | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./gnu/rts/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' longjmp.gs | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./gnu/rts/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' setjmp.gs | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./gnu/rts/\1:' >> .depend-gnu
Index: /trunk/minix/lib/gnu/rts/Makefile
===================================================================
--- /trunk/minix/lib/gnu/rts/Makefile	(revision 9)
+++ /trunk/minix/lib/gnu/rts/Makefile	(revision 9)
@@ -0,0 +1,52 @@
+#Generated from ./gnu/rts/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../generate.sh ./gnu/rts ../../obj-ack/ ../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../generate.sh ./gnu/rts ../../obj-ack/ ../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-gnu: ../../obj-gnu/libc.a
+
+../../obj-gnu/libc.a: ../../obj-gnu/./gnu/rts/_longjmp.o
+../../obj-gnu/libc.a: ../../obj-gnu/./gnu/rts/_setjmp.o
+../../obj-gnu/libc.a: ../../obj-gnu/./gnu/rts/longjmp.o
+../../obj-gnu/libc.a: ../../obj-gnu/./gnu/rts/setjmp.o
+
+../../obj-gnu/libc.a:
+	gar cr ../../obj-gnu/libc.a $?
+
+../../obj-gnu/./gnu/rts/_longjmp.o: _longjmp.gs
+	gas -o ../../obj-gnu/./gnu/rts/_longjmp.o _longjmp.gs
+
+../../obj-gnu/./gnu/rts/_setjmp.o: _setjmp.gs
+	gas -o ../../obj-gnu/./gnu/rts/_setjmp.o _setjmp.gs
+
+../../obj-gnu/./gnu/rts/longjmp.o: longjmp.gs
+	gas -o ../../obj-gnu/./gnu/rts/longjmp.o longjmp.gs
+
+../../obj-gnu/./gnu/rts/setjmp.o: setjmp.gs
+	gas -o ../../obj-gnu/./gnu/rts/setjmp.o setjmp.gs
+
+
+
+
+clean::
+	rm -f ../../obj-gnu/./gnu/rts/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/gnu/rts/Makefile.in
===================================================================
--- /trunk/minix/lib/gnu/rts/Makefile.in	(revision 9)
+++ /trunk/minix/lib/gnu/rts/Makefile.in	(revision 9)
@@ -0,0 +1,10 @@
+
+LIBRARIES=libc
+
+libc_FILES=" \
+	_longjmp.gs \
+	_setjmp.gs \
+	longjmp.gs \
+	setjmp.gs"
+
+TYPE=gnu
Index: /trunk/minix/lib/gnu/rts/_longjmp.gs
===================================================================
--- /trunk/minix/lib/gnu/rts/_longjmp.gs	(revision 9)
+++ /trunk/minix/lib/gnu/rts/_longjmp.gs	(revision 9)
@@ -0,0 +1,38 @@
+/ _longjmp.gnu.s
+/
+/ Created:	Oct 15, 1993 by Philip Homburg <philip@cs.vu.nl>
+
+.text
+.globl __longjmp
+__longjmp:
+	movl	4(%esp), %eax		# jmp_buf
+	cmpl	$0, 0(%eax)			# save mask?
+	je		1f
+	leal	4(%eax), %ebx		# pointer to sigset_t
+	pushl	%ebx
+	call	___oldsigset		# restore mask
+	addl	$4, %esp
+	movl	4(%esp), %eax		# jmp_buf
+1:	
+	movl	8(%esp), %ecx		# result value
+	movl	12(%eax), %esp 		# restore stack pointer
+
+	movl	8(%eax), %ebx 		# restore program counter
+	movl	%ebx, 0(%esp)
+
+	pushl	%ecx			# save result code
+	
+	movl	16(%eax), %ebp		# restore frame pointer
+	movl	20(%eax), %ebx
+	movl	24(%eax), %ecx
+	movl	28(%eax), %edx
+	movl	32(%eax), %esi
+	movl	36(%eax), %edi
+	pop	%eax
+	testl	%eax, %eax
+	jz	1f
+	ret
+1:	movl	$1, %eax
+	ret
+
+/ $PchId: _longjmp.gnu.s,v 1.4 1996/03/12 19:30:02 philip Exp $
Index: /trunk/minix/lib/gnu/rts/_setjmp.gs
===================================================================
--- /trunk/minix/lib/gnu/rts/_setjmp.gs	(revision 9)
+++ /trunk/minix/lib/gnu/rts/_setjmp.gs	(revision 9)
@@ -0,0 +1,32 @@
+/ _setjmp.gnu.s
+/
+/ Created:	Oct 14, 1993 by Philip Homburg <philip@cs.vu.nl>
+
+.text
+.globl ___setjmp
+___setjmp:
+	movl	4(%esp), %eax		# jmp_buf
+	movl	%ebx, 20(%eax)		# save ebx
+	movl	0(%esp), %ebx
+	movl	%ebx, 8(%eax)		# save program counter
+	movl	%esp, 12(%eax)		# save stack pointer
+	movl	%ebp, 16(%eax)		# save frame pointer
+	movl	20(%eax), %ebx 		# restore ebx
+	movl	%ecx, 24(%eax)
+	movl	%edx, 28(%eax)
+	movl	%esi, 32(%eax)
+	movl	%edi, 36(%eax)
+	
+	movl	8(%esp), %ebx		# save mask?
+	movl	%ebx, 0(%eax)		# save whether to restore mask
+	testl	%ebx, %ebx
+	jz		1f
+	leal	4(%eax), %ebx		# pointer to sigset_t
+	pushl	%ebx
+	call	___newsigset		# save mask	
+	addl	$4, %esp
+1:
+	movl	$0, %eax
+	ret
+
+/ $PchId: _setjmp.gnu.s,v 1.4 1996/03/12 19:30:54 philip Exp $
Index: /trunk/minix/lib/gnu/rts/longjmp.gs
===================================================================
--- /trunk/minix/lib/gnu/rts/longjmp.gs	(revision 9)
+++ /trunk/minix/lib/gnu/rts/longjmp.gs	(revision 9)
@@ -0,0 +1,6 @@
+	.text
+.globl	_longjmp
+_longjmp:
+	jmp	__longjmp
+
+/ $PchId: longjmp.gnu.s,v 1.4 1996/03/12 19:31:18 philip Exp $
Index: /trunk/minix/lib/gnu/rts/setjmp.gs
===================================================================
--- /trunk/minix/lib/gnu/rts/setjmp.gs	(revision 9)
+++ /trunk/minix/lib/gnu/rts/setjmp.gs	(revision 9)
@@ -0,0 +1,6 @@
+	.text
+.globl	_setjmp
+_setjmp:
+	jmp	___setjmp
+
+/ $PchId: setjmp.gnu.s,v 1.4 1996/03/12 19:31:18 philip Exp $
Index: /trunk/minix/lib/i386/Makefile
===================================================================
--- /trunk/minix/lib/i386/Makefile	(revision 9)
+++ /trunk/minix/lib/i386/Makefile	(revision 9)
@@ -0,0 +1,67 @@
+#Generated from ./i386/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./i386 ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./i386 ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+all-ack: makefiles
+	mkdir -p ../obj-ack//./i386/int64
+	cd int64 && $(MAKE) $@
+	mkdir -p ../obj-ack//./i386/misc
+	cd misc && $(MAKE) $@
+	mkdir -p ../obj-ack//./i386/rts
+	cd rts && $(MAKE) $@
+	mkdir -p ../obj-ack//./i386/string
+	cd string && $(MAKE) $@
+
+all-gnu: makefiles
+	mkdir -p ../obj-gnu/./i386/int64
+	cd int64 && $(MAKE) $@
+	mkdir -p ../obj-gnu/./i386/misc
+	cd misc && $(MAKE) $@
+	mkdir -p ../obj-gnu/./i386/rts
+	cd rts && $(MAKE) $@
+	mkdir -p ../obj-gnu/./i386/string
+	cd string && $(MAKE) $@
+
+clean depend depend-ack depend-gnu:: makefiles
+	cd int64 && $(MAKE) $@
+	cd misc && $(MAKE) $@
+	cd rts && $(MAKE) $@
+	cd string && $(MAKE) $@
+
+makefiles: int64/Makefile
+makefiles: misc/Makefile
+makefiles: rts/Makefile
+makefiles: string/Makefile
+
+int64/Makefile: int64/Makefile.in
+	cd int64 && sh ../../generate.sh ./i386/int64 ../../obj-ack/ ../../obj-gnu && $(MAKE) makefiles
+misc/Makefile: misc/Makefile.in
+	cd misc && sh ../../generate.sh ./i386/misc ../../obj-ack/ ../../obj-gnu && $(MAKE) makefiles
+rts/Makefile: rts/Makefile.in
+	cd rts && sh ../../generate.sh ./i386/rts ../../obj-ack/ ../../obj-gnu && $(MAKE) makefiles
+string/Makefile: string/Makefile.in
+	cd string && sh ../../generate.sh ./i386/string ../../obj-ack/ ../../obj-gnu && $(MAKE) makefiles
+
+clean::
+	rm -f ../obj-ack//./i386/*
+	rm -f ../obj-gnu/./i386/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/i386/Makefile.in
===================================================================
--- /trunk/minix/lib/i386/Makefile.in	(revision 9)
+++ /trunk/minix/lib/i386/Makefile.in	(revision 9)
@@ -0,0 +1,9 @@
+# Makefile for lib/i386.
+
+SUBDIRS="\
+	int64 \
+	misc \
+	rts \
+	string"
+
+TYPE=both
Index: /trunk/minix/lib/i386/em/byte_order.h
===================================================================
--- /trunk/minix/lib/i386/em/byte_order.h	(revision 9)
+++ /trunk/minix/lib/i386/em/byte_order.h	(revision 9)
@@ -0,0 +1,6 @@
+#define CHAR_UNSIGNED	0
+#define MSB_AT_LOW_ADDRESS	0
+#define MSW_AT_LOW_ADDRESS	0
+#define FL_MSB_AT_LOW_ADDRESS	0
+#define FL_MSW_AT_LOW_ADDRESS	0
+#define FL_MSL_AT_LOW_ADDRESS	0
Index: /trunk/minix/lib/i386/em/em_adf4.s
===================================================================
--- /trunk/minix/lib/i386/em/em_adf4.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_adf4.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .adf4
+
+	.sect .text
+.adf4:
+	mov	bx,sp
+	flds	4(bx)
+	fadds	8(bx)
+	fstps	8(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_adf8.s
===================================================================
--- /trunk/minix/lib/i386/em/em_adf8.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_adf8.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .adf8
+
+	.sect .text
+.adf8:
+	mov	bx,sp
+	fldd	4(bx)
+	faddd	12(bx)
+	fstpd	12(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_adi.s
===================================================================
--- /trunk/minix/lib/i386/em/em_adi.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_adi.s	(revision 9)
@@ -0,0 +1,18 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .adi
+
+	! #bytes in ecx , top of stack in eax
+	.sect .text
+.adi:
+	pop     ebx              ! return address
+	cmp     ecx,4
+	jne     9f
+	pop     ecx
+	add     eax,ecx
+	jmp     ebx
+9:
+.extern	EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push	ebx
+	jmp     .trp
Index: /trunk/minix/lib/i386/em/em_and.s
===================================================================
--- /trunk/minix/lib/i386/em/em_and.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_and.s	(revision 9)
@@ -0,0 +1,20 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define	.and
+
+	! #bytes in ecx
+	! save edi; it might be a register variable
+
+	.sect .text
+.and:
+	pop	ebx		! return address
+	mov	edx,edi
+	mov	edi,esp
+	add	edi,ecx
+	sar	ecx,2
+1:
+	pop	eax
+	and	eax,(edi)
+	stos
+	loop	1b
+	mov	edi,edx
+	jmp	ebx
Index: /trunk/minix/lib/i386/em/em_blm.s
===================================================================
--- /trunk/minix/lib/i386/em/em_blm.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_blm.s	(revision 9)
@@ -0,0 +1,16 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .blm
+
+	! ecx: count in words
+.blm:
+	mov	ebx,esp
+	mov	eax,esi
+	mov	edx,edi
+	mov	edi,4(ebx)
+	mov	esi,8(ebx)
+	rep	movs
+	mov	esi,eax
+	mov	edi,edx
+	ret	8
+
Index: /trunk/minix/lib/i386/em/em_cff4.s
===================================================================
--- /trunk/minix/lib/i386/em/em_cff4.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_cff4.s	(revision 9)
@@ -0,0 +1,19 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cff4
+
+	.sect .text
+.cff4:
+	mov	bx,sp
+	fldd	4(bx)
+	fstcw	4(bx)
+	wait
+	mov	dx,4(bx)
+	and	4(bx),0xf3ff	! set to rounding mode
+	wait
+	fldcw	4(bx)
+	fstps	8(bx)
+	mov	4(bx),dx
+	wait
+	fldcw	4(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_cff8.s
===================================================================
--- /trunk/minix/lib/i386/em/em_cff8.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_cff8.s	(revision 9)
@@ -0,0 +1,10 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cff8
+
+	.sect .text
+.cff8:
+	mov	bx,sp
+	flds	4(bx)
+	fstpd	4(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_cfi.s
===================================================================
--- /trunk/minix/lib/i386/em/em_cfi.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_cfi.s	(revision 9)
@@ -0,0 +1,27 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cfi
+
+	.sect .text
+.cfi:
+	mov	bx,sp
+	fstcw	4(bx)
+	wait
+	mov	dx,4(bx)
+	or	4(bx),0xc00	! truncating mode
+	wait
+	fldcw	4(bx)
+	cmp	8(bx),4
+	jne	2f
+				! loc 4 loc ? cfi
+	flds	12(bx)
+	fistpl	12(bx)
+1:
+	mov	4(bx),dx
+	wait
+	fldcw	4(bx)
+	ret
+2:
+				! loc 8 loc ? cfi
+	fldd	12(bx)
+	fistpl	16(bx)
+	jmp	1b
Index: /trunk/minix/lib/i386/em/em_cfu.s
===================================================================
--- /trunk/minix/lib/i386/em/em_cfu.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_cfu.s	(revision 9)
@@ -0,0 +1,38 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cfu
+
+	.sect .text
+.cfu:
+	mov	bx,sp
+	fstcw	4(bx)
+	wait
+	mov	dx,4(bx)
+	or	4(bx),0xc00	! truncating mode
+	wait
+	fldcw	4(bx)
+	cmp	8(bx),4
+	jne	2f
+				! loc 4 loc ? cfu
+	flds	12(bx)
+	fabs			! ???
+	fiaddl	(bigmin)
+	fistpl	12(bx)
+	wait
+	mov	ax,12(bx)
+	sub	ax,(bigmin)
+	mov	12(bx),ax
+1:
+	mov	4(bx),dx
+	wait
+	fldcw	4(bx)
+	ret
+2:
+				! loc 8 loc ? cfu
+	fldd	12(bx)
+	fabs			! ???
+	fiaddl	(bigmin)
+	fistpl	16(bx)
+	mov	ax,16(bx)
+	sub	ax,(bigmin)
+	mov	16(bx),ax
+	jmp	1b
Index: /trunk/minix/lib/i386/em/em_cif4.s
===================================================================
--- /trunk/minix/lib/i386/em/em_cif4.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_cif4.s	(revision 9)
@@ -0,0 +1,10 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cif4
+
+	.sect .text
+.cif4:
+	mov	bx,sp
+	fildl	8(bx)
+	fstps	8(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_cif8.s
===================================================================
--- /trunk/minix/lib/i386/em/em_cif8.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_cif8.s	(revision 9)
@@ -0,0 +1,10 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cif8
+
+	.sect .text
+.cif8:
+	mov	bx,sp
+	fildl	8(bx)
+	fstpd	4(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_cii.s
===================================================================
--- /trunk/minix/lib/i386/em/em_cii.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_cii.s	(revision 9)
@@ -0,0 +1,31 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cii
+
+.sect .text
+.cii:
+	pop     ebx              ! return address
+				! pop     ecx, dest. size
+				! pop     edx, src. size
+				! eax is source
+	cmp	edx,1
+	jne	2f
+	movsxb	eax,al
+	mov	edx,4
+	jmp	1f
+2:
+	cmp	edx,2
+	jne	1f
+	cwde			! convert from 2 to 4 bytes
+	mov	edx,4
+1:
+	cmp     edx,ecx
+	jne     9f
+	cmp	edx,4
+	jne	9f
+	jmp     ebx
+9:
+.extern EILLINS
+.extern .fat
+	mov     eax,EILLINS
+	push    eax
+	jmp     .fat
Index: /trunk/minix/lib/i386/em/em_cmf4.s
===================================================================
--- /trunk/minix/lib/i386/em/em_cmf4.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_cmf4.s	(revision 9)
@@ -0,0 +1,22 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cmf4
+
+	.sect .text
+.cmf4:
+	mov	bx,sp
+	xor	cx,cx
+	flds	8(bx)
+	flds	4(bx)
+	fcompp			! compare and pop operands
+	fstsw	ax
+	wait
+	sahf
+	je	1f
+	jb	2f
+	dec	cx
+	jmp	1f
+2:
+	inc	cx
+1:
+	mov	ax,cx
+	ret
Index: /trunk/minix/lib/i386/em/em_cmf8.s
===================================================================
--- /trunk/minix/lib/i386/em/em_cmf8.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_cmf8.s	(revision 9)
@@ -0,0 +1,22 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cmf8
+
+	.sect .text
+.cmf8:
+	mov	bx,sp
+	xor	cx,cx
+	fldd	12(bx)
+	fldd	4(bx)
+	fcompp			! compare and pop operands
+	fstsw	ax
+	wait
+	sahf
+	je	1f
+	jb	2f
+	dec	cx
+	jmp	1f
+2:
+	inc	cx
+1:
+	mov	ax,cx
+	ret
Index: /trunk/minix/lib/i386/em/em_cms.s
===================================================================
--- /trunk/minix/lib/i386/em/em_cms.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_cms.s	(revision 9)
@@ -0,0 +1,23 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cms
+
+	! #bytes in ecx
+	.sect .text
+.cms:
+	pop     ebx              ! return address
+	mov     edx,esp
+	push	esi
+	push	edi
+	mov     esi,edx
+	add     edx,ecx
+	mov     edi,edx
+	add     edx,ecx
+	sar     ecx,2
+	repe cmps
+	je      1f
+	inc     ecx
+1:
+	pop	edi
+	pop	esi
+	mov     esp,edx
+	jmp     ebx
Index: /trunk/minix/lib/i386/em/em_com.s
===================================================================
--- /trunk/minix/lib/i386/em/em_com.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_com.s	(revision 9)
@@ -0,0 +1,14 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define	.com
+
+	! #bytes in ecx
+	.sect .text
+.com:
+	mov	ebx,esp
+	add	ebx,4
+	sar	ecx,2
+1:
+	not	(ebx)
+	add	ebx,4
+	loop	1b
+	ret
Index: /trunk/minix/lib/i386/em/em_csa4.s
===================================================================
--- /trunk/minix/lib/i386/em/em_csa4.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_csa4.s	(revision 9)
@@ -0,0 +1,27 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .csa4
+
+.sect .text
+.csa4:
+				! ebx, descriptor address
+				! eax, index
+	mov     edx,(ebx)         ! default
+	sub     eax,4(ebx)
+	cmp     eax,8(ebx)
+	ja      1f
+	sal     eax,2
+	add	ebx,eax
+	mov     ebx,12(ebx)
+	test    ebx,ebx
+	jnz     2f
+1:
+	mov     ebx,edx
+	test    ebx,ebx
+	jnz     2f
+.extern ECASE
+.extern .fat
+	mov     eax,ECASE
+	push    eax
+	jmp     .fat
+2:
+	jmp     ebx
Index: /trunk/minix/lib/i386/em/em_csb4.s
===================================================================
--- /trunk/minix/lib/i386/em/em_csb4.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_csb4.s	(revision 9)
@@ -0,0 +1,29 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .csb4
+
+.sect .text
+.csb4:
+				!ebx, descriptor address
+				!eax,  index
+	mov	edx,(ebx)
+	mov	ecx,4(ebx)
+1:
+	add	ebx,8
+	dec     ecx
+	jl      4f
+	cmp     eax,(ebx)
+	jne     1b
+	mov	ebx,4(ebx)
+2:
+	test    ebx,ebx
+	jnz     3f
+.extern ECASE
+.extern .fat
+	mov     eax,ECASE
+	push    eax
+	jmp     .fat
+3:
+	jmp     ebx
+4:
+	mov	ebx,edx
+	jmp	2b
Index: /trunk/minix/lib/i386/em/em_cuf4.s
===================================================================
--- /trunk/minix/lib/i386/em/em_cuf4.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_cuf4.s	(revision 9)
@@ -0,0 +1,15 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cuf4
+
+	.sect .text
+.cuf4:
+	mov	bx,sp
+	fildl	8(bx)
+	cmp	8(bx),0
+	jge	1f
+	fisubl	(bigmin)
+	fisubl	(bigmin)
+1:
+	fstps	8(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_cuf8.s
===================================================================
--- /trunk/minix/lib/i386/em/em_cuf8.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_cuf8.s	(revision 9)
@@ -0,0 +1,15 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .cuf8
+
+	.sect .text
+.cuf8:
+	mov	bx,sp
+	fildl	8(bx)
+	cmp	8(bx),0
+	jge	1f
+	fisubl	(bigmin)
+	fisubl	(bigmin)
+1:
+	fstpd	4(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_cuu.s
===================================================================
--- /trunk/minix/lib/i386/em/em_cuu.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_cuu.s	(revision 9)
@@ -0,0 +1,22 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .ciu
+.define .cui
+.define .cuu
+
+.sect .text
+.ciu:
+.cui:
+.cuu:
+	pop     ebx              ! return address
+				! pop     ecx, dest. size
+				! pop     edx, source size
+				! eax is source
+	cmp     edx,ecx
+	jne     8f
+	jmp     ebx
+8:
+.extern EILLINS
+.extern .fat
+	mov     eax,EILLINS
+	push    eax
+	jmp     .fat
Index: /trunk/minix/lib/i386/em/em_dup.s
===================================================================
--- /trunk/minix/lib/i386/em/em_dup.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_dup.s	(revision 9)
@@ -0,0 +1,17 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define	.dup
+
+	! #bytes in ecx
+	.sect .text
+.dup:
+	pop	ebx		! return address
+	mov	eax,esi
+	mov	edx,edi
+	mov	esi,esp
+	sub	esp,ecx
+	mov	edi,esp
+	sar	ecx,2
+	rep movs
+	mov	esi,eax
+	mov	edi,edx
+	jmp	ebx
Index: /trunk/minix/lib/i386/em/em_dvf4.s
===================================================================
--- /trunk/minix/lib/i386/em/em_dvf4.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_dvf4.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .dvf4
+
+	.sect .text
+.dvf4:
+	mov	bx,sp
+	flds	8(bx)
+	fdivs	4(bx)
+	fstps	8(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_dvf8.s
===================================================================
--- /trunk/minix/lib/i386/em/em_dvf8.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_dvf8.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .dvf8
+
+	.sect .text
+.dvf8:
+	mov	bx,sp
+	fldd	12(bx)
+	fdivd	4(bx)
+	fstpd	12(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_dvi.s
===================================================================
--- /trunk/minix/lib/i386/em/em_dvi.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_dvi.s	(revision 9)
@@ -0,0 +1,21 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .dvi
+
+        ! #bytes in eax
+	.sect .text
+.dvi:
+        pop     ebx              ! return address
+        cmp     eax,4
+        jne     1f
+        pop     eax
+        cwd
+        pop     ecx
+        idiv    ecx
+        push    eax
+        jmp     ebx
+1:
+.extern EODDZ
+.extern .trp
+        mov     eax,EODDZ
+        push    ebx
+        jmp     .trp
Index: /trunk/minix/lib/i386/em/em_dvu.s
===================================================================
--- /trunk/minix/lib/i386/em/em_dvu.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_dvu.s	(revision 9)
@@ -0,0 +1,21 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .dvu
+
+	! #bytes in eax
+	.sect .text
+.dvu:
+	pop     ebx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	xor     edx,edx
+	pop     ecx
+	div     ecx
+	push    eax
+	jmp     ebx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    ebx
+	jmp     .trp
Index: /trunk/minix/lib/i386/em/em_error.s
===================================================================
--- /trunk/minix/lib/i386/em/em_error.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_error.s	(revision 9)
@@ -0,0 +1,32 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .error
+.define .Xtrp
+
+	! eax is trap number
+	! all registers must be saved
+	! because return is possible
+	! May only be called with error no's <16
+.sect .text
+.error:
+	mov  ecx,eax
+	mov  ebx,1
+	sal  ebx,cl
+.extern .ignmask
+.extern .trp
+	test ebx,(.ignmask)
+	jne  2f
+	call    .trp
+2:
+	ret
+
+.Xtrp:
+	pusha
+	cmp	eax,16
+	jge	1f
+	call	.error
+	popa
+	ret
+1:
+	call	.trp
+	popa
+	ret
Index: /trunk/minix/lib/i386/em/em_exg.s
===================================================================
--- /trunk/minix/lib/i386/em/em_exg.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_exg.s	(revision 9)
@@ -0,0 +1,22 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .exg
+
+	! #bytes in ecx
+.sect .text
+.exg:
+	push	edi
+	mov	edi,esp
+	add	edi,8
+	mov	ebx,edi
+	add	ebx,ecx
+	sar     ecx,2
+1:
+	mov	eax,(ebx)
+	xchg	eax,(edi)
+	mov	(ebx),eax
+	add	edi,4
+	add	ebx,4
+	loop	1b
+2:
+	pop	edi
+	ret
Index: /trunk/minix/lib/i386/em/em_fat.s
===================================================================
--- /trunk/minix/lib/i386/em/em_fat.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_fat.s	(revision 9)
@@ -0,0 +1,10 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .fat
+
+.fat:
+.extern .trp
+.extern .stop
+	call    .trp
+	call    .stop
+	! no return
Index: /trunk/minix/lib/i386/em/em_fef4.s
===================================================================
--- /trunk/minix/lib/i386/em/em_fef4.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_fef4.s	(revision 9)
@@ -0,0 +1,49 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .fef4
+
+	.sect .text
+.fef4:
+				! this could be simpler, if only the
+				! fxtract instruction was emulated properly
+	mov	bx,sp
+	mov	ax,8(bx)
+	and	ax,0x7f800000
+	je	1f		! zero exponent
+	shr	ax,23
+	sub	ax,126
+	mov	cx,ax		! exponent in cx
+	mov	ax,8(bx)
+	and	ax,0x807fffff
+	or	ax,0x3f000000	! load -1 exponent
+	mov	bx,4(bx)
+	mov	4(bx),ax
+	mov	(bx),cx
+	ret
+1:				! we get here on zero exp
+	mov	ax,8(bx)
+	and	ax,0x007fffff
+	jne	1f		! zero result
+	mov	bx,4(bx)
+	mov	(bx),ax
+	mov	4(bx),ax
+	ret
+1:				! otherwise unnormalized number
+	mov	cx,8(bx)
+	and	cx,0x807fffff
+	mov	dx,cx
+	and	cx,0x80000000
+	mov	ax,-125
+2:
+	test	dx,0x800000
+	jne	1f
+	dec	ax
+	shl	dx,1
+	or	dx,cx
+	jmp	2b
+1:
+	mov	bx,4(bx)
+	mov	(bx),ax
+	and	dx,0x807fffff
+	or	dx,0x3f000000	! load -1 exponent
+	mov	4(bx),dx
+	ret
Index: /trunk/minix/lib/i386/em/em_fef8.s
===================================================================
--- /trunk/minix/lib/i386/em/em_fef8.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_fef8.s	(revision 9)
@@ -0,0 +1,56 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .fef8
+
+	.sect .text
+.fef8:
+				! this could be simpler, if only the
+				! fxtract instruction was emulated properly
+	mov	bx,sp
+	mov	ax,12(bx)
+	and	ax,0x7ff00000
+	je	1f		! zero exponent
+	shr	ax,20
+	sub	ax,1022
+	mov	cx,ax		! exponent in cx
+	mov	ax,12(bx)
+	and	ax,0x800fffff
+	or	ax,0x3fe00000	! load -1 exponent
+	mov	dx,8(bx)
+	mov	bx,4(bx)
+	mov	4(bx),dx
+	mov	8(bx),ax
+	mov	(bx),cx
+	ret
+1:				! we get here on zero exp
+	mov	ax,12(bx)
+	and	ax,0xfffff
+	or	ax,8(bx)
+	jne	1f		! zero result
+	mov	bx,4(bx)
+	mov	(bx),ax
+	mov	4(bx),ax
+	mov	8(bx),ax
+	ret
+1:				! otherwise unnormalized number
+	mov	cx,12(bx)
+	and	cx,0x800fffff
+	mov	dx,cx
+	and	cx,0x80000000
+	mov	ax,-1021
+2:
+	test	dx,0x100000
+	jne	1f
+	dec	ax
+	shl	8(bx),1
+	rcl	dx,1
+	or	dx,cx
+	jmp	2b
+1:
+	and	dx,0x800fffff
+	or	dx,0x3fe00000	! load -1 exponent
+	mov	cx,8(bx)
+	mov	bx,4(bx)
+	mov	(bx),ax
+	mov	8(bx),dx
+	mov	4(bx),cx
+	ret
Index: /trunk/minix/lib/i386/em/em_fif4.s
===================================================================
--- /trunk/minix/lib/i386/em/em_fif4.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_fif4.s	(revision 9)
@@ -0,0 +1,37 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .fif4
+
+	.sect .text
+.fif4:
+	mov	bx,sp
+	flds	8(bx)
+	fmuls	12(bx)		! multiply
+	fld	st		! copy result
+	ftst			! test sign; handle negative separately
+	fstsw	ax
+	wait
+	sahf			! result of test in condition codes
+	jb	1f
+	frndint			! this one rounds (?)
+	fcom	st(1)		! compare with original; if <=, then OK
+	fstsw	ax
+	wait
+	sahf
+	jbe	2f
+	fisubs	(one)		! else subtract 1
+	jmp	2f
+1:				! here, negative case
+	frndint			! this one rounds (?)
+	fcom	st(1)		! compare with original; if >=, then OK
+	fstsw	ax
+	wait
+	sahf
+	jae	2f
+	fiadds	(one)		! else add 1
+2:
+	fsub	st(1),st	! subtract integer part
+	mov	bx,4(bx)
+	fstps	(bx)
+	fstps	4(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_fif8.s
===================================================================
--- /trunk/minix/lib/i386/em/em_fif8.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_fif8.s	(revision 9)
@@ -0,0 +1,37 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .fif8
+
+	.sect .text
+.fif8:
+	mov	bx,sp
+	fldd	8(bx)
+	fmuld	16(bx)		! multiply
+	fld	st		! and copy result
+	ftst			! test sign; handle negative separately
+	fstsw	ax
+	wait
+	sahf			! result of test in condition codes
+	jb	1f
+	frndint			! this one rounds (?)
+	fcom	st(1)		! compare with original; if <=, then OK
+	fstsw	ax
+	wait
+	sahf
+	jbe	2f
+	fisubs	(one)		! else subtract 1
+	jmp	2f
+1:				! here, negative case
+	frndint			! this one rounds (?)
+	fcom	st(1)		! compare with original; if >=, then OK
+	fstsw	ax
+	wait
+	sahf
+	jae	2f
+	fiadds	(one)		! else add 1
+2:
+	fsub	st(1),st	! subtract integer part
+	mov	bx,4(bx)
+	fstpd	(bx)
+	fstpd	8(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_fp8087.s
===================================================================
--- /trunk/minix/lib/i386/em/em_fp8087.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_fp8087.s	(revision 9)
@@ -0,0 +1,10 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define one, bigmin
+
+	.sect .rom
+one:
+	.data2	1
+two:
+	.data2	2
+bigmin:
+	.data4 	-2147483648
Index: /trunk/minix/lib/i386/em/em_gto.s
===================================================================
--- /trunk/minix/lib/i386/em/em_gto.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_gto.s	(revision 9)
@@ -0,0 +1,8 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .gto
+
+.gto:
+	mov     ebp,8(ebx)
+	mov     esp,4(ebx)
+	jmp     (ebx)
Index: /trunk/minix/lib/i386/em/em_hol0.s
===================================================================
--- /trunk/minix/lib/i386/em/em_hol0.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_hol0.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+.define hol0
+.sect .data
+hol0:
+	.data4	0, 0
+	.data4	0, 0
Index: /trunk/minix/lib/i386/em/em_iaar.s
===================================================================
--- /trunk/minix/lib/i386/em/em_iaar.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_iaar.s	(revision 9)
@@ -0,0 +1,18 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .iaar
+
+.iaar:
+	pop     ecx
+	pop     edx
+	cmp     edx,4
+.extern .unknown
+	jne     .unknown
+	pop     ebx     ! descriptor address
+	pop     eax     ! index
+	sub     eax,(ebx)
+	mul     8(ebx)
+	pop	ebx	! array base
+	add     ebx,eax
+	push	ecx
+	ret
Index: /trunk/minix/lib/i386/em/em_ilar.s
===================================================================
--- /trunk/minix/lib/i386/em/em_ilar.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_ilar.s	(revision 9)
@@ -0,0 +1,15 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .ilar
+
+.ilar:
+	pop     ecx
+	pop     edx
+.extern .unknown
+	cmp     edx,4
+	jne     .unknown
+	pop     ebx      ! descriptor address
+	pop     eax      ! index
+	push    ecx
+.extern .lar4
+	jmp    .lar4
Index: /trunk/minix/lib/i386/em/em_inn.s
===================================================================
--- /trunk/minix/lib/i386/em/em_inn.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_inn.s	(revision 9)
@@ -0,0 +1,32 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .inn
+
+	! #bytes in ecx
+	! bit # in eax
+.inn:
+	xor     edx,edx
+	mov     ebx,8
+	div     ebx
+	mov     ebx,esp
+	add	ebx,4
+	add     ebx,eax
+	cmp     eax,ecx
+	jae     1f
+	movb	al,(ebx)
+	mov	ebx,edx
+	testb   al,bits(ebx)
+	jz      1f
+	mov	eax,1
+	jmp	2f
+1:
+	xor	eax,eax
+2:
+	pop	ebx
+	add     esp,ecx
+	! eax is result
+	jmp     ebx
+
+	.sect .rom
+bits:
+	.data1 1,2,4,8,16,32,64,128
Index: /trunk/minix/lib/i386/em/em_ior.s
===================================================================
--- /trunk/minix/lib/i386/em/em_ior.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_ior.s	(revision 9)
@@ -0,0 +1,18 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define	.ior
+
+	! #bytes in ecx
+.ior:
+	pop	ebx		! return address
+	mov	edx,edi
+	mov	edi,esp
+	add	edi,ecx
+	sar	ecx,2
+1:
+	pop	eax
+	or	eax,(edi)
+	stos
+	loop	1b
+	mov	edi,edx
+	jmp	ebx
Index: /trunk/minix/lib/i386/em/em_isar.s
===================================================================
--- /trunk/minix/lib/i386/em/em_isar.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_isar.s	(revision 9)
@@ -0,0 +1,15 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .isar
+
+.isar:
+	pop     ecx
+	pop     eax
+	cmp     eax,4
+.extern .unknown
+	jne     .unknown
+	pop     ebx      ! descriptor address
+	pop     eax      ! index
+	push    ecx
+.extern .sar4
+	jmp    .sar4
Index: /trunk/minix/lib/i386/em/em_lar4.s
===================================================================
--- /trunk/minix/lib/i386/em/em_lar4.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_lar4.s	(revision 9)
@@ -0,0 +1,37 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .lar4
+
+.lar4:
+				! ebx, descriptor address
+				! eax, index
+	sub     eax,(ebx)
+	mov     ecx,8(ebx)
+	imul    ecx
+	pop	ebx
+	pop	edx		! base address
+	add     edx,eax
+	sar     ecx,1
+	jnb     1f
+	xor     eax,eax
+	movb	al,(edx)
+	push    eax
+	jmp     ebx
+1:
+	sar     ecx,1
+	jnb     1f
+	xor     eax,eax
+	o16 mov	ax,(edx)
+	push    eax
+	jmp     ebx
+1:
+	xchg	edx,esi		! saved esi
+	mov	eax,ecx
+	sal	eax,2
+	sub     esp,eax
+	mov	eax,edi		! save edi
+	mov     edi,esp
+	rep movs
+	mov	edi,eax
+	mov	esi,edx
+	jmp     ebx
Index: /trunk/minix/lib/i386/em/em_loi.s
===================================================================
--- /trunk/minix/lib/i386/em/em_loi.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_loi.s	(revision 9)
@@ -0,0 +1,44 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .loi
+.define .los
+
+	! #bytes in ecx
+	! address in ebx
+	! save esi/edi. they might be register variables
+.los:
+	pop	edx
+	mov     eax,ecx
+	sar     ecx,1
+	jnb     1f
+	movsxb	eax,(ebx)
+	push    eax
+	jmp     edx
+1:
+	sar     ecx,1
+	jnb     1f
+	movsx	eax,(ebx)
+	push    eax
+	jmp     edx
+1:
+	push	edx
+	mov	edx,esi
+	mov	esi,ebx
+	pop	ebx
+	sub     esp,eax
+	jmp	1f
+
+.loi:
+	! only called with size >= 4
+	mov	edx,esi
+	mov	esi,ebx
+	pop	ebx
+	sub	esp,ecx
+	sar	ecx,2
+1:
+	mov	eax,edi
+	mov     edi,esp
+	rep movs
+	mov	esi,edx
+	mov	edi,eax
+	jmp     ebx
Index: /trunk/minix/lib/i386/em/em_mlf4.s
===================================================================
--- /trunk/minix/lib/i386/em/em_mlf4.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_mlf4.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .mlf4
+
+	.sect .text
+.mlf4:
+	mov	bx,sp
+	flds	4(bx)
+	fmuls	8(bx)
+	fstps	8(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_mlf8.s
===================================================================
--- /trunk/minix/lib/i386/em/em_mlf8.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_mlf8.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .mlf8
+
+	.sect .text
+.mlf8:
+	mov	bx,sp
+	fldd	4(bx)
+	fmuld	12(bx)
+	fstpd	12(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_mli.s
===================================================================
--- /trunk/minix/lib/i386/em/em_mli.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_mli.s	(revision 9)
@@ -0,0 +1,20 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .mli
+
+	! #bytes in eax
+.mli:
+	pop     ebx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	pop     ecx
+	mul     ecx
+	push    eax
+	jmp     ebx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    ebx
+	jmp     .trp
Index: /trunk/minix/lib/i386/em/em_mon.s
===================================================================
--- /trunk/minix/lib/i386/em/em_mon.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_mon.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .mon
+
+.mon:
+.extern .stop
+	call    .stop
Index: /trunk/minix/lib/i386/em/em_ngf4.s
===================================================================
--- /trunk/minix/lib/i386/em/em_ngf4.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_ngf4.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .ngf4
+
+	.sect .text
+.ngf4:
+	mov	bx,sp
+	flds	4(bx)
+	fchs
+	fstps	4(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_ngf8.s
===================================================================
--- /trunk/minix/lib/i386/em/em_ngf8.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_ngf8.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .ngf8
+
+	.sect .text
+.ngf8:
+	mov	bx,sp
+	fldd	4(bx)
+	fchs
+	fstpd	4(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_ngi.s
===================================================================
--- /trunk/minix/lib/i386/em/em_ngi.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_ngi.s	(revision 9)
@@ -0,0 +1,19 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .ngi
+
+	! #bytes in eax
+.ngi:
+	pop     ebx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     ecx
+	neg     ecx
+	push    ecx
+	jmp     ebx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    ebx
+	jmp     .trp
Index: /trunk/minix/lib/i386/em/em_nop.s
===================================================================
--- /trunk/minix/lib/i386/em/em_nop.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_nop.s	(revision 9)
@@ -0,0 +1,10 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .nop
+.extern printd, printc, hol0
+
+.nop:
+	mov     eax,(hol0)
+	call    printd
+	movb    al,'\n'
+	jmp     printc
Index: /trunk/minix/lib/i386/em/em_print.s
===================================================================
--- /trunk/minix/lib/i386/em/em_print.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_print.s	(revision 9)
@@ -0,0 +1,47 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define	printc,printd,prints
+
+	! argument in eax
+	! uses ebx
+prints:
+	xchg	eax,ebx
+1:
+	movb	al,(ebx)
+	inc	ebx
+	testb	al,al
+	jz	2f
+	call	printc
+	jmp	1b
+2:
+	ret
+
+	! argument in eax
+	! uses ecx and edx
+printd:
+	xor	edx,edx
+	mov	ecx,10
+	div	ecx
+	test	eax,eax
+	jz	1f
+	push	edx
+	call	printd
+	pop	edx
+1:
+	xchg	eax,edx
+	addb	al,'0'
+
+	! argument in eax
+printc:
+	push	eax
+	mov	ebx,esp
+	mov	eax,1
+	push	eax
+	push	ebx
+	push	eax
+	call	__write
+	pop	ebx
+	pop	ebx
+	pop	ebx
+	pop	ebx
+	ret
Index: /trunk/minix/lib/i386/em/em_rck.s
===================================================================
--- /trunk/minix/lib/i386/em/em_rck.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_rck.s	(revision 9)
@@ -0,0 +1,20 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .rck
+
+	! descriptor address in ebx
+	! value in eax, must be left there
+.rck:
+	cmp     eax,(ebx)
+	jl      2f
+	cmp     eax,4(ebx)
+	jg      2f
+	ret
+2:
+	push    eax
+.extern ERANGE
+.extern .error
+	mov     eax,ERANGE
+	call    .error
+	pop     eax
+	ret
Index: /trunk/minix/lib/i386/em/em_rmi.s
===================================================================
--- /trunk/minix/lib/i386/em/em_rmi.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_rmi.s	(revision 9)
@@ -0,0 +1,21 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .rmi
+
+	! #bytes in eax
+.rmi:
+	pop     ebx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	cwd
+	pop     ecx
+	idiv    ecx
+	push    edx
+	jmp     ebx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    ebx
+	jmp     .trp
Index: /trunk/minix/lib/i386/em/em_rmu.s
===================================================================
--- /trunk/minix/lib/i386/em/em_rmu.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_rmu.s	(revision 9)
@@ -0,0 +1,21 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .rmu
+
+	! #bytes in eax
+.rmu:
+	pop     ebx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	xor     edx,edx
+	pop     ecx
+	idiv    ecx
+	push    edx
+	jmp     ebx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    ebx
+	jmp     .trp
Index: /trunk/minix/lib/i386/em/em_rol.s
===================================================================
--- /trunk/minix/lib/i386/em/em_rol.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_rol.s	(revision 9)
@@ -0,0 +1,20 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .rol
+
+	! #bytes in eax
+.rol:
+	pop     edx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	pop     ecx
+	rol     eax,cl
+	push    eax
+	jmp     edx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    edx
+	jmp     .trp
Index: /trunk/minix/lib/i386/em/em_ror.s
===================================================================
--- /trunk/minix/lib/i386/em/em_ror.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_ror.s	(revision 9)
@@ -0,0 +1,20 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .ror
+
+	! #bytes in eax
+.ror:
+	pop     edx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	pop     ecx
+	ror     eax,cl
+	push    eax
+	jmp     edx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    edx
+	jmp     .trp
Index: /trunk/minix/lib/i386/em/em_sar4.s
===================================================================
--- /trunk/minix/lib/i386/em/em_sar4.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_sar4.s	(revision 9)
@@ -0,0 +1,33 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .sar4
+
+.sar4:
+				! ebx, descriptor address
+				! eax, index
+	sub     eax,(ebx)
+	mov     ecx,8(ebx)
+	imul    ecx
+	pop	ebx
+	pop	edx		! base address
+	add     edx,eax
+	sar     ecx,1
+	jnb     1f
+	pop     eax
+	movb	(edx),al
+	jmp     ebx
+1:
+	sar     ecx,1
+	jnb     1f
+	pop     eax
+	o16 mov (edx),ax
+	jmp     ebx
+1:
+	xchg	edi,edx		! edi = base address, edx is saved edi
+	mov	eax,esi
+	mov     esi,esp
+	rep movs
+	mov     esp,esi
+	mov	esi,eax
+	mov	edi,edx
+	jmp     ebx
Index: /trunk/minix/lib/i386/em/em_sbf4.s
===================================================================
--- /trunk/minix/lib/i386/em/em_sbf4.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_sbf4.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .sbf4
+
+	.sect .text
+.sbf4:
+	mov	bx,sp
+	flds	8(bx)
+	fsubs	4(bx)
+	fstps	8(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_sbf8.s
===================================================================
--- /trunk/minix/lib/i386/em/em_sbf8.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_sbf8.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .sbf8
+
+	.sect .text
+.sbf8:
+	mov	bx,sp
+	fldd	12(bx)
+	fsubd	4(bx)
+	fstpd	12(bx)
+	wait
+	ret
Index: /trunk/minix/lib/i386/em/em_sbi.s
===================================================================
--- /trunk/minix/lib/i386/em/em_sbi.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_sbi.s	(revision 9)
@@ -0,0 +1,19 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .sbi
+
+	! #bytes in ecx , top of stack in eax
+.sbi:
+	pop     ebx              ! return subress
+	cmp     ecx,4
+	jne     1f
+	pop     ecx
+	sub     eax,ecx
+	neg     eax
+	jmp     ebx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    ebx
+	jmp     .trp
Index: /trunk/minix/lib/i386/em/em_set.s
===================================================================
--- /trunk/minix/lib/i386/em/em_set.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_set.s	(revision 9)
@@ -0,0 +1,42 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .set
+
+	! #bytes in ecx
+	! bit # in eax
+.set:
+	pop     ebx              ! return address
+	xor     edx,edx
+!ifdef create set
+	sub	esp,ecx
+	push	ebx
+	push	edi
+	mov     ebx,esp
+	xor	edi,edi
+	sar	ecx,2
+1:
+	mov     8(ebx)(edi),edx
+	add	edi,4
+	loop	1b
+!endif
+	mov     ebx,8
+	div     ebx
+	cmp     eax,edi
+	jae     2f
+	mov	edi,edx
+	movb	dl,bits(edi)
+	mov     edi,esp
+	add     edi,eax
+	orb     8(edi),dl
+	pop	edi
+	ret
+2:
+.extern ESET
+.extern .trp
+	pop	edi
+	mov     eax,ESET
+	jmp     .trp
+
+	.sect .rom
+bits:
+	.data1   1,2,4,8,16,32,64,128
Index: /trunk/minix/lib/i386/em/em_sli.s
===================================================================
--- /trunk/minix/lib/i386/em/em_sli.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_sli.s	(revision 9)
@@ -0,0 +1,20 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .sli
+
+	! #bytes in eax
+.sli:
+	pop     edx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	pop     ecx
+	sal     eax,cl
+	push    eax
+	jmp     edx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    edx
+	jmp     .trp
Index: /trunk/minix/lib/i386/em/em_sri.s
===================================================================
--- /trunk/minix/lib/i386/em/em_sri.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_sri.s	(revision 9)
@@ -0,0 +1,20 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .sri
+
+	! #bytes in eax
+.sri:
+	pop     edx              ! return address
+	cmp     eax,4
+	jne     1f
+	pop     eax
+	pop     ecx
+	sar     eax,cl
+	push    eax
+	jmp     edx
+1:
+.extern EODDZ
+.extern .trp
+	mov     eax,EODDZ
+	push    edx
+	jmp     .trp
Index: /trunk/minix/lib/i386/em/em_sti.s
===================================================================
--- /trunk/minix/lib/i386/em/em_sti.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_sti.s	(revision 9)
@@ -0,0 +1,41 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .sti
+.define .sts
+
+	! #bytes in ecx
+	! address in ebx
+	! save edi/esi. they might be register variables
+.sts:
+	pop	edx
+	sar     ecx,1
+	jnb     1f
+	pop     eax
+	movb	(ebx),al
+	jmp     edx
+1:
+	sar     ecx,1
+	jnb     1f
+	pop     eax
+	o16 mov	(ebx),ax
+	jmp     edx
+1:
+	push	edx
+	mov	edx,edi
+	mov	edi,ebx
+	pop	ebx
+	jmp	1f
+.sti:
+	! only called with count >> 4
+	mov	edx,edi
+	mov	edi,ebx
+	pop	ebx
+	sar	ecx,2
+1:
+	mov	eax,esi
+	mov     esi,esp
+	rep movs
+	mov     esp,esi
+	mov	edi,edx
+	mov	esi,eax
+	jmp     ebx
Index: /trunk/minix/lib/i386/em/em_stop.s
===================================================================
--- /trunk/minix/lib/i386/em/em_stop.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_stop.s	(revision 9)
@@ -0,0 +1,5 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .stop
+.stop:
+	jmp	___exit
Index: /trunk/minix/lib/i386/em/em_trp.s
===================================================================
--- /trunk/minix/lib/i386/em/em_trp.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_trp.s	(revision 9)
@@ -0,0 +1,18 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .trp
+.extern .trppc, .stop
+
+		! eax is trap number
+.trp:
+	xor     ebx,ebx
+	xchg    ebx,(.trppc)
+	test    ebx,ebx
+	jz      2f
+	push    eax
+	call    ebx
+	pop     eax
+	ret
+2:
+	push	eax
+	call    .stop
Index: /trunk/minix/lib/i386/em/em_unknown.s
===================================================================
--- /trunk/minix/lib/i386/em/em_unknown.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_unknown.s	(revision 9)
@@ -0,0 +1,9 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define .unknown
+.extern EILLINS, .fat
+
+.unknown:
+	mov  eax,EILLINS
+	push eax
+	jmp  .fat
Index: /trunk/minix/lib/i386/em/em_xor.s
===================================================================
--- /trunk/minix/lib/i386/em/em_xor.s	(revision 9)
+++ /trunk/minix/lib/i386/em/em_xor.s	(revision 9)
@@ -0,0 +1,18 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define	.xor
+
+	! #bytes in ecx
+.xor:
+	pop	ebx		! return address
+	mov	edx,edi
+	mov	edi,esp
+	add	edi,ecx
+	sar	ecx,2
+1:
+	pop	eax
+	xor	eax,(edi)
+	stos
+	loop	1b
+	mov	edi,edx
+	jmp	ebx
Index: /trunk/minix/lib/i386/head/em_abs.h
===================================================================
--- /trunk/minix/lib/i386/head/em_abs.h	(revision 9)
+++ /trunk/minix/lib/i386/head/em_abs.h	(revision 9)
@@ -0,0 +1,35 @@
+/* $Header: /cvsup/minix/src/lib/i386/head/em_abs.h,v 1.1.1.1 2005/04/21 14:56:12 beng Exp $ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#define LINO_AD         0
+#define FILN_AD         4
+
+#define LINO            (*(int    *)(_hol0()+LINO_AD))
+#define FILN            (*(char  **)(_hol0()+FILN_AD))
+
+#define EARRAY          0
+#define ERANGE          1
+#define ESET            2
+#define EIOVFL          3
+#define EFOVFL          4
+#define EFUNFL          5
+#define EIDIVZ          6
+#define EFDIVZ          7
+#define EIUND           8
+#define EFUND           9
+#define ECONV           10
+
+#define ESTACK          16
+#define EHEAP           17
+#define EILLINS         18
+#define EODDZ           19
+#define ECASE           20
+#define EMEMFLT         21
+#define EBADPTR         22
+#define EBADPC          23
+#define EBADLAE         24
+#define EBADMON         25
+#define EBADLIN         26
+#define EBADGTO         27
Index: /trunk/minix/lib/i386/head/em_head.s
===================================================================
--- /trunk/minix/lib/i386/head/em_head.s	(revision 9)
+++ /trunk/minix/lib/i386/head/em_head.s	(revision 9)
@@ -0,0 +1,20 @@
+#
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define ERANGE,ESET,EHEAP,ECASE,EILLINS,EIDIVZ,EODDZ
+.define .trppc, .ignmask
+
+ERANGE		= 1
+ESET		= 2
+EIDIVZ		= 6
+EHEAP		= 17
+EILLINS		= 18
+EODDZ		= 19
+ECASE		= 20
+
+#include <em_abs.h>
+
+.sect .data
+.trppc:
+	.data4	0
+.ignmask:
+	.data4	EIOVFL | EIUND | ECONV | EFOVFL | EFUNFL
Index: /trunk/minix/lib/i386/int64/Makedepend-ack
===================================================================
--- /trunk/minix/lib/i386/int64/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/i386/int64/Makedepend-ack	(revision 9)
@@ -0,0 +1,15 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' add64.s | sed -e 's:^\(.\):../../obj-ack//./i386/int64/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' add64u.s | sed -e 's:^\(.\):../../obj-ack//./i386/int64/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' cmp64.s | sed -e 's:^\(.\):../../obj-ack//./i386/int64/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' cv64u.s | sed -e 's:^\(.\):../../obj-ack//./i386/int64/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' cvu64.s | sed -e 's:^\(.\):../../obj-ack//./i386/int64/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' diff64.s | sed -e 's:^\(.\):../../obj-ack//./i386/int64/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' div64u.s | sed -e 's:^\(.\):../../obj-ack//./i386/int64/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' ex64.s | sed -e 's:^\(.\):../../obj-ack//./i386/int64/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' make64.s | sed -e 's:^\(.\):../../obj-ack//./i386/int64/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' mul64u.s | sed -e 's:^\(.\):../../obj-ack//./i386/int64/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sub64.s | sed -e 's:^\(.\):../../obj-ack//./i386/int64/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sub64u.s | sed -e 's:^\(.\):../../obj-ack//./i386/int64/\1:' >> .depend-ack
Index: /trunk/minix/lib/i386/int64/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/i386/int64/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/i386/int64/Makedepend-gnu	(revision 9)
@@ -0,0 +1,15 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' add64.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/int64/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' add64u.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/int64/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' cmp64.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/int64/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' cv64u.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/int64/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' cvu64.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/int64/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' diff64.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/int64/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' div64u.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/int64/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' ex64.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/int64/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' make64.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/int64/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' mul64u.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/int64/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' sub64.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/int64/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' sub64u.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/int64/\1:' >> .depend-gnu
Index: /trunk/minix/lib/i386/int64/Makefile
===================================================================
--- /trunk/minix/lib/i386/int64/Makefile	(revision 9)
+++ /trunk/minix/lib/i386/int64/Makefile	(revision 9)
@@ -0,0 +1,141 @@
+#Generated from ./i386/int64/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../generate.sh ./i386/int64 ../../obj-ack/ ../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../generate.sh ./i386/int64 ../../obj-ack/ ../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../../obj-ack//libc.a
+
+../../obj-ack//libc.a: ../../obj-ack//libc.a(add64.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(add64u.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(cmp64.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(cv64u.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(cvu64.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(diff64.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(div64u.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(ex64.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(make64.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(mul64u.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(sub64.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(sub64u.o)
+
+../../obj-ack//libc.a:
+	ar cr ../../obj-ack//libc.a ../../obj-ack//./i386/int64/*.o
+	rm ../../obj-ack//./i386/int64/*.o
+
+../../obj-ack//libc.a(add64.o): add64.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/int64/add64.o add64.s
+../../obj-ack//libc.a(add64u.o): add64u.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/int64/add64u.o add64u.s
+../../obj-ack//libc.a(cmp64.o): cmp64.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/int64/cmp64.o cmp64.s
+../../obj-ack//libc.a(cv64u.o): cv64u.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/int64/cv64u.o cv64u.s
+../../obj-ack//libc.a(cvu64.o): cvu64.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/int64/cvu64.o cvu64.s
+../../obj-ack//libc.a(diff64.o): diff64.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/int64/diff64.o diff64.s
+../../obj-ack//libc.a(div64u.o): div64u.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/int64/div64u.o div64u.s
+../../obj-ack//libc.a(ex64.o): ex64.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/int64/ex64.o ex64.s
+../../obj-ack//libc.a(make64.o): make64.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/int64/make64.o make64.s
+../../obj-ack//libc.a(mul64u.o): mul64u.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/int64/mul64u.o mul64u.s
+../../obj-ack//libc.a(sub64.o): sub64.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/int64/sub64.o sub64.s
+../../obj-ack//libc.a(sub64u.o): sub64u.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/int64/sub64u.o sub64u.s
+
+all-gnu: ../../obj-gnu/libc.a
+
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/int64/add64.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/int64/add64u.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/int64/cmp64.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/int64/cv64u.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/int64/cvu64.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/int64/diff64.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/int64/div64u.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/int64/ex64.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/int64/make64.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/int64/mul64u.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/int64/sub64.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/int64/sub64u.o
+
+../../obj-gnu/libc.a:
+	gar cr ../../obj-gnu/libc.a $?
+
+../../obj-gnu/./i386/int64/add64.o: add64.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. add64.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/int64/add64.s.gnu || true
+	gas -o ../../obj-gnu/./i386/int64/add64.o ../../obj-gnu/./i386/int64/add64.s.gnu
+
+../../obj-gnu/./i386/int64/add64u.o: add64u.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. add64u.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/int64/add64u.s.gnu || true
+	gas -o ../../obj-gnu/./i386/int64/add64u.o ../../obj-gnu/./i386/int64/add64u.s.gnu
+
+../../obj-gnu/./i386/int64/cmp64.o: cmp64.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. cmp64.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/int64/cmp64.s.gnu || true
+	gas -o ../../obj-gnu/./i386/int64/cmp64.o ../../obj-gnu/./i386/int64/cmp64.s.gnu
+
+../../obj-gnu/./i386/int64/cv64u.o: cv64u.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. cv64u.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/int64/cv64u.s.gnu || true
+	gas -o ../../obj-gnu/./i386/int64/cv64u.o ../../obj-gnu/./i386/int64/cv64u.s.gnu
+
+../../obj-gnu/./i386/int64/cvu64.o: cvu64.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. cvu64.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/int64/cvu64.s.gnu || true
+	gas -o ../../obj-gnu/./i386/int64/cvu64.o ../../obj-gnu/./i386/int64/cvu64.s.gnu
+
+../../obj-gnu/./i386/int64/diff64.o: diff64.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. diff64.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/int64/diff64.s.gnu || true
+	gas -o ../../obj-gnu/./i386/int64/diff64.o ../../obj-gnu/./i386/int64/diff64.s.gnu
+
+../../obj-gnu/./i386/int64/div64u.o: div64u.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. div64u.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/int64/div64u.s.gnu || true
+	gas -o ../../obj-gnu/./i386/int64/div64u.o ../../obj-gnu/./i386/int64/div64u.s.gnu
+
+../../obj-gnu/./i386/int64/ex64.o: ex64.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. ex64.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/int64/ex64.s.gnu || true
+	gas -o ../../obj-gnu/./i386/int64/ex64.o ../../obj-gnu/./i386/int64/ex64.s.gnu
+
+../../obj-gnu/./i386/int64/make64.o: make64.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. make64.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/int64/make64.s.gnu || true
+	gas -o ../../obj-gnu/./i386/int64/make64.o ../../obj-gnu/./i386/int64/make64.s.gnu
+
+../../obj-gnu/./i386/int64/mul64u.o: mul64u.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. mul64u.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/int64/mul64u.s.gnu || true
+	gas -o ../../obj-gnu/./i386/int64/mul64u.o ../../obj-gnu/./i386/int64/mul64u.s.gnu
+
+../../obj-gnu/./i386/int64/sub64.o: sub64.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. sub64.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/int64/sub64.s.gnu || true
+	gas -o ../../obj-gnu/./i386/int64/sub64.o ../../obj-gnu/./i386/int64/sub64.s.gnu
+
+../../obj-gnu/./i386/int64/sub64u.o: sub64u.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. sub64u.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/int64/sub64u.s.gnu || true
+	gas -o ../../obj-gnu/./i386/int64/sub64u.o ../../obj-gnu/./i386/int64/sub64u.s.gnu
+
+
+
+
+clean::
+	rm -f ../../obj-ack//./i386/int64/*
+	rm -f ../../obj-gnu/./i386/int64/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/i386/int64/Makefile.in
===================================================================
--- /trunk/minix/lib/i386/int64/Makefile.in	(revision 9)
+++ /trunk/minix/lib/i386/int64/Makefile.in	(revision 9)
@@ -0,0 +1,21 @@
+# Makefile for lib/i386/int64.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
+
+LIBRARIES=libc
+
+libc_FILES=" \
+	add64.s \
+	add64u.s \
+	cmp64.s \
+	cv64u.s \
+	cvu64.s \
+	diff64.s \
+	div64u.s \
+	ex64.s \
+	make64.s \
+	mul64u.s \
+	sub64.s \
+	sub64u.s"
+
+TYPE=both
Index: /trunk/minix/lib/i386/int64/add64.s
===================================================================
--- /trunk/minix/lib/i386/int64/add64.s	(revision 9)
+++ /trunk/minix/lib/i386/int64/add64.s	(revision 9)
@@ -0,0 +1,17 @@
+!	add64() - 64 bit addition			Author: Kees J. Bot
+!								7 Dec 1995
+.sect .text
+.define _add64
+
+_add64:				! u64_t add64(u64_t i, u64_t j);
+	mov	eax, 4(esp)
+	mov	edx, 8(esp)
+	add	edx, 16(esp)
+	mov	(eax), edx
+	mov	edx, 12(esp)
+	adc	edx, 20(esp)
+	mov	4(eax), edx
+	ret
+
+!
+! $PchId: add64.ack.s,v 1.2 1996/04/11 18:59:57 philip Exp $
Index: /trunk/minix/lib/i386/int64/add64u.s
===================================================================
--- /trunk/minix/lib/i386/int64/add64u.s	(revision 9)
+++ /trunk/minix/lib/i386/int64/add64u.s	(revision 9)
@@ -0,0 +1,18 @@
+!	add64u() - unsigned to 64 bit addition		Author: Kees J. Bot
+!								7 Dec 1995
+.sect .text
+.define _add64u, _add64ul
+
+_add64u:			! u64_t add64u(u64_t i, unsigned j);
+_add64ul:			! u64_t add64ul(u64_t i, unsigned long j);
+	mov	eax, 4(esp)
+	mov	edx, 8(esp)
+	add	edx, 16(esp)
+	mov	(eax), edx
+	mov	edx, 12(esp)
+	adc	edx, 0
+	mov	4(eax), edx
+	ret
+
+!
+! $PchId: add64u.ack.s,v 1.2 1996/04/11 18:59:57 philip Exp $
Index: /trunk/minix/lib/i386/int64/cmp64.s
===================================================================
--- /trunk/minix/lib/i386/int64/cmp64.s	(revision 9)
+++ /trunk/minix/lib/i386/int64/cmp64.s	(revision 9)
@@ -0,0 +1,31 @@
+!	cmp64*() - 64 bit compare			Author: Kees J. Bot
+!								7 Dec 1995
+.sect .text
+.define _cmp64, _cmp64u, _cmp64ul
+
+_cmp64:				! int cmp64(u64_t i, u64_t j);
+	mov	ecx, esp
+cmp64:	xor	eax, eax
+	mov	edx, 4(ecx)
+	sub	edx, 12(ecx)
+	mov	edx, 8(ecx)
+	sbb	edx, 16(ecx)
+	sbb	eax, eax		! eax = - (i < j)
+	mov	edx, 12(ecx)
+	sub	edx, 4(ecx)
+	mov	edx, 16(ecx)
+	sbb	edx, 8(ecx)
+	adc	eax, 0			! eax = (i > j) - (i < j)
+	ret
+
+_cmp64u:			! int cmp64u(u64_t i, unsigned j);
+_cmp64ul:			! int cmp64ul(u64_t i, unsigned long j);
+	mov	ecx, esp
+	push	16(ecx)
+	mov	16(ecx), 0
+	call	cmp64
+	pop	16(ecx)
+	ret
+
+!
+! $PchId: cmp64.ack.s,v 1.2 1996/04/11 18:59:57 philip Exp $
Index: /trunk/minix/lib/i386/int64/cv64u.s
===================================================================
--- /trunk/minix/lib/i386/int64/cv64u.s	(revision 9)
+++ /trunk/minix/lib/i386/int64/cv64u.s	(revision 9)
@@ -0,0 +1,15 @@
+!	cv64u() - 64 bit converted to unsigned		Author: Kees J. Bot
+!								7 Dec 1995
+.sect .text
+.define _cv64u, _cv64ul
+
+_cv64u:				! unsigned cv64u(u64_t i);
+_cv64ul:			! unsigned long cv64ul(u64_t i);
+	mov	eax, 4(esp)
+	cmp	8(esp), 0		! return ULONG_MAX if really big
+	jz	0f
+	mov	eax, -1
+0:	ret
+
+!
+! $PchId: cv64u.ack.s,v 1.2 1996/04/11 18:59:57 philip Exp $
Index: /trunk/minix/lib/i386/int64/cvu64.s
===================================================================
--- /trunk/minix/lib/i386/int64/cvu64.s	(revision 9)
+++ /trunk/minix/lib/i386/int64/cvu64.s	(revision 9)
@@ -0,0 +1,15 @@
+!	cvu64() - unsigned converted to 64 bit		Author: Kees J. Bot
+!								7 Dec 1995
+.sect .text
+.define _cvu64, _cvul64
+
+_cvu64:				! u64_t cvu64(unsigned i);
+_cvul64:			! u64_t cvul64(unsigned long i);
+	mov	eax, 4(esp)
+	mov	edx, 8(esp)
+	mov	(eax), edx
+	mov	4(eax), 0
+	ret
+
+!
+! $PchId: cvu64.ack.s,v 1.2 1996/04/11 18:59:57 philip Exp $
Index: /trunk/minix/lib/i386/int64/diff64.s
===================================================================
--- /trunk/minix/lib/i386/int64/diff64.s	(revision 9)
+++ /trunk/minix/lib/i386/int64/diff64.s	(revision 9)
@@ -0,0 +1,12 @@
+!	diff64() - 64 bit subtraction giving unsigned 	Author: Kees J. Bot
+!								7 Dec 1995
+.sect .text
+.define _diff64
+
+_diff64:			! unsigned diff64(u64_t i, u64_t j);
+	mov	eax, 4(esp)
+	sub	eax, 12(esp)
+	ret
+
+!
+! $PchId: diff64.ack.s,v 1.2 1996/04/11 18:59:57 philip Exp $
Index: /trunk/minix/lib/i386/int64/div64u.s
===================================================================
--- /trunk/minix/lib/i386/int64/div64u.s	(revision 9)
+++ /trunk/minix/lib/i386/int64/div64u.s	(revision 9)
@@ -0,0 +1,22 @@
+!	div64u() - 64 bit divided by unsigned giving unsigned long
+!							Author: Kees J. Bot
+!								7 Dec 1995
+.sect .text
+.define _div64u, _rem64u
+
+_div64u:			! unsigned long div64u(u64_t i, unsigned j);
+	xor	edx, edx
+	mov	eax, 8(esp)		! i = (ih<<32) + il
+	div	12(esp)			! ih = q * j + r
+	mov	eax, 4(esp)
+	div	12(esp)			! i / j = (q<<32) + ((r<<32) + il) / j
+	ret
+
+_rem64u:			! unsigned rem64u(u64_t i, unsigned j);
+	pop	ecx
+	call	_div64u
+	mov	eax, edx
+	jmp	ecx
+
+!
+! $PchId: div64u.ack.s,v 1.2 1996/04/11 18:59:57 philip Exp $
Index: /trunk/minix/lib/i386/int64/ex64.s
===================================================================
--- /trunk/minix/lib/i386/int64/ex64.s	(revision 9)
+++ /trunk/minix/lib/i386/int64/ex64.s	(revision 9)
@@ -0,0 +1,16 @@
+!	ex64*() - extract low or high 32 bits of a 64 bit number
+!							Author: Kees J. Bot
+!								7 Dec 1995
+.sect .text
+.define _ex64lo, _ex64hi
+
+_ex64lo:			! unsigned long ex64lo(u64_t i);
+	mov	eax, 4(esp)
+	ret
+
+_ex64hi:			! unsigned long ex64hi(u64_t i);
+	mov	eax, 8(esp)
+	ret
+
+!
+! $PchId: ex64.ack.s,v 1.2 1996/04/11 18:59:57 philip Exp $
Index: /trunk/minix/lib/i386/int64/make64.s
===================================================================
--- /trunk/minix/lib/i386/int64/make64.s	(revision 9)
+++ /trunk/minix/lib/i386/int64/make64.s	(revision 9)
@@ -0,0 +1,16 @@
+!	make64() - make a 64 bit number from two 32 bit halves
+!							Author: Kees J. Bot
+!								7 Dec 1995
+.sect .text
+.define _make64
+
+_make64:		    ! u64_t make64(unsigned long lo, unsigned long hi);
+	mov	eax, 4(esp)
+	mov	edx, 8(esp)
+	mov	(eax), edx
+	mov	edx, 12(esp)
+	mov	4(eax), edx
+	ret
+
+!
+! $PchId: make64.ack.s,v 1.2 1996/04/11 18:59:57 philip Exp $
Index: /trunk/minix/lib/i386/int64/mul64u.s
===================================================================
--- /trunk/minix/lib/i386/int64/mul64u.s	(revision 9)
+++ /trunk/minix/lib/i386/int64/mul64u.s	(revision 9)
@@ -0,0 +1,17 @@
+!	mul64u() - unsigned long by unsigned multiply giving 64 bit result
+!							Author: Kees J. Bot
+!								7 Dec 1995
+.sect .text
+.define _mul64u
+
+_mul64u:			! u64_t mul64u(unsigned long i, unsigned j);
+	mov	ecx, 4(esp)
+	mov	eax, 8(esp)
+	mul	12(esp)
+	mov	(ecx), eax
+	mov	4(ecx), edx
+	mov	eax, ecx
+	ret
+
+!
+! $PchId: mul64u.ack.s,v 1.2 1996/04/11 18:59:57 philip Exp $
Index: /trunk/minix/lib/i386/int64/sub64.s
===================================================================
--- /trunk/minix/lib/i386/int64/sub64.s	(revision 9)
+++ /trunk/minix/lib/i386/int64/sub64.s	(revision 9)
@@ -0,0 +1,17 @@
+!	sub64() - 64 bit subtraction			Author: Kees J. Bot
+!								7 Dec 1995
+.sect .text
+.define _sub64
+
+_sub64:				! u64_t sub64(u64_t i, u64_t j);
+	mov	eax, 4(esp)
+	mov	edx, 8(esp)
+	sub	edx, 16(esp)
+	mov	(eax), edx
+	mov	edx, 12(esp)
+	sbb	edx, 20(esp)
+	mov	4(eax), edx
+	ret
+
+!
+! $PchId: sub64.ack.s,v 1.2 1996/04/11 18:59:57 philip Exp $
Index: /trunk/minix/lib/i386/int64/sub64u.s
===================================================================
--- /trunk/minix/lib/i386/int64/sub64u.s	(revision 9)
+++ /trunk/minix/lib/i386/int64/sub64u.s	(revision 9)
@@ -0,0 +1,18 @@
+!	sub64() - unsigned from 64 bit subtraction	Author: Kees J. Bot
+!								7 Dec 1995
+.sect .text
+.define _sub64u, _sub64ul
+
+_sub64u:			! u64_t sub64u(u64_t i, unsigned j);
+_sub64ul:			! u64_t sub64ul(u64_t i, unsigned long j);
+	mov	eax, 4(esp)
+	mov	edx, 8(esp)
+	sub	edx, 16(esp)
+	mov	(eax), edx
+	mov	edx, 12(esp)
+	sbb	edx, 0
+	mov	4(eax), edx
+	ret
+
+!
+! $PchId: sub64u.ack.s,v 1.2 1996/04/11 18:59:57 philip Exp $
Index: /trunk/minix/lib/i386/misc/Makedepend-ack
===================================================================
--- /trunk/minix/lib/i386/misc/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/i386/misc/Makedepend-ack	(revision 9)
@@ -0,0 +1,20 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' alloca.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' get_bp.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' getprocessor.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' io_inb.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' io_inl.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' io_insb.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' io_insl.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' io_insw.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' io_intr.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' io_inw.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' io_outb.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' io_outl.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' io_outsb.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' io_outsl.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' io_outsw.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' io_outw.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' oneC_sum.s | sed -e 's:^\(.\):../../obj-ack//./i386/misc/\1:' >> .depend-ack
Index: /trunk/minix/lib/i386/misc/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/i386/misc/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/i386/misc/Makedepend-gnu	(revision 9)
@@ -0,0 +1,20 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' alloca.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' get_bp.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' getprocessor.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' io_inb.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' io_inl.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' io_insb.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' io_insl.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' io_insw.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' io_intr.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' io_inw.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' io_outb.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' io_outl.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' io_outsb.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' io_outsl.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' io_outsw.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' io_outw.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' oneC_sum.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/misc/\1:' >> .depend-gnu
Index: /trunk/minix/lib/i386/misc/Makefile
===================================================================
--- /trunk/minix/lib/i386/misc/Makefile	(revision 9)
+++ /trunk/minix/lib/i386/misc/Makefile	(revision 9)
@@ -0,0 +1,181 @@
+#Generated from ./i386/misc/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../generate.sh ./i386/misc ../../obj-ack/ ../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../generate.sh ./i386/misc ../../obj-ack/ ../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../../obj-ack//libc.a
+
+../../obj-ack//libc.a: ../../obj-ack//libc.a(alloca.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(get_bp.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(getprocessor.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(io_inb.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(io_inl.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(io_insb.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(io_insl.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(io_insw.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(io_intr.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(io_inw.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(io_outb.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(io_outl.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(io_outsb.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(io_outsl.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(io_outsw.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(io_outw.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(oneC_sum.o)
+
+../../obj-ack//libc.a:
+	ar cr ../../obj-ack//libc.a ../../obj-ack//./i386/misc/*.o
+	rm ../../obj-ack//./i386/misc/*.o
+
+../../obj-ack//libc.a(alloca.o): alloca.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/alloca.o alloca.s
+../../obj-ack//libc.a(get_bp.o): get_bp.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/get_bp.o get_bp.s
+../../obj-ack//libc.a(getprocessor.o): getprocessor.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/getprocessor.o getprocessor.s
+../../obj-ack//libc.a(io_inb.o): io_inb.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/io_inb.o io_inb.s
+../../obj-ack//libc.a(io_inl.o): io_inl.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/io_inl.o io_inl.s
+../../obj-ack//libc.a(io_insb.o): io_insb.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/io_insb.o io_insb.s
+../../obj-ack//libc.a(io_insl.o): io_insl.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/io_insl.o io_insl.s
+../../obj-ack//libc.a(io_insw.o): io_insw.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/io_insw.o io_insw.s
+../../obj-ack//libc.a(io_intr.o): io_intr.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/io_intr.o io_intr.s
+../../obj-ack//libc.a(io_inw.o): io_inw.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/io_inw.o io_inw.s
+../../obj-ack//libc.a(io_outb.o): io_outb.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/io_outb.o io_outb.s
+../../obj-ack//libc.a(io_outl.o): io_outl.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/io_outl.o io_outl.s
+../../obj-ack//libc.a(io_outsb.o): io_outsb.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/io_outsb.o io_outsb.s
+../../obj-ack//libc.a(io_outsl.o): io_outsl.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/io_outsl.o io_outsl.s
+../../obj-ack//libc.a(io_outsw.o): io_outsw.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/io_outsw.o io_outsw.s
+../../obj-ack//libc.a(io_outw.o): io_outw.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/io_outw.o io_outw.s
+../../obj-ack//libc.a(oneC_sum.o): oneC_sum.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/misc/oneC_sum.o oneC_sum.s
+
+all-gnu: ../../obj-gnu/libc.a
+
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/alloca.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/get_bp.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/getprocessor.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/io_inb.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/io_inl.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/io_insb.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/io_insl.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/io_insw.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/io_intr.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/io_inw.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/io_outb.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/io_outl.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/io_outsb.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/io_outsl.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/io_outsw.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/io_outw.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/misc/oneC_sum.o
+
+../../obj-gnu/libc.a:
+	gar cr ../../obj-gnu/libc.a $?
+
+../../obj-gnu/./i386/misc/alloca.o: alloca.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. alloca.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/alloca.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/alloca.o ../../obj-gnu/./i386/misc/alloca.s.gnu
+
+../../obj-gnu/./i386/misc/get_bp.o: get_bp.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. get_bp.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/get_bp.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/get_bp.o ../../obj-gnu/./i386/misc/get_bp.s.gnu
+
+../../obj-gnu/./i386/misc/getprocessor.o: getprocessor.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. getprocessor.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/getprocessor.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/getprocessor.o ../../obj-gnu/./i386/misc/getprocessor.s.gnu
+
+../../obj-gnu/./i386/misc/io_inb.o: io_inb.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. io_inb.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/io_inb.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/io_inb.o ../../obj-gnu/./i386/misc/io_inb.s.gnu
+
+../../obj-gnu/./i386/misc/io_inl.o: io_inl.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. io_inl.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/io_inl.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/io_inl.o ../../obj-gnu/./i386/misc/io_inl.s.gnu
+
+../../obj-gnu/./i386/misc/io_insb.o: io_insb.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. io_insb.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/io_insb.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/io_insb.o ../../obj-gnu/./i386/misc/io_insb.s.gnu
+
+../../obj-gnu/./i386/misc/io_insl.o: io_insl.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. io_insl.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/io_insl.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/io_insl.o ../../obj-gnu/./i386/misc/io_insl.s.gnu
+
+../../obj-gnu/./i386/misc/io_insw.o: io_insw.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. io_insw.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/io_insw.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/io_insw.o ../../obj-gnu/./i386/misc/io_insw.s.gnu
+
+../../obj-gnu/./i386/misc/io_intr.o: io_intr.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. io_intr.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/io_intr.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/io_intr.o ../../obj-gnu/./i386/misc/io_intr.s.gnu
+
+../../obj-gnu/./i386/misc/io_inw.o: io_inw.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. io_inw.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/io_inw.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/io_inw.o ../../obj-gnu/./i386/misc/io_inw.s.gnu
+
+../../obj-gnu/./i386/misc/io_outb.o: io_outb.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. io_outb.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/io_outb.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/io_outb.o ../../obj-gnu/./i386/misc/io_outb.s.gnu
+
+../../obj-gnu/./i386/misc/io_outl.o: io_outl.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. io_outl.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/io_outl.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/io_outl.o ../../obj-gnu/./i386/misc/io_outl.s.gnu
+
+../../obj-gnu/./i386/misc/io_outsb.o: io_outsb.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. io_outsb.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/io_outsb.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/io_outsb.o ../../obj-gnu/./i386/misc/io_outsb.s.gnu
+
+../../obj-gnu/./i386/misc/io_outsl.o: io_outsl.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. io_outsl.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/io_outsl.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/io_outsl.o ../../obj-gnu/./i386/misc/io_outsl.s.gnu
+
+../../obj-gnu/./i386/misc/io_outsw.o: io_outsw.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. io_outsw.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/io_outsw.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/io_outsw.o ../../obj-gnu/./i386/misc/io_outsw.s.gnu
+
+../../obj-gnu/./i386/misc/io_outw.o: io_outw.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. io_outw.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/io_outw.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/io_outw.o ../../obj-gnu/./i386/misc/io_outw.s.gnu
+
+../../obj-gnu/./i386/misc/oneC_sum.o: oneC_sum.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. oneC_sum.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/misc/oneC_sum.s.gnu || true
+	gas -o ../../obj-gnu/./i386/misc/oneC_sum.o ../../obj-gnu/./i386/misc/oneC_sum.s.gnu
+
+
+
+
+clean::
+	rm -f ../../obj-ack//./i386/misc/*
+	rm -f ../../obj-gnu/./i386/misc/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/i386/misc/Makefile.in
===================================================================
--- /trunk/minix/lib/i386/misc/Makefile.in	(revision 9)
+++ /trunk/minix/lib/i386/misc/Makefile.in	(revision 9)
@@ -0,0 +1,26 @@
+# Makefile for lib/i386/misc.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
+
+LIBRARIES=libc
+
+libc_FILES=" \
+	alloca.s \
+	get_bp.s \
+	getprocessor.s \
+	io_inb.s \
+	io_inl.s \
+	io_insb.s \
+	io_insl.s \
+	io_insw.s \
+	io_intr.s \
+	io_inw.s \
+	io_outb.s \
+	io_outl.s \
+	io_outsb.s \
+	io_outsl.s \
+	io_outsw.s \
+	io_outw.s \
+	oneC_sum.s"
+
+TYPE=both
Index: /trunk/minix/lib/i386/misc/alloca.s
===================================================================
--- /trunk/minix/lib/i386/misc/alloca.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/alloca.s	(revision 9)
@@ -0,0 +1,33 @@
+#
+!	alloca() - allocate space on the stack		Author: Kees J. Bot
+!								2 Dec 1993
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+.sect .text
+	.align	16
+.define _alloca
+_alloca:
+#if __ACK__
+	pop	ecx		! Return address
+	pop	eax		! Bytes to allocate
+	add	eax, 2*4+3	! Add space for two saved register variables
+	andb	al, 0xFC	! Align
+	mov	ebx, esp	! Keep current esp
+	sub	esp, eax	! Lower stack
+	mov	eax, esp	! Return value
+	push	4(ebx)		! Push what is probably the saved esi
+	push	(ebx)		! Saved edi
+				! Now ACK can still do:
+				!	pop edi; pop esi; leave; ret
+	push	eax		! Dummy argument
+	jmp	ecx
+#else
+	pop	ecx		! Return address
+	pop	eax		! Bytes to allocate
+	add	eax, 3
+	andb	al, 0xFC	! Align
+	sub	esp, eax	! Lower stack
+	mov	eax, esp	! Return value
+	push	eax		! Dummy argument
+	jmp	ecx
+#endif
Index: /trunk/minix/lib/i386/misc/get_bp.s
===================================================================
--- /trunk/minix/lib/i386/misc/get_bp.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/get_bp.s	(revision 9)
@@ -0,0 +1,16 @@
+! get_bp.s
+!
+! return EBP in EAX
+!
+! Created:	Sep 7, 1992 by Philip Homburg
+
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+.sect .text
+.define _get_bp
+_get_bp:
+	mov	eax, ebp
+	ret
+
+! $PchId: get_bp.ack.s,v 1.3 1996/02/23 08:30:52 philip Exp $
+
Index: /trunk/minix/lib/i386/misc/getprocessor.s
===================================================================
--- /trunk/minix/lib/i386/misc/getprocessor.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/getprocessor.s	(revision 9)
@@ -0,0 +1,56 @@
+!	getprocessor() - determine processor type	Author: Kees J. Bot
+!								26 Jan 1994
+
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+
+! int getprocessor(void);
+!	Return 386, 486, 586, ...
+
+.define	_getprocessor
+
+_getprocessor:
+	push	ebp
+	mov	ebp, esp
+	and	esp, 0xFFFFFFFC	! Align stack to avoid AC fault
+	mov	ecx, 0x00040000	! Try to flip the AC bit introduced on the 486
+	call	flip
+	mov	eax, 386	! 386 if it didn't react to "flipping"
+	jz	gotprocessor
+	mov	ecx, 0x00200000	! Try to flip the ID bit introduced on the 586
+	call	flip
+	mov	eax, 486	! 486 if it didn't react
+	jz	gotprocessor
+	pushf
+	pusha			! Save the world
+	mov	eax, 1
+	.data1	0x0F, 0xA2	! CPUID instruction tells the processor type
+	andb	ah, 0x0F	! Extract the family (5, 6, ...)
+	movzxb	eax, ah
+	cmp	eax, 15		! 15: extended family
+	jne	direct
+	mov	eax, 6		! Make it 686
+direct:
+	imul	eax, 100	! 500, 600, ...
+	add	eax, 86		! 586, 686, ...
+	mov	7*4(esp), eax	! Pass eax through
+	popa
+	popf
+gotprocessor:
+	leave
+	ret
+
+flip:
+	pushf			! Push eflags
+	pop	eax		! eax = eflags
+	mov	edx, eax	! Save original eflags
+	xor	eax, ecx	! Flip the bit to test
+	push	eax		! Push modified eflags value
+	popf			! Load modified eflags register
+	pushf
+	pop	eax		! Get it again
+	push	edx
+	popf			! Restore original eflags register
+	xor	eax, edx	! See if the bit changed
+	test	eax, ecx
+	ret
Index: /trunk/minix/lib/i386/misc/io_inb.s
===================================================================
--- /trunk/minix/lib/i386/misc/io_inb.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/io_inb.s	(revision 9)
@@ -0,0 +1,14 @@
+!	inb() - Input one byte				Author: Kees J. Bot
+!								18 Mar 1996
+!	unsigned inb(U16_t port);
+
+.sect .text
+.define _inb
+_inb:
+	push	ebp
+	mov	ebp, esp
+	mov	edx, 8(ebp)		! port
+	xor	eax, eax
+	inb	dx			! read 1 byte
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/misc/io_inl.s
===================================================================
--- /trunk/minix/lib/i386/misc/io_inl.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/io_inl.s	(revision 9)
@@ -0,0 +1,13 @@
+!	inl() - Input one dword				Author: Kees J. Bot
+!								18 Mar 1996
+!	unsigned inl(U16_t port);
+
+.sect .text
+.define _inl
+_inl:
+	push	ebp
+	mov	ebp, esp
+	mov	edx, 8(ebp)		! port
+	in	dx			! read 1 dword
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/misc/io_insb.s
===================================================================
--- /trunk/minix/lib/i386/misc/io_insb.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/io_insb.s	(revision 9)
@@ -0,0 +1,18 @@
+!	insb() - Input a byte array			Author: Kees J. Bot
+!								18 Mar 1996
+!	void insb(U16_t port, void *buf, size_t count);
+
+.sect .text
+.define _insb
+_insb:
+	push	ebp
+	mov	ebp, esp
+	cld
+	push	edi
+	mov	edx, 8(ebp)		! port
+	mov	edi, 12(ebp)		! buf
+	mov	ecx, 16(ebp)		! byte count
+   rep	insb				! input many bytes
+	pop	edi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/misc/io_insl.s
===================================================================
--- /trunk/minix/lib/i386/misc/io_insl.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/io_insl.s	(revision 9)
@@ -0,0 +1,19 @@
+!	insl() - Input a dword array			Author: Kees J. Bot
+!								18 Mar 1996
+!	void insl(U16_t port, void *buf, size_t count);
+
+.sect .text
+.define _insl
+_insl:
+	push	ebp
+	mov	ebp, esp
+	cld
+	push	edi
+	mov	edx, 8(ebp)		! port
+	mov	edi, 12(ebp)		! buf
+	mov	ecx, 16(ebp)		! byte count
+	shr	ecx, 2			! dword count
+   rep	ins				! input many dwords
+	pop	edi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/misc/io_insw.s
===================================================================
--- /trunk/minix/lib/i386/misc/io_insw.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/io_insw.s	(revision 9)
@@ -0,0 +1,19 @@
+!	insw() - Input a word array			Author: Kees J. Bot
+!								18 Mar 1996
+!	void insw(U16_t port, void *buf, size_t count);
+
+.sect .text
+.define _insw
+_insw:
+	push	ebp
+	mov	ebp, esp
+	cld
+	push	edi
+	mov	edx, 8(ebp)		! port
+	mov	edi, 12(ebp)		! buf
+	mov	ecx, 16(ebp)		! byte count
+	shr	ecx, 1			! word count
+rep o16	ins				! input many words
+	pop	edi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/misc/io_intr.s
===================================================================
--- /trunk/minix/lib/i386/misc/io_intr.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/io_intr.s	(revision 9)
@@ -0,0 +1,16 @@
+!	intr_disable(), intr_enable - Disable/Enable hardware interrupts.
+!							Author: Kees J. Bot
+!								18 Mar 1996
+!	void intr_disable(void);
+!	void intr_enable(void);
+
+.sect .text
+.define _intr_disable
+_intr_disable:
+	cli
+	ret
+
+.define _intr_enable
+_intr_enable:
+	sti
+	ret
Index: /trunk/minix/lib/i386/misc/io_inw.s
===================================================================
--- /trunk/minix/lib/i386/misc/io_inw.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/io_inw.s	(revision 9)
@@ -0,0 +1,14 @@
+!	inw() - Input one word				Author: Kees J. Bot
+!								18 Mar 1996
+!	unsigned inw(U16_t port);
+
+.sect .text
+.define _inw
+_inw:
+	push	ebp
+	mov	ebp, esp
+	mov	edx, 8(ebp)		! port
+	xor	eax, eax
+    o16	in	dx			! read 1 word
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/misc/io_outb.s
===================================================================
--- /trunk/minix/lib/i386/misc/io_outb.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/io_outb.s	(revision 9)
@@ -0,0 +1,14 @@
+!	outb() - Output one byte			Author: Kees J. Bot
+!								18 Mar 1996
+!	void outb(U16_t port, U8_t value);
+
+.sect .text
+.define _outb
+_outb:
+	push	ebp
+	mov	ebp, esp
+	mov	edx, 8(ebp)		! port
+	mov	eax, 8+4(ebp)		! value
+	outb	dx			! output 1 byte
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/misc/io_outl.s
===================================================================
--- /trunk/minix/lib/i386/misc/io_outl.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/io_outl.s	(revision 9)
@@ -0,0 +1,14 @@
+!	outl() - Output one dword			Author: Kees J. Bot
+!								18 Mar 1996
+!	void outl(U16_t port, u32_t value);
+
+.sect .text
+.define _outl
+_outl:
+	push	ebp
+	mov	ebp, esp
+	mov	edx, 8(ebp)		! port
+	mov	eax, 8+4(ebp)		! value
+	out	dx			! output 1 dword
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/misc/io_outsb.s
===================================================================
--- /trunk/minix/lib/i386/misc/io_outsb.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/io_outsb.s	(revision 9)
@@ -0,0 +1,18 @@
+!	outsb() - Output a byte array		Author: Kees J. Bot
+!								18 Mar 1996
+!	void outsb(U16_t port, void *buf, size_t count);
+
+.sect .text
+.define _outsb
+_outsb:
+	push	ebp
+	mov	ebp, esp
+	cld
+	push	esi
+	mov	edx, 8(ebp)		! port
+	mov	esi, 12(ebp)		! buf
+	mov	ecx, 16(ebp)		! byte count
+   rep	outsb				! output many bytes
+	pop	esi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/misc/io_outsl.s
===================================================================
--- /trunk/minix/lib/i386/misc/io_outsl.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/io_outsl.s	(revision 9)
@@ -0,0 +1,19 @@
+!	outsl() - Output a dword array		Author: Kees J. Bot
+!								18 Mar 1996
+!	void outsl(U16_t port, void *buf, size_t count);
+
+.sect .text
+.define _outsl
+_outsl:
+	push	ebp
+	mov	ebp, esp
+	cld
+	push	esi
+	mov	edx, 8(ebp)		! port
+	mov	esi, 12(ebp)		! buf
+	mov	ecx, 16(ebp)		! byte count
+	shr	ecx, 2			! dword count
+   rep	outs				! output many dwords
+	pop	esi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/misc/io_outsw.s
===================================================================
--- /trunk/minix/lib/i386/misc/io_outsw.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/io_outsw.s	(revision 9)
@@ -0,0 +1,19 @@
+!	outsw() - Output a word array		Author: Kees J. Bot
+!								18 Mar 1996
+!	void outsw(U16_t port, void *buf, size_t count);
+
+.sect .text
+.define _outsw
+_outsw:
+	push	ebp
+	mov	ebp, esp
+	cld
+	push	esi
+	mov	edx, 8(ebp)		! port
+	mov	esi, 12(ebp)		! buf
+	mov	ecx, 16(ebp)		! byte count
+	shr	ecx, 1			! word count
+rep o16	outs				! output many words
+	pop	esi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/misc/io_outw.s
===================================================================
--- /trunk/minix/lib/i386/misc/io_outw.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/io_outw.s	(revision 9)
@@ -0,0 +1,14 @@
+!	outw() - Output one word			Author: Kees J. Bot
+!								18 Mar 1996
+!	void outw(U16_t port, U16_t value);
+
+.sect .text
+.define _outw
+_outw:
+	push	ebp
+	mov	ebp, esp
+	mov	edx, 8(ebp)		! port
+	mov	eax, 8+4(ebp)		! value
+    o16	out	dx			! output 1 word
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/misc/oneC_sum.s
===================================================================
--- /trunk/minix/lib/i386/misc/oneC_sum.s	(revision 9)
+++ /trunk/minix/lib/i386/misc/oneC_sum.s	(revision 9)
@@ -0,0 +1,80 @@
+!	oneC_sum() - One complement`s checksum		Author: Kees J. Bot
+!								9 May 1995
+! See RFC 1071, "Computing the Internet checksum"
+! See also the C version of this code.
+
+.sect .text
+
+.define _oneC_sum
+	.align	16
+_oneC_sum:
+	push	ebp
+	mov	ebp, esp
+	push	esi
+	push	edi
+	movzx	eax, 8(ebp)		! Checksum of previous block
+	mov	esi, 12(ebp)		! Data to compute checksum over
+	mov	edi, 16(ebp)		! Number of bytes
+
+	xor	edx, edx
+	xorb	cl, cl
+align:	test	esi, 3			! Is the data aligned?
+	jz	aligned
+	test	edi, edi
+	jz	0f
+	movb	dl, (esi)		! Rotate the first unaligned bytes
+	dec	edi			! into the edx register
+0:	inc	esi
+	ror	edx, 8
+	ror	eax, 8			! Rotate the checksum likewise
+	addb	cl, 8			! Number of bits rotated
+	jmp	align
+aligned:add	eax, edx		! Summate the unaligned bytes
+	adc	eax, 0			! Add carry back in for one`s complement
+
+	jmp	add6test
+	.align	16
+add6:	add	eax, (esi)		! Six times unrolled loop, see below
+	adc	eax, 4(esi)
+	adc	eax, 8(esi)
+	adc	eax, 12(esi)
+	adc	eax, 16(esi)
+	adc	eax, 20(esi)
+	adc	eax, 0
+	add	esi, 24
+add6test:
+	sub	edi, 24
+	jae	add6
+	add	edi, 24
+
+	jmp	add1test
+	.align	16
+add1:	add	eax, (esi)		! while ((edi -= 4) >= 0)
+	adc	eax, 0			!	eax += *esi++;
+	add	esi, 4			! edi += 4;
+add1test:
+	sub	edi, 4
+	jae	add1
+	add	edi, 4
+
+	jz	done			! Are there extra bytes?
+	mov	edx, (esi)		! Load extra bytes in a full dword
+	and	edx, mask-4(edi*4)	! Mask off excess
+	add	eax, edx		! Add in the last bits
+	adc	eax, 0
+done:	rol	eax, cl			! Undo the rotation at the beginning
+	mov	edx, eax
+	shr	eax, 16
+  o16	add	ax, dx			! Add the two words in eax to form
+  o16	adc	ax, 0			! a 16 bit sum
+	pop	edi
+	pop	esi
+	pop	ebp
+	ret
+
+.sect .rom
+	.align	4
+mask:	.data4	0x000000FF, 0x0000FFFF, 0x00FFFFFF
+
+!
+! $PchId: oneC_sum.ack.s,v 1.2 1996/03/12 19:33:51 philip Exp $
Index: /trunk/minix/lib/i386/rts/Makedepend-ack
===================================================================
--- /trunk/minix/lib/i386/rts/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/i386/rts/Makedepend-ack	(revision 9)
@@ -0,0 +1,10 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' __sigreturn.s | sed -e 's:^\(.\):../../obj-ack//./i386/rts/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _ipc.s | sed -e 's:^\(.\):../../obj-ack//./i386/rts/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _ipcnew.s | sed -e 's:^\(.\):../../obj-ack//./i386/rts/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' brksize.s | sed -e 's:^\(.\):../../obj-ack//./i386/rts/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' crtso.s | sed -e 's:^\(.\):../../obj-ack/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' m2rtso.s | sed -e 's:^\(.\):../../obj-ack/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' prtso.s | sed -e 's:^\(.\):../../obj-ack/\1:' >> .depend-ack
Index: /trunk/minix/lib/i386/rts/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/i386/rts/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/i386/rts/Makedepend-gnu	(revision 9)
@@ -0,0 +1,10 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' __sigreturn.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/rts/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' _ipc.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/rts/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' _ipcnew.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/rts/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' brksize.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/rts/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' crtso.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' m2rtso.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I.' prtso.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/\1:' >> .depend-gnu
Index: /trunk/minix/lib/i386/rts/Makefile
===================================================================
--- /trunk/minix/lib/i386/rts/Makefile	(revision 9)
+++ /trunk/minix/lib/i386/rts/Makefile	(revision 9)
@@ -0,0 +1,113 @@
+#Generated from ./i386/rts/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../generate.sh ./i386/rts ../../obj-ack/ ../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../generate.sh ./i386/rts ../../obj-ack/ ../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../../obj-ack//libc.a
+
+../../obj-ack//libc.a: ../../obj-ack//libc.a(__sigreturn.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(_ipc.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(_ipcnew.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(brksize.o)
+
+../../obj-ack//libc.a:
+	ar cr ../../obj-ack//libc.a ../../obj-ack//./i386/rts/*.o
+	rm ../../obj-ack//./i386/rts/*.o
+
+../../obj-ack//libc.a(__sigreturn.o): __sigreturn.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/rts/__sigreturn.o __sigreturn.s
+../../obj-ack//libc.a(_ipc.o): _ipc.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/rts/_ipc.o _ipc.s
+../../obj-ack//libc.a(_ipcnew.o): _ipcnew.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/rts/_ipcnew.o _ipcnew.s
+../../obj-ack//libc.a(brksize.o): brksize.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//./i386/rts/brksize.o brksize.s
+
+all-gnu: ../../obj-gnu/libc.a
+
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/rts/__sigreturn.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/rts/_ipc.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/rts/_ipcnew.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/rts/brksize.o
+
+../../obj-gnu/libc.a:
+	gar cr ../../obj-gnu/libc.a $?
+
+../../obj-gnu/./i386/rts/__sigreturn.o: __sigreturn.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. __sigreturn.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/rts/__sigreturn.s.gnu || true
+	gas -o ../../obj-gnu/./i386/rts/__sigreturn.o ../../obj-gnu/./i386/rts/__sigreturn.s.gnu
+
+../../obj-gnu/./i386/rts/_ipc.o: _ipc.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. _ipc.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/rts/_ipc.s.gnu || true
+	gas -o ../../obj-gnu/./i386/rts/_ipc.o ../../obj-gnu/./i386/rts/_ipc.s.gnu
+
+../../obj-gnu/./i386/rts/_ipcnew.o: _ipcnew.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. _ipcnew.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/rts/_ipcnew.s.gnu || true
+	gas -o ../../obj-gnu/./i386/rts/_ipcnew.o ../../obj-gnu/./i386/rts/_ipcnew.s.gnu
+
+../../obj-gnu/./i386/rts/brksize.o: brksize.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. brksize.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/rts/brksize.s.gnu || true
+	gas -o ../../obj-gnu/./i386/rts/brksize.o ../../obj-gnu/./i386/rts/brksize.s.gnu
+
+
+
+all-ack: ../../obj-ack//crtso.o
+
+../../obj-ack//crtso.o: crtso.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//crtso.o crtso.s
+
+all-gnu: ../../obj-gnu/crtso.o
+
+../../obj-gnu/crtso.o: crtso.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. crtso.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/rts/crtso.s.gnu || true
+	gas -o ../../obj-gnu/crtso.o ../../obj-gnu/./i386/rts/crtso.s.gnu
+
+
+all-ack: ../../obj-ack//m2rtso.o
+
+../../obj-ack//m2rtso.o: m2rtso.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//m2rtso.o m2rtso.s
+
+all-gnu: ../../obj-gnu/m2rtso.o
+
+../../obj-gnu/m2rtso.o: m2rtso.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. m2rtso.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/rts/m2rtso.s.gnu || true
+	gas -o ../../obj-gnu/m2rtso.o ../../obj-gnu/./i386/rts/m2rtso.s.gnu
+
+
+all-ack: ../../obj-ack//prtso.o
+
+../../obj-ack//prtso.o: prtso.s
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../../obj-ack//prtso.o prtso.s
+
+all-gnu: ../../obj-gnu/prtso.o
+
+../../obj-gnu/prtso.o: prtso.s
+	gcc -O -D_MINIX -D_POSIX_SOURCE -E -x assembler-with-cpp -I. prtso.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/rts/prtso.s.gnu || true
+	gas -o ../../obj-gnu/prtso.o ../../obj-gnu/./i386/rts/prtso.s.gnu
+
+
+
+clean::
+	rm -f ../../obj-ack//./i386/rts/*
+	rm -f ../../obj-gnu/./i386/rts/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/i386/rts/Makefile.in
===================================================================
--- /trunk/minix/lib/i386/rts/Makefile.in	(revision 9)
+++ /trunk/minix/lib/i386/rts/Makefile.in	(revision 9)
@@ -0,0 +1,18 @@
+# Makefile for lib/i386/rts.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
+
+LIBRARIES=libc
+
+libc_FILES=" \
+	__sigreturn.s \
+	_ipc.s \
+	_ipcnew.s \
+	brksize.s"
+	
+STARTFILES="\
+	crtso.s \
+	m2rtso.s \
+	prtso.s"
+
+TYPE=both
Index: /trunk/minix/lib/i386/rts/__sigreturn.s
===================================================================
--- /trunk/minix/lib/i386/rts/__sigreturn.s	(revision 9)
+++ /trunk/minix/lib/i386/rts/__sigreturn.s	(revision 9)
@@ -0,0 +1,10 @@
+! This routine is the low-level code for returning from signals.  
+! It calls __sigreturn, which is the normal "system call" routine.
+! Both ___sigreturn and __sigreturn are needed.
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define ___sigreturn
+.extern __sigreturn
+___sigreturn:
+	add esp, 16
+	jmp __sigreturn
Index: /trunk/minix/lib/i386/rts/_ipc.s
===================================================================
--- /trunk/minix/lib/i386/rts/_ipc.s	(revision 9)
+++ /trunk/minix/lib/i386/rts/_ipc.s	(revision 9)
@@ -0,0 +1,79 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define __echo, __notify, __send, __receive, __sendrec 
+
+! See src/kernel/ipc.h for C definitions
+SEND = 1
+RECEIVE = 2
+SENDREC = 3 
+NOTIFY = 4
+ECHO = 8
+SYSVEC = 33			! trap to kernel 
+
+SRC_DST = 8			! source/ destination process 
+ECHO_MESS = 8			! echo doesn't have SRC_DST 
+MESSAGE = 12			! message pointer 
+
+!*========================================================================*
+!                           IPC assembly routines			  *
+!*========================================================================*
+! all message passing routines save ebp, but destroy eax and ecx.
+.define __echo, __notify, __send, __receive, __sendrec 
+.sect .text
+__send:
+	push	ebp
+	mov	ebp, esp
+	push	ebx
+	mov	eax, SRC_DST(ebp)	! eax = dest-src
+	mov	ebx, MESSAGE(ebp)	! ebx = message pointer
+	mov	ecx, SEND		! _send(dest, ptr)
+	int	SYSVEC			! trap to the kernel
+	pop	ebx
+	pop	ebp
+	ret
+
+__receive:
+	push	ebp
+	mov	ebp, esp
+	push	ebx
+	mov	eax, SRC_DST(ebp)	! eax = dest-src
+	mov	ebx, MESSAGE(ebp)	! ebx = message pointer
+	mov	ecx, RECEIVE		! _receive(src, ptr)
+	int	SYSVEC			! trap to the kernel
+	pop	ebx
+	pop	ebp
+	ret
+
+__sendrec:
+	push	ebp
+	mov	ebp, esp
+	push	ebx
+	mov	eax, SRC_DST(ebp)	! eax = dest-src
+	mov	ebx, MESSAGE(ebp)	! ebx = message pointer
+	mov	ecx, SENDREC		! _sendrec(srcdest, ptr)
+	int	SYSVEC			! trap to the kernel
+	pop	ebx
+	pop	ebp
+	ret
+
+__notify:
+	push	ebp
+	mov	ebp, esp
+	push	ebx
+	mov	eax, SRC_DST(ebp)	! ebx = destination 
+	mov	ecx, NOTIFY		! _notify(srcdst)
+	int	SYSVEC			! trap to the kernel
+	pop	ebx
+	pop	ebp
+	ret
+
+__echo:
+	push	ebp
+	mov	ebp, esp
+	push	ebx
+	mov	ebx, ECHO_MESS(ebp)	! ebx = message pointer
+	mov	ecx, ECHO		! _echo(srcdest, ptr)
+	int	SYSVEC			! trap to the kernel
+	pop	ebx
+	pop	ebp
+	ret
+
Index: /trunk/minix/lib/i386/rts/_ipcnew.s
===================================================================
--- /trunk/minix/lib/i386/rts/_ipcnew.s	(revision 9)
+++ /trunk/minix/lib/i386/rts/_ipcnew.s	(revision 9)
@@ -0,0 +1,75 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define __ipc_request, __ipc_reply, __ipc_notify, __ipc_receive
+
+! See src/kernel/ipc.h for C definitions.
+IPC_REQUEST = 16		! each gets a distinct bit
+IPC_REPLY = 32
+IPC_NOTIFY = 64
+IPC_RECEIVE = 128
+
+SYSVEC = 33			! trap to kernel 
+
+! Offsets of arguments relative to stack pointer.
+SRC_DST = 8			! source/ destination process 
+SEND_MSG = 12			! message pointer for sending 
+EVENT_SET = 12			! notification event set 
+RECV_MSG = 16			! message pointer for receiving 
+
+
+!*========================================================================*
+!                           IPC assembly routines			  *
+!*========================================================================*
+! all message passing routines save ebp, but destroy eax, ecx, and edx.
+.define __ipc_request, __ipc_reply, __ipc_notify, __ipc_receive
+.sect .text
+
+__ipc_request:
+	push	ebp
+	mov	ebp, esp
+	push	ebx
+	mov	eax, SRC_DST(ebp)	! eax = destination
+	mov	ebx, SEND_MSG(ebp)	! ebx = message pointer
+	mov	ecx, IPC_REQUEST	! _ipc_request(dst, ptr)
+	int	SYSVEC			! trap to the kernel
+	pop	ebx
+	pop	ebp
+	ret
+
+__ipc_reply:
+	push	ebp
+	mov	ebp, esp
+	push	ebx
+	mov	eax, SRC_DST(ebp)	! eax = destination
+	mov	ebx, SEND_MSG(ebp)	! ebx = message pointer
+	mov	ecx, IPC_REPLY		! _ipc_reply(dst, ptr)
+	int	SYSVEC			! trap to the kernel
+	pop	ebx
+	pop	ebp
+	ret
+
+__ipc_receive:
+	push	ebp
+	mov	ebp, esp
+	push	ebx
+	mov	eax, SRC_DST(ebp)	! eax = source
+	mov	edx, EVENT_SET(ebp)	! ebx = event set
+	mov	ebx, RCV_MSG(ebp)	! ebx = message pointer
+	mov	ecx, IPC_RECEIVE	! _ipc_receive(src, events, ptr)
+	int	SYSVEC			! trap to the kernel
+	pop	ebx
+	pop	ebp
+	ret
+
+__ipc_notify:
+	push	ebp
+	mov	ebp, esp
+	push	ebx
+	mov	eax, SRC_DST(ebp)	! ebx = destination 
+	mov	edx, EVENT_SET(ebp)	! edx = event set 
+	mov	ecx, IPC_NOTIFY		! _ipc_notify(dst, events)
+	int	SYSVEC			! trap to the kernel
+	pop	ebx
+	pop	ebp
+	ret
+
+
Index: /trunk/minix/lib/i386/rts/brksize.s
===================================================================
--- /trunk/minix/lib/i386/rts/brksize.s	(revision 9)
+++ /trunk/minix/lib/i386/rts/brksize.s	(revision 9)
@@ -0,0 +1,5 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define __brksize
+.sect .data
+.extern endbss, __brksize
+__brksize: .data4 endbss
Index: /trunk/minix/lib/i386/rts/crtso.s
===================================================================
--- /trunk/minix/lib/i386/rts/crtso.s	(revision 9)
+++ /trunk/minix/lib/i386/rts/crtso.s	(revision 9)
@@ -0,0 +1,72 @@
+! This is the C run-time start-off routine.  It's job is to take the
+! arguments as put on the stack by EXEC, and to parse them and set them up the
+! way _main expects them.
+! It also initializes _environ when this variable isn't defined by the
+! programmer.  The detection of whether _environ belong to us is rather
+! simplistic.  We simply check for some magic value, but there is no other
+! way.
+
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+.define begtext, begdata, begbss
+.sect .text
+begtext:
+.sect .rom
+begrom:
+.sect .data
+begdata:
+.sect .bss
+begbss:
+
+.define crtso, __penviron, __penvp, __fpu_present
+.extern _main, _exit
+.sect .text
+crtso:
+	xor     ebp, ebp		! clear for backtrace of core files
+	mov     eax, (esp)		! argc
+	lea     edx, 4(esp)		! argv
+	lea     ecx, 8(esp)(eax*4)	! envp
+
+	! Test if environ is in the initialized data area and is set to our
+	! magic number.  If so then it is not redefined by the user.
+	mov	ebx, _environ
+	cmp	ebx, __edata		! within initialized data?
+	jae	0f
+	testb	bl, 3			! aligned?
+	jnz	0f
+	cmp	(ebx), 0x53535353	! is it our _environ?
+	jne	0f
+	mov	(__penviron), ebx	! _penviron = &environ;
+0:	mov	ebx, (__penviron)
+	mov	(ebx), ecx		! *_penviron = envp;
+
+	push	ecx			! push envp
+	push	edx			! push argv
+	push	eax			! push argc
+
+	! Test the EM bit of the MSW to determine if an FPU is present and
+	! set __fpu_present if one is found.
+	smsw	ax
+	testb	al, 0x4			! EM bit in MSW
+	setz	(__fpu_present)		! True if not set
+
+	call	_main			! main(argc, argv, envp)
+
+	push	eax			! push exit status
+	call	_exit
+
+	hlt				! force a trap if exit fails
+
+.sect .rom
+	.data4	0			! Separate I&D: *NULL == 0
+					! Also keeps the first string in the
+					! program from appearing at location 0!
+.sect .data
+__penviron:
+	.data4	__penvp			! Pointer to environ, or hidden pointer
+
+.sect .bss
+	.comm	__penvp, 4		! Hidden environment vector
+	.comm	__fpu_present, 4	! FPU present flag
+
+.extern endtext				! Force loading of end labels.
Index: /trunk/minix/lib/i386/rts/m2rtso.s
===================================================================
--- /trunk/minix/lib/i386/rts/m2rtso.s	(revision 9)
+++ /trunk/minix/lib/i386/rts/m2rtso.s	(revision 9)
@@ -0,0 +1,67 @@
+! This is the Modula-2 run-time start-off routine.  It's job is to take the
+! arguments as put on the stack by EXEC, and to parse them and set them up the
+! way _m_a_i_n expects them.
+
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+.define begtext, begdata, begbss
+.sect .text
+begtext:
+.sect .rom
+begrom:
+.sect .data
+begdata:
+.sect .bss
+begbss:
+
+.define m2rtso, hol0, __penviron, __penvp, __fpu_present
+.sect .text
+m2rtso:
+	xor	ebp, ebp		! clear for backtrace of core files
+	mov	eax, (esp)		! argc
+	lea	edx, 4(esp)		! argv
+	lea	ecx, 8(esp)(eax*4)	! envp
+
+	! Test if environ is in the initialized data area and is set to our
+	! magic number.  If so then it is not redefined by the user.
+	mov	ebx, _environ
+	cmp	ebx, __edata		! within initialized data?
+	jae	0f
+	testb	bl, 3			! aligned?
+	jnz	0f
+	cmp	(ebx), 0x53535353	! is it our environ?
+	jne	0f
+	mov	(__penviron), ebx	! _penviron = &environ;
+0:	mov	ebx, (__penviron)
+	mov	(ebx), ecx		! *_penviron = envp;
+
+	push	ecx			! push envp
+	push	edx			! push argv
+	push	eax			! push argc
+
+	! Test the EM bit of the MSW to determine if an FPU is present and
+	! set __fpu_present if one is found.
+	smsw	ax
+	testb	al, 0x4			! EM bit in MSW
+	setz	(__fpu_present)		! True if not set
+
+	call	__m_a_i_n		! run Modula-2 program
+
+	push	eax			! push exit status
+	call	__exit
+
+	hlt				! force a trap if exit fails
+
+.sect .rom
+	.data4	0			! Separate I&D: *NULL == 0
+					! Also keeps the first string in the
+					! program from appearing at location 0!
+.sect .data
+__penviron:
+	.data4	__penvp			! Pointer to environ, or hidden pointer
+
+.sect .bss
+	.comm	__penvp, 4		! Hidden environment vector
+	.comm	__fpu_present, 4	! FPU present flag
+
+.extern endtext				! Force loading of end labels.
Index: /trunk/minix/lib/i386/rts/prtso.s
===================================================================
--- /trunk/minix/lib/i386/rts/prtso.s	(revision 9)
+++ /trunk/minix/lib/i386/rts/prtso.s	(revision 9)
@@ -0,0 +1,69 @@
+! This is the Pascal run-time start-off routine.  It's job is to take the
+! arguments as put on the stack by EXEC, and to parse them and set them up the
+! way _m_a_i_n expects them.
+
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+.define begtext, begdata, begbss
+.sect .text
+begtext:
+.sect .rom
+begrom:
+.sect .data
+begdata:
+.sect .bss
+begbss:
+
+.define prtso, hol0, __penviron, __penvp, __fpu_present
+.sect .text
+prtso:
+	xor	ebp, ebp		! clear for backtrace of core files
+	mov	eax, (esp)		! argc
+	lea	edx, 4(esp)		! argv
+	lea	ecx, 8(esp)(eax*4)	! envp
+
+	! Test if environ is in the initialized data area and is set to our
+	! magic number.  If so then it is not redefined by the user.
+	mov	ebx, _environ
+	cmp	ebx, __edata		! within initialized data?
+	jae	0f
+	testb	bl, 3			! aligned?
+	jnz	0f
+	cmp	(ebx), 0x53535353	! is it our environ?
+	jne	0f
+	mov	(__penviron), ebx	! _penviron = &environ;
+0:	mov	ebx, (__penviron)
+	mov	(ebx), ecx		! *_penviron = envp;
+
+	push	ecx			! push envp
+	push	edx			! push argv
+	push	eax			! push argc
+
+	! Test the EM bit of the MSW to determine if an FPU is present and
+	! set __fpu_present if one is found.
+	smsw	ax
+	testb	al, 0x4			! EM bit in MSW
+	setz	(__fpu_present)		! True if not set
+
+	mov	(.ignmask), 56
+
+	call	__m_a_i_n		! Run Pascal program
+
+	push	eax			! push exit status
+	call	__exit
+
+	hlt				! force a trap if exit fails
+
+.sect .rom
+	.data4	0			! Separate I&D: *NULL == 0
+					! Also keeps the first string in the
+					! program from appearing at location 0!
+.sect .data
+__penviron:
+	.data4	__penvp			! Pointer to environ, or hidden pointer
+
+.sect .bss
+	.comm	__penvp, 4		! Hidden environment vector
+	.comm	__fpu_present, 4	! FPU present flag
+
+.extern endtext				! Force loading of end labels.
Index: /trunk/minix/lib/i386/string/Makedepend-ack
===================================================================
--- /trunk/minix/lib/i386/string/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/i386/string/Makedepend-ack	(revision 9)
@@ -0,0 +1,28 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc  -E' _memmove.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' _strncat.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' _strncmp.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' _strncpy.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' _strnlen.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' bcmp.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' bcopy.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' bzero.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' index.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' memchr.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' memcmp.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' memcpy.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' memmove.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' memset.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' rindex.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' strcat.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' strchr.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' strcmp.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' strcpy.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' strlen.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' strncat.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' strncmp.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' strncpy.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' strnlen.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
+	mkdep 'cc  -E' strrchr.s | sed -e 's:^\(.\):../../obj-ack//./i386/string/\1:' >> .depend-ack
Index: /trunk/minix/lib/i386/string/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/i386/string/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/i386/string/Makedepend-gnu	(revision 9)
@@ -0,0 +1,28 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' _memmove.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' _strncat.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' _strncmp.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' _strncpy.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' _strnlen.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' bcmp.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' bcopy.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' bzero.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' index.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' memchr.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' memcmp.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' memcpy.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' memmove.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' memset.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' rindex.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' strcat.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' strchr.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' strcmp.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' strcpy.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' strlen.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' strncat.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' strncmp.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' strncpy.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' strnlen.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' strrchr.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../../obj-gnu/./i386/string/\1:' >> .depend-gnu
Index: /trunk/minix/lib/i386/string/Makefile
===================================================================
--- /trunk/minix/lib/i386/string/Makefile	(revision 9)
+++ /trunk/minix/lib/i386/string/Makefile	(revision 9)
@@ -0,0 +1,245 @@
+#Generated from ./i386/string/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../../generate.sh ./i386/string ../../obj-ack/ ../../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../../generate.sh ./i386/string ../../obj-ack/ ../../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../../obj-ack//libc.a
+
+../../obj-ack//libc.a: ../../obj-ack//libc.a(_memmove.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(_strncat.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(_strncmp.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(_strncpy.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(_strnlen.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(bcmp.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(bcopy.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(bzero.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(index.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(memchr.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(memcmp.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(memcpy.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(memmove.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(memset.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(rindex.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(strcat.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(strchr.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(strcmp.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(strcpy.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(strlen.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(strncat.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(strncmp.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(strncpy.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(strnlen.o)
+../../obj-ack//libc.a: ../../obj-ack//libc.a(strrchr.o)
+
+../../obj-ack//libc.a:
+	ar cr ../../obj-ack//libc.a ../../obj-ack//./i386/string/*.o
+	rm ../../obj-ack//./i386/string/*.o
+
+../../obj-ack//libc.a(_memmove.o): _memmove.s
+	cc  -c -o ../../obj-ack//./i386/string/_memmove.o _memmove.s
+../../obj-ack//libc.a(_strncat.o): _strncat.s
+	cc  -c -o ../../obj-ack//./i386/string/_strncat.o _strncat.s
+../../obj-ack//libc.a(_strncmp.o): _strncmp.s
+	cc  -c -o ../../obj-ack//./i386/string/_strncmp.o _strncmp.s
+../../obj-ack//libc.a(_strncpy.o): _strncpy.s
+	cc  -c -o ../../obj-ack//./i386/string/_strncpy.o _strncpy.s
+../../obj-ack//libc.a(_strnlen.o): _strnlen.s
+	cc  -c -o ../../obj-ack//./i386/string/_strnlen.o _strnlen.s
+../../obj-ack//libc.a(bcmp.o): bcmp.s
+	cc  -c -o ../../obj-ack//./i386/string/bcmp.o bcmp.s
+../../obj-ack//libc.a(bcopy.o): bcopy.s
+	cc  -c -o ../../obj-ack//./i386/string/bcopy.o bcopy.s
+../../obj-ack//libc.a(bzero.o): bzero.s
+	cc  -c -o ../../obj-ack//./i386/string/bzero.o bzero.s
+../../obj-ack//libc.a(index.o): index.s
+	cc  -c -o ../../obj-ack//./i386/string/index.o index.s
+../../obj-ack//libc.a(memchr.o): memchr.s
+	cc  -c -o ../../obj-ack//./i386/string/memchr.o memchr.s
+../../obj-ack//libc.a(memcmp.o): memcmp.s
+	cc  -c -o ../../obj-ack//./i386/string/memcmp.o memcmp.s
+../../obj-ack//libc.a(memcpy.o): memcpy.s
+	cc  -c -o ../../obj-ack//./i386/string/memcpy.o memcpy.s
+../../obj-ack//libc.a(memmove.o): memmove.s
+	cc  -c -o ../../obj-ack//./i386/string/memmove.o memmove.s
+../../obj-ack//libc.a(memset.o): memset.s
+	cc  -c -o ../../obj-ack//./i386/string/memset.o memset.s
+../../obj-ack//libc.a(rindex.o): rindex.s
+	cc  -c -o ../../obj-ack//./i386/string/rindex.o rindex.s
+../../obj-ack//libc.a(strcat.o): strcat.s
+	cc  -c -o ../../obj-ack//./i386/string/strcat.o strcat.s
+../../obj-ack//libc.a(strchr.o): strchr.s
+	cc  -c -o ../../obj-ack//./i386/string/strchr.o strchr.s
+../../obj-ack//libc.a(strcmp.o): strcmp.s
+	cc  -c -o ../../obj-ack//./i386/string/strcmp.o strcmp.s
+../../obj-ack//libc.a(strcpy.o): strcpy.s
+	cc  -c -o ../../obj-ack//./i386/string/strcpy.o strcpy.s
+../../obj-ack//libc.a(strlen.o): strlen.s
+	cc  -c -o ../../obj-ack//./i386/string/strlen.o strlen.s
+../../obj-ack//libc.a(strncat.o): strncat.s
+	cc  -c -o ../../obj-ack//./i386/string/strncat.o strncat.s
+../../obj-ack//libc.a(strncmp.o): strncmp.s
+	cc  -c -o ../../obj-ack//./i386/string/strncmp.o strncmp.s
+../../obj-ack//libc.a(strncpy.o): strncpy.s
+	cc  -c -o ../../obj-ack//./i386/string/strncpy.o strncpy.s
+../../obj-ack//libc.a(strnlen.o): strnlen.s
+	cc  -c -o ../../obj-ack//./i386/string/strnlen.o strnlen.s
+../../obj-ack//libc.a(strrchr.o): strrchr.s
+	cc  -c -o ../../obj-ack//./i386/string/strrchr.o strrchr.s
+
+all-gnu: ../../obj-gnu/libc.a
+
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/_memmove.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/_strncat.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/_strncmp.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/_strncpy.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/_strnlen.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/bcmp.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/bcopy.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/bzero.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/index.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/memchr.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/memcmp.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/memcpy.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/memmove.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/memset.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/rindex.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/strcat.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/strchr.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/strcmp.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/strcpy.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/strlen.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/strncat.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/strncmp.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/strncpy.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/strnlen.o
+../../obj-gnu/libc.a: ../../obj-gnu/./i386/string/strrchr.o
+
+../../obj-gnu/libc.a:
+	gar cr ../../obj-gnu/libc.a $?
+
+../../obj-gnu/./i386/string/_memmove.o: _memmove.s
+	gcc  -E -x assembler-with-cpp -I. _memmove.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/_memmove.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/_memmove.o ../../obj-gnu/./i386/string/_memmove.s.gnu
+
+../../obj-gnu/./i386/string/_strncat.o: _strncat.s
+	gcc  -E -x assembler-with-cpp -I. _strncat.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/_strncat.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/_strncat.o ../../obj-gnu/./i386/string/_strncat.s.gnu
+
+../../obj-gnu/./i386/string/_strncmp.o: _strncmp.s
+	gcc  -E -x assembler-with-cpp -I. _strncmp.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/_strncmp.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/_strncmp.o ../../obj-gnu/./i386/string/_strncmp.s.gnu
+
+../../obj-gnu/./i386/string/_strncpy.o: _strncpy.s
+	gcc  -E -x assembler-with-cpp -I. _strncpy.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/_strncpy.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/_strncpy.o ../../obj-gnu/./i386/string/_strncpy.s.gnu
+
+../../obj-gnu/./i386/string/_strnlen.o: _strnlen.s
+	gcc  -E -x assembler-with-cpp -I. _strnlen.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/_strnlen.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/_strnlen.o ../../obj-gnu/./i386/string/_strnlen.s.gnu
+
+../../obj-gnu/./i386/string/bcmp.o: bcmp.s
+	gcc  -E -x assembler-with-cpp -I. bcmp.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/bcmp.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/bcmp.o ../../obj-gnu/./i386/string/bcmp.s.gnu
+
+../../obj-gnu/./i386/string/bcopy.o: bcopy.s
+	gcc  -E -x assembler-with-cpp -I. bcopy.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/bcopy.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/bcopy.o ../../obj-gnu/./i386/string/bcopy.s.gnu
+
+../../obj-gnu/./i386/string/bzero.o: bzero.s
+	gcc  -E -x assembler-with-cpp -I. bzero.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/bzero.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/bzero.o ../../obj-gnu/./i386/string/bzero.s.gnu
+
+../../obj-gnu/./i386/string/index.o: index.s
+	gcc  -E -x assembler-with-cpp -I. index.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/index.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/index.o ../../obj-gnu/./i386/string/index.s.gnu
+
+../../obj-gnu/./i386/string/memchr.o: memchr.s
+	gcc  -E -x assembler-with-cpp -I. memchr.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/memchr.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/memchr.o ../../obj-gnu/./i386/string/memchr.s.gnu
+
+../../obj-gnu/./i386/string/memcmp.o: memcmp.s
+	gcc  -E -x assembler-with-cpp -I. memcmp.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/memcmp.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/memcmp.o ../../obj-gnu/./i386/string/memcmp.s.gnu
+
+../../obj-gnu/./i386/string/memcpy.o: memcpy.s
+	gcc  -E -x assembler-with-cpp -I. memcpy.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/memcpy.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/memcpy.o ../../obj-gnu/./i386/string/memcpy.s.gnu
+
+../../obj-gnu/./i386/string/memmove.o: memmove.s
+	gcc  -E -x assembler-with-cpp -I. memmove.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/memmove.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/memmove.o ../../obj-gnu/./i386/string/memmove.s.gnu
+
+../../obj-gnu/./i386/string/memset.o: memset.s
+	gcc  -E -x assembler-with-cpp -I. memset.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/memset.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/memset.o ../../obj-gnu/./i386/string/memset.s.gnu
+
+../../obj-gnu/./i386/string/rindex.o: rindex.s
+	gcc  -E -x assembler-with-cpp -I. rindex.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/rindex.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/rindex.o ../../obj-gnu/./i386/string/rindex.s.gnu
+
+../../obj-gnu/./i386/string/strcat.o: strcat.s
+	gcc  -E -x assembler-with-cpp -I. strcat.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/strcat.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/strcat.o ../../obj-gnu/./i386/string/strcat.s.gnu
+
+../../obj-gnu/./i386/string/strchr.o: strchr.s
+	gcc  -E -x assembler-with-cpp -I. strchr.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/strchr.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/strchr.o ../../obj-gnu/./i386/string/strchr.s.gnu
+
+../../obj-gnu/./i386/string/strcmp.o: strcmp.s
+	gcc  -E -x assembler-with-cpp -I. strcmp.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/strcmp.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/strcmp.o ../../obj-gnu/./i386/string/strcmp.s.gnu
+
+../../obj-gnu/./i386/string/strcpy.o: strcpy.s
+	gcc  -E -x assembler-with-cpp -I. strcpy.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/strcpy.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/strcpy.o ../../obj-gnu/./i386/string/strcpy.s.gnu
+
+../../obj-gnu/./i386/string/strlen.o: strlen.s
+	gcc  -E -x assembler-with-cpp -I. strlen.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/strlen.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/strlen.o ../../obj-gnu/./i386/string/strlen.s.gnu
+
+../../obj-gnu/./i386/string/strncat.o: strncat.s
+	gcc  -E -x assembler-with-cpp -I. strncat.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/strncat.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/strncat.o ../../obj-gnu/./i386/string/strncat.s.gnu
+
+../../obj-gnu/./i386/string/strncmp.o: strncmp.s
+	gcc  -E -x assembler-with-cpp -I. strncmp.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/strncmp.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/strncmp.o ../../obj-gnu/./i386/string/strncmp.s.gnu
+
+../../obj-gnu/./i386/string/strncpy.o: strncpy.s
+	gcc  -E -x assembler-with-cpp -I. strncpy.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/strncpy.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/strncpy.o ../../obj-gnu/./i386/string/strncpy.s.gnu
+
+../../obj-gnu/./i386/string/strnlen.o: strnlen.s
+	gcc  -E -x assembler-with-cpp -I. strnlen.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/strnlen.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/strnlen.o ../../obj-gnu/./i386/string/strnlen.s.gnu
+
+../../obj-gnu/./i386/string/strrchr.o: strrchr.s
+	gcc  -E -x assembler-with-cpp -I. strrchr.s | asmconv -mi386 ack gnu > ../../obj-gnu/./i386/string/strrchr.s.gnu || true
+	gas -o ../../obj-gnu/./i386/string/strrchr.o ../../obj-gnu/./i386/string/strrchr.s.gnu
+
+
+
+
+clean::
+	rm -f ../../obj-ack//./i386/string/*
+	rm -f ../../obj-gnu/./i386/string/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/i386/string/Makefile.in
===================================================================
--- /trunk/minix/lib/i386/string/Makefile.in	(revision 9)
+++ /trunk/minix/lib/i386/string/Makefile.in	(revision 9)
@@ -0,0 +1,32 @@
+# Makefile for lib/i386/string.
+
+LIBRARIES=libc
+
+libc_FILES=" \
+	_memmove.s \
+	_strncat.s \
+	_strncmp.s \
+	_strncpy.s \
+	_strnlen.s \
+	bcmp.s \
+	bcopy.s \
+	bzero.s \
+	index.s \
+	memchr.s \
+	memcmp.s \
+	memcpy.s \
+	memmove.s \
+	memset.s \
+	rindex.s \
+	strcat.s \
+	strchr.s \
+	strcmp.s \
+	strcpy.s \
+	strlen.s \
+	strncat.s \
+	strncmp.s \
+	strncpy.s \
+	strnlen.s \
+	strrchr.s"
+
+TYPE=both
Index: /trunk/minix/lib/i386/string/README
===================================================================
--- /trunk/minix/lib/i386/string/README	(revision 9)
+++ /trunk/minix/lib/i386/string/README	(revision 9)
@@ -0,0 +1,52 @@
+Notes on i80386 string assembly routines.		Author: Kees J. Bot
+								2 Jan 1994
+
+Remarks.
+    All routines set up proper stack frames, so that stack traces can be
+    derived from core dumps.  String routines are often the ones that
+    get the bad pointer.
+
+    Flags are often not right in boundary cases (zero string length) on
+    repeated string scanning or comparing instructions.  This has been
+    handled in sometimes nonobvious ways.
+
+    Only the eax, edx, and ecx registers are not preserved, all other
+    registers are.  This is what GCC expects.  (ACK sees ebx as scratch
+    too.)  The direction byte is assumed to be wrong, and left clear on
+    exit.
+
+Assumptions.
+    The average string is short, so short strings should not suffer from
+    smart tricks to copy, compare, or search large strings fast.  This
+    means that the routines are fast on average, but not optimal for
+    long strings.
+
+    It doesn't pay to use word or longword operations on strings, the
+    setup time hurts the average case.
+
+    Memory blocks are probably large and on word or longword boundaries.
+
+    No unaligned word moves are done.  Again the setup time may hurt the
+    average case.  Furthermore, the author likes to enable the alignment
+    check on a 486.
+
+String routines.
+    They have been implemented using byte string instructions.  The
+    length of a string it usually determined first, followed by the
+    actual operation.
+
+Strcmp.
+    This is the only string routine that uses a loop, and not
+    instructions with a repeat prefix.  Problem is that we don't know
+    how long the string is.  Scanning for the end costs if the strings
+    are unequal in the first few bytes.
+
+Strchr.
+    The character we look for is often not there, or at some distance
+    from the start.  The string is scanned twice, for the terminating
+    zero and the character searched, in chunks of increasing length.
+
+Memory routines.
+    Memmove, memcpy, and memset use word or longword instructions if the
+    address(es) are at word or longword boundaries.  No tricks to get
+    alignment after doing a few bytes.  No unaligned operations.
Index: /trunk/minix/lib/i386/string/_memmove.s
===================================================================
--- /trunk/minix/lib/i386/string/_memmove.s	(revision 9)
+++ /trunk/minix/lib/i386/string/_memmove.s	(revision 9)
@@ -0,0 +1,58 @@
+!	_memmove()					Author: Kees J. Bot
+!								2 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! void *_memmove(void *s1, const void *s2, size_t n)
+!	Copy a chunk of memory.  Handle overlap.
+!
+.sect .text
+.define __memmove, __memcpy
+	.align	16
+__memmove:
+	push	ebp
+	mov	ebp, esp
+	push	esi
+	push	edi
+	mov	edi, 8(ebp)	! String s1
+	mov	esi, 12(ebp)	! String s2
+	mov	ecx, 16(ebp)	! Length
+	mov	eax, edi
+	sub	eax, esi
+	cmp	eax, ecx
+	jb	downwards	! if (s2 - s1) < n then copy downwards
+__memcpy:
+	cld			! Clear direction bit: upwards
+	cmp	ecx, 16
+	jb	upbyte		! Don't bother being smart with short arrays
+	mov	eax, esi
+	or	eax, edi
+	testb	al, 1
+	jnz	upbyte		! Bit 0 set, use byte copy
+	testb	al, 2
+	jnz	upword		! Bit 1 set, use word copy
+uplword:shrd	eax, ecx, 2	! Save low 2 bits of ecx in eax
+	shr	ecx, 2
+	rep
+	movs			! Copy longwords.
+	shld	ecx, eax, 2	! Restore excess count
+upword:	shr	ecx, 1
+	rep
+    o16	movs			! Copy words
+	adc	ecx, ecx	! One more byte?
+upbyte:	rep
+	movsb			! Copy bytes
+done:	mov	eax, 8(ebp)	! Absolutely noone cares about this value
+	pop	edi
+	pop	esi
+	pop	ebp
+	ret
+
+! Handle bad overlap by copying downwards, don't bother to do word copies.
+downwards:
+	std			! Set direction bit: downwards
+	lea	esi, -1(esi)(ecx*1)
+	lea	edi, -1(edi)(ecx*1)
+	rep
+	movsb			! Copy bytes
+	cld
+	jmp	done
Index: /trunk/minix/lib/i386/string/_strncat.s
===================================================================
--- /trunk/minix/lib/i386/string/_strncat.s	(revision 9)
+++ /trunk/minix/lib/i386/string/_strncat.s	(revision 9)
@@ -0,0 +1,41 @@
+!	_strncat()					Author: Kees J. Bot
+!								1 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *_strncat(char *s1, const char *s2, size_t edx)
+!	Append string s2 to s1.
+!
+.sect .text
+.define __strncat
+	.align	16
+__strncat:
+	push	ebp
+	mov	ebp, esp
+	push	esi
+	push	edi
+	mov	edi, 8(ebp)	! String s1
+	mov	ecx, -1
+	xorb	al, al		! Null byte
+	cld
+	repne
+	scasb			! Look for the zero byte in s1
+	dec	edi		! Back one up (and clear 'Z' flag)
+	push	edi		! Save end of s1
+	mov	edi, 12(ebp)	! edi = string s2
+	mov	ecx, edx	! Maximum count
+	repne
+	scasb			! Look for the end of s2
+	jne	no0
+	inc	ecx		! Exclude null byte
+no0:	sub	edx, ecx	! Number of bytes in s2
+	mov	ecx, edx
+	mov	esi, 12(ebp)	! esi = string s2
+	pop	edi		! edi = end of string s1
+	rep
+	movsb			! Copy bytes
+	stosb			! Add a terminating null
+	mov	eax, 8(ebp)	! Return s1
+	pop	edi
+	pop	esi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/string/_strncmp.s
===================================================================
--- /trunk/minix/lib/i386/string/_strncmp.s	(revision 9)
+++ /trunk/minix/lib/i386/string/_strncmp.s	(revision 9)
@@ -0,0 +1,35 @@
+!	strncmp()					Author: Kees J. Bot
+!								1 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! int strncmp(const char *s1, const char *s2, size_t ecx)
+!	Compare two strings.
+!
+.sect .text
+.define __strncmp
+	.align	16
+__strncmp:
+	push	ebp
+	mov	ebp, esp
+	push	esi
+	push	edi
+	test	ecx, ecx	! Max length is zero?
+	je	done
+	mov	esi, 8(ebp)	! esi = string s1
+	mov	edi, 12(ebp)	! edi = string s2
+	cld
+compare:
+	cmpsb			! Compare two bytes
+	jne	done
+	cmpb	-1(esi), 0	! End of string?
+	je	done
+	dec	ecx		! Length limit reached?
+	jne	compare
+done:	seta	al		! al = (s1 > s2)
+	setb	ah		! ah = (s1 < s2)
+	subb	al, ah
+	movsxb	eax, al		! eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1
+	pop	edi
+	pop	esi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/string/_strncpy.s
===================================================================
--- /trunk/minix/lib/i386/string/_strncpy.s	(revision 9)
+++ /trunk/minix/lib/i386/string/_strncpy.s	(revision 9)
@@ -0,0 +1,24 @@
+!	_strncpy()					Author: Kees J. Bot
+!								1 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *_strncpy(char *s1, const char *s2, size_t ecx)
+!	Copy string s2 to s1.
+!
+.sect .text
+.define __strncpy
+	.align	16
+__strncpy:
+	mov	edi, 12(ebp)	! edi = string s2
+	xorb	al, al		! Look for a zero byte
+	mov	edx, ecx	! Save maximum count
+	cld
+	repne
+	scasb			! Look for end of s2
+	sub	edx, ecx	! Number of bytes in s2 including null
+	xchg	ecx, edx
+	mov	esi, 12(ebp)	! esi = string s2
+	mov	edi, 8(ebp)	! edi = string s1
+	rep
+	movsb			! Copy bytes
+	ret
Index: /trunk/minix/lib/i386/string/_strnlen.s
===================================================================
--- /trunk/minix/lib/i386/string/_strnlen.s	(revision 9)
+++ /trunk/minix/lib/i386/string/_strnlen.s	(revision 9)
@@ -0,0 +1,28 @@
+!	_strnlen()					Author: Kees J. Bot
+!								1 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! size_t _strnlen(const char *s, size_t ecx)
+!	Return the length of a string.
+!
+.sect .text
+.define __strnlen
+	.align	16
+__strnlen:
+	push	ebp
+	mov	ebp, esp
+	push	edi
+	mov	edi, 8(ebp)	! edi = string
+	xorb	al, al		! Look for a zero byte
+	mov	edx, ecx	! Save maximum count
+	cmpb	cl, 1		! 'Z' bit must be clear if ecx = 0
+	cld
+	repne
+	scasb			! Look for zero
+	jne	no0
+	inc	ecx		! Don't count zero byte
+no0:	mov	eax, edx
+	sub	eax, ecx	! Compute bytes scanned
+	pop	edi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/string/bcmp.s
===================================================================
--- /trunk/minix/lib/i386/string/bcmp.s	(revision 9)
+++ /trunk/minix/lib/i386/string/bcmp.s	(revision 9)
@@ -0,0 +1,28 @@
+!	bcmp()						Author: Kees J. Bot
+!								2 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! int bcmp(const void *s1, const void *s2, size_t n)
+!	Compare two chunks of memory.
+!	This is a BSD routine that escaped from the kernel.  Don't use.
+!	(Alas it is not without some use, it reports the number of bytes
+!	after the bytes that are equal.  So it can't be simply replaced.)
+!
+.sect .text
+.define _bcmp
+	.align	16
+_bcmp:
+	push	ebp
+	mov	ebp, esp
+	push	16(ebp)
+	push	12(ebp)
+	push	8(ebp)
+	call	_memcmp		! Let memcmp do the work
+	test	eax, eax
+	jz	equal
+	sub	edx, 8(ebp)	! Memcmp was nice enough to leave "esi" in edx
+	dec	edx		! Number of bytes that are equal
+	mov	eax, 16(ebp)
+	sub	eax, edx	! Number of bytes that are unequal
+equal:	leave
+	ret
Index: /trunk/minix/lib/i386/string/bcopy.s
===================================================================
--- /trunk/minix/lib/i386/string/bcopy.s	(revision 9)
+++ /trunk/minix/lib/i386/string/bcopy.s	(revision 9)
@@ -0,0 +1,16 @@
+!	bcopy()						Author: Kees J. Bot
+!								2 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! void bcopy(const void *s1, void *s2, size_t n)
+!	Copy a chunk of memory.  Handle overlap.
+!	This is a BSD routine that escaped from the kernel.  Don't use.
+!
+.sect .text
+.define _bcopy
+	.align	16
+_bcopy:
+	mov	eax, 4(esp)	! Exchange string arguments
+	xchg	eax, 8(esp)
+	mov	4(esp), eax
+	jmp	__memmove	! Call the proper routine
Index: /trunk/minix/lib/i386/string/bzero.s
===================================================================
--- /trunk/minix/lib/i386/string/bzero.s	(revision 9)
+++ /trunk/minix/lib/i386/string/bzero.s	(revision 9)
@@ -0,0 +1,20 @@
+!	bzero()						Author: Kees J. Bot
+!								2 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! void bzero(void *s, size_t n)
+!	Set a chunk of memory to zero.
+!	This is a BSD routine that escaped from the kernel.  Don't use.
+!
+.sect .text
+.define _bzero
+	.align	16
+_bzero:
+	push	ebp
+	mov	ebp, esp
+	push	12(ebp)		! Size
+	push	0		! Zero
+	push	8(ebp)		! String
+	call	_memset		! Call the proper routine
+	leave
+	ret
Index: /trunk/minix/lib/i386/string/index.s
===================================================================
--- /trunk/minix/lib/i386/string/index.s	(revision 9)
+++ /trunk/minix/lib/i386/string/index.s	(revision 9)
@@ -0,0 +1,13 @@
+!	index()						Author: Kees J. Bot
+!								2 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *index(const char *s, int c)
+!	Look for a character in a string.  Has suffered from a hostile
+!	takeover by strchr().
+!
+.sect .text
+.define _index
+	.align	16
+_index:
+	jmp	_strchr
Index: /trunk/minix/lib/i386/string/memchr.s
===================================================================
--- /trunk/minix/lib/i386/string/memchr.s	(revision 9)
+++ /trunk/minix/lib/i386/string/memchr.s	(revision 9)
@@ -0,0 +1,30 @@
+!	memchr()					Author: Kees J. Bot
+!								2 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! void *memchr(const void *s, int c, size_t n)
+!	Look for a character in a chunk of memory.
+!
+.sect .text
+.define _memchr
+	.align	16
+_memchr:
+	push	ebp
+	mov	ebp, esp
+	push	edi
+	mov	edi, 8(ebp)	! edi = string
+	movb	al, 12(ebp)	! The character to look for
+	mov	ecx, 16(ebp)	! Length
+	cmpb	cl, 1		! 'Z' bit must be clear if ecx = 0
+	cld
+	repne
+	scasb
+	jne	failure
+	lea	eax, -1(edi)	! Found
+	pop	edi
+	pop	ebp
+	ret
+failure:xor	eax, eax
+	pop	edi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/string/memcmp.s
===================================================================
--- /trunk/minix/lib/i386/string/memcmp.s	(revision 9)
+++ /trunk/minix/lib/i386/string/memcmp.s	(revision 9)
@@ -0,0 +1,56 @@
+!	memcmp()					Author: Kees J. Bot
+!								2 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! int memcmp(const void *s1, const void *s2, size_t n)
+!	Compare two chunks of memory.
+!
+.sect .text
+.define _memcmp
+	.align	16
+_memcmp:
+	cld
+	push	ebp
+	mov	ebp, esp
+	push	esi
+	push	edi
+	mov	esi, 8(ebp)	! String s1
+	mov	edi, 12(ebp)	! String s2
+	mov	ecx, 16(ebp)	! Length
+	cmp	ecx, 16
+	jb	cbyte		! Don't bother being smart with short arrays
+	mov	eax, esi
+	or	eax, edi
+	testb	al, 1
+	jnz	cbyte		! Bit 0 set, use byte compare
+	testb	al, 2
+	jnz	cword		! Bit 1 set, use word compare
+clword:	shrd	eax, ecx, 2	! Save low two bits of ecx in eax
+	shr	ecx, 2
+	repe
+	cmps			! Compare longwords
+	sub	esi, 4
+	sub	edi, 4
+	inc	ecx		! Recompare the last longword
+	shld	ecx, eax, 2	! And any excess bytes
+	jmp	last
+cword:	shrd	eax, ecx, 1	! Save low bit of ecx in eax
+	shr	ecx, 1
+	repe
+    o16	cmps			! Compare words
+	sub	esi, 2
+	sub	edi, 2
+	inc	ecx		! Recompare the last word
+	shld	ecx, eax, 1	! And one more byte?
+cbyte:	test	ecx, ecx	! Set 'Z' flag if ecx = 0
+last:	repe
+	cmpsb			! Look for the first differing byte
+	seta	al		! al = (s1 > s2)
+	setb	ah		! ah = (s1 < s2)
+	subb	al, ah
+	movsxb	eax, al		! eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1
+	mov	edx, esi	! For bcmp() to play with
+	pop	edi
+	pop	esi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/string/memcpy.s
===================================================================
--- /trunk/minix/lib/i386/string/memcpy.s	(revision 9)
+++ /trunk/minix/lib/i386/string/memcpy.s	(revision 9)
@@ -0,0 +1,24 @@
+!	memcpy()					Author: Kees J. Bot
+!								2 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! void *memcpy(void *s1, const void *s2, size_t n)
+!	Copy a chunk of memory.
+!	This routine need not handle overlap, so it does not handle overlap.
+!	One could simply call __memmove, the cost of the overlap check is
+!	negligible, but you are dealing with a programmer who believes that
+!	if anything can go wrong, it should go wrong.
+!
+.sect .text
+.define _memcpy
+	.align	16
+_memcpy:
+	push	ebp
+	mov	ebp, esp
+	push	esi
+	push	edi
+	mov	edi, 8(ebp)	! String s1
+	mov	esi, 12(ebp)	! String s2
+	mov	ecx, 16(ebp)	! Length
+	! No overlap check here
+	jmp	__memcpy	! Call the part of __memmove that copies up
Index: /trunk/minix/lib/i386/string/memmove.s
===================================================================
--- /trunk/minix/lib/i386/string/memmove.s	(revision 9)
+++ /trunk/minix/lib/i386/string/memmove.s	(revision 9)
@@ -0,0 +1,12 @@
+!	memmove()					Author: Kees J. Bot
+!								2 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! void *memmove(void *s1, const void *s2, size_t n)
+!	Copy a chunk of memory.  Handle overlap.
+!
+.sect .text
+.define _memmove
+	.align	16
+_memmove:
+	jmp	__memmove	! Call common code
Index: /trunk/minix/lib/i386/string/memset.s
===================================================================
--- /trunk/minix/lib/i386/string/memset.s	(revision 9)
+++ /trunk/minix/lib/i386/string/memset.s	(revision 9)
@@ -0,0 +1,44 @@
+!	memset()					Author: Kees J. Bot
+!								2 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! void *memset(void *s, int c, size_t n)
+!	Set a chunk of memory to the same byte value.
+!
+.sect .text
+.define _memset
+	.align	16
+_memset:
+	push	ebp
+	mov	ebp, esp
+	push	edi
+	mov	edi, 8(ebp)	! The string
+	movzxb	eax, 12(ebp)	! The fill byte
+	mov	ecx, 16(ebp)	! Length
+	cld
+	cmp	ecx, 16
+	jb	sbyte		! Don't bother being smart with short arrays
+	test	edi, 1
+	jnz	sbyte		! Bit 0 set, use byte store
+	test	edi, 2
+	jnz	sword		! Bit 1 set, use word store
+slword:	movb	ah, al
+	mov	edx, eax
+	sal	edx, 16
+	or	eax, edx	! One byte to four bytes
+	shrd	edx, ecx, 2	! Save low two bits of ecx in edx
+	shr	ecx, 2
+	rep
+	stos			! Store longwords.
+	shld	ecx, edx, 2	! Restore low two bits
+sword:	movb	ah, al		! One byte to two bytes
+	shr	ecx, 1
+	rep
+    o16	stos			! Store words
+	adc	ecx, ecx	! One more byte?
+sbyte:	rep
+	stosb			! Store bytes
+done:	mov	eax, 8(ebp)	! Return some value you have no need for
+	pop	edi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/string/rindex.s
===================================================================
--- /trunk/minix/lib/i386/string/rindex.s	(revision 9)
+++ /trunk/minix/lib/i386/string/rindex.s	(revision 9)
@@ -0,0 +1,13 @@
+!	rindex()					Author: Kees J. Bot
+!								2 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *rindex(const char *s, int c)
+!	Look for the last occurrence a character in a string.  Has suffered
+!	from a hostile takeover by strrchr().
+!
+.sect .text
+.define _rindex
+	.align	16
+_rindex:
+	jmp	_strrchr
Index: /trunk/minix/lib/i386/string/strcat.s
===================================================================
--- /trunk/minix/lib/i386/string/strcat.s	(revision 9)
+++ /trunk/minix/lib/i386/string/strcat.s	(revision 9)
@@ -0,0 +1,13 @@
+!	strcat()					Author: Kees J. Bot
+!								1 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *strcat(char *s1, const char *s2)
+!	Append string s2 to s1.
+!
+.sect .text
+.define _strcat
+	.align	16
+_strcat:
+	mov	edx, -1		! Unlimited length
+	jmp	__strncat	! Common code
Index: /trunk/minix/lib/i386/string/strchr.s
===================================================================
--- /trunk/minix/lib/i386/string/strchr.s	(revision 9)
+++ /trunk/minix/lib/i386/string/strchr.s	(revision 9)
@@ -0,0 +1,41 @@
+!	strchr()					Author: Kees J. Bot
+!								1 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *strchr(const char *s, int c)
+!	Look for a character in a string.
+!
+.sect .text
+.define _strchr
+	.align	16
+_strchr:
+	push	ebp
+	mov	ebp, esp
+	push	edi
+	cld
+	mov	edi, 8(ebp)	! edi = string
+	mov	edx, 16		! Look at small chunks of the string
+next:	shl	edx, 1		! Chunks become bigger each time
+	mov	ecx, edx
+	xorb	al, al		! Look for the zero at the end
+	repne
+	scasb
+	pushf			! Remember the flags
+	sub	ecx, edx
+	neg	ecx		! Some or all of the chunk
+	sub	edi, ecx	! Step back
+	movb	al, 12(ebp)	! The character to look for
+	repne
+	scasb
+	je	found
+	popf			! Did we find the end of string earlier?
+	jne	next		! No, try again
+	xor	eax, eax	! Return NULL
+	pop	edi
+	pop	ebp
+	ret
+found:	pop	eax		! Get rid of those flags
+	lea	eax, -1(edi)	! Address of byte found
+	pop	edi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/string/strcmp.s
===================================================================
--- /trunk/minix/lib/i386/string/strcmp.s	(revision 9)
+++ /trunk/minix/lib/i386/string/strcmp.s	(revision 9)
@@ -0,0 +1,13 @@
+!	strcmp()					Author: Kees J. Bot
+!								1 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! int strcmp(const char *s1, const char *s2)
+!	Compare two strings.
+!
+.sect .text
+.define _strcmp
+	.align	16
+_strcmp:
+	mov	ecx, -1		! Unlimited length
+	jmp	__strncmp	! Common code
Index: /trunk/minix/lib/i386/string/strcpy.s
===================================================================
--- /trunk/minix/lib/i386/string/strcpy.s	(revision 9)
+++ /trunk/minix/lib/i386/string/strcpy.s	(revision 9)
@@ -0,0 +1,22 @@
+!	strcpy()					Author: Kees J. Bot
+!								1 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *strcpy(char *s1, const char *s2)
+!	Copy string s2 to s1.
+!
+.sect .text
+.define _strcpy
+	.align	16
+_strcpy:
+	push	ebp
+	mov	ebp, esp
+	push	esi
+	push	edi
+	mov	ecx, -1		! Unlimited length
+	call	__strncpy	! Common code
+	mov	eax, 8(ebp)	! Return s1
+	pop	edi
+	pop	esi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/string/strlen.s
===================================================================
--- /trunk/minix/lib/i386/string/strlen.s	(revision 9)
+++ /trunk/minix/lib/i386/string/strlen.s	(revision 9)
@@ -0,0 +1,13 @@
+!	strlen()					Author: Kees J. Bot
+!								1 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! size_t strlen(const char *s)
+!	Return the length of a string.
+!
+.sect .text
+.define _strlen
+	.align	16
+_strlen:
+	mov	ecx, -1		! Unlimited length
+	jmp	__strnlen	! Common code
Index: /trunk/minix/lib/i386/string/strncat.s
===================================================================
--- /trunk/minix/lib/i386/string/strncat.s	(revision 9)
+++ /trunk/minix/lib/i386/string/strncat.s	(revision 9)
@@ -0,0 +1,13 @@
+!	strncat()					Author: Kees J. Bot
+!								1 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! size_t strncat(char *s1, const char *s2, size_t n)
+!	Append string s2 to s1.
+!
+.sect .text
+.define _strncat
+	.align	16
+_strncat:
+	mov	edx, 12(esp)	! Maximum length
+	jmp	__strncat	! Common code
Index: /trunk/minix/lib/i386/string/strncmp.s
===================================================================
--- /trunk/minix/lib/i386/string/strncmp.s	(revision 9)
+++ /trunk/minix/lib/i386/string/strncmp.s	(revision 9)
@@ -0,0 +1,13 @@
+!	strncmp()					Author: Kees J. Bot
+!								1 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! int strncmp(const char *s1, const char *s2, size_t n)
+!	Compare two strings.
+!
+.sect .text
+.define _strncmp
+	.align	16
+_strncmp:
+	mov	ecx, 12(esp)	! Maximum length
+	jmp	__strncmp	! Common code
Index: /trunk/minix/lib/i386/string/strncpy.s
===================================================================
--- /trunk/minix/lib/i386/string/strncpy.s	(revision 9)
+++ /trunk/minix/lib/i386/string/strncpy.s	(revision 9)
@@ -0,0 +1,25 @@
+!	strncpy()					Author: Kees J. Bot
+!								1 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *strncpy(char *s1, const char *s2, size_t n)
+!	Copy string s2 to s1.
+!
+.sect .text
+.define _strncpy
+	.align	16
+_strncpy:
+	push	ebp
+	mov	ebp, esp
+	push	esi
+	push	edi
+	mov	ecx, 16(ebp)	! Maximum length
+	call	__strncpy	! Common code
+	mov	ecx, edx	! Number of bytes not copied
+	rep
+	stosb			! strncpy always copies n bytes by null padding
+	mov	eax, 8(ebp)	! Return s1
+	pop	edi
+	pop	esi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i386/string/strnlen.s
===================================================================
--- /trunk/minix/lib/i386/string/strnlen.s	(revision 9)
+++ /trunk/minix/lib/i386/string/strnlen.s	(revision 9)
@@ -0,0 +1,13 @@
+!	strnlen()					Author: Kees J. Bot
+!								1 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! size_t strnlen(const char *s, size_t n)
+!	Return the length of a string.
+!
+.sect .text
+.define _strnlen
+	.align	16
+_strnlen:
+	mov	ecx, 8(esp)	! Maximum length
+	jmp	__strnlen	! Common code
Index: /trunk/minix/lib/i386/string/strrchr.s
===================================================================
--- /trunk/minix/lib/i386/string/strrchr.s	(revision 9)
+++ /trunk/minix/lib/i386/string/strrchr.s	(revision 9)
@@ -0,0 +1,36 @@
+!	strrchr()					Author: Kees J. Bot
+!								2 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *strrchr(const char *s, int c)
+!	Look for the last occurrence a character in a string.
+!
+.sect .text
+.define _strrchr
+	.align	16
+_strrchr:
+	push	ebp
+	mov	ebp, esp
+	push	edi
+	mov	edi, 8(ebp)	! edi = string
+	mov	ecx, -1
+	xorb	al, al
+	cld
+	repne
+	scasb			! Look for the end of the string
+	not	ecx		! -1 - ecx = Length of the string + null
+	dec	edi		! Put edi back on the zero byte
+	movb	al, 12(ebp)	! The character to look for
+	std			! Downwards search
+	repne
+	scasb
+	cld			! Direction bit back to default
+	jne	failure
+	lea	eax, 1(edi)	! Found it
+	pop	edi
+	pop	ebp
+	ret
+failure:xor	eax, eax	! Not there
+	pop	edi
+	pop	ebp
+	ret
Index: /trunk/minix/lib/i86/em/em_adi.s
===================================================================
--- /trunk/minix/lib/i86/em/em_adi.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_adi.s	(revision 9)
@@ -0,0 +1,24 @@
+.define .adi
+
+	.text
+.adi:
+	pop     bx 
+	cmp     cx,#2
+	jne     1f
+	pop     cx
+	add     ax,cx
+	jmp     (bx)
+1:
+	cmp     cx,#4
+	jne     9f
+	pop     dx
+	pop     cx
+	add     ax,cx
+	pop     cx
+	adc     dx,cx
+	push    dx
+	jmp     (bx)
+9:
+.extern .trpilin
+	push	bx
+	jmp     .trpilin
Index: /trunk/minix/lib/i86/em/em_and.s
===================================================================
--- /trunk/minix/lib/i86/em/em_and.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_and.s	(revision 9)
@@ -0,0 +1,19 @@
+.define	.and
+
+	! #bytes in cx
+	! save di; it might be a register variable
+
+	.text
+.and:
+	pop	bx		! return address
+	mov	dx,di
+	mov	di,sp
+	add	di,cx
+	sar	cx,#1
+1:
+	pop	ax
+	and	ax,(di)
+	stos
+	loop	1b
+	mov	di,dx
+	jmp	(bx)
Index: /trunk/minix/lib/i86/em/em_blm.s
===================================================================
--- /trunk/minix/lib/i86/em/em_blm.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_blm.s	(revision 9)
@@ -0,0 +1,15 @@
+.define .blm
+.text
+
+	! cx: count in words
+.blm:
+	mov	bx,sp
+	mov	ax,si
+	mov	dx,di
+	mov	di,2(bx)
+	mov	si,4(bx)
+	rep
+	mov
+	mov	si,ax
+	mov	di,dx
+	ret	4
Index: /trunk/minix/lib/i86/em/em_cii.s
===================================================================
--- /trunk/minix/lib/i86/em/em_cii.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_cii.s	(revision 9)
@@ -0,0 +1,37 @@
+.define .cii
+
+.text
+.cii:
+	pop     bx              ! return address
+				! pop     cx, dest. size
+				! pop     dx, src. size
+				! ax is first word of source
+	cmp	dx,#1
+	jne	2f
+	cbw
+	mov	dx,#2
+2:
+	cmp     dx,cx
+	je      8f
+	cmp     dx,#2
+	je      1f
+	cmp     dx,#4
+	jne     9f
+	cmp     cx,#2
+	jne     9f
+	pop     dx
+8:
+	jmp     (bx)
+1:
+	cmp     cx,#4
+	jne     9f
+	cwd
+	push    dx
+	jmp     (bx)
+9:
+	push    ax              ! push low source
+EILLINS = 18
+.extern .fat
+	mov     ax,#EILLINS
+	push    ax
+	jmp     .fat
Index: /trunk/minix/lib/i86/em/em_cmi4.s
===================================================================
--- /trunk/minix/lib/i86/em/em_cmi4.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_cmi4.s	(revision 9)
@@ -0,0 +1,27 @@
+.define .cmi4
+
+.text
+.cmi4:
+	pop     bx              ! return address
+	pop     cx
+	pop     dx
+	pop     ax
+	push	si
+	mov	si,sp
+	xchg	bx,2(si)
+	pop	si
+	cmp     bx,dx
+	jg      1f
+	jl      2f
+	cmp     ax,cx
+	ja      1f
+	je      3f
+2:
+	mov	ax,#-1
+	ret
+3:
+	xor	ax,ax
+	ret
+1:
+	mov	ax,#1
+	ret
Index: /trunk/minix/lib/i86/em/em_cms.s
===================================================================
--- /trunk/minix/lib/i86/em/em_cms.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_cms.s	(revision 9)
@@ -0,0 +1,23 @@
+.define .cms
+
+	! #bytes in cx
+	.text
+.cms:
+	pop     bx              ! return address
+	mov     dx,sp
+	push	si
+	push	di
+	mov     si,dx
+	add     dx,cx
+	mov     di,dx
+	add     dx,cx
+	sar     cx,#1
+	repe
+	cmp
+	je      1f
+	inc     cx
+1:
+	pop	di
+	pop	si
+	mov     sp,dx
+	jmp     (bx)
Index: /trunk/minix/lib/i86/em/em_cmu4.s
===================================================================
--- /trunk/minix/lib/i86/em/em_cmu4.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_cmu4.s	(revision 9)
@@ -0,0 +1,27 @@
+.define .cmu4
+
+.text
+.cmu4:
+	pop     bx              ! return address
+	pop     cx
+	pop     dx
+	pop     ax
+	push	si
+	mov	si,sp
+	xchg	bx,2(si)
+	pop	si
+	cmp     bx,dx
+	ja      1f
+	jb      2f
+	cmp     ax,cx
+	ja      1f
+	je      3f
+2:
+	mov	ax,#-1
+	ret
+3:
+	xor	ax,ax
+	ret
+1:
+	mov	ax,#1
+	ret
Index: /trunk/minix/lib/i86/em/em_com.s
===================================================================
--- /trunk/minix/lib/i86/em/em_com.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_com.s	(revision 9)
@@ -0,0 +1,15 @@
+.define	.com
+
+	! #bytes in cx
+	.text
+.com:
+	mov	bx,sp
+	inc	bx
+	inc	bx
+	sar	cx,#1
+1:
+	not	(bx)
+	inc	bx
+	inc	bx
+	loop	1b
+	ret
Index: /trunk/minix/lib/i86/em/em_csa2.s
===================================================================
--- /trunk/minix/lib/i86/em/em_csa2.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_csa2.s	(revision 9)
@@ -0,0 +1,26 @@
+.define .csa2
+
+.text
+.csa2:
+				! bx, descriptor address
+				! ax, index
+	mov     dx,(bx)         ! default
+	sub     ax,2(bx)
+	cmp     ax,4(bx)
+	ja      1f
+	sal     ax,#1
+	add	bx,ax
+	mov     bx,6(bx)
+	test    bx,bx
+	jnz     2f
+1:
+	mov     bx,dx
+	test    bx,bx
+	jnz     2f
+ECASE = 20
+.extern .fat
+	mov     ax,#ECASE
+	push    ax
+	jmp     .fat
+2:
+	jmp     (bx)
Index: /trunk/minix/lib/i86/em/em_csa4.s
===================================================================
--- /trunk/minix/lib/i86/em/em_csa4.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_csa4.s	(revision 9)
@@ -0,0 +1,30 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .csa4
+
+.sect .text
+.csa4:
+				! bx, descriptor address
+				! ax, dx: index
+	mov	cx,(bx)         ! default
+	sub     ax,2(bx)
+				! ignore high order word; if non-zero, the
+				! case descriptor would not fit anyway
+	cmp	ax,6(bx)
+	ja	1f
+2:
+	sal     ax,#1
+	add	bx,ax
+	mov     bx,10(bx)
+	test    bx,bx
+	jnz     2f
+1:
+	mov	bx,cx
+	test    bx,bx
+	jnz     2f
+ECASE = 20
+.extern .fat
+	mov     ax,#ECASE
+	push    ax
+	jmp     .fat
+2:
+	jmp     (bx)
Index: /trunk/minix/lib/i86/em/em_csb2.s
===================================================================
--- /trunk/minix/lib/i86/em/em_csb2.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_csb2.s	(revision 9)
@@ -0,0 +1,28 @@
+.define .csb2
+
+.text
+.csb2:
+				!bx, descriptor address
+				!ax,  index
+	mov	dx,(bx)
+	mov	cx,2(bx)
+1:
+	add	bx,#4
+	dec     cx
+	jl      4f
+	cmp     ax,(bx)
+	jne     1b
+	mov	bx,2(bx)
+2:
+	test    bx,bx
+	jnz     3f
+ECASE = 20
+.extern .fat
+	mov     ax,#ECASE
+	push    ax
+	jmp     .fat
+3:
+	jmp     (bx)
+4:
+	mov	bx,dx
+	jmp	2b
Index: /trunk/minix/lib/i86/em/em_csb4.s
===================================================================
--- /trunk/minix/lib/i86/em/em_csb4.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_csb4.s	(revision 9)
@@ -0,0 +1,33 @@
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.define .csb4
+
+.sect .text
+.csb4:
+				!bx: descriptor address
+				!ax, dx:  index
+	push	(bx)		! default
+	mov	cx,2(bx)	! count (ignore high order word, the descriptor
+				! would not fit anyway)
+1:
+	add	bx,#6
+	dec     cx
+	jl      4f
+	cmp     ax,(bx)
+	jne     1b
+	cmp	dx,2(bx)
+	jne     1b
+	pop	bx
+	mov	bx,4(bx)
+2:
+	test    bx,bx
+	jnz     3f
+ECASE = 20
+.extern .fat
+	mov     ax,#ECASE
+	push    ax
+	jmp     .fat
+3:
+	jmp	(bx)
+4:
+	pop	bx
+	jmp	2b
Index: /trunk/minix/lib/i86/em/em_cuu.s
===================================================================
--- /trunk/minix/lib/i86/em/em_cuu.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_cuu.s	(revision 9)
@@ -0,0 +1,36 @@
+.define .ciu
+.define .cui
+.define .cuu
+
+.text
+.ciu:
+.cui:
+.cuu:
+	pop     bx              ! return address
+				! pop     cx, dest. size
+				! pop     dx, source size
+				! ax is low word of source
+	cmp     dx,cx
+	je      8f
+	cmp     dx,#2
+	je      1f
+	cmp     dx,#4
+	jne     9f
+	cmp     cx,#2
+	jne     9f
+	pop     dx
+8:
+	jmp     (bx)
+1:
+	cmp     cx,#4
+	jne     9f
+	xor     dx,dx
+	push    dx
+	jmp     (bx)
+9:
+	push    ax              ! to help debugging ?
+EILLINS = 18
+.extern .fat
+	mov     ax,#EILLINS
+	push    ax
+	jmp     .fat
Index: /trunk/minix/lib/i86/em/em_dup.s
===================================================================
--- /trunk/minix/lib/i86/em/em_dup.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_dup.s	(revision 9)
@@ -0,0 +1,17 @@
+.define	.dup
+
+	! #bytes in cx
+	.text
+.dup:
+	pop	bx		! return address
+	mov	ax,si
+	mov	dx,di
+	mov	si,sp
+	sub	sp,cx
+	mov	di,sp
+	sar	cx,#1
+	rep
+	mov
+	mov	si,ax
+	mov	di,dx
+	jmp	(bx)
Index: /trunk/minix/lib/i86/em/em_dvi4.s
===================================================================
--- /trunk/minix/lib/i86/em/em_dvi4.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_dvi4.s	(revision 9)
@@ -0,0 +1,90 @@
+.define .dvi4
+
+yl=6
+yh=8
+xl=10
+xh=12
+
+.text
+.dvi4:
+	push	si
+	push	di
+	mov     si,sp           ! copy of sp
+	mov     bx,yl(si)
+	mov     ax,yh(si)
+	cwd
+	mov     di,dx
+	cmp     dx,ax
+	jne     7f
+	and     dx,dx
+	jge     1f
+	neg     bx
+	je      7f
+1:
+	xor     dx,dx
+	mov     cx,xl(si)
+	mov     ax,xh(si)
+	and     ax,ax
+	jge     2f
+	neg     ax
+	neg     cx
+	sbb     ax,dx
+	not     di
+2:
+	div     bx
+	xchg    ax,cx
+	div     bx              ! cx = high abs(result), ax=low abs(result)
+9:
+	and     di,di
+	jge     1f
+	neg     cx
+	neg     ax
+	sbb     cx,#0
+1:
+			! cx is high order result
+			! ax is low order result
+	mov	dx,cx
+	pop	di
+	pop	si
+	ret	8	! result in ax/dx
+
+7:
+	push    dx              ! sign of y
+	mov     di,ax
+	xor     bx,bx
+	and     di,di
+	jge     1f
+	neg     di
+	neg     yl(si)
+	sbb     di,bx
+1:
+	mov     ax,xl(si)
+	mov     dx,xh(si)
+	and     dx,dx
+	jge     1f
+	neg     dx
+	neg     ax
+	sbb     dx,bx
+	not     -2(si)
+1:
+	mov     cx,#16
+1:
+	shl     ax,#1
+	rcl     dx,#1
+	rcl     bx,#1
+	cmp     di,bx
+	ja      3f
+	jb      2f
+	cmp     yl(si),dx
+	jbe     2f
+3:
+	loop    1b
+	jmp     1f
+2:
+	sub     dx,yl(si)
+	sbb     bx,di
+	inc     ax
+	loop    1b
+1:
+	pop     di              ! di=sign of result,ax= result
+	jmp     9b
Index: /trunk/minix/lib/i86/em/em_dvu4.s
===================================================================
--- /trunk/minix/lib/i86/em/em_dvu4.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_dvu4.s	(revision 9)
@@ -0,0 +1,54 @@
+.define .dvu4
+
+yl=6
+yh=8
+xl=10
+xh=12
+
+.text
+.dvu4:
+	push	si
+	push	di
+	mov     si,sp           ! copy of sp
+	mov     bx,yl(si)
+	mov     ax,yh(si)
+	or      ax,ax
+	jne     7f
+	xor     dx,dx
+	mov     cx,xl(si)
+	mov     ax,xh(si)
+	div     bx
+	xchg    ax,cx
+	div     bx
+9:
+			! cx is high order result
+			! ax is low order result
+	mov	dx,cx
+	pop	di
+	pop	si
+	ret	8	! result in ax/dx
+
+7:
+	mov     di,ax
+	xor     bx,bx
+	mov     ax,xl(si)
+	mov     dx,xh(si)
+	mov     cx,#16
+1:
+	shl     ax,#1
+	rcl     dx,#1
+	rcl     bx,#1
+	cmp     di,bx
+	ja      3f
+	jb      2f
+	cmp     yl(si),dx
+	jbe     2f
+3:
+	loop    1b
+	jmp     9b
+2:
+	sub     dx,yl(si)
+	sbb     bx,di
+	inc     ax
+	loop    1b
+	jmp     9b
Index: /trunk/minix/lib/i86/em/em_error.s
===================================================================
--- /trunk/minix/lib/i86/em/em_error.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_error.s	(revision 9)
@@ -0,0 +1,41 @@
+.define .error
+.define .Xtrp
+
+	! ax is trap number
+	! all registers must be saved
+	! because return is possible
+	! May only be called with error no's <16
+.text
+.error:
+	push bp
+	push si
+	push di
+	push dx
+	push cx
+	push bx
+	push ax
+	mov  cx,ax
+	mov  bx,#1
+	sal  bx,cl
+.extern .ignmask
+.extern .trp
+	test bx,.ignmask
+	jne  2f
+	call    .trp
+2:
+	pop  ax
+	pop  bx
+	pop  cx
+	pop  dx
+	pop  di
+	pop  si
+	pop  bp
+	ret
+
+.Xtrp:
+	cmp	ax,#16
+	jge	1f
+	call	.error
+	ret
+1:
+	jmp	.trp
Index: /trunk/minix/lib/i86/em/em_exg.s
===================================================================
--- /trunk/minix/lib/i86/em/em_exg.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_exg.s	(revision 9)
@@ -0,0 +1,21 @@
+.define .exg
+
+	! #bytes in cx
+.text
+.exg:
+	push	di
+	mov	sp,di
+	add	di,#4
+	mov	bx,di
+	add	bx,cx
+	sar     cx,#1
+1:
+	mov	ax,(bx)
+	xchg	ax,(di)
+	mov	(bx),ax
+	add	di,#2
+	add	bx,#2
+	loop	1b
+2:
+	pop	di
+	ret
Index: /trunk/minix/lib/i86/em/em_fat.s
===================================================================
--- /trunk/minix/lib/i86/em/em_fat.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_fat.s	(revision 9)
@@ -0,0 +1,9 @@
+.define .fat
+.text
+
+.fat:
+.extern .trp
+.extern .stop
+	call    .trp
+	call    .stop
+	! no return
Index: /trunk/minix/lib/i86/em/em_fp8087.s
===================================================================
--- /trunk/minix/lib/i86/em/em_fp8087.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_fp8087.s	(revision 9)
@@ -0,0 +1,615 @@
+.define .adf4, .adf8, .sbf4, .sbf8, .mlf4, .mlf8, .dvf4, .dvf8
+.define .ngf4, .ngf8, .fif4, .fif8, .fef4, .fef8
+.define .cif4, .cif8, .cuf4, .cuf8, .cfi, .cfu, .cff4, .cff8
+.define .cmf4, .cmf8
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+!	$Header: /cvsup/minix/src/lib/i86/em/em_fp8087.s,v 1.1.1.1 2005/04/21 14:56:13 beng Exp $
+
+!	Implement interface to floating point package for Intel 8087
+
+	.sect .rom
+one:
+	.data2	1
+two:
+	.data2	2
+bigmin:
+	.data2	0, -32768
+
+	.sect .text
+.adf4:
+	mov	bx,sp
+	wait
+	flds	2(bx)
+	wait
+	fadds	6(bx)
+	wait
+	fstps	6(bx)
+	wait
+	ret
+.adf8:
+	mov	bx,sp
+	wait
+	fldd	2(bx)
+	wait
+	faddd	10(bx)
+	wait
+	fstpd	10(bx)
+	wait
+	ret
+
+.sbf4:
+	mov	bx,sp
+	wait
+	flds	6(bx)
+	wait
+	fsubs	2(bx)
+	wait
+	fstps	6(bx)
+	wait
+	ret
+
+.sbf8:
+	mov	bx,sp
+	wait
+	fldd	10(bx)
+	wait
+	fsubd	2(bx)
+	wait
+	fstpd	10(bx)
+	wait
+	ret
+
+.mlf4:
+	mov	bx,sp
+	wait
+	flds	2(bx)
+	wait
+	fmuls	6(bx)
+	wait
+	fstps	6(bx)
+	wait
+	ret
+.mlf8:
+	mov	bx,sp
+	wait
+	fldd	2(bx)
+	wait
+	fmuld	10(bx)
+	wait
+	fstpd	10(bx)
+	wait
+	ret
+
+.dvf4:
+	mov	bx,sp
+	wait
+	flds	6(bx)
+	wait
+	fdivs	2(bx)
+	wait
+	fstps	6(bx)
+	wait
+	ret
+
+.dvf8:
+	mov	bx,sp
+	wait
+	fldd	10(bx)
+	wait
+	fdivd	2(bx)
+	wait
+	fstpd	10(bx)
+	wait
+	ret
+
+.ngf4:
+	mov	bx,sp
+	wait
+	flds	2(bx)
+	wait
+	fchs
+	wait
+	fstps	2(bx)
+	wait
+	ret
+
+.ngf8:
+	mov	bx,sp
+	wait
+	fldd	2(bx)
+	wait
+	fchs
+	wait
+	fstpd	2(bx)
+	wait
+	ret
+
+.fif4:
+	mov	bx,sp
+	push	bx		! make room for FP status word
+	wait
+	flds	4(bx)
+	wait
+	fmuls	8(bx)		! multiply
+	wait
+	fld	st		! copy result
+	wait
+	ftst			! test sign; handle negative separately
+	wait
+	fstsw	-2(bx)
+	wait
+	mov	ax,-2(bx)
+	sahf			! result of test in condition codes
+	jb	1f
+	frndint			! this one rounds (?)
+	wait
+	fcom	st(1)		! compare with original; if <=, then OK
+	wait
+	fstsw	-2(bx)
+	wait
+	mov	ax,-2(bx)
+	sahf
+	jbe	2f
+	fisubs	one		! else subtract 1
+	wait
+	jmp	2f
+1:				! here, negative case
+	frndint			! this one rounds (?)
+	wait
+	fcom	st(1)		! compare with original; if >=, then OK
+	wait
+	fstsw	-2(bx)
+	wait
+	mov	ax,-2(bx)
+	sahf
+	jae	2f
+	fiadds	one		! else add 1
+	wait
+2:
+	fsub	st(1),st	! subtract integer part
+	wait
+	mov	bx,2(bx)
+	fstps	(bx)
+	wait
+	fstps	4(bx)
+	wait
+	pop	bx
+	ret
+
+.fif8:
+	mov	bx,sp
+	push	bx		! make room for FP status word
+	wait
+	fldd	4(bx)
+	wait
+	fmuld	12(bx)		! multiply
+	wait
+	fld	st		! and copy result
+	wait
+	ftst			! test sign; handle negative separately
+	wait
+	fstsw	-2(bx)
+	wait
+	mov	ax,-2(bx)
+	sahf			! result of test in condition codes
+	jb	1f
+	frndint			! this one rounds (?)
+	wait
+	fcom	st(1)		! compare with original; if <=, then OK
+	wait
+	fstsw	-2(bx)
+	wait
+	mov	ax,-2(bx)
+	sahf
+	jbe	2f
+	fisubs	one		! else subtract 1
+	wait
+	jmp	2f
+1:				! here, negative case
+	frndint			! this one rounds (?)
+	wait
+	fcom	st(1)		! compare with original; if >=, then OK
+	wait
+	fstsw	-2(bx)
+	wait
+	mov	ax,-2(bx)
+	sahf
+	jae	2f
+	fiadds	one		! else add 1
+	wait
+2:
+	fsub	st(1),st	! subtract integer part
+	mov	bx,2(bx)
+	fstpd	(bx)
+	wait
+	fstpd	8(bx)
+	wait
+	pop	bx
+	ret
+
+.fef4:
+				! this could be simpler, if only the
+				! fxtract instruction was emulated properly
+	mov	bx,sp
+	mov	ax,6(bx)
+	and	ax,#077600
+	je	1f		! zero exponent
+	mov	cx,#7
+	shr	ax,cl
+	sub	ax,#126
+	mov	cx,ax		! exponent in cx
+	mov	ax,6(bx)
+	and	ax,#0100177
+	or	ax,#0037400	! load -1 exponent
+	mov	dx,4(bx)
+	mov	bx,2(bx)
+	mov	4(bx),ax
+	mov	2(bx),dx
+	mov	(bx),cx
+	ret
+1:				! we get here on zero exp
+	mov	ax,6(bx)
+	and	ax,#0177
+	or	ax,4(bx)
+	jne	1f		! zero result
+	xor	ax,ax
+	mov	bx,2(bx)
+	mov	(bx),ax
+	mov	2(bx),ax
+	mov	4(bx),ax
+	ret
+1:				! otherwise unnormalized number
+	mov	cx,6(bx)
+	and	cx,#0100177
+	mov	dx,cx
+	and	cx,#0x8000
+	mov	ax,#-125
+2:
+	test	dx,#0x80
+	jne	1f
+	dec	ax
+	shl	4(bx),#1
+	rcl	dx,#1
+	or	dx,cx
+	jmp	2b
+1:
+	mov	cx,4(bx)
+	mov	bx,2(bx)
+	mov	(bx),ax
+	mov	2(bx),cx
+	and	dx,#0100177
+	or	dx,#0037400	! load -1 exponent
+	mov	4(bx),dx
+	ret
+
+.fef8:
+				! this could be simpler, if only the
+				! fxtract instruction was emulated properly
+	mov	bx,sp
+	mov	ax,10(bx)
+	and	ax,#077760
+	je	1f		! zero exponent
+	mov	cx,#4
+	shr	ax,cl
+	sub	ax,#1022
+	mov	cx,ax		! exponent in cx
+	mov	ax,10(bx)
+	and	ax,#0100017
+	or	ax,#0037740	! load -1 exponent
+	push	8(bx)
+	push	6(bx)
+	push	4(bx)
+	mov	bx,2(bx)
+	pop	2(bx)
+	pop	4(bx)
+	pop	6(bx)
+	mov	8(bx),ax
+	mov	(bx),cx
+	ret
+1:				! we get here on zero exp
+	mov	ax,10(bx)
+	and	ax,#017
+	or	ax,8(bx)
+	or	ax,6(bx)
+	or	ax,4(bx)
+	jne	1f		! zero result
+	xor	ax,ax
+	mov	bx,2(bx)
+	mov	(bx),ax
+	mov	2(bx),ax
+	mov	4(bx),ax
+	mov	6(bx),ax
+	mov	8(bx),ax
+	ret
+1:				! otherwise unnormalized number
+	mov	cx,10(bx)
+	and	cx,#0100017
+	mov	dx,cx
+	and	cx,#0x8000
+	mov	ax,#-1021
+2:
+	test	dx,#0x10
+	jne	1f
+	dec	ax
+	shl	4(bx),#1
+	rcl	6(bx),#1
+	rcl	8(bx),#1
+	rcl	dx,#1
+	or	dx,cx
+	jmp	2b
+1:
+	and	dx,#0100017
+	or	dx,#0037740	! load -1 exponent
+	mov	cx,8(bx)
+	push	6(bx)
+	push	4(bx)
+	mov	bx,2(bx)
+	mov	(bx),ax
+	mov	8(bx),dx
+	mov	6(bx),cx
+	pop	2(bx)
+	pop	4(bx)
+	ret
+
+.cif4:
+	mov	bx,sp
+	cmp	2(bx),#2
+	jne	1f
+	wait
+	filds	4(bx)
+	wait
+	fstps	2(bx)
+	wait
+	ret
+1:
+	wait
+	fildl	4(bx)
+	wait
+	fstps	4(bx)
+	wait
+	ret
+
+.cif8:
+	mov	bx,sp
+	cmp	2(bx),#2
+	jne	1f
+	wait
+	filds	4(bx)
+	wait
+	fstpd	2(bx)
+	wait
+	ret
+1:
+	wait
+	fildl	4(bx)
+	wait
+	fstpd	2(bx)
+	wait
+	ret
+
+.cuf4:
+	mov	bx,sp
+	cmp	2(bx),#2
+	jne	1f
+	mov	ax,4(bx)
+	mov	2(bx),ax
+	mov	4(bx),#0
+	wait
+	fildl	2(bx)
+	wait
+	fstps	2(bx)
+	wait
+	ret
+1:
+	wait
+	fildl	4(bx)
+	wait
+	cmp	6(bx),#0
+	jge	1f
+2:
+	wait
+	fisubl	bigmin
+	wait
+	fisubl	bigmin
+1:
+	wait
+	fstps	4(bx)
+	wait
+	ret
+
+.cuf8:
+	mov	bx,sp
+	cmp	2(bx),#2
+	jne	1f
+	mov	6(bx),#0
+1:
+	wait
+	fildl	4(bx)
+	wait
+	cmp	6(bx),#0
+	jge	1f
+2:
+	wait
+	fisubl	bigmin
+	wait
+	fisubl	bigmin
+1:
+	wait
+	fstpd	2(bx)
+	wait
+	ret
+
+.cfi:
+	mov	bx,sp
+	push	bx
+	wait
+	fstcw	-2(bx)
+	wait
+	mov	dx,-2(bx)
+	or	-2(bx),#0xc00	! truncating mode
+	wait
+	fldcw	-2(bx)
+	pop	ax
+	cmp	4(bx),#4
+	jne	2f
+				! loc 4 loc ? cfi
+	wait
+	flds	6(bx)
+	wait
+	fistpl	6(bx)
+	wait
+	cmp	2(bx),#2
+	jne	1f
+	mov	ax,6(bx)
+1:
+	mov	4(bx),dx
+	wait
+	fldcw	4(bx)
+	wait
+	ret
+2:
+				! loc 8 loc ? cfi
+	wait
+	fldd	6(bx)
+	wait
+	fistpl	10(bx)
+	wait
+	cmp	2(bx),#2
+	jne	1b
+	mov	ax,10(bx)
+	jmp	1b
+
+.cfu:
+	mov	bx,sp
+	push	bx
+	wait
+	fstcw	-2(bx)
+	wait
+	mov	dx,-2(bx)
+	and	-2(bx),#0xf3ff
+	or	-2(bx),#0x400	! to -infinity
+	wait
+	fldcw	-2(bx)
+	wait
+	pop	ax
+	cmp	4(bx),#4
+	jne	2f
+				! loc 4 loc ? cfu
+	flds	6(bx)
+	wait
+	fabs			! ???
+	wait
+	fiaddl	bigmin
+	fistpl	6(bx)
+	wait
+	mov	ax,8(bx)
+	sub	ax,bigmin+2
+	mov	8(bx),ax
+	cmp	2(bx),#2
+	jne	1f
+	mov	ax,6(bx)
+1:
+	mov	4(bx),dx
+	wait
+	fldcw	4(bx)
+	wait
+	ret
+2:
+	wait
+				! loc 8 loc ? cfu
+	fldd	6(bx)
+	wait
+	fabs			! ???
+	wait
+	fiaddl	bigmin
+	fistpl	10(bx)
+	wait
+	mov	ax,12(bx)
+	sub	ax,bigmin+2
+	mov	12(bx),ax
+	cmp	2(bx),#2
+	jne	1b
+	mov	ax,10(bx)
+	jmp	1b
+
+.cff4:
+	mov	bx,sp
+	wait
+	fldd	2(bx)
+	wait
+	fstcw	2(bx)
+	wait
+	mov	dx,2(bx)
+	and	2(bx),#0xf3ff	! set to rounding mode
+	wait
+	fldcw	2(bx)
+	wait
+	fstps	6(bx)
+	mov	2(bx),dx
+	wait
+	fldcw	2(bx)
+	wait
+	ret
+
+.cff8:
+	mov	bx,sp
+	wait
+	flds	2(bx)
+	wait
+	fstpd	2(bx)
+	wait
+	ret
+
+.cmf4:
+	mov	bx,sp
+	push	bx		! room for 8087 status word
+	xor	cx,cx
+	wait
+	flds	6(bx)
+	wait
+	flds	2(bx)
+	wait
+	fcompp			! compare and pop operands
+	wait
+	fstsw	-2(bx)
+	wait
+	mov	ax,-2(bx)
+	sahf
+	je	1f
+	jb	2f
+	dec	cx
+	jmp	1f
+2:
+	inc	cx
+1:
+	mov	ax,cx
+	pop	bx
+	ret
+
+
+.cmf8:
+	mov	bx,sp
+	push	bx		! room for 8087 status word
+	xor	cx,cx
+	wait
+	fldd	10(bx)
+	wait
+	fldd	2(bx)
+	wait
+	fcompp			! compare and pop operands
+	wait
+	fstsw	-2(bx)
+	wait
+	mov	ax,-2(bx)
+	sahf
+	je	1f
+	jb	2f
+	dec	cx
+	jmp	1f
+2:
+	inc	cx
+1:
+	mov	ax,cx
+	pop	bx
+	ret
Index: /trunk/minix/lib/i86/em/em_gto.s
===================================================================
--- /trunk/minix/lib/i86/em/em_gto.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_gto.s	(revision 9)
@@ -0,0 +1,7 @@
+.define .gto
+.text
+
+.gto:
+	mov     bp,4(bx)
+	mov     sp,2(bx)
+	jmp     @(bx)
Index: /trunk/minix/lib/i86/em/em_hol0.s
===================================================================
--- /trunk/minix/lib/i86/em/em_hol0.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_hol0.s	(revision 9)
@@ -0,0 +1,5 @@
+.define hol0
+.data
+hol0:
+	.data2	0, 0
+	.data2	0, 0
Index: /trunk/minix/lib/i86/em/em_iaar.s
===================================================================
--- /trunk/minix/lib/i86/em/em_iaar.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_iaar.s	(revision 9)
@@ -0,0 +1,17 @@
+.define .iaar
+.text
+
+.iaar:
+	pop     cx
+	pop     dx
+	cmp     dx,#2
+.extern .unknown
+	jne     .unknown
+	pop     bx      ! descriptor address
+	pop     ax      ! index
+	sub     ax,(bx)
+	mul     4(bx)
+	pop     bx      ! array base
+	add     bx,ax
+	push	cx
+	ret
Index: /trunk/minix/lib/i86/em/em_ilar.s
===================================================================
--- /trunk/minix/lib/i86/em/em_ilar.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_ilar.s	(revision 9)
@@ -0,0 +1,14 @@
+.define .ilar
+.text
+
+.ilar:
+	pop     cx
+	pop     dx
+.extern .unknown
+	cmp     dx,#2
+	jne     .unknown
+	pop     bx      ! descriptor address
+	pop     ax      ! index
+	push    cx
+.extern .lar2
+	jmp    .lar2
Index: /trunk/minix/lib/i86/em/em_inn.s
===================================================================
--- /trunk/minix/lib/i86/em/em_inn.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_inn.s	(revision 9)
@@ -0,0 +1,31 @@
+.define .inn
+.text
+
+	! #bytes in cx
+	! bit # in ax
+.inn:
+	xor     dx,dx
+	mov     bx,#8
+	div     bx
+	mov     bx,sp
+	add	bx,#2
+	add     bx,ax
+	cmp     ax,cx
+	jae     1f
+	movb	al,(bx)
+	mov	bx,dx
+	testb   al,bits(bx)
+	jz      1f
+	mov	ax,#1
+	jmp	2f
+1:
+	xor	ax,ax
+2:
+	pop	bx
+	add     sp,cx
+	! ax is result
+	jmp     (bx)
+
+	.data
+bits:
+	.data1 1,2,4,8,16,32,64,128
Index: /trunk/minix/lib/i86/em/em_ior.s
===================================================================
--- /trunk/minix/lib/i86/em/em_ior.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_ior.s	(revision 9)
@@ -0,0 +1,17 @@
+.define	.ior
+.text
+
+	! #bytes in cx
+.ior:
+	pop	bx		! return address
+	mov	dx,di
+	mov	di,sp
+	add	di,cx
+	sar	cx,#1
+1:
+	pop	ax
+	or	ax,(di)
+	stos
+	loop	1b
+	mov	di,dx
+	jmp	(bx)
Index: /trunk/minix/lib/i86/em/em_isar.s
===================================================================
--- /trunk/minix/lib/i86/em/em_isar.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_isar.s	(revision 9)
@@ -0,0 +1,14 @@
+.define .isar
+.text
+
+.isar:
+	pop     cx
+	pop     ax
+	cmp     ax,#2
+.extern .unknown
+	jne     .unknown
+	pop     bx      ! descriptor address
+	pop     ax      ! index
+	push    cx
+.extern .sar2
+	jmp    .sar2
Index: /trunk/minix/lib/i86/em/em_lar2.s
===================================================================
--- /trunk/minix/lib/i86/em/em_lar2.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_lar2.s	(revision 9)
@@ -0,0 +1,35 @@
+.define .lar2
+.text
+
+.lar2:
+				! bx, descriptor address
+				! ax, index
+	pop	cx
+	pop	dx		! base address
+	push	cx
+	push	si
+	mov	si,dx
+	sub     ax,(bx)
+	mov     cx,4(bx)
+	imul    cx
+	add     si,ax
+	sar     cx,#1
+	jnb     1f
+	xorb    ah,ah
+	lodsb
+	pop	si
+	pop	bx
+	push    ax
+	jmp     (bx)
+1:
+	pop	dx		! saved si
+	mov	ax,4(bx)
+	pop	bx		! return address
+	sub     sp,ax
+	mov	ax,di		! save di
+	mov     di,sp
+	rep
+	mov
+	mov	di,ax
+	mov	si,dx
+	jmp     (bx)
Index: /trunk/minix/lib/i86/em/em_lfr6.s
===================================================================
--- /trunk/minix/lib/i86/em/em_lfr6.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_lfr6.s	(revision 9)
@@ -0,0 +1,10 @@
+.define .lfr6
+.text
+.extern .retarea
+
+.lfr6:
+	pop	bx
+	push	.retarea+4
+	push	.retarea+2
+	push	.retarea
+	jmp	(bx)
Index: /trunk/minix/lib/i86/em/em_lfr8.s
===================================================================
--- /trunk/minix/lib/i86/em/em_lfr8.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_lfr8.s	(revision 9)
@@ -0,0 +1,11 @@
+.define .lfr8
+.text
+.extern .retarea
+
+.lfr8:
+	pop	bx
+	push	.retarea+6
+	push	.retarea+4
+	push	.retarea+2
+	push	.retarea
+	jmp	(bx)
Index: /trunk/minix/lib/i86/em/em_loi.s
===================================================================
--- /trunk/minix/lib/i86/em/em_loi.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_loi.s	(revision 9)
@@ -0,0 +1,38 @@
+.define .loi
+.define .los
+.text
+
+	! #bytes in cx
+	! address in bx
+	! save si/di. they might be register variables
+.los:
+	mov	dx,si
+	mov	si,bx
+	pop	bx
+	mov	ax,cx
+	sar	cx,#1
+	jnb	1f
+	xorb	ah,ah
+	lodsb
+	mov	si,dx
+	push	ax
+	jmp	(bx)
+1:
+	sub	sp,ax
+	jmp	1f
+
+.loi:
+	! only called with size > 4
+	mov	dx,si
+	mov	si,bx
+	pop     bx
+	sub     sp,cx
+	sar     cx,#1
+1:
+	mov	ax,di
+	mov     di,sp
+	rep
+	mov
+	mov	si,dx
+	mov	di,ax
+	jmp     (bx)
Index: /trunk/minix/lib/i86/em/em_mli4.s
===================================================================
--- /trunk/minix/lib/i86/em/em_mli4.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_mli4.s	(revision 9)
@@ -0,0 +1,25 @@
+.define .mli4
+.text
+
+yl=2
+yh=4
+	! x * y
+	! xl in ax
+	! xh in dx
+
+.mli4:
+	mov	bx,sp
+	push	dx
+	mov	cx,ax
+	mul	yh(bx)           ! xl*yh
+	pop	dx
+	push	ax
+	mov	ax,dx
+	mul	yl(bx)		! xh * yl
+	pop	dx
+	add     dx,ax           ! xh*yl+xl*yh
+	mov     ax,cx
+	mov	cx,dx
+	mul     yl(bx)           ! xl*yl
+	add     dx,cx
+	ret	4
Index: /trunk/minix/lib/i86/em/em_mon.s
===================================================================
--- /trunk/minix/lib/i86/em/em_mon.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_mon.s	(revision 9)
@@ -0,0 +1,6 @@
+.define .mon
+.text
+
+.mon:
+.extern .stop
+	call    .stop
Index: /trunk/minix/lib/i86/em/em_nop.s
===================================================================
--- /trunk/minix/lib/i86/em/em_nop.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_nop.s	(revision 9)
@@ -0,0 +1,4 @@
+.define .nop
+.text
+.nop:
+	ret
Index: /trunk/minix/lib/i86/em/em_rck.s
===================================================================
--- /trunk/minix/lib/i86/em/em_rck.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_rck.s	(revision 9)
@@ -0,0 +1,19 @@
+.define .rck
+.text
+
+	! descriptor address in bx
+	! value in ax, must be left there
+.rck:
+	cmp     ax,(bx)
+	jl      2f
+	cmp     ax,2(bx)
+	jg      2f
+	ret
+2:
+	push    ax
+ERANGE = 1
+.extern .error
+	mov     ax,#ERANGE
+	call    .error
+	pop     ax
+	ret
Index: /trunk/minix/lib/i86/em/em_ret6.s
===================================================================
--- /trunk/minix/lib/i86/em/em_ret6.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_ret6.s	(revision 9)
@@ -0,0 +1,10 @@
+.define .ret6
+.text
+.extern .retarea
+
+.ret6:
+	pop	bx
+	pop	.retarea
+	pop	.retarea+2
+	pop	.retarea+4
+	jmp	(bx)
Index: /trunk/minix/lib/i86/em/em_ret8.s
===================================================================
--- /trunk/minix/lib/i86/em/em_ret8.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_ret8.s	(revision 9)
@@ -0,0 +1,11 @@
+.define .ret8
+.text
+.extern .retarea
+
+.ret8:
+	pop	bx
+	pop	.retarea
+	pop	.retarea+2
+	pop	.retarea+4
+	pop	.retarea+6
+	jmp	(bx)
Index: /trunk/minix/lib/i86/em/em_retarea.s
===================================================================
--- /trunk/minix/lib/i86/em/em_retarea.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_retarea.s	(revision 9)
@@ -0,0 +1,5 @@
+.define .retarea
+
+.bss
+.retarea:
+	.zerow 8/2
Index: /trunk/minix/lib/i86/em/em_return.s
===================================================================
--- /trunk/minix/lib/i86/em/em_return.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_return.s	(revision 9)
@@ -0,0 +1,17 @@
+.define .sdret, .dsret, .sret, .dret, .cret 
+.text
+
+.dsret:
+	pop	di
+.sret:
+	pop	si
+.cret:
+	mov	sp,bp
+	pop	bp
+	ret
+
+.sdret:
+	pop	si
+.dret:
+	pop	di
+	jmp	.cret
Index: /trunk/minix/lib/i86/em/em_rmi4.s
===================================================================
--- /trunk/minix/lib/i86/em/em_rmi4.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_rmi4.s	(revision 9)
@@ -0,0 +1,89 @@
+.define .rmi4
+.text
+
+yl=6
+yh=8
+xl=10
+xh=12
+
+.rmi4:
+	push	si
+	push	di
+	mov     si,sp           ! copy of sp
+	mov     bx,yl(si)
+	mov     ax,yh(si)
+	cwd
+	cmp     dx,ax
+	jne     7f
+	and     dx,dx
+	jge     1f
+	neg     bx
+	je      7f
+1:
+	xor     dx,dx
+	mov     cx,xl(si)
+	mov     ax,xh(si)
+	and     ax,ax
+	jge     2f
+	neg     ax
+	neg     cx
+	sbb     ax,dx
+2:
+	div     bx
+	xchg    ax,cx
+	div     bx              ! dx= result(low), 0=result(high)
+	xor     bx,bx
+9:
+	cmp     xh(si),#0
+	jge     1f
+	neg     bx
+	neg     dx
+	sbb     bx,#0
+1:
+			! bx is high order result
+			! dx is low order result
+	mov	ax,dx
+	mov	dx,bx	! result in ax/dx
+	pop	di
+	pop	si
+	ret	8
+
+7:
+	mov     di,ax
+	xor     bx,bx
+	and     di,di
+	jge     1f
+	neg     di
+	neg     yl(si)
+	sbb     di,bx
+1:
+	mov     ax,xl(si)
+	mov     dx,xh(si)
+	and     dx,dx
+	jge     1f
+	neg     dx
+	neg     ax
+	sbb     dx,bx
+1:
+	mov     cx,#16
+1:
+	shl     ax,#1
+	rcl     dx,#1
+	rcl     bx,#1
+	cmp     di,bx
+	ja      3f
+	jb      2f
+	cmp     yl(si),dx
+	jbe     2f
+3:
+	loop    1b
+		! dx=result(low), bx=result(high)
+	jmp     9b
+2:
+	sub     dx,yl(si)
+	sbb     bx,di
+	inc     ax
+	loop    1b
+1:
+		! dx=result(low), bx=result(high)
+	jmp     9b
Index: /trunk/minix/lib/i86/em/em_rmu4.s
===================================================================
--- /trunk/minix/lib/i86/em/em_rmu4.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_rmu4.s	(revision 9)
@@ -0,0 +1,61 @@
+.define .rmu4
+.text
+
+yl=6
+yh=8
+xl=10
+xh=12
+
+.rmu4:
+	push	si
+	push	di
+	mov     si,sp           ! copy of sp
+	mov     bx,yl(si)
+	mov     ax,yh(si)
+	or      ax,ax
+	jne     7f
+1:
+	xor     dx,dx
+	mov     cx,xl(si)
+	mov     ax,xh(si)
+2:
+	div     bx
+	xchg    ax,cx
+	div     bx
+	xor     bx,bx
+9:
+			! bx is high order result
+			! dx is low order result
+	mov	ax,dx
+	mov	dx,bx
+	pop	di
+	pop	si
+	ret	8	! result in ax/dx
+
+7:
+	mov     di,ax
+	xor     bx,bx
+	mov     ax,xl(si)
+	mov     dx,xh(si)
+	mov     cx,#16
+1:
+	shl     ax,#1
+	rcl     dx,#1
+	rcl     bx,#1
+	cmp     di,bx
+	ja      3f
+	jb      2f
+	cmp     yl(si),dx
+	jbe     2f
+3:
+	loop    1b
+		! dx=result(low), bx=result(high)
+	jmp     9b
+2:
+	sub     dx,yl(si)
+	sbb     bx,di
+	inc     ax
+	loop    1b
+1:
+		! dx=result(low), bx=result(high)
+	jmp     9b
Index: /trunk/minix/lib/i86/em/em_sar2.s
===================================================================
--- /trunk/minix/lib/i86/em/em_sar2.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_sar2.s	(revision 9)
@@ -0,0 +1,33 @@
+.define .sar2
+.text
+
+.sar2:
+				! bx, descriptor address
+				! ax, index
+	pop	cx
+	pop	dx		! base address
+	push	cx
+	xchg	di,dx		! di = base address, dx is saved di
+	sub     ax,(bx)
+	mov     cx,4(bx)
+	push	dx
+	imul    cx
+	pop	dx
+	add     di,ax
+	sar     cx,#1
+	jnb     1f
+	pop	bx
+	pop     ax
+	stosb
+	mov	di,dx
+	jmp     (bx)
+1:
+	pop	bx
+	mov	ax,si
+	mov     si,sp
+	rep
+	mov
+	mov     sp,si
+	mov	si,ax
+	mov	di,dx
+	jmp     (bx)
Index: /trunk/minix/lib/i86/em/em_sbi.s
===================================================================
--- /trunk/minix/lib/i86/em/em_sbi.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_sbi.s	(revision 9)
@@ -0,0 +1,27 @@
+.define .sbi
+.text
+
+	! #bytes in cx , top of stack in ax
+.sbi:
+	pop     bx              ! return subress
+	cmp     cx,#2
+	jne     1f
+	pop     cx
+	sub     ax,cx
+	neg     ax
+	jmp     (bx)
+1:
+	cmp     cx,#4
+	jne     9f
+	pop     dx
+	pop     cx
+	sub     cx,ax
+	mov     ax,cx
+	pop     cx
+	sbb     cx,dx
+	push    cx
+	jmp     (bx)
+9:
+.extern .trpilin
+	push    bx
+	jmp     .trpilin
Index: /trunk/minix/lib/i86/em/em_set.s
===================================================================
--- /trunk/minix/lib/i86/em/em_set.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_set.s	(revision 9)
@@ -0,0 +1,43 @@
+.define .set
+.text
+
+	! #bytes in cx
+	! bit # in ax
+.set:
+	pop     bx              ! return address
+	xor     dx,dx
+!ifdef create set
+	sub	sp,cx
+	push	bx
+	push	di
+	mov     bx,sp
+	xor	di,di
+	sar	cx,#1
+1:
+	mov     4(bx)(di),dx
+	inc	di
+	inc	di
+	loop	1b
+!endif
+	mov     bx,#8
+	div     bx
+	cmp     ax,di
+	jae     2f
+	mov	di,dx
+	movb	dl,bits(di)
+	mov     di,sp
+	add     di,ax
+	orb     4(di),dl
+	pop	di
+	ret
+2:
+ESET = 2
+.extern .error
+	pop	di
+	mov     ax,#ESET
+	call	.error
+	ret
+
+	.data
+bits:
+	.data1   1,2,4,8,16,32,64,128
Index: /trunk/minix/lib/i86/em/em_stb.s
===================================================================
--- /trunk/minix/lib/i86/em/em_stb.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_stb.s	(revision 9)
@@ -0,0 +1,16 @@
+.define ___stb
+.text
+
+	! Routine for copying structs.
+___stb:
+	mov	bx,sp
+	push	si
+	push	di
+	mov	cx,2(bx)
+	mov	si,4(bx)
+	mov	di,6(bx)
+	rep
+	movb
+	pop	di
+	pop	si
+	ret
Index: /trunk/minix/lib/i86/em/em_sti.s
===================================================================
--- /trunk/minix/lib/i86/em/em_sti.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_sti.s	(revision 9)
@@ -0,0 +1,32 @@
+.define .sti
+.define .sts
+.text
+
+	! #bytes in cx
+	! address in bx
+	! save di/si. they might be register variables
+.sts:
+	mov	dx,di		! save di
+	mov	di,bx
+	pop     bx              ! return address
+	sar     cx,#1
+	jnb     1f
+	pop     ax
+	stosb
+	mov	di,dx
+	jmp     (bx)
+.sti:
+	! only called with count > 4
+	mov	dx,di
+	mov	di,bx
+	pop	bx
+	sar	cx,#1
+1:
+	mov	ax,si
+	mov     si,sp
+	rep
+	mov
+	mov     sp,si
+	mov	di,dx
+	mov	si,ax
+	jmp     (bx)
Index: /trunk/minix/lib/i86/em/em_stop.s
===================================================================
--- /trunk/minix/lib/i86/em/em_stop.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_stop.s	(revision 9)
@@ -0,0 +1,4 @@
+.define .stop
+.text
+.stop:
+	call	__exit
Index: /trunk/minix/lib/i86/em/em_trp.s
===================================================================
--- /trunk/minix/lib/i86/em/em_trp.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_trp.s	(revision 9)
@@ -0,0 +1,138 @@
+.define .trpdivz
+.define .trpilin
+.define .trpcase
+.define .trprang
+.define .trpset
+.define .trpnofp
+.define .trpheap
+.define .trp
+
+.bss
+.M: .zerow 24/2
+
+.text
+.extern .trpdivz
+.extern .trpilin
+.extern .trpcase
+.extern .trprang
+.extern .trpset
+.extern .trpnofp
+.extern .trpheap
+.extern .trp
+
+.trpdivz:
+mov ax,#6
+mov dx,#.Mdivz
+jmp .Trp
+.trpilin:
+mov ax,#18
+mov dx,#.Milin
+jmp .Trp
+.trpcase:
+mov ax,#20
+mov dx,#.Mcase
+jmp .Trp
+.trprang:
+mov ax,#1
+mov dx,#.Mrang
+jmp .Trp
+.trpset:
+mov ax,#2
+mov dx,#.Mset
+jmp .Trp
+.trpnofp:
+mov ax,#18
+mov dx,#.Mnofp
+jmp .Trp
+.trpheap:
+mov ax,#17
+mov dx,#.Mheap
+jmp .Trp
+
+.Trp:
+xor     bx,bx
+.extern .trppc
+xchg    bx,.trppc
+test    bx,bx
+jz      2f
+push    ax
+call    (bx)
+pop     ax
+ret
+2:
+mov bx,#22
+push bx
+push dx
+mov ax,#2
+push ax
+call .Write
+call __exit
+
+.trp:
+mov dx,ax
+cmp dx,#21
+jae 1f
+sal dx,#1
+mov bx,#.Mtable
+add bx,dx
+mov bx,(bx)
+test bx,bx
+jz 1f
+mov dx,bx
+jmp 2f
+1:
+mov bx,#.Mtrp+14
+mov cx,#6
+mov dx,ax
+1:
+and dx,#7
+add dx,'0'
+movb (bx),dl
+dec bx
+sar dx,#1
+sar dx,#1
+sar dx,#1
+loop 1b
+mov dx,#.Mtrp
+2:
+jmp .Trp
+
+.Write:
+push bp
+mov bp,sp
+mov .M+2,#4
+mov bx,4(bp)
+mov .M+4,bx
+mov bx,8(bp)
+mov .M+6,bx
+mov bx,6(bp)
+mov .M+10,bx
+mov ax,#.M
+push ax
+mov ax,#1
+push ax
+
+mov ax,#1
+mov bx,#.M
+mov cx,#3
+int 32
+mov sp,bp
+pop bp
+ret
+
+
+.data
+.Mtable:
+	.data2 0,	.Mrang,	.Mset,	0,	0,	0,	.Mdivz,	0
+	.data2 0,	0,	0,	0,	0,	0,	0,	0
+	.data2 0,	.Mheap,	.Milin,	.Milin,	.Mcase
+
+.Mdivz: .asciz "Error: Division by 0 \n"
+.Milin: .asciz "Illegal EM instruct'n\n"
+.Mcase: .asciz "Err in EM case instr \n"
+.Mrang: .asciz "Variable out of range\n"
+.Mset:  .asciz "Err in EM set instr  \n"
+.Mnofp: .asciz "Floating pt not impl.\n"
+.Mheap: .asciz "Heap overflow        \n"
+
+.Mtrp:	.asciz "EM trap 0000000 octal\n"
Index: /trunk/minix/lib/i86/em/em_unknown.s
===================================================================
--- /trunk/minix/lib/i86/em/em_unknown.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_unknown.s	(revision 9)
@@ -0,0 +1,9 @@
+.define .unknown
+.text
+.extern .fat
+EILLINS = 18
+
+.unknown:
+	mov  ax,#EILLINS
+	push ax
+	jmp  .fat
Index: /trunk/minix/lib/i86/em/em_vars.s
===================================================================
--- /trunk/minix/lib/i86/em/em_vars.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_vars.s	(revision 9)
@@ -0,0 +1,12 @@
+.define .reghp, .limhp, .ignmask, .trppc
+.extern .reghp, .limhp, .ignmask, .trppc
+
+.data
+.reghp:
+	.data2   endbss
+.limhp:
+	.data2   endbss
+.ignmask:
+	.data2   1336
+.trppc:
+	.data2   0
Index: /trunk/minix/lib/i86/em/em_xor.s
===================================================================
--- /trunk/minix/lib/i86/em/em_xor.s	(revision 9)
+++ /trunk/minix/lib/i86/em/em_xor.s	(revision 9)
@@ -0,0 +1,17 @@
+.define	.xor
+.text
+
+	! #bytes in cx
+.xor:
+	pop	bx		! return address
+	mov	dx,di
+	mov	di,sp
+	add	di,cx
+	sar	cx,#1
+1:
+	pop	ax
+	xor	ax,(di)
+	stos
+	loop	1b
+	mov	di,dx
+	jmp	(bx)
Index: /trunk/minix/lib/i86/int64/add64.s
===================================================================
--- /trunk/minix/lib/i86/int64/add64.s	(revision 9)
+++ /trunk/minix/lib/i86/int64/add64.s	(revision 9)
@@ -0,0 +1,24 @@
+!	add64() - 64 bit addition			Author: Kees J. Bot
+!								24 Dec 1995
+.sect .text
+.define _add64
+
+_add64:				! u64_t add64(u64_t i, u64_t j);
+	push	bp
+	mov	bp, sp
+	mov	bx, 4(bp)
+	mov	ax, 6(bp)
+	add	ax, 14(bp)
+	mov	(bx), ax
+	mov	ax, 8(bp)
+	adc	ax, 16(bp)
+	mov	2(bx), ax
+	mov	ax, 10(bp)
+	adc	ax, 18(bp)
+	mov	4(bx), ax
+	mov	ax, 12(bp)
+	adc	ax, 20(bp)
+	mov	6(bx), ax
+	mov	ax, bx
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/int64/add64u.s
===================================================================
--- /trunk/minix/lib/i86/int64/add64u.s	(revision 9)
+++ /trunk/minix/lib/i86/int64/add64u.s	(revision 9)
@@ -0,0 +1,30 @@
+!	add64u() - unsigned to 64 bit addition		Author: Kees J. Bot
+!								24 Dec 1995
+.sect .text
+.define _add64u, _add64ul
+
+_add64u:			! u64_t add64u(u64_t i, unsigned j);
+	push	bp
+	mov	bp, sp
+	xor	cx, cx
+	jmp	0f
+_add64ul:			! u64_t add64ul(u64_t i, unsigned long j);
+	push	bp
+	mov	bp, sp
+	mov	cx, 16(bp)
+0:	mov	bx, 4(bp)
+	mov	ax, 6(bp)
+	add	ax, 14(bp)
+	mov	(bx), ax
+	mov	ax, 8(bp)
+	adc	ax, cx
+	mov	2(bx), ax
+	mov	ax, 10(bp)
+	adc	ax, #0
+	mov	4(bx), ax
+	mov	ax, 12(bp)
+	adc	ax, #0
+	mov	6(bx), ax
+	mov	ax, bx
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/int64/cmp64.s
===================================================================
--- /trunk/minix/lib/i86/int64/cmp64.s	(revision 9)
+++ /trunk/minix/lib/i86/int64/cmp64.s	(revision 9)
@@ -0,0 +1,52 @@
+!	cmp64*() - 64 bit compare			Author: Kees J. Bot
+!								24 Dec 1995
+.sect .text
+.define _cmp64, _cmp64u, _cmp64ul
+
+_cmp64:				! int cmp64(u64_t i, u64_t j);
+	mov	bx, sp
+cmp64:	xor	ax, ax
+	mov	dx, 2(bx)
+	sub	dx, 10(bx)
+	mov	dx, 4(bx)
+	sbb	dx, 12(bx)
+	mov	dx, 6(bx)
+	sbb	dx, 14(bx)
+	mov	dx, 8(bx)
+	sbb	dx, 16(bx)
+	sbb	ax, ax			! ax = - (i < j)
+	mov	dx, 10(bx)
+	sub	dx, 2(bx)
+	mov	dx, 12(bx)
+	sbb	dx, 4(bx)
+	mov	dx, 14(bx)
+	sbb	dx, 6(bx)
+	mov	dx, 16(bx)
+	sbb	dx, 8(bx)
+	adc	ax, #0			! ax = (i > j) - (i < j)
+	ret
+
+_cmp64u:			! int cmp64u(u64_t i, unsigned j);
+	mov	bx, sp
+	push	16(bx)
+	mov	16(bx), #0
+	push	14(bx)
+	mov	14(bx), #0
+	push	12(bx)
+	mov	12(bx), #0
+	call	cmp64
+	pop	12(bx)
+	pop	14(bx)
+	pop	16(bx)
+	ret
+
+_cmp64ul:			! int cmp64ul(u64_t i, unsigned long j);
+	mov	bx, sp
+	push	14(bx)
+	mov	14(bx), #0
+	push	12(bx)
+	mov	12(bx), #0
+	call	cmp64
+	pop	12(bx)
+	pop	14(bx)
+	ret
Index: /trunk/minix/lib/i86/int64/cv64u.s
===================================================================
--- /trunk/minix/lib/i86/int64/cv64u.s	(revision 9)
+++ /trunk/minix/lib/i86/int64/cv64u.s	(revision 9)
@@ -0,0 +1,21 @@
+!	cv64u() - 64 bit converted to unsigned		Author: Kees J. Bot
+!								24 Dec 1995
+.sect .text
+.define _cv64u, _cv64ul
+
+_cv64u:				! unsigned cv64u(u64_t i);
+	mov	bx, sp
+	mov	cx, 4(bx)
+	jmp	0f
+
+_cv64ul:			! unsigned long cv64ul(u64_t i);
+	mov	bx, sp
+	xor	cx, cx
+0:	mov	ax, 2(bx)
+	mov	dx, 4(bx)
+	or	cx, 6(bx)
+	or	cx, 8(bx)		! return UINT/ULONG_MAX if really big
+	jz	0f
+	mov	ax, #-1
+	mov	dx, ax
+0:	ret
Index: /trunk/minix/lib/i86/int64/cvu64.s
===================================================================
--- /trunk/minix/lib/i86/int64/cvu64.s	(revision 9)
+++ /trunk/minix/lib/i86/int64/cvu64.s	(revision 9)
@@ -0,0 +1,21 @@
+!	cvu64() - unsigned converted to 64 bit		Author: Kees J. Bot
+!								24 Dec 1995
+.sect .text
+.define _cvu64, _cvul64
+
+_cvu64:				! u64_t cvu64(unsigned i);
+	mov	bx, sp
+	xor	dx, dx
+	jmp	0f
+
+_cvul64:			! u64_t cvul64(unsigned long i);
+	mov	bx, sp
+	mov	dx, 6(bx)
+0:	mov	ax, 4(bx)
+	mov	bx, 2(bx)
+	mov	(bx), ax
+	mov	2(bx), dx
+	mov	4(bx), #0
+	mov	6(bx), #0
+	mov	ax, bx
+	ret
Index: /trunk/minix/lib/i86/int64/diff64.s
===================================================================
--- /trunk/minix/lib/i86/int64/diff64.s	(revision 9)
+++ /trunk/minix/lib/i86/int64/diff64.s	(revision 9)
@@ -0,0 +1,10 @@
+!	diff64() - 64 bit subtraction giving unsigned 	Author: Kees J. Bot
+!								24 Dec 1995
+.sect .text
+.define _diff64
+
+_diff64:			! unsigned diff64(u64_t i, u64_t j);
+	mov	bx, sp
+	mov	ax, 2(bx)
+	sub	ax, 10(bx)
+	ret
Index: /trunk/minix/lib/i86/int64/div64u.s
===================================================================
--- /trunk/minix/lib/i86/int64/div64u.s	(revision 9)
+++ /trunk/minix/lib/i86/int64/div64u.s	(revision 9)
@@ -0,0 +1,26 @@
+!	div64u() - 64 bit divided by unsigned giving unsigned long
+!							Author: Kees J. Bot
+!								24 Dec 1995
+.sect .text
+.define _div64u, _rem64u
+
+_div64u:			! unsigned long div64u(u64_t i, unsigned j);
+	mov	bx, sp
+div64u:	xor	dx, dx
+	mov	ax, 8(bx)
+	div	10(bx)
+	mov	ax, 6(bx)
+	div	10(bx)
+	mov	ax, 4(bx)
+	div	10(bx)			! division bits 16-31
+	mov	cx, ax
+	mov	ax, 2(bx)
+	div	10(bx)			! division bits 0-15
+	xchg	dx, cx			! division in dx:ax, remainder in cx
+	ret
+
+_rem64u:			! unsigned rem64u(u64_t i, unsigned j);
+	mov	bx, sp
+	call	div64u
+	mov	ax, cx
+	ret
Index: /trunk/minix/lib/i86/int64/ex64.s
===================================================================
--- /trunk/minix/lib/i86/int64/ex64.s	(revision 9)
+++ /trunk/minix/lib/i86/int64/ex64.s	(revision 9)
@@ -0,0 +1,17 @@
+!	ex64*() - extract low or high 32 bits of a 64 bit number
+!							Author: Kees J. Bot
+!								24 Dec 1995
+.sect .text
+.define _ex64lo, _ex64hi
+
+_ex64lo:			! unsigned long ex64lo(u64_t i);
+	mov	bx, sp
+	mov	ax, 2(bx)
+	mov	dx, 4(bx)
+	ret
+
+_ex64hi:			! unsigned long ex64hi(u64_t i);
+	mov	bx, sp
+	mov	ax, 6(bx)
+	mov	dx, 8(bx)
+	ret
Index: /trunk/minix/lib/i86/int64/make64.s
===================================================================
--- /trunk/minix/lib/i86/int64/make64.s	(revision 9)
+++ /trunk/minix/lib/i86/int64/make64.s	(revision 9)
@@ -0,0 +1,19 @@
+!	make64() - make a 64 bit number from two 32 bit halves
+!							Author: Kees J. Bot
+!								24 Dec 1995
+.sect .text
+.define _make64
+
+_make64:		    ! u64_t make64(unsigned long lo, unsigned long hi);
+	mov	bx, sp
+	mov	ax, 4(bx)
+	mov	dx, 6(bx)
+	mov	cx, 8(bx)
+	push	10(bx)
+	mov	bx, 2(bx)
+	mov	(bx), ax
+	mov	2(bx), dx
+	mov	4(bx), cx
+	pop	6(bx)
+	mov	ax, bx
+	ret
Index: /trunk/minix/lib/i86/int64/mul64u.s
===================================================================
--- /trunk/minix/lib/i86/int64/mul64u.s	(revision 9)
+++ /trunk/minix/lib/i86/int64/mul64u.s	(revision 9)
@@ -0,0 +1,23 @@
+!	mul64u() - unsigned long by unsigned multiply giving 64 bit result
+!							Author: Kees J. Bot
+!								24 Dec 1995
+.sect .text
+.define _mul64u
+
+_mul64u:			! u64_t mul64u(unsigned long i, unsigned j);
+	push	bp
+	mov	bp, sp
+	mov	bx, 4(bp)
+	mov	ax, 6(bp)
+	mul	10(bp)
+	mov	(bx), ax
+	mov	2(bx), dx
+	mov	ax, 8(bp)
+	mul	10(bp)
+	add	2(bx), ax
+	adc	dx, #0
+	mov	4(bx), dx
+	mov	6(bx), #0
+	mov	ax, bx
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/int64/sub64.s
===================================================================
--- /trunk/minix/lib/i86/int64/sub64.s	(revision 9)
+++ /trunk/minix/lib/i86/int64/sub64.s	(revision 9)
@@ -0,0 +1,24 @@
+!	sub64() - 64 bit subtraction			Author: Kees J. Bot
+!								24 Dec 1995
+.sect .text
+.define _sub64
+
+_sub64:				! u64_t sub64(u64_t i, u64_t j);
+	push	bp
+	mov	bp, sp
+	mov	bx, 4(bp)
+	mov	ax, 6(bp)
+	sub	ax, 14(bp)
+	mov	(bx), ax
+	mov	ax, 8(bp)
+	sbb	ax, 16(bp)
+	mov	2(bx), ax
+	mov	ax, 10(bp)
+	sbb	ax, 18(bp)
+	mov	4(bx), ax
+	mov	ax, 12(bp)
+	sbb	ax, 20(bp)
+	mov	6(bx), ax
+	mov	ax, bx
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/int64/sub64u.s
===================================================================
--- /trunk/minix/lib/i86/int64/sub64u.s	(revision 9)
+++ /trunk/minix/lib/i86/int64/sub64u.s	(revision 9)
@@ -0,0 +1,30 @@
+!	sub64u() - unsigned from 64 bit subtraction	Author: Kees J. Bot
+!								24 Dec 1995
+.sect .text
+.define _sub64u, _sub64ul
+
+_sub64u:			! u64_t sub64u(u64_t i, unsigned j);
+	push	bp
+	mov	bp, sp
+	xor	cx, cx
+	jmp	0f
+_sub64ul:			! u64_t sub64ul(u64_t i, unsigned long j);
+	push	bp
+	mov	bp, sp
+	mov	cx, 16(bp)
+0:	mov	bx, 4(bp)
+	mov	ax, 6(bp)
+	sub	ax, 14(bp)
+	mov	(bx), ax
+	mov	ax, 8(bp)
+	sbb	ax, cx
+	mov	2(bx), ax
+	mov	ax, 10(bp)
+	sbb	ax, #0
+	mov	4(bx), ax
+	mov	ax, 12(bp)
+	sbb	ax, #0
+	mov	6(bx), ax
+	mov	ax, bx
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/misc/alloca.s
===================================================================
--- /trunk/minix/lib/i86/misc/alloca.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/alloca.s	(revision 9)
@@ -0,0 +1,23 @@
+#
+!	alloca() - allocate space on the stack		Author: Kees J. Bot
+!								26 Jan 1994
+
+#if __ACK__	/* BCC can't do alloca(), register saving is wrong. */
+
+.text
+.define _alloca
+_alloca:
+	pop	cx		! Return address
+	pop	ax		! Bytes to allocate
+	add	ax, #2*2+1	! Add space for two saved register variables
+	andb	al, #0xFE	! Align
+	mov	bx, sp		! Keep current sp
+	sub	sp, ax		! Lower stack
+	mov	ax, sp		! Return value
+	push	2(bx)		! Push what is probably the saved si
+	push	(bx)		! Saved di
+				! Now ACK can still do:
+				!	pop di; pop si; mov sp, bp; pop bp; ret
+	push	ax		! Dummy argument
+	jmp	(cx)
+#endif
Index: /trunk/minix/lib/i86/misc/get_bp.s
===================================================================
--- /trunk/minix/lib/i86/misc/get_bp.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/get_bp.s	(revision 9)
@@ -0,0 +1,15 @@
+! get_bp.s
+!
+! return BP in AX
+!
+! Created:	Sep 7, 1992 by Philip Homburg
+
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+.sect .text
+.define _get_bp
+_get_bp:
+	mov	ax, bp
+	ret
+
+! $PchId: get_bp.ack.s,v 1.3 1996/02/23 08:27:48 philip Exp $
Index: /trunk/minix/lib/i86/misc/getprocessor.s
===================================================================
--- /trunk/minix/lib/i86/misc/getprocessor.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/getprocessor.s	(revision 9)
@@ -0,0 +1,92 @@
+!	getprocessor() - determine processor type	Author: Kees J. Bot
+!								26 Jan 1994
+
+.text
+
+	o32 = 0x66		! 32 bit operand size prefix
+
+! int getprocessor(void);
+!	Return 86, 186, 286, 386, 486, 586, ...
+
+.define	_getprocessor
+
+_getprocessor:
+	push	bp
+	mov	bp, sp
+	push	sp		! see if pushed sp == sp
+	pop	ax
+	cmp	ax, sp
+	jz	new_processor
+	mov	cx, #0x0120	! see if shifts are mod 32
+	shlb	ch, cl		! zero tells if 86
+	mov	ax, #86
+	jz	got_processor
+	mov	ax, #186
+	jmp	got_processor
+
+new_processor:			! see if high bits are set in saved IDT
+	sub	sp, #6		! space for IDT ptr
+	sidt	-6(bp)		! save 3 word IDT ptr
+	cmpb	-1(bp), #0xFF	! top byte of IDT ptr is always FF on 286
+	mov	ax, #286
+	je	got_processor
+
+! 386, 486, 586
+	and	sp, #0xFFFC	! Align stack to avoid AC fault (needed?)
+	mov	cx, #0x0004	! Try to flip the AC bit introduced on the 486
+	call	flip
+	mov	ax, #386	! 386 if it didn't react to "flipping"
+	jz	got_processor
+	mov	cx, #0x0020	! Try to flip the ID bit introduced on the 586
+	call	flip
+	mov	ax, #486	! 486 if it didn't react
+	jz	got_processor
+	.data1	o32
+	pushf
+	.data1	o32
+	pusha			! Save the world
+	.data1	o32
+	xor	ax, ax
+	inc	ax		! eax = 1
+	.data1	0x0F, 0xA2	! CPUID instruction tells the processor type
+	andb	ah, #0x0F	! Extract the family (5, 6, ...)
+	movb	al, ah
+	movb	ah, #100
+	mulb	ah		! 500, 600, ...
+	add	ax, #86		! 586, 686, ...
+	mov	bx, sp
+	mov	7*4(bx), ax	! Pass ax through
+	.data1	o32
+	popa
+	.data1	o32
+	popf
+
+got_processor:
+	mov	sp, bp
+	pop	bp
+	ret
+
+flip:
+	push	bx		! Save bx and realign stack to multiple of 4
+	.data1	o32		! About to operate on a 32 bit object
+	pushf			! Push eflags
+	pop	ax
+	pop	dx		! dx:ax = eflags
+	mov	bx, dx		! Save original eflags (high word only)
+	xor	dx, cx		! Flip the bit to test
+	push	dx
+	push	ax		! Push modified eflags value
+	.data1	o32
+	popf			! Load modified eflags register
+	.data1	o32
+	pushf
+	pop	ax
+	pop	dx		! Get it again
+	push	bx
+	push	ax
+	.data1	o32
+	popf			! Restore original eflags register
+	xor	dx, bx		! See if the bit changed
+	test	dx, cx
+	pop	bx		! Restore bx
+	ret
Index: /trunk/minix/lib/i86/misc/hton86.s
===================================================================
--- /trunk/minix/lib/i86/misc/hton86.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/hton86.s	(revision 9)
@@ -0,0 +1,25 @@
+!	htonX(), ntohX() - Host to network byte order conversion
+!							Author: Kees J. Bot
+!								7 Jan 1997
+!
+! This is a little endian 8086, so we swap bytes to/from the big endian network
+! order.  The normal <net/hton.h> macros are not used, they give lousy code.
+
+.text
+.define _htons, _ntohs
+_htons:
+_ntohs:
+	mov	bx, sp
+	movb	ah, 2(bx)	! Load bytes into ax in reverse order
+	movb	al, 3(bx)
+	ret
+
+.define _htonl, _ntohl
+_htonl:
+_ntohl:
+	mov	bx, sp
+	movb	dh, 2(bx)	! Load bytes into dx:ax in reverse order
+	movb	dl, 3(bx)
+	movb	ah, 4(bx)
+	movb	al, 5(bx)
+	ret
Index: /trunk/minix/lib/i86/misc/io_inb.s
===================================================================
--- /trunk/minix/lib/i86/misc/io_inb.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/io_inb.s	(revision 9)
@@ -0,0 +1,14 @@
+!	inb() - Input one byte				Author: Kees J. Bot
+!								18 Mar 1996
+!	unsigned inb(U16_t port);
+
+.sect .text
+.define _inb
+_inb:
+	push	bp
+	mov	bp, sp
+	mov	dx, 4(bp)		! port
+	inb	dx			! read 1 byte
+	xorb	ah, ah
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/misc/io_inl.s
===================================================================
--- /trunk/minix/lib/i86/misc/io_inl.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/io_inl.s	(revision 9)
@@ -0,0 +1,23 @@
+!	inl() - Input one dword				Author: Kees J. Bot
+!								18 Mar 1996
+!	unsigned inl(U16_t port);
+
+	o32 = 0x66
+
+.sect .text
+.define _inl
+_inl:
+	push	bp
+	mov	bp, sp
+	pushf
+	cli				! eax is not interrupt safe
+	mov	dx, 4(bp)		! port
+	.data1	o32
+	in	dx			! read 1 dword
+	.data1	o32
+	push	ax			! push eax
+	pop	ax
+	pop	dx			! dx:ax = eax
+	popf
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/misc/io_insb.s
===================================================================
--- /trunk/minix/lib/i86/misc/io_insb.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/io_insb.s	(revision 9)
@@ -0,0 +1,21 @@
+!	insb() - Input a byte array			Author: Kees J. Bot
+!								18 Mar 1996
+!	void insb(U16_t port, void *buf, size_t count);
+
+.sect .text
+.define _insb
+_insb:
+	push	bp
+	mov	bp, sp
+	cld
+	push	di
+	mov	dx, 4(bp)		! port
+	mov	di, 6(bp)		! buf
+	mov	cx, 8(bp)		! byte count
+	jcxz	1f
+0:	inb	dx			! input 1 byte
+	stosb				! write 1 byte
+	loop	0b			! many times
+1:	pop	di
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/misc/io_insl.s
===================================================================
--- /trunk/minix/lib/i86/misc/io_insl.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/io_insl.s	(revision 9)
@@ -0,0 +1,22 @@
+!	insl() - Input a dword array			Author: Kees J. Bot
+!								18 Mar 1996
+!	void insl(U16_t port, void *buf, size_t count);
+
+	o32 = 0x66
+
+.sect .text
+.define _insl
+_insl:
+	push	bp
+	mov	bp, sp
+	cld
+	push	di
+	mov	dx, 4(bp)		! port
+	mov	di, 6(bp)		! buf
+	mov	cx, 8(bp)		! byte count
+	shr	cx, #2			! dword count
+	.data1	o32
+   rep	ins				! input many dwords
+	pop	di
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/misc/io_insw.s
===================================================================
--- /trunk/minix/lib/i86/misc/io_insw.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/io_insw.s	(revision 9)
@@ -0,0 +1,19 @@
+!	insw() - Input a word array			Author: Kees J. Bot
+!								18 Mar 1996
+!	void insw(U16_t port, void *buf, size_t count);
+
+.sect .text
+.define _insw
+_insw:
+	push	bp
+	mov	bp, sp
+	cld
+	push	di
+	mov	dx, 4(bp)		! port
+	mov	di, 6(bp)		! buf
+	mov	cx, 8(bp)		! byte count
+	shr	cx, #1			! word count
+   rep	ins				! input many words
+	pop	di
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/misc/io_intr.s
===================================================================
--- /trunk/minix/lib/i86/misc/io_intr.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/io_intr.s	(revision 9)
@@ -0,0 +1,16 @@
+!	intr_disable(), intr_enable - Disable/Enable hardware interrupts.
+!							Author: Kees J. Bot
+!								18 Mar 1996
+!	void intr_disable(void);
+!	void intr_enable(void);
+
+.sect .text
+.define _intr_disable
+_intr_disable:
+	cli
+	ret
+
+.define _intr_enable
+_intr_enable:
+	sti
+	ret
Index: /trunk/minix/lib/i86/misc/io_inw.s
===================================================================
--- /trunk/minix/lib/i86/misc/io_inw.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/io_inw.s	(revision 9)
@@ -0,0 +1,13 @@
+!	inw() - Input one word				Author: Kees J. Bot
+!								18 Mar 1996
+!	unsigned inw(U16_t port);
+
+.sect .text
+.define _inw
+_inw:
+	push	bp
+	mov	bp, sp
+	mov	dx, 4(bp)		! port
+	in	dx			! read 1 word
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/misc/io_outb.s
===================================================================
--- /trunk/minix/lib/i86/misc/io_outb.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/io_outb.s	(revision 9)
@@ -0,0 +1,14 @@
+!	outb() - Output one byte			Author: Kees J. Bot
+!								18 Mar 1996
+!	void outb(U16_t port, U8_t value);
+
+.sect .text
+.define _outb
+_outb:
+	push	bp
+	mov	bp, sp
+	mov	dx, 4(bp)		! port
+	mov	ax, 4+2(bp)		! value
+	outb	dx			! output 1 byte
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/misc/io_outl.s
===================================================================
--- /trunk/minix/lib/i86/misc/io_outl.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/io_outl.s	(revision 9)
@@ -0,0 +1,21 @@
+!	outl() - Output one dword			Author: Kees J. Bot
+!								18 Mar 1996
+!	void outl(U16_t port, u32_t value);
+
+	o32 = 0x66
+
+.sect .text
+.define _outl
+_outl:
+	push	bp
+	mov	bp, sp
+	pushf
+	cli				! eax is not interrupt safe
+	mov	dx, 4(bp)		! port
+	.data1	o32
+	mov	ax, 4+2(bp)		! value
+	.data1	o32
+	out	dx			! output 1 dword
+	popf
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/misc/io_outsb.s
===================================================================
--- /trunk/minix/lib/i86/misc/io_outsb.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/io_outsb.s	(revision 9)
@@ -0,0 +1,21 @@
+!	outsb() - Output a byte array		Author: Kees J. Bot
+!								18 Mar 1996
+!	void outsb(U16_t port, void *buf, size_t count);
+
+.sect .text
+.define _outsb
+_outsb:
+	push	bp
+	mov	bp, sp
+	cld
+	push	si
+	mov	dx, 4(bp)		! port
+	mov	si, 6(bp)		! buf
+	mov	cx, 8(bp)		! byte count
+	jcxz	1f
+0:	lodsb				! read 1 byte
+	outb	dx			! output 1 byte
+	loop	0b			! many times
+1:	pop	si
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/misc/io_outsl.s
===================================================================
--- /trunk/minix/lib/i86/misc/io_outsl.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/io_outsl.s	(revision 9)
@@ -0,0 +1,22 @@
+!	outsl() - Output a dword array		Author: Kees J. Bot
+!								18 Mar 1996
+!	void outsl(U16_t port, void *buf, size_t count);
+
+	o32 = 0x66
+
+.sect .text
+.define _outsl
+_outsl:
+	push	bp
+	mov	bp, sp
+	cld
+	push	si
+	mov	dx, 4(bp)		! port
+	mov	si, 6(bp)		! buf
+	mov	cx, 8(bp)		! byte count
+	shr	cx, #2			! dword count
+	.data1	o32
+   rep	outs				! output many dwords
+	pop	si
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/misc/io_outsw.s
===================================================================
--- /trunk/minix/lib/i86/misc/io_outsw.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/io_outsw.s	(revision 9)
@@ -0,0 +1,19 @@
+!	outsw() - Output a word array		Author: Kees J. Bot
+!								18 Mar 1996
+!	void outsw(U16_t port, void *buf, size_t count);
+
+.sect .text
+.define _outsw
+_outsw:
+	push	bp
+	mov	bp, sp
+	cld
+	push	si
+	mov	dx, 4(bp)		! port
+	mov	si, 6(bp)		! buf
+	mov	cx, 8(bp)		! byte count
+	shr	cx, #1			! word count
+   rep	outs				! output many words
+	pop	si
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/misc/io_outw.s
===================================================================
--- /trunk/minix/lib/i86/misc/io_outw.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/io_outw.s	(revision 9)
@@ -0,0 +1,14 @@
+!	outw() - Output one word			Author: Kees J. Bot
+!								18 Mar 1996
+!	void outw(U16_t port, U16_t value);
+
+.sect .text
+.define _outw
+_outw:
+	push	bp
+	mov	bp, sp
+	mov	dx, 4(bp)		! port
+	mov	ax, 4+2(bp)		! value
+	out	dx			! output 1 word
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/misc/oneC_sum.s
===================================================================
--- /trunk/minix/lib/i86/misc/oneC_sum.s	(revision 9)
+++ /trunk/minix/lib/i86/misc/oneC_sum.s	(revision 9)
@@ -0,0 +1,68 @@
+!	oneC_sum() - One complement`s checksum		Author: Kees J. Bot
+!								23 May 1998
+! See RFC 1071, "Computing the Internet checksum"
+! See also the C version of this code.
+
+.text
+
+.define _oneC_sum
+	.align	4
+_oneC_sum:
+	push	bp
+	mov	bp, sp
+	push	si
+	push	di
+	mov	ax, 4(bp)		! Checksum of previous block
+	mov	si, 6(bp)		! Data to compute checksum over
+	mov	di, 8(bp)		! Number of bytes
+
+	xor	dx, dx
+	xorb	cl, cl
+align:	test	si, #1			! Is the data aligned?
+	jz	aligned
+	test	di, di
+	jz	0f
+	movb	dh, (si)		! First unaligned byte in high half of
+	dec	di			! the dx register, i.e. rotate 8 bits
+0:	inc	si
+	movb	cl, #8			! Number of bits "rotated"
+	ror	ax, cl			! Rotate the checksum likewise
+aligned:add	ax, dx			! Summate the unaligned byte
+	adc	ax, #0			! Add carry back in for one`s complement
+
+	jmp	add6test
+	.align	4
+add6:	add	ax, (si)		! Six times unrolled loop, see below
+	adc	ax, 2(si)
+	adc	ax, 4(si)
+	adc	ax, 6(si)
+	adc	ax, 8(si)
+	adc	ax, 10(si)
+	adc	ax, #0
+	add	si, #12
+add6test:
+	sub	di, #12
+	jae	add6
+	add	di, #12
+
+	jmp	add1test
+	.align	4
+add1:	add	ax, (si)		! while ((di -= 2) >= 0)
+	adc	ax, #0			!	ax += *si++;
+	add	si, #2			! di += 2;
+add1test:
+	sub	di, #2
+	jae	add1
+	add	di, #2
+
+	jz	done			! Is there an extra byte?
+	movb	dl, (si)		! Load extra byte in word
+	xorb	dh, dh
+	add	ax, dx			! Add in the last bits
+	adc	ax, #0
+done:
+	rol	ax, cl			! Undo the rotation at the beginning
+	pop	di
+	pop	si
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/rts/__sigreturn.s
===================================================================
--- /trunk/minix/lib/i86/rts/__sigreturn.s	(revision 9)
+++ /trunk/minix/lib/i86/rts/__sigreturn.s	(revision 9)
@@ -0,0 +1,10 @@
+! This routine is the low-level code for returning from signals.  
+! It calls __sigreturn, which is the normal "system call" routine.
+! Both ___sigreturn and __sigreturn are needed.
+.sect .text; .sect .rom; .sect .data; .sect .bss
+.sect .text
+.define ___sigreturn
+.extern __sigreturn
+___sigreturn:
+	add sp, #8
+	jmp __sigreturn
Index: /trunk/minix/lib/i86/rts/_sendrec.s
===================================================================
--- /trunk/minix/lib/i86/rts/_sendrec.s	(revision 9)
+++ /trunk/minix/lib/i86/rts/_sendrec.s	(revision 9)
@@ -0,0 +1,32 @@
+.define __send, __receive, __sendrec
+
+! See ../h/com.h for C definitions
+SEND = 1
+RECEIVE = 2
+BOTH = 3
+SYSVEC = 32
+
+!*========================================================================*
+!                           _send and _receive                            *
+!*========================================================================*
+! _send(), _receive(), _sendrec() all save bp, but destroy ax, bx, and cx.
+.extern __send, __receive, __sendrec
+__send:	mov cx,*SEND		! _send(dest, ptr)
+	jmp L0
+
+__receive:
+	mov cx,*RECEIVE		! _receive(src, ptr)
+	jmp L0
+
+__sendrec:
+	mov cx,*BOTH		! _sendrec(srcdest, ptr)
+	jmp L0
+
+  L0:	push bp			! save bp
+	mov bp,sp		! can't index off sp
+	mov ax,4(bp)		! ax = dest-src
+	mov bx,6(bp)		! bx = message pointer
+	int SYSVEC		! trap to the kernel
+	pop bp			! restore bp
+	ret			! return
+
Index: /trunk/minix/lib/i86/rts/brksize.s
===================================================================
--- /trunk/minix/lib/i86/rts/brksize.s	(revision 9)
+++ /trunk/minix/lib/i86/rts/brksize.s	(revision 9)
@@ -0,0 +1,4 @@
+.define __brksize
+.data
+.extern endbss, __brksize
+__brksize: .data2 endbss
Index: /trunk/minix/lib/i86/rts/ncrtso.s
===================================================================
--- /trunk/minix/lib/i86/rts/ncrtso.s	(revision 9)
+++ /trunk/minix/lib/i86/rts/ncrtso.s	(revision 9)
@@ -0,0 +1,54 @@
+! This is the C run-time start-off routine.  It's job is to take the
+! arguments as put on the stack by EXEC, and to parse them and set them up the
+! way _main expects them.
+! It also initializes _environ when this variable isn't defined by the
+! programmer.  The detection of whether _environ belong to us is rather
+! simplistic.  We simply check for some magic value, but there is no other
+! way.
+
+.extern _main, _exit, crtso, __penviron, __penvp
+.extern begtext, begdata, begbss, endtext, enddata, endbss
+.text
+begtext:
+crtso:
+	xor	bp, bp			! clear for backtrace of core files
+	mov	bx, sp
+	mov	ax, (bx)		! argc
+	lea	dx, 2(bx)		! argv
+	lea	cx, 4(bx)
+	add	cx, ax
+	add	cx, ax			! envp
+
+	! Test if environ is in the initialized data area and is set to our
+	! magic number.  If so then it is not redefined by the user.
+	mov	bx, #_environ
+	cmp	bx, #__edata		! within initialized data?
+	jae	0f
+	testb	bl, #1			! aligned?
+	jnz	0f
+	cmp	(bx), #0x5353		! is it our environ?
+	jne	0f
+	mov	__penviron, bx		! _penviron = &environ;
+0:	mov	bx, __penviron
+	mov	(bx), cx		! *_penviron = envp;
+
+	push	cx			! push envp
+	push	dx			! push argv
+	push	ax			! push argc
+
+	call	_main			! main(argc, argv, envp)
+
+	push	ax			! push exit status
+	call	_exit
+
+	hlt				! force a trap if exit fails
+
+.data
+begdata:
+	.data2	0			! for sep I&D: *NULL == 0
+__penviron:
+	.data2	__penvp			! Pointer to environ, or hidden pointer
+
+.bss
+begbss:
+	.comm	__penvp, 2		! Hidden environment vector
Index: /trunk/minix/lib/i86/rts/nm2rtso.s
===================================================================
--- /trunk/minix/lib/i86/rts/nm2rtso.s	(revision 9)
+++ /trunk/minix/lib/i86/rts/nm2rtso.s	(revision 9)
@@ -0,0 +1,50 @@
+! This is the Modula-2 run-time start-off routine.  It's job is to take the
+! arguments as put on the stack by EXEC, and to parse them and set them up the
+! way _m_a_i_n expects them.
+
+.extern __m_a_i_n, _exit, m2rtso, hol0, __penvp
+.extern begtext, begdata, begbss, endtext, enddata, endbss
+.text
+begtext:
+m2rtso:
+	xor	bp, bp			! clear for backtrace of core files
+	mov	bx, sp
+	mov	ax, (bx)		! argc
+	lea	dx, 2(bx)		! argv
+	lea	cx, 4(bx)
+	add	cx, ax
+	add	cx, ax			! envp
+
+	! Test if environ is in the initialized data area and is set to our
+	! magic number.  If so then it is not redefined by the user.
+	mov	bx, #_environ
+	cmp	bx, #__edata		! within initialized data?
+	jae	0f
+	testb	bl, #1			! aligned?
+	jnz	0f
+	cmp	(bx), #0x5353		! is it our environ?
+	jne	0f
+	mov	__penviron, bx		! _penviron = &environ;
+0:	mov	bx, __penviron
+	mov	(bx), cx		! *_penviron = envp;
+
+	push	cx			! push envp
+	push	dx			! push argv
+	push	ax			! push argc
+
+	call	__m_a_i_n		! run Modula-2 program
+
+	push	ax			! push exit status
+	call	__exit
+
+	hlt				! force a trap if exit fails
+
+.data
+begdata:
+	.data2	0			! for sep I&D: *NULL == 0
+__penviron:
+	.data2	__penvp			! Pointer to environ, or hidden pointer
+
+.bss
+begbss:
+	.comm	__penvp, 2		! Hidden environment vector
Index: /trunk/minix/lib/i86/rts/nprtso.s
===================================================================
--- /trunk/minix/lib/i86/rts/nprtso.s	(revision 9)
+++ /trunk/minix/lib/i86/rts/nprtso.s	(revision 9)
@@ -0,0 +1,52 @@
+! This is the Pascal run-time start-off routine.  It's job is to take the
+! arguments as put on the stack by EXEC, and to parse them and set them up the
+! way _m_a_i_n expects them.
+
+.extern __m_a_i_n, _exit, prtso, hol0, __penvp
+.extern begtext, begdata, begbss, endtext, enddata, endbss
+.text
+begtext:
+prtso:
+	xor	bp, bp			! clear for backtrace of core files
+	mov	bx, sp
+	mov	ax, (bx)		! argc
+	lea	dx, 2(bx)		! argv
+	lea	cx, 4(bx)
+	add	cx, ax
+	add	cx, ax			! envp
+
+	! Test if environ is in the initialized data area and is set to our
+	! magic number.  If so then it is not redefined by the user.
+	mov	bx, #_environ
+	cmp	bx, #__edata		! within initialized data?
+	jae	0f
+	testb	bl, #1			! aligned?
+	jnz	0f
+	cmp	(bx), #0x5353		! is it our environ?
+	jne	0f
+	mov	__penviron, bx		! _penviron = &environ;
+0:	mov	bx, __penviron
+	mov	(bx), cx		! *_penviron = envp;
+
+	push	cx			! push envp
+	push	dx			! push argv
+	push	ax			! push argc
+
+	mov	.ignmask, #56
+
+	call	__m_a_i_n		! run Pascal program
+
+	push	ax			! push exit status
+	call	__exit
+
+	hlt				! force a trap if exit fails
+
+.data
+begdata:
+	.data2	0			! for sep I&D: *NULL == 0
+__penviron:
+	.data2	__penvp			! Pointer to environ, or hidden pointer
+
+.bss
+begbss:
+	.comm	__penvp, 2		! Hidden environment vector
Index: /trunk/minix/lib/i86/string/README
===================================================================
--- /trunk/minix/lib/i86/string/README	(revision 9)
+++ /trunk/minix/lib/i86/string/README	(revision 9)
@@ -0,0 +1,5 @@
+Notes on i8086 string assembly routines.		Author: Kees J. Bot
+								27 Jan 1994
+
+These routines are simply translations of the 386 code, so all comments
+to that code apply here.
Index: /trunk/minix/lib/i86/string/_memmove.s
===================================================================
--- /trunk/minix/lib/i86/string/_memmove.s	(revision 9)
+++ /trunk/minix/lib/i86/string/_memmove.s	(revision 9)
@@ -0,0 +1,50 @@
+!	_memmove()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! void *_memmove(void *s1, const void *s2, size_t n)
+!	Copy a chunk of memory.  Handle overlap.
+!
+.sect .text
+.define __memmove, __memcpy
+__memmove:
+	push	bp
+	mov	bp, sp
+	push	si
+	push	di
+	mov	di, 4(bp)	! String s1
+	mov	si, 6(bp)	! String s2
+	mov	cx, 8(bp)	! Length
+	mov	ax, di
+	sub	ax, si
+	cmp	ax, cx
+	jb	downwards	! if (s2 - s1) < n then copy downwards
+__memcpy:
+	cld			! Clear direction bit: upwards
+	cmp	cx, #16
+	jb	upbyte		! Don't bother being smart with short arrays
+	mov	ax, si
+	or	ax, di
+	testb	al, #1
+	jnz	upbyte		! Bit 0 set, use byte copy
+upword:	shr	cx, #1
+    rep	movs			! Copy words
+	adc	cx, cx		! One more byte?
+upbyte:
+    rep	movsb			! Copy bytes
+done:	mov	ax, 4(bp)	! Absolutely noone cares about this value
+	pop	di
+	pop	si
+	pop	bp
+	ret
+
+! Handle bad overlap by copying downwards, don't bother to do word copies.
+downwards:
+	std			! Set direction bit: downwards
+	add	si, cx
+	dec	si
+	add	di, cx
+	dec	di
+    rep	movsb			! Copy bytes
+	cld
+	jmp	done
Index: /trunk/minix/lib/i86/string/_strncat.s
===================================================================
--- /trunk/minix/lib/i86/string/_strncat.s	(revision 9)
+++ /trunk/minix/lib/i86/string/_strncat.s	(revision 9)
@@ -0,0 +1,37 @@
+!	_strncat()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *_strncat(char *s1, const char *s2, size_t dx)
+!	Append string s2 to s1.
+!
+.sect .text
+.define __strncat
+__strncat:
+	push	bp
+	mov	bp, sp
+	push	si
+	push	di
+	mov	di, 4(bp)	! String s1
+	mov	cx, #-1
+	xorb	al, al		! Null byte
+	cld
+  repne	scasb			! Look for the zero byte in s1
+	dec	di		! Back one up (and clear 'Z' flag)
+	push	di		! Save end of s1
+	mov	di, 6(bp)	! di = string s2
+	mov	cx, dx		! Maximum count
+  repne	scasb			! Look for the end of s2
+	jne	no0
+	inc	cx		! Exclude null byte
+no0:	sub	dx, cx		! Number of bytes in s2
+	mov	cx, dx
+	mov	si, 6(bp)	! si = string s2
+	pop	di		! di = end of string s1
+    rep	movsb			! Copy bytes
+	stosb			! Add a terminating null
+	mov	ax, 4(bp)	! Return s1
+	pop	di
+	pop	si
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/string/_strncmp.s
===================================================================
--- /trunk/minix/lib/i86/string/_strncmp.s	(revision 9)
+++ /trunk/minix/lib/i86/string/_strncmp.s	(revision 9)
@@ -0,0 +1,36 @@
+!	strncmp()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! int strncmp(const char *s1, const char *s2, size_t cx)
+!	Compare two strings.
+!
+.sect .text
+.define __strncmp
+__strncmp:
+	push	bp
+	mov	bp, sp
+	push	si
+	push	di
+	xor	ax, ax		! Prepare return value
+	test	cx, cx		! Max length is zero?
+	je	equal
+	mov	si, 4(bp)	! si = string s1
+	mov	di, 6(bp)	! di = string s2
+	cld
+compare:
+	cmpsb			! Compare two bytes
+	jne	unequal
+	cmpb	-1(si), #0	! End of string?
+	je	equal
+	dec	cx		! Length limit reached?
+	jne	compare
+	jmp	equal
+unequal:
+	ja	after
+	sub	ax, #2		! if (s1 < s2) ax -= 2;
+after:	inc	ax		! ax++, now it's -1 or 1
+equal:	pop	di
+	pop	si
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/string/_strncpy.s
===================================================================
--- /trunk/minix/lib/i86/string/_strncpy.s	(revision 9)
+++ /trunk/minix/lib/i86/string/_strncpy.s	(revision 9)
@@ -0,0 +1,21 @@
+!	_strncpy()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *_strncpy(char *s1, const char *s2, size_t cx)
+!	Copy string s2 to s1.
+!
+.sect .text
+.define __strncpy
+__strncpy:
+	mov	di, 6(bp)	! di = string s2
+	xorb	al, al		! Look for a zero byte
+	mov	dx, cx		! Save maximum count
+	cld
+  repne	scasb			! Look for end of s2
+	sub	dx, cx		! Number of bytes in s2 including null
+	xchg	cx, dx
+	mov	si, 6(bp)	! si = string s2
+	mov	di, 4(bp)	! di = string s1
+    rep	movsb			! Copy bytes
+	ret
Index: /trunk/minix/lib/i86/string/_strnlen.s
===================================================================
--- /trunk/minix/lib/i86/string/_strnlen.s	(revision 9)
+++ /trunk/minix/lib/i86/string/_strnlen.s	(revision 9)
@@ -0,0 +1,26 @@
+!	_strnlen()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! size_t _strnlen(const char *s, size_t cx)
+!	Return the length of a string.
+!
+.sect .text
+.define __strnlen
+__strnlen:
+	push	bp
+	mov	bp, sp
+	push	di
+	mov	di, 4(bp)	! di = string
+	xorb	al, al		! Look for a zero byte
+	mov	dx, cx		! Save maximum count
+	cmpb	cl, #1		! 'Z' bit must be clear if cx = 0
+	cld
+  repne	scasb			! Look for zero
+	jne	no0
+	inc	cx		! Don't count zero byte
+no0:	mov	ax, dx
+	sub	ax, cx		! Compute bytes scanned
+	pop	di
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/string/bcmp.s
===================================================================
--- /trunk/minix/lib/i86/string/bcmp.s	(revision 9)
+++ /trunk/minix/lib/i86/string/bcmp.s	(revision 9)
@@ -0,0 +1,28 @@
+!	bcmp()						Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! int bcmp(const void *s1, const void *s2, size_t n)
+!	Compare two chunks of memory.
+!	This is a BSD routine that escaped from the kernel.  Don't use.
+!	(Alas it is not without some use, it reports the number of bytes
+!	after the bytes that are equal.  So it can't be simply replaced.)
+!
+.sect .text
+.define _bcmp
+_bcmp:
+	push	bp
+	mov	bp, sp
+	push	8(bp)
+	push	6(bp)
+	push	4(bp)
+	call	_memcmp		! Let memcmp do the work
+	mov	sp, bp
+	test	ax, ax
+	jz	equal
+	sub	dx, 4(bp)	! Memcmp was nice enough to leave "si" in dx
+	dec	dx		! Number of bytes that are equal
+	mov	ax, 8(bp)
+	sub	ax, dx		! Number of bytes that are unequal
+equal:	pop	bp
+	ret
Index: /trunk/minix/lib/i86/string/bcopy.s
===================================================================
--- /trunk/minix/lib/i86/string/bcopy.s	(revision 9)
+++ /trunk/minix/lib/i86/string/bcopy.s	(revision 9)
@@ -0,0 +1,19 @@
+!	bcopy()						Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! void bcopy(const void *s1, void *s2, size_t n)
+!	Copy a chunk of memory.  Handle overlap.
+!	This is a BSD routine that escaped from the kernel.  Don't use.
+!
+.sect .text
+.define _bcopy
+.extern __memmove
+_bcopy:
+	pop	cx
+	pop	ax
+	pop	dx		! Pop return address and arguments
+	push	ax
+	push	dx		! Arguments reversed
+	push	cx
+	jmp	__memmove	! Call the proper routine
Index: /trunk/minix/lib/i86/string/bzero.s
===================================================================
--- /trunk/minix/lib/i86/string/bzero.s	(revision 9)
+++ /trunk/minix/lib/i86/string/bzero.s	(revision 9)
@@ -0,0 +1,21 @@
+!	bzero()						Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! void bzero(void *s, size_t n)
+!	Set a chunk of memory to zero.
+!	This is a BSD routine that escaped from the kernel.  Don't use.
+!
+.sect .text
+.define _bzero
+_bzero:
+	push	bp
+	mov	bp, sp
+	push	6(bp)		! Size
+	xor	ax, ax
+	push	ax		! Zero
+	push	4(bp)		! String
+	call	_memset		! Call the proper routine
+	mov	sp, bp
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/string/index.s
===================================================================
--- /trunk/minix/lib/i86/string/index.s	(revision 9)
+++ /trunk/minix/lib/i86/string/index.s	(revision 9)
@@ -0,0 +1,12 @@
+!	index()						Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *index(const char *s, int c)
+!	Look for a character in a string.  Has suffered from a hostile
+!	takeover by strchr().
+!
+.sect .text
+.define _index
+_index:
+	jmp	_strchr
Index: /trunk/minix/lib/i86/string/memchr.s
===================================================================
--- /trunk/minix/lib/i86/string/memchr.s	(revision 9)
+++ /trunk/minix/lib/i86/string/memchr.s	(revision 9)
@@ -0,0 +1,28 @@
+!	memchr()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! void *memchr(const void *s, int c, size_t n)
+!	Look for a character in a chunk of memory.
+!
+.sect .text
+.define _memchr
+_memchr:
+	push	bp
+	mov	bp, sp
+	push	di
+	mov	di, 4(bp)	! di = string
+	movb	al, 6(bp)	! The character to look for
+	mov	cx, 8(bp)	! Length
+	cmpb	cl, #1		! 'Z' bit must be clear if cx = 0
+	cld
+  repne	scasb
+	jne	failure
+	lea	ax, -1(di)	! Found
+	pop	di
+	pop	bp
+	ret
+failure:xor	ax, ax
+	pop	di
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/string/memcmp.s
===================================================================
--- /trunk/minix/lib/i86/string/memcmp.s	(revision 9)
+++ /trunk/minix/lib/i86/string/memcmp.s	(revision 9)
@@ -0,0 +1,44 @@
+!	memcmp()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! int memcmp(const void *s1, const void *s2, size_t n)
+!	Compare two chunks of memory.
+!
+.sect .text
+.define _memcmp
+_memcmp:
+	cld
+	push	bp
+	mov	bp, sp
+	push	si
+	push	di
+	xor	ax, ax		! Prepare return value
+	mov	si, 4(bp)	! String s1
+	mov	di, 6(bp)	! String s2
+	mov	cx, 8(bp)	! Length
+	cmp	cx, #16
+	jb	cbyte		! Don't bother being smart with short arrays
+	mov	dx, si
+	or	dx, di
+	andb	dl, #1
+	jnz	cbyte		! Bit 0 set, use byte compare
+cword:	sar	cx, #1
+	adcb	dl, dl		! Save carry
+   repe	cmps			! Compare words
+	mov	cx, #2		! Recompare the last word
+	sub	si, cx
+	sub	di, cx
+	addb	cl, dl		! One more byte?
+cbyte:	test	cx, cx		! Set 'Z' flag if cx = 0
+last:
+   repe	cmpsb			! Look for the first differing byte
+	je	equal
+	ja	after
+	sub	ax, #2		! if (s1 < s2) ax -= 2;
+after:	inc	ax		! ax++, now it's -1 or 1
+equal:	mov	dx, si		! For bcmp() to play with
+	pop	di
+	pop	si
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/string/memcpy.s
===================================================================
--- /trunk/minix/lib/i86/string/memcpy.s	(revision 9)
+++ /trunk/minix/lib/i86/string/memcpy.s	(revision 9)
@@ -0,0 +1,23 @@
+!	memcpy()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! void *memcpy(void *s1, const void *s2, size_t n)
+!	Copy a chunk of memory.
+!	This routine need not handle overlap, so it does not handle overlap.
+!	One could simply call __memmove, the cost of the overlap check is
+!	negligible, but you are dealing with a programmer who believes that
+!	if anything can go wrong, it should go wrong.
+!
+.sect .text
+.define _memcpy
+_memcpy:
+	push	bp
+	mov	bp, sp
+	push	si
+	push	di
+	mov	di, 4(bp)	! String s1
+	mov	si, 6(bp)	! String s2
+	mov	cx, 8(bp)	! Length
+	! No overlap check here
+	jmp	__memcpy	! Call the part of __memmove that copies up
Index: /trunk/minix/lib/i86/string/memmove.s
===================================================================
--- /trunk/minix/lib/i86/string/memmove.s	(revision 9)
+++ /trunk/minix/lib/i86/string/memmove.s	(revision 9)
@@ -0,0 +1,11 @@
+!	memmove()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! void *memmove(void *s1, const void *s2, size_t n)
+!	Copy a chunk of memory.  Handle overlap.
+!
+.sect .text
+.define _memmove
+_memmove:
+	jmp	__memmove	! Call common code
Index: /trunk/minix/lib/i86/string/memset.s
===================================================================
--- /trunk/minix/lib/i86/string/memset.s	(revision 9)
+++ /trunk/minix/lib/i86/string/memset.s	(revision 9)
@@ -0,0 +1,31 @@
+!	memset()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! void *memset(void *s, int c, size_t n)
+!	Set a chunk of memory to the same byte value.
+!
+.sect .text
+.define _memset
+_memset:
+	push	bp
+	mov	bp, sp
+	push	di
+	mov	di, 4(bp)	! The string
+	movb	al, 6(bp)	! The fill byte
+	mov	cx, 8(bp)	! Length
+	cld
+	cmp	cx, #16
+	jb	sbyte		! Don't bother being smart with short arrays
+	test	di, #1
+	jnz	sbyte		! Bit 0 set, use byte store
+sword:	movb	ah, al		! One byte to two bytes
+	sar	cx, #1
+    rep	stos			! Store words
+    	adc	cx, cx		! One more byte?
+sbyte:
+    rep	stosb			! Store bytes
+done:	mov	ax, 4(bp)	! Return some value you have no need for
+	pop	di
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/string/rindex.s
===================================================================
--- /trunk/minix/lib/i86/string/rindex.s	(revision 9)
+++ /trunk/minix/lib/i86/string/rindex.s	(revision 9)
@@ -0,0 +1,12 @@
+!	rindex()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *rindex(const char *s, int c)
+!	Look for the last occurrence a character in a string.  Has suffered
+!	from a hostile takeover by strrchr().
+!
+.sect .text
+.define _rindex
+_rindex:
+	jmp	_strrchr
Index: /trunk/minix/lib/i86/string/strcat.s
===================================================================
--- /trunk/minix/lib/i86/string/strcat.s	(revision 9)
+++ /trunk/minix/lib/i86/string/strcat.s	(revision 9)
@@ -0,0 +1,12 @@
+!	strcat()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *strcat(char *s1, const char *s2)
+!	Append string s2 to s1.
+!
+.sect .text
+.define _strcat
+_strcat:
+	mov	dx, #-1		! Unlimited length
+	jmp	__strncat	! Common code
Index: /trunk/minix/lib/i86/string/strchr.s
===================================================================
--- /trunk/minix/lib/i86/string/strchr.s	(revision 9)
+++ /trunk/minix/lib/i86/string/strchr.s	(revision 9)
@@ -0,0 +1,38 @@
+!	strchr()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *strchr(const char *s, int c)
+!	Look for a character in a string.
+!
+.sect .text
+.define _strchr
+_strchr:
+	push	bp
+	mov	bp, sp
+	push	di
+	cld
+	mov	di, 4(bp)	! di = string
+	mov	dx, #16		! Look at small chunks of the string
+next:	shl	dx, #1		! Chunks become bigger each time
+	mov	cx, dx
+	xorb	al, al		! Look for the zero at the end
+  repne	scasb
+	pushf			! Remember the flags
+	sub	cx, dx
+	neg	cx		! Some or all of the chunk
+	sub	di, cx		! Step back
+	movb	al, 6(bp)	! The character to look for
+  repne	scasb
+	je	found
+	popf			! Did we find the end of string earlier?
+	jne	next		! No, try again
+	xor	ax, ax		! Return NULL
+	pop	di
+	pop	bp
+	ret
+found:	pop	ax		! Get rid of those flags
+	lea	ax, -1(di)	! Address of byte found
+	pop	di
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/string/strcmp.s
===================================================================
--- /trunk/minix/lib/i86/string/strcmp.s	(revision 9)
+++ /trunk/minix/lib/i86/string/strcmp.s	(revision 9)
@@ -0,0 +1,12 @@
+!	strcmp()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! int strcmp(const char *s1, const char *s2)
+!	Compare two strings.
+!
+.sect .text
+.define _strcmp
+_strcmp:
+	mov	cx, #-1		! Unlimited length
+	jmp	__strncmp	! Common code
Index: /trunk/minix/lib/i86/string/strcpy.s
===================================================================
--- /trunk/minix/lib/i86/string/strcpy.s	(revision 9)
+++ /trunk/minix/lib/i86/string/strcpy.s	(revision 9)
@@ -0,0 +1,21 @@
+!	strcpy()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *strcpy(char *s1, const char *s2)
+!	Copy string s2 to s1.
+!
+.sect .text
+.define _strcpy
+_strcpy:
+	push	bp
+	mov	bp, sp
+	push	si
+	push	di
+	mov	cx, #-1		! Unlimited length
+	call	__strncpy	! Common code
+	mov	ax, 4(bp)	! Return s1
+	pop	di
+	pop	si
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/string/strlen.s
===================================================================
--- /trunk/minix/lib/i86/string/strlen.s	(revision 9)
+++ /trunk/minix/lib/i86/string/strlen.s	(revision 9)
@@ -0,0 +1,12 @@
+!	strlen()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! size_t strlen(const char *s)
+!	Return the length of a string.
+!
+.sect .text
+.define _strlen
+_strlen:
+	mov	cx, #-1		! Unlimited length
+	jmp	__strnlen	! Common code
Index: /trunk/minix/lib/i86/string/strncat.s
===================================================================
--- /trunk/minix/lib/i86/string/strncat.s	(revision 9)
+++ /trunk/minix/lib/i86/string/strncat.s	(revision 9)
@@ -0,0 +1,13 @@
+!	strncat()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! size_t strncat(char *s1, const char *s2, size_t n)
+!	Append string s2 to s1.
+!
+.sect .text
+.define _strncat
+_strncat:
+	mov	bx, sp
+	mov	dx, 6(bx)	! Maximum length
+	jmp	__strncat	! Common code
Index: /trunk/minix/lib/i86/string/strncmp.s
===================================================================
--- /trunk/minix/lib/i86/string/strncmp.s	(revision 9)
+++ /trunk/minix/lib/i86/string/strncmp.s	(revision 9)
@@ -0,0 +1,13 @@
+!	strncmp()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! int strncmp(const char *s1, const char *s2, size_t n)
+!	Compare two strings.
+!
+.sect .text
+.define _strncmp
+_strncmp:
+	mov	bx, sp
+	mov	cx, 6(bx)	! Maximum length
+	jmp	__strncmp	! Common code
Index: /trunk/minix/lib/i86/string/strncpy.s
===================================================================
--- /trunk/minix/lib/i86/string/strncpy.s	(revision 9)
+++ /trunk/minix/lib/i86/string/strncpy.s	(revision 9)
@@ -0,0 +1,23 @@
+!	strncpy()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *strncpy(char *s1, const char *s2, size_t n)
+!	Copy string s2 to s1.
+!
+.sect .text
+.define _strncpy
+_strncpy:
+	push	bp
+	mov	bp, sp
+	push	si
+	push	di
+	mov	cx, 8(bp)	! Maximum length
+	call	__strncpy	! Common code
+	mov	cx, dx		! Number of bytes not copied
+    rep	stosb			! strncpy always copies n bytes by null padding
+	mov	ax, 4(bp)	! Return s1
+	pop	di
+	pop	si
+	pop	bp
+	ret
Index: /trunk/minix/lib/i86/string/strnlen.s
===================================================================
--- /trunk/minix/lib/i86/string/strnlen.s	(revision 9)
+++ /trunk/minix/lib/i86/string/strnlen.s	(revision 9)
@@ -0,0 +1,13 @@
+!	strnlen()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! size_t strnlen(const char *s, size_t n)
+!	Return the length of a string.
+!
+.sect .text
+.define _strnlen
+_strnlen:
+	mov	bx, sp
+	mov	cx, 4(bx)	! Maximum length
+	jmp	__strnlen	! Common code
Index: /trunk/minix/lib/i86/string/strrchr.s
===================================================================
--- /trunk/minix/lib/i86/string/strrchr.s	(revision 9)
+++ /trunk/minix/lib/i86/string/strrchr.s	(revision 9)
@@ -0,0 +1,33 @@
+!	strrchr()					Author: Kees J. Bot
+!								27 Jan 1994
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+! char *strrchr(const char *s, int c)
+!	Look for the last occurrence a character in a string.
+!
+.sect .text
+.define _strrchr
+_strrchr:
+	push	bp
+	mov	bp, sp
+	push	di
+	mov	di, 4(bp)	! di = string
+	mov	cx, #-1
+	xorb	al, al
+	cld
+  repne	scasb			! Look for the end of the string
+	not	cx		! -1 - cx = Length of the string + null
+	dec	di		! Put di back on the zero byte
+	movb	al, 6(bp)	! The character to look for
+	std			! Downwards search
+  repne	scasb
+	cld			! Direction bit back to default
+	jne	failure
+	lea	ax, 1(di)	! Found it
+	pop	di
+	pop	bp
+	ret
+failure:xor	ax, ax		! Not there
+	pop	di
+	pop	bp
+	ret
Index: /trunk/minix/lib/ip/Makedepend-ack
===================================================================
--- /trunk/minix/lib/ip/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/ip/Makedepend-ack	(revision 9)
@@ -0,0 +1,55 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' accept.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' bind.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' connect.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' dhcp_gettag.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' dhcp_settag.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' domainname.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' ether_line.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' ethera2n.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' ethere2a.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' etherh2n.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' ethern2h.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getdomain.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' gethnmadr.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' gethostent.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' gethostname.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getifaddrs.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getnetbyaddr.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getnetbyname.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getnetent.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getpeername.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getproto.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getprotoent.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getprotoname.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getservent.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getsockname.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getsockopt.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getsrvbyname.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getsrvbyport.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' hton.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' inet_addr.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' inet_network.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' inet_ntoa.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' listen.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' memcspn.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' oneC_sum.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' rcmd.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' recv.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' recvfrom.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' res_comp.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' res_init.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' res_mkquery.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' res_query.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' res_send.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' ruserok.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' send.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' sendto.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' servxcheck.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' sethostent.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' setsockopt.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' shutdown.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' socket.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' strcasecmp.c | sed -e 's:^\(.\):../obj-ack//./ip/\1:' >> .depend-ack
Index: /trunk/minix/lib/ip/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/ip/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/ip/Makedepend-gnu	(revision 9)
@@ -0,0 +1,55 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' accept.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' bind.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' connect.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' dhcp_gettag.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' dhcp_settag.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' domainname.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' ether_line.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' ethera2n.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' ethere2a.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' etherh2n.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' ethern2h.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getdomain.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' gethnmadr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' gethostent.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' gethostname.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getifaddrs.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getnetbyaddr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getnetbyname.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getnetent.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getpeername.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getproto.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getprotoent.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getprotoname.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getservent.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getsockname.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getsockopt.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getsrvbyname.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' getsrvbyport.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' hton.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' inet_addr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' inet_network.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' inet_ntoa.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' listen.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' memcspn.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' oneC_sum.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' rcmd.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' recv.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' recvfrom.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' res_comp.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' res_init.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' res_mkquery.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' res_query.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' res_send.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' ruserok.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' send.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' sendto.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' servxcheck.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' sethostent.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' setsockopt.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' shutdown.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' socket.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -E' strcasecmp.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./ip/\1:' >> .depend-gnu
Index: /trunk/minix/lib/ip/Makefile
===================================================================
--- /trunk/minix/lib/ip/Makefile	(revision 9)
+++ /trunk/minix/lib/ip/Makefile	(revision 9)
@@ -0,0 +1,409 @@
+#Generated from ./ip/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./ip ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./ip ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libc.a
+
+../obj-ack//libc.a: ../obj-ack//libc.a(accept.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(bind.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(connect.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(dhcp_gettag.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(dhcp_settag.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(domainname.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ether_line.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ethera2n.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ethere2a.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(etherh2n.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ethern2h.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getdomain.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(gethnmadr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(gethostent.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(gethostname.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getifaddrs.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getnetbyaddr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getnetbyname.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getnetent.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getpeername.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getproto.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getprotoent.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getprotoname.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getservent.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getsockname.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getsockopt.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getsrvbyname.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getsrvbyport.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(hton.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(inet_addr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(inet_network.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(inet_ntoa.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(listen.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(memcspn.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(oneC_sum.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(rcmd.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(recv.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(recvfrom.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(res_comp.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(res_init.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(res_mkquery.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(res_query.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(res_send.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ruserok.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(send.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sendto.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(servxcheck.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sethostent.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(setsockopt.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(shutdown.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(socket.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(strcasecmp.o)
+
+../obj-ack//libc.a:
+	ar cr ../obj-ack//libc.a ../obj-ack//./ip/*.o
+	rm ../obj-ack//./ip/*.o
+
+../obj-ack//libc.a(accept.o): accept.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/accept.o accept.c
+../obj-ack//libc.a(bind.o): bind.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/bind.o bind.c
+../obj-ack//libc.a(connect.o): connect.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/connect.o connect.c
+../obj-ack//libc.a(dhcp_gettag.o): dhcp_gettag.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/dhcp_gettag.o dhcp_gettag.c
+../obj-ack//libc.a(dhcp_settag.o): dhcp_settag.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/dhcp_settag.o dhcp_settag.c
+../obj-ack//libc.a(domainname.o): domainname.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/domainname.o domainname.c
+../obj-ack//libc.a(ether_line.o): ether_line.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/ether_line.o ether_line.c
+../obj-ack//libc.a(ethera2n.o): ethera2n.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/ethera2n.o ethera2n.c
+../obj-ack//libc.a(ethere2a.o): ethere2a.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/ethere2a.o ethere2a.c
+../obj-ack//libc.a(etherh2n.o): etherh2n.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/etherh2n.o etherh2n.c
+../obj-ack//libc.a(ethern2h.o): ethern2h.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/ethern2h.o ethern2h.c
+../obj-ack//libc.a(getdomain.o): getdomain.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/getdomain.o getdomain.c
+../obj-ack//libc.a(gethnmadr.o): gethnmadr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/gethnmadr.o gethnmadr.c
+../obj-ack//libc.a(gethostent.o): gethostent.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/gethostent.o gethostent.c
+../obj-ack//libc.a(gethostname.o): gethostname.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/gethostname.o gethostname.c
+../obj-ack//libc.a(getifaddrs.o): getifaddrs.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/getifaddrs.o getifaddrs.c
+../obj-ack//libc.a(getnetbyaddr.o): getnetbyaddr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/getnetbyaddr.o getnetbyaddr.c
+../obj-ack//libc.a(getnetbyname.o): getnetbyname.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/getnetbyname.o getnetbyname.c
+../obj-ack//libc.a(getnetent.o): getnetent.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/getnetent.o getnetent.c
+../obj-ack//libc.a(getpeername.o): getpeername.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/getpeername.o getpeername.c
+../obj-ack//libc.a(getproto.o): getproto.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/getproto.o getproto.c
+../obj-ack//libc.a(getprotoent.o): getprotoent.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/getprotoent.o getprotoent.c
+../obj-ack//libc.a(getprotoname.o): getprotoname.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/getprotoname.o getprotoname.c
+../obj-ack//libc.a(getservent.o): getservent.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/getservent.o getservent.c
+../obj-ack//libc.a(getsockname.o): getsockname.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/getsockname.o getsockname.c
+../obj-ack//libc.a(getsockopt.o): getsockopt.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/getsockopt.o getsockopt.c
+../obj-ack//libc.a(getsrvbyname.o): getsrvbyname.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/getsrvbyname.o getsrvbyname.c
+../obj-ack//libc.a(getsrvbyport.o): getsrvbyport.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/getsrvbyport.o getsrvbyport.c
+../obj-ack//libc.a(hton.o): hton.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/hton.o hton.c
+../obj-ack//libc.a(inet_addr.o): inet_addr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/inet_addr.o inet_addr.c
+../obj-ack//libc.a(inet_network.o): inet_network.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/inet_network.o inet_network.c
+../obj-ack//libc.a(inet_ntoa.o): inet_ntoa.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/inet_ntoa.o inet_ntoa.c
+../obj-ack//libc.a(listen.o): listen.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/listen.o listen.c
+../obj-ack//libc.a(memcspn.o): memcspn.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/memcspn.o memcspn.c
+../obj-ack//libc.a(oneC_sum.o): oneC_sum.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/oneC_sum.o oneC_sum.c
+../obj-ack//libc.a(rcmd.o): rcmd.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/rcmd.o rcmd.c
+../obj-ack//libc.a(recv.o): recv.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/recv.o recv.c
+../obj-ack//libc.a(recvfrom.o): recvfrom.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/recvfrom.o recvfrom.c
+../obj-ack//libc.a(res_comp.o): res_comp.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/res_comp.o res_comp.c
+../obj-ack//libc.a(res_init.o): res_init.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/res_init.o res_init.c
+../obj-ack//libc.a(res_mkquery.o): res_mkquery.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/res_mkquery.o res_mkquery.c
+../obj-ack//libc.a(res_query.o): res_query.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/res_query.o res_query.c
+../obj-ack//libc.a(res_send.o): res_send.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/res_send.o res_send.c
+../obj-ack//libc.a(ruserok.o): ruserok.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/ruserok.o ruserok.c
+../obj-ack//libc.a(send.o): send.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/send.o send.c
+../obj-ack//libc.a(sendto.o): sendto.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/sendto.o sendto.c
+../obj-ack//libc.a(servxcheck.o): servxcheck.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/servxcheck.o servxcheck.c
+../obj-ack//libc.a(sethostent.o): sethostent.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/sethostent.o sethostent.c
+../obj-ack//libc.a(setsockopt.o): setsockopt.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/setsockopt.o setsockopt.c
+../obj-ack//libc.a(shutdown.o): shutdown.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/shutdown.o shutdown.c
+../obj-ack//libc.a(socket.o): socket.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/socket.o socket.c
+../obj-ack//libc.a(strcasecmp.o): strcasecmp.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-ack//./ip/strcasecmp.o strcasecmp.c
+
+all-gnu: ../obj-gnu/libc.a
+
+../obj-gnu/libc.a: ../obj-gnu/./ip/accept.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/bind.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/connect.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/dhcp_gettag.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/dhcp_settag.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/domainname.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/ether_line.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/ethera2n.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/ethere2a.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/etherh2n.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/ethern2h.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/getdomain.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/gethnmadr.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/gethostent.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/gethostname.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/getifaddrs.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/getnetbyaddr.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/getnetbyname.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/getnetent.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/getpeername.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/getproto.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/getprotoent.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/getprotoname.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/getservent.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/getsockname.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/getsockopt.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/getsrvbyname.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/getsrvbyport.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/hton.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/inet_addr.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/inet_network.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/inet_ntoa.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/listen.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/memcspn.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/oneC_sum.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/rcmd.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/recv.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/recvfrom.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/res_comp.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/res_init.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/res_mkquery.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/res_query.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/res_send.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/ruserok.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/send.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/sendto.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/servxcheck.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/sethostent.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/setsockopt.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/shutdown.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/socket.o
+../obj-gnu/libc.a: ../obj-gnu/./ip/strcasecmp.o
+
+../obj-gnu/libc.a:
+	gar cr ../obj-gnu/libc.a $?
+
+../obj-gnu/./ip/accept.o: accept.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/accept.o accept.c
+
+../obj-gnu/./ip/bind.o: bind.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/bind.o bind.c
+
+../obj-gnu/./ip/connect.o: connect.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/connect.o connect.c
+
+../obj-gnu/./ip/dhcp_gettag.o: dhcp_gettag.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/dhcp_gettag.o dhcp_gettag.c
+
+../obj-gnu/./ip/dhcp_settag.o: dhcp_settag.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/dhcp_settag.o dhcp_settag.c
+
+../obj-gnu/./ip/domainname.o: domainname.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/domainname.o domainname.c
+
+../obj-gnu/./ip/ether_line.o: ether_line.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/ether_line.o ether_line.c
+
+../obj-gnu/./ip/ethera2n.o: ethera2n.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/ethera2n.o ethera2n.c
+
+../obj-gnu/./ip/ethere2a.o: ethere2a.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/ethere2a.o ethere2a.c
+
+../obj-gnu/./ip/etherh2n.o: etherh2n.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/etherh2n.o etherh2n.c
+
+../obj-gnu/./ip/ethern2h.o: ethern2h.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/ethern2h.o ethern2h.c
+
+../obj-gnu/./ip/getdomain.o: getdomain.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/getdomain.o getdomain.c
+
+../obj-gnu/./ip/gethnmadr.o: gethnmadr.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/gethnmadr.o gethnmadr.c
+
+../obj-gnu/./ip/gethostent.o: gethostent.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/gethostent.o gethostent.c
+
+../obj-gnu/./ip/gethostname.o: gethostname.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/gethostname.o gethostname.c
+
+../obj-gnu/./ip/getifaddrs.o: getifaddrs.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/getifaddrs.o getifaddrs.c
+
+../obj-gnu/./ip/getnetbyaddr.o: getnetbyaddr.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/getnetbyaddr.o getnetbyaddr.c
+
+../obj-gnu/./ip/getnetbyname.o: getnetbyname.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/getnetbyname.o getnetbyname.c
+
+../obj-gnu/./ip/getnetent.o: getnetent.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/getnetent.o getnetent.c
+
+../obj-gnu/./ip/getpeername.o: getpeername.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/getpeername.o getpeername.c
+
+../obj-gnu/./ip/getproto.o: getproto.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/getproto.o getproto.c
+
+../obj-gnu/./ip/getprotoent.o: getprotoent.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/getprotoent.o getprotoent.c
+
+../obj-gnu/./ip/getprotoname.o: getprotoname.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/getprotoname.o getprotoname.c
+
+../obj-gnu/./ip/getservent.o: getservent.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/getservent.o getservent.c
+
+../obj-gnu/./ip/getsockname.o: getsockname.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/getsockname.o getsockname.c
+
+../obj-gnu/./ip/getsockopt.o: getsockopt.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/getsockopt.o getsockopt.c
+
+../obj-gnu/./ip/getsrvbyname.o: getsrvbyname.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/getsrvbyname.o getsrvbyname.c
+
+../obj-gnu/./ip/getsrvbyport.o: getsrvbyport.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/getsrvbyport.o getsrvbyport.c
+
+../obj-gnu/./ip/hton.o: hton.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/hton.o hton.c
+
+../obj-gnu/./ip/inet_addr.o: inet_addr.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/inet_addr.o inet_addr.c
+
+../obj-gnu/./ip/inet_network.o: inet_network.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/inet_network.o inet_network.c
+
+../obj-gnu/./ip/inet_ntoa.o: inet_ntoa.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/inet_ntoa.o inet_ntoa.c
+
+../obj-gnu/./ip/listen.o: listen.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/listen.o listen.c
+
+../obj-gnu/./ip/memcspn.o: memcspn.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/memcspn.o memcspn.c
+
+../obj-gnu/./ip/oneC_sum.o: oneC_sum.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/oneC_sum.o oneC_sum.c
+
+../obj-gnu/./ip/rcmd.o: rcmd.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/rcmd.o rcmd.c
+
+../obj-gnu/./ip/recv.o: recv.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/recv.o recv.c
+
+../obj-gnu/./ip/recvfrom.o: recvfrom.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/recvfrom.o recvfrom.c
+
+../obj-gnu/./ip/res_comp.o: res_comp.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/res_comp.o res_comp.c
+
+../obj-gnu/./ip/res_init.o: res_init.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/res_init.o res_init.c
+
+../obj-gnu/./ip/res_mkquery.o: res_mkquery.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/res_mkquery.o res_mkquery.c
+
+../obj-gnu/./ip/res_query.o: res_query.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/res_query.o res_query.c
+
+../obj-gnu/./ip/res_send.o: res_send.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/res_send.o res_send.c
+
+../obj-gnu/./ip/ruserok.o: ruserok.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/ruserok.o ruserok.c
+
+../obj-gnu/./ip/send.o: send.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/send.o send.c
+
+../obj-gnu/./ip/sendto.o: sendto.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/sendto.o sendto.c
+
+../obj-gnu/./ip/servxcheck.o: servxcheck.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/servxcheck.o servxcheck.c
+
+../obj-gnu/./ip/sethostent.o: sethostent.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/sethostent.o sethostent.c
+
+../obj-gnu/./ip/setsockopt.o: setsockopt.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/setsockopt.o setsockopt.c
+
+../obj-gnu/./ip/shutdown.o: shutdown.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/shutdown.o shutdown.c
+
+../obj-gnu/./ip/socket.o: socket.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/socket.o socket.c
+
+../obj-gnu/./ip/strcasecmp.o: strcasecmp.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG -c -o ../obj-gnu/./ip/strcasecmp.o strcasecmp.c
+
+
+
+
+clean::
+	rm -f ../obj-ack//./ip/*
+	rm -f ../obj-gnu/./ip/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/ip/Makefile.in
===================================================================
--- /trunk/minix/lib/ip/Makefile.in	(revision 9)
+++ /trunk/minix/lib/ip/Makefile.in	(revision 9)
@@ -0,0 +1,63 @@
+# Makefile for lib/ip.
+#
+# Note: The oneC_sum.c file is not used if there is an assembly equivalent.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG"
+
+LIBRARIES=libc
+
+libc_FILES=" \
+	accept.c \
+	bind.c \
+	connect.c \
+	dhcp_gettag.c \
+	dhcp_settag.c \
+	domainname.c \
+	ether_line.c \
+	ethera2n.c \
+	ethere2a.c \
+	etherh2n.c \
+	ethern2h.c \
+	getdomain.c \
+	gethnmadr.c \
+	gethostent.c \
+	gethostname.c \
+	getifaddrs.c \
+	getnetbyaddr.c \
+	getnetbyname.c \
+	getnetent.c \
+	getpeername.c \
+	getproto.c \
+	getprotoent.c \
+	getprotoname.c \
+	getservent.c \
+	getsockname.c \
+	getsockopt.c \
+	getsrvbyname.c \
+	getsrvbyport.c \
+	hton.c \
+	inet_addr.c \
+	inet_network.c \
+	inet_ntoa.c \
+	listen.c \
+	memcspn.c \
+	oneC_sum.c \
+	rcmd.c \
+	recv.c \
+	recvfrom.c \
+	res_comp.c \
+	res_init.c \
+	res_mkquery.c \
+	res_query.c \
+	res_send.c \
+	ruserok.c \
+	send.c \
+	sendto.c \
+	servxcheck.c \
+	sethostent.c \
+	setsockopt.c \
+	shutdown.c \
+	socket.c \
+	strcasecmp.c"
+
+TYPE=both
Index: /trunk/minix/lib/ip/accept.c
===================================================================
--- /trunk/minix/lib/ip/accept.c	(revision 9)
+++ /trunk/minix/lib/ip/accept.c	(revision 9)
@@ -0,0 +1,65 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/netlib.h>
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+static int _tcp_accept(int socket, struct sockaddr *_RESTRICT address,
+	socklen_t *_RESTRICT address_len);
+
+int accept(int socket, struct sockaddr *_RESTRICT address,
+	socklen_t *_RESTRICT address_len)
+{
+	int r;
+
+	r= _tcp_accept(socket, address, address_len);
+	return r;
+
+#if DEBUG
+	fprintf(stderr, "accept: not implemented for fd %d\n", socket);
+#endif
+	errno= ENOSYS;
+	return -1;
+}
+
+static int _tcp_accept(int socket, struct sockaddr *_RESTRICT address,
+	socklen_t *_RESTRICT address_len)
+{
+	int r, s1, t_errno;
+	tcp_cookie_t cookie;
+
+	s1= open(TCP_DEVICE, O_RDWR);
+	if (s1 == -1)
+		return s1;
+	r= ioctl(s1, NWIOGTCPCOOKIE, &cookie);
+	if (r == -1)
+	{
+		t_errno= errno;
+		close(s1);
+		errno= t_errno;
+		return -1;
+	}
+	r= ioctl(socket, NWIOTCPACCEPTTO, &cookie);
+	if (r == -1)
+	{
+		t_errno= errno;
+		close(s1);
+		errno= t_errno;
+		return -1;
+	}
+	if (address != NULL)
+		getpeername(s1, address, address_len);
+	return s1;
+}
Index: /trunk/minix/lib/ip/bind.c
===================================================================
--- /trunk/minix/lib/ip/bind.c	(revision 9)
+++ /trunk/minix/lib/ip/bind.c	(revision 9)
@@ -0,0 +1,153 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+static int _tcp_bind(int socket, const struct sockaddr *address,
+	socklen_t address_len, nwio_tcpconf_t *tcpconfp);
+static int _udp_bind(int socket, const struct sockaddr *address,
+	socklen_t address_len, nwio_udpopt_t *udpoptp);
+
+int bind(int socket, const struct sockaddr *address, socklen_t address_len)
+{
+	int r;
+	nwio_tcpconf_t tcpconf;
+	nwio_udpopt_t udpopt;
+
+	r= ioctl(socket, NWIOGTCPCONF, &tcpconf);
+	if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
+	{
+		if (r == -1)
+			return r;
+		r= _tcp_bind(socket, address, address_len, &tcpconf);
+#if DEBUG
+		if (r == -1)
+		{
+			int t_errno= errno;
+			fprintf(stderr, "bind(tcp) failed: %s\n",
+				strerror(errno));
+			errno= t_errno;
+		}
+#endif
+		return r;
+	}
+
+	r= ioctl(socket, NWIOGUDPOPT, &udpopt);
+	if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
+	{
+		if (r == -1)
+			return r;
+		return _udp_bind(socket, address, address_len, &udpopt);
+	}
+
+#if DEBUG
+	fprintf(stderr, "bind: not implemented for fd %d\n", socket);
+#endif
+	errno= ENOSYS;
+	return -1;
+}
+
+static int _tcp_bind(int socket, const struct sockaddr *address,
+	socklen_t address_len, nwio_tcpconf_t *tcpconfp)
+{
+	int r;
+	nwio_tcpconf_t tcpconf;
+	struct sockaddr_in *sinp;
+
+	sinp= (struct sockaddr_in *)address;
+	if (sinp->sin_family != AF_INET || address_len != sizeof(*sinp))
+	{
+#if DEBUG
+		fprintf(stderr, "bind(tcp): sin_family = %d, len = %d\n",
+			sinp->sin_family, address_len);
+#endif
+		errno= EAFNOSUPPORT;
+		return -1;
+	}
+
+	if (sinp->sin_addr.s_addr != INADDR_ANY &&
+		sinp->sin_addr.s_addr != tcpconfp->nwtc_locaddr)
+	{
+		errno= EADDRNOTAVAIL;
+		return -1;
+	}
+
+	tcpconf.nwtc_flags= 0;
+
+	if (sinp->sin_port == 0)
+		tcpconf.nwtc_flags |= NWTC_LP_SEL;
+	else
+	{
+		tcpconf.nwtc_flags |= NWTC_LP_SET;
+		tcpconf.nwtc_locport= sinp->sin_port;
+	}
+
+	r= ioctl(socket, NWIOSTCPCONF, &tcpconf);
+	return r;
+}
+
+static int _udp_bind(int socket, const struct sockaddr *address,
+	socklen_t address_len, nwio_udpopt_t *udpoptp)
+{
+	int r;
+	unsigned long curr_flags;
+	nwio_udpopt_t udpopt;
+	struct sockaddr_in *sinp;
+
+	sinp= (struct sockaddr_in *)address;
+	if (sinp->sin_family != AF_INET || address_len != sizeof(*sinp))
+	{
+#if DEBUG
+		fprintf(stderr, "bind(udp): sin_family = %d, len = %d\n",
+			sinp->sin_family, address_len);
+#endif
+		errno= EAFNOSUPPORT;
+		return -1;
+	}
+
+	if (sinp->sin_addr.s_addr != INADDR_ANY &&
+		sinp->sin_addr.s_addr != udpoptp->nwuo_locaddr)
+	{
+		errno= EADDRNOTAVAIL;
+		return -1;
+	}
+
+	udpopt.nwuo_flags= 0;
+
+	if (sinp->sin_port == 0)
+		udpopt.nwuo_flags |= NWUO_LP_SEL;
+	else
+	{
+		udpopt.nwuo_flags |= NWUO_LP_SET;
+		udpopt.nwuo_locport= sinp->sin_port;
+	}
+
+	curr_flags= udpoptp->nwuo_flags;
+	if (!(curr_flags & NWUO_ACC_MASK))
+		udpopt.nwuo_flags |= NWUO_EXCL;
+	if (!(curr_flags & (NWUO_EN_LOC|NWUO_DI_LOC)))
+		udpopt.nwuo_flags |= NWUO_EN_LOC;
+	if (!(curr_flags & (NWUO_EN_BROAD|NWUO_DI_BROAD)))
+		udpopt.nwuo_flags |= NWUO_EN_BROAD;
+	if (!(curr_flags & (NWUO_RP_SET|NWUO_RP_ANY)))
+		udpopt.nwuo_flags |= NWUO_RP_ANY;
+	if (!(curr_flags & (NWUO_RA_SET|NWUO_RA_ANY)))
+		udpopt.nwuo_flags |= NWUO_RA_ANY;
+	if (!(curr_flags & (NWUO_RWDATONLY|NWUO_RWDATALL)))
+		udpopt.nwuo_flags |= NWUO_RWDATALL;
+	if (!(curr_flags & (NWUO_EN_IPOPT|NWUO_DI_IPOPT)))
+		udpopt.nwuo_flags |= NWUO_DI_IPOPT;
+
+	r= ioctl(socket, NWIOSUDPOPT, &udpopt);
+	return r;
+}
Index: /trunk/minix/lib/ip/connect.c
===================================================================
--- /trunk/minix/lib/ip/connect.c	(revision 9)
+++ /trunk/minix/lib/ip/connect.c	(revision 9)
@@ -0,0 +1,138 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+static int _tcp_connect(int socket, const struct sockaddr *address,
+	socklen_t address_len, nwio_tcpconf_t *tcpconfp);
+static int _udp_connect(int socket, const struct sockaddr *address,
+	socklen_t address_len, nwio_udpopt_t *udpoptp);
+
+int connect(int socket, const struct sockaddr *address,
+	socklen_t address_len)
+{
+	int r;
+	nwio_tcpconf_t tcpconf;
+	nwio_udpopt_t udpopt;
+
+	r= ioctl(socket, NWIOGTCPCONF, &tcpconf);
+	if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
+	{
+		if (r == -1)
+		{
+			/* Bad file descriptor */
+			return -1;
+		}
+		return _tcp_connect(socket, address, address_len, &tcpconf);
+	}
+
+	r= ioctl(socket, NWIOGUDPOPT, &udpopt);
+	if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
+	{
+		if (r == -1)
+		{
+			/* Bad file descriptor */
+			return -1;
+		}
+		return _udp_connect(socket, address, address_len, &udpopt);
+	}
+#if DEBUG
+	fprintf(stderr, "connect: not implemented for fd %d\n", socket);
+#endif
+	errno= ENOSYS;
+	return -1;
+}
+
+static int _tcp_connect(int socket, const struct sockaddr *address,
+	socklen_t address_len, nwio_tcpconf_t *tcpconfp)
+{
+	int r;
+	struct sockaddr_in *sinp;
+	nwio_tcpconf_t tcpconf;
+	nwio_tcpcl_t tcpcl;
+
+	if (address_len != sizeof(*sinp))
+	{
+		errno= EINVAL;
+		return -1;
+	}
+	sinp= (struct sockaddr_in *)address;
+	if (sinp->sin_family != AF_INET)
+	{
+		errno= EINVAL;
+		return -1;
+	}
+	tcpconf.nwtc_flags= NWTC_SET_RA | NWTC_SET_RP;
+	if ((tcpconfp->nwtc_flags & NWTC_LOCPORT_MASK) == NWTC_LP_UNSET)
+		tcpconf.nwtc_flags |= NWTC_LP_SEL;
+	tcpconf.nwtc_remaddr= sinp->sin_addr.s_addr;
+	tcpconf.nwtc_remport= sinp->sin_port;
+
+	if (ioctl(socket, NWIOSTCPCONF, &tcpconf) == -1)
+        {
+		/* Ignore EISCONN error. The NWIOTCPCONN ioctl will get the
+		 * right error.
+		 */
+		if (errno != EISCONN)
+			return -1;
+	}
+
+	tcpcl.nwtcl_flags= TCF_DEFAULT;
+
+	r= fcntl(socket, F_GETFL);
+	if (r == 1)
+		return -1;
+	if (r & O_NONBLOCK)
+		tcpcl.nwtcl_flags |= TCF_ASYNCH;
+
+	r= ioctl(socket, NWIOTCPCONN, &tcpcl);
+	return r;
+}
+
+static int _udp_connect(int socket, const struct sockaddr *address,
+	socklen_t address_len, nwio_udpopt_t *udpoptp)
+{
+	int r;
+	struct sockaddr_in *sinp;
+	nwio_udpopt_t udpopt;
+
+	if (address == NULL)
+	{
+		/* Unset remote address */
+		udpopt.nwuo_flags= NWUO_RP_ANY | NWUO_RA_ANY;
+
+		r= ioctl(socket, NWIOSUDPOPT, &udpopt);
+		return r;
+	}
+
+	if (address_len != sizeof(*sinp))
+	{
+		errno= EINVAL;
+		return -1;
+	}
+	sinp= (struct sockaddr_in *)address;
+	if (sinp->sin_family != AF_INET)
+	{
+		errno= EINVAL;
+		return -1;
+	}
+	udpopt.nwuo_flags= NWUO_RP_SET | NWUO_RA_SET;
+	if ((udpoptp->nwuo_flags & NWUO_LOCPORT_MASK) == NWUO_LP_ANY)
+		udpopt.nwuo_flags |= NWUO_LP_SEL;
+	udpopt.nwuo_remaddr= sinp->sin_addr.s_addr;
+	udpopt.nwuo_remport= sinp->sin_port;
+
+	r= ioctl(socket, NWIOSUDPOPT, &udpopt);
+	return r;
+}
Index: /trunk/minix/lib/ip/dhcp_gettag.c
===================================================================
--- /trunk/minix/lib/ip/dhcp_gettag.c	(revision 9)
+++ /trunk/minix/lib/ip/dhcp_gettag.c	(revision 9)
@@ -0,0 +1,55 @@
+/*	dhcp_gettag()					Author: Kees J. Bot
+ *								1 Dec 2000
+ */
+#define nil ((void*)0)
+#include <stddef.h>
+#include <string.h>
+#include <sys/types.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/dhcp.h>
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+
+int dhcp_gettag(dhcp_t *dp, int searchtag, u8_t **pdata, size_t *plen)
+{
+    /* Find a tag in the options field, or possibly in the file or sname
+     * fields.  Return true iff found, and return the data and/or length if
+     * their pointers are non-null.
+     */
+    u8_t *p;
+    u8_t *optfield[3];
+    size_t optlen[3];
+    int i, tag, len;
+
+    /* The DHCP magic number must be correct, or no tags. */
+    if (dp->magic != DHCP_MAGIC) return 0;
+
+    optfield[0]= dp->options;
+    optlen[0]= arraysize(dp->options);
+    optfield[1]= dp->file;
+    optlen[1]= 0;		/* Unknown if used for options yet. */
+    optfield[2]= dp->sname;
+    optlen[2]= 0;
+
+    for (i= 0; i < 3; i++) {
+	p= optfield[i];
+	while (p < optfield[i] + optlen[i]) {
+	    tag= *p++;
+	    if (tag == 255) break;
+	    len= tag == 0 ? 0 : *p++;
+	    if (tag == searchtag) {
+		if (pdata != nil) *pdata= p;
+		if (plen != nil) *plen= len;
+		return 1;
+	    }
+	    if (tag == DHCP_TAG_OVERLOAD) {
+		/* There are also options in the file or sname field. */
+		if (*p & 1) optlen[1]= arraysize(dp->file);
+		if (*p & 2) optlen[1]= arraysize(dp->sname);
+	    }
+	    p += len;
+	}
+    }
+    return 0;
+}
Index: /trunk/minix/lib/ip/dhcp_settag.c
===================================================================
--- /trunk/minix/lib/ip/dhcp_settag.c	(revision 9)
+++ /trunk/minix/lib/ip/dhcp_settag.c	(revision 9)
@@ -0,0 +1,57 @@
+/*	dhcp_init(), dhcp_settag()			Author: Kees J. Bot
+ *								1 Dec 2000
+ */
+#define nil ((void*)0)
+#include <stddef.h>
+#include <string.h>
+#include <sys/types.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/dhcp.h>
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+
+void dhcp_init(dhcp_t *dp)
+{
+    /* Initialize a DHCP packet. */
+    memset(dp, 0, offsetof(dhcp_t, magic));
+    dp->magic= DHCP_MAGIC;
+    memset(dp->options, 255, sizeof(dp->options));
+}
+
+int dhcp_settag(dhcp_t *dp, int tag, void *data, size_t len)
+{
+    /* Add a tag to a DHCP packet.  No padding.  Only do the options field.
+     * (This is Minix, we don't need megabytes of silly bits of data.)
+     * The length may be zero to delete a tag.
+     */
+    u8_t *p;
+    int n;
+
+    if (tag <= 0 || tag >= 255) return 0;
+
+    for (p= dp->options; p < arraylimit(dp->options) && *p != 255; p += n) {
+	n= 1 + 1 + p[1];
+	if (*p == tag) {
+	    /* The tag is already there, remove it so it gets replaced. */
+	    memmove(p, p + n, arraylimit(dp->options) - (p + n));
+	    memset(arraylimit(dp->options) - n, 255, n);
+	    n= 0;
+	}
+    }
+
+    /* Add tag. */
+    if (len == 0) {
+	/* We're merely deleting a tag. */
+    } else
+    if (p + 1 + 1 + len <= arraylimit(dp->options)) {
+	*p++ = tag;
+	*p++ = len;
+	memcpy(p, data, len);
+    } else {
+	/* Oops, it didn't fit?  Is this really Minix??? */
+	return 0;
+    }
+    return 1;
+}
Index: /trunk/minix/lib/ip/domainname.c
===================================================================
--- /trunk/minix/lib/ip/domainname.c	(revision 9)
+++ /trunk/minix/lib/ip/domainname.c	(revision 9)
@@ -0,0 +1,30 @@
+/*
+domainname.c
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <net/netlib.h>
+
+int getdomainname(domain, size)
+char *domain;
+size_t size;
+{
+	FILE *domainfile;
+	char *line;
+
+	domainfile= fopen("/etc/domainname", "r");
+	if (!domainfile)
+	{
+		return -1;
+	}
+
+	line= fgets(domain, size, domainfile);
+	fclose(domainfile);
+	if (!line)
+		return -1;
+	line= strchr(domain, '\n');
+	if (line)
+		*line= '\0';
+	return 0;
+}
Index: /trunk/minix/lib/ip/ether.h
===================================================================
--- /trunk/minix/lib/ip/ether.h	(revision 9)
+++ /trunk/minix/lib/ip/ether.h	(revision 9)
@@ -0,0 +1,151 @@
+/* $Id: ether.h,v 1.1.1.1 2005/04/21 14:56:15 beng Exp $ */
+
+/* Interface definitions for ethernet access library */
+
+typedef union etheraddr
+{
+    unsigned char bytes[6];		/* byteorder safe initialization */
+    unsigned short shorts[3];		/* force 2-byte alignment */
+}
+	  ether_addr;
+
+typedef struct etherpacket
+{
+    ether_addr dest;
+    ether_addr src;
+    unsigned char type[2];		/* in network byte order! */
+    unsigned short pktlen;		/* length of pktbuf ONLY */
+    char *pktbuf;
+}
+	    ether_packet;
+
+typedef struct ethervec
+{
+    ether_addr dest;
+    ether_addr src;
+    unsigned char type[2];		/* in network byte order! */
+    unsigned short iovcnt;		/* number of iovec to use */
+    struct iovec *iov;			/* ptr to array of iovec */
+}
+	 ether_vec;
+
+#ifndef __ETHER_BCAST_ADDR__
+extern ether_addr ether_bcast_addr;
+#endif
+
+#ifdef __STDC__
+
+int ether_open (char *name, unsigned type, ether_addr * address);
+
+ether_addr *ether_address (int fd, ether_addr * address);
+
+ether_addr *ether_intfaddr (char *intf, ether_addr * address);
+
+char **ether_interfaces (void);
+
+int ether_write (int fd, ether_packet * packet);
+
+int ether_writev (int fd, ether_vec * packet);
+
+int ether_read (int fd, ether_packet * packet);
+
+int ether_readv (int fd, ether_vec * packet);
+
+int ether_blocking (int fd, int state);
+
+int ether_send_self (int fd);
+
+int ether_mcast_self (int fd);
+
+int ether_bcast_self (int fd);
+
+char *ether_ntoa (ether_addr *);
+
+ether_addr *ether_aton (char *);
+
+#ifdef __GNUC__
+
+/*
+ * Avoid stupid warnings if structs aren't defined
+ */
+
+typedef struct in_addr *_ether_NoNsEnSe;
+typedef struct hostent *_ether_nOnSeNsE;
+
+#endif
+
+char *ether_e2a (ether_addr *, char *);
+
+ether_addr *ether_a2e (char *, ether_addr *);
+
+struct in_addr *ether_e2ip (ether_addr *, struct in_addr *);
+
+ether_addr *ether_ip2e (struct in_addr *, ether_addr *);
+
+char *ether_e2host (ether_addr *, char *);
+
+ether_addr *ether_host2e (char *, ether_addr *);
+
+ether_addr *ether_hostent2e (struct hostent *, ether_addr *);
+
+#else
+
+int ether_open ();
+ether_addr *ether_address ();
+ether_addr *ether_intfaddr ();
+char **ether_interfaces ();
+int ether_write ();
+int ether_writev ();
+int ether_read ();
+int ether_readv ();
+int ether_blocking ();
+int ether_send_self ();
+int ether_mcast_self ();
+int ether_bcast_self ();
+
+char *ether_ntoa ();
+ether_addr *ether_aton ();
+char *ether_e2a ();
+ether_addr *ether_a2e ();
+struct in_addr *ether_e2ip ();
+ether_addr *ether_ip2e ();
+char *ether_e2host ();
+ether_addr *ether_host2e ();
+ether_addr *ether_hostent2e ();
+
+#endif
+
+#undef ether_cmp			/* lose def from netinet/if_ether.h */
+
+#define ether_cmp(addr1,addr2) \
+ ((addr1)->shorts[0] != (addr2)->shorts[0] \
+  || (addr1)->shorts[1] != (addr2)->shorts[1] \
+  || (addr1)->shorts[2] != (addr2)->shorts[2])
+
+#define ETHERSTRLEN 18			/* max length of "xx:xx:xx:xx:xx:xx" */
+
+#ifdef NOFILE				/* i.e. we have included sys/param.h */
+#ifndef MAXHOSTNAMELEN			/* but MAXHOSTNAMELEN still isnt set */
+#define MAXHOSTNAMELEN 64
+#endif
+#endif
+
+/* should be defined in terms of ether_packet struct; need offsetof() macro */
+
+#define ETHER_DST	0
+#define ETHER_SRC	6
+#define ETHER_TYPE	12
+#define ETHER_PKT	14
+#define ETHER_MIN	46
+#define ETHER_MAX	1500
+
+#define ETHER_MINTYPE	0x5DD		/* lowest protocol not valid IEEE802 */
+#define ETHER_MAXTYPE	0xFFFF		/* largest possible protocol */
+
+#define ETHER_MCAST(addr) (((unsigned char *) (addr))[0] & 0x01)
+
+#ifdef NT_ALLTYPES
+#define ETHER_ALLTYPES NT_ALLTYPES
+#else
+#define ETHER_ALLTYPES ((unsigned) -1)
+#endif
Index: /trunk/minix/lib/ip/ether_line.c
===================================================================
--- /trunk/minix/lib/ip/ether_line.c	(revision 9)
+++ /trunk/minix/lib/ip/ether_line.c	(revision 9)
@@ -0,0 +1,58 @@
+/*
+**  ETHER_LINE
+**
+**	This routine parses the array pointed to by "line" (which should be
+**	from a file in the format of /etc/ethers) and returns in "eaddr" the
+**	ethernet address at the start of the line and the corresponding host
+**	name in "hostname".  It assumes either tabs or spaces separate the
+**	two.  The buffer pointed to by "hostname" must be big enough to hold
+**	the host name plus a NULL byte.
+**	The function returns 0 on success and 1 on failure.
+**	Arguments are assumed sensible.  Null pointers will probably cause
+**	exceptions.
+**	Author: Gregory J. Sharp, July 1990
+**	Adapted to MINIX: Philip Homburg, May 1992
+*/
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <net/gen/ether.h>
+#include <net/gen/if_ether.h>
+
+int
+ether_line(line, eaddr, hostname)
+char *			line;
+struct ether_addr *	eaddr;
+char *			hostname;
+{
+    register int i;
+    register unsigned long val;
+
+/* skip leading white space */
+    while (*line != '\n' && (*line == ' ' || *line == '\t'))
+	line++;
+
+/* read the ethernet address */
+    for (i = 0; i < 5; i++)
+    {
+	val = (unsigned long) strtol(line, &line, 16);
+	if (val > 255 || *line++ != ':')
+	    return 1;
+	eaddr->ea_addr[i] = val & 0xff;
+    }
+    val = (unsigned long) strtol(line, &line, 16);
+    if (val > 255 || (*line != ' ' && *line != '\t'))
+	return 1;
+    eaddr->ea_addr[i] = val & 0xff;
+
+/* skip leading white space */
+    while (*line != '\n' && (*line == ' ' || *line == '\t'))
+	line++;
+
+/* read in the hostname */
+    while (!isspace(*line))
+	*hostname++ = *line++;
+    *hostname = '\0';
+    return 0;
+}
Index: /trunk/minix/lib/ip/ethera2n.c
===================================================================
--- /trunk/minix/lib/ip/ethera2n.c	(revision 9)
+++ /trunk/minix/lib/ip/ethera2n.c	(revision 9)
@@ -0,0 +1,42 @@
+/*
+ethera2n.c
+
+Convert an ASCII string with an ethernet address into a struct ether_addr.
+
+Created:	Nov 17, 1992 by Philip Homburg
+*/
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <net/netlib.h>
+#include <net/gen/ether.h>
+#include <net/gen/if_ether.h>
+
+struct ether_addr *ether_aton(s)
+_CONST char *s;
+{
+	static struct ether_addr ea;
+
+	int i;
+	long v;
+	char *check;
+
+	if (s == NULL)
+		return NULL;
+
+	for (i=0; i<6; i++)
+	{
+		v= strtol(s, &check, 16);
+		if (v<0 || v>255)
+			return NULL;
+		if ((i<5 && check[0] != ':') || (i == 5 && check[0] != '\0'))
+			return NULL;
+		ea.ea_addr[i]= v;
+		s= check+1;
+	}
+	return &ea;
+}
+
+/*
+ * $PchId: ethera2n.c,v 1.3 1996/02/22 21:10:01 philip Exp $
+ */
Index: /trunk/minix/lib/ip/ethere2a.c
===================================================================
--- /trunk/minix/lib/ip/ethere2a.c	(revision 9)
+++ /trunk/minix/lib/ip/ethere2a.c	(revision 9)
@@ -0,0 +1,50 @@
+/* $Id: ethere2a.c,v 1.1.1.1 2005/04/21 14:56:16 beng Exp $ */
+/* This file was part of the etherlib package. */
+
+#include <stdio.h>
+
+#ifdef _MINIX
+#include <sys/types.h>
+#include <stdlib.h>
+
+#include <net/gen/ether.h>
+#include <net/gen/if_ether.h>
+
+#define ETHERSTRLEN 18			/* max length of "xx:xx:xx:xx:xx:xx" */
+#define ether_addr	ether_addr_t
+#define bytes		ea_addr
+char *ether_e2a _ARGS(( ether_addr_t *a, char *e ));
+#else
+#include "libether.h"
+#endif
+
+char *
+ether_e2a (addr, estring)
+ether_addr *addr;
+char *estring;
+{
+#ifdef lint
+    char *sprintf ();
+#endif
+    if (estring == NULL)
+	estring = (char *) malloc (ETHERSTRLEN);
+
+    if (estring != NULL)
+	(void) sprintf (estring, "%x:%x:%x:%x:%x:%x",
+			addr->bytes[0], addr->bytes[1], addr->bytes[2],
+			addr->bytes[3], addr->bytes[4], addr->bytes[5]);
+    return (estring);
+}
+
+#ifndef ETHERDB
+
+char *
+ether_ntoa (addr)
+ether_addr *addr;
+{
+    static char estring[ETHERSTRLEN];
+
+    return (ether_e2a (addr, estring));
+}
+
+#endif
Index: /trunk/minix/lib/ip/etherh2n.c
===================================================================
--- /trunk/minix/lib/ip/etherh2n.c	(revision 9)
+++ /trunk/minix/lib/ip/etherh2n.c	(revision 9)
@@ -0,0 +1,33 @@
+/*
+etherh2n.c
+
+Created:	May 20, 1992 by Philip Homburg
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <net/gen/if_ether.h>
+
+int
+ether_hostton(hostname, e)
+char *hostname;
+struct ether_addr *e;
+{
+	FILE *etherf;
+	char b[256], hn[256];
+
+	etherf= fopen(_PATH_ETHERS, "r");
+	if (etherf == NULL)
+		return 1;
+
+	while(fgets(b, sizeof(b), etherf) != NULL)
+	{
+		if (ether_line(b, e, hn) == 0 && strcmp(hn, hostname) == 0)
+		{
+			fclose(etherf);
+			return 0;
+		}
+	}
+	fclose(etherf);
+	return 1;
+}
Index: /trunk/minix/lib/ip/ethern2h.c
===================================================================
--- /trunk/minix/lib/ip/ethern2h.c	(revision 9)
+++ /trunk/minix/lib/ip/ethern2h.c	(revision 9)
@@ -0,0 +1,37 @@
+/*
+ethern2h.c
+
+Created:	Nov 12, 1992 by Philip Homburg
+*/
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <net/gen/ether.h>
+#include <net/gen/if_ether.h>
+
+int
+ether_ntohost(hostname, e)
+char *hostname;
+struct ether_addr *e;
+{
+	FILE *etherf;
+	char b[256];
+	struct ether_addr e_tmp;
+
+	etherf= fopen(_PATH_ETHERS, "r");
+	if (etherf == NULL)
+		return 1;
+
+	while(fgets(b, sizeof(b), etherf) != NULL)
+	{
+		if (ether_line(b, &e_tmp, hostname) == 0 && 
+		memcmp(&e_tmp, e, sizeof(e_tmp)) == 0)
+		{
+			fclose(etherf);
+			return 0;
+		}
+	}
+	fclose(etherf);
+	return 1;
+}
Index: /trunk/minix/lib/ip/getdomain.c
===================================================================
--- /trunk/minix/lib/ip/getdomain.c	(revision 9)
+++ /trunk/minix/lib/ip/getdomain.c	(revision 9)
@@ -0,0 +1,23 @@
+/*	getdomainname()					Author: Kees J. Bot
+ *								2 Dec 1994
+ */
+#define nil 0
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+#include <string.h>
+
+int getdomainname(char *domain, size_t size)
+{
+	char nodename[256];
+	char *dot;
+
+	if (gethostname(nodename, sizeof(nodename)) < 0)
+		return -1;
+	nodename[sizeof(nodename)-1]= 0;
+	if ((dot= strchr(nodename, '.')) == nil) dot= ".";
+
+	strncpy(domain, dot+1, size);
+	if (size > 0) domain[size-1]= 0;
+	return 0;
+}
Index: /trunk/minix/lib/ip/gethnmadr.c
===================================================================
--- /trunk/minix/lib/ip/gethnmadr.c	(revision 9)
+++ /trunk/minix/lib/ip/gethnmadr.c	(revision 9)
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 1985, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c	6.41 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef _MINIX
+#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <net/hton.h>
+#include <net/gen/nameser.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/resolv.h>
+#include <net/gen/socket.h>
+#else
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#endif /* AMOEABA */
+
+#define	MAXALIASES	35
+#define	MAXADDRS	35
+
+static char *h_addr_ptrs[MAXADDRS + 1];
+
+#ifdef _MINIX
+struct in_addr
+{
+	ipaddr_t s_addr;
+};
+union querybuf;
+
+extern int dn_skipname _ARGS(( const u_char *comp_dn, const u_char *eom ));
+#define getshort _getshort
+static struct hostent *getanswer _ARGS(( union querybuf *answer, int anslen, 
+	int iquery ));
+#define bcmp memcmp
+#define bcopy(s, d, l) memcpy(d, s, l)
+#endif /* _MINIX */
+
+static struct hostent host;
+static char *host_aliases[MAXALIASES];
+static char hostbuf[BUFSIZ+1];
+static struct in_addr host_addr;
+
+#ifndef _MINIX
+char *strpbrk();
+#endif /* !_MINIX */
+
+#if PACKETSZ > 1024
+#define	MAXPACKET	PACKETSZ
+#else
+#define	MAXPACKET	1024
+#endif
+
+typedef union querybuf
+{
+	dns_hdr_t hdr;
+	u_char buf[MAXPACKET];
+} querybuf_t;
+
+typedef union align {
+    long al;
+    char ac;
+} align_t;
+
+static struct hostent *
+getanswer(answer, anslen, iquery)
+	querybuf_t *answer;
+	int anslen;
+	int iquery;
+{
+	register dns_hdr_t *hp;
+	register u_char *cp;
+	register int n;
+	u_char *eom;
+	char *bp, **ap;
+	int type, class, buflen, ancount, qdcount;
+	int haveanswer, getclass = C_ANY;
+	char **hap;
+
+	eom = answer->buf + anslen;
+	/*
+	 * find first satisfactory answer
+	 */
+	hp = &answer->hdr;
+	ancount = ntohs(hp->dh_ancount);
+	qdcount = ntohs(hp->dh_qdcount);
+	bp = hostbuf;
+	buflen = sizeof(hostbuf);
+	cp = answer->buf + sizeof(dns_hdr_t);
+	if (qdcount) {
+		if (iquery) {
+			if ((n = dn_expand((u_char *)answer->buf, eom,
+			     cp, (u_char *)bp, buflen)) < 0) {
+				h_errno = NO_RECOVERY;
+				return ((struct hostent *) NULL);
+			}
+			cp += n + QFIXEDSZ;
+			host.h_name = bp;
+			n = strlen(bp) + 1;
+			bp += n;
+			buflen -= n;
+		} else
+			cp += dn_skipname(cp, eom) + QFIXEDSZ;
+		while (--qdcount > 0)
+			cp += dn_skipname(cp, eom) + QFIXEDSZ;
+	} else if (iquery) {
+		if (hp->dh_flag1 & DHF_AA)
+			h_errno = HOST_NOT_FOUND;
+		else
+			h_errno = TRY_AGAIN;
+		return ((struct hostent *) NULL);
+	}
+	ap = host_aliases;
+	*ap = NULL;
+	host.h_aliases = host_aliases;
+	hap = h_addr_ptrs;
+	*hap = NULL;
+#if BSD >= 43 || defined(h_addr)	/* new-style hostent structure */
+	host.h_addr_list = h_addr_ptrs;
+#endif
+	haveanswer = 0;
+	while (--ancount >= 0 && cp < eom) {
+		if ((n = dn_expand((u_char *)answer->buf, eom, cp, (u_char *)bp,
+			buflen)) < 0)
+			break;
+		cp += n;
+		type = getshort(cp);
+ 		cp += sizeof(u_short);
+		class = getshort(cp);
+ 		cp += sizeof(u_short) + sizeof(u_long);
+		n = getshort(cp);
+		cp += sizeof(u_short);
+		if (type == T_CNAME) {
+			cp += n;
+			if (ap >= &host_aliases[MAXALIASES-1])
+				continue;
+			*ap++ = bp;
+			n = strlen(bp) + 1;
+			bp += n;
+			buflen -= n;
+			continue;
+		}
+		if (iquery && type == T_PTR) {
+			if ((n = dn_expand((u8_t *)answer->buf, eom,
+			    cp, (u8_t *)bp, buflen)) < 0) {
+				cp += n;
+				continue;
+			}
+			cp += n;
+			host.h_name = bp;
+			return(&host);
+		}
+		if (iquery || type != T_A)  {
+#ifdef DEBUG
+			if (_res.options & RES_DEBUG)
+				printf("unexpected answer type %d, size %d\n",
+					type, n);
+#endif
+			cp += n;
+			continue;
+		}
+		if (haveanswer) {
+			if (n != host.h_length) {
+				cp += n;
+				continue;
+			}
+			if (class != getclass) {
+				cp += n;
+				continue;
+			}
+		} else {
+			host.h_length = n;
+			getclass = class;
+			host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
+			if (!iquery) {
+				host.h_name = bp;
+				bp += strlen(bp) + 1;
+			}
+		}
+
+		bp += (size_t)(sizeof(align_t) - 
+						((u_long)bp % sizeof(align_t)));
+
+		if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
+#ifdef DEBUG
+			if (_res.options & RES_DEBUG)
+				printf("size (%d) too big\n", n);
+#endif
+			break;
+		}
+		bcopy(cp, *hap++ = bp, n);
+		bp +=n;
+		cp += n;
+		haveanswer++;
+	}
+	if (haveanswer) {
+		*ap = NULL;
+#if BSD >= 43 || defined(h_addr)	/* new-style hostent structure */
+		*hap = NULL;
+#else
+		host.h_addr = h_addr_ptrs[0];
+#endif
+		return (&host);
+	} else {
+		h_errno = TRY_AGAIN;
+		return ((struct hostent *) NULL);
+	}
+}
+
+struct hostent *
+gethostbyname(name)
+	_CONST char *name;
+{
+	querybuf_t buf;
+	register _CONST char *cp;
+	int n;
+
+	/*
+	 * disallow names consisting only of digits/dots, unless
+	 * they end in a dot.
+	 */
+	if (isdigit(name[0]))
+		for (cp = name;; ++cp) {
+			if (!*cp) {
+				if (*--cp == '.')
+					break;
+				/*
+				 * All-numeric, no dot at the end.
+				 * Fake up a hostent as if we'd actually
+				 * done a lookup.  What if someone types
+				 * 255.255.255.255?  The test below will
+				 * succeed spuriously... ???
+				 */
+				if ((host_addr.s_addr = inet_addr(name)) == -1) {
+					h_errno = HOST_NOT_FOUND;
+					return((struct hostent *) NULL);
+				}
+				host.h_name = (char *) name;
+				host.h_aliases = host_aliases;
+				host_aliases[0] = NULL;
+				host.h_addrtype = AF_INET;
+				host.h_length = sizeof(u_long);
+				h_addr_ptrs[0] = (char *)&host_addr;
+				h_addr_ptrs[1] = (char *)0;
+#if BSD >= 43 || defined(h_addr)	/* new-style hostent structure */
+				host.h_addr_list = h_addr_ptrs;
+#else
+				host.h_addr = h_addr_ptrs[0];
+#endif
+				return (&host);
+			}
+			if (!isdigit(*cp) && *cp != '.') 
+				break;
+		}
+
+	if ((n = res_search((char*)name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
+#ifdef DEBUG
+		if (_res.options & RES_DEBUG)
+			printf("res_search failed\n");
+#endif
+		return ((struct hostent *) NULL);
+	}
+	return (getanswer(&buf, n, 0));
+}
+
+struct hostent *
+gethostbyaddr(addr, len, type)
+	const char *addr;
+	int len, type;
+{
+	int n;
+	querybuf_t buf;
+	register struct hostent *hp;
+	char qbuf[MAXDNAME];
+	
+	if (type != AF_INET)
+		return ((struct hostent *) NULL);
+	(void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
+		((unsigned)addr[3] & 0xff),
+		((unsigned)addr[2] & 0xff),
+		((unsigned)addr[1] & 0xff),
+		((unsigned)addr[0] & 0xff));
+	n = res_query(qbuf, C_IN, T_PTR, (u8_t *)&buf, sizeof(buf));
+	if (n < 0) {
+#ifdef DEBUG
+		if (_res.options & RES_DEBUG)
+			printf("res_query failed\n");
+#endif
+		return ((struct hostent *) NULL);
+	}
+	hp = getanswer(&buf, n, 1);
+	if (hp == NULL)
+		return ((struct hostent *) NULL);
+	hp->h_addrtype = type;
+	hp->h_length = len;
+	h_addr_ptrs[0] = (char *)&host_addr;
+	h_addr_ptrs[1] = (char *)0;
+	host_addr = *(struct in_addr *)addr;
+#if BSD < 43 && !defined(h_addr)	/* new-style hostent structure */
+	hp->h_addr = h_addr_ptrs[0];
+#endif
+	return(hp);
+}
Index: /trunk/minix/lib/ip/gethostent.c
===================================================================
--- /trunk/minix/lib/ip/gethostent.c	(revision 9)
+++ /trunk/minix/lib/ip/gethostent.c	(revision 9)
@@ -0,0 +1,168 @@
+/*	gethostent() - Interface to /etc/hosts		Author: Kees J. Bot
+ *								31 May 1999
+ */
+
+/* Prefix the functions defined here with underscores to distinguish them
+ * from the newer replacements in the resolver library.
+ */
+#define sethostent	_sethostent
+#define endhostent	_endhostent
+#define gethostent	_gethostent
+#define gethostbyname	_gethostbyname
+#define gethostbyaddr	_gethostbyaddr
+
+#define nil 0
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/socket.h>
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+#define isspace(c)	((unsigned) (c) <= ' ')
+
+static char HOSTS[]= _PATH_HOSTS;
+static char *hosts= HOSTS;	/* Current hosts file. */
+static FILE *hfp;		/* Open hosts file. */
+
+void sethostent(int stayopen)
+/* Start search.  (Same as ending it.) */
+{
+    endhostent();
+}
+
+void endhostent(void)
+/* End search and reinitialize. */
+{
+    if (hfp != nil) {
+	fclose(hfp);
+	hfp= nil;
+    }
+    hosts= _PATH_HOSTS;
+}
+
+struct hostent *gethostent(void)
+/* Return the next entry from the hosts files. */
+{
+    static char line[256];	/* One line in a hosts file. */
+    static ipaddr_t addr;	/* IP address found first on the line. */
+    static char *names[16];	/* Pointers to the words on the line. */
+    static char *addrs[2]= {	/* List of IP addresses (just one.) */
+	(char *) &addr,
+	nil,
+    };
+    static struct hostent host = {
+	nil,			/* h_name, will set to names[1]. */
+	names + 2,		/* h_aliases, the rest of the names. */
+	AF_INET,		/* h_addrtype */
+	sizeof(ipaddr_t),	/* Size of an address in the address list. */
+	addrs,			/* List of IP addresses. */
+    };
+    static char nexthosts[128];	/* Next hosts file to include. */
+    char *lp, **np;
+    int c;
+
+    for (;;) {
+	if (hfp == nil) {
+	    /* No hosts file open, try to open the next one. */
+	    if (hosts == 0) return nil;
+	    if ((hfp= fopen(hosts, "r")) == nil) { hosts= nil; continue; }
+	}
+
+	/* Read a line. */
+	lp= line;
+	while ((c= getc(hfp)) != EOF && c != '\n') {
+	    if (lp < arraylimit(line)) *lp++= c;
+	}
+
+	/* EOF?  Then close and prepare for reading the next file. */
+	if (c == EOF) {
+	    fclose(hfp);
+	    hfp= nil;
+	    hosts= nil;
+	    continue;
+	}
+
+	if (lp == arraylimit(line)) continue;
+	*lp= 0;
+
+	/* Break the line up in words. */
+	np= names;
+	lp= line;
+	for (;;) {
+	    while (isspace(*lp) && *lp != 0) lp++;
+	    if (*lp == 0 || *lp == '#') break;
+	    if (np == arraylimit(names)) break;
+	    *np++= lp;
+	    while (!isspace(*lp) && *lp != 0) lp++;
+	    if (*lp == 0) break;
+	    *lp++= 0;
+	}
+
+	if (np == arraylimit(names)) continue;
+	*np= nil;
+
+	/* Special "include file" directive. */
+	if (np == names + 2 && strcmp(names[0], "include") == 0) {
+	    fclose(hfp);
+	    hfp= nil;
+	    hosts= nil;
+	    if (strlen(names[1]) < sizeof(nexthosts)) {
+		strcpy(nexthosts, names[1]);
+		hosts= nexthosts;
+	    }
+	    continue;
+	}
+
+	/* At least two words, the first of which is an IP address. */
+	if (np < names + 2) continue;
+	if (!inet_aton((char *) names[0], &addr)) continue;
+	host.h_name= (char *) names[1];
+
+	return &host;
+    }
+}
+
+/* Rest kept in reserve, we probably never need 'em. */
+#if XXX
+struct hostent *gethostbyname(const char *name)
+{
+    struct hostent *he;
+    char **pa;
+    char alias[256];
+    char *domain;
+    
+    sethostent(0);
+    while ((he= gethostent()) != nil) {
+	if (strcasecmp(he->h_name, name) == 0) goto found;
+
+	domain= strchr(he->h_name, '.');
+	for (pa= he->h_aliases; *pa != nil; pa++) {
+	    strcpy(alias, *pa);
+	    if (domain != nil && strchr(alias, '.') == nil) {
+		strcat(alias, domain);
+	    }
+	    if (strcasecmp(alias, name) == 0) goto found;
+	}
+    }
+  found:
+    endhostent();
+    return he;
+}
+
+struct hostent *gethostbyaddr(const char *addr, int len, int type)
+{
+    struct hostent *he;
+
+    sethostent(0);
+    while ((he= gethostent()) != nil) {
+	if (he->h_name[0] == '%') continue;
+	if (type == AF_INET && memcmp(he->h_addr, addr, len) == 0) break;
+    }
+    endhostent();
+    return he;
+}
+#endif
Index: /trunk/minix/lib/ip/gethostname.c
===================================================================
--- /trunk/minix/lib/ip/gethostname.c	(revision 9)
+++ /trunk/minix/lib/ip/gethostname.c	(revision 9)
@@ -0,0 +1,27 @@
+/* gethostname(2) system call emulation */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <net/gen/netdb.h>
+
+#define HOSTNAME_FILE "/etc/hostname.file"
+
+int gethostname(char *buf, size_t len)
+{
+	int fd;
+	int r;
+	char *nl;
+
+	if ((fd= open(HOSTNAME_FILE, O_RDONLY)) < 0) return -1;
+
+	r= read(fd, buf, len);
+	close(fd);
+	if (r == -1) return -1;
+
+	buf[len-1]= '\0';
+	if ((nl= strchr(buf, '\n')) != NULL) *nl= '\0';
+	return 0;
+}
Index: /trunk/minix/lib/ip/getifaddrs.c
===================================================================
--- /trunk/minix/lib/ip/getifaddrs.c	(revision 9)
+++ /trunk/minix/lib/ip/getifaddrs.c	(revision 9)
@@ -0,0 +1,71 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <ifaddrs.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include <net/gen/in.h>
+#include <net/gen/ip_io.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+
+int
+getifaddrs(struct ifaddrs **ifap)
+{
+	static int fd = -1;
+	nwio_ipconf_t ipconf;
+	int flags, err, r;
+	static struct ifaddrs ifa;
+	static struct sockaddr_in addr, netmask;
+
+	memset(&ifa, 0, sizeof(ifa));
+	memset(&addr, 0, sizeof(addr));
+	memset(&netmask, 0, sizeof(netmask));
+	ifa.ifa_next = NULL;
+	ifa.ifa_name = "ip";
+	addr.sin_family = netmask.sin_family = AF_INET;
+	ifa.ifa_addr = (struct sockaddr *) &addr;
+	ifa.ifa_netmask = (struct sockaddr *) &netmask;
+	addr.sin_addr.s_addr = 0;
+	netmask.sin_addr.s_addr = 0;
+
+	if(fd < 0) {
+		char *ipd;
+		if(!(ipd=getenv("IP_DEVICE")))
+			ipd="/dev/ip";
+		if((fd = open(ipd, O_RDWR)) < 0)
+			return -1;
+	}
+
+	/* Code taken from commands/simple/ifconfig.c. */
+
+	if((flags = fcntl(fd, F_GETFL)) < 0 ||
+	   fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0 ||
+	   ioctl(fd, NWIOGIPCONF, &ipconf))
+		return 0;	/* Report interface as down. */
+
+	addr.sin_addr.s_addr = ipconf.nwic_ipaddr;
+	netmask.sin_addr.s_addr = ipconf.nwic_netmask;
+	if(addr.sin_addr.s_addr) ifa.ifa_flags = IFF_UP;
+
+	/* Just report on this interface. */
+
+	*ifap = &ifa;
+
+	return 0;
+}
+
+void
+freeifaddrs(struct ifaddrs *ifp)
+{
+	/* getifaddrs points to static data, so no need to free. */
+	;
+}
+
Index: /trunk/minix/lib/ip/getnetbyaddr.c
===================================================================
--- /trunk/minix/lib/ip/getnetbyaddr.c	(revision 9)
+++ /trunk/minix/lib/ip/getnetbyaddr.c	(revision 9)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1983, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getnetbyaddr.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <net/gen/netdb.h>
+
+extern int _net_stayopen;
+
+struct netent *
+getnetbyaddr(net, type)
+	register long net;
+	register int type;
+{
+	register struct netent *p;
+
+	setnetent(_net_stayopen);
+	while (p = getnetent())
+		if (p->n_addrtype == type && p->n_net == net)
+			break;
+	if (!_net_stayopen)
+		endnetent();
+	return (p);
+}
Index: /trunk/minix/lib/ip/getnetbyname.c
===================================================================
--- /trunk/minix/lib/ip/getnetbyname.c	(revision 9)
+++ /trunk/minix/lib/ip/getnetbyname.c	(revision 9)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1983, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getnetbyname.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <string.h>
+#include <net/gen/netdb.h>
+
+extern int _net_stayopen;
+
+struct netent *
+getnetbyname(name)
+	register const char *name;
+{
+	register struct netent *p;
+	register char **cp;
+
+	setnetent(_net_stayopen);
+	while (p = getnetent()) {
+		if (strcmp(p->n_name, name) == 0)
+			break;
+		for (cp = p->n_aliases; *cp != 0; cp++)
+			if (strcmp(*cp, name) == 0)
+				goto found;
+	}
+found:
+	if (!_net_stayopen)
+		endnetent();
+	return (p);
+}
Index: /trunk/minix/lib/ip/getnetent.c
===================================================================
--- /trunk/minix/lib/ip/getnetent.c	(revision 9)
+++ /trunk/minix/lib/ip/getnetent.c	(revision 9)
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 1983, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getnetent.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <net/gen/in.h>
+#include <net/gen/netdb.h>
+#include <net/gen/inet.h>
+#include <net/gen/socket.h>
+
+#define	MAXALIASES	35
+
+static FILE *netf;
+static char line[BUFSIZ+1];
+static struct netent net;
+static char *net_aliases[MAXALIASES];
+int _net_stayopen;
+
+void
+setnetent(f)
+	int f;
+{
+	if (netf == NULL)
+		netf = fopen(_PATH_NETWORKS, "r" );
+	else
+		rewind(netf);
+	_net_stayopen |= f;
+}
+
+void
+endnetent()
+{
+	if (netf) {
+		fclose(netf);
+		netf = NULL;
+	}
+	_net_stayopen = 0;
+}
+
+struct netent *
+getnetent()
+{
+	char *p;
+	register char *cp, **q;
+
+	if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL)
+		return (NULL);
+again:
+	p = fgets(line, BUFSIZ, netf);
+	if (p == NULL)
+		return (NULL);
+	if (*p == '#')
+		goto again;
+	cp = strpbrk(p, "#\n");
+	if (cp == NULL)
+		goto again;
+	*cp = '\0';
+	net.n_name = p;
+	cp = strpbrk(p, " \t");
+	if (cp == NULL)
+		goto again;
+	*cp++ = '\0';
+	while (*cp == ' ' || *cp == '\t')
+		cp++;
+	p = strpbrk(cp, " \t");
+	if (p != NULL)
+		*p++ = '\0';
+	net.n_net = inet_network(cp);
+	net.n_addrtype = AF_INET;
+	q = net.n_aliases = net_aliases;
+	if (p != NULL) 
+		cp = p;
+	while (cp && *cp) {
+		if (*cp == ' ' || *cp == '\t') {
+			cp++;
+			continue;
+		}
+		if (q < &net_aliases[MAXALIASES - 1])
+			*q++ = cp;
+		cp = strpbrk(cp, " \t");
+		if (cp != NULL)
+			*cp++ = '\0';
+	}
+	*q = NULL;
+	return (&net);
+}
Index: /trunk/minix/lib/ip/getpeername.c
===================================================================
--- /trunk/minix/lib/ip/getpeername.c	(revision 9)
+++ /trunk/minix/lib/ip/getpeername.c	(revision 9)
@@ -0,0 +1,70 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+static int _tcp_getpeername(int socket, struct sockaddr *_RESTRICT address,
+	socklen_t *_RESTRICT address_len, nwio_tcpconf_t *tcpconfp);
+
+int getpeername(int socket, struct sockaddr *_RESTRICT address,
+	socklen_t *_RESTRICT address_len)
+{
+	int r;
+	nwio_tcpconf_t tcpconf;
+
+	r= ioctl(socket, NWIOGTCPCONF, &tcpconf);
+	if (r != -1 || errno != ENOTTY)
+	{
+		if (r == -1)
+		{
+			/* Bad file descriptor */
+			return -1;
+		}
+		return _tcp_getpeername(socket, address, address_len,
+			&tcpconf);
+	}
+
+#if DEBUG
+	fprintf(stderr, "getpeername: not implemented for fd %d\n", socket);
+#endif
+	errno= ENOSYS;
+	return -1;
+}
+
+static int _tcp_getpeername(int socket, struct sockaddr *_RESTRICT address,
+	socklen_t *_RESTRICT address_len, nwio_tcpconf_t *tcpconfp)
+{
+	socklen_t len;
+	struct sockaddr_in sin;
+
+	if (tcpconfp->nwtc_remaddr == 0 ||
+		tcpconfp->nwtc_remport == 0)
+	{
+		errno= ENOTCONN;
+		return -1;
+	}
+
+	memset(&sin, '\0', sizeof(sin));
+	sin.sin_family= AF_INET;
+	sin.sin_addr.s_addr= tcpconfp->nwtc_remaddr;
+	sin.sin_port= tcpconfp->nwtc_remport;
+
+	len= *address_len;
+	if (len > sizeof(sin))
+		len= sizeof(sin);
+	memcpy(address, &sin, len);
+	*address_len= len;
+
+	return 0;
+}
+
Index: /trunk/minix/lib/ip/getproto.c
===================================================================
--- /trunk/minix/lib/ip/getproto.c	(revision 9)
+++ /trunk/minix/lib/ip/getproto.c	(revision 9)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getproto.c	5.6 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stddef.h>
+
+#ifdef _MINIX
+#include <ansi.h>
+#include <net/gen/netdb.h>
+#endif
+
+extern int _proto_stayopen;
+
+struct protoent *
+getprotobynumber(proto)
+	register int proto;
+{
+	register struct protoent *p;
+
+	setprotoent(_proto_stayopen);
+	while (p = getprotoent())
+		if (p->p_proto == proto)
+			break;
+	if (!_proto_stayopen)
+		endprotoent();
+	return (p);
+}
Index: /trunk/minix/lib/ip/getprotoent.c
===================================================================
--- /trunk/minix/lib/ip/getprotoent.c	(revision 9)
+++ /trunk/minix/lib/ip/getprotoent.c	(revision 9)
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getprotoent.c	5.7 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef _MINIX
+#include <net/gen/netdb.h>
+
+static char *any _ARGS(( char *cp, char *match ));
+#endif
+
+#define	MAXALIASES	35
+
+static FILE *protof = NULL;
+static char line[BUFSIZ+1];
+static struct protoent proto;
+static char *proto_aliases[MAXALIASES];
+int _proto_stayopen;
+
+void
+setprotoent(f)
+	int f;
+{
+	if (protof == NULL)
+		protof = fopen(_PATH_PROTOCOLS, "r" );
+	else
+		rewind(protof);
+	_proto_stayopen |= f;
+}
+
+void
+endprotoent()
+{
+	if (protof) {
+		fclose(protof);
+		protof = NULL;
+	}
+	_proto_stayopen = 0;
+}
+
+struct protoent *
+getprotoent()
+{
+	char *p;
+	register char *cp, **q;
+
+	if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL)
+		return (NULL);
+again:
+	if ((p = fgets(line, BUFSIZ, protof)) == NULL)
+		return (NULL);
+	if (*p == '#')
+		goto again;
+	cp = any(p, "#\n");
+	if (cp == NULL)
+		goto again;
+	*cp = '\0';
+	proto.p_name = p;
+	cp = any(p, " \t");
+	if (cp == NULL)
+		goto again;
+	*cp++ = '\0';
+	while (*cp == ' ' || *cp == '\t')
+		cp++;
+	p = any(cp, " \t");
+	if (p != NULL)
+		*p++ = '\0';
+	proto.p_proto = atoi(cp);
+	q = proto.p_aliases = proto_aliases;
+	if (p != NULL) {
+		cp = p;
+		while (cp && *cp) {
+			if (*cp == ' ' || *cp == '\t') {
+				cp++;
+				continue;
+			}
+			if (q < &proto_aliases[MAXALIASES - 1])
+				*q++ = cp;
+			cp = any(cp, " \t");
+			if (cp != NULL)
+				*cp++ = '\0';
+		}
+	}
+	*q = NULL;
+	return (&proto);
+}
+
+static char *
+any(cp, match)
+	register char *cp;
+	char *match;
+{
+	register char *mp, c;
+
+	while (c = *cp) {
+		for (mp = match; *mp; mp++)
+			if (*mp == c)
+				return (cp);
+		cp++;
+	}
+	return ((char *)0);
+}
Index: /trunk/minix/lib/ip/getprotoname.c
===================================================================
--- /trunk/minix/lib/ip/getprotoname.c	(revision 9)
+++ /trunk/minix/lib/ip/getprotoname.c	(revision 9)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1983, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getprotoname.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <netdb.h>
+#include <string.h>
+
+extern int _proto_stayopen;
+
+struct protoent *
+getprotobyname(name)
+	register const char *name;
+{
+	register struct protoent *p;
+	register char **cp;
+
+	setprotoent(_proto_stayopen);
+	while ( (p = getprotoent()) ) {
+		if (strcmp(p->p_name, name) == 0)
+			break;
+		for (cp = p->p_aliases; *cp != 0; cp++)
+			if (strcmp(*cp, name) == 0)
+				goto found;
+	}
+found:
+	if (!_proto_stayopen)
+		endprotoent();
+	return (p);
+}
Index: /trunk/minix/lib/ip/getservent.c
===================================================================
--- /trunk/minix/lib/ip/getservent.c	(revision 9)
+++ /trunk/minix/lib/ip/getservent.c	(revision 9)
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getservent.c	5.8 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <net/hton.h>
+#include <net/gen/netdb.h>
+
+#define	MAXALIASES	35
+
+static FILE *servf = NULL;
+static char line[BUFSIZ+1];
+static struct servent serv;
+static char *serv_aliases[MAXALIASES];
+int _serv_stayopen;
+
+static char *any _ARGS(( char *cp, char *match ));
+
+void
+setservent(f)
+	int f;
+{
+	if (servf == NULL)
+		servf = fopen(_PATH_SERVICES, "r" );
+	else
+		rewind(servf);
+	_serv_stayopen |= f;
+}
+
+void
+endservent()
+{
+	if (servf) {
+		fclose(servf);
+		servf = NULL;
+	}
+	_serv_stayopen = 0;
+}
+
+struct servent *
+getservent()
+{
+	char *p;
+	register char *cp, **q;
+
+	if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL)
+		return (NULL);
+again:
+	if ((p = fgets(line, BUFSIZ, servf)) == NULL)
+		return (NULL);
+	if (*p == '#')
+		goto again;
+	cp = any(p, "#\n");
+	if (cp == NULL)
+		goto again;
+	*cp = '\0';
+	serv.s_name = p;
+	p = any(p, " \t");
+	if (p == NULL)
+		goto again;
+	*p++ = '\0';
+	while (*p == ' ' || *p == '\t')
+		p++;
+	cp = any(p, ",/");
+	if (cp == NULL)
+		goto again;
+	*cp++ = '\0';
+	serv.s_port = htons((u16_t)atoi(p));
+	serv.s_proto = cp;
+	q = serv.s_aliases = serv_aliases;
+	cp = any(cp, " \t");
+	if (cp != NULL)
+		*cp++ = '\0';
+	while (cp && *cp) {
+		if (*cp == ' ' || *cp == '\t') {
+			cp++;
+			continue;
+		}
+		if (q < &serv_aliases[MAXALIASES - 1])
+			*q++ = cp;
+		cp = any(cp, " \t");
+		if (cp != NULL)
+			*cp++ = '\0';
+	}
+	*q = NULL;
+	return (&serv);
+}
+
+static char *
+any(cp, match)
+	register char *cp;
+	char *match;
+{
+	register char *mp, c;
+
+	while (c = *cp) {
+		for (mp = match; *mp; mp++)
+			if (*mp == c)
+				return (cp);
+		cp++;
+	}
+	return ((char *)0);
+}
Index: /trunk/minix/lib/ip/getsockname.c
===================================================================
--- /trunk/minix/lib/ip/getsockname.c	(revision 9)
+++ /trunk/minix/lib/ip/getsockname.c	(revision 9)
@@ -0,0 +1,79 @@
+/*
+
+   getsockname()
+
+   from socket emulation library for Minix 2.0.x
+
+*/
+
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+
+
+/*
+#define DEBUG 0
+*/
+
+/*
+   getsockname...
+*/
+int getsockname(int fd, struct sockaddr *_RESTRICT address, 
+   socklen_t *_RESTRICT address_len)
+{
+	nwio_tcpconf_t tcpconf;
+	socklen_t len;
+	struct sockaddr_in sin;
+
+#ifdef DEBUG
+	fprintf(stderr,"mnx_getsockname: ioctl fd %d.\n", fd);
+#endif
+	if (ioctl(fd, NWIOGTCPCONF, &tcpconf)==-1) {
+#ifdef DEBUG
+	   fprintf(stderr,"mnx_getsockname: error %d\n", errno);
+#endif
+	   return (-1);
+	   }
+#ifdef DEBUG1
+	fprintf(stderr, "mnx_getsockname: from %s, %u",
+			inet_ntoa(tcpconf.nwtc_remaddr),
+			ntohs(tcpconf.nwtc_remport));
+	fprintf(stderr," for %s, %u\n",
+			inet_ntoa(tcpconf.nwtc_locaddr),
+			ntohs(tcpconf.nwtc_locport));
+#endif
+/*
+	addr->sin_addr.s_addr = tcpconf.nwtc_remaddr ;
+	addr->sin_port = tcpconf.nwtc_locport;
+*/
+	memset(&sin, '\0', sizeof(sin));
+	sin.sin_family= AF_INET;
+	sin.sin_addr.s_addr= tcpconf.nwtc_locaddr ;
+	sin.sin_port= tcpconf.nwtc_locport;
+
+	len= *address_len;
+	if (len > sizeof(sin))
+		len= sizeof(sin);
+	memcpy(address, &sin, len);
+	*address_len= len;
+
+	return 0;
+}
+
+
+
+
+
+
+
+
Index: /trunk/minix/lib/ip/getsockopt.c
===================================================================
--- /trunk/minix/lib/ip/getsockopt.c	(revision 9)
+++ /trunk/minix/lib/ip/getsockopt.c	(revision 9)
@@ -0,0 +1,141 @@
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/tcp.h>
+
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+static int _tcp_getsockopt(int socket, int level, int option_name,
+	void *_RESTRICT option_value, socklen_t *_RESTRICT option_len);
+static int _udp_getsockopt(int socket, int level, int option_name,
+	void *_RESTRICT option_value, socklen_t *_RESTRICT option_len);
+
+int getsockopt(int socket, int level, int option_name,
+        void *_RESTRICT option_value, socklen_t *_RESTRICT option_len)
+{
+	int r;
+	nwio_tcpopt_t tcpopt;
+	nwio_udpopt_t udpopt;
+
+	r= ioctl(socket, NWIOGTCPOPT, &tcpopt);
+	if (r != -1 || errno != ENOTTY)
+	{
+		if (r == -1)
+		{
+			/* Bad file descriptor */
+			return -1;
+		}
+		return _tcp_getsockopt(socket, level, option_name,
+			option_value, option_len);
+	}
+
+	r= ioctl(socket, NWIOGUDPOPT, &udpopt);
+	if (r != -1 || errno != ENOTTY)
+	{
+		if (r == -1)
+		{
+			/* Bad file descriptor */
+			return -1;
+		}
+		return _udp_getsockopt(socket, level, option_name,
+			option_value, option_len);
+	}
+
+#if DEBUG
+	fprintf(stderr, "getsockopt: not implemented for fd %d\n", socket);
+#endif
+	errno= ENOTSOCK;
+	return -1;
+}
+
+static int _tcp_getsockopt(int socket, int level, int option_name,
+	void *_RESTRICT option_value, socklen_t *_RESTRICT option_len)
+{
+	int i, r, err;
+
+	if (level == SOL_SOCKET && option_name == SO_KEEPALIVE)
+	{
+		i= 1;	/* Keepalive is always on */
+		if (*option_len < sizeof(i))
+			memcpy(option_value, &i, *option_len);
+		else
+			memcpy(option_value, &i, sizeof(i));
+		*option_len= sizeof(i);
+		return 0;
+	}
+	if (level == SOL_SOCKET && option_name == SO_ERROR)
+	{
+		r= ioctl(socket, NWIOTCPGERROR, &err);
+		if (r != 0)
+			return r;
+		if (*option_len < sizeof(err))
+			memcpy(option_value, &err, *option_len);
+		else
+			memcpy(option_value, &err, sizeof(err));
+		*option_len= sizeof(err);
+		return 0;
+	}
+	if (level == SOL_SOCKET && option_name == SO_RCVBUF)
+	{
+		i= 32*1024;	/* Receive buffer in the current
+				 * implementation
+				 */
+		if (*option_len < sizeof(i))
+			memcpy(option_value, &i, *option_len);
+		else
+			memcpy(option_value, &i, sizeof(i));
+		*option_len= sizeof(i);
+		return 0;
+	}
+	if (level == SOL_SOCKET && option_name == SO_SNDBUF)
+	{
+		i= 32*1024;	/* Send buffer in the current implementation */
+		if (*option_len < sizeof(i))
+			memcpy(option_value, &i, *option_len);
+		else
+			memcpy(option_value, &i, sizeof(i));
+		*option_len= sizeof(i);
+		return 0;
+	}
+	if (level == IPPROTO_TCP && option_name == TCP_NODELAY)
+	{
+		i= 0;	/* nodelay is always off */
+		if (*option_len < sizeof(i))
+			memcpy(option_value, &i, *option_len);
+		else
+			memcpy(option_value, &i, sizeof(i));
+		*option_len= sizeof(i);
+		return 0;
+	}
+#if DEBUG
+	fprintf(stderr, "_tcp_getsocketopt: level %d, name %d\n",
+		level, option_name);
+#endif
+
+	errno= ENOPROTOOPT;
+	return -1;
+}
+
+static int _udp_getsockopt(int socket, int level, int option_name,
+	void *_RESTRICT option_value, socklen_t *_RESTRICT option_len)
+{
+	int i;
+
+#if DEBUG
+	fprintf(stderr, "_udp_getsocketopt: level %d, name %d\n",
+		level, option_name);
+#endif
+
+	errno= ENOSYS;
+	return -1;
+}
Index: /trunk/minix/lib/ip/getsrvbyname.c
===================================================================
--- /trunk/minix/lib/ip/getsrvbyname.c	(revision 9)
+++ /trunk/minix/lib/ip/getsrvbyname.c	(revision 9)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getservbyname.c	5.6 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
+#include <string.h>
+
+#include <net/gen/netdb.h>
+
+extern int _serv_stayopen;
+
+struct servent *
+getservbyname(name, proto)
+	const char *name, *proto;
+{
+	register struct servent *p;
+	register char **cp;
+
+	setservent(_serv_stayopen);
+	while (p = getservent()) {
+		if (strcmp(name, p->s_name) == 0)
+			goto gotname;
+		for (cp = p->s_aliases; *cp; cp++)
+			if (strcmp(name, *cp) == 0)
+				goto gotname;
+		continue;
+gotname:
+		if (proto == 0 || strcmp(p->s_proto, proto) == 0)
+			break;
+	}
+	if (!_serv_stayopen)
+		endservent();
+	return (p);
+}
Index: /trunk/minix/lib/ip/getsrvbyport.c
===================================================================
--- /trunk/minix/lib/ip/getsrvbyport.c	(revision 9)
+++ /trunk/minix/lib/ip/getsrvbyport.c	(revision 9)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getservbyport.c	5.6 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stddef.h>
+#include <string.h>
+
+#ifdef _MINIX
+#include <net/gen/netdb.h>
+#endif
+
+extern int _serv_stayopen;
+
+struct servent *
+getservbyport(port, proto)
+	int port;
+	const char *proto;
+{
+	register struct servent *p;
+
+	setservent(_serv_stayopen);
+	while (p = getservent()) {
+		if (p->s_port != port)
+			continue;
+		if (proto == 0 || strcmp(p->s_proto, proto) == 0)
+			break;
+	}
+	if (!_serv_stayopen)
+		endservent();
+	return (p);
+}
Index: /trunk/minix/lib/ip/hton.c
===================================================================
--- /trunk/minix/lib/ip/hton.c	(revision 9)
+++ /trunk/minix/lib/ip/hton.c	(revision 9)
@@ -0,0 +1,18 @@
+/*
+hton.c
+*/
+
+#include <sys/types.h>
+#include <minix/config.h>
+#include <net/hton.h>
+
+u16_t _tmp;
+u32_t _tmp_l;
+
+#if _WORD_SIZE > 2
+u16_t (htons)(u16_t x) { return HTONS(x); }
+u16_t (ntohs)(u16_t x) { return NTOHS(x); }
+u32_t (htonl)(u32_t x) { return HTONL(x); }
+u32_t (ntohl)(u32_t x) { return NTOHL(x); }
+#endif
+
Index: /trunk/minix/lib/ip/inet_addr.c
===================================================================
--- /trunk/minix/lib/ip/inet_addr.c	(revision 9)
+++ /trunk/minix/lib/ip/inet_addr.c	(revision 9)
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 1983, 1990 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted provided
+ * that: (1) source distributions retain this entire copyright notice and
+ * comment, and (2) distributions including binaries display the following
+ * acknowledgement:  ``This product includes software developed by the
+ * University of California, Berkeley and its contributors'' in the
+ * documentation or other materials provided with the distribution and in
+ * all advertising materials mentioning features or use of this software.
+ * Neither the name of the University nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)inet_addr.c	5.8 (Berkeley) 6/23/90";
+#endif /* LIBC_SCCS and not lint */
+
+#if _MINIX
+#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#endif
+
+#ifdef __STDC__
+#define _CONST	const
+#else
+#define _CONST
+#endif
+
+/*
+ * Ascii internet address interpretation routine.
+ * The value returned is in network order.
+ */
+ipaddr_t
+inet_addr(cp)
+	register _CONST char *cp;
+{
+	ipaddr_t val;
+
+	if (inet_aton(cp, &val))
+		return (val);
+	errno= EINVAL;
+	return (ipaddr_t)-1;
+}
+
+/* 
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+
+int
+inet_aton(cp, addr)
+	register _CONST char *cp;
+	ipaddr_t *addr;
+{
+	register u32_t val, base, n;
+	register char c;
+	u32_t parts[4], *pp = parts;
+
+	for (;;) {
+		/*
+		 * Collect number up to ``.''.
+		 * Values are specified as for C:
+		 * 0x=hex, 0=octal, other=decimal.
+		 */
+		val = 0; base = 10;
+		if (*cp == '0') {
+			if (*++cp == 'x' || *cp == 'X')
+				base = 16, cp++;
+			else
+				base = 8;
+		}
+		while ((c = *cp) != '\0') {
+			if (isascii(c) && isdigit(c)) {
+				val = (val * base) + (c - '0');
+				cp++;
+				continue;
+			}
+			if (base == 16 && isascii(c) && isxdigit(c)) {
+				val = (val << 4) + 
+					(c + 10 - (islower(c) ? 'a' : 'A'));
+				cp++;
+				continue;
+			}
+			break;
+		}
+		if (*cp == '.') {
+			/*
+			 * Internet format:
+			 *	a.b.c.d
+			 *	a.b.c	(with c treated as 16-bits)
+			 *	a.b	(with b treated as 24 bits)
+			 */
+			if (pp >= parts + 3 || val > 0xff)
+				return (0);
+			*pp++ = val, cp++;
+		} else
+			break;
+	}
+	/*
+	 * Check for trailing characters.
+	 */
+	if (*cp && (!isascii(*cp) || !isspace(*cp)))
+		return (0);
+	/*
+	 * Concoct the address according to
+	 * the number of parts specified.
+	 */
+	n = pp - parts + 1;
+	switch (n) {
+
+	case 1:				/* a -- 32 bits */
+		break;
+
+	case 2:				/* a.b -- 8.24 bits */
+		if (val > 0xffffff)
+			return (0);
+		val |= parts[0] << 24;
+		break;
+
+	case 3:				/* a.b.c -- 8.8.16 bits */
+		if (val > 0xffff)
+			return (0);
+		val |= (parts[0] << 24) | (parts[1] << 16);
+		break;
+
+	case 4:				/* a.b.c.d -- 8.8.8.8 bits */
+		if (val > 0xff)
+			return (0);
+		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+		break;
+	}
+	if (addr)
+		*addr = htonl(val);
+	return (1);
+}
Index: /trunk/minix/lib/ip/inet_network.c
===================================================================
--- /trunk/minix/lib/ip/inet_network.c	(revision 9)
+++ /trunk/minix/lib/ip/inet_network.c	(revision 9)
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 1983, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)inet_network.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+
+#define INADDR_NONE	((ipaddr_t) -1)
+
+/*
+ * Internet network address interpretation routine.
+ * The library routines call this routine to interpret
+ * network numbers.
+ */
+ipaddr_t
+inet_network(cp)
+	register const char *cp;
+{
+	register ipaddr_t val, base, n;
+	register char c;
+	ipaddr_t parts[4], *pp = parts;
+	register int i;
+
+again:
+	val = 0; base = 10;
+	if (*cp == '0')
+		base = 8, cp++;
+	if (*cp == 'x' || *cp == 'X')
+		base = 16, cp++;
+	while (c = *cp) {
+		if (isdigit(c)) {
+			val = (val * base) + (c - '0');
+			cp++;
+			continue;
+		}
+		if (base == 16 && isxdigit(c)) {
+			val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
+			cp++;
+			continue;
+		}
+		break;
+	}
+	if (*cp == '.') {
+		if (pp >= parts + 4)
+			return (INADDR_NONE);
+		*pp++ = val, cp++;
+		goto again;
+	}
+	if (*cp && !isspace(*cp))
+		return (INADDR_NONE);
+	*pp++ = val;
+	n = pp - parts;
+	if (n > 4)
+		return (INADDR_NONE);
+	for (val = 0, i = 0; i < n; i++) {
+		val <<= 8;
+		val |= parts[i] & 0xff;
+	}
+	return (val);
+}
Index: /trunk/minix/lib/ip/inet_ntoa.c
===================================================================
--- /trunk/minix/lib/ip/inet_ntoa.c	(revision 9)
+++ /trunk/minix/lib/ip/inet_ntoa.c	(revision 9)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)inet_ntoa.c	5.5 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Convert network-format internet address
+ * to base 256 d.d.d.d representation.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+
+char *
+inet_ntoa(in)
+	ipaddr_t in;
+{
+	static char b[18];
+	register u8_t *p;
+
+	p = (u8_t *)&in;
+	sprintf(b, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+	return (b);
+}
Index: /trunk/minix/lib/ip/listen.c
===================================================================
--- /trunk/minix/lib/ip/listen.c	(revision 9)
+++ /trunk/minix/lib/ip/listen.c	(revision 9)
@@ -0,0 +1,30 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+int listen(int socket, int backlog)
+{
+	int r;
+
+	r= ioctl(socket, NWIOTCPLISTENQ, &backlog);
+	if (r != -1 || errno != EBADIOCTL)
+		return r;
+
+#if DEBUG
+	fprintf(stderr, "listen: not implemented for fd %d\n", socket);
+#endif
+	errno= ENOSYS;
+	return -1;
+}
+
Index: /trunk/minix/lib/ip/memcspn.c
===================================================================
--- /trunk/minix/lib/ip/memcspn.c	(revision 9)
+++ /trunk/minix/lib/ip/memcspn.c	(revision 9)
@@ -0,0 +1,22 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/ip/memcspn.c,v 1.1.1.1 2005/04/21 14:56:18 beng Exp $ */
+
+#include	<string.h>
+
+size_t
+memcspn(const char *string, size_t strlen, const char *notin, size_t notinlen)
+{
+	register const char *s1, *s2;
+	int i,j;
+
+	for (s1 = string, i = 0; i<strlen; s1++, i++) {
+		for(s2 = notin, j = 0; *s2 != *s1 && j < notinlen; s2++, j++)
+			/* EMPTY */ ;
+		if (j != notinlen)
+			break;
+	}
+	return s1 - string;
+}
Index: /trunk/minix/lib/ip/oneC_sum.c
===================================================================
--- /trunk/minix/lib/ip/oneC_sum.c	(revision 9)
+++ /trunk/minix/lib/ip/oneC_sum.c	(revision 9)
@@ -0,0 +1,61 @@
+/*	oneC_sum() - One complement's checksum		Author: Kees J. Bot
+ *								8 May 1995
+ * See RFC 1071, "Computing the Internet checksum"
+ */
+
+#include <sys/types.h>
+#include <net/gen/oneCsum.h>
+
+u16_t oneC_sum(U16_t prev, void *data, size_t size)
+{
+	u8_t *dptr;
+	size_t n;
+	u16_t word;
+	u32_t sum;
+	int swap= 0;
+
+	sum= prev;
+	dptr= data;
+	n= size;
+
+	swap= ((size_t) dptr & 1);
+	if (swap) {
+		sum= ((sum & 0xFF) << 8) | ((sum & 0xFF00) >> 8);
+		if (n > 0) {
+			((u8_t *) &word)[0]= 0;
+			((u8_t *) &word)[1]= dptr[0];
+			sum+= (u32_t) word;
+			dptr+= 1;
+			n-= 1;
+		}
+	}
+
+	while (n >= 8) {
+		sum+= (u32_t) ((u16_t *) dptr)[0]
+		    + (u32_t) ((u16_t *) dptr)[1]
+		    + (u32_t) ((u16_t *) dptr)[2]
+		    + (u32_t) ((u16_t *) dptr)[3];
+		dptr+= 8;
+		n-= 8;
+	}
+
+	while (n >= 2) {
+		sum+= (u32_t) ((u16_t *) dptr)[0];
+		dptr+= 2;
+		n-= 2;
+	}
+
+	if (n > 0) {
+		((u8_t *) &word)[0]= dptr[0];
+		((u8_t *) &word)[1]= 0;
+		sum+= (u32_t) word;
+	}
+
+	sum= (sum & 0xFFFF) + (sum >> 16);
+	if (sum > 0xFFFF) sum++;
+
+	if (swap) {
+		sum= ((sum & 0xFF) << 8) | ((sum & 0xFF00) >> 8);
+	}
+	return sum;
+}
Index: /trunk/minix/lib/ip/rcmd.c
===================================================================
--- /trunk/minix/lib/ip/rcmd.c	(revision 9)
+++ /trunk/minix/lib/ip/rcmd.c	(revision 9)
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rcmd.c	5.22 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/hton.h>
+#include <net/netlib.h>
+
+#define MAXHOSTNAMELEN	256
+#define MAXPATHLEN PATH_MAX
+
+#ifdef __STDC__
+#define CONST	const
+#else
+#define CONST
+#endif
+
+extern	errno;
+
+int rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
+char **ahost;
+int rport;
+CONST char *locuser, *remuser, *cmd;
+int *fd2p;
+{
+	int fd, fd2, result;
+	struct hostent *hp;
+	int n;
+	static tcpport_t lport;
+	nwio_tcpconf_t tcpconf;
+	nwio_tcpcl_t tcpconnopt;
+	pid_t pid;
+	char num[8];
+	char c;
+	char *tcp_device;
+
+	fd= -1;
+	fd2= -1;
+
+	if (lport == 0) {
+		pid = getpid();
+		lport = 1;
+		do {
+			lport = (lport << 1) | (pid & 1);
+
+			pid >>= 1;
+		} while (lport < TCPPORT_RESERVED/2);
+	}
+
+	tcp_device= getenv("TCP_DEVICE");
+	if (tcp_device == NULL)
+		tcp_device= TCP_DEVICE;
+	hp= gethostbyname(*ahost);
+	if (!hp)
+	{
+		fprintf(stderr, "%s: unknown host\n", *ahost);
+		return -1;
+	}
+	*ahost= hp->h_name;
+	n = TCPPORT_RESERVED/2;
+	do
+	{
+		if (--lport < TCPPORT_RESERVED/2)
+			lport = TCPPORT_RESERVED-1;
+		fd= open (tcp_device, O_RDWR);
+		if (fd<0)
+		{
+			fprintf(stderr, "unable to open %s: %s\n",
+				tcp_device, strerror(errno));
+			goto bad;
+		}
+		tcpconf.nwtc_flags= NWTC_LP_SET | NWTC_SET_RA | NWTC_SET_RP |
+			NWTC_EXCL;
+		tcpconf.nwtc_locport= htons(lport);
+		tcpconf.nwtc_remport= rport;
+		tcpconf.nwtc_remaddr= *(ipaddr_t *)hp->h_addr;
+
+		result= ioctl(fd, NWIOSTCPCONF, &tcpconf);
+		if (result<0)
+		{
+			if (errno == EADDRINUSE)
+			{
+				close(fd);
+				continue;
+			}
+			fprintf(stderr, "unable to ioctl(NWIOSTCPCONF): %s\n",
+				strerror(errno));
+			goto bad;
+		}
+		tcpconf.nwtc_flags= NWTC_SHARED;
+		result= ioctl(fd, NWIOSTCPCONF, &tcpconf);
+		if (result<0)
+		{
+			fprintf(stderr, "unable to ioctl(NWIOSTCPCONF): %s\n",
+				strerror(errno));
+			goto bad;
+		}
+		tcpconnopt.nwtcl_flags= 0;
+
+		do
+		{
+			result= ioctl (fd, NWIOTCPCONN, &tcpconnopt);
+			if (result<0 && errno == EAGAIN)
+			{
+				sleep(2);
+			}
+		} while (result<0 && errno == EAGAIN);
+		if (result<0 && errno != EADDRINUSE)
+		{
+			fprintf(stderr,
+				"unable to ioctl(NWIOTCPCONN): %s\n",
+				strerror(errno));
+			goto bad;
+		}
+		if (result>=0)
+			break;
+	} while (--n > 0);
+	if (n == 0)
+	{
+		fprintf(stderr, "can't get port\n");
+		return -1;
+	}
+	if (!fd2p)
+	{
+		if (write(fd, "", 1) != 1)
+		{
+			fprintf(stderr, "unable to write: %s", strerror(errno));
+			goto bad;
+		}
+	}
+	else
+	{
+		fd2= open (tcp_device, O_RDWR);
+		if (fd2<0)
+		{
+			fprintf(stderr, "unable to open %s: %s\n",
+				tcp_device, strerror(errno));
+			goto bad;
+		}
+		tcpconf.nwtc_flags= NWTC_LP_SET | NWTC_UNSET_RA | 
+			NWTC_UNSET_RP | NWTC_SHARED;
+		tcpconf.nwtc_locport= htons(lport);
+
+		result= ioctl(fd2, NWIOSTCPCONF, &tcpconf);
+		if (result<0)
+		{
+			fprintf(stderr,
+				"unable to ioctl(NWIOSTCPCONF): %s\n",
+				strerror(errno));
+			goto bad;
+		}
+		pid= fork();
+		if (pid<0)
+		{
+			fprintf(stderr, "unable to fork: %s\n",
+				strerror(errno));
+			goto bad;
+		}
+		if (!pid)
+		{
+			alarm(0);
+			signal(SIGALRM, SIG_DFL);
+			alarm(30); /* give up after half a minute */
+			tcpconnopt.nwtcl_flags= 0;
+
+			do
+			{
+				result= ioctl (fd2, NWIOTCPLISTEN,
+					&tcpconnopt);
+				if (result<0 && errno == EAGAIN)
+				{
+					sleep(2);
+				}
+			} while (result<0 && errno == EAGAIN);
+			if (result<0 && errno != EADDRINUSE)
+			{
+				fprintf(stderr,
+					"unable to ioctl(NWIOTCPLISTEN): %s\n",
+					strerror(errno));
+				exit(1);
+			}
+			if (result>=0)
+				exit(0);
+			else
+				exit(1);
+		}
+		/*
+		 * This sleep is a HACK.  The command that we are starting
+		 * will try to connect to the fd2 port.  It seems that for
+		 * this to succeed the child process must have already made
+		 * the call to ioctl above (the NWIOTCPLISTEN) call.
+		 * The sleep gives the child a chance to make the call
+		 * before the parent sends the port number to the
+		 * command being started.
+		 */
+		sleep(1);
+
+		sprintf(num, "%d", lport);
+		if (write(fd, num, strlen(num)+1) != strlen(num)+1)
+		{
+			fprintf(stderr, "unable to write: %s\n",
+				strerror(errno));
+			goto bad;
+		}
+
+	}
+	write (fd, locuser, strlen(locuser)+1);
+	write (fd, remuser, strlen(remuser)+1);
+	write (fd, cmd, strlen(cmd)+1);
+	if (read(fd, &c, 1) != 1)
+	{
+		fprintf(stderr, "unable to read: %s\n", strerror(errno) );
+		goto bad;
+	}
+	if (c != 0)
+	{
+		while (read(fd, &c, 1) == 1)
+		{
+			write(2, &c, 1);
+			if (c == '\n')
+				break;
+		}
+		goto bad;
+	}
+	if (fd2p)
+	{
+		*fd2p= fd2;
+		result= ioctl(fd2, NWIOGTCPCONF, &tcpconf);
+		if (result<0)
+		{
+			fprintf(stderr, "unable to ioctl(NWIOGTCPCONF): %s\n",
+				strerror(errno) );
+			goto bad;
+		}
+		if (ntohs(tcpconf.nwtc_remport) >= TCPPORT_RESERVED)
+		{
+			fprintf(stderr, "unable to setup 2nd channel\n");
+			goto bad;
+		}
+	}
+	return fd;
+
+bad:
+	if (fd>=0)
+		close(fd);
+	if (fd2>=0)
+		close(fd2);
+	return -1;
+}
Index: /trunk/minix/lib/ip/recv.c
===================================================================
--- /trunk/minix/lib/ip/recv.c	(revision 9)
+++ /trunk/minix/lib/ip/recv.c	(revision 9)
@@ -0,0 +1,8 @@
+#include <stdlib.h>
+#include <sys/socket.h>
+
+ssize_t recv(int socket, void *buffer, size_t length, int flags)
+{
+	return recvfrom(socket, buffer, length, flags, NULL, NULL);
+}
+
Index: /trunk/minix/lib/ip/recvfrom.c
===================================================================
--- /trunk/minix/lib/ip/recvfrom.c	(revision 9)
+++ /trunk/minix/lib/ip/recvfrom.c	(revision 9)
@@ -0,0 +1,125 @@
+#undef NDEBUG
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/gen/in.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+static ssize_t _udp_recvfrom(int socket, void *_RESTRICT buffer, size_t length,
+	int flags, struct sockaddr *_RESTRICT address,
+	socklen_t *_RESTRICT address_len, nwio_udpopt_t *udpoptp);
+
+ssize_t recvfrom(int socket, void *_RESTRICT buffer, size_t length,
+	int flags, struct sockaddr *_RESTRICT address,
+	socklen_t *_RESTRICT address_len)
+{
+	int r;
+	nwio_udpopt_t udpopt;
+
+	fprintf(stderr, "recvfrom: for fd %d\n", socket);
+
+	r= ioctl(socket, NWIOGUDPOPT, &udpopt);
+	if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
+	{
+		if (r == -1)
+			return r;
+		return _udp_recvfrom(socket, buffer, length, flags,
+			address, address_len, &udpopt);
+	}
+
+#if DEBUG
+	fprintf(stderr, "recvfrom: not implemented for fd %d\n", socket);
+#endif
+	errno= ENOSYS;
+	assert(0);
+	return -1;
+}
+
+static ssize_t _udp_recvfrom(int socket, void *_RESTRICT buffer, size_t length,
+	int flags, struct sockaddr *_RESTRICT address,
+	socklen_t *_RESTRICT address_len, nwio_udpopt_t *udpoptp)
+{
+	int r, t_errno;
+	size_t buflen, len;
+	void *buf;
+	struct sockaddr_in *sinp;
+	udp_io_hdr_t *io_hdrp;
+	struct sockaddr_in sin;
+
+	if (flags)
+	{
+#if DEBUG
+		fprintf(stderr, "recvfrom(udp): flags not implemented\n");
+#endif
+		errno= ENOSYS;
+		return -1;
+	}
+
+	if (udpoptp->nwuo_flags & NWUO_RWDATONLY)
+	{
+#if DEBUG
+		fprintf(stderr,
+			"recvfrom(udp): NWUO_RWDATONLY not implemented\n");
+#endif
+		errno= ENOSYS;
+		return -1;
+	}
+
+	buflen= sizeof(*io_hdrp) + length;
+	if (buflen < length)
+	{	
+		/* Overflow */
+		errno= EMSGSIZE;
+		return -1;
+	}
+	buf= malloc(buflen);
+	if (buf == NULL)
+		return -1;
+
+	r= read(socket, buf, buflen);
+	if (r == -1)
+	{
+		t_errno= errno;
+#if DEBUG
+		fprintf(stderr, "recvfrom(udp): read failed: %s\n",
+			strerror(errno));
+		fprintf(stderr, "udp opt flags = 0x%x\n", udpoptp->nwuo_flags);
+#endif
+		free(buf);
+		errno= t_errno;
+		return -1;
+	}
+
+	assert(r >= sizeof(*io_hdrp));
+	length= r-sizeof(*io_hdrp);
+
+	io_hdrp= buf;
+	memcpy(buffer, &io_hdrp[1], length);
+
+	if (address != NULL)
+	{
+		sin.sin_family= AF_INET;
+		sin.sin_addr.s_addr= io_hdrp->uih_src_addr;
+		sin.sin_port= io_hdrp->uih_src_port;
+		len= *address_len;
+		if (len > sizeof(sin))
+			len= sizeof(sin);
+		memcpy(address, &sin, len);
+		*address_len= sizeof(sin);
+	}	
+	free(buf);
+	return length;
+}
+
Index: /trunk/minix/lib/ip/res_comp.c
===================================================================
--- /trunk/minix/lib/ip/res_comp.c	(revision 9)
+++ /trunk/minix/lib/ip/res_comp.c	(revision 9)
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 1985 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted provided
+ * that: (1) source distributions retain this entire copyright notice and
+ * comment, and (2) distributions including binaries display the following
+ * acknowledgement:  ``This product includes software developed by the
+ * University of California, Berkeley and its contributors'' in the
+ * documentation or other materials provided with the distribution and in
+ * all advertising materials mentioning features or use of this software.
+ * Neither the name of the University nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_comp.c	6.18 (Berkeley) 6/27/90";
+#endif /* LIBC_SCCS and not lint */
+
+#if _MINIX
+#include <sys/types.h>
+#include <stdlib.h>
+
+#include <net/gen/in.h>
+#include <net/gen/nameser.h>
+#include <net/gen/resolv.h>
+
+static int dn_find _ARGS(( const u_char *exp_dn, const u_char *msg,
+	u_char **dnptrs, u_char **lastdnptr ));
+int dn_skipname _ARGS(( const u_char *comp_dn, const u_char *eom ));
+
+#define getshort _getshort
+#define getlong _getlong
+#define putshort __putshort
+#define putlong __putlong
+#else
+#include <sys/types.h>
+#include <stdio.h>
+#include <arpa/nameser.h>
+
+static dn_find();
+#endif
+
+#ifdef __STDC__
+#define CONST	const
+#else
+#define CONST
+#endif
+
+/*
+ * Expand compressed domain name 'comp_dn' to full domain name.
+ * 'msg' is a pointer to the begining of the message,
+ * 'eomorig' points to the first location after the message,
+ * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
+ * Return size of compressed name or -1 if there was an error.
+ */
+dn_expand(msg, eomorig, comp_dn, exp_dn, length)
+	CONST u_char *msg, *eomorig, *comp_dn;
+	u_char *exp_dn;
+	int length;
+{
+	register CONST u_char *cp;
+	register u_char *dn;
+	register int n, c;
+	CONST u_char *eom;
+	int len = -1, checked = 0;
+
+	dn = exp_dn;
+	cp = comp_dn;
+	eom = exp_dn + length;
+	/*
+	 * fetch next label in domain name
+	 */
+	while (n = *cp++) {
+		/*
+		 * Check for indirection
+		 */
+		switch (n & INDIR_MASK) {
+		case 0:
+			if (dn != exp_dn) {
+				if (dn >= eom)
+					return (-1);
+				*dn++ = '.';
+			}
+			if (dn+n >= eom)
+				return (-1);
+			checked += n + 1;
+			while (--n >= 0) {
+				if ((c = *cp++) == '.') {
+					if (dn + n + 2 >= eom)
+						return (-1);
+					*dn++ = '\\';
+				}
+				*dn++ = c;
+				if (cp >= eomorig)	/* out of range */
+					return(-1);
+			}
+			break;
+
+		case INDIR_MASK:
+			if (len < 0)
+				len = cp - comp_dn + 1;
+			cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
+			if (cp < msg || cp >= eomorig)	/* out of range */
+				return(-1);
+			checked += 2;
+			/*
+			 * Check for loops in the compressed name;
+			 * if we've looked at the whole message,
+			 * there must be a loop.
+			 */
+			if (checked >= eomorig - msg)
+				return (-1);
+			break;
+
+		default:
+			return (-1);			/* flag error */
+		}
+	}
+	*dn = '\0';
+	if (len < 0)
+		len = cp - comp_dn;
+	return (len);
+}
+
+/*
+ * Compress domain name 'exp_dn' into 'comp_dn'.
+ * Return the size of the compressed name or -1.
+ * 'length' is the size of the array pointed to by 'comp_dn'.
+ * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
+ * is a pointer to the beginning of the message. The list ends with NULL.
+ * 'lastdnptr' is a pointer to the end of the arrary pointed to
+ * by 'dnptrs'. Side effect is to update the list of pointers for
+ * labels inserted into the message as we compress the name.
+ * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
+ * is NULL, we don't update the list.
+ */
+int
+dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
+	CONST u_char *exp_dn;
+	u_char *comp_dn;
+	int length;
+	u_char **dnptrs, **lastdnptr;
+{
+	register u_char *cp;
+	register CONST u_char *dn;
+	register int c, l;
+	u_char **cpp, **lpp, *sp, *eob;
+	u_char *msg;
+
+	dn = exp_dn;
+	cp = comp_dn;
+	eob = cp + length;
+	if (dnptrs != NULL) {
+		if ((msg = *dnptrs++) != NULL) {
+			for (cpp = dnptrs; *cpp != NULL; cpp++)
+				;
+			lpp = cpp;	/* end of list to search */
+		}
+	} else
+		msg = NULL;
+	for (c = *dn++; c != '\0'; ) {
+		/* look to see if we can use pointers */
+		if (msg != NULL) {
+			if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
+				if (cp+1 >= eob)
+					return (-1);
+				*cp++ = (l >> 8) | INDIR_MASK;
+				*cp++ = l % 256;
+				return (cp - comp_dn);
+			}
+			/* not found, save it */
+			if (lastdnptr != NULL && cpp < lastdnptr-1) {
+				*cpp++ = cp;
+				*cpp = NULL;
+			}
+		}
+		sp = cp++;	/* save ptr to length byte */
+		do {
+			if (c == '.') {
+				c = *dn++;
+				break;
+			}
+			if (c == '\\') {
+				if ((c = *dn++) == '\0')
+					break;
+			}
+			if (cp >= eob) {
+				if (msg != NULL)
+					*lpp = NULL;
+				return (-1);
+			}
+			*cp++ = c;
+		} while ((c = *dn++) != '\0');
+		/* catch trailing '.'s but not '..' */
+		if ((l = cp - sp - 1) == 0 && c == '\0') {
+			cp--;
+			break;
+		}
+		if (l <= 0 || l > MAXLABEL) {
+			if (msg != NULL)
+				*lpp = NULL;
+			return (-1);
+		}
+		*sp = l;
+	}
+	if (cp >= eob) {
+		if (msg != NULL)
+			*lpp = NULL;
+		return (-1);
+	}
+	*cp++ = '\0';
+	return (cp - comp_dn);
+}
+
+/*
+ * Skip over a compressed domain name. Return the size or -1.
+ */
+dn_skipname(comp_dn, eom)
+	CONST u_char *comp_dn, *eom;
+{
+	register CONST u_char *cp;
+	register int n;
+
+	cp = comp_dn;
+	while (cp < eom && (n = *cp++)) {
+		/*
+		 * check for indirection
+		 */
+		switch (n & INDIR_MASK) {
+		case 0:		/* normal case, n == len */
+			cp += n;
+			continue;
+		default:	/* illegal type */
+			return (-1);
+		case INDIR_MASK:	/* indirection */
+			cp++;
+		}
+		break;
+	}
+	return (cp - comp_dn);
+}
+
+/*
+ * Search for expanded name from a list of previously compressed names.
+ * Return the offset from msg if found or -1.
+ * dnptrs is the pointer to the first name on the list,
+ * not the pointer to the start of the message.
+ */
+static int
+dn_find(exp_dn, msg, dnptrs, lastdnptr)
+	CONST u_char *exp_dn, *msg;
+	u_char **dnptrs, **lastdnptr;
+{
+	CONST register u_char *dn, *cp;
+	register u_char **cpp;
+	register int n;
+	CONST u_char *sp;
+
+	for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
+		dn = exp_dn;
+		sp = cp = *cpp;
+		while (n = *cp++) {
+			/*
+			 * check for indirection
+			 */
+			switch (n & INDIR_MASK) {
+			case 0:		/* normal case, n == len */
+				while (--n >= 0) {
+					if (*dn == '.')
+						goto next;
+					if (*dn == '\\')
+						dn++;
+					if (*dn++ != *cp++)
+						goto next;
+				}
+				if ((n = *dn++) == '\0' && *cp == '\0')
+					return (sp - msg);
+				if (n == '.')
+					continue;
+				goto next;
+
+			default:	/* illegal type */
+				return (-1);
+
+			case INDIR_MASK:	/* indirection */
+				cp = msg + (((n & 0x3f) << 8) | *cp);
+			}
+		}
+		if (*dn == '\0')
+			return (sp - msg);
+	next:	;
+	}
+	return (-1);
+}
+
+/*
+ * Routines to insert/extract short/long's. Must account for byte
+ * order and non-alignment problems. This code at least has the
+ * advantage of being portable.
+ *
+ * used by sendmail.
+ */
+
+u16_t
+getshort(msgp)
+	CONST u8_t *msgp;
+{
+	return ((msgp[0] << 8) | (msgp[1] << 0));
+}
+
+u32_t
+getlong(msgp)
+	CONST u8_t *msgp;
+{
+	return (  ((u32_t) msgp[0] << 24)
+		| ((u32_t) msgp[1] << 16)
+		| ((u32_t) msgp[2] <<  8)
+		| ((u32_t) msgp[3] <<  0));
+}
+
+
+void
+putshort(s, msgp)
+	register U16_t s;
+	register u8_t *msgp;
+{
+
+	msgp[1] = s;
+	msgp[0] = s >> 8;
+}
+
+void
+putlong(l, msgp)
+	register u32_t l;
+	register u8_t *msgp;
+{
+
+	msgp[3] = l;
+	msgp[2] = (l >>= 8);
+	msgp[1] = (l >>= 8);
+	msgp[0] = l >> 8;
+}
Index: /trunk/minix/lib/ip/res_init.c
===================================================================
--- /trunk/minix/lib/ip/res_init.c	(revision 9)
+++ /trunk/minix/lib/ip/res_init.c	(revision 9)
@@ -0,0 +1,197 @@
+/*-
+ * Copyright (c) 1985, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted provided
+ * that: (1) source distributions retain this entire copyright notice and
+ * comment, and (2) distributions including binaries display the following
+ * acknowledgement:  ``This product includes software developed by the
+ * University of California, Berkeley and its contributors'' in the
+ * documentation or other materials provided with the distribution and in
+ * all advertising materials mentioning features or use of this software.
+ * Neither the name of the University nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_init.c	6.14 (Berkeley) 6/27/90";
+#endif /* LIBC_SCCS and not lint */
+
+#if _MINIX
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/nameser.h>
+#include <net/gen/netdb.h>
+#include <net/gen/resolv.h>
+#include <net/gen/socket.h>
+
+#define index(s,c) strchr(s,c)
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#endif
+
+/*
+ * Resolver state
+ */
+struct state _res;
+
+/*
+ * Set up default settings.  If the configuration file exist, the values
+ * there will have precedence.  Otherwise, the server address is set to
+ * 127.0.0.1 (localhost) and the default domain name comes from gethostname().
+ *
+ * The configuration file should only be used if you want to redefine your
+ * domain or run without a server on your machine.
+ *
+ * Return 0 if completes successfully, -1 on error
+ */
+int
+res_init()
+{
+	register FILE *fp;
+	register char *cp, **pp;
+	register int n;
+	char buf[BUFSIZ];
+	int haveenv = 0;
+	int havesearch = 0;
+	struct servent* servent;
+	u16_t nameserver_port;
+
+	/* Resolver state default settings */
+	_res.retrans = RES_TIMEOUT;	/* retransmition time interval */
+	_res.retry = 4;			/* number of times to retransmit */
+	_res.options = RES_DEFAULT;	/* options flags */
+	_res.nscount = 0;		/* number of name servers */
+	_res.defdname[0] = 0;		/* domain */
+
+	servent= getservbyname("domain", NULL);
+	if (!servent)
+	{
+		h_errno= NO_RECOVERY;
+		return -1;
+	}
+	nameserver_port= servent->s_port;
+
+	/* Allow user to override the local domain definition */
+	if ((cp = getenv("LOCALDOMAIN")) != NULL) {
+		(void)strncpy(_res.defdname, cp, sizeof(_res.defdname));
+		haveenv++;
+	}
+
+	if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
+	    /* read the config file */
+	    while (fgets(buf, sizeof(buf), fp) != NULL) {
+		/* read default domain name */
+		if (!strncmp(buf, "domain", sizeof("domain") - 1)) {
+		    if (haveenv)	/* skip if have from environ */
+			    continue;
+		    cp = buf + sizeof("domain") - 1;
+		    while (*cp == ' ' || *cp == '\t')
+			    cp++;
+		    if ((*cp == '\0') || (*cp == '\n'))
+			    continue;
+		    (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+		    if ((cp = index(_res.defdname, '\n')) != NULL)
+			    *cp = '\0';
+		    havesearch = 0;
+		    continue;
+		}
+		/* set search list */
+		if (!strncmp(buf, "search", sizeof("search") - 1)) {
+		    if (haveenv)	/* skip if have from environ */
+			    continue;
+		    cp = buf + sizeof("search") - 1;
+		    while (*cp == ' ' || *cp == '\t')
+			    cp++;
+		    if ((*cp == '\0') || (*cp == '\n'))
+			    continue;
+		    (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+		    if ((cp = index(_res.defdname, '\n')) != NULL)
+			    *cp = '\0';
+		    /*
+		     * Set search list to be blank-separated strings
+		     * on rest of line.
+		     */
+		    cp = _res.defdname;
+		    pp = _res.dnsrch;
+		    *pp++ = cp;
+		    for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
+			    if (*cp == ' ' || *cp == '\t') {
+				    *cp = 0;
+				    n = 1;
+			    } else if (n) {
+				    *pp++ = cp;
+				    n = 0;
+			    }
+		    }
+		    /* null terminate last domain if there are excess */
+		    while (*cp != '\0' && *cp != ' ' && *cp != '\t')
+			    cp++;
+		    *cp = '\0';
+		    *pp++ = 0;
+		    havesearch = 1;
+		    continue;
+		}
+		/* read nameservers to query */
+		if (!strncmp(buf, "nameserver", sizeof("nameserver") - 1) &&
+		   _res.nscount < MAXNS) {
+		    cp = buf + sizeof("nameserver") - 1;
+		    while (*cp == ' ' || *cp == '\t')
+			    cp++;
+		    if ((*cp == '\0') || (*cp == '\n'))
+			    continue;
+		    if (!inet_aton(cp, &_res.nsaddr_list[_res.nscount]))
+			    continue;
+		    _res.nsport_list[_res.nscount]= nameserver_port;
+		    _res.nscount++;
+		    continue;
+		}
+	    }
+	    (void) fclose(fp);
+	}
+	if (_res.nscount == 0) {
+		/* "localhost" is the default nameserver. */
+		_res.nsaddr_list[0]= HTONL(0x7F000001);
+		_res.nsport_list[0]= nameserver_port;
+		_res.nscount= 1;
+	}
+	if (_res.defdname[0] == 0) {
+		if (gethostname(buf, sizeof(_res.defdname)) == 0 &&
+		   (cp = index(buf, '.')))
+			(void)strcpy(_res.defdname, cp + 1);
+	}
+
+	/* find components of local domain that might be searched */
+	if (havesearch == 0) {
+		pp = _res.dnsrch;
+		*pp++ = _res.defdname;
+		for (cp = _res.defdname, n = 0; *cp; cp++)
+			if (*cp == '.')
+				n++;
+		cp = _res.defdname;
+		for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH;
+		    n--) {
+			cp = index(cp, '.');
+			*pp++ = ++cp;
+		}
+		*pp++ = 0;
+	}
+	_res.options |= RES_INIT;
+	return (0);
+}
Index: /trunk/minix/lib/ip/res_mkquery.c
===================================================================
--- /trunk/minix/lib/ip/res_mkquery.c	(revision 9)
+++ /trunk/minix/lib/ip/res_mkquery.c	(revision 9)
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 1985 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_mkquery.c	6.12 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
+#if _MINIX
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/nameser.h>
+#include <net/gen/resolv.h>
+
+#define bzero(b,l) memset(b,0,l)
+#define bcopy(s,d,l) memcpy(d,s,l)
+
+#define putshort __putshort
+#define putlong __putlong
+#else
+#include <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#endif
+
+#ifdef __STDC__
+#define _CONST	const
+#else
+#define _CONST
+#endif
+
+/*
+ * Form all types of queries.
+ * Returns the size of the result or -1.
+ */
+res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
+	int op;			/* opcode of query */
+	_CONST char *dname;	/* domain name */
+	int class, type;	/* class and type of query */
+	_CONST char *data;	/* resource record data */
+	int datalen;		/* length of data */
+	_CONST struct rrec *newrr; /* new rr for modify or append */
+	char *buf;		/* buffer to put query */
+	int buflen;		/* size of buffer */
+{
+	register dns_hdr_t *hp;
+	register char *cp;
+	register int n;
+	char *dnptrs[10], **dpp, **lastdnptr;
+
+#ifdef DEBUG
+	if (_res.options & RES_DEBUG)
+		printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
+#endif /* DEBUG */
+	/*
+	 * Initialize header fields.
+	 */
+	if ((buf == NULL) || (buflen < sizeof(dns_hdr_t)))
+		return(-1);
+	bzero(buf, sizeof(dns_hdr_t));
+	hp = (dns_hdr_t *) buf;
+	hp->dh_id = htons(++_res.id);
+	hp->dh_flag1= 0;
+	hp->dh_flag2= 0;
+	hp->dh_flag1 |= (op << 3) & DHF_OPCODE;
+	hp->dh_flag2 |= ((_res.options & RES_PRIMARY) != 0 ? 1 : 0) << 6;
+	hp->dh_flag1 |= (_res.options & RES_RECURSE) != 0 ? 1 : 0;
+	hp->dh_flag2 |= NOERROR & DHF_RCODE;
+	cp = buf + sizeof(dns_hdr_t);
+	buflen -= sizeof(dns_hdr_t);
+	dpp = dnptrs;
+	*dpp++ = buf;
+	*dpp++ = NULL;
+	lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
+	/*
+	 * perform opcode specific processing
+	 */
+	switch (op) {
+	case QUERY:
+		if ((buflen -= QFIXEDSZ) < 0)
+			return(-1);
+		if ((n = dn_comp((u8_t *)dname, (u8_t *)cp, buflen, 
+			(u8_t **)dnptrs, (u8_t **)lastdnptr)) < 0)
+			return (-1);
+		cp += n;
+		buflen -= n;
+		putshort(type, (u8_t *)cp);
+		cp += sizeof(u_short);
+		putshort(class, (u8_t *)cp);
+		cp += sizeof(u_short);
+		hp->dh_qdcount = HTONS(1);
+		if (op == QUERY || data == NULL)
+			break;
+		/*
+		 * Make an additional record for completion domain.
+		 */
+		buflen -= RRFIXEDSZ;
+		if ((n = dn_comp((u8_t *)data, (u8_t *)cp, buflen, 
+			(u8_t **)dnptrs, (u8_t **)lastdnptr)) < 0)
+			return (-1);
+		cp += n;
+		buflen -= n;
+		putshort(T_NULL, (u8_t *)cp);
+		cp += sizeof(u_short);
+		putshort(class, (u8_t *)cp);
+		cp += sizeof(u_short);
+		putlong(0, (u8_t *)cp);
+		cp += sizeof(u_long);
+		putshort(0, (u8_t *)cp);
+		cp += sizeof(u_short);
+		hp->dh_arcount = HTONS(1);
+		break;
+
+	case IQUERY:
+		/*
+		 * Initialize answer section
+		 */
+		if (buflen < 1 + RRFIXEDSZ + datalen)
+			return (-1);
+		*cp++ = '\0';	/* no domain name */
+		putshort(type, (u8_t *)cp);
+		cp += sizeof(u_short);
+		putshort(class, (u8_t *)cp);
+		cp += sizeof(u_short);
+		putlong(0, (u8_t *)cp);
+		cp += sizeof(u_long);
+		putshort(datalen, (u8_t *)cp);
+		cp += sizeof(u_short);
+		if (datalen) {
+			bcopy(data, cp, datalen);
+			cp += datalen;
+		}
+		hp->dh_ancount = HTONS(1);
+		break;
+
+#ifdef ALLOW_UPDATES
+	/*
+	 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
+	 * (Record to be modified is followed by its replacement in msg.)
+	 */
+	case UPDATEM:
+	case UPDATEMA:
+
+	case UPDATED:
+		/*
+		 * The res code for UPDATED and UPDATEDA is the same; user
+		 * calls them differently: specifies data for UPDATED; server
+		 * ignores data if specified for UPDATEDA.
+		 */
+	case UPDATEDA:
+		buflen -= RRFIXEDSZ + datalen;
+		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
+			return (-1);
+		cp += n;
+		putshort(type, cp);
+                cp += sizeof(u_short);
+                putshort(class, cp);
+                cp += sizeof(u_short);
+		putlong(0, cp);
+		cp += sizeof(u_long);
+		putshort(datalen, cp);
+                cp += sizeof(u_short);
+		if (datalen) {
+			bcopy(data, cp, datalen);
+			cp += datalen;
+		}
+		if ( (op == UPDATED) || (op == UPDATEDA) ) {
+			hp->ancount = HTONS(0);
+			break;
+		}
+		/* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
+
+	case UPDATEA:	/* Add new resource record */
+		buflen -= RRFIXEDSZ + datalen;
+		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
+			return (-1);
+		cp += n;
+		putshort(newrr->r_type, cp);
+                cp += sizeof(u_short);
+                putshort(newrr->r_class, cp);
+                cp += sizeof(u_short);
+		putlong(0, cp);
+		cp += sizeof(u_long);
+		putshort(newrr->r_size, cp);
+                cp += sizeof(u_short);
+		if (newrr->r_size) {
+			bcopy(newrr->r_data, cp, newrr->r_size);
+			cp += newrr->r_size;
+		}
+		hp->ancount = HTONS(0);
+		break;
+
+#endif /* ALLOW_UPDATES */
+	}
+	return (cp - buf);
+}
Index: /trunk/minix/lib/ip/res_query.c
===================================================================
--- /trunk/minix/lib/ip/res_query.c	(revision 9)
+++ /trunk/minix/lib/ip/res_query.c	(revision 9)
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_query.c	5.7 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
+#if _MINIX
+#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/nameser.h>
+#include <net/gen/netdb.h>
+#include <net/gen/resolv.h>
+
+#define bcopy(s,d,l) memcpy(d,s,l)
+
+#define hostalias __hostalias
+#else
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+extern int errno;
+#endif
+
+#if __STDC__
+#define CONST	const
+#else
+#define CONST
+#endif
+
+#if PACKETSZ > 1024
+#define MAXPACKET	PACKETSZ
+#else
+#define MAXPACKET	1024
+#endif
+
+int h_errno;
+
+/*
+ * Formulate a normal query, send, and await answer.
+ * Returned answer is placed in supplied buffer "answer".
+ * Perform preliminary check of answer, returning success only
+ * if no error is indicated and the answer count is nonzero.
+ * Return the size of the response on success, -1 on error.
+ * Error number is left in h_errno.
+ * Caller must parse answer and determine whether it answers the question.
+ */
+int
+res_query(name, class, type, answer, anslen)
+	char *name;		/* domain name */
+	int class, type;	/* class and type of query */
+	u_char *answer;		/* buffer to put answer */
+	int anslen;		/* size of answer buffer */
+{
+	char buf[MAXPACKET];
+	dns_hdr_t *hp;
+	int n;
+
+	if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+		return (-1);
+#ifdef DEBUG
+	if (_res.options & RES_DEBUG)
+		printf("res_query(%s, %d, %d)\n", name, class, type);
+#endif
+	n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0, NULL,
+	    buf, sizeof(buf));
+
+	if (n <= 0) {
+#ifdef DEBUG
+		if (_res.options & RES_DEBUG)
+			printf("res_query: mkquery failed\n");
+#endif
+		h_errno = NO_RECOVERY;
+		return (n);
+	}
+	n = res_send(buf, n, (char *)answer, anslen);
+	if (n < 0) {
+#ifdef DEBUG
+		if (_res.options & RES_DEBUG)
+			printf("res_query: send error(%d)\n", errno);
+#endif
+		h_errno = TRY_AGAIN;
+		return(n);
+	}
+
+	hp = (dns_hdr_t *) answer;
+	if ((hp->dh_flag2 & DHF_RCODE) != NOERROR || 
+		ntohs(hp->dh_ancount) == 0) {
+#ifdef DEBUG
+		if (_res.options & RES_DEBUG)
+			printf("rcode = %d, ancount=%d\n", 
+				hp->dh_flag2 & DHF_RCODE,
+			    ntohs(hp->dh_ancount));
+#endif
+		switch (hp->dh_flag2 & DHF_RCODE) {
+			case NXDOMAIN:
+				h_errno = HOST_NOT_FOUND;
+				break;
+			case SERVFAIL:
+				h_errno = TRY_AGAIN;
+				break;
+			case NOERROR:
+				h_errno = NO_DATA;
+				break;
+			case FORMERR:
+			case NOTIMP:
+			case REFUSED:
+			default:
+				h_errno = NO_RECOVERY;
+				break;
+		}
+		return (-1);
+	}
+	return(n);
+}
+
+/*
+ * Formulate a normal query, send, and retrieve answer in supplied buffer.
+ * Return the size of the response on success, -1 on error.
+ * If enabled, implement search rules until answer or unrecoverable failure
+ * is detected.  Error number is left in h_errno.
+ * Only useful for queries in the same name hierarchy as the local host
+ * (not, for example, for host address-to-name lookups in domain in-addr.arpa).
+ */
+res_search(name, class, type, answer, anslen)
+	char *name;		/* domain name */
+	int class, type;	/* class and type of query */
+	u_char *answer;		/* buffer to put answer */
+	int anslen;		/* size of answer */
+{
+	register char *cp, **domain;
+	int n, ret, got_nodata = 0;
+
+	if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+		return (-1);
+
+	errno = 0;
+	h_errno = HOST_NOT_FOUND;		/* default, if we never query */
+	for (cp = name, n = 0; *cp; cp++)
+		if (*cp == '.')
+			n++;
+	if (n == 0 && (cp = hostalias(name)))
+		return (res_query(cp, class, type, answer, anslen));
+
+	/*
+	 * We do at least one level of search if
+	 *	- there is no dot and RES_DEFNAME is set, or
+	 *	- there is at least one dot, there is no trailing dot,
+	 *	  and RES_DNSRCH is set.
+	 */
+	if ((n == 0 && _res.options & RES_DEFNAMES) ||
+	   (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH))
+	     for (domain = _res.dnsrch; *domain; domain++) {
+		ret = res_querydomain(name, *domain, class, type,
+		    answer, anslen);
+		if (ret > 0)
+			return (ret);
+		/*
+		 * If no server present, give up.
+		 * If name isn't found in this domain,
+		 * keep trying higher domains in the search list
+		 * (if that's enabled).
+		 * On a NO_DATA error, keep trying, otherwise
+		 * a wildcard entry of another type could keep us
+		 * from finding this entry higher in the domain.
+		 * If we get some other error (negative answer or
+		 * server failure), then stop searching up,
+		 * but try the input name below in case it's fully-qualified.
+		 */
+		if (errno == ECONNREFUSED) {
+			h_errno = TRY_AGAIN;
+			return (-1);
+		}
+		if (h_errno == NO_DATA)
+			got_nodata++;
+		if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) ||
+		    (_res.options & RES_DNSRCH) == 0)
+			break;
+	}
+	/*
+	 * If the search/default failed, try the name as fully-qualified,
+	 * but only if it contained at least one dot (even trailing).
+	 * This is purely a heuristic; we assume that any reasonable query
+	 * about a top-level domain (for servers, SOA, etc) will not use
+	 * res_search.
+	 */
+	if (n && (ret = res_querydomain(name, (char *)NULL, class, type,
+	    answer, anslen)) > 0)
+		return (ret);
+	if (got_nodata)
+		h_errno = NO_DATA;
+	return (-1);
+}
+
+/*
+ * Perform a call on res_query on the concatenation of name and domain,
+ * removing a trailing dot from name if domain is NULL.
+ */
+int
+res_querydomain(name, domain, class, type, answer, anslen)
+	char *name, *domain;
+	int class, type;	/* class and type of query */
+	u_char *answer;		/* buffer to put answer */
+	int anslen;		/* size of answer */
+{
+	char nbuf[2*MAXDNAME+2];
+	char *longname = nbuf;
+	int n;
+
+#ifdef DEBUG
+	if (_res.options & RES_DEBUG)
+		printf("res_querydomain(%s, %s, %d, %d)\n",
+		    name, domain, class, type);
+#endif
+	if (domain == NULL) {
+		/*
+		 * Check for trailing '.';
+		 * copy without '.' if present.
+		 */
+		n = strlen(name) - 1;
+		if (name[n] == '.' && n < sizeof(nbuf) - 1) {
+			bcopy(name, nbuf, n);
+			nbuf[n] = '\0';
+		} else
+			longname = name;
+	} else
+		(void)sprintf(nbuf, "%.*s.%.*s",
+		    MAXDNAME, name, MAXDNAME, domain);
+
+	return (res_query(longname, class, type, answer, anslen));
+}
+
+char *
+hostalias(name)
+	register CONST char *name;
+{
+	register char *C1, *C2;
+	FILE *fp;
+	char *file;
+	char buf[BUFSIZ];
+	static char abuf[MAXDNAME];
+
+	file = getenv("HOSTALIASES");
+	if (file == NULL || (fp = fopen(file, "r")) == NULL)
+		return (NULL);
+	buf[sizeof(buf) - 1] = '\0';
+	while (fgets(buf, sizeof(buf), fp)) {
+		for (C1 = buf; *C1 && !isspace(*C1); ++C1);
+		if (!*C1)
+			break;
+		*C1 = '\0';
+		if (!strcasecmp(buf, name)) {
+			while (isspace(*++C1));
+			if (!*C1)
+				break;
+			for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2);
+			abuf[sizeof(abuf) - 1] = *C2 = '\0';
+			(void)strncpy(abuf, C1, sizeof(abuf) - 1);
+			fclose(fp);
+			return (abuf);
+		}
+	}
+	fclose(fp);
+	return (NULL);
+}
Index: /trunk/minix/lib/ip/res_send.c
===================================================================
--- /trunk/minix/lib/ip/res_send.c	(revision 9)
+++ /trunk/minix/lib/ip/res_send.c	(revision 9)
@@ -0,0 +1,903 @@
+/*
+ * Copyright (c) 1985, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_send.c	6.27 (Berkeley) 2/24/91";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Send query to name server and wait for reply.
+ */
+
+#if !_MINIX
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <stdio.h>
+#include <errno.h>
+#include <resolv.h>
+#include <unistd.h>
+#include <string.h>
+
+#else /* _MINIX */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <net/hton.h>
+
+#include <net/netlib.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/netdb.h>
+#include <net/gen/nameser.h>
+#include <net/gen/resolv.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/udp_io.h>
+
+static int tcp_connect _ARGS(( ipaddr_t host, Tcpport_t port, int *terrno ));
+static int tcpip_writeall _ARGS(( int fd, const char *buf, size_t siz ));
+static int udp_connect _ARGS(( void ));
+static int udp_sendto _ARGS(( int fd, const char *buf, unsigned buflen,
+				ipaddr_t addr, Udpport_t port ));
+static int udp_receive _ARGS(( int fd, char *buf, unsigned buflen,
+				time_t timeout ));
+static void alarm_handler _ARGS(( int sig ));
+
+#endif /* !_MINIX */
+
+static int s = -1;	/* socket used for communications */
+#if !_MINIX
+static struct sockaddr no_addr;
+
+#ifndef FD_SET
+#define	NFDBITS		32
+#define	FD_SETSIZE	32
+#define	FD_SET(n, p)	((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+#define	FD_CLR(n, p)	((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define	FD_ISSET(n, p)	((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+#define FD_ZERO(p)	bzero((char *)(p), sizeof(*(p)))
+#endif /* FD_SET */
+#endif /* _MINIX */
+
+res_send(buf, buflen, answer, anslen)
+	const char *buf;
+	int buflen;
+	char *answer;
+	int anslen;
+{
+	register int n;
+	int try, v_circuit, resplen, ns;
+	int gotsomewhere = 0, connected = 0;
+	int connreset = 0;
+#if !_MINIX
+	u_short id, len;
+#else /* _MINIX */
+	u16_t id, len;
+#endif /* !_MINIX */
+	char *cp;
+#if !_MINIX
+	fd_set dsmask;
+	struct timeval timeout;
+	HEADER *hp = (HEADER *) buf;
+	HEADER *anhp = (HEADER *) answer;
+	struct iovec iov[2];
+#else /* _MINIX */
+	time_t timeout;
+	dns_hdr_t *hp = (dns_hdr_t *) buf;
+	dns_hdr_t *anhp = (dns_hdr_t *) answer;
+#endif /* !_MINIX */
+	int terrno = ETIMEDOUT;
+	char junk[512];
+
+#ifdef DEBUG
+	if (_res.options & RES_DEBUG) {
+		printf("res_send()\n");
+		__p_query(buf);
+	}
+#endif /* DEBUG */
+	if (!(_res.options & RES_INIT))
+		if (res_init() == -1) {
+			return(-1);
+		}
+
+	v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
+#if !_MINIX
+	id = hp->id;
+#else /* _MINIX */
+	id = hp->dh_id;
+#endif /* !_MINIX */
+	/*
+	 * Send request, RETRY times, or until successful
+	 */
+	for (try = 0; try < _res.retry; try++) {
+	   for (ns = 0; ns < _res.nscount; ns++) {
+#ifdef DEBUG
+#if !_MINIX
+		if (_res.options & RES_DEBUG)
+			printf("Querying server (# %d) address = %s\n", ns+1,
+			      inet_ntoa(_res.nsaddr_list[ns].sin_addr));
+#else /* _MINIX */
+		if (_res.options & RES_DEBUG)
+			printf("Querying server (# %d) address = %s\n", ns+1,
+			      inet_ntoa(_res.nsaddr_list[ns]));
+#endif /* !_MINIX */
+#endif /* DEBUG */
+	usevc:
+		if (v_circuit) {
+#if !_MINIX
+			int truncated = 0;
+
+			/*
+			 * Use virtual circuit;
+			 * at most one attempt per server.
+			 */
+			try = _res.retry;
+			if (s < 0) {
+				s = socket(AF_INET, SOCK_STREAM, 0);
+				if (s < 0) {
+					terrno = errno;
+#ifdef DEBUG
+					if (_res.options & RES_DEBUG)
+					    perror("socket (vc) failed");
+#endif /* DEBUG */
+					continue;
+				}
+				if (connect(s,
+				    (struct sockaddr *)&(_res.nsaddr_list[ns]),
+				    sizeof(struct sockaddr)) < 0) {
+					terrno = errno;
+#ifdef DEBUG
+					if (_res.options & RES_DEBUG)
+					    perror("connect failed");
+#endif /* DEBUG */
+					(void) close(s);
+					s = -1;
+					continue;
+				}
+			}
+			/*
+			 * Send length & message
+			 */
+			len = htons((u_short)buflen);
+			iov[0].iov_base = (caddr_t)&len;
+			iov[0].iov_len = sizeof(len);
+			iov[1].iov_base = (char *)buf;
+			iov[1].iov_len = buflen;
+			if (writev(s, iov, 2) != sizeof(len) + buflen) {
+				terrno = errno;
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					perror("write failed");
+#endif /* DEBUG */
+				(void) close(s);
+				s = -1;
+				continue;
+			}
+			/*
+			 * Receive length & response
+			 */
+			cp = answer;
+			len = sizeof(short);
+			while (len != 0 &&
+			    (n = read(s, (char *)cp, (int)len)) > 0) {
+				cp += n;
+				len -= n;
+			}
+			if (n <= 0) {
+				terrno = errno;
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					perror("read failed");
+#endif /* DEBUG */
+				(void) close(s);
+				s = -1;
+				/*
+				 * A long running process might get its TCP
+				 * connection reset if the remote server was
+				 * restarted.  Requery the server instead of
+				 * trying a new one.  When there is only one
+				 * server, this means that a query might work
+				 * instead of failing.  We only allow one reset
+				 * per query to prevent looping.
+				 */
+				if (terrno == ECONNRESET && !connreset) {
+					connreset = 1;
+					ns--;
+				}
+				continue;
+			}
+			cp = answer;
+			if ((resplen = ntohs(*(u_short *)cp)) > anslen) {
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					fprintf(stderr, "response truncated\n");
+#endif /* DEBUG */
+				len = anslen;
+				truncated = 1;
+			} else
+				len = resplen;
+			while (len != 0 &&
+			   (n = read(s, (char *)cp, (int)len)) > 0) {
+				cp += n;
+				len -= n;
+			}
+			if (n <= 0) {
+				terrno = errno;
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					perror("read failed");
+#endif /* DEBUG */
+				(void) close(s);
+				s = -1;
+				continue;
+			}
+			if (truncated) {
+				/*
+				 * Flush rest of answer
+				 * so connection stays in synch.
+				 */
+				anhp->tc = 1;
+				len = resplen - anslen;
+				while (len != 0) {
+					n = (len > sizeof(junk) ?
+					    sizeof(junk) : len);
+					if ((n = read(s, junk, n)) > 0)
+						len -= n;
+					else
+						break;
+				}
+			}
+#else /* _MINIX */
+			int truncated = 0;
+			int nbytes;
+
+			/*
+			 * Use virtual circuit;
+			 * at most one attempt per server.
+			 */
+			try = _res.retry;
+			if (s < 0) 
+			{
+				s= tcp_connect(_res.nsaddr_list[ns],
+					_res.nsport_list[ns], &terrno);
+				if (s == -1)
+					continue;
+			}
+			/*
+			 * Send length & message
+			 */
+			len = htons((u_short)buflen);
+			nbytes= tcpip_writeall(s, (char *)&len, 
+				sizeof(len));
+			if (nbytes != sizeof(len))
+			{
+				terrno= errno;
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					fprintf(stderr, "write failed: %s\n",
+					strerror(terrno));
+#endif /* DEBUG */
+				close(s);
+				s= -1;
+				continue;
+			}
+			nbytes= tcpip_writeall(s, buf, buflen);
+			if (nbytes != buflen)
+			{
+				terrno= errno;
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					fprintf(stderr, "write failed: %s\n",
+					strerror(terrno));
+#endif /* DEBUG */
+				close(s);
+				s= -1;
+				continue;
+			}
+			/*
+			 * Receive length & response
+			 */
+			cp = answer;
+			len = sizeof(short);
+			while (len != 0)
+			{
+				n = read(s, (char *)cp, (int)len);
+				if (n <= 0)
+					break;
+				cp += n;
+				assert(len >= n);
+				len -= n;
+			}
+			if (len) {
+				terrno = errno;
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					fprintf(stderr, "read failed: %s\n",
+						strerror(terrno));
+#endif /* DEBUG */
+				close(s);
+				s= -1;
+				/*
+				 * A long running process might get its TCP
+				 * connection reset if the remote server was
+				 * restarted.  Requery the server instead of
+				 * trying a new one.  When there is only one
+				 * server, this means that a query might work
+				 * instead of failing.  We only allow one reset
+				 * per query to prevent looping.
+				 */
+				if (terrno == ECONNRESET && !connreset) {
+					connreset = 1;
+					ns--;
+				}
+				continue;
+			}
+			cp = answer;
+			if ((resplen = ntohs(*(u_short *)cp)) > anslen) {
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					fprintf(stderr, "response truncated\n");
+#endif /* DEBUG */
+				len = anslen;
+				truncated = 1;
+			} else
+				len = resplen;
+			while (len != 0)
+			{
+				n= read(s, (char *)cp, (int)len);
+				if (n <= 0)
+					break;
+				cp += n;
+				assert(len >= n);
+				len -= n;
+			}
+			if (len) {
+				terrno = errno;
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					fprintf(stderr, "read failed: %s\n",
+						strerror(terrno));
+#endif /* DEBUG */
+				close(s);
+				s= -1;
+				continue;
+			}
+			if (truncated) {
+				/*
+				 * Flush rest of answer
+				 * so connection stays in synch.
+				 */
+				anhp->dh_flag1 |= DHF_TC;
+				len = resplen - anslen;
+				while (len != 0) {
+					n = (len > sizeof(junk) ?
+					    sizeof(junk) : len);
+					n = read(s, junk, n);
+					if (n <= 0)
+					{
+						assert(len >= n);
+						len -= n;
+					}
+					else
+						break;
+				}
+			}
+#endif /* _MINIX */
+		} else {
+#if !_MINIX
+			/*
+			 * Use datagrams.
+			 */
+			if (s < 0) {
+				s = socket(AF_INET, SOCK_DGRAM, 0);
+				if (s < 0) {
+					terrno = errno;
+#ifdef DEBUG
+					if (_res.options & RES_DEBUG)
+					    perror("socket (dg) failed");
+#endif /* DEBUG */
+					continue;
+				}
+			}
+#if	BSD >= 43
+			/*
+			 * I'm tired of answering this question, so:
+			 * On a 4.3BSD+ machine (client and server,
+			 * actually), sending to a nameserver datagram
+			 * port with no nameserver will cause an
+			 * ICMP port unreachable message to be returned.
+			 * If our datagram socket is "connected" to the
+			 * server, we get an ECONNREFUSED error on the next
+			 * socket operation, and select returns if the
+			 * error message is received.  We can thus detect
+			 * the absence of a nameserver without timing out.
+			 * If we have sent queries to at least two servers,
+			 * however, we don't want to remain connected,
+			 * as we wish to receive answers from the first
+			 * server to respond.
+			 */
+			if (_res.nscount == 1 || (try == 0 && ns == 0)) {
+				/*
+				 * Don't use connect if we might
+				 * still receive a response
+				 * from another server.
+				 */
+				if (connected == 0) {
+			if (connect(s, (struct sockaddr *)&_res.nsaddr_list[ns],
+					    sizeof(struct sockaddr)) < 0) {
+#ifdef DEBUG
+						if (_res.options & RES_DEBUG)
+							perror("connect");
+#endif /* DEBUG */
+						continue;
+					}
+					connected = 1;
+				}
+				if (send(s, buf, buflen, 0) != buflen) {
+#ifdef DEBUG
+					if (_res.options & RES_DEBUG)
+						perror("send");
+#endif /* DEBUG */
+					continue;
+				}
+			} else {
+				/*
+				 * Disconnect if we want to listen
+				 * for responses from more than one server.
+				 */
+				if (connected) {
+					(void) connect(s, &no_addr,
+					    sizeof(no_addr));
+					connected = 0;
+				}
+#endif /* BSD */
+				if (sendto(s, buf, buflen, 0,
+				    (struct sockaddr *)&_res.nsaddr_list[ns],
+				    sizeof(struct sockaddr)) != buflen) {
+#ifdef DEBUG
+					if (_res.options & RES_DEBUG)
+						perror("sendto");
+#endif /* DEBUG */
+					continue;
+				}
+#if	BSD >= 43
+			}
+#endif /* BSD */
+
+			/*
+			 * Wait for reply
+			 */
+			timeout.tv_sec = (_res.retrans << try);
+			if (try > 0)
+				timeout.tv_sec /= _res.nscount;
+			if (timeout.tv_sec <= 0)
+				timeout.tv_sec = 1;
+			timeout.tv_usec = 0;
+wait:
+			FD_ZERO(&dsmask);
+			FD_SET(s, &dsmask);
+			n = select(s+1, &dsmask, (fd_set *)NULL,
+				(fd_set *)NULL, &timeout);
+			if (n < 0) {
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					perror("select");
+#endif /* DEBUG */
+				continue;
+			}
+			if (n == 0) {
+				/*
+				 * timeout
+				 */
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					printf("timeout\n");
+#endif /* DEBUG */
+#if BSD >= 43
+				gotsomewhere = 1;
+#endif
+				continue;
+			}
+			if ((resplen = recv(s, answer, anslen, 0)) <= 0) {
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					perror("recvfrom");
+#endif /* DEBUG */
+				continue;
+			}
+			gotsomewhere = 1;
+			if (id != anhp->id) {
+				/*
+				 * response from old query, ignore it
+				 */
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG) {
+					printf("old answer:\n");
+					__p_query(answer);
+				}
+#endif /* DEBUG */
+				goto wait;
+			}
+			if (!(_res.options & RES_IGNTC) && anhp->tc) {
+				/*
+				 * get rest of answer;
+				 * use TCP with same server.
+				 */
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					printf("truncated answer\n");
+#endif /* DEBUG */
+				(void) close(s);
+				s = -1;
+				v_circuit = 1;
+				goto usevc;
+			}
+#else /* _MINIX */
+			/*
+			 * Use datagrams.
+			 */
+			if (s < 0) {
+				s = udp_connect();
+				if (s < 0) {
+					terrno = errno;
+#ifdef DEBUG
+					if (_res.options & RES_DEBUG)
+					    perror("udp_connect failed");
+#endif /* DEBUG */
+					continue;
+				}
+			}
+			if (udp_sendto(s, buf, buflen, _res.nsaddr_list[ns],
+				_res.nsport_list[ns]) != buflen) {
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					perror("sendto");
+#endif /* DEBUG */
+				continue;
+			}
+
+			/*
+			 * Wait for reply
+			 */
+			timeout= (_res.retrans << try);
+			if (try > 0)
+				timeout /= _res.nscount;
+			if (timeout <= 0)
+				timeout= 1;
+wait:
+			if ((resplen= udp_receive(s, answer, anslen, timeout))
+				== -1)
+			{
+				if (errno == EINTR)
+				{
+				/*
+				 * timeout
+				 */
+#ifdef DEBUG
+					if (_res.options & RES_DEBUG)
+						printf("timeout\n");
+#endif /* DEBUG */
+					gotsomewhere = 1;
+				}
+				else
+				{
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					perror("udp_receive");
+#endif /* DEBUG */
+				}
+				continue;
+			}
+			gotsomewhere = 1;
+			if (id != anhp->dh_id) {
+				/*
+				 * response from old query, ignore it
+				 */
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG) {
+					printf("old answer:\n");
+					__p_query(answer);
+				}
+#endif /* DEBUG */
+				goto wait;
+			}
+			if (!(_res.options & RES_IGNTC) &&
+				(anhp->dh_flag1 & DHF_TC)) {
+				/*
+				 * get rest of answer;
+				 * use TCP with same server.
+				 */
+#ifdef DEBUG
+				if (_res.options & RES_DEBUG)
+					printf("truncated answer\n");
+#endif /* DEBUG */
+				(void) close(s);
+				s = -1;
+				v_circuit = 1;
+				goto usevc;
+			}
+#endif /* !_MINIX */
+		}
+#ifdef DEBUG
+		if (_res.options & RES_DEBUG) {
+			printf("got answer:\n");
+			__p_query(answer);
+		}
+#endif /* DEBUG */
+		/*
+		 * If using virtual circuits, we assume that the first server
+		 * is preferred * over the rest (i.e. it is on the local
+		 * machine) and only keep that one open.
+		 * If we have temporarily opened a virtual circuit,
+		 * or if we haven't been asked to keep a socket open,
+		 * close the socket.
+		 */
+		if ((v_circuit &&
+		    ((_res.options & RES_USEVC) == 0 || ns != 0)) ||
+		    (_res.options & RES_STAYOPEN) == 0) {
+			(void) close(s);
+			s = -1;
+		}
+		return (resplen);
+	   }
+	}
+	if (s >= 0) {
+		(void) close(s);
+		s = -1;
+	}
+	if (v_circuit == 0)
+		if (gotsomewhere == 0)
+			errno = ECONNREFUSED;	/* no nameservers found */
+		else
+			errno = ETIMEDOUT;	/* no answer obtained */
+	else
+		errno = terrno;
+	return (-1);
+}
+
+/*
+ * This routine is for closing the socket if a virtual circuit is used and
+ * the program wants to close it.  This provides support for endhostent()
+ * which expects to close the socket.
+ *
+ * This routine is not expected to be user visible.
+ */
+void
+_res_close()
+{
+	if (s != -1) {
+		(void) close(s);
+		s = -1;
+	}
+}
+
+#if _MINIX
+static int tcp_connect(host, port, terrno)
+ipaddr_t host;
+tcpport_t port;
+int *terrno;
+{
+	char *dev_name;
+	int fd;
+	int error;
+	nwio_tcpconf_t tcpconf;
+	nwio_tcpcl_t clopt;
+
+	dev_name= getenv("TCP_DEVICE");
+	if (!dev_name)
+		dev_name= TCP_DEVICE;
+	fd= open(dev_name, O_RDWR);
+	if (fd == -1)
+	{
+		*terrno= errno;
+		return -1;
+	}
+	tcpconf.nwtc_flags= NWTC_EXCL | NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
+	tcpconf.nwtc_remaddr= host;
+	tcpconf.nwtc_remport= port;
+	error= ioctl(fd, NWIOSTCPCONF, &tcpconf);
+	if (error == -1)
+	{
+		*terrno= errno;
+		close(fd);
+		return -1;
+	}
+	clopt.nwtcl_flags= 0;
+	error= ioctl(fd, NWIOTCPCONN, &clopt);
+	if (error == -1)
+	{
+		*terrno= errno;
+		close(fd);
+		return -1;
+	}
+	*terrno= 0;
+	return fd;
+}
+
+static int tcpip_writeall(fd, buf, siz)
+int fd;
+const char *buf;
+size_t siz;
+{
+	size_t siz_org;
+	int nbytes;
+
+	siz_org= siz;
+
+	while (siz)
+	{
+		nbytes= write(fd, buf, siz);
+		if (nbytes <= 0)
+			return siz_org-siz;
+		assert(siz >= nbytes);
+		buf += nbytes;
+		siz -= nbytes;
+	}
+	return siz_org;
+}
+
+
+static int udp_connect()
+{
+	nwio_udpopt_t udpopt;
+	char *dev_name;
+	int fd, r, terrno;
+
+	dev_name= getenv("UDP_DEVICE");
+	if (!dev_name)
+		dev_name= UDP_DEVICE;
+	fd= open(dev_name, O_RDWR);
+	if (fd == -1)
+		return -1;
+
+	udpopt.nwuo_flags= NWUO_COPY | NWUO_LP_SEL | NWUO_EN_LOC |
+		NWUO_EN_BROAD | NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL |
+		NWUO_DI_IPOPT;
+	r= ioctl(fd, NWIOSUDPOPT, &udpopt);
+	if (r == -1)
+	{
+		terrno= errno;
+		close(fd);
+		errno= terrno;
+		return -1;
+	}
+	return fd;
+}
+
+static int udp_sendto(fd, buf, buflen, addr, port)
+int fd;
+const char *buf;
+unsigned buflen;
+ipaddr_t addr;
+udpport_t port;
+{
+	char *newbuf;
+	udp_io_hdr_t *udp_io_hdr;
+	int r, terrno;
+
+	newbuf= malloc(sizeof(*udp_io_hdr) + buflen);
+	if (newbuf == NULL)
+	{
+		errno= ENOMEM;
+		return -1;
+	}
+	udp_io_hdr= (udp_io_hdr_t *)newbuf;
+	udp_io_hdr->uih_dst_addr= addr;
+	udp_io_hdr->uih_dst_port= port;
+	udp_io_hdr->uih_ip_opt_len= 0;
+	udp_io_hdr->uih_data_len= buflen;
+
+	memcpy(newbuf + sizeof(*udp_io_hdr), buf, buflen);
+	r= write(fd, newbuf, sizeof(*udp_io_hdr) + buflen);
+	terrno= errno;
+	free(newbuf);
+	if (r >= sizeof(*udp_io_hdr))
+		r -= sizeof(*udp_io_hdr);
+	errno= terrno;
+	return r;
+}
+
+static void alarm_handler(sig)
+int sig;
+{
+	signal(SIGALRM, alarm_handler);
+	alarm(1);
+}
+
+static int udp_receive(fd, buf, buflen, timeout)
+int fd;
+char *buf;
+unsigned buflen;
+time_t timeout;
+{
+	char *newbuf;
+	udp_io_hdr_t *udp_io_hdr;
+	int r, terrno;
+	void (*u_handler) _ARGS(( int sig ));
+	time_t u_timeout;
+
+	newbuf= malloc(sizeof(*udp_io_hdr) + buflen);
+	if (newbuf == NULL)
+	{
+		errno= ENOMEM;
+		return -1;
+	}
+
+	u_handler= signal(SIGALRM, alarm_handler);
+	u_timeout= alarm(timeout);
+
+	r= read(fd, newbuf, sizeof(*udp_io_hdr) + buflen);
+	terrno= errno;
+
+	if (r < 0 || r <= sizeof(*udp_io_hdr))
+	{
+		if (r > 0)
+			r= 0;
+		free(newbuf);
+
+
+		alarm(0);
+		signal(SIGALRM, u_handler);
+		alarm(u_timeout);
+
+		errno= terrno;
+		return r;
+	}
+
+	memcpy(buf, newbuf + sizeof(*udp_io_hdr), r - sizeof(*udp_io_hdr));
+	free(newbuf);
+
+	alarm(0);
+	signal(SIGALRM, u_handler);
+	alarm(u_timeout);
+
+	return r-sizeof(*udp_io_hdr);
+}
+
+#endif
Index: /trunk/minix/lib/ip/ruserok.c
===================================================================
--- /trunk/minix/lib/ip/ruserok.c	(revision 9)
+++ /trunk/minix/lib/ip/ruserok.c	(revision 9)
@@ -0,0 +1,187 @@
+/*	ruserok() - hosts.equiv and .rhosts check	Author: Kees J. Bot
+ *								25 May 2001
+ *
+ * Under Minix one can use IP addresses, CIDR network blocks, and hostnames
+ * with wildcards in .rhosts files.  Only the iruserok() interface can be
+ * used, and the IP address is reverse/forward crosschecked if a hostname
+ * match is done.  Ruserok() is dead and buried.  The superuser parameter is
+ * ignored, because it makes root too special.  Most users on Minix can be
+ * root, so hosts.equiv would become useless if root can't use it.  Likewise
+ * .rhosts isn't checked to be root or user owned and stuff, users have to
+ * be careful themselves.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <limits.h>
+#include <pwd.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/netdb.h>
+#include <net/gen/inet.h>
+#include <net/gen/socket.h>
+#include <net/gen/nameser.h>
+
+/* Odd global variable.  Seems to be used by lpd(8). */
+int	__check_rhosts_file = 1;
+
+static int cidr_aton(char *word, ipaddr_t *addr, ipaddr_t *mask)
+/* Try to interpret 'word' as an CIDR spec, e.g. 172.16.102.64/27. */
+{
+    char *slash;
+    int r;
+    static char S32[]= "/32";
+
+    if (*word == 0) return 0;
+
+    if ((slash= strchr(word, '/')) == NULL) slash= S32;
+
+    *slash= 0;
+    r= inet_aton(word, addr);
+    *slash++= '/';
+    if (!r) return 0;
+
+    r= 0;
+    while ((*slash - '0') < 10u) {
+	r= 10*r + (*slash++ - '0');
+	if (r > 32) return 0;
+    }
+    if (*slash != 0 || slash[-1] == '/') return 0;
+    *mask= htonl(r == 0 ? 0L : (0xFFFFFFFFUL >> (32 - r)) << (32 - r));
+    return 1;
+}
+
+static int match(const char *word, const char *pattern)
+/* Match word onto a pattern.  Pattern may contain the * wildcard. */
+{
+    unsigned cw, cp;
+#define lc(c, d) ((((c)= (d)) - 'A') <= ('Z' - 'A') ? (c)+= ('a' - 'A') : 0)
+
+    for (;;) {
+	lc(cw, *word);
+	lc(cp, *pattern);
+
+	if (cp == '*') {
+	    do pattern++; while (*pattern == '*');
+	    lc(cp, *pattern);
+	    if (cp == 0) return 1;
+
+	    while (cw != 0) {
+		if (cw == cp && match(word+1, pattern+1)) return 1;
+		word++;
+		lc(cw, *word);
+	    }
+	    return 0;
+	} else
+	if (cw == 0 || cp == 0) {
+	    return cw == cp;
+	} else
+	if (cw == cp) {
+	    word++;
+	    pattern++;
+	} else {
+	    return 0;
+	}
+    }
+#undef lc
+}
+
+static int get_name(ipaddr_t addr, char *name)
+/* Do a reverse lookup on the remote IP address followed by a forward lookup
+ * to check if the host has that address.  Return true if this is so, return
+ * either the true name or the ascii IP address in name[].
+ */
+{
+    struct hostent *he;
+    int ok, i;
+
+    ok= 0;
+    he= gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
+    if (he != NULL) {
+	strcpy(name, he->h_name);
+	he= gethostbyname(name);
+
+	if (he != NULL && he->h_addrtype == AF_INET) {
+	    for (i= 0; he->h_addr_list[i] != NULL; i++) {
+		if (memcmp(he->h_addr_list[i], &addr, sizeof(addr)) == 0) {
+		    ok= 1;
+		    break;
+		}
+	    }
+	}
+    }
+    strcpy(name, ok ? he->h_name : inet_ntoa(addr));
+    return ok;
+}
+
+int __ivaliduser(FILE *hostf, unsigned long raddr,
+    const char *luser, const char *ruser)
+{
+    register char *p;
+    char buf[MAXDNAME + 128];		/* host + login */
+    char rhost[MAXDNAME];		/* remote host */
+    char *word[2];
+    int i, ch, got_name;
+    ipaddr_t addr, mask;
+
+    got_name = -1;
+
+    while (fgets(buf, sizeof(buf), hostf)) {
+	/* Skip lines that are too long. */
+	if (strchr(buf, '\n') == NULL) {
+	    while ((ch = fgetc(hostf)) != '\n' && ch != EOF);
+	    continue;
+	}
+	i = 0;
+	p = buf;
+	for (;;) {
+	    while (isspace(*p)) *p++ = '\0';
+	    if (*p == '\0') break;
+	    if (i < 2) word[i] = p;
+	    i++;
+	    while (*p != '\0' && !isspace(*p)) p++;
+	}
+	if (i != 1 && i != 2) continue;
+	if (word[0][0] == '#') continue;
+	if (strcmp(ruser, i == 2 ? word[1] : luser) != 0) continue;
+
+	if (cidr_aton(word[0], &addr, &mask)) {
+	    if (((raddr ^ addr) & mask) == 0) return (0);
+	    continue;
+	}
+
+	if (got_name == -1) got_name = get_name(raddr, rhost);
+	if (match(rhost, word[0])) return (0);
+    }
+    return (-1);
+}
+
+int iruserok(unsigned long raddr, int superuser,
+    const char *ruser, const char *luser)
+{
+    /* Returns 0 if ok, -1 if not ok. */
+    struct passwd *pwd;
+    FILE *hostf;
+    int i, r;
+    char pbuf[PATH_MAX];
+
+    for (i = 0; i < 2; i++) {
+	if (i == 0) {
+	    strcpy(pbuf, _PATH_HEQUIV);
+	} else {
+	    if (!__check_rhosts_file) return (-1);
+	    if ((pwd = getpwnam(luser)) == NULL) return (-1);
+	    (void)strcpy(pbuf, pwd->pw_dir);
+	    (void)strcat(pbuf, "/.rhosts");
+	}
+
+	if ((hostf = fopen(pbuf, "r")) == NULL) return (-1);
+
+	r = __ivaliduser(hostf, raddr, luser, ruser);
+	(void)fclose(hostf);
+	if (r == 0) return (0);
+    }
+    return (-1);
+}
Index: /trunk/minix/lib/ip/send.c
===================================================================
--- /trunk/minix/lib/ip/send.c	(revision 9)
+++ /trunk/minix/lib/ip/send.c	(revision 9)
@@ -0,0 +1,11 @@
+#include <stdlib.h>
+#include <sys/socket.h>
+
+ssize_t send(int socket, const void *buffer, size_t length, int flags)
+{
+	struct sockaddr sa;
+
+	sa.sa_family= AF_UNSPEC;
+	return sendto(socket, buffer, length, flags, &sa, sizeof(sa));
+}
+
Index: /trunk/minix/lib/ip/sendto.c
===================================================================
--- /trunk/minix/lib/ip/sendto.c	(revision 9)
+++ /trunk/minix/lib/ip/sendto.c	(revision 9)
@@ -0,0 +1,123 @@
+#undef NDEBUG
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/gen/in.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+static ssize_t _udp_sendto(int socket, const void *message, size_t length,
+	int flags, const struct sockaddr *dest_addr, socklen_t dest_len,
+	nwio_udpopt_t *udpoptp);
+
+ssize_t sendto(int socket, const void *message, size_t length, int flags,
+	const struct sockaddr *dest_addr, socklen_t dest_len)
+{
+	int r;
+	nwio_udpopt_t udpopt;
+
+	r= ioctl(socket, NWIOGUDPOPT, &udpopt);
+	if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
+	{
+		if (r == -1)
+			return r;
+		return _udp_sendto(socket, message, length, flags,
+			dest_addr, dest_len, &udpopt);
+	}
+
+#if DEBUG
+	fprintf(stderr, "sendto: not implemented for fd %d\n", socket);
+#endif
+	errno= ENOSYS;
+	return -1;
+}
+
+static ssize_t _udp_sendto(int socket, const void *message, size_t length,
+	int flags, const struct sockaddr *dest_addr, socklen_t dest_len,
+	nwio_udpopt_t *udpoptp)
+{
+	int r, t_errno;
+	size_t buflen;
+	void *buf;
+	struct sockaddr_in *sinp;
+	udp_io_hdr_t *io_hdrp;
+
+	if (flags)
+	{
+#if DEBUG
+		fprintf(stderr, "sendto(udp): flags not implemented\n");
+#endif
+		errno= ENOSYS;
+		return -1;
+	}
+
+	if (udpoptp->nwuo_flags & NWUO_RWDATONLY)
+		return write(socket, message, length);
+
+	if ((udpoptp->nwuo_flags & NWUO_RP_ANY) ||
+		(udpoptp->nwuo_flags & NWUO_RA_ANY))
+	{
+		/* Check destination address */
+		if (dest_len < sizeof(*sinp))
+		{
+			errno= EINVAL;
+			return -1;
+		}
+		sinp= (struct sockaddr_in *)dest_addr;
+		if (sinp->sin_family != AF_INET)
+		{
+			errno= EAFNOSUPPORT;
+			return -1;
+		}
+	}
+
+	buflen= sizeof(*io_hdrp) + length;
+	if (buflen < length)
+	{	
+		/* Overflow */
+		errno= EMSGSIZE;
+		return -1;
+	}
+	buf= malloc(buflen);
+	if (buf == NULL)
+		return -1;
+
+	io_hdrp= buf;
+	io_hdrp->uih_src_addr= 0;	/* Unused */
+	io_hdrp->uih_src_port= 0;	/* Will cause error if NWUO_LP_ANY */
+	if (udpoptp->nwuo_flags & NWUO_RA_ANY)
+		io_hdrp->uih_dst_addr= sinp->sin_addr.s_addr;
+	else
+		io_hdrp->uih_dst_addr= 0;
+	if (udpoptp->nwuo_flags & NWUO_RP_ANY)
+		io_hdrp->uih_dst_port= sinp->sin_port;
+	else
+		io_hdrp->uih_dst_port= 0;
+	io_hdrp->uih_ip_opt_len= 0;
+	io_hdrp->uih_data_len= 0;
+
+	memcpy(&io_hdrp[1], message, length);
+	r= write(socket, buf, buflen);
+	if (r == -1)
+	{
+		t_errno= errno;
+		free(buf);
+		errno= t_errno;
+		return -1;
+	}
+	assert(r == buflen);
+	free(buf);
+	return length;
+}
+
Index: /trunk/minix/lib/ip/servxcheck.c
===================================================================
--- /trunk/minix/lib/ip/servxcheck.c	(revision 9)
+++ /trunk/minix/lib/ip/servxcheck.c	(revision 9)
@@ -0,0 +1,302 @@
+/*	servxcheck() - Service access check.		Author: Kees J. Bot
+ *								8 Jan 1997
+ */
+#define nil 0
+#define ioctl _ioctl
+#define open _open
+#define write _write
+#define close _close
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/inet.h>
+#include <net/gen/socket.h>
+#include <net/gen/netdb.h>
+
+/* Default service access file. */
+static const char *path_servacces = _PATH_SERVACCES;
+
+#define WLEN	256
+
+static int getword(FILE *fp, char *word)
+/* Read a word from the file open by 'fp', skip whitespace and comments.
+ * Colon and semicolon are returned as a one character "word".  Returns
+ * word[0] or EOF.
+ */
+{
+    int c;
+    char *pw;
+    int wc;
+
+    wc= 0;
+    for (;;) {
+	if ((c= getc(fp)) == EOF) return EOF;
+	if (c == '#') { wc= 1; continue; }
+	if (c == '\n') { wc= 0; continue; }
+	if (wc) continue;
+	if (c <= ' ') continue;
+	break;
+    }
+
+    pw= word;
+    if (c == ':' || c == ';') {
+	    *pw++ = c;
+    } else {
+	do {
+	    if (pw < word + WLEN-1) *pw++ = c;
+	    c= getc(fp);
+	} while (c != EOF && c > ' ' && c != ':' && c != ';');
+	if (c != EOF) ungetc(c, fp);
+    }
+    *pw= 0;
+    return word[0];
+}
+
+static int netspec(char *word, ipaddr_t *addr, ipaddr_t *mask)
+/* Try to interpret 'word' as an network spec, e.g. 172.16.102.64/27. */
+{
+    char *slash;
+    int r;
+    static char S32[]= "/32";
+
+    if (*word == 0) return 0;
+
+    if ((slash= strchr(word, '/')) == NULL) slash= S32;
+
+    *slash= 0;
+    r= inet_aton(word, addr);
+    *slash++= '/';
+    if (!r) return 0;
+
+    r= 0;
+    while ((*slash - '0') < 10u) {
+	r= 10*r + (*slash++ - '0');
+	if (r > 32) return 0;
+    }
+    if (*slash != 0 || slash[-1] == '/') return 0;
+    *mask= htonl(r == 0 ? 0L : (0xFFFFFFFFUL >> (32 - r)) << (32 - r));
+    return 1;
+}
+
+static int match(const char *word, const char *pattern)
+/* Match word onto a pattern.  Pattern may contain the * wildcard. */
+{
+    unsigned cw, cp;
+#define lc(c, d) ((((c)= (d)) - 'A') <= ('Z' - 'A') ? (c)+= ('a' - 'A') : 0)
+
+    for (;;) {
+	lc(cw, *word);
+	lc(cp, *pattern);
+
+	if (cp == '*') {
+	    do pattern++; while (*pattern == '*');
+	    lc(cp, *pattern);
+	    if (cp == 0) return 1;
+
+	    while (cw != 0) {
+		if (cw == cp && match(word+1, pattern+1)) return 1;
+		word++;
+		lc(cw, *word);
+	    }
+	    return 0;
+	} else
+	if (cw == 0 || cp == 0) {
+	    return cw == cp;
+	} else
+	if (cw == cp) {
+	    word++;
+	    pattern++;
+	} else {
+	    return 0;
+	}
+    }
+#undef lc
+}
+
+static int get_name(ipaddr_t addr, char *name)
+/* Do a reverse lookup on the remote IP address followed by a forward lookup
+ * to check if the host has that address.  Return true if this is so, return
+ * either the true name or the ascii IP address in name[].
+ */
+{
+    struct hostent *he;
+    int i;
+
+    he= gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
+    if (he != NULL) {
+	strcpy(name, he->h_name);
+	he= gethostbyname(name);
+
+	if (he != NULL && he->h_addrtype == AF_INET) {
+	    for (i= 0; he->h_addr_list[i] != NULL; i++) {
+		if (memcmp(he->h_addr_list[i], &addr, sizeof(addr)) == 0) {
+		    strcpy(name, he->h_name);
+		    return 1;
+		}
+	    }
+	}
+    }
+    strcpy(name, inet_ntoa(addr));
+    return 0;
+}
+
+/* "state" and "log" flags, made to be bitwise comparable. */
+#define DEFFAIL		 0x01
+#define FAIL		(0x02 | DEFFAIL)
+#define PASS		 0x04
+
+int servxcheck(ipaddr_t peer, const char *service,
+		void (*logf)(int pass, const char *name))
+{
+    FILE *fp;
+    char word[WLEN];
+    char name[WLEN];
+    int c;
+    int got_name, slist, seen, explicit, state, log;
+    ipaddr_t addr, mask;
+
+    /* Localhost? */
+    if ((peer & HTONL(0xFF000000)) == HTONL(0x7F000000)) return 1;
+
+    if ((fp= fopen(path_servacces, "r")) == nil) {
+	/* Succeed on error, fail if simply nonexistent. */
+	return (errno != ENOENT);
+    }
+
+    slist= 1;		/* Services list (before the colon.) */
+    seen= 0;		/* Given service not yet seen. */
+    explicit= 0;	/* Service mentioned explicitly. */
+    got_name= -1;	/* No reverse lookup done yet. */
+    log= FAIL;		/* By default log failures only. */
+    state= DEFFAIL;	/* Access denied until we know better. */
+
+    while ((c= getword(fp, word)) != EOF) {
+	if (c == ':') {
+	    slist= 0;		/* Switch to access list. */
+	} else
+	if (c == ';') {
+	    slist= 1;		/* Back to list of services. */
+	    seen= 0;
+	} else
+	if (slist) {
+	    /* Traverse services list. */
+
+	    if (match(service, word)) {
+		/* Service has been spotted! */
+		if (match(word, service)) {
+		    /* Service mentioned without wildcards. */
+		    seen= explicit= 1;
+		} else {
+		    /* Matched by a wildcard. */
+		    if (!explicit) seen= 1;
+		}
+	    }
+	} else {
+	    /* Traverse access list. */
+
+	    if (c == 'l' && strcmp(word, "log") == 0) {
+		if (seen) {
+		    /* Log failures and successes. */
+		    log= FAIL|PASS;
+		}
+		continue;
+	    }
+
+	    if (c != '-' && c != '+') {
+		if (logf == nil) {
+		    fprintf(stderr, "%s: strange check word '%s'\n",
+			path_servacces, word);
+		}
+		continue;
+	    }
+
+	    if (seen) {
+		if (state == DEFFAIL) {
+		    /* First check determines the default. */
+		    state= c == '+' ? FAIL : PASS;
+		}
+
+		if ((state == PASS) == (c == '+')) {
+		    /* This check won't change state. */
+		} else
+		if (word[1] == 0) {
+		    /* Lone + or - allows all or none. */
+		    state= c == '-' ? FAIL : PASS;
+		} else
+		if (netspec(word+1, &addr, &mask)) {
+		    /* Remote host is on the specified network? */
+		    if (((peer ^ addr) & mask) == 0) {
+			state= c == '-' ? FAIL : PASS;
+		    }
+		} else {
+		    /* Name check. */
+		    if (got_name == -1) {
+			got_name= get_name(peer, name);
+		    }
+
+		    /* Remote host name matches the word? */
+		    if (!got_name) {
+			state= FAIL;
+		    } else
+		    if (match(name, word+1)) {
+			state= c == '-' ? FAIL : PASS;
+		    }
+		}
+	    }
+	}
+    }
+    fclose(fp);
+
+    if ((log & state) != 0) {
+	/* Log the result of the check. */
+	if (got_name == -1) (void) get_name(peer, name);
+
+	if (logf != nil) {
+	    (*logf)(state == PASS, name);
+	} else {
+	    int lfd;
+	    char line[128+WLEN];
+	    time_t t;
+	    struct tm *tm;
+	    char month[][4]= {
+		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+	    };
+
+	    if ((lfd= open("/usr/adm/log", O_WRONLY|O_APPEND)) != -1) {
+		time(&t);
+		tm= localtime(&t);
+		sprintf(line, "%s %02d %02d:%02d:%02d service '%s' %s to %s\n",
+		    month[tm->tm_mon],
+		    tm->tm_mday,
+		    tm->tm_hour, tm->tm_min, tm->tm_sec,
+		    service,
+		    state == PASS ? "granted" : "denied",
+		    name);
+		(void) write(lfd, line, strlen(line));
+		close(lfd);
+	    }
+	}
+    }
+    return state == PASS;
+}
+
+char *servxfile(const char *file)
+/* Specify a file to use for the access checks other than the default.  Return
+ * the old path.
+ */
+{
+    const char *oldpath= path_servacces;
+    path_servacces= file;
+    return (char *) oldpath;	/* (avoid const poisoning) */
+}
Index: /trunk/minix/lib/ip/sethostent.c
===================================================================
--- /trunk/minix/lib/ip/sethostent.c	(revision 9)
+++ /trunk/minix/lib/ip/sethostent.c	(revision 9)
@@ -0,0 +1,84 @@
+/*	$OpenBSD: sethostent.c,v 1.1 1997/03/12 10:42:11 downsj Exp $	*/
+
+/*
+ * Copyright (c) 1985, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)sethostent.c	8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: sethostent.c,v 8.5 1996/09/28 06:51:07 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: sethostent.c,v 1.1 1997/03/12 10:42:11 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef notyet
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+#else
+#include <sys/types.h>
+#include <net/gen/in.h>
+#include <net/gen/nameser.h>
+#include <net/gen/netdb.h>
+#include <net/gen/resolv.h>
+#endif
+
+void
+sethostent(stayopen)
+	int stayopen;
+{
+	if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+		return;
+	if (stayopen)
+	{
+		_res.options |= RES_STAYOPEN;
+#ifdef __minix_vmd
+		_res.options |= RES_USEVC;
+#endif
+	}
+}
+
+void
+endhostent()
+{
+	_res.options &= ~(RES_STAYOPEN | RES_USEVC);
+	_res_close();
+}
+
+/*
+ * $PchId: sethostent.c,v 1.2 2000/04/01 18:27:16 philip Exp $
+ */
Index: /trunk/minix/lib/ip/setsockopt.c
===================================================================
--- /trunk/minix/lib/ip/setsockopt.c	(revision 9)
+++ /trunk/minix/lib/ip/setsockopt.c	(revision 9)
@@ -0,0 +1,164 @@
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/tcp.h>
+
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+
+#define DEBUG 0
+
+static int _tcp_setsockopt(int socket, int level, int option_name,
+	const void *option_value, socklen_t option_len);
+
+static int _udp_setsockopt(int socket, int level, int option_name,
+	const void *option_value, socklen_t option_len);
+
+int setsockopt(int socket, int level, int option_name,
+        const void *option_value, socklen_t option_len)
+{
+	int r;
+	nwio_tcpopt_t tcpopt;
+	nwio_udpopt_t udpopt;
+
+	r= ioctl(socket, NWIOGTCPOPT, &tcpopt);
+	if (r != -1 || errno != ENOTTY)
+	{
+		if (r == -1)
+		{
+			/* Bad file descriptor */
+			return -1;
+		}
+		return _tcp_setsockopt(socket, level, option_name,
+			option_value, option_len);
+	}
+
+	r= ioctl(socket, NWIOGUDPOPT, &udpopt);
+	if (r != -1 || errno != ENOTTY)
+	{
+		if (r == -1)
+		{
+			/* Bad file descriptor */
+			return -1;
+		}
+		return _udp_setsockopt(socket, level, option_name,
+			option_value, option_len);
+	}
+
+#if DEBUG
+	fprintf(stderr, "setsockopt: not implemented for fd %d\n", socket);
+#endif
+	errno= ENOTSOCK;
+	return -1;
+}
+
+static int _tcp_setsockopt(int socket, int level, int option_name,
+	const void *option_value, socklen_t option_len)
+{
+	int i;
+
+	if (level == SOL_SOCKET && option_name == SO_KEEPALIVE)
+	{
+		if (option_len != sizeof(i))
+		{
+			errno= EINVAL;
+			return -1;
+		}
+		i= *(int *)option_value;
+		if (!i)
+		{
+			/* At the moment there is no way to turn off 
+			 * keepalives.
+			 */
+			errno= ENOSYS;
+			return -1;
+		}
+		return 0;
+	}
+	if (level == SOL_SOCKET && option_name == SO_RCVBUF)
+	{
+		if (option_len != sizeof(i))
+		{
+			errno= EINVAL;
+			return -1;
+		}
+		i= *(int *)option_value;
+		if (i > 32*1024)
+		{
+			/* The receive buffer is limited to 32K at the moment.
+			 */
+			errno= ENOSYS;
+			return -1;
+		}
+		/* There is no way to reduce the receive buffer, do we have to
+		 * let this call fail for smaller buffers?
+		 */
+		return 0;
+	}
+	if (level == SOL_SOCKET && option_name == SO_SNDBUF)
+	{
+		if (option_len != sizeof(i))
+		{
+			errno= EINVAL;
+			return -1;
+		}
+		i= *(int *)option_value;
+		if (i > 32*1024)
+		{
+			/* The send buffer is limited to 32K at the moment.
+			 */
+			errno= ENOSYS;
+			return -1;
+		}
+		/* There is no way to reduce the send buffer, do we have to
+		 * let this call fail for smaller buffers?
+		 */
+		return 0;
+	}
+	if (level == IPPROTO_TCP && option_name == TCP_NODELAY)
+	{
+		if (option_len != sizeof(i))
+		{
+			errno= EINVAL;
+			return -1;
+		}
+		i= *(int *)option_value;
+		if (i)
+		{
+			/* At the moment there is no way to turn on 
+			 * nodelay.
+			 */
+			errno= ENOSYS;
+			return -1;
+		}
+		return 0;
+	}
+#if DEBUG
+	fprintf(stderr, "_tcp_setsocketopt: level %d, name %d\n",
+		level, option_name);
+#endif
+
+	errno= ENOSYS;
+	return -1;
+}
+
+static int _udp_setsockopt(int socket, int level, int option_name,
+	const void *option_value, socklen_t option_len)
+{
+	int i;
+
+#if DEBUG
+	fprintf(stderr, "_udp_setsocketopt: level %d, name %d\n",
+		level, option_name);
+#endif
+
+	errno= ENOSYS;
+	return -1;
+}
+
Index: /trunk/minix/lib/ip/shutdown.c
===================================================================
--- /trunk/minix/lib/ip/shutdown.c	(revision 9)
+++ /trunk/minix/lib/ip/shutdown.c	(revision 9)
@@ -0,0 +1,54 @@
+#include <errno.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+
+#define DEBUG 1
+
+static int _tcp_shutdown(int socket, int how);
+
+int shutdown(int socket, int how)
+{
+	int r;
+	nwio_tcpconf_t tcpconf;
+
+	r= ioctl(socket, NWIOGTCPCONF, &tcpconf);
+	if (r != -1 || errno != ENOTTY)
+	{
+		if (r == -1)
+		{
+			/* Bad file descriptor */
+			return -1;
+		}
+		return _tcp_shutdown(socket, how);
+	}
+#if DEBUG
+	fprintf(stderr, "shutdown: not implemented for fd %d\n", socket);
+#endif
+	errno= ENOSYS;
+	return -1;
+}
+
+static int _tcp_shutdown(int socket, int how)
+{
+	int r;
+
+	if (how == SHUT_WR || how == SHUT_RDWR)
+	{
+		r= ioctl(socket, NWIOTCPSHUTDOWN, NULL);
+		if (r == -1)
+			return -1;
+		if (how == SHUT_WR)
+			return 0;
+	}
+
+	/* We can't shutdown the read side of the socket. */
+	errno= ENOSYS;
+	return -1;
+}
+
+
Index: /trunk/minix/lib/ip/socket.c
===================================================================
--- /trunk/minix/lib/ip/socket.c	(revision 9)
+++ /trunk/minix/lib/ip/socket.c	(revision 9)
@@ -0,0 +1,90 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#include <net/netlib.h>
+#include <netinet/in.h>
+
+#define DEBUG 0
+
+static int _tcp_socket(int protocol);
+static int _udp_socket(int protocol);
+
+int socket(int domain, int type, int protocol)
+{
+#if DEBUG
+	fprintf(stderr, "socket: domain %d, type %d, protocol %d\n",
+		domain, type, protocol);
+#endif
+	if (domain != AF_INET)
+	{
+#if DEBUG
+		fprintf(stderr, "socket: bad domain %d\n", domain);
+#endif
+		errno= EAFNOSUPPORT;
+		return -1;
+	}
+	if (type == SOCK_STREAM)
+		return _tcp_socket(protocol);
+
+	if (type == SOCK_DGRAM)
+		return _udp_socket(protocol);
+
+#if DEBUG
+	fprintf(stderr, "socket: nothing for domain %d, type %d, protocol %d\n",
+		domain, type, protocol);
+#endif
+	errno= EPROTOTYPE;
+	return -1;
+}
+
+static int _tcp_socket(int protocol)
+{
+	int fd;
+	if (protocol != 0 && protocol != IPPROTO_TCP)
+	{
+#if DEBUG
+		fprintf(stderr, "socket(tcp): bad protocol %d\n", protocol);
+#endif
+		errno= EPROTONOSUPPORT;
+		return -1;
+	}
+	fd= open(TCP_DEVICE, O_RDWR);
+	return fd;
+}
+
+static int _udp_socket(int protocol)
+{
+	int r, fd, t_errno;
+	struct sockaddr_in sin;
+
+	if (protocol != 0 && protocol != IPPROTO_UDP)
+	{
+#if DEBUG
+		fprintf(stderr, "socket(udp): bad protocol %d\n", protocol);
+#endif
+		errno= EPROTONOSUPPORT;
+		return -1;
+	}
+	fd= open(UDP_DEVICE, O_RDWR);
+	if (fd == -1)
+		return fd;
+
+	/* Bind is implict for UDP sockets? */
+	sin.sin_family= AF_INET;
+	sin.sin_addr.s_addr= INADDR_ANY;
+	sin.sin_port= 0;
+	r= bind(fd, (struct sockaddr *)&sin, sizeof(sin));
+	if (r != 0)
+	{
+		t_errno= errno;
+		close(fd);
+		errno= t_errno;
+		return -1;
+	}
+	return fd;
+}
+
Index: /trunk/minix/lib/ip/strcasecmp.c
===================================================================
--- /trunk/minix/lib/ip/strcasecmp.c	(revision 9)
+++ /trunk/minix/lib/ip/strcasecmp.c	(revision 9)
@@ -0,0 +1,43 @@
+/*
+strcasecmp.c
+
+Created Oct 14, 1991 by Philip Homburg
+*/
+
+#include <ctype.h>
+#include <string.h>
+
+#ifdef __STDC__
+#define _CONST	const
+#else
+#define _CONST
+#endif
+
+int
+strcasecmp(s1, s2)
+_CONST char *s1, *s2;
+{
+	int c1, c2;
+	while (c1= toupper(*s1++), c2= toupper(*s2++), c1 == c2 && (c1 & c2))
+		;
+	if (c1 & c2)
+		return c1 < c2 ? -1 : 1;
+	return c1 ? 1 : (c2 ? -1 : 0);
+}
+
+int
+strncasecmp(s1, s2, len)
+_CONST char *s1, *s2;
+size_t len;
+{
+	int c1, c2;
+	do {
+		if (len == 0)
+			return 0;
+		len--;
+	} while (c1= toupper(*s1++), c2= toupper(*s2++), c1 == c2 && (c1 & c2))
+		;
+	if (c1 & c2)
+		return c1 < c2 ? -1 : 1;
+	return c1 ? 1 : (c2 ? -1 : 0);
+}
Index: /trunk/minix/lib/math/Makedepend-ack
===================================================================
--- /trunk/minix/lib/math/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/math/Makedepend-ack	(revision 9)
@@ -0,0 +1,20 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' asin.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' atan.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' atan2.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' ceil.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' exp.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fabs.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' floor.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fmod.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' hugeval.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' log.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' log10.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pow.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sin.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sinh.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sqrt.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' tan.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' tanh.c | sed -e 's:^\(.\):../obj-ack//./math/\1:' >> .depend-ack
Index: /trunk/minix/lib/math/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/math/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/math/Makedepend-gnu	(revision 9)
@@ -0,0 +1,20 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' asin.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' atan.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' atan2.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' ceil.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' exp.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fabs.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' floor.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fmod.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' hugeval.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' log.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' log10.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pow.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sin.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sinh.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sqrt.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' tan.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' tanh.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./math/\1:' >> .depend-gnu
Index: /trunk/minix/lib/math/Makefile
===================================================================
--- /trunk/minix/lib/math/Makefile	(revision 9)
+++ /trunk/minix/lib/math/Makefile	(revision 9)
@@ -0,0 +1,164 @@
+#Generated from ./math/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./math ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./math ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libc.a
+
+../obj-ack//libc.a: ../obj-ack//libc.a(asin.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(atan.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(atan2.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ceil.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(exp.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fabs.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(floor.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fmod.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(hugeval.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(log.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(log10.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(pow.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sin.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sinh.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sqrt.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(tan.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(tanh.o)
+
+../obj-ack//libc.a:
+	ar cr ../obj-ack//libc.a ../obj-ack//./math/*.o
+	rm ../obj-ack//./math/*.o
+
+../obj-ack//libc.a(asin.o): asin.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/asin.o asin.c
+../obj-ack//libc.a(atan.o): atan.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/atan.o atan.c
+../obj-ack//libc.a(atan2.o): atan2.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/atan2.o atan2.c
+../obj-ack//libc.a(ceil.o): ceil.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/ceil.o ceil.c
+../obj-ack//libc.a(exp.o): exp.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/exp.o exp.c
+../obj-ack//libc.a(fabs.o): fabs.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/fabs.o fabs.c
+../obj-ack//libc.a(floor.o): floor.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/floor.o floor.c
+../obj-ack//libc.a(fmod.o): fmod.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/fmod.o fmod.c
+../obj-ack//libc.a(hugeval.o): hugeval.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/hugeval.o hugeval.c
+../obj-ack//libc.a(log.o): log.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/log.o log.c
+../obj-ack//libc.a(log10.o): log10.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/log10.o log10.c
+../obj-ack//libc.a(pow.o): pow.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/pow.o pow.c
+../obj-ack//libc.a(sin.o): sin.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/sin.o sin.c
+../obj-ack//libc.a(sinh.o): sinh.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/sinh.o sinh.c
+../obj-ack//libc.a(sqrt.o): sqrt.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/sqrt.o sqrt.c
+../obj-ack//libc.a(tan.o): tan.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/tan.o tan.c
+../obj-ack//libc.a(tanh.o): tanh.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./math/tanh.o tanh.c
+
+all-gnu: ../obj-gnu/libc.a
+
+../obj-gnu/libc.a: ../obj-gnu/./math/asin.o
+../obj-gnu/libc.a: ../obj-gnu/./math/atan.o
+../obj-gnu/libc.a: ../obj-gnu/./math/atan2.o
+../obj-gnu/libc.a: ../obj-gnu/./math/ceil.o
+../obj-gnu/libc.a: ../obj-gnu/./math/exp.o
+../obj-gnu/libc.a: ../obj-gnu/./math/fabs.o
+../obj-gnu/libc.a: ../obj-gnu/./math/floor.o
+../obj-gnu/libc.a: ../obj-gnu/./math/fmod.o
+../obj-gnu/libc.a: ../obj-gnu/./math/hugeval.o
+../obj-gnu/libc.a: ../obj-gnu/./math/log.o
+../obj-gnu/libc.a: ../obj-gnu/./math/log10.o
+../obj-gnu/libc.a: ../obj-gnu/./math/pow.o
+../obj-gnu/libc.a: ../obj-gnu/./math/sin.o
+../obj-gnu/libc.a: ../obj-gnu/./math/sinh.o
+../obj-gnu/libc.a: ../obj-gnu/./math/sqrt.o
+../obj-gnu/libc.a: ../obj-gnu/./math/tan.o
+../obj-gnu/libc.a: ../obj-gnu/./math/tanh.o
+
+../obj-gnu/libc.a:
+	gar cr ../obj-gnu/libc.a $?
+
+../obj-gnu/./math/asin.o: asin.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/asin.o asin.c
+
+../obj-gnu/./math/atan.o: atan.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/atan.o atan.c
+
+../obj-gnu/./math/atan2.o: atan2.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/atan2.o atan2.c
+
+../obj-gnu/./math/ceil.o: ceil.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/ceil.o ceil.c
+
+../obj-gnu/./math/exp.o: exp.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/exp.o exp.c
+
+../obj-gnu/./math/fabs.o: fabs.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/fabs.o fabs.c
+
+../obj-gnu/./math/floor.o: floor.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/floor.o floor.c
+
+../obj-gnu/./math/fmod.o: fmod.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/fmod.o fmod.c
+
+../obj-gnu/./math/hugeval.o: hugeval.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/hugeval.o hugeval.c
+
+../obj-gnu/./math/log.o: log.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/log.o log.c
+
+../obj-gnu/./math/log10.o: log10.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/log10.o log10.c
+
+../obj-gnu/./math/pow.o: pow.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/pow.o pow.c
+
+../obj-gnu/./math/sin.o: sin.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/sin.o sin.c
+
+../obj-gnu/./math/sinh.o: sinh.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/sinh.o sinh.c
+
+../obj-gnu/./math/sqrt.o: sqrt.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/sqrt.o sqrt.c
+
+../obj-gnu/./math/tan.o: tan.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/tan.o tan.c
+
+../obj-gnu/./math/tanh.o: tanh.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./math/tanh.o tanh.c
+
+
+
+
+clean::
+	rm -f ../obj-ack//./math/*
+	rm -f ../obj-gnu/./math/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/math/Makefile.in
===================================================================
--- /trunk/minix/lib/math/Makefile.in	(revision 9)
+++ /trunk/minix/lib/math/Makefile.in	(revision 9)
@@ -0,0 +1,26 @@
+# Makefile for lib/math.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
+
+LIBRARIES=libc
+
+libc_FILES=" \
+	asin.c \
+	atan.c \
+	atan2.c \
+	ceil.c \
+	exp.c \
+	fabs.c \
+	floor.c \
+	fmod.c \
+	hugeval.c \
+	log.c \
+	log10.c \
+	pow.c \
+	sin.c \
+	sinh.c \
+	sqrt.c \
+	tan.c \
+	tanh.c"
+
+TYPE=both
Index: /trunk/minix/lib/math/asin.c
===================================================================
--- /trunk/minix/lib/math/asin.c	(revision 9)
+++ /trunk/minix/lib/math/asin.c	(revision 9)
@@ -0,0 +1,82 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+/* $Header: /cvsup/minix/src/lib/math/asin.c,v 1.1.1.1 2005/04/21 14:56:24 beng Exp $ */
+
+#include	<math.h>
+#include	<errno.h>
+#include	"localmath.h"
+
+static double
+asin_acos(double x, int cosfl)
+{
+	int negative = x < 0;
+	int     i;
+	double  g;
+	static double p[] = {
+		-0.27368494524164255994e+2,
+		 0.57208227877891731407e+2,
+		-0.39688862997540877339e+2,
+		 0.10152522233806463645e+2,
+		-0.69674573447350646411e+0
+	};
+	static double q[] = {
+		-0.16421096714498560795e+3,
+		 0.41714430248260412556e+3,
+		-0.38186303361750149284e+3,
+		 0.15095270841030604719e+3,
+		-0.23823859153670238830e+2,
+		 1.0
+	};
+
+	if (__IsNan(x)) {
+		errno = EDOM;
+		return x;
+	}
+
+	if (negative) {
+		x = -x;
+	}
+	if (x > 0.5) {
+		i = 1;
+		if (x > 1) {
+			errno = EDOM;
+			return 0;
+		}
+		g = 0.5 - 0.5 * x;
+		x = - sqrt(g);
+		x += x;
+	}
+	else {
+		/* ??? avoid underflow ??? */
+		i = 0;
+		g = x * x;
+	}
+	x += x * g * POLYNOM4(g, p) / POLYNOM5(g, q);
+	if (cosfl) {
+		if (! negative) x = -x;
+	}
+	if ((cosfl == 0) == (i == 1)) {
+		x = (x + M_PI_4) + M_PI_4;
+	}
+	else if (cosfl && negative && i == 1) {
+		x = (x + M_PI_2) + M_PI_2;
+	}
+	if (! cosfl && negative) x = -x;
+	return x;
+}
+
+double
+asin(double x)
+{
+	return asin_acos(x, 0);
+}
+
+double
+acos(double x)
+{
+	return asin_acos(x, 1);
+}
Index: /trunk/minix/lib/math/atan.c
===================================================================
--- /trunk/minix/lib/math/atan.c	(revision 9)
+++ /trunk/minix/lib/math/atan.c	(revision 9)
@@ -0,0 +1,72 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+/* $Header: /cvsup/minix/src/lib/math/atan.c,v 1.1.1.1 2005/04/21 14:56:24 beng Exp $ */
+
+#include	<float.h>
+#include	<math.h>
+#include	<errno.h>
+#include	"localmath.h"
+
+double
+atan(double x)
+{
+	/*      Algorithm and coefficients from:
+			"Software manual for the elementary functions"
+			by W.J. Cody and W. Waite, Prentice-Hall, 1980
+	*/
+
+	static double p[] = {
+		-0.13688768894191926929e+2,
+		-0.20505855195861651981e+2,
+		-0.84946240351320683534e+1,
+		-0.83758299368150059274e+0
+	};
+	static double q[] = {
+		 0.41066306682575781263e+2,
+		 0.86157349597130242515e+2,
+		 0.59578436142597344465e+2,
+		 0.15024001160028576121e+2,
+		 1.0
+	};
+	static double a[] = {
+		0.0,
+		0.52359877559829887307710723554658381,  /* pi/6 */
+		M_PI_2,
+		1.04719755119659774615421446109316763   /* pi/3 */
+	};
+
+	int     neg = x < 0;
+	int     n;
+	double  g;
+
+	if (__IsNan(x)) {
+		errno = EDOM;
+		return x;
+	}
+	if (neg) {
+		x = -x;
+	}
+	if (x > 1.0) {
+		x = 1.0/x;
+		n = 2;
+	}
+	else    n = 0;
+
+	if (x > 0.26794919243112270647) {       /* 2-sqtr(3) */
+		n = n + 1;
+		x = (((0.73205080756887729353*x-0.5)-0.5)+x)/
+			(1.73205080756887729353+x);
+	}
+
+	/* ??? avoid underflow ??? */
+
+	g = x * x;
+	x += x * g * POLYNOM3(g, p) / POLYNOM4(g, q);
+	if (n > 1) x = -x;
+	x += a[n];
+	return neg ? -x : x;
+}
Index: /trunk/minix/lib/math/atan2.c
===================================================================
--- /trunk/minix/lib/math/atan2.c	(revision 9)
+++ /trunk/minix/lib/math/atan2.c	(revision 9)
@@ -0,0 +1,42 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+/* $Header: /cvsup/minix/src/lib/math/atan2.c,v 1.1.1.1 2005/04/21 14:56:24 beng Exp $ */
+
+#include	<math.h>
+#include	<errno.h>
+#include	"localmath.h"
+
+double
+atan2(double y, double x)
+{
+	double absx, absy, val;
+
+	if (x == 0 && y == 0) {
+		errno = EDOM;
+		return 0;
+	}
+	absy = y < 0 ? -y : y;
+	absx = x < 0 ? -x : x;
+	if (absy - absx == absy) {
+		/* x negligible compared to y */
+		return y < 0 ? -M_PI_2 : M_PI_2;
+	}
+	if (absx - absy == absx) {
+		/* y negligible compared to x */
+		val = 0.0;
+	}
+	else	val = atan(y/x);
+	if (x > 0) {
+		/* first or fourth quadrant; already correct */
+		return val;
+	}
+	if (y < 0) {
+		/* third quadrant */
+		return val - M_PI;
+	}
+	return val + M_PI;
+}
Index: /trunk/minix/lib/math/ceil.c
===================================================================
--- /trunk/minix/lib/math/ceil.c	(revision 9)
+++ /trunk/minix/lib/math/ceil.c	(revision 9)
@@ -0,0 +1,20 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+/* $Header: /cvsup/minix/src/lib/math/ceil.c,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+
+#include	<math.h>
+
+double
+ceil(double x)
+{
+	double val;
+
+	return modf(x, &val) > 0 ? val + 1.0 : val ;
+	/*	this also works if modf always returns a positive
+		fractional part
+	*/
+}
Index: /trunk/minix/lib/math/exp.c
===================================================================
--- /trunk/minix/lib/math/exp.c	(revision 9)
+++ /trunk/minix/lib/math/exp.c	(revision 9)
@@ -0,0 +1,72 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+/* $Header: /cvsup/minix/src/lib/math/exp.c,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+
+#include	<math.h>
+#include	<float.h>
+#include	<errno.h>
+#include	"localmath.h"
+
+
+double
+exp(double x)
+{
+	/*	Algorithm and coefficients from:
+			"Software manual for the elementary functions"
+			by W.J. Cody and W. Waite, Prentice-Hall, 1980
+	*/
+
+	static double p[] = {
+		0.25000000000000000000e+0,
+		0.75753180159422776666e-2,
+		0.31555192765684646356e-4
+	};
+
+	static double q[] = {
+		0.50000000000000000000e+0,
+		0.56817302698551221787e-1,
+		0.63121894374398503557e-3,
+		0.75104028399870046114e-6
+	};
+	double	xn, g;
+	int	n;
+	int	negative = x < 0;
+
+	if (__IsNan(x)) {
+		errno = EDOM;
+		return x;
+	}
+	if (x < M_LN_MIN_D) {
+		errno = ERANGE;
+		return 0.0;
+	}
+	if (x > M_LN_MAX_D) {
+		errno = ERANGE;
+		return HUGE_VAL;
+	}
+
+	if (negative) x = -x;
+ 
+	/* ??? avoid underflow ??? */
+
+	n = x * M_LOG2E + 0.5;	/* 1/ln(2) = log2(e), 0.5 added for rounding */
+	xn = n;
+	{
+		double	x1 = (long) x;
+		double	x2 = x - x1;
+
+		g = ((x1-xn*0.693359375)+x2) - xn*(-2.1219444005469058277e-4);
+	}
+	if (negative) {
+		g = -g;
+		n = -n;
+	}
+	xn = g * g;
+	x = g * POLYNOM2(xn, p);
+	n += 1;
+	return (ldexp(0.5 + x/(POLYNOM3(xn, q) - x), n));
+}
Index: /trunk/minix/lib/math/fabs.c
===================================================================
--- /trunk/minix/lib/math/fabs.c	(revision 9)
+++ /trunk/minix/lib/math/fabs.c	(revision 9)
@@ -0,0 +1,13 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+/* $Header: /cvsup/minix/src/lib/math/fabs.c,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+
+double
+fabs(double x)
+{
+	return  x < 0 ? -x : x;
+}
Index: /trunk/minix/lib/math/floor.c
===================================================================
--- /trunk/minix/lib/math/floor.c	(revision 9)
+++ /trunk/minix/lib/math/floor.c	(revision 9)
@@ -0,0 +1,20 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+/* $Header: /cvsup/minix/src/lib/math/floor.c,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+
+#include	<math.h>
+
+double
+floor(double x)
+{
+	double val;
+
+	return modf(x, &val) < 0 ? val - 1.0 : val ;
+	/*	this also works if modf always returns a positive
+		fractional part
+	*/
+}
Index: /trunk/minix/lib/math/fmod.c
===================================================================
--- /trunk/minix/lib/math/fmod.c	(revision 9)
+++ /trunk/minix/lib/math/fmod.c	(revision 9)
@@ -0,0 +1,34 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Hans van Eck
+ */
+/* $Header: /cvsup/minix/src/lib/math/fmod.c,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+
+#include	<math.h>
+#include	<errno.h>
+
+double
+fmod(double x, double y)
+{
+	long	i;
+	double val;
+	double frac;
+
+	if (y == 0) {
+		errno = EDOM;
+		return 0;
+	}
+	frac = modf( x / y, &val);
+
+	return frac * y;
+
+/*
+	val = x / y;
+	if (val > LONG_MIN && val < LONG_MAX) {
+		i = val;
+		return x - i * y;
+	}
+*/
+}
Index: /trunk/minix/lib/math/hugeval.c
===================================================================
--- /trunk/minix/lib/math/hugeval.c	(revision 9)
+++ /trunk/minix/lib/math/hugeval.c	(revision 9)
@@ -0,0 +1,14 @@
+/*
+ * (c) copyright 1990 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Hans van Eck
+ */
+/* $Header: /cvsup/minix/src/lib/math/hugeval.c,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+#include	<math.h>
+
+double
+__huge_val(void)
+{
+	return 1.0e+1000;	/* This will generate a warning */
+}
Index: /trunk/minix/lib/math/localmath.h
===================================================================
--- /trunk/minix/lib/math/localmath.h	(revision 9)
+++ /trunk/minix/lib/math/localmath.h	(revision 9)
@@ -0,0 +1,42 @@
+/*
+ * localmath.h - This header is used by the mathematical library.
+ */
+/* $Header: /cvsup/minix/src/lib/math/localmath.h,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+
+/* some constants (Hart & Cheney) */
+#define	M_PI		3.14159265358979323846264338327950288
+#define	M_2PI		6.28318530717958647692528676655900576
+#define	M_3PI_4		2.35619449019234492884698253745962716
+#define	M_PI_2		1.57079632679489661923132169163975144
+#define	M_3PI_8		1.17809724509617246442349126872981358
+#define	M_PI_4		0.78539816339744830961566084581987572
+#define	M_PI_8		0.39269908169872415480783042290993786
+#define	M_1_PI		0.31830988618379067153776752674502872
+#define	M_2_PI		0.63661977236758134307553505349005744
+#define	M_4_PI		1.27323954473516268615107010698011488
+#define	M_E		2.71828182845904523536028747135266250
+#define	M_LOG2E		1.44269504088896340735992468100189213
+#define	M_LOG10E	0.43429448190325182765112891891660508
+#define	M_LN2		0.69314718055994530941723212145817657
+#define	M_LN10		2.30258509299404568401799145468436421
+#define	M_SQRT2		1.41421356237309504880168872420969808
+#define	M_1_SQRT2	0.70710678118654752440084436210484904
+#define	M_EULER		0.57721566490153286060651209008240243
+
+/* macros for constructing polynomials */
+#define	POLYNOM1(x, a)	((a)[1]*(x)+(a)[0])
+#define	POLYNOM2(x, a)	(POLYNOM1((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM3(x, a)	(POLYNOM2((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM4(x, a)	(POLYNOM3((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM5(x, a)	(POLYNOM4((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM6(x, a)	(POLYNOM5((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM7(x, a)	(POLYNOM6((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM8(x, a)	(POLYNOM7((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM9(x, a)	(POLYNOM8((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM10(x, a)	(POLYNOM9((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM11(x, a)	(POLYNOM10((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM12(x, a)	(POLYNOM11((x),(a)+1)*(x)+(a)[0])
+#define	POLYNOM13(x, a)	(POLYNOM12((x),(a)+1)*(x)+(a)[0])
+
+#define	M_LN_MAX_D	(M_LN2 * DBL_MAX_EXP)
+#define	M_LN_MIN_D	(M_LN2 * (DBL_MIN_EXP - 1))
Index: /trunk/minix/lib/math/log.c
===================================================================
--- /trunk/minix/lib/math/log.c	(revision 9)
+++ /trunk/minix/lib/math/log.c	(revision 9)
@@ -0,0 +1,67 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+/* $Header: /cvsup/minix/src/lib/math/log.c,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+
+#include	<math.h>
+#include	<float.h>
+#include	<errno.h>
+#include	"localmath.h"
+
+double
+log(double x)
+{
+	/*	Algorithm and coefficients from:
+			"Software manual for the elementary functions"
+			by W.J. Cody and W. Waite, Prentice-Hall, 1980
+	*/
+	static double a[] = {
+		-0.64124943423745581147e2,
+		 0.16383943563021534222e2,
+		-0.78956112887491257267e0
+	};
+	static double b[] = {
+		-0.76949932108494879777e3,
+		 0.31203222091924532844e3,
+		-0.35667977739034646171e2,
+		 1.0
+	};
+
+	double	znum, zden, z, w;
+	int	exponent;
+
+	if (__IsNan(x)) {
+		errno = EDOM;
+		return x;
+	}
+	if (x < 0) {
+		errno = EDOM;
+		return -HUGE_VAL;
+	}
+	else if (x == 0) {
+		errno = ERANGE;
+		return -HUGE_VAL;
+	}
+
+	if (x <= DBL_MAX) {
+	}
+	else return x;	/* for infinity and Nan */
+	x = frexp(x, &exponent);
+	if (x > M_1_SQRT2) {
+		znum = (x - 0.5) - 0.5;
+		zden = x * 0.5 + 0.5;
+	}
+	else {
+		znum = x - 0.5;
+		zden = znum * 0.5 + 0.5;
+		exponent--;
+	}
+	z = znum/zden; w = z * z;
+	x = z + z * w * (POLYNOM2(w,a)/POLYNOM3(w,b));
+	z = exponent;
+	x += z * (-2.121944400546905827679e-4);
+	return x + z * 0.693359375;
+}
Index: /trunk/minix/lib/math/log10.c
===================================================================
--- /trunk/minix/lib/math/log10.c	(revision 9)
+++ /trunk/minix/lib/math/log10.c	(revision 9)
@@ -0,0 +1,30 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+/* $Header: /cvsup/minix/src/lib/math/log10.c,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+
+#include	<math.h>
+#include	<errno.h>
+#include	"localmath.h"
+
+double
+log10(double x)
+{
+	if (__IsNan(x)) {
+		errno = EDOM;
+		return x;
+	}
+	if (x < 0) {
+		errno = EDOM;
+		return -HUGE_VAL;
+	}
+	else if (x == 0) {
+		errno = ERANGE;
+		return -HUGE_VAL;
+	}
+
+	return log(x) / M_LN10;
+}
Index: /trunk/minix/lib/math/pow.c
===================================================================
--- /trunk/minix/lib/math/pow.c	(revision 9)
+++ /trunk/minix/lib/math/pow.c	(revision 9)
@@ -0,0 +1,54 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+/* $Header: /cvsup/minix/src/lib/math/pow.c,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+
+#include	<math.h>
+#include	<float.h>
+#include	<errno.h>
+#include	"localmath.h"
+
+double
+pow(double x, double y)
+{
+	/*	Simple version for now. The Cody and Waite book has
+		a very complicated, much more precise version, but
+		this version has machine-dependent arrays A1 and A2,
+		and I don't know yet how to solve this ???
+	*/
+	double dummy;
+	int	result_neg = 0;
+
+	if ((x == 0 && y == 0) ||
+	    (x < 0 && modf(y, &dummy) != 0)) {
+		errno = EDOM;
+		return 0;
+	}
+
+	if (x == 0) return x;
+
+	if (x < 0) {
+		if (modf(y/2.0, &dummy) != 0) {
+			/* y was odd */
+			result_neg = 1;
+		}
+		x = -x;
+	}
+	x = log(x);
+
+	if (x < 0) {
+		x = -x;
+		y = -y;
+	}
+	/* Beware of overflow in the multiplication */
+	if (x > 1.0 && y > DBL_MAX/x) {
+		errno = ERANGE;
+		return result_neg ? -HUGE_VAL : HUGE_VAL;
+	}
+
+	x = exp(x * y);
+	return result_neg ? -x : x;
+}
Index: /trunk/minix/lib/math/sin.c
===================================================================
--- /trunk/minix/lib/math/sin.c	(revision 9)
+++ /trunk/minix/lib/math/sin.c	(revision 9)
@@ -0,0 +1,99 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+/* $Header: /cvsup/minix/src/lib/math/sin.c,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+
+#include	<math.h>
+#include	<float.h>
+#include	<errno.h>
+#include	"localmath.h"
+
+static double
+sinus(double x, int cos_flag)
+{
+	/*      Algorithm and coefficients from:
+			"Software manual for the elementary functions"
+			by W.J. Cody and W. Waite, Prentice-Hall, 1980
+	*/
+
+	static double r[] = {
+		-0.16666666666666665052e+0,
+		 0.83333333333331650314e-2,
+		-0.19841269841201840457e-3,
+		 0.27557319210152756119e-5,
+		-0.25052106798274584544e-7,
+		 0.16058936490371589114e-9,
+		-0.76429178068910467734e-12,
+		 0.27204790957888846175e-14
+	};
+
+	double  y;
+	int     neg = 1;
+
+	if (__IsNan(x)) {
+		errno = EDOM;
+		return x;
+	}
+	if (x < 0) {
+		x = -x;
+		neg = -1;
+	}
+	if (cos_flag) {
+		neg = 1;
+		y = M_PI_2 + x;
+	}
+	else    y = x;
+
+	/* ??? avoid loss of significance, if y is too large, error ??? */
+
+	y = y * M_1_PI + 0.5;
+
+	if (y >= DBL_MAX/M_PI) return 0.0;
+
+	/*      Use extended precision to calculate reduced argument.
+		Here we used 12 bits of the mantissa for a1.
+		Also split x in integer part x1 and fraction part x2.
+	*/
+#define A1 3.1416015625
+#define A2 -8.908910206761537356617e-6
+	{
+		double x1, x2;
+
+		modf(y, &y);
+		if (modf(0.5*y, &x1)) neg = -neg;
+		if (cos_flag) y -= 0.5;
+		x2 = modf(x, &x1);
+		x = x1 - y * A1;
+		x += x2;
+		x -= y * A2;
+#undef A1
+#undef A2
+	}
+ 
+	if (x < 0) {
+		neg = -neg;
+		x = -x;
+	}
+
+	/* ??? avoid underflow ??? */
+
+	y = x * x;
+	x += x * y * POLYNOM7(y, r);
+	return neg==-1 ? -x : x;
+}
+
+double
+sin(double x)
+{
+	return sinus(x, 0);
+}
+
+double
+cos(double x)
+{
+	if (x < 0) x = -x;
+	return sinus(x, 1);
+}
Index: /trunk/minix/lib/math/sinh.c
===================================================================
--- /trunk/minix/lib/math/sinh.c	(revision 9)
+++ /trunk/minix/lib/math/sinh.c	(revision 9)
@@ -0,0 +1,81 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+/* $Header: /cvsup/minix/src/lib/math/sinh.c,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+
+#include	<math.h>
+#include	<float.h>
+#include	<errno.h>
+#include	"localmath.h"
+
+static double
+sinh_cosh(double x, int cosh_flag)
+{
+	/*	Algorithm and coefficients from:
+			"Software manual for the elementary functions"
+			by W.J. Cody and W. Waite, Prentice-Hall, 1980
+	*/
+
+	static double p[] = {
+		-0.35181283430177117881e+6,
+		-0.11563521196851768270e+5,
+		-0.16375798202630751372e+3,
+		-0.78966127417357099479e+0
+	};
+	static double q[] = {
+		-0.21108770058106271242e+7,
+		 0.36162723109421836460e+5,
+		-0.27773523119650701167e+3,
+		 1.0
+	};
+	int	negative = x < 0;
+	double	y = negative ? -x : x;
+
+	if (__IsNan(x)) {
+		errno = EDOM;
+		return x;
+	}
+	if (! cosh_flag && y <= 1.0) {
+		/* ??? check for underflow ??? */
+		y = y * y;
+		return x + x * y * POLYNOM3(y, p)/POLYNOM3(y,q);
+	}
+
+	if (y >= M_LN_MAX_D) {
+		/* exp(y) would cause overflow */
+#define LNV	0.69316101074218750000e+0
+#define VD2M1	0.52820835025874852469e-4
+		double	w = y - LNV;
+		
+		if (w < M_LN_MAX_D+M_LN2-LNV) {
+			x = exp(w);
+			x += VD2M1 * x;
+		}
+		else {
+			errno = ERANGE;
+			x = HUGE_VAL;
+		}
+	}
+	else {
+		double	z = exp(y);
+		
+		x = 0.5 * (z + (cosh_flag ? 1.0 : -1.0)/z);
+	}
+	return negative ? -x : x;
+}
+
+double
+sinh(double x)
+{
+	return sinh_cosh(x, 0);
+}
+
+double
+cosh(double x)
+{
+	if (x < 0) x = -x;
+	return sinh_cosh(x, 1);
+}
Index: /trunk/minix/lib/math/sqrt.c
===================================================================
--- /trunk/minix/lib/math/sqrt.c	(revision 9)
+++ /trunk/minix/lib/math/sqrt.c	(revision 9)
@@ -0,0 +1,43 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+/* $Header: /cvsup/minix/src/lib/math/sqrt.c,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+
+#include	<math.h>
+#include	<float.h>
+#include	<errno.h>
+
+#define NITER	5
+
+double
+sqrt(double x)
+{
+	int exponent;
+	double val;
+
+	if (__IsNan(x)) {
+		errno = EDOM;
+		return x;
+	}
+	if (x <= 0) {
+		if (x < 0) errno = EDOM;
+		return 0;
+	}
+
+	if (x > DBL_MAX) return x;	/* for infinity */
+
+	val = frexp(x, &exponent);
+	if (exponent & 1) {
+		exponent--;
+		val *= 2;
+	}
+	val = ldexp(val + 1.0, exponent/2 - 1);
+	/* was: val = (val + 1.0)/2.0; val = ldexp(val, exponent/2); */
+	for (exponent = NITER - 1; exponent >= 0; exponent--) {
+		val = (val + x / val) / 2.0;
+	}
+	return val;
+}
Index: /trunk/minix/lib/math/tan.c
===================================================================
--- /trunk/minix/lib/math/tan.c	(revision 9)
+++ /trunk/minix/lib/math/tan.c	(revision 9)
@@ -0,0 +1,76 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+/* $Header: /cvsup/minix/src/lib/math/tan.c,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+
+#include	<math.h>
+#include	<float.h>
+#include	<errno.h>
+#include	"localmath.h"
+
+double
+tan(double x)
+{
+	/*      Algorithm and coefficients from:
+			"Software manual for the elementary functions"
+			by W.J. Cody and W. Waite, Prentice-Hall, 1980
+	*/
+
+	int negative = x < 0;
+	int invert = 0;
+	double  y;
+	static double   p[] = {
+		 1.0,
+		-0.13338350006421960681e+0,
+		 0.34248878235890589960e-2,
+		-0.17861707342254426711e-4
+	};
+	static double   q[] = {
+		 1.0,
+		-0.46671683339755294240e+0,
+		 0.25663832289440112864e-1,
+		-0.31181531907010027307e-3,
+		 0.49819433993786512270e-6
+	};
+
+	if (__IsNan(x)) {
+		errno = EDOM;
+		return x;
+	}
+	if (negative) x = -x;
+ 
+	/* ??? avoid loss of significance, error if x is too large ??? */
+
+	y = x * M_2_PI + 0.5;
+
+	if (y >= DBL_MAX/M_PI_2) return 0.0;
+
+	/*      Use extended precision to calculate reduced argument.
+		Here we used 12 bits of the mantissa for a1.
+		Also split x in integer part x1 and fraction part x2.
+	*/
+    #define A1 1.57080078125
+    #define A2 -4.454455103380768678308e-6
+	{
+		double x1, x2;
+
+		modf(y, &y);
+		if (modf(0.5*y, &x1)) invert = 1;
+		x2 = modf(x, &x1);
+		x = x1 - y * A1;
+		x += x2;
+		x -= y * A2;
+    #undef A1
+    #undef A2
+	}
+
+	/* ??? avoid underflow ??? */
+	y = x * x;
+	x += x * y * POLYNOM2(y, p+1);
+	y = POLYNOM4(y, q);
+	if (negative) x = -x;
+	return invert ? -y/x : x/y;
+}
Index: /trunk/minix/lib/math/tanh.c
===================================================================
--- /trunk/minix/lib/math/tanh.c	(revision 9)
+++ /trunk/minix/lib/math/tanh.c	(revision 9)
@@ -0,0 +1,55 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+/* $Header: /cvsup/minix/src/lib/math/tanh.c,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+
+#include	<float.h>
+#include	<math.h>
+#include	<errno.h>
+#include	"localmath.h"
+
+double
+tanh(double x)
+{
+	/*	Algorithm and coefficients from:
+			"Software manual for the elementary functions"
+			by W.J. Cody and W. Waite, Prentice-Hall, 1980
+	*/
+
+	static double p[] = {
+		-0.16134119023996228053e+4,
+		-0.99225929672236083313e+2,
+		-0.96437492777225469787e+0
+	};
+	static double q[] = {
+		 0.48402357071988688686e+4,
+		 0.22337720718962312926e+4,
+		 0.11274474380534949335e+3,
+		 1.0
+	};
+	int 	negative = x < 0;
+
+	if (__IsNan(x)) {
+		errno = EDOM;
+		return x;
+	}
+	if (negative) x = -x;
+
+	if (x >= 0.5*M_LN_MAX_D) {
+		x = 1.0;
+	}
+#define LN3D2	0.54930614433405484570e+0	/* ln(3)/2 */
+	else if (x > LN3D2) {
+		x = 0.5 - 1.0/(exp(x+x)+1.0);
+		x += x;
+	}
+	else {
+		/* ??? avoid underflow ??? */
+		double g = x*x;
+		x += x * g * POLYNOM2(g, p)/POLYNOM3(g, q);
+	}
+	return negative ? -x : x;
+}
Index: /trunk/minix/lib/other/Makedepend-ack
===================================================================
--- /trunk/minix/lib/other/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/other/Makedepend-ack	(revision 9)
@@ -0,0 +1,79 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _allocmem.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _brk.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _devctl.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' __pm_findproc.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _freemem.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _getnpid.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _getsigset.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _getnprocnr.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _getpprocnr.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _getprocnr.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _getsysinfo.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _reboot.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _seekdir.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _svrctl.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' asynchio.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' basename.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' bcmp.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' bcopy.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' bzero.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' configfile.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' crypt.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' ctermid.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' cuserid.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' environ.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' errno.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' fdopen.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' ffs.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' flock.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' fslib.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' fts.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' fsversion.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' getgrent.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' getlogin.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' getpagesize.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' getpass.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' getpwent.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' getttyent.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' getw.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' hypot.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' index.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' itoa.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' loadname.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' lock.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' lrand.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' lsearch.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' memccpy.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' mstats.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' mtab.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' nlist.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' paramvalue.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' peekpoke.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' popen.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' putenv.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' putw.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' random.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' rindex.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' setenv.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' setgroups.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' settimeofday.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' stderr.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' strdup.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' strtok_r.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' swab.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' sys_eniop.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' syscall.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' sysconf.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' syslog.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' taskcall.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' telldir.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' termcap.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' ttyname.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' ttyslot.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' v8regerror.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' v8regexp.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' v8regsub.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' writev.c | sed -e 's:^\(.\):../obj-ack//./other/\1:' >> .depend-ack
Index: /trunk/minix/lib/other/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/other/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/other/Makedepend-gnu	(revision 9)
@@ -0,0 +1,79 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _allocmem.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _brk.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _devctl.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' __pm_findproc.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _freemem.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _getnpid.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _getsigset.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _getnprocnr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _getpprocnr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _getprocnr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _getsysinfo.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _reboot.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _seekdir.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' _svrctl.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' asynchio.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' basename.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' bcmp.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' bcopy.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' bzero.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' configfile.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' crypt.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' ctermid.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' cuserid.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' environ.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' errno.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' fdopen.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' ffs.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' flock.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' fslib.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' fts.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' fsversion.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' getgrent.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' getlogin.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' getpagesize.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' getpass.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' getpwent.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' getttyent.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' getw.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' hypot.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' index.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' itoa.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' loadname.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' lock.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' lrand.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' lsearch.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' memccpy.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' mstats.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' mtab.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' nlist.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' paramvalue.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' peekpoke.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' popen.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' putenv.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' putw.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' random.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' rindex.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' setenv.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' setgroups.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' settimeofday.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' stderr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' strdup.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' strtok_r.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' swab.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' sys_eniop.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' syscall.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' sysconf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' syslog.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' taskcall.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' telldir.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' termcap.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' ttyname.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' ttyslot.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' v8regerror.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' v8regexp.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' v8regsub.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -E' writev.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./other/\1:' >> .depend-gnu
Index: /trunk/minix/lib/other/Makefile
===================================================================
--- /trunk/minix/lib/other/Makefile	(revision 9)
+++ /trunk/minix/lib/other/Makefile	(revision 9)
@@ -0,0 +1,577 @@
+#Generated from ./other/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./other ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./other ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libc.a
+
+../obj-ack//libc.a: ../obj-ack//libc.a(_allocmem.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_brk.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_devctl.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(__pm_findproc.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_freemem.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_getnpid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_getsigset.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_getnprocnr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_getpprocnr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_getprocnr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_getsysinfo.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_reboot.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_seekdir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_svrctl.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(asynchio.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(basename.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(bcmp.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(bcopy.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(bzero.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(configfile.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(crypt.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ctermid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(cuserid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(environ.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(errno.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fdopen.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ffs.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(flock.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fslib.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fts.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fsversion.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getgrent.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getlogin.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getpagesize.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getpass.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getpwent.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getttyent.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getw.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(hypot.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(index.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(itoa.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(loadname.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(lock.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(lrand.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(lsearch.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(memccpy.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(mstats.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(mtab.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(nlist.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(paramvalue.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(peekpoke.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(popen.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(putenv.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(putw.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(random.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(rindex.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(setenv.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(setgroups.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(settimeofday.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(stderr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(strdup.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(strtok_r.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(swab.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sys_eniop.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(syscall.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sysconf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(syslog.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(taskcall.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(telldir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(termcap.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ttyname.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ttyslot.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(v8regerror.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(v8regexp.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(v8regsub.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(writev.o)
+
+../obj-ack//libc.a:
+	ar cr ../obj-ack//libc.a ../obj-ack//./other/*.o
+	rm ../obj-ack//./other/*.o
+
+../obj-ack//libc.a(_allocmem.o): _allocmem.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/_allocmem.o _allocmem.c
+../obj-ack//libc.a(_brk.o): _brk.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/_brk.o _brk.c
+../obj-ack//libc.a(_devctl.o): _devctl.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/_devctl.o _devctl.c
+../obj-ack//libc.a(__pm_findproc.o): __pm_findproc.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/__pm_findproc.o __pm_findproc.c
+../obj-ack//libc.a(_freemem.o): _freemem.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/_freemem.o _freemem.c
+../obj-ack//libc.a(_getnpid.o): _getnpid.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/_getnpid.o _getnpid.c
+../obj-ack//libc.a(_getsigset.o): _getsigset.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/_getsigset.o _getsigset.c
+../obj-ack//libc.a(_getnprocnr.o): _getnprocnr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/_getnprocnr.o _getnprocnr.c
+../obj-ack//libc.a(_getpprocnr.o): _getpprocnr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/_getpprocnr.o _getpprocnr.c
+../obj-ack//libc.a(_getprocnr.o): _getprocnr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/_getprocnr.o _getprocnr.c
+../obj-ack//libc.a(_getsysinfo.o): _getsysinfo.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/_getsysinfo.o _getsysinfo.c
+../obj-ack//libc.a(_reboot.o): _reboot.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/_reboot.o _reboot.c
+../obj-ack//libc.a(_seekdir.o): _seekdir.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/_seekdir.o _seekdir.c
+../obj-ack//libc.a(_svrctl.o): _svrctl.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/_svrctl.o _svrctl.c
+../obj-ack//libc.a(asynchio.o): asynchio.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/asynchio.o asynchio.c
+../obj-ack//libc.a(basename.o): basename.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/basename.o basename.c
+../obj-ack//libc.a(bcmp.o): bcmp.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/bcmp.o bcmp.c
+../obj-ack//libc.a(bcopy.o): bcopy.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/bcopy.o bcopy.c
+../obj-ack//libc.a(bzero.o): bzero.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/bzero.o bzero.c
+../obj-ack//libc.a(configfile.o): configfile.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/configfile.o configfile.c
+../obj-ack//libc.a(crypt.o): crypt.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/crypt.o crypt.c
+../obj-ack//libc.a(ctermid.o): ctermid.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/ctermid.o ctermid.c
+../obj-ack//libc.a(cuserid.o): cuserid.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/cuserid.o cuserid.c
+../obj-ack//libc.a(environ.o): environ.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/environ.o environ.c
+../obj-ack//libc.a(errno.o): errno.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/errno.o errno.c
+../obj-ack//libc.a(fdopen.o): fdopen.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/fdopen.o fdopen.c
+../obj-ack//libc.a(ffs.o): ffs.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/ffs.o ffs.c
+../obj-ack//libc.a(flock.o): flock.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/flock.o flock.c
+../obj-ack//libc.a(fslib.o): fslib.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/fslib.o fslib.c
+../obj-ack//libc.a(fts.o): fts.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/fts.o fts.c
+../obj-ack//libc.a(fsversion.o): fsversion.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/fsversion.o fsversion.c
+../obj-ack//libc.a(getgrent.o): getgrent.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/getgrent.o getgrent.c
+../obj-ack//libc.a(getlogin.o): getlogin.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/getlogin.o getlogin.c
+../obj-ack//libc.a(getpagesize.o): getpagesize.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/getpagesize.o getpagesize.c
+../obj-ack//libc.a(getpass.o): getpass.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/getpass.o getpass.c
+../obj-ack//libc.a(getpwent.o): getpwent.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/getpwent.o getpwent.c
+../obj-ack//libc.a(getttyent.o): getttyent.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/getttyent.o getttyent.c
+../obj-ack//libc.a(getw.o): getw.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/getw.o getw.c
+../obj-ack//libc.a(hypot.o): hypot.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/hypot.o hypot.c
+../obj-ack//libc.a(index.o): index.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/index.o index.c
+../obj-ack//libc.a(itoa.o): itoa.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/itoa.o itoa.c
+../obj-ack//libc.a(loadname.o): loadname.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/loadname.o loadname.c
+../obj-ack//libc.a(lock.o): lock.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/lock.o lock.c
+../obj-ack//libc.a(lrand.o): lrand.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/lrand.o lrand.c
+../obj-ack//libc.a(lsearch.o): lsearch.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/lsearch.o lsearch.c
+../obj-ack//libc.a(memccpy.o): memccpy.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/memccpy.o memccpy.c
+../obj-ack//libc.a(mstats.o): mstats.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/mstats.o mstats.c
+../obj-ack//libc.a(mtab.o): mtab.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/mtab.o mtab.c
+../obj-ack//libc.a(nlist.o): nlist.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/nlist.o nlist.c
+../obj-ack//libc.a(paramvalue.o): paramvalue.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/paramvalue.o paramvalue.c
+../obj-ack//libc.a(peekpoke.o): peekpoke.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/peekpoke.o peekpoke.c
+../obj-ack//libc.a(popen.o): popen.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/popen.o popen.c
+../obj-ack//libc.a(putenv.o): putenv.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/putenv.o putenv.c
+../obj-ack//libc.a(putw.o): putw.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/putw.o putw.c
+../obj-ack//libc.a(random.o): random.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/random.o random.c
+../obj-ack//libc.a(rindex.o): rindex.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/rindex.o rindex.c
+../obj-ack//libc.a(setenv.o): setenv.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/setenv.o setenv.c
+../obj-ack//libc.a(setgroups.o): setgroups.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/setgroups.o setgroups.c
+../obj-ack//libc.a(settimeofday.o): settimeofday.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/settimeofday.o settimeofday.c
+../obj-ack//libc.a(stderr.o): stderr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/stderr.o stderr.c
+../obj-ack//libc.a(strdup.o): strdup.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/strdup.o strdup.c
+../obj-ack//libc.a(strtok_r.o): strtok_r.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/strtok_r.o strtok_r.c
+../obj-ack//libc.a(swab.o): swab.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/swab.o swab.c
+../obj-ack//libc.a(sys_eniop.o): sys_eniop.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/sys_eniop.o sys_eniop.c
+../obj-ack//libc.a(syscall.o): syscall.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/syscall.o syscall.c
+../obj-ack//libc.a(sysconf.o): sysconf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/sysconf.o sysconf.c
+../obj-ack//libc.a(syslog.o): syslog.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/syslog.o syslog.c
+../obj-ack//libc.a(taskcall.o): taskcall.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/taskcall.o taskcall.c
+../obj-ack//libc.a(telldir.o): telldir.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/telldir.o telldir.c
+../obj-ack//libc.a(termcap.o): termcap.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/termcap.o termcap.c
+../obj-ack//libc.a(ttyname.o): ttyname.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/ttyname.o ttyname.c
+../obj-ack//libc.a(ttyslot.o): ttyslot.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/ttyslot.o ttyslot.c
+../obj-ack//libc.a(v8regerror.o): v8regerror.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/v8regerror.o v8regerror.c
+../obj-ack//libc.a(v8regexp.o): v8regexp.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/v8regexp.o v8regexp.c
+../obj-ack//libc.a(v8regsub.o): v8regsub.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/v8regsub.o v8regsub.c
+../obj-ack//libc.a(writev.o): writev.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-ack//./other/writev.o writev.c
+
+all-gnu: ../obj-gnu/libc.a
+
+../obj-gnu/libc.a: ../obj-gnu/./other/_allocmem.o
+../obj-gnu/libc.a: ../obj-gnu/./other/_brk.o
+../obj-gnu/libc.a: ../obj-gnu/./other/_devctl.o
+../obj-gnu/libc.a: ../obj-gnu/./other/__pm_findproc.o
+../obj-gnu/libc.a: ../obj-gnu/./other/_freemem.o
+../obj-gnu/libc.a: ../obj-gnu/./other/_getnpid.o
+../obj-gnu/libc.a: ../obj-gnu/./other/_getsigset.o
+../obj-gnu/libc.a: ../obj-gnu/./other/_getnprocnr.o
+../obj-gnu/libc.a: ../obj-gnu/./other/_getpprocnr.o
+../obj-gnu/libc.a: ../obj-gnu/./other/_getprocnr.o
+../obj-gnu/libc.a: ../obj-gnu/./other/_getsysinfo.o
+../obj-gnu/libc.a: ../obj-gnu/./other/_reboot.o
+../obj-gnu/libc.a: ../obj-gnu/./other/_seekdir.o
+../obj-gnu/libc.a: ../obj-gnu/./other/_svrctl.o
+../obj-gnu/libc.a: ../obj-gnu/./other/asynchio.o
+../obj-gnu/libc.a: ../obj-gnu/./other/basename.o
+../obj-gnu/libc.a: ../obj-gnu/./other/bcmp.o
+../obj-gnu/libc.a: ../obj-gnu/./other/bcopy.o
+../obj-gnu/libc.a: ../obj-gnu/./other/bzero.o
+../obj-gnu/libc.a: ../obj-gnu/./other/configfile.o
+../obj-gnu/libc.a: ../obj-gnu/./other/crypt.o
+../obj-gnu/libc.a: ../obj-gnu/./other/ctermid.o
+../obj-gnu/libc.a: ../obj-gnu/./other/cuserid.o
+../obj-gnu/libc.a: ../obj-gnu/./other/environ.o
+../obj-gnu/libc.a: ../obj-gnu/./other/errno.o
+../obj-gnu/libc.a: ../obj-gnu/./other/fdopen.o
+../obj-gnu/libc.a: ../obj-gnu/./other/ffs.o
+../obj-gnu/libc.a: ../obj-gnu/./other/flock.o
+../obj-gnu/libc.a: ../obj-gnu/./other/fslib.o
+../obj-gnu/libc.a: ../obj-gnu/./other/fts.o
+../obj-gnu/libc.a: ../obj-gnu/./other/fsversion.o
+../obj-gnu/libc.a: ../obj-gnu/./other/getgrent.o
+../obj-gnu/libc.a: ../obj-gnu/./other/getlogin.o
+../obj-gnu/libc.a: ../obj-gnu/./other/getpagesize.o
+../obj-gnu/libc.a: ../obj-gnu/./other/getpass.o
+../obj-gnu/libc.a: ../obj-gnu/./other/getpwent.o
+../obj-gnu/libc.a: ../obj-gnu/./other/getttyent.o
+../obj-gnu/libc.a: ../obj-gnu/./other/getw.o
+../obj-gnu/libc.a: ../obj-gnu/./other/hypot.o
+../obj-gnu/libc.a: ../obj-gnu/./other/index.o
+../obj-gnu/libc.a: ../obj-gnu/./other/itoa.o
+../obj-gnu/libc.a: ../obj-gnu/./other/loadname.o
+../obj-gnu/libc.a: ../obj-gnu/./other/lock.o
+../obj-gnu/libc.a: ../obj-gnu/./other/lrand.o
+../obj-gnu/libc.a: ../obj-gnu/./other/lsearch.o
+../obj-gnu/libc.a: ../obj-gnu/./other/memccpy.o
+../obj-gnu/libc.a: ../obj-gnu/./other/mstats.o
+../obj-gnu/libc.a: ../obj-gnu/./other/mtab.o
+../obj-gnu/libc.a: ../obj-gnu/./other/nlist.o
+../obj-gnu/libc.a: ../obj-gnu/./other/paramvalue.o
+../obj-gnu/libc.a: ../obj-gnu/./other/peekpoke.o
+../obj-gnu/libc.a: ../obj-gnu/./other/popen.o
+../obj-gnu/libc.a: ../obj-gnu/./other/putenv.o
+../obj-gnu/libc.a: ../obj-gnu/./other/putw.o
+../obj-gnu/libc.a: ../obj-gnu/./other/random.o
+../obj-gnu/libc.a: ../obj-gnu/./other/rindex.o
+../obj-gnu/libc.a: ../obj-gnu/./other/setenv.o
+../obj-gnu/libc.a: ../obj-gnu/./other/setgroups.o
+../obj-gnu/libc.a: ../obj-gnu/./other/settimeofday.o
+../obj-gnu/libc.a: ../obj-gnu/./other/stderr.o
+../obj-gnu/libc.a: ../obj-gnu/./other/strdup.o
+../obj-gnu/libc.a: ../obj-gnu/./other/strtok_r.o
+../obj-gnu/libc.a: ../obj-gnu/./other/swab.o
+../obj-gnu/libc.a: ../obj-gnu/./other/sys_eniop.o
+../obj-gnu/libc.a: ../obj-gnu/./other/syscall.o
+../obj-gnu/libc.a: ../obj-gnu/./other/sysconf.o
+../obj-gnu/libc.a: ../obj-gnu/./other/syslog.o
+../obj-gnu/libc.a: ../obj-gnu/./other/taskcall.o
+../obj-gnu/libc.a: ../obj-gnu/./other/telldir.o
+../obj-gnu/libc.a: ../obj-gnu/./other/termcap.o
+../obj-gnu/libc.a: ../obj-gnu/./other/ttyname.o
+../obj-gnu/libc.a: ../obj-gnu/./other/ttyslot.o
+../obj-gnu/libc.a: ../obj-gnu/./other/v8regerror.o
+../obj-gnu/libc.a: ../obj-gnu/./other/v8regexp.o
+../obj-gnu/libc.a: ../obj-gnu/./other/v8regsub.o
+../obj-gnu/libc.a: ../obj-gnu/./other/writev.o
+
+../obj-gnu/libc.a:
+	gar cr ../obj-gnu/libc.a $?
+
+../obj-gnu/./other/_allocmem.o: _allocmem.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/_allocmem.o _allocmem.c
+
+../obj-gnu/./other/_brk.o: _brk.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/_brk.o _brk.c
+
+../obj-gnu/./other/_devctl.o: _devctl.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/_devctl.o _devctl.c
+
+../obj-gnu/./other/__pm_findproc.o: __pm_findproc.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/__pm_findproc.o __pm_findproc.c
+
+../obj-gnu/./other/_freemem.o: _freemem.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/_freemem.o _freemem.c
+
+../obj-gnu/./other/_getnpid.o: _getnpid.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/_getnpid.o _getnpid.c
+
+../obj-gnu/./other/_getsigset.o: _getsigset.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/_getsigset.o _getsigset.c
+
+../obj-gnu/./other/_getnprocnr.o: _getnprocnr.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/_getnprocnr.o _getnprocnr.c
+
+../obj-gnu/./other/_getpprocnr.o: _getpprocnr.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/_getpprocnr.o _getpprocnr.c
+
+../obj-gnu/./other/_getprocnr.o: _getprocnr.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/_getprocnr.o _getprocnr.c
+
+../obj-gnu/./other/_getsysinfo.o: _getsysinfo.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/_getsysinfo.o _getsysinfo.c
+
+../obj-gnu/./other/_reboot.o: _reboot.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/_reboot.o _reboot.c
+
+../obj-gnu/./other/_seekdir.o: _seekdir.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/_seekdir.o _seekdir.c
+
+../obj-gnu/./other/_svrctl.o: _svrctl.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/_svrctl.o _svrctl.c
+
+../obj-gnu/./other/asynchio.o: asynchio.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/asynchio.o asynchio.c
+
+../obj-gnu/./other/basename.o: basename.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/basename.o basename.c
+
+../obj-gnu/./other/bcmp.o: bcmp.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/bcmp.o bcmp.c
+
+../obj-gnu/./other/bcopy.o: bcopy.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/bcopy.o bcopy.c
+
+../obj-gnu/./other/bzero.o: bzero.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/bzero.o bzero.c
+
+../obj-gnu/./other/configfile.o: configfile.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/configfile.o configfile.c
+
+../obj-gnu/./other/crypt.o: crypt.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/crypt.o crypt.c
+
+../obj-gnu/./other/ctermid.o: ctermid.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/ctermid.o ctermid.c
+
+../obj-gnu/./other/cuserid.o: cuserid.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/cuserid.o cuserid.c
+
+../obj-gnu/./other/environ.o: environ.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/environ.o environ.c
+
+../obj-gnu/./other/errno.o: errno.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/errno.o errno.c
+
+../obj-gnu/./other/fdopen.o: fdopen.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/fdopen.o fdopen.c
+
+../obj-gnu/./other/ffs.o: ffs.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/ffs.o ffs.c
+
+../obj-gnu/./other/flock.o: flock.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/flock.o flock.c
+
+../obj-gnu/./other/fslib.o: fslib.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/fslib.o fslib.c
+
+../obj-gnu/./other/fts.o: fts.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/fts.o fts.c
+
+../obj-gnu/./other/fsversion.o: fsversion.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/fsversion.o fsversion.c
+
+../obj-gnu/./other/getgrent.o: getgrent.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/getgrent.o getgrent.c
+
+../obj-gnu/./other/getlogin.o: getlogin.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/getlogin.o getlogin.c
+
+../obj-gnu/./other/getpagesize.o: getpagesize.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/getpagesize.o getpagesize.c
+
+../obj-gnu/./other/getpass.o: getpass.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/getpass.o getpass.c
+
+../obj-gnu/./other/getpwent.o: getpwent.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/getpwent.o getpwent.c
+
+../obj-gnu/./other/getttyent.o: getttyent.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/getttyent.o getttyent.c
+
+../obj-gnu/./other/getw.o: getw.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/getw.o getw.c
+
+../obj-gnu/./other/hypot.o: hypot.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/hypot.o hypot.c
+
+../obj-gnu/./other/index.o: index.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/index.o index.c
+
+../obj-gnu/./other/itoa.o: itoa.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/itoa.o itoa.c
+
+../obj-gnu/./other/loadname.o: loadname.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/loadname.o loadname.c
+
+../obj-gnu/./other/lock.o: lock.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/lock.o lock.c
+
+../obj-gnu/./other/lrand.o: lrand.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/lrand.o lrand.c
+
+../obj-gnu/./other/lsearch.o: lsearch.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/lsearch.o lsearch.c
+
+../obj-gnu/./other/memccpy.o: memccpy.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/memccpy.o memccpy.c
+
+../obj-gnu/./other/mstats.o: mstats.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/mstats.o mstats.c
+
+../obj-gnu/./other/mtab.o: mtab.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/mtab.o mtab.c
+
+../obj-gnu/./other/nlist.o: nlist.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/nlist.o nlist.c
+
+../obj-gnu/./other/paramvalue.o: paramvalue.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/paramvalue.o paramvalue.c
+
+../obj-gnu/./other/peekpoke.o: peekpoke.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/peekpoke.o peekpoke.c
+
+../obj-gnu/./other/popen.o: popen.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/popen.o popen.c
+
+../obj-gnu/./other/putenv.o: putenv.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/putenv.o putenv.c
+
+../obj-gnu/./other/putw.o: putw.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/putw.o putw.c
+
+../obj-gnu/./other/random.o: random.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/random.o random.c
+
+../obj-gnu/./other/rindex.o: rindex.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/rindex.o rindex.c
+
+../obj-gnu/./other/setenv.o: setenv.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/setenv.o setenv.c
+
+../obj-gnu/./other/setgroups.o: setgroups.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/setgroups.o setgroups.c
+
+../obj-gnu/./other/settimeofday.o: settimeofday.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/settimeofday.o settimeofday.c
+
+../obj-gnu/./other/stderr.o: stderr.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/stderr.o stderr.c
+
+../obj-gnu/./other/strdup.o: strdup.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/strdup.o strdup.c
+
+../obj-gnu/./other/strtok_r.o: strtok_r.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/strtok_r.o strtok_r.c
+
+../obj-gnu/./other/swab.o: swab.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/swab.o swab.c
+
+../obj-gnu/./other/sys_eniop.o: sys_eniop.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/sys_eniop.o sys_eniop.c
+
+../obj-gnu/./other/syscall.o: syscall.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/syscall.o syscall.c
+
+../obj-gnu/./other/sysconf.o: sysconf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/sysconf.o sysconf.c
+
+../obj-gnu/./other/syslog.o: syslog.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/syslog.o syslog.c
+
+../obj-gnu/./other/taskcall.o: taskcall.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/taskcall.o taskcall.c
+
+../obj-gnu/./other/telldir.o: telldir.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/telldir.o telldir.c
+
+../obj-gnu/./other/termcap.o: termcap.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/termcap.o termcap.c
+
+../obj-gnu/./other/ttyname.o: ttyname.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/ttyname.o ttyname.c
+
+../obj-gnu/./other/ttyslot.o: ttyslot.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/ttyslot.o ttyslot.c
+
+../obj-gnu/./other/v8regerror.o: v8regerror.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/v8regerror.o v8regerror.c
+
+../obj-gnu/./other/v8regexp.o: v8regexp.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/v8regexp.o v8regexp.c
+
+../obj-gnu/./other/v8regsub.o: v8regsub.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/v8regsub.o v8regsub.c
+
+../obj-gnu/./other/writev.o: writev.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -I../../servers -c -o ../obj-gnu/./other/writev.o writev.c
+
+
+
+
+clean::
+	rm -f ../obj-ack//./other/*
+	rm -f ../obj-gnu/./other/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/other/Makefile.in
===================================================================
--- /trunk/minix/lib/other/Makefile.in	(revision 9)
+++ /trunk/minix/lib/other/Makefile.in	(revision 9)
@@ -0,0 +1,85 @@
+# Makefile for lib/other.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE -I../../servers"
+
+LIBRARIES=libc
+
+libc_FILES=" \
+	_allocmem.c \
+	_brk.c \
+	_devctl.c \
+	__pm_findproc.c \
+	_freemem.c \
+	_getnpid.c \
+	_getsigset.c \
+	_getnprocnr.c \
+	_getpprocnr.c \
+	_getprocnr.c \
+	_getsysinfo.c \
+	_reboot.c \
+	_seekdir.c \
+	_svrctl.c \
+	asynchio.c \
+	basename.c \
+	bcmp.c \
+	bcopy.c \
+	bzero.c \
+	configfile.c \
+	crypt.c \
+	ctermid.c \
+	cuserid.c \
+	environ.c \
+	errno.c \
+	fdopen.c \
+	ffs.c \
+	flock.c \
+	fslib.c \
+	fts.c \
+	fsversion.c \
+	getgrent.c \
+	getlogin.c \
+	getpagesize.c \
+	getpass.c \
+	getpwent.c \
+	getttyent.c \
+	getw.c \
+	hypot.c \
+	index.c \
+	itoa.c \
+	loadname.c \
+	lock.c \
+	lrand.c \
+	lsearch.c \
+	memccpy.c \
+	mstats.c \
+	mtab.c \
+	nlist.c \
+	paramvalue.c \
+	peekpoke.c \
+	popen.c \
+	putenv.c \
+	putw.c \
+	random.c \
+	rindex.c \
+	setenv.c \
+	setgroups.c \
+	settimeofday.c \
+	stderr.c \
+	strdup.c \
+	strtok_r.c \
+	swab.c \
+	sys_eniop.c \
+	syscall.c \
+	sysconf.c \
+	syslog.c \
+	taskcall.c \
+	telldir.c \
+	termcap.c \
+	ttyname.c \
+	ttyslot.c \
+	v8regerror.c \
+	v8regexp.c \
+	v8regsub.c \
+	writev.c"
+
+TYPE=both
Index: /trunk/minix/lib/other/__pm_findproc.c
===================================================================
--- /trunk/minix/lib/other/__pm_findproc.c	(revision 9)
+++ /trunk/minix/lib/other/__pm_findproc.c	(revision 9)
@@ -0,0 +1,19 @@
+#include <lib.h>
+#define _pm_findproc	__pm_findproc
+#include <unistd.h>
+#include <string.h>
+
+PUBLIC int _pm_findproc(proc_name, proc_nr)
+char *proc_name;		/* name of process to search for */
+int *proc_nr;			/* return process number here */
+{
+  message m;
+
+  m.m1_p1 = proc_name;
+  m.m1_i1 = -1;			/* search by name */
+  m.m1_i2 = strlen(proc_name) + 1;
+  if (_syscall(MM, GETPROCNR, &m) < 0) return(-1);
+  *proc_nr = m.m1_i1;
+  return(0);
+}
+
Index: /trunk/minix/lib/other/_allocmem.c
===================================================================
--- /trunk/minix/lib/other/_allocmem.c	(revision 9)
+++ /trunk/minix/lib/other/_allocmem.c	(revision 9)
@@ -0,0 +1,16 @@
+#include <lib.h>
+#define allocmem	_allocmem
+#include <unistd.h>
+
+
+PUBLIC int allocmem(size, base)
+phys_bytes size;			/* size of mem chunk requested */
+phys_bytes *base;			/* return base address */
+{
+  message m;
+  m.m4_l1 = size;		
+  if (_syscall(MM, ALLOCMEM, &m) < 0) return(-1);
+  *base = m.m4_l2;
+  return(0);
+}
+
Index: /trunk/minix/lib/other/_brk.c
===================================================================
--- /trunk/minix/lib/other/_brk.c	(revision 9)
+++ /trunk/minix/lib/other/_brk.c	(revision 9)
@@ -0,0 +1,44 @@
+#include <lib.h>
+#define brk	_brk
+#define sbrk	_sbrk
+#include <unistd.h>
+
+extern char *_brksize;
+
+/* Both OSF/1 and SYSVR4 man pages specify that brk(2) returns int.
+ * However, BSD4.3 specifies that brk() returns char*.  POSIX omits
+ * brk() on the grounds that it imposes a memory model on an architecture.
+ * For this reason, brk() and sbrk() are not in the lib/posix directory.
+ * On the other hand, they are so crucial to correct operation of so many
+ * parts of the system, that we have chosen to hide the name brk using _brk,
+ * as with system calls.  In this way, if a user inadvertently defines a
+ * procedure brk, MINIX may continue to work because the true call is _brk.
+ */
+PUBLIC int brk(addr)
+char *addr;
+{
+  message m;
+
+  if (addr != _brksize) {
+	m.m1_p1 = addr;
+	if (_syscall(MM, BRK, &m) < 0) return(-1);
+	_brksize = m.m2_p1;
+  }
+  return(0);
+}
+
+
+PUBLIC char *sbrk(incr)
+int incr;
+{
+  char *newsize, *oldsize;
+
+  oldsize = _brksize;
+  newsize = _brksize + incr;
+  if ((incr > 0 && newsize < oldsize) || (incr < 0 && newsize > oldsize))
+	return( (char *) -1);
+  if (brk(newsize) == 0)
+	return(oldsize);
+  else
+	return( (char *) -1);
+}
Index: /trunk/minix/lib/other/_devctl.c
===================================================================
--- /trunk/minix/lib/other/_devctl.c	(revision 9)
+++ /trunk/minix/lib/other/_devctl.c	(revision 9)
@@ -0,0 +1,16 @@
+#include <lib.h>
+#define devctl	_devctl
+#include <unistd.h>
+
+
+PUBLIC int devctl(int ctl_req, int proc_nr, int dev_nr, int dev_style)
+{
+  message m;
+  m.m4_l1 = ctl_req;
+  m.m4_l2 = proc_nr;
+  m.m4_l3 = dev_nr;
+  m.m4_l4 = dev_style;
+  if (_syscall(FS, DEVCTL, &m) < 0) return(-1);
+  return(0);
+}
+
Index: /trunk/minix/lib/other/_freemem.c
===================================================================
--- /trunk/minix/lib/other/_freemem.c	(revision 9)
+++ /trunk/minix/lib/other/_freemem.c	(revision 9)
@@ -0,0 +1,16 @@
+#include <lib.h>
+#define freemem	_freemem
+#include <unistd.h>
+
+
+PUBLIC int freemem(size, base)
+phys_bytes size;			/* size of mem chunk requested */
+phys_bytes base;			/* base address of mem chunk */
+{
+  message m;
+  m.m4_l1 = size;		
+  m.m4_l2 = base;		
+  if (_syscall(MM, FREEMEM, &m) < 0) return(-1);
+  return(0);
+}
+
Index: /trunk/minix/lib/other/_getnpid.c
===================================================================
--- /trunk/minix/lib/other/_getnpid.c	(revision 9)
+++ /trunk/minix/lib/other/_getnpid.c	(revision 9)
@@ -0,0 +1,11 @@
+#include <lib.h>
+#define getnpid	_getnpid
+#include <unistd.h>
+
+PUBLIC pid_t getnpid(int proc_nr)
+{
+  message m;
+  m.m1_i1 = proc_nr;		/* search pid for this process */
+  if (_syscall(MM, GETPID, &m) < 0) return ( (pid_t) -1);
+  return( (pid_t) m.m2_i2);	/* return search result */
+}
Index: /trunk/minix/lib/other/_getnprocnr.c
===================================================================
--- /trunk/minix/lib/other/_getnprocnr.c	(revision 9)
+++ /trunk/minix/lib/other/_getnprocnr.c	(revision 9)
@@ -0,0 +1,14 @@
+#include <lib.h>
+#define getnprocnr	_getnprocnr
+#include <unistd.h>
+
+
+PUBLIC int getnprocnr(pid_t pid)
+{
+  message m;
+  m.m1_i1 = pid;		/* pass pid >=0 to search for */
+  m.m1_i2 = 0;			/* don't pass name to search for */
+  if (_syscall(PM_PROC_NR, GETPROCNR, &m) < 0) return(-1);
+  return(m.m1_i1);		/* return search result */
+}
+
Index: /trunk/minix/lib/other/_getpprocnr.c
===================================================================
--- /trunk/minix/lib/other/_getpprocnr.c	(revision 9)
+++ /trunk/minix/lib/other/_getpprocnr.c	(revision 9)
@@ -0,0 +1,14 @@
+#include <lib.h>
+#define getpprocnr	_getpprocnr
+#include <unistd.h>
+
+
+PUBLIC int getpprocnr()
+{
+  message m;
+  m.m1_i1 = -1;			/* don't pass pid to search for */
+  m.m1_i2 = 0;			/* don't pass name to search for */
+  if (_syscall(PM_PROC_NR, GETPROCNR, &m) < 0) return(-1);
+  return(m.m1_i2);		/* return parent process number */
+}
+
Index: /trunk/minix/lib/other/_getprocnr.c
===================================================================
--- /trunk/minix/lib/other/_getprocnr.c	(revision 9)
+++ /trunk/minix/lib/other/_getprocnr.c	(revision 9)
@@ -0,0 +1,14 @@
+#include <lib.h>
+#define getprocnr	_getprocnr
+#include <unistd.h>
+
+
+PUBLIC int getprocnr()
+{
+  message m;
+  m.m1_i1 = -1;			/* don't pass pid to search for */
+  m.m1_i2 = 0;			/* don't pass name to search for */
+  if (_syscall(PM_PROC_NR, GETPROCNR, &m) < 0) return(-1);
+  return(m.m1_i1);		/* return own process number */
+}
+
Index: /trunk/minix/lib/other/_getsigset.c
===================================================================
--- /trunk/minix/lib/other/_getsigset.c	(revision 9)
+++ /trunk/minix/lib/other/_getsigset.c	(revision 9)
@@ -0,0 +1,15 @@
+#include <lib.h>
+#define getsigset	_getsigset
+#include <unistd.h>
+
+
+PUBLIC int getsigset(sp)
+sigset_t *sp;				/* where to put it */
+{
+  message m;
+  m.m2_i1 = SELF;			/* request own signal set */
+  if (_syscall(PM_PROC_NR, PROCSTAT, &m) < 0) return(-1);
+  *sp = m.m2_l1;
+  return(0);
+}
+
Index: /trunk/minix/lib/other/_getsysinfo.c
===================================================================
--- /trunk/minix/lib/other/_getsysinfo.c	(revision 9)
+++ /trunk/minix/lib/other/_getsysinfo.c	(revision 9)
@@ -0,0 +1,17 @@
+#include <lib.h>
+#define getsysinfo	_getsysinfo
+#include <unistd.h>
+
+
+PUBLIC int getsysinfo(who, what, where)
+int who;			/* from whom to request info */
+int what;			/* what information is requested */
+void *where;			/* where to put it */
+{
+  message m;
+  m.m1_i1 = what;
+  m.m1_p1 = where;
+  if (_syscall(who, GETSYSINFO, &m) < 0) return(-1);
+  return(0);
+}
+
Index: /trunk/minix/lib/other/_reboot.c
===================================================================
--- /trunk/minix/lib/other/_reboot.c	(revision 9)
+++ /trunk/minix/lib/other/_reboot.c	(revision 9)
@@ -0,0 +1,24 @@
+/* reboot.c - Systemcall interface to mm/signal.c::do_reboot()
+
+   author: Edvard Tuinder  v892231@si.hhs.NL
+ */
+
+#include <lib.h>
+#define reboot	_reboot
+#include <unistd.h>
+#include <stdarg.h>
+
+int reboot(int how, ...)
+{
+  message m;
+  va_list ap;
+
+  va_start(ap, how);
+  if ((m.m1_i1 = how) == RBT_MONITOR) {
+	m.m1_p1 = va_arg(ap, char *);
+	m.m1_i2 = va_arg(ap, size_t);
+  }
+  va_end(ap);
+
+  return _syscall(MM, REBOOT, &m);
+}
Index: /trunk/minix/lib/other/_seekdir.c
===================================================================
--- /trunk/minix/lib/other/_seekdir.c	(revision 9)
+++ /trunk/minix/lib/other/_seekdir.c	(revision 9)
@@ -0,0 +1,32 @@
+/*	seekdir()					Author: Kees J. Bot
+ *								24 Apr 1989
+ */
+#define nil 0
+#include <lib.h>
+#define lseek	_lseek
+#define readdir	_readdir
+#define seekdir	_seekdir
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <errno.h>
+
+int seekdir(DIR *dp, off_t pos)
+/* Seek to position pos in a directory. */
+{
+	int off;
+
+	if (dp == nil) { errno= EBADF; return -1; }
+
+	dp->_count= 0;
+	dp->_ptr= dp->_buf;
+
+	off= pos & (sizeof(dp->_buf) - 1);
+	dp->_pos= pos - off;
+
+	if (lseek(dp->_fd, dp->_pos, SEEK_SET) == -1) return -1;
+
+	while (dp->_pos < pos && readdir(dp) != nil) {}
+
+	return 0;
+}
Index: /trunk/minix/lib/other/_svrctl.c
===================================================================
--- /trunk/minix/lib/other/_svrctl.c	(revision 9)
+++ /trunk/minix/lib/other/_svrctl.c	(revision 9)
@@ -0,0 +1,29 @@
+/*	svrctl() - special server control functions.	Author: Kees J. Bot
+ *								24 Apr 1994
+ */
+#include <lib.h>
+#include <stdio.h>
+#define svrctl _svrctl
+#include <sys/svrctl.h>
+
+int svrctl(int request, void *argp)
+{
+	message m;
+
+	m.m2_i1 = request;
+	m.m2_p1 = argp;
+
+	switch ((request >> 8) & 0xFF) {
+	case 'M':
+	case 'S':
+		/* MM handles calls for itself and the kernel. */
+		return _syscall(MM, SVRCTL, &m);
+	case 'F':
+	case 'I':
+		/* FS handles calls for itself and inet. */
+		return _syscall(FS, SVRCTL, &m);
+	default:
+		errno = EINVAL;
+		return -1;
+	}
+}
Index: /trunk/minix/lib/other/asynchio.c
===================================================================
--- /trunk/minix/lib/other/asynchio.c	(revision 9)
+++ /trunk/minix/lib/other/asynchio.c	(revision 9)
@@ -0,0 +1,154 @@
+/*	asyn_init(), asyn_read(), asyn_write(), asyn_ioctl(),
+ *	asyn_wait(), asyn_synch(), asyn_close()
+ *							Author: Kees J. Bot
+ *								26 Jan 1995
+ * Thise are just stub routines that are call compatible with
+ * the asynchio(3) library of Minix-vmd.  See asynchio.h.
+ */
+#define nil 0
+#define alarm	_alarm
+#define ioctl	_ioctl
+#define read	_read
+#define sigaction _sigaction
+#define sigfillset _sigfillset
+#define time	_time
+#define write	_write
+#include <lib.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <sys/asynchio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+
+#define IO_IDLE		0
+#define IO_INPROGRESS	1
+#define IO_RESULT	2
+
+#define OP_NOOP		0
+#define OP_READ		1
+#define OP_WRITE	2
+#define OP_IOCTL	3
+
+static asynchio_t *asyn_current;
+
+void asyn_init(asynchio_t *asyn)
+{
+	asyn->state= IO_IDLE;
+	asyn->op= OP_NOOP;
+}
+
+static ssize_t operation(int op, asynchio_t *asyn, int fd, int req,
+						void *data, ssize_t count)
+{
+	switch (asyn->state) {
+	case IO_INPROGRESS:
+		if (asyn_current != asyn && asyn->op != op) abort();
+		/*FALL THROUGH*/
+	case IO_IDLE:
+		asyn_current= asyn;
+		asyn->op= op;
+		asyn->fd= fd;
+		asyn->req= req;
+		asyn->data= data;
+		asyn->count= count;
+		asyn->state= IO_INPROGRESS;
+		errno= EINPROGRESS;
+		return -1;
+	case IO_RESULT:
+		if (asyn_current != asyn && asyn->op != op) abort();
+		errno= asyn->errno;
+		return asyn->count;
+	}
+}
+
+ssize_t asyn_read(asynchio_t *asyn, int fd, void *buf, size_t len)
+{
+	return operation(OP_READ, asyn, fd, 0, buf, len);
+}
+
+ssize_t asyn_write(asynchio_t *asyn, int fd, const void *buf, size_t len)
+{
+	return operation(OP_WRITE, asyn, fd, 0, (void *) buf, len);
+}
+
+int asyn_ioctl(asynchio_t *asyn, int fd, unsigned long request, void *data)
+{
+	return operation(OP_IOCTL, asyn, fd, request, data, 0);
+}
+
+static void time_out(int sig)
+{
+	alarm(1);
+}
+
+int asyn_wait(asynchio_t *asyn, int flags, struct timeval *to)
+{
+	time_t now;
+	unsigned old_timer, new_timer;
+	struct sigaction old_sa, new_sa;
+
+	if (asyn_current != asyn) abort();
+	if (flags & ASYN_NONBLOCK) abort();
+
+	if (asyn->state == IO_RESULT) {
+		asyn->state= IO_IDLE;
+		asyn->op= OP_NOOP;
+		return 0;
+	}
+
+	if (to != nil) {
+		now= time(nil);
+		if (to->tv_sec <= now) { errno= EINTR; return -1; }
+		old_timer= alarm(0);
+		new_sa.sa_handler= time_out;
+		sigfillset(&new_sa.sa_mask);
+		new_sa.sa_flags= 0;
+		sigaction(SIGALRM, &new_sa, &old_sa);
+		new_timer= to->tv_sec - now;
+		if (new_timer < old_timer) {
+			new_timer= old_timer;
+		}
+		alarm(new_timer);
+	}
+	switch (asyn->op) {
+	case OP_NOOP:
+		asyn->count= pause();
+		asyn->errno= errno;
+	case OP_READ:
+		asyn->count= read(asyn->fd, asyn->data, asyn->count);
+		asyn->errno= errno;
+		break;
+	case OP_WRITE:
+		asyn->count= write(asyn->fd, asyn->data, asyn->count);
+		asyn->errno= errno;
+		break;
+	case OP_IOCTL:
+		asyn->count= ioctl(asyn->fd, asyn->req, asyn->data);
+		asyn->errno= errno;
+		break;
+	}
+	if (to != nil) {
+		alarm(0);
+		sigaction(SIGALRM, &old_sa, (struct sigaction *)0);
+		alarm(old_timer);
+	}
+
+	if (asyn->count == -1 && asyn->errno == EINTR) {
+		errno= EINTR;
+		return -1;
+	} else {
+		asyn->state= IO_RESULT;
+		return 0;
+	}
+}
+
+int asyn_synch(asynchio_t *asyn, int fd)
+{
+}
+
+int asyn_close(asynchio_t *asyn, int fd)
+{
+	asyn_init(asyn);
+}
Index: /trunk/minix/lib/other/basename.c
===================================================================
--- /trunk/minix/lib/other/basename.c	(revision 9)
+++ /trunk/minix/lib/other/basename.c	(revision 9)
@@ -0,0 +1,30 @@
+/*
+basename.c
+*/
+
+#include <libgen.h>
+#include <string.h>
+
+char *basename(path)
+char *path;
+{
+	size_t len;
+	char *cp;
+
+	if (path == NULL)
+		return ".";
+	len= strlen(path);
+	if (len == 0)
+		return ".";
+	while (path[len-1] == '/')
+	{
+		if (len == 1)
+			return path;	/* just "/" */
+		len--;
+		path[len]= '\0';
+	}
+	cp= strrchr(path, '/');
+	if (cp != NULL)
+		return cp+1;
+	return path;
+}
Index: /trunk/minix/lib/other/bcmp.c
===================================================================
--- /trunk/minix/lib/other/bcmp.c	(revision 9)
+++ /trunk/minix/lib/other/bcmp.c	(revision 9)
@@ -0,0 +1,12 @@
+#include <lib.h>
+/* bcmp - Berklix equivalent of memcmp  */
+
+#include <string.h>
+
+int bcmp(s1, s2, length)	/* == 0 or != 0 for equality and inequality */ 
+_CONST void *s1;
+_CONST void *s2;
+size_t length;
+{
+  return(memcmp(s1, s2, length));
+}
Index: /trunk/minix/lib/other/bcopy.c
===================================================================
--- /trunk/minix/lib/other/bcopy.c	(revision 9)
+++ /trunk/minix/lib/other/bcopy.c	(revision 9)
@@ -0,0 +1,12 @@
+#include <lib.h>
+/* bcopy - Berklix equivalent of memcpy  */
+
+#include <string.h>
+
+void bcopy(src, dst, length)
+_CONST void *src;
+void *dst;
+size_t length;
+{
+  (void) memcpy(dst, src, length);
+}
Index: /trunk/minix/lib/other/bzero.c
===================================================================
--- /trunk/minix/lib/other/bzero.c	(revision 9)
+++ /trunk/minix/lib/other/bzero.c	(revision 9)
@@ -0,0 +1,11 @@
+#include <lib.h>
+/* bzero - Berklix subset of memset  */
+
+#include <string.h>
+
+void bzero(dst, length)
+void *dst;
+size_t length;
+{
+  (void) memset(dst, 0, length);
+}
Index: /trunk/minix/lib/other/configfile.c
===================================================================
--- /trunk/minix/lib/other/configfile.c	(revision 9)
+++ /trunk/minix/lib/other/configfile.c	(revision 9)
@@ -0,0 +1,574 @@
+/*	config_read(), _delete(), _length() - Generic config file routines.
+ *							Author: Kees J. Bot
+ *								5 Jun 1999
+ */
+#define nil ((void*)0)
+#if __minix_vmd
+#include <minix/stubs.h>
+#else
+#define fstat _fstat
+#define stat _stat
+#endif
+#include <sys/types.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <sys/stat.h>
+#if __minix_vmd
+#include <minix/asciictype.h>
+#else
+#include <ctype.h>
+#endif
+#define _c /* not const */
+#include <configfile.h>
+
+typedef struct configfile {	/* List of (included) configuration files. */
+	struct configfile *next;	/* A list indeed. */
+	time_t		ctime;		/* Last changed time, -1 if no file. */
+	char		name[1];	/* File name. */
+} configfile_t;
+
+/* Size of a configfile_t given a file name of length 'len'. */
+#define configfilesize(len)	(offsetof(configfile_t, name) + 1 + (len))
+
+typedef struct firstconfig {	/* First file and first word share a slot. */
+	configfile_t	*filelist;
+	char		new;		/* Set when created. */
+	config_t	config1;
+} firstconfig_t;
+
+/* Size of a config_t given a word of lenght 'len'.  Same for firstconfig_t. */
+#define config0size()		(offsetof(config_t, word))
+#define configsize(len)		(config0size() + 1 + (len))
+#define firstconfigsize(len)	\
+			(offsetof(firstconfig_t, config1) + configsize(len))
+
+/* Translate address of first config word to enclosing firstconfig_t and vv. */
+#define cfg2fcfg(p)	\
+    ((firstconfig_t *) ((char *) (p) - offsetof(firstconfig_t, config1)))
+#define fcfg2cfg(p)	(&(p)->config1)
+
+/* Variables used while building data. */
+static configfile_t *c_files;		/* List of (included) config files. */
+static int c_flags;			/* Flags argument of config_read(). */
+static FILE *c_fp;			/* Current open file. */
+static char *c_file;			/* Current open file name. */
+static unsigned c_line;			/* Current line number. */
+static int c;				/* Next character. */
+
+static void *allocate(void *mem, size_t size)
+/* Like realloc(), but checked. */
+{
+    if ((mem= realloc(mem, size)) == nil) {
+	fprintf(stderr, "\"%s\", line %u: Out of memory\n", c_file, c_line);
+	exit(1);
+    }
+    return mem;
+}
+
+#define deallocate(mem)	free(mem)
+
+static void delete_filelist(configfile_t *cfgf)
+/* Delete configuration file list. */
+{
+    void *junk;
+
+    while (cfgf != nil) {
+	junk= cfgf;
+	cfgf= cfgf->next;
+	deallocate(junk);
+    }
+}
+
+static void delete_config(config_t *cfg)
+/* Delete configuration file data. */
+{
+    config_t *next, *list, *junk;
+
+    next= cfg;
+    list= nil;
+    for (;;) {
+	if (next != nil) {
+	    /* Push the 'next' chain in reverse on the 'list' chain, putting
+	     * a leaf cell (next == nil) on top of 'list'.
+	     */
+	    junk= next;
+	    next= next->next;
+	    junk->next= list;
+	    list= junk;
+	} else
+	if (list != nil) {
+	    /* Delete the leaf cell.  If it has a sublist then that becomes
+	     * the 'next' chain.
+	     */
+	    junk= list;
+	    next= list->list;
+	    list= list->next;
+	    deallocate(junk);
+	} else {
+	    /* Both chains are gone. */
+	    break;
+	}
+    }
+}
+
+void config_delete(config_t *cfg1)
+/* Delete configuration file data, being careful with the odd first one. */
+{
+    firstconfig_t *fcfg= cfg2fcfg(cfg1);
+
+    delete_filelist(fcfg->filelist);
+    delete_config(fcfg->config1.next);
+    delete_config(fcfg->config1.list);
+    deallocate(fcfg);
+}
+
+static void nextc(void)
+/* Read the next character of the current file into 'c'. */
+{
+    if (c == '\n') c_line++;
+    c= getc(c_fp);
+    if (c == EOF && ferror(c_fp)) {
+	fprintf(stderr, "\"%s\", line %u: %s\n",
+	    c_file, c_line, strerror(errno));
+	exit(1);
+    }
+}
+
+static void skipwhite(void)
+/* Skip whitespace and comments. */
+{
+    while (isspace(c)) {
+	nextc();
+	if (c == '#') {
+	    do nextc(); while (c != EOF && c != '\n');
+	}
+    }
+}
+
+static void parse_err(void)
+/* Tell user that you can't parse past the current character. */
+{
+    char sc[2];
+
+    sc[0]= c;
+    sc[1]= 0;
+    fprintf(stderr, "\"%s\", line %u: parse error at '%s'\n",
+	c_file, c_line, c == EOF ? "EOF" : sc);
+    exit(1);
+}
+
+static config_t *read_word(void)
+/* Read a word or string. */
+{
+    config_t *w;
+    size_t i, len;
+    int q;
+    static char SPECIAL[] = "!#$%&*+-./:<=>?[\\]^_|~";
+
+    i= 0;
+    len= 32;
+    w= allocate(nil, configsize(32));
+    w->next= nil;
+    w->list= nil;
+    w->file= c_file;
+    w->line= c_line;
+    w->flags= 0;
+
+    /* Is it a quoted string? */
+    if (c == '\'' || c == '"') {
+	q= c;	/* yes */
+	nextc();
+    } else {
+	q= -1;	/* no */
+    }
+
+    for (;;) {
+	if (i == len) {
+	    len+= 32;
+	    w= allocate(w, configsize(len));
+	}
+
+	if (q == -1) {
+	    /* A word consists of letters, numbers and a few special chars. */
+	    if (!isalnum(c) && c < 0x80 && strchr(SPECIAL, c) == nil) break;
+	} else {
+	    /* Strings are made up of anything except newlines. */
+	    if (c == EOF || c == '\n') {
+		fprintf(stderr,
+		    "\"%s\", line %u: string at line %u not closed\n",
+		    c_file, c_line, w->line);
+		exit(1);
+		break;
+	    }
+	    if (c == q) {	/* Closing quote? */
+		nextc();
+		break;
+	    }
+	}
+
+	if (c != '\\') {	/* Simply add non-escapes. */
+	    w->word[i++]= c;
+	    nextc();
+	} else {		/* Interpret an escape. */
+	    nextc();
+	    if (isspace(c)) {
+		skipwhite();
+		continue;
+	    }
+
+	    if (c_flags & CFG_ESCAPED) {
+		w->word[i++]= '\\';	/* Keep the \ for the caller. */
+		if (i == len) {
+		    len+= 32;
+		    w= allocate(w, configsize(len));
+		}
+		w->flags |= CFG_ESCAPED;
+	    }
+
+	    if (isdigit(c)) {		/* Octal escape */
+		int n= 3;
+		int d= 0;
+
+		do {
+		    d= d * 010 + (c - '0');
+		    nextc();
+		} while (--n > 0 && isdigit(c));
+		w->word[i++]= d;
+	    } else
+	    if (c == 'x' || c == 'X') {	/* Hex escape */
+		int n= 2;
+		int d= 0;
+
+		nextc();
+		if (!isxdigit(c)) {
+		    fprintf(stderr, "\"%s\", line %u: bad hex escape\n",
+			c_file, c_line);
+		    exit(1);
+		}
+		do {
+		    d= d * 0x10 + (islower(c) ? (c - 'a' + 0xa) :
+				    isupper(c) ? (c - 'A' + 0xA) :
+				    (c - '0'));
+		    nextc();
+		} while (--n > 0 && isxdigit(c));
+		w->word[i++]= d;
+	    } else {
+		switch (c) {
+		case 'a':	c= '\a';	break;
+		case 'b':	c= '\b';	break;
+		case 'e':	c= '\033';	break;
+		case 'f':	c= '\f';	break;
+		case 'n':	c= '\n';	break;
+		case 'r':	c= '\r';	break;
+		case 's':	c= ' ';		break;
+		case 't':	c= '\t';	break;
+		case 'v':	c= '\v';	break;
+		default:	/* Anything else is kept as-is. */;
+		}
+		w->word[i++]= c;
+		nextc();
+	    }
+	}
+    }
+    w->word[i]= 0;
+    if (q != -1) {
+	w->flags |= CFG_STRING;
+    } else {
+	int f;
+	char *end;
+	static char base[]= { 0, 010, 10, 0x10 };
+
+	if (i == 0) parse_err();
+
+	/* Can the word be used as a number? */
+	for (f= 0; f < 4; f++) {
+	    (void) strtol(w->word, &end, base[f]);
+	    if (*end == 0) w->flags |= 1 << (f + 0);
+	    (void) strtoul(w->word, &end, base[f]);
+	    if (*end == 0) w->flags |= 1 << (f + 4);
+	}
+    }
+    return allocate(w, configsize(i));
+}
+
+static config_t *read_file(const char *file);
+static config_t *read_list(void);
+
+static config_t *read_line(void)
+/* Read and return one line of the config file. */
+{
+    config_t *cline, **pcline, *clist;
+
+    cline= nil;
+    pcline= &cline;
+
+    for (;;) {
+	skipwhite();
+
+	if (c == EOF || c == '}') {
+if(0)	    if (cline != nil) parse_err();
+	    break;
+	} else
+	if (c == ';') {
+	    nextc();
+	    if (cline != nil) break;
+	} else
+	if (cline != nil && c == '{') {
+	    /* A sublist. */
+	    nextc();
+	    clist= allocate(nil, config0size());
+	    clist->next= nil;
+	    clist->file= c_file;
+	    clist->line= c_line;
+	    clist->list= read_list();
+	    clist->flags= CFG_SUBLIST;
+	    *pcline= clist;
+	    pcline= &clist->next;
+	    if (c != '}') parse_err();
+	    nextc();
+	} else {
+	    *pcline= read_word();
+	    pcline= &(*pcline)->next;
+	}
+    }
+    return cline;
+}
+
+static config_t *read_list(void)
+/* Read and return a list of config file commands. */
+{
+    config_t *clist, **pclist, *cline;
+
+    clist= nil;
+    pclist= &clist;
+
+    while ((cline= read_line()) != nil) {
+	if (strcmp(cline->word, "include") == 0) {
+	    config_t *file= cline->next;
+	    if (file == nil || file->next != nil || !config_isatom(file)) {
+		fprintf(stderr,
+		    "\"%s\", line %u: 'include' command requires an argument\n",
+		    c_file, cline->line);
+		exit(1);
+	    }
+	    if (file->flags & CFG_ESCAPED) {
+		char *p, *q;
+		p= q= file->word;
+		for (;;) {
+		    if ((*q = *p) == '\\') *q = *++p;
+		    if (*q == 0) break;
+		    p++;
+		    q++;
+		}
+	    }
+	    file= read_file(file->word);
+	    delete_config(cline);
+	    *pclist= file;
+	    while (*pclist != nil) pclist= &(*pclist)->next;
+	} else {
+	    config_t *cfg= allocate(nil, config0size());
+	    cfg->next= nil;
+	    cfg->list= cline;
+	    cfg->file= cline->file;
+	    cfg->line= cline->line;
+	    cfg->flags= CFG_SUBLIST;
+	    *pclist= cfg;
+	    pclist= &cfg->next;
+	}
+    }
+    return clist;
+}
+
+static config_t *read_file(const char *file)
+/* Read and return a configuration file. */
+{
+    configfile_t *cfgf;
+    config_t *cfg;
+    struct stat st;
+    FILE *old_fp;	/* old_* variables store current file context. */
+    char *old_file;
+    unsigned old_line;
+    int old_c;
+    size_t n;
+    char *slash;
+
+    old_fp= c_fp;
+    old_file= c_file;
+    old_line= c_line;
+    old_c= c;
+
+    n= 0;
+    if (file[0] != '/' && old_file != nil
+			&& (slash= strrchr(old_file, '/')) != nil) {
+	n= slash - old_file + 1;
+    }
+    cfgf= allocate(nil, configfilesize(n + strlen(file)));
+    memcpy(cfgf->name, old_file, n);
+    strcpy(cfgf->name + n, file);
+    cfgf->next= c_files;
+    c_files= cfgf;
+
+    c_file= cfgf->name;
+    c_line= 0;
+
+    if ((c_fp= fopen(file, "r")) == nil || fstat(fileno(c_fp), &st) < 0) {
+	if (errno != ENOENT) {
+	    fprintf(stderr, "\"%s\", line 1: %s\n", file, strerror(errno));
+	    exit(1);
+	}
+	cfgf->ctime= -1;
+	c= EOF;
+    } else {
+	cfgf->ctime= st.st_ctime;
+	c= '\n';
+    }
+
+    cfg= read_list();
+    if (c != EOF) parse_err();
+
+    if (c_fp != nil) fclose(c_fp);
+    c_fp= old_fp;
+    c_file= old_file;
+    c_line= old_line;
+    c= old_c;
+    return cfg;
+}
+
+config_t *config_read(const char *file, int flags, config_t *cfg)
+/* Read and parse a configuration file. */
+{
+    if (cfg != nil) {
+	/* First check if any of the involved files has changed. */
+	firstconfig_t *fcfg;
+	configfile_t *cfgf;
+	struct stat st;
+
+	fcfg= cfg2fcfg(cfg);
+	for (cfgf= fcfg->filelist; cfgf != nil; cfgf= cfgf->next) {
+	    if (stat(cfgf->name, &st) < 0) {
+		if (errno != ENOENT) break;
+		st.st_ctime= -1;
+	    }
+	    if (st.st_ctime != cfgf->ctime) break;
+	}
+
+	if (cfgf == nil) return cfg;	/* Everything as it was. */
+	config_delete(cfg);		/* Otherwise delete and reread. */
+    }
+
+    errno= 0;
+    c_files= nil;
+    c_flags= flags;
+    cfg= read_file(file);
+
+    if (cfg != nil) {
+	/* Change first word to have a hidden pointer to a file list. */
+	size_t len= strlen(cfg->word);
+	firstconfig_t *fcfg;
+
+	fcfg= allocate(cfg, firstconfigsize(len));
+	memmove(&fcfg->config1, fcfg, configsize(len));
+	fcfg->filelist= c_files;
+	fcfg->new= 1;
+	return fcfg2cfg(fcfg);
+    }
+    /* Couldn't read (errno != 0) of nothing read (errno == 0). */
+    delete_filelist(c_files);
+    delete_config(cfg);
+    return nil;
+}
+
+int config_renewed(config_t *cfg)
+{
+    int new;
+
+    if (cfg == nil) {
+	new= 1;
+    } else {
+	new= cfg2fcfg(cfg)->new;
+	cfg2fcfg(cfg)->new= 0;
+    }
+    return new;
+}
+
+size_t config_length(config_t *cfg)
+/* Count the number of items on a list. */
+{
+    size_t n= 0;
+
+    while (cfg != nil) {
+	n++;
+	cfg= cfg->next;
+    }
+    return n;
+}
+
+#if TEST
+#include <unistd.h>
+
+static void print_list(int indent, config_t *cfg);
+
+static void print_words(int indent, config_t *cfg)
+{
+    while (cfg != nil) {
+	if (config_isatom(cfg)) {
+	    if (config_isstring(cfg)) fputc('"', stdout);
+	    printf("%s", cfg->word);
+	    if (config_isstring(cfg)) fputc('"', stdout);
+	} else {
+	    printf("{\n");
+	    print_list(indent+4, cfg->list);
+	    printf("%*s}", indent, "");
+	}
+	cfg= cfg->next;
+	if (cfg != nil) fputc(' ', stdout);
+    }
+    printf(";\n");
+}
+
+static void print_list(int indent, config_t *cfg)
+{
+    while (cfg != nil) {
+	if (!config_issub(cfg)) {
+	    fprintf(stderr, "Cell at \"%s\", line %u is not a sublist\n");
+	    break;
+	}
+	printf("%*s", indent, "");
+	print_words(indent, cfg->list);
+	cfg= cfg->next;
+    }
+}
+
+static void print_config(config_t *cfg)
+{
+    if (!config_renewed(cfg)) {
+	printf("# Config didn't change\n");
+    } else {
+	print_list(0, cfg);
+    }
+}
+
+int main(int argc, char **argv)
+{
+    config_t *cfg;
+    int c;
+
+    if (argc != 2) {
+	fprintf(stderr, "One config file name please\n");
+	exit(1);
+    }
+
+    cfg= nil;
+    do {
+	cfg= config_read(argv[1], CFG_ESCAPED, cfg);
+	print_config(cfg);
+	if (!isatty(0)) break;
+	while ((c= getchar()) != EOF && c != '\n') {}
+    } while (c != EOF);
+    return 0;
+}
+#endif /* TEST */
Index: /trunk/minix/lib/other/crypt.c
===================================================================
--- /trunk/minix/lib/other/crypt.c	(revision 9)
+++ /trunk/minix/lib/other/crypt.c	(revision 9)
@@ -0,0 +1,115 @@
+/*	crypt() - one-way password encryption function	Author: Kees J. Bot
+ *								7 Feb 1994
+ * This routine does not encrypt anything, it uses the pwdauth
+ * program to do the hard work.
+ */
+#define nil ((void*)0)
+#define pipe _pipe
+#define fork _fork
+#define close _close
+#define dup2 _dup2
+#define execl _execl
+#define read _read
+#define _exit __exit
+#define write _write
+#define waitpid _waitpid
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <sys/wait.h>
+
+/* Set-uid root program to read /etc/shadow or encrypt passwords. */
+static char PWDAUTH[] = "/usr/lib/pwdauth";
+#define LEN	1024
+
+static void tell(const char *s0, ...)
+{
+	va_list ap;
+	const char *s;
+
+	va_start(ap, s0);
+	s= s0;
+	while (s != nil) {
+		(void) write(2, s, strlen(s));
+		s= va_arg(ap, const char *);
+	}
+	va_end(ap);
+}
+
+char *crypt(const char *key, const char *salt)
+{
+	pid_t pid;
+	int status;
+	int pfd[2];
+	static char pwdata[LEN];
+	char *p= pwdata;
+	const char *k= key;
+	const char *s= salt;
+	int n;
+
+	/* Fill pwdata[] with the key and salt. */
+	while ((*p++ = *k++) != 0) if (p == pwdata+LEN-1) goto fail;
+	while ((*p++ = *s++) != 0) if (p == pwdata+LEN-0) goto fail;
+
+	if (pipe(pfd) < 0) goto fail;
+
+	/* Prefill the pipe. */
+	(void) write(pfd[1], pwdata, p - pwdata);
+
+	switch ((pid= fork())) {
+	case -1:
+		close(pfd[0]);
+		close(pfd[1]);
+		goto fail;
+	case 0:
+		/* Connect both input and output to the pipe. */
+		if (pfd[0] != 0) {
+			dup2(pfd[0], 0);
+			close(pfd[0]);
+		}
+		if (pfd[1] != 1) {
+			dup2(pfd[1], 1);
+			close(pfd[1]);
+		}
+
+		execl(PWDAUTH, PWDAUTH, (char *) nil);
+
+		tell("crypt(): ", PWDAUTH, ": ", strerror(errno), "\r\n",
+								(char *) nil);
+		/* No pwdauth?  Fail! */
+		(void) read(0, pwdata, LEN);
+		_exit(1);
+	}
+	close(pfd[1]);
+
+	status= -1;
+	while (waitpid(pid, &status, 0) == -1 && errno == EINTR) {}
+	if (status != 0) {
+		close(pfd[0]);
+		goto fail;
+	}
+
+	/* Read and return the result.  Check if it contains exactly one
+	 * string.
+	 */
+	n= read(pfd[0], pwdata, LEN);
+	close(pfd[0]);
+	if (n < 0) goto fail;
+	p = pwdata + n;
+	n = 0;
+	while (p > pwdata) if (*--p == 0) n++;
+	if (n != 1) goto fail;
+	return pwdata;
+
+fail:
+	pwdata[0] = salt[0] ^ 1;		/* make result != salt */
+	pwdata[1] = 0;
+	return pwdata;
+}
+
+/*
+ * $PchId: crypt.c,v 1.5 1996/04/11 07:46:11 philip Exp $
+ */
Index: /trunk/minix/lib/other/ctermid.c
===================================================================
--- /trunk/minix/lib/other/ctermid.c	(revision 9)
+++ /trunk/minix/lib/other/ctermid.c	(revision 9)
@@ -0,0 +1,32 @@
+/*  ctermid(3)
+ *
+ *  Author: Terrence Holm          Aug. 1988
+ *
+ *
+ *  Ctermid(3) returns a pointer to a string naming the controlling
+ *  terminal. If <name_space> is NULL then local PRIVATE storage
+ *  is used, otherwise <name_space> must point to storage of at
+ *  least L_ctermid characters.
+ *
+ *  Returns a pointer to "/dev/tty".
+ */
+
+#include <lib.h>
+#include <string.h>
+#include <stdio.h>
+
+_PROTOTYPE( char *ctermid, (char *name_space));
+
+#ifndef L_ctermid
+#define L_ctermid  9
+#endif
+
+char *ctermid(name_space)
+char *name_space;
+{
+  PRIVATE char termid[L_ctermid];
+
+  if (name_space == (char *)NULL) name_space = termid;
+  strcpy(name_space, "/dev/tty");
+  return(name_space);
+}
Index: /trunk/minix/lib/other/cuserid.c
===================================================================
--- /trunk/minix/lib/other/cuserid.c	(revision 9)
+++ /trunk/minix/lib/other/cuserid.c	(revision 9)
@@ -0,0 +1,33 @@
+/*  cuserid(3)
+ *
+ *  Author: Terrence W. Holm          Sept. 1987
+ */
+
+#include <lib.h>
+#include <pwd.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#ifndef  L_cuserid
+#define  L_cuserid   9
+#endif
+
+char *cuserid(user_name)
+char *user_name;
+{
+  PRIVATE char userid[L_cuserid];
+  struct passwd *pw_entry;
+
+  if (user_name == (char *)NULL) user_name = userid;
+
+  pw_entry = getpwuid(geteuid());
+
+  if (pw_entry == (struct passwd *)NULL) {
+	*user_name = '\0';
+	return((char *)NULL);
+  }
+  strcpy(user_name, pw_entry->pw_name);
+
+  return(user_name);
+}
Index: /trunk/minix/lib/other/environ.c
===================================================================
--- /trunk/minix/lib/other/environ.c	(revision 9)
+++ /trunk/minix/lib/other/environ.c	(revision 9)
@@ -0,0 +1,20 @@
+/*
+ * environ.c - define the variable environ
+ */
+/* $Header: /cvsup/minix/src/lib/other/environ.c,v 1.1.1.1 2005/04/21 14:56:26 beng Exp $ */
+/*
+ * This file defines the variable environ and initializes it with a magic
+ * value.  The C run-time start-off routine tests whether the variable
+ * environ is initialized with this value.  If it is not, it is assumed
+ * that it is defined by the user.  Only two bytes are tested, since we
+ * don't know the endian-ness and alignment restrictions of the machine.
+ * This means that the low-order two-bytes should be equal to the
+ * high-order two-bytes on machines with four-byte pointers.  In fact, all
+ * the bytes in the pointer are the same, just in case.
+ */
+
+#if _EM_PSIZE==2
+char **environ = (char **) 0x5353;
+#else
+char **environ = (char **) 0x53535353;
+#endif
Index: /trunk/minix/lib/other/errno.c
===================================================================
--- /trunk/minix/lib/other/errno.c	(revision 9)
+++ /trunk/minix/lib/other/errno.c	(revision 9)
@@ -0,0 +1,4 @@
+#include <lib.h>
+/* errno.c - declare variable errno             Author: F. Meulenbroeks */
+
+int errno = 0;
Index: /trunk/minix/lib/other/fdopen.c
===================================================================
--- /trunk/minix/lib/other/fdopen.c	(revision 9)
+++ /trunk/minix/lib/other/fdopen.c	(revision 9)
@@ -0,0 +1,73 @@
+/*
+ * fdopen - convert a (UNIX) file descriptor into a FILE pointer
+ */
+/* $Header: /cvsup/minix/src/lib/other/fdopen.c,v 1.2 2005/09/06 10:15:57 beng Exp $ */
+
+#include	<stdlib.h>
+#include	"../stdio/loc_incl.h"
+#include	<stdio.h>
+#include	<sys/stat.h>
+
+FILE *
+fdopen(fd, mode)
+int fd;
+_CONST char *mode;
+{
+	register int i;
+	struct stat st;
+	FILE *stream;
+	int flags = 0;
+
+	if (fd < 0) return (FILE *)NULL;
+	for (i = 0; __iotab[i] != 0 ; i++) 
+		if (i >= FOPEN_MAX-1)
+			return (FILE *)NULL;
+
+	switch(*mode++) {
+	case 'r':
+		flags |= _IOREAD | _IOREADING;
+		break;
+	case 'a':
+		flags |= _IOAPPEND;
+	case 'w':
+		flags |= _IOWRITE | _IOWRITING;
+		break;
+	default:
+		return (FILE *)NULL;
+	}
+	while(*mode) {
+		switch(*mode++) {
+		case 'b':
+			continue;
+		case '+':
+			flags |= _IOREAD | _IOWRITE;
+			continue;
+		/* The sequence may be followed by aditional characters */
+		default:
+			break;
+		}
+		break;
+	}
+
+	if ( fstat( fd, &st ) < 0 ) {
+		return (FILE *)NULL;
+	}
+	
+	if ( st.st_mode & S_IFIFO ) {
+		flags |= _IOFIFO;
+	}
+	
+	if ((stream = (FILE *) malloc(sizeof(FILE))) == NULL) {
+		return (FILE *)NULL;
+	}
+
+	if ((flags & _IOREAD) && (flags & _IOWRITE))
+		flags &= ~(_IOREADING | _IOWRITING);
+
+	stream->_count = 0;
+	stream->_fd = fd;
+	stream->_flags = flags;
+	stream->_buf = NULL;
+	__iotab[i] = stream;
+	return stream;
+}
Index: /trunk/minix/lib/other/ffs.c
===================================================================
--- /trunk/minix/lib/other/ffs.c	(revision 9)
+++ /trunk/minix/lib/other/ffs.c	(revision 9)
@@ -0,0 +1,17 @@
+#include <lib.h>
+/*  ffs(3)
+ *
+ *  Author: Terrence W. Holm          Sep. 1988
+ */
+_PROTOTYPE( int ffs, (int word));
+
+int ffs(word)
+int word;
+{
+  int i;
+
+  if (word == 0) return(0);
+
+  for (i = 1;; ++i, word >>= 1)
+	if (word & 1) return(i);
+}
Index: /trunk/minix/lib/other/flock.c
===================================================================
--- /trunk/minix/lib/other/flock.c	(revision 9)
+++ /trunk/minix/lib/other/flock.c	(revision 9)
@@ -0,0 +1,32 @@
+
+/* Library routines
+ *
+ * Porting to Minix 2.0.0
+ * Author:	Giovanni Falzoni <gfalzoni@pointest.com>
+ *
+ * $Id: flock.c,v 1.1 2005/10/31 14:31:05 beng Exp $
+ */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+/*
+ *	Name:		int flock(int fd, int mode);
+ *	Function:	Implements the flock function in Minix.
+ */
+int flock(int fd, int mode)
+{
+  struct flock lck;
+  register int retcode;
+
+  memset((void *) &lck, 0, sizeof(struct flock));
+  lck.l_type = mode & ~LOCK_NB;
+  lck.l_pid = getpid();
+  if ((retcode = fcntl(fd, mode & LOCK_NB ? F_SETLK : F_SETLKW, &lck)) < 0 && errno == EAGAIN)
+	errno = EWOULDBLOCK;
+  return retcode;
+}
+
+/** flock.c **/
Index: /trunk/minix/lib/other/fslib.c
===================================================================
--- /trunk/minix/lib/other/fslib.c	(revision 9)
+++ /trunk/minix/lib/other/fslib.c	(revision 9)
@@ -0,0 +1,191 @@
+/* fslib.c - routines needed by fs and fs utilities */
+
+#include <minix/config.h>	/* for unused stuff in <minix/type.h> :-( */
+#include <ansi.h>
+#include <limits.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <minix/const.h>
+#include <minix/type.h>		/* for unshort :-( */
+#include "fs/const.h"		/* depends of -I flag in Makefile */
+#include "fs/type.h"		/* ditto */
+#include "fs/inode.h"		/* ditto */
+#include "fs/super.h"
+#include <minix/fslib.h>
+
+/* The next routine is copied from fsck.c and mkfs.c...  (Re)define some
+ * things for consistency.  Some things should be done better.
+ */
+
+/* Convert from bit count to a block count. The usual expression
+ *
+ *	(nr_bits + (1 << BITMAPSHIFT) - 1) >> BITMAPSHIFT
+ *
+ * doesn't work because of overflow.
+ *
+ * Other overflow bugs, such as the expression for N_ILIST overflowing when
+ * s_inodes is just over V*_INODES_PER_BLOCK less than the maximum+1, are not
+ * fixed yet, because that number of inodes is silly.
+ */
+/* The above comment doesn't all apply now bit_t is long.  Overflow is now
+ * unlikely, but negative bit counts are now possible (though unlikely)
+ * and give silly results.
+ */ 
+PUBLIC int bitmapsize(nr_bits, block_size)
+bit_t nr_bits;
+int block_size;
+{
+  int nr_blocks;
+
+  nr_blocks = (int) (nr_bits / FS_BITS_PER_BLOCK(block_size));
+  if (((bit_t) nr_blocks * FS_BITS_PER_BLOCK(block_size)) < nr_bits) ++nr_blocks;
+  return(nr_blocks);
+}
+
+
+/*===========================================================================*
+ *				conv2					     *
+ *===========================================================================*/
+PUBLIC unsigned conv2(norm, w)
+int norm;			/* TRUE if no swap, FALSE for byte swap */
+int w;				/* promotion of 16-bit word to be swapped */
+{
+/* Possibly swap a 16-bit word between 8086 and 68000 byte order. */
+
+  if (norm) return( (unsigned) w & 0xFFFF);
+  return( ((w&BYTE) << 8) | ( (w>>8) & BYTE));
+}
+
+
+/*===========================================================================*
+ *				conv4					     *
+ *===========================================================================*/
+PUBLIC long conv4(norm, x)
+int norm;			/* TRUE if no swap, FALSE for byte swap */
+long x;				/* 32-bit long to be byte swapped */
+{
+/* Possibly swap a 32-bit long between 8086 and 68000 byte order. */
+
+  unsigned lo, hi;
+  long l;
+  
+  if (norm) return(x);			/* byte order was already ok */
+  lo = conv2(FALSE, (int) x & 0xFFFF);	/* low-order half, byte swapped */
+  hi = conv2(FALSE, (int) (x>>16) & 0xFFFF);	/* high-order half, swapped */
+  l = ( (long) lo <<16) | hi;
+  return(l);
+}
+
+
+/*===========================================================================*
+ *				conv_inode				     *
+ *===========================================================================*/
+PUBLIC void conv_inode(rip, dip, dip2, rw_flag, magic)
+register struct inode *rip;	/* pointer to the in-core inode struct */
+register d1_inode *dip;		/* pointer to the V1 on-disk inode struct */
+register d2_inode *dip2;	/* pointer to the V2 on-disk inode struct */
+int rw_flag;			/* READING or WRITING */
+int magic;			/* magic number of file system */
+{ 
+/* Copy the inode from the disk block to the in-core table or vice versa.
+ * If the fourth parameter below is FALSE, the bytes are swapped.
+ */
+  switch (magic) {
+	case SUPER_MAGIC:	old_icopy(rip, dip,  rw_flag, TRUE);	break;
+	case SUPER_REV:		old_icopy(rip, dip,  rw_flag, FALSE);	break;
+	case SUPER_V3:
+	case SUPER_V2:		new_icopy(rip, dip2, rw_flag, TRUE);	break;
+	case SUPER_V2_REV:	new_icopy(rip, dip2, rw_flag, FALSE);	break;
+  } 
+}
+
+
+/*===========================================================================*
+ *				old_icopy				     *
+ *===========================================================================*/
+PUBLIC void old_icopy(rip, dip, direction, norm)
+register struct inode *rip;	/* pointer to the in-core inode struct */
+register d1_inode *dip;		/* pointer to the d1_inode inode struct */
+int direction;			/* READING (from disk) or WRITING (to disk) */
+int norm;			/* TRUE = do not swap bytes; FALSE = swap */
+
+{
+/* 4 different on-disk inode layouts are supported, one for each combination
+ * of V1.x/V2.x * bytes-swapped/not-swapped.  When an inode is read or written
+ * this routine handles the conversions so that the information in the inode
+ * table is independent of the disk structure from which the inode came.
+ * The old_icopy routine copies to and from V1 disks.
+ */
+
+  int i;
+
+  if (direction == READING) {
+	/* Copy V1.x inode to the in-core table, swapping bytes if need be. */
+	rip->i_mode    = conv2(norm, dip->d1_mode);
+	rip->i_uid     = conv2(norm,dip->d1_uid );
+	rip->i_size    = conv4(norm,dip->d1_size);
+	rip->i_mtime   = conv4(norm,dip->d1_mtime);
+	rip->i_atime   = 0;
+	rip->i_ctime   = 0;
+	rip->i_nlinks  = (nlink_t) dip->d1_nlinks;	/* 1 char */
+	rip->i_gid     = (gid_t) dip->d1_gid;		/* 1 char */
+	rip->i_ndzones = V1_NR_DZONES;
+	rip->i_nindirs = V1_INDIRECTS;
+	for (i = 0; i < V1_NR_TZONES; i++)
+		rip->i_zone[i] = conv2(norm, (int) dip->d1_zone[i]);
+  } else {
+	/* Copying V1.x inode to disk from the in-core table. */
+	dip->d1_mode   = conv2(norm,rip->i_mode);
+	dip->d1_uid    = conv2(norm,rip->i_uid );
+	dip->d1_size   = conv4(norm,rip->i_size);
+	dip->d1_mtime  = conv4(norm,rip->i_mtime);
+	dip->d1_nlinks = (nlink_t) rip->i_nlinks;	/* 1 char */
+	dip->d1_gid    = (gid_t) rip->i_gid;		/* 1 char */
+	for (i = 0; i < V1_NR_TZONES; i++)
+		dip->d1_zone[i] = conv2(norm, (int) rip->i_zone[i]);
+  }
+}
+
+
+/*===========================================================================*
+ *				new_icopy				     *
+ *===========================================================================*/
+PUBLIC void new_icopy(rip, dip, direction, norm)
+register struct inode *rip;	/* pointer to the in-core inode struct */
+register d2_inode *dip;	/* pointer to the d2_inode struct */
+int direction;			/* READING (from disk) or WRITING (to disk) */
+int norm;			/* TRUE = do not swap bytes; FALSE = swap */
+
+{
+/* Same as old_icopy, but to/from V2 disk layout. */
+
+  int i;
+
+  if (direction == READING) {
+	/* Copy V2.x inode to the in-core table, swapping bytes if need be. */
+	rip->i_mode    = conv2(norm,dip->d2_mode);
+	rip->i_uid     = conv2(norm,dip->d2_uid );
+	rip->i_nlinks  = conv2(norm,(int) dip->d2_nlinks);
+	rip->i_gid     = conv2(norm,(int) dip->d2_gid );
+	rip->i_size    = conv4(norm,dip->d2_size);
+	rip->i_atime   = conv4(norm,dip->d2_atime);
+	rip->i_ctime   = conv4(norm,dip->d2_ctime);
+	rip->i_mtime   = conv4(norm,dip->d2_mtime);
+	rip->i_ndzones = V2_NR_DZONES;
+	rip->i_nindirs = V2_INDIRECTS(rip->i_sp->s_block_size);
+	for (i = 0; i < V2_NR_TZONES; i++)
+		rip->i_zone[i] = conv4(norm, (long) dip->d2_zone[i]);
+  } else {
+	/* Copying V2.x inode to disk from the in-core table. */
+	dip->d2_mode   = conv2(norm,rip->i_mode);
+	dip->d2_uid    = conv2(norm,rip->i_uid );
+	dip->d2_nlinks = conv2(norm,rip->i_nlinks);
+	dip->d2_gid    = conv2(norm,rip->i_gid );
+	dip->d2_size   = conv4(norm,rip->i_size);
+	dip->d2_atime  = conv4(norm,rip->i_atime);
+	dip->d2_ctime  = conv4(norm,rip->i_ctime);
+	dip->d2_mtime  = conv4(norm,rip->i_mtime);
+	for (i = 0; i < V2_NR_TZONES; i++)
+		dip->d2_zone[i] = conv4(norm, (long) rip->i_zone[i]);
+  }
+}
Index: /trunk/minix/lib/other/fsversion.c
===================================================================
--- /trunk/minix/lib/other/fsversion.c	(revision 9)
+++ /trunk/minix/lib/other/fsversion.c	(revision 9)
@@ -0,0 +1,52 @@
+/* This procedure examines a file system and figures out whether it is
+ * version 1 or version 2.  It returns the result as an int.  If the
+ * file system is neither, it returns -1.  A typical call is:
+ *
+ *	n = fsversion("/dev/hd1", "df");
+ *
+ * The first argument is the special file for the file system. 
+ * The second is the program name, which is used in error messages.
+ */
+
+#include <sys/types.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include "fs/const.h"
+#include "fs/type.h"
+#include "fs/super.h"
+
+static struct super_block super, *sp;
+
+int fsversion(dev, prog)
+char *dev, *prog;
+{
+  int fd;
+
+  if ((fd = open(dev, O_RDONLY)) < 0) {
+	std_err(prog);
+	std_err(" cannot open ");
+	perror(dev);
+	return(-1);
+  }
+
+  lseek(fd, (off_t) SUPER_BLOCK_BYTES, SEEK_SET);	/* skip boot block */
+  if (read(fd, (char *) &super, (unsigned) SUPER_SIZE) != SUPER_SIZE) {
+	std_err(prog);
+	std_err(" cannot read super block on ");
+	perror(dev);
+	close(fd);
+	return(-1);
+  }
+  close(fd);
+  sp = &super;
+  if (sp->s_magic == SUPER_MAGIC) return(1);
+  if (sp->s_magic == SUPER_V2) return(2);
+  if (sp->s_magic == SUPER_V3) return(3);
+  return(-1);
+}
Index: /trunk/minix/lib/other/fts.c
===================================================================
--- /trunk/minix/lib/other/fts.c	(revision 9)
+++ /trunk/minix/lib/other/fts.c	(revision 9)
@@ -0,0 +1,1217 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $OpenBSD: fts.c,v 1.22 1999/10/03 19:22:22 millert Exp $
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fts.c	8.6 (Berkeley) 8/14/94";
+#endif /* LIBC_SCCS and not lint */
+#endif
+
+#define MAX(a, b)   ((a) > (b) ? (a) : (b))
+#define MIN(a, b)   ((a) < (b) ? (a) : (b))
+
+
+#define _POSIX_SOURCE 1
+#define _MINIX 1
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+static FTSENT	*fts_alloc(FTS *, char *, int);
+static FTSENT	*fts_build(FTS *, int);
+static void	 fts_lfree(FTSENT *);
+static void	 fts_load(FTS *, FTSENT *);
+static size_t	 fts_maxarglen(char * const *);
+static void	 fts_padjust(FTS *, FTSENT *);
+static int	 fts_palloc(FTS *, size_t);
+static FTSENT	*fts_sort(FTS *, FTSENT *, int);
+static u_short	 fts_stat(FTS *, FTSENT *, int);
+static int	 fts_safe_changedir(FTS *, FTSENT *, int, char *);
+static int	 fts_ufslinks(FTS *, const FTSENT *);
+
+#define	ISDOT(a)	(a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
+
+#define	CLR(opt)	(sp->fts_options &= ~(opt))
+#define	ISSET(opt)	(sp->fts_options & (opt))
+#define	SET(opt)	(sp->fts_options |= (opt))
+
+#define	FCHDIR(sp, fd)	(!ISSET(FTS_NOCHDIR) && fchdir(fd))
+
+/* fts_build flags */
+#define	BCHILD		1		/* fts_children */
+#define	BNAMES		2		/* fts_children, names only */
+#define	BREAD		3		/* fts_read */
+
+/*
+ * Internal representation of an FTS, including extra implementation
+ * details.  The FTS returned from fts_open points to this structure's
+ * ftsp_fts member (and can be cast to an _fts_private as required)
+ */
+struct _fts_private {
+	FTS		ftsp_fts;
+	dev_t		ftsp_dev;
+	int		ftsp_linksreliable;
+};
+
+/*
+ * The "FTS_NOSTAT" option can avoid a lot of calls to stat(2) if it
+ * knows that a directory could not possibly have subdirectories.  This
+ * is decided by looking at the link count: a subdirectory would
+ * increment its parent's link count by virtue of its own ".." entry.
+ * This assumption only holds for UFS-like filesystems that implement
+ * links and directories this way, so we must punt for others.
+ */
+
+static const char *ufslike_filesystems[] = {
+	"ufs",
+	"nfs",
+	"nfs4",
+	"ext2fs",
+	0
+};
+
+static void *reallocf(void *ptr, size_t size)
+{
+	void *p;
+	if((p = realloc(ptr, size))) return p;
+	if(ptr) free(ptr);
+	return NULL;
+}
+
+FTS *
+fts_open(argv, options, compar)
+	char * const *argv;
+	int options;
+	int (*compar)(const FTSENT * const *, const FTSENT * const *);
+{
+	struct _fts_private *priv;
+	FTS *sp;
+	FTSENT *p, *root;
+	int nitems;
+	FTSENT *parent, *tmp;
+	int len;
+
+	/* Options check. */
+	if (options & ~FTS_OPTIONMASK) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	/* Allocate/initialize the stream. */
+	if ((priv = malloc(sizeof(*priv))) == NULL)
+		return (NULL);
+	memset(priv, 0, sizeof(*priv));
+	sp = &priv->ftsp_fts;
+	sp->fts_compar = compar;
+	sp->fts_options = options;
+
+	/* Shush, GCC. */
+	tmp = NULL;
+
+	/* Logical walks turn on NOCHDIR; symbolic links are too hard. */
+	if (ISSET(FTS_LOGICAL))
+		SET(FTS_NOCHDIR);
+
+	/*
+	 * Start out with 1K of path space, and enough, in any case,
+	 * to hold the user's paths.
+	 */
+	if (fts_palloc(sp, MAX(fts_maxarglen(argv), PATH_MAX)))
+		goto mem1;
+
+	/* Allocate/initialize root's parent. */
+	if ((parent = fts_alloc(sp, "", 0)) == NULL)
+		goto mem2;
+	parent->fts_level = FTS_ROOTPARENTLEVEL;
+
+	/* Allocate/initialize root(s). */
+	for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
+		/* Don't allow zero-length paths. */
+		if ((len = strlen(*argv)) == 0) {
+			errno = ENOENT;
+			goto mem3;
+		}
+
+		p = fts_alloc(sp, *argv, len);
+		p->fts_level = FTS_ROOTLEVEL;
+		p->fts_parent = parent;
+		p->fts_accpath = p->fts_name;
+		p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW));
+
+		/* Command-line "." and ".." are real directories. */
+		if (p->fts_info == FTS_DOT)
+			p->fts_info = FTS_D;
+
+		/*
+		 * If comparison routine supplied, traverse in sorted
+		 * order; otherwise traverse in the order specified.
+		 */
+		if (compar) {
+			p->fts_link = root;
+			root = p;
+		} else {
+			p->fts_link = NULL;
+			if (root == NULL)
+				tmp = root = p;
+			else {
+				tmp->fts_link = p;
+				tmp = p;
+			}
+		}
+	}
+	if (compar && nitems > 1)
+		root = fts_sort(sp, root, nitems);
+
+	/*
+	 * Allocate a dummy pointer and make fts_read think that we've just
+	 * finished the node before the root(s); set p->fts_info to FTS_INIT
+	 * so that everything about the "current" node is ignored.
+	 */
+	if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
+		goto mem3;
+	sp->fts_cur->fts_link = root;
+	sp->fts_cur->fts_info = FTS_INIT;
+
+	/*
+	 * If using chdir(2), grab a file descriptor pointing to dot to ensure
+	 * that we can get back here; this could be avoided for some paths,
+	 * but almost certainly not worth the effort.  Slashes, symbolic links,
+	 * and ".." are all fairly nasty problems.  Note, if we can't get the
+	 * descriptor we run anyway, just more slowly.
+	 */
+	if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = _open(".", O_RDONLY, 0)) < 0)
+		SET(FTS_NOCHDIR);
+
+	return (sp);
+
+mem3:	fts_lfree(root);
+	free(parent);
+mem2:	free(sp->fts_path);
+mem1:	free(sp);
+	return (NULL);
+}
+
+static void
+fts_load(sp, p)
+	FTS *sp;
+	FTSENT *p;
+{
+	int len;
+	char *cp;
+
+	/*
+	 * Load the stream structure for the next traversal.  Since we don't
+	 * actually enter the directory until after the preorder visit, set
+	 * the fts_accpath field specially so the chdir gets done to the right
+	 * place and the user can access the first node.  From fts_open it's
+	 * known that the path will fit.
+	 */
+	len = p->fts_pathlen = p->fts_namelen;
+	memmove(sp->fts_path, p->fts_name, len + 1);
+	if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
+		len = strlen(++cp);
+		memmove(p->fts_name, cp, len + 1);
+		p->fts_namelen = len;
+	}
+	p->fts_accpath = p->fts_path = sp->fts_path;
+	sp->fts_dev = p->fts_dev;
+}
+
+int
+fts_close(sp)
+	FTS *sp;
+{
+	FTSENT *freep, *p;
+	int saved_errno;
+
+	/*
+	 * This still works if we haven't read anything -- the dummy structure
+	 * points to the root list, so we step through to the end of the root
+	 * list which has a valid parent pointer.
+	 */
+	if (sp->fts_cur) {
+		for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
+			freep = p;
+			p = p->fts_link != NULL ? p->fts_link : p->fts_parent;
+			free(freep);
+		}
+		free(p);
+	}
+
+	/* Free up child linked list, sort array, path buffer. */
+	if (sp->fts_child)
+		fts_lfree(sp->fts_child);
+	if (sp->fts_array)
+		free(sp->fts_array);
+	free(sp->fts_path);
+
+	/* Return to original directory, save errno if necessary. */
+	if (!ISSET(FTS_NOCHDIR)) {
+		saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
+		(void)_close(sp->fts_rfd);
+
+		/* Set errno and return. */
+		if (saved_errno != 0) {
+			/* Free up the stream pointer. */
+			free(sp);
+			errno = saved_errno;
+			return (-1);
+		}
+	}
+
+	/* Free up the stream pointer. */
+	free(sp);
+	return (0);
+}
+
+/*
+ * Special case of "/" at the end of the path so that slashes aren't
+ * appended which would cause paths to be written as "....//foo".
+ */
+#define	NAPPEND(p)							\
+	(p->fts_path[p->fts_pathlen - 1] == '/'				\
+	    ? p->fts_pathlen - 1 : p->fts_pathlen)
+
+FTSENT *
+fts_read(sp)
+	FTS *sp;
+{
+	FTSENT *p, *tmp;
+	int instr;
+	char *t;
+	int saved_errno;
+
+	/* If finished or unrecoverable error, return NULL. */
+	if (sp->fts_cur == NULL || ISSET(FTS_STOP))
+		return (NULL);
+
+	/* Set current node pointer. */
+	p = sp->fts_cur;
+
+	/* Save and zero out user instructions. */
+	instr = p->fts_instr;
+	p->fts_instr = FTS_NOINSTR;
+
+	/* Any type of file may be re-visited; re-stat and re-turn. */
+	if (instr == FTS_AGAIN) {
+		p->fts_info = fts_stat(sp, p, 0);
+		return (p);
+	}
+
+	/*
+	 * Following a symlink -- SLNONE test allows application to see
+	 * SLNONE and recover.  If indirecting through a symlink, have
+	 * keep a pointer to current location.  If unable to get that
+	 * pointer, follow fails.
+	 */
+	if (instr == FTS_FOLLOW &&
+	    (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
+		p->fts_info = fts_stat(sp, p, 1);
+		if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+			if ((p->fts_symfd = _open(".", O_RDONLY, 0)) < 0) {
+				p->fts_errno = errno;
+				p->fts_info = FTS_ERR;
+			} else
+				p->fts_flags |= FTS_SYMFOLLOW;
+		}
+		return (p);
+	}
+
+	/* Directory in pre-order. */
+	if (p->fts_info == FTS_D) {
+		/* If skipped or crossed mount point, do post-order visit. */
+		if (instr == FTS_SKIP ||
+		    (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
+			if (p->fts_flags & FTS_SYMFOLLOW)
+				(void)_close(p->fts_symfd);
+			if (sp->fts_child) {
+				fts_lfree(sp->fts_child);
+				sp->fts_child = NULL;
+			}
+			p->fts_info = FTS_DP;
+			return (p);
+		}
+
+		/* Rebuild if only read the names and now traversing. */
+		if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) {
+			CLR(FTS_NAMEONLY);
+			fts_lfree(sp->fts_child);
+			sp->fts_child = NULL;
+		}
+
+		/*
+		 * Cd to the subdirectory.
+		 *
+		 * If have already read and now fail to chdir, whack the list
+		 * to make the names come out right, and set the parent errno
+		 * so the application will eventually get an error condition.
+		 * Set the FTS_DONTCHDIR flag so that when we logically change
+		 * directories back to the parent we don't do a chdir.
+		 *
+		 * If haven't read do so.  If the read fails, fts_build sets
+		 * FTS_STOP or the fts_info field of the node.
+		 */
+		if (sp->fts_child != NULL) {
+			if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
+				p->fts_errno = errno;
+				p->fts_flags |= FTS_DONTCHDIR;
+				for (p = sp->fts_child; p != NULL;
+				    p = p->fts_link)
+					p->fts_accpath =
+					    p->fts_parent->fts_accpath;
+			}
+		} else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
+			if (ISSET(FTS_STOP))
+				return (NULL);
+			return (p);
+		}
+		p = sp->fts_child;
+		sp->fts_child = NULL;
+		goto name;
+	}
+
+	/* Move to the next node on this level. */
+next:	tmp = p;
+	if ((p = p->fts_link) != NULL) {
+		free(tmp);
+
+		/*
+		 * If reached the top, return to the original directory (or
+		 * the root of the tree), and load the paths for the next root.
+		 */
+		if (p->fts_level == FTS_ROOTLEVEL) {
+			if (FCHDIR(sp, sp->fts_rfd)) {
+				SET(FTS_STOP);
+				return (NULL);
+			}
+			fts_load(sp, p);
+			return (sp->fts_cur = p);
+		}
+
+		/*
+		 * User may have called fts_set on the node.  If skipped,
+		 * ignore.  If followed, get a file descriptor so we can
+		 * get back if necessary.
+		 */
+		if (p->fts_instr == FTS_SKIP)
+			goto next;
+		if (p->fts_instr == FTS_FOLLOW) {
+			p->fts_info = fts_stat(sp, p, 1);
+			if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+				if ((p->fts_symfd =
+				    _open(".", O_RDONLY, 0)) < 0) {
+					p->fts_errno = errno;
+					p->fts_info = FTS_ERR;
+				} else
+					p->fts_flags |= FTS_SYMFOLLOW;
+			}
+			p->fts_instr = FTS_NOINSTR;
+		}
+
+name:		t = sp->fts_path + NAPPEND(p->fts_parent);
+		*t++ = '/';
+		memmove(t, p->fts_name, p->fts_namelen + 1);
+		return (sp->fts_cur = p);
+	}
+
+	/* Move up to the parent node. */
+	p = tmp->fts_parent;
+	free(tmp);
+
+	if (p->fts_level == FTS_ROOTPARENTLEVEL) {
+		/*
+		 * Done; free everything up and set errno to 0 so the user
+		 * can distinguish between error and EOF.
+		 */
+		free(p);
+		errno = 0;
+		return (sp->fts_cur = NULL);
+	}
+
+	/* NUL terminate the pathname. */
+	sp->fts_path[p->fts_pathlen] = '\0';
+
+	/*
+	 * Return to the parent directory.  If at a root node or came through
+	 * a symlink, go back through the file descriptor.  Otherwise, cd up
+	 * one directory.
+	 */
+	if (p->fts_level == FTS_ROOTLEVEL) {
+		if (FCHDIR(sp, sp->fts_rfd)) {
+			SET(FTS_STOP);
+			return (NULL);
+		}
+	} else if (p->fts_flags & FTS_SYMFOLLOW) {
+		if (FCHDIR(sp, p->fts_symfd)) {
+			saved_errno = errno;
+			(void)_close(p->fts_symfd);
+			errno = saved_errno;
+			SET(FTS_STOP);
+			return (NULL);
+		}
+		(void)_close(p->fts_symfd);
+	} else if (!(p->fts_flags & FTS_DONTCHDIR) &&
+	    fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
+		SET(FTS_STOP);
+		return (NULL);
+	}
+	p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
+	return (sp->fts_cur = p);
+}
+
+/*
+ * Fts_set takes the stream as an argument although it's not used in this
+ * implementation; it would be necessary if anyone wanted to add global
+ * semantics to fts using fts_set.  An error return is allowed for similar
+ * reasons.
+ */
+/* ARGSUSED */
+int
+fts_set(sp, p, instr)
+	FTS *sp;
+	FTSENT *p;
+	int instr;
+{
+	if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
+	    instr != FTS_NOINSTR && instr != FTS_SKIP) {
+		errno = EINVAL;
+		return (1);
+	}
+	p->fts_instr = instr;
+	return (0);
+}
+
+FTSENT *
+fts_children(sp, instr)
+	FTS *sp;
+	int instr;
+{
+	FTSENT *p;
+	int fd;
+
+	if (instr != 0 && instr != FTS_NAMEONLY) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	/* Set current node pointer. */
+	p = sp->fts_cur;
+
+	/*
+	 * Errno set to 0 so user can distinguish empty directory from
+	 * an error.
+	 */
+	errno = 0;
+
+	/* Fatal errors stop here. */
+	if (ISSET(FTS_STOP))
+		return (NULL);
+
+	/* Return logical hierarchy of user's arguments. */
+	if (p->fts_info == FTS_INIT)
+		return (p->fts_link);
+
+	/*
+	 * If not a directory being visited in pre-order, stop here.  Could
+	 * allow FTS_DNR, assuming the user has fixed the problem, but the
+	 * same effect is available with FTS_AGAIN.
+	 */
+	if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
+		return (NULL);
+
+	/* Free up any previous child list. */
+	if (sp->fts_child != NULL)
+		fts_lfree(sp->fts_child);
+
+	if (instr == FTS_NAMEONLY) {
+		SET(FTS_NAMEONLY);
+		instr = BNAMES;
+	} else
+		instr = BCHILD;
+
+	/*
+	 * If using chdir on a relative path and called BEFORE fts_read does
+	 * its chdir to the root of a traversal, we can lose -- we need to
+	 * chdir into the subdirectory, and we don't know where the current
+	 * directory is, so we can't get back so that the upcoming chdir by
+	 * fts_read will work.
+	 */
+	if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
+	    ISSET(FTS_NOCHDIR))
+		return (sp->fts_child = fts_build(sp, instr));
+
+	if ((fd = _open(".", O_RDONLY, 0)) < 0)
+		return (NULL);
+	sp->fts_child = fts_build(sp, instr);
+	if (fchdir(fd))
+		return (NULL);
+	(void)_close(fd);
+	return (sp->fts_child);
+}
+
+#ifndef fts_get_clientptr
+#error "fts_get_clientptr not defined"
+#endif
+
+void *
+(fts_get_clientptr)(FTS *sp)
+{
+
+	return (fts_get_clientptr(sp));
+}
+
+#ifndef fts_get_stream
+#error "fts_get_stream not defined"
+#endif
+
+FTS *
+(fts_get_stream)(FTSENT *p)
+{
+	return (fts_get_stream(p));
+}
+
+void
+fts_set_clientptr(FTS *sp, void *clientptr)
+{
+
+	sp->fts_clientptr = clientptr;
+}
+
+/*
+ * This is the tricky part -- do not casually change *anything* in here.  The
+ * idea is to build the linked list of entries that are used by fts_children
+ * and fts_read.  There are lots of special cases.
+ *
+ * The real slowdown in walking the tree is the stat calls.  If FTS_NOSTAT is
+ * set and it's a physical walk (so that symbolic links can't be directories),
+ * we can do things quickly.  First, if it's a 4.4BSD file system, the type
+ * of the file is in the directory entry.  Otherwise, we assume that the number
+ * of subdirectories in a node is equal to the number of links to the parent.
+ * The former skips all stat calls.  The latter skips stat calls in any leaf
+ * directories and for any files after the subdirectories in the directory have
+ * been found, cutting the stat calls by about 2/3.
+ */
+static FTSENT *
+fts_build(sp, type)
+	FTS *sp;
+	int type;
+{
+	struct dirent *dp;
+	FTSENT *p, *head;
+	int nitems;
+	FTSENT *cur, *tail;
+	DIR *dirp;
+	void *oldaddr;
+	size_t dnamlen;
+	int cderrno, descend, len, level, maxlen, nlinks, oflag, saved_errno,
+	    nostat, doadjust;
+	char *cp;
+
+	/* Set current node pointer. */
+	cur = sp->fts_cur;
+
+	/*
+	 * Open the directory for reading.  If this fails, we're done.
+	 * If being called from fts_read, set the fts_info field.
+	 */
+#ifdef FTS_WHITEOUT
+	if (ISSET(FTS_WHITEOUT))
+		oflag = DTF_NODUP | DTF_REWIND;
+	else
+		oflag = DTF_HIDEW | DTF_NODUP | DTF_REWIND;
+#else
+#define __opendir2(path, flag) opendir(path)
+#endif
+	if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
+		if (type == BREAD) {
+			cur->fts_info = FTS_DNR;
+			cur->fts_errno = errno;
+		}
+		return (NULL);
+	}
+
+	/*
+	 * Nlinks is the number of possible entries of type directory in the
+	 * directory if we're cheating on stat calls, 0 if we're not doing
+	 * any stat calls at all, -1 if we're doing stats on everything.
+	 */
+	if (type == BNAMES) {
+		nlinks = 0;
+		/* Be quiet about nostat, GCC. */
+		nostat = 0;
+	} else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
+		if (fts_ufslinks(sp, cur))
+			nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
+		else
+			nlinks = -1;
+		nostat = 1;
+	} else {
+		nlinks = -1;
+		nostat = 0;
+	}
+
+#ifdef notdef
+	(void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink);
+	(void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
+	    ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
+#endif
+	/*
+	 * If we're going to need to stat anything or we want to descend
+	 * and stay in the directory, chdir.  If this fails we keep going,
+	 * but set a flag so we don't chdir after the post-order visit.
+	 * We won't be able to stat anything, but we can still return the
+	 * names themselves.  Note, that since fts_read won't be able to
+	 * chdir into the directory, it will have to return different path
+	 * names than before, i.e. "a/b" instead of "b".  Since the node
+	 * has already been visited in pre-order, have to wait until the
+	 * post-order visit to return the error.  There is a special case
+	 * here, if there was nothing to stat then it's not an error to
+	 * not be able to stat.  This is all fairly nasty.  If a program
+	 * needed sorted entries or stat information, they had better be
+	 * checking FTS_NS on the returned nodes.
+	 */
+	cderrno = 0;
+	if (nlinks || type == BREAD) {
+		if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
+			if (nlinks && type == BREAD)
+				cur->fts_errno = errno;
+			cur->fts_flags |= FTS_DONTCHDIR;
+			descend = 0;
+			cderrno = errno;
+		} else
+			descend = 1;
+	} else
+		descend = 0;
+
+	/*
+	 * Figure out the max file name length that can be stored in the
+	 * current path -- the inner loop allocates more path as necessary.
+	 * We really wouldn't have to do the maxlen calculations here, we
+	 * could do them in fts_read before returning the path, but it's a
+	 * lot easier here since the length is part of the dirent structure.
+	 *
+	 * If not changing directories set a pointer so that can just append
+	 * each new name into the path.
+	 */
+	len = NAPPEND(cur);
+	if (ISSET(FTS_NOCHDIR)) {
+		cp = sp->fts_path + len;
+		*cp++ = '/';
+	} else {
+		/* GCC, you're too verbose. */
+		cp = NULL;
+	}
+	len++;
+	maxlen = sp->fts_pathlen - len;
+
+	level = cur->fts_level + 1;
+
+	/* Read the directory, attaching each entry to the `link' pointer. */
+	doadjust = 0;
+	for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) {
+		dnamlen = strlen(dp->d_name);
+		if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
+			continue;
+
+		if ((p = fts_alloc(sp, dp->d_name, (int)dnamlen)) == NULL)
+			goto mem1;
+		if (dnamlen >= maxlen) {	/* include space for NUL */
+			oldaddr = sp->fts_path;
+			if (fts_palloc(sp, dnamlen + len + 1)) {
+				/*
+				 * No more memory for path or structures.  Save
+				 * errno, free up the current structure and the
+				 * structures already allocated.
+				 */
+mem1:				saved_errno = errno;
+				if (p)
+					free(p);
+				fts_lfree(head);
+				(void)closedir(dirp);
+				cur->fts_info = FTS_ERR;
+				SET(FTS_STOP);
+				errno = saved_errno;
+				return (NULL);
+			}
+			/* Did realloc() change the pointer? */
+			if (oldaddr != sp->fts_path) {
+				doadjust = 1;
+				if (ISSET(FTS_NOCHDIR))
+					cp = sp->fts_path + len;
+			}
+			maxlen = sp->fts_pathlen - len;
+		}
+
+		if (len + dnamlen >= USHRT_MAX) {
+			/*
+			 * In an FTSENT, fts_pathlen is a u_short so it is
+			 * possible to wraparound here.  If we do, free up
+			 * the current structure and the structures already
+			 * allocated, then error out with ENAMETOOLONG.
+			 */
+			free(p);
+			fts_lfree(head);
+			(void)closedir(dirp);
+			cur->fts_info = FTS_ERR;
+			SET(FTS_STOP);
+			errno = ENAMETOOLONG;
+			return (NULL);
+		}
+		p->fts_level = level;
+		p->fts_parent = sp->fts_cur;
+		p->fts_pathlen = len + dnamlen;
+
+#ifdef FTS_WHITEOUT
+		if (dp->d_type == DT_WHT)
+			p->fts_flags |= FTS_ISW;
+#endif
+
+		if (cderrno) {
+			if (nlinks) {
+				p->fts_info = FTS_NS;
+				p->fts_errno = cderrno;
+			} else
+				p->fts_info = FTS_NSOK;
+			p->fts_accpath = cur->fts_accpath;
+		} else if (nlinks == 0
+#ifdef DT_DIR
+		    || (nostat &&
+		    dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
+#endif
+		    ) {
+			p->fts_accpath =
+			    ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
+			p->fts_info = FTS_NSOK;
+		} else {
+			/* Build a file name for fts_stat to stat. */
+			if (ISSET(FTS_NOCHDIR)) {
+				p->fts_accpath = p->fts_path;
+				memmove(cp, p->fts_name, p->fts_namelen + 1);
+			} else
+				p->fts_accpath = p->fts_name;
+			/* Stat it. */
+			p->fts_info = fts_stat(sp, p, 0);
+
+			/* Decrement link count if applicable. */
+			if (nlinks > 0 && (p->fts_info == FTS_D ||
+			    p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
+				--nlinks;
+		}
+
+		/* We walk in directory order so "ls -f" doesn't get upset. */
+		p->fts_link = NULL;
+		if (head == NULL)
+			head = tail = p;
+		else {
+			tail->fts_link = p;
+			tail = p;
+		}
+		++nitems;
+	}
+	if (dirp)
+		(void)closedir(dirp);
+
+	/*
+	 * If realloc() changed the address of the path, adjust the
+	 * addresses for the rest of the tree and the dir list.
+	 */
+	if (doadjust)
+		fts_padjust(sp, head);
+
+	/*
+	 * If not changing directories, reset the path back to original
+	 * state.
+	 */
+	if (ISSET(FTS_NOCHDIR)) {
+		if (len == sp->fts_pathlen || nitems == 0)
+			--cp;
+		*cp = '\0';
+	}
+
+	/*
+	 * If descended after called from fts_children or after called from
+	 * fts_read and nothing found, get back.  At the root level we use
+	 * the saved fd; if one of fts_open()'s arguments is a relative path
+	 * to an empty directory, we wind up here with no other way back.  If
+	 * can't get back, we're done.
+	 */
+	if (descend && (type == BCHILD || !nitems) &&
+	    (cur->fts_level == FTS_ROOTLEVEL ?
+	    FCHDIR(sp, sp->fts_rfd) :
+	    fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
+		cur->fts_info = FTS_ERR;
+		SET(FTS_STOP);
+		return (NULL);
+	}
+
+	/* If didn't find anything, return NULL. */
+	if (!nitems) {
+		if (type == BREAD)
+			cur->fts_info = FTS_DP;
+		return (NULL);
+	}
+
+	/* Sort the entries. */
+	if (sp->fts_compar && nitems > 1)
+		head = fts_sort(sp, head, nitems);
+	return (head);
+}
+
+static u_short
+fts_stat(sp, p, follow)
+	FTS *sp;
+	FTSENT *p;
+	int follow;
+{
+	FTSENT *t;
+	dev_t dev;
+	ino_t ino;
+	struct stat *sbp, sb;
+	int saved_errno;
+
+	/* If user needs stat info, stat buffer already allocated. */
+	sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
+
+#ifdef FTS_WHITEOUT
+	/* Check for whiteout. */
+	if (p->fts_flags & FTS_ISW) {
+		if (sbp != &sb) {
+			memset(sbp, '\0', sizeof(*sbp));
+			sbp->st_mode = S_IFWHT;
+		}
+		return (FTS_W);
+	}
+#endif
+
+	/*
+	 * If doing a logical walk, or application requested FTS_FOLLOW, do
+	 * a stat(2).  If that fails, check for a non-existent symlink.  If
+	 * fail, set the errno from the stat call.
+	 */
+	if (ISSET(FTS_LOGICAL) || follow) {
+		if (stat(p->fts_accpath, sbp)) {
+			saved_errno = errno;
+			if (!lstat(p->fts_accpath, sbp)) {
+				errno = 0;
+				return (FTS_SLNONE);
+			}
+			p->fts_errno = saved_errno;
+			goto err;
+		}
+	} else if (lstat(p->fts_accpath, sbp)) {
+		p->fts_errno = errno;
+err:		memset(sbp, 0, sizeof(struct stat));
+		return (FTS_NS);
+	}
+
+	if (S_ISDIR(sbp->st_mode)) {
+		/*
+		 * Set the device/inode.  Used to find cycles and check for
+		 * crossing mount points.  Also remember the link count, used
+		 * in fts_build to limit the number of stat calls.  It is
+		 * understood that these fields are only referenced if fts_info
+		 * is set to FTS_D.
+		 */
+		dev = p->fts_dev = sbp->st_dev;
+		ino = p->fts_ino = sbp->st_ino;
+		p->fts_nlink = sbp->st_nlink;
+
+		if (ISDOT(p->fts_name))
+			return (FTS_DOT);
+
+		/*
+		 * Cycle detection is done by brute force when the directory
+		 * is first encountered.  If the tree gets deep enough or the
+		 * number of symbolic links to directories is high enough,
+		 * something faster might be worthwhile.
+		 */
+		for (t = p->fts_parent;
+		    t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
+			if (ino == t->fts_ino && dev == t->fts_dev) {
+				p->fts_cycle = t;
+				return (FTS_DC);
+			}
+		return (FTS_D);
+	}
+	if (S_ISLNK(sbp->st_mode))
+		return (FTS_SL);
+	if (S_ISREG(sbp->st_mode))
+		return (FTS_F);
+	return (FTS_DEFAULT);
+}
+
+/*
+ * The comparison function takes pointers to pointers to FTSENT structures.
+ * Qsort wants a comparison function that takes pointers to void.
+ * (Both with appropriate levels of const-poisoning, of course!)
+ * Use a trampoline function to deal with the difference.
+ */
+static int
+fts_compar(const void *a, const void *b)
+{
+	FTS *parent;
+
+	parent = (*(const FTSENT * const *)a)->fts_fts;
+	return (*parent->fts_compar)(a, b);
+}
+
+static FTSENT *
+fts_sort(sp, head, nitems)
+	FTS *sp;
+	FTSENT *head;
+	int nitems;
+{
+	FTSENT **ap, *p;
+
+	/*
+	 * Construct an array of pointers to the structures and call qsort(3).
+	 * Reassemble the array in the order returned by qsort.  If unable to
+	 * sort for memory reasons, return the directory entries in their
+	 * current order.  Allocate enough space for the current needs plus
+	 * 40 so don't realloc one entry at a time.
+	 */
+	if (nitems > sp->fts_nitems) {
+		sp->fts_nitems = nitems + 40;
+		if ((sp->fts_array = reallocf(sp->fts_array,
+		    sp->fts_nitems * sizeof(FTSENT *))) == NULL) {
+			sp->fts_nitems = 0;
+			return (head);
+		}
+	}
+	for (ap = sp->fts_array, p = head; p; p = p->fts_link)
+		*ap++ = p;
+	qsort(sp->fts_array, nitems, sizeof(FTSENT *), fts_compar);
+	for (head = *(ap = sp->fts_array); --nitems; ++ap)
+		ap[0]->fts_link = ap[1];
+	ap[0]->fts_link = NULL;
+	return (head);
+}
+
+static FTSENT *
+fts_alloc(sp, name, namelen)
+	FTS *sp;
+	char *name;
+	int namelen;
+{
+	FTSENT *p;
+	size_t len;
+
+	struct ftsent_withstat {
+		FTSENT	ent;
+		struct	stat statbuf;
+	};
+
+	/*
+	 * The file name is a variable length array and no stat structure is
+	 * necessary if the user has set the nostat bit.  Allocate the FTSENT
+	 * structure, the file name and the stat structure in one chunk, but
+	 * be careful that the stat structure is reasonably aligned.
+	 */
+	if (ISSET(FTS_NOSTAT))
+		len = sizeof(FTSENT) + namelen + 1;
+	else
+		len = sizeof(struct ftsent_withstat) + namelen + 1;
+
+	if ((p = malloc(len)) == NULL)
+		return (NULL);
+
+	if (ISSET(FTS_NOSTAT)) {
+		p->fts_name = (char *)(p + 1);
+		p->fts_statp = NULL;
+	} else {
+		p->fts_name = (char *)((struct ftsent_withstat *)p + 1);
+		p->fts_statp = &((struct ftsent_withstat *)p)->statbuf;
+	}
+
+	/* Copy the name and guarantee NUL termination. */
+	memcpy(p->fts_name, name, namelen);
+	p->fts_name[namelen] = '\0';
+	p->fts_namelen = namelen;
+	p->fts_path = sp->fts_path;
+	p->fts_errno = 0;
+	p->fts_flags = 0;
+	p->fts_instr = FTS_NOINSTR;
+	p->fts_number = 0;
+	p->fts_pointer = NULL;
+	p->fts_fts = sp;
+	return (p);
+}
+
+static void
+fts_lfree(head)
+	FTSENT *head;
+{
+	FTSENT *p;
+
+	/* Free a linked list of structures. */
+	while ((p = head)) {
+		head = head->fts_link;
+		free(p);
+	}
+}
+
+/*
+ * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
+ * Most systems will allow creation of paths much longer than PATH_MAX, even
+ * though the kernel won't resolve them.  Add the size (not just what's needed)
+ * plus 256 bytes so don't realloc the path 2 bytes at a time.
+ */
+static int
+fts_palloc(sp, more)
+	FTS *sp;
+	size_t more;
+{
+
+	sp->fts_pathlen += more + 256;
+	/*
+	 * Check for possible wraparound.  In an FTS, fts_pathlen is
+	 * a signed int but in an FTSENT it is an unsigned short.
+	 * We limit fts_pathlen to USHRT_MAX to be safe in both cases.
+	 */
+	if (sp->fts_pathlen < 0 || sp->fts_pathlen >= USHRT_MAX) {
+		if (sp->fts_path)
+			free(sp->fts_path);
+		sp->fts_path = NULL;
+		errno = ENAMETOOLONG;
+		return (1);
+	}
+	sp->fts_path = reallocf(sp->fts_path, sp->fts_pathlen);
+	return (sp->fts_path == NULL);
+}
+
+/*
+ * When the path is realloc'd, have to fix all of the pointers in structures
+ * already returned.
+ */
+static void
+fts_padjust(sp, head)
+	FTS *sp;
+	FTSENT *head;
+{
+	FTSENT *p;
+	char *addr = sp->fts_path;
+
+#define	ADJUST(p) do {							\
+	if ((p)->fts_accpath != (p)->fts_name) {			\
+		(p)->fts_accpath =					\
+		    (char *)addr + ((p)->fts_accpath - (p)->fts_path);	\
+	}								\
+	(p)->fts_path = addr;						\
+} while (0)
+	/* Adjust the current set of children. */
+	for (p = sp->fts_child; p; p = p->fts_link)
+		ADJUST(p);
+
+	/* Adjust the rest of the tree, including the current level. */
+	for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
+		ADJUST(p);
+		p = p->fts_link ? p->fts_link : p->fts_parent;
+	}
+}
+
+static size_t
+fts_maxarglen(argv)
+	char * const *argv;
+{
+	size_t len, max;
+
+	for (max = 0; *argv; ++argv)
+		if ((len = strlen(*argv)) > max)
+			max = len;
+	return (max + 1);
+}
+
+/*
+ * Change to dir specified by fd or p->fts_accpath without getting
+ * tricked by someone changing the world out from underneath us.
+ * Assumes p->fts_dev and p->fts_ino are filled in.
+ */
+static int
+fts_safe_changedir(sp, p, fd, path)
+	FTS *sp;
+	FTSENT *p;
+	int fd;
+	char *path;
+{
+	int ret, oerrno, newfd;
+	struct stat sb;
+
+	newfd = fd;
+	if (ISSET(FTS_NOCHDIR))
+		return (0);
+	if (fd < 0 && (newfd = _open(path, O_RDONLY, 0)) < 0)
+		return (-1);
+	if (_fstat(newfd, &sb)) {
+		ret = -1;
+		goto bail;
+	}
+	if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) {
+		errno = ENOENT;		/* disinformation */
+		ret = -1;
+		goto bail;
+	}
+	ret = fchdir(newfd);
+bail:
+	oerrno = errno;
+	if (fd < 0)
+		(void)_close(newfd);
+	errno = oerrno;
+	return (ret);
+}
+
+/*
+ * Check if the filesystem for "ent" has UFS-style links.
+ */
+static int
+fts_ufslinks(FTS *sp, const FTSENT *ent)
+{
+	struct _fts_private *priv;
+	const char **cpp;
+
+	priv = (struct _fts_private *)sp;
+	priv->ftsp_linksreliable = 0;
+	return 0;
+}
Index: /trunk/minix/lib/other/getgrent.c
===================================================================
--- /trunk/minix/lib/other/getgrent.c	(revision 9)
+++ /trunk/minix/lib/other/getgrent.c	(revision 9)
@@ -0,0 +1,150 @@
+/*	getgrent(), getgrgid(), getgrnam() - group file routines
+ *
+ *							Author: Kees J. Bot
+ *								31 Jan 1994
+ */
+#define nil 0
+#define open _open
+#define fcntl _fcntl
+#define read _read
+#define close _close
+#include <sys/types.h>
+#include <grp.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+
+static char GROUP[]= "/etc/group";	/* The group file. */
+static const char *grfile;		/* Current group file. */
+
+static char buf[1024];			/* Read buffer. */
+static char grline[512];		/* One line from the group file. */
+static struct group entry;		/* Entry to fill and return. */
+static char *members[64];		/* Group members with the entry. */
+static int grfd= -1;			/* Filedescriptor to the file. */
+static char *bufptr;			/* Place in buf. */
+static ssize_t buflen= 0;		/* Remaining characters in buf. */
+static char *lineptr;			/* Place in the line. */
+
+void endgrent(void)
+/* Close the group file. */
+{
+	if (grfd >= 0) {
+		(void) close(grfd);
+		grfd= -1;
+		buflen= 0;
+	}
+}
+
+int setgrent(void)
+/* Open the group file. */
+{
+	if (grfd >= 0) endgrent();
+
+	if (grfile == nil) grfile= GROUP;
+
+	if ((grfd= open(grfile, O_RDONLY)) < 0) return -1;
+	(void) fcntl(grfd, F_SETFD, fcntl(grfd, F_GETFD) | FD_CLOEXEC);
+	return 0;
+}
+
+void setgrfile(const char *file)
+/* Prepare for reading an alternate group file. */
+{
+	endgrent();
+	grfile= file;
+}
+
+static int getline(void)
+/* Get one line from the group file, return 0 if bad or EOF. */
+{
+	lineptr= grline;
+
+	do {
+		if (buflen == 0) {
+			if ((buflen= read(grfd, buf, sizeof(buf))) <= 0)
+				return 0;
+			bufptr= buf;
+		}
+
+		if (lineptr == arraylimit(grline)) return 0;
+		buflen--;
+	} while ((*lineptr++ = *bufptr++) != '\n');
+
+	lineptr= grline;
+	return 1;
+}
+
+static char *scan_punct(int punct)
+/* Scan for a field separator in a line, return the start of the field. */
+{
+	char *field= lineptr;
+	char *last;
+
+	for (;;) {
+		last= lineptr;
+		if (*lineptr == 0) return nil;
+		if (*lineptr == '\n') break;
+		if (*lineptr++ == punct) break;
+		if (lineptr[-1] == ':') return nil;	/* :::,,,:,,,? */
+	}
+	*last= 0;
+	return field;
+}
+
+struct group *getgrent(void)
+/* Read one entry from the group file. */
+{
+	char *p;
+	char **mem;
+
+	/* Open the file if not yet open. */
+	if (grfd < 0 && setgrent() < 0) return nil;
+
+	/* Until a good line is read. */
+	for (;;) {
+		if (!getline()) return nil;	/* EOF or corrupt. */
+
+		if ((entry.gr_name= scan_punct(':')) == nil) continue;
+		if ((entry.gr_passwd= scan_punct(':')) == nil) continue;
+		if ((p= scan_punct(':')) == nil) continue;
+		entry.gr_gid= strtol(p, nil, 0);
+
+		entry.gr_mem= mem= members;
+		if (*lineptr != '\n') {
+			do {
+				if ((*mem= scan_punct(',')) == nil) goto again;
+				if (mem < arraylimit(members) - 1) mem++;
+			} while (*lineptr != 0);
+		}
+		*mem= nil;
+		return &entry;
+	again:;
+	}
+}
+
+struct group *getgrgid(_mnx_Gid_t gid)
+/* Return the group file entry belonging to the user-id. */
+{
+	struct group *gr;
+
+	endgrent();
+	while ((gr= getgrent()) != nil && gr->gr_gid != gid) {}
+	endgrent();
+	return gr;
+}
+
+struct group *getgrnam(const char *name)
+/* Return the group file entry belonging to the user name. */
+{
+	struct group *gr;
+
+	endgrent();
+	while ((gr= getgrent()) != nil && strcmp(gr->gr_name, name) != 0) {}
+	endgrent();
+	return gr;
+}
Index: /trunk/minix/lib/other/getlogin.c
===================================================================
--- /trunk/minix/lib/other/getlogin.c	(revision 9)
+++ /trunk/minix/lib/other/getlogin.c	(revision 9)
@@ -0,0 +1,28 @@
+/*  getlogin(3)
+ *
+ *  Author: Terrence W. Holm          Aug. 1988
+ */
+
+#include <lib.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifndef  L_cuserid
+#define  L_cuserid   9
+#endif
+
+char *getlogin()
+{
+  PRIVATE char userid[L_cuserid];
+  struct passwd *pw_entry;
+
+  pw_entry = getpwuid(getuid());
+
+  if (pw_entry == (struct passwd *)NULL) return((char *)NULL);
+
+  strcpy(userid, pw_entry->pw_name);
+
+  return(userid);
+}
Index: /trunk/minix/lib/other/getpagesize.c
===================================================================
--- /trunk/minix/lib/other/getpagesize.c	(revision 9)
+++ /trunk/minix/lib/other/getpagesize.c	(revision 9)
@@ -0,0 +1,11 @@
+/*
+getpagesize.c
+*/
+
+#include <unistd.h>
+
+int getpagesize(void)
+{
+	/* We don't have paging. Pretend that we do. */
+	return 4096;
+}
Index: /trunk/minix/lib/other/getpass.c
===================================================================
--- /trunk/minix/lib/other/getpass.c	(revision 9)
+++ /trunk/minix/lib/other/getpass.c	(revision 9)
@@ -0,0 +1,75 @@
+/*	getpass() - read a password		Author: Kees J. Bot
+ *							Feb 16 1993
+ */
+#define open _open
+#define sigaction _sigaction
+#define sigemptyset _sigemptyset
+#define tcgetattr _tcgetattr
+#define tcsetattr _tcsetattr
+#define write _write
+#define read _read
+#define close _close
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <termios.h>
+#include <string.h>
+
+static int intr;
+
+static void catch(int sig)
+{
+	intr= 1;
+}
+
+char *getpass(const char *prompt)
+{
+	struct sigaction osa, sa;
+	struct termios cooked, raw;
+	static char password[32+1];
+	int fd, n= 0;
+
+	/* Try to open the controlling terminal. */
+	if ((fd= open("/dev/tty", O_RDONLY)) < 0) return NULL;
+
+	/* Trap interrupts unless ignored. */
+	intr= 0;
+	sigaction(SIGINT, NULL, &osa);
+	if (osa.sa_handler != SIG_IGN) {
+		sigemptyset(&sa.sa_mask);
+		sa.sa_flags= 0;
+		sa.sa_handler= catch;
+		sigaction(SIGINT, &sa, &osa);
+	}
+
+	/* Set the terminal to non-echo mode. */
+	tcgetattr(fd, &cooked);
+	raw= cooked;
+	raw.c_iflag|= ICRNL;
+	raw.c_lflag&= ~ECHO;
+	raw.c_lflag|= ECHONL;
+	raw.c_oflag|= OPOST | ONLCR;
+	tcsetattr(fd, TCSANOW, &raw);
+
+	/* Print the prompt.  (After setting non-echo!) */
+	write(2, prompt, strlen(prompt));
+
+	/* Read the password, 32 characters max. */
+	while (read(fd, password+n, 1) > 0) {
+		if (password[n] == '\n') break;
+		if (n < 32) n++;
+	}
+	password[n]= 0;
+
+	/* Terminal back to cooked mode. */
+	tcsetattr(fd, TCSANOW, &cooked);
+
+	close(fd);
+
+	/* Interrupt? */
+	sigaction(SIGINT, &osa, NULL);
+	if (intr) raise(SIGINT);
+
+	return password;
+}
Index: /trunk/minix/lib/other/getpwent.c
===================================================================
--- /trunk/minix/lib/other/getpwent.c	(revision 9)
+++ /trunk/minix/lib/other/getpwent.c	(revision 9)
@@ -0,0 +1,143 @@
+/*	getpwent(), getpwuid(), getpwnam() - password file routines
+ *
+ *							Author: Kees J. Bot
+ *								31 Jan 1994
+ */
+#define nil 0
+#define open _open
+#define fcntl _fcntl
+#define read _read
+#define close _close
+#include <sys/types.h>
+#include <pwd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+
+static char PASSWD[]= "/etc/passwd";	/* The password file. */
+static const char *pwfile;		/* Current password file. */
+
+static char buf[1024];			/* Read buffer. */
+static char pwline[256];		/* One line from the password file. */
+static struct passwd entry;		/* Entry to fill and return. */
+static int pwfd= -1;			/* Filedescriptor to the file. */
+static char *bufptr;			/* Place in buf. */
+static ssize_t buflen= 0;		/* Remaining characters in buf. */
+static char *lineptr;			/* Place in the line. */
+
+void endpwent(void)
+/* Close the password file. */
+{
+	if (pwfd >= 0) {
+		(void) close(pwfd);
+		pwfd= -1;
+		buflen= 0;
+	}
+}
+
+int setpwent(void)
+/* Open the password file. */
+{
+	if (pwfd >= 0) endpwent();
+
+	if (pwfile == nil) pwfile= PASSWD;
+
+	if ((pwfd= open(pwfile, O_RDONLY)) < 0) return -1;
+	(void) fcntl(pwfd, F_SETFD, fcntl(pwfd, F_GETFD) | FD_CLOEXEC);
+	return 0;
+}
+
+void setpwfile(const char *file)
+/* Prepare for reading an alternate password file. */
+{
+	endpwent();
+	pwfile= file;
+}
+
+static int getline(void)
+/* Get one line from the password file, return 0 if bad or EOF. */
+{
+	lineptr= pwline;
+
+	do {
+		if (buflen == 0) {
+			if ((buflen= read(pwfd, buf, sizeof(buf))) <= 0)
+				return 0;
+			bufptr= buf;
+		}
+
+		if (lineptr == arraylimit(pwline)) return 0;
+		buflen--;
+	} while ((*lineptr++ = *bufptr++) != '\n');
+
+	lineptr= pwline;
+	return 1;
+}
+
+static char *scan_colon(void)
+/* Scan for a field separator in a line, return the start of the field. */
+{
+	char *field= lineptr;
+	char *last;
+
+	for (;;) {
+		last= lineptr;
+		if (*lineptr == 0) return nil;
+		if (*lineptr == '\n') break;
+		if (*lineptr++ == ':') break;
+	}
+	*last= 0;
+	return field;
+}
+
+struct passwd *getpwent(void)
+/* Read one entry from the password file. */
+{
+	char *p;
+
+	/* Open the file if not yet open. */
+	if (pwfd < 0 && setpwent() < 0) return nil;
+
+	/* Until a good line is read. */
+	for (;;) {
+		if (!getline()) return nil;	/* EOF or corrupt. */
+
+		if ((entry.pw_name= scan_colon()) == nil) continue;
+		if ((entry.pw_passwd= scan_colon()) == nil) continue;
+		if ((p= scan_colon()) == nil) continue;
+		entry.pw_uid= strtol(p, nil, 0);
+		if ((p= scan_colon()) == nil) continue;
+		entry.pw_gid= strtol(p, nil, 0);
+		if ((entry.pw_gecos= scan_colon()) == nil) continue;
+		if ((entry.pw_dir= scan_colon()) == nil) continue;
+		if ((entry.pw_shell= scan_colon()) == nil) continue;
+
+		if (*lineptr == 0) return &entry;
+	}
+}
+
+struct passwd *getpwuid(_mnx_Uid_t uid)
+/* Return the password file entry belonging to the user-id. */
+{
+	struct passwd *pw;
+
+	endpwent();
+	while ((pw= getpwent()) != nil && pw->pw_uid != uid) {}
+	endpwent();
+	return pw;
+}
+
+struct passwd *getpwnam(const char *name)
+/* Return the password file entry belonging to the user name. */
+{
+	struct passwd *pw;
+
+	endpwent();
+	while ((pw= getpwent()) != nil && strcmp(pw->pw_name, name) != 0) {}
+	endpwent();
+	return pw;
+}
Index: /trunk/minix/lib/other/getttyent.c
===================================================================
--- /trunk/minix/lib/other/getttyent.c	(revision 9)
+++ /trunk/minix/lib/other/getttyent.c	(revision 9)
@@ -0,0 +1,153 @@
+/*	getttyent(3) - get a ttytab entry		Author: Kees J. Bot
+ *								28 Oct 1995
+ */
+#define nil 0
+#define open _open
+#define close _close
+#define fcntl _fcntl
+#define read _read
+#include <string.h>
+#include <sys/types.h>
+#include <ttyent.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
+#define arraylimit(a)	((a) + arraysize(a))
+
+static char TTYTAB[]= "/etc/ttytab";	/* The table of terminal devices. */
+
+static char buf[512];			/* Read buffer. */
+static char ttline[256];		/* One line from the ttytab file. */
+static char *ttargv[32];		/* Compound arguments. */
+static struct ttyent entry;		/* Entry to fill and return. */
+static int ttfd= -1;			/* Filedescriptor to the file. */
+static char *bufptr;			/* Place in buf. */
+static ssize_t buflen= 0;		/* Remaining characters in buf. */
+static char *lineptr;			/* Place in the line. */
+static char **argvptr;			/* Place in word lists. */
+
+void endttyent(void)
+/* Close the ttytab file. */
+{
+	if (ttfd >= 0) {
+		(void) close(ttfd);
+		ttfd= -1;
+		buflen= 0;
+	}
+}
+
+int setttyent(void)
+/* Open the ttytab file. */
+{
+	if (ttfd >= 0) endttyent();
+
+	if ((ttfd= open(TTYTAB, O_RDONLY)) < 0) return -1;
+	(void) fcntl(ttfd, F_SETFD, fcntl(ttfd, F_GETFD) | FD_CLOEXEC);
+	return 0;
+}
+
+static int getline(void)
+/* Get one line from the ttytab file, return 0 if bad or EOF. */
+{
+	lineptr= ttline;
+	argvptr= ttargv;
+
+	do {
+		if (buflen == 0) {
+			if ((buflen= read(ttfd, buf, sizeof(buf))) <= 0)
+				return 0;
+			bufptr= buf;
+		}
+
+		if (lineptr == arraylimit(ttline)) return 0;
+		buflen--;
+	} while ((*lineptr++ = *bufptr++) != '\n');
+
+	lineptr= ttline;
+	return 1;
+}
+
+static int white(int c)
+/* Whitespace? */
+{
+	return c == ' ' || c == '\t';
+}
+
+static char *scan_white(int quoted)
+/* Scan for a field separator in a line, return the start of the field.
+ * "quoted" is set if we have to watch out for double quotes.
+ */
+{
+	char *field, *last;
+
+	while (white(*lineptr)) lineptr++;
+	if (!quoted && *lineptr == '#') return nil;
+
+	field= lineptr;
+	for (;;) {
+		last= lineptr;
+		if (*lineptr == 0) return nil;
+		if (*lineptr == '\n') break;
+		if (quoted && *lineptr == '"') return field;
+		if (white(*lineptr++)) break;
+	}
+	*last= 0;
+	return *field == 0 ? nil : field;
+}
+
+static char **scan_quoted(void)
+/* Read a field that may be a quoted list of words. */
+{
+	char *p, **field= argvptr;
+
+	while (white(*lineptr)) lineptr++;
+
+	if (*lineptr == '"') {
+		/* Quoted list of words. */
+		lineptr++;
+		while ((p= scan_white(1)) != nil && *p != '"') {
+			if (argvptr == arraylimit(ttargv)) return nil;
+			*argvptr++= p;
+		}
+		if (*lineptr == '"') *lineptr++= 0;
+	} else {
+		/* Just one word. */
+		if ((p= scan_white(0)) == nil) return nil;
+		if (argvptr == arraylimit(ttargv)) return nil;
+		*argvptr++= p;
+	}
+	if (argvptr == arraylimit(ttargv)) return nil;
+	*argvptr++= nil;
+	return field;
+}
+
+struct ttyent *getttyent(void)
+/* Read one entry from the ttytab file. */
+{
+	/* Open the file if not yet open. */
+	if (ttfd < 0 && setttyent() < 0) return nil;
+
+	/* Look for a line with something on it. */
+	for (;;) {
+		if (!getline()) return nil;	/* EOF or corrupt. */
+
+		if ((entry.ty_name= scan_white(0)) == nil) continue;
+		entry.ty_type= scan_white(0);
+		entry.ty_getty= scan_quoted();
+		entry.ty_init= scan_quoted();
+
+		return &entry;
+	}
+}
+
+struct ttyent *getttynam(const char *name)
+/* Return the ttytab file entry for a given tty. */
+{
+	struct ttyent *tty;
+
+	endttyent();
+	while ((tty= getttyent()) != nil && strcmp(tty->ty_name, name) != 0) {}
+	endttyent();
+	return tty;
+}
Index: /trunk/minix/lib/other/getw.c
===================================================================
--- /trunk/minix/lib/other/getw.c	(revision 9)
+++ /trunk/minix/lib/other/getw.c	(revision 9)
@@ -0,0 +1,22 @@
+/*
+ * getw - read a word from a stream
+ */
+/* $Header: /cvsup/minix/src/lib/other/getw.c,v 1.1.1.1 2005/04/21 14:56:27 beng Exp $ */
+
+#include	<stdio.h>
+
+_PROTOTYPE(int getw, (FILE *stream ));
+
+int getw(stream)
+register FILE *stream;
+{
+	register int cnt = sizeof(int);
+	int w;
+	register char *p = (char *) &w;
+
+	while (cnt--) {
+		*p++ = getc(stream);
+	}
+	if (feof(stream) || ferror(stream)) return EOF;
+	return w;
+}
Index: /trunk/minix/lib/other/hypot.c
===================================================================
--- /trunk/minix/lib/other/hypot.c	(revision 9)
+++ /trunk/minix/lib/other/hypot.c	(revision 9)
@@ -0,0 +1,43 @@
+/*
+ * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ *
+ * Author: Ceriel J.H. Jacobs
+ */
+
+#include <math.h>
+
+struct complex {
+	double r,i;
+};
+
+_PROTOTYPE(double hypot, (double x, double y ));
+_PROTOTYPE(double cabs, (struct complex p_compl ));
+
+/* $Header: /cvsup/minix/src/lib/other/hypot.c,v 1.1.1.1 2005/04/21 14:56:27 beng Exp $ */
+
+double
+hypot(x, y)
+double x, y;
+{
+	/*	Computes sqrt(x*x+y*y), avoiding overflow */
+
+	if (x < 0) x = -x;
+	if (y < 0) y = -y;
+	if (x > y) {
+		double t = y;
+		y = x;
+		x = t;
+	}
+	/* sqrt(x*x+y*y) = sqrt(y*y*(x*x/(y*y)+1.0)) = y*sqrt(x*x/(y*y)+1.0) */
+	if (y == 0.0) return 0.0;
+	x /= y;
+	return y*sqrt(x*x+1.0);
+}
+
+double
+cabs(p_compl)
+struct complex p_compl;
+{
+	return hypot(p_compl.r, p_compl.i);
+}
Index: /trunk/minix/lib/other/index.c
===================================================================
--- /trunk/minix/lib/other/index.c	(revision 9)
+++ /trunk/minix/lib/other/index.c	(revision 9)
@@ -0,0 +1,11 @@
+#include <lib.h>
+/* index - find first occurrence of a character in a string */
+
+#include <string.h>
+
+char *index(s, charwanted)	/* found char, or NULL if none */
+_CONST char *s;
+char charwanted;
+{
+  return(strchr(s, charwanted));
+}
Index: /trunk/minix/lib/other/itoa.c
===================================================================
--- /trunk/minix/lib/other/itoa.c	(revision 9)
+++ /trunk/minix/lib/other/itoa.c	(revision 9)
@@ -0,0 +1,36 @@
+#include <lib.h>
+/* Integer to ASCII for signed decimal integers. */
+
+PRIVATE int next;
+PRIVATE char qbuf[8];
+
+_PROTOTYPE( char *itoa, (int n));
+
+char *itoa(n)
+int n;
+{
+  register int r, k;
+  int flag = 0;
+
+  next = 0;
+  if (n < 0) {
+	qbuf[next++] = '-';
+	n = -n;
+  }
+  if (n == 0) {
+	qbuf[next++] = '0';
+  } else {
+	k = 10000;
+	while (k > 0) {
+		r = n / k;
+		if (flag || r > 0) {
+			qbuf[next++] = '0' + r;
+			flag = 1;
+		}
+		n -= r * k;
+		k = k / 10;
+	}
+  }
+  qbuf[next] = 0;
+  return(qbuf);
+}
Index: /trunk/minix/lib/other/loadname.c
===================================================================
--- /trunk/minix/lib/other/loadname.c	(revision 9)
+++ /trunk/minix/lib/other/loadname.c	(revision 9)
@@ -0,0 +1,19 @@
+#include <lib.h>
+#include <string.h>
+
+PUBLIC void _loadname(name, msgptr)
+_CONST char *name;
+message *msgptr;
+{
+/* This function is used to load a string into a type m3 message. If the
+ * string fits in the message, it is copied there.  If not, a pointer to
+ * it is passed.
+ */
+
+  register size_t k;
+
+  k = strlen(name) + 1;
+  msgptr->m3_i1 = k;
+  msgptr->m3_p1 = (char *) name;
+  if (k <= sizeof msgptr->m3_ca1) strcpy(msgptr->m3_ca1, name);
+}
Index: /trunk/minix/lib/other/lock.c
===================================================================
--- /trunk/minix/lib/other/lock.c	(revision 9)
+++ /trunk/minix/lib/other/lock.c	(revision 9)
@@ -0,0 +1,62 @@
+#include <lib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stdio.h>
+#if _ANSI
+#include <stdlib.h>
+#endif
+
+typedef enum {
+  False, True
+} BOOLEAN;
+
+#define LOCKDIR "/tmp/"		/* or /usr/tmp/ as the case may be */
+#define MAXTRIES 3
+#define NAPTIME (unsigned int)5
+
+PRIVATE _PROTOTYPE( char *lockpath, (char *name));
+_PROTOTYPE( void syserr, (char *errstring));
+_PROTOTYPE( BOOLEAN lock, (char *name));
+_PROTOTYPE( void unlock, (char *name));
+
+void
+syserr(errstring)
+char *errstring;
+{
+	fprintf(stderr,"couldn't %s\n", errstring);
+	exit(1);
+}
+
+BOOLEAN lock(name)		/* acquire lock */
+char *name;
+{
+  char *path;
+  int fd, tries;
+
+  path = lockpath(name);
+  tries = 0;
+  while ((fd = creat(path, 0)) == -1 && errno == EACCES) {
+	if (++tries >= MAXTRIES) return(False);
+	sleep(NAPTIME);
+  }
+  if (fd == -1 || close(fd) == -1) syserr("lock");
+  return(True);
+}
+
+void unlock(name)		/* free lock */
+char *name;
+{
+  if (unlink(lockpath(name)) == -1) syserr("unlock");
+}
+
+PRIVATE char *lockpath(name)	/* generate lock file path */
+char *name;
+{
+  PRIVATE char path[20];
+
+  strcpy(path, LOCKDIR);
+  return(strcat(path, name));
+}
Index: /trunk/minix/lib/other/lrand.c
===================================================================
--- /trunk/minix/lib/other/lrand.c	(revision 9)
+++ /trunk/minix/lib/other/lrand.c	(revision 9)
@@ -0,0 +1,53 @@
+/*  lrand(3)
+ *
+ *  Author: Terrence W. Holm          Nov. 1988
+ *
+ *
+ *  A prime modulus multiplicative linear congruential
+ *  generator (PMMLCG), or "Lehmer generator".
+ *  Implementation directly derived from the article:
+ *
+ *	S. K. Park and K. W. Miller
+ *	Random Number Generators: Good Ones are Hard to Find
+ *	CACM vol 31, #10. Oct. 1988. pp 1192-1201.
+ *
+ *
+ *  Using the following multiplier and modulus, we obtain a
+ *  generator which:
+ *
+ *	1)  Has a full period: 1 to 2^31 - 2.
+ *	2)  Is testably "random" (see the article).
+ *	3)  Has a known implementation by E. L. Schrage.
+ */
+
+#include <lib.h>
+
+_PROTOTYPE( long seed, (long lseed));
+_PROTOTYPE( long lrand, (void));
+
+#define  A	  16807L	/* A "good" multiplier	  */
+#define  M   2147483647L	/* Modulus: 2^31 - 1	  */
+#define  Q       127773L	/* M / A		  */
+#define  R         2836L	/* M % A		  */
+
+PRIVATE long _lseed = 1L;
+
+long seed(lseed)
+long lseed;
+{
+  long previous_seed = _lseed;
+
+  _lseed = lseed;
+
+  return(previous_seed);
+}
+
+
+long lrand()
+{
+  _lseed = A * (_lseed % Q) - R * (_lseed / Q);
+
+  if (_lseed < 0) _lseed += M;
+
+  return(_lseed);
+}
Index: /trunk/minix/lib/other/lsearch.c
===================================================================
--- /trunk/minix/lib/other/lsearch.c	(revision 9)
+++ /trunk/minix/lib/other/lsearch.c	(revision 9)
@@ -0,0 +1,50 @@
+#include <lib.h>
+#include <string.h>
+/*  lsearch(3)  and  lfind(3)
+ *
+ *  Author: Terrence W. Holm          Sep. 1988
+ */
+
+#include <stddef.h>
+
+_PROTOTYPE( char *lsearch, (char *key, char *base,
+			    unsigned *count, unsigned width,
+			    int (*keycmp)(const void *, const void *)));
+_PROTOTYPE( char *lfind, (char *key, char *base,
+			    unsigned *count, unsigned width,
+			    int (*keycmp)(const void *, const void *)));
+
+char *lsearch(key, base, count, width, keycmp)
+char *key;
+char *base;
+unsigned *count;
+unsigned width;
+_PROTOTYPE( int (*keycmp), (const void *, const void *));
+{
+  char *entry;
+  char *last = base + *count * width;
+
+  for (entry = base; entry < last; entry += width)
+	if (keycmp(key, entry) == 0) return(entry);
+
+  bcopy(key, last, width);
+  *count += 1;
+  return(last);
+}
+
+
+char *lfind(key, base, count, width, keycmp)
+char *key;
+char *base;
+unsigned *count;
+unsigned width;
+_PROTOTYPE( int (*keycmp), (const void *, const void *));
+{
+  char *entry;
+  char *last = base + *count * width;
+
+  for (entry = base; entry < last; entry += width)
+	if (keycmp(key, entry) == 0) return(entry);
+
+  return((char *)NULL);
+}
Index: /trunk/minix/lib/other/memccpy.c
===================================================================
--- /trunk/minix/lib/other/memccpy.c	(revision 9)
+++ /trunk/minix/lib/other/memccpy.c	(revision 9)
@@ -0,0 +1,39 @@
+#include <lib.h>
+/* memccpy - copy bytes up to a certain char
+ *
+ * CHARBITS should be defined only if the compiler lacks "unsigned char".
+ * It should be a mask, e.g. 0377 for an 8-bit machine.
+ */
+
+#include <ansi.h>
+#include <stddef.h>
+
+_PROTOTYPE( void *memccpy, (void *dst, const void *src,
+			    int ucharstop, size_t size));
+#ifndef CHARBITS
+#	define	UNSCHAR(c)	((unsigned char)(c))
+#else
+#	define	UNSCHAR(c)	((c)&CHARBITS)
+#endif
+
+void *memccpy(dst, src, ucharstop, size)
+void * dst;
+_CONST void * src;
+int ucharstop;
+_SIZET size;
+{
+  register char *d;
+  register _CONST char *s;
+  register _SIZET n;
+  register int uc;
+
+  if (size <= 0) return( (void *) NULL);
+
+  s = (char *) src;
+  d = (char *) dst;
+  uc = UNSCHAR(ucharstop);
+  for (n = size; n > 0; n--)
+	if (UNSCHAR(*d++ = *s++) == (char) uc) return( (void *) d);
+
+  return( (void *) NULL);
+}
Index: /trunk/minix/lib/other/mstats.c
===================================================================
--- /trunk/minix/lib/other/mstats.c	(revision 9)
+++ /trunk/minix/lib/other/mstats.c	(revision 9)
@@ -0,0 +1,23 @@
+#include <minix/config.h>
+
+#if ENABLE_MESSAGE_STATS
+
+#include <lib.h>
+#include <unistd.h>
+
+PUBLIC int mstats(struct message_statentry *ms, int entries, int reset)
+{
+	message m;
+
+	m.m1_i1 = entries;
+	m.m1_i2 = reset;
+	m.m1_p1 = (void *) ms;
+
+	if(_syscall(MM, MSTATS, &m) < 0) {
+		return -1;
+	}
+
+	return m.m_type;
+}
+
+#endif
Index: /trunk/minix/lib/other/mtab.c
===================================================================
--- /trunk/minix/lib/other/mtab.c	(revision 9)
+++ /trunk/minix/lib/other/mtab.c	(revision 9)
@@ -0,0 +1,205 @@
+/* This package consists of 4 routines for handling the /etc/mtab file.
+ * The /etc/mtab file contains information about the root and mounted file
+ * systems as a series of lines, each one with exactly four fields separated 
+ * by one space as follows:
+ *
+ *	special mounted_on version rw_flag
+ *
+ * where 
+ *	special is the name of the block special file
+ *	mounted_on is the directory on which it is mounted
+ *	version is either 1 or 2 for MINIX V1 and V2 file systems
+ *	rw_flag is rw or ro for read/write or read only
+ *
+ * An example /etc/mtab:
+ *
+ *	/dev/ram / 2 rw
+ *	/dev/hd1 /usr 2 rw
+ *	/dev/fd0 /user 1 ro
+ *
+ *
+ * The four routines for handling /etc/mtab are as follows.  They use two
+ * (hidden) internal buffers, mtab_in for input and mtab_out for output.
+ *
+ *	load_mtab(&prog_name)		   - read /etc/mtab into mtab_in
+ *	get_mtab_entry(&s1, &s2, &s3, &s4) - arrays that are filled in
+ *	put_mtab_entry(&s1, &s2, &s3, &s4) - append a line to mtab_out
+ *	rewrite_mtab(&prog_name)	   - write mtab_out to /etc/mtab
+ *
+ * If load_mtab and rewrite_mtab work, they return 0.  If they fail, they
+ * print their own error messages on stderr and return -1.  When get_mtab_entry
+ * runs out of entries to return, it sets the first pointer to NULL and returns
+ * -1 instead of 0.  Also, rewrite_mtab returns -1 if it fails.
+ */
+ 
+#include <sys/types.h>
+#include <minix/minlib.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define BUF_SIZE   512		  /* size of the /etc/mtab buffer */
+
+char *etc_mtab = "/etc/mtab";	  /* name of the /etc/mtab file */
+static char mtab_in[BUF_SIZE+1];  /* holds /etc/mtab when it is read in */
+static char mtab_out[BUF_SIZE+1]; /* buf to build /etc/mtab for output later */
+static char *iptr = mtab_in;	  /* pointer to next line to feed out. */
+static char *optr = mtab_out;	  /* pointer to place where next line goes */
+
+_PROTOTYPE(int load_mtab, (char *prog_name ));
+_PROTOTYPE(int rewrite_mtab, (char *prog_name ));
+_PROTOTYPE(int get_mtab_entry, (char *special, char *mounted_on, 
+					char *version, char *rw_flag));
+_PROTOTYPE(int put_mtab_entry, (char *special, char *mounted_on, 
+					char *version, char *rw_flag));
+_PROTOTYPE(void err, (char *prog_name, char *str ));
+
+
+int load_mtab(prog_name)
+char *prog_name;
+{
+/* Read in /etc/mtab and store it in /etc/mtab. */
+
+  int fd, n;
+  char *ptr;
+
+  /* Open the file. */
+  fd = open(etc_mtab, O_RDONLY);
+  if (fd < 0) {
+	err(prog_name, ": cannot open ");
+	return(-1);
+  }
+
+  /* File opened.  Read it in. */
+  n = read(fd, mtab_in, BUF_SIZE);
+  if (n <= 0) {
+	/* Read failed. */
+	err(prog_name, ": cannot read ");
+	return(-1);
+  }
+  if (n == BUF_SIZE) {
+	/* Some nut has mounted 50 file systems or something like that. */
+	std_err(prog_name);
+	std_err(": file too large: ");
+	std_err(etc_mtab);
+	return(-1);
+  }
+
+  close(fd);
+
+  /* Replace all the whitespace by '\0'. */
+  ptr = mtab_in;
+  while (*ptr != '\0') {
+	if (isspace(*ptr)) *ptr = '\0';
+	ptr++;
+  }
+  return(0);
+}
+
+
+int rewrite_mtab(prog_name)
+char *prog_name;
+{
+/* Write mtab_out to /etc/mtab. */
+
+  int fd, n;
+
+  /* Do a creat to truncate the file. */
+  fd = creat(etc_mtab, 0777);
+  if (fd < 0) {
+	err(prog_name, ": cannot overwrite ");
+	return(-1);
+  }
+
+  /* File created.  Write it. */
+  n = write(fd, mtab_out, (unsigned int)(optr - mtab_out));
+  if (n <= 0) {
+	/* Write failed. */
+	err(prog_name, " could not write ");
+	return(-1);
+  }
+
+  close(fd);
+  return(0);
+}
+
+
+int get_mtab_entry(special, mounted_on, version, rw_flag)
+char *special;
+char *mounted_on;
+char *version;
+char *rw_flag;
+{
+/* Return the next entry from mtab_in. */
+
+  if (iptr >= &mtab_in[BUF_SIZE]) {
+	special[0] = '\0';
+	return(-1);
+  }
+
+  strcpy(special, iptr);
+  while (isprint(*iptr)) iptr++;
+  while (*iptr == '\0'&& iptr < &mtab_in[BUF_SIZE]) iptr++;
+
+  strcpy(mounted_on, iptr);
+  while (isprint(*iptr)) iptr++;
+  while (*iptr == '\0'&& iptr < &mtab_in[BUF_SIZE]) iptr++;
+
+  strcpy(version, iptr);
+  while (isprint(*iptr)) iptr++;
+  while (*iptr == '\0'&& iptr < &mtab_in[BUF_SIZE]) iptr++;
+
+  strcpy(rw_flag, iptr);
+  while (isprint(*iptr)) iptr++;
+  while (*iptr == '\0'&& iptr < &mtab_in[BUF_SIZE]) iptr++;
+  return(0);
+}
+
+
+int put_mtab_entry(special, mounted_on, version, rw_flag)
+char *special;
+char *mounted_on;
+char *version;
+char *rw_flag;
+{
+/* Append an entry to the mtab_out buffer. */
+
+  int n1, n2, n3, n4;
+
+  n1 = strlen(special);
+  n2 = strlen(mounted_on);
+  n3 = strlen(version);
+  n4 = strlen(rw_flag);
+
+  if (optr + n1 + n2 + n3 + n4 + 5 >= &mtab_out[BUF_SIZE]) return(-1);
+  strcpy(optr, special);
+  optr += n1;
+  *optr++ = ' ';
+
+  strcpy(optr, mounted_on);
+  optr += n2;
+  *optr++ = ' ';
+
+  strcpy(optr, version);
+  optr += n3;
+  *optr++ = ' ';
+
+  strcpy(optr, rw_flag);
+  optr += n4;
+  *optr++ = '\n';
+  return(0);
+}
+
+
+void
+err(prog_name, str)
+char *prog_name, *str;
+{
+  std_err(prog_name); 
+  std_err(str);
+  std_err(etc_mtab);
+  perror(" ");
+}
Index: /trunk/minix/lib/other/namespace.h
===================================================================
--- /trunk/minix/lib/other/namespace.h	(revision 9)
+++ /trunk/minix/lib/other/namespace.h	(revision 9)
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2001 Daniel Eischen <deischen@FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libc/include/namespace.h,v 1.16 2003/05/01 19:03:13 nectar Exp $
+ */
+
+#ifndef _NAMESPACE_H_
+#define _NAMESPACE_H_
+
+/*
+ * Adjust names so that headers declare "hidden" names.
+ *
+ * README: When modifying this file don't forget to make the appropriate
+ *         changes in un-namespace.h!!!
+ */
+
+/*
+ * ISO C (C90) section.  Most names in libc aren't in ISO C, so they
+ * should be here.  Most aren't here...
+ */
+#define		err				_err
+#define		warn				_warn
+#define		nsdispatch			_nsdispatch
+
+/*
+ * Prototypes for syscalls/functions that need to be overridden
+ * in libc_r/libpthread.
+ */
+#define		accept				_accept
+#define		__acl_aclcheck_fd		___acl_aclcheck_fd
+#define		__acl_delete_fd			___acl_delete_fd
+#define		__acl_get_fd			___acl_get_fd
+#define		__acl_set_fd			___acl_set_fd
+#define		bind				_bind
+#define		__cap_get_fd			___cap_get_fd
+#define		__cap_set_fd			___cap_set_fd
+#define		close				_close
+#define		connect				_connect
+#define		dup				_dup
+#define		dup2				_dup2
+#define		execve				_execve
+#define		fcntl				_fcntl
+/*#define		flock				_flock */
+#define		flockfile			_flockfile
+#define		fpathconf			_fpathconf
+#define		fstat				_fstat
+#define		fstatfs				_fstatfs
+#define		fsync				_fsync
+#define		funlockfile			_funlockfile
+#define		getdirentries			_getdirentries
+#define		getlogin			_getlogin
+#define		getpeername			_getpeername
+#define		getprogname			_getprogname
+#define		getsockname			_getsockname
+#define		getsockopt			_getsockopt
+#define		ioctl				_ioctl
+/* #define		kevent				_kevent */
+#define		listen				_listen
+#define		nanosleep			_nanosleep
+#define		open				_open
+#define		poll				_poll
+#define		pthread_cond_broadcast		_pthread_cond_broadcast
+#define		pthread_cond_destroy		_pthread_cond_destroy
+#define		pthread_cond_init		_pthread_cond_init
+#define		pthread_cond_signal		_pthread_cond_signal
+#define		pthread_cond_timedwait		_pthread_cond_timedwait
+#define		pthread_cond_wait		_pthread_cond_wait
+#define		pthread_exit			_pthread_exit
+#define		pthread_getspecific		_pthread_getspecific
+#define		pthread_key_create		_pthread_key_create
+#define		pthread_key_delete		_pthread_key_delete
+#define		pthread_main_np			_pthread_main_np
+#define		pthread_mutex_destroy		_pthread_mutex_destroy
+#define		pthread_mutex_init		_pthread_mutex_init
+#define		pthread_mutex_lock		_pthread_mutex_lock
+#define		pthread_mutex_trylock		_pthread_mutex_trylock
+#define		pthread_mutex_unlock		_pthread_mutex_unlock
+#define		pthread_mutexattr_destroy	_pthread_mutexattr_destroy
+#define		pthread_mutexattr_init		_pthread_mutexattr_init
+#define		pthread_mutexattr_settype	_pthread_mutexattr_settype
+#define		pthread_once			_pthread_once
+#define		pthread_rwlock_destroy		_pthread_rwlock_destroy
+#define		pthread_rwlock_init		_pthread_rwlock_init
+#define		pthread_rwlock_rdlock		_pthread_rwlock_rdlock
+#define		pthread_rwlock_wrlock		_pthread_rwlock_wrlock
+#define		pthread_rwlock_tryrdlock	_pthread_rwlock_tryrdlock
+#define		pthread_rwlock_trywrlock	_pthread_rwlock_trywrlock
+#define		pthread_rwlock_unlock		_pthread_rwlock_unlock
+#define		pthread_self			_pthread_self
+#define		pthread_setspecific		_pthread_setspecific
+#define		pthread_sigmask			_pthread_sigmask
+#define		read				_read
+#define		readv				_readv
+#define		recvfrom			_recvfrom
+#define		recvmsg				_recvmsg
+#define		select				_select
+#define		sendmsg				_sendmsg
+#define		sendto				_sendto
+#define		setsockopt			_setsockopt
+/*#define		sigaction			_sigaction*/
+#define		sigprocmask			_sigprocmask
+#define		sigsuspend			_sigsuspend
+#define		socket				_socket
+#define		socketpair			_socketpair
+#define		wait4				_wait4
+#define		waitpid				_waitpid
+#define		write				_write
+#define		writev				_writev
+
+
+/*
+ * Other hidden syscalls/functions that libc_r needs to override
+ * but are not used internally by libc.
+ *
+ * XXX - When modifying libc to use one of the following, remove
+ * the prototype from below and place it in the list above.
+ */
+#if 0
+#define		creat				_creat
+#define		fchflags			_fchflags
+#define		fchmod				_fchmod
+#define		ftrylockfile			_ftrylockfile
+#define		msync				_msync
+#define		nfssvc				_nfssvc
+#define		pause				_pause
+#define		pthread_rwlockattr_init		_pthread_rwlockattr_init
+#define		pthread_rwlockattr_destroy	_pthread_rwlockattr_destroy
+#define		sched_yield			_sched_yield
+#define		sendfile			_sendfile
+#define		shutdown			_shutdown
+#define		sigaltstack			_sigaltstack
+#define		sigpending			_sigpending
+#define		sigreturn			_sigreturn
+#define		sigsetmask			_sigsetmask
+#define		sleep				_sleep
+#define		system				_system
+#define		tcdrain				_tcdrain
+#define		wait				_wait
+#endif
+
+#endif /* _NAMESPACE_H_ */
Index: /trunk/minix/lib/other/nlist.c
===================================================================
--- /trunk/minix/lib/other/nlist.c	(revision 9)
+++ /trunk/minix/lib/other/nlist.c	(revision 9)
@@ -0,0 +1,71 @@
+/*
+ * "nlist.c", Peter Valkenburg, january 1989.
+ */
+ 
+#include <lib.h>
+#include <string.h>
+#include <a.out.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define fail(fp)	(fclose(fp), -1)	/* ret. exp. when nlist fails */
+
+_PROTOTYPE( int nlist, (char *file, struct nlist nl[]));
+
+/*
+ * Nlist fills fields n_sclass and n_value of array nl with values found in
+ * non-stripped executable file.  Entries that are not found have their
+ * n_value/n_sclass fields set to 0.  Nl ends with a 0 or nul string n_name.
+ * The return value is -1 on failure, else the number of entries not found.
+ */
+int nlist(file, nl)
+char *file;
+struct nlist nl[];
+{
+	int nents, nsrch, nfound, i;
+	struct nlist nlent;
+	FILE *fp;
+	struct exec hd;
+
+	/* open executable with namelist */
+	if ((fp = fopen(file, "r")) == NULL)
+		return -1;
+		
+	/* get header and seek to start of namelist */	
+	if (fread((char *) &hd, sizeof(struct exec), 1, fp) != 1 ||
+	    BADMAG(hd) || fseek(fp, A_SYMPOS(hd), SEEK_SET) != 0)
+		return fail(fp);
+	
+	/* determine number of entries searched for & reset fields */
+	nsrch = 0;
+	while (nl[nsrch].n_name != NULL && *(nl[nsrch].n_name) != '\0') {
+		nl[nsrch].n_sclass = 0;
+		nl[nsrch].n_value = 0;
+		nl[nsrch].n_type = 0;		/* for compatability */
+		nsrch++;
+	}
+
+	/* loop through namelist & fill in user array */
+	nfound = 0;
+	for (nents = (hd.a_syms & 0xFFFF) / sizeof(struct nlist);
+	     nents > 0; nents--) {
+		if (nsrch == nfound)
+			break;			/* no need to look further */
+		if (fread((char *) &nlent, sizeof(struct nlist), 1, fp) != 1)
+			return fail(fp);	  
+		for (i = 0; i < nsrch; i++)
+			if (nl[i].n_sclass == 0 &&
+			    strncmp(nl[i].n_name, nlent.n_name,
+			    	    sizeof(nlent.n_name)) == 0) {
+				nl[i] = nlent;
+				nfound++;
+				break;
+			}
+	}
+
+	(void) fclose(fp);
+	
+	return nsrch - nfound;
+}
Index: /trunk/minix/lib/other/paramvalue.c
===================================================================
--- /trunk/minix/lib/other/paramvalue.c	(revision 9)
+++ /trunk/minix/lib/other/paramvalue.c	(revision 9)
@@ -0,0 +1,51 @@
+/*	paramvalue() - decode kernel parameter values	Author: Kees J. Bot
+ *								7 May 1994
+ * The kernel returns the results of parameter queries
+ * by the XXQUERYPARAM svrctl calls as an array of hex digits, like this:
+ * "75020000,080C0000".  These are the values of two four-byte variables.
+ * Paramvalue() decodes such a string.
+ */
+#define nil 0
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <minix/queryparam.h>
+
+size_t paramvalue(char **value, void *address, size_t size)
+/* Decode the string *value storing the result in the object at address with
+ * the given size.  *value is left at the next parameter, *address is padded
+ * with zeros if needed, and the actual size of the value is returned.
+ */
+{
+	unsigned char *addr= address;
+	char *v= *value;
+	int nibble;
+	size_t n;
+
+	n= 0;
+
+	while (*v != 0 && *v != ',') {
+		nibble= *v++ - '0';
+		if (nibble > 0x9) nibble= nibble + '0' - 'A' + 0xA;
+		if (nibble > 0xF) nibble= nibble + 'A' - 'a';
+		if (size > 0) {
+			if (n % 2 == 0) {
+				*addr= nibble << 4;
+			} else {
+				*addr++|= nibble;
+				size--;
+			}
+			n++;
+		}
+	}
+	while (size > 0) { *addr++= 0; size--; }
+	while (*v != 0 && *v++ != ',') {}
+	*value= v;
+	return n / 2;
+}
+
+
+/*
+ * $PchId: paramvalue.c,v 1.3 1996/02/22 09:15:56 philip Exp $
+ */
Index: /trunk/minix/lib/other/peekpoke.c
===================================================================
--- /trunk/minix/lib/other/peekpoke.c	(revision 9)
+++ /trunk/minix/lib/other/peekpoke.c	(revision 9)
@@ -0,0 +1,49 @@
+/* Peek and poke using /dev/mem.
+ *
+ * Callers now ought to check the return values.
+ *
+ * Calling peek() requires read permission on /dev/mem, and consumes
+ * a file descriptor.  Calling poke() requires write permission, and
+ * consumes another file descriptor.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+_PROTOTYPE( int peek, (unsigned segment, unsigned offset));
+_PROTOTYPE( int poke, (unsigned segment, unsigned offset, unsigned value));
+
+#define SEGSIZE 0x10
+
+int peek(segment, offset)
+unsigned segment;
+unsigned offset;
+{
+  unsigned char chvalue;
+  static int infd = -1;
+
+  if (infd < 0) infd = open("/dev/mem", O_RDONLY);
+  if (infd < 0 ||
+      lseek(infd, (unsigned long) segment * SEGSIZE + offset, SEEK_SET) < 0 ||
+      read(infd, (char *) &chvalue, (unsigned) 1) != 1)
+	return(-1);
+  return(chvalue);
+}
+
+int poke(segment, offset, value)
+unsigned segment;
+unsigned offset;
+unsigned value;
+{
+  unsigned char chvalue;
+  static int outfd = -1;
+
+  chvalue = value;
+  if (outfd < 0) outfd = open("/dev/mem", O_WRONLY);
+  if (outfd < 0 ||
+      lseek(outfd, (unsigned long) segment * SEGSIZE + offset, SEEK_SET) < 0 ||
+      write(outfd, (char *) &chvalue, (unsigned) 1) != 1)
+	return(-1);
+  return(chvalue);
+}
Index: /trunk/minix/lib/other/popen.c
===================================================================
--- /trunk/minix/lib/other/popen.c	(revision 9)
+++ /trunk/minix/lib/other/popen.c	(revision 9)
@@ -0,0 +1,122 @@
+/*
+ * popen - open a pipe
+ */
+/* $Header: /cvsup/minix/src/lib/other/popen.c,v 1.1.1.1 2005/04/21 14:56:27 beng Exp $ */
+
+#include	<sys/types.h>
+#include	<limits.h>
+#include	<errno.h>
+#include	<signal.h>
+#include	<stdio.h>
+
+#if	defined(__BSD4_2)
+union wait {
+	int	w_status;
+};
+typedef union wait wait_arg;
+#else
+typedef int wait_arg;
+#endif	/* __BSD4_2 */
+
+#include	"../stdio/loc_incl.h"
+
+#ifdef _ANSI
+int _close(int d);
+int _dup2(int oldd, int newd);		/* not present in System 5 */
+int _execl(const char *name, const char *_arg, ... );
+pid_t _fork(void);
+int _pipe(int fildes[2]);
+pid_t _wait(wait_arg *status);
+void _exit(int status);
+#endif
+
+static int pids[OPEN_MAX];
+
+FILE *
+popen(command, type)
+_CONST char *command;
+_CONST char *type;
+{
+	int piped[2];
+	int Xtype = *type == 'r' ? 0 : *type == 'w' ? 1 : 2;
+	int pid;
+
+	if (Xtype == 2 ||
+	    _pipe(piped) < 0 ||
+	    (pid = _fork()) < 0) return 0;
+	
+	if (pid == 0) {
+		/* child */
+		register int *p;
+
+		for (p = pids; p < &pids[OPEN_MAX]; p++) {
+			if (*p) _close((int)(p - pids));
+		}
+		_close(piped[Xtype]);
+		_dup2(piped[!Xtype], !Xtype);
+		_close(piped[!Xtype]);
+		_execl("/bin/sh", "sh", "-c", command, (char *) 0);
+		_exit(127);	/* like system() ??? */
+	}
+
+	pids[piped[Xtype]] = pid;
+	_close(piped[!Xtype]);
+	return fdopen(piped[Xtype], type);
+}
+
+#if	defined(__BSD4_2)
+#define	ret_val	status.w_status
+#else
+#define	ret_val	status
+#endif
+
+int
+pclose(stream)
+FILE *stream;
+{
+	int fd = fileno(stream);
+	wait_arg status;
+	int wret;
+
+#ifdef _ANSI
+	void (*intsave)(int) = signal(SIGINT, SIG_IGN);
+	void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN);
+#else
+	void (*intsave)() = signal(SIGINT, SIG_IGN);
+	void (*quitsave)() = signal(SIGQUIT, SIG_IGN);
+#endif
+	fclose(stream);
+	while ((wret = _wait(&status)) != -1) {
+		if (wret == pids[fd]) break;
+	}
+	if (wret == -1) ret_val = -1;
+	signal(SIGINT, intsave);
+	signal(SIGQUIT, quitsave);
+	pids[fd] = 0;
+	return ret_val;
+}
+
+#if	defined(__USG)
+int _dup(int fildes);
+
+static int
+_dup2(oldd, newd)
+int oldd, newd;
+{
+	int i = 0, fd, tmp;
+	int fdbuf[_NFILES];
+
+	/* ignore the error on the close() */
+	tmp = errno; (void) _close(newd); errno = tmp;
+	while ((fd = _dup(oldd)) != newd) {
+		if (fd == -1) break;
+		fdbuf[i++] = fd;
+	}
+	tmp = errno;
+	while (--i >= 0) {
+		_close(fdbuf[i]);
+	}
+	errno = tmp;
+	return -(fd == -1);
+}
+#endif	/* __USG */
Index: /trunk/minix/lib/other/putenv.c
===================================================================
--- /trunk/minix/lib/other/putenv.c	(revision 9)
+++ /trunk/minix/lib/other/putenv.c	(revision 9)
@@ -0,0 +1,79 @@
+/*
+ * (c) copyright 1989 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: /cvsup/minix/src/lib/other/putenv.c,v 1.1.1.1.8.1 2006/05/03 21:13:45 beng Exp $ */
+
+#include	<stdlib.h>
+#include	<string.h>
+
+#define	ENTRY_INC	10
+#define	rounded(x)	(((x / ENTRY_INC) + 1) * ENTRY_INC)
+
+extern _CONST char ***_penviron;
+
+int
+putenv(name)
+char *name;
+{
+	register _CONST char **v = *_penviron;
+	register char *r;
+	static int size = 0;
+	/* When size != 0, it contains the number of entries in the
+	 * table (including the final NULL pointer). This means that the
+	 * last non-null entry  is environ[size - 2].
+	 */
+
+	if (!name) return 0;
+	if (*_penviron == NULL) return 1;
+	if (r = strchr(name, '=')) {
+		register _CONST char *p, *q;
+
+		*r = '\0';
+
+		if (v != NULL) {
+			while ((p = *v) != NULL) {
+				q = name;
+				while (*q && (*q++ == *p++))
+					/* EMPTY */ ;
+				if (*q || (*p != '=')) {
+					v++;
+				} else {
+					/* The name was already in the
+					 * environment.
+					 */
+					*r = '=';
+					*v = name;
+					return 0;
+				}
+			}
+		}
+		*r = '=';
+		v = *_penviron;
+	}
+
+	if (!size) {
+		register _CONST char **p;
+		register int i = 0;
+
+		if (v)
+			do {
+				i++;
+			} while (*v++);
+		if (!(v = malloc(rounded(i) * sizeof(char **))))
+			return 1;
+		size = i;
+		p = *_penviron;
+		*_penviron = v;
+		while (*v++ = *p++);		/* copy the environment */
+		v = *_penviron;
+	} else if (!(size % ENTRY_INC)) {
+		if (!(v = realloc(*_penviron, rounded(size) * sizeof(char **))))
+			return 1;
+		*_penviron = v;
+	}
+	v[size - 1] = name;
+	v[size] = NULL;
+	size++;
+	return 0;
+}
Index: /trunk/minix/lib/other/putw.c
===================================================================
--- /trunk/minix/lib/other/putw.c	(revision 9)
+++ /trunk/minix/lib/other/putw.c	(revision 9)
@@ -0,0 +1,23 @@
+/* 
+ * putw - write an word on a stream
+ */
+/* $Header: /cvsup/minix/src/lib/other/putw.c,v 1.1.1.1 2005/04/21 14:56:27 beng Exp $ */
+
+#include	<stdio.h>
+
+_PROTOTYPE(int putw, (int w, FILE *stream ));
+
+int
+putw(w, stream)
+int w;
+register FILE *stream;
+{
+	register int cnt = sizeof(int);
+	register char *p = (char *) &w;
+
+	while (cnt--) {
+		putc(*p++, stream);
+	}
+	if (ferror(stream)) return EOF;
+	return w;
+}
Index: /trunk/minix/lib/other/random.c
===================================================================
--- /trunk/minix/lib/other/random.c	(revision 9)
+++ /trunk/minix/lib/other/random.c	(revision 9)
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 1983, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)random.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * random.c:
+ *
+ * An improved random number generation package.  In addition to the standard
+ * rand()/srand() like interface, this package also has a special state info
+ * interface.  The initstate() routine is called with a seed, an array of
+ * bytes, and a count of how many bytes are being passed in; this array is
+ * then initialized to contain information for random number generation with
+ * that much state information.  Good sizes for the amount of state
+ * information are 32, 64, 128, and 256 bytes.  The state can be switched by
+ * calling the setstate() routine with the same array as was initiallized
+ * with initstate().  By default, the package runs with 128 bytes of state
+ * information and generates far better random numbers than a linear
+ * congruential generator.  If the amount of state information is less than
+ * 32 bytes, a simple linear congruential R.N.G. is used.
+ *
+ * Internally, the state information is treated as an array of longs; the
+ * zeroeth element of the array is the type of R.N.G. being used (small
+ * integer); the remainder of the array is the state information for the
+ * R.N.G.  Thus, 32 bytes of state information will give 7 longs worth of
+ * state information, which will allow a degree seven polynomial.  (Note:
+ * the zeroeth word of state information also has some other information
+ * stored in it -- see setstate() for details).
+ * 
+ * The random number generation technique is a linear feedback shift register
+ * approach, employing trinomials (since there are fewer terms to sum up that
+ * way).  In this approach, the least significant bit of all the numbers in
+ * the state table will act as a linear feedback shift register, and will
+ * have period 2^deg - 1 (where deg is the degree of the polynomial being
+ * used, assuming that the polynomial is irreducible and primitive).  The
+ * higher order bits will have longer periods, since their values are also
+ * influenced by pseudo-random carries out of the lower bits.  The total
+ * period of the generator is approximately deg*(2**deg - 1); thus doubling
+ * the amount of state information has a vast influence on the period of the
+ * generator.  Note: the deg*(2**deg - 1) is an approximation only good for
+ * large deg, when the period of the shift register is the dominant factor.
+ * With deg equal to seven, the period is actually much longer than the
+ * 7*(2**7 - 1) predicted by this formula.
+ */
+
+/*
+ * For each of the currently supported random number generators, we have a
+ * break value on the amount of state information (you need at least this
+ * many bytes of state info to support this random number generator), a degree
+ * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
+ * the separation between the two lower order coefficients of the trinomial.
+ */
+#define	TYPE_0		0		/* linear congruential */
+#define	BREAK_0		8
+#define	DEG_0		0
+#define	SEP_0		0
+
+#define	TYPE_1		1		/* x**7 + x**3 + 1 */
+#define	BREAK_1		32
+#define	DEG_1		7
+#define	SEP_1		3
+
+#define	TYPE_2		2		/* x**15 + x + 1 */
+#define	BREAK_2		64
+#define	DEG_2		15
+#define	SEP_2		1
+
+#define	TYPE_3		3		/* x**31 + x**3 + 1 */
+#define	BREAK_3		128
+#define	DEG_3		31
+#define	SEP_3		3
+
+#define	TYPE_4		4		/* x**63 + x + 1 */
+#define	BREAK_4		256
+#define	DEG_4		63
+#define	SEP_4		1
+
+/*
+ * Array versions of the above information to make code run faster --
+ * relies on fact that TYPE_i == i.
+ */
+#define	MAX_TYPES	5		/* max number of types above */
+
+static int degrees[MAX_TYPES] =	{ DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
+static int seps [MAX_TYPES] =	{ SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
+
+/*
+ * Initially, everything is set up as if from:
+ *
+ *	initstate(1, &randtbl, 128);
+ *
+ * Note that this initialization takes advantage of the fact that srandom()
+ * advances the front and rear pointers 10*rand_deg times, and hence the
+ * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
+ * element of the state information, which contains info about the current
+ * position of the rear pointer is just
+ *
+ *	MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
+ */
+
+static long randtbl[DEG_3 + 1] = {
+	TYPE_3,
+	0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5,
+	0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd,
+	0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88,
+	0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc,
+	0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b,
+	0x27fb47b9,
+};
+
+/*
+ * fptr and rptr are two pointers into the state info, a front and a rear
+ * pointer.  These two pointers are always rand_sep places aparts, as they
+ * cycle cyclically through the state information.  (Yes, this does mean we
+ * could get away with just one pointer, but the code for random() is more
+ * efficient this way).  The pointers are left positioned as they would be
+ * from the call
+ *
+ *	initstate(1, randtbl, 128);
+ *
+ * (The position of the rear pointer, rptr, is really 0 (as explained above
+ * in the initialization of randtbl) because the state table pointer is set
+ * to point to randtbl[1] (as explained below).
+ */
+static long *fptr = &randtbl[SEP_3 + 1];
+static long *rptr = &randtbl[1];
+
+/*
+ * The following things are the pointer to the state information table, the
+ * type of the current generator, the degree of the current polynomial being
+ * used, and the separation between the two pointers.  Note that for efficiency
+ * of random(), we remember the first location of the state information, not
+ * the zeroeth.  Hence it is valid to access state[-1], which is used to
+ * store the type of the R.N.G.  Also, we remember the last location, since
+ * this is more efficient than indexing every time to find the address of
+ * the last element to see if the front and rear pointers have wrapped.
+ */
+static long *state = &randtbl[1];
+static int rand_type = TYPE_3;
+static int rand_deg = DEG_3;
+static int rand_sep = SEP_3;
+static long *end_ptr = &randtbl[DEG_3 + 1];
+
+/*
+ * srandom:
+ *
+ * Initialize the random number generator based on the given seed.  If the
+ * type is the trivial no-state-information type, just remember the seed.
+ * Otherwise, initializes state[] based on the given "seed" via a linear
+ * congruential generator.  Then, the pointers are set to known locations
+ * that are exactly rand_sep places apart.  Lastly, it cycles the state
+ * information a given number of times to get rid of any initial dependencies
+ * introduced by the L.C.R.N.G.  Note that the initialization of randtbl[]
+ * for default usage relies on values produced by this routine.
+ */
+void
+srandom(x)
+	u_int x;
+{
+	register int i, j;
+
+	if (rand_type == TYPE_0)
+		state[0] = x;
+	else {
+		j = 1;
+		state[0] = x;
+		for (i = 1; i < rand_deg; i++)
+			state[i] = 1103515245 * state[i - 1] + 12345;
+		fptr = &state[rand_sep];
+		rptr = &state[0];
+		for (i = 0; i < 10 * rand_deg; i++)
+			(void)random();
+	}
+}
+
+/*
+ * initstate:
+ *
+ * Initialize the state information in the given array of n bytes for future
+ * random number generation.  Based on the number of bytes we are given, and
+ * the break values for the different R.N.G.'s, we choose the best (largest)
+ * one we can and set things up for it.  srandom() is then called to
+ * initialize the state information.
+ * 
+ * Note that on return from srandom(), we set state[-1] to be the type
+ * multiplexed with the current value of the rear pointer; this is so
+ * successive calls to initstate() won't lose this information and will be
+ * able to restart with setstate().
+ * 
+ * Note: the first thing we do is save the current state, if any, just like
+ * setstate() so that it doesn't matter when initstate is called.
+ *
+ * Returns a pointer to the old state.
+ */
+char *
+initstate(seed, arg_state, n)
+	u_int seed;			/* seed for R.N.G. */
+	char *arg_state;		/* pointer to state array */
+	size_t n;			/* # bytes of state info */
+{
+	register char *ostate = (char *)(&state[-1]);
+
+	if (rand_type == TYPE_0)
+		state[-1] = rand_type;
+	else
+		state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+	if (n < BREAK_0) {
+		(void)fprintf(stderr,
+		    "random: not enough state (%d bytes); ignored.\n", n);
+		return(0);
+	}
+	if (n < BREAK_1) {
+		rand_type = TYPE_0;
+		rand_deg = DEG_0;
+		rand_sep = SEP_0;
+	} else if (n < BREAK_2) {
+		rand_type = TYPE_1;
+		rand_deg = DEG_1;
+		rand_sep = SEP_1;
+	} else if (n < BREAK_3) {
+		rand_type = TYPE_2;
+		rand_deg = DEG_2;
+		rand_sep = SEP_2;
+	} else if (n < BREAK_4) {
+		rand_type = TYPE_3;
+		rand_deg = DEG_3;
+		rand_sep = SEP_3;
+	} else {
+		rand_type = TYPE_4;
+		rand_deg = DEG_4;
+		rand_sep = SEP_4;
+	}
+	state = &(((long *)arg_state)[1]);	/* first location */
+	end_ptr = &state[rand_deg];	/* must set end_ptr before srandom */
+	srandom(seed);
+	if (rand_type == TYPE_0)
+		state[-1] = rand_type;
+	else
+		state[-1] = MAX_TYPES*(rptr - state) + rand_type;
+	return(ostate);
+}
+
+/*
+ * setstate:
+ *
+ * Restore the state from the given state array.
+ *
+ * Note: it is important that we also remember the locations of the pointers
+ * in the current state information, and restore the locations of the pointers
+ * from the old state information.  This is done by multiplexing the pointer
+ * location into the zeroeth word of the state information.
+ *
+ * Note that due to the order in which things are done, it is OK to call
+ * setstate() with the same state as the current state.
+ *
+ * Returns a pointer to the old state information.
+ */
+char *
+setstate(arg_state)
+	const char *arg_state;
+{
+	register long *new_state = (long *)arg_state;
+	register int type = new_state[0] % MAX_TYPES;
+	register int rear = new_state[0] / MAX_TYPES;
+	char *ostate = (char *)(&state[-1]);
+
+	if (rand_type == TYPE_0)
+		state[-1] = rand_type;
+	else
+		state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+	switch(type) {
+	case TYPE_0:
+	case TYPE_1:
+	case TYPE_2:
+	case TYPE_3:
+	case TYPE_4:
+		rand_type = type;
+		rand_deg = degrees[type];
+		rand_sep = seps[type];
+		break;
+	default:
+		(void)fprintf(stderr,
+		    "random: state info corrupted; not changed.\n");
+	}
+	state = &new_state[1];
+	if (rand_type != TYPE_0) {
+		rptr = &state[rear];
+		fptr = &state[(rear + rand_sep) % rand_deg];
+	}
+	end_ptr = &state[rand_deg];		/* set end_ptr too */
+	return(ostate);
+}
+
+/*
+ * random:
+ *
+ * If we are using the trivial TYPE_0 R.N.G., just do the old linear
+ * congruential bit.  Otherwise, we do our fancy trinomial stuff, which is
+ * the same in all the other cases due to all the global variables that have
+ * been set up.  The basic operation is to add the number at the rear pointer
+ * into the one at the front pointer.  Then both pointers are advanced to
+ * the next location cyclically in the table.  The value returned is the sum
+ * generated, reduced to 31 bits by throwing away the "least random" low bit.
+ *
+ * Note: the code takes advantage of the fact that both the front and
+ * rear pointers can't wrap on the same call by not testing the rear
+ * pointer if the front one has wrapped.
+ *
+ * Returns a 31-bit random number.
+ */
+long
+random()
+{
+	long i;
+
+	if (rand_type == TYPE_0)
+		i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
+	else {
+		*fptr += *rptr;
+		i = (*fptr >> 1) & 0x7fffffff;	/* chucking least random bit */
+		if (++fptr >= end_ptr) {
+			fptr = state;
+			++rptr;
+		} else if (++rptr >= end_ptr)
+			rptr = state;
+	}
+	return(i);
+}
Index: /trunk/minix/lib/other/rindex.c
===================================================================
--- /trunk/minix/lib/other/rindex.c	(revision 9)
+++ /trunk/minix/lib/other/rindex.c	(revision 9)
@@ -0,0 +1,11 @@
+#include <lib.h>
+/* rindex - find last occurrence of a character in a string  */
+
+#include <string.h>
+
+char *rindex(s, charwanted)	/* found char, or NULL if none */
+_CONST char *s;
+char charwanted;
+{
+  return(strrchr(s, charwanted));
+}
Index: /trunk/minix/lib/other/setenv.c
===================================================================
--- /trunk/minix/lib/other/setenv.c	(revision 9)
+++ /trunk/minix/lib/other/setenv.c	(revision 9)
@@ -0,0 +1,25 @@
+
+#include	<stdlib.h>
+#include	<string.h>
+
+int
+setenv(const char *name, const char *val, int overwrite)
+{
+	char *bf;
+	int r;
+
+	if(!overwrite && getenv(name))
+		return 0;
+
+	if(!(bf=malloc(strlen(name)+strlen(val)+2)))
+		return -1;
+
+	strcpy(bf, name);
+	strcat(bf, "=");
+	strcat(bf, val);
+
+	r = putenv(bf);
+
+	return r == 0 ? 0 : -1;
+}
+
Index: /trunk/minix/lib/other/setgroups.c
===================================================================
--- /trunk/minix/lib/other/setgroups.c	(revision 9)
+++ /trunk/minix/lib/other/setgroups.c	(revision 9)
@@ -0,0 +1,53 @@
+/*
+setgroups.c
+*/
+
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <grp.h>
+
+int setgroups(int ngroups, const gid_t *gidset)
+{
+	if(ngroups > 1) {
+		/* Supplementary groups not implemented */
+		errno= EINVAL;
+		return -1;
+	}
+
+	if(ngroups == 1)
+		return setgid(gidset[0]);
+
+	return 0;
+}
+
+int initgroups(const char *name, gid_t basegid)
+{
+	struct group *gr;
+	int r, found = 0;
+	if((r = setgid(basegid)) < 0)
+		return r;
+
+	setgrent();
+	while (!found && (gr = getgrent()) != NULL) {
+		char **mem;
+		for(mem = gr->gr_mem; mem && *mem; mem++) {
+			if(!strcmp(name, *mem)) {
+				found = 1;
+				break;
+			}
+		}
+	}
+	endgrent();
+
+	/* Because supplemental groups aren't implemented, this call
+	 * should fail if the user is in any supplemental groups.
+	 */
+	if(found) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	return 0;
+}
+
Index: /trunk/minix/lib/other/settimeofday.c
===================================================================
--- /trunk/minix/lib/other/settimeofday.c	(revision 9)
+++ /trunk/minix/lib/other/settimeofday.c	(revision 9)
@@ -0,0 +1,14 @@
+/*
+settimeofday.c
+*/
+
+#define stime _stime
+
+#include <sys/time.h>
+#include <time.h>
+
+int settimeofday(const struct timeval *tp, const void *tzp)
+{
+	/* Ignore time zones */
+	return stime(&tp->tv_sec);
+}
Index: /trunk/minix/lib/other/stderr.c
===================================================================
--- /trunk/minix/lib/other/stderr.c	(revision 9)
+++ /trunk/minix/lib/other/stderr.c	(revision 9)
@@ -0,0 +1,14 @@
+#include <lib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+_PROTOTYPE( void std_err, (char *s));
+
+void std_err(s)
+char *s;
+{
+  register char *p = s;
+
+  while (*p != 0) p++;
+  write(2, s, (int) (p - s));
+}
Index: /trunk/minix/lib/other/strdup.c
===================================================================
--- /trunk/minix/lib/other/strdup.c	(revision 9)
+++ /trunk/minix/lib/other/strdup.c	(revision 9)
@@ -0,0 +1,23 @@
+/*
+lib/other/strdup.c
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+char *strdup(s1)
+const char *s1;
+{
+	size_t len;
+	char *s2;
+
+	len= strlen(s1)+1;
+
+	s2= malloc(len);
+	if (s2 == NULL)
+		return NULL;
+	strcpy(s2, s1);
+
+	return s2;
+}
+
Index: /trunk/minix/lib/other/strtok_r.c
===================================================================
--- /trunk/minix/lib/other/strtok_r.c	(revision 9)
+++ /trunk/minix/lib/other/strtok_r.c	(revision 9)
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 1998 Softweyr LLC.  All rights reserved.
+ *
+ * strtok_r, from Berkeley strtok
+ * Oct 13, 1998 by Wes Peters <wes@softweyr.com>
+ *
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notices, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notices, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *
+ *	This product includes software developed by Softweyr LLC, the
+ *      University of California, Berkeley, and its contributors.
+ *
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL SOFTWEYR LLC, THE
+ * REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+  "$FreeBSD: src/lib/libc/string/strtok.c,v 1.2.6.1 2001/07/09 23:30:07 obrien Exp $";
+#endif
+
+#include <stddef.h>
+#include <string.h>
+
+char *
+strtok_r(char *s, const char *delim, char **last)
+{
+    char *spanp;
+    int c, sc;
+    char *tok;
+
+    if (s == NULL && (s = *last) == NULL)
+    {
+	return NULL;
+    }
+
+    /*
+     * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+     */
+cont:
+    c = *s++;
+    for (spanp = (char *)delim; (sc = *spanp++) != 0; )
+    {
+	if (c == sc)
+	{
+	    goto cont;
+	}
+    }
+
+    if (c == 0)		/* no non-delimiter characters */
+    {
+	*last = NULL;
+	return NULL;
+    }
+    tok = s - 1;
+
+    /*
+     * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+     * Note that delim must have one NUL; we stop if we see that, too.
+     */
+    for (;;)
+    {
+	c = *s++;
+	spanp = (char *)delim;
+	do
+	{
+	    if ((sc = *spanp++) == c)
+	    {
+		if (c == 0)
+		{
+		    s = NULL;
+		}
+		else
+		{
+		    char *w = s - 1;
+		    *w = '\0';
+		}
+		*last = s;
+		return tok;
+	    }
+	}
+	while (sc != 0);
+    }
+    /* NOTREACHED */
+}
+
+
+#if 0
+char *
+strtok(char *s, const char *delim)
+{
+    static char *last;
+
+    return strtok_r(s, delim, &last);
+}
+#endif
+
+#if defined(DEBUG_STRTOK)
+
+/*
+ * Test the tokenizer.
+ */
+int
+main()
+{
+    char test[80], blah[80];
+    char *sep = "\\/:;=-";
+    char *word, *phrase, *brkt, *brkb;
+
+    printf("String tokenizer test:\n");
+
+    strcpy(test, "This;is.a:test:of=the/string\\tokenizer-function.");
+
+    for (word = strtok(test, sep);
+	 word;
+	 word = strtok(NULL, sep))
+    {
+	printf("Next word is \"%s\".\n", word);
+    }
+
+    phrase = "foo";
+
+    strcpy(test, "This;is.a:test:of=the/string\\tokenizer-function.");
+
+    for (word = strtok_r(test, sep, &brkt);
+	 word;
+	 word = strtok_r(NULL, sep, &brkt))
+    {
+	strcpy(blah, "blah:blat:blab:blag");
+
+	for (phrase = strtok_r(blah, sep, &brkb);
+	     phrase;
+	     phrase = strtok_r(NULL, sep, &brkb))
+	{
+	    printf("So far we're at %s:%s\n", word, phrase);
+	}
+    }
+
+    return 0;
+}
+
+#endif /* DEBUG_STRTOK */
Index: /trunk/minix/lib/other/swab.c
===================================================================
--- /trunk/minix/lib/other/swab.c	(revision 9)
+++ /trunk/minix/lib/other/swab.c	(revision 9)
@@ -0,0 +1,22 @@
+#include <lib.h>
+/*  swab(3)
+ *
+ *  Author: Terrence W. Holm          Sep. 1988
+ */
+_PROTOTYPE( void swab, (char *from, char *to, int count));
+
+void swab(from, to, count)
+char *from;
+char *to;
+int count;
+{
+  register char temp;
+
+  count >>= 1;
+
+  while (--count >= 0) {
+	temp = *from++;
+	*to++ = *from++;
+	*to++ = temp;
+  }
+}
Index: /trunk/minix/lib/other/sys_eniop.c
===================================================================
--- /trunk/minix/lib/other/sys_eniop.c	(revision 9)
+++ /trunk/minix/lib/other/sys_eniop.c	(revision 9)
@@ -0,0 +1,14 @@
+#include "../syslib/syslib.h"
+
+/*===========================================================================*
+ *                               sys_enable_iop				     *    
+ *===========================================================================*/
+PUBLIC int sys_enable_iop(proc_nr)
+int proc_nr;			/* number of process to allow I/O */
+{
+    message m_iop;
+    m_iop.IO_ENDPT = proc_nr;
+    return _taskcall(SYSTASK, SYS_IOPENABLE, &m_iop);
+}
+
+
Index: /trunk/minix/lib/other/syscall.c
===================================================================
--- /trunk/minix/lib/other/syscall.c	(revision 9)
+++ /trunk/minix/lib/other/syscall.c	(revision 9)
@@ -0,0 +1,22 @@
+#include <lib.h>
+
+PUBLIC int _syscall(who, syscallnr, msgptr)
+int who;
+int syscallnr;
+register message *msgptr;
+{
+  int status;
+
+  msgptr->m_type = syscallnr;
+  status = _sendrec(who, msgptr);
+  if (status != 0) {
+	/* 'sendrec' itself failed. */
+	/* XXX - strerror doesn't know all the codes */
+	msgptr->m_type = status;
+  }
+  if (msgptr->m_type < 0) {
+	errno = -msgptr->m_type;
+	return(-1);
+  }
+  return(msgptr->m_type);
+}
Index: /trunk/minix/lib/other/sysconf.c
===================================================================
--- /trunk/minix/lib/other/sysconf.c	(revision 9)
+++ /trunk/minix/lib/other/sysconf.c	(revision 9)
@@ -0,0 +1,55 @@
+/* sysconf.c						POSIX 4.8.1
+ *	long int sysconf(int name);
+ *
+ *	POSIX allows some of the values in <limits.h> to be increased at
+ *	run time.  The sysconf() function allows such values to be checked
+ *	at run time.  MINIX does not use this facility - the run time
+ *	limits are those given in <limits.h>.
+ */
+
+#include <lib.h>
+#include <unistd.h>
+#include <time.h>
+
+PUBLIC long int sysconf(name)
+int name;			/* property being inspected */
+{
+  switch(name) {
+	case _SC_ARG_MAX:
+		return (long) ARG_MAX;
+
+	case _SC_CHILD_MAX:
+		return (long) CHILD_MAX;
+
+	case _SC_CLK_TCK:
+		return (long) CLOCKS_PER_SEC;
+
+	case _SC_NGROUPS_MAX:
+		return (long) NGROUPS_MAX;
+
+	case _SC_OPEN_MAX:
+		return (long) OPEN_MAX;
+
+	case _SC_JOB_CONTROL:
+		return -1L;			/* no job control */
+
+	case _SC_SAVED_IDS:
+		return -1L;			/* no saved uid/gid */
+
+	case _SC_VERSION:
+		return (long) _POSIX_VERSION;
+
+	case _SC_STREAM_MAX:
+		return (long) STREAM_MAX;
+
+	case _SC_TZNAME_MAX:
+		return (long) TZNAME_MAX;
+
+	case _SC_PAGESIZE:
+		return getpagesize();
+
+	default:
+		errno = EINVAL;
+		return -1L;
+  }
+}
Index: /trunk/minix/lib/other/syslog.c
===================================================================
--- /trunk/minix/lib/other/syslog.c	(revision 9)
+++ /trunk/minix/lib/other/syslog.c	(revision 9)
@@ -0,0 +1,167 @@
+/* Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * #if defined(LIBC_SCCS) && !defined(lint)
+ * static char sccsid[] = "@(#)syslog.c    8.4 (Berkeley) 3/18/94";
+ * #endif
+ *
+ * Author: Eric Allman
+ * Modified to use UNIX domain IPC by Ralph Campbell
+ * Patched March 12, 1996 by A. Ian Vogelesang <vogelesang@hdshq.com>
+ * Rewritten by Martin Mares <mj@atrey.karlin.mff.cuni.cz> on May 14, 1997
+ * Rewritten by G. Falzoni <gfalzoni@inwind.it> for porting to Minix
+ *
+ * $Id: syslog.c,v 1.2 2006/04/03 15:03:07 beng Exp $
+ */
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <sys/ioctl.h>
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+#include <net/gen/netdb.h>
+#include <errno.h>
+#include <net/gen/inet.h>
+
+static int LogPid = (-1);
+static int nfd = (-1);
+static int LogFacility = LOG_USER;
+static int LogFlags = 0;
+static char TagBuffer[40] = "syslog";
+
+/*
+** OPENLOG -- open system log
+** 	- establishes a channel to syslogd using UDP device
+**	  (port 514 is used _ syslog/udp)
+**	- stores program tag (if not NULL) and other options
+**	  for use by syslog
+*/
+void openlog(const char *ident, int option, int facility)
+{
+  struct nwio_udpopt udpopt;
+
+  /* Stores logging flags */
+  LogFlags = option & (LOG_PID | LOG_PERROR | LOG_CONS);
+  /* Stores process id. if LOG_PID was specified */
+  if (option & LOG_PID) LogPid = getpid();
+  /* Stores the requested facility */
+  LogFacility = facility;
+  /* Stores log tag if supplied */
+  if (ident != NULL && *ident != '0' && ident != TagBuffer) {
+	strncpy(TagBuffer, ident, sizeof(TagBuffer));
+	TagBuffer[sizeof(TagBuffer) - 1] = '0';
+  }
+
+  /* Opens channel to syslog daemon via UDP device */
+  /* Static values used to minimize code */
+  if (option & LOG_NDELAY) {
+	/* Opens UDP device */
+	if ((nfd = open(UDP_DEVICE, O_RDWR)) < 0) {
+		 /* Report error */ ;
+	}
+	/* Sets options for UDP device */
+	udpopt.nwuo_flags = NWUO_SHARED | NWUO_LP_SET | NWUO_DI_LOC |
+		NWUO_DI_BROAD | NWUO_RP_SET | NWUO_RA_SET |
+		NWUO_RWDATONLY | NWUO_DI_IPOPT;
+	udpopt.nwuo_locaddr = udpopt.nwuo_remaddr = htonl(0x7F000001L);
+	udpopt.nwuo_locport = udpopt.nwuo_remport = htons(514);
+	if (ioctl(nfd, NWIOSUDPOPT, &udpopt) < 0 ||
+	    ioctl(nfd, NWIOGUDPOPT, &udpopt) < 0) {
+		 /* Report error */ ;
+	}
+  }
+  return;
+}
+
+/*
+**  SYSLOG -- print message on log file
+**
+**  This routine looks a lot like printf, except that it outputs to the
+**  log file instead of the standard output.  Also:
+**	- adds a timestamp,
+**	- prints the module name in front of the message,
+**	- has some other formatting types (or will sometime),
+**	- adds a newline on the end of the message.
+**
+** The output of this routine is intended to be read by syslogd(8).
+*/
+void syslog(int lprty, const char *msg,...)
+{
+  time_t now;
+  char buff[512];
+  int len, rc;
+  va_list ap;
+
+  /* First log message open chnnel to syslog */
+  if (nfd < 0) openlog(TagBuffer, LogFlags | LOG_NDELAY, LogFacility);
+  time(&now);
+  len = sprintf(buff, "<%d>%.15s %s: ",
+		LogFacility | lprty, ctime(&now) + 4, TagBuffer);
+  if (LogFlags & LOG_PID) {
+	len -= 2;
+	len += sprintf(buff + len, "[%d]: ", LogPid);
+  }
+  va_start(ap, msg);
+  len += vsprintf(buff + len, msg, ap);
+  va_end(ap);
+  rc = write(nfd, buff, len);
+  if ((rc != len && LogFlags & LOG_CONS) || LogFlags & LOG_PERROR) {
+	write(STDERR_FILENO, buff, len);
+	write(STDERR_FILENO, "\n", 1);
+  }
+  return;
+}
+
+/*
+**  CLOSELOG -- close access to syslogd
+**	- closes UDP channel
+**	- restores default values
+*/
+void closelog(void)
+{
+
+  close(nfd);
+  LogPid = nfd = -1;
+  LogFacility = LOG_USER;
+  LogFlags = 0;
+  return;
+}
+
+/** syslog.c **/
Index: /trunk/minix/lib/other/taskcall.c
===================================================================
--- /trunk/minix/lib/other/taskcall.c	(revision 9)
+++ /trunk/minix/lib/other/taskcall.c	(revision 9)
@@ -0,0 +1,20 @@
+/* _taskcall() is the same as _syscall() except it returns negative error
+ * codes directly and not in errno.  This is a better interface for MM and
+ * FS.
+ */
+
+#include <lib.h>
+#include <minix/syslib.h>
+
+PUBLIC int _taskcall(who, syscallnr, msgptr)
+int who;
+int syscallnr;
+register message *msgptr;
+{
+  int status;
+
+  msgptr->m_type = syscallnr;
+  status = _sendrec(who, msgptr);
+  if (status != 0) return(status);
+  return(msgptr->m_type);
+}
Index: /trunk/minix/lib/other/telldir.c
===================================================================
--- /trunk/minix/lib/other/telldir.c	(revision 9)
+++ /trunk/minix/lib/other/telldir.c	(revision 9)
@@ -0,0 +1,16 @@
+/*	telldir()					Author: Kees J. Bot
+ *								24 Apr 1989
+ */
+#define nil 0
+#include <lib.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+
+off_t telldir(DIR *dp)
+/* Return the current read position in a directory. */
+{
+	if (dp == nil) { errno= EBADF; return -1; }
+
+	return dp->_pos;
+}
Index: /trunk/minix/lib/other/termcap.c
===================================================================
--- /trunk/minix/lib/other/termcap.c	(revision 9)
+++ /trunk/minix/lib/other/termcap.c	(revision 9)
@@ -0,0 +1,325 @@
+/*
+ *	termcap.c	V1.1	20/7/87		agc	Joypace Ltd
+ *
+ *	Copyright Joypace Ltd, London, UK, 1987. All rights reserved.
+ *	This file may be freely distributed provided that this notice
+ *	remains attached.
+ *
+ *	A public domain implementation of the termcap(3) routines.
+ *
+ *
+ *
+ *	 Klamer Schutte	      V1.2    Nov. 1988
+ *
+ *   - Can match multiple terminal names		 [tgetent]
+ *   - Removal of **area assignments			 [tgetstr]
+ *
+ *	 Terrence W. Holm     V1.3    May, Sep, Oct.  1988
+ *
+ *   - Correct when TERM != name and TERMCAP is defined	 [tgetent]
+ *   - Correct the comparison for the terminal name 	 [tgetent]
+ *   - Correct the value of ^x escapes              	 [tgetstr]
+ *   - Added %r to reverse row/column			 [tgoto]
+ *   - Fixed end of definition test			 [tgetnum/flag/str]
+ *
+ *	 Terrence W. Holm     V1.4    Jan. 1989
+ *
+ *   - Incorporated Klamer's V1.2 fixes into V1.3
+ *   - Added %d, (old %d is now %2)			 [tgoto]
+ *   - Allow '#' comments in definition file		 [tgetent]
+ */
+
+#include <lib.h>
+#include <termcap.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+char *capab = (char *)NULL;		/* the capability itself */
+
+#if 0
+/*  The following are not yet used.  */
+extern short ospeed;		/* output speed */
+extern char PC;			/* padding character */
+extern char *BC;		/* back cursor movement */
+extern char *UP;		/* up cursor movement */
+#endif
+
+/*
+ *	tgetent - get the termcap entry for terminal name, and put it
+ *	in bp (which must be an array of 1024 chars). Returns 1 if
+ *	termcap entry found, 0 if not found, and -1 if file not found.
+ */
+
+int tgetent(bp, name)
+char *bp;
+char *name;
+{
+  FILE *fp;
+  char *file;
+  char *term;
+  short len = strlen(name);
+
+  capab = bp;
+
+  /* If TERMCAP begins with a '/' then use TERMCAP as the path	 */
+  /* Name of the termcap definitions file. If TERMCAP is a	 */
+  /* Definition and TERM equals "name" then use TERMCAP as the	 */
+  /* Definition. Otherwise use "/etc/termcap" as the path name.	 */
+
+  if ((file = getenv("TERMCAP")) == (char *)NULL)
+	file = "/etc/termcap";
+  else if (*file != '/')
+	if ((term = getenv("TERM")) != (char *)NULL && strcmp(term, name) == 0) {
+		*bp = '\0';
+		strncat(bp, file, 1023);
+		return(1);
+	} else
+		file = "/etc/termcap";
+
+  if ((fp = fopen(file, "r")) == (FILE *) NULL) {
+	capab = (char *)NULL;		/* no valid termcap  */
+	return(-1);
+  }
+  for (;;) {
+	/* Read in each definition */
+	int def_len = 0;
+	char *cp = bp;
+
+	do {
+		if (fgets(&bp[def_len], (unsigned int)(1024 - def_len), fp) == (char *)NULL) {
+			fclose(fp);
+			capab = (char *)NULL;	/* no valid termcap */
+			return(0);
+		}
+		def_len = strlen(bp) - 2;
+	} while (bp[def_len] == '\\');
+
+	while (isspace(*cp)) cp++;
+
+	/* Comment lines start with a '#'  */
+	if (*cp == '#') continue;
+
+	/* See if any of the terminal names in this definition */
+	/* Match "name".						 */
+
+	do {
+		if (strncmp(name, cp, len) == 0 &&
+		    (cp[len] == '|' || cp[len] == ':')) {
+			fclose(fp);
+			return(1);
+		}
+		while ((*cp) && (*cp != '|') && (*cp != ':')) cp++;
+	} while (*cp++ == '|');
+  }
+}
+
+
+/*
+ *	tgetnum - get the numeric terminal capability corresponding
+ *	to id. Returns the value, -1 if invalid.
+ */
+
+int tgetnum(id)
+char *id;
+{
+  register char *cp = capab;
+
+  if (cp == (char *)NULL || id == (char *)NULL) return(-1);
+
+  for (;;) {
+	while (*cp++ != ':')
+		if (cp[-1] == '\0') return(-1);
+
+	while (isspace(*cp)) cp++;
+
+	if (strncmp(cp, id, 2) == 0 && cp[2] == '#') return(atoi(cp + 3));
+  }
+}
+
+
+/*
+ *	tgetflag - get the boolean flag corresponding to id. Returns -1
+ *	if invalid, 0 if the flag is not in termcap entry, or 1 if it is
+ *	present.
+ */
+
+int tgetflag(id)
+char *id;
+{
+  register char *cp = capab;
+
+  if (cp == (char *)NULL || id == (char *)NULL) return(-1);
+
+  for (;;) {
+	while (*cp++ != ':')
+		if (cp[-1] == '\0') return(0);
+
+	while (isspace(*cp)) cp++;
+
+	if (strncmp(cp, id, 2) == 0) return(1);
+  }
+}
+
+
+/*
+ *	tgetstr - get the string capability corresponding to id and place
+ *	it in area (advancing area at same time). Expand escape sequences
+ *	etc. Returns the string, or NULL if it can't do it.
+ */
+
+char *tgetstr(id, area)
+char *id;
+char **area;
+{
+  register char *cp = capab;
+  register char *wsp = *area;	/* workspace pointer  */
+
+  if (cp == (char *)NULL || id == (char *)NULL) return((char *)NULL);
+
+  for (;;) {
+	while (*cp++ != ':')
+		if (cp[-1] == '\0') return((char *)NULL);
+
+	while (isspace(*cp)) cp++;
+
+	if (strncmp(cp, id, 2) == 0 && cp[2] == '=') {
+		for (cp += 3; *cp && *cp != ':'; wsp++, cp++) switch (*cp) {
+			    case '^':
+				*wsp = *++cp - '@';
+				break;
+
+			    case '\\':
+				switch (*++cp) {
+				    case 'E':
+					*wsp = '\033';
+					break;
+				    case 'n':
+					*wsp = '\n';
+					break;
+				    case 'r':
+					*wsp = '\r';
+					break;
+				    case 't':
+					*wsp = '\t';
+					break;
+				    case 'b':
+					*wsp = '\b';
+					break;
+				    case 'f':
+					*wsp = '\f';
+					break;
+				    case '0':
+				    case '1':
+				    case '2':
+				    case '3':
+					{
+						int i;
+						int t = 0;
+						for (i = 0; i < 3 &&
+						     isdigit(*cp); ++i, ++cp)
+							t = t * 8 + *cp - '0';
+						*wsp = t;
+						cp--;
+						break;
+					}
+				    default:
+					*wsp = *cp;
+				}
+				break;
+
+			    default:	*wsp = *cp;
+  			}
+
+		*wsp++ = '\0';
+
+		{
+			char *ret = *area;
+			*area = wsp;
+			return(ret);
+		}
+	}
+  }				/* end for(;;) */
+}
+
+
+
+/*
+ *	tgoto - given the cursor motion string cm, make up the string
+ *	for the cursor to go to (destcol, destline), and return the string.
+ *	Returns "OOPS" if something's gone wrong, or the string otherwise.
+ */
+
+char *tgoto(cm, destcol, destline)
+char *cm;
+int destcol;
+int destline;
+{
+  PRIVATE char ret[24];
+  char *rp = ret;
+  int incr = 0;
+  int argno = 0;
+  int numval;
+
+  for (; *cm; cm++) {
+	if (*cm == '%') {
+		switch (*++cm) {
+		    case 'i':	incr = 1;	  			break;
+
+		    case 'r':	argno = 1;	  			break;
+
+		    case '+':
+			numval = (argno == 0 ? destline : destcol);
+			*rp++ = numval + incr + *++cm;
+			argno = 1 - argno;
+			break;
+
+		    case '2':
+			numval = (argno == 0 ? destline : destcol);
+			numval = (numval + incr) % 100;
+			*rp++ = '0' + (numval / 10);
+			*rp++ = '0' + (numval % 10);
+			argno = 1 - argno;
+			break;
+
+		    case 'd':
+			numval = (argno == 0 ? destline : destcol);
+			numval = (numval + incr) % 1000;
+			if (numval > 99) *rp++ = '0' + (numval / 100);
+			if (numval > 9) *rp++ = '0' + (numval / 10) % 10;
+			*rp++ = '0' + (numval % 10);
+			argno = 1 - argno;
+			break;
+
+		    case '%':	*rp++ = '%';	  			break;
+
+		    default:	return("OOPS");
+  		}
+
+	} else
+		*rp++ = *cm;
+  }
+
+  *rp = '\0';
+  return(ret);
+}
+
+
+
+/*
+ *	tputs - put the string cp out onto the terminal, using the function
+ *	outc. This should do padding for the terminal, but I can't find a
+ *	terminal that needs padding at the moment...
+ */
+
+int tputs(cp, affcnt, outc)
+register char *cp;
+int affcnt;
+_PROTOTYPE( void (*outc), (int ch));
+{
+  if (cp == (char *)NULL) return(1);
+  /* Do any padding interpretation - left null for MINIX just now */
+  while (*cp) (*outc) (*cp++);
+  return(1);
+}
Index: /trunk/minix/lib/other/ttyname.c
===================================================================
--- /trunk/minix/lib/other/ttyname.c	(revision 9)
+++ /trunk/minix/lib/other/ttyname.c	(revision 9)
@@ -0,0 +1,53 @@
+/* ttyname.c						POSIX 4.7.2
+ *	char *ttyname(int fildes);
+ *
+ *	Determines name of a terminal device.
+ */
+
+#include <lib.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+
+PRIVATE char base[] = "/dev";
+PRIVATE char path[sizeof(base) + 1 + NAME_MAX];	/* extra 1 for '/' */
+
+PUBLIC char *ttyname(fildes)
+int fildes;
+{
+  DIR *devices;
+  struct dirent *entry;
+  struct stat tty_stat;
+  struct stat dev_stat;
+
+  /* Simple first test: file descriptor must be a character device */
+  if (fstat(fildes, &tty_stat) < 0 || !S_ISCHR(tty_stat.st_mode))
+	return (char *) NULL;
+
+  /* Open device directory for reading  */
+  if ((devices = opendir(base)) == (DIR *) NULL)
+	return (char *) NULL;
+
+  /* Scan the entries for one that matches perfectly */
+  while ((entry = readdir(devices)) != (struct dirent *) NULL) {
+	if (tty_stat.st_ino != entry->d_ino)
+		continue;
+	strcpy(path, base);
+	strcat(path, "/");
+	strcat(path, entry->d_name);
+	if (stat(path, &dev_stat) < 0 || !S_ISCHR(dev_stat.st_mode))
+		continue;
+	if (tty_stat.st_ino == dev_stat.st_ino &&
+	    tty_stat.st_dev == dev_stat.st_dev &&
+	    tty_stat.st_rdev == dev_stat.st_rdev) {
+		closedir(devices);
+		return path;
+	}
+  }
+
+  closedir(devices);
+  return (char *) NULL;
+}
Index: /trunk/minix/lib/other/ttyslot.c
===================================================================
--- /trunk/minix/lib/other/ttyslot.c	(revision 9)
+++ /trunk/minix/lib/other/ttyslot.c	(revision 9)
@@ -0,0 +1,62 @@
+/*
+ttyslot.c
+
+Return the index in the utmp file for the current user's terminal. The 
+current user's terminal is the first file descriptor in the range 0..2
+for which ttyname() returns a name. The index is the line number in the
+/etc/ttytab file. 0 will be returned in case of an error.
+
+Created:	Oct 11, 1992 by Philip Homburg
+*/
+
+#define _MINIX_SOURCE
+
+#include <sys/types.h>
+#include <ttyent.h>
+#include <string.h>
+#include <unistd.h>
+
+int ttyslot()
+{
+	int slot;
+
+	slot= fttyslot(0);
+	if (slot == 0) slot= fttyslot(1);
+	if (slot == 0) slot= fttyslot(2);
+	return slot;
+}
+
+int fttyslot(fd)
+int fd;
+{
+	char *tname;
+	int lineno;
+	struct ttyent *ttyp;
+
+	tname= ttyname(fd);
+	if (tname == NULL) return 0;
+
+	/* Assume that tty devices are in /dev */
+	if (strncmp(tname, "/dev/", 5) != 0)
+		return 0;	/* Malformed tty name. */
+	tname += 5;
+
+	/* Scan /etc/ttytab. */
+	lineno= 1;
+	while ((ttyp= getttyent()) != NULL)
+	{
+		if (strcmp(tname, ttyp->ty_name) == 0)
+		{
+			endttyent();
+			return lineno;
+		}
+		lineno++;
+	}
+	/* No match */
+	endttyent();
+	return 0;
+}
+
+/*
+ * $PchHeader: /mount/hd2/minix/lib/misc/RCS/ttyslot.c,v 1.3 1994/12/22 13:49:12 philip Exp $
+ */
Index: /trunk/minix/lib/other/un-namespace.h
===================================================================
--- /trunk/minix/lib/other/un-namespace.h	(revision 9)
+++ /trunk/minix/lib/other/un-namespace.h	(revision 9)
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2001 Daniel Eischen <deischen@FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libc/include/un-namespace.h,v 1.13 2003/05/01 19:03:13 nectar Exp $
+ */
+
+#ifndef _UN_NAMESPACE_H_
+#define _UN_NAMESPACE_H_
+
+#undef		accept
+#undef		__acl_aclcheck_fd
+#undef		__acl_delete_fd
+#undef		__acl_get_fd
+#undef		__acl_set_fd
+#undef		bind
+#undef		__cap_get_fd
+#undef		__cap_set_fd
+#undef		close
+#undef		connect
+#undef		dup
+#undef		dup2
+#undef		execve
+#undef		fcntl
+#undef		flock
+#undef		flockfile
+#undef		fpathconf
+#undef		fstat
+#undef		fstatfs
+#undef		fsync
+#undef		funlockfile
+#undef		getdirentries
+#undef		getlogin
+#undef		getpeername
+#undef		getprogname
+#undef		getsockname
+#undef		getsockopt
+#undef		ioctl
+#undef		kevent
+#undef		listen
+#undef		nanosleep
+#undef		open
+#undef		poll
+#undef		pthread_cond_broadcast
+#undef		pthread_cond_destroy
+#undef		pthread_cond_init
+#undef		pthread_cond_signal
+#undef		pthread_cond_timedwait
+#undef		pthread_cond_wait
+#undef		pthread_exit
+#undef		pthread_getspecific
+#undef		pthread_key_create
+#undef		pthread_key_delete
+#undef		pthread_main_np
+#undef		pthread_mutex_destroy
+#undef		pthread_mutex_init
+#undef		pthread_mutex_lock
+#undef		pthread_mutex_trylock
+#undef		pthread_mutex_unlock
+#undef		pthread_mutexattr_init
+#undef		pthread_mutexattr_destroy
+#undef		pthread_mutexattr_settype
+#undef		pthread_once
+#undef		pthread_rwlock_destroy
+#undef		pthread_rwlock_init
+#undef		pthread_rwlock_rdlock
+#undef		pthread_rwlock_wrlock
+#undef		pthread_rwlock_tryrdlock
+#undef		pthread_rwlock_trywrlock
+#undef		pthread_rwlock_unlock
+#undef		pthread_self
+#undef		pthread_setspecific
+#undef		pthread_sigmask
+#undef		read
+#undef		readv
+#undef		recvfrom
+#undef		recvmsg
+#undef		select
+#undef		sendmsg
+#undef		sendto
+#undef		setsockopt
+#undef		sigaction
+#undef		sigprocmask
+#undef		sigsuspend
+#undef		socket
+#undef		socketpair
+#undef		wait4
+#undef		waitpid
+#undef		write
+#undef		writev
+
+#if 0
+#undef		creat
+#undef		fchflags
+#undef		fchmod
+#undef		ftrylockfile
+#undef		msync
+#undef		nfssvc
+#undef		pause
+#undef		pthread_rwlockattr_init
+#undef		pthread_rwlockattr_destroy
+#undef		sched_yield
+#undef		sendfile
+#undef		shutdown
+#undef		sigaltstack
+#undef		sigpending
+#undef		sigreturn
+#undef		sigsetmask
+#undef		sleep
+#undef		system
+#undef		tcdrain
+#undef		wait
+#endif	/* 0 */
+
+#ifdef _SIGNAL_H_
+int     	_sigaction(int, const struct sigaction *, struct sigaction *);
+#endif
+
+#ifdef _SYS_EVENT_H_
+int		_kevent(int, const struct kevent *, int, struct kevent *,
+		    int, const struct timespec *);
+#endif
+
+#ifdef _SYS_FCNTL_H_
+int		_flock(int, int);
+#endif
+
+#undef		err
+#undef		warn
+#undef		nsdispatch
+
+#endif	/* _UN_NAMESPACE_H_ */
Index: /trunk/minix/lib/other/v8regerror.c
===================================================================
--- /trunk/minix/lib/other/v8regerror.c	(revision 9)
+++ /trunk/minix/lib/other/v8regerror.c	(revision 9)
@@ -0,0 +1,15 @@
+/*	regerror() - Default regexp error report	Author: Kees J. Bot
+ *								12 Jun 1999
+ *
+ * A better version of this routine should be supplied by the user in
+ * the program using regexps.
+ */
+#include <stdio.h>
+#define const		/* avoid "const poisoning" */
+#include <regexp.h>
+#undef const
+
+void regerror(char *message)
+{
+	fprintf(stderr, "regexp error: %s\n", message);
+}
Index: /trunk/minix/lib/other/v8regexp.c
===================================================================
--- /trunk/minix/lib/other/v8regexp.c	(revision 9)
+++ /trunk/minix/lib/other/v8regexp.c	(revision 9)
@@ -0,0 +1,1075 @@
+/* regcomp and regexec -- regsub and regerror are elsewhere
+ *
+ *	Copyright (c) 1986 by University of Toronto.
+ *	Written by Henry Spencer.  Not derived from licensed software.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to redistribute it freely,
+ *	subject to the following restrictions:
+ *
+ *	1. The author is not responsible for the consequences of use of
+ *		this software, no matter how awful, even if they arise
+ *		from defects in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *		by explicit claim or by omission.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *		be misrepresented as being the original software.
+ *
+ * Beware that some of this code is subtly aware of the way operator
+ * precedence is structured in regular expressions.  Serious changes in
+ * regular-expression syntax might require a total rethink.
+ *
+ *	The third parameter to regexec was added by Martin C. Atkins.
+ *	Andy Tanenbaum also made some changes.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#define const		/* avoid "const poisoning" */
+#include <regexp.h>
+#undef const
+
+/* The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte.
+ */
+#define	MAGIC	0234
+
+/* The "internal use only" fields in regexp.h are present to pass info from
+ * compile to execute that permits the execute phase to run lots faster on
+ * simple cases.  They are:
+ *
+ * regstart	char that must begin a match; '\0' if none obvious
+ * reganch	is the match anchored (at beginning-of-line only)?
+ * regmust	string (pointer into program) that match must include, or NULL
+ * regmlen	length of regmust string
+ *
+ * Regstart and reganch permit very fast decisions on suitable starting points
+ * for a match, cutting down the work a lot.  Regmust permits fast rejection
+ * of lines that cannot possibly match.  The regmust tests are costly enough
+ * that regcomp() supplies a regmust only if the r.e. contains something
+ * potentially expensive (at present, the only such thing detected is * or +
+ * at the start of the r.e., which can involve a lot of backup).  Regmlen is
+ * supplied because the test in regexec() needs it and regcomp() is computing
+ * it anyway.
+ */
+
+/* Structure for regexp "program".  This is essentially a linear encoding
+ * of a nondeterministic finite-state machine (aka syntax charts or
+ * "railroad normal form" in parsing technology).  Each node is an opcode
+ * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
+ * all nodes except BRANCH implement concatenation; a "next" pointer with
+ * a BRANCH on both ends of it is connecting two alternatives.  (Here we
+ * have one of the subtle syntax dependencies:  an individual BRANCH (as
+ * opposed to a collection of them) is never concatenated with anything
+ * because of operator precedence.)  The operand of some types of node is
+ * a literal string; for others, it is a node leading into a sub-FSM.  In
+ * particular, the operand of a BRANCH node is the first node of the branch.
+ * (NB this is *not* a tree structure:  the tail of the branch connects
+ * to the thing following the set of BRANCHes.)  The opcodes are:
+ */
+
+/* Definition	number	opnd?	meaning */
+#define	END	0		/* no	End of program. */
+#define	BOL	1		/* no	Match "" at beginning of line. */
+#define	EOL	2		/* no	Match "" at end of line. */
+#define	ANY	3		/* no	Match any one character. */
+#define	ANYOF	4		/* str	Match any character in this string. */
+#define	ANYBUT	5		/* str	Match any character not in this
+			 * string. */
+#define	BRANCH	6		/* node	Match this alternative, or the
+			 * next... */
+#define	BACK	7		/* no	Match "", "next" ptr points backward. */
+#define	EXACTLY	8		/* str	Match this string. */
+#define	NOTHING	9		/* no	Match empty string. */
+#define	STAR	10		/* node	Match this (simple) thing 0 or more
+			 * times. */
+#define	PLUS	11		/* node	Match this (simple) thing 1 or more
+			 * times. */
+#define	OPEN	20		/* no	Mark this point in input as start of
+			 * #n. */
+ /* OPEN+1 is number 1, etc. */
+#define	CLOSE	30		/* no	Analogous to OPEN. */
+
+/* Opcode notes:
+ *
+ * BRANCH	The set of branches constituting a single choice are hooked
+ *		together with their "next" pointers, since precedence prevents
+ *		anything being concatenated to any individual branch.  The
+ *		"next" pointer of the last BRANCH in a choice points to the
+ *		thing following the whole choice.  This is also where the
+ *		final "next" pointer of each individual branch points; each
+ *		branch starts with the operand node of a BRANCH node.
+ *
+ * BACK		Normal "next" pointers all implicitly point forward; BACK
+ *		exists to make loop structures possible.
+ *
+ * STAR,PLUS	'?', and complex '*' and '+', are implemented as circular
+ *		BRANCH structures using BACK.  Simple cases (one character
+ *		per match) are implemented with STAR and PLUS for speed
+ *		and to minimize recursive plunges.
+ *
+ * OPEN,CLOSE	...are numbered at compile time.
+ */
+
+/* A node is one char of opcode followed by two chars of "next" pointer.
+ * "Next" pointers are stored as two 8-bit pieces, high order first.  The
+ * value is a positive offset from the opcode of the node containing it.
+ * An operand, if any, simply follows the node.  (Note that much of the
+ * code generation knows about this implicit relationship.)
+ *
+ * Using two bytes for the "next" pointer is vast overkill for most things,
+ * but allows patterns to get big without disasters.
+ */
+#define	OP(p)	(*(p))
+#define	NEXT(p)	(((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
+#define	OPERAND(p)	((p) + 3)
+
+/* Utility definitions.
+ */
+#ifndef CHARBITS
+#define	UCHARAT(p)	((int)*(unsigned char *)(p))
+#else
+#define	UCHARAT(p)	((int)*(p)&CHARBITS)
+#endif
+
+#define	CFAIL(m)	{ regerror(m); return((char *)NULL); }
+#define	RFAIL(m)	{ regerror(m); return((regexp *)NULL); }
+#define	ISMULT(c)	((c) == '*' || (c) == '+' || (c) == '?')
+#define	META	"^$.[()|?+*\\"
+
+/* Flags to be passed up and down.
+ */
+#define	HASWIDTH	01	/* Known never to match null string. */
+#define	SIMPLE		02	/* Simple enough to be STAR/PLUS operand. */
+#define	SPSTART		04	/* Starts with * or +. */
+#define	WORST		0	/* Worst case. */
+
+/* Global work variables for regcomp().
+ */
+static char *regparse;		/* Input-scan pointer. */
+static int regnpar;		/* () count. */
+static char regdummy;
+static char *regcode;		/* Code-emit pointer; &regdummy = don't. */
+static long regsize;		/* Code size. */
+
+/* Forward declarations for regcomp()'s friends.
+ */
+static char *reg(int paren, int *flagp);
+static char *regbranch(int *flagp);
+static char *regpiece(int *flagp);
+static char *regatom(int *flagp);
+static char *regnode(int op);
+static char *regnext(char *p);
+static void regc(int b);
+static void reginsert(int op, char *opnd);
+static void regtail(char *p, char *val);
+static void regoptail(char *p, char *val);
+
+/*
+ - regcomp - compile a regular expression into internal code
+ *
+ * We can't allocate space until we know how big the compiled form will be,
+ * but we can't compile it (and thus know how big it is) until we've got a
+ * place to put the code.  So we cheat:  we compile it twice, once with code
+ * generation turned off and size counting turned on, and once "for real".
+ * This also means that we don't allocate space until we are sure that the
+ * thing really will compile successfully, and we never have to move the
+ * code and thus invalidate pointers into it.  (Note that it has to be in
+ * one piece because free() must be able to free it all.)
+ *
+ * Beware that the optimization-preparation code in here knows about some
+ * of the structure of the compiled regexp.
+ */
+regexp *regcomp(exp)
+char *exp;
+{
+  register regexp *r;
+  register char *scan;
+  register char *longest;
+  register int len;
+  int flags;
+
+  if (exp == (char *)NULL) RFAIL("NULL argument");
+
+  /* First pass: determine size, legality. */
+  regparse = exp;
+  regnpar = 1;
+  regsize = 0L;
+  regcode = &regdummy;
+  regc(MAGIC);
+  if (reg(0, &flags) == (char *)NULL) return((regexp *)NULL);
+
+  /* Small enough for pointer-storage convention? */
+  if (regsize >= 32767L)	/* Probably could be 65535L. */
+	RFAIL("regexp too big");
+
+  /* Allocate space. */
+  r = (regexp *) malloc(sizeof(regexp) + (unsigned) regsize);
+  if (r == (regexp *)NULL) RFAIL("out of space");
+
+  /* Second pass: emit code. */
+  regparse = exp;
+  regnpar = 1;
+  regcode = r->program;
+  regc(MAGIC);
+  if (reg(0, &flags) == (char *)NULL) return((regexp *)NULL);
+
+  /* Dig out information for optimizations. */
+  r->regstart = '\0';		/* Worst-case defaults. */
+  r->reganch = 0;
+  r->regmust = (char *)NULL;
+  r->regmlen = 0;
+  scan = r->program + 1;	/* First BRANCH. */
+  if (OP(regnext(scan)) == END) {	/* Only one top-level choice. */
+	scan = OPERAND(scan);
+
+	/* Starting-point info. */
+	if (OP(scan) == EXACTLY)
+		r->regstart = *OPERAND(scan);
+	else if (OP(scan) == BOL)
+		r->reganch++;
+
+	/* If there's something expensive in the r.e., find the
+	 * longest literal string that must appear and make it the
+	 * regmust.  Resolve ties in favor of later strings, since
+	 * the regstart check works with the beginning of the r.e.
+	 * and avoiding duplication strengthens checking.  Not a
+	 * strong reason, but sufficient in the absence of others. */
+	if (flags & SPSTART) {
+		longest = (char *)NULL;
+		len = 0;
+		for (; scan != (char *)NULL; scan = regnext(scan))
+			if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
+				longest = OPERAND(scan);
+				len = strlen(OPERAND(scan));
+			}
+		r->regmust = longest;
+		r->regmlen = len;
+	}
+  }
+  return(r);
+}
+
+/*
+ - reg - regular expression, i.e. main body or parenthesized thing
+ *
+ * Caller must absorb opening parenthesis.
+ *
+ * Combining parenthesis handling with the base level of regular expression
+ * is a trifle forced, but the need to tie the tails of the branches to what
+ * follows makes it hard to avoid.
+ */
+static char *reg(paren, flagp)
+int paren;			/* Parenthesized? */
+int *flagp;
+{
+  register char *ret;
+  register char *br;
+  register char *ender;
+  register int parno;
+  int flags;
+
+  *flagp = HASWIDTH;		/* Tentatively. */
+
+  /* Make an OPEN node, if parenthesized. */
+  if (paren) {
+	if (regnpar >= NSUBEXP) CFAIL("too many ()");
+	parno = regnpar;
+	regnpar++;
+	ret = regnode(OPEN + parno);
+  } else {
+	parno = 0;		/* not actually used, keep compiler quiet */
+	ret = (char *)NULL;
+  }
+
+  /* Pick up the branches, linking them together. */
+  br = regbranch(&flags);
+  if (br == (char *)NULL) return((char *)NULL);
+  if (ret != (char *)NULL)
+	regtail(ret, br);	/* OPEN -> first. */
+  else
+	ret = br;
+  if (!(flags & HASWIDTH)) *flagp &= ~HASWIDTH;
+  *flagp |= flags & SPSTART;
+  while (*regparse == '|') {
+	regparse++;
+	br = regbranch(&flags);
+	if (br == (char *)NULL) return((char *)NULL);
+	regtail(ret, br);	/* BRANCH -> BRANCH. */
+	if (!(flags & HASWIDTH)) *flagp &= ~HASWIDTH;
+	*flagp |= flags & SPSTART;
+  }
+
+  /* Make a closing node, and hook it on the end. */
+  ender = regnode((paren) ? CLOSE + parno : END);
+  regtail(ret, ender);
+
+  /* Hook the tails of the branches to the closing node. */
+  for (br = ret; br != (char *)NULL; br = regnext(br)) regoptail(br, ender);
+
+  /* Check for proper termination. */
+  if (paren && *regparse++ != ')') {
+	CFAIL("unmatched ()");
+  } else if (!paren && *regparse != '\0') {
+	if (*regparse == ')') {
+		CFAIL("unmatched ()");
+	} else
+		CFAIL("junk on end");	/* "Can't happen". */
+	/* NOTREACHED */
+  }
+  return(ret);
+}
+
+/*
+ - regbranch - one alternative of an | operator
+ *
+ * Implements the concatenation operator.
+ */
+static char *regbranch(flagp)
+int *flagp;
+{
+  register char *ret;
+  register char *chain;
+  register char *latest;
+  int flags;
+
+  *flagp = WORST;		/* Tentatively. */
+
+  ret = regnode(BRANCH);
+  chain = (char *)NULL;
+  while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
+	latest = regpiece(&flags);
+	if (latest == (char *)NULL) return((char *)NULL);
+	*flagp |= flags & HASWIDTH;
+	if (chain == (char *)NULL)	/* First piece. */
+		*flagp |= flags & SPSTART;
+	else
+		regtail(chain, latest);
+	chain = latest;
+  }
+  if (chain == (char *)NULL)		/* Loop ran zero times. */
+	regnode(NOTHING);
+
+  return(ret);
+}
+
+/*
+ - regpiece - something followed by possible [*+?]
+ *
+ * Note that the branching code sequences used for ? and the general cases
+ * of * and + are somewhat optimized:  they use the same NOTHING node as
+ * both the endmarker for their branch list and the body of the last branch.
+ * It might seem that this node could be dispensed with entirely, but the
+ * endmarker role is not redundant.
+ */
+static char *regpiece(flagp)
+int *flagp;
+{
+  register char *ret;
+  register char op;
+  register char *next;
+  int flags;
+
+  ret = regatom(&flags);
+  if (ret == (char *)NULL) return((char *)NULL);
+
+  op = *regparse;
+  if (!ISMULT(op)) {
+	*flagp = flags;
+	return(ret);
+  }
+  if (!(flags & HASWIDTH) && op != '?') CFAIL("*+ operand could be empty");
+  *flagp = (op != '+') ? (WORST | SPSTART) : (WORST | HASWIDTH);
+
+  if (op == '*' && (flags & SIMPLE))
+	reginsert(STAR, ret);
+  else if (op == '*') {
+	/* Emit x* as (x&|), where & means "self". */
+	reginsert(BRANCH, ret);	/* Either x */
+	regoptail(ret, regnode(BACK));	/* and loop */
+	regoptail(ret, ret);	/* back */
+	regtail(ret, regnode(BRANCH));	/* or */
+	regtail(ret, regnode(NOTHING));	/* null. */
+  } else if (op == '+' && (flags & SIMPLE))
+	reginsert(PLUS, ret);
+  else if (op == '+') {
+	/* Emit x+ as x(&|), where & means "self". */
+	next = regnode(BRANCH);	/* Either */
+	regtail(ret, next);
+	regtail(regnode(BACK), ret);	/* loop back */
+	regtail(next, regnode(BRANCH));	/* or */
+	regtail(ret, regnode(NOTHING));	/* null. */
+  } else if (op == '?') {
+	/* Emit x? as (x|) */
+	reginsert(BRANCH, ret);	/* Either x */
+	regtail(ret, regnode(BRANCH));	/* or */
+	next = regnode(NOTHING);/* null. */
+	regtail(ret, next);
+	regoptail(ret, next);
+  }
+  regparse++;
+  if (ISMULT(*regparse)) CFAIL("nested *?+");
+
+  return(ret);
+}
+
+/*
+ - regatom - the lowest level
+ *
+ * Optimization:  gobbles an entire sequence of ordinary characters so that
+ * it can turn them into a single node, which is smaller to store and
+ * faster to run.  Backslashed characters are exceptions, each becoming a
+ * separate node; the code is simpler that way and it's not worth fixing.
+ */
+static char *regatom(flagp)
+int *flagp;
+{
+  register char *ret;
+  int flags;
+
+  *flagp = WORST;		/* Tentatively. */
+
+  switch (*regparse++) {
+      case '^':	ret = regnode(BOL);	  	break;
+      case '$':	ret = regnode(EOL);	  	break;
+      case '.':
+	ret = regnode(ANY);
+	*flagp |= HASWIDTH | SIMPLE;
+	break;
+      case '[':{
+		register int class;
+		register int classend;
+
+		if (*regparse == '^') {	/* Complement of range. */
+			ret = regnode(ANYBUT);
+			regparse++;
+		} else
+			ret = regnode(ANYOF);
+		if (*regparse == ']' || *regparse == '-') regc(*regparse++);
+		while (*regparse != '\0' && *regparse != ']') {
+			if (*regparse == '-') {
+				regparse++;
+				if (*regparse == ']' || *regparse == '\0')
+					regc('-');
+				else {
+					class = UCHARAT(regparse - 2) + 1;
+					classend = UCHARAT(regparse);
+					if (class > classend + 1)
+						CFAIL("invalid [] range");
+					for (; class <= classend; class++)
+						regc(class);
+					regparse++;
+				}
+			} else
+				regc(*regparse++);
+		}
+		regc('\0');
+		if (*regparse != ']') CFAIL("unmatched []");
+		regparse++;
+		*flagp |= HASWIDTH | SIMPLE;
+	}
+	break;
+      case '(':
+	ret = reg(1, &flags);
+	if (ret == (char *)NULL) return((char *)NULL);
+	*flagp |= flags & (HASWIDTH | SPSTART);
+	break;
+      case '\0':
+      case '|':
+      case ')':
+	CFAIL("internal urp");	/* Supposed to be caught earlier. */
+	break;
+      case '?':
+      case '+':
+      case '*':	CFAIL("?+* follows nothing");	  	break;
+      case '\\':
+	if (*regparse == '\0') CFAIL("trailing \\");
+	ret = regnode(EXACTLY);
+	regc(*regparse++);
+	regc('\0');
+	*flagp |= HASWIDTH | SIMPLE;
+	break;
+      default:{
+		register int len;
+		register char ender;
+
+		regparse--;
+		len = strcspn(regparse, META);
+		if (len <= 0) CFAIL("internal disaster");
+		ender = *(regparse + len);
+		if (len > 1 && ISMULT(ender))
+			len--;	/* Back off clear of ?+* operand. */
+		*flagp |= HASWIDTH;
+		if (len == 1) *flagp |= SIMPLE;
+		ret = regnode(EXACTLY);
+		while (len > 0) {
+			regc(*regparse++);
+			len--;
+		}
+		regc('\0');
+	}
+	break;
+  }
+
+  return(ret);
+}
+
+/*
+ - regnode - emit a node
+ */
+static char *regnode(op)
+char op;
+{
+  register char *ret;
+  register char *ptr;
+
+  ret = regcode;
+  if (ret == &regdummy) {
+	regsize += 3;
+	return(ret);
+  }
+  ptr = ret;
+  *ptr++ = op;
+  *ptr++ = '\0';		/* Null "next" pointer. */
+  *ptr++ = '\0';
+  regcode = ptr;
+
+  return(ret);
+}
+
+/*
+ - regc - emit (if appropriate) a byte of code
+ */
+static void regc(b)
+char b;
+{
+  if (regcode != &regdummy)
+	*regcode++ = b;
+  else
+	regsize++;
+}
+
+/*
+ - reginsert - insert an operator in front of already-emitted operand
+ *
+ * Means relocating the operand.
+ */
+static void reginsert(op, opnd)
+char op;
+char *opnd;
+{
+  register char *src;
+  register char *dst;
+  register char *place;
+
+  if (regcode == &regdummy) {
+	regsize += 3;
+	return;
+  }
+  src = regcode;
+  regcode += 3;
+  dst = regcode;
+  while (src > opnd) *--dst = *--src;
+
+  place = opnd;			/* Op node, where operand used to be. */
+  *place++ = op;
+  *place++ = '\0';
+  *place++ = '\0';
+}
+
+/*
+ - regtail - set the next-pointer at the end of a node chain
+ */
+static void regtail(p, val)
+char *p;
+char *val;
+{
+  register char *scan;
+  register char *temp;
+  register int offset;
+
+  if (p == &regdummy) return;
+
+  /* Find last node. */
+  scan = p;
+  for (;;) {
+	temp = (char *)regnext(scan);
+	if (temp == (char *)NULL) break;
+	scan = temp;
+  }
+
+  if (OP(scan) == BACK)
+	offset = scan - val;
+  else
+	offset = val - scan;
+  *(scan + 1) = (offset >> 8) & 0377;
+  *(scan + 2) = offset & 0377;
+}
+
+/*
+ - regoptail - regtail on operand of first argument; nop if operandless
+ */
+static void regoptail(p, val)
+char *p;
+char *val;
+{
+  /* "Operandless" and "op != BRANCH" are synonymous in practice. */
+  if (p == (char *)NULL || p == &regdummy || OP(p) != BRANCH) return;
+  regtail(OPERAND(p), val);
+}
+
+/* regexec and friends
+ */
+
+/* Global work variables for regexec().
+ */
+static char *reginput;		/* String-input pointer. */
+static char *regbol;		/* Beginning of input, for ^ check. */
+static char **regstartp;	/* Pointer to startp array. */
+static char **regendp;		/* Ditto for endp. */
+
+/* Forwards.
+ */
+static int regtry(regexp *prog, char *string);
+static int regmatch(char *prog);
+static int regrepeat(char *p);
+
+#ifdef DEBUG
+int regnarrate = 0;
+void regdump();
+static char *regprop(char *op);
+#endif
+
+/*
+ - regexec - match a regexp against a string
+ */
+int regexec(prog, string, bolflag)
+register regexp *prog;
+register char *string;
+int bolflag;
+{
+  register char *s;
+
+  /* Be paranoid... */
+  if (prog == (regexp *)NULL || string == (char *)NULL) {
+	regerror("NULL parameter");
+	return(0);
+  }
+
+  /* Check validity of program. */
+  if (UCHARAT(prog->program) != MAGIC) {
+	regerror("corrupted program");
+	return(0);
+  }
+
+  /* If there is a "must appear" string, look for it. */
+  if (prog->regmust != (char *)NULL) {
+	s = string;
+	while ((s = strchr(s, prog->regmust[0])) != (char *)NULL) {
+		if (strncmp(s, prog->regmust, prog->regmlen) == 0)
+			break;	/* Found it. */
+		s++;
+	}
+	if (s == (char *)NULL)		/* Not present. */
+		return(0);
+  }
+
+  /* Mark beginning of line for ^ . */
+  if (bolflag)
+	regbol = string;
+  else
+	regbol = (char *)NULL;
+
+  /* Simplest case:  anchored match need be tried only once. */
+  if (prog->reganch) return(regtry(prog, string));
+
+  /* Messy cases:  unanchored match. */
+  s = string;
+  if (prog->regstart != '\0') 	/* We know what char it must start with. */
+	while ((s = strchr(s, prog->regstart)) != (char *)NULL) {
+		if (regtry(prog, s)) return(1);
+		s++;
+	}
+  else
+	/* We don't -- general case. */
+	do {
+		if (regtry(prog, s)) return(1);
+	} while (*s++ != '\0');
+
+  /* Failure. */
+  return(0);
+}
+
+/*
+ - regtry - try match at specific point
+ */
+static int regtry(prog, string)   /* 0 failure, 1 success */
+regexp *prog;
+char *string;
+{
+  register int i;
+  register char **sp;
+  register char **ep;
+
+  reginput = string;
+  regstartp = prog->startp;
+  regendp = prog->endp;
+
+  sp = prog->startp;
+  ep = prog->endp;
+  for (i = NSUBEXP; i > 0; i--) {
+	*sp++ = (char *)NULL;
+	*ep++ = (char *)NULL;
+  }
+  if (regmatch(prog->program + 1)) {
+	prog->startp[0] = string;
+	prog->endp[0] = reginput;
+	return(1);
+  } else
+	return(0);
+}
+
+/*
+ - regmatch - main matching routine
+ *
+ * Conceptually the strategy is simple:  check to see whether the current
+ * node matches, call self recursively to see whether the rest matches,
+ * and then act accordingly.  In practice we make some effort to avoid
+ * recursion, in particular by going through "ordinary" nodes (that don't
+ * need to know whether the rest of the match failed) by a loop instead of
+ * by recursion.
+ */
+static int regmatch(prog)	/* 0 failure, 1 success */ 
+char *prog;
+{
+  register char *scan;		/* Current node. */
+  char *next;			/* Next node. */
+
+  scan = prog;
+#ifdef DEBUG
+  if (scan != (char *)NULL && regnarrate) fprintf(stderr, "%s(\n", regprop(scan));
+#endif
+  while (scan != (char *)NULL) {
+#ifdef DEBUG
+	if (regnarrate) fprintf(stderr, "%s...\n", regprop(scan));
+#endif
+	next = regnext(scan);
+
+	switch (OP(scan)) {
+	    case BOL:
+		if (reginput != regbol) return(0);
+		break;
+	    case EOL:
+		if (*reginput != '\0') return(0);
+		break;
+	    case ANY:
+		if (*reginput == '\0') return(0);
+		reginput++;
+		break;
+	    case EXACTLY:{
+			register int len;
+			register char *opnd;
+
+			opnd = OPERAND(scan);
+			/* Inline the first character, for speed. */
+			if (*opnd != *reginput) return(0);
+			len = strlen(opnd);
+			if (len > 1 && strncmp(opnd, reginput, len) != 0)
+				return(0);
+			reginput += len;
+		}
+		break;
+	    case ANYOF:
+		if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == (char *)NULL)
+			return(0);
+		reginput++;
+		break;
+	    case ANYBUT:
+		if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != (char *)NULL)
+			return(0);
+		reginput++;
+		break;
+	    case NOTHING:
+		break;
+	    case BACK:
+		break;
+	    case OPEN + 1:
+	    case OPEN + 2:
+	    case OPEN + 3:
+	    case OPEN + 4:
+	    case OPEN + 5:
+	    case OPEN + 6:
+	    case OPEN + 7:
+	    case OPEN + 8:
+	    case OPEN + 9:{
+			register int no;
+			register char *save;
+
+			no = OP(scan) - OPEN;
+			save = reginput;
+
+			if (regmatch(next)) {
+				/* Don't set startp if some later
+				 * invocation of the same parentheses
+				 * already has. */
+				if (regstartp[no] == (char *)NULL)
+					regstartp[no] = save;
+				return(1);
+			} else
+				return(0);
+		}
+		break;
+	    case CLOSE + 1:
+	    case CLOSE + 2:
+	    case CLOSE + 3:
+	    case CLOSE + 4:
+	    case CLOSE + 5:
+	    case CLOSE + 6:
+	    case CLOSE + 7:
+	    case CLOSE + 8:
+	    case CLOSE + 9:{
+			register int no;
+			register char *save;
+
+			no = OP(scan) - CLOSE;
+			save = reginput;
+
+			if (regmatch(next)) {
+				/* Don't set endp if some later
+				 * invocation of the same parentheses
+				 * already has. */
+				if (regendp[no] == (char *)NULL) regendp[no] = save;
+				return(1);
+			} else
+				return(0);
+		}
+		break;
+	    case BRANCH:{
+			register char *save;
+
+			if (OP(next) != BRANCH)	/* No choice. */
+				next = OPERAND(scan);	/* Avoid recursion. */
+			else {
+				do {
+					save = reginput;
+					if (regmatch(OPERAND(scan)))
+						return(1);
+					reginput = save;
+					scan = regnext(scan);
+				} while (scan != (char *)NULL && OP(scan) == BRANCH);
+				return(0);
+				/* NOTREACHED */
+			}
+		}
+		break;
+	    case STAR:
+	    case PLUS:{
+			register char nextch;
+			register int no;
+			register char *save;
+			register int min;
+
+			/* Lookahead to avoid useless match attempts
+			 * when we know what character comes next. */
+			nextch = '\0';
+			if (OP(next) == EXACTLY) nextch = *OPERAND(next);
+			min = (OP(scan) == STAR) ? 0 : 1;
+			save = reginput;
+			no = regrepeat(OPERAND(scan));
+			while (no >= min) {
+				/* If it could work, try it. */
+				if (nextch == '\0' || *reginput == nextch)
+					if (regmatch(next)) return(1);
+				/* Couldn't or didn't -- back up. */
+				no--;
+				reginput = save + no;
+			}
+			return(0);
+		}
+		break;
+	    case END:
+		return(1);	/* Success! */
+		break;
+	    default:
+		regerror("memory corruption");
+		return(0);
+		break;
+	}
+
+	scan = next;
+  }
+
+  /* We get here only if there's trouble -- normally "case END" is the
+   * terminating point. */
+  regerror("corrupted pointers");
+  return(0);
+}
+
+/*
+ - regrepeat - repeatedly match something simple, report how many
+ */
+static int regrepeat(p)
+char *p;
+{
+  register int count = 0;
+  register char *scan;
+  register char *opnd;
+
+  scan = reginput;
+  opnd = OPERAND(p);
+  switch (OP(p)) {
+      case ANY:
+	count = strlen(scan);
+	scan += count;
+	break;
+      case EXACTLY:
+	while (*opnd == *scan) {
+		count++;
+		scan++;
+	}
+	break;
+      case ANYOF:
+	while (*scan != '\0' && strchr(opnd, *scan) != (char *)NULL) {
+		count++;
+		scan++;
+	}
+	break;
+      case ANYBUT:
+	while (*scan != '\0' && strchr(opnd, *scan) == (char *)NULL) {
+		count++;
+		scan++;
+	}
+	break;
+      default:			/* Oh dear.  Called inappropriately. */
+	regerror("internal foulup");
+	count = 0;		/* Best compromise. */
+	break;
+  }
+  reginput = scan;
+
+  return(count);
+}
+
+/*
+ - regnext - dig the "next" pointer out of a node
+ */
+static char *regnext(p)
+register char *p;
+{
+  register int offset;
+
+  if (p == &regdummy) return((char *)NULL);
+
+  offset = NEXT(p);
+  if (offset == 0) return((char *)NULL);
+
+  if (OP(p) == BACK)
+	return(p - offset);
+  else
+	return(p + offset);
+}
+
+#ifdef DEBUG
+
+static char *regprop();
+
+/*
+ - regdump - dump a regexp onto stdout in vaguely comprehensible form
+ */
+void regdump(r)
+regexp *r;
+{
+  register char *s;
+  register char op = EXACTLY;	/* Arbitrary non-END op. */
+  register char *next;
+
+  s = r->program + 1;
+  while (op != END) {		/* While that wasn't END last time... */
+	op = OP(s);
+	printf("%2d%s", (int) (s - r->program), regprop(s));	/* Where, what. */
+	next = regnext(s);
+	if (next == (char *)NULL)	/* Next ptr. */
+		printf("(0)");
+	else
+		printf("(%d)", (int) (s - r->program) + (int) (next - s));
+	s += 3;
+	if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
+		/* Literal string, where present. */
+		while (*s != '\0') {
+			putchar(*s);
+			s++;
+		}
+		s++;
+	}
+	putchar('\n');
+  }
+
+  /* Header fields of interest. */
+  if (r->regstart != '\0') printf("start `%c' ", r->regstart);
+  if (r->reganch) printf("anchored ");
+  if (r->regmust != (char *)NULL) printf("must have \"%s\"", r->regmust);
+  printf("\n");
+}
+
+/*
+ - regprop - printable representation of opcode
+ */
+static char *regprop(op)
+char *op;
+{
+  register char *p;
+  static char buf[50];
+
+  (void) strcpy(buf, ":");
+
+  switch (OP(op)) {
+      case BOL:	p = "BOL";	  	break;
+      case EOL:	p = "EOL";	  	break;
+      case ANY:	p = "ANY";	  	break;
+      case ANYOF:	p = "ANYOF";	  	break;
+      case ANYBUT:	p = "ANYBUT";	  	break;
+      case BRANCH:	p = "BRANCH";	  	break;
+      case EXACTLY:	p = "EXACTLY";	  	break;
+      case NOTHING:	p = "NOTHING";	  	break;
+      case BACK:	p = "BACK";	  	break;
+      case END:	p = "END";	  	break;
+      case OPEN + 1:
+      case OPEN + 2:
+      case OPEN + 3:
+      case OPEN + 4:
+      case OPEN + 5:
+      case OPEN + 6:
+      case OPEN + 7:
+      case OPEN + 8:
+      case OPEN + 9:
+	sprintf(buf + strlen(buf), "OPEN%d", OP(op) - OPEN);
+	p = (char *)NULL;
+	break;
+      case CLOSE + 1:
+      case CLOSE + 2:
+      case CLOSE + 3:
+      case CLOSE + 4:
+      case CLOSE + 5:
+      case CLOSE + 6:
+      case CLOSE + 7:
+      case CLOSE + 8:
+      case CLOSE + 9:
+	sprintf(buf + strlen(buf), "CLOSE%d", OP(op) - CLOSE);
+	p = (char *)NULL;
+	break;
+      case STAR:	p = "STAR";	  	break;
+      case PLUS:	p = "PLUS";	  	break;
+      default:	regerror("corrupted opcode"); p = (char *) NULL; break;
+  }
+  if (p != (char *)NULL) (void) strcat(buf, p);
+  return(buf);
+}
+
+#endif
+
+/*
+ * $PchId: regexp.c,v 1.4 1996/02/22 09:03:07 philip Exp $
+ */
Index: /trunk/minix/lib/other/v8regsub.c
===================================================================
--- /trunk/minix/lib/other/v8regsub.c	(revision 9)
+++ /trunk/minix/lib/other/v8regsub.c	(revision 9)
@@ -0,0 +1,90 @@
+/* regsub
+ *
+ *	Copyright (c) 1986 by University of Toronto.
+ *	Written by Henry Spencer.  Not derived from licensed software.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to redistribute it freely,
+ *	subject to the following restrictions:
+ *
+ *	1. The author is not responsible for the consequences of use of
+ *		this software, no matter how awful, even if they arise
+ *		from defects in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *		by explicit claim or by omission.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *		be misrepresented as being the original software.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#define const		/* avoid "const poisoning" */
+#include <regexp.h>
+#undef const
+
+/* The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte.
+ */
+#define	MAGIC	0234
+
+#define CHARBITS 0377
+#ifndef CHARBITS
+#define	UCHARAT(p)	((int)*(unsigned char *)(p))
+#else
+#define	UCHARAT(p)	((int)*(p)&CHARBITS)
+#endif
+
+/*
+ - regsub - perform substitutions after a regexp match
+ */
+void regsub(prog, source, dest)
+regexp *prog;
+char *source;
+char *dest;
+{
+  register char *src;
+  register char *dst;
+  register char c;
+  register int no;
+  register int len;
+
+  if (prog == (regexp *)NULL || source == (char *)NULL || dest == (char *)NULL) {
+	regerror("NULL parm to regsub");
+	return;
+  }
+  if (UCHARAT(prog->program) != MAGIC) {
+	regerror("damaged regexp fed to regsub");
+	return;
+  }
+  src = source;
+  dst = dest;
+  while ((c = *src++) != '\0') {
+	if (c == '&')
+		no = 0;
+	else if (c == '\\' && '0' <= *src && *src <= '9')
+		no = *src++ - '0';
+	else
+		no = -1;
+
+	if (no < 0) {		/* Ordinary character. */
+		if (c == '\\' && (*src == '\\' || *src == '&')) c = *src++;
+		*dst++ = c;
+	} else
+	if (prog->startp[no] != (char *)NULL && prog->endp[no] != (char *)NULL) {
+		len = (int) (prog->endp[no] - prog->startp[no]);
+		strncpy(dst, prog->startp[no], len);
+		dst += len;
+		if (len != 0 && *(dst - 1) == '\0') {	/* strncpy hit NUL. */
+			regerror("damaged match string");
+			return;
+		}
+	}
+  }
+  *dst++ = '\0';
+}
+
+/*
+ * $PchId: regsub.c,v 1.3 1995/11/27 20:18:16 philip Exp $
+ */
Index: /trunk/minix/lib/other/writev.c
===================================================================
--- /trunk/minix/lib/other/writev.c	(revision 9)
+++ /trunk/minix/lib/other/writev.c	(revision 9)
@@ -0,0 +1,39 @@
+#include <errno.h>
+#include <stdio.h>
+#include <sys/uio.h>
+
+ssize_t writev(int fildes, const struct iovec *iov, int iovcnt)
+{
+#if DEBUG
+	fprintf(stderr, "bind: not implemented for fd %d\n", socket);
+#endif
+	errno= ENOSYS;
+	return -1;
+
+#if 0
+	int i, r;
+	char *p;
+	ssize_t l, sum;
+
+	/* We should buffer */
+	sum= 0;
+	for (i= 0; i<iovcnt; i++)
+	{
+		p= iov[i].iov_base;
+		l= iov[i].iov_len;
+		while (l > 0)
+		{
+			r= write(fildes, p, l);
+			if (r <= 0)
+			{
+				assert(sum == 0);
+				return r;
+			}
+			p += r;
+			l -= r;
+			sum += r;
+		}
+	}
+	return sum;
+#endif
+}
Index: /trunk/minix/lib/posix/Makedepend-ack
===================================================================
--- /trunk/minix/lib/posix/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/posix/Makedepend-ack	(revision 9)
@@ -0,0 +1,100 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' __exit.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _access.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _alarm.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _cfgetispeed.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _cfgetospeed.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _cfsetispeed.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _cfsetospeed.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _chdir.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _chmod.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _chown.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _chroot.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _close.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _closedir.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _creat.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _dup.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _dup2.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _execl.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _execle.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _execlp.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _execv.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _execve.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _execvp.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _fcntl.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _fork.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _fpathconf.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _fstat.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _fstatfs.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _fsync.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _getcwd.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _getegid.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _geteuid.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _getgid.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _getgroups.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _getpgrp.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _getpid.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _getppid.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _getuid.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _ioctl.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _isatty.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _kill.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _link.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _lseek.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _lstat.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _mkdir.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _mkfifo.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _mknod.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _mount.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _open.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _opendir.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _pathconf.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _pause.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _pipe.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _ptrace.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _read.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _readdir.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _readlink.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _rename.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _rewinddir.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _rmdir.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _select.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _setgid.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _setsid.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _setuid.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _sigaction.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _sigpending.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _sigprocmask.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _sigreturn.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _sigset.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _sigsetjmp.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _sigsuspend.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _sleep.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _stat.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _stime.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _symlink.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _sync.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _tcdrain.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _tcflow.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _tcflush.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _tcgetattr.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _tcsendbreak.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _tcsetattr.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _time.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _times.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _truncate.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _umask.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _umount.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _uname.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _unlink.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _utime.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _wait.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _waitpid.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' _write.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' getloadavg.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' getopt.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' gettimeofday.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' priority.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' usleep.c | sed -e 's:^\(.\):../obj-ack//./posix/\1:' >> .depend-ack
Index: /trunk/minix/lib/posix/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/posix/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/posix/Makedepend-gnu	(revision 9)
@@ -0,0 +1,100 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' __exit.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _access.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _alarm.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _cfgetispeed.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _cfgetospeed.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _cfsetispeed.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _cfsetospeed.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _chdir.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _chmod.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _chown.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _chroot.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _close.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _closedir.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _creat.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _dup.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _dup2.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _execl.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _execle.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _execlp.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _execv.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _execve.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _execvp.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _fcntl.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _fork.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _fpathconf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _fstat.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _fstatfs.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _fsync.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _getcwd.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _getegid.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _geteuid.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _getgid.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _getgroups.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _getpgrp.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _getpid.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _getppid.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _getuid.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _ioctl.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _isatty.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _kill.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _link.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _lseek.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _lstat.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _mkdir.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _mkfifo.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _mknod.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _mount.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _open.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _opendir.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _pathconf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _pause.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _pipe.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _ptrace.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _read.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _readdir.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _readlink.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _rename.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _rewinddir.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _rmdir.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _select.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _setgid.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _setsid.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _setuid.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _sigaction.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _sigpending.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _sigprocmask.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _sigreturn.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _sigset.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _sigsetjmp.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _sigsuspend.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _sleep.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _stat.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _stime.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _symlink.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _sync.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _tcdrain.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _tcflow.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _tcflush.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _tcgetattr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _tcsendbreak.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _tcsetattr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _time.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _times.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _truncate.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _umask.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _umount.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _uname.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _unlink.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _utime.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _wait.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _waitpid.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' _write.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' getloadavg.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' getopt.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' gettimeofday.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' priority.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' usleep.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./posix/\1:' >> .depend-gnu
Index: /trunk/minix/lib/posix/Makefile
===================================================================
--- /trunk/minix/lib/posix/Makefile	(revision 9)
+++ /trunk/minix/lib/posix/Makefile	(revision 9)
@@ -0,0 +1,724 @@
+#Generated from ./posix/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./posix ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./posix ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libc.a
+
+../obj-ack//libc.a: ../obj-ack//libc.a(__exit.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_access.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_alarm.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_cfgetispeed.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_cfgetospeed.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_cfsetispeed.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_cfsetospeed.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_chdir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_chmod.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_chown.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_chroot.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_close.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_closedir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_creat.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_dup.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_dup2.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_execl.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_execle.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_execlp.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_execv.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_execve.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_execvp.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_fcntl.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_fork.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_fpathconf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_fstat.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_fstatfs.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_fsync.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_getcwd.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_getegid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_geteuid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_getgid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_getgroups.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_getpgrp.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_getpid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_getppid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_getuid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_ioctl.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_isatty.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_kill.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_link.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_lseek.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_lstat.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_mkdir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_mkfifo.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_mknod.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_mount.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_open.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_opendir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_pathconf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_pause.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_pipe.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_ptrace.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_read.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_readdir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_readlink.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_rename.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_rewinddir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_rmdir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_select.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_setgid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_setsid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_setuid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_sigaction.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_sigpending.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_sigprocmask.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_sigreturn.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_sigset.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_sigsetjmp.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_sigsuspend.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_sleep.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_stat.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_stime.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_symlink.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_sync.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_tcdrain.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_tcflow.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_tcflush.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_tcgetattr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_tcsendbreak.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_tcsetattr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_time.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_times.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_truncate.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_umask.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_umount.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_uname.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_unlink.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_utime.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_wait.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_waitpid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_write.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getloadavg.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getopt.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(gettimeofday.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(priority.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(usleep.o)
+
+../obj-ack//libc.a:
+	ar cr ../obj-ack//libc.a ../obj-ack//./posix/*.o
+	rm ../obj-ack//./posix/*.o
+
+../obj-ack//libc.a(__exit.o): __exit.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/__exit.o __exit.c
+../obj-ack//libc.a(_access.o): _access.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_access.o _access.c
+../obj-ack//libc.a(_alarm.o): _alarm.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_alarm.o _alarm.c
+../obj-ack//libc.a(_cfgetispeed.o): _cfgetispeed.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_cfgetispeed.o _cfgetispeed.c
+../obj-ack//libc.a(_cfgetospeed.o): _cfgetospeed.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_cfgetospeed.o _cfgetospeed.c
+../obj-ack//libc.a(_cfsetispeed.o): _cfsetispeed.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_cfsetispeed.o _cfsetispeed.c
+../obj-ack//libc.a(_cfsetospeed.o): _cfsetospeed.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_cfsetospeed.o _cfsetospeed.c
+../obj-ack//libc.a(_chdir.o): _chdir.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_chdir.o _chdir.c
+../obj-ack//libc.a(_chmod.o): _chmod.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_chmod.o _chmod.c
+../obj-ack//libc.a(_chown.o): _chown.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_chown.o _chown.c
+../obj-ack//libc.a(_chroot.o): _chroot.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_chroot.o _chroot.c
+../obj-ack//libc.a(_close.o): _close.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_close.o _close.c
+../obj-ack//libc.a(_closedir.o): _closedir.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_closedir.o _closedir.c
+../obj-ack//libc.a(_creat.o): _creat.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_creat.o _creat.c
+../obj-ack//libc.a(_dup.o): _dup.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_dup.o _dup.c
+../obj-ack//libc.a(_dup2.o): _dup2.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_dup2.o _dup2.c
+../obj-ack//libc.a(_execl.o): _execl.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_execl.o _execl.c
+../obj-ack//libc.a(_execle.o): _execle.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_execle.o _execle.c
+../obj-ack//libc.a(_execlp.o): _execlp.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_execlp.o _execlp.c
+../obj-ack//libc.a(_execv.o): _execv.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_execv.o _execv.c
+../obj-ack//libc.a(_execve.o): _execve.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_execve.o _execve.c
+../obj-ack//libc.a(_execvp.o): _execvp.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_execvp.o _execvp.c
+../obj-ack//libc.a(_fcntl.o): _fcntl.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_fcntl.o _fcntl.c
+../obj-ack//libc.a(_fork.o): _fork.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_fork.o _fork.c
+../obj-ack//libc.a(_fpathconf.o): _fpathconf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_fpathconf.o _fpathconf.c
+../obj-ack//libc.a(_fstat.o): _fstat.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_fstat.o _fstat.c
+../obj-ack//libc.a(_fstatfs.o): _fstatfs.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_fstatfs.o _fstatfs.c
+../obj-ack//libc.a(_fsync.o): _fsync.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_fsync.o _fsync.c
+../obj-ack//libc.a(_getcwd.o): _getcwd.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_getcwd.o _getcwd.c
+../obj-ack//libc.a(_getegid.o): _getegid.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_getegid.o _getegid.c
+../obj-ack//libc.a(_geteuid.o): _geteuid.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_geteuid.o _geteuid.c
+../obj-ack//libc.a(_getgid.o): _getgid.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_getgid.o _getgid.c
+../obj-ack//libc.a(_getgroups.o): _getgroups.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_getgroups.o _getgroups.c
+../obj-ack//libc.a(_getpgrp.o): _getpgrp.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_getpgrp.o _getpgrp.c
+../obj-ack//libc.a(_getpid.o): _getpid.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_getpid.o _getpid.c
+../obj-ack//libc.a(_getppid.o): _getppid.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_getppid.o _getppid.c
+../obj-ack//libc.a(_getuid.o): _getuid.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_getuid.o _getuid.c
+../obj-ack//libc.a(_ioctl.o): _ioctl.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_ioctl.o _ioctl.c
+../obj-ack//libc.a(_isatty.o): _isatty.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_isatty.o _isatty.c
+../obj-ack//libc.a(_kill.o): _kill.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_kill.o _kill.c
+../obj-ack//libc.a(_link.o): _link.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_link.o _link.c
+../obj-ack//libc.a(_lseek.o): _lseek.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_lseek.o _lseek.c
+../obj-ack//libc.a(_lstat.o): _lstat.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_lstat.o _lstat.c
+../obj-ack//libc.a(_mkdir.o): _mkdir.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_mkdir.o _mkdir.c
+../obj-ack//libc.a(_mkfifo.o): _mkfifo.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_mkfifo.o _mkfifo.c
+../obj-ack//libc.a(_mknod.o): _mknod.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_mknod.o _mknod.c
+../obj-ack//libc.a(_mount.o): _mount.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_mount.o _mount.c
+../obj-ack//libc.a(_open.o): _open.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_open.o _open.c
+../obj-ack//libc.a(_opendir.o): _opendir.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_opendir.o _opendir.c
+../obj-ack//libc.a(_pathconf.o): _pathconf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_pathconf.o _pathconf.c
+../obj-ack//libc.a(_pause.o): _pause.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_pause.o _pause.c
+../obj-ack//libc.a(_pipe.o): _pipe.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_pipe.o _pipe.c
+../obj-ack//libc.a(_ptrace.o): _ptrace.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_ptrace.o _ptrace.c
+../obj-ack//libc.a(_read.o): _read.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_read.o _read.c
+../obj-ack//libc.a(_readdir.o): _readdir.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_readdir.o _readdir.c
+../obj-ack//libc.a(_readlink.o): _readlink.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_readlink.o _readlink.c
+../obj-ack//libc.a(_rename.o): _rename.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_rename.o _rename.c
+../obj-ack//libc.a(_rewinddir.o): _rewinddir.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_rewinddir.o _rewinddir.c
+../obj-ack//libc.a(_rmdir.o): _rmdir.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_rmdir.o _rmdir.c
+../obj-ack//libc.a(_select.o): _select.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_select.o _select.c
+../obj-ack//libc.a(_setgid.o): _setgid.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_setgid.o _setgid.c
+../obj-ack//libc.a(_setsid.o): _setsid.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_setsid.o _setsid.c
+../obj-ack//libc.a(_setuid.o): _setuid.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_setuid.o _setuid.c
+../obj-ack//libc.a(_sigaction.o): _sigaction.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_sigaction.o _sigaction.c
+../obj-ack//libc.a(_sigpending.o): _sigpending.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_sigpending.o _sigpending.c
+../obj-ack//libc.a(_sigprocmask.o): _sigprocmask.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_sigprocmask.o _sigprocmask.c
+../obj-ack//libc.a(_sigreturn.o): _sigreturn.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_sigreturn.o _sigreturn.c
+../obj-ack//libc.a(_sigset.o): _sigset.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_sigset.o _sigset.c
+../obj-ack//libc.a(_sigsetjmp.o): _sigsetjmp.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_sigsetjmp.o _sigsetjmp.c
+../obj-ack//libc.a(_sigsuspend.o): _sigsuspend.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_sigsuspend.o _sigsuspend.c
+../obj-ack//libc.a(_sleep.o): _sleep.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_sleep.o _sleep.c
+../obj-ack//libc.a(_stat.o): _stat.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_stat.o _stat.c
+../obj-ack//libc.a(_stime.o): _stime.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_stime.o _stime.c
+../obj-ack//libc.a(_symlink.o): _symlink.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_symlink.o _symlink.c
+../obj-ack//libc.a(_sync.o): _sync.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_sync.o _sync.c
+../obj-ack//libc.a(_tcdrain.o): _tcdrain.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_tcdrain.o _tcdrain.c
+../obj-ack//libc.a(_tcflow.o): _tcflow.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_tcflow.o _tcflow.c
+../obj-ack//libc.a(_tcflush.o): _tcflush.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_tcflush.o _tcflush.c
+../obj-ack//libc.a(_tcgetattr.o): _tcgetattr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_tcgetattr.o _tcgetattr.c
+../obj-ack//libc.a(_tcsendbreak.o): _tcsendbreak.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_tcsendbreak.o _tcsendbreak.c
+../obj-ack//libc.a(_tcsetattr.o): _tcsetattr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_tcsetattr.o _tcsetattr.c
+../obj-ack//libc.a(_time.o): _time.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_time.o _time.c
+../obj-ack//libc.a(_times.o): _times.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_times.o _times.c
+../obj-ack//libc.a(_truncate.o): _truncate.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_truncate.o _truncate.c
+../obj-ack//libc.a(_umask.o): _umask.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_umask.o _umask.c
+../obj-ack//libc.a(_umount.o): _umount.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_umount.o _umount.c
+../obj-ack//libc.a(_uname.o): _uname.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_uname.o _uname.c
+../obj-ack//libc.a(_unlink.o): _unlink.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_unlink.o _unlink.c
+../obj-ack//libc.a(_utime.o): _utime.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_utime.o _utime.c
+../obj-ack//libc.a(_wait.o): _wait.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_wait.o _wait.c
+../obj-ack//libc.a(_waitpid.o): _waitpid.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_waitpid.o _waitpid.c
+../obj-ack//libc.a(_write.o): _write.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/_write.o _write.c
+../obj-ack//libc.a(getloadavg.o): getloadavg.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/getloadavg.o getloadavg.c
+../obj-ack//libc.a(getopt.o): getopt.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/getopt.o getopt.c
+../obj-ack//libc.a(gettimeofday.o): gettimeofday.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/gettimeofday.o gettimeofday.c
+../obj-ack//libc.a(priority.o): priority.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/priority.o priority.c
+../obj-ack//libc.a(usleep.o): usleep.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./posix/usleep.o usleep.c
+
+all-gnu: ../obj-gnu/libc.a
+
+../obj-gnu/libc.a: ../obj-gnu/./posix/__exit.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_access.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_alarm.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_cfgetispeed.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_cfgetospeed.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_cfsetispeed.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_cfsetospeed.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_chdir.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_chmod.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_chown.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_chroot.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_close.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_closedir.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_creat.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_dup.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_dup2.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_execl.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_execle.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_execlp.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_execv.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_execve.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_execvp.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_fcntl.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_fork.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_fpathconf.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_fstat.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_fstatfs.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_fsync.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_getcwd.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_getegid.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_geteuid.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_getgid.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_getgroups.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_getpgrp.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_getpid.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_getppid.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_getuid.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_ioctl.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_isatty.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_kill.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_link.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_lseek.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_lstat.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_mkdir.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_mkfifo.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_mknod.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_mount.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_open.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_opendir.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_pathconf.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_pause.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_pipe.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_ptrace.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_read.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_readdir.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_readlink.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_rename.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_rewinddir.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_rmdir.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_select.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_setgid.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_setsid.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_setuid.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_sigaction.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_sigpending.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_sigprocmask.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_sigreturn.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_sigset.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_sigsetjmp.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_sigsuspend.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_sleep.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_stat.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_stime.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_symlink.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_sync.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_tcdrain.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_tcflow.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_tcflush.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_tcgetattr.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_tcsendbreak.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_tcsetattr.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_time.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_times.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_truncate.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_umask.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_umount.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_uname.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_unlink.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_utime.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_wait.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_waitpid.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/_write.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/getloadavg.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/getopt.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/gettimeofday.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/priority.o
+../obj-gnu/libc.a: ../obj-gnu/./posix/usleep.o
+
+../obj-gnu/libc.a:
+	gar cr ../obj-gnu/libc.a $?
+
+../obj-gnu/./posix/__exit.o: __exit.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/__exit.o __exit.c
+
+../obj-gnu/./posix/_access.o: _access.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_access.o _access.c
+
+../obj-gnu/./posix/_alarm.o: _alarm.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_alarm.o _alarm.c
+
+../obj-gnu/./posix/_cfgetispeed.o: _cfgetispeed.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_cfgetispeed.o _cfgetispeed.c
+
+../obj-gnu/./posix/_cfgetospeed.o: _cfgetospeed.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_cfgetospeed.o _cfgetospeed.c
+
+../obj-gnu/./posix/_cfsetispeed.o: _cfsetispeed.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_cfsetispeed.o _cfsetispeed.c
+
+../obj-gnu/./posix/_cfsetospeed.o: _cfsetospeed.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_cfsetospeed.o _cfsetospeed.c
+
+../obj-gnu/./posix/_chdir.o: _chdir.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_chdir.o _chdir.c
+
+../obj-gnu/./posix/_chmod.o: _chmod.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_chmod.o _chmod.c
+
+../obj-gnu/./posix/_chown.o: _chown.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_chown.o _chown.c
+
+../obj-gnu/./posix/_chroot.o: _chroot.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_chroot.o _chroot.c
+
+../obj-gnu/./posix/_close.o: _close.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_close.o _close.c
+
+../obj-gnu/./posix/_closedir.o: _closedir.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_closedir.o _closedir.c
+
+../obj-gnu/./posix/_creat.o: _creat.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_creat.o _creat.c
+
+../obj-gnu/./posix/_dup.o: _dup.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_dup.o _dup.c
+
+../obj-gnu/./posix/_dup2.o: _dup2.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_dup2.o _dup2.c
+
+../obj-gnu/./posix/_execl.o: _execl.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_execl.o _execl.c
+
+../obj-gnu/./posix/_execle.o: _execle.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_execle.o _execle.c
+
+../obj-gnu/./posix/_execlp.o: _execlp.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_execlp.o _execlp.c
+
+../obj-gnu/./posix/_execv.o: _execv.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_execv.o _execv.c
+
+../obj-gnu/./posix/_execve.o: _execve.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_execve.o _execve.c
+
+../obj-gnu/./posix/_execvp.o: _execvp.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_execvp.o _execvp.c
+
+../obj-gnu/./posix/_fcntl.o: _fcntl.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_fcntl.o _fcntl.c
+
+../obj-gnu/./posix/_fork.o: _fork.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_fork.o _fork.c
+
+../obj-gnu/./posix/_fpathconf.o: _fpathconf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_fpathconf.o _fpathconf.c
+
+../obj-gnu/./posix/_fstat.o: _fstat.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_fstat.o _fstat.c
+
+../obj-gnu/./posix/_fstatfs.o: _fstatfs.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_fstatfs.o _fstatfs.c
+
+../obj-gnu/./posix/_fsync.o: _fsync.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_fsync.o _fsync.c
+
+../obj-gnu/./posix/_getcwd.o: _getcwd.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_getcwd.o _getcwd.c
+
+../obj-gnu/./posix/_getegid.o: _getegid.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_getegid.o _getegid.c
+
+../obj-gnu/./posix/_geteuid.o: _geteuid.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_geteuid.o _geteuid.c
+
+../obj-gnu/./posix/_getgid.o: _getgid.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_getgid.o _getgid.c
+
+../obj-gnu/./posix/_getgroups.o: _getgroups.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_getgroups.o _getgroups.c
+
+../obj-gnu/./posix/_getpgrp.o: _getpgrp.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_getpgrp.o _getpgrp.c
+
+../obj-gnu/./posix/_getpid.o: _getpid.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_getpid.o _getpid.c
+
+../obj-gnu/./posix/_getppid.o: _getppid.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_getppid.o _getppid.c
+
+../obj-gnu/./posix/_getuid.o: _getuid.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_getuid.o _getuid.c
+
+../obj-gnu/./posix/_ioctl.o: _ioctl.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_ioctl.o _ioctl.c
+
+../obj-gnu/./posix/_isatty.o: _isatty.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_isatty.o _isatty.c
+
+../obj-gnu/./posix/_kill.o: _kill.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_kill.o _kill.c
+
+../obj-gnu/./posix/_link.o: _link.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_link.o _link.c
+
+../obj-gnu/./posix/_lseek.o: _lseek.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_lseek.o _lseek.c
+
+../obj-gnu/./posix/_lstat.o: _lstat.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_lstat.o _lstat.c
+
+../obj-gnu/./posix/_mkdir.o: _mkdir.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_mkdir.o _mkdir.c
+
+../obj-gnu/./posix/_mkfifo.o: _mkfifo.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_mkfifo.o _mkfifo.c
+
+../obj-gnu/./posix/_mknod.o: _mknod.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_mknod.o _mknod.c
+
+../obj-gnu/./posix/_mount.o: _mount.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_mount.o _mount.c
+
+../obj-gnu/./posix/_open.o: _open.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_open.o _open.c
+
+../obj-gnu/./posix/_opendir.o: _opendir.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_opendir.o _opendir.c
+
+../obj-gnu/./posix/_pathconf.o: _pathconf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_pathconf.o _pathconf.c
+
+../obj-gnu/./posix/_pause.o: _pause.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_pause.o _pause.c
+
+../obj-gnu/./posix/_pipe.o: _pipe.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_pipe.o _pipe.c
+
+../obj-gnu/./posix/_ptrace.o: _ptrace.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_ptrace.o _ptrace.c
+
+../obj-gnu/./posix/_read.o: _read.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_read.o _read.c
+
+../obj-gnu/./posix/_readdir.o: _readdir.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_readdir.o _readdir.c
+
+../obj-gnu/./posix/_readlink.o: _readlink.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_readlink.o _readlink.c
+
+../obj-gnu/./posix/_rename.o: _rename.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_rename.o _rename.c
+
+../obj-gnu/./posix/_rewinddir.o: _rewinddir.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_rewinddir.o _rewinddir.c
+
+../obj-gnu/./posix/_rmdir.o: _rmdir.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_rmdir.o _rmdir.c
+
+../obj-gnu/./posix/_select.o: _select.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_select.o _select.c
+
+../obj-gnu/./posix/_setgid.o: _setgid.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_setgid.o _setgid.c
+
+../obj-gnu/./posix/_setsid.o: _setsid.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_setsid.o _setsid.c
+
+../obj-gnu/./posix/_setuid.o: _setuid.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_setuid.o _setuid.c
+
+../obj-gnu/./posix/_sigaction.o: _sigaction.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_sigaction.o _sigaction.c
+
+../obj-gnu/./posix/_sigpending.o: _sigpending.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_sigpending.o _sigpending.c
+
+../obj-gnu/./posix/_sigprocmask.o: _sigprocmask.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_sigprocmask.o _sigprocmask.c
+
+../obj-gnu/./posix/_sigreturn.o: _sigreturn.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_sigreturn.o _sigreturn.c
+
+../obj-gnu/./posix/_sigset.o: _sigset.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_sigset.o _sigset.c
+
+../obj-gnu/./posix/_sigsetjmp.o: _sigsetjmp.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_sigsetjmp.o _sigsetjmp.c
+
+../obj-gnu/./posix/_sigsuspend.o: _sigsuspend.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_sigsuspend.o _sigsuspend.c
+
+../obj-gnu/./posix/_sleep.o: _sleep.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_sleep.o _sleep.c
+
+../obj-gnu/./posix/_stat.o: _stat.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_stat.o _stat.c
+
+../obj-gnu/./posix/_stime.o: _stime.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_stime.o _stime.c
+
+../obj-gnu/./posix/_symlink.o: _symlink.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_symlink.o _symlink.c
+
+../obj-gnu/./posix/_sync.o: _sync.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_sync.o _sync.c
+
+../obj-gnu/./posix/_tcdrain.o: _tcdrain.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_tcdrain.o _tcdrain.c
+
+../obj-gnu/./posix/_tcflow.o: _tcflow.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_tcflow.o _tcflow.c
+
+../obj-gnu/./posix/_tcflush.o: _tcflush.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_tcflush.o _tcflush.c
+
+../obj-gnu/./posix/_tcgetattr.o: _tcgetattr.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_tcgetattr.o _tcgetattr.c
+
+../obj-gnu/./posix/_tcsendbreak.o: _tcsendbreak.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_tcsendbreak.o _tcsendbreak.c
+
+../obj-gnu/./posix/_tcsetattr.o: _tcsetattr.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_tcsetattr.o _tcsetattr.c
+
+../obj-gnu/./posix/_time.o: _time.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_time.o _time.c
+
+../obj-gnu/./posix/_times.o: _times.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_times.o _times.c
+
+../obj-gnu/./posix/_truncate.o: _truncate.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_truncate.o _truncate.c
+
+../obj-gnu/./posix/_umask.o: _umask.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_umask.o _umask.c
+
+../obj-gnu/./posix/_umount.o: _umount.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_umount.o _umount.c
+
+../obj-gnu/./posix/_uname.o: _uname.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_uname.o _uname.c
+
+../obj-gnu/./posix/_unlink.o: _unlink.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_unlink.o _unlink.c
+
+../obj-gnu/./posix/_utime.o: _utime.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_utime.o _utime.c
+
+../obj-gnu/./posix/_wait.o: _wait.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_wait.o _wait.c
+
+../obj-gnu/./posix/_waitpid.o: _waitpid.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_waitpid.o _waitpid.c
+
+../obj-gnu/./posix/_write.o: _write.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/_write.o _write.c
+
+../obj-gnu/./posix/getloadavg.o: getloadavg.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/getloadavg.o getloadavg.c
+
+../obj-gnu/./posix/getopt.o: getopt.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/getopt.o getopt.c
+
+../obj-gnu/./posix/gettimeofday.o: gettimeofday.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/gettimeofday.o gettimeofday.c
+
+../obj-gnu/./posix/priority.o: priority.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/priority.o priority.c
+
+../obj-gnu/./posix/usleep.o: usleep.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./posix/usleep.o usleep.c
+
+
+
+
+clean::
+	rm -f ../obj-ack//./posix/*
+	rm -f ../obj-gnu/./posix/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/posix/Makefile.in
===================================================================
--- /trunk/minix/lib/posix/Makefile.in	(revision 9)
+++ /trunk/minix/lib/posix/Makefile.in	(revision 9)
@@ -0,0 +1,109 @@
+# Makefile for lib/posix.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
+
+LIBRARIES=libc
+
+libc_FILES=" \
+	__exit.c \
+	_access.c \
+	_alarm.c \
+	_cfgetispeed.c \
+	_cfgetospeed.c \
+	_cfsetispeed.c \
+	_cfsetospeed.c \
+	_chdir.c \
+	_chmod.c \
+	_chown.c \
+	_chroot.c \
+	_close.c \
+	_closedir.c \
+	_creat.c \
+	_dup.c \
+	_dup2.c \
+	_execl.c \
+	_execle.c \
+	_execlp.c \
+	_execv.c \
+	_execve.c \
+	_execvp.c \
+	_fcntl.c \
+	_fork.c \
+	_fpathconf.c \
+	_fstat.c \
+	_fstatfs.c \
+	_fsync.c \
+	_getcwd.c \
+	_getegid.c \
+	_geteuid.c \
+	_getgid.c \
+	_getgroups.c \
+	_getpgrp.c \
+	_getpid.c \
+	_getppid.c \
+	_getuid.c \
+	_ioctl.c \
+	_isatty.c \
+	_kill.c \
+	_link.c \
+	_lseek.c \
+	_lstat.c \
+	_mkdir.c \
+	_mkfifo.c \
+	_mknod.c \
+	_mount.c \
+	_open.c \
+	_opendir.c \
+	_pathconf.c \
+	_pause.c \
+	_pipe.c \
+	_ptrace.c \
+	_read.c \
+	_readdir.c \
+	_readlink.c \
+	_rename.c \
+	_rewinddir.c \
+	_rmdir.c \
+	_select.c \
+	_setgid.c \
+	_setsid.c \
+	_setuid.c \
+	_sigaction.c \
+	_sigpending.c \
+	_sigprocmask.c \
+	_sigreturn.c \
+	_sigset.c \
+	_sigsetjmp.c \
+	_sigsuspend.c \
+	_sleep.c \
+	_stat.c \
+	_stime.c \
+	_symlink.c \
+	_sync.c \
+	_tcdrain.c \
+	_tcflow.c \
+	_tcflush.c \
+	_tcgetattr.c \
+	_tcsendbreak.c \
+	_tcsetattr.c \
+	_time.c \
+	_times.c \
+	_truncate.c \
+	_umask.c \
+	_umount.c \
+	_uname.c \
+	_unlink.c \
+	_utime.c \
+	_wait.c \
+	_waitpid.c \
+	_write.c \
+	getloadavg.c \
+	getopt.c \
+	gettimeofday.c \
+	priority.c \
+	usleep.c"
+
+TYPE=both
+
+#$(call ADDDEPENDENCIES,_uname.o,/usr/include/minix/config.h)
+
Index: /trunk/minix/lib/posix/__exit.c
===================================================================
--- /trunk/minix/lib/posix/__exit.c	(revision 9)
+++ /trunk/minix/lib/posix/__exit.c	(revision 9)
@@ -0,0 +1,23 @@
+#define _exit	__exit
+#include <lib.h>
+#include <unistd.h>
+
+PUBLIC void _exit(status)
+int status;
+{
+  void (*suicide)(void);
+  message m;
+
+  m.m1_i1 = status;
+  _syscall(MM, EXIT, &m);
+
+  /* If exiting nicely through PM fails for some reason, try to
+   * commit suicide. E.g., message to PM might fail due to deadlock.
+   */
+  suicide = (void (*)(void)) -1;
+  suicide();
+
+  /* If committing suicide fails for some reason, hang. */
+  for(;;) { }
+}
+
Index: /trunk/minix/lib/posix/_access.c
===================================================================
--- /trunk/minix/lib/posix/_access.c	(revision 9)
+++ /trunk/minix/lib/posix/_access.c	(revision 9)
@@ -0,0 +1,14 @@
+#include <lib.h>
+#define access	_access
+#include <unistd.h>
+
+PUBLIC int access(name, mode)
+_CONST char *name;
+int mode;
+{
+  message m;
+
+  m.m3_i2 = mode;
+  _loadname(name, &m);
+  return(_syscall(FS, ACCESS, &m));
+}
Index: /trunk/minix/lib/posix/_alarm.c
===================================================================
--- /trunk/minix/lib/posix/_alarm.c	(revision 9)
+++ /trunk/minix/lib/posix/_alarm.c	(revision 9)
@@ -0,0 +1,12 @@
+#include <lib.h>
+#define alarm	_alarm
+#include <unistd.h>
+
+PUBLIC unsigned int alarm(sec)
+unsigned int sec;
+{
+  message m;
+
+  m.m1_i1 = (int) sec;
+  return( (unsigned) _syscall(MM, ALARM, &m));
+}
Index: /trunk/minix/lib/posix/_cfgetispeed.c
===================================================================
--- /trunk/minix/lib/posix/_cfgetispeed.c	(revision 9)
+++ /trunk/minix/lib/posix/_cfgetispeed.c	(revision 9)
@@ -0,0 +1,12 @@
+/*
+posix/_cfgetispeed
+
+Created:	June 11, 1993 by Philip Homburg
+*/
+
+#include <termios.h>
+
+speed_t _cfgetispeed(const struct termios *termios_p)
+{
+  return termios_p->c_ispeed;
+}
Index: /trunk/minix/lib/posix/_cfgetospeed.c
===================================================================
--- /trunk/minix/lib/posix/_cfgetospeed.c	(revision 9)
+++ /trunk/minix/lib/posix/_cfgetospeed.c	(revision 9)
@@ -0,0 +1,12 @@
+/*
+posix/_cfgetospeed
+
+Created:	June 11, 1993 by Philip Homburg
+*/
+
+#include <termios.h>
+
+speed_t _cfgetospeed(const struct termios *termios_p)
+{
+  return termios_p->c_ospeed;
+}
Index: /trunk/minix/lib/posix/_cfsetispeed.c
===================================================================
--- /trunk/minix/lib/posix/_cfsetispeed.c	(revision 9)
+++ /trunk/minix/lib/posix/_cfsetispeed.c	(revision 9)
@@ -0,0 +1,13 @@
+/*
+posix/_cfsetispeed
+
+Created:	June 11, 1993 by Philip Homburg
+*/
+
+#include <termios.h>
+
+int _cfsetispeed(struct termios *termios_p, speed_t speed)
+{
+  termios_p->c_ispeed= speed;
+  return 0;
+}
Index: /trunk/minix/lib/posix/_cfsetospeed.c
===================================================================
--- /trunk/minix/lib/posix/_cfsetospeed.c	(revision 9)
+++ /trunk/minix/lib/posix/_cfsetospeed.c	(revision 9)
@@ -0,0 +1,13 @@
+/*
+posix/_cfsetospeed
+
+Created:	June 11, 1993 by Philip Homburg
+*/
+
+#include <termios.h>
+
+int _cfsetospeed(struct termios *termios_p, speed_t speed)
+{
+  termios_p->c_ospeed= speed;
+  return 0;
+}
Index: /trunk/minix/lib/posix/_chdir.c
===================================================================
--- /trunk/minix/lib/posix/_chdir.c	(revision 9)
+++ /trunk/minix/lib/posix/_chdir.c	(revision 9)
@@ -0,0 +1,22 @@
+#include <lib.h>
+#define chdir	_chdir
+#define fchdir	_fchdir
+#include <unistd.h>
+
+PUBLIC int chdir(name)
+_CONST char *name;
+{
+  message m;
+
+  _loadname(name, &m);
+  return(_syscall(FS, CHDIR, &m));
+}
+
+PUBLIC int fchdir(fd)
+int fd;
+{
+  message m;
+
+  m.m1_i1 = fd;
+  return(_syscall(FS, FCHDIR, &m));
+}
Index: /trunk/minix/lib/posix/_chmod.c
===================================================================
--- /trunk/minix/lib/posix/_chmod.c	(revision 9)
+++ /trunk/minix/lib/posix/_chmod.c	(revision 9)
@@ -0,0 +1,14 @@
+#include <lib.h>
+#define chmod	_chmod
+#include <sys/stat.h>
+
+PUBLIC int chmod(name, mode)
+_CONST char *name;
+_mnx_Mode_t mode;
+{
+  message m;
+
+  m.m3_i2 = mode;
+  _loadname(name, &m);
+  return(_syscall(FS, CHMOD, &m));
+}
Index: /trunk/minix/lib/posix/_chown.c
===================================================================
--- /trunk/minix/lib/posix/_chown.c	(revision 9)
+++ /trunk/minix/lib/posix/_chown.c	(revision 9)
@@ -0,0 +1,18 @@
+#include <lib.h>
+#define chown	_chown
+#include <string.h>
+#include <unistd.h>
+
+PUBLIC int chown(name, owner, grp)
+_CONST char *name;
+_mnx_Uid_t owner;
+_mnx_Gid_t grp;
+{
+  message m;
+
+  m.m1_i1 = strlen(name) + 1;
+  m.m1_i2 = owner;
+  m.m1_i3 = grp;
+  m.m1_p1 = (char *) name;
+  return(_syscall(FS, CHOWN, &m));
+}
Index: /trunk/minix/lib/posix/_chroot.c
===================================================================
--- /trunk/minix/lib/posix/_chroot.c	(revision 9)
+++ /trunk/minix/lib/posix/_chroot.c	(revision 9)
@@ -0,0 +1,12 @@
+#include <lib.h>
+#define chroot	_chroot
+#include <unistd.h>
+
+PUBLIC int chroot(name)
+_CONST char *name;
+{
+  message m;
+
+  _loadname(name, &m);
+  return(_syscall(FS, CHROOT, &m));
+}
Index: /trunk/minix/lib/posix/_close.c
===================================================================
--- /trunk/minix/lib/posix/_close.c	(revision 9)
+++ /trunk/minix/lib/posix/_close.c	(revision 9)
@@ -0,0 +1,12 @@
+#include <lib.h>
+#define close	_close
+#include <unistd.h>
+
+PUBLIC int close(fd)
+int fd;
+{
+  message m;
+
+  m.m1_i1 = fd;
+  return(_syscall(FS, CLOSE, &m));
+}
Index: /trunk/minix/lib/posix/_closedir.c
===================================================================
--- /trunk/minix/lib/posix/_closedir.c	(revision 9)
+++ /trunk/minix/lib/posix/_closedir.c	(revision 9)
@@ -0,0 +1,24 @@
+/*	closedir()					Author: Kees J. Bot
+ *								24 Apr 1989
+ */
+#define nil 0
+#include <lib.h>
+#define close	_close
+#define closedir _closedir
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+int closedir(DIR *dp)
+/* Finish reading a directory. */
+{
+	int d;
+
+	if (dp == nil) { errno= EBADF; return -1; }
+
+	d= dp->_fd;
+	free((void *) dp);
+	return close(d);
+}
Index: /trunk/minix/lib/posix/_creat.c
===================================================================
--- /trunk/minix/lib/posix/_creat.c	(revision 9)
+++ /trunk/minix/lib/posix/_creat.c	(revision 9)
@@ -0,0 +1,14 @@
+#include <lib.h>
+#define creat	_creat
+#include <fcntl.h>
+
+PUBLIC int creat(name, mode)
+_CONST char *name;
+_mnx_Mode_t mode;
+{
+  message m;
+
+  m.m3_i2 = mode;
+  _loadname(name, &m);
+  return(_syscall(FS, CREAT, &m));
+}
Index: /trunk/minix/lib/posix/_dup.c
===================================================================
--- /trunk/minix/lib/posix/_dup.c	(revision 9)
+++ /trunk/minix/lib/posix/_dup.c	(revision 9)
@@ -0,0 +1,11 @@
+#include <lib.h>
+#define dup	_dup
+#define fcntl	_fcntl
+#include <fcntl.h>
+#include <unistd.h>
+
+PUBLIC int dup(fd)
+int fd;
+{
+  return(fcntl(fd, F_DUPFD, 0));
+}
Index: /trunk/minix/lib/posix/_dup2.c
===================================================================
--- /trunk/minix/lib/posix/_dup2.c	(revision 9)
+++ /trunk/minix/lib/posix/_dup2.c	(revision 9)
@@ -0,0 +1,30 @@
+#include <lib.h>
+#define close	_close
+#define dup2	_dup2
+#define fcntl	_fcntl
+#include <fcntl.h>
+#include <unistd.h>
+
+PUBLIC int dup2(fd, fd2)
+int fd, fd2;
+{
+/* The behavior of dup2 is defined by POSIX in 6.2.1.2 as almost, but not
+ * quite the same as fcntl.
+ */
+
+  if (fd2 < 0 || fd2 > OPEN_MAX) {
+	errno = EBADF;
+	return(-1);
+  }
+
+  /* Check to see if fildes is valid. */
+  if (fcntl(fd, F_GETFL) < 0) {
+	/* 'fd' is not valid. */
+	return(-1);
+  } else {
+	/* 'fd' is valid. */
+	if (fd == fd2) return(fd2);
+	close(fd2);
+	return(fcntl(fd, F_DUPFD, fd2));
+  }
+}
Index: /trunk/minix/lib/posix/_execl.c
===================================================================
--- /trunk/minix/lib/posix/_execl.c	(revision 9)
+++ /trunk/minix/lib/posix/_execl.c	(revision 9)
@@ -0,0 +1,18 @@
+/*	execl() - execute				Author: Kees J. Bot
+ *								21 Jan 1994
+ */
+#define execl _execl
+#define execve _execve
+#include <unistd.h>
+
+extern char * const **_penviron;	/* The default environment. */
+
+int execl(const char *path, const char *arg1, ...)
+/* execl("/bin/sh", "sh", "-c", "example", (char *) 0); */
+{
+	/* Assumption:  The C-implementation for this machine pushes
+	 * function arguments downwards on the stack making a perfect
+	 * argument array.  Luckily this is almost always so.
+	 */
+	return execve(path, (char * const *) &arg1, *_penviron);
+}
Index: /trunk/minix/lib/posix/_execle.c
===================================================================
--- /trunk/minix/lib/posix/_execle.c	(revision 9)
+++ /trunk/minix/lib/posix/_execle.c	(revision 9)
@@ -0,0 +1,25 @@
+/*	execle() - execute with a custom environment	Author: Kees J. Bot
+ *								21 Jan 1994
+ */
+#define nil 0
+#define execle _execle
+#define execve _execve
+#include <unistd.h>
+#include <stdarg.h>
+
+int execle(const char *path, const char *arg1, ...)
+/* execle("/bin/sh", "sh", "-c", "example", (char *) 0, my_env_array); */
+{
+	char * const * envp;
+	va_list ap;
+
+	va_start(ap, arg1);
+
+	/* Find the end of the argument array. */
+	if (arg1 != nil) while (va_arg(ap, const char *) != nil) {}
+
+	envp = va_arg(ap, char * const *);
+	va_end(ap);
+
+	return execve(path, (char * const *) &arg1, envp);
+}
Index: /trunk/minix/lib/posix/_execlp.c
===================================================================
--- /trunk/minix/lib/posix/_execlp.c	(revision 9)
+++ /trunk/minix/lib/posix/_execlp.c	(revision 9)
@@ -0,0 +1,12 @@
+/*	execlp() - execute with PATH search		Author: Kees J. Bot
+ *								22 Jan 1994
+ */
+#define execlp _execlp
+#define execvp _execvp
+#include <unistd.h>
+
+int execlp(const char *file, const char *arg1, ...)
+/* execlp("sh", "sh", "-c", "example", (char *) 0); */
+{
+	return execvp(file, (char * const *) &arg1);
+}
Index: /trunk/minix/lib/posix/_execv.c
===================================================================
--- /trunk/minix/lib/posix/_execv.c	(revision 9)
+++ /trunk/minix/lib/posix/_execv.c	(revision 9)
@@ -0,0 +1,13 @@
+/*	execv() - execute with prepared arguments	Author: Kees J. Bot
+ *								21 Jan 1994
+ */
+#define execv _execv
+#define execve _execve
+#include <unistd.h>
+
+extern char * const **_penviron;	/* The default environment. */
+
+int execv(const char *path, char * const *argv)
+{
+	return execve(path, argv, *_penviron);
+}
Index: /trunk/minix/lib/posix/_execve.c
===================================================================
--- /trunk/minix/lib/posix/_execve.c	(revision 9)
+++ /trunk/minix/lib/posix/_execve.c	(revision 9)
@@ -0,0 +1,115 @@
+/*	execve() - basic program execution call		Author: Kees J. Bot
+ *								21 Jan 1994
+ */
+
+#define _MINIX_SOURCE
+
+#define nil 0
+#define execve _execve
+#define sbrk _sbrk
+#include <lib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stddef.h>
+
+int execve(const char *path, char * const *argv, char * const *envp)
+{
+	char * const *ap;
+	char * const *ep;
+	char *frame;
+	char **vp;
+	char *sp;
+	size_t argc;
+	size_t frame_size;
+	size_t string_off;
+	size_t n;
+	int ov;
+	message m;
+
+	/* Assumptions: size_t and char *, it's all the same thing. */
+
+	/* Create a stack image that only needs to be patched up slightly
+	 * by the kernel to be used for the process to be executed.
+	 */
+
+	ov= 0;			/* No overflow yet. */
+	frame_size= 0;		/* Size of the new initial stack. */
+	string_off= 0;		/* Offset to start of the strings. */
+	argc= 0;		/* Argument count. */
+
+	for (ap= argv; *ap != nil; ap++) {
+		n = sizeof(*ap) + strlen(*ap) + 1;
+		frame_size+= n;
+		if (frame_size < n) ov= 1;
+		string_off+= sizeof(*ap);
+		argc++;
+	}
+
+	for (ep= envp; *ep != nil; ep++) {
+		n = sizeof(*ep) + strlen(*ep) + 1;
+		frame_size+= n;
+		if (frame_size < n) ov= 1;
+		string_off+= sizeof(*ap);
+	}
+
+	/* Add an argument count and two terminating nulls. */
+	frame_size+= sizeof(argc) + sizeof(*ap) + sizeof(*ep);
+	string_off+= sizeof(argc) + sizeof(*ap) + sizeof(*ep);
+
+	/* Align. */
+	frame_size= (frame_size + sizeof(char *) - 1) & ~(sizeof(char *) - 1);
+
+	/* The party is off if there is an overflow. */
+	if (ov || frame_size < 3 * sizeof(char *)) {
+		errno= E2BIG;
+		return -1;
+	}
+
+	/* Allocate space for the stack frame. */
+	if ((frame = (char *) sbrk(frame_size)) == (char *) -1) {
+		errno = E2BIG;
+		return -1;
+	}
+
+	/* Set arg count, init pointers to vector and string tables. */
+	* (size_t *) frame = argc;
+	vp = (char **) (frame + sizeof(argc));
+	sp = frame + string_off;
+
+	/* Load the argument vector and strings. */
+	for (ap= argv; *ap != nil; ap++) {
+		*vp++= (char *) (sp - frame);
+		n= strlen(*ap) + 1;
+		memcpy(sp, *ap, n);
+		sp+= n;
+	}
+	*vp++= nil;
+
+	/* Load the environment vector and strings. */
+	for (ep= envp; *ep != nil; ep++) {
+		*vp++= (char *) (sp - frame);
+		n= strlen(*ep) + 1;
+		memcpy(sp, *ep, n);
+		sp+= n;
+	}
+	*vp++= nil;
+
+	/* Padding. */
+	while (sp < frame + frame_size) *sp++= 0;
+
+	/* We can finally make the system call. */
+	m.m1_i1 = strlen(path) + 1;
+	m.m1_i2 = frame_size;
+	m.m1_p1 = (char *) path;
+	m.m1_p2 = frame;
+
+	/* Clear unused fields */
+	m.m1_i3 = 0;
+	m.m1_p3 = NULL;
+
+	(void) _syscall(MM, EXEC, &m);
+
+	/* Failure, return the memory used for the frame and exit. */
+	(void) sbrk(-frame_size);
+	return -1;
+}
Index: /trunk/minix/lib/posix/_execvp.c
===================================================================
--- /trunk/minix/lib/posix/_execvp.c	(revision 9)
+++ /trunk/minix/lib/posix/_execvp.c	(revision 9)
@@ -0,0 +1,73 @@
+/*	execvp() - execute with PATH search and prepared arguments
+ *							Author: Kees J. Bot
+ *								21 Jan 1994
+ */
+
+#define _MINIX_SOURCE
+
+#define nil 0
+#define execve _execve
+#define execvp _execvp
+#define sbrk _sbrk
+#define stat _stat
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+extern char * const **_penviron;	/* The default environment. */
+
+int execvp(const char *file, char * const *argv)
+/* Execute the file with a path search on $PATH, just like the shell.  The
+ * search continues on the errors ENOENT (not there), and EACCES (file not
+ * executable or leading directories protected.)
+ * Unlike other execvp implementations there is no default path, and no shell
+ * is started for scripts.  One is supposed to define $PATH, and use #!/bin/sh.
+ */
+{
+	struct stat sb;
+	const char *path;		/* $PATH */
+	char *full;			/* Full name to try. */
+	char *f;
+	size_t full_size;
+	int err= ENOENT;		/* Error return on failure. */
+
+	if (strchr(file, '/') != nil || (path= getenv("PATH")) == nil)
+		path= "";
+
+	/* Compute the maximum length the full name may have, and align. */
+	full_size= strlen(path) + 1 + strlen(file) + 1 + sizeof(char *) - 1;
+	full_size&= ~(sizeof(char *) - 1);
+
+	/* Claim space. */
+	if ((full= (char *) sbrk(full_size)) == (char *) -1) {
+		errno= E2BIG;
+		return -1;
+	}
+
+	/* For each directory in the path... */
+	do {
+		f= full;
+		while (*path != 0 && *path != ':') *f++= *path++;
+
+		if (f > full) *f++= '/';
+
+		strcpy(f, file);
+
+		/* Stat first, small speed-up, better for ptrace. */
+		if (stat(full, &sb) == -1) continue;
+
+		(void) execve(full, argv, *_penviron);
+
+		/* Prefer more interesting errno values then "not there". */
+		if (errno != ENOENT) err= errno;
+
+		/* Continue only on some errors. */
+		if (err != ENOENT && err != EACCES) break;
+	} while (*path++ != 0);
+
+	(void) sbrk(-full_size);
+	errno= err;
+	return -1;
+}
Index: /trunk/minix/lib/posix/_fcntl.c
===================================================================
--- /trunk/minix/lib/posix/_fcntl.c	(revision 9)
+++ /trunk/minix/lib/posix/_fcntl.c	(revision 9)
@@ -0,0 +1,45 @@
+#include <lib.h>
+#define fcntl _fcntl
+#include <fcntl.h>
+#include <stdarg.h>
+
+#if _ANSI
+PUBLIC int fcntl(int fd, int cmd, ...)
+#else
+PUBLIC int fcntl(fd, cmd)
+int fd;
+int cmd;
+#endif
+{
+  va_list argp;
+  message m;
+
+  va_start(argp, cmd);
+
+  /* Set up for the sensible case where there is no variable parameter.  This
+   * covers F_GETFD, F_GETFL and invalid commands.
+   */
+  m.m1_i3 = 0;
+  m.m1_p1 = NIL_PTR;
+
+  /* Adjust for the stupid cases. */
+  switch(cmd) {
+     case F_DUPFD:
+     case F_SETFD:
+     case F_SETFL:
+	m.m1_i3 = va_arg(argp, int);
+	break;
+     case F_GETLK:
+     case F_SETLK:
+     case F_SETLKW:
+     case F_FREESP:
+	m.m1_p1 = (char *) va_arg(argp, struct flock *);
+	break;
+  }
+
+  /* Clean up and make the system call. */
+  va_end(argp);
+  m.m1_i1 = fd;
+  m.m1_i2 = cmd;
+  return(_syscall(FS, FCNTL, &m));
+}
Index: /trunk/minix/lib/posix/_fork.c
===================================================================
--- /trunk/minix/lib/posix/_fork.c	(revision 9)
+++ /trunk/minix/lib/posix/_fork.c	(revision 9)
@@ -0,0 +1,10 @@
+#include <lib.h>
+#define fork	_fork
+#include <unistd.h>
+
+PUBLIC pid_t fork()
+{
+  message m;
+
+  return(_syscall(MM, FORK, &m));
+}
Index: /trunk/minix/lib/posix/_fpathconf.c
===================================================================
--- /trunk/minix/lib/posix/_fpathconf.c	(revision 9)
+++ /trunk/minix/lib/posix/_fpathconf.c	(revision 9)
@@ -0,0 +1,61 @@
+/* POSIX fpathconf (Sec. 5.7.1) 		Author: Andy Tanenbaum */
+
+#include <lib.h>
+#define fstat		_fstat
+#define fpathconf	_fpathconf
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include <termios.h>
+
+PUBLIC long fpathconf(fd, name)
+int fd;				/* file descriptor being interrogated */
+int name;			/* property being inspected */
+{
+/* POSIX allows some of the values in <limits.h> to be increased at
+ * run time.  The pathconf and fpathconf functions allow these values
+ * to be checked at run time.  MINIX does not use this facility.
+ * The run-time limits are those given in <limits.h>.
+ */
+
+  struct stat stbuf;
+
+  switch(name) {
+	case _PC_LINK_MAX:
+		/* Fstat the file.  If that fails, return -1. */
+		if (fstat(fd, &stbuf) != 0) return(-1);
+		if (S_ISDIR(stbuf.st_mode))
+			return(1L);	/* no links to directories */
+		else
+			return( (long) LINK_MAX);
+
+	case _PC_MAX_CANON:
+		return( (long) MAX_CANON);
+
+	case _PC_MAX_INPUT:
+		return( (long) MAX_INPUT);
+
+	case _PC_NAME_MAX:
+		return( (long) NAME_MAX);
+
+	case _PC_PATH_MAX:
+		return( (long) PATH_MAX);
+
+	case _PC_PIPE_BUF:
+		return( (long) PIPE_BUF);
+
+	case _PC_CHOWN_RESTRICTED:
+		return( (long) _POSIX_CHOWN_RESTRICTED);
+
+	case _PC_NO_TRUNC:
+		return( (long) _POSIX_NO_TRUNC);
+
+	case _PC_VDISABLE:
+		return( (long) _POSIX_VDISABLE);
+
+	default:
+		errno = EINVAL;
+		return(-1);
+  }
+}
Index: /trunk/minix/lib/posix/_fstat.c
===================================================================
--- /trunk/minix/lib/posix/_fstat.c	(revision 9)
+++ /trunk/minix/lib/posix/_fstat.c	(revision 9)
@@ -0,0 +1,14 @@
+#include <lib.h>
+#define fstat	_fstat
+#include <sys/stat.h>
+
+PUBLIC int fstat(fd, buffer)
+int fd;
+struct stat *buffer;
+{
+  message m;
+
+  m.m1_i1 = fd;
+  m.m1_p1 = (char *) buffer;
+  return(_syscall(FS, FSTAT, &m));
+}
Index: /trunk/minix/lib/posix/_fstatfs.c
===================================================================
--- /trunk/minix/lib/posix/_fstatfs.c	(revision 9)
+++ /trunk/minix/lib/posix/_fstatfs.c	(revision 9)
@@ -0,0 +1,13 @@
+#include <lib.h>
+#define fstatfs	_fstatfs
+#include <sys/stat.h>
+#include <sys/statfs.h>
+
+PUBLIC int fstatfs(int fd, struct statfs *buffer)
+{
+  message m;
+
+  m.m1_i1 = fd;
+  m.m1_p1 = (char *) buffer;
+  return(_syscall(FS, FSTATFS, &m));
+}
Index: /trunk/minix/lib/posix/_fsync.c
===================================================================
--- /trunk/minix/lib/posix/_fsync.c	(revision 9)
+++ /trunk/minix/lib/posix/_fsync.c	(revision 9)
@@ -0,0 +1,12 @@
+#include <lib.h>
+#define sync	_sync
+#include <unistd.h>
+
+PUBLIC int fsync(int fd)
+{
+  message m;
+
+  m.m1_i1 = fd;
+
+  return(_syscall(FS, FSYNC, &m));
+}
Index: /trunk/minix/lib/posix/_getcwd.c
===================================================================
--- /trunk/minix/lib/posix/_getcwd.c	(revision 9)
+++ /trunk/minix/lib/posix/_getcwd.c	(revision 9)
@@ -0,0 +1,143 @@
+/*	getcwd() - get the name of the current working directory.
+ *							Author: Kees J. Bot
+ *								30 Apr 1989
+ */
+#define nil 0
+#define chdir _chdir
+#define closedir _closedir
+#define getcwd _getcwd
+#define opendir _opendir
+#define readdir _readdir
+#define rewinddir _rewinddir
+#define stat _stat
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <limits.h>
+#include <string.h>
+
+static int addpath(const char *path, char **ap, const char *entry)
+/* Add the name of a directory entry at the front of the path being built.
+ * Note that the result always starts with a slash.
+ */
+{
+	const char *e= entry;
+	char *p= *ap;
+
+	while (*e != 0) e++;
+
+	while (e > entry && p > path) *--p = *--e;
+
+	if (p == path) return -1;
+	*--p = '/';
+	*ap= p;
+	return 0;
+}
+
+static int recover(char *p)
+/* Undo all those chdir("..")'s that have been recorded by addpath.  This
+ * has to be done entry by entry, because the whole pathname may be too long.
+ */
+{
+	int e= errno, slash;
+	char *p0;
+
+	while (*p != 0) {
+		p0= ++p;
+
+		do p++; while (*p != 0 && *p != '/');
+		slash= *p; *p= 0;
+
+		if (chdir(p0) < 0) return -1;
+		*p= slash;
+	}
+	errno= e;
+	return 0;
+}
+
+char *getcwd(char *path, size_t size)
+{
+	struct stat above, current, tmp;
+	struct dirent *entry;
+	DIR *d;
+	char *p, *up, *dotdot;
+	int cycle;
+
+	if (path == nil || size <= 1) { errno= EINVAL; return nil; }
+
+	p= path + size;
+	*--p = 0;
+
+	if (stat(".", &current) < 0) return nil;
+
+	while (1) {
+		dotdot= "..";
+		if (stat(dotdot, &above) < 0) { recover(p); return nil; }
+
+		if (above.st_dev == current.st_dev
+					&& above.st_ino == current.st_ino)
+			break;	/* Root dir found */
+
+		if ((d= opendir(dotdot)) == nil) { recover(p); return nil; }
+
+		/* Cycle is 0 for a simple inode nr search, or 1 for a search
+		 * for inode *and* device nr.
+		 */
+		cycle= above.st_dev == current.st_dev ? 0 : 1;
+
+		do {
+			char name[3 + NAME_MAX + 1];
+
+			tmp.st_ino= 0;
+			if ((entry= readdir(d)) == nil) {
+				switch (++cycle) {
+				case 1:
+					rewinddir(d);
+					continue;
+				case 2:
+					closedir(d);
+					errno= ENOENT;
+					recover(p);
+					return nil;
+				}
+			}
+			if (strcmp(entry->d_name, ".") == 0) continue;
+			if (strcmp(entry->d_name, "..") == 0) continue;
+
+			switch (cycle) {
+			case 0:
+				/* Simple test on inode nr. */
+				if (entry->d_ino != current.st_ino) continue;
+				/*FALL THROUGH*/
+
+			case 1:
+				/* Current is mounted. */
+				strcpy(name, "../");
+				strcpy(name+3, entry->d_name);
+				if (stat(name, &tmp) < 0) continue;
+				break;
+			}
+		} while (tmp.st_ino != current.st_ino
+					|| tmp.st_dev != current.st_dev);
+
+		up= p;
+		if (addpath(path, &up, entry->d_name) < 0) {
+			closedir(d);
+			errno = ERANGE;
+			recover(p);
+			return nil;
+		}
+		closedir(d);
+
+		if (chdir(dotdot) < 0) { recover(p); return nil; }
+		p= up;
+
+		current= above;
+	}
+	if (recover(p) < 0) return nil;	/* Undo all those chdir("..")'s. */
+	if (*p == 0) *--p = '/';	/* Cwd is "/" if nothing added */
+	if (p > path) strcpy(path, p);	/* Move string to start of path. */
+	return path;
+}
Index: /trunk/minix/lib/posix/_getegid.c
===================================================================
--- /trunk/minix/lib/posix/_getegid.c	(revision 9)
+++ /trunk/minix/lib/posix/_getegid.c	(revision 9)
@@ -0,0 +1,16 @@
+#include <lib.h>
+#define getegid	_getegid
+#include <unistd.h>
+
+PUBLIC gid_t getegid()
+{
+  message m;
+
+  /* POSIX says that this function is always successful and that no
+   * return value is reserved to indicate an error.  Minix syscalls
+   * are not always successful and Minix returns the unreserved value
+   * (gid_t) -1 when there is an error.
+   */
+  if (_syscall(MM, GETGID, &m) < 0) return ( (gid_t) -1);
+  return( (gid_t) m.m2_i1);
+}
Index: /trunk/minix/lib/posix/_geteuid.c
===================================================================
--- /trunk/minix/lib/posix/_geteuid.c	(revision 9)
+++ /trunk/minix/lib/posix/_geteuid.c	(revision 9)
@@ -0,0 +1,16 @@
+#include <lib.h>
+#define geteuid	_geteuid
+#include <unistd.h>
+
+PUBLIC uid_t geteuid()
+{
+  message m;
+
+  /* POSIX says that this function is always successful and that no
+   * return value is reserved to indicate an error.  Minix syscalls
+   * are not always successful and Minix returns the unreserved value
+   * (uid_t) -1 when there is an error.
+   */
+  if (_syscall(MM, GETUID, &m) < 0) return ( (uid_t) -1);
+  return( (uid_t) m.m2_i1);
+}
Index: /trunk/minix/lib/posix/_getgid.c
===================================================================
--- /trunk/minix/lib/posix/_getgid.c	(revision 9)
+++ /trunk/minix/lib/posix/_getgid.c	(revision 9)
@@ -0,0 +1,10 @@
+#include <lib.h>
+#define getgid	_getgid
+#include <unistd.h>
+
+PUBLIC gid_t getgid()
+{
+  message m;
+
+  return( (gid_t) _syscall(MM, GETGID, &m));
+}
Index: /trunk/minix/lib/posix/_getgroups.c
===================================================================
--- /trunk/minix/lib/posix/_getgroups.c	(revision 9)
+++ /trunk/minix/lib/posix/_getgroups.c	(revision 9)
@@ -0,0 +1,18 @@
+/* getgroups.c						POSIX 4.2.3
+ *	int getgroups(gidsetsize, grouplist);
+ *
+ *	This call relates to suplementary group ids, which are not
+ *	supported in MINIX.
+ */
+
+#include <lib.h>
+#define getgroups _getgroups
+#include <unistd.h>
+#include <time.h>
+
+PUBLIC int getgroups(gidsetsize, grouplist)
+int gidsetsize;
+gid_t grouplist[];
+{
+  return(0);
+}
Index: /trunk/minix/lib/posix/_getpgrp.c
===================================================================
--- /trunk/minix/lib/posix/_getpgrp.c	(revision 9)
+++ /trunk/minix/lib/posix/_getpgrp.c	(revision 9)
@@ -0,0 +1,10 @@
+#include <lib.h>
+#define getpgrp	_getpgrp
+#include <unistd.h>
+
+PUBLIC pid_t getpgrp()
+{
+  message m;
+
+  return(_syscall(MM, GETPGRP, &m));
+}
Index: /trunk/minix/lib/posix/_getpid.c
===================================================================
--- /trunk/minix/lib/posix/_getpid.c	(revision 9)
+++ /trunk/minix/lib/posix/_getpid.c	(revision 9)
@@ -0,0 +1,10 @@
+#include <lib.h>
+#define getpid	_getpid
+#include <unistd.h>
+
+PUBLIC pid_t getpid()
+{
+  message m;
+
+  return(_syscall(MM, GETPID, &m));
+}
Index: /trunk/minix/lib/posix/_getppid.c
===================================================================
--- /trunk/minix/lib/posix/_getppid.c	(revision 9)
+++ /trunk/minix/lib/posix/_getppid.c	(revision 9)
@@ -0,0 +1,16 @@
+#include <lib.h>
+#define getppid	_getppid
+#include <unistd.h>
+
+PUBLIC pid_t getppid()
+{
+  message m;
+
+  /* POSIX says that this function is always successful and that no
+   * return value is reserved to indicate an error.  Minix syscalls
+   * are not always successful and Minix returns the reserved value
+   * (pid_t) -1 when there is an error.
+   */
+  if (_syscall(MM, GETPID, &m) < 0) return ( (pid_t) -1);
+  return( (pid_t) m.m2_i1);
+}
Index: /trunk/minix/lib/posix/_getuid.c
===================================================================
--- /trunk/minix/lib/posix/_getuid.c	(revision 9)
+++ /trunk/minix/lib/posix/_getuid.c	(revision 9)
@@ -0,0 +1,10 @@
+#include <lib.h>
+#define getuid	_getuid
+#include <unistd.h>
+
+PUBLIC uid_t getuid()
+{
+  message m;
+
+  return( (uid_t) _syscall(MM, GETUID, &m));
+}
Index: /trunk/minix/lib/posix/_ioctl.c
===================================================================
--- /trunk/minix/lib/posix/_ioctl.c	(revision 9)
+++ /trunk/minix/lib/posix/_ioctl.c	(revision 9)
@@ -0,0 +1,17 @@
+#include <lib.h>
+#define ioctl	_ioctl
+#include <minix/com.h>
+#include <sys/ioctl.h>
+
+PUBLIC int ioctl(fd, request, data)
+int fd;
+int request;
+void *data;
+{
+  message m;
+
+  m.TTY_LINE = fd;
+  m.TTY_REQUEST = request;
+  m.ADDRESS = (char *) data;
+  return(_syscall(FS, IOCTL, &m));
+}
Index: /trunk/minix/lib/posix/_isatty.c
===================================================================
--- /trunk/minix/lib/posix/_isatty.c	(revision 9)
+++ /trunk/minix/lib/posix/_isatty.c	(revision 9)
@@ -0,0 +1,13 @@
+#include <lib.h>
+#define isatty _isatty
+#define tcgetattr _tcgetattr
+#include <termios.h>
+#include <unistd.h>
+
+PUBLIC int isatty(fd)
+int fd;
+{
+  struct termios dummy;
+
+  return(tcgetattr(fd, &dummy) == 0);
+}
Index: /trunk/minix/lib/posix/_kill.c
===================================================================
--- /trunk/minix/lib/posix/_kill.c	(revision 9)
+++ /trunk/minix/lib/posix/_kill.c	(revision 9)
@@ -0,0 +1,14 @@
+#include <lib.h>
+#define kill	_kill
+#include <signal.h>
+
+PUBLIC int kill(proc, sig)
+int proc;			/* which process is to be sent the signal */
+int sig;			/* signal number */
+{
+  message m;
+
+  m.m1_i1 = proc;
+  m.m1_i2 = sig;
+  return(_syscall(MM, KILL, &m));
+}
Index: /trunk/minix/lib/posix/_link.c
===================================================================
--- /trunk/minix/lib/posix/_link.c	(revision 9)
+++ /trunk/minix/lib/posix/_link.c	(revision 9)
@@ -0,0 +1,16 @@
+#include <lib.h>
+#define link	_link
+#include <string.h>
+#include <unistd.h>
+
+PUBLIC int link(name, name2)
+_CONST char *name, *name2;
+{
+  message m;
+
+  m.m1_i1 = strlen(name) + 1;
+  m.m1_i2 = strlen(name2) + 1;
+  m.m1_p1 = (char *) name;
+  m.m1_p2 = (char *) name2;
+  return(_syscall(FS, LINK, &m));
+}
Index: /trunk/minix/lib/posix/_lseek.c
===================================================================
--- /trunk/minix/lib/posix/_lseek.c	(revision 9)
+++ /trunk/minix/lib/posix/_lseek.c	(revision 9)
@@ -0,0 +1,17 @@
+#include <lib.h>
+#define lseek	_lseek
+#include <unistd.h>
+
+PUBLIC off_t lseek(fd, offset, whence)
+int fd;
+off_t offset;
+int whence;
+{
+  message m;
+
+  m.m2_i1 = fd;
+  m.m2_l1 = offset;
+  m.m2_i2 = whence;
+  if (_syscall(FS, LSEEK, &m) < 0) return( (off_t) -1);
+  return( (off_t) m.m2_l1);
+}
Index: /trunk/minix/lib/posix/_lstat.c
===================================================================
--- /trunk/minix/lib/posix/_lstat.c	(revision 9)
+++ /trunk/minix/lib/posix/_lstat.c	(revision 9)
@@ -0,0 +1,19 @@
+#include <lib.h>
+#define lstat	_lstat
+#include <sys/stat.h>
+#include <string.h>
+
+PUBLIC int lstat(name, buffer)
+_CONST char *name;
+struct stat *buffer;
+{
+  message m;
+  int r;
+
+  m.m1_i1 = strlen(name) + 1;
+  m.m1_p1 = (char *) name;
+  m.m1_p2 = (char *) buffer;
+  if((r = _syscall(FS, LSTAT, &m)) >= 0 || errno != ENOSYS)
+     return r;
+  return _stat(name, buffer);
+}
Index: /trunk/minix/lib/posix/_mkdir.c
===================================================================
--- /trunk/minix/lib/posix/_mkdir.c	(revision 9)
+++ /trunk/minix/lib/posix/_mkdir.c	(revision 9)
@@ -0,0 +1,16 @@
+#include <lib.h>
+#define mkdir	_mkdir
+#include <sys/stat.h>
+#include <string.h>
+
+PUBLIC int mkdir(name, mode)
+_CONST char *name;
+_mnx_Mode_t mode;
+{
+  message m;
+
+  m.m1_i1 = strlen(name) + 1;
+  m.m1_i2 = mode;
+  m.m1_p1 = (char *) name;
+  return(_syscall(FS, MKDIR, &m));
+}
Index: /trunk/minix/lib/posix/_mkfifo.c
===================================================================
--- /trunk/minix/lib/posix/_mkfifo.c	(revision 9)
+++ /trunk/minix/lib/posix/_mkfifo.c	(revision 9)
@@ -0,0 +1,12 @@
+#include <lib.h>
+#define mkfifo	_mkfifo
+#define mknod	_mknod
+#include <sys/stat.h>
+#include <unistd.h>
+
+PUBLIC int mkfifo(name, mode)
+_CONST char *name;
+_mnx_Mode_t mode;
+{
+  return mknod(name, mode | S_IFIFO, (Dev_t) 0);
+}
Index: /trunk/minix/lib/posix/_mknod.c
===================================================================
--- /trunk/minix/lib/posix/_mknod.c	(revision 9)
+++ /trunk/minix/lib/posix/_mknod.c	(revision 9)
@@ -0,0 +1,20 @@
+#include <lib.h>
+#define mknod	_mknod
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+PUBLIC int mknod(name, mode, dev)
+_CONST char *name;
+_mnx_Mode_t mode;
+Dev_t dev;
+{
+  message m;
+
+  m.m1_i1 = strlen(name) + 1;
+  m.m1_i2 = mode;
+  m.m1_i3 = dev;
+  m.m1_p1 = (char *) name;
+  m.m1_p2 = (char *) ((int) 0);		/* obsolete size field */
+  return(_syscall(FS, MKNOD, &m));
+}
Index: /trunk/minix/lib/posix/_mount.c
===================================================================
--- /trunk/minix/lib/posix/_mount.c	(revision 9)
+++ /trunk/minix/lib/posix/_mount.c	(revision 9)
@@ -0,0 +1,18 @@
+#include <lib.h>
+#define mount	_mount
+#include <string.h>
+#include <unistd.h>
+
+PUBLIC int mount(special, name, rwflag)
+char *name, *special;
+int rwflag;
+{
+  message m;
+
+  m.m1_i1 = strlen(special) + 1;
+  m.m1_i2 = strlen(name) + 1;
+  m.m1_i3 = rwflag;
+  m.m1_p1 = special;
+  m.m1_p2 = name;
+  return(_syscall(FS, MOUNT, &m));
+}
Index: /trunk/minix/lib/posix/_open.c
===================================================================
--- /trunk/minix/lib/posix/_open.c	(revision 9)
+++ /trunk/minix/lib/posix/_open.c	(revision 9)
@@ -0,0 +1,30 @@
+#include <lib.h>
+#define open	_open
+#include <fcntl.h>
+#include <stdarg.h>
+#include <string.h>
+
+#if _ANSI
+PUBLIC int open(const char *name, int flags, ...)
+#else
+PUBLIC int open(name, flags)
+_CONST char *name;
+int flags;
+#endif
+{
+  va_list argp;
+  message m;
+
+  va_start(argp, flags);
+  if (flags & O_CREAT) {
+	m.m1_i1 = strlen(name) + 1;
+	m.m1_i2 = flags;
+	m.m1_i3 = va_arg(argp, _mnx_Mode_t);
+	m.m1_p1 = (char *) name;
+  } else {
+	_loadname(name, &m);
+	m.m3_i2 = flags;
+  }
+  va_end(argp);
+  return (_syscall(FS, OPEN, &m));
+}
Index: /trunk/minix/lib/posix/_opendir.c
===================================================================
--- /trunk/minix/lib/posix/_opendir.c	(revision 9)
+++ /trunk/minix/lib/posix/_opendir.c	(revision 9)
@@ -0,0 +1,53 @@
+/*	opendir()					Author: Kees J. Bot
+ *								24 Apr 1989
+ */
+#define nil 0
+#include <lib.h>
+#define close	_close
+#define fcntl	_fcntl
+#define fstat	_fstat
+#define open	_open
+#define opendir	_opendir
+#define stat	_stat
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+
+DIR *opendir(const char *name)
+/* Open a directory for reading. */
+{
+	int d, f;
+	DIR *dp;
+	struct stat st;
+
+	/* Only read directories. */
+	if (stat(name, &st) < 0) return nil;
+	if (!S_ISDIR(st.st_mode)) { errno= ENOTDIR; return nil; }
+
+	if ((d= open(name, O_RDONLY | O_NONBLOCK)) < 0) return nil;
+
+	/* Check the type again, mark close-on-exec, get a buffer. */
+	if (fstat(d, &st) < 0
+		|| (errno= ENOTDIR, !S_ISDIR(st.st_mode))
+		|| (f= fcntl(d, F_GETFD)) < 0
+		|| fcntl(d, F_SETFD, f | FD_CLOEXEC) < 0
+		|| (dp= (DIR *) malloc(sizeof(*dp))) == nil
+	) {
+		int err= errno;
+		(void) close(d);
+		errno= err;
+		return nil;
+	}
+
+	dp->_fd= d;
+	dp->_v7= -1;
+	dp->_count= 0;
+	dp->_pos= 0;
+
+	return dp;
+}
+
Index: /trunk/minix/lib/posix/_pathconf.c
===================================================================
--- /trunk/minix/lib/posix/_pathconf.c	(revision 9)
+++ /trunk/minix/lib/posix/_pathconf.c	(revision 9)
@@ -0,0 +1,28 @@
+/* POSIX pathconf (Sec. 5.7.1) 		Author: Andy Tanenbaum */
+
+#include <lib.h>
+#define close		_close
+#define open		_open
+#define pathconf	_pathconf
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+PUBLIC long pathconf(path, name)
+_CONST char *path;		/* name of file being interrogated */
+int name;			/* property being inspected */
+{
+/* POSIX allows some of the values in <limits.h> to be increased at
+ * run time.  The pathconf and fpathconf functions allow these values
+ * to be checked at run time.  MINIX does not use this facility.
+ * The run-time limits are those given in <limits.h>.
+ */
+
+  int fd;
+  long val;
+
+  if ( (fd = open(path, O_RDONLY)) < 0) return(-1L);
+  val = fpathconf(fd, name);
+  close(fd);
+  return(val);
+}
Index: /trunk/minix/lib/posix/_pause.c
===================================================================
--- /trunk/minix/lib/posix/_pause.c	(revision 9)
+++ /trunk/minix/lib/posix/_pause.c	(revision 9)
@@ -0,0 +1,10 @@
+#include <lib.h>
+#define pause	_pause
+#include <unistd.h>
+
+PUBLIC int pause()
+{
+  message m;
+
+  return(_syscall(MM, PAUSE, &m));
+}
Index: /trunk/minix/lib/posix/_pipe.c
===================================================================
--- /trunk/minix/lib/posix/_pipe.c	(revision 9)
+++ /trunk/minix/lib/posix/_pipe.c	(revision 9)
@@ -0,0 +1,14 @@
+#include <lib.h>
+#define pipe	_pipe
+#include <unistd.h>
+
+PUBLIC int pipe(fild)
+int fild[2];
+{
+  message m;
+
+  if (_syscall(FS, PIPE, &m) < 0) return(-1);
+  fild[0] = m.m1_i1;
+  fild[1] = m.m1_i2;
+  return(0);
+}
Index: /trunk/minix/lib/posix/_ptrace.c
===================================================================
--- /trunk/minix/lib/posix/_ptrace.c	(revision 9)
+++ /trunk/minix/lib/posix/_ptrace.c	(revision 9)
@@ -0,0 +1,25 @@
+#include <lib.h>
+#define ptrace	_ptrace
+#include <unistd.h>
+
+PUBLIC long ptrace(req, pid, addr, data)
+int req;
+pid_t pid;
+long addr;
+long data;
+{
+  message m;
+
+  m.m2_i1 = pid;
+  m.m2_i2 = req;
+  m.m2_l1 = addr;
+  m.m2_l2 = data;
+  if (_syscall(MM, PTRACE, &m) < 0) return(-1);
+
+  /* There was no error, but -1 is a legal return value.  Clear errno if
+   * necessary to distinguish this case.  _syscall has set errno to nonzero
+   * for the error case.
+   */
+  if (m.m2_l2 == -1) errno = 0;
+  return(m.m2_l2);
+}
Index: /trunk/minix/lib/posix/_read.c
===================================================================
--- /trunk/minix/lib/posix/_read.c	(revision 9)
+++ /trunk/minix/lib/posix/_read.c	(revision 9)
@@ -0,0 +1,16 @@
+#include <lib.h>
+#define read	_read
+#include <unistd.h>
+
+PUBLIC ssize_t read(fd, buffer, nbytes)
+int fd;
+void *buffer;
+size_t nbytes;
+{
+  message m;
+
+  m.m1_i1 = fd;
+  m.m1_i2 = nbytes;
+  m.m1_p1 = (char *) buffer;
+  return(_syscall(FS, READ, &m));
+}
Index: /trunk/minix/lib/posix/_readdir.c
===================================================================
--- /trunk/minix/lib/posix/_readdir.c	(revision 9)
+++ /trunk/minix/lib/posix/_readdir.c	(revision 9)
@@ -0,0 +1,59 @@
+/*	readdir()					Author: Kees J. Bot
+ *								24 Apr 1989
+ */
+#define nil 0
+#include <lib.h>
+#define read	_read
+#define readdir	_readdir
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+
+#define v7ent(p)	((struct _v7_direct *) (p))
+#define V7_EXTENT	(sizeof(struct _v7_direct) / sizeof(struct _fl_direct) - 1)
+
+struct dirent *readdir(DIR *dp)
+/* Return the next entry in a directory.  Handle V7 and FLEX format dirs. */
+{
+	struct dirent *e;
+
+	if (dp == nil) { errno= EBADF; return nil; }
+
+	do {
+		if (dp->_count <= 0) {
+			/* Read the next directory block. */
+			dp->_count= read(dp->_fd, dp->_buf, sizeof(dp->_buf));
+			if (dp->_count <= 0) return nil;
+
+			dp->_count/= sizeof(dp->_buf[0]);
+			dp->_ptr= dp->_buf;
+
+			/* Extent is zero of the first flex entry. */
+			if (dp->_v7 == (char)-1) dp->_v7= dp->_buf[0].d_extent;
+		}
+
+		if (!dp->_v7) {
+			/* FLEX. */
+			e= (struct dirent *) dp->_ptr;
+		} else {
+			/* V7: transform to FLEX. */
+			e= (struct dirent *) dp->_v7f;
+			e->d_ino= v7ent(dp->_ptr)->d_ino;
+			e->d_extent= V7_EXTENT;
+			memcpy(e->d_name, v7ent(dp->_ptr)->d_name, DIRSIZ);
+			e->d_name[DIRSIZ]= 0;
+		}
+
+		dp->_ptr+= 1 + e->d_extent;
+		dp->_count-= 1 + e->d_extent;
+		dp->_pos+= (1 + e->d_extent) * sizeof(*dp->_ptr);
+
+	} while (e->d_ino == 0);
+	return e;
+}
Index: /trunk/minix/lib/posix/_readlink.c
===================================================================
--- /trunk/minix/lib/posix/_readlink.c	(revision 9)
+++ /trunk/minix/lib/posix/_readlink.c	(revision 9)
@@ -0,0 +1,19 @@
+#include <lib.h>
+#define readlink _readlink
+#include <unistd.h>
+#include <string.h>
+
+PUBLIC int readlink(name, buffer, bufsiz)
+_CONST char *name;
+char *buffer;
+size_t bufsiz;
+{
+  message m;
+
+  m.m1_i1 = strlen(name) + 1;
+  m.m1_i2 = bufsiz;
+  m.m1_p1 = (char *) name;
+  m.m1_p2 = (char *) buffer;
+
+  return(_syscall(FS, RDLNK, &m));
+}
Index: /trunk/minix/lib/posix/_rename.c
===================================================================
--- /trunk/minix/lib/posix/_rename.c	(revision 9)
+++ /trunk/minix/lib/posix/_rename.c	(revision 9)
@@ -0,0 +1,16 @@
+#include <lib.h>
+#define rename	_rename
+#include <string.h>
+#include <stdio.h>
+
+PUBLIC int rename(name, name2)
+_CONST char *name, *name2;
+{
+  message m;
+
+  m.m1_i1 = strlen(name) + 1;
+  m.m1_i2 = strlen(name2) + 1;
+  m.m1_p1 = (char *) name;
+  m.m1_p2 = (char *) name2;
+  return(_syscall(FS, RENAME, &m));
+}
Index: /trunk/minix/lib/posix/_rewinddir.c
===================================================================
--- /trunk/minix/lib/posix/_rewinddir.c	(revision 9)
+++ /trunk/minix/lib/posix/_rewinddir.c	(revision 9)
@@ -0,0 +1,14 @@
+/*	rewinddir()					Author: Kees J. Bot
+ *								24 Apr 1989
+ */
+#define nil 0
+#include <lib.h>
+#define rewinddir _rewinddir
+#define seekdir	_seekdir
+#include <sys/types.h>
+#include <dirent.h>
+
+void rewinddir(DIR *dp)
+{
+	(void) seekdir(dp, 0);
+}
Index: /trunk/minix/lib/posix/_rmdir.c
===================================================================
--- /trunk/minix/lib/posix/_rmdir.c	(revision 9)
+++ /trunk/minix/lib/posix/_rmdir.c	(revision 9)
@@ -0,0 +1,12 @@
+#include <lib.h>
+#define rmdir	_rmdir
+#include <unistd.h>
+
+PUBLIC int rmdir(name)
+_CONST char *name;
+{
+  message m;
+
+  _loadname(name, &m);
+  return(_syscall(FS, RMDIR, &m));
+}
Index: /trunk/minix/lib/posix/_select.c
===================================================================
--- /trunk/minix/lib/posix/_select.c	(revision 9)
+++ /trunk/minix/lib/posix/_select.c	(revision 9)
@@ -0,0 +1,20 @@
+
+#include <lib.h>
+#include <sys/time.h>
+#include <sys/select.h>
+
+PUBLIC int select(int nfds,
+	fd_set *readfds, fd_set *writefds, fd_set *errorfds,
+	struct timeval *timeout)
+{
+  message m;
+
+  m.SEL_NFDS = nfds;
+  m.SEL_READFDS = (char *) readfds;
+  m.SEL_WRITEFDS = (char *) writefds;
+  m.SEL_ERRORFDS = (char *) errorfds;
+  m.SEL_TIMEOUT = (char *) timeout;
+
+  return (_syscall(FS, SELECT, &m));
+}
+
Index: /trunk/minix/lib/posix/_setgid.c
===================================================================
--- /trunk/minix/lib/posix/_setgid.c	(revision 9)
+++ /trunk/minix/lib/posix/_setgid.c	(revision 9)
@@ -0,0 +1,22 @@
+#include <lib.h>
+#define setgid	_setgid
+#define setegid	_setegid
+#include <unistd.h>
+
+PUBLIC int setgid(grp)
+gid_t grp;
+{
+  message m;
+
+  m.m1_i1 = (int) grp;
+  return(_syscall(MM, SETGID, &m));
+}
+
+PUBLIC int setegid(grp)
+gid_t grp;
+{
+  message m;
+
+  m.m1_i1 = (int) grp;
+  return(_syscall(MM, SETEGID, &m));
+}
Index: /trunk/minix/lib/posix/_setsid.c
===================================================================
--- /trunk/minix/lib/posix/_setsid.c	(revision 9)
+++ /trunk/minix/lib/posix/_setsid.c	(revision 9)
@@ -0,0 +1,10 @@
+#include <lib.h>
+#define setsid	_setsid
+#include <unistd.h>
+
+PUBLIC pid_t setsid()
+{
+  message m;
+
+  return(_syscall(MM, SETSID, &m));
+}
Index: /trunk/minix/lib/posix/_setuid.c
===================================================================
--- /trunk/minix/lib/posix/_setuid.c	(revision 9)
+++ /trunk/minix/lib/posix/_setuid.c	(revision 9)
@@ -0,0 +1,22 @@
+#include <lib.h>
+#define setuid	_setuid
+#define seteuid	_seteuid
+#include <unistd.h>
+
+PUBLIC int setuid(usr)
+_mnx_Uid_t usr;
+{
+  message m;
+
+  m.m1_i1 = usr;
+  return(_syscall(MM, SETUID, &m));
+}
+
+PUBLIC int seteuid(usr)
+_mnx_Uid_t usr;
+{
+  message m;
+
+  m.m1_i1 = usr;
+  return(_syscall(MM, SETEUID, &m));
+}
Index: /trunk/minix/lib/posix/_sigaction.c
===================================================================
--- /trunk/minix/lib/posix/_sigaction.c	(revision 9)
+++ /trunk/minix/lib/posix/_sigaction.c	(revision 9)
@@ -0,0 +1,23 @@
+#include <lib.h>
+#define sigaction _sigaction
+#include <sys/sigcontext.h>
+#include <signal.h>
+
+_PROTOTYPE(int __sigreturn, (void));
+
+PUBLIC int sigaction(sig, act, oact)
+int sig;
+_CONST struct sigaction *act;
+struct sigaction *oact;
+{
+  message m;
+
+  m.m1_i2 = sig;
+
+  /* XXX - yet more type puns because message struct is short of types. */
+  m.m1_p1 = (char *) act;
+  m.m1_p2 = (char *) oact;
+  m.m1_p3 = (char *) __sigreturn;
+
+  return(_syscall(MM, SIGACTION, &m));
+}
Index: /trunk/minix/lib/posix/_sigpending.c
===================================================================
--- /trunk/minix/lib/posix/_sigpending.c	(revision 9)
+++ /trunk/minix/lib/posix/_sigpending.c	(revision 9)
@@ -0,0 +1,13 @@
+#include <lib.h>
+#define sigpending _sigpending
+#include <signal.h>
+
+PUBLIC int sigpending(set)
+sigset_t *set;
+{
+  message m;
+
+  if (_syscall(MM, SIGPENDING, &m) < 0) return(-1);
+  *set = (sigset_t) m.m2_l1;
+  return(m.m_type);
+}
Index: /trunk/minix/lib/posix/_sigprocmask.c
===================================================================
--- /trunk/minix/lib/posix/_sigprocmask.c	(revision 9)
+++ /trunk/minix/lib/posix/_sigprocmask.c	(revision 9)
@@ -0,0 +1,22 @@
+#include <lib.h>
+#define sigprocmask _sigprocmask
+#include <signal.h>
+
+PUBLIC int sigprocmask(how, set, oset)
+int how;
+_CONST sigset_t *set;
+sigset_t *oset;
+{
+  message m;
+
+  if (set == (sigset_t *) NULL) {
+	m.m2_i1 = SIG_INQUIRE;
+	m.m2_l1 = 0;
+  } else {
+	m.m2_i1 = how;
+	m.m2_l1 = (long) *set;
+  }
+  if (_syscall(MM, SIGPROCMASK, &m) < 0) return(-1);
+  if (oset != (sigset_t *) NULL) *oset = (sigset_t) (m.m2_l1);
+  return(m.m_type);
+}
Index: /trunk/minix/lib/posix/_sigreturn.c
===================================================================
--- /trunk/minix/lib/posix/_sigreturn.c	(revision 9)
+++ /trunk/minix/lib/posix/_sigreturn.c	(revision 9)
@@ -0,0 +1,60 @@
+#include <lib.h>
+#define sigfillset	_sigfillset
+#define sigjmp		_sigjmp
+#define sigprocmask	_sigprocmask
+#define sigreturn	_sigreturn
+#include <sys/sigcontext.h>
+#include <setjmp.h>
+#include <signal.h>
+
+_PROTOTYPE( int sigjmp, (jmp_buf jb, int retval));
+
+#if (_SETJMP_SAVES_REGS == 0)
+/* 'sigreturn' using a short format jmp_buf (no registers saved). */
+PUBLIC int sigjmp(jb, retval)
+jmp_buf jb;
+int retval;
+{
+  struct sigcontext sc;
+
+  sc.sc_flags = jb[0].__flags;
+  sc.sc_mask = jb[0].__mask;
+
+#if (CHIP == INTEL)
+  sc.sc_pc = (int) jb[0].__pc;
+  sc.sc_sp = (int) jb[0].__sp;
+  sc.sc_fp = (int) jb[0].__lb;
+#endif
+
+#if (CHIP == M68000)
+  sc.sc_pc = (long) jb[0].__pc;
+  sc.sc_sp = (long) jb[0].__sp;
+  sc.sc_fp = (long) jb[0].__lb;
+#endif
+
+  sc.sc_retreg = retval;
+  return sigreturn(&sc);
+}
+#endif
+
+PUBLIC int sigreturn(scp)
+register struct sigcontext *scp;
+{
+  sigset_t set;
+
+  /* The message can't be on the stack, because the stack will vanish out
+   * from under us.  The send part of sendrec will succeed, but when
+   * a message is sent to restart the current process, who knows what will
+   * be in the place formerly occupied by the message?
+   */
+  static message m;
+
+  /* Protect against race conditions by blocking all interrupts. */
+  sigfillset(&set);		/* splhi */
+  sigprocmask(SIG_SETMASK, &set, (sigset_t *) NULL);
+
+  m.m2_l1 = scp->sc_mask;
+  m.m2_i2 = scp->sc_flags;
+  m.m2_p1 = (char *) scp;
+  return(_syscall(MM, SIGRETURN, &m));	/* normally this doesn't return */
+}
Index: /trunk/minix/lib/posix/_sigset.c
===================================================================
--- /trunk/minix/lib/posix/_sigset.c	(revision 9)
+++ /trunk/minix/lib/posix/_sigset.c	(revision 9)
@@ -0,0 +1,75 @@
+#include <lib.h>
+/* XXX - these have to be hidden because signal() uses them and signal() is
+ * ANSI and not POSIX.  It would be surely be better to use macros for the
+ * library and system uses, and perhaps macros as well as functions for the
+ * POSIX user interface.  The macros would not need underlines.  It may be
+ * inconvenient to match the exact semantics of the current functions
+ * because the interface is bloated by reporting errors.  For library and
+ * system uses, the signal number is mostly already known to be valid
+ * before the sigset-changing routines are called.
+ */
+#define sigaddset	_sigaddset
+#define sigdelset	_sigdelset
+#define sigemptyset	_sigemptyset
+#define sigfillset	_sigfillset
+#define sigismember	_sigismember
+#include <signal.h>
+
+/* Low bit of signal masks. */
+#define SIGBIT_0	((sigset_t) 1)
+
+/* Mask of valid signals (0 - _NSIG). */
+#define SIGMASK		(((SIGBIT_0 << _NSIG) << 1) - 1)
+
+#define sigisvalid(signo) ((unsigned) (signo) <= _NSIG)
+
+PUBLIC int sigaddset(set, signo)
+sigset_t *set;
+int signo;
+{
+  if (!sigisvalid(signo)) {
+  	errno = EINVAL;
+	return -1;
+  }
+  *set |= SIGBIT_0 << signo;
+  return 0;
+}
+
+PUBLIC int sigdelset(set, signo)
+sigset_t *set;
+int signo;
+{
+  if (!sigisvalid(signo)) {
+  	errno = EINVAL;
+	return -1;
+  }
+  *set &= ~(SIGBIT_0 << signo);
+  return 0;
+}
+
+PUBLIC int sigemptyset(set)
+sigset_t *set;
+{
+  *set = 0;
+  return 0;
+}
+
+PUBLIC int sigfillset(set)
+sigset_t *set;
+{
+  *set = SIGMASK;
+  return 0;
+}
+
+PUBLIC int sigismember(set, signo)
+_CONST sigset_t *set;
+int signo;
+{
+  if (!sigisvalid(signo)) {
+  	errno = EINVAL;
+	return -1;
+  }
+  if (*set & (SIGBIT_0 << signo))
+  	return 1;
+  return 0;
+}
Index: /trunk/minix/lib/posix/_sigsetjmp.c
===================================================================
--- /trunk/minix/lib/posix/_sigsetjmp.c	(revision 9)
+++ /trunk/minix/lib/posix/_sigsetjmp.c	(revision 9)
@@ -0,0 +1,13 @@
+#include <lib.h>
+#include <sys/sigcontext.h>
+#include <setjmp.h>
+
+PUBLIC void siglongjmp(env, val)
+sigjmp_buf env;
+int val;
+{
+  if (env[0].__flags & SC_SIGCONTEXT)
+	longjmp(env, val);
+  else
+	_longjmp(env, val);
+}
Index: /trunk/minix/lib/posix/_sigsuspend.c
===================================================================
--- /trunk/minix/lib/posix/_sigsuspend.c	(revision 9)
+++ /trunk/minix/lib/posix/_sigsuspend.c	(revision 9)
@@ -0,0 +1,12 @@
+#include <lib.h>
+#define sigsuspend _sigsuspend
+#include <signal.h>
+
+PUBLIC int sigsuspend(set)
+_CONST sigset_t *set;
+{
+  message m;
+
+  m.m2_l1 = (long) *set;
+  return(_syscall(MM, SIGSUSPEND, &m));
+}
Index: /trunk/minix/lib/posix/_sleep.c
===================================================================
--- /trunk/minix/lib/posix/_sleep.c	(revision 9)
+++ /trunk/minix/lib/posix/_sleep.c	(revision 9)
@@ -0,0 +1,69 @@
+/*	sleep() - Sleep for a number of seconds.	Author: Kees J. Bot
+ *								24 Apr 2000
+ * (Inspired by the Minix-vmd version of same, except that
+ * this implementation doesn't bother to check if all the signal
+ * functions succeed.  Under Minix that is no problem.)
+ */
+
+#include <lib.h>
+#define sleep _sleep
+#include <signal.h>
+#include <unistd.h>
+#include <time.h>
+
+static void handler(int sig)
+{
+	/* Dummy signal handler. */
+}
+
+unsigned sleep(unsigned sleep_seconds)
+{
+	sigset_t ss_full, ss_orig, ss_alarm;
+	struct sigaction action_alarm, action_orig;
+	unsigned alarm_seconds, nap_seconds;
+
+	if (sleep_seconds == 0) return 0;	/* No rest for the wicked */
+
+	/* Mask all signals. */
+	sigfillset(&ss_full);
+	sigprocmask(SIG_BLOCK, &ss_full, &ss_orig);
+
+	/* Cancel currently running alarm. */
+	alarm_seconds= alarm(0);
+
+	/* How long can we nap without interruptions? */
+	nap_seconds= sleep_seconds;
+	if (alarm_seconds != 0 && alarm_seconds < sleep_seconds) {
+		nap_seconds= alarm_seconds;
+	}
+
+	/* Now sleep. */
+	action_alarm.sa_handler= handler;
+	sigemptyset(&action_alarm.sa_mask);
+	action_alarm.sa_flags= 0;
+	sigaction(SIGALRM, &action_alarm, &action_orig);
+	alarm(nap_seconds);
+
+	/* Wait for a wakeup call, either our alarm, or some other signal. */
+	ss_alarm= ss_orig;
+	sigdelset(&ss_alarm, SIGALRM);
+	sigsuspend(&ss_alarm);
+
+	/* Cancel alarm, set mask and stuff back to normal. */
+	nap_seconds -= alarm(0);
+	sigaction(SIGALRM, &action_orig, NULL);
+	sigprocmask(SIG_SETMASK, &ss_orig, NULL);
+
+	/* Restore alarm counter to the time remaining. */
+	if (alarm_seconds != 0 && alarm_seconds >= nap_seconds) {
+		alarm_seconds -= nap_seconds;
+		if (alarm_seconds == 0) {
+			raise(SIGALRM);		/* Alarm expires now! */
+		} else {
+			alarm(alarm_seconds);	/* Count time remaining. */
+		}
+	}
+
+	/* Return time not slept. */
+	return sleep_seconds - nap_seconds;
+}
Index: /trunk/minix/lib/posix/_stat.c
===================================================================
--- /trunk/minix/lib/posix/_stat.c	(revision 9)
+++ /trunk/minix/lib/posix/_stat.c	(revision 9)
@@ -0,0 +1,16 @@
+#include <lib.h>
+#define stat	_stat
+#include <sys/stat.h>
+#include <string.h>
+
+PUBLIC int stat(name, buffer)
+_CONST char *name;
+struct stat *buffer;
+{
+  message m;
+
+  m.m1_i1 = strlen(name) + 1;
+  m.m1_p1 = (char *) name;
+  m.m1_p2 = (char *) buffer;
+  return(_syscall(FS, STAT, &m));
+}
Index: /trunk/minix/lib/posix/_stime.c
===================================================================
--- /trunk/minix/lib/posix/_stime.c	(revision 9)
+++ /trunk/minix/lib/posix/_stime.c	(revision 9)
@@ -0,0 +1,13 @@
+#include <lib.h>
+#define stime	_stime
+#include <minix/minlib.h>
+#include <time.h>
+
+PUBLIC int stime(top)
+long *top;
+{
+  message m;
+
+  m.m2_l1 = *top;
+  return(_syscall(MM, STIME, &m));
+}
Index: /trunk/minix/lib/posix/_symlink.c
===================================================================
--- /trunk/minix/lib/posix/_symlink.c	(revision 9)
+++ /trunk/minix/lib/posix/_symlink.c	(revision 9)
@@ -0,0 +1,16 @@
+#include <lib.h>
+#define symlink	_symlink
+#include <string.h>
+#include <unistd.h>
+
+PUBLIC int symlink(name, name2)
+_CONST char *name, *name2;
+{
+  message m;
+
+  m.m1_i1 = strlen(name) + 1;
+  m.m1_i2 = strlen(name2) + 1;
+  m.m1_p1 = (char *) name;
+  m.m1_p2 = (char *) name2;
+  return(_syscall(FS, SYMLINK, &m));
+}
Index: /trunk/minix/lib/posix/_sync.c
===================================================================
--- /trunk/minix/lib/posix/_sync.c	(revision 9)
+++ /trunk/minix/lib/posix/_sync.c	(revision 9)
@@ -0,0 +1,10 @@
+#include <lib.h>
+#define sync	_sync
+#include <unistd.h>
+
+PUBLIC int sync()
+{
+  message m;
+
+  return(_syscall(FS, SYNC, &m));
+}
Index: /trunk/minix/lib/posix/_tcdrain.c
===================================================================
--- /trunk/minix/lib/posix/_tcdrain.c	(revision 9)
+++ /trunk/minix/lib/posix/_tcdrain.c	(revision 9)
@@ -0,0 +1,16 @@
+/*
+posix/_tcdrain.c
+
+Created:	July 26, 1994 by Philip Homburg
+*/
+
+#define tcdrain _tcdrain
+#define ioctl _ioctl
+#include <termios.h>
+#include <sys/ioctl.h>
+
+int tcdrain(fd)
+int fd;
+{
+  return(ioctl(fd, TCDRAIN, (void *)0));
+}
Index: /trunk/minix/lib/posix/_tcflow.c
===================================================================
--- /trunk/minix/lib/posix/_tcflow.c	(revision 9)
+++ /trunk/minix/lib/posix/_tcflow.c	(revision 9)
@@ -0,0 +1,17 @@
+/*
+posix/_tcflow.c
+
+Created:	June 8, 1993 by Philip Homburg
+*/
+
+#define tcflow _tcflow
+#define ioctl _ioctl
+#include <termios.h>
+#include <sys/ioctl.h>
+
+int tcflow(fd, action)
+int fd;
+int action;
+{
+  return(ioctl(fd, TCFLOW, &action));
+}
Index: /trunk/minix/lib/posix/_tcflush.c
===================================================================
--- /trunk/minix/lib/posix/_tcflush.c	(revision 9)
+++ /trunk/minix/lib/posix/_tcflush.c	(revision 9)
@@ -0,0 +1,12 @@
+/*	tcflush() - flush buffered characters		Author: Kees J. Bot
+ *								13 Jan 1994
+ */
+#define tcflush _tcflush
+#define ioctl _ioctl
+#include <termios.h>
+#include <sys/ioctl.h>
+
+int tcflush(int fd, int queue_selector)
+{
+  return(ioctl(fd, TCFLSH, &queue_selector));
+}
Index: /trunk/minix/lib/posix/_tcgetattr.c
===================================================================
--- /trunk/minix/lib/posix/_tcgetattr.c	(revision 9)
+++ /trunk/minix/lib/posix/_tcgetattr.c	(revision 9)
@@ -0,0 +1,12 @@
+#define tcgetattr _tcgetattr
+#define ioctl _ioctl
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <termios.h>
+
+int tcgetattr(fd, termios_p)
+int fd;
+struct termios *termios_p;
+{
+  return(ioctl(fd, TCGETS, termios_p));
+}
Index: /trunk/minix/lib/posix/_tcsendbreak.c
===================================================================
--- /trunk/minix/lib/posix/_tcsendbreak.c	(revision 9)
+++ /trunk/minix/lib/posix/_tcsendbreak.c	(revision 9)
@@ -0,0 +1,12 @@
+/*	tcsendbreak() - send a break			Author: Kees J. Bot
+ *								13 Jan 1994
+ */
+#define tcsendbreak _tcsendbreak
+#define ioctl _ioctl
+#include <termios.h>
+#include <sys/ioctl.h>
+
+int tcsendbreak(int fd, int duration)
+{
+  return(ioctl(fd, TCSBRK, &duration));
+}
Index: /trunk/minix/lib/posix/_tcsetattr.c
===================================================================
--- /trunk/minix/lib/posix/_tcsetattr.c	(revision 9)
+++ /trunk/minix/lib/posix/_tcsetattr.c	(revision 9)
@@ -0,0 +1,29 @@
+/*
+posix/_tcsetattr.c
+
+Created:	June 11, 1993 by Philip Homburg
+*/
+
+#define tcsetattr _tcsetattr
+#define ioctl _ioctl
+#include <errno.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+int tcsetattr(fd, opt_actions, termios_p)
+int fd;
+int opt_actions;
+_CONST struct termios *termios_p;
+{
+  int request;
+
+  switch(opt_actions)
+  {
+    case TCSANOW:	request = TCSETS;	break;
+    case TCSADRAIN:	request = TCSETSW;	break;
+    case TCSAFLUSH:	request = TCSETSF;	break;
+    default:		errno = EINVAL;		return(-1);
+  };
+  return(ioctl(fd, request, (void *) termios_p));
+}
Index: /trunk/minix/lib/posix/_time.c
===================================================================
--- /trunk/minix/lib/posix/_time.c	(revision 9)
+++ /trunk/minix/lib/posix/_time.c	(revision 9)
@@ -0,0 +1,13 @@
+#include <lib.h>
+#define time	_time
+#include <time.h>
+
+PUBLIC time_t time(tp)
+time_t *tp;
+{
+  message m;
+
+  if (_syscall(MM, TIME, &m) < 0) return( (time_t) -1);
+  if (tp != (time_t *) 0) *tp = m.m2_l1;
+  return(m.m2_l1);
+}
Index: /trunk/minix/lib/posix/_times.c
===================================================================
--- /trunk/minix/lib/posix/_times.c	(revision 9)
+++ /trunk/minix/lib/posix/_times.c	(revision 9)
@@ -0,0 +1,18 @@
+#include <lib.h>
+#define times	_times
+#include <sys/times.h>
+#include <time.h>
+
+PUBLIC clock_t times(buf)
+struct tms *buf;
+{
+  message m;
+
+  m.m4_l5 = 0;			/* return this if system is pre-1.6 */
+  if (_syscall(MM, TIMES, &m) < 0) return( (clock_t) -1);
+  buf->tms_utime = m.m4_l1;
+  buf->tms_stime = m.m4_l2;
+  buf->tms_cutime = m.m4_l3;
+  buf->tms_cstime = m.m4_l4;
+  return(m.m4_l5);
+}
Index: /trunk/minix/lib/posix/_truncate.c
===================================================================
--- /trunk/minix/lib/posix/_truncate.c	(revision 9)
+++ /trunk/minix/lib/posix/_truncate.c	(revision 9)
@@ -0,0 +1,24 @@
+#include <lib.h>
+#include <string.h>
+#define truncate	_truncate
+#define ftruncate	_ftruncate
+#include <unistd.h>
+
+PUBLIC int truncate(const char *_path, off_t _length)
+{
+  message m;
+  m.m2_p1 = (char *) _path;
+  m.m2_i1 = strlen(_path)+1;
+  m.m2_l1 = _length;
+
+  return(_syscall(FS, TRUNCATE, &m));
+}
+
+PUBLIC int ftruncate(int _fd, off_t _length)
+{
+  message m;
+  m.m2_l1 = _length;
+  m.m2_i1 = _fd;
+
+  return(_syscall(FS, FTRUNCATE, &m));
+}
Index: /trunk/minix/lib/posix/_umask.c
===================================================================
--- /trunk/minix/lib/posix/_umask.c	(revision 9)
+++ /trunk/minix/lib/posix/_umask.c	(revision 9)
@@ -0,0 +1,12 @@
+#include <lib.h>
+#define umask	_umask
+#include <sys/stat.h>
+
+PUBLIC mode_t umask(complmode)
+_mnx_Mode_t complmode;
+{
+  message m;
+
+  m.m1_i1 = complmode;
+  return( (mode_t) _syscall(FS, UMASK, &m));
+}
Index: /trunk/minix/lib/posix/_umount.c
===================================================================
--- /trunk/minix/lib/posix/_umount.c	(revision 9)
+++ /trunk/minix/lib/posix/_umount.c	(revision 9)
@@ -0,0 +1,12 @@
+#include <lib.h>
+#define umount	_umount
+#include <unistd.h>
+
+PUBLIC int umount(name)
+_CONST char *name;
+{
+  message m;
+
+  _loadname(name, &m);
+  return(_syscall(FS, UMOUNT, &m));
+}
Index: /trunk/minix/lib/posix/_uname.c
===================================================================
--- /trunk/minix/lib/posix/_uname.c	(revision 9)
+++ /trunk/minix/lib/posix/_uname.c	(revision 9)
@@ -0,0 +1,59 @@
+/*	uname() - get system info			Author: Kees J. Bot
+ *								7 Nov 1994
+ * Returns information about the Minix system.  Alas most
+ * of it is gathered at compile time, so machine is wrong, and
+ * release and version become wrong if not recompiled.
+ * More chip types and Minix versions need to be added.
+ */
+#define uname	_uname
+#define open	_open
+#define read	_read
+#define close	_close
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <minix/config.h>
+#include <minix/com.h>
+#include <minix/minlib.h>
+
+int uname(name) struct utsname *name;
+{
+  int hf, n, err;
+  struct kinfo kinfo;
+  char *nl;
+
+  /* Read the node name from /etc/hostname.file. */
+  if ((hf = open("/etc/hostname.file", O_RDONLY)) < 0) {
+	if (errno != ENOENT) return(-1);
+	strcpy(name->nodename, "noname");
+  } else {
+	n = read(hf, name->nodename, sizeof(name->nodename) - 1);
+	err = errno;
+	close(hf);
+	errno = err;
+	if (n < 0) return(-1);
+	name->nodename[n] = 0;
+	if ((nl = strchr(name->nodename, '\n')) != NULL) {
+		memset(nl, 0, (name->nodename + sizeof(name->nodename)) - nl);
+	}
+  }
+ 
+  getsysinfo(PM_PROC_NR, SI_KINFO, &kinfo);
+
+  strcpy(name->sysname, "Minix");
+  strcpy(name->release, kinfo.release);
+  strcpy(name->version, kinfo.version);
+#if (CHIP == INTEL)
+  name->machine[0] = 'i';
+  strcpy(name->machine + 1, itoa(getprocessor()));
+#if _WORD_SIZE == 4
+  strcpy(name->arch, "i386");
+#else
+  strcpy(name->arch, "i86");
+#endif
+#endif
+  return(0);
+}
Index: /trunk/minix/lib/posix/_unlink.c
===================================================================
--- /trunk/minix/lib/posix/_unlink.c	(revision 9)
+++ /trunk/minix/lib/posix/_unlink.c	(revision 9)
@@ -0,0 +1,12 @@
+#include <lib.h>
+#define unlink	_unlink
+#include <unistd.h>
+
+PUBLIC int unlink(name)
+_CONST char *name;
+{
+  message m;
+
+  _loadname(name, &m);
+  return(_syscall(FS, UNLINK, &m));
+}
Index: /trunk/minix/lib/posix/_utime.c
===================================================================
--- /trunk/minix/lib/posix/_utime.c	(revision 9)
+++ /trunk/minix/lib/posix/_utime.c	(revision 9)
@@ -0,0 +1,24 @@
+/* utime(2) for POSIX		Authors: Terrence W. Holm & Edwin L. Froese */
+
+#include <lib.h>
+#define utime	_utime
+#include <string.h>
+#include <utime.h>
+
+PUBLIC int utime(name, timp)
+_CONST char *name;
+_CONST struct utimbuf *timp;
+{
+  message m;
+
+  if (timp == NULL) {
+	m.m2_i1 = 0;		/* name size 0 means NULL `timp' */
+	m.m2_i2 = strlen(name) + 1;	/* actual size here */
+  } else {
+	m.m2_l1 = timp->actime;
+	m.m2_l2 = timp->modtime;
+	m.m2_i1 = strlen(name) + 1;
+  }
+  m.m2_p1 = (char *) name;
+  return(_syscall(FS, UTIME, &m));
+}
Index: /trunk/minix/lib/posix/_wait.c
===================================================================
--- /trunk/minix/lib/posix/_wait.c	(revision 9)
+++ /trunk/minix/lib/posix/_wait.c	(revision 9)
@@ -0,0 +1,13 @@
+#include <lib.h>
+#define wait	_wait
+#include <sys/wait.h>
+
+PUBLIC pid_t wait(status)
+int *status;
+{
+  message m;
+
+  if (_syscall(MM, WAIT, &m) < 0) return(-1);
+  if (status != 0) *status = m.m2_i1;
+  return(m.m_type);
+}
Index: /trunk/minix/lib/posix/_waitpid.c
===================================================================
--- /trunk/minix/lib/posix/_waitpid.c	(revision 9)
+++ /trunk/minix/lib/posix/_waitpid.c	(revision 9)
@@ -0,0 +1,17 @@
+#include <lib.h>
+#define waitpid	_waitpid
+#include <sys/wait.h>
+
+PUBLIC pid_t waitpid(pid, status, options)
+pid_t pid;
+int *status;
+int options;
+{
+  message m;
+
+  m.m1_i1 = pid;
+  m.m1_i2 = options;
+  if (_syscall(MM, WAITPID, &m) < 0) return(-1);
+  if (status != 0) *status = m.m2_i1;
+  return m.m_type;
+}
Index: /trunk/minix/lib/posix/_write.c
===================================================================
--- /trunk/minix/lib/posix/_write.c	(revision 9)
+++ /trunk/minix/lib/posix/_write.c	(revision 9)
@@ -0,0 +1,16 @@
+#include <lib.h>
+#define write	_write
+#include <unistd.h>
+
+PUBLIC ssize_t write(fd, buffer, nbytes)
+int fd;
+_CONST void *buffer;
+size_t nbytes;
+{
+  message m;
+
+  m.m1_i1 = fd;
+  m.m1_i2 = nbytes;
+  m.m1_p1 = (char *) buffer;
+  return(_syscall(FS, WRITE, &m));
+}
Index: /trunk/minix/lib/posix/getloadavg.c
===================================================================
--- /trunk/minix/lib/posix/getloadavg.c	(revision 9)
+++ /trunk/minix/lib/posix/getloadavg.c	(revision 9)
@@ -0,0 +1,56 @@
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <lib.h>
+
+/* Retrieve system load average information. */
+int getloadavg(double *loadavg, int nelem)
+{
+  struct loadinfo loadinfo;
+  int h, p, unfilled_ticks;
+#define PERIODS 3
+  int minutes[3] = { 1, 5, 15 };
+  if(nelem < 1) {
+	errno = ENOSPC;
+	return -1;
+  }
+
+  if(getsysinfo(PM_PROC_NR, SI_LOADINFO, &loadinfo) < 0)
+	return -1;
+  if(nelem > PERIODS)
+	nelem = PERIODS;
+
+  /* How many ticks are missing from the newest-filled slot? */
+#define TICKSPERSLOT (_LOAD_UNIT_SECS * HZ)
+  unfilled_ticks = TICKSPERSLOT - (loadinfo.last_clock % TICKSPERSLOT);
+
+  for(p = 0; p < nelem; p++) {
+    int h, offset, slots;
+    double l = 0.0;
+    int latest = loadinfo.proc_last_slot;
+    slots = minutes[p] * 60 / _LOAD_UNIT_SECS;
+
+    /* Add up the total number of process ticks for this number
+     * of minutes (minutes[p]). Start with the newest slot, which
+     * is latest, and count back for the number of slots that 
+     * correspond to the right number of minutes. Take wraparound
+     * into account by calculating the index modulo _LOAD_HISTORY,
+     * which is the number of slots of history kept.
+     */
+    for(h = 0; h < slots; h++) {
+       int slot;
+       slot = (latest - h + _LOAD_HISTORY) % _LOAD_HISTORY;
+       l += (double) loadinfo.proc_load_history[slot];
+    }
+
+    /* The load average over this number of minutes is the number of
+     * process-ticks divided by the number of ticks, not counting the
+     * number of ticks the last slot hasn't been around yet.
+     */
+    loadavg[p] = l / (slots * TICKSPERSLOT - unfilled_ticks);
+  }
+
+  return nelem;
+}
+
Index: /trunk/minix/lib/posix/getopt.c
===================================================================
--- /trunk/minix/lib/posix/getopt.c	(revision 9)
+++ /trunk/minix/lib/posix/getopt.c	(revision 9)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 1987, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+int	opterr = 1,		/* if error message should be printed */
+	optind = 1,		/* index into parent argv vector */
+	optopt,			/* character checked for validity */
+	optreset;		/* reset getopt */
+char	*optarg;		/* argument associated with option */
+
+#define	BADCH	(int)'?'
+#define	BADARG	(int)':'
+#define	EMSG	""
+
+/*
+ * getopt --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt(int nargc, char * const nargv[], const char *ostr)
+{
+	static char *place = EMSG;		/* option letter processing */
+	char *oli;				/* option letter list index */
+
+	if (optreset || !*place) {		/* update scanning pointer */
+		optreset = 0;
+		if (optind >= nargc || *(place = nargv[optind]) != '-') {
+			place = EMSG;
+			return (-1);
+		}
+		if (place[1] && *++place == '-') {	/* found "--" */
+			++optind;
+			place = EMSG;
+			return (-1);
+		}
+	}					/* option letter okay? */
+	if ((optopt = (int)*place++) == (int)':' ||
+	    !(oli = strchr(ostr, optopt))) {
+		/*
+		 * if the user didn't specify '-' as an option,
+		 * assume it means -1.
+		 */
+		if (optopt == (int)'-')
+			return (-1);
+		if (!*place)
+			++optind;
+		if (opterr && *ostr != ':')
+			(void)printf("illegal option -- %c\n", optopt);
+		return (BADCH);
+	}
+	if (*++oli != ':') {			/* don't need argument */
+		optarg = NULL;
+		if (!*place)
+			++optind;
+	}
+	else {					/* need an argument */
+		if (*place)			/* no white space */
+			optarg = place;
+		else if (nargc <= ++optind) {	/* no arg */
+			place = EMSG;
+			if (*ostr == ':')
+				return (BADARG);
+			if (opterr)
+				(void)printf("option requires an argument -- %c\n", optopt);
+			return (BADCH);
+		}
+	 	else				/* white space */
+			optarg = nargv[optind];
+		place = EMSG;
+		++optind;
+	}
+	return (optopt);			/* dump back option letter */
+}
Index: /trunk/minix/lib/posix/gettimeofday.c
===================================================================
--- /trunk/minix/lib/posix/gettimeofday.c	(revision 9)
+++ /trunk/minix/lib/posix/gettimeofday.c	(revision 9)
@@ -0,0 +1,21 @@
+/*
+gettimeofday.c
+*/
+
+#include <sys/time.h>
+#include <lib.h>
+#include <time.h>
+
+int gettimeofday(struct timeval *_RESTRICT tp, void *_RESTRICT tzp)
+{
+  message m;
+
+  if (_syscall(MM, GETTIMEOFDAY, &m) < 0)
+  	return -1;
+
+  tp->tv_sec = m.m2_l1;
+  tp->tv_usec = m.m2_l2;
+
+  return 0;
+}
+
Index: /trunk/minix/lib/posix/priority.c
===================================================================
--- /trunk/minix/lib/posix/priority.c	(revision 9)
+++ /trunk/minix/lib/posix/priority.c	(revision 9)
@@ -0,0 +1,46 @@
+/*
+priority.c
+*/
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <lib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stddef.h>
+
+
+int getpriority(int which, int who)
+{
+	int v;
+	message m;
+
+	m.m1_i1 = which;
+	m.m1_i2 = who;
+
+	/* GETPRIORITY returns negative for error.
+	 * Otherwise, it returns the priority plus the minimum
+	 * priority, to distiginuish from error. We have to
+	 * correct for this. (The user program has to check errno
+	 * to see if something really went wrong.)
+	 */
+
+	if((v = _syscall(MM, GETPRIORITY, &m)) < 0) {
+		return v;
+	}
+
+	return v + PRIO_MIN;
+}
+
+int setpriority(int which, int who, int prio)
+{
+	message m;
+
+	m.m1_i1 = which;
+	m.m1_i2 = who;
+	m.m1_i3 = prio;
+
+	return _syscall(MM, SETPRIORITY, &m);
+}
+
Index: /trunk/minix/lib/posix/usleep.c
===================================================================
--- /trunk/minix/lib/posix/usleep.c	(revision 9)
+++ /trunk/minix/lib/posix/usleep.c	(revision 9)
@@ -0,0 +1,18 @@
+/*
+lib/posix/usleep.c
+*/
+
+#include <unistd.h>
+#include <sys/select.h>
+#include <sys/time.h>
+
+int usleep(useconds_t useconds)
+{
+	int r;
+	struct timeval tv;
+
+	tv.tv_sec= useconds/1000000;
+	tv.tv_usec= useconds % 1000000;
+	r= select(0, NULL, NULL, NULL, &tv);
+	return r;
+}
Index: /trunk/minix/lib/regex/COPYRIGHT
===================================================================
--- /trunk/minix/lib/regex/COPYRIGHT	(revision 9)
+++ /trunk/minix/lib/regex/COPYRIGHT	(revision 9)
@@ -0,0 +1,56 @@
+Copyright 1992, 1993, 1994 Henry Spencer.  All rights reserved.
+This software is not subject to any license of the American Telephone
+and Telegraph Company or of the Regents of the University of California.
+
+Permission is granted to anyone to use this software for any purpose on
+any computer system, and to alter it and redistribute it, subject
+to the following restrictions:
+
+1. The author is not responsible for the consequences of use of this
+   software, no matter how awful, even if they arise from flaws in it.
+
+2. The origin of this software must not be misrepresented, either by
+   explicit claim or by omission.  Since few users ever read sources,
+   credits must appear in the documentation.
+
+3. Altered versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.  Since few users
+   ever read sources, credits must appear in the documentation.
+
+4. This notice may not be removed or altered.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+/*-
+ * Copyright (c) 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)COPYRIGHT	8.1 (Berkeley) 3/16/94
+ */
Index: /trunk/minix/lib/regex/Makedepend-ack
===================================================================
--- /trunk/minix/lib/regex/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/regex/Makedepend-ack	(revision 9)
@@ -0,0 +1,7 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' regcomp.c | sed -e 's:^\(.\):../obj-ack//./regex/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' regerror.c | sed -e 's:^\(.\):../obj-ack//./regex/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' regexec.c | sed -e 's:^\(.\):../obj-ack//./regex/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' regfree.c | sed -e 's:^\(.\):../obj-ack//./regex/\1:' >> .depend-ack
Index: /trunk/minix/lib/regex/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/regex/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/regex/Makedepend-gnu	(revision 9)
@@ -0,0 +1,7 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' regcomp.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./regex/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' regerror.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./regex/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' regexec.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./regex/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' regfree.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./regex/\1:' >> .depend-gnu
Index: /trunk/minix/lib/regex/Makefile
===================================================================
--- /trunk/minix/lib/regex/Makefile	(revision 9)
+++ /trunk/minix/lib/regex/Makefile	(revision 9)
@@ -0,0 +1,73 @@
+#Generated from ./regex/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./regex ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./regex ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libc.a
+
+../obj-ack//libc.a: ../obj-ack//libc.a(regcomp.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(regerror.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(regexec.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(regfree.o)
+
+../obj-ack//libc.a:
+	ar cr ../obj-ack//libc.a ../obj-ack//./regex/*.o
+	rm ../obj-ack//./regex/*.o
+
+../obj-ack//libc.a(regcomp.o): regcomp.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./regex/regcomp.o regcomp.c
+../obj-ack//libc.a(regerror.o): regerror.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./regex/regerror.o regerror.c
+../obj-ack//libc.a(regexec.o): regexec.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./regex/regexec.o regexec.c
+../obj-ack//libc.a(regfree.o): regfree.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./regex/regfree.o regfree.c
+
+all-gnu: ../obj-gnu/libc.a
+
+../obj-gnu/libc.a: ../obj-gnu/./regex/regcomp.o
+../obj-gnu/libc.a: ../obj-gnu/./regex/regerror.o
+../obj-gnu/libc.a: ../obj-gnu/./regex/regexec.o
+../obj-gnu/libc.a: ../obj-gnu/./regex/regfree.o
+
+../obj-gnu/libc.a:
+	gar cr ../obj-gnu/libc.a $?
+
+../obj-gnu/./regex/regcomp.o: regcomp.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./regex/regcomp.o regcomp.c
+
+../obj-gnu/./regex/regerror.o: regerror.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./regex/regerror.o regerror.c
+
+../obj-gnu/./regex/regexec.o: regexec.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./regex/regexec.o regexec.c
+
+../obj-gnu/./regex/regfree.o: regfree.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./regex/regfree.o regfree.c
+
+
+
+
+clean::
+	rm -f ../obj-ack//./regex/*
+	rm -f ../obj-gnu/./regex/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/regex/Makefile.in
===================================================================
--- /trunk/minix/lib/regex/Makefile.in	(revision 9)
+++ /trunk/minix/lib/regex/Makefile.in	(revision 9)
@@ -0,0 +1,13 @@
+# Makefile for lib/regex.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
+
+LIBRARIES=libc
+
+libc_FILES=" \
+	regcomp.c \
+	regerror.c \
+	regexec.c \
+	regfree.c"
+
+TYPE=both
Index: /trunk/minix/lib/regex/WHATSNEW
===================================================================
--- /trunk/minix/lib/regex/WHATSNEW	(revision 9)
+++ /trunk/minix/lib/regex/WHATSNEW	(revision 9)
@@ -0,0 +1,94 @@
+# @(#)WHATSNEW	8.3 (Berkeley) 3/18/94
+
+New in alpha3.4:  The complex bug alluded to below has been fixed (in a
+slightly kludgey temporary way that may hurt efficiency a bit; this is
+another "get it out the door for 4.4" release).  The tests at the end of
+the tests file have accordingly been uncommented.  The primary sign of
+the bug was that something like a?b matching ab matched b rather than ab.
+(The bug was essentially specific to this exact situation, else it would
+have shown up earlier.)
+
+New in alpha3.3:  The definition of word boundaries has been altered
+slightly, to more closely match the usual programming notion that "_"
+is an alphabetic.  Stuff used for pre-ANSI systems is now in a subdir,
+and the makefile no longer alludes to it in mysterious ways.  The
+makefile has generally been cleaned up some.  Fixes have been made
+(again!) so that the regression test will run without -DREDEBUG, at
+the cost of weaker checking.  A workaround for a bug in some folks'
+<assert.h> has been added.  And some more things have been added to
+tests, including a couple right at the end which are commented out
+because the code currently flunks them (complex bug; fix coming).
+Plus the usual minor cleanup.
+
+New in alpha3.2:  Assorted bits of cleanup and portability improvement
+(the development base is now a BSDI system using GCC instead of an ancient
+Sun system, and the newer compiler exposed some glitches).  Fix for a
+serious bug that affected REs using many [] (including REG_ICASE REs
+because of the way they are implemented), *sometimes*, depending on
+memory-allocation patterns.  The header-file prototypes no longer name
+the parameters, avoiding possible name conflicts.  The possibility that
+some clot has defined CHAR_MIN as (say) `-128' instead of `(-128)' is
+now handled gracefully.  "uchar" is no longer used as an internal type
+name (too many people have the same idea).  Still the same old lousy
+performance, alas.
+
+New in alpha3.1:  Basically nothing, this release is just a bookkeeping
+convenience.  Stay tuned.
+
+New in alpha3.0:  Performance is no better, alas, but some fixes have been
+made and some functionality has been added.  (This is basically the "get
+it out the door in time for 4.4" release.)  One bug fix:  regfree() didn't
+free the main internal structure (how embarrassing).  It is now possible
+to put NULs in either the RE or the target string, using (resp.) a new
+REG_PEND flag and the old REG_STARTEND flag.  The REG_NOSPEC flag to
+regcomp() makes all characters ordinary, so you can match a literal
+string easily (this will become more useful when performance improves!).
+There are now primitives to match beginnings and ends of words, although
+the syntax is disgusting and so is the implementation.  The REG_ATOI
+debugging interface has changed a bit.  And there has been considerable
+internal cleanup of various kinds.
+
+New in alpha2.3:  Split change list out of README, and moved flags notes
+into Makefile.  Macro-ized the name of regex(7) in regex(3), since it has
+to change for 4.4BSD.  Cleanup work in engine.c, and some new regression
+tests to catch tricky cases thereof.
+
+New in alpha2.2:  Out-of-date manpages updated.  Regerror() acquires two
+small extensions -- REG_ITOA and REG_ATOI -- which avoid debugging kludges
+in my own test program and might be useful to others for similar purposes.
+The regression test will now compile (and run) without REDEBUG.  The
+BRE \$ bug is fixed.  Most uses of "uchar" are gone; it's all chars now.
+Char/uchar parameters are now written int/unsigned, to avoid possible
+portability problems with unpromoted parameters.  Some unsigned casts have
+been introduced to minimize portability problems with shifting into sign
+bits.
+
+New in alpha2.1:  Lots of little stuff, cleanup and fixes.  The one big
+thing is that regex.h is now generated, using mkh, rather than being
+supplied in the distribution; due to circularities in dependencies,
+you have to build regex.h explicitly by "make h".  The two known bugs
+have been fixed (and the regression test now checks for them), as has a
+problem with assertions not being suppressed in the absence of REDEBUG.
+No performance work yet.
+
+New in alpha2:  Backslash-anything is an ordinary character, not an
+error (except, of course, for the handful of backslashed metacharacters
+in BREs), which should reduce script breakage.  The regression test
+checks *where* null strings are supposed to match, and has generally
+been tightened up somewhat.  Small bug fixes in parameter passing (not
+harmful, but technically errors) and some other areas.  Debugging
+invoked by defining REDEBUG rather than not defining NDEBUG.
+
+New in alpha+3:  full prototyping for internal routines, using a little
+helper program, mkh, which extracts prototypes given in stylized comments.
+More minor cleanup.  Buglet fix:  it's CHAR_BIT, not CHAR_BITS.  Simple
+pre-screening of input when a literal string is known to be part of the
+RE; this does wonders for performance.
+
+New in alpha+2:  minor bits of cleanup.  Notably, the number "32" for the
+word width isn't hardwired into regexec.c any more, the public header
+file prototypes the functions if __STDC__ is defined, and some small typos
+in the manpages have been fixed.
+
+New in alpha+1:  improvements to the manual pages, and an important
+extension, the REG_STARTEND option to regexec().
Index: /trunk/minix/lib/regex/cclass.h
===================================================================
--- /trunk/minix/lib/regex/cclass.h	(revision 9)
+++ /trunk/minix/lib/regex/cclass.h	(revision 9)
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)cclass.h	8.3 (Berkeley) 3/20/94
+ */
+
+/* character-class table */
+static struct cclass {
+	char *name;
+	char *chars;
+	char *multis;
+} cclasses[] = {
+	"alnum",	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
+0123456789",				"",
+	"alpha",	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
+					"",
+	"blank",	" \t",		"",
+	"cntrl",	"\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\
+\25\26\27\30\31\32\33\34\35\36\37\177",	"",
+	"digit",	"0123456789",	"",
+	"graph",	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
+0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
+					"",
+	"lower",	"abcdefghijklmnopqrstuvwxyz",
+					"",
+	"print",	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
+0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ",
+					"",
+	"punct",	"!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
+					"",
+	"space",	"\t\n\v\f\r ",	"",
+	"upper",	"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+					"",
+	"xdigit",	"0123456789ABCDEFabcdef",
+					"",
+	NULL,		0,		""
+};
Index: /trunk/minix/lib/regex/cname.h
===================================================================
--- /trunk/minix/lib/regex/cname.h	(revision 9)
+++ /trunk/minix/lib/regex/cname.h	(revision 9)
@@ -0,0 +1,141 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)cname.h	8.3 (Berkeley) 3/20/94
+ */
+
+/* character-name table */
+static struct cname {
+	char *name;
+	char code;
+} cnames[] = {
+	"NUL",	'\0',
+	"SOH",	'\001',
+	"STX",	'\002',
+	"ETX",	'\003',
+	"EOT",	'\004',
+	"ENQ",	'\005',
+	"ACK",	'\006',
+	"BEL",	'\007',
+	"alert",	'\007',
+	"BS",		'\010',
+	"backspace",	'\b',
+	"HT",		'\011',
+	"tab",		'\t',
+	"LF",		'\012',
+	"newline",	'\n',
+	"VT",		'\013',
+	"vertical-tab",	'\v',
+	"FF",		'\014',
+	"form-feed",	'\f',
+	"CR",		'\015',
+	"carriage-return",	'\r',
+	"SO",	'\016',
+	"SI",	'\017',
+	"DLE",	'\020',
+	"DC1",	'\021',
+	"DC2",	'\022',
+	"DC3",	'\023',
+	"DC4",	'\024',
+	"NAK",	'\025',
+	"SYN",	'\026',
+	"ETB",	'\027',
+	"CAN",	'\030',
+	"EM",	'\031',
+	"SUB",	'\032',
+	"ESC",	'\033',
+	"IS4",	'\034',
+	"FS",	'\034',
+	"IS3",	'\035',
+	"GS",	'\035',
+	"IS2",	'\036',
+	"RS",	'\036',
+	"IS1",	'\037',
+	"US",	'\037',
+	"space",		' ',
+	"exclamation-mark",	'!',
+	"quotation-mark",	'"',
+	"number-sign",		'#',
+	"dollar-sign",		'$',
+	"percent-sign",		'%',
+	"ampersand",		'&',
+	"apostrophe",		'\'',
+	"left-parenthesis",	'(',
+	"right-parenthesis",	')',
+	"asterisk",	'*',
+	"plus-sign",	'+',
+	"comma",	',',
+	"hyphen",	'-',
+	"hyphen-minus",	'-',
+	"period",	'.',
+	"full-stop",	'.',
+	"slash",	'/',
+	"solidus",	'/',
+	"zero",		'0',
+	"one",		'1',
+	"two",		'2',
+	"three",	'3',
+	"four",		'4',
+	"five",		'5',
+	"six",		'6',
+	"seven",	'7',
+	"eight",	'8',
+	"nine",		'9',
+	"colon",	':',
+	"semicolon",	';',
+	"less-than-sign",	'<',
+	"equals-sign",		'=',
+	"greater-than-sign",	'>',
+	"question-mark",	'?',
+	"commercial-at",	'@',
+	"left-square-bracket",	'[',
+	"backslash",		'\\',
+	"reverse-solidus",	'\\',
+	"right-square-bracket",	']',
+	"circumflex",		'^',
+	"circumflex-accent",	'^',
+	"underscore",		'_',
+	"low-line",		'_',
+	"grave-accent",		'`',
+	"left-brace",		'{',
+	"left-curly-bracket",	'{',
+	"vertical-line",	'|',
+	"right-brace",		'}',
+	"right-curly-bracket",	'}',
+	"tilde",		'~',
+	"DEL",	'\177',
+	NULL,	0,
+};
Index: /trunk/minix/lib/regex/engine.c
===================================================================
--- /trunk/minix/lib/regex/engine.c	(revision 9)
+++ /trunk/minix/lib/regex/engine.c	(revision 9)
@@ -0,0 +1,1091 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)engine.c	8.5 (Berkeley) 3/20/94
+ */
+
+/*
+ * The matching engine and friends.  This file is #included by regexec.c
+ * after suitable #defines of a variety of macros used herein, so that
+ * different state representations can be used without duplicating masses
+ * of code.
+ */
+
+#ifdef SNAMES
+#define	matcher	smatcher
+#define	fast	sfast
+#define	slow	sslow
+#define	dissect	sdissect
+#define	backref	sbackref
+#define	step	sstep
+#define	print	sprint
+#define	at	sat
+#define	match	smat
+#endif
+#ifdef LNAMES
+#define	matcher	lmatcher
+#define	fast	lfast
+#define	slow	lslow
+#define	dissect	ldissect
+#define	backref	lbackref
+#define	step	lstep
+#define	print	lprint
+#define	at	lat
+#define	match	lmat
+#endif
+
+/* another structure passed up and down to avoid zillions of parameters */
+struct match {
+	struct re_guts *g;
+	int eflags;
+	regmatch_t *pmatch;	/* [nsub+1] (0 element unused) */
+	char *offp;		/* offsets work from here */
+	char *beginp;		/* start of string -- virtual NUL precedes */
+	char *endp;		/* end of string -- virtual NUL here */
+	char *coldp;		/* can be no match starting before here */
+	char **lastpos;		/* [nplus+1] */
+	STATEVARS;
+	states st;		/* current states */
+	states fresh;		/* states for a fresh start */
+	states tmp;		/* temporary */
+	states empty;		/* empty set of states */
+};
+
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === engine.c === */
+static int matcher(struct re_guts *g, char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
+static char *dissect(struct match *m, char *start, char *stop, sopno startst, sopno stopst);
+static char *backref(struct match *m, char *start, char *stop, sopno startst, sopno stopst, sopno lev);
+static char *fast(struct match *m, char *start, char *stop, sopno startst, sopno stopst);
+static char *slow(struct match *m, char *start, char *stop, sopno startst, sopno stopst);
+static states step(struct re_guts *g, sopno start, sopno stop, states bef, int ch, states aft);
+#define	BOL	(OUT+1)
+#define	EOL	(BOL+1)
+#define	BOLEOL	(BOL+2)
+#define	NOTHING	(BOL+3)
+#define	BOW	(BOL+4)
+#define	EOW	(BOL+5)
+#define	CODEMAX	(BOL+5)		/* highest code used */
+#define	NONCHAR(c)	((c) > CHAR_MAX)
+#define	NNONCHAR	(CODEMAX-CHAR_MAX)
+#ifdef REDEBUG
+static void print(struct match *m, char *caption, states st, int ch, FILE *d);
+#endif
+#ifdef REDEBUG
+static void at(struct match *m, char *title, char *start, char *stop, sopno startst, sopno stopst);
+#endif
+#ifdef REDEBUG
+static char *pchar(int ch);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
+
+#ifdef REDEBUG
+#define	SP(t, s, c)	print(m, t, s, c, stdout)
+#define	AT(t, p1, p2, s1, s2)	at(m, t, p1, p2, s1, s2)
+#define	NOTE(str)	{ if (m->eflags&REG_TRACE) printf("=%s\n", (str)); }
+#else
+#define	SP(t, s, c)	/* nothing */
+#define	AT(t, p1, p2, s1, s2)	/* nothing */
+#define	NOTE(s)	/* nothing */
+#endif
+
+/*
+ - matcher - the actual matching engine
+ == static int matcher(register struct re_guts *g, char *string, \
+ ==	size_t nmatch, regmatch_t pmatch[], int eflags);
+ */
+static int			/* 0 success, REG_NOMATCH failure */
+matcher(g, string, nmatch, pmatch, eflags)
+register struct re_guts *g;
+char *string;
+size_t nmatch;
+regmatch_t pmatch[];
+int eflags;
+{
+	register char *endp;
+	register int i;
+	struct match mv;
+	register struct match *m = &mv;
+	register char *dp;
+	const register sopno gf = g->firststate+1;	/* +1 for OEND */
+	const register sopno gl = g->laststate;
+	char *start;
+	char *stop;
+
+	/* simplify the situation where possible */
+	if (g->cflags&REG_NOSUB)
+		nmatch = 0;
+	if (eflags&REG_STARTEND) {
+		start = string + pmatch[0].rm_so;
+		stop = string + pmatch[0].rm_eo;
+	} else {
+		start = string;
+		stop = start + strlen(start);
+	}
+	if (stop < start)
+		return(REG_INVARG);
+
+	/* prescreening; this does wonders for this rather slow code */
+	if (g->must != NULL) {
+		for (dp = start; dp < stop; dp++)
+			if (*dp == g->must[0] && stop - dp >= g->mlen &&
+				memcmp(dp, g->must, (size_t)g->mlen) == 0)
+				break;
+		if (dp == stop)		/* we didn't find g->must */
+			return(REG_NOMATCH);
+	}
+
+	/* match struct setup */
+	m->g = g;
+	m->eflags = eflags;
+	m->pmatch = NULL;
+	m->lastpos = NULL;
+	m->offp = string;
+	m->beginp = start;
+	m->endp = stop;
+	STATESETUP(m, 4);
+	SETUP(m->st);
+	SETUP(m->fresh);
+	SETUP(m->tmp);
+	SETUP(m->empty);
+	CLEAR(m->empty);
+
+	/* this loop does only one repetition except for backrefs */
+	for (;;) {
+		endp = fast(m, start, stop, gf, gl);
+		if (endp == NULL) {		/* a miss */
+			STATETEARDOWN(m);
+			return(REG_NOMATCH);
+		}
+		if (nmatch == 0 && !g->backrefs)
+			break;		/* no further info needed */
+
+		/* where? */
+		assert(m->coldp != NULL);
+		for (;;) {
+			NOTE("finding start");
+			endp = slow(m, m->coldp, stop, gf, gl);
+			if (endp != NULL)
+				break;
+			assert(m->coldp < m->endp);
+			m->coldp++;
+		}
+		if (nmatch == 1 && !g->backrefs)
+			break;		/* no further info needed */
+
+		/* oh my, he wants the subexpressions... */
+		if (m->pmatch == NULL)
+			m->pmatch = (regmatch_t *)malloc((m->g->nsub + 1) *
+							sizeof(regmatch_t));
+		if (m->pmatch == NULL) {
+			STATETEARDOWN(m);
+			return(REG_ESPACE);
+		}
+		for (i = 1; i <= m->g->nsub; i++)
+			m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1;
+		if (!g->backrefs && !(m->eflags&REG_BACKR)) {
+			NOTE("dissecting");
+			dp = dissect(m, m->coldp, endp, gf, gl);
+		} else {
+			if (g->nplus > 0 && m->lastpos == NULL)
+				m->lastpos = (char **)malloc((g->nplus+1) *
+							sizeof(char *));
+			if (g->nplus > 0 && m->lastpos == NULL) {
+				free(m->pmatch);
+				STATETEARDOWN(m);
+				return(REG_ESPACE);
+			}
+			NOTE("backref dissect");
+			dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+		}
+		if (dp != NULL)
+			break;
+
+		/* uh-oh... we couldn't find a subexpression-level match */
+		assert(g->backrefs);	/* must be back references doing it */
+		assert(g->nplus == 0 || m->lastpos != NULL);
+		for (;;) {
+			if (dp != NULL || endp <= m->coldp)
+				break;		/* defeat */
+			NOTE("backoff");
+			endp = slow(m, m->coldp, endp-1, gf, gl);
+			if (endp == NULL)
+				break;		/* defeat */
+			/* try it on a shorter possibility */
+#ifndef NDEBUG
+			for (i = 1; i <= m->g->nsub; i++) {
+				assert(m->pmatch[i].rm_so == -1);
+				assert(m->pmatch[i].rm_eo == -1);
+			}
+#endif
+			NOTE("backoff dissect");
+			dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+		}
+		assert(dp == NULL || dp == endp);
+		if (dp != NULL)		/* found a shorter one */
+			break;
+
+		/* despite initial appearances, there is no match here */
+		NOTE("false alarm");
+		start = m->coldp + 1;	/* recycle starting later */
+		assert(start <= stop);
+	}
+
+	/* fill in the details if requested */
+	if (nmatch > 0) {
+		pmatch[0].rm_so = m->coldp - m->offp;
+		pmatch[0].rm_eo = endp - m->offp;
+	}
+	if (nmatch > 1) {
+		assert(m->pmatch != NULL);
+		for (i = 1; i < nmatch; i++)
+			if (i <= m->g->nsub)
+				pmatch[i] = m->pmatch[i];
+			else {
+				pmatch[i].rm_so = -1;
+				pmatch[i].rm_eo = -1;
+			}
+	}
+
+	if (m->pmatch != NULL)
+		free((char *)m->pmatch);
+	if (m->lastpos != NULL)
+		free((char *)m->lastpos);
+	STATETEARDOWN(m);
+	return(0);
+}
+
+/*
+ - dissect - figure out what matched what, no back references
+ == static char *dissect(register struct match *m, char *start, \
+ ==	char *stop, sopno startst, sopno stopst);
+ */
+static char *			/* == stop (success) always */
+dissect(m, start, stop, startst, stopst)
+register struct match *m;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+{
+	register int i;
+	register sopno ss;	/* start sop of current subRE */
+	register sopno es;	/* end sop of current subRE */
+	register char *sp;	/* start of string matched by it */
+	register char *stp;	/* string matched by it cannot pass here */
+	register char *rest;	/* start of rest of string */
+	register char *tail;	/* string unmatched by rest of RE */
+	register sopno ssub;	/* start sop of subsubRE */
+	register sopno esub;	/* end sop of subsubRE */
+	register char *ssp;	/* start of string matched by subsubRE */
+	register char *sep;	/* end of string matched by subsubRE */
+	register char *oldssp;	/* previous ssp */
+	register char *dp;
+
+	AT("diss", start, stop, startst, stopst);
+	sp = start;
+	for (ss = startst; ss < stopst; ss = es) {
+		/* identify end of subRE */
+		es = ss;
+		switch (OP(m->g->strip[es])) {
+		case OPLUS_:
+		case OQUEST_:
+			es += OPND(m->g->strip[es]);
+			break;
+		case OCH_:
+			while (OP(m->g->strip[es]) != O_CH)
+				es += OPND(m->g->strip[es]);
+			break;
+		}
+		es++;
+
+		/* figure out what it matched */
+		switch (OP(m->g->strip[ss])) {
+		case OEND:
+			assert(nope);
+			break;
+		case OCHAR:
+			sp++;
+			break;
+		case OBOL:
+		case OEOL:
+		case OBOW:
+		case OEOW:
+			break;
+		case OANY:
+		case OANYOF:
+			sp++;
+			break;
+		case OBACK_:
+		case O_BACK:
+			assert(nope);
+			break;
+		/* cases where length of match is hard to find */
+		case OQUEST_:
+			stp = stop;
+			for (;;) {
+				/* how long could this one be? */
+				rest = slow(m, sp, stp, ss, es);
+				assert(rest != NULL);	/* it did match */
+				/* could the rest match the rest? */
+				tail = slow(m, rest, stop, es, stopst);
+				if (tail == stop)
+					break;		/* yes! */
+				/* no -- try a shorter match for this one */
+				stp = rest - 1;
+				assert(stp >= sp);	/* it did work */
+			}
+			ssub = ss + 1;
+			esub = es - 1;
+			/* did innards match? */
+			if (slow(m, sp, rest, ssub, esub) != NULL) {
+				dp = dissect(m, sp, rest, ssub, esub);
+				assert(dp == rest);
+			} else		/* no */
+				assert(sp == rest);
+			sp = rest;
+			break;
+		case OPLUS_:
+			stp = stop;
+			for (;;) {
+				/* how long could this one be? */
+				rest = slow(m, sp, stp, ss, es);
+				assert(rest != NULL);	/* it did match */
+				/* could the rest match the rest? */
+				tail = slow(m, rest, stop, es, stopst);
+				if (tail == stop)
+					break;		/* yes! */
+				/* no -- try a shorter match for this one */
+				stp = rest - 1;
+				assert(stp >= sp);	/* it did work */
+			}
+			ssub = ss + 1;
+			esub = es - 1;
+			ssp = sp;
+			oldssp = ssp;
+			for (;;) {	/* find last match of innards */
+				sep = slow(m, ssp, rest, ssub, esub);
+				if (sep == NULL || sep == ssp)
+					break;	/* failed or matched null */
+				oldssp = ssp;	/* on to next try */
+				ssp = sep;
+			}
+			if (sep == NULL) {
+				/* last successful match */
+				sep = ssp;
+				ssp = oldssp;
+			}
+			assert(sep == rest);	/* must exhaust substring */
+			assert(slow(m, ssp, sep, ssub, esub) == rest);
+			dp = dissect(m, ssp, sep, ssub, esub);
+			assert(dp == sep);
+			sp = rest;
+			break;
+		case OCH_:
+			stp = stop;
+			for (;;) {
+				/* how long could this one be? */
+				rest = slow(m, sp, stp, ss, es);
+				assert(rest != NULL);	/* it did match */
+				/* could the rest match the rest? */
+				tail = slow(m, rest, stop, es, stopst);
+				if (tail == stop)
+					break;		/* yes! */
+				/* no -- try a shorter match for this one */
+				stp = rest - 1;
+				assert(stp >= sp);	/* it did work */
+			}
+			ssub = ss + 1;
+			esub = ss + OPND(m->g->strip[ss]) - 1;
+			assert(OP(m->g->strip[esub]) == OOR1);
+			for (;;) {	/* find first matching branch */
+				if (slow(m, sp, rest, ssub, esub) == rest)
+					break;	/* it matched all of it */
+				/* that one missed, try next one */
+				assert(OP(m->g->strip[esub]) == OOR1);
+				esub++;
+				assert(OP(m->g->strip[esub]) == OOR2);
+				ssub = esub + 1;
+				esub += OPND(m->g->strip[esub]);
+				if (OP(m->g->strip[esub]) == OOR2)
+					esub--;
+				else
+					assert(OP(m->g->strip[esub]) == O_CH);
+			}
+			dp = dissect(m, sp, rest, ssub, esub);
+			assert(dp == rest);
+			sp = rest;
+			break;
+		case O_PLUS:
+		case O_QUEST:
+		case OOR1:
+		case OOR2:
+		case O_CH:
+			assert(nope);
+			break;
+		case OLPAREN:
+			i = OPND(m->g->strip[ss]);
+			assert(0 < i && i <= m->g->nsub);
+			m->pmatch[i].rm_so = sp - m->offp;
+			break;
+		case ORPAREN:
+			i = OPND(m->g->strip[ss]);
+			assert(0 < i && i <= m->g->nsub);
+			m->pmatch[i].rm_eo = sp - m->offp;
+			break;
+		default:		/* uh oh */
+			assert(nope);
+			break;
+		}
+	}
+
+	assert(sp == stop);
+	return(sp);
+}
+
+/*
+ - backref - figure out what matched what, figuring in back references
+ == static char *backref(register struct match *m, char *start, \
+ ==	char *stop, sopno startst, sopno stopst, sopno lev);
+ */
+static char *			/* == stop (success) or NULL (failure) */
+backref(m, start, stop, startst, stopst, lev)
+register struct match *m;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+sopno lev;			/* PLUS nesting level */
+{
+	register int i;
+	register sopno ss;	/* start sop of current subRE */
+	register char *sp;	/* start of string matched by it */
+	register sopno ssub;	/* start sop of subsubRE */
+	register sopno esub;	/* end sop of subsubRE */
+	register char *ssp;	/* start of string matched by subsubRE */
+	register char *dp;
+	register size_t len;
+	register int hard;
+	register sop s;
+	register regoff_t offsave;
+	register cset *cs;
+
+	AT("back", start, stop, startst, stopst);
+	sp = start;
+
+	/* get as far as we can with easy stuff */
+	hard = 0;
+	for (ss = startst; !hard && ss < stopst; ss++)
+		switch (OP(s = m->g->strip[ss])) {
+		case OCHAR:
+			if (sp == stop || *sp++ != (char)OPND(s))
+				return(NULL);
+			break;
+		case OANY:
+			if (sp == stop)
+				return(NULL);
+			sp++;
+			break;
+		case OANYOF:
+			cs = &m->g->sets[OPND(s)];
+			if (sp == stop || !CHIN(cs, *sp++))
+				return(NULL);
+			break;
+		case OBOL:
+			if ( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
+					(sp < m->endp && *(sp-1) == '\n' &&
+						(m->g->cflags&REG_NEWLINE)) )
+				{ /* yes */ }
+			else
+				return(NULL);
+			break;
+		case OEOL:
+			if ( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
+					(sp < m->endp && *sp == '\n' &&
+						(m->g->cflags&REG_NEWLINE)) )
+				{ /* yes */ }
+			else
+				return(NULL);
+			break;
+		case OBOW:
+			if (( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
+					(sp < m->endp && *(sp-1) == '\n' &&
+						(m->g->cflags&REG_NEWLINE)) ||
+					(sp > m->beginp &&
+							!ISWORD(*(sp-1))) ) &&
+					(sp < m->endp && ISWORD(*sp)) )
+				{ /* yes */ }
+			else
+				return(NULL);
+			break;
+		case OEOW:
+			if (( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
+					(sp < m->endp && *sp == '\n' &&
+						(m->g->cflags&REG_NEWLINE)) ||
+					(sp < m->endp && !ISWORD(*sp)) ) &&
+					(sp > m->beginp && ISWORD(*(sp-1))) )
+				{ /* yes */ }
+			else
+				return(NULL);
+			break;
+		case O_QUEST:
+			break;
+		case OOR1:	/* matches null but needs to skip */
+			ss++;
+			s = m->g->strip[ss];
+			do {
+				assert(OP(s) == OOR2);
+				ss += OPND(s);
+			} while (OP(s = m->g->strip[ss]) != O_CH);
+			/* note that the ss++ gets us past the O_CH */
+			break;
+		default:	/* have to make a choice */
+			hard = 1;
+			break;
+		}
+	if (!hard) {		/* that was it! */
+		if (sp != stop)
+			return(NULL);
+		return(sp);
+	}
+	ss--;			/* adjust for the for's final increment */
+
+	/* the hard stuff */
+	AT("hard", sp, stop, ss, stopst);
+	s = m->g->strip[ss];
+	switch (OP(s)) {
+	case OBACK_:		/* the vilest depths */
+		i = OPND(s);
+		assert(0 < i && i <= m->g->nsub);
+		if (m->pmatch[i].rm_eo == -1)
+			return(NULL);
+		assert(m->pmatch[i].rm_so != -1);
+		len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so;
+		assert(stop - m->beginp >= len);
+		if (sp > stop - len)
+			return(NULL);	/* not enough left to match */
+		ssp = m->offp + m->pmatch[i].rm_so;
+		if (memcmp(sp, ssp, len) != 0)
+			return(NULL);
+		while (m->g->strip[ss] != SOP(O_BACK, i))
+			ss++;
+		return(backref(m, sp+len, stop, ss+1, stopst, lev));
+		break;
+	case OQUEST_:		/* to null or not */
+		dp = backref(m, sp, stop, ss+1, stopst, lev);
+		if (dp != NULL)
+			return(dp);	/* not */
+		return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev));
+		break;
+	case OPLUS_:
+		assert(m->lastpos != NULL);
+		assert(lev+1 <= m->g->nplus);
+		m->lastpos[lev+1] = sp;
+		return(backref(m, sp, stop, ss+1, stopst, lev+1));
+		break;
+	case O_PLUS:
+		if (sp == m->lastpos[lev])	/* last pass matched null */
+			return(backref(m, sp, stop, ss+1, stopst, lev-1));
+		/* try another pass */
+		m->lastpos[lev] = sp;
+		dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev);
+		if (dp == NULL)
+			return(backref(m, sp, stop, ss+1, stopst, lev-1));
+		else
+			return(dp);
+		break;
+	case OCH_:		/* find the right one, if any */
+		ssub = ss + 1;
+		esub = ss + OPND(s) - 1;
+		assert(OP(m->g->strip[esub]) == OOR1);
+		for (;;) {	/* find first matching branch */
+			dp = backref(m, sp, stop, ssub, esub, lev);
+			if (dp != NULL)
+				return(dp);
+			/* that one missed, try next one */
+			if (OP(m->g->strip[esub]) == O_CH)
+				return(NULL);	/* there is none */
+			esub++;
+			assert(OP(m->g->strip[esub]) == OOR2);
+			ssub = esub + 1;
+			esub += OPND(m->g->strip[esub]);
+			if (OP(m->g->strip[esub]) == OOR2)
+				esub--;
+			else
+				assert(OP(m->g->strip[esub]) == O_CH);
+		}
+		break;
+	case OLPAREN:		/* must undo assignment if rest fails */
+		i = OPND(s);
+		assert(0 < i && i <= m->g->nsub);
+		offsave = m->pmatch[i].rm_so;
+		m->pmatch[i].rm_so = sp - m->offp;
+		dp = backref(m, sp, stop, ss+1, stopst, lev);
+		if (dp != NULL)
+			return(dp);
+		m->pmatch[i].rm_so = offsave;
+		return(NULL);
+		break;
+	case ORPAREN:		/* must undo assignment if rest fails */
+		i = OPND(s);
+		assert(0 < i && i <= m->g->nsub);
+		offsave = m->pmatch[i].rm_eo;
+		m->pmatch[i].rm_eo = sp - m->offp;
+		dp = backref(m, sp, stop, ss+1, stopst, lev);
+		if (dp != NULL)
+			return(dp);
+		m->pmatch[i].rm_eo = offsave;
+		return(NULL);
+		break;
+	default:		/* uh oh */
+		assert(nope);
+		break;
+	}
+
+	/* "can't happen" */
+	assert(nope);
+	/* NOTREACHED */
+}
+
+/*
+ - fast - step through the string at top speed
+ == static char *fast(register struct match *m, char *start, \
+ ==	char *stop, sopno startst, sopno stopst);
+ */
+static char *			/* where tentative match ended, or NULL */
+fast(m, start, stop, startst, stopst)
+register struct match *m;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+{
+	register states st = m->st;
+	register states fresh = m->fresh;
+	register states tmp = m->tmp;
+	register char *p = start;
+	register int c = (start == m->beginp) ? OUT : *(start-1);
+	register int lastc;	/* previous c */
+	register int flagch;
+	register int i;
+	register char *coldp;	/* last p after which no match was underway */
+
+	CLEAR(st);
+	SET1(st, startst);
+	st = step(m->g, startst, stopst, st, NOTHING, st);
+	ASSIGN(fresh, st);
+	SP("start", st, *p);
+	coldp = NULL;
+	for (;;) {
+		/* next character */
+		lastc = c;
+		c = (p == m->endp) ? OUT : *p;
+		if (EQ(st, fresh))
+			coldp = p;
+
+		/* is there an EOL and/or BOL between lastc and c? */
+		flagch = '\0';
+		i = 0;
+		if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||
+				(lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
+			flagch = BOL;
+			i = m->g->nbol;
+		}
+		if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||
+				(c == OUT && !(m->eflags&REG_NOTEOL)) ) {
+			flagch = (flagch == BOL) ? BOLEOL : EOL;
+			i += m->g->neol;
+		}
+		if (i != 0) {
+			for (; i > 0; i--)
+				st = step(m->g, startst, stopst, st, flagch, st);
+			SP("boleol", st, c);
+		}
+
+		/* how about a word boundary? */
+		if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
+					(c != OUT && ISWORD(c)) ) {
+			flagch = BOW;
+		}
+		if ( (lastc != OUT && ISWORD(lastc)) &&
+				(flagch == EOL || (c != OUT && !ISWORD(c))) ) {
+			flagch = EOW;
+		}
+		if (flagch == BOW || flagch == EOW) {
+			st = step(m->g, startst, stopst, st, flagch, st);
+			SP("boweow", st, c);
+		}
+
+		/* are we done? */
+		if (ISSET(st, stopst) || p == stop)
+			break;		/* NOTE BREAK OUT */
+
+		/* no, we must deal with this character */
+		ASSIGN(tmp, st);
+		ASSIGN(st, fresh);
+		assert(c != OUT);
+		st = step(m->g, startst, stopst, tmp, c, st);
+		SP("aft", st, c);
+		assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
+		p++;
+	}
+
+	assert(coldp != NULL);
+	m->coldp = coldp;
+	if (ISSET(st, stopst))
+		return(p+1);
+	else
+		return(NULL);
+}
+
+/*
+ - slow - step through the string more deliberately
+ == static char *slow(register struct match *m, char *start, \
+ ==	char *stop, sopno startst, sopno stopst);
+ */
+static char *			/* where it ended */
+slow(m, start, stop, startst, stopst)
+register struct match *m;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+{
+	register states st = m->st;
+	register states empty = m->empty;
+	register states tmp = m->tmp;
+	register char *p = start;
+	register int c = (start == m->beginp) ? OUT : *(start-1);
+	register int lastc;	/* previous c */
+	register int flagch;
+	register int i;
+	register char *matchp;	/* last p at which a match ended */
+
+	AT("slow", start, stop, startst, stopst);
+	CLEAR(st);
+	SET1(st, startst);
+	SP("sstart", st, *p);
+	st = step(m->g, startst, stopst, st, NOTHING, st);
+	matchp = NULL;
+	for (;;) {
+		/* next character */
+		lastc = c;
+		c = (p == m->endp) ? OUT : *p;
+
+		/* is there an EOL and/or BOL between lastc and c? */
+		flagch = '\0';
+		i = 0;
+		if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||
+				(lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
+			flagch = BOL;
+			i = m->g->nbol;
+		}
+		if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||
+				(c == OUT && !(m->eflags&REG_NOTEOL)) ) {
+			flagch = (flagch == BOL) ? BOLEOL : EOL;
+			i += m->g->neol;
+		}
+		if (i != 0) {
+			for (; i > 0; i--)
+				st = step(m->g, startst, stopst, st, flagch, st);
+			SP("sboleol", st, c);
+		}
+
+		/* how about a word boundary? */
+		if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
+					(c != OUT && ISWORD(c)) ) {
+			flagch = BOW;
+		}
+		if ( (lastc != OUT && ISWORD(lastc)) &&
+				(flagch == EOL || (c != OUT && !ISWORD(c))) ) {
+			flagch = EOW;
+		}
+		if (flagch == BOW || flagch == EOW) {
+			st = step(m->g, startst, stopst, st, flagch, st);
+			SP("sboweow", st, c);
+		}
+
+		/* are we done? */
+		if (ISSET(st, stopst))
+			matchp = p;
+		if (EQ(st, empty) || p == stop)
+			break;		/* NOTE BREAK OUT */
+
+		/* no, we must deal with this character */
+		ASSIGN(tmp, st);
+		ASSIGN(st, empty);
+		assert(c != OUT);
+		st = step(m->g, startst, stopst, tmp, c, st);
+		SP("saft", st, c);
+		assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
+		p++;
+	}
+
+	return(matchp);
+}
+
+
+/*
+ - step - map set of states reachable before char to set reachable after
+ == static states step(register struct re_guts *g, sopno start, sopno stop, \
+ ==	register states bef, int ch, register states aft);
+ == #define	BOL	(OUT+1)
+ == #define	EOL	(BOL+1)
+ == #define	BOLEOL	(BOL+2)
+ == #define	NOTHING	(BOL+3)
+ == #define	BOW	(BOL+4)
+ == #define	EOW	(BOL+5)
+ == #define	CODEMAX	(BOL+5)		// highest code used
+ == #define	NONCHAR(c)	((c) > CHAR_MAX)
+ == #define	NNONCHAR	(CODEMAX-CHAR_MAX)
+ */
+static states
+step(g, start, stop, bef, ch, aft)
+register struct re_guts *g;
+sopno start;			/* start state within strip */
+sopno stop;			/* state after stop state within strip */
+register states bef;		/* states reachable before */
+int ch;				/* character or NONCHAR code */
+register states aft;		/* states already known reachable after */
+{
+	register cset *cs;
+	register sop s;
+	register sopno pc;
+	register onestate here;		/* note, macros know this name */
+	register sopno look;
+	register int i;
+
+	for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) {
+		s = g->strip[pc];
+		switch (OP(s)) {
+		case OEND:
+			assert(pc == stop-1);
+			break;
+		case OCHAR:
+			/* only characters can match */
+			assert(!NONCHAR(ch) || ch != (char)OPND(s));
+			if (ch == (char)OPND(s))
+				FWD(aft, bef, 1);
+			break;
+		case OBOL:
+			if (ch == BOL || ch == BOLEOL)
+				FWD(aft, bef, 1);
+			break;
+		case OEOL:
+			if (ch == EOL || ch == BOLEOL)
+				FWD(aft, bef, 1);
+			break;
+		case OBOW:
+			if (ch == BOW)
+				FWD(aft, bef, 1);
+			break;
+		case OEOW:
+			if (ch == EOW)
+				FWD(aft, bef, 1);
+			break;
+		case OANY:
+			if (!NONCHAR(ch))
+				FWD(aft, bef, 1);
+			break;
+		case OANYOF:
+			cs = &g->sets[OPND(s)];
+			if (!NONCHAR(ch) && CHIN(cs, ch))
+				FWD(aft, bef, 1);
+			break;
+		case OBACK_:		/* ignored here */
+		case O_BACK:
+			FWD(aft, aft, 1);
+			break;
+		case OPLUS_:		/* forward, this is just an empty */
+			FWD(aft, aft, 1);
+			break;
+		case O_PLUS:		/* both forward and back */
+			FWD(aft, aft, 1);
+			i = ISSETBACK(aft, OPND(s));
+			BACK(aft, aft, OPND(s));
+			if (!i && ISSETBACK(aft, OPND(s))) {
+				/* oho, must reconsider loop body */
+				pc -= OPND(s) + 1;
+				INIT(here, pc);
+			}
+			break;
+		case OQUEST_:		/* two branches, both forward */
+			FWD(aft, aft, 1);
+			FWD(aft, aft, OPND(s));
+			break;
+		case O_QUEST:		/* just an empty */
+			FWD(aft, aft, 1);
+			break;
+		case OLPAREN:		/* not significant here */
+		case ORPAREN:
+			FWD(aft, aft, 1);
+			break;
+		case OCH_:		/* mark the first two branches */
+			FWD(aft, aft, 1);
+			assert(OP(g->strip[pc+OPND(s)]) == OOR2);
+			FWD(aft, aft, OPND(s));
+			break;
+		case OOR1:		/* done a branch, find the O_CH */
+			if (ISSTATEIN(aft, here)) {
+				for (look = 1;
+						OP(s = g->strip[pc+look]) != O_CH;
+						look += OPND(s))
+					assert(OP(s) == OOR2);
+				FWD(aft, aft, look);
+			}
+			break;
+		case OOR2:		/* propagate OCH_'s marking */
+			FWD(aft, aft, 1);
+			if (OP(g->strip[pc+OPND(s)]) != O_CH) {
+				assert(OP(g->strip[pc+OPND(s)]) == OOR2);
+				FWD(aft, aft, OPND(s));
+			}
+			break;
+		case O_CH:		/* just empty */
+			FWD(aft, aft, 1);
+			break;
+		default:		/* ooooops... */
+			assert(nope);
+			break;
+		}
+	}
+
+	return(aft);
+}
+
+#ifdef REDEBUG
+/*
+ - print - print a set of states
+ == #ifdef REDEBUG
+ == static void print(struct match *m, char *caption, states st, \
+ ==	int ch, FILE *d);
+ == #endif
+ */
+static void
+print(m, caption, st, ch, d)
+struct match *m;
+char *caption;
+states st;
+int ch;
+FILE *d;
+{
+	register struct re_guts *g = m->g;
+	register int i;
+	register int first = 1;
+
+	if (!(m->eflags&REG_TRACE))
+		return;
+
+	fprintf(d, "%s", caption);
+	if (ch != '\0')
+		fprintf(d, " %s", pchar(ch));
+	for (i = 0; i < g->nstates; i++)
+		if (ISSET(st, i)) {
+			fprintf(d, "%s%d", (first) ? "\t" : ", ", i);
+			first = 0;
+		}
+	fprintf(d, "\n");
+}
+
+/* 
+ - at - print current situation
+ == #ifdef REDEBUG
+ == static void at(struct match *m, char *title, char *start, char *stop, \
+ ==						sopno startst, sopno stopst);
+ == #endif
+ */
+static void
+at(m, title, start, stop, startst, stopst)
+struct match *m;
+char *title;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+{
+	if (!(m->eflags&REG_TRACE))
+		return;
+
+	printf("%s %s-", title, pchar(*start));
+	printf("%s ", pchar(*stop));
+	printf("%ld-%ld\n", (long)startst, (long)stopst);
+}
+
+#ifndef PCHARDONE
+#define	PCHARDONE	/* never again */
+/*
+ - pchar - make a character printable
+ == #ifdef REDEBUG
+ == static char *pchar(int ch);
+ == #endif
+ *
+ * Is this identical to regchar() over in debug.c?  Well, yes.  But a
+ * duplicate here avoids having a debugging-capable regexec.o tied to
+ * a matching debug.o, and this is convenient.  It all disappears in
+ * the non-debug compilation anyway, so it doesn't matter much.
+ */
+static char *			/* -> representation */
+pchar(ch)
+int ch;
+{
+	static char pbuf[10];
+
+	if (isprint(ch) || ch == ' ')
+		sprintf(pbuf, "%c", ch);
+	else
+		sprintf(pbuf, "\\%o", ch);
+	return(pbuf);
+}
+#endif
+#endif
+
+#undef	matcher
+#undef	fast
+#undef	slow
+#undef	dissect
+#undef	backref
+#undef	step
+#undef	print
+#undef	at
+#undef	match
Index: /trunk/minix/lib/regex/re_format.7
===================================================================
--- /trunk/minix/lib/regex/re_format.7	(revision 9)
+++ /trunk/minix/lib/regex/re_format.7	(revision 9)
@@ -0,0 +1,269 @@
+.\" Copyright (c) 1992, 1993, 1994 Henry Spencer.
+.\" Copyright (c) 1992, 1993, 1994
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Henry Spencer.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)re_format.7	8.3 (Berkeley) 3/20/94
+.\"
+.TH RE_FORMAT 7 "March 20, 1994"
+.SH NAME
+re_format \- POSIX 1003.2 regular expressions
+.SH DESCRIPTION
+Regular expressions (``RE''s),
+as defined in POSIX 1003.2, come in two forms:
+modern REs (roughly those of
+.BR egrep ;
+1003.2 calls these ``extended'' REs)
+and obsolete REs (roughly those of
+.BR ed ;
+1003.2 ``basic'' REs).
+Obsolete REs mostly exist for backward compatibility in some old programs;
+they will be discussed at the end.
+1003.2 leaves some aspects of RE syntax and semantics open;
+`\(dg' marks decisions on these aspects that
+may not be fully portable to other 1003.2 implementations.
+.PP
+A (modern) RE is one\(dg or more non-empty\(dg \fIbranches\fR,
+separated by `|'.
+It matches anything that matches one of the branches.
+.PP
+A branch is one\(dg or more \fIpieces\fR, concatenated.
+It matches a match for the first, followed by a match for the second, etc.
+.PP
+A piece is an \fIatom\fR possibly followed
+by a single\(dg `*', `+', `?', or \fIbound\fR.
+An atom followed by `*' matches a sequence of 0 or more matches of the atom.
+An atom followed by `+' matches a sequence of 1 or more matches of the atom.
+An atom followed by `?' matches a sequence of 0 or 1 matches of the atom.
+.PP
+A \fIbound\fR is `{' followed by an unsigned decimal integer,
+possibly followed by `,'
+possibly followed by another unsigned decimal integer,
+always followed by `}'.
+The integers must lie between 0 and RE_DUP_MAX (255\(dg) inclusive,
+and if there are two of them, the first may not exceed the second.
+An atom followed by a bound containing one integer \fIi\fR
+and no comma matches
+a sequence of exactly \fIi\fR matches of the atom.
+An atom followed by a bound
+containing one integer \fIi\fR and a comma matches
+a sequence of \fIi\fR or more matches of the atom.
+An atom followed by a bound
+containing two integers \fIi\fR and \fIj\fR matches
+a sequence of \fIi\fR through \fIj\fR (inclusive) matches of the atom.
+.PP
+An atom is a regular expression enclosed in `()' (matching a match for the
+regular expression),
+an empty set of `()' (matching the null string)\(dg,
+a \fIbracket expression\fR (see below), `.'
+(matching any single character), `^' (matching the null string at the
+beginning of a line), `$' (matching the null string at the
+end of a line), a `\e' followed by one of the characters
+`^.[$()|*+?{\e'
+(matching that character taken as an ordinary character),
+a `\e' followed by any other character\(dg
+(matching that character taken as an ordinary character,
+as if the `\e' had not been present\(dg),
+or a single character with no other significance (matching that character).
+A `{' followed by a character other than a digit is an ordinary
+character, not the beginning of a bound\(dg.
+It is illegal to end an RE with `\e'.
+.PP
+A \fIbracket expression\fR is a list of characters enclosed in `[]'.
+It normally matches any single character from the list (but see below).
+If the list begins with `^',
+it matches any single character
+(but see below) \fInot\fR from the rest of the list.
+If two characters in the list are separated by `\-', this is shorthand
+for the full \fIrange\fR of characters between those two (inclusive) in the
+collating sequence,
+e.g. `[0-9]' in ASCII matches any decimal digit.
+It is illegal\(dg for two ranges to share an
+endpoint, e.g. `a-c-e'.
+Ranges are very collating-sequence-dependent,
+and portable programs should avoid relying on them.
+.PP
+To include a literal `]' in the list, make it the first character
+(following a possible `^').
+To include a literal `\-', make it the first or last character,
+or the second endpoint of a range.
+To use a literal `\-' as the first endpoint of a range,
+enclose it in `[.' and `.]' to make it a collating element (see below).
+With the exception of these and some combinations using `[' (see next
+paragraphs), all other special characters, including `\e', lose their
+special significance within a bracket expression.
+.PP
+Within a bracket expression, a collating element (a character,
+a multi-character sequence that collates as if it were a single character,
+or a collating-sequence name for either)
+enclosed in `[.' and `.]' stands for the
+sequence of characters of that collating element.
+The sequence is a single element of the bracket expression's list.
+A bracket expression containing a multi-character collating element 
+can thus match more than one character,
+e.g. if the collating sequence includes a `ch' collating element,
+then the RE `[[.ch.]]*c' matches the first five characters
+of `chchcc'.
+.PP
+Within a bracket expression, a collating element enclosed in `[=' and
+`=]' is an equivalence class, standing for the sequences of characters
+of all collating elements equivalent to that one, including itself.
+(If there are no other equivalent collating elements,
+the treatment is as if the enclosing delimiters were `[.' and `.]'.)
+For example, if o and \o'o^' are the members of an equivalence class,
+then `[[=o=]]', `[[=\o'o^'=]]', and `[o\o'o^']' are all synonymous.
+An equivalence class may not\(dg be an endpoint
+of a range.
+.PP
+Within a bracket expression, the name of a \fIcharacter class\fR enclosed
+in `[:' and `:]' stands for the list of all characters belonging to that
+class.
+Standard character class names are:
+.PP
+.RS
+.nf
+.ta 3c 6c 9c
+alnum	digit	punct
+alpha	graph	space
+blank	lower	upper
+cntrl	print	xdigit
+.fi
+.RE
+.PP
+These stand for the character classes defined in
+.BR ctype (3).
+A locale may provide others.
+A character class may not be used as an endpoint of a range.
+.PP
+There are two special cases\(dg of bracket expressions:
+the bracket expressions `[[:<:]]' and `[[:>:]]' match the null string at
+the beginning and end of a word respectively.
+A word is defined as a sequence of
+word characters
+which is neither preceded nor followed by
+word characters.
+A word character is an
+.B alnum
+character (as defined by
+.BR ctype (3))
+or an underscore.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+.PP
+In the event that an RE could match more than one substring of a given
+string,
+the RE matches the one starting earliest in the string.
+If the RE could match more than one substring starting at that point,
+it matches the longest.
+Subexpressions also match the longest possible substrings, subject to
+the constraint that the whole match be as long as possible,
+with subexpressions starting earlier in the RE taking priority over
+ones starting later.
+Note that higher-level subexpressions thus take priority over
+their lower-level component subexpressions.
+.PP
+Match lengths are measured in characters, not collating elements.
+A null string is considered longer than no match at all.
+For example,
+`bb*' matches the three middle characters of `abbbc',
+`(wee|week)(knights|nights)' matches all ten characters of `weeknights',
+when `(.*).*' is matched against `abc' the parenthesized subexpression
+matches all three characters, and
+when `(a*)*' is matched against `bc' both the whole RE and the parenthesized
+subexpression match the null string.
+.PP
+If case-independent matching is specified,
+the effect is much as if all case distinctions had vanished from the
+alphabet.
+When an alphabetic that exists in multiple cases appears as an
+ordinary character outside a bracket expression, it is effectively
+transformed into a bracket expression containing both cases,
+e.g. `x' becomes `[xX]'.
+When it appears inside a bracket expression, all case counterparts
+of it are added to the bracket expression, so that (e.g.) `[x]'
+becomes `[xX]' and `[^x]' becomes `[^xX]'.
+.PP
+No particular limit is imposed on the length of REs\(dg.
+Programs intended to be portable should not employ REs longer
+than 256 bytes,
+as an implementation can refuse to accept such REs and remain
+POSIX-compliant.
+.PP
+Obsolete (``basic'') regular expressions differ in several respects.
+`|', `+', and `?' are ordinary characters and there is no equivalent
+for their functionality.
+The delimiters for bounds are `\e{' and `\e}',
+with `{' and `}' by themselves ordinary characters.
+The parentheses for nested subexpressions are `\e(' and `\e)',
+with `(' and `)' by themselves ordinary characters.
+`^' is an ordinary character except at the beginning of the
+RE or\(dg the beginning of a parenthesized subexpression,
+`$' is an ordinary character except at the end of the
+RE or\(dg the end of a parenthesized subexpression,
+and `*' is an ordinary character if it appears at the beginning of the
+RE or the beginning of a parenthesized subexpression
+(after a possible leading `^').
+Finally, there is one new type of atom, a \fIback reference\fR:
+`\e' followed by a non-zero decimal digit \fId\fR
+matches the same sequence of characters
+matched by the \fId\fRth parenthesized subexpression
+(numbering subexpressions by the positions of their opening parentheses,
+left to right),
+so that (e.g.) `\e([bc]\e)\e1' matches `bb' or `cc' but not `bc'.
+.SH SEE ALSO
+regex(3)
+.PP
+POSIX 1003.2, section 2.8 (Regular Expression Notation).
+.SH BUGS
+Having two kinds of REs is a botch.
+.PP
+The current 1003.2 spec says that `)' is an ordinary character in
+the absence of an unmatched `(';
+this was an unintentional result of a wording error,
+and change is likely.
+Avoid relying on it.
+.PP
+Back references are a dreadful botch,
+posing major problems for efficient implementations.
+They are also somewhat vaguely defined
+(does
+`a\e(\e(b\e)*\e2\e)*d' match `abbbd'?).
+Avoid using them.
+.PP
+1003.2's specification of case-independent matching is vague.
+The ``one case implies all cases'' definition given above
+is current consensus among implementors as to the right interpretation.
+.PP
+The syntax for word boundaries is incredibly ugly.
Index: /trunk/minix/lib/regex/regcomp.c
===================================================================
--- /trunk/minix/lib/regex/regcomp.c	(revision 9)
+++ /trunk/minix/lib/regex/regcomp.c	(revision 9)
@@ -0,0 +1,1706 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)regcomp.c	8.5 (Berkeley) 3/20/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regcomp.c	8.5 (Berkeley) 3/20/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef __minix_vmd
+#include <bsd/asciictype.h>
+#else
+#include <ctype.h>
+#endif
+#include <limits.h>
+#include <stdlib.h>
+#include <regex.h>
+
+#include "utils.h"
+#include "regex2.h"
+
+#include "cclass.h"
+#include "cname.h"
+
+/*
+ * parse structure, passed up and down to avoid global variables and
+ * other clumsinesses
+ */
+struct parse {
+	char *next;		/* next character in RE */
+	char *end;		/* end of string (-> NUL normally) */
+	int error;		/* has an error been seen? */
+	sop *strip;		/* malloced strip */
+	sopno ssize;		/* malloced strip size (allocated) */
+	sopno slen;		/* malloced strip length (used) */
+	int ncsalloc;		/* number of csets allocated */
+	struct re_guts *g;
+#	define	NPAREN	10	/* we need to remember () 1-9 for back refs */
+	sopno pbegin[NPAREN];	/* -> ( ([0] unused) */
+	sopno pend[NPAREN];	/* -> ) ([0] unused) */
+};
+
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regcomp.c === */
+static void p_ere(struct parse *p, int stop);
+static void p_ere_exp(struct parse *p);
+static void p_str(struct parse *p);
+static void p_bre(struct parse *p, int end1, int end2);
+static int p_simp_re(struct parse *p, int starordinary);
+static int p_count(struct parse *p);
+static void p_bracket(struct parse *p);
+static void p_b_term(struct parse *p, cset *cs);
+static void p_b_cclass(struct parse *p, cset *cs);
+static void p_b_eclass(struct parse *p, cset *cs);
+static char p_b_symbol(struct parse *p);
+static char p_b_coll_elem(struct parse *p, int endc);
+static char othercase(int ch);
+static void bothcases(struct parse *p, int ch);
+static void ordinary(struct parse *p, int ch);
+static void nonnewline(struct parse *p);
+static void repeat(struct parse *p, sopno start, int from, int to);
+static int seterr(struct parse *p, int e);
+static cset *allocset(struct parse *p);
+static void freeset(struct parse *p, cset *cs);
+static int freezeset(struct parse *p, cset *cs);
+static int firstch(struct parse *p, cset *cs);
+static int nch(struct parse *p, cset *cs);
+static void mcadd(struct parse *p, cset *cs, char *cp);
+static void mcsub(cset *cs, char *cp);
+static int mcin(cset *cs, char *cp);
+static char *mcfind(cset *cs, char *cp);
+static void mcinvert(struct parse *p, cset *cs);
+static void mccase(struct parse *p, cset *cs);
+static int isinsets(struct re_guts *g, int c);
+static int samesets(struct re_guts *g, int c1, int c2);
+static void categorize(struct parse *p, struct re_guts *g);
+static sopno dupl(struct parse *p, sopno start, sopno finish);
+static void doemit(struct parse *p, sop op, size_t opnd);
+static void doinsert(struct parse *p, sop op, size_t opnd, sopno pos);
+static void dofwd(struct parse *p, sopno pos, sop value);
+static void enlarge(struct parse *p, sopno size);
+static void stripsnug(struct parse *p, struct re_guts *g);
+static void findmust(struct parse *p, struct re_guts *g);
+static sopno pluscount(struct parse *p, struct re_guts *g);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
+
+static char nuls[10];		/* place to point scanner in event of error */
+
+/*
+ * macros for use with parse structure
+ * BEWARE:  these know that the parse structure is named `p' !!!
+ */
+#define	PEEK()	(*p->next)
+#define	PEEK2()	(*(p->next+1))
+#define	MORE()	(p->next < p->end)
+#define	MORE2()	(p->next+1 < p->end)
+#define	SEE(c)	(MORE() && PEEK() == (c))
+#define	SEETWO(a, b)	(MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b))
+#define	EAT(c)	((SEE(c)) ? (NEXT(), 1) : 0)
+#define	EATTWO(a, b)	((SEETWO(a, b)) ? (NEXT2(), 1) : 0)
+#define	NEXT()	(p->next++)
+#define	NEXT2()	(p->next += 2)
+#define	NEXTn(n)	(p->next += (n))
+#define	GETNEXT()	(*p->next++)
+#define	SETERROR(e)	seterr(p, (e))
+#define	REQUIRE(co, e)	((co) || SETERROR(e))
+#define	MUSTSEE(c, e)	(REQUIRE(MORE() && PEEK() == (c), e))
+#define	MUSTEAT(c, e)	(REQUIRE(MORE() && GETNEXT() == (c), e))
+#define	MUSTNOTSEE(c, e)	(REQUIRE(!MORE() || PEEK() != (c), e))
+#define	EMIT(op, sopnd)	doemit(p, (sop)(op), (size_t)(sopnd))
+#define	INSERT(op, pos)	doinsert(p, (sop)(op), HERE()-(pos)+1, pos)
+#define	AHEAD(pos)		dofwd(p, pos, HERE()-(pos))
+#define	ASTERN(sop, pos)	EMIT(sop, HERE()-pos)
+#define	HERE()		(p->slen)
+#define	THERE()		(p->slen - 1)
+#define	THERETHERE()	(p->slen - 2)
+#define	DROP(n)	(p->slen -= (n))
+
+#ifndef NDEBUG
+static int never = 0;		/* for use in asserts; shuts lint up */
+#else
+#define	never	0		/* some <assert.h>s have bugs too */
+#endif
+
+/*
+ - regcomp - interface for parser and compilation
+ = extern int regcomp(regex_t *, const char *, int);
+ = #define	REG_BASIC	0000
+ = #define	REG_EXTENDED	0001
+ = #define	REG_ICASE	0002
+ = #define	REG_NOSUB	0004
+ = #define	REG_NEWLINE	0010
+ = #define	REG_NOSPEC	0020
+ = #define	REG_PEND	0040
+ = #define	REG_DUMP	0200
+ */
+int				/* 0 success, otherwise REG_something */
+regcomp(preg, pattern, cflags)
+regex_t *preg;
+const char *pattern;
+int cflags;
+{
+	struct parse pa;
+	register struct re_guts *g;
+	register struct parse *p = &pa;
+	register int i;
+	register size_t len;
+#ifdef REDEBUG
+#	define	GOODFLAGS(f)	(f)
+#else
+#	define	GOODFLAGS(f)	((f)&~REG_DUMP)
+#endif
+
+	cflags = GOODFLAGS(cflags);
+	if ((cflags&REG_EXTENDED) && (cflags&REG_NOSPEC))
+		return(REG_INVARG);
+
+	if (cflags&REG_PEND) {
+		if (preg->re_endp < pattern)
+			return(REG_INVARG);
+		len = preg->re_endp - pattern;
+	} else
+		len = strlen((char *)pattern);
+
+	/* do the mallocs early so failure handling is easy */
+	g = (struct re_guts *)malloc(sizeof(struct re_guts) +
+							(NC-1)*sizeof(cat_t));
+	if (g == NULL)
+		return(REG_ESPACE);
+	p->ssize = len/(size_t)2*(size_t)3 + (size_t)1;	/* ugh */
+	p->strip = (sop *)malloc(p->ssize * sizeof(sop));
+	p->slen = 0;
+	if (p->strip == NULL) {
+		free((char *)g);
+		return(REG_ESPACE);
+	}
+
+	/* set things up */
+	p->g = g;
+	p->next = (char *)pattern;	/* convenience; we do not modify it */
+	p->end = p->next + len;
+	p->error = 0;
+	p->ncsalloc = 0;
+	for (i = 0; i < NPAREN; i++) {
+		p->pbegin[i] = 0;
+		p->pend[i] = 0;
+	}
+	g->csetsize = NC;
+	g->sets = NULL;
+	g->setbits = NULL;
+	g->ncsets = 0;
+	g->cflags = cflags;
+	g->iflags = 0;
+	g->nbol = 0;
+	g->neol = 0;
+	g->must = NULL;
+	g->mlen = 0;
+	g->nsub = 0;
+	g->ncategories = 1;	/* category 0 is "everything else" */
+	g->categories = &g->catspace[-(CHAR_MIN)];
+	(void) memset((char *)g->catspace, 0, NC*sizeof(cat_t));
+	g->backrefs = 0;
+
+	/* do it */
+	EMIT(OEND, 0);
+	g->firststate = THERE();
+	if (cflags&REG_EXTENDED)
+		p_ere(p, OUT);
+	else if (cflags&REG_NOSPEC)
+		p_str(p);
+	else
+		p_bre(p, OUT, OUT);
+	EMIT(OEND, 0);
+	g->laststate = THERE();
+
+	/* tidy up loose ends and fill things in */
+	categorize(p, g);
+	stripsnug(p, g);
+	findmust(p, g);
+	g->nplus = pluscount(p, g);
+	g->magic = MAGIC2;
+	preg->re_nsub = g->nsub;
+	preg->re_g = g;
+	preg->re_magic = MAGIC1;
+#ifndef REDEBUG
+	/* not debugging, so can't rely on the assert() in regexec() */
+	if (g->iflags&BAD)
+		SETERROR(REG_ASSERT);
+#endif
+
+	/* win or lose, we're done */
+	if (p->error != 0)	/* lose */
+		regfree(preg);
+	return(p->error);
+}
+
+/*
+ - p_ere - ERE parser top level, concatenation and alternation
+ == static void p_ere(register struct parse *p, int stop);
+ */
+static void
+p_ere(p, stop)
+register struct parse *p;
+int stop;			/* character this ERE should end at */
+{
+	register char c;
+	register sopno prevback;
+	register sopno prevfwd;
+	register sopno conc;
+	register int first = 1;		/* is this the first alternative? */
+
+	for (;;) {
+		/* do a bunch of concatenated expressions */
+		conc = HERE();
+		while (MORE() && (c = PEEK()) != '|' && c != stop)
+			p_ere_exp(p);
+		REQUIRE(HERE() != conc, REG_EMPTY);	/* require nonempty */
+
+		if (!EAT('|'))
+			break;		/* NOTE BREAK OUT */
+
+		if (first) {
+			INSERT(OCH_, conc);	/* offset is wrong */
+			prevfwd = conc;
+			prevback = conc;
+			first = 0;
+		}
+		ASTERN(OOR1, prevback);
+		prevback = THERE();
+		AHEAD(prevfwd);			/* fix previous offset */
+		prevfwd = HERE();
+		EMIT(OOR2, 0);			/* offset is very wrong */
+	}
+
+	if (!first) {		/* tail-end fixups */
+		AHEAD(prevfwd);
+		ASTERN(O_CH, prevback);
+	}
+
+	assert(!MORE() || SEE(stop));
+}
+
+/*
+ - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op
+ == static void p_ere_exp(register struct parse *p);
+ */
+static void
+p_ere_exp(p)
+register struct parse *p;
+{
+	register char c;
+	register sopno pos;
+	register int count;
+	register int count2;
+	register sopno subno;
+	int wascaret = 0;
+
+	assert(MORE());		/* caller should have ensured this */
+	c = GETNEXT();
+
+	pos = HERE();
+	switch (c) {
+	case '(':
+		REQUIRE(MORE(), REG_EPAREN);
+		p->g->nsub++;
+		subno = p->g->nsub;
+		if (subno < NPAREN)
+			p->pbegin[subno] = HERE();
+		EMIT(OLPAREN, subno);
+		if (!SEE(')'))
+			p_ere(p, ')');
+		if (subno < NPAREN) {
+			p->pend[subno] = HERE();
+			assert(p->pend[subno] != 0);
+		}
+		EMIT(ORPAREN, subno);
+		MUSTEAT(')', REG_EPAREN);
+		break;
+#ifndef POSIX_MISTAKE
+	case ')':		/* happens only if no current unmatched ( */
+		/*
+		 * You may ask, why the ifndef?  Because I didn't notice
+		 * this until slightly too late for 1003.2, and none of the
+		 * other 1003.2 regular-expression reviewers noticed it at
+		 * all.  So an unmatched ) is legal POSIX, at least until
+		 * we can get it fixed.
+		 */
+		SETERROR(REG_EPAREN);
+		break;
+#endif
+	case '^':
+		EMIT(OBOL, 0);
+		p->g->iflags |= USEBOL;
+		p->g->nbol++;
+		wascaret = 1;
+		break;
+	case '$':
+		EMIT(OEOL, 0);
+		p->g->iflags |= USEEOL;
+		p->g->neol++;
+		break;
+	case '|':
+		SETERROR(REG_EMPTY);
+		break;
+	case '*':
+	case '+':
+	case '?':
+		SETERROR(REG_BADRPT);
+		break;
+	case '.':
+		if (p->g->cflags&REG_NEWLINE)
+			nonnewline(p);
+		else
+			EMIT(OANY, 0);
+		break;
+	case '[':
+		p_bracket(p);
+		break;
+	case '\\':
+		REQUIRE(MORE(), REG_EESCAPE);
+		c = GETNEXT();
+		ordinary(p, c);
+		break;
+	case '{':		/* okay as ordinary except if digit follows */
+		REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT);
+		/* FALLTHROUGH */
+	default:
+		ordinary(p, c);
+		break;
+	}
+
+	if (!MORE())
+		return;
+	c = PEEK();
+	/* we call { a repetition if followed by a digit */
+	if (!( c == '*' || c == '+' || c == '?' ||
+				(c == '{' && MORE2() && isdigit(PEEK2())) ))
+		return;		/* no repetition, we're done */
+	NEXT();
+
+	REQUIRE(!wascaret, REG_BADRPT);
+	switch (c) {
+	case '*':	/* implemented as +? */
+		/* this case does not require the (y|) trick, noKLUDGE */
+		INSERT(OPLUS_, pos);
+		ASTERN(O_PLUS, pos);
+		INSERT(OQUEST_, pos);
+		ASTERN(O_QUEST, pos);
+		break;
+	case '+':
+		INSERT(OPLUS_, pos);
+		ASTERN(O_PLUS, pos);
+		break;
+	case '?':
+		/* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
+		INSERT(OCH_, pos);		/* offset slightly wrong */
+		ASTERN(OOR1, pos);		/* this one's right */
+		AHEAD(pos);			/* fix the OCH_ */
+		EMIT(OOR2, 0);			/* offset very wrong... */
+		AHEAD(THERE());			/* ...so fix it */
+		ASTERN(O_CH, THERETHERE());
+		break;
+	case '{':
+		count = p_count(p);
+		if (EAT(',')) {
+			if (isdigit(PEEK())) {
+				count2 = p_count(p);
+				REQUIRE(count <= count2, REG_BADBR);
+			} else		/* single number with comma */
+				count2 = INFINITY;
+		} else		/* just a single number */
+			count2 = count;
+		repeat(p, pos, count, count2);
+		if (!EAT('}')) {	/* error heuristics */
+			while (MORE() && PEEK() != '}')
+				NEXT();
+			REQUIRE(MORE(), REG_EBRACE);
+			SETERROR(REG_BADBR);
+		}
+		break;
+	}
+
+	if (!MORE())
+		return;
+	c = PEEK();
+	if (!( c == '*' || c == '+' || c == '?' ||
+				(c == '{' && MORE2() && isdigit(PEEK2())) ) )
+		return;
+	SETERROR(REG_BADRPT);
+}
+
+/*
+ - p_str - string (no metacharacters) "parser"
+ == static void p_str(register struct parse *p);
+ */
+static void
+p_str(p)
+register struct parse *p;
+{
+	REQUIRE(MORE(), REG_EMPTY);
+	while (MORE())
+		ordinary(p, GETNEXT());
+}
+
+/*
+ - p_bre - BRE parser top level, anchoring and concatenation
+ == static void p_bre(register struct parse *p, register int end1, \
+ ==	register int end2);
+ * Giving end1 as OUT essentially eliminates the end1/end2 check.
+ *
+ * This implementation is a bit of a kludge, in that a trailing $ is first
+ * taken as an ordinary character and then revised to be an anchor.  The
+ * only undesirable side effect is that '$' gets included as a character
+ * category in such cases.  This is fairly harmless; not worth fixing.
+ * The amount of lookahead needed to avoid this kludge is excessive.
+ */
+static void
+p_bre(p, end1, end2)
+register struct parse *p;
+register int end1;		/* first terminating character */
+register int end2;		/* second terminating character */
+{
+	register sopno start = HERE();
+	register int first = 1;			/* first subexpression? */
+	register int wasdollar = 0;
+
+	if (EAT('^')) {
+		EMIT(OBOL, 0);
+		p->g->iflags |= USEBOL;
+		p->g->nbol++;
+	}
+	while (MORE() && !SEETWO(end1, end2)) {
+		wasdollar = p_simp_re(p, first);
+		first = 0;
+	}
+	if (wasdollar) {	/* oops, that was a trailing anchor */
+		DROP(1);
+		EMIT(OEOL, 0);
+		p->g->iflags |= USEEOL;
+		p->g->neol++;
+	}
+
+	REQUIRE(HERE() != start, REG_EMPTY);	/* require nonempty */
+}
+
+/*
+ - p_simp_re - parse a simple RE, an atom possibly followed by a repetition
+ == static int p_simp_re(register struct parse *p, int starordinary);
+ */
+static int			/* was the simple RE an unbackslashed $? */
+p_simp_re(p, starordinary)
+register struct parse *p;
+int starordinary;		/* is a leading * an ordinary character? */
+{
+	register int c;
+	register int count;
+	register int count2;
+	register sopno pos;
+	register int i;
+	register sopno subno;
+#	define	BACKSL	(1<<CHAR_BIT)
+
+	pos = HERE();		/* repetion op, if any, covers from here */
+
+	assert(MORE());		/* caller should have ensured this */
+	c = GETNEXT();
+	if (c == '\\') {
+		REQUIRE(MORE(), REG_EESCAPE);
+		c = BACKSL | (unsigned char)GETNEXT();
+	}
+	switch (c) {
+	case '.':
+		if (p->g->cflags&REG_NEWLINE)
+			nonnewline(p);
+		else
+			EMIT(OANY, 0);
+		break;
+	case '[':
+		p_bracket(p);
+		break;
+	case BACKSL|'{':
+		SETERROR(REG_BADRPT);
+		break;
+	case BACKSL|'(':
+		p->g->nsub++;
+		subno = p->g->nsub;
+		if (subno < NPAREN)
+			p->pbegin[subno] = HERE();
+		EMIT(OLPAREN, subno);
+		/* the MORE here is an error heuristic */
+		if (MORE() && !SEETWO('\\', ')'))
+			p_bre(p, '\\', ')');
+		if (subno < NPAREN) {
+			p->pend[subno] = HERE();
+			assert(p->pend[subno] != 0);
+		}
+		EMIT(ORPAREN, subno);
+		REQUIRE(EATTWO('\\', ')'), REG_EPAREN);
+		break;
+	case BACKSL|')':	/* should not get here -- must be user */
+	case BACKSL|'}':
+		SETERROR(REG_EPAREN);
+		break;
+	case BACKSL|'1':
+	case BACKSL|'2':
+	case BACKSL|'3':
+	case BACKSL|'4':
+	case BACKSL|'5':
+	case BACKSL|'6':
+	case BACKSL|'7':
+	case BACKSL|'8':
+	case BACKSL|'9':
+		i = (c&~BACKSL) - '0';
+		assert(i < NPAREN);
+		if (p->pend[i] != 0) {
+			assert(i <= p->g->nsub);
+			EMIT(OBACK_, i);
+			assert(p->pbegin[i] != 0);
+			assert(OP(p->strip[p->pbegin[i]]) == OLPAREN);
+			assert(OP(p->strip[p->pend[i]]) == ORPAREN);
+			(void) dupl(p, p->pbegin[i]+1, p->pend[i]);
+			EMIT(O_BACK, i);
+		} else
+			SETERROR(REG_ESUBREG);
+		p->g->backrefs = 1;
+		break;
+	case '*':
+		REQUIRE(starordinary, REG_BADRPT);
+		/* FALLTHROUGH */
+	default:
+		ordinary(p, c &~ BACKSL);
+		break;
+	}
+
+	if (EAT('*')) {		/* implemented as +? */
+		/* this case does not require the (y|) trick, noKLUDGE */
+		INSERT(OPLUS_, pos);
+		ASTERN(O_PLUS, pos);
+		INSERT(OQUEST_, pos);
+		ASTERN(O_QUEST, pos);
+	} else if (EATTWO('\\', '{')) {
+		count = p_count(p);
+		if (EAT(',')) {
+			if (MORE() && isdigit(PEEK())) {
+				count2 = p_count(p);
+				REQUIRE(count <= count2, REG_BADBR);
+			} else		/* single number with comma */
+				count2 = INFINITY;
+		} else		/* just a single number */
+			count2 = count;
+		repeat(p, pos, count, count2);
+		if (!EATTWO('\\', '}')) {	/* error heuristics */
+			while (MORE() && !SEETWO('\\', '}'))
+				NEXT();
+			REQUIRE(MORE(), REG_EBRACE);
+			SETERROR(REG_BADBR);
+		}
+	} else if (c == (unsigned char)'$')	/* $ (but not \$) ends it */
+		return(1);
+
+	return(0);
+}
+
+/*
+ - p_count - parse a repetition count
+ == static int p_count(register struct parse *p);
+ */
+static int			/* the value */
+p_count(p)
+register struct parse *p;
+{
+	register int count = 0;
+	register int ndigits = 0;
+
+	while (MORE() && isdigit(PEEK()) && count <= DUPMAX) {
+		count = count*10 + (GETNEXT() - '0');
+		ndigits++;
+	}
+
+	REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR);
+	return(count);
+}
+
+/*
+ - p_bracket - parse a bracketed character list
+ == static void p_bracket(register struct parse *p);
+ *
+ * Note a significant property of this code:  if the allocset() did SETERROR,
+ * no set operations are done.
+ */
+static void
+p_bracket(p)
+register struct parse *p;
+{
+	register char c;
+	register cset *cs = allocset(p);
+	register int invert = 0;
+
+	/* Dept of Truly Sickening Special-Case Kludges */
+	if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) {
+		EMIT(OBOW, 0);
+		NEXTn(6);
+		return;
+	}
+	if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) {
+		EMIT(OEOW, 0);
+		NEXTn(6);
+		return;
+	}
+
+	if (EAT('^'))
+		invert++;	/* make note to invert set at end */
+	if (EAT(']'))
+		CHadd(cs, ']');
+	else if (EAT('-'))
+		CHadd(cs, '-');
+	while (MORE() && PEEK() != ']' && !SEETWO('-', ']'))
+		p_b_term(p, cs);
+	if (EAT('-'))
+		CHadd(cs, '-');
+	MUSTEAT(']', REG_EBRACK);
+
+	if (p->error != 0)	/* don't mess things up further */
+		return;
+
+	if (p->g->cflags&REG_ICASE) {
+		register int i;
+		register int ci;
+
+		for (i = p->g->csetsize - 1; i >= 0; i--)
+			if (CHIN(cs, i) && isalpha(i)) {
+				ci = othercase(i);
+				if (ci != i)
+					CHadd(cs, ci);
+			}
+		if (cs->multis != NULL)
+			mccase(p, cs);
+	}
+	if (invert) {
+		register int i;
+
+		for (i = p->g->csetsize - 1; i >= 0; i--)
+			if (CHIN(cs, i))
+				CHsub(cs, i);
+			else
+				CHadd(cs, i);
+		if (p->g->cflags&REG_NEWLINE)
+			CHsub(cs, '\n');
+		if (cs->multis != NULL)
+			mcinvert(p, cs);
+	}
+
+	assert(cs->multis == NULL);		/* xxx */
+
+	if (nch(p, cs) == 1) {		/* optimize singleton sets */
+		ordinary(p, firstch(p, cs));
+		freeset(p, cs);
+	} else
+		EMIT(OANYOF, freezeset(p, cs));
+}
+
+/*
+ - p_b_term - parse one term of a bracketed character list
+ == static void p_b_term(register struct parse *p, register cset *cs);
+ */
+static void
+p_b_term(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+	register char c;
+	register char start, finish;
+	register int i;
+
+	/* classify what we've got */
+	switch ((MORE()) ? PEEK() : '\0') {
+	case '[':
+		c = (MORE2()) ? PEEK2() : '\0';
+		break;
+	case '-':
+		SETERROR(REG_ERANGE);
+		return;			/* NOTE RETURN */
+		break;
+	default:
+		c = '\0';
+		break;
+	}
+
+	switch (c) {
+	case ':':		/* character class */
+		NEXT2();
+		REQUIRE(MORE(), REG_EBRACK);
+		c = PEEK();
+		REQUIRE(c != '-' && c != ']', REG_ECTYPE);
+		p_b_cclass(p, cs);
+		REQUIRE(MORE(), REG_EBRACK);
+		REQUIRE(EATTWO(':', ']'), REG_ECTYPE);
+		break;
+	case '=':		/* equivalence class */
+		NEXT2();
+		REQUIRE(MORE(), REG_EBRACK);
+		c = PEEK();
+		REQUIRE(c != '-' && c != ']', REG_ECOLLATE);
+		p_b_eclass(p, cs);
+		REQUIRE(MORE(), REG_EBRACK);
+		REQUIRE(EATTWO('=', ']'), REG_ECOLLATE);
+		break;
+	default:		/* symbol, ordinary character, or range */
+/* xxx revision needed for multichar stuff */
+		start = p_b_symbol(p);
+		if (SEE('-') && MORE2() && PEEK2() != ']') {
+			/* range */
+			NEXT();
+			if (EAT('-'))
+				finish = '-';
+			else
+				finish = p_b_symbol(p);
+		} else
+			finish = start;
+/* xxx what about signed chars here... */
+		REQUIRE(start <= finish, REG_ERANGE);
+		for (i = start; i <= finish; i++)
+			CHadd(cs, i);
+		break;
+	}
+}
+
+/*
+ - p_b_cclass - parse a character-class name and deal with it
+ == static void p_b_cclass(register struct parse *p, register cset *cs);
+ */
+static void
+p_b_cclass(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+	register char *sp = p->next;
+	register struct cclass *cp;
+	register size_t len;
+	register char *u;
+	register char c;
+
+	while (MORE() && isalpha(PEEK()))
+		NEXT();
+	len = p->next - sp;
+	for (cp = cclasses; cp->name != NULL; cp++)
+		if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
+			break;
+	if (cp->name == NULL) {
+		/* oops, didn't find it */
+		SETERROR(REG_ECTYPE);
+		return;
+	}
+
+	u = cp->chars;
+	while ((c = *u++) != '\0')
+		CHadd(cs, c);
+	for (u = cp->multis; *u != '\0'; u += strlen(u) + 1)
+		MCadd(p, cs, u);
+}
+
+/*
+ - p_b_eclass - parse an equivalence-class name and deal with it
+ == static void p_b_eclass(register struct parse *p, register cset *cs);
+ *
+ * This implementation is incomplete. xxx
+ */
+static void
+p_b_eclass(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+	register char c;
+
+	c = p_b_coll_elem(p, '=');
+	CHadd(cs, c);
+}
+
+/*
+ - p_b_symbol - parse a character or [..]ed multicharacter collating symbol
+ == static char p_b_symbol(register struct parse *p);
+ */
+static char			/* value of symbol */
+p_b_symbol(p)
+register struct parse *p;
+{
+	register char value;
+
+	REQUIRE(MORE(), REG_EBRACK);
+	if (!EATTWO('[', '.'))
+		return(GETNEXT());
+
+	/* collating symbol */
+	value = p_b_coll_elem(p, '.');
+	REQUIRE(EATTWO('.', ']'), REG_ECOLLATE);
+	return(value);
+}
+
+/*
+ - p_b_coll_elem - parse a collating-element name and look it up
+ == static char p_b_coll_elem(register struct parse *p, int endc);
+ */
+static char			/* value of collating element */
+p_b_coll_elem(p, endc)
+register struct parse *p;
+int endc;			/* name ended by endc,']' */
+{
+	register char *sp = p->next;
+	register struct cname *cp;
+	register int len;
+	register char c;
+
+	while (MORE() && !SEETWO(endc, ']'))
+		NEXT();
+	if (!MORE()) {
+		SETERROR(REG_EBRACK);
+		return(0);
+	}
+	len = p->next - sp;
+	for (cp = cnames; cp->name != NULL; cp++)
+		if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
+			return(cp->code);	/* known name */
+	if (len == 1)
+		return(*sp);	/* single character */
+	SETERROR(REG_ECOLLATE);			/* neither */
+	return(0);
+}
+
+/*
+ - othercase - return the case counterpart of an alphabetic
+ == static char othercase(int ch);
+ */
+static char			/* if no counterpart, return ch */
+othercase(ch)
+int ch;
+{
+	assert(isalpha(ch));
+	if (isupper(ch))
+		return(tolower(ch));
+	else if (islower(ch))
+		return(toupper(ch));
+	else			/* peculiar, but could happen */
+		return(ch);
+}
+
+/*
+ - bothcases - emit a dualcase version of a two-case character
+ == static void bothcases(register struct parse *p, int ch);
+ *
+ * Boy, is this implementation ever a kludge...
+ */
+static void
+bothcases(p, ch)
+register struct parse *p;
+int ch;
+{
+	register char *oldnext = p->next;
+	register char *oldend = p->end;
+	char bracket[3];
+
+	assert(othercase(ch) != ch);	/* p_bracket() would recurse */
+	p->next = bracket;
+	p->end = bracket+2;
+	bracket[0] = ch;
+	bracket[1] = ']';
+	bracket[2] = '\0';
+	p_bracket(p);
+	assert(p->next == bracket+2);
+	p->next = oldnext;
+	p->end = oldend;
+}
+
+/*
+ - ordinary - emit an ordinary character
+ == static void ordinary(register struct parse *p, register int ch);
+ */
+static void
+ordinary(p, ch)
+register struct parse *p;
+register int ch;
+{
+	register cat_t *cap = p->g->categories;
+
+	if ((p->g->cflags&REG_ICASE) && isalpha(ch) && othercase(ch) != ch)
+		bothcases(p, ch);
+	else {
+		EMIT(OCHAR, (unsigned char)ch);
+		if (cap[ch] == 0)
+			cap[ch] = p->g->ncategories++;
+	}
+}
+
+/*
+ - nonnewline - emit REG_NEWLINE version of OANY
+ == static void nonnewline(register struct parse *p);
+ *
+ * Boy, is this implementation ever a kludge...
+ */
+static void
+nonnewline(p)
+register struct parse *p;
+{
+	register char *oldnext = p->next;
+	register char *oldend = p->end;
+	char bracket[4];
+
+	p->next = bracket;
+	p->end = bracket+3;
+	bracket[0] = '^';
+	bracket[1] = '\n';
+	bracket[2] = ']';
+	bracket[3] = '\0';
+	p_bracket(p);
+	assert(p->next == bracket+3);
+	p->next = oldnext;
+	p->end = oldend;
+}
+
+/*
+ - repeat - generate code for a bounded repetition, recursively if needed
+ == static void repeat(register struct parse *p, sopno start, int from, int to);
+ */
+static void
+repeat(p, start, from, to)
+register struct parse *p;
+sopno start;			/* operand from here to end of strip */
+int from;			/* repeated from this number */
+int to;				/* to this number of times (maybe INFINITY) */
+{
+	register sopno finish = HERE();
+#	define	N	2
+#	define	INF	3
+#	define	REP(f, t)	((f)*8 + (t))
+#	define	MAP(n)	(((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N)
+	register sopno copy;
+
+	if (p->error != 0)	/* head off possible runaway recursion */
+		return;
+
+	assert(from <= to);
+
+	switch (REP(MAP(from), MAP(to))) {
+	case REP(0, 0):			/* must be user doing this */
+		DROP(finish-start);	/* drop the operand */
+		break;
+	case REP(0, 1):			/* as x{1,1}? */
+	case REP(0, N):			/* as x{1,n}? */
+	case REP(0, INF):		/* as x{1,}? */
+		/* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
+		INSERT(OCH_, start);		/* offset is wrong... */
+		repeat(p, start+1, 1, to);
+		ASTERN(OOR1, start);
+		AHEAD(start);			/* ... fix it */
+		EMIT(OOR2, 0);
+		AHEAD(THERE());
+		ASTERN(O_CH, THERETHERE());
+		break;
+	case REP(1, 1):			/* trivial case */
+		/* done */
+		break;
+	case REP(1, N):			/* as x?x{1,n-1} */
+		/* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
+		INSERT(OCH_, start);
+		ASTERN(OOR1, start);
+		AHEAD(start);
+		EMIT(OOR2, 0);			/* offset very wrong... */
+		AHEAD(THERE());			/* ...so fix it */
+		ASTERN(O_CH, THERETHERE());
+		copy = dupl(p, start+1, finish+1);
+		assert(copy == finish+4);
+		repeat(p, copy, 1, to-1);
+		break;
+	case REP(1, INF):		/* as x+ */
+		INSERT(OPLUS_, start);
+		ASTERN(O_PLUS, start);
+		break;
+	case REP(N, N):			/* as xx{m-1,n-1} */
+		copy = dupl(p, start, finish);
+		repeat(p, copy, from-1, to-1);
+		break;
+	case REP(N, INF):		/* as xx{n-1,INF} */
+		copy = dupl(p, start, finish);
+		repeat(p, copy, from-1, to);
+		break;
+	default:			/* "can't happen" */
+		SETERROR(REG_ASSERT);	/* just in case */
+		break;
+	}
+}
+
+/*
+ - seterr - set an error condition
+ == static int seterr(register struct parse *p, int e);
+ */
+static int			/* useless but makes type checking happy */
+seterr(p, e)
+register struct parse *p;
+int e;
+{
+	if (p->error == 0)	/* keep earliest error condition */
+		p->error = e;
+	p->next = nuls;		/* try to bring things to a halt */
+	p->end = nuls;
+	return(0);		/* make the return value well-defined */
+}
+
+/*
+ - allocset - allocate a set of characters for []
+ == static cset *allocset(register struct parse *p);
+ */
+static cset *
+allocset(p)
+register struct parse *p;
+{
+	register int no = p->g->ncsets++;
+	register size_t nc;
+	register size_t nbytes;
+	register cset *cs;
+	register size_t css = (size_t)p->g->csetsize;
+	register int i;
+
+	if (no >= p->ncsalloc) {	/* need another column of space */
+		p->ncsalloc += CHAR_BIT;
+		nc = p->ncsalloc;
+		assert(nc % CHAR_BIT == 0);
+		nbytes = nc / CHAR_BIT * css;
+		if (p->g->sets == NULL)
+			p->g->sets = (cset *)malloc(nc * sizeof(cset));
+		else
+			p->g->sets = (cset *)realloc((char *)p->g->sets,
+							nc * sizeof(cset));
+		if (p->g->setbits == NULL)
+			p->g->setbits = (uch *)malloc(nbytes);
+		else {
+			p->g->setbits = (uch *)realloc((char *)p->g->setbits,
+								nbytes);
+			/* xxx this isn't right if setbits is now NULL */
+			for (i = 0; i < no; i++)
+				p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT);
+		}
+		if (p->g->sets != NULL && p->g->setbits != NULL)
+			(void) memset((char *)p->g->setbits + (nbytes - css),
+								0, css);
+		else {
+			no = 0;
+			SETERROR(REG_ESPACE);
+			/* caller's responsibility not to do set ops */
+		}
+	}
+
+	assert(p->g->sets != NULL);	/* xxx */
+	cs = &p->g->sets[no];
+	cs->ptr = p->g->setbits + css*((no)/CHAR_BIT);
+	cs->mask = 1 << ((no) % CHAR_BIT);
+	cs->hash = 0;
+	cs->smultis = 0;
+	cs->multis = NULL;
+
+	return(cs);
+}
+
+/*
+ - freeset - free a now-unused set
+ == static void freeset(register struct parse *p, register cset *cs);
+ */
+static void
+freeset(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+	register int i;
+	register cset *top = &p->g->sets[p->g->ncsets];
+	register size_t css = (size_t)p->g->csetsize;
+
+	for (i = 0; i < css; i++)
+		CHsub(cs, i);
+	if (cs == top-1)	/* recover only the easy case */
+		p->g->ncsets--;
+}
+
+/*
+ - freezeset - final processing on a set of characters
+ == static int freezeset(register struct parse *p, register cset *cs);
+ *
+ * The main task here is merging identical sets.  This is usually a waste
+ * of time (although the hash code minimizes the overhead), but can win
+ * big if REG_ICASE is being used.  REG_ICASE, by the way, is why the hash
+ * is done using addition rather than xor -- all ASCII [aA] sets xor to
+ * the same value!
+ */
+static int			/* set number */
+freezeset(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+	register uch h = cs->hash;
+	register int i;
+	register cset *top = &p->g->sets[p->g->ncsets];
+	register cset *cs2;
+	register size_t css = (size_t)p->g->csetsize;
+
+	/* look for an earlier one which is the same */
+	for (cs2 = &p->g->sets[0]; cs2 < top; cs2++)
+		if (cs2->hash == h && cs2 != cs) {
+			/* maybe */
+			for (i = 0; i < css; i++)
+				if (!!CHIN(cs2, i) != !!CHIN(cs, i))
+					break;		/* no */
+			if (i == css)
+				break;			/* yes */
+		}
+
+	if (cs2 < top) {	/* found one */
+		freeset(p, cs);
+		cs = cs2;
+	}
+
+	return((int)(cs - p->g->sets));
+}
+
+/*
+ - firstch - return first character in a set (which must have at least one)
+ == static int firstch(register struct parse *p, register cset *cs);
+ */
+static int			/* character; there is no "none" value */
+firstch(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+	register int i;
+	register size_t css = (size_t)p->g->csetsize;
+
+	for (i = 0; i < css; i++)
+		if (CHIN(cs, i))
+			return((char)i);
+	assert(never);
+	return(0);		/* arbitrary */
+}
+
+/*
+ - nch - number of characters in a set
+ == static int nch(register struct parse *p, register cset *cs);
+ */
+static int
+nch(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+	register int i;
+	register size_t css = (size_t)p->g->csetsize;
+	register int n = 0;
+
+	for (i = 0; i < css; i++)
+		if (CHIN(cs, i))
+			n++;
+	return(n);
+}
+
+/*
+ - mcadd - add a collating element to a cset
+ == static void mcadd(register struct parse *p, register cset *cs, \
+ ==	register char *cp);
+ */
+static void
+mcadd(p, cs, cp)
+register struct parse *p;
+register cset *cs;
+register char *cp;
+{
+	register size_t oldend = cs->smultis;
+
+	cs->smultis += strlen(cp) + 1;
+	if (cs->multis == NULL)
+		cs->multis = malloc(cs->smultis);
+	else
+		cs->multis = realloc(cs->multis, cs->smultis);
+	if (cs->multis == NULL) {
+		SETERROR(REG_ESPACE);
+		return;
+	}
+
+	(void) strcpy(cs->multis + oldend - 1, cp);
+	cs->multis[cs->smultis - 1] = '\0';
+}
+
+/*
+ - mcsub - subtract a collating element from a cset
+ == static void mcsub(register cset *cs, register char *cp);
+ */
+static void
+mcsub(cs, cp)
+register cset *cs;
+register char *cp;
+{
+	register char *fp = mcfind(cs, cp);
+	register size_t len = strlen(fp);
+
+	assert(fp != NULL);
+	(void) memmove(fp, fp + len + 1,
+				cs->smultis - (fp + len + 1 - cs->multis));
+	cs->smultis -= len;
+
+	if (cs->smultis == 0) {
+		free(cs->multis);
+		cs->multis = NULL;
+		return;
+	}
+
+	cs->multis = realloc(cs->multis, cs->smultis);
+	assert(cs->multis != NULL);
+}
+
+/*
+ - mcin - is a collating element in a cset?
+ == static int mcin(register cset *cs, register char *cp);
+ */
+static int
+mcin(cs, cp)
+register cset *cs;
+register char *cp;
+{
+	return(mcfind(cs, cp) != NULL);
+}
+
+/*
+ - mcfind - find a collating element in a cset
+ == static char *mcfind(register cset *cs, register char *cp);
+ */
+static char *
+mcfind(cs, cp)
+register cset *cs;
+register char *cp;
+{
+	register char *p;
+
+	if (cs->multis == NULL)
+		return(NULL);
+	for (p = cs->multis; *p != '\0'; p += strlen(p) + 1)
+		if (strcmp(cp, p) == 0)
+			return(p);
+	return(NULL);
+}
+
+/*
+ - mcinvert - invert the list of collating elements in a cset
+ == static void mcinvert(register struct parse *p, register cset *cs);
+ *
+ * This would have to know the set of possibilities.  Implementation
+ * is deferred.
+ */
+static void
+mcinvert(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+	assert(cs->multis == NULL);	/* xxx */
+}
+
+/*
+ - mccase - add case counterparts of the list of collating elements in a cset
+ == static void mccase(register struct parse *p, register cset *cs);
+ *
+ * This would have to know the set of possibilities.  Implementation
+ * is deferred.
+ */
+static void
+mccase(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+	assert(cs->multis == NULL);	/* xxx */
+}
+
+/*
+ - isinsets - is this character in any sets?
+ == static int isinsets(register struct re_guts *g, int c);
+ */
+static int			/* predicate */
+isinsets(g, c)
+register struct re_guts *g;
+int c;
+{
+	register uch *col;
+	register int i;
+	register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT;
+	register unsigned uc = (unsigned char)c;
+
+	for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)
+		if (col[uc] != 0)
+			return(1);
+	return(0);
+}
+
+/*
+ - samesets - are these two characters in exactly the same sets?
+ == static int samesets(register struct re_guts *g, int c1, int c2);
+ */
+static int			/* predicate */
+samesets(g, c1, c2)
+register struct re_guts *g;
+int c1;
+int c2;
+{
+	register uch *col;
+	register int i;
+	register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT;
+	register unsigned uc1 = (unsigned char)c1;
+	register unsigned uc2 = (unsigned char)c2;
+
+	for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)
+		if (col[uc1] != col[uc2])
+			return(0);
+	return(1);
+}
+
+/*
+ - categorize - sort out character categories
+ == static void categorize(struct parse *p, register struct re_guts *g);
+ */
+static void
+categorize(p, g)
+struct parse *p;
+register struct re_guts *g;
+{
+	register cat_t *cats = g->categories;
+	register int c;
+	register int c2;
+	register cat_t cat;
+
+	/* avoid making error situations worse */
+	if (p->error != 0)
+		return;
+
+	for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+		if (cats[c] == 0 && isinsets(g, c)) {
+			cat = g->ncategories++;
+			cats[c] = cat;
+			for (c2 = c+1; c2 <= CHAR_MAX; c2++)
+				if (cats[c2] == 0 && samesets(g, c, c2))
+					cats[c2] = cat;
+		}
+}
+
+/*
+ - dupl - emit a duplicate of a bunch of sops
+ == static sopno dupl(register struct parse *p, sopno start, sopno finish);
+ */
+static sopno			/* start of duplicate */
+dupl(p, start, finish)
+register struct parse *p;
+sopno start;			/* from here */
+sopno finish;			/* to this less one */
+{
+	register sopno ret = HERE();
+	register sopno len = finish - start;
+
+	assert(finish >= start);
+	if (len == 0)
+		return(ret);
+	enlarge(p, p->ssize + len);	/* this many unexpected additions */
+	assert(p->ssize >= p->slen + len);
+	(void) memcpy((char *)(p->strip + p->slen),
+		(char *)(p->strip + start), (size_t)len*sizeof(sop));
+	p->slen += len;
+	return(ret);
+}
+
+/*
+ - doemit - emit a strip operator
+ == static void doemit(register struct parse *p, sop op, size_t opnd);
+ *
+ * It might seem better to implement this as a macro with a function as
+ * hard-case backup, but it's just too big and messy unless there are
+ * some changes to the data structures.  Maybe later.
+ */
+static void
+doemit(p, op, opnd)
+register struct parse *p;
+sop op;
+size_t opnd;
+{
+	/* avoid making error situations worse */
+	if (p->error != 0)
+		return;
+
+	/* deal with oversize operands ("can't happen", more or less) */
+	assert(opnd < 1<<OPSHIFT);
+
+	/* deal with undersized strip */
+	if (p->slen >= p->ssize)
+		enlarge(p, (p->ssize+1) / 2 * 3);	/* +50% */
+	assert(p->slen < p->ssize);
+
+	/* finally, it's all reduced to the easy case */
+	p->strip[p->slen++] = SOP(op, opnd);
+}
+
+/*
+ - doinsert - insert a sop into the strip
+ == static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos);
+ */
+static void
+doinsert(p, op, opnd, pos)
+register struct parse *p;
+sop op;
+size_t opnd;
+sopno pos;
+{
+	register sopno sn;
+	register sop s;
+	register int i;
+
+	/* avoid making error situations worse */
+	if (p->error != 0)
+		return;
+
+	sn = HERE();
+	EMIT(op, opnd);		/* do checks, ensure space */
+	assert(HERE() == sn+1);
+	s = p->strip[sn];
+
+	/* adjust paren pointers */
+	assert(pos > 0);
+	for (i = 1; i < NPAREN; i++) {
+		if (p->pbegin[i] >= pos) {
+			p->pbegin[i]++;
+		}
+		if (p->pend[i] >= pos) {
+			p->pend[i]++;
+		}
+	}
+
+	memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos],
+						(HERE()-pos-1)*sizeof(sop));
+	p->strip[pos] = s;
+}
+
+/*
+ - dofwd - complete a forward reference
+ == static void dofwd(register struct parse *p, sopno pos, sop value);
+ */
+static void
+dofwd(p, pos, value)
+register struct parse *p;
+register sopno pos;
+sop value;
+{
+	/* avoid making error situations worse */
+	if (p->error != 0)
+		return;
+
+	assert(value < 1<<OPSHIFT);
+	p->strip[pos] = OP(p->strip[pos]) | value;
+}
+
+/*
+ - enlarge - enlarge the strip
+ == static void enlarge(register struct parse *p, sopno size);
+ */
+static void
+enlarge(p, size)
+register struct parse *p;
+register sopno size;
+{
+	register sop *sp;
+
+	if (p->ssize >= size)
+		return;
+
+	sp = (sop *)realloc(p->strip, size*sizeof(sop));
+	if (sp == NULL) {
+		SETERROR(REG_ESPACE);
+		return;
+	}
+	p->strip = sp;
+	p->ssize = size;
+}
+
+/*
+ - stripsnug - compact the strip
+ == static void stripsnug(register struct parse *p, register struct re_guts *g);
+ */
+static void
+stripsnug(p, g)
+register struct parse *p;
+register struct re_guts *g;
+{
+	g->nstates = p->slen;
+	g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop));
+	if (g->strip == NULL) {
+		SETERROR(REG_ESPACE);
+		g->strip = p->strip;
+	}
+}
+
+/*
+ - findmust - fill in must and mlen with longest mandatory literal string
+ == static void findmust(register struct parse *p, register struct re_guts *g);
+ *
+ * This algorithm could do fancy things like analyzing the operands of |
+ * for common subsequences.  Someday.  This code is simple and finds most
+ * of the interesting cases.
+ *
+ * Note that must and mlen got initialized during setup.
+ */
+static void
+findmust(p, g)
+struct parse *p;
+register struct re_guts *g;
+{
+	register sop *scan;
+	sop *start;
+	register sop *newstart;
+	register sopno newlen;
+	register sop s;
+	register char *cp;
+	register sopno i;
+
+	/* avoid making error situations worse */
+	if (p->error != 0)
+		return;
+
+	/* find the longest OCHAR sequence in strip */
+	newlen = 0;
+	scan = g->strip + 1;
+	do {
+		s = *scan++;
+		switch (OP(s)) {
+		case OCHAR:		/* sequence member */
+			if (newlen == 0)		/* new sequence */
+				newstart = scan - 1;
+			newlen++;
+			break;
+		case OPLUS_:		/* things that don't break one */
+		case OLPAREN:
+		case ORPAREN:
+			break;
+		case OQUEST_:		/* things that must be skipped */
+		case OCH_:
+			scan--;
+			do {
+				scan += OPND(s);
+				s = *scan;
+				/* assert() interferes w debug printouts */
+				if (OP(s) != O_QUEST && OP(s) != O_CH &&
+							OP(s) != OOR2) {
+					g->iflags |= BAD;
+					return;
+				}
+			} while (OP(s) != O_QUEST && OP(s) != O_CH);
+			/* fallthrough */
+		default:		/* things that break a sequence */
+			if (newlen > g->mlen) {		/* ends one */
+				start = newstart;
+				g->mlen = newlen;
+			}
+			newlen = 0;
+			break;
+		}
+	} while (OP(s) != OEND);
+
+	if (g->mlen == 0)		/* there isn't one */
+		return;
+
+	/* turn it into a character string */
+	g->must = malloc((size_t)g->mlen + 1);
+	if (g->must == NULL) {		/* argh; just forget it */
+		g->mlen = 0;
+		return;
+	}
+	cp = g->must;
+	scan = start;
+	for (i = g->mlen; i > 0; i--) {
+		while (OP(s = *scan++) != OCHAR)
+			continue;
+		assert(cp < g->must + g->mlen);
+		*cp++ = (char)OPND(s);
+	}
+	assert(cp == g->must + g->mlen);
+	*cp++ = '\0';		/* just on general principles */
+}
+
+/*
+ - pluscount - count + nesting
+ == static sopno pluscount(register struct parse *p, register struct re_guts *g);
+ */
+static sopno			/* nesting depth */
+pluscount(p, g)
+struct parse *p;
+register struct re_guts *g;
+{
+	register sop *scan;
+	register sop s;
+	register sopno plusnest = 0;
+	register sopno maxnest = 0;
+
+	if (p->error != 0)
+		return(0);	/* there may not be an OEND */
+
+	scan = g->strip + 1;
+	do {
+		s = *scan++;
+		switch (OP(s)) {
+		case OPLUS_:
+			plusnest++;
+			break;
+		case O_PLUS:
+			if (plusnest > maxnest)
+				maxnest = plusnest;
+			plusnest--;
+			break;
+		}
+	} while (OP(s) != OEND);
+	if (plusnest != 0)
+		g->iflags |= BAD;
+	return(maxnest);
+}
+
+/*
+ * $PchId: regcomp.c,v 1.2 1996/03/12 19:10:15 philip Exp $
+ */
Index: /trunk/minix/lib/regex/regerror.c
===================================================================
--- /trunk/minix/lib/regex/regerror.c	(revision 9)
+++ /trunk/minix/lib/regex/regerror.c	(revision 9)
@@ -0,0 +1,188 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)regerror.c	8.4 (Berkeley) 3/20/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regerror.c	8.4 (Berkeley) 3/20/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef __minix_vmd
+#include <bsd/asciictype.h>
+#else
+#include <ctype.h>
+#endif
+#include <limits.h>
+#include <stdlib.h>
+#include <regex.h>
+
+#include "utils.h"
+
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regerror.c === */
+static char *regatoi(const regex_t *preg, char *localbuf);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
+/*
+ = #define	REG_NOMATCH	 1
+ = #define	REG_BADPAT	 2
+ = #define	REG_ECOLLATE	 3
+ = #define	REG_ECTYPE	 4
+ = #define	REG_EESCAPE	 5
+ = #define	REG_ESUBREG	 6
+ = #define	REG_EBRACK	 7
+ = #define	REG_EPAREN	 8
+ = #define	REG_EBRACE	 9
+ = #define	REG_BADBR	10
+ = #define	REG_ERANGE	11
+ = #define	REG_ESPACE	12
+ = #define	REG_BADRPT	13
+ = #define	REG_EMPTY	14
+ = #define	REG_ASSERT	15
+ = #define	REG_INVARG	16
+ = #define	REG_ATOI	255	// convert name to number (!)
+ = #define	REG_ITOA	0400	// convert number to name (!)
+ */
+static struct rerr {
+	int code;
+	char *name;
+	char *explain;
+} rerrs[] = {
+	REG_NOMATCH,	"REG_NOMATCH",	"regexec() failed to match",
+	REG_BADPAT,	"REG_BADPAT",	"invalid regular expression",
+	REG_ECOLLATE,	"REG_ECOLLATE",	"invalid collating element",
+	REG_ECTYPE,	"REG_ECTYPE",	"invalid character class",
+	REG_EESCAPE,	"REG_EESCAPE",	"trailing backslash (\\)",
+	REG_ESUBREG,	"REG_ESUBREG",	"invalid backreference number",
+	REG_EBRACK,	"REG_EBRACK",	"brackets ([ ]) not balanced",
+	REG_EPAREN,	"REG_EPAREN",	"parentheses not balanced",
+	REG_EBRACE,	"REG_EBRACE",	"braces not balanced",
+	REG_BADBR,	"REG_BADBR",	"invalid repetition count(s)",
+	REG_ERANGE,	"REG_ERANGE",	"invalid character range",
+	REG_ESPACE,	"REG_ESPACE",	"out of memory",
+	REG_BADRPT,	"REG_BADRPT",	"repetition-operator operand invalid",
+	REG_EMPTY,	"REG_EMPTY",	"empty (sub)expression",
+	REG_ASSERT,	"REG_ASSERT",	"\"can't happen\" -- you found a bug",
+	REG_INVARG,	"REG_INVARG",	"invalid argument to regex routine",
+	0,		"",		"*** unknown regexp error code ***",
+};
+
+/*
+ - regerror - the interface to error numbers
+ = extern size_t regerror(int, const regex_t *, char *, size_t);
+ */
+/* ARGSUSED */
+size_t
+regerror(errcode, preg, errbuf, errbuf_size)
+int errcode;
+const regex_t *preg;
+char *errbuf;
+size_t errbuf_size;
+{
+	register struct rerr *r;
+	register size_t len;
+	register int target = errcode &~ REG_ITOA;
+	register char *s;
+	char convbuf[50];
+
+	if (errcode == REG_ATOI)
+		s = regatoi(preg, convbuf);
+	else {
+		for (r = rerrs; r->code != 0; r++)
+			if (r->code == target)
+				break;
+	
+		if (errcode&REG_ITOA) {
+			if (r->code != 0)
+				(void) strcpy(convbuf, r->name);
+			else
+				sprintf(convbuf, "REG_0x%x", target);
+			assert(strlen(convbuf) < sizeof(convbuf));
+			s = convbuf;
+		} else
+			s = r->explain;
+	}
+
+	len = strlen(s) + 1;
+	if (errbuf_size > 0) {
+		if (errbuf_size > len)
+			(void) strcpy(errbuf, s);
+		else {
+			(void) strncpy(errbuf, s, errbuf_size-1);
+			errbuf[errbuf_size-1] = '\0';
+		}
+	}
+
+	return(len);
+}
+
+/*
+ - regatoi - internal routine to implement REG_ATOI
+ == static char *regatoi(const regex_t *preg, char *localbuf);
+ */
+static char *
+regatoi(preg, localbuf)
+const regex_t *preg;
+char *localbuf;
+{
+	register struct rerr *r;
+	register size_t siz;
+	register char *p;
+
+	for (r = rerrs; r->code != 0; r++)
+		if (strcmp(r->name, preg->re_endp) == 0)
+			break;
+	if (r->code == 0)
+		return("0");
+
+	sprintf(localbuf, "%d", r->code);
+	return(localbuf);
+}
+
+/*
+ * $PchId: regerror.c,v 1.2 1996/03/12 19:10:15 philip Exp $
+ */
Index: /trunk/minix/lib/regex/regex.3
===================================================================
--- /trunk/minix/lib/regex/regex.3	(revision 9)
+++ /trunk/minix/lib/regex/regex.3	(revision 9)
@@ -0,0 +1,541 @@
+.\" Copyright (c) 1992, 1993, 1994 Henry Spencer.
+.\" Copyright (c) 1992, 1993, 1994
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Henry Spencer.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)regex.3	8.4 (Berkeley) 3/20/94
+.\"
+.TH REGEX 3 "March 20, 1994"
+.de ZR
+.\" one other place knows this name:  the SEE ALSO section
+.BR re_format (7) \\$1
+..
+.SH NAME
+regex, regcomp, regexec, regerror, regfree \- regular-expression library
+.SH SYNOPSIS
+.ft B
+.\".na
+#include <sys/types.h>
+.br
+#include <regex.h>
+.sp
+.in +.5i
+.ti -.5i
+int regcomp(regex_t *\fIpreg\fP, const char *\fIpattern\fP, int \fIcflags\fP);
+.ti -.5i
+int regexec(const regex_t *\fIpreg\fP, const char *\fIstring\fP,
+size_t \fInmatch\fP, regmatch_t \fIpmatch\fP[], int \fIeflags\fP);
+.ti -.5i
+size_t regerror(int \fIerrcode\fP, const regex_t *\fIpreg\fP,
+char *\fIerrbuf\fP, size_t \fIerrbuf_size\fP);
+.ti -.5i
+void regfree(regex_t *\fIpreg\fP);
+.in -.5i
+.ft R
+.SH DESCRIPTION
+These routines implement POSIX 1003.2 regular expressions (``RE''s);
+see
+.ZR .
+.B Regcomp
+compiles an RE written as a string into an internal form,
+.B regexec
+matches that internal form against a string and reports results,
+.B regerror
+transforms error codes from either into human-readable messages,
+and
+.B regfree
+frees any dynamically-allocated storage used by the internal form
+of an RE.
+.PP
+The header
+.I <regex.h>
+declares two structure types,
+.B regex_t
+and
+.BR regmatch_t ,
+the former for compiled internal forms and the latter for match reporting.
+It also declares the four functions,
+a type
+.BR regoff_t ,
+and a number of constants with names starting with ``REG_''.
+.PP
+.B Regcomp
+compiles the regular expression contained in the
+.I pattern
+string,
+subject to the flags in
+.IR cflags ,
+and places the results in the
+.B regex_t
+structure pointed to by
+.IR preg .
+.I Cflags
+is the bitwise OR of zero or more of the following flags:
+.IP REG_EXTENDED \w'REG_EXTENDED'u+2n
+Compile modern (``extended'') REs,
+rather than the obsolete (``basic'') REs that
+are the default.
+.IP REG_BASIC
+This is a synonym for 0,
+provided as a counterpart to REG_EXTENDED to improve readability.
+.IP REG_NOSPEC
+Compile with recognition of all special characters turned off.
+All characters are thus considered ordinary,
+so the ``RE'' is a literal string.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+REG_EXTENDED and REG_NOSPEC may not be used
+in the same call to
+.IR regcomp .
+.IP REG_ICASE
+Compile for matching that ignores upper/lower case distinctions.
+See
+.ZR .
+.IP REG_NOSUB
+Compile for matching that need only report success or failure,
+not what was matched.
+.IP REG_NEWLINE
+Compile for newline-sensitive matching.
+By default, newline is a completely ordinary character with no special
+meaning in either REs or strings.
+With this flag,
+`[^' bracket expressions and `.' never match newline,
+a `^' anchor matches the null string after any newline in the string
+in addition to its normal function,
+and the `$' anchor matches the null string before any newline in the
+string in addition to its normal function.
+.IP REG_PEND
+The regular expression ends,
+not at the first NUL,
+but just before the character pointed to by the
+.B re_endp
+member of the structure pointed to by
+.IR preg .
+The
+.B re_endp
+member is of type
+.BR "const\ char\ *" .
+This flag permits inclusion of NULs in the RE;
+they are considered ordinary characters.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+.PP
+When successful,
+.B regcomp
+returns 0 and fills in the structure pointed to by
+.IR preg .
+One member of that structure
+(other than
+.BR re_endp )
+is publicized:
+.BR re_nsub ,
+of type
+.BR size_t ,
+contains the number of parenthesized subexpressions within the RE
+(except that the value of this member is undefined if the
+REG_NOSUB flag was used).
+If
+.B regcomp
+fails, it returns a non-zero error code;
+see DIAGNOSTICS.
+.PP
+.B Regexec
+matches the compiled RE pointed to by
+.I preg
+against the
+.IR string ,
+subject to the flags in
+.IR eflags ,
+and reports results using
+.IR nmatch ,
+.IR pmatch ,
+and the returned value.
+The RE must have been compiled by a previous invocation of
+.BR regcomp .
+The compiled form is not altered during execution of
+.BR regexec ,
+so a single compiled RE can be used simultaneously by multiple threads.
+.PP
+By default,
+the NUL-terminated string pointed to by
+.I string
+is considered to be the text of an entire line, minus any terminating
+newline.
+The
+.I eflags
+argument is the bitwise OR of zero or more of the following flags:
+.IP REG_NOTBOL \w'REG_STARTEND'u+2n
+The first character of
+the string
+is not the beginning of a line, so the `^' anchor should not match before it.
+This does not affect the behavior of newlines under REG_NEWLINE.
+.IP REG_NOTEOL
+The NUL terminating
+the string
+does not end a line, so the `$' anchor should not match before it.
+This does not affect the behavior of newlines under REG_NEWLINE.
+.IP REG_STARTEND
+The string is considered to start at
+\fIstring\fR\ + \fIpmatch\fR[0].\fBrm_so\fR
+and to have a terminating NUL located at
+\fIstring\fR\ + \fIpmatch\fR[0].\fBrm_eo\fR
+(there need not actually be a NUL at that location),
+regardless of the value of
+.IR nmatch .
+See below for the definition of
+.IR pmatch
+and
+.IR nmatch .
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+Note that a non-zero \fBrm_so\fR does not imply REG_NOTBOL;
+REG_STARTEND affects only the location of the string,
+not how it is matched.
+.PP
+See
+.ZR
+for a discussion of what is matched in situations where an RE or a
+portion thereof could match any of several substrings of
+.IR string .
+.PP
+Normally,
+.B regexec
+returns 0 for success and the non-zero code REG_NOMATCH for failure.
+Other non-zero error codes may be returned in exceptional situations;
+see DIAGNOSTICS.
+.PP
+If REG_NOSUB was specified in the compilation of the RE,
+or if
+.I nmatch
+is 0,
+.B regexec
+ignores the
+.I pmatch
+argument (but see below for the case where REG_STARTEND is specified).
+Otherwise,
+.I pmatch
+points to an array of
+.I nmatch
+structures of type
+.BR regmatch_t .
+Such a structure has at least the members
+.B rm_so
+and
+.BR rm_eo ,
+both of type
+.B regoff_t
+(a signed arithmetic type at least as large as an
+.B off_t
+and a
+.BR ssize_t ),
+containing respectively the offset of the first character of a substring
+and the offset of the first character after the end of the substring.
+Offsets are measured from the beginning of the
+.I string
+argument given to
+.BR regexec .
+An empty substring is denoted by equal offsets,
+both indicating the character following the empty substring.
+.PP
+The 0th member of the
+.I pmatch
+array is filled in to indicate what substring of
+.I string
+was matched by the entire RE.
+Remaining members report what substring was matched by parenthesized
+subexpressions within the RE;
+member
+.I i
+reports subexpression
+.IR i ,
+with subexpressions counted (starting at 1) by the order of their opening
+parentheses in the RE, left to right.
+Unused entries in the array\(emcorresponding either to subexpressions that
+did not participate in the match at all, or to subexpressions that do not
+exist in the RE (that is, \fIi\fR\ > \fIpreg\fR\->\fBre_nsub\fR)\(emhave both
+.B rm_so
+and
+.B rm_eo
+set to \-1.
+If a subexpression participated in the match several times,
+the reported substring is the last one it matched.
+(Note, as an example in particular, that when the RE `(b*)+' matches `bbb',
+the parenthesized subexpression matches each of the three `b's and then
+an infinite number of empty strings following the last `b',
+so the reported substring is one of the empties.)
+.PP
+If REG_STARTEND is specified,
+.I pmatch
+must point to at least one
+.B regmatch_t
+(even if
+.I nmatch
+is 0 or REG_NOSUB was specified),
+to hold the input offsets for REG_STARTEND.
+Use for output is still entirely controlled by
+.IR nmatch ;
+if
+.I nmatch
+is 0 or REG_NOSUB was specified,
+the value of
+.IR pmatch [0]
+will not be changed by a successful
+.BR regexec .
+.PP
+.B Regerror
+maps a non-zero
+.I errcode
+from either
+.B regcomp
+or
+.B regexec
+to a human-readable, printable message.
+If
+.I preg
+is non-NULL,
+the error code should have arisen from use of
+the
+.B regex_t
+pointed to by
+.IR preg ,
+and if the error code came from
+.BR regcomp ,
+it should have been the result from the most recent
+.B regcomp
+using that
+.BR regex_t .
+.RI ( Regerror
+may be able to supply a more detailed message using information
+from the
+.BR regex_t .)
+.B Regerror
+places the NUL-terminated message into the buffer pointed to by
+.IR errbuf ,
+limiting the length (including the NUL) to at most
+.I errbuf_size
+bytes.
+If the whole message won't fit,
+as much of it as will fit before the terminating NUL is supplied.
+In any case,
+the returned value is the size of buffer needed to hold the whole
+message (including terminating NUL).
+If
+.I errbuf_size
+is 0,
+.I errbuf
+is ignored but the return value is still correct.
+.PP
+If the
+.I errcode
+given to
+.B regerror
+is first ORed with REG_ITOA,
+the ``message'' that results is the printable name of the error code,
+e.g. ``REG_NOMATCH'',
+rather than an explanation thereof.
+If
+.I errcode
+is REG_ATOI,
+then
+.I preg
+shall be non-NULL and the
+.B re_endp
+member of the structure it points to
+must point to the printable name of an error code;
+in this case, the result in
+.I errbuf
+is the decimal digits of
+the numeric value of the error code
+(0 if the name is not recognized).
+REG_ITOA and REG_ATOI are intended primarily as debugging facilities;
+they are extensions,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+Be warned also that they are considered experimental and changes are possible.
+.PP
+.B Regfree
+frees any dynamically-allocated storage associated with the compiled RE
+pointed to by
+.IR preg .
+The remaining
+.B regex_t
+is no longer a valid compiled RE
+and the effect of supplying it to
+.B regexec
+or
+.B regerror
+is undefined.
+.PP
+None of these functions references global variables except for tables
+of constants;
+all are safe for use from multiple threads if the arguments are safe.
+.SH IMPLEMENTATION CHOICES
+There are a number of decisions that 1003.2 leaves up to the implementor,
+either by explicitly saying ``undefined'' or by virtue of them being
+forbidden by the RE grammar.
+This implementation treats them as follows.
+.PP
+See
+.ZR
+for a discussion of the definition of case-independent matching.
+.PP
+There is no particular limit on the length of REs,
+except insofar as memory is limited.
+Memory usage is approximately linear in RE size, and largely insensitive
+to RE complexity, except for bounded repetitions.
+See BUGS for one short RE using them
+that will run almost any system out of memory.
+.PP
+A backslashed character other than one specifically given a magic meaning
+by 1003.2 (such magic meanings occur only in obsolete [``basic''] REs)
+is taken as an ordinary character.
+.PP
+Any unmatched [ is a REG_EBRACK error.
+.PP
+Equivalence classes cannot begin or end bracket-expression ranges.
+The endpoint of one range cannot begin another.
+.PP
+RE_DUP_MAX, the limit on repetition counts in bounded repetitions, is 255.
+.PP
+A repetition operator (?, *, +, or bounds) cannot follow another
+repetition operator.
+A repetition operator cannot begin an expression or subexpression
+or follow `^' or `|'.
+.PP
+`|' cannot appear first or last in a (sub)expression or after another `|',
+i.e. an operand of `|' cannot be an empty subexpression.
+An empty parenthesized subexpression, `()', is legal and matches an
+empty (sub)string.
+An empty string is not a legal RE.
+.PP
+A `{' followed by a digit is considered the beginning of bounds for a
+bounded repetition, which must then follow the syntax for bounds.
+A `{' \fInot\fR followed by a digit is considered an ordinary character.
+.PP
+`^' and `$' beginning and ending subexpressions in obsolete (``basic'')
+REs are anchors, not ordinary characters.
+.SH SEE ALSO
+.BR grep (1),
+.BR re_format (7).
+.PP
+POSIX 1003.2, sections 2.8 (Regular Expression Notation)
+and
+B.5 (C Binding for Regular Expression Matching).
+.SH DIAGNOSTICS
+Non-zero error codes from
+.B regcomp
+and
+.B regexec
+include the following:
+.PP
+.nf
+.ta \w'REG_ECOLLATE'u+3n
+REG_NOMATCH	regexec() failed to match
+REG_BADPAT	invalid regular expression
+REG_ECOLLATE	invalid collating element
+REG_ECTYPE	invalid character class
+REG_EESCAPE	\e applied to unescapable character
+REG_ESUBREG	invalid backreference number
+REG_EBRACK	brackets [ ] not balanced
+REG_EPAREN	parentheses ( ) not balanced
+REG_EBRACE	braces { } not balanced
+REG_BADBR	invalid repetition count(s) in { }
+REG_ERANGE	invalid character range in [ ]
+REG_ESPACE	ran out of memory
+REG_BADRPT	?, *, or + operand invalid
+REG_EMPTY	empty (sub)expression
+REG_ASSERT	``can't happen''\(emyou found a bug
+REG_INVARG	invalid argument, e.g. negative-length string
+.fi
+.SH HISTORY
+Originally written by Henry Spencer.
+Altered for inclusion in the 4.4BSD distribution.
+.SH BUGS
+This is an alpha release with known defects.
+Please report problems.
+.PP
+There is one known functionality bug.
+The implementation of internationalization is incomplete:
+the locale is always assumed to be the default one of 1003.2,
+and only the collating elements etc. of that locale are available.
+.PP
+The back-reference code is subtle and doubts linger about its correctness
+in complex cases.
+.PP
+.B Regexec
+performance is poor.
+This will improve with later releases.
+.I Nmatch
+exceeding 0 is expensive;
+.I nmatch
+exceeding 1 is worse.
+.B Regexec
+is largely insensitive to RE complexity \fIexcept\fR that back
+references are massively expensive.
+RE length does matter; in particular, there is a strong speed bonus
+for keeping RE length under about 30 characters,
+with most special characters counting roughly double.
+.PP
+.B Regcomp
+implements bounded repetitions by macro expansion,
+which is costly in time and space if counts are large
+or bounded repetitions are nested.
+An RE like, say,
+`((((a{1,100}){1,100}){1,100}){1,100}){1,100}'
+will (eventually) run almost any existing machine out of swap space.
+.PP
+There are suspected problems with response to obscure error conditions.
+Notably,
+certain kinds of internal overflow,
+produced only by truly enormous REs or by multiply nested bounded repetitions,
+are probably not handled well.
+.PP
+Due to a mistake in 1003.2, things like `a)b' are legal REs because `)' is
+a special character only in the presence of a previous unmatched `('.
+This can't be fixed until the spec is fixed.
+.PP
+The standard's definition of back references is vague.
+For example, does
+`a\e(\e(b\e)*\e2\e)*d' match `abbbd'?
+Until the standard is clarified,
+behavior in such cases should not be relied on.
+.PP
+The implementation of word-boundary matching is a bit of a kludge,
+and bugs may lurk in combinations of word-boundary matching and anchoring.
Index: /trunk/minix/lib/regex/regex2.h
===================================================================
--- /trunk/minix/lib/regex/regex2.h	(revision 9)
+++ /trunk/minix/lib/regex/regex2.h	(revision 9)
@@ -0,0 +1,173 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)regex2.h	8.4 (Berkeley) 3/20/94
+ */
+
+/*
+ * First, the stuff that ends up in the outside-world include file
+ = typedef off_t regoff_t;
+ = typedef struct {
+ = 	int re_magic;
+ = 	size_t re_nsub;		// number of parenthesized subexpressions
+ = 	const char *re_endp;	// end pointer for REG_PEND
+ = 	struct re_guts *re_g;	// none of your business :-)
+ = } regex_t;
+ = typedef struct {
+ = 	regoff_t rm_so;		// start of match
+ = 	regoff_t rm_eo;		// end of match
+ = } regmatch_t;
+ */
+/*
+ * internals of regex_t
+ */
+#define	MAGIC1	((('r'^0200)<<8) | 'e')
+
+/*
+ * The internal representation is a *strip*, a sequence of
+ * operators ending with an endmarker.  (Some terminology etc. is a
+ * historical relic of earlier versions which used multiple strips.)
+ * Certain oddities in the representation are there to permit running
+ * the machinery backwards; in particular, any deviation from sequential
+ * flow must be marked at both its source and its destination.  Some
+ * fine points:
+ *
+ * - OPLUS_ and O_PLUS are *inside* the loop they create.
+ * - OQUEST_ and O_QUEST are *outside* the bypass they create.
+ * - OCH_ and O_CH are *outside* the multi-way branch they create, while
+ *   OOR1 and OOR2 are respectively the end and the beginning of one of
+ *   the branches.  Note that there is an implicit OOR2 following OCH_
+ *   and an implicit OOR1 preceding O_CH.
+ *
+ * In state representations, an operator's bit is on to signify a state
+ * immediately *preceding* "execution" of that operator.
+ */
+typedef unsigned long sop;	/* strip operator */
+typedef long sopno;
+#define	OPRMASK	0xf8000000
+#define	OPDMASK	0x07ffffff
+#define	OPSHIFT	((unsigned)27)
+#define	OP(n)	((n)&OPRMASK)
+#define	OPND(n)	((n)&OPDMASK)
+#define	SOP(op, opnd)	((op)|(opnd))
+/* operators			   meaning	operand			*/
+/*						(back, fwd are offsets)	*/
+#define	OEND	(1<<OPSHIFT)	/* endmarker	-			*/
+#define	OCHAR	(2<<OPSHIFT)	/* character	unsigned char		*/
+#define	OBOL	(3<<OPSHIFT)	/* left anchor	-			*/
+#define	OEOL	(4<<OPSHIFT)	/* right anchor	-			*/
+#define	OANY	(5<<OPSHIFT)	/* .		-			*/
+#define	OANYOF	(6<<OPSHIFT)	/* [...]	set number		*/
+#define	OBACK_	(7<<OPSHIFT)	/* begin \d	paren number		*/
+#define	O_BACK	(8<<OPSHIFT)	/* end \d	paren number		*/
+#define	OPLUS_	(9<<OPSHIFT)	/* + prefix	fwd to suffix		*/
+#define	O_PLUS	(10<<OPSHIFT)	/* + suffix	back to prefix		*/
+#define	OQUEST_	(11<<OPSHIFT)	/* ? prefix	fwd to suffix		*/
+#define	O_QUEST	(12<<OPSHIFT)	/* ? suffix	back to prefix		*/
+#define	OLPAREN	(13<<OPSHIFT)	/* (		fwd to )		*/
+#define	ORPAREN	(14<<OPSHIFT)	/* )		back to (		*/
+#define	OCH_	(15<<OPSHIFT)	/* begin choice	fwd to OOR2		*/
+#define	OOR1	(16<<OPSHIFT)	/* | pt. 1	back to OOR1 or OCH_	*/
+#define	OOR2	(17<<OPSHIFT)	/* | pt. 2	fwd to OOR2 or O_CH	*/
+#define	O_CH	(18<<OPSHIFT)	/* end choice	back to OOR1		*/
+#define	OBOW	(19<<OPSHIFT)	/* begin word	-			*/
+#define	OEOW	(20<<OPSHIFT)	/* end word	-			*/
+
+/*
+ * Structure for [] character-set representation.  Character sets are
+ * done as bit vectors, grouped 8 to a byte vector for compactness.
+ * The individual set therefore has both a pointer to the byte vector
+ * and a mask to pick out the relevant bit of each byte.  A hash code
+ * simplifies testing whether two sets could be identical.
+ *
+ * This will get trickier for multicharacter collating elements.  As
+ * preliminary hooks for dealing with such things, we also carry along
+ * a string of multi-character elements, and decide the size of the
+ * vectors at run time.
+ */
+typedef struct {
+	uch *ptr;		/* -> uch [csetsize] */
+	uch mask;		/* bit within array */
+	uch hash;		/* hash code */
+	size_t smultis;
+	char *multis;		/* -> char[smulti]  ab\0cd\0ef\0\0 */
+} cset;
+/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */
+#define	CHadd(cs, c)	((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c))
+#define	CHsub(cs, c)	((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c))
+#define	CHIN(cs, c)	((cs)->ptr[(uch)(c)] & (cs)->mask)
+#define	MCadd(p, cs, cp)	mcadd(p, cs, cp)	/* regcomp() internal fns */
+#define	MCsub(p, cs, cp)	mcsub(p, cs, cp)
+#define	MCin(p, cs, cp)	mcin(p, cs, cp)
+
+/* stuff for character categories */
+typedef unsigned char cat_t;
+
+/*
+ * main compiled-expression structure
+ */
+struct re_guts {
+	int magic;
+#		define	MAGIC2	((('R'^0200)<<8)|'E')
+	sop *strip;		/* malloced area for strip */
+	int csetsize;		/* number of bits in a cset vector */
+	int ncsets;		/* number of csets in use */
+	cset *sets;		/* -> cset [ncsets] */
+	uch *setbits;		/* -> uch[csetsize][ncsets/CHAR_BIT] */
+	int cflags;		/* copy of regcomp() cflags argument */
+	sopno nstates;		/* = number of sops */
+	sopno firststate;	/* the initial OEND (normally 0) */
+	sopno laststate;	/* the final OEND */
+	int iflags;		/* internal flags */
+#		define	USEBOL	01	/* used ^ */
+#		define	USEEOL	02	/* used $ */
+#		define	BAD	04	/* something wrong */
+	int nbol;		/* number of ^ used */
+	int neol;		/* number of $ used */
+	int ncategories;	/* how many character categories */
+	cat_t *categories;	/* ->catspace[-CHAR_MIN] */
+	char *must;		/* match must contain this string */
+	int mlen;		/* length of must */
+	size_t nsub;		/* copy of re_nsub */
+	int backrefs;		/* does it use back references? */
+	sopno nplus;		/* how deep does it nest +s? */
+	/* catspace must be last */
+	cat_t catspace[1];	/* actually [NC] */
+};
+
+/* misc utilities */
+#define	OUT	(CHAR_MAX+1)	/* a non-character value */
+#define	ISWORD(c)	(isalnum(c) || (c) == '_')
Index: /trunk/minix/lib/regex/regexec.c
===================================================================
--- /trunk/minix/lib/regex/regexec.c	(revision 9)
+++ /trunk/minix/lib/regex/regexec.c	(revision 9)
@@ -0,0 +1,189 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)regexec.c	8.3 (Berkeley) 3/20/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regexec.c	8.3 (Berkeley) 3/20/94";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * the outer shell of regexec()
+ *
+ * This file includes engine.c *twice*, after muchos fiddling with the
+ * macros that code uses.  This lets the same code operate on two different
+ * representations for state sets.
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#ifdef __minix_vmd
+#include <bsd/asciictype.h>
+#else
+#include <ctype.h>
+#endif
+#include <regex.h>
+
+#include "utils.h"
+#include "regex2.h"
+
+static int nope = 0;		/* for use in asserts; shuts lint up */
+
+/* macros for manipulating states, small version */
+#define	states	long
+#define	states1	states		/* for later use in regexec() decision */
+#define	CLEAR(v)	((v) = 0)
+#define	SET0(v, n)	((v) &= ~(1 << (n)))
+#define	SET1(v, n)	((v) |= 1 << (n))
+#define	ISSET(v, n)	((v) & (1 << (n)))
+#define	ASSIGN(d, s)	((d) = (s))
+#define	EQ(a, b)	((a) == (b))
+#define	STATEVARS	int dummy	/* dummy version */
+#define	STATESETUP(m, n)	/* nothing */
+#define	STATETEARDOWN(m)	/* nothing */
+#define	SETUP(v)	((v) = 0)
+#define	onestate	int
+#define	INIT(o, n)	((o) = (unsigned)1 << (n))
+#define	INC(o)	((o) <<= 1)
+#define	ISSTATEIN(v, o)	((v) & (o))
+/* some abbreviations; note that some of these know variable names! */
+/* do "if I'm here, I can also be there" etc without branches */
+#define	FWD(dst, src, n)	((dst) |= ((unsigned)(src)&(here)) << (n))
+#define	BACK(dst, src, n)	((dst) |= ((unsigned)(src)&(here)) >> (n))
+#define	ISSETBACK(v, n)	((v) & ((unsigned)here >> (n)))
+/* function names */
+#define SNAMES			/* engine.c looks after details */
+
+#include "engine.c"
+
+/* now undo things */
+#undef	states
+#undef	CLEAR
+#undef	SET0
+#undef	SET1
+#undef	ISSET
+#undef	ASSIGN
+#undef	EQ
+#undef	STATEVARS
+#undef	STATESETUP
+#undef	STATETEARDOWN
+#undef	SETUP
+#undef	onestate
+#undef	INIT
+#undef	INC
+#undef	ISSTATEIN
+#undef	FWD
+#undef	BACK
+#undef	ISSETBACK
+#undef	SNAMES
+
+/* macros for manipulating states, large version */
+#define	states	char *
+#define	CLEAR(v)	memset(v, 0, m->g->nstates)
+#define	SET0(v, n)	((v)[n] = 0)
+#define	SET1(v, n)	((v)[n] = 1)
+#define	ISSET(v, n)	((v)[n])
+#define	ASSIGN(d, s)	memcpy(d, s, m->g->nstates)
+#define	EQ(a, b)	(memcmp(a, b, m->g->nstates) == 0)
+#define	STATEVARS	int vn; char *space
+#define	STATESETUP(m, nv)	{ (m)->space = malloc((nv)*(m)->g->nstates); \
+				if ((m)->space == NULL) return(REG_ESPACE); \
+				(m)->vn = 0; }
+#define	STATETEARDOWN(m)	{ free((m)->space); }
+#define	SETUP(v)	((v) = &m->space[m->vn++ * m->g->nstates])
+#define	onestate	int
+#define	INIT(o, n)	((o) = (n))
+#define	INC(o)	((o)++)
+#define	ISSTATEIN(v, o)	((v)[o])
+/* some abbreviations; note that some of these know variable names! */
+/* do "if I'm here, I can also be there" etc without branches */
+#define	FWD(dst, src, n)	((dst)[here+(n)] |= (src)[here])
+#define	BACK(dst, src, n)	((dst)[here-(n)] |= (src)[here])
+#define	ISSETBACK(v, n)	((v)[here - (n)])
+/* function names */
+#define	LNAMES			/* flag */
+
+#include "engine.c"
+
+/*
+ - regexec - interface for matching
+ = extern int regexec(const regex_t *, const char *, size_t, \
+ =					regmatch_t [], int);
+ = #define	REG_NOTBOL	00001
+ = #define	REG_NOTEOL	00002
+ = #define	REG_STARTEND	00004
+ = #define	REG_TRACE	00400	// tracing of execution
+ = #define	REG_LARGE	01000	// force large representation
+ = #define	REG_BACKR	02000	// force use of backref code
+ *
+ * We put this here so we can exploit knowledge of the state representation
+ * when choosing which matcher to call.  Also, by this point the matchers
+ * have been prototyped.
+ */
+int				/* 0 success, REG_NOMATCH failure */
+regexec(preg, string, nmatch, pmatch, eflags)
+const regex_t *preg;
+const char *string;
+size_t nmatch;
+regmatch_t pmatch[];
+int eflags;
+{
+	register struct re_guts *g = preg->re_g;
+#ifdef REDEBUG
+#	define	GOODFLAGS(f)	(f)
+#else
+#	define	GOODFLAGS(f)	((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND))
+#endif
+
+	if (preg->re_magic != MAGIC1 || g->magic != MAGIC2)
+		return(REG_BADPAT);
+	assert(!(g->iflags&BAD));
+	if (g->iflags&BAD)		/* backstop for no-debug case */
+		return(REG_BADPAT);
+	eflags = GOODFLAGS(eflags);
+
+	if (g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags&REG_LARGE))
+		return(smatcher(g, (char *)string, nmatch, pmatch, eflags));
+	else
+		return(lmatcher(g, (char *)string, nmatch, pmatch, eflags));
+}
+
+/*
+ * $PchId: regexec.c,v 1.2 1996/03/12 19:10:15 philip Exp $
+ */
Index: /trunk/minix/lib/regex/regfree.c
===================================================================
--- /trunk/minix/lib/regex/regfree.c	(revision 9)
+++ /trunk/minix/lib/regex/regfree.c	(revision 9)
@@ -0,0 +1,84 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)regfree.c	8.3 (Berkeley) 3/20/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regfree.c	8.3 (Berkeley) 3/20/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <regex.h>
+
+#include "utils.h"
+#include "regex2.h"
+
+/*
+ - regfree - free everything
+ = extern void regfree(regex_t *);
+ */
+void
+regfree(preg)
+regex_t *preg;
+{
+	register struct re_guts *g;
+
+	if (preg->re_magic != MAGIC1)	/* oops */
+		return;			/* nice to complain, but hard */
+
+	g = preg->re_g;
+	if (g == NULL || g->magic != MAGIC2)	/* oops again */
+		return;
+	preg->re_magic = 0;		/* mark it invalid */
+	g->magic = 0;			/* mark it invalid */
+
+	if (g->strip != NULL)
+		free((char *)g->strip);
+	if (g->sets != NULL)
+		free((char *)g->sets);
+	if (g->setbits != NULL)
+		free((char *)g->setbits);
+	if (g->must != NULL)
+		free(g->must);
+	free((char *)g);
+}
+
+/*
+ * $PchId: regfree.c,v 1.2 1996/03/12 19:10:15 philip Exp $
+ */
Index: /trunk/minix/lib/regex/utils.h
===================================================================
--- /trunk/minix/lib/regex/utils.h	(revision 9)
+++ /trunk/minix/lib/regex/utils.h	(revision 9)
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)utils.h	8.3 (Berkeley) 3/20/94
+ */
+
+/* utility definitions */
+#ifdef _POSIX2_RE_DUP_MAX
+#define	DUPMAX		_POSIX2_RE_DUP_MAX	/* xxx is this right? */
+#else
+#define	DUPMAX		255
+#endif
+#define	INFINITY	(DUPMAX + 1)
+#define	NC		(CHAR_MAX - CHAR_MIN + 1)
+typedef unsigned char uch;
+
+/* switch off assertions (if not already off) if no REDEBUG */
+#ifndef REDEBUG
+#ifndef NDEBUG
+#define	NDEBUG	/* no assertions please */
+#endif
+#endif
+#include <assert.h>
+
+/* for old systems with bcopy() but no memmove() */
+#ifdef USEBCOPY
+#define	memmove(d, s, c)	bcopy(s, d, c)
+#endif
Index: /trunk/minix/lib/stdio/Makedepend-ack
===================================================================
--- /trunk/minix/lib/stdio/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/stdio/Makedepend-ack	(revision 9)
@@ -0,0 +1,54 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' clearerr.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' data.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' doprnt.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' doscan.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' ecvt.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fclose.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' feof.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' ferror.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fflush.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fgetc.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fgetpos.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fgets.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fileno.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fillbuf.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' flushbuf.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fopen.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fprintf.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fputc.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fputs.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fread.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' freopen.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fscanf.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fseek.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fsetpos.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' ftell.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fwrite.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' getc.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' getchar.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' gets.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' icompute.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' mktemp.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' perror.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' printf.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' putc.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' putchar.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' puts.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' remove.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' rewind.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' scanf.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' setbuf.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' setvbuf.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sprintf.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sscanf.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' tmpfile.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' tmpnam.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' ungetc.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' vfprintf.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' vprintf.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' vscanf.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' vsprintf.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' vsscanf.c | sed -e 's:^\(.\):../obj-ack//./stdio/\1:' >> .depend-ack
Index: /trunk/minix/lib/stdio/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/stdio/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/stdio/Makedepend-gnu	(revision 9)
@@ -0,0 +1,54 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' clearerr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' data.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' doprnt.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' doscan.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' ecvt.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fclose.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' feof.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' ferror.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fflush.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fgetc.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fgetpos.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fgets.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fileno.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fillbuf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' flushbuf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fopen.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fprintf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fputc.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fputs.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fread.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' freopen.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fscanf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fseek.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fsetpos.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' ftell.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fwrite.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' getc.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' getchar.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' gets.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' icompute.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' mktemp.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' perror.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' printf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' putc.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' putchar.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' puts.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' remove.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' rewind.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' scanf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' setbuf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' setvbuf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sprintf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sscanf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' tmpfile.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' tmpnam.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' ungetc.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' vfprintf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' vprintf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' vscanf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' vsprintf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' vsscanf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./stdio/\1:' >> .depend-gnu
Index: /trunk/minix/lib/stdio/Makefile
===================================================================
--- /trunk/minix/lib/stdio/Makefile	(revision 9)
+++ /trunk/minix/lib/stdio/Makefile	(revision 9)
@@ -0,0 +1,402 @@
+#Generated from ./stdio/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./stdio ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./stdio ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libc.a
+
+../obj-ack//libc.a: ../obj-ack//libc.a(clearerr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(data.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(doprnt.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(doscan.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ecvt.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fclose.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(feof.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ferror.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fflush.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fgetc.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fgetpos.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fgets.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fileno.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fillbuf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(flushbuf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fopen.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fprintf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fputc.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fputs.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fread.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(freopen.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fscanf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fseek.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fsetpos.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ftell.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fwrite.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getc.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getchar.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(gets.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(icompute.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(mktemp.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(perror.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(printf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(putc.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(putchar.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(puts.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(remove.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(rewind.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(scanf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(setbuf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(setvbuf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sprintf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sscanf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(tmpfile.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(tmpnam.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ungetc.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(vfprintf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(vprintf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(vscanf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(vsprintf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(vsscanf.o)
+
+../obj-ack//libc.a:
+	ar cr ../obj-ack//libc.a ../obj-ack//./stdio/*.o
+	rm ../obj-ack//./stdio/*.o
+
+../obj-ack//libc.a(clearerr.o): clearerr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/clearerr.o clearerr.c
+../obj-ack//libc.a(data.o): data.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/data.o data.c
+../obj-ack//libc.a(doprnt.o): doprnt.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/doprnt.o doprnt.c
+../obj-ack//libc.a(doscan.o): doscan.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/doscan.o doscan.c
+../obj-ack//libc.a(ecvt.o): ecvt.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/ecvt.o ecvt.c
+../obj-ack//libc.a(fclose.o): fclose.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fclose.o fclose.c
+../obj-ack//libc.a(feof.o): feof.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/feof.o feof.c
+../obj-ack//libc.a(ferror.o): ferror.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/ferror.o ferror.c
+../obj-ack//libc.a(fflush.o): fflush.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fflush.o fflush.c
+../obj-ack//libc.a(fgetc.o): fgetc.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fgetc.o fgetc.c
+../obj-ack//libc.a(fgetpos.o): fgetpos.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fgetpos.o fgetpos.c
+../obj-ack//libc.a(fgets.o): fgets.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fgets.o fgets.c
+../obj-ack//libc.a(fileno.o): fileno.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fileno.o fileno.c
+../obj-ack//libc.a(fillbuf.o): fillbuf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fillbuf.o fillbuf.c
+../obj-ack//libc.a(flushbuf.o): flushbuf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/flushbuf.o flushbuf.c
+../obj-ack//libc.a(fopen.o): fopen.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fopen.o fopen.c
+../obj-ack//libc.a(fprintf.o): fprintf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fprintf.o fprintf.c
+../obj-ack//libc.a(fputc.o): fputc.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fputc.o fputc.c
+../obj-ack//libc.a(fputs.o): fputs.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fputs.o fputs.c
+../obj-ack//libc.a(fread.o): fread.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fread.o fread.c
+../obj-ack//libc.a(freopen.o): freopen.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/freopen.o freopen.c
+../obj-ack//libc.a(fscanf.o): fscanf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fscanf.o fscanf.c
+../obj-ack//libc.a(fseek.o): fseek.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fseek.o fseek.c
+../obj-ack//libc.a(fsetpos.o): fsetpos.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fsetpos.o fsetpos.c
+../obj-ack//libc.a(ftell.o): ftell.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/ftell.o ftell.c
+../obj-ack//libc.a(fwrite.o): fwrite.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/fwrite.o fwrite.c
+../obj-ack//libc.a(getc.o): getc.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/getc.o getc.c
+../obj-ack//libc.a(getchar.o): getchar.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/getchar.o getchar.c
+../obj-ack//libc.a(gets.o): gets.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/gets.o gets.c
+../obj-ack//libc.a(icompute.o): icompute.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/icompute.o icompute.c
+../obj-ack//libc.a(mktemp.o): mktemp.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/mktemp.o mktemp.c
+../obj-ack//libc.a(perror.o): perror.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/perror.o perror.c
+../obj-ack//libc.a(printf.o): printf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/printf.o printf.c
+../obj-ack//libc.a(putc.o): putc.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/putc.o putc.c
+../obj-ack//libc.a(putchar.o): putchar.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/putchar.o putchar.c
+../obj-ack//libc.a(puts.o): puts.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/puts.o puts.c
+../obj-ack//libc.a(remove.o): remove.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/remove.o remove.c
+../obj-ack//libc.a(rewind.o): rewind.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/rewind.o rewind.c
+../obj-ack//libc.a(scanf.o): scanf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/scanf.o scanf.c
+../obj-ack//libc.a(setbuf.o): setbuf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/setbuf.o setbuf.c
+../obj-ack//libc.a(setvbuf.o): setvbuf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/setvbuf.o setvbuf.c
+../obj-ack//libc.a(sprintf.o): sprintf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/sprintf.o sprintf.c
+../obj-ack//libc.a(sscanf.o): sscanf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/sscanf.o sscanf.c
+../obj-ack//libc.a(tmpfile.o): tmpfile.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/tmpfile.o tmpfile.c
+../obj-ack//libc.a(tmpnam.o): tmpnam.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/tmpnam.o tmpnam.c
+../obj-ack//libc.a(ungetc.o): ungetc.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/ungetc.o ungetc.c
+../obj-ack//libc.a(vfprintf.o): vfprintf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/vfprintf.o vfprintf.c
+../obj-ack//libc.a(vprintf.o): vprintf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/vprintf.o vprintf.c
+../obj-ack//libc.a(vscanf.o): vscanf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/vscanf.o vscanf.c
+../obj-ack//libc.a(vsprintf.o): vsprintf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/vsprintf.o vsprintf.c
+../obj-ack//libc.a(vsscanf.o): vsscanf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./stdio/vsscanf.o vsscanf.c
+
+all-gnu: ../obj-gnu/libc.a
+
+../obj-gnu/libc.a: ../obj-gnu/./stdio/clearerr.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/data.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/doprnt.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/doscan.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/ecvt.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fclose.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/feof.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/ferror.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fflush.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fgetc.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fgetpos.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fgets.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fileno.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fillbuf.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/flushbuf.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fopen.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fprintf.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fputc.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fputs.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fread.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/freopen.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fscanf.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fseek.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fsetpos.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/ftell.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/fwrite.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/getc.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/getchar.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/gets.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/icompute.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/mktemp.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/perror.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/printf.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/putc.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/putchar.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/puts.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/remove.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/rewind.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/scanf.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/setbuf.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/setvbuf.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/sprintf.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/sscanf.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/tmpfile.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/tmpnam.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/ungetc.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/vfprintf.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/vprintf.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/vscanf.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/vsprintf.o
+../obj-gnu/libc.a: ../obj-gnu/./stdio/vsscanf.o
+
+../obj-gnu/libc.a:
+	gar cr ../obj-gnu/libc.a $?
+
+../obj-gnu/./stdio/clearerr.o: clearerr.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/clearerr.o clearerr.c
+
+../obj-gnu/./stdio/data.o: data.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/data.o data.c
+
+../obj-gnu/./stdio/doprnt.o: doprnt.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/doprnt.o doprnt.c
+
+../obj-gnu/./stdio/doscan.o: doscan.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/doscan.o doscan.c
+
+../obj-gnu/./stdio/ecvt.o: ecvt.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/ecvt.o ecvt.c
+
+../obj-gnu/./stdio/fclose.o: fclose.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fclose.o fclose.c
+
+../obj-gnu/./stdio/feof.o: feof.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/feof.o feof.c
+
+../obj-gnu/./stdio/ferror.o: ferror.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/ferror.o ferror.c
+
+../obj-gnu/./stdio/fflush.o: fflush.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fflush.o fflush.c
+
+../obj-gnu/./stdio/fgetc.o: fgetc.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fgetc.o fgetc.c
+
+../obj-gnu/./stdio/fgetpos.o: fgetpos.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fgetpos.o fgetpos.c
+
+../obj-gnu/./stdio/fgets.o: fgets.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fgets.o fgets.c
+
+../obj-gnu/./stdio/fileno.o: fileno.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fileno.o fileno.c
+
+../obj-gnu/./stdio/fillbuf.o: fillbuf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fillbuf.o fillbuf.c
+
+../obj-gnu/./stdio/flushbuf.o: flushbuf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/flushbuf.o flushbuf.c
+
+../obj-gnu/./stdio/fopen.o: fopen.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fopen.o fopen.c
+
+../obj-gnu/./stdio/fprintf.o: fprintf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fprintf.o fprintf.c
+
+../obj-gnu/./stdio/fputc.o: fputc.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fputc.o fputc.c
+
+../obj-gnu/./stdio/fputs.o: fputs.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fputs.o fputs.c
+
+../obj-gnu/./stdio/fread.o: fread.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fread.o fread.c
+
+../obj-gnu/./stdio/freopen.o: freopen.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/freopen.o freopen.c
+
+../obj-gnu/./stdio/fscanf.o: fscanf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fscanf.o fscanf.c
+
+../obj-gnu/./stdio/fseek.o: fseek.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fseek.o fseek.c
+
+../obj-gnu/./stdio/fsetpos.o: fsetpos.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fsetpos.o fsetpos.c
+
+../obj-gnu/./stdio/ftell.o: ftell.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/ftell.o ftell.c
+
+../obj-gnu/./stdio/fwrite.o: fwrite.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/fwrite.o fwrite.c
+
+../obj-gnu/./stdio/getc.o: getc.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/getc.o getc.c
+
+../obj-gnu/./stdio/getchar.o: getchar.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/getchar.o getchar.c
+
+../obj-gnu/./stdio/gets.o: gets.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/gets.o gets.c
+
+../obj-gnu/./stdio/icompute.o: icompute.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/icompute.o icompute.c
+
+../obj-gnu/./stdio/mktemp.o: mktemp.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/mktemp.o mktemp.c
+
+../obj-gnu/./stdio/perror.o: perror.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/perror.o perror.c
+
+../obj-gnu/./stdio/printf.o: printf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/printf.o printf.c
+
+../obj-gnu/./stdio/putc.o: putc.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/putc.o putc.c
+
+../obj-gnu/./stdio/putchar.o: putchar.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/putchar.o putchar.c
+
+../obj-gnu/./stdio/puts.o: puts.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/puts.o puts.c
+
+../obj-gnu/./stdio/remove.o: remove.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/remove.o remove.c
+
+../obj-gnu/./stdio/rewind.o: rewind.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/rewind.o rewind.c
+
+../obj-gnu/./stdio/scanf.o: scanf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/scanf.o scanf.c
+
+../obj-gnu/./stdio/setbuf.o: setbuf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/setbuf.o setbuf.c
+
+../obj-gnu/./stdio/setvbuf.o: setvbuf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/setvbuf.o setvbuf.c
+
+../obj-gnu/./stdio/sprintf.o: sprintf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/sprintf.o sprintf.c
+
+../obj-gnu/./stdio/sscanf.o: sscanf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/sscanf.o sscanf.c
+
+../obj-gnu/./stdio/tmpfile.o: tmpfile.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/tmpfile.o tmpfile.c
+
+../obj-gnu/./stdio/tmpnam.o: tmpnam.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/tmpnam.o tmpnam.c
+
+../obj-gnu/./stdio/ungetc.o: ungetc.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/ungetc.o ungetc.c
+
+../obj-gnu/./stdio/vfprintf.o: vfprintf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/vfprintf.o vfprintf.c
+
+../obj-gnu/./stdio/vprintf.o: vprintf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/vprintf.o vprintf.c
+
+../obj-gnu/./stdio/vscanf.o: vscanf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/vscanf.o vscanf.c
+
+../obj-gnu/./stdio/vsprintf.o: vsprintf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/vsprintf.o vsprintf.c
+
+../obj-gnu/./stdio/vsscanf.o: vsscanf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./stdio/vsscanf.o vsscanf.c
+
+
+
+
+clean::
+	rm -f ../obj-ack//./stdio/*
+	rm -f ../obj-gnu/./stdio/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/stdio/Makefile.in
===================================================================
--- /trunk/minix/lib/stdio/Makefile.in	(revision 9)
+++ /trunk/minix/lib/stdio/Makefile.in	(revision 9)
@@ -0,0 +1,60 @@
+# Makefile for lib/stdio.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
+
+LIBRARIES=libc
+
+libc_FILES=" \
+	clearerr.c \
+	data.c \
+	doprnt.c \
+	doscan.c \
+	ecvt.c \
+	fclose.c \
+	feof.c \
+	ferror.c \
+	fflush.c \
+	fgetc.c \
+	fgetpos.c \
+	fgets.c \
+	fileno.c \
+	fillbuf.c \
+	flushbuf.c \
+	fopen.c \
+	fprintf.c \
+	fputc.c \
+	fputs.c \
+	fread.c \
+	freopen.c \
+	fscanf.c \
+	fseek.c \
+	fsetpos.c \
+	ftell.c \
+	fwrite.c \
+	getc.c \
+	getchar.c \
+	gets.c \
+	icompute.c \
+	mktemp.c \
+	perror.c \
+	printf.c \
+	putc.c \
+	putchar.c \
+	puts.c \
+	remove.c \
+	rewind.c \
+	scanf.c \
+	setbuf.c \
+	setvbuf.c \
+	sprintf.c \
+	sscanf.c \
+	tmpfile.c \
+	tmpnam.c \
+	ungetc.c \
+	vfprintf.c \
+	vprintf.c \
+	vscanf.c \
+	vsprintf.c \
+	vsscanf.c"
+
+TYPE=both
Index: /trunk/minix/lib/stdio/clearerr.c
===================================================================
--- /trunk/minix/lib/stdio/clearerr.c	(revision 9)
+++ /trunk/minix/lib/stdio/clearerr.c	(revision 9)
@@ -0,0 +1,12 @@
+/*
+ * clearerr.c - clear error and end-of-file indicators of a stream
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/clearerr.c,v 1.1.1.1 2005/04/21 14:56:34 beng Exp $ */
+
+#include	<stdio.h>
+
+void
+(clearerr)(FILE *stream)
+{
+	clearerr(stream);
+}
Index: /trunk/minix/lib/stdio/data.c
===================================================================
--- /trunk/minix/lib/stdio/data.c	(revision 9)
+++ /trunk/minix/lib/stdio/data.c	(revision 9)
@@ -0,0 +1,28 @@
+/*
+ * data.c - this is the initialization for the standard streams
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/data.c,v 1.1.1.1 2005/04/21 14:56:34 beng Exp $ */
+
+#include	<stdio.h>
+
+struct __iobuf __stdin = {
+	0, 0, _IOREAD, 0,
+	(unsigned char *)NULL, (unsigned char *)NULL, 
+};
+
+struct __iobuf __stdout = {
+	0, 1, _IOWRITE, 0,
+	(unsigned char *)NULL, (unsigned char *)NULL, 
+};
+
+struct __iobuf __stderr = {
+	0, 2, _IOWRITE | _IOLBF, 0,
+	(unsigned char *)NULL, (unsigned char *)NULL, 
+};
+
+FILE *__iotab[FOPEN_MAX] = {
+	&__stdin,
+	&__stdout,
+	&__stderr,
+	0
+};
Index: /trunk/minix/lib/stdio/doprnt.c
===================================================================
--- /trunk/minix/lib/stdio/doprnt.c	(revision 9)
+++ /trunk/minix/lib/stdio/doprnt.c	(revision 9)
@@ -0,0 +1,310 @@
+/*
+ * doprnt.c - print formatted output
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/doprnt.c,v 1.1.1.1 2005/04/21 14:56:34 beng Exp $ */
+
+#include	<ctype.h>
+#include	<stdio.h>
+#include	<stdarg.h>
+#include	<string.h>
+#include	"loc_incl.h"
+
+/* gnum() is used to get the width and precision fields of a format. */
+static const char *
+gnum(register const char *f, int *ip, va_list *app)
+{
+	register int	i, c;
+
+	if (*f == '*') {
+		*ip = va_arg((*app), int);
+		f++;
+	} else {
+		i = 0;
+		while ((c = *f - '0') >= 0 && c <= 9) {
+			i = i*10 + c;
+			f++;
+		}
+		*ip = i;
+	}
+	return f;
+}
+
+#if	_EM_WSIZE == _EM_PSIZE
+#define set_pointer(flags)				/* nothing */
+#elif	_EM_LSIZE == _EM_PSIZE
+#define set_pointer(flags)	(flags |= FL_LONG)
+#else
+#error garbage pointer size
+#define set_pointer(flags)		/* compilation might continue */
+#endif
+
+/* print an ordinal number */
+static char *
+o_print(va_list *ap, int flags, char *s, char c, int precision, int is_signed)
+{
+	long signed_val;
+	unsigned long unsigned_val;
+	char *old_s = s;
+	int base;
+
+	switch (flags & (FL_SHORT | FL_LONG)) {
+	case FL_SHORT:
+		if (is_signed) {
+			signed_val = (short) va_arg(*ap, int);
+		} else {
+			unsigned_val = (unsigned short) va_arg(*ap, unsigned);
+		}
+		break;
+	case FL_LONG:
+		if (is_signed) {
+			signed_val = va_arg(*ap, long);
+		} else {
+			unsigned_val = va_arg(*ap, unsigned long);
+		}
+		break;
+	default:
+		if (is_signed) {
+			signed_val = va_arg(*ap, int);
+		} else {
+			unsigned_val = va_arg(*ap, unsigned int);
+		}
+		break;
+	}
+
+	if (is_signed) {
+		if (signed_val < 0) {
+			*s++ = '-';
+			signed_val = -signed_val;
+		} else if (flags & FL_SIGN) *s++ = '+';
+		else if (flags & FL_SPACE) *s++ = ' ';
+		unsigned_val = signed_val;
+	}
+	if ((flags & FL_ALT) && (c == 'o')) *s++ = '0';
+	if (!unsigned_val) {
+		 if (!precision)
+			return s;
+	} else if (((flags & FL_ALT) && (c == 'x' || c == 'X'))
+		    || c == 'p') {
+		*s++ = '0';
+		*s++ = (c == 'X' ? 'X' : 'x');
+	}
+
+	switch (c) {
+	case 'b':	base = 2;	break;
+	case 'o':	base = 8;	break;
+	case 'd':
+	case 'i':
+	case 'u':	base = 10;	break;
+	case 'x':
+	case 'X':
+	case 'p':	base = 16;	break;
+	}
+
+	s = _i_compute(unsigned_val, base, s, precision);
+
+	if (c == 'X')
+		while (old_s != s) {
+			*old_s = toupper(*old_s);
+			old_s++;
+		}
+
+	return s;
+}
+
+int
+_doprnt(register const char *fmt, va_list ap, FILE *stream)
+{
+	register char	*s;
+	register int	j;
+	int		i, c, width, precision, zfill, flags, between_fill;
+	int		nrchars=0;
+	const char	*oldfmt;
+	char		*s1, buf[1025];
+
+	while (c = *fmt++) {
+		if (c != '%') {
+#ifdef	CPM
+			if (c == '\n') {
+				if (putc('\r', stream) == EOF)
+					return nrchars ? -nrchars : -1;
+				nrchars++;
+			}
+#endif
+			if (putc(c, stream) == EOF)
+				return nrchars ? -nrchars : -1;
+			nrchars++;
+			continue;
+		}
+		flags = 0;
+		do {
+			switch(*fmt) {
+			case '-':	flags |= FL_LJUST;	break;
+			case '+':	flags |= FL_SIGN;	break;
+			case ' ':	flags |= FL_SPACE;	break;
+			case '#':	flags |= FL_ALT;	break;
+			case '0':	flags |= FL_ZEROFILL;	break;
+			default:	flags |= FL_NOMORE;	continue;
+			}
+			fmt++;
+		} while(!(flags & FL_NOMORE));
+
+		oldfmt = fmt;
+		fmt = gnum(fmt, &width, &ap);
+		if (fmt != oldfmt) flags |= FL_WIDTHSPEC;
+
+		if (*fmt == '.') {
+			fmt++; oldfmt = fmt;
+			fmt = gnum(fmt, &precision, &ap);
+			if (precision >= 0) flags |= FL_PRECSPEC;
+		}
+
+		if ((flags & FL_WIDTHSPEC) && width < 0) {
+			width = -width;
+			flags |= FL_LJUST;
+		}
+		if (!(flags & FL_WIDTHSPEC)) width = 0;
+
+		if (flags & FL_SIGN) flags &= ~FL_SPACE;
+
+		if (flags & FL_LJUST) flags &= ~FL_ZEROFILL;
+
+
+		s = s1 = buf;
+
+		switch (*fmt) {
+		case 'h':	flags |= FL_SHORT; fmt++; break;
+		case 'l':	flags |= FL_LONG; fmt++; break;
+		case 'L':	flags |= FL_LONGDOUBLE; fmt++; break;
+		}
+
+		switch (c = *fmt++) {
+		default:
+#ifdef	CPM
+			if (c == '\n') {
+				if (putc('\r', stream) == EOF)
+					return nrchars ? -nrchars : -1;
+				nrchars++;
+			}
+#endif
+			if (putc(c, stream) == EOF)
+				return nrchars ? -nrchars : -1;
+			nrchars++;
+			continue;
+		case 'n':
+			if (flags & FL_SHORT)
+				*va_arg(ap, short *) = (short) nrchars;
+			else if (flags & FL_LONG)
+				*va_arg(ap, long *) = (long) nrchars;
+			else
+				*va_arg(ap, int *) = (int) nrchars;
+			continue;
+		case 's':
+			s1 = va_arg(ap, char *);
+			if (s1 == NULL)
+				s1 = "(null)";
+			s = s1;
+			while (precision || !(flags & FL_PRECSPEC)) {
+				if (*s == '\0')
+					break;
+				s++;
+				precision--;
+			}
+			break;
+		case 'p':
+			set_pointer(flags);
+			/* fallthrough */
+		case 'b':
+		case 'o':
+		case 'u':
+		case 'x':
+		case 'X':
+			if (!(flags & FL_PRECSPEC)) precision = 1;
+			else if (c != 'p') flags &= ~FL_ZEROFILL;
+			s = o_print(&ap, flags, s, c, precision, 0);
+			break;
+		case 'd':
+		case 'i':
+			flags |= FL_SIGNEDCONV;
+			if (!(flags & FL_PRECSPEC)) precision = 1;
+			else flags &= ~FL_ZEROFILL;
+			s = o_print(&ap, flags, s, c, precision, 1);
+			break;
+		case 'c':
+			*s++ = va_arg(ap, int);
+			break;
+#ifndef NOFLOAT
+		case 'G':
+		case 'g':
+			if ((flags & FL_PRECSPEC) && (precision == 0))
+				precision = 1;
+		case 'f':
+		case 'E':
+		case 'e':
+			if (!(flags & FL_PRECSPEC)) 
+				precision = 6;
+
+			if (precision >= sizeof(buf))
+				precision = sizeof(buf) - 1;
+
+			flags |= FL_SIGNEDCONV;
+			s = _f_print(&ap, flags, s, c, precision);
+			break;
+#endif	/* NOFLOAT */
+		case 'r':
+			ap = va_arg(ap, va_list);
+			fmt = va_arg(ap, char *);
+			continue;
+		}
+		zfill = ' ';
+		if (flags & FL_ZEROFILL) zfill = '0';
+		j = s - s1;
+
+		/* between_fill is true under the following conditions:
+		 * 1- the fill character is '0'
+		 * and
+		 * 2a- the number is of the form 0x... or 0X...
+		 * or
+		 * 2b- the number contains a sign or space
+		 */
+		between_fill = 0;
+		if ((flags & FL_ZEROFILL)
+		    && (((c == 'x' || c == 'X') && (flags & FL_ALT))
+			|| (c == 'p')
+			|| ((flags & FL_SIGNEDCONV)
+			    && ( *s1 == '+' || *s1 == '-' || *s1 == ' '))))
+			between_fill++;
+
+		if ((i = width - j) > 0)
+			if (!(flags & FL_LJUST)) {	/* right justify */
+				nrchars += i;
+				if (between_fill) {
+				    if (flags & FL_SIGNEDCONV) {
+					j--; nrchars++;
+					if (putc(*s1++, stream) == EOF)
+						return nrchars ? -nrchars : -1;
+				    } else {
+					j -= 2; nrchars += 2;
+					if ((putc(*s1++, stream) == EOF)
+					    || (putc(*s1++, stream) == EOF))
+						return nrchars ? -nrchars : -1;
+				    }
+				}
+				do {
+					if (putc(zfill, stream) == EOF)
+						return nrchars ? -nrchars : -1;
+				} while (--i);
+			}
+
+		nrchars += j;
+		while (--j >= 0) {
+			if (putc(*s1++, stream) == EOF)
+				return nrchars ? -nrchars : -1;
+		}
+
+		if (i > 0) nrchars += i;
+		while (--i >= 0)
+			if (putc(zfill, stream) == EOF)
+				return nrchars ? -nrchars : -1;
+	}
+	return nrchars;
+}
Index: /trunk/minix/lib/stdio/doscan.c
===================================================================
--- /trunk/minix/lib/stdio/doscan.c	(revision 9)
+++ /trunk/minix/lib/stdio/doscan.c	(revision 9)
@@ -0,0 +1,449 @@
+/*
+ * doscan.c - scan formatted input
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/doscan.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	<ctype.h>
+#include	<stdarg.h>
+#include	"loc_incl.h"
+
+#if	_EM_WSIZE == _EM_PSIZE
+#define set_pointer(flags)				/* nothing */
+#elif	_EM_LSIZE == _EM_PSIZE
+#define set_pointer(flags)	(flags |= FL_LONG)
+#else
+#error garbage pointer size
+#define set_pointer(flags)		/* compilation might continue */
+#endif
+
+#define	NUMLEN	512
+#define	NR_CHARS	256
+
+static char	Xtable[NR_CHARS];
+static char	inp_buf[NUMLEN];
+
+/* Collect a number of characters which constitite an ordinal number.
+ * When the type is 'i', the base can be 8, 10, or 16, depending on the
+ * first 1 or 2 characters. This means that the base must be adjusted
+ * according to the format of the number. At the end of the function, base
+ * is then set to 0, so strtol() will get the right argument.
+ */
+static char *
+o_collect(register int c, register FILE *stream, char type,
+			unsigned int width, int *basep)
+{
+	register char *bufp = inp_buf;
+	register int base;
+
+	switch (type) {
+	case 'i':	/* i means octal, decimal or hexadecimal */
+	case 'p':
+	case 'x':
+	case 'X':	base = 16;	break;
+	case 'd':
+	case 'u':	base = 10;	break;
+	case 'o':	base = 8;	break;
+	case 'b':	base = 2;	break;
+	}
+
+	if (c == '-' || c == '+') {
+		*bufp++ = c;
+		if (--width)
+		    c = getc(stream);
+	}
+
+	if (width && c == '0' && base == 16) {
+		*bufp++ = c;
+		if (--width)
+			c = getc(stream);
+		if (c != 'x' && c != 'X') {
+			if (type == 'i') base = 8;
+		}
+		else if (width) {
+			*bufp++ = c;
+			if (--width)
+				c = getc(stream);
+		}
+	}
+	else if (type == 'i') base = 10;
+
+	while (width) {
+		if (((base == 10) && isdigit(c))
+		    || ((base == 16) && isxdigit(c))
+		    || ((base == 8) && isdigit(c) && (c < '8'))
+		    || ((base == 2) && isdigit(c) && (c < '2'))) {
+			*bufp++ = c;
+			if (--width)
+				c = getc(stream);
+		}
+		else break;
+	}
+
+	if (width && c != EOF) ungetc(c, stream);
+	if (type == 'i') base = 0;
+	*basep = base;
+	*bufp = '\0';
+	return bufp - 1;
+}
+
+#ifndef	NOFLOAT
+/* The function f_collect() reads a string that has the format of a
+ * floating-point number. The function returns as soon as a format-error
+ * is encountered, leaving the offending character in the input. This means
+ * that 1.el leaves the 'l' in the input queue. Since all detection of
+ * format errors is done here, _doscan() doesn't call strtod() when it's
+ * not necessary, although the use of the width field can cause incomplete
+ * numbers to be passed to strtod(). (e.g. 1.3e+)
+ */
+static char *
+f_collect(register int c, register FILE *stream, register unsigned int width)
+{
+	register char *bufp = inp_buf;
+	int digit_seen = 0;
+
+	if (c == '-' || c == '+') {
+		*bufp++ = c;
+		if (--width)
+			c = getc(stream);
+	}
+
+	while (width && isdigit(c)) {
+		digit_seen++;
+		*bufp++ = c;
+		if (--width)
+			c = getc(stream);
+	}
+	if (width && c == '.') {
+		*bufp++ = c;
+		if(--width)
+			c = getc(stream);
+		while (width && isdigit(c)) {
+			digit_seen++;
+			*bufp++ = c;
+			if (--width)
+				c = getc(stream);
+		}
+	}
+
+	if (!digit_seen) {
+		if (width && c != EOF) ungetc(c, stream);
+		return inp_buf - 1;
+	}
+	else digit_seen = 0;
+
+	if (width && (c == 'e' || c == 'E')) {
+		*bufp++ = c;
+		if (--width)
+			c = getc(stream);
+		if (width && (c == '+' || c == '-')) {
+			*bufp++ = c;
+			if (--width)
+				c = getc(stream);
+		}
+		while (width && isdigit(c)) {
+			digit_seen++;
+			*bufp++ = c;
+			if (--width)
+				c = getc(stream);
+		}
+		if (!digit_seen) {
+			if (width && c != EOF) ungetc(c,stream);
+			return inp_buf - 1;
+		}
+	}
+
+	if (width && c != EOF) ungetc(c, stream);
+	*bufp = '\0';
+	return bufp - 1;
+}
+#endif	/* NOFLOAT */
+
+
+/*
+ * the routine that does the scanning 
+ */
+
+int
+_doscan(register FILE *stream, const char *format, va_list ap)
+{
+	int		done = 0;	/* number of items done */
+	int		nrchars = 0;	/* number of characters read */
+	int		conv = 0;	/* # of conversions */
+	int		base;		/* conversion base */
+	unsigned long	val;		/* an integer value */
+	register char	*str;		/* temporary pointer */
+	char		*tmp_string;	/* ditto */
+	unsigned	width = 0;	/* width of field */
+	int		flags;		/* some flags */
+	int		reverse;	/* reverse the checking in [...] */
+	int		kind;
+	register int	ic = EOF;	/* the input character */
+#ifndef	NOFLOAT
+	long double	ld_val;
+#endif
+
+	if (!*format) return 0;
+
+	while (1) {
+		if (isspace(*format)) {
+			while (isspace(*format))
+				format++;	/* skip whitespace */
+			ic = getc(stream);
+			nrchars++;
+			while (isspace (ic)) {
+				ic = getc(stream);
+				nrchars++;
+			}
+			if (ic != EOF) ungetc(ic,stream);
+			nrchars--;
+		}
+		if (!*format) break;	/* end of format */
+
+		if (*format != '%') {
+			ic = getc(stream);
+			nrchars++;
+			if (ic != *format++) break;	/* error */
+			continue;
+		}
+		format++;
+		if (*format == '%') {
+			ic = getc(stream);
+			nrchars++;
+			if (ic == '%') {
+				format++;
+				continue;
+			}
+			else break;
+		}
+		flags = 0;
+		if (*format == '*') {
+			format++;
+			flags |= FL_NOASSIGN;
+		}
+		if (isdigit (*format)) {
+			flags |= FL_WIDTHSPEC;
+			for (width = 0; isdigit (*format);)
+				width = width * 10 + *format++ - '0';
+		}
+
+		switch (*format) {
+		case 'h': flags |= FL_SHORT; format++; break;
+		case 'l': flags |= FL_LONG; format++; break;
+		case 'L': flags |= FL_LONGDOUBLE; format++; break;
+		}
+		kind = *format;
+		if ((kind != 'c') && (kind != '[') && (kind != 'n')) {
+			do {
+				ic = getc(stream);
+				nrchars++;
+			} while (isspace(ic));
+			if (ic == EOF) break;		/* outer while */
+		} else if (kind != 'n') {		/* %c or %[ */
+			ic = getc(stream);
+			if (ic == EOF) break;		/* outer while */
+			nrchars++;
+		}
+		switch (kind) {
+		default:
+			/* not recognized, like %q */
+			return conv || (ic != EOF) ? done : EOF;
+			break;
+		case 'n':
+			if (!(flags & FL_NOASSIGN)) {	/* silly, though */
+				if (flags & FL_SHORT)
+					*va_arg(ap, short *) = (short) nrchars;
+				else if (flags & FL_LONG)
+					*va_arg(ap, long *) = (long) nrchars;
+				else
+					*va_arg(ap, int *) = (int) nrchars;
+			}
+			break;
+		case 'p':		/* pointer */
+			set_pointer(flags);
+			/* fallthrough */
+		case 'b':		/* binary */
+		case 'd':		/* decimal */
+		case 'i':		/* general integer */
+		case 'o':		/* octal */
+		case 'u':		/* unsigned */
+		case 'x':		/* hexadecimal */
+		case 'X':		/* ditto */
+			if (!(flags & FL_WIDTHSPEC) || width > NUMLEN)
+				width = NUMLEN;
+			if (!width) return done;
+
+			str = o_collect(ic, stream, kind, width, &base);
+			if (str < inp_buf
+			    || (str == inp_buf
+				    && (*str == '-'
+					|| *str == '+'))) return done;
+
+			/*
+			 * Although the length of the number is str-inp_buf+1
+			 * we don't add the 1 since we counted it already
+			 */
+			nrchars += str - inp_buf;
+
+			if (!(flags & FL_NOASSIGN)) {
+				if (kind == 'd' || kind == 'i')
+				    val = strtol(inp_buf, &tmp_string, base);
+				else
+				    val = strtoul(inp_buf, &tmp_string, base);
+				if (flags & FL_LONG)
+					*va_arg(ap, unsigned long *) = (unsigned long) val;
+				else if (flags & FL_SHORT)
+					*va_arg(ap, unsigned short *) = (unsigned short) val;
+				else
+					*va_arg(ap, unsigned *) = (unsigned) val;
+			}
+			break;
+		case 'c':
+			if (!(flags & FL_WIDTHSPEC))
+				width = 1;
+			if (!(flags & FL_NOASSIGN))
+				str = va_arg(ap, char *);
+			if (!width) return done;
+
+			while (width && ic != EOF) {
+				if (!(flags & FL_NOASSIGN))
+					*str++ = (char) ic;
+				if (--width) {
+					ic = getc(stream);
+					nrchars++;
+				}
+			}
+
+			if (width) {
+				if (ic != EOF) ungetc(ic,stream);
+				nrchars--;
+			}
+			break;
+		case 's':
+			if (!(flags & FL_WIDTHSPEC))
+				width = 0xffff;
+			if (!(flags & FL_NOASSIGN))
+				str = va_arg(ap, char *);
+			if (!width) return done;
+
+			while (width && ic != EOF && !isspace(ic)) {
+				if (!(flags & FL_NOASSIGN))
+					*str++ = (char) ic;
+				if (--width) {
+					ic = getc(stream);
+					nrchars++;
+				}
+			}
+			/* terminate the string */
+			if (!(flags & FL_NOASSIGN))
+				*str = '\0';	
+			if (width) {
+				if (ic != EOF) ungetc(ic,stream);
+				nrchars--;
+			}
+			break;
+		case '[':
+			if (!(flags & FL_WIDTHSPEC))
+				width = 0xffff;
+			if (!width) return done;
+
+			if ( *++format == '^' ) {
+				reverse = 1;
+				format++;
+			} else
+				reverse = 0;
+
+			for (str = Xtable; str < &Xtable[NR_CHARS]
+							; str++)
+				*str = 0;
+
+			if (*format == ']') Xtable[*format++] = 1;
+
+			while (*format && *format != ']') {
+				Xtable[*format++] = 1;
+				if (*format == '-') {
+					format++;
+					if (*format
+					    && *format != ']'
+					    && *(format) >= *(format -2)) {
+						int c;
+
+						for( c = *(format -2) + 1
+						    ; c <= *format ; c++)
+							Xtable[c] = 1;
+						format++;
+					}
+					else Xtable['-'] = 1;
+				}
+			}
+			if (!*format) return done;
+			
+			if (!(Xtable[ic] ^ reverse)) {
+			/* MAT 8/9/96 no match must return character */
+				ungetc(ic, stream);
+				return done;
+			}
+
+			if (!(flags & FL_NOASSIGN))
+				str = va_arg(ap, char *);
+
+			do {
+				if (!(flags & FL_NOASSIGN))
+					*str++ = (char) ic;
+				if (--width) {
+					ic = getc(stream);
+					nrchars++;
+				}
+			} while (width && ic != EOF && (Xtable[ic] ^ reverse));
+
+			if (width) {
+				if (ic != EOF) ungetc(ic, stream);
+				nrchars--;
+			}
+			if (!(flags & FL_NOASSIGN)) {	/* terminate string */
+				*str = '\0';	
+			}
+			break;
+#ifndef	NOFLOAT
+		case 'e':
+		case 'E':
+		case 'f':
+		case 'g':
+		case 'G':
+			if (!(flags & FL_WIDTHSPEC) || width > NUMLEN)
+				width = NUMLEN;
+
+			if (!width) return done;
+			str = f_collect(ic, stream, width);
+
+			if (str < inp_buf
+			    || (str == inp_buf
+				&& (*str == '-'
+				    || *str == '+'))) return done;
+
+			/*
+			 * Although the length of the number is str-inp_buf+1
+			 * we don't add the 1 since we counted it already
+			 */
+			nrchars += str - inp_buf;
+
+			if (!(flags & FL_NOASSIGN)) {
+				ld_val = strtod(inp_buf, &tmp_string);
+				if (flags & FL_LONGDOUBLE)
+					*va_arg(ap, long double *) = (long double) ld_val;
+				else
+				    if (flags & FL_LONG)
+					*va_arg(ap, double *) = (double) ld_val;
+				else
+					*va_arg(ap, float *) = (float) ld_val;
+			}
+			break;
+#endif
+		}		/* end switch */
+		conv++;
+		if (!(flags & FL_NOASSIGN) && kind != 'n') done++;
+		format++;
+	}
+	return conv || (ic != EOF) ? done : EOF;
+}
Index: /trunk/minix/lib/stdio/ecvt.c
===================================================================
--- /trunk/minix/lib/stdio/ecvt.c	(revision 9)
+++ /trunk/minix/lib/stdio/ecvt.c	(revision 9)
@@ -0,0 +1,31 @@
+/* $Header: /cvsup/minix/src/lib/stdio/ecvt.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#ifndef NOFLOAT
+
+#include	"../ansi/ext_fmt.h"
+void _dbl_ext_cvt(double value, struct EXTEND *e);
+char *_ext_str_cvt(struct EXTEND *e, int ndigit, int *decpt, int * sign, int ecvtflag);
+
+static char *
+cvt(long double value, int ndigit, int *decpt, int *sign, int ecvtflag)
+{
+	struct EXTEND e;
+
+	_dbl_ext_cvt(value, &e);
+	return _ext_str_cvt(&e, ndigit, decpt, sign, ecvtflag);
+}
+
+char *
+_ecvt(long double value, int ndigit, int *decpt, int *sign)
+{
+
+	return cvt(value, ndigit, decpt, sign, 1);
+}
+
+char *
+_fcvt(long double value, int ndigit, int *decpt, int *sign)
+{
+	return cvt(value, ndigit, decpt, sign, 0);
+}
+
+#endif	/* NOFLOAT */
Index: /trunk/minix/lib/stdio/fclose.c
===================================================================
--- /trunk/minix/lib/stdio/fclose.c	(revision 9)
+++ /trunk/minix/lib/stdio/fclose.c	(revision 9)
@@ -0,0 +1,31 @@
+/*
+ * fclose.c - flush a stream and close the file
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fclose.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	"loc_incl.h"
+
+int _close(int d);
+
+int
+fclose(FILE *fp)
+{
+	register int i, retval = 0;
+
+	for (i=0; i<FOPEN_MAX; i++)
+		if (fp == __iotab[i]) {
+			__iotab[i] = 0;
+			break;
+		}
+	if (i >= FOPEN_MAX)
+		return EOF;
+	if (fflush(fp)) retval = EOF;
+	if (_close(fileno(fp))) retval = EOF;
+	if ( io_testflag(fp,_IOMYBUF) && fp->_buf )
+		free((void *)fp->_buf);
+	if (fp != stdin && fp != stdout && fp != stderr)
+		free((void *)fp);
+	return retval;
+}
Index: /trunk/minix/lib/stdio/feof.c
===================================================================
--- /trunk/minix/lib/stdio/feof.c	(revision 9)
+++ /trunk/minix/lib/stdio/feof.c	(revision 9)
@@ -0,0 +1,12 @@
+/*
+ * feof.c - test if eof on a stream occurred
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/feof.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+int
+(feof)(FILE *stream)
+{
+	return feof(stream);
+}
Index: /trunk/minix/lib/stdio/ferror.c
===================================================================
--- /trunk/minix/lib/stdio/ferror.c	(revision 9)
+++ /trunk/minix/lib/stdio/ferror.c	(revision 9)
@@ -0,0 +1,12 @@
+/*
+ * ferror .c - test if an error on a stream occurred
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/ferror.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+int
+(ferror)(FILE *stream)
+{
+	return ferror(stream);
+}
Index: /trunk/minix/lib/stdio/fflush.c
===================================================================
--- /trunk/minix/lib/stdio/fflush.c	(revision 9)
+++ /trunk/minix/lib/stdio/fflush.c	(revision 9)
@@ -0,0 +1,86 @@
+/*
+ * fflush.c - flush stream(s)
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fflush.c,v 1.3 2006/02/02 16:59:07 beng Exp $ */
+
+#include	<sys/types.h>
+#include	<stdio.h>
+#include	<errno.h>
+#include	"loc_incl.h"
+
+ssize_t _write(int d, const char *buf, size_t nbytes);
+off_t _lseek(int fildes, off_t offset, int whence);
+
+int
+fflush(FILE *stream)
+{
+	int count, c1, i, retval = 0;
+
+	if (!stream) {
+	    for(i= 0; i < FOPEN_MAX; i++)
+		if (__iotab[i] && fflush(__iotab[i]))
+			retval = EOF;
+	    return retval;
+	}
+
+	if (!stream->_buf
+	    || (!io_testflag(stream, _IOREADING)
+		&& !io_testflag(stream, _IOWRITING)))
+		return 0;
+	if (io_testflag(stream, _IOREADING)) {
+		/* (void) fseek(stream, 0L, SEEK_CUR); */
+		int adjust = 0;
+		if (io_testflag(stream, _IOFIFO)) {
+			/* Can't seek in a pipe. */
+			return 0;
+		}
+		if (stream->_buf && !io_testflag(stream,_IONBF))
+			adjust = -stream->_count;
+		stream->_count = 0;
+		if (_lseek(fileno(stream), (off_t) adjust, SEEK_CUR) == -1 &&
+		  errno != ESPIPE) {
+			stream->_flags |= _IOERR;
+			return EOF;
+		}
+		errno = 0;
+		if (io_testflag(stream, _IOWRITE))
+			stream->_flags &= ~(_IOREADING | _IOWRITING);
+		stream->_ptr = stream->_buf;
+		return 0;
+	} else if (io_testflag(stream, _IONBF)) return 0;
+
+	if (io_testflag(stream, _IOREAD))		/* "a" or "+" mode */
+		stream->_flags &= ~_IOWRITING;
+
+	count = stream->_ptr - stream->_buf;
+	stream->_ptr = stream->_buf;
+
+	if ( count <= 0 )
+		return 0;
+
+	if (io_testflag(stream, _IOAPPEND)) {
+		if (_lseek(fileno(stream), 0L, SEEK_END) == -1) {
+			stream->_flags |= _IOERR;
+			return EOF;
+		}
+	}
+	c1 = _write(stream->_fd, (char *)stream->_buf, count);
+
+	stream->_count = 0;
+
+	if ( count == c1 )
+		return 0;
+
+	stream->_flags |= _IOERR;
+	return EOF; 
+}
+
+void
+__cleanup(void)
+{
+	register int i;
+
+	for(i= 0; i < FOPEN_MAX; i++)
+		if (__iotab[i] && io_testflag(__iotab[i], _IOWRITING))
+			(void) fflush(__iotab[i]);
+}
Index: /trunk/minix/lib/stdio/fgetc.c
===================================================================
--- /trunk/minix/lib/stdio/fgetc.c	(revision 9)
+++ /trunk/minix/lib/stdio/fgetc.c	(revision 9)
@@ -0,0 +1,12 @@
+/*
+ * fgetc - get an unsigned character and return it as an int
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fgetc.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+int
+fgetc(FILE *stream)
+{
+	return getc(stream);
+}
Index: /trunk/minix/lib/stdio/fgetpos.c
===================================================================
--- /trunk/minix/lib/stdio/fgetpos.c	(revision 9)
+++ /trunk/minix/lib/stdio/fgetpos.c	(revision 9)
@@ -0,0 +1,14 @@
+/*
+ * fgetpos.c - get the position in the file
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fgetpos.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+int
+fgetpos(FILE *stream, fpos_t *pos)
+{
+	*pos = ftell(stream);
+	if (*pos == -1) return -1;
+	return 0;
+}
Index: /trunk/minix/lib/stdio/fgets.c
===================================================================
--- /trunk/minix/lib/stdio/fgets.c	(revision 9)
+++ /trunk/minix/lib/stdio/fgets.c	(revision 9)
@@ -0,0 +1,27 @@
+/*
+ * fgets.c - get a string from a file
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fgets.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+char *
+fgets(char *s, register int n, register FILE *stream)
+{
+	register int ch;
+	register char *ptr;
+
+	ptr = s;
+	while (--n > 0 && (ch = getc(stream)) != EOF) {
+		*ptr++ = ch;
+		if ( ch == '\n')
+			break;
+	}
+	if (ch == EOF) {
+		if (feof(stream)) {
+			if (ptr == s) return NULL;
+		} else return NULL;
+	}
+	*ptr = '\0';
+	return s;
+}
Index: /trunk/minix/lib/stdio/fileno.c
===================================================================
--- /trunk/minix/lib/stdio/fileno.c	(revision 9)
+++ /trunk/minix/lib/stdio/fileno.c	(revision 9)
@@ -0,0 +1,12 @@
+/*
+ * fileno .c - map a stream to a file descriptor
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fileno.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+int
+(fileno)(FILE *stream)
+{
+	return stream->_fd;
+}
Index: /trunk/minix/lib/stdio/fillbuf.c
===================================================================
--- /trunk/minix/lib/stdio/fillbuf.c	(revision 9)
+++ /trunk/minix/lib/stdio/fillbuf.c	(revision 9)
@@ -0,0 +1,69 @@
+/*
+ * fillbuf.c - fill a buffer
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fillbuf.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#if	defined(_POSIX_SOURCE)
+#include	<sys/types.h>
+#endif
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	"loc_incl.h"
+
+ssize_t _read(ssize_t d, char *buf, size_t nbytes);
+
+int
+__fillbuf(register FILE *stream)
+{
+	static unsigned char ch[FOPEN_MAX];
+	register int i;
+
+	stream->_count = 0;
+	if (fileno(stream) < 0) return EOF;
+	if (io_testflag(stream, (_IOEOF | _IOERR ))) return EOF; 
+	if (!io_testflag(stream, _IOREAD))
+	     { stream->_flags |= _IOERR; return EOF; }
+	if (io_testflag(stream, _IOWRITING))
+	     { stream->_flags |= _IOERR; return EOF; }
+
+	if (!io_testflag(stream, _IOREADING))
+		stream->_flags |= _IOREADING;
+	
+	if (!io_testflag(stream, _IONBF) && !stream->_buf) {
+		stream->_buf = (unsigned char *) malloc(BUFSIZ);
+		if (!stream->_buf) {
+			stream->_flags |= _IONBF;
+		}
+		else {
+			stream->_flags |= _IOMYBUF;
+			stream->_bufsiz = BUFSIZ;
+		}
+	}
+
+	/* flush line-buffered output when filling an input buffer */
+	for (i = 0; i < FOPEN_MAX; i++) {
+		if (__iotab[i] && io_testflag(__iotab[i], _IOLBF))
+			if (io_testflag(__iotab[i], _IOWRITING))
+				(void) fflush(__iotab[i]);
+	}
+
+	if (!stream->_buf) {
+		stream->_buf = &ch[fileno(stream)];
+		stream->_bufsiz = 1;
+	}
+	stream->_ptr = stream->_buf;
+	stream->_count = _read(stream->_fd, (char *)stream->_buf, stream->_bufsiz);
+
+	if (stream->_count <= 0){
+		if (stream->_count == 0) {
+			stream->_flags |= _IOEOF;
+		}
+		else 
+			stream->_flags |= _IOERR;
+
+		return EOF;
+	}
+	stream->_count--;
+
+	return *stream->_ptr++;
+}
Index: /trunk/minix/lib/stdio/flushbuf.c
===================================================================
--- /trunk/minix/lib/stdio/flushbuf.c	(revision 9)
+++ /trunk/minix/lib/stdio/flushbuf.c	(revision 9)
@@ -0,0 +1,127 @@
+/*
+ * flushbuf.c - flush a buffer
+ */
+/* $Id: flushbuf.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	"loc_incl.h"
+
+#include	<sys/types.h>
+
+off_t _lseek(int fildes, off_t offset, int whence);
+ssize_t _write(int d, const char *buf, int nbytes);
+int _isatty(int d);
+extern void (*_clean)(void);
+
+static int
+do_write(int d, char *buf, int nbytes)
+{
+	int c;
+
+	/* POSIX actually allows write() to return a positive value less
+	   than nbytes, so loop ...
+	*/
+	while ((c = _write(d, buf, nbytes)) > 0 && c < nbytes) {
+		nbytes -= c;
+		buf += c;
+	}
+	return c > 0;
+}
+
+int
+__flushbuf(int c, FILE * stream)
+{
+	_clean = __cleanup;
+	if (fileno(stream) < 0) return (unsigned char) c;
+	if (!io_testflag(stream, _IOWRITE)) return EOF;
+	if (io_testflag(stream, _IOREADING) && !feof(stream)) return EOF;
+
+	stream->_flags &= ~_IOREADING;
+	stream->_flags |= _IOWRITING;
+	if (!io_testflag(stream, _IONBF)) {
+		if (!stream->_buf) {
+			if (stream == stdout && _isatty(fileno(stdout))) {
+				if (!(stream->_buf =
+					    (unsigned char *) malloc(BUFSIZ))) {
+					stream->_flags |= _IONBF;
+				} else {
+					stream->_flags |= _IOLBF|_IOMYBUF;
+					stream->_bufsiz = BUFSIZ;
+					stream->_count = -1;
+				}
+			} else {
+				if (!(stream->_buf =
+					    (unsigned char *) malloc(BUFSIZ))) {
+					stream->_flags |= _IONBF;
+				} else {
+					stream->_flags |= _IOMYBUF;
+					stream->_bufsiz = BUFSIZ;
+					if (!io_testflag(stream, _IOLBF))
+						stream->_count = BUFSIZ - 1;
+					else	stream->_count = -1;
+				}
+			}
+			stream->_ptr = stream->_buf;
+		}
+	}
+
+	if (io_testflag(stream, _IONBF)) {
+		char c1 = c;
+
+		stream->_count = 0;
+		if (io_testflag(stream, _IOAPPEND)) {
+			if (_lseek(fileno(stream), 0L, SEEK_END) == -1) {
+				stream->_flags |= _IOERR;
+				return EOF;
+			}
+		}
+		if (_write(fileno(stream), &c1, 1) != 1) {
+			stream->_flags |= _IOERR;
+			return EOF;
+		}
+		return (unsigned char) c;
+	} else if (io_testflag(stream, _IOLBF)) {
+		*stream->_ptr++ = c;
+		/* stream->_count has been updated in putc macro. */
+		if (c == '\n' || stream->_count == -stream->_bufsiz) {
+			int count = -stream->_count;
+
+			stream->_ptr  = stream->_buf;
+			stream->_count = 0;
+
+			if (io_testflag(stream, _IOAPPEND)) {
+				if (_lseek(fileno(stream), 0L, SEEK_END) == -1) {
+					stream->_flags |= _IOERR;
+					return EOF;
+				}
+			}
+			if (! do_write(fileno(stream), (char *)stream->_buf,
+					count)) {
+				stream->_flags |= _IOERR;
+				return EOF;
+			}
+		}
+	} else {
+		int count = stream->_ptr - stream->_buf;
+
+		stream->_count = stream->_bufsiz - 1;
+		stream->_ptr = stream->_buf + 1;
+
+		if (count > 0) {
+			if (io_testflag(stream, _IOAPPEND)) {
+				if (_lseek(fileno(stream), 0L, SEEK_END) == -1) {
+					stream->_flags |= _IOERR;
+					return EOF;
+				}
+			}
+			if (! do_write(fileno(stream), (char *)stream->_buf, count)) {
+				*(stream->_buf) = c;
+				stream->_flags |= _IOERR;
+				return EOF;
+			}
+		}
+		*(stream->_buf) = c;
+	}
+	return (unsigned char) c;
+}
Index: /trunk/minix/lib/stdio/fopen.c
===================================================================
--- /trunk/minix/lib/stdio/fopen.c	(revision 9)
+++ /trunk/minix/lib/stdio/fopen.c	(revision 9)
@@ -0,0 +1,129 @@
+/*
+ * fopen.c - open a stream
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fopen.c,v 1.4 2006/02/02 16:59:07 beng Exp $ */
+
+#if	defined(_POSIX_SOURCE)
+#include	<sys/types.h>
+#endif
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	"loc_incl.h"
+#include	<sys/stat.h>
+
+#define	PMODE		0666
+
+/* The next 3 defines are true in all UNIX systems known to me.
+ */
+#define	O_RDONLY	0
+#define	O_WRONLY	1
+#define	O_RDWR		2
+
+/* Since the O_CREAT flag is not available on all systems, we can't get it
+ * from the standard library. Furthermore, even if we know that <fcntl.h>
+ * contains such a flag, it's not sure whether it can be used, since we
+ * might be cross-compiling for another system, which may use an entirely
+ * different value for O_CREAT (or not support such a mode). The safest
+ * thing is to just use the Version 7 semantics for open, and use creat()
+ * whenever necessary.
+ *
+ * Another problem is O_APPEND, for which the same holds. When "a"
+ * open-mode is used, an lseek() to the end is done before every write()
+ * system-call.
+ *
+ * The O_CREAT, O_TRUNC and O_APPEND given here, are only for convenience.
+ * They are not passed to open(), so the values don't have to match a value
+ * from the real world. It is enough when they are unique.
+ */
+#define	O_CREAT		0x010
+#define	O_TRUNC		0x020
+#define	O_APPEND	0x040
+
+int _open(const char *path, int flags);
+int _creat(const char *path, _mnx_Mode_t mode);
+int _close(int d);
+
+FILE *
+fopen(const char *name, const char *mode)
+{
+	register int i;
+	int rwmode = 0, rwflags = 0;
+	FILE *stream;
+	struct stat st;
+	int fd, flags = 0;
+
+	for (i = 0; __iotab[i] != 0 ; i++) 
+		if ( i >= FOPEN_MAX-1 )
+			return (FILE *)NULL;
+
+	switch(*mode++) {
+	case 'r':
+		flags |= _IOREAD | _IOREADING;	
+		rwmode = O_RDONLY;
+		break;
+	case 'w':
+		flags |= _IOWRITE | _IOWRITING;
+		rwmode = O_WRONLY;
+		rwflags = O_CREAT | O_TRUNC;
+		break;
+	case 'a': 
+		flags |= _IOWRITE | _IOWRITING | _IOAPPEND;
+		rwmode = O_WRONLY;
+		rwflags |= O_APPEND | O_CREAT;
+		break;         
+	default:
+		return (FILE *)NULL;
+	}
+
+	while (*mode) {
+		switch(*mode++) {
+		case 'b':
+			continue;
+		case '+':
+			rwmode = O_RDWR;
+			flags |= _IOREAD | _IOWRITE;
+			continue;
+		/* The sequence may be followed by additional characters */
+		default:
+			break;
+		}
+		break;
+	}
+
+	/* Perform a creat() when the file should be truncated or when
+	 * the file is opened for writing and the open() failed.
+	 */
+	if ((rwflags & O_TRUNC)
+	    || (((fd = _open(name, rwmode)) < 0)
+		    && (rwflags & O_CREAT))) {
+		if (((fd = _creat(name, PMODE)) > 0) && flags  | _IOREAD) {
+			(void) _close(fd);
+			fd = _open(name, rwmode);
+		}
+			
+	}
+
+	if (fd < 0) return (FILE *)NULL;
+
+	if ( fstat( fd, &st ) < 0 ) {
+		_close(fd);
+		return (FILE *)NULL;
+	}
+	
+	if ( S_ISFIFO(st.st_mode) ) flags |= _IOFIFO;
+	
+	if (( stream = (FILE *) malloc(sizeof(FILE))) == NULL ) {
+		_close(fd);
+		return (FILE *)NULL;
+	}
+
+	if ((flags & (_IOREAD | _IOWRITE))  == (_IOREAD | _IOWRITE))
+		flags &= ~(_IOREADING | _IOWRITING);
+
+	stream->_count = 0;
+	stream->_fd = fd;
+	stream->_flags = flags;
+	stream->_buf = NULL;
+	__iotab[i] = stream;
+	return stream;
+}
Index: /trunk/minix/lib/stdio/fprintf.c
===================================================================
--- /trunk/minix/lib/stdio/fprintf.c	(revision 9)
+++ /trunk/minix/lib/stdio/fprintf.c	(revision 9)
@@ -0,0 +1,23 @@
+/*
+ * fprintf - write output on a stream
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fprintf.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+#include	<stdarg.h>
+#include	"loc_incl.h"
+
+int
+fprintf(FILE *stream, const char *format, ...)
+{
+	va_list ap;
+	int retval;
+	
+	va_start(ap, format);
+
+	retval = _doprnt (format, ap, stream);
+
+	va_end(ap);
+
+	return retval;
+}
Index: /trunk/minix/lib/stdio/fputc.c
===================================================================
--- /trunk/minix/lib/stdio/fputc.c	(revision 9)
+++ /trunk/minix/lib/stdio/fputc.c	(revision 9)
@@ -0,0 +1,12 @@
+/*
+ * fputc.c - print an unsigned character
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fputc.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+int
+fputc(int c, FILE *stream)
+{
+	return putc(c, stream);
+}
Index: /trunk/minix/lib/stdio/fputs.c
===================================================================
--- /trunk/minix/lib/stdio/fputs.c	(revision 9)
+++ /trunk/minix/lib/stdio/fputs.c	(revision 9)
@@ -0,0 +1,18 @@
+/*
+ * fputs - print a string
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fputs.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+int
+fputs(register const char *s, register FILE *stream)
+{
+	register int i = 0;
+
+	while (*s) 
+		if (putc(*s++, stream) == EOF) return EOF;
+		else i++;
+
+	return i;
+}
Index: /trunk/minix/lib/stdio/fread.c
===================================================================
--- /trunk/minix/lib/stdio/fread.c	(revision 9)
+++ /trunk/minix/lib/stdio/fread.c	(revision 9)
@@ -0,0 +1,29 @@
+/*
+ * fread.c - read a number of members into an array
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fread.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+size_t
+fread(void *ptr, size_t size, size_t nmemb, register FILE *stream)
+{
+	register char *cp = ptr;
+	register int c;
+	size_t ndone = 0;
+	register size_t s;
+
+	if (size)
+		while ( ndone < nmemb ) {
+			s = size;
+			do {
+				if ((c = getc(stream)) != EOF)
+					*cp++ = c;
+				else
+					return ndone;
+			} while (--s);
+			ndone++;
+		}
+
+	return ndone;
+}
Index: /trunk/minix/lib/stdio/freopen.c
===================================================================
--- /trunk/minix/lib/stdio/freopen.c	(revision 9)
+++ /trunk/minix/lib/stdio/freopen.c	(revision 9)
@@ -0,0 +1,110 @@
+/*
+ * freopen.c - open a file and associate a stream with it
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/freopen.c,v 1.4 2006/02/02 16:59:07 beng Exp $ */
+
+#if	defined(_POSIX_SOURCE)
+#include	<sys/types.h>
+#endif
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	"loc_incl.h"
+#include	<sys/stat.h>
+
+#define	PMODE		0666
+
+/* Do not "optimize" this file to use the open with O_CREAT if the file
+ * does not exist. The reason is given in fopen.c.
+ */
+#define	O_RDONLY	0
+#define	O_WRONLY	1
+#define	O_RDWR		2
+
+#define	O_CREAT		0x010
+#define	O_TRUNC		0x020
+#define	O_APPEND	0x040
+
+int _open(const char *path, int flags);
+int _creat(const char *path, _mnx_Mode_t mode);
+int _close(int d);
+
+FILE *
+freopen(const char *name, const char *mode, FILE *stream)
+{
+	register int i;
+	struct stat st;
+	int rwmode = 0, rwflags = 0;
+	int fd, flags = stream->_flags & (_IONBF | _IOFBF | _IOLBF | _IOMYBUF);
+
+	(void) fflush(stream);				/* ignore errors */
+	(void) _close(fileno(stream));
+
+	switch(*mode++) {
+	case 'r':
+		flags |= _IOREAD;	
+		rwmode = O_RDONLY;
+		break;
+	case 'w':
+		flags |= _IOWRITE;
+		rwmode = O_WRONLY;
+		rwflags = O_CREAT | O_TRUNC;
+		break;
+	case 'a': 
+		flags |= _IOWRITE | _IOAPPEND;
+		rwmode = O_WRONLY;
+		rwflags |= O_APPEND | O_CREAT;
+		break;         
+	default:
+		goto loser;
+	}
+
+	while (*mode) {
+		switch(*mode++) {
+		case 'b':
+			continue;
+		case '+':
+			rwmode = O_RDWR;
+			flags |= _IOREAD | _IOWRITE;
+			continue;
+		/* The sequence may be followed by aditional characters */
+		default:
+			break;
+		}
+		break;
+	}
+
+	if ((rwflags & O_TRUNC)
+	    || (((fd = _open(name, rwmode)) < 0)
+		    && (rwflags & O_CREAT))) {
+		if (((fd = _creat(name, PMODE)) < 0) && flags | _IOREAD) {
+			(void) _close(fd);
+			fd = _open(name, rwmode);
+		}
+	}
+
+	if (fd < 0) {
+		goto loser;
+	}
+
+	if ( fstat( fd, &st ) == 0 ) {
+		if ( S_ISFIFO(st.st_mode) ) flags |= _IOFIFO;
+	} else {
+		goto loser;
+	}
+	
+	stream->_count = 0;
+	stream->_fd = fd;
+	stream->_flags = flags;
+	return stream;
+
+loser:
+	for( i = 0; i < FOPEN_MAX; i++) {
+		if (stream == __iotab[i]) {
+			__iotab[i] = 0;
+			break;
+		}
+	}
+	if (stream != stdin && stream != stdout && stream != stderr)
+		free((void *)stream);
+	return (FILE *)NULL;	
+}
Index: /trunk/minix/lib/stdio/fscanf.c
===================================================================
--- /trunk/minix/lib/stdio/fscanf.c	(revision 9)
+++ /trunk/minix/lib/stdio/fscanf.c	(revision 9)
@@ -0,0 +1,23 @@
+/*
+ * fscanf.c - read formatted input from stream
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fscanf.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+#include	<stdarg.h>
+#include	"loc_incl.h"
+
+int
+fscanf(FILE *stream, const char *format, ...)
+{
+	va_list ap;
+	int retval;
+
+	va_start(ap, format);
+
+	retval = _doscan(stream, format, ap);
+
+	va_end(ap);
+
+	return retval;
+}
Index: /trunk/minix/lib/stdio/fseek.c
===================================================================
--- /trunk/minix/lib/stdio/fseek.c	(revision 9)
+++ /trunk/minix/lib/stdio/fseek.c	(revision 9)
@@ -0,0 +1,44 @@
+/*
+ * fseek.c - perform an fseek
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fseek.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+#if	(SEEK_CUR != 1) || (SEEK_END != 2) || (SEEK_SET != 0)
+#error SEEK_* values are wrong
+#endif
+
+#include	"loc_incl.h"
+
+#include	<sys/types.h>
+
+off_t _lseek(int fildes, off_t offset, int whence);
+
+int
+fseek(FILE *stream, long int offset, int whence)
+{
+	int adjust = 0;
+	long pos;
+
+	stream->_flags &= ~(_IOEOF | _IOERR);
+	/* Clear both the end of file and error flags */
+
+	if (io_testflag(stream, _IOREADING)) {
+		if (whence == SEEK_CUR
+		    && stream->_buf
+		    && !io_testflag(stream,_IONBF))
+			adjust = stream->_count;
+		stream->_count = 0;
+	} else if (io_testflag(stream,_IOWRITING)) {
+		fflush(stream);
+	} else	/* neither reading nor writing. The buffer must be empty */
+		/* EMPTY */ ;
+
+	pos = _lseek(fileno(stream), offset - adjust, whence);
+	if (io_testflag(stream, _IOREAD) && io_testflag(stream, _IOWRITE))
+		stream->_flags &= ~(_IOREADING | _IOWRITING);
+
+	stream->_ptr = stream->_buf;
+	return ((pos == -1) ? -1 : 0);
+}
Index: /trunk/minix/lib/stdio/fsetpos.c
===================================================================
--- /trunk/minix/lib/stdio/fsetpos.c	(revision 9)
+++ /trunk/minix/lib/stdio/fsetpos.c	(revision 9)
@@ -0,0 +1,12 @@
+/*
+ * fsetpos.c - set the position in the file
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fsetpos.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+int
+fsetpos(FILE *stream, fpos_t *pos)
+{
+	return fseek(stream, *pos, SEEK_SET);
+}
Index: /trunk/minix/lib/stdio/ftell.c
===================================================================
--- /trunk/minix/lib/stdio/ftell.c	(revision 9)
+++ /trunk/minix/lib/stdio/ftell.c	(revision 9)
@@ -0,0 +1,38 @@
+/*
+ * ftell.c - obtain the value of the file-position indicator of a stream
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/ftell.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+#if	(SEEK_CUR != 1) || (SEEK_SET != 0) || (SEEK_END != 2)
+#error SEEK_* values are wrong
+#endif
+
+#include	"loc_incl.h"
+
+#include	<sys/types.h>
+
+off_t _lseek(int fildes, off_t offset, int whence);
+
+long ftell(FILE *stream)
+{
+	long result;
+	int adjust = 0;
+
+	if (io_testflag(stream,_IOREADING))
+		adjust = -stream->_count;
+	else if (io_testflag(stream,_IOWRITING)
+		    && stream->_buf
+		    && !io_testflag(stream,_IONBF))
+		adjust = stream->_ptr - stream->_buf;
+	else adjust = 0;
+
+	result = _lseek(fileno(stream), (off_t)0, SEEK_CUR);
+
+	if ( result == -1 )
+		return result;
+
+	result += (long) adjust;
+	return result;
+}
Index: /trunk/minix/lib/stdio/fwrite.c
===================================================================
--- /trunk/minix/lib/stdio/fwrite.c	(revision 9)
+++ /trunk/minix/lib/stdio/fwrite.c	(revision 9)
@@ -0,0 +1,29 @@
+/*
+ * fwrite.c - write a number of array elements on a file
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/fwrite.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+size_t
+fwrite(const void *ptr, size_t size, size_t nmemb,
+	    register FILE *stream)
+{
+	register const unsigned char *cp = ptr;
+	register size_t s;
+	size_t ndone = 0;
+
+	if (size)
+		while ( ndone < nmemb ) {
+			s = size;
+			do {
+				if (putc((int)*cp, stream)
+					== EOF)
+					return ndone;
+				cp++;
+			} 
+			while (--s);
+			ndone++;
+		}
+	return ndone;
+}
Index: /trunk/minix/lib/stdio/getc.c
===================================================================
--- /trunk/minix/lib/stdio/getc.c	(revision 9)
+++ /trunk/minix/lib/stdio/getc.c	(revision 9)
@@ -0,0 +1,12 @@
+/*
+ * getc.c - read an unsigned character
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/getc.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+int
+(getc)(FILE *stream)
+{
+	return getc(stream);
+}
Index: /trunk/minix/lib/stdio/getchar.c
===================================================================
--- /trunk/minix/lib/stdio/getchar.c	(revision 9)
+++ /trunk/minix/lib/stdio/getchar.c	(revision 9)
@@ -0,0 +1,12 @@
+/*
+ * getchar.c - read a character from the standard input stream
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/getchar.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+int
+(getchar)(void)
+{
+	return getchar();
+}
Index: /trunk/minix/lib/stdio/gets.c
===================================================================
--- /trunk/minix/lib/stdio/gets.c	(revision 9)
+++ /trunk/minix/lib/stdio/gets.c	(revision 9)
@@ -0,0 +1,27 @@
+/*
+ * gets.c - read a line from a stream
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/gets.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	<stdio.h>
+
+char *
+gets(char *s)
+{
+	register FILE *stream = stdin;
+	register int ch;
+	register char *ptr;
+
+	ptr = s;
+	while ((ch = getc(stream)) != EOF && ch != '\n')
+		*ptr++ = ch;
+
+	if (ch == EOF) {
+		if (feof(stream)) {
+			if (ptr == s) return NULL;
+		} else return NULL;
+	}
+
+	*ptr = '\0';
+	return s;
+}
Index: /trunk/minix/lib/stdio/icompute.c
===================================================================
--- /trunk/minix/lib/stdio/icompute.c	(revision 9)
+++ /trunk/minix/lib/stdio/icompute.c	(revision 9)
@@ -0,0 +1,21 @@
+/*
+ * icompute.c - compute an integer
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/icompute.c,v 1.1.1.1 2005/04/21 14:56:35 beng Exp $ */
+
+#include	"loc_incl.h"
+
+/* This routine is used in doprnt.c as well as in tmpfile.c and tmpnam.c. */
+
+char *
+_i_compute(unsigned long val, int base, char *s, int nrdigits)
+{
+	int c;
+
+	c= val % base ;
+	val /= base ;
+	if (val || nrdigits > 1)
+		s = _i_compute(val, base, s, nrdigits - 1);
+	*s++ = (c>9 ? c-10+'a' : c+'0');
+	return s;
+}
Index: /trunk/minix/lib/stdio/loc_incl.h
===================================================================
--- /trunk/minix/lib/stdio/loc_incl.h	(revision 9)
+++ /trunk/minix/lib/stdio/loc_incl.h	(revision 9)
@@ -0,0 +1,40 @@
+/*
+ * loc_incl.h - local include file for stdio library
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/loc_incl.h,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+
+#define	io_testflag(p,x)	((p)->_flags & (x))
+
+#include	<stdarg.h>
+
+#ifdef _ANSI
+int _doprnt(const char *format, va_list ap, FILE *stream);
+int _doscan(FILE * stream, const char *format, va_list ap);
+char *_i_compute(unsigned long val, int base, char *s, int nrdigits);
+char *_f_print(va_list *ap, int flags, char *s, char c, int precision);
+void __cleanup(void);
+
+FILE *popen(const char *command, const char *type);
+FILE *fdopen(int fd, const char *mode);
+
+#ifndef	NOFLOAT
+char *_ecvt(long double value, int ndigit, int *decpt, int *sign);
+char *_fcvt(long double value, int ndigit, int *decpt, int *sign);
+#endif	/* NOFLOAT */
+#endif
+
+#define	FL_LJUST	0x0001		/* left-justify field */
+#define	FL_SIGN		0x0002		/* sign in signed conversions */
+#define	FL_SPACE	0x0004		/* space in signed conversions */
+#define	FL_ALT		0x0008		/* alternate form */
+#define	FL_ZEROFILL	0x0010		/* fill with zero's */
+#define	FL_SHORT	0x0020		/* optional h */
+#define	FL_LONG		0x0040		/* optional l */
+#define	FL_LONGDOUBLE	0x0080		/* optional L */
+#define	FL_WIDTHSPEC	0x0100		/* field width is specified */
+#define	FL_PRECSPEC	0x0200		/* precision is specified */
+#define FL_SIGNEDCONV	0x0400		/* may contain a sign */
+#define	FL_NOASSIGN	0x0800		/* do not assign (in scanf) */
+#define	FL_NOMORE	0x1000		/* all flags collected */
Index: /trunk/minix/lib/stdio/mktemp.c
===================================================================
--- /trunk/minix/lib/stdio/mktemp.c	(revision 9)
+++ /trunk/minix/lib/stdio/mktemp.c	(revision 9)
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 1987, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)mktemp.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+static int _gettemp(char*,int*);
+
+mkstemp(path)
+	char *path;
+{
+	int fd;
+
+	return (_gettemp(path, &fd) ? fd : -1);
+}
+
+char *
+mktemp(path)
+	char *path;
+{
+	return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
+}
+
+static
+_gettemp(path, doopen)
+	char *path;
+	register int *doopen;
+{
+	extern int errno;
+	register char *start, *trv;
+	struct stat sbuf;
+	u_int pid;
+
+	pid = getpid();
+	for (trv = path; *trv; ++trv);		/* extra X's get set to 0's */
+	while (*--trv == 'X') {
+		*trv = (pid % 10) + '0';
+		pid /= 10;
+	}
+
+	/*
+	 * check the target directory; if you have six X's and it
+	 * doesn't exist this runs for a *very* long time.
+	 */
+	for (start = trv + 1;; --trv) {
+		if (trv <= path)
+			break;
+		if (*trv == '/') {
+			*trv = '\0';
+			if (stat(path, &sbuf))
+				return(0);
+			if (!S_ISDIR(sbuf.st_mode)) {
+				errno = ENOTDIR;
+				return(0);
+			}
+			*trv = '/';
+			break;
+		}
+	}
+
+	for (;;) {
+		if (doopen) {
+			if ((*doopen =
+			    open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
+				return(1);
+			if (errno != EEXIST)
+				return(0);
+		}
+		else if (stat(path, &sbuf))
+			return(errno == ENOENT ? 1 : 0);
+
+		/* tricky little algorithm for backward compatibility */
+		for (trv = start;;) {
+			if (!*trv)
+				return(0);
+			if (*trv == 'z')
+				*trv++ = 'a';
+			else {
+				if (isdigit(*trv))
+					*trv = 'a';
+				else
+					++*trv;
+				break;
+			}
+		}
+	}
+	/*NOTREACHED*/
+}
+
+/*
+ * $PchId: mktemp.c,v 1.3 1995/11/20 19:10:39 philip Exp $
+ */
Index: /trunk/minix/lib/stdio/perror.c
===================================================================
--- /trunk/minix/lib/stdio/perror.c	(revision 9)
+++ /trunk/minix/lib/stdio/perror.c	(revision 9)
@@ -0,0 +1,33 @@
+/*
+ * perror.c - print an error message on the standard error output
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/perror.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#if	defined(_POSIX_SOURCE)
+#include	<sys/types.h>
+#endif
+#include	<stdio.h>
+#include	<errno.h>
+#include	<stdio.h>
+#include	<string.h>
+#include	"loc_incl.h"
+
+ssize_t _write(int d, const char *buf, size_t nbytes);
+
+void
+perror(const char *s)
+{
+	char *p;
+	int fd;
+
+	p = strerror(errno);
+	fd = fileno(stderr);
+	fflush(stdout);
+	fflush(stderr);
+	if (s && *s) {
+		_write(fd, s, strlen(s));
+		_write(fd, ": ", 2);
+	}
+	_write(fd, p, strlen(p));
+	_write(fd, "\n", 1);
+}
Index: /trunk/minix/lib/stdio/printf.c
===================================================================
--- /trunk/minix/lib/stdio/printf.c	(revision 9)
+++ /trunk/minix/lib/stdio/printf.c	(revision 9)
@@ -0,0 +1,23 @@
+/*
+ * printf - write on the standard output stream
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/printf.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+#include	<stdarg.h>
+#include	"loc_incl.h"
+
+int
+printf(const char *format, ...)
+{
+	va_list ap;
+	int retval;
+
+	va_start(ap, format);
+
+	retval = _doprnt(format, ap, stdout);
+
+	va_end(ap);
+
+	return retval;
+}
Index: /trunk/minix/lib/stdio/putc.c
===================================================================
--- /trunk/minix/lib/stdio/putc.c	(revision 9)
+++ /trunk/minix/lib/stdio/putc.c	(revision 9)
@@ -0,0 +1,12 @@
+/*
+ * putc.c - print (or buffer) one character
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/putc.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+
+int
+(putc)(int c, FILE *stream)
+{
+	return putc(c, stream);
+}
Index: /trunk/minix/lib/stdio/putchar.c
===================================================================
--- /trunk/minix/lib/stdio/putchar.c	(revision 9)
+++ /trunk/minix/lib/stdio/putchar.c	(revision 9)
@@ -0,0 +1,12 @@
+/*
+ * putchar.c - print (or buffer) a character on the standard output stream
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/putchar.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+
+int
+(putchar)(int c)
+{
+	return putchar(c);
+}
Index: /trunk/minix/lib/stdio/puts.c
===================================================================
--- /trunk/minix/lib/stdio/puts.c	(revision 9)
+++ /trunk/minix/lib/stdio/puts.c	(revision 9)
@@ -0,0 +1,20 @@
+/*
+ * puts.c - print a string onto the standard output stream
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/puts.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+
+int
+puts(register const char *s)
+{
+	register FILE *file = stdout;
+	register int i = 0;
+
+	while (*s) {
+		if (putc(*s++, file) == EOF) return EOF;
+		else i++;
+	}
+	if (putc('\n', file) == EOF) return EOF;
+	return i + 1;
+}
Index: /trunk/minix/lib/stdio/remove.c
===================================================================
--- /trunk/minix/lib/stdio/remove.c	(revision 9)
+++ /trunk/minix/lib/stdio/remove.c	(revision 9)
@@ -0,0 +1,13 @@
+/*
+ * remove.c - remove a file
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/remove.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+
+int _unlink(const char *path);
+
+int
+remove(const char *filename) {
+	return _unlink(filename);
+}
Index: /trunk/minix/lib/stdio/rewind.c
===================================================================
--- /trunk/minix/lib/stdio/rewind.c	(revision 9)
+++ /trunk/minix/lib/stdio/rewind.c	(revision 9)
@@ -0,0 +1,14 @@
+/*
+ * rewind.c - set the file position indicator of a stream to the start
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/rewind.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+#include	"loc_incl.h"
+
+void
+rewind(FILE *stream)
+{
+	(void) fseek(stream, 0L, SEEK_SET);
+	clearerr(stream);
+}
Index: /trunk/minix/lib/stdio/scanf.c
===================================================================
--- /trunk/minix/lib/stdio/scanf.c	(revision 9)
+++ /trunk/minix/lib/stdio/scanf.c	(revision 9)
@@ -0,0 +1,25 @@
+/*
+ * scanf.c - read formatted input from the standard input stream
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/scanf.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+#include	<stdarg.h>
+#include	"loc_incl.h"
+
+int
+scanf(const char *format, ...)
+{
+	va_list ap;
+	int retval;
+
+	va_start(ap, format);
+
+	retval = _doscan(stdin, format, ap);
+
+	va_end(ap);
+
+	return retval;
+}
+
+
Index: /trunk/minix/lib/stdio/setbuf.c
===================================================================
--- /trunk/minix/lib/stdio/setbuf.c	(revision 9)
+++ /trunk/minix/lib/stdio/setbuf.c	(revision 9)
@@ -0,0 +1,13 @@
+/*
+ * setbuf.c - control buffering of a stream
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/setbuf.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+#include	"loc_incl.h"
+
+void
+setbuf(register FILE *stream, char *buf)
+{
+	(void) setvbuf(stream, buf, (buf ? _IOFBF : _IONBF), (size_t) BUFSIZ);
+}
Index: /trunk/minix/lib/stdio/setvbuf.c
===================================================================
--- /trunk/minix/lib/stdio/setvbuf.c	(revision 9)
+++ /trunk/minix/lib/stdio/setvbuf.c	(revision 9)
@@ -0,0 +1,48 @@
+/*
+ * setbuf.c - control buffering of a stream
+ */
+/* $Id: setvbuf.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	"loc_incl.h"
+
+extern void (*_clean)(void);
+
+int
+setvbuf(register FILE *stream, char *buf, int mode, size_t size)
+{
+	int retval = 0;
+
+	_clean = __cleanup;
+	if (mode != _IOFBF && mode != _IOLBF && mode != _IONBF)
+		return EOF;
+
+	if (stream->_buf && io_testflag(stream,_IOMYBUF) )
+		free((void *)stream->_buf);
+
+	stream->_flags &= ~(_IOMYBUF | _IONBF | _IOLBF);
+
+	if (buf && size <= 0) retval = EOF;
+	if (!buf && (mode != _IONBF)) {
+		if (size <= 0 || (buf = (char *) malloc(size)) == NULL) {
+			retval = EOF;
+		} else {
+			stream->_flags |= _IOMYBUF;
+		}
+	}
+
+	stream->_buf = (unsigned char *) buf;
+
+	stream->_count = 0;
+	stream->_flags |= mode;
+	stream->_ptr = stream->_buf;
+
+	if (!buf) {
+		stream->_bufsiz = 1;
+	} else {
+		stream->_bufsiz = size;
+	}
+
+	return retval;
+}
Index: /trunk/minix/lib/stdio/sprintf.c
===================================================================
--- /trunk/minix/lib/stdio/sprintf.c	(revision 9)
+++ /trunk/minix/lib/stdio/sprintf.c	(revision 9)
@@ -0,0 +1,39 @@
+/*
+ * sprintf - print formatted output on an array
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/sprintf.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+#include	<stdarg.h>
+#include	<limits.h>
+#include	"loc_incl.h"
+
+int
+sprintf(char *s, const char *format, ...)
+{
+	va_list ap;
+	int retval;
+
+	va_start(ap, format);
+
+	retval = vsnprintf(s, INT_MAX, format, ap);
+
+	va_end(ap);
+
+	return retval;
+}
+
+int
+snprintf(char *s, size_t n, const char *format, ...)
+{
+	va_list ap;
+	int retval;
+
+	va_start(ap, format);
+
+	retval = vsnprintf(s, n, format, ap);
+
+	va_end(ap);
+
+	return retval;
+}
Index: /trunk/minix/lib/stdio/sscanf.c
===================================================================
--- /trunk/minix/lib/stdio/sscanf.c	(revision 9)
+++ /trunk/minix/lib/stdio/sscanf.c	(revision 9)
@@ -0,0 +1,30 @@
+/*
+ * sscanf - read formatted output from a string
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/sscanf.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+#include	<stdarg.h>
+#include	<string.h>
+#include	"loc_incl.h"
+
+int sscanf(const char *s, const char *format, ...)
+{
+	va_list ap;
+	int retval;
+	FILE tmp_stream;
+
+	va_start(ap, format);
+
+	tmp_stream._fd     = -1;
+	tmp_stream._flags  = _IOREAD + _IONBF + _IOREADING;
+	tmp_stream._buf    = (unsigned char *) s;
+	tmp_stream._ptr    = (unsigned char *) s;
+	tmp_stream._count  = strlen(s);
+
+	retval = _doscan(&tmp_stream, format, ap);
+
+	va_end(ap);
+
+	return retval;
+}
Index: /trunk/minix/lib/stdio/tmpfile.c
===================================================================
--- /trunk/minix/lib/stdio/tmpfile.c	(revision 9)
+++ /trunk/minix/lib/stdio/tmpfile.c	(revision 9)
@@ -0,0 +1,31 @@
+/*
+ * tmpfile.c - create and open a temporary file
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/tmpfile.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#if	defined(_POSIX_SOURCE)
+#include	<sys/types.h>
+#endif
+#include	<stdio.h>
+#include	<string.h>
+#include	"loc_incl.h"
+
+pid_t _getpid(void);
+
+FILE *
+tmpfile(void) {
+	static char name_buffer[L_tmpnam] = "/tmp/tmp." ;
+	static char *name = NULL;
+	FILE *file;
+
+	if (!name) {
+		name = name_buffer + strlen(name_buffer);
+		name = _i_compute(_getpid(), 10, name, 5);
+		*name = '\0';
+	}
+
+	file = fopen(name_buffer,"wb+");
+	if (!file) return (FILE *)NULL;
+	(void) remove(name_buffer);
+	return file;
+}
Index: /trunk/minix/lib/stdio/tmpnam.c
===================================================================
--- /trunk/minix/lib/stdio/tmpnam.c	(revision 9)
+++ /trunk/minix/lib/stdio/tmpnam.c	(revision 9)
@@ -0,0 +1,31 @@
+/*
+ * tmpnam.c - create a unique filename
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/tmpnam.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#if	defined(_POSIX_SOURCE)
+#include	<sys/types.h>
+#endif
+#include	<stdio.h>
+#include	<string.h>
+#include	"loc_incl.h"
+
+pid_t _getpid(void);
+
+char *
+tmpnam(char *s) {
+	static char name_buffer[L_tmpnam] = "/tmp/tmp.";
+	static unsigned long count = 0;
+	static char *name = NULL;
+
+	if (!name) { 
+		name = name_buffer + strlen(name_buffer);
+		name = _i_compute((unsigned long)_getpid(), 10, name, 5);
+		*name++ = '.';
+		*name = '\0';
+	}
+	if (++count > TMP_MAX) count = 1;	/* wrap-around */
+	*_i_compute(count, 10, name, 3) = '\0';
+	if (s) return strcpy(s, name_buffer);
+	else return name_buffer;
+}
Index: /trunk/minix/lib/stdio/ungetc.c
===================================================================
--- /trunk/minix/lib/stdio/ungetc.c	(revision 9)
+++ /trunk/minix/lib/stdio/ungetc.c	(revision 9)
@@ -0,0 +1,26 @@
+/*
+ * ungetc.c - push a character back onto an input stream
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/ungetc.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+#include	"loc_incl.h"
+
+int
+ungetc(int ch, FILE *stream)
+{
+	unsigned char *p;
+
+	if (ch == EOF  || !io_testflag(stream,_IOREADING))
+		return EOF;
+	if (stream->_ptr == stream->_buf) {
+		if (stream->_count != 0) return EOF;
+		stream->_ptr++;
+	}
+	stream->_count++;
+	p = --(stream->_ptr);		/* ??? Bloody vax assembler !!! */
+	/* ungetc() in sscanf() shouldn't write in rom */
+	if (*p != (unsigned char) ch)
+		*p = (unsigned char) ch;
+	return ch;
+}
Index: /trunk/minix/lib/stdio/vfprintf.c
===================================================================
--- /trunk/minix/lib/stdio/vfprintf.c	(revision 9)
+++ /trunk/minix/lib/stdio/vfprintf.c	(revision 9)
@@ -0,0 +1,14 @@
+/*
+ * vfprintf - formatted output without ellipsis
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/vfprintf.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+#include	<stdarg.h>
+#include	"loc_incl.h"
+
+int
+vfprintf(FILE *stream, const char *format, va_list arg)
+{
+	return _doprnt (format, arg, stream);
+}
Index: /trunk/minix/lib/stdio/vprintf.c
===================================================================
--- /trunk/minix/lib/stdio/vprintf.c	(revision 9)
+++ /trunk/minix/lib/stdio/vprintf.c	(revision 9)
@@ -0,0 +1,14 @@
+/*
+ * vprintf - formatted output without ellipsis to the standard output stream
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/vprintf.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+#include	<stdarg.h>
+#include	"loc_incl.h"
+
+int
+vprintf(const char *format, va_list arg)
+{
+	return _doprnt(format, arg, stdout);
+}
Index: /trunk/minix/lib/stdio/vscanf.c
===================================================================
--- /trunk/minix/lib/stdio/vscanf.c	(revision 9)
+++ /trunk/minix/lib/stdio/vscanf.c	(revision 9)
@@ -0,0 +1,13 @@
+/*
+ * vscanf.c - read formatted input from the standard input stream
+ */
+
+#include	<stdio.h>
+#include	<stdarg.h>
+#include	"loc_incl.h"
+
+int
+vscanf(const char *format, va_list ap)
+{
+	return _doscan(stdin, format, ap);
+}
Index: /trunk/minix/lib/stdio/vsprintf.c
===================================================================
--- /trunk/minix/lib/stdio/vsprintf.c	(revision 9)
+++ /trunk/minix/lib/stdio/vsprintf.c	(revision 9)
@@ -0,0 +1,34 @@
+/*
+ * vsprintf - print formatted output without ellipsis on an array
+ */
+/* $Header: /cvsup/minix/src/lib/stdio/vsprintf.c,v 1.1.1.1 2005/04/21 14:56:36 beng Exp $ */
+
+#include	<stdio.h>
+#include	<stdarg.h>
+#include	<limits.h>
+#include	"loc_incl.h"
+
+int
+vsnprintf(char *s, size_t n, const char *format, va_list arg)
+{
+	int retval;
+	FILE tmp_stream;
+
+	tmp_stream._fd     = -1;
+	tmp_stream._flags  = _IOWRITE + _IONBF + _IOWRITING;
+	tmp_stream._buf    = (unsigned char *) s;
+	tmp_stream._ptr    = (unsigned char *) s;
+	tmp_stream._count  = n-1;
+
+	retval = _doprnt(format, arg, &tmp_stream);
+	tmp_stream._count  = 1;
+	putc('\0',&tmp_stream);
+
+	return retval;
+}
+
+int
+vsprintf(char *s, const char *format, va_list arg)
+{
+	return vsnprintf(s, INT_MAX, format, arg);
+}
Index: /trunk/minix/lib/stdio/vsscanf.c
===================================================================
--- /trunk/minix/lib/stdio/vsscanf.c	(revision 9)
+++ /trunk/minix/lib/stdio/vsscanf.c	(revision 9)
@@ -0,0 +1,21 @@
+/*
+ * vsscanf - read formatted output from a string
+ */
+
+#include	<stdio.h>
+#include	<stdarg.h>
+#include	<string.h>
+#include	"loc_incl.h"
+
+int vsscanf(const char *s, const char *format, va_list ap)
+{
+	FILE tmp_stream;
+
+	tmp_stream._fd     = -1;
+	tmp_stream._flags  = _IOREAD + _IONBF + _IOREADING;
+	tmp_stream._buf    = (unsigned char *) s;
+	tmp_stream._ptr    = (unsigned char *) s;
+	tmp_stream._count  = strlen(s);
+
+	return _doscan(&tmp_stream, format, ap);
+}
Index: /trunk/minix/lib/syscall/Makedepend-ack
===================================================================
--- /trunk/minix/lib/syscall/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/syscall/Makedepend-ack	(revision 9)
@@ -0,0 +1,111 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc  -E' _exit.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' _pm_findproc.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' access.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' alarm.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' allocmem.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' brk.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' cfgetispeed.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' cfgetospeed.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' cfsetispeed.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' cfsetospeed.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' chdir.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' chmod.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' chown.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' chroot.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' close.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' closedir.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' creat.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' devctl.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' dup.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' dup2.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' execl.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' execle.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' execlp.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' execv.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' execve.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' execvp.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' fcntl.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' fork.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' fpathconf.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' freemem.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' fstat.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' fstatfs.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' getcwd.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' getegid.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' geteuid.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' getgid.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' getgroups.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' getnpid.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' getnprocnr.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' getpgrp.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' getpid.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' getppid.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' getpprocnr.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' getprocnr.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' getsigset.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' getsysinfo.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' getuid.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' ioctl.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' isatty.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' kill.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' link.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' lseek.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' lstat.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' mkdir.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' mkfifo.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' mknod.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' mount.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' open.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' opendir.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' pathconf.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' pause.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' pipe.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' ptrace.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' read.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' readdir.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' readlink.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' reboot.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' rename.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' rewinddir.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' rmdir.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' sbrk.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' seekdir.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' setgid.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' setsid.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' setuid.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' sigaction.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' sigaddset.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' sigdelset.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' sigemptyset.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' sigfillset.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' sigismember.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' sigpending.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' sigprocmask.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' sigreturn.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' sigsuspend.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' sleep.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' stat.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' stime.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' svrctl.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' symlink.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' sync.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' tcdrain.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' tcflow.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' tcflush.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' tcgetattr.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' tcsendbreak.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' tcsetattr.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' time.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' times.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' truncate.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' umask.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' umount.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' uname.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' unlink.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' utime.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' wait.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' waitpid.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
+	mkdep 'cc  -E' write.s | sed -e 's:^\(.\):../obj-ack//./syscall/\1:' >> .depend-ack
Index: /trunk/minix/lib/syscall/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/syscall/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/syscall/Makedepend-gnu	(revision 9)
@@ -0,0 +1,111 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' _exit.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' _pm_findproc.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' access.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' alarm.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' allocmem.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' brk.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' cfgetispeed.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' cfgetospeed.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' cfsetispeed.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' cfsetospeed.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' chdir.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' chmod.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' chown.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' chroot.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' close.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' closedir.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' creat.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' devctl.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' dup.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' dup2.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' execl.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' execle.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' execlp.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' execv.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' execve.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' execvp.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' fcntl.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' fork.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' fpathconf.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' freemem.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' fstat.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' fstatfs.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' getcwd.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' getegid.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' geteuid.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' getgid.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' getgroups.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' getnpid.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' getnprocnr.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' getpgrp.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' getpid.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' getppid.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' getpprocnr.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' getprocnr.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' getsigset.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' getsysinfo.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' getuid.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' ioctl.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' isatty.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' kill.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' link.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' lseek.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' lstat.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' mkdir.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' mkfifo.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' mknod.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' mount.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' open.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' opendir.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' pathconf.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' pause.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' pipe.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' ptrace.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' read.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' readdir.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' readlink.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' reboot.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' rename.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' rewinddir.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' rmdir.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' sbrk.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' seekdir.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' setgid.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' setsid.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' setuid.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' sigaction.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' sigaddset.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' sigdelset.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' sigemptyset.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' sigfillset.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' sigismember.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' sigpending.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' sigprocmask.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' sigreturn.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' sigsuspend.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' sleep.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' stat.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' stime.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' svrctl.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' symlink.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' sync.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' tcdrain.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' tcflow.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' tcflush.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' tcgetattr.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' tcsendbreak.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' tcsetattr.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' time.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' times.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' truncate.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' umask.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' umount.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' uname.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' unlink.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' utime.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' wait.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' waitpid.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
+	mkdep 'gcc  -E -x assembler-with-cpp -I.' write.s | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syscall/\1:' >> .depend-gnu
Index: /trunk/minix/lib/syscall/Makefile
===================================================================
--- /trunk/minix/lib/syscall/Makefile	(revision 9)
+++ /trunk/minix/lib/syscall/Makefile	(revision 9)
@@ -0,0 +1,909 @@
+#Generated from ./syscall/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./syscall ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./syscall ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libc.a
+
+../obj-ack//libc.a: ../obj-ack//libc.a(_exit.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(_pm_findproc.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(access.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(alarm.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(allocmem.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(brk.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(cfgetispeed.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(cfgetospeed.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(cfsetispeed.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(cfsetospeed.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(chdir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(chmod.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(chown.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(chroot.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(close.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(closedir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(creat.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(devctl.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(dup.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(dup2.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(execl.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(execle.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(execlp.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(execv.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(execve.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(execvp.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fcntl.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fork.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fpathconf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(freemem.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fstat.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(fstatfs.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getcwd.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getegid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(geteuid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getgid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getgroups.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getnpid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getnprocnr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getpgrp.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getpid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getppid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getpprocnr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getprocnr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getsigset.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getsysinfo.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(getuid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ioctl.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(isatty.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(kill.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(link.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(lseek.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(lstat.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(mkdir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(mkfifo.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(mknod.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(mount.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(open.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(opendir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(pathconf.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(pause.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(pipe.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(ptrace.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(read.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(readdir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(readlink.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(reboot.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(rename.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(rewinddir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(rmdir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sbrk.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(seekdir.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(setgid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(setsid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(setuid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sigaction.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sigaddset.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sigdelset.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sigemptyset.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sigfillset.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sigismember.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sigpending.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sigprocmask.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sigreturn.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sigsuspend.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sleep.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(stat.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(stime.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(svrctl.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(symlink.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(sync.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(tcdrain.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(tcflow.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(tcflush.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(tcgetattr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(tcsendbreak.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(tcsetattr.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(time.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(times.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(truncate.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(umask.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(umount.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(uname.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(unlink.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(utime.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(wait.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(waitpid.o)
+../obj-ack//libc.a: ../obj-ack//libc.a(write.o)
+
+../obj-ack//libc.a:
+	ar cr ../obj-ack//libc.a ../obj-ack//./syscall/*.o
+	rm ../obj-ack//./syscall/*.o
+
+../obj-ack//libc.a(_exit.o): _exit.s
+	cc  -c -o ../obj-ack//./syscall/_exit.o _exit.s
+../obj-ack//libc.a(_pm_findproc.o): _pm_findproc.s
+	cc  -c -o ../obj-ack//./syscall/_pm_findproc.o _pm_findproc.s
+../obj-ack//libc.a(access.o): access.s
+	cc  -c -o ../obj-ack//./syscall/access.o access.s
+../obj-ack//libc.a(alarm.o): alarm.s
+	cc  -c -o ../obj-ack//./syscall/alarm.o alarm.s
+../obj-ack//libc.a(allocmem.o): allocmem.s
+	cc  -c -o ../obj-ack//./syscall/allocmem.o allocmem.s
+../obj-ack//libc.a(brk.o): brk.s
+	cc  -c -o ../obj-ack//./syscall/brk.o brk.s
+../obj-ack//libc.a(cfgetispeed.o): cfgetispeed.s
+	cc  -c -o ../obj-ack//./syscall/cfgetispeed.o cfgetispeed.s
+../obj-ack//libc.a(cfgetospeed.o): cfgetospeed.s
+	cc  -c -o ../obj-ack//./syscall/cfgetospeed.o cfgetospeed.s
+../obj-ack//libc.a(cfsetispeed.o): cfsetispeed.s
+	cc  -c -o ../obj-ack//./syscall/cfsetispeed.o cfsetispeed.s
+../obj-ack//libc.a(cfsetospeed.o): cfsetospeed.s
+	cc  -c -o ../obj-ack//./syscall/cfsetospeed.o cfsetospeed.s
+../obj-ack//libc.a(chdir.o): chdir.s
+	cc  -c -o ../obj-ack//./syscall/chdir.o chdir.s
+../obj-ack//libc.a(chmod.o): chmod.s
+	cc  -c -o ../obj-ack//./syscall/chmod.o chmod.s
+../obj-ack//libc.a(chown.o): chown.s
+	cc  -c -o ../obj-ack//./syscall/chown.o chown.s
+../obj-ack//libc.a(chroot.o): chroot.s
+	cc  -c -o ../obj-ack//./syscall/chroot.o chroot.s
+../obj-ack//libc.a(close.o): close.s
+	cc  -c -o ../obj-ack//./syscall/close.o close.s
+../obj-ack//libc.a(closedir.o): closedir.s
+	cc  -c -o ../obj-ack//./syscall/closedir.o closedir.s
+../obj-ack//libc.a(creat.o): creat.s
+	cc  -c -o ../obj-ack//./syscall/creat.o creat.s
+../obj-ack//libc.a(devctl.o): devctl.s
+	cc  -c -o ../obj-ack//./syscall/devctl.o devctl.s
+../obj-ack//libc.a(dup.o): dup.s
+	cc  -c -o ../obj-ack//./syscall/dup.o dup.s
+../obj-ack//libc.a(dup2.o): dup2.s
+	cc  -c -o ../obj-ack//./syscall/dup2.o dup2.s
+../obj-ack//libc.a(execl.o): execl.s
+	cc  -c -o ../obj-ack//./syscall/execl.o execl.s
+../obj-ack//libc.a(execle.o): execle.s
+	cc  -c -o ../obj-ack//./syscall/execle.o execle.s
+../obj-ack//libc.a(execlp.o): execlp.s
+	cc  -c -o ../obj-ack//./syscall/execlp.o execlp.s
+../obj-ack//libc.a(execv.o): execv.s
+	cc  -c -o ../obj-ack//./syscall/execv.o execv.s
+../obj-ack//libc.a(execve.o): execve.s
+	cc  -c -o ../obj-ack//./syscall/execve.o execve.s
+../obj-ack//libc.a(execvp.o): execvp.s
+	cc  -c -o ../obj-ack//./syscall/execvp.o execvp.s
+../obj-ack//libc.a(fcntl.o): fcntl.s
+	cc  -c -o ../obj-ack//./syscall/fcntl.o fcntl.s
+../obj-ack//libc.a(fork.o): fork.s
+	cc  -c -o ../obj-ack//./syscall/fork.o fork.s
+../obj-ack//libc.a(fpathconf.o): fpathconf.s
+	cc  -c -o ../obj-ack//./syscall/fpathconf.o fpathconf.s
+../obj-ack//libc.a(freemem.o): freemem.s
+	cc  -c -o ../obj-ack//./syscall/freemem.o freemem.s
+../obj-ack//libc.a(fstat.o): fstat.s
+	cc  -c -o ../obj-ack//./syscall/fstat.o fstat.s
+../obj-ack//libc.a(fstatfs.o): fstatfs.s
+	cc  -c -o ../obj-ack//./syscall/fstatfs.o fstatfs.s
+../obj-ack//libc.a(getcwd.o): getcwd.s
+	cc  -c -o ../obj-ack//./syscall/getcwd.o getcwd.s
+../obj-ack//libc.a(getegid.o): getegid.s
+	cc  -c -o ../obj-ack//./syscall/getegid.o getegid.s
+../obj-ack//libc.a(geteuid.o): geteuid.s
+	cc  -c -o ../obj-ack//./syscall/geteuid.o geteuid.s
+../obj-ack//libc.a(getgid.o): getgid.s
+	cc  -c -o ../obj-ack//./syscall/getgid.o getgid.s
+../obj-ack//libc.a(getgroups.o): getgroups.s
+	cc  -c -o ../obj-ack//./syscall/getgroups.o getgroups.s
+../obj-ack//libc.a(getnpid.o): getnpid.s
+	cc  -c -o ../obj-ack//./syscall/getnpid.o getnpid.s
+../obj-ack//libc.a(getnprocnr.o): getnprocnr.s
+	cc  -c -o ../obj-ack//./syscall/getnprocnr.o getnprocnr.s
+../obj-ack//libc.a(getpgrp.o): getpgrp.s
+	cc  -c -o ../obj-ack//./syscall/getpgrp.o getpgrp.s
+../obj-ack//libc.a(getpid.o): getpid.s
+	cc  -c -o ../obj-ack//./syscall/getpid.o getpid.s
+../obj-ack//libc.a(getppid.o): getppid.s
+	cc  -c -o ../obj-ack//./syscall/getppid.o getppid.s
+../obj-ack//libc.a(getpprocnr.o): getpprocnr.s
+	cc  -c -o ../obj-ack//./syscall/getpprocnr.o getpprocnr.s
+../obj-ack//libc.a(getprocnr.o): getprocnr.s
+	cc  -c -o ../obj-ack//./syscall/getprocnr.o getprocnr.s
+../obj-ack//libc.a(getsigset.o): getsigset.s
+	cc  -c -o ../obj-ack//./syscall/getsigset.o getsigset.s
+../obj-ack//libc.a(getsysinfo.o): getsysinfo.s
+	cc  -c -o ../obj-ack//./syscall/getsysinfo.o getsysinfo.s
+../obj-ack//libc.a(getuid.o): getuid.s
+	cc  -c -o ../obj-ack//./syscall/getuid.o getuid.s
+../obj-ack//libc.a(ioctl.o): ioctl.s
+	cc  -c -o ../obj-ack//./syscall/ioctl.o ioctl.s
+../obj-ack//libc.a(isatty.o): isatty.s
+	cc  -c -o ../obj-ack//./syscall/isatty.o isatty.s
+../obj-ack//libc.a(kill.o): kill.s
+	cc  -c -o ../obj-ack//./syscall/kill.o kill.s
+../obj-ack//libc.a(link.o): link.s
+	cc  -c -o ../obj-ack//./syscall/link.o link.s
+../obj-ack//libc.a(lseek.o): lseek.s
+	cc  -c -o ../obj-ack//./syscall/lseek.o lseek.s
+../obj-ack//libc.a(lstat.o): lstat.s
+	cc  -c -o ../obj-ack//./syscall/lstat.o lstat.s
+../obj-ack//libc.a(mkdir.o): mkdir.s
+	cc  -c -o ../obj-ack//./syscall/mkdir.o mkdir.s
+../obj-ack//libc.a(mkfifo.o): mkfifo.s
+	cc  -c -o ../obj-ack//./syscall/mkfifo.o mkfifo.s
+../obj-ack//libc.a(mknod.o): mknod.s
+	cc  -c -o ../obj-ack//./syscall/mknod.o mknod.s
+../obj-ack//libc.a(mount.o): mount.s
+	cc  -c -o ../obj-ack//./syscall/mount.o mount.s
+../obj-ack//libc.a(open.o): open.s
+	cc  -c -o ../obj-ack//./syscall/open.o open.s
+../obj-ack//libc.a(opendir.o): opendir.s
+	cc  -c -o ../obj-ack//./syscall/opendir.o opendir.s
+../obj-ack//libc.a(pathconf.o): pathconf.s
+	cc  -c -o ../obj-ack//./syscall/pathconf.o pathconf.s
+../obj-ack//libc.a(pause.o): pause.s
+	cc  -c -o ../obj-ack//./syscall/pause.o pause.s
+../obj-ack//libc.a(pipe.o): pipe.s
+	cc  -c -o ../obj-ack//./syscall/pipe.o pipe.s
+../obj-ack//libc.a(ptrace.o): ptrace.s
+	cc  -c -o ../obj-ack//./syscall/ptrace.o ptrace.s
+../obj-ack//libc.a(read.o): read.s
+	cc  -c -o ../obj-ack//./syscall/read.o read.s
+../obj-ack//libc.a(readdir.o): readdir.s
+	cc  -c -o ../obj-ack//./syscall/readdir.o readdir.s
+../obj-ack//libc.a(readlink.o): readlink.s
+	cc  -c -o ../obj-ack//./syscall/readlink.o readlink.s
+../obj-ack//libc.a(reboot.o): reboot.s
+	cc  -c -o ../obj-ack//./syscall/reboot.o reboot.s
+../obj-ack//libc.a(rename.o): rename.s
+	cc  -c -o ../obj-ack//./syscall/rename.o rename.s
+../obj-ack//libc.a(rewinddir.o): rewinddir.s
+	cc  -c -o ../obj-ack//./syscall/rewinddir.o rewinddir.s
+../obj-ack//libc.a(rmdir.o): rmdir.s
+	cc  -c -o ../obj-ack//./syscall/rmdir.o rmdir.s
+../obj-ack//libc.a(sbrk.o): sbrk.s
+	cc  -c -o ../obj-ack//./syscall/sbrk.o sbrk.s
+../obj-ack//libc.a(seekdir.o): seekdir.s
+	cc  -c -o ../obj-ack//./syscall/seekdir.o seekdir.s
+../obj-ack//libc.a(setgid.o): setgid.s
+	cc  -c -o ../obj-ack//./syscall/setgid.o setgid.s
+../obj-ack//libc.a(setsid.o): setsid.s
+	cc  -c -o ../obj-ack//./syscall/setsid.o setsid.s
+../obj-ack//libc.a(setuid.o): setuid.s
+	cc  -c -o ../obj-ack//./syscall/setuid.o setuid.s
+../obj-ack//libc.a(sigaction.o): sigaction.s
+	cc  -c -o ../obj-ack//./syscall/sigaction.o sigaction.s
+../obj-ack//libc.a(sigaddset.o): sigaddset.s
+	cc  -c -o ../obj-ack//./syscall/sigaddset.o sigaddset.s
+../obj-ack//libc.a(sigdelset.o): sigdelset.s
+	cc  -c -o ../obj-ack//./syscall/sigdelset.o sigdelset.s
+../obj-ack//libc.a(sigemptyset.o): sigemptyset.s
+	cc  -c -o ../obj-ack//./syscall/sigemptyset.o sigemptyset.s
+../obj-ack//libc.a(sigfillset.o): sigfillset.s
+	cc  -c -o ../obj-ack//./syscall/sigfillset.o sigfillset.s
+../obj-ack//libc.a(sigismember.o): sigismember.s
+	cc  -c -o ../obj-ack//./syscall/sigismember.o sigismember.s
+../obj-ack//libc.a(sigpending.o): sigpending.s
+	cc  -c -o ../obj-ack//./syscall/sigpending.o sigpending.s
+../obj-ack//libc.a(sigprocmask.o): sigprocmask.s
+	cc  -c -o ../obj-ack//./syscall/sigprocmask.o sigprocmask.s
+../obj-ack//libc.a(sigreturn.o): sigreturn.s
+	cc  -c -o ../obj-ack//./syscall/sigreturn.o sigreturn.s
+../obj-ack//libc.a(sigsuspend.o): sigsuspend.s
+	cc  -c -o ../obj-ack//./syscall/sigsuspend.o sigsuspend.s
+../obj-ack//libc.a(sleep.o): sleep.s
+	cc  -c -o ../obj-ack//./syscall/sleep.o sleep.s
+../obj-ack//libc.a(stat.o): stat.s
+	cc  -c -o ../obj-ack//./syscall/stat.o stat.s
+../obj-ack//libc.a(stime.o): stime.s
+	cc  -c -o ../obj-ack//./syscall/stime.o stime.s
+../obj-ack//libc.a(svrctl.o): svrctl.s
+	cc  -c -o ../obj-ack//./syscall/svrctl.o svrctl.s
+../obj-ack//libc.a(symlink.o): symlink.s
+	cc  -c -o ../obj-ack//./syscall/symlink.o symlink.s
+../obj-ack//libc.a(sync.o): sync.s
+	cc  -c -o ../obj-ack//./syscall/sync.o sync.s
+../obj-ack//libc.a(tcdrain.o): tcdrain.s
+	cc  -c -o ../obj-ack//./syscall/tcdrain.o tcdrain.s
+../obj-ack//libc.a(tcflow.o): tcflow.s
+	cc  -c -o ../obj-ack//./syscall/tcflow.o tcflow.s
+../obj-ack//libc.a(tcflush.o): tcflush.s
+	cc  -c -o ../obj-ack//./syscall/tcflush.o tcflush.s
+../obj-ack//libc.a(tcgetattr.o): tcgetattr.s
+	cc  -c -o ../obj-ack//./syscall/tcgetattr.o tcgetattr.s
+../obj-ack//libc.a(tcsendbreak.o): tcsendbreak.s
+	cc  -c -o ../obj-ack//./syscall/tcsendbreak.o tcsendbreak.s
+../obj-ack//libc.a(tcsetattr.o): tcsetattr.s
+	cc  -c -o ../obj-ack//./syscall/tcsetattr.o tcsetattr.s
+../obj-ack//libc.a(time.o): time.s
+	cc  -c -o ../obj-ack//./syscall/time.o time.s
+../obj-ack//libc.a(times.o): times.s
+	cc  -c -o ../obj-ack//./syscall/times.o times.s
+../obj-ack//libc.a(truncate.o): truncate.s
+	cc  -c -o ../obj-ack//./syscall/truncate.o truncate.s
+../obj-ack//libc.a(umask.o): umask.s
+	cc  -c -o ../obj-ack//./syscall/umask.o umask.s
+../obj-ack//libc.a(umount.o): umount.s
+	cc  -c -o ../obj-ack//./syscall/umount.o umount.s
+../obj-ack//libc.a(uname.o): uname.s
+	cc  -c -o ../obj-ack//./syscall/uname.o uname.s
+../obj-ack//libc.a(unlink.o): unlink.s
+	cc  -c -o ../obj-ack//./syscall/unlink.o unlink.s
+../obj-ack//libc.a(utime.o): utime.s
+	cc  -c -o ../obj-ack//./syscall/utime.o utime.s
+../obj-ack//libc.a(wait.o): wait.s
+	cc  -c -o ../obj-ack//./syscall/wait.o wait.s
+../obj-ack//libc.a(waitpid.o): waitpid.s
+	cc  -c -o ../obj-ack//./syscall/waitpid.o waitpid.s
+../obj-ack//libc.a(write.o): write.s
+	cc  -c -o ../obj-ack//./syscall/write.o write.s
+
+all-gnu: ../obj-gnu/libc.a
+
+../obj-gnu/libc.a: ../obj-gnu/./syscall/_exit.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/_pm_findproc.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/access.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/alarm.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/allocmem.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/brk.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/cfgetispeed.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/cfgetospeed.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/cfsetispeed.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/cfsetospeed.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/chdir.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/chmod.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/chown.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/chroot.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/close.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/closedir.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/creat.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/devctl.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/dup.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/dup2.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/execl.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/execle.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/execlp.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/execv.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/execve.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/execvp.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/fcntl.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/fork.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/fpathconf.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/freemem.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/fstat.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/fstatfs.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/getcwd.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/getegid.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/geteuid.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/getgid.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/getgroups.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/getnpid.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/getnprocnr.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/getpgrp.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/getpid.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/getppid.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/getpprocnr.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/getprocnr.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/getsigset.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/getsysinfo.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/getuid.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/ioctl.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/isatty.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/kill.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/link.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/lseek.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/lstat.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/mkdir.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/mkfifo.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/mknod.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/mount.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/open.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/opendir.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/pathconf.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/pause.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/pipe.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/ptrace.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/read.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/readdir.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/readlink.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/reboot.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/rename.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/rewinddir.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/rmdir.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/sbrk.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/seekdir.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/setgid.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/setsid.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/setuid.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/sigaction.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/sigaddset.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/sigdelset.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/sigemptyset.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/sigfillset.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/sigismember.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/sigpending.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/sigprocmask.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/sigreturn.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/sigsuspend.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/sleep.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/stat.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/stime.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/svrctl.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/symlink.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/sync.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/tcdrain.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/tcflow.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/tcflush.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/tcgetattr.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/tcsendbreak.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/tcsetattr.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/time.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/times.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/truncate.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/umask.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/umount.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/uname.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/unlink.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/utime.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/wait.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/waitpid.o
+../obj-gnu/libc.a: ../obj-gnu/./syscall/write.o
+
+../obj-gnu/libc.a:
+	gar cr ../obj-gnu/libc.a $?
+
+../obj-gnu/./syscall/_exit.o: _exit.s
+	gcc  -E -x assembler-with-cpp -I. _exit.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/_exit.s.gnu || true
+	gas -o ../obj-gnu/./syscall/_exit.o ../obj-gnu/./syscall/_exit.s.gnu
+
+../obj-gnu/./syscall/_pm_findproc.o: _pm_findproc.s
+	gcc  -E -x assembler-with-cpp -I. _pm_findproc.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/_pm_findproc.s.gnu || true
+	gas -o ../obj-gnu/./syscall/_pm_findproc.o ../obj-gnu/./syscall/_pm_findproc.s.gnu
+
+../obj-gnu/./syscall/access.o: access.s
+	gcc  -E -x assembler-with-cpp -I. access.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/access.s.gnu || true
+	gas -o ../obj-gnu/./syscall/access.o ../obj-gnu/./syscall/access.s.gnu
+
+../obj-gnu/./syscall/alarm.o: alarm.s
+	gcc  -E -x assembler-with-cpp -I. alarm.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/alarm.s.gnu || true
+	gas -o ../obj-gnu/./syscall/alarm.o ../obj-gnu/./syscall/alarm.s.gnu
+
+../obj-gnu/./syscall/allocmem.o: allocmem.s
+	gcc  -E -x assembler-with-cpp -I. allocmem.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/allocmem.s.gnu || true
+	gas -o ../obj-gnu/./syscall/allocmem.o ../obj-gnu/./syscall/allocmem.s.gnu
+
+../obj-gnu/./syscall/brk.o: brk.s
+	gcc  -E -x assembler-with-cpp -I. brk.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/brk.s.gnu || true
+	gas -o ../obj-gnu/./syscall/brk.o ../obj-gnu/./syscall/brk.s.gnu
+
+../obj-gnu/./syscall/cfgetispeed.o: cfgetispeed.s
+	gcc  -E -x assembler-with-cpp -I. cfgetispeed.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/cfgetispeed.s.gnu || true
+	gas -o ../obj-gnu/./syscall/cfgetispeed.o ../obj-gnu/./syscall/cfgetispeed.s.gnu
+
+../obj-gnu/./syscall/cfgetospeed.o: cfgetospeed.s
+	gcc  -E -x assembler-with-cpp -I. cfgetospeed.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/cfgetospeed.s.gnu || true
+	gas -o ../obj-gnu/./syscall/cfgetospeed.o ../obj-gnu/./syscall/cfgetospeed.s.gnu
+
+../obj-gnu/./syscall/cfsetispeed.o: cfsetispeed.s
+	gcc  -E -x assembler-with-cpp -I. cfsetispeed.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/cfsetispeed.s.gnu || true
+	gas -o ../obj-gnu/./syscall/cfsetispeed.o ../obj-gnu/./syscall/cfsetispeed.s.gnu
+
+../obj-gnu/./syscall/cfsetospeed.o: cfsetospeed.s
+	gcc  -E -x assembler-with-cpp -I. cfsetospeed.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/cfsetospeed.s.gnu || true
+	gas -o ../obj-gnu/./syscall/cfsetospeed.o ../obj-gnu/./syscall/cfsetospeed.s.gnu
+
+../obj-gnu/./syscall/chdir.o: chdir.s
+	gcc  -E -x assembler-with-cpp -I. chdir.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/chdir.s.gnu || true
+	gas -o ../obj-gnu/./syscall/chdir.o ../obj-gnu/./syscall/chdir.s.gnu
+
+../obj-gnu/./syscall/chmod.o: chmod.s
+	gcc  -E -x assembler-with-cpp -I. chmod.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/chmod.s.gnu || true
+	gas -o ../obj-gnu/./syscall/chmod.o ../obj-gnu/./syscall/chmod.s.gnu
+
+../obj-gnu/./syscall/chown.o: chown.s
+	gcc  -E -x assembler-with-cpp -I. chown.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/chown.s.gnu || true
+	gas -o ../obj-gnu/./syscall/chown.o ../obj-gnu/./syscall/chown.s.gnu
+
+../obj-gnu/./syscall/chroot.o: chroot.s
+	gcc  -E -x assembler-with-cpp -I. chroot.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/chroot.s.gnu || true
+	gas -o ../obj-gnu/./syscall/chroot.o ../obj-gnu/./syscall/chroot.s.gnu
+
+../obj-gnu/./syscall/close.o: close.s
+	gcc  -E -x assembler-with-cpp -I. close.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/close.s.gnu || true
+	gas -o ../obj-gnu/./syscall/close.o ../obj-gnu/./syscall/close.s.gnu
+
+../obj-gnu/./syscall/closedir.o: closedir.s
+	gcc  -E -x assembler-with-cpp -I. closedir.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/closedir.s.gnu || true
+	gas -o ../obj-gnu/./syscall/closedir.o ../obj-gnu/./syscall/closedir.s.gnu
+
+../obj-gnu/./syscall/creat.o: creat.s
+	gcc  -E -x assembler-with-cpp -I. creat.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/creat.s.gnu || true
+	gas -o ../obj-gnu/./syscall/creat.o ../obj-gnu/./syscall/creat.s.gnu
+
+../obj-gnu/./syscall/devctl.o: devctl.s
+	gcc  -E -x assembler-with-cpp -I. devctl.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/devctl.s.gnu || true
+	gas -o ../obj-gnu/./syscall/devctl.o ../obj-gnu/./syscall/devctl.s.gnu
+
+../obj-gnu/./syscall/dup.o: dup.s
+	gcc  -E -x assembler-with-cpp -I. dup.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/dup.s.gnu || true
+	gas -o ../obj-gnu/./syscall/dup.o ../obj-gnu/./syscall/dup.s.gnu
+
+../obj-gnu/./syscall/dup2.o: dup2.s
+	gcc  -E -x assembler-with-cpp -I. dup2.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/dup2.s.gnu || true
+	gas -o ../obj-gnu/./syscall/dup2.o ../obj-gnu/./syscall/dup2.s.gnu
+
+../obj-gnu/./syscall/execl.o: execl.s
+	gcc  -E -x assembler-with-cpp -I. execl.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/execl.s.gnu || true
+	gas -o ../obj-gnu/./syscall/execl.o ../obj-gnu/./syscall/execl.s.gnu
+
+../obj-gnu/./syscall/execle.o: execle.s
+	gcc  -E -x assembler-with-cpp -I. execle.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/execle.s.gnu || true
+	gas -o ../obj-gnu/./syscall/execle.o ../obj-gnu/./syscall/execle.s.gnu
+
+../obj-gnu/./syscall/execlp.o: execlp.s
+	gcc  -E -x assembler-with-cpp -I. execlp.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/execlp.s.gnu || true
+	gas -o ../obj-gnu/./syscall/execlp.o ../obj-gnu/./syscall/execlp.s.gnu
+
+../obj-gnu/./syscall/execv.o: execv.s
+	gcc  -E -x assembler-with-cpp -I. execv.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/execv.s.gnu || true
+	gas -o ../obj-gnu/./syscall/execv.o ../obj-gnu/./syscall/execv.s.gnu
+
+../obj-gnu/./syscall/execve.o: execve.s
+	gcc  -E -x assembler-with-cpp -I. execve.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/execve.s.gnu || true
+	gas -o ../obj-gnu/./syscall/execve.o ../obj-gnu/./syscall/execve.s.gnu
+
+../obj-gnu/./syscall/execvp.o: execvp.s
+	gcc  -E -x assembler-with-cpp -I. execvp.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/execvp.s.gnu || true
+	gas -o ../obj-gnu/./syscall/execvp.o ../obj-gnu/./syscall/execvp.s.gnu
+
+../obj-gnu/./syscall/fcntl.o: fcntl.s
+	gcc  -E -x assembler-with-cpp -I. fcntl.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/fcntl.s.gnu || true
+	gas -o ../obj-gnu/./syscall/fcntl.o ../obj-gnu/./syscall/fcntl.s.gnu
+
+../obj-gnu/./syscall/fork.o: fork.s
+	gcc  -E -x assembler-with-cpp -I. fork.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/fork.s.gnu || true
+	gas -o ../obj-gnu/./syscall/fork.o ../obj-gnu/./syscall/fork.s.gnu
+
+../obj-gnu/./syscall/fpathconf.o: fpathconf.s
+	gcc  -E -x assembler-with-cpp -I. fpathconf.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/fpathconf.s.gnu || true
+	gas -o ../obj-gnu/./syscall/fpathconf.o ../obj-gnu/./syscall/fpathconf.s.gnu
+
+../obj-gnu/./syscall/freemem.o: freemem.s
+	gcc  -E -x assembler-with-cpp -I. freemem.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/freemem.s.gnu || true
+	gas -o ../obj-gnu/./syscall/freemem.o ../obj-gnu/./syscall/freemem.s.gnu
+
+../obj-gnu/./syscall/fstat.o: fstat.s
+	gcc  -E -x assembler-with-cpp -I. fstat.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/fstat.s.gnu || true
+	gas -o ../obj-gnu/./syscall/fstat.o ../obj-gnu/./syscall/fstat.s.gnu
+
+../obj-gnu/./syscall/fstatfs.o: fstatfs.s
+	gcc  -E -x assembler-with-cpp -I. fstatfs.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/fstatfs.s.gnu || true
+	gas -o ../obj-gnu/./syscall/fstatfs.o ../obj-gnu/./syscall/fstatfs.s.gnu
+
+../obj-gnu/./syscall/getcwd.o: getcwd.s
+	gcc  -E -x assembler-with-cpp -I. getcwd.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/getcwd.s.gnu || true
+	gas -o ../obj-gnu/./syscall/getcwd.o ../obj-gnu/./syscall/getcwd.s.gnu
+
+../obj-gnu/./syscall/getegid.o: getegid.s
+	gcc  -E -x assembler-with-cpp -I. getegid.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/getegid.s.gnu || true
+	gas -o ../obj-gnu/./syscall/getegid.o ../obj-gnu/./syscall/getegid.s.gnu
+
+../obj-gnu/./syscall/geteuid.o: geteuid.s
+	gcc  -E -x assembler-with-cpp -I. geteuid.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/geteuid.s.gnu || true
+	gas -o ../obj-gnu/./syscall/geteuid.o ../obj-gnu/./syscall/geteuid.s.gnu
+
+../obj-gnu/./syscall/getgid.o: getgid.s
+	gcc  -E -x assembler-with-cpp -I. getgid.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/getgid.s.gnu || true
+	gas -o ../obj-gnu/./syscall/getgid.o ../obj-gnu/./syscall/getgid.s.gnu
+
+../obj-gnu/./syscall/getgroups.o: getgroups.s
+	gcc  -E -x assembler-with-cpp -I. getgroups.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/getgroups.s.gnu || true
+	gas -o ../obj-gnu/./syscall/getgroups.o ../obj-gnu/./syscall/getgroups.s.gnu
+
+../obj-gnu/./syscall/getnpid.o: getnpid.s
+	gcc  -E -x assembler-with-cpp -I. getnpid.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/getnpid.s.gnu || true
+	gas -o ../obj-gnu/./syscall/getnpid.o ../obj-gnu/./syscall/getnpid.s.gnu
+
+../obj-gnu/./syscall/getnprocnr.o: getnprocnr.s
+	gcc  -E -x assembler-with-cpp -I. getnprocnr.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/getnprocnr.s.gnu || true
+	gas -o ../obj-gnu/./syscall/getnprocnr.o ../obj-gnu/./syscall/getnprocnr.s.gnu
+
+../obj-gnu/./syscall/getpgrp.o: getpgrp.s
+	gcc  -E -x assembler-with-cpp -I. getpgrp.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/getpgrp.s.gnu || true
+	gas -o ../obj-gnu/./syscall/getpgrp.o ../obj-gnu/./syscall/getpgrp.s.gnu
+
+../obj-gnu/./syscall/getpid.o: getpid.s
+	gcc  -E -x assembler-with-cpp -I. getpid.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/getpid.s.gnu || true
+	gas -o ../obj-gnu/./syscall/getpid.o ../obj-gnu/./syscall/getpid.s.gnu
+
+../obj-gnu/./syscall/getppid.o: getppid.s
+	gcc  -E -x assembler-with-cpp -I. getppid.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/getppid.s.gnu || true
+	gas -o ../obj-gnu/./syscall/getppid.o ../obj-gnu/./syscall/getppid.s.gnu
+
+../obj-gnu/./syscall/getpprocnr.o: getpprocnr.s
+	gcc  -E -x assembler-with-cpp -I. getpprocnr.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/getpprocnr.s.gnu || true
+	gas -o ../obj-gnu/./syscall/getpprocnr.o ../obj-gnu/./syscall/getpprocnr.s.gnu
+
+../obj-gnu/./syscall/getprocnr.o: getprocnr.s
+	gcc  -E -x assembler-with-cpp -I. getprocnr.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/getprocnr.s.gnu || true
+	gas -o ../obj-gnu/./syscall/getprocnr.o ../obj-gnu/./syscall/getprocnr.s.gnu
+
+../obj-gnu/./syscall/getsigset.o: getsigset.s
+	gcc  -E -x assembler-with-cpp -I. getsigset.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/getsigset.s.gnu || true
+	gas -o ../obj-gnu/./syscall/getsigset.o ../obj-gnu/./syscall/getsigset.s.gnu
+
+../obj-gnu/./syscall/getsysinfo.o: getsysinfo.s
+	gcc  -E -x assembler-with-cpp -I. getsysinfo.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/getsysinfo.s.gnu || true
+	gas -o ../obj-gnu/./syscall/getsysinfo.o ../obj-gnu/./syscall/getsysinfo.s.gnu
+
+../obj-gnu/./syscall/getuid.o: getuid.s
+	gcc  -E -x assembler-with-cpp -I. getuid.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/getuid.s.gnu || true
+	gas -o ../obj-gnu/./syscall/getuid.o ../obj-gnu/./syscall/getuid.s.gnu
+
+../obj-gnu/./syscall/ioctl.o: ioctl.s
+	gcc  -E -x assembler-with-cpp -I. ioctl.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/ioctl.s.gnu || true
+	gas -o ../obj-gnu/./syscall/ioctl.o ../obj-gnu/./syscall/ioctl.s.gnu
+
+../obj-gnu/./syscall/isatty.o: isatty.s
+	gcc  -E -x assembler-with-cpp -I. isatty.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/isatty.s.gnu || true
+	gas -o ../obj-gnu/./syscall/isatty.o ../obj-gnu/./syscall/isatty.s.gnu
+
+../obj-gnu/./syscall/kill.o: kill.s
+	gcc  -E -x assembler-with-cpp -I. kill.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/kill.s.gnu || true
+	gas -o ../obj-gnu/./syscall/kill.o ../obj-gnu/./syscall/kill.s.gnu
+
+../obj-gnu/./syscall/link.o: link.s
+	gcc  -E -x assembler-with-cpp -I. link.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/link.s.gnu || true
+	gas -o ../obj-gnu/./syscall/link.o ../obj-gnu/./syscall/link.s.gnu
+
+../obj-gnu/./syscall/lseek.o: lseek.s
+	gcc  -E -x assembler-with-cpp -I. lseek.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/lseek.s.gnu || true
+	gas -o ../obj-gnu/./syscall/lseek.o ../obj-gnu/./syscall/lseek.s.gnu
+
+../obj-gnu/./syscall/lstat.o: lstat.s
+	gcc  -E -x assembler-with-cpp -I. lstat.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/lstat.s.gnu || true
+	gas -o ../obj-gnu/./syscall/lstat.o ../obj-gnu/./syscall/lstat.s.gnu
+
+../obj-gnu/./syscall/mkdir.o: mkdir.s
+	gcc  -E -x assembler-with-cpp -I. mkdir.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/mkdir.s.gnu || true
+	gas -o ../obj-gnu/./syscall/mkdir.o ../obj-gnu/./syscall/mkdir.s.gnu
+
+../obj-gnu/./syscall/mkfifo.o: mkfifo.s
+	gcc  -E -x assembler-with-cpp -I. mkfifo.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/mkfifo.s.gnu || true
+	gas -o ../obj-gnu/./syscall/mkfifo.o ../obj-gnu/./syscall/mkfifo.s.gnu
+
+../obj-gnu/./syscall/mknod.o: mknod.s
+	gcc  -E -x assembler-with-cpp -I. mknod.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/mknod.s.gnu || true
+	gas -o ../obj-gnu/./syscall/mknod.o ../obj-gnu/./syscall/mknod.s.gnu
+
+../obj-gnu/./syscall/mount.o: mount.s
+	gcc  -E -x assembler-with-cpp -I. mount.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/mount.s.gnu || true
+	gas -o ../obj-gnu/./syscall/mount.o ../obj-gnu/./syscall/mount.s.gnu
+
+../obj-gnu/./syscall/open.o: open.s
+	gcc  -E -x assembler-with-cpp -I. open.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/open.s.gnu || true
+	gas -o ../obj-gnu/./syscall/open.o ../obj-gnu/./syscall/open.s.gnu
+
+../obj-gnu/./syscall/opendir.o: opendir.s
+	gcc  -E -x assembler-with-cpp -I. opendir.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/opendir.s.gnu || true
+	gas -o ../obj-gnu/./syscall/opendir.o ../obj-gnu/./syscall/opendir.s.gnu
+
+../obj-gnu/./syscall/pathconf.o: pathconf.s
+	gcc  -E -x assembler-with-cpp -I. pathconf.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/pathconf.s.gnu || true
+	gas -o ../obj-gnu/./syscall/pathconf.o ../obj-gnu/./syscall/pathconf.s.gnu
+
+../obj-gnu/./syscall/pause.o: pause.s
+	gcc  -E -x assembler-with-cpp -I. pause.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/pause.s.gnu || true
+	gas -o ../obj-gnu/./syscall/pause.o ../obj-gnu/./syscall/pause.s.gnu
+
+../obj-gnu/./syscall/pipe.o: pipe.s
+	gcc  -E -x assembler-with-cpp -I. pipe.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/pipe.s.gnu || true
+	gas -o ../obj-gnu/./syscall/pipe.o ../obj-gnu/./syscall/pipe.s.gnu
+
+../obj-gnu/./syscall/ptrace.o: ptrace.s
+	gcc  -E -x assembler-with-cpp -I. ptrace.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/ptrace.s.gnu || true
+	gas -o ../obj-gnu/./syscall/ptrace.o ../obj-gnu/./syscall/ptrace.s.gnu
+
+../obj-gnu/./syscall/read.o: read.s
+	gcc  -E -x assembler-with-cpp -I. read.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/read.s.gnu || true
+	gas -o ../obj-gnu/./syscall/read.o ../obj-gnu/./syscall/read.s.gnu
+
+../obj-gnu/./syscall/readdir.o: readdir.s
+	gcc  -E -x assembler-with-cpp -I. readdir.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/readdir.s.gnu || true
+	gas -o ../obj-gnu/./syscall/readdir.o ../obj-gnu/./syscall/readdir.s.gnu
+
+../obj-gnu/./syscall/readlink.o: readlink.s
+	gcc  -E -x assembler-with-cpp -I. readlink.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/readlink.s.gnu || true
+	gas -o ../obj-gnu/./syscall/readlink.o ../obj-gnu/./syscall/readlink.s.gnu
+
+../obj-gnu/./syscall/reboot.o: reboot.s
+	gcc  -E -x assembler-with-cpp -I. reboot.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/reboot.s.gnu || true
+	gas -o ../obj-gnu/./syscall/reboot.o ../obj-gnu/./syscall/reboot.s.gnu
+
+../obj-gnu/./syscall/rename.o: rename.s
+	gcc  -E -x assembler-with-cpp -I. rename.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/rename.s.gnu || true
+	gas -o ../obj-gnu/./syscall/rename.o ../obj-gnu/./syscall/rename.s.gnu
+
+../obj-gnu/./syscall/rewinddir.o: rewinddir.s
+	gcc  -E -x assembler-with-cpp -I. rewinddir.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/rewinddir.s.gnu || true
+	gas -o ../obj-gnu/./syscall/rewinddir.o ../obj-gnu/./syscall/rewinddir.s.gnu
+
+../obj-gnu/./syscall/rmdir.o: rmdir.s
+	gcc  -E -x assembler-with-cpp -I. rmdir.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/rmdir.s.gnu || true
+	gas -o ../obj-gnu/./syscall/rmdir.o ../obj-gnu/./syscall/rmdir.s.gnu
+
+../obj-gnu/./syscall/sbrk.o: sbrk.s
+	gcc  -E -x assembler-with-cpp -I. sbrk.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/sbrk.s.gnu || true
+	gas -o ../obj-gnu/./syscall/sbrk.o ../obj-gnu/./syscall/sbrk.s.gnu
+
+../obj-gnu/./syscall/seekdir.o: seekdir.s
+	gcc  -E -x assembler-with-cpp -I. seekdir.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/seekdir.s.gnu || true
+	gas -o ../obj-gnu/./syscall/seekdir.o ../obj-gnu/./syscall/seekdir.s.gnu
+
+../obj-gnu/./syscall/setgid.o: setgid.s
+	gcc  -E -x assembler-with-cpp -I. setgid.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/setgid.s.gnu || true
+	gas -o ../obj-gnu/./syscall/setgid.o ../obj-gnu/./syscall/setgid.s.gnu
+
+../obj-gnu/./syscall/setsid.o: setsid.s
+	gcc  -E -x assembler-with-cpp -I. setsid.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/setsid.s.gnu || true
+	gas -o ../obj-gnu/./syscall/setsid.o ../obj-gnu/./syscall/setsid.s.gnu
+
+../obj-gnu/./syscall/setuid.o: setuid.s
+	gcc  -E -x assembler-with-cpp -I. setuid.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/setuid.s.gnu || true
+	gas -o ../obj-gnu/./syscall/setuid.o ../obj-gnu/./syscall/setuid.s.gnu
+
+../obj-gnu/./syscall/sigaction.o: sigaction.s
+	gcc  -E -x assembler-with-cpp -I. sigaction.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/sigaction.s.gnu || true
+	gas -o ../obj-gnu/./syscall/sigaction.o ../obj-gnu/./syscall/sigaction.s.gnu
+
+../obj-gnu/./syscall/sigaddset.o: sigaddset.s
+	gcc  -E -x assembler-with-cpp -I. sigaddset.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/sigaddset.s.gnu || true
+	gas -o ../obj-gnu/./syscall/sigaddset.o ../obj-gnu/./syscall/sigaddset.s.gnu
+
+../obj-gnu/./syscall/sigdelset.o: sigdelset.s
+	gcc  -E -x assembler-with-cpp -I. sigdelset.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/sigdelset.s.gnu || true
+	gas -o ../obj-gnu/./syscall/sigdelset.o ../obj-gnu/./syscall/sigdelset.s.gnu
+
+../obj-gnu/./syscall/sigemptyset.o: sigemptyset.s
+	gcc  -E -x assembler-with-cpp -I. sigemptyset.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/sigemptyset.s.gnu || true
+	gas -o ../obj-gnu/./syscall/sigemptyset.o ../obj-gnu/./syscall/sigemptyset.s.gnu
+
+../obj-gnu/./syscall/sigfillset.o: sigfillset.s
+	gcc  -E -x assembler-with-cpp -I. sigfillset.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/sigfillset.s.gnu || true
+	gas -o ../obj-gnu/./syscall/sigfillset.o ../obj-gnu/./syscall/sigfillset.s.gnu
+
+../obj-gnu/./syscall/sigismember.o: sigismember.s
+	gcc  -E -x assembler-with-cpp -I. sigismember.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/sigismember.s.gnu || true
+	gas -o ../obj-gnu/./syscall/sigismember.o ../obj-gnu/./syscall/sigismember.s.gnu
+
+../obj-gnu/./syscall/sigpending.o: sigpending.s
+	gcc  -E -x assembler-with-cpp -I. sigpending.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/sigpending.s.gnu || true
+	gas -o ../obj-gnu/./syscall/sigpending.o ../obj-gnu/./syscall/sigpending.s.gnu
+
+../obj-gnu/./syscall/sigprocmask.o: sigprocmask.s
+	gcc  -E -x assembler-with-cpp -I. sigprocmask.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/sigprocmask.s.gnu || true
+	gas -o ../obj-gnu/./syscall/sigprocmask.o ../obj-gnu/./syscall/sigprocmask.s.gnu
+
+../obj-gnu/./syscall/sigreturn.o: sigreturn.s
+	gcc  -E -x assembler-with-cpp -I. sigreturn.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/sigreturn.s.gnu || true
+	gas -o ../obj-gnu/./syscall/sigreturn.o ../obj-gnu/./syscall/sigreturn.s.gnu
+
+../obj-gnu/./syscall/sigsuspend.o: sigsuspend.s
+	gcc  -E -x assembler-with-cpp -I. sigsuspend.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/sigsuspend.s.gnu || true
+	gas -o ../obj-gnu/./syscall/sigsuspend.o ../obj-gnu/./syscall/sigsuspend.s.gnu
+
+../obj-gnu/./syscall/sleep.o: sleep.s
+	gcc  -E -x assembler-with-cpp -I. sleep.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/sleep.s.gnu || true
+	gas -o ../obj-gnu/./syscall/sleep.o ../obj-gnu/./syscall/sleep.s.gnu
+
+../obj-gnu/./syscall/stat.o: stat.s
+	gcc  -E -x assembler-with-cpp -I. stat.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/stat.s.gnu || true
+	gas -o ../obj-gnu/./syscall/stat.o ../obj-gnu/./syscall/stat.s.gnu
+
+../obj-gnu/./syscall/stime.o: stime.s
+	gcc  -E -x assembler-with-cpp -I. stime.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/stime.s.gnu || true
+	gas -o ../obj-gnu/./syscall/stime.o ../obj-gnu/./syscall/stime.s.gnu
+
+../obj-gnu/./syscall/svrctl.o: svrctl.s
+	gcc  -E -x assembler-with-cpp -I. svrctl.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/svrctl.s.gnu || true
+	gas -o ../obj-gnu/./syscall/svrctl.o ../obj-gnu/./syscall/svrctl.s.gnu
+
+../obj-gnu/./syscall/symlink.o: symlink.s
+	gcc  -E -x assembler-with-cpp -I. symlink.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/symlink.s.gnu || true
+	gas -o ../obj-gnu/./syscall/symlink.o ../obj-gnu/./syscall/symlink.s.gnu
+
+../obj-gnu/./syscall/sync.o: sync.s
+	gcc  -E -x assembler-with-cpp -I. sync.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/sync.s.gnu || true
+	gas -o ../obj-gnu/./syscall/sync.o ../obj-gnu/./syscall/sync.s.gnu
+
+../obj-gnu/./syscall/tcdrain.o: tcdrain.s
+	gcc  -E -x assembler-with-cpp -I. tcdrain.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/tcdrain.s.gnu || true
+	gas -o ../obj-gnu/./syscall/tcdrain.o ../obj-gnu/./syscall/tcdrain.s.gnu
+
+../obj-gnu/./syscall/tcflow.o: tcflow.s
+	gcc  -E -x assembler-with-cpp -I. tcflow.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/tcflow.s.gnu || true
+	gas -o ../obj-gnu/./syscall/tcflow.o ../obj-gnu/./syscall/tcflow.s.gnu
+
+../obj-gnu/./syscall/tcflush.o: tcflush.s
+	gcc  -E -x assembler-with-cpp -I. tcflush.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/tcflush.s.gnu || true
+	gas -o ../obj-gnu/./syscall/tcflush.o ../obj-gnu/./syscall/tcflush.s.gnu
+
+../obj-gnu/./syscall/tcgetattr.o: tcgetattr.s
+	gcc  -E -x assembler-with-cpp -I. tcgetattr.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/tcgetattr.s.gnu || true
+	gas -o ../obj-gnu/./syscall/tcgetattr.o ../obj-gnu/./syscall/tcgetattr.s.gnu
+
+../obj-gnu/./syscall/tcsendbreak.o: tcsendbreak.s
+	gcc  -E -x assembler-with-cpp -I. tcsendbreak.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/tcsendbreak.s.gnu || true
+	gas -o ../obj-gnu/./syscall/tcsendbreak.o ../obj-gnu/./syscall/tcsendbreak.s.gnu
+
+../obj-gnu/./syscall/tcsetattr.o: tcsetattr.s
+	gcc  -E -x assembler-with-cpp -I. tcsetattr.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/tcsetattr.s.gnu || true
+	gas -o ../obj-gnu/./syscall/tcsetattr.o ../obj-gnu/./syscall/tcsetattr.s.gnu
+
+../obj-gnu/./syscall/time.o: time.s
+	gcc  -E -x assembler-with-cpp -I. time.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/time.s.gnu || true
+	gas -o ../obj-gnu/./syscall/time.o ../obj-gnu/./syscall/time.s.gnu
+
+../obj-gnu/./syscall/times.o: times.s
+	gcc  -E -x assembler-with-cpp -I. times.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/times.s.gnu || true
+	gas -o ../obj-gnu/./syscall/times.o ../obj-gnu/./syscall/times.s.gnu
+
+../obj-gnu/./syscall/truncate.o: truncate.s
+	gcc  -E -x assembler-with-cpp -I. truncate.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/truncate.s.gnu || true
+	gas -o ../obj-gnu/./syscall/truncate.o ../obj-gnu/./syscall/truncate.s.gnu
+
+../obj-gnu/./syscall/umask.o: umask.s
+	gcc  -E -x assembler-with-cpp -I. umask.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/umask.s.gnu || true
+	gas -o ../obj-gnu/./syscall/umask.o ../obj-gnu/./syscall/umask.s.gnu
+
+../obj-gnu/./syscall/umount.o: umount.s
+	gcc  -E -x assembler-with-cpp -I. umount.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/umount.s.gnu || true
+	gas -o ../obj-gnu/./syscall/umount.o ../obj-gnu/./syscall/umount.s.gnu
+
+../obj-gnu/./syscall/uname.o: uname.s
+	gcc  -E -x assembler-with-cpp -I. uname.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/uname.s.gnu || true
+	gas -o ../obj-gnu/./syscall/uname.o ../obj-gnu/./syscall/uname.s.gnu
+
+../obj-gnu/./syscall/unlink.o: unlink.s
+	gcc  -E -x assembler-with-cpp -I. unlink.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/unlink.s.gnu || true
+	gas -o ../obj-gnu/./syscall/unlink.o ../obj-gnu/./syscall/unlink.s.gnu
+
+../obj-gnu/./syscall/utime.o: utime.s
+	gcc  -E -x assembler-with-cpp -I. utime.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/utime.s.gnu || true
+	gas -o ../obj-gnu/./syscall/utime.o ../obj-gnu/./syscall/utime.s.gnu
+
+../obj-gnu/./syscall/wait.o: wait.s
+	gcc  -E -x assembler-with-cpp -I. wait.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/wait.s.gnu || true
+	gas -o ../obj-gnu/./syscall/wait.o ../obj-gnu/./syscall/wait.s.gnu
+
+../obj-gnu/./syscall/waitpid.o: waitpid.s
+	gcc  -E -x assembler-with-cpp -I. waitpid.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/waitpid.s.gnu || true
+	gas -o ../obj-gnu/./syscall/waitpid.o ../obj-gnu/./syscall/waitpid.s.gnu
+
+../obj-gnu/./syscall/write.o: write.s
+	gcc  -E -x assembler-with-cpp -I. write.s | asmconv -mi386 ack gnu > ../obj-gnu/./syscall/write.s.gnu || true
+	gas -o ../obj-gnu/./syscall/write.o ../obj-gnu/./syscall/write.s.gnu
+
+
+
+
+clean::
+	rm -f ../obj-ack//./syscall/*
+	rm -f ../obj-gnu/./syscall/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/syscall/Makefile.in
===================================================================
--- /trunk/minix/lib/syscall/Makefile.in	(revision 9)
+++ /trunk/minix/lib/syscall/Makefile.in	(revision 9)
@@ -0,0 +1,115 @@
+# Makefile for lib/syscall.
+
+LIBRARIES=libc
+
+libc_FILES=" \
+	_exit.s \
+	_pm_findproc.s \
+	access.s \
+	alarm.s \
+	allocmem.s \
+	brk.s \
+	cfgetispeed.s \
+	cfgetospeed.s \
+	cfsetispeed.s \
+	cfsetospeed.s \
+	chdir.s \
+	chmod.s \
+	chown.s \
+	chroot.s \
+	close.s \
+	closedir.s \
+	creat.s \
+	devctl.s \
+	dup.s \
+	dup2.s \
+	execl.s \
+	execle.s \
+	execlp.s \
+	execv.s \
+	execve.s \
+	execvp.s \
+	fcntl.s \
+	fork.s \
+	fpathconf.s \
+	freemem.s \
+	fstat.s \
+	fstatfs.s \
+	getcwd.s \
+	getegid.s \
+	geteuid.s \
+	getgid.s \
+	getgroups.s \
+	getnpid.s \
+	getnprocnr.s \
+	getpgrp.s \
+	getpid.s \
+	getppid.s \
+	getpprocnr.s \
+	getprocnr.s \
+	getsigset.s \
+	getsysinfo.s \
+	getuid.s \
+	ioctl.s \
+	isatty.s \
+	kill.s \
+	link.s \
+	lseek.s \
+	lstat.s \
+	mkdir.s \
+	mkfifo.s \
+	mknod.s \
+	mount.s \
+	open.s \
+	opendir.s \
+	pathconf.s \
+	pause.s \
+	pipe.s \
+	ptrace.s \
+	read.s \
+	readdir.s \
+	readlink.s \
+	reboot.s \
+	rename.s \
+	rewinddir.s \
+	rmdir.s \
+	sbrk.s \
+	seekdir.s \
+	setgid.s \
+	setsid.s \
+	setuid.s \
+	sigaction.s \
+	sigaddset.s \
+	sigdelset.s \
+	sigemptyset.s \
+	sigfillset.s \
+	sigismember.s \
+	sigpending.s \
+	sigprocmask.s \
+	sigreturn.s \
+	sigsuspend.s \
+	sleep.s \
+	stat.s \
+	stime.s \
+	svrctl.s \
+	symlink.s \
+	sync.s \
+	tcdrain.s \
+	tcflow.s \
+	tcflush.s \
+	tcgetattr.s \
+	tcsendbreak.s \
+	tcsetattr.s \
+	time.s \
+	times.s \
+	truncate.s \
+	umask.s \
+	umount.s \
+	uname.s \
+	unlink.s \
+	utime.s \
+	wait.s \
+	waitpid.s \
+	write.s"
+
+TYPE=both
Index: /trunk/minix/lib/syscall/_exit.s
===================================================================
--- /trunk/minix/lib/syscall/_exit.s	(revision 9)
+++ /trunk/minix/lib/syscall/_exit.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	___exit
+.define	__exit
+.align 2
+
+__exit:
+	jmp	___exit
Index: /trunk/minix/lib/syscall/_pm_findproc.s
===================================================================
--- /trunk/minix/lib/syscall/_pm_findproc.s	(revision 9)
+++ /trunk/minix/lib/syscall/_pm_findproc.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	___pm_findproc
+.define	__pm_findproc
+.align 2
+
+__pm_findproc:
+	jmp	___pm_findproc
Index: /trunk/minix/lib/syscall/access.s
===================================================================
--- /trunk/minix/lib/syscall/access.s	(revision 9)
+++ /trunk/minix/lib/syscall/access.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__access
+.define	_access
+.align 2
+
+_access:
+	jmp	__access
Index: /trunk/minix/lib/syscall/alarm.s
===================================================================
--- /trunk/minix/lib/syscall/alarm.s	(revision 9)
+++ /trunk/minix/lib/syscall/alarm.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__alarm
+.define	_alarm
+.align 2
+
+_alarm:
+	jmp	__alarm
Index: /trunk/minix/lib/syscall/allocmem.s
===================================================================
--- /trunk/minix/lib/syscall/allocmem.s	(revision 9)
+++ /trunk/minix/lib/syscall/allocmem.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__allocmem
+.define	_allocmem
+.align 2
+
+_allocmem:
+	jmp	__allocmem
Index: /trunk/minix/lib/syscall/brk.s
===================================================================
--- /trunk/minix/lib/syscall/brk.s	(revision 9)
+++ /trunk/minix/lib/syscall/brk.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__brk
+.define	_brk
+.align 2
+
+_brk:
+	jmp	__brk
Index: /trunk/minix/lib/syscall/cfgetispeed.s
===================================================================
--- /trunk/minix/lib/syscall/cfgetispeed.s	(revision 9)
+++ /trunk/minix/lib/syscall/cfgetispeed.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__cfgetispeed
+.define	_cfgetispeed
+.align 2
+
+_cfgetispeed:
+	jmp	__cfgetispeed
Index: /trunk/minix/lib/syscall/cfgetospeed.s
===================================================================
--- /trunk/minix/lib/syscall/cfgetospeed.s	(revision 9)
+++ /trunk/minix/lib/syscall/cfgetospeed.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__cfgetospeed
+.define	_cfgetospeed
+.align 2
+
+_cfgetospeed:
+	jmp	__cfgetospeed
Index: /trunk/minix/lib/syscall/cfsetispeed.s
===================================================================
--- /trunk/minix/lib/syscall/cfsetispeed.s	(revision 9)
+++ /trunk/minix/lib/syscall/cfsetispeed.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__cfsetispeed
+.define	_cfsetispeed
+.align 2
+
+_cfsetispeed:
+	jmp	__cfsetispeed
Index: /trunk/minix/lib/syscall/cfsetospeed.s
===================================================================
--- /trunk/minix/lib/syscall/cfsetospeed.s	(revision 9)
+++ /trunk/minix/lib/syscall/cfsetospeed.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__cfsetospeed
+.define	_cfsetospeed
+.align 2
+
+_cfsetospeed:
+	jmp	__cfsetospeed
Index: /trunk/minix/lib/syscall/chdir.s
===================================================================
--- /trunk/minix/lib/syscall/chdir.s	(revision 9)
+++ /trunk/minix/lib/syscall/chdir.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text
+.extern	__chdir
+.define	_chdir
+.extern	__fchdir
+.define	_fchdir
+.align 2
+
+_chdir:
+	jmp	__chdir
+_fchdir:
+	jmp	__fchdir
Index: /trunk/minix/lib/syscall/chmod.s
===================================================================
--- /trunk/minix/lib/syscall/chmod.s	(revision 9)
+++ /trunk/minix/lib/syscall/chmod.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__chmod
+.define	_chmod
+.align 2
+
+_chmod:
+	jmp	__chmod
Index: /trunk/minix/lib/syscall/chown.s
===================================================================
--- /trunk/minix/lib/syscall/chown.s	(revision 9)
+++ /trunk/minix/lib/syscall/chown.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__chown
+.define	_chown
+.align 2
+
+_chown:
+	jmp	__chown
Index: /trunk/minix/lib/syscall/chroot.s
===================================================================
--- /trunk/minix/lib/syscall/chroot.s	(revision 9)
+++ /trunk/minix/lib/syscall/chroot.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__chroot
+.define	_chroot
+.align 2
+
+_chroot:
+	jmp	__chroot
Index: /trunk/minix/lib/syscall/close.s
===================================================================
--- /trunk/minix/lib/syscall/close.s	(revision 9)
+++ /trunk/minix/lib/syscall/close.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__close
+.define	_close
+.align 2
+
+_close:
+	jmp	__close
Index: /trunk/minix/lib/syscall/closedir.s
===================================================================
--- /trunk/minix/lib/syscall/closedir.s	(revision 9)
+++ /trunk/minix/lib/syscall/closedir.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__closedir
+.define	_closedir
+.align 2
+
+_closedir:
+	jmp	__closedir
Index: /trunk/minix/lib/syscall/creat.s
===================================================================
--- /trunk/minix/lib/syscall/creat.s	(revision 9)
+++ /trunk/minix/lib/syscall/creat.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__creat
+.define	_creat
+.align 2
+
+_creat:
+	jmp	__creat
Index: /trunk/minix/lib/syscall/devctl.s
===================================================================
--- /trunk/minix/lib/syscall/devctl.s	(revision 9)
+++ /trunk/minix/lib/syscall/devctl.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__devctl
+.define	_devctl
+.align 2
+
+_devctl:
+	jmp	__devctl
Index: /trunk/minix/lib/syscall/dup.s
===================================================================
--- /trunk/minix/lib/syscall/dup.s	(revision 9)
+++ /trunk/minix/lib/syscall/dup.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__dup
+.define	_dup
+.align 2
+
+_dup:
+	jmp	__dup
Index: /trunk/minix/lib/syscall/dup2.s
===================================================================
--- /trunk/minix/lib/syscall/dup2.s	(revision 9)
+++ /trunk/minix/lib/syscall/dup2.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__dup2
+.define	_dup2
+.align 2
+
+_dup2:
+	jmp	__dup2
Index: /trunk/minix/lib/syscall/execl.s
===================================================================
--- /trunk/minix/lib/syscall/execl.s	(revision 9)
+++ /trunk/minix/lib/syscall/execl.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__execl
+.define	_execl
+.align 2
+
+_execl:
+	jmp	__execl
Index: /trunk/minix/lib/syscall/execle.s
===================================================================
--- /trunk/minix/lib/syscall/execle.s	(revision 9)
+++ /trunk/minix/lib/syscall/execle.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__execle
+.define	_execle
+.align 2
+
+_execle:
+	jmp	__execle
Index: /trunk/minix/lib/syscall/execlp.s
===================================================================
--- /trunk/minix/lib/syscall/execlp.s	(revision 9)
+++ /trunk/minix/lib/syscall/execlp.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__execlp
+.define	_execlp
+.align 2
+
+_execlp:
+	jmp	__execlp
Index: /trunk/minix/lib/syscall/execv.s
===================================================================
--- /trunk/minix/lib/syscall/execv.s	(revision 9)
+++ /trunk/minix/lib/syscall/execv.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__execv
+.define	_execv
+.align 2
+
+_execv:
+	jmp	__execv
Index: /trunk/minix/lib/syscall/execve.s
===================================================================
--- /trunk/minix/lib/syscall/execve.s	(revision 9)
+++ /trunk/minix/lib/syscall/execve.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__execve
+.define	_execve
+.align 2
+
+_execve:
+	jmp	__execve
Index: /trunk/minix/lib/syscall/execvp.s
===================================================================
--- /trunk/minix/lib/syscall/execvp.s	(revision 9)
+++ /trunk/minix/lib/syscall/execvp.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__execvp
+.define	_execvp
+.align 2
+
+_execvp:
+	jmp	__execvp
Index: /trunk/minix/lib/syscall/fcntl.s
===================================================================
--- /trunk/minix/lib/syscall/fcntl.s	(revision 9)
+++ /trunk/minix/lib/syscall/fcntl.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__fcntl
+.define	_fcntl
+.align 2
+
+_fcntl:
+	jmp	__fcntl
Index: /trunk/minix/lib/syscall/fork.s
===================================================================
--- /trunk/minix/lib/syscall/fork.s	(revision 9)
+++ /trunk/minix/lib/syscall/fork.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__fork
+.define	_fork
+.align 2
+
+_fork:
+	jmp	__fork
Index: /trunk/minix/lib/syscall/fpathconf.s
===================================================================
--- /trunk/minix/lib/syscall/fpathconf.s	(revision 9)
+++ /trunk/minix/lib/syscall/fpathconf.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__fpathconf
+.define	_fpathconf
+.align 2
+
+_fpathconf:
+	jmp	__fpathconf
Index: /trunk/minix/lib/syscall/freemem.s
===================================================================
--- /trunk/minix/lib/syscall/freemem.s	(revision 9)
+++ /trunk/minix/lib/syscall/freemem.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__freemem
+.define	_freemem
+.align 2
+
+_freemem:
+	jmp	__freemem
Index: /trunk/minix/lib/syscall/fstat.s
===================================================================
--- /trunk/minix/lib/syscall/fstat.s	(revision 9)
+++ /trunk/minix/lib/syscall/fstat.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__fstat
+.define	_fstat
+.align 2
+
+_fstat:
+	jmp	__fstat
Index: /trunk/minix/lib/syscall/fstatfs.s
===================================================================
--- /trunk/minix/lib/syscall/fstatfs.s	(revision 9)
+++ /trunk/minix/lib/syscall/fstatfs.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__fstatfs
+.define	_fstatfs
+.align 2
+
+_fstatfs:
+	jmp	__fstatfs
Index: /trunk/minix/lib/syscall/getcwd.s
===================================================================
--- /trunk/minix/lib/syscall/getcwd.s	(revision 9)
+++ /trunk/minix/lib/syscall/getcwd.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__getcwd
+.define	_getcwd
+.align 2
+
+_getcwd:
+	jmp	__getcwd
Index: /trunk/minix/lib/syscall/getegid.s
===================================================================
--- /trunk/minix/lib/syscall/getegid.s	(revision 9)
+++ /trunk/minix/lib/syscall/getegid.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__getegid
+.define	_getegid
+.align 2
+
+_getegid:
+	jmp	__getegid
Index: /trunk/minix/lib/syscall/geteuid.s
===================================================================
--- /trunk/minix/lib/syscall/geteuid.s	(revision 9)
+++ /trunk/minix/lib/syscall/geteuid.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__geteuid
+.define	_geteuid
+.align 2
+
+_geteuid:
+	jmp	__geteuid
Index: /trunk/minix/lib/syscall/getgid.s
===================================================================
--- /trunk/minix/lib/syscall/getgid.s	(revision 9)
+++ /trunk/minix/lib/syscall/getgid.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__getgid
+.define	_getgid
+.align 2
+
+_getgid:
+	jmp	__getgid
Index: /trunk/minix/lib/syscall/getgroups.s
===================================================================
--- /trunk/minix/lib/syscall/getgroups.s	(revision 9)
+++ /trunk/minix/lib/syscall/getgroups.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__getgroups
+.define	_getgroups
+.align 2
+
+_getgroups:
+	jmp	__getgroups
Index: /trunk/minix/lib/syscall/getnpid.s
===================================================================
--- /trunk/minix/lib/syscall/getnpid.s	(revision 9)
+++ /trunk/minix/lib/syscall/getnpid.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__getnpid
+.define	_getnpid
+.align 2
+
+_getnpid:
+	jmp	__getnpid
Index: /trunk/minix/lib/syscall/getnprocnr.s
===================================================================
--- /trunk/minix/lib/syscall/getnprocnr.s	(revision 9)
+++ /trunk/minix/lib/syscall/getnprocnr.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__getnprocnr
+.define	_getnprocnr
+.align 2
+
+_getnprocnr:
+	jmp	__getnprocnr
Index: /trunk/minix/lib/syscall/getpgrp.s
===================================================================
--- /trunk/minix/lib/syscall/getpgrp.s	(revision 9)
+++ /trunk/minix/lib/syscall/getpgrp.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__getpgrp
+.define	_getpgrp
+.align 2
+
+_getpgrp:
+	jmp	__getpgrp
Index: /trunk/minix/lib/syscall/getpid.s
===================================================================
--- /trunk/minix/lib/syscall/getpid.s	(revision 9)
+++ /trunk/minix/lib/syscall/getpid.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__getpid
+.define	_getpid
+.align 2
+
+_getpid:
+	jmp	__getpid
Index: /trunk/minix/lib/syscall/getppid.s
===================================================================
--- /trunk/minix/lib/syscall/getppid.s	(revision 9)
+++ /trunk/minix/lib/syscall/getppid.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__getppid
+.define	_getppid
+.align 2
+
+_getppid:
+	jmp	__getppid
Index: /trunk/minix/lib/syscall/getpprocnr.s
===================================================================
--- /trunk/minix/lib/syscall/getpprocnr.s	(revision 9)
+++ /trunk/minix/lib/syscall/getpprocnr.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__getpprocnr
+.define	_getpprocnr
+.align 2
+
+_getpprocnr:
+	jmp	__getpprocnr
Index: /trunk/minix/lib/syscall/getprocnr.s
===================================================================
--- /trunk/minix/lib/syscall/getprocnr.s	(revision 9)
+++ /trunk/minix/lib/syscall/getprocnr.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__getprocnr
+.define	_getprocnr
+.align 2
+
+_getprocnr:
+	jmp	__getprocnr
Index: /trunk/minix/lib/syscall/getsigset.s
===================================================================
--- /trunk/minix/lib/syscall/getsigset.s	(revision 9)
+++ /trunk/minix/lib/syscall/getsigset.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__getsigset
+.define	_getsigset
+.align 2
+
+_getsigset:
+	jmp	__getsigset
Index: /trunk/minix/lib/syscall/getsysinfo.s
===================================================================
--- /trunk/minix/lib/syscall/getsysinfo.s	(revision 9)
+++ /trunk/minix/lib/syscall/getsysinfo.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__getsysinfo
+.define	_getsysinfo
+.align 2
+
+_getsysinfo:
+	jmp	__getsysinfo
Index: /trunk/minix/lib/syscall/getuid.s
===================================================================
--- /trunk/minix/lib/syscall/getuid.s	(revision 9)
+++ /trunk/minix/lib/syscall/getuid.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__getuid
+.define	_getuid
+.align 2
+
+_getuid:
+	jmp	__getuid
Index: /trunk/minix/lib/syscall/ioctl.s
===================================================================
--- /trunk/minix/lib/syscall/ioctl.s	(revision 9)
+++ /trunk/minix/lib/syscall/ioctl.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__ioctl
+.define	_ioctl
+.align 2
+
+_ioctl:
+	jmp	__ioctl
Index: /trunk/minix/lib/syscall/isatty.s
===================================================================
--- /trunk/minix/lib/syscall/isatty.s	(revision 9)
+++ /trunk/minix/lib/syscall/isatty.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__isatty
+.define	_isatty
+.align 2
+
+_isatty:
+	jmp	__isatty
Index: /trunk/minix/lib/syscall/kill.s
===================================================================
--- /trunk/minix/lib/syscall/kill.s	(revision 9)
+++ /trunk/minix/lib/syscall/kill.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__kill
+.define	_kill
+.align 2
+
+_kill:
+	jmp	__kill
Index: /trunk/minix/lib/syscall/link.s
===================================================================
--- /trunk/minix/lib/syscall/link.s	(revision 9)
+++ /trunk/minix/lib/syscall/link.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__link
+.define	_link
+.align 2
+
+_link:
+	jmp	__link
Index: /trunk/minix/lib/syscall/lseek.s
===================================================================
--- /trunk/minix/lib/syscall/lseek.s	(revision 9)
+++ /trunk/minix/lib/syscall/lseek.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__lseek
+.define	_lseek
+.align 2
+
+_lseek:
+	jmp	__lseek
Index: /trunk/minix/lib/syscall/lstat.s
===================================================================
--- /trunk/minix/lib/syscall/lstat.s	(revision 9)
+++ /trunk/minix/lib/syscall/lstat.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__lstat
+.define	_lstat
+.align 2
+
+_lstat:
+	jmp	__lstat
Index: /trunk/minix/lib/syscall/mkdir.s
===================================================================
--- /trunk/minix/lib/syscall/mkdir.s	(revision 9)
+++ /trunk/minix/lib/syscall/mkdir.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__mkdir
+.define	_mkdir
+.align 2
+
+_mkdir:
+	jmp	__mkdir
Index: /trunk/minix/lib/syscall/mkfifo.s
===================================================================
--- /trunk/minix/lib/syscall/mkfifo.s	(revision 9)
+++ /trunk/minix/lib/syscall/mkfifo.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__mkfifo
+.define	_mkfifo
+.align 2
+
+_mkfifo:
+	jmp	__mkfifo
Index: /trunk/minix/lib/syscall/mknod.s
===================================================================
--- /trunk/minix/lib/syscall/mknod.s	(revision 9)
+++ /trunk/minix/lib/syscall/mknod.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__mknod
+.define	_mknod
+.align 2
+
+_mknod:
+	jmp	__mknod
Index: /trunk/minix/lib/syscall/mount.s
===================================================================
--- /trunk/minix/lib/syscall/mount.s	(revision 9)
+++ /trunk/minix/lib/syscall/mount.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__mount
+.define	_mount
+.align 2
+
+_mount:
+	jmp	__mount
Index: /trunk/minix/lib/syscall/open.s
===================================================================
--- /trunk/minix/lib/syscall/open.s	(revision 9)
+++ /trunk/minix/lib/syscall/open.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__open
+.define	_open
+.align 2
+
+_open:
+	jmp	__open
Index: /trunk/minix/lib/syscall/opendir.s
===================================================================
--- /trunk/minix/lib/syscall/opendir.s	(revision 9)
+++ /trunk/minix/lib/syscall/opendir.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__opendir
+.define	_opendir
+.align 2
+
+_opendir:
+	jmp	__opendir
Index: /trunk/minix/lib/syscall/pathconf.s
===================================================================
--- /trunk/minix/lib/syscall/pathconf.s	(revision 9)
+++ /trunk/minix/lib/syscall/pathconf.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__pathconf
+.define	_pathconf
+.align 2
+
+_pathconf:
+	jmp	__pathconf
Index: /trunk/minix/lib/syscall/pause.s
===================================================================
--- /trunk/minix/lib/syscall/pause.s	(revision 9)
+++ /trunk/minix/lib/syscall/pause.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__pause
+.define	_pause
+.align 2
+
+_pause:
+	jmp	__pause
Index: /trunk/minix/lib/syscall/pipe.s
===================================================================
--- /trunk/minix/lib/syscall/pipe.s	(revision 9)
+++ /trunk/minix/lib/syscall/pipe.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__pipe
+.define	_pipe
+.align 2
+
+_pipe:
+	jmp	__pipe
Index: /trunk/minix/lib/syscall/ptrace.s
===================================================================
--- /trunk/minix/lib/syscall/ptrace.s	(revision 9)
+++ /trunk/minix/lib/syscall/ptrace.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__ptrace
+.define	_ptrace
+.align 2
+
+_ptrace:
+	jmp	__ptrace
Index: /trunk/minix/lib/syscall/read.s
===================================================================
--- /trunk/minix/lib/syscall/read.s	(revision 9)
+++ /trunk/minix/lib/syscall/read.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__read
+.define	_read
+.align 2
+
+_read:
+	jmp	__read
Index: /trunk/minix/lib/syscall/readdir.s
===================================================================
--- /trunk/minix/lib/syscall/readdir.s	(revision 9)
+++ /trunk/minix/lib/syscall/readdir.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__readdir
+.define	_readdir
+.align 2
+
+_readdir:
+	jmp	__readdir
Index: /trunk/minix/lib/syscall/readlink.s
===================================================================
--- /trunk/minix/lib/syscall/readlink.s	(revision 9)
+++ /trunk/minix/lib/syscall/readlink.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__readlink
+.define	_readlink
+.align 2
+
+_readlink:
+	jmp	__readlink
Index: /trunk/minix/lib/syscall/reboot.s
===================================================================
--- /trunk/minix/lib/syscall/reboot.s	(revision 9)
+++ /trunk/minix/lib/syscall/reboot.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__reboot
+.define	_reboot
+.align 2
+
+_reboot:
+	jmp	__reboot
Index: /trunk/minix/lib/syscall/rename.s
===================================================================
--- /trunk/minix/lib/syscall/rename.s	(revision 9)
+++ /trunk/minix/lib/syscall/rename.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__rename
+.define	_rename
+.align 2
+
+_rename:
+	jmp	__rename
Index: /trunk/minix/lib/syscall/rewinddir.s
===================================================================
--- /trunk/minix/lib/syscall/rewinddir.s	(revision 9)
+++ /trunk/minix/lib/syscall/rewinddir.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__rewinddir
+.define	_rewinddir
+.align 2
+
+_rewinddir:
+	jmp	__rewinddir
Index: /trunk/minix/lib/syscall/rmdir.s
===================================================================
--- /trunk/minix/lib/syscall/rmdir.s	(revision 9)
+++ /trunk/minix/lib/syscall/rmdir.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__rmdir
+.define	_rmdir
+.align 2
+
+_rmdir:
+	jmp	__rmdir
Index: /trunk/minix/lib/syscall/sbrk.s
===================================================================
--- /trunk/minix/lib/syscall/sbrk.s	(revision 9)
+++ /trunk/minix/lib/syscall/sbrk.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__sbrk
+.define	_sbrk
+.align 2
+
+_sbrk:
+	jmp	__sbrk
Index: /trunk/minix/lib/syscall/seekdir.s
===================================================================
--- /trunk/minix/lib/syscall/seekdir.s	(revision 9)
+++ /trunk/minix/lib/syscall/seekdir.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__seekdir
+.define	_seekdir
+.align 2
+
+_seekdir:
+	jmp	__seekdir
Index: /trunk/minix/lib/syscall/setgid.s
===================================================================
--- /trunk/minix/lib/syscall/setgid.s	(revision 9)
+++ /trunk/minix/lib/syscall/setgid.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text
+.extern	__setgid
+.define	_setgid
+.define	_setegid
+.align 2
+
+_setgid:
+	jmp	__setgid
+
+_setegid:
+	jmp	__setegid
Index: /trunk/minix/lib/syscall/setsid.s
===================================================================
--- /trunk/minix/lib/syscall/setsid.s	(revision 9)
+++ /trunk/minix/lib/syscall/setsid.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__setsid
+.define	_setsid
+.align 2
+
+_setsid:
+	jmp	__setsid
Index: /trunk/minix/lib/syscall/setuid.s
===================================================================
--- /trunk/minix/lib/syscall/setuid.s	(revision 9)
+++ /trunk/minix/lib/syscall/setuid.s	(revision 9)
@@ -0,0 +1,11 @@
+.sect .text
+.extern	__setuid
+.define	_setuid
+.define	_seteuid
+.align 2
+
+_setuid:
+	jmp	__setuid
+
+_seteuid:
+	jmp	__seteuid
Index: /trunk/minix/lib/syscall/sigaction.s
===================================================================
--- /trunk/minix/lib/syscall/sigaction.s	(revision 9)
+++ /trunk/minix/lib/syscall/sigaction.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__sigaction
+.define	_sigaction
+.align 2
+
+_sigaction:
+	jmp	__sigaction
Index: /trunk/minix/lib/syscall/sigaddset.s
===================================================================
--- /trunk/minix/lib/syscall/sigaddset.s	(revision 9)
+++ /trunk/minix/lib/syscall/sigaddset.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__sigaddset
+.define	_sigaddset
+.align 2
+
+_sigaddset:
+	jmp	__sigaddset
Index: /trunk/minix/lib/syscall/sigdelset.s
===================================================================
--- /trunk/minix/lib/syscall/sigdelset.s	(revision 9)
+++ /trunk/minix/lib/syscall/sigdelset.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__sigdelset
+.define	_sigdelset
+.align 2
+
+_sigdelset:
+	jmp	__sigdelset
Index: /trunk/minix/lib/syscall/sigemptyset.s
===================================================================
--- /trunk/minix/lib/syscall/sigemptyset.s	(revision 9)
+++ /trunk/minix/lib/syscall/sigemptyset.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__sigemptyset
+.define	_sigemptyset
+.align 2
+
+_sigemptyset:
+	jmp	__sigemptyset
Index: /trunk/minix/lib/syscall/sigfillset.s
===================================================================
--- /trunk/minix/lib/syscall/sigfillset.s	(revision 9)
+++ /trunk/minix/lib/syscall/sigfillset.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__sigfillset
+.define	_sigfillset
+.align 2
+
+_sigfillset:
+	jmp	__sigfillset
Index: /trunk/minix/lib/syscall/sigismember.s
===================================================================
--- /trunk/minix/lib/syscall/sigismember.s	(revision 9)
+++ /trunk/minix/lib/syscall/sigismember.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__sigismember
+.define	_sigismember
+.align 2
+
+_sigismember:
+	jmp	__sigismember
Index: /trunk/minix/lib/syscall/sigpending.s
===================================================================
--- /trunk/minix/lib/syscall/sigpending.s	(revision 9)
+++ /trunk/minix/lib/syscall/sigpending.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__sigpending
+.define	_sigpending
+.align 2
+
+_sigpending:
+	jmp	__sigpending
Index: /trunk/minix/lib/syscall/sigprocmask.s
===================================================================
--- /trunk/minix/lib/syscall/sigprocmask.s	(revision 9)
+++ /trunk/minix/lib/syscall/sigprocmask.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__sigprocmask
+.define	_sigprocmask
+.align 2
+
+_sigprocmask:
+	jmp	__sigprocmask
Index: /trunk/minix/lib/syscall/sigreturn.s
===================================================================
--- /trunk/minix/lib/syscall/sigreturn.s	(revision 9)
+++ /trunk/minix/lib/syscall/sigreturn.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__sigreturn
+.define	_sigreturn
+.align 2
+
+_sigreturn:
+	jmp	__sigreturn
Index: /trunk/minix/lib/syscall/sigsuspend.s
===================================================================
--- /trunk/minix/lib/syscall/sigsuspend.s	(revision 9)
+++ /trunk/minix/lib/syscall/sigsuspend.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__sigsuspend
+.define	_sigsuspend
+.align 2
+
+_sigsuspend:
+	jmp	__sigsuspend
Index: /trunk/minix/lib/syscall/sleep.s
===================================================================
--- /trunk/minix/lib/syscall/sleep.s	(revision 9)
+++ /trunk/minix/lib/syscall/sleep.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__sleep
+.define	_sleep
+.align 2
+
+_sleep:
+	jmp	__sleep
Index: /trunk/minix/lib/syscall/stat.s
===================================================================
--- /trunk/minix/lib/syscall/stat.s	(revision 9)
+++ /trunk/minix/lib/syscall/stat.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__stat
+.define	_stat
+.align 2
+
+_stat:
+	jmp	__stat
Index: /trunk/minix/lib/syscall/stime.s
===================================================================
--- /trunk/minix/lib/syscall/stime.s	(revision 9)
+++ /trunk/minix/lib/syscall/stime.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__stime
+.define	_stime
+.align 2
+
+_stime:
+	jmp	__stime
Index: /trunk/minix/lib/syscall/svrctl.s
===================================================================
--- /trunk/minix/lib/syscall/svrctl.s	(revision 9)
+++ /trunk/minix/lib/syscall/svrctl.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__svrctl
+.define	_svrctl
+.align 2
+
+_svrctl:
+	jmp	__svrctl
Index: /trunk/minix/lib/syscall/symlink.s
===================================================================
--- /trunk/minix/lib/syscall/symlink.s	(revision 9)
+++ /trunk/minix/lib/syscall/symlink.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__symlink
+.define	_symlink
+.align 2
+
+_symlink:
+	jmp	__symlink
Index: /trunk/minix/lib/syscall/sync.s
===================================================================
--- /trunk/minix/lib/syscall/sync.s	(revision 9)
+++ /trunk/minix/lib/syscall/sync.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__sync
+.define	_sync
+.align 2
+
+_sync:
+	jmp	__sync
Index: /trunk/minix/lib/syscall/tcdrain.s
===================================================================
--- /trunk/minix/lib/syscall/tcdrain.s	(revision 9)
+++ /trunk/minix/lib/syscall/tcdrain.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__tcdrain
+.define	_tcdrain
+.align 2
+
+_tcdrain:
+	jmp	__tcdrain
Index: /trunk/minix/lib/syscall/tcflow.s
===================================================================
--- /trunk/minix/lib/syscall/tcflow.s	(revision 9)
+++ /trunk/minix/lib/syscall/tcflow.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__tcflow
+.define	_tcflow
+.align 2
+
+_tcflow:
+	jmp	__tcflow
Index: /trunk/minix/lib/syscall/tcflush.s
===================================================================
--- /trunk/minix/lib/syscall/tcflush.s	(revision 9)
+++ /trunk/minix/lib/syscall/tcflush.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__tcflush
+.define	_tcflush
+.align 2
+
+_tcflush:
+	jmp	__tcflush
Index: /trunk/minix/lib/syscall/tcgetattr.s
===================================================================
--- /trunk/minix/lib/syscall/tcgetattr.s	(revision 9)
+++ /trunk/minix/lib/syscall/tcgetattr.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__tcgetattr
+.define	_tcgetattr
+.align 2
+
+_tcgetattr:
+	jmp	__tcgetattr
Index: /trunk/minix/lib/syscall/tcsendbreak.s
===================================================================
--- /trunk/minix/lib/syscall/tcsendbreak.s	(revision 9)
+++ /trunk/minix/lib/syscall/tcsendbreak.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__tcsendbreak
+.define	_tcsendbreak
+.align 2
+
+_tcsendbreak:
+	jmp	__tcsendbreak
Index: /trunk/minix/lib/syscall/tcsetattr.s
===================================================================
--- /trunk/minix/lib/syscall/tcsetattr.s	(revision 9)
+++ /trunk/minix/lib/syscall/tcsetattr.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__tcsetattr
+.define	_tcsetattr
+.align 2
+
+_tcsetattr:
+	jmp	__tcsetattr
Index: /trunk/minix/lib/syscall/time.s
===================================================================
--- /trunk/minix/lib/syscall/time.s	(revision 9)
+++ /trunk/minix/lib/syscall/time.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__time
+.define	_time
+.align 2
+
+_time:
+	jmp	__time
Index: /trunk/minix/lib/syscall/times.s
===================================================================
--- /trunk/minix/lib/syscall/times.s	(revision 9)
+++ /trunk/minix/lib/syscall/times.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__times
+.define	_times
+.align 2
+
+_times:
+	jmp	__times
Index: /trunk/minix/lib/syscall/truncate.s
===================================================================
--- /trunk/minix/lib/syscall/truncate.s	(revision 9)
+++ /trunk/minix/lib/syscall/truncate.s	(revision 9)
@@ -0,0 +1,13 @@
+.sect .text
+.extern	__truncate
+.extern	__ftruncate
+.define	_truncate
+.define	_ftruncate
+.align 2
+
+_truncate:
+	jmp	__truncate
+
+.align 2
+_ftruncate:
+	jmp	__ftruncate
Index: /trunk/minix/lib/syscall/umask.s
===================================================================
--- /trunk/minix/lib/syscall/umask.s	(revision 9)
+++ /trunk/minix/lib/syscall/umask.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__umask
+.define	_umask
+.align 2
+
+_umask:
+	jmp	__umask
Index: /trunk/minix/lib/syscall/umount.s
===================================================================
--- /trunk/minix/lib/syscall/umount.s	(revision 9)
+++ /trunk/minix/lib/syscall/umount.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__umount
+.define	_umount
+.align 2
+
+_umount:
+	jmp	__umount
Index: /trunk/minix/lib/syscall/uname.s
===================================================================
--- /trunk/minix/lib/syscall/uname.s	(revision 9)
+++ /trunk/minix/lib/syscall/uname.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__uname
+.define	_uname
+.align 2
+
+_uname:
+	jmp	__uname
Index: /trunk/minix/lib/syscall/unlink.s
===================================================================
--- /trunk/minix/lib/syscall/unlink.s	(revision 9)
+++ /trunk/minix/lib/syscall/unlink.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__unlink
+.define	_unlink
+.align 2
+
+_unlink:
+	jmp	__unlink
Index: /trunk/minix/lib/syscall/utime.s
===================================================================
--- /trunk/minix/lib/syscall/utime.s	(revision 9)
+++ /trunk/minix/lib/syscall/utime.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__utime
+.define	_utime
+.align 2
+
+_utime:
+	jmp	__utime
Index: /trunk/minix/lib/syscall/wait.s
===================================================================
--- /trunk/minix/lib/syscall/wait.s	(revision 9)
+++ /trunk/minix/lib/syscall/wait.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__wait
+.define	_wait
+.align 2
+
+_wait:
+	jmp	__wait
Index: /trunk/minix/lib/syscall/waitpid.s
===================================================================
--- /trunk/minix/lib/syscall/waitpid.s	(revision 9)
+++ /trunk/minix/lib/syscall/waitpid.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__waitpid
+.define	_waitpid
+.align 2
+
+_waitpid:
+	jmp	__waitpid
Index: /trunk/minix/lib/syscall/write.s
===================================================================
--- /trunk/minix/lib/syscall/write.s	(revision 9)
+++ /trunk/minix/lib/syscall/write.s	(revision 9)
@@ -0,0 +1,7 @@
+.sect .text
+.extern	__write
+.define	_write
+.align 2
+
+_write:
+	jmp	__write
Index: /trunk/minix/lib/syslib/Makedepend-ack
===================================================================
--- /trunk/minix/lib/syslib/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/syslib/Makedepend-ack	(revision 9)
@@ -0,0 +1,57 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' assert.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' panic.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_attr_r16.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_attr_r32.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_attr_r8.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_attr_w16.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_attr_w32.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_attr_w8.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_dev_name.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_find_dev.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_first_dev.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_ids.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_init.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_init1.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_next_dev.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_rescan_bus.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_reserve.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' pci_slot_name.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_abort.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_endsig.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_eniop.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_exec.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_exit.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_fork.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_getinfo.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_getsig.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_in.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_int86.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_irqctl.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_kill.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_memset.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_newmap.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_nice.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_out.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_physcopy.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_sdevio.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_segctl.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_setalarm.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_sigreturn.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_sigsend.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_privctl.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_times.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_trace.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_umap.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_vinb.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_vinl.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_vinw.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_vircopy.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_vm_map.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_vm_setbuf.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_voutb.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_voutl.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' sys_voutw.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' taskcall.c | sed -e 's:^\(.\):../obj-ack//./syslib/\1:' >> .depend-ack
Index: /trunk/minix/lib/syslib/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/syslib/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/syslib/Makedepend-gnu	(revision 9)
@@ -0,0 +1,57 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' assert.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' panic.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_attr_r16.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_attr_r32.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_attr_r8.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_attr_w16.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_attr_w32.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_attr_w8.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_dev_name.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_find_dev.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_first_dev.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_ids.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_init.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_init1.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_next_dev.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_rescan_bus.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_reserve.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' pci_slot_name.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_abort.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_endsig.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_eniop.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_exec.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_exit.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_fork.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_getinfo.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_getsig.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_in.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_int86.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_irqctl.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_kill.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_memset.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_newmap.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_nice.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_out.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_physcopy.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_sdevio.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_segctl.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_setalarm.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_sigreturn.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_sigsend.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_privctl.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_times.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_trace.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_umap.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_vinb.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_vinl.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_vinw.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_vircopy.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_vm_map.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_vm_setbuf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_voutb.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_voutl.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' sys_voutw.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' taskcall.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./syslib/\1:' >> .depend-gnu
Index: /trunk/minix/lib/syslib/Makefile
===================================================================
--- /trunk/minix/lib/syslib/Makefile	(revision 9)
+++ /trunk/minix/lib/syslib/Makefile	(revision 9)
@@ -0,0 +1,423 @@
+#Generated from ./syslib/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./syslib ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./syslib ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libsys.a
+
+../obj-ack//libsys.a: ../obj-ack//libsys.a(assert.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(panic.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_attr_r16.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_attr_r32.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_attr_r8.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_attr_w16.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_attr_w32.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_attr_w8.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_dev_name.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_find_dev.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_first_dev.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_ids.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_init.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_init1.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_next_dev.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_rescan_bus.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_reserve.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(pci_slot_name.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_abort.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_endsig.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_eniop.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_exec.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_exit.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_fork.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_getinfo.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_getsig.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_in.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_int86.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_irqctl.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_kill.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_memset.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_newmap.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_nice.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_out.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_physcopy.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_sdevio.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_segctl.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_setalarm.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_sigreturn.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_sigsend.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_privctl.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_times.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_trace.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_umap.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_vinb.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_vinl.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_vinw.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_vircopy.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_vm_map.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_vm_setbuf.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_voutb.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_voutl.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(sys_voutw.o)
+../obj-ack//libsys.a: ../obj-ack//libsys.a(taskcall.o)
+
+../obj-ack//libsys.a:
+	ar cr ../obj-ack//libsys.a ../obj-ack//./syslib/*.o
+	rm ../obj-ack//./syslib/*.o
+
+../obj-ack//libsys.a(assert.o): assert.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/assert.o assert.c
+../obj-ack//libsys.a(panic.o): panic.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/panic.o panic.c
+../obj-ack//libsys.a(pci_attr_r16.o): pci_attr_r16.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_attr_r16.o pci_attr_r16.c
+../obj-ack//libsys.a(pci_attr_r32.o): pci_attr_r32.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_attr_r32.o pci_attr_r32.c
+../obj-ack//libsys.a(pci_attr_r8.o): pci_attr_r8.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_attr_r8.o pci_attr_r8.c
+../obj-ack//libsys.a(pci_attr_w16.o): pci_attr_w16.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_attr_w16.o pci_attr_w16.c
+../obj-ack//libsys.a(pci_attr_w32.o): pci_attr_w32.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_attr_w32.o pci_attr_w32.c
+../obj-ack//libsys.a(pci_attr_w8.o): pci_attr_w8.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_attr_w8.o pci_attr_w8.c
+../obj-ack//libsys.a(pci_dev_name.o): pci_dev_name.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_dev_name.o pci_dev_name.c
+../obj-ack//libsys.a(pci_find_dev.o): pci_find_dev.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_find_dev.o pci_find_dev.c
+../obj-ack//libsys.a(pci_first_dev.o): pci_first_dev.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_first_dev.o pci_first_dev.c
+../obj-ack//libsys.a(pci_ids.o): pci_ids.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_ids.o pci_ids.c
+../obj-ack//libsys.a(pci_init.o): pci_init.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_init.o pci_init.c
+../obj-ack//libsys.a(pci_init1.o): pci_init1.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_init1.o pci_init1.c
+../obj-ack//libsys.a(pci_next_dev.o): pci_next_dev.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_next_dev.o pci_next_dev.c
+../obj-ack//libsys.a(pci_rescan_bus.o): pci_rescan_bus.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_rescan_bus.o pci_rescan_bus.c
+../obj-ack//libsys.a(pci_reserve.o): pci_reserve.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_reserve.o pci_reserve.c
+../obj-ack//libsys.a(pci_slot_name.o): pci_slot_name.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/pci_slot_name.o pci_slot_name.c
+../obj-ack//libsys.a(sys_abort.o): sys_abort.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_abort.o sys_abort.c
+../obj-ack//libsys.a(sys_endsig.o): sys_endsig.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_endsig.o sys_endsig.c
+../obj-ack//libsys.a(sys_eniop.o): sys_eniop.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_eniop.o sys_eniop.c
+../obj-ack//libsys.a(sys_exec.o): sys_exec.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_exec.o sys_exec.c
+../obj-ack//libsys.a(sys_exit.o): sys_exit.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_exit.o sys_exit.c
+../obj-ack//libsys.a(sys_fork.o): sys_fork.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_fork.o sys_fork.c
+../obj-ack//libsys.a(sys_getinfo.o): sys_getinfo.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_getinfo.o sys_getinfo.c
+../obj-ack//libsys.a(sys_getsig.o): sys_getsig.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_getsig.o sys_getsig.c
+../obj-ack//libsys.a(sys_in.o): sys_in.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_in.o sys_in.c
+../obj-ack//libsys.a(sys_int86.o): sys_int86.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_int86.o sys_int86.c
+../obj-ack//libsys.a(sys_irqctl.o): sys_irqctl.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_irqctl.o sys_irqctl.c
+../obj-ack//libsys.a(sys_kill.o): sys_kill.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_kill.o sys_kill.c
+../obj-ack//libsys.a(sys_memset.o): sys_memset.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_memset.o sys_memset.c
+../obj-ack//libsys.a(sys_newmap.o): sys_newmap.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_newmap.o sys_newmap.c
+../obj-ack//libsys.a(sys_nice.o): sys_nice.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_nice.o sys_nice.c
+../obj-ack//libsys.a(sys_out.o): sys_out.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_out.o sys_out.c
+../obj-ack//libsys.a(sys_physcopy.o): sys_physcopy.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_physcopy.o sys_physcopy.c
+../obj-ack//libsys.a(sys_sdevio.o): sys_sdevio.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_sdevio.o sys_sdevio.c
+../obj-ack//libsys.a(sys_segctl.o): sys_segctl.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_segctl.o sys_segctl.c
+../obj-ack//libsys.a(sys_setalarm.o): sys_setalarm.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_setalarm.o sys_setalarm.c
+../obj-ack//libsys.a(sys_sigreturn.o): sys_sigreturn.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_sigreturn.o sys_sigreturn.c
+../obj-ack//libsys.a(sys_sigsend.o): sys_sigsend.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_sigsend.o sys_sigsend.c
+../obj-ack//libsys.a(sys_privctl.o): sys_privctl.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_privctl.o sys_privctl.c
+../obj-ack//libsys.a(sys_times.o): sys_times.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_times.o sys_times.c
+../obj-ack//libsys.a(sys_trace.o): sys_trace.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_trace.o sys_trace.c
+../obj-ack//libsys.a(sys_umap.o): sys_umap.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_umap.o sys_umap.c
+../obj-ack//libsys.a(sys_vinb.o): sys_vinb.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_vinb.o sys_vinb.c
+../obj-ack//libsys.a(sys_vinl.o): sys_vinl.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_vinl.o sys_vinl.c
+../obj-ack//libsys.a(sys_vinw.o): sys_vinw.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_vinw.o sys_vinw.c
+../obj-ack//libsys.a(sys_vircopy.o): sys_vircopy.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_vircopy.o sys_vircopy.c
+../obj-ack//libsys.a(sys_vm_map.o): sys_vm_map.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_vm_map.o sys_vm_map.c
+../obj-ack//libsys.a(sys_vm_setbuf.o): sys_vm_setbuf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_vm_setbuf.o sys_vm_setbuf.c
+../obj-ack//libsys.a(sys_voutb.o): sys_voutb.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_voutb.o sys_voutb.c
+../obj-ack//libsys.a(sys_voutl.o): sys_voutl.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_voutl.o sys_voutl.c
+../obj-ack//libsys.a(sys_voutw.o): sys_voutw.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/sys_voutw.o sys_voutw.c
+../obj-ack//libsys.a(taskcall.o): taskcall.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./syslib/taskcall.o taskcall.c
+
+all-gnu: ../obj-gnu/libsys.a
+
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/assert.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/panic.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_attr_r16.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_attr_r32.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_attr_r8.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_attr_w16.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_attr_w32.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_attr_w8.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_dev_name.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_find_dev.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_first_dev.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_ids.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_init.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_init1.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_next_dev.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_rescan_bus.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_reserve.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/pci_slot_name.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_abort.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_endsig.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_eniop.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_exec.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_exit.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_fork.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_getinfo.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_getsig.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_in.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_int86.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_irqctl.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_kill.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_memset.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_newmap.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_nice.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_out.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_physcopy.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_sdevio.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_segctl.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_setalarm.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_sigreturn.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_sigsend.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_privctl.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_times.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_trace.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_umap.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_vinb.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_vinl.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_vinw.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_vircopy.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_vm_map.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_vm_setbuf.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_voutb.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_voutl.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/sys_voutw.o
+../obj-gnu/libsys.a: ../obj-gnu/./syslib/taskcall.o
+
+../obj-gnu/libsys.a:
+	gar cr ../obj-gnu/libsys.a $?
+
+../obj-gnu/./syslib/assert.o: assert.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/assert.o assert.c
+
+../obj-gnu/./syslib/panic.o: panic.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/panic.o panic.c
+
+../obj-gnu/./syslib/pci_attr_r16.o: pci_attr_r16.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_attr_r16.o pci_attr_r16.c
+
+../obj-gnu/./syslib/pci_attr_r32.o: pci_attr_r32.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_attr_r32.o pci_attr_r32.c
+
+../obj-gnu/./syslib/pci_attr_r8.o: pci_attr_r8.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_attr_r8.o pci_attr_r8.c
+
+../obj-gnu/./syslib/pci_attr_w16.o: pci_attr_w16.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_attr_w16.o pci_attr_w16.c
+
+../obj-gnu/./syslib/pci_attr_w32.o: pci_attr_w32.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_attr_w32.o pci_attr_w32.c
+
+../obj-gnu/./syslib/pci_attr_w8.o: pci_attr_w8.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_attr_w8.o pci_attr_w8.c
+
+../obj-gnu/./syslib/pci_dev_name.o: pci_dev_name.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_dev_name.o pci_dev_name.c
+
+../obj-gnu/./syslib/pci_find_dev.o: pci_find_dev.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_find_dev.o pci_find_dev.c
+
+../obj-gnu/./syslib/pci_first_dev.o: pci_first_dev.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_first_dev.o pci_first_dev.c
+
+../obj-gnu/./syslib/pci_ids.o: pci_ids.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_ids.o pci_ids.c
+
+../obj-gnu/./syslib/pci_init.o: pci_init.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_init.o pci_init.c
+
+../obj-gnu/./syslib/pci_init1.o: pci_init1.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_init1.o pci_init1.c
+
+../obj-gnu/./syslib/pci_next_dev.o: pci_next_dev.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_next_dev.o pci_next_dev.c
+
+../obj-gnu/./syslib/pci_rescan_bus.o: pci_rescan_bus.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_rescan_bus.o pci_rescan_bus.c
+
+../obj-gnu/./syslib/pci_reserve.o: pci_reserve.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_reserve.o pci_reserve.c
+
+../obj-gnu/./syslib/pci_slot_name.o: pci_slot_name.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/pci_slot_name.o pci_slot_name.c
+
+../obj-gnu/./syslib/sys_abort.o: sys_abort.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_abort.o sys_abort.c
+
+../obj-gnu/./syslib/sys_endsig.o: sys_endsig.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_endsig.o sys_endsig.c
+
+../obj-gnu/./syslib/sys_eniop.o: sys_eniop.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_eniop.o sys_eniop.c
+
+../obj-gnu/./syslib/sys_exec.o: sys_exec.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_exec.o sys_exec.c
+
+../obj-gnu/./syslib/sys_exit.o: sys_exit.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_exit.o sys_exit.c
+
+../obj-gnu/./syslib/sys_fork.o: sys_fork.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_fork.o sys_fork.c
+
+../obj-gnu/./syslib/sys_getinfo.o: sys_getinfo.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_getinfo.o sys_getinfo.c
+
+../obj-gnu/./syslib/sys_getsig.o: sys_getsig.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_getsig.o sys_getsig.c
+
+../obj-gnu/./syslib/sys_in.o: sys_in.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_in.o sys_in.c
+
+../obj-gnu/./syslib/sys_int86.o: sys_int86.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_int86.o sys_int86.c
+
+../obj-gnu/./syslib/sys_irqctl.o: sys_irqctl.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_irqctl.o sys_irqctl.c
+
+../obj-gnu/./syslib/sys_kill.o: sys_kill.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_kill.o sys_kill.c
+
+../obj-gnu/./syslib/sys_memset.o: sys_memset.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_memset.o sys_memset.c
+
+../obj-gnu/./syslib/sys_newmap.o: sys_newmap.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_newmap.o sys_newmap.c
+
+../obj-gnu/./syslib/sys_nice.o: sys_nice.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_nice.o sys_nice.c
+
+../obj-gnu/./syslib/sys_out.o: sys_out.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_out.o sys_out.c
+
+../obj-gnu/./syslib/sys_physcopy.o: sys_physcopy.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_physcopy.o sys_physcopy.c
+
+../obj-gnu/./syslib/sys_sdevio.o: sys_sdevio.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_sdevio.o sys_sdevio.c
+
+../obj-gnu/./syslib/sys_segctl.o: sys_segctl.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_segctl.o sys_segctl.c
+
+../obj-gnu/./syslib/sys_setalarm.o: sys_setalarm.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_setalarm.o sys_setalarm.c
+
+../obj-gnu/./syslib/sys_sigreturn.o: sys_sigreturn.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_sigreturn.o sys_sigreturn.c
+
+../obj-gnu/./syslib/sys_sigsend.o: sys_sigsend.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_sigsend.o sys_sigsend.c
+
+../obj-gnu/./syslib/sys_privctl.o: sys_privctl.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_privctl.o sys_privctl.c
+
+../obj-gnu/./syslib/sys_times.o: sys_times.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_times.o sys_times.c
+
+../obj-gnu/./syslib/sys_trace.o: sys_trace.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_trace.o sys_trace.c
+
+../obj-gnu/./syslib/sys_umap.o: sys_umap.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_umap.o sys_umap.c
+
+../obj-gnu/./syslib/sys_vinb.o: sys_vinb.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_vinb.o sys_vinb.c
+
+../obj-gnu/./syslib/sys_vinl.o: sys_vinl.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_vinl.o sys_vinl.c
+
+../obj-gnu/./syslib/sys_vinw.o: sys_vinw.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_vinw.o sys_vinw.c
+
+../obj-gnu/./syslib/sys_vircopy.o: sys_vircopy.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_vircopy.o sys_vircopy.c
+
+../obj-gnu/./syslib/sys_vm_map.o: sys_vm_map.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_vm_map.o sys_vm_map.c
+
+../obj-gnu/./syslib/sys_vm_setbuf.o: sys_vm_setbuf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_vm_setbuf.o sys_vm_setbuf.c
+
+../obj-gnu/./syslib/sys_voutb.o: sys_voutb.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_voutb.o sys_voutb.c
+
+../obj-gnu/./syslib/sys_voutl.o: sys_voutl.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_voutl.o sys_voutl.c
+
+../obj-gnu/./syslib/sys_voutw.o: sys_voutw.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/sys_voutw.o sys_voutw.c
+
+../obj-gnu/./syslib/taskcall.o: taskcall.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./syslib/taskcall.o taskcall.c
+
+
+
+
+clean::
+	rm -f ../obj-ack//./syslib/*
+	rm -f ../obj-gnu/./syslib/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/syslib/Makefile.in
===================================================================
--- /trunk/minix/lib/syslib/Makefile.in	(revision 9)
+++ /trunk/minix/lib/syslib/Makefile.in	(revision 9)
@@ -0,0 +1,63 @@
+# Makefile for lib/syslib.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
+
+LIBRARIES=libsys
+
+libsys_FILES=" \
+	assert.c \
+	panic.c \
+	pci_attr_r16.c \
+	pci_attr_r32.c \
+	pci_attr_r8.c \
+	pci_attr_w16.c \
+	pci_attr_w32.c \
+	pci_attr_w8.c \
+	pci_dev_name.c \
+	pci_find_dev.c \
+	pci_first_dev.c \
+	pci_ids.c \
+	pci_init.c \
+	pci_init1.c \
+	pci_next_dev.c \
+	pci_rescan_bus.c \
+	pci_reserve.c \
+	pci_slot_name.c \
+	sys_abort.c \
+	sys_endsig.c \
+	sys_eniop.c \
+	sys_exec.c \
+	sys_exit.c \
+	sys_fork.c \
+	sys_getinfo.c \
+	sys_getsig.c \
+	sys_in.c \
+	sys_int86.c \
+	sys_irqctl.c \
+	sys_kill.c \
+	sys_memset.c \
+	sys_newmap.c \
+	sys_nice.c \
+	sys_out.c \
+	sys_physcopy.c \
+	sys_sdevio.c \
+	sys_segctl.c \
+	sys_setalarm.c \
+	sys_sigreturn.c \
+	sys_sigsend.c \
+	sys_privctl.c \
+	sys_times.c \
+	sys_trace.c \
+	sys_umap.c \
+	sys_vinb.c \
+	sys_vinl.c \
+	sys_vinw.c \
+	sys_vircopy.c \
+	sys_vm_map.c \
+	sys_vm_setbuf.c \
+	sys_voutb.c \
+	sys_voutl.c \
+	sys_voutw.c \
+	taskcall.c"
+
+TYPE=both
Index: /trunk/minix/lib/syslib/assert.c
===================================================================
--- /trunk/minix/lib/syslib/assert.c	(revision 9)
+++ /trunk/minix/lib/syslib/assert.c	(revision 9)
@@ -0,0 +1,14 @@
+/*
+ * assert.c - diagnostics
+ */
+
+#include	<assert.h>
+#include	<stdio.h>
+#include	<minix/config.h>
+#include	<minix/const.h>
+#include	<minix/sysutil.h>
+
+void __bad_assertion(const char *mess) {
+	printf("%s", mess);
+	panic(NULL, NULL, NO_NUM);
+}
Index: /trunk/minix/lib/syslib/panic.c
===================================================================
--- /trunk/minix/lib/syslib/panic.c	(revision 9)
+++ /trunk/minix/lib/syslib/panic.c	(revision 9)
@@ -0,0 +1,45 @@
+#include <stdlib.h>
+#include <signal.h>
+#include <minix/sysutil.h>
+
+#include "syslib.h"
+
+int panicing= 0;
+
+/*===========================================================================*
+ *				panic					     *
+ *===========================================================================*/
+PUBLIC void panic(who, mess, num)
+char *who;			/* server identification */
+char *mess;			/* message format string */
+int num;			/* number to go with format string */
+{
+/* Something awful has happened. Panics are caused when an internal
+ * inconsistency is detected, e.g., a programming error or illegal 
+ * value of a defined constant.
+ */
+  message m;
+  void (*suicide)(void);
+
+  panicing= 1;
+  if (NULL != who && NULL != mess) {
+      if (num != NO_NUM) {
+          printf("Panic in %s: %s: %d\n", who, mess, num); 
+      } else {
+          printf("Panic in %s: %s\n", who, mess); 
+      }
+  }
+
+  /* Try to signal ourself */
+  sys_kill(SELF, SIGKILL);
+
+  /* If exiting nicely through PM fails for some reason, try to
+   * commit suicide. E.g., message to PM might fail due to deadlock.
+   */
+  suicide = (void (*)(void)) -1;
+  suicide();
+
+  /* If committing suicide fails for some reason, hang. */
+  for(;;) { }
+}
+
Index: /trunk/minix/lib/syslib/pci.h
===================================================================
--- /trunk/minix/lib/syslib/pci.h	(revision 9)
+++ /trunk/minix/lib/syslib/pci.h	(revision 9)
@@ -0,0 +1,1 @@
+extern int pci_procnr;
Index: /trunk/minix/lib/syslib/pci_attr_r16.c
===================================================================
--- /trunk/minix/lib/syslib/pci_attr_r16.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_attr_r16.c	(revision 9)
@@ -0,0 +1,32 @@
+/*
+pci_attr_r16.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *				pci_attr_r16				     *
+ *===========================================================================*/
+PUBLIC u16_t pci_attr_r16(devind, port)
+int devind;
+int port;
+{
+	int r;
+	message m;
+
+	m.m_type= BUSC_PCI_ATTR_R16;
+	m.m2_i1= devind;
+	m.m2_i2= port;
+
+	r= sendrec(pci_procnr, &m);
+	if (r != 0)
+		panic("pci", "pci_attr_r16: can't talk to PCI", r);
+
+	if (m.m_type != 0)
+		panic("pci", "pci_attr_r16: got bad reply from PCI", m.m_type);
+
+	return m.m2_l1;
+}
+
Index: /trunk/minix/lib/syslib/pci_attr_r32.c
===================================================================
--- /trunk/minix/lib/syslib/pci_attr_r32.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_attr_r32.c	(revision 9)
@@ -0,0 +1,32 @@
+/*
+pci_attr_r32.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *				pci_attr_r32				     *
+ *===========================================================================*/
+PUBLIC u32_t pci_attr_r32(devind, port)
+int devind;
+int port;
+{
+	int r;
+	message m;
+
+	m.m_type= BUSC_PCI_ATTR_R32;
+	m.m2_i1= devind;
+	m.m2_i2= port;
+
+	r= sendrec(pci_procnr, &m);
+	if (r != 0)
+		panic("pci", "pci_attr_r32: can't talk to PCI", r);
+
+	if (m.m_type != 0)
+		panic("pci", "pci_attr_r32: got bad reply from PCI", m.m_type);
+
+	return m.m2_l1;
+}
+
Index: /trunk/minix/lib/syslib/pci_attr_r8.c
===================================================================
--- /trunk/minix/lib/syslib/pci_attr_r8.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_attr_r8.c	(revision 9)
@@ -0,0 +1,32 @@
+/*
+pci_attr_r8.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *				pci_attr_r8				     *
+ *===========================================================================*/
+PUBLIC u8_t pci_attr_r8(devind, port)
+int devind;
+int port;
+{
+	int r;
+	message m;
+
+	m.m_type= BUSC_PCI_ATTR_R8;
+	m.m2_i1= devind;
+	m.m2_i2= port;
+
+	r= sendrec(pci_procnr, &m);
+	if (r != 0)
+		panic("pci", "pci_attr_r8: can't talk to PCI", r);
+
+	if (m.m_type != 0)
+		panic("pci", "pci_attr_r8: got bad reply from PCI", m.m_type);
+
+	return m.m2_l1;
+}
+
Index: /trunk/minix/lib/syslib/pci_attr_w16.c
===================================================================
--- /trunk/minix/lib/syslib/pci_attr_w16.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_attr_w16.c	(revision 9)
@@ -0,0 +1,32 @@
+/*
+pci_attr_w16.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *				pci_attr_w16				     *
+ *===========================================================================*/
+PUBLIC void pci_attr_w16(devind, port, value)
+int devind;
+int port;
+u16_t value;
+{
+	int r;
+	message m;
+
+	m.m_type= BUSC_PCI_ATTR_W16;
+	m.m2_i1= devind;
+	m.m2_i2= port;
+	m.m2_l1= value;
+
+	r= sendrec(pci_procnr, &m);
+	if (r != 0)
+		panic("pci", "pci_attr_w16: can't talk to PCI", r);
+
+	if (m.m_type != 0)
+		panic("pci", "pci_attr_w16: got bad reply from PCI", m.m_type);
+}
+
Index: /trunk/minix/lib/syslib/pci_attr_w32.c
===================================================================
--- /trunk/minix/lib/syslib/pci_attr_w32.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_attr_w32.c	(revision 9)
@@ -0,0 +1,32 @@
+/*
+pci_attr_w32.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *				pci_attr_w32				     *
+ *===========================================================================*/
+PUBLIC void pci_attr_w32(devind, port, value)
+int devind;
+int port;
+u32_t value;
+{
+	int r;
+	message m;
+
+	m.m_type= BUSC_PCI_ATTR_W32;
+	m.m2_i1= devind;
+	m.m2_i2= port;
+	m.m2_l1= value;
+
+	r= sendrec(pci_procnr, &m);
+	if (r != 0)
+		panic("pci", "pci_attr_w32: can't talk to PCI", r);
+
+	if (m.m_type != 0)
+		panic("pci", "pci_attr_w32: got bad reply from PCI", m.m_type);
+}
+
Index: /trunk/minix/lib/syslib/pci_attr_w8.c
===================================================================
--- /trunk/minix/lib/syslib/pci_attr_w8.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_attr_w8.c	(revision 9)
@@ -0,0 +1,32 @@
+/*
+pci_attr_w8.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *				pci_attr_w8				     *
+ *===========================================================================*/
+PUBLIC void pci_attr_w8(devind, port, value)
+int devind;
+int port;
+u8_t value;
+{
+	int r;
+	message m;
+
+	m.m_type= BUSC_PCI_ATTR_W8;
+	m.m2_i1= devind;
+	m.m2_i2= port;
+	m.m2_l1= value;
+
+	r= sendrec(pci_procnr, &m);
+	if (r != 0)
+		panic("pci", "pci_attr_w8: can't talk to PCI", r);
+
+	if (m.m_type != 0)
+		panic("pci", "pci_attr_w8: got bad reply from PCI", m.m_type);
+}
+
Index: /trunk/minix/lib/syslib/pci_dev_name.c
===================================================================
--- /trunk/minix/lib/syslib/pci_dev_name.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_dev_name.c	(revision 9)
@@ -0,0 +1,48 @@
+/*
+pci_dev_name.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *				pci_dev_name				     *
+ *===========================================================================*/
+PUBLIC char *pci_dev_name(vid, did)
+u16_t vid;
+u16_t did;
+{
+	static char name[80];	/* We need a better interface for this */
+
+	int r;
+	message m;
+
+	m.m_type= BUSC_PCI_DEV_NAME;
+	m.m1_i1= vid;
+	m.m1_i2= did;
+	m.m1_i3= sizeof(name);
+	m.m1_p1= name;
+
+	r= sendrec(pci_procnr, &m);
+	if (r != 0)
+		panic("pci", "pci_dev_name: can't talk to PCI", r);
+
+	if (m.m_type == ENOENT)
+	{
+		printf("pci_dev_name: got no name\n");
+		return NULL;	/* No name for this device */
+	}
+	if (m.m_type != 0)
+		panic("pci", "pci_dev_name: got bad reply from PCI", m.m_type);
+
+	name[sizeof(name)-1]= '\0';	/* Make sure that the string is NUL
+					 * terminated.
+					 */
+
+#if DEBUG
+	printf("pci_dev_name: got name %s\n", name);
+#endif
+	return name;
+}
+
Index: /trunk/minix/lib/syslib/pci_find_dev.c
===================================================================
--- /trunk/minix/lib/syslib/pci_find_dev.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_find_dev.c	(revision 9)
@@ -0,0 +1,43 @@
+/*
+pci_find_dev.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *				pci_find_dev				     *
+ *===========================================================================*/
+PUBLIC int pci_find_dev(bus, dev, func, devindp)
+u8_t bus;
+u8_t dev;
+u8_t func;
+int *devindp;
+{
+	int r;
+	message m;
+
+	m.m_type= BUSC_PCI_FIND_DEV;
+	m.m1_i1= bus;
+	m.m1_i2= dev;
+	m.m1_i3= func;
+
+	r= sendrec(pci_procnr, &m);
+	if (r != 0)
+		panic("pci", "pci_find_dev: can't talk to PCI", r);
+
+	if (m.m_type == 1)
+	{
+		*devindp= m.m1_i1;
+		printf("pci_find_dev: got device %d for %d.%d.%d\n",
+			*devindp, bus, dev, func);
+		return 1;
+	}
+	if (m.m_type != 0)
+		panic("pci", "pci_find_dev: got bad reply from PCI", m.m_type);
+
+	printf("pci_find_dev: got nothing\n");
+	return 0;
+}
+
Index: /trunk/minix/lib/syslib/pci_first_dev.c
===================================================================
--- /trunk/minix/lib/syslib/pci_first_dev.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_first_dev.c	(revision 9)
@@ -0,0 +1,42 @@
+/*
+pci_first_dev.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *				pci_first_dev				     *
+ *===========================================================================*/
+PUBLIC int pci_first_dev(devindp, vidp, didp)
+int *devindp;
+u16_t *vidp;
+u16_t *didp;
+{
+	int r;
+	message m;
+
+	m.m_type= BUSC_PCI_FIRST_DEV;
+	r= sendrec(pci_procnr, &m);
+	if (r != 0)
+		panic("pci", "pci_first_dev: can't talk to PCI", r);
+	if (m.m_type == 1)
+	{
+		*devindp= m.m1_i1;
+		*vidp= m.m1_i2;
+		*didp= m.m1_i3;
+#if DEBUG
+		printf("pci_first_dev: got device %d, %04x/%04x\n", 
+			*devindp, *vidp, *didp);
+#endif
+		return 1;
+	}
+	if (m.m_type != 0)
+		panic("pci", "pci_first_dev: got bad reply from PCI", m.m_type);
+
+#if DEBUG
+	printf("pci_first_dev: got nothing\n");
+#endif
+	return 0;
+}
Index: /trunk/minix/lib/syslib/pci_ids.c
===================================================================
--- /trunk/minix/lib/syslib/pci_ids.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_ids.c	(revision 9)
@@ -0,0 +1,33 @@
+/*
+pci_ids.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *				pci_ids					     *
+ *===========================================================================*/
+PUBLIC void pci_ids(devind, vidp, didp)
+int devind;
+u16_t *vidp;
+u16_t *didp;
+{
+	int r;
+	message m;
+
+	m.m_type= BUSC_PCI_IDS;
+	m.m1_i1= devind;
+
+	r= sendrec(pci_procnr, &m);
+	if (r != 0)
+		panic("pci", "pci_ids: can't talk to PCI", r);
+
+	if (m.m_type != 0)
+		panic("pci", "pci_ids: got bad reply from PCI", m.m_type);
+	*vidp= m.m1_i1;
+	*didp= m.m1_i2;
+	printf("pci_ids: %04x/%04x\n", *vidp, *didp);
+}
+
Index: /trunk/minix/lib/syslib/pci_init.c
===================================================================
--- /trunk/minix/lib/syslib/pci_init.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_init.c	(revision 9)
@@ -0,0 +1,15 @@
+/*
+pci_init.c
+*/
+
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *				pci_init				     *
+ *===========================================================================*/
+PUBLIC void pci_init()
+{
+	pci_init1("");
+}
+
Index: /trunk/minix/lib/syslib/pci_init1.c
===================================================================
--- /trunk/minix/lib/syslib/pci_init1.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_init1.c	(revision 9)
@@ -0,0 +1,43 @@
+/*
+pci_init1.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <string.h>
+#include <unistd.h>
+#include <minix/sysutil.h>
+
+int pci_procnr= ANY;
+
+/*===========================================================================*
+ *				pci_init1				     *
+ *===========================================================================*/
+PUBLIC void pci_init1(name)
+char *name;
+{
+	int r;
+	size_t len;
+	message m;
+
+	r= _pm_findproc("pci", &pci_procnr);
+	if (r != 0)
+		panic("pci", "pci_init1: _pm_findproc failed for 'pci'", r);
+
+	m.m_type= BUSC_PCI_INIT;
+	len= strlen(name);
+	if (len+1 <= sizeof(m.m3_ca1))
+		strcpy(m.m3_ca1, name);
+	else
+	{
+		len= sizeof(m.m3_ca1)-1;
+		memcpy(m.m3_ca1, name, len);
+		m.m3_ca1[len]= '\0';
+	}
+	r= sendrec(pci_procnr, &m);
+	if (r != 0)
+		panic("pci", "pci_init1: can't talk to PCI", r);
+	if (m.m_type != 0)
+		panic("pci", "pci_init1: got bad reply from PCI", m.m_type);
+}
+
Index: /trunk/minix/lib/syslib/pci_next_dev.c
===================================================================
--- /trunk/minix/lib/syslib/pci_next_dev.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_next_dev.c	(revision 9)
@@ -0,0 +1,43 @@
+/*
+pci_next_dev.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *				pci_next_dev				     *
+ *===========================================================================*/
+PUBLIC int pci_next_dev(devindp, vidp, didp)
+int *devindp;
+u16_t *vidp;
+u16_t *didp;
+{
+	int r;
+	message m;
+
+	m.m_type= BUSC_PCI_NEXT_DEV;
+	m.m1_i1= *devindp;
+
+	r= sendrec(pci_procnr, &m);
+	if (r != 0)
+		panic("pci", "pci_next_dev: can't talk to PCI", r);
+
+	if (m.m_type == 1)
+	{
+		*devindp= m.m1_i1;
+		*vidp= m.m1_i2;
+		*didp= m.m1_i3;
+#if 0
+		printf("pci_next_dev: got device %d, %04x/%04x\n", 
+			*devindp, *vidp, *didp);
+#endif
+		return 1;
+	}
+	if (m.m_type != 0)
+		panic("pci", "pci_next_dev: got bad reply from PCI", m.m_type);
+
+	return 0;
+}
+
Index: /trunk/minix/lib/syslib/pci_rescan_bus.c
===================================================================
--- /trunk/minix/lib/syslib/pci_rescan_bus.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_rescan_bus.c	(revision 9)
@@ -0,0 +1,31 @@
+/*
+pci_rescan_bus.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *				pci_rescan_bus				     *
+ *===========================================================================*/
+PUBLIC void pci_rescan_bus(busnr)
+u8_t busnr;
+{
+	int r;
+	message m;
+
+	m.m_type= BUSC_PCI_RESCAN;
+	m.m1_i1= busnr;
+
+	r= sendrec(pci_procnr, &m);
+	if (r != 0)
+		panic("pci", "pci_rescan_bus: can't talk to PCI", r);
+
+	if (m.m_type != 0)
+	{
+		panic("pci", "pci_rescan_bus: got bad reply from PCI",
+			m.m_type);
+	}
+}
+
Index: /trunk/minix/lib/syslib/pci_reserve.c
===================================================================
--- /trunk/minix/lib/syslib/pci_reserve.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_reserve.c	(revision 9)
@@ -0,0 +1,28 @@
+/*
+pci_reserve.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *				pci_reserve				     *
+ *===========================================================================*/
+PUBLIC void pci_reserve(devind)
+int devind;
+{
+	int r;
+	message m;
+
+	m.m_type= BUSC_PCI_RESERVE;
+	m.m1_i1= devind;
+
+	r= sendrec(pci_procnr, &m);
+	if (r != 0)
+		panic("pci", "pci_reserve: can't talk to PCI", r);
+
+	if (m.m_type != 0)
+		panic("pci", "pci_reserve: got bad reply from PCI", m.m_type);
+}
+
Index: /trunk/minix/lib/syslib/pci_slot_name.c
===================================================================
--- /trunk/minix/lib/syslib/pci_slot_name.c	(revision 9)
+++ /trunk/minix/lib/syslib/pci_slot_name.c	(revision 9)
@@ -0,0 +1,39 @@
+/*
+pci_slot_name.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *				pci_slot_name				     *
+ *===========================================================================*/
+PUBLIC char *pci_slot_name(devind)
+int devind;
+{
+	static char name[80];	/* We need a better interface for this */
+
+	int r;
+	message m;
+
+	m.m_type= BUSC_PCI_SLOT_NAME;
+	m.m1_i1= devind;
+	m.m1_i2= sizeof(name);
+	m.m1_p1= name;
+
+	r= sendrec(pci_procnr, &m);
+	if (r != 0)
+		panic("pci", "pci_slot_name: can't talk to PCI", r);
+
+	if (m.m_type != 0)
+		panic("pci", "pci_slot_name: got bad reply from PCI", m.m_type);
+
+	name[sizeof(name)-1]= '\0';	/* Make sure that the string is NUL
+					 * terminated.
+					 */
+
+	printf("pci_slot_name: got name %s\n", name);
+	return name;
+}
+
Index: /trunk/minix/lib/syslib/sys_abort.c
===================================================================
--- /trunk/minix/lib/syslib/sys_abort.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_abort.c	(revision 9)
@@ -0,0 +1,21 @@
+#include "syslib.h"
+#include <stdarg.h>
+#include <unistd.h>
+
+PUBLIC int sys_abort(int how, ...)
+{
+/* Something awful has happened.  Abandon ship. */
+
+  message m;
+  va_list ap;
+
+  va_start(ap, how);
+  if ((m.ABRT_HOW = how) == RBT_MONITOR) {
+	m.ABRT_MON_ENDPT = va_arg(ap, int);
+	m.ABRT_MON_ADDR = va_arg(ap, char *);
+	m.ABRT_MON_LEN = va_arg(ap, size_t);
+  }
+  va_end(ap);
+
+  return(_taskcall(SYSTASK, SYS_ABORT, &m));
+}
Index: /trunk/minix/lib/syslib/sys_endsig.c
===================================================================
--- /trunk/minix/lib/syslib/sys_endsig.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_endsig.c	(revision 9)
@@ -0,0 +1,16 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_endksig				     *
+ *===========================================================================*/
+PUBLIC int sys_endksig(proc_nr)
+int proc_nr;				/* process number */
+{
+    message m;
+    int result;
+
+    m.SIG_ENDPT = proc_nr;
+    result = _taskcall(SYSTASK, SYS_ENDKSIG, &m);
+    return(result);
+}
+
Index: /trunk/minix/lib/syslib/sys_eniop.c
===================================================================
--- /trunk/minix/lib/syslib/sys_eniop.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_eniop.c	(revision 9)
@@ -0,0 +1,14 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                               sys_enable_iop				     *    
+ *===========================================================================*/
+PUBLIC int sys_enable_iop(proc_nr_e)
+int proc_nr_e;			/* number of process to allow I/O */
+{
+    message m_iop;
+    m_iop.IO_ENDPT = proc_nr_e;
+    return _taskcall(SYSTASK, SYS_IOPENABLE, &m_iop);
+}
+
+
Index: /trunk/minix/lib/syslib/sys_exec.c
===================================================================
--- /trunk/minix/lib/syslib/sys_exec.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_exec.c	(revision 9)
@@ -0,0 +1,18 @@
+#include "syslib.h"
+
+PUBLIC int sys_exec(proc, ptr, prog_name, initpc)
+int proc;			/* process that did exec */
+char *ptr;			/* new stack pointer */
+char *prog_name;		/* name of the new program */
+vir_bytes initpc;
+{
+/* A process has exec'd.  Tell the kernel. */
+
+  message m;
+
+  m.PR_ENDPT = proc;
+  m.PR_STACK_PTR = ptr;
+  m.PR_NAME_PTR = prog_name;
+  m.PR_IP_PTR = (char *)initpc;
+  return(_taskcall(SYSTASK, SYS_EXEC, &m));
+}
Index: /trunk/minix/lib/syslib/sys_exit.c
===================================================================
--- /trunk/minix/lib/syslib/sys_exit.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_exit.c	(revision 9)
@@ -0,0 +1,17 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_exit			     	     *
+ *===========================================================================*/
+PUBLIC int sys_exit(proc)
+int proc;			/* which process has exited */
+{
+/* A process has exited. PM tells the kernel. In addition this call can be
+ * used by system processes to directly exit without passing through the
+ * PM. This should be used with care to prevent inconsistent PM tables. 
+ */
+  message m;
+
+  m.PR_ENDPT = proc;
+  return(_taskcall(SYSTASK, SYS_EXIT, &m));
+}
Index: /trunk/minix/lib/syslib/sys_fork.c
===================================================================
--- /trunk/minix/lib/syslib/sys_fork.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_fork.c	(revision 9)
@@ -0,0 +1,18 @@
+#include "syslib.h"
+
+PUBLIC int sys_fork(parent, child, child_endpoint)
+int parent;			/* process doing the fork */
+int child;			/* which proc has been created by the fork */
+int *child_endpoint;
+{
+/* A process has forked.  Tell the kernel. */
+
+  message m;
+  int r;
+
+  m.PR_ENDPT = parent;
+  m.PR_SLOT = child;
+  r = _taskcall(SYSTASK, SYS_FORK, &m);
+  *child_endpoint = m.PR_ENDPT;
+  return r;
+}
Index: /trunk/minix/lib/syslib/sys_getinfo.c
===================================================================
--- /trunk/minix/lib/syslib/sys_getinfo.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_getinfo.c	(revision 9)
@@ -0,0 +1,25 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_getinfo				     *
+ *===========================================================================*/
+PUBLIC int sys_getinfo(request, ptr, len, ptr2, len2)
+int request; 				/* system info requested */
+void *ptr;				/* pointer where to store it */
+int len;				/* max length of value to get */
+void *ptr2;				/* second pointer */
+int len2;				/* length or process nr */ 
+{
+    message m;
+
+    m.I_REQUEST = request;
+    m.I_ENDPT = SELF;			/* always store values at caller */
+    m.I_VAL_PTR = ptr;
+    m.I_VAL_LEN = len;
+    m.I_VAL_PTR2 = ptr2;
+    m.I_VAL_LEN2_E = len2;
+
+    return(_taskcall(SYSTASK, SYS_GETINFO, &m));
+}
+
+
Index: /trunk/minix/lib/syslib/sys_getsig.c
===================================================================
--- /trunk/minix/lib/syslib/sys_getsig.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_getsig.c	(revision 9)
@@ -0,0 +1,18 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_getksig				     *
+ *===========================================================================*/
+PUBLIC int sys_getksig(k_proc_nr, k_sig_map)
+int *k_proc_nr;				/* return process number here */
+sigset_t *k_sig_map;			/* return signal map here */
+{
+    message m;
+    int result;
+
+    result = _taskcall(SYSTASK, SYS_GETKSIG, &m);
+    *k_proc_nr = m.SIG_ENDPT;
+    *k_sig_map = (sigset_t) m.SIG_MAP;
+    return(result);
+}
+
Index: /trunk/minix/lib/syslib/sys_in.c
===================================================================
--- /trunk/minix/lib/syslib/sys_in.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_in.c	(revision 9)
@@ -0,0 +1,22 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_in				     *
+ *===========================================================================*/
+PUBLIC int sys_in(port, value, type)
+int port; 				/* port address to read from */
+unsigned long *value;			/* pointer where to store value */
+int type;				/* byte, word, long */
+{
+    message m_io;
+    int result;
+
+    m_io.DIO_TYPE = type;
+    m_io.DIO_REQUEST = DIO_INPUT;
+    m_io.DIO_PORT = port;
+
+    result = _taskcall(SYSTASK, SYS_DEVIO, &m_io);
+    *value = m_io.DIO_VALUE;
+    return(result);
+}
+
Index: /trunk/minix/lib/syslib/sys_int86.c
===================================================================
--- /trunk/minix/lib/syslib/sys_int86.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_int86.c	(revision 9)
@@ -0,0 +1,17 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_int86				     *
+ *===========================================================================*/
+PUBLIC int sys_int86(reg86p)
+struct reg86u *reg86p;
+{
+    message m;
+    int result;
+
+    m.m1_p1= (char *)reg86p;
+
+    result = _taskcall(SYSTASK, SYS_INT86, &m);
+    return(result);
+}
+
Index: /trunk/minix/lib/syslib/sys_irqctl.c
===================================================================
--- /trunk/minix/lib/syslib/sys_irqctl.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_irqctl.c	(revision 9)
@@ -0,0 +1,26 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                               sys_irqctl				     *
+ *===========================================================================*/
+PUBLIC int sys_irqctl(req, irq_vec, policy, hook_id)
+int req;				/* IRQ control request */
+int irq_vec;				/* IRQ vector to control */
+int policy;				/* bit mask for policy flags */
+int *hook_id;				/* ID of IRQ hook at kernel */
+{
+    message m_irq;
+    int s;
+    
+    m_irq.m_type = SYS_IRQCTL;
+    m_irq.IRQ_REQUEST = req;
+    m_irq.IRQ_VECTOR = irq_vec;
+    m_irq.IRQ_POLICY = policy;
+    m_irq.IRQ_HOOK_ID = *hook_id;
+    
+    s = _taskcall(SYSTASK, SYS_IRQCTL, &m_irq);
+    if (req == IRQ_SETPOLICY) *hook_id = m_irq.IRQ_HOOK_ID;
+    return(s);
+}
+
+
Index: /trunk/minix/lib/syslib/sys_kill.c
===================================================================
--- /trunk/minix/lib/syslib/sys_kill.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_kill.c	(revision 9)
@@ -0,0 +1,14 @@
+#include "syslib.h"
+
+PUBLIC int sys_kill(proc, signr)
+int proc;			/* which proc has exited */
+int signr;			/* signal number: 1 - 16 */
+{
+/* A proc has to be signaled via MM.  Tell the kernel. */
+  message m;
+
+  m.SIG_ENDPT = proc;
+  m.SIG_NUMBER = signr;
+  return(_taskcall(SYSTASK, SYS_KILL, &m));
+}
+
Index: /trunk/minix/lib/syslib/sys_memset.c
===================================================================
--- /trunk/minix/lib/syslib/sys_memset.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_memset.c	(revision 9)
@@ -0,0 +1,16 @@
+#include "syslib.h"
+
+PUBLIC int sys_memset(unsigned long pattern, phys_bytes base, phys_bytes bytes)
+{
+/* Zero a block of data.  */
+  message mess;
+
+  if (bytes == 0L) return(OK);
+
+  mess.MEM_PTR = (char *) base;
+  mess.MEM_COUNT   = bytes;
+  mess.MEM_PATTERN = pattern;
+
+  return(_taskcall(SYSTASK, SYS_MEMSET, &mess));
+}
+
Index: /trunk/minix/lib/syslib/sys_newmap.c
===================================================================
--- /trunk/minix/lib/syslib/sys_newmap.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_newmap.c	(revision 9)
@@ -0,0 +1,14 @@
+#include "syslib.h"
+
+PUBLIC int sys_newmap(proc, ptr)
+int proc;			/* process whose map is to be changed */
+struct mem_map *ptr;		/* pointer to new map */
+{
+/* A process has been assigned a new memory map.  Tell the kernel. */
+
+  message m;
+
+  m.PR_ENDPT = proc;
+  m.PR_MEM_PTR = (char *) ptr;
+  return(_taskcall(SYSTASK, SYS_NEWMAP, &m));
+}
Index: /trunk/minix/lib/syslib/sys_nice.c
===================================================================
--- /trunk/minix/lib/syslib/sys_nice.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_nice.c	(revision 9)
@@ -0,0 +1,13 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_nice			     	     *
+ *===========================================================================*/
+PUBLIC int sys_nice(int proc, int prio)
+{
+  message m;
+
+  m.m1_i1 = proc;
+  m.m1_i2 = prio;
+  return(_taskcall(SYSTASK, SYS_NICE, &m));
+}
Index: /trunk/minix/lib/syslib/sys_out.c
===================================================================
--- /trunk/minix/lib/syslib/sys_out.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_out.c	(revision 9)
@@ -0,0 +1,20 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_out				     *
+ *===========================================================================*/
+PUBLIC int sys_out(port, value, type)
+int port; 				/* port address to write to */
+unsigned long value;			/* value to write */
+int type;				/* byte, word, long */
+{
+    message m_io;
+
+    m_io.DIO_TYPE = type;
+    m_io.DIO_REQUEST = DIO_OUTPUT;
+    m_io.DIO_PORT = port;
+    m_io.DIO_VALUE = value;
+
+    return _taskcall(SYSTASK, SYS_DEVIO, &m_io);
+}
+
Index: /trunk/minix/lib/syslib/sys_physcopy.c
===================================================================
--- /trunk/minix/lib/syslib/sys_physcopy.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_physcopy.c	(revision 9)
@@ -0,0 +1,30 @@
+#include "syslib.h"
+
+PUBLIC int sys_physcopy(src_proc, src_seg, src_vir, 
+	dst_proc, dst_seg, dst_vir, bytes)
+int src_proc;			/* source process */
+int src_seg;			/* source memory segment */
+vir_bytes src_vir;		/* source virtual address */
+int dst_proc;			/* destination process */
+int dst_seg;			/* destination memory segment */
+vir_bytes dst_vir;		/* destination virtual address */
+phys_bytes bytes;		/* how many bytes */
+{
+/* Transfer a block of data.  The source and destination can each either be a
+ * process number or SELF (to indicate own process number). Virtual addresses 
+ * are offsets within LOCAL_SEG (text, stack, data), REMOTE_SEG, or BIOS_SEG. 
+ * Physicall addressing is also possible with PHYS_SEG.
+ */
+
+  message copy_mess;
+
+  if (bytes == 0L) return(OK);
+  copy_mess.CP_SRC_ENDPT = src_proc;
+  copy_mess.CP_SRC_SPACE = src_seg;
+  copy_mess.CP_SRC_ADDR = (long) src_vir;
+  copy_mess.CP_DST_ENDPT = dst_proc;
+  copy_mess.CP_DST_SPACE = dst_seg;
+  copy_mess.CP_DST_ADDR = (long) dst_vir;
+  copy_mess.CP_NR_BYTES = (long) bytes;
+  return(_taskcall(SYSTASK, SYS_PHYSCOPY, &copy_mess));
+}
Index: /trunk/minix/lib/syslib/sys_privctl.c
===================================================================
--- /trunk/minix/lib/syslib/sys_privctl.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_privctl.c	(revision 9)
@@ -0,0 +1,13 @@
+#include "syslib.h"
+
+int sys_privctl(int proc, int request, int i, void *p)
+{
+  message m;
+
+  m.CTL_ENDPT = proc;
+  m.CTL_REQUEST = request;
+  m.CTL_MM_PRIV = i;
+  m.CTL_ARG_PTR = p;
+
+  return _taskcall(SYSTASK, SYS_PRIVCTL, &m);
+}
Index: /trunk/minix/lib/syslib/sys_sdevio.c
===================================================================
--- /trunk/minix/lib/syslib/sys_sdevio.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_sdevio.c	(revision 9)
@@ -0,0 +1,26 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_sdevio				     *
+ *===========================================================================*/
+PUBLIC int sys_sdevio(req, port, type, proc_nr, buffer, count)
+int req;				/* request: DIO_INPUT/ DIO_OUTPUT */
+long port; 				/* port address to read from */
+int type;				/* byte, word, long */
+int proc_nr;				/* process where buffer is */
+void *buffer;				/* pointer to buffer */
+int count;				/* number of elements */
+{
+    message m_io;
+    int result;
+
+    m_io.DIO_REQUEST = req;
+    m_io.DIO_TYPE = type;
+    m_io.DIO_PORT = port;
+    m_io.DIO_VEC_ENDPT = proc_nr;
+    m_io.DIO_VEC_ADDR = buffer;
+    m_io.DIO_VEC_SIZE = count;
+
+    return(_taskcall(SYSTASK, SYS_SDEVIO, &m_io));
+}
+
Index: /trunk/minix/lib/syslib/sys_segctl.c
===================================================================
--- /trunk/minix/lib/syslib/sys_segctl.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_segctl.c	(revision 9)
@@ -0,0 +1,24 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                               sys_segctl				     *    
+ *===========================================================================*/
+PUBLIC int sys_segctl(index, seg, off, phys, size)
+int *index;				/* return index of remote segment */
+u16_t *seg;				/* return segment selector here */
+vir_bytes *off;				/* return offset in segment here */
+phys_bytes phys;			/* physical address to convert */
+vir_bytes size;				/* size of segment */
+{
+    message m;
+    int s;
+    m.SEG_PHYS = phys;
+    m.SEG_SIZE = size;
+    s = _taskcall(SYSTASK, SYS_SEGCTL, &m);
+    *index = (int) m.SEG_INDEX;
+    *seg = (u16_t) m.SEG_SELECT;
+    *off = (vir_bytes) m.SEG_OFFSET;
+    return s;
+}
+
+
Index: /trunk/minix/lib/syslib/sys_setalarm.c
===================================================================
--- /trunk/minix/lib/syslib/sys_setalarm.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_setalarm.c	(revision 9)
@@ -0,0 +1,18 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                               sys_setalarm		     	     	     *
+ *===========================================================================*/
+PUBLIC int sys_setalarm(exp_time, abs_time)
+clock_t exp_time;	/* expiration time for the alarm */
+int abs_time;		/* use absolute or relative expiration time */
+{
+/* Ask the SYSTEM schedule a synchronous alarm for the caller. The process
+ * number can be SELF if the caller doesn't know its process number.
+ */
+    message m;
+    m.ALRM_EXP_TIME = exp_time;		/* the expiration time */
+    m.ALRM_ABS_TIME = abs_time;		/* time is absolute? */
+    return _taskcall(SYSTASK, SYS_SETALARM, &m);
+}
+
Index: /trunk/minix/lib/syslib/sys_sigreturn.c
===================================================================
--- /trunk/minix/lib/syslib/sys_sigreturn.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_sigreturn.c	(revision 9)
@@ -0,0 +1,18 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_sigreturn				     *
+ *===========================================================================*/
+PUBLIC int sys_sigreturn(proc_nr, sig_ctxt)
+int proc_nr;				/* for which process */
+struct sigmsg *sig_ctxt;		/* POSIX style handling */
+{
+    message m;
+    int result;
+
+    m.SIG_ENDPT = proc_nr;
+    m.SIG_CTXT_PTR = (char *) sig_ctxt;
+    result = _taskcall(SYSTASK, SYS_SIGRETURN, &m);
+    return(result);
+}
+
Index: /trunk/minix/lib/syslib/sys_sigsend.c
===================================================================
--- /trunk/minix/lib/syslib/sys_sigsend.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_sigsend.c	(revision 9)
@@ -0,0 +1,18 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_sigsend				     *
+ *===========================================================================*/
+PUBLIC int sys_sigsend(proc_nr, sig_ctxt)
+int proc_nr;				/* for which process */
+struct sigmsg *sig_ctxt;		/* POSIX style handling */
+{
+    message m;
+    int result;
+
+    m.SIG_ENDPT = proc_nr;
+    m.SIG_CTXT_PTR = (char *) sig_ctxt;
+    result = _taskcall(SYSTASK, SYS_SIGSEND, &m);
+    return(result);
+}
+
Index: /trunk/minix/lib/syslib/sys_svrctl.c
===================================================================
--- /trunk/minix/lib/syslib/sys_svrctl.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_svrctl.c	(revision 9)
@@ -0,0 +1,13 @@
+#include "syslib.h"
+
+int sys_svrctl(int proc, int request, int priv, vir_bytes argp)
+{
+  message m;
+
+  m.CTL_ENDPT = proc;
+  m.CTL_REQUEST = request;
+  m.CTL_MM_PRIV = priv;
+  m.CTL_ARG_PTR = (char *) argp;
+
+  return _taskcall(SYSTASK, SYS_PRIVCTL, &m);
+}
Index: /trunk/minix/lib/syslib/sys_times.c
===================================================================
--- /trunk/minix/lib/syslib/sys_times.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_times.c	(revision 9)
@@ -0,0 +1,19 @@
+#include "syslib.h"
+
+PUBLIC int sys_times(proc, ptr)
+int proc;			/* proc whose times are needed */
+clock_t ptr[5];			/* pointer to time buffer */
+{
+/* Fetch the accounting info for a proc. */
+  message m;
+  int r;
+
+  m.T_ENDPT = proc;
+  r = _taskcall(SYSTASK, SYS_TIMES, &m);
+  ptr[0] = m.T_USER_TIME;
+  ptr[1] = m.T_SYSTEM_TIME;
+  ptr[2] = m.T_CHILD_UTIME;
+  ptr[3] = m.T_CHILD_STIME;
+  ptr[4] = m.T_BOOT_TICKS;
+  return(r);
+}
Index: /trunk/minix/lib/syslib/sys_trace.c
===================================================================
--- /trunk/minix/lib/syslib/sys_trace.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_trace.c	(revision 9)
@@ -0,0 +1,17 @@
+#include "syslib.h"
+
+PUBLIC int sys_trace(req, proc_nr, addr, data_p)
+int req, proc_nr;
+long addr, *data_p;
+{
+  message m;
+  int r;
+
+  m.CTL_ENDPT = proc_nr;
+  m.CTL_REQUEST = req;
+  m.CTL_ADDRESS = addr;
+  if (data_p) m.CTL_DATA = *data_p;
+  r = _taskcall(SYSTASK, SYS_TRACE, &m);
+  if (data_p) *data_p = m.CTL_DATA;
+  return(r);
+}
Index: /trunk/minix/lib/syslib/sys_umap.c
===================================================================
--- /trunk/minix/lib/syslib/sys_umap.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_umap.c	(revision 9)
@@ -0,0 +1,25 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_umap				     *
+ *===========================================================================*/
+PUBLIC int sys_umap(proc_nr, seg, vir_addr, bytes, phys_addr)
+int proc_nr; 				/* process number to do umap for */
+int seg;				/* T, D, or S segment */
+vir_bytes vir_addr;			/* address in bytes with segment*/
+vir_bytes bytes;			/* number of bytes to be copied */
+phys_bytes *phys_addr;			/* placeholder for result */
+{
+    message m;
+    int result;
+
+    m.CP_SRC_ENDPT = proc_nr;
+    m.CP_SRC_SPACE = seg;
+    m.CP_SRC_ADDR = vir_addr;
+    m.CP_NR_BYTES = bytes;
+
+    result = _taskcall(SYSTASK, SYS_UMAP, &m);
+    *phys_addr = m.CP_DST_ADDR;
+    return(result);
+}
+
Index: /trunk/minix/lib/syslib/sys_vinb.c
===================================================================
--- /trunk/minix/lib/syslib/sys_vinb.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_vinb.c	(revision 9)
@@ -0,0 +1,18 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_vinb				     *
+ *===========================================================================*/
+PUBLIC int sys_vinb(pvb_pairs, nr_ports)
+pvb_pair_t *pvb_pairs;			/* (port,byte-value)-pairs */
+int nr_ports;				/* nr of pairs to be processed */
+{
+    message m_io;
+
+    m_io.DIO_TYPE = DIO_BYTE;
+    m_io.DIO_REQUEST = DIO_INPUT;
+    m_io.DIO_VEC_ADDR = (char *) pvb_pairs;
+    m_io.DIO_VEC_SIZE = nr_ports;
+    return _taskcall(SYSTASK, SYS_VDEVIO, &m_io);
+}
+
Index: /trunk/minix/lib/syslib/sys_vinl.c
===================================================================
--- /trunk/minix/lib/syslib/sys_vinl.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_vinl.c	(revision 9)
@@ -0,0 +1,18 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_vinl				     *
+ *===========================================================================*/
+PUBLIC int sys_vinl(pvl_pairs, nr_ports)
+pvl_pair_t *pvl_pairs;			/* (port,long-value)-pairs */
+int nr_ports;				/* nr of pairs to be processed */
+{
+    message m_io;
+
+    m_io.DIO_TYPE = DIO_LONG;
+    m_io.DIO_REQUEST = DIO_INPUT;
+    m_io.DIO_VEC_ADDR = (char *) pvl_pairs;
+    m_io.DIO_VEC_SIZE = nr_ports;
+    return _taskcall(SYSTASK, SYS_VDEVIO, &m_io);
+}
+
Index: /trunk/minix/lib/syslib/sys_vinw.c
===================================================================
--- /trunk/minix/lib/syslib/sys_vinw.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_vinw.c	(revision 9)
@@ -0,0 +1,19 @@
+#include "syslib.h"
+
+
+/*===========================================================================*
+ *                                sys_vinw				     *
+ *===========================================================================*/
+PUBLIC int sys_vinw(pvw_pairs, nr_ports)
+pvw_pair_t *pvw_pairs;			/* (port,word-value)-pairs */
+int nr_ports;				/* nr of pairs to be processed */
+{
+    message m_io;
+
+    m_io.DIO_TYPE = DIO_WORD;
+    m_io.DIO_REQUEST = DIO_INPUT;
+    m_io.DIO_VEC_ADDR = (char *) pvw_pairs;
+    m_io.DIO_VEC_SIZE = nr_ports;
+    return _taskcall(SYSTASK, SYS_VDEVIO, &m_io);
+}
+
Index: /trunk/minix/lib/syslib/sys_vircopy.c
===================================================================
--- /trunk/minix/lib/syslib/sys_vircopy.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_vircopy.c	(revision 9)
@@ -0,0 +1,29 @@
+#include "syslib.h"
+
+PUBLIC int sys_vircopy(src_proc, src_seg, src_vir, 
+	dst_proc, dst_seg, dst_vir, bytes)
+int src_proc;			/* source process */
+int src_seg;			/* source memory segment */
+vir_bytes src_vir;		/* source virtual address */
+int dst_proc;			/* destination process */
+int dst_seg;			/* destination memory segment */
+vir_bytes dst_vir;		/* destination virtual address */
+phys_bytes bytes;		/* how many bytes */
+{
+/* Transfer a block of data.  The source and destination can each either be a
+ * process number or SELF (to indicate own process number). Virtual addresses 
+ * are offsets within LOCAL_SEG (text, stack, data), REMOTE_SEG, or BIOS_SEG. 
+ */
+
+  message copy_mess;
+
+  if (bytes == 0L) return(OK);
+  copy_mess.CP_SRC_ENDPT = src_proc;
+  copy_mess.CP_SRC_SPACE = src_seg;
+  copy_mess.CP_SRC_ADDR = (long) src_vir;
+  copy_mess.CP_DST_ENDPT = dst_proc;
+  copy_mess.CP_DST_SPACE = dst_seg;
+  copy_mess.CP_DST_ADDR = (long) dst_vir;
+  copy_mess.CP_NR_BYTES = (long) bytes;
+  return(_taskcall(SYSTASK, SYS_VIRCOPY, &copy_mess));
+}
Index: /trunk/minix/lib/syslib/sys_vm_map.c
===================================================================
--- /trunk/minix/lib/syslib/sys_vm_map.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_vm_map.c	(revision 9)
@@ -0,0 +1,25 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_vm_map				     *
+ *===========================================================================*/
+PUBLIC int sys_vm_map(proc_nr, do_map, base, size, offset)
+int proc_nr;
+int do_map;
+phys_bytes base;
+phys_bytes size;
+phys_bytes offset;
+{
+    message m;
+    int result;
+
+    m.m4_l1= proc_nr;
+    m.m4_l2= do_map;
+    m.m4_l3= base;
+    m.m4_l4= size;
+    m.m4_l5= offset;
+
+    result = _taskcall(SYSTASK, SYS_VM_MAP, &m);
+    return(result);
+}
+
Index: /trunk/minix/lib/syslib/sys_vm_setbuf.c
===================================================================
--- /trunk/minix/lib/syslib/sys_vm_setbuf.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_vm_setbuf.c	(revision 9)
@@ -0,0 +1,21 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_vm_setbuf				     *
+ *===========================================================================*/
+PUBLIC int sys_vm_setbuf(base, size, high)
+phys_bytes base;
+phys_bytes size;
+phys_bytes high;
+{
+    message m;
+    int result;
+
+    m.m4_l1= base;
+    m.m4_l2= size;
+    m.m4_l3= high;
+
+    result = _taskcall(SYSTASK, SYS_VM_SETBUF, &m);
+    return(result);
+}
+
Index: /trunk/minix/lib/syslib/sys_voutb.c
===================================================================
--- /trunk/minix/lib/syslib/sys_voutb.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_voutb.c	(revision 9)
@@ -0,0 +1,18 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_voutb				     *
+ *===========================================================================*/
+PUBLIC int sys_voutb(pvb_pairs, nr_ports)
+pvb_pair_t *pvb_pairs;			/* (port,byte-value)-pairs */
+int nr_ports;				/* nr of pairs to be processed */
+{
+    message m_io;
+    m_io.DIO_TYPE = DIO_BYTE;
+    m_io.DIO_REQUEST = DIO_OUTPUT;
+    m_io.DIO_VEC_ADDR = (char *) pvb_pairs;
+    m_io.DIO_VEC_SIZE = nr_ports;
+    return _taskcall(SYSTASK, SYS_VDEVIO, &m_io);
+}
+
+
Index: /trunk/minix/lib/syslib/sys_voutl.c
===================================================================
--- /trunk/minix/lib/syslib/sys_voutl.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_voutl.c	(revision 9)
@@ -0,0 +1,18 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_voutl				     *
+ *===========================================================================*/
+PUBLIC int sys_voutl(pvl_pairs, nr_ports)
+pvl_pair_t *pvl_pairs;			/* (port,long-value)-pairs */
+int nr_ports;				/* nr of pairs to be processed */
+{
+    message m_io;
+
+    m_io.DIO_TYPE = DIO_LONG;
+    m_io.DIO_REQUEST = DIO_OUTPUT;
+    m_io.DIO_VEC_ADDR = (char *) pvl_pairs;
+    m_io.DIO_VEC_SIZE = nr_ports;
+    return _taskcall(SYSTASK, SYS_VDEVIO, &m_io);
+}
+
Index: /trunk/minix/lib/syslib/sys_voutw.c
===================================================================
--- /trunk/minix/lib/syslib/sys_voutw.c	(revision 9)
+++ /trunk/minix/lib/syslib/sys_voutw.c	(revision 9)
@@ -0,0 +1,19 @@
+#include "syslib.h"
+
+
+/*===========================================================================*
+ *                                sys_voutw				     *
+ *===========================================================================*/
+PUBLIC int sys_voutw(pvw_pairs, nr_ports)
+pvw_pair_t *pvw_pairs;			/* (port,word-value)-pairs */
+int nr_ports;				/* nr of pairs to be processed */
+{
+    message m_io;
+
+    m_io.DIO_TYPE = DIO_WORD;
+    m_io.DIO_REQUEST = DIO_OUTPUT;
+    m_io.DIO_VEC_ADDR = (char *) pvw_pairs;
+    m_io.DIO_VEC_SIZE = nr_ports;
+    return _taskcall(SYSTASK, SYS_VDEVIO, &m_io);
+}
+
Index: /trunk/minix/lib/syslib/syslib.h
===================================================================
--- /trunk/minix/lib/syslib/syslib.h	(revision 9)
+++ /trunk/minix/lib/syslib/syslib.h	(revision 9)
@@ -0,0 +1,7 @@
+/*	syslib.h - System library common definitions.	*/
+
+#define _SYSTEM
+
+#include <lib.h>
+#include <minix/com.h>
+#include <minix/syslib.h>
Index: /trunk/minix/lib/syslib/taskcall.c
===================================================================
--- /trunk/minix/lib/syslib/taskcall.c	(revision 9)
+++ /trunk/minix/lib/syslib/taskcall.c	(revision 9)
@@ -0,0 +1,20 @@
+/* _taskcall() is the same as _syscall() except it returns negative error
+ * codes directly and not in errno.  This is a better interface for MM and
+ * FS.
+ */
+
+#include <lib.h>
+#include <minix/syslib.h>
+
+PUBLIC int _taskcall(who, syscallnr, msgptr)
+int who;
+int syscallnr;
+register message *msgptr;
+{
+  int status;
+
+  msgptr->m_type = syscallnr;
+  status = _sendrec(who, msgptr);
+  if (status != 0) return(status);
+  return(msgptr->m_type);
+}
Index: /trunk/minix/lib/sysutil/Makedepend-ack
===================================================================
--- /trunk/minix/lib/sysutil/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/sysutil/Makedepend-ack	(revision 9)
@@ -0,0 +1,15 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' kmalloc.c | sed -e 's:^\(.\):../obj-ack//./sysutil/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' kprintf.c | sed -e 's:^\(.\):../obj-ack//./sysutil/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' kputc.c | sed -e 's:^\(.\):../obj-ack//./sysutil/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' tickdelay.c | sed -e 's:^\(.\):../obj-ack//./sysutil/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' getuptime.c | sed -e 's:^\(.\):../obj-ack//./sysutil/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' env_get_prm.c | sed -e 's:^\(.\):../obj-ack//./sysutil/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' env_parse.c | sed -e 's:^\(.\):../obj-ack//./sysutil/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' env_panic.c | sed -e 's:^\(.\):../obj-ack//./sysutil/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' env_prefix.c | sed -e 's:^\(.\):../obj-ack//./sysutil/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' fkey_ctl.c | sed -e 's:^\(.\):../obj-ack//./sysutil/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' report.c | sed -e 's:^\(.\):../obj-ack//./sysutil/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' taskcall.c | sed -e 's:^\(.\):../obj-ack//./sysutil/\1:' >> .depend-ack
Index: /trunk/minix/lib/sysutil/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/sysutil/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/sysutil/Makedepend-gnu	(revision 9)
@@ -0,0 +1,15 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' kmalloc.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./sysutil/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' kprintf.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./sysutil/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' kputc.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./sysutil/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' tickdelay.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./sysutil/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' getuptime.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./sysutil/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' env_get_prm.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./sysutil/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' env_parse.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./sysutil/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' env_panic.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./sysutil/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' env_prefix.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./sysutil/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' fkey_ctl.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./sysutil/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' report.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./sysutil/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' taskcall.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./sysutil/\1:' >> .depend-gnu
Index: /trunk/minix/lib/sysutil/Makefile
===================================================================
--- /trunk/minix/lib/sysutil/Makefile	(revision 9)
+++ /trunk/minix/lib/sysutil/Makefile	(revision 9)
@@ -0,0 +1,129 @@
+#Generated from ./sysutil/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./sysutil ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./sysutil ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libsysutil.a
+
+../obj-ack//libsysutil.a: ../obj-ack//libsysutil.a(kmalloc.o)
+../obj-ack//libsysutil.a: ../obj-ack//libsysutil.a(kprintf.o)
+../obj-ack//libsysutil.a: ../obj-ack//libsysutil.a(kputc.o)
+../obj-ack//libsysutil.a: ../obj-ack//libsysutil.a(tickdelay.o)
+../obj-ack//libsysutil.a: ../obj-ack//libsysutil.a(getuptime.o)
+../obj-ack//libsysutil.a: ../obj-ack//libsysutil.a(env_get_prm.o)
+../obj-ack//libsysutil.a: ../obj-ack//libsysutil.a(env_parse.o)
+../obj-ack//libsysutil.a: ../obj-ack//libsysutil.a(env_panic.o)
+../obj-ack//libsysutil.a: ../obj-ack//libsysutil.a(env_prefix.o)
+../obj-ack//libsysutil.a: ../obj-ack//libsysutil.a(fkey_ctl.o)
+../obj-ack//libsysutil.a: ../obj-ack//libsysutil.a(report.o)
+../obj-ack//libsysutil.a: ../obj-ack//libsysutil.a(taskcall.o)
+
+../obj-ack//libsysutil.a:
+	ar cr ../obj-ack//libsysutil.a ../obj-ack//./sysutil/*.o
+	rm ../obj-ack//./sysutil/*.o
+
+../obj-ack//libsysutil.a(kmalloc.o): kmalloc.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./sysutil/kmalloc.o kmalloc.c
+../obj-ack//libsysutil.a(kprintf.o): kprintf.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./sysutil/kprintf.o kprintf.c
+../obj-ack//libsysutil.a(kputc.o): kputc.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./sysutil/kputc.o kputc.c
+../obj-ack//libsysutil.a(tickdelay.o): tickdelay.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./sysutil/tickdelay.o tickdelay.c
+../obj-ack//libsysutil.a(getuptime.o): getuptime.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./sysutil/getuptime.o getuptime.c
+../obj-ack//libsysutil.a(env_get_prm.o): env_get_prm.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./sysutil/env_get_prm.o env_get_prm.c
+../obj-ack//libsysutil.a(env_parse.o): env_parse.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./sysutil/env_parse.o env_parse.c
+../obj-ack//libsysutil.a(env_panic.o): env_panic.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./sysutil/env_panic.o env_panic.c
+../obj-ack//libsysutil.a(env_prefix.o): env_prefix.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./sysutil/env_prefix.o env_prefix.c
+../obj-ack//libsysutil.a(fkey_ctl.o): fkey_ctl.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./sysutil/fkey_ctl.o fkey_ctl.c
+../obj-ack//libsysutil.a(report.o): report.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./sysutil/report.o report.c
+../obj-ack//libsysutil.a(taskcall.o): taskcall.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./sysutil/taskcall.o taskcall.c
+
+all-gnu: ../obj-gnu/libsysutil.a
+
+../obj-gnu/libsysutil.a: ../obj-gnu/./sysutil/kmalloc.o
+../obj-gnu/libsysutil.a: ../obj-gnu/./sysutil/kprintf.o
+../obj-gnu/libsysutil.a: ../obj-gnu/./sysutil/kputc.o
+../obj-gnu/libsysutil.a: ../obj-gnu/./sysutil/tickdelay.o
+../obj-gnu/libsysutil.a: ../obj-gnu/./sysutil/getuptime.o
+../obj-gnu/libsysutil.a: ../obj-gnu/./sysutil/env_get_prm.o
+../obj-gnu/libsysutil.a: ../obj-gnu/./sysutil/env_parse.o
+../obj-gnu/libsysutil.a: ../obj-gnu/./sysutil/env_panic.o
+../obj-gnu/libsysutil.a: ../obj-gnu/./sysutil/env_prefix.o
+../obj-gnu/libsysutil.a: ../obj-gnu/./sysutil/fkey_ctl.o
+../obj-gnu/libsysutil.a: ../obj-gnu/./sysutil/report.o
+../obj-gnu/libsysutil.a: ../obj-gnu/./sysutil/taskcall.o
+
+../obj-gnu/libsysutil.a:
+	gar cr ../obj-gnu/libsysutil.a $?
+
+../obj-gnu/./sysutil/kmalloc.o: kmalloc.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./sysutil/kmalloc.o kmalloc.c
+
+../obj-gnu/./sysutil/kprintf.o: kprintf.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./sysutil/kprintf.o kprintf.c
+
+../obj-gnu/./sysutil/kputc.o: kputc.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./sysutil/kputc.o kputc.c
+
+../obj-gnu/./sysutil/tickdelay.o: tickdelay.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./sysutil/tickdelay.o tickdelay.c
+
+../obj-gnu/./sysutil/getuptime.o: getuptime.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./sysutil/getuptime.o getuptime.c
+
+../obj-gnu/./sysutil/env_get_prm.o: env_get_prm.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./sysutil/env_get_prm.o env_get_prm.c
+
+../obj-gnu/./sysutil/env_parse.o: env_parse.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./sysutil/env_parse.o env_parse.c
+
+../obj-gnu/./sysutil/env_panic.o: env_panic.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./sysutil/env_panic.o env_panic.c
+
+../obj-gnu/./sysutil/env_prefix.o: env_prefix.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./sysutil/env_prefix.o env_prefix.c
+
+../obj-gnu/./sysutil/fkey_ctl.o: fkey_ctl.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./sysutil/fkey_ctl.o fkey_ctl.c
+
+../obj-gnu/./sysutil/report.o: report.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./sysutil/report.o report.c
+
+../obj-gnu/./sysutil/taskcall.o: taskcall.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./sysutil/taskcall.o taskcall.c
+
+
+
+
+clean::
+	rm -f ../obj-ack//./sysutil/*
+	rm -f ../obj-gnu/./sysutil/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/sysutil/Makefile.in
===================================================================
--- /trunk/minix/lib/sysutil/Makefile.in	(revision 9)
+++ /trunk/minix/lib/sysutil/Makefile.in	(revision 9)
@@ -0,0 +1,21 @@
+# Makefile for lib/utils.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
+
+LIBRARIES=libsysutil
+
+libsysutil_FILES=" \
+	kmalloc.c \
+	kprintf.c \
+	kputc.c \
+	tickdelay.c \
+	getuptime.c \
+	env_get_prm.c \
+	env_parse.c \
+	env_panic.c \
+	env_prefix.c \
+	fkey_ctl.c \
+	report.c \
+	taskcall.c"
+
+TYPE=both
Index: /trunk/minix/lib/sysutil/env_get_prm.c
===================================================================
--- /trunk/minix/lib/sysutil/env_get_prm.c	(revision 9)
+++ /trunk/minix/lib/sysutil/env_get_prm.c	(revision 9)
@@ -0,0 +1,97 @@
+#include "sysutil.h"
+#include <minix/config.h>
+#include <string.h>
+
+PRIVATE int argc = 0;
+PRIVATE char **argv = NULL;
+
+FORWARD _PROTOTYPE( char *find_key, (const char *params, const char *key));
+
+/*===========================================================================*
+ *				env_setargs				     *
+ *===========================================================================*/
+PUBLIC void env_setargs(arg_c, arg_v)
+int arg_c;
+char *arg_v[];
+{
+	argc= arg_c;
+	argv= arg_v;
+}
+
+/*===========================================================================*
+ *				env_get_param				     *
+ *===========================================================================*/
+PUBLIC int env_get_param(key, value, max_len)
+char *key;				/* which key to look up */
+char *value;				/* where to store value */
+int max_len;				/* maximum length of value */
+{
+  message m;
+  static char mon_params[128*sizeof(char *)];	/* copy parameters here */
+  char *key_value;
+  int i, s, keylen;
+
+  if (key == NULL)
+  	return EINVAL;
+
+  keylen= strlen(key);
+  for (i= 1; i<argc; i++)
+  {
+  	if (strncmp(argv[i], key, keylen) != 0)
+  		continue;
+	if (strlen(argv[i]) <= keylen)
+		continue;
+	if (argv[i][keylen] != '=')
+		continue;
+	key_value= argv[i]+keylen+1;
+	if (strlen(key_value)+1 > EP_BUF_SIZE)
+	      return(E2BIG);
+	strcpy(value, key_value);
+	return OK;
+  }
+
+  /* Get copy of boot monitor parameters. */
+  m.m_type = SYS_GETINFO;
+  m.I_REQUEST = GET_MONPARAMS;
+  m.I_ENDPT = SELF;
+  m.I_VAL_LEN = sizeof(mon_params);
+  m.I_VAL_PTR = mon_params;
+  if ((s=_taskcall(SYSTASK, SYS_GETINFO, &m)) != OK) {
+	printf("SYS_GETINFO: %d (size %u)\n", s, sizeof(mon_params));
+	return(s);
+  }
+
+  /* We got a copy, now search requested key. */
+  if ((key_value = find_key(mon_params, key)) == NULL)
+	return(ESRCH);
+
+  /* Value found, make the actual copy (as far as possible). */
+  strncpy(value, key_value, max_len);
+
+  /* See if it fits in the client's buffer. */
+  if ((strlen(key_value)+1) > max_len) return(E2BIG);
+  return(OK);
+}
+
+
+/*==========================================================================*
+ *				find_key					    *
+ *==========================================================================*/
+PRIVATE char *find_key(params,name)
+const char *params;
+const char *name;
+{
+  register const char *namep;
+  register char *envp;
+
+  for (envp = (char *) params; *envp != 0;) {
+	for (namep = name; *namep != 0 && *namep == *envp; namep++, envp++)
+		;
+	if (*namep == '\0' && *envp == '=') 
+		return(envp + 1);
+	while (*envp++ != 0)
+		;
+  }
+  return(NULL);
+}
+
Index: /trunk/minix/lib/sysutil/env_panic.c
===================================================================
--- /trunk/minix/lib/sysutil/env_panic.c	(revision 9)
+++ /trunk/minix/lib/sysutil/env_panic.c	(revision 9)
@@ -0,0 +1,19 @@
+#include "sysutil.h"
+#include <string.h>
+
+/*=========================================================================*
+ *				env_panic				   *
+ *=========================================================================*/
+PUBLIC void env_panic(key)
+char *key;		/* environment variable whose value is bogus */
+{
+  static char value[EP_BUF_SIZE] = "<unknown>";
+  int s;
+  if ((s=env_get_param(key, value, sizeof(value))) == 0) {
+  	if (s != ESRCH)		/* only error allowed */
+  	printf("WARNING: get_mon_param() failed in env_panic(): %d\n", s);
+  }
+  printf("Bad environment setting: '%s = %s'\n", key, value);
+  panic("","", NO_NUM);
+}
+
Index: /trunk/minix/lib/sysutil/env_parse.c
===================================================================
--- /trunk/minix/lib/sysutil/env_parse.c	(revision 9)
+++ /trunk/minix/lib/sysutil/env_parse.c	(revision 9)
@@ -0,0 +1,90 @@
+#include "sysutil.h"
+#include <stdlib.h>
+#include <string.h>
+
+
+/*=========================================================================*
+ *				env_parse				   *
+ *=========================================================================*/
+PUBLIC int env_parse(env, fmt, field, param, min, max)
+char *env;		/* environment variable to inspect */
+char *fmt;		/* template to parse it with */
+int field;		/* field number of value to return */
+long *param;		/* address of parameter to get */
+long min, max;		/* minimum and maximum values for the parameter */
+{
+/* Parse an environment variable setting, something like "DPETH0=300:3".
+ * Panic if the parsing fails.  Return EP_UNSET if the environment variable
+ * is not set, EP_OFF if it is set to "off", EP_ON if set to "on" or a
+ * field is left blank, or EP_SET if a field is given (return value through
+ * *param).  Punctuation may be used in the environment and format string,
+ * fields in the environment string may be empty, and punctuation may be
+ * missing to skip fields.  The format string contains characters 'd', 'o',
+ * 'x' and 'c' to indicate that 10, 8, 16, or 0 is used as the last argument
+ * to strtol().  A '*' means that a field should be skipped.  If the format
+ * string contains something like "\4" then the string is repeated 4 characters
+ * to the left.
+ */
+  char *val, *end;
+  char value[EP_BUF_SIZE];
+  char PUNCT[] = ":,;.";
+  long newpar;
+  int s, i, radix, r, keylen;
+
+  if ((s=env_get_param(env, value, sizeof(value))) != 0) { 
+      if (s == ESRCH) return(EP_UNSET);		/* only error allowed */ 
+      printf("WARNING: get_mon_param() failed in env_parse(): %d\n",s);
+      return(EP_EGETKENV);
+  }
+  val = value;
+  if (strcmp(val, "off") == 0) return(EP_OFF);
+  if (strcmp(val, "on") == 0) return(EP_ON);
+
+  i = 0;
+  r = EP_ON;
+  for (;;) {
+	while (*val == ' ') val++;	/* skip spaces */
+	if (*val == 0) return(r);	/* the proper exit point */
+	if (*fmt == 0) break;		/* too many values */
+
+	if (strchr(PUNCT, *val) != NULL) {
+		/* Time to go to the next field. */
+		if (strchr(PUNCT, *fmt) != NULL) i++;
+		if (*fmt++ == *val) val++;
+		if (*fmt < 32) fmt -= *fmt;	/* step back? */
+	} else {
+		/* Environment contains a value, get it. */
+		switch (*fmt) {
+		case '*':	radix =   -1;	break;
+		case 'd':	radix =   10;	break;
+		case 'o':	radix =  010;	break;
+		case 'x':	radix = 0x10;	break;
+		case 'c':	radix =    0;	break;
+		default:	goto badenv;
+		}
+		
+		if (radix < 0) {
+			/* Skip. */
+			while (strchr(PUNCT, *val) == NULL) val++;
+			continue;
+		} else {
+			/* A number. */
+			newpar = strtol(val, &end, radix);
+
+			if (end == val) break;	/* not a number */
+			val = end;
+		}
+
+		if (i == field) {
+			/* The field requested. */
+			if (newpar < min || newpar > max) break;
+			*param = newpar;
+			r = EP_SET;
+		}
+	}
+  }
+badenv:
+  env_panic(env);
+}
+
+
Index: /trunk/minix/lib/sysutil/env_prefix.c
===================================================================
--- /trunk/minix/lib/sysutil/env_prefix.c	(revision 9)
+++ /trunk/minix/lib/sysutil/env_prefix.c	(revision 9)
@@ -0,0 +1,30 @@
+#include "sysutil.h"
+#include <stdlib.h>
+#include <string.h>
+
+/*=========================================================================*
+ *				env_prefix				   *
+ *=========================================================================*/
+PUBLIC int env_prefix(env, prefix)
+char *env;		/* environment variable to inspect */
+char *prefix;		/* prefix to test for */
+{
+/* An environment setting may be prefixed by a word, usually "pci".  
+ * Return TRUE if a given prefix is used.
+ */
+  char value[EP_BUF_SIZE];
+  char punct[] = ":,;.";
+  int i, s, keylen;
+  char *val;
+  size_t n;
+
+  if ((s = env_get_param(env, value, sizeof(value))) != 0) {
+  	if (s != ESRCH)		/* only error allowed */
+  	printf("WARNING: get_mon_param() failed in env_prefix(): %d\n", s);	
+  }
+  n = strlen(prefix);
+  return(value != NULL
+	&& strncmp(value, prefix, n) == 0
+	&& strchr(punct, value[n]) != NULL);
+}
+
Index: /trunk/minix/lib/sysutil/fkey_ctl.c
===================================================================
--- /trunk/minix/lib/sysutil/fkey_ctl.c	(revision 9)
+++ /trunk/minix/lib/sysutil/fkey_ctl.c	(revision 9)
@@ -0,0 +1,27 @@
+#include "sysutil.h" 
+
+/*===========================================================================*
+ *				fkey_ctl				     *
+ *===========================================================================*/
+PUBLIC int fkey_ctl(request, fkeys, sfkeys)
+int request;				/* request to perform */
+int *fkeys;				/* bit masks for F1-F12 keys */
+int *sfkeys;				/* bit masks for Shift F1-F12 keys */
+{
+/* Send a message to the TTY server to request notifications for function 
+ * key presses or to disable notifications. Enabling succeeds unless the key
+ * is already bound to another process. Disabling only succeeds if the key is
+ * bound to the current process.   
+ */ 
+    message m;
+    int s;
+    m.FKEY_REQUEST = request;
+    m.FKEY_FKEYS = (fkeys) ? *fkeys : 0;
+    m.FKEY_SFKEYS = (sfkeys) ? *sfkeys : 0;
+    s = _taskcall(TTY_PROC_NR, FKEY_CONTROL, &m);
+    if (fkeys) *fkeys = m.FKEY_FKEYS;
+    if (sfkeys) *sfkeys = m.FKEY_SFKEYS;
+    return(s);
+}
+
+
Index: /trunk/minix/lib/sysutil/getuptime.c
===================================================================
--- /trunk/minix/lib/sysutil/getuptime.c	(revision 9)
+++ /trunk/minix/lib/sysutil/getuptime.c	(revision 9)
@@ -0,0 +1,22 @@
+#include "sysutil.h"
+
+/*===========================================================================*
+ *                               getuptime			    	     *
+ *===========================================================================*/
+PUBLIC int getuptime(ticks)
+clock_t *ticks;				/* uptime in ticks */
+{
+    message m;
+    int s;
+
+    m.m_type = SYS_TIMES;		/* request time information */
+    m.T_ENDPT = NONE;			/* ignore process times */
+    s = _taskcall(SYSTASK, SYS_TIMES, &m);
+    *ticks = m.T_BOOT_TICKS;
+    return(s);
+}
+
+
+
+
+
Index: /trunk/minix/lib/sysutil/kmalloc.c
===================================================================
--- /trunk/minix/lib/sysutil/kmalloc.c	(revision 9)
+++ /trunk/minix/lib/sysutil/kmalloc.c	(revision 9)
@@ -0,0 +1,177 @@
+/*	malloc(), realloc(), free() - simple memory allocation routines
+ *
+ * This is a very small and simple minded malloc	Author: Kees J. Bot
+ * implementation.  Ideal for things like a			29 Jan 1994
+ * bootstrap program, or for debugging.  Six times
+ * slower than any good malloc.
+ */
+#define nil 0
+
+#define sbrk _sbrk
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#if !DEBUG
+#define NDEBUG	1
+#define debug(expr)	((void) 0)
+#else
+#define debug(expr)	expr
+#endif
+#include <assert.h>
+
+typedef struct cell {
+	size_t		size;		/* Size of a malloc()'ed object. */
+#if DEBUG
+	unsigned	magic;		/* To recognize a cell. */
+#endif
+	struct cell	*next;		/* Next cell on the free list. */
+#if DEBUG
+	unsigned	sacred;		/* Don't touch while unallocated. */
+#endif
+} cell_t;
+
+#if UINT_MAX <= 0xFFFF
+#define MAGIC	0x537B
+#else
+#define MAGIC	0x537BC0D8
+#endif
+
+/* Size of the header of an object. */
+#define HDR_SIZE	offsetof(cell_t, next)
+
+/* An offset from a cell pointer to a next cell. */
+#define offset(cp, size)	((cell_t *) ((char *) (cp) + (size)))
+
+/* Address of the object in a cell and back. */
+#define cell2obj(cp)		((void *) ((char *) (cp) + HDR_SIZE))
+#define obj2cell(op)		((cell_t *) ((char *) (op) - HDR_SIZE))
+
+/* The free list. */
+static cell_t *freelist;
+
+void *malloc(size_t size)
+/* Allocate an object of at least the given size. */
+{
+	cell_t **pcp, *cp;
+
+	size += HDR_SIZE;
+	if (size < sizeof(cell_t)) size= sizeof(cell_t);
+
+	/* Align to a word.  Use a real malloc if you need better alignment. */
+	size= (size + sizeof(int) - 1) & ~(sizeof(int) - 1);
+
+	/* Space for a magic number at the end of the chunk. */
+	debug(size += sizeof(unsigned));
+
+	for (;;) {
+		/* Do a first fit search. */
+		pcp= &freelist;
+		while ((cp= *pcp) != nil) {
+			cell_t *next= cp->next;
+
+			assert(cp->magic == MAGIC);
+			assert(cp->sacred == MAGIC);
+
+			if (offset(cp, cp->size) == next) {
+				/* Join adjacent free cells. */
+				assert(next->magic == MAGIC);
+				assert(next->sacred == MAGIC);
+
+				cp->size+= next->size;
+				cp->next= next->next;
+
+				continue;		/* Try again. */
+			}
+			if (size <= cp->size) break;	/* Big enough. */
+
+			/* Next cell. */
+			pcp= &cp->next;
+		}
+
+		if (cp != nil) break;	/* Found a big enough chunk. */
+
+		/* Allocate a new chunk at the break. */
+		if ((cp= (cell_t *) sbrk(size)) == (cell_t *) -1) {
+			return nil;
+		}
+
+		cp->size= size;
+		cp->next= nil;
+		debug(cp->magic= MAGIC);
+		debug(cp->sacred= MAGIC);
+		*pcp= cp;
+	}
+
+	/* We've got a cell that is big enough.  Can we break it up? */
+	if (cp->size >= size + sizeof(cell_t)) {
+		cell_t *next= offset(cp, size);
+
+		next->size= cp->size - size;
+		next->next= cp->next;
+		debug(next->magic= MAGIC);
+		debug(next->sacred= MAGIC);
+		cp->size= size;
+		cp->next= next;
+	}
+
+	/* Unchain the cell we've found and return an address in it. */
+	*pcp= cp->next;
+	debug(memset(cell2obj(cp), 0xAA, cp->size - HDR_SIZE));
+	debug(((unsigned *) offset(cp, cp->size))[-1]= MAGIC);
+
+	return cell2obj(cp);
+}
+
+void free(void *op)
+/* Deallocate an object. */
+{
+	cell_t **prev, *next, *cp;
+
+	if (op == nil) return;		/* Aaargh. */
+
+	cp= obj2cell(op);
+	assert(cp->magic == MAGIC);
+	assert(((unsigned *) offset(cp, cp->size))[-1] == MAGIC);
+	debug(cp->sacred= MAGIC);
+
+	/* Find the spot where the object belongs. */
+	prev= &freelist;
+	while ((next= *prev) != nil && next < cp) {
+		assert(next->magic == MAGIC);
+		assert(next->sacred == MAGIC);
+		prev= &next->next;
+	}
+
+	/* Put the new free cell in the list. */
+	*prev= cp;
+	cp->next= next;
+
+#if DEBUG
+	/* Check the rest of the list. */
+	while (next != nil) {
+		assert(next->magic == MAGIC);
+		assert(next->sacred == MAGIC);
+		next= next->next;
+	}
+#endif
+}
+
+void *realloc(void *op, size_t size)
+/* Change the size of an object.  Don't bother being smart, just copy it. */
+{
+	size_t oldsize;
+	void *new;
+
+	oldsize= op == nil ? 0 : obj2cell(op)->size - HDR_SIZE;
+
+	new= malloc(size);
+	memcpy(new, op, oldsize > size ? size : oldsize);
+	free(op);
+	return new;
+}
+
+/*
+ * $PchId: malloc.c,v 1.4 1996/02/22 09:15:56 philip Exp $
+ */
Index: /trunk/minix/lib/sysutil/kprintf.c
===================================================================
--- /trunk/minix/lib/sysutil/kprintf.c	(revision 9)
+++ /trunk/minix/lib/sysutil/kprintf.c	(revision 9)
@@ -0,0 +1,191 @@
+/*	printf() - system services printf()		Author: Kees J. Bot
+ *								15 Jan 1994
+ */
+#define nil 0
+#include <stdarg.h>
+#include <stddef.h>
+#include <limits.h>
+
+#define isdigit(c)	((unsigned) ((c) - '0') <  (unsigned) 10)
+
+#if !__STDC__
+/* Classic C stuff, ignore. */
+void kputc();
+int printf(fmt) char *fmt;
+#else
+
+/* Printf() uses kputc() to print characters. */
+void kputc(int c);
+
+#define count_kputc(c) do { charcount++; kputc(c); } while(0)
+
+int printf(const char *fmt, ...)
+#endif
+{
+	int c, charcount = 0;
+	enum { LEFT, RIGHT } adjust;
+	enum { LONG, INT } intsize;
+	int fill;
+	int width, max, len, base;
+	static char X2C_tab[]= "0123456789ABCDEF";
+	static char x2c_tab[]= "0123456789abcdef";
+	char *x2c;
+	char *p;
+	long i;
+	unsigned long u;
+	char temp[8 * sizeof(long) / 3 + 2];
+
+	va_list argp;
+
+	va_start(argp, fmt);
+
+	while ((c= *fmt++) != 0) {
+		if (c != '%') {
+			/* Ordinary character. */
+			count_kputc(c);
+			continue;
+		}
+
+		/* Format specifier of the form:
+		 *	%[adjust][fill][width][.max]keys
+		 */
+		c= *fmt++;
+
+		adjust= RIGHT;
+		if (c == '-') {
+			adjust= LEFT;
+			c= *fmt++;
+		}
+
+		fill= ' ';
+		if (c == '0') {
+			fill= '0';
+			c= *fmt++;
+		}
+
+		width= 0;
+		if (c == '*') {
+			/* Width is specified as an argument, e.g. %*d. */
+			width= va_arg(argp, int);
+			c= *fmt++;
+		} else
+		if (isdigit(c)) {
+			/* A number tells the width, e.g. %10d. */
+			do {
+				width= width * 10 + (c - '0');
+			} while (isdigit(c= *fmt++));
+		}
+
+		max= INT_MAX;
+		if (c == '.') {
+			/* Max field length coming up. */
+			if ((c= *fmt++) == '*') {
+				max= va_arg(argp, int);
+				c= *fmt++;
+			} else
+			if (isdigit(c)) {
+				max= 0;
+				do {
+					max= max * 10 + (c - '0');
+				} while (isdigit(c= *fmt++));
+			}
+		}
+
+		/* Set a few flags to the default. */
+		x2c= x2c_tab;
+		i= 0;
+		base= 10;
+		intsize= INT;
+		if (c == 'l' || c == 'L') {
+			/* "Long" key, e.g. %ld. */
+			intsize= LONG;
+			c= *fmt++;
+		}
+		if (c == 0) break;
+
+		switch (c) {
+			/* Decimal. */
+		case 'd':
+			i= intsize == LONG ? va_arg(argp, long)
+						: va_arg(argp, int);
+			u= i < 0 ? -i : i;
+			goto int2ascii;
+
+			/* Octal. */
+		case 'o':
+			base= 010;
+			goto getint;
+
+			/* Pointer, interpret as %X or %lX. */
+		case 'p':
+			if (sizeof(char *) > sizeof(int)) intsize= LONG;
+
+			/* Hexadecimal.  %X prints upper case A-F, not %lx. */
+		case 'X':
+			x2c= X2C_tab;
+		case 'x':
+			base= 0x10;
+			goto getint;
+
+			/* Unsigned decimal. */
+		case 'u':
+		getint:
+			u= intsize == LONG ? va_arg(argp, unsigned long)
+						: va_arg(argp, unsigned int);
+		int2ascii:
+			p= temp + sizeof(temp)-1;
+			*p= 0;
+			do {
+				*--p= x2c[(ptrdiff_t) (u % base)];
+			} while ((u /= base) > 0);
+			goto string_length;
+
+			/* A character. */
+		case 'c':
+			p= temp;
+			*p= va_arg(argp, int);
+			len= 1;
+			goto string_print;
+
+			/* Simply a percent. */
+		case '%':
+			p= temp;
+			*p= '%';
+			len= 1;
+			goto string_print;
+
+			/* A string.  The other cases will join in here. */
+		case 's':
+			p= va_arg(argp, char *);
+
+		string_length:
+			for (len= 0; p[len] != 0 && len < max; len++) {}
+
+		string_print:
+			width -= len;
+			if (i < 0) width--;
+			if (fill == '0' && i < 0) count_kputc('-');
+			if (adjust == RIGHT) {
+				while (width > 0) { count_kputc(fill); width--; }
+			}
+			if (fill == ' ' && i < 0) count_kputc('-');
+			while (len > 0) { count_kputc((unsigned char) *p++); len--; }
+			while (width > 0) { count_kputc(fill); width--; }
+			break;
+
+			/* Unrecognized format key, echo it back. */
+		default:
+			count_kputc('%');
+			count_kputc(c);
+		}
+	}
+
+	/* Mark the end with a null (should be something else, like -1). */
+	kputc(0);
+	va_end(argp);
+	return charcount;
+}
+
+/*
+ * $PchId: kprintf.c,v 1.5 1996/04/11 06:59:05 philip Exp $
+ */
Index: /trunk/minix/lib/sysutil/kputc.c
===================================================================
--- /trunk/minix/lib/sysutil/kputc.c	(revision 9)
+++ /trunk/minix/lib/sysutil/kputc.c	(revision 9)
@@ -0,0 +1,47 @@
+/* A server must occasionally print some message.  It uses a simple version of 
+ * printf() found in the system lib that calls kputc() to output characters.
+ * Printing is done with a call to the kernel, and not by going through FS.
+ *
+ * This routine can only be used by servers and device drivers.  The kernel
+ * must define its own kputc(). Note that the log driver also defines its own 
+ * kputc() to directly call the TTY instead of going through this library.
+ */
+
+#include "sysutil.h"
+
+/*===========================================================================*
+ *				kputc					     *
+ *===========================================================================*/
+void kputc(c)
+int c;
+{
+/* Accumulate another character.  If 0 or buffer full, print it. */
+  static int buf_count;		/* # characters in the buffer */
+  static char print_buf[80];	/* output is buffered here */
+  message m;
+
+  if ((c == 0 && buf_count > 0) || buf_count == sizeof(print_buf)) {
+	int procs[] = OUTPUT_PROCS_ARRAY;
+	int p;
+
+	for(p = 0; procs[p] != NONE; p++) {
+		/* Send the buffer to this output driver. */
+		m.DIAG_BUF_COUNT = buf_count;
+		m.DIAG_PRINT_BUF = print_buf;
+		m.DIAG_ENDPT = SELF;
+		m.m_type = DIAGNOSTICS;
+		(void) _sendrec(procs[p], &m);
+	}
+	buf_count = 0;
+
+	/* If the output fails, e.g., due to an ELOCKED, do not retry output
+         * at the FS as if this were a normal user-land printf(). This may 
+         * result in even worse problems. 
+         */
+  }
+  if (c != 0) { 
+        
+        /* Append a single character to the output buffer. */
+  	print_buf[buf_count++] = c;
+  }
+}
Index: /trunk/minix/lib/sysutil/report.c
===================================================================
--- /trunk/minix/lib/sysutil/report.c	(revision 9)
+++ /trunk/minix/lib/sysutil/report.c	(revision 9)
@@ -0,0 +1,20 @@
+#include "sysutil.h" 
+
+/*===========================================================================*
+ *				    report					     *
+ *===========================================================================*/
+PUBLIC void report(who, mess, num)
+char *who;				/* server identification */
+char *mess;				/* message format to print */
+int num;				/* number to go with the message */
+{
+/* Display a message for a server. */ 
+
+  if (num != NO_NUM) {
+      printf("%s: %s %d\n", who, mess, num);
+  } else {
+      printf("%s: %s\n", who, mess);
+  }
+}
+
+
Index: /trunk/minix/lib/sysutil/sysutil.h
===================================================================
--- /trunk/minix/lib/sysutil/sysutil.h	(revision 9)
+++ /trunk/minix/lib/sysutil/sysutil.h	(revision 9)
@@ -0,0 +1,8 @@
+/*	sysutil.h - System library utilities.	*/
+
+#define _SYSTEM
+
+#include <lib.h>		/* common to all libraries */
+#include <minix/com.h>		/* need task numbers + message types */
+#include <minix/syslib.h>	/* need sendrec, _taskcall, etc */
+#include <minix/sysutil.h>	/* prototypes in this library */
Index: /trunk/minix/lib/sysutil/taskcall.c
===================================================================
--- /trunk/minix/lib/sysutil/taskcall.c	(revision 9)
+++ /trunk/minix/lib/sysutil/taskcall.c	(revision 9)
@@ -0,0 +1,20 @@
+/* _taskcall() is the same as _syscall() except it returns negative error
+ * codes directly and not in errno.  This is a better interface for MM and
+ * FS.
+ */
+
+#include <lib.h>
+#include <minix/syslib.h>
+
+PUBLIC int _taskcall(who, syscallnr, msgptr)
+int who;
+int syscallnr;
+register message *msgptr;
+{
+  int status;
+
+  msgptr->m_type = syscallnr;
+  status = _sendrec(who, msgptr);
+  if (status != 0) return(status);
+  return(msgptr->m_type);
+}
Index: /trunk/minix/lib/sysutil/tickdelay.c
===================================================================
--- /trunk/minix/lib/sysutil/tickdelay.c	(revision 9)
+++ /trunk/minix/lib/sysutil/tickdelay.c	(revision 9)
@@ -0,0 +1,44 @@
+#include "sysutil.h"
+#include <timers.h>
+
+/*===========================================================================*
+ *                               tickdelay			    	     *
+ *===========================================================================*/
+PUBLIC int tickdelay(ticks)
+long ticks;				/* number of ticks to wait */
+{
+/* This function uses the synchronous alarm to delay for a while. This works
+ * even if a previous synchronous alarm was scheduled, because the remaining
+ * tick of the previous alarm are returned so that it can be rescheduled.
+ * Note however that a long tick_delay (longer than the remaining time of the
+ * previous) alarm will also delay the previous alarm.
+ */
+    message m, m_alarm;
+    clock_t time_left;
+    int s;
+
+    if (ticks <= 0) return;		/* check for robustness */
+
+    m.ALRM_ENDPT = SELF;		/* SELF means this process nr */
+    m.ALRM_EXP_TIME = ticks;		/* request message after ticks */
+    m.ALRM_ABS_TIME = 0;		/* ticks are relative to now */
+    s = _taskcall(SYSTASK, SYS_SETALARM, &m);
+    if (s != OK) return(s);
+
+    receive(CLOCK,&m_alarm);		/* await synchronous alarm */
+
+    /* Check if we must reschedule the current alarm. */
+    if (m.ALRM_TIME_LEFT > 0 && m.ALRM_TIME_LEFT != TMR_NEVER) {
+    	m.ALRM_EXP_TIME = m.ALRM_TIME_LEFT - ticks;
+    	if (m.ALRM_EXP_TIME <= 0) 
+    		m.ALRM_EXP_TIME = 1;
+    	s = _taskcall(SYSTASK, SYS_SETALARM, &m);
+    }
+
+    return(s);
+}
+
+
+
+
+
Index: /trunk/minix/lib/timers/Makedepend-ack
===================================================================
--- /trunk/minix/lib/timers/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/timers/Makedepend-ack	(revision 9)
@@ -0,0 +1,6 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' tmrs_set.c | sed -e 's:^\(.\):../obj-ack//./timers/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' tmrs_clr.c | sed -e 's:^\(.\):../obj-ack//./timers/\1:' >> .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' tmrs_exp.c | sed -e 's:^\(.\):../obj-ack//./timers/\1:' >> .depend-ack
Index: /trunk/minix/lib/timers/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/timers/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/timers/Makedepend-gnu	(revision 9)
@@ -0,0 +1,6 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' tmrs_set.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./timers/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' tmrs_clr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./timers/\1:' >> .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' tmrs_exp.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./timers/\1:' >> .depend-gnu
Index: /trunk/minix/lib/timers/Makefile
===================================================================
--- /trunk/minix/lib/timers/Makefile	(revision 9)
+++ /trunk/minix/lib/timers/Makefile	(revision 9)
@@ -0,0 +1,66 @@
+#Generated from ./timers/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./timers ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./timers ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libtimers.a
+
+../obj-ack//libtimers.a: ../obj-ack//libtimers.a(tmrs_set.o)
+../obj-ack//libtimers.a: ../obj-ack//libtimers.a(tmrs_clr.o)
+../obj-ack//libtimers.a: ../obj-ack//libtimers.a(tmrs_exp.o)
+
+../obj-ack//libtimers.a:
+	ar cr ../obj-ack//libtimers.a ../obj-ack//./timers/*.o
+	rm ../obj-ack//./timers/*.o
+
+../obj-ack//libtimers.a(tmrs_set.o): tmrs_set.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./timers/tmrs_set.o tmrs_set.c
+../obj-ack//libtimers.a(tmrs_clr.o): tmrs_clr.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./timers/tmrs_clr.o tmrs_clr.c
+../obj-ack//libtimers.a(tmrs_exp.o): tmrs_exp.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./timers/tmrs_exp.o tmrs_exp.c
+
+all-gnu: ../obj-gnu/libtimers.a
+
+../obj-gnu/libtimers.a: ../obj-gnu/./timers/tmrs_set.o
+../obj-gnu/libtimers.a: ../obj-gnu/./timers/tmrs_clr.o
+../obj-gnu/libtimers.a: ../obj-gnu/./timers/tmrs_exp.o
+
+../obj-gnu/libtimers.a:
+	gar cr ../obj-gnu/libtimers.a $?
+
+../obj-gnu/./timers/tmrs_set.o: tmrs_set.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./timers/tmrs_set.o tmrs_set.c
+
+../obj-gnu/./timers/tmrs_clr.o: tmrs_clr.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./timers/tmrs_clr.o tmrs_clr.c
+
+../obj-gnu/./timers/tmrs_exp.o: tmrs_exp.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./timers/tmrs_exp.o tmrs_exp.c
+
+
+
+
+clean::
+	rm -f ../obj-ack//./timers/*
+	rm -f ../obj-gnu/./timers/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/timers/Makefile.in
===================================================================
--- /trunk/minix/lib/timers/Makefile.in	(revision 9)
+++ /trunk/minix/lib/timers/Makefile.in	(revision 9)
@@ -0,0 +1,12 @@
+# Makefile for lib/tmrslib.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
+
+LIBRARIES=libtimers
+
+libtimers_FILES=" \
+	tmrs_set.c \
+	tmrs_clr.c \
+	tmrs_exp.c"
+
+TYPE=both
Index: /trunk/minix/lib/timers/timers.h
===================================================================
--- /trunk/minix/lib/timers/timers.h	(revision 9)
+++ /trunk/minix/lib/timers/timers.h	(revision 9)
@@ -0,0 +1,7 @@
+/* This library provides generic watchdog timer management functionality.
+ * See the comments in <timers.h> for details.
+ */
+
+#include <timers.h>		/* definitions and function prototypes */
+#define NULL 	(void *) 0	/* null-pointer definition */
+
Index: /trunk/minix/lib/timers/tmrs_clr.c
===================================================================
--- /trunk/minix/lib/timers/tmrs_clr.c	(revision 9)
+++ /trunk/minix/lib/timers/tmrs_clr.c	(revision 9)
@@ -0,0 +1,40 @@
+#include "timers.h"
+
+/*===========================================================================*
+ *				tmrs_clrtimer				     *
+ *===========================================================================*/
+clock_t tmrs_clrtimer(tmrs, tp, next_time)
+timer_t **tmrs;				/* pointer to timers queue */
+timer_t *tp;				/* timer to be removed */
+clock_t *next_time;
+{
+/* Deactivate a timer and remove it from the timers queue. 
+ */
+  timer_t **atp;
+  struct proc *p;
+  clock_t prev_time;
+
+  if(*tmrs)
+  	prev_time = (*tmrs)->tmr_exp_time;
+  else
+  	prev_time = 0;
+
+  tp->tmr_exp_time = TMR_NEVER;
+
+  for (atp = tmrs; *atp != NULL; atp = &(*atp)->tmr_next) {
+	if (*atp == tp) {
+		*atp = tp->tmr_next;
+		break;
+	}
+  }
+
+  if(next_time) {
+  	if(*tmrs)
+  		*next_time = (*tmrs)->tmr_exp_time;
+  	else	
+  		*next_time = 0;
+  }
+
+  return prev_time;
+}
+
Index: /trunk/minix/lib/timers/tmrs_exp.c
===================================================================
--- /trunk/minix/lib/timers/tmrs_exp.c	(revision 9)
+++ /trunk/minix/lib/timers/tmrs_exp.c	(revision 9)
@@ -0,0 +1,31 @@
+#include "timers.h"
+
+/*===========================================================================*
+ *				tmrs_exptimers				     *
+ *===========================================================================*/
+void tmrs_exptimers(tmrs, now, new_head)
+timer_t **tmrs;				/* pointer to timers queue */
+clock_t now;				/* current time */
+clock_t *new_head;
+{
+/* Use the current time to check the timers queue list for expired timers. 
+ * Run the watchdog functions for all expired timers and deactivate them.
+ * The caller is responsible for scheduling a new alarm if needed.
+ */
+  timer_t *tp;
+
+  while ((tp = *tmrs) != NULL && tp->tmr_exp_time <= now) {
+	*tmrs = tp->tmr_next;
+	tp->tmr_exp_time = TMR_NEVER;
+	(*tp->tmr_func)(tp);
+  }
+
+  if(new_head) {
+  	if(*tmrs)
+  		*new_head = (*tmrs)->tmr_exp_time;
+  	else
+  		*new_head = 0;
+  }
+}
+
+
Index: /trunk/minix/lib/timers/tmrs_set.c
===================================================================
--- /trunk/minix/lib/timers/tmrs_set.c	(revision 9)
+++ /trunk/minix/lib/timers/tmrs_set.c	(revision 9)
@@ -0,0 +1,39 @@
+#include "timers.h"
+
+/*===========================================================================*
+ *				tmrs_settimer				     *
+ *===========================================================================*/
+clock_t tmrs_settimer(tmrs, tp, exp_time, watchdog, new_head)
+timer_t **tmrs;				/* pointer to timers queue */
+timer_t *tp;				/* the timer to be added */
+clock_t exp_time;			/* its expiration time */
+tmr_func_t watchdog;			/* watchdog function to be run */
+clock_t *new_head;			/* new earliest timer, if non NULL */
+{
+/* Activate a timer to run function 'fp' at time 'exp_time'. If the timer is
+ * already in use it is first removed from the timers queue. Then, it is put
+ * in the list of active timers with the first to expire in front.
+ * The caller responsible for scheduling a new alarm for the timer if needed. 
+ */
+  timer_t **atp;
+  clock_t old_head = 0;
+
+  if(*tmrs)
+  	old_head = (*tmrs)->tmr_exp_time;
+
+  /* Set the timer's variables. */
+  (void) tmrs_clrtimer(tmrs, tp, NULL);
+  tp->tmr_exp_time = exp_time;
+  tp->tmr_func = watchdog;
+
+  /* Add the timer to the active timers. The next timer due is in front. */
+  for (atp = tmrs; *atp != NULL; atp = &(*atp)->tmr_next) {
+	if (exp_time < (*atp)->tmr_exp_time) break;
+  }
+  tp->tmr_next = *atp;
+  *atp = tp;
+  if(new_head)
+  	(*new_head) = (*tmrs)->tmr_exp_time;
+  return old_head;
+}
+
Index: /trunk/minix/lib/util/Makedepend-ack
===================================================================
--- /trunk/minix/lib/util/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/util/Makedepend-ack	(revision 9)
@@ -0,0 +1,4 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -D_MINIX -D_POSIX_SOURCE -E' openpty.c | sed -e 's:^\(.\):../obj-ack//./util/\1:' >> .depend-ack
Index: /trunk/minix/lib/util/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/util/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/util/Makedepend-gnu	(revision 9)
@@ -0,0 +1,4 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -D_MINIX -D_POSIX_SOURCE -E' openpty.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./util/\1:' >> .depend-gnu
Index: /trunk/minix/lib/util/Makefile
===================================================================
--- /trunk/minix/lib/util/Makefile	(revision 9)
+++ /trunk/minix/lib/util/Makefile	(revision 9)
@@ -0,0 +1,52 @@
+#Generated from ./util/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./util ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./util ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libutil.a
+
+../obj-ack//libutil.a: ../obj-ack//libutil.a(openpty.o)
+
+../obj-ack//libutil.a:
+	ar cr ../obj-ack//libutil.a ../obj-ack//./util/*.o
+	rm ../obj-ack//./util/*.o
+
+../obj-ack//libutil.a(openpty.o): openpty.c
+	cc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-ack//./util/openpty.o openpty.c
+
+all-gnu: ../obj-gnu/libutil.a
+
+../obj-gnu/libutil.a: ../obj-gnu/./util/openpty.o
+
+../obj-gnu/libutil.a:
+	gar cr ../obj-gnu/libutil.a $?
+
+../obj-gnu/./util/openpty.o: openpty.c
+	gcc -O -D_MINIX -D_POSIX_SOURCE -c -o ../obj-gnu/./util/openpty.o openpty.c
+
+
+
+
+clean::
+	rm -f ../obj-ack//./util/*
+	rm -f ../obj-gnu/./util/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/util/Makefile.in
===================================================================
--- /trunk/minix/lib/util/Makefile.in	(revision 9)
+++ /trunk/minix/lib/util/Makefile.in	(revision 9)
@@ -0,0 +1,9 @@
+# Makefile for lib/util.
+
+CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
+
+LIBRARIES=libutil
+
+libutil_FILES=openpty.c
+
+TYPE=both
Index: /trunk/minix/lib/util/openpty.c
===================================================================
--- /trunk/minix/lib/util/openpty.c	(revision 9)
+++ /trunk/minix/lib/util/openpty.c	(revision 9)
@@ -0,0 +1,82 @@
+/*
+ * openpty() tries to open a pty; applications won't have to
+ * duplicate this code all the time (or change it if the system
+ * pty interface changes).
+ *
+ * First version by Ben Gras <beng@few.vu.nl>,
+ * Initially heavily based on telnetd/pty.c
+ * by Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>.
+ *
+ */
+#include <libutil.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioc_tty.h>
+
+#define DEV_DIR		"/dev"
+
+/*
+ * Allocate a PTY, by trying to open one repeatedly.
+ */
+int openpty(int *amaster, int *aslave, char *name,
+	struct termios *termp, struct winsize *winp)
+{
+  char buff[128], temp[128];
+  register int i, j;
+  int pty_fd = -1, gr;
+  static char tty_name[128];
+  struct group *ttygroup;
+  gid_t tty_gid = 0;
+
+  if(!amaster || !aslave) {
+  	errno = EINVAL;
+  	return -1;
+  }
+
+  for(i = 'p'; i < 'w'; i++) {
+	j = 0;
+	do {
+		sprintf(buff, "%s/pty%c%c",
+			DEV_DIR, i, (j < 10) ? j + '0' : j + 'a' - 10);
+
+		if((*amaster = open(buff, O_RDWR)) >= 0) {
+		  sprintf(tty_name, "%s/tty%c%c", DEV_DIR,
+			i, (j < 10) ? j + '0' : j + 'a' - 10);
+		  if((*aslave = open(tty_name, O_RDWR)) >= 0)
+		  	break;
+		}
+		close(*amaster);
+
+		j++;
+		if (j == 16) break;
+	} while(1);
+
+	/* Did we find one? */
+	if (j < 16) break;
+  }
+  if (*amaster < 0) { errno = ENOENT; return(-1); }
+
+  setgrent();
+  ttygroup = getgrnam("tty");
+  endgrent();
+  if(ttygroup) tty_gid = ttygroup->gr_gid;
+
+  if(name) strcpy(name, tty_name);
+
+  /* Ignore errors on these. */
+  chown(tty_name, getuid(), tty_gid);
+  chmod(tty_name, 0620);	/* -rw--w---- */
+  if(termp) tcsetattr(*aslave, TCSAFLUSH, termp);
+  if(winp) ioctl(*aslave, TIOCSWINSZ, winp);
+
+  return(0);
+}
+
Index: /trunk/minix/lib/zlib-1.2.3/ChangeLog
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/ChangeLog	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/ChangeLog	(revision 9)
@@ -0,0 +1,855 @@
+
+                ChangeLog file for zlib
+
+Changes in 1.2.3 (18 July 2005)
+- Apply security vulnerability fixes to contrib/infback9 as well
+- Clean up some text files (carriage returns, trailing space)
+- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant]
+
+Changes in 1.2.2.4 (11 July 2005)
+- Add inflatePrime() function for starting inflation at bit boundary
+- Avoid some Visual C warnings in deflate.c
+- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit
+  compile
+- Fix some spelling errors in comments [Betts]
+- Correct inflateInit2() error return documentation in zlib.h
+- Added zran.c example of compressed data random access to examples
+  directory, shows use of inflatePrime()
+- Fix cast for assignments to strm->state in inflate.c and infback.c
+- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer]
+- Move declarations of gf2 functions to right place in crc32.c [Oberhumer]
+- Add cast in trees.c t avoid a warning [Oberhumer]
+- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer]
+- Update make_vms.com [Zinser]
+- Initialize state->write in inflateReset() since copied in inflate_fast()
+- Be more strict on incomplete code sets in inflate_table() and increase
+  ENOUGH and MAXD -- this repairs a possible security vulnerability for
+  invalid inflate input.  Thanks to Tavis Ormandy and Markus Oberhumer for
+  discovering the vulnerability and providing test cases.
+- Add ia64 support to configure for HP-UX [Smith]
+- Add error return to gzread() for format or i/o error [Levin]
+- Use malloc.h for OS/2 [Necasek]
+
+Changes in 1.2.2.3 (27 May 2005)
+- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile
+- Typecast fread() return values in gzio.c [Vollant]
+- Remove trailing space in minigzip.c outmode (VC++ can't deal with it)
+- Fix crc check bug in gzread() after gzungetc() [Heiner]
+- Add the deflateTune() function to adjust internal compression parameters
+- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack)
+- Remove an incorrect assertion in examples/zpipe.c
+- Add C++ wrapper in infback9.h [Donais]
+- Fix bug in inflateCopy() when decoding fixed codes
+- Note in zlib.h how much deflateSetDictionary() actually uses
+- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used)
+- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer]
+- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer]
+- Add gzdirect() function to indicate transparent reads
+- Update contrib/minizip [Vollant]
+- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer]
+- Add casts in crc32.c to avoid warnings [Oberhumer]
+- Add contrib/masmx64 [Vollant]
+- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant]
+
+Changes in 1.2.2.2 (30 December 2004)
+- Replace structure assignments in deflate.c and inflate.c with zmemcpy to
+  avoid implicit memcpy calls (portability for no-library compilation)
+- Increase sprintf() buffer size in gzdopen() to allow for large numbers
+- Add INFLATE_STRICT to check distances against zlib header
+- Improve WinCE errno handling and comments [Chang]
+- Remove comment about no gzip header processing in FAQ
+- Add Z_FIXED strategy option to deflateInit2() to force fixed trees
+- Add updated make_vms.com [Coghlan], update README
+- Create a new "examples" directory, move gzappend.c there, add zpipe.c,
+  fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html.
+- Add FAQ entry and comments in deflate.c on uninitialized memory access
+- Add Solaris 9 make options in configure [Gilbert]
+- Allow strerror() usage in gzio.c for STDC
+- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer]
+- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant]
+- Use z_off_t for adler32_combine() and crc32_combine() lengths
+- Make adler32() much faster for small len
+- Use OS_CODE in deflate() default gzip header
+
+Changes in 1.2.2.1 (31 October 2004)
+- Allow inflateSetDictionary() call for raw inflate
+- Fix inflate header crc check bug for file names and comments
+- Add deflateSetHeader() and gz_header structure for custom gzip headers
+- Add inflateGetheader() to retrieve gzip headers
+- Add crc32_combine() and adler32_combine() functions
+- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list
+- Use zstreamp consistently in zlib.h (inflate_back functions)
+- Remove GUNZIP condition from definition of inflate_mode in inflate.h
+  and in contrib/inflate86/inffast.S [Truta, Anderson]
+- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson]
+- Update projects/README.projects and projects/visualc6 [Truta]
+- Update win32/DLL_FAQ.txt [Truta]
+- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta]
+- Deprecate Z_ASCII; use Z_TEXT instead [Truta]
+- Use a new algorithm for setting strm->data_type in trees.c [Truta]
+- Do not define an exit() prototype in zutil.c unless DEBUG defined
+- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta]
+- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate()
+- Fix Darwin build version identification [Peterson]
+
+Changes in 1.2.2 (3 October 2004)
+- Update zlib.h comments on gzip in-memory processing
+- Set adler to 1 in inflateReset() to support Java test suite [Walles]
+- Add contrib/dotzlib [Ravn]
+- Update win32/DLL_FAQ.txt [Truta]
+- Update contrib/minizip [Vollant]
+- Move contrib/visual-basic.txt to old/ [Truta]
+- Fix assembler builds in projects/visualc6/ [Truta]
+
+Changes in 1.2.1.2 (9 September 2004)
+- Update INDEX file
+- Fix trees.c to update strm->data_type (no one ever noticed!)
+- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown]
+- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE)
+- Add limited multitasking protection to DYNAMIC_CRC_TABLE
+- Add NO_vsnprintf for VMS in zutil.h [Mozilla]
+- Don't declare strerror() under VMS [Mozilla]
+- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize
+- Update contrib/ada [Anisimkov]
+- Update contrib/minizip [Vollant]
+- Fix configure to not hardcode directories for Darwin [Peterson]
+- Fix gzio.c to not return error on empty files [Brown]
+- Fix indentation; update version in contrib/delphi/ZLib.pas and
+  contrib/pascal/zlibpas.pas [Truta]
+- Update mkasm.bat in contrib/masmx86 [Truta]
+- Update contrib/untgz [Truta]
+- Add projects/README.projects [Truta]
+- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta]
+- Update win32/DLL_FAQ.txt [Truta]
+- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta]
+- Remove an unnecessary assignment to curr in inftrees.c [Truta]
+- Add OS/2 to exe builds in configure [Poltorak]
+- Remove err dummy parameter in zlib.h [Kientzle]
+
+Changes in 1.2.1.1 (9 January 2004)
+- Update email address in README
+- Several FAQ updates
+- Fix a big fat bug in inftrees.c that prevented decoding valid
+  dynamic blocks with only literals and no distance codes --
+  Thanks to "Hot Emu" for the bug report and sample file
+- Add a note to puff.c on no distance codes case.
+
+Changes in 1.2.1 (17 November 2003)
+- Remove a tab in contrib/gzappend/gzappend.c
+- Update some interfaces in contrib for new zlib functions
+- Update zlib version number in some contrib entries
+- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta]
+- Support shared libraries on Hurd and KFreeBSD [Brown]
+- Fix error in NO_DIVIDE option of adler32.c
+
+Changes in 1.2.0.8 (4 November 2003)
+- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas
+- Add experimental NO_DIVIDE #define in adler32.c
+    - Possibly faster on some processors (let me know if it is)
+- Correct Z_BLOCK to not return on first inflate call if no wrap
+- Fix strm->data_type on inflate() return to correctly indicate EOB
+- Add deflatePrime() function for appending in the middle of a byte
+- Add contrib/gzappend for an example of appending to a stream
+- Update win32/DLL_FAQ.txt [Truta]
+- Delete Turbo C comment in README [Truta]
+- Improve some indentation in zconf.h [Truta]
+- Fix infinite loop on bad input in configure script [Church]
+- Fix gzeof() for concatenated gzip files [Johnson]
+- Add example to contrib/visual-basic.txt [Michael B.]
+- Add -p to mkdir's in Makefile.in [vda]
+- Fix configure to properly detect presence or lack of printf functions
+- Add AS400 support [Monnerat]
+- Add a little Cygwin support [Wilson]
+
+Changes in 1.2.0.7 (21 September 2003)
+- Correct some debug formats in contrib/infback9
+- Cast a type in a debug statement in trees.c
+- Change search and replace delimiter in configure from % to # [Beebe]
+- Update contrib/untgz to 0.2 with various fixes [Truta]
+- Add build support for Amiga [Nikl]
+- Remove some directories in old that have been updated to 1.2
+- Add dylib building for Mac OS X in configure and Makefile.in
+- Remove old distribution stuff from Makefile
+- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X
+- Update links in README
+
+Changes in 1.2.0.6 (13 September 2003)
+- Minor FAQ updates
+- Update contrib/minizip to 1.00 [Vollant]
+- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta]
+- Update POSTINC comment for 68060 [Nikl]
+- Add contrib/infback9 with deflate64 decoding (unsupported)
+- For MVS define NO_vsnprintf and undefine FAR [van Burik]
+- Add pragma for fdopen on MVS [van Burik]
+
+Changes in 1.2.0.5 (8 September 2003)
+- Add OF to inflateBackEnd() declaration in zlib.h
+- Remember start when using gzdopen in the middle of a file
+- Use internal off_t counters in gz* functions to properly handle seeks
+- Perform more rigorous check for distance-too-far in inffast.c
+- Add Z_BLOCK flush option to return from inflate at block boundary
+- Set strm->data_type on return from inflate
+    - Indicate bits unused, if at block boundary, and if in last block
+- Replace size_t with ptrdiff_t in crc32.c, and check for correct size
+- Add condition so old NO_DEFLATE define still works for compatibility
+- FAQ update regarding the Windows DLL [Truta]
+- INDEX update: add qnx entry, remove aix entry [Truta]
+- Install zlib.3 into mandir [Wilson]
+- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta]
+- Adapt the zlib interface to the new DLL convention guidelines [Truta]
+- Introduce ZLIB_WINAPI macro to allow the export of functions using
+  the WINAPI calling convention, for Visual Basic [Vollant, Truta]
+- Update msdos and win32 scripts and makefiles [Truta]
+- Export symbols by name, not by ordinal, in win32/zlib.def [Truta]
+- Add contrib/ada [Anisimkov]
+- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta]
+- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant]
+- Add contrib/masm686 [Truta]
+- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm
+  [Truta, Vollant]
+- Update contrib/delphi; rename to contrib/pascal; add example [Truta]
+- Remove contrib/delphi2; add a new contrib/delphi [Truta]
+- Avoid inclusion of the nonstandard <memory.h> in contrib/iostream,
+  and fix some method prototypes [Truta]
+- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip
+  [Truta]
+- Avoid the use of backslash (\) in contrib/minizip [Vollant]
+- Fix file time handling in contrib/untgz; update makefiles [Truta]
+- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines
+  [Vollant]
+- Remove contrib/vstudio/vc15_16 [Vollant]
+- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta]
+- Update README.contrib [Truta]
+- Invert the assignment order of match_head and s->prev[...] in
+  INSERT_STRING [Truta]
+- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings
+  [Truta]
+- Compare function pointers with 0, not with NULL or Z_NULL [Truta]
+- Fix prototype of syncsearch in inflate.c [Truta]
+- Introduce ASMINF macro to be enabled when using an ASM implementation
+  of inflate_fast [Truta]
+- Change NO_DEFLATE to NO_GZCOMPRESS [Truta]
+- Modify test_gzio in example.c to take a single file name as a
+  parameter [Truta]
+- Exit the example.c program if gzopen fails [Truta]
+- Add type casts around strlen in example.c [Truta]
+- Remove casting to sizeof in minigzip.c; give a proper type
+  to the variable compared with SUFFIX_LEN [Truta]
+- Update definitions of STDC and STDC99 in zconf.h [Truta]
+- Synchronize zconf.h with the new Windows DLL interface [Truta]
+- Use SYS16BIT instead of __32BIT__ to distinguish between
+  16- and 32-bit platforms [Truta]
+- Use far memory allocators in small 16-bit memory models for
+  Turbo C [Truta]
+- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in
+  zlibCompileFlags [Truta]
+- Cygwin has vsnprintf [Wilson]
+- In Windows16, OS_CODE is 0, as in MSDOS [Truta]
+- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson]
+
+Changes in 1.2.0.4 (10 August 2003)
+- Minor FAQ updates
+- Be more strict when checking inflateInit2's windowBits parameter
+- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well
+- Add gzip wrapper option to deflateInit2 using windowBits
+- Add updated QNX rule in configure and qnx directory [Bonnefoy]
+- Make inflate distance-too-far checks more rigorous
+- Clean up FAR usage in inflate
+- Add casting to sizeof() in gzio.c and minigzip.c
+
+Changes in 1.2.0.3 (19 July 2003)
+- Fix silly error in gzungetc() implementation [Vollant]
+- Update contrib/minizip and contrib/vstudio [Vollant]
+- Fix printf format in example.c
+- Correct cdecl support in zconf.in.h [Anisimkov]
+- Minor FAQ updates
+
+Changes in 1.2.0.2 (13 July 2003)
+- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons
+- Attempt to avoid warnings in crc32.c for pointer-int conversion
+- Add AIX to configure, remove aix directory [Bakker]
+- Add some casts to minigzip.c
+- Improve checking after insecure sprintf() or vsprintf() calls
+- Remove #elif's from crc32.c
+- Change leave label to inf_leave in inflate.c and infback.c to avoid
+  library conflicts
+- Remove inflate gzip decoding by default--only enable gzip decoding by
+  special request for stricter backward compatibility
+- Add zlibCompileFlags() function to return compilation information
+- More typecasting in deflate.c to avoid warnings
+- Remove leading underscore from _Capital #defines [Truta]
+- Fix configure to link shared library when testing
+- Add some Windows CE target adjustments [Mai]
+- Remove #define ZLIB_DLL in zconf.h [Vollant]
+- Add zlib.3 [Rodgers]
+- Update RFC URL in deflate.c and algorithm.txt [Mai]
+- Add zlib_dll_FAQ.txt to contrib [Truta]
+- Add UL to some constants [Truta]
+- Update minizip and vstudio [Vollant]
+- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h
+- Expand use of NO_DUMMY_DECL to avoid all dummy structures
+- Added iostream3 to contrib [Schwardt]
+- Replace rewind() with fseek() for WinCE [Truta]
+- Improve setting of zlib format compression level flags
+    - Report 0 for huffman and rle strategies and for level == 0 or 1
+    - Report 2 only for level == 6
+- Only deal with 64K limit when necessary at compile time [Truta]
+- Allow TOO_FAR check to be turned off at compile time [Truta]
+- Add gzclearerr() function [Souza]
+- Add gzungetc() function
+
+Changes in 1.2.0.1 (17 March 2003)
+- Add Z_RLE strategy for run-length encoding [Truta]
+    - When Z_RLE requested, restrict matches to distance one
+    - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE
+- Correct FASTEST compilation to allow level == 0
+- Clean up what gets compiled for FASTEST
+- Incorporate changes to zconf.in.h [Vollant]
+    - Refine detection of Turbo C need for dummy returns
+    - Refine ZLIB_DLL compilation
+    - Include additional header file on VMS for off_t typedef
+- Try to use _vsnprintf where it supplants vsprintf [Vollant]
+- Add some casts in inffast.c
+- Enchance comments in zlib.h on what happens if gzprintf() tries to
+  write more than 4095 bytes before compression
+- Remove unused state from inflateBackEnd()
+- Remove exit(0) from minigzip.c, example.c
+- Get rid of all those darn tabs
+- Add "check" target to Makefile.in that does the same thing as "test"
+- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in
+- Update contrib/inflate86 [Anderson]
+- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant]
+- Add msdos and win32 directories with makefiles [Truta]
+- More additions and improvements to the FAQ
+
+Changes in 1.2.0 (9 March 2003)
+- New and improved inflate code
+    - About 20% faster
+    - Does not allocate 32K window unless and until needed
+    - Automatically detects and decompresses gzip streams
+    - Raw inflate no longer needs an extra dummy byte at end
+    - Added inflateBack functions using a callback interface--even faster
+      than inflate, useful for file utilities (gzip, zip)
+    - Added inflateCopy() function to record state for random access on
+      externally generated deflate streams (e.g. in gzip files)
+    - More readable code (I hope)
+- New and improved crc32()
+    - About 50% faster, thanks to suggestions from Rodney Brown
+- Add deflateBound() and compressBound() functions
+- Fix memory leak in deflateInit2()
+- Permit setting dictionary for raw deflate (for parallel deflate)
+- Fix const declaration for gzwrite()
+- Check for some malloc() failures in gzio.c
+- Fix bug in gzopen() on single-byte file 0x1f
+- Fix bug in gzread() on concatenated file with 0x1f at end of buffer
+  and next buffer doesn't start with 0x8b
+- Fix uncompress() to return Z_DATA_ERROR on truncated input
+- Free memory at end of example.c
+- Remove MAX #define in trees.c (conflicted with some libraries)
+- Fix static const's in deflate.c, gzio.c, and zutil.[ch]
+- Declare malloc() and free() in gzio.c if STDC not defined
+- Use malloc() instead of calloc() in zutil.c if int big enough
+- Define STDC for AIX
+- Add aix/ with approach for compiling shared library on AIX
+- Add HP-UX support for shared libraries in configure
+- Add OpenUNIX support for shared libraries in configure
+- Use $cc instead of gcc to build shared library
+- Make prefix directory if needed when installing
+- Correct Macintosh avoidance of typedef Byte in zconf.h
+- Correct Turbo C memory allocation when under Linux
+- Use libz.a instead of -lz in Makefile (assure use of compiled library)
+- Update configure to check for snprintf or vsnprintf functions and their
+  return value, warn during make if using an insecure function
+- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that
+  is lost when library is used--resolution is to build new zconf.h
+- Documentation improvements (in zlib.h):
+    - Document raw deflate and inflate
+    - Update RFCs URL
+    - Point out that zlib and gzip formats are different
+    - Note that Z_BUF_ERROR is not fatal
+    - Document string limit for gzprintf() and possible buffer overflow
+    - Note requirement on avail_out when flushing
+    - Note permitted values of flush parameter of inflate()
+- Add some FAQs (and even answers) to the FAQ
+- Add contrib/inflate86/ for x86 faster inflate
+- Add contrib/blast/ for PKWare Data Compression Library decompression
+- Add contrib/puff/ simple inflate for deflate format description
+
+Changes in 1.1.4 (11 March 2002)
+- ZFREE was repeated on same allocation on some error conditions.
+  This creates a security problem described in
+  http://www.zlib.org/advisory-2002-03-11.txt
+- Returned incorrect error (Z_MEM_ERROR) on some invalid data
+- Avoid accesses before window for invalid distances with inflate window
+  less than 32K.
+- force windowBits > 8 to avoid a bug in the encoder for a window size
+  of 256 bytes. (A complete fix will be available in 1.1.5).
+
+Changes in 1.1.3 (9 July 1998)
+- fix "an inflate input buffer bug that shows up on rare but persistent
+  occasions" (Mark)
+- fix gzread and gztell for concatenated .gz files (Didier Le Botlan)
+- fix gzseek(..., SEEK_SET) in write mode
+- fix crc check after a gzeek (Frank Faubert)
+- fix miniunzip when the last entry in a zip file is itself a zip file
+  (J Lillge)
+- add contrib/asm586 and contrib/asm686 (Brian Raiter)
+  See http://www.muppetlabs.com/~breadbox/software/assembly.html
+- add support for Delphi 3 in contrib/delphi (Bob Dellaca)
+- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti)
+- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren)
+- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks)
+- added a FAQ file
+
+- Support gzdopen on Mac with Metrowerks (Jason Linhart)
+- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart)
+- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young)
+- avoid some warnings with Borland C (Tom Tanner)
+- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant)
+- emulate utime() for WIN32 in contrib/untgz  (Gilles Vollant)
+- allow several arguments to configure (Tim Mooney, Frodo Looijaard)
+- use libdir and includedir in Makefile.in (Tim Mooney)
+- support shared libraries on OSF1 V4 (Tim Mooney)
+- remove so_locations in "make clean"  (Tim Mooney)
+- fix maketree.c compilation error (Glenn, Mark)
+- Python interface to zlib now in Python 1.5 (Jeremy Hylton)
+- new Makefile.riscos (Rich Walker)
+- initialize static descriptors in trees.c for embedded targets (Nick Smith)
+- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith)
+- add the OS/2 files in Makefile.in too (Andrew Zabolotny)
+- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane)
+- fix maketree.c to allow clean compilation of inffixed.h (Mark)
+- fix parameter check in deflateCopy (Gunther Nikl)
+- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler)
+- Many portability patches by Christian Spieler:
+  . zutil.c, zutil.h: added "const" for zmem*
+  . Make_vms.com: fixed some typos
+  . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists
+  . msdos/Makefile.msc: remove "default rtl link library" info from obj files
+  . msdos/Makefile.*: use model-dependent name for the built zlib library
+  . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc:
+     new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT)
+- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane)
+- replace __far with _far for better portability (Christian Spieler, Tom Lane)
+- fix test for errno.h in configure (Tim Newsham)
+
+Changes in 1.1.2 (19 March 98)
+- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant)
+  See http://www.winimage.com/zLibDll/unzip.html
+- preinitialize the inflate tables for fixed codes, to make the code
+  completely thread safe (Mark)
+- some simplifications and slight speed-up to the inflate code (Mark)
+- fix gzeof on non-compressed files (Allan Schrum)
+- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs)
+- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn)
+- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny)
+- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori)
+- do not wrap extern "C" around system includes (Tom Lane)
+- mention zlib binding for TCL in README (Andreas Kupries)
+- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert)
+- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson)
+- allow "configure --prefix $HOME" (Tim Mooney)
+- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson)
+- move Makefile.sas to amiga/Makefile.sas
+
+Changes in 1.1.1 (27 Feb 98)
+- fix macros _tr_tally_* in deflate.h for debug mode  (Glenn Randers-Pehrson)
+- remove block truncation heuristic which had very marginal effect for zlib
+  (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the
+  compression ratio on some files. This also allows inlining _tr_tally for
+  matches in deflate_slow.
+- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier)
+
+Changes in 1.1.0 (24 Feb 98)
+- do not return STREAM_END prematurely in inflate (John Bowler)
+- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler)
+- compile with -DFASTEST to get compression code optimized for speed only
+- in minigzip, try mmap'ing the input file first (Miguel Albrecht)
+- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain
+  on Sun but significant on HP)
+
+- add a pointer to experimental unzip library in README (Gilles Vollant)
+- initialize variable gcc in configure (Chris Herborth)
+
+Changes in 1.0.9 (17 Feb 1998)
+- added gzputs and gzgets functions
+- do not clear eof flag in gzseek (Mark Diekhans)
+- fix gzseek for files in transparent mode (Mark Diekhans)
+- do not assume that vsprintf returns the number of bytes written (Jens Krinke)
+- replace EXPORT with ZEXPORT to avoid conflict with other programs
+- added compress2 in zconf.h, zlib.def, zlib.dnt
+- new asm code from Gilles Vollant in contrib/asm386
+- simplify the inflate code (Mark):
+ . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new()
+ . ZALLOC the length list in inflate_trees_fixed() instead of using stack
+ . ZALLOC the value area for huft_build() instead of using stack
+ . Simplify Z_FINISH check in inflate()
+
+- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8
+- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi)
+- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with
+  the declaration of FAR (Gilles VOllant)
+- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann)
+- read_buf buf parameter of type Bytef* instead of charf*
+- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout)
+- do not redeclare unlink in minigzip.c for WIN32 (John Bowler)
+- fix check for presence of directories in "make install" (Ian Willis)
+
+Changes in 1.0.8 (27 Jan 1998)
+- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant)
+- fix gzgetc and gzputc for big endian systems (Markus Oberhumer)
+- added compress2() to allow setting the compression level
+- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong)
+- use constant arrays for the static trees in trees.c instead of computing
+  them at run time (thanks to Ken Raeburn for this suggestion). To create
+  trees.h, compile with GEN_TREES_H and run "make test".
+- check return code of example in "make test" and display result
+- pass minigzip command line options to file_compress
+- simplifying code of inflateSync to avoid gcc 2.8 bug
+
+- support CC="gcc -Wall" in configure -s (QingLong)
+- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn)
+- fix test for shared library support to avoid compiler warnings
+- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant)
+- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit)
+- do not use fdopen for Metrowerks on Mac (Brad Pettit))
+- add checks for gzputc and gzputc in example.c
+- avoid warnings in gzio.c and deflate.c (Andreas Kleinert)
+- use const for the CRC table (Ken Raeburn)
+- fixed "make uninstall" for shared libraries
+- use Tracev instead of Trace in infblock.c
+- in example.c use correct compressed length for test_sync
+- suppress +vnocompatwarnings in configure for HPUX (not always supported)
+
+Changes in 1.0.7 (20 Jan 1998)
+- fix gzseek which was broken in write mode
+- return error for gzseek to negative absolute position
+- fix configure for Linux (Chun-Chung Chen)
+- increase stack space for MSC (Tim Wegner)
+- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant)
+- define EXPORTVA for gzprintf (Gilles Vollant)
+- added man page zlib.3 (Rick Rodgers)
+- for contrib/untgz, fix makedir() and improve Makefile
+
+- check gzseek in write mode in example.c
+- allocate extra buffer for seeks only if gzseek is actually called
+- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant)
+- add inflateSyncPoint in zconf.h
+- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def
+
+Changes in 1.0.6 (19 Jan 1998)
+- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
+  gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
+- Fix a deflate bug occurring only with compression level 0 (thanks to
+  Andy Buckler for finding this one).
+- In minigzip, pass transparently also the first byte for .Z files.
+- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
+- check Z_FINISH in inflate (thanks to Marc Schluper)
+- Implement deflateCopy (thanks to Adam Costello)
+- make static libraries by default in configure, add --shared option.
+- move MSDOS or Windows specific files to directory msdos
+- suppress the notion of partial flush to simplify the interface
+  (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4)
+- suppress history buffer provided by application to simplify the interface
+  (this feature was not implemented anyway in 1.0.4)
+- next_in and avail_in must be initialized before calling inflateInit or
+  inflateInit2
+- add EXPORT in all exported functions (for Windows DLL)
+- added Makefile.nt (thanks to Stephen Williams)
+- added the unsupported "contrib" directory:
+   contrib/asm386/ by Gilles Vollant <info@winimage.com>
+        386 asm code replacing longest_match().
+   contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
+        A C++ I/O streams interface to the zlib gz* functions
+   contrib/iostream2/  by Tyge Løvset <Tyge.Lovset@cmr.no>
+        Another C++ I/O streams interface
+   contrib/untgz/  by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
+        A very simple tar.gz file extractor using zlib
+   contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
+        How to use compress(), uncompress() and the gz* functions from VB.
+- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
+  level) in minigzip (thanks to Tom Lane)
+
+- use const for rommable constants in deflate
+- added test for gzseek and gztell in example.c
+- add undocumented function inflateSyncPoint() (hack for Paul Mackerras)
+- add undocumented function zError to convert error code to string
+  (for Tim Smithers)
+- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code.
+- Use default memcpy for Symantec MSDOS compiler.
+- Add EXPORT keyword for check_func (needed for Windows DLL)
+- add current directory to LD_LIBRARY_PATH for "make test"
+- create also a link for libz.so.1
+- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura)
+- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX)
+- added -soname for Linux in configure (Chun-Chung Chen,
+- assign numbers to the exported functions in zlib.def (for Windows DLL)
+- add advice in zlib.h for best usage of deflateSetDictionary
+- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn)
+- allow compilation with ANSI keywords only enabled for TurboC in large model
+- avoid "versionString"[0] (Borland bug)
+- add NEED_DUMMY_RETURN for Borland
+- use variable z_verbose for tracing in debug mode (L. Peter Deutsch).
+- allow compilation with CC
+- defined STDC for OS/2 (David Charlap)
+- limit external names to 8 chars for MVS (Thomas Lund)
+- in minigzip.c, use static buffers only for 16-bit systems
+- fix suffix check for "minigzip -d foo.gz"
+- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee)
+- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau)
+- added makelcc.bat for lcc-win32 (Tom St Denis)
+- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe)
+- Avoid expanded $Id: ChangeLog,v 1.1 2005/09/23 22:39:00 beng Exp $. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion.
+- check for unistd.h in configure (for off_t)
+- remove useless check parameter in inflate_blocks_free
+- avoid useless assignment of s->check to itself in inflate_blocks_new
+- do not flush twice in gzclose (thanks to Ken Raeburn)
+- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h
+- use NO_ERRNO_H instead of enumeration of operating systems with errno.h
+- work around buggy fclose on pipes for HP/UX
+- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson)
+- fix configure if CC is already equal to gcc
+
+Changes in 1.0.5 (3 Jan 98)
+- Fix inflate to terminate gracefully when fed corrupted or invalid data
+- Use const for rommable constants in inflate
+- Eliminate memory leaks on error conditions in inflate
+- Removed some vestigial code in inflate
+- Update web address in README
+
+Changes in 1.0.4 (24 Jul 96)
+- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
+  bit, so the decompressor could decompress all the correct data but went
+  on to attempt decompressing extra garbage data. This affected minigzip too.
+- zlibVersion and gzerror return const char* (needed for DLL)
+- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
+- use z_error only for DEBUG (avoid problem with DLLs)
+
+Changes in 1.0.3 (2 Jul 96)
+- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS
+  small and medium models; this makes the library incompatible with previous
+  versions for these models. (No effect in large model or on other systems.)
+- return OK instead of BUF_ERROR if previous deflate call returned with
+  avail_out as zero but there is nothing to do
+- added memcmp for non STDC compilers
+- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly)
+- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO)
+- better check for 16-bit mode MSC (avoids problem with Symantec)
+
+Changes in 1.0.2 (23 May 96)
+- added Windows DLL support
+- added a function zlibVersion (for the DLL support)
+- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model)
+- Bytef is define's instead of typedef'd only for Borland C
+- avoid reading uninitialized memory in example.c
+- mention in README that the zlib format is now RFC1950
+- updated Makefile.dj2
+- added algorithm.doc
+
+Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
+- fix array overlay in deflate.c which sometimes caused bad compressed data
+- fix inflate bug with empty stored block
+- fix MSDOS medium model which was broken in 0.99
+- fix deflateParams() which could generated bad compressed data.
+- Bytef is define'd instead of typedef'ed (work around Borland bug)
+- added an INDEX file
+- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
+  Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas)
+- speed up adler32 for modern machines without auto-increment
+- added -ansi for IRIX in configure
+- static_init_done in trees.c is an int
+- define unlink as delete for VMS
+- fix configure for QNX
+- add configure branch for SCO and HPUX
+- avoid many warnings (unused variables, dead assignments, etc...)
+- no fdopen for BeOS
+- fix the Watcom fix for 32 bit mode (define FAR as empty)
+- removed redefinition of Byte for MKWERKS
+- work around an MWKERKS bug (incorrect merge of all .h files)
+
+Changes in 0.99 (27 Jan 96)
+- allow preset dictionary shared between compressor and decompressor
+- allow compression level 0 (no compression)
+- add deflateParams in zlib.h: allow dynamic change of compression level
+  and compression strategy.
+- test large buffers and deflateParams in example.c
+- add optional "configure" to build zlib as a shared library
+- suppress Makefile.qnx, use configure instead
+- fixed deflate for 64-bit systems (detected on Cray)
+- fixed inflate_blocks for 64-bit systems (detected on Alpha)
+- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2)
+- always return Z_BUF_ERROR when deflate() has nothing to do
+- deflateInit and inflateInit are now macros to allow version checking
+- prefix all global functions and types with z_ with -DZ_PREFIX
+- make falloc completely reentrant (inftrees.c)
+- fixed very unlikely race condition in ct_static_init
+- free in reverse order of allocation to help memory manager
+- use zlib-1.0/* instead of zlib/* inside the tar.gz
+- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith
+  -Wconversion -Wstrict-prototypes -Wmissing-prototypes"
+- allow gzread on concatenated .gz files
+- deflateEnd now returns Z_DATA_ERROR if it was premature
+- deflate is finally (?) fully deterministic (no matches beyond end of input)
+- Document Z_SYNC_FLUSH
+- add uninstall in Makefile
+- Check for __cpluplus in zlib.h
+- Better test in ct_align for partial flush
+- avoid harmless warnings for Borland C++
+- initialize hash_head in deflate.c
+- avoid warning on fdopen (gzio.c) for HP cc -Aa
+- include stdlib.h for STDC compilers
+- include errno.h for Cray
+- ignore error if ranlib doesn't exist
+- call ranlib twice for NeXTSTEP
+- use exec_prefix instead of prefix for libz.a
+- renamed ct_* as _tr_* to avoid conflict with applications
+- clear z->msg in inflateInit2 before any error return
+- initialize opaque in example.c, gzio.c, deflate.c and inflate.c
+- fixed typo in zconf.h (_GNUC__ => __GNUC__)
+- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode)
+- fix typo in Make_vms.com (f$trnlnm -> f$getsyi)
+- in fcalloc, normalize pointer if size > 65520 bytes
+- don't use special fcalloc for 32 bit Borland C++
+- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc...
+- use Z_BINARY instead of BINARY
+- document that gzclose after gzdopen will close the file
+- allow "a" as mode in gzopen.
+- fix error checking in gzread
+- allow skipping .gz extra-field on pipes
+- added reference to Perl interface in README
+- put the crc table in FAR data (I dislike more and more the medium model :)
+- added get_crc_table
+- added a dimension to all arrays (Borland C can't count).
+- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
+- guard against multiple inclusion of *.h (for precompiled header on Mac)
+- Watcom C pretends to be Microsoft C small model even in 32 bit mode.
+- don't use unsized arrays to avoid silly warnings by Visual C++:
+     warning C4746: 'inflate_mask' : unsized array treated as  '__far'
+     (what's wrong with far data in far model?).
+- define enum out of inflate_blocks_state to allow compilation with C++
+
+Changes in 0.95 (16 Aug 95)
+- fix MSDOS small and medium model (now easier to adapt to any compiler)
+- inlined send_bits
+- fix the final (:-) bug for deflate with flush (output was correct but
+  not completely flushed in rare occasions).
+- default window size is same for compression and decompression
+  (it's now sufficient to set MAX_WBITS in zconf.h).
+- voidp -> voidpf and voidnp -> voidp (for consistency with other
+  typedefs and because voidnp was not near in large model).
+
+Changes in 0.94 (13 Aug 95)
+- support MSDOS medium model
+- fix deflate with flush (could sometimes generate bad output)
+- fix deflateReset (zlib header was incorrectly suppressed)
+- added support for VMS
+- allow a compression level in gzopen()
+- gzflush now calls fflush
+- For deflate with flush, flush even if no more input is provided.
+- rename libgz.a as libz.a
+- avoid complex expression in infcodes.c triggering Turbo C bug
+- work around a problem with gcc on Alpha (in INSERT_STRING)
+- don't use inline functions (problem with some gcc versions)
+- allow renaming of Byte, uInt, etc... with #define.
+- avoid warning about (unused) pointer before start of array in deflate.c
+- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
+- avoid reserved word 'new' in trees.c
+
+Changes in 0.93 (25 June 95)
+- temporarily disable inline functions
+- make deflate deterministic
+- give enough lookahead for PARTIAL_FLUSH
+- Set binary mode for stdin/stdout in minigzip.c for OS/2
+- don't even use signed char in inflate (not portable enough)
+- fix inflate memory leak for segmented architectures
+
+Changes in 0.92 (3 May 95)
+- don't assume that char is signed (problem on SGI)
+- Clear bit buffer when starting a stored block
+- no memcpy on Pyramid
+- suppressed inftest.c
+- optimized fill_window, put longest_match inline for gcc
+- optimized inflate on stored blocks.
+- untabify all sources to simplify patches
+
+Changes in 0.91 (2 May 95)
+- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h
+- Document the memory requirements in zconf.h
+- added "make install"
+- fix sync search logic in inflateSync
+- deflate(Z_FULL_FLUSH) now works even if output buffer too short
+- after inflateSync, don't scare people with just "lo world"
+- added support for DJGPP
+
+Changes in 0.9 (1 May 95)
+- don't assume that zalloc clears the allocated memory (the TurboC bug
+  was Mark's bug after all :)
+- let again gzread copy uncompressed data unchanged (was working in 0.71)
+- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
+- added a test of inflateSync in example.c
+- moved MAX_WBITS to zconf.h because users might want to change that.
+- document explicitly that zalloc(64K) on MSDOS must return a normalized
+  pointer (zero offset)
+- added Makefiles for Microsoft C, Turbo C, Borland C++
+- faster crc32()
+
+Changes in 0.8 (29 April 95)
+- added fast inflate (inffast.c)
+- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
+  is incompatible with previous versions of zlib which returned Z_OK.
+- work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
+  (actually that was not a compiler bug, see 0.81 above)
+- gzread no longer reads one extra byte in certain cases
+- In gzio destroy(), don't reference a freed structure
+- avoid many warnings for MSDOS
+- avoid the ERROR symbol which is used by MS Windows
+
+Changes in 0.71 (14 April 95)
+- Fixed more MSDOS compilation problems :( There is still a bug with
+  TurboC large model.
+
+Changes in 0.7 (14 April 95)
+- Added full inflate support.
+- Simplified the crc32() interface. The pre- and post-conditioning
+  (one's complement) is now done inside crc32(). WARNING: this is
+  incompatible with previous versions; see zlib.h for the new usage.
+
+Changes in 0.61 (12 April 95)
+- workaround for a bug in TurboC. example and minigzip now work on MSDOS.
+
+Changes in 0.6 (11 April 95)
+- added minigzip.c
+- added gzdopen to reopen a file descriptor as gzFile
+- added transparent reading of non-gziped files in gzread.
+- fixed bug in gzread (don't read crc as data)
+- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose).
+- don't allocate big arrays in the stack (for MSDOS)
+- fix some MSDOS compilation problems
+
+Changes in 0.5:
+- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
+  not yet Z_FULL_FLUSH.
+- support decompression but only in a single step (forced Z_FINISH)
+- added opaque object for zalloc and zfree.
+- added deflateReset and inflateReset
+- added a variable zlib_version for consistency checking.
+- renamed the 'filter' parameter of deflateInit2 as 'strategy'.
+  Added Z_FILTERED and Z_HUFFMAN_ONLY constants.
+
+Changes in 0.4:
+- avoid "zip" everywhere, use zlib instead of ziplib.
+- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
+  if compression method == 8.
+- added adler32 and crc32
+- renamed deflateOptions as deflateInit2, call one or the other but not both
+- added the method parameter for deflateInit2.
+- added inflateInit2
+- simplied considerably deflateInit and inflateInit by not supporting
+  user-provided history buffer. This is supported only in deflateInit2
+  and inflateInit2.
+
+Changes in 0.3:
+- prefix all macro names with Z_
+- use Z_FINISH instead of deflateEnd to finish compression.
+- added Z_HUFFMAN_ONLY
+- added gzerror()
Index: /trunk/minix/lib/zlib-1.2.3/FAQ
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/FAQ	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/FAQ	(revision 9)
@@ -0,0 +1,339 @@
+
+                Frequently Asked Questions about zlib
+
+
+If your question is not there, please check the zlib home page
+http://www.zlib.org which may have more recent information.
+The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
+
+
+ 1. Is zlib Y2K-compliant?
+
+    Yes. zlib doesn't handle dates.
+
+ 2. Where can I get a Windows DLL version?
+
+    The zlib sources can be compiled without change to produce a DLL.
+    See the file win32/DLL_FAQ.txt in the zlib distribution.
+    Pointers to the precompiled DLL are found in the zlib web site at
+    http://www.zlib.org.
+
+ 3. Where can I get a Visual Basic interface to zlib?
+
+    See
+        * http://www.dogma.net/markn/articles/zlibtool/zlibtool.htm
+        * contrib/visual-basic.txt in the zlib distribution
+        * win32/DLL_FAQ.txt in the zlib distribution
+
+ 4. compress() returns Z_BUF_ERROR.
+
+    Make sure that before the call of compress, the length of the compressed
+    buffer is equal to the total size of the compressed buffer and not
+    zero. For Visual Basic, check that this parameter is passed by reference
+    ("as any"), not by value ("as long").
+
+ 5. deflate() or inflate() returns Z_BUF_ERROR.
+
+    Before making the call, make sure that avail_in and avail_out are not
+    zero. When setting the parameter flush equal to Z_FINISH, also make sure
+    that avail_out is big enough to allow processing all pending input.
+    Note that a Z_BUF_ERROR is not fatal--another call to deflate() or
+    inflate() can be made with more input or output space. A Z_BUF_ERROR
+    may in fact be unavoidable depending on how the functions are used, since
+    it is not possible to tell whether or not there is more output pending
+    when strm.avail_out returns with zero.
+
+ 6. Where's the zlib documentation (man pages, etc.)?
+
+    It's in zlib.h for the moment, and Francis S. Lin has converted it to a
+    web page zlib.html. Volunteers to transform this to Unix-style man pages,
+    please contact us (zlib@gzip.org). Examples of zlib usage are in the files
+    example.c and minigzip.c.
+
+ 7. Why don't you use GNU autoconf or libtool or ...?
+
+    Because we would like to keep zlib as a very small and simple
+    package. zlib is rather portable and doesn't need much configuration.
+
+ 8. I found a bug in zlib.
+
+    Most of the time, such problems are due to an incorrect usage of
+    zlib. Please try to reproduce the problem with a small program and send
+    the corresponding source to us at zlib@gzip.org . Do not send
+    multi-megabyte data files without prior agreement.
+
+ 9. Why do I get "undefined reference to gzputc"?
+
+    If "make test" produces something like
+
+       example.o(.text+0x154): undefined reference to `gzputc'
+
+    check that you don't have old files libz.* in /usr/lib, /usr/local/lib or
+    /usr/X11R6/lib. Remove any old versions, then do "make install".
+
+10. I need a Delphi interface to zlib.
+
+    See the contrib/delphi directory in the zlib distribution.
+
+11. Can zlib handle .zip archives?
+
+    Not by itself, no.  See the directory contrib/minizip in the zlib
+    distribution.
+
+12. Can zlib handle .Z files?
+
+    No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt
+    the code of uncompress on your own.
+
+13. How can I make a Unix shared library?
+
+    make clean
+    ./configure -s
+    make
+
+14. How do I install a shared zlib library on Unix?
+
+    After the above, then:
+
+    make install
+
+    However, many flavors of Unix come with a shared zlib already installed.
+    Before going to the trouble of compiling a shared version of zlib and
+    trying to install it, you may want to check if it's already there! If you
+    can #include <zlib.h>, it's there. The -lz option will probably link to it.
+
+15. I have a question about OttoPDF.
+
+    We are not the authors of OttoPDF. The real author is on the OttoPDF web
+    site: Joel Hainley, jhainley@myndkryme.com.
+
+16. Can zlib decode Flate data in an Adobe PDF file?
+
+    Yes. See http://www.fastio.com/ (ClibPDF), or http://www.pdflib.com/ .
+    To modify PDF forms, see http://sourceforge.net/projects/acroformtool/ .
+
+17. Why am I getting this "register_frame_info not found" error on Solaris?
+
+    After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib
+    generates an error such as:
+
+        ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so:
+        symbol __register_frame_info: referenced symbol not found
+
+    The symbol __register_frame_info is not part of zlib, it is generated by
+    the C compiler (cc or gcc). You must recompile applications using zlib
+    which have this problem. This problem is specific to Solaris. See
+    http://www.sunfreeware.com for Solaris versions of zlib and applications
+    using zlib.
+
+18. Why does gzip give an error on a file I make with compress/deflate?
+
+    The compress and deflate functions produce data in the zlib format, which
+    is different and incompatible with the gzip format. The gz* functions in
+    zlib on the other hand use the gzip format. Both the zlib and gzip
+    formats use the same compressed data format internally, but have different
+    headers and trailers around the compressed data.
+
+19. Ok, so why are there two different formats?
+
+    The gzip format was designed to retain the directory information about
+    a single file, such as the name and last modification date. The zlib
+    format on the other hand was designed for in-memory and communication
+    channel applications, and has a much more compact header and trailer and
+    uses a faster integrity check than gzip.
+
+20. Well that's nice, but how do I make a gzip file in memory?
+
+    You can request that deflate write the gzip format instead of the zlib
+    format using deflateInit2(). You can also request that inflate decode
+    the gzip format using inflateInit2(). Read zlib.h for more details.
+
+21. Is zlib thread-safe?
+
+    Yes. However any library routines that zlib uses and any application-
+    provided memory allocation routines must also be thread-safe. zlib's gz*
+    functions use stdio library routines, and most of zlib's functions use the
+    library memory allocation routines by default. zlib's Init functions allow
+    for the application to provide custom memory allocation routines.
+
+    Of course, you should only operate on any given zlib or gzip stream from a
+    single thread at a time.
+
+22. Can I use zlib in my commercial application?
+
+    Yes. Please read the license in zlib.h.
+
+23. Is zlib under the GNU license?
+
+    No. Please read the license in zlib.h.
+
+24. The license says that altered source versions must be "plainly marked". So
+    what exactly do I need to do to meet that requirement?
+
+    You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In
+    particular, the final version number needs to be changed to "f", and an
+    identification string should be appended to ZLIB_VERSION. Version numbers
+    x.x.x.f are reserved for modifications to zlib by others than the zlib
+    maintainers. For example, if the version of the base zlib you are altering
+    is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and
+    ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also
+    update the version strings in deflate.c and inftrees.c.
+
+    For altered source distributions, you should also note the origin and
+    nature of the changes in zlib.h, as well as in ChangeLog and README, along
+    with the dates of the alterations. The origin should include at least your
+    name (or your company's name), and an email address to contact for help or
+    issues with the library.
+
+    Note that distributing a compiled zlib library along with zlib.h and
+    zconf.h is also a source distribution, and so you should change
+    ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes
+    in zlib.h as you would for a full source distribution.
+
+25. Will zlib work on a big-endian or little-endian architecture, and can I
+    exchange compressed data between them?
+
+    Yes and yes.
+
+26. Will zlib work on a 64-bit machine?
+
+    It should. It has been tested on 64-bit machines, and has no dependence
+    on any data types being limited to 32-bits in length. If you have any
+    difficulties, please provide a complete problem report to zlib@gzip.org
+
+27. Will zlib decompress data from the PKWare Data Compression Library?
+
+    No. The PKWare DCL uses a completely different compressed data format
+    than does PKZIP and zlib. However, you can look in zlib's contrib/blast
+    directory for a possible solution to your problem.
+
+28. Can I access data randomly in a compressed stream?
+
+    No, not without some preparation. If when compressing you periodically
+    use Z_FULL_FLUSH, carefully write all the pending data at those points,
+    and keep an index of those locations, then you can start decompression
+    at those points. You have to be careful to not use Z_FULL_FLUSH too
+    often, since it can significantly degrade compression.
+
+29. Does zlib work on MVS, OS/390, CICS, etc.?
+
+    We don't know for sure. We have heard occasional reports of success on
+    these systems. If you do use it on one of these, please provide us with
+    a report, instructions, and patches that we can reference when we get
+    these questions. Thanks.
+
+30. Is there some simpler, easier to read version of inflate I can look at
+    to understand the deflate format?
+
+    First off, you should read RFC 1951. Second, yes. Look in zlib's
+    contrib/puff directory.
+
+31. Does zlib infringe on any patents?
+
+    As far as we know, no. In fact, that was originally the whole point behind
+    zlib. Look here for some more information:
+
+    http://www.gzip.org/#faq11
+
+32. Can zlib work with greater than 4 GB of data?
+
+    Yes. inflate() and deflate() will process any amount of data correctly.
+    Each call of inflate() or deflate() is limited to input and output chunks
+    of the maximum value that can be stored in the compiler's "unsigned int"
+    type, but there is no limit to the number of chunks. Note however that the
+    strm.total_in and strm_total_out counters may be limited to 4 GB. These
+    counters are provided as a convenience and are not used internally by
+    inflate() or deflate(). The application can easily set up its own counters
+    updated after each call of inflate() or deflate() to count beyond 4 GB.
+    compress() and uncompress() may be limited to 4 GB, since they operate in a
+    single call. gzseek() and gztell() may be limited to 4 GB depending on how
+    zlib is compiled. See the zlibCompileFlags() function in zlib.h.
+
+    The word "may" appears several times above since there is a 4 GB limit
+    only if the compiler's "long" type is 32 bits. If the compiler's "long"
+    type is 64 bits, then the limit is 16 exabytes.
+
+33. Does zlib have any security vulnerabilities?
+
+    The only one that we are aware of is potentially in gzprintf(). If zlib
+    is compiled to use sprintf() or vsprintf(), then there is no protection
+    against a buffer overflow of a 4K string space, other than the caller of
+    gzprintf() assuring that the output will not exceed 4K. On the other
+    hand, if zlib is compiled to use snprintf() or vsnprintf(), which should
+    normally be the case, then there is no vulnerability. The ./configure
+    script will display warnings if an insecure variation of sprintf() will
+    be used by gzprintf(). Also the zlibCompileFlags() function will return
+    information on what variant of sprintf() is used by gzprintf().
+
+    If you don't have snprintf() or vsnprintf() and would like one, you can
+    find a portable implementation here:
+
+        http://www.ijs.si/software/snprintf/
+
+    Note that you should be using the most recent version of zlib. Versions
+    1.1.3 and before were subject to a double-free vulnerability.
+
+34. Is there a Java version of zlib?
+
+    Probably what you want is to use zlib in Java. zlib is already included
+    as part of the Java SDK in the java.util.zip package. If you really want
+    a version of zlib written in the Java language, look on the zlib home
+    page for links: http://www.zlib.org/
+
+35. I get this or that compiler or source-code scanner warning when I crank it
+    up to maximally-pedantic. Can't you guys write proper code?
+
+    Many years ago, we gave up attempting to avoid warnings on every compiler
+    in the universe. It just got to be a waste of time, and some compilers
+    were downright silly. So now, we simply make sure that the code always
+    works.
+
+36. Valgrind (or some similar memory access checker) says that deflate is
+    performing a conditional jump that depends on an uninitialized value.
+    Isn't that a bug?
+
+    No.  That is intentional for performance reasons, and the output of
+    deflate is not affected.  This only started showing up recently since
+    zlib 1.2.x uses malloc() by default for allocations, whereas earlier
+    versions used calloc(), which zeros out the allocated memory.
+
+37. Will zlib read the (insert any ancient or arcane format here) compressed
+    data format?
+
+    Probably not. Look in the comp.compression FAQ for pointers to various
+    formats and associated software.
+
+38. How can I encrypt/decrypt zip files with zlib?
+
+    zlib doesn't support encryption. The original PKZIP encryption is very weak
+    and can be broken with freely available programs. To get strong encryption,
+    use GnuPG, http://www.gnupg.org/ , which already includes zlib compression.
+    For PKZIP compatible "encryption", look at http://www.info-zip.org/
+
+39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
+
+    "gzip" is the gzip format, and "deflate" is the zlib format. They should
+    probably have called the second one "zlib" instead to avoid confusion
+    with the raw deflate compressed data format. While the HTTP 1.1 RFC 2616
+    correctly points to the zlib specification in RFC 1950 for the "deflate"
+    transfer encoding, there have been reports of servers and browsers that
+    incorrectly produce or expect raw deflate data per the deflate
+    specficiation in RFC 1951, most notably Microsoft. So even though the
+    "deflate" transfer encoding using the zlib format would be the more
+    efficient approach (and in fact exactly what the zlib format was designed
+    for), using the "gzip" transfer encoding is probably more reliable due to
+    an unfortunate choice of name on the part of the HTTP 1.1 authors.
+
+    Bottom line: use the gzip format for HTTP 1.1 encoding.
+
+40. Does zlib support the new "Deflate64" format introduced by PKWare?
+
+    No. PKWare has apparently decided to keep that format proprietary, since
+    they have not documented it as they have previous compression formats.
+    In any case, the compression improvements are so modest compared to other
+    more modern approaches, that it's not worth the effort to implement.
+
+41. Can you please sign these lengthy legal documents and fax them back to us
+    so that we can use your software in our product?
+
+    No. Go away. Shoo.
Index: /trunk/minix/lib/zlib-1.2.3/INDEX
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/INDEX	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/INDEX	(revision 9)
@@ -0,0 +1,51 @@
+ChangeLog       history of changes
+FAQ             Frequently Asked Questions about zlib
+INDEX           this file
+Makefile        makefile for Unix (generated by configure)
+Makefile.in     makefile for Unix (template for configure)
+README          guess what
+algorithm.txt   description of the (de)compression algorithm
+configure       configure script for Unix
+zconf.in.h      template for zconf.h (used by configure)
+
+amiga/          makefiles for Amiga SAS C
+as400/          makefiles for IBM AS/400
+msdos/          makefiles for MSDOS
+old/            makefiles for various architectures and zlib documentation
+                files that have not yet been updated for zlib 1.2.x
+projects/       projects for various Integrated Development Environments
+qnx/            makefiles for QNX
+win32/          makefiles for Windows
+
+                zlib public header files (must be kept):
+zconf.h
+zlib.h
+
+                private source files used to build the zlib library:
+adler32.c
+compress.c
+crc32.c
+crc32.h
+deflate.c
+deflate.h
+gzio.c
+infback.c
+inffast.c
+inffast.h
+inffixed.h
+inflate.c
+inflate.h
+inftrees.c
+inftrees.h
+trees.c
+trees.h
+uncompr.c
+zutil.c
+zutil.h
+
+                source files for sample programs:
+example.c
+minigzip.c
+
+                unsupported contribution by third parties
+See contrib/README.contrib
Index: /trunk/minix/lib/zlib-1.2.3/Makedepend-ack
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/Makedepend-ack	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/Makedepend-ack	(revision 9)
@@ -0,0 +1,15 @@
+depend-ack:
+	rm .depend-ack
+	touch .depend-ack
+	mkdep 'cc -O -E' adler32.c | sed -e 's:^\(.\):../obj-ack//./zlib-1.2.3/\1:' >> .depend-ack
+	mkdep 'cc -O -E' compress.c | sed -e 's:^\(.\):../obj-ack//./zlib-1.2.3/\1:' >> .depend-ack
+	mkdep 'cc -O -E' crc32.c | sed -e 's:^\(.\):../obj-ack//./zlib-1.2.3/\1:' >> .depend-ack
+	mkdep 'cc -O -E' gzio.c | sed -e 's:^\(.\):../obj-ack//./zlib-1.2.3/\1:' >> .depend-ack
+	mkdep 'cc -O -E' uncompr.c | sed -e 's:^\(.\):../obj-ack//./zlib-1.2.3/\1:' >> .depend-ack
+	mkdep 'cc -O -E' deflate.c | sed -e 's:^\(.\):../obj-ack//./zlib-1.2.3/\1:' >> .depend-ack
+	mkdep 'cc -O -E' trees.c | sed -e 's:^\(.\):../obj-ack//./zlib-1.2.3/\1:' >> .depend-ack
+	mkdep 'cc -O -E' zutil.c | sed -e 's:^\(.\):../obj-ack//./zlib-1.2.3/\1:' >> .depend-ack
+	mkdep 'cc -O -E' inflate.c | sed -e 's:^\(.\):../obj-ack//./zlib-1.2.3/\1:' >> .depend-ack
+	mkdep 'cc -O -E' infback.c | sed -e 's:^\(.\):../obj-ack//./zlib-1.2.3/\1:' >> .depend-ack
+	mkdep 'cc -O -E' inftrees.c | sed -e 's:^\(.\):../obj-ack//./zlib-1.2.3/\1:' >> .depend-ack
+	mkdep 'cc -O -E' inffast.c | sed -e 's:^\(.\):../obj-ack//./zlib-1.2.3/\1:' >> .depend-ack
Index: /trunk/minix/lib/zlib-1.2.3/Makedepend-gnu
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/Makedepend-gnu	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/Makedepend-gnu	(revision 9)
@@ -0,0 +1,15 @@
+depend-gnu:
+	rm .depend-gnu
+	touch .depend-gnu
+	mkdep 'gcc -O -E' adler32.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./zlib-1.2.3/\1:' >> .depend-gnu
+	mkdep 'gcc -O -E' compress.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./zlib-1.2.3/\1:' >> .depend-gnu
+	mkdep 'gcc -O -E' crc32.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./zlib-1.2.3/\1:' >> .depend-gnu
+	mkdep 'gcc -O -E' gzio.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./zlib-1.2.3/\1:' >> .depend-gnu
+	mkdep 'gcc -O -E' uncompr.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./zlib-1.2.3/\1:' >> .depend-gnu
+	mkdep 'gcc -O -E' deflate.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./zlib-1.2.3/\1:' >> .depend-gnu
+	mkdep 'gcc -O -E' trees.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./zlib-1.2.3/\1:' >> .depend-gnu
+	mkdep 'gcc -O -E' zutil.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./zlib-1.2.3/\1:' >> .depend-gnu
+	mkdep 'gcc -O -E' inflate.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./zlib-1.2.3/\1:' >> .depend-gnu
+	mkdep 'gcc -O -E' infback.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./zlib-1.2.3/\1:' >> .depend-gnu
+	mkdep 'gcc -O -E' inftrees.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./zlib-1.2.3/\1:' >> .depend-gnu
+	mkdep 'gcc -O -E' inffast.c | sed -e '/<built-in>/d' -e '/<command line>/d' -e 's:^\(.\):../obj-gnu/./zlib-1.2.3/\1:' >> .depend-gnu
Index: /trunk/minix/lib/zlib-1.2.3/Makefile
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/Makefile	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/Makefile	(revision 9)
@@ -0,0 +1,129 @@
+#Generated from ./zlib-1.2.3/Makefile.in
+all: all-ack
+
+all-ack:
+all-gnu:
+
+makefiles: Makefile
+Makedepend-ack Makedepend-gnu: 
+	sh ../generate.sh ./zlib-1.2.3 ../obj-ack/ ../obj-gnu
+
+Makefile: Makefile.in Makedepend-ack Makedepend-gnu
+	sh ../generate.sh ./zlib-1.2.3 ../obj-ack/ ../obj-gnu
+	@echo
+	@echo *Attention*
+	@echo Makefile is regenerated... rerun command to see changes
+	@echo *Attention*
+	@echo
+
+depend: depend-ack
+all-ack: ../obj-ack//libz.a
+
+../obj-ack//libz.a: ../obj-ack//libz.a(adler32.o)
+../obj-ack//libz.a: ../obj-ack//libz.a(compress.o)
+../obj-ack//libz.a: ../obj-ack//libz.a(crc32.o)
+../obj-ack//libz.a: ../obj-ack//libz.a(gzio.o)
+../obj-ack//libz.a: ../obj-ack//libz.a(uncompr.o)
+../obj-ack//libz.a: ../obj-ack//libz.a(deflate.o)
+../obj-ack//libz.a: ../obj-ack//libz.a(trees.o)
+../obj-ack//libz.a: ../obj-ack//libz.a(zutil.o)
+../obj-ack//libz.a: ../obj-ack//libz.a(inflate.o)
+../obj-ack//libz.a: ../obj-ack//libz.a(infback.o)
+../obj-ack//libz.a: ../obj-ack//libz.a(inftrees.o)
+../obj-ack//libz.a: ../obj-ack//libz.a(inffast.o)
+
+../obj-ack//libz.a:
+	ar cr ../obj-ack//libz.a ../obj-ack//./zlib-1.2.3/*.o
+	rm ../obj-ack//./zlib-1.2.3/*.o
+
+../obj-ack//libz.a(adler32.o): adler32.c
+	cc -O -c -o ../obj-ack//./zlib-1.2.3/adler32.o adler32.c
+../obj-ack//libz.a(compress.o): compress.c
+	cc -O -c -o ../obj-ack//./zlib-1.2.3/compress.o compress.c
+../obj-ack//libz.a(crc32.o): crc32.c
+	cc -O -c -o ../obj-ack//./zlib-1.2.3/crc32.o crc32.c
+../obj-ack//libz.a(gzio.o): gzio.c
+	cc -O -c -o ../obj-ack//./zlib-1.2.3/gzio.o gzio.c
+../obj-ack//libz.a(uncompr.o): uncompr.c
+	cc -O -c -o ../obj-ack//./zlib-1.2.3/uncompr.o uncompr.c
+../obj-ack//libz.a(deflate.o): deflate.c
+	cc -O -c -o ../obj-ack//./zlib-1.2.3/deflate.o deflate.c
+../obj-ack//libz.a(trees.o): trees.c
+	cc -O -c -o ../obj-ack//./zlib-1.2.3/trees.o trees.c
+../obj-ack//libz.a(zutil.o): zutil.c
+	cc -O -c -o ../obj-ack//./zlib-1.2.3/zutil.o zutil.c
+../obj-ack//libz.a(inflate.o): inflate.c
+	cc -O -c -o ../obj-ack//./zlib-1.2.3/inflate.o inflate.c
+../obj-ack//libz.a(infback.o): infback.c
+	cc -O -c -o ../obj-ack//./zlib-1.2.3/infback.o infback.c
+../obj-ack//libz.a(inftrees.o): inftrees.c
+	cc -O -c -o ../obj-ack//./zlib-1.2.3/inftrees.o inftrees.c
+../obj-ack//libz.a(inffast.o): inffast.c
+	cc -O -c -o ../obj-ack//./zlib-1.2.3/inffast.o inffast.c
+
+all-gnu: ../obj-gnu/libz.a
+
+../obj-gnu/libz.a: ../obj-gnu/./zlib-1.2.3/adler32.o
+../obj-gnu/libz.a: ../obj-gnu/./zlib-1.2.3/compress.o
+../obj-gnu/libz.a: ../obj-gnu/./zlib-1.2.3/crc32.o
+../obj-gnu/libz.a: ../obj-gnu/./zlib-1.2.3/gzio.o
+../obj-gnu/libz.a: ../obj-gnu/./zlib-1.2.3/uncompr.o
+../obj-gnu/libz.a: ../obj-gnu/./zlib-1.2.3/deflate.o
+../obj-gnu/libz.a: ../obj-gnu/./zlib-1.2.3/trees.o
+../obj-gnu/libz.a: ../obj-gnu/./zlib-1.2.3/zutil.o
+../obj-gnu/libz.a: ../obj-gnu/./zlib-1.2.3/inflate.o
+../obj-gnu/libz.a: ../obj-gnu/./zlib-1.2.3/infback.o
+../obj-gnu/libz.a: ../obj-gnu/./zlib-1.2.3/inftrees.o
+../obj-gnu/libz.a: ../obj-gnu/./zlib-1.2.3/inffast.o
+
+../obj-gnu/libz.a:
+	gar cr ../obj-gnu/libz.a $?
+
+../obj-gnu/./zlib-1.2.3/adler32.o: adler32.c
+	gcc -O -c -o ../obj-gnu/./zlib-1.2.3/adler32.o adler32.c
+
+../obj-gnu/./zlib-1.2.3/compress.o: compress.c
+	gcc -O -c -o ../obj-gnu/./zlib-1.2.3/compress.o compress.c
+
+../obj-gnu/./zlib-1.2.3/crc32.o: crc32.c
+	gcc -O -c -o ../obj-gnu/./zlib-1.2.3/crc32.o crc32.c
+
+../obj-gnu/./zlib-1.2.3/gzio.o: gzio.c
+	gcc -O -c -o ../obj-gnu/./zlib-1.2.3/gzio.o gzio.c
+
+../obj-gnu/./zlib-1.2.3/uncompr.o: uncompr.c
+	gcc -O -c -o ../obj-gnu/./zlib-1.2.3/uncompr.o uncompr.c
+
+../obj-gnu/./zlib-1.2.3/deflate.o: deflate.c
+	gcc -O -c -o ../obj-gnu/./zlib-1.2.3/deflate.o deflate.c
+
+../obj-gnu/./zlib-1.2.3/trees.o: trees.c
+	gcc -O -c -o ../obj-gnu/./zlib-1.2.3/trees.o trees.c
+
+../obj-gnu/./zlib-1.2.3/zutil.o: zutil.c
+	gcc -O -c -o ../obj-gnu/./zlib-1.2.3/zutil.o zutil.c
+
+../obj-gnu/./zlib-1.2.3/inflate.o: inflate.c
+	gcc -O -c -o ../obj-gnu/./zlib-1.2.3/inflate.o inflate.c
+
+../obj-gnu/./zlib-1.2.3/infback.o: infback.c
+	gcc -O -c -o ../obj-gnu/./zlib-1.2.3/infback.o infback.c
+
+../obj-gnu/./zlib-1.2.3/inftrees.o: inftrees.c
+	gcc -O -c -o ../obj-gnu/./zlib-1.2.3/inftrees.o inftrees.c
+
+../obj-gnu/./zlib-1.2.3/inffast.o: inffast.c
+	gcc -O -c -o ../obj-gnu/./zlib-1.2.3/inffast.o inffast.c
+
+
+
+
+clean::
+	rm -f ../obj-ack//./zlib-1.2.3/*
+	rm -f ../obj-gnu/./zlib-1.2.3/*
+
+include Makedepend-ack
+include .depend-ack
+
+include Makedepend-gnu
+include .depend-gnu
Index: /trunk/minix/lib/zlib-1.2.3/Makefile.in
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/Makefile.in	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/Makefile.in	(revision 9)
@@ -0,0 +1,12 @@
+# Makefile for zlib
+
+CC=cc
+
+CFLAGS=-O
+
+LIBRARIES=libz
+
+libz_FILES="adler32.c compress.c crc32.c gzio.c uncompr.c deflate.c trees.c \
+       zutil.c inflate.c infback.c inftrees.c inffast.c"
+
+TYPE=both
Index: /trunk/minix/lib/zlib-1.2.3/README
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/README	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/README	(revision 9)
@@ -0,0 +1,125 @@
+ZLIB DATA COMPRESSION LIBRARY
+
+zlib 1.2.3 is a general purpose data compression library.  All the code is
+thread safe.  The data format used by the zlib library is described by RFCs
+(Request for Comments) 1950 to 1952 in the files
+http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
+and rfc1952.txt (gzip format). These documents are also available in other
+formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
+
+All functions of the compression library are documented in the file zlib.h
+(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
+of the library is given in the file example.c which also tests that the library
+is working correctly. Another example is given in the file minigzip.c. The
+compression library itself is composed of all source files except example.c and
+minigzip.c.
+
+To compile all files and run the test program, follow the instructions given at
+the top of Makefile. In short "make test; make install" should work for most
+machines. For Unix: "./configure; make test; make install". For MSDOS, use one
+of the special makefiles such as Makefile.msc. For VMS, use make_vms.com.
+
+Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
+<info@winimage.com> for the Windows DLL version. The zlib home page is
+http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem,
+please check this site to verify that you have the latest version of zlib;
+otherwise get the latest version and check whether the problem still exists or
+not.
+
+PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking
+for help.
+
+Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
+issue of  Dr. Dobb's Journal; a copy of the article is available in
+http://dogma.net/markn/articles/zlibtool/zlibtool.htm
+
+The changes made in version 1.2.3 are documented in the file ChangeLog.
+
+Unsupported third party contributions are provided in directory "contrib".
+
+A Java implementation of zlib is available in the Java Development Kit
+http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html
+See the zlib home page http://www.zlib.org for details.
+
+A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is in the
+CPAN (Comprehensive Perl Archive Network) sites
+http://www.cpan.org/modules/by-module/Compress/
+
+A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
+available in Python 1.5 and later versions, see
+http://www.python.org/doc/lib/module-zlib.html
+
+A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com> is
+availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html
+
+An experimental package to read and write files in .zip format, written on top
+of zlib by Gilles Vollant <info@winimage.com>, is available in the
+contrib/minizip directory of zlib.
+
+
+Notes for some targets:
+
+- For Windows DLL versions, please see win32/DLL_FAQ.txt
+
+- For 64-bit Irix, deflate.c must be compiled without any optimization. With
+  -O, one libpng test fails. The test works in 32 bit mode (with the -n32
+  compiler flag). The compiler bug has been reported to SGI.
+
+- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
+  when compiled with cc.
+
+- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
+  necessary to get gzprintf working correctly. This is done by configure.
+
+- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
+  other compilers. Use "make test" to check your compiler.
+
+- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
+
+- For PalmOs, see http://palmzlib.sourceforge.net/
+
+- When building a shared, i.e. dynamic library on Mac OS X, the library must be
+  installed before testing (do "make install" before "make test"), since the
+  library location is specified in the library.
+
+
+Acknowledgments:
+
+  The deflate format used by zlib was defined by Phil Katz. The deflate
+  and zlib specifications were written by L. Peter Deutsch. Thanks to all the
+  people who reported problems and suggested various improvements in zlib;
+  they are too numerous to cite here.
+
+Copyright notice:
+
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not*
+receiving lengthy legal documents to sign. The sources are provided
+for free but without warranty of any kind.  The library has been
+entirely written by Jean-loup Gailly and Mark Adler; it does not
+include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include
+in the file ChangeLog history information documenting your changes. Please
+read the FAQ for more information on the distribution of modified source
+versions.
Index: /trunk/minix/lib/zlib-1.2.3/adler32.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/adler32.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/adler32.c	(revision 9)
@@ -0,0 +1,149 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: adler32.c,v 1.1 2005/09/23 22:39:00 beng Exp $ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+#define BASE 65521UL    /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware */
+#ifdef NO_DIVIDE
+#  define MOD(a) \
+    do { \
+        if (a >= (BASE << 16)) a -= (BASE << 16); \
+        if (a >= (BASE << 15)) a -= (BASE << 15); \
+        if (a >= (BASE << 14)) a -= (BASE << 14); \
+        if (a >= (BASE << 13)) a -= (BASE << 13); \
+        if (a >= (BASE << 12)) a -= (BASE << 12); \
+        if (a >= (BASE << 11)) a -= (BASE << 11); \
+        if (a >= (BASE << 10)) a -= (BASE << 10); \
+        if (a >= (BASE << 9)) a -= (BASE << 9); \
+        if (a >= (BASE << 8)) a -= (BASE << 8); \
+        if (a >= (BASE << 7)) a -= (BASE << 7); \
+        if (a >= (BASE << 6)) a -= (BASE << 6); \
+        if (a >= (BASE << 5)) a -= (BASE << 5); \
+        if (a >= (BASE << 4)) a -= (BASE << 4); \
+        if (a >= (BASE << 3)) a -= (BASE << 3); \
+        if (a >= (BASE << 2)) a -= (BASE << 2); \
+        if (a >= (BASE << 1)) a -= (BASE << 1); \
+        if (a >= BASE) a -= BASE; \
+    } while (0)
+#  define MOD4(a) \
+    do { \
+        if (a >= (BASE << 4)) a -= (BASE << 4); \
+        if (a >= (BASE << 3)) a -= (BASE << 3); \
+        if (a >= (BASE << 2)) a -= (BASE << 2); \
+        if (a >= (BASE << 1)) a -= (BASE << 1); \
+        if (a >= BASE) a -= BASE; \
+    } while (0)
+#else
+#  define MOD(a) a %= BASE
+#  define MOD4(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+    uLong adler;
+    const Bytef *buf;
+    uInt len;
+{
+    unsigned long sum2;
+    unsigned n;
+
+    /* split Adler-32 into component sums */
+    sum2 = (adler >> 16) & 0xffff;
+    adler &= 0xffff;
+
+    /* in case user likes doing a byte at a time, keep it fast */
+    if (len == 1) {
+        adler += buf[0];
+        if (adler >= BASE)
+            adler -= BASE;
+        sum2 += adler;
+        if (sum2 >= BASE)
+            sum2 -= BASE;
+        return adler | (sum2 << 16);
+    }
+
+    /* initial Adler-32 value (deferred check for len == 1 speed) */
+    if (buf == Z_NULL)
+        return 1L;
+
+    /* in case short lengths are provided, keep it somewhat fast */
+    if (len < 16) {
+        while (len--) {
+            adler += *buf++;
+            sum2 += adler;
+        }
+        if (adler >= BASE)
+            adler -= BASE;
+        MOD4(sum2);             /* only added so many BASE's */
+        return adler | (sum2 << 16);
+    }
+
+    /* do length NMAX blocks -- requires just one modulo operation */
+    while (len >= NMAX) {
+        len -= NMAX;
+        n = NMAX / 16;          /* NMAX is divisible by 16 */
+        do {
+            DO16(buf);          /* 16 sums unrolled */
+            buf += 16;
+        } while (--n);
+        MOD(adler);
+        MOD(sum2);
+    }
+
+    /* do remaining bytes (less than NMAX, still just one modulo) */
+    if (len) {                  /* avoid modulos if none remaining */
+        while (len >= 16) {
+            len -= 16;
+            DO16(buf);
+            buf += 16;
+        }
+        while (len--) {
+            adler += *buf++;
+            sum2 += adler;
+        }
+        MOD(adler);
+        MOD(sum2);
+    }
+
+    /* return recombined sums */
+    return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(adler1, adler2, len2)
+    uLong adler1;
+    uLong adler2;
+    z_off_t len2;
+{
+    unsigned long sum1;
+    unsigned long sum2;
+    unsigned rem;
+
+    /* the derivation of this formula is left as an exercise for the reader */
+    rem = (unsigned)(len2 % BASE);
+    sum1 = adler1 & 0xffff;
+    sum2 = rem * sum1;
+    MOD(sum2);
+    sum1 += (adler2 & 0xffff) + BASE - 1;
+    sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+    if (sum1 > BASE) sum1 -= BASE;
+    if (sum1 > BASE) sum1 -= BASE;
+    if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
+    if (sum2 > BASE) sum2 -= BASE;
+    return sum1 | (sum2 << 16);
+}
Index: /trunk/minix/lib/zlib-1.2.3/algorithm.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/algorithm.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/algorithm.txt	(revision 9)
@@ -0,0 +1,209 @@
+1. Compression algorithm (deflate)
+
+The deflation algorithm used by gzip (also zip and zlib) is a variation of
+LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
+the input data.  The second occurrence of a string is replaced by a
+pointer to the previous string, in the form of a pair (distance,
+length).  Distances are limited to 32K bytes, and lengths are limited
+to 258 bytes. When a string does not occur anywhere in the previous
+32K bytes, it is emitted as a sequence of literal bytes.  (In this
+description, `string' must be taken as an arbitrary sequence of bytes,
+and is not restricted to printable characters.)
+
+Literals or match lengths are compressed with one Huffman tree, and
+match distances are compressed with another tree. The trees are stored
+in a compact form at the start of each block. The blocks can have any
+size (except that the compressed data for one block must fit in
+available memory). A block is terminated when deflate() determines that
+it would be useful to start another block with fresh trees. (This is
+somewhat similar to the behavior of LZW-based _compress_.)
+
+Duplicated strings are found using a hash table. All input strings of
+length 3 are inserted in the hash table. A hash index is computed for
+the next 3 bytes. If the hash chain for this index is not empty, all
+strings in the chain are compared with the current input string, and
+the longest match is selected.
+
+The hash chains are searched starting with the most recent strings, to
+favor small distances and thus take advantage of the Huffman encoding.
+The hash chains are singly linked. There are no deletions from the
+hash chains, the algorithm simply discards matches that are too old.
+
+To avoid a worst-case situation, very long hash chains are arbitrarily
+truncated at a certain length, determined by a runtime option (level
+parameter of deflateInit). So deflate() does not always find the longest
+possible match but generally finds a match which is long enough.
+
+deflate() also defers the selection of matches with a lazy evaluation
+mechanism. After a match of length N has been found, deflate() searches for
+a longer match at the next input byte. If a longer match is found, the
+previous match is truncated to a length of one (thus producing a single
+literal byte) and the process of lazy evaluation begins again. Otherwise,
+the original match is kept, and the next match search is attempted only N
+steps later.
+
+The lazy match evaluation is also subject to a runtime parameter. If
+the current match is long enough, deflate() reduces the search for a longer
+match, thus speeding up the whole process. If compression ratio is more
+important than speed, deflate() attempts a complete second search even if
+the first match is already long enough.
+
+The lazy match evaluation is not performed for the fastest compression
+modes (level parameter 1 to 3). For these fast modes, new strings
+are inserted in the hash table only when no match was found, or
+when the match is not too long. This degrades the compression ratio
+but saves time since there are both fewer insertions and fewer searches.
+
+
+2. Decompression algorithm (inflate)
+
+2.1 Introduction
+
+The key question is how to represent a Huffman code (or any prefix code) so
+that you can decode fast.  The most important characteristic is that shorter
+codes are much more common than longer codes, so pay attention to decoding the
+short codes fast, and let the long codes take longer to decode.
+
+inflate() sets up a first level table that covers some number of bits of
+input less than the length of longest code.  It gets that many bits from the
+stream, and looks it up in the table.  The table will tell if the next
+code is that many bits or less and how many, and if it is, it will tell
+the value, else it will point to the next level table for which inflate()
+grabs more bits and tries to decode a longer code.
+
+How many bits to make the first lookup is a tradeoff between the time it
+takes to decode and the time it takes to build the table.  If building the
+table took no time (and if you had infinite memory), then there would only
+be a first level table to cover all the way to the longest code.  However,
+building the table ends up taking a lot longer for more bits since short
+codes are replicated many times in such a table.  What inflate() does is
+simply to make the number of bits in the first table a variable, and  then
+to set that variable for the maximum speed.
+
+For inflate, which has 286 possible codes for the literal/length tree, the size
+of the first table is nine bits.  Also the distance trees have 30 possible
+values, and the size of the first table is six bits.  Note that for each of
+those cases, the table ended up one bit longer than the ``average'' code
+length, i.e. the code length of an approximately flat code which would be a
+little more than eight bits for 286 symbols and a little less than five bits
+for 30 symbols.
+
+
+2.2 More details on the inflate table lookup
+
+Ok, you want to know what this cleverly obfuscated inflate tree actually
+looks like.  You are correct that it's not a Huffman tree.  It is simply a
+lookup table for the first, let's say, nine bits of a Huffman symbol.  The
+symbol could be as short as one bit or as long as 15 bits.  If a particular
+symbol is shorter than nine bits, then that symbol's translation is duplicated
+in all those entries that start with that symbol's bits.  For example, if the
+symbol is four bits, then it's duplicated 32 times in a nine-bit table.  If a
+symbol is nine bits long, it appears in the table once.
+
+If the symbol is longer than nine bits, then that entry in the table points
+to another similar table for the remaining bits.  Again, there are duplicated
+entries as needed.  The idea is that most of the time the symbol will be short
+and there will only be one table look up.  (That's whole idea behind data
+compression in the first place.)  For the less frequent long symbols, there
+will be two lookups.  If you had a compression method with really long
+symbols, you could have as many levels of lookups as is efficient.  For
+inflate, two is enough.
+
+So a table entry either points to another table (in which case nine bits in
+the above example are gobbled), or it contains the translation for the symbol
+and the number of bits to gobble.  Then you start again with the next
+ungobbled bit.
+
+You may wonder: why not just have one lookup table for how ever many bits the
+longest symbol is?  The reason is that if you do that, you end up spending
+more time filling in duplicate symbol entries than you do actually decoding.
+At least for deflate's output that generates new trees every several 10's of
+kbytes.  You can imagine that filling in a 2^15 entry table for a 15-bit code
+would take too long if you're only decoding several thousand symbols.  At the
+other extreme, you could make a new table for every bit in the code.  In fact,
+that's essentially a Huffman tree.  But then you spend two much time
+traversing the tree while decoding, even for short symbols.
+
+So the number of bits for the first lookup table is a trade of the time to
+fill out the table vs. the time spent looking at the second level and above of
+the table.
+
+Here is an example, scaled down:
+
+The code being decoded, with 10 symbols, from 1 to 6 bits long:
+
+A: 0
+B: 10
+C: 1100
+D: 11010
+E: 11011
+F: 11100
+G: 11101
+H: 11110
+I: 111110
+J: 111111
+
+Let's make the first table three bits long (eight entries):
+
+000: A,1
+001: A,1
+010: A,1
+011: A,1
+100: B,2
+101: B,2
+110: -> table X (gobble 3 bits)
+111: -> table Y (gobble 3 bits)
+
+Each entry is what the bits decode as and how many bits that is, i.e. how
+many bits to gobble.  Or the entry points to another table, with the number of
+bits to gobble implicit in the size of the table.
+
+Table X is two bits long since the longest code starting with 110 is five bits
+long:
+
+00: C,1
+01: C,1
+10: D,2
+11: E,2
+
+Table Y is three bits long since the longest code starting with 111 is six
+bits long:
+
+000: F,2
+001: F,2
+010: G,2
+011: G,2
+100: H,2
+101: H,2
+110: I,3
+111: J,3
+
+So what we have here are three tables with a total of 20 entries that had to
+be constructed.  That's compared to 64 entries for a single table.  Or
+compared to 16 entries for a Huffman tree (six two entry tables and one four
+entry table).  Assuming that the code ideally represents the probability of
+the symbols, it takes on the average 1.25 lookups per symbol.  That's compared
+to one lookup for the single table, or 1.66 lookups per symbol for the
+Huffman tree.
+
+There, I think that gives you a picture of what's going on.  For inflate, the
+meaning of a particular symbol is often more than just a letter.  It can be a
+byte (a "literal"), or it can be either a length or a distance which
+indicates a base value and a number of bits to fetch after the code that is
+added to the base value.  Or it might be the special end-of-block code.  The
+data structures created in inftrees.c try to encode all that information
+compactly in the tables.
+
+
+Jean-loup Gailly        Mark Adler
+jloup@gzip.org          madler@alumni.caltech.edu
+
+
+References:
+
+[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
+Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
+pp. 337-343.
+
+``DEFLATE Compressed Data Format Specification'' available in
+http://www.ietf.org/rfc/rfc1951.txt
Index: /trunk/minix/lib/zlib-1.2.3/amiga/Makefile.pup
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/amiga/Makefile.pup	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/amiga/Makefile.pup	(revision 9)
@@ -0,0 +1,66 @@
+# Amiga powerUP (TM) Makefile
+# makefile for libpng and SAS C V6.58/7.00 PPC compiler
+# Copyright (C) 1998 by Andreas R. Kleinert
+
+LIBNAME	= libzip.a
+
+CC	= scppc
+CFLAGS	= NOSTKCHK NOSINT OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL \
+	  OPTLOOP OPTRDEP=8 OPTDEP=8 OPTCOMP=8 NOVER
+AR	= ppc-amigaos-ar cr
+RANLIB	= ppc-amigaos-ranlib
+LD	= ppc-amigaos-ld -r
+LDFLAGS	= -o
+LDLIBS	= LIB:scppc.a LIB:end.o
+RM	= delete quiet
+
+OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
+       zutil.o inflate.o infback.o inftrees.o inffast.o
+
+TEST_OBJS = example.o minigzip.o
+
+all: example minigzip
+
+check: test
+test: all
+	example
+	echo hello world | minigzip | minigzip -d
+
+$(LIBNAME): $(OBJS)
+	$(AR) $@ $(OBJS)
+	-$(RANLIB) $@
+
+example: example.o $(LIBNAME)
+	$(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS)
+
+minigzip: minigzip.o $(LIBNAME)
+	$(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS)
+
+mostlyclean: clean
+clean:
+	$(RM) *.o example minigzip $(LIBNAME) foo.gz
+
+zip:
+	zip -ul9 zlib README ChangeLog Makefile Make????.??? Makefile.?? \
+	  descrip.mms *.[ch]
+
+tgz:
+	cd ..; tar cfz zlib/zlib.tgz zlib/README zlib/ChangeLog zlib/Makefile \
+	  zlib/Make????.??? zlib/Makefile.?? zlib/descrip.mms zlib/*.[ch]
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+adler32.o: zlib.h zconf.h
+compress.o: zlib.h zconf.h
+crc32.o: crc32.h zlib.h zconf.h
+deflate.o: deflate.h zutil.h zlib.h zconf.h
+example.o: zlib.h zconf.h
+gzio.o: zutil.h zlib.h zconf.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inftrees.o: zutil.h zlib.h zconf.h inftrees.h
+minigzip.o: zlib.h zconf.h
+trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
+uncompr.o: zlib.h zconf.h
+zutil.o: zutil.h zlib.h zconf.h
Index: /trunk/minix/lib/zlib-1.2.3/amiga/Makefile.sas
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/amiga/Makefile.sas	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/amiga/Makefile.sas	(revision 9)
@@ -0,0 +1,65 @@
+# SMakefile for zlib
+# Modified from the standard UNIX Makefile Copyright Jean-loup Gailly
+# Osma Ahvenlampi <Osma.Ahvenlampi@hut.fi>
+# Amiga, SAS/C 6.56 & Smake
+
+CC=sc
+CFLAGS=OPT
+#CFLAGS=OPT CPU=68030
+#CFLAGS=DEBUG=LINE
+LDFLAGS=LIB z.lib
+
+SCOPTIONS=OPTSCHED OPTINLINE OPTALIAS OPTTIME OPTINLOCAL STRMERGE \
+       NOICONS PARMS=BOTH NOSTACKCHECK UTILLIB NOVERSION ERRORREXX \
+       DEF=POSTINC
+
+OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
+       zutil.o inflate.o infback.o inftrees.o inffast.o
+
+TEST_OBJS = example.o minigzip.o
+
+all: SCOPTIONS example minigzip
+
+check: test
+test: all
+	example
+	echo hello world | minigzip | minigzip -d
+
+install: z.lib
+	copy clone zlib.h zconf.h INCLUDE:
+	copy clone z.lib LIB:
+
+z.lib: $(OBJS)
+	oml z.lib r $(OBJS)
+
+example: example.o z.lib
+	$(CC) $(CFLAGS) LINK TO $@ example.o $(LDFLAGS)
+
+minigzip: minigzip.o z.lib
+	$(CC) $(CFLAGS) LINK TO $@ minigzip.o $(LDFLAGS)
+
+mostlyclean: clean
+clean:
+	-delete force quiet example minigzip *.o z.lib foo.gz *.lnk SCOPTIONS
+
+SCOPTIONS: Makefile.sas
+	copy to $@ <from <
+$(SCOPTIONS)
+<
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+adler32.o: zlib.h zconf.h
+compress.o: zlib.h zconf.h
+crc32.o: crc32.h zlib.h zconf.h
+deflate.o: deflate.h zutil.h zlib.h zconf.h
+example.o: zlib.h zconf.h
+gzio.o: zutil.h zlib.h zconf.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inftrees.o: zutil.h zlib.h zconf.h inftrees.h
+minigzip.o: zlib.h zconf.h
+trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
+uncompr.o: zlib.h zconf.h
+zutil.o: zutil.h zlib.h zconf.h
Index: /trunk/minix/lib/zlib-1.2.3/as400/bndsrc
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/as400/bndsrc	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/as400/bndsrc	(revision 9)
@@ -0,0 +1,132 @@
+STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('ZLIB')
+
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+/*   Version 1.1.3 entry points.                                    */
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+
+/********************************************************************/
+/*   *MODULE      ADLER32      ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("adler32")
+
+/********************************************************************/
+/*   *MODULE      COMPRESS     ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("compress")
+  EXPORT SYMBOL("compress2")
+
+/********************************************************************/
+/*   *MODULE      CRC32        ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("crc32")
+  EXPORT SYMBOL("get_crc_table")
+
+/********************************************************************/
+/*   *MODULE      DEFLATE      ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("deflate")
+  EXPORT SYMBOL("deflateEnd")
+  EXPORT SYMBOL("deflateSetDictionary")
+  EXPORT SYMBOL("deflateCopy")
+  EXPORT SYMBOL("deflateReset")
+  EXPORT SYMBOL("deflateParams")
+  EXPORT SYMBOL("deflatePrime")
+  EXPORT SYMBOL("deflateInit_")
+  EXPORT SYMBOL("deflateInit2_")
+
+/********************************************************************/
+/*   *MODULE      GZIO         ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("gzopen")
+  EXPORT SYMBOL("gzdopen")
+  EXPORT SYMBOL("gzsetparams")
+  EXPORT SYMBOL("gzread")
+  EXPORT SYMBOL("gzwrite")
+  EXPORT SYMBOL("gzprintf")
+  EXPORT SYMBOL("gzputs")
+  EXPORT SYMBOL("gzgets")
+  EXPORT SYMBOL("gzputc")
+  EXPORT SYMBOL("gzgetc")
+  EXPORT SYMBOL("gzflush")
+  EXPORT SYMBOL("gzseek")
+  EXPORT SYMBOL("gzrewind")
+  EXPORT SYMBOL("gztell")
+  EXPORT SYMBOL("gzeof")
+  EXPORT SYMBOL("gzclose")
+  EXPORT SYMBOL("gzerror")
+
+/********************************************************************/
+/*   *MODULE      INFLATE      ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("inflate")
+  EXPORT SYMBOL("inflateEnd")
+  EXPORT SYMBOL("inflateSetDictionary")
+  EXPORT SYMBOL("inflateSync")
+  EXPORT SYMBOL("inflateReset")
+  EXPORT SYMBOL("inflateInit_")
+  EXPORT SYMBOL("inflateInit2_")
+  EXPORT SYMBOL("inflateSyncPoint")
+
+/********************************************************************/
+/*   *MODULE      UNCOMPR      ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("uncompress")
+
+/********************************************************************/
+/*   *MODULE      ZUTIL        ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("zlibVersion")
+  EXPORT SYMBOL("zError")
+
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+/*   Version 1.2.1 additional entry points.                         */
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+
+/********************************************************************/
+/*   *MODULE      COMPRESS     ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("compressBound")
+
+/********************************************************************/
+/*   *MODULE      DEFLATE      ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("deflateBound")
+
+/********************************************************************/
+/*   *MODULE      GZIO         ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("gzungetc")
+  EXPORT SYMBOL("gzclearerr")
+
+/********************************************************************/
+/*   *MODULE      INFBACK      ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("inflateBack")
+  EXPORT SYMBOL("inflateBackEnd")
+  EXPORT SYMBOL("inflateBackInit_")
+
+/********************************************************************/
+/*   *MODULE      INFLATE      ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("inflateCopy")
+
+/********************************************************************/
+/*   *MODULE      ZUTIL        ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("zlibCompileFlags")
+
+ENDPGMEXP
Index: /trunk/minix/lib/zlib-1.2.3/as400/compile.clp
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/as400/compile.clp	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/as400/compile.clp	(revision 9)
@@ -0,0 +1,123 @@
+/******************************************************************************/
+/*                                                                            */
+/*  ZLIB                                                                      */
+/*                                                                            */
+/*    Compile sources into modules and link them into a service program.      */
+/*                                                                            */
+/******************************************************************************/
+
+             PGM
+
+/*      Configuration adjustable parameters.                                  */
+
+             DCL        VAR(&SRCLIB) TYPE(*CHAR) LEN(10) +
+                          VALUE('ZLIB')                         /* Source library. */
+             DCL        VAR(&SRCFILE) TYPE(*CHAR) LEN(10) +
+                          VALUE('SOURCES')                      /* Source member file. */
+             DCL        VAR(&CTLFILE) TYPE(*CHAR) LEN(10) +
+                          VALUE('TOOLS')                        /* Control member file. */
+
+             DCL        VAR(&MODLIB) TYPE(*CHAR) LEN(10) +
+                          VALUE('ZLIB')                         /* Module library. */
+
+             DCL        VAR(&SRVLIB) TYPE(*CHAR) LEN(10) +
+                          VALUE('LGPL')                         /* Service program library. */
+
+             DCL        VAR(&CFLAGS) TYPE(*CHAR) +
+                          VALUE('OPTIMIZE(40)')                 /* Compile options. */
+
+
+/*      Working storage.                                                      */
+
+             DCL        VAR(&CMDLEN) TYPE(*DEC) LEN(15 5) VALUE(300)    /* Command length. */
+             DCL        VAR(&CMD) TYPE(*CHAR) LEN(512)
+
+
+/*      Compile sources into modules.                                         */
+
+             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
+                        '/ADLER32)               SRCFILE(' *TCAT               +
+                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
+                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
+                        '/COMPRESS)              SRCFILE(' *TCAT               +
+                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
+                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
+                        '/CRC32)                 SRCFILE(' *TCAT               +
+                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
+                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
+                        '/DEFLATE)               SRCFILE(' *TCAT               +
+                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
+                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
+                        '/GZIO)                  SRCFILE(' *TCAT               +
+                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
+                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
+                        '/INFBACK)               SRCFILE(' *TCAT               +
+                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
+                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
+                        '/INFFAST)               SRCFILE(' *TCAT               +
+                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
+                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
+                        '/INFLATE)               SRCFILE(' *TCAT               +
+                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
+                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
+                        '/INFTREES)              SRCFILE(' *TCAT               +
+                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
+                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
+                        '/TREES)                 SRCFILE(' *TCAT               +
+                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
+                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
+                        '/UNCOMPR)               SRCFILE(' *TCAT               +
+                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
+                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
+                        '/ZUTIL)                 SRCFILE(' *TCAT               +
+                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
+                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+
+/*      Link modules into a service program.                                  */
+
+             CRTSRVPGM  SRVPGM(&SRVLIB/ZLIB) +
+                          MODULE(&MODLIB/ADLER32     &MODLIB/COMPRESS    +
+                                 &MODLIB/CRC32       &MODLIB/DEFLATE     +
+                                 &MODLIB/GZIO        &MODLIB/INFBACK     +
+                                 &MODLIB/INFFAST     &MODLIB/INFLATE     +
+                                 &MODLIB/INFTREES    &MODLIB/TREES       +
+                                 &MODLIB/UNCOMPR     &MODLIB/ZUTIL)      +
+                          SRCFILE(&SRCLIB/&CTLFILE) SRCMBR(BNDSRC) +
+                          TEXT('ZLIB 1.2.3') TGTRLS(V4R4M0)
+
+             ENDPGM
Index: /trunk/minix/lib/zlib-1.2.3/as400/readme.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/as400/readme.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/as400/readme.txt	(revision 9)
@@ -0,0 +1,111 @@
+        ZLIB version 1.2.3 for AS400 installation instructions
+
+I) From an AS400 *SAVF file:
+
+1)      Unpacking archive to an AS400 save file
+
+On the AS400:
+
+_       Create the ZLIB AS400 library:
+
+        CRTLIB LIB(ZLIB) TYPE(PROD) TEXT('ZLIB compression API library')
+
+_       Create a work save file, for example:
+
+                CRTSAVF FILE(ZLIB/ZLIBSAVF)
+
+On a PC connected to the target AS400:
+
+_       Unpack the save file image to a PC file "ZLIBSAVF"
+_       Upload this file into the save file on the AS400, for example
+                using ftp in BINARY mode.
+
+
+2)      Populating the ZLIB AS400 source library
+
+On the AS400:
+
+_       Extract the saved objects into the ZLIB AS400 library using:
+
+RSTOBJ OBJ(*ALL) SAVLIB(ZLIB) DEV(*SAVF) SAVF(ZLIB/ZLIBSAVF) RSTLIB(ZLIB)
+
+
+3)      Customize installation:
+
+_       Edit CL member ZLIB/TOOLS(COMPILE) and change parameters if needed,
+                according to the comments.
+
+_       Compile this member with:
+
+        CRTCLPGM PGM(ZLIB/COMPILE) SRCFILE(ZLIB/TOOLS) SRCMBR(COMPILE)
+
+
+4)      Compile and generate the service program:
+
+_       This can now be done by executing:
+
+        CALL PGM(ZLIB/COMPILE)
+
+
+
+II) From the original source distribution:
+
+1)      On the AS400, create the source library:
+
+        CRTLIB LIB(ZLIB) TYPE(PROD) TEXT('ZLIB compression API library')
+
+2)      Create the source files:
+
+        CRTSRCPF FILE(ZLIB/SOURCES) RCDLEN(112) TEXT('ZLIB library modules')
+        CRTSRCPF FILE(ZLIB/H)       RCDLEN(112) TEXT('ZLIB library includes')
+        CRTSRCPF FILE(ZLIB/TOOLS)   RCDLEN(112) TEXT('ZLIB library control utilities')
+
+3)      From the machine hosting the distribution files, upload them (with
+                FTP in text mode, for example) according to the following table:
+
+    Original    AS400   AS400    AS400 AS400
+    file        file    member   type  description
+                SOURCES                Original ZLIB C subprogram sources
+    adler32.c           ADLER32  C     ZLIB - Compute the Adler-32 checksum of a dta strm
+    compress.c          COMPRESS C     ZLIB - Compress a memory buffer
+    crc32.c             CRC32    C     ZLIB - Compute the CRC-32 of a data stream
+    deflate.c           DEFLATE  C     ZLIB - Compress data using the deflation algorithm
+    gzio.c              GZIO     C     ZLIB - IO on .gz files
+    infback.c           INFBACK  C     ZLIB - Inflate using a callback interface
+    inffast.c           INFFAST  C     ZLIB - Fast proc. literals & length/distance pairs
+    inflate.c           INFLATE  C     ZLIB - Interface to inflate modules
+    inftrees.c          INFTREES C     ZLIB - Generate Huffman trees for efficient decode
+    trees.c             TREES    C     ZLIB - Output deflated data using Huffman coding
+    uncompr.c           UNCOMPR  C     ZLIB - Decompress a memory buffer
+    zutil.c             ZUTIL    C     ZLIB - Target dependent utility functions
+                H                      Original ZLIB C and ILE/RPG include files
+    crc32.h             CRC32    C     ZLIB - CRC32 tables
+    deflate.h           DEFLATE  C     ZLIB - Internal compression state
+    inffast.h           INFFAST  C     ZLIB - Header to use inffast.c
+    inffixed.h          INFFIXED C     ZLIB - Table for decoding fixed codes
+    inflate.h           INFLATE  C     ZLIB - Internal inflate state definitions
+    inftrees.h          INFTREES C     ZLIB - Header to use inftrees.c
+    trees.h             TREES    C     ZLIB - Created automatically with -DGEN_TREES_H
+    zconf.h             ZCONF    C     ZLIB - Compression library configuration
+    zlib.h              ZLIB     C     ZLIB - Compression library C user interface
+    as400/zlib.inc      ZLIB.INC RPGLE ZLIB - Compression library ILE RPG user interface
+    zutil.h             ZUTIL    C     ZLIB - Internal interface and configuration
+                TOOLS                  Building source software & AS/400 README
+    as400/bndsrc        BNDSRC         Entry point exportation list
+    as400/compile.clp   COMPILE  CLP   Compile sources & generate service program
+    as400/readme.txt    README   TXT   Installation instructions
+
+4)      Continue as in I)3).
+
+
+
+
+Notes:  For AS400 ILE RPG programmers, a /copy member defining the ZLIB
+                API prototypes for ILE RPG can be found in ZLIB/H(ZLIB.INC).
+                Please read comments in this member for more information.
+
+        Remember that most foreign textual data are ASCII coded: this
+                implementation does not handle conversion from/to ASCII, so
+                text data code conversions must be done explicitely.
+
+        Always open zipped files in binary mode.
Index: /trunk/minix/lib/zlib-1.2.3/as400/zlib.inc
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/as400/zlib.inc	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/as400/zlib.inc	(revision 9)
@@ -0,0 +1,331 @@
+      *  ZLIB.INC - Interface to the general purpose compression library
+      *
+      *  ILE RPG400 version by Patrick Monnerat, DATASPHERE.
+      *  Version 1.2.3
+      *
+      *
+      *  WARNING:
+      *     Procedures inflateInit(), inflateInit2(), deflateInit(),
+      *         deflateInit2() and inflateBackInit() need to be called with
+      *         two additional arguments:
+      *         the package version string and the stream control structure.
+      *         size. This is needed because RPG lacks some macro feature.
+      *         Call these procedures as:
+      *             inflateInit(...: ZLIB_VERSION: %size(z_stream))
+      *
+      /if not defined(ZLIB_H_)
+      /define ZLIB_H_
+      *
+      **************************************************************************
+      *                               Constants
+      **************************************************************************
+      *
+      *  Versioning information.
+      *
+     D ZLIB_VERSION    C                   '1.2.3'
+     D ZLIB_VERNUM     C                   X'1230'
+      *
+      *  Other equates.
+      *
+     D Z_NO_FLUSH      C                   0
+     D Z_SYNC_FLUSH    C                   2
+     D Z_FULL_FLUSH    C                   3
+     D Z_FINISH        C                   4
+     D Z_BLOCK         C                   5
+      *
+     D Z_OK            C                   0
+     D Z_STREAM_END    C                   1
+     D Z_NEED_DICT     C                   2
+     D Z_ERRNO         C                   -1
+     D Z_STREAM_ERROR  C                   -2
+     D Z_DATA_ERROR    C                   -3
+     D Z_MEM_ERROR     C                   -4
+     D Z_BUF_ERROR     C                   -5
+     DZ_VERSION_ERROR  C                   -6
+      *
+     D Z_NO_COMPRESSION...
+     D                 C                   0
+     D Z_BEST_SPEED    C                   1
+     D Z_BEST_COMPRESSION...
+     D                 C                   9
+     D Z_DEFAULT_COMPRESSION...
+     D                 C                   -1
+      *
+     D Z_FILTERED      C                   1
+     D Z_HUFFMAN_ONLY  C                   2
+     D Z_RLE           C                   3
+     D Z_DEFAULT_STRATEGY...
+     D                 C                   0
+      *
+     D Z_BINARY        C                   0
+     D Z_ASCII         C                   1
+     D Z_UNKNOWN       C                   2
+      *
+     D Z_DEFLATED      C                   8
+      *
+     D Z_NULL          C                   0
+      *
+      **************************************************************************
+      *                                 Types
+      **************************************************************************
+      *
+     D z_streamp       S               *                                        Stream struct ptr
+     D gzFile          S               *                                        File pointer
+     D z_off_t         S             10i 0                                      Stream offsets
+      *
+      **************************************************************************
+      *                               Structures
+      **************************************************************************
+      *
+      *  The GZIP encode/decode stream support structure.
+      *
+     D z_stream        DS                  align based(z_streamp)
+     D  zs_next_in                     *                                        Next input byte
+     D  zs_avail_in                  10U 0                                      Byte cnt at next_in
+     D  zs_total_in                  10U 0                                      Total bytes read
+     D  zs_next_out                    *                                        Output buffer ptr
+     D  zs_avail_out                 10U 0                                      Room left @ next_out
+     D  zs_total_out                 10U 0                                      Total bytes written
+     D  zs_msg                         *                                        Last errmsg or null
+     D  zs_state                       *                                        Internal state
+     D  zs_zalloc                      *   procptr                              Int. state allocator
+     D  zs_free                        *   procptr                              Int. state dealloc.
+     D  zs_opaque                      *                                        Private alloc. data
+     D  zs_data_type                 10i 0                                      ASC/BIN best guess
+     D  zs_adler                     10u 0                                      Uncompr. adler32 val
+     D                               10U 0                                      Reserved
+     D                               10U 0                                      Ptr. alignment
+      *
+      **************************************************************************
+      *                     Utility function prototypes
+      **************************************************************************
+      *
+     D compress        PR            10I 0 extproc('compress')
+     D  dest                      32767    options(*varsize)                    Destination buffer
+     D  destLen                      10U 0                                      Destination length
+     D  source                    32767    const options(*varsize)              Source buffer
+     D  sourceLen                    10u 0 value                                Source length
+      *
+     D compress2       PR            10I 0 extproc('compress2')
+     D  dest                      32767    options(*varsize)                    Destination buffer
+     D  destLen                      10U 0                                      Destination length
+     D  source                    32767    const options(*varsize)              Source buffer
+     D  sourceLen                    10U 0 value                                Source length
+     D  level                        10I 0 value                                Compression level
+      *
+     D compressBound   PR            10U 0 extproc('compressBound')
+     D  sourceLen                    10U 0 value
+      *
+     D uncompress      PR            10I 0 extproc('uncompress')
+     D  dest                      32767    options(*varsize)                    Destination buffer
+     D  destLen                      10U 0                                      Destination length
+     D  source                    32767    const options(*varsize)              Source buffer
+     D  sourceLen                    10U 0 value                                Source length
+      *
+     D gzopen          PR                  extproc('gzopen')
+     D                                     like(gzFile)
+     D  path                           *   value options(*string)               File pathname
+     D  mode                           *   value options(*string)               Open mode
+      *
+     D gzdopen         PR                  extproc('gzdopen')
+     D                                     like(gzFile)
+     D  fd                           10i 0 value                                File descriptor
+     D  mode                           *   value options(*string)               Open mode
+      *
+     D gzsetparams     PR            10I 0 extproc('gzsetparams')
+     D  file                               value like(gzFile)                   File pointer
+     D  level                        10I 0 value
+     D  strategy                     10i 0 value
+      *
+     D gzread          PR            10I 0 extproc('gzread')
+     D  file                               value like(gzFile)                   File pointer
+     D  buf                       32767    options(*varsize)                    Buffer
+     D  len                          10u 0 value                                Buffer length
+      *
+     D gzwrite         PR            10I 0 extproc('gzwrite')
+     D  file                               value like(gzFile)                   File pointer
+     D  buf                       32767    const options(*varsize)              Buffer
+     D  len                          10u 0 value                                Buffer length
+      *
+     D gzputs          PR            10I 0 extproc('gzputs')
+     D  file                               value like(gzFile)                   File pointer
+     D  s                              *   value options(*string)               String to output
+      *
+     D gzgets          PR              *   extproc('gzgets')
+     D  file                               value like(gzFile)                   File pointer
+     D  buf                       32767    options(*varsize)                    Read buffer
+     D  len                          10i 0 value                                Buffer length
+      *
+     D gzflush         PR            10i 0 extproc('gzflush')
+     D  file                               value like(gzFile)                   File pointer
+     D  flush                        10I 0 value                                Type of flush
+      *
+     D gzseek          PR                  extproc('gzseek')
+     D                                     like(z_off_t)
+     D  file                               value like(gzFile)                   File pointer
+     D  offset                             value like(z_off_t)                  Offset
+     D  whence                       10i 0 value                                Origin
+      *
+     D gzrewind        PR            10i 0 extproc('gzrewind')
+     D  file                               value like(gzFile)                   File pointer
+      *
+     D gztell          PR                  extproc('gztell')
+     D                                     like(z_off_t)
+     D  file                               value like(gzFile)                   File pointer
+      *
+     D gzeof           PR            10i 0 extproc('gzeof')
+     D  file                               value like(gzFile)                   File pointer
+      *
+     D gzclose         PR            10i 0 extproc('gzclose')
+     D  file                               value like(gzFile)                   File pointer
+      *
+     D gzerror         PR              *   extproc('gzerror')                   Error string
+     D  file                               value like(gzFile)                   File pointer
+     D  errnum                       10I 0                                      Error code
+      *
+     D gzclearerr      PR                  extproc('gzclearerr')
+     D  file                               value like(gzFile)                   File pointer
+      *
+      **************************************************************************
+      *                        Basic function prototypes
+      **************************************************************************
+      *
+     D zlibVersion     PR              *   extproc('zlibVersion')               Version string
+      *
+     D deflateInit     PR            10I 0 extproc('deflateInit_')              Init. compression
+     D  strm                               like(z_stream)                       Compression stream
+     D  level                        10I 0 value                                Compression level
+     D  version                        *   value options(*string)               Version string
+     D  stream_size                  10i 0 value                                Stream struct. size
+      *
+     D deflate         PR            10I 0 extproc('deflate')                   Compress data
+     D  strm                               like(z_stream)                       Compression stream
+     D  flush                        10I 0 value                                Flush type required
+      *
+     D deflateEnd      PR            10I 0 extproc('deflateEnd')                Termin. compression
+     D  strm                               like(z_stream)                       Compression stream
+      *
+     D inflateInit     PR            10I 0 extproc('inflateInit_')              Init. expansion
+     D  strm                               like(z_stream)                       Expansion stream
+     D  version                        *   value options(*string)               Version string
+     D  stream_size                  10i 0 value                                Stream struct. size
+      *
+     D inflate         PR            10I 0 extproc('inflate')                   Expand data
+     D  strm                               like(z_stream)                       Expansion stream
+     D  flush                        10I 0 value                                Flush type required
+      *
+     D inflateEnd      PR            10I 0 extproc('inflateEnd')                Termin. expansion
+     D  strm                               like(z_stream)                       Expansion stream
+      *
+      **************************************************************************
+      *                        Advanced function prototypes
+      **************************************************************************
+      *
+     D deflateInit2    PR            10I 0 extproc('deflateInit2_')             Init. compression
+     D  strm                               like(z_stream)                       Compression stream
+     D  level                        10I 0 value                                Compression level
+     D  method                       10I 0 value                                Compression method
+     D  windowBits                   10I 0 value                                log2(window size)
+     D  memLevel                     10I 0 value                                Mem/cmpress tradeoff
+     D  strategy                     10I 0 value                                Compression stategy
+     D  version                        *   value options(*string)               Version string
+     D  stream_size                  10i 0 value                                Stream struct. size
+      *
+     D deflateSetDictionary...
+     D                 PR            10I 0 extproc('deflateSetDictionary')      Init. dictionary
+     D  strm                               like(z_stream)                       Compression stream
+     D  dictionary                32767    const options(*varsize)              Dictionary bytes
+     D  dictLength                   10U 0 value                                Dictionary length
+      *
+     D deflateCopy     PR            10I 0 extproc('deflateCopy')               Compress strm 2 strm
+     D  dest                               like(z_stream)                       Destination stream
+     D  source                             like(z_stream)                       Source stream
+      *
+     D deflateReset    PR            10I 0 extproc('deflateReset')              End and init. stream
+     D  strm                               like(z_stream)                       Compression stream
+      *
+     D deflateParams   PR            10I 0 extproc('deflateParams')             Change level & strat
+     D  strm                               like(z_stream)                       Compression stream
+     D  level                        10I 0 value                                Compression level
+     D  strategy                     10I 0 value                                Compression stategy
+      *
+     D deflateBound    PR            10U 0 extproc('deflateBound')              Change level & strat
+     D  strm                               like(z_stream)                       Compression stream
+     D  sourcelen                    10U 0 value                                Compression level
+      *
+     D deflatePrime    PR            10I 0 extproc('deflatePrime')              Change level & strat
+     D  strm                               like(z_stream)                       Compression stream
+     D  bits                         10I 0 value                                Number of bits to insert
+     D  value                        10I 0 value                                Bits to insert
+      *
+     D inflateInit2    PR            10I 0 extproc('inflateInit2_')             Init. expansion
+     D  strm                               like(z_stream)                       Expansion stream
+     D  windowBits                   10I 0 value                                log2(window size)
+     D  version                        *   value options(*string)               Version string
+     D  stream_size                  10i 0 value                                Stream struct. size
+      *
+     D inflateSetDictionary...
+     D                 PR            10I 0 extproc('inflateSetDictionary')      Init. dictionary
+     D  strm                               like(z_stream)                       Expansion stream
+     D  dictionary                32767    const options(*varsize)              Dictionary bytes
+     D  dictLength                   10U 0 value                                Dictionary length
+      *
+     D inflateSync     PR            10I 0 extproc('inflateSync')               Sync. expansion
+     D  strm                               like(z_stream)                       Expansion stream
+      *
+     D inflateCopy     PR            10I 0 extproc('inflateCopy')
+     D  dest                               like(z_stream)                       Destination stream
+     D  source                             like(z_stream)                       Source stream
+      *
+     D inflateReset    PR            10I 0 extproc('inflateReset')              End and init. stream
+     D  strm                               like(z_stream)                       Expansion stream
+      *
+     D inflateBackInit...
+     D                 PR            10I 0 extproc('inflateBackInit_')
+     D  strm                               like(z_stream)                       Expansion stream
+     D  windowBits                   10I 0 value                                Log2(buffer size)
+     D  window                    32767    options(*varsize)                    Buffer
+     D  version                        *   value options(*string)               Version string
+     D  stream_size                  10i 0 value                                Stream struct. size
+      *
+     D inflateBack     PR            10I 0 extproc('inflateBack')
+     D  strm                               like(z_stream)                       Expansion stream
+     D  in                             *   value procptr                        Input function
+     D  in_desc                        *   value                                Input descriptor
+     D  out                            *   value procptr                        Output function
+     D  out_desc                       *   value                                Output descriptor
+      *
+     D inflateBackEnd  PR            10I 0 extproc('inflateBackEnd')
+     D  strm                               like(z_stream)                       Expansion stream
+      *
+     D zlibCompileFlags...
+     D                 PR            10U 0 extproc('zlibCompileFlags')
+      *
+      **************************************************************************
+      *                        Checksum function prototypes
+      **************************************************************************
+      *
+     D adler32         PR            10U 0 extproc('adler32')                   New checksum
+     D  adler                        10U 0 value                                Old checksum
+     D  buf                       32767    const options(*varsize)              Bytes to accumulate
+     D  len                          10U 0 value                                Buffer length
+      *
+     D crc32           PR            10U 0 extproc('crc32')                     New checksum
+     D  crc                          10U 0 value                                Old checksum
+     D  buf                       32767    const options(*varsize)              Bytes to accumulate
+     D  len                          10U 0 value                                Buffer length
+      *
+      **************************************************************************
+      *                     Miscellaneous function prototypes
+      **************************************************************************
+      *
+     D zError          PR              *   extproc('zError')                    Error string
+     D  err                          10I 0 value                                Error code
+      *
+     D inflateSyncPoint...
+     D                 PR            10I 0 extproc('inflateSyncPoint')
+     D  strm                               like(z_stream)                       Expansion stream
+      *
+     D get_crc_table   PR              *   extproc('get_crc_table')             Ptr to ulongs
+      *
+      /endif
Index: /trunk/minix/lib/zlib-1.2.3/compress.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/compress.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/compress.c	(revision 9)
@@ -0,0 +1,79 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: compress.c,v 1.1 2005/09/23 22:39:00 beng Exp $ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least 0.1% larger than sourceLen plus
+   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+    int level;
+{
+    z_stream stream;
+    int err;
+
+    stream.next_in = (Bytef*)source;
+    stream.avail_in = (uInt)sourceLen;
+#ifdef MAXSEG_64K
+    /* Check for source > 64K on 16-bit machine: */
+    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+#endif
+    stream.next_out = dest;
+    stream.avail_out = (uInt)*destLen;
+    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+    stream.zalloc = (alloc_func)0;
+    stream.zfree = (free_func)0;
+    stream.opaque = (voidpf)0;
+
+    err = deflateInit(&stream, level);
+    if (err != Z_OK) return err;
+
+    err = deflate(&stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        deflateEnd(&stream);
+        return err == Z_OK ? Z_BUF_ERROR : err;
+    }
+    *destLen = stream.total_out;
+
+    err = deflateEnd(&stream);
+    return err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress (dest, destLen, source, sourceLen)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+{
+    return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
+
+/* ===========================================================================
+     If the default memLevel or windowBits for deflateInit() is changed, then
+   this function needs to be updated.
+ */
+uLong ZEXPORT compressBound (sourceLen)
+    uLong sourceLen;
+{
+    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
+}
Index: /trunk/minix/lib/zlib-1.2.3/configure
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/configure	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/configure	(revision 9)
@@ -0,0 +1,459 @@
+#!/bin/sh
+# configure script for zlib. This script is needed only if
+# you wish to build a shared library and your system supports them,
+# of if you need special compiler, flags or install directory.
+# Otherwise, you can just use directly "make test; make install"
+#
+# To create a shared library, use "configure --shared"; by default a static
+# library is created. If the primitive shared library support provided here
+# does not work, use ftp://prep.ai.mit.edu/pub/gnu/libtool-*.tar.gz
+#
+# To impose specific compiler or flags or install directory, use for example:
+#    prefix=$HOME CC=cc CFLAGS="-O4" ./configure
+# or for csh/tcsh users:
+#    (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure)
+# LDSHARED is the command to be used to create a shared library
+
+# Incorrect settings of CC or CFLAGS may prevent creating a shared library.
+# If you have problems, try without defining CC and CFLAGS before reporting
+# an error.
+
+LIBS=libz.a
+LDFLAGS="-L. ${LIBS}"
+VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`
+VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < zlib.h`
+VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < zlib.h`
+AR=${AR-"ar rc"}
+RANLIB=${RANLIB-"ranlib"}
+prefix=${prefix-/usr/local}
+exec_prefix=${exec_prefix-'${prefix}'}
+libdir=${libdir-'${exec_prefix}/lib'}
+includedir=${includedir-'${prefix}/include'}
+mandir=${mandir-'${prefix}/share/man'}
+shared_ext='.so'
+shared=0
+gcc=0
+old_cc="$CC"
+old_cflags="$CFLAGS"
+
+while test $# -ge 1
+do
+case "$1" in
+    -h* | --h*)
+      echo 'usage:'
+      echo '  configure [--shared] [--prefix=PREFIX]  [--exec_prefix=EXPREFIX]'
+      echo '     [--libdir=LIBDIR] [--includedir=INCLUDEDIR]'
+        exit 0;;
+    -p*=* | --p*=*) prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
+    -e*=* | --e*=*) exec_prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
+    -l*=* | --libdir=*) libdir=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
+    -i*=* | --includedir=*) includedir=`echo $1 | sed 's/[-a-z_]*=//'`;shift;;
+    -p* | --p*) prefix="$2"; shift; shift;;
+    -e* | --e*) exec_prefix="$2"; shift; shift;;
+    -l* | --l*) libdir="$2"; shift; shift;;
+    -i* | --i*) includedir="$2"; shift; shift;;
+    -s* | --s*) shared=1; shift;;
+    *) echo "unknown option: $1"; echo "$0 --help for help"; exit 1;;
+    esac
+done
+
+test=ztest$$
+cat > $test.c <<EOF
+extern int getchar();
+int hello() {return getchar();}
+EOF
+
+test -z "$CC" && echo Checking for gcc...
+cc=${CC-gcc}
+cflags=${CFLAGS-"-O3"}
+# to force the asm version use: CFLAGS="-O3 -DASMV" ./configure
+case "$cc" in
+  *gcc*) gcc=1;;
+esac
+
+if test "$gcc" -eq 1 && ($cc -c $cflags $test.c) 2>/dev/null; then
+  CC="$cc"
+  SFLAGS=${CFLAGS-"-fPIC -O3"}
+  CFLAGS="$cflags"
+  case `(uname -s || echo unknown) 2>/dev/null` in
+  Linux | linux | GNU | GNU/*) LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1"};;
+  CYGWIN* | Cygwin* | cygwin* | OS/2* )
+             EXE='.exe';;
+  QNX*)  # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4
+         # (alain.bonnefoy@icbt.com)
+                 LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"};;
+  HP-UX*)
+         LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"}
+         case `(uname -m || echo unknown) 2>/dev/null` in
+         ia64)
+                 shared_ext='.so'
+                 SHAREDLIB='libz.so';;
+         *)
+                 shared_ext='.sl'
+                 SHAREDLIB='libz.sl';;
+         esac;;
+  Darwin*)   shared_ext='.dylib'
+             SHAREDLIB=libz$shared_ext
+             SHAREDLIBV=libz.$VER$shared_ext
+             SHAREDLIBM=libz.$VER1$shared_ext
+             LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER"};;
+  *)             LDSHARED=${LDSHARED-"$cc -shared"};;
+  esac
+else
+  # find system name and corresponding cc options
+  CC=${CC-cc}
+  case `(uname -sr || echo unknown) 2>/dev/null` in
+  HP-UX*)    SFLAGS=${CFLAGS-"-O +z"}
+             CFLAGS=${CFLAGS-"-O"}
+#            LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"}
+             LDSHARED=${LDSHARED-"ld -b"}
+         case `(uname -m || echo unknown) 2>/dev/null` in
+         ia64)
+             shared_ext='.so'
+             SHAREDLIB='libz.so';;
+         *)
+             shared_ext='.sl'
+             SHAREDLIB='libz.sl';;
+         esac;;
+  IRIX*)     SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."}
+             CFLAGS=${CFLAGS-"-ansi -O2"}
+             LDSHARED=${LDSHARED-"cc -shared"};;
+  OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"}
+             CFLAGS=${CFLAGS-"-O -std1"}
+             LDSHARED=${LDSHARED-"cc -shared  -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"};;
+  OSF1*)     SFLAGS=${CFLAGS-"-O -std1"}
+             CFLAGS=${CFLAGS-"-O -std1"}
+             LDSHARED=${LDSHARED-"cc -shared"};;
+  QNX*)      SFLAGS=${CFLAGS-"-4 -O"}
+             CFLAGS=${CFLAGS-"-4 -O"}
+             LDSHARED=${LDSHARED-"cc"}
+             RANLIB=${RANLIB-"true"}
+             AR="cc -A";;
+  SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "}
+             CFLAGS=${CFLAGS-"-O3"}
+             LDSHARED=${LDSHARED-"cc -dy -KPIC -G"};;
+  SunOS\ 5*) SFLAGS=${CFLAGS-"-fast -xcg89 -KPIC -R."}
+             CFLAGS=${CFLAGS-"-fast -xcg89"}
+             LDSHARED=${LDSHARED-"cc -G"};;
+  SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"}
+             CFLAGS=${CFLAGS-"-O2"}
+             LDSHARED=${LDSHARED-"ld"};;
+  SunStudio\ 9*) SFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"}
+             CFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xtarget=ultra3 -xarch=v9b"}
+             LDSHARED=${LDSHARED-"cc -xarch=v9b"};;
+  UNIX_System_V\ 4.2.0)
+             SFLAGS=${CFLAGS-"-KPIC -O"}
+             CFLAGS=${CFLAGS-"-O"}
+             LDSHARED=${LDSHARED-"cc -G"};;
+  UNIX_SV\ 4.2MP)
+             SFLAGS=${CFLAGS-"-Kconform_pic -O"}
+             CFLAGS=${CFLAGS-"-O"}
+             LDSHARED=${LDSHARED-"cc -G"};;
+  OpenUNIX\ 5)
+             SFLAGS=${CFLAGS-"-KPIC -O"}
+             CFLAGS=${CFLAGS-"-O"}
+             LDSHARED=${LDSHARED-"cc -G"};;
+  AIX*)  # Courtesy of dbakker@arrayasolutions.com
+             SFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
+             CFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
+             LDSHARED=${LDSHARED-"xlc -G"};;
+  # send working options for other systems to support@gzip.org
+  *)         SFLAGS=${CFLAGS-"-O"}
+             CFLAGS=${CFLAGS-"-O"}
+             LDSHARED=${LDSHARED-"cc -shared"};;
+  esac
+fi
+
+SHAREDLIB=${SHAREDLIB-"libz$shared_ext"}
+SHAREDLIBV=${SHAREDLIBV-"libz$shared_ext.$VER"}
+SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"}
+
+if test $shared -eq 1; then
+  echo Checking for shared library support...
+  # we must test in two steps (cc then ld), required at least on SunOS 4.x
+  if test "`($CC -c $SFLAGS $test.c) 2>&1`" = "" &&
+     test "`($LDSHARED -o $test$shared_ext $test.o) 2>&1`" = ""; then
+    CFLAGS="$SFLAGS"
+    LIBS="$SHAREDLIBV"
+    echo Building shared library $SHAREDLIBV with $CC.
+  elif test -z "$old_cc" -a -z "$old_cflags"; then
+    echo No shared library support.
+    shared=0;
+  else
+    echo 'No shared library support; try without defining CC and CFLAGS'
+    shared=0;
+  fi
+fi
+if test $shared -eq 0; then
+  LDSHARED="$CC"
+  echo Building static library $LIBS version $VER with $CC.
+else
+  LDFLAGS="-L. ${SHAREDLIBV}"
+fi
+
+cat > $test.c <<EOF
+#include <unistd.h>
+int main() { return 0; }
+EOF
+if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+  sed < zconf.in.h "/HAVE_UNISTD_H/s%0%1%" > zconf.h
+  echo "Checking for unistd.h... Yes."
+else
+  cp -p zconf.in.h zconf.h
+  echo "Checking for unistd.h... No."
+fi
+
+cat > $test.c <<EOF
+#include <stdio.h>
+#include <stdarg.h>
+#include "zconf.h"
+
+int main()
+{
+#ifndef STDC
+  choke me
+#endif
+
+  return 0;
+}
+EOF
+
+if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+  echo "Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf()"
+
+  cat > $test.c <<EOF
+#include <stdio.h>
+#include <stdarg.h>
+
+int mytest(char *fmt, ...)
+{
+  char buf[20];
+  va_list ap;
+
+  va_start(ap, fmt);
+  vsnprintf(buf, sizeof(buf), fmt, ap);
+  va_end(ap);
+  return 0;
+}
+
+int main()
+{
+  return (mytest("Hello%d\n", 1));
+}
+EOF
+
+  if test "`($CC $CFLAGS -o $test $test.c) 2>&1`" = ""; then
+    echo "Checking for vsnprintf() in stdio.h... Yes."
+
+    cat >$test.c <<EOF
+#include <stdio.h>
+#include <stdarg.h>
+
+int mytest(char *fmt, ...)
+{
+  int n;
+  char buf[20];
+  va_list ap;
+
+  va_start(ap, fmt);
+  n = vsnprintf(buf, sizeof(buf), fmt, ap);
+  va_end(ap);
+  return n;
+}
+
+int main()
+{
+  return (mytest("Hello%d\n", 1));
+}
+EOF
+
+    if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+      echo "Checking for return value of vsnprintf()... Yes."
+    else
+      CFLAGS="$CFLAGS -DHAS_vsnprintf_void"
+      echo "Checking for return value of vsnprintf()... No."
+      echo "  WARNING: apparently vsnprintf() does not return a value. zlib"
+      echo "  can build but will be open to possible string-format security"
+      echo "  vulnerabilities."
+    fi
+  else
+    CFLAGS="$CFLAGS -DNO_vsnprintf"
+    echo "Checking for vsnprintf() in stdio.h... No."
+    echo "  WARNING: vsnprintf() not found, falling back to vsprintf(). zlib"
+    echo "  can build but will be open to possible buffer-overflow security"
+    echo "  vulnerabilities."
+
+    cat >$test.c <<EOF
+#include <stdio.h>
+#include <stdarg.h>
+
+int mytest(char *fmt, ...)
+{
+  int n;
+  char buf[20];
+  va_list ap;
+
+  va_start(ap, fmt);
+  n = vsprintf(buf, fmt, ap);
+  va_end(ap);
+  return n;
+}
+
+int main()
+{
+  return (mytest("Hello%d\n", 1));
+}
+EOF
+
+    if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+      echo "Checking for return value of vsprintf()... Yes."
+    else
+      CFLAGS="$CFLAGS -DHAS_vsprintf_void"
+      echo "Checking for return value of vsprintf()... No."
+      echo "  WARNING: apparently vsprintf() does not return a value. zlib"
+      echo "  can build but will be open to possible string-format security"
+      echo "  vulnerabilities."
+    fi
+  fi
+else
+  echo "Checking whether to use vs[n]printf() or s[n]printf()... using s[n]printf()"
+
+  cat >$test.c <<EOF
+#include <stdio.h>
+
+int mytest()
+{
+  char buf[20];
+
+  snprintf(buf, sizeof(buf), "%s", "foo");
+  return 0;
+}
+
+int main()
+{
+  return (mytest());
+}
+EOF
+
+  if test "`($CC $CFLAGS -o $test $test.c) 2>&1`" = ""; then
+    echo "Checking for snprintf() in stdio.h... Yes."
+
+    cat >$test.c <<EOF
+#include <stdio.h>
+
+int mytest()
+{
+  char buf[20];
+
+  return snprintf(buf, sizeof(buf), "%s", "foo");
+}
+
+int main()
+{
+  return (mytest());
+}
+EOF
+
+    if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+      echo "Checking for return value of snprintf()... Yes."
+    else
+      CFLAGS="$CFLAGS -DHAS_snprintf_void"
+      echo "Checking for return value of snprintf()... No."
+      echo "  WARNING: apparently snprintf() does not return a value. zlib"
+      echo "  can build but will be open to possible string-format security"
+      echo "  vulnerabilities."
+    fi
+  else
+    CFLAGS="$CFLAGS -DNO_snprintf"
+    echo "Checking for snprintf() in stdio.h... No."
+    echo "  WARNING: snprintf() not found, falling back to sprintf(). zlib"
+    echo "  can build but will be open to possible buffer-overflow security"
+    echo "  vulnerabilities."
+
+    cat >$test.c <<EOF
+#include <stdio.h>
+
+int mytest()
+{
+  char buf[20];
+
+  return sprintf(buf, "%s", "foo");
+}
+
+int main()
+{
+  return (mytest());
+}
+EOF
+
+    if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+      echo "Checking for return value of sprintf()... Yes."
+    else
+      CFLAGS="$CFLAGS -DHAS_sprintf_void"
+      echo "Checking for return value of sprintf()... No."
+      echo "  WARNING: apparently sprintf() does not return a value. zlib"
+      echo "  can build but will be open to possible string-format security"
+      echo "  vulnerabilities."
+    fi
+  fi
+fi
+
+cat >$test.c <<EOF
+#include <errno.h>
+int main() { return 0; }
+EOF
+if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+  echo "Checking for errno.h... Yes."
+else
+  echo "Checking for errno.h... No."
+  CFLAGS="$CFLAGS -DNO_ERRNO_H"
+fi
+
+cat > $test.c <<EOF
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+caddr_t hello() {
+  return mmap((caddr_t)0, (off_t)0, PROT_READ, MAP_SHARED, 0, (off_t)0);
+}
+EOF
+if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+  CFLAGS="$CFLAGS -DUSE_MMAP"
+  echo Checking for mmap support... Yes.
+else
+  echo Checking for mmap support... No.
+fi
+
+CPP=${CPP-"$CC -E"}
+case $CFLAGS in
+  *ASMV*)
+    if test "`nm $test.o | grep _hello`" = ""; then
+      CPP="$CPP -DNO_UNDERLINE"
+      echo Checking for underline in external names... No.
+    else
+      echo Checking for underline in external names... Yes.
+    fi;;
+esac
+
+rm -f $test.[co] $test $test$shared_ext
+
+# udpate Makefile
+sed < Makefile.in "
+/^CC *=/s#=.*#=$CC#
+/^CFLAGS *=/s#=.*#=$CFLAGS#
+/^CPP *=/s#=.*#=$CPP#
+/^LDSHARED *=/s#=.*#=$LDSHARED#
+/^LIBS *=/s#=.*#=$LIBS#
+/^SHAREDLIB *=/s#=.*#=$SHAREDLIB#
+/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV#
+/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM#
+/^AR *=/s#=.*#=$AR#
+/^RANLIB *=/s#=.*#=$RANLIB#
+/^EXE *=/s#=.*#=$EXE#
+/^prefix *=/s#=.*#=$prefix#
+/^exec_prefix *=/s#=.*#=$exec_prefix#
+/^libdir *=/s#=.*#=$libdir#
+/^includedir *=/s#=.*#=$includedir#
+/^mandir *=/s#=.*#=$mandir#
+/^LDFLAGS *=/s#=.*#=$LDFLAGS#
+" > Makefile
Index: /trunk/minix/lib/zlib-1.2.3/contrib/README.contrib
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/README.contrib	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/README.contrib	(revision 9)
@@ -0,0 +1,71 @@
+All files under this contrib directory are UNSUPPORTED. There were
+provided by users of zlib and were not tested by the authors of zlib.
+Use at your own risk. Please contact the authors of the contributions
+for help about these, not the zlib authors. Thanks.
+
+
+ada/        by Dmitriy Anisimkov <anisimkov@yahoo.com>
+        Support for Ada
+        See http://zlib-ada.sourceforge.net/
+
+asm586/
+asm686/     by Brian Raiter <breadbox@muppetlabs.com>
+        asm code for Pentium and PPro/PII, using the AT&T (GNU as) syntax
+        See http://www.muppetlabs.com/~breadbox/software/assembly.html
+
+blast/      by Mark Adler <madler@alumni.caltech.edu>
+        Decompressor for output of PKWare Data Compression Library (DCL)
+
+delphi/     by Cosmin Truta <cosmint@cs.ubbcluj.ro>
+        Support for Delphi and C++ Builder
+
+dotzlib/    by Henrik Ravn <henrik@ravn.com>
+        Support for Microsoft .Net and Visual C++ .Net
+
+infback9/   by Mark Adler <madler@alumni.caltech.edu>
+        Unsupported diffs to infback to decode the deflate64 format
+
+inflate86/  by Chris Anderson <christop@charm.net>
+        Tuned x86 gcc asm code to replace inflate_fast()
+
+iostream/   by Kevin Ruland <kevin@rodin.wustl.edu>
+        A C++ I/O streams interface to the zlib gz* functions
+
+iostream2/  by Tyge Løvset <Tyge.Lovset@cmr.no>
+        Another C++ I/O streams interface
+
+iostream3/  by Ludwig Schwardt <schwardt@sun.ac.za>
+            and Kevin Ruland <kevin@rodin.wustl.edu>
+        Yet another C++ I/O streams interface
+
+masm686/    by Dan Higdon <hdan@kinesoft.com>
+            and Chuck Walbourn <chuckw@kinesoft.com>
+        asm code for Pentium Pro/PII, using the MASM syntax
+
+masmx64/    by Gilles Vollant <info@winimage.com>
+	x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to
+	replace longest_match() and inflate_fast()
+
+masmx86/    by Gilles Vollant <info@winimage.com>
+        x86 asm code to replace longest_match() and inflate_fast(),
+        for Visual C++ and MASM
+
+minizip/    by Gilles Vollant <info@winimage.com>
+        Mini zip and unzip based on zlib
+        See http://www.winimage.com/zLibDll/unzip.html
+
+pascal/     by Bob Dellaca <bobdl@xtra.co.nz> et al.
+        Support for Pascal
+
+puff/       by Mark Adler <madler@alumni.caltech.edu>
+        Small, low memory usage inflate.  Also serves to provide an
+        unambiguous description of the deflate format.
+
+testzlib/   by Gilles Vollant <info@winimage.com>
+        Example of the use of zlib
+
+untgz/      by Pedro A. Aranda Gutierrez <paag@tid.es>
+        A very simple tar.gz file extractor using zlib
+
+vstudio/    by Gilles Vollant <info@winimage.com>
+        Building a minizip-enhanced zlib with Microsoft Visual Studio
Index: /trunk/minix/lib/zlib-1.2.3/contrib/ada/buffer_demo.adb
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/ada/buffer_demo.adb	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/ada/buffer_demo.adb	(revision 9)
@@ -0,0 +1,106 @@
+----------------------------------------------------------------
+--  ZLib for Ada thick binding.                               --
+--                                                            --
+--  Copyright (C) 2002-2004 Dmitriy Anisimkov                 --
+--                                                            --
+--  Open source license information is in the zlib.ads file.  --
+----------------------------------------------------------------
+--
+--  $Id: buffer_demo.adb,v 1.1 2005/09/23 22:39:01 beng Exp $
+
+--  This demo program provided by Dr Steve Sangwine <sjs@essex.ac.uk>
+--
+--  Demonstration of a problem with Zlib-Ada (already fixed) when a buffer
+--  of exactly the correct size is used for decompressed data, and the last
+--  few bytes passed in to Zlib are checksum bytes.
+
+--  This program compresses a string of text, and then decompresses the
+--  compressed text into a buffer of the same size as the original text.
+
+with Ada.Streams; use Ada.Streams;
+with Ada.Text_IO;
+
+with ZLib; use ZLib;
+
+procedure Buffer_Demo is
+   EOL  : Character renames ASCII.LF;
+   Text : constant String
+     := "Four score and seven years ago our fathers brought forth," & EOL &
+        "upon this continent, a new nation, conceived in liberty," & EOL &
+        "and dedicated to the proposition that `all men are created equal'.";
+
+   Source : Stream_Element_Array (1 .. Text'Length);
+   for Source'Address use Text'Address;
+
+begin
+   Ada.Text_IO.Put (Text);
+   Ada.Text_IO.New_Line;
+   Ada.Text_IO.Put_Line
+     ("Uncompressed size : " & Positive'Image (Text'Length) & " bytes");
+
+   declare
+      Compressed_Data : Stream_Element_Array (1 .. Text'Length);
+      L               : Stream_Element_Offset;
+   begin
+      Compress : declare
+         Compressor : Filter_Type;
+         I : Stream_Element_Offset;
+      begin
+         Deflate_Init (Compressor);
+
+         --  Compress the whole of T at once.
+
+         Translate (Compressor, Source, I, Compressed_Data, L, Finish);
+         pragma Assert (I = Source'Last);
+
+         Close (Compressor);
+
+         Ada.Text_IO.Put_Line
+           ("Compressed size :   "
+            & Stream_Element_Offset'Image (L) & " bytes");
+      end Compress;
+
+      --  Now we decompress the data, passing short blocks of data to Zlib
+      --  (because this demonstrates the problem - the last block passed will
+      --  contain checksum information and there will be no output, only a
+      --  check inside Zlib that the checksum is correct).
+
+      Decompress : declare
+         Decompressor : Filter_Type;
+
+         Uncompressed_Data : Stream_Element_Array (1 .. Text'Length);
+
+         Block_Size : constant := 4;
+         --  This makes sure that the last block contains
+         --  only Adler checksum data.
+
+         P : Stream_Element_Offset := Compressed_Data'First - 1;
+         O : Stream_Element_Offset;
+      begin
+         Inflate_Init (Decompressor);
+
+         loop
+            Translate
+              (Decompressor,
+               Compressed_Data
+                 (P + 1 .. Stream_Element_Offset'Min (P + Block_Size, L)),
+               P,
+               Uncompressed_Data
+                 (Total_Out (Decompressor) + 1 .. Uncompressed_Data'Last),
+               O,
+               No_Flush);
+
+               Ada.Text_IO.Put_Line
+                 ("Total in : " & Count'Image (Total_In (Decompressor)) &
+                  ", out : " & Count'Image (Total_Out (Decompressor)));
+
+               exit when P = L;
+         end loop;
+
+         Ada.Text_IO.New_Line;
+         Ada.Text_IO.Put_Line
+           ("Decompressed text matches original text : "
+             & Boolean'Image (Uncompressed_Data = Source));
+      end Decompress;
+   end;
+end Buffer_Demo;
Index: /trunk/minix/lib/zlib-1.2.3/contrib/ada/mtest.adb
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/ada/mtest.adb	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/ada/mtest.adb	(revision 9)
@@ -0,0 +1,156 @@
+----------------------------------------------------------------
+--  ZLib for Ada thick binding.                               --
+--                                                            --
+--  Copyright (C) 2002-2003 Dmitriy Anisimkov                 --
+--                                                            --
+--  Open source license information is in the zlib.ads file.  --
+----------------------------------------------------------------
+--  Continuous test for ZLib multithreading. If the test would fail
+--  we should provide thread safe allocation routines for the Z_Stream.
+--
+--  $Id: mtest.adb,v 1.1 2005/09/23 22:39:01 beng Exp $
+
+with ZLib;
+with Ada.Streams;
+with Ada.Numerics.Discrete_Random;
+with Ada.Text_IO;
+with Ada.Exceptions;
+with Ada.Task_Identification;
+
+procedure MTest is
+   use Ada.Streams;
+   use ZLib;
+
+   Stop : Boolean := False;
+
+   pragma Atomic (Stop);
+
+   subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#;
+
+   package Random_Elements is
+      new Ada.Numerics.Discrete_Random (Visible_Symbols);
+
+   task type Test_Task;
+
+   task body Test_Task is
+      Buffer : Stream_Element_Array (1 .. 100_000);
+      Gen : Random_Elements.Generator;
+
+      Buffer_First  : Stream_Element_Offset;
+      Compare_First : Stream_Element_Offset;
+
+      Deflate : Filter_Type;
+      Inflate : Filter_Type;
+
+      procedure Further (Item : in Stream_Element_Array);
+
+      procedure Read_Buffer
+        (Item : out Ada.Streams.Stream_Element_Array;
+         Last : out Ada.Streams.Stream_Element_Offset);
+
+      -------------
+      -- Further --
+      -------------
+
+      procedure Further (Item : in Stream_Element_Array) is
+
+         procedure Compare (Item : in Stream_Element_Array);
+
+         -------------
+         -- Compare --
+         -------------
+
+         procedure Compare (Item : in Stream_Element_Array) is
+            Next_First : Stream_Element_Offset := Compare_First + Item'Length;
+         begin
+            if Buffer (Compare_First .. Next_First - 1) /= Item then
+               raise Program_Error;
+            end if;
+
+            Compare_First := Next_First;
+         end Compare;
+
+         procedure Compare_Write is new ZLib.Write (Write => Compare);
+      begin
+         Compare_Write (Inflate, Item, No_Flush);
+      end Further;
+
+      -----------------
+      -- Read_Buffer --
+      -----------------
+
+      procedure Read_Buffer
+        (Item : out Ada.Streams.Stream_Element_Array;
+         Last : out Ada.Streams.Stream_Element_Offset)
+      is
+         Buff_Diff   : Stream_Element_Offset := Buffer'Last - Buffer_First;
+         Next_First : Stream_Element_Offset;
+      begin
+         if Item'Length <= Buff_Diff then
+            Last := Item'Last;
+
+            Next_First := Buffer_First + Item'Length;
+
+            Item := Buffer (Buffer_First .. Next_First - 1);
+
+            Buffer_First := Next_First;
+         else
+            Last := Item'First + Buff_Diff;
+            Item (Item'First .. Last) := Buffer (Buffer_First .. Buffer'Last);
+            Buffer_First := Buffer'Last + 1;
+         end if;
+      end Read_Buffer;
+
+      procedure Translate is new Generic_Translate
+                                   (Data_In  => Read_Buffer,
+                                    Data_Out => Further);
+
+   begin
+      Random_Elements.Reset (Gen);
+
+      Buffer := (others => 20);
+
+      Main : loop
+         for J in Buffer'Range loop
+            Buffer (J) := Random_Elements.Random (Gen);
+
+            Deflate_Init (Deflate);
+            Inflate_Init (Inflate);
+
+            Buffer_First  := Buffer'First;
+            Compare_First := Buffer'First;
+
+            Translate (Deflate);
+
+            if Compare_First /= Buffer'Last + 1 then
+               raise Program_Error;
+            end if;
+
+            Ada.Text_IO.Put_Line
+              (Ada.Task_Identification.Image
+                 (Ada.Task_Identification.Current_Task)
+               & Stream_Element_Offset'Image (J)
+               & ZLib.Count'Image (Total_Out (Deflate)));
+
+            Close (Deflate);
+            Close (Inflate);
+
+            exit Main when Stop;
+         end loop;
+      end loop Main;
+   exception
+      when E : others =>
+         Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Information (E));
+         Stop := True;
+   end Test_Task;
+
+   Test : array (1 .. 4) of Test_Task;
+
+   pragma Unreferenced (Test);
+
+   Dummy : Character;
+
+begin
+   Ada.Text_IO.Get_Immediate (Dummy);
+   Stop := True;
+end MTest;
Index: /trunk/minix/lib/zlib-1.2.3/contrib/ada/read.adb
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/ada/read.adb	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/ada/read.adb	(revision 9)
@@ -0,0 +1,156 @@
+----------------------------------------------------------------
+--  ZLib for Ada thick binding.                               --
+--                                                            --
+--  Copyright (C) 2002-2003 Dmitriy Anisimkov                 --
+--                                                            --
+--  Open source license information is in the zlib.ads file.  --
+----------------------------------------------------------------
+
+--  $Id: read.adb,v 1.1 2005/09/23 22:39:01 beng Exp $
+
+--  Test/demo program for the generic read interface.
+
+with Ada.Numerics.Discrete_Random;
+with Ada.Streams;
+with Ada.Text_IO;
+
+with ZLib;
+
+procedure Read is
+
+   use Ada.Streams;
+
+   ------------------------------------
+   --  Test configuration parameters --
+   ------------------------------------
+
+   File_Size   : Stream_Element_Offset := 100_000;
+
+   Continuous  : constant Boolean          := False;
+   --  If this constant is True, the test would be repeated again and again,
+   --  with increment File_Size for every iteration.
+
+   Header      : constant ZLib.Header_Type := ZLib.Default;
+   --  Do not use Header other than Default in ZLib versions 1.1.4 and older.
+
+   Init_Random : constant := 8;
+   --  We are using the same random sequence, in case of we catch bug,
+   --  so we would be able to reproduce it.
+
+   -- End --
+
+   Pack_Size : Stream_Element_Offset;
+   Offset    : Stream_Element_Offset;
+
+   Filter     : ZLib.Filter_Type;
+
+   subtype Visible_Symbols
+      is Stream_Element range 16#20# .. 16#7E#;
+
+   package Random_Elements is new
+      Ada.Numerics.Discrete_Random (Visible_Symbols);
+
+   Gen : Random_Elements.Generator;
+   Period  : constant Stream_Element_Offset := 200;
+   --  Period constant variable for random generator not to be very random.
+   --  Bigger period, harder random.
+
+   Read_Buffer : Stream_Element_Array (1 .. 2048);
+   Read_First  : Stream_Element_Offset;
+   Read_Last   : Stream_Element_Offset;
+
+   procedure Reset;
+
+   procedure Read
+     (Item : out Stream_Element_Array;
+      Last : out Stream_Element_Offset);
+   --  this procedure is for generic instantiation of
+   --  ZLib.Read
+   --  reading data from the File_In.
+
+   procedure Read is new ZLib.Read
+                           (Read,
+                            Read_Buffer,
+                            Rest_First => Read_First,
+                            Rest_Last  => Read_Last);
+
+   ----------
+   -- Read --
+   ----------
+
+   procedure Read
+     (Item : out Stream_Element_Array;
+      Last : out Stream_Element_Offset) is
+   begin
+      Last := Stream_Element_Offset'Min
+               (Item'Last,
+                Item'First + File_Size - Offset);
+
+      for J in Item'First .. Last loop
+         if J < Item'First + Period then
+            Item (J) := Random_Elements.Random (Gen);
+         else
+            Item (J) := Item (J - Period);
+         end if;
+
+         Offset   := Offset + 1;
+      end loop;
+   end Read;
+
+   -----------
+   -- Reset --
+   -----------
+
+   procedure Reset is
+   begin
+      Random_Elements.Reset (Gen, Init_Random);
+      Pack_Size := 0;
+      Offset := 1;
+      Read_First := Read_Buffer'Last + 1;
+      Read_Last  := Read_Buffer'Last;
+   end Reset;
+
+begin
+   Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version);
+
+   loop
+      for Level in ZLib.Compression_Level'Range loop
+
+         Ada.Text_IO.Put ("Level ="
+            & ZLib.Compression_Level'Image (Level));
+
+         --  Deflate using generic instantiation.
+
+         ZLib.Deflate_Init
+               (Filter,
+                Level,
+                Header => Header);
+
+         Reset;
+
+         Ada.Text_IO.Put
+           (Stream_Element_Offset'Image (File_Size) & " ->");
+
+         loop
+            declare
+               Buffer : Stream_Element_Array (1 .. 1024);
+               Last   : Stream_Element_Offset;
+            begin
+               Read (Filter, Buffer, Last);
+
+               Pack_Size := Pack_Size + Last - Buffer'First + 1;
+
+               exit when Last < Buffer'Last;
+            end;
+         end loop;
+
+         Ada.Text_IO.Put_Line (Stream_Element_Offset'Image (Pack_Size));
+
+         ZLib.Close (Filter);
+      end loop;
+
+      exit when not Continuous;
+
+      File_Size := File_Size + 1;
+   end loop;
+end Read;
Index: /trunk/minix/lib/zlib-1.2.3/contrib/ada/readme.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/ada/readme.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/ada/readme.txt	(revision 9)
@@ -0,0 +1,65 @@
+                        ZLib for Ada thick binding (ZLib.Ada)
+                        Release 1.3
+
+ZLib.Ada is a thick binding interface to the popular ZLib data
+compression library, available at http://www.gzip.org/zlib/.
+It provides Ada-style access to the ZLib C library.
+
+
+        Here are the main changes since ZLib.Ada 1.2:
+
+- Attension: ZLib.Read generic routine have a initialization requirement
+  for Read_Last parameter now. It is a bit incompartible with previous version,
+  but extends functionality, we could use new parameters Allow_Read_Some and
+  Flush now.
+
+- Added Is_Open routines to ZLib and ZLib.Streams packages.
+
+- Add pragma Assert to check Stream_Element is 8 bit.
+
+- Fix extraction to buffer with exact known decompressed size. Error reported by
+  Steve Sangwine.
+
+- Fix definition of ULong (changed to unsigned_long), fix regression on 64 bits
+  computers. Patch provided by Pascal Obry.
+
+- Add Status_Error exception definition.
+
+- Add pragma Assertion that Ada.Streams.Stream_Element size is 8 bit.
+
+
+        How to build ZLib.Ada under GNAT
+
+You should have the ZLib library already build on your computer, before
+building ZLib.Ada. Make the directory of ZLib.Ada sources current and
+issue the command:
+
+  gnatmake test -largs -L<directory where libz.a is> -lz
+
+Or use the GNAT project file build for GNAT 3.15 or later:
+
+  gnatmake -Pzlib.gpr -L<directory where libz.a is>
+
+
+        How to build ZLib.Ada under Aonix ObjectAda for Win32 7.2.2
+
+1. Make a project with all *.ads and *.adb files from the distribution.
+2. Build the libz.a library from the ZLib C sources.
+3. Rename libz.a to z.lib.
+4. Add the library z.lib to the project.
+5. Add the libc.lib library from the ObjectAda distribution to the project.
+6. Build the executable using test.adb as a main procedure.
+
+
+        How to use ZLib.Ada
+
+The source files test.adb and read.adb are small demo programs that show
+the main functionality of ZLib.Ada.
+
+The routines from the package specifications are commented.
+
+
+Homepage: http://zlib-ada.sourceforge.net/
+Author: Dmitriy Anisimkov <anisimkov@yahoo.com>
+
+Contributors: Pascal Obry <pascal@obry.org>, Steve Sangwine <sjs@essex.ac.uk>
Index: /trunk/minix/lib/zlib-1.2.3/contrib/ada/test.adb
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/ada/test.adb	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/ada/test.adb	(revision 9)
@@ -0,0 +1,463 @@
+----------------------------------------------------------------
+--  ZLib for Ada thick binding.                               --
+--                                                            --
+--  Copyright (C) 2002-2003 Dmitriy Anisimkov                 --
+--                                                            --
+--  Open source license information is in the zlib.ads file.  --
+----------------------------------------------------------------
+
+--  $Id: test.adb,v 1.1 2005/09/23 22:39:01 beng Exp $
+
+--  The program has a few aims.
+--  1. Test ZLib.Ada95 thick binding functionality.
+--  2. Show the example of use main functionality of the ZLib.Ada95 binding.
+--  3. Build this program automatically compile all ZLib.Ada95 packages under
+--     GNAT Ada95 compiler.
+
+with ZLib.Streams;
+with Ada.Streams.Stream_IO;
+with Ada.Numerics.Discrete_Random;
+
+with Ada.Text_IO;
+
+with Ada.Calendar;
+
+procedure Test is
+
+   use Ada.Streams;
+   use Stream_IO;
+
+   ------------------------------------
+   --  Test configuration parameters --
+   ------------------------------------
+
+   File_Size   : Count   := 100_000;
+   Continuous  : constant Boolean := False;
+
+   Header      : constant ZLib.Header_Type := ZLib.Default;
+                                              --  ZLib.None;
+                                              --  ZLib.Auto;
+                                              --  ZLib.GZip;
+   --  Do not use Header other then Default in ZLib versions 1.1.4
+   --  and older.
+
+   Strategy    : constant ZLib.Strategy_Type := ZLib.Default_Strategy;
+   Init_Random : constant := 10;
+
+   -- End --
+
+   In_File_Name  : constant String := "testzlib.in";
+   --  Name of the input file
+
+   Z_File_Name   : constant String := "testzlib.zlb";
+   --  Name of the compressed file.
+
+   Out_File_Name : constant String := "testzlib.out";
+   --  Name of the decompressed file.
+
+   File_In   : File_Type;
+   File_Out  : File_Type;
+   File_Back : File_Type;
+   File_Z    : ZLib.Streams.Stream_Type;
+
+   Filter : ZLib.Filter_Type;
+
+   Time_Stamp : Ada.Calendar.Time;
+
+   procedure Generate_File;
+   --  Generate file of spetsified size with some random data.
+   --  The random data is repeatable, for the good compression.
+
+   procedure Compare_Streams
+     (Left, Right : in out Root_Stream_Type'Class);
+   --  The procedure compearing data in 2 streams.
+   --  It is for compare data before and after compression/decompression.
+
+   procedure Compare_Files (Left, Right : String);
+   --  Compare files. Based on the Compare_Streams.
+
+   procedure Copy_Streams
+     (Source, Target : in out Root_Stream_Type'Class;
+      Buffer_Size    : in     Stream_Element_Offset := 1024);
+   --  Copying data from one stream to another. It is for test stream
+   --  interface of the library.
+
+   procedure Data_In
+     (Item : out Stream_Element_Array;
+      Last : out Stream_Element_Offset);
+   --  this procedure is for generic instantiation of
+   --  ZLib.Generic_Translate.
+   --  reading data from the File_In.
+
+   procedure Data_Out (Item : in Stream_Element_Array);
+   --  this procedure is for generic instantiation of
+   --  ZLib.Generic_Translate.
+   --  writing data to the File_Out.
+
+   procedure Stamp;
+   --  Store the timestamp to the local variable.
+
+   procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count);
+   --  Print the time statistic with the message.
+
+   procedure Translate is new ZLib.Generic_Translate
+                                (Data_In  => Data_In,
+                                 Data_Out => Data_Out);
+   --  This procedure is moving data from File_In to File_Out
+   --  with compression or decompression, depend on initialization of
+   --  Filter parameter.
+
+   -------------------
+   -- Compare_Files --
+   -------------------
+
+   procedure Compare_Files (Left, Right : String) is
+      Left_File, Right_File : File_Type;
+   begin
+      Open (Left_File, In_File, Left);
+      Open (Right_File, In_File, Right);
+      Compare_Streams (Stream (Left_File).all, Stream (Right_File).all);
+      Close (Left_File);
+      Close (Right_File);
+   end Compare_Files;
+
+   ---------------------
+   -- Compare_Streams --
+   ---------------------
+
+   procedure Compare_Streams
+     (Left, Right : in out Ada.Streams.Root_Stream_Type'Class)
+   is
+      Left_Buffer, Right_Buffer : Stream_Element_Array (0 .. 16#FFF#);
+      Left_Last, Right_Last : Stream_Element_Offset;
+   begin
+      loop
+         Read (Left, Left_Buffer, Left_Last);
+         Read (Right, Right_Buffer, Right_Last);
+
+         if Left_Last /= Right_Last then
+            Ada.Text_IO.Put_Line ("Compare error :"
+              & Stream_Element_Offset'Image (Left_Last)
+              & " /= "
+              & Stream_Element_Offset'Image (Right_Last));
+
+            raise Constraint_Error;
+
+         elsif Left_Buffer (0 .. Left_Last)
+               /= Right_Buffer (0 .. Right_Last)
+         then
+            Ada.Text_IO.Put_Line ("ERROR: IN and OUT files is not equal.");
+            raise Constraint_Error;
+
+         end if;
+
+         exit when Left_Last < Left_Buffer'Last;
+      end loop;
+   end Compare_Streams;
+
+   ------------------
+   -- Copy_Streams --
+   ------------------
+
+   procedure Copy_Streams
+     (Source, Target : in out Ada.Streams.Root_Stream_Type'Class;
+      Buffer_Size    : in     Stream_Element_Offset := 1024)
+   is
+      Buffer : Stream_Element_Array (1 .. Buffer_Size);
+      Last   : Stream_Element_Offset;
+   begin
+      loop
+         Read  (Source, Buffer, Last);
+         Write (Target, Buffer (1 .. Last));
+
+         exit when Last < Buffer'Last;
+      end loop;
+   end Copy_Streams;
+
+   -------------
+   -- Data_In --
+   -------------
+
+   procedure Data_In
+     (Item : out Stream_Element_Array;
+      Last : out Stream_Element_Offset) is
+   begin
+      Read (File_In, Item, Last);
+   end Data_In;
+
+   --------------
+   -- Data_Out --
+   --------------
+
+   procedure Data_Out (Item : in Stream_Element_Array) is
+   begin
+      Write (File_Out, Item);
+   end Data_Out;
+
+   -------------------
+   -- Generate_File --
+   -------------------
+
+   procedure Generate_File is
+      subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#;
+
+      package Random_Elements is
+         new Ada.Numerics.Discrete_Random (Visible_Symbols);
+
+      Gen    : Random_Elements.Generator;
+      Buffer : Stream_Element_Array := (1 .. 77 => 16#20#) & 10;
+
+      Buffer_Count : constant Count := File_Size / Buffer'Length;
+      --  Number of same buffers in the packet.
+
+      Density : constant Count := 30; --  from 0 to Buffer'Length - 2;
+
+      procedure Fill_Buffer (J, D : in Count);
+      --  Change the part of the buffer.
+
+      -----------------
+      -- Fill_Buffer --
+      -----------------
+
+      procedure Fill_Buffer (J, D : in Count) is
+      begin
+         for K in 0 .. D loop
+            Buffer
+              (Stream_Element_Offset ((J + K) mod (Buffer'Length - 1) + 1))
+             := Random_Elements.Random (Gen);
+
+         end loop;
+      end Fill_Buffer;
+
+   begin
+      Random_Elements.Reset (Gen, Init_Random);
+
+      Create (File_In, Out_File, In_File_Name);
+
+      Fill_Buffer (1, Buffer'Length - 2);
+
+      for J in 1 .. Buffer_Count loop
+         Write (File_In, Buffer);
+
+         Fill_Buffer (J, Density);
+      end loop;
+
+      --  fill remain size.
+
+      Write
+        (File_In,
+         Buffer
+           (1 .. Stream_Element_Offset
+                   (File_Size - Buffer'Length * Buffer_Count)));
+
+      Flush (File_In);
+      Close (File_In);
+   end Generate_File;
+
+   ---------------------
+   -- Print_Statistic --
+   ---------------------
+
+   procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count) is
+      use Ada.Calendar;
+      use Ada.Text_IO;
+
+      package Count_IO is new Integer_IO (ZLib.Count);
+
+      Curr_Dur : Duration := Clock - Time_Stamp;
+   begin
+      Put (Msg);
+
+      Set_Col (20);
+      Ada.Text_IO.Put ("size =");
+
+      Count_IO.Put
+        (Data_Size,
+         Width => Stream_IO.Count'Image (File_Size)'Length);
+
+      Put_Line (" duration =" & Duration'Image (Curr_Dur));
+   end Print_Statistic;
+
+   -----------
+   -- Stamp --
+   -----------
+
+   procedure Stamp is
+   begin
+      Time_Stamp := Ada.Calendar.Clock;
+   end Stamp;
+
+begin
+   Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version);
+
+   loop
+      Generate_File;
+
+      for Level in ZLib.Compression_Level'Range loop
+
+         Ada.Text_IO.Put_Line ("Level ="
+            & ZLib.Compression_Level'Image (Level));
+
+         --  Test generic interface.
+         Open   (File_In, In_File, In_File_Name);
+         Create (File_Out, Out_File, Z_File_Name);
+
+         Stamp;
+
+         --  Deflate using generic instantiation.
+
+         ZLib.Deflate_Init
+               (Filter   => Filter,
+                Level    => Level,
+                Strategy => Strategy,
+                Header   => Header);
+
+         Translate (Filter);
+         Print_Statistic ("Generic compress", ZLib.Total_Out (Filter));
+         ZLib.Close (Filter);
+
+         Close (File_In);
+         Close (File_Out);
+
+         Open   (File_In, In_File, Z_File_Name);
+         Create (File_Out, Out_File, Out_File_Name);
+
+         Stamp;
+
+         --  Inflate using generic instantiation.
+
+         ZLib.Inflate_Init (Filter, Header => Header);
+
+         Translate (Filter);
+         Print_Statistic ("Generic decompress", ZLib.Total_Out (Filter));
+
+         ZLib.Close (Filter);
+
+         Close (File_In);
+         Close (File_Out);
+
+         Compare_Files (In_File_Name, Out_File_Name);
+
+         --  Test stream interface.
+
+         --  Compress to the back stream.
+
+         Open   (File_In, In_File, In_File_Name);
+         Create (File_Back, Out_File, Z_File_Name);
+
+         Stamp;
+
+         ZLib.Streams.Create
+           (Stream          => File_Z,
+            Mode            => ZLib.Streams.Out_Stream,
+            Back            => ZLib.Streams.Stream_Access
+                                 (Stream (File_Back)),
+            Back_Compressed => True,
+            Level           => Level,
+            Strategy        => Strategy,
+            Header          => Header);
+
+         Copy_Streams
+           (Source => Stream (File_In).all,
+            Target => File_Z);
+
+         --  Flushing internal buffers to the back stream.
+
+         ZLib.Streams.Flush (File_Z, ZLib.Finish);
+
+         Print_Statistic ("Write compress",
+                          ZLib.Streams.Write_Total_Out (File_Z));
+
+         ZLib.Streams.Close (File_Z);
+
+         Close (File_In);
+         Close (File_Back);
+
+         --  Compare reading from original file and from
+         --  decompression stream.
+
+         Open (File_In,   In_File, In_File_Name);
+         Open (File_Back, In_File, Z_File_Name);
+
+         ZLib.Streams.Create
+           (Stream          => File_Z,
+            Mode            => ZLib.Streams.In_Stream,
+            Back            => ZLib.Streams.Stream_Access
+                                 (Stream (File_Back)),
+            Back_Compressed => True,
+            Header          => Header);
+
+         Stamp;
+         Compare_Streams (Stream (File_In).all, File_Z);
+
+         Print_Statistic ("Read decompress",
+                          ZLib.Streams.Read_Total_Out (File_Z));
+
+         ZLib.Streams.Close (File_Z);
+         Close (File_In);
+         Close (File_Back);
+
+         --  Compress by reading from compression stream.
+
+         Open (File_Back, In_File, In_File_Name);
+         Create (File_Out, Out_File, Z_File_Name);
+
+         ZLib.Streams.Create
+           (Stream          => File_Z,
+            Mode            => ZLib.Streams.In_Stream,
+            Back            => ZLib.Streams.Stream_Access
+                                 (Stream (File_Back)),
+            Back_Compressed => False,
+            Level           => Level,
+            Strategy        => Strategy,
+            Header          => Header);
+
+         Stamp;
+         Copy_Streams
+           (Source => File_Z,
+            Target => Stream (File_Out).all);
+
+         Print_Statistic ("Read compress",
+                          ZLib.Streams.Read_Total_Out (File_Z));
+
+         ZLib.Streams.Close (File_Z);
+
+         Close (File_Out);
+         Close (File_Back);
+
+         --  Decompress to decompression stream.
+
+         Open   (File_In,   In_File, Z_File_Name);
+         Create (File_Back, Out_File, Out_File_Name);
+
+         ZLib.Streams.Create
+           (Stream          => File_Z,
+            Mode            => ZLib.Streams.Out_Stream,
+            Back            => ZLib.Streams.Stream_Access
+                                 (Stream (File_Back)),
+            Back_Compressed => False,
+            Header          => Header);
+
+         Stamp;
+
+         Copy_Streams
+           (Source => Stream (File_In).all,
+            Target => File_Z);
+
+         Print_Statistic ("Write decompress",
+                          ZLib.Streams.Write_Total_Out (File_Z));
+
+         ZLib.Streams.Close (File_Z);
+         Close (File_In);
+         Close (File_Back);
+
+         Compare_Files (In_File_Name, Out_File_Name);
+      end loop;
+
+      Ada.Text_IO.Put_Line (Count'Image (File_Size) & " Ok.");
+
+      exit when not Continuous;
+
+      File_Size := File_Size + 1;
+   end loop;
+end Test;
Index: /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib-streams.adb
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib-streams.adb	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib-streams.adb	(revision 9)
@@ -0,0 +1,225 @@
+----------------------------------------------------------------
+--  ZLib for Ada thick binding.                               --
+--                                                            --
+--  Copyright (C) 2002-2003 Dmitriy Anisimkov                 --
+--                                                            --
+--  Open source license information is in the zlib.ads file.  --
+----------------------------------------------------------------
+
+--  $Id: zlib-streams.adb,v 1.1 2005/09/23 22:39:01 beng Exp $
+
+with Ada.Unchecked_Deallocation;
+
+package body ZLib.Streams is
+
+   -----------
+   -- Close --
+   -----------
+
+   procedure Close (Stream : in out Stream_Type) is
+      procedure Free is new Ada.Unchecked_Deallocation
+         (Stream_Element_Array, Buffer_Access);
+   begin
+      if Stream.Mode = Out_Stream or Stream.Mode = Duplex then
+         --  We should flush the data written by the writer.
+
+         Flush (Stream, Finish);
+
+         Close (Stream.Writer);
+      end if;
+
+      if Stream.Mode = In_Stream or Stream.Mode = Duplex then
+         Close (Stream.Reader);
+         Free (Stream.Buffer);
+      end if;
+   end Close;
+
+   ------------
+   -- Create --
+   ------------
+
+   procedure Create
+     (Stream            :    out Stream_Type;
+      Mode              : in     Stream_Mode;
+      Back              : in     Stream_Access;
+      Back_Compressed   : in     Boolean;
+      Level             : in     Compression_Level := Default_Compression;
+      Strategy          : in     Strategy_Type     := Default_Strategy;
+      Header            : in     Header_Type       := Default;
+      Read_Buffer_Size  : in     Ada.Streams.Stream_Element_Offset
+                                    := Default_Buffer_Size;
+      Write_Buffer_Size : in     Ada.Streams.Stream_Element_Offset
+                                    := Default_Buffer_Size)
+   is
+
+      subtype Buffer_Subtype is Stream_Element_Array (1 .. Read_Buffer_Size);
+
+      procedure Init_Filter
+         (Filter   : in out Filter_Type;
+          Compress : in     Boolean);
+
+      -----------------
+      -- Init_Filter --
+      -----------------
+
+      procedure Init_Filter
+         (Filter   : in out Filter_Type;
+          Compress : in     Boolean) is
+      begin
+         if Compress then
+            Deflate_Init
+              (Filter, Level, Strategy, Header => Header);
+         else
+            Inflate_Init (Filter, Header => Header);
+         end if;
+      end Init_Filter;
+
+   begin
+      Stream.Back := Back;
+      Stream.Mode := Mode;
+
+      if Mode = Out_Stream or Mode = Duplex then
+         Init_Filter (Stream.Writer, Back_Compressed);
+         Stream.Buffer_Size := Write_Buffer_Size;
+      else
+         Stream.Buffer_Size := 0;
+      end if;
+
+      if Mode = In_Stream or Mode = Duplex then
+         Init_Filter (Stream.Reader, not Back_Compressed);
+
+         Stream.Buffer     := new Buffer_Subtype;
+         Stream.Rest_First := Stream.Buffer'Last + 1;
+         Stream.Rest_Last  := Stream.Buffer'Last;
+      end if;
+   end Create;
+
+   -----------
+   -- Flush --
+   -----------
+
+   procedure Flush
+     (Stream : in out Stream_Type;
+      Mode   : in     Flush_Mode := Sync_Flush)
+   is
+      Buffer : Stream_Element_Array (1 .. Stream.Buffer_Size);
+      Last   : Stream_Element_Offset;
+   begin
+      loop
+         Flush (Stream.Writer, Buffer, Last, Mode);
+
+         Ada.Streams.Write (Stream.Back.all, Buffer (1 .. Last));
+
+         exit when Last < Buffer'Last;
+      end loop;
+   end Flush;
+
+   -------------
+   -- Is_Open --
+   -------------
+
+   function Is_Open (Stream : Stream_Type) return Boolean is
+   begin
+      return Is_Open (Stream.Reader) or else Is_Open (Stream.Writer);
+   end Is_Open;
+
+   ----------
+   -- Read --
+   ----------
+
+   procedure Read
+     (Stream : in out Stream_Type;
+      Item   :    out Stream_Element_Array;
+      Last   :    out Stream_Element_Offset)
+   is
+
+      procedure Read
+        (Item : out Stream_Element_Array;
+         Last : out Stream_Element_Offset);
+
+      ----------
+      -- Read --
+      ----------
+
+      procedure Read
+        (Item : out Stream_Element_Array;
+         Last : out Stream_Element_Offset) is
+      begin
+         Ada.Streams.Read (Stream.Back.all, Item, Last);
+      end Read;
+
+      procedure Read is new ZLib.Read
+         (Read       => Read,
+          Buffer     => Stream.Buffer.all,
+          Rest_First => Stream.Rest_First,
+          Rest_Last  => Stream.Rest_Last);
+
+   begin
+      Read (Stream.Reader, Item, Last);
+   end Read;
+
+   -------------------
+   -- Read_Total_In --
+   -------------------
+
+   function Read_Total_In (Stream : in Stream_Type) return Count is
+   begin
+      return Total_In (Stream.Reader);
+   end Read_Total_In;
+
+   --------------------
+   -- Read_Total_Out --
+   --------------------
+
+   function Read_Total_Out (Stream : in Stream_Type) return Count is
+   begin
+      return Total_Out (Stream.Reader);
+   end Read_Total_Out;
+
+   -----------
+   -- Write --
+   -----------
+
+   procedure Write
+     (Stream : in out Stream_Type;
+      Item   : in     Stream_Element_Array)
+   is
+
+      procedure Write (Item : in Stream_Element_Array);
+
+      -----------
+      -- Write --
+      -----------
+
+      procedure Write (Item : in Stream_Element_Array) is
+      begin
+         Ada.Streams.Write (Stream.Back.all, Item);
+      end Write;
+
+      procedure Write is new ZLib.Write
+         (Write       => Write,
+          Buffer_Size => Stream.Buffer_Size);
+
+   begin
+      Write (Stream.Writer, Item, No_Flush);
+   end Write;
+
+   --------------------
+   -- Write_Total_In --
+   --------------------
+
+   function Write_Total_In (Stream : in Stream_Type) return Count is
+   begin
+      return Total_In (Stream.Writer);
+   end Write_Total_In;
+
+   ---------------------
+   -- Write_Total_Out --
+   ---------------------
+
+   function Write_Total_Out (Stream : in Stream_Type) return Count is
+   begin
+      return Total_Out (Stream.Writer);
+   end Write_Total_Out;
+
+end ZLib.Streams;
Index: /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib-streams.ads
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib-streams.ads	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib-streams.ads	(revision 9)
@@ -0,0 +1,114 @@
+----------------------------------------------------------------
+--  ZLib for Ada thick binding.                               --
+--                                                            --
+--  Copyright (C) 2002-2003 Dmitriy Anisimkov                 --
+--                                                            --
+--  Open source license information is in the zlib.ads file.  --
+----------------------------------------------------------------
+
+--  $Id: zlib-streams.ads,v 1.1 2005/09/23 22:39:01 beng Exp $
+
+package ZLib.Streams is
+
+   type Stream_Mode is (In_Stream, Out_Stream, Duplex);
+
+   type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class;
+
+   type Stream_Type is
+      new Ada.Streams.Root_Stream_Type with private;
+
+   procedure Read
+     (Stream : in out Stream_Type;
+      Item   :    out Ada.Streams.Stream_Element_Array;
+      Last   :    out Ada.Streams.Stream_Element_Offset);
+
+   procedure Write
+     (Stream : in out Stream_Type;
+      Item   : in     Ada.Streams.Stream_Element_Array);
+
+   procedure Flush
+     (Stream : in out Stream_Type;
+      Mode   : in     Flush_Mode := Sync_Flush);
+   --  Flush the written data to the back stream,
+   --  all data placed to the compressor is flushing to the Back stream.
+   --  Should not be used untill necessary, becouse it is decreasing
+   --  compression.
+
+   function Read_Total_In (Stream : in Stream_Type) return Count;
+   pragma Inline (Read_Total_In);
+   --  Return total number of bytes read from back stream so far.
+
+   function Read_Total_Out (Stream : in Stream_Type) return Count;
+   pragma Inline (Read_Total_Out);
+   --  Return total number of bytes read so far.
+
+   function Write_Total_In (Stream : in Stream_Type) return Count;
+   pragma Inline (Write_Total_In);
+   --  Return total number of bytes written so far.
+
+   function Write_Total_Out (Stream : in Stream_Type) return Count;
+   pragma Inline (Write_Total_Out);
+   --  Return total number of bytes written to the back stream.
+
+   procedure Create
+     (Stream            :    out Stream_Type;
+      Mode              : in     Stream_Mode;
+      Back              : in     Stream_Access;
+      Back_Compressed   : in     Boolean;
+      Level             : in     Compression_Level := Default_Compression;
+      Strategy          : in     Strategy_Type     := Default_Strategy;
+      Header            : in     Header_Type       := Default;
+      Read_Buffer_Size  : in     Ada.Streams.Stream_Element_Offset
+                                    := Default_Buffer_Size;
+      Write_Buffer_Size : in     Ada.Streams.Stream_Element_Offset
+                                    := Default_Buffer_Size);
+   --  Create the Comression/Decompression stream.
+   --  If mode is In_Stream then Write operation is disabled.
+   --  If mode is Out_Stream then Read operation is disabled.
+
+   --  If Back_Compressed is true then
+   --  Data written to the Stream is compressing to the Back stream
+   --  and data read from the Stream is decompressed data from the Back stream.
+
+   --  If Back_Compressed is false then
+   --  Data written to the Stream is decompressing to the Back stream
+   --  and data read from the Stream is compressed data from the Back stream.
+
+   --  !!! When the Need_Header is False ZLib-Ada is using undocumented
+   --  ZLib 1.1.4 functionality to do not create/wait for ZLib headers.
+
+   function Is_Open (Stream : Stream_Type) return Boolean;
+
+   procedure Close (Stream : in out Stream_Type);
+
+private
+
+   use Ada.Streams;
+
+   type Buffer_Access is access all Stream_Element_Array;
+
+   type Stream_Type
+     is new Root_Stream_Type with
+   record
+      Mode       : Stream_Mode;
+
+      Buffer     : Buffer_Access;
+      Rest_First : Stream_Element_Offset;
+      Rest_Last  : Stream_Element_Offset;
+      --  Buffer for Read operation.
+      --  We need to have this buffer in the record
+      --  becouse not all read data from back stream
+      --  could be processed during the read operation.
+
+      Buffer_Size : Stream_Element_Offset;
+      --  Buffer size for write operation.
+      --  We do not need to have this buffer
+      --  in the record becouse all data could be
+      --  processed in the write operation.
+
+      Back       : Stream_Access;
+      Reader     : Filter_Type;
+      Writer     : Filter_Type;
+   end record;
+
+end ZLib.Streams;
Index: /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib-thin.adb
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib-thin.adb	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib-thin.adb	(revision 9)
@@ -0,0 +1,141 @@
+----------------------------------------------------------------
+--  ZLib for Ada thick binding.                               --
+--                                                            --
+--  Copyright (C) 2002-2003 Dmitriy Anisimkov                 --
+--                                                            --
+--  Open source license information is in the zlib.ads file.  --
+----------------------------------------------------------------
+
+--  $Id: zlib-thin.adb,v 1.1 2005/09/23 22:39:01 beng Exp $
+
+package body ZLib.Thin is
+
+   ZLIB_VERSION  : constant Chars_Ptr := zlibVersion;
+
+   Z_Stream_Size : constant Int := Z_Stream'Size / System.Storage_Unit;
+
+   --------------
+   -- Avail_In --
+   --------------
+
+   function Avail_In (Strm : in Z_Stream) return UInt is
+   begin
+      return Strm.Avail_In;
+   end Avail_In;
+
+   ---------------
+   -- Avail_Out --
+   ---------------
+
+   function Avail_Out (Strm : in Z_Stream) return UInt is
+   begin
+      return Strm.Avail_Out;
+   end Avail_Out;
+
+   ------------------
+   -- Deflate_Init --
+   ------------------
+
+   function Deflate_Init
+     (strm       : Z_Streamp;
+      level      : Int;
+      method     : Int;
+      windowBits : Int;
+      memLevel   : Int;
+      strategy   : Int)
+      return       Int is
+   begin
+      return deflateInit2
+               (strm,
+                level,
+                method,
+                windowBits,
+                memLevel,
+                strategy,
+                ZLIB_VERSION,
+                Z_Stream_Size);
+   end Deflate_Init;
+
+   ------------------
+   -- Inflate_Init --
+   ------------------
+
+   function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int is
+   begin
+      return inflateInit2 (strm, windowBits, ZLIB_VERSION, Z_Stream_Size);
+   end Inflate_Init;
+
+   ------------------------
+   -- Last_Error_Message --
+   ------------------------
+
+   function Last_Error_Message (Strm : in Z_Stream) return String is
+      use Interfaces.C.Strings;
+   begin
+      if Strm.msg = Null_Ptr then
+         return "";
+      else
+         return Value (Strm.msg);
+      end if;
+   end Last_Error_Message;
+
+   ------------
+   -- Set_In --
+   ------------
+
+   procedure Set_In
+     (Strm   : in out Z_Stream;
+      Buffer : in     Voidp;
+      Size   : in     UInt) is
+   begin
+      Strm.Next_In  := Buffer;
+      Strm.Avail_In := Size;
+   end Set_In;
+
+   ------------------
+   -- Set_Mem_Func --
+   ------------------
+
+   procedure Set_Mem_Func
+     (Strm   : in out Z_Stream;
+      Opaque : in     Voidp;
+      Alloc  : in     alloc_func;
+      Free   : in     free_func) is
+   begin
+      Strm.opaque := Opaque;
+      Strm.zalloc := Alloc;
+      Strm.zfree  := Free;
+   end Set_Mem_Func;
+
+   -------------
+   -- Set_Out --
+   -------------
+
+   procedure Set_Out
+     (Strm   : in out Z_Stream;
+      Buffer : in     Voidp;
+      Size   : in     UInt) is
+   begin
+      Strm.Next_Out  := Buffer;
+      Strm.Avail_Out := Size;
+   end Set_Out;
+
+   --------------
+   -- Total_In --
+   --------------
+
+   function Total_In (Strm : in Z_Stream) return ULong is
+   begin
+      return Strm.Total_In;
+   end Total_In;
+
+   ---------------
+   -- Total_Out --
+   ---------------
+
+   function Total_Out (Strm : in Z_Stream) return ULong is
+   begin
+      return Strm.Total_Out;
+   end Total_Out;
+
+end ZLib.Thin;
Index: /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib-thin.ads
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib-thin.ads	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib-thin.ads	(revision 9)
@@ -0,0 +1,450 @@
+----------------------------------------------------------------
+--  ZLib for Ada thick binding.                               --
+--                                                            --
+--  Copyright (C) 2002-2003 Dmitriy Anisimkov                 --
+--                                                            --
+--  Open source license information is in the zlib.ads file.  --
+----------------------------------------------------------------
+
+--  $Id: zlib-thin.ads,v 1.1 2005/09/23 22:39:01 beng Exp $
+
+with Interfaces.C.Strings;
+
+with System;
+
+private package ZLib.Thin is
+
+   --  From zconf.h
+
+   MAX_MEM_LEVEL : constant := 9;         --  zconf.h:105
+                                          --  zconf.h:105
+   MAX_WBITS : constant := 15;      --  zconf.h:115
+                                    --  32K LZ77 window
+                                    --  zconf.h:115
+   SEEK_SET : constant := 8#0000#;  --  zconf.h:244
+                                    --  Seek from beginning of file.
+                                    --  zconf.h:244
+   SEEK_CUR : constant := 1;        --  zconf.h:245
+                                    --  Seek from current position.
+                                    --  zconf.h:245
+   SEEK_END : constant := 2;        --  zconf.h:246
+                                    --  Set file pointer to EOF plus "offset"
+                                    --  zconf.h:246
+
+   type Byte is new Interfaces.C.unsigned_char; --  8 bits
+                                                --  zconf.h:214
+   type UInt is new Interfaces.C.unsigned;      --  16 bits or more
+                                                --  zconf.h:216
+   type Int is new Interfaces.C.int;
+
+   type ULong is new Interfaces.C.unsigned_long;     --  32 bits or more
+                                                     --  zconf.h:217
+   subtype Chars_Ptr is Interfaces.C.Strings.chars_ptr;
+
+   type ULong_Access is access ULong;
+   type Int_Access is access Int;
+
+   subtype Voidp is System.Address;            --  zconf.h:232
+
+   subtype Byte_Access is Voidp;
+
+   Nul : constant Voidp := System.Null_Address;
+   --  end from zconf
+
+   Z_NO_FLUSH : constant := 8#0000#;   --  zlib.h:125
+                                       --  zlib.h:125
+   Z_PARTIAL_FLUSH : constant := 1;       --  zlib.h:126
+                                          --  will be removed, use
+                                          --  Z_SYNC_FLUSH instead
+                                          --  zlib.h:126
+   Z_SYNC_FLUSH : constant := 2;       --  zlib.h:127
+                                       --  zlib.h:127
+   Z_FULL_FLUSH : constant := 3;       --  zlib.h:128
+                                       --  zlib.h:128
+   Z_FINISH : constant := 4;        --  zlib.h:129
+                                    --  zlib.h:129
+   Z_OK : constant := 8#0000#;   --  zlib.h:132
+                                 --  zlib.h:132
+   Z_STREAM_END : constant := 1;       --  zlib.h:133
+                                       --  zlib.h:133
+   Z_NEED_DICT : constant := 2;        --  zlib.h:134
+                                       --  zlib.h:134
+   Z_ERRNO : constant := -1;        --  zlib.h:135
+                                    --  zlib.h:135
+   Z_STREAM_ERROR : constant := -2;       --  zlib.h:136
+                                          --  zlib.h:136
+   Z_DATA_ERROR : constant := -3;      --  zlib.h:137
+                                       --  zlib.h:137
+   Z_MEM_ERROR : constant := -4;       --  zlib.h:138
+                                       --  zlib.h:138
+   Z_BUF_ERROR : constant := -5;       --  zlib.h:139
+                                       --  zlib.h:139
+   Z_VERSION_ERROR : constant := -6;      --  zlib.h:140
+                                          --  zlib.h:140
+   Z_NO_COMPRESSION : constant := 8#0000#;   --  zlib.h:145
+                                             --  zlib.h:145
+   Z_BEST_SPEED : constant := 1;       --  zlib.h:146
+                                       --  zlib.h:146
+   Z_BEST_COMPRESSION : constant := 9;       --  zlib.h:147
+                                             --  zlib.h:147
+   Z_DEFAULT_COMPRESSION : constant := -1;      --  zlib.h:148
+                                                --  zlib.h:148
+   Z_FILTERED : constant := 1;      --  zlib.h:151
+                                    --  zlib.h:151
+   Z_HUFFMAN_ONLY : constant := 2;        --  zlib.h:152
+                                          --  zlib.h:152
+   Z_DEFAULT_STRATEGY : constant := 8#0000#; --  zlib.h:153
+                                             --  zlib.h:153
+   Z_BINARY : constant := 8#0000#;  --  zlib.h:156
+                                    --  zlib.h:156
+   Z_ASCII : constant := 1;      --  zlib.h:157
+                                 --  zlib.h:157
+   Z_UNKNOWN : constant := 2;       --  zlib.h:158
+                                    --  zlib.h:158
+   Z_DEFLATED : constant := 8;      --  zlib.h:161
+                                    --  zlib.h:161
+   Z_NULL : constant := 8#0000#; --  zlib.h:164
+                                 --  for initializing zalloc, zfree, opaque
+                                 --  zlib.h:164
+   type gzFile is new Voidp;                  --  zlib.h:646
+
+   type Z_Stream is private;
+
+   type Z_Streamp is access all Z_Stream;     --  zlib.h:89
+
+   type alloc_func is access function
+     (Opaque : Voidp;
+      Items  : UInt;
+      Size   : UInt)
+      return Voidp; --  zlib.h:63
+
+   type free_func is access procedure (opaque : Voidp; address : Voidp);
+
+   function zlibVersion return Chars_Ptr;
+
+   function Deflate (strm : Z_Streamp; flush : Int) return Int;
+
+   function DeflateEnd (strm : Z_Streamp) return Int;
+
+   function Inflate (strm : Z_Streamp; flush : Int) return Int;
+
+   function InflateEnd (strm : Z_Streamp) return Int;
+
+   function deflateSetDictionary
+     (strm       : Z_Streamp;
+      dictionary : Byte_Access;
+      dictLength : UInt)
+      return       Int;
+
+   function deflateCopy (dest : Z_Streamp; source : Z_Streamp) return Int;
+   --  zlib.h:478
+
+   function deflateReset (strm : Z_Streamp) return Int; -- zlib.h:495
+
+   function deflateParams
+     (strm     : Z_Streamp;
+      level    : Int;
+      strategy : Int)
+      return     Int;       -- zlib.h:506
+
+   function inflateSetDictionary
+     (strm       : Z_Streamp;
+      dictionary : Byte_Access;
+      dictLength : UInt)
+      return       Int; --  zlib.h:548
+
+   function inflateSync (strm : Z_Streamp) return Int;  --  zlib.h:565
+
+   function inflateReset (strm : Z_Streamp) return Int; --  zlib.h:580
+
+   function compress
+     (dest      : Byte_Access;
+      destLen   : ULong_Access;
+      source    : Byte_Access;
+      sourceLen : ULong)
+      return      Int;           -- zlib.h:601
+
+   function compress2
+     (dest      : Byte_Access;
+      destLen   : ULong_Access;
+      source    : Byte_Access;
+      sourceLen : ULong;
+      level     : Int)
+      return      Int;          -- zlib.h:615
+
+   function uncompress
+     (dest      : Byte_Access;
+      destLen   : ULong_Access;
+      source    : Byte_Access;
+      sourceLen : ULong)
+      return      Int;
+
+   function gzopen (path : Chars_Ptr; mode : Chars_Ptr) return gzFile;
+
+   function gzdopen (fd : Int; mode : Chars_Ptr) return gzFile;
+
+   function gzsetparams
+     (file     : gzFile;
+      level    : Int;
+      strategy : Int)
+      return     Int;
+
+   function gzread
+     (file : gzFile;
+      buf  : Voidp;
+      len  : UInt)
+      return Int;
+
+   function gzwrite
+     (file : in gzFile;
+      buf  : in Voidp;
+      len  : in UInt)
+      return Int;
+
+   function gzprintf (file : in gzFile; format : in Chars_Ptr) return Int;
+
+   function gzputs (file : in gzFile; s : in Chars_Ptr) return Int;
+
+   function gzgets
+     (file : gzFile;
+      buf  : Chars_Ptr;
+      len  : Int)
+      return Chars_Ptr;
+
+   function gzputc (file : gzFile; char : Int) return Int;
+
+   function gzgetc (file : gzFile) return Int;
+
+   function gzflush (file : gzFile; flush : Int) return Int;
+
+   function gzseek
+     (file   : gzFile;
+      offset : Int;
+      whence : Int)
+      return   Int;
+
+   function gzrewind (file : gzFile) return Int;
+
+   function gztell (file : gzFile) return Int;
+
+   function gzeof (file : gzFile) return Int;
+
+   function gzclose (file : gzFile) return Int;
+
+   function gzerror (file : gzFile; errnum : Int_Access) return Chars_Ptr;
+
+   function adler32
+     (adler : ULong;
+      buf   : Byte_Access;
+      len   : UInt)
+      return  ULong;
+
+   function crc32
+     (crc  : ULong;
+      buf  : Byte_Access;
+      len  : UInt)
+      return ULong;
+
+   function deflateInit
+     (strm        : Z_Streamp;
+      level       : Int;
+      version     : Chars_Ptr;
+      stream_size : Int)
+      return        Int;
+
+   function deflateInit2
+     (strm        : Z_Streamp;
+      level       : Int;
+      method      : Int;
+      windowBits  : Int;
+      memLevel    : Int;
+      strategy    : Int;
+      version     : Chars_Ptr;
+      stream_size : Int)
+      return        Int;
+
+   function Deflate_Init
+     (strm       : Z_Streamp;
+      level      : Int;
+      method     : Int;
+      windowBits : Int;
+      memLevel   : Int;
+      strategy   : Int)
+      return       Int;
+   pragma Inline (Deflate_Init);
+
+   function inflateInit
+     (strm        : Z_Streamp;
+      version     : Chars_Ptr;
+      stream_size : Int)
+      return        Int;
+
+   function inflateInit2
+     (strm        : in Z_Streamp;
+      windowBits  : in Int;
+      version     : in Chars_Ptr;
+      stream_size : in Int)
+      return      Int;
+
+   function inflateBackInit
+     (strm        : in Z_Streamp;
+      windowBits  : in Int;
+      window      : in Byte_Access;
+      version     : in Chars_Ptr;
+      stream_size : in Int)
+      return      Int;
+   --  Size of window have to be 2**windowBits.
+
+   function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int;
+   pragma Inline (Inflate_Init);
+
+   function zError (err : Int) return Chars_Ptr;
+
+   function inflateSyncPoint (z : Z_Streamp) return Int;
+
+   function get_crc_table return ULong_Access;
+
+   --  Interface to the available fields of the z_stream structure.
+   --  The application must update next_in and avail_in when avail_in has
+   --  dropped to zero. It must update next_out and avail_out when avail_out
+   --  has dropped to zero. The application must initialize zalloc, zfree and
+   --  opaque before calling the init function.
+
+   procedure Set_In
+     (Strm   : in out Z_Stream;
+      Buffer : in Voidp;
+      Size   : in UInt);
+   pragma Inline (Set_In);
+
+   procedure Set_Out
+     (Strm   : in out Z_Stream;
+      Buffer : in Voidp;
+      Size   : in UInt);
+   pragma Inline (Set_Out);
+
+   procedure Set_Mem_Func
+     (Strm   : in out Z_Stream;
+      Opaque : in Voidp;
+      Alloc  : in alloc_func;
+      Free   : in free_func);
+   pragma Inline (Set_Mem_Func);
+
+   function Last_Error_Message (Strm : in Z_Stream) return String;
+   pragma Inline (Last_Error_Message);
+
+   function Avail_Out (Strm : in Z_Stream) return UInt;
+   pragma Inline (Avail_Out);
+
+   function Avail_In (Strm : in Z_Stream) return UInt;
+   pragma Inline (Avail_In);
+
+   function Total_In (Strm : in Z_Stream) return ULong;
+   pragma Inline (Total_In);
+
+   function Total_Out (Strm : in Z_Stream) return ULong;
+   pragma Inline (Total_Out);
+
+   function inflateCopy
+     (dest   : in Z_Streamp;
+      Source : in Z_Streamp)
+      return Int;
+
+   function compressBound (Source_Len : in ULong) return ULong;
+
+   function deflateBound
+     (Strm       : in Z_Streamp;
+      Source_Len : in ULong)
+      return     ULong;
+
+   function gzungetc (C : in Int; File : in  gzFile) return Int;
+
+   function zlibCompileFlags return ULong;
+
+private
+
+   type Z_Stream is record            -- zlib.h:68
+      Next_In   : Voidp      := Nul;  -- next input byte
+      Avail_In  : UInt       := 0;    -- number of bytes available at next_in
+      Total_In  : ULong      := 0;    -- total nb of input bytes read so far
+      Next_Out  : Voidp      := Nul;  -- next output byte should be put there
+      Avail_Out : UInt       := 0;    -- remaining free space at next_out
+      Total_Out : ULong      := 0;    -- total nb of bytes output so far
+      msg       : Chars_Ptr;          -- last error message, NULL if no error
+      state     : Voidp;              -- not visible by applications
+      zalloc    : alloc_func := null; -- used to allocate the internal state
+      zfree     : free_func  := null; -- used to free the internal state
+      opaque    : Voidp;              -- private data object passed to
+                                      --  zalloc and zfree
+      data_type : Int;                -- best guess about the data type:
+                                      --  ascii or binary
+      adler     : ULong;              -- adler32 value of the uncompressed
+                                      --  data
+      reserved  : ULong;              -- reserved for future use
+   end record;
+
+   pragma Convention (C, Z_Stream);
+
+   pragma Import (C, zlibVersion, "zlibVersion");
+   pragma Import (C, Deflate, "deflate");
+   pragma Import (C, DeflateEnd, "deflateEnd");
+   pragma Import (C, Inflate, "inflate");
+   pragma Import (C, InflateEnd, "inflateEnd");
+   pragma Import (C, deflateSetDictionary, "deflateSetDictionary");
+   pragma Import (C, deflateCopy, "deflateCopy");
+   pragma Import (C, deflateReset, "deflateReset");
+   pragma Import (C, deflateParams, "deflateParams");
+   pragma Import (C, inflateSetDictionary, "inflateSetDictionary");
+   pragma Import (C, inflateSync, "inflateSync");
+   pragma Import (C, inflateReset, "inflateReset");
+   pragma Import (C, compress, "compress");
+   pragma Import (C, compress2, "compress2");
+   pragma Import (C, uncompress, "uncompress");
+   pragma Import (C, gzopen, "gzopen");
+   pragma Import (C, gzdopen, "gzdopen");
+   pragma Import (C, gzsetparams, "gzsetparams");
+   pragma Import (C, gzread, "gzread");
+   pragma Import (C, gzwrite, "gzwrite");
+   pragma Import (C, gzprintf, "gzprintf");
+   pragma Import (C, gzputs, "gzputs");
+   pragma Import (C, gzgets, "gzgets");
+   pragma Import (C, gzputc, "gzputc");
+   pragma Import (C, gzgetc, "gzgetc");
+   pragma Import (C, gzflush, "gzflush");
+   pragma Import (C, gzseek, "gzseek");
+   pragma Import (C, gzrewind, "gzrewind");
+   pragma Import (C, gztell, "gztell");
+   pragma Import (C, gzeof, "gzeof");
+   pragma Import (C, gzclose, "gzclose");
+   pragma Import (C, gzerror, "gzerror");
+   pragma Import (C, adler32, "adler32");
+   pragma Import (C, crc32, "crc32");
+   pragma Import (C, deflateInit, "deflateInit_");
+   pragma Import (C, inflateInit, "inflateInit_");
+   pragma Import (C, deflateInit2, "deflateInit2_");
+   pragma Import (C, inflateInit2, "inflateInit2_");
+   pragma Import (C, zError, "zError");
+   pragma Import (C, inflateSyncPoint, "inflateSyncPoint");
+   pragma Import (C, get_crc_table, "get_crc_table");
+
+   --  since zlib 1.2.0:
+
+   pragma Import (C, inflateCopy, "inflateCopy");
+   pragma Import (C, compressBound, "compressBound");
+   pragma Import (C, deflateBound, "deflateBound");
+   pragma Import (C, gzungetc, "gzungetc");
+   pragma Import (C, zlibCompileFlags, "zlibCompileFlags");
+
+   pragma Import (C, inflateBackInit, "inflateBackInit_");
+
+   --  I stopped binding the inflateBack routines, becouse realize that
+   --  it does not support zlib and gzip headers for now, and have no
+   --  symmetric deflateBack routines.
+   --  ZLib-Ada is symmetric regarding deflate/inflate data transformation
+   --  and has a similar generic callback interface for the
+   --  deflate/inflate transformation based on the regular Deflate/Inflate
+   --  routines.
+
+   --  pragma Import (C, inflateBack, "inflateBack");
+   --  pragma Import (C, inflateBackEnd, "inflateBackEnd");
+
+end ZLib.Thin;
Index: /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib.adb
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib.adb	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib.adb	(revision 9)
@@ -0,0 +1,701 @@
+----------------------------------------------------------------
+--  ZLib for Ada thick binding.                               --
+--                                                            --
+--  Copyright (C) 2002-2004 Dmitriy Anisimkov                 --
+--                                                            --
+--  Open source license information is in the zlib.ads file.  --
+----------------------------------------------------------------
+
+--  $Id: zlib.adb,v 1.1 2005/09/23 22:39:01 beng Exp $
+
+with Ada.Exceptions;
+with Ada.Unchecked_Conversion;
+with Ada.Unchecked_Deallocation;
+
+with Interfaces.C.Strings;
+
+with ZLib.Thin;
+
+package body ZLib is
+
+   use type Thin.Int;
+
+   type Z_Stream is new Thin.Z_Stream;
+
+   type Return_Code_Enum is
+      (OK,
+       STREAM_END,
+       NEED_DICT,
+       ERRNO,
+       STREAM_ERROR,
+       DATA_ERROR,
+       MEM_ERROR,
+       BUF_ERROR,
+       VERSION_ERROR);
+
+   type Flate_Step_Function is access
+     function (Strm : in Thin.Z_Streamp; Flush : in Thin.Int) return Thin.Int;
+   pragma Convention (C, Flate_Step_Function);
+
+   type Flate_End_Function is access
+      function (Ctrm : in Thin.Z_Streamp) return Thin.Int;
+   pragma Convention (C, Flate_End_Function);
+
+   type Flate_Type is record
+      Step : Flate_Step_Function;
+      Done : Flate_End_Function;
+   end record;
+
+   subtype Footer_Array is Stream_Element_Array (1 .. 8);
+
+   Simple_GZip_Header : constant Stream_Element_Array (1 .. 10)
+     := (16#1f#, 16#8b#,                 --  Magic header
+         16#08#,                         --  Z_DEFLATED
+         16#00#,                         --  Flags
+         16#00#, 16#00#, 16#00#, 16#00#, --  Time
+         16#00#,                         --  XFlags
+         16#03#                          --  OS code
+        );
+   --  The simplest gzip header is not for informational, but just for
+   --  gzip format compatibility.
+   --  Note that some code below is using assumption
+   --  Simple_GZip_Header'Last > Footer_Array'Last, so do not make
+   --  Simple_GZip_Header'Last <= Footer_Array'Last.
+
+   Return_Code : constant array (Thin.Int range <>) of Return_Code_Enum
+     := (0 => OK,
+         1 => STREAM_END,
+         2 => NEED_DICT,
+        -1 => ERRNO,
+        -2 => STREAM_ERROR,
+        -3 => DATA_ERROR,
+        -4 => MEM_ERROR,
+        -5 => BUF_ERROR,
+        -6 => VERSION_ERROR);
+
+   Flate : constant array (Boolean) of Flate_Type
+     := (True  => (Step => Thin.Deflate'Access,
+                   Done => Thin.DeflateEnd'Access),
+         False => (Step => Thin.Inflate'Access,
+                   Done => Thin.InflateEnd'Access));
+
+   Flush_Finish : constant array (Boolean) of Flush_Mode
+     := (True => Finish, False => No_Flush);
+
+   procedure Raise_Error (Stream : in Z_Stream);
+   pragma Inline (Raise_Error);
+
+   procedure Raise_Error (Message : in String);
+   pragma Inline (Raise_Error);
+
+   procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int);
+
+   procedure Free is new Ada.Unchecked_Deallocation
+      (Z_Stream, Z_Stream_Access);
+
+   function To_Thin_Access is new Ada.Unchecked_Conversion
+     (Z_Stream_Access, Thin.Z_Streamp);
+
+   procedure Translate_GZip
+     (Filter    : in out Filter_Type;
+      In_Data   : in     Ada.Streams.Stream_Element_Array;
+      In_Last   :    out Ada.Streams.Stream_Element_Offset;
+      Out_Data  :    out Ada.Streams.Stream_Element_Array;
+      Out_Last  :    out Ada.Streams.Stream_Element_Offset;
+      Flush     : in     Flush_Mode);
+   --  Separate translate routine for make gzip header.
+
+   procedure Translate_Auto
+     (Filter    : in out Filter_Type;
+      In_Data   : in     Ada.Streams.Stream_Element_Array;
+      In_Last   :    out Ada.Streams.Stream_Element_Offset;
+      Out_Data  :    out Ada.Streams.Stream_Element_Array;
+      Out_Last  :    out Ada.Streams.Stream_Element_Offset;
+      Flush     : in     Flush_Mode);
+   --  translate routine without additional headers.
+
+   -----------------
+   -- Check_Error --
+   -----------------
+
+   procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int) is
+      use type Thin.Int;
+   begin
+      if Code /= Thin.Z_OK then
+         Raise_Error
+            (Return_Code_Enum'Image (Return_Code (Code))
+              & ": " & Last_Error_Message (Stream));
+      end if;
+   end Check_Error;
+
+   -----------
+   -- Close --
+   -----------
+
+   procedure Close
+     (Filter       : in out Filter_Type;
+      Ignore_Error : in     Boolean := False)
+   is
+      Code : Thin.Int;
+   begin
+      if not Ignore_Error and then not Is_Open (Filter) then
+         raise Status_Error;
+      end if;
+
+      Code := Flate (Filter.Compression).Done (To_Thin_Access (Filter.Strm));
+
+      if Ignore_Error or else Code = Thin.Z_OK then
+         Free (Filter.Strm);
+      else
+         declare
+            Error_Message : constant String
+              := Last_Error_Message (Filter.Strm.all);
+         begin
+            Free (Filter.Strm);
+            Ada.Exceptions.Raise_Exception
+               (ZLib_Error'Identity,
+                Return_Code_Enum'Image (Return_Code (Code))
+                  & ": " & Error_Message);
+         end;
+      end if;
+   end Close;
+
+   -----------
+   -- CRC32 --
+   -----------
+
+   function CRC32
+     (CRC  : in Unsigned_32;
+      Data : in Ada.Streams.Stream_Element_Array)
+      return Unsigned_32
+   is
+      use Thin;
+   begin
+      return Unsigned_32 (crc32 (ULong (CRC),
+                                 Data'Address,
+                                 Data'Length));
+   end CRC32;
+
+   procedure CRC32
+     (CRC  : in out Unsigned_32;
+      Data : in     Ada.Streams.Stream_Element_Array) is
+   begin
+      CRC := CRC32 (CRC, Data);
+   end CRC32;
+
+   ------------------
+   -- Deflate_Init --
+   ------------------
+
+   procedure Deflate_Init
+     (Filter       : in out Filter_Type;
+      Level        : in     Compression_Level  := Default_Compression;
+      Strategy     : in     Strategy_Type      := Default_Strategy;
+      Method       : in     Compression_Method := Deflated;
+      Window_Bits  : in     Window_Bits_Type   := Default_Window_Bits;
+      Memory_Level : in     Memory_Level_Type  := Default_Memory_Level;
+      Header       : in     Header_Type        := Default)
+   is
+      use type Thin.Int;
+      Win_Bits : Thin.Int := Thin.Int (Window_Bits);
+   begin
+      if Is_Open (Filter) then
+         raise Status_Error;
+      end if;
+
+      --  We allow ZLib to make header only in case of default header type.
+      --  Otherwise we would either do header by ourselfs, or do not do
+      --  header at all.
+
+      if Header = None or else Header = GZip then
+         Win_Bits := -Win_Bits;
+      end if;
+
+      --  For the GZip CRC calculation and make headers.
+
+      if Header = GZip then
+         Filter.CRC    := 0;
+         Filter.Offset := Simple_GZip_Header'First;
+      else
+         Filter.Offset := Simple_GZip_Header'Last + 1;
+      end if;
+
+      Filter.Strm        := new Z_Stream;
+      Filter.Compression := True;
+      Filter.Stream_End  := False;
+      Filter.Header      := Header;
+
+      if Thin.Deflate_Init
+           (To_Thin_Access (Filter.Strm),
+            Level      => Thin.Int (Level),
+            method     => Thin.Int (Method),
+            windowBits => Win_Bits,
+            memLevel   => Thin.Int (Memory_Level),
+            strategy   => Thin.Int (Strategy)) /= Thin.Z_OK
+      then
+         Raise_Error (Filter.Strm.all);
+      end if;
+   end Deflate_Init;
+
+   -----------
+   -- Flush --
+   -----------
+
+   procedure Flush
+     (Filter    : in out Filter_Type;
+      Out_Data  :    out Ada.Streams.Stream_Element_Array;
+      Out_Last  :    out Ada.Streams.Stream_Element_Offset;
+      Flush     : in     Flush_Mode)
+   is
+      No_Data : Stream_Element_Array := (1 .. 0 => 0);
+      Last    : Stream_Element_Offset;
+   begin
+      Translate (Filter, No_Data, Last, Out_Data, Out_Last, Flush);
+   end Flush;
+
+   -----------------------
+   -- Generic_Translate --
+   -----------------------
+
+   procedure Generic_Translate
+     (Filter          : in out ZLib.Filter_Type;
+      In_Buffer_Size  : in     Integer := Default_Buffer_Size;
+      Out_Buffer_Size : in     Integer := Default_Buffer_Size)
+   is
+      In_Buffer  : Stream_Element_Array
+                     (1 .. Stream_Element_Offset (In_Buffer_Size));
+      Out_Buffer : Stream_Element_Array
+                     (1 .. Stream_Element_Offset (Out_Buffer_Size));
+      Last       : Stream_Element_Offset;
+      In_Last    : Stream_Element_Offset;
+      In_First   : Stream_Element_Offset;
+      Out_Last   : Stream_Element_Offset;
+   begin
+      Main : loop
+         Data_In (In_Buffer, Last);
+
+         In_First := In_Buffer'First;
+
+         loop
+            Translate
+              (Filter   => Filter,
+               In_Data  => In_Buffer (In_First .. Last),
+               In_Last  => In_Last,
+               Out_Data => Out_Buffer,
+               Out_Last => Out_Last,
+               Flush    => Flush_Finish (Last < In_Buffer'First));
+
+            if Out_Buffer'First <= Out_Last then
+               Data_Out (Out_Buffer (Out_Buffer'First .. Out_Last));
+            end if;
+
+            exit Main when Stream_End (Filter);
+
+            --  The end of in buffer.
+
+            exit when In_Last = Last;
+
+            In_First := In_Last + 1;
+         end loop;
+      end loop Main;
+
+   end Generic_Translate;
+
+   ------------------
+   -- Inflate_Init --
+   ------------------
+
+   procedure Inflate_Init
+     (Filter      : in out Filter_Type;
+      Window_Bits : in     Window_Bits_Type := Default_Window_Bits;
+      Header      : in     Header_Type      := Default)
+   is
+      use type Thin.Int;
+      Win_Bits : Thin.Int := Thin.Int (Window_Bits);
+
+      procedure Check_Version;
+      --  Check the latest header types compatibility.
+
+      procedure Check_Version is
+      begin
+         if Version <= "1.1.4" then
+            Raise_Error
+              ("Inflate header type " & Header_Type'Image (Header)
+               & " incompatible with ZLib version " & Version);
+         end if;
+      end Check_Version;
+
+   begin
+      if Is_Open (Filter) then
+         raise Status_Error;
+      end if;
+
+      case Header is
+         when None =>
+            Check_Version;
+
+            --  Inflate data without headers determined
+            --  by negative Win_Bits.
+
+            Win_Bits := -Win_Bits;
+         when GZip =>
+            Check_Version;
+
+            --  Inflate gzip data defined by flag 16.
+
+            Win_Bits := Win_Bits + 16;
+         when Auto =>
+            Check_Version;
+
+            --  Inflate with automatic detection
+            --  of gzip or native header defined by flag 32.
+
+            Win_Bits := Win_Bits + 32;
+         when Default => null;
+      end case;
+
+      Filter.Strm        := new Z_Stream;
+      Filter.Compression := False;
+      Filter.Stream_End  := False;
+      Filter.Header      := Header;
+
+      if Thin.Inflate_Init
+         (To_Thin_Access (Filter.Strm), Win_Bits) /= Thin.Z_OK
+      then
+         Raise_Error (Filter.Strm.all);
+      end if;
+   end Inflate_Init;
+
+   -------------
+   -- Is_Open --
+   -------------
+
+   function Is_Open (Filter : in Filter_Type) return Boolean is
+   begin
+      return Filter.Strm /= null;
+   end Is_Open;
+
+   -----------------
+   -- Raise_Error --
+   -----------------
+
+   procedure Raise_Error (Message : in String) is
+   begin
+      Ada.Exceptions.Raise_Exception (ZLib_Error'Identity, Message);
+   end Raise_Error;
+
+   procedure Raise_Error (Stream : in Z_Stream) is
+   begin
+      Raise_Error (Last_Error_Message (Stream));
+   end Raise_Error;
+
+   ----------
+   -- Read --
+   ----------
+
+   procedure Read
+     (Filter : in out Filter_Type;
+      Item   :    out Ada.Streams.Stream_Element_Array;
+      Last   :    out Ada.Streams.Stream_Element_Offset;
+      Flush  : in     Flush_Mode := No_Flush)
+   is
+      In_Last    : Stream_Element_Offset;
+      Item_First : Ada.Streams.Stream_Element_Offset := Item'First;
+      V_Flush    : Flush_Mode := Flush;
+
+   begin
+      pragma Assert (Rest_First in Buffer'First .. Buffer'Last + 1);
+      pragma Assert (Rest_Last in Buffer'First - 1 .. Buffer'Last);
+
+      loop
+         if Rest_Last = Buffer'First - 1 then
+            V_Flush := Finish;
+
+         elsif Rest_First > Rest_Last then
+            Read (Buffer, Rest_Last);
+            Rest_First := Buffer'First;
+
+            if Rest_Last < Buffer'First then
+               V_Flush := Finish;
+            end if;
+         end if;
+
+         Translate
+           (Filter   => Filter,
+            In_Data  => Buffer (Rest_First .. Rest_Last),
+            In_Last  => In_Last,
+            Out_Data => Item (Item_First .. Item'Last),
+            Out_Last => Last,
+            Flush    => V_Flush);
+
+         Rest_First := In_Last + 1;
+
+         exit when Stream_End (Filter)
+           or else Last = Item'Last
+           or else (Last >= Item'First and then Allow_Read_Some);
+
+         Item_First := Last + 1;
+      end loop;
+   end Read;
+
+   ----------------
+   -- Stream_End --
+   ----------------
+
+   function Stream_End (Filter : in Filter_Type) return Boolean is
+   begin
+      if Filter.Header = GZip and Filter.Compression then
+         return Filter.Stream_End
+            and then Filter.Offset = Footer_Array'Last + 1;
+      else
+         return Filter.Stream_End;
+      end if;
+   end Stream_End;
+
+   --------------
+   -- Total_In --
+   --------------
+
+   function Total_In (Filter : in Filter_Type) return Count is
+   begin
+      return Count (Thin.Total_In (To_Thin_Access (Filter.Strm).all));
+   end Total_In;
+
+   ---------------
+   -- Total_Out --
+   ---------------
+
+   function Total_Out (Filter : in Filter_Type) return Count is
+   begin
+      return Count (Thin.Total_Out (To_Thin_Access (Filter.Strm).all));
+   end Total_Out;
+
+   ---------------
+   -- Translate --
+   ---------------
+
+   procedure Translate
+     (Filter    : in out Filter_Type;
+      In_Data   : in     Ada.Streams.Stream_Element_Array;
+      In_Last   :    out Ada.Streams.Stream_Element_Offset;
+      Out_Data  :    out Ada.Streams.Stream_Element_Array;
+      Out_Last  :    out Ada.Streams.Stream_Element_Offset;
+      Flush     : in     Flush_Mode) is
+   begin
+      if Filter.Header = GZip and then Filter.Compression then
+         Translate_GZip
+           (Filter   => Filter,
+            In_Data  => In_Data,
+            In_Last  => In_Last,
+            Out_Data => Out_Data,
+            Out_Last => Out_Last,
+            Flush    => Flush);
+      else
+         Translate_Auto
+           (Filter   => Filter,
+            In_Data  => In_Data,
+            In_Last  => In_Last,
+            Out_Data => Out_Data,
+            Out_Last => Out_Last,
+            Flush    => Flush);
+      end if;
+   end Translate;
+
+   --------------------
+   -- Translate_Auto --
+   --------------------
+
+   procedure Translate_Auto
+     (Filter    : in out Filter_Type;
+      In_Data   : in     Ada.Streams.Stream_Element_Array;
+      In_Last   :    out Ada.Streams.Stream_Element_Offset;
+      Out_Data  :    out Ada.Streams.Stream_Element_Array;
+      Out_Last  :    out Ada.Streams.Stream_Element_Offset;
+      Flush     : in     Flush_Mode)
+   is
+      use type Thin.Int;
+      Code : Thin.Int;
+
+   begin
+      if not Is_Open (Filter) then
+         raise Status_Error;
+      end if;
+
+      if Out_Data'Length = 0 and then In_Data'Length = 0 then
+         raise Constraint_Error;
+      end if;
+
+      Set_Out (Filter.Strm.all, Out_Data'Address, Out_Data'Length);
+      Set_In  (Filter.Strm.all, In_Data'Address, In_Data'Length);
+
+      Code := Flate (Filter.Compression).Step
+        (To_Thin_Access (Filter.Strm),
+         Thin.Int (Flush));
+
+      if Code = Thin.Z_STREAM_END then
+         Filter.Stream_End := True;
+      else
+         Check_Error (Filter.Strm.all, Code);
+      end if;
+
+      In_Last  := In_Data'Last
+         - Stream_Element_Offset (Avail_In (Filter.Strm.all));
+      Out_Last := Out_Data'Last
+         - Stream_Element_Offset (Avail_Out (Filter.Strm.all));
+   end Translate_Auto;
+
+   --------------------
+   -- Translate_GZip --
+   --------------------
+
+   procedure Translate_GZip
+     (Filter    : in out Filter_Type;
+      In_Data   : in     Ada.Streams.Stream_Element_Array;
+      In_Last   :    out Ada.Streams.Stream_Element_Offset;
+      Out_Data  :    out Ada.Streams.Stream_Element_Array;
+      Out_Last  :    out Ada.Streams.Stream_Element_Offset;
+      Flush     : in     Flush_Mode)
+   is
+      Out_First : Stream_Element_Offset;
+
+      procedure Add_Data (Data : in Stream_Element_Array);
+      --  Add data to stream from the Filter.Offset till necessary,
+      --  used for add gzip headr/footer.
+
+      procedure Put_32
+        (Item : in out Stream_Element_Array;
+         Data : in     Unsigned_32);
+      pragma Inline (Put_32);
+
+      --------------
+      -- Add_Data --
+      --------------
+
+      procedure Add_Data (Data : in Stream_Element_Array) is
+         Data_First : Stream_Element_Offset renames Filter.Offset;
+         Data_Last  : Stream_Element_Offset;
+         Data_Len   : Stream_Element_Offset; --  -1
+         Out_Len    : Stream_Element_Offset; --  -1
+      begin
+         Out_First := Out_Last + 1;
+
+         if Data_First > Data'Last then
+            return;
+         end if;
+
+         Data_Len  := Data'Last     - Data_First;
+         Out_Len   := Out_Data'Last - Out_First;
+
+         if Data_Len <= Out_Len then
+            Out_Last  := Out_First  + Data_Len;
+            Data_Last := Data'Last;
+         else
+            Out_Last  := Out_Data'Last;
+            Data_Last := Data_First + Out_Len;
+         end if;
+
+         Out_Data (Out_First .. Out_Last) := Data (Data_First .. Data_Last);
+
+         Data_First := Data_Last + 1;
+         Out_First  := Out_Last + 1;
+      end Add_Data;
+
+      ------------
+      -- Put_32 --
+      ------------
+
+      procedure Put_32
+        (Item : in out Stream_Element_Array;
+         Data : in     Unsigned_32)
+      is
+         D : Unsigned_32 := Data;
+      begin
+         for J in Item'First .. Item'First + 3 loop
+            Item (J) := Stream_Element (D and 16#FF#);
+            D := Shift_Right (D, 8);
+         end loop;
+      end Put_32;
+
+   begin
+      Out_Last := Out_Data'First - 1;
+
+      if not Filter.Stream_End then
+         Add_Data (Simple_GZip_Header);
+
+         Translate_Auto
+           (Filter   => Filter,
+            In_Data  => In_Data,
+            In_Last  => In_Last,
+            Out_Data => Out_Data (Out_First .. Out_Data'Last),
+            Out_Last => Out_Last,
+            Flush    => Flush);
+
+         CRC32 (Filter.CRC, In_Data (In_Data'First .. In_Last));
+      end if;
+
+      if Filter.Stream_End and then Out_Last <= Out_Data'Last then
+         --  This detection method would work only when
+         --  Simple_GZip_Header'Last > Footer_Array'Last
+
+         if Filter.Offset = Simple_GZip_Header'Last + 1 then
+            Filter.Offset := Footer_Array'First;
+         end if;
+
+         declare
+            Footer : Footer_Array;
+         begin
+            Put_32 (Footer, Filter.CRC);
+            Put_32 (Footer (Footer'First + 4 .. Footer'Last),
+                    Unsigned_32 (Total_In (Filter)));
+            Add_Data (Footer);
+         end;
+      end if;
+   end Translate_GZip;
+
+   -------------
+   -- Version --
+   -------------
+
+   function Version return String is
+   begin
+      return Interfaces.C.Strings.Value (Thin.zlibVersion);
+   end Version;
+
+   -----------
+   -- Write --
+   -----------
+
+   procedure Write
+     (Filter : in out Filter_Type;
+      Item   : in     Ada.Streams.Stream_Element_Array;
+      Flush  : in     Flush_Mode := No_Flush)
+   is
+      Buffer   : Stream_Element_Array (1 .. Buffer_Size);
+      In_Last  : Stream_Element_Offset;
+      Out_Last : Stream_Element_Offset;
+      In_First : Stream_Element_Offset := Item'First;
+   begin
+      if Item'Length = 0 and Flush = No_Flush then
+         return;
+      end if;
+
+      loop
+         Translate
+           (Filter   => Filter,
+            In_Data  => Item (In_First .. Item'Last),
+            In_Last  => In_Last,
+            Out_Data => Buffer,
+            Out_Last => Out_Last,
+            Flush    => Flush);
+
+         if Out_Last >= Buffer'First then
+            Write (Buffer (1 .. Out_Last));
+         end if;
+
+         exit when In_Last = Item'Last or Stream_End (Filter);
+
+         In_First := In_Last + 1;
+      end loop;
+   end Write;
+
+end ZLib;
Index: /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib.ads
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib.ads	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib.ads	(revision 9)
@@ -0,0 +1,328 @@
+------------------------------------------------------------------------------
+--                      ZLib for Ada thick binding.                         --
+--                                                                          --
+--              Copyright (C) 2002-2004 Dmitriy Anisimkov                   --
+--                                                                          --
+--  This library is free software; you can redistribute it and/or modify    --
+--  it under the terms of the GNU General Public License as published by    --
+--  the Free Software Foundation; either version 2 of the License, or (at   --
+--  your option) any later version.                                         --
+--                                                                          --
+--  This library is distributed in the hope that it will be useful, but     --
+--  WITHOUT ANY WARRANTY; without even the implied warranty of              --
+--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       --
+--  General Public License for more details.                                --
+--                                                                          --
+--  You should have received a copy of the GNU General Public License       --
+--  along with this library; if not, write to the Free Software Foundation, --
+--  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.          --
+--                                                                          --
+--  As a special exception, if other files instantiate generics from this   --
+--  unit, or you link this unit with other files to produce an executable,  --
+--  this  unit  does not  by itself cause  the resulting executable to be   --
+--  covered by the GNU General Public License. This exception does not      --
+--  however invalidate any other reasons why the executable file  might be  --
+--  covered by the  GNU Public License.                                     --
+------------------------------------------------------------------------------
+
+--  $Id: zlib.ads,v 1.1 2005/09/23 22:39:01 beng Exp $
+
+with Ada.Streams;
+
+with Interfaces;
+
+package ZLib is
+
+   ZLib_Error   : exception;
+   Status_Error : exception;
+
+   type Compression_Level is new Integer range -1 .. 9;
+
+   type Flush_Mode is private;
+
+   type Compression_Method is private;
+
+   type Window_Bits_Type is new Integer range 8 .. 15;
+
+   type Memory_Level_Type is new Integer range 1 .. 9;
+
+   type Unsigned_32 is new Interfaces.Unsigned_32;
+
+   type Strategy_Type is private;
+
+   type Header_Type is (None, Auto, Default, GZip);
+   --  Header type usage have a some limitation for inflate.
+   --  See comment for Inflate_Init.
+
+   subtype Count is Ada.Streams.Stream_Element_Count;
+
+   Default_Memory_Level : constant Memory_Level_Type := 8;
+   Default_Window_Bits  : constant Window_Bits_Type  := 15;
+
+   ----------------------------------
+   -- Compression method constants --
+   ----------------------------------
+
+   Deflated : constant Compression_Method;
+   --  Only one method allowed in this ZLib version
+
+   ---------------------------------
+   -- Compression level constants --
+   ---------------------------------
+
+   No_Compression      : constant Compression_Level := 0;
+   Best_Speed          : constant Compression_Level := 1;
+   Best_Compression    : constant Compression_Level := 9;
+   Default_Compression : constant Compression_Level := -1;
+
+   --------------------------
+   -- Flush mode constants --
+   --------------------------
+
+   No_Flush      : constant Flush_Mode;
+   --  Regular way for compression, no flush
+
+   Partial_Flush : constant Flush_Mode;
+   --  Will be removed, use Z_SYNC_FLUSH instead
+
+   Sync_Flush    : constant Flush_Mode;
+   --  All pending output is flushed to the output buffer and the output
+   --  is aligned on a byte boundary, so that the decompressor can get all
+   --  input data available so far. (In particular avail_in is zero after the
+   --  call if enough output space has been provided  before the call.)
+   --  Flushing may degrade compression for some compression algorithms and so
+   --  it should be used only when necessary.
+
+   Block_Flush   : constant Flush_Mode;
+   --  Z_BLOCK requests that inflate() stop
+   --  if and when it get to the next deflate block boundary. When decoding the
+   --  zlib or gzip format, this will cause inflate() to return immediately
+   --  after the header and before the first block. When doing a raw inflate,
+   --  inflate() will go ahead and process the first block, and will return
+   --  when it gets to the end of that block, or when it runs out of data.
+
+   Full_Flush    : constant Flush_Mode;
+   --  All output is flushed as with SYNC_FLUSH, and the compression state
+   --  is reset so that decompression can restart from this point if previous
+   --  compressed data has been damaged or if random access is desired. Using
+   --  Full_Flush too often can seriously degrade the compression.
+
+   Finish        : constant Flush_Mode;
+   --  Just for tell the compressor that input data is complete.
+
+   ------------------------------------
+   -- Compression strategy constants --
+   ------------------------------------
+
+   --  RLE stategy could be used only in version 1.2.0 and later.
+
+   Filtered         : constant Strategy_Type;
+   Huffman_Only     : constant Strategy_Type;
+   RLE              : constant Strategy_Type;
+   Default_Strategy : constant Strategy_Type;
+
+   Default_Buffer_Size : constant := 4096;
+
+   type Filter_Type is tagged limited private;
+   --  The filter is for compression and for decompression.
+   --  The usage of the type is depend of its initialization.
+
+   function Version return String;
+   pragma Inline (Version);
+   --  Return string representation of the ZLib version.
+
+   procedure Deflate_Init
+     (Filter       : in out Filter_Type;
+      Level        : in     Compression_Level  := Default_Compression;
+      Strategy     : in     Strategy_Type      := Default_Strategy;
+      Method       : in     Compression_Method := Deflated;
+      Window_Bits  : in     Window_Bits_Type   := Default_Window_Bits;
+      Memory_Level : in     Memory_Level_Type  := Default_Memory_Level;
+      Header       : in     Header_Type        := Default);
+   --  Compressor initialization.
+   --  When Header parameter is Auto or Default, then default zlib header
+   --  would be provided for compressed data.
+   --  When Header is GZip, then gzip header would be set instead of
+   --  default header.
+   --  When Header is None, no header would be set for compressed data.
+
+   procedure Inflate_Init
+     (Filter      : in out Filter_Type;
+      Window_Bits : in     Window_Bits_Type := Default_Window_Bits;
+      Header      : in     Header_Type      := Default);
+   --  Decompressor initialization.
+   --  Default header type mean that ZLib default header is expecting in the
+   --  input compressed stream.
+   --  Header type None mean that no header is expecting in the input stream.
+   --  GZip header type mean that GZip header is expecting in the
+   --  input compressed stream.
+   --  Auto header type mean that header type (GZip or Native) would be
+   --  detected automatically in the input stream.
+   --  Note that header types parameter values None, GZip and Auto are
+   --  supported for inflate routine only in ZLib versions 1.2.0.2 and later.
+   --  Deflate_Init is supporting all header types.
+
+   function Is_Open (Filter : in Filter_Type) return Boolean;
+   pragma Inline (Is_Open);
+   --  Is the filter opened for compression or decompression.
+
+   procedure Close
+     (Filter       : in out Filter_Type;
+      Ignore_Error : in     Boolean := False);
+   --  Closing the compression or decompressor.
+   --  If stream is closing before the complete and Ignore_Error is False,
+   --  The exception would be raised.
+
+   generic
+      with procedure Data_In
+        (Item : out Ada.Streams.Stream_Element_Array;
+         Last : out Ada.Streams.Stream_Element_Offset);
+      with procedure Data_Out
+        (Item : in Ada.Streams.Stream_Element_Array);
+   procedure Generic_Translate
+     (Filter          : in out Filter_Type;
+      In_Buffer_Size  : in     Integer := Default_Buffer_Size;
+      Out_Buffer_Size : in     Integer := Default_Buffer_Size);
+   --  Compress/decompress data fetch from Data_In routine and pass the result
+   --  to the Data_Out routine. User should provide Data_In and Data_Out
+   --  for compression/decompression data flow.
+   --  Compression or decompression depend on Filter initialization.
+
+   function Total_In (Filter : in Filter_Type) return Count;
+   pragma Inline (Total_In);
+   --  Returns total number of input bytes read so far
+
+   function Total_Out (Filter : in Filter_Type) return Count;
+   pragma Inline (Total_Out);
+   --  Returns total number of bytes output so far
+
+   function CRC32
+     (CRC    : in Unsigned_32;
+      Data   : in Ada.Streams.Stream_Element_Array)
+      return Unsigned_32;
+   pragma Inline (CRC32);
+   --  Compute CRC32, it could be necessary for make gzip format
+
+   procedure CRC32
+     (CRC  : in out Unsigned_32;
+      Data : in     Ada.Streams.Stream_Element_Array);
+   pragma Inline (CRC32);
+   --  Compute CRC32, it could be necessary for make gzip format
+
+   -------------------------------------------------
+   --  Below is more complex low level routines.  --
+   -------------------------------------------------
+
+   procedure Translate
+     (Filter    : in out Filter_Type;
+      In_Data   : in     Ada.Streams.Stream_Element_Array;
+      In_Last   :    out Ada.Streams.Stream_Element_Offset;
+      Out_Data  :    out Ada.Streams.Stream_Element_Array;
+      Out_Last  :    out Ada.Streams.Stream_Element_Offset;
+      Flush     : in     Flush_Mode);
+   --  Compress/decompress the In_Data buffer and place the result into
+   --  Out_Data. In_Last is the index of last element from In_Data accepted by
+   --  the Filter. Out_Last is the last element of the received data from
+   --  Filter. To tell the filter that incoming data are complete put the
+   --  Flush parameter to Finish.
+
+   function Stream_End (Filter : in Filter_Type) return Boolean;
+   pragma Inline (Stream_End);
+   --  Return the true when the stream is complete.
+
+   procedure Flush
+     (Filter    : in out Filter_Type;
+      Out_Data  :    out Ada.Streams.Stream_Element_Array;
+      Out_Last  :    out Ada.Streams.Stream_Element_Offset;
+      Flush     : in     Flush_Mode);
+   pragma Inline (Flush);
+   --  Flushing the data from the compressor.
+
+   generic
+      with procedure Write
+        (Item : in Ada.Streams.Stream_Element_Array);
+      --  User should provide this routine for accept
+      --  compressed/decompressed data.
+
+      Buffer_Size : in Ada.Streams.Stream_Element_Offset
+         := Default_Buffer_Size;
+      --  Buffer size for Write user routine.
+
+   procedure Write
+     (Filter  : in out Filter_Type;
+      Item    : in     Ada.Streams.Stream_Element_Array;
+      Flush   : in     Flush_Mode := No_Flush);
+   --  Compress/Decompress data from Item to the generic parameter procedure
+   --  Write. Output buffer size could be set in Buffer_Size generic parameter.
+
+   generic
+      with procedure Read
+        (Item : out Ada.Streams.Stream_Element_Array;
+         Last : out Ada.Streams.Stream_Element_Offset);
+      --  User should provide data for compression/decompression
+      --  thru this routine.
+
+      Buffer : in out Ada.Streams.Stream_Element_Array;
+      --  Buffer for keep remaining data from the previous
+      --  back read.
+
+      Rest_First, Rest_Last : in out Ada.Streams.Stream_Element_Offset;
+      --  Rest_First have to be initialized to Buffer'Last + 1
+      --  Rest_Last have to be initialized to Buffer'Last
+      --  before usage.
+
+      Allow_Read_Some : in Boolean := False;
+      --  Is it allowed to return Last < Item'Last before end of data.
+
+   procedure Read
+     (Filter : in out Filter_Type;
+      Item   :    out Ada.Streams.Stream_Element_Array;
+      Last   :    out Ada.Streams.Stream_Element_Offset;
+      Flush  : in     Flush_Mode := No_Flush);
+   --  Compress/Decompress data from generic parameter procedure Read to the
+   --  Item. User should provide Buffer and initialized Rest_First, Rest_Last
+   --  indicators. If Allow_Read_Some is True, Read routines could return
+   --  Last < Item'Last only at end of stream.
+
+private
+
+   use Ada.Streams;
+
+   pragma Assert (Ada.Streams.Stream_Element'Size    =    8);
+   pragma Assert (Ada.Streams.Stream_Element'Modulus = 2**8);
+
+   type Flush_Mode is new Integer range 0 .. 5;
+
+   type Compression_Method is new Integer range 8 .. 8;
+
+   type Strategy_Type is new Integer range 0 .. 3;
+
+   No_Flush      : constant Flush_Mode := 0;
+   Partial_Flush : constant Flush_Mode := 1;
+   Sync_Flush    : constant Flush_Mode := 2;
+   Full_Flush    : constant Flush_Mode := 3;
+   Finish        : constant Flush_Mode := 4;
+   Block_Flush   : constant Flush_Mode := 5;
+
+   Filtered         : constant Strategy_Type := 1;
+   Huffman_Only     : constant Strategy_Type := 2;
+   RLE              : constant Strategy_Type := 3;
+   Default_Strategy : constant Strategy_Type := 0;
+
+   Deflated : constant Compression_Method := 8;
+
+   type Z_Stream;
+
+   type Z_Stream_Access is access all Z_Stream;
+
+   type Filter_Type is tagged limited record
+      Strm        : Z_Stream_Access;
+      Compression : Boolean;
+      Stream_End  : Boolean;
+      Header      : Header_Type;
+      CRC         : Unsigned_32;
+      Offset      : Stream_Element_Offset;
+      --  Offset for gzip header/footer output.
+   end record;
+
+end ZLib;
Index: /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib.gpr
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib.gpr	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/ada/zlib.gpr	(revision 9)
@@ -0,0 +1,20 @@
+project Zlib is
+
+   for Languages use ("Ada");
+   for Source_Dirs use (".");
+   for Object_Dir use ".";
+   for Main use ("test.adb", "mtest.adb", "read.adb", "buffer_demo");
+
+   package Compiler is
+      for Default_Switches ("ada") use ("-gnatwcfilopru", "-gnatVcdfimorst", "-gnatyabcefhiklmnoprst");
+   end Compiler;
+
+   package Linker is
+      for Default_Switches ("ada") use ("-lz");
+   end Linker;
+
+   package Builder is
+      for Default_Switches ("ada") use ("-s", "-gnatQ");
+   end Builder;
+
+end Zlib;
Index: /trunk/minix/lib/zlib-1.2.3/contrib/asm586/README.586
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/asm586/README.586	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/asm586/README.586	(revision 9)
@@ -0,0 +1,43 @@
+This is a patched version of zlib modified to use
+Pentium-optimized assembly code in the deflation algorithm. The files
+changed/added by this patch are:
+
+README.586
+match.S
+
+The effectiveness of these modifications is a bit marginal, as the the
+program's bottleneck seems to be mostly L1-cache contention, for which
+there is no real way to work around without rewriting the basic
+algorithm. The speedup on average is around 5-10% (which is generally
+less than the amount of variance between subsequent executions).
+However, when used at level 9 compression, the cache contention can
+drop enough for the assembly version to achieve 10-20% speedup (and
+sometimes more, depending on the amount of overall redundancy in the
+files). Even here, though, cache contention can still be the limiting
+factor, depending on the nature of the program using the zlib library.
+This may also mean that better improvements will be seen on a Pentium
+with MMX, which suffers much less from L1-cache contention, but I have
+not yet verified this.
+
+Note that this code has been tailored for the Pentium in particular,
+and will not perform well on the Pentium Pro (due to the use of a
+partial register in the inner loop).
+
+If you are using an assembler other than GNU as, you will have to
+translate match.S to use your assembler's syntax. (Have fun.)
+
+Brian Raiter
+breadbox@muppetlabs.com
+April, 1998
+
+
+Added for zlib 1.1.3:
+
+The patches come from
+http://www.muppetlabs.com/~breadbox/software/assembly.html
+
+To compile zlib with this asm file, copy match.S to the zlib directory
+then do:
+
+CFLAGS="-O3 -DASMV" ./configure
+make OBJA=match.o
Index: /trunk/minix/lib/zlib-1.2.3/contrib/asm586/match.S
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/asm586/match.S	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/asm586/match.S	(revision 9)
@@ -0,0 +1,364 @@
+/* match.s -- Pentium-optimized version of longest_match()
+ * Written for zlib 1.1.2
+ * Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License.
+ */
+
+#ifndef NO_UNDERLINE
+#define	match_init	_match_init
+#define	longest_match	_longest_match
+#endif
+
+#define	MAX_MATCH	(258)
+#define	MIN_MATCH	(3)
+#define	MIN_LOOKAHEAD	(MAX_MATCH + MIN_MATCH + 1)
+#define	MAX_MATCH_8	((MAX_MATCH + 7) & ~7)
+
+/* stack frame offsets */
+
+#define	wmask			0	/* local copy of s->wmask	*/
+#define	window			4	/* local copy of s->window	*/
+#define	windowbestlen		8	/* s->window + bestlen		*/
+#define	chainlenscanend		12	/* high word: current chain len	*/
+					/* low word: last bytes sought	*/
+#define	scanstart		16	/* first two bytes of string	*/
+#define	scanalign		20	/* dword-misalignment of string	*/
+#define	nicematch		24	/* a good enough match size	*/
+#define	bestlen			28	/* size of best match so far	*/
+#define	scan			32	/* ptr to string wanting match	*/
+
+#define	LocalVarsSize		(36)
+/*	saved ebx		36 */
+/*	saved edi		40 */
+/*	saved esi		44 */
+/*	saved ebp		48 */
+/*	return address		52 */
+#define	deflatestate		56	/* the function arguments	*/
+#define	curmatch		60
+
+/* Offsets for fields in the deflate_state structure. These numbers
+ * are calculated from the definition of deflate_state, with the
+ * assumption that the compiler will dword-align the fields. (Thus,
+ * changing the definition of deflate_state could easily cause this
+ * program to crash horribly, without so much as a warning at
+ * compile time. Sigh.)
+ */
+
+/* All the +zlib1222add offsets are due to the addition of fields
+ *  in zlib in the deflate_state structure since the asm code was first written
+ * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
+ * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
+ * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
+ */
+
+#define zlib1222add		(8)
+
+#define	dsWSize			(36+zlib1222add)
+#define	dsWMask			(44+zlib1222add)
+#define	dsWindow		(48+zlib1222add)
+#define	dsPrev			(56+zlib1222add)
+#define	dsMatchLen		(88+zlib1222add)
+#define	dsPrevMatch		(92+zlib1222add)
+#define	dsStrStart		(100+zlib1222add)
+#define	dsMatchStart		(104+zlib1222add)
+#define	dsLookahead		(108+zlib1222add)
+#define	dsPrevLen		(112+zlib1222add)
+#define	dsMaxChainLen		(116+zlib1222add)
+#define	dsGoodMatch		(132+zlib1222add)
+#define	dsNiceMatch		(136+zlib1222add)
+
+
+.file "match.S"
+
+.globl	match_init, longest_match
+
+.text
+
+/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
+
+longest_match:
+
+/* Save registers that the compiler may be using, and adjust %esp to	*/
+/* make room for our stack frame.					*/
+
+		pushl	%ebp
+		pushl	%edi
+		pushl	%esi
+		pushl	%ebx
+		subl	$LocalVarsSize, %esp
+
+/* Retrieve the function arguments. %ecx will hold cur_match		*/
+/* throughout the entire function. %edx will hold the pointer to the	*/
+/* deflate_state structure during the function's setup (before		*/
+/* entering the main loop).						*/
+
+		movl	deflatestate(%esp), %edx
+		movl	curmatch(%esp), %ecx
+
+/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;	*/
+
+		movl	dsNiceMatch(%edx), %eax
+		movl	dsLookahead(%edx), %ebx
+		cmpl	%eax, %ebx
+		jl	LookaheadLess
+		movl	%eax, %ebx
+LookaheadLess:	movl	%ebx, nicematch(%esp)
+
+/* register Bytef *scan = s->window + s->strstart;			*/
+
+		movl	dsWindow(%edx), %esi
+		movl	%esi, window(%esp)
+		movl	dsStrStart(%edx), %ebp
+		lea	(%esi,%ebp), %edi
+		movl	%edi, scan(%esp)
+
+/* Determine how many bytes the scan ptr is off from being		*/
+/* dword-aligned.							*/
+
+		movl	%edi, %eax
+		negl	%eax
+		andl	$3, %eax
+		movl	%eax, scanalign(%esp)
+
+/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?			*/
+/*     s->strstart - (IPos)MAX_DIST(s) : NIL;				*/
+
+		movl	dsWSize(%edx), %eax
+		subl	$MIN_LOOKAHEAD, %eax
+		subl	%eax, %ebp
+		jg	LimitPositive
+		xorl	%ebp, %ebp
+LimitPositive:
+
+/* unsigned chain_length = s->max_chain_length;				*/
+/* if (s->prev_length >= s->good_match) {				*/
+/*     chain_length >>= 2;						*/
+/* }									*/
+
+		movl	dsPrevLen(%edx), %eax
+		movl	dsGoodMatch(%edx), %ebx
+		cmpl	%ebx, %eax
+		movl	dsMaxChainLen(%edx), %ebx
+		jl	LastMatchGood
+		shrl	$2, %ebx
+LastMatchGood:
+
+/* chainlen is decremented once beforehand so that the function can	*/
+/* use the sign flag instead of the zero flag for the exit test.	*/
+/* It is then shifted into the high word, to make room for the scanend	*/
+/* scanend value, which it will always accompany.			*/
+
+		decl	%ebx
+		shll	$16, %ebx
+
+/* int best_len = s->prev_length;					*/
+
+		movl	dsPrevLen(%edx), %eax
+		movl	%eax, bestlen(%esp)
+
+/* Store the sum of s->window + best_len in %esi locally, and in %esi.	*/
+
+		addl	%eax, %esi
+		movl	%esi, windowbestlen(%esp)
+
+/* register ush scan_start = *(ushf*)scan;				*/
+/* register ush scan_end   = *(ushf*)(scan+best_len-1);			*/
+
+		movw	(%edi), %bx
+		movw	%bx, scanstart(%esp)
+		movw	-1(%edi,%eax), %bx
+		movl	%ebx, chainlenscanend(%esp)
+
+/* Posf *prev = s->prev;						*/
+/* uInt wmask = s->w_mask;						*/
+
+		movl	dsPrev(%edx), %edi
+		movl	dsWMask(%edx), %edx
+		mov	%edx, wmask(%esp)
+
+/* Jump into the main loop.						*/
+
+		jmp	LoopEntry
+
+.balign 16
+
+/* do {
+ *     match = s->window + cur_match;
+ *     if (*(ushf*)(match+best_len-1) != scan_end ||
+ *         *(ushf*)match != scan_start) continue;
+ *     [...]
+ * } while ((cur_match = prev[cur_match & wmask]) > limit
+ *          && --chain_length != 0);
+ *
+ * Here is the inner loop of the function. The function will spend the
+ * majority of its time in this loop, and majority of that time will
+ * be spent in the first ten instructions.
+ *
+ * Within this loop:
+ * %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend)
+ * %ecx = curmatch
+ * %edx = curmatch & wmask
+ * %esi = windowbestlen - i.e., (window + bestlen)
+ * %edi = prev
+ * %ebp = limit
+ *
+ * Two optimization notes on the choice of instructions:
+ *
+ * The first instruction uses a 16-bit address, which costs an extra,
+ * unpairable cycle. This is cheaper than doing a 32-bit access and
+ * zeroing the high word, due to the 3-cycle misalignment penalty which
+ * would occur half the time. This also turns out to be cheaper than
+ * doing two separate 8-bit accesses, as the memory is so rarely in the
+ * L1 cache.
+ *
+ * The window buffer, however, apparently spends a lot of time in the
+ * cache, and so it is faster to retrieve the word at the end of the
+ * match string with two 8-bit loads. The instructions that test the
+ * word at the beginning of the match string, however, are executed
+ * much less frequently, and there it was cheaper to use 16-bit
+ * instructions, which avoided the necessity of saving off and
+ * subsequently reloading one of the other registers.
+ */
+LookupLoop:
+							/* 1 U & V  */
+		movw	(%edi,%edx,2), %cx		/* 2 U pipe */
+		movl	wmask(%esp), %edx		/* 2 V pipe */
+		cmpl	%ebp, %ecx			/* 3 U pipe */
+		jbe	LeaveNow			/* 3 V pipe */
+		subl	$0x00010000, %ebx		/* 4 U pipe */
+		js	LeaveNow			/* 4 V pipe */
+LoopEntry:	movb	-1(%esi,%ecx), %al		/* 5 U pipe */
+		andl	%ecx, %edx			/* 5 V pipe */
+		cmpb	%bl, %al			/* 6 U pipe */
+		jnz	LookupLoop			/* 6 V pipe */
+		movb	(%esi,%ecx), %ah
+		cmpb	%bh, %ah
+		jnz	LookupLoop
+		movl	window(%esp), %eax
+		movw	(%eax,%ecx), %ax
+		cmpw	scanstart(%esp), %ax
+		jnz	LookupLoop
+
+/* Store the current value of chainlen.					*/
+
+		movl	%ebx, chainlenscanend(%esp)
+
+/* Point %edi to the string under scrutiny, and %esi to the string we	*/
+/* are hoping to match it up with. In actuality, %esi and %edi are	*/
+/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is	*/
+/* initialized to -(MAX_MATCH_8 - scanalign).				*/
+
+		movl	window(%esp), %esi
+		movl	scan(%esp), %edi
+		addl	%ecx, %esi
+		movl	scanalign(%esp), %eax
+		movl	$(-MAX_MATCH_8), %edx
+		lea	MAX_MATCH_8(%edi,%eax), %edi
+		lea	MAX_MATCH_8(%esi,%eax), %esi
+
+/* Test the strings for equality, 8 bytes at a time. At the end,
+ * adjust %edx so that it is offset to the exact byte that mismatched.
+ *
+ * We already know at this point that the first three bytes of the
+ * strings match each other, and they can be safely passed over before
+ * starting the compare loop. So what this code does is skip over 0-3
+ * bytes, as much as necessary in order to dword-align the %edi
+ * pointer. (%esi will still be misaligned three times out of four.)
+ *
+ * It should be confessed that this loop usually does not represent
+ * much of the total running time. Replacing it with a more
+ * straightforward "rep cmpsb" would not drastically degrade
+ * performance.
+ */
+LoopCmps:
+		movl	(%esi,%edx), %eax
+		movl	(%edi,%edx), %ebx
+		xorl	%ebx, %eax
+		jnz	LeaveLoopCmps
+		movl	4(%esi,%edx), %eax
+		movl	4(%edi,%edx), %ebx
+		xorl	%ebx, %eax
+		jnz	LeaveLoopCmps4
+		addl	$8, %edx
+		jnz	LoopCmps
+		jmp	LenMaximum
+LeaveLoopCmps4:	addl	$4, %edx
+LeaveLoopCmps:	testl	$0x0000FFFF, %eax
+		jnz	LenLower
+		addl	$2, %edx
+		shrl	$16, %eax
+LenLower:	subb	$1, %al
+		adcl	$0, %edx
+
+/* Calculate the length of the match. If it is longer than MAX_MATCH,	*/
+/* then automatically accept it as the best possible match and leave.	*/
+
+		lea	(%edi,%edx), %eax
+		movl	scan(%esp), %edi
+		subl	%edi, %eax
+		cmpl	$MAX_MATCH, %eax
+		jge	LenMaximum
+
+/* If the length of the match is not longer than the best match we	*/
+/* have so far, then forget it and return to the lookup loop.		*/
+
+		movl	deflatestate(%esp), %edx
+		movl	bestlen(%esp), %ebx
+		cmpl	%ebx, %eax
+		jg	LongerMatch
+		movl	chainlenscanend(%esp), %ebx
+		movl	windowbestlen(%esp), %esi
+		movl	dsPrev(%edx), %edi
+		movl	wmask(%esp), %edx
+		andl	%ecx, %edx
+		jmp	LookupLoop
+
+/*         s->match_start = cur_match;					*/
+/*         best_len = len;						*/
+/*         if (len >= nice_match) break;				*/
+/*         scan_end = *(ushf*)(scan+best_len-1);			*/
+
+LongerMatch:	movl	nicematch(%esp), %ebx
+		movl	%eax, bestlen(%esp)
+		movl	%ecx, dsMatchStart(%edx)
+		cmpl	%ebx, %eax
+		jge	LeaveNow
+		movl	window(%esp), %esi
+		addl	%eax, %esi
+		movl	%esi, windowbestlen(%esp)
+		movl	chainlenscanend(%esp), %ebx
+		movw	-1(%edi,%eax), %bx
+		movl	dsPrev(%edx), %edi
+		movl	%ebx, chainlenscanend(%esp)
+		movl	wmask(%esp), %edx
+		andl	%ecx, %edx
+		jmp	LookupLoop
+
+/* Accept the current string, with the maximum possible length.		*/
+
+LenMaximum:	movl	deflatestate(%esp), %edx
+		movl	$MAX_MATCH, bestlen(%esp)
+		movl	%ecx, dsMatchStart(%edx)
+
+/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;		*/
+/* return s->lookahead;							*/
+
+LeaveNow:
+		movl	deflatestate(%esp), %edx
+		movl	bestlen(%esp), %ebx
+		movl	dsLookahead(%edx), %eax
+		cmpl	%eax, %ebx
+		jg	LookaheadRet
+		movl	%ebx, %eax
+LookaheadRet:
+
+/* Restore the stack and return from whence we came.			*/
+
+		addl	$LocalVarsSize, %esp
+		popl	%ebx
+		popl	%esi
+		popl	%edi
+		popl	%ebp
+match_init:	ret
Index: /trunk/minix/lib/zlib-1.2.3/contrib/asm686/README.686
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/asm686/README.686	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/asm686/README.686	(revision 9)
@@ -0,0 +1,34 @@
+This is a patched version of zlib, modified to use
+Pentium-Pro-optimized assembly code in the deflation algorithm. The
+files changed/added by this patch are:
+
+README.686
+match.S
+
+The speedup that this patch provides varies, depending on whether the
+compiler used to build the original version of zlib falls afoul of the
+PPro's speed traps. My own tests show a speedup of around 10-20% at
+the default compression level, and 20-30% using -9, against a version
+compiled using gcc 2.7.2.3. Your mileage may vary.
+
+Note that this code has been tailored for the PPro/PII in particular,
+and will not perform particuarly well on a Pentium.
+
+If you are using an assembler other than GNU as, you will have to
+translate match.S to use your assembler's syntax. (Have fun.)
+
+Brian Raiter
+breadbox@muppetlabs.com
+April, 1998
+
+
+Added for zlib 1.1.3:
+
+The patches come from
+http://www.muppetlabs.com/~breadbox/software/assembly.html
+
+To compile zlib with this asm file, copy match.S to the zlib directory
+then do:
+
+CFLAGS="-O3 -DASMV" ./configure
+make OBJA=match.o
Index: /trunk/minix/lib/zlib-1.2.3/contrib/asm686/match.S
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/asm686/match.S	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/asm686/match.S	(revision 9)
@@ -0,0 +1,329 @@
+/* match.s -- Pentium-Pro-optimized version of longest_match()
+ * Written for zlib 1.1.2
+ * Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License.
+ */
+
+#ifndef NO_UNDERLINE
+#define	match_init	_match_init
+#define	longest_match	_longest_match
+#endif
+
+#define	MAX_MATCH	(258)
+#define	MIN_MATCH	(3)
+#define	MIN_LOOKAHEAD	(MAX_MATCH + MIN_MATCH + 1)
+#define	MAX_MATCH_8	((MAX_MATCH + 7) & ~7)
+
+/* stack frame offsets */
+
+#define	chainlenwmask		0	/* high word: current chain len	*/
+					/* low word: s->wmask		*/
+#define	window			4	/* local copy of s->window	*/
+#define	windowbestlen		8	/* s->window + bestlen		*/
+#define	scanstart		16	/* first two bytes of string	*/
+#define	scanend			12	/* last two bytes of string	*/
+#define	scanalign		20	/* dword-misalignment of string	*/
+#define	nicematch		24	/* a good enough match size	*/
+#define	bestlen			28	/* size of best match so far	*/
+#define	scan			32	/* ptr to string wanting match	*/
+
+#define	LocalVarsSize		(36)
+/*	saved ebx		36 */
+/*	saved edi		40 */
+/*	saved esi		44 */
+/*	saved ebp		48 */
+/*	return address		52 */
+#define	deflatestate		56	/* the function arguments	*/
+#define	curmatch		60
+
+/* All the +zlib1222add offsets are due to the addition of fields
+ *  in zlib in the deflate_state structure since the asm code was first written
+ * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
+ * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
+ * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
+ */
+
+#define zlib1222add		(8)
+
+#define	dsWSize			(36+zlib1222add)
+#define	dsWMask			(44+zlib1222add)
+#define	dsWindow		(48+zlib1222add)
+#define	dsPrev			(56+zlib1222add)
+#define	dsMatchLen		(88+zlib1222add)
+#define	dsPrevMatch		(92+zlib1222add)
+#define	dsStrStart		(100+zlib1222add)
+#define	dsMatchStart		(104+zlib1222add)
+#define	dsLookahead		(108+zlib1222add)
+#define	dsPrevLen		(112+zlib1222add)
+#define	dsMaxChainLen		(116+zlib1222add)
+#define	dsGoodMatch		(132+zlib1222add)
+#define	dsNiceMatch		(136+zlib1222add)
+
+
+.file "match.S"
+
+.globl	match_init, longest_match
+
+.text
+
+/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
+
+longest_match:
+
+/* Save registers that the compiler may be using, and adjust %esp to	*/
+/* make room for our stack frame.					*/
+
+		pushl	%ebp
+		pushl	%edi
+		pushl	%esi
+		pushl	%ebx
+		subl	$LocalVarsSize, %esp
+
+/* Retrieve the function arguments. %ecx will hold cur_match		*/
+/* throughout the entire function. %edx will hold the pointer to the	*/
+/* deflate_state structure during the function's setup (before		*/
+/* entering the main loop).						*/
+
+		movl	deflatestate(%esp), %edx
+		movl	curmatch(%esp), %ecx
+
+/* uInt wmask = s->w_mask;						*/
+/* unsigned chain_length = s->max_chain_length;				*/
+/* if (s->prev_length >= s->good_match) {				*/
+/*     chain_length >>= 2;						*/
+/* }									*/
+
+		movl	dsPrevLen(%edx), %eax
+		movl	dsGoodMatch(%edx), %ebx
+		cmpl	%ebx, %eax
+		movl	dsWMask(%edx), %eax
+		movl	dsMaxChainLen(%edx), %ebx
+		jl	LastMatchGood
+		shrl	$2, %ebx
+LastMatchGood:
+
+/* chainlen is decremented once beforehand so that the function can	*/
+/* use the sign flag instead of the zero flag for the exit test.	*/
+/* It is then shifted into the high word, to make room for the wmask	*/
+/* value, which it will always accompany.				*/
+
+		decl	%ebx
+		shll	$16, %ebx
+		orl	%eax, %ebx
+		movl	%ebx, chainlenwmask(%esp)
+
+/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;	*/
+
+		movl	dsNiceMatch(%edx), %eax
+		movl	dsLookahead(%edx), %ebx
+		cmpl	%eax, %ebx
+		jl	LookaheadLess
+		movl	%eax, %ebx
+LookaheadLess:	movl	%ebx, nicematch(%esp)
+
+/* register Bytef *scan = s->window + s->strstart;			*/
+
+		movl	dsWindow(%edx), %esi
+		movl	%esi, window(%esp)
+		movl	dsStrStart(%edx), %ebp
+		lea	(%esi,%ebp), %edi
+		movl	%edi, scan(%esp)
+
+/* Determine how many bytes the scan ptr is off from being		*/
+/* dword-aligned.							*/
+
+		movl	%edi, %eax
+		negl	%eax
+		andl	$3, %eax
+		movl	%eax, scanalign(%esp)
+
+/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?			*/
+/*     s->strstart - (IPos)MAX_DIST(s) : NIL;				*/
+
+		movl	dsWSize(%edx), %eax
+		subl	$MIN_LOOKAHEAD, %eax
+		subl	%eax, %ebp
+		jg	LimitPositive
+		xorl	%ebp, %ebp
+LimitPositive:
+
+/* int best_len = s->prev_length;					*/
+
+		movl	dsPrevLen(%edx), %eax
+		movl	%eax, bestlen(%esp)
+
+/* Store the sum of s->window + best_len in %esi locally, and in %esi.	*/
+
+		addl	%eax, %esi
+		movl	%esi, windowbestlen(%esp)
+
+/* register ush scan_start = *(ushf*)scan;				*/
+/* register ush scan_end   = *(ushf*)(scan+best_len-1);			*/
+/* Posf *prev = s->prev;						*/
+
+		movzwl	(%edi), %ebx
+		movl	%ebx, scanstart(%esp)
+		movzwl	-1(%edi,%eax), %ebx
+		movl	%ebx, scanend(%esp)
+		movl	dsPrev(%edx), %edi
+
+/* Jump into the main loop.						*/
+
+		movl	chainlenwmask(%esp), %edx
+		jmp	LoopEntry
+
+.balign 16
+
+/* do {
+ *     match = s->window + cur_match;
+ *     if (*(ushf*)(match+best_len-1) != scan_end ||
+ *         *(ushf*)match != scan_start) continue;
+ *     [...]
+ * } while ((cur_match = prev[cur_match & wmask]) > limit
+ *          && --chain_length != 0);
+ *
+ * Here is the inner loop of the function. The function will spend the
+ * majority of its time in this loop, and majority of that time will
+ * be spent in the first ten instructions.
+ *
+ * Within this loop:
+ * %ebx = scanend
+ * %ecx = curmatch
+ * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
+ * %esi = windowbestlen - i.e., (window + bestlen)
+ * %edi = prev
+ * %ebp = limit
+ */
+LookupLoop:
+		andl	%edx, %ecx
+		movzwl	(%edi,%ecx,2), %ecx
+		cmpl	%ebp, %ecx
+		jbe	LeaveNow
+		subl	$0x00010000, %edx
+		js	LeaveNow
+LoopEntry:	movzwl	-1(%esi,%ecx), %eax
+		cmpl	%ebx, %eax
+		jnz	LookupLoop
+		movl	window(%esp), %eax
+		movzwl	(%eax,%ecx), %eax
+		cmpl	scanstart(%esp), %eax
+		jnz	LookupLoop
+
+/* Store the current value of chainlen.					*/
+
+		movl	%edx, chainlenwmask(%esp)
+
+/* Point %edi to the string under scrutiny, and %esi to the string we	*/
+/* are hoping to match it up with. In actuality, %esi and %edi are	*/
+/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is	*/
+/* initialized to -(MAX_MATCH_8 - scanalign).				*/
+
+		movl	window(%esp), %esi
+		movl	scan(%esp), %edi
+		addl	%ecx, %esi
+		movl	scanalign(%esp), %eax
+		movl	$(-MAX_MATCH_8), %edx
+		lea	MAX_MATCH_8(%edi,%eax), %edi
+		lea	MAX_MATCH_8(%esi,%eax), %esi
+
+/* Test the strings for equality, 8 bytes at a time. At the end,
+ * adjust %edx so that it is offset to the exact byte that mismatched.
+ *
+ * We already know at this point that the first three bytes of the
+ * strings match each other, and they can be safely passed over before
+ * starting the compare loop. So what this code does is skip over 0-3
+ * bytes, as much as necessary in order to dword-align the %edi
+ * pointer. (%esi will still be misaligned three times out of four.)
+ *
+ * It should be confessed that this loop usually does not represent
+ * much of the total running time. Replacing it with a more
+ * straightforward "rep cmpsb" would not drastically degrade
+ * performance.
+ */
+LoopCmps:
+		movl	(%esi,%edx), %eax
+		xorl	(%edi,%edx), %eax
+		jnz	LeaveLoopCmps
+		movl	4(%esi,%edx), %eax
+		xorl	4(%edi,%edx), %eax
+		jnz	LeaveLoopCmps4
+		addl	$8, %edx
+		jnz	LoopCmps
+		jmp	LenMaximum
+LeaveLoopCmps4:	addl	$4, %edx
+LeaveLoopCmps:	testl	$0x0000FFFF, %eax
+		jnz	LenLower
+		addl	$2, %edx
+		shrl	$16, %eax
+LenLower:	subb	$1, %al
+		adcl	$0, %edx
+
+/* Calculate the length of the match. If it is longer than MAX_MATCH,	*/
+/* then automatically accept it as the best possible match and leave.	*/
+
+		lea	(%edi,%edx), %eax
+		movl	scan(%esp), %edi
+		subl	%edi, %eax
+		cmpl	$MAX_MATCH, %eax
+		jge	LenMaximum
+
+/* If the length of the match is not longer than the best match we	*/
+/* have so far, then forget it and return to the lookup loop.		*/
+
+		movl	deflatestate(%esp), %edx
+		movl	bestlen(%esp), %ebx
+		cmpl	%ebx, %eax
+		jg	LongerMatch
+		movl	windowbestlen(%esp), %esi
+		movl	dsPrev(%edx), %edi
+		movl	scanend(%esp), %ebx
+		movl	chainlenwmask(%esp), %edx
+		jmp	LookupLoop
+
+/*         s->match_start = cur_match;					*/
+/*         best_len = len;						*/
+/*         if (len >= nice_match) break;				*/
+/*         scan_end = *(ushf*)(scan+best_len-1);			*/
+
+LongerMatch:	movl	nicematch(%esp), %ebx
+		movl	%eax, bestlen(%esp)
+		movl	%ecx, dsMatchStart(%edx)
+		cmpl	%ebx, %eax
+		jge	LeaveNow
+		movl	window(%esp), %esi
+		addl	%eax, %esi
+		movl	%esi, windowbestlen(%esp)
+		movzwl	-1(%edi,%eax), %ebx
+		movl	dsPrev(%edx), %edi
+		movl	%ebx, scanend(%esp)
+		movl	chainlenwmask(%esp), %edx
+		jmp	LookupLoop
+
+/* Accept the current string, with the maximum possible length.		*/
+
+LenMaximum:	movl	deflatestate(%esp), %edx
+		movl	$MAX_MATCH, bestlen(%esp)
+		movl	%ecx, dsMatchStart(%edx)
+
+/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;		*/
+/* return s->lookahead;							*/
+
+LeaveNow:
+		movl	deflatestate(%esp), %edx
+		movl	bestlen(%esp), %ebx
+		movl	dsLookahead(%edx), %eax
+		cmpl	%eax, %ebx
+		jg	LookaheadRet
+		movl	%ebx, %eax
+LookaheadRet:
+
+/* Restore the stack and return from whence we came.			*/
+
+		addl	$LocalVarsSize, %esp
+		popl	%ebx
+		popl	%esi
+		popl	%edi
+		popl	%ebp
+match_init:	ret
Index: /trunk/minix/lib/zlib-1.2.3/contrib/blast/Makefile
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/blast/Makefile	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/blast/Makefile	(revision 9)
@@ -0,0 +1,8 @@
+blast: blast.c blast.h
+	cc -DTEST -o blast blast.c
+
+test: blast
+	blast < test.pk | cmp - test.txt
+
+clean:
+	rm -f blast blast.o
Index: /trunk/minix/lib/zlib-1.2.3/contrib/blast/README
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/blast/README	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/blast/README	(revision 9)
@@ -0,0 +1,4 @@
+Read blast.h for purpose and usage.
+
+Mark Adler
+madler@alumni.caltech.edu
Index: /trunk/minix/lib/zlib-1.2.3/contrib/blast/blast.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/blast/blast.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/blast/blast.c	(revision 9)
@@ -0,0 +1,444 @@
+/* blast.c
+ * Copyright (C) 2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in blast.h
+ * version 1.1, 16 Feb 2003
+ *
+ * blast.c decompresses data compressed by the PKWare Compression Library.
+ * This function provides functionality similar to the explode() function of
+ * the PKWare library, hence the name "blast".
+ *
+ * This decompressor is based on the excellent format description provided by
+ * Ben Rudiak-Gould in comp.compression on August 13, 2001.  Interestingly, the
+ * example Ben provided in the post is incorrect.  The distance 110001 should
+ * instead be 111000.  When corrected, the example byte stream becomes:
+ *
+ *    00 04 82 24 25 8f 80 7f
+ *
+ * which decompresses to "AIAIAIAIAIAIA" (without the quotes).
+ */
+
+/*
+ * Change history:
+ *
+ * 1.0  12 Feb 2003     - First version
+ * 1.1  16 Feb 2003     - Fixed distance check for > 4 GB uncompressed data
+ */
+
+#include <setjmp.h>             /* for setjmp(), longjmp(), and jmp_buf */
+#include "blast.h"              /* prototype for blast() */
+
+#define local static            /* for local function definitions */
+#define MAXBITS 13              /* maximum code length */
+#define MAXWIN 4096             /* maximum window size */
+
+/* input and output state */
+struct state {
+    /* input state */
+    blast_in infun;             /* input function provided by user */
+    void *inhow;                /* opaque information passed to infun() */
+    unsigned char *in;          /* next input location */
+    unsigned left;              /* available input at in */
+    int bitbuf;                 /* bit buffer */
+    int bitcnt;                 /* number of bits in bit buffer */
+
+    /* input limit error return state for bits() and decode() */
+    jmp_buf env;
+
+    /* output state */
+    blast_out outfun;           /* output function provided by user */
+    void *outhow;               /* opaque information passed to outfun() */
+    unsigned next;              /* index of next write location in out[] */
+    int first;                  /* true to check distances (for first 4K) */
+    unsigned char out[MAXWIN];  /* output buffer and sliding window */
+};
+
+/*
+ * Return need bits from the input stream.  This always leaves less than
+ * eight bits in the buffer.  bits() works properly for need == 0.
+ *
+ * Format notes:
+ *
+ * - Bits are stored in bytes from the least significant bit to the most
+ *   significant bit.  Therefore bits are dropped from the bottom of the bit
+ *   buffer, using shift right, and new bytes are appended to the top of the
+ *   bit buffer, using shift left.
+ */
+local int bits(struct state *s, int need)
+{
+    int val;            /* bit accumulator */
+
+    /* load at least need bits into val */
+    val = s->bitbuf;
+    while (s->bitcnt < need) {
+        if (s->left == 0) {
+            s->left = s->infun(s->inhow, &(s->in));
+            if (s->left == 0) longjmp(s->env, 1);       /* out of input */
+        }
+        val |= (int)(*(s->in)++) << s->bitcnt;          /* load eight bits */
+        s->left--;
+        s->bitcnt += 8;
+    }
+
+    /* drop need bits and update buffer, always zero to seven bits left */
+    s->bitbuf = val >> need;
+    s->bitcnt -= need;
+
+    /* return need bits, zeroing the bits above that */
+    return val & ((1 << need) - 1);
+}
+
+/*
+ * Huffman code decoding tables.  count[1..MAXBITS] is the number of symbols of
+ * each length, which for a canonical code are stepped through in order.
+ * symbol[] are the symbol values in canonical order, where the number of
+ * entries is the sum of the counts in count[].  The decoding process can be
+ * seen in the function decode() below.
+ */
+struct huffman {
+    short *count;       /* number of symbols of each length */
+    short *symbol;      /* canonically ordered symbols */
+};
+
+/*
+ * Decode a code from the stream s using huffman table h.  Return the symbol or
+ * a negative value if there is an error.  If all of the lengths are zero, i.e.
+ * an empty code, or if the code is incomplete and an invalid code is received,
+ * then -9 is returned after reading MAXBITS bits.
+ *
+ * Format notes:
+ *
+ * - The codes as stored in the compressed data are bit-reversed relative to
+ *   a simple integer ordering of codes of the same lengths.  Hence below the
+ *   bits are pulled from the compressed data one at a time and used to
+ *   build the code value reversed from what is in the stream in order to
+ *   permit simple integer comparisons for decoding.
+ *
+ * - The first code for the shortest length is all ones.  Subsequent codes of
+ *   the same length are simply integer decrements of the previous code.  When
+ *   moving up a length, a one bit is appended to the code.  For a complete
+ *   code, the last code of the longest length will be all zeros.  To support
+ *   this ordering, the bits pulled during decoding are inverted to apply the
+ *   more "natural" ordering starting with all zeros and incrementing.
+ */
+local int decode(struct state *s, struct huffman *h)
+{
+    int len;            /* current number of bits in code */
+    int code;           /* len bits being decoded */
+    int first;          /* first code of length len */
+    int count;          /* number of codes of length len */
+    int index;          /* index of first code of length len in symbol table */
+    int bitbuf;         /* bits from stream */
+    int left;           /* bits left in next or left to process */
+    short *next;        /* next number of codes */
+
+    bitbuf = s->bitbuf;
+    left = s->bitcnt;
+    code = first = index = 0;
+    len = 1;
+    next = h->count + 1;
+    while (1) {
+        while (left--) {
+            code |= (bitbuf & 1) ^ 1;   /* invert code */
+            bitbuf >>= 1;
+            count = *next++;
+            if (code < first + count) { /* if length len, return symbol */
+                s->bitbuf = bitbuf;
+                s->bitcnt = (s->bitcnt - len) & 7;
+                return h->symbol[index + (code - first)];
+            }
+            index += count;             /* else update for next length */
+            first += count;
+            first <<= 1;
+            code <<= 1;
+            len++;
+        }
+        left = (MAXBITS+1) - len;
+        if (left == 0) break;
+        if (s->left == 0) {
+            s->left = s->infun(s->inhow, &(s->in));
+            if (s->left == 0) longjmp(s->env, 1);       /* out of input */
+        }
+        bitbuf = *(s->in)++;
+        s->left--;
+        if (left > 8) left = 8;
+    }
+    return -9;                          /* ran out of codes */
+}
+
+/*
+ * Given a list of repeated code lengths rep[0..n-1], where each byte is a
+ * count (high four bits + 1) and a code length (low four bits), generate the
+ * list of code lengths.  This compaction reduces the size of the object code.
+ * Then given the list of code lengths length[0..n-1] representing a canonical
+ * Huffman code for n symbols, construct the tables required to decode those
+ * codes.  Those tables are the number of codes of each length, and the symbols
+ * sorted by length, retaining their original order within each length.  The
+ * return value is zero for a complete code set, negative for an over-
+ * subscribed code set, and positive for an incomplete code set.  The tables
+ * can be used if the return value is zero or positive, but they cannot be used
+ * if the return value is negative.  If the return value is zero, it is not
+ * possible for decode() using that table to return an error--any stream of
+ * enough bits will resolve to a symbol.  If the return value is positive, then
+ * it is possible for decode() using that table to return an error for received
+ * codes past the end of the incomplete lengths.
+ */
+local int construct(struct huffman *h, const unsigned char *rep, int n)
+{
+    int symbol;         /* current symbol when stepping through length[] */
+    int len;            /* current length when stepping through h->count[] */
+    int left;           /* number of possible codes left of current length */
+    short offs[MAXBITS+1];      /* offsets in symbol table for each length */
+    short length[256];  /* code lengths */
+
+    /* convert compact repeat counts into symbol bit length list */
+    symbol = 0;
+    do {
+        len = *rep++;
+        left = (len >> 4) + 1;
+        len &= 15;
+        do {
+            length[symbol++] = len;
+        } while (--left);
+    } while (--n);
+    n = symbol;
+
+    /* count number of codes of each length */
+    for (len = 0; len <= MAXBITS; len++)
+        h->count[len] = 0;
+    for (symbol = 0; symbol < n; symbol++)
+        (h->count[length[symbol]])++;   /* assumes lengths are within bounds */
+    if (h->count[0] == n)               /* no codes! */
+        return 0;                       /* complete, but decode() will fail */
+
+    /* check for an over-subscribed or incomplete set of lengths */
+    left = 1;                           /* one possible code of zero length */
+    for (len = 1; len <= MAXBITS; len++) {
+        left <<= 1;                     /* one more bit, double codes left */
+        left -= h->count[len];          /* deduct count from possible codes */
+        if (left < 0) return left;      /* over-subscribed--return negative */
+    }                                   /* left > 0 means incomplete */
+
+    /* generate offsets into symbol table for each length for sorting */
+    offs[1] = 0;
+    for (len = 1; len < MAXBITS; len++)
+        offs[len + 1] = offs[len] + h->count[len];
+
+    /*
+     * put symbols in table sorted by length, by symbol order within each
+     * length
+     */
+    for (symbol = 0; symbol < n; symbol++)
+        if (length[symbol] != 0)
+            h->symbol[offs[length[symbol]]++] = symbol;
+
+    /* return zero for complete set, positive for incomplete set */
+    return left;
+}
+
+/*
+ * Decode PKWare Compression Library stream.
+ *
+ * Format notes:
+ *
+ * - First byte is 0 if literals are uncoded or 1 if they are coded.  Second
+ *   byte is 4, 5, or 6 for the number of extra bits in the distance code.
+ *   This is the base-2 logarithm of the dictionary size minus six.
+ *
+ * - Compressed data is a combination of literals and length/distance pairs
+ *   terminated by an end code.  Literals are either Huffman coded or
+ *   uncoded bytes.  A length/distance pair is a coded length followed by a
+ *   coded distance to represent a string that occurs earlier in the
+ *   uncompressed data that occurs again at the current location.
+ *
+ * - A bit preceding a literal or length/distance pair indicates which comes
+ *   next, 0 for literals, 1 for length/distance.
+ *
+ * - If literals are uncoded, then the next eight bits are the literal, in the
+ *   normal bit order in th stream, i.e. no bit-reversal is needed. Similarly,
+ *   no bit reversal is needed for either the length extra bits or the distance
+ *   extra bits.
+ *
+ * - Literal bytes are simply written to the output.  A length/distance pair is
+ *   an instruction to copy previously uncompressed bytes to the output.  The
+ *   copy is from distance bytes back in the output stream, copying for length
+ *   bytes.
+ *
+ * - Distances pointing before the beginning of the output data are not
+ *   permitted.
+ *
+ * - Overlapped copies, where the length is greater than the distance, are
+ *   allowed and common.  For example, a distance of one and a length of 518
+ *   simply copies the last byte 518 times.  A distance of four and a length of
+ *   twelve copies the last four bytes three times.  A simple forward copy
+ *   ignoring whether the length is greater than the distance or not implements
+ *   this correctly.
+ */
+local int decomp(struct state *s)
+{
+    int lit;            /* true if literals are coded */
+    int dict;           /* log2(dictionary size) - 6 */
+    int symbol;         /* decoded symbol, extra bits for distance */
+    int len;            /* length for copy */
+    int dist;           /* distance for copy */
+    int copy;           /* copy counter */
+    unsigned char *from, *to;   /* copy pointers */
+    static int virgin = 1;                              /* build tables once */
+    static short litcnt[MAXBITS+1], litsym[256];        /* litcode memory */
+    static short lencnt[MAXBITS+1], lensym[16];         /* lencode memory */
+    static short distcnt[MAXBITS+1], distsym[64];       /* distcode memory */
+    static struct huffman litcode = {litcnt, litsym};   /* length code */
+    static struct huffman lencode = {lencnt, lensym};   /* length code */
+    static struct huffman distcode = {distcnt, distsym};/* distance code */
+        /* bit lengths of literal codes */
+    static const unsigned char litlen[] = {
+        11, 124, 8, 7, 28, 7, 188, 13, 76, 4, 10, 8, 12, 10, 12, 10, 8, 23, 8,
+        9, 7, 6, 7, 8, 7, 6, 55, 8, 23, 24, 12, 11, 7, 9, 11, 12, 6, 7, 22, 5,
+        7, 24, 6, 11, 9, 6, 7, 22, 7, 11, 38, 7, 9, 8, 25, 11, 8, 11, 9, 12,
+        8, 12, 5, 38, 5, 38, 5, 11, 7, 5, 6, 21, 6, 10, 53, 8, 7, 24, 10, 27,
+        44, 253, 253, 253, 252, 252, 252, 13, 12, 45, 12, 45, 12, 61, 12, 45,
+        44, 173};
+        /* bit lengths of length codes 0..15 */
+    static const unsigned char lenlen[] = {2, 35, 36, 53, 38, 23};
+        /* bit lengths of distance codes 0..63 */
+    static const unsigned char distlen[] = {2, 20, 53, 230, 247, 151, 248};
+    static const short base[16] = {     /* base for length codes */
+        3, 2, 4, 5, 6, 7, 8, 9, 10, 12, 16, 24, 40, 72, 136, 264};
+    static const char extra[16] = {     /* extra bits for length codes */
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8};
+
+    /* set up decoding tables (once--might not be thread-safe) */
+    if (virgin) {
+        construct(&litcode, litlen, sizeof(litlen));
+        construct(&lencode, lenlen, sizeof(lenlen));
+        construct(&distcode, distlen, sizeof(distlen));
+        virgin = 0;
+    }
+
+    /* read header */
+    lit = bits(s, 8);
+    if (lit > 1) return -1;
+    dict = bits(s, 8);
+    if (dict < 4 || dict > 6) return -2;
+
+    /* decode literals and length/distance pairs */
+    do {
+        if (bits(s, 1)) {
+            /* get length */
+            symbol = decode(s, &lencode);
+            len = base[symbol] + bits(s, extra[symbol]);
+            if (len == 519) break;              /* end code */
+
+            /* get distance */
+            symbol = len == 2 ? 2 : dict;
+            dist = decode(s, &distcode) << symbol;
+            dist += bits(s, symbol);
+            dist++;
+            if (s->first && dist > s->next)
+                return -3;              /* distance too far back */
+
+            /* copy length bytes from distance bytes back */
+            do {
+                to = s->out + s->next;
+                from = to - dist;
+                copy = MAXWIN;
+                if (s->next < dist) {
+                    from += copy;
+                    copy = dist;
+                }
+                copy -= s->next;
+                if (copy > len) copy = len;
+                len -= copy;
+                s->next += copy;
+                do {
+                    *to++ = *from++;
+                } while (--copy);
+                if (s->next == MAXWIN) {
+                    if (s->outfun(s->outhow, s->out, s->next)) return 1;
+                    s->next = 0;
+                    s->first = 0;
+                }
+            } while (len != 0);
+        }
+        else {
+            /* get literal and write it */
+            symbol = lit ? decode(s, &litcode) : bits(s, 8);
+            s->out[s->next++] = symbol;
+            if (s->next == MAXWIN) {
+                if (s->outfun(s->outhow, s->out, s->next)) return 1;
+                s->next = 0;
+                s->first = 0;
+            }
+        }
+    } while (1);
+    return 0;
+}
+
+/* See comments in blast.h */
+int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow)
+{
+    struct state s;             /* input/output state */
+    int err;                    /* return value */
+
+    /* initialize input state */
+    s.infun = infun;
+    s.inhow = inhow;
+    s.left = 0;
+    s.bitbuf = 0;
+    s.bitcnt = 0;
+
+    /* initialize output state */
+    s.outfun = outfun;
+    s.outhow = outhow;
+    s.next = 0;
+    s.first = 1;
+
+    /* return if bits() or decode() tries to read past available input */
+    if (setjmp(s.env) != 0)             /* if came back here via longjmp(), */
+        err = 2;                        /*  then skip decomp(), return error */
+    else
+        err = decomp(&s);               /* decompress */
+
+    /* write any leftover output and update the error code if needed */
+    if (err != 1 && s.next && s.outfun(s.outhow, s.out, s.next) && err == 0)
+        err = 1;
+    return err;
+}
+
+#ifdef TEST
+/* Example of how to use blast() */
+#include <stdio.h>
+#include <stdlib.h>
+
+#define CHUNK 16384
+
+local unsigned inf(void *how, unsigned char **buf)
+{
+    static unsigned char hold[CHUNK];
+
+    *buf = hold;
+    return fread(hold, 1, CHUNK, (FILE *)how);
+}
+
+local int outf(void *how, unsigned char *buf, unsigned len)
+{
+    return fwrite(buf, 1, len, (FILE *)how) != len;
+}
+
+/* Decompress a PKWare Compression Library stream from stdin to stdout */
+int main(void)
+{
+    int ret, n;
+
+    /* decompress to stdout */
+    ret = blast(inf, stdin, outf, stdout);
+    if (ret != 0) fprintf(stderr, "blast error: %d\n", ret);
+
+    /* see if there are any leftover bytes */
+    n = 0;
+    while (getchar() != EOF) n++;
+    if (n) fprintf(stderr, "blast warning: %d unused bytes of input\n", n);
+
+    /* return blast() error code */
+    return ret;
+}
+#endif
Index: /trunk/minix/lib/zlib-1.2.3/contrib/blast/blast.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/blast/blast.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/blast/blast.h	(revision 9)
@@ -0,0 +1,71 @@
+/* blast.h -- interface for blast.c
+  Copyright (C) 2003 Mark Adler
+  version 1.1, 16 Feb 2003
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the author be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Mark Adler    madler@alumni.caltech.edu
+ */
+
+
+/*
+ * blast() decompresses the PKWare Data Compression Library (DCL) compressed
+ * format.  It provides the same functionality as the explode() function in
+ * that library.  (Note: PKWare overused the "implode" verb, and the format
+ * used by their library implode() function is completely different and
+ * incompatible with the implode compression method supported by PKZIP.)
+ */
+
+
+typedef unsigned (*blast_in)(void *how, unsigned char **buf);
+typedef int (*blast_out)(void *how, unsigned char *buf, unsigned len);
+/* Definitions for input/output functions passed to blast().  See below for
+ * what the provided functions need to do.
+ */
+
+
+int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow);
+/* Decompress input to output using the provided infun() and outfun() calls.
+ * On success, the return value of blast() is zero.  If there is an error in
+ * the source data, i.e. it is not in the proper format, then a negative value
+ * is returned.  If there is not enough input available or there is not enough
+ * output space, then a positive error is returned.
+ *
+ * The input function is invoked: len = infun(how, &buf), where buf is set by
+ * infun() to point to the input buffer, and infun() returns the number of
+ * available bytes there.  If infun() returns zero, then blast() returns with
+ * an input error.  (blast() only asks for input if it needs it.)  inhow is for
+ * use by the application to pass an input descriptor to infun(), if desired.
+ *
+ * The output function is invoked: err = outfun(how, buf, len), where the bytes
+ * to be written are buf[0..len-1].  If err is not zero, then blast() returns
+ * with an output error.  outfun() is always called with len <= 4096.  outhow
+ * is for use by the application to pass an output descriptor to outfun(), if
+ * desired.
+ *
+ * The return codes are:
+ *
+ *   2:  ran out of input before completing decompression
+ *   1:  output error before completing decompression
+ *   0:  successful decompression
+ *  -1:  literal flag not zero or one
+ *  -2:  dictionary size not in 4..6
+ *  -3:  distance is too far back
+ *
+ * At the bottom of blast.c is an example program that uses blast() that can be
+ * compiled to produce a command-line decompression filter by defining TEST.
+ */
Index: /trunk/minix/lib/zlib-1.2.3/contrib/blast/test.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/blast/test.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/blast/test.txt	(revision 9)
@@ -0,0 +1,1 @@
+AIAIAIAIAIAIA
Index: /trunk/minix/lib/zlib-1.2.3/contrib/delphi/ZLib.pas
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/delphi/ZLib.pas	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/delphi/ZLib.pas	(revision 9)
@@ -0,0 +1,557 @@
+{*******************************************************}
+{                                                       }
+{       Borland Delphi Supplemental Components          }
+{       ZLIB Data Compression Interface Unit            }
+{                                                       }
+{       Copyright (c) 1997,99 Borland Corporation       }
+{                                                       }
+{*******************************************************}
+
+{ Updated for zlib 1.2.x by Cosmin Truta <cosmint@cs.ubbcluj.ro> }
+
+unit ZLib;
+
+interface
+
+uses SysUtils, Classes;
+
+type
+  TAlloc = function (AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
+  TFree = procedure (AppData, Block: Pointer); cdecl;
+
+  // Internal structure.  Ignore.
+  TZStreamRec = packed record
+    next_in: PChar;       // next input byte
+    avail_in: Integer;    // number of bytes available at next_in
+    total_in: Longint;    // total nb of input bytes read so far
+
+    next_out: PChar;      // next output byte should be put here
+    avail_out: Integer;   // remaining free space at next_out
+    total_out: Longint;   // total nb of bytes output so far
+
+    msg: PChar;           // last error message, NULL if no error
+    internal: Pointer;    // not visible by applications
+
+    zalloc: TAlloc;       // used to allocate the internal state
+    zfree: TFree;         // used to free the internal state
+    AppData: Pointer;     // private data object passed to zalloc and zfree
+
+    data_type: Integer;   // best guess about the data type: ascii or binary
+    adler: Longint;       // adler32 value of the uncompressed data
+    reserved: Longint;    // reserved for future use
+  end;
+
+  // Abstract ancestor class
+  TCustomZlibStream = class(TStream)
+  private
+    FStrm: TStream;
+    FStrmPos: Integer;
+    FOnProgress: TNotifyEvent;
+    FZRec: TZStreamRec;
+    FBuffer: array [Word] of Char;
+  protected
+    procedure Progress(Sender: TObject); dynamic;
+    property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
+    constructor Create(Strm: TStream);
+  end;
+
+{ TCompressionStream compresses data on the fly as data is written to it, and
+  stores the compressed data to another stream.
+
+  TCompressionStream is write-only and strictly sequential. Reading from the
+  stream will raise an exception. Using Seek to move the stream pointer
+  will raise an exception.
+
+  Output data is cached internally, written to the output stream only when
+  the internal output buffer is full.  All pending output data is flushed
+  when the stream is destroyed.
+
+  The Position property returns the number of uncompressed bytes of
+  data that have been written to the stream so far.
+
+  CompressionRate returns the on-the-fly percentage by which the original
+  data has been compressed:  (1 - (CompressedBytes / UncompressedBytes)) * 100
+  If raw data size = 100 and compressed data size = 25, the CompressionRate
+  is 75%
+
+  The OnProgress event is called each time the output buffer is filled and
+  written to the output stream.  This is useful for updating a progress
+  indicator when you are writing a large chunk of data to the compression
+  stream in a single call.}
+
+
+  TCompressionLevel = (clNone, clFastest, clDefault, clMax);
+
+  TCompressionStream = class(TCustomZlibStream)
+  private
+    function GetCompressionRate: Single;
+  public
+    constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream);
+    destructor Destroy; override;
+    function Read(var Buffer; Count: Longint): Longint; override;
+    function Write(const Buffer; Count: Longint): Longint; override;
+    function Seek(Offset: Longint; Origin: Word): Longint; override;
+    property CompressionRate: Single read GetCompressionRate;
+    property OnProgress;
+  end;
+
+{ TDecompressionStream decompresses data on the fly as data is read from it.
+
+  Compressed data comes from a separate source stream.  TDecompressionStream
+  is read-only and unidirectional; you can seek forward in the stream, but not
+  backwards.  The special case of setting the stream position to zero is
+  allowed.  Seeking forward decompresses data until the requested position in
+  the uncompressed data has been reached.  Seeking backwards, seeking relative
+  to the end of the stream, requesting the size of the stream, and writing to
+  the stream will raise an exception.
+
+  The Position property returns the number of bytes of uncompressed data that
+  have been read from the stream so far.
+
+  The OnProgress event is called each time the internal input buffer of
+  compressed data is exhausted and the next block is read from the input stream.
+  This is useful for updating a progress indicator when you are reading a
+  large chunk of data from the decompression stream in a single call.}
+
+  TDecompressionStream = class(TCustomZlibStream)
+  public
+    constructor Create(Source: TStream);
+    destructor Destroy; override;
+    function Read(var Buffer; Count: Longint): Longint; override;
+    function Write(const Buffer; Count: Longint): Longint; override;
+    function Seek(Offset: Longint; Origin: Word): Longint; override;
+    property OnProgress;
+  end;
+
+
+
+{ CompressBuf compresses data, buffer to buffer, in one call.
+   In: InBuf = ptr to compressed data
+       InBytes = number of bytes in InBuf
+  Out: OutBuf = ptr to newly allocated buffer containing decompressed data
+       OutBytes = number of bytes in OutBuf   }
+procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
+                      out OutBuf: Pointer; out OutBytes: Integer);
+
+
+{ DecompressBuf decompresses data, buffer to buffer, in one call.
+   In: InBuf = ptr to compressed data
+       InBytes = number of bytes in InBuf
+       OutEstimate = zero, or est. size of the decompressed data
+  Out: OutBuf = ptr to newly allocated buffer containing decompressed data
+       OutBytes = number of bytes in OutBuf   }
+procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
+ OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
+
+{ DecompressToUserBuf decompresses data, buffer to buffer, in one call.
+   In: InBuf = ptr to compressed data
+       InBytes = number of bytes in InBuf
+  Out: OutBuf = ptr to user-allocated buffer to contain decompressed data
+       BufSize = number of bytes in OutBuf   }
+procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
+  const OutBuf: Pointer; BufSize: Integer);
+
+const
+  zlib_version = '1.2.3';
+
+type
+  EZlibError = class(Exception);
+  ECompressionError = class(EZlibError);
+  EDecompressionError = class(EZlibError);
+
+implementation
+
+uses ZLibConst;
+
+const
+  Z_NO_FLUSH      = 0;
+  Z_PARTIAL_FLUSH = 1;
+  Z_SYNC_FLUSH    = 2;
+  Z_FULL_FLUSH    = 3;
+  Z_FINISH        = 4;
+
+  Z_OK            = 0;
+  Z_STREAM_END    = 1;
+  Z_NEED_DICT     = 2;
+  Z_ERRNO         = (-1);
+  Z_STREAM_ERROR  = (-2);
+  Z_DATA_ERROR    = (-3);
+  Z_MEM_ERROR     = (-4);
+  Z_BUF_ERROR     = (-5);
+  Z_VERSION_ERROR = (-6);
+
+  Z_NO_COMPRESSION       =   0;
+  Z_BEST_SPEED           =   1;
+  Z_BEST_COMPRESSION     =   9;
+  Z_DEFAULT_COMPRESSION  = (-1);
+
+  Z_FILTERED            = 1;
+  Z_HUFFMAN_ONLY        = 2;
+  Z_RLE                 = 3;
+  Z_DEFAULT_STRATEGY    = 0;
+
+  Z_BINARY   = 0;
+  Z_ASCII    = 1;
+  Z_UNKNOWN  = 2;
+
+  Z_DEFLATED = 8;
+
+
+{$L adler32.obj}
+{$L compress.obj}
+{$L crc32.obj}
+{$L deflate.obj}
+{$L infback.obj}
+{$L inffast.obj}
+{$L inflate.obj}
+{$L inftrees.obj}
+{$L trees.obj}
+{$L uncompr.obj}
+{$L zutil.obj}
+
+procedure adler32; external;
+procedure compressBound; external;
+procedure crc32; external;
+procedure deflateInit2_; external;
+procedure deflateParams; external;
+
+function _malloc(Size: Integer): Pointer; cdecl;
+begin
+  Result := AllocMem(Size);
+end;
+
+procedure _free(Block: Pointer); cdecl;
+begin
+  FreeMem(Block);
+end;
+
+procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl;
+begin
+  FillChar(P^, count, B);
+end;
+
+procedure _memcpy(dest, source: Pointer; count: Integer); cdecl;
+begin
+  Move(source^, dest^, count);
+end;
+
+
+
+// deflate compresses data
+function deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar;
+  recsize: Integer): Integer; external;
+function deflate(var strm: TZStreamRec; flush: Integer): Integer; external;
+function deflateEnd(var strm: TZStreamRec): Integer; external;
+
+// inflate decompresses data
+function inflateInit_(var strm: TZStreamRec; version: PChar;
+  recsize: Integer): Integer; external;
+function inflate(var strm: TZStreamRec; flush: Integer): Integer; external;
+function inflateEnd(var strm: TZStreamRec): Integer; external;
+function inflateReset(var strm: TZStreamRec): Integer; external;
+
+
+function zlibAllocMem(AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
+begin
+//  GetMem(Result, Items*Size);
+  Result := AllocMem(Items * Size);
+end;
+
+procedure zlibFreeMem(AppData, Block: Pointer); cdecl;
+begin
+  FreeMem(Block);
+end;
+
+{function zlibCheck(code: Integer): Integer;
+begin
+  Result := code;
+  if code < 0 then
+    raise EZlibError.Create('error');    //!!
+end;}
+
+function CCheck(code: Integer): Integer;
+begin
+  Result := code;
+  if code < 0 then
+    raise ECompressionError.Create('error'); //!!
+end;
+
+function DCheck(code: Integer): Integer;
+begin
+  Result := code;
+  if code < 0 then
+    raise EDecompressionError.Create('error');  //!!
+end;
+
+procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
+                      out OutBuf: Pointer; out OutBytes: Integer);
+var
+  strm: TZStreamRec;
+  P: Pointer;
+begin
+  FillChar(strm, sizeof(strm), 0);
+  strm.zalloc := zlibAllocMem;
+  strm.zfree := zlibFreeMem;
+  OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255;
+  GetMem(OutBuf, OutBytes);
+  try
+    strm.next_in := InBuf;
+    strm.avail_in := InBytes;
+    strm.next_out := OutBuf;
+    strm.avail_out := OutBytes;
+    CCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm)));
+    try
+      while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do
+      begin
+        P := OutBuf;
+        Inc(OutBytes, 256);
+        ReallocMem(OutBuf, OutBytes);
+        strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
+        strm.avail_out := 256;
+      end;
+    finally
+      CCheck(deflateEnd(strm));
+    end;
+    ReallocMem(OutBuf, strm.total_out);
+    OutBytes := strm.total_out;
+  except
+    FreeMem(OutBuf);
+    raise
+  end;
+end;
+
+
+procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
+  OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
+var
+  strm: TZStreamRec;
+  P: Pointer;
+  BufInc: Integer;
+begin
+  FillChar(strm, sizeof(strm), 0);
+  strm.zalloc := zlibAllocMem;
+  strm.zfree := zlibFreeMem;
+  BufInc := (InBytes + 255) and not 255;
+  if OutEstimate = 0 then
+    OutBytes := BufInc
+  else
+    OutBytes := OutEstimate;
+  GetMem(OutBuf, OutBytes);
+  try
+    strm.next_in := InBuf;
+    strm.avail_in := InBytes;
+    strm.next_out := OutBuf;
+    strm.avail_out := OutBytes;
+    DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
+    try
+      while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do
+      begin
+        P := OutBuf;
+        Inc(OutBytes, BufInc);
+        ReallocMem(OutBuf, OutBytes);
+        strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
+        strm.avail_out := BufInc;
+      end;
+    finally
+      DCheck(inflateEnd(strm));
+    end;
+    ReallocMem(OutBuf, strm.total_out);
+    OutBytes := strm.total_out;
+  except
+    FreeMem(OutBuf);
+    raise
+  end;
+end;
+
+procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
+  const OutBuf: Pointer; BufSize: Integer);
+var
+  strm: TZStreamRec;
+begin
+  FillChar(strm, sizeof(strm), 0);
+  strm.zalloc := zlibAllocMem;
+  strm.zfree := zlibFreeMem;
+  strm.next_in := InBuf;
+  strm.avail_in := InBytes;
+  strm.next_out := OutBuf;
+  strm.avail_out := BufSize;
+  DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
+  try
+    if DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END then
+      raise EZlibError.CreateRes(@sTargetBufferTooSmall);
+  finally
+    DCheck(inflateEnd(strm));
+  end;
+end;
+
+// TCustomZlibStream
+
+constructor TCustomZLibStream.Create(Strm: TStream);
+begin
+  inherited Create;
+  FStrm := Strm;
+  FStrmPos := Strm.Position;
+  FZRec.zalloc := zlibAllocMem;
+  FZRec.zfree := zlibFreeMem;
+end;
+
+procedure TCustomZLibStream.Progress(Sender: TObject);
+begin
+  if Assigned(FOnProgress) then FOnProgress(Sender);
+end;
+
+
+// TCompressionStream
+
+constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel;
+  Dest: TStream);
+const
+  Levels: array [TCompressionLevel] of ShortInt =
+    (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION);
+begin
+  inherited Create(Dest);
+  FZRec.next_out := FBuffer;
+  FZRec.avail_out := sizeof(FBuffer);
+  CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec)));
+end;
+
+destructor TCompressionStream.Destroy;
+begin
+  FZRec.next_in := nil;
+  FZRec.avail_in := 0;
+  try
+    if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
+    while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END)
+      and (FZRec.avail_out = 0) do
+    begin
+      FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
+      FZRec.next_out := FBuffer;
+      FZRec.avail_out := sizeof(FBuffer);
+    end;
+    if FZRec.avail_out < sizeof(FBuffer) then
+      FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out);
+  finally
+    deflateEnd(FZRec);
+  end;
+  inherited Destroy;
+end;
+
+function TCompressionStream.Read(var Buffer; Count: Longint): Longint;
+begin
+  raise ECompressionError.CreateRes(@sInvalidStreamOp);
+end;
+
+function TCompressionStream.Write(const Buffer; Count: Longint): Longint;
+begin
+  FZRec.next_in := @Buffer;
+  FZRec.avail_in := Count;
+  if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
+  while (FZRec.avail_in > 0) do
+  begin
+    CCheck(deflate(FZRec, 0));
+    if FZRec.avail_out = 0 then
+    begin
+      FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
+      FZRec.next_out := FBuffer;
+      FZRec.avail_out := sizeof(FBuffer);
+      FStrmPos := FStrm.Position;
+      Progress(Self);
+    end;
+  end;
+  Result := Count;
+end;
+
+function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
+begin
+  if (Offset = 0) and (Origin = soFromCurrent) then
+    Result := FZRec.total_in
+  else
+    raise ECompressionError.CreateRes(@sInvalidStreamOp);
+end;
+
+function TCompressionStream.GetCompressionRate: Single;
+begin
+  if FZRec.total_in = 0 then
+    Result := 0
+  else
+    Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0;
+end;
+
+
+// TDecompressionStream
+
+constructor TDecompressionStream.Create(Source: TStream);
+begin
+  inherited Create(Source);
+  FZRec.next_in := FBuffer;
+  FZRec.avail_in := 0;
+  DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec)));
+end;
+
+destructor TDecompressionStream.Destroy;
+begin
+  FStrm.Seek(-FZRec.avail_in, 1);
+  inflateEnd(FZRec);
+  inherited Destroy;
+end;
+
+function TDecompressionStream.Read(var Buffer; Count: Longint): Longint;
+begin
+  FZRec.next_out := @Buffer;
+  FZRec.avail_out := Count;
+  if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
+  while (FZRec.avail_out > 0) do
+  begin
+    if FZRec.avail_in = 0 then
+    begin
+      FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer));
+      if FZRec.avail_in = 0 then
+      begin
+        Result := Count - FZRec.avail_out;
+        Exit;
+      end;
+      FZRec.next_in := FBuffer;
+      FStrmPos := FStrm.Position;
+      Progress(Self);
+    end;
+    CCheck(inflate(FZRec, 0));
+  end;
+  Result := Count;
+end;
+
+function TDecompressionStream.Write(const Buffer; Count: Longint): Longint;
+begin
+  raise EDecompressionError.CreateRes(@sInvalidStreamOp);
+end;
+
+function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
+var
+  I: Integer;
+  Buf: array [0..4095] of Char;
+begin
+  if (Offset = 0) and (Origin = soFromBeginning) then
+  begin
+    DCheck(inflateReset(FZRec));
+    FZRec.next_in := FBuffer;
+    FZRec.avail_in := 0;
+    FStrm.Position := 0;
+    FStrmPos := 0;
+  end
+  else if ( (Offset >= 0) and (Origin = soFromCurrent)) or
+          ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then
+  begin
+    if Origin = soFromBeginning then Dec(Offset, FZRec.total_out);
+    if Offset > 0 then
+    begin
+      for I := 1 to Offset div sizeof(Buf) do
+        ReadBuffer(Buf, sizeof(Buf));
+      ReadBuffer(Buf, Offset mod sizeof(Buf));
+    end;
+  end
+  else
+    raise EDecompressionError.CreateRes(@sInvalidStreamOp);
+  Result := FZRec.total_out;
+end;
+
+
+end.
Index: /trunk/minix/lib/zlib-1.2.3/contrib/delphi/ZLibConst.pas
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/delphi/ZLibConst.pas	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/delphi/ZLibConst.pas	(revision 9)
@@ -0,0 +1,11 @@
+unit ZLibConst;
+
+interface
+
+resourcestring
+  sTargetBufferTooSmall = 'ZLib error: target buffer may be too small';
+  sInvalidStreamOp = 'Invalid stream operation';
+
+implementation
+
+end.
Index: /trunk/minix/lib/zlib-1.2.3/contrib/delphi/readme.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/delphi/readme.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/delphi/readme.txt	(revision 9)
@@ -0,0 +1,76 @@
+
+Overview
+========
+
+This directory contains an update to the ZLib interface unit,
+distributed by Borland as a Delphi supplemental component.
+
+The original ZLib unit is Copyright (c) 1997,99 Borland Corp.,
+and is based on zlib version 1.0.4.  There are a series of bugs
+and security problems associated with that old zlib version, and
+we recommend the users to update their ZLib unit.
+
+
+Summary of modifications
+========================
+
+- Improved makefile, adapted to zlib version 1.2.1.
+
+- Some field types from TZStreamRec are changed from Integer to
+  Longint, for consistency with the zlib.h header, and for 64-bit
+  readiness.
+
+- The zlib_version constant is updated.
+
+- The new Z_RLE strategy has its corresponding symbolic constant.
+
+- The allocation and deallocation functions and function types
+  (TAlloc, TFree, zlibAllocMem and zlibFreeMem) are now cdecl,
+  and _malloc and _free are added as C RTL stubs.  As a result,
+  the original C sources of zlib can be compiled out of the box,
+  and linked to the ZLib unit.
+
+
+Suggestions for improvements
+============================
+
+Currently, the ZLib unit provides only a limited wrapper around
+the zlib library, and much of the original zlib functionality is
+missing.  Handling compressed file formats like ZIP/GZIP or PNG
+cannot be implemented without having this functionality.
+Applications that handle these formats are either using their own,
+duplicated code, or not using the ZLib unit at all.
+
+Here are a few suggestions:
+
+- Checksum class wrappers around adler32() and crc32(), similar
+  to the Java classes that implement the java.util.zip.Checksum
+  interface.
+
+- The ability to read and write raw deflate streams, without the
+  zlib stream header and trailer.  Raw deflate streams are used
+  in the ZIP file format.
+
+- The ability to read and write gzip streams, used in the GZIP
+  file format, and normally produced by the gzip program.
+
+- The ability to select a different compression strategy, useful
+  to PNG and MNG image compression, and to multimedia compression
+  in general.  Besides the compression level
+
+    TCompressionLevel = (clNone, clFastest, clDefault, clMax);
+
+  which, in fact, could have used the 'z' prefix and avoided
+  TColor-like symbols
+
+    TCompressionLevel = (zcNone, zcFastest, zcDefault, zcMax);
+
+  there could be a compression strategy
+
+    TCompressionStrategy = (zsDefault, zsFiltered, zsHuffmanOnly, zsRle);
+
+- ZIP and GZIP stream handling via TStreams.
+
+
+--
+Cosmin Truta <cosmint@cs.ubbcluj.ro>
Index: /trunk/minix/lib/zlib-1.2.3/contrib/delphi/zlibd32.mak
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/delphi/zlibd32.mak	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/delphi/zlibd32.mak	(revision 9)
@@ -0,0 +1,93 @@
+# Makefile for zlib
+# For use with Delphi and C++ Builder under Win32
+# Updated for zlib 1.2.x by Cosmin Truta
+
+# ------------ Borland C++ ------------
+
+# This project uses the Delphi (fastcall/register) calling convention:
+LOC = -DZEXPORT=__fastcall -DZEXPORTVA=__cdecl
+
+CC = bcc32
+LD = bcc32
+AR = tlib
+# do not use "-pr" in CFLAGS
+CFLAGS = -a -d -k- -O2 $(LOC)
+LDFLAGS =
+
+
+# variables
+ZLIB_LIB = zlib.lib
+
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
+OBJ2 = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infback.obj
+OBJP2 = +inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+
+
+# targets
+all: $(ZLIB_LIB) example.exe minigzip.exe
+
+.c.obj:
+	$(CC) -c $(CFLAGS) $*.c
+
+adler32.obj: adler32.c zlib.h zconf.h
+
+compress.obj: compress.c zlib.h zconf.h
+
+crc32.obj: crc32.c zlib.h zconf.h crc32.h
+
+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
+
+gzio.obj: gzio.c zutil.h zlib.h zconf.h
+
+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h
+
+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
+
+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
+
+uncompr.obj: uncompr.c zlib.h zconf.h
+
+zutil.obj: zutil.c zutil.h zlib.h zconf.h
+
+example.obj: example.c zlib.h zconf.h
+
+minigzip.obj: minigzip.c zlib.h zconf.h
+
+
+# For the sake of the old Borland make,
+# the command line is cut to fit in the MS-DOS 128 byte limit:
+$(ZLIB_LIB): $(OBJ1) $(OBJ2)
+	-del $(ZLIB_LIB)
+	$(AR) $(ZLIB_LIB) $(OBJP1)
+	$(AR) $(ZLIB_LIB) $(OBJP2)
+
+
+# testing
+test: example.exe minigzip.exe
+	example
+	echo hello world | minigzip | minigzip -d
+
+example.exe: example.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) example.obj $(ZLIB_LIB)
+
+minigzip.exe: minigzip.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB)
+
+
+# cleanup
+clean:
+	-del *.obj
+	-del *.exe
+	-del *.lib
+	-del *.tds
+	-del zlib.bak
+	-del foo.gz
+
Index: /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib.build
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib.build	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib.build	(revision 9)
@@ -0,0 +1,33 @@
+﻿<?xml version="1.0" encoding="utf-8" ?>
+<project name="DotZLib" default="build" basedir="./DotZLib">
+	<description>A .Net wrapper library around ZLib1.dll</description>
+
+	<property name="nunit.location" value="c:/program files/NUnit V2.1/bin" />
+	<property name="build.root" value="bin" />
+	
+	<property name="debug" value="true" />
+	<property name="nunit" value="true" />
+
+	<property name="build.folder" value="${build.root}/debug/" if="${debug}" />
+	<property name="build.folder" value="${build.root}/release/" unless="${debug}" />
+
+	<target name="clean" description="Remove all generated files">
+		<delete dir="${build.root}" failonerror="false" />
+	</target>
+
+	<target name="build" description="compiles the source code">
+		
+		<mkdir dir="${build.folder}" />
+		<csc target="library" output="${build.folder}DotZLib.dll" debug="${debug}">
+			<references basedir="${nunit.location}">
+				<includes if="${nunit}" name="nunit.framework.dll" />
+			</references>
+			<sources>
+				<includes name="*.cs" />
+				<excludes name="UnitTests.cs" unless="${nunit}" />
+			</sources>
+			<arg value="/d:nunit" if="${nunit}" />
+		</csc>
+	</target>
+
+</project>
Index: /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib.sln
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib.sln	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib.sln	(revision 9)
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotZLib", "DotZLib\DotZLib.csproj", "{BB1EE0B1-1808-46CB-B786-949D91117FC5}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		Debug = Debug
+		Release = Release
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{BB1EE0B1-1808-46CB-B786-949D91117FC5}.Debug.ActiveCfg = Debug|.NET
+		{BB1EE0B1-1808-46CB-B786-949D91117FC5}.Debug.Build.0 = Debug|.NET
+		{BB1EE0B1-1808-46CB-B786-949D91117FC5}.Release.ActiveCfg = Release|.NET
+		{BB1EE0B1-1808-46CB-B786-949D91117FC5}.Release.Build.0 = Release|.NET
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
Index: /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/AssemblyInfo.cs
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/AssemblyInfo.cs	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/AssemblyInfo.cs	(revision 9)
@@ -0,0 +1,58 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("DotZLib")]
+[assembly: AssemblyDescription(".Net bindings for ZLib compression dll 1.2.x")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Henrik Ravn")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("(c) 2004 by Henrik Ravn")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]		
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the 
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing. 
+//
+// Notes: 
+//   (*) If no key is specified, the assembly is not signed.
+//   (*) KeyName refers to a key that has been installed in the Crypto Service
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains
+//       a key.
+//   (*) If the KeyFile and the KeyName values are both specified, the 
+//       following processing occurs:
+//       (1) If the KeyName can be found in the CSP, that key is used.
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key 
+//           in the KeyFile is installed into the CSP and used.
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+//       When specifying the KeyFile, the location of the KeyFile should be
+//       relative to the project output directory which is
+//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+//       located in the project directory, you would specify the AssemblyKeyFile 
+//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+//       documentation for more information on this.
+//
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]
Index: /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/ChecksumImpl.cs
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/ChecksumImpl.cs	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/ChecksumImpl.cs	(revision 9)
@@ -0,0 +1,202 @@
+//
+// © Copyright Henrik Ravn 2004
+//
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+
+namespace DotZLib
+{
+    #region ChecksumGeneratorBase
+    /// <summary>
+    /// Implements the common functionality needed for all <see cref="ChecksumGenerator"/>s
+    /// </summary>
+    /// <example></example>
+    public abstract class ChecksumGeneratorBase : ChecksumGenerator
+    {
+        /// <summary>
+        /// The value of the current checksum
+        /// </summary>
+        protected uint _current;
+
+        /// <summary>
+        /// Initializes a new instance of the checksum generator base - the current checksum is 
+        /// set to zero
+        /// </summary>
+        public ChecksumGeneratorBase()
+        {
+            _current = 0;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the checksum generator basewith a specified value
+        /// </summary>
+        /// <param name="initialValue">The value to set the current checksum to</param>
+        public ChecksumGeneratorBase(uint initialValue)
+        {
+            _current = initialValue;
+        }
+
+        /// <summary>
+        /// Resets the current checksum to zero
+        /// </summary>
+        public void Reset() { _current = 0; }
+
+        /// <summary>
+        /// Gets the current checksum value
+        /// </summary>
+        public uint Value { get { return _current; } }
+
+        /// <summary>
+        /// Updates the current checksum with part of an array of bytes
+        /// </summary>
+        /// <param name="data">The data to update the checksum with</param>
+        /// <param name="offset">Where in <c>data</c> to start updating</param>
+        /// <param name="count">The number of bytes from <c>data</c> to use</param>
+        /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception>
+        /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception>
+        /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception>
+        /// <remarks>All the other <c>Update</c> methods are implmeneted in terms of this one. 
+        /// This is therefore the only method a derived class has to implement</remarks>
+        public abstract void Update(byte[] data, int offset, int count);
+
+        /// <summary>
+        /// Updates the current checksum with an array of bytes.
+        /// </summary>
+        /// <param name="data">The data to update the checksum with</param>
+        public void Update(byte[] data)
+        {
+            Update(data, 0, data.Length);
+        }
+
+        /// <summary>
+        /// Updates the current checksum with the data from a string
+        /// </summary>
+        /// <param name="data">The string to update the checksum with</param>
+        /// <remarks>The characters in the string are converted by the UTF-8 encoding</remarks>
+        public void Update(string data)
+        {
+			Update(Encoding.UTF8.GetBytes(data));
+        }
+
+        /// <summary>
+        /// Updates the current checksum with the data from a string, using a specific encoding
+        /// </summary>
+        /// <param name="data">The string to update the checksum with</param>
+        /// <param name="encoding">The encoding to use</param>
+        public void Update(string data, Encoding encoding)
+        {
+            Update(encoding.GetBytes(data));
+        }
+
+    }
+    #endregion
+
+    #region CRC32
+    /// <summary>
+    /// Implements a CRC32 checksum generator
+    /// </summary>
+    public sealed class CRC32Checksum : ChecksumGeneratorBase    
+    {
+        #region DLL imports
+
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
+        private static extern uint crc32(uint crc, int data, uint length);
+
+        #endregion
+
+        /// <summary>
+        /// Initializes a new instance of the CRC32 checksum generator
+        /// </summary>
+        public CRC32Checksum() : base() {}
+
+        /// <summary>
+        /// Initializes a new instance of the CRC32 checksum generator with a specified value
+        /// </summary>
+        /// <param name="initialValue">The value to set the current checksum to</param>
+        public CRC32Checksum(uint initialValue) : base(initialValue) {}
+
+        /// <summary>
+        /// Updates the current checksum with part of an array of bytes
+        /// </summary>
+        /// <param name="data">The data to update the checksum with</param>
+        /// <param name="offset">Where in <c>data</c> to start updating</param>
+        /// <param name="count">The number of bytes from <c>data</c> to use</param>
+        /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception>
+        /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception>
+        /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception>
+        public override void Update(byte[] data, int offset, int count)
+        {
+            if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
+            if ((offset+count) > data.Length) throw new ArgumentException();
+            GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned);
+            try
+            {
+                _current = crc32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count);
+            }
+            finally
+            {
+                hData.Free();
+            }
+        }
+
+    }
+    #endregion
+
+    #region Adler
+    /// <summary>
+    /// Implements a checksum generator that computes the Adler checksum on data
+    /// </summary>
+    public sealed class AdlerChecksum : ChecksumGeneratorBase    
+    {
+        #region DLL imports
+
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
+        private static extern uint adler32(uint adler, int data, uint length);
+
+        #endregion
+
+        /// <summary>
+        /// Initializes a new instance of the Adler checksum generator
+        /// </summary>
+        public AdlerChecksum() : base() {}
+
+        /// <summary>
+        /// Initializes a new instance of the Adler checksum generator with a specified value
+        /// </summary>
+        /// <param name="initialValue">The value to set the current checksum to</param>
+        public AdlerChecksum(uint initialValue) : base(initialValue) {}
+
+        /// <summary>
+        /// Updates the current checksum with part of an array of bytes
+        /// </summary>
+        /// <param name="data">The data to update the checksum with</param>
+        /// <param name="offset">Where in <c>data</c> to start updating</param>
+        /// <param name="count">The number of bytes from <c>data</c> to use</param>
+        /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception>
+        /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception>
+        /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception>
+        public override void Update(byte[] data, int offset, int count)
+        {
+            if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
+            if ((offset+count) > data.Length) throw new ArgumentException();
+            GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned);
+            try
+            {
+                _current = adler32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count);
+            }
+            finally
+            {
+                hData.Free();
+            }
+        }
+
+    }
+    #endregion
+
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/CircularBuffer.cs
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/CircularBuffer.cs	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/CircularBuffer.cs	(revision 9)
@@ -0,0 +1,83 @@
+//
+// © Copyright Henrik Ravn 2004
+//
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+using System;
+using System.Diagnostics;
+
+namespace DotZLib
+{
+
+	/// <summary>
+	/// This class implements a circular buffer
+	/// </summary>
+	internal class CircularBuffer
+	{
+        #region Private data
+        private int _capacity;
+        private int _head;
+        private int _tail;
+        private int _size;
+        private byte[] _buffer;
+        #endregion
+
+        public CircularBuffer(int capacity)
+        {    
+            Debug.Assert( capacity > 0 );
+            _buffer = new byte[capacity];
+            _capacity = capacity;
+            _head = 0;
+            _tail = 0;
+            _size = 0;
+        }
+
+        public int Size { get { return _size; } }
+
+        public int Put(byte[] source, int offset, int count)
+        {
+            Debug.Assert( count > 0 );
+            int trueCount = Math.Min(count, _capacity - Size);
+            for (int i = 0; i < trueCount; ++i)
+                _buffer[(_tail+i) % _capacity] = source[offset+i];
+            _tail += trueCount;
+            _tail %= _capacity;
+            _size += trueCount;
+            return trueCount;
+        }
+
+        public bool Put(byte b)
+        {
+            if (Size == _capacity) // no room
+                return false;
+            _buffer[_tail++] = b;
+            _tail %= _capacity;
+            ++_size;
+            return true;
+        }
+
+        public int Get(byte[] destination, int offset, int count)
+        {
+            int trueCount = Math.Min(count,Size);
+            for (int i = 0; i < trueCount; ++i)
+                destination[offset + i] = _buffer[(_head+i) % _capacity];
+            _head += trueCount;
+            _head %= _capacity;
+            _size -= trueCount;
+            return trueCount;
+        }
+
+        public int Get()
+        {
+            if (Size == 0)
+                return -1;
+
+            int result = (int)_buffer[_head++ % _capacity];
+            --_size;
+            return result;
+        }
+
+    }
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/CodecBase.cs
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/CodecBase.cs	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/CodecBase.cs	(revision 9)
@@ -0,0 +1,198 @@
+//
+// © Copyright Henrik Ravn 2004
+//
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace DotZLib
+{
+	/// <summary>
+	/// Implements the common functionality needed for all <see cref="Codec"/>s
+	/// </summary>
+	public abstract class CodecBase : Codec, IDisposable
+	{
+
+        #region Data members
+
+        /// <summary>
+        /// Instance of the internal zlib buffer structure that is 
+        /// passed to all functions in the zlib dll
+        /// </summary>
+        internal ZStream _ztream = new ZStream();
+
+        /// <summary>
+        /// True if the object instance has been disposed, false otherwise
+        /// </summary>
+        protected bool _isDisposed = false;
+
+        /// <summary>
+        /// The size of the internal buffers
+        /// </summary>
+        protected const int kBufferSize = 16384;
+
+        private byte[] _outBuffer = new byte[kBufferSize];
+        private byte[] _inBuffer = new byte[kBufferSize];
+
+        private GCHandle _hInput;
+        private GCHandle _hOutput;
+
+        private uint _checksum = 0;
+
+        #endregion
+
+        /// <summary>
+        /// Initializes a new instance of the <c>CodeBase</c> class. 
+        /// </summary>
+		public CodecBase()
+		{
+            try
+            {
+                _hInput = GCHandle.Alloc(_inBuffer, GCHandleType.Pinned);
+                _hOutput = GCHandle.Alloc(_outBuffer, GCHandleType.Pinned);
+            }
+            catch (Exception)
+            {
+                CleanUp(false);
+                throw;
+            }
+        }
+
+
+        #region Codec Members
+
+        /// <summary>
+        /// Occurs when more processed data are available.
+        /// </summary>
+        public event DataAvailableHandler DataAvailable;
+
+        /// <summary>
+        /// Fires the <see cref="DataAvailable"/> event
+        /// </summary>
+        protected void OnDataAvailable()
+        {
+            if (_ztream.total_out > 0)
+            {
+                if (DataAvailable != null)
+                    DataAvailable( _outBuffer, 0, (int)_ztream.total_out); 
+                resetOutput();
+            }
+        }
+
+        /// <summary>
+        /// Adds more data to the codec to be processed.
+        /// </summary>
+        /// <param name="data">Byte array containing the data to be added to the codec</param>
+        /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks>
+        public void Add(byte[] data)
+        {
+            Add(data,0,data.Length);
+        }
+
+        /// <summary>
+        /// Adds more data to the codec to be processed.
+        /// </summary>
+        /// <param name="data">Byte array containing the data to be added to the codec</param>
+        /// <param name="offset">The index of the first byte to add from <c>data</c></param>
+        /// <param name="count">The number of bytes to add</param>
+        /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks>
+        /// <remarks>This must be implemented by a derived class</remarks>
+        public abstract void Add(byte[] data, int offset, int count);
+
+        /// <summary>
+        /// Finishes up any pending data that needs to be processed and handled.
+        /// </summary>
+        /// <remarks>This must be implemented by a derived class</remarks>
+        public abstract void Finish();
+
+        /// <summary>
+        /// Gets the checksum of the data that has been added so far
+        /// </summary>
+        public uint Checksum { get { return _checksum; } }
+
+        #endregion
+
+        #region Destructor & IDisposable stuff
+
+        /// <summary>
+        /// Destroys this instance
+        /// </summary>
+        ~CodecBase()
+        {
+            CleanUp(false);
+        }
+
+        /// <summary>
+        /// Releases any unmanaged resources and calls the <see cref="CleanUp()"/> method of the derived class
+        /// </summary>
+        public void Dispose()
+        {
+            CleanUp(true);
+        }
+
+        /// <summary>
+        /// Performs any codec specific cleanup
+        /// </summary>
+        /// <remarks>This must be implemented by a derived class</remarks>
+        protected abstract void CleanUp();
+
+        // performs the release of the handles and calls the dereived CleanUp()
+        private void CleanUp(bool isDisposing)
+        {
+            if (!_isDisposed)
+            {
+                CleanUp();
+                if (_hInput.IsAllocated)
+                    _hInput.Free();
+                if (_hOutput.IsAllocated)
+                    _hOutput.Free();
+
+                _isDisposed = true;
+            }
+        }
+
+
+        #endregion
+
+        #region Helper methods
+
+        /// <summary>
+        /// Copies a number of bytes to the internal codec buffer - ready for proccesing
+        /// </summary>
+        /// <param name="data">The byte array that contains the data to copy</param>
+        /// <param name="startIndex">The index of the first byte to copy</param>
+        /// <param name="count">The number of bytes to copy from <c>data</c></param>
+        protected void copyInput(byte[] data, int startIndex, int count)
+        {
+            Array.Copy(data, startIndex, _inBuffer,0, count);
+            _ztream.next_in = _hInput.AddrOfPinnedObject();
+            _ztream.total_in = 0;
+            _ztream.avail_in = (uint)count;
+
+        }
+
+        /// <summary>
+        /// Resets the internal output buffers to a known state - ready for processing
+        /// </summary>
+        protected void resetOutput()
+        {
+            _ztream.total_out = 0;
+            _ztream.avail_out = kBufferSize;
+            _ztream.next_out = _hOutput.AddrOfPinnedObject();
+        }
+
+        /// <summary>
+        /// Updates the running checksum property
+        /// </summary>
+        /// <param name="newSum">The new checksum value</param>
+        protected void setChecksum(uint newSum)
+        {
+            _checksum = newSum;
+        }
+        #endregion
+
+    }
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/Deflater.cs
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/Deflater.cs	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/Deflater.cs	(revision 9)
@@ -0,0 +1,106 @@
+//
+// © Copyright Henrik Ravn 2004
+//
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace DotZLib
+{
+
+    /// <summary>
+    /// Implements a data compressor, using the deflate algorithm in the ZLib dll
+    /// </summary>
+	public sealed class Deflater : CodecBase
+	{
+        #region Dll imports
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)]
+        private static extern int deflateInit_(ref ZStream sz, int level, string vs, int size);
+
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
+        private static extern int deflate(ref ZStream sz, int flush);
+
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
+        private static extern int deflateReset(ref ZStream sz);
+
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
+        private static extern int deflateEnd(ref ZStream sz);
+        #endregion
+
+        /// <summary>
+        /// Constructs an new instance of the <c>Deflater</c>
+        /// </summary>
+        /// <param name="level">The compression level to use for this <c>Deflater</c></param>
+		public Deflater(CompressLevel level) : base()
+		{
+            int retval = deflateInit_(ref _ztream, (int)level, Info.Version, Marshal.SizeOf(_ztream));
+            if (retval != 0)
+                throw new ZLibException(retval, "Could not initialize deflater");
+
+            resetOutput();
+		}
+
+        /// <summary>
+        /// Adds more data to the codec to be processed.
+        /// </summary>
+        /// <param name="data">Byte array containing the data to be added to the codec</param>
+        /// <param name="offset">The index of the first byte to add from <c>data</c></param>
+        /// <param name="count">The number of bytes to add</param>
+        /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks>
+        public override void Add(byte[] data, int offset, int count)
+        {
+            if (data == null) throw new ArgumentNullException();
+            if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
+            if ((offset+count) > data.Length) throw new ArgumentException();
+            
+            int total = count;
+            int inputIndex = offset;
+            int err = 0;
+
+            while (err >= 0 && inputIndex < total)
+            {
+                copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize));
+                while (err >= 0 && _ztream.avail_in > 0)
+                {
+                    err = deflate(ref _ztream, (int)FlushTypes.None);
+                    if (err == 0)
+                        while (_ztream.avail_out == 0)
+                        {
+                            OnDataAvailable();
+                            err = deflate(ref _ztream, (int)FlushTypes.None);
+                        }
+                    inputIndex += (int)_ztream.total_in;
+                }
+            }
+            setChecksum( _ztream.adler );
+        }
+
+
+        /// <summary>
+        /// Finishes up any pending data that needs to be processed and handled.
+        /// </summary>
+        public override void Finish()
+        {
+            int err;
+            do 
+            {
+                err = deflate(ref _ztream, (int)FlushTypes.Finish);
+                OnDataAvailable();
+            }
+            while (err == 0);
+            setChecksum( _ztream.adler );
+            deflateReset(ref _ztream);
+            resetOutput();
+        }
+
+        /// <summary>
+        /// Closes the internal zlib deflate stream
+        /// </summary>
+        protected override void CleanUp() { deflateEnd(ref _ztream); }
+
+    }
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/DotZLib.cs
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/DotZLib.cs	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/DotZLib.cs	(revision 9)
@@ -0,0 +1,288 @@
+//
+// © Copyright Henrik Ravn 2004
+//
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+
+
+namespace DotZLib
+{
+
+    #region Internal types
+
+    /// <summary>
+    /// Defines constants for the various flush types used with zlib
+    /// </summary>
+    internal enum FlushTypes 
+    {
+        None,  Partial,  Sync,  Full,  Finish,  Block
+    }
+
+    #region ZStream structure
+    // internal mapping of the zlib zstream structure for marshalling
+    [StructLayoutAttribute(LayoutKind.Sequential, Pack=4, Size=0, CharSet=CharSet.Ansi)]
+    internal struct ZStream
+    {
+        public IntPtr next_in;
+        public uint avail_in;
+        public uint total_in;
+
+        public IntPtr next_out;
+        public uint avail_out;
+        public uint total_out;
+
+        [MarshalAs(UnmanagedType.LPStr)]
+        string msg; 
+        uint state;
+
+        uint zalloc;
+        uint zfree;
+        uint opaque;
+
+        int data_type;
+        public uint adler;
+        uint reserved;
+    }
+
+    #endregion
+    
+    #endregion
+
+    #region Public enums
+    /// <summary>
+    /// Defines constants for the available compression levels in zlib
+    /// </summary>
+    public enum CompressLevel : int
+    {
+        /// <summary>
+        /// The default compression level with a reasonable compromise between compression and speed
+        /// </summary>
+        Default = -1,   
+        /// <summary>
+        /// No compression at all. The data are passed straight through.
+        /// </summary>
+        None = 0,
+        /// <summary>
+        /// The maximum compression rate available.
+        /// </summary>
+        Best = 9,   
+        /// <summary>
+        /// The fastest available compression level.
+        /// </summary>
+        Fastest = 1
+    }
+    #endregion
+
+    #region Exception classes
+    /// <summary>
+    /// The exception that is thrown when an error occurs on the zlib dll
+    /// </summary>
+    public class ZLibException : ApplicationException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ZLibException"/> class with a specified 
+        /// error message and error code
+        /// </summary>
+        /// <param name="errorCode">The zlib error code that caused the exception</param>
+        /// <param name="msg">A message that (hopefully) describes the error</param>
+        public ZLibException(int errorCode, string msg) : base(String.Format("ZLib error {0} {1}", errorCode, msg))
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ZLibException"/> class with a specified 
+        /// error code
+        /// </summary>
+        /// <param name="errorCode">The zlib error code that caused the exception</param>
+        public ZLibException(int errorCode) : base(String.Format("ZLib error {0}", errorCode))
+        {
+        }
+    }
+    #endregion
+
+    #region Interfaces
+
+    /// <summary>
+    /// Declares methods and properties that enables a running checksum to be calculated 
+    /// </summary>
+    public interface ChecksumGenerator
+    {
+        /// <summary>
+        /// Gets the current value of the checksum
+        /// </summary>
+        uint Value { get; }
+
+        /// <summary>
+        /// Clears the current checksum to 0
+        /// </summary>
+        void Reset();
+
+        /// <summary>
+        /// Updates the current checksum with an array of bytes
+        /// </summary>
+        /// <param name="data">The data to update the checksum with</param>
+        void Update(byte[] data);
+
+        /// <summary>
+        /// Updates the current checksum with part of an array of bytes
+        /// </summary>
+        /// <param name="data">The data to update the checksum with</param>
+        /// <param name="offset">Where in <c>data</c> to start updating</param>
+        /// <param name="count">The number of bytes from <c>data</c> to use</param>
+        /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception>
+        /// <exception cref="ArgumentNullException"><c>data</c> is a null reference</exception>
+        /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception>
+        void Update(byte[] data, int offset, int count);
+
+        /// <summary>
+        /// Updates the current checksum with the data from a string
+        /// </summary>
+        /// <param name="data">The string to update the checksum with</param>
+        /// <remarks>The characters in the string are converted by the UTF-8 encoding</remarks>
+        void Update(string data);
+
+        /// <summary>
+        /// Updates the current checksum with the data from a string, using a specific encoding
+        /// </summary>
+        /// <param name="data">The string to update the checksum with</param>
+        /// <param name="encoding">The encoding to use</param>
+        void Update(string data, Encoding encoding);
+    }
+
+
+    /// <summary>
+    /// Represents the method that will be called from a codec when new data
+    /// are available.
+    /// </summary>
+    /// <paramref name="data">The byte array containing the processed data</paramref>
+    /// <paramref name="startIndex">The index of the first processed byte in <c>data</c></paramref>
+    /// <paramref name="count">The number of processed bytes available</paramref>
+    /// <remarks>On return from this method, the data may be overwritten, so grab it while you can. 
+    /// You cannot assume that startIndex will be zero.
+    /// </remarks>
+    public delegate void DataAvailableHandler(byte[] data, int startIndex, int count);
+
+    /// <summary>
+    /// Declares methods and events for implementing compressors/decompressors
+    /// </summary>
+    public interface Codec
+    {
+        /// <summary>
+        /// Occurs when more processed data are available.
+        /// </summary>
+        event DataAvailableHandler DataAvailable;
+
+        /// <summary>
+        /// Adds more data to the codec to be processed.
+        /// </summary>
+        /// <param name="data">Byte array containing the data to be added to the codec</param>
+        /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks>
+        void Add(byte[] data);
+
+        /// <summary>
+        /// Adds more data to the codec to be processed.
+        /// </summary>
+        /// <param name="data">Byte array containing the data to be added to the codec</param>
+        /// <param name="offset">The index of the first byte to add from <c>data</c></param>
+        /// <param name="count">The number of bytes to add</param>
+        /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks>
+        void Add(byte[] data, int offset, int count);
+
+        /// <summary>
+        /// Finishes up any pending data that needs to be processed and handled.
+        /// </summary>
+        void Finish();
+
+        /// <summary>
+        /// Gets the checksum of the data that has been added so far
+        /// </summary>
+        uint Checksum { get; }
+
+
+    }
+
+    #endregion
+
+    #region Classes
+    /// <summary>
+    /// Encapsulates general information about the ZLib library
+    /// </summary>
+    public class Info
+    {
+        #region DLL imports
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
+        private static extern uint zlibCompileFlags();
+
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
+        private static extern string zlibVersion();
+        #endregion
+
+        #region Private stuff
+        private uint _flags;
+
+        // helper function that unpacks a bitsize mask
+        private static int bitSize(uint bits)
+        {
+            switch (bits)
+            {
+                case 0: return 16;
+                case 1: return 32;
+                case 2: return 64;
+            }
+            return -1;
+        }
+        #endregion
+
+        /// <summary>
+        /// Constructs an instance of the <c>Info</c> class.
+        /// </summary>
+        public Info()
+        {
+            _flags = zlibCompileFlags();
+        }
+
+        /// <summary>
+        /// True if the library is compiled with debug info
+        /// </summary>
+        public bool HasDebugInfo { get { return 0 != (_flags & 0x100); } }
+
+        /// <summary>
+        /// True if the library is compiled with assembly optimizations
+        /// </summary>
+        public bool UsesAssemblyCode { get { return 0 != (_flags & 0x200); } }
+
+        /// <summary>
+        /// Gets the size of the unsigned int that was compiled into Zlib
+        /// </summary>
+        public int SizeOfUInt { get { return bitSize(_flags & 3); } }
+
+        /// <summary>
+        /// Gets the size of the unsigned long that was compiled into Zlib
+        /// </summary>
+        public int SizeOfULong { get { return bitSize((_flags >> 2) & 3); } }
+
+        /// <summary>
+        /// Gets the size of the pointers that were compiled into Zlib
+        /// </summary>
+        public int SizeOfPointer { get { return bitSize((_flags >> 4) & 3); } }
+
+        /// <summary>
+        /// Gets the size of the z_off_t type that was compiled into Zlib
+        /// </summary>
+        public int SizeOfOffset { get { return bitSize((_flags >> 6) & 3); } }
+
+        /// <summary>
+        /// Gets the version of ZLib as a string, e.g. "1.2.1"
+        /// </summary>
+        public static string Version { get { return zlibVersion(); } }
+    }
+
+    #endregion
+
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/DotZLib.csproj
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/DotZLib.csproj	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/DotZLib.csproj	(revision 9)
@@ -0,0 +1,141 @@
+<VisualStudioProject>
+    <CSHARP
+        ProjectType = "Local"
+        ProductVersion = "7.10.3077"
+        SchemaVersion = "2.0"
+        ProjectGuid = "{BB1EE0B1-1808-46CB-B786-949D91117FC5}"
+    >
+        <Build>
+            <Settings
+                ApplicationIcon = ""
+                AssemblyKeyContainerName = ""
+                AssemblyName = "DotZLib"
+                AssemblyOriginatorKeyFile = ""
+                DefaultClientScript = "JScript"
+                DefaultHTMLPageLayout = "Grid"
+                DefaultTargetSchema = "IE50"
+                DelaySign = "false"
+                OutputType = "Library"
+                PreBuildEvent = ""
+                PostBuildEvent = ""
+                RootNamespace = "DotZLib"
+                RunPostBuildEvent = "OnBuildSuccess"
+                StartupObject = ""
+            >
+                <Config
+                    Name = "Debug"
+                    AllowUnsafeBlocks = "false"
+                    BaseAddress = "285212672"
+                    CheckForOverflowUnderflow = "false"
+                    ConfigurationOverrideFile = ""
+                    DefineConstants = "DEBUG;TRACE"
+                    DocumentationFile = "docs\DotZLib.xml"
+                    DebugSymbols = "true"
+                    FileAlignment = "4096"
+                    IncrementalBuild = "false"
+                    NoStdLib = "false"
+                    NoWarn = "1591"
+                    Optimize = "false"
+                    OutputPath = "bin\Debug\"
+                    RegisterForComInterop = "false"
+                    RemoveIntegerChecks = "false"
+                    TreatWarningsAsErrors = "false"
+                    WarningLevel = "4"
+                />
+                <Config
+                    Name = "Release"
+                    AllowUnsafeBlocks = "false"
+                    BaseAddress = "285212672"
+                    CheckForOverflowUnderflow = "false"
+                    ConfigurationOverrideFile = ""
+                    DefineConstants = "TRACE"
+                    DocumentationFile = "docs\DotZLib.xml"
+                    DebugSymbols = "false"
+                    FileAlignment = "4096"
+                    IncrementalBuild = "false"
+                    NoStdLib = "false"
+                    NoWarn = ""
+                    Optimize = "true"
+                    OutputPath = "bin\Release\"
+                    RegisterForComInterop = "false"
+                    RemoveIntegerChecks = "false"
+                    TreatWarningsAsErrors = "false"
+                    WarningLevel = "4"
+                />
+            </Settings>
+            <References>
+                <Reference
+                    Name = "System"
+                    AssemblyName = "System"
+                    HintPath = "C:\WINNT\Microsoft.NET\Framework\v1.1.4322\System.dll"
+                />
+                <Reference
+                    Name = "System.Data"
+                    AssemblyName = "System.Data"
+                    HintPath = "C:\WINNT\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
+                />
+                <Reference
+                    Name = "System.XML"
+                    AssemblyName = "System.Xml"
+                    HintPath = "C:\WINNT\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
+                />
+                <Reference
+                    Name = "nunit.framework"
+                    AssemblyName = "nunit.framework"
+                    HintPath = "E:\apps\NUnit V2.1\\bin\nunit.framework.dll"
+                    AssemblyFolderKey = "hklm\dn\nunit.framework"
+                />
+            </References>
+        </Build>
+        <Files>
+            <Include>
+                <File
+                    RelPath = "AssemblyInfo.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "ChecksumImpl.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "CircularBuffer.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "CodecBase.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "Deflater.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "DotZLib.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "GZipStream.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "Inflater.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "UnitTests.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+            </Include>
+        </Files>
+    </CSHARP>
+</VisualStudioProject>
+
Index: /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/GZipStream.cs
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/GZipStream.cs	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/GZipStream.cs	(revision 9)
@@ -0,0 +1,301 @@
+//
+// © Copyright Henrik Ravn 2004
+//
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace DotZLib
+{
+	/// <summary>
+	/// Implements a compressed <see cref="Stream"/>, in GZip (.gz) format.
+	/// </summary>
+	public class GZipStream : Stream, IDisposable
+	{
+        #region Dll Imports
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)]
+        private static extern IntPtr gzopen(string name, string mode);
+
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
+        private static extern int gzclose(IntPtr gzFile);
+
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
+        private static extern int gzwrite(IntPtr gzFile, int data, int length);
+
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
+        private static extern int gzread(IntPtr gzFile, int data, int length);
+
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
+        private static extern int gzgetc(IntPtr gzFile);
+
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
+        private static extern int gzputc(IntPtr gzFile, int c);
+
+        #endregion
+
+        #region Private data
+        private IntPtr _gzFile;
+        private bool _isDisposed = false;
+        private bool _isWriting;
+        #endregion
+
+        #region Constructors
+        /// <summary>
+        /// Creates a new file as a writeable GZipStream
+        /// </summary>
+        /// <param name="fileName">The name of the compressed file to create</param>
+        /// <param name="level">The compression level to use when adding data</param>
+        /// <exception cref="ZLibException">If an error occurred in the internal zlib function</exception>
+		public GZipStream(string fileName, CompressLevel level)
+		{
+            _isWriting = true;
+            _gzFile = gzopen(fileName, String.Format("wb{0}", (int)level));
+            if (_gzFile == IntPtr.Zero)
+                throw new ZLibException(-1, "Could not open " + fileName);
+		}
+
+        /// <summary>
+        /// Opens an existing file as a readable GZipStream
+        /// </summary>
+        /// <param name="fileName">The name of the file to open</param>
+        /// <exception cref="ZLibException">If an error occurred in the internal zlib function</exception>
+        public GZipStream(string fileName)
+        {
+            _isWriting = false;
+            _gzFile = gzopen(fileName, "rb");
+            if (_gzFile == IntPtr.Zero)
+                throw new ZLibException(-1, "Could not open " + fileName);
+
+        }
+        #endregion
+
+        #region Access properties
+        /// <summary>
+        /// Returns true of this stream can be read from, false otherwise
+        /// </summary>
+        public override bool CanRead
+        {
+            get
+            {
+                return !_isWriting;
+            }
+        }
+    
+
+        /// <summary>
+        /// Returns false.
+        /// </summary>
+        public override bool CanSeek
+        {
+            get
+            {
+                return false;
+            }
+        }
+    
+        /// <summary>
+        /// Returns true if this tsream is writeable, false otherwise
+        /// </summary>
+        public override bool CanWrite
+        {
+            get
+            {
+                return _isWriting;
+            }
+        }
+        #endregion
+    
+        #region Destructor & IDispose stuff
+
+        /// <summary>
+        /// Destroys this instance
+        /// </summary>
+        ~GZipStream()
+        {
+            cleanUp(false);
+        }
+
+        /// <summary>
+        /// Closes the external file handle
+        /// </summary>
+        public void Dispose()
+        {
+            cleanUp(true);
+        }
+
+        // Does the actual closing of the file handle.
+        private void cleanUp(bool isDisposing)
+        {
+            if (!_isDisposed)
+            {
+                gzclose(_gzFile);
+                _isDisposed = true;
+            }
+        }
+        #endregion
+    
+        #region Basic reading and writing
+        /// <summary>
+        /// Attempts to read a number of bytes from the stream.
+        /// </summary>
+        /// <param name="buffer">The destination data buffer</param>
+        /// <param name="offset">The index of the first destination byte in <c>buffer</c></param>
+        /// <param name="count">The number of bytes requested</param>
+        /// <returns>The number of bytes read</returns>
+        /// <exception cref="ArgumentNullException">If <c>buffer</c> is null</exception>
+        /// <exception cref="ArgumentOutOfRangeException">If <c>count</c> or <c>offset</c> are negative</exception>
+        /// <exception cref="ArgumentException">If <c>offset</c>  + <c>count</c> is &gt; buffer.Length</exception>
+        /// <exception cref="NotSupportedException">If this stream is not readable.</exception>
+        /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception>
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            if (!CanRead) throw new NotSupportedException();
+            if (buffer == null) throw new ArgumentNullException();
+            if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
+            if ((offset+count) > buffer.Length) throw new ArgumentException();
+            if (_isDisposed) throw new ObjectDisposedException("GZipStream");
+
+            GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+            int result;
+            try
+            {
+                result = gzread(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count);
+                if (result < 0)
+                    throw new IOException();
+            }
+            finally
+            {
+                h.Free();
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// Attempts to read a single byte from the stream.
+        /// </summary>
+        /// <returns>The byte that was read, or -1 in case of error or End-Of-File</returns>
+        public override int ReadByte()
+        {
+            if (!CanRead) throw new NotSupportedException();
+            if (_isDisposed) throw new ObjectDisposedException("GZipStream");
+            return gzgetc(_gzFile);
+        }
+
+        /// <summary>
+        /// Writes a number of bytes to the stream
+        /// </summary>
+        /// <param name="buffer"></param>
+        /// <param name="offset"></param>
+        /// <param name="count"></param>
+        /// <exception cref="ArgumentNullException">If <c>buffer</c> is null</exception>
+        /// <exception cref="ArgumentOutOfRangeException">If <c>count</c> or <c>offset</c> are negative</exception>
+        /// <exception cref="ArgumentException">If <c>offset</c>  + <c>count</c> is &gt; buffer.Length</exception>
+        /// <exception cref="NotSupportedException">If this stream is not writeable.</exception>
+        /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception>
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            if (!CanWrite) throw new NotSupportedException();
+            if (buffer == null) throw new ArgumentNullException();
+            if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
+            if ((offset+count) > buffer.Length) throw new ArgumentException();
+            if (_isDisposed) throw new ObjectDisposedException("GZipStream");
+
+            GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+            try
+            {
+                int result = gzwrite(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count);
+                if (result < 0)
+                    throw new IOException();
+            }
+            finally
+            {
+                h.Free();
+            }
+        }
+
+        /// <summary>
+        /// Writes a single byte to the stream
+        /// </summary>
+        /// <param name="value">The byte to add to the stream.</param>
+        /// <exception cref="NotSupportedException">If this stream is not writeable.</exception>
+        /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception>
+        public override void WriteByte(byte value)
+        {
+            if (!CanWrite) throw new NotSupportedException();
+            if (_isDisposed) throw new ObjectDisposedException("GZipStream");
+
+            int result = gzputc(_gzFile, (int)value);
+            if (result < 0)
+                throw new IOException();
+        }
+        #endregion
+
+        #region Position & length stuff
+        /// <summary>
+        /// Not supported.
+        /// </summary>
+        /// <param name="value"></param>
+        /// <exception cref="NotSupportedException">Always thrown</exception>
+        public override void SetLength(long value)
+        {
+            throw new NotSupportedException();
+        }
+    
+        /// <summary>
+        ///  Not suppported.
+        /// </summary>
+        /// <param name="offset"></param>
+        /// <param name="origin"></param>
+        /// <returns></returns>
+        /// <exception cref="NotSupportedException">Always thrown</exception>
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            throw new NotSupportedException();
+        }
+    
+        /// <summary>
+        /// Flushes the <c>GZipStream</c>.
+        /// </summary>
+        /// <remarks>In this implementation, this method does nothing. This is because excessive
+        /// flushing may degrade the achievable compression rates.</remarks>
+        public override void Flush()
+        {
+            // left empty on purpose
+        }
+    
+        /// <summary>
+        /// Gets/sets the current position in the <c>GZipStream</c>. Not suppported.
+        /// </summary>
+        /// <remarks>In this implementation this property is not supported</remarks>
+        /// <exception cref="NotSupportedException">Always thrown</exception>
+        public override long Position
+        {
+            get
+            {
+                throw new NotSupportedException();
+            }
+            set
+            {
+                throw new NotSupportedException();
+            }
+        }
+    
+        /// <summary>
+        /// Gets the size of the stream. Not suppported.
+        /// </summary>
+        /// <remarks>In this implementation this property is not supported</remarks>
+        /// <exception cref="NotSupportedException">Always thrown</exception>
+        public override long Length
+        {
+            get
+            {
+                throw new NotSupportedException();
+            }
+        }
+        #endregion
+    }
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/Inflater.cs
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/Inflater.cs	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/Inflater.cs	(revision 9)
@@ -0,0 +1,105 @@
+//
+// © Copyright Henrik Ravn 2004
+//
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace DotZLib
+{
+    
+    /// <summary>
+    /// Implements a data decompressor, using the inflate algorithm in the ZLib dll
+    /// </summary>
+    public class Inflater : CodecBase
+	{
+        #region Dll imports
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)]
+        private static extern int inflateInit_(ref ZStream sz, string vs, int size);
+
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
+        private static extern int inflate(ref ZStream sz, int flush);
+
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
+        private static extern int inflateReset(ref ZStream sz);
+
+        [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
+        private static extern int inflateEnd(ref ZStream sz);
+        #endregion
+
+        /// <summary>
+        /// Constructs an new instance of the <c>Inflater</c>
+        /// </summary>
+        public Inflater() : base()
+		{
+            int retval = inflateInit_(ref _ztream, Info.Version, Marshal.SizeOf(_ztream));
+            if (retval != 0)
+                throw new ZLibException(retval, "Could not initialize inflater");
+
+            resetOutput();
+        }
+
+
+        /// <summary>
+        /// Adds more data to the codec to be processed.
+        /// </summary>
+        /// <param name="data">Byte array containing the data to be added to the codec</param>
+        /// <param name="offset">The index of the first byte to add from <c>data</c></param>
+        /// <param name="count">The number of bytes to add</param>
+        /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks>
+        public override void Add(byte[] data, int offset, int count)
+        {
+            if (data == null) throw new ArgumentNullException();
+            if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
+            if ((offset+count) > data.Length) throw new ArgumentException();
+
+            int total = count;
+            int inputIndex = offset;
+            int err = 0;
+
+            while (err >= 0 && inputIndex < total)
+            {
+                copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize));
+                err = inflate(ref _ztream, (int)FlushTypes.None);
+                if (err == 0)
+                    while (_ztream.avail_out == 0)
+                    {
+                        OnDataAvailable();
+                        err = inflate(ref _ztream, (int)FlushTypes.None);
+                    }
+
+                inputIndex += (int)_ztream.total_in;
+            }
+            setChecksum( _ztream.adler );
+        }
+
+
+        /// <summary>
+        /// Finishes up any pending data that needs to be processed and handled.
+        /// </summary>
+        public override void Finish()
+        {
+            int err;
+            do 
+            {
+                err = inflate(ref _ztream, (int)FlushTypes.Finish);
+                OnDataAvailable();
+            }
+            while (err == 0);
+            setChecksum( _ztream.adler );
+            inflateReset(ref _ztream);
+            resetOutput();
+        }
+
+        /// <summary>
+        /// Closes the internal zlib inflate stream
+        /// </summary>
+        protected override void CleanUp() { inflateEnd(ref _ztream); }
+
+
+	}
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/UnitTests.cs
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/UnitTests.cs	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/DotZLib/UnitTests.cs	(revision 9)
@@ -0,0 +1,274 @@
+//
+// © Copyright Henrik Ravn 2004
+//
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+using System;
+using System.Collections;
+using System.IO;
+
+// uncomment the define below to include unit tests
+//#define nunit
+#if nunit
+using NUnit.Framework;
+
+// Unit tests for the DotZLib class library
+// ----------------------------------------
+//
+// Use this with NUnit 2 from http://www.nunit.org
+//
+
+namespace DotZLibTests
+{
+    using DotZLib;
+
+    // helper methods
+    internal class Utils
+    {
+        public static bool byteArrEqual( byte[] lhs, byte[] rhs )
+        {
+            if (lhs.Length != rhs.Length)
+                return false;
+            for (int i = lhs.Length-1; i >= 0; --i)
+                if (lhs[i] != rhs[i])
+                    return false;
+            return true;
+        }
+
+    }
+
+
+    [TestFixture]
+    public class CircBufferTests
+    {
+        #region Circular buffer tests
+        [Test]
+        public void SinglePutGet()
+        {
+            CircularBuffer buf = new CircularBuffer(10);
+            Assert.AreEqual( 0, buf.Size );
+            Assert.AreEqual( -1, buf.Get() );
+
+            Assert.IsTrue(buf.Put( 1 ));
+            Assert.AreEqual( 1, buf.Size );
+            Assert.AreEqual( 1, buf.Get() );
+            Assert.AreEqual( 0, buf.Size );
+            Assert.AreEqual( -1, buf.Get() );
+        }
+
+        [Test]
+        public void BlockPutGet()
+        {
+            CircularBuffer buf = new CircularBuffer(10);
+            byte[] arr = {1,2,3,4,5,6,7,8,9,10};
+            Assert.AreEqual( 10, buf.Put(arr,0,10) );
+            Assert.AreEqual( 10, buf.Size );
+            Assert.IsFalse( buf.Put(11) );
+            Assert.AreEqual( 1, buf.Get() );
+            Assert.IsTrue( buf.Put(11) );
+
+            byte[] arr2 = (byte[])arr.Clone();
+            Assert.AreEqual( 9, buf.Get(arr2,1,9) );
+            Assert.IsTrue( Utils.byteArrEqual(arr,arr2) );
+        }
+
+        #endregion
+    }
+
+    [TestFixture]
+    public class ChecksumTests
+    {
+        #region CRC32 Tests
+        [Test]
+        public void CRC32_Null()
+        {
+            CRC32Checksum crc32 = new CRC32Checksum();
+            Assert.AreEqual( 0, crc32.Value );
+
+            crc32 = new CRC32Checksum(1);
+            Assert.AreEqual( 1, crc32.Value );
+
+            crc32 = new CRC32Checksum(556);
+            Assert.AreEqual( 556, crc32.Value );
+        }
+
+        [Test]
+        public void CRC32_Data()
+        {
+            CRC32Checksum crc32 = new CRC32Checksum();
+            byte[] data = { 1,2,3,4,5,6,7 };
+            crc32.Update(data);
+            Assert.AreEqual( 0x70e46888, crc32.Value  );
+
+            crc32 = new CRC32Checksum();
+            crc32.Update("penguin");
+            Assert.AreEqual( 0x0e5c1a120, crc32.Value );
+
+            crc32 = new CRC32Checksum(1);
+            crc32.Update("penguin");
+            Assert.AreEqual(0x43b6aa94, crc32.Value);
+
+        }
+        #endregion
+
+        #region Adler tests
+
+        [Test]
+        public void Adler_Null()
+        {
+            AdlerChecksum adler = new AdlerChecksum();
+            Assert.AreEqual(0, adler.Value);
+
+            adler = new AdlerChecksum(1);
+            Assert.AreEqual( 1, adler.Value );
+
+            adler = new AdlerChecksum(556);
+            Assert.AreEqual( 556, adler.Value );
+        }
+
+        [Test]
+        public void Adler_Data()
+        {
+            AdlerChecksum adler = new AdlerChecksum(1);
+            byte[] data = { 1,2,3,4,5,6,7 };
+            adler.Update(data);
+            Assert.AreEqual( 0x5b001d, adler.Value  );
+
+            adler = new AdlerChecksum();
+            adler.Update("penguin");
+            Assert.AreEqual(0x0bcf02f6, adler.Value );
+
+            adler = new AdlerChecksum(1);
+            adler.Update("penguin");
+            Assert.AreEqual(0x0bd602f7, adler.Value);
+
+        }
+        #endregion
+    }
+
+    [TestFixture]
+    public class InfoTests
+    {
+        #region Info tests
+        [Test]
+        public void Info_Version()
+        {
+            Info info = new Info();
+            Assert.AreEqual("1.2.3", Info.Version);
+            Assert.AreEqual(32, info.SizeOfUInt);
+            Assert.AreEqual(32, info.SizeOfULong);
+            Assert.AreEqual(32, info.SizeOfPointer);
+            Assert.AreEqual(32, info.SizeOfOffset);
+        }
+        #endregion
+    }
+
+    [TestFixture]
+    public class DeflateInflateTests
+    {
+        #region Deflate tests
+        [Test]
+        public void Deflate_Init()
+        {
+            using (Deflater def = new Deflater(CompressLevel.Default))
+            {
+            }
+        }
+
+        private ArrayList compressedData = new ArrayList();
+        private uint adler1;
+
+        private ArrayList uncompressedData = new ArrayList();
+        private uint adler2;
+
+        public void CDataAvail(byte[] data, int startIndex, int count)
+        {
+            for (int i = 0; i < count; ++i)
+                compressedData.Add(data[i+startIndex]);
+        }
+
+        [Test]
+        public void Deflate_Compress()
+        {
+            compressedData.Clear();
+
+            byte[] testData = new byte[35000];
+            for (int i = 0; i < testData.Length; ++i)
+                testData[i] = 5;
+
+            using (Deflater def = new Deflater((CompressLevel)5))
+            {
+                def.DataAvailable += new DataAvailableHandler(CDataAvail);
+                def.Add(testData);
+                def.Finish();
+                adler1 = def.Checksum;
+            }
+        }
+        #endregion
+
+        #region Inflate tests
+        [Test]
+        public void Inflate_Init()
+        {
+            using (Inflater inf = new Inflater())
+            {
+            }
+        }
+
+        private void DDataAvail(byte[] data, int startIndex, int count)
+        {
+            for (int i = 0; i < count; ++i)
+                uncompressedData.Add(data[i+startIndex]);
+        }
+
+        [Test]
+        public void Inflate_Expand()
+        { 
+            uncompressedData.Clear();
+
+            using (Inflater inf = new Inflater())
+            {
+                inf.DataAvailable += new DataAvailableHandler(DDataAvail);
+                inf.Add((byte[])compressedData.ToArray(typeof(byte)));
+                inf.Finish();
+                adler2 = inf.Checksum;
+            }
+            Assert.AreEqual( adler1, adler2 );
+        }
+        #endregion
+    }
+
+    [TestFixture]
+    public class GZipStreamTests
+    {
+        #region GZipStream test
+        [Test]
+        public void GZipStream_WriteRead()
+        {
+            using (GZipStream gzOut = new GZipStream("gzstream.gz", CompressLevel.Best))
+            {
+                BinaryWriter writer = new BinaryWriter(gzOut);
+                writer.Write("hi there");
+                writer.Write(Math.PI);
+                writer.Write(42);
+            }
+
+            using (GZipStream gzIn = new GZipStream("gzstream.gz"))
+            {
+                BinaryReader reader = new BinaryReader(gzIn);
+                string s = reader.ReadString();
+                Assert.AreEqual("hi there",s);
+                double d = reader.ReadDouble();
+                Assert.AreEqual(Math.PI, d);
+                int i = reader.ReadInt32();
+                Assert.AreEqual(42,i);
+            }
+
+        }
+        #endregion
+	}
+}
+
+#endif
Index: /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/LICENSE_1_0.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/LICENSE_1_0.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/LICENSE_1_0.txt	(revision 9)
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
Index: /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/readme.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/readme.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/dotzlib/readme.txt	(revision 9)
@@ -0,0 +1,58 @@
+This directory contains a .Net wrapper class library for the ZLib1.dll
+
+The wrapper includes support for inflating/deflating memory buffers, 
+.Net streaming wrappers for the gz streams part of zlib, and wrappers
+for the checksum parts of zlib. See DotZLib/UnitTests.cs for examples.
+
+Directory structure:
+--------------------
+
+LICENSE_1_0.txt       - License file.
+readme.txt            - This file.
+DotZLib.chm           - Class library documentation
+DotZLib.build         - NAnt build file
+DotZLib.sln           - Microsoft Visual Studio 2003 solution file
+
+DotZLib\*.cs          - Source files for the class library
+
+Unit tests:
+-----------
+The file DotZLib/UnitTests.cs contains unit tests for use with NUnit 2.1 or higher.
+To include unit tests in the build, define nunit before building.
+
+
+Build instructions:
+-------------------
+
+1. Using Visual Studio.Net 2003:
+   Open DotZLib.sln in VS.Net and build from there. Output file (DotZLib.dll)
+   will be found ./DotZLib/bin/release or ./DotZLib/bin/debug, depending on 
+   you are building the release or debug version of the library. Check 
+   DotZLib/UnitTests.cs for instructions on how to include unit tests in the
+   build.
+   
+2. Using NAnt:
+   Open a command prompt with access to the build environment and run nant
+   in the same directory as the DotZLib.build file.
+   You can define 2 properties on the nant command-line to control the build:
+   debug={true|false} to toggle between release/debug builds (default=true).
+   nunit={true|false} to include or esclude unit tests (default=true).
+   Also the target clean will remove binaries.
+   Output file (DotZLib.dll) will be found in either ./DotZLib/bin/release 
+   or ./DotZLib/bin/debug, depending on whether you are building the release 
+   or debug version of the library.
+
+   Examples: 
+     nant -D:debug=false -D:nunit=false
+       will build a release mode version of the library without unit tests.
+     nant
+       will build a debug version of the library with unit tests 
+     nant clean
+       will remove all previously built files.
+
+
+---------------------------------
+Copyright (c) Henrik Ravn 2004
+
+Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Index: /trunk/minix/lib/zlib-1.2.3/contrib/infback9/README
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/infback9/README	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/infback9/README	(revision 9)
@@ -0,0 +1,1 @@
+See infback9.h for what this is and how to use it.
Index: /trunk/minix/lib/zlib-1.2.3/contrib/infback9/infback9.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/infback9/infback9.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/infback9/infback9.c	(revision 9)
@@ -0,0 +1,608 @@
+/* infback9.c -- inflate deflate64 data using a call-back interface
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infback9.h"
+#include "inftree9.h"
+#include "inflate9.h"
+
+#define WSIZE 65536UL
+
+/*
+   strm provides memory allocation functions in zalloc and zfree, or
+   Z_NULL to use the library memory allocation functions.
+
+   window is a user-supplied window and output buffer that is 64K bytes.
+ */
+int ZEXPORT inflateBack9Init_(strm, window, version, stream_size)
+z_stream FAR *strm;
+unsigned char FAR *window;
+const char *version;
+int stream_size;
+{
+    struct inflate_state FAR *state;
+
+    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+        stream_size != (int)(sizeof(z_stream)))
+        return Z_VERSION_ERROR;
+    if (strm == Z_NULL || window == Z_NULL)
+        return Z_STREAM_ERROR;
+    strm->msg = Z_NULL;                 /* in case we return an error */
+    if (strm->zalloc == (alloc_func)0) {
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
+                                               sizeof(struct inflate_state));
+    if (state == Z_NULL) return Z_MEM_ERROR;
+    Tracev((stderr, "inflate: allocated\n"));
+    strm->state = (voidpf)state;
+    state->window = window;
+    return Z_OK;
+}
+
+/*
+   Build and output length and distance decoding tables for fixed code
+   decoding.
+ */
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+void makefixed9(void)
+{
+    unsigned sym, bits, low, size;
+    code *next, *lenfix, *distfix;
+    struct inflate_state state;
+    code fixed[544];
+
+    /* literal/length table */
+    sym = 0;
+    while (sym < 144) state.lens[sym++] = 8;
+    while (sym < 256) state.lens[sym++] = 9;
+    while (sym < 280) state.lens[sym++] = 7;
+    while (sym < 288) state.lens[sym++] = 8;
+    next = fixed;
+    lenfix = next;
+    bits = 9;
+    inflate_table9(LENS, state.lens, 288, &(next), &(bits), state.work);
+
+    /* distance table */
+    sym = 0;
+    while (sym < 32) state.lens[sym++] = 5;
+    distfix = next;
+    bits = 5;
+    inflate_table9(DISTS, state.lens, 32, &(next), &(bits), state.work);
+
+    /* write tables */
+    puts("    /* inffix9.h -- table for decoding deflate64 fixed codes");
+    puts("     * Generated automatically by makefixed9().");
+    puts("     */");
+    puts("");
+    puts("    /* WARNING: this file should *not* be used by applications.");
+    puts("       It is part of the implementation of this library and is");
+    puts("       subject to change. Applications should only use zlib.h.");
+    puts("     */");
+    puts("");
+    size = 1U << 9;
+    printf("    static const code lenfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 6) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", lenfix[low].op, lenfix[low].bits,
+               lenfix[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+    size = 1U << 5;
+    printf("\n    static const code distfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 5) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", distfix[low].op, distfix[low].bits,
+               distfix[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+}
+#endif /* MAKEFIXED */
+
+/* Macros for inflateBack(): */
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+    do { \
+        hold = 0; \
+        bits = 0; \
+    } while (0)
+
+/* Assure that some input is available.  If input is requested, but denied,
+   then return a Z_BUF_ERROR from inflateBack(). */
+#define PULL() \
+    do { \
+        if (have == 0) { \
+            have = in(in_desc, &next); \
+            if (have == 0) { \
+                next = Z_NULL; \
+                ret = Z_BUF_ERROR; \
+                goto inf_leave; \
+            } \
+        } \
+    } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflateBack()
+   with an error if there is no input available. */
+#define PULLBYTE() \
+    do { \
+        PULL(); \
+        have--; \
+        hold += (unsigned long)(*next++) << bits; \
+        bits += 8; \
+    } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator.  If there is
+   not enough available input to do that, then return from inflateBack() with
+   an error. */
+#define NEEDBITS(n) \
+    do { \
+        while (bits < (unsigned)(n)) \
+            PULLBYTE(); \
+    } while (0)
+
+/* Return the low n bits of the bit accumulator (n <= 16) */
+#define BITS(n) \
+    ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+    do { \
+        hold >>= (n); \
+        bits -= (unsigned)(n); \
+    } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+    do { \
+        hold >>= bits & 7; \
+        bits -= bits & 7; \
+    } while (0)
+
+/* Assure that some output space is available, by writing out the window
+   if it's full.  If the write fails, return from inflateBack() with a
+   Z_BUF_ERROR. */
+#define ROOM() \
+    do { \
+        if (left == 0) { \
+            put = window; \
+            left = WSIZE; \
+            wrap = 1; \
+            if (out(out_desc, put, (unsigned)left)) { \
+                ret = Z_BUF_ERROR; \
+                goto inf_leave; \
+            } \
+        } \
+    } while (0)
+
+/*
+   strm provides the memory allocation functions and window buffer on input,
+   and provides information on the unused input on return.  For Z_DATA_ERROR
+   returns, strm will also provide an error message.
+
+   in() and out() are the call-back input and output functions.  When
+   inflateBack() needs more input, it calls in().  When inflateBack() has
+   filled the window with output, or when it completes with data in the
+   window, it calls out() to write out the data.  The application must not
+   change the provided input until in() is called again or inflateBack()
+   returns.  The application must not change the window/output buffer until
+   inflateBack() returns.
+
+   in() and out() are called with a descriptor parameter provided in the
+   inflateBack() call.  This parameter can be a structure that provides the
+   information required to do the read or write, as well as accumulated
+   information on the input and output such as totals and check values.
+
+   in() should return zero on failure.  out() should return non-zero on
+   failure.  If either in() or out() fails, than inflateBack() returns a
+   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
+   was in() or out() that caused in the error.  Otherwise,  inflateBack()
+   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
+   error, or Z_MEM_ERROR if it could not allocate memory for the state.
+   inflateBack() can also return Z_STREAM_ERROR if the input parameters
+   are not correct, i.e. strm is Z_NULL or the state was not initialized.
+ */
+int ZEXPORT inflateBack9(strm, in, in_desc, out, out_desc)
+z_stream FAR *strm;
+in_func in;
+void FAR *in_desc;
+out_func out;
+void FAR *out_desc;
+{
+    struct inflate_state FAR *state;
+    unsigned char FAR *next;    /* next input */
+    unsigned char FAR *put;     /* next output */
+    unsigned have;              /* available input */
+    unsigned long left;         /* available output */
+    inflate_mode mode;          /* current inflate mode */
+    int lastblock;              /* true if processing last block */
+    int wrap;                   /* true if the window has wrapped */
+    unsigned long write;        /* window write index */
+    unsigned char FAR *window;  /* allocated sliding window, if needed */
+    unsigned long hold;         /* bit buffer */
+    unsigned bits;              /* bits in bit buffer */
+    unsigned extra;             /* extra bits needed */
+    unsigned long length;       /* literal or length of data to copy */
+    unsigned long offset;       /* distance back to copy string from */
+    unsigned long copy;         /* number of stored or match bytes to copy */
+    unsigned char FAR *from;    /* where to copy match bytes from */
+    code const FAR *lencode;    /* starting table for length/literal codes */
+    code const FAR *distcode;   /* starting table for distance codes */
+    unsigned lenbits;           /* index bits for lencode */
+    unsigned distbits;          /* index bits for distcode */
+    code this;                  /* current decoding table entry */
+    code last;                  /* parent table entry */
+    unsigned len;               /* length to copy for repeats, bits to drop */
+    int ret;                    /* return code */
+    static const unsigned short order[19] = /* permutation of code lengths */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+#include "inffix9.h"
+
+    /* Check that the strm exists and that the state was initialized */
+    if (strm == Z_NULL || strm->state == Z_NULL)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* Reset the state */
+    strm->msg = Z_NULL;
+    mode = TYPE;
+    lastblock = 0;
+    write = 0;
+    wrap = 0;
+    window = state->window;
+    next = strm->next_in;
+    have = next != Z_NULL ? strm->avail_in : 0;
+    hold = 0;
+    bits = 0;
+    put = window;
+    left = WSIZE;
+    lencode = Z_NULL;
+    distcode = Z_NULL;
+
+    /* Inflate until end of block marked as last */
+    for (;;)
+        switch (mode) {
+        case TYPE:
+            /* determine and dispatch block type */
+            if (lastblock) {
+                BYTEBITS();
+                mode = DONE;
+                break;
+            }
+            NEEDBITS(3);
+            lastblock = BITS(1);
+            DROPBITS(1);
+            switch (BITS(2)) {
+            case 0:                             /* stored block */
+                Tracev((stderr, "inflate:     stored block%s\n",
+                        lastblock ? " (last)" : ""));
+                mode = STORED;
+                break;
+            case 1:                             /* fixed block */
+                lencode = lenfix;
+                lenbits = 9;
+                distcode = distfix;
+                distbits = 5;
+                Tracev((stderr, "inflate:     fixed codes block%s\n",
+                        lastblock ? " (last)" : ""));
+                mode = LEN;                     /* decode codes */
+                break;
+            case 2:                             /* dynamic block */
+                Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                        lastblock ? " (last)" : ""));
+                mode = TABLE;
+                break;
+            case 3:
+                strm->msg = (char *)"invalid block type";
+                mode = BAD;
+            }
+            DROPBITS(2);
+            break;
+
+        case STORED:
+            /* get and verify stored block length */
+            BYTEBITS();                         /* go to byte boundary */
+            NEEDBITS(32);
+            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+                strm->msg = (char *)"invalid stored block lengths";
+                mode = BAD;
+                break;
+            }
+            length = (unsigned)hold & 0xffff;
+            Tracev((stderr, "inflate:       stored length %lu\n",
+                    length));
+            INITBITS();
+
+            /* copy stored block from input to output */
+            while (length != 0) {
+                copy = length;
+                PULL();
+                ROOM();
+                if (copy > have) copy = have;
+                if (copy > left) copy = left;
+                zmemcpy(put, next, copy);
+                have -= copy;
+                next += copy;
+                left -= copy;
+                put += copy;
+                length -= copy;
+            }
+            Tracev((stderr, "inflate:       stored end\n"));
+            mode = TYPE;
+            break;
+
+        case TABLE:
+            /* get dynamic table entries descriptor */
+            NEEDBITS(14);
+            state->nlen = BITS(5) + 257;
+            DROPBITS(5);
+            state->ndist = BITS(5) + 1;
+            DROPBITS(5);
+            state->ncode = BITS(4) + 4;
+            DROPBITS(4);
+            if (state->nlen > 286) {
+                strm->msg = (char *)"too many length symbols";
+                mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       table sizes ok\n"));
+
+            /* get code length code lengths (not a typo) */
+            state->have = 0;
+            while (state->have < state->ncode) {
+                NEEDBITS(3);
+                state->lens[order[state->have++]] = (unsigned short)BITS(3);
+                DROPBITS(3);
+            }
+            while (state->have < 19)
+                state->lens[order[state->have++]] = 0;
+            state->next = state->codes;
+            lencode = (code const FAR *)(state->next);
+            lenbits = 7;
+            ret = inflate_table9(CODES, state->lens, 19, &(state->next),
+                                &(lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid code lengths set";
+                mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       code lengths ok\n"));
+
+            /* get length and distance code code lengths */
+            state->have = 0;
+            while (state->have < state->nlen + state->ndist) {
+                for (;;) {
+                    this = lencode[BITS(lenbits)];
+                    if ((unsigned)(this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                if (this.val < 16) {
+                    NEEDBITS(this.bits);
+                    DROPBITS(this.bits);
+                    state->lens[state->have++] = this.val;
+                }
+                else {
+                    if (this.val == 16) {
+                        NEEDBITS(this.bits + 2);
+                        DROPBITS(this.bits);
+                        if (state->have == 0) {
+                            strm->msg = (char *)"invalid bit length repeat";
+                            mode = BAD;
+                            break;
+                        }
+                        len = (unsigned)(state->lens[state->have - 1]);
+                        copy = 3 + BITS(2);
+                        DROPBITS(2);
+                    }
+                    else if (this.val == 17) {
+                        NEEDBITS(this.bits + 3);
+                        DROPBITS(this.bits);
+                        len = 0;
+                        copy = 3 + BITS(3);
+                        DROPBITS(3);
+                    }
+                    else {
+                        NEEDBITS(this.bits + 7);
+                        DROPBITS(this.bits);
+                        len = 0;
+                        copy = 11 + BITS(7);
+                        DROPBITS(7);
+                    }
+                    if (state->have + copy > state->nlen + state->ndist) {
+                        strm->msg = (char *)"invalid bit length repeat";
+                        mode = BAD;
+                        break;
+                    }
+                    while (copy--)
+                        state->lens[state->have++] = (unsigned short)len;
+                }
+            }
+
+            /* handle error breaks in while */
+            if (mode == BAD) break;
+
+            /* build code tables */
+            state->next = state->codes;
+            lencode = (code const FAR *)(state->next);
+            lenbits = 9;
+            ret = inflate_table9(LENS, state->lens, state->nlen,
+                            &(state->next), &(lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid literal/lengths set";
+                mode = BAD;
+                break;
+            }
+            distcode = (code const FAR *)(state->next);
+            distbits = 6;
+            ret = inflate_table9(DISTS, state->lens + state->nlen,
+                            state->ndist, &(state->next), &(distbits),
+                            state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid distances set";
+                mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       codes ok\n"));
+            mode = LEN;
+
+        case LEN:
+            /* get a literal, length, or end-of-block code */
+            for (;;) {
+                this = lencode[BITS(lenbits)];
+                if ((unsigned)(this.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if (this.op && (this.op & 0xf0) == 0) {
+                last = this;
+                for (;;) {
+                    this = lencode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(this.bits);
+            length = (unsigned)this.val;
+
+            /* process literal */
+            if (this.op == 0) {
+                Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+                        "inflate:         literal '%c'\n" :
+                        "inflate:         literal 0x%02x\n", this.val));
+                ROOM();
+                *put++ = (unsigned char)(length);
+                left--;
+                mode = LEN;
+                break;
+            }
+
+            /* process end of block */
+            if (this.op & 32) {
+                Tracevv((stderr, "inflate:         end of block\n"));
+                mode = TYPE;
+                break;
+            }
+
+            /* invalid code */
+            if (this.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                mode = BAD;
+                break;
+            }
+
+            /* length code -- get extra bits, if any */
+            extra = (unsigned)(this.op) & 31;
+            if (extra != 0) {
+                NEEDBITS(extra);
+                length += BITS(extra);
+                DROPBITS(extra);
+            }
+            Tracevv((stderr, "inflate:         length %lu\n", length));
+
+            /* get distance code */
+            for (;;) {
+                this = distcode[BITS(distbits)];
+                if ((unsigned)(this.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if ((this.op & 0xf0) == 0) {
+                last = this;
+                for (;;) {
+                    this = distcode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(this.bits);
+            if (this.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                mode = BAD;
+                break;
+            }
+            offset = (unsigned)this.val;
+
+            /* get distance extra bits, if any */
+            extra = (unsigned)(this.op) & 15;
+            if (extra != 0) {
+                NEEDBITS(extra);
+                offset += BITS(extra);
+                DROPBITS(extra);
+            }
+            if (offset > WSIZE - (wrap ? 0: left)) {
+                strm->msg = (char *)"invalid distance too far back";
+                mode = BAD;
+                break;
+            }
+            Tracevv((stderr, "inflate:         distance %lu\n", offset));
+
+            /* copy match from window to output */
+            do {
+                ROOM();
+                copy = WSIZE - offset;
+                if (copy < left) {
+                    from = put + copy;
+                    copy = left - copy;
+                }
+                else {
+                    from = put - offset;
+                    copy = left;
+                }
+                if (copy > length) copy = length;
+                length -= copy;
+                left -= copy;
+                do {
+                    *put++ = *from++;
+                } while (--copy);
+            } while (length != 0);
+            break;
+
+        case DONE:
+            /* inflate stream terminated properly -- write leftover output */
+            ret = Z_STREAM_END;
+            if (left < WSIZE) {
+                if (out(out_desc, window, (unsigned)(WSIZE - left)))
+                    ret = Z_BUF_ERROR;
+            }
+            goto inf_leave;
+
+        case BAD:
+            ret = Z_DATA_ERROR;
+            goto inf_leave;
+
+        default:                /* can't happen, but makes compilers happy */
+            ret = Z_STREAM_ERROR;
+            goto inf_leave;
+        }
+
+    /* Return unused input */
+  inf_leave:
+    strm->next_in = next;
+    strm->avail_in = have;
+    return ret;
+}
+
+int ZEXPORT inflateBack9End(strm)
+z_stream FAR *strm;
+{
+    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+        return Z_STREAM_ERROR;
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+    Tracev((stderr, "inflate: end\n"));
+    return Z_OK;
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/infback9/infback9.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/infback9/infback9.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/infback9/infback9.h	(revision 9)
@@ -0,0 +1,37 @@
+/* infback9.h -- header for using inflateBack9 functions
+ * Copyright (C) 2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * This header file and associated patches provide a decoder for PKWare's
+ * undocumented deflate64 compression method (method 9).  Use with infback9.c,
+ * inftree9.h, inftree9.c, and inffix9.h.  These patches are not supported.
+ * This should be compiled with zlib, since it uses zutil.h and zutil.o.
+ * This code has not yet been tested on 16-bit architectures.  See the
+ * comments in zlib.h for inflateBack() usage.  These functions are used
+ * identically, except that there is no windowBits parameter, and a 64K
+ * window must be provided.  Also if int's are 16 bits, then a zero for
+ * the third parameter of the "out" function actually means 65536UL.
+ * zlib.h must be included before this header file.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm,
+                                    in_func in, void FAR *in_desc,
+                                    out_func out, void FAR *out_desc));
+ZEXTERN int ZEXPORT inflateBack9End OF((z_stream FAR *strm));
+ZEXTERN int ZEXPORT inflateBack9Init_ OF((z_stream FAR *strm,
+                                         unsigned char FAR *window,
+                                         const char *version,
+                                         int stream_size));
+#define inflateBack9Init(strm, window) \
+        inflateBack9Init_((strm), (window), \
+        ZLIB_VERSION, sizeof(z_stream))
+
+#ifdef __cplusplus
+}
+#endif
Index: /trunk/minix/lib/zlib-1.2.3/contrib/infback9/inffix9.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/infback9/inffix9.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/infback9/inffix9.h	(revision 9)
@@ -0,0 +1,107 @@
+    /* inffix9.h -- table for decoding deflate64 fixed codes
+     * Generated automatically by makefixed9().
+     */
+
+    /* WARNING: this file should *not* be used by applications.
+       It is part of the implementation of this library and is
+       subject to change. Applications should only use zlib.h.
+     */
+
+    static const code lenfix[512] = {
+        {96,7,0},{0,8,80},{0,8,16},{132,8,115},{130,7,31},{0,8,112},
+        {0,8,48},{0,9,192},{128,7,10},{0,8,96},{0,8,32},{0,9,160},
+        {0,8,0},{0,8,128},{0,8,64},{0,9,224},{128,7,6},{0,8,88},
+        {0,8,24},{0,9,144},{131,7,59},{0,8,120},{0,8,56},{0,9,208},
+        {129,7,17},{0,8,104},{0,8,40},{0,9,176},{0,8,8},{0,8,136},
+        {0,8,72},{0,9,240},{128,7,4},{0,8,84},{0,8,20},{133,8,227},
+        {131,7,43},{0,8,116},{0,8,52},{0,9,200},{129,7,13},{0,8,100},
+        {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},
+        {128,7,8},{0,8,92},{0,8,28},{0,9,152},{132,7,83},{0,8,124},
+        {0,8,60},{0,9,216},{130,7,23},{0,8,108},{0,8,44},{0,9,184},
+        {0,8,12},{0,8,140},{0,8,76},{0,9,248},{128,7,3},{0,8,82},
+        {0,8,18},{133,8,163},{131,7,35},{0,8,114},{0,8,50},{0,9,196},
+        {129,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},{0,8,130},
+        {0,8,66},{0,9,228},{128,7,7},{0,8,90},{0,8,26},{0,9,148},
+        {132,7,67},{0,8,122},{0,8,58},{0,9,212},{130,7,19},{0,8,106},
+        {0,8,42},{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},
+        {128,7,5},{0,8,86},{0,8,22},{65,8,0},{131,7,51},{0,8,118},
+        {0,8,54},{0,9,204},{129,7,15},{0,8,102},{0,8,38},{0,9,172},
+        {0,8,6},{0,8,134},{0,8,70},{0,9,236},{128,7,9},{0,8,94},
+        {0,8,30},{0,9,156},{132,7,99},{0,8,126},{0,8,62},{0,9,220},
+        {130,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+        {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{133,8,131},
+        {130,7,31},{0,8,113},{0,8,49},{0,9,194},{128,7,10},{0,8,97},
+        {0,8,33},{0,9,162},{0,8,1},{0,8,129},{0,8,65},{0,9,226},
+        {128,7,6},{0,8,89},{0,8,25},{0,9,146},{131,7,59},{0,8,121},
+        {0,8,57},{0,9,210},{129,7,17},{0,8,105},{0,8,41},{0,9,178},
+        {0,8,9},{0,8,137},{0,8,73},{0,9,242},{128,7,4},{0,8,85},
+        {0,8,21},{144,8,3},{131,7,43},{0,8,117},{0,8,53},{0,9,202},
+        {129,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},
+        {0,8,69},{0,9,234},{128,7,8},{0,8,93},{0,8,29},{0,9,154},
+        {132,7,83},{0,8,125},{0,8,61},{0,9,218},{130,7,23},{0,8,109},
+        {0,8,45},{0,9,186},{0,8,13},{0,8,141},{0,8,77},{0,9,250},
+        {128,7,3},{0,8,83},{0,8,19},{133,8,195},{131,7,35},{0,8,115},
+        {0,8,51},{0,9,198},{129,7,11},{0,8,99},{0,8,35},{0,9,166},
+        {0,8,3},{0,8,131},{0,8,67},{0,9,230},{128,7,7},{0,8,91},
+        {0,8,27},{0,9,150},{132,7,67},{0,8,123},{0,8,59},{0,9,214},
+        {130,7,19},{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},
+        {0,8,75},{0,9,246},{128,7,5},{0,8,87},{0,8,23},{77,8,0},
+        {131,7,51},{0,8,119},{0,8,55},{0,9,206},{129,7,15},{0,8,103},
+        {0,8,39},{0,9,174},{0,8,7},{0,8,135},{0,8,71},{0,9,238},
+        {128,7,9},{0,8,95},{0,8,31},{0,9,158},{132,7,99},{0,8,127},
+        {0,8,63},{0,9,222},{130,7,27},{0,8,111},{0,8,47},{0,9,190},
+        {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},
+        {0,8,16},{132,8,115},{130,7,31},{0,8,112},{0,8,48},{0,9,193},
+        {128,7,10},{0,8,96},{0,8,32},{0,9,161},{0,8,0},{0,8,128},
+        {0,8,64},{0,9,225},{128,7,6},{0,8,88},{0,8,24},{0,9,145},
+        {131,7,59},{0,8,120},{0,8,56},{0,9,209},{129,7,17},{0,8,104},
+        {0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},{0,9,241},
+        {128,7,4},{0,8,84},{0,8,20},{133,8,227},{131,7,43},{0,8,116},
+        {0,8,52},{0,9,201},{129,7,13},{0,8,100},{0,8,36},{0,9,169},
+        {0,8,4},{0,8,132},{0,8,68},{0,9,233},{128,7,8},{0,8,92},
+        {0,8,28},{0,9,153},{132,7,83},{0,8,124},{0,8,60},{0,9,217},
+        {130,7,23},{0,8,108},{0,8,44},{0,9,185},{0,8,12},{0,8,140},
+        {0,8,76},{0,9,249},{128,7,3},{0,8,82},{0,8,18},{133,8,163},
+        {131,7,35},{0,8,114},{0,8,50},{0,9,197},{129,7,11},{0,8,98},
+        {0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+        {128,7,7},{0,8,90},{0,8,26},{0,9,149},{132,7,67},{0,8,122},
+        {0,8,58},{0,9,213},{130,7,19},{0,8,106},{0,8,42},{0,9,181},
+        {0,8,10},{0,8,138},{0,8,74},{0,9,245},{128,7,5},{0,8,86},
+        {0,8,22},{65,8,0},{131,7,51},{0,8,118},{0,8,54},{0,9,205},
+        {129,7,15},{0,8,102},{0,8,38},{0,9,173},{0,8,6},{0,8,134},
+        {0,8,70},{0,9,237},{128,7,9},{0,8,94},{0,8,30},{0,9,157},
+        {132,7,99},{0,8,126},{0,8,62},{0,9,221},{130,7,27},{0,8,110},
+        {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},
+        {96,7,0},{0,8,81},{0,8,17},{133,8,131},{130,7,31},{0,8,113},
+        {0,8,49},{0,9,195},{128,7,10},{0,8,97},{0,8,33},{0,9,163},
+        {0,8,1},{0,8,129},{0,8,65},{0,9,227},{128,7,6},{0,8,89},
+        {0,8,25},{0,9,147},{131,7,59},{0,8,121},{0,8,57},{0,9,211},
+        {129,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},{0,8,137},
+        {0,8,73},{0,9,243},{128,7,4},{0,8,85},{0,8,21},{144,8,3},
+        {131,7,43},{0,8,117},{0,8,53},{0,9,203},{129,7,13},{0,8,101},
+        {0,8,37},{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},
+        {128,7,8},{0,8,93},{0,8,29},{0,9,155},{132,7,83},{0,8,125},
+        {0,8,61},{0,9,219},{130,7,23},{0,8,109},{0,8,45},{0,9,187},
+        {0,8,13},{0,8,141},{0,8,77},{0,9,251},{128,7,3},{0,8,83},
+        {0,8,19},{133,8,195},{131,7,35},{0,8,115},{0,8,51},{0,9,199},
+        {129,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+        {0,8,67},{0,9,231},{128,7,7},{0,8,91},{0,8,27},{0,9,151},
+        {132,7,67},{0,8,123},{0,8,59},{0,9,215},{130,7,19},{0,8,107},
+        {0,8,43},{0,9,183},{0,8,11},{0,8,139},{0,8,75},{0,9,247},
+        {128,7,5},{0,8,87},{0,8,23},{77,8,0},{131,7,51},{0,8,119},
+        {0,8,55},{0,9,207},{129,7,15},{0,8,103},{0,8,39},{0,9,175},
+        {0,8,7},{0,8,135},{0,8,71},{0,9,239},{128,7,9},{0,8,95},
+        {0,8,31},{0,9,159},{132,7,99},{0,8,127},{0,8,63},{0,9,223},
+        {130,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},
+        {0,8,79},{0,9,255}
+    };
+
+    static const code distfix[32] = {
+        {128,5,1},{135,5,257},{131,5,17},{139,5,4097},{129,5,5},
+        {137,5,1025},{133,5,65},{141,5,16385},{128,5,3},{136,5,513},
+        {132,5,33},{140,5,8193},{130,5,9},{138,5,2049},{134,5,129},
+        {142,5,32769},{128,5,2},{135,5,385},{131,5,25},{139,5,6145},
+        {129,5,7},{137,5,1537},{133,5,97},{141,5,24577},{128,5,4},
+        {136,5,769},{132,5,49},{140,5,12289},{130,5,13},{138,5,3073},
+        {134,5,193},{142,5,49153}
+    };
Index: /trunk/minix/lib/zlib-1.2.3/contrib/infback9/inflate9.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/infback9/inflate9.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/infback9/inflate9.h	(revision 9)
@@ -0,0 +1,47 @@
+/* inflate9.h -- internal inflate state definition
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+        TYPE,       /* i: waiting for type bits, including last-flag bit */
+        STORED,     /* i: waiting for stored size (length and complement) */
+        TABLE,      /* i: waiting for dynamic block table lengths */
+            LEN,        /* i: waiting for length/lit code */
+    DONE,       /* finished check, done -- remain here until reset */
+    BAD         /* got a data error -- remain here until reset */
+} inflate_mode;
+
+/*
+    State transitions between above modes -
+
+    (most modes can go to the BAD mode -- not shown for clarity)
+
+    Read deflate blocks:
+            TYPE -> STORED or TABLE or LEN or DONE
+            STORED -> TYPE
+            TABLE -> LENLENS -> CODELENS -> LEN
+    Read deflate codes:
+                LEN -> LEN or TYPE
+ */
+
+/* state maintained between inflate() calls.  Approximately 7K bytes. */
+struct inflate_state {
+        /* sliding window */
+    unsigned char FAR *window;  /* allocated sliding window, if needed */
+        /* dynamic table building */
+    unsigned ncode;             /* number of code length code lengths */
+    unsigned nlen;              /* number of length code lengths */
+    unsigned ndist;             /* number of distance code lengths */
+    unsigned have;              /* number of code lengths in lens[] */
+    code FAR *next;             /* next available space in codes[] */
+    unsigned short lens[320];   /* temporary storage for code lengths */
+    unsigned short work[288];   /* work area for code table building */
+    code codes[ENOUGH];         /* space for code tables */
+};
Index: /trunk/minix/lib/zlib-1.2.3/contrib/infback9/inftree9.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/infback9/inftree9.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/infback9/inftree9.c	(revision 9)
@@ -0,0 +1,323 @@
+/* inftree9.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftree9.h"
+
+#define MAXBITS 15
+
+const char inflate9_copyright[] =
+   " inflate9 1.2.3 Copyright 1995-2005 Mark Adler ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/*
+   Build a set of tables to decode the provided canonical Huffman code.
+   The code lengths are lens[0..codes-1].  The result starts at *table,
+   whose indices are 0..2^bits-1.  work is a writable array of at least
+   lens shorts, which is used as a work area.  type is the type of code
+   to be generated, CODES, LENS, or DISTS.  On return, zero is success,
+   -1 is an invalid code, and +1 means that ENOUGH isn't enough.  table
+   on return points to the next available entry's address.  bits is the
+   requested root table index bits, and on return it is the actual root
+   table index bits.  It will differ if the request is greater than the
+   longest code or if it is less than the shortest code.
+ */
+int inflate_table9(type, lens, codes, table, bits, work)
+codetype type;
+unsigned short FAR *lens;
+unsigned codes;
+code FAR * FAR *table;
+unsigned FAR *bits;
+unsigned short FAR *work;
+{
+    unsigned len;               /* a code's length in bits */
+    unsigned sym;               /* index of code symbols */
+    unsigned min, max;          /* minimum and maximum code lengths */
+    unsigned root;              /* number of index bits for root table */
+    unsigned curr;              /* number of index bits for current table */
+    unsigned drop;              /* code bits to drop for sub-table */
+    int left;                   /* number of prefix codes available */
+    unsigned used;              /* code entries in table used */
+    unsigned huff;              /* Huffman code */
+    unsigned incr;              /* for incrementing code, index */
+    unsigned fill;              /* index for replicating entries */
+    unsigned low;               /* low bits for current root entry */
+    unsigned mask;              /* mask for low root bits */
+    code this;                  /* table entry for duplication */
+    code FAR *next;             /* next available space in table */
+    const unsigned short FAR *base;     /* base value table to use */
+    const unsigned short FAR *extra;    /* extra bits table to use */
+    int end;                    /* use base and extra for symbol > end */
+    unsigned short count[MAXBITS+1];    /* number of codes of each length */
+    unsigned short offs[MAXBITS+1];     /* offsets in table for each length */
+    static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17,
+        19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115,
+        131, 163, 195, 227, 3, 0, 0};
+    static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+        128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129,
+        130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132,
+        133, 133, 133, 133, 144, 201, 196};
+    static const unsigned short dbase[32] = { /* Distance codes 0..31 base */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49,
+        65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073,
+        4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153};
+    static const unsigned short dext[32] = { /* Distance codes 0..31 extra */
+        128, 128, 128, 128, 129, 129, 130, 130, 131, 131, 132, 132,
+        133, 133, 134, 134, 135, 135, 136, 136, 137, 137, 138, 138,
+        139, 139, 140, 140, 141, 141, 142, 142};
+
+    /*
+       Process a set of code lengths to create a canonical Huffman code.  The
+       code lengths are lens[0..codes-1].  Each length corresponds to the
+       symbols 0..codes-1.  The Huffman code is generated by first sorting the
+       symbols by length from short to long, and retaining the symbol order
+       for codes with equal lengths.  Then the code starts with all zero bits
+       for the first code of the shortest length, and the codes are integer
+       increments for the same length, and zeros are appended as the length
+       increases.  For the deflate format, these bits are stored backwards
+       from their more natural integer increment ordering, and so when the
+       decoding tables are built in the large loop below, the integer codes
+       are incremented backwards.
+
+       This routine assumes, but does not check, that all of the entries in
+       lens[] are in the range 0..MAXBITS.  The caller must assure this.
+       1..MAXBITS is interpreted as that code length.  zero means that that
+       symbol does not occur in this code.
+
+       The codes are sorted by computing a count of codes for each length,
+       creating from that a table of starting indices for each length in the
+       sorted table, and then entering the symbols in order in the sorted
+       table.  The sorted table is work[], with that space being provided by
+       the caller.
+
+       The length counts are used for other purposes as well, i.e. finding
+       the minimum and maximum length codes, determining if there are any
+       codes at all, checking for a valid set of lengths, and looking ahead
+       at length counts to determine sub-table sizes when building the
+       decoding tables.
+     */
+
+    /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+    for (len = 0; len <= MAXBITS; len++)
+        count[len] = 0;
+    for (sym = 0; sym < codes; sym++)
+        count[lens[sym]]++;
+
+    /* bound code lengths, force root to be within code lengths */
+    root = *bits;
+    for (max = MAXBITS; max >= 1; max--)
+        if (count[max] != 0) break;
+    if (root > max) root = max;
+    if (max == 0) return -1;            /* no codes! */
+    for (min = 1; min <= MAXBITS; min++)
+        if (count[min] != 0) break;
+    if (root < min) root = min;
+
+    /* check for an over-subscribed or incomplete set of lengths */
+    left = 1;
+    for (len = 1; len <= MAXBITS; len++) {
+        left <<= 1;
+        left -= count[len];
+        if (left < 0) return -1;        /* over-subscribed */
+    }
+    if (left > 0 && (type == CODES || max != 1))
+        return -1;                      /* incomplete set */
+
+    /* generate offsets into symbol table for each length for sorting */
+    offs[1] = 0;
+    for (len = 1; len < MAXBITS; len++)
+        offs[len + 1] = offs[len] + count[len];
+
+    /* sort symbols by length, by symbol order within each length */
+    for (sym = 0; sym < codes; sym++)
+        if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+    /*
+       Create and fill in decoding tables.  In this loop, the table being
+       filled is at next and has curr index bits.  The code being used is huff
+       with length len.  That code is converted to an index by dropping drop
+       bits off of the bottom.  For codes where len is less than drop + curr,
+       those top drop + curr - len bits are incremented through all values to
+       fill the table with replicated entries.
+
+       root is the number of index bits for the root table.  When len exceeds
+       root, sub-tables are created pointed to by the root entry with an index
+       of the low root bits of huff.  This is saved in low to check for when a
+       new sub-table should be started.  drop is zero when the root table is
+       being filled, and drop is root when sub-tables are being filled.
+
+       When a new sub-table is needed, it is necessary to look ahead in the
+       code lengths to determine what size sub-table is needed.  The length
+       counts are used for this, and so count[] is decremented as codes are
+       entered in the tables.
+
+       used keeps track of how many table entries have been allocated from the
+       provided *table space.  It is checked when a LENS table is being made
+       against the space in *table, ENOUGH, minus the maximum space needed by
+       the worst case distance code, MAXD.  This should never happen, but the
+       sufficiency of ENOUGH has not been proven exhaustively, hence the check.
+       This assumes that when type == LENS, bits == 9.
+
+       sym increments through all symbols, and the loop terminates when
+       all codes of length max, i.e. all codes, have been processed.  This
+       routine permits incomplete codes, so another loop after this one fills
+       in the rest of the decoding tables with invalid code markers.
+     */
+
+    /* set up for code type */
+    switch (type) {
+    case CODES:
+        base = extra = work;    /* dummy value--not used */
+        end = 19;
+        break;
+    case LENS:
+        base = lbase;
+        base -= 257;
+        extra = lext;
+        extra -= 257;
+        end = 256;
+        break;
+    default:            /* DISTS */
+        base = dbase;
+        extra = dext;
+        end = -1;
+    }
+
+    /* initialize state for loop */
+    huff = 0;                   /* starting code */
+    sym = 0;                    /* starting code symbol */
+    len = min;                  /* starting code length */
+    next = *table;              /* current table to fill in */
+    curr = root;                /* current table index bits */
+    drop = 0;                   /* current bits to drop from code for index */
+    low = (unsigned)(-1);       /* trigger new sub-table when len > root */
+    used = 1U << root;          /* use root table entries */
+    mask = used - 1;            /* mask for comparing low */
+
+    /* check available table space */
+    if (type == LENS && used >= ENOUGH - MAXD)
+        return 1;
+
+    /* process all codes and make table entries */
+    for (;;) {
+        /* create table entry */
+        this.bits = (unsigned char)(len - drop);
+        if ((int)(work[sym]) < end) {
+            this.op = (unsigned char)0;
+            this.val = work[sym];
+        }
+        else if ((int)(work[sym]) > end) {
+            this.op = (unsigned char)(extra[work[sym]]);
+            this.val = base[work[sym]];
+        }
+        else {
+            this.op = (unsigned char)(32 + 64);         /* end of block */
+            this.val = 0;
+        }
+
+        /* replicate for those indices with low len bits equal to huff */
+        incr = 1U << (len - drop);
+        fill = 1U << curr;
+        do {
+            fill -= incr;
+            next[(huff >> drop) + fill] = this;
+        } while (fill != 0);
+
+        /* backwards increment the len-bit code huff */
+        incr = 1U << (len - 1);
+        while (huff & incr)
+            incr >>= 1;
+        if (incr != 0) {
+            huff &= incr - 1;
+            huff += incr;
+        }
+        else
+            huff = 0;
+
+        /* go to next symbol, update count, len */
+        sym++;
+        if (--(count[len]) == 0) {
+            if (len == max) break;
+            len = lens[work[sym]];
+        }
+
+        /* create new sub-table if needed */
+        if (len > root && (huff & mask) != low) {
+            /* if first time, transition to sub-tables */
+            if (drop == 0)
+                drop = root;
+
+            /* increment past last table */
+            next += 1U << curr;
+
+            /* determine length of next table */
+            curr = len - drop;
+            left = (int)(1 << curr);
+            while (curr + drop < max) {
+                left -= count[curr + drop];
+                if (left <= 0) break;
+                curr++;
+                left <<= 1;
+            }
+
+            /* check for enough space */
+            used += 1U << curr;
+            if (type == LENS && used >= ENOUGH - MAXD)
+                return 1;
+
+            /* point entry in root table to sub-table */
+            low = huff & mask;
+            (*table)[low].op = (unsigned char)curr;
+            (*table)[low].bits = (unsigned char)root;
+            (*table)[low].val = (unsigned short)(next - *table);
+        }
+    }
+
+    /*
+       Fill in rest of table for incomplete codes.  This loop is similar to the
+       loop above in incrementing huff for table indices.  It is assumed that
+       len is equal to curr + drop, so there is no loop needed to increment
+       through high index bits.  When the current sub-table is filled, the loop
+       drops back to the root table to fill in any remaining entries there.
+     */
+    this.op = (unsigned char)64;                /* invalid code marker */
+    this.bits = (unsigned char)(len - drop);
+    this.val = (unsigned short)0;
+    while (huff != 0) {
+        /* when done with sub-table, drop back to root table */
+        if (drop != 0 && (huff & mask) != low) {
+            drop = 0;
+            len = root;
+            next = *table;
+            curr = root;
+            this.bits = (unsigned char)len;
+        }
+
+        /* put invalid code marker in table */
+        next[huff >> drop] = this;
+
+        /* backwards increment the len-bit code huff */
+        incr = 1U << (len - 1);
+        while (huff & incr)
+            incr >>= 1;
+        if (incr != 0) {
+            huff &= incr - 1;
+            huff += incr;
+        }
+        else
+            huff = 0;
+    }
+
+    /* set return parameters */
+    *table += used;
+    *bits = root;
+    return 0;
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/infback9/inftree9.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/infback9/inftree9.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/infback9/inftree9.h	(revision 9)
@@ -0,0 +1,55 @@
+/* inftree9.h -- header to use inftree9.c
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Structure for decoding tables.  Each entry provides either the
+   information needed to do the operation requested by the code that
+   indexed that table entry, or it provides a pointer to another
+   table that indexes more bits of the code.  op indicates whether
+   the entry is a pointer to another table, a literal, a length or
+   distance, an end-of-block, or an invalid code.  For a table
+   pointer, the low four bits of op is the number of index bits of
+   that table.  For a length or distance, the low four bits of op
+   is the number of extra bits to get after the code.  bits is
+   the number of bits in this code or part of the code to drop off
+   of the bit buffer.  val is the actual byte to output in the case
+   of a literal, the base length or distance, or the offset from
+   the current table to the next table.  Each entry is four bytes. */
+typedef struct {
+    unsigned char op;           /* operation, extra bits, table bits */
+    unsigned char bits;         /* bits in this part of the code */
+    unsigned short val;         /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+    00000000 - literal
+    0000tttt - table link, tttt != 0 is the number of table index bits
+    100eeeee - length or distance, eeee is the number of extra bits
+    01100000 - end of block
+    01000000 - invalid code
+ */
+
+/* Maximum size of dynamic tree.  The maximum found in a long but non-
+   exhaustive search was 1444 code structures (852 for length/literals
+   and 592 for distances, the latter actually the result of an
+   exhaustive search).  The true maximum is not known, but the value
+   below is more than safe. */
+#define ENOUGH 2048
+#define MAXD 592
+
+/* Type of code to build for inftable() */
+typedef enum {
+    CODES,
+    LENS,
+    DISTS
+} codetype;
+
+extern int inflate_table9 OF((codetype type, unsigned short FAR *lens,
+                             unsigned codes, code FAR * FAR *table,
+                             unsigned FAR *bits, unsigned short FAR *work));
Index: /trunk/minix/lib/zlib-1.2.3/contrib/inflate86/inffas86.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/inflate86/inffas86.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/inflate86/inffas86.c	(revision 9)
@@ -0,0 +1,1157 @@
+/* inffas86.c is a hand tuned assembler version of
+ *
+ * inffast.c -- fast decoding
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Copyright (C) 2003 Chris Anderson <christop@charm.net>
+ * Please use the copyright conditions above.
+ *
+ * Dec-29-2003 -- I added AMD64 inflate asm support.  This version is also
+ * slightly quicker on x86 systems because, instead of using rep movsb to copy
+ * data, it uses rep movsw, which moves data in 2-byte chunks instead of single
+ * bytes.  I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates
+ * from http://fedora.linux.duke.edu/fc1_x86_64
+ * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with
+ * 1GB ram.  The 64-bit version is about 4% faster than the 32-bit version,
+ * when decompressing mozilla-source-1.3.tar.gz.
+ *
+ * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from
+ * the gcc -S output of zlib-1.2.0/inffast.c.  Zlib-1.2.0 is in beta release at
+ * the moment.  I have successfully compiled and tested this code with gcc2.96,
+ * gcc3.2, icc5.0, msvc6.0.  It is very close to the speed of inffast.S
+ * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX
+ * enabled.  I will attempt to merge the MMX code into this version.  Newer
+ * versions of this and inffast.S can be found at
+ * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+/* Mark Adler's comments from inffast.c: */
+
+/*
+   Decode literal, length, and distance codes and write out the resulting
+   literal and match bytes until either not enough input or output is
+   available, an end-of-block is encountered, or a data error is encountered.
+   When large enough input and output buffers are supplied to inflate(), for
+   example, a 16K input buffer and a 64K output buffer, more than 95% of the
+   inflate execution time is spent in this routine.
+
+   Entry assumptions:
+
+        state->mode == LEN
+        strm->avail_in >= 6
+        strm->avail_out >= 258
+        start >= strm->avail_out
+        state->bits < 8
+
+   On return, state->mode is one of:
+
+        LEN -- ran out of enough output space or enough available input
+        TYPE -- reached end of block code, inflate() to interpret next block
+        BAD -- error in block data
+
+   Notes:
+
+    - The maximum input bits used by a length/distance pair is 15 bits for the
+      length code, 5 bits for the length extra, 15 bits for the distance code,
+      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
+      Therefore if strm->avail_in >= 6, then there is enough input to avoid
+      checking for available input while decoding.
+
+    - The maximum bytes that a single length/distance pair can output is 258
+      bytes, which is the maximum length that can be coded.  inflate_fast()
+      requires strm->avail_out >= 258 for each loop to avoid checking for
+      output space.
+ */
+void inflate_fast(strm, start)
+z_streamp strm;
+unsigned start;         /* inflate()'s starting value for strm->avail_out */
+{
+    struct inflate_state FAR *state;
+    struct inffast_ar {
+/* 64   32                               x86  x86_64 */
+/* ar offset                              register */
+/*  0    0 */ void *esp;                /* esp save */
+/*  8    4 */ void *ebp;                /* ebp save */
+/* 16    8 */ unsigned char FAR *in;    /* esi rsi  local strm->next_in */
+/* 24   12 */ unsigned char FAR *last;  /*     r9   while in < last */
+/* 32   16 */ unsigned char FAR *out;   /* edi rdi  local strm->next_out */
+/* 40   20 */ unsigned char FAR *beg;   /*          inflate()'s init next_out */
+/* 48   24 */ unsigned char FAR *end;   /*     r10  while out < end */
+/* 56   28 */ unsigned char FAR *window;/*          size of window, wsize!=0 */
+/* 64   32 */ code const FAR *lcode;    /* ebp rbp  local strm->lencode */
+/* 72   36 */ code const FAR *dcode;    /*     r11  local strm->distcode */
+/* 80   40 */ unsigned long hold;       /* edx rdx  local strm->hold */
+/* 88   44 */ unsigned bits;            /* ebx rbx  local strm->bits */
+/* 92   48 */ unsigned wsize;           /*          window size */
+/* 96   52 */ unsigned write;           /*          window write index */
+/*100   56 */ unsigned lmask;           /*     r12  mask for lcode */
+/*104   60 */ unsigned dmask;           /*     r13  mask for dcode */
+/*108   64 */ unsigned len;             /*     r14  match length */
+/*112   68 */ unsigned dist;            /*     r15  match distance */
+/*116   72 */ unsigned status;          /*          set when state chng*/
+    } ar;
+
+#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )
+#define PAD_AVAIL_IN 6
+#define PAD_AVAIL_OUT 258
+#else
+#define PAD_AVAIL_IN 5
+#define PAD_AVAIL_OUT 257
+#endif
+
+    /* copy state to local variables */
+    state = (struct inflate_state FAR *)strm->state;
+    ar.in = strm->next_in;
+    ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN);
+    ar.out = strm->next_out;
+    ar.beg = ar.out - (start - strm->avail_out);
+    ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT);
+    ar.wsize = state->wsize;
+    ar.write = state->write;
+    ar.window = state->window;
+    ar.hold = state->hold;
+    ar.bits = state->bits;
+    ar.lcode = state->lencode;
+    ar.dcode = state->distcode;
+    ar.lmask = (1U << state->lenbits) - 1;
+    ar.dmask = (1U << state->distbits) - 1;
+
+    /* decode literals and length/distances until end-of-block or not enough
+       input data or output space */
+
+    /* align in on 1/2 hold size boundary */
+    while (((unsigned long)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) {
+        ar.hold += (unsigned long)*ar.in++ << ar.bits;
+        ar.bits += 8;
+    }
+
+#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )
+    __asm__ __volatile__ (
+"        leaq    %0, %%rax\n"
+"        movq    %%rbp, 8(%%rax)\n"       /* save regs rbp and rsp */
+"        movq    %%rsp, (%%rax)\n"
+"        movq    %%rax, %%rsp\n"          /* make rsp point to &ar */
+"        movq    16(%%rsp), %%rsi\n"      /* rsi  = in */
+"        movq    32(%%rsp), %%rdi\n"      /* rdi  = out */
+"        movq    24(%%rsp), %%r9\n"       /* r9   = last */
+"        movq    48(%%rsp), %%r10\n"      /* r10  = end */
+"        movq    64(%%rsp), %%rbp\n"      /* rbp  = lcode */
+"        movq    72(%%rsp), %%r11\n"      /* r11  = dcode */
+"        movq    80(%%rsp), %%rdx\n"      /* rdx  = hold */
+"        movl    88(%%rsp), %%ebx\n"      /* ebx  = bits */
+"        movl    100(%%rsp), %%r12d\n"    /* r12d = lmask */
+"        movl    104(%%rsp), %%r13d\n"    /* r13d = dmask */
+                                          /* r14d = len */
+                                          /* r15d = dist */
+"        cld\n"
+"        cmpq    %%rdi, %%r10\n"
+"        je      .L_one_time\n"           /* if only one decode left */
+"        cmpq    %%rsi, %%r9\n"
+"        je      .L_one_time\n"
+"        jmp     .L_do_loop\n"
+
+".L_one_time:\n"
+"        movq    %%r12, %%r8\n"           /* r8 = lmask */
+"        cmpb    $32, %%bl\n"
+"        ja      .L_get_length_code_one_time\n"
+
+"        lodsl\n"                         /* eax = *(uint *)in++ */
+"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
+"        addb    $32, %%bl\n"             /* bits += 32 */
+"        shlq    %%cl, %%rax\n"
+"        orq     %%rax, %%rdx\n"          /* hold |= *((uint *)in)++ << bits */
+"        jmp     .L_get_length_code_one_time\n"
+
+".align 32,0x90\n"
+".L_while_test:\n"
+"        cmpq    %%rdi, %%r10\n"
+"        jbe     .L_break_loop\n"
+"        cmpq    %%rsi, %%r9\n"
+"        jbe     .L_break_loop\n"
+
+".L_do_loop:\n"
+"        movq    %%r12, %%r8\n"           /* r8 = lmask */
+"        cmpb    $32, %%bl\n"
+"        ja      .L_get_length_code\n"    /* if (32 < bits) */
+
+"        lodsl\n"                         /* eax = *(uint *)in++ */
+"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
+"        addb    $32, %%bl\n"             /* bits += 32 */
+"        shlq    %%cl, %%rax\n"
+"        orq     %%rax, %%rdx\n"          /* hold |= *((uint *)in)++ << bits */
+
+".L_get_length_code:\n"
+"        andq    %%rdx, %%r8\n"            /* r8 &= hold */
+"        movl    (%%rbp,%%r8,4), %%eax\n"  /* eax = lcode[hold & lmask] */
+
+"        movb    %%ah, %%cl\n"            /* cl = this.bits */
+"        subb    %%ah, %%bl\n"            /* bits -= this.bits */
+"        shrq    %%cl, %%rdx\n"           /* hold >>= this.bits */
+
+"        testb   %%al, %%al\n"
+"        jnz     .L_test_for_length_base\n" /* if (op != 0) 45.7% */
+
+"        movq    %%r12, %%r8\n"            /* r8 = lmask */
+"        shrl    $16, %%eax\n"            /* output this.val char */
+"        stosb\n"
+
+".L_get_length_code_one_time:\n"
+"        andq    %%rdx, %%r8\n"            /* r8 &= hold */
+"        movl    (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */
+
+".L_dolen:\n"
+"        movb    %%ah, %%cl\n"            /* cl = this.bits */
+"        subb    %%ah, %%bl\n"            /* bits -= this.bits */
+"        shrq    %%cl, %%rdx\n"           /* hold >>= this.bits */
+
+"        testb   %%al, %%al\n"
+"        jnz     .L_test_for_length_base\n" /* if (op != 0) 45.7% */
+
+"        shrl    $16, %%eax\n"            /* output this.val char */
+"        stosb\n"
+"        jmp     .L_while_test\n"
+
+".align 32,0x90\n"
+".L_test_for_length_base:\n"
+"        movl    %%eax, %%r14d\n"         /* len = this */
+"        shrl    $16, %%r14d\n"           /* len = this.val */
+"        movb    %%al, %%cl\n"
+
+"        testb   $16, %%al\n"
+"        jz      .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */
+"        andb    $15, %%cl\n"             /* op &= 15 */
+"        jz      .L_decode_distance\n"    /* if (!op) */
+
+".L_add_bits_to_len:\n"
+"        subb    %%cl, %%bl\n"
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"
+"        andl    %%edx, %%eax\n"          /* eax &= hold */
+"        shrq    %%cl, %%rdx\n"
+"        addl    %%eax, %%r14d\n"         /* len += hold & mask[op] */
+
+".L_decode_distance:\n"
+"        movq    %%r13, %%r8\n"           /* r8 = dmask */
+"        cmpb    $32, %%bl\n"
+"        ja      .L_get_distance_code\n"  /* if (32 < bits) */
+
+"        lodsl\n"                         /* eax = *(uint *)in++ */
+"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
+"        addb    $32, %%bl\n"             /* bits += 32 */
+"        shlq    %%cl, %%rax\n"
+"        orq     %%rax, %%rdx\n"          /* hold |= *((uint *)in)++ << bits */
+
+".L_get_distance_code:\n"
+"        andq    %%rdx, %%r8\n"           /* r8 &= hold */
+"        movl    (%%r11,%%r8,4), %%eax\n" /* eax = dcode[hold & dmask] */
+
+".L_dodist:\n"
+"        movl    %%eax, %%r15d\n"         /* dist = this */
+"        shrl    $16, %%r15d\n"           /* dist = this.val */
+"        movb    %%ah, %%cl\n"
+"        subb    %%ah, %%bl\n"            /* bits -= this.bits */
+"        shrq    %%cl, %%rdx\n"           /* hold >>= this.bits */
+"        movb    %%al, %%cl\n"            /* cl = this.op */
+
+"        testb   $16, %%al\n"             /* if ((op & 16) == 0) */
+"        jz      .L_test_for_second_level_dist\n"
+"        andb    $15, %%cl\n"             /* op &= 15 */
+"        jz      .L_check_dist_one\n"
+
+".L_add_bits_to_dist:\n"
+"        subb    %%cl, %%bl\n"
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"                 /* (1 << op) - 1 */
+"        andl    %%edx, %%eax\n"          /* eax &= hold */
+"        shrq    %%cl, %%rdx\n"
+"        addl    %%eax, %%r15d\n"         /* dist += hold & ((1 << op) - 1) */
+
+".L_check_window:\n"
+"        movq    %%rsi, %%r8\n"           /* save in so from can use it's reg */
+"        movq    %%rdi, %%rax\n"
+"        subq    40(%%rsp), %%rax\n"      /* nbytes = out - beg */
+
+"        cmpl    %%r15d, %%eax\n"
+"        jb      .L_clip_window\n"        /* if (dist > nbytes) 4.2% */
+
+"        movl    %%r14d, %%ecx\n"         /* ecx = len */
+"        movq    %%rdi, %%rsi\n"
+"        subq    %%r15, %%rsi\n"          /* from = out - dist */
+
+"        sarl    %%ecx\n"
+"        jnc     .L_copy_two\n"           /* if len % 2 == 0 */
+
+"        rep     movsw\n"
+"        movb    (%%rsi), %%al\n"
+"        movb    %%al, (%%rdi)\n"
+"        incq    %%rdi\n"
+
+"        movq    %%r8, %%rsi\n"           /* move in back to %rsi, toss from */
+"        jmp     .L_while_test\n"
+
+".L_copy_two:\n"
+"        rep     movsw\n"
+"        movq    %%r8, %%rsi\n"           /* move in back to %rsi, toss from */
+"        jmp     .L_while_test\n"
+
+".align 32,0x90\n"
+".L_check_dist_one:\n"
+"        cmpl    $1, %%r15d\n"            /* if dist 1, is a memset */
+"        jne     .L_check_window\n"
+"        cmpq    %%rdi, 40(%%rsp)\n"      /* if out == beg, outside window */
+"        je      .L_check_window\n"
+
+"        movl    %%r14d, %%ecx\n"         /* ecx = len */
+"        movb    -1(%%rdi), %%al\n"
+"        movb    %%al, %%ah\n"
+
+"        sarl    %%ecx\n"
+"        jnc     .L_set_two\n"
+"        movb    %%al, (%%rdi)\n"
+"        incq    %%rdi\n"
+
+".L_set_two:\n"
+"        rep     stosw\n"
+"        jmp     .L_while_test\n"
+
+".align 32,0x90\n"
+".L_test_for_second_level_length:\n"
+"        testb   $64, %%al\n"
+"        jnz     .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */
+
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"
+"        andl    %%edx, %%eax\n"         /* eax &= hold */
+"        addl    %%r14d, %%eax\n"        /* eax += len */
+"        movl    (%%rbp,%%rax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/
+"        jmp     .L_dolen\n"
+
+".align 32,0x90\n"
+".L_test_for_second_level_dist:\n"
+"        testb   $64, %%al\n"
+"        jnz     .L_invalid_distance_code\n" /* if ((op & 64) != 0) */
+
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"
+"        andl    %%edx, %%eax\n"         /* eax &= hold */
+"        addl    %%r15d, %%eax\n"        /* eax += dist */
+"        movl    (%%r11,%%rax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/
+"        jmp     .L_dodist\n"
+
+".align 32,0x90\n"
+".L_clip_window:\n"
+"        movl    %%eax, %%ecx\n"         /* ecx = nbytes */
+"        movl    92(%%rsp), %%eax\n"     /* eax = wsize, prepare for dist cmp */
+"        negl    %%ecx\n"                /* nbytes = -nbytes */
+
+"        cmpl    %%r15d, %%eax\n"
+"        jb      .L_invalid_distance_too_far\n" /* if (dist > wsize) */
+
+"        addl    %%r15d, %%ecx\n"         /* nbytes = dist - nbytes */
+"        cmpl    $0, 96(%%rsp)\n"
+"        jne     .L_wrap_around_window\n" /* if (write != 0) */
+
+"        movq    56(%%rsp), %%rsi\n"     /* from  = window */
+"        subl    %%ecx, %%eax\n"         /* eax  -= nbytes */
+"        addq    %%rax, %%rsi\n"         /* from += wsize - nbytes */
+
+"        movl    %%r14d, %%eax\n"        /* eax = len */
+"        cmpl    %%ecx, %%r14d\n"
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* eax -= nbytes */
+"        rep     movsb\n"
+"        movq    %%rdi, %%rsi\n"
+"        subq    %%r15, %%rsi\n"         /* from = &out[ -dist ] */
+"        jmp     .L_do_copy\n"
+
+".align 32,0x90\n"
+".L_wrap_around_window:\n"
+"        movl    96(%%rsp), %%eax\n"     /* eax = write */
+"        cmpl    %%eax, %%ecx\n"
+"        jbe     .L_contiguous_in_window\n" /* if (write >= nbytes) */
+
+"        movl    92(%%rsp), %%esi\n"     /* from  = wsize */
+"        addq    56(%%rsp), %%rsi\n"     /* from += window */
+"        addq    %%rax, %%rsi\n"         /* from += write */
+"        subq    %%rcx, %%rsi\n"         /* from -= nbytes */
+"        subl    %%eax, %%ecx\n"         /* nbytes -= write */
+
+"        movl    %%r14d, %%eax\n"        /* eax = len */
+"        cmpl    %%ecx, %%eax\n"
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
+"        rep     movsb\n"
+"        movq    56(%%rsp), %%rsi\n"     /* from = window */
+"        movl    96(%%rsp), %%ecx\n"     /* nbytes = write */
+"        cmpl    %%ecx, %%eax\n"
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
+"        rep     movsb\n"
+"        movq    %%rdi, %%rsi\n"
+"        subq    %%r15, %%rsi\n"         /* from = out - dist */
+"        jmp     .L_do_copy\n"
+
+".align 32,0x90\n"
+".L_contiguous_in_window:\n"
+"        movq    56(%%rsp), %%rsi\n"     /* rsi = window */
+"        addq    %%rax, %%rsi\n"
+"        subq    %%rcx, %%rsi\n"         /* from += write - nbytes */
+
+"        movl    %%r14d, %%eax\n"        /* eax = len */
+"        cmpl    %%ecx, %%eax\n"
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
+"        rep     movsb\n"
+"        movq    %%rdi, %%rsi\n"
+"        subq    %%r15, %%rsi\n"         /* from = out - dist */
+"        jmp     .L_do_copy\n"           /* if (nbytes >= len) */
+
+".align 32,0x90\n"
+".L_do_copy:\n"
+"        movl    %%eax, %%ecx\n"         /* ecx = len */
+"        rep     movsb\n"
+
+"        movq    %%r8, %%rsi\n"          /* move in back to %esi, toss from */
+"        jmp     .L_while_test\n"
+
+".L_test_for_end_of_block:\n"
+"        testb   $32, %%al\n"
+"        jz      .L_invalid_literal_length_code\n"
+"        movl    $1, 116(%%rsp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_invalid_literal_length_code:\n"
+"        movl    $2, 116(%%rsp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_invalid_distance_code:\n"
+"        movl    $3, 116(%%rsp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_invalid_distance_too_far:\n"
+"        movl    $4, 116(%%rsp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_break_loop:\n"
+"        movl    $0, 116(%%rsp)\n"
+
+".L_break_loop_with_status:\n"
+/* put in, out, bits, and hold back into ar and pop esp */
+"        movq    %%rsi, 16(%%rsp)\n"     /* in */
+"        movq    %%rdi, 32(%%rsp)\n"     /* out */
+"        movl    %%ebx, 88(%%rsp)\n"     /* bits */
+"        movq    %%rdx, 80(%%rsp)\n"     /* hold */
+"        movq    (%%rsp), %%rax\n"       /* restore rbp and rsp */
+"        movq    8(%%rsp), %%rbp\n"
+"        movq    %%rax, %%rsp\n"
+          :
+          : "m" (ar)
+          : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi",
+            "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
+    );
+#elif ( defined( __GNUC__ ) || defined( __ICC ) ) && defined( __i386 )
+    __asm__ __volatile__ (
+"        leal    %0, %%eax\n"
+"        movl    %%esp, (%%eax)\n"        /* save esp, ebp */
+"        movl    %%ebp, 4(%%eax)\n"
+"        movl    %%eax, %%esp\n"
+"        movl    8(%%esp), %%esi\n"       /* esi = in */
+"        movl    16(%%esp), %%edi\n"      /* edi = out */
+"        movl    40(%%esp), %%edx\n"      /* edx = hold */
+"        movl    44(%%esp), %%ebx\n"      /* ebx = bits */
+"        movl    32(%%esp), %%ebp\n"      /* ebp = lcode */
+
+"        cld\n"
+"        jmp     .L_do_loop\n"
+
+".align 32,0x90\n"
+".L_while_test:\n"
+"        cmpl    %%edi, 24(%%esp)\n"      /* out < end */
+"        jbe     .L_break_loop\n"
+"        cmpl    %%esi, 12(%%esp)\n"      /* in < last */
+"        jbe     .L_break_loop\n"
+
+".L_do_loop:\n"
+"        cmpb    $15, %%bl\n"
+"        ja      .L_get_length_code\n"    /* if (15 < bits) */
+
+"        xorl    %%eax, %%eax\n"
+"        lodsw\n"                         /* al = *(ushort *)in++ */
+"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
+"        addb    $16, %%bl\n"             /* bits += 16 */
+"        shll    %%cl, %%eax\n"
+"        orl     %%eax, %%edx\n"        /* hold |= *((ushort *)in)++ << bits */
+
+".L_get_length_code:\n"
+"        movl    56(%%esp), %%eax\n"      /* eax = lmask */
+"        andl    %%edx, %%eax\n"          /* eax &= hold */
+"        movl    (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[hold & lmask] */
+
+".L_dolen:\n"
+"        movb    %%ah, %%cl\n"            /* cl = this.bits */
+"        subb    %%ah, %%bl\n"            /* bits -= this.bits */
+"        shrl    %%cl, %%edx\n"           /* hold >>= this.bits */
+
+"        testb   %%al, %%al\n"
+"        jnz     .L_test_for_length_base\n" /* if (op != 0) 45.7% */
+
+"        shrl    $16, %%eax\n"            /* output this.val char */
+"        stosb\n"
+"        jmp     .L_while_test\n"
+
+".align 32,0x90\n"
+".L_test_for_length_base:\n"
+"        movl    %%eax, %%ecx\n"          /* len = this */
+"        shrl    $16, %%ecx\n"            /* len = this.val */
+"        movl    %%ecx, 64(%%esp)\n"      /* save len */
+"        movb    %%al, %%cl\n"
+
+"        testb   $16, %%al\n"
+"        jz      .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */
+"        andb    $15, %%cl\n"             /* op &= 15 */
+"        jz      .L_decode_distance\n"    /* if (!op) */
+"        cmpb    %%cl, %%bl\n"
+"        jae     .L_add_bits_to_len\n"    /* if (op <= bits) */
+
+"        movb    %%cl, %%ch\n"            /* stash op in ch, freeing cl */
+"        xorl    %%eax, %%eax\n"
+"        lodsw\n"                         /* al = *(ushort *)in++ */
+"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
+"        addb    $16, %%bl\n"             /* bits += 16 */
+"        shll    %%cl, %%eax\n"
+"        orl     %%eax, %%edx\n"         /* hold |= *((ushort *)in)++ << bits */
+"        movb    %%ch, %%cl\n"            /* move op back to ecx */
+
+".L_add_bits_to_len:\n"
+"        subb    %%cl, %%bl\n"
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"
+"        andl    %%edx, %%eax\n"          /* eax &= hold */
+"        shrl    %%cl, %%edx\n"
+"        addl    %%eax, 64(%%esp)\n"      /* len += hold & mask[op] */
+
+".L_decode_distance:\n"
+"        cmpb    $15, %%bl\n"
+"        ja      .L_get_distance_code\n"  /* if (15 < bits) */
+
+"        xorl    %%eax, %%eax\n"
+"        lodsw\n"                         /* al = *(ushort *)in++ */
+"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
+"        addb    $16, %%bl\n"             /* bits += 16 */
+"        shll    %%cl, %%eax\n"
+"        orl     %%eax, %%edx\n"         /* hold |= *((ushort *)in)++ << bits */
+
+".L_get_distance_code:\n"
+"        movl    60(%%esp), %%eax\n"      /* eax = dmask */
+"        movl    36(%%esp), %%ecx\n"      /* ecx = dcode */
+"        andl    %%edx, %%eax\n"          /* eax &= hold */
+"        movl    (%%ecx,%%eax,4), %%eax\n"/* eax = dcode[hold & dmask] */
+
+".L_dodist:\n"
+"        movl    %%eax, %%ebp\n"          /* dist = this */
+"        shrl    $16, %%ebp\n"            /* dist = this.val */
+"        movb    %%ah, %%cl\n"
+"        subb    %%ah, %%bl\n"            /* bits -= this.bits */
+"        shrl    %%cl, %%edx\n"           /* hold >>= this.bits */
+"        movb    %%al, %%cl\n"            /* cl = this.op */
+
+"        testb   $16, %%al\n"             /* if ((op & 16) == 0) */
+"        jz      .L_test_for_second_level_dist\n"
+"        andb    $15, %%cl\n"             /* op &= 15 */
+"        jz      .L_check_dist_one\n"
+"        cmpb    %%cl, %%bl\n"
+"        jae     .L_add_bits_to_dist\n"   /* if (op <= bits) 97.6% */
+
+"        movb    %%cl, %%ch\n"            /* stash op in ch, freeing cl */
+"        xorl    %%eax, %%eax\n"
+"        lodsw\n"                         /* al = *(ushort *)in++ */
+"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
+"        addb    $16, %%bl\n"             /* bits += 16 */
+"        shll    %%cl, %%eax\n"
+"        orl     %%eax, %%edx\n"        /* hold |= *((ushort *)in)++ << bits */
+"        movb    %%ch, %%cl\n"            /* move op back to ecx */
+
+".L_add_bits_to_dist:\n"
+"        subb    %%cl, %%bl\n"
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"                 /* (1 << op) - 1 */
+"        andl    %%edx, %%eax\n"          /* eax &= hold */
+"        shrl    %%cl, %%edx\n"
+"        addl    %%eax, %%ebp\n"          /* dist += hold & ((1 << op) - 1) */
+
+".L_check_window:\n"
+"        movl    %%esi, 8(%%esp)\n"       /* save in so from can use it's reg */
+"        movl    %%edi, %%eax\n"
+"        subl    20(%%esp), %%eax\n"      /* nbytes = out - beg */
+
+"        cmpl    %%ebp, %%eax\n"
+"        jb      .L_clip_window\n"        /* if (dist > nbytes) 4.2% */
+
+"        movl    64(%%esp), %%ecx\n"      /* ecx = len */
+"        movl    %%edi, %%esi\n"
+"        subl    %%ebp, %%esi\n"          /* from = out - dist */
+
+"        sarl    %%ecx\n"
+"        jnc     .L_copy_two\n"           /* if len % 2 == 0 */
+
+"        rep     movsw\n"
+"        movb    (%%esi), %%al\n"
+"        movb    %%al, (%%edi)\n"
+"        incl    %%edi\n"
+
+"        movl    8(%%esp), %%esi\n"       /* move in back to %esi, toss from */
+"        movl    32(%%esp), %%ebp\n"      /* ebp = lcode */
+"        jmp     .L_while_test\n"
+
+".L_copy_two:\n"
+"        rep     movsw\n"
+"        movl    8(%%esp), %%esi\n"       /* move in back to %esi, toss from */
+"        movl    32(%%esp), %%ebp\n"      /* ebp = lcode */
+"        jmp     .L_while_test\n"
+
+".align 32,0x90\n"
+".L_check_dist_one:\n"
+"        cmpl    $1, %%ebp\n"            /* if dist 1, is a memset */
+"        jne     .L_check_window\n"
+"        cmpl    %%edi, 20(%%esp)\n"
+"        je      .L_check_window\n"      /* out == beg, if outside window */
+
+"        movl    64(%%esp), %%ecx\n"      /* ecx = len */
+"        movb    -1(%%edi), %%al\n"
+"        movb    %%al, %%ah\n"
+
+"        sarl    %%ecx\n"
+"        jnc     .L_set_two\n"
+"        movb    %%al, (%%edi)\n"
+"        incl    %%edi\n"
+
+".L_set_two:\n"
+"        rep     stosw\n"
+"        movl    32(%%esp), %%ebp\n"      /* ebp = lcode */
+"        jmp     .L_while_test\n"
+
+".align 32,0x90\n"
+".L_test_for_second_level_length:\n"
+"        testb   $64, %%al\n"
+"        jnz     .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */
+
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"
+"        andl    %%edx, %%eax\n"         /* eax &= hold */
+"        addl    64(%%esp), %%eax\n"     /* eax += len */
+"        movl    (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/
+"        jmp     .L_dolen\n"
+
+".align 32,0x90\n"
+".L_test_for_second_level_dist:\n"
+"        testb   $64, %%al\n"
+"        jnz     .L_invalid_distance_code\n" /* if ((op & 64) != 0) */
+
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"
+"        andl    %%edx, %%eax\n"         /* eax &= hold */
+"        addl    %%ebp, %%eax\n"         /* eax += dist */
+"        movl    36(%%esp), %%ecx\n"     /* ecx = dcode */
+"        movl    (%%ecx,%%eax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/
+"        jmp     .L_dodist\n"
+
+".align 32,0x90\n"
+".L_clip_window:\n"
+"        movl    %%eax, %%ecx\n"
+"        movl    48(%%esp), %%eax\n"     /* eax = wsize */
+"        negl    %%ecx\n"                /* nbytes = -nbytes */
+"        movl    28(%%esp), %%esi\n"     /* from = window */
+
+"        cmpl    %%ebp, %%eax\n"
+"        jb      .L_invalid_distance_too_far\n" /* if (dist > wsize) */
+
+"        addl    %%ebp, %%ecx\n"         /* nbytes = dist - nbytes */
+"        cmpl    $0, 52(%%esp)\n"
+"        jne     .L_wrap_around_window\n" /* if (write != 0) */
+
+"        subl    %%ecx, %%eax\n"
+"        addl    %%eax, %%esi\n"         /* from += wsize - nbytes */
+
+"        movl    64(%%esp), %%eax\n"     /* eax = len */
+"        cmpl    %%ecx, %%eax\n"
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
+"        rep     movsb\n"
+"        movl    %%edi, %%esi\n"
+"        subl    %%ebp, %%esi\n"         /* from = out - dist */
+"        jmp     .L_do_copy\n"
+
+".align 32,0x90\n"
+".L_wrap_around_window:\n"
+"        movl    52(%%esp), %%eax\n"     /* eax = write */
+"        cmpl    %%eax, %%ecx\n"
+"        jbe     .L_contiguous_in_window\n" /* if (write >= nbytes) */
+
+"        addl    48(%%esp), %%esi\n"     /* from += wsize */
+"        addl    %%eax, %%esi\n"         /* from += write */
+"        subl    %%ecx, %%esi\n"         /* from -= nbytes */
+"        subl    %%eax, %%ecx\n"         /* nbytes -= write */
+
+"        movl    64(%%esp), %%eax\n"     /* eax = len */
+"        cmpl    %%ecx, %%eax\n"
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
+"        rep     movsb\n"
+"        movl    28(%%esp), %%esi\n"     /* from = window */
+"        movl    52(%%esp), %%ecx\n"     /* nbytes = write */
+"        cmpl    %%ecx, %%eax\n"
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
+"        rep     movsb\n"
+"        movl    %%edi, %%esi\n"
+"        subl    %%ebp, %%esi\n"         /* from = out - dist */
+"        jmp     .L_do_copy\n"
+
+".align 32,0x90\n"
+".L_contiguous_in_window:\n"
+"        addl    %%eax, %%esi\n"
+"        subl    %%ecx, %%esi\n"         /* from += write - nbytes */
+
+"        movl    64(%%esp), %%eax\n"     /* eax = len */
+"        cmpl    %%ecx, %%eax\n"
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
+"        rep     movsb\n"
+"        movl    %%edi, %%esi\n"
+"        subl    %%ebp, %%esi\n"         /* from = out - dist */
+"        jmp     .L_do_copy\n"           /* if (nbytes >= len) */
+
+".align 32,0x90\n"
+".L_do_copy:\n"
+"        movl    %%eax, %%ecx\n"
+"        rep     movsb\n"
+
+"        movl    8(%%esp), %%esi\n"      /* move in back to %esi, toss from */
+"        movl    32(%%esp), %%ebp\n"     /* ebp = lcode */
+"        jmp     .L_while_test\n"
+
+".L_test_for_end_of_block:\n"
+"        testb   $32, %%al\n"
+"        jz      .L_invalid_literal_length_code\n"
+"        movl    $1, 72(%%esp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_invalid_literal_length_code:\n"
+"        movl    $2, 72(%%esp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_invalid_distance_code:\n"
+"        movl    $3, 72(%%esp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_invalid_distance_too_far:\n"
+"        movl    8(%%esp), %%esi\n"
+"        movl    $4, 72(%%esp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_break_loop:\n"
+"        movl    $0, 72(%%esp)\n"
+
+".L_break_loop_with_status:\n"
+/* put in, out, bits, and hold back into ar and pop esp */
+"        movl    %%esi, 8(%%esp)\n"      /* save in */
+"        movl    %%edi, 16(%%esp)\n"     /* save out */
+"        movl    %%ebx, 44(%%esp)\n"     /* save bits */
+"        movl    %%edx, 40(%%esp)\n"     /* save hold */
+"        movl    4(%%esp), %%ebp\n"      /* restore esp, ebp */
+"        movl    (%%esp), %%esp\n"
+          :
+          : "m" (ar)
+          : "memory", "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi"
+    );
+#elif defined( _MSC_VER ) && ! defined( _M_AMD64 )
+    __asm {
+	lea	eax, ar
+	mov	[eax], esp         /* save esp, ebp */
+	mov	[eax+4], ebp
+	mov	esp, eax
+	mov	esi, [esp+8]       /* esi = in */
+	mov	edi, [esp+16]      /* edi = out */
+	mov	edx, [esp+40]      /* edx = hold */
+	mov	ebx, [esp+44]      /* ebx = bits */
+	mov	ebp, [esp+32]      /* ebp = lcode */
+
+	cld
+	jmp	L_do_loop
+
+ALIGN 4
+L_while_test:
+	cmp	[esp+24], edi
+	jbe	L_break_loop
+	cmp	[esp+12], esi
+	jbe	L_break_loop
+
+L_do_loop:
+	cmp	bl, 15
+	ja	L_get_length_code    /* if (15 < bits) */
+
+	xor	eax, eax
+	lodsw                         /* al = *(ushort *)in++ */
+	mov	cl, bl            /* cl = bits, needs it for shifting */
+	add	bl, 16             /* bits += 16 */
+	shl	eax, cl
+	or	edx, eax        /* hold |= *((ushort *)in)++ << bits */
+
+L_get_length_code:
+	mov	eax, [esp+56]      /* eax = lmask */
+	and	eax, edx          /* eax &= hold */
+	mov	eax, [ebp+eax*4] /* eax = lcode[hold & lmask] */
+
+L_dolen:
+	mov	cl, ah            /* cl = this.bits */
+	sub	bl, ah            /* bits -= this.bits */
+	shr	edx, cl           /* hold >>= this.bits */
+
+	test	al, al
+	jnz	L_test_for_length_base /* if (op != 0) 45.7% */
+
+	shr	eax, 16            /* output this.val char */
+	stosb
+	jmp	L_while_test
+
+ALIGN 4
+L_test_for_length_base:
+	mov	ecx, eax          /* len = this */
+	shr	ecx, 16            /* len = this.val */
+	mov	[esp+64], ecx      /* save len */
+	mov	cl, al
+
+	test	al, 16
+	jz	L_test_for_second_level_length /* if ((op & 16) == 0) 8% */
+	and	cl, 15             /* op &= 15 */
+	jz	L_decode_distance    /* if (!op) */
+	cmp	bl, cl
+	jae	L_add_bits_to_len    /* if (op <= bits) */
+
+	mov	ch, cl            /* stash op in ch, freeing cl */
+	xor	eax, eax
+	lodsw                         /* al = *(ushort *)in++ */
+	mov	cl, bl            /* cl = bits, needs it for shifting */
+	add	bl, 16             /* bits += 16 */
+	shl	eax, cl
+	or	edx, eax         /* hold |= *((ushort *)in)++ << bits */
+	mov	cl, ch            /* move op back to ecx */
+
+L_add_bits_to_len:
+	sub	bl, cl
+	xor	eax, eax
+	inc	eax
+	shl	eax, cl
+	dec	eax
+	and	eax, edx          /* eax &= hold */
+	shr	edx, cl
+	add	[esp+64], eax      /* len += hold & mask[op] */
+
+L_decode_distance:
+	cmp	bl, 15
+	ja	L_get_distance_code  /* if (15 < bits) */
+
+	xor	eax, eax
+	lodsw                         /* al = *(ushort *)in++ */
+	mov	cl, bl            /* cl = bits, needs it for shifting */
+	add	bl, 16             /* bits += 16 */
+	shl	eax, cl
+	or	edx, eax         /* hold |= *((ushort *)in)++ << bits */
+
+L_get_distance_code:
+	mov	eax, [esp+60]      /* eax = dmask */
+	mov	ecx, [esp+36]      /* ecx = dcode */
+	and	eax, edx          /* eax &= hold */
+	mov	eax, [ecx+eax*4]/* eax = dcode[hold & dmask] */
+
+L_dodist:
+	mov	ebp, eax          /* dist = this */
+	shr	ebp, 16            /* dist = this.val */
+	mov	cl, ah
+	sub	bl, ah            /* bits -= this.bits */
+	shr	edx, cl           /* hold >>= this.bits */
+	mov	cl, al            /* cl = this.op */
+
+	test	al, 16             /* if ((op & 16) == 0) */
+	jz	L_test_for_second_level_dist
+	and	cl, 15             /* op &= 15 */
+	jz	L_check_dist_one
+	cmp	bl, cl
+	jae	L_add_bits_to_dist   /* if (op <= bits) 97.6% */
+
+	mov	ch, cl            /* stash op in ch, freeing cl */
+	xor	eax, eax
+	lodsw                         /* al = *(ushort *)in++ */
+	mov	cl, bl            /* cl = bits, needs it for shifting */
+	add	bl, 16             /* bits += 16 */
+	shl	eax, cl
+	or	edx, eax        /* hold |= *((ushort *)in)++ << bits */
+	mov	cl, ch            /* move op back to ecx */
+
+L_add_bits_to_dist:
+	sub	bl, cl
+	xor	eax, eax
+	inc	eax
+	shl	eax, cl
+	dec	eax                 /* (1 << op) - 1 */
+	and	eax, edx          /* eax &= hold */
+	shr	edx, cl
+	add	ebp, eax          /* dist += hold & ((1 << op) - 1) */
+
+L_check_window:
+	mov	[esp+8], esi       /* save in so from can use it's reg */
+	mov	eax, edi
+	sub	eax, [esp+20]      /* nbytes = out - beg */
+
+	cmp	eax, ebp
+	jb	L_clip_window        /* if (dist > nbytes) 4.2% */
+
+	mov	ecx, [esp+64]      /* ecx = len */
+	mov	esi, edi
+	sub	esi, ebp          /* from = out - dist */
+
+	sar	ecx, 1
+	jnc	L_copy_two
+
+	rep     movsw
+	mov	al, [esi]
+	mov	[edi], al
+	inc	edi
+
+	mov	esi, [esp+8]      /* move in back to %esi, toss from */
+	mov	ebp, [esp+32]     /* ebp = lcode */
+	jmp	L_while_test
+
+L_copy_two:
+	rep     movsw
+	mov	esi, [esp+8]      /* move in back to %esi, toss from */
+	mov	ebp, [esp+32]     /* ebp = lcode */
+	jmp	L_while_test
+
+ALIGN 4
+L_check_dist_one:
+	cmp	ebp, 1            /* if dist 1, is a memset */
+	jne	L_check_window
+	cmp	[esp+20], edi
+	je	L_check_window    /* out == beg, if outside window */
+
+	mov	ecx, [esp+64]     /* ecx = len */
+	mov	al, [edi-1]
+	mov	ah, al
+
+	sar	ecx, 1
+	jnc	L_set_two
+	mov	[edi], al         /* memset out with from[-1] */
+	inc	edi
+
+L_set_two:
+	rep     stosw
+	mov	ebp, [esp+32]     /* ebp = lcode */
+	jmp	L_while_test
+
+ALIGN 4
+L_test_for_second_level_length:
+	test	al, 64
+	jnz	L_test_for_end_of_block /* if ((op & 64) != 0) */
+
+	xor	eax, eax
+	inc	eax
+	shl	eax, cl
+	dec	eax
+	and	eax, edx         /* eax &= hold */
+	add	eax, [esp+64]     /* eax += len */
+	mov	eax, [ebp+eax*4] /* eax = lcode[val+(hold&mask[op])]*/
+	jmp	L_dolen
+
+ALIGN 4
+L_test_for_second_level_dist:
+	test	al, 64
+	jnz	L_invalid_distance_code /* if ((op & 64) != 0) */
+
+	xor	eax, eax
+	inc	eax
+	shl	eax, cl
+	dec	eax
+	and	eax, edx         /* eax &= hold */
+	add	eax, ebp         /* eax += dist */
+	mov	ecx, [esp+36]     /* ecx = dcode */
+	mov	eax, [ecx+eax*4] /* eax = dcode[val+(hold&mask[op])]*/
+	jmp	L_dodist
+
+ALIGN 4
+L_clip_window:
+	mov	ecx, eax
+	mov	eax, [esp+48]     /* eax = wsize */
+	neg	ecx                /* nbytes = -nbytes */
+	mov	esi, [esp+28]     /* from = window */
+
+	cmp	eax, ebp
+	jb	L_invalid_distance_too_far /* if (dist > wsize) */
+
+	add	ecx, ebp         /* nbytes = dist - nbytes */
+	cmp	dword ptr [esp+52], 0
+	jne	L_wrap_around_window /* if (write != 0) */
+
+	sub	eax, ecx
+	add	esi, eax         /* from += wsize - nbytes */
+
+	mov	eax, [esp+64]    /* eax = len */
+	cmp	eax, ecx
+	jbe	L_do_copy          /* if (nbytes >= len) */
+
+	sub	eax, ecx         /* len -= nbytes */
+	rep     movsb
+	mov	esi, edi
+	sub	esi, ebp         /* from = out - dist */
+	jmp	L_do_copy
+
+ALIGN 4
+L_wrap_around_window:
+	mov	eax, [esp+52]    /* eax = write */
+	cmp	ecx, eax
+	jbe	L_contiguous_in_window /* if (write >= nbytes) */
+
+	add	esi, [esp+48]    /* from += wsize */
+	add	esi, eax         /* from += write */
+	sub	esi, ecx         /* from -= nbytes */
+	sub	ecx, eax         /* nbytes -= write */
+
+	mov	eax, [esp+64]    /* eax = len */
+	cmp	eax, ecx
+	jbe	L_do_copy          /* if (nbytes >= len) */
+
+	sub	eax, ecx         /* len -= nbytes */
+	rep     movsb
+	mov	esi, [esp+28]     /* from = window */
+	mov	ecx, [esp+52]     /* nbytes = write */
+	cmp	eax, ecx
+	jbe	L_do_copy          /* if (nbytes >= len) */
+
+	sub	eax, ecx         /* len -= nbytes */
+	rep     movsb
+	mov	esi, edi
+	sub	esi, ebp         /* from = out - dist */
+	jmp	L_do_copy
+
+ALIGN 4
+L_contiguous_in_window:
+	add	esi, eax
+	sub	esi, ecx         /* from += write - nbytes */
+
+	mov	eax, [esp+64]    /* eax = len */
+	cmp	eax, ecx
+	jbe	L_do_copy          /* if (nbytes >= len) */
+
+	sub	eax, ecx         /* len -= nbytes */
+	rep     movsb
+	mov	esi, edi
+	sub	esi, ebp         /* from = out - dist */
+	jmp	L_do_copy
+
+ALIGN 4
+L_do_copy:
+	mov	ecx, eax
+	rep     movsb
+
+	mov	esi, [esp+8]      /* move in back to %esi, toss from */
+	mov	ebp, [esp+32]     /* ebp = lcode */
+	jmp	L_while_test
+
+L_test_for_end_of_block:
+	test	al, 32
+	jz	L_invalid_literal_length_code
+	mov	dword ptr [esp+72], 1
+	jmp	L_break_loop_with_status
+
+L_invalid_literal_length_code:
+	mov	dword ptr [esp+72], 2
+	jmp	L_break_loop_with_status
+
+L_invalid_distance_code:
+	mov	dword ptr [esp+72], 3
+	jmp	L_break_loop_with_status
+
+L_invalid_distance_too_far:
+	mov	esi, [esp+4]
+	mov	dword ptr [esp+72], 4
+	jmp	L_break_loop_with_status
+
+L_break_loop:
+	mov	dword ptr [esp+72], 0
+
+L_break_loop_with_status:
+/* put in, out, bits, and hold back into ar and pop esp */
+	mov	[esp+8], esi     /* save in */
+	mov	[esp+16], edi    /* save out */
+	mov	[esp+44], ebx    /* save bits */
+	mov	[esp+40], edx    /* save hold */
+	mov	ebp, [esp+4]     /* restore esp, ebp */
+	mov	esp, [esp]
+    }
+#else
+#error "x86 architecture not defined"
+#endif
+
+    if (ar.status > 1) {
+        if (ar.status == 2)
+            strm->msg = "invalid literal/length code";
+        else if (ar.status == 3)
+            strm->msg = "invalid distance code";
+        else
+            strm->msg = "invalid distance too far back";
+        state->mode = BAD;
+    }
+    else if ( ar.status == 1 ) {
+        state->mode = TYPE;
+    }
+
+    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+    ar.len = ar.bits >> 3;
+    ar.in -= ar.len;
+    ar.bits -= ar.len << 3;
+    ar.hold &= (1U << ar.bits) - 1;
+
+    /* update state and return */
+    strm->next_in = ar.in;
+    strm->next_out = ar.out;
+    strm->avail_in = (unsigned)(ar.in < ar.last ?
+                                PAD_AVAIL_IN + (ar.last - ar.in) :
+                                PAD_AVAIL_IN - (ar.in - ar.last));
+    strm->avail_out = (unsigned)(ar.out < ar.end ?
+                                 PAD_AVAIL_OUT + (ar.end - ar.out) :
+                                 PAD_AVAIL_OUT - (ar.out - ar.end));
+    state->hold = ar.hold;
+    state->bits = ar.bits;
+    return;
+}
+
Index: /trunk/minix/lib/zlib-1.2.3/contrib/inflate86/inffast.S
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/inflate86/inffast.S	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/inflate86/inffast.S	(revision 9)
@@ -0,0 +1,1368 @@
+/*
+ * inffast.S is a hand tuned assembler version of:
+ *
+ * inffast.c -- fast decoding
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Copyright (C) 2003 Chris Anderson <christop@charm.net>
+ * Please use the copyright conditions above.
+ *
+ * This version (Jan-23-2003) of inflate_fast was coded and tested under
+ * GNU/Linux on a pentium 3, using the gcc-3.2 compiler distribution.  On that
+ * machine, I found that gzip style archives decompressed about 20% faster than
+ * the gcc-3.2 -O3 -fomit-frame-pointer compiled version.  Your results will
+ * depend on how large of a buffer is used for z_stream.next_in & next_out
+ * (8K-32K worked best for my 256K cpu cache) and how much overhead there is in
+ * stream processing I/O and crc32/addler32.  In my case, this routine used
+ * 70% of the cpu time and crc32 used 20%.
+ *
+ * I am confident that this version will work in the general case, but I have
+ * not tested a wide variety of datasets or a wide variety of platforms.
+ *
+ * Jan-24-2003 -- Added -DUSE_MMX define for slightly faster inflating.
+ * It should be a runtime flag instead of compile time flag...
+ *
+ * Jan-26-2003 -- Added runtime check for MMX support with cpuid instruction.
+ * With -DUSE_MMX, only MMX code is compiled.  With -DNO_MMX, only non-MMX code
+ * is compiled.  Without either option, runtime detection is enabled.  Runtime
+ * detection should work on all modern cpus and the recomended algorithm (flip
+ * ID bit on eflags and then use the cpuid instruction) is used in many
+ * multimedia applications.  Tested under win2k with gcc-2.95 and gas-2.12
+ * distributed with cygwin3.  Compiling with gcc-2.95 -c inffast.S -o
+ * inffast.obj generates a COFF object which can then be linked with MSVC++
+ * compiled code.  Tested under FreeBSD 4.7 with gcc-2.95.
+ *
+ * Jan-28-2003 -- Tested Athlon XP... MMX mode is slower than no MMX (and
+ * slower than compiler generated code).  Adjusted cpuid check to use the MMX
+ * code only for Pentiums < P4 until I have more data on the P4.  Speed
+ * improvment is only about 15% on the Athlon when compared with code generated
+ * with MSVC++.  Not sure yet, but I think the P4 will also be slower using the
+ * MMX mode because many of it's x86 ALU instructions execute in .5 cycles and
+ * have less latency than MMX ops.  Added code to buffer the last 11 bytes of
+ * the input stream since the MMX code grabs bits in chunks of 32, which
+ * differs from the inffast.c algorithm.  I don't think there would have been
+ * read overruns where a page boundary was crossed (a segfault), but there
+ * could have been overruns when next_in ends on unaligned memory (unintialized
+ * memory read).
+ *
+ * Mar-13-2003 -- P4 MMX is slightly slower than P4 NO_MMX.  I created a C
+ * version of the non-MMX code so that it doesn't depend on zstrm and zstate
+ * structure offsets which are hard coded in this file.  This was last tested
+ * with zlib-1.2.0 which is currently in beta testing, newer versions of this
+ * and inffas86.c can be found at http://www.eetbeetee.com/zlib/ and
+ * http://www.charm.net/~christop/zlib/
+ */
+
+
+/*
+ * if you have underscore linking problems (_inflate_fast undefined), try
+ * using -DGAS_COFF
+ */
+#if ! defined( GAS_COFF ) && ! defined( GAS_ELF )
+
+#if defined( WIN32 ) || defined( __CYGWIN__ )
+#define GAS_COFF /* windows object format */
+#else
+#define GAS_ELF
+#endif
+
+#endif /* ! GAS_COFF && ! GAS_ELF */
+
+
+#if defined( GAS_COFF )
+
+/* coff externals have underscores */
+#define inflate_fast _inflate_fast
+#define inflate_fast_use_mmx _inflate_fast_use_mmx
+
+#endif /* GAS_COFF */
+
+
+.file "inffast.S"
+
+.globl inflate_fast
+
+.text
+.align 4,0
+.L_invalid_literal_length_code_msg:
+.string "invalid literal/length code"
+
+.align 4,0
+.L_invalid_distance_code_msg:
+.string "invalid distance code"
+
+.align 4,0
+.L_invalid_distance_too_far_msg:
+.string "invalid distance too far back"
+
+#if ! defined( NO_MMX )
+.align 4,0
+.L_mask: /* mask[N] = ( 1 << N ) - 1 */
+.long 0
+.long 1
+.long 3
+.long 7
+.long 15
+.long 31
+.long 63
+.long 127
+.long 255
+.long 511
+.long 1023
+.long 2047
+.long 4095
+.long 8191
+.long 16383
+.long 32767
+.long 65535
+.long 131071
+.long 262143
+.long 524287
+.long 1048575
+.long 2097151
+.long 4194303
+.long 8388607
+.long 16777215
+.long 33554431
+.long 67108863
+.long 134217727
+.long 268435455
+.long 536870911
+.long 1073741823
+.long 2147483647
+.long 4294967295
+#endif /* NO_MMX */
+
+.text
+
+/*
+ * struct z_stream offsets, in zlib.h
+ */
+#define next_in_strm   0   /* strm->next_in */
+#define avail_in_strm  4   /* strm->avail_in */
+#define next_out_strm  12  /* strm->next_out */
+#define avail_out_strm 16  /* strm->avail_out */
+#define msg_strm       24  /* strm->msg */
+#define state_strm     28  /* strm->state */
+
+/*
+ * struct inflate_state offsets, in inflate.h
+ */
+#define mode_state     0   /* state->mode */
+#define wsize_state    32  /* state->wsize */
+#define write_state    40  /* state->write */
+#define window_state   44  /* state->window */
+#define hold_state     48  /* state->hold */
+#define bits_state     52  /* state->bits */
+#define lencode_state  68  /* state->lencode */
+#define distcode_state 72  /* state->distcode */
+#define lenbits_state  76  /* state->lenbits */
+#define distbits_state 80  /* state->distbits */
+
+/*
+ * inflate_fast's activation record
+ */
+#define local_var_size 64 /* how much local space for vars */
+#define strm_sp        88 /* first arg: z_stream * (local_var_size + 24) */
+#define start_sp       92 /* second arg: unsigned int (local_var_size + 28) */
+
+/*
+ * offsets for local vars on stack
+ */
+#define out            60  /* unsigned char* */
+#define window         56  /* unsigned char* */
+#define wsize          52  /* unsigned int */
+#define write          48  /* unsigned int */
+#define in             44  /* unsigned char* */
+#define beg            40  /* unsigned char* */
+#define buf            28  /* char[ 12 ] */
+#define len            24  /* unsigned int */
+#define last           20  /* unsigned char* */
+#define end            16  /* unsigned char* */
+#define dcode          12  /* code* */
+#define lcode           8  /* code* */
+#define dmask           4  /* unsigned int */
+#define lmask           0  /* unsigned int */
+
+/*
+ * typedef enum inflate_mode consts, in inflate.h
+ */
+#define INFLATE_MODE_TYPE 11  /* state->mode flags enum-ed in inflate.h */
+#define INFLATE_MODE_BAD  26
+
+
+#if ! defined( USE_MMX ) && ! defined( NO_MMX )
+
+#define RUN_TIME_MMX
+
+#define CHECK_MMX    1
+#define DO_USE_MMX   2
+#define DONT_USE_MMX 3
+
+.globl inflate_fast_use_mmx
+
+.data
+
+.align 4,0
+inflate_fast_use_mmx: /* integer flag for run time control 1=check,2=mmx,3=no */
+.long CHECK_MMX
+
+#if defined( GAS_ELF )
+/* elf info */
+.type   inflate_fast_use_mmx,@object
+.size   inflate_fast_use_mmx,4
+#endif
+
+#endif /* RUN_TIME_MMX */
+
+#if defined( GAS_COFF )
+/* coff info: scl 2 = extern, type 32 = function */
+.def inflate_fast; .scl 2; .type 32; .endef
+#endif
+
+.text
+
+.align 32,0x90
+inflate_fast:
+        pushl   %edi
+        pushl   %esi
+        pushl   %ebp
+        pushl   %ebx
+        pushf   /* save eflags (strm_sp, state_sp assumes this is 32 bits) */
+        subl    $local_var_size, %esp
+        cld
+
+#define strm_r  %esi
+#define state_r %edi
+
+        movl    strm_sp(%esp), strm_r
+        movl    state_strm(strm_r), state_r
+
+        /* in = strm->next_in;
+         * out = strm->next_out;
+         * last = in + strm->avail_in - 11;
+         * beg = out - (start - strm->avail_out);
+         * end = out + (strm->avail_out - 257);
+         */
+        movl    avail_in_strm(strm_r), %edx
+        movl    next_in_strm(strm_r), %eax
+
+        addl    %eax, %edx      /* avail_in += next_in */
+        subl    $11, %edx       /* avail_in -= 11 */
+
+        movl    %eax, in(%esp)
+        movl    %edx, last(%esp)
+
+        movl    start_sp(%esp), %ebp
+        movl    avail_out_strm(strm_r), %ecx
+        movl    next_out_strm(strm_r), %ebx
+
+        subl    %ecx, %ebp      /* start -= avail_out */
+        negl    %ebp            /* start = -start */
+        addl    %ebx, %ebp      /* start += next_out */
+
+        subl    $257, %ecx      /* avail_out -= 257 */
+        addl    %ebx, %ecx      /* avail_out += out */
+
+        movl    %ebx, out(%esp)
+        movl    %ebp, beg(%esp)
+        movl    %ecx, end(%esp)
+
+        /* wsize = state->wsize;
+         * write = state->write;
+         * window = state->window;
+         * hold = state->hold;
+         * bits = state->bits;
+         * lcode = state->lencode;
+         * dcode = state->distcode;
+         * lmask = ( 1 << state->lenbits ) - 1;
+         * dmask = ( 1 << state->distbits ) - 1;
+         */
+
+        movl    lencode_state(state_r), %eax
+        movl    distcode_state(state_r), %ecx
+
+        movl    %eax, lcode(%esp)
+        movl    %ecx, dcode(%esp)
+
+        movl    $1, %eax
+        movl    lenbits_state(state_r), %ecx
+        shll    %cl, %eax
+        decl    %eax
+        movl    %eax, lmask(%esp)
+
+        movl    $1, %eax
+        movl    distbits_state(state_r), %ecx
+        shll    %cl, %eax
+        decl    %eax
+        movl    %eax, dmask(%esp)
+
+        movl    wsize_state(state_r), %eax
+        movl    write_state(state_r), %ecx
+        movl    window_state(state_r), %edx
+
+        movl    %eax, wsize(%esp)
+        movl    %ecx, write(%esp)
+        movl    %edx, window(%esp)
+
+        movl    hold_state(state_r), %ebp
+        movl    bits_state(state_r), %ebx
+
+#undef strm_r
+#undef state_r
+
+#define in_r       %esi
+#define from_r     %esi
+#define out_r      %edi
+
+        movl    in(%esp), in_r
+        movl    last(%esp), %ecx
+        cmpl    in_r, %ecx
+        ja      .L_align_long           /* if in < last */
+
+        addl    $11, %ecx               /* ecx = &in[ avail_in ] */
+        subl    in_r, %ecx              /* ecx = avail_in */
+        movl    $12, %eax
+        subl    %ecx, %eax              /* eax = 12 - avail_in */
+        leal    buf(%esp), %edi
+        rep     movsb                   /* memcpy( buf, in, avail_in ) */
+        movl    %eax, %ecx
+        xorl    %eax, %eax
+        rep     stosb         /* memset( &buf[ avail_in ], 0, 12 - avail_in ) */
+        leal    buf(%esp), in_r         /* in = buf */
+        movl    in_r, last(%esp)        /* last = in, do just one iteration */
+        jmp     .L_is_aligned
+
+        /* align in_r on long boundary */
+.L_align_long:
+        testl   $3, in_r
+        jz      .L_is_aligned
+        xorl    %eax, %eax
+        movb    (in_r), %al
+        incl    in_r
+        movl    %ebx, %ecx
+        addl    $8, %ebx
+        shll    %cl, %eax
+        orl     %eax, %ebp
+        jmp     .L_align_long
+
+.L_is_aligned:
+        movl    out(%esp), out_r
+
+#if defined( NO_MMX )
+        jmp     .L_do_loop
+#endif
+
+#if defined( USE_MMX )
+        jmp     .L_init_mmx
+#endif
+
+/*** Runtime MMX check ***/
+
+#if defined( RUN_TIME_MMX )
+.L_check_mmx:
+        cmpl    $DO_USE_MMX, inflate_fast_use_mmx
+        je      .L_init_mmx
+        ja      .L_do_loop /* > 2 */
+
+        pushl   %eax
+        pushl   %ebx
+        pushl   %ecx
+        pushl   %edx
+        pushf
+        movl    (%esp), %eax      /* copy eflags to eax */
+        xorl    $0x200000, (%esp) /* try toggling ID bit of eflags (bit 21)
+                                   * to see if cpu supports cpuid...
+                                   * ID bit method not supported by NexGen but
+                                   * bios may load a cpuid instruction and
+                                   * cpuid may be disabled on Cyrix 5-6x86 */
+        popf
+        pushf
+        popl    %edx              /* copy new eflags to edx */
+        xorl    %eax, %edx        /* test if ID bit is flipped */
+        jz      .L_dont_use_mmx   /* not flipped if zero */
+        xorl    %eax, %eax
+        cpuid
+        cmpl    $0x756e6547, %ebx /* check for GenuineIntel in ebx,ecx,edx */
+        jne     .L_dont_use_mmx
+        cmpl    $0x6c65746e, %ecx
+        jne     .L_dont_use_mmx
+        cmpl    $0x49656e69, %edx
+        jne     .L_dont_use_mmx
+        movl    $1, %eax
+        cpuid                     /* get cpu features */
+        shrl    $8, %eax
+        andl    $15, %eax
+        cmpl    $6, %eax          /* check for Pentium family, is 0xf for P4 */
+        jne     .L_dont_use_mmx
+        testl   $0x800000, %edx   /* test if MMX feature is set (bit 23) */
+        jnz     .L_use_mmx
+        jmp     .L_dont_use_mmx
+.L_use_mmx:
+        movl    $DO_USE_MMX, inflate_fast_use_mmx
+        jmp     .L_check_mmx_pop
+.L_dont_use_mmx:
+        movl    $DONT_USE_MMX, inflate_fast_use_mmx
+.L_check_mmx_pop:
+        popl    %edx
+        popl    %ecx
+        popl    %ebx
+        popl    %eax
+        jmp     .L_check_mmx
+#endif
+
+
+/*** Non-MMX code ***/
+
+#if defined ( NO_MMX ) || defined( RUN_TIME_MMX )
+
+#define hold_r     %ebp
+#define bits_r     %bl
+#define bitslong_r %ebx
+
+.align 32,0x90
+.L_while_test:
+        /* while (in < last && out < end)
+         */
+        cmpl    out_r, end(%esp)
+        jbe     .L_break_loop           /* if (out >= end) */
+
+        cmpl    in_r, last(%esp)
+        jbe     .L_break_loop
+
+.L_do_loop:
+        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out
+         *
+         * do {
+         *   if (bits < 15) {
+         *     hold |= *((unsigned short *)in)++ << bits;
+         *     bits += 16
+         *   }
+         *   this = lcode[hold & lmask]
+         */
+        cmpb    $15, bits_r
+        ja      .L_get_length_code      /* if (15 < bits) */
+
+        xorl    %eax, %eax
+        lodsw                           /* al = *(ushort *)in++ */
+        movb    bits_r, %cl             /* cl = bits, needs it for shifting */
+        addb    $16, bits_r             /* bits += 16 */
+        shll    %cl, %eax
+        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */
+
+.L_get_length_code:
+        movl    lmask(%esp), %edx       /* edx = lmask */
+        movl    lcode(%esp), %ecx       /* ecx = lcode */
+        andl    hold_r, %edx            /* edx &= hold */
+        movl    (%ecx,%edx,4), %eax     /* eax = lcode[hold & lmask] */
+
+.L_dolen:
+        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out
+         *
+         * dolen:
+         *    bits -= this.bits;
+         *    hold >>= this.bits
+         */
+        movb    %ah, %cl                /* cl = this.bits */
+        subb    %ah, bits_r             /* bits -= this.bits */
+        shrl    %cl, hold_r             /* hold >>= this.bits */
+
+        /* check if op is a literal
+         * if (op == 0) {
+         *    PUP(out) = this.val;
+         *  }
+         */
+        testb   %al, %al
+        jnz     .L_test_for_length_base /* if (op != 0) 45.7% */
+
+        shrl    $16, %eax               /* output this.val char */
+        stosb
+        jmp     .L_while_test
+
+.L_test_for_length_base:
+        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = len
+         *
+         * else if (op & 16) {
+         *   len = this.val
+         *   op &= 15
+         *   if (op) {
+         *     if (op > bits) {
+         *       hold |= *((unsigned short *)in)++ << bits;
+         *       bits += 16
+         *     }
+         *     len += hold & mask[op];
+         *     bits -= op;
+         *     hold >>= op;
+         *   }
+         */
+#define len_r %edx
+        movl    %eax, len_r             /* len = this */
+        shrl    $16, len_r              /* len = this.val */
+        movb    %al, %cl
+
+        testb   $16, %al
+        jz      .L_test_for_second_level_length /* if ((op & 16) == 0) 8% */
+        andb    $15, %cl                /* op &= 15 */
+        jz      .L_save_len             /* if (!op) */
+        cmpb    %cl, bits_r
+        jae     .L_add_bits_to_len      /* if (op <= bits) */
+
+        movb    %cl, %ch                /* stash op in ch, freeing cl */
+        xorl    %eax, %eax
+        lodsw                           /* al = *(ushort *)in++ */
+        movb    bits_r, %cl             /* cl = bits, needs it for shifting */
+        addb    $16, bits_r             /* bits += 16 */
+        shll    %cl, %eax
+        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */
+        movb    %ch, %cl                /* move op back to ecx */
+
+.L_add_bits_to_len:
+        movl    $1, %eax
+        shll    %cl, %eax
+        decl    %eax
+        subb    %cl, bits_r
+        andl    hold_r, %eax            /* eax &= hold */
+        shrl    %cl, hold_r
+        addl    %eax, len_r             /* len += hold & mask[op] */
+
+.L_save_len:
+        movl    len_r, len(%esp)        /* save len */
+#undef  len_r
+
+.L_decode_distance:
+        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = dist
+         *
+         *   if (bits < 15) {
+         *     hold |= *((unsigned short *)in)++ << bits;
+         *     bits += 16
+         *   }
+         *   this = dcode[hold & dmask];
+         * dodist:
+         *   bits -= this.bits;
+         *   hold >>= this.bits;
+         *   op = this.op;
+         */
+
+        cmpb    $15, bits_r
+        ja      .L_get_distance_code    /* if (15 < bits) */
+
+        xorl    %eax, %eax
+        lodsw                           /* al = *(ushort *)in++ */
+        movb    bits_r, %cl             /* cl = bits, needs it for shifting */
+        addb    $16, bits_r             /* bits += 16 */
+        shll    %cl, %eax
+        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */
+
+.L_get_distance_code:
+        movl    dmask(%esp), %edx       /* edx = dmask */
+        movl    dcode(%esp), %ecx       /* ecx = dcode */
+        andl    hold_r, %edx            /* edx &= hold */
+        movl    (%ecx,%edx,4), %eax     /* eax = dcode[hold & dmask] */
+
+#define dist_r %edx
+.L_dodist:
+        movl    %eax, dist_r            /* dist = this */
+        shrl    $16, dist_r             /* dist = this.val */
+        movb    %ah, %cl
+        subb    %ah, bits_r             /* bits -= this.bits */
+        shrl    %cl, hold_r             /* hold >>= this.bits */
+
+        /* if (op & 16) {
+         *   dist = this.val
+         *   op &= 15
+         *   if (op > bits) {
+         *     hold |= *((unsigned short *)in)++ << bits;
+         *     bits += 16
+         *   }
+         *   dist += hold & mask[op];
+         *   bits -= op;
+         *   hold >>= op;
+         */
+        movb    %al, %cl                /* cl = this.op */
+
+        testb   $16, %al                /* if ((op & 16) == 0) */
+        jz      .L_test_for_second_level_dist
+        andb    $15, %cl                /* op &= 15 */
+        jz      .L_check_dist_one
+        cmpb    %cl, bits_r
+        jae     .L_add_bits_to_dist     /* if (op <= bits) 97.6% */
+
+        movb    %cl, %ch                /* stash op in ch, freeing cl */
+        xorl    %eax, %eax
+        lodsw                           /* al = *(ushort *)in++ */
+        movb    bits_r, %cl             /* cl = bits, needs it for shifting */
+        addb    $16, bits_r             /* bits += 16 */
+        shll    %cl, %eax
+        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */
+        movb    %ch, %cl                /* move op back to ecx */
+
+.L_add_bits_to_dist:
+        movl    $1, %eax
+        shll    %cl, %eax
+        decl    %eax                    /* (1 << op) - 1 */
+        subb    %cl, bits_r
+        andl    hold_r, %eax            /* eax &= hold */
+        shrl    %cl, hold_r
+        addl    %eax, dist_r            /* dist += hold & ((1 << op) - 1) */
+        jmp     .L_check_window
+
+.L_check_window:
+        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist
+         *       %ecx = nbytes
+         *
+         * nbytes = out - beg;
+         * if (dist <= nbytes) {
+         *   from = out - dist;
+         *   do {
+         *     PUP(out) = PUP(from);
+         *   } while (--len > 0) {
+         * }
+         */
+
+        movl    in_r, in(%esp)          /* save in so from can use it's reg */
+        movl    out_r, %eax
+        subl    beg(%esp), %eax         /* nbytes = out - beg */
+
+        cmpl    dist_r, %eax
+        jb      .L_clip_window          /* if (dist > nbytes) 4.2% */
+
+        movl    len(%esp), %ecx
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+
+        subl    $3, %ecx
+        movb    (from_r), %al
+        movb    %al, (out_r)
+        movb    1(from_r), %al
+        movb    2(from_r), %dl
+        addl    $3, from_r
+        movb    %al, 1(out_r)
+        movb    %dl, 2(out_r)
+        addl    $3, out_r
+        rep     movsb
+
+        movl    in(%esp), in_r          /* move in back to %esi, toss from */
+        jmp     .L_while_test
+
+.align 16,0x90
+.L_check_dist_one:
+        cmpl    $1, dist_r
+        jne     .L_check_window
+        cmpl    out_r, beg(%esp)
+        je      .L_check_window
+
+        decl    out_r
+        movl    len(%esp), %ecx
+        movb    (out_r), %al
+        subl    $3, %ecx
+
+        movb    %al, 1(out_r)
+        movb    %al, 2(out_r)
+        movb    %al, 3(out_r)
+        addl    $4, out_r
+        rep     stosb
+
+        jmp     .L_while_test
+
+.align 16,0x90
+.L_test_for_second_level_length:
+        /* else if ((op & 64) == 0) {
+         *   this = lcode[this.val + (hold & mask[op])];
+         * }
+         */
+        testb   $64, %al
+        jnz     .L_test_for_end_of_block  /* if ((op & 64) != 0) */
+
+        movl    $1, %eax
+        shll    %cl, %eax
+        decl    %eax
+        andl    hold_r, %eax            /* eax &= hold */
+        addl    %edx, %eax              /* eax += this.val */
+        movl    lcode(%esp), %edx       /* edx = lcode */
+        movl    (%edx,%eax,4), %eax     /* eax = lcode[val + (hold&mask[op])] */
+        jmp     .L_dolen
+
+.align 16,0x90
+.L_test_for_second_level_dist:
+        /* else if ((op & 64) == 0) {
+         *   this = dcode[this.val + (hold & mask[op])];
+         * }
+         */
+        testb   $64, %al
+        jnz     .L_invalid_distance_code  /* if ((op & 64) != 0) */
+
+        movl    $1, %eax
+        shll    %cl, %eax
+        decl    %eax
+        andl    hold_r, %eax            /* eax &= hold */
+        addl    %edx, %eax              /* eax += this.val */
+        movl    dcode(%esp), %edx       /* edx = dcode */
+        movl    (%edx,%eax,4), %eax     /* eax = dcode[val + (hold&mask[op])] */
+        jmp     .L_dodist
+
+.align 16,0x90
+.L_clip_window:
+        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist
+         *       %ecx = nbytes
+         *
+         * else {
+         *   if (dist > wsize) {
+         *     invalid distance
+         *   }
+         *   from = window;
+         *   nbytes = dist - nbytes;
+         *   if (write == 0) {
+         *     from += wsize - nbytes;
+         */
+#define nbytes_r %ecx
+        movl    %eax, nbytes_r
+        movl    wsize(%esp), %eax       /* prepare for dist compare */
+        negl    nbytes_r                /* nbytes = -nbytes */
+        movl    window(%esp), from_r    /* from = window */
+
+        cmpl    dist_r, %eax
+        jb      .L_invalid_distance_too_far /* if (dist > wsize) */
+
+        addl    dist_r, nbytes_r        /* nbytes = dist - nbytes */
+        cmpl    $0, write(%esp)
+        jne     .L_wrap_around_window   /* if (write != 0) */
+
+        subl    nbytes_r, %eax
+        addl    %eax, from_r            /* from += wsize - nbytes */
+
+        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist
+         *       %ecx = nbytes, %eax = len
+         *
+         *     if (nbytes < len) {
+         *       len -= nbytes;
+         *       do {
+         *         PUP(out) = PUP(from);
+         *       } while (--nbytes);
+         *       from = out - dist;
+         *     }
+         *   }
+         */
+#define len_r %eax
+        movl    len(%esp), len_r
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1             /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+        jmp     .L_do_copy1
+
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1             /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+        jmp     .L_do_copy1
+
+.L_wrap_around_window:
+        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist
+         *       %ecx = nbytes, %eax = write, %eax = len
+         *
+         *   else if (write < nbytes) {
+         *     from += wsize + write - nbytes;
+         *     nbytes -= write;
+         *     if (nbytes < len) {
+         *       len -= nbytes;
+         *       do {
+         *         PUP(out) = PUP(from);
+         *       } while (--nbytes);
+         *       from = window;
+         *       nbytes = write;
+         *       if (nbytes < len) {
+         *         len -= nbytes;
+         *         do {
+         *           PUP(out) = PUP(from);
+         *         } while(--nbytes);
+         *         from = out - dist;
+         *       }
+         *     }
+         *   }
+         */
+#define write_r %eax
+        movl    write(%esp), write_r
+        cmpl    write_r, nbytes_r
+        jbe     .L_contiguous_in_window /* if (write >= nbytes) */
+
+        addl    wsize(%esp), from_r
+        addl    write_r, from_r
+        subl    nbytes_r, from_r        /* from += wsize + write - nbytes */
+        subl    write_r, nbytes_r       /* nbytes -= write */
+#undef write_r
+
+        movl    len(%esp), len_r
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1             /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    window(%esp), from_r    /* from = window */
+        movl    write(%esp), nbytes_r   /* nbytes = write */
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1             /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+        jmp     .L_do_copy1
+
+.L_contiguous_in_window:
+        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist
+         *       %ecx = nbytes, %eax = write, %eax = len
+         *
+         *   else {
+         *     from += write - nbytes;
+         *     if (nbytes < len) {
+         *       len -= nbytes;
+         *       do {
+         *         PUP(out) = PUP(from);
+         *       } while (--nbytes);
+         *       from = out - dist;
+         *     }
+         *   }
+         */
+#define write_r %eax
+        addl    write_r, from_r
+        subl    nbytes_r, from_r        /* from += write - nbytes */
+#undef write_r
+
+        movl    len(%esp), len_r
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1             /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+
+.L_do_copy1:
+        /* regs: %esi = from, %esi = in, %ebp = hold, %bl = bits, %edi = out
+         *       %eax = len
+         *
+         *     while (len > 0) {
+         *       PUP(out) = PUP(from);
+         *       len--;
+         *     }
+         *   }
+         * } while (in < last && out < end);
+         */
+#undef nbytes_r
+#define in_r %esi
+        movl    len_r, %ecx
+        rep     movsb
+
+        movl    in(%esp), in_r          /* move in back to %esi, toss from */
+        jmp     .L_while_test
+
+#undef len_r
+#undef dist_r
+
+#endif /* NO_MMX || RUN_TIME_MMX */
+
+
+/*** MMX code ***/
+
+#if defined( USE_MMX ) || defined( RUN_TIME_MMX )
+
+.align 32,0x90
+.L_init_mmx:
+        emms
+
+#undef  bits_r
+#undef  bitslong_r
+#define bitslong_r %ebp
+#define hold_mm    %mm0
+        movd    %ebp, hold_mm
+        movl    %ebx, bitslong_r
+
+#define used_mm   %mm1
+#define dmask2_mm %mm2
+#define lmask2_mm %mm3
+#define lmask_mm  %mm4
+#define dmask_mm  %mm5
+#define tmp_mm    %mm6
+
+        movd    lmask(%esp), lmask_mm
+        movq    lmask_mm, lmask2_mm
+        movd    dmask(%esp), dmask_mm
+        movq    dmask_mm, dmask2_mm
+        pxor    used_mm, used_mm
+        movl    lcode(%esp), %ebx       /* ebx = lcode */
+        jmp     .L_do_loop_mmx
+
+.align 32,0x90
+.L_while_test_mmx:
+        /* while (in < last && out < end)
+         */
+        cmpl    out_r, end(%esp)
+        jbe     .L_break_loop           /* if (out >= end) */
+
+        cmpl    in_r, last(%esp)
+        jbe     .L_break_loop
+
+.L_do_loop_mmx:
+        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
+
+        cmpl    $32, bitslong_r
+        ja      .L_get_length_code_mmx  /* if (32 < bits) */
+
+        movd    bitslong_r, tmp_mm
+        movd    (in_r), %mm7
+        addl    $4, in_r
+        psllq   tmp_mm, %mm7
+        addl    $32, bitslong_r
+        por     %mm7, hold_mm           /* hold_mm |= *((uint *)in)++ << bits */
+
+.L_get_length_code_mmx:
+        pand    hold_mm, lmask_mm
+        movd    lmask_mm, %eax
+        movq    lmask2_mm, lmask_mm
+        movl    (%ebx,%eax,4), %eax     /* eax = lcode[hold & lmask] */
+
+.L_dolen_mmx:
+        movzbl  %ah, %ecx               /* ecx = this.bits */
+        movd    %ecx, used_mm
+        subl    %ecx, bitslong_r        /* bits -= this.bits */
+
+        testb   %al, %al
+        jnz     .L_test_for_length_base_mmx /* if (op != 0) 45.7% */
+
+        shrl    $16, %eax               /* output this.val char */
+        stosb
+        jmp     .L_while_test_mmx
+
+.L_test_for_length_base_mmx:
+#define len_r  %edx
+        movl    %eax, len_r             /* len = this */
+        shrl    $16, len_r              /* len = this.val */
+
+        testb   $16, %al
+        jz      .L_test_for_second_level_length_mmx /* if ((op & 16) == 0) 8% */
+        andl    $15, %eax               /* op &= 15 */
+        jz      .L_decode_distance_mmx  /* if (!op) */
+
+        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
+        movd    %eax, used_mm
+        movd    hold_mm, %ecx
+        subl    %eax, bitslong_r
+        andl    .L_mask(,%eax,4), %ecx
+        addl    %ecx, len_r             /* len += hold & mask[op] */
+
+.L_decode_distance_mmx:
+        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
+
+        cmpl    $32, bitslong_r
+        ja      .L_get_dist_code_mmx    /* if (32 < bits) */
+
+        movd    bitslong_r, tmp_mm
+        movd    (in_r), %mm7
+        addl    $4, in_r
+        psllq   tmp_mm, %mm7
+        addl    $32, bitslong_r
+        por     %mm7, hold_mm           /* hold_mm |= *((uint *)in)++ << bits */
+
+.L_get_dist_code_mmx:
+        movl    dcode(%esp), %ebx       /* ebx = dcode */
+        pand    hold_mm, dmask_mm
+        movd    dmask_mm, %eax
+        movq    dmask2_mm, dmask_mm
+        movl    (%ebx,%eax,4), %eax     /* eax = dcode[hold & lmask] */
+
+.L_dodist_mmx:
+#define dist_r %ebx
+        movzbl  %ah, %ecx               /* ecx = this.bits */
+        movl    %eax, dist_r
+        shrl    $16, dist_r             /* dist  = this.val */
+        subl    %ecx, bitslong_r        /* bits -= this.bits */
+        movd    %ecx, used_mm
+
+        testb   $16, %al                /* if ((op & 16) == 0) */
+        jz      .L_test_for_second_level_dist_mmx
+        andl    $15, %eax               /* op &= 15 */
+        jz      .L_check_dist_one_mmx
+
+.L_add_bits_to_dist_mmx:
+        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
+        movd    %eax, used_mm           /* save bit length of current op */
+        movd    hold_mm, %ecx           /* get the next bits on input stream */
+        subl    %eax, bitslong_r        /* bits -= op bits */
+        andl    .L_mask(,%eax,4), %ecx  /* ecx   = hold & mask[op] */
+        addl    %ecx, dist_r            /* dist += hold & mask[op] */
+
+.L_check_window_mmx:
+        movl    in_r, in(%esp)          /* save in so from can use it's reg */
+        movl    out_r, %eax
+        subl    beg(%esp), %eax         /* nbytes = out - beg */
+
+        cmpl    dist_r, %eax
+        jb      .L_clip_window_mmx      /* if (dist > nbytes) 4.2% */
+
+        movl    len_r, %ecx
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+
+        subl    $3, %ecx
+        movb    (from_r), %al
+        movb    %al, (out_r)
+        movb    1(from_r), %al
+        movb    2(from_r), %dl
+        addl    $3, from_r
+        movb    %al, 1(out_r)
+        movb    %dl, 2(out_r)
+        addl    $3, out_r
+        rep     movsb
+
+        movl    in(%esp), in_r          /* move in back to %esi, toss from */
+        movl    lcode(%esp), %ebx       /* move lcode back to %ebx, toss dist */
+        jmp     .L_while_test_mmx
+
+.align 16,0x90
+.L_check_dist_one_mmx:
+        cmpl    $1, dist_r
+        jne     .L_check_window_mmx
+        cmpl    out_r, beg(%esp)
+        je      .L_check_window_mmx
+
+        decl    out_r
+        movl    len_r, %ecx
+        movb    (out_r), %al
+        subl    $3, %ecx
+
+        movb    %al, 1(out_r)
+        movb    %al, 2(out_r)
+        movb    %al, 3(out_r)
+        addl    $4, out_r
+        rep     stosb
+
+        movl    lcode(%esp), %ebx       /* move lcode back to %ebx, toss dist */
+        jmp     .L_while_test_mmx
+
+.align 16,0x90
+.L_test_for_second_level_length_mmx:
+        testb   $64, %al
+        jnz     .L_test_for_end_of_block  /* if ((op & 64) != 0) */
+
+        andl    $15, %eax
+        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
+        movd    hold_mm, %ecx
+        andl    .L_mask(,%eax,4), %ecx
+        addl    len_r, %ecx
+        movl    (%ebx,%ecx,4), %eax     /* eax = lcode[hold & lmask] */
+        jmp     .L_dolen_mmx
+
+.align 16,0x90
+.L_test_for_second_level_dist_mmx:
+        testb   $64, %al
+        jnz     .L_invalid_distance_code  /* if ((op & 64) != 0) */
+
+        andl    $15, %eax
+        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
+        movd    hold_mm, %ecx
+        andl    .L_mask(,%eax,4), %ecx
+        movl    dcode(%esp), %eax       /* ecx = dcode */
+        addl    dist_r, %ecx
+        movl    (%eax,%ecx,4), %eax     /* eax = lcode[hold & lmask] */
+        jmp     .L_dodist_mmx
+
+.align 16,0x90
+.L_clip_window_mmx:
+#define nbytes_r %ecx
+        movl    %eax, nbytes_r
+        movl    wsize(%esp), %eax       /* prepare for dist compare */
+        negl    nbytes_r                /* nbytes = -nbytes */
+        movl    window(%esp), from_r    /* from = window */
+
+        cmpl    dist_r, %eax
+        jb      .L_invalid_distance_too_far /* if (dist > wsize) */
+
+        addl    dist_r, nbytes_r        /* nbytes = dist - nbytes */
+        cmpl    $0, write(%esp)
+        jne     .L_wrap_around_window_mmx /* if (write != 0) */
+
+        subl    nbytes_r, %eax
+        addl    %eax, from_r            /* from += wsize - nbytes */
+
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1_mmx         /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+        jmp     .L_do_copy1_mmx
+
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1_mmx         /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+        jmp     .L_do_copy1_mmx
+
+.L_wrap_around_window_mmx:
+#define write_r %eax
+        movl    write(%esp), write_r
+        cmpl    write_r, nbytes_r
+        jbe     .L_contiguous_in_window_mmx /* if (write >= nbytes) */
+
+        addl    wsize(%esp), from_r
+        addl    write_r, from_r
+        subl    nbytes_r, from_r        /* from += wsize + write - nbytes */
+        subl    write_r, nbytes_r       /* nbytes -= write */
+#undef write_r
+
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1_mmx         /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    window(%esp), from_r    /* from = window */
+        movl    write(%esp), nbytes_r   /* nbytes = write */
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1_mmx         /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+        jmp     .L_do_copy1_mmx
+
+.L_contiguous_in_window_mmx:
+#define write_r %eax
+        addl    write_r, from_r
+        subl    nbytes_r, from_r        /* from += write - nbytes */
+#undef write_r
+
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1_mmx         /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+
+.L_do_copy1_mmx:
+#undef nbytes_r
+#define in_r %esi
+        movl    len_r, %ecx
+        rep     movsb
+
+        movl    in(%esp), in_r          /* move in back to %esi, toss from */
+        movl    lcode(%esp), %ebx       /* move lcode back to %ebx, toss dist */
+        jmp     .L_while_test_mmx
+
+#undef hold_r
+#undef bitslong_r
+
+#endif /* USE_MMX || RUN_TIME_MMX */
+
+
+/*** USE_MMX, NO_MMX, and RUNTIME_MMX from here on ***/
+
+.L_invalid_distance_code:
+        /* else {
+         *   strm->msg = "invalid distance code";
+         *   state->mode = BAD;
+         * }
+         */
+        movl    $.L_invalid_distance_code_msg, %ecx
+        movl    $INFLATE_MODE_BAD, %edx
+        jmp     .L_update_stream_state
+
+.L_test_for_end_of_block:
+        /* else if (op & 32) {
+         *   state->mode = TYPE;
+         *   break;
+         * }
+         */
+        testb   $32, %al
+        jz      .L_invalid_literal_length_code  /* if ((op & 32) == 0) */
+
+        movl    $0, %ecx
+        movl    $INFLATE_MODE_TYPE, %edx
+        jmp     .L_update_stream_state
+
+.L_invalid_literal_length_code:
+        /* else {
+         *   strm->msg = "invalid literal/length code";
+         *   state->mode = BAD;
+         * }
+         */
+        movl    $.L_invalid_literal_length_code_msg, %ecx
+        movl    $INFLATE_MODE_BAD, %edx
+        jmp     .L_update_stream_state
+
+.L_invalid_distance_too_far:
+        /* strm->msg = "invalid distance too far back";
+         * state->mode = BAD;
+         */
+        movl    in(%esp), in_r          /* from_r has in's reg, put in back */
+        movl    $.L_invalid_distance_too_far_msg, %ecx
+        movl    $INFLATE_MODE_BAD, %edx
+        jmp     .L_update_stream_state
+
+.L_update_stream_state:
+        /* set strm->msg = %ecx, strm->state->mode = %edx */
+        movl    strm_sp(%esp), %eax
+        testl   %ecx, %ecx              /* if (msg != NULL) */
+        jz      .L_skip_msg
+        movl    %ecx, msg_strm(%eax)    /* strm->msg = msg */
+.L_skip_msg:
+        movl    state_strm(%eax), %eax  /* state = strm->state */
+        movl    %edx, mode_state(%eax)  /* state->mode = edx (BAD | TYPE) */
+        jmp     .L_break_loop
+
+.align 32,0x90
+.L_break_loop:
+
+/*
+ * Regs:
+ *
+ * bits = %ebp when mmx, and in %ebx when non-mmx
+ * hold = %hold_mm when mmx, and in %ebp when non-mmx
+ * in   = %esi
+ * out  = %edi
+ */
+
+#if defined( USE_MMX ) || defined( RUN_TIME_MMX )
+
+#if defined( RUN_TIME_MMX )
+
+        cmpl    $DO_USE_MMX, inflate_fast_use_mmx
+        jne     .L_update_next_in
+
+#endif /* RUN_TIME_MMX */
+
+        movl    %ebp, %ebx
+
+.L_update_next_in:
+
+#endif
+
+#define strm_r  %eax
+#define state_r %edx
+
+        /* len = bits >> 3;
+         * in -= len;
+         * bits -= len << 3;
+         * hold &= (1U << bits) - 1;
+         * state->hold = hold;
+         * state->bits = bits;
+         * strm->next_in = in;
+         * strm->next_out = out;
+         */
+        movl    strm_sp(%esp), strm_r
+        movl    %ebx, %ecx
+        movl    state_strm(strm_r), state_r
+        shrl    $3, %ecx
+        subl    %ecx, in_r
+        shll    $3, %ecx
+        subl    %ecx, %ebx
+        movl    out_r, next_out_strm(strm_r)
+        movl    %ebx, bits_state(state_r)
+        movl    %ebx, %ecx
+
+        leal    buf(%esp), %ebx
+        cmpl    %ebx, last(%esp)
+        jne     .L_buf_not_used         /* if buf != last */
+
+        subl    %ebx, in_r              /* in -= buf */
+        movl    next_in_strm(strm_r), %ebx
+        movl    %ebx, last(%esp)        /* last = strm->next_in */
+        addl    %ebx, in_r              /* in += strm->next_in */
+        movl    avail_in_strm(strm_r), %ebx
+        subl    $11, %ebx
+        addl    %ebx, last(%esp)    /* last = &strm->next_in[ avail_in - 11 ] */
+
+.L_buf_not_used:
+        movl    in_r, next_in_strm(strm_r)
+
+        movl    $1, %ebx
+        shll    %cl, %ebx
+        decl    %ebx
+
+#if defined( USE_MMX ) || defined( RUN_TIME_MMX )
+
+#if defined( RUN_TIME_MMX )
+
+        cmpl    $DO_USE_MMX, inflate_fast_use_mmx
+        jne     .L_update_hold
+
+#endif /* RUN_TIME_MMX */
+
+        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
+        movd    hold_mm, %ebp
+
+        emms
+
+.L_update_hold:
+
+#endif /* USE_MMX || RUN_TIME_MMX */
+
+        andl    %ebx, %ebp
+        movl    %ebp, hold_state(state_r)
+
+#define last_r %ebx
+
+        /* strm->avail_in = in < last ? 11 + (last - in) : 11 - (in - last) */
+        movl    last(%esp), last_r
+        cmpl    in_r, last_r
+        jbe     .L_last_is_smaller     /* if (in >= last) */
+
+        subl    in_r, last_r           /* last -= in */
+        addl    $11, last_r            /* last += 11 */
+        movl    last_r, avail_in_strm(strm_r)
+        jmp     .L_fixup_out
+.L_last_is_smaller:
+        subl    last_r, in_r           /* in -= last */
+        negl    in_r                   /* in = -in */
+        addl    $11, in_r              /* in += 11 */
+        movl    in_r, avail_in_strm(strm_r)
+
+#undef last_r
+#define end_r %ebx
+
+.L_fixup_out:
+        /* strm->avail_out = out < end ? 257 + (end - out) : 257 - (out - end)*/
+        movl    end(%esp), end_r
+        cmpl    out_r, end_r
+        jbe     .L_end_is_smaller      /* if (out >= end) */
+
+        subl    out_r, end_r           /* end -= out */
+        addl    $257, end_r            /* end += 257 */
+        movl    end_r, avail_out_strm(strm_r)
+        jmp     .L_done
+.L_end_is_smaller:
+        subl    end_r, out_r           /* out -= end */
+        negl    out_r                  /* out = -out */
+        addl    $257, out_r            /* out += 257 */
+        movl    out_r, avail_out_strm(strm_r)
+
+#undef end_r
+#undef strm_r
+#undef state_r
+
+.L_done:
+        addl    $local_var_size, %esp
+        popf
+        popl    %ebx
+        popl    %ebp
+        popl    %esi
+        popl    %edi
+        ret
+
+#if defined( GAS_ELF )
+/* elf info */
+.type inflate_fast,@function
+.size inflate_fast,.-inflate_fast
+#endif
Index: /trunk/minix/lib/zlib-1.2.3/contrib/iostream/test.cpp
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/iostream/test.cpp	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/iostream/test.cpp	(revision 9)
@@ -0,0 +1,24 @@
+
+#include "zfstream.h"
+
+int main() {
+
+  // Construct a stream object with this filebuffer.  Anything sent
+  // to this stream will go to standard out.
+  gzofstream os( 1, ios::out );
+
+  // This text is getting compressed and sent to stdout.
+  // To prove this, run 'test | zcat'.
+  os << "Hello, Mommy" << endl;
+
+  os << setcompressionlevel( Z_NO_COMPRESSION );
+  os << "hello, hello, hi, ho!" << endl;
+
+  setcompressionlevel( os, Z_DEFAULT_COMPRESSION )
+    << "I'm compressing again" << endl;
+
+  os.close();
+
+  return 0;
+
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/iostream/zfstream.cpp
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/iostream/zfstream.cpp	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/iostream/zfstream.cpp	(revision 9)
@@ -0,0 +1,329 @@
+
+#include "zfstream.h"
+
+gzfilebuf::gzfilebuf() :
+  file(NULL),
+  mode(0),
+  own_file_descriptor(0)
+{ }
+
+gzfilebuf::~gzfilebuf() {
+
+  sync();
+  if ( own_file_descriptor )
+    close();
+
+}
+
+gzfilebuf *gzfilebuf::open( const char *name,
+                            int io_mode ) {
+
+  if ( is_open() )
+    return NULL;
+
+  char char_mode[10];
+  char *p = char_mode;
+
+  if ( io_mode & ios::in ) {
+    mode = ios::in;
+    *p++ = 'r';
+  } else if ( io_mode & ios::app ) {
+    mode = ios::app;
+    *p++ = 'a';
+  } else {
+    mode = ios::out;
+    *p++ = 'w';
+  }
+
+  if ( io_mode & ios::binary ) {
+    mode |= ios::binary;
+    *p++ = 'b';
+  }
+
+  // Hard code the compression level
+  if ( io_mode & (ios::out|ios::app )) {
+    *p++ = '9';
+  }
+
+  // Put the end-of-string indicator
+  *p = '\0';
+
+  if ( (file = gzopen(name, char_mode)) == NULL )
+    return NULL;
+
+  own_file_descriptor = 1;
+
+  return this;
+
+}
+
+gzfilebuf *gzfilebuf::attach( int file_descriptor,
+                              int io_mode ) {
+
+  if ( is_open() )
+    return NULL;
+
+  char char_mode[10];
+  char *p = char_mode;
+
+  if ( io_mode & ios::in ) {
+    mode = ios::in;
+    *p++ = 'r';
+  } else if ( io_mode & ios::app ) {
+    mode = ios::app;
+    *p++ = 'a';
+  } else {
+    mode = ios::out;
+    *p++ = 'w';
+  }
+
+  if ( io_mode & ios::binary ) {
+    mode |= ios::binary;
+    *p++ = 'b';
+  }
+
+  // Hard code the compression level
+  if ( io_mode & (ios::out|ios::app )) {
+    *p++ = '9';
+  }
+
+  // Put the end-of-string indicator
+  *p = '\0';
+
+  if ( (file = gzdopen(file_descriptor, char_mode)) == NULL )
+    return NULL;
+
+  own_file_descriptor = 0;
+
+  return this;
+
+}
+
+gzfilebuf *gzfilebuf::close() {
+
+  if ( is_open() ) {
+
+    sync();
+    gzclose( file );
+    file = NULL;
+
+  }
+
+  return this;
+
+}
+
+int gzfilebuf::setcompressionlevel( int comp_level ) {
+
+  return gzsetparams(file, comp_level, -2);
+
+}
+
+int gzfilebuf::setcompressionstrategy( int comp_strategy ) {
+
+  return gzsetparams(file, -2, comp_strategy);
+
+}
+
+
+streampos gzfilebuf::seekoff( streamoff off, ios::seek_dir dir, int which ) {
+
+  return streampos(EOF);
+
+}
+
+int gzfilebuf::underflow() {
+
+  // If the file hasn't been opened for reading, error.
+  if ( !is_open() || !(mode & ios::in) )
+    return EOF;
+
+  // if a buffer doesn't exists, allocate one.
+  if ( !base() ) {
+
+    if ( (allocate()) == EOF )
+      return EOF;
+    setp(0,0);
+
+  } else {
+
+    if ( in_avail() )
+      return (unsigned char) *gptr();
+
+    if ( out_waiting() ) {
+      if ( flushbuf() == EOF )
+        return EOF;
+    }
+
+  }
+
+  // Attempt to fill the buffer.
+
+  int result = fillbuf();
+  if ( result == EOF ) {
+    // disable get area
+    setg(0,0,0);
+    return EOF;
+  }
+
+  return (unsigned char) *gptr();
+
+}
+
+int gzfilebuf::overflow( int c ) {
+
+  if ( !is_open() || !(mode & ios::out) )
+    return EOF;
+
+  if ( !base() ) {
+    if ( allocate() == EOF )
+      return EOF;
+    setg(0,0,0);
+  } else {
+    if (in_avail()) {
+        return EOF;
+    }
+    if (out_waiting()) {
+      if (flushbuf() == EOF)
+        return EOF;
+    }
+  }
+
+  int bl = blen();
+  setp( base(), base() + bl);
+
+  if ( c != EOF ) {
+
+    *pptr() = c;
+    pbump(1);
+
+  }
+
+  return 0;
+
+}
+
+int gzfilebuf::sync() {
+
+  if ( !is_open() )
+    return EOF;
+
+  if ( out_waiting() )
+    return flushbuf();
+
+  return 0;
+
+}
+
+int gzfilebuf::flushbuf() {
+
+  int n;
+  char *q;
+
+  q = pbase();
+  n = pptr() - q;
+
+  if ( gzwrite( file, q, n) < n )
+    return EOF;
+
+  setp(0,0);
+
+  return 0;
+
+}
+
+int gzfilebuf::fillbuf() {
+
+  int required;
+  char *p;
+
+  p = base();
+
+  required = blen();
+
+  int t = gzread( file, p, required );
+
+  if ( t <= 0) return EOF;
+
+  setg( base(), base(), base()+t);
+
+  return t;
+
+}
+
+gzfilestream_common::gzfilestream_common() :
+  ios( gzfilestream_common::rdbuf() )
+{ }
+
+gzfilestream_common::~gzfilestream_common()
+{ }
+
+void gzfilestream_common::attach( int fd, int io_mode ) {
+
+  if ( !buffer.attach( fd, io_mode) )
+    clear( ios::failbit | ios::badbit );
+  else
+    clear();
+
+}
+
+void gzfilestream_common::open( const char *name, int io_mode ) {
+
+  if ( !buffer.open( name, io_mode ) )
+    clear( ios::failbit | ios::badbit );
+  else
+    clear();
+
+}
+
+void gzfilestream_common::close() {
+
+  if ( !buffer.close() )
+    clear( ios::failbit | ios::badbit );
+
+}
+
+gzfilebuf *gzfilestream_common::rdbuf()
+{
+  return &buffer;
+}
+
+gzifstream::gzifstream() :
+  ios( gzfilestream_common::rdbuf() )
+{
+  clear( ios::badbit );
+}
+
+gzifstream::gzifstream( const char *name, int io_mode ) :
+  ios( gzfilestream_common::rdbuf() )
+{
+  gzfilestream_common::open( name, io_mode );
+}
+
+gzifstream::gzifstream( int fd, int io_mode ) :
+  ios( gzfilestream_common::rdbuf() )
+{
+  gzfilestream_common::attach( fd, io_mode );
+}
+
+gzifstream::~gzifstream() { }
+
+gzofstream::gzofstream() :
+  ios( gzfilestream_common::rdbuf() )
+{
+  clear( ios::badbit );
+}
+
+gzofstream::gzofstream( const char *name, int io_mode ) :
+  ios( gzfilestream_common::rdbuf() )
+{
+  gzfilestream_common::open( name, io_mode );
+}
+
+gzofstream::gzofstream( int fd, int io_mode ) :
+  ios( gzfilestream_common::rdbuf() )
+{
+  gzfilestream_common::attach( fd, io_mode );
+}
+
+gzofstream::~gzofstream() { }
Index: /trunk/minix/lib/zlib-1.2.3/contrib/iostream/zfstream.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/iostream/zfstream.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/iostream/zfstream.h	(revision 9)
@@ -0,0 +1,128 @@
+
+#ifndef zfstream_h
+#define zfstream_h
+
+#include <fstream.h>
+#include "zlib.h"
+
+class gzfilebuf : public streambuf {
+
+public:
+
+  gzfilebuf( );
+  virtual ~gzfilebuf();
+
+  gzfilebuf *open( const char *name, int io_mode );
+  gzfilebuf *attach( int file_descriptor, int io_mode );
+  gzfilebuf *close();
+
+  int setcompressionlevel( int comp_level );
+  int setcompressionstrategy( int comp_strategy );
+
+  inline int is_open() const { return (file !=NULL); }
+
+  virtual streampos seekoff( streamoff, ios::seek_dir, int );
+
+  virtual int sync();
+
+protected:
+
+  virtual int underflow();
+  virtual int overflow( int = EOF );
+
+private:
+
+  gzFile file;
+  short mode;
+  short own_file_descriptor;
+
+  int flushbuf();
+  int fillbuf();
+
+};
+
+class gzfilestream_common : virtual public ios {
+
+  friend class gzifstream;
+  friend class gzofstream;
+  friend gzofstream &setcompressionlevel( gzofstream &, int );
+  friend gzofstream &setcompressionstrategy( gzofstream &, int );
+
+public:
+  virtual ~gzfilestream_common();
+
+  void attach( int fd, int io_mode );
+  void open( const char *name, int io_mode );
+  void close();
+
+protected:
+  gzfilestream_common();
+
+private:
+  gzfilebuf *rdbuf();
+
+  gzfilebuf buffer;
+
+};
+
+class gzifstream : public gzfilestream_common, public istream {
+
+public:
+
+  gzifstream();
+  gzifstream( const char *name, int io_mode = ios::in );
+  gzifstream( int fd, int io_mode = ios::in );
+
+  virtual ~gzifstream();
+
+};
+
+class gzofstream : public gzfilestream_common, public ostream {
+
+public:
+
+  gzofstream();
+  gzofstream( const char *name, int io_mode = ios::out );
+  gzofstream( int fd, int io_mode = ios::out );
+
+  virtual ~gzofstream();
+
+};
+
+template<class T> class gzomanip {
+  friend gzofstream &operator<<(gzofstream &, const gzomanip<T> &);
+public:
+  gzomanip(gzofstream &(*f)(gzofstream &, T), T v) : func(f), val(v) { }
+private:
+  gzofstream &(*func)(gzofstream &, T);
+  T val;
+};
+
+template<class T> gzofstream &operator<<(gzofstream &s, const gzomanip<T> &m)
+{
+  return (*m.func)(s, m.val);
+}
+
+inline gzofstream &setcompressionlevel( gzofstream &s, int l )
+{
+  (s.rdbuf())->setcompressionlevel(l);
+  return s;
+}
+
+inline gzofstream &setcompressionstrategy( gzofstream &s, int l )
+{
+  (s.rdbuf())->setcompressionstrategy(l);
+  return s;
+}
+
+inline gzomanip<int> setcompressionlevel(int l)
+{
+  return gzomanip<int>(&setcompressionlevel,l);
+}
+
+inline gzomanip<int> setcompressionstrategy(int l)
+{
+  return gzomanip<int>(&setcompressionstrategy,l);
+}
+
+#endif
Index: /trunk/minix/lib/zlib-1.2.3/contrib/iostream2/zstream.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/iostream2/zstream.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/iostream2/zstream.h	(revision 9)
@@ -0,0 +1,307 @@
+/*
+ *
+ * Copyright (c) 1997
+ * Christian Michelsen Research AS
+ * Advanced Computing
+ * Fantoftvegen 38, 5036 BERGEN, Norway
+ * http://www.cmr.no
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Christian Michelsen Research AS makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef ZSTREAM__H
+#define ZSTREAM__H
+
+/*
+ * zstream.h - C++ interface to the 'zlib' general purpose compression library
+ * $Id: zstream.h,v 1.1 2005/09/23 22:39:03 beng Exp $
+ */
+
+#include <strstream.h>
+#include <string.h>
+#include <stdio.h>
+#include "zlib.h"
+
+#if defined(_WIN32)
+#   include <fcntl.h>
+#   include <io.h>
+#   define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+#   define SET_BINARY_MODE(file)
+#endif
+
+class zstringlen {
+public:
+    zstringlen(class izstream&);
+    zstringlen(class ozstream&, const char*);
+    size_t value() const { return val.word; }
+private:
+    struct Val { unsigned char byte; size_t word; } val;
+};
+
+//  ----------------------------- izstream -----------------------------
+
+class izstream
+{
+    public:
+        izstream() : m_fp(0) {}
+        izstream(FILE* fp) : m_fp(0) { open(fp); }
+        izstream(const char* name) : m_fp(0) { open(name); }
+        ~izstream() { close(); }
+
+        /* Opens a gzip (.gz) file for reading.
+         * open() can be used to read a file which is not in gzip format;
+         * in this case read() will directly read from the file without
+         * decompression. errno can be checked to distinguish two error
+         * cases (if errno is zero, the zlib error is Z_MEM_ERROR).
+         */
+        void open(const char* name) {
+            if (m_fp) close();
+            m_fp = ::gzopen(name, "rb");
+        }
+
+        void open(FILE* fp) {
+            SET_BINARY_MODE(fp);
+            if (m_fp) close();
+            m_fp = ::gzdopen(fileno(fp), "rb");
+        }
+
+        /* Flushes all pending input if necessary, closes the compressed file
+         * and deallocates all the (de)compression state. The return value is
+         * the zlib error number (see function error() below).
+         */
+        int close() {
+            int r = ::gzclose(m_fp);
+            m_fp = 0; return r;
+        }
+
+        /* Binary read the given number of bytes from the compressed file.
+         */
+        int read(void* buf, size_t len) {
+            return ::gzread(m_fp, buf, len);
+        }
+
+        /* Returns the error message for the last error which occurred on the
+         * given compressed file. errnum is set to zlib error number. If an
+         * error occurred in the file system and not in the compression library,
+         * errnum is set to Z_ERRNO and the application may consult errno
+         * to get the exact error code.
+         */
+        const char* error(int* errnum) {
+            return ::gzerror(m_fp, errnum);
+        }
+
+        gzFile fp() { return m_fp; }
+
+    private:
+        gzFile m_fp;
+};
+
+/*
+ * Binary read the given (array of) object(s) from the compressed file.
+ * If the input file was not in gzip format, read() copies the objects number
+ * of bytes into the buffer.
+ * returns the number of uncompressed bytes actually read
+ * (0 for end of file, -1 for error).
+ */
+template <class T, class Items>
+inline int read(izstream& zs, T* x, Items items) {
+    return ::gzread(zs.fp(), x, items*sizeof(T));
+}
+
+/*
+ * Binary input with the '>' operator.
+ */
+template <class T>
+inline izstream& operator>(izstream& zs, T& x) {
+    ::gzread(zs.fp(), &x, sizeof(T));
+    return zs;
+}
+
+
+inline zstringlen::zstringlen(izstream& zs) {
+    zs > val.byte;
+    if (val.byte == 255) zs > val.word;
+    else val.word = val.byte;
+}
+
+/*
+ * Read length of string + the string with the '>' operator.
+ */
+inline izstream& operator>(izstream& zs, char* x) {
+    zstringlen len(zs);
+    ::gzread(zs.fp(), x, len.value());
+    x[len.value()] = '\0';
+    return zs;
+}
+
+inline char* read_string(izstream& zs) {
+    zstringlen len(zs);
+    char* x = new char[len.value()+1];
+    ::gzread(zs.fp(), x, len.value());
+    x[len.value()] = '\0';
+    return x;
+}
+
+// ----------------------------- ozstream -----------------------------
+
+class ozstream
+{
+    public:
+        ozstream() : m_fp(0), m_os(0) {
+        }
+        ozstream(FILE* fp, int level = Z_DEFAULT_COMPRESSION)
+            : m_fp(0), m_os(0) {
+            open(fp, level);
+        }
+        ozstream(const char* name, int level = Z_DEFAULT_COMPRESSION)
+            : m_fp(0), m_os(0) {
+            open(name, level);
+        }
+        ~ozstream() {
+            close();
+        }
+
+        /* Opens a gzip (.gz) file for writing.
+         * The compression level parameter should be in 0..9
+         * errno can be checked to distinguish two error cases
+         * (if errno is zero, the zlib error is Z_MEM_ERROR).
+         */
+        void open(const char* name, int level = Z_DEFAULT_COMPRESSION) {
+            char mode[4] = "wb\0";
+            if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level;
+            if (m_fp) close();
+            m_fp = ::gzopen(name, mode);
+        }
+
+        /* open from a FILE pointer.
+         */
+        void open(FILE* fp, int level = Z_DEFAULT_COMPRESSION) {
+            SET_BINARY_MODE(fp);
+            char mode[4] = "wb\0";
+            if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level;
+            if (m_fp) close();
+            m_fp = ::gzdopen(fileno(fp), mode);
+        }
+
+        /* Flushes all pending output if necessary, closes the compressed file
+         * and deallocates all the (de)compression state. The return value is
+         * the zlib error number (see function error() below).
+         */
+        int close() {
+            if (m_os) {
+                ::gzwrite(m_fp, m_os->str(), m_os->pcount());
+                delete[] m_os->str(); delete m_os; m_os = 0;
+            }
+            int r = ::gzclose(m_fp); m_fp = 0; return r;
+        }
+
+        /* Binary write the given number of bytes into the compressed file.
+         */
+        int write(const void* buf, size_t len) {
+            return ::gzwrite(m_fp, (voidp) buf, len);
+        }
+
+        /* Flushes all pending output into the compressed file. The parameter
+         * _flush is as in the deflate() function. The return value is the zlib
+         * error number (see function gzerror below). flush() returns Z_OK if
+         * the flush_ parameter is Z_FINISH and all output could be flushed.
+         * flush() should be called only when strictly necessary because it can
+         * degrade compression.
+         */
+        int flush(int _flush) {
+            os_flush();
+            return ::gzflush(m_fp, _flush);
+        }
+
+        /* Returns the error message for the last error which occurred on the
+         * given compressed file. errnum is set to zlib error number. If an
+         * error occurred in the file system and not in the compression library,
+         * errnum is set to Z_ERRNO and the application may consult errno
+         * to get the exact error code.
+         */
+        const char* error(int* errnum) {
+            return ::gzerror(m_fp, errnum);
+        }
+
+        gzFile fp() { return m_fp; }
+
+        ostream& os() {
+            if (m_os == 0) m_os = new ostrstream;
+            return *m_os;
+        }
+
+        void os_flush() {
+            if (m_os && m_os->pcount()>0) {
+                ostrstream* oss = new ostrstream;
+                oss->fill(m_os->fill());
+                oss->flags(m_os->flags());
+                oss->precision(m_os->precision());
+                oss->width(m_os->width());
+                ::gzwrite(m_fp, m_os->str(), m_os->pcount());
+                delete[] m_os->str(); delete m_os; m_os = oss;
+            }
+        }
+
+    private:
+        gzFile m_fp;
+        ostrstream* m_os;
+};
+
+/*
+ * Binary write the given (array of) object(s) into the compressed file.
+ * returns the number of uncompressed bytes actually written
+ * (0 in case of error).
+ */
+template <class T, class Items>
+inline int write(ozstream& zs, const T* x, Items items) {
+    return ::gzwrite(zs.fp(), (voidp) x, items*sizeof(T));
+}
+
+/*
+ * Binary output with the '<' operator.
+ */
+template <class T>
+inline ozstream& operator<(ozstream& zs, const T& x) {
+    ::gzwrite(zs.fp(), (voidp) &x, sizeof(T));
+    return zs;
+}
+
+inline zstringlen::zstringlen(ozstream& zs, const char* x) {
+    val.byte = 255;  val.word = ::strlen(x);
+    if (val.word < 255) zs < (val.byte = val.word);
+    else zs < val;
+}
+
+/*
+ * Write length of string + the string with the '<' operator.
+ */
+inline ozstream& operator<(ozstream& zs, const char* x) {
+    zstringlen len(zs, x);
+    ::gzwrite(zs.fp(), (voidp) x, len.value());
+    return zs;
+}
+
+#ifdef _MSC_VER
+inline ozstream& operator<(ozstream& zs, char* const& x) {
+    return zs < (const char*) x;
+}
+#endif
+
+/*
+ * Ascii write with the << operator;
+ */
+template <class T>
+inline ostream& operator<<(ozstream& zs, const T& x) {
+    zs.os_flush();
+    return zs.os() << x;
+}
+
+#endif
Index: /trunk/minix/lib/zlib-1.2.3/contrib/iostream2/zstream_test.cpp
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/iostream2/zstream_test.cpp	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/iostream2/zstream_test.cpp	(revision 9)
@@ -0,0 +1,25 @@
+#include "zstream.h"
+#include <math.h>
+#include <stdlib.h>
+#include <iomanip.h>
+
+void main() {
+    char h[256] = "Hello";
+    char* g = "Goodbye";
+    ozstream out("temp.gz");
+    out < "This works well" < h < g;
+    out.close();
+
+    izstream in("temp.gz"); // read it back
+    char *x = read_string(in), *y = new char[256], z[256];
+    in > y > z;
+    in.close();
+    cout << x << endl << y << endl << z << endl;
+
+    out.open("temp.gz"); // try ascii output; zcat temp.gz to see the results
+    out << setw(50) << setfill('#') << setprecision(20) << x << endl << y << endl << z << endl;
+    out << z << endl << y << endl << x << endl;
+    out << 1.1234567890123456789 << endl;
+
+    delete[] x; delete[] y;
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/iostream3/README
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/iostream3/README	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/iostream3/README	(revision 9)
@@ -0,0 +1,35 @@
+These classes provide a C++ stream interface to the zlib library. It allows you
+to do things like:
+
+  gzofstream outf("blah.gz");
+  outf << "These go into the gzip file " << 123 << endl;
+
+It does this by deriving a specialized stream buffer for gzipped files, which is
+the way Stroustrup would have done it. :->
+
+The gzifstream and gzofstream classes were originally written by Kevin Ruland
+and made available in the zlib contrib/iostream directory. The older version still
+compiles under gcc 2.xx, but not under gcc 3.xx, which sparked the development of
+this version.
+
+The new classes are as standard-compliant as possible, closely following the
+approach of the standard library's fstream classes. It compiles under gcc versions
+3.2 and 3.3, but not under gcc 2.xx. This is mainly due to changes in the standard
+library naming scheme. The new version of gzifstream/gzofstream/gzfilebuf differs
+from the previous one in the following respects:
+- added showmanyc
+- added setbuf, with support for unbuffered output via setbuf(0,0)
+- a few bug fixes of stream behavior
+- gzipped output file opened with default compression level instead of maximum level
+- setcompressionlevel()/strategy() members replaced by single setcompression()
+
+The code is provided "as is", with the permission to use, copy, modify, distribute
+and sell it for any purpose without fee.
+
+Ludwig Schwardt
+<schwardt@sun.ac.za>
+
+DSP Lab
+Electrical & Electronic Engineering Department
+University of Stellenbosch
+South Africa
Index: /trunk/minix/lib/zlib-1.2.3/contrib/iostream3/TODO
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/iostream3/TODO	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/iostream3/TODO	(revision 9)
@@ -0,0 +1,17 @@
+Possible upgrades to gzfilebuf:
+
+- The ability to do putback (e.g. putbackfail)
+
+- The ability to seek (zlib supports this, but could be slow/tricky)
+
+- Simultaneous read/write access (does it make sense?)
+
+- Support for ios_base::ate open mode
+
+- Locale support?
+
+- Check public interface to see which calls give problems
+  (due to dependence on library internals)
+
+- Override operator<<(ostream&, gzfilebuf*) to allow direct copying
+  of stream buffer to stream ( i.e. os << is.rdbuf(); )
Index: /trunk/minix/lib/zlib-1.2.3/contrib/iostream3/test.cc
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/iostream3/test.cc	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/iostream3/test.cc	(revision 9)
@@ -0,0 +1,50 @@
+/*
+ * Test program for gzifstream and gzofstream
+ *
+ * by Ludwig Schwardt <schwardt@sun.ac.za>
+ * original version by Kevin Ruland <kevin@rodin.wustl.edu>
+ */
+
+#include "zfstream.h"
+#include <iostream>      // for cout
+
+int main() {
+
+  gzofstream outf;
+  gzifstream inf;
+  char buf[80];
+
+  outf.open("test1.txt.gz");
+  outf << "The quick brown fox sidestepped the lazy canine\n"
+       << 1.3 << "\nPlan " << 9 << std::endl;
+  outf.close();
+  std::cout << "Wrote the following message to 'test1.txt.gz' (check with zcat or zless):\n"
+            << "The quick brown fox sidestepped the lazy canine\n"
+            << 1.3 << "\nPlan " << 9 << std::endl;
+
+  std::cout << "\nReading 'test1.txt.gz' (buffered) produces:\n";
+  inf.open("test1.txt.gz");
+  while (inf.getline(buf,80,'\n')) {
+    std::cout << buf << "\t(" << inf.rdbuf()->in_avail() << " chars left in buffer)\n";
+  }
+  inf.close();
+
+  outf.rdbuf()->pubsetbuf(0,0);
+  outf.open("test2.txt.gz");
+  outf << setcompression(Z_NO_COMPRESSION)
+       << "The quick brown fox sidestepped the lazy canine\n"
+       << 1.3 << "\nPlan " << 9 << std::endl;
+  outf.close();
+  std::cout << "\nWrote the same message to 'test2.txt.gz' in uncompressed form";
+
+  std::cout << "\nReading 'test2.txt.gz' (unbuffered) produces:\n";
+  inf.rdbuf()->pubsetbuf(0,0);
+  inf.open("test2.txt.gz");
+  while (inf.getline(buf,80,'\n')) {
+    std::cout << buf << "\t(" << inf.rdbuf()->in_avail() << " chars left in buffer)\n";
+  }
+  inf.close();
+
+  return 0;
+
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/iostream3/zfstream.cc
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/iostream3/zfstream.cc	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/iostream3/zfstream.cc	(revision 9)
@@ -0,0 +1,479 @@
+/*
+ * A C++ I/O streams interface to the zlib gz* functions
+ *
+ * by Ludwig Schwardt <schwardt@sun.ac.za>
+ * original version by Kevin Ruland <kevin@rodin.wustl.edu>
+ *
+ * This version is standard-compliant and compatible with gcc 3.x.
+ */
+
+#include "zfstream.h"
+#include <cstring>          // for strcpy, strcat, strlen (mode strings)
+#include <cstdio>           // for BUFSIZ
+
+// Internal buffer sizes (default and "unbuffered" versions)
+#define BIGBUFSIZE BUFSIZ
+#define SMALLBUFSIZE 1
+
+/*****************************************************************************/
+
+// Default constructor
+gzfilebuf::gzfilebuf()
+: file(NULL), io_mode(std::ios_base::openmode(0)), own_fd(false),
+  buffer(NULL), buffer_size(BIGBUFSIZE), own_buffer(true)
+{
+  // No buffers to start with
+  this->disable_buffer();
+}
+
+// Destructor
+gzfilebuf::~gzfilebuf()
+{
+  // Sync output buffer and close only if responsible for file
+  // (i.e. attached streams should be left open at this stage)
+  this->sync();
+  if (own_fd)
+    this->close();
+  // Make sure internal buffer is deallocated
+  this->disable_buffer();
+}
+
+// Set compression level and strategy
+int
+gzfilebuf::setcompression(int comp_level,
+                          int comp_strategy)
+{
+  return gzsetparams(file, comp_level, comp_strategy);
+}
+
+// Open gzipped file
+gzfilebuf*
+gzfilebuf::open(const char *name,
+                std::ios_base::openmode mode)
+{
+  // Fail if file already open
+  if (this->is_open())
+    return NULL;
+  // Don't support simultaneous read/write access (yet)
+  if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
+    return NULL;
+
+  // Build mode string for gzopen and check it [27.8.1.3.2]
+  char char_mode[6] = "\0\0\0\0\0";
+  if (!this->open_mode(mode, char_mode))
+    return NULL;
+
+  // Attempt to open file
+  if ((file = gzopen(name, char_mode)) == NULL)
+    return NULL;
+
+  // On success, allocate internal buffer and set flags
+  this->enable_buffer();
+  io_mode = mode;
+  own_fd = true;
+  return this;
+}
+
+// Attach to gzipped file
+gzfilebuf*
+gzfilebuf::attach(int fd,
+                  std::ios_base::openmode mode)
+{
+  // Fail if file already open
+  if (this->is_open())
+    return NULL;
+  // Don't support simultaneous read/write access (yet)
+  if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
+    return NULL;
+
+  // Build mode string for gzdopen and check it [27.8.1.3.2]
+  char char_mode[6] = "\0\0\0\0\0";
+  if (!this->open_mode(mode, char_mode))
+    return NULL;
+
+  // Attempt to attach to file
+  if ((file = gzdopen(fd, char_mode)) == NULL)
+    return NULL;
+
+  // On success, allocate internal buffer and set flags
+  this->enable_buffer();
+  io_mode = mode;
+  own_fd = false;
+  return this;
+}
+
+// Close gzipped file
+gzfilebuf*
+gzfilebuf::close()
+{
+  // Fail immediately if no file is open
+  if (!this->is_open())
+    return NULL;
+  // Assume success
+  gzfilebuf* retval = this;
+  // Attempt to sync and close gzipped file
+  if (this->sync() == -1)
+    retval = NULL;
+  if (gzclose(file) < 0)
+    retval = NULL;
+  // File is now gone anyway (postcondition [27.8.1.3.8])
+  file = NULL;
+  own_fd = false;
+  // Destroy internal buffer if it exists
+  this->disable_buffer();
+  return retval;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+// Convert int open mode to mode string
+bool
+gzfilebuf::open_mode(std::ios_base::openmode mode,
+                     char* c_mode) const
+{
+  bool testb = mode & std::ios_base::binary;
+  bool testi = mode & std::ios_base::in;
+  bool testo = mode & std::ios_base::out;
+  bool testt = mode & std::ios_base::trunc;
+  bool testa = mode & std::ios_base::app;
+
+  // Check for valid flag combinations - see [27.8.1.3.2] (Table 92)
+  // Original zfstream hardcoded the compression level to maximum here...
+  // Double the time for less than 1% size improvement seems
+  // excessive though - keeping it at the default level
+  // To change back, just append "9" to the next three mode strings
+  if (!testi && testo && !testt && !testa)
+    strcpy(c_mode, "w");
+  if (!testi && testo && !testt && testa)
+    strcpy(c_mode, "a");
+  if (!testi && testo && testt && !testa)
+    strcpy(c_mode, "w");
+  if (testi && !testo && !testt && !testa)
+    strcpy(c_mode, "r");
+  // No read/write mode yet
+//  if (testi && testo && !testt && !testa)
+//    strcpy(c_mode, "r+");
+//  if (testi && testo && testt && !testa)
+//    strcpy(c_mode, "w+");
+
+  // Mode string should be empty for invalid combination of flags
+  if (strlen(c_mode) == 0)
+    return false;
+  if (testb)
+    strcat(c_mode, "b");
+  return true;
+}
+
+// Determine number of characters in internal get buffer
+std::streamsize
+gzfilebuf::showmanyc()
+{
+  // Calls to underflow will fail if file not opened for reading
+  if (!this->is_open() || !(io_mode & std::ios_base::in))
+    return -1;
+  // Make sure get area is in use
+  if (this->gptr() && (this->gptr() < this->egptr()))
+    return std::streamsize(this->egptr() - this->gptr());
+  else
+    return 0;
+}
+
+// Fill get area from gzipped file
+gzfilebuf::int_type
+gzfilebuf::underflow()
+{
+  // If something is left in the get area by chance, return it
+  // (this shouldn't normally happen, as underflow is only supposed
+  // to be called when gptr >= egptr, but it serves as error check)
+  if (this->gptr() && (this->gptr() < this->egptr()))
+    return traits_type::to_int_type(*(this->gptr()));
+
+  // If the file hasn't been opened for reading, produce error
+  if (!this->is_open() || !(io_mode & std::ios_base::in))
+    return traits_type::eof();
+
+  // Attempt to fill internal buffer from gzipped file
+  // (buffer must be guaranteed to exist...)
+  int bytes_read = gzread(file, buffer, buffer_size);
+  // Indicates error or EOF
+  if (bytes_read <= 0)
+  {
+    // Reset get area
+    this->setg(buffer, buffer, buffer);
+    return traits_type::eof();
+  }
+  // Make all bytes read from file available as get area
+  this->setg(buffer, buffer, buffer + bytes_read);
+
+  // Return next character in get area
+  return traits_type::to_int_type(*(this->gptr()));
+}
+
+// Write put area to gzipped file
+gzfilebuf::int_type
+gzfilebuf::overflow(int_type c)
+{
+  // Determine whether put area is in use
+  if (this->pbase())
+  {
+    // Double-check pointer range
+    if (this->pptr() > this->epptr() || this->pptr() < this->pbase())
+      return traits_type::eof();
+    // Add extra character to buffer if not EOF
+    if (!traits_type::eq_int_type(c, traits_type::eof()))
+    {
+      *(this->pptr()) = traits_type::to_char_type(c);
+      this->pbump(1);
+    }
+    // Number of characters to write to file
+    int bytes_to_write = this->pptr() - this->pbase();
+    // Overflow doesn't fail if nothing is to be written
+    if (bytes_to_write > 0)
+    {
+      // If the file hasn't been opened for writing, produce error
+      if (!this->is_open() || !(io_mode & std::ios_base::out))
+        return traits_type::eof();
+      // If gzipped file won't accept all bytes written to it, fail
+      if (gzwrite(file, this->pbase(), bytes_to_write) != bytes_to_write)
+        return traits_type::eof();
+      // Reset next pointer to point to pbase on success
+      this->pbump(-bytes_to_write);
+    }
+  }
+  // Write extra character to file if not EOF
+  else if (!traits_type::eq_int_type(c, traits_type::eof()))
+  {
+    // If the file hasn't been opened for writing, produce error
+    if (!this->is_open() || !(io_mode & std::ios_base::out))
+      return traits_type::eof();
+    // Impromptu char buffer (allows "unbuffered" output)
+    char_type last_char = traits_type::to_char_type(c);
+    // If gzipped file won't accept this character, fail
+    if (gzwrite(file, &last_char, 1) != 1)
+      return traits_type::eof();
+  }
+
+  // If you got here, you have succeeded (even if c was EOF)
+  // The return value should therefore be non-EOF
+  if (traits_type::eq_int_type(c, traits_type::eof()))
+    return traits_type::not_eof(c);
+  else
+    return c;
+}
+
+// Assign new buffer
+std::streambuf*
+gzfilebuf::setbuf(char_type* p,
+                  std::streamsize n)
+{
+  // First make sure stuff is sync'ed, for safety
+  if (this->sync() == -1)
+    return NULL;
+  // If buffering is turned off on purpose via setbuf(0,0), still allocate one...
+  // "Unbuffered" only really refers to put [27.8.1.4.10], while get needs at
+  // least a buffer of size 1 (very inefficient though, therefore make it bigger?)
+  // This follows from [27.5.2.4.3]/12 (gptr needs to point at something, it seems)
+  if (!p || !n)
+  {
+    // Replace existing buffer (if any) with small internal buffer
+    this->disable_buffer();
+    buffer = NULL;
+    buffer_size = 0;
+    own_buffer = true;
+    this->enable_buffer();
+  }
+  else
+  {
+    // Replace existing buffer (if any) with external buffer
+    this->disable_buffer();
+    buffer = p;
+    buffer_size = n;
+    own_buffer = false;
+    this->enable_buffer();
+  }
+  return this;
+}
+
+// Write put area to gzipped file (i.e. ensures that put area is empty)
+int
+gzfilebuf::sync()
+{
+  return traits_type::eq_int_type(this->overflow(), traits_type::eof()) ? -1 : 0;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+// Allocate internal buffer
+void
+gzfilebuf::enable_buffer()
+{
+  // If internal buffer required, allocate one
+  if (own_buffer && !buffer)
+  {
+    // Check for buffered vs. "unbuffered"
+    if (buffer_size > 0)
+    {
+      // Allocate internal buffer
+      buffer = new char_type[buffer_size];
+      // Get area starts empty and will be expanded by underflow as need arises
+      this->setg(buffer, buffer, buffer);
+      // Setup entire internal buffer as put area.
+      // The one-past-end pointer actually points to the last element of the buffer,
+      // so that overflow(c) can safely add the extra character c to the sequence.
+      // These pointers remain in place for the duration of the buffer
+      this->setp(buffer, buffer + buffer_size - 1);
+    }
+    else
+    {
+      // Even in "unbuffered" case, (small?) get buffer is still required
+      buffer_size = SMALLBUFSIZE;
+      buffer = new char_type[buffer_size];
+      this->setg(buffer, buffer, buffer);
+      // "Unbuffered" means no put buffer
+      this->setp(0, 0);
+    }
+  }
+  else
+  {
+    // If buffer already allocated, reset buffer pointers just to make sure no
+    // stale chars are lying around
+    this->setg(buffer, buffer, buffer);
+    this->setp(buffer, buffer + buffer_size - 1);
+  }
+}
+
+// Destroy internal buffer
+void
+gzfilebuf::disable_buffer()
+{
+  // If internal buffer exists, deallocate it
+  if (own_buffer && buffer)
+  {
+    // Preserve unbuffered status by zeroing size
+    if (!this->pbase())
+      buffer_size = 0;
+    delete[] buffer;
+    buffer = NULL;
+    this->setg(0, 0, 0);
+    this->setp(0, 0);
+  }
+  else
+  {
+    // Reset buffer pointers to initial state if external buffer exists
+    this->setg(buffer, buffer, buffer);
+    if (buffer)
+      this->setp(buffer, buffer + buffer_size - 1);
+    else
+      this->setp(0, 0);
+  }
+}
+
+/*****************************************************************************/
+
+// Default constructor initializes stream buffer
+gzifstream::gzifstream()
+: std::istream(NULL), sb()
+{ this->init(&sb); }
+
+// Initialize stream buffer and open file
+gzifstream::gzifstream(const char* name,
+                       std::ios_base::openmode mode)
+: std::istream(NULL), sb()
+{
+  this->init(&sb);
+  this->open(name, mode);
+}
+
+// Initialize stream buffer and attach to file
+gzifstream::gzifstream(int fd,
+                       std::ios_base::openmode mode)
+: std::istream(NULL), sb()
+{
+  this->init(&sb);
+  this->attach(fd, mode);
+}
+
+// Open file and go into fail() state if unsuccessful
+void
+gzifstream::open(const char* name,
+                 std::ios_base::openmode mode)
+{
+  if (!sb.open(name, mode | std::ios_base::in))
+    this->setstate(std::ios_base::failbit);
+  else
+    this->clear();
+}
+
+// Attach to file and go into fail() state if unsuccessful
+void
+gzifstream::attach(int fd,
+                   std::ios_base::openmode mode)
+{
+  if (!sb.attach(fd, mode | std::ios_base::in))
+    this->setstate(std::ios_base::failbit);
+  else
+    this->clear();
+}
+
+// Close file
+void
+gzifstream::close()
+{
+  if (!sb.close())
+    this->setstate(std::ios_base::failbit);
+}
+
+/*****************************************************************************/
+
+// Default constructor initializes stream buffer
+gzofstream::gzofstream()
+: std::ostream(NULL), sb()
+{ this->init(&sb); }
+
+// Initialize stream buffer and open file
+gzofstream::gzofstream(const char* name,
+                       std::ios_base::openmode mode)
+: std::ostream(NULL), sb()
+{
+  this->init(&sb);
+  this->open(name, mode);
+}
+
+// Initialize stream buffer and attach to file
+gzofstream::gzofstream(int fd,
+                       std::ios_base::openmode mode)
+: std::ostream(NULL), sb()
+{
+  this->init(&sb);
+  this->attach(fd, mode);
+}
+
+// Open file and go into fail() state if unsuccessful
+void
+gzofstream::open(const char* name,
+                 std::ios_base::openmode mode)
+{
+  if (!sb.open(name, mode | std::ios_base::out))
+    this->setstate(std::ios_base::failbit);
+  else
+    this->clear();
+}
+
+// Attach to file and go into fail() state if unsuccessful
+void
+gzofstream::attach(int fd,
+                   std::ios_base::openmode mode)
+{
+  if (!sb.attach(fd, mode | std::ios_base::out))
+    this->setstate(std::ios_base::failbit);
+  else
+    this->clear();
+}
+
+// Close file
+void
+gzofstream::close()
+{
+  if (!sb.close())
+    this->setstate(std::ios_base::failbit);
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/iostream3/zfstream.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/iostream3/zfstream.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/iostream3/zfstream.h	(revision 9)
@@ -0,0 +1,466 @@
+/*
+ * A C++ I/O streams interface to the zlib gz* functions
+ *
+ * by Ludwig Schwardt <schwardt@sun.ac.za>
+ * original version by Kevin Ruland <kevin@rodin.wustl.edu>
+ *
+ * This version is standard-compliant and compatible with gcc 3.x.
+ */
+
+#ifndef ZFSTREAM_H
+#define ZFSTREAM_H
+
+#include <istream>  // not iostream, since we don't need cin/cout
+#include <ostream>
+#include "zlib.h"
+
+/*****************************************************************************/
+
+/**
+ *  @brief  Gzipped file stream buffer class.
+ *
+ *  This class implements basic_filebuf for gzipped files. It doesn't yet support
+ *  seeking (allowed by zlib but slow/limited), putback and read/write access
+ *  (tricky). Otherwise, it attempts to be a drop-in replacement for the standard
+ *  file streambuf.
+*/
+class gzfilebuf : public std::streambuf
+{
+public:
+  //  Default constructor.
+  gzfilebuf();
+
+  //  Destructor.
+  virtual
+  ~gzfilebuf();
+
+  /**
+   *  @brief  Set compression level and strategy on the fly.
+   *  @param  comp_level  Compression level (see zlib.h for allowed values)
+   *  @param  comp_strategy  Compression strategy (see zlib.h for allowed values)
+   *  @return  Z_OK on success, Z_STREAM_ERROR otherwise.
+   *
+   *  Unfortunately, these parameters cannot be modified separately, as the
+   *  previous zfstream version assumed. Since the strategy is seldom changed,
+   *  it can default and setcompression(level) then becomes like the old
+   *  setcompressionlevel(level).
+  */
+  int
+  setcompression(int comp_level,
+                 int comp_strategy = Z_DEFAULT_STRATEGY);
+
+  /**
+   *  @brief  Check if file is open.
+   *  @return  True if file is open.
+  */
+  bool
+  is_open() const { return (file != NULL); }
+
+  /**
+   *  @brief  Open gzipped file.
+   *  @param  name  File name.
+   *  @param  mode  Open mode flags.
+   *  @return  @c this on success, NULL on failure.
+  */
+  gzfilebuf*
+  open(const char* name,
+       std::ios_base::openmode mode);
+
+  /**
+   *  @brief  Attach to already open gzipped file.
+   *  @param  fd  File descriptor.
+   *  @param  mode  Open mode flags.
+   *  @return  @c this on success, NULL on failure.
+  */
+  gzfilebuf*
+  attach(int fd,
+         std::ios_base::openmode mode);
+
+  /**
+   *  @brief  Close gzipped file.
+   *  @return  @c this on success, NULL on failure.
+  */
+  gzfilebuf*
+  close();
+
+protected:
+  /**
+   *  @brief  Convert ios open mode int to mode string used by zlib.
+   *  @return  True if valid mode flag combination.
+  */
+  bool
+  open_mode(std::ios_base::openmode mode,
+            char* c_mode) const;
+
+  /**
+   *  @brief  Number of characters available in stream buffer.
+   *  @return  Number of characters.
+   *
+   *  This indicates number of characters in get area of stream buffer.
+   *  These characters can be read without accessing the gzipped file.
+  */
+  virtual std::streamsize
+  showmanyc();
+
+  /**
+   *  @brief  Fill get area from gzipped file.
+   *  @return  First character in get area on success, EOF on error.
+   *
+   *  This actually reads characters from gzipped file to stream
+   *  buffer. Always buffered.
+  */
+  virtual int_type
+  underflow();
+
+  /**
+   *  @brief  Write put area to gzipped file.
+   *  @param  c  Extra character to add to buffer contents.
+   *  @return  Non-EOF on success, EOF on error.
+   *
+   *  This actually writes characters in stream buffer to
+   *  gzipped file. With unbuffered output this is done one
+   *  character at a time.
+  */
+  virtual int_type
+  overflow(int_type c = traits_type::eof());
+
+  /**
+   *  @brief  Installs external stream buffer.
+   *  @param  p  Pointer to char buffer.
+   *  @param  n  Size of external buffer.
+   *  @return  @c this on success, NULL on failure.
+   *
+   *  Call setbuf(0,0) to enable unbuffered output.
+  */
+  virtual std::streambuf*
+  setbuf(char_type* p,
+         std::streamsize n);
+
+  /**
+   *  @brief  Flush stream buffer to file.
+   *  @return  0 on success, -1 on error.
+   *
+   *  This calls underflow(EOF) to do the job.
+  */
+  virtual int
+  sync();
+
+//
+// Some future enhancements
+//
+//  virtual int_type uflow();
+//  virtual int_type pbackfail(int_type c = traits_type::eof());
+//  virtual pos_type
+//  seekoff(off_type off,
+//          std::ios_base::seekdir way,
+//          std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out);
+//  virtual pos_type
+//  seekpos(pos_type sp,
+//          std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out);
+
+private:
+  /**
+   *  @brief  Allocate internal buffer.
+   *
+   *  This function is safe to call multiple times. It will ensure
+   *  that a proper internal buffer exists if it is required. If the
+   *  buffer already exists or is external, the buffer pointers will be
+   *  reset to their original state.
+  */
+  void
+  enable_buffer();
+
+  /**
+   *  @brief  Destroy internal buffer.
+   *
+   *  This function is safe to call multiple times. It will ensure
+   *  that the internal buffer is deallocated if it exists. In any
+   *  case, it will also reset the buffer pointers.
+  */
+  void
+  disable_buffer();
+
+  /**
+   *  Underlying file pointer.
+  */
+  gzFile file;
+
+  /**
+   *  Mode in which file was opened.
+  */
+  std::ios_base::openmode io_mode;
+
+  /**
+   *  @brief  True if this object owns file descriptor.
+   *
+   *  This makes the class responsible for closing the file
+   *  upon destruction.
+  */
+  bool own_fd;
+
+  /**
+   *  @brief  Stream buffer.
+   *
+   *  For simplicity this remains allocated on the free store for the
+   *  entire life span of the gzfilebuf object, unless replaced by setbuf.
+  */
+  char_type* buffer;
+
+  /**
+   *  @brief  Stream buffer size.
+   *
+   *  Defaults to system default buffer size (typically 8192 bytes).
+   *  Modified by setbuf.
+  */
+  std::streamsize buffer_size;
+
+  /**
+   *  @brief  True if this object owns stream buffer.
+   *
+   *  This makes the class responsible for deleting the buffer
+   *  upon destruction.
+  */
+  bool own_buffer;
+};
+
+/*****************************************************************************/
+
+/**
+ *  @brief  Gzipped file input stream class.
+ *
+ *  This class implements ifstream for gzipped files. Seeking and putback
+ *  is not supported yet.
+*/
+class gzifstream : public std::istream
+{
+public:
+  //  Default constructor
+  gzifstream();
+
+  /**
+   *  @brief  Construct stream on gzipped file to be opened.
+   *  @param  name  File name.
+   *  @param  mode  Open mode flags (forced to contain ios::in).
+  */
+  explicit
+  gzifstream(const char* name,
+             std::ios_base::openmode mode = std::ios_base::in);
+
+  /**
+   *  @brief  Construct stream on already open gzipped file.
+   *  @param  fd    File descriptor.
+   *  @param  mode  Open mode flags (forced to contain ios::in).
+  */
+  explicit
+  gzifstream(int fd,
+             std::ios_base::openmode mode = std::ios_base::in);
+
+  /**
+   *  Obtain underlying stream buffer.
+  */
+  gzfilebuf*
+  rdbuf() const
+  { return const_cast<gzfilebuf*>(&sb); }
+
+  /**
+   *  @brief  Check if file is open.
+   *  @return  True if file is open.
+  */
+  bool
+  is_open() { return sb.is_open(); }
+
+  /**
+   *  @brief  Open gzipped file.
+   *  @param  name  File name.
+   *  @param  mode  Open mode flags (forced to contain ios::in).
+   *
+   *  Stream will be in state good() if file opens successfully;
+   *  otherwise in state fail(). This differs from the behavior of
+   *  ifstream, which never sets the state to good() and therefore
+   *  won't allow you to reuse the stream for a second file unless
+   *  you manually clear() the state. The choice is a matter of
+   *  convenience.
+  */
+  void
+  open(const char* name,
+       std::ios_base::openmode mode = std::ios_base::in);
+
+  /**
+   *  @brief  Attach to already open gzipped file.
+   *  @param  fd  File descriptor.
+   *  @param  mode  Open mode flags (forced to contain ios::in).
+   *
+   *  Stream will be in state good() if attach succeeded; otherwise
+   *  in state fail().
+  */
+  void
+  attach(int fd,
+         std::ios_base::openmode mode = std::ios_base::in);
+
+  /**
+   *  @brief  Close gzipped file.
+   *
+   *  Stream will be in state fail() if close failed.
+  */
+  void
+  close();
+
+private:
+  /**
+   *  Underlying stream buffer.
+  */
+  gzfilebuf sb;
+};
+
+/*****************************************************************************/
+
+/**
+ *  @brief  Gzipped file output stream class.
+ *
+ *  This class implements ofstream for gzipped files. Seeking and putback
+ *  is not supported yet.
+*/
+class gzofstream : public std::ostream
+{
+public:
+  //  Default constructor
+  gzofstream();
+
+  /**
+   *  @brief  Construct stream on gzipped file to be opened.
+   *  @param  name  File name.
+   *  @param  mode  Open mode flags (forced to contain ios::out).
+  */
+  explicit
+  gzofstream(const char* name,
+             std::ios_base::openmode mode = std::ios_base::out);
+
+  /**
+   *  @brief  Construct stream on already open gzipped file.
+   *  @param  fd    File descriptor.
+   *  @param  mode  Open mode flags (forced to contain ios::out).
+  */
+  explicit
+  gzofstream(int fd,
+             std::ios_base::openmode mode = std::ios_base::out);
+
+  /**
+   *  Obtain underlying stream buffer.
+  */
+  gzfilebuf*
+  rdbuf() const
+  { return const_cast<gzfilebuf*>(&sb); }
+
+  /**
+   *  @brief  Check if file is open.
+   *  @return  True if file is open.
+  */
+  bool
+  is_open() { return sb.is_open(); }
+
+  /**
+   *  @brief  Open gzipped file.
+   *  @param  name  File name.
+   *  @param  mode  Open mode flags (forced to contain ios::out).
+   *
+   *  Stream will be in state good() if file opens successfully;
+   *  otherwise in state fail(). This differs from the behavior of
+   *  ofstream, which never sets the state to good() and therefore
+   *  won't allow you to reuse the stream for a second file unless
+   *  you manually clear() the state. The choice is a matter of
+   *  convenience.
+  */
+  void
+  open(const char* name,
+       std::ios_base::openmode mode = std::ios_base::out);
+
+  /**
+   *  @brief  Attach to already open gzipped file.
+   *  @param  fd  File descriptor.
+   *  @param  mode  Open mode flags (forced to contain ios::out).
+   *
+   *  Stream will be in state good() if attach succeeded; otherwise
+   *  in state fail().
+  */
+  void
+  attach(int fd,
+         std::ios_base::openmode mode = std::ios_base::out);
+
+  /**
+   *  @brief  Close gzipped file.
+   *
+   *  Stream will be in state fail() if close failed.
+  */
+  void
+  close();
+
+private:
+  /**
+   *  Underlying stream buffer.
+  */
+  gzfilebuf sb;
+};
+
+/*****************************************************************************/
+
+/**
+ *  @brief  Gzipped file output stream manipulator class.
+ *
+ *  This class defines a two-argument manipulator for gzofstream. It is used
+ *  as base for the setcompression(int,int) manipulator.
+*/
+template<typename T1, typename T2>
+  class gzomanip2
+  {
+  public:
+    // Allows insertor to peek at internals
+    template <typename Ta, typename Tb>
+      friend gzofstream&
+      operator<<(gzofstream&,
+                 const gzomanip2<Ta,Tb>&);
+
+    // Constructor
+    gzomanip2(gzofstream& (*f)(gzofstream&, T1, T2),
+              T1 v1,
+              T2 v2);
+  private:
+    // Underlying manipulator function
+    gzofstream&
+    (*func)(gzofstream&, T1, T2);
+
+    // Arguments for manipulator function
+    T1 val1;
+    T2 val2;
+  };
+
+/*****************************************************************************/
+
+// Manipulator function thunks through to stream buffer
+inline gzofstream&
+setcompression(gzofstream &gzs, int l, int s = Z_DEFAULT_STRATEGY)
+{
+  (gzs.rdbuf())->setcompression(l, s);
+  return gzs;
+}
+
+// Manipulator constructor stores arguments
+template<typename T1, typename T2>
+  inline
+  gzomanip2<T1,T2>::gzomanip2(gzofstream &(*f)(gzofstream &, T1, T2),
+                              T1 v1,
+                              T2 v2)
+  : func(f), val1(v1), val2(v2)
+  { }
+
+// Insertor applies underlying manipulator function to stream
+template<typename T1, typename T2>
+  inline gzofstream&
+  operator<<(gzofstream& s, const gzomanip2<T1,T2>& m)
+  { return (*m.func)(s, m.val1, m.val2); }
+
+// Insert this onto stream to simplify setting of compression level
+inline gzomanip2<int,int>
+setcompression(int l, int s = Z_DEFAULT_STRATEGY)
+{ return gzomanip2<int,int>(&setcompression, l, s); }
+
+#endif // ZFSTREAM_H
Index: /trunk/minix/lib/zlib-1.2.3/contrib/masm686/match.asm
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/masm686/match.asm	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/masm686/match.asm	(revision 9)
@@ -0,0 +1,413 @@
+
+; match.asm -- Pentium-Pro optimized version of longest_match()
+;
+; Updated for zlib 1.1.3 and converted to MASM 6.1x
+; Copyright (C) 2000 Dan Higdon <hdan@kinesoft.com>
+;                    and Chuck Walbourn <chuckw@kinesoft.com>
+; Corrections by Cosmin Truta <cosmint@cs.ubbcluj.ro>
+;
+; This is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License.
+
+; Based on match.S
+; Written for zlib 1.1.2
+; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
+;
+; Modified by Gilles Vollant (2005) for add gzhead and gzindex
+
+	.686P
+	.MODEL	FLAT
+
+;===========================================================================
+; EQUATES
+;===========================================================================
+
+MAX_MATCH	EQU 258
+MIN_MATCH	EQU 3
+MIN_LOOKAHEAD	EQU (MAX_MATCH + MIN_MATCH + 1)
+MAX_MATCH_8	EQU ((MAX_MATCH + 7) AND (NOT 7))
+
+;===========================================================================
+; STRUCTURES
+;===========================================================================
+
+; This STRUCT assumes a 4-byte alignment
+
+DEFLATE_STATE	STRUCT
+ds_strm			dd ?
+ds_status		dd ?
+ds_pending_buf		dd ?
+ds_pending_buf_size	dd ?
+ds_pending_out		dd ?
+ds_pending		dd ?
+ds_wrap			dd ?
+; gzhead and gzindex are added in zlib 1.2.2.2 (see deflate.h)
+ds_gzhead               dd ?
+ds_gzindex              dd ?
+ds_data_type		db ?
+ds_method		db ?
+			db ?	; padding
+			db ?	; padding
+ds_last_flush		dd ?
+ds_w_size		dd ?	; used
+ds_w_bits		dd ?
+ds_w_mask		dd ?	; used
+ds_window		dd ?	; used
+ds_window_size		dd ?
+ds_prev			dd ?	; used
+ds_head			dd ?
+ds_ins_h		dd ?
+ds_hash_size		dd ?
+ds_hash_bits		dd ?
+ds_hash_mask		dd ?
+ds_hash_shift		dd ?
+ds_block_start		dd ?
+ds_match_length		dd ?	; used
+ds_prev_match		dd ?	; used
+ds_match_available	dd ?
+ds_strstart		dd ?	; used
+ds_match_start		dd ?	; used
+ds_lookahead		dd ?	; used
+ds_prev_length		dd ?	; used
+ds_max_chain_length	dd ?	; used
+ds_max_laxy_match	dd ?
+ds_level		dd ?
+ds_strategy		dd ?
+ds_good_match		dd ?	; used
+ds_nice_match		dd ?	; used
+
+; Don't need anymore of the struct for match
+DEFLATE_STATE	ENDS
+
+;===========================================================================
+; CODE
+;===========================================================================
+_TEXT	SEGMENT
+
+;---------------------------------------------------------------------------
+; match_init
+;---------------------------------------------------------------------------
+	ALIGN	4
+PUBLIC	_match_init
+_match_init	PROC
+	; no initialization needed
+	ret
+_match_init	ENDP
+
+;---------------------------------------------------------------------------
+; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
+;---------------------------------------------------------------------------
+	ALIGN	4
+
+PUBLIC	_longest_match
+_longest_match	PROC
+
+; Since this code uses EBP for a scratch register, the stack frame must
+; be manually constructed and referenced relative to the ESP register.
+
+; Stack image
+; Variables
+chainlenwmask	=  0	; high word: current chain len
+			; low word: s->wmask
+window		=  4	; local copy of s->window
+windowbestlen	=  8	; s->window + bestlen
+scanend		= 12	; last two bytes of string
+scanstart	= 16	; first two bytes of string
+scanalign	= 20	; dword-misalignment of string
+nicematch	= 24	; a good enough match size
+bestlen		= 28	; size of best match so far
+scan		= 32	; ptr to string wanting match
+varsize		= 36	; number of bytes (also offset to last saved register)
+
+; Saved Registers (actually pushed into place)
+ebx_save	= 36
+edi_save	= 40
+esi_save	= 44
+ebp_save	= 48
+
+; Parameters
+retaddr		= 52
+deflatestate	= 56
+curmatch	= 60
+
+; Save registers that the compiler may be using
+	push	ebp
+	push	edi
+	push	esi
+	push	ebx
+
+; Allocate local variable space
+	sub	esp,varsize
+
+; Retrieve the function arguments. ecx will hold cur_match
+; throughout the entire function. edx will hold the pointer to the
+; deflate_state structure during the function's setup (before
+; entering the main loop).
+
+	mov	edx, [esp+deflatestate]
+ASSUME	edx:PTR DEFLATE_STATE
+
+	mov	ecx, [esp+curmatch]
+
+; uInt wmask = s->w_mask;
+; unsigned chain_length = s->max_chain_length;
+; if (s->prev_length >= s->good_match) {
+;     chain_length >>= 2;
+; }
+
+	mov	eax, [edx].ds_prev_length
+	mov	ebx, [edx].ds_good_match
+	cmp	eax, ebx
+	mov	eax, [edx].ds_w_mask
+	mov	ebx, [edx].ds_max_chain_length
+	jl	SHORT LastMatchGood
+	shr	ebx, 2
+LastMatchGood:
+
+; chainlen is decremented once beforehand so that the function can
+; use the sign flag instead of the zero flag for the exit test.
+; It is then shifted into the high word, to make room for the wmask
+; value, which it will always accompany.
+
+	dec	ebx
+	shl	ebx, 16
+	or	ebx, eax
+	mov	[esp+chainlenwmask], ebx
+
+; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+	mov	eax, [edx].ds_nice_match
+	mov	ebx, [edx].ds_lookahead
+	cmp	ebx, eax
+	jl	SHORT LookaheadLess
+	mov	ebx, eax
+LookaheadLess:
+	mov	[esp+nicematch], ebx
+
+;/* register Bytef *scan = s->window + s->strstart;                     */
+
+	mov	esi, [edx].ds_window
+	mov	[esp+window], esi
+	mov	ebp, [edx].ds_strstart
+	lea	edi, [esi+ebp]
+	mov	[esp+scan],edi
+
+;/* Determine how many bytes the scan ptr is off from being             */
+;/* dword-aligned.                                                      */
+
+	mov	eax, edi
+	neg	eax
+	and	eax, 3
+	mov	[esp+scanalign], eax
+
+;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?                      */
+;/*     s->strstart - (IPos)MAX_DIST(s) : NIL;                          */
+
+	mov	eax, [edx].ds_w_size
+	sub	eax, MIN_LOOKAHEAD
+	sub	ebp, eax
+	jg	SHORT LimitPositive
+	xor	ebp, ebp
+LimitPositive:
+
+;/* int best_len = s->prev_length;                                      */
+
+	mov	eax, [edx].ds_prev_length
+	mov	[esp+bestlen], eax
+
+;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
+
+	add	esi, eax
+	mov	[esp+windowbestlen], esi
+
+;/* register ush scan_start = *(ushf*)scan;                             */
+;/* register ush scan_end   = *(ushf*)(scan+best_len-1);                */
+;/* Posf *prev = s->prev;                                               */
+
+	movzx	ebx, WORD PTR[edi]
+	mov	[esp+scanstart], ebx
+	movzx	ebx, WORD PTR[eax+edi-1]
+	mov	[esp+scanend], ebx
+	mov	edi, [edx].ds_prev
+
+;/* Jump into the main loop.                                            */
+
+	mov	edx, [esp+chainlenwmask]
+	jmp	SHORT LoopEntry
+
+;/* do {
+; *     match = s->window + cur_match;
+; *     if (*(ushf*)(match+best_len-1) != scan_end ||
+; *         *(ushf*)match != scan_start) continue;
+; *     [...]
+; * } while ((cur_match = prev[cur_match & wmask]) > limit
+; *          && --chain_length != 0);
+; *
+; * Here is the inner loop of the function. The function will spend the
+; * majority of its time in this loop, and majority of that time will
+; * be spent in the first ten instructions.
+; *
+; * Within this loop:
+; * %ebx = scanend
+; * %ecx = curmatch
+; * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
+; * %esi = windowbestlen - i.e., (window + bestlen)
+; * %edi = prev
+; * %ebp = limit
+; */
+
+	ALIGN	4
+LookupLoop:
+	and	ecx, edx
+	movzx	ecx, WORD PTR[edi+ecx*2]
+	cmp	ecx, ebp
+	jbe	LeaveNow
+	sub	edx, 000010000H
+	js	LeaveNow
+
+LoopEntry:
+	movzx	eax, WORD PTR[esi+ecx-1]
+	cmp	eax, ebx
+	jnz	SHORT LookupLoop
+
+	mov	eax, [esp+window]
+	movzx	eax, WORD PTR[eax+ecx]
+	cmp	eax, [esp+scanstart]
+	jnz	SHORT LookupLoop
+
+;/* Store the current value of chainlen.                                */
+
+	mov	[esp+chainlenwmask], edx
+
+;/* Point %edi to the string under scrutiny, and %esi to the string we  */
+;/* are hoping to match it up with. In actuality, %esi and %edi are     */
+;/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is     */
+;/* initialized to -(MAX_MATCH_8 - scanalign).                          */
+
+	mov	esi, [esp+window]
+	mov	edi, [esp+scan]
+	add	esi, ecx
+	mov	eax, [esp+scanalign]
+	mov	edx, -MAX_MATCH_8
+	lea	edi, [edi+eax+MAX_MATCH_8]
+	lea	esi, [esi+eax+MAX_MATCH_8]
+
+;/* Test the strings for equality, 8 bytes at a time. At the end,
+; * adjust %edx so that it is offset to the exact byte that mismatched.
+; *
+; * We already know at this point that the first three bytes of the
+; * strings match each other, and they can be safely passed over before
+; * starting the compare loop. So what this code does is skip over 0-3
+; * bytes, as much as necessary in order to dword-align the %edi
+; * pointer. (%esi will still be misaligned three times out of four.)
+; *
+; * It should be confessed that this loop usually does not represent
+; * much of the total running time. Replacing it with a more
+; * straightforward "rep cmpsb" would not drastically degrade
+; * performance.
+; */
+
+LoopCmps:
+	mov	eax, DWORD PTR[esi+edx]
+	xor	eax, DWORD PTR[edi+edx]
+	jnz	SHORT LeaveLoopCmps
+
+	mov	eax, DWORD PTR[esi+edx+4]
+	xor	eax, DWORD PTR[edi+edx+4]
+	jnz	SHORT LeaveLoopCmps4
+
+	add	edx, 8
+	jnz	SHORT LoopCmps
+	jmp	LenMaximum
+	ALIGN	4
+
+LeaveLoopCmps4:
+	add	edx, 4
+
+LeaveLoopCmps:
+	test	eax, 00000FFFFH
+	jnz	SHORT LenLower
+
+	add	edx, 2
+	shr	eax, 16
+
+LenLower:
+	sub	al, 1
+	adc	edx, 0
+
+;/* Calculate the length of the match. If it is longer than MAX_MATCH,  */
+;/* then automatically accept it as the best possible match and leave.  */
+
+	lea	eax, [edi+edx]
+	mov	edi, [esp+scan]
+	sub	eax, edi
+	cmp	eax, MAX_MATCH
+	jge	SHORT LenMaximum
+
+;/* If the length of the match is not longer than the best match we     */
+;/* have so far, then forget it and return to the lookup loop.          */
+
+	mov	edx, [esp+deflatestate]
+	mov	ebx, [esp+bestlen]
+	cmp	eax, ebx
+	jg	SHORT LongerMatch
+	mov	esi, [esp+windowbestlen]
+	mov	edi, [edx].ds_prev
+	mov	ebx, [esp+scanend]
+	mov	edx, [esp+chainlenwmask]
+	jmp	LookupLoop
+	ALIGN	4
+
+;/*         s->match_start = cur_match;                                 */
+;/*         best_len = len;                                             */
+;/*         if (len >= nice_match) break;                               */
+;/*         scan_end = *(ushf*)(scan+best_len-1);                       */
+
+LongerMatch:
+	mov	ebx, [esp+nicematch]
+	mov	[esp+bestlen], eax
+	mov	[edx].ds_match_start, ecx
+	cmp	eax, ebx
+	jge	SHORT LeaveNow
+	mov	esi, [esp+window]
+	add	esi, eax
+	mov	[esp+windowbestlen], esi
+	movzx	ebx, WORD PTR[edi+eax-1]
+	mov	edi, [edx].ds_prev
+	mov	[esp+scanend], ebx
+	mov	edx, [esp+chainlenwmask]
+	jmp	LookupLoop
+	ALIGN	4
+
+;/* Accept the current string, with the maximum possible length.        */
+
+LenMaximum:
+	mov	edx, [esp+deflatestate]
+	mov	DWORD PTR[esp+bestlen], MAX_MATCH
+	mov	[edx].ds_match_start, ecx
+
+;/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;          */
+;/* return s->lookahead;                                                */
+
+LeaveNow:
+	mov	edx, [esp+deflatestate]
+	mov	ebx, [esp+bestlen]
+	mov	eax, [edx].ds_lookahead
+	cmp	ebx, eax
+	jg	SHORT LookaheadRet
+	mov	eax, ebx
+LookaheadRet:
+
+; Restore the stack and return from whence we came.
+
+	add	esp, varsize
+	pop	ebx
+	pop	esi
+	pop	edi
+	pop	ebp
+	ret
+
+_longest_match	ENDP
+
+_TEXT	ENDS
+END
Index: /trunk/minix/lib/zlib-1.2.3/contrib/masmx64/bld_ml64.bat
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/masmx64/bld_ml64.bat	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/masmx64/bld_ml64.bat	(revision 9)
@@ -0,0 +1,2 @@
+ml64.exe /Flinffasx64 /c /Zi inffasx64.asm
+ml64.exe /Flgvmat64   /c /Zi gvmat64.asm
Index: /trunk/minix/lib/zlib-1.2.3/contrib/masmx64/gvmat64.asm
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/masmx64/gvmat64.asm	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/masmx64/gvmat64.asm	(revision 9)
@@ -0,0 +1,513 @@
+;uInt longest_match_x64(
+;    deflate_state *s,
+;    IPos cur_match);                             /* current match */
+
+; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86
+; Copyright (C) 1995-2005 Jean-loup Gailly, Brian Raiter and Gilles Vollant.
+;
+; File written by Gilles Vollant, by converting to assembly the longest_match
+;  from Jean-loup Gailly in deflate.c of zLib and infoZip zip.
+;
+;  and by taking inspiration on asm686 with masm, optimised assembly code
+;        from Brian Raiter, written 1998
+;
+;         http://www.zlib.net
+;         http://www.winimage.com/zLibDll
+;         http://www.muppetlabs.com/~breadbox/software/assembly.html
+;
+; to compile this file for infozip Zip, I use option:
+;   ml64.exe /Flgvmat64 /c /Zi /DINFOZIP gvmat64.asm
+;
+; to compile this file for zLib, I use option:
+;   ml64.exe /Flgvmat64 /c /Zi gvmat64.asm
+; Be carrefull to adapt zlib1222add below to your version of zLib
+;   (if you use a version of zLib before 1.0.4 or after 1.2.2.2, change
+;    value of zlib1222add later)
+;
+; This file compile with Microsoft Macro Assembler (x64) for AMD64
+;
+;   ml64.exe is given with Visual Studio 2005 and Windows 2003 server DDK
+;
+;   (you can get Windows 2003 server DDK with ml64 and cl for AMD64 from
+;      http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)
+;
+
+
+;uInt longest_match(s, cur_match)
+;    deflate_state *s;
+;    IPos cur_match;                             /* current match */
+.code
+longest_match PROC
+
+
+;LocalVarsSize   equ 88
+ LocalVarsSize   equ 72
+
+; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12
+; free register :  r14,r15
+; register can be saved : rsp
+
+ chainlenwmask   equ  rsp + 8 - LocalVarsSize    ; high word: current chain len
+                                                 ; low word: s->wmask
+;window          equ  rsp + xx - LocalVarsSize   ; local copy of s->window ; stored in r10
+;windowbestlen   equ  rsp + xx - LocalVarsSize   ; s->window + bestlen , use r10+r11
+;scanstart       equ  rsp + xx - LocalVarsSize   ; first two bytes of string ; stored in r12w
+;scanend         equ  rsp + xx - LocalVarsSize   ; last two bytes of string use ebx
+;scanalign       equ  rsp + xx - LocalVarsSize   ; dword-misalignment of string r13
+;bestlen         equ  rsp + xx - LocalVarsSize   ; size of best match so far -> r11d
+;scan            equ  rsp + xx - LocalVarsSize   ; ptr to string wanting match -> r9
+IFDEF INFOZIP
+ELSE
+ nicematch       equ  (rsp + 16 - LocalVarsSize) ; a good enough match size
+ENDIF
+
+save_rdi        equ  rsp + 24 - LocalVarsSize
+save_rsi        equ  rsp + 32 - LocalVarsSize
+save_rbx        equ  rsp + 40 - LocalVarsSize
+save_rbp        equ  rsp + 48 - LocalVarsSize
+save_r12        equ  rsp + 56 - LocalVarsSize
+save_r13        equ  rsp + 64 - LocalVarsSize
+;save_r14        equ  rsp + 72 - LocalVarsSize
+;save_r15        equ  rsp + 80 - LocalVarsSize
+
+
+
+;  all the +4 offsets are due to the addition of pending_buf_size (in zlib
+;  in the deflate_state structure since the asm code was first written
+;  (if you compile with zlib 1.0.4 or older, remove the +4).
+;  Note : these value are good with a 8 bytes boundary pack structure
+
+
+    MAX_MATCH           equ     258
+    MIN_MATCH           equ     3
+    MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)
+
+
+;;; Offsets for fields in the deflate_state structure. These numbers
+;;; are calculated from the definition of deflate_state, with the
+;;; assumption that the compiler will dword-align the fields. (Thus,
+;;; changing the definition of deflate_state could easily cause this
+;;; program to crash horribly, without so much as a warning at
+;;; compile time. Sigh.)
+
+;  all the +zlib1222add offsets are due to the addition of fields
+;  in zlib in the deflate_state structure since the asm code was first written
+;  (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
+;  (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
+;  if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
+
+
+IFDEF INFOZIP
+
+_DATA   SEGMENT
+COMM    window_size:DWORD
+; WMask ; 7fff
+COMM    window:BYTE:010040H
+COMM    prev:WORD:08000H
+; MatchLen : unused
+; PrevMatch : unused
+COMM    strstart:DWORD
+COMM    match_start:DWORD
+; Lookahead : ignore
+COMM    prev_length:DWORD ; PrevLen
+COMM    max_chain_length:DWORD
+COMM    good_match:DWORD
+COMM    nice_match:DWORD
+prev_ad equ OFFSET prev
+window_ad equ OFFSET window
+nicematch equ nice_match
+_DATA ENDS
+WMask equ 07fffh
+
+ELSE
+
+  IFNDEF zlib1222add
+    zlib1222add equ 8
+  ENDIF
+dsWSize         equ 56+zlib1222add+(zlib1222add/2)
+dsWMask         equ 64+zlib1222add+(zlib1222add/2)
+dsWindow        equ 72+zlib1222add
+dsPrev          equ 88+zlib1222add
+dsMatchLen      equ 128+zlib1222add
+dsPrevMatch     equ 132+zlib1222add
+dsStrStart      equ 140+zlib1222add
+dsMatchStart    equ 144+zlib1222add
+dsLookahead     equ 148+zlib1222add
+dsPrevLen       equ 152+zlib1222add
+dsMaxChainLen   equ 156+zlib1222add
+dsGoodMatch     equ 172+zlib1222add
+dsNiceMatch     equ 176+zlib1222add
+
+window_size     equ [ rcx + dsWSize]
+WMask           equ [ rcx + dsWMask]
+window_ad       equ [ rcx + dsWindow]
+prev_ad         equ [ rcx + dsPrev]
+strstart        equ [ rcx + dsStrStart]
+match_start     equ [ rcx + dsMatchStart]
+Lookahead       equ [ rcx + dsLookahead] ; 0ffffffffh on infozip
+prev_length     equ [ rcx + dsPrevLen]
+max_chain_length equ [ rcx + dsMaxChainLen]
+good_match      equ [ rcx + dsGoodMatch]
+nice_match      equ [ rcx + dsNiceMatch]
+ENDIF
+
+; parameter 1 in r8(deflate state s), param 2 in rdx (cur match)
+
+; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and
+; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp
+;
+; All registers must be preserved across the call, except for
+;   rax, rcx, rdx, r8, r9, r10, and r11, which are scratch.
+
+
+
+;;; Save registers that the compiler may be using, and adjust esp to
+;;; make room for our stack frame.
+
+
+;;; Retrieve the function arguments. r8d will hold cur_match
+;;; throughout the entire function. edx will hold the pointer to the
+;;; deflate_state structure during the function's setup (before
+;;; entering the main loop.
+
+; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match)
+
+; this clear high 32 bits of r8, which can be garbage in both r8 and rdx
+
+        mov [save_rdi],rdi
+        mov [save_rsi],rsi
+        mov [save_rbx],rbx
+        mov [save_rbp],rbp
+IFDEF INFOZIP
+        mov r8d,ecx
+ELSE
+        mov r8d,edx
+ENDIF
+        mov [save_r12],r12
+        mov [save_r13],r13
+;        mov [save_r14],r14
+;        mov [save_r15],r15
+
+
+;;; uInt wmask = s->w_mask;
+;;; unsigned chain_length = s->max_chain_length;
+;;; if (s->prev_length >= s->good_match) {
+;;;     chain_length >>= 2;
+;;; }
+
+        mov edi, prev_length
+        mov esi, good_match
+        mov eax, WMask
+        mov ebx, max_chain_length
+        cmp edi, esi
+        jl  LastMatchGood
+        shr ebx, 2
+LastMatchGood:
+
+;;; chainlen is decremented once beforehand so that the function can
+;;; use the sign flag instead of the zero flag for the exit test.
+;;; It is then shifted into the high word, to make room for the wmask
+;;; value, which it will always accompany.
+
+        dec ebx
+        shl ebx, 16
+        or  ebx, eax
+
+;;; on zlib only
+;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+IFDEF INFOZIP
+        mov [chainlenwmask], ebx
+; on infozip nice_match = [nice_match]
+ELSE
+        mov eax, nice_match
+        mov [chainlenwmask], ebx
+        mov r10d, Lookahead
+        cmp r10d, eax
+        cmovnl r10d, eax
+        mov [nicematch],r10d
+ENDIF
+
+;;; register Bytef *scan = s->window + s->strstart;
+        mov r10, window_ad
+        mov ebp, strstart
+        lea r13, [r10 + rbp]
+
+;;; Determine how many bytes the scan ptr is off from being
+;;; dword-aligned.
+
+         mov r9,r13
+         neg r13
+         and r13,3
+
+;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;
+IFDEF INFOZIP
+        mov eax,07efah ; MAX_DIST = (WSIZE-MIN_LOOKAHEAD) (0x8000-(3+8+1))
+ELSE
+        mov eax, window_size
+        sub eax, MIN_LOOKAHEAD
+ENDIF
+        xor edi,edi
+        sub ebp, eax
+
+        mov r11d, prev_length
+
+        cmovng ebp,edi
+
+;;; int best_len = s->prev_length;
+
+
+;;; Store the sum of s->window + best_len in esi locally, and in esi.
+
+       lea  rsi,[r10+r11]
+
+;;; register ush scan_start = *(ushf*)scan;
+;;; register ush scan_end   = *(ushf*)(scan+best_len-1);
+;;; Posf *prev = s->prev;
+
+        movzx r12d,word ptr [r9]
+        movzx ebx, word ptr [r9 + r11 - 1]
+
+        mov rdi, prev_ad
+
+;;; Jump into the main loop.
+
+        mov edx, [chainlenwmask]
+
+        cmp bx,word ptr [rsi + r8 - 1]
+        jz  LookupLoopIsZero
+
+LookupLoop1:
+        and r8d, edx
+
+        movzx   r8d, word ptr [rdi + r8*2]
+        cmp r8d, ebp
+        jbe LeaveNow
+        sub edx, 00010000h
+        js  LeaveNow
+
+LoopEntry1:
+        cmp bx,word ptr [rsi + r8 - 1]
+        jz  LookupLoopIsZero
+
+LookupLoop2:
+        and r8d, edx
+
+        movzx   r8d, word ptr [rdi + r8*2]
+        cmp r8d, ebp
+        jbe LeaveNow
+        sub edx, 00010000h
+        js  LeaveNow
+
+LoopEntry2:
+        cmp bx,word ptr [rsi + r8 - 1]
+        jz  LookupLoopIsZero
+
+LookupLoop4:
+        and r8d, edx
+
+        movzx   r8d, word ptr [rdi + r8*2]
+        cmp r8d, ebp
+        jbe LeaveNow
+        sub edx, 00010000h
+        js  LeaveNow
+
+LoopEntry4:
+
+        cmp bx,word ptr [rsi + r8 - 1]
+        jnz LookupLoop1
+        jmp LookupLoopIsZero
+
+
+;;; do {
+;;;     match = s->window + cur_match;
+;;;     if (*(ushf*)(match+best_len-1) != scan_end ||
+;;;         *(ushf*)match != scan_start) continue;
+;;;     [...]
+;;; } while ((cur_match = prev[cur_match & wmask]) > limit
+;;;          && --chain_length != 0);
+;;;
+;;; Here is the inner loop of the function. The function will spend the
+;;; majority of its time in this loop, and majority of that time will
+;;; be spent in the first ten instructions.
+;;;
+;;; Within this loop:
+;;; ebx = scanend
+;;; r8d = curmatch
+;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
+;;; esi = windowbestlen - i.e., (window + bestlen)
+;;; edi = prev
+;;; ebp = limit
+
+LookupLoop:
+        and r8d, edx
+
+        movzx   r8d, word ptr [rdi + r8*2]
+        cmp r8d, ebp
+        jbe LeaveNow
+        sub edx, 00010000h
+        js  LeaveNow
+
+LoopEntry:
+
+        cmp bx,word ptr [rsi + r8 - 1]
+        jnz LookupLoop1
+LookupLoopIsZero:
+        cmp     r12w, word ptr [r10 + r8]
+        jnz LookupLoop1
+
+
+;;; Store the current value of chainlen.
+        mov [chainlenwmask], edx
+
+;;; Point edi to the string under scrutiny, and esi to the string we
+;;; are hoping to match it up with. In actuality, esi and edi are
+;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
+;;; initialized to -(MAX_MATCH_8 - scanalign).
+
+        lea rsi,[r8+r10]
+        mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8)
+        lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8]
+        lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8]
+
+        prefetcht1 [rsi+rdx]
+        prefetcht1 [rdi+rdx]
+
+
+;;; Test the strings for equality, 8 bytes at a time. At the end,
+;;; adjust rdx so that it is offset to the exact byte that mismatched.
+;;;
+;;; We already know at this point that the first three bytes of the
+;;; strings match each other, and they can be safely passed over before
+;;; starting the compare loop. So what this code does is skip over 0-3
+;;; bytes, as much as necessary in order to dword-align the edi
+;;; pointer. (rsi will still be misaligned three times out of four.)
+;;;
+;;; It should be confessed that this loop usually does not represent
+;;; much of the total running time. Replacing it with a more
+;;; straightforward "rep cmpsb" would not drastically degrade
+;;; performance.
+
+
+LoopCmps:
+        mov rax, [rsi + rdx]
+        xor rax, [rdi + rdx]
+        jnz LeaveLoopCmps
+
+        mov rax, [rsi + rdx + 8]
+        xor rax, [rdi + rdx + 8]
+        jnz LeaveLoopCmps8
+
+
+        mov rax, [rsi + rdx + 8+8]
+        xor rax, [rdi + rdx + 8+8]
+        jnz LeaveLoopCmps16
+
+        add rdx,8+8+8
+
+        jmp short LoopCmps
+LeaveLoopCmps16: add rdx,8
+LeaveLoopCmps8: add rdx,8
+LeaveLoopCmps:
+
+        test    eax, 0000FFFFh
+        jnz LenLower
+
+        test eax,0ffffffffh
+
+        jnz LenLower32
+
+        add rdx,4
+        shr rax,32
+        or ax,ax
+        jnz LenLower
+
+LenLower32:
+        shr eax,16
+        add rdx,2
+LenLower:   sub al, 1
+        adc rdx, 0
+;;; Calculate the length of the match. If it is longer than MAX_MATCH,
+;;; then automatically accept it as the best possible match and leave.
+
+        lea rax, [rdi + rdx]
+        sub rax, r9
+        cmp eax, MAX_MATCH
+        jge LenMaximum
+
+;;; If the length of the match is not longer than the best match we
+;;; have so far, then forget it and return to the lookup loop.
+;///////////////////////////////////
+
+        cmp eax, r11d
+        jg  LongerMatch
+
+        lea rsi,[r10+r11]
+
+        mov rdi, prev_ad
+        mov edx, [chainlenwmask]
+        jmp LookupLoop
+
+;;;         s->match_start = cur_match;
+;;;         best_len = len;
+;;;         if (len >= nice_match) break;
+;;;         scan_end = *(ushf*)(scan+best_len-1);
+
+LongerMatch:
+        mov r11d, eax
+        mov match_start, r8d
+        cmp eax, [nicematch]
+        jge LeaveNow
+
+        lea rsi,[r10+rax]
+
+        movzx   ebx, word ptr [r9 + rax - 1]
+        mov rdi, prev_ad
+        mov edx, [chainlenwmask]
+        jmp LookupLoop
+
+;;; Accept the current string, with the maximum possible length.
+
+LenMaximum:
+        mov r11d,MAX_MATCH
+        mov match_start, r8d
+
+;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+;;; return s->lookahead;
+
+LeaveNow:
+IFDEF INFOZIP
+        mov eax,r11d
+ELSE
+        mov eax, Lookahead
+        cmp r11d, eax
+        cmovng eax, r11d
+ENDIF
+
+;;; Restore the stack and return from whence we came.
+
+
+        mov rsi,[save_rsi]
+        mov rdi,[save_rdi]
+        mov rbx,[save_rbx]
+        mov rbp,[save_rbp]
+        mov r12,[save_r12]
+        mov r13,[save_r13]
+;        mov r14,[save_r14]
+;        mov r15,[save_r15]
+
+
+        ret 0
+; please don't remove this string !
+; Your can freely use gvmat64 in any free or commercial app
+; but it is far better don't remove the string in the binary!
+    db     0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0
+longest_match   ENDP
+
+match_init PROC
+  ret 0
+match_init ENDP
+
+
+END
Index: /trunk/minix/lib/zlib-1.2.3/contrib/masmx64/inffas8664.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/masmx64/inffas8664.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/masmx64/inffas8664.c	(revision 9)
@@ -0,0 +1,186 @@
+/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding
+ * version for AMD64 on Windows using Microsoft C compiler
+ *
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Copyright (C) 2003 Chris Anderson <christop@charm.net>
+ * Please use the copyright conditions above.
+ *
+ * 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant
+ *
+ * inffas8664.c call function inffas8664fnc in inffasx64.asm
+ *  inffasx64.asm is automatically convert from AMD64 portion of inffas86.c
+ *
+ * Dec-29-2003 -- I added AMD64 inflate asm support.  This version is also
+ * slightly quicker on x86 systems because, instead of using rep movsb to copy
+ * data, it uses rep movsw, which moves data in 2-byte chunks instead of single
+ * bytes.  I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates
+ * from http://fedora.linux.duke.edu/fc1_x86_64
+ * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with
+ * 1GB ram.  The 64-bit version is about 4% faster than the 32-bit version,
+ * when decompressing mozilla-source-1.3.tar.gz.
+ *
+ * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from
+ * the gcc -S output of zlib-1.2.0/inffast.c.  Zlib-1.2.0 is in beta release at
+ * the moment.  I have successfully compiled and tested this code with gcc2.96,
+ * gcc3.2, icc5.0, msvc6.0.  It is very close to the speed of inffast.S
+ * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX
+ * enabled.  I will attempt to merge the MMX code into this version.  Newer
+ * versions of this and inffast.S can be found at
+ * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/
+ *
+ */
+
+#include <stdio.h>
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+/* Mark Adler's comments from inffast.c: */
+
+/*
+   Decode literal, length, and distance codes and write out the resulting
+   literal and match bytes until either not enough input or output is
+   available, an end-of-block is encountered, or a data error is encountered.
+   When large enough input and output buffers are supplied to inflate(), for
+   example, a 16K input buffer and a 64K output buffer, more than 95% of the
+   inflate execution time is spent in this routine.
+
+   Entry assumptions:
+
+        state->mode == LEN
+        strm->avail_in >= 6
+        strm->avail_out >= 258
+        start >= strm->avail_out
+        state->bits < 8
+
+   On return, state->mode is one of:
+
+        LEN -- ran out of enough output space or enough available input
+        TYPE -- reached end of block code, inflate() to interpret next block
+        BAD -- error in block data
+
+   Notes:
+
+    - The maximum input bits used by a length/distance pair is 15 bits for the
+      length code, 5 bits for the length extra, 15 bits for the distance code,
+      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
+      Therefore if strm->avail_in >= 6, then there is enough input to avoid
+      checking for available input while decoding.
+
+    - The maximum bytes that a single length/distance pair can output is 258
+      bytes, which is the maximum length that can be coded.  inflate_fast()
+      requires strm->avail_out >= 258 for each loop to avoid checking for
+      output space.
+ */
+
+
+
+    typedef struct inffast_ar {
+/* 64   32                               x86  x86_64 */
+/* ar offset                              register */
+/*  0    0 */ void *esp;                /* esp save */
+/*  8    4 */ void *ebp;                /* ebp save */
+/* 16    8 */ unsigned char FAR *in;    /* esi rsi  local strm->next_in */
+/* 24   12 */ unsigned char FAR *last;  /*     r9   while in < last */
+/* 32   16 */ unsigned char FAR *out;   /* edi rdi  local strm->next_out */
+/* 40   20 */ unsigned char FAR *beg;   /*          inflate()'s init next_out */
+/* 48   24 */ unsigned char FAR *end;   /*     r10  while out < end */
+/* 56   28 */ unsigned char FAR *window;/*          size of window, wsize!=0 */
+/* 64   32 */ code const FAR *lcode;    /* ebp rbp  local strm->lencode */
+/* 72   36 */ code const FAR *dcode;    /*     r11  local strm->distcode */
+/* 80   40 */ size_t /*unsigned long */hold;       /* edx rdx  local strm->hold */
+/* 88   44 */ unsigned bits;            /* ebx rbx  local strm->bits */
+/* 92   48 */ unsigned wsize;           /*          window size */
+/* 96   52 */ unsigned write;           /*          window write index */
+/*100   56 */ unsigned lmask;           /*     r12  mask for lcode */
+/*104   60 */ unsigned dmask;           /*     r13  mask for dcode */
+/*108   64 */ unsigned len;             /*     r14  match length */
+/*112   68 */ unsigned dist;            /*     r15  match distance */
+/*116   72 */ unsigned status;          /*          set when state chng*/
+    } type_ar;
+#ifdef ASMINF
+
+void inflate_fast(strm, start)
+z_streamp strm;
+unsigned start;         /* inflate()'s starting value for strm->avail_out */
+{
+    struct inflate_state FAR *state;
+    type_ar ar;
+    void inffas8664fnc(struct inffast_ar * par);
+
+    
+
+#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64))
+#define PAD_AVAIL_IN 6
+#define PAD_AVAIL_OUT 258    
+#else
+#define PAD_AVAIL_IN 5
+#define PAD_AVAIL_OUT 257
+#endif
+
+    /* copy state to local variables */
+    state = (struct inflate_state FAR *)strm->state;
+
+    ar.in = strm->next_in;
+    ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN);
+    ar.out = strm->next_out;
+    ar.beg = ar.out - (start - strm->avail_out);
+    ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT);
+    ar.wsize = state->wsize;
+    ar.write = state->write;
+    ar.window = state->window;
+    ar.hold = state->hold;
+    ar.bits = state->bits;
+    ar.lcode = state->lencode;
+    ar.dcode = state->distcode;
+    ar.lmask = (1U << state->lenbits) - 1;
+    ar.dmask = (1U << state->distbits) - 1;
+
+    /* decode literals and length/distances until end-of-block or not enough
+       input data or output space */
+
+    /* align in on 1/2 hold size boundary */
+    while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) {
+        ar.hold += (unsigned long)*ar.in++ << ar.bits;
+        ar.bits += 8;
+    }
+
+    inffas8664fnc(&ar);
+
+    if (ar.status > 1) {
+        if (ar.status == 2)
+            strm->msg = "invalid literal/length code";
+        else if (ar.status == 3)
+            strm->msg = "invalid distance code";
+        else
+            strm->msg = "invalid distance too far back";
+        state->mode = BAD;
+    }
+    else if ( ar.status == 1 ) {
+        state->mode = TYPE;
+    }
+
+    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+    ar.len = ar.bits >> 3;
+    ar.in -= ar.len;
+    ar.bits -= ar.len << 3;
+    ar.hold &= (1U << ar.bits) - 1;
+
+    /* update state and return */
+    strm->next_in = ar.in;
+    strm->next_out = ar.out;
+    strm->avail_in = (unsigned)(ar.in < ar.last ?
+                                PAD_AVAIL_IN + (ar.last - ar.in) :
+                                PAD_AVAIL_IN - (ar.in - ar.last));
+    strm->avail_out = (unsigned)(ar.out < ar.end ?
+                                 PAD_AVAIL_OUT + (ar.end - ar.out) :
+                                 PAD_AVAIL_OUT - (ar.out - ar.end));
+    state->hold = (unsigned long)ar.hold;
+    state->bits = ar.bits;
+    return;
+}
+
+#endif
Index: /trunk/minix/lib/zlib-1.2.3/contrib/masmx64/inffasx64.asm
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/masmx64/inffasx64.asm	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/masmx64/inffasx64.asm	(revision 9)
@@ -0,0 +1,392 @@
+; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding
+; version for AMD64 on Windows using Microsoft C compiler
+;
+; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c
+; inffasx64.asm is called by inffas8664.c, which contain more info.
+
+
+; to compile this file, I use option
+;   ml64.exe /Flinffasx64 /c /Zi inffasx64.asm
+;   with Microsoft Macro Assembler (x64) for AMD64
+;
+;   ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK
+;
+;   (you can get Windows 2003 server DDK with ml64 and cl.exe for AMD64 from 
+;      http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)
+;
+
+.code
+inffas8664fnc PROC
+
+; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and
+; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp
+;
+; All registers must be preserved across the call, except for
+;   rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch.
+
+
+	mov [rsp-8],rsi
+	mov [rsp-16],rdi
+	mov [rsp-24],r12
+	mov [rsp-32],r13
+	mov [rsp-40],r14
+	mov [rsp-48],r15
+	mov [rsp-56],rbx
+
+	mov rax,rcx
+
+	mov	[rax+8], rbp       ; /* save regs rbp and rsp */
+	mov	[rax], rsp
+
+	mov	rsp, rax          ; /* make rsp point to &ar */
+
+	mov	rsi, [rsp+16]      ; /* rsi  = in */
+	mov	rdi, [rsp+32]      ; /* rdi  = out */
+	mov	r9, [rsp+24]       ; /* r9   = last */
+	mov	r10, [rsp+48]      ; /* r10  = end */
+	mov	rbp, [rsp+64]      ; /* rbp  = lcode */
+	mov	r11, [rsp+72]      ; /* r11  = dcode */
+	mov	rdx, [rsp+80]      ; /* rdx  = hold */
+	mov	ebx, [rsp+88]      ; /* ebx  = bits */
+	mov	r12d, [rsp+100]    ; /* r12d = lmask */
+	mov	r13d, [rsp+104]    ; /* r13d = dmask */
+                                          ; /* r14d = len */
+                                          ; /* r15d = dist */
+
+
+	cld
+	cmp	r10, rdi
+	je	L_one_time           ; /* if only one decode left */
+	cmp	r9, rsi
+
+    jne L_do_loop
+
+
+L_one_time:
+	mov	r8, r12           ; /* r8 = lmask */
+	cmp	bl, 32
+	ja	L_get_length_code_one_time
+
+	lodsd                         ; /* eax = *(uint *)in++ */
+	mov	cl, bl            ; /* cl = bits, needs it for shifting */
+	add	bl, 32             ; /* bits += 32 */
+	shl	rax, cl
+	or	rdx, rax          ; /* hold |= *((uint *)in)++ << bits */
+	jmp	L_get_length_code_one_time
+
+ALIGN 4
+L_while_test:
+	cmp	r10, rdi
+	jbe	L_break_loop
+	cmp	r9, rsi
+	jbe	L_break_loop
+
+L_do_loop:
+	mov	r8, r12           ; /* r8 = lmask */
+	cmp	bl, 32
+	ja	L_get_length_code    ; /* if (32 < bits) */
+
+	lodsd                         ; /* eax = *(uint *)in++ */
+	mov	cl, bl            ; /* cl = bits, needs it for shifting */
+	add	bl, 32             ; /* bits += 32 */
+	shl	rax, cl
+	or	rdx, rax          ; /* hold |= *((uint *)in)++ << bits */
+
+L_get_length_code:
+	and	r8, rdx            ; /* r8 &= hold */
+	mov	eax, [rbp+r8*4]  ; /* eax = lcode[hold & lmask] */
+
+	mov	cl, ah            ; /* cl = this.bits */
+	sub	bl, ah            ; /* bits -= this.bits */
+	shr	rdx, cl           ; /* hold >>= this.bits */
+
+	test	al, al
+	jnz	L_test_for_length_base ; /* if (op != 0) 45.7% */
+
+	mov	r8, r12            ; /* r8 = lmask */
+	shr	eax, 16            ; /* output this.val char */
+	stosb
+
+L_get_length_code_one_time:
+	and	r8, rdx            ; /* r8 &= hold */
+	mov	eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */
+
+L_dolen:
+	mov	cl, ah            ; /* cl = this.bits */
+	sub	bl, ah            ; /* bits -= this.bits */
+	shr	rdx, cl           ; /* hold >>= this.bits */
+
+	test	al, al
+	jnz	L_test_for_length_base ; /* if (op != 0) 45.7% */
+
+	shr	eax, 16            ; /* output this.val char */
+	stosb
+	jmp	L_while_test
+
+ALIGN 4
+L_test_for_length_base:
+	mov	r14d, eax         ; /* len = this */
+	shr	r14d, 16           ; /* len = this.val */
+	mov	cl, al
+
+	test	al, 16
+	jz	L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */
+	and	cl, 15             ; /* op &= 15 */
+	jz	L_decode_distance    ; /* if (!op) */
+
+L_add_bits_to_len:
+	sub	bl, cl
+	xor	eax, eax
+	inc	eax
+	shl	eax, cl
+	dec	eax
+	and	eax, edx          ; /* eax &= hold */
+	shr	rdx, cl
+	add	r14d, eax         ; /* len += hold & mask[op] */
+
+L_decode_distance:
+	mov	r8, r13           ; /* r8 = dmask */
+	cmp	bl, 32
+	ja	L_get_distance_code  ; /* if (32 < bits) */
+
+	lodsd                         ; /* eax = *(uint *)in++ */
+	mov	cl, bl            ; /* cl = bits, needs it for shifting */
+	add	bl, 32             ; /* bits += 32 */
+	shl	rax, cl
+	or	rdx, rax          ; /* hold |= *((uint *)in)++ << bits */
+
+L_get_distance_code:
+	and	r8, rdx           ; /* r8 &= hold */
+	mov	eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */
+
+L_dodist:
+	mov	r15d, eax         ; /* dist = this */
+	shr	r15d, 16           ; /* dist = this.val */
+	mov	cl, ah
+	sub	bl, ah            ; /* bits -= this.bits */
+	shr	rdx, cl           ; /* hold >>= this.bits */
+	mov	cl, al            ; /* cl = this.op */
+
+	test	al, 16             ; /* if ((op & 16) == 0) */
+	jz	L_test_for_second_level_dist
+	and	cl, 15             ; /* op &= 15 */
+	jz	L_check_dist_one
+
+L_add_bits_to_dist:
+	sub	bl, cl
+	xor	eax, eax
+	inc	eax
+	shl	eax, cl
+	dec	eax                 ; /* (1 << op) - 1 */
+	and	eax, edx          ; /* eax &= hold */
+	shr	rdx, cl
+	add	r15d, eax         ; /* dist += hold & ((1 << op) - 1) */
+
+L_check_window:
+	mov	r8, rsi           ; /* save in so from can use it's reg */
+	mov	rax, rdi
+	sub	rax, [rsp+40]      ; /* nbytes = out - beg */
+
+	cmp	eax, r15d
+	jb	L_clip_window        ; /* if (dist > nbytes) 4.2% */
+
+	mov	ecx, r14d         ; /* ecx = len */
+	mov	rsi, rdi
+	sub	rsi, r15          ; /* from = out - dist */
+
+	sar	ecx, 1
+	jnc	L_copy_two           ; /* if len % 2 == 0 */
+
+	rep     movsw
+	mov	al, [rsi]
+	mov	[rdi], al
+	inc	rdi
+
+	mov	rsi, r8           ; /* move in back to %rsi, toss from */
+	jmp	L_while_test
+
+L_copy_two:
+	rep     movsw
+	mov	rsi, r8           ; /* move in back to %rsi, toss from */
+	jmp	L_while_test
+
+ALIGN 4
+L_check_dist_one:
+	cmp	r15d, 1            ; /* if dist 1, is a memset */
+	jne	L_check_window
+	cmp	[rsp+40], rdi      ; /* if out == beg, outside window */
+	je	L_check_window
+
+	mov	ecx, r14d         ; /* ecx = len */
+	mov	al, [rdi-1]
+	mov	ah, al
+
+	sar	ecx, 1
+	jnc	L_set_two
+	mov	[rdi], al
+	inc	rdi
+
+L_set_two:
+	rep     stosw
+	jmp	L_while_test
+
+ALIGN 4
+L_test_for_second_level_length:
+	test	al, 64
+	jnz	L_test_for_end_of_block ; /* if ((op & 64) != 0) */
+
+	xor	eax, eax
+	inc	eax
+	shl	eax, cl
+	dec	eax
+	and	eax, edx         ; /* eax &= hold */
+	add	eax, r14d        ; /* eax += len */
+	mov	eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/
+	jmp	L_dolen
+
+ALIGN 4
+L_test_for_second_level_dist:
+	test	al, 64
+	jnz	L_invalid_distance_code ; /* if ((op & 64) != 0) */
+
+	xor	eax, eax
+	inc	eax
+	shl	eax, cl
+	dec	eax
+	and	eax, edx         ; /* eax &= hold */
+	add	eax, r15d        ; /* eax += dist */
+	mov	eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/
+	jmp	L_dodist
+
+ALIGN 4
+L_clip_window:
+	mov	ecx, eax         ; /* ecx = nbytes */
+	mov	eax, [rsp+92]     ; /* eax = wsize, prepare for dist cmp */
+	neg	ecx                ; /* nbytes = -nbytes */
+
+	cmp	eax, r15d
+	jb	L_invalid_distance_too_far ; /* if (dist > wsize) */
+
+	add	ecx, r15d         ; /* nbytes = dist - nbytes */
+	cmp	dword ptr [rsp+96], 0
+	jne	L_wrap_around_window ; /* if (write != 0) */
+
+	mov	rsi, [rsp+56]     ; /* from  = window */
+	sub	eax, ecx         ; /* eax  -= nbytes */
+	add	rsi, rax         ; /* from += wsize - nbytes */
+
+	mov	eax, r14d        ; /* eax = len */
+	cmp	r14d, ecx
+	jbe	L_do_copy           ; /* if (nbytes >= len) */
+
+	sub	eax, ecx         ; /* eax -= nbytes */
+	rep     movsb
+	mov	rsi, rdi
+	sub	rsi, r15         ; /* from = &out[ -dist ] */
+	jmp	L_do_copy
+
+ALIGN 4
+L_wrap_around_window:
+	mov	eax, [rsp+96]     ; /* eax = write */
+	cmp	ecx, eax
+	jbe	L_contiguous_in_window ; /* if (write >= nbytes) */
+
+	mov	esi, [rsp+92]     ; /* from  = wsize */
+	add	rsi, [rsp+56]     ; /* from += window */
+	add	rsi, rax         ; /* from += write */
+	sub	rsi, rcx         ; /* from -= nbytes */
+	sub	ecx, eax         ; /* nbytes -= write */
+
+	mov	eax, r14d        ; /* eax = len */
+	cmp	eax, ecx
+	jbe	L_do_copy           ; /* if (nbytes >= len) */
+
+	sub	eax, ecx         ; /* len -= nbytes */
+	rep     movsb
+	mov	rsi, [rsp+56]     ; /* from = window */
+	mov	ecx, [rsp+96]     ; /* nbytes = write */
+	cmp	eax, ecx
+	jbe	L_do_copy           ; /* if (nbytes >= len) */
+
+	sub	eax, ecx         ; /* len -= nbytes */
+	rep     movsb
+	mov	rsi, rdi
+	sub	rsi, r15         ; /* from = out - dist */
+	jmp	L_do_copy
+
+ALIGN 4
+L_contiguous_in_window:
+	mov	rsi, [rsp+56]     ; /* rsi = window */
+	add	rsi, rax
+	sub	rsi, rcx         ; /* from += write - nbytes */
+
+	mov	eax, r14d        ; /* eax = len */
+	cmp	eax, ecx
+	jbe	L_do_copy           ; /* if (nbytes >= len) */
+
+	sub	eax, ecx         ; /* len -= nbytes */
+	rep     movsb
+	mov	rsi, rdi
+	sub	rsi, r15         ; /* from = out - dist */
+	jmp	L_do_copy           ; /* if (nbytes >= len) */
+
+ALIGN 4
+L_do_copy:
+	mov	ecx, eax         ; /* ecx = len */
+	rep     movsb
+
+	mov	rsi, r8          ; /* move in back to %esi, toss from */
+	jmp	L_while_test
+
+L_test_for_end_of_block:
+	test	al, 32
+	jz	L_invalid_literal_length_code
+	mov	dword ptr [rsp+116], 1
+	jmp	L_break_loop_with_status
+
+L_invalid_literal_length_code:
+	mov	dword ptr [rsp+116], 2
+	jmp	L_break_loop_with_status
+
+L_invalid_distance_code:
+	mov	dword ptr [rsp+116], 3
+	jmp	L_break_loop_with_status
+
+L_invalid_distance_too_far:
+	mov	dword ptr [rsp+116], 4
+	jmp	L_break_loop_with_status
+
+L_break_loop:
+	mov	dword ptr [rsp+116], 0
+
+L_break_loop_with_status:
+; /* put in, out, bits, and hold back into ar and pop esp */
+	mov	[rsp+16], rsi     ; /* in */
+	mov	[rsp+32], rdi     ; /* out */
+	mov	[rsp+88], ebx     ; /* bits */
+	mov	[rsp+80], rdx     ; /* hold */
+
+	mov	rax, [rsp]       ; /* restore rbp and rsp */
+	mov	rbp, [rsp+8]
+	mov	rsp, rax
+
+
+
+	mov rsi,[rsp-8]
+	mov rdi,[rsp-16]
+	mov r12,[rsp-24]
+	mov r13,[rsp-32]
+	mov r14,[rsp-40]
+	mov r15,[rsp-48]
+	mov rbx,[rsp-56]
+	
+    ret 0
+;          :
+;          : "m" (ar)
+;          : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi",
+;            "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
+;    );
+
+inffas8664fnc 	ENDP
+;_TEXT	ENDS
+END
Index: /trunk/minix/lib/zlib-1.2.3/contrib/masmx64/readme.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/masmx64/readme.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/masmx64/readme.txt	(revision 9)
@@ -0,0 +1,28 @@
+Summary
+-------
+This directory contains ASM implementations of the functions
+longest_match() and inflate_fast(), for 64 bits x86 (both AMD64 and Intel EM64t),
+for use with Microsoft Macro Assembler (x64) for AMD64 and Microsoft C++ 64 bits.
+
+gvmat64.asm is written by Gilles Vollant (2005), by using Brian Raiter 686/32 bits
+   assembly optimized version from Jean-loup Gailly original longest_match function
+
+inffasx64.asm and inffas8664.c were written by Chris Anderson, by optimizing
+   original function from Mark Adler
+
+Use instructions
+----------------
+Copy these files into the zlib source directory.
+
+define ASMV and ASMINF in your project. Include inffas8664.c in your source tree,
+and inffasx64.obj and gvmat64.obj as object to link.
+
+
+Build instructions
+------------------
+run bld_64.bat with Microsoft Macro Assembler (x64) for AMD64 (ml64.exe)
+
+ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK
+
+You can get Windows 2003 server DDK with ml64 and cl for AMD64 from 
+  http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)
Index: /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/bld_ml32.bat
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/bld_ml32.bat	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/bld_ml32.bat	(revision 9)
@@ -0,0 +1,2 @@
+ml /coff /Zi /c /Flgvmat32.lst  gvmat32.asm 
+ml /coff /Zi /c /Flinffas32.lst inffas32.asm 
Index: /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/gvmat32.asm
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/gvmat32.asm	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/gvmat32.asm	(revision 9)
@@ -0,0 +1,972 @@
+; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86
+; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
+; File written by Gilles Vollant, by modifiying the longest_match
+;  from Jean-loup Gailly in deflate.c
+;
+;         http://www.zlib.net
+;         http://www.winimage.com/zLibDll
+;         http://www.muppetlabs.com/~breadbox/software/assembly.html
+;
+; For Visual C++ 4.x and higher and ML 6.x and higher
+;   ml.exe is in directory \MASM611C of Win95 DDK
+;   ml.exe is also distributed in http://www.masm32.com/masmdl.htm
+;    and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/
+;
+; this file contain two implementation of longest_match
+;
+;  longest_match_7fff : written 1996 by Gilles Vollant optimized for 
+;            first Pentium. Assume s->w_mask == 0x7fff
+;  longest_match_686 : written by Brian raiter (1998), optimized for Pentium Pro
+;
+;  for using an seembly version of longest_match, you need define ASMV in project
+;  There is two way in using gvmat32.asm
+;
+;  A) Suggested method
+;    if you want include both longest_match_7fff and longest_match_686
+;    compile the asm file running
+;           ml /coff /Zi /Flgvmat32.lst /c gvmat32.asm
+;    and include gvmat32c.c in your project
+;    if you have an old cpu (386,486 or first Pentium) and s->w_mask==0x7fff,
+;        longest_match_7fff will be used
+;    if you have a more modern CPU (Pentium Pro, II and higher)
+;        longest_match_686 will be used
+;    on old cpu with s->w_mask!=0x7fff, longest_match_686 will be used,
+;        but this is not a sitation you'll find often
+;
+;  B) Alternative
+;    if you are not interresed in old cpu performance and want the smaller
+;       binaries possible
+;
+;    compile the asm file running
+;           ml /coff /Zi /c /Flgvmat32.lst /DNOOLDPENTIUMCODE gvmat32.asm
+;    and do not include gvmat32c.c in your project (ou define also 
+;              NOOLDPENTIUMCODE)
+;
+; note : as I known, longest_match_686 is very faster than longest_match_7fff
+;        on pentium Pro/II/III, faster (but less) in P4, but it seem
+;        longest_match_7fff can be faster (very very litte) on AMD Athlon64/K8
+;
+; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2
+
+;uInt longest_match_7fff(s, cur_match)
+;    deflate_state *s;
+;    IPos cur_match;                             /* current match */
+
+    NbStack         equ     76
+    cur_match       equ     dword ptr[esp+NbStack-0]
+    str_s           equ     dword ptr[esp+NbStack-4]
+; 5 dword on top (ret,ebp,esi,edi,ebx)
+    adrret          equ     dword ptr[esp+NbStack-8]
+    pushebp         equ     dword ptr[esp+NbStack-12]
+    pushedi         equ     dword ptr[esp+NbStack-16]
+    pushesi         equ     dword ptr[esp+NbStack-20]
+    pushebx         equ     dword ptr[esp+NbStack-24]
+
+    chain_length    equ     dword ptr [esp+NbStack-28]
+    limit           equ     dword ptr [esp+NbStack-32]
+    best_len        equ     dword ptr [esp+NbStack-36]
+    window          equ     dword ptr [esp+NbStack-40]
+    prev            equ     dword ptr [esp+NbStack-44]
+    scan_start      equ      word ptr [esp+NbStack-48]
+    wmask           equ     dword ptr [esp+NbStack-52]
+    match_start_ptr equ     dword ptr [esp+NbStack-56]
+    nice_match      equ     dword ptr [esp+NbStack-60]
+    scan            equ     dword ptr [esp+NbStack-64]
+
+    windowlen       equ     dword ptr [esp+NbStack-68]
+    match_start     equ     dword ptr [esp+NbStack-72]
+    strend          equ     dword ptr [esp+NbStack-76]
+    NbStackAdd      equ     (NbStack-24)
+
+    .386p
+
+    name    gvmatch
+    .MODEL  FLAT
+
+
+
+;  all the +zlib1222add offsets are due to the addition of fields
+;  in zlib in the deflate_state structure since the asm code was first written
+;  (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
+;  (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
+;  if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
+
+    zlib1222add         equ     8
+
+;  Note : these value are good with a 8 bytes boundary pack structure
+    dep_chain_length    equ     74h+zlib1222add
+    dep_window          equ     30h+zlib1222add
+    dep_strstart        equ     64h+zlib1222add
+    dep_prev_length     equ     70h+zlib1222add
+    dep_nice_match      equ     88h+zlib1222add
+    dep_w_size          equ     24h+zlib1222add
+    dep_prev            equ     38h+zlib1222add
+    dep_w_mask          equ     2ch+zlib1222add
+    dep_good_match      equ     84h+zlib1222add
+    dep_match_start     equ     68h+zlib1222add
+    dep_lookahead       equ     6ch+zlib1222add
+
+
+_TEXT                   segment
+
+IFDEF NOUNDERLINE
+   IFDEF NOOLDPENTIUMCODE
+            public  longest_match
+            public  match_init
+   ELSE            
+            public  longest_match_7fff
+            public  cpudetect32
+            public  longest_match_686
+   ENDIF
+ELSE
+   IFDEF NOOLDPENTIUMCODE
+            public  _longest_match
+            public  _match_init
+   ELSE
+            public  _longest_match_7fff
+            public  _cpudetect32
+            public  _longest_match_686
+   ENDIF
+ENDIF
+
+    MAX_MATCH           equ     258
+    MIN_MATCH           equ     3
+    MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)
+
+
+
+IFNDEF NOOLDPENTIUMCODE
+IFDEF NOUNDERLINE
+longest_match_7fff   proc near
+ELSE
+_longest_match_7fff  proc near
+ENDIF
+
+    mov     edx,[esp+4]
+
+
+
+    push    ebp
+    push    edi
+    push    esi
+    push    ebx
+
+    sub     esp,NbStackAdd
+
+; initialize or check the variables used in match.asm.
+    mov     ebp,edx
+
+; chain_length = s->max_chain_length
+; if (prev_length>=good_match) chain_length >>= 2
+    mov     edx,[ebp+dep_chain_length]
+    mov     ebx,[ebp+dep_prev_length]
+    cmp     [ebp+dep_good_match],ebx
+    ja      noshr
+    shr     edx,2
+noshr:
+; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop
+    inc     edx
+    mov     edi,[ebp+dep_nice_match]
+    mov     chain_length,edx
+    mov     eax,[ebp+dep_lookahead]
+    cmp     eax,edi
+; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+    jae     nolookaheadnicematch
+    mov     edi,eax
+nolookaheadnicematch:
+; best_len = s->prev_length
+    mov     best_len,ebx
+
+; window = s->window
+    mov     esi,[ebp+dep_window]
+    mov     ecx,[ebp+dep_strstart]
+    mov     window,esi
+
+    mov     nice_match,edi
+; scan = window + strstart
+    add     esi,ecx
+    mov     scan,esi
+; dx = *window
+    mov     dx,word ptr [esi]
+; bx = *(window+best_len-1)
+    mov     bx,word ptr [esi+ebx-1]
+    add     esi,MAX_MATCH-1
+; scan_start = *scan
+    mov     scan_start,dx
+; strend = scan + MAX_MATCH-1
+    mov     strend,esi
+; bx = scan_end = *(window+best_len-1)
+
+;    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+;        s->strstart - (IPos)MAX_DIST(s) : NIL;
+
+    mov     esi,[ebp+dep_w_size]
+    sub     esi,MIN_LOOKAHEAD
+; here esi = MAX_DIST(s)
+    sub     ecx,esi
+    ja      nodist
+    xor     ecx,ecx
+nodist:
+    mov     limit,ecx
+
+; prev = s->prev
+    mov     edx,[ebp+dep_prev]
+    mov     prev,edx
+
+;
+    mov     edx,dword ptr [ebp+dep_match_start]
+    mov     bp,scan_start
+    mov     eax,cur_match
+    mov     match_start,edx
+
+    mov     edx,window
+    mov     edi,edx
+    add     edi,best_len
+    mov     esi,prev
+    dec     edi
+; windowlen = window + best_len -1
+    mov     windowlen,edi
+
+    jmp     beginloop2
+    align   4
+
+; here, in the loop
+;       eax = ax = cur_match
+;       ecx = limit
+;        bx = scan_end
+;        bp = scan_start
+;       edi = windowlen (window + best_len -1)
+;       esi = prev
+
+
+;// here; chain_length <=16
+normalbeg0add16:
+    add     chain_length,16
+    jz      exitloop
+normalbeg0:
+    cmp     word ptr[edi+eax],bx
+    je      normalbeg2noroll
+rcontlabnoroll:
+; cur_match = prev[cur_match & wmask]
+    and     eax,7fffh
+    mov     ax,word ptr[esi+eax*2]
+; if cur_match > limit, go to exitloop
+    cmp     ecx,eax
+    jnb     exitloop
+; if --chain_length != 0, go to exitloop
+    dec     chain_length
+    jnz     normalbeg0
+    jmp     exitloop
+
+normalbeg2noroll:
+; if (scan_start==*(cur_match+window)) goto normalbeg2
+    cmp     bp,word ptr[edx+eax]
+    jne     rcontlabnoroll
+    jmp     normalbeg2
+
+contloop3:
+    mov     edi,windowlen
+
+; cur_match = prev[cur_match & wmask]
+    and     eax,7fffh
+    mov     ax,word ptr[esi+eax*2]
+; if cur_match > limit, go to exitloop
+    cmp     ecx,eax
+jnbexitloopshort1:
+    jnb     exitloop
+; if --chain_length != 0, go to exitloop
+
+
+; begin the main loop
+beginloop2:
+    sub     chain_length,16+1
+; if chain_length <=16, don't use the unrolled loop
+    jna     normalbeg0add16
+
+do16:
+    cmp     word ptr[edi+eax],bx
+    je      normalbeg2dc0
+
+maccn   MACRO   lab
+    and     eax,7fffh
+    mov     ax,word ptr[esi+eax*2]
+    cmp     ecx,eax
+    jnb     exitloop
+    cmp     word ptr[edi+eax],bx
+    je      lab
+    ENDM
+
+rcontloop0:
+    maccn   normalbeg2dc1
+
+rcontloop1:
+    maccn   normalbeg2dc2
+
+rcontloop2:
+    maccn   normalbeg2dc3
+
+rcontloop3:
+    maccn   normalbeg2dc4
+
+rcontloop4:
+    maccn   normalbeg2dc5
+
+rcontloop5:
+    maccn   normalbeg2dc6
+
+rcontloop6:
+    maccn   normalbeg2dc7
+
+rcontloop7:
+    maccn   normalbeg2dc8
+
+rcontloop8:
+    maccn   normalbeg2dc9
+
+rcontloop9:
+    maccn   normalbeg2dc10
+
+rcontloop10:
+    maccn   short normalbeg2dc11
+
+rcontloop11:
+    maccn   short normalbeg2dc12
+
+rcontloop12:
+    maccn   short normalbeg2dc13
+
+rcontloop13:
+    maccn   short normalbeg2dc14
+
+rcontloop14:
+    maccn   short normalbeg2dc15
+
+rcontloop15:
+    and     eax,7fffh
+    mov     ax,word ptr[esi+eax*2]
+    cmp     ecx,eax
+    jnb     exitloop
+
+    sub     chain_length,16
+    ja      do16
+    jmp     normalbeg0add16
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+normbeg MACRO   rcontlab,valsub
+; if we are here, we know that *(match+best_len-1) == scan_end
+    cmp     bp,word ptr[edx+eax]
+; if (match != scan_start) goto rcontlab
+    jne     rcontlab
+; calculate the good chain_length, and we'll compare scan and match string
+    add     chain_length,16-valsub
+    jmp     iseq
+    ENDM
+
+
+normalbeg2dc11:
+    normbeg rcontloop11,11
+
+normalbeg2dc12:
+    normbeg short rcontloop12,12
+
+normalbeg2dc13:
+    normbeg short rcontloop13,13
+
+normalbeg2dc14:
+    normbeg short rcontloop14,14
+
+normalbeg2dc15:
+    normbeg short rcontloop15,15
+
+normalbeg2dc10:
+    normbeg rcontloop10,10
+
+normalbeg2dc9:
+    normbeg rcontloop9,9
+
+normalbeg2dc8:
+    normbeg rcontloop8,8
+
+normalbeg2dc7:
+    normbeg rcontloop7,7
+
+normalbeg2dc6:
+    normbeg rcontloop6,6
+
+normalbeg2dc5:
+    normbeg rcontloop5,5
+
+normalbeg2dc4:
+    normbeg rcontloop4,4
+
+normalbeg2dc3:
+    normbeg rcontloop3,3
+
+normalbeg2dc2:
+    normbeg rcontloop2,2
+
+normalbeg2dc1:
+    normbeg rcontloop1,1
+
+normalbeg2dc0:
+    normbeg rcontloop0,0
+
+
+; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end
+
+normalbeg2:
+    mov     edi,window
+
+    cmp     bp,word ptr[edi+eax]
+    jne     contloop3                   ; if *(ushf*)match != scan_start, continue
+
+iseq:
+; if we are here, we know that *(match+best_len-1) == scan_end
+; and (match == scan_start)
+
+    mov     edi,edx
+    mov     esi,scan                    ; esi = scan
+    add     edi,eax                     ; edi = window + cur_match = match
+
+    mov     edx,[esi+3]                 ; compare manually dword at match+3
+    xor     edx,[edi+3]                 ; and scan +3
+
+    jz      begincompare                ; if equal, go to long compare
+
+; we will determine the unmatch byte and calculate len (in esi)
+    or      dl,dl
+    je      eq1rr
+    mov     esi,3
+    jmp     trfinval
+eq1rr:
+    or      dx,dx
+    je      eq1
+
+    mov     esi,4
+    jmp     trfinval
+eq1:
+    and     edx,0ffffffh
+    jz      eq11
+    mov     esi,5
+    jmp     trfinval
+eq11:
+    mov     esi,6
+    jmp     trfinval
+
+begincompare:
+    ; here we now scan and match begin same
+    add     edi,6
+    add     esi,6
+    mov     ecx,(MAX_MATCH-(2+4))/4     ; scan for at most MAX_MATCH bytes
+    repe    cmpsd                       ; loop until mismatch
+
+    je      trfin                       ; go to trfin if not unmatch
+; we determine the unmatch byte
+    sub     esi,4
+    mov     edx,[edi-4]
+    xor     edx,[esi]
+
+    or      dl,dl
+    jnz     trfin
+    inc     esi
+
+    or      dx,dx
+    jnz     trfin
+    inc     esi
+
+    and     edx,0ffffffh
+    jnz     trfin
+    inc     esi
+
+trfin:
+    sub     esi,scan          ; esi = len
+trfinval:
+; here we have finised compare, and esi contain len of equal string
+    cmp     esi,best_len        ; if len > best_len, go newbestlen
+    ja      short newbestlen
+; now we restore edx, ecx and esi, for the big loop
+    mov     esi,prev
+    mov     ecx,limit
+    mov     edx,window
+    jmp     contloop3
+
+newbestlen:
+    mov     best_len,esi        ; len become best_len
+
+    mov     match_start,eax     ; save new position as match_start
+    cmp     esi,nice_match      ; if best_len >= nice_match, exit
+    jae     exitloop
+    mov     ecx,scan
+    mov     edx,window          ; restore edx=window
+    add     ecx,esi
+    add     esi,edx
+
+    dec     esi
+    mov     windowlen,esi       ; windowlen = window + best_len-1
+    mov     bx,[ecx-1]          ; bx = *(scan+best_len-1) = scan_end
+
+; now we restore ecx and esi, for the big loop :
+    mov     esi,prev
+    mov     ecx,limit
+    jmp     contloop3
+
+exitloop:
+; exit : s->match_start=match_start
+    mov     ebx,match_start
+    mov     ebp,str_s
+    mov     ecx,best_len
+    mov     dword ptr [ebp+dep_match_start],ebx
+    mov     eax,dword ptr [ebp+dep_lookahead]
+    cmp     ecx,eax
+    ja      minexlo
+    mov     eax,ecx
+minexlo:
+; return min(best_len,s->lookahead)
+
+; restore stack and register ebx,esi,edi,ebp
+    add     esp,NbStackAdd
+
+    pop     ebx
+    pop     esi
+    pop     edi
+    pop     ebp
+    ret
+InfoAuthor:
+; please don't remove this string !
+; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary!
+    db     0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah
+
+
+
+IFDEF NOUNDERLINE
+longest_match_7fff   endp
+ELSE
+_longest_match_7fff  endp
+ENDIF
+
+
+IFDEF NOUNDERLINE
+cpudetect32     proc near
+ELSE
+_cpudetect32    proc near
+ENDIF
+
+    push    ebx
+
+    pushfd                  ; push original EFLAGS
+    pop     eax             ; get original EFLAGS
+    mov     ecx, eax        ; save original EFLAGS
+    xor     eax, 40000h     ; flip AC bit in EFLAGS
+    push    eax             ; save new EFLAGS value on stack
+    popfd                   ; replace current EFLAGS value
+    pushfd                  ; get new EFLAGS
+    pop     eax             ; store new EFLAGS in EAX
+    xor     eax, ecx        ; cant toggle AC bit, processor=80386
+    jz      end_cpu_is_386  ; jump if 80386 processor
+    push    ecx
+    popfd                   ; restore AC bit in EFLAGS first
+
+    pushfd
+    pushfd
+    pop     ecx
+
+    mov     eax, ecx        ; get original EFLAGS
+    xor     eax, 200000h    ; flip ID bit in EFLAGS
+    push    eax             ; save new EFLAGS value on stack
+    popfd                   ; replace current EFLAGS value
+    pushfd                  ; get new EFLAGS
+    pop     eax             ; store new EFLAGS in EAX
+    popfd                   ; restore original EFLAGS
+    xor     eax, ecx        ; cant toggle ID bit,
+    je      is_old_486      ; processor=old
+
+    mov     eax,1
+    db      0fh,0a2h        ;CPUID
+
+exitcpudetect:
+    pop ebx
+    ret
+
+end_cpu_is_386:
+    mov     eax,0300h
+    jmp     exitcpudetect
+
+is_old_486:
+    mov     eax,0400h
+    jmp     exitcpudetect
+
+IFDEF NOUNDERLINE
+cpudetect32     endp
+ELSE
+_cpudetect32    endp
+ENDIF
+ENDIF
+
+MAX_MATCH       equ     258
+MIN_MATCH       equ     3
+MIN_LOOKAHEAD   equ     (MAX_MATCH + MIN_MATCH + 1)
+MAX_MATCH_8_     equ     ((MAX_MATCH + 7) AND 0FFF0h)
+
+
+;;; stack frame offsets
+
+chainlenwmask   equ  esp + 0    ; high word: current chain len
+                    ; low word: s->wmask
+window      equ  esp + 4    ; local copy of s->window
+windowbestlen   equ  esp + 8    ; s->window + bestlen
+scanstart   equ  esp + 16   ; first two bytes of string
+scanend     equ  esp + 12   ; last two bytes of string
+scanalign   equ  esp + 20   ; dword-misalignment of string
+nicematch   equ  esp + 24   ; a good enough match size
+bestlen     equ  esp + 28   ; size of best match so far
+scan        equ  esp + 32   ; ptr to string wanting match
+
+LocalVarsSize   equ 36
+;   saved ebx   byte esp + 36
+;   saved edi   byte esp + 40
+;   saved esi   byte esp + 44
+;   saved ebp   byte esp + 48
+;   return address  byte esp + 52
+deflatestate    equ  esp + 56   ; the function arguments
+curmatch    equ  esp + 60
+
+;;; Offsets for fields in the deflate_state structure. These numbers
+;;; are calculated from the definition of deflate_state, with the
+;;; assumption that the compiler will dword-align the fields. (Thus,
+;;; changing the definition of deflate_state could easily cause this
+;;; program to crash horribly, without so much as a warning at
+;;; compile time. Sigh.)
+
+dsWSize     equ 36+zlib1222add
+dsWMask     equ 44+zlib1222add
+dsWindow    equ 48+zlib1222add
+dsPrev      equ 56+zlib1222add
+dsMatchLen  equ 88+zlib1222add
+dsPrevMatch equ 92+zlib1222add
+dsStrStart  equ 100+zlib1222add
+dsMatchStart    equ 104+zlib1222add
+dsLookahead equ 108+zlib1222add
+dsPrevLen   equ 112+zlib1222add
+dsMaxChainLen   equ 116+zlib1222add
+dsGoodMatch equ 132+zlib1222add
+dsNiceMatch equ 136+zlib1222add
+
+
+;;; match.asm -- Pentium-Pro-optimized version of longest_match()
+;;; Written for zlib 1.1.2
+;;; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
+;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html
+;;;
+;;; This is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License.
+
+;GLOBAL _longest_match, _match_init
+
+
+;SECTION    .text
+
+;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
+
+;_longest_match:
+IFDEF NOOLDPENTIUMCODE
+    IFDEF NOUNDERLINE
+    longest_match       proc near
+    ELSE
+    _longest_match      proc near
+    ENDIF
+ELSE
+    IFDEF NOUNDERLINE
+    longest_match_686   proc near
+    ELSE
+    _longest_match_686  proc near
+    ENDIF
+ENDIF
+
+;;; Save registers that the compiler may be using, and adjust esp to
+;;; make room for our stack frame.
+
+        push    ebp
+        push    edi
+        push    esi
+        push    ebx
+        sub esp, LocalVarsSize
+
+;;; Retrieve the function arguments. ecx will hold cur_match
+;;; throughout the entire function. edx will hold the pointer to the
+;;; deflate_state structure during the function's setup (before
+;;; entering the main loop.
+
+        mov edx, [deflatestate]
+        mov ecx, [curmatch]
+
+;;; uInt wmask = s->w_mask;
+;;; unsigned chain_length = s->max_chain_length;
+;;; if (s->prev_length >= s->good_match) {
+;;;     chain_length >>= 2;
+;;; }
+
+        mov eax, [edx + dsPrevLen]
+        mov ebx, [edx + dsGoodMatch]
+        cmp eax, ebx
+        mov eax, [edx + dsWMask]
+        mov ebx, [edx + dsMaxChainLen]
+        jl  LastMatchGood
+        shr ebx, 2
+LastMatchGood:
+
+;;; chainlen is decremented once beforehand so that the function can
+;;; use the sign flag instead of the zero flag for the exit test.
+;;; It is then shifted into the high word, to make room for the wmask
+;;; value, which it will always accompany.
+
+        dec ebx
+        shl ebx, 16
+        or  ebx, eax
+        mov [chainlenwmask], ebx
+
+;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+        mov eax, [edx + dsNiceMatch]
+        mov ebx, [edx + dsLookahead]
+        cmp ebx, eax
+        jl  LookaheadLess
+        mov ebx, eax
+LookaheadLess:  mov [nicematch], ebx
+
+;;; register Bytef *scan = s->window + s->strstart;
+
+        mov esi, [edx + dsWindow]
+        mov [window], esi
+        mov ebp, [edx + dsStrStart]
+        lea edi, [esi + ebp]
+        mov [scan], edi
+
+;;; Determine how many bytes the scan ptr is off from being
+;;; dword-aligned.
+
+        mov eax, edi
+        neg eax
+        and eax, 3
+        mov [scanalign], eax
+
+;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;
+
+        mov eax, [edx + dsWSize]
+        sub eax, MIN_LOOKAHEAD
+        sub ebp, eax
+        jg  LimitPositive
+        xor ebp, ebp
+LimitPositive:
+
+;;; int best_len = s->prev_length;
+
+        mov eax, [edx + dsPrevLen]
+        mov [bestlen], eax
+
+;;; Store the sum of s->window + best_len in esi locally, and in esi.
+
+        add esi, eax
+        mov [windowbestlen], esi
+
+;;; register ush scan_start = *(ushf*)scan;
+;;; register ush scan_end   = *(ushf*)(scan+best_len-1);
+;;; Posf *prev = s->prev;
+
+        movzx   ebx, word ptr [edi]
+        mov [scanstart], ebx
+        movzx   ebx, word ptr [edi + eax - 1]
+        mov [scanend], ebx
+        mov edi, [edx + dsPrev]
+
+;;; Jump into the main loop.
+
+        mov edx, [chainlenwmask]
+        jmp short LoopEntry
+
+align 4
+
+;;; do {
+;;;     match = s->window + cur_match;
+;;;     if (*(ushf*)(match+best_len-1) != scan_end ||
+;;;         *(ushf*)match != scan_start) continue;
+;;;     [...]
+;;; } while ((cur_match = prev[cur_match & wmask]) > limit
+;;;          && --chain_length != 0);
+;;;
+;;; Here is the inner loop of the function. The function will spend the
+;;; majority of its time in this loop, and majority of that time will
+;;; be spent in the first ten instructions.
+;;;
+;;; Within this loop:
+;;; ebx = scanend
+;;; ecx = curmatch
+;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
+;;; esi = windowbestlen - i.e., (window + bestlen)
+;;; edi = prev
+;;; ebp = limit
+
+LookupLoop:
+        and ecx, edx
+        movzx   ecx, word ptr [edi + ecx*2]
+        cmp ecx, ebp
+        jbe LeaveNow
+        sub edx, 00010000h
+        js  LeaveNow
+LoopEntry:  movzx   eax, word ptr [esi + ecx - 1]
+        cmp eax, ebx
+        jnz LookupLoop
+        mov eax, [window]
+        movzx   eax, word ptr [eax + ecx]
+        cmp eax, [scanstart]
+        jnz LookupLoop
+
+;;; Store the current value of chainlen.
+
+        mov [chainlenwmask], edx
+
+;;; Point edi to the string under scrutiny, and esi to the string we
+;;; are hoping to match it up with. In actuality, esi and edi are
+;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
+;;; initialized to -(MAX_MATCH_8 - scanalign).
+
+        mov esi, [window]
+        mov edi, [scan]
+        add esi, ecx
+        mov eax, [scanalign]
+        mov edx, 0fffffef8h; -(MAX_MATCH_8)
+        lea edi, [edi + eax + 0108h] ;MAX_MATCH_8]
+        lea esi, [esi + eax + 0108h] ;MAX_MATCH_8]
+
+;;; Test the strings for equality, 8 bytes at a time. At the end,
+;;; adjust edx so that it is offset to the exact byte that mismatched.
+;;;
+;;; We already know at this point that the first three bytes of the
+;;; strings match each other, and they can be safely passed over before
+;;; starting the compare loop. So what this code does is skip over 0-3
+;;; bytes, as much as necessary in order to dword-align the edi
+;;; pointer. (esi will still be misaligned three times out of four.)
+;;;
+;;; It should be confessed that this loop usually does not represent
+;;; much of the total running time. Replacing it with a more
+;;; straightforward "rep cmpsb" would not drastically degrade
+;;; performance.
+
+LoopCmps:
+        mov eax, [esi + edx]
+        xor eax, [edi + edx]
+        jnz LeaveLoopCmps
+        mov eax, [esi + edx + 4]
+        xor eax, [edi + edx + 4]
+        jnz LeaveLoopCmps4
+        add edx, 8
+        jnz LoopCmps
+        jmp short LenMaximum
+LeaveLoopCmps4: add edx, 4
+LeaveLoopCmps:  test    eax, 0000FFFFh
+        jnz LenLower
+        add edx,  2
+        shr eax, 16
+LenLower:   sub al, 1
+        adc edx, 0
+
+;;; Calculate the length of the match. If it is longer than MAX_MATCH,
+;;; then automatically accept it as the best possible match and leave.
+
+        lea eax, [edi + edx]
+        mov edi, [scan]
+        sub eax, edi
+        cmp eax, MAX_MATCH
+        jge LenMaximum
+
+;;; If the length of the match is not longer than the best match we
+;;; have so far, then forget it and return to the lookup loop.
+
+        mov edx, [deflatestate]
+        mov ebx, [bestlen]
+        cmp eax, ebx
+        jg  LongerMatch
+        mov esi, [windowbestlen]
+        mov edi, [edx + dsPrev]
+        mov ebx, [scanend]
+        mov edx, [chainlenwmask]
+        jmp LookupLoop
+
+;;;         s->match_start = cur_match;
+;;;         best_len = len;
+;;;         if (len >= nice_match) break;
+;;;         scan_end = *(ushf*)(scan+best_len-1);
+
+LongerMatch:    mov ebx, [nicematch]
+        mov [bestlen], eax
+        mov [edx + dsMatchStart], ecx
+        cmp eax, ebx
+        jge LeaveNow
+        mov esi, [window]
+        add esi, eax
+        mov [windowbestlen], esi
+        movzx   ebx, word ptr [edi + eax - 1]
+        mov edi, [edx + dsPrev]
+        mov [scanend], ebx
+        mov edx, [chainlenwmask]
+        jmp LookupLoop
+
+;;; Accept the current string, with the maximum possible length.
+
+LenMaximum: mov edx, [deflatestate]
+        mov dword ptr [bestlen], MAX_MATCH
+        mov [edx + dsMatchStart], ecx
+
+;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+;;; return s->lookahead;
+
+LeaveNow:
+        mov edx, [deflatestate]
+        mov ebx, [bestlen]
+        mov eax, [edx + dsLookahead]
+        cmp ebx, eax
+        jg  LookaheadRet
+        mov eax, ebx
+LookaheadRet:
+
+;;; Restore the stack and return from whence we came.
+
+        add esp, LocalVarsSize
+        pop ebx
+        pop esi
+        pop edi
+        pop ebp
+
+        ret
+; please don't remove this string !
+; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary!
+    db     0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah
+
+
+IFDEF NOOLDPENTIUMCODE
+    IFDEF NOUNDERLINE
+    longest_match       endp
+    ELSE
+    _longest_match      endp
+    ENDIF
+
+    IFDEF NOUNDERLINE
+    match_init      proc near
+                    ret
+    match_init      endp
+    ELSE
+    _match_init     proc near
+                    ret
+    _match_init     endp
+    ENDIF    
+ELSE
+    IFDEF NOUNDERLINE
+    longest_match_686   endp
+    ELSE
+    _longest_match_686  endp
+    ENDIF
+ENDIF
+
+_TEXT   ends
+end
Index: /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/gvmat32c.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/gvmat32c.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/gvmat32c.c	(revision 9)
@@ -0,0 +1,62 @@
+/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86
+ * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
+ * File written by Gilles Vollant, by modifiying the longest_match
+ *  from Jean-loup Gailly in deflate.c
+ *  it prepare all parameters and call the assembly longest_match_gvasm
+ *  longest_match execute standard C code is wmask != 0x7fff
+ *     (assembly code is faster with a fixed wmask)
+ *
+ * Read comment at beginning of gvmat32.asm for more information
+ */
+
+#if defined(ASMV) && (!defined(NOOLDPENTIUMCODE))
+#include "deflate.h"
+
+/* if your C compiler don't add underline before function name,
+        define ADD_UNDERLINE_ASMFUNC */
+#ifdef ADD_UNDERLINE_ASMFUNC
+#define longest_match_7fff _longest_match_7fff
+#define longest_match_686  _longest_match_686
+#define cpudetect32        _cpudetect32
+#endif
+
+
+unsigned long cpudetect32();
+
+uInt longest_match_c(
+    deflate_state *s,
+    IPos cur_match);                             /* current match */
+
+
+uInt longest_match_7fff(
+    deflate_state *s,
+    IPos cur_match);                             /* current match */
+
+uInt longest_match_686(
+    deflate_state *s,
+    IPos cur_match);                             /* current match */
+
+
+static uInt iIsPPro=2;
+
+void match_init ()
+{
+    iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;
+}
+
+uInt longest_match(
+    deflate_state *s,
+    IPos cur_match)                             /* current match */
+{
+    if (iIsPPro!=0)
+        return longest_match_686(s,cur_match);
+
+    if (s->w_mask != 0x7fff)
+        return longest_match_686(s,cur_match);
+
+    /* now ((s->w_mask == 0x7fff) && (iIsPPro==0)) */
+        return longest_match_7fff(s,cur_match);
+}
+
+
+#endif /* defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) */
Index: /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/inffas32.asm
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/inffas32.asm	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/inffas32.asm	(revision 9)
@@ -0,0 +1,1083 @@
+;/* inffas32.asm is a hand tuned assembler version of inffast.c -- fast decoding
+; *
+; * inffas32.asm is derivated from inffas86.c, with translation of assembly code
+; *
+; * Copyright (C) 1995-2003 Mark Adler
+; * For conditions of distribution and use, see copyright notice in zlib.h
+; *
+; * Copyright (C) 2003 Chris Anderson <christop@charm.net>
+; * Please use the copyright conditions above.
+; *
+; * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from
+; * the gcc -S output of zlib-1.2.0/inffast.c.  Zlib-1.2.0 is in beta release at
+; * the moment.  I have successfully compiled and tested this code with gcc2.96,
+; * gcc3.2, icc5.0, msvc6.0.  It is very close to the speed of inffast.S
+; * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX
+; * enabled.  I will attempt to merge the MMX code into this version.  Newer
+; * versions of this and inffast.S can be found at
+; * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/
+; * 
+; * 2005 : modification by Gilles Vollant
+; */
+; For Visual C++ 4.x and higher and ML 6.x and higher
+;   ml.exe is in directory \MASM611C of Win95 DDK
+;   ml.exe is also distributed in http://www.masm32.com/masmdl.htm
+;    and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/
+;
+;
+;   compile with command line option
+;   ml  /coff /Zi /c /Flinffas32.lst inffas32.asm
+
+;   if you define NO_GZIP (see inflate.h), compile with
+;   ml  /coff /Zi /c /Flinffas32.lst /DNO_GUNZIP inffas32.asm
+
+
+; zlib122sup is 0 fort zlib 1.2.2.1 and lower
+; zlib122sup is 8 fort zlib 1.2.2.2 and more (with addition of dmax and head 
+;        in inflate_state in inflate.h)
+zlib1222sup      equ    8
+
+
+IFDEF GUNZIP
+  INFLATE_MODE_TYPE    equ 11
+  INFLATE_MODE_BAD     equ 26
+ELSE
+  IFNDEF NO_GUNZIP
+    INFLATE_MODE_TYPE    equ 11
+    INFLATE_MODE_BAD     equ 26
+  ELSE
+    INFLATE_MODE_TYPE    equ 3
+    INFLATE_MODE_BAD     equ 17
+  ENDIF
+ENDIF
+
+
+; 75 "inffast.S"
+;FILE "inffast.S"
+
+;;;GLOBAL _inflate_fast
+
+;;;SECTION .text
+
+
+
+	.586p
+	.mmx
+
+	name	inflate_fast_x86
+	.MODEL	FLAT
+
+_DATA			segment
+inflate_fast_use_mmx:
+	dd	1
+
+
+_TEXT			segment
+PUBLIC _inflate_fast
+
+ALIGN 4
+_inflate_fast:
+	jmp inflate_fast_entry
+
+
+
+ALIGN 4
+	db	'Fast decoding Code from Chris Anderson'
+	db	0
+
+ALIGN 4
+invalid_literal_length_code_msg:
+	db	'invalid literal/length code'
+	db	0
+
+ALIGN 4
+invalid_distance_code_msg:
+	db	'invalid distance code'
+	db	0
+
+ALIGN 4
+invalid_distance_too_far_msg:
+	db	'invalid distance too far back'
+	db	0
+
+
+ALIGN 4
+inflate_fast_mask:
+dd	0
+dd	1
+dd	3
+dd	7
+dd	15
+dd	31
+dd	63
+dd	127
+dd	255
+dd	511
+dd	1023
+dd	2047
+dd	4095
+dd	8191
+dd	16383
+dd	32767
+dd	65535
+dd	131071
+dd	262143
+dd	524287
+dd	1048575
+dd	2097151
+dd	4194303
+dd	8388607
+dd	16777215
+dd	33554431
+dd	67108863
+dd	134217727
+dd	268435455
+dd	536870911
+dd	1073741823
+dd	2147483647
+dd	4294967295
+
+
+mode_state	 equ	0	;/* state->mode	*/
+wsize_state	 equ	(32+zlib1222sup)	;/* state->wsize */
+write_state	 equ	(36+4+zlib1222sup)	;/* state->write */
+window_state	 equ	(40+4+zlib1222sup)	;/* state->window */
+hold_state	 equ	(44+4+zlib1222sup)	;/* state->hold	*/
+bits_state	 equ	(48+4+zlib1222sup)	;/* state->bits	*/
+lencode_state	 equ	(64+4+zlib1222sup)	;/* state->lencode */
+distcode_state	 equ	(68+4+zlib1222sup)	;/* state->distcode */
+lenbits_state	 equ	(72+4+zlib1222sup)	;/* state->lenbits */
+distbits_state	 equ	(76+4+zlib1222sup)	;/* state->distbits */
+
+
+;;SECTION .text
+; 205 "inffast.S"
+;GLOBAL	inflate_fast_use_mmx
+
+;SECTION .data
+
+
+; GLOBAL inflate_fast_use_mmx:object
+;.size inflate_fast_use_mmx, 4
+; 226 "inffast.S"
+;SECTION .text
+
+ALIGN 4
+inflate_fast_entry:
+	push  edi
+	push  esi
+	push  ebp
+	push  ebx
+	pushfd
+	sub  esp,64
+	cld
+
+
+
+
+	mov  esi, [esp+88]
+	mov  edi, [esi+28]
+
+
+
+
+
+
+
+	mov  edx, [esi+4]
+	mov  eax, [esi+0]
+
+	add  edx,eax
+	sub  edx,11
+
+	mov  [esp+44],eax
+	mov  [esp+20],edx
+
+	mov  ebp, [esp+92]
+	mov  ecx, [esi+16]
+	mov  ebx, [esi+12]
+
+	sub  ebp,ecx
+	neg  ebp
+	add  ebp,ebx
+
+	sub  ecx,257
+	add  ecx,ebx
+
+	mov  [esp+60],ebx
+	mov  [esp+40],ebp
+	mov  [esp+16],ecx
+; 285 "inffast.S"
+	mov  eax, [edi+lencode_state]
+	mov  ecx, [edi+distcode_state]
+
+	mov  [esp+8],eax
+	mov  [esp+12],ecx
+
+	mov  eax,1
+	mov  ecx, [edi+lenbits_state]
+	shl  eax,cl
+	dec  eax
+	mov  [esp+0],eax
+
+	mov  eax,1
+	mov  ecx, [edi+distbits_state]
+	shl  eax,cl
+	dec  eax
+	mov  [esp+4],eax
+
+	mov  eax, [edi+wsize_state]
+	mov  ecx, [edi+write_state]
+	mov  edx, [edi+window_state]
+
+	mov  [esp+52],eax
+	mov  [esp+48],ecx
+	mov  [esp+56],edx
+
+	mov  ebp, [edi+hold_state]
+	mov  ebx, [edi+bits_state]
+; 321 "inffast.S"
+	mov  esi, [esp+44]
+	mov  ecx, [esp+20]
+	cmp  ecx,esi
+	ja   L_align_long
+
+	add  ecx,11
+	sub  ecx,esi
+	mov  eax,12
+	sub  eax,ecx
+	lea  edi, [esp+28]
+	rep movsb
+	mov  ecx,eax
+	xor  eax,eax
+	rep stosb
+	lea  esi, [esp+28]
+	mov  [esp+20],esi
+	jmp  L_is_aligned
+
+
+L_align_long:
+	test  esi,3
+	jz   L_is_aligned
+	xor  eax,eax
+	mov  al, [esi]
+	inc  esi
+	mov  ecx,ebx
+	add  ebx,8
+	shl  eax,cl
+	or  ebp,eax
+	jmp L_align_long
+
+L_is_aligned:
+	mov  edi, [esp+60]
+; 366 "inffast.S"
+L_check_mmx:
+	cmp  dword ptr [inflate_fast_use_mmx],2
+	je   L_init_mmx
+	ja   L_do_loop
+
+	push  eax
+	push  ebx
+	push  ecx
+	push  edx
+	pushfd
+	mov  eax, [esp]
+	xor  dword ptr [esp],0200000h
+
+
+
+
+	popfd
+	pushfd
+	pop  edx
+	xor  edx,eax
+	jz   L_dont_use_mmx
+	xor  eax,eax
+	cpuid
+	cmp  ebx,0756e6547h
+	jne  L_dont_use_mmx
+	cmp  ecx,06c65746eh
+	jne  L_dont_use_mmx
+	cmp  edx,049656e69h
+	jne  L_dont_use_mmx
+	mov  eax,1
+	cpuid
+	shr  eax,8
+	and  eax,15
+	cmp  eax,6
+	jne  L_dont_use_mmx
+	test  edx,0800000h
+	jnz  L_use_mmx
+	jmp  L_dont_use_mmx
+L_use_mmx:
+	mov  dword ptr [inflate_fast_use_mmx],2
+	jmp  L_check_mmx_pop
+L_dont_use_mmx:
+	mov  dword ptr [inflate_fast_use_mmx],3
+L_check_mmx_pop:
+	pop  edx
+	pop  ecx
+	pop  ebx
+	pop  eax
+	jmp  L_check_mmx
+; 426 "inffast.S"
+ALIGN 4
+L_do_loop:
+; 437 "inffast.S"
+	cmp  bl,15
+	ja   L_get_length_code
+
+	xor  eax,eax
+	lodsw
+	mov  cl,bl
+	add  bl,16
+	shl  eax,cl
+	or  ebp,eax
+
+L_get_length_code:
+	mov  edx, [esp+0]
+	mov  ecx, [esp+8]
+	and  edx,ebp
+	mov  eax, [ecx+edx*4]
+
+L_dolen:
+
+
+
+
+
+
+	mov  cl,ah
+	sub  bl,ah
+	shr  ebp,cl
+
+
+
+
+
+
+	test  al,al
+	jnz   L_test_for_length_base
+
+	shr  eax,16
+	stosb
+
+L_while_test:
+
+
+	cmp  [esp+16],edi
+	jbe  L_break_loop
+
+	cmp  [esp+20],esi
+	ja   L_do_loop
+	jmp  L_break_loop
+
+L_test_for_length_base:
+; 502 "inffast.S"
+	mov  edx,eax
+	shr  edx,16
+	mov  cl,al
+
+	test  al,16
+	jz   L_test_for_second_level_length
+	and  cl,15
+	jz   L_save_len
+	cmp  bl,cl
+	jae  L_add_bits_to_len
+
+	mov  ch,cl
+	xor  eax,eax
+	lodsw
+	mov  cl,bl
+	add  bl,16
+	shl  eax,cl
+	or  ebp,eax
+	mov  cl,ch
+
+L_add_bits_to_len:
+	mov  eax,1
+	shl  eax,cl
+	dec  eax
+	sub  bl,cl
+	and  eax,ebp
+	shr  ebp,cl
+	add  edx,eax
+
+L_save_len:
+	mov  [esp+24],edx
+
+
+L_decode_distance:
+; 549 "inffast.S"
+	cmp  bl,15
+	ja   L_get_distance_code
+
+	xor  eax,eax
+	lodsw
+	mov  cl,bl
+	add  bl,16
+	shl  eax,cl
+	or  ebp,eax
+
+L_get_distance_code:
+	mov  edx, [esp+4]
+	mov  ecx, [esp+12]
+	and  edx,ebp
+	mov  eax, [ecx+edx*4]
+
+
+L_dodist:
+	mov  edx,eax
+	shr  edx,16
+	mov  cl,ah
+	sub  bl,ah
+	shr  ebp,cl
+; 584 "inffast.S"
+	mov  cl,al
+
+	test  al,16
+	jz  L_test_for_second_level_dist
+	and  cl,15
+	jz  L_check_dist_one
+	cmp  bl,cl
+	jae  L_add_bits_to_dist
+
+	mov  ch,cl
+	xor  eax,eax
+	lodsw
+	mov  cl,bl
+	add  bl,16
+	shl  eax,cl
+	or  ebp,eax
+	mov  cl,ch
+
+L_add_bits_to_dist:
+	mov  eax,1
+	shl  eax,cl
+	dec  eax
+	sub  bl,cl
+	and  eax,ebp
+	shr  ebp,cl
+	add  edx,eax
+	jmp  L_check_window
+
+L_check_window:
+; 625 "inffast.S"
+	mov  [esp+44],esi
+	mov  eax,edi
+	sub  eax, [esp+40]
+
+	cmp  eax,edx
+	jb   L_clip_window
+
+	mov  ecx, [esp+24]
+	mov  esi,edi
+	sub  esi,edx
+
+	sub  ecx,3
+	mov  al, [esi]
+	mov  [edi],al
+	mov  al, [esi+1]
+	mov  dl, [esi+2]
+	add  esi,3
+	mov  [edi+1],al
+	mov  [edi+2],dl
+	add  edi,3
+	rep movsb
+
+	mov  esi, [esp+44]
+	jmp  L_while_test
+
+ALIGN 4
+L_check_dist_one:
+	cmp  edx,1
+	jne  L_check_window
+	cmp  [esp+40],edi
+	je  L_check_window
+
+	dec  edi
+	mov  ecx, [esp+24]
+	mov  al, [edi]
+	sub  ecx,3
+
+	mov  [edi+1],al
+	mov  [edi+2],al
+	mov  [edi+3],al
+	add  edi,4
+	rep stosb
+
+	jmp  L_while_test
+
+ALIGN 4
+L_test_for_second_level_length:
+
+
+
+
+	test  al,64
+	jnz   L_test_for_end_of_block
+
+	mov  eax,1
+	shl  eax,cl
+	dec  eax
+	and  eax,ebp
+	add  eax,edx
+	mov  edx, [esp+8]
+	mov  eax, [edx+eax*4]
+	jmp  L_dolen
+
+ALIGN 4
+L_test_for_second_level_dist:
+
+
+
+
+	test  al,64
+	jnz   L_invalid_distance_code
+
+	mov  eax,1
+	shl  eax,cl
+	dec  eax
+	and  eax,ebp
+	add  eax,edx
+	mov  edx, [esp+12]
+	mov  eax, [edx+eax*4]
+	jmp  L_dodist
+
+ALIGN 4
+L_clip_window:
+; 721 "inffast.S"
+	mov  ecx,eax
+	mov  eax, [esp+52]
+	neg  ecx
+	mov  esi, [esp+56]
+
+	cmp  eax,edx
+	jb   L_invalid_distance_too_far
+
+	add  ecx,edx
+	cmp  dword ptr [esp+48],0
+	jne  L_wrap_around_window
+
+	sub  eax,ecx
+	add  esi,eax
+; 749 "inffast.S"
+	mov  eax, [esp+24]
+	cmp  eax,ecx
+	jbe  L_do_copy1
+
+	sub  eax,ecx
+	rep movsb
+	mov  esi,edi
+	sub  esi,edx
+	jmp  L_do_copy1
+
+	cmp  eax,ecx
+	jbe  L_do_copy1
+
+	sub  eax,ecx
+	rep movsb
+	mov  esi,edi
+	sub  esi,edx
+	jmp  L_do_copy1
+
+L_wrap_around_window:
+; 793 "inffast.S"
+	mov  eax, [esp+48]
+	cmp  ecx,eax
+	jbe  L_contiguous_in_window
+
+	add  esi, [esp+52]
+	add  esi,eax
+	sub  esi,ecx
+	sub  ecx,eax
+
+
+	mov  eax, [esp+24]
+	cmp  eax,ecx
+	jbe  L_do_copy1
+
+	sub  eax,ecx
+	rep movsb
+	mov  esi, [esp+56]
+	mov  ecx, [esp+48]
+	cmp  eax,ecx
+	jbe  L_do_copy1
+
+	sub  eax,ecx
+	rep movsb
+	mov  esi,edi
+	sub  esi,edx
+	jmp  L_do_copy1
+
+L_contiguous_in_window:
+; 836 "inffast.S"
+	add  esi,eax
+	sub  esi,ecx
+
+
+	mov  eax, [esp+24]
+	cmp  eax,ecx
+	jbe  L_do_copy1
+
+	sub  eax,ecx
+	rep movsb
+	mov  esi,edi
+	sub  esi,edx
+
+L_do_copy1:
+; 862 "inffast.S"
+	mov  ecx,eax
+	rep movsb
+
+	mov  esi, [esp+44]
+	jmp  L_while_test
+; 878 "inffast.S"
+ALIGN 4
+L_init_mmx:
+	emms
+
+
+
+
+
+	movd mm0,ebp
+	mov  ebp,ebx
+; 896 "inffast.S"
+	movd mm4,[esp+0]
+	movq mm3,mm4
+	movd mm5,[esp+4]
+	movq mm2,mm5
+	pxor mm1,mm1
+	mov  ebx, [esp+8]
+	jmp  L_do_loop_mmx
+
+ALIGN 4
+L_do_loop_mmx:
+	psrlq mm0,mm1
+
+	cmp  ebp,32
+	ja  L_get_length_code_mmx
+
+	movd mm6,ebp
+	movd mm7,[esi]
+	add  esi,4
+	psllq mm7,mm6
+	add  ebp,32
+	por mm0,mm7
+
+L_get_length_code_mmx:
+	pand mm4,mm0
+	movd eax,mm4
+	movq mm4,mm3
+	mov  eax, [ebx+eax*4]
+
+L_dolen_mmx:
+	movzx  ecx,ah
+	movd mm1,ecx
+	sub  ebp,ecx
+
+	test  al,al
+	jnz L_test_for_length_base_mmx
+
+	shr  eax,16
+	stosb
+
+L_while_test_mmx:
+
+
+	cmp  [esp+16],edi
+	jbe L_break_loop
+
+	cmp  [esp+20],esi
+	ja L_do_loop_mmx
+	jmp L_break_loop
+
+L_test_for_length_base_mmx:
+
+	mov  edx,eax
+	shr  edx,16
+
+	test  al,16
+	jz  L_test_for_second_level_length_mmx
+	and  eax,15
+	jz L_decode_distance_mmx
+
+	psrlq mm0,mm1
+	movd mm1,eax
+	movd ecx,mm0
+	sub  ebp,eax
+	and  ecx, [inflate_fast_mask+eax*4]
+	add  edx,ecx
+
+L_decode_distance_mmx:
+	psrlq mm0,mm1
+
+	cmp  ebp,32
+	ja L_get_dist_code_mmx
+
+	movd mm6,ebp
+	movd mm7,[esi]
+	add  esi,4
+	psllq mm7,mm6
+	add  ebp,32
+	por mm0,mm7
+
+L_get_dist_code_mmx:
+	mov  ebx, [esp+12]
+	pand mm5,mm0
+	movd eax,mm5
+	movq mm5,mm2
+	mov  eax, [ebx+eax*4]
+
+L_dodist_mmx:
+
+	movzx  ecx,ah
+	mov  ebx,eax
+	shr  ebx,16
+	sub  ebp,ecx
+	movd mm1,ecx
+
+	test  al,16
+	jz L_test_for_second_level_dist_mmx
+	and  eax,15
+	jz L_check_dist_one_mmx
+
+L_add_bits_to_dist_mmx:
+	psrlq mm0,mm1
+	movd mm1,eax
+	movd ecx,mm0
+	sub  ebp,eax
+	and  ecx, [inflate_fast_mask+eax*4]
+	add  ebx,ecx
+
+L_check_window_mmx:
+	mov  [esp+44],esi
+	mov  eax,edi
+	sub  eax, [esp+40]
+
+	cmp  eax,ebx
+	jb L_clip_window_mmx
+
+	mov  ecx,edx
+	mov  esi,edi
+	sub  esi,ebx
+
+	sub  ecx,3
+	mov  al, [esi]
+	mov  [edi],al
+	mov  al, [esi+1]
+	mov  dl, [esi+2]
+	add  esi,3
+	mov  [edi+1],al
+	mov  [edi+2],dl
+	add  edi,3
+	rep movsb
+
+	mov  esi, [esp+44]
+	mov  ebx, [esp+8]
+	jmp  L_while_test_mmx
+
+ALIGN 4
+L_check_dist_one_mmx:
+	cmp  ebx,1
+	jne  L_check_window_mmx
+	cmp  [esp+40],edi
+	je   L_check_window_mmx
+
+	dec  edi
+	mov  ecx,edx
+	mov  al, [edi]
+	sub  ecx,3
+
+	mov  [edi+1],al
+	mov  [edi+2],al
+	mov  [edi+3],al
+	add  edi,4
+	rep stosb
+
+	mov  ebx, [esp+8]
+	jmp  L_while_test_mmx
+
+ALIGN 4
+L_test_for_second_level_length_mmx:
+	test  al,64
+	jnz L_test_for_end_of_block
+
+	and  eax,15
+	psrlq mm0,mm1
+	movd ecx,mm0
+	and  ecx, [inflate_fast_mask+eax*4]
+	add  ecx,edx
+	mov  eax, [ebx+ecx*4]
+	jmp L_dolen_mmx
+
+ALIGN 4
+L_test_for_second_level_dist_mmx:
+	test  al,64
+	jnz L_invalid_distance_code
+
+	and  eax,15
+	psrlq mm0,mm1
+	movd ecx,mm0
+	and  ecx, [inflate_fast_mask+eax*4]
+	mov  eax, [esp+12]
+	add  ecx,ebx
+	mov  eax, [eax+ecx*4]
+	jmp  L_dodist_mmx
+
+ALIGN 4
+L_clip_window_mmx:
+
+	mov  ecx,eax
+	mov  eax, [esp+52]
+	neg  ecx
+	mov  esi, [esp+56]
+
+	cmp  eax,ebx
+	jb  L_invalid_distance_too_far
+
+	add  ecx,ebx
+	cmp  dword ptr [esp+48],0
+	jne  L_wrap_around_window_mmx
+
+	sub  eax,ecx
+	add  esi,eax
+
+	cmp  edx,ecx
+	jbe  L_do_copy1_mmx
+
+	sub  edx,ecx
+	rep movsb
+	mov  esi,edi
+	sub  esi,ebx
+	jmp  L_do_copy1_mmx
+
+	cmp  edx,ecx
+	jbe  L_do_copy1_mmx
+
+	sub  edx,ecx
+	rep movsb
+	mov  esi,edi
+	sub  esi,ebx
+	jmp  L_do_copy1_mmx
+
+L_wrap_around_window_mmx:
+
+	mov  eax, [esp+48]
+	cmp  ecx,eax
+	jbe  L_contiguous_in_window_mmx
+
+	add  esi, [esp+52]
+	add  esi,eax
+	sub  esi,ecx
+	sub  ecx,eax
+
+
+	cmp  edx,ecx
+	jbe  L_do_copy1_mmx
+
+	sub  edx,ecx
+	rep movsb
+	mov  esi, [esp+56]
+	mov  ecx, [esp+48]
+	cmp  edx,ecx
+	jbe  L_do_copy1_mmx
+
+	sub  edx,ecx
+	rep movsb
+	mov  esi,edi
+	sub  esi,ebx
+	jmp  L_do_copy1_mmx
+
+L_contiguous_in_window_mmx:
+
+	add  esi,eax
+	sub  esi,ecx
+
+
+	cmp  edx,ecx
+	jbe  L_do_copy1_mmx
+
+	sub  edx,ecx
+	rep movsb
+	mov  esi,edi
+	sub  esi,ebx
+
+L_do_copy1_mmx:
+
+
+	mov  ecx,edx
+	rep movsb
+
+	mov  esi, [esp+44]
+	mov  ebx, [esp+8]
+	jmp  L_while_test_mmx
+; 1174 "inffast.S"
+L_invalid_distance_code:
+
+
+
+
+
+	mov  ecx, invalid_distance_code_msg
+	mov  edx,INFLATE_MODE_BAD
+	jmp  L_update_stream_state
+
+L_test_for_end_of_block:
+
+
+
+
+
+	test  al,32
+	jz  L_invalid_literal_length_code
+
+	mov  ecx,0
+	mov  edx,INFLATE_MODE_TYPE
+	jmp  L_update_stream_state
+
+L_invalid_literal_length_code:
+
+
+
+
+
+	mov  ecx, invalid_literal_length_code_msg
+	mov  edx,INFLATE_MODE_BAD
+	jmp  L_update_stream_state
+
+L_invalid_distance_too_far:
+
+
+
+	mov  esi, [esp+44]
+	mov  ecx, invalid_distance_too_far_msg
+	mov  edx,INFLATE_MODE_BAD
+	jmp  L_update_stream_state
+
+L_update_stream_state:
+
+	mov  eax, [esp+88]
+	test  ecx,ecx
+	jz  L_skip_msg
+	mov  [eax+24],ecx
+L_skip_msg:
+	mov  eax, [eax+28]
+	mov  [eax+mode_state],edx
+	jmp  L_break_loop
+
+ALIGN 4
+L_break_loop:
+; 1243 "inffast.S"
+	cmp  dword ptr [inflate_fast_use_mmx],2
+	jne  L_update_next_in
+
+
+
+	mov  ebx,ebp
+
+L_update_next_in:
+; 1266 "inffast.S"
+	mov  eax, [esp+88]
+	mov  ecx,ebx
+	mov  edx, [eax+28]
+	shr  ecx,3
+	sub  esi,ecx
+	shl  ecx,3
+	sub  ebx,ecx
+	mov  [eax+12],edi
+	mov  [edx+bits_state],ebx
+	mov  ecx,ebx
+
+	lea  ebx, [esp+28]
+	cmp  [esp+20],ebx
+	jne  L_buf_not_used
+
+	sub  esi,ebx
+	mov  ebx, [eax+0]
+	mov  [esp+20],ebx
+	add  esi,ebx
+	mov  ebx, [eax+4]
+	sub  ebx,11
+	add  [esp+20],ebx
+
+L_buf_not_used:
+	mov  [eax+0],esi
+
+	mov  ebx,1
+	shl  ebx,cl
+	dec  ebx
+
+
+
+
+
+	cmp  dword ptr [inflate_fast_use_mmx],2
+	jne  L_update_hold
+
+
+
+	psrlq mm0,mm1
+	movd ebp,mm0
+
+	emms
+
+L_update_hold:
+
+
+
+	and  ebp,ebx
+	mov  [edx+hold_state],ebp
+
+
+
+
+	mov  ebx, [esp+20]
+	cmp  ebx,esi
+	jbe  L_last_is_smaller
+
+	sub  ebx,esi
+	add  ebx,11
+	mov  [eax+4],ebx
+	jmp  L_fixup_out
+L_last_is_smaller:
+	sub  esi,ebx
+	neg  esi
+	add  esi,11
+	mov  [eax+4],esi
+
+
+
+
+L_fixup_out:
+
+	mov  ebx, [esp+16]
+	cmp  ebx,edi
+	jbe  L_end_is_smaller
+
+	sub  ebx,edi
+	add  ebx,257
+	mov  [eax+16],ebx
+	jmp  L_done
+L_end_is_smaller:
+	sub  edi,ebx
+	neg  edi
+	add  edi,257
+	mov  [eax+16],edi
+
+
+
+
+
+L_done:
+	add  esp,64
+	popfd
+	pop  ebx
+	pop  ebp
+	pop  esi
+	pop  edi
+	ret
+
+_TEXT	ends
+end
Index: /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/mkasm.bat
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/mkasm.bat	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/mkasm.bat	(revision 9)
@@ -0,0 +1,3 @@
+cl /DASMV /I..\.. /O2 /c gvmat32c.c
+ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm
+ml /coff /Zi /c /Flinffas32.lst inffas32.asm
Index: /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/readme.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/readme.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/masmx86/readme.txt	(revision 9)
@@ -0,0 +1,21 @@
+
+Summary
+-------
+This directory contains ASM implementations of the functions
+longest_match() and inflate_fast().
+
+
+Use instructions
+----------------
+Copy these files into the zlib source directory, then run the
+appropriate makefile, as suggested below.
+
+
+Build instructions
+------------------
+* With Microsoft C and MASM:
+nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" OBJA="gvmat32c.obj gvmat32.obj inffas32.obj"
+
+* With Borland C and TASM:
+make -f win32/Makefile.bor LOCAL_ZLIB="-DASMV -DASMINF" OBJA="gvmat32c.obj gvmat32.obj inffas32.obj" OBJPA="+gvmat32c.obj+gvmat32.obj+inffas32.obj"
+
Index: /trunk/minix/lib/zlib-1.2.3/contrib/minizip/ChangeLogUnzip
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/minizip/ChangeLogUnzip	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/minizip/ChangeLogUnzip	(revision 9)
@@ -0,0 +1,67 @@
+Change in 1.01e (12 feb 05)
+- Fix in zipOpen2 for globalcomment (Rolf Kalbermatter)
+- Fix possible memory leak in unzip.c (Zoran Stevanovic)
+
+Change in 1.01b (20 may 04)
+- Integrate patch from Debian package (submited by Mark Brown)
+- Add tools mztools from Xavier Roche
+
+Change in 1.01 (8 may 04)
+- fix buffer overrun risk in unzip.c (Xavier Roche)
+- fix a minor buffer insecurity in minizip.c (Mike Whittaker)
+
+Change in 1.00: (10 sept 03)
+- rename to 1.00
+- cosmetic code change
+
+Change in 0.22: (19 May 03)
+- crypting support (unless you define NOCRYPT)
+- append file in existing zipfile
+
+Change in 0.21: (10 Mar 03)
+- bug fixes
+
+Change in 0.17: (27 Jan 02)
+- bug fixes
+
+Change in 0.16: (19 Jan 02)
+- Support of ioapi for virtualize zip file access
+
+Change in 0.15: (19 Mar 98)
+- fix memory leak in minizip.c
+
+Change in 0.14: (10 Mar 98)
+- fix bugs in minizip.c sample for zipping big file
+- fix problem in month in date handling
+- fix bug in unzlocal_GetCurrentFileInfoInternal in unzip.c for
+    comment handling
+
+Change in 0.13: (6 Mar 98)
+- fix bugs in zip.c
+- add real minizip sample
+
+Change in 0.12: (4 Mar 98)
+- add zip.c and zip.h for creates .zip file
+- fix change_file_date in miniunz.c for Unix (Jean-loup Gailly)
+- fix miniunz.c for file without specific record for directory
+
+Change in 0.11: (3 Mar 98)
+- fix bug in unzGetCurrentFileInfo for get extra field and comment
+- enhance miniunz sample, remove the bad unztst.c sample
+
+Change in 0.10: (2 Mar 98)
+- fix bug in unzReadCurrentFile
+- rename unzip* to unz* function and structure
+- remove Windows-like hungary notation variable name
+- modify some structure in unzip.h
+- add somes comment in source
+- remove unzipGetcCurrentFile function
+- replace ZUNZEXPORT by ZEXPORT
+- add unzGetLocalExtrafield for get the local extrafield info
+- add a new sample, miniunz.c
+
+Change in 0.4: (25 Feb 98)
+- suppress the type unzipFileInZip.
+  Only on file in the zipfile can be open at the same time
+- fix somes typo in code
+- added tm_unz structure in unzip_file_info (date/time in readable format)
Index: /trunk/minix/lib/zlib-1.2.3/contrib/minizip/Makefile
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/minizip/Makefile	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/minizip/Makefile	(revision 9)
@@ -0,0 +1,25 @@
+CC=cc
+CFLAGS=-O -I../..
+
+UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
+ZIP_OBJS = minizip.o zip.o   ioapi.o ../../libz.a
+
+.c.o:
+	$(CC) -c $(CFLAGS) $*.c
+
+all: miniunz minizip
+
+miniunz:  $(UNZ_OBJS)
+	$(CC) $(CFLAGS) -o $@ $(UNZ_OBJS)
+
+minizip:  $(ZIP_OBJS)
+	$(CC) $(CFLAGS) -o $@ $(ZIP_OBJS)
+
+test:	miniunz minizip
+	./minizip test readme.txt
+	./miniunz -l test.zip
+	mv readme.txt readme.old
+	./miniunz test.zip
+
+clean:
+	/bin/rm -f *.o *~ minizip miniunz
Index: /trunk/minix/lib/zlib-1.2.3/contrib/minizip/crypt.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/minizip/crypt.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/minizip/crypt.h	(revision 9)
@@ -0,0 +1,132 @@
+/* crypt.h -- base code for crypt/uncrypt ZIPfile
+
+
+   Version 1.01e, February 12th, 2005
+
+   Copyright (C) 1998-2005 Gilles Vollant
+
+   This code is a modified version of crypting code in Infozip distribution
+
+   The encryption/decryption parts of this source code (as opposed to the
+   non-echoing password parts) were originally written in Europe.  The
+   whole source package can be freely distributed, including from the USA.
+   (Prior to January 2000, re-export from the US was a violation of US law.)
+
+   This encryption code is a direct transcription of the algorithm from
+   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
+   file (appnote.txt) is distributed with the PKZIP program (even in the
+   version without encryption capabilities).
+
+   If you don't need crypting in your application, just define symbols
+   NOCRYPT and NOUNCRYPT.
+
+   This code support the "Traditional PKWARE Encryption".
+
+   The new AES encryption added on Zip format by Winzip (see the page
+   http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
+   Encryption is not supported.
+*/
+
+#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
+
+/***********************************************************************
+ * Return the next byte in the pseudo-random sequence
+ */
+static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
+{
+    unsigned temp;  /* POTENTIAL BUG:  temp*(temp^1) may overflow in an
+                     * unpredictable manner on 16-bit systems; not a problem
+                     * with any known compiler so far, though */
+
+    temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
+    return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
+}
+
+/***********************************************************************
+ * Update the encryption keys with the next byte of plain text
+ */
+static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
+{
+    (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
+    (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
+    (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
+    {
+      register int keyshift = (int)((*(pkeys+1)) >> 24);
+      (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
+    }
+    return c;
+}
+
+
+/***********************************************************************
+ * Initialize the encryption keys and the random header according to
+ * the given password.
+ */
+static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
+{
+    *(pkeys+0) = 305419896L;
+    *(pkeys+1) = 591751049L;
+    *(pkeys+2) = 878082192L;
+    while (*passwd != '\0') {
+        update_keys(pkeys,pcrc_32_tab,(int)*passwd);
+        passwd++;
+    }
+}
+
+#define zdecode(pkeys,pcrc_32_tab,c) \
+    (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
+
+#define zencode(pkeys,pcrc_32_tab,c,t) \
+    (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
+
+#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
+
+#define RAND_HEAD_LEN  12
+   /* "last resort" source for second part of crypt seed pattern */
+#  ifndef ZCR_SEED2
+#    define ZCR_SEED2 3141592654UL     /* use PI as default pattern */
+#  endif
+
+static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
+    const char *passwd;         /* password string */
+    unsigned char *buf;         /* where to write header */
+    int bufSize;
+    unsigned long* pkeys;
+    const unsigned long* pcrc_32_tab;
+    unsigned long crcForCrypting;
+{
+    int n;                       /* index in random header */
+    int t;                       /* temporary */
+    int c;                       /* random byte */
+    unsigned char header[RAND_HEAD_LEN-2]; /* random header */
+    static unsigned calls = 0;   /* ensure different random header each time */
+
+    if (bufSize<RAND_HEAD_LEN)
+      return 0;
+
+    /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
+     * output of rand() to get less predictability, since rand() is
+     * often poorly implemented.
+     */
+    if (++calls == 1)
+    {
+        srand((unsigned)(time(NULL) ^ ZCR_SEED2));
+    }
+    init_keys(passwd, pkeys, pcrc_32_tab);
+    for (n = 0; n < RAND_HEAD_LEN-2; n++)
+    {
+        c = (rand() >> 7) & 0xff;
+        header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
+    }
+    /* Encrypt random header (last two bytes is high word of crc) */
+    init_keys(passwd, pkeys, pcrc_32_tab);
+    for (n = 0; n < RAND_HEAD_LEN-2; n++)
+    {
+        buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
+    }
+    buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
+    buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
+    return n;
+}
+
+#endif
Index: /trunk/minix/lib/zlib-1.2.3/contrib/minizip/ioapi.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/minizip/ioapi.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/minizip/ioapi.c	(revision 9)
@@ -0,0 +1,177 @@
+/* ioapi.c -- IO base function header for compress/uncompress .zip
+   files using zlib + zip or unzip API
+
+   Version 1.01e, February 12th, 2005
+
+   Copyright (C) 1998-2005 Gilles Vollant
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "zlib.h"
+#include "ioapi.h"
+
+
+
+/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
+
+#ifndef SEEK_CUR
+#define SEEK_CUR    1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END    2
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET    0
+#endif
+
+voidpf ZCALLBACK fopen_file_func OF((
+   voidpf opaque,
+   const char* filename,
+   int mode));
+
+uLong ZCALLBACK fread_file_func OF((
+   voidpf opaque,
+   voidpf stream,
+   void* buf,
+   uLong size));
+
+uLong ZCALLBACK fwrite_file_func OF((
+   voidpf opaque,
+   voidpf stream,
+   const void* buf,
+   uLong size));
+
+long ZCALLBACK ftell_file_func OF((
+   voidpf opaque,
+   voidpf stream));
+
+long ZCALLBACK fseek_file_func OF((
+   voidpf opaque,
+   voidpf stream,
+   uLong offset,
+   int origin));
+
+int ZCALLBACK fclose_file_func OF((
+   voidpf opaque,
+   voidpf stream));
+
+int ZCALLBACK ferror_file_func OF((
+   voidpf opaque,
+   voidpf stream));
+
+
+voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
+   voidpf opaque;
+   const char* filename;
+   int mode;
+{
+    FILE* file = NULL;
+    const char* mode_fopen = NULL;
+    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+        mode_fopen = "rb";
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+        mode_fopen = "r+b";
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+        mode_fopen = "wb";
+
+    if ((filename!=NULL) && (mode_fopen != NULL))
+        file = fopen(filename, mode_fopen);
+    return file;
+}
+
+
+uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
+   voidpf opaque;
+   voidpf stream;
+   void* buf;
+   uLong size;
+{
+    uLong ret;
+    ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
+    return ret;
+}
+
+
+uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
+   voidpf opaque;
+   voidpf stream;
+   const void* buf;
+   uLong size;
+{
+    uLong ret;
+    ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
+    return ret;
+}
+
+long ZCALLBACK ftell_file_func (opaque, stream)
+   voidpf opaque;
+   voidpf stream;
+{
+    long ret;
+    ret = ftell((FILE *)stream);
+    return ret;
+}
+
+long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
+   voidpf opaque;
+   voidpf stream;
+   uLong offset;
+   int origin;
+{
+    int fseek_origin=0;
+    long ret;
+    switch (origin)
+    {
+    case ZLIB_FILEFUNC_SEEK_CUR :
+        fseek_origin = SEEK_CUR;
+        break;
+    case ZLIB_FILEFUNC_SEEK_END :
+        fseek_origin = SEEK_END;
+        break;
+    case ZLIB_FILEFUNC_SEEK_SET :
+        fseek_origin = SEEK_SET;
+        break;
+    default: return -1;
+    }
+    ret = 0;
+    fseek((FILE *)stream, offset, fseek_origin);
+    return ret;
+}
+
+int ZCALLBACK fclose_file_func (opaque, stream)
+   voidpf opaque;
+   voidpf stream;
+{
+    int ret;
+    ret = fclose((FILE *)stream);
+    return ret;
+}
+
+int ZCALLBACK ferror_file_func (opaque, stream)
+   voidpf opaque;
+   voidpf stream;
+{
+    int ret;
+    ret = ferror((FILE *)stream);
+    return ret;
+}
+
+void fill_fopen_filefunc (pzlib_filefunc_def)
+  zlib_filefunc_def* pzlib_filefunc_def;
+{
+    pzlib_filefunc_def->zopen_file = fopen_file_func;
+    pzlib_filefunc_def->zread_file = fread_file_func;
+    pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+    pzlib_filefunc_def->ztell_file = ftell_file_func;
+    pzlib_filefunc_def->zseek_file = fseek_file_func;
+    pzlib_filefunc_def->zclose_file = fclose_file_func;
+    pzlib_filefunc_def->zerror_file = ferror_file_func;
+    pzlib_filefunc_def->opaque = NULL;
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/minizip/ioapi.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/minizip/ioapi.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/minizip/ioapi.h	(revision 9)
@@ -0,0 +1,75 @@
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+   files using zlib + zip or unzip API
+
+   Version 1.01e, February 12th, 2005
+
+   Copyright (C) 1998-2005 Gilles Vollant
+*/
+
+#ifndef _ZLIBIOAPI_H
+#define _ZLIBIOAPI_H
+
+
+#define ZLIB_FILEFUNC_SEEK_CUR (1)
+#define ZLIB_FILEFUNC_SEEK_END (2)
+#define ZLIB_FILEFUNC_SEEK_SET (0)
+
+#define ZLIB_FILEFUNC_MODE_READ      (1)
+#define ZLIB_FILEFUNC_MODE_WRITE     (2)
+#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
+
+#define ZLIB_FILEFUNC_MODE_EXISTING (4)
+#define ZLIB_FILEFUNC_MODE_CREATE   (8)
+
+
+#ifndef ZCALLBACK
+
+#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
+#define ZCALLBACK CALLBACK
+#else
+#define ZCALLBACK
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
+typedef uLong  (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+typedef uLong  (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
+typedef long   (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
+typedef long   (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
+typedef int    (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
+typedef int    (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
+
+typedef struct zlib_filefunc_def_s
+{
+    open_file_func      zopen_file;
+    read_file_func      zread_file;
+    write_file_func     zwrite_file;
+    tell_file_func      ztell_file;
+    seek_file_func      zseek_file;
+    close_file_func     zclose_file;
+    testerror_file_func zerror_file;
+    voidpf              opaque;
+} zlib_filefunc_def;
+
+
+
+void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
+
+#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
+#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
+#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))
+#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))
+#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
+#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: /trunk/minix/lib/zlib-1.2.3/contrib/minizip/iowin32.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/minizip/iowin32.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/minizip/iowin32.c	(revision 9)
@@ -0,0 +1,270 @@
+/* iowin32.c -- IO base function header for compress/uncompress .zip
+   files using zlib + zip or unzip API
+   This IO API version uses the Win32 API (for Microsoft Windows)
+
+   Version 1.01e, February 12th, 2005
+
+   Copyright (C) 1998-2005 Gilles Vollant
+*/
+
+#include <stdlib.h>
+
+#include "zlib.h"
+#include "ioapi.h"
+#include "iowin32.h"
+
+#ifndef INVALID_HANDLE_VALUE
+#define INVALID_HANDLE_VALUE (0xFFFFFFFF)
+#endif
+
+#ifndef INVALID_SET_FILE_POINTER
+#define INVALID_SET_FILE_POINTER ((DWORD)-1)
+#endif
+
+voidpf ZCALLBACK win32_open_file_func OF((
+   voidpf opaque,
+   const char* filename,
+   int mode));
+
+uLong ZCALLBACK win32_read_file_func OF((
+   voidpf opaque,
+   voidpf stream,
+   void* buf,
+   uLong size));
+
+uLong ZCALLBACK win32_write_file_func OF((
+   voidpf opaque,
+   voidpf stream,
+   const void* buf,
+   uLong size));
+
+long ZCALLBACK win32_tell_file_func OF((
+   voidpf opaque,
+   voidpf stream));
+
+long ZCALLBACK win32_seek_file_func OF((
+   voidpf opaque,
+   voidpf stream,
+   uLong offset,
+   int origin));
+
+int ZCALLBACK win32_close_file_func OF((
+   voidpf opaque,
+   voidpf stream));
+
+int ZCALLBACK win32_error_file_func OF((
+   voidpf opaque,
+   voidpf stream));
+
+typedef struct
+{
+    HANDLE hf;
+    int error;
+} WIN32FILE_IOWIN;
+
+voidpf ZCALLBACK win32_open_file_func (opaque, filename, mode)
+   voidpf opaque;
+   const char* filename;
+   int mode;
+{
+    const char* mode_fopen = NULL;
+    DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
+    HANDLE hFile = 0;
+    voidpf ret=NULL;
+
+    dwDesiredAccess = dwShareMode = dwFlagsAndAttributes = 0;
+
+    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+    {
+        dwDesiredAccess = GENERIC_READ;
+        dwCreationDisposition = OPEN_EXISTING;
+        dwShareMode = FILE_SHARE_READ;
+    }
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+    {
+        dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
+        dwCreationDisposition = OPEN_EXISTING;
+    }
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+    {
+        dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
+        dwCreationDisposition = CREATE_ALWAYS;
+    }
+
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+        hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL,
+                      dwCreationDisposition, dwFlagsAndAttributes, NULL);
+
+    if (hFile == INVALID_HANDLE_VALUE)
+        hFile = NULL;
+
+    if (hFile != NULL)
+    {
+        WIN32FILE_IOWIN w32fiow;
+        w32fiow.hf = hFile;
+        w32fiow.error = 0;
+        ret = malloc(sizeof(WIN32FILE_IOWIN));
+        if (ret==NULL)
+            CloseHandle(hFile);
+        else *((WIN32FILE_IOWIN*)ret) = w32fiow;
+    }
+    return ret;
+}
+
+
+uLong ZCALLBACK win32_read_file_func (opaque, stream, buf, size)
+   voidpf opaque;
+   voidpf stream;
+   void* buf;
+   uLong size;
+{
+    uLong ret=0;
+    HANDLE hFile = NULL;
+    if (stream!=NULL)
+        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+    if (hFile != NULL)
+        if (!ReadFile(hFile, buf, size, &ret, NULL))
+        {
+            DWORD dwErr = GetLastError();
+            if (dwErr == ERROR_HANDLE_EOF)
+                dwErr = 0;
+            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
+        }
+
+    return ret;
+}
+
+
+uLong ZCALLBACK win32_write_file_func (opaque, stream, buf, size)
+   voidpf opaque;
+   voidpf stream;
+   const void* buf;
+   uLong size;
+{
+    uLong ret=0;
+    HANDLE hFile = NULL;
+    if (stream!=NULL)
+        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+
+    if (hFile !=NULL)
+        if (!WriteFile(hFile, buf, size, &ret, NULL))
+        {
+            DWORD dwErr = GetLastError();
+            if (dwErr == ERROR_HANDLE_EOF)
+                dwErr = 0;
+            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
+        }
+
+    return ret;
+}
+
+long ZCALLBACK win32_tell_file_func (opaque, stream)
+   voidpf opaque;
+   voidpf stream;
+{
+    long ret=-1;
+    HANDLE hFile = NULL;
+    if (stream!=NULL)
+        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+    if (hFile != NULL)
+    {
+        DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
+        if (dwSet == INVALID_SET_FILE_POINTER)
+        {
+            DWORD dwErr = GetLastError();
+            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
+            ret = -1;
+        }
+        else
+            ret=(long)dwSet;
+    }
+    return ret;
+}
+
+long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin)
+   voidpf opaque;
+   voidpf stream;
+   uLong offset;
+   int origin;
+{
+    DWORD dwMoveMethod=0xFFFFFFFF;
+    HANDLE hFile = NULL;
+
+    long ret=-1;
+    if (stream!=NULL)
+        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+    switch (origin)
+    {
+    case ZLIB_FILEFUNC_SEEK_CUR :
+        dwMoveMethod = FILE_CURRENT;
+        break;
+    case ZLIB_FILEFUNC_SEEK_END :
+        dwMoveMethod = FILE_END;
+        break;
+    case ZLIB_FILEFUNC_SEEK_SET :
+        dwMoveMethod = FILE_BEGIN;
+        break;
+    default: return -1;
+    }
+
+    if (hFile != NULL)
+    {
+        DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod);
+        if (dwSet == INVALID_SET_FILE_POINTER)
+        {
+            DWORD dwErr = GetLastError();
+            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
+            ret = -1;
+        }
+        else
+            ret=0;
+    }
+    return ret;
+}
+
+int ZCALLBACK win32_close_file_func (opaque, stream)
+   voidpf opaque;
+   voidpf stream;
+{
+    int ret=-1;
+
+    if (stream!=NULL)
+    {
+        HANDLE hFile;
+        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+        if (hFile != NULL)
+        {
+            CloseHandle(hFile);
+            ret=0;
+        }
+        free(stream);
+    }
+    return ret;
+}
+
+int ZCALLBACK win32_error_file_func (opaque, stream)
+   voidpf opaque;
+   voidpf stream;
+{
+    int ret=-1;
+    if (stream!=NULL)
+    {
+        ret = ((WIN32FILE_IOWIN*)stream) -> error;
+    }
+    return ret;
+}
+
+void fill_win32_filefunc (pzlib_filefunc_def)
+  zlib_filefunc_def* pzlib_filefunc_def;
+{
+    pzlib_filefunc_def->zopen_file = win32_open_file_func;
+    pzlib_filefunc_def->zread_file = win32_read_file_func;
+    pzlib_filefunc_def->zwrite_file = win32_write_file_func;
+    pzlib_filefunc_def->ztell_file = win32_tell_file_func;
+    pzlib_filefunc_def->zseek_file = win32_seek_file_func;
+    pzlib_filefunc_def->zclose_file = win32_close_file_func;
+    pzlib_filefunc_def->zerror_file = win32_error_file_func;
+    pzlib_filefunc_def->opaque=NULL;
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/minizip/iowin32.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/minizip/iowin32.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/minizip/iowin32.h	(revision 9)
@@ -0,0 +1,21 @@
+/* iowin32.h -- IO base function header for compress/uncompress .zip
+   files using zlib + zip or unzip API
+   This IO API version uses the Win32 API (for Microsoft Windows)
+
+   Version 1.01e, February 12th, 2005
+
+   Copyright (C) 1998-2005 Gilles Vollant
+*/
+
+#include <windows.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
+
+#ifdef __cplusplus
+}
+#endif
Index: /trunk/minix/lib/zlib-1.2.3/contrib/minizip/miniunz.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/minizip/miniunz.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/minizip/miniunz.c	(revision 9)
@@ -0,0 +1,585 @@
+/*
+   miniunz.c
+   Version 1.01e, February 12th, 2005
+
+   Copyright (C) 1998-2005 Gilles Vollant
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#ifdef unix
+# include <unistd.h>
+# include <utime.h>
+#else
+# include <direct.h>
+# include <io.h>
+#endif
+
+#include "unzip.h"
+
+#define CASESENSITIVITY (0)
+#define WRITEBUFFERSIZE (8192)
+#define MAXFILENAME (256)
+
+#ifdef WIN32
+#define USEWIN32IOAPI
+#include "iowin32.h"
+#endif
+/*
+  mini unzip, demo of unzip package
+
+  usage :
+  Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir]
+
+  list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT
+    if it exists
+*/
+
+
+/* change_file_date : change the date/time of a file
+    filename : the filename of the file where date/time must be modified
+    dosdate : the new date at the MSDos format (4 bytes)
+    tmu_date : the SAME new date at the tm_unz format */
+void change_file_date(filename,dosdate,tmu_date)
+    const char *filename;
+    uLong dosdate;
+    tm_unz tmu_date;
+{
+#ifdef WIN32
+  HANDLE hFile;
+  FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
+
+  hFile = CreateFile(filename,GENERIC_READ | GENERIC_WRITE,
+                      0,NULL,OPEN_EXISTING,0,NULL);
+  GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
+  DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
+  LocalFileTimeToFileTime(&ftLocal,&ftm);
+  SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
+  CloseHandle(hFile);
+#else
+#ifdef unix
+  struct utimbuf ut;
+  struct tm newdate;
+  newdate.tm_sec = tmu_date.tm_sec;
+  newdate.tm_min=tmu_date.tm_min;
+  newdate.tm_hour=tmu_date.tm_hour;
+  newdate.tm_mday=tmu_date.tm_mday;
+  newdate.tm_mon=tmu_date.tm_mon;
+  if (tmu_date.tm_year > 1900)
+      newdate.tm_year=tmu_date.tm_year - 1900;
+  else
+      newdate.tm_year=tmu_date.tm_year ;
+  newdate.tm_isdst=-1;
+
+  ut.actime=ut.modtime=mktime(&newdate);
+  utime(filename,&ut);
+#endif
+#endif
+}
+
+
+/* mymkdir and change_file_date are not 100 % portable
+   As I don't know well Unix, I wait feedback for the unix portion */
+
+int mymkdir(dirname)
+    const char* dirname;
+{
+    int ret=0;
+#ifdef WIN32
+    ret = mkdir(dirname);
+#else
+#ifdef unix
+    ret = mkdir (dirname,0775);
+#endif
+#endif
+    return ret;
+}
+
+int makedir (newdir)
+    char *newdir;
+{
+  char *buffer ;
+  char *p;
+  int  len = (int)strlen(newdir);
+
+  if (len <= 0)
+    return 0;
+
+  buffer = (char*)malloc(len+1);
+  strcpy(buffer,newdir);
+
+  if (buffer[len-1] == '/') {
+    buffer[len-1] = '\0';
+  }
+  if (mymkdir(buffer) == 0)
+    {
+      free(buffer);
+      return 1;
+    }
+
+  p = buffer+1;
+  while (1)
+    {
+      char hold;
+
+      while(*p && *p != '\\' && *p != '/')
+        p++;
+      hold = *p;
+      *p = 0;
+      if ((mymkdir(buffer) == -1) && (errno == ENOENT))
+        {
+          printf("couldn't create directory %s\n",buffer);
+          free(buffer);
+          return 0;
+        }
+      if (hold == 0)
+        break;
+      *p++ = hold;
+    }
+  free(buffer);
+  return 1;
+}
+
+void do_banner()
+{
+    printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n");
+    printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
+}
+
+void do_help()
+{
+    printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \
+           "  -e  Extract without pathname (junk paths)\n" \
+           "  -x  Extract with pathname\n" \
+           "  -v  list files\n" \
+           "  -l  list files\n" \
+           "  -d  directory to extract into\n" \
+           "  -o  overwrite files without prompting\n" \
+           "  -p  extract crypted file using password\n\n");
+}
+
+
+int do_list(uf)
+    unzFile uf;
+{
+    uLong i;
+    unz_global_info gi;
+    int err;
+
+    err = unzGetGlobalInfo (uf,&gi);
+    if (err!=UNZ_OK)
+        printf("error %d with zipfile in unzGetGlobalInfo \n",err);
+    printf(" Length  Method   Size  Ratio   Date    Time   CRC-32     Name\n");
+    printf(" ------  ------   ----  -----   ----    ----   ------     ----\n");
+    for (i=0;i<gi.number_entry;i++)
+    {
+        char filename_inzip[256];
+        unz_file_info file_info;
+        uLong ratio=0;
+        const char *string_method;
+        char charCrypt=' ';
+        err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
+        if (err!=UNZ_OK)
+        {
+            printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
+            break;
+        }
+        if (file_info.uncompressed_size>0)
+            ratio = (file_info.compressed_size*100)/file_info.uncompressed_size;
+
+        /* display a '*' if the file is crypted */
+        if ((file_info.flag & 1) != 0)
+            charCrypt='*';
+
+        if (file_info.compression_method==0)
+            string_method="Stored";
+        else
+        if (file_info.compression_method==Z_DEFLATED)
+        {
+            uInt iLevel=(uInt)((file_info.flag & 0x6)/2);
+            if (iLevel==0)
+              string_method="Defl:N";
+            else if (iLevel==1)
+              string_method="Defl:X";
+            else if ((iLevel==2) || (iLevel==3))
+              string_method="Defl:F"; /* 2:fast , 3 : extra fast*/
+        }
+        else
+            string_method="Unkn. ";
+
+        printf("%7lu  %6s%c%7lu %3lu%%  %2.2lu-%2.2lu-%2.2lu  %2.2lu:%2.2lu  %8.8lx   %s\n",
+                file_info.uncompressed_size,string_method,
+                charCrypt,
+                file_info.compressed_size,
+                ratio,
+                (uLong)file_info.tmu_date.tm_mon + 1,
+                (uLong)file_info.tmu_date.tm_mday,
+                (uLong)file_info.tmu_date.tm_year % 100,
+                (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min,
+                (uLong)file_info.crc,filename_inzip);
+        if ((i+1)<gi.number_entry)
+        {
+            err = unzGoToNextFile(uf);
+            if (err!=UNZ_OK)
+            {
+                printf("error %d with zipfile in unzGoToNextFile\n",err);
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
+
+
+int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password)
+    unzFile uf;
+    const int* popt_extract_without_path;
+    int* popt_overwrite;
+    const char* password;
+{
+    char filename_inzip[256];
+    char* filename_withoutpath;
+    char* p;
+    int err=UNZ_OK;
+    FILE *fout=NULL;
+    void* buf;
+    uInt size_buf;
+
+    unz_file_info file_info;
+    uLong ratio=0;
+    err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
+
+    if (err!=UNZ_OK)
+    {
+        printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
+        return err;
+    }
+
+    size_buf = WRITEBUFFERSIZE;
+    buf = (void*)malloc(size_buf);
+    if (buf==NULL)
+    {
+        printf("Error allocating memory\n");
+        return UNZ_INTERNALERROR;
+    }
+
+    p = filename_withoutpath = filename_inzip;
+    while ((*p) != '\0')
+    {
+        if (((*p)=='/') || ((*p)=='\\'))
+            filename_withoutpath = p+1;
+        p++;
+    }
+
+    if ((*filename_withoutpath)=='\0')
+    {
+        if ((*popt_extract_without_path)==0)
+        {
+            printf("creating directory: %s\n",filename_inzip);
+            mymkdir(filename_inzip);
+        }
+    }
+    else
+    {
+        const char* write_filename;
+        int skip=0;
+
+        if ((*popt_extract_without_path)==0)
+            write_filename = filename_inzip;
+        else
+            write_filename = filename_withoutpath;
+
+        err = unzOpenCurrentFilePassword(uf,password);
+        if (err!=UNZ_OK)
+        {
+            printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
+        }
+
+        if (((*popt_overwrite)==0) && (err==UNZ_OK))
+        {
+            char rep=0;
+            FILE* ftestexist;
+            ftestexist = fopen(write_filename,"rb");
+            if (ftestexist!=NULL)
+            {
+                fclose(ftestexist);
+                do
+                {
+                    char answer[128];
+                    int ret;
+
+                    printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ",write_filename);
+                    ret = scanf("%1s",answer);
+                    if (ret != 1) 
+                    {
+                       exit(EXIT_FAILURE);
+                    }
+                    rep = answer[0] ;
+                    if ((rep>='a') && (rep<='z'))
+                        rep -= 0x20;
+                }
+                while ((rep!='Y') && (rep!='N') && (rep!='A'));
+            }
+
+            if (rep == 'N')
+                skip = 1;
+
+            if (rep == 'A')
+                *popt_overwrite=1;
+        }
+
+        if ((skip==0) && (err==UNZ_OK))
+        {
+            fout=fopen(write_filename,"wb");
+
+            /* some zipfile don't contain directory alone before file */
+            if ((fout==NULL) && ((*popt_extract_without_path)==0) &&
+                                (filename_withoutpath!=(char*)filename_inzip))
+            {
+                char c=*(filename_withoutpath-1);
+                *(filename_withoutpath-1)='\0';
+                makedir(write_filename);
+                *(filename_withoutpath-1)=c;
+                fout=fopen(write_filename,"wb");
+            }
+
+            if (fout==NULL)
+            {
+                printf("error opening %s\n",write_filename);
+            }
+        }
+
+        if (fout!=NULL)
+        {
+            printf(" extracting: %s\n",write_filename);
+
+            do
+            {
+                err = unzReadCurrentFile(uf,buf,size_buf);
+                if (err<0)
+                {
+                    printf("error %d with zipfile in unzReadCurrentFile\n",err);
+                    break;
+                }
+                if (err>0)
+                    if (fwrite(buf,err,1,fout)!=1)
+                    {
+                        printf("error in writing extracted file\n");
+                        err=UNZ_ERRNO;
+                        break;
+                    }
+            }
+            while (err>0);
+            if (fout)
+                    fclose(fout);
+
+            if (err==0)
+                change_file_date(write_filename,file_info.dosDate,
+                                 file_info.tmu_date);
+        }
+
+        if (err==UNZ_OK)
+        {
+            err = unzCloseCurrentFile (uf);
+            if (err!=UNZ_OK)
+            {
+                printf("error %d with zipfile in unzCloseCurrentFile\n",err);
+            }
+        }
+        else
+            unzCloseCurrentFile(uf); /* don't lose the error */
+    }
+
+    free(buf);
+    return err;
+}
+
+
+int do_extract(uf,opt_extract_without_path,opt_overwrite,password)
+    unzFile uf;
+    int opt_extract_without_path;
+    int opt_overwrite;
+    const char* password;
+{
+    uLong i;
+    unz_global_info gi;
+    int err;
+    FILE* fout=NULL;
+
+    err = unzGetGlobalInfo (uf,&gi);
+    if (err!=UNZ_OK)
+        printf("error %d with zipfile in unzGetGlobalInfo \n",err);
+
+    for (i=0;i<gi.number_entry;i++)
+    {
+        if (do_extract_currentfile(uf,&opt_extract_without_path,
+                                      &opt_overwrite,
+                                      password) != UNZ_OK)
+            break;
+
+        if ((i+1)<gi.number_entry)
+        {
+            err = unzGoToNextFile(uf);
+            if (err!=UNZ_OK)
+            {
+                printf("error %d with zipfile in unzGoToNextFile\n",err);
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
+
+int do_extract_onefile(uf,filename,opt_extract_without_path,opt_overwrite,password)
+    unzFile uf;
+    const char* filename;
+    int opt_extract_without_path;
+    int opt_overwrite;
+    const char* password;
+{
+    int err = UNZ_OK;
+    if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK)
+    {
+        printf("file %s not found in the zipfile\n",filename);
+        return 2;
+    }
+
+    if (do_extract_currentfile(uf,&opt_extract_without_path,
+                                      &opt_overwrite,
+                                      password) == UNZ_OK)
+        return 0;
+    else
+        return 1;
+}
+
+
+int main(argc,argv)
+    int argc;
+    char *argv[];
+{
+    const char *zipfilename=NULL;
+    const char *filename_to_extract=NULL;
+    const char *password=NULL;
+    char filename_try[MAXFILENAME+16] = "";
+    int i;
+    int opt_do_list=0;
+    int opt_do_extract=1;
+    int opt_do_extract_withoutpath=0;
+    int opt_overwrite=0;
+    int opt_extractdir=0;
+    const char *dirname=NULL;
+    unzFile uf=NULL;
+
+    do_banner();
+    if (argc==1)
+    {
+        do_help();
+        return 0;
+    }
+    else
+    {
+        for (i=1;i<argc;i++)
+        {
+            if ((*argv[i])=='-')
+            {
+                const char *p=argv[i]+1;
+
+                while ((*p)!='\0')
+                {
+                    char c=*(p++);;
+                    if ((c=='l') || (c=='L'))
+                        opt_do_list = 1;
+                    if ((c=='v') || (c=='V'))
+                        opt_do_list = 1;
+                    if ((c=='x') || (c=='X'))
+                        opt_do_extract = 1;
+                    if ((c=='e') || (c=='E'))
+                        opt_do_extract = opt_do_extract_withoutpath = 1;
+                    if ((c=='o') || (c=='O'))
+                        opt_overwrite=1;
+                    if ((c=='d') || (c=='D'))
+                    {
+                        opt_extractdir=1;
+                        dirname=argv[i+1];
+                    }
+
+                    if (((c=='p') || (c=='P')) && (i+1<argc))
+                    {
+                        password=argv[i+1];
+                        i++;
+                    }
+                }
+            }
+            else
+            {
+                if (zipfilename == NULL)
+                    zipfilename = argv[i];
+                else if ((filename_to_extract==NULL) && (!opt_extractdir))
+                        filename_to_extract = argv[i] ;
+            }
+        }
+    }
+
+    if (zipfilename!=NULL)
+    {
+
+#        ifdef USEWIN32IOAPI
+        zlib_filefunc_def ffunc;
+#        endif
+
+        strncpy(filename_try, zipfilename,MAXFILENAME-1);
+        /* strncpy doesnt append the trailing NULL, of the string is too long. */
+        filename_try[ MAXFILENAME ] = '\0';
+
+#        ifdef USEWIN32IOAPI
+        fill_win32_filefunc(&ffunc);
+        uf = unzOpen2(zipfilename,&ffunc);
+#        else
+        uf = unzOpen(zipfilename);
+#        endif
+        if (uf==NULL)
+        {
+            strcat(filename_try,".zip");
+#            ifdef USEWIN32IOAPI
+            uf = unzOpen2(filename_try,&ffunc);
+#            else
+            uf = unzOpen(filename_try);
+#            endif
+        }
+    }
+
+    if (uf==NULL)
+    {
+        printf("Cannot open %s or %s.zip\n",zipfilename,zipfilename);
+        return 1;
+    }
+    printf("%s opened\n",filename_try);
+
+    if (opt_do_list==1)
+        return do_list(uf);
+    else if (opt_do_extract==1)
+    {
+        if (opt_extractdir && chdir(dirname)) 
+        {
+          printf("Error changing into %s, aborting\n", dirname);
+          exit(-1);
+        }
+
+        if (filename_to_extract == NULL)
+            return do_extract(uf,opt_do_extract_withoutpath,opt_overwrite,password);
+        else
+            return do_extract_onefile(uf,filename_to_extract,
+                                      opt_do_extract_withoutpath,opt_overwrite,password);
+    }
+    unzCloseCurrentFile(uf);
+
+    return 0;
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/minizip/minizip.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/minizip/minizip.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/minizip/minizip.c	(revision 9)
@@ -0,0 +1,420 @@
+/*
+   minizip.c
+   Version 1.01e, February 12th, 2005
+
+   Copyright (C) 1998-2005 Gilles Vollant
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#ifdef unix
+# include <unistd.h>
+# include <utime.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+#else
+# include <direct.h>
+# include <io.h>
+#endif
+
+#include "zip.h"
+
+#ifdef WIN32
+#define USEWIN32IOAPI
+#include "iowin32.h"
+#endif
+
+
+
+#define WRITEBUFFERSIZE (16384)
+#define MAXFILENAME (256)
+
+#ifdef WIN32
+uLong filetime(f, tmzip, dt)
+    char *f;                /* name of file to get info on */
+    tm_zip *tmzip;             /* return value: access, modific. and creation times */
+    uLong *dt;             /* dostime */
+{
+  int ret = 0;
+  {
+      FILETIME ftLocal;
+      HANDLE hFind;
+      WIN32_FIND_DATA  ff32;
+
+      hFind = FindFirstFile(f,&ff32);
+      if (hFind != INVALID_HANDLE_VALUE)
+      {
+        FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
+        FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
+        FindClose(hFind);
+        ret = 1;
+      }
+  }
+  return ret;
+}
+#else
+#ifdef unix
+uLong filetime(f, tmzip, dt)
+    char *f;               /* name of file to get info on */
+    tm_zip *tmzip;         /* return value: access, modific. and creation times */
+    uLong *dt;             /* dostime */
+{
+  int ret=0;
+  struct stat s;        /* results of stat() */
+  struct tm* filedate;
+  time_t tm_t=0;
+
+  if (strcmp(f,"-")!=0)
+  {
+    char name[MAXFILENAME+1];
+    int len = strlen(f);
+    if (len > MAXFILENAME)
+      len = MAXFILENAME;
+
+    strncpy(name, f,MAXFILENAME-1);
+    /* strncpy doesnt append the trailing NULL, of the string is too long. */
+    name[ MAXFILENAME ] = '\0';
+
+    if (name[len - 1] == '/')
+      name[len - 1] = '\0';
+    /* not all systems allow stat'ing a file with / appended */
+    if (stat(name,&s)==0)
+    {
+      tm_t = s.st_mtime;
+      ret = 1;
+    }
+  }
+  filedate = localtime(&tm_t);
+
+  tmzip->tm_sec  = filedate->tm_sec;
+  tmzip->tm_min  = filedate->tm_min;
+  tmzip->tm_hour = filedate->tm_hour;
+  tmzip->tm_mday = filedate->tm_mday;
+  tmzip->tm_mon  = filedate->tm_mon ;
+  tmzip->tm_year = filedate->tm_year;
+
+  return ret;
+}
+#else
+uLong filetime(f, tmzip, dt)
+    char *f;                /* name of file to get info on */
+    tm_zip *tmzip;             /* return value: access, modific. and creation times */
+    uLong *dt;             /* dostime */
+{
+    return 0;
+}
+#endif
+#endif
+
+
+
+
+int check_exist_file(filename)
+    const char* filename;
+{
+    FILE* ftestexist;
+    int ret = 1;
+    ftestexist = fopen(filename,"rb");
+    if (ftestexist==NULL)
+        ret = 0;
+    else
+        fclose(ftestexist);
+    return ret;
+}
+
+void do_banner()
+{
+    printf("MiniZip 1.01b, demo of zLib + Zip package written by Gilles Vollant\n");
+    printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
+}
+
+void do_help()
+{
+    printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] file.zip [files_to_add]\n\n" \
+           "  -o  Overwrite existing file.zip\n" \
+           "  -a  Append to existing file.zip\n" \
+           "  -0  Store only\n" \
+           "  -1  Compress faster\n" \
+           "  -9  Compress better\n\n");
+}
+
+/* calculate the CRC32 of a file,
+   because to encrypt a file, we need known the CRC32 of the file before */
+int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc)
+{
+   unsigned long calculate_crc=0;
+   int err=ZIP_OK;
+   FILE * fin = fopen(filenameinzip,"rb");
+   unsigned long size_read = 0;
+   unsigned long total_read = 0;
+   if (fin==NULL)
+   {
+       err = ZIP_ERRNO;
+   }
+
+    if (err == ZIP_OK)
+        do
+        {
+            err = ZIP_OK;
+            size_read = (int)fread(buf,1,size_buf,fin);
+            if (size_read < size_buf)
+                if (feof(fin)==0)
+            {
+                printf("error in reading %s\n",filenameinzip);
+                err = ZIP_ERRNO;
+            }
+
+            if (size_read>0)
+                calculate_crc = crc32(calculate_crc,buf,size_read);
+            total_read += size_read;
+
+        } while ((err == ZIP_OK) && (size_read>0));
+
+    if (fin)
+        fclose(fin);
+
+    *result_crc=calculate_crc;
+    printf("file %s crc %x\n",filenameinzip,calculate_crc);
+    return err;
+}
+
+int main(argc,argv)
+    int argc;
+    char *argv[];
+{
+    int i;
+    int opt_overwrite=0;
+    int opt_compress_level=Z_DEFAULT_COMPRESSION;
+    int zipfilenamearg = 0;
+    char filename_try[MAXFILENAME+16];
+    int zipok;
+    int err=0;
+    int size_buf=0;
+    void* buf=NULL;
+    const char* password=NULL;
+
+
+    do_banner();
+    if (argc==1)
+    {
+        do_help();
+        return 0;
+    }
+    else
+    {
+        for (i=1;i<argc;i++)
+        {
+            if ((*argv[i])=='-')
+            {
+                const char *p=argv[i]+1;
+
+                while ((*p)!='\0')
+                {
+                    char c=*(p++);;
+                    if ((c=='o') || (c=='O'))
+                        opt_overwrite = 1;
+                    if ((c=='a') || (c=='A'))
+                        opt_overwrite = 2;
+                    if ((c>='0') && (c<='9'))
+                        opt_compress_level = c-'0';
+
+                    if (((c=='p') || (c=='P')) && (i+1<argc))
+                    {
+                        password=argv[i+1];
+                        i++;
+                    }
+                }
+            }
+            else
+                if (zipfilenamearg == 0)
+                    zipfilenamearg = i ;
+        }
+    }
+
+    size_buf = WRITEBUFFERSIZE;
+    buf = (void*)malloc(size_buf);
+    if (buf==NULL)
+    {
+        printf("Error allocating memory\n");
+        return ZIP_INTERNALERROR;
+    }
+
+    if (zipfilenamearg==0)
+        zipok=0;
+    else
+    {
+        int i,len;
+        int dot_found=0;
+
+        zipok = 1 ;
+        strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1);
+        /* strncpy doesnt append the trailing NULL, of the string is too long. */
+        filename_try[ MAXFILENAME ] = '\0';
+
+        len=(int)strlen(filename_try);
+        for (i=0;i<len;i++)
+            if (filename_try[i]=='.')
+                dot_found=1;
+
+        if (dot_found==0)
+            strcat(filename_try,".zip");
+
+        if (opt_overwrite==2)
+        {
+            /* if the file don't exist, we not append file */
+            if (check_exist_file(filename_try)==0)
+                opt_overwrite=1;
+        }
+        else
+        if (opt_overwrite==0)
+            if (check_exist_file(filename_try)!=0)
+            {
+                char rep=0;
+                do
+                {
+                    char answer[128];
+                    int ret;
+                    printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ",filename_try);
+                    ret = scanf("%1s",answer);
+                    if (ret != 1)
+                    {
+                       exit(EXIT_FAILURE);
+                    }
+                    rep = answer[0] ;
+                    if ((rep>='a') && (rep<='z'))
+                        rep -= 0x20;
+                }
+                while ((rep!='Y') && (rep!='N') && (rep!='A'));
+                if (rep=='N')
+                    zipok = 0;
+                if (rep=='A')
+                    opt_overwrite = 2;
+            }
+    }
+
+    if (zipok==1)
+    {
+        zipFile zf;
+        int errclose;
+#        ifdef USEWIN32IOAPI
+        zlib_filefunc_def ffunc;
+        fill_win32_filefunc(&ffunc);
+        zf = zipOpen2(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc);
+#        else
+        zf = zipOpen(filename_try,(opt_overwrite==2) ? 2 : 0);
+#        endif
+
+        if (zf == NULL)
+        {
+            printf("error opening %s\n",filename_try);
+            err= ZIP_ERRNO;
+        }
+        else
+            printf("creating %s\n",filename_try);
+
+        for (i=zipfilenamearg+1;(i<argc) && (err==ZIP_OK);i++)
+        {
+            if (!((((*(argv[i]))=='-') || ((*(argv[i]))=='/')) &&
+                  ((argv[i][1]=='o') || (argv[i][1]=='O') ||
+                   (argv[i][1]=='a') || (argv[i][1]=='A') ||
+                   (argv[i][1]=='p') || (argv[i][1]=='P') ||
+                   ((argv[i][1]>='0') || (argv[i][1]<='9'))) &&
+                  (strlen(argv[i]) == 2)))
+            {
+                FILE * fin;
+                int size_read;
+                const char* filenameinzip = argv[i];
+                zip_fileinfo zi;
+                unsigned long crcFile=0;
+
+                zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
+                zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
+                zi.dosDate = 0;
+                zi.internal_fa = 0;
+                zi.external_fa = 0;
+                filetime(filenameinzip,&zi.tmz_date,&zi.dosDate);
+
+/*
+                err = zipOpenNewFileInZip(zf,filenameinzip,&zi,
+                                 NULL,0,NULL,0,NULL / * comment * /,
+                                 (opt_compress_level != 0) ? Z_DEFLATED : 0,
+                                 opt_compress_level);
+*/
+                if ((password != NULL) && (err==ZIP_OK))
+                    err = getFileCrc(filenameinzip,buf,size_buf,&crcFile);
+
+                err = zipOpenNewFileInZip3(zf,filenameinzip,&zi,
+                                 NULL,0,NULL,0,NULL /* comment*/,
+                                 (opt_compress_level != 0) ? Z_DEFLATED : 0,
+                                 opt_compress_level,0,
+                                 /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
+                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
+                                 password,crcFile);
+
+                if (err != ZIP_OK)
+                    printf("error in opening %s in zipfile\n",filenameinzip);
+                else
+                {
+                    fin = fopen(filenameinzip,"rb");
+                    if (fin==NULL)
+                    {
+                        err=ZIP_ERRNO;
+                        printf("error in opening %s for reading\n",filenameinzip);
+                    }
+                }
+
+                if (err == ZIP_OK)
+                    do
+                    {
+                        err = ZIP_OK;
+                        size_read = (int)fread(buf,1,size_buf,fin);
+                        if (size_read < size_buf)
+                            if (feof(fin)==0)
+                        {
+                            printf("error in reading %s\n",filenameinzip);
+                            err = ZIP_ERRNO;
+                        }
+
+                        if (size_read>0)
+                        {
+                            err = zipWriteInFileInZip (zf,buf,size_read);
+                            if (err<0)
+                            {
+                                printf("error in writing %s in the zipfile\n",
+                                                 filenameinzip);
+                            }
+
+                        }
+                    } while ((err == ZIP_OK) && (size_read>0));
+
+                if (fin)
+                    fclose(fin);
+
+                if (err<0)
+                    err=ZIP_ERRNO;
+                else
+                {
+                    err = zipCloseFileInZip(zf);
+                    if (err!=ZIP_OK)
+                        printf("error in closing %s in the zipfile\n",
+                                    filenameinzip);
+                }
+            }
+        }
+        errclose = zipClose(zf,NULL);
+        if (errclose != ZIP_OK)
+            printf("error in closing %s\n",filename_try);
+    }
+    else
+    {
+       do_help();
+    }
+
+    free(buf);
+    return 0;
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/minizip/mztools.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/minizip/mztools.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/minizip/mztools.c	(revision 9)
@@ -0,0 +1,281 @@
+/*
+  Additional tools for Minizip
+  Code: Xavier Roche '2004
+  License: Same as ZLIB (www.gzip.org)
+*/
+
+/* Code */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "zlib.h"
+#include "unzip.h"
+
+#define READ_8(adr)  ((unsigned char)*(adr))
+#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) )
+#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) )
+
+#define WRITE_8(buff, n) do { \
+  *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \
+} while(0)
+#define WRITE_16(buff, n) do { \
+  WRITE_8((unsigned char*)(buff), n); \
+  WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \
+} while(0)
+#define WRITE_32(buff, n) do { \
+  WRITE_16((unsigned char*)(buff), (n) & 0xffff); \
+  WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \
+} while(0)
+
+extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered)
+const char* file;
+const char* fileOut;
+const char* fileOutTmp;
+uLong* nRecovered;
+uLong* bytesRecovered;
+{
+  int err = Z_OK;
+  FILE* fpZip = fopen(file, "rb");
+  FILE* fpOut = fopen(fileOut, "wb");
+  FILE* fpOutCD = fopen(fileOutTmp, "wb");
+  if (fpZip != NULL &&  fpOut != NULL) {
+    int entries = 0;
+    uLong totalBytes = 0;
+    char header[30];
+    char filename[256];
+    char extra[1024];
+    int offset = 0;
+    int offsetCD = 0;
+    while ( fread(header, 1, 30, fpZip) == 30 ) {
+      int currentOffset = offset;
+
+      /* File entry */
+      if (READ_32(header) == 0x04034b50) {
+        unsigned int version = READ_16(header + 4);
+        unsigned int gpflag = READ_16(header + 6);
+        unsigned int method = READ_16(header + 8);
+        unsigned int filetime = READ_16(header + 10);
+        unsigned int filedate = READ_16(header + 12);
+        unsigned int crc = READ_32(header + 14); /* crc */
+        unsigned int cpsize = READ_32(header + 18); /* compressed size */
+        unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */
+        unsigned int fnsize = READ_16(header + 26); /* file name length */
+        unsigned int extsize = READ_16(header + 28); /* extra field length */
+        filename[0] = extra[0] = '\0';
+        
+        /* Header */
+        if (fwrite(header, 1, 30, fpOut) == 30) {
+          offset += 30;
+        } else {
+          err = Z_ERRNO;
+          break;
+        }
+        
+        /* Filename */
+        if (fnsize > 0) {
+          if (fread(filename, 1, fnsize, fpZip) == fnsize) {
+            if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {
+              offset += fnsize;
+            } else {
+              err = Z_ERRNO;
+              break;
+            }
+          } else {
+            err = Z_ERRNO;
+            break;
+          }
+        } else {
+          err = Z_STREAM_ERROR;
+          break;
+        }
+
+        /* Extra field */
+        if (extsize > 0) {
+          if (fread(extra, 1, extsize, fpZip) == extsize) {
+            if (fwrite(extra, 1, extsize, fpOut) == extsize) {
+              offset += extsize;
+            } else {
+              err = Z_ERRNO;
+              break;
+            }
+          } else {
+            err = Z_ERRNO;
+            break;
+          }
+        }
+        
+        /* Data */
+        {
+          int dataSize = cpsize;
+          if (dataSize == 0) {
+            dataSize = uncpsize;
+          }
+          if (dataSize > 0) {
+            char* data = malloc(dataSize);
+            if (data != NULL) {
+              if ((int)fread(data, 1, dataSize, fpZip) == dataSize) {
+                if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) {
+                  offset += dataSize;
+                  totalBytes += dataSize;
+                } else {
+                  err = Z_ERRNO;
+                }
+              } else {
+                err = Z_ERRNO;
+              }
+              free(data);
+              if (err != Z_OK) {
+                break;
+              }
+            } else {
+              err = Z_MEM_ERROR;
+              break;
+            }
+          }
+        }
+        
+        /* Central directory entry */
+        {
+          char header[46];
+          char* comment = "";
+          int comsize = (int) strlen(comment);
+          WRITE_32(header, 0x02014b50);
+          WRITE_16(header + 4, version);
+          WRITE_16(header + 6, version);
+          WRITE_16(header + 8, gpflag);
+          WRITE_16(header + 10, method);
+          WRITE_16(header + 12, filetime);
+          WRITE_16(header + 14, filedate);
+          WRITE_32(header + 16, crc);
+          WRITE_32(header + 20, cpsize);
+          WRITE_32(header + 24, uncpsize);
+          WRITE_16(header + 28, fnsize);
+          WRITE_16(header + 30, extsize);
+          WRITE_16(header + 32, comsize);
+          WRITE_16(header + 34, 0);     /* disk # */
+          WRITE_16(header + 36, 0);     /* int attrb */
+          WRITE_32(header + 38, 0);     /* ext attrb */
+          WRITE_32(header + 42, currentOffset);
+          /* Header */
+          if (fwrite(header, 1, 46, fpOutCD) == 46) {
+            offsetCD += 46;
+            
+            /* Filename */
+            if (fnsize > 0) {
+              if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) {
+                offsetCD += fnsize;
+              } else {
+                err = Z_ERRNO;
+                break;
+              }
+            } else {
+              err = Z_STREAM_ERROR;
+              break;
+            }
+            
+            /* Extra field */
+            if (extsize > 0) {
+              if (fwrite(extra, 1, extsize, fpOutCD) == extsize) {
+                offsetCD += extsize;
+              } else {
+                err = Z_ERRNO;
+                break;
+              }
+            }
+            
+            /* Comment field */
+            if (comsize > 0) {
+              if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) {
+                offsetCD += comsize;
+              } else {
+                err = Z_ERRNO;
+                break;
+              }
+            }
+            
+            
+          } else {
+            err = Z_ERRNO;
+            break;
+          }
+        }
+
+        /* Success */
+        entries++;
+
+      } else {
+        break;
+      }
+    }
+
+    /* Final central directory  */
+    {
+      int entriesZip = entries;
+      char header[22];
+      char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools";
+      int comsize = (int) strlen(comment);
+      if (entriesZip > 0xffff) {
+        entriesZip = 0xffff;
+      }
+      WRITE_32(header, 0x06054b50);
+      WRITE_16(header + 4, 0);    /* disk # */
+      WRITE_16(header + 6, 0);    /* disk # */
+      WRITE_16(header + 8, entriesZip);   /* hack */
+      WRITE_16(header + 10, entriesZip);  /* hack */
+      WRITE_32(header + 12, offsetCD);    /* size of CD */
+      WRITE_32(header + 16, offset);      /* offset to CD */
+      WRITE_16(header + 20, comsize);     /* comment */
+      
+      /* Header */
+      if (fwrite(header, 1, 22, fpOutCD) == 22) {
+        
+        /* Comment field */
+        if (comsize > 0) {
+          if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) {
+            err = Z_ERRNO;
+          }
+        }
+        
+      } else {
+        err = Z_ERRNO;
+      }
+    }
+
+    /* Final merge (file + central directory) */
+    fclose(fpOutCD);
+    if (err == Z_OK) {
+      fpOutCD = fopen(fileOutTmp, "rb");
+      if (fpOutCD != NULL) {
+        int nRead;
+        char buffer[8192];
+        while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) {
+          if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) {
+            err = Z_ERRNO;
+            break;
+          }
+        }
+        fclose(fpOutCD);
+      }
+    }
+    
+    /* Close */
+    fclose(fpZip);
+    fclose(fpOut);
+    
+    /* Wipe temporary file */
+    (void)remove(fileOutTmp);
+    
+    /* Number of recovered entries */
+    if (err == Z_OK) {
+      if (nRecovered != NULL) {
+        *nRecovered = entries;
+      }
+      if (bytesRecovered != NULL) {
+        *bytesRecovered = totalBytes;
+      }
+    }
+  } else {
+    err = Z_STREAM_ERROR;
+  }
+  return err;
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/minizip/mztools.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/minizip/mztools.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/minizip/mztools.h	(revision 9)
@@ -0,0 +1,31 @@
+/*
+  Additional tools for Minizip
+  Code: Xavier Roche '2004
+  License: Same as ZLIB (www.gzip.org)
+*/
+
+#ifndef _zip_tools_H
+#define _zip_tools_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _ZLIB_H
+#include "zlib.h"
+#endif
+
+#include "unzip.h"
+
+/* Repair a ZIP file (missing central directory) 
+   file: file to recover
+   fileOut: output file after recovery
+   fileOutTmp: temporary file name used for recovery
+*/
+extern int ZEXPORT unzRepair(const char* file, 
+                             const char* fileOut, 
+                             const char* fileOutTmp, 
+                             uLong* nRecovered,
+                             uLong* bytesRecovered);
+
+#endif
Index: /trunk/minix/lib/zlib-1.2.3/contrib/minizip/unzip.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/minizip/unzip.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/minizip/unzip.c	(revision 9)
@@ -0,0 +1,1598 @@
+/* unzip.c -- IO for uncompress .zip files using zlib
+   Version 1.01e, February 12th, 2005
+
+   Copyright (C) 1998-2005 Gilles Vollant
+
+   Read unzip.h for more info
+*/
+
+/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
+compatibility with older software. The following is from the original crypt.c. Code
+woven in by Terry Thorsen 1/2003.
+*/
+/*
+  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2000-Apr-09 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, all these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+  crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
+
+  The encryption/decryption parts of this source code (as opposed to the
+  non-echoing password parts) were originally written in Europe.  The
+  whole source package can be freely distributed, including from the USA.
+  (Prior to January 2000, re-export from the US was a violation of US law.)
+ */
+
+/*
+  This encryption code is a direct transcription of the algorithm from
+  Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
+  file (appnote.txt) is distributed with the PKZIP program (even in the
+  version without encryption capabilities).
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "zlib.h"
+#include "unzip.h"
+
+#ifdef STDC
+#  include <stddef.h>
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+    extern int errno;
+#else
+#   include <errno.h>
+#endif
+
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+
+#ifndef CASESENSITIVITYDEFAULT_NO
+#  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
+#    define CASESENSITIVITYDEFAULT_NO
+#  endif
+#endif
+
+
+#ifndef UNZ_BUFSIZE
+#define UNZ_BUFSIZE (16384)
+#endif
+
+#ifndef UNZ_MAXFILENAMEINZIP
+#define UNZ_MAXFILENAMEINZIP (256)
+#endif
+
+#ifndef ALLOC
+# define ALLOC(size) (malloc(size))
+#endif
+#ifndef TRYFREE
+# define TRYFREE(p) {if (p) free(p);}
+#endif
+
+#define SIZECENTRALDIRITEM (0x2e)
+#define SIZEZIPLOCALHEADER (0x1e)
+
+
+
+
+const char unz_copyright[] =
+   " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
+
+/* unz_file_info_interntal contain internal info about a file in zipfile*/
+typedef struct unz_file_info_internal_s
+{
+    uLong offset_curfile;/* relative offset of local header 4 bytes */
+} unz_file_info_internal;
+
+
+/* file_in_zip_read_info_s contain internal information about a file in zipfile,
+    when reading and decompress it */
+typedef struct
+{
+    char  *read_buffer;         /* internal buffer for compressed data */
+    z_stream stream;            /* zLib stream structure for inflate */
+
+    uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
+    uLong stream_initialised;   /* flag set if stream structure is initialised*/
+
+    uLong offset_local_extrafield;/* offset of the local extra field */
+    uInt  size_local_extrafield;/* size of the local extra field */
+    uLong pos_local_extrafield;   /* position in the local extra field in read*/
+
+    uLong crc32;                /* crc32 of all data uncompressed */
+    uLong crc32_wait;           /* crc32 we must obtain after decompress all */
+    uLong rest_read_compressed; /* number of byte to be decompressed */
+    uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
+    zlib_filefunc_def z_filefunc;
+    voidpf filestream;        /* io structore of the zipfile */
+    uLong compression_method;   /* compression method (0==store) */
+    uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+    int   raw;
+} file_in_zip_read_info_s;
+
+
+/* unz_s contain internal information about the zipfile
+*/
+typedef struct
+{
+    zlib_filefunc_def z_filefunc;
+    voidpf filestream;        /* io structore of the zipfile */
+    unz_global_info gi;       /* public global information */
+    uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+    uLong num_file;             /* number of the current file in the zipfile*/
+    uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
+    uLong current_file_ok;      /* flag about the usability of the current file*/
+    uLong central_pos;          /* position of the beginning of the central dir*/
+
+    uLong size_central_dir;     /* size of the central directory  */
+    uLong offset_central_dir;   /* offset of start of central directory with
+                                   respect to the starting disk number */
+
+    unz_file_info cur_file_info; /* public info about the current file in zip*/
+    unz_file_info_internal cur_file_info_internal; /* private info about it*/
+    file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
+                                        file if we are decompressing it */
+    int encrypted;
+#    ifndef NOUNCRYPT
+    unsigned long keys[3];     /* keys defining the pseudo-random sequence */
+    const unsigned long* pcrc_32_tab;
+#    endif
+} unz_s;
+
+
+#ifndef NOUNCRYPT
+#include "crypt.h"
+#endif
+
+/* ===========================================================================
+     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+   for end of file.
+   IN assertion: the stream s has been sucessfully opened for reading.
+*/
+
+
+local int unzlocal_getByte OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream,
+    int *pi));
+
+local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
+    int *pi;
+{
+    unsigned char c;
+    int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
+    if (err==1)
+    {
+        *pi = (int)c;
+        return UNZ_OK;
+    }
+    else
+    {
+        if (ZERROR(*pzlib_filefunc_def,filestream))
+            return UNZ_ERRNO;
+        else
+            return UNZ_EOF;
+    }
+}
+
+
+/* ===========================================================================
+   Reads a long in LSB order from the given gz_stream. Sets
+*/
+local int unzlocal_getShort OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream,
+    uLong *pX));
+
+local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
+    uLong *pX;
+{
+    uLong x ;
+    int i;
+    int err;
+
+    err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x = (uLong)i;
+
+    if (err==UNZ_OK)
+        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x += ((uLong)i)<<8;
+
+    if (err==UNZ_OK)
+        *pX = x;
+    else
+        *pX = 0;
+    return err;
+}
+
+local int unzlocal_getLong OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream,
+    uLong *pX));
+
+local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
+    uLong *pX;
+{
+    uLong x ;
+    int i;
+    int err;
+
+    err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x = (uLong)i;
+
+    if (err==UNZ_OK)
+        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x += ((uLong)i)<<8;
+
+    if (err==UNZ_OK)
+        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x += ((uLong)i)<<16;
+
+    if (err==UNZ_OK)
+        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x += ((uLong)i)<<24;
+
+    if (err==UNZ_OK)
+        *pX = x;
+    else
+        *pX = 0;
+    return err;
+}
+
+
+/* My own strcmpi / strcasecmp */
+local int strcmpcasenosensitive_internal (fileName1,fileName2)
+    const char* fileName1;
+    const char* fileName2;
+{
+    for (;;)
+    {
+        char c1=*(fileName1++);
+        char c2=*(fileName2++);
+        if ((c1>='a') && (c1<='z'))
+            c1 -= 0x20;
+        if ((c2>='a') && (c2<='z'))
+            c2 -= 0x20;
+        if (c1=='\0')
+            return ((c2=='\0') ? 0 : -1);
+        if (c2=='\0')
+            return 1;
+        if (c1<c2)
+            return -1;
+        if (c1>c2)
+            return 1;
+    }
+}
+
+
+#ifdef  CASESENSITIVITYDEFAULT_NO
+#define CASESENSITIVITYDEFAULTVALUE 2
+#else
+#define CASESENSITIVITYDEFAULTVALUE 1
+#endif
+
+#ifndef STRCMPCASENOSENTIVEFUNCTION
+#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
+#endif
+
+/*
+   Compare two filename (fileName1,fileName2).
+   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+                                                                or strcasecmp)
+   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+        (like 1 on Unix, 2 on Windows)
+
+*/
+extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
+    const char* fileName1;
+    const char* fileName2;
+    int iCaseSensitivity;
+{
+    if (iCaseSensitivity==0)
+        iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
+
+    if (iCaseSensitivity==1)
+        return strcmp(fileName1,fileName2);
+
+    return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
+}
+
+#ifndef BUFREADCOMMENT
+#define BUFREADCOMMENT (0x400)
+#endif
+
+/*
+  Locate the Central directory of a zipfile (at the end, just before
+    the global comment)
+*/
+local uLong unzlocal_SearchCentralDir OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream));
+
+local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
+{
+    unsigned char* buf;
+    uLong uSizeFile;
+    uLong uBackRead;
+    uLong uMaxBack=0xffff; /* maximum size of global comment */
+    uLong uPosFound=0;
+
+    if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+        return 0;
+
+
+    uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
+
+    if (uMaxBack>uSizeFile)
+        uMaxBack = uSizeFile;
+
+    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+    if (buf==NULL)
+        return 0;
+
+    uBackRead = 4;
+    while (uBackRead<uMaxBack)
+    {
+        uLong uReadSize,uReadPos ;
+        int i;
+        if (uBackRead+BUFREADCOMMENT>uMaxBack)
+            uBackRead = uMaxBack;
+        else
+            uBackRead+=BUFREADCOMMENT;
+        uReadPos = uSizeFile-uBackRead ;
+
+        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
+        if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            break;
+
+        if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+            break;
+
+        for (i=(int)uReadSize-3; (i--)>0;)
+            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+            {
+                uPosFound = uReadPos+i;
+                break;
+            }
+
+        if (uPosFound!=0)
+            break;
+    }
+    TRYFREE(buf);
+    return uPosFound;
+}
+
+/*
+  Open a Zip file. path contain the full pathname (by example,
+     on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
+     "zlib/zlib114.zip".
+     If the zipfile cannot be opened (file doesn't exist or in not valid), the
+       return value is NULL.
+     Else, the return value is a unzFile Handle, usable with other function
+       of this unzip package.
+*/
+extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
+    const char *path;
+    zlib_filefunc_def* pzlib_filefunc_def;
+{
+    unz_s us;
+    unz_s *s;
+    uLong central_pos,uL;
+
+    uLong number_disk;          /* number of the current dist, used for
+                                   spaning ZIP, unsupported, always 0*/
+    uLong number_disk_with_CD;  /* number the the disk with central dir, used
+                                   for spaning ZIP, unsupported, always 0*/
+    uLong number_entry_CD;      /* total number of entries in
+                                   the central dir
+                                   (same than number_entry on nospan) */
+
+    int err=UNZ_OK;
+
+    if (unz_copyright[0]!=' ')
+        return NULL;
+
+    if (pzlib_filefunc_def==NULL)
+        fill_fopen_filefunc(&us.z_filefunc);
+    else
+        us.z_filefunc = *pzlib_filefunc_def;
+
+    us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
+                                                 path,
+                                                 ZLIB_FILEFUNC_MODE_READ |
+                                                 ZLIB_FILEFUNC_MODE_EXISTING);
+    if (us.filestream==NULL)
+        return NULL;
+
+    central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
+    if (central_pos==0)
+        err=UNZ_ERRNO;
+
+    if (ZSEEK(us.z_filefunc, us.filestream,
+                                      central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        err=UNZ_ERRNO;
+
+    /* the signature, already checked */
+    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+        err=UNZ_ERRNO;
+
+    /* number of this disk */
+    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+        err=UNZ_ERRNO;
+
+    /* number of the disk with the start of the central directory */
+    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+        err=UNZ_ERRNO;
+
+    /* total number of entries in the central dir on this disk */
+    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
+        err=UNZ_ERRNO;
+
+    /* total number of entries in the central dir */
+    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if ((number_entry_CD!=us.gi.number_entry) ||
+        (number_disk_with_CD!=0) ||
+        (number_disk!=0))
+        err=UNZ_BADZIPFILE;
+
+    /* size of the central directory */
+    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
+        err=UNZ_ERRNO;
+
+    /* offset of start of central directory with respect to the
+          starting disk number */
+    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
+        err=UNZ_ERRNO;
+
+    /* zipfile comment length */
+    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
+        (err==UNZ_OK))
+        err=UNZ_BADZIPFILE;
+
+    if (err!=UNZ_OK)
+    {
+        ZCLOSE(us.z_filefunc, us.filestream);
+        return NULL;
+    }
+
+    us.byte_before_the_zipfile = central_pos -
+                            (us.offset_central_dir+us.size_central_dir);
+    us.central_pos = central_pos;
+    us.pfile_in_zip_read = NULL;
+    us.encrypted = 0;
+
+
+    s=(unz_s*)ALLOC(sizeof(unz_s));
+    *s=us;
+    unzGoToFirstFile((unzFile)s);
+    return (unzFile)s;
+}
+
+
+extern unzFile ZEXPORT unzOpen (path)
+    const char *path;
+{
+    return unzOpen2(path, NULL);
+}
+
+/*
+  Close a ZipFile opened with unzipOpen.
+  If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
+    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+  return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzClose (file)
+    unzFile file;
+{
+    unz_s* s;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+
+    if (s->pfile_in_zip_read!=NULL)
+        unzCloseCurrentFile(file);
+
+    ZCLOSE(s->z_filefunc, s->filestream);
+    TRYFREE(s);
+    return UNZ_OK;
+}
+
+
+/*
+  Write info about the ZipFile in the *pglobal_info structure.
+  No preparation of the structure is needed
+  return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
+    unzFile file;
+    unz_global_info *pglobal_info;
+{
+    unz_s* s;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    *pglobal_info=s->gi;
+    return UNZ_OK;
+}
+
+
+/*
+   Translate date/time from Dos format to tm_unz (readable more easilty)
+*/
+local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
+    uLong ulDosDate;
+    tm_unz* ptm;
+{
+    uLong uDate;
+    uDate = (uLong)(ulDosDate>>16);
+    ptm->tm_mday = (uInt)(uDate&0x1f) ;
+    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
+    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
+
+    ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
+    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
+    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
+}
+
+/*
+  Get Info about the current file in the zipfile, with internal only info
+*/
+local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
+                                                  unz_file_info *pfile_info,
+                                                  unz_file_info_internal
+                                                  *pfile_info_internal,
+                                                  char *szFileName,
+                                                  uLong fileNameBufferSize,
+                                                  void *extraField,
+                                                  uLong extraFieldBufferSize,
+                                                  char *szComment,
+                                                  uLong commentBufferSize));
+
+local int unzlocal_GetCurrentFileInfoInternal (file,
+                                              pfile_info,
+                                              pfile_info_internal,
+                                              szFileName, fileNameBufferSize,
+                                              extraField, extraFieldBufferSize,
+                                              szComment,  commentBufferSize)
+    unzFile file;
+    unz_file_info *pfile_info;
+    unz_file_info_internal *pfile_info_internal;
+    char *szFileName;
+    uLong fileNameBufferSize;
+    void *extraField;
+    uLong extraFieldBufferSize;
+    char *szComment;
+    uLong commentBufferSize;
+{
+    unz_s* s;
+    unz_file_info file_info;
+    unz_file_info_internal file_info_internal;
+    int err=UNZ_OK;
+    uLong uMagic;
+    long lSeek=0;
+
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    if (ZSEEK(s->z_filefunc, s->filestream,
+              s->pos_in_central_dir+s->byte_before_the_zipfile,
+              ZLIB_FILEFUNC_SEEK_SET)!=0)
+        err=UNZ_ERRNO;
+
+
+    /* we check the magic */
+    if (err==UNZ_OK)
+        if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+            err=UNZ_ERRNO;
+        else if (uMagic!=0x02014b50)
+            err=UNZ_BADZIPFILE;
+
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
+
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    lSeek+=file_info.size_filename;
+    if ((err==UNZ_OK) && (szFileName!=NULL))
+    {
+        uLong uSizeRead ;
+        if (file_info.size_filename<fileNameBufferSize)
+        {
+            *(szFileName+file_info.size_filename)='\0';
+            uSizeRead = file_info.size_filename;
+        }
+        else
+            uSizeRead = fileNameBufferSize;
+
+        if ((file_info.size_filename>0) && (fileNameBufferSize>0))
+            if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
+                err=UNZ_ERRNO;
+        lSeek -= uSizeRead;
+    }
+
+
+    if ((err==UNZ_OK) && (extraField!=NULL))
+    {
+        uLong uSizeRead ;
+        if (file_info.size_file_extra<extraFieldBufferSize)
+            uSizeRead = file_info.size_file_extra;
+        else
+            uSizeRead = extraFieldBufferSize;
+
+        if (lSeek!=0)
+            if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+                lSeek=0;
+            else
+                err=UNZ_ERRNO;
+        if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
+            if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
+                err=UNZ_ERRNO;
+        lSeek += file_info.size_file_extra - uSizeRead;
+    }
+    else
+        lSeek+=file_info.size_file_extra;
+
+
+    if ((err==UNZ_OK) && (szComment!=NULL))
+    {
+        uLong uSizeRead ;
+        if (file_info.size_file_comment<commentBufferSize)
+        {
+            *(szComment+file_info.size_file_comment)='\0';
+            uSizeRead = file_info.size_file_comment;
+        }
+        else
+            uSizeRead = commentBufferSize;
+
+        if (lSeek!=0)
+            if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+                lSeek=0;
+            else
+                err=UNZ_ERRNO;
+        if ((file_info.size_file_comment>0) && (commentBufferSize>0))
+            if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
+                err=UNZ_ERRNO;
+        lSeek+=file_info.size_file_comment - uSizeRead;
+    }
+    else
+        lSeek+=file_info.size_file_comment;
+
+    if ((err==UNZ_OK) && (pfile_info!=NULL))
+        *pfile_info=file_info;
+
+    if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
+        *pfile_info_internal=file_info_internal;
+
+    return err;
+}
+
+
+
+/*
+  Write info about the ZipFile in the *pglobal_info structure.
+  No preparation of the structure is needed
+  return UNZ_OK if there is no problem.
+*/
+extern int ZEXPORT unzGetCurrentFileInfo (file,
+                                          pfile_info,
+                                          szFileName, fileNameBufferSize,
+                                          extraField, extraFieldBufferSize,
+                                          szComment,  commentBufferSize)
+    unzFile file;
+    unz_file_info *pfile_info;
+    char *szFileName;
+    uLong fileNameBufferSize;
+    void *extraField;
+    uLong extraFieldBufferSize;
+    char *szComment;
+    uLong commentBufferSize;
+{
+    return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
+                                                szFileName,fileNameBufferSize,
+                                                extraField,extraFieldBufferSize,
+                                                szComment,commentBufferSize);
+}
+
+/*
+  Set the current file of the zipfile to the first file.
+  return UNZ_OK if there is no problem
+*/
+extern int ZEXPORT unzGoToFirstFile (file)
+    unzFile file;
+{
+    int err=UNZ_OK;
+    unz_s* s;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    s->pos_in_central_dir=s->offset_central_dir;
+    s->num_file=0;
+    err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+                                             &s->cur_file_info_internal,
+                                             NULL,0,NULL,0,NULL,0);
+    s->current_file_ok = (err == UNZ_OK);
+    return err;
+}
+
+/*
+  Set the current file of the zipfile to the next file.
+  return UNZ_OK if there is no problem
+  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+extern int ZEXPORT unzGoToNextFile (file)
+    unzFile file;
+{
+    unz_s* s;
+    int err;
+
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    if (!s->current_file_ok)
+        return UNZ_END_OF_LIST_OF_FILE;
+    if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
+      if (s->num_file+1==s->gi.number_entry)
+        return UNZ_END_OF_LIST_OF_FILE;
+
+    s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
+            s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
+    s->num_file++;
+    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+                                               &s->cur_file_info_internal,
+                                               NULL,0,NULL,0,NULL,0);
+    s->current_file_ok = (err == UNZ_OK);
+    return err;
+}
+
+
+/*
+  Try locate the file szFileName in the zipfile.
+  For the iCaseSensitivity signification, see unzipStringFileNameCompare
+
+  return value :
+  UNZ_OK if the file is found. It becomes the current file.
+  UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
+    unzFile file;
+    const char *szFileName;
+    int iCaseSensitivity;
+{
+    unz_s* s;
+    int err;
+
+    /* We remember the 'current' position in the file so that we can jump
+     * back there if we fail.
+     */
+    unz_file_info cur_file_infoSaved;
+    unz_file_info_internal cur_file_info_internalSaved;
+    uLong num_fileSaved;
+    uLong pos_in_central_dirSaved;
+
+
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+
+    if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
+        return UNZ_PARAMERROR;
+
+    s=(unz_s*)file;
+    if (!s->current_file_ok)
+        return UNZ_END_OF_LIST_OF_FILE;
+
+    /* Save the current state */
+    num_fileSaved = s->num_file;
+    pos_in_central_dirSaved = s->pos_in_central_dir;
+    cur_file_infoSaved = s->cur_file_info;
+    cur_file_info_internalSaved = s->cur_file_info_internal;
+
+    err = unzGoToFirstFile(file);
+
+    while (err == UNZ_OK)
+    {
+        char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
+        err = unzGetCurrentFileInfo(file,NULL,
+                                    szCurrentFileName,sizeof(szCurrentFileName)-1,
+                                    NULL,0,NULL,0);
+        if (err == UNZ_OK)
+        {
+            if (unzStringFileNameCompare(szCurrentFileName,
+                                            szFileName,iCaseSensitivity)==0)
+                return UNZ_OK;
+            err = unzGoToNextFile(file);
+        }
+    }
+
+    /* We failed, so restore the state of the 'current file' to where we
+     * were.
+     */
+    s->num_file = num_fileSaved ;
+    s->pos_in_central_dir = pos_in_central_dirSaved ;
+    s->cur_file_info = cur_file_infoSaved;
+    s->cur_file_info_internal = cur_file_info_internalSaved;
+    return err;
+}
+
+
+/*
+///////////////////////////////////////////
+// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
+// I need random access
+//
+// Further optimization could be realized by adding an ability
+// to cache the directory in memory. The goal being a single
+// comprehensive file read to put the file I need in a memory.
+*/
+
+/*
+typedef struct unz_file_pos_s
+{
+    uLong pos_in_zip_directory;   // offset in file
+    uLong num_of_file;            // # of file
+} unz_file_pos;
+*/
+
+extern int ZEXPORT unzGetFilePos(file, file_pos)
+    unzFile file;
+    unz_file_pos* file_pos;
+{
+    unz_s* s;
+
+    if (file==NULL || file_pos==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    if (!s->current_file_ok)
+        return UNZ_END_OF_LIST_OF_FILE;
+
+    file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
+    file_pos->num_of_file           = s->num_file;
+
+    return UNZ_OK;
+}
+
+extern int ZEXPORT unzGoToFilePos(file, file_pos)
+    unzFile file;
+    unz_file_pos* file_pos;
+{
+    unz_s* s;
+    int err;
+
+    if (file==NULL || file_pos==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+
+    /* jump to the right spot */
+    s->pos_in_central_dir = file_pos->pos_in_zip_directory;
+    s->num_file           = file_pos->num_of_file;
+
+    /* set the current file */
+    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+                                               &s->cur_file_info_internal,
+                                               NULL,0,NULL,0,NULL,0);
+    /* return results */
+    s->current_file_ok = (err == UNZ_OK);
+    return err;
+}
+
+/*
+// Unzip Helper Functions - should be here?
+///////////////////////////////////////////
+*/
+
+/*
+  Read the local header of the current zipfile
+  Check the coherency of the local header and info in the end of central
+        directory about this file
+  store in *piSizeVar the size of extra info in local header
+        (filename and size of extra field data)
+*/
+local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
+                                                    poffset_local_extrafield,
+                                                    psize_local_extrafield)
+    unz_s* s;
+    uInt* piSizeVar;
+    uLong *poffset_local_extrafield;
+    uInt  *psize_local_extrafield;
+{
+    uLong uMagic,uData,uFlags;
+    uLong size_filename;
+    uLong size_extra_field;
+    int err=UNZ_OK;
+
+    *piSizeVar = 0;
+    *poffset_local_extrafield = 0;
+    *psize_local_extrafield = 0;
+
+    if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
+                                s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        return UNZ_ERRNO;
+
+
+    if (err==UNZ_OK)
+        if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+            err=UNZ_ERRNO;
+        else if (uMagic!=0x04034b50)
+            err=UNZ_BADZIPFILE;
+
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+        err=UNZ_ERRNO;
+/*
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
+        err=UNZ_BADZIPFILE;
+*/
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
+        err=UNZ_ERRNO;
+
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+        err=UNZ_ERRNO;
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
+        err=UNZ_BADZIPFILE;
+
+    if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
+                         (s->cur_file_info.compression_method!=Z_DEFLATED))
+        err=UNZ_BADZIPFILE;
+
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
+        err=UNZ_ERRNO;
+
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
+        err=UNZ_ERRNO;
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
+                              ((uFlags & 8)==0))
+        err=UNZ_BADZIPFILE;
+
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
+        err=UNZ_ERRNO;
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
+                              ((uFlags & 8)==0))
+        err=UNZ_BADZIPFILE;
+
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
+        err=UNZ_ERRNO;
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
+                              ((uFlags & 8)==0))
+        err=UNZ_BADZIPFILE;
+
+
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
+        err=UNZ_ERRNO;
+    else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
+        err=UNZ_BADZIPFILE;
+
+    *piSizeVar += (uInt)size_filename;
+
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
+        err=UNZ_ERRNO;
+    *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
+                                    SIZEZIPLOCALHEADER + size_filename;
+    *psize_local_extrafield = (uInt)size_extra_field;
+
+    *piSizeVar += (uInt)size_extra_field;
+
+    return err;
+}
+
+/*
+  Open for reading data the current file in the zipfile.
+  If there is no error and the file is opened, the return value is UNZ_OK.
+*/
+extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
+    unzFile file;
+    int* method;
+    int* level;
+    int raw;
+    const char* password;
+{
+    int err=UNZ_OK;
+    uInt iSizeVar;
+    unz_s* s;
+    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    uLong offset_local_extrafield;  /* offset of the local extra field */
+    uInt  size_local_extrafield;    /* size of the local extra field */
+#    ifndef NOUNCRYPT
+    char source[12];
+#    else
+    if (password != NULL)
+        return UNZ_PARAMERROR;
+#    endif
+
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    if (!s->current_file_ok)
+        return UNZ_PARAMERROR;
+
+    if (s->pfile_in_zip_read != NULL)
+        unzCloseCurrentFile(file);
+
+    if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
+                &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
+        return UNZ_BADZIPFILE;
+
+    pfile_in_zip_read_info = (file_in_zip_read_info_s*)
+                                        ALLOC(sizeof(file_in_zip_read_info_s));
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_INTERNALERROR;
+
+    pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
+    pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
+    pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
+    pfile_in_zip_read_info->pos_local_extrafield=0;
+    pfile_in_zip_read_info->raw=raw;
+
+    if (pfile_in_zip_read_info->read_buffer==NULL)
+    {
+        TRYFREE(pfile_in_zip_read_info);
+        return UNZ_INTERNALERROR;
+    }
+
+    pfile_in_zip_read_info->stream_initialised=0;
+
+    if (method!=NULL)
+        *method = (int)s->cur_file_info.compression_method;
+
+    if (level!=NULL)
+    {
+        *level = 6;
+        switch (s->cur_file_info.flag & 0x06)
+        {
+          case 6 : *level = 1; break;
+          case 4 : *level = 2; break;
+          case 2 : *level = 9; break;
+        }
+    }
+
+    if ((s->cur_file_info.compression_method!=0) &&
+        (s->cur_file_info.compression_method!=Z_DEFLATED))
+        err=UNZ_BADZIPFILE;
+
+    pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
+    pfile_in_zip_read_info->crc32=0;
+    pfile_in_zip_read_info->compression_method =
+            s->cur_file_info.compression_method;
+    pfile_in_zip_read_info->filestream=s->filestream;
+    pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
+    pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
+
+    pfile_in_zip_read_info->stream.total_out = 0;
+
+    if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
+        (!raw))
+    {
+      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+      pfile_in_zip_read_info->stream.zfree = (free_func)0;
+      pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+      pfile_in_zip_read_info->stream.next_in = (voidpf)0;
+      pfile_in_zip_read_info->stream.avail_in = 0;
+
+      err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
+      if (err == Z_OK)
+        pfile_in_zip_read_info->stream_initialised=1;
+      else
+      {
+        TRYFREE(pfile_in_zip_read_info);
+        return err;
+      }
+        /* windowBits is passed < 0 to tell that there is no zlib header.
+         * Note that in this case inflate *requires* an extra "dummy" byte
+         * after the compressed stream in order to complete decompression and
+         * return Z_STREAM_END.
+         * In unzip, i don't wait absolutely Z_STREAM_END because I known the
+         * size of both compressed and uncompressed data
+         */
+    }
+    pfile_in_zip_read_info->rest_read_compressed =
+            s->cur_file_info.compressed_size ;
+    pfile_in_zip_read_info->rest_read_uncompressed =
+            s->cur_file_info.uncompressed_size ;
+
+
+    pfile_in_zip_read_info->pos_in_zipfile =
+            s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
+              iSizeVar;
+
+    pfile_in_zip_read_info->stream.avail_in = (uInt)0;
+
+    s->pfile_in_zip_read = pfile_in_zip_read_info;
+
+#    ifndef NOUNCRYPT
+    if (password != NULL)
+    {
+        int i;
+        s->pcrc_32_tab = get_crc_table();
+        init_keys(password,s->keys,s->pcrc_32_tab);
+        if (ZSEEK(s->z_filefunc, s->filestream,
+                  s->pfile_in_zip_read->pos_in_zipfile +
+                     s->pfile_in_zip_read->byte_before_the_zipfile,
+                  SEEK_SET)!=0)
+            return UNZ_INTERNALERROR;
+        if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
+            return UNZ_INTERNALERROR;
+
+        for (i = 0; i<12; i++)
+            zdecode(s->keys,s->pcrc_32_tab,source[i]);
+
+        s->pfile_in_zip_read->pos_in_zipfile+=12;
+        s->encrypted=1;
+    }
+#    endif
+
+
+    return UNZ_OK;
+}
+
+extern int ZEXPORT unzOpenCurrentFile (file)
+    unzFile file;
+{
+    return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
+}
+
+extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
+    unzFile file;
+    const char* password;
+{
+    return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
+}
+
+extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
+    unzFile file;
+    int* method;
+    int* level;
+    int raw;
+{
+    return unzOpenCurrentFile3(file, method, level, raw, NULL);
+}
+
+/*
+  Read bytes from the current file.
+  buf contain buffer where data must be copied
+  len the size of buf.
+
+  return the number of byte copied if somes bytes are copied
+  return 0 if the end of file was reached
+  return <0 with error code if there is an error
+    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
+    unzFile file;
+    voidp buf;
+    unsigned len;
+{
+    int err=UNZ_OK;
+    uInt iRead = 0;
+    unz_s* s;
+    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_PARAMERROR;
+
+
+    if ((pfile_in_zip_read_info->read_buffer == NULL))
+        return UNZ_END_OF_LIST_OF_FILE;
+    if (len==0)
+        return 0;
+
+    pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
+
+    pfile_in_zip_read_info->stream.avail_out = (uInt)len;
+
+    if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
+        (!(pfile_in_zip_read_info->raw)))
+        pfile_in_zip_read_info->stream.avail_out =
+            (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
+
+    if ((len>pfile_in_zip_read_info->rest_read_compressed+
+           pfile_in_zip_read_info->stream.avail_in) &&
+         (pfile_in_zip_read_info->raw))
+        pfile_in_zip_read_info->stream.avail_out =
+            (uInt)pfile_in_zip_read_info->rest_read_compressed+
+            pfile_in_zip_read_info->stream.avail_in;
+
+    while (pfile_in_zip_read_info->stream.avail_out>0)
+    {
+        if ((pfile_in_zip_read_info->stream.avail_in==0) &&
+            (pfile_in_zip_read_info->rest_read_compressed>0))
+        {
+            uInt uReadThis = UNZ_BUFSIZE;
+            if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
+                uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
+            if (uReadThis == 0)
+                return UNZ_EOF;
+            if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
+                      pfile_in_zip_read_info->filestream,
+                      pfile_in_zip_read_info->pos_in_zipfile +
+                         pfile_in_zip_read_info->byte_before_the_zipfile,
+                         ZLIB_FILEFUNC_SEEK_SET)!=0)
+                return UNZ_ERRNO;
+            if (ZREAD(pfile_in_zip_read_info->z_filefunc,
+                      pfile_in_zip_read_info->filestream,
+                      pfile_in_zip_read_info->read_buffer,
+                      uReadThis)!=uReadThis)
+                return UNZ_ERRNO;
+
+
+#            ifndef NOUNCRYPT
+            if(s->encrypted)
+            {
+                uInt i;
+                for(i=0;i<uReadThis;i++)
+                  pfile_in_zip_read_info->read_buffer[i] =
+                      zdecode(s->keys,s->pcrc_32_tab,
+                              pfile_in_zip_read_info->read_buffer[i]);
+            }
+#            endif
+
+
+            pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+
+            pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
+
+            pfile_in_zip_read_info->stream.next_in =
+                (Bytef*)pfile_in_zip_read_info->read_buffer;
+            pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
+        }
+
+        if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
+        {
+            uInt uDoCopy,i ;
+
+            if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
+                (pfile_in_zip_read_info->rest_read_compressed == 0))
+                return (iRead==0) ? UNZ_EOF : iRead;
+
+            if (pfile_in_zip_read_info->stream.avail_out <
+                            pfile_in_zip_read_info->stream.avail_in)
+                uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
+            else
+                uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
+
+            for (i=0;i<uDoCopy;i++)
+                *(pfile_in_zip_read_info->stream.next_out+i) =
+                        *(pfile_in_zip_read_info->stream.next_in+i);
+
+            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
+                                pfile_in_zip_read_info->stream.next_out,
+                                uDoCopy);
+            pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
+            pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
+            pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
+            pfile_in_zip_read_info->stream.next_out += uDoCopy;
+            pfile_in_zip_read_info->stream.next_in += uDoCopy;
+            pfile_in_zip_read_info->stream.total_out += uDoCopy;
+            iRead += uDoCopy;
+        }
+        else
+        {
+            uLong uTotalOutBefore,uTotalOutAfter;
+            const Bytef *bufBefore;
+            uLong uOutThis;
+            int flush=Z_SYNC_FLUSH;
+
+            uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
+            bufBefore = pfile_in_zip_read_info->stream.next_out;
+
+            /*
+            if ((pfile_in_zip_read_info->rest_read_uncompressed ==
+                     pfile_in_zip_read_info->stream.avail_out) &&
+                (pfile_in_zip_read_info->rest_read_compressed == 0))
+                flush = Z_FINISH;
+            */
+            err=inflate(&pfile_in_zip_read_info->stream,flush);
+
+            if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
+              err = Z_DATA_ERROR;
+
+            uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
+            uOutThis = uTotalOutAfter-uTotalOutBefore;
+
+            pfile_in_zip_read_info->crc32 =
+                crc32(pfile_in_zip_read_info->crc32,bufBefore,
+                        (uInt)(uOutThis));
+
+            pfile_in_zip_read_info->rest_read_uncompressed -=
+                uOutThis;
+
+            iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
+
+            if (err==Z_STREAM_END)
+                return (iRead==0) ? UNZ_EOF : iRead;
+            if (err!=Z_OK)
+                break;
+        }
+    }
+
+    if (err==Z_OK)
+        return iRead;
+    return err;
+}
+
+
+/*
+  Give the current position in uncompressed data
+*/
+extern z_off_t ZEXPORT unztell (file)
+    unzFile file;
+{
+    unz_s* s;
+    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_PARAMERROR;
+
+    return (z_off_t)pfile_in_zip_read_info->stream.total_out;
+}
+
+
+/*
+  return 1 if the end of file was reached, 0 elsewhere
+*/
+extern int ZEXPORT unzeof (file)
+    unzFile file;
+{
+    unz_s* s;
+    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_PARAMERROR;
+
+    if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
+        return 1;
+    else
+        return 0;
+}
+
+
+
+/*
+  Read extra field from the current file (opened by unzOpenCurrentFile)
+  This is the local-header version of the extra field (sometimes, there is
+    more info in the local-header version than in the central-header)
+
+  if buf==NULL, it return the size of the local extra field that can be read
+
+  if buf!=NULL, len is the size of the buffer, the extra header is copied in
+    buf.
+  the return value is the number of bytes copied in buf, or (if <0)
+    the error code
+*/
+extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
+    unzFile file;
+    voidp buf;
+    unsigned len;
+{
+    unz_s* s;
+    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    uInt read_now;
+    uLong size_to_read;
+
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_PARAMERROR;
+
+    size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
+                pfile_in_zip_read_info->pos_local_extrafield);
+
+    if (buf==NULL)
+        return (int)size_to_read;
+
+    if (len>size_to_read)
+        read_now = (uInt)size_to_read;
+    else
+        read_now = (uInt)len ;
+
+    if (read_now==0)
+        return 0;
+
+    if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
+              pfile_in_zip_read_info->filestream,
+              pfile_in_zip_read_info->offset_local_extrafield +
+              pfile_in_zip_read_info->pos_local_extrafield,
+              ZLIB_FILEFUNC_SEEK_SET)!=0)
+        return UNZ_ERRNO;
+
+    if (ZREAD(pfile_in_zip_read_info->z_filefunc,
+              pfile_in_zip_read_info->filestream,
+              buf,read_now)!=read_now)
+        return UNZ_ERRNO;
+
+    return (int)read_now;
+}
+
+/*
+  Close the file in zip opened with unzipOpenCurrentFile
+  Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+extern int ZEXPORT unzCloseCurrentFile (file)
+    unzFile file;
+{
+    int err=UNZ_OK;
+
+    unz_s* s;
+    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_PARAMERROR;
+
+
+    if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
+        (!pfile_in_zip_read_info->raw))
+    {
+        if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
+            err=UNZ_CRCERROR;
+    }
+
+
+    TRYFREE(pfile_in_zip_read_info->read_buffer);
+    pfile_in_zip_read_info->read_buffer = NULL;
+    if (pfile_in_zip_read_info->stream_initialised)
+        inflateEnd(&pfile_in_zip_read_info->stream);
+
+    pfile_in_zip_read_info->stream_initialised = 0;
+    TRYFREE(pfile_in_zip_read_info);
+
+    s->pfile_in_zip_read=NULL;
+
+    return err;
+}
+
+
+/*
+  Get the global comment string of the ZipFile, in the szComment buffer.
+  uSizeBuf is the size of the szComment buffer.
+  return the number of byte copied or an error code <0
+*/
+extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
+    unzFile file;
+    char *szComment;
+    uLong uSizeBuf;
+{
+    int err=UNZ_OK;
+    unz_s* s;
+    uLong uReadThis ;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+
+    uReadThis = uSizeBuf;
+    if (uReadThis>s->gi.size_comment)
+        uReadThis = s->gi.size_comment;
+
+    if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        return UNZ_ERRNO;
+
+    if (uReadThis>0)
+    {
+      *szComment='\0';
+      if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
+        return UNZ_ERRNO;
+    }
+
+    if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
+        *(szComment+s->gi.size_comment)='\0';
+    return (int)uReadThis;
+}
+
+/* Additions by RX '2004 */
+extern uLong ZEXPORT unzGetOffset (file)
+    unzFile file;
+{
+    unz_s* s;
+
+    if (file==NULL)
+          return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    if (!s->current_file_ok)
+      return 0;
+    if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
+      if (s->num_file==s->gi.number_entry)
+         return 0;
+    return s->pos_in_central_dir;
+}
+
+extern int ZEXPORT unzSetOffset (file, pos)
+        unzFile file;
+        uLong pos;
+{
+    unz_s* s;
+    int err;
+
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+
+    s->pos_in_central_dir = pos;
+    s->num_file = s->gi.number_entry;      /* hack */
+    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+                                              &s->cur_file_info_internal,
+                                              NULL,0,NULL,0,NULL,0);
+    s->current_file_ok = (err == UNZ_OK);
+    return err;
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/minizip/unzip.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/minizip/unzip.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/minizip/unzip.h	(revision 9)
@@ -0,0 +1,354 @@
+/* unzip.h -- IO for uncompress .zip files using zlib
+   Version 1.01e, February 12th, 2005
+
+   Copyright (C) 1998-2005 Gilles Vollant
+
+   This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
+     WinZip, InfoZip tools and compatible.
+
+   Multi volume ZipFile (span) are not supported.
+   Encryption compatible with pkzip 2.04g only supported
+   Old compressions used by old PKZip 1.x are not supported
+
+
+   I WAIT FEEDBACK at mail info@winimage.com
+   Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
+
+   Condition of use and distribution are the same than zlib :
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+
+*/
+
+/* for more info about .ZIP format, see
+      http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
+      http://www.info-zip.org/pub/infozip/doc/
+   PkWare has also a specification at :
+      ftp://ftp.pkware.com/probdesc.zip
+*/
+
+#ifndef _unz_H
+#define _unz_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _ZLIB_H
+#include "zlib.h"
+#endif
+
+#ifndef _ZLIBIOAPI_H
+#include "ioapi.h"
+#endif
+
+#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+    from (void*) without cast */
+typedef struct TagunzFile__ { int unused; } unzFile__;
+typedef unzFile__ *unzFile;
+#else
+typedef voidp unzFile;
+#endif
+
+
+#define UNZ_OK                          (0)
+#define UNZ_END_OF_LIST_OF_FILE         (-100)
+#define UNZ_ERRNO                       (Z_ERRNO)
+#define UNZ_EOF                         (0)
+#define UNZ_PARAMERROR                  (-102)
+#define UNZ_BADZIPFILE                  (-103)
+#define UNZ_INTERNALERROR               (-104)
+#define UNZ_CRCERROR                    (-105)
+
+/* tm_unz contain date/time info */
+typedef struct tm_unz_s
+{
+    uInt tm_sec;            /* seconds after the minute - [0,59] */
+    uInt tm_min;            /* minutes after the hour - [0,59] */
+    uInt tm_hour;           /* hours since midnight - [0,23] */
+    uInt tm_mday;           /* day of the month - [1,31] */
+    uInt tm_mon;            /* months since January - [0,11] */
+    uInt tm_year;           /* years - [1980..2044] */
+} tm_unz;
+
+/* unz_global_info structure contain global data about the ZIPfile
+   These data comes from the end of central dir */
+typedef struct unz_global_info_s
+{
+    uLong number_entry;         /* total number of entries in
+                       the central dir on this disk */
+    uLong size_comment;         /* size of the global comment of the zipfile */
+} unz_global_info;
+
+
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_info_s
+{
+    uLong version;              /* version made by                 2 bytes */
+    uLong version_needed;       /* version needed to extract       2 bytes */
+    uLong flag;                 /* general purpose bit flag        2 bytes */
+    uLong compression_method;   /* compression method              2 bytes */
+    uLong dosDate;              /* last mod file date in Dos fmt   4 bytes */
+    uLong crc;                  /* crc-32                          4 bytes */
+    uLong compressed_size;      /* compressed size                 4 bytes */
+    uLong uncompressed_size;    /* uncompressed size               4 bytes */
+    uLong size_filename;        /* filename length                 2 bytes */
+    uLong size_file_extra;      /* extra field length              2 bytes */
+    uLong size_file_comment;    /* file comment length             2 bytes */
+
+    uLong disk_num_start;       /* disk number start               2 bytes */
+    uLong internal_fa;          /* internal file attributes        2 bytes */
+    uLong external_fa;          /* external file attributes        4 bytes */
+
+    tm_unz tmu_date;
+} unz_file_info;
+
+extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
+                                                 const char* fileName2,
+                                                 int iCaseSensitivity));
+/*
+   Compare two filename (fileName1,fileName2).
+   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+                                or strcasecmp)
+   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+    (like 1 on Unix, 2 on Windows)
+*/
+
+
+extern unzFile ZEXPORT unzOpen OF((const char *path));
+/*
+  Open a Zip file. path contain the full pathname (by example,
+     on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
+     "zlib/zlib113.zip".
+     If the zipfile cannot be opened (file don't exist or in not valid), the
+       return value is NULL.
+     Else, the return value is a unzFile Handle, usable with other function
+       of this unzip package.
+*/
+
+extern unzFile ZEXPORT unzOpen2 OF((const char *path,
+                                    zlib_filefunc_def* pzlib_filefunc_def));
+/*
+   Open a Zip file, like unzOpen, but provide a set of file low level API
+      for read/write the zip file (see ioapi.h)
+*/
+
+extern int ZEXPORT unzClose OF((unzFile file));
+/*
+  Close a ZipFile opened with unzipOpen.
+  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+  return UNZ_OK if there is no problem. */
+
+extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
+                                        unz_global_info *pglobal_info));
+/*
+  Write info about the ZipFile in the *pglobal_info structure.
+  No preparation of the structure is needed
+  return UNZ_OK if there is no problem. */
+
+
+extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
+                                           char *szComment,
+                                           uLong uSizeBuf));
+/*
+  Get the global comment string of the ZipFile, in the szComment buffer.
+  uSizeBuf is the size of the szComment buffer.
+  return the number of byte copied or an error code <0
+*/
+
+
+/***************************************************************************/
+/* Unzip package allow you browse the directory of the zipfile */
+
+extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
+/*
+  Set the current file of the zipfile to the first file.
+  return UNZ_OK if there is no problem
+*/
+
+extern int ZEXPORT unzGoToNextFile OF((unzFile file));
+/*
+  Set the current file of the zipfile to the next file.
+  return UNZ_OK if there is no problem
+  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+
+extern int ZEXPORT unzLocateFile OF((unzFile file,
+                     const char *szFileName,
+                     int iCaseSensitivity));
+/*
+  Try locate the file szFileName in the zipfile.
+  For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+  return value :
+  UNZ_OK if the file is found. It becomes the current file.
+  UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+
+
+/* ****************************************** */
+/* Ryan supplied functions */
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_pos_s
+{
+    uLong pos_in_zip_directory;   /* offset in zip file directory */
+    uLong num_of_file;            /* # of file */
+} unz_file_pos;
+
+extern int ZEXPORT unzGetFilePos(
+    unzFile file,
+    unz_file_pos* file_pos);
+
+extern int ZEXPORT unzGoToFilePos(
+    unzFile file,
+    unz_file_pos* file_pos);
+
+/* ****************************************** */
+
+extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
+                         unz_file_info *pfile_info,
+                         char *szFileName,
+                         uLong fileNameBufferSize,
+                         void *extraField,
+                         uLong extraFieldBufferSize,
+                         char *szComment,
+                         uLong commentBufferSize));
+/*
+  Get Info about the current file
+  if pfile_info!=NULL, the *pfile_info structure will contain somes info about
+        the current file
+  if szFileName!=NULL, the filemane string will be copied in szFileName
+            (fileNameBufferSize is the size of the buffer)
+  if extraField!=NULL, the extra field information will be copied in extraField
+            (extraFieldBufferSize is the size of the buffer).
+            This is the Central-header version of the extra field
+  if szComment!=NULL, the comment string of the file will be copied in szComment
+            (commentBufferSize is the size of the buffer)
+*/
+
+/***************************************************************************/
+/* for reading the content of the current zipfile, you can open it, read data
+   from it, and close it (you can close it before reading all the file)
+   */
+
+extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
+/*
+  Open for reading data the current file in the zipfile.
+  If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
+                                                  const char* password));
+/*
+  Open for reading data the current file in the zipfile.
+  password is a crypting password
+  If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
+                                           int* method,
+                                           int* level,
+                                           int raw));
+/*
+  Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+    if raw==1
+  *method will receive method of compression, *level will receive level of
+     compression
+  note : you can set level parameter as NULL (if you did not want known level,
+         but you CANNOT set method parameter as NULL
+*/
+
+extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
+                                           int* method,
+                                           int* level,
+                                           int raw,
+                                           const char* password));
+/*
+  Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+    if raw==1
+  *method will receive method of compression, *level will receive level of
+     compression
+  note : you can set level parameter as NULL (if you did not want known level,
+         but you CANNOT set method parameter as NULL
+*/
+
+
+extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
+/*
+  Close the file in zip opened with unzOpenCurrentFile
+  Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+
+extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
+                      voidp buf,
+                      unsigned len));
+/*
+  Read bytes from the current file (opened by unzOpenCurrentFile)
+  buf contain buffer where data must be copied
+  len the size of buf.
+
+  return the number of byte copied if somes bytes are copied
+  return 0 if the end of file was reached
+  return <0 with error code if there is an error
+    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+
+extern z_off_t ZEXPORT unztell OF((unzFile file));
+/*
+  Give the current position in uncompressed data
+*/
+
+extern int ZEXPORT unzeof OF((unzFile file));
+/*
+  return 1 if the end of file was reached, 0 elsewhere
+*/
+
+extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
+                                             voidp buf,
+                                             unsigned len));
+/*
+  Read extra field from the current file (opened by unzOpenCurrentFile)
+  This is the local-header version of the extra field (sometimes, there is
+    more info in the local-header version than in the central-header)
+
+  if buf==NULL, it return the size of the local extra field
+
+  if buf!=NULL, len is the size of the buffer, the extra header is copied in
+    buf.
+  the return value is the number of bytes copied in buf, or (if <0)
+    the error code
+*/
+
+/***************************************************************************/
+
+/* Get the current file offset */
+extern uLong ZEXPORT unzGetOffset (unzFile file);
+
+/* Set the current file offset */
+extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _unz_H */
Index: /trunk/minix/lib/zlib-1.2.3/contrib/minizip/zip.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/minizip/zip.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/minizip/zip.c	(revision 9)
@@ -0,0 +1,1219 @@
+/* zip.c -- IO on .zip files using zlib
+   Version 1.01e, February 12th, 2005
+
+   27 Dec 2004 Rolf Kalbermatter
+   Modification to zipOpen2 to support globalComment retrieval.
+
+   Copyright (C) 1998-2005 Gilles Vollant
+
+   Read zip.h for more info
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "zlib.h"
+#include "zip.h"
+
+#ifdef STDC
+#  include <stddef.h>
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+    extern int errno;
+#else
+#   include <errno.h>
+#endif
+
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+#ifndef VERSIONMADEBY
+# define VERSIONMADEBY   (0x0) /* platform depedent */
+#endif
+
+#ifndef Z_BUFSIZE
+#define Z_BUFSIZE (16384)
+#endif
+
+#ifndef Z_MAXFILENAMEINZIP
+#define Z_MAXFILENAMEINZIP (256)
+#endif
+
+#ifndef ALLOC
+# define ALLOC(size) (malloc(size))
+#endif
+#ifndef TRYFREE
+# define TRYFREE(p) {if (p) free(p);}
+#endif
+
+/*
+#define SIZECENTRALDIRITEM (0x2e)
+#define SIZEZIPLOCALHEADER (0x1e)
+*/
+
+/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
+
+#ifndef SEEK_CUR
+#define SEEK_CUR    1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END    2
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET    0
+#endif
+
+#ifndef DEF_MEM_LEVEL
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+#endif
+const char zip_copyright[] =
+   " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
+
+
+#define SIZEDATA_INDATABLOCK (4096-(4*4))
+
+#define LOCALHEADERMAGIC    (0x04034b50)
+#define CENTRALHEADERMAGIC  (0x02014b50)
+#define ENDHEADERMAGIC      (0x06054b50)
+
+#define FLAG_LOCALHEADER_OFFSET (0x06)
+#define CRC_LOCALHEADER_OFFSET  (0x0e)
+
+#define SIZECENTRALHEADER (0x2e) /* 46 */
+
+typedef struct linkedlist_datablock_internal_s
+{
+  struct linkedlist_datablock_internal_s* next_datablock;
+  uLong  avail_in_this_block;
+  uLong  filled_in_this_block;
+  uLong  unused; /* for future use and alignement */
+  unsigned char data[SIZEDATA_INDATABLOCK];
+} linkedlist_datablock_internal;
+
+typedef struct linkedlist_data_s
+{
+    linkedlist_datablock_internal* first_block;
+    linkedlist_datablock_internal* last_block;
+} linkedlist_data;
+
+
+typedef struct
+{
+    z_stream stream;            /* zLib stream structure for inflate */
+    int  stream_initialised;    /* 1 is stream is initialised */
+    uInt pos_in_buffered_data;  /* last written byte in buffered_data */
+
+    uLong pos_local_header;     /* offset of the local header of the file
+                                     currenty writing */
+    char* central_header;       /* central header data for the current file */
+    uLong size_centralheader;   /* size of the central header for cur file */
+    uLong flag;                 /* flag of the file currently writing */
+
+    int  method;                /* compression method of file currenty wr.*/
+    int  raw;                   /* 1 for directly writing raw data */
+    Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
+    uLong dosDate;
+    uLong crc32;
+    int  encrypt;
+#ifndef NOCRYPT
+    unsigned long keys[3];     /* keys defining the pseudo-random sequence */
+    const unsigned long* pcrc_32_tab;
+    int crypt_header_size;
+#endif
+} curfile_info;
+
+typedef struct
+{
+    zlib_filefunc_def z_filefunc;
+    voidpf filestream;        /* io structore of the zipfile */
+    linkedlist_data central_dir;/* datablock with central dir in construction*/
+    int  in_opened_file_inzip;  /* 1 if a file in the zip is currently writ.*/
+    curfile_info ci;            /* info on the file curretly writing */
+
+    uLong begin_pos;            /* position of the beginning of the zipfile */
+    uLong add_position_when_writting_offset;
+    uLong number_entry;
+#ifndef NO_ADDFILEINEXISTINGZIP
+    char *globalcomment;
+#endif
+} zip_internal;
+
+
+
+#ifndef NOCRYPT
+#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
+#include "crypt.h"
+#endif
+
+local linkedlist_datablock_internal* allocate_new_datablock()
+{
+    linkedlist_datablock_internal* ldi;
+    ldi = (linkedlist_datablock_internal*)
+                 ALLOC(sizeof(linkedlist_datablock_internal));
+    if (ldi!=NULL)
+    {
+        ldi->next_datablock = NULL ;
+        ldi->filled_in_this_block = 0 ;
+        ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
+    }
+    return ldi;
+}
+
+local void free_datablock(ldi)
+    linkedlist_datablock_internal* ldi;
+{
+    while (ldi!=NULL)
+    {
+        linkedlist_datablock_internal* ldinext = ldi->next_datablock;
+        TRYFREE(ldi);
+        ldi = ldinext;
+    }
+}
+
+local void init_linkedlist(ll)
+    linkedlist_data* ll;
+{
+    ll->first_block = ll->last_block = NULL;
+}
+
+local void free_linkedlist(ll)
+    linkedlist_data* ll;
+{
+    free_datablock(ll->first_block);
+    ll->first_block = ll->last_block = NULL;
+}
+
+
+local int add_data_in_datablock(ll,buf,len)
+    linkedlist_data* ll;
+    const void* buf;
+    uLong len;
+{
+    linkedlist_datablock_internal* ldi;
+    const unsigned char* from_copy;
+
+    if (ll==NULL)
+        return ZIP_INTERNALERROR;
+
+    if (ll->last_block == NULL)
+    {
+        ll->first_block = ll->last_block = allocate_new_datablock();
+        if (ll->first_block == NULL)
+            return ZIP_INTERNALERROR;
+    }
+
+    ldi = ll->last_block;
+    from_copy = (unsigned char*)buf;
+
+    while (len>0)
+    {
+        uInt copy_this;
+        uInt i;
+        unsigned char* to_copy;
+
+        if (ldi->avail_in_this_block==0)
+        {
+            ldi->next_datablock = allocate_new_datablock();
+            if (ldi->next_datablock == NULL)
+                return ZIP_INTERNALERROR;
+            ldi = ldi->next_datablock ;
+            ll->last_block = ldi;
+        }
+
+        if (ldi->avail_in_this_block < len)
+            copy_this = (uInt)ldi->avail_in_this_block;
+        else
+            copy_this = (uInt)len;
+
+        to_copy = &(ldi->data[ldi->filled_in_this_block]);
+
+        for (i=0;i<copy_this;i++)
+            *(to_copy+i)=*(from_copy+i);
+
+        ldi->filled_in_this_block += copy_this;
+        ldi->avail_in_this_block -= copy_this;
+        from_copy += copy_this ;
+        len -= copy_this;
+    }
+    return ZIP_OK;
+}
+
+
+
+/****************************************************************************/
+
+#ifndef NO_ADDFILEINEXISTINGZIP
+/* ===========================================================================
+   Inputs a long in LSB order to the given file
+   nbByte == 1, 2 or 4 (byte, short or long)
+*/
+
+local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def,
+                                voidpf filestream, uLong x, int nbByte));
+local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
+    uLong x;
+    int nbByte;
+{
+    unsigned char buf[4];
+    int n;
+    for (n = 0; n < nbByte; n++)
+    {
+        buf[n] = (unsigned char)(x & 0xff);
+        x >>= 8;
+    }
+    if (x != 0)
+      {     /* data overflow - hack for ZIP64 (X Roche) */
+      for (n = 0; n < nbByte; n++)
+        {
+          buf[n] = 0xff;
+        }
+      }
+
+    if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)
+        return ZIP_ERRNO;
+    else
+        return ZIP_OK;
+}
+
+local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte));
+local void ziplocal_putValue_inmemory (dest, x, nbByte)
+    void* dest;
+    uLong x;
+    int nbByte;
+{
+    unsigned char* buf=(unsigned char*)dest;
+    int n;
+    for (n = 0; n < nbByte; n++) {
+        buf[n] = (unsigned char)(x & 0xff);
+        x >>= 8;
+    }
+
+    if (x != 0)
+    {     /* data overflow - hack for ZIP64 */
+       for (n = 0; n < nbByte; n++)
+       {
+          buf[n] = 0xff;
+       }
+    }
+}
+
+/****************************************************************************/
+
+
+local uLong ziplocal_TmzDateToDosDate(ptm,dosDate)
+    const tm_zip* ptm;
+    uLong dosDate;
+{
+    uLong year = (uLong)ptm->tm_year;
+    if (year>1980)
+        year-=1980;
+    else if (year>80)
+        year-=80;
+    return
+      (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
+        ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
+}
+
+
+/****************************************************************************/
+
+local int ziplocal_getByte OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream,
+    int *pi));
+
+local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
+    int *pi;
+{
+    unsigned char c;
+    int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
+    if (err==1)
+    {
+        *pi = (int)c;
+        return ZIP_OK;
+    }
+    else
+    {
+        if (ZERROR(*pzlib_filefunc_def,filestream))
+            return ZIP_ERRNO;
+        else
+            return ZIP_EOF;
+    }
+}
+
+
+/* ===========================================================================
+   Reads a long in LSB order from the given gz_stream. Sets
+*/
+local int ziplocal_getShort OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream,
+    uLong *pX));
+
+local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
+    uLong *pX;
+{
+    uLong x ;
+    int i;
+    int err;
+
+    err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x = (uLong)i;
+
+    if (err==ZIP_OK)
+        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x += ((uLong)i)<<8;
+
+    if (err==ZIP_OK)
+        *pX = x;
+    else
+        *pX = 0;
+    return err;
+}
+
+local int ziplocal_getLong OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream,
+    uLong *pX));
+
+local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
+    uLong *pX;
+{
+    uLong x ;
+    int i;
+    int err;
+
+    err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x = (uLong)i;
+
+    if (err==ZIP_OK)
+        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x += ((uLong)i)<<8;
+
+    if (err==ZIP_OK)
+        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x += ((uLong)i)<<16;
+
+    if (err==ZIP_OK)
+        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x += ((uLong)i)<<24;
+
+    if (err==ZIP_OK)
+        *pX = x;
+    else
+        *pX = 0;
+    return err;
+}
+
+#ifndef BUFREADCOMMENT
+#define BUFREADCOMMENT (0x400)
+#endif
+/*
+  Locate the Central directory of a zipfile (at the end, just before
+    the global comment)
+*/
+local uLong ziplocal_SearchCentralDir OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream));
+
+local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
+{
+    unsigned char* buf;
+    uLong uSizeFile;
+    uLong uBackRead;
+    uLong uMaxBack=0xffff; /* maximum size of global comment */
+    uLong uPosFound=0;
+
+    if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+        return 0;
+
+
+    uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
+
+    if (uMaxBack>uSizeFile)
+        uMaxBack = uSizeFile;
+
+    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+    if (buf==NULL)
+        return 0;
+
+    uBackRead = 4;
+    while (uBackRead<uMaxBack)
+    {
+        uLong uReadSize,uReadPos ;
+        int i;
+        if (uBackRead+BUFREADCOMMENT>uMaxBack)
+            uBackRead = uMaxBack;
+        else
+            uBackRead+=BUFREADCOMMENT;
+        uReadPos = uSizeFile-uBackRead ;
+
+        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
+        if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            break;
+
+        if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+            break;
+
+        for (i=(int)uReadSize-3; (i--)>0;)
+            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+            {
+                uPosFound = uReadPos+i;
+                break;
+            }
+
+        if (uPosFound!=0)
+            break;
+    }
+    TRYFREE(buf);
+    return uPosFound;
+}
+#endif /* !NO_ADDFILEINEXISTINGZIP*/
+
+/************************************************************/
+extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def)
+    const char *pathname;
+    int append;
+    zipcharpc* globalcomment;
+    zlib_filefunc_def* pzlib_filefunc_def;
+{
+    zip_internal ziinit;
+    zip_internal* zi;
+    int err=ZIP_OK;
+
+
+    if (pzlib_filefunc_def==NULL)
+        fill_fopen_filefunc(&ziinit.z_filefunc);
+    else
+        ziinit.z_filefunc = *pzlib_filefunc_def;
+
+    ziinit.filestream = (*(ziinit.z_filefunc.zopen_file))
+                 (ziinit.z_filefunc.opaque,
+                  pathname,
+                  (append == APPEND_STATUS_CREATE) ?
+                  (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) :
+                    (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING));
+
+    if (ziinit.filestream == NULL)
+        return NULL;
+    ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream);
+    ziinit.in_opened_file_inzip = 0;
+    ziinit.ci.stream_initialised = 0;
+    ziinit.number_entry = 0;
+    ziinit.add_position_when_writting_offset = 0;
+    init_linkedlist(&(ziinit.central_dir));
+
+
+    zi = (zip_internal*)ALLOC(sizeof(zip_internal));
+    if (zi==NULL)
+    {
+        ZCLOSE(ziinit.z_filefunc,ziinit.filestream);
+        return NULL;
+    }
+
+    /* now we add file in a zipfile */
+#    ifndef NO_ADDFILEINEXISTINGZIP
+    ziinit.globalcomment = NULL;
+    if (append == APPEND_STATUS_ADDINZIP)
+    {
+        uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+
+        uLong size_central_dir;     /* size of the central directory  */
+        uLong offset_central_dir;   /* offset of start of central directory */
+        uLong central_pos,uL;
+
+        uLong number_disk;          /* number of the current dist, used for
+                                    spaning ZIP, unsupported, always 0*/
+        uLong number_disk_with_CD;  /* number the the disk with central dir, used
+                                    for spaning ZIP, unsupported, always 0*/
+        uLong number_entry;
+        uLong number_entry_CD;      /* total number of entries in
+                                    the central dir
+                                    (same than number_entry on nospan) */
+        uLong size_comment;
+
+        central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream);
+        if (central_pos==0)
+            err=ZIP_ERRNO;
+
+        if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
+                                        central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            err=ZIP_ERRNO;
+
+        /* the signature, already checked */
+        if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        /* number of this disk */
+        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        /* number of the disk with the start of the central directory */
+        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        /* total number of entries in the central dir on this disk */
+        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        /* total number of entries in the central dir */
+        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        if ((number_entry_CD!=number_entry) ||
+            (number_disk_with_CD!=0) ||
+            (number_disk!=0))
+            err=ZIP_BADZIPFILE;
+
+        /* size of the central directory */
+        if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        /* offset of start of central directory with respect to the
+            starting disk number */
+        if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        /* zipfile global comment length */
+        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        if ((central_pos<offset_central_dir+size_central_dir) &&
+            (err==ZIP_OK))
+            err=ZIP_BADZIPFILE;
+
+        if (err!=ZIP_OK)
+        {
+            ZCLOSE(ziinit.z_filefunc, ziinit.filestream);
+            return NULL;
+        }
+
+        if (size_comment>0)
+        {
+            ziinit.globalcomment = ALLOC(size_comment+1);
+            if (ziinit.globalcomment)
+            {
+               size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment);
+               ziinit.globalcomment[size_comment]=0;
+            }
+        }
+
+        byte_before_the_zipfile = central_pos -
+                                (offset_central_dir+size_central_dir);
+        ziinit.add_position_when_writting_offset = byte_before_the_zipfile;
+
+        {
+            uLong size_central_dir_to_read = size_central_dir;
+            size_t buf_size = SIZEDATA_INDATABLOCK;
+            void* buf_read = (void*)ALLOC(buf_size);
+            if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
+                  offset_central_dir + byte_before_the_zipfile,
+                  ZLIB_FILEFUNC_SEEK_SET) != 0)
+                  err=ZIP_ERRNO;
+
+            while ((size_central_dir_to_read>0) && (err==ZIP_OK))
+            {
+                uLong read_this = SIZEDATA_INDATABLOCK;
+                if (read_this > size_central_dir_to_read)
+                    read_this = size_central_dir_to_read;
+                if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this)
+                    err=ZIP_ERRNO;
+
+                if (err==ZIP_OK)
+                    err = add_data_in_datablock(&ziinit.central_dir,buf_read,
+                                                (uLong)read_this);
+                size_central_dir_to_read-=read_this;
+            }
+            TRYFREE(buf_read);
+        }
+        ziinit.begin_pos = byte_before_the_zipfile;
+        ziinit.number_entry = number_entry_CD;
+
+        if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
+                  offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            err=ZIP_ERRNO;
+    }
+
+    if (globalcomment)
+    {
+      *globalcomment = ziinit.globalcomment;
+    }
+#    endif /* !NO_ADDFILEINEXISTINGZIP*/
+
+    if (err != ZIP_OK)
+    {
+#    ifndef NO_ADDFILEINEXISTINGZIP
+        TRYFREE(ziinit.globalcomment);
+#    endif /* !NO_ADDFILEINEXISTINGZIP*/
+        TRYFREE(zi);
+        return NULL;
+    }
+    else
+    {
+        *zi = ziinit;
+        return (zipFile)zi;
+    }
+}
+
+extern zipFile ZEXPORT zipOpen (pathname, append)
+    const char *pathname;
+    int append;
+{
+    return zipOpen2(pathname,append,NULL,NULL);
+}
+
+extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,
+                                         extrafield_local, size_extrafield_local,
+                                         extrafield_global, size_extrafield_global,
+                                         comment, method, level, raw,
+                                         windowBits, memLevel, strategy,
+                                         password, crcForCrypting)
+    zipFile file;
+    const char* filename;
+    const zip_fileinfo* zipfi;
+    const void* extrafield_local;
+    uInt size_extrafield_local;
+    const void* extrafield_global;
+    uInt size_extrafield_global;
+    const char* comment;
+    int method;
+    int level;
+    int raw;
+    int windowBits;
+    int memLevel;
+    int strategy;
+    const char* password;
+    uLong crcForCrypting;
+{
+    zip_internal* zi;
+    uInt size_filename;
+    uInt size_comment;
+    uInt i;
+    int err = ZIP_OK;
+
+#    ifdef NOCRYPT
+    if (password != NULL)
+        return ZIP_PARAMERROR;
+#    endif
+
+    if (file == NULL)
+        return ZIP_PARAMERROR;
+    if ((method!=0) && (method!=Z_DEFLATED))
+        return ZIP_PARAMERROR;
+
+    zi = (zip_internal*)file;
+
+    if (zi->in_opened_file_inzip == 1)
+    {
+        err = zipCloseFileInZip (file);
+        if (err != ZIP_OK)
+            return err;
+    }
+
+
+    if (filename==NULL)
+        filename="-";
+
+    if (comment==NULL)
+        size_comment = 0;
+    else
+        size_comment = (uInt)strlen(comment);
+
+    size_filename = (uInt)strlen(filename);
+
+    if (zipfi == NULL)
+        zi->ci.dosDate = 0;
+    else
+    {
+        if (zipfi->dosDate != 0)
+            zi->ci.dosDate = zipfi->dosDate;
+        else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate);
+    }
+
+    zi->ci.flag = 0;
+    if ((level==8) || (level==9))
+      zi->ci.flag |= 2;
+    if ((level==2))
+      zi->ci.flag |= 4;
+    if ((level==1))
+      zi->ci.flag |= 6;
+    if (password != NULL)
+      zi->ci.flag |= 1;
+
+    zi->ci.crc32 = 0;
+    zi->ci.method = method;
+    zi->ci.encrypt = 0;
+    zi->ci.stream_initialised = 0;
+    zi->ci.pos_in_buffered_data = 0;
+    zi->ci.raw = raw;
+    zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ;
+    zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename +
+                                      size_extrafield_global + size_comment;
+    zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader);
+
+    ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
+    /* version info */
+    ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2);
+    ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
+    ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
+    ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
+    ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
+    ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
+    ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
+    ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
+    ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
+    ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
+    ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
+    ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
+
+    if (zipfi==NULL)
+        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);
+    else
+        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);
+
+    if (zipfi==NULL)
+        ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);
+    else
+        ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
+
+    ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4);
+
+    for (i=0;i<size_filename;i++)
+        *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
+
+    for (i=0;i<size_extrafield_global;i++)
+        *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
+              *(((const char*)extrafield_global)+i);
+
+    for (i=0;i<size_comment;i++)
+        *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
+              size_extrafield_global+i) = *(comment+i);
+    if (zi->ci.central_header == NULL)
+        return ZIP_INTERNALERROR;
+
+    /* write the local header */
+    err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4);
+
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);
+
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
+
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
+
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */
+
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
+
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2);
+
+    if ((err==ZIP_OK) && (size_filename>0))
+        if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)
+                err = ZIP_ERRNO;
+
+    if ((err==ZIP_OK) && (size_extrafield_local>0))
+        if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local)
+                                                                           !=size_extrafield_local)
+                err = ZIP_ERRNO;
+
+    zi->ci.stream.avail_in = (uInt)0;
+    zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
+    zi->ci.stream.next_out = zi->ci.buffered_data;
+    zi->ci.stream.total_in = 0;
+    zi->ci.stream.total_out = 0;
+
+    if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
+    {
+        zi->ci.stream.zalloc = (alloc_func)0;
+        zi->ci.stream.zfree = (free_func)0;
+        zi->ci.stream.opaque = (voidpf)0;
+
+        if (windowBits>0)
+            windowBits = -windowBits;
+
+        err = deflateInit2(&zi->ci.stream, level,
+               Z_DEFLATED, windowBits, memLevel, strategy);
+
+        if (err==Z_OK)
+            zi->ci.stream_initialised = 1;
+    }
+#    ifndef NOCRYPT
+    zi->ci.crypt_header_size = 0;
+    if ((err==Z_OK) && (password != NULL))
+    {
+        unsigned char bufHead[RAND_HEAD_LEN];
+        unsigned int sizeHead;
+        zi->ci.encrypt = 1;
+        zi->ci.pcrc_32_tab = get_crc_table();
+        /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
+
+        sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);
+        zi->ci.crypt_header_size = sizeHead;
+
+        if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
+                err = ZIP_ERRNO;
+    }
+#    endif
+
+    if (err==Z_OK)
+        zi->in_opened_file_inzip = 1;
+    return err;
+}
+
+extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi,
+                                        extrafield_local, size_extrafield_local,
+                                        extrafield_global, size_extrafield_global,
+                                        comment, method, level, raw)
+    zipFile file;
+    const char* filename;
+    const zip_fileinfo* zipfi;
+    const void* extrafield_local;
+    uInt size_extrafield_local;
+    const void* extrafield_global;
+    uInt size_extrafield_global;
+    const char* comment;
+    int method;
+    int level;
+    int raw;
+{
+    return zipOpenNewFileInZip3 (file, filename, zipfi,
+                                 extrafield_local, size_extrafield_local,
+                                 extrafield_global, size_extrafield_global,
+                                 comment, method, level, raw,
+                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
+                                 NULL, 0);
+}
+
+extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi,
+                                        extrafield_local, size_extrafield_local,
+                                        extrafield_global, size_extrafield_global,
+                                        comment, method, level)
+    zipFile file;
+    const char* filename;
+    const zip_fileinfo* zipfi;
+    const void* extrafield_local;
+    uInt size_extrafield_local;
+    const void* extrafield_global;
+    uInt size_extrafield_global;
+    const char* comment;
+    int method;
+    int level;
+{
+    return zipOpenNewFileInZip2 (file, filename, zipfi,
+                                 extrafield_local, size_extrafield_local,
+                                 extrafield_global, size_extrafield_global,
+                                 comment, method, level, 0);
+}
+
+local int zipFlushWriteBuffer(zi)
+  zip_internal* zi;
+{
+    int err=ZIP_OK;
+
+    if (zi->ci.encrypt != 0)
+    {
+#ifndef NOCRYPT
+        uInt i;
+        int t;
+        for (i=0;i<zi->ci.pos_in_buffered_data;i++)
+            zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab,
+                                       zi->ci.buffered_data[i],t);
+#endif
+    }
+    if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data)
+                                                                    !=zi->ci.pos_in_buffered_data)
+      err = ZIP_ERRNO;
+    zi->ci.pos_in_buffered_data = 0;
+    return err;
+}
+
+extern int ZEXPORT zipWriteInFileInZip (file, buf, len)
+    zipFile file;
+    const void* buf;
+    unsigned len;
+{
+    zip_internal* zi;
+    int err=ZIP_OK;
+
+    if (file == NULL)
+        return ZIP_PARAMERROR;
+    zi = (zip_internal*)file;
+
+    if (zi->in_opened_file_inzip == 0)
+        return ZIP_PARAMERROR;
+
+    zi->ci.stream.next_in = (void*)buf;
+    zi->ci.stream.avail_in = len;
+    zi->ci.crc32 = crc32(zi->ci.crc32,buf,len);
+
+    while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
+    {
+        if (zi->ci.stream.avail_out == 0)
+        {
+            if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
+                err = ZIP_ERRNO;
+            zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
+            zi->ci.stream.next_out = zi->ci.buffered_data;
+        }
+
+
+        if(err != ZIP_OK)
+            break;
+
+        if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
+        {
+            uLong uTotalOutBefore = zi->ci.stream.total_out;
+            err=deflate(&zi->ci.stream,  Z_NO_FLUSH);
+            zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
+
+        }
+        else
+        {
+            uInt copy_this,i;
+            if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
+                copy_this = zi->ci.stream.avail_in;
+            else
+                copy_this = zi->ci.stream.avail_out;
+            for (i=0;i<copy_this;i++)
+                *(((char*)zi->ci.stream.next_out)+i) =
+                    *(((const char*)zi->ci.stream.next_in)+i);
+            {
+                zi->ci.stream.avail_in -= copy_this;
+                zi->ci.stream.avail_out-= copy_this;
+                zi->ci.stream.next_in+= copy_this;
+                zi->ci.stream.next_out+= copy_this;
+                zi->ci.stream.total_in+= copy_this;
+                zi->ci.stream.total_out+= copy_this;
+                zi->ci.pos_in_buffered_data += copy_this;
+            }
+        }
+    }
+
+    return err;
+}
+
+extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32)
+    zipFile file;
+    uLong uncompressed_size;
+    uLong crc32;
+{
+    zip_internal* zi;
+    uLong compressed_size;
+    int err=ZIP_OK;
+
+    if (file == NULL)
+        return ZIP_PARAMERROR;
+    zi = (zip_internal*)file;
+
+    if (zi->in_opened_file_inzip == 0)
+        return ZIP_PARAMERROR;
+    zi->ci.stream.avail_in = 0;
+
+    if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
+        while (err==ZIP_OK)
+    {
+        uLong uTotalOutBefore;
+        if (zi->ci.stream.avail_out == 0)
+        {
+            if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
+                err = ZIP_ERRNO;
+            zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
+            zi->ci.stream.next_out = zi->ci.buffered_data;
+        }
+        uTotalOutBefore = zi->ci.stream.total_out;
+        err=deflate(&zi->ci.stream,  Z_FINISH);
+        zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
+    }
+
+    if (err==Z_STREAM_END)
+        err=ZIP_OK; /* this is normal */
+
+    if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
+        if (zipFlushWriteBuffer(zi)==ZIP_ERRNO)
+            err = ZIP_ERRNO;
+
+    if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
+    {
+        err=deflateEnd(&zi->ci.stream);
+        zi->ci.stream_initialised = 0;
+    }
+
+    if (!zi->ci.raw)
+    {
+        crc32 = (uLong)zi->ci.crc32;
+        uncompressed_size = (uLong)zi->ci.stream.total_in;
+    }
+    compressed_size = (uLong)zi->ci.stream.total_out;
+#    ifndef NOCRYPT
+    compressed_size += zi->ci.crypt_header_size;
+#    endif
+
+    ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/
+    ziplocal_putValue_inmemory(zi->ci.central_header+20,
+                                compressed_size,4); /*compr size*/
+    if (zi->ci.stream.data_type == Z_ASCII)
+        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);
+    ziplocal_putValue_inmemory(zi->ci.central_header+24,
+                                uncompressed_size,4); /*uncompr size*/
+
+    if (err==ZIP_OK)
+        err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header,
+                                       (uLong)zi->ci.size_centralheader);
+    free(zi->ci.central_header);
+
+    if (err==ZIP_OK)
+    {
+        long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
+        if (ZSEEK(zi->z_filefunc,zi->filestream,
+                  zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            err = ZIP_ERRNO;
+
+        if (err==ZIP_OK)
+            err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
+
+        if (err==ZIP_OK) /* compressed size, unknown */
+            err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);
+
+        if (err==ZIP_OK) /* uncompressed size, unknown */
+            err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);
+
+        if (ZSEEK(zi->z_filefunc,zi->filestream,
+                  cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            err = ZIP_ERRNO;
+    }
+
+    zi->number_entry ++;
+    zi->in_opened_file_inzip = 0;
+
+    return err;
+}
+
+extern int ZEXPORT zipCloseFileInZip (file)
+    zipFile file;
+{
+    return zipCloseFileInZipRaw (file,0,0);
+}
+
+extern int ZEXPORT zipClose (file, global_comment)
+    zipFile file;
+    const char* global_comment;
+{
+    zip_internal* zi;
+    int err = 0;
+    uLong size_centraldir = 0;
+    uLong centraldir_pos_inzip;
+    uInt size_global_comment;
+    if (file == NULL)
+        return ZIP_PARAMERROR;
+    zi = (zip_internal*)file;
+
+    if (zi->in_opened_file_inzip == 1)
+    {
+        err = zipCloseFileInZip (file);
+    }
+
+#ifndef NO_ADDFILEINEXISTINGZIP
+    if (global_comment==NULL)
+        global_comment = zi->globalcomment;
+#endif
+    if (global_comment==NULL)
+        size_global_comment = 0;
+    else
+        size_global_comment = (uInt)strlen(global_comment);
+
+    centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
+    if (err==ZIP_OK)
+    {
+        linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
+        while (ldi!=NULL)
+        {
+            if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
+                if (ZWRITE(zi->z_filefunc,zi->filestream,
+                           ldi->data,ldi->filled_in_this_block)
+                              !=ldi->filled_in_this_block )
+                    err = ZIP_ERRNO;
+
+            size_centraldir += ldi->filled_in_this_block;
+            ldi = ldi->next_datablock;
+        }
+    }
+    free_datablock(zi->central_dir.first_block);
+
+    if (err==ZIP_OK) /* Magic End */
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);
+
+    if (err==ZIP_OK) /* number of this disk */
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
+
+    if (err==ZIP_OK) /* number of the disk with the start of the central directory */
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
+
+    if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
+
+    if (err==ZIP_OK) /* total number of entries in the central dir */
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
+
+    if (err==ZIP_OK) /* size of the central directory */
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);
+
+    if (err==ZIP_OK) /* offset of start of central directory with respect to the
+                            starting disk number */
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,
+                                (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);
+
+    if (err==ZIP_OK) /* zipfile comment length */
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
+
+    if ((err==ZIP_OK) && (size_global_comment>0))
+        if (ZWRITE(zi->z_filefunc,zi->filestream,
+                   global_comment,size_global_comment) != size_global_comment)
+                err = ZIP_ERRNO;
+
+    if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0)
+        if (err == ZIP_OK)
+            err = ZIP_ERRNO;
+
+#ifndef NO_ADDFILEINEXISTINGZIP
+    TRYFREE(zi->globalcomment);
+#endif
+    TRYFREE(zi);
+
+    return err;
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/minizip/zip.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/minizip/zip.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/minizip/zip.h	(revision 9)
@@ -0,0 +1,235 @@
+/* zip.h -- IO for compress .zip files using zlib
+   Version 1.01e, February 12th, 2005
+
+   Copyright (C) 1998-2005 Gilles Vollant
+
+   This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
+     WinZip, InfoZip tools and compatible.
+   Multi volume ZipFile (span) are not supported.
+   Encryption compatible with pkzip 2.04g only supported
+   Old compressions used by old PKZip 1.x are not supported
+
+  For uncompress .zip file, look at unzip.h
+
+
+   I WAIT FEEDBACK at mail info@winimage.com
+   Visit also http://www.winimage.com/zLibDll/unzip.html for evolution
+
+   Condition of use and distribution are the same than zlib :
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+
+*/
+
+/* for more info about .ZIP format, see
+      http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
+      http://www.info-zip.org/pub/infozip/doc/
+   PkWare has also a specification at :
+      ftp://ftp.pkware.com/probdesc.zip
+*/
+
+#ifndef _zip_H
+#define _zip_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _ZLIB_H
+#include "zlib.h"
+#endif
+
+#ifndef _ZLIBIOAPI_H
+#include "ioapi.h"
+#endif
+
+#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+    from (void*) without cast */
+typedef struct TagzipFile__ { int unused; } zipFile__;
+typedef zipFile__ *zipFile;
+#else
+typedef voidp zipFile;
+#endif
+
+#define ZIP_OK                          (0)
+#define ZIP_EOF                         (0)
+#define ZIP_ERRNO                       (Z_ERRNO)
+#define ZIP_PARAMERROR                  (-102)
+#define ZIP_BADZIPFILE                  (-103)
+#define ZIP_INTERNALERROR               (-104)
+
+#ifndef DEF_MEM_LEVEL
+#  if MAX_MEM_LEVEL >= 8
+#    define DEF_MEM_LEVEL 8
+#  else
+#    define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#  endif
+#endif
+/* default memLevel */
+
+/* tm_zip contain date/time info */
+typedef struct tm_zip_s
+{
+    uInt tm_sec;            /* seconds after the minute - [0,59] */
+    uInt tm_min;            /* minutes after the hour - [0,59] */
+    uInt tm_hour;           /* hours since midnight - [0,23] */
+    uInt tm_mday;           /* day of the month - [1,31] */
+    uInt tm_mon;            /* months since January - [0,11] */
+    uInt tm_year;           /* years - [1980..2044] */
+} tm_zip;
+
+typedef struct
+{
+    tm_zip      tmz_date;       /* date in understandable format           */
+    uLong       dosDate;       /* if dos_date == 0, tmu_date is used      */
+/*    uLong       flag;        */   /* general purpose bit flag        2 bytes */
+
+    uLong       internal_fa;    /* internal file attributes        2 bytes */
+    uLong       external_fa;    /* external file attributes        4 bytes */
+} zip_fileinfo;
+
+typedef const char* zipcharpc;
+
+
+#define APPEND_STATUS_CREATE        (0)
+#define APPEND_STATUS_CREATEAFTER   (1)
+#define APPEND_STATUS_ADDINZIP      (2)
+
+extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
+/*
+  Create a zipfile.
+     pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
+       an Unix computer "zlib/zlib113.zip".
+     if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
+       will be created at the end of the file.
+         (useful if the file contain a self extractor code)
+     if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
+       add files in existing zip (be sure you don't add file that doesn't exist)
+     If the zipfile cannot be opened, the return value is NULL.
+     Else, the return value is a zipFile Handle, usable with other function
+       of this zip package.
+*/
+
+/* Note : there is no delete function into a zipfile.
+   If you want delete file into a zipfile, you must open a zipfile, and create another
+   Of couse, you can use RAW reading and writing to copy the file you did not want delte
+*/
+
+extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
+                                   int append,
+                                   zipcharpc* globalcomment,
+                                   zlib_filefunc_def* pzlib_filefunc_def));
+
+extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
+                       const char* filename,
+                       const zip_fileinfo* zipfi,
+                       const void* extrafield_local,
+                       uInt size_extrafield_local,
+                       const void* extrafield_global,
+                       uInt size_extrafield_global,
+                       const char* comment,
+                       int method,
+                       int level));
+/*
+  Open a file in the ZIP for writing.
+  filename : the filename in zip (if NULL, '-' without quote will be used
+  *zipfi contain supplemental information
+  if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
+    contains the extrafield data the the local header
+  if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
+    contains the extrafield data the the local header
+  if comment != NULL, comment contain the comment string
+  method contain the compression method (0 for store, Z_DEFLATED for deflate)
+  level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
+*/
+
+
+extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
+                                            const char* filename,
+                                            const zip_fileinfo* zipfi,
+                                            const void* extrafield_local,
+                                            uInt size_extrafield_local,
+                                            const void* extrafield_global,
+                                            uInt size_extrafield_global,
+                                            const char* comment,
+                                            int method,
+                                            int level,
+                                            int raw));
+
+/*
+  Same than zipOpenNewFileInZip, except if raw=1, we write raw file
+ */
+
+extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
+                                            const char* filename,
+                                            const zip_fileinfo* zipfi,
+                                            const void* extrafield_local,
+                                            uInt size_extrafield_local,
+                                            const void* extrafield_global,
+                                            uInt size_extrafield_global,
+                                            const char* comment,
+                                            int method,
+                                            int level,
+                                            int raw,
+                                            int windowBits,
+                                            int memLevel,
+                                            int strategy,
+                                            const char* password,
+                                            uLong crcForCtypting));
+
+/*
+  Same than zipOpenNewFileInZip2, except
+    windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
+    password : crypting password (NULL for no crypting)
+    crcForCtypting : crc of file to compress (needed for crypting)
+ */
+
+
+extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
+                       const void* buf,
+                       unsigned len));
+/*
+  Write data in the zipfile
+*/
+
+extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
+/*
+  Close the current file in the zipfile
+*/
+
+extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
+                                            uLong uncompressed_size,
+                                            uLong crc32));
+/*
+  Close the current file in the zipfile, for fiel opened with
+    parameter raw=1 in zipOpenNewFileInZip2
+  uncompressed_size and crc32 are value for the uncompressed size
+*/
+
+extern int ZEXPORT zipClose OF((zipFile file,
+                const char* global_comment));
+/*
+  Close the zipfile
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _zip_H */
Index: /trunk/minix/lib/zlib-1.2.3/contrib/pascal/example.pas
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/pascal/example.pas	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/pascal/example.pas	(revision 9)
@@ -0,0 +1,599 @@
+(* example.c -- usage example of the zlib compression library
+ * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Pascal translation
+ * Copyright (C) 1998 by Jacques Nomssi Nzali.
+ * For conditions of distribution and use, see copyright notice in readme.txt
+ *
+ * Adaptation to the zlibpas interface
+ * Copyright (C) 2003 by Cosmin Truta.
+ * For conditions of distribution and use, see copyright notice in readme.txt
+ *)
+
+program example;
+
+{$DEFINE TEST_COMPRESS}
+{DO NOT $DEFINE TEST_GZIO}
+{$DEFINE TEST_DEFLATE}
+{$DEFINE TEST_INFLATE}
+{$DEFINE TEST_FLUSH}
+{$DEFINE TEST_SYNC}
+{$DEFINE TEST_DICT}
+
+uses SysUtils, zlibpas;
+
+const TESTFILE = 'foo.gz';
+
+(* "hello world" would be more standard, but the repeated "hello"
+ * stresses the compression code better, sorry...
+ *)
+const hello: PChar = 'hello, hello!';
+
+const dictionary: PChar = 'hello';
+
+var dictId: LongInt; (* Adler32 value of the dictionary *)
+
+procedure CHECK_ERR(err: Integer; msg: String);
+begin
+  if err <> Z_OK then
+  begin
+    WriteLn(msg, ' error: ', err);
+    Halt(1);
+  end;
+end;
+
+procedure EXIT_ERR(const msg: String);
+begin
+  WriteLn('Error: ', msg);
+  Halt(1);
+end;
+
+(* ===========================================================================
+ * Test compress and uncompress
+ *)
+{$IFDEF TEST_COMPRESS}
+procedure test_compress(compr: Pointer; comprLen: LongInt;
+                        uncompr: Pointer; uncomprLen: LongInt);
+var err: Integer;
+    len: LongInt;
+begin
+  len := StrLen(hello)+1;
+
+  err := compress(compr, comprLen, hello, len);
+  CHECK_ERR(err, 'compress');
+
+  StrCopy(PChar(uncompr), 'garbage');
+
+  err := uncompress(uncompr, uncomprLen, compr, comprLen);
+  CHECK_ERR(err, 'uncompress');
+
+  if StrComp(PChar(uncompr), hello) <> 0 then
+    EXIT_ERR('bad uncompress')
+  else
+    WriteLn('uncompress(): ', PChar(uncompr));
+end;
+{$ENDIF}
+
+(* ===========================================================================
+ * Test read/write of .gz files
+ *)
+{$IFDEF TEST_GZIO}
+procedure test_gzio(const fname: PChar; (* compressed file name *)
+                    uncompr: Pointer;
+                    uncomprLen: LongInt);
+var err: Integer;
+    len: Integer;
+    zfile: gzFile;
+    pos: LongInt;
+begin
+  len := StrLen(hello)+1;
+
+  zfile := gzopen(fname, 'wb');
+  if zfile = NIL then
+  begin
+    WriteLn('gzopen error');
+    Halt(1);
+  end;
+  gzputc(zfile, 'h');
+  if gzputs(zfile, 'ello') <> 4 then
+  begin
+    WriteLn('gzputs err: ', gzerror(zfile, err));
+    Halt(1);
+  end;
+  {$IFDEF GZ_FORMAT_STRING}
+  if gzprintf(zfile, ', %s!', 'hello') <> 8 then
+  begin
+    WriteLn('gzprintf err: ', gzerror(zfile, err));
+    Halt(1);
+  end;
+  {$ELSE}
+  if gzputs(zfile, ', hello!') <> 8 then
+  begin
+    WriteLn('gzputs err: ', gzerror(zfile, err));
+    Halt(1);
+  end;
+  {$ENDIF}
+  gzseek(zfile, 1, SEEK_CUR); (* add one zero byte *)
+  gzclose(zfile);
+
+  zfile := gzopen(fname, 'rb');
+  if zfile = NIL then
+  begin
+    WriteLn('gzopen error');
+    Halt(1);
+  end;
+
+  StrCopy(PChar(uncompr), 'garbage');
+
+  if gzread(zfile, uncompr, uncomprLen) <> len then
+  begin
+    WriteLn('gzread err: ', gzerror(zfile, err));
+    Halt(1);
+  end;
+  if StrComp(PChar(uncompr), hello) <> 0 then
+  begin
+    WriteLn('bad gzread: ', PChar(uncompr));
+    Halt(1);
+  end
+  else
+    WriteLn('gzread(): ', PChar(uncompr));
+
+  pos := gzseek(zfile, -8, SEEK_CUR);
+  if (pos <> 6) or (gztell(zfile) <> pos) then
+  begin
+    WriteLn('gzseek error, pos=', pos, ', gztell=', gztell(zfile));
+    Halt(1);
+  end;
+
+  if gzgetc(zfile) <> ' ' then
+  begin
+    WriteLn('gzgetc error');
+    Halt(1);
+  end;
+
+  if gzungetc(' ', zfile) <> ' ' then
+  begin
+    WriteLn('gzungetc error');
+    Halt(1);
+  end;
+
+  gzgets(zfile, PChar(uncompr), uncomprLen);
+  uncomprLen := StrLen(PChar(uncompr));
+  if uncomprLen <> 7 then (* " hello!" *)
+  begin
+    WriteLn('gzgets err after gzseek: ', gzerror(zfile, err));
+    Halt(1);
+  end;
+  if StrComp(PChar(uncompr), hello + 6) <> 0 then
+  begin
+    WriteLn('bad gzgets after gzseek');
+    Halt(1);
+  end
+  else
+    WriteLn('gzgets() after gzseek: ', PChar(uncompr));
+
+  gzclose(zfile);
+end;
+{$ENDIF}
+
+(* ===========================================================================
+ * Test deflate with small buffers
+ *)
+{$IFDEF TEST_DEFLATE}
+procedure test_deflate(compr: Pointer; comprLen: LongInt);
+var c_stream: z_stream; (* compression stream *)
+    err: Integer;
+    len: LongInt;
+begin
+  len := StrLen(hello)+1;
+
+  c_stream.zalloc := NIL;
+  c_stream.zfree := NIL;
+  c_stream.opaque := NIL;
+
+  err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION);
+  CHECK_ERR(err, 'deflateInit');
+
+  c_stream.next_in := hello;
+  c_stream.next_out := compr;
+
+  while (c_stream.total_in <> len) and
+        (c_stream.total_out < comprLen) do
+  begin
+    c_stream.avail_out := 1; { force small buffers }
+    c_stream.avail_in := 1;
+    err := deflate(c_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, 'deflate');
+  end;
+
+  (* Finish the stream, still forcing small buffers: *)
+  while TRUE do
+  begin
+    c_stream.avail_out := 1;
+    err := deflate(c_stream, Z_FINISH);
+    if err = Z_STREAM_END then
+      break;
+    CHECK_ERR(err, 'deflate');
+  end;
+
+  err := deflateEnd(c_stream);
+  CHECK_ERR(err, 'deflateEnd');
+end;
+{$ENDIF}
+
+(* ===========================================================================
+ * Test inflate with small buffers
+ *)
+{$IFDEF TEST_INFLATE}
+procedure test_inflate(compr: Pointer; comprLen : LongInt;
+                       uncompr: Pointer; uncomprLen : LongInt);
+var err: Integer;
+    d_stream: z_stream; (* decompression stream *)
+begin
+  StrCopy(PChar(uncompr), 'garbage');
+
+  d_stream.zalloc := NIL;
+  d_stream.zfree := NIL;
+  d_stream.opaque := NIL;
+
+  d_stream.next_in := compr;
+  d_stream.avail_in := 0;
+  d_stream.next_out := uncompr;
+
+  err := inflateInit(d_stream);
+  CHECK_ERR(err, 'inflateInit');
+
+  while (d_stream.total_out < uncomprLen) and
+        (d_stream.total_in < comprLen) do
+  begin
+    d_stream.avail_out := 1; (* force small buffers *)
+    d_stream.avail_in := 1;
+    err := inflate(d_stream, Z_NO_FLUSH);
+    if err = Z_STREAM_END then
+      break;
+    CHECK_ERR(err, 'inflate');
+  end;
+
+  err := inflateEnd(d_stream);
+  CHECK_ERR(err, 'inflateEnd');
+
+  if StrComp(PChar(uncompr), hello) <> 0 then
+    EXIT_ERR('bad inflate')
+  else
+    WriteLn('inflate(): ', PChar(uncompr));
+end;
+{$ENDIF}
+
+(* ===========================================================================
+ * Test deflate with large buffers and dynamic change of compression level
+ *)
+{$IFDEF TEST_DEFLATE}
+procedure test_large_deflate(compr: Pointer; comprLen: LongInt;
+                             uncompr: Pointer; uncomprLen: LongInt);
+var c_stream: z_stream; (* compression stream *)
+    err: Integer;
+begin
+  c_stream.zalloc := NIL;
+  c_stream.zfree := NIL;
+  c_stream.opaque := NIL;
+
+  err := deflateInit(c_stream, Z_BEST_SPEED);
+  CHECK_ERR(err, 'deflateInit');
+
+  c_stream.next_out := compr;
+  c_stream.avail_out := Integer(comprLen);
+
+  (* At this point, uncompr is still mostly zeroes, so it should compress
+   * very well:
+   *)
+  c_stream.next_in := uncompr;
+  c_stream.avail_in := Integer(uncomprLen);
+  err := deflate(c_stream, Z_NO_FLUSH);
+  CHECK_ERR(err, 'deflate');
+  if c_stream.avail_in <> 0 then
+    EXIT_ERR('deflate not greedy');
+
+  (* Feed in already compressed data and switch to no compression: *)
+  deflateParams(c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
+  c_stream.next_in := compr;
+  c_stream.avail_in := Integer(comprLen div 2);
+  err := deflate(c_stream, Z_NO_FLUSH);
+  CHECK_ERR(err, 'deflate');
+
+  (* Switch back to compressing mode: *)
+  deflateParams(c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
+  c_stream.next_in := uncompr;
+  c_stream.avail_in := Integer(uncomprLen);
+  err := deflate(c_stream, Z_NO_FLUSH);
+  CHECK_ERR(err, 'deflate');
+
+  err := deflate(c_stream, Z_FINISH);
+  if err <> Z_STREAM_END then
+    EXIT_ERR('deflate should report Z_STREAM_END');
+
+  err := deflateEnd(c_stream);
+  CHECK_ERR(err, 'deflateEnd');
+end;
+{$ENDIF}
+
+(* ===========================================================================
+ * Test inflate with large buffers
+ *)
+{$IFDEF TEST_INFLATE}
+procedure test_large_inflate(compr: Pointer; comprLen: LongInt;
+                             uncompr: Pointer; uncomprLen: LongInt);
+var err: Integer;
+    d_stream: z_stream; (* decompression stream *)
+begin
+  StrCopy(PChar(uncompr), 'garbage');
+
+  d_stream.zalloc := NIL;
+  d_stream.zfree := NIL;
+  d_stream.opaque := NIL;
+
+  d_stream.next_in := compr;
+  d_stream.avail_in := Integer(comprLen);
+
+  err := inflateInit(d_stream);
+  CHECK_ERR(err, 'inflateInit');
+
+  while TRUE do
+  begin
+    d_stream.next_out := uncompr;            (* discard the output *)
+    d_stream.avail_out := Integer(uncomprLen);
+    err := inflate(d_stream, Z_NO_FLUSH);
+    if err = Z_STREAM_END then
+      break;
+    CHECK_ERR(err, 'large inflate');
+  end;
+
+  err := inflateEnd(d_stream);
+  CHECK_ERR(err, 'inflateEnd');
+
+  if d_stream.total_out <> 2 * uncomprLen + comprLen div 2 then
+  begin
+    WriteLn('bad large inflate: ', d_stream.total_out);
+    Halt(1);
+  end
+  else
+    WriteLn('large_inflate(): OK');
+end;
+{$ENDIF}
+
+(* ===========================================================================
+ * Test deflate with full flush
+ *)
+{$IFDEF TEST_FLUSH}
+procedure test_flush(compr: Pointer; var comprLen : LongInt);
+var c_stream: z_stream; (* compression stream *)
+    err: Integer;
+    len: Integer;
+begin
+  len := StrLen(hello)+1;
+
+  c_stream.zalloc := NIL;
+  c_stream.zfree := NIL;
+  c_stream.opaque := NIL;
+
+  err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION);
+  CHECK_ERR(err, 'deflateInit');
+
+  c_stream.next_in := hello;
+  c_stream.next_out := compr;
+  c_stream.avail_in := 3;
+  c_stream.avail_out := Integer(comprLen);
+  err := deflate(c_stream, Z_FULL_FLUSH);
+  CHECK_ERR(err, 'deflate');
+
+  Inc(PByteArray(compr)^[3]); (* force an error in first compressed block *)
+  c_stream.avail_in := len - 3;
+
+  err := deflate(c_stream, Z_FINISH);
+  if err <> Z_STREAM_END then
+    CHECK_ERR(err, 'deflate');
+
+  err := deflateEnd(c_stream);
+  CHECK_ERR(err, 'deflateEnd');
+
+  comprLen := c_stream.total_out;
+end;
+{$ENDIF}
+
+(* ===========================================================================
+ * Test inflateSync()
+ *)
+{$IFDEF TEST_SYNC}
+procedure test_sync(compr: Pointer; comprLen: LongInt;
+                    uncompr: Pointer; uncomprLen : LongInt);
+var err: Integer;
+    d_stream: z_stream; (* decompression stream *)
+begin
+  StrCopy(PChar(uncompr), 'garbage');
+
+  d_stream.zalloc := NIL;
+  d_stream.zfree := NIL;
+  d_stream.opaque := NIL;
+
+  d_stream.next_in := compr;
+  d_stream.avail_in := 2; (* just read the zlib header *)
+
+  err := inflateInit(d_stream);
+  CHECK_ERR(err, 'inflateInit');
+
+  d_stream.next_out := uncompr;
+  d_stream.avail_out := Integer(uncomprLen);
+
+  inflate(d_stream, Z_NO_FLUSH);
+  CHECK_ERR(err, 'inflate');
+
+  d_stream.avail_in := Integer(comprLen-2);   (* read all compressed data *)
+  err := inflateSync(d_stream);               (* but skip the damaged part *)
+  CHECK_ERR(err, 'inflateSync');
+
+  err := inflate(d_stream, Z_FINISH);
+  if err <> Z_DATA_ERROR then
+    EXIT_ERR('inflate should report DATA_ERROR');
+    (* Because of incorrect adler32 *)
+
+  err := inflateEnd(d_stream);
+  CHECK_ERR(err, 'inflateEnd');
+
+  WriteLn('after inflateSync(): hel', PChar(uncompr));
+end;
+{$ENDIF}
+
+(* ===========================================================================
+ * Test deflate with preset dictionary
+ *)
+{$IFDEF TEST_DICT}
+procedure test_dict_deflate(compr: Pointer; comprLen: LongInt);
+var c_stream: z_stream; (* compression stream *)
+    err: Integer;
+begin
+  c_stream.zalloc := NIL;
+  c_stream.zfree := NIL;
+  c_stream.opaque := NIL;
+
+  err := deflateInit(c_stream, Z_BEST_COMPRESSION);
+  CHECK_ERR(err, 'deflateInit');
+
+  err := deflateSetDictionary(c_stream, dictionary, StrLen(dictionary));
+  CHECK_ERR(err, 'deflateSetDictionary');
+
+  dictId := c_stream.adler;
+  c_stream.next_out := compr;
+  c_stream.avail_out := Integer(comprLen);
+
+  c_stream.next_in := hello;
+  c_stream.avail_in := StrLen(hello)+1;
+
+  err := deflate(c_stream, Z_FINISH);
+  if err <> Z_STREAM_END then
+    EXIT_ERR('deflate should report Z_STREAM_END');
+
+  err := deflateEnd(c_stream);
+  CHECK_ERR(err, 'deflateEnd');
+end;
+{$ENDIF}
+
+(* ===========================================================================
+ * Test inflate with a preset dictionary
+ *)
+{$IFDEF TEST_DICT}
+procedure test_dict_inflate(compr: Pointer; comprLen: LongInt;
+                            uncompr: Pointer; uncomprLen: LongInt);
+var err: Integer;
+    d_stream: z_stream; (* decompression stream *)
+begin
+  StrCopy(PChar(uncompr), 'garbage');
+
+  d_stream.zalloc := NIL;
+  d_stream.zfree := NIL;
+  d_stream.opaque := NIL;
+
+  d_stream.next_in := compr;
+  d_stream.avail_in := Integer(comprLen);
+
+  err := inflateInit(d_stream);
+  CHECK_ERR(err, 'inflateInit');
+
+  d_stream.next_out := uncompr;
+  d_stream.avail_out := Integer(uncomprLen);
+
+  while TRUE do
+  begin
+    err := inflate(d_stream, Z_NO_FLUSH);
+    if err = Z_STREAM_END then
+      break;
+    if err = Z_NEED_DICT then
+    begin
+      if d_stream.adler <> dictId then
+        EXIT_ERR('unexpected dictionary');
+      err := inflateSetDictionary(d_stream, dictionary, StrLen(dictionary));
+    end;
+    CHECK_ERR(err, 'inflate with dict');
+  end;
+
+  err := inflateEnd(d_stream);
+  CHECK_ERR(err, 'inflateEnd');
+
+  if StrComp(PChar(uncompr), hello) <> 0 then
+    EXIT_ERR('bad inflate with dict')
+  else
+    WriteLn('inflate with dictionary: ', PChar(uncompr));
+end;
+{$ENDIF}
+
+var compr, uncompr: Pointer;
+    comprLen, uncomprLen: LongInt;
+
+begin
+  if zlibVersion^ <> ZLIB_VERSION[1] then
+    EXIT_ERR('Incompatible zlib version');
+
+  WriteLn('zlib version: ', zlibVersion);
+  WriteLn('zlib compile flags: ', Format('0x%x', [zlibCompileFlags]));
+
+  comprLen := 10000 * SizeOf(Integer); (* don't overflow on MSDOS *)
+  uncomprLen := comprLen;
+  GetMem(compr, comprLen);
+  GetMem(uncompr, uncomprLen);
+  if (compr = NIL) or (uncompr = NIL) then
+    EXIT_ERR('Out of memory');
+  (* compr and uncompr are cleared to avoid reading uninitialized
+   * data and to ensure that uncompr compresses well.
+   *)
+  FillChar(compr^, comprLen, 0);
+  FillChar(uncompr^, uncomprLen, 0);
+
+  {$IFDEF TEST_COMPRESS}
+  WriteLn('** Testing compress');
+  test_compress(compr, comprLen, uncompr, uncomprLen);
+  {$ENDIF}
+
+  {$IFDEF TEST_GZIO}
+  WriteLn('** Testing gzio');
+  if ParamCount >= 1 then
+    test_gzio(ParamStr(1), uncompr, uncomprLen)
+  else
+    test_gzio(TESTFILE, uncompr, uncomprLen);
+  {$ENDIF}
+
+  {$IFDEF TEST_DEFLATE}
+  WriteLn('** Testing deflate with small buffers');
+  test_deflate(compr, comprLen);
+  {$ENDIF}
+  {$IFDEF TEST_INFLATE}
+  WriteLn('** Testing inflate with small buffers');
+  test_inflate(compr, comprLen, uncompr, uncomprLen);
+  {$ENDIF}
+
+  {$IFDEF TEST_DEFLATE}
+  WriteLn('** Testing deflate with large buffers');
+  test_large_deflate(compr, comprLen, uncompr, uncomprLen);
+  {$ENDIF}
+  {$IFDEF TEST_INFLATE}
+  WriteLn('** Testing inflate with large buffers');
+  test_large_inflate(compr, comprLen, uncompr, uncomprLen);
+  {$ENDIF}
+
+  {$IFDEF TEST_FLUSH}
+  WriteLn('** Testing deflate with full flush');
+  test_flush(compr, comprLen);
+  {$ENDIF}
+  {$IFDEF TEST_SYNC}
+  WriteLn('** Testing inflateSync');
+  test_sync(compr, comprLen, uncompr, uncomprLen);
+  {$ENDIF}
+  comprLen := uncomprLen;
+
+  {$IFDEF TEST_DICT}
+  WriteLn('** Testing deflate and inflate with preset dictionary');
+  test_dict_deflate(compr, comprLen);
+  test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
+  {$ENDIF}
+
+  FreeMem(compr, comprLen);
+  FreeMem(uncompr, uncomprLen);
+end.
Index: /trunk/minix/lib/zlib-1.2.3/contrib/pascal/readme.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/pascal/readme.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/pascal/readme.txt	(revision 9)
@@ -0,0 +1,76 @@
+
+This directory contains a Pascal (Delphi, Kylix) interface to the
+zlib data compression library.
+
+
+Directory listing
+=================
+
+zlibd32.mak     makefile for Borland C++
+example.pas     usage example of zlib
+zlibpas.pas     the Pascal interface to zlib
+readme.txt      this file
+
+
+Compatibility notes
+===================
+
+- Although the name "zlib" would have been more normal for the
+  zlibpas unit, this name is already taken by Borland's ZLib unit.
+  This is somehow unfortunate, because that unit is not a genuine
+  interface to the full-fledged zlib functionality, but a suite of
+  class wrappers around zlib streams.  Other essential features,
+  such as checksums, are missing.
+  It would have been more appropriate for that unit to have a name
+  like "ZStreams", or something similar.
+
+- The C and zlib-supplied types int, uInt, long, uLong, etc. are
+  translated directly into Pascal types of similar sizes (Integer,
+  LongInt, etc.), to avoid namespace pollution.  In particular,
+  there is no conversion of unsigned int into a Pascal unsigned
+  integer.  The Word type is non-portable and has the same size
+  (16 bits) both in a 16-bit and in a 32-bit environment, unlike
+  Integer.  Even if there is a 32-bit Cardinal type, there is no
+  real need for unsigned int in zlib under a 32-bit environment.
+
+- Except for the callbacks, the zlib function interfaces are
+  assuming the calling convention normally used in Pascal
+  (__pascal for DOS and Windows16, __fastcall for Windows32).
+  Since the cdecl keyword is used, the old Turbo Pascal does
+  not work with this interface.
+
+- The gz* function interfaces are not translated, to avoid
+  interfacing problems with the C runtime library.  Besides,
+    gzprintf(gzFile file, const char *format, ...)
+  cannot be translated into Pascal.
+
+
+Legal issues
+============
+
+The zlibpas interface is:
+  Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler.
+  Copyright (C) 1998 by Bob Dellaca.
+  Copyright (C) 2003 by Cosmin Truta.
+
+The example program is:
+  Copyright (C) 1995-2003 by Jean-loup Gailly.
+  Copyright (C) 1998,1999,2000 by Jacques Nomssi Nzali.
+  Copyright (C) 2003 by Cosmin Truta.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the author be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
Index: /trunk/minix/lib/zlib-1.2.3/contrib/pascal/zlibd32.mak
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/pascal/zlibd32.mak	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/pascal/zlibd32.mak	(revision 9)
@@ -0,0 +1,93 @@
+# Makefile for zlib
+# For use with Delphi and C++ Builder under Win32
+# Updated for zlib 1.2.x by Cosmin Truta
+
+# ------------ Borland C++ ------------
+
+# This project uses the Delphi (fastcall/register) calling convention:
+LOC = -DZEXPORT=__fastcall -DZEXPORTVA=__cdecl
+
+CC = bcc32
+LD = bcc32
+AR = tlib
+# do not use "-pr" in CFLAGS
+CFLAGS = -a -d -k- -O2 $(LOC)
+LDFLAGS =
+
+
+# variables
+ZLIB_LIB = zlib.lib
+
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
+OBJ2 = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infback.obj
+OBJP2 = +inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+
+
+# targets
+all: $(ZLIB_LIB) example.exe minigzip.exe
+
+.c.obj:
+	$(CC) -c $(CFLAGS) $*.c
+
+adler32.obj: adler32.c zlib.h zconf.h
+
+compress.obj: compress.c zlib.h zconf.h
+
+crc32.obj: crc32.c zlib.h zconf.h crc32.h
+
+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
+
+gzio.obj: gzio.c zutil.h zlib.h zconf.h
+
+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h
+
+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
+
+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
+
+uncompr.obj: uncompr.c zlib.h zconf.h
+
+zutil.obj: zutil.c zutil.h zlib.h zconf.h
+
+example.obj: example.c zlib.h zconf.h
+
+minigzip.obj: minigzip.c zlib.h zconf.h
+
+
+# For the sake of the old Borland make,
+# the command line is cut to fit in the MS-DOS 128 byte limit:
+$(ZLIB_LIB): $(OBJ1) $(OBJ2)
+	-del $(ZLIB_LIB)
+	$(AR) $(ZLIB_LIB) $(OBJP1)
+	$(AR) $(ZLIB_LIB) $(OBJP2)
+
+
+# testing
+test: example.exe minigzip.exe
+	example
+	echo hello world | minigzip | minigzip -d
+
+example.exe: example.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) example.obj $(ZLIB_LIB)
+
+minigzip.exe: minigzip.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB)
+
+
+# cleanup
+clean:
+	-del *.obj
+	-del *.exe
+	-del *.lib
+	-del *.tds
+	-del zlib.bak
+	-del foo.gz
+
Index: /trunk/minix/lib/zlib-1.2.3/contrib/pascal/zlibpas.pas
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/pascal/zlibpas.pas	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/pascal/zlibpas.pas	(revision 9)
@@ -0,0 +1,236 @@
+(* zlibpas -- Pascal interface to the zlib data compression library
+ *
+ * Copyright (C) 2003 Cosmin Truta.
+ * Derived from original sources by Bob Dellaca.
+ * For conditions of distribution and use, see copyright notice in readme.txt
+ *)
+
+unit zlibpas;
+
+interface
+
+const
+  ZLIB_VERSION = '1.2.3';
+
+type
+  alloc_func = function(opaque: Pointer; items, size: Integer): Pointer;
+                 cdecl;
+  free_func  = procedure(opaque, address: Pointer);
+                 cdecl;
+
+  in_func    = function(opaque: Pointer; var buf: PByte): Integer;
+                 cdecl;
+  out_func   = function(opaque: Pointer; buf: PByte; size: Integer): Integer;
+                 cdecl;
+
+  z_streamp = ^z_stream;
+  z_stream = packed record
+    next_in: PChar;       (* next input byte *)
+    avail_in: Integer;    (* number of bytes available at next_in *)
+    total_in: LongInt;    (* total nb of input bytes read so far *)
+
+    next_out: PChar;      (* next output byte should be put there *)
+    avail_out: Integer;   (* remaining free space at next_out *)
+    total_out: LongInt;   (* total nb of bytes output so far *)
+
+    msg: PChar;           (* last error message, NULL if no error *)
+    state: Pointer;       (* not visible by applications *)
+
+    zalloc: alloc_func;   (* used to allocate the internal state *)
+    zfree: free_func;     (* used to free the internal state *)
+    opaque: Pointer;      (* private data object passed to zalloc and zfree *)
+
+    data_type: Integer;   (* best guess about the data type: ascii or binary *)
+    adler: LongInt;       (* adler32 value of the uncompressed data *)
+    reserved: LongInt;    (* reserved for future use *)
+  end;
+
+(* constants *)
+const
+  Z_NO_FLUSH      = 0;
+  Z_PARTIAL_FLUSH = 1;
+  Z_SYNC_FLUSH    = 2;
+  Z_FULL_FLUSH    = 3;
+  Z_FINISH        = 4;
+
+  Z_OK            =  0;
+  Z_STREAM_END    =  1;
+  Z_NEED_DICT     =  2;
+  Z_ERRNO         = -1;
+  Z_STREAM_ERROR  = -2;
+  Z_DATA_ERROR    = -3;
+  Z_MEM_ERROR     = -4;
+  Z_BUF_ERROR     = -5;
+  Z_VERSION_ERROR = -6;
+
+  Z_NO_COMPRESSION       =  0;
+  Z_BEST_SPEED           =  1;
+  Z_BEST_COMPRESSION     =  9;
+  Z_DEFAULT_COMPRESSION  = -1;
+
+  Z_FILTERED            = 1;
+  Z_HUFFMAN_ONLY        = 2;
+  Z_RLE                 = 3;
+  Z_DEFAULT_STRATEGY    = 0;
+
+  Z_BINARY   = 0;
+  Z_ASCII    = 1;
+  Z_UNKNOWN  = 2;
+
+  Z_DEFLATED = 8;
+
+(* basic functions *)
+function zlibVersion: PChar;
+function deflateInit(var strm: z_stream; level: Integer): Integer;
+function deflate(var strm: z_stream; flush: Integer): Integer;
+function deflateEnd(var strm: z_stream): Integer;
+function inflateInit(var strm: z_stream): Integer;
+function inflate(var strm: z_stream; flush: Integer): Integer;
+function inflateEnd(var strm: z_stream): Integer;
+
+(* advanced functions *)
+function deflateInit2(var strm: z_stream; level, method, windowBits,
+                      memLevel, strategy: Integer): Integer;
+function deflateSetDictionary(var strm: z_stream; const dictionary: PChar;
+                              dictLength: Integer): Integer;
+function deflateCopy(var dest, source: z_stream): Integer;
+function deflateReset(var strm: z_stream): Integer;
+function deflateParams(var strm: z_stream; level, strategy: Integer): Integer;
+function deflateBound(var strm: z_stream; sourceLen: LongInt): LongInt;
+function deflatePrime(var strm: z_stream; bits, value: Integer): Integer;
+function inflateInit2(var strm: z_stream; windowBits: Integer): Integer;
+function inflateSetDictionary(var strm: z_stream; const dictionary: PChar;
+                              dictLength: Integer): Integer;
+function inflateSync(var strm: z_stream): Integer;
+function inflateCopy(var dest, source: z_stream): Integer;
+function inflateReset(var strm: z_stream): Integer;
+function inflateBackInit(var strm: z_stream;
+                         windowBits: Integer; window: PChar): Integer;
+function inflateBack(var strm: z_stream; in_fn: in_func; in_desc: Pointer;
+                     out_fn: out_func; out_desc: Pointer): Integer;
+function inflateBackEnd(var strm: z_stream): Integer;
+function zlibCompileFlags: LongInt;
+
+(* utility functions *)
+function compress(dest: PChar; var destLen: LongInt;
+                  const source: PChar; sourceLen: LongInt): Integer;
+function compress2(dest: PChar; var destLen: LongInt;
+                  const source: PChar; sourceLen: LongInt;
+                  level: Integer): Integer;
+function compressBound(sourceLen: LongInt): LongInt;
+function uncompress(dest: PChar; var destLen: LongInt;
+                    const source: PChar; sourceLen: LongInt): Integer;
+
+(* checksum functions *)
+function adler32(adler: LongInt; const buf: PChar; len: Integer): LongInt;
+function crc32(crc: LongInt; const buf: PChar; len: Integer): LongInt;
+
+(* various hacks, don't look :) *)
+function deflateInit_(var strm: z_stream; level: Integer;
+                      const version: PChar; stream_size: Integer): Integer;
+function inflateInit_(var strm: z_stream; const version: PChar;
+                      stream_size: Integer): Integer;
+function deflateInit2_(var strm: z_stream;
+                       level, method, windowBits, memLevel, strategy: Integer;
+                       const version: PChar; stream_size: Integer): Integer;
+function inflateInit2_(var strm: z_stream; windowBits: Integer;
+                       const version: PChar; stream_size: Integer): Integer;
+function inflateBackInit_(var strm: z_stream;
+                          windowBits: Integer; window: PChar;
+                          const version: PChar; stream_size: Integer): Integer;
+
+
+implementation
+
+{$L adler32.obj}
+{$L compress.obj}
+{$L crc32.obj}
+{$L deflate.obj}
+{$L infback.obj}
+{$L inffast.obj}
+{$L inflate.obj}
+{$L inftrees.obj}
+{$L trees.obj}
+{$L uncompr.obj}
+{$L zutil.obj}
+
+function adler32; external;
+function compress; external;
+function compress2; external;
+function compressBound; external;
+function crc32; external;
+function deflate; external;
+function deflateBound; external;
+function deflateCopy; external;
+function deflateEnd; external;
+function deflateInit_; external;
+function deflateInit2_; external;
+function deflateParams; external;
+function deflatePrime; external;
+function deflateReset; external;
+function deflateSetDictionary; external;
+function inflate; external;
+function inflateBack; external;
+function inflateBackEnd; external;
+function inflateBackInit_; external;
+function inflateCopy; external;
+function inflateEnd; external;
+function inflateInit_; external;
+function inflateInit2_; external;
+function inflateReset; external;
+function inflateSetDictionary; external;
+function inflateSync; external;
+function uncompress; external;
+function zlibCompileFlags; external;
+function zlibVersion; external;
+
+function deflateInit(var strm: z_stream; level: Integer): Integer;
+begin
+  Result := deflateInit_(strm, level, ZLIB_VERSION, sizeof(z_stream));
+end;
+
+function deflateInit2(var strm: z_stream; level, method, windowBits, memLevel,
+                      strategy: Integer): Integer;
+begin
+  Result := deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+                          ZLIB_VERSION, sizeof(z_stream));
+end;
+
+function inflateInit(var strm: z_stream): Integer;
+begin
+  Result := inflateInit_(strm, ZLIB_VERSION, sizeof(z_stream));
+end;
+
+function inflateInit2(var strm: z_stream; windowBits: Integer): Integer;
+begin
+  Result := inflateInit2_(strm, windowBits, ZLIB_VERSION, sizeof(z_stream));
+end;
+
+function inflateBackInit(var strm: z_stream;
+                         windowBits: Integer; window: PChar): Integer;
+begin
+  Result := inflateBackInit_(strm, windowBits, window,
+                             ZLIB_VERSION, sizeof(z_stream));
+end;
+
+function _malloc(Size: Integer): Pointer; cdecl;
+begin
+  GetMem(Result, Size);
+end;
+
+procedure _free(Block: Pointer); cdecl;
+begin
+  FreeMem(Block);
+end;
+
+procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl;
+begin
+  FillChar(P^, count, B);
+end;
+
+procedure _memcpy(dest, source: Pointer; count: Integer); cdecl;
+begin
+  Move(source^, dest^, count);
+end;
+
+end.
Index: /trunk/minix/lib/zlib-1.2.3/contrib/puff/Makefile
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/puff/Makefile	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/puff/Makefile	(revision 9)
@@ -0,0 +1,8 @@
+puff: puff.c puff.h
+	cc -DTEST -o puff puff.c
+
+test: puff
+	puff zeros.raw
+
+clean:
+	rm -f puff puff.o
Index: /trunk/minix/lib/zlib-1.2.3/contrib/puff/README
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/puff/README	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/puff/README	(revision 9)
@@ -0,0 +1,63 @@
+Puff -- A Simple Inflate
+3 Mar 2003
+Mark Adler
+madler@alumni.caltech.edu
+
+What this is --
+
+puff.c provides the routine puff() to decompress the deflate data format.  It
+does so more slowly than zlib, but the code is about one-fifth the size of the
+inflate code in zlib, and written to be very easy to read.
+
+Why I wrote this --
+
+puff.c was written to document the deflate format unambiguously, by virtue of
+being working C code.  It is meant to supplement RFC 1951, which formally
+describes the deflate format.  I have received many questions on details of the
+deflate format, and I hope that reading this code will answer those questions.
+puff.c is heavily commented with details of the deflate format, especially
+those little nooks and cranies of the format that might not be obvious from a
+specification.
+
+puff.c may also be useful in applications where code size or memory usage is a
+very limited resource, and speed is not as important.
+
+How to use it --
+
+Well, most likely you should just be reading puff.c and using zlib for actual
+applications, but if you must ...
+
+Include puff.h in your code, which provides this prototype:
+
+int puff(unsigned char *dest,           /* pointer to destination pointer */
+         unsigned long *destlen,        /* amount of output space */
+         unsigned char *source,         /* pointer to source data pointer */
+         unsigned long *sourcelen);     /* amount of input available */
+
+Then you can call puff() to decompress a deflate stream that is in memory in
+its entirety at source, to a sufficiently sized block of memory for the
+decompressed data at dest.  puff() is the only external symbol in puff.c  The
+only C library functions that puff.c needs are setjmp() and longjmp(), which
+are used to simplify error checking in the code to improve readabilty.  puff.c
+does no memory allocation, and uses less than 2K bytes off of the stack.
+
+If destlen is not enough space for the uncompressed data, then inflate will
+return an error without writing more than destlen bytes.  Note that this means
+that in order to decompress the deflate data successfully, you need to know
+the size of the uncompressed data ahead of time.
+
+If needed, puff() can determine the size of the uncompressed data with no
+output space.  This is done by passing dest equal to (unsigned char *)0.  Then
+the initial value of *destlen is ignored and *destlen is set to the length of
+the uncompressed data.  So if the size of the uncompressed data is not known,
+then two passes of puff() can be used--first to determine the size, and second
+to do the actual inflation after allocating the appropriate memory.  Not
+pretty, but it works.  (This is one of the reasons you should be using zlib.)
+
+The deflate format is self-terminating.  If the deflate stream does not end
+in *sourcelen bytes, puff() will return an error without reading at or past
+endsource.
+
+On return, *sourcelen is updated to the amount of input data consumed, and
+*destlen is updated to the size of the uncompressed data.  See the comments
+in puff.c for the possible return codes for puff().
Index: /trunk/minix/lib/zlib-1.2.3/contrib/puff/puff.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/puff/puff.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/puff/puff.c	(revision 9)
@@ -0,0 +1,837 @@
+/*
+ * puff.c
+ * Copyright (C) 2002-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in puff.h
+ * version 1.8, 9 Jan 2004
+ *
+ * puff.c is a simple inflate written to be an unambiguous way to specify the
+ * deflate format.  It is not written for speed but rather simplicity.  As a
+ * side benefit, this code might actually be useful when small code is more
+ * important than speed, such as bootstrap applications.  For typical deflate
+ * data, zlib's inflate() is about four times as fast as puff().  zlib's
+ * inflate compiles to around 20K on my machine, whereas puff.c compiles to
+ * around 4K on my machine (a PowerPC using GNU cc).  If the faster decode()
+ * function here is used, then puff() is only twice as slow as zlib's
+ * inflate().
+ *
+ * All dynamically allocated memory comes from the stack.  The stack required
+ * is less than 2K bytes.  This code is compatible with 16-bit int's and
+ * assumes that long's are at least 32 bits.  puff.c uses the short data type,
+ * assumed to be 16 bits, for arrays in order to to conserve memory.  The code
+ * works whether integers are stored big endian or little endian.
+ *
+ * In the comments below are "Format notes" that describe the inflate process
+ * and document some of the less obvious aspects of the format.  This source
+ * code is meant to supplement RFC 1951, which formally describes the deflate
+ * format:
+ *
+ *    http://www.zlib.org/rfc-deflate.html
+ */
+
+/*
+ * Change history:
+ *
+ * 1.0  10 Feb 2002     - First version
+ * 1.1  17 Feb 2002     - Clarifications of some comments and notes
+ *                      - Update puff() dest and source pointers on negative
+ *                        errors to facilitate debugging deflators
+ *                      - Remove longest from struct huffman -- not needed
+ *                      - Simplify offs[] index in construct()
+ *                      - Add input size and checking, using longjmp() to
+ *                        maintain easy readability
+ *                      - Use short data type for large arrays
+ *                      - Use pointers instead of long to specify source and
+ *                        destination sizes to avoid arbitrary 4 GB limits
+ * 1.2  17 Mar 2002     - Add faster version of decode(), doubles speed (!),
+ *                        but leave simple version for readabilty
+ *                      - Make sure invalid distances detected if pointers
+ *                        are 16 bits
+ *                      - Fix fixed codes table error
+ *                      - Provide a scanning mode for determining size of
+ *                        uncompressed data
+ * 1.3  20 Mar 2002     - Go back to lengths for puff() parameters [Jean-loup]
+ *                      - Add a puff.h file for the interface
+ *                      - Add braces in puff() for else do [Jean-loup]
+ *                      - Use indexes instead of pointers for readability
+ * 1.4  31 Mar 2002     - Simplify construct() code set check
+ *                      - Fix some comments
+ *                      - Add FIXLCODES #define
+ * 1.5   6 Apr 2002     - Minor comment fixes
+ * 1.6   7 Aug 2002     - Minor format changes
+ * 1.7   3 Mar 2003     - Added test code for distribution
+ *                      - Added zlib-like license
+ * 1.8   9 Jan 2004     - Added some comments on no distance codes case
+ */
+
+#include <setjmp.h>             /* for setjmp(), longjmp(), and jmp_buf */
+#include "puff.h"               /* prototype for puff() */
+
+#define local static            /* for local function definitions */
+#define NIL ((unsigned char *)0)        /* for no output option */
+
+/*
+ * Maximums for allocations and loops.  It is not useful to change these --
+ * they are fixed by the deflate format.
+ */
+#define MAXBITS 15              /* maximum bits in a code */
+#define MAXLCODES 286           /* maximum number of literal/length codes */
+#define MAXDCODES 30            /* maximum number of distance codes */
+#define MAXCODES (MAXLCODES+MAXDCODES)  /* maximum codes lengths to read */
+#define FIXLCODES 288           /* number of fixed literal/length codes */
+
+/* input and output state */
+struct state {
+    /* output state */
+    unsigned char *out;         /* output buffer */
+    unsigned long outlen;       /* available space at out */
+    unsigned long outcnt;       /* bytes written to out so far */
+
+    /* input state */
+    unsigned char *in;          /* input buffer */
+    unsigned long inlen;        /* available input at in */
+    unsigned long incnt;        /* bytes read so far */
+    int bitbuf;                 /* bit buffer */
+    int bitcnt;                 /* number of bits in bit buffer */
+
+    /* input limit error return state for bits() and decode() */
+    jmp_buf env;
+};
+
+/*
+ * Return need bits from the input stream.  This always leaves less than
+ * eight bits in the buffer.  bits() works properly for need == 0.
+ *
+ * Format notes:
+ *
+ * - Bits are stored in bytes from the least significant bit to the most
+ *   significant bit.  Therefore bits are dropped from the bottom of the bit
+ *   buffer, using shift right, and new bytes are appended to the top of the
+ *   bit buffer, using shift left.
+ */
+local int bits(struct state *s, int need)
+{
+    long val;           /* bit accumulator (can use up to 20 bits) */
+
+    /* load at least need bits into val */
+    val = s->bitbuf;
+    while (s->bitcnt < need) {
+        if (s->incnt == s->inlen) longjmp(s->env, 1);   /* out of input */
+        val |= (long)(s->in[s->incnt++]) << s->bitcnt;  /* load eight bits */
+        s->bitcnt += 8;
+    }
+
+    /* drop need bits and update buffer, always zero to seven bits left */
+    s->bitbuf = (int)(val >> need);
+    s->bitcnt -= need;
+
+    /* return need bits, zeroing the bits above that */
+    return (int)(val & ((1L << need) - 1));
+}
+
+/*
+ * Process a stored block.
+ *
+ * Format notes:
+ *
+ * - After the two-bit stored block type (00), the stored block length and
+ *   stored bytes are byte-aligned for fast copying.  Therefore any leftover
+ *   bits in the byte that has the last bit of the type, as many as seven, are
+ *   discarded.  The value of the discarded bits are not defined and should not
+ *   be checked against any expectation.
+ *
+ * - The second inverted copy of the stored block length does not have to be
+ *   checked, but it's probably a good idea to do so anyway.
+ *
+ * - A stored block can have zero length.  This is sometimes used to byte-align
+ *   subsets of the compressed data for random access or partial recovery.
+ */
+local int stored(struct state *s)
+{
+    unsigned len;       /* length of stored block */
+
+    /* discard leftover bits from current byte (assumes s->bitcnt < 8) */
+    s->bitbuf = 0;
+    s->bitcnt = 0;
+
+    /* get length and check against its one's complement */
+    if (s->incnt + 4 > s->inlen) return 2;      /* not enough input */
+    len = s->in[s->incnt++];
+    len |= s->in[s->incnt++] << 8;
+    if (s->in[s->incnt++] != (~len & 0xff) ||
+        s->in[s->incnt++] != ((~len >> 8) & 0xff))
+        return -2;                              /* didn't match complement! */
+
+    /* copy len bytes from in to out */
+    if (s->incnt + len > s->inlen) return 2;    /* not enough input */
+    if (s->out != NIL) {
+        if (s->outcnt + len > s->outlen)
+            return 1;                           /* not enough output space */
+        while (len--)
+            s->out[s->outcnt++] = s->in[s->incnt++];
+    }
+    else {                                      /* just scanning */
+        s->outcnt += len;
+        s->incnt += len;
+    }
+
+    /* done with a valid stored block */
+    return 0;
+}
+
+/*
+ * Huffman code decoding tables.  count[1..MAXBITS] is the number of symbols of
+ * each length, which for a canonical code are stepped through in order.
+ * symbol[] are the symbol values in canonical order, where the number of
+ * entries is the sum of the counts in count[].  The decoding process can be
+ * seen in the function decode() below.
+ */
+struct huffman {
+    short *count;       /* number of symbols of each length */
+    short *symbol;      /* canonically ordered symbols */
+};
+
+/*
+ * Decode a code from the stream s using huffman table h.  Return the symbol or
+ * a negative value if there is an error.  If all of the lengths are zero, i.e.
+ * an empty code, or if the code is incomplete and an invalid code is received,
+ * then -9 is returned after reading MAXBITS bits.
+ *
+ * Format notes:
+ *
+ * - The codes as stored in the compressed data are bit-reversed relative to
+ *   a simple integer ordering of codes of the same lengths.  Hence below the
+ *   bits are pulled from the compressed data one at a time and used to
+ *   build the code value reversed from what is in the stream in order to
+ *   permit simple integer comparisons for decoding.  A table-based decoding
+ *   scheme (as used in zlib) does not need to do this reversal.
+ *
+ * - The first code for the shortest length is all zeros.  Subsequent codes of
+ *   the same length are simply integer increments of the previous code.  When
+ *   moving up a length, a zero bit is appended to the code.  For a complete
+ *   code, the last code of the longest length will be all ones.
+ *
+ * - Incomplete codes are handled by this decoder, since they are permitted
+ *   in the deflate format.  See the format notes for fixed() and dynamic().
+ */
+#ifdef SLOW
+local int decode(struct state *s, struct huffman *h)
+{
+    int len;            /* current number of bits in code */
+    int code;           /* len bits being decoded */
+    int first;          /* first code of length len */
+    int count;          /* number of codes of length len */
+    int index;          /* index of first code of length len in symbol table */
+
+    code = first = index = 0;
+    for (len = 1; len <= MAXBITS; len++) {
+        code |= bits(s, 1);             /* get next bit */
+        count = h->count[len];
+        if (code < first + count)       /* if length len, return symbol */
+            return h->symbol[index + (code - first)];
+        index += count;                 /* else update for next length */
+        first += count;
+        first <<= 1;
+        code <<= 1;
+    }
+    return -9;                          /* ran out of codes */
+}
+
+/*
+ * A faster version of decode() for real applications of this code.   It's not
+ * as readable, but it makes puff() twice as fast.  And it only makes the code
+ * a few percent larger.
+ */
+#else /* !SLOW */
+local int decode(struct state *s, struct huffman *h)
+{
+    int len;            /* current number of bits in code */
+    int code;           /* len bits being decoded */
+    int first;          /* first code of length len */
+    int count;          /* number of codes of length len */
+    int index;          /* index of first code of length len in symbol table */
+    int bitbuf;         /* bits from stream */
+    int left;           /* bits left in next or left to process */
+    short *next;        /* next number of codes */
+
+    bitbuf = s->bitbuf;
+    left = s->bitcnt;
+    code = first = index = 0;
+    len = 1;
+    next = h->count + 1;
+    while (1) {
+        while (left--) {
+            code |= bitbuf & 1;
+            bitbuf >>= 1;
+            count = *next++;
+            if (code < first + count) { /* if length len, return symbol */
+                s->bitbuf = bitbuf;
+                s->bitcnt = (s->bitcnt - len) & 7;
+                return h->symbol[index + (code - first)];
+            }
+            index += count;             /* else update for next length */
+            first += count;
+            first <<= 1;
+            code <<= 1;
+            len++;
+        }
+        left = (MAXBITS+1) - len;
+        if (left == 0) break;
+        if (s->incnt == s->inlen) longjmp(s->env, 1);   /* out of input */
+        bitbuf = s->in[s->incnt++];
+        if (left > 8) left = 8;
+    }
+    return -9;                          /* ran out of codes */
+}
+#endif /* SLOW */
+
+/*
+ * Given the list of code lengths length[0..n-1] representing a canonical
+ * Huffman code for n symbols, construct the tables required to decode those
+ * codes.  Those tables are the number of codes of each length, and the symbols
+ * sorted by length, retaining their original order within each length.  The
+ * return value is zero for a complete code set, negative for an over-
+ * subscribed code set, and positive for an incomplete code set.  The tables
+ * can be used if the return value is zero or positive, but they cannot be used
+ * if the return value is negative.  If the return value is zero, it is not
+ * possible for decode() using that table to return an error--any stream of
+ * enough bits will resolve to a symbol.  If the return value is positive, then
+ * it is possible for decode() using that table to return an error for received
+ * codes past the end of the incomplete lengths.
+ *
+ * Not used by decode(), but used for error checking, h->count[0] is the number
+ * of the n symbols not in the code.  So n - h->count[0] is the number of
+ * codes.  This is useful for checking for incomplete codes that have more than
+ * one symbol, which is an error in a dynamic block.
+ *
+ * Assumption: for all i in 0..n-1, 0 <= length[i] <= MAXBITS
+ * This is assured by the construction of the length arrays in dynamic() and
+ * fixed() and is not verified by construct().
+ *
+ * Format notes:
+ *
+ * - Permitted and expected examples of incomplete codes are one of the fixed
+ *   codes and any code with a single symbol which in deflate is coded as one
+ *   bit instead of zero bits.  See the format notes for fixed() and dynamic().
+ *
+ * - Within a given code length, the symbols are kept in ascending order for
+ *   the code bits definition.
+ */
+local int construct(struct huffman *h, short *length, int n)
+{
+    int symbol;         /* current symbol when stepping through length[] */
+    int len;            /* current length when stepping through h->count[] */
+    int left;           /* number of possible codes left of current length */
+    short offs[MAXBITS+1];      /* offsets in symbol table for each length */
+
+    /* count number of codes of each length */
+    for (len = 0; len <= MAXBITS; len++)
+        h->count[len] = 0;
+    for (symbol = 0; symbol < n; symbol++)
+        (h->count[length[symbol]])++;   /* assumes lengths are within bounds */
+    if (h->count[0] == n)               /* no codes! */
+        return 0;                       /* complete, but decode() will fail */
+
+    /* check for an over-subscribed or incomplete set of lengths */
+    left = 1;                           /* one possible code of zero length */
+    for (len = 1; len <= MAXBITS; len++) {
+        left <<= 1;                     /* one more bit, double codes left */
+        left -= h->count[len];          /* deduct count from possible codes */
+        if (left < 0) return left;      /* over-subscribed--return negative */
+    }                                   /* left > 0 means incomplete */
+
+    /* generate offsets into symbol table for each length for sorting */
+    offs[1] = 0;
+    for (len = 1; len < MAXBITS; len++)
+        offs[len + 1] = offs[len] + h->count[len];
+
+    /*
+     * put symbols in table sorted by length, by symbol order within each
+     * length
+     */
+    for (symbol = 0; symbol < n; symbol++)
+        if (length[symbol] != 0)
+            h->symbol[offs[length[symbol]]++] = symbol;
+
+    /* return zero for complete set, positive for incomplete set */
+    return left;
+}
+
+/*
+ * Decode literal/length and distance codes until an end-of-block code.
+ *
+ * Format notes:
+ *
+ * - Compressed data that is after the block type if fixed or after the code
+ *   description if dynamic is a combination of literals and length/distance
+ *   pairs terminated by and end-of-block code.  Literals are simply Huffman
+ *   coded bytes.  A length/distance pair is a coded length followed by a
+ *   coded distance to represent a string that occurs earlier in the
+ *   uncompressed data that occurs again at the current location.
+ *
+ * - Literals, lengths, and the end-of-block code are combined into a single
+ *   code of up to 286 symbols.  They are 256 literals (0..255), 29 length
+ *   symbols (257..285), and the end-of-block symbol (256).
+ *
+ * - There are 256 possible lengths (3..258), and so 29 symbols are not enough
+ *   to represent all of those.  Lengths 3..10 and 258 are in fact represented
+ *   by just a length symbol.  Lengths 11..257 are represented as a symbol and
+ *   some number of extra bits that are added as an integer to the base length
+ *   of the length symbol.  The number of extra bits is determined by the base
+ *   length symbol.  These are in the static arrays below, lens[] for the base
+ *   lengths and lext[] for the corresponding number of extra bits.
+ *
+ * - The reason that 258 gets its own symbol is that the longest length is used
+ *   often in highly redundant files.  Note that 258 can also be coded as the
+ *   base value 227 plus the maximum extra value of 31.  While a good deflate
+ *   should never do this, it is not an error, and should be decoded properly.
+ *
+ * - If a length is decoded, including its extra bits if any, then it is
+ *   followed a distance code.  There are up to 30 distance symbols.  Again
+ *   there are many more possible distances (1..32768), so extra bits are added
+ *   to a base value represented by the symbol.  The distances 1..4 get their
+ *   own symbol, but the rest require extra bits.  The base distances and
+ *   corresponding number of extra bits are below in the static arrays dist[]
+ *   and dext[].
+ *
+ * - Literal bytes are simply written to the output.  A length/distance pair is
+ *   an instruction to copy previously uncompressed bytes to the output.  The
+ *   copy is from distance bytes back in the output stream, copying for length
+ *   bytes.
+ *
+ * - Distances pointing before the beginning of the output data are not
+ *   permitted.
+ *
+ * - Overlapped copies, where the length is greater than the distance, are
+ *   allowed and common.  For example, a distance of one and a length of 258
+ *   simply copies the last byte 258 times.  A distance of four and a length of
+ *   twelve copies the last four bytes three times.  A simple forward copy
+ *   ignoring whether the length is greater than the distance or not implements
+ *   this correctly.  You should not use memcpy() since its behavior is not
+ *   defined for overlapped arrays.  You should not use memmove() or bcopy()
+ *   since though their behavior -is- defined for overlapping arrays, it is
+ *   defined to do the wrong thing in this case.
+ */
+local int codes(struct state *s,
+                struct huffman *lencode,
+                struct huffman *distcode)
+{
+    int symbol;         /* decoded symbol */
+    int len;            /* length for copy */
+    unsigned dist;      /* distance for copy */
+    static const short lens[29] = { /* Size base for length codes 257..285 */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
+    static const short lext[29] = { /* Extra bits for length codes 257..285 */
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
+    static const short dists[30] = { /* Offset base for distance codes 0..29 */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577};
+    static const short dext[30] = { /* Extra bits for distance codes 0..29 */
+        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+        12, 12, 13, 13};
+
+    /* decode literals and length/distance pairs */
+    do {
+        symbol = decode(s, lencode);
+        if (symbol < 0) return symbol;  /* invalid symbol */
+        if (symbol < 256) {             /* literal: symbol is the byte */
+            /* write out the literal */
+            if (s->out != NIL) {
+                if (s->outcnt == s->outlen) return 1;
+                s->out[s->outcnt] = symbol;
+            }
+            s->outcnt++;
+        }
+        else if (symbol > 256) {        /* length */
+            /* get and compute length */
+            symbol -= 257;
+            if (symbol >= 29) return -9;        /* invalid fixed code */
+            len = lens[symbol] + bits(s, lext[symbol]);
+
+            /* get and check distance */
+            symbol = decode(s, distcode);
+            if (symbol < 0) return symbol;      /* invalid symbol */
+            dist = dists[symbol] + bits(s, dext[symbol]);
+            if (dist > s->outcnt)
+                return -10;     /* distance too far back */
+
+            /* copy length bytes from distance bytes back */
+            if (s->out != NIL) {
+                if (s->outcnt + len > s->outlen) return 1;
+                while (len--) {
+                    s->out[s->outcnt] = s->out[s->outcnt - dist];
+                    s->outcnt++;
+                }
+            }
+            else
+                s->outcnt += len;
+        }
+    } while (symbol != 256);            /* end of block symbol */
+
+    /* done with a valid fixed or dynamic block */
+    return 0;
+}
+
+/*
+ * Process a fixed codes block.
+ *
+ * Format notes:
+ *
+ * - This block type can be useful for compressing small amounts of data for
+ *   which the size of the code descriptions in a dynamic block exceeds the
+ *   benefit of custom codes for that block.  For fixed codes, no bits are
+ *   spent on code descriptions.  Instead the code lengths for literal/length
+ *   codes and distance codes are fixed.  The specific lengths for each symbol
+ *   can be seen in the "for" loops below.
+ *
+ * - The literal/length code is complete, but has two symbols that are invalid
+ *   and should result in an error if received.  This cannot be implemented
+ *   simply as an incomplete code since those two symbols are in the "middle"
+ *   of the code.  They are eight bits long and the longest literal/length\
+ *   code is nine bits.  Therefore the code must be constructed with those
+ *   symbols, and the invalid symbols must be detected after decoding.
+ *
+ * - The fixed distance codes also have two invalid symbols that should result
+ *   in an error if received.  Since all of the distance codes are the same
+ *   length, this can be implemented as an incomplete code.  Then the invalid
+ *   codes are detected while decoding.
+ */
+local int fixed(struct state *s)
+{
+    static int virgin = 1;
+    static short lencnt[MAXBITS+1], lensym[FIXLCODES];
+    static short distcnt[MAXBITS+1], distsym[MAXDCODES];
+    static struct huffman lencode = {lencnt, lensym};
+    static struct huffman distcode = {distcnt, distsym};
+
+    /* build fixed huffman tables if first call (may not be thread safe) */
+    if (virgin) {
+        int symbol;
+        short lengths[FIXLCODES];
+
+        /* literal/length table */
+        for (symbol = 0; symbol < 144; symbol++)
+            lengths[symbol] = 8;
+        for (; symbol < 256; symbol++)
+            lengths[symbol] = 9;
+        for (; symbol < 280; symbol++)
+            lengths[symbol] = 7;
+        for (; symbol < FIXLCODES; symbol++)
+            lengths[symbol] = 8;
+        construct(&lencode, lengths, FIXLCODES);
+
+        /* distance table */
+        for (symbol = 0; symbol < MAXDCODES; symbol++)
+            lengths[symbol] = 5;
+        construct(&distcode, lengths, MAXDCODES);
+
+        /* do this just once */
+        virgin = 0;
+    }
+
+    /* decode data until end-of-block code */
+    return codes(s, &lencode, &distcode);
+}
+
+/*
+ * Process a dynamic codes block.
+ *
+ * Format notes:
+ *
+ * - A dynamic block starts with a description of the literal/length and
+ *   distance codes for that block.  New dynamic blocks allow the compressor to
+ *   rapidly adapt to changing data with new codes optimized for that data.
+ *
+ * - The codes used by the deflate format are "canonical", which means that
+ *   the actual bits of the codes are generated in an unambiguous way simply
+ *   from the number of bits in each code.  Therefore the code descriptions
+ *   are simply a list of code lengths for each symbol.
+ *
+ * - The code lengths are stored in order for the symbols, so lengths are
+ *   provided for each of the literal/length symbols, and for each of the
+ *   distance symbols.
+ *
+ * - If a symbol is not used in the block, this is represented by a zero as
+ *   as the code length.  This does not mean a zero-length code, but rather
+ *   that no code should be created for this symbol.  There is no way in the
+ *   deflate format to represent a zero-length code.
+ *
+ * - The maximum number of bits in a code is 15, so the possible lengths for
+ *   any code are 1..15.
+ *
+ * - The fact that a length of zero is not permitted for a code has an
+ *   interesting consequence.  Normally if only one symbol is used for a given
+ *   code, then in fact that code could be represented with zero bits.  However
+ *   in deflate, that code has to be at least one bit.  So for example, if
+ *   only a single distance base symbol appears in a block, then it will be
+ *   represented by a single code of length one, in particular one 0 bit.  This
+ *   is an incomplete code, since if a 1 bit is received, it has no meaning,
+ *   and should result in an error.  So incomplete distance codes of one symbol
+ *   should be permitted, and the receipt of invalid codes should be handled.
+ *
+ * - It is also possible to have a single literal/length code, but that code
+ *   must be the end-of-block code, since every dynamic block has one.  This
+ *   is not the most efficient way to create an empty block (an empty fixed
+ *   block is fewer bits), but it is allowed by the format.  So incomplete
+ *   literal/length codes of one symbol should also be permitted.
+ *
+ * - If there are only literal codes and no lengths, then there are no distance
+ *   codes.  This is represented by one distance code with zero bits.
+ *
+ * - The list of up to 286 length/literal lengths and up to 30 distance lengths
+ *   are themselves compressed using Huffman codes and run-length encoding.  In
+ *   the list of code lengths, a 0 symbol means no code, a 1..15 symbol means
+ *   that length, and the symbols 16, 17, and 18 are run-length instructions.
+ *   Each of 16, 17, and 18 are follwed by extra bits to define the length of
+ *   the run.  16 copies the last length 3 to 6 times.  17 represents 3 to 10
+ *   zero lengths, and 18 represents 11 to 138 zero lengths.  Unused symbols
+ *   are common, hence the special coding for zero lengths.
+ *
+ * - The symbols for 0..18 are Huffman coded, and so that code must be
+ *   described first.  This is simply a sequence of up to 19 three-bit values
+ *   representing no code (0) or the code length for that symbol (1..7).
+ *
+ * - A dynamic block starts with three fixed-size counts from which is computed
+ *   the number of literal/length code lengths, the number of distance code
+ *   lengths, and the number of code length code lengths (ok, you come up with
+ *   a better name!) in the code descriptions.  For the literal/length and
+ *   distance codes, lengths after those provided are considered zero, i.e. no
+ *   code.  The code length code lengths are received in a permuted order (see
+ *   the order[] array below) to make a short code length code length list more
+ *   likely.  As it turns out, very short and very long codes are less likely
+ *   to be seen in a dynamic code description, hence what may appear initially
+ *   to be a peculiar ordering.
+ *
+ * - Given the number of literal/length code lengths (nlen) and distance code
+ *   lengths (ndist), then they are treated as one long list of nlen + ndist
+ *   code lengths.  Therefore run-length coding can and often does cross the
+ *   boundary between the two sets of lengths.
+ *
+ * - So to summarize, the code description at the start of a dynamic block is
+ *   three counts for the number of code lengths for the literal/length codes,
+ *   the distance codes, and the code length codes.  This is followed by the
+ *   code length code lengths, three bits each.  This is used to construct the
+ *   code length code which is used to read the remainder of the lengths.  Then
+ *   the literal/length code lengths and distance lengths are read as a single
+ *   set of lengths using the code length codes.  Codes are constructed from
+ *   the resulting two sets of lengths, and then finally you can start
+ *   decoding actual compressed data in the block.
+ *
+ * - For reference, a "typical" size for the code description in a dynamic
+ *   block is around 80 bytes.
+ */
+local int dynamic(struct state *s)
+{
+    int nlen, ndist, ncode;             /* number of lengths in descriptor */
+    int index;                          /* index of lengths[] */
+    int err;                            /* construct() return value */
+    short lengths[MAXCODES];            /* descriptor code lengths */
+    short lencnt[MAXBITS+1], lensym[MAXLCODES];         /* lencode memory */
+    short distcnt[MAXBITS+1], distsym[MAXDCODES];       /* distcode memory */
+    struct huffman lencode = {lencnt, lensym};          /* length code */
+    struct huffman distcode = {distcnt, distsym};       /* distance code */
+    static const short order[19] =      /* permutation of code length codes */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+    /* get number of lengths in each table, check lengths */
+    nlen = bits(s, 5) + 257;
+    ndist = bits(s, 5) + 1;
+    ncode = bits(s, 4) + 4;
+    if (nlen > MAXLCODES || ndist > MAXDCODES)
+        return -3;                      /* bad counts */
+
+    /* read code length code lengths (really), missing lengths are zero */
+    for (index = 0; index < ncode; index++)
+        lengths[order[index]] = bits(s, 3);
+    for (; index < 19; index++)
+        lengths[order[index]] = 0;
+
+    /* build huffman table for code lengths codes (use lencode temporarily) */
+    err = construct(&lencode, lengths, 19);
+    if (err != 0) return -4;            /* require complete code set here */
+
+    /* read length/literal and distance code length tables */
+    index = 0;
+    while (index < nlen + ndist) {
+        int symbol;             /* decoded value */
+        int len;                /* last length to repeat */
+
+        symbol = decode(s, &lencode);
+        if (symbol < 16)                /* length in 0..15 */
+            lengths[index++] = symbol;
+        else {                          /* repeat instruction */
+            len = 0;                    /* assume repeating zeros */
+            if (symbol == 16) {         /* repeat last length 3..6 times */
+                if (index == 0) return -5;      /* no last length! */
+                len = lengths[index - 1];       /* last length */
+                symbol = 3 + bits(s, 2);
+            }
+            else if (symbol == 17)      /* repeat zero 3..10 times */
+                symbol = 3 + bits(s, 3);
+            else                        /* == 18, repeat zero 11..138 times */
+                symbol = 11 + bits(s, 7);
+            if (index + symbol > nlen + ndist)
+                return -6;              /* too many lengths! */
+            while (symbol--)            /* repeat last or zero symbol times */
+                lengths[index++] = len;
+        }
+    }
+
+    /* build huffman table for literal/length codes */
+    err = construct(&lencode, lengths, nlen);
+    if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1))
+        return -7;      /* only allow incomplete codes if just one code */
+
+    /* build huffman table for distance codes */
+    err = construct(&distcode, lengths + nlen, ndist);
+    if (err < 0 || (err > 0 && ndist - distcode.count[0] != 1))
+        return -8;      /* only allow incomplete codes if just one code */
+
+    /* decode data until end-of-block code */
+    return codes(s, &lencode, &distcode);
+}
+
+/*
+ * Inflate source to dest.  On return, destlen and sourcelen are updated to the
+ * size of the uncompressed data and the size of the deflate data respectively.
+ * On success, the return value of puff() is zero.  If there is an error in the
+ * source data, i.e. it is not in the deflate format, then a negative value is
+ * returned.  If there is not enough input available or there is not enough
+ * output space, then a positive error is returned.  In that case, destlen and
+ * sourcelen are not updated to facilitate retrying from the beginning with the
+ * provision of more input data or more output space.  In the case of invalid
+ * inflate data (a negative error), the dest and source pointers are updated to
+ * facilitate the debugging of deflators.
+ *
+ * puff() also has a mode to determine the size of the uncompressed output with
+ * no output written.  For this dest must be (unsigned char *)0.  In this case,
+ * the input value of *destlen is ignored, and on return *destlen is set to the
+ * size of the uncompressed output.
+ *
+ * The return codes are:
+ *
+ *   2:  available inflate data did not terminate
+ *   1:  output space exhausted before completing inflate
+ *   0:  successful inflate
+ *  -1:  invalid block type (type == 3)
+ *  -2:  stored block length did not match one's complement
+ *  -3:  dynamic block code description: too many length or distance codes
+ *  -4:  dynamic block code description: code lengths codes incomplete
+ *  -5:  dynamic block code description: repeat lengths with no first length
+ *  -6:  dynamic block code description: repeat more than specified lengths
+ *  -7:  dynamic block code description: invalid literal/length code lengths
+ *  -8:  dynamic block code description: invalid distance code lengths
+ *  -9:  invalid literal/length or distance code in fixed or dynamic block
+ * -10:  distance is too far back in fixed or dynamic block
+ *
+ * Format notes:
+ *
+ * - Three bits are read for each block to determine the kind of block and
+ *   whether or not it is the last block.  Then the block is decoded and the
+ *   process repeated if it was not the last block.
+ *
+ * - The leftover bits in the last byte of the deflate data after the last
+ *   block (if it was a fixed or dynamic block) are undefined and have no
+ *   expected values to check.
+ */
+int puff(unsigned char *dest,           /* pointer to destination pointer */
+         unsigned long *destlen,        /* amount of output space */
+         unsigned char *source,         /* pointer to source data pointer */
+         unsigned long *sourcelen)      /* amount of input available */
+{
+    struct state s;             /* input/output state */
+    int last, type;             /* block information */
+    int err;                    /* return value */
+
+    /* initialize output state */
+    s.out = dest;
+    s.outlen = *destlen;                /* ignored if dest is NIL */
+    s.outcnt = 0;
+
+    /* initialize input state */
+    s.in = source;
+    s.inlen = *sourcelen;
+    s.incnt = 0;
+    s.bitbuf = 0;
+    s.bitcnt = 0;
+
+    /* return if bits() or decode() tries to read past available input */
+    if (setjmp(s.env) != 0)             /* if came back here via longjmp() */
+        err = 2;                        /* then skip do-loop, return error */
+    else {
+        /* process blocks until last block or error */
+        do {
+            last = bits(&s, 1);         /* one if last block */
+            type = bits(&s, 2);         /* block type 0..3 */
+            err = type == 0 ? stored(&s) :
+                  (type == 1 ? fixed(&s) :
+                   (type == 2 ? dynamic(&s) :
+                    -1));               /* type == 3, invalid */
+            if (err != 0) break;        /* return with error */
+        } while (!last);
+    }
+
+    /* update the lengths and return */
+    if (err <= 0) {
+        *destlen = s.outcnt;
+        *sourcelen = s.incnt;
+    }
+    return err;
+}
+
+#ifdef TEST
+/* Example of how to use puff() */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+local unsigned char *yank(char *name, unsigned long *len)
+{
+    unsigned long size;
+    unsigned char *buf;
+    FILE *in;
+    struct stat s;
+
+    *len = 0;
+    if (stat(name, &s)) return NULL;
+    if ((s.st_mode & S_IFMT) != S_IFREG) return NULL;
+    size = (unsigned long)(s.st_size);
+    if (size == 0 || (off_t)size != s.st_size) return NULL;
+    in = fopen(name, "r");
+    if (in == NULL) return NULL;
+    buf = malloc(size);
+    if (buf != NULL && fread(buf, 1, size, in) != size) {
+        free(buf);
+        buf = NULL;
+    }
+    fclose(in);
+    *len = size;
+    return buf;
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+    unsigned char *source;
+    unsigned long len, sourcelen, destlen;
+
+    if (argc < 2) return 2;
+    source = yank(argv[1], &len);
+    if (source == NULL) return 2;
+    sourcelen = len;
+    ret = puff(NIL, &destlen, source, &sourcelen);
+    if (ret)
+        printf("puff() failed with return code %d\n", ret);
+    else {
+        printf("puff() succeeded uncompressing %lu bytes\n", destlen);
+        if (sourcelen < len) printf("%lu compressed bytes unused\n",
+                                    len - sourcelen);
+    }
+    free(source);
+    return ret;
+}
+#endif
Index: /trunk/minix/lib/zlib-1.2.3/contrib/puff/puff.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/puff/puff.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/puff/puff.h	(revision 9)
@@ -0,0 +1,31 @@
+/* puff.h
+  Copyright (C) 2002, 2003 Mark Adler, all rights reserved
+  version 1.7, 3 Mar 2002
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the author be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Mark Adler    madler@alumni.caltech.edu
+ */
+
+
+/*
+ * See puff.c for purpose and usage.
+ */
+int puff(unsigned char *dest,           /* pointer to destination pointer */
+         unsigned long *destlen,        /* amount of output space */
+         unsigned char *source,         /* pointer to source data pointer */
+         unsigned long *sourcelen);     /* amount of input available */
Index: /trunk/minix/lib/zlib-1.2.3/contrib/testzlib/testzlib.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/testzlib/testzlib.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/testzlib/testzlib.c	(revision 9)
@@ -0,0 +1,275 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+
+#include "zlib.h"
+
+
+void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B)
+{
+    R->HighPart = A.HighPart - B.HighPart;
+    if (A.LowPart >= B.LowPart)
+        R->LowPart = A.LowPart - B.LowPart;
+    else
+    {
+        R->LowPart = A.LowPart - B.LowPart;
+        R->HighPart --;
+    }
+}
+
+#ifdef _M_X64
+// see http://msdn2.microsoft.com/library/twchhe95(en-us,vs.80).aspx for __rdtsc
+unsigned __int64 __rdtsc(void);
+void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)
+{
+ //   printf("rdtsc = %I64x\n",__rdtsc());
+   pbeginTime64->QuadPart=__rdtsc();
+}
+
+LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
+{
+    LARGE_INTEGER LIres;
+    unsigned _int64 res=__rdtsc()-((unsigned _int64)(beginTime64.QuadPart));
+    LIres.QuadPart=res;
+   // printf("rdtsc = %I64x\n",__rdtsc());
+    return LIres;
+}
+#else
+#ifdef _M_IX86
+void myGetRDTSC32(LARGE_INTEGER * pbeginTime64)
+{
+    DWORD dwEdx,dwEax;
+    _asm
+    {
+        rdtsc
+        mov dwEax,eax
+        mov dwEdx,edx
+    }
+    pbeginTime64->LowPart=dwEax;
+    pbeginTime64->HighPart=dwEdx;
+}
+
+void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)
+{
+    myGetRDTSC32(pbeginTime64);
+}
+
+LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
+{
+    LARGE_INTEGER LIres,endTime64;
+    myGetRDTSC32(&endTime64);
+
+    LIres.LowPart=LIres.HighPart=0;
+    MyDoMinus64(&LIres,endTime64,beginTime64);
+    return LIres;
+}
+#else
+void myGetRDTSC32(LARGE_INTEGER * pbeginTime64)
+{
+}
+
+void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)
+{
+}
+
+LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
+{
+    LARGE_INTEGER lr;
+    lr.QuadPart=0;
+    return lr;
+}
+#endif
+#endif
+
+void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf)
+{
+    if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64)))
+    {
+        pbeginTime64->LowPart = GetTickCount();
+        pbeginTime64->HighPart = 0;
+    }
+}
+
+DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
+{
+    LARGE_INTEGER endTime64,ticksPerSecond,ticks;
+    DWORDLONG ticksShifted,tickSecShifted;
+    DWORD dwLog=16+0;
+    DWORD dwRet;
+    if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64)))
+        dwRet = (GetTickCount() - beginTime64.LowPart)*1;
+    else
+    {
+        MyDoMinus64(&ticks,endTime64,beginTime64);
+        QueryPerformanceFrequency(&ticksPerSecond);
+
+    
+        {
+            ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog);
+            tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog);
+        
+        } 
+
+        dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted));
+        dwRet *=1;
+    }
+    return dwRet;
+}
+
+int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr)
+{
+    FILE* stream;
+    void* ptr;
+    int retVal=1;
+    stream=fopen(filename, "rb");
+    if (stream==NULL)
+        return 0;
+
+    fseek(stream,0,SEEK_END);
+
+    *plFileSize=ftell(stream);
+    fseek(stream,0,SEEK_SET);
+    ptr=malloc((*plFileSize)+1);
+    if (ptr==NULL)
+        retVal=0;
+    else
+    {
+        if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize))
+            retVal=0;
+    }
+    fclose(stream);
+    *pFilePtr=ptr;
+    return retVal;
+}
+
+int main(int argc, char *argv[])
+{
+    int BlockSizeCompress=0x8000;
+    int BlockSizeUncompress=0x8000;
+    int cprLevel=Z_DEFAULT_COMPRESSION ;
+    long lFileSize;
+    unsigned char* FilePtr;
+    long lBufferSizeCpr;
+    long lBufferSizeUncpr;
+    long lCompressedSize=0;
+    unsigned char* CprPtr;
+    unsigned char* UncprPtr;
+    long lSizeCpr,lSizeUncpr;
+    DWORD dwGetTick,dwMsecQP;
+    LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc;
+
+    if (argc<=1)
+    {
+        printf("run TestZlib <File> [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n");
+        return 0;
+    }
+
+    if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0)
+    {
+        printf("error reading %s\n",argv[1]);
+        return 1;
+    }
+    else printf("file %s read, %u bytes\n",argv[1],lFileSize);
+
+    if (argc>=3)
+        BlockSizeCompress=atol(argv[2]);
+
+    if (argc>=4)
+        BlockSizeUncompress=atol(argv[3]);
+
+    if (argc>=5)
+        cprLevel=(int)atol(argv[4]);
+
+    lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200;
+    lBufferSizeUncpr = lBufferSizeCpr;
+
+    CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress);
+
+    BeginCountPerfCounter(&li_qp,TRUE);
+    dwGetTick=GetTickCount();
+    BeginCountRdtsc(&li_rdtsc);
+    {
+        z_stream zcpr;
+        int ret=Z_OK;
+        long lOrigToDo = lFileSize;
+        long lOrigDone = 0;
+        int step=0;
+        memset(&zcpr,0,sizeof(z_stream));
+        deflateInit(&zcpr,cprLevel);
+
+        zcpr.next_in = FilePtr;
+        zcpr.next_out = CprPtr;
+
+
+        do
+        {
+            long all_read_before = zcpr.total_in;
+            zcpr.avail_in = min(lOrigToDo,BlockSizeCompress);
+            zcpr.avail_out = BlockSizeCompress;
+            ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH);
+            lOrigDone += (zcpr.total_in-all_read_before);
+            lOrigToDo -= (zcpr.total_in-all_read_before);
+            step++;
+        } while (ret==Z_OK);
+
+        lSizeCpr=zcpr.total_out;
+        deflateEnd(&zcpr);
+        dwGetTick=GetTickCount()-dwGetTick;
+        dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE);
+        dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE);
+        printf("total compress size = %u, in %u step\n",lSizeCpr,step);
+        printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.);
+        printf("defcpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.);
+        printf("defcpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart);
+    }
+
+    CprPtr=(unsigned char*)realloc(CprPtr,lSizeCpr);
+    UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress);
+
+    BeginCountPerfCounter(&li_qp,TRUE);
+    dwGetTick=GetTickCount();
+    BeginCountRdtsc(&li_rdtsc);
+    {
+        z_stream zcpr;
+        int ret=Z_OK;
+        long lOrigToDo = lSizeCpr;
+        long lOrigDone = 0;
+        int step=0;
+        memset(&zcpr,0,sizeof(z_stream));
+        inflateInit(&zcpr);
+
+        zcpr.next_in = CprPtr;
+        zcpr.next_out = UncprPtr;
+
+
+        do
+        {
+            long all_read_before = zcpr.total_in;
+            zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress);
+            zcpr.avail_out = BlockSizeUncompress;
+            ret=inflate(&zcpr,Z_SYNC_FLUSH);
+            lOrigDone += (zcpr.total_in-all_read_before);
+            lOrigToDo -= (zcpr.total_in-all_read_before);
+            step++;
+        } while (ret==Z_OK);
+
+        lSizeUncpr=zcpr.total_out;
+        inflateEnd(&zcpr);
+        dwGetTick=GetTickCount()-dwGetTick;
+        dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE);
+        dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE);
+        printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step);
+        printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.);
+        printf("uncpr  time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.);
+        printf("uncpr  result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart);
+    }
+
+    if (lSizeUncpr==lFileSize)
+    {
+        if (memcmp(FilePtr,UncprPtr,lFileSize)==0)
+            printf("compare ok\n");
+
+    }
+
+    return 0;
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/testzlib/testzlib.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/testzlib/testzlib.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/testzlib/testzlib.txt	(revision 9)
@@ -0,0 +1,10 @@
+To build testzLib with Visual Studio 2005:
+
+copy to a directory file from :
+- root of zLib tree
+- contrib/testzlib
+- contrib/masmx86
+- contrib/masmx64
+- contrib/vstudio/vc7
+
+and open testzlib8.sln
Index: /trunk/minix/lib/zlib-1.2.3/contrib/untgz/Makefile
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/untgz/Makefile	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/untgz/Makefile	(revision 9)
@@ -0,0 +1,14 @@
+CC=cc
+CFLAGS=-g
+
+untgz: untgz.o ../../libz.a
+	$(CC) $(CFLAGS) -o untgz untgz.o -L../.. -lz
+
+untgz.o: untgz.c ../../zlib.h
+	$(CC) $(CFLAGS) -c -I../.. untgz.c
+
+../../libz.a:
+	cd ../..; ./configure; make
+
+clean:
+	rm -f untgz untgz.o *~
Index: /trunk/minix/lib/zlib-1.2.3/contrib/untgz/Makefile.msc
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/untgz/Makefile.msc	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/untgz/Makefile.msc	(revision 9)
@@ -0,0 +1,17 @@
+CC=cl
+CFLAGS=-MD
+
+untgz.exe: untgz.obj ..\..\zlib.lib
+	$(CC) $(CFLAGS) untgz.obj ..\..\zlib.lib
+
+untgz.obj: untgz.c ..\..\zlib.h
+	$(CC) $(CFLAGS) -c -I..\.. untgz.c
+
+..\..\zlib.lib:
+	cd ..\..
+	$(MAKE) -f win32\makefile.msc
+	cd contrib\untgz
+
+clean:
+	-del untgz.obj
+	-del untgz.exe
Index: /trunk/minix/lib/zlib-1.2.3/contrib/untgz/untgz.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/untgz/untgz.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/untgz/untgz.c	(revision 9)
@@ -0,0 +1,674 @@
+/*
+ * untgz.c -- Display contents and extract files from a gzip'd TAR file
+ *
+ * written by Pedro A. Aranda Gutierrez <paag@tid.es>
+ * adaptation to Unix by Jean-loup Gailly <jloup@gzip.org>
+ * various fixes by Cosmin Truta <cosmint@cs.ubbcluj.ro>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#include "zlib.h"
+
+#ifdef unix
+#  include <unistd.h>
+#else
+#  include <direct.h>
+#  include <io.h>
+#endif
+
+#ifdef WIN32
+#include <windows.h>
+#  ifndef F_OK
+#    define F_OK  0
+#  endif
+#  define mkdir(dirname,mode)   _mkdir(dirname)
+#  ifdef _MSC_VER
+#    define access(path,mode)   _access(path,mode)
+#    define chmod(path,mode)    _chmod(path,mode)
+#    define strdup(str)         _strdup(str)
+#  endif
+#else
+#  include <utime.h>
+#endif
+
+
+/* values used in typeflag field */
+
+#define REGTYPE  '0'            /* regular file */
+#define AREGTYPE '\0'           /* regular file */
+#define LNKTYPE  '1'            /* link */
+#define SYMTYPE  '2'            /* reserved */
+#define CHRTYPE  '3'            /* character special */
+#define BLKTYPE  '4'            /* block special */
+#define DIRTYPE  '5'            /* directory */
+#define FIFOTYPE '6'            /* FIFO special */
+#define CONTTYPE '7'            /* reserved */
+
+/* GNU tar extensions */
+
+#define GNUTYPE_DUMPDIR  'D'    /* file names from dumped directory */
+#define GNUTYPE_LONGLINK 'K'    /* long link name */
+#define GNUTYPE_LONGNAME 'L'    /* long file name */
+#define GNUTYPE_MULTIVOL 'M'    /* continuation of file from another volume */
+#define GNUTYPE_NAMES    'N'    /* file name that does not fit into main hdr */
+#define GNUTYPE_SPARSE   'S'    /* sparse file */
+#define GNUTYPE_VOLHDR   'V'    /* tape/volume header */
+
+
+/* tar header */
+
+#define BLOCKSIZE     512
+#define SHORTNAMESIZE 100
+
+struct tar_header
+{                               /* byte offset */
+  char name[100];               /*   0 */
+  char mode[8];                 /* 100 */
+  char uid[8];                  /* 108 */
+  char gid[8];                  /* 116 */
+  char size[12];                /* 124 */
+  char mtime[12];               /* 136 */
+  char chksum[8];               /* 148 */
+  char typeflag;                /* 156 */
+  char linkname[100];           /* 157 */
+  char magic[6];                /* 257 */
+  char version[2];              /* 263 */
+  char uname[32];               /* 265 */
+  char gname[32];               /* 297 */
+  char devmajor[8];             /* 329 */
+  char devminor[8];             /* 337 */
+  char prefix[155];             /* 345 */
+                                /* 500 */
+};
+
+union tar_buffer
+{
+  char               buffer[BLOCKSIZE];
+  struct tar_header  header;
+};
+
+struct attr_item
+{
+  struct attr_item  *next;
+  char              *fname;
+  int                mode;
+  time_t             time;
+};
+
+enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID };
+
+char *TGZfname          OF((const char *));
+void TGZnotfound        OF((const char *));
+
+int getoct              OF((char *, int));
+char *strtime           OF((time_t *));
+int setfiletime         OF((char *, time_t));
+void push_attr          OF((struct attr_item **, char *, int, time_t));
+void restore_attr       OF((struct attr_item **));
+
+int ExprMatch           OF((char *, char *));
+
+int makedir             OF((char *));
+int matchname           OF((int, int, char **, char *));
+
+void error              OF((const char *));
+int tar                 OF((gzFile, int, int, int, char **));
+
+void help               OF((int));
+int main                OF((int, char **));
+
+char *prog;
+
+const char *TGZsuffix[] = { "\0", ".tar", ".tar.gz", ".taz", ".tgz", NULL };
+
+/* return the file name of the TGZ archive */
+/* or NULL if it does not exist */
+
+char *TGZfname (const char *arcname)
+{
+  static char buffer[1024];
+  int origlen,i;
+
+  strcpy(buffer,arcname);
+  origlen = strlen(buffer);
+
+  for (i=0; TGZsuffix[i]; i++)
+    {
+       strcpy(buffer+origlen,TGZsuffix[i]);
+       if (access(buffer,F_OK) == 0)
+         return buffer;
+    }
+  return NULL;
+}
+
+
+/* error message for the filename */
+
+void TGZnotfound (const char *arcname)
+{
+  int i;
+
+  fprintf(stderr,"%s: Couldn't find ",prog);
+  for (i=0;TGZsuffix[i];i++)
+    fprintf(stderr,(TGZsuffix[i+1]) ? "%s%s, " : "or %s%s\n",
+            arcname,
+            TGZsuffix[i]);
+  exit(1);
+}
+
+
+/* convert octal digits to int */
+/* on error return -1 */
+
+int getoct (char *p,int width)
+{
+  int result = 0;
+  char c;
+
+  while (width--)
+    {
+      c = *p++;
+      if (c == 0)
+        break;
+      if (c == ' ')
+        continue;
+      if (c < '0' || c > '7')
+        return -1;
+      result = result * 8 + (c - '0');
+    }
+  return result;
+}
+
+
+/* convert time_t to string */
+/* use the "YYYY/MM/DD hh:mm:ss" format */
+
+char *strtime (time_t *t)
+{
+  struct tm   *local;
+  static char result[32];
+
+  local = localtime(t);
+  sprintf(result,"%4d/%02d/%02d %02d:%02d:%02d",
+          local->tm_year+1900, local->tm_mon+1, local->tm_mday,
+          local->tm_hour, local->tm_min, local->tm_sec);
+  return result;
+}
+
+
+/* set file time */
+
+int setfiletime (char *fname,time_t ftime)
+{
+#ifdef WIN32
+  static int isWinNT = -1;
+  SYSTEMTIME st;
+  FILETIME locft, modft;
+  struct tm *loctm;
+  HANDLE hFile;
+  int result;
+
+  loctm = localtime(&ftime);
+  if (loctm == NULL)
+    return -1;
+
+  st.wYear         = (WORD)loctm->tm_year + 1900;
+  st.wMonth        = (WORD)loctm->tm_mon + 1;
+  st.wDayOfWeek    = (WORD)loctm->tm_wday;
+  st.wDay          = (WORD)loctm->tm_mday;
+  st.wHour         = (WORD)loctm->tm_hour;
+  st.wMinute       = (WORD)loctm->tm_min;
+  st.wSecond       = (WORD)loctm->tm_sec;
+  st.wMilliseconds = 0;
+  if (!SystemTimeToFileTime(&st, &locft) ||
+      !LocalFileTimeToFileTime(&locft, &modft))
+    return -1;
+
+  if (isWinNT < 0)
+    isWinNT = (GetVersion() < 0x80000000) ? 1 : 0;
+  hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
+                     (isWinNT ? FILE_FLAG_BACKUP_SEMANTICS : 0),
+                     NULL);
+  if (hFile == INVALID_HANDLE_VALUE)
+    return -1;
+  result = SetFileTime(hFile, NULL, NULL, &modft) ? 0 : -1;
+  CloseHandle(hFile);
+  return result;
+#else
+  struct utimbuf settime;
+
+  settime.actime = settime.modtime = ftime;
+  return utime(fname,&settime);
+#endif
+}
+
+
+/* push file attributes */
+
+void push_attr(struct attr_item **list,char *fname,int mode,time_t time)
+{
+  struct attr_item *item;
+
+  item = (struct attr_item *)malloc(sizeof(struct attr_item));
+  if (item == NULL)
+    error("Out of memory");
+  item->fname = strdup(fname);
+  item->mode  = mode;
+  item->time  = time;
+  item->next  = *list;
+  *list       = item;
+}
+
+
+/* restore file attributes */
+
+void restore_attr(struct attr_item **list)
+{
+  struct attr_item *item, *prev;
+
+  for (item = *list; item != NULL; )
+    {
+      setfiletime(item->fname,item->time);
+      chmod(item->fname,item->mode);
+      prev = item;
+      item = item->next;
+      free(prev);
+    }
+  *list = NULL;
+}
+
+
+/* match regular expression */
+
+#define ISSPECIAL(c) (((c) == '*') || ((c) == '/'))
+
+int ExprMatch (char *string,char *expr)
+{
+  while (1)
+    {
+      if (ISSPECIAL(*expr))
+        {
+          if (*expr == '/')
+            {
+              if (*string != '\\' && *string != '/')
+                return 0;
+              string ++; expr++;
+            }
+          else if (*expr == '*')
+            {
+              if (*expr ++ == 0)
+                return 1;
+              while (*++string != *expr)
+                if (*string == 0)
+                  return 0;
+            }
+        }
+      else
+        {
+          if (*string != *expr)
+            return 0;
+          if (*expr++ == 0)
+            return 1;
+          string++;
+        }
+    }
+}
+
+
+/* recursive mkdir */
+/* abort on ENOENT; ignore other errors like "directory already exists" */
+/* return 1 if OK */
+/*        0 on error */
+
+int makedir (char *newdir)
+{
+  char *buffer = strdup(newdir);
+  char *p;
+  int  len = strlen(buffer);
+
+  if (len <= 0) {
+    free(buffer);
+    return 0;
+  }
+  if (buffer[len-1] == '/') {
+    buffer[len-1] = '\0';
+  }
+  if (mkdir(buffer, 0755) == 0)
+    {
+      free(buffer);
+      return 1;
+    }
+
+  p = buffer+1;
+  while (1)
+    {
+      char hold;
+
+      while(*p && *p != '\\' && *p != '/')
+        p++;
+      hold = *p;
+      *p = 0;
+      if ((mkdir(buffer, 0755) == -1) && (errno == ENOENT))
+        {
+          fprintf(stderr,"%s: Couldn't create directory %s\n",prog,buffer);
+          free(buffer);
+          return 0;
+        }
+      if (hold == 0)
+        break;
+      *p++ = hold;
+    }
+  free(buffer);
+  return 1;
+}
+
+
+int matchname (int arg,int argc,char **argv,char *fname)
+{
+  if (arg == argc)      /* no arguments given (untgz tgzarchive) */
+    return 1;
+
+  while (arg < argc)
+    if (ExprMatch(fname,argv[arg++]))
+      return 1;
+
+  return 0; /* ignore this for the moment being */
+}
+
+
+/* tar file list or extract */
+
+int tar (gzFile in,int action,int arg,int argc,char **argv)
+{
+  union  tar_buffer buffer;
+  int    len;
+  int    err;
+  int    getheader = 1;
+  int    remaining = 0;
+  FILE   *outfile = NULL;
+  char   fname[BLOCKSIZE];
+  int    tarmode;
+  time_t tartime;
+  struct attr_item *attributes = NULL;
+
+  if (action == TGZ_LIST)
+    printf("    date      time     size                       file\n"
+           " ---------- -------- --------- -------------------------------------\n");
+  while (1)
+    {
+      len = gzread(in, &buffer, BLOCKSIZE);
+      if (len < 0)
+        error(gzerror(in, &err));
+      /*
+       * Always expect complete blocks to process
+       * the tar information.
+       */
+      if (len != BLOCKSIZE)
+        {
+          action = TGZ_INVALID; /* force error exit */
+          remaining = 0;        /* force I/O cleanup */
+        }
+
+      /*
+       * If we have to get a tar header
+       */
+      if (getheader >= 1)
+        {
+          /*
+           * if we met the end of the tar
+           * or the end-of-tar block,
+           * we are done
+           */
+          if (len == 0 || buffer.header.name[0] == 0)
+            break;
+
+          tarmode = getoct(buffer.header.mode,8);
+          tartime = (time_t)getoct(buffer.header.mtime,12);
+          if (tarmode == -1 || tartime == (time_t)-1)
+            {
+              buffer.header.name[0] = 0;
+              action = TGZ_INVALID;
+            }
+
+          if (getheader == 1)
+            {
+              strncpy(fname,buffer.header.name,SHORTNAMESIZE);
+              if (fname[SHORTNAMESIZE-1] != 0)
+                  fname[SHORTNAMESIZE] = 0;
+            }
+          else
+            {
+              /*
+               * The file name is longer than SHORTNAMESIZE
+               */
+              if (strncmp(fname,buffer.header.name,SHORTNAMESIZE-1) != 0)
+                  error("bad long name");
+              getheader = 1;
+            }
+
+          /*
+           * Act according to the type flag
+           */
+          switch (buffer.header.typeflag)
+            {
+            case DIRTYPE:
+              if (action == TGZ_LIST)
+                printf(" %s     <dir> %s\n",strtime(&tartime),fname);
+              if (action == TGZ_EXTRACT)
+                {
+                  makedir(fname);
+                  push_attr(&attributes,fname,tarmode,tartime);
+                }
+              break;
+            case REGTYPE:
+            case AREGTYPE:
+              remaining = getoct(buffer.header.size,12);
+              if (remaining == -1)
+                {
+                  action = TGZ_INVALID;
+                  break;
+                }
+              if (action == TGZ_LIST)
+                printf(" %s %9d %s\n",strtime(&tartime),remaining,fname);
+              else if (action == TGZ_EXTRACT)
+                {
+                  if (matchname(arg,argc,argv,fname))
+                    {
+                      outfile = fopen(fname,"wb");
+                      if (outfile == NULL) {
+                        /* try creating directory */
+                        char *p = strrchr(fname, '/');
+                        if (p != NULL) {
+                          *p = '\0';
+                          makedir(fname);
+                          *p = '/';
+                          outfile = fopen(fname,"wb");
+                        }
+                      }
+                      if (outfile != NULL)
+                        printf("Extracting %s\n",fname);
+                      else
+                        fprintf(stderr, "%s: Couldn't create %s",prog,fname);
+                    }
+                  else
+                    outfile = NULL;
+                }
+              getheader = 0;
+              break;
+            case GNUTYPE_LONGLINK:
+            case GNUTYPE_LONGNAME:
+              remaining = getoct(buffer.header.size,12);
+              if (remaining < 0 || remaining >= BLOCKSIZE)
+                {
+                  action = TGZ_INVALID;
+                  break;
+                }
+              len = gzread(in, fname, BLOCKSIZE);
+              if (len < 0)
+                error(gzerror(in, &err));
+              if (fname[BLOCKSIZE-1] != 0 || (int)strlen(fname) > remaining)
+                {
+                  action = TGZ_INVALID;
+                  break;
+                }
+              getheader = 2;
+              break;
+            default:
+              if (action == TGZ_LIST)
+                printf(" %s     <---> %s\n",strtime(&tartime),fname);
+              break;
+            }
+        }
+      else
+        {
+          unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining;
+
+          if (outfile != NULL)
+            {
+              if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes)
+                {
+                  fprintf(stderr,
+                    "%s: Error writing %s -- skipping\n",prog,fname);
+                  fclose(outfile);
+                  outfile = NULL;
+                  remove(fname);
+                }
+            }
+          remaining -= bytes;
+        }
+
+      if (remaining == 0)
+        {
+          getheader = 1;
+          if (outfile != NULL)
+            {
+              fclose(outfile);
+              outfile = NULL;
+              if (action != TGZ_INVALID)
+                push_attr(&attributes,fname,tarmode,tartime);
+            }
+        }
+
+      /*
+       * Abandon if errors are found
+       */
+      if (action == TGZ_INVALID)
+        {
+          error("broken archive");
+          break;
+        }
+    }
+
+  /*
+   * Restore file modes and time stamps
+   */
+  restore_attr(&attributes);
+
+  if (gzclose(in) != Z_OK)
+    error("failed gzclose");
+
+  return 0;
+}
+
+
+/* ============================================================ */
+
+void help(int exitval)
+{
+  printf("untgz version 0.2.1\n"
+         "  using zlib version %s\n\n",
+         zlibVersion());
+  printf("Usage: untgz file.tgz            extract all files\n"
+         "       untgz file.tgz fname ...  extract selected files\n"
+         "       untgz -l file.tgz         list archive contents\n"
+         "       untgz -h                  display this help\n");
+  exit(exitval);
+}
+
+void error(const char *msg)
+{
+  fprintf(stderr, "%s: %s\n", prog, msg);
+  exit(1);
+}
+
+
+/* ============================================================ */
+
+#if defined(WIN32) && defined(__GNUC__)
+int _CRT_glob = 0;      /* disable argument globbing in MinGW */
+#endif
+
+int main(int argc,char **argv)
+{
+    int         action = TGZ_EXTRACT;
+    int         arg = 1;
+    char        *TGZfile;
+    gzFile      *f;
+
+    prog = strrchr(argv[0],'\\');
+    if (prog == NULL)
+      {
+        prog = strrchr(argv[0],'/');
+        if (prog == NULL)
+          {
+            prog = strrchr(argv[0],':');
+            if (prog == NULL)
+              prog = argv[0];
+            else
+              prog++;
+          }
+        else
+          prog++;
+      }
+    else
+      prog++;
+
+    if (argc == 1)
+      help(0);
+
+    if (strcmp(argv[arg],"-l") == 0)
+      {
+        action = TGZ_LIST;
+        if (argc == ++arg)
+          help(0);
+      }
+    else if (strcmp(argv[arg],"-h") == 0)
+      {
+        help(0);
+      }
+
+    if ((TGZfile = TGZfname(argv[arg])) == NULL)
+      TGZnotfound(argv[arg]);
+
+    ++arg;
+    if ((action == TGZ_LIST) && (arg != argc))
+      help(1);
+
+/*
+ *  Process the TGZ file
+ */
+    switch(action)
+      {
+      case TGZ_LIST:
+      case TGZ_EXTRACT:
+        f = gzopen(TGZfile,"rb");
+        if (f == NULL)
+          {
+            fprintf(stderr,"%s: Couldn't gzopen %s\n",prog,TGZfile);
+            return 1;
+          }
+        exit(tar(f, action, arg, argc, argv));
+      break;
+
+      default:
+        error("Unknown option");
+        exit(1);
+      }
+
+    return 0;
+}
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/readme.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/readme.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/readme.txt	(revision 9)
@@ -0,0 +1,73 @@
+Building instructions for the DLL versions of Zlib 1.2.3
+========================================================
+
+This directory contains projects that build zlib and minizip using
+Microsoft Visual C++ 7.0/7.1, and Visual C++ .
+
+You don't need to build these projects yourself. You can download the
+binaries from:
+  http://www.winimage.com/zLibDll
+
+More information can be found at this site.
+
+
+Build instructions for Visual Studio 7.x (32 bits)
+--------------------------------------------------
+- Uncompress current zlib, including all contrib/* files
+- Download the crtdll library from
+    http://www.winimage.com/zLibDll/crtdll.zip
+  Unzip crtdll.zip to extract crtdll.lib on contrib\vstudio\vc7.
+- Open contrib\vstudio\vc7\zlibvc.sln with Microsoft Visual C++ 7.x
+  (Visual Studio .Net 2002 or 2003).
+
+Build instructions for Visual Studio 2005 (32 bits or 64 bits)
+--------------------------------------------------------------
+- Uncompress current zlib, including all contrib/* files
+- For 32 bits only: download the crtdll library from
+    http://www.winimage.com/zLibDll/crtdll.zip
+  Unzip crtdll.zip to extract crtdll.lib on contrib\vstudio\vc8.
+- Open contrib\vstudio\vc8\zlibvc.sln with Microsoft Visual C++ 8.0
+
+Build instructions for Visual Studio 2005 64 bits, PSDK compiler
+----------------------------------------------------------------
+at the time of writing this text file, Visual Studio 2005 (and 
+  Microsoft Visual C++ 8.0) is on the beta 2 stage.
+Using you can get the free 64 bits compiler from Platform SDK, 
+  which is NOT a beta, and compile using the Visual studio 2005 IDE
+see http://www.winimage.com/misc/sdk64onvs2005/ for instruction
+
+- Uncompress current zlib, including all contrib/* files
+- start Visual Studio 2005 from a platform SDK command prompt, using
+  the /useenv switch
+- Open contrib\vstudio\vc8\zlibvc.sln with Microsoft Visual C++ 8.0
+
+
+Important
+---------
+- To use zlibwapi.dll in your application, you must define the
+  macro ZLIB_WINAPI when compiling your application's source files.
+
+
+Additional notes
+----------------
+- This DLL, named zlibwapi.dll, is compatible to the old zlib.dll built
+  by Gilles Vollant from the zlib 1.1.x sources, and distributed at
+    http://www.winimage.com/zLibDll
+  It uses the WINAPI calling convention for the exported functions, and
+  includes the minizip functionality. If your application needs that
+  particular build of zlib.dll, you can rename zlibwapi.dll to zlib.dll.
+
+- The new DLL was renamed because there exist several incompatible
+  versions of zlib.dll on the Internet.
+
+- There is also an official DLL build of zlib, named zlib1.dll. This one
+  is exporting the functions using the CDECL convention. See the file
+  win32\DLL_FAQ.txt found in this zlib distribution.
+
+- There used to be a ZLIB_DLL macro in zlib 1.1.x, but now this symbol
+  has a slightly different effect. To avoid compatibility problems, do
+  not define it here.
+
+
+Gilles Vollant
+info@winimage.com
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/miniunz.vcproj
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/miniunz.vcproj	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/miniunz.vcproj	(revision 9)
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding = "Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="miniunz"
+	ProjectGUID="{C52F9E7B-498A-42BE-8DB4-85A15694382A}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="5"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/miniunz.exe"
+				LinkIncremental="2"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/miniunz.pdb"
+				SubSystem="1"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="TRUE"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE"
+				StringPooling="TRUE"
+				RuntimeLibrary="4"
+				EnableFunctionLevelLinking="TRUE"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/miniunz.exe"
+				LinkIncremental="1"
+				GenerateDebugInformation="TRUE"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
+			<File
+				RelativePath="..\..\minizip\miniunz.c">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc">
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+		</Filter>
+		<File
+			RelativePath="ReleaseDll\zlibwapi.lib">
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/minizip.vcproj
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/minizip.vcproj	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/minizip.vcproj	(revision 9)
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding = "Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="minizip"
+	ProjectGUID="{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="5"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/minizip.exe"
+				LinkIncremental="2"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/minizip.pdb"
+				SubSystem="1"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="TRUE"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE"
+				StringPooling="TRUE"
+				RuntimeLibrary="4"
+				EnableFunctionLevelLinking="TRUE"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/minizip.exe"
+				LinkIncremental="1"
+				GenerateDebugInformation="TRUE"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
+			<File
+				RelativePath="..\..\minizip\minizip.c">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc">
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+		</Filter>
+		<File
+			RelativePath="ReleaseDll\zlibwapi.lib">
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/testzlib.vcproj
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/testzlib.vcproj	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/testzlib.vcproj	(revision 9)
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding = "Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="testZlibDll"
+	ProjectGUID="{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\.."
+				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="5"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/testzlib.exe"
+				LinkIncremental="2"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
+				SubSystem="1"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="TRUE"
+				AdditionalIncludeDirectories="..\..\.."
+				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE"
+				StringPooling="TRUE"
+				RuntimeLibrary="4"
+				EnableFunctionLevelLinking="TRUE"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/testzlib.exe"
+				LinkIncremental="1"
+				GenerateDebugInformation="TRUE"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
+			<File
+				RelativePath="..\..\testzlib\testzlib.c">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc">
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+		</Filter>
+		<File
+			RelativePath="ReleaseDll\zlibwapi.lib">
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/zlib.rc
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/zlib.rc	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/zlib.rc	(revision 9)
@@ -0,0 +1,32 @@
+#include <windows.h>
+
+#define IDR_VERSION1  1
+IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
+  FILEVERSION	 1,2,3,0
+  PRODUCTVERSION 1,2,3,0
+  FILEFLAGSMASK	VS_FFI_FILEFLAGSMASK
+  FILEFLAGS	0
+  FILEOS	VOS_DOS_WINDOWS32
+  FILETYPE	VFT_DLL
+  FILESUBTYPE	0	// not used
+BEGIN
+  BLOCK "StringFileInfo"
+  BEGIN
+    BLOCK "040904E4"
+    //language ID = U.S. English, char set = Windows, Multilingual
+
+    BEGIN
+      VALUE "FileDescription", "zlib data compression library\0"
+      VALUE "FileVersion",	"1.2.3.0\0"
+      VALUE "InternalName",	"zlib\0"
+      VALUE "OriginalFilename",	"zlib.dll\0"
+      VALUE "ProductName",	"ZLib.DLL\0"
+      VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
+      VALUE "LegalCopyright", "(C) 1995-2003 Jean-loup Gailly & Mark Adler\0"
+    END
+  END
+  BLOCK "VarFileInfo"
+  BEGIN
+    VALUE "Translation", 0x0409, 1252
+  END
+END
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/zlibstat.vcproj
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/zlibstat.vcproj	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/zlibstat.vcproj	(revision 9)
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding = "Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="zlibstat"
+	SccProjectName=""
+	SccLocalPath="">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory=".\zlibstatDebug"
+			IntermediateDirectory=".\zlibstatDebug"
+			ConfigurationType="4"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32;ZLIB_WINAPI"
+				ExceptionHandling="FALSE"
+				RuntimeLibrary="5"
+				PrecompiledHeaderFile=".\zlibstatDebug/zlibstat.pch"
+				AssemblerListingLocation=".\zlibstatDebug/"
+				ObjectFile=".\zlibstatDebug/"
+				ProgramDataBaseFileName=".\zlibstatDebug/"
+				WarningLevel="3"
+				SuppressStartupBanner="TRUE"
+				DebugInformationFormat="1"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="/NODEFAULTLIB "
+				OutputFile=".\zlibstatDebug\zlibstat.lib"
+				SuppressStartupBanner="TRUE"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				Culture="1036"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseAxp|Win32"
+			OutputDirectory=".\zlibsta0"
+			IntermediateDirectory=".\zlibsta0"
+			ConfigurationType="4"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE">
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32;ZLIB_WINAPI"
+				StringPooling="TRUE"
+				ExceptionHandling="FALSE"
+				RuntimeLibrary="4"
+				EnableFunctionLevelLinking="TRUE"
+				PrecompiledHeaderFile=".\zlibsta0/zlibstat.pch"
+				AssemblerListingLocation=".\zlibsta0/"
+				ObjectFile=".\zlibsta0/"
+				ProgramDataBaseFileName=".\zlibsta0/"
+				WarningLevel="3"
+				SuppressStartupBanner="TRUE"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="/NODEFAULTLIB "
+				OutputFile=".\zlibsta0\zlibstat.lib"
+				SuppressStartupBanner="TRUE"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory=".\zlibstat"
+			IntermediateDirectory=".\zlibstat"
+			ConfigurationType="4"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE">
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;ASMV;ASMINF"
+				StringPooling="TRUE"
+				ExceptionHandling="FALSE"
+				RuntimeLibrary="4"
+				EnableFunctionLevelLinking="TRUE"
+				PrecompiledHeaderFile=".\zlibstat/zlibstat.pch"
+				AssemblerListingLocation=".\zlibstat/"
+				ObjectFile=".\zlibstat/"
+				ProgramDataBaseFileName=".\zlibstat/"
+				WarningLevel="3"
+				SuppressStartupBanner="TRUE"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj /NODEFAULTLIB "
+				OutputFile=".\zlibstat\zlibstat.lib"
+				SuppressStartupBanner="TRUE"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				Culture="1036"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseWithoutAsm|Win32"
+			OutputDirectory="zlibstatWithoutAsm"
+			IntermediateDirectory="zlibstatWithoutAsm"
+			ConfigurationType="4"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE">
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32;ZLIB_WINAPI"
+				StringPooling="TRUE"
+				ExceptionHandling="FALSE"
+				RuntimeLibrary="4"
+				EnableFunctionLevelLinking="TRUE"
+				PrecompiledHeaderFile=".\zlibstat/zlibstat.pch"
+				AssemblerListingLocation=".\zlibstatWithoutAsm/"
+				ObjectFile=".\zlibstatWithoutAsm/"
+				ProgramDataBaseFileName=".\zlibstatWithoutAsm/"
+				WarningLevel="3"
+				SuppressStartupBanner="TRUE"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions=" /NODEFAULTLIB "
+				OutputFile=".\zlibstatWithoutAsm\zlibstat.lib"
+				SuppressStartupBanner="TRUE"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				Culture="1036"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="">
+			<File
+				RelativePath="..\..\..\adler32.c">
+			</File>
+			<File
+				RelativePath="..\..\..\compress.c">
+			</File>
+			<File
+				RelativePath="..\..\..\crc32.c">
+			</File>
+			<File
+				RelativePath="..\..\..\deflate.c">
+			</File>
+			<File
+				RelativePath="..\..\masmx86\gvmat32c.c">
+			</File>
+			<File
+				RelativePath="..\..\..\gzio.c">
+			</File>
+			<File
+				RelativePath="..\..\..\infback.c">
+			</File>
+			<File
+				RelativePath="..\..\..\inffast.c">
+			</File>
+			<File
+				RelativePath="..\..\..\inflate.c">
+			</File>
+			<File
+				RelativePath="..\..\..\inftrees.c">
+			</File>
+			<File
+				RelativePath="..\..\minizip\ioapi.c">
+			</File>
+			<File
+				RelativePath="..\..\..\trees.c">
+			</File>
+			<File
+				RelativePath="..\..\..\uncompr.c">
+			</File>
+			<File
+				RelativePath="..\..\minizip\unzip.c">
+			</File>
+			<File
+				RelativePath="..\..\minizip\zip.c">
+			</File>
+			<File
+				RelativePath=".\zlib.rc">
+			</File>
+			<File
+				RelativePath=".\zlibvc.def">
+			</File>
+			<File
+				RelativePath="..\..\..\zutil.c">
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/zlibvc.def
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/zlibvc.def	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/zlibvc.def	(revision 9)
@@ -0,0 +1,92 @@
+
+VERSION		1.23
+
+HEAPSIZE	1048576,8192
+
+EXPORTS
+        adler32                                  @1
+        compress                                 @2
+        crc32                                    @3
+        deflate                                  @4
+        deflateCopy                              @5
+        deflateEnd                               @6
+        deflateInit2_                            @7
+        deflateInit_                             @8
+        deflateParams                            @9
+        deflateReset                             @10
+        deflateSetDictionary                     @11
+        gzclose                                  @12
+        gzdopen                                  @13
+        gzerror                                  @14
+        gzflush                                  @15
+        gzopen                                   @16
+        gzread                                   @17
+        gzwrite                                  @18
+        inflate                                  @19
+        inflateEnd                               @20
+        inflateInit2_                            @21
+        inflateInit_                             @22
+        inflateReset                             @23
+        inflateSetDictionary                     @24
+        inflateSync                              @25
+        uncompress                               @26
+        zlibVersion                              @27
+        gzprintf                                 @28
+        gzputc                                   @29
+        gzgetc                                   @30
+        gzseek                                   @31
+        gzrewind                                 @32
+        gztell                                   @33
+        gzeof                                    @34
+        gzsetparams                              @35
+        zError                                   @36
+        inflateSyncPoint                         @37
+        get_crc_table                            @38
+        compress2                                @39
+        gzputs                                   @40
+        gzgets                                   @41
+        inflateCopy                              @42
+        inflateBackInit_                         @43
+        inflateBack                              @44
+        inflateBackEnd                           @45
+        compressBound                            @46
+        deflateBound                             @47
+        gzclearerr                               @48
+        gzungetc                                 @49
+        zlibCompileFlags                         @50
+        deflatePrime                             @51
+
+        unzOpen                                  @61
+        unzClose                                 @62
+        unzGetGlobalInfo                         @63
+        unzGetCurrentFileInfo                    @64
+        unzGoToFirstFile                         @65
+        unzGoToNextFile                          @66
+        unzOpenCurrentFile                       @67
+        unzReadCurrentFile                       @68
+        unzOpenCurrentFile3                      @69
+        unztell                                  @70
+        unzeof                                   @71
+        unzCloseCurrentFile                      @72
+        unzGetGlobalComment                      @73
+        unzStringFileNameCompare                 @74
+        unzLocateFile                            @75
+        unzGetLocalExtrafield                    @76
+        unzOpen2                                 @77
+        unzOpenCurrentFile2                      @78
+        unzOpenCurrentFilePassword               @79
+
+        zipOpen                                  @80
+        zipOpenNewFileInZip                      @81
+        zipWriteInFileInZip                      @82
+        zipCloseFileInZip                        @83
+        zipClose                                 @84
+        zipOpenNewFileInZip2                     @86
+        zipCloseFileInZipRaw                     @87
+        zipOpen2                                 @88
+        zipOpenNewFileInZip3                     @89
+
+        unzGetFilePos                            @100
+        unzGoToFilePos                           @101
+
+        fill_win32_filefunc                      @110
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/zlibvc.sln
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/zlibvc.sln	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/zlibvc.sln	(revision 9)
@@ -0,0 +1,78 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testZlibDll", "testzlib.vcproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}"
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		ConfigName.0 = Debug
+		ConfigName.1 = Release
+		ConfigName.2 = ReleaseAxp
+		ConfigName.3 = ReleaseWithoutAsm
+		ConfigName.4 = ReleaseWithoutCrtdll
+	EndGlobalSection
+	GlobalSection(ProjectDependencies) = postSolution
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug.ActiveCfg = Debug|Win32
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug.Build.0 = Debug|Win32
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release.ActiveCfg = Release|Win32
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release.Build.0 = Release|Win32
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseAxp.ActiveCfg = ReleaseAxp|Win32
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseAxp.Build.0 = ReleaseAxp|Win32
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm.ActiveCfg = ReleaseWithoutAsm|Win32
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm.Build.0 = ReleaseWithoutAsm|Win32
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutCrtdll.ActiveCfg = ReleaseAxp|Win32
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutCrtdll.Build.0 = ReleaseAxp|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug.ActiveCfg = Debug|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug.Build.0 = Debug|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release.ActiveCfg = Release|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release.Build.0 = Release|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseAxp.ActiveCfg = ReleaseAxp|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseAxp.Build.0 = ReleaseAxp|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm.ActiveCfg = ReleaseWithoutAsm|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm.Build.0 = ReleaseWithoutAsm|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutCrtdll.ActiveCfg = ReleaseWithoutCrtdll|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutCrtdll.Build.0 = ReleaseWithoutCrtdll|Win32
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug.ActiveCfg = Debug|Win32
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug.Build.0 = Debug|Win32
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release.ActiveCfg = Release|Win32
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release.Build.0 = Release|Win32
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAxp.ActiveCfg = Release|Win32
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAxp.Build.0 = Release|Win32
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm.ActiveCfg = Release|Win32
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm.Build.0 = Release|Win32
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutCrtdll.ActiveCfg = Release|Win32
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutCrtdll.Build.0 = Release|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug.ActiveCfg = Debug|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug.Build.0 = Debug|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release.ActiveCfg = Release|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release.Build.0 = Release|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseAxp.ActiveCfg = Release|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseAxp.Build.0 = Release|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm.ActiveCfg = Release|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm.Build.0 = Release|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutCrtdll.ActiveCfg = Release|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutCrtdll.Build.0 = Release|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.Debug.ActiveCfg = Debug|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.Debug.Build.0 = Debug|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.Release.ActiveCfg = Release|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.Release.Build.0 = Release|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.ReleaseAxp.ActiveCfg = Release|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.ReleaseAxp.Build.0 = Release|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.ReleaseWithoutAsm.ActiveCfg = Release|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.ReleaseWithoutAsm.Build.0 = Release|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.ReleaseWithoutCrtdll.ActiveCfg = Release|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.ReleaseWithoutCrtdll.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/zlibvc.vcproj
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/zlibvc.vcproj	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc7/zlibvc.vcproj	(revision 9)
@@ -0,0 +1,445 @@
+<?xml version="1.0" encoding = "Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="zlibvc"
+	SccProjectName=""
+	SccLocalPath="">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory=".\DebugDll"
+			IntermediateDirectory=".\DebugDll"
+			ConfigurationType="2"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32,ZLIB_WINAPI,ASMV,ASMINF"
+				ExceptionHandling="FALSE"
+				RuntimeLibrary="1"
+				PrecompiledHeaderFile=".\DebugDll/zlibvc.pch"
+				AssemblerListingLocation=".\DebugDll/"
+				ObjectFile=".\DebugDll/"
+				ProgramDataBaseFileName=".\DebugDll/"
+				WarningLevel="3"
+				SuppressStartupBanner="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/MACHINE:I386"
+				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj"
+				OutputFile=".\DebugDll\zlibwapi.dll"
+				LinkIncremental="2"
+				SuppressStartupBanner="TRUE"
+				ModuleDefinitionFile=".\zlibvc.def"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile=".\DebugDll/zlibwapi.pdb"
+				SubSystem="2"
+				ImportLibrary=".\DebugDll/zlibwapi.lib"/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="TRUE"
+				SuppressStartupBanner="TRUE"
+				TargetEnvironment="1"
+				TypeLibraryName=".\DebugDll/zlibvc.tlb"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1036"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseWithoutAsm|Win32"
+			OutputDirectory=".\zlibDllWithoutAsm"
+			IntermediateDirectory=".\zlibDllWithoutAsm"
+			ConfigurationType="2"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE"
+			WholeProgramOptimization="TRUE">
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32,ZLIB_WINAPI"
+				StringPooling="TRUE"
+				ExceptionHandling="FALSE"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="TRUE"
+				PrecompiledHeaderFile=".\zlibDllWithoutAsm/zlibvc.pch"
+				AssemblerOutput="2"
+				AssemblerListingLocation=".\zlibDllWithoutAsm/"
+				ObjectFile=".\zlibDllWithoutAsm/"
+				ProgramDataBaseFileName=".\zlibDllWithoutAsm/"
+				BrowseInformation="1"
+				WarningLevel="3"
+				SuppressStartupBanner="TRUE"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/MACHINE:I386"
+				AdditionalDependencies="crtdll.lib"
+				OutputFile=".\zlibDllWithoutAsm\zlibwapi.dll"
+				LinkIncremental="1"
+				SuppressStartupBanner="TRUE"
+				IgnoreAllDefaultLibraries="TRUE"
+				ModuleDefinitionFile=".\zlibvc.def"
+				ProgramDatabaseFile=".\zlibDllWithoutAsm/zlibwapi.pdb"
+				GenerateMapFile="TRUE"
+				MapFileName=".\zlibDllWithoutAsm/zlibwapi.map"
+				SubSystem="2"
+				OptimizeForWindows98="1"
+				ImportLibrary=".\zlibDllWithoutAsm/zlibwapi.lib"/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="TRUE"
+				SuppressStartupBanner="TRUE"
+				TargetEnvironment="1"
+				TypeLibraryName=".\zlibDllWithoutAsm/zlibvc.tlb"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1036"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseWithoutCrtdll|Win32"
+			OutputDirectory=".\zlibDllWithoutCrtDll"
+			IntermediateDirectory=".\zlibDllWithoutCrtDll"
+			ConfigurationType="2"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE"
+			WholeProgramOptimization="TRUE">
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32,ZLIB_WINAPI,ASMV,ASMINF"
+				StringPooling="TRUE"
+				ExceptionHandling="FALSE"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="TRUE"
+				PrecompiledHeaderFile=".\zlibDllWithoutCrtDll/zlibvc.pch"
+				AssemblerOutput="2"
+				AssemblerListingLocation=".\zlibDllWithoutCrtDll/"
+				ObjectFile=".\zlibDllWithoutCrtDll/"
+				ProgramDataBaseFileName=".\zlibDllWithoutCrtDll/"
+				BrowseInformation="1"
+				WarningLevel="3"
+				SuppressStartupBanner="TRUE"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/MACHINE:I386"
+				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj "
+				OutputFile=".\zlibDllWithoutCrtDll\zlibwapi.dll"
+				LinkIncremental="1"
+				SuppressStartupBanner="TRUE"
+				IgnoreAllDefaultLibraries="FALSE"
+				ModuleDefinitionFile=".\zlibvc.def"
+				ProgramDatabaseFile=".\zlibDllWithoutCrtDll/zlibwapi.pdb"
+				GenerateMapFile="TRUE"
+				MapFileName=".\zlibDllWithoutCrtDll/zlibwapi.map"
+				SubSystem="2"
+				OptimizeForWindows98="1"
+				ImportLibrary=".\zlibDllWithoutCrtDll/zlibwapi.lib"/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="TRUE"
+				SuppressStartupBanner="TRUE"
+				TargetEnvironment="1"
+				TypeLibraryName=".\zlibDllWithoutCrtDll/zlibvc.tlb"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1036"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseAxp|Win32"
+			OutputDirectory=".\zlibvc__"
+			IntermediateDirectory=".\zlibvc__"
+			ConfigurationType="2"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE"
+			WholeProgramOptimization="TRUE">
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32,ZLIB_WINAPI"
+				StringPooling="TRUE"
+				ExceptionHandling="FALSE"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="TRUE"
+				PrecompiledHeaderFile=".\zlibvc__/zlibvc.pch"
+				AssemblerOutput="2"
+				AssemblerListingLocation=".\zlibvc__/"
+				ObjectFile=".\zlibvc__/"
+				ProgramDataBaseFileName=".\zlibvc__/"
+				BrowseInformation="1"
+				WarningLevel="3"
+				SuppressStartupBanner="TRUE"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="crtdll.lib"
+				OutputFile="zlibvc__\zlibwapi.dll"
+				LinkIncremental="1"
+				SuppressStartupBanner="TRUE"
+				IgnoreAllDefaultLibraries="TRUE"
+				ModuleDefinitionFile=".\zlibvc.def"
+				ProgramDatabaseFile=".\zlibvc__/zlibwapi.pdb"
+				GenerateMapFile="TRUE"
+				MapFileName=".\zlibvc__/zlibwapi.map"
+				SubSystem="2"
+				ImportLibrary=".\zlibvc__/zlibwapi.lib"/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="TRUE"
+				SuppressStartupBanner="TRUE"
+				TargetEnvironment="1"
+				TypeLibraryName=".\zlibvc__/zlibvc.tlb"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1036"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory=".\ReleaseDll"
+			IntermediateDirectory=".\ReleaseDll"
+			ConfigurationType="2"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE"
+			WholeProgramOptimization="TRUE">
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32,ZLIB_WINAPI,ASMV,ASMINF"
+				StringPooling="TRUE"
+				ExceptionHandling="FALSE"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="TRUE"
+				PrecompiledHeaderFile=".\ReleaseDll/zlibvc.pch"
+				AssemblerOutput="2"
+				AssemblerListingLocation=".\ReleaseDll/"
+				ObjectFile=".\ReleaseDll/"
+				ProgramDataBaseFileName=".\ReleaseDll/"
+				BrowseInformation="1"
+				WarningLevel="3"
+				SuppressStartupBanner="TRUE"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/MACHINE:I386"
+				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj crtdll.lib"
+				OutputFile=".\ReleaseDll\zlibwapi.dll"
+				LinkIncremental="1"
+				SuppressStartupBanner="TRUE"
+				IgnoreAllDefaultLibraries="TRUE"
+				ModuleDefinitionFile=".\zlibvc.def"
+				ProgramDatabaseFile=".\ReleaseDll/zlibwapi.pdb"
+				GenerateMapFile="TRUE"
+				MapFileName=".\ReleaseDll/zlibwapi.map"
+				SubSystem="2"
+				OptimizeForWindows98="1"
+				ImportLibrary=".\ReleaseDll/zlibwapi.lib"/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="TRUE"
+				SuppressStartupBanner="TRUE"
+				TargetEnvironment="1"
+				TypeLibraryName=".\Release/zlibvc.tlb"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1036"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90">
+			<File
+				RelativePath="..\..\..\adler32.c">
+			</File>
+			<File
+				RelativePath="..\..\..\compress.c">
+			</File>
+			<File
+				RelativePath="..\..\..\crc32.c">
+			</File>
+			<File
+				RelativePath="..\..\..\deflate.c">
+			</File>
+			<File
+				RelativePath="..\..\masmx86\gvmat32c.c">
+				<FileConfiguration
+					Name="ReleaseWithoutAsm|Win32"
+					ExcludedFromBuild="TRUE">
+					<Tool
+						Name="VCCLCompilerTool"/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\..\gzio.c">
+			</File>
+			<File
+				RelativePath="..\..\..\infback.c">
+			</File>
+			<File
+				RelativePath="..\..\..\inffast.c">
+			</File>
+			<File
+				RelativePath="..\..\..\inflate.c">
+			</File>
+			<File
+				RelativePath="..\..\..\inftrees.c">
+			</File>
+			<File
+				RelativePath="..\..\minizip\ioapi.c">
+			</File>
+			<File
+				RelativePath="..\..\minizip\iowin32.c">
+			</File>
+			<File
+				RelativePath="..\..\..\trees.c">
+			</File>
+			<File
+				RelativePath="..\..\..\uncompr.c">
+			</File>
+			<File
+				RelativePath="..\..\minizip\unzip.c">
+				<FileConfiguration
+					Name="Release|Win32">
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions="ZLIB_INTERNAL"/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\minizip\zip.c">
+				<FileConfiguration
+					Name="Release|Win32">
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions="ZLIB_INTERNAL"/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\zlib.rc">
+			</File>
+			<File
+				RelativePath=".\zlibvc.def">
+			</File>
+			<File
+				RelativePath="..\..\..\zutil.c">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;fi;fd">
+			<File
+				RelativePath="..\..\..\deflate.h">
+			</File>
+			<File
+				RelativePath="..\..\..\infblock.h">
+			</File>
+			<File
+				RelativePath="..\..\..\infcodes.h">
+			</File>
+			<File
+				RelativePath="..\..\..\inffast.h">
+			</File>
+			<File
+				RelativePath="..\..\..\inftrees.h">
+			</File>
+			<File
+				RelativePath="..\..\..\infutil.h">
+			</File>
+			<File
+				RelativePath="..\..\..\zconf.h">
+			</File>
+			<File
+				RelativePath="..\..\..\zlib.h">
+			</File>
+			<File
+				RelativePath="..\..\..\zutil.h">
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe">
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/miniunz.vcproj
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/miniunz.vcproj	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/miniunz.vcproj	(revision 9)
@@ -0,0 +1,566 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8,00"
+	Name="miniunz"
+	ProjectGUID="{C52F9E7B-498A-42BE-8DB4-85A15694382A}"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+		<Platform
+			Name="Itanium"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="x86\MiniUnzip$(ConfigurationName)"
+			IntermediateDirectory="x86\MiniUnzip$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="1"
+				BufferSecurityCheck="false"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="x86\ZlibDllDebug\zlibwapi.lib"
+				OutputFile="$(OutDir)/miniunz.exe"
+				LinkIncremental="2"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/miniunz.pdb"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="x64\MiniUnzip$(ConfigurationName)"
+			IntermediateDirectory="x64\MiniUnzip$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="false"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="x64\ZlibDllDebug\zlibwapi.lib"
+				OutputFile="$(OutDir)/miniunz.exe"
+				LinkIncremental="2"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/miniunz.pdb"
+				SubSystem="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|Itanium"
+			OutputDirectory="ia64\MiniUnzip$(ConfigurationName)"
+			IntermediateDirectory="ia64\MiniUnzip$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="2"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="false"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="ia64\ZlibDllDebug\zlibwapi.lib"
+				OutputFile="$(OutDir)/miniunz.exe"
+				LinkIncremental="2"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/miniunz.pdb"
+				SubSystem="1"
+				TargetMachine="5"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="x86\MiniUnzip$(ConfigurationName)"
+			IntermediateDirectory="x86\MiniUnzip$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE"
+				StringPooling="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="0"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="x86\ZlibDllRelease\zlibwapi.lib"
+				OutputFile="$(OutDir)/miniunz.exe"
+				LinkIncremental="1"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="x64\MiniUnzip$(ConfigurationName)"
+			IntermediateDirectory="x64\MiniUnzip$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64"
+				StringPooling="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="x64\ZlibDllRelease\zlibwapi.lib"
+				OutputFile="$(OutDir)/miniunz.exe"
+				LinkIncremental="1"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Itanium"
+			OutputDirectory="ia64\MiniUnzip$(ConfigurationName)"
+			IntermediateDirectory="ia64\MiniUnzip$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="2"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64"
+				StringPooling="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="ia64\ZlibDllRelease\zlibwapi.lib"
+				OutputFile="$(OutDir)/miniunz.exe"
+				LinkIncremental="1"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="5"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+			>
+			<File
+				RelativePath="..\..\minizip\miniunz.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc"
+			>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/minizip.vcproj
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/minizip.vcproj	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/minizip.vcproj	(revision 9)
@@ -0,0 +1,563 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8,00"
+	Name="minizip"
+	ProjectGUID="{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+		<Platform
+			Name="Itanium"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="x86\MiniZip$(ConfigurationName)"
+			IntermediateDirectory="x86\MiniZip$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="1"
+				BufferSecurityCheck="false"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="x86\ZlibDllDebug\zlibwapi.lib"
+				OutputFile="$(OutDir)/minizip.exe"
+				LinkIncremental="2"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/minizip.pdb"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="x64\$(ConfigurationName)"
+			IntermediateDirectory="x64\$(ConfigurationName)"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="false"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="x64\ZlibDllDebug\zlibwapi.lib"
+				OutputFile="$(OutDir)/minizip.exe"
+				LinkIncremental="2"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/minizip.pdb"
+				SubSystem="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|Itanium"
+			OutputDirectory="ia64\$(ConfigurationName)"
+			IntermediateDirectory="ia64\$(ConfigurationName)"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="2"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="false"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="ia64\ZlibDllDebug\zlibwapi.lib"
+				OutputFile="$(OutDir)/minizip.exe"
+				LinkIncremental="2"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/minizip.pdb"
+				SubSystem="1"
+				TargetMachine="5"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="x86\MiniZip$(ConfigurationName)"
+			IntermediateDirectory="x86\MiniZip$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE"
+				StringPooling="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="0"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="x86\ZlibDllRelease\zlibwapi.lib"
+				OutputFile="$(OutDir)/minizip.exe"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="x64\$(ConfigurationName)"
+			IntermediateDirectory="x64\$(ConfigurationName)"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64"
+				StringPooling="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="x64\ZlibDllRelease\zlibwapi.lib"
+				OutputFile="$(OutDir)/minizip.exe"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Itanium"
+			OutputDirectory="ia64\$(ConfigurationName)"
+			IntermediateDirectory="ia64\$(ConfigurationName)"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="2"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64"
+				StringPooling="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="ia64\ZlibDllRelease\zlibwapi.lib"
+				OutputFile="$(OutDir)/minizip.exe"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="5"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+			>
+			<File
+				RelativePath="..\..\minizip\minizip.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc"
+			>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/testzlib.vcproj
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/testzlib.vcproj	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/testzlib.vcproj	(revision 9)
@@ -0,0 +1,948 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8,00"
+	Name="testzlib"
+	ProjectGUID="{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}"
+	RootNamespace="testzlib"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+		<Platform
+			Name="Itanium"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="x86\TestZlib$(ConfigurationName)"
+			IntermediateDirectory="x86\TestZlib$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\.."
+				PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="1"
+				BufferSecurityCheck="false"
+				UsePrecompiledHeader="0"
+				AssemblerOutput="4"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj"
+				OutputFile="$(OutDir)/testzlib.exe"
+				LinkIncremental="2"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="x64\TestZlib$(ConfigurationName)"
+			IntermediateDirectory="x64\TestZlib$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\..\.."
+				PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="false"
+				AssemblerListingLocation="$(IntDir)\"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="..\..\masmx64\gvmat64.obj ..\..\masmx64\inffasx64.obj"
+				GenerateManifest="false"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|Itanium"
+			OutputDirectory="ia64\TestZlib$(ConfigurationName)"
+			IntermediateDirectory="ia64\TestZlib$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="2"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\.."
+				PreprocessorDefinitions="ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="false"
+				UsePrecompiledHeader="0"
+				AssemblerOutput="4"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/testzlib.exe"
+				LinkIncremental="2"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
+				SubSystem="1"
+				TargetMachine="5"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseWithoutAsm|Win32"
+			OutputDirectory="x86\TestZlib$(ConfigurationName)"
+			IntermediateDirectory="x86\TestZlib$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="..\..\.."
+				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
+				StringPooling="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="0"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/testzlib.exe"
+				LinkIncremental="1"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseWithoutAsm|x64"
+			OutputDirectory="x64\TestZlib$(ConfigurationName)"
+			IntermediateDirectory="x64\TestZlib$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\..\.."
+				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				AssemblerListingLocation="$(IntDir)\"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies=""
+				GenerateManifest="false"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseWithoutAsm|Itanium"
+			OutputDirectory="ia64\TestZlib$(ConfigurationName)"
+			IntermediateDirectory="ia64\TestZlib$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="2"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="..\..\.."
+				PreprocessorDefinitions="ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
+				StringPooling="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/testzlib.exe"
+				LinkIncremental="1"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="5"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="x86\TestZlib$(ConfigurationName)"
+			IntermediateDirectory="x86\TestZlib$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="..\..\.."
+				PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
+				StringPooling="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="0"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj"
+				OutputFile="$(OutDir)/testzlib.exe"
+				LinkIncremental="1"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="x64\TestZlib$(ConfigurationName)"
+			IntermediateDirectory="x64\TestZlib$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\..\.."
+				PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				AssemblerListingLocation="$(IntDir)\"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="..\..\masmx64\gvmat64.obj ..\..\masmx64\inffasx64.obj"
+				GenerateManifest="false"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Itanium"
+			OutputDirectory="ia64\TestZlib$(ConfigurationName)"
+			IntermediateDirectory="ia64\TestZlib$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="2"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="..\..\.."
+				PreprocessorDefinitions="ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
+				StringPooling="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/testzlib.exe"
+				LinkIncremental="1"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="5"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+			>
+			<File
+				RelativePath="..\..\..\adler32.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\compress.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\crc32.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\deflate.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\masmx86\gvmat32c.c"
+				>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="ReleaseWithoutAsm|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="ReleaseWithoutAsm|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win64 (AMD64)"
+					ExcludedFromBuild="TRUE"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win64 (AMD64)"
+					ExcludedFromBuild="TRUE"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="ReleaseAsm|Win64 (AMD64)"
+					ExcludedFromBuild="TRUE"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\..\infback.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\masmx64\inffas8664.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="ReleaseWithoutAsm|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="ReleaseWithoutAsm|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\..\inffast.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\inflate.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\inftrees.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\testzlib\testzlib.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\trees.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\uncompr.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\zutil.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc"
+			>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/testzlibdll.vcproj
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/testzlibdll.vcproj	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/testzlibdll.vcproj	(revision 9)
@@ -0,0 +1,567 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8,00"
+	Name="TestZlibDll"
+	ProjectGUID="{C52F9E7B-498A-42BE-8DB4-85A15694366A}"
+	Keyword="Win32Proj"
+	SignManifests="true"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+		<Platform
+			Name="Itanium"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="x86\TestZlibDll$(ConfigurationName)"
+			IntermediateDirectory="x86\TestZlibDll$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="1"
+				BufferSecurityCheck="false"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="x86\ZlibDllDebug\zlibwapi.lib"
+				OutputFile="$(OutDir)/testzlib.exe"
+				LinkIncremental="2"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="x64\TestZlibDll$(ConfigurationName)"
+			IntermediateDirectory="x64\TestZlibDll$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="false"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="x64\ZlibDllDebug\zlibwapi.lib"
+				OutputFile="$(OutDir)/testzlib.exe"
+				LinkIncremental="2"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
+				SubSystem="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|Itanium"
+			OutputDirectory="ia64\TestZlibDll$(ConfigurationName)"
+			IntermediateDirectory="ia64\TestZlibDll$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="2"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="false"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="ia64\ZlibDllDebug\zlibwapi.lib"
+				OutputFile="$(OutDir)/testzlib.exe"
+				LinkIncremental="2"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
+				SubSystem="1"
+				TargetMachine="5"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="x86\TestZlibDll$(ConfigurationName)"
+			IntermediateDirectory="x86\TestZlibDll$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE"
+				StringPooling="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="0"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="x86\ZlibDllRelease\zlibwapi.lib"
+				OutputFile="$(OutDir)/testzlib.exe"
+				LinkIncremental="1"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="x64\TestZlibDll$(ConfigurationName)"
+			IntermediateDirectory="x64\TestZlibDll$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64"
+				StringPooling="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="x64\ZlibDllRelease\zlibwapi.lib"
+				OutputFile="$(OutDir)/testzlib.exe"
+				LinkIncremental="1"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Itanium"
+			OutputDirectory="ia64\TestZlibDll$(ConfigurationName)"
+			IntermediateDirectory="ia64\TestZlibDll$(ConfigurationName)\Tmp"
+			ConfigurationType="1"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="2"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
+				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64"
+				StringPooling="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(IntDir)\"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="ia64\ZlibDllRelease\zlibwapi.lib"
+				OutputFile="$(OutDir)/testzlib.exe"
+				LinkIncremental="1"
+				GenerateManifest="false"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
+				TargetMachine="5"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+			>
+			<File
+				RelativePath="..\..\testzlib\testzlib.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc"
+			>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/zlib.rc
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/zlib.rc	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/zlib.rc	(revision 9)
@@ -0,0 +1,32 @@
+#include <windows.h>
+
+#define IDR_VERSION1  1
+IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
+  FILEVERSION	 1,2,3,0
+  PRODUCTVERSION 1,2,3,0
+  FILEFLAGSMASK	VS_FFI_FILEFLAGSMASK
+  FILEFLAGS	0
+  FILEOS	VOS_DOS_WINDOWS32
+  FILETYPE	VFT_DLL
+  FILESUBTYPE	0	// not used
+BEGIN
+  BLOCK "StringFileInfo"
+  BEGIN
+    BLOCK "040904E4"
+    //language ID = U.S. English, char set = Windows, Multilingual
+
+    BEGIN
+      VALUE "FileDescription", "zlib data compression library\0"
+      VALUE "FileVersion",	"1.2.3.0\0"
+      VALUE "InternalName",	"zlib\0"
+      VALUE "OriginalFilename",	"zlib.dll\0"
+      VALUE "ProductName",	"ZLib.DLL\0"
+      VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
+      VALUE "LegalCopyright", "(C) 1995-2003 Jean-loup Gailly & Mark Adler\0"
+    END
+  END
+  BLOCK "VarFileInfo"
+  BEGIN
+    VALUE "Translation", 0x0409, 1252
+  END
+END
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/zlibstat.vcproj
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/zlibstat.vcproj	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/zlibstat.vcproj	(revision 9)
@@ -0,0 +1,870 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8,00"
+	Name="zlibstat"
+	ProjectGUID="{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+		<Platform
+			Name="Itanium"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="x86\ZlibStat$(ConfigurationName)"
+			IntermediateDirectory="x86\ZlibStat$(ConfigurationName)\Tmp"
+			ConfigurationType="4"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
+				ExceptionHandling="0"
+				RuntimeLibrary="1"
+				BufferSecurityCheck="false"
+				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="/MACHINE:X86 /NODEFAULTLIB"
+				OutputFile="$(OutDir)\zlibstat.lib"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="x64\ZlibStat$(ConfigurationName)"
+			IntermediateDirectory="x64\ZlibStat$(ConfigurationName)\Tmp"
+			ConfigurationType="4"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
+				ExceptionHandling="0"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="false"
+				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="/MACHINE:AMD64 /NODEFAULTLIB"
+				OutputFile="$(OutDir)\zlibstat.lib"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|Itanium"
+			OutputDirectory="ia64\ZlibStat$(ConfigurationName)"
+			IntermediateDirectory="ia64\ZlibStat$(ConfigurationName)\Tmp"
+			ConfigurationType="4"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="2"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
+				ExceptionHandling="0"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="false"
+				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="/MACHINE:IA64 /NODEFAULTLIB"
+				OutputFile="$(OutDir)\zlibstat.lib"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="x86\ZlibStat$(ConfigurationName)"
+			IntermediateDirectory="x86\ZlibStat$(ConfigurationName)\Tmp"
+			ConfigurationType="4"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ASMV;ASMINF"
+				StringPooling="true"
+				ExceptionHandling="0"
+				RuntimeLibrary="0"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="/MACHINE:X86 /NODEFAULTLIB"
+				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj "
+				OutputFile="$(OutDir)\zlibstat.lib"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="x64\ZlibStat$(ConfigurationName)"
+			IntermediateDirectory="x64\ZlibStat$(ConfigurationName)\Tmp"
+			ConfigurationType="4"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ASMV;ASMINF;WIN64"
+				StringPooling="true"
+				ExceptionHandling="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="/MACHINE:AMD64 /NODEFAULTLIB"
+				AdditionalDependencies="..\..\masmx64\gvmat64.obj ..\..\masmx64\inffasx64.obj "
+				OutputFile="$(OutDir)\zlibstat.lib"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Itanium"
+			OutputDirectory="ia64\ZlibStat$(ConfigurationName)"
+			IntermediateDirectory="ia64\ZlibStat$(ConfigurationName)\Tmp"
+			ConfigurationType="4"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="2"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
+				StringPooling="true"
+				ExceptionHandling="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="/MACHINE:IA64 /NODEFAULTLIB"
+				OutputFile="$(OutDir)\zlibstat.lib"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseWithoutAsm|Win32"
+			OutputDirectory="x86\ZlibStat$(ConfigurationName)"
+			IntermediateDirectory="x86\ZlibStat$(ConfigurationName)\Tmp"
+			ConfigurationType="4"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
+				StringPooling="true"
+				ExceptionHandling="0"
+				RuntimeLibrary="0"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="/MACHINE:X86 /NODEFAULTLIB"
+				OutputFile="$(OutDir)\zlibstat.lib"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseWithoutAsm|x64"
+			OutputDirectory="x64\ZlibStat$(ConfigurationName)"
+			IntermediateDirectory="x64\ZlibStat$(ConfigurationName)\Tmp"
+			ConfigurationType="4"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
+				StringPooling="true"
+				ExceptionHandling="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="/MACHINE:AMD64 /NODEFAULTLIB"
+				OutputFile="$(OutDir)\zlibstat.lib"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseWithoutAsm|Itanium"
+			OutputDirectory="ia64\ZlibStat$(ConfigurationName)"
+			IntermediateDirectory="ia64\ZlibStat$(ConfigurationName)\Tmp"
+			ConfigurationType="4"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="2"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
+				StringPooling="true"
+				ExceptionHandling="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalOptions="/MACHINE:IA64 /NODEFAULTLIB"
+				OutputFile="$(OutDir)\zlibstat.lib"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			>
+			<File
+				RelativePath="..\..\..\adler32.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\compress.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\crc32.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\deflate.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\masmx86\gvmat32c.c"
+				>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="ReleaseWithoutAsm|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="ReleaseWithoutAsm|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\..\gzio.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\infback.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\masmx64\inffas8664.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="ReleaseWithoutAsm|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="ReleaseWithoutAsm|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\..\inffast.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\inflate.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\inftrees.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\minizip\ioapi.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\trees.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\uncompr.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\minizip\unzip.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\minizip\zip.c"
+				>
+			</File>
+			<File
+				RelativePath=".\zlib.rc"
+				>
+			</File>
+			<File
+				RelativePath=".\zlibvc.def"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\zutil.c"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/zlibvc.def
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/zlibvc.def	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/zlibvc.def	(revision 9)
@@ -0,0 +1,92 @@
+
+VERSION		1.23
+
+HEAPSIZE	1048576,8192
+
+EXPORTS
+        adler32                                  @1
+        compress                                 @2
+        crc32                                    @3
+        deflate                                  @4
+        deflateCopy                              @5
+        deflateEnd                               @6
+        deflateInit2_                            @7
+        deflateInit_                             @8
+        deflateParams                            @9
+        deflateReset                             @10
+        deflateSetDictionary                     @11
+        gzclose                                  @12
+        gzdopen                                  @13
+        gzerror                                  @14
+        gzflush                                  @15
+        gzopen                                   @16
+        gzread                                   @17
+        gzwrite                                  @18
+        inflate                                  @19
+        inflateEnd                               @20
+        inflateInit2_                            @21
+        inflateInit_                             @22
+        inflateReset                             @23
+        inflateSetDictionary                     @24
+        inflateSync                              @25
+        uncompress                               @26
+        zlibVersion                              @27
+        gzprintf                                 @28
+        gzputc                                   @29
+        gzgetc                                   @30
+        gzseek                                   @31
+        gzrewind                                 @32
+        gztell                                   @33
+        gzeof                                    @34
+        gzsetparams                              @35
+        zError                                   @36
+        inflateSyncPoint                         @37
+        get_crc_table                            @38
+        compress2                                @39
+        gzputs                                   @40
+        gzgets                                   @41
+        inflateCopy                              @42
+        inflateBackInit_                         @43
+        inflateBack                              @44
+        inflateBackEnd                           @45
+        compressBound                            @46
+        deflateBound                             @47
+        gzclearerr                               @48
+        gzungetc                                 @49
+        zlibCompileFlags                         @50
+        deflatePrime                             @51
+
+        unzOpen                                  @61
+        unzClose                                 @62
+        unzGetGlobalInfo                         @63
+        unzGetCurrentFileInfo                    @64
+        unzGoToFirstFile                         @65
+        unzGoToNextFile                          @66
+        unzOpenCurrentFile                       @67
+        unzReadCurrentFile                       @68
+        unzOpenCurrentFile3                      @69
+        unztell                                  @70
+        unzeof                                   @71
+        unzCloseCurrentFile                      @72
+        unzGetGlobalComment                      @73
+        unzStringFileNameCompare                 @74
+        unzLocateFile                            @75
+        unzGetLocalExtrafield                    @76
+        unzOpen2                                 @77
+        unzOpenCurrentFile2                      @78
+        unzOpenCurrentFilePassword               @79
+
+        zipOpen                                  @80
+        zipOpenNewFileInZip                      @81
+        zipWriteInFileInZip                      @82
+        zipCloseFileInZip                        @83
+        zipClose                                 @84
+        zipOpenNewFileInZip2                     @86
+        zipCloseFileInZipRaw                     @87
+        zipOpen2                                 @88
+        zipOpenNewFileInZip3                     @89
+
+        unzGetFilePos                            @100
+        unzGoToFilePos                           @101
+
+        fill_win32_filefunc                      @110
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/zlibvc.sln
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/zlibvc.sln	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/zlibvc.sln	(revision 9)
@@ -0,0 +1,144 @@
+﻿
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestZlibDll", "testzlibdll.vcproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}"
+	ProjectSection(ProjectDependencies) = postProject
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}"
+	ProjectSection(ProjectDependencies) = postProject
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}"
+	ProjectSection(ProjectDependencies) = postProject
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Itanium = Debug|Itanium
+		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
+		Release|Itanium = Release|Itanium
+		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
+		ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium
+		ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32
+		ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Itanium
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.Build.0 = Debug|Itanium
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Itanium
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.Build.0 = Release|Itanium
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = ReleaseWithoutAsm|x64
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = ReleaseWithoutAsm|x64
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64
+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Itanium
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.Build.0 = Debug|Itanium
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Itanium
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.Build.0 = Release|Itanium
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64
+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64
+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Itanium
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.Build.0 = Debug|Itanium
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Itanium
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.Build.0 = Release|Itanium
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Itanium
+		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|Itanium
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Itanium
+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|Itanium
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Itanium
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.Build.0 = Debug|Itanium
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Itanium
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.Build.0 = Release|Itanium
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Itanium
+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|Itanium
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
Index: /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/zlibvc.vcproj
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/zlibvc.vcproj	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/contrib/vstudio/vc8/zlibvc.vcproj	(revision 9)
@@ -0,0 +1,1219 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8,00"
+	Name="zlibvc"
+	ProjectGUID="{8FD826F8-3739-44E6-8CC8-997122E53B8D}"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+		<Platform
+			Name="Itanium"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="x86\ZlibDll$(ConfigurationName)"
+			IntermediateDirectory="x86\ZlibDll$(ConfigurationName)\Tmp"
+			ConfigurationType="2"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName="$(OutDir)/zlibvc.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32,_CRT_SECURE_NO_DEPRECATE,ZLIB_WINAPI,ASMV,ASMINF"
+				ExceptionHandling="0"
+				RuntimeLibrary="1"
+				BufferSecurityCheck="false"
+				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				BrowseInformation="0"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/MACHINE:I386"
+				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj"
+				OutputFile="$(OutDir)\zlibwapi.dll"
+				LinkIncremental="2"
+				SuppressStartupBanner="true"
+				GenerateManifest="false"
+				ModuleDefinitionFile=".\zlibvc.def"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
+				GenerateMapFile="true"
+				MapFileName="$(OutDir)/zlibwapi.map"
+				SubSystem="2"
+				ImportLibrary="$(OutDir)/zlibwapi.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="x64\ZlibDll$(ConfigurationName)"
+			IntermediateDirectory="x64\ZlibDll$(ConfigurationName)\Tmp"
+			ConfigurationType="2"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="3"
+				TypeLibraryName="$(OutDir)/zlibvc.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32,_CRT_SECURE_NO_DEPRECATE,ZLIB_WINAPI,ASMV,ASMINF;WIN64"
+				ExceptionHandling="0"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="false"
+				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				BrowseInformation="0"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="..\..\masmx64\gvmat64.obj ..\..\masmx64\inffasx64.obj "
+				OutputFile="$(OutDir)\zlibwapi.dll"
+				LinkIncremental="2"
+				SuppressStartupBanner="true"
+				GenerateManifest="false"
+				ModuleDefinitionFile=".\zlibvc.def"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
+				GenerateMapFile="true"
+				MapFileName="$(OutDir)/zlibwapi.map"
+				SubSystem="2"
+				ImportLibrary="$(OutDir)/zlibwapi.lib"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|Itanium"
+			OutputDirectory="ia64\ZlibDll$(ConfigurationName)"
+			IntermediateDirectory="ia64\ZlibDll$(ConfigurationName)\Tmp"
+			ConfigurationType="2"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="2"
+				TypeLibraryName="$(OutDir)/zlibvc.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;WIN64"
+				ExceptionHandling="0"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="false"
+				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				BrowseInformation="0"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\zlibwapi.dll"
+				LinkIncremental="2"
+				SuppressStartupBanner="true"
+				GenerateManifest="false"
+				ModuleDefinitionFile=".\zlibvc.def"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
+				GenerateMapFile="true"
+				MapFileName="$(OutDir)/zlibwapi.map"
+				SubSystem="2"
+				ImportLibrary="$(OutDir)/zlibwapi.lib"
+				TargetMachine="5"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseWithoutAsm|Win32"
+			OutputDirectory="x86\ZlibDll$(ConfigurationName)"
+			IntermediateDirectory="x86\ZlibDll$(ConfigurationName)\Tmp"
+			ConfigurationType="2"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName="$(OutDir)/zlibvc.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32,_CRT_SECURE_NO_DEPRECATE,ZLIB_WINAPI"
+				StringPooling="true"
+				ExceptionHandling="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
+				AssemblerOutput="2"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				BrowseInformation="0"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/MACHINE:I386"
+				OutputFile="$(OutDir)\zlibwapi.dll"
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				GenerateManifest="false"
+				IgnoreAllDefaultLibraries="false"
+				ModuleDefinitionFile=".\zlibvc.def"
+				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
+				GenerateMapFile="true"
+				MapFileName="$(OutDir)/zlibwapi.map"
+				SubSystem="2"
+				OptimizeForWindows98="1"
+				ImportLibrary="$(OutDir)/zlibwapi.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseWithoutAsm|x64"
+			OutputDirectory="x64\ZlibDll$(ConfigurationName)"
+			IntermediateDirectory="x64\ZlibDll$(ConfigurationName)\Tmp"
+			ConfigurationType="2"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="3"
+				TypeLibraryName="$(OutDir)/zlibvc.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32,_CRT_SECURE_NO_DEPRECATE,ZLIB_WINAPI;WIN64"
+				StringPooling="true"
+				ExceptionHandling="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
+				AssemblerOutput="2"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				BrowseInformation="0"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\zlibwapi.dll"
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				GenerateManifest="false"
+				IgnoreAllDefaultLibraries="false"
+				ModuleDefinitionFile=".\zlibvc.def"
+				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
+				GenerateMapFile="true"
+				MapFileName="$(OutDir)/zlibwapi.map"
+				SubSystem="2"
+				OptimizeForWindows98="1"
+				ImportLibrary="$(OutDir)/zlibwapi.lib"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseWithoutAsm|Itanium"
+			OutputDirectory="ia64\ZlibDll$(ConfigurationName)"
+			IntermediateDirectory="ia64\ZlibDll$(ConfigurationName)\Tmp"
+			ConfigurationType="2"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="2"
+				TypeLibraryName="$(OutDir)/zlibvc.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32,_CRT_SECURE_NO_DEPRECATE,ZLIB_WINAPI;WIN64"
+				StringPooling="true"
+				ExceptionHandling="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
+				AssemblerOutput="2"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				BrowseInformation="0"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\zlibwapi.dll"
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				GenerateManifest="false"
+				IgnoreAllDefaultLibraries="false"
+				ModuleDefinitionFile=".\zlibvc.def"
+				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
+				GenerateMapFile="true"
+				MapFileName="$(OutDir)/zlibwapi.map"
+				SubSystem="2"
+				OptimizeForWindows98="1"
+				ImportLibrary="$(OutDir)/zlibwapi.lib"
+				TargetMachine="5"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="x86\ZlibDll$(ConfigurationName)"
+			IntermediateDirectory="x86\ZlibDll$(ConfigurationName)\Tmp"
+			ConfigurationType="2"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName="$(OutDir)/zlibvc.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;ASMV;ASMINF"
+				StringPooling="true"
+				ExceptionHandling="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
+				AssemblerOutput="2"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				BrowseInformation="0"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/MACHINE:I386"
+				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj "
+				OutputFile="$(OutDir)\zlibwapi.dll"
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				GenerateManifest="false"
+				IgnoreAllDefaultLibraries="false"
+				ModuleDefinitionFile=".\zlibvc.def"
+				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
+				GenerateMapFile="true"
+				MapFileName="$(OutDir)/zlibwapi.map"
+				SubSystem="2"
+				OptimizeForWindows98="1"
+				ImportLibrary="$(OutDir)/zlibwapi.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="x64\ZlibDll$(ConfigurationName)"
+			IntermediateDirectory="x64\ZlibDll$(ConfigurationName)\Tmp"
+			ConfigurationType="2"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="3"
+				TypeLibraryName="$(OutDir)/zlibvc.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;ASMV;ASMINF;WIN64"
+				StringPooling="true"
+				ExceptionHandling="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
+				AssemblerOutput="2"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				BrowseInformation="0"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="..\..\masmx64\gvmat64.obj ..\..\masmx64\inffasx64.obj "
+				OutputFile="$(OutDir)\zlibwapi.dll"
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				GenerateManifest="false"
+				IgnoreAllDefaultLibraries="false"
+				ModuleDefinitionFile=".\zlibvc.def"
+				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
+				GenerateMapFile="true"
+				MapFileName="$(OutDir)/zlibwapi.map"
+				SubSystem="2"
+				OptimizeForWindows98="1"
+				ImportLibrary="$(OutDir)/zlibwapi.lib"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Itanium"
+			OutputDirectory="ia64\ZlibDll$(ConfigurationName)"
+			IntermediateDirectory="ia64\ZlibDll$(ConfigurationName)\Tmp"
+			ConfigurationType="2"
+			InheritedPropertySheets="UpgradeFromVC70.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="2"
+				TypeLibraryName="$(OutDir)/zlibvc.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;WIN64"
+				StringPooling="true"
+				ExceptionHandling="0"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
+				AssemblerOutput="2"
+				AssemblerListingLocation="$(IntDir)\"
+				ObjectFile="$(IntDir)\"
+				ProgramDataBaseFileName="$(OutDir)\"
+				BrowseInformation="0"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1036"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\zlibwapi.dll"
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				GenerateManifest="false"
+				IgnoreAllDefaultLibraries="false"
+				ModuleDefinitionFile=".\zlibvc.def"
+				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
+				GenerateMapFile="true"
+				MapFileName="$(OutDir)/zlibwapi.map"
+				SubSystem="2"
+				OptimizeForWindows98="1"
+				ImportLibrary="$(OutDir)/zlibwapi.lib"
+				TargetMachine="5"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
+			>
+			<File
+				RelativePath="..\..\..\adler32.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\compress.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\crc32.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\deflate.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\masmx86\gvmat32c.c"
+				>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="ReleaseWithoutAsm|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="ReleaseWithoutAsm|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="ReleaseWithoutAsm|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\..\gzio.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\infback.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\masmx64\inffas8664.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="ReleaseWithoutAsm|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="ReleaseWithoutAsm|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Itanium"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\..\inffast.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\inflate.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\inftrees.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\minizip\ioapi.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\minizip\iowin32.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\trees.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\uncompr.c"
+				>
+			</File>
+			<File
+				RelativePath="..\..\minizip\unzip.c"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions="ZLIB_INTERNAL"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions="ZLIB_INTERNAL"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Itanium"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions="ZLIB_INTERNAL"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\minizip\zip.c"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions="ZLIB_INTERNAL"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions="ZLIB_INTERNAL"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Itanium"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions="ZLIB_INTERNAL"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\zlib.rc"
+				>
+			</File>
+			<File
+				RelativePath=".\zlibvc.def"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\zutil.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;fi;fd"
+			>
+			<File
+				RelativePath="..\..\..\deflate.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\infblock.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\infcodes.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\inffast.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\inftrees.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\infutil.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\zconf.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\zlib.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\zutil.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /trunk/minix/lib/zlib-1.2.3/crc32.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/crc32.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/crc32.c	(revision 9)
@@ -0,0 +1,423 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
+ * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
+ * tables for updating the shift register in one step with three exclusive-ors
+ * instead of four steps with four exclusive-ors.  This results in about a
+ * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ */
+
+/* @(#) $Id: crc32.c,v 1.1 2005/09/23 22:39:00 beng Exp $ */
+
+/*
+  Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
+  protection on the static variables used to control the first-use generation
+  of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+  first call get_crc_table() to initialize the tables before allowing more than
+  one thread to use crc32().
+ */
+
+#ifdef MAKECRCH
+#  include <stdio.h>
+#  ifndef DYNAMIC_CRC_TABLE
+#    define DYNAMIC_CRC_TABLE
+#  endif /* !DYNAMIC_CRC_TABLE */
+#endif /* MAKECRCH */
+
+#include "zutil.h"      /* for STDC and FAR definitions */
+
+#define local static
+
+/* Find a four-byte integer type for crc32_little() and crc32_big(). */
+#ifndef NOBYFOUR
+#  ifdef STDC           /* need ANSI C limits.h to determine sizes */
+#    include <limits.h>
+#    define BYFOUR
+#    if (UINT_MAX == 0xffffffffUL)
+       typedef unsigned int u4;
+#    else
+#      if (ULONG_MAX == 0xffffffffUL)
+         typedef unsigned long u4;
+#      else
+#        if (USHRT_MAX == 0xffffffffUL)
+           typedef unsigned short u4;
+#        else
+#          undef BYFOUR     /* can't find a four-byte integer type! */
+#        endif
+#      endif
+#    endif
+#  endif /* STDC */
+#endif /* !NOBYFOUR */
+
+/* Definitions for doing the crc four data bytes at a time. */
+#ifdef BYFOUR
+#  define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
+                (((w)&0xff00)<<8)+(((w)&0xff)<<24))
+   local unsigned long crc32_little OF((unsigned long,
+                        const unsigned char FAR *, unsigned));
+   local unsigned long crc32_big OF((unsigned long,
+                        const unsigned char FAR *, unsigned));
+#  define TBLS 8
+#else
+#  define TBLS 1
+#endif /* BYFOUR */
+
+/* Local functions for crc concatenation */
+local unsigned long gf2_matrix_times OF((unsigned long *mat,
+                                         unsigned long vec));
+local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local volatile int crc_table_empty = 1;
+local unsigned long FAR crc_table[TBLS][256];
+local void make_crc_table OF((void));
+#ifdef MAKECRCH
+   local void write_table OF((FILE *, const unsigned long FAR *));
+#endif /* MAKECRCH */
+/*
+  Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
+  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+  Polynomials over GF(2) are represented in binary, one bit per coefficient,
+  with the lowest powers in the most significant bit.  Then adding polynomials
+  is just exclusive-or, and multiplying a polynomial by x is a right shift by
+  one.  If we call the above polynomial p, and represent a byte as the
+  polynomial q, also with the lowest power in the most significant bit (so the
+  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+  where a mod b means the remainder after dividing a by b.
+
+  This calculation is done using the shift-register method of multiplying and
+  taking the remainder.  The register is initialized to zero, and for each
+  incoming bit, x^32 is added mod p to the register if the bit is a one (where
+  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+  x (which is shifting right by one and adding x^32 mod p if the bit shifted
+  out is a one).  We start with the highest power (least significant bit) of
+  q and repeat for all eight bits of q.
+
+  The first table is simply the CRC of all possible eight bit values.  This is
+  all the information needed to generate CRCs on data a byte at a time for all
+  combinations of CRC register values and incoming bytes.  The remaining tables
+  allow for word-at-a-time CRC calculation for both big-endian and little-
+  endian machines, where a word is four bytes.
+*/
+local void make_crc_table()
+{
+    unsigned long c;
+    int n, k;
+    unsigned long poly;                 /* polynomial exclusive-or pattern */
+    /* terms of polynomial defining this crc (except x^32): */
+    static volatile int first = 1;      /* flag to limit concurrent making */
+    static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+    /* See if another task is already doing this (not thread-safe, but better
+       than nothing -- significantly reduces duration of vulnerability in
+       case the advice about DYNAMIC_CRC_TABLE is ignored) */
+    if (first) {
+        first = 0;
+
+        /* make exclusive-or pattern from polynomial (0xedb88320UL) */
+        poly = 0UL;
+        for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
+            poly |= 1UL << (31 - p[n]);
+
+        /* generate a crc for every 8-bit value */
+        for (n = 0; n < 256; n++) {
+            c = (unsigned long)n;
+            for (k = 0; k < 8; k++)
+                c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+            crc_table[0][n] = c;
+        }
+
+#ifdef BYFOUR
+        /* generate crc for each value followed by one, two, and three zeros,
+           and then the byte reversal of those as well as the first table */
+        for (n = 0; n < 256; n++) {
+            c = crc_table[0][n];
+            crc_table[4][n] = REV(c);
+            for (k = 1; k < 4; k++) {
+                c = crc_table[0][c & 0xff] ^ (c >> 8);
+                crc_table[k][n] = c;
+                crc_table[k + 4][n] = REV(c);
+            }
+        }
+#endif /* BYFOUR */
+
+        crc_table_empty = 0;
+    }
+    else {      /* not first */
+        /* wait for the other guy to finish (not efficient, but rare) */
+        while (crc_table_empty)
+            ;
+    }
+
+#ifdef MAKECRCH
+    /* write out CRC tables to crc32.h */
+    {
+        FILE *out;
+
+        out = fopen("crc32.h", "w");
+        if (out == NULL) return;
+        fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
+        fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
+        fprintf(out, "local const unsigned long FAR ");
+        fprintf(out, "crc_table[TBLS][256] =\n{\n  {\n");
+        write_table(out, crc_table[0]);
+#  ifdef BYFOUR
+        fprintf(out, "#ifdef BYFOUR\n");
+        for (k = 1; k < 8; k++) {
+            fprintf(out, "  },\n  {\n");
+            write_table(out, crc_table[k]);
+        }
+        fprintf(out, "#endif\n");
+#  endif /* BYFOUR */
+        fprintf(out, "  }\n};\n");
+        fclose(out);
+    }
+#endif /* MAKECRCH */
+}
+
+#ifdef MAKECRCH
+local void write_table(out, table)
+    FILE *out;
+    const unsigned long FAR *table;
+{
+    int n;
+
+    for (n = 0; n < 256; n++)
+        fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ", table[n],
+                n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
+}
+#endif /* MAKECRCH */
+
+#else /* !DYNAMIC_CRC_TABLE */
+/* ========================================================================
+ * Tables of CRC-32s of all single-byte values, made by make_crc_table().
+ */
+#include "crc32.h"
+#endif /* DYNAMIC_CRC_TABLE */
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const unsigned long FAR * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+        make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+    return (const unsigned long FAR *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
+#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    unsigned len;
+{
+    if (buf == Z_NULL) return 0UL;
+
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+        make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+
+#ifdef BYFOUR
+    if (sizeof(void *) == sizeof(ptrdiff_t)) {
+        u4 endian;
+
+        endian = 1;
+        if (*((unsigned char *)(&endian)))
+            return crc32_little(crc, buf, len);
+        else
+            return crc32_big(crc, buf, len);
+    }
+#endif /* BYFOUR */
+    crc = crc ^ 0xffffffffUL;
+    while (len >= 8) {
+        DO8;
+        len -= 8;
+    }
+    if (len) do {
+        DO1;
+    } while (--len);
+    return crc ^ 0xffffffffUL;
+}
+
+#ifdef BYFOUR
+
+/* ========================================================================= */
+#define DOLIT4 c ^= *buf4++; \
+        c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
+            crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
+#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
+
+/* ========================================================================= */
+local unsigned long crc32_little(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    unsigned len;
+{
+    register u4 c;
+    register const u4 FAR *buf4;
+
+    c = (u4)crc;
+    c = ~c;
+    while (len && ((ptrdiff_t)buf & 3)) {
+        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+        len--;
+    }
+
+    buf4 = (const u4 FAR *)(const void FAR *)buf;
+    while (len >= 32) {
+        DOLIT32;
+        len -= 32;
+    }
+    while (len >= 4) {
+        DOLIT4;
+        len -= 4;
+    }
+    buf = (const unsigned char FAR *)buf4;
+
+    if (len) do {
+        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+    } while (--len);
+    c = ~c;
+    return (unsigned long)c;
+}
+
+/* ========================================================================= */
+#define DOBIG4 c ^= *++buf4; \
+        c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
+            crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
+#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
+
+/* ========================================================================= */
+local unsigned long crc32_big(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    unsigned len;
+{
+    register u4 c;
+    register const u4 FAR *buf4;
+
+    c = REV((u4)crc);
+    c = ~c;
+    while (len && ((ptrdiff_t)buf & 3)) {
+        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+        len--;
+    }
+
+    buf4 = (const u4 FAR *)(const void FAR *)buf;
+    buf4--;
+    while (len >= 32) {
+        DOBIG32;
+        len -= 32;
+    }
+    while (len >= 4) {
+        DOBIG4;
+        len -= 4;
+    }
+    buf4++;
+    buf = (const unsigned char FAR *)buf4;
+
+    if (len) do {
+        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+    } while (--len);
+    c = ~c;
+    return (unsigned long)(REV(c));
+}
+
+#endif /* BYFOUR */
+
+#define GF2_DIM 32      /* dimension of GF(2) vectors (length of CRC) */
+
+/* ========================================================================= */
+local unsigned long gf2_matrix_times(mat, vec)
+    unsigned long *mat;
+    unsigned long vec;
+{
+    unsigned long sum;
+
+    sum = 0;
+    while (vec) {
+        if (vec & 1)
+            sum ^= *mat;
+        vec >>= 1;
+        mat++;
+    }
+    return sum;
+}
+
+/* ========================================================================= */
+local void gf2_matrix_square(square, mat)
+    unsigned long *square;
+    unsigned long *mat;
+{
+    int n;
+
+    for (n = 0; n < GF2_DIM; n++)
+        square[n] = gf2_matrix_times(mat, mat[n]);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(crc1, crc2, len2)
+    uLong crc1;
+    uLong crc2;
+    z_off_t len2;
+{
+    int n;
+    unsigned long row;
+    unsigned long even[GF2_DIM];    /* even-power-of-two zeros operator */
+    unsigned long odd[GF2_DIM];     /* odd-power-of-two zeros operator */
+
+    /* degenerate case */
+    if (len2 == 0)
+        return crc1;
+
+    /* put operator for one zero bit in odd */
+    odd[0] = 0xedb88320L;           /* CRC-32 polynomial */
+    row = 1;
+    for (n = 1; n < GF2_DIM; n++) {
+        odd[n] = row;
+        row <<= 1;
+    }
+
+    /* put operator for two zero bits in even */
+    gf2_matrix_square(even, odd);
+
+    /* put operator for four zero bits in odd */
+    gf2_matrix_square(odd, even);
+
+    /* apply len2 zeros to crc1 (first square will put the operator for one
+       zero byte, eight zero bits, in even) */
+    do {
+        /* apply zeros operator for this bit of len2 */
+        gf2_matrix_square(even, odd);
+        if (len2 & 1)
+            crc1 = gf2_matrix_times(even, crc1);
+        len2 >>= 1;
+
+        /* if no more bits set, then done */
+        if (len2 == 0)
+            break;
+
+        /* another iteration of the loop with odd and even swapped */
+        gf2_matrix_square(odd, even);
+        if (len2 & 1)
+            crc1 = gf2_matrix_times(odd, crc1);
+        len2 >>= 1;
+
+        /* if no more bits set, then done */
+    } while (len2 != 0);
+
+    /* return combined crc */
+    crc1 ^= crc2;
+    return crc1;
+}
Index: /trunk/minix/lib/zlib-1.2.3/crc32.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/crc32.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/crc32.h	(revision 9)
@@ -0,0 +1,441 @@
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+local const unsigned long FAR crc_table[TBLS][256] =
+{
+  {
+    0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+    0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+    0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+    0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+    0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+    0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+    0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+    0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+    0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+    0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+    0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+    0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+    0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+    0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+    0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+    0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+    0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+    0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+    0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+    0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+    0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+    0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+    0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+    0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+    0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+    0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+    0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+    0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+    0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+    0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+    0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+    0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+    0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+    0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+    0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+    0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+    0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+    0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+    0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+    0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+    0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+    0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+    0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+    0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+    0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+    0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+    0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+    0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+    0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+    0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+    0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+    0x2d02ef8dUL
+#ifdef BYFOUR
+  },
+  {
+    0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
+    0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
+    0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
+    0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
+    0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
+    0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
+    0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
+    0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
+    0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
+    0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
+    0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
+    0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
+    0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
+    0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
+    0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
+    0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
+    0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
+    0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
+    0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
+    0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
+    0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
+    0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
+    0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
+    0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
+    0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
+    0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
+    0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
+    0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
+    0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
+    0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
+    0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
+    0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
+    0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
+    0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
+    0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
+    0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
+    0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
+    0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
+    0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
+    0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
+    0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
+    0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
+    0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
+    0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
+    0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
+    0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
+    0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
+    0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
+    0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
+    0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
+    0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
+    0x9324fd72UL
+  },
+  {
+    0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
+    0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
+    0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
+    0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
+    0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
+    0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
+    0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
+    0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
+    0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
+    0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
+    0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
+    0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
+    0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
+    0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
+    0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
+    0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
+    0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
+    0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
+    0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
+    0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
+    0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
+    0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
+    0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
+    0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
+    0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
+    0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
+    0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
+    0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
+    0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
+    0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
+    0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
+    0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
+    0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
+    0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
+    0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
+    0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
+    0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
+    0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
+    0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
+    0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
+    0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
+    0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
+    0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
+    0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
+    0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
+    0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
+    0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
+    0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
+    0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
+    0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
+    0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
+    0xbe9834edUL
+  },
+  {
+    0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
+    0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
+    0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
+    0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
+    0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
+    0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
+    0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
+    0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
+    0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
+    0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
+    0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
+    0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
+    0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
+    0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
+    0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
+    0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
+    0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
+    0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
+    0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
+    0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
+    0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
+    0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
+    0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
+    0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
+    0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
+    0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
+    0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
+    0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
+    0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
+    0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
+    0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
+    0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
+    0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
+    0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
+    0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
+    0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
+    0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
+    0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
+    0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
+    0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
+    0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
+    0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
+    0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
+    0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
+    0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
+    0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
+    0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
+    0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
+    0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
+    0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
+    0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
+    0xde0506f1UL
+  },
+  {
+    0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
+    0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
+    0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
+    0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
+    0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
+    0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
+    0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
+    0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
+    0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
+    0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
+    0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
+    0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
+    0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
+    0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
+    0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
+    0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
+    0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
+    0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
+    0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
+    0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
+    0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
+    0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
+    0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
+    0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
+    0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
+    0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
+    0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
+    0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
+    0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
+    0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
+    0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
+    0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
+    0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
+    0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
+    0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
+    0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
+    0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
+    0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
+    0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
+    0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
+    0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
+    0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
+    0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
+    0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
+    0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
+    0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
+    0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
+    0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
+    0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
+    0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
+    0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
+    0x8def022dUL
+  },
+  {
+    0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
+    0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
+    0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
+    0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
+    0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
+    0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
+    0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
+    0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
+    0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
+    0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
+    0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
+    0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
+    0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
+    0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
+    0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
+    0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
+    0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
+    0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
+    0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
+    0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
+    0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
+    0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
+    0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
+    0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
+    0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
+    0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
+    0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
+    0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
+    0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
+    0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
+    0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
+    0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
+    0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
+    0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
+    0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
+    0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
+    0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
+    0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
+    0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
+    0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
+    0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
+    0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
+    0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
+    0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
+    0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
+    0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
+    0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
+    0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
+    0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
+    0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
+    0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
+    0x72fd2493UL
+  },
+  {
+    0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
+    0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
+    0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
+    0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
+    0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
+    0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
+    0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
+    0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
+    0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
+    0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
+    0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
+    0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
+    0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
+    0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
+    0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
+    0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
+    0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
+    0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
+    0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
+    0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
+    0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
+    0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
+    0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
+    0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
+    0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
+    0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
+    0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
+    0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
+    0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
+    0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
+    0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
+    0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
+    0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
+    0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
+    0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
+    0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
+    0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
+    0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
+    0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
+    0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
+    0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
+    0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
+    0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
+    0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
+    0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
+    0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
+    0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
+    0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
+    0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
+    0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
+    0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
+    0xed3498beUL
+  },
+  {
+    0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
+    0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
+    0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
+    0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
+    0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
+    0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
+    0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
+    0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
+    0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
+    0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
+    0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
+    0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
+    0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
+    0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
+    0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
+    0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
+    0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
+    0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
+    0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
+    0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
+    0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
+    0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
+    0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
+    0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
+    0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
+    0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
+    0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
+    0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
+    0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
+    0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
+    0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
+    0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
+    0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
+    0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
+    0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
+    0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
+    0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
+    0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
+    0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
+    0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
+    0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
+    0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
+    0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
+    0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
+    0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
+    0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
+    0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
+    0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
+    0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
+    0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
+    0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
+    0xf10605deUL
+#endif
+  }
+};
Index: /trunk/minix/lib/zlib-1.2.3/deflate.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/deflate.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/deflate.c	(revision 9)
@@ -0,0 +1,1736 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process depends on being able to identify portions
+ *      of the input text which are identical to earlier input (within a
+ *      sliding window trailing behind the input currently being processed).
+ *
+ *      The most straightforward technique turns out to be the fastest for
+ *      most input files: try all possible matches and select the longest.
+ *      The key feature of this algorithm is that insertions into the string
+ *      dictionary are very simple and thus fast, and deletions are avoided
+ *      completely. Insertions are performed at each input character, whereas
+ *      string matches are performed only when the previous match ends. So it
+ *      is preferable to spend more time in matches to allow very fast string
+ *      insertions and avoid deletions. The matching algorithm for small
+ *      strings is inspired from that of Rabin & Karp. A brute force approach
+ *      is used to find longer strings when a small match has been found.
+ *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ *      (by Leonid Broukhis).
+ *         A previous version of this file used a more sophisticated algorithm
+ *      (by Fiala and Greene) which is guaranteed to run in linear amortized
+ *      time, but has a larger average cost, uses more memory and is patented.
+ *      However the F&G algorithm may be faster for some highly redundant
+ *      files if the parameter max_chain_length (described below) is too large.
+ *
+ *  ACKNOWLEDGEMENTS
+ *
+ *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ *      I found it in 'freeze' written by Leonid Broukhis.
+ *      Thanks to many people for bug reports and testing.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ *      Available in http://www.ietf.org/rfc/rfc1951.txt
+ *
+ *      A description of the Rabin and Karp algorithm is given in the book
+ *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ *      Fiala,E.R., and Greene,D.H.
+ *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id: deflate.c,v 1.1 2005/09/23 22:39:00 beng Exp $ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+   " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ *  Function prototypes.
+ */
+typedef enum {
+    need_more,      /* block not completed, need more input or more output */
+    block_done,     /* block flush performed */
+    finish_started, /* finish started, need only more output at next deflate */
+    finish_done     /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window    OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast   OF((deflate_state *s, int flush));
+#ifndef FASTEST
+local block_state deflate_slow   OF((deflate_state *s, int flush));
+#endif
+local void lm_init        OF((deflate_state *s));
+local void putShortMSB    OF((deflate_state *s, uInt b));
+local void flush_pending  OF((z_streamp strm));
+local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifndef FASTEST
+#ifdef ASMV
+      void match_init OF((void)); /* asm code initialization */
+      uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#endif
+#endif
+local uInt longest_match_fast OF((deflate_state *s, IPos cur_match));
+
+#ifdef DEBUG
+local  void check_match OF((deflate_state *s, IPos start, IPos match,
+                            int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+#  define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+   ush good_length; /* reduce lazy search above this match length */
+   ush max_lazy;    /* do not perform lazy search above this match length */
+   ush nice_length; /* quit search above this match length */
+   ush max_chain;
+   compress_func func;
+} config;
+
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}}; /* max speed, no lazy matches */
+#else
+local const config configuration_table[10] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}, /* max speed, no lazy matches */
+/* 2 */ {4,    5, 16,    8, deflate_fast},
+/* 3 */ {4,    6, 32,   32, deflate_fast},
+
+/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */
+/* 5 */ {8,   16, 32,   32, deflate_slow},
+/* 6 */ {8,   16, 128, 128, deflate_slow},
+/* 7 */ {8,   32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
+#endif
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+#ifndef NO_DUMMY_DECL
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+#endif
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
+ *    input characters, so that a running hash key can be computed from the
+ *    previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN  assertion: all calls to to INSERT_STRING are made with consecutive
+ *    input characters and the first MIN_MATCH bytes of str are valid
+ *    (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    match_head = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+    s->head[s->hash_size-1] = NIL; \
+    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(strm, level, version, stream_size)
+    z_streamp strm;
+    int level;
+    const char *version;
+    int stream_size;
+{
+    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+                         Z_DEFAULT_STRATEGY, version, stream_size);
+    /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+                  version, stream_size)
+    z_streamp strm;
+    int  level;
+    int  method;
+    int  windowBits;
+    int  memLevel;
+    int  strategy;
+    const char *version;
+    int stream_size;
+{
+    deflate_state *s;
+    int wrap = 1;
+    static const char my_version[] = ZLIB_VERSION;
+
+    ushf *overlay;
+    /* We overlay pending_buf and d_buf+l_buf. This works since the average
+     * output size for (length,distance) codes is <= 24 bits.
+     */
+
+    if (version == Z_NULL || version[0] != my_version[0] ||
+        stream_size != sizeof(z_stream)) {
+        return Z_VERSION_ERROR;
+    }
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+    strm->msg = Z_NULL;
+    if (strm->zalloc == (alloc_func)0) {
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+
+#ifdef FASTEST
+    if (level != 0) level = 1;
+#else
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+
+    if (windowBits < 0) { /* suppress zlib wrapper */
+        wrap = 0;
+        windowBits = -windowBits;
+    }
+#ifdef GZIP
+    else if (windowBits > 15) {
+        wrap = 2;       /* write gzip wrapper instead */
+        windowBits -= 16;
+    }
+#endif
+    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+        windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+        strategy < 0 || strategy > Z_FIXED) {
+        return Z_STREAM_ERROR;
+    }
+    if (windowBits == 8) windowBits = 9;  /* until 256-byte window bug fixed */
+    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+    if (s == Z_NULL) return Z_MEM_ERROR;
+    strm->state = (struct internal_state FAR *)s;
+    s->strm = strm;
+
+    s->wrap = wrap;
+    s->gzhead = Z_NULL;
+    s->w_bits = windowBits;
+    s->w_size = 1 << s->w_bits;
+    s->w_mask = s->w_size - 1;
+
+    s->hash_bits = memLevel + 7;
+    s->hash_size = 1 << s->hash_bits;
+    s->hash_mask = s->hash_size - 1;
+    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
+    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+    s->pending_buf = (uchf *) overlay;
+    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+        s->pending_buf == Z_NULL) {
+        s->status = FINISH_STATE;
+        strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+        deflateEnd (strm);
+        return Z_MEM_ERROR;
+    }
+    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+    s->level = level;
+    s->strategy = strategy;
+    s->method = (Byte)method;
+
+    return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
+    z_streamp strm;
+    const Bytef *dictionary;
+    uInt  dictLength;
+{
+    deflate_state *s;
+    uInt length = dictLength;
+    uInt n;
+    IPos hash_head = 0;
+
+    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+        strm->state->wrap == 2 ||
+        (strm->state->wrap == 1 && strm->state->status != INIT_STATE))
+        return Z_STREAM_ERROR;
+
+    s = strm->state;
+    if (s->wrap)
+        strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+    if (length < MIN_MATCH) return Z_OK;
+    if (length > MAX_DIST(s)) {
+        length = MAX_DIST(s);
+        dictionary += dictLength - length; /* use the tail of the dictionary */
+    }
+    zmemcpy(s->window, dictionary, length);
+    s->strstart = length;
+    s->block_start = (long)length;
+
+    /* Insert all strings in the hash table (except for the last two bytes).
+     * s->lookahead stays null, so s->ins_h will be recomputed at the next
+     * call of fill_window.
+     */
+    s->ins_h = s->window[0];
+    UPDATE_HASH(s, s->ins_h, s->window[1]);
+    for (n = 0; n <= length - MIN_MATCH; n++) {
+        INSERT_STRING(s, n, hash_head);
+    }
+    if (hash_head) hash_head = 0;  /* to make compiler happy */
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (strm)
+    z_streamp strm;
+{
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) {
+        return Z_STREAM_ERROR;
+    }
+
+    strm->total_in = strm->total_out = 0;
+    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+    strm->data_type = Z_UNKNOWN;
+
+    s = (deflate_state *)strm->state;
+    s->pending = 0;
+    s->pending_out = s->pending_buf;
+
+    if (s->wrap < 0) {
+        s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
+    }
+    s->status = s->wrap ? INIT_STATE : BUSY_STATE;
+    strm->adler =
+#ifdef GZIP
+        s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
+#endif
+        adler32(0L, Z_NULL, 0);
+    s->last_flush = Z_NO_FLUSH;
+
+    _tr_init(s);
+    lm_init(s);
+
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetHeader (strm, head)
+    z_streamp strm;
+    gz_headerp head;
+{
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    if (strm->state->wrap != 2) return Z_STREAM_ERROR;
+    strm->state->gzhead = head;
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePrime (strm, bits, value)
+    z_streamp strm;
+    int bits;
+    int value;
+{
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    strm->state->bi_valid = bits;
+    strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(strm, level, strategy)
+    z_streamp strm;
+    int level;
+    int strategy;
+{
+    deflate_state *s;
+    compress_func func;
+    int err = Z_OK;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    s = strm->state;
+
+#ifdef FASTEST
+    if (level != 0) level = 1;
+#else
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
+        return Z_STREAM_ERROR;
+    }
+    func = configuration_table[s->level].func;
+
+    if (func != configuration_table[level].func && strm->total_in != 0) {
+        /* Flush the last buffer: */
+        err = deflate(strm, Z_PARTIAL_FLUSH);
+    }
+    if (s->level != level) {
+        s->level = level;
+        s->max_lazy_match   = configuration_table[level].max_lazy;
+        s->good_match       = configuration_table[level].good_length;
+        s->nice_match       = configuration_table[level].nice_length;
+        s->max_chain_length = configuration_table[level].max_chain;
+    }
+    s->strategy = strategy;
+    return err;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
+    z_streamp strm;
+    int good_length;
+    int max_lazy;
+    int nice_length;
+    int max_chain;
+{
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    s = strm->state;
+    s->good_match = good_length;
+    s->max_lazy_match = max_lazy;
+    s->nice_match = nice_length;
+    s->max_chain_length = max_chain;
+    return Z_OK;
+}
+
+/* =========================================================================
+ * For the default windowBits of 15 and memLevel of 8, this function returns
+ * a close to exact, as well as small, upper bound on the compressed size.
+ * They are coded as constants here for a reason--if the #define's are
+ * changed, then this function needs to be changed as well.  The return
+ * value for 15 and 8 only works for those exact settings.
+ *
+ * For any setting other than those defaults for windowBits and memLevel,
+ * the value returned is a conservative worst case for the maximum expansion
+ * resulting from using fixed blocks instead of stored blocks, which deflate
+ * can emit on compressed data for some combinations of the parameters.
+ *
+ * This function could be more sophisticated to provide closer upper bounds
+ * for every combination of windowBits and memLevel, as well as wrap.
+ * But even the conservative upper bound of about 14% expansion does not
+ * seem onerous for output buffer allocation.
+ */
+uLong ZEXPORT deflateBound(strm, sourceLen)
+    z_streamp strm;
+    uLong sourceLen;
+{
+    deflate_state *s;
+    uLong destLen;
+
+    /* conservative upper bound */
+    destLen = sourceLen +
+              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11;
+
+    /* if can't get parameters, return conservative bound */
+    if (strm == Z_NULL || strm->state == Z_NULL)
+        return destLen;
+
+    /* if not default parameters, return conservative bound */
+    s = strm->state;
+    if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+        return destLen;
+
+    /* default settings: return tight bound for that case */
+    return compressBound(sourceLen);
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (s, b)
+    deflate_state *s;
+    uInt b;
+{
+    put_byte(s, (Byte)(b >> 8));
+    put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(strm)
+    z_streamp strm;
+{
+    unsigned len = strm->state->pending;
+
+    if (len > strm->avail_out) len = strm->avail_out;
+    if (len == 0) return;
+
+    zmemcpy(strm->next_out, strm->state->pending_out, len);
+    strm->next_out  += len;
+    strm->state->pending_out  += len;
+    strm->total_out += len;
+    strm->avail_out  -= len;
+    strm->state->pending -= len;
+    if (strm->state->pending == 0) {
+        strm->state->pending_out = strm->state->pending_buf;
+    }
+}
+
+/* ========================================================================= */
+int ZEXPORT deflate (strm, flush)
+    z_streamp strm;
+    int flush;
+{
+    int old_flush; /* value of flush param for previous deflate call */
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+        flush > Z_FINISH || flush < 0) {
+        return Z_STREAM_ERROR;
+    }
+    s = strm->state;
+
+    if (strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+        (s->status == FINISH_STATE && flush != Z_FINISH)) {
+        ERR_RETURN(strm, Z_STREAM_ERROR);
+    }
+    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+    s->strm = strm; /* just in case */
+    old_flush = s->last_flush;
+    s->last_flush = flush;
+
+    /* Write the header */
+    if (s->status == INIT_STATE) {
+#ifdef GZIP
+        if (s->wrap == 2) {
+            strm->adler = crc32(0L, Z_NULL, 0);
+            put_byte(s, 31);
+            put_byte(s, 139);
+            put_byte(s, 8);
+            if (s->gzhead == NULL) {
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, s->level == 9 ? 2 :
+                            (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+                             4 : 0));
+                put_byte(s, OS_CODE);
+                s->status = BUSY_STATE;
+            }
+            else {
+                put_byte(s, (s->gzhead->text ? 1 : 0) +
+                            (s->gzhead->hcrc ? 2 : 0) +
+                            (s->gzhead->extra == Z_NULL ? 0 : 4) +
+                            (s->gzhead->name == Z_NULL ? 0 : 8) +
+                            (s->gzhead->comment == Z_NULL ? 0 : 16)
+                        );
+                put_byte(s, (Byte)(s->gzhead->time & 0xff));
+                put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+                put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+                put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
+                put_byte(s, s->level == 9 ? 2 :
+                            (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+                             4 : 0));
+                put_byte(s, s->gzhead->os & 0xff);
+                if (s->gzhead->extra != NULL) {
+                    put_byte(s, s->gzhead->extra_len & 0xff);
+                    put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+                }
+                if (s->gzhead->hcrc)
+                    strm->adler = crc32(strm->adler, s->pending_buf,
+                                        s->pending);
+                s->gzindex = 0;
+                s->status = EXTRA_STATE;
+            }
+        }
+        else
+#endif
+        {
+            uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+            uInt level_flags;
+
+            if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+                level_flags = 0;
+            else if (s->level < 6)
+                level_flags = 1;
+            else if (s->level == 6)
+                level_flags = 2;
+            else
+                level_flags = 3;
+            header |= (level_flags << 6);
+            if (s->strstart != 0) header |= PRESET_DICT;
+            header += 31 - (header % 31);
+
+            s->status = BUSY_STATE;
+            putShortMSB(s, header);
+
+            /* Save the adler32 of the preset dictionary: */
+            if (s->strstart != 0) {
+                putShortMSB(s, (uInt)(strm->adler >> 16));
+                putShortMSB(s, (uInt)(strm->adler & 0xffff));
+            }
+            strm->adler = adler32(0L, Z_NULL, 0);
+        }
+    }
+#ifdef GZIP
+    if (s->status == EXTRA_STATE) {
+        if (s->gzhead->extra != NULL) {
+            uInt beg = s->pending;  /* start of bytes to update crc */
+
+            while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
+                if (s->pending == s->pending_buf_size) {
+                    if (s->gzhead->hcrc && s->pending > beg)
+                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                            s->pending - beg);
+                    flush_pending(strm);
+                    beg = s->pending;
+                    if (s->pending == s->pending_buf_size)
+                        break;
+                }
+                put_byte(s, s->gzhead->extra[s->gzindex]);
+                s->gzindex++;
+            }
+            if (s->gzhead->hcrc && s->pending > beg)
+                strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                    s->pending - beg);
+            if (s->gzindex == s->gzhead->extra_len) {
+                s->gzindex = 0;
+                s->status = NAME_STATE;
+            }
+        }
+        else
+            s->status = NAME_STATE;
+    }
+    if (s->status == NAME_STATE) {
+        if (s->gzhead->name != NULL) {
+            uInt beg = s->pending;  /* start of bytes to update crc */
+            int val;
+
+            do {
+                if (s->pending == s->pending_buf_size) {
+                    if (s->gzhead->hcrc && s->pending > beg)
+                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                            s->pending - beg);
+                    flush_pending(strm);
+                    beg = s->pending;
+                    if (s->pending == s->pending_buf_size) {
+                        val = 1;
+                        break;
+                    }
+                }
+                val = s->gzhead->name[s->gzindex++];
+                put_byte(s, val);
+            } while (val != 0);
+            if (s->gzhead->hcrc && s->pending > beg)
+                strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                    s->pending - beg);
+            if (val == 0) {
+                s->gzindex = 0;
+                s->status = COMMENT_STATE;
+            }
+        }
+        else
+            s->status = COMMENT_STATE;
+    }
+    if (s->status == COMMENT_STATE) {
+        if (s->gzhead->comment != NULL) {
+            uInt beg = s->pending;  /* start of bytes to update crc */
+            int val;
+
+            do {
+                if (s->pending == s->pending_buf_size) {
+                    if (s->gzhead->hcrc && s->pending > beg)
+                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                            s->pending - beg);
+                    flush_pending(strm);
+                    beg = s->pending;
+                    if (s->pending == s->pending_buf_size) {
+                        val = 1;
+                        break;
+                    }
+                }
+                val = s->gzhead->comment[s->gzindex++];
+                put_byte(s, val);
+            } while (val != 0);
+            if (s->gzhead->hcrc && s->pending > beg)
+                strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                    s->pending - beg);
+            if (val == 0)
+                s->status = HCRC_STATE;
+        }
+        else
+            s->status = HCRC_STATE;
+    }
+    if (s->status == HCRC_STATE) {
+        if (s->gzhead->hcrc) {
+            if (s->pending + 2 > s->pending_buf_size)
+                flush_pending(strm);
+            if (s->pending + 2 <= s->pending_buf_size) {
+                put_byte(s, (Byte)(strm->adler & 0xff));
+                put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+                strm->adler = crc32(0L, Z_NULL, 0);
+                s->status = BUSY_STATE;
+            }
+        }
+        else
+            s->status = BUSY_STATE;
+    }
+#endif
+
+    /* Flush as much pending output as possible */
+    if (s->pending != 0) {
+        flush_pending(strm);
+        if (strm->avail_out == 0) {
+            /* Since avail_out is 0, deflate will be called again with
+             * more output space, but possibly with both pending and
+             * avail_in equal to zero. There won't be anything to do,
+             * but this is not an error situation so make sure we
+             * return OK instead of BUF_ERROR at next call of deflate:
+             */
+            s->last_flush = -1;
+            return Z_OK;
+        }
+
+    /* Make sure there is something to do and avoid duplicate consecutive
+     * flushes. For repeated and useless calls with Z_FINISH, we keep
+     * returning Z_STREAM_END instead of Z_BUF_ERROR.
+     */
+    } else if (strm->avail_in == 0 && flush <= old_flush &&
+               flush != Z_FINISH) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* User must not provide more input after the first FINISH: */
+    if (s->status == FINISH_STATE && strm->avail_in != 0) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* Start a new block or continue the current one.
+     */
+    if (strm->avail_in != 0 || s->lookahead != 0 ||
+        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+        block_state bstate;
+
+        bstate = (*(configuration_table[s->level].func))(s, flush);
+
+        if (bstate == finish_started || bstate == finish_done) {
+            s->status = FINISH_STATE;
+        }
+        if (bstate == need_more || bstate == finish_started) {
+            if (strm->avail_out == 0) {
+                s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+            }
+            return Z_OK;
+            /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+             * of deflate should use the same flush parameter to make sure
+             * that the flush is complete. So we don't have to output an
+             * empty block here, this will be done at next call. This also
+             * ensures that for a very small output buffer, we emit at most
+             * one empty block.
+             */
+        }
+        if (bstate == block_done) {
+            if (flush == Z_PARTIAL_FLUSH) {
+                _tr_align(s);
+            } else { /* FULL_FLUSH or SYNC_FLUSH */
+                _tr_stored_block(s, (char*)0, 0L, 0);
+                /* For a full flush, this empty block will be recognized
+                 * as a special marker by inflate_sync().
+                 */
+                if (flush == Z_FULL_FLUSH) {
+                    CLEAR_HASH(s);             /* forget history */
+                }
+            }
+            flush_pending(strm);
+            if (strm->avail_out == 0) {
+              s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+              return Z_OK;
+            }
+        }
+    }
+    Assert(strm->avail_out > 0, "bug2");
+
+    if (flush != Z_FINISH) return Z_OK;
+    if (s->wrap <= 0) return Z_STREAM_END;
+
+    /* Write the trailer */
+#ifdef GZIP
+    if (s->wrap == 2) {
+        put_byte(s, (Byte)(strm->adler & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
+        put_byte(s, (Byte)(strm->total_in & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
+    }
+    else
+#endif
+    {
+        putShortMSB(s, (uInt)(strm->adler >> 16));
+        putShortMSB(s, (uInt)(strm->adler & 0xffff));
+    }
+    flush_pending(strm);
+    /* If avail_out is zero, the application will call deflate again
+     * to flush the rest.
+     */
+    if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+    return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (strm)
+    z_streamp strm;
+{
+    int status;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+    status = strm->state->status;
+    if (status != INIT_STATE &&
+        status != EXTRA_STATE &&
+        status != NAME_STATE &&
+        status != COMMENT_STATE &&
+        status != HCRC_STATE &&
+        status != BUSY_STATE &&
+        status != FINISH_STATE) {
+      return Z_STREAM_ERROR;
+    }
+
+    /* Deallocate in reverse order of allocations: */
+    TRY_FREE(strm, strm->state->pending_buf);
+    TRY_FREE(strm, strm->state->head);
+    TRY_FREE(strm, strm->state->prev);
+    TRY_FREE(strm, strm->state->window);
+
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+
+    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (dest, source)
+    z_streamp dest;
+    z_streamp source;
+{
+#ifdef MAXSEG_64K
+    return Z_STREAM_ERROR;
+#else
+    deflate_state *ds;
+    deflate_state *ss;
+    ushf *overlay;
+
+
+    if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+        return Z_STREAM_ERROR;
+    }
+
+    ss = source->state;
+
+    zmemcpy(dest, source, sizeof(z_stream));
+
+    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+    if (ds == Z_NULL) return Z_MEM_ERROR;
+    dest->state = (struct internal_state FAR *) ds;
+    zmemcpy(ds, ss, sizeof(deflate_state));
+    ds->strm = dest;
+
+    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
+    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
+    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+    ds->pending_buf = (uchf *) overlay;
+
+    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+        ds->pending_buf == Z_NULL) {
+        deflateEnd (dest);
+        return Z_MEM_ERROR;
+    }
+    /* following zmemcpy do not work for 16-bit MSDOS */
+    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+    zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
+    zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+    ds->l_desc.dyn_tree = ds->dyn_ltree;
+    ds->d_desc.dyn_tree = ds->dyn_dtree;
+    ds->bl_desc.dyn_tree = ds->bl_tree;
+
+    return Z_OK;
+#endif /* MAXSEG_64K */
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read.  All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(strm, buf, size)
+    z_streamp strm;
+    Bytef *buf;
+    unsigned size;
+{
+    unsigned len = strm->avail_in;
+
+    if (len > size) len = size;
+    if (len == 0) return 0;
+
+    strm->avail_in  -= len;
+
+    if (strm->state->wrap == 1) {
+        strm->adler = adler32(strm->adler, strm->next_in, len);
+    }
+#ifdef GZIP
+    else if (strm->state->wrap == 2) {
+        strm->adler = crc32(strm->adler, strm->next_in, len);
+    }
+#endif
+    zmemcpy(buf, strm->next_in, len);
+    strm->next_in  += len;
+    strm->total_in += len;
+
+    return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (s)
+    deflate_state *s;
+{
+    s->window_size = (ulg)2L*s->w_size;
+
+    CLEAR_HASH(s);
+
+    /* Set the default configuration parameters:
+     */
+    s->max_lazy_match   = configuration_table[s->level].max_lazy;
+    s->good_match       = configuration_table[s->level].good_length;
+    s->nice_match       = configuration_table[s->level].nice_length;
+    s->max_chain_length = configuration_table[s->level].max_chain;
+
+    s->strstart = 0;
+    s->block_start = 0L;
+    s->lookahead = 0;
+    s->match_length = s->prev_length = MIN_MATCH-1;
+    s->match_available = 0;
+    s->ins_h = 0;
+#ifndef FASTEST
+#ifdef ASMV
+    match_init(); /* initialize the asm code */
+#endif
+#endif
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+local uInt longest_match(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    unsigned chain_length = s->max_chain_length;/* max hash chain length */
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    int best_len = s->prev_length;              /* best match length so far */
+    int nice_match = s->nice_match;             /* stop if match long enough */
+    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+        s->strstart - (IPos)MAX_DIST(s) : NIL;
+    /* Stop when cur_match becomes <= limit. To simplify the code,
+     * we prevent matches with the string of window index 0.
+     */
+    Posf *prev = s->prev;
+    uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+    /* Compare two bytes at a time. Note: this is not always beneficial.
+     * Try with and without -DUNALIGNED_OK to check.
+     */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+    register ush scan_start = *(ushf*)scan;
+    register ush scan_end   = *(ushf*)(scan+best_len-1);
+#else
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+    register Byte scan_end1  = scan[best_len-1];
+    register Byte scan_end   = scan[best_len];
+#endif
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    /* Do not waste too much time if we already have a good match: */
+    if (s->prev_length >= s->good_match) {
+        chain_length >>= 2;
+    }
+    /* Do not look for matches beyond the end of the input. This is necessary
+     * to make deflate deterministic.
+     */
+    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    do {
+        Assert(cur_match < s->strstart, "no future");
+        match = s->window + cur_match;
+
+        /* Skip to next match if the match length cannot increase
+         * or if the match length is less than 2.  Note that the checks below
+         * for insufficient lookahead only occur occasionally for performance
+         * reasons.  Therefore uninitialized memory will be accessed, and
+         * conditional jumps will be made that depend on those values.
+         * However the length of the match is limited to the lookahead, so
+         * the output of deflate is not affected by the uninitialized values.
+         */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+        /* This code assumes sizeof(unsigned short) == 2. Do not use
+         * UNALIGNED_OK if your compiler uses a different size.
+         */
+        if (*(ushf*)(match+best_len-1) != scan_end ||
+            *(ushf*)match != scan_start) continue;
+
+        /* It is not necessary to compare scan[2] and match[2] since they are
+         * always equal when the other bytes match, given that the hash keys
+         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+         * strstart+3, +5, ... up to strstart+257. We check for insufficient
+         * lookahead only every 4th comparison; the 128th check will be made
+         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+         * necessary to put more guard bytes at the end of the window, or
+         * to check more often for insufficient lookahead.
+         */
+        Assert(scan[2] == match[2], "scan[2]?");
+        scan++, match++;
+        do {
+        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 scan < strend);
+        /* The funny "do {}" generates better code on most compilers */
+
+        /* Here, scan <= window+strstart+257 */
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+        if (*scan == *match) scan++;
+
+        len = (MAX_MATCH - 1) - (int)(strend-scan);
+        scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+        if (match[best_len]   != scan_end  ||
+            match[best_len-1] != scan_end1 ||
+            *match            != *scan     ||
+            *++match          != scan[1])      continue;
+
+        /* The check at best_len-1 can be removed because it will be made
+         * again later. (This heuristic is not always a win.)
+         * It is not necessary to compare scan[2] and match[2] since they
+         * are always equal when the other bytes match, given that
+         * the hash keys are equal and that HASH_BITS >= 8.
+         */
+        scan += 2, match++;
+        Assert(*scan == *match, "match[2]?");
+
+        /* We check for insufficient lookahead only every 8th comparison;
+         * the 256th check will be made at strstart+258.
+         */
+        do {
+        } while (*++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 scan < strend);
+
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+        len = MAX_MATCH - (int)(strend - scan);
+        scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+        if (len > best_len) {
+            s->match_start = cur_match;
+            best_len = len;
+            if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+            scan_end = *(ushf*)(scan+best_len-1);
+#else
+            scan_end1  = scan[best_len-1];
+            scan_end   = scan[best_len];
+#endif
+        }
+    } while ((cur_match = prev[cur_match & wmask]) > limit
+             && --chain_length != 0);
+
+    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+    return s->lookahead;
+}
+#endif /* ASMV */
+#endif /* FASTEST */
+
+/* ---------------------------------------------------------------------------
+ * Optimized version for level == 1 or strategy == Z_RLE only
+ */
+local uInt longest_match_fast(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    Assert(cur_match < s->strstart, "no future");
+
+    match = s->window + cur_match;
+
+    /* Return failure if the match length is less than 2:
+     */
+    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+    /* The check at best_len-1 can be removed because it will be made
+     * again later. (This heuristic is not always a win.)
+     * It is not necessary to compare scan[2] and match[2] since they
+     * are always equal when the other bytes match, given that
+     * the hash keys are equal and that HASH_BITS >= 8.
+     */
+    scan += 2, match += 2;
+    Assert(*scan == *match, "match[2]?");
+
+    /* We check for insufficient lookahead only every 8th comparison;
+     * the 256th check will be made at strstart+258.
+     */
+    do {
+    } while (*++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             scan < strend);
+
+    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+    len = MAX_MATCH - (int)(strend - scan);
+
+    if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+    s->match_start = cur_match;
+    return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
+}
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+    deflate_state *s;
+    IPos start, match;
+    int length;
+{
+    /* check that the match is indeed a match */
+    if (zmemcmp(s->window + match,
+                s->window + start, length) != EQUAL) {
+        fprintf(stderr, " start %u, match %u, length %d\n",
+                start, match, length);
+        do {
+            fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+        } while (--length != 0);
+        z_error("invalid match");
+    }
+    if (z_verbose > 1) {
+        fprintf(stderr,"\\[%d,%d]", start-match, length);
+        do { putc(s->window[start++], stderr); } while (--length != 0);
+    }
+}
+#else
+#  define check_match(s, start, match, length)
+#endif /* DEBUG */
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ *    At least one byte has been read, or avail_in == 0; reads are
+ *    performed for at least two bytes (required for the zip translate_eol
+ *    option -- not supported here).
+ */
+local void fill_window(s)
+    deflate_state *s;
+{
+    register unsigned n, m;
+    register Posf *p;
+    unsigned more;    /* Amount of free space at the end of the window. */
+    uInt wsize = s->w_size;
+
+    do {
+        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+        /* Deal with !@#$% 64K limit: */
+        if (sizeof(int) <= 2) {
+            if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+                more = wsize;
+
+            } else if (more == (unsigned)(-1)) {
+                /* Very unlikely, but possible on 16 bit machine if
+                 * strstart == 0 && lookahead == 1 (input done a byte at time)
+                 */
+                more--;
+            }
+        }
+
+        /* If the window is almost full and there is insufficient lookahead,
+         * move the upper half to the lower one to make room in the upper half.
+         */
+        if (s->strstart >= wsize+MAX_DIST(s)) {
+
+            zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
+            s->match_start -= wsize;
+            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
+            s->block_start -= (long) wsize;
+
+            /* Slide the hash table (could be avoided with 32 bit values
+               at the expense of memory usage). We slide even when level == 0
+               to keep the hash table consistent if we switch back to level > 0
+               later. (Using level 0 permanently is not an optimal usage of
+               zlib, so we don't care about this pathological case.)
+             */
+            /* %%% avoid this when Z_RLE */
+            n = s->hash_size;
+            p = &s->head[n];
+            do {
+                m = *--p;
+                *p = (Pos)(m >= wsize ? m-wsize : NIL);
+            } while (--n);
+
+            n = wsize;
+#ifndef FASTEST
+            p = &s->prev[n];
+            do {
+                m = *--p;
+                *p = (Pos)(m >= wsize ? m-wsize : NIL);
+                /* If n is not on any hash chain, prev[n] is garbage but
+                 * its value will never be used.
+                 */
+            } while (--n);
+#endif
+            more += wsize;
+        }
+        if (s->strm->avail_in == 0) return;
+
+        /* If there was no sliding:
+         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+         *    more == window_size - lookahead - strstart
+         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+         * => more >= window_size - 2*WSIZE + 2
+         * In the BIG_MEM or MMAP case (not yet supported),
+         *   window_size == input_size + MIN_LOOKAHEAD  &&
+         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+         * Otherwise, window_size == 2*WSIZE so more >= 2.
+         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+         */
+        Assert(more >= 2, "more < 2");
+
+        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+        s->lookahead += n;
+
+        /* Initialize the hash value now that we have some input: */
+        if (s->lookahead >= MIN_MATCH) {
+            s->ins_h = s->window[s->strstart];
+            UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+            Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+        }
+        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+         * but this is not important since only literal bytes will be emitted.
+         */
+
+    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, eof) { \
+   _tr_flush_block(s, (s->block_start >= 0L ? \
+                   (charf *)&s->window[(unsigned)s->block_start] : \
+                   (charf *)Z_NULL), \
+                (ulg)((long)s->strstart - s->block_start), \
+                (eof)); \
+   s->block_start = s->strstart; \
+   flush_pending(s->strm); \
+   Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, eof) { \
+   FLUSH_BLOCK_ONLY(s, eof); \
+   if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+local block_state deflate_stored(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+     * to pending_buf_size, and each stored block has a 5 byte header:
+     */
+    ulg max_block_size = 0xffff;
+    ulg max_start;
+
+    if (max_block_size > s->pending_buf_size - 5) {
+        max_block_size = s->pending_buf_size - 5;
+    }
+
+    /* Copy as much as possible from input to output: */
+    for (;;) {
+        /* Fill the window as much as possible: */
+        if (s->lookahead <= 1) {
+
+            Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+                   s->block_start >= (long)s->w_size, "slide too late");
+
+            fill_window(s);
+            if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+        Assert(s->block_start >= 0L, "block gone");
+
+        s->strstart += s->lookahead;
+        s->lookahead = 0;
+
+        /* Emit a stored block if pending_buf will be full: */
+        max_start = s->block_start + max_block_size;
+        if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+            /* strstart == 0 is possible when wraparound on 16-bit machine */
+            s->lookahead = (uInt)(s->strstart - max_start);
+            s->strstart = (uInt)max_start;
+            FLUSH_BLOCK(s, 0);
+        }
+        /* Flush if we may have to slide, otherwise block_start may become
+         * negative and the data will be gone:
+         */
+        if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+            FLUSH_BLOCK(s, 0);
+        }
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head = NIL; /* head of the hash chain */
+    int bflush;           /* set if current block must be flushed */
+
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         * At this point we have always match_length < MIN_MATCH
+         */
+        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+#ifdef FASTEST
+            if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) ||
+                (s->strategy == Z_RLE && s->strstart - hash_head == 1)) {
+                s->match_length = longest_match_fast (s, hash_head);
+            }
+#else
+            if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
+                s->match_length = longest_match (s, hash_head);
+            } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+                s->match_length = longest_match_fast (s, hash_head);
+            }
+#endif
+            /* longest_match() or longest_match_fast() sets match_start */
+        }
+        if (s->match_length >= MIN_MATCH) {
+            check_match(s, s->strstart, s->match_start, s->match_length);
+
+            _tr_tally_dist(s, s->strstart - s->match_start,
+                           s->match_length - MIN_MATCH, bflush);
+
+            s->lookahead -= s->match_length;
+
+            /* Insert new strings in the hash table only if the match length
+             * is not too large. This saves time but degrades compression.
+             */
+#ifndef FASTEST
+            if (s->match_length <= s->max_insert_length &&
+                s->lookahead >= MIN_MATCH) {
+                s->match_length--; /* string at strstart already in table */
+                do {
+                    s->strstart++;
+                    INSERT_STRING(s, s->strstart, hash_head);
+                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+                     * always MIN_MATCH bytes ahead.
+                     */
+                } while (--s->match_length != 0);
+                s->strstart++;
+            } else
+#endif
+            {
+                s->strstart += s->match_length;
+                s->match_length = 0;
+                s->ins_h = s->window[s->strstart];
+                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+                Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+                 * matter since it will be recomputed at next deflate call.
+                 */
+            }
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c", s->window[s->strstart]));
+            _tr_tally_lit (s, s->window[s->strstart], bflush);
+            s->lookahead--;
+            s->strstart++;
+        }
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head = NIL;    /* head of hash chain */
+    int bflush;              /* set if current block must be flushed */
+
+    /* Process the input block. */
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         */
+        s->prev_length = s->match_length, s->prev_match = s->match_start;
+        s->match_length = MIN_MATCH-1;
+
+        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+            s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+            if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
+                s->match_length = longest_match (s, hash_head);
+            } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+                s->match_length = longest_match_fast (s, hash_head);
+            }
+            /* longest_match() or longest_match_fast() sets match_start */
+
+            if (s->match_length <= 5 && (s->strategy == Z_FILTERED
+#if TOO_FAR <= 32767
+                || (s->match_length == MIN_MATCH &&
+                    s->strstart - s->match_start > TOO_FAR)
+#endif
+                )) {
+
+                /* If prev_match is also MIN_MATCH, match_start is garbage
+                 * but we will ignore the current match anyway.
+                 */
+                s->match_length = MIN_MATCH-1;
+            }
+        }
+        /* If there was a match at the previous step and the current
+         * match is not better, output the previous match:
+         */
+        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+            /* Do not insert strings in hash table beyond this. */
+
+            check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+                           s->prev_length - MIN_MATCH, bflush);
+
+            /* Insert in hash table all strings up to the end of the match.
+             * strstart-1 and strstart are already inserted. If there is not
+             * enough lookahead, the last two strings are not inserted in
+             * the hash table.
+             */
+            s->lookahead -= s->prev_length-1;
+            s->prev_length -= 2;
+            do {
+                if (++s->strstart <= max_insert) {
+                    INSERT_STRING(s, s->strstart, hash_head);
+                }
+            } while (--s->prev_length != 0);
+            s->match_available = 0;
+            s->match_length = MIN_MATCH-1;
+            s->strstart++;
+
+            if (bflush) FLUSH_BLOCK(s, 0);
+
+        } else if (s->match_available) {
+            /* If there was no match at the previous position, output a
+             * single literal. If there was a match but the current match
+             * is longer, truncate the previous match to a single literal.
+             */
+            Tracevv((stderr,"%c", s->window[s->strstart-1]));
+            _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+            if (bflush) {
+                FLUSH_BLOCK_ONLY(s, 0);
+            }
+            s->strstart++;
+            s->lookahead--;
+            if (s->strm->avail_out == 0) return need_more;
+        } else {
+            /* There is no previous match to compare with, wait for
+             * the next step to decide.
+             */
+            s->match_available = 1;
+            s->strstart++;
+            s->lookahead--;
+        }
+    }
+    Assert (flush != Z_NO_FLUSH, "no flush?");
+    if (s->match_available) {
+        Tracevv((stderr,"%c", s->window[s->strstart-1]));
+        _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+        s->match_available = 0;
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif /* FASTEST */
+
+#if 0
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one.  Do not maintain a hash table.  (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    int bflush;         /* set if current block must be flushed */
+    uInt run;           /* length of run */
+    uInt max;           /* maximum length of run */
+    uInt prev;          /* byte at distance one to match */
+    Bytef *scan;        /* scan for end of run */
+
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the longest encodable run.
+         */
+        if (s->lookahead < MAX_MATCH) {
+            fill_window(s);
+            if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* See how many times the previous byte repeats */
+        run = 0;
+        if (s->strstart > 0) {      /* if there is a previous byte, that is */
+            max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH;
+            scan = s->window + s->strstart - 1;
+            prev = *scan++;
+            do {
+                if (*scan++ != prev)
+                    break;
+            } while (++run < max);
+        }
+
+        /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+        if (run >= MIN_MATCH) {
+            check_match(s, s->strstart, s->strstart - 1, run);
+            _tr_tally_dist(s, 1, run - MIN_MATCH, bflush);
+            s->lookahead -= run;
+            s->strstart += run;
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c", s->window[s->strstart]));
+            _tr_tally_lit (s, s->window[s->strstart], bflush);
+            s->lookahead--;
+            s->strstart++;
+        }
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif
Index: /trunk/minix/lib/zlib-1.2.3/deflate.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/deflate.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/deflate.h	(revision 9)
@@ -0,0 +1,331 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2004 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: deflate.h,v 1.1 2005/09/23 22:39:00 beng Exp $ */
+
+#ifndef DEFLATE_H
+#define DEFLATE_H
+
+#include "zutil.h"
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+   trailer creation by deflate().  NO_GZIP would be used to avoid linking in
+   the crc code when it is not needed.  For shared libraries, gzip encoding
+   should be left enabled. */
+#ifndef NO_GZIP
+#  define GZIP
+#endif
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS  256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES   30
+/* number of distance codes */
+
+#define BL_CODES  19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE    42
+#define EXTRA_STATE   69
+#define NAME_STATE    73
+#define COMMENT_STATE 91
+#define HCRC_STATE   103
+#define BUSY_STATE   113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+    union {
+        ush  freq;       /* frequency count */
+        ush  code;       /* bit string */
+    } fc;
+    union {
+        ush  dad;        /* father node in Huffman tree */
+        ush  len;        /* length of bit string */
+    } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad  dl.dad
+#define Len  dl.len
+
+typedef struct static_tree_desc_s  static_tree_desc;
+
+typedef struct tree_desc_s {
+    ct_data *dyn_tree;           /* the dynamic tree */
+    int     max_code;            /* largest code with non zero frequency */
+    static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+    z_streamp strm;      /* pointer back to this zlib stream */
+    int   status;        /* as the name implies */
+    Bytef *pending_buf;  /* output still pending */
+    ulg   pending_buf_size; /* size of pending_buf */
+    Bytef *pending_out;  /* next pending byte to output to the stream */
+    uInt   pending;      /* nb of bytes in the pending buffer */
+    int   wrap;          /* bit 0 true for zlib, bit 1 true for gzip */
+    gz_headerp  gzhead;  /* gzip header information to write */
+    uInt   gzindex;      /* where in extra, name, or comment */
+    Byte  method;        /* STORED (for zip only) or DEFLATED */
+    int   last_flush;    /* value of flush param for previous deflate call */
+
+                /* used by deflate.c: */
+
+    uInt  w_size;        /* LZ77 window size (32K by default) */
+    uInt  w_bits;        /* log2(w_size)  (8..16) */
+    uInt  w_mask;        /* w_size - 1 */
+
+    Bytef *window;
+    /* Sliding window. Input bytes are read into the second half of the window,
+     * and move to the first half later to keep a dictionary of at least wSize
+     * bytes. With this organization, matches are limited to a distance of
+     * wSize-MAX_MATCH bytes, but this ensures that IO is always
+     * performed with a length multiple of the block size. Also, it limits
+     * the window size to 64K, which is quite useful on MSDOS.
+     * To do: use the user input buffer as sliding window.
+     */
+
+    ulg window_size;
+    /* Actual size of window: 2*wSize, except when the user input buffer
+     * is directly used as sliding window.
+     */
+
+    Posf *prev;
+    /* Link to older string with same hash index. To limit the size of this
+     * array to 64K, this link is maintained only for the last 32K strings.
+     * An index in this array is thus a window index modulo 32K.
+     */
+
+    Posf *head; /* Heads of the hash chains or NIL. */
+
+    uInt  ins_h;          /* hash index of string to be inserted */
+    uInt  hash_size;      /* number of elements in hash table */
+    uInt  hash_bits;      /* log2(hash_size) */
+    uInt  hash_mask;      /* hash_size-1 */
+
+    uInt  hash_shift;
+    /* Number of bits by which ins_h must be shifted at each input
+     * step. It must be such that after MIN_MATCH steps, the oldest
+     * byte no longer takes part in the hash key, that is:
+     *   hash_shift * MIN_MATCH >= hash_bits
+     */
+
+    long block_start;
+    /* Window position at the beginning of the current output block. Gets
+     * negative when the window is moved backwards.
+     */
+
+    uInt match_length;           /* length of best match */
+    IPos prev_match;             /* previous match */
+    int match_available;         /* set if previous match exists */
+    uInt strstart;               /* start of string to insert */
+    uInt match_start;            /* start of matching string */
+    uInt lookahead;              /* number of valid bytes ahead in window */
+
+    uInt prev_length;
+    /* Length of the best match at previous step. Matches not greater than this
+     * are discarded. This is used in the lazy match evaluation.
+     */
+
+    uInt max_chain_length;
+    /* To speed up deflation, hash chains are never searched beyond this
+     * length.  A higher limit improves compression ratio but degrades the
+     * speed.
+     */
+
+    uInt max_lazy_match;
+    /* Attempt to find a better match only when the current match is strictly
+     * smaller than this value. This mechanism is used only for compression
+     * levels >= 4.
+     */
+#   define max_insert_length  max_lazy_match
+    /* Insert new strings in the hash table only if the match length is not
+     * greater than this length. This saves time but degrades compression.
+     * max_insert_length is used only for compression levels <= 3.
+     */
+
+    int level;    /* compression level (1..9) */
+    int strategy; /* favor or force Huffman coding*/
+
+    uInt good_match;
+    /* Use a faster search when the previous match is longer than this */
+
+    int nice_match; /* Stop searching when current match exceeds this */
+
+                /* used by trees.c: */
+    /* Didn't use ct_data typedef below to supress compiler warning */
+    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
+    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
+
+    struct tree_desc_s l_desc;               /* desc. for literal tree */
+    struct tree_desc_s d_desc;               /* desc. for distance tree */
+    struct tree_desc_s bl_desc;              /* desc. for bit length tree */
+
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
+    int heap_len;               /* number of elements in the heap */
+    int heap_max;               /* element of largest frequency */
+    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+     * The same heap array is used to build all trees.
+     */
+
+    uch depth[2*L_CODES+1];
+    /* Depth of each subtree used as tie breaker for trees of equal frequency
+     */
+
+    uchf *l_buf;          /* buffer for literals or lengths */
+
+    uInt  lit_bufsize;
+    /* Size of match buffer for literals/lengths.  There are 4 reasons for
+     * limiting lit_bufsize to 64K:
+     *   - frequencies can be kept in 16 bit counters
+     *   - if compression is not successful for the first block, all input
+     *     data is still in the window so we can still emit a stored block even
+     *     when input comes from standard input.  (This can also be done for
+     *     all blocks if lit_bufsize is not greater than 32K.)
+     *   - if compression is not successful for a file smaller than 64K, we can
+     *     even emit a stored file instead of a stored block (saving 5 bytes).
+     *     This is applicable only for zip (not gzip or zlib).
+     *   - creating new Huffman trees less frequently may not provide fast
+     *     adaptation to changes in the input data statistics. (Take for
+     *     example a binary file with poorly compressible code followed by
+     *     a highly compressible string table.) Smaller buffer sizes give
+     *     fast adaptation but have of course the overhead of transmitting
+     *     trees more frequently.
+     *   - I can't count above 4
+     */
+
+    uInt last_lit;      /* running index in l_buf */
+
+    ushf *d_buf;
+    /* Buffer for distances. To simplify the code, d_buf and l_buf have
+     * the same number of elements. To use different lengths, an extra flag
+     * array would be necessary.
+     */
+
+    ulg opt_len;        /* bit length of current block with optimal trees */
+    ulg static_len;     /* bit length of current block with static trees */
+    uInt matches;       /* number of string matches in current block */
+    int last_eob_len;   /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+    ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */
+#endif
+
+    ush bi_buf;
+    /* Output buffer. bits are inserted starting at the bottom (least
+     * significant bits).
+     */
+    int bi_valid;
+    /* Number of valid bits in bi_buf.  All bits above the last valid bit
+     * are always zero.
+     */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+        /* in trees.c */
+void _tr_init         OF((deflate_state *s));
+int  _tr_tally        OF((deflate_state *s, unsigned dist, unsigned lc));
+void _tr_flush_block  OF((deflate_state *s, charf *buf, ulg stored_len,
+                          int eof));
+void _tr_align        OF((deflate_state *s));
+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
+                          int eof));
+
+#define d_code(dist) \
+   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+  extern uch _length_code[];
+  extern uch _dist_code[];
+#else
+  extern const uch _length_code[];
+  extern const uch _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+  { uch cc = (c); \
+    s->d_buf[s->last_lit] = 0; \
+    s->l_buf[s->last_lit++] = cc; \
+    s->dyn_ltree[cc].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+   }
+# define _tr_tally_dist(s, distance, length, flush) \
+  { uch len = (length); \
+    ush dist = (distance); \
+    s->d_buf[s->last_lit] = dist; \
+    s->l_buf[s->last_lit++] = len; \
+    dist--; \
+    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+    s->dyn_dtree[d_code(dist)].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+  }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+              flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* DEFLATE_H */
Index: /trunk/minix/lib/zlib-1.2.3/example.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/example.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/example.c	(revision 9)
@@ -0,0 +1,565 @@
+/* example.c -- usage example of the zlib compression library
+ * Copyright (C) 1995-2004 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: example.c,v 1.1 2005/09/23 22:39:00 beng Exp $ */
+
+#include <stdio.h>
+#include "zlib.h"
+
+#ifdef STDC
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+
+#if defined(VMS) || defined(RISCOS)
+#  define TESTFILE "foo-gz"
+#else
+#  define TESTFILE "foo.gz"
+#endif
+
+#define CHECK_ERR(err, msg) { \
+    if (err != Z_OK) { \
+        fprintf(stderr, "%s error: %d\n", msg, err); \
+        exit(1); \
+    } \
+}
+
+const char hello[] = "hello, hello!";
+/* "hello world" would be more standard, but the repeated "hello"
+ * stresses the compression code better, sorry...
+ */
+
+const char dictionary[] = "hello";
+uLong dictId; /* Adler32 value of the dictionary */
+
+void test_compress      OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+void test_gzio          OF((const char *fname,
+                            Byte *uncompr, uLong uncomprLen));
+void test_deflate       OF((Byte *compr, uLong comprLen));
+void test_inflate       OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+void test_large_deflate OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+void test_large_inflate OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+void test_flush         OF((Byte *compr, uLong *comprLen));
+void test_sync          OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+void test_dict_deflate  OF((Byte *compr, uLong comprLen));
+void test_dict_inflate  OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+int  main               OF((int argc, char *argv[]));
+
+/* ===========================================================================
+ * Test compress() and uncompress()
+ */
+void test_compress(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    uLong len = (uLong)strlen(hello)+1;
+
+    err = compress(compr, &comprLen, (const Bytef*)hello, len);
+    CHECK_ERR(err, "compress");
+
+    strcpy((char*)uncompr, "garbage");
+
+    err = uncompress(uncompr, &uncomprLen, compr, comprLen);
+    CHECK_ERR(err, "uncompress");
+
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad uncompress\n");
+        exit(1);
+    } else {
+        printf("uncompress(): %s\n", (char *)uncompr);
+    }
+}
+
+/* ===========================================================================
+ * Test read/write of .gz files
+ */
+void test_gzio(fname, uncompr, uncomprLen)
+    const char *fname; /* compressed file name */
+    Byte *uncompr;
+    uLong uncomprLen;
+{
+#ifdef NO_GZCOMPRESS
+    fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
+#else
+    int err;
+    int len = (int)strlen(hello)+1;
+    gzFile file;
+    z_off_t pos;
+
+    file = gzopen(fname, "wb");
+    if (file == NULL) {
+        fprintf(stderr, "gzopen error\n");
+        exit(1);
+    }
+    gzputc(file, 'h');
+    if (gzputs(file, "ello") != 4) {
+        fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
+        exit(1);
+    }
+    if (gzprintf(file, ", %s!", "hello") != 8) {
+        fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
+        exit(1);
+    }
+    gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
+    gzclose(file);
+
+    file = gzopen(fname, "rb");
+    if (file == NULL) {
+        fprintf(stderr, "gzopen error\n");
+        exit(1);
+    }
+    strcpy((char*)uncompr, "garbage");
+
+    if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {
+        fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
+        exit(1);
+    }
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
+        exit(1);
+    } else {
+        printf("gzread(): %s\n", (char*)uncompr);
+    }
+
+    pos = gzseek(file, -8L, SEEK_CUR);
+    if (pos != 6 || gztell(file) != pos) {
+        fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
+                (long)pos, (long)gztell(file));
+        exit(1);
+    }
+
+    if (gzgetc(file) != ' ') {
+        fprintf(stderr, "gzgetc error\n");
+        exit(1);
+    }
+
+    if (gzungetc(' ', file) != ' ') {
+        fprintf(stderr, "gzungetc error\n");
+        exit(1);
+    }
+
+    gzgets(file, (char*)uncompr, (int)uncomprLen);
+    if (strlen((char*)uncompr) != 7) { /* " hello!" */
+        fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
+        exit(1);
+    }
+    if (strcmp((char*)uncompr, hello + 6)) {
+        fprintf(stderr, "bad gzgets after gzseek\n");
+        exit(1);
+    } else {
+        printf("gzgets() after gzseek: %s\n", (char*)uncompr);
+    }
+
+    gzclose(file);
+#endif
+}
+
+/* ===========================================================================
+ * Test deflate() with small buffers
+ */
+void test_deflate(compr, comprLen)
+    Byte *compr;
+    uLong comprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+    uLong len = (uLong)strlen(hello)+1;
+
+    c_stream.zalloc = (alloc_func)0;
+    c_stream.zfree = (free_func)0;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+    CHECK_ERR(err, "deflateInit");
+
+    c_stream.next_in  = (Bytef*)hello;
+    c_stream.next_out = compr;
+
+    while (c_stream.total_in != len && c_stream.total_out < comprLen) {
+        c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
+        err = deflate(&c_stream, Z_NO_FLUSH);
+        CHECK_ERR(err, "deflate");
+    }
+    /* Finish the stream, still forcing small buffers: */
+    for (;;) {
+        c_stream.avail_out = 1;
+        err = deflate(&c_stream, Z_FINISH);
+        if (err == Z_STREAM_END) break;
+        CHECK_ERR(err, "deflate");
+    }
+
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with small buffers
+ */
+void test_inflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = (alloc_func)0;
+    d_stream.zfree = (free_func)0;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = 0;
+    d_stream.next_out = uncompr;
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
+        d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
+        err = inflate(&d_stream, Z_NO_FLUSH);
+        if (err == Z_STREAM_END) break;
+        CHECK_ERR(err, "inflate");
+    }
+
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad inflate\n");
+        exit(1);
+    } else {
+        printf("inflate(): %s\n", (char *)uncompr);
+    }
+}
+
+/* ===========================================================================
+ * Test deflate() with large buffers and dynamic change of compression level
+ */
+void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+
+    c_stream.zalloc = (alloc_func)0;
+    c_stream.zfree = (free_func)0;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_BEST_SPEED);
+    CHECK_ERR(err, "deflateInit");
+
+    c_stream.next_out = compr;
+    c_stream.avail_out = (uInt)comprLen;
+
+    /* At this point, uncompr is still mostly zeroes, so it should compress
+     * very well:
+     */
+    c_stream.next_in = uncompr;
+    c_stream.avail_in = (uInt)uncomprLen;
+    err = deflate(&c_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "deflate");
+    if (c_stream.avail_in != 0) {
+        fprintf(stderr, "deflate not greedy\n");
+        exit(1);
+    }
+
+    /* Feed in already compressed data and switch to no compression: */
+    deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
+    c_stream.next_in = compr;
+    c_stream.avail_in = (uInt)comprLen/2;
+    err = deflate(&c_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "deflate");
+
+    /* Switch back to compressing mode: */
+    deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
+    c_stream.next_in = uncompr;
+    c_stream.avail_in = (uInt)uncomprLen;
+    err = deflate(&c_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "deflate");
+
+    err = deflate(&c_stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        fprintf(stderr, "deflate should report Z_STREAM_END\n");
+        exit(1);
+    }
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with large buffers
+ */
+void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = (alloc_func)0;
+    d_stream.zfree = (free_func)0;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = (uInt)comprLen;
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    for (;;) {
+        d_stream.next_out = uncompr;            /* discard the output */
+        d_stream.avail_out = (uInt)uncomprLen;
+        err = inflate(&d_stream, Z_NO_FLUSH);
+        if (err == Z_STREAM_END) break;
+        CHECK_ERR(err, "large inflate");
+    }
+
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
+        fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
+        exit(1);
+    } else {
+        printf("large_inflate(): OK\n");
+    }
+}
+
+/* ===========================================================================
+ * Test deflate() with full flush
+ */
+void test_flush(compr, comprLen)
+    Byte *compr;
+    uLong *comprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+    uInt len = (uInt)strlen(hello)+1;
+
+    c_stream.zalloc = (alloc_func)0;
+    c_stream.zfree = (free_func)0;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+    CHECK_ERR(err, "deflateInit");
+
+    c_stream.next_in  = (Bytef*)hello;
+    c_stream.next_out = compr;
+    c_stream.avail_in = 3;
+    c_stream.avail_out = (uInt)*comprLen;
+    err = deflate(&c_stream, Z_FULL_FLUSH);
+    CHECK_ERR(err, "deflate");
+
+    compr[3]++; /* force an error in first compressed block */
+    c_stream.avail_in = len - 3;
+
+    err = deflate(&c_stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        CHECK_ERR(err, "deflate");
+    }
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+
+    *comprLen = c_stream.total_out;
+}
+
+/* ===========================================================================
+ * Test inflateSync()
+ */
+void test_sync(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = (alloc_func)0;
+    d_stream.zfree = (free_func)0;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = 2; /* just read the zlib header */
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    d_stream.next_out = uncompr;
+    d_stream.avail_out = (uInt)uncomprLen;
+
+    inflate(&d_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "inflate");
+
+    d_stream.avail_in = (uInt)comprLen-2;   /* read all compressed data */
+    err = inflateSync(&d_stream);           /* but skip the damaged part */
+    CHECK_ERR(err, "inflateSync");
+
+    err = inflate(&d_stream, Z_FINISH);
+    if (err != Z_DATA_ERROR) {
+        fprintf(stderr, "inflate should report DATA_ERROR\n");
+        /* Because of incorrect adler32 */
+        exit(1);
+    }
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    printf("after inflateSync(): hel%s\n", (char *)uncompr);
+}
+
+/* ===========================================================================
+ * Test deflate() with preset dictionary
+ */
+void test_dict_deflate(compr, comprLen)
+    Byte *compr;
+    uLong comprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+
+    c_stream.zalloc = (alloc_func)0;
+    c_stream.zfree = (free_func)0;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
+    CHECK_ERR(err, "deflateInit");
+
+    err = deflateSetDictionary(&c_stream,
+                               (const Bytef*)dictionary, sizeof(dictionary));
+    CHECK_ERR(err, "deflateSetDictionary");
+
+    dictId = c_stream.adler;
+    c_stream.next_out = compr;
+    c_stream.avail_out = (uInt)comprLen;
+
+    c_stream.next_in = (Bytef*)hello;
+    c_stream.avail_in = (uInt)strlen(hello)+1;
+
+    err = deflate(&c_stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        fprintf(stderr, "deflate should report Z_STREAM_END\n");
+        exit(1);
+    }
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with a preset dictionary
+ */
+void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = (alloc_func)0;
+    d_stream.zfree = (free_func)0;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = (uInt)comprLen;
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    d_stream.next_out = uncompr;
+    d_stream.avail_out = (uInt)uncomprLen;
+
+    for (;;) {
+        err = inflate(&d_stream, Z_NO_FLUSH);
+        if (err == Z_STREAM_END) break;
+        if (err == Z_NEED_DICT) {
+            if (d_stream.adler != dictId) {
+                fprintf(stderr, "unexpected dictionary");
+                exit(1);
+            }
+            err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
+                                       sizeof(dictionary));
+        }
+        CHECK_ERR(err, "inflate with dict");
+    }
+
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad inflate with dict\n");
+        exit(1);
+    } else {
+        printf("inflate with dictionary: %s\n", (char *)uncompr);
+    }
+}
+
+/* ===========================================================================
+ * Usage:  example [output.gz  [input.gz]]
+ */
+
+int main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    Byte *compr, *uncompr;
+    uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
+    uLong uncomprLen = comprLen;
+    static const char* myVersion = ZLIB_VERSION;
+
+    if (zlibVersion()[0] != myVersion[0]) {
+        fprintf(stderr, "incompatible zlib version\n");
+        exit(1);
+
+    } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
+        fprintf(stderr, "warning: different zlib version\n");
+    }
+
+    printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
+            ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());
+
+    compr    = (Byte*)calloc((uInt)comprLen, 1);
+    uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);
+    /* compr and uncompr are cleared to avoid reading uninitialized
+     * data and to ensure that uncompr compresses well.
+     */
+    if (compr == Z_NULL || uncompr == Z_NULL) {
+        printf("out of memory\n");
+        exit(1);
+    }
+    test_compress(compr, comprLen, uncompr, uncomprLen);
+
+    test_gzio((argc > 1 ? argv[1] : TESTFILE),
+              uncompr, uncomprLen);
+
+    test_deflate(compr, comprLen);
+    test_inflate(compr, comprLen, uncompr, uncomprLen);
+
+    test_large_deflate(compr, comprLen, uncompr, uncomprLen);
+    test_large_inflate(compr, comprLen, uncompr, uncomprLen);
+
+    test_flush(compr, &comprLen);
+    test_sync(compr, comprLen, uncompr, uncomprLen);
+    comprLen = uncomprLen;
+
+    test_dict_deflate(compr, comprLen);
+    test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
+
+    free(compr);
+    free(uncompr);
+
+    return 0;
+}
Index: /trunk/minix/lib/zlib-1.2.3/examples/README.examples
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/examples/README.examples	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/examples/README.examples	(revision 9)
@@ -0,0 +1,42 @@
+This directory contains examples of the use of zlib.
+
+fitblk.c
+    compress just enough input to nearly fill a requested output size
+    - zlib isn't designed to do this, but fitblk does it anyway
+
+gun.c
+    uncompress a gzip file
+    - illustrates the use of inflateBack() for high speed file-to-file
+      decompression using call-back functions
+    - is approximately twice as fast as gzip -d
+    - also provides Unix uncompress functionality, again twice as fast
+
+gzappend.c
+    append to a gzip file
+    - illustrates the use of the Z_BLOCK flush parameter for inflate()
+    - illustrates the use of deflatePrime() to start at any bit
+
+gzjoin.c
+    join gzip files without recalculating the crc or recompressing
+    - illustrates the use of the Z_BLOCK flush parameter for inflate()
+    - illustrates the use of crc32_combine()
+
+gzlog.c
+gzlog.h
+    efficiently maintain a message log file in gzip format
+    - illustrates use of raw deflate and Z_SYNC_FLUSH
+    - illustrates use of gzip header extra field
+
+zlib_how.html
+    painfully comprehensive description of zpipe.c (see below)
+    - describes in excruciating detail the use of deflate() and inflate()
+
+zpipe.c
+    reads and writes zlib streams from stdin to stdout
+    - illustrates the proper use of deflate() and inflate()
+    - deeply commented in zlib_how.html (see above)
+
+zran.c
+    index a zlib or gzip stream and randomly access it
+    - illustrates the use of Z_BLOCK, inflatePrime(), and
+      inflateSetDictionary() to provide random access
Index: /trunk/minix/lib/zlib-1.2.3/examples/fitblk.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/examples/fitblk.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/examples/fitblk.c	(revision 9)
@@ -0,0 +1,233 @@
+/* fitblk.c: example of fitting compressed output to a specified size
+   Not copyrighted -- provided to the public domain
+   Version 1.1  25 November 2004  Mark Adler */
+
+/* Version history:
+   1.0  24 Nov 2004  First version
+   1.1  25 Nov 2004  Change deflateInit2() to deflateInit()
+                     Use fixed-size, stack-allocated raw buffers
+                     Simplify code moving compression to subroutines
+                     Use assert() for internal errors
+                     Add detailed description of approach
+ */
+
+/* Approach to just fitting a requested compressed size:
+
+   fitblk performs three compression passes on a portion of the input
+   data in order to determine how much of that input will compress to
+   nearly the requested output block size.  The first pass generates
+   enough deflate blocks to produce output to fill the requested
+   output size plus a specfied excess amount (see the EXCESS define
+   below).  The last deflate block may go quite a bit past that, but
+   is discarded.  The second pass decompresses and recompresses just
+   the compressed data that fit in the requested plus excess sized
+   buffer.  The deflate process is terminated after that amount of
+   input, which is less than the amount consumed on the first pass.
+   The last deflate block of the result will be of a comparable size
+   to the final product, so that the header for that deflate block and
+   the compression ratio for that block will be about the same as in
+   the final product.  The third compression pass decompresses the
+   result of the second step, but only the compressed data up to the
+   requested size minus an amount to allow the compressed stream to
+   complete (see the MARGIN define below).  That will result in a
+   final compressed stream whose length is less than or equal to the
+   requested size.  Assuming sufficient input and a requested size
+   greater than a few hundred bytes, the shortfall will typically be
+   less than ten bytes.
+
+   If the input is short enough that the first compression completes
+   before filling the requested output size, then that compressed
+   stream is return with no recompression.
+
+   EXCESS is chosen to be just greater than the shortfall seen in a
+   two pass approach similar to the above.  That shortfall is due to
+   the last deflate block compressing more efficiently with a smaller
+   header on the second pass.  EXCESS is set to be large enough so
+   that there is enough uncompressed data for the second pass to fill
+   out the requested size, and small enough so that the final deflate
+   block of the second pass will be close in size to the final deflate
+   block of the third and final pass.  MARGIN is chosen to be just
+   large enough to assure that the final compression has enough room
+   to complete in all cases.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "zlib.h"
+
+#define local static
+
+/* print nastygram and leave */
+local void quit(char *why)
+{
+    fprintf(stderr, "fitblk abort: %s\n", why);
+    exit(1);
+}
+
+#define RAWLEN 4096    /* intermediate uncompressed buffer size */
+
+/* compress from file to def until provided buffer is full or end of
+   input reached; return last deflate() return value, or Z_ERRNO if
+   there was read error on the file */
+local int partcompress(FILE *in, z_streamp def)
+{
+    int ret, flush;
+    unsigned char raw[RAWLEN];
+
+    flush = Z_NO_FLUSH;
+    do {
+        def->avail_in = fread(raw, 1, RAWLEN, in);
+        if (ferror(in))
+            return Z_ERRNO;
+        def->next_in = raw;
+        if (feof(in))
+            flush = Z_FINISH;
+        ret = deflate(def, flush);
+        assert(ret != Z_STREAM_ERROR);
+    } while (def->avail_out != 0 && flush == Z_NO_FLUSH);
+    return ret;
+}
+
+/* recompress from inf's input to def's output; the input for inf and
+   the output for def are set in those structures before calling;
+   return last deflate() return value, or Z_MEM_ERROR if inflate()
+   was not able to allocate enough memory when it needed to */
+local int recompress(z_streamp inf, z_streamp def)
+{
+    int ret, flush;
+    unsigned char raw[RAWLEN];
+
+    flush = Z_NO_FLUSH;
+    do {
+        /* decompress */
+        inf->avail_out = RAWLEN;
+        inf->next_out = raw;
+        ret = inflate(inf, Z_NO_FLUSH);
+        assert(ret != Z_STREAM_ERROR && ret != Z_DATA_ERROR &&
+               ret != Z_NEED_DICT);
+        if (ret == Z_MEM_ERROR)
+            return ret;
+
+        /* compress what was decompresed until done or no room */
+        def->avail_in = RAWLEN - inf->avail_out;
+        def->next_in = raw;
+        if (inf->avail_out != 0)
+            flush = Z_FINISH;
+        ret = deflate(def, flush);
+        assert(ret != Z_STREAM_ERROR);
+    } while (ret != Z_STREAM_END && def->avail_out != 0);
+    return ret;
+}
+
+#define EXCESS 256      /* empirically determined stream overage */
+#define MARGIN 8        /* amount to back off for completion */
+
+/* compress from stdin to fixed-size block on stdout */
+int main(int argc, char **argv)
+{
+    int ret;                /* return code */
+    unsigned size;          /* requested fixed output block size */
+    unsigned have;          /* bytes written by deflate() call */
+    unsigned char *blk;     /* intermediate and final stream */
+    unsigned char *tmp;     /* close to desired size stream */
+    z_stream def, inf;      /* zlib deflate and inflate states */
+
+    /* get requested output size */
+    if (argc != 2)
+        quit("need one argument: size of output block");
+    ret = strtol(argv[1], argv + 1, 10);
+    if (argv[1][0] != 0)
+        quit("argument must be a number");
+    if (ret < 8)            /* 8 is minimum zlib stream size */
+        quit("need positive size of 8 or greater");
+    size = (unsigned)ret;
+
+    /* allocate memory for buffers and compression engine */
+    blk = malloc(size + EXCESS);
+    def.zalloc = Z_NULL;
+    def.zfree = Z_NULL;
+    def.opaque = Z_NULL;
+    ret = deflateInit(&def, Z_DEFAULT_COMPRESSION);
+    if (ret != Z_OK || blk == NULL)
+        quit("out of memory");
+
+    /* compress from stdin until output full, or no more input */
+    def.avail_out = size + EXCESS;
+    def.next_out = blk;
+    ret = partcompress(stdin, &def);
+    if (ret == Z_ERRNO)
+        quit("error reading input");
+
+    /* if it all fit, then size was undersubscribed -- done! */
+    if (ret == Z_STREAM_END && def.avail_out >= EXCESS) {
+        /* write block to stdout */
+        have = size + EXCESS - def.avail_out;
+        if (fwrite(blk, 1, have, stdout) != have || ferror(stdout))
+            quit("error writing output");
+
+        /* clean up and print results to stderr */
+        ret = deflateEnd(&def);
+        assert(ret != Z_STREAM_ERROR);
+        free(blk);
+        fprintf(stderr,
+                "%u bytes unused out of %u requested (all input)\n",
+                size - have, size);
+        return 0;
+    }
+
+    /* it didn't all fit -- set up for recompression */
+    inf.zalloc = Z_NULL;
+    inf.zfree = Z_NULL;
+    inf.opaque = Z_NULL;
+    inf.avail_in = 0;
+    inf.next_in = Z_NULL;
+    ret = inflateInit(&inf);
+    tmp = malloc(size + EXCESS);
+    if (ret != Z_OK || tmp == NULL)
+        quit("out of memory");
+    ret = deflateReset(&def);
+    assert(ret != Z_STREAM_ERROR);
+
+    /* do first recompression close to the right amount */
+    inf.avail_in = size + EXCESS;
+    inf.next_in = blk;
+    def.avail_out = size + EXCESS;
+    def.next_out = tmp;
+    ret = recompress(&inf, &def);
+    if (ret == Z_MEM_ERROR)
+        quit("out of memory");
+
+    /* set up for next reocmpression */
+    ret = inflateReset(&inf);
+    assert(ret != Z_STREAM_ERROR);
+    ret = deflateReset(&def);
+    assert(ret != Z_STREAM_ERROR);
+
+    /* do second and final recompression (third compression) */
+    inf.avail_in = size - MARGIN;   /* assure stream will complete */
+    inf.next_in = tmp;
+    def.avail_out = size;
+    def.next_out = blk;
+    ret = recompress(&inf, &def);
+    if (ret == Z_MEM_ERROR)
+        quit("out of memory");
+    assert(ret == Z_STREAM_END);    /* otherwise MARGIN too small */
+
+    /* done -- write block to stdout */
+    have = size - def.avail_out;
+    if (fwrite(blk, 1, have, stdout) != have || ferror(stdout))
+        quit("error writing output");
+
+    /* clean up and print results to stderr */
+    free(tmp);
+    ret = inflateEnd(&inf);
+    assert(ret != Z_STREAM_ERROR);
+    ret = deflateEnd(&def);
+    assert(ret != Z_STREAM_ERROR);
+    free(blk);
+    fprintf(stderr,
+            "%u bytes unused out of %u requested (%lu input)\n",
+            size - have, size, def.total_in);
+    return 0;
+}
Index: /trunk/minix/lib/zlib-1.2.3/examples/gun.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/examples/gun.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/examples/gun.c	(revision 9)
@@ -0,0 +1,693 @@
+/* gun.c -- simple gunzip to give an example of the use of inflateBack()
+ * Copyright (C) 2003, 2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+   Version 1.3  12 June 2005  Mark Adler */
+
+/* Version history:
+   1.0  16 Feb 2003  First version for testing of inflateBack()
+   1.1  21 Feb 2005  Decompress concatenated gzip streams
+                     Remove use of "this" variable (C++ keyword)
+                     Fix return value for in()
+                     Improve allocation failure checking
+                     Add typecasting for void * structures
+                     Add -h option for command version and usage
+                     Add a bunch of comments
+   1.2  20 Mar 2005  Add Unix compress (LZW) decompression
+                     Copy file attributes from input file to output file
+   1.3  12 Jun 2005  Add casts for error messages [Oberhumer]
+ */
+
+/*
+   gun [ -t ] [ name ... ]
+
+   decompresses the data in the named gzip files.  If no arguments are given,
+   gun will decompress from stdin to stdout.  The names must end in .gz, -gz,
+   .z, -z, _z, or .Z.  The uncompressed data will be written to a file name
+   with the suffix stripped.  On success, the original file is deleted.  On
+   failure, the output file is deleted.  For most failures, the command will
+   continue to process the remaining names on the command line.  A memory
+   allocation failure will abort the command.  If -t is specified, then the
+   listed files or stdin will be tested as gzip files for integrity (without
+   checking for a proper suffix), no output will be written, and no files
+   will be deleted.
+
+   Like gzip, gun allows concatenated gzip streams and will decompress them,
+   writing all of the uncompressed data to the output.  Unlike gzip, gun allows
+   an empty file on input, and will produce no error writing an empty output
+   file.
+
+   gun will also decompress files made by Unix compress, which uses LZW
+   compression.  These files are automatically detected by virtue of their
+   magic header bytes.  Since the end of Unix compress stream is marked by the
+   end-of-file, they cannot be concantenated.  If a Unix compress stream is
+   encountered in an input file, it is the last stream in that file.
+
+   Like gunzip and uncompress, the file attributes of the orignal compressed
+   file are maintained in the final uncompressed file, to the extent that the
+   user permissions allow it.
+
+   On my Mac OS X PowerPC G4, gun is almost twice as fast as gunzip (version
+   1.2.4) is on the same file, when gun is linked with zlib 1.2.2.  Also the
+   LZW decompression provided by gun is about twice as fast as the standard
+   Unix uncompress command.
+ */
+
+/* external functions and related types and constants */
+#include <stdio.h>          /* fprintf() */
+#include <stdlib.h>         /* malloc(), free() */
+#include <string.h>         /* strerror(), strcmp(), strlen(), memcpy() */
+#include <errno.h>          /* errno */
+#include <fcntl.h>          /* open() */
+#include <unistd.h>         /* read(), write(), close(), chown(), unlink() */
+#include <sys/types.h>
+#include <sys/stat.h>       /* stat(), chmod() */
+#include <utime.h>          /* utime() */
+#include "zlib.h"           /* inflateBackInit(), inflateBack(), */
+                            /* inflateBackEnd(), crc32() */
+
+/* function declaration */
+#define local static
+
+/* buffer constants */
+#define SIZE 32768U         /* input and output buffer sizes */
+#define PIECE 16384         /* limits i/o chunks for 16-bit int case */
+
+/* structure for infback() to pass to input function in() -- it maintains the
+   input file and a buffer of size SIZE */
+struct ind {
+    int infile;
+    unsigned char *inbuf;
+};
+
+/* Load input buffer, assumed to be empty, and return bytes loaded and a
+   pointer to them.  read() is called until the buffer is full, or until it
+   returns end-of-file or error.  Return 0 on error. */
+local unsigned in(void *in_desc, unsigned char **buf)
+{
+    int ret;
+    unsigned len;
+    unsigned char *next;
+    struct ind *me = (struct ind *)in_desc;
+
+    next = me->inbuf;
+    *buf = next;
+    len = 0;
+    do {
+        ret = PIECE;
+        if ((unsigned)ret > SIZE - len)
+            ret = (int)(SIZE - len);
+        ret = (int)read(me->infile, next, ret);
+        if (ret == -1) {
+            len = 0;
+            break;
+        }
+        next += ret;
+        len += ret;
+    } while (ret != 0 && len < SIZE);
+    return len;
+}
+
+/* structure for infback() to pass to output function out() -- it maintains the
+   output file, a running CRC-32 check on the output and the total number of
+   bytes output, both for checking against the gzip trailer.  (The length in
+   the gzip trailer is stored modulo 2^32, so it's ok if a long is 32 bits and
+   the output is greater than 4 GB.) */
+struct outd {
+    int outfile;
+    int check;                  /* true if checking crc and total */
+    unsigned long crc;
+    unsigned long total;
+};
+
+/* Write output buffer and update the CRC-32 and total bytes written.  write()
+   is called until all of the output is written or an error is encountered.
+   On success out() returns 0.  For a write failure, out() returns 1.  If the
+   output file descriptor is -1, then nothing is written.
+ */
+local int out(void *out_desc, unsigned char *buf, unsigned len)
+{
+    int ret;
+    struct outd *me = (struct outd *)out_desc;
+
+    if (me->check) {
+        me->crc = crc32(me->crc, buf, len);
+        me->total += len;
+    }
+    if (me->outfile != -1)
+        do {
+            ret = PIECE;
+            if ((unsigned)ret > len)
+                ret = (int)len;
+            ret = (int)write(me->outfile, buf, ret);
+            if (ret == -1)
+                return 1;
+            buf += ret;
+            len -= ret;
+        } while (len != 0);
+    return 0;
+}
+
+/* next input byte macro for use inside lunpipe() and gunpipe() */
+#define NEXT() (have ? 0 : (have = in(indp, &next)), \
+                last = have ? (have--, (int)(*next++)) : -1)
+
+/* memory for gunpipe() and lunpipe() --
+   the first 256 entries of prefix[] and suffix[] are never used, could
+   have offset the index, but it's faster to waste the memory */
+unsigned char inbuf[SIZE];              /* input buffer */
+unsigned char outbuf[SIZE];             /* output buffer */
+unsigned short prefix[65536];           /* index to LZW prefix string */
+unsigned char suffix[65536];            /* one-character LZW suffix */
+unsigned char match[65280 + 2];         /* buffer for reversed match or gzip
+                                           32K sliding window */
+
+/* throw out what's left in the current bits byte buffer (this is a vestigial
+   aspect of the compressed data format derived from an implementation that
+   made use of a special VAX machine instruction!) */
+#define FLUSHCODE() \
+    do { \
+        left = 0; \
+        rem = 0; \
+        if (chunk > have) { \
+            chunk -= have; \
+            have = 0; \
+            if (NEXT() == -1) \
+                break; \
+            chunk--; \
+            if (chunk > have) { \
+                chunk = have = 0; \
+                break; \
+            } \
+        } \
+        have -= chunk; \
+        next += chunk; \
+        chunk = 0; \
+    } while (0)
+
+/* Decompress a compress (LZW) file from indp to outfile.  The compress magic
+   header (two bytes) has already been read and verified.  There are have bytes
+   of buffered input at next.  strm is used for passing error information back
+   to gunpipe().
+
+   lunpipe() will return Z_OK on success, Z_BUF_ERROR for an unexpected end of
+   file, read error, or write error (a write error indicated by strm->next_in
+   not equal to Z_NULL), or Z_DATA_ERROR for invalid input.
+ */
+local int lunpipe(unsigned have, unsigned char *next, struct ind *indp,
+                  int outfile, z_stream *strm)
+{
+    int last;                   /* last byte read by NEXT(), or -1 if EOF */
+    int chunk;                  /* bytes left in current chunk */
+    int left;                   /* bits left in rem */
+    unsigned rem;               /* unused bits from input */
+    int bits;                   /* current bits per code */
+    unsigned code;              /* code, table traversal index */
+    unsigned mask;              /* mask for current bits codes */
+    int max;                    /* maximum bits per code for this stream */
+    int flags;                  /* compress flags, then block compress flag */
+    unsigned end;               /* last valid entry in prefix/suffix tables */
+    unsigned temp;              /* current code */
+    unsigned prev;              /* previous code */
+    unsigned final;             /* last character written for previous code */
+    unsigned stack;             /* next position for reversed string */
+    unsigned outcnt;            /* bytes in output buffer */
+    struct outd outd;           /* output structure */
+
+    /* set up output */
+    outd.outfile = outfile;
+    outd.check = 0;
+
+    /* process remainder of compress header -- a flags byte */
+    flags = NEXT();
+    if (last == -1)
+        return Z_BUF_ERROR;
+    if (flags & 0x60) {
+        strm->msg = (char *)"unknown lzw flags set";
+        return Z_DATA_ERROR;
+    }
+    max = flags & 0x1f;
+    if (max < 9 || max > 16) {
+        strm->msg = (char *)"lzw bits out of range";
+        return Z_DATA_ERROR;
+    }
+    if (max == 9)                           /* 9 doesn't really mean 9 */
+        max = 10;
+    flags &= 0x80;                          /* true if block compress */
+
+    /* clear table */
+    bits = 9;
+    mask = 0x1ff;
+    end = flags ? 256 : 255;
+
+    /* set up: get first 9-bit code, which is the first decompressed byte, but
+       don't create a table entry until the next code */
+    if (NEXT() == -1)                       /* no compressed data is ok */
+        return Z_OK;
+    final = prev = (unsigned)last;          /* low 8 bits of code */
+    if (NEXT() == -1)                       /* missing a bit */
+        return Z_BUF_ERROR;
+    if (last & 1) {                         /* code must be < 256 */
+        strm->msg = (char *)"invalid lzw code";
+        return Z_DATA_ERROR;
+    }
+    rem = (unsigned)last >> 1;              /* remaining 7 bits */
+    left = 7;
+    chunk = bits - 2;                       /* 7 bytes left in this chunk */
+    outbuf[0] = (unsigned char)final;       /* write first decompressed byte */
+    outcnt = 1;
+
+    /* decode codes */
+    stack = 0;
+    for (;;) {
+        /* if the table will be full after this, increment the code size */
+        if (end >= mask && bits < max) {
+            FLUSHCODE();
+            bits++;
+            mask <<= 1;
+            mask++;
+        }
+
+        /* get a code of length bits */
+        if (chunk == 0)                     /* decrement chunk modulo bits */
+            chunk = bits;
+        code = rem;                         /* low bits of code */
+        if (NEXT() == -1) {                 /* EOF is end of compressed data */
+            /* write remaining buffered output */
+            if (outcnt && out(&outd, outbuf, outcnt)) {
+                strm->next_in = outbuf;     /* signal write error */
+                return Z_BUF_ERROR;
+            }
+            return Z_OK;
+        }
+        code += (unsigned)last << left;     /* middle (or high) bits of code */
+        left += 8;
+        chunk--;
+        if (bits > left) {                  /* need more bits */
+            if (NEXT() == -1)               /* can't end in middle of code */
+                return Z_BUF_ERROR;
+            code += (unsigned)last << left; /* high bits of code */
+            left += 8;
+            chunk--;
+        }
+        code &= mask;                       /* mask to current code length */
+        left -= bits;                       /* number of unused bits */
+        rem = (unsigned)last >> (8 - left); /* unused bits from last byte */
+
+        /* process clear code (256) */
+        if (code == 256 && flags) {
+            FLUSHCODE();
+            bits = 9;                       /* initialize bits and mask */
+            mask = 0x1ff;
+            end = 255;                      /* empty table */
+            continue;                       /* get next code */
+        }
+
+        /* special code to reuse last match */
+        temp = code;                        /* save the current code */
+        if (code > end) {
+            /* Be picky on the allowed code here, and make sure that the code
+               we drop through (prev) will be a valid index so that random
+               input does not cause an exception.  The code != end + 1 check is
+               empirically derived, and not checked in the original uncompress
+               code.  If this ever causes a problem, that check could be safely
+               removed.  Leaving this check in greatly improves gun's ability
+               to detect random or corrupted input after a compress header.
+               In any case, the prev > end check must be retained. */
+            if (code != end + 1 || prev > end) {
+                strm->msg = (char *)"invalid lzw code";
+                return Z_DATA_ERROR;
+            }
+            match[stack++] = (unsigned char)final;
+            code = prev;
+        }
+
+        /* walk through linked list to generate output in reverse order */
+        while (code >= 256) {
+            match[stack++] = suffix[code];
+            code = prefix[code];
+        }
+        match[stack++] = (unsigned char)code;
+        final = code;
+
+        /* link new table entry */
+        if (end < mask) {
+            end++;
+            prefix[end] = (unsigned short)prev;
+            suffix[end] = (unsigned char)final;
+        }
+
+        /* set previous code for next iteration */
+        prev = temp;
+
+        /* write output in forward order */
+        while (stack > SIZE - outcnt) {
+            while (outcnt < SIZE)
+                outbuf[outcnt++] = match[--stack];
+            if (out(&outd, outbuf, outcnt)) {
+                strm->next_in = outbuf; /* signal write error */
+                return Z_BUF_ERROR;
+            }
+            outcnt = 0;
+        }
+        do {
+            outbuf[outcnt++] = match[--stack];
+        } while (stack);
+
+        /* loop for next code with final and prev as the last match, rem and
+           left provide the first 0..7 bits of the next code, end is the last
+           valid table entry */
+    }
+}
+
+/* Decompress a gzip file from infile to outfile.  strm is assumed to have been
+   successfully initialized with inflateBackInit().  The input file may consist
+   of a series of gzip streams, in which case all of them will be decompressed
+   to the output file.  If outfile is -1, then the gzip stream(s) integrity is
+   checked and nothing is written.
+
+   The return value is a zlib error code: Z_MEM_ERROR if out of memory,
+   Z_DATA_ERROR if the header or the compressed data is invalid, or if the
+   trailer CRC-32 check or length doesn't match, Z_BUF_ERROR if the input ends
+   prematurely or a write error occurs, or Z_ERRNO if junk (not a another gzip
+   stream) follows a valid gzip stream.
+ */
+local int gunpipe(z_stream *strm, int infile, int outfile)
+{
+    int ret, first, last;
+    unsigned have, flags, len;
+    unsigned char *next;
+    struct ind ind, *indp;
+    struct outd outd;
+
+    /* setup input buffer */
+    ind.infile = infile;
+    ind.inbuf = inbuf;
+    indp = &ind;
+
+    /* decompress concatenated gzip streams */
+    have = 0;                               /* no input data read in yet */
+    first = 1;                              /* looking for first gzip header */
+    strm->next_in = Z_NULL;                 /* so Z_BUF_ERROR means EOF */
+    for (;;) {
+        /* look for the two magic header bytes for a gzip stream */
+        if (NEXT() == -1) {
+            ret = Z_OK;
+            break;                          /* empty gzip stream is ok */
+        }
+        if (last != 31 || (NEXT() != 139 && last != 157)) {
+            strm->msg = (char *)"incorrect header check";
+            ret = first ? Z_DATA_ERROR : Z_ERRNO;
+            break;                          /* not a gzip or compress header */
+        }
+        first = 0;                          /* next non-header is junk */
+
+        /* process a compress (LZW) file -- can't be concatenated after this */
+        if (last == 157) {
+            ret = lunpipe(have, next, indp, outfile, strm);
+            break;
+        }
+
+        /* process remainder of gzip header */
+        ret = Z_BUF_ERROR;
+        if (NEXT() != 8) {                  /* only deflate method allowed */
+            if (last == -1) break;
+            strm->msg = (char *)"unknown compression method";
+            ret = Z_DATA_ERROR;
+            break;
+        }
+        flags = NEXT();                     /* header flags */
+        NEXT();                             /* discard mod time, xflgs, os */
+        NEXT();
+        NEXT();
+        NEXT();
+        NEXT();
+        NEXT();
+        if (last == -1) break;
+        if (flags & 0xe0) {
+            strm->msg = (char *)"unknown header flags set";
+            ret = Z_DATA_ERROR;
+            break;
+        }
+        if (flags & 4) {                    /* extra field */
+            len = NEXT();
+            len += (unsigned)(NEXT()) << 8;
+            if (last == -1) break;
+            while (len > have) {
+                len -= have;
+                have = 0;
+                if (NEXT() == -1) break;
+                len--;
+            }
+            if (last == -1) break;
+            have -= len;
+            next += len;
+        }
+        if (flags & 8)                      /* file name */
+            while (NEXT() != 0 && last != -1)
+                ;
+        if (flags & 16)                     /* comment */
+            while (NEXT() != 0 && last != -1)
+                ;
+        if (flags & 2) {                    /* header crc */
+            NEXT();
+            NEXT();
+        }
+        if (last == -1) break;
+
+        /* set up output */
+        outd.outfile = outfile;
+        outd.check = 1;
+        outd.crc = crc32(0L, Z_NULL, 0);
+        outd.total = 0;
+
+        /* decompress data to output */
+        strm->next_in = next;
+        strm->avail_in = have;
+        ret = inflateBack(strm, in, indp, out, &outd);
+        if (ret != Z_STREAM_END) break;
+        next = strm->next_in;
+        have = strm->avail_in;
+        strm->next_in = Z_NULL;             /* so Z_BUF_ERROR means EOF */
+
+        /* check trailer */
+        ret = Z_BUF_ERROR;
+        if (NEXT() != (outd.crc & 0xff) ||
+            NEXT() != ((outd.crc >> 8) & 0xff) ||
+            NEXT() != ((outd.crc >> 16) & 0xff) ||
+            NEXT() != ((outd.crc >> 24) & 0xff)) {
+            /* crc error */
+            if (last != -1) {
+                strm->msg = (char *)"incorrect data check";
+                ret = Z_DATA_ERROR;
+            }
+            break;
+        }
+        if (NEXT() != (outd.total & 0xff) ||
+            NEXT() != ((outd.total >> 8) & 0xff) ||
+            NEXT() != ((outd.total >> 16) & 0xff) ||
+            NEXT() != ((outd.total >> 24) & 0xff)) {
+            /* length error */
+            if (last != -1) {
+                strm->msg = (char *)"incorrect length check";
+                ret = Z_DATA_ERROR;
+            }
+            break;
+        }
+
+        /* go back and look for another gzip stream */
+    }
+
+    /* clean up and return */
+    return ret;
+}
+
+/* Copy file attributes, from -> to, as best we can.  This is best effort, so
+   no errors are reported.  The mode bits, including suid, sgid, and the sticky
+   bit are copied (if allowed), the owner's user id and group id are copied
+   (again if allowed), and the access and modify times are copied. */
+local void copymeta(char *from, char *to)
+{
+    struct stat was;
+    struct utimbuf when;
+
+    /* get all of from's Unix meta data, return if not a regular file */
+    if (stat(from, &was) != 0 || (was.st_mode & S_IFMT) != S_IFREG)
+        return;
+
+    /* set to's mode bits, ignore errors */
+    (void)chmod(to, was.st_mode & 07777);
+
+    /* copy owner's user and group, ignore errors */
+    (void)chown(to, was.st_uid, was.st_gid);
+
+    /* copy access and modify times, ignore errors */
+    when.actime = was.st_atime;
+    when.modtime = was.st_mtime;
+    (void)utime(to, &when);
+}
+
+/* Decompress the file inname to the file outnname, of if test is true, just
+   decompress without writing and check the gzip trailer for integrity.  If
+   inname is NULL or an empty string, read from stdin.  If outname is NULL or
+   an empty string, write to stdout.  strm is a pre-initialized inflateBack
+   structure.  When appropriate, copy the file attributes from inname to
+   outname.
+
+   gunzip() returns 1 if there is an out-of-memory error or an unexpected
+   return code from gunpipe().  Otherwise it returns 0.
+ */
+local int gunzip(z_stream *strm, char *inname, char *outname, int test)
+{
+    int ret;
+    int infile, outfile;
+
+    /* open files */
+    if (inname == NULL || *inname == 0) {
+        inname = "-";
+        infile = 0;     /* stdin */
+    }
+    else {
+        infile = open(inname, O_RDONLY, 0);
+        if (infile == -1) {
+            fprintf(stderr, "gun cannot open %s\n", inname);
+            return 0;
+        }
+    }
+    if (test)
+        outfile = -1;
+    else if (outname == NULL || *outname == 0) {
+        outname = "-";
+        outfile = 1;    /* stdout */
+    }
+    else {
+        outfile = open(outname, O_CREAT | O_TRUNC | O_WRONLY, 0666);
+        if (outfile == -1) {
+            close(infile);
+            fprintf(stderr, "gun cannot create %s\n", outname);
+            return 0;
+        }
+    }
+    errno = 0;
+
+    /* decompress */
+    ret = gunpipe(strm, infile, outfile);
+    if (outfile > 2) close(outfile);
+    if (infile > 2) close(infile);
+
+    /* interpret result */
+    switch (ret) {
+    case Z_OK:
+    case Z_ERRNO:
+        if (infile > 2 && outfile > 2) {
+            copymeta(inname, outname);          /* copy attributes */
+            unlink(inname);
+        }
+        if (ret == Z_ERRNO)
+            fprintf(stderr, "gun warning: trailing garbage ignored in %s\n",
+                    inname);
+        break;
+    case Z_DATA_ERROR:
+        if (outfile > 2) unlink(outname);
+        fprintf(stderr, "gun data error on %s: %s\n", inname, strm->msg);
+        break;
+    case Z_MEM_ERROR:
+        if (outfile > 2) unlink(outname);
+        fprintf(stderr, "gun out of memory error--aborting\n");
+        return 1;
+    case Z_BUF_ERROR:
+        if (outfile > 2) unlink(outname);
+        if (strm->next_in != Z_NULL) {
+            fprintf(stderr, "gun write error on %s: %s\n",
+                    outname, strerror(errno));
+        }
+        else if (errno) {
+            fprintf(stderr, "gun read error on %s: %s\n",
+                    inname, strerror(errno));
+        }
+        else {
+            fprintf(stderr, "gun unexpected end of file on %s\n",
+                    inname);
+        }
+        break;
+    default:
+        if (outfile > 2) unlink(outname);
+        fprintf(stderr, "gun internal error--aborting\n");
+        return 1;
+    }
+    return 0;
+}
+
+/* Process the gun command line arguments.  See the command syntax near the
+   beginning of this source file. */
+int main(int argc, char **argv)
+{
+    int ret, len, test;
+    char *outname;
+    unsigned char *window;
+    z_stream strm;
+
+    /* initialize inflateBack state for repeated use */
+    window = match;                         /* reuse LZW match buffer */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    ret = inflateBackInit(&strm, 15, window);
+    if (ret != Z_OK) {
+        fprintf(stderr, "gun out of memory error--aborting\n");
+        return 1;
+    }
+
+    /* decompress each file to the same name with the suffix removed */
+    argc--;
+    argv++;
+    test = 0;
+    if (argc && strcmp(*argv, "-h") == 0) {
+        fprintf(stderr, "gun 1.3 (12 Jun 2005)\n");
+        fprintf(stderr, "Copyright (c) 2005 Mark Adler\n");
+        fprintf(stderr, "usage: gun [-t] [file1.gz [file2.Z ...]]\n");
+        return 0;
+    }
+    if (argc && strcmp(*argv, "-t") == 0) {
+        test = 1;
+        argc--;
+        argv++;
+    }
+    if (argc)
+        do {
+            if (test)
+                outname = NULL;
+            else {
+                len = (int)strlen(*argv);
+                if (strcmp(*argv + len - 3, ".gz") == 0 ||
+                    strcmp(*argv + len - 3, "-gz") == 0)
+                    len -= 3;
+                else if (strcmp(*argv + len - 2, ".z") == 0 ||
+                    strcmp(*argv + len - 2, "-z") == 0 ||
+                    strcmp(*argv + len - 2, "_z") == 0 ||
+                    strcmp(*argv + len - 2, ".Z") == 0)
+                    len -= 2;
+                else {
+                    fprintf(stderr, "gun error: no gz type on %s--skipping\n",
+                            *argv);
+                    continue;
+                }
+                outname = malloc(len + 1);
+                if (outname == NULL) {
+                    fprintf(stderr, "gun out of memory error--aborting\n");
+                    ret = 1;
+                    break;
+                }
+                memcpy(outname, *argv, len);
+                outname[len] = 0;
+            }
+            ret = gunzip(&strm, *argv, outname, test);
+            if (outname != NULL) free(outname);
+            if (ret) break;
+        } while (argv++, --argc);
+    else
+        ret = gunzip(&strm, NULL, NULL, test);
+
+    /* clean up */
+    inflateBackEnd(&strm);
+    return ret;
+}
Index: /trunk/minix/lib/zlib-1.2.3/examples/gzappend.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/examples/gzappend.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/examples/gzappend.c	(revision 9)
@@ -0,0 +1,500 @@
+/* gzappend -- command to append to a gzip file
+
+  Copyright (C) 2003 Mark Adler, all rights reserved
+  version 1.1, 4 Nov 2003
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the author be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Mark Adler    madler@alumni.caltech.edu
+ */
+
+/*
+ * Change history:
+ *
+ * 1.0  19 Oct 2003     - First version
+ * 1.1   4 Nov 2003     - Expand and clarify some comments and notes
+ *                      - Add version and copyright to help
+ *                      - Send help to stdout instead of stderr
+ *                      - Add some preemptive typecasts
+ *                      - Add L to constants in lseek() calls
+ *                      - Remove some debugging information in error messages
+ *                      - Use new data_type definition for zlib 1.2.1
+ *                      - Simplfy and unify file operations
+ *                      - Finish off gzip file in gztack()
+ *                      - Use deflatePrime() instead of adding empty blocks
+ *                      - Keep gzip file clean on appended file read errors
+ *                      - Use in-place rotate instead of auxiliary buffer
+ *                        (Why you ask?  Because it was fun to write!)
+ */
+
+/*
+   gzappend takes a gzip file and appends to it, compressing files from the
+   command line or data from stdin.  The gzip file is written to directly, to
+   avoid copying that file, in case it's large.  Note that this results in the
+   unfriendly behavior that if gzappend fails, the gzip file is corrupted.
+
+   This program was written to illustrate the use of the new Z_BLOCK option of
+   zlib 1.2.x's inflate() function.  This option returns from inflate() at each
+   block boundary to facilitate locating and modifying the last block bit at
+   the start of the final deflate block.  Also whether using Z_BLOCK or not,
+   another required feature of zlib 1.2.x is that inflate() now provides the
+   number of unusued bits in the last input byte used.  gzappend will not work
+   with versions of zlib earlier than 1.2.1.
+
+   gzappend first decompresses the gzip file internally, discarding all but
+   the last 32K of uncompressed data, and noting the location of the last block
+   bit and the number of unused bits in the last byte of the compressed data.
+   The gzip trailer containing the CRC-32 and length of the uncompressed data
+   is verified.  This trailer will be later overwritten.
+
+   Then the last block bit is cleared by seeking back in the file and rewriting
+   the byte that contains it.  Seeking forward, the last byte of the compressed
+   data is saved along with the number of unused bits to initialize deflate.
+
+   A deflate process is initialized, using the last 32K of the uncompressed
+   data from the gzip file to initialize the dictionary.  If the total
+   uncompressed data was less than 32K, then all of it is used to initialize
+   the dictionary.  The deflate output bit buffer is also initialized with the
+   last bits from the original deflate stream.  From here on, the data to
+   append is simply compressed using deflate, and written to the gzip file.
+   When that is complete, the new CRC-32 and uncompressed length are written
+   as the trailer of the gzip file.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "zlib.h"
+
+#define local static
+#define LGCHUNK 14
+#define CHUNK (1U << LGCHUNK)
+#define DSIZE 32768U
+
+/* print an error message and terminate with extreme prejudice */
+local void bye(char *msg1, char *msg2)
+{
+    fprintf(stderr, "gzappend error: %s%s\n", msg1, msg2);
+    exit(1);
+}
+
+/* return the greatest common divisor of a and b using Euclid's algorithm,
+   modified to be fast when one argument much greater than the other, and
+   coded to avoid unnecessary swapping */
+local unsigned gcd(unsigned a, unsigned b)
+{
+    unsigned c;
+
+    while (a && b)
+        if (a > b) {
+            c = b;
+            while (a - c >= c)
+                c <<= 1;
+            a -= c;
+        }
+        else {
+            c = a;
+            while (b - c >= c)
+                c <<= 1;
+            b -= c;
+        }
+    return a + b;
+}
+
+/* rotate list[0..len-1] left by rot positions, in place */
+local void rotate(unsigned char *list, unsigned len, unsigned rot)
+{
+    unsigned char tmp;
+    unsigned cycles;
+    unsigned char *start, *last, *to, *from;
+
+    /* normalize rot and handle degenerate cases */
+    if (len < 2) return;
+    if (rot >= len) rot %= len;
+    if (rot == 0) return;
+
+    /* pointer to last entry in list */
+    last = list + (len - 1);
+
+    /* do simple left shift by one */
+    if (rot == 1) {
+        tmp = *list;
+        memcpy(list, list + 1, len - 1);
+        *last = tmp;
+        return;
+    }
+
+    /* do simple right shift by one */
+    if (rot == len - 1) {
+        tmp = *last;
+        memmove(list + 1, list, len - 1);
+        *list = tmp;
+        return;
+    }
+
+    /* otherwise do rotate as a set of cycles in place */
+    cycles = gcd(len, rot);             /* number of cycles */
+    do {
+        start = from = list + cycles;   /* start index is arbitrary */
+        tmp = *from;                    /* save entry to be overwritten */
+        for (;;) {
+            to = from;                  /* next step in cycle */
+            from += rot;                /* go right rot positions */
+            if (from > last) from -= len;   /* (pointer better not wrap) */
+            if (from == start) break;   /* all but one shifted */
+            *to = *from;                /* shift left */
+        }
+        *to = tmp;                      /* complete the circle */
+    } while (--cycles);
+}
+
+/* structure for gzip file read operations */
+typedef struct {
+    int fd;                     /* file descriptor */
+    int size;                   /* 1 << size is bytes in buf */
+    unsigned left;              /* bytes available at next */
+    unsigned char *buf;         /* buffer */
+    unsigned char *next;        /* next byte in buffer */
+    char *name;                 /* file name for error messages */
+} file;
+
+/* reload buffer */
+local int readin(file *in)
+{
+    int len;
+
+    len = read(in->fd, in->buf, 1 << in->size);
+    if (len == -1) bye("error reading ", in->name);
+    in->left = (unsigned)len;
+    in->next = in->buf;
+    return len;
+}
+
+/* read from file in, exit if end-of-file */
+local int readmore(file *in)
+{
+    if (readin(in) == 0) bye("unexpected end of ", in->name);
+    return 0;
+}
+
+#define read1(in) (in->left == 0 ? readmore(in) : 0, \
+                   in->left--, *(in->next)++)
+
+/* skip over n bytes of in */
+local void skip(file *in, unsigned n)
+{
+    unsigned bypass;
+
+    if (n > in->left) {
+        n -= in->left;
+        bypass = n & ~((1U << in->size) - 1);
+        if (bypass) {
+            if (lseek(in->fd, (off_t)bypass, SEEK_CUR) == -1)
+                bye("seeking ", in->name);
+            n -= bypass;
+        }
+        readmore(in);
+        if (n > in->left)
+            bye("unexpected end of ", in->name);
+    }
+    in->left -= n;
+    in->next += n;
+}
+
+/* read a four-byte unsigned integer, little-endian, from in */
+unsigned long read4(file *in)
+{
+    unsigned long val;
+
+    val = read1(in);
+    val += (unsigned)read1(in) << 8;
+    val += (unsigned long)read1(in) << 16;
+    val += (unsigned long)read1(in) << 24;
+    return val;
+}
+
+/* skip over gzip header */
+local void gzheader(file *in)
+{
+    int flags;
+    unsigned n;
+
+    if (read1(in) != 31 || read1(in) != 139) bye(in->name, " not a gzip file");
+    if (read1(in) != 8) bye("unknown compression method in", in->name);
+    flags = read1(in);
+    if (flags & 0xe0) bye("unknown header flags set in", in->name);
+    skip(in, 6);
+    if (flags & 4) {
+        n = read1(in);
+        n += (unsigned)(read1(in)) << 8;
+        skip(in, n);
+    }
+    if (flags & 8) while (read1(in) != 0) ;
+    if (flags & 16) while (read1(in) != 0) ;
+    if (flags & 2) skip(in, 2);
+}
+
+/* decompress gzip file "name", return strm with a deflate stream ready to
+   continue compression of the data in the gzip file, and return a file
+   descriptor pointing to where to write the compressed data -- the deflate
+   stream is initialized to compress using level "level" */
+local int gzscan(char *name, z_stream *strm, int level)
+{
+    int ret, lastbit, left, full;
+    unsigned have;
+    unsigned long crc, tot;
+    unsigned char *window;
+    off_t lastoff, end;
+    file gz;
+
+    /* open gzip file */
+    gz.name = name;
+    gz.fd = open(name, O_RDWR, 0);
+    if (gz.fd == -1) bye("cannot open ", name);
+    gz.buf = malloc(CHUNK);
+    if (gz.buf == NULL) bye("out of memory", "");
+    gz.size = LGCHUNK;
+    gz.left = 0;
+
+    /* skip gzip header */
+    gzheader(&gz);
+
+    /* prepare to decompress */
+    window = malloc(DSIZE);
+    if (window == NULL) bye("out of memory", "");
+    strm->zalloc = Z_NULL;
+    strm->zfree = Z_NULL;
+    strm->opaque = Z_NULL;
+    ret = inflateInit2(strm, -15);
+    if (ret != Z_OK) bye("out of memory", " or library mismatch");
+
+    /* decompress the deflate stream, saving append information */
+    lastbit = 0;
+    lastoff = lseek(gz.fd, 0L, SEEK_CUR) - gz.left;
+    left = 0;
+    strm->avail_in = gz.left;
+    strm->next_in = gz.next;
+    crc = crc32(0L, Z_NULL, 0);
+    have = full = 0;
+    do {
+        /* if needed, get more input */
+        if (strm->avail_in == 0) {
+            readmore(&gz);
+            strm->avail_in = gz.left;
+            strm->next_in = gz.next;
+        }
+
+        /* set up output to next available section of sliding window */
+        strm->avail_out = DSIZE - have;
+        strm->next_out = window + have;
+
+        /* inflate and check for errors */
+        ret = inflate(strm, Z_BLOCK);
+        if (ret == Z_STREAM_ERROR) bye("internal stream error!", "");
+        if (ret == Z_MEM_ERROR) bye("out of memory", "");
+        if (ret == Z_DATA_ERROR)
+            bye("invalid compressed data--format violated in", name);
+
+        /* update crc and sliding window pointer */
+        crc = crc32(crc, window + have, DSIZE - have - strm->avail_out);
+        if (strm->avail_out)
+            have = DSIZE - strm->avail_out;
+        else {
+            have = 0;
+            full = 1;
+        }
+
+        /* process end of block */
+        if (strm->data_type & 128) {
+            if (strm->data_type & 64)
+                left = strm->data_type & 0x1f;
+            else {
+                lastbit = strm->data_type & 0x1f;
+                lastoff = lseek(gz.fd, 0L, SEEK_CUR) - strm->avail_in;
+            }
+        }
+    } while (ret != Z_STREAM_END);
+    inflateEnd(strm);
+    gz.left = strm->avail_in;
+    gz.next = strm->next_in;
+
+    /* save the location of the end of the compressed data */
+    end = lseek(gz.fd, 0L, SEEK_CUR) - gz.left;
+
+    /* check gzip trailer and save total for deflate */
+    if (crc != read4(&gz))
+        bye("invalid compressed data--crc mismatch in ", name);
+    tot = strm->total_out;
+    if ((tot & 0xffffffffUL) != read4(&gz))
+        bye("invalid compressed data--length mismatch in", name);
+
+    /* if not at end of file, warn */
+    if (gz.left || readin(&gz))
+        fprintf(stderr,
+            "gzappend warning: junk at end of gzip file overwritten\n");
+
+    /* clear last block bit */
+    lseek(gz.fd, lastoff - (lastbit != 0), SEEK_SET);
+    if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name);
+    *gz.buf = (unsigned char)(*gz.buf ^ (1 << ((8 - lastbit) & 7)));
+    lseek(gz.fd, -1L, SEEK_CUR);
+    if (write(gz.fd, gz.buf, 1) != 1) bye("writing after seek to ", name);
+
+    /* if window wrapped, build dictionary from window by rotating */
+    if (full) {
+        rotate(window, DSIZE, have);
+        have = DSIZE;
+    }
+
+    /* set up deflate stream with window, crc, total_in, and leftover bits */
+    ret = deflateInit2(strm, level, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
+    if (ret != Z_OK) bye("out of memory", "");
+    deflateSetDictionary(strm, window, have);
+    strm->adler = crc;
+    strm->total_in = tot;
+    if (left) {
+        lseek(gz.fd, --end, SEEK_SET);
+        if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name);
+        deflatePrime(strm, 8 - left, *gz.buf);
+    }
+    lseek(gz.fd, end, SEEK_SET);
+
+    /* clean up and return */
+    free(window);
+    free(gz.buf);
+    return gz.fd;
+}
+
+/* append file "name" to gzip file gd using deflate stream strm -- if last
+   is true, then finish off the deflate stream at the end */
+local void gztack(char *name, int gd, z_stream *strm, int last)
+{
+    int fd, len, ret;
+    unsigned left;
+    unsigned char *in, *out;
+
+    /* open file to compress and append */
+    fd = 0;
+    if (name != NULL) {
+        fd = open(name, O_RDONLY, 0);
+        if (fd == -1)
+            fprintf(stderr, "gzappend warning: %s not found, skipping ...\n",
+                    name);
+    }
+
+    /* allocate buffers */
+    in = fd == -1 ? NULL : malloc(CHUNK);
+    out = malloc(CHUNK);
+    if (out == NULL) bye("out of memory", "");
+
+    /* compress input file and append to gzip file */
+    do {
+        /* get more input */
+        len = fd == -1 ? 0 : read(fd, in, CHUNK);
+        if (len == -1) {
+            fprintf(stderr,
+                    "gzappend warning: error reading %s, skipping rest ...\n",
+                    name);
+            len = 0;
+        }
+        strm->avail_in = (unsigned)len;
+        strm->next_in = in;
+        if (len) strm->adler = crc32(strm->adler, in, (unsigned)len);
+
+        /* compress and write all available output */
+        do {
+            strm->avail_out = CHUNK;
+            strm->next_out = out;
+            ret = deflate(strm, last && len == 0 ? Z_FINISH : Z_NO_FLUSH);
+            left = CHUNK - strm->avail_out;
+            while (left) {
+                len = write(gd, out + CHUNK - strm->avail_out - left, left);
+                if (len == -1) bye("writing gzip file", "");
+                left -= (unsigned)len;
+            }
+        } while (strm->avail_out == 0 && ret != Z_STREAM_END);
+    } while (len != 0);
+
+    /* write trailer after last entry */
+    if (last) {
+        deflateEnd(strm);
+        out[0] = (unsigned char)(strm->adler);
+        out[1] = (unsigned char)(strm->adler >> 8);
+        out[2] = (unsigned char)(strm->adler >> 16);
+        out[3] = (unsigned char)(strm->adler >> 24);
+        out[4] = (unsigned char)(strm->total_in);
+        out[5] = (unsigned char)(strm->total_in >> 8);
+        out[6] = (unsigned char)(strm->total_in >> 16);
+        out[7] = (unsigned char)(strm->total_in >> 24);
+        len = 8;
+        do {
+            ret = write(gd, out + 8 - len, len);
+            if (ret == -1) bye("writing gzip file", "");
+            len -= ret;
+        } while (len);
+        close(gd);
+    }
+
+    /* clean up and return */
+    free(out);
+    if (in != NULL) free(in);
+    if (fd > 0) close(fd);
+}
+
+/* process the compression level option if present, scan the gzip file, and
+   append the specified files, or append the data from stdin if no other file
+   names are provided on the command line -- the gzip file must be writable
+   and seekable */
+int main(int argc, char **argv)
+{
+    int gd, level;
+    z_stream strm;
+
+    /* ignore command name */
+    argv++;
+
+    /* provide usage if no arguments */
+    if (*argv == NULL) {
+        printf("gzappend 1.1 (4 Nov 2003) Copyright (C) 2003 Mark Adler\n");
+        printf(
+            "usage: gzappend [-level] file.gz [ addthis [ andthis ... ]]\n");
+        return 0;
+    }
+
+    /* set compression level */
+    level = Z_DEFAULT_COMPRESSION;
+    if (argv[0][0] == '-') {
+        if (argv[0][1] < '0' || argv[0][1] > '9' || argv[0][2] != 0)
+            bye("invalid compression level", "");
+        level = argv[0][1] - '0';
+        if (*++argv == NULL) bye("no gzip file name after options", "");
+    }
+
+    /* prepare to append to gzip file */
+    gd = gzscan(*argv++, &strm, level);
+
+    /* append files on command line, or from stdin if none */
+    if (*argv == NULL)
+        gztack(NULL, gd, &strm, 1);
+    else
+        do {
+            gztack(*argv, gd, &strm, argv[1] == NULL);
+        } while (*++argv != NULL);
+    return 0;
+}
Index: /trunk/minix/lib/zlib-1.2.3/examples/gzjoin.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/examples/gzjoin.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/examples/gzjoin.c	(revision 9)
@@ -0,0 +1,448 @@
+/* gzjoin -- command to join gzip files into one gzip file
+
+  Copyright (C) 2004 Mark Adler, all rights reserved
+  version 1.0, 11 Dec 2004
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the author be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Mark Adler    madler@alumni.caltech.edu
+ */
+
+/*
+ * Change history:
+ *
+ * 1.0  11 Dec 2004     - First version
+ * 1.1  12 Jun 2005     - Changed ssize_t to long for portability
+ */
+
+/*
+   gzjoin takes one or more gzip files on the command line and writes out a
+   single gzip file that will uncompress to the concatenation of the
+   uncompressed data from the individual gzip files.  gzjoin does this without
+   having to recompress any of the data and without having to calculate a new
+   crc32 for the concatenated uncompressed data.  gzjoin does however have to
+   decompress all of the input data in order to find the bits in the compressed
+   data that need to be modified to concatenate the streams.
+
+   gzjoin does not do an integrity check on the input gzip files other than
+   checking the gzip header and decompressing the compressed data.  They are
+   otherwise assumed to be complete and correct.
+
+   Each joint between gzip files removes at least 18 bytes of previous trailer
+   and subsequent header, and inserts an average of about three bytes to the
+   compressed data in order to connect the streams.  The output gzip file
+   has a minimal ten-byte gzip header with no file name or modification time.
+
+   This program was written to illustrate the use of the Z_BLOCK option of
+   inflate() and the crc32_combine() function.  gzjoin will not compile with
+   versions of zlib earlier than 1.2.3.
+ */
+
+#include <stdio.h>      /* fputs(), fprintf(), fwrite(), putc() */
+#include <stdlib.h>     /* exit(), malloc(), free() */
+#include <fcntl.h>      /* open() */
+#include <unistd.h>     /* close(), read(), lseek() */
+#include "zlib.h"
+    /* crc32(), crc32_combine(), inflateInit2(), inflate(), inflateEnd() */
+
+#define local static
+
+/* exit with an error (return a value to allow use in an expression) */
+local int bail(char *why1, char *why2)
+{
+    fprintf(stderr, "gzjoin error: %s%s, output incomplete\n", why1, why2);
+    exit(1);
+    return 0;
+}
+
+/* -- simple buffered file input with access to the buffer -- */
+
+#define CHUNK 32768         /* must be a power of two and fit in unsigned */
+
+/* bin buffered input file type */
+typedef struct {
+    char *name;             /* name of file for error messages */
+    int fd;                 /* file descriptor */
+    unsigned left;          /* bytes remaining at next */
+    unsigned char *next;    /* next byte to read */
+    unsigned char *buf;     /* allocated buffer of length CHUNK */
+} bin;
+
+/* close a buffered file and free allocated memory */
+local void bclose(bin *in)
+{
+    if (in != NULL) {
+        if (in->fd != -1)
+            close(in->fd);
+        if (in->buf != NULL)
+            free(in->buf);
+        free(in);
+    }
+}
+
+/* open a buffered file for input, return a pointer to type bin, or NULL on
+   failure */
+local bin *bopen(char *name)
+{
+    bin *in;
+
+    in = malloc(sizeof(bin));
+    if (in == NULL)
+        return NULL;
+    in->buf = malloc(CHUNK);
+    in->fd = open(name, O_RDONLY, 0);
+    if (in->buf == NULL || in->fd == -1) {
+        bclose(in);
+        return NULL;
+    }
+    in->left = 0;
+    in->next = in->buf;
+    in->name = name;
+    return in;
+}
+
+/* load buffer from file, return -1 on read error, 0 or 1 on success, with
+   1 indicating that end-of-file was reached */
+local int bload(bin *in)
+{
+    long len;
+
+    if (in == NULL)
+        return -1;
+    if (in->left != 0)
+        return 0;
+    in->next = in->buf;
+    do {
+        len = (long)read(in->fd, in->buf + in->left, CHUNK - in->left);
+        if (len < 0)
+            return -1;
+        in->left += (unsigned)len;
+    } while (len != 0 && in->left < CHUNK);
+    return len == 0 ? 1 : 0;
+}
+
+/* get a byte from the file, bail if end of file */
+#define bget(in) (in->left ? 0 : bload(in), \
+                  in->left ? (in->left--, *(in->next)++) : \
+                    bail("unexpected end of file on ", in->name))
+
+/* get a four-byte little-endian unsigned integer from file */
+local unsigned long bget4(bin *in)
+{
+    unsigned long val;
+
+    val = bget(in);
+    val += (unsigned long)(bget(in)) << 8;
+    val += (unsigned long)(bget(in)) << 16;
+    val += (unsigned long)(bget(in)) << 24;
+    return val;
+}
+
+/* skip bytes in file */
+local void bskip(bin *in, unsigned skip)
+{
+    /* check pointer */
+    if (in == NULL)
+        return;
+
+    /* easy case -- skip bytes in buffer */
+    if (skip <= in->left) {
+        in->left -= skip;
+        in->next += skip;
+        return;
+    }
+
+    /* skip what's in buffer, discard buffer contents */
+    skip -= in->left;
+    in->left = 0;
+
+    /* seek past multiples of CHUNK bytes */
+    if (skip > CHUNK) {
+        unsigned left;
+
+        left = skip & (CHUNK - 1);
+        if (left == 0) {
+            /* exact number of chunks: seek all the way minus one byte to check
+               for end-of-file with a read */
+            lseek(in->fd, skip - 1, SEEK_CUR);
+            if (read(in->fd, in->buf, 1) != 1)
+                bail("unexpected end of file on ", in->name);
+            return;
+        }
+
+        /* skip the integral chunks, update skip with remainder */
+        lseek(in->fd, skip - left, SEEK_CUR);
+        skip = left;
+    }
+
+    /* read more input and skip remainder */
+    bload(in);
+    if (skip > in->left)
+        bail("unexpected end of file on ", in->name);
+    in->left -= skip;
+    in->next += skip;
+}
+
+/* -- end of buffered input functions -- */
+
+/* skip the gzip header from file in */
+local void gzhead(bin *in)
+{
+    int flags;
+
+    /* verify gzip magic header and compression method */
+    if (bget(in) != 0x1f || bget(in) != 0x8b || bget(in) != 8)
+        bail(in->name, " is not a valid gzip file");
+
+    /* get and verify flags */
+    flags = bget(in);
+    if ((flags & 0xe0) != 0)
+        bail("unknown reserved bits set in ", in->name);
+
+    /* skip modification time, extra flags, and os */
+    bskip(in, 6);
+
+    /* skip extra field if present */
+    if (flags & 4) {
+        unsigned len;
+
+        len = bget(in);
+        len += (unsigned)(bget(in)) << 8;
+        bskip(in, len);
+    }
+
+    /* skip file name if present */
+    if (flags & 8)
+        while (bget(in) != 0)
+            ;
+
+    /* skip comment if present */
+    if (flags & 16)
+        while (bget(in) != 0)
+            ;
+
+    /* skip header crc if present */
+    if (flags & 2)
+        bskip(in, 2);
+}
+
+/* write a four-byte little-endian unsigned integer to out */
+local void put4(unsigned long val, FILE *out)
+{
+    putc(val & 0xff, out);
+    putc((val >> 8) & 0xff, out);
+    putc((val >> 16) & 0xff, out);
+    putc((val >> 24) & 0xff, out);
+}
+
+/* Load up zlib stream from buffered input, bail if end of file */
+local void zpull(z_streamp strm, bin *in)
+{
+    if (in->left == 0)
+        bload(in);
+    if (in->left == 0)
+        bail("unexpected end of file on ", in->name);
+    strm->avail_in = in->left;
+    strm->next_in = in->next;
+}
+
+/* Write header for gzip file to out and initialize trailer. */
+local void gzinit(unsigned long *crc, unsigned long *tot, FILE *out)
+{
+    fwrite("\x1f\x8b\x08\0\0\0\0\0\0\xff", 1, 10, out);
+    *crc = crc32(0L, Z_NULL, 0);
+    *tot = 0;
+}
+
+/* Copy the compressed data from name, zeroing the last block bit of the last
+   block if clr is true, and adding empty blocks as needed to get to a byte
+   boundary.  If clr is false, then the last block becomes the last block of
+   the output, and the gzip trailer is written.  crc and tot maintains the
+   crc and length (modulo 2^32) of the output for the trailer.  The resulting
+   gzip file is written to out.  gzinit() must be called before the first call
+   of gzcopy() to write the gzip header and to initialize crc and tot. */
+local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot,
+                  FILE *out)
+{
+    int ret;                /* return value from zlib functions */
+    int pos;                /* where the "last block" bit is in byte */
+    int last;               /* true if processing the last block */
+    bin *in;                /* buffered input file */
+    unsigned char *start;   /* start of compressed data in buffer */
+    unsigned char *junk;    /* buffer for uncompressed data -- discarded */
+    z_off_t len;            /* length of uncompressed data (support > 4 GB) */
+    z_stream strm;          /* zlib inflate stream */
+
+    /* open gzip file and skip header */
+    in = bopen(name);
+    if (in == NULL)
+        bail("could not open ", name);
+    gzhead(in);
+
+    /* allocate buffer for uncompressed data and initialize raw inflate
+       stream */
+    junk = malloc(CHUNK);
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    strm.avail_in = 0;
+    strm.next_in = Z_NULL;
+    ret = inflateInit2(&strm, -15);
+    if (junk == NULL || ret != Z_OK)
+        bail("out of memory", "");
+
+    /* inflate and copy compressed data, clear last-block bit if requested */
+    len = 0;
+    zpull(&strm, in);
+    start = strm.next_in;
+    last = start[0] & 1;
+    if (last && clr)
+        start[0] &= ~1;
+    strm.avail_out = 0;
+    for (;;) {
+        /* if input used and output done, write used input and get more */
+        if (strm.avail_in == 0 && strm.avail_out != 0) {
+            fwrite(start, 1, strm.next_in - start, out);
+            start = in->buf;
+            in->left = 0;
+            zpull(&strm, in);
+        }
+
+        /* decompress -- return early when end-of-block reached */
+        strm.avail_out = CHUNK;
+        strm.next_out = junk;
+        ret = inflate(&strm, Z_BLOCK);
+        switch (ret) {
+        case Z_MEM_ERROR:
+            bail("out of memory", "");
+        case Z_DATA_ERROR:
+            bail("invalid compressed data in ", in->name);
+        }
+
+        /* update length of uncompressed data */
+        len += CHUNK - strm.avail_out;
+
+        /* check for block boundary (only get this when block copied out) */
+        if (strm.data_type & 128) {
+            /* if that was the last block, then done */
+            if (last)
+                break;
+
+            /* number of unused bits in last byte */
+            pos = strm.data_type & 7;
+
+            /* find the next last-block bit */
+            if (pos != 0) {
+                /* next last-block bit is in last used byte */
+                pos = 0x100 >> pos;
+                last = strm.next_in[-1] & pos;
+                if (last && clr)
+                    strm.next_in[-1] &= ~pos;
+            }
+            else {
+                /* next last-block bit is in next unused byte */
+                if (strm.avail_in == 0) {
+                    /* don't have that byte yet -- get it */
+                    fwrite(start, 1, strm.next_in - start, out);
+                    start = in->buf;
+                    in->left = 0;
+                    zpull(&strm, in);
+                }
+                last = strm.next_in[0] & 1;
+                if (last && clr)
+                    strm.next_in[0] &= ~1;
+            }
+        }
+    }
+
+    /* update buffer with unused input */
+    in->left = strm.avail_in;
+    in->next = strm.next_in;
+
+    /* copy used input, write empty blocks to get to byte boundary */
+    pos = strm.data_type & 7;
+    fwrite(start, 1, in->next - start - 1, out);
+    last = in->next[-1];
+    if (pos == 0 || !clr)
+        /* already at byte boundary, or last file: write last byte */
+        putc(last, out);
+    else {
+        /* append empty blocks to last byte */
+        last &= ((0x100 >> pos) - 1);       /* assure unused bits are zero */
+        if (pos & 1) {
+            /* odd -- append an empty stored block */
+            putc(last, out);
+            if (pos == 1)
+                putc(0, out);               /* two more bits in block header */
+            fwrite("\0\0\xff\xff", 1, 4, out);
+        }
+        else {
+            /* even -- append 1, 2, or 3 empty fixed blocks */
+            switch (pos) {
+            case 6:
+                putc(last | 8, out);
+                last = 0;
+            case 4:
+                putc(last | 0x20, out);
+                last = 0;
+            case 2:
+                putc(last | 0x80, out);
+                putc(0, out);
+            }
+        }
+    }
+
+    /* update crc and tot */
+    *crc = crc32_combine(*crc, bget4(in), len);
+    *tot += (unsigned long)len;
+
+    /* clean up */
+    inflateEnd(&strm);
+    free(junk);
+    bclose(in);
+
+    /* write trailer if this is the last gzip file */
+    if (!clr) {
+        put4(*crc, out);
+        put4(*tot, out);
+    }
+}
+
+/* join the gzip files on the command line, write result to stdout */
+int main(int argc, char **argv)
+{
+    unsigned long crc, tot;     /* running crc and total uncompressed length */
+
+    /* skip command name */
+    argc--;
+    argv++;
+
+    /* show usage if no arguments */
+    if (argc == 0) {
+        fputs("gzjoin usage: gzjoin f1.gz [f2.gz [f3.gz ...]] > fjoin.gz\n",
+              stderr);
+        return 0;
+    }
+
+    /* join gzip files on command line and write to stdout */
+    gzinit(&crc, &tot, stdout);
+    while (argc--)
+        gzcopy(*argv++, argc, &crc, &tot, stdout);
+
+    /* done */
+    return 0;
+}
Index: /trunk/minix/lib/zlib-1.2.3/examples/gzlog.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/examples/gzlog.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/examples/gzlog.c	(revision 9)
@@ -0,0 +1,413 @@
+/*
+ * gzlog.c
+ * Copyright (C) 2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in gzlog.h
+ * version 1.0, 26 Nov 2004
+ *
+ */
+
+#include <string.h>             /* memcmp() */
+#include <stdlib.h>             /* malloc(), free(), NULL */
+#include <sys/types.h>          /* size_t, off_t */
+#include <unistd.h>             /* read(), close(), sleep(), ftruncate(), */
+                                /* lseek() */
+#include <fcntl.h>              /* open() */
+#include <sys/file.h>           /* flock() */
+#include "zlib.h"               /* deflateInit2(), deflate(), deflateEnd() */
+
+#include "gzlog.h"              /* interface */
+#define local static
+
+/* log object structure */
+typedef struct {
+    int id;                 /* object identifier */
+    int fd;                 /* log file descriptor */
+    off_t extra;            /* offset of extra "ap" subfield */
+    off_t mark_off;         /* offset of marked data */
+    off_t last_off;         /* offset of last block */
+    unsigned long crc;      /* uncompressed crc */
+    unsigned long len;      /* uncompressed length (modulo 2^32) */
+    unsigned stored;        /* length of current stored block */
+} gz_log;
+
+#define GZLOGID 19334       /* gz_log object identifier */
+
+#define LOCK_RETRY 1            /* retry lock once a second */
+#define LOCK_PATIENCE 1200      /* try about twenty minutes before forcing */
+
+/* acquire a lock on a file */
+local int lock(int fd)
+{
+    int patience;
+
+    /* try to lock every LOCK_RETRY seconds for LOCK_PATIENCE seconds */
+    patience = LOCK_PATIENCE;
+    do {
+        if (flock(fd, LOCK_EX + LOCK_NB) == 0)
+            return 0;
+        (void)sleep(LOCK_RETRY);
+        patience -= LOCK_RETRY;
+    } while (patience > 0);
+
+    /* we've run out of patience -- give up */
+    return -1;
+}
+
+/* release lock */
+local void unlock(int fd)
+{
+    (void)flock(fd, LOCK_UN);
+}
+
+/* release a log object */
+local void log_clean(gz_log *log)
+{
+    unlock(log->fd);
+    (void)close(log->fd);
+    free(log);
+}
+
+/* read an unsigned long from a byte buffer little-endian */
+local unsigned long make_ulg(unsigned char *buf)
+{
+    int n;
+    unsigned long val;
+
+    val = (unsigned long)(*buf++);
+    for (n = 8; n < 32; n += 8)
+        val += (unsigned long)(*buf++) << n;
+    return val;
+}
+
+/* read an off_t from a byte buffer little-endian */
+local off_t make_off(unsigned char *buf)
+{
+    int n;
+    off_t val;
+
+    val = (off_t)(*buf++);
+    for (n = 8; n < 64; n += 8)
+        val += (off_t)(*buf++) << n;
+    return val;
+}
+
+/* write an unsigned long little-endian to byte buffer */
+local void dice_ulg(unsigned long val, unsigned char *buf)
+{
+    int n;
+
+    for (n = 0; n < 4; n++) {
+        *buf++ = val & 0xff;
+        val >>= 8;
+    }
+}
+
+/* write an off_t little-endian to byte buffer */
+local void dice_off(off_t val, unsigned char *buf)
+{
+    int n;
+
+    for (n = 0; n < 8; n++) {
+        *buf++ = val & 0xff;
+        val >>= 8;
+    }
+}
+
+/* initial, empty gzip file for appending */
+local char empty_gz[] = {
+    0x1f, 0x8b,                 /* magic gzip id */
+    8,                          /* compression method is deflate */
+    4,                          /* there is an extra field */
+    0, 0, 0, 0,                 /* no modification time provided */
+    0, 0xff,                    /* no extra flags, no OS */
+    20, 0, 'a', 'p', 16, 0,     /* extra field with "ap" subfield */
+    32, 0, 0, 0, 0, 0, 0, 0,    /* offset of uncompressed data */
+    32, 0, 0, 0, 0, 0, 0, 0,    /* offset of last block */
+    1, 0, 0, 0xff, 0xff,        /* empty stored block (last) */
+    0, 0, 0, 0,                 /* crc */
+    0, 0, 0, 0                  /* uncompressed length */
+};
+
+/* initialize a log object with locking */
+void *gzlog_open(char *path)
+{
+    unsigned xlen;
+    unsigned char temp[20];
+    unsigned sub_len;
+    int good;
+    gz_log *log;
+
+    /* allocate log structure */
+    log = malloc(sizeof(gz_log));
+    if (log == NULL)
+        return NULL;
+    log->id = GZLOGID;
+
+    /* open file, creating it if necessary, and locking it */
+    log->fd = open(path, O_RDWR | O_CREAT, 0600);
+    if (log->fd < 0) {
+        free(log);
+        return NULL;
+    }
+    if (lock(log->fd)) {
+        close(log->fd);
+        free(log);
+        return NULL;
+    }
+
+    /* if file is empty, write new gzip stream */
+    if (lseek(log->fd, 0, SEEK_END) == 0) {
+        if (write(log->fd, empty_gz, sizeof(empty_gz)) != sizeof(empty_gz)) {
+            log_clean(log);
+            return NULL;
+        }
+    }
+
+    /* check gzip header */
+    (void)lseek(log->fd, 0, SEEK_SET);
+    if (read(log->fd, temp, 12) != 12 || temp[0] != 0x1f ||
+        temp[1] != 0x8b || temp[2] != 8 || (temp[3] & 4) == 0) {
+        log_clean(log);
+        return NULL;
+    }
+
+    /* process extra field to find "ap" sub-field */
+    xlen = temp[10] + (temp[11] << 8);
+    good = 0;
+    while (xlen) {
+        if (xlen < 4 || read(log->fd, temp, 4) != 4)
+            break;
+        sub_len = temp[2];
+        sub_len += temp[3] << 8;
+        xlen -= 4;
+        if (memcmp(temp, "ap", 2) == 0 && sub_len == 16) {
+            good = 1;
+            break;
+        }
+        if (xlen < sub_len)
+            break;
+        (void)lseek(log->fd, sub_len, SEEK_CUR);
+        xlen -= sub_len;
+    }
+    if (!good) {
+        log_clean(log);
+        return NULL;
+    }
+
+    /* read in "ap" sub-field */
+    log->extra = lseek(log->fd, 0, SEEK_CUR);
+    if (read(log->fd, temp, 16) != 16) {
+        log_clean(log);
+        return NULL;
+    }
+    log->mark_off = make_off(temp);
+    log->last_off = make_off(temp + 8);
+
+    /* get crc, length of gzip file */
+    (void)lseek(log->fd, log->last_off, SEEK_SET);
+    if (read(log->fd, temp, 13) != 13 ||
+        memcmp(temp, "\001\000\000\377\377", 5) != 0) {
+        log_clean(log);
+        return NULL;
+    }
+    log->crc = make_ulg(temp + 5);
+    log->len = make_ulg(temp + 9);
+
+    /* set up to write over empty last block */
+    (void)lseek(log->fd, log->last_off + 5, SEEK_SET);
+    log->stored = 0;
+    return (void *)log;
+}
+
+/* maximum amount to put in a stored block before starting a new one */
+#define MAX_BLOCK 16384
+
+/* write a block to a log object */
+int gzlog_write(void *obj, char *data, size_t len)
+{
+    size_t some;
+    unsigned char temp[5];
+    gz_log *log;
+
+    /* check object */
+    log = (gz_log *)obj;
+    if (log == NULL || log->id != GZLOGID)
+        return 1;
+
+    /* write stored blocks until all of the input is written */
+    do {
+        some = MAX_BLOCK - log->stored;
+        if (some > len)
+            some = len;
+        if (write(log->fd, data, some) != some)
+            return 1;
+        log->crc = crc32(log->crc, data, some);
+        log->len += some;
+        len -= some;
+        data += some;
+        log->stored += some;
+
+        /* if the stored block is full, end it and start another */
+        if (log->stored == MAX_BLOCK) {
+            (void)lseek(log->fd, log->last_off, SEEK_SET);
+            temp[0] = 0;
+            dice_ulg(log->stored + ((unsigned long)(~log->stored) << 16),
+                     temp + 1);
+            if (write(log->fd, temp, 5) != 5)
+                return 1;
+            log->last_off = lseek(log->fd, log->stored, SEEK_CUR);
+            (void)lseek(log->fd, 5, SEEK_CUR);
+            log->stored = 0;
+        }
+    } while (len);
+    return 0;
+}
+
+/* recompress the remaining stored deflate data in place */
+local int recomp(gz_log *log)
+{
+    z_stream strm;
+    size_t len, max;
+    unsigned char *in;
+    unsigned char *out;
+    unsigned char temp[16];
+
+    /* allocate space and read it all in (it's around 1 MB) */
+    len = log->last_off - log->mark_off;
+    max = len + (len >> 12) + (len >> 14) + 11;
+    out = malloc(max);
+    if (out == NULL)
+        return 1;
+    in = malloc(len);
+    if (in == NULL) {
+        free(out);
+        return 1;
+    }
+    (void)lseek(log->fd, log->mark_off, SEEK_SET);
+    if (read(log->fd, in, len) != len) {
+        free(in);
+        free(out);
+        return 1;
+    }
+
+    /* recompress in memory, decoding stored data as we go */
+    /* note: this assumes that unsigned is four bytes or more */
+    /*       consider not making that assumption */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    if (deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, -15, 8,
+        Z_DEFAULT_STRATEGY) != Z_OK) {
+        free(in);
+        free(out);
+        return 1;
+    }
+    strm.next_in = in;
+    strm.avail_out = max;
+    strm.next_out = out;
+    while (len >= 5) {
+        if (strm.next_in[0] != 0)
+            break;
+        strm.avail_in = strm.next_in[1] + (strm.next_in[2] << 8);
+        strm.next_in += 5;
+        len -= 5;
+        if (strm.avail_in != 0) {
+            if (len < strm.avail_in)
+                break;
+            len -= strm.avail_in;
+            (void)deflate(&strm, Z_NO_FLUSH);
+            if (strm.avail_in != 0 || strm.avail_out == 0)
+                break;
+        }
+    }
+    (void)deflate(&strm, Z_SYNC_FLUSH);
+    (void)deflateEnd(&strm);
+    free(in);
+    if (len != 0 || strm.avail_out == 0) {
+        free(out);
+        return 1;
+    }
+
+    /* overwrite stored data with compressed data */
+    (void)lseek(log->fd, log->mark_off, SEEK_SET);
+    len = max - strm.avail_out;
+    if (write(log->fd, out, len) != len) {
+        free(out);
+        return 1;
+    }
+    free(out);
+
+    /* write last empty block, crc, and length */
+    log->mark_off = log->last_off = lseek(log->fd, 0, SEEK_CUR);
+    temp[0] = 1;
+    dice_ulg(0xffffL << 16, temp + 1);
+    dice_ulg(log->crc, temp + 5);
+    dice_ulg(log->len, temp + 9);
+    if (write(log->fd, temp, 13) != 13)
+        return 1;
+
+    /* truncate file to discard remaining stored data and old trailer */
+    ftruncate(log->fd, lseek(log->fd, 0, SEEK_CUR));
+
+    /* update extra field to point to new last empty block */
+    (void)lseek(log->fd, log->extra, SEEK_SET);
+    dice_off(log->mark_off, temp);
+    dice_off(log->last_off, temp + 8);
+    if (write(log->fd, temp, 16) != 16)
+        return 1;
+    return 0;
+}
+
+/* maximum accumulation of stored blocks before compressing */
+#define MAX_STORED 1048576
+
+/* close log object */
+int gzlog_close(void *obj)
+{
+    unsigned char temp[8];
+    gz_log *log;
+
+    /* check object */
+    log = (gz_log *)obj;
+    if (log == NULL || log->id != GZLOGID)
+        return 1;
+
+    /* go to start of most recent block being written */
+    (void)lseek(log->fd, log->last_off, SEEK_SET);
+
+    /* if some stuff was put there, update block */
+    if (log->stored) {
+        temp[0] = 0;
+        dice_ulg(log->stored + ((unsigned long)(~log->stored) << 16),
+                 temp + 1);
+        if (write(log->fd, temp, 5) != 5)
+            return 1;
+        log->last_off = lseek(log->fd, log->stored, SEEK_CUR);
+    }
+
+    /* write last block (empty) */
+    if (write(log->fd, "\001\000\000\377\377", 5) != 5)
+        return 1;
+
+    /* write updated crc and uncompressed length */
+    dice_ulg(log->crc, temp);
+    dice_ulg(log->len, temp + 4);
+    if (write(log->fd, temp, 8) != 8)
+        return 1;
+
+    /* put offset of that last block in gzip extra block */
+    (void)lseek(log->fd, log->extra + 8, SEEK_SET);
+    dice_off(log->last_off, temp);
+    if (write(log->fd, temp, 8) != 8)
+        return 1;
+
+    /* if more than 1 MB stored, then time to compress it */
+    if (log->last_off - log->mark_off > MAX_STORED) {
+        if (recomp(log))
+            return 1;
+    }
+
+    /* unlock and close file */
+    log_clean(log);
+    return 0;
+}
Index: /trunk/minix/lib/zlib-1.2.3/examples/gzlog.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/examples/gzlog.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/examples/gzlog.h	(revision 9)
@@ -0,0 +1,58 @@
+/* gzlog.h
+  Copyright (C) 2004 Mark Adler, all rights reserved
+  version 1.0, 26 Nov 2004
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the author be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Mark Adler    madler@alumni.caltech.edu
+ */
+
+/*
+   The gzlog object allows writing short messages to a gzipped log file,
+   opening the log file locked for small bursts, and then closing it.  The log
+   object works by appending stored data to the gzip file until 1 MB has been
+   accumulated.  At that time, the stored data is compressed, and replaces the
+   uncompressed data in the file.  The log file is truncated to its new size at
+   that time.  After closing, the log file is always valid gzip file that can
+   decompressed to recover what was written.
+
+   A gzip header "extra" field contains two file offsets for appending.  The
+   first points to just after the last compressed data.  The second points to
+   the last stored block in the deflate stream, which is empty.  All of the
+   data between those pointers is uncompressed.
+ */
+
+/* Open a gzlog object, creating the log file if it does not exist.  Return
+   NULL on error.  Note that gzlog_open() could take a long time to return if
+   there is difficulty in locking the file. */
+void *gzlog_open(char *path);
+
+/* Write to a gzlog object.  Return non-zero on error.  This function will
+   simply write data to the file uncompressed.  Compression of the data
+   will not occur until gzlog_close() is called.  It is expected that
+   gzlog_write() is used for a short message, and then gzlog_close() is
+   called.  If a large amount of data is to be written, then the application
+   should write no more than 1 MB at a time with gzlog_write() before
+   calling gzlog_close() and then gzlog_open() again. */
+int gzlog_write(void *log, char *data, size_t len);
+
+/* Close a gzlog object.  Return non-zero on error.  The log file is locked
+   until this function is called.  This function will compress stored data
+   at the end of the gzip file if at least 1 MB has been accumulated.  Note
+   that the file will not be a valid gzip file until this function completes.
+ */
+int gzlog_close(void *log);
Index: /trunk/minix/lib/zlib-1.2.3/examples/zlib_how.html
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/examples/zlib_how.html	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/examples/zlib_how.html	(revision 9)
@@ -0,0 +1,523 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
+  "http://www.w3.org/TR/REC-html40/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>zlib Usage Example</title>
+<!--  Copyright (c) 2004 Mark Adler.  -->
+</head>
+<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#00A000">
+<h2 align="center"> zlib Usage Example </h2>
+We often get questions about how the <tt>deflate()</tt> and <tt>inflate()</tt> functions should be used.
+Users wonder when they should provide more input, when they should use more output,
+what to do with a <tt>Z_BUF_ERROR</tt>, how to make sure the process terminates properly, and
+so on.  So for those who have read <tt>zlib.h</tt> (a few times), and
+would like further edification, below is an annotated example in C of simple routines to compress and decompress
+from an input file to an output file using <tt>deflate()</tt> and <tt>inflate()</tt> respectively.  The
+annotations are interspersed between lines of the code.  So please read between the lines.
+We hope this helps explain some of the intricacies of <em>zlib</em>.
+<p>
+Without further adieu, here is the program <a href="zpipe.c"><tt>zpipe.c</tt></a>:
+<pre><b>
+/* zpipe.c: example of proper use of zlib's inflate() and deflate()
+   Not copyrighted -- provided to the public domain
+   Version 1.2  9 November 2004  Mark Adler */
+
+/* Version history:
+   1.0  30 Oct 2004  First version
+   1.1   8 Nov 2004  Add void casting for unused return values
+                     Use switch statement for inflate() return values
+   1.2   9 Nov 2004  Add assertions to document zlib guarantees
+ */
+</b></pre><!-- -->
+We now include the header files for the required definitions.  From
+<tt>stdio.h</tt> we use <tt>fopen()</tt>, <tt>fread()</tt>, <tt>fwrite()</tt>,
+<tt>feof()</tt>, <tt>ferror()</tt>, and <tt>fclose()</tt> for file i/o, and
+<tt>fputs()</tt> for error messages.  From <tt>string.h</tt> we use
+<tt>strcmp()</tt> for command line argument processing.
+From <tt>assert.h</tt> we use the <tt>assert()</tt> macro.
+From <tt>zlib.h</tt>
+we use the basic compression functions <tt>deflateInit()</tt>,
+<tt>deflate()</tt>, and <tt>deflateEnd()</tt>, and the basic decompression
+functions <tt>inflateInit()</tt>, <tt>inflate()</tt>, and
+<tt>inflateEnd()</tt>.
+<pre><b>
+#include &lt;stdio.h&gt;
+#include &lt;string.h&gt;
+#include &lt;assert.h&gt;
+#include "zlib.h"
+</b></pre><!-- -->
+<tt>CHUNK</tt> is simply the buffer size for feeding data to and pulling data
+from the <em>zlib</em> routines.  Larger buffer sizes would be more efficient,
+especially for <tt>inflate()</tt>.  If the memory is available, buffers sizes
+on the order of 128K or 256K bytes should be used.
+<pre><b>
+#define CHUNK 16384
+</b></pre><!-- -->
+The <tt>def()</tt> routine compresses data from an input file to an output file.  The output data
+will be in the <em>zlib</em> format, which is different from the <em>gzip</em> or <em>zip</em>
+formats.  The <em>zlib</em> format has a very small header of only two bytes to identify it as
+a <em>zlib</em> stream and to provide decoding information, and a four-byte trailer with a fast
+check value to verify the integrity of the uncompressed data after decoding.
+<pre><b>
+/* Compress from file source to file dest until EOF on source.
+   def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+   allocated for processing, Z_STREAM_ERROR if an invalid compression
+   level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
+   version of the library linked do not match, or Z_ERRNO if there is
+   an error reading or writing the files. */
+int def(FILE *source, FILE *dest, int level)
+{
+</b></pre>
+Here are the local variables for <tt>def()</tt>.  <tt>ret</tt> will be used for <em>zlib</em>
+return codes.  <tt>flush</tt> will keep track of the current flushing state for <tt>deflate()</tt>,
+which is either no flushing, or flush to completion after the end of the input file is reached.
+<tt>have</tt> is the amount of data returned from <tt>deflate()</tt>.  The <tt>strm</tt> structure
+is used to pass information to and from the <em>zlib</em> routines, and to maintain the
+<tt>deflate()</tt> state.  <tt>in</tt> and <tt>out</tt> are the input and output buffers for
+<tt>deflate()</tt>.
+<pre><b>
+    int ret, flush;
+    unsigned have;
+    z_stream strm;
+    char in[CHUNK];
+    char out[CHUNK];
+</b></pre><!-- -->
+The first thing we do is to initialize the <em>zlib</em> state for compression using
+<tt>deflateInit()</tt>.  This must be done before the first use of <tt>deflate()</tt>.
+The <tt>zalloc</tt>, <tt>zfree</tt>, and <tt>opaque</tt> fields in the <tt>strm</tt>
+structure must be initialized before calling <tt>deflateInit()</tt>.  Here they are
+set to the <em>zlib</em> constant <tt>Z_NULL</tt> to request that <em>zlib</em> use
+the default memory allocation routines.  An application may also choose to provide
+custom memory allocation routines here.  <tt>deflateInit()</tt> will allocate on the
+order of 256K bytes for the internal state.
+(See <a href="zlib_tech.html"><em>zlib Technical Details</em></a>.)
+<p>
+<tt>deflateInit()</tt> is called with a pointer to the structure to be initialized and
+the compression level, which is an integer in the range of -1 to 9.  Lower compression
+levels result in faster execution, but less compression.  Higher levels result in
+greater compression, but slower execution.  The <em>zlib</em> constant Z_DEFAULT_COMPRESSION,
+equal to -1,
+provides a good compromise between compression and speed and is equivalent to level 6.
+Level 0 actually does no compression at all, and in fact expands the data slightly to produce
+the <em>zlib</em> format (it is not a byte-for-byte copy of the input).
+More advanced applications of <em>zlib</em>
+may use <tt>deflateInit2()</tt> here instead.  Such an application may want to reduce how
+much memory will be used, at some price in compression.  Or it may need to request a
+<em>gzip</em> header and trailer instead of a <em>zlib</em> header and trailer, or raw
+encoding with no header or trailer at all.
+<p>
+We must check the return value of <tt>deflateInit()</tt> against the <em>zlib</em> constant
+<tt>Z_OK</tt> to make sure that it was able to
+allocate memory for the internal state, and that the provided arguments were valid.
+<tt>deflateInit()</tt> will also check that the version of <em>zlib</em> that the <tt>zlib.h</tt>
+file came from matches the version of <em>zlib</em> actually linked with the program.  This
+is especially important for environments in which <em>zlib</em> is a shared library.
+<p>
+Note that an application can initialize multiple, independent <em>zlib</em> streams, which can
+operate in parallel.  The state information maintained in the structure allows the <em>zlib</em>
+routines to be reentrant.
+<pre><b>
+    /* allocate deflate state */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    ret = deflateInit(&amp;strm, level);
+    if (ret != Z_OK)
+        return ret;
+</b></pre><!-- -->
+With the pleasantries out of the way, now we can get down to business.  The outer <tt>do</tt>-loop
+reads all of the input file and exits at the bottom of the loop once end-of-file is reached.
+This loop contains the only call of <tt>deflate()</tt>.  So we must make sure that all of the
+input data has been processed and that all of the output data has been generated and consumed
+before we fall out of the loop at the bottom.
+<pre><b>
+    /* compress until end of file */
+    do {
+</b></pre>
+We start off by reading data from the input file.  The number of bytes read is put directly
+into <tt>avail_in</tt>, and a pointer to those bytes is put into <tt>next_in</tt>.  We also
+check to see if end-of-file on the input has been reached.  If we are at the end of file, then <tt>flush</tt> is set to the
+<em>zlib</em> constant <tt>Z_FINISH</tt>, which is later passed to <tt>deflate()</tt> to
+indicate that this is the last chunk of input data to compress.  We need to use <tt>feof()</tt>
+to check for end-of-file as opposed to seeing if fewer than <tt>CHUNK</tt> bytes have been read.  The
+reason is that if the input file length is an exact multiple of <tt>CHUNK</tt>, we will miss
+the fact that we got to the end-of-file, and not know to tell <tt>deflate()</tt> to finish
+up the compressed stream.  If we are not yet at the end of the input, then the <em>zlib</em>
+constant <tt>Z_NO_FLUSH</tt> will be passed to <tt>deflate</tt> to indicate that we are still
+in the middle of the uncompressed data.
+<p>
+If there is an error in reading from the input file, the process is aborted with
+<tt>deflateEnd()</tt> being called to free the allocated <em>zlib</em> state before returning
+the error.  We wouldn't want a memory leak, now would we?  <tt>deflateEnd()</tt> can be called
+at any time after the state has been initialized.  Once that's done, <tt>deflateInit()</tt> (or
+<tt>deflateInit2()</tt>) would have to be called to start a new compression process.  There is
+no point here in checking the <tt>deflateEnd()</tt> return code.  The deallocation can't fail.
+<pre><b>
+        strm.avail_in = fread(in, 1, CHUNK, source);
+        if (ferror(source)) {
+            (void)deflateEnd(&amp;strm);
+            return Z_ERRNO;
+        }
+        flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
+        strm.next_in = in;
+</b></pre><!-- -->
+The inner <tt>do</tt>-loop passes our chunk of input data to <tt>deflate()</tt>, and then
+keeps calling <tt>deflate()</tt> until it is done producing output.  Once there is no more
+new output, <tt>deflate()</tt> is guaranteed to have consumed all of the input, i.e.,
+<tt>avail_in</tt> will be zero.
+<pre><b>
+        /* run deflate() on input until output buffer not full, finish
+           compression if all of source has been read in */
+        do {
+</b></pre>
+Output space is provided to <tt>deflate()</tt> by setting <tt>avail_out</tt> to the number
+of available output bytes and <tt>next_out</tt> to a pointer to that space.
+<pre><b>
+            strm.avail_out = CHUNK;
+            strm.next_out = out;
+</b></pre>
+Now we call the compression engine itself, <tt>deflate()</tt>.  It takes as many of the
+<tt>avail_in</tt> bytes at <tt>next_in</tt> as it can process, and writes as many as
+<tt>avail_out</tt> bytes to <tt>next_out</tt>.  Those counters and pointers are then
+updated past the input data consumed and the output data written.  It is the amount of
+output space available that may limit how much input is consumed.
+Hence the inner loop to make sure that
+all of the input is consumed by providing more output space each time.  Since <tt>avail_in</tt>
+and <tt>next_in</tt> are updated by <tt>deflate()</tt>, we don't have to mess with those
+between <tt>deflate()</tt> calls until it's all used up.
+<p>
+The parameters to <tt>deflate()</tt> are a pointer to the <tt>strm</tt> structure containing
+the input and output information and the internal compression engine state, and a parameter
+indicating whether and how to flush data to the output.  Normally <tt>deflate</tt> will consume
+several K bytes of input data before producing any output (except for the header), in order
+to accumulate statistics on the data for optimum compression.  It will then put out a burst of
+compressed data, and proceed to consume more input before the next burst.  Eventually,
+<tt>deflate()</tt>
+must be told to terminate the stream, complete the compression with provided input data, and
+write out the trailer check value.  <tt>deflate()</tt> will continue to compress normally as long
+as the flush parameter is <tt>Z_NO_FLUSH</tt>.  Once the <tt>Z_FINISH</tt> parameter is provided,
+<tt>deflate()</tt> will begin to complete the compressed output stream.  However depending on how
+much output space is provided, <tt>deflate()</tt> may have to be called several times until it
+has provided the complete compressed stream, even after it has consumed all of the input.  The flush
+parameter must continue to be <tt>Z_FINISH</tt> for those subsequent calls.
+<p>
+There are other values of the flush parameter that are used in more advanced applications.  You can
+force <tt>deflate()</tt> to produce a burst of output that encodes all of the input data provided
+so far, even if it wouldn't have otherwise, for example to control data latency on a link with
+compressed data.  You can also ask that <tt>deflate()</tt> do that as well as erase any history up to
+that point so that what follows can be decompressed independently, for example for random access
+applications.  Both requests will degrade compression by an amount depending on how often such
+requests are made.
+<p>
+<tt>deflate()</tt> has a return value that can indicate errors, yet we do not check it here.  Why
+not?  Well, it turns out that <tt>deflate()</tt> can do no wrong here.  Let's go through
+<tt>deflate()</tt>'s return values and dispense with them one by one.  The possible values are
+<tt>Z_OK</tt>, <tt>Z_STREAM_END</tt>, <tt>Z_STREAM_ERROR</tt>, or <tt>Z_BUF_ERROR</tt>.  <tt>Z_OK</tt>
+is, well, ok.  <tt>Z_STREAM_END</tt> is also ok and will be returned for the last call of
+<tt>deflate()</tt>.  This is already guaranteed by calling <tt>deflate()</tt> with <tt>Z_FINISH</tt>
+until it has no more output.  <tt>Z_STREAM_ERROR</tt> is only possible if the stream is not
+initialized properly, but we did initialize it properly.  There is no harm in checking for
+<tt>Z_STREAM_ERROR</tt> here, for example to check for the possibility that some
+other part of the application inadvertently clobbered the memory containing the <em>zlib</em> state.
+<tt>Z_BUF_ERROR</tt> will be explained further below, but
+suffice it to say that this is simply an indication that <tt>deflate()</tt> could not consume
+more input or produce more output.  <tt>deflate()</tt> can be called again with more output space
+or more available input, which it will be in this code.
+<pre><b>
+            ret = deflate(&amp;strm, flush);    /* no bad return value */
+            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
+</b></pre>
+Now we compute how much output <tt>deflate()</tt> provided on the last call, which is the
+difference between how much space was provided before the call, and how much output space
+is still available after the call.  Then that data, if any, is written to the output file.
+We can then reuse the output buffer for the next call of <tt>deflate()</tt>.  Again if there
+is a file i/o error, we call <tt>deflateEnd()</tt> before returning to avoid a memory leak.
+<pre><b>
+            have = CHUNK - strm.avail_out;
+            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
+                (void)deflateEnd(&amp;strm);
+                return Z_ERRNO;
+            }
+</b></pre>
+The inner <tt>do</tt>-loop is repeated until the last <tt>deflate()</tt> call fails to fill the
+provided output buffer.  Then we know that <tt>deflate()</tt> has done as much as it can with
+the provided input, and that all of that input has been consumed.  We can then fall out of this
+loop and reuse the input buffer.
+<p>
+The way we tell that <tt>deflate()</tt> has no more output is by seeing that it did not fill
+the output buffer, leaving <tt>avail_out</tt> greater than zero.  However suppose that
+<tt>deflate()</tt> has no more output, but just so happened to exactly fill the output buffer!
+<tt>avail_out</tt> is zero, and we can't tell that <tt>deflate()</tt> has done all it can.
+As far as we know, <tt>deflate()</tt>
+has more output for us.  So we call it again.  But now <tt>deflate()</tt> produces no output
+at all, and <tt>avail_out</tt> remains unchanged as <tt>CHUNK</tt>.  That <tt>deflate()</tt> call
+wasn't able to do anything, either consume input or produce output, and so it returns
+<tt>Z_BUF_ERROR</tt>.  (See, I told you I'd cover this later.)  However this is not a problem at
+all.  Now we finally have the desired indication that <tt>deflate()</tt> is really done,
+and so we drop out of the inner loop to provide more input to <tt>deflate()</tt>.
+<p>
+With <tt>flush</tt> set to <tt>Z_FINISH</tt>, this final set of <tt>deflate()</tt> calls will
+complete the output stream.  Once that is done, subsequent calls of <tt>deflate()</tt> would return
+<tt>Z_STREAM_ERROR</tt> if the flush parameter is not <tt>Z_FINISH</tt>, and do no more processing
+until the state is reinitialized.
+<p>
+Some applications of <em>zlib</em> have two loops that call <tt>deflate()</tt>
+instead of the single inner loop we have here.  The first loop would call
+without flushing and feed all of the data to <tt>deflate()</tt>.  The second loop would call
+<tt>deflate()</tt> with no more
+data and the <tt>Z_FINISH</tt> parameter to complete the process.  As you can see from this
+example, that can be avoided by simply keeping track of the current flush state.
+<pre><b>
+        } while (strm.avail_out == 0);
+        assert(strm.avail_in == 0);     /* all input will be used */
+</b></pre><!-- -->
+Now we check to see if we have already processed all of the input file.  That information was
+saved in the <tt>flush</tt> variable, so we see if that was set to <tt>Z_FINISH</tt>.  If so,
+then we're done and we fall out of the outer loop.  We're guaranteed to get <tt>Z_STREAM_END</tt>
+from the last <tt>deflate()</tt> call, since we ran it until the last chunk of input was
+consumed and all of the output was generated.
+<pre><b>
+        /* done when last data in file processed */
+    } while (flush != Z_FINISH);
+    assert(ret == Z_STREAM_END);        /* stream will be complete */
+</b></pre><!-- -->
+The process is complete, but we still need to deallocate the state to avoid a memory leak
+(or rather more like a memory hemorrhage if you didn't do this).  Then
+finally we can return with a happy return value.
+<pre><b>
+    /* clean up and return */
+    (void)deflateEnd(&amp;strm);
+    return Z_OK;
+}
+</b></pre><!-- -->
+Now we do the same thing for decompression in the <tt>inf()</tt> routine. <tt>inf()</tt>
+decompresses what is hopefully a valid <em>zlib</em> stream from the input file and writes the
+uncompressed data to the output file.  Much of the discussion above for <tt>def()</tt>
+applies to <tt>inf()</tt> as well, so the discussion here will focus on the differences between
+the two.
+<pre><b>
+/* Decompress from file source to file dest until stream ends or EOF.
+   inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+   allocated for processing, Z_DATA_ERROR if the deflate data is
+   invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
+   the version of the library linked do not match, or Z_ERRNO if there
+   is an error reading or writing the files. */
+int inf(FILE *source, FILE *dest)
+{
+</b></pre>
+The local variables have the same functionality as they do for <tt>def()</tt>.  The
+only difference is that there is no <tt>flush</tt> variable, since <tt>inflate()</tt>
+can tell from the <em>zlib</em> stream itself when the stream is complete.
+<pre><b>
+    int ret;
+    unsigned have;
+    z_stream strm;
+    char in[CHUNK];
+    char out[CHUNK];
+</b></pre><!-- -->
+The initialization of the state is the same, except that there is no compression level,
+of course, and two more elements of the structure are initialized.  <tt>avail_in</tt>
+and <tt>next_in</tt> must be initialized before calling <tt>inflateInit()</tt>.  This
+is because the application has the option to provide the start of the zlib stream in
+order for <tt>inflateInit()</tt> to have access to information about the compression
+method to aid in memory allocation.  In the current implementation of <em>zlib</em>
+(up through versions 1.2.x), the method-dependent memory allocations are deferred to the first call of
+<tt>inflate()</tt> anyway.  However those fields must be initialized since later versions
+of <em>zlib</em> that provide more compression methods may take advantage of this interface.
+In any case, no decompression is performed by <tt>inflateInit()</tt>, so the
+<tt>avail_out</tt> and <tt>next_out</tt> fields do not need to be initialized before calling.
+<p>
+Here <tt>avail_in</tt> is set to zero and <tt>next_in</tt> is set to <tt>Z_NULL</tt> to
+indicate that no input data is being provided.
+<pre><b>
+    /* allocate inflate state */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    strm.avail_in = 0;
+    strm.next_in = Z_NULL;
+    ret = inflateInit(&amp;strm);
+    if (ret != Z_OK)
+        return ret;
+</b></pre><!-- -->
+The outer <tt>do</tt>-loop decompresses input until <tt>inflate()</tt> indicates
+that it has reached the end of the compressed data and has produced all of the uncompressed
+output.  This is in contrast to <tt>def()</tt> which processes all of the input file.
+If end-of-file is reached before the compressed data self-terminates, then the compressed
+data is incomplete and an error is returned.
+<pre><b>
+    /* decompress until deflate stream ends or end of file */
+    do {
+</b></pre>
+We read input data and set the <tt>strm</tt> structure accordingly.  If we've reached the
+end of the input file, then we leave the outer loop and report an error, since the
+compressed data is incomplete.  Note that we may read more data than is eventually consumed
+by <tt>inflate()</tt>, if the input file continues past the <em>zlib</em> stream.
+For applications where <em>zlib</em> streams are embedded in other data, this routine would
+need to be modified to return the unused data, or at least indicate how much of the input
+data was not used, so the application would know where to pick up after the <em>zlib</em> stream.
+<pre><b>
+        strm.avail_in = fread(in, 1, CHUNK, source);
+        if (ferror(source)) {
+            (void)inflateEnd(&amp;strm);
+            return Z_ERRNO;
+        }
+        if (strm.avail_in == 0)
+            break;
+        strm.next_in = in;
+</b></pre><!-- -->
+The inner <tt>do</tt>-loop has the same function it did in <tt>def()</tt>, which is to
+keep calling <tt>inflate()</tt> until has generated all of the output it can with the
+provided input.
+<pre><b>
+        /* run inflate() on input until output buffer not full */
+        do {
+</b></pre>
+Just like in <tt>def()</tt>, the same output space is provided for each call of <tt>inflate()</tt>.
+<pre><b>
+            strm.avail_out = CHUNK;
+            strm.next_out = out;
+</b></pre>
+Now we run the decompression engine itself.  There is no need to adjust the flush parameter, since
+the <em>zlib</em> format is self-terminating. The main difference here is that there are
+return values that we need to pay attention to.  <tt>Z_DATA_ERROR</tt>
+indicates that <tt>inflate()</tt> detected an error in the <em>zlib</em> compressed data format,
+which means that either the data is not a <em>zlib</em> stream to begin with, or that the data was
+corrupted somewhere along the way since it was compressed.  The other error to be processed is
+<tt>Z_MEM_ERROR</tt>, which can occur since memory allocation is deferred until <tt>inflate()</tt>
+needs it, unlike <tt>deflate()</tt>, whose memory is allocated at the start by <tt>deflateInit()</tt>.
+<p>
+Advanced applications may use
+<tt>deflateSetDictionary()</tt> to prime <tt>deflate()</tt> with a set of likely data to improve the
+first 32K or so of compression.  This is noted in the <em>zlib</em> header, so <tt>inflate()</tt>
+requests that that dictionary be provided before it can start to decompress.  Without the dictionary,
+correct decompression is not possible.  For this routine, we have no idea what the dictionary is,
+so the <tt>Z_NEED_DICT</tt> indication is converted to a <tt>Z_DATA_ERROR</tt>.
+<p>
+<tt>inflate()</tt> can also return <tt>Z_STREAM_ERROR</tt>, which should not be possible here,
+but could be checked for as noted above for <tt>def()</tt>.  <tt>Z_BUF_ERROR</tt> does not need to be
+checked for here, for the same reasons noted for <tt>def()</tt>.  <tt>Z_STREAM_END</tt> will be
+checked for later.
+<pre><b>
+            ret = inflate(&amp;strm, Z_NO_FLUSH);
+            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
+            switch (ret) {
+            case Z_NEED_DICT:
+                ret = Z_DATA_ERROR;     /* and fall through */
+            case Z_DATA_ERROR:
+            case Z_MEM_ERROR:
+                (void)inflateEnd(&amp;strm);
+                return ret;
+            }
+</b></pre>
+The output of <tt>inflate()</tt> is handled identically to that of <tt>deflate()</tt>.
+<pre><b>
+            have = CHUNK - strm.avail_out;
+            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
+                (void)inflateEnd(&amp;strm);
+                return Z_ERRNO;
+            }
+</b></pre>
+The inner <tt>do</tt>-loop ends when <tt>inflate()</tt> has no more output as indicated
+by not filling the output buffer, just as for <tt>deflate()</tt>.  In this case, we cannot
+assert that <tt>strm.avail_in</tt> will be zero, since the deflate stream may end before the file
+does.
+<pre><b>
+        } while (strm.avail_out == 0);
+</b></pre><!-- -->
+The outer <tt>do</tt>-loop ends when <tt>inflate()</tt> reports that it has reached the
+end of the input <em>zlib</em> stream, has completed the decompression and integrity
+check, and has provided all of the output.  This is indicated by the <tt>inflate()</tt>
+return value <tt>Z_STREAM_END</tt>.  The inner loop is guaranteed to leave <tt>ret</tt>
+equal to <tt>Z_STREAM_END</tt> if the last chunk of the input file read contained the end
+of the <em>zlib</em> stream.  So if the return value is not <tt>Z_STREAM_END</tt>, the
+loop continues to read more input.
+<pre><b>
+        /* done when inflate() says it's done */
+    } while (ret != Z_STREAM_END);
+</b></pre><!-- -->
+At this point, decompression successfully completed, or we broke out of the loop due to no
+more data being available from the input file.  If the last <tt>inflate()</tt> return value
+is not <tt>Z_STREAM_END</tt>, then the <em>zlib</em> stream was incomplete and a data error
+is returned.  Otherwise, we return with a happy return value.  Of course, <tt>inflateEnd()</tt>
+is called first to avoid a memory leak.
+<pre><b>
+    /* clean up and return */
+    (void)inflateEnd(&amp;strm);
+    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
+}
+</b></pre><!-- -->
+That ends the routines that directly use <em>zlib</em>.  The following routines make this
+a command-line program by running data through the above routines from <tt>stdin</tt> to
+<tt>stdout</tt>, and handling any errors reported by <tt>def()</tt> or <tt>inf()</tt>.
+<p>
+<tt>zerr()</tt> is used to interpret the possible error codes from <tt>def()</tt>
+and <tt>inf()</tt>, as detailed in their comments above, and print out an error message.
+Note that these are only a subset of the possible return values from <tt>deflate()</tt>
+and <tt>inflate()</tt>.
+<pre><b>
+/* report a zlib or i/o error */
+void zerr(int ret)
+{
+    fputs("zpipe: ", stderr);
+    switch (ret) {
+    case Z_ERRNO:
+        if (ferror(stdin))
+            fputs("error reading stdin\n", stderr);
+        if (ferror(stdout))
+            fputs("error writing stdout\n", stderr);
+        break;
+    case Z_STREAM_ERROR:
+        fputs("invalid compression level\n", stderr);
+        break;
+    case Z_DATA_ERROR:
+        fputs("invalid or incomplete deflate data\n", stderr);
+        break;
+    case Z_MEM_ERROR:
+        fputs("out of memory\n", stderr);
+        break;
+    case Z_VERSION_ERROR:
+        fputs("zlib version mismatch!\n", stderr);
+    }
+}
+</b></pre><!-- -->
+Here is the <tt>main()</tt> routine used to test <tt>def()</tt> and <tt>inf()</tt>.  The
+<tt>zpipe</tt> command is simply a compression pipe from <tt>stdin</tt> to <tt>stdout</tt>, if
+no arguments are given, or it is a decompression pipe if <tt>zpipe -d</tt> is used.  If any other
+arguments are provided, no compression or decompression is performed.  Instead a usage
+message is displayed.  Examples are <tt>zpipe < foo.txt > foo.txt.z</tt> to compress, and
+<tt>zpipe -d < foo.txt.z > foo.txt</tt> to decompress.
+<pre><b>
+/* compress or decompress from stdin to stdout */
+int main(int argc, char **argv)
+{
+    int ret;
+
+    /* do compression if no arguments */
+    if (argc == 1) {
+        ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
+        if (ret != Z_OK)
+            zerr(ret);
+        return ret;
+    }
+
+    /* do decompression if -d specified */
+    else if (argc == 2 &amp;&amp; strcmp(argv[1], "-d") == 0) {
+        ret = inf(stdin, stdout);
+        if (ret != Z_OK)
+            zerr(ret);
+        return ret;
+    }
+
+    /* otherwise, report usage */
+    else {
+        fputs("zpipe usage: zpipe [-d] &lt; source &gt; dest\n", stderr);
+        return 1;
+    }
+}
+</b></pre>
+<hr>
+<i>Copyright (c) 2004 by Mark Adler<br>Last modified 13 November 2004</i>
+</body>
+</html>
Index: /trunk/minix/lib/zlib-1.2.3/examples/zpipe.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/examples/zpipe.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/examples/zpipe.c	(revision 9)
@@ -0,0 +1,191 @@
+/* zpipe.c: example of proper use of zlib's inflate() and deflate()
+   Not copyrighted -- provided to the public domain
+   Version 1.2  9 November 2004  Mark Adler */
+
+/* Version history:
+   1.0  30 Oct 2004  First version
+   1.1   8 Nov 2004  Add void casting for unused return values
+                     Use switch statement for inflate() return values
+   1.2   9 Nov 2004  Add assertions to document zlib guarantees
+   1.3   6 Apr 2005  Remove incorrect assertion in inf()
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "zlib.h"
+
+#define CHUNK 16384
+
+/* Compress from file source to file dest until EOF on source.
+   def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+   allocated for processing, Z_STREAM_ERROR if an invalid compression
+   level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
+   version of the library linked do not match, or Z_ERRNO if there is
+   an error reading or writing the files. */
+int def(FILE *source, FILE *dest, int level)
+{
+    int ret, flush;
+    unsigned have;
+    z_stream strm;
+    char in[CHUNK];
+    char out[CHUNK];
+
+    /* allocate deflate state */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    ret = deflateInit(&strm, level);
+    if (ret != Z_OK)
+        return ret;
+
+    /* compress until end of file */
+    do {
+        strm.avail_in = fread(in, 1, CHUNK, source);
+        if (ferror(source)) {
+            (void)deflateEnd(&strm);
+            return Z_ERRNO;
+        }
+        flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
+        strm.next_in = in;
+
+        /* run deflate() on input until output buffer not full, finish
+           compression if all of source has been read in */
+        do {
+            strm.avail_out = CHUNK;
+            strm.next_out = out;
+            ret = deflate(&strm, flush);    /* no bad return value */
+            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
+            have = CHUNK - strm.avail_out;
+            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
+                (void)deflateEnd(&strm);
+                return Z_ERRNO;
+            }
+        } while (strm.avail_out == 0);
+        assert(strm.avail_in == 0);     /* all input will be used */
+
+        /* done when last data in file processed */
+    } while (flush != Z_FINISH);
+    assert(ret == Z_STREAM_END);        /* stream will be complete */
+
+    /* clean up and return */
+    (void)deflateEnd(&strm);
+    return Z_OK;
+}
+
+/* Decompress from file source to file dest until stream ends or EOF.
+   inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+   allocated for processing, Z_DATA_ERROR if the deflate data is
+   invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
+   the version of the library linked do not match, or Z_ERRNO if there
+   is an error reading or writing the files. */
+int inf(FILE *source, FILE *dest)
+{
+    int ret;
+    unsigned have;
+    z_stream strm;
+    char in[CHUNK];
+    char out[CHUNK];
+
+    /* allocate inflate state */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    strm.avail_in = 0;
+    strm.next_in = Z_NULL;
+    ret = inflateInit(&strm);
+    if (ret != Z_OK)
+        return ret;
+
+    /* decompress until deflate stream ends or end of file */
+    do {
+        strm.avail_in = fread(in, 1, CHUNK, source);
+        if (ferror(source)) {
+            (void)inflateEnd(&strm);
+            return Z_ERRNO;
+        }
+        if (strm.avail_in == 0)
+            break;
+        strm.next_in = in;
+
+        /* run inflate() on input until output buffer not full */
+        do {
+            strm.avail_out = CHUNK;
+            strm.next_out = out;
+            ret = inflate(&strm, Z_NO_FLUSH);
+            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
+            switch (ret) {
+            case Z_NEED_DICT:
+                ret = Z_DATA_ERROR;     /* and fall through */
+            case Z_DATA_ERROR:
+            case Z_MEM_ERROR:
+                (void)inflateEnd(&strm);
+                return ret;
+            }
+            have = CHUNK - strm.avail_out;
+            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
+                (void)inflateEnd(&strm);
+                return Z_ERRNO;
+            }
+        } while (strm.avail_out == 0);
+
+        /* done when inflate() says it's done */
+    } while (ret != Z_STREAM_END);
+
+    /* clean up and return */
+    (void)inflateEnd(&strm);
+    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
+}
+
+/* report a zlib or i/o error */
+void zerr(int ret)
+{
+    fputs("zpipe: ", stderr);
+    switch (ret) {
+    case Z_ERRNO:
+        if (ferror(stdin))
+            fputs("error reading stdin\n", stderr);
+        if (ferror(stdout))
+            fputs("error writing stdout\n", stderr);
+        break;
+    case Z_STREAM_ERROR:
+        fputs("invalid compression level\n", stderr);
+        break;
+    case Z_DATA_ERROR:
+        fputs("invalid or incomplete deflate data\n", stderr);
+        break;
+    case Z_MEM_ERROR:
+        fputs("out of memory\n", stderr);
+        break;
+    case Z_VERSION_ERROR:
+        fputs("zlib version mismatch!\n", stderr);
+    }
+}
+
+/* compress or decompress from stdin to stdout */
+int main(int argc, char **argv)
+{
+    int ret;
+
+    /* do compression if no arguments */
+    if (argc == 1) {
+        ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
+        if (ret != Z_OK)
+            zerr(ret);
+        return ret;
+    }
+
+    /* do decompression if -d specified */
+    else if (argc == 2 && strcmp(argv[1], "-d") == 0) {
+        ret = inf(stdin, stdout);
+        if (ret != Z_OK)
+            zerr(ret);
+        return ret;
+    }
+
+    /* otherwise, report usage */
+    else {
+        fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr);
+        return 1;
+    }
+}
Index: /trunk/minix/lib/zlib-1.2.3/examples/zran.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/examples/zran.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/examples/zran.c	(revision 9)
@@ -0,0 +1,404 @@
+/* zran.c -- example of zlib/gzip stream indexing and random access
+ * Copyright (C) 2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+   Version 1.0  29 May 2005  Mark Adler */
+
+/* Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary()
+   for random access of a compressed file.  A file containing a zlib or gzip
+   stream is provided on the command line.  The compressed stream is decoded in
+   its entirety, and an index built with access points about every SPAN bytes
+   in the uncompressed output.  The compressed file is left open, and can then
+   be read randomly, having to decompress on the average SPAN/2 uncompressed
+   bytes before getting to the desired block of data.
+
+   An access point can be created at the start of any deflate block, by saving
+   the starting file offset and bit of that block, and the 32K bytes of
+   uncompressed data that precede that block.  Also the uncompressed offset of
+   that block is saved to provide a referece for locating a desired starting
+   point in the uncompressed stream.  build_index() works by decompressing the
+   input zlib or gzip stream a block at a time, and at the end of each block
+   deciding if enough uncompressed data has gone by to justify the creation of
+   a new access point.  If so, that point is saved in a data structure that
+   grows as needed to accommodate the points.
+
+   To use the index, an offset in the uncompressed data is provided, for which
+   the latest accees point at or preceding that offset is located in the index.
+   The input file is positioned to the specified location in the index, and if
+   necessary the first few bits of the compressed data is read from the file.
+   inflate is initialized with those bits and the 32K of uncompressed data, and
+   the decompression then proceeds until the desired offset in the file is
+   reached.  Then the decompression continues to read the desired uncompressed
+   data from the file.
+
+   Another approach would be to generate the index on demand.  In that case,
+   requests for random access reads from the compressed data would try to use
+   the index, but if a read far enough past the end of the index is required,
+   then further index entries would be generated and added.
+
+   There is some fair bit of overhead to starting inflation for the random
+   access, mainly copying the 32K byte dictionary.  So if small pieces of the
+   file are being accessed, it would make sense to implement a cache to hold
+   some lookahead and avoid many calls to extract() for small lengths.
+
+   Another way to build an index would be to use inflateCopy().  That would
+   not be constrained to have access points at block boundaries, but requires
+   more memory per access point, and also cannot be saved to file due to the
+   use of pointers in the state.  The approach here allows for storage of the
+   index in a file.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "zlib.h"
+
+#define local static
+
+#define SPAN 1048576L       /* desired distance between access points */
+#define WINSIZE 32768U      /* sliding window size */
+#define CHUNK 16384         /* file input buffer size */
+
+/* access point entry */
+struct point {
+    off_t out;          /* corresponding offset in uncompressed data */
+    off_t in;           /* offset in input file of first full byte */
+    int bits;           /* number of bits (1-7) from byte at in - 1, or 0 */
+    unsigned char window[WINSIZE];  /* preceding 32K of uncompressed data */
+};
+
+/* access point list */
+struct access {
+    int have;           /* number of list entries filled in */
+    int size;           /* number of list entries allocated */
+    struct point *list; /* allocated list */
+};
+
+/* Deallocate an index built by build_index() */
+local void free_index(struct access *index)
+{
+    if (index != NULL) {
+        free(index->list);
+        free(index);
+    }
+}
+
+/* Add an entry to the access point list.  If out of memory, deallocate the
+   existing list and return NULL. */
+local struct access *addpoint(struct access *index, int bits,
+    off_t in, off_t out, unsigned left, unsigned char *window)
+{
+    struct point *next;
+
+    /* if list is empty, create it (start with eight points) */
+    if (index == NULL) {
+        index = malloc(sizeof(struct access));
+        if (index == NULL) return NULL;
+        index->list = malloc(sizeof(struct point) << 3);
+        if (index->list == NULL) {
+            free(index);
+            return NULL;
+        }
+        index->size = 8;
+        index->have = 0;
+    }
+
+    /* if list is full, make it bigger */
+    else if (index->have == index->size) {
+        index->size <<= 1;
+        next = realloc(index->list, sizeof(struct point) * index->size);
+        if (next == NULL) {
+            free_index(index);
+            return NULL;
+        }
+        index->list = next;
+    }
+
+    /* fill in entry and increment how many we have */
+    next = index->list + index->have;
+    next->bits = bits;
+    next->in = in;
+    next->out = out;
+    if (left)
+        memcpy(next->window, window + WINSIZE - left, left);
+    if (left < WINSIZE)
+        memcpy(next->window + left, window, WINSIZE - left);
+    index->have++;
+
+    /* return list, possibly reallocated */
+    return index;
+}
+
+/* Make one entire pass through the compressed stream and build an index, with
+   access points about every span bytes of uncompressed output -- span is
+   chosen to balance the speed of random access against the memory requirements
+   of the list, about 32K bytes per access point.  Note that data after the end
+   of the first zlib or gzip stream in the file is ignored.  build_index()
+   returns the number of access points on success (>= 1), Z_MEM_ERROR for out
+   of memory, Z_DATA_ERROR for an error in the input file, or Z_ERRNO for a
+   file read error.  On success, *built points to the resulting index. */
+local int build_index(FILE *in, off_t span, struct access **built)
+{
+    int ret;
+    off_t totin, totout;        /* our own total counters to avoid 4GB limit */
+    off_t last;                 /* totout value of last access point */
+    struct access *index;       /* access points being generated */
+    z_stream strm;
+    unsigned char input[CHUNK];
+    unsigned char window[WINSIZE];
+
+    /* initialize inflate */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    strm.avail_in = 0;
+    strm.next_in = Z_NULL;
+    ret = inflateInit2(&strm, 47);      /* automatic zlib or gzip decoding */
+    if (ret != Z_OK)
+        return ret;
+
+    /* inflate the input, maintain a sliding window, and build an index -- this
+       also validates the integrity of the compressed data using the check
+       information at the end of the gzip or zlib stream */
+    totin = totout = last = 0;
+    index = NULL;               /* will be allocated by first addpoint() */
+    strm.avail_out = 0;
+    do {
+        /* get some compressed data from input file */
+        strm.avail_in = fread(input, 1, CHUNK, in);
+        if (ferror(in)) {
+            ret = Z_ERRNO;
+            goto build_index_error;
+        }
+        if (strm.avail_in == 0) {
+            ret = Z_DATA_ERROR;
+            goto build_index_error;
+        }
+        strm.next_in = input;
+
+        /* process all of that, or until end of stream */
+        do {
+            /* reset sliding window if necessary */
+            if (strm.avail_out == 0) {
+                strm.avail_out = WINSIZE;
+                strm.next_out = window;
+            }
+
+            /* inflate until out of input, output, or at end of block --
+               update the total input and output counters */
+            totin += strm.avail_in;
+            totout += strm.avail_out;
+            ret = inflate(&strm, Z_BLOCK);      /* return at end of block */
+            totin -= strm.avail_in;
+            totout -= strm.avail_out;
+            if (ret == Z_NEED_DICT)
+                ret = Z_DATA_ERROR;
+            if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
+                goto build_index_error;
+            if (ret == Z_STREAM_END)
+                break;
+
+            /* if at end of block, consider adding an index entry (note that if
+               data_type indicates an end-of-block, then all of the
+               uncompressed data from that block has been delivered, and none
+               of the compressed data after that block has been consumed,
+               except for up to seven bits) -- the totout == 0 provides an
+               entry point after the zlib or gzip header, and assures that the
+               index always has at least one access point; we avoid creating an
+               access point after the last block by checking bit 6 of data_type
+             */
+            if ((strm.data_type & 128) && !(strm.data_type & 64) &&
+                (totout == 0 || totout - last > span)) {
+                index = addpoint(index, strm.data_type & 7, totin,
+                                 totout, strm.avail_out, window);
+                if (index == NULL) {
+                    ret = Z_MEM_ERROR;
+                    goto build_index_error;
+                }
+                last = totout;
+            }
+        } while (strm.avail_in != 0);
+    } while (ret != Z_STREAM_END);
+
+    /* clean up and return index (release unused entries in list) */
+    (void)inflateEnd(&strm);
+    index = realloc(index, sizeof(struct point) * index->have);
+    index->size = index->have;
+    *built = index;
+    return index->size;
+
+    /* return error */
+  build_index_error:
+    (void)inflateEnd(&strm);
+    if (index != NULL)
+        free_index(index);
+    return ret;
+}
+
+/* Use the index to read len bytes from offset into buf, return bytes read or
+   negative for error (Z_DATA_ERROR or Z_MEM_ERROR).  If data is requested past
+   the end of the uncompressed data, then extract() will return a value less
+   than len, indicating how much as actually read into buf.  This function
+   should not return a data error unless the file was modified since the index
+   was generated.  extract() may also return Z_ERRNO if there is an error on
+   reading or seeking the input file. */
+local int extract(FILE *in, struct access *index, off_t offset,
+                  unsigned char *buf, int len)
+{
+    int ret, skip;
+    z_stream strm;
+    struct point *here;
+    unsigned char input[CHUNK];
+    unsigned char discard[WINSIZE];
+
+    /* proceed only if something reasonable to do */
+    if (len < 0)
+        return 0;
+
+    /* find where in stream to start */
+    here = index->list;
+    ret = index->have;
+    while (--ret && here[1].out <= offset)
+        here++;
+
+    /* initialize file and inflate state to start there */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    strm.avail_in = 0;
+    strm.next_in = Z_NULL;
+    ret = inflateInit2(&strm, -15);         /* raw inflate */
+    if (ret != Z_OK)
+        return ret;
+    ret = fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET);
+    if (ret == -1)
+        goto extract_ret;
+    if (here->bits) {
+        ret = getc(in);
+        if (ret == -1) {
+            ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR;
+            goto extract_ret;
+        }
+        (void)inflatePrime(&strm, here->bits, ret >> (8 - here->bits));
+    }
+    (void)inflateSetDictionary(&strm, here->window, WINSIZE);
+
+    /* skip uncompressed bytes until offset reached, then satisfy request */
+    offset -= here->out;
+    strm.avail_in = 0;
+    skip = 1;                               /* while skipping to offset */
+    do {
+        /* define where to put uncompressed data, and how much */
+        if (offset == 0 && skip) {          /* at offset now */
+            strm.avail_out = len;
+            strm.next_out = buf;
+            skip = 0;                       /* only do this once */
+        }
+        if (offset > WINSIZE) {             /* skip WINSIZE bytes */
+            strm.avail_out = WINSIZE;
+            strm.next_out = discard;
+            offset -= WINSIZE;
+        }
+        else if (offset != 0) {             /* last skip */
+            strm.avail_out = (unsigned)offset;
+            strm.next_out = discard;
+            offset = 0;
+        }
+
+        /* uncompress until avail_out filled, or end of stream */
+        do {
+            if (strm.avail_in == 0) {
+                strm.avail_in = fread(input, 1, CHUNK, in);
+                if (ferror(in)) {
+                    ret = Z_ERRNO;
+                    goto extract_ret;
+                }
+                if (strm.avail_in == 0) {
+                    ret = Z_DATA_ERROR;
+                    goto extract_ret;
+                }
+                strm.next_in = input;
+            }
+            ret = inflate(&strm, Z_NO_FLUSH);       /* normal inflate */
+            if (ret == Z_NEED_DICT)
+                ret = Z_DATA_ERROR;
+            if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
+                goto extract_ret;
+            if (ret == Z_STREAM_END)
+                break;
+        } while (strm.avail_out != 0);
+
+        /* if reach end of stream, then don't keep trying to get more */
+        if (ret == Z_STREAM_END)
+            break;
+
+        /* do until offset reached and requested data read, or stream ends */
+    } while (skip);
+
+    /* compute number of uncompressed bytes read after offset */
+    ret = skip ? 0 : len - strm.avail_out;
+
+    /* clean up and return bytes read or error */
+  extract_ret:
+    (void)inflateEnd(&strm);
+    return ret;
+}
+
+/* Demonstrate the use of build_index() and extract() by processing the file
+   provided on the command line, and the extracting 16K from about 2/3rds of
+   the way through the uncompressed output, and writing that to stdout. */
+int main(int argc, char **argv)
+{
+    int len;
+    off_t offset;
+    FILE *in;
+    struct access *index;
+    unsigned char buf[CHUNK];
+
+    /* open input file */
+    if (argc != 2) {
+        fprintf(stderr, "usage: zran file.gz\n");
+        return 1;
+    }
+    in = fopen(argv[1], "rb");
+    if (in == NULL) {
+        fprintf(stderr, "zran: could not open %s for reading\n", argv[1]);
+        return 1;
+    }
+
+    /* build index */
+    len = build_index(in, SPAN, &index);
+    if (len < 0) {
+        fclose(in);
+        switch (len) {
+        case Z_MEM_ERROR:
+            fprintf(stderr, "zran: out of memory\n");
+            break;
+        case Z_DATA_ERROR:
+            fprintf(stderr, "zran: compressed data error in %s\n", argv[1]);
+            break;
+        case Z_ERRNO:
+            fprintf(stderr, "zran: read error on %s\n", argv[1]);
+            break;
+        default:
+            fprintf(stderr, "zran: error %d while building index\n", len);
+        }
+        return 1;
+    }
+    fprintf(stderr, "zran: built index with %d access points\n", len);
+
+    /* use index by reading some bytes from an arbitrary offset */
+    offset = (index->list[index->have - 1].out << 1) / 3;
+    len = extract(in, index, offset, buf, CHUNK);
+    if (len < 0)
+        fprintf(stderr, "zran: extraction failed: %s error\n",
+                len == Z_MEM_ERROR ? "out of memory" : "input corrupted");
+    else {
+        fwrite(buf, 1, len, stdout);
+        fprintf(stderr, "zran: extracted %d bytes at %llu\n", len, offset);
+    }
+
+    /* clean up and exit */
+    free_index(index);
+    fclose(in);
+    return 0;
+}
Index: /trunk/minix/lib/zlib-1.2.3/gzio.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/gzio.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/gzio.c	(revision 9)
@@ -0,0 +1,1026 @@
+/* gzio.c -- IO on .gz files
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
+ */
+
+/* @(#) $Id: gzio.c,v 1.1 2005/09/23 22:39:00 beng Exp $ */
+
+#include <stdio.h>
+
+#include "zutil.h"
+
+#ifdef NO_DEFLATE       /* for compatibility with old definition */
+#  define NO_GZCOMPRESS
+#endif
+
+#ifndef NO_DUMMY_DECL
+struct internal_state {int dummy;}; /* for buggy compilers */
+#endif
+
+#ifndef Z_BUFSIZE
+#  ifdef MAXSEG_64K
+#    define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
+#  else
+#    define Z_BUFSIZE 16384
+#  endif
+#endif
+#ifndef Z_PRINTF_BUFSIZE
+#  define Z_PRINTF_BUFSIZE 4096
+#endif
+
+#ifdef __MVS__
+#  pragma map (fdopen , "\174\174FDOPEN")
+   FILE *fdopen(int, const char *);
+#endif
+
+#ifndef STDC
+extern voidp  malloc OF((uInt size));
+extern void   free   OF((voidpf ptr));
+#endif
+
+#define ALLOC(size) malloc(size)
+#define TRYFREE(p) {if (p) free(p);}
+
+static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define COMMENT      0x10 /* bit 4 set: file comment present */
+#define RESERVED     0xE0 /* bits 5..7: reserved */
+
+typedef struct gz_stream {
+    z_stream stream;
+    int      z_err;   /* error code for last stream operation */
+    int      z_eof;   /* set if end of input file */
+    FILE     *file;   /* .gz file */
+    Byte     *inbuf;  /* input buffer */
+    Byte     *outbuf; /* output buffer */
+    uLong    crc;     /* crc32 of uncompressed data */
+    char     *msg;    /* error message */
+    char     *path;   /* path name for debugging only */
+    int      transparent; /* 1 if input file is not a .gz file */
+    char     mode;    /* 'w' or 'r' */
+    z_off_t  start;   /* start of compressed data in file (header skipped) */
+    z_off_t  in;      /* bytes into deflate or inflate */
+    z_off_t  out;     /* bytes out of deflate or inflate */
+    int      back;    /* one character push-back */
+    int      last;    /* true if push-back is last character */
+} gz_stream;
+
+
+local gzFile gz_open      OF((const char *path, const char *mode, int  fd));
+local int do_flush        OF((gzFile file, int flush));
+local int    get_byte     OF((gz_stream *s));
+local void   check_header OF((gz_stream *s));
+local int    destroy      OF((gz_stream *s));
+local void   putLong      OF((FILE *file, uLong x));
+local uLong  getLong      OF((gz_stream *s));
+
+/* ===========================================================================
+     Opens a gzip (.gz) file for reading or writing. The mode parameter
+   is as in fopen ("rb" or "wb"). The file is given either by file descriptor
+   or path name (if fd == -1).
+     gz_open returns NULL if the file could not be opened or if there was
+   insufficient memory to allocate the (de)compression state; errno
+   can be checked to distinguish the two cases (if errno is zero, the
+   zlib error is Z_MEM_ERROR).
+*/
+local gzFile gz_open (path, mode, fd)
+    const char *path;
+    const char *mode;
+    int  fd;
+{
+    int err;
+    int level = Z_DEFAULT_COMPRESSION; /* compression level */
+    int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
+    char *p = (char*)mode;
+    gz_stream *s;
+    char fmode[80]; /* copy of mode, without the compression level */
+    char *m = fmode;
+
+    if (!path || !mode) return Z_NULL;
+
+    s = (gz_stream *)ALLOC(sizeof(gz_stream));
+    if (!s) return Z_NULL;
+
+    s->stream.zalloc = (alloc_func)0;
+    s->stream.zfree = (free_func)0;
+    s->stream.opaque = (voidpf)0;
+    s->stream.next_in = s->inbuf = Z_NULL;
+    s->stream.next_out = s->outbuf = Z_NULL;
+    s->stream.avail_in = s->stream.avail_out = 0;
+    s->file = NULL;
+    s->z_err = Z_OK;
+    s->z_eof = 0;
+    s->in = 0;
+    s->out = 0;
+    s->back = EOF;
+    s->crc = crc32(0L, Z_NULL, 0);
+    s->msg = NULL;
+    s->transparent = 0;
+
+    s->path = (char*)ALLOC(strlen(path)+1);
+    if (s->path == NULL) {
+        return destroy(s), (gzFile)Z_NULL;
+    }
+    strcpy(s->path, path); /* do this early for debugging */
+
+    s->mode = '\0';
+    do {
+        if (*p == 'r') s->mode = 'r';
+        if (*p == 'w' || *p == 'a') s->mode = 'w';
+        if (*p >= '0' && *p <= '9') {
+            level = *p - '0';
+        } else if (*p == 'f') {
+          strategy = Z_FILTERED;
+        } else if (*p == 'h') {
+          strategy = Z_HUFFMAN_ONLY;
+        } else if (*p == 'R') {
+          strategy = Z_RLE;
+        } else {
+            *m++ = *p; /* copy the mode */
+        }
+    } while (*p++ && m != fmode + sizeof(fmode));
+    if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
+
+    if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+        err = Z_STREAM_ERROR;
+#else
+        err = deflateInit2(&(s->stream), level,
+                           Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
+        /* windowBits is passed < 0 to suppress zlib header */
+
+        s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
+#endif
+        if (err != Z_OK || s->outbuf == Z_NULL) {
+            return destroy(s), (gzFile)Z_NULL;
+        }
+    } else {
+        s->stream.next_in  = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
+
+        err = inflateInit2(&(s->stream), -MAX_WBITS);
+        /* windowBits is passed < 0 to tell that there is no zlib header.
+         * Note that in this case inflate *requires* an extra "dummy" byte
+         * after the compressed stream in order to complete decompression and
+         * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
+         * present after the compressed stream.
+         */
+        if (err != Z_OK || s->inbuf == Z_NULL) {
+            return destroy(s), (gzFile)Z_NULL;
+        }
+    }
+    s->stream.avail_out = Z_BUFSIZE;
+
+    errno = 0;
+    s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
+
+    if (s->file == NULL) {
+        return destroy(s), (gzFile)Z_NULL;
+    }
+    if (s->mode == 'w') {
+        /* Write a very simple .gz header:
+         */
+        fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
+             Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
+        s->start = 10L;
+        /* We use 10L instead of ftell(s->file) to because ftell causes an
+         * fflush on some systems. This version of the library doesn't use
+         * start anyway in write mode, so this initialization is not
+         * necessary.
+         */
+    } else {
+        check_header(s); /* skip the .gz header */
+        s->start = ftell(s->file) - s->stream.avail_in;
+    }
+
+    return (gzFile)s;
+}
+
+/* ===========================================================================
+     Opens a gzip (.gz) file for reading or writing.
+*/
+gzFile ZEXPORT gzopen (path, mode)
+    const char *path;
+    const char *mode;
+{
+    return gz_open (path, mode, -1);
+}
+
+/* ===========================================================================
+     Associate a gzFile with the file descriptor fd. fd is not dup'ed here
+   to mimic the behavio(u)r of fdopen.
+*/
+gzFile ZEXPORT gzdopen (fd, mode)
+    int fd;
+    const char *mode;
+{
+    char name[46];      /* allow for up to 128-bit integers */
+
+    if (fd < 0) return (gzFile)Z_NULL;
+    sprintf(name, "<fd:%d>", fd); /* for debugging */
+
+    return gz_open (name, mode, fd);
+}
+
+/* ===========================================================================
+ * Update the compression level and strategy
+ */
+int ZEXPORT gzsetparams (file, level, strategy)
+    gzFile file;
+    int level;
+    int strategy;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+    /* Make room to allow flushing */
+    if (s->stream.avail_out == 0) {
+
+        s->stream.next_out = s->outbuf;
+        if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
+            s->z_err = Z_ERRNO;
+        }
+        s->stream.avail_out = Z_BUFSIZE;
+    }
+
+    return deflateParams (&(s->stream), level, strategy);
+}
+
+/* ===========================================================================
+     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+   for end of file.
+   IN assertion: the stream s has been sucessfully opened for reading.
+*/
+local int get_byte(s)
+    gz_stream *s;
+{
+    if (s->z_eof) return EOF;
+    if (s->stream.avail_in == 0) {
+        errno = 0;
+        s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+        if (s->stream.avail_in == 0) {
+            s->z_eof = 1;
+            if (ferror(s->file)) s->z_err = Z_ERRNO;
+            return EOF;
+        }
+        s->stream.next_in = s->inbuf;
+    }
+    s->stream.avail_in--;
+    return *(s->stream.next_in)++;
+}
+
+/* ===========================================================================
+      Check the gzip header of a gz_stream opened for reading. Set the stream
+    mode to transparent if the gzip magic header is not present; set s->err
+    to Z_DATA_ERROR if the magic header is present but the rest of the header
+    is incorrect.
+    IN assertion: the stream s has already been created sucessfully;
+       s->stream.avail_in is zero for the first time, but may be non-zero
+       for concatenated .gz files.
+*/
+local void check_header(s)
+    gz_stream *s;
+{
+    int method; /* method byte */
+    int flags;  /* flags byte */
+    uInt len;
+    int c;
+
+    /* Assure two bytes in the buffer so we can peek ahead -- handle case
+       where first byte of header is at the end of the buffer after the last
+       gzip segment */
+    len = s->stream.avail_in;
+    if (len < 2) {
+        if (len) s->inbuf[0] = s->stream.next_in[0];
+        errno = 0;
+        len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
+        if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
+        s->stream.avail_in += len;
+        s->stream.next_in = s->inbuf;
+        if (s->stream.avail_in < 2) {
+            s->transparent = s->stream.avail_in;
+            return;
+        }
+    }
+
+    /* Peek ahead to check the gzip magic header */
+    if (s->stream.next_in[0] != gz_magic[0] ||
+        s->stream.next_in[1] != gz_magic[1]) {
+        s->transparent = 1;
+        return;
+    }
+    s->stream.avail_in -= 2;
+    s->stream.next_in += 2;
+
+    /* Check the rest of the gzip header */
+    method = get_byte(s);
+    flags = get_byte(s);
+    if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
+        s->z_err = Z_DATA_ERROR;
+        return;
+    }
+
+    /* Discard time, xflags and OS code: */
+    for (len = 0; len < 6; len++) (void)get_byte(s);
+
+    if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
+        len  =  (uInt)get_byte(s);
+        len += ((uInt)get_byte(s))<<8;
+        /* len is garbage if EOF but the loop below will quit anyway */
+        while (len-- != 0 && get_byte(s) != EOF) ;
+    }
+    if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
+        while ((c = get_byte(s)) != 0 && c != EOF) ;
+    }
+    if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
+        while ((c = get_byte(s)) != 0 && c != EOF) ;
+    }
+    if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
+        for (len = 0; len < 2; len++) (void)get_byte(s);
+    }
+    s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
+}
+
+ /* ===========================================================================
+ * Cleanup then free the given gz_stream. Return a zlib error code.
+   Try freeing in the reverse order of allocations.
+ */
+local int destroy (s)
+    gz_stream *s;
+{
+    int err = Z_OK;
+
+    if (!s) return Z_STREAM_ERROR;
+
+    TRYFREE(s->msg);
+
+    if (s->stream.state != NULL) {
+        if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+            err = Z_STREAM_ERROR;
+#else
+            err = deflateEnd(&(s->stream));
+#endif
+        } else if (s->mode == 'r') {
+            err = inflateEnd(&(s->stream));
+        }
+    }
+    if (s->file != NULL && fclose(s->file)) {
+#ifdef ESPIPE
+        if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
+#endif
+            err = Z_ERRNO;
+    }
+    if (s->z_err < 0) err = s->z_err;
+
+    TRYFREE(s->inbuf);
+    TRYFREE(s->outbuf);
+    TRYFREE(s->path);
+    TRYFREE(s);
+    return err;
+}
+
+/* ===========================================================================
+     Reads the given number of uncompressed bytes from the compressed file.
+   gzread returns the number of bytes actually read (0 for end of file).
+*/
+int ZEXPORT gzread (file, buf, len)
+    gzFile file;
+    voidp buf;
+    unsigned len;
+{
+    gz_stream *s = (gz_stream*)file;
+    Bytef *start = (Bytef*)buf; /* starting point for crc computation */
+    Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */
+
+    if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
+
+    if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
+    if (s->z_err == Z_STREAM_END) return 0;  /* EOF */
+
+    next_out = (Byte*)buf;
+    s->stream.next_out = (Bytef*)buf;
+    s->stream.avail_out = len;
+
+    if (s->stream.avail_out && s->back != EOF) {
+        *next_out++ = s->back;
+        s->stream.next_out++;
+        s->stream.avail_out--;
+        s->back = EOF;
+        s->out++;
+        start++;
+        if (s->last) {
+            s->z_err = Z_STREAM_END;
+            return 1;
+        }
+    }
+
+    while (s->stream.avail_out != 0) {
+
+        if (s->transparent) {
+            /* Copy first the lookahead bytes: */
+            uInt n = s->stream.avail_in;
+            if (n > s->stream.avail_out) n = s->stream.avail_out;
+            if (n > 0) {
+                zmemcpy(s->stream.next_out, s->stream.next_in, n);
+                next_out += n;
+                s->stream.next_out = next_out;
+                s->stream.next_in   += n;
+                s->stream.avail_out -= n;
+                s->stream.avail_in  -= n;
+            }
+            if (s->stream.avail_out > 0) {
+                s->stream.avail_out -=
+                    (uInt)fread(next_out, 1, s->stream.avail_out, s->file);
+            }
+            len -= s->stream.avail_out;
+            s->in  += len;
+            s->out += len;
+            if (len == 0) s->z_eof = 1;
+            return (int)len;
+        }
+        if (s->stream.avail_in == 0 && !s->z_eof) {
+
+            errno = 0;
+            s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+            if (s->stream.avail_in == 0) {
+                s->z_eof = 1;
+                if (ferror(s->file)) {
+                    s->z_err = Z_ERRNO;
+                    break;
+                }
+            }
+            s->stream.next_in = s->inbuf;
+        }
+        s->in += s->stream.avail_in;
+        s->out += s->stream.avail_out;
+        s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
+        s->in -= s->stream.avail_in;
+        s->out -= s->stream.avail_out;
+
+        if (s->z_err == Z_STREAM_END) {
+            /* Check CRC and original size */
+            s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+            start = s->stream.next_out;
+
+            if (getLong(s) != s->crc) {
+                s->z_err = Z_DATA_ERROR;
+            } else {
+                (void)getLong(s);
+                /* The uncompressed length returned by above getlong() may be
+                 * different from s->out in case of concatenated .gz files.
+                 * Check for such files:
+                 */
+                check_header(s);
+                if (s->z_err == Z_OK) {
+                    inflateReset(&(s->stream));
+                    s->crc = crc32(0L, Z_NULL, 0);
+                }
+            }
+        }
+        if (s->z_err != Z_OK || s->z_eof) break;
+    }
+    s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+
+    if (len == s->stream.avail_out &&
+        (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
+        return -1;
+    return (int)(len - s->stream.avail_out);
+}
+
+
+/* ===========================================================================
+      Reads one byte from the compressed file. gzgetc returns this byte
+   or -1 in case of end of file or error.
+*/
+int ZEXPORT gzgetc(file)
+    gzFile file;
+{
+    unsigned char c;
+
+    return gzread(file, &c, 1) == 1 ? c : -1;
+}
+
+
+/* ===========================================================================
+      Push one byte back onto the stream.
+*/
+int ZEXPORT gzungetc(c, file)
+    int c;
+    gzFile file;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF;
+    s->back = c;
+    s->out--;
+    s->last = (s->z_err == Z_STREAM_END);
+    if (s->last) s->z_err = Z_OK;
+    s->z_eof = 0;
+    return c;
+}
+
+
+/* ===========================================================================
+      Reads bytes from the compressed file until len-1 characters are
+   read, or a newline character is read and transferred to buf, or an
+   end-of-file condition is encountered.  The string is then terminated
+   with a null character.
+      gzgets returns buf, or Z_NULL in case of error.
+
+      The current implementation is not optimized at all.
+*/
+char * ZEXPORT gzgets(file, buf, len)
+    gzFile file;
+    char *buf;
+    int len;
+{
+    char *b = buf;
+    if (buf == Z_NULL || len <= 0) return Z_NULL;
+
+    while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
+    *buf = '\0';
+    return b == buf && len > 0 ? Z_NULL : b;
+}
+
+
+#ifndef NO_GZCOMPRESS
+/* ===========================================================================
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of bytes actually written (0 in case of error).
+*/
+int ZEXPORT gzwrite (file, buf, len)
+    gzFile file;
+    voidpc buf;
+    unsigned len;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+    s->stream.next_in = (Bytef*)buf;
+    s->stream.avail_in = len;
+
+    while (s->stream.avail_in != 0) {
+
+        if (s->stream.avail_out == 0) {
+
+            s->stream.next_out = s->outbuf;
+            if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
+                s->z_err = Z_ERRNO;
+                break;
+            }
+            s->stream.avail_out = Z_BUFSIZE;
+        }
+        s->in += s->stream.avail_in;
+        s->out += s->stream.avail_out;
+        s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
+        s->in -= s->stream.avail_in;
+        s->out -= s->stream.avail_out;
+        if (s->z_err != Z_OK) break;
+    }
+    s->crc = crc32(s->crc, (const Bytef *)buf, len);
+
+    return (int)(len - s->stream.avail_in);
+}
+
+
+/* ===========================================================================
+     Converts, formats, and writes the args to the compressed file under
+   control of the format string, as in fprintf. gzprintf returns the number of
+   uncompressed bytes actually written (0 in case of error).
+*/
+#ifdef STDC
+#include <stdarg.h>
+
+int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
+{
+    char buf[Z_PRINTF_BUFSIZE];
+    va_list va;
+    int len;
+
+    buf[sizeof(buf) - 1] = 0;
+    va_start(va, format);
+#ifdef NO_vsnprintf
+#  ifdef HAS_vsprintf_void
+    (void)vsprintf(buf, format, va);
+    va_end(va);
+    for (len = 0; len < sizeof(buf); len++)
+        if (buf[len] == 0) break;
+#  else
+    len = vsprintf(buf, format, va);
+    va_end(va);
+#  endif
+#else
+#  ifdef HAS_vsnprintf_void
+    (void)vsnprintf(buf, sizeof(buf), format, va);
+    va_end(va);
+    len = strlen(buf);
+#  else
+    len = vsnprintf(buf, sizeof(buf), format, va);
+    va_end(va);
+#  endif
+#endif
+    if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0)
+        return 0;
+    return gzwrite(file, buf, (unsigned)len);
+}
+#else /* not ANSI C */
+
+int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+                       a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
+    gzFile file;
+    const char *format;
+    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
+{
+    char buf[Z_PRINTF_BUFSIZE];
+    int len;
+
+    buf[sizeof(buf) - 1] = 0;
+#ifdef NO_snprintf
+#  ifdef HAS_sprintf_void
+    sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
+            a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+    for (len = 0; len < sizeof(buf); len++)
+        if (buf[len] == 0) break;
+#  else
+    len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
+                a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+#  endif
+#else
+#  ifdef HAS_snprintf_void
+    snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
+             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+    len = strlen(buf);
+#  else
+    len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
+                 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+#  endif
+#endif
+    if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0)
+        return 0;
+    return gzwrite(file, buf, len);
+}
+#endif
+
+/* ===========================================================================
+      Writes c, converted to an unsigned char, into the compressed file.
+   gzputc returns the value that was written, or -1 in case of error.
+*/
+int ZEXPORT gzputc(file, c)
+    gzFile file;
+    int c;
+{
+    unsigned char cc = (unsigned char) c; /* required for big endian systems */
+
+    return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
+}
+
+
+/* ===========================================================================
+      Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+      gzputs returns the number of characters written, or -1 in case of error.
+*/
+int ZEXPORT gzputs(file, s)
+    gzFile file;
+    const char *s;
+{
+    return gzwrite(file, (char*)s, (unsigned)strlen(s));
+}
+
+
+/* ===========================================================================
+     Flushes all pending output into the compressed file. The parameter
+   flush is as in the deflate() function.
+*/
+local int do_flush (file, flush)
+    gzFile file;
+    int flush;
+{
+    uInt len;
+    int done = 0;
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+    s->stream.avail_in = 0; /* should be zero already anyway */
+
+    for (;;) {
+        len = Z_BUFSIZE - s->stream.avail_out;
+
+        if (len != 0) {
+            if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
+                s->z_err = Z_ERRNO;
+                return Z_ERRNO;
+            }
+            s->stream.next_out = s->outbuf;
+            s->stream.avail_out = Z_BUFSIZE;
+        }
+        if (done) break;
+        s->out += s->stream.avail_out;
+        s->z_err = deflate(&(s->stream), flush);
+        s->out -= s->stream.avail_out;
+
+        /* Ignore the second of two consecutive flushes: */
+        if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
+
+        /* deflate has finished flushing only when it hasn't used up
+         * all the available space in the output buffer:
+         */
+        done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
+
+        if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
+    }
+    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
+}
+
+int ZEXPORT gzflush (file, flush)
+     gzFile file;
+     int flush;
+{
+    gz_stream *s = (gz_stream*)file;
+    int err = do_flush (file, flush);
+
+    if (err) return err;
+    fflush(s->file);
+    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
+}
+#endif /* NO_GZCOMPRESS */
+
+/* ===========================================================================
+      Sets the starting position for the next gzread or gzwrite on the given
+   compressed file. The offset represents a number of bytes in the
+      gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error.
+      SEEK_END is not implemented, returns error.
+      In this version of the library, gzseek can be extremely slow.
+*/
+z_off_t ZEXPORT gzseek (file, offset, whence)
+    gzFile file;
+    z_off_t offset;
+    int whence;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || whence == SEEK_END ||
+        s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
+        return -1L;
+    }
+
+    if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+        return -1L;
+#else
+        if (whence == SEEK_SET) {
+            offset -= s->in;
+        }
+        if (offset < 0) return -1L;
+
+        /* At this point, offset is the number of zero bytes to write. */
+        if (s->inbuf == Z_NULL) {
+            s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
+            if (s->inbuf == Z_NULL) return -1L;
+            zmemzero(s->inbuf, Z_BUFSIZE);
+        }
+        while (offset > 0)  {
+            uInt size = Z_BUFSIZE;
+            if (offset < Z_BUFSIZE) size = (uInt)offset;
+
+            size = gzwrite(file, s->inbuf, size);
+            if (size == 0) return -1L;
+
+            offset -= size;
+        }
+        return s->in;
+#endif
+    }
+    /* Rest of function is for reading only */
+
+    /* compute absolute position */
+    if (whence == SEEK_CUR) {
+        offset += s->out;
+    }
+    if (offset < 0) return -1L;
+
+    if (s->transparent) {
+        /* map to fseek */
+        s->back = EOF;
+        s->stream.avail_in = 0;
+        s->stream.next_in = s->inbuf;
+        if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
+
+        s->in = s->out = offset;
+        return offset;
+    }
+
+    /* For a negative seek, rewind and use positive seek */
+    if (offset >= s->out) {
+        offset -= s->out;
+    } else if (gzrewind(file) < 0) {
+        return -1L;
+    }
+    /* offset is now the number of bytes to skip. */
+
+    if (offset != 0 && s->outbuf == Z_NULL) {
+        s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
+        if (s->outbuf == Z_NULL) return -1L;
+    }
+    if (offset && s->back != EOF) {
+        s->back = EOF;
+        s->out++;
+        offset--;
+        if (s->last) s->z_err = Z_STREAM_END;
+    }
+    while (offset > 0)  {
+        int size = Z_BUFSIZE;
+        if (offset < Z_BUFSIZE) size = (int)offset;
+
+        size = gzread(file, s->outbuf, (uInt)size);
+        if (size <= 0) return -1L;
+        offset -= size;
+    }
+    return s->out;
+}
+
+/* ===========================================================================
+     Rewinds input file.
+*/
+int ZEXPORT gzrewind (file)
+    gzFile file;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || s->mode != 'r') return -1;
+
+    s->z_err = Z_OK;
+    s->z_eof = 0;
+    s->back = EOF;
+    s->stream.avail_in = 0;
+    s->stream.next_in = s->inbuf;
+    s->crc = crc32(0L, Z_NULL, 0);
+    if (!s->transparent) (void)inflateReset(&s->stream);
+    s->in = 0;
+    s->out = 0;
+    return fseek(s->file, s->start, SEEK_SET);
+}
+
+/* ===========================================================================
+     Returns the starting position for the next gzread or gzwrite on the
+   given compressed file. This position represents a number of bytes in the
+   uncompressed data stream.
+*/
+z_off_t ZEXPORT gztell (file)
+    gzFile file;
+{
+    return gzseek(file, 0L, SEEK_CUR);
+}
+
+/* ===========================================================================
+     Returns 1 when EOF has previously been detected reading the given
+   input stream, otherwise zero.
+*/
+int ZEXPORT gzeof (file)
+    gzFile file;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    /* With concatenated compressed files that can have embedded
+     * crc trailers, z_eof is no longer the only/best indicator of EOF
+     * on a gz_stream. Handle end-of-stream error explicitly here.
+     */
+    if (s == NULL || s->mode != 'r') return 0;
+    if (s->z_eof) return 1;
+    return s->z_err == Z_STREAM_END;
+}
+
+/* ===========================================================================
+     Returns 1 if reading and doing so transparently, otherwise zero.
+*/
+int ZEXPORT gzdirect (file)
+    gzFile file;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || s->mode != 'r') return 0;
+    return s->transparent;
+}
+
+/* ===========================================================================
+   Outputs a long in LSB order to the given file
+*/
+local void putLong (file, x)
+    FILE *file;
+    uLong x;
+{
+    int n;
+    for (n = 0; n < 4; n++) {
+        fputc((int)(x & 0xff), file);
+        x >>= 8;
+    }
+}
+
+/* ===========================================================================
+   Reads a long in LSB order from the given gz_stream. Sets z_err in case
+   of error.
+*/
+local uLong getLong (s)
+    gz_stream *s;
+{
+    uLong x = (uLong)get_byte(s);
+    int c;
+
+    x += ((uLong)get_byte(s))<<8;
+    x += ((uLong)get_byte(s))<<16;
+    c = get_byte(s);
+    if (c == EOF) s->z_err = Z_DATA_ERROR;
+    x += ((uLong)c)<<24;
+    return x;
+}
+
+/* ===========================================================================
+     Flushes all pending output if necessary, closes the compressed file
+   and deallocates all the (de)compression state.
+*/
+int ZEXPORT gzclose (file)
+    gzFile file;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL) return Z_STREAM_ERROR;
+
+    if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+        return Z_STREAM_ERROR;
+#else
+        if (do_flush (file, Z_FINISH) != Z_OK)
+            return destroy((gz_stream*)file);
+
+        putLong (s->file, s->crc);
+        putLong (s->file, (uLong)(s->in & 0xffffffff));
+#endif
+    }
+    return destroy((gz_stream*)file);
+}
+
+#ifdef STDC
+#  define zstrerror(errnum) strerror(errnum)
+#else
+#  define zstrerror(errnum) ""
+#endif
+
+/* ===========================================================================
+     Returns the error message for the last error which occurred on the
+   given compressed file. errnum is set to zlib error number. If an
+   error occurred in the file system and not in the compression library,
+   errnum is set to Z_ERRNO and the application may consult errno
+   to get the exact error code.
+*/
+const char * ZEXPORT gzerror (file, errnum)
+    gzFile file;
+    int *errnum;
+{
+    char *m;
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL) {
+        *errnum = Z_STREAM_ERROR;
+        return (const char*)ERR_MSG(Z_STREAM_ERROR);
+    }
+    *errnum = s->z_err;
+    if (*errnum == Z_OK) return (const char*)"";
+
+    m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
+
+    if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
+
+    TRYFREE(s->msg);
+    s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
+    if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR);
+    strcpy(s->msg, s->path);
+    strcat(s->msg, ": ");
+    strcat(s->msg, m);
+    return (const char*)s->msg;
+}
+
+/* ===========================================================================
+     Clear the error and end-of-file flags, and do the same for the real file.
+*/
+void ZEXPORT gzclearerr (file)
+    gzFile file;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL) return;
+    if (s->z_err != Z_STREAM_END) s->z_err = Z_OK;
+    s->z_eof = 0;
+    clearerr(s->file);
+}
Index: /trunk/minix/lib/zlib-1.2.3/infback.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/infback.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/infback.c	(revision 9)
@@ -0,0 +1,623 @@
+/* infback.c -- inflate using a call-back interface
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+   This code is largely copied from inflate.c.  Normally either infback.o or
+   inflate.o would be linked into an application--not both.  The interface
+   with inffast.c is retained so that optimized assembler-coded versions of
+   inflate_fast() can be used with either inflate.c or infback.c.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+
+/*
+   strm provides memory allocation functions in zalloc and zfree, or
+   Z_NULL to use the library memory allocation functions.
+
+   windowBits is in the range 8..15, and window is a user-supplied
+   window and output buffer that is 2**windowBits bytes.
+ */
+int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
+z_streamp strm;
+int windowBits;
+unsigned char FAR *window;
+const char *version;
+int stream_size;
+{
+    struct inflate_state FAR *state;
+
+    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+        stream_size != (int)(sizeof(z_stream)))
+        return Z_VERSION_ERROR;
+    if (strm == Z_NULL || window == Z_NULL ||
+        windowBits < 8 || windowBits > 15)
+        return Z_STREAM_ERROR;
+    strm->msg = Z_NULL;                 /* in case we return an error */
+    if (strm->zalloc == (alloc_func)0) {
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
+                                               sizeof(struct inflate_state));
+    if (state == Z_NULL) return Z_MEM_ERROR;
+    Tracev((stderr, "inflate: allocated\n"));
+    strm->state = (struct internal_state FAR *)state;
+    state->dmax = 32768U;
+    state->wbits = windowBits;
+    state->wsize = 1U << windowBits;
+    state->window = window;
+    state->write = 0;
+    state->whave = 0;
+    return Z_OK;
+}
+
+/*
+   Return state with length and distance decoding tables and index sizes set to
+   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
+   If BUILDFIXED is defined, then instead this routine builds the tables the
+   first time it's called, and returns those tables the first time and
+   thereafter.  This reduces the size of the code by about 2K bytes, in
+   exchange for a little execution time.  However, BUILDFIXED should not be
+   used for threaded applications, since the rewriting of the tables and virgin
+   may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+    static int virgin = 1;
+    static code *lenfix, *distfix;
+    static code fixed[544];
+
+    /* build fixed huffman tables if first call (may not be thread safe) */
+    if (virgin) {
+        unsigned sym, bits;
+        static code *next;
+
+        /* literal/length table */
+        sym = 0;
+        while (sym < 144) state->lens[sym++] = 8;
+        while (sym < 256) state->lens[sym++] = 9;
+        while (sym < 280) state->lens[sym++] = 7;
+        while (sym < 288) state->lens[sym++] = 8;
+        next = fixed;
+        lenfix = next;
+        bits = 9;
+        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+        /* distance table */
+        sym = 0;
+        while (sym < 32) state->lens[sym++] = 5;
+        distfix = next;
+        bits = 5;
+        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+        /* do this just once */
+        virgin = 0;
+    }
+#else /* !BUILDFIXED */
+#   include "inffixed.h"
+#endif /* BUILDFIXED */
+    state->lencode = lenfix;
+    state->lenbits = 9;
+    state->distcode = distfix;
+    state->distbits = 5;
+}
+
+/* Macros for inflateBack(): */
+
+/* Load returned state from inflate_fast() */
+#define LOAD() \
+    do { \
+        put = strm->next_out; \
+        left = strm->avail_out; \
+        next = strm->next_in; \
+        have = strm->avail_in; \
+        hold = state->hold; \
+        bits = state->bits; \
+    } while (0)
+
+/* Set state from registers for inflate_fast() */
+#define RESTORE() \
+    do { \
+        strm->next_out = put; \
+        strm->avail_out = left; \
+        strm->next_in = next; \
+        strm->avail_in = have; \
+        state->hold = hold; \
+        state->bits = bits; \
+    } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+    do { \
+        hold = 0; \
+        bits = 0; \
+    } while (0)
+
+/* Assure that some input is available.  If input is requested, but denied,
+   then return a Z_BUF_ERROR from inflateBack(). */
+#define PULL() \
+    do { \
+        if (have == 0) { \
+            have = in(in_desc, &next); \
+            if (have == 0) { \
+                next = Z_NULL; \
+                ret = Z_BUF_ERROR; \
+                goto inf_leave; \
+            } \
+        } \
+    } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflateBack()
+   with an error if there is no input available. */
+#define PULLBYTE() \
+    do { \
+        PULL(); \
+        have--; \
+        hold += (unsigned long)(*next++) << bits; \
+        bits += 8; \
+    } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator.  If there is
+   not enough available input to do that, then return from inflateBack() with
+   an error. */
+#define NEEDBITS(n) \
+    do { \
+        while (bits < (unsigned)(n)) \
+            PULLBYTE(); \
+    } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+    ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+    do { \
+        hold >>= (n); \
+        bits -= (unsigned)(n); \
+    } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+    do { \
+        hold >>= bits & 7; \
+        bits -= bits & 7; \
+    } while (0)
+
+/* Assure that some output space is available, by writing out the window
+   if it's full.  If the write fails, return from inflateBack() with a
+   Z_BUF_ERROR. */
+#define ROOM() \
+    do { \
+        if (left == 0) { \
+            put = state->window; \
+            left = state->wsize; \
+            state->whave = left; \
+            if (out(out_desc, put, left)) { \
+                ret = Z_BUF_ERROR; \
+                goto inf_leave; \
+            } \
+        } \
+    } while (0)
+
+/*
+   strm provides the memory allocation functions and window buffer on input,
+   and provides information on the unused input on return.  For Z_DATA_ERROR
+   returns, strm will also provide an error message.
+
+   in() and out() are the call-back input and output functions.  When
+   inflateBack() needs more input, it calls in().  When inflateBack() has
+   filled the window with output, or when it completes with data in the
+   window, it calls out() to write out the data.  The application must not
+   change the provided input until in() is called again or inflateBack()
+   returns.  The application must not change the window/output buffer until
+   inflateBack() returns.
+
+   in() and out() are called with a descriptor parameter provided in the
+   inflateBack() call.  This parameter can be a structure that provides the
+   information required to do the read or write, as well as accumulated
+   information on the input and output such as totals and check values.
+
+   in() should return zero on failure.  out() should return non-zero on
+   failure.  If either in() or out() fails, than inflateBack() returns a
+   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
+   was in() or out() that caused in the error.  Otherwise,  inflateBack()
+   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
+   error, or Z_MEM_ERROR if it could not allocate memory for the state.
+   inflateBack() can also return Z_STREAM_ERROR if the input parameters
+   are not correct, i.e. strm is Z_NULL or the state was not initialized.
+ */
+int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
+z_streamp strm;
+in_func in;
+void FAR *in_desc;
+out_func out;
+void FAR *out_desc;
+{
+    struct inflate_state FAR *state;
+    unsigned char FAR *next;    /* next input */
+    unsigned char FAR *put;     /* next output */
+    unsigned have, left;        /* available input and output */
+    unsigned long hold;         /* bit buffer */
+    unsigned bits;              /* bits in bit buffer */
+    unsigned copy;              /* number of stored or match bytes to copy */
+    unsigned char FAR *from;    /* where to copy match bytes from */
+    code this;                  /* current decoding table entry */
+    code last;                  /* parent table entry */
+    unsigned len;               /* length to copy for repeats, bits to drop */
+    int ret;                    /* return code */
+    static const unsigned short order[19] = /* permutation of code lengths */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+    /* Check that the strm exists and that the state was initialized */
+    if (strm == Z_NULL || strm->state == Z_NULL)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* Reset the state */
+    strm->msg = Z_NULL;
+    state->mode = TYPE;
+    state->last = 0;
+    state->whave = 0;
+    next = strm->next_in;
+    have = next != Z_NULL ? strm->avail_in : 0;
+    hold = 0;
+    bits = 0;
+    put = state->window;
+    left = state->wsize;
+
+    /* Inflate until end of block marked as last */
+    for (;;)
+        switch (state->mode) {
+        case TYPE:
+            /* determine and dispatch block type */
+            if (state->last) {
+                BYTEBITS();
+                state->mode = DONE;
+                break;
+            }
+            NEEDBITS(3);
+            state->last = BITS(1);
+            DROPBITS(1);
+            switch (BITS(2)) {
+            case 0:                             /* stored block */
+                Tracev((stderr, "inflate:     stored block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = STORED;
+                break;
+            case 1:                             /* fixed block */
+                fixedtables(state);
+                Tracev((stderr, "inflate:     fixed codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = LEN;              /* decode codes */
+                break;
+            case 2:                             /* dynamic block */
+                Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = TABLE;
+                break;
+            case 3:
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
+            }
+            DROPBITS(2);
+            break;
+
+        case STORED:
+            /* get and verify stored block length */
+            BYTEBITS();                         /* go to byte boundary */
+            NEEDBITS(32);
+            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
+                break;
+            }
+            state->length = (unsigned)hold & 0xffff;
+            Tracev((stderr, "inflate:       stored length %u\n",
+                    state->length));
+            INITBITS();
+
+            /* copy stored block from input to output */
+            while (state->length != 0) {
+                copy = state->length;
+                PULL();
+                ROOM();
+                if (copy > have) copy = have;
+                if (copy > left) copy = left;
+                zmemcpy(put, next, copy);
+                have -= copy;
+                next += copy;
+                left -= copy;
+                put += copy;
+                state->length -= copy;
+            }
+            Tracev((stderr, "inflate:       stored end\n"));
+            state->mode = TYPE;
+            break;
+
+        case TABLE:
+            /* get dynamic table entries descriptor */
+            NEEDBITS(14);
+            state->nlen = BITS(5) + 257;
+            DROPBITS(5);
+            state->ndist = BITS(5) + 1;
+            DROPBITS(5);
+            state->ncode = BITS(4) + 4;
+            DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+            if (state->nlen > 286 || state->ndist > 30) {
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracev((stderr, "inflate:       table sizes ok\n"));
+
+            /* get code length code lengths (not a typo) */
+            state->have = 0;
+            while (state->have < state->ncode) {
+                NEEDBITS(3);
+                state->lens[order[state->have++]] = (unsigned short)BITS(3);
+                DROPBITS(3);
+            }
+            while (state->have < 19)
+                state->lens[order[state->have++]] = 0;
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 7;
+            ret = inflate_table(CODES, state->lens, 19, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       code lengths ok\n"));
+
+            /* get length and distance code code lengths */
+            state->have = 0;
+            while (state->have < state->nlen + state->ndist) {
+                for (;;) {
+                    this = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                if (this.val < 16) {
+                    NEEDBITS(this.bits);
+                    DROPBITS(this.bits);
+                    state->lens[state->have++] = this.val;
+                }
+                else {
+                    if (this.val == 16) {
+                        NEEDBITS(this.bits + 2);
+                        DROPBITS(this.bits);
+                        if (state->have == 0) {
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
+                            break;
+                        }
+                        len = (unsigned)(state->lens[state->have - 1]);
+                        copy = 3 + BITS(2);
+                        DROPBITS(2);
+                    }
+                    else if (this.val == 17) {
+                        NEEDBITS(this.bits + 3);
+                        DROPBITS(this.bits);
+                        len = 0;
+                        copy = 3 + BITS(3);
+                        DROPBITS(3);
+                    }
+                    else {
+                        NEEDBITS(this.bits + 7);
+                        DROPBITS(this.bits);
+                        len = 0;
+                        copy = 11 + BITS(7);
+                        DROPBITS(7);
+                    }
+                    if (state->have + copy > state->nlen + state->ndist) {
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
+                        break;
+                    }
+                    while (copy--)
+                        state->lens[state->have++] = (unsigned short)len;
+                }
+            }
+
+            /* handle error breaks in while */
+            if (state->mode == BAD) break;
+
+            /* build code tables */
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 9;
+            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
+                break;
+            }
+            state->distcode = (code const FAR *)(state->next);
+            state->distbits = 6;
+            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+                            &(state->next), &(state->distbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       codes ok\n"));
+            state->mode = LEN;
+
+        case LEN:
+            /* use inflate_fast() if we have enough input and output */
+            if (have >= 6 && left >= 258) {
+                RESTORE();
+                if (state->whave < state->wsize)
+                    state->whave = state->wsize - left;
+                inflate_fast(strm, state->wsize);
+                LOAD();
+                break;
+            }
+
+            /* get a literal, length, or end-of-block code */
+            for (;;) {
+                this = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(this.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if (this.op && (this.op & 0xf0) == 0) {
+                last = this;
+                for (;;) {
+                    this = state->lencode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(this.bits);
+            state->length = (unsigned)this.val;
+
+            /* process literal */
+            if (this.op == 0) {
+                Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+                        "inflate:         literal '%c'\n" :
+                        "inflate:         literal 0x%02x\n", this.val));
+                ROOM();
+                *put++ = (unsigned char)(state->length);
+                left--;
+                state->mode = LEN;
+                break;
+            }
+
+            /* process end of block */
+            if (this.op & 32) {
+                Tracevv((stderr, "inflate:         end of block\n"));
+                state->mode = TYPE;
+                break;
+            }
+
+            /* invalid code */
+            if (this.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
+                break;
+            }
+
+            /* length code -- get extra bits, if any */
+            state->extra = (unsigned)(this.op) & 15;
+            if (state->extra != 0) {
+                NEEDBITS(state->extra);
+                state->length += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+            Tracevv((stderr, "inflate:         length %u\n", state->length));
+
+            /* get distance code */
+            for (;;) {
+                this = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(this.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if ((this.op & 0xf0) == 0) {
+                last = this;
+                for (;;) {
+                    this = state->distcode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(this.bits);
+            if (this.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+            state->offset = (unsigned)this.val;
+
+            /* get distance extra bits, if any */
+            state->extra = (unsigned)(this.op) & 15;
+            if (state->extra != 0) {
+                NEEDBITS(state->extra);
+                state->offset += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+            if (state->offset > state->wsize - (state->whave < state->wsize ?
+                                                left : 0)) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
+
+            /* copy match from window to output */
+            do {
+                ROOM();
+                copy = state->wsize - state->offset;
+                if (copy < left) {
+                    from = put + copy;
+                    copy = left - copy;
+                }
+                else {
+                    from = put - state->offset;
+                    copy = left;
+                }
+                if (copy > state->length) copy = state->length;
+                state->length -= copy;
+                left -= copy;
+                do {
+                    *put++ = *from++;
+                } while (--copy);
+            } while (state->length != 0);
+            break;
+
+        case DONE:
+            /* inflate stream terminated properly -- write leftover output */
+            ret = Z_STREAM_END;
+            if (left < state->wsize) {
+                if (out(out_desc, state->window, state->wsize - left))
+                    ret = Z_BUF_ERROR;
+            }
+            goto inf_leave;
+
+        case BAD:
+            ret = Z_DATA_ERROR;
+            goto inf_leave;
+
+        default:                /* can't happen, but makes compilers happy */
+            ret = Z_STREAM_ERROR;
+            goto inf_leave;
+        }
+
+    /* Return unused input */
+  inf_leave:
+    strm->next_in = next;
+    strm->avail_in = have;
+    return ret;
+}
+
+int ZEXPORT inflateBackEnd(strm)
+z_streamp strm;
+{
+    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+        return Z_STREAM_ERROR;
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+    Tracev((stderr, "inflate: end\n"));
+    return Z_OK;
+}
Index: /trunk/minix/lib/zlib-1.2.3/inffast.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/inffast.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/inffast.c	(revision 9)
@@ -0,0 +1,318 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifndef ASMINF
+
+/* Allow machine dependent optimization for post-increment or pre-increment.
+   Based on testing to date,
+   Pre-increment preferred for:
+   - PowerPC G3 (Adler)
+   - MIPS R5000 (Randers-Pehrson)
+   Post-increment preferred for:
+   - none
+   No measurable difference:
+   - Pentium III (Anderson)
+   - M68060 (Nikl)
+ */
+#ifdef POSTINC
+#  define OFF 0
+#  define PUP(a) *(a)++
+#else
+#  define OFF 1
+#  define PUP(a) *++(a)
+#endif
+
+/*
+   Decode literal, length, and distance codes and write out the resulting
+   literal and match bytes until either not enough input or output is
+   available, an end-of-block is encountered, or a data error is encountered.
+   When large enough input and output buffers are supplied to inflate(), for
+   example, a 16K input buffer and a 64K output buffer, more than 95% of the
+   inflate execution time is spent in this routine.
+
+   Entry assumptions:
+
+        state->mode == LEN
+        strm->avail_in >= 6
+        strm->avail_out >= 258
+        start >= strm->avail_out
+        state->bits < 8
+
+   On return, state->mode is one of:
+
+        LEN -- ran out of enough output space or enough available input
+        TYPE -- reached end of block code, inflate() to interpret next block
+        BAD -- error in block data
+
+   Notes:
+
+    - The maximum input bits used by a length/distance pair is 15 bits for the
+      length code, 5 bits for the length extra, 15 bits for the distance code,
+      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
+      Therefore if strm->avail_in >= 6, then there is enough input to avoid
+      checking for available input while decoding.
+
+    - The maximum bytes that a single length/distance pair can output is 258
+      bytes, which is the maximum length that can be coded.  inflate_fast()
+      requires strm->avail_out >= 258 for each loop to avoid checking for
+      output space.
+ */
+void inflate_fast(strm, start)
+z_streamp strm;
+unsigned start;         /* inflate()'s starting value for strm->avail_out */
+{
+    struct inflate_state FAR *state;
+    unsigned char FAR *in;      /* local strm->next_in */
+    unsigned char FAR *last;    /* while in < last, enough input available */
+    unsigned char FAR *out;     /* local strm->next_out */
+    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
+    unsigned char FAR *end;     /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+    unsigned dmax;              /* maximum distance from zlib header */
+#endif
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned write;             /* window write index */
+    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
+    unsigned long hold;         /* local strm->hold */
+    unsigned bits;              /* local strm->bits */
+    code const FAR *lcode;      /* local strm->lencode */
+    code const FAR *dcode;      /* local strm->distcode */
+    unsigned lmask;             /* mask for first level of length codes */
+    unsigned dmask;             /* mask for first level of distance codes */
+    code this;                  /* retrieved table entry */
+    unsigned op;                /* code bits, operation, extra bits, or */
+                                /*  window position, window bytes to copy */
+    unsigned len;               /* match length, unused bytes */
+    unsigned dist;              /* match distance */
+    unsigned char FAR *from;    /* where to copy match from */
+
+    /* copy state to local variables */
+    state = (struct inflate_state FAR *)strm->state;
+    in = strm->next_in - OFF;
+    last = in + (strm->avail_in - 5);
+    out = strm->next_out - OFF;
+    beg = out - (start - strm->avail_out);
+    end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+    dmax = state->dmax;
+#endif
+    wsize = state->wsize;
+    whave = state->whave;
+    write = state->write;
+    window = state->window;
+    hold = state->hold;
+    bits = state->bits;
+    lcode = state->lencode;
+    dcode = state->distcode;
+    lmask = (1U << state->lenbits) - 1;
+    dmask = (1U << state->distbits) - 1;
+
+    /* decode literals and length/distances until end-of-block or not enough
+       input data or output space */
+    do {
+        if (bits < 15) {
+            hold += (unsigned long)(PUP(in)) << bits;
+            bits += 8;
+            hold += (unsigned long)(PUP(in)) << bits;
+            bits += 8;
+        }
+        this = lcode[hold & lmask];
+      dolen:
+        op = (unsigned)(this.bits);
+        hold >>= op;
+        bits -= op;
+        op = (unsigned)(this.op);
+        if (op == 0) {                          /* literal */
+            Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+                    "inflate:         literal '%c'\n" :
+                    "inflate:         literal 0x%02x\n", this.val));
+            PUP(out) = (unsigned char)(this.val);
+        }
+        else if (op & 16) {                     /* length base */
+            len = (unsigned)(this.val);
+            op &= 15;                           /* number of extra bits */
+            if (op) {
+                if (bits < op) {
+                    hold += (unsigned long)(PUP(in)) << bits;
+                    bits += 8;
+                }
+                len += (unsigned)hold & ((1U << op) - 1);
+                hold >>= op;
+                bits -= op;
+            }
+            Tracevv((stderr, "inflate:         length %u\n", len));
+            if (bits < 15) {
+                hold += (unsigned long)(PUP(in)) << bits;
+                bits += 8;
+                hold += (unsigned long)(PUP(in)) << bits;
+                bits += 8;
+            }
+            this = dcode[hold & dmask];
+          dodist:
+            op = (unsigned)(this.bits);
+            hold >>= op;
+            bits -= op;
+            op = (unsigned)(this.op);
+            if (op & 16) {                      /* distance base */
+                dist = (unsigned)(this.val);
+                op &= 15;                       /* number of extra bits */
+                if (bits < op) {
+                    hold += (unsigned long)(PUP(in)) << bits;
+                    bits += 8;
+                    if (bits < op) {
+                        hold += (unsigned long)(PUP(in)) << bits;
+                        bits += 8;
+                    }
+                }
+                dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+                if (dist > dmax) {
+                    strm->msg = (char *)"invalid distance too far back";
+                    state->mode = BAD;
+                    break;
+                }
+#endif
+                hold >>= op;
+                bits -= op;
+                Tracevv((stderr, "inflate:         distance %u\n", dist));
+                op = (unsigned)(out - beg);     /* max distance in output */
+                if (dist > op) {                /* see if copy from window */
+                    op = dist - op;             /* distance back in window */
+                    if (op > whave) {
+                        strm->msg = (char *)"invalid distance too far back";
+                        state->mode = BAD;
+                        break;
+                    }
+                    from = window - OFF;
+                    if (write == 0) {           /* very common case */
+                        from += wsize - op;
+                        if (op < len) {         /* some from window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = out - dist;  /* rest from output */
+                        }
+                    }
+                    else if (write < op) {      /* wrap around window */
+                        from += wsize + write - op;
+                        op -= write;
+                        if (op < len) {         /* some from end of window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = window - OFF;
+                            if (write < len) {  /* some from start of window */
+                                op = write;
+                                len -= op;
+                                do {
+                                    PUP(out) = PUP(from);
+                                } while (--op);
+                                from = out - dist;      /* rest from output */
+                            }
+                        }
+                    }
+                    else {                      /* contiguous in window */
+                        from += write - op;
+                        if (op < len) {         /* some from window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = out - dist;  /* rest from output */
+                        }
+                    }
+                    while (len > 2) {
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        len -= 3;
+                    }
+                    if (len) {
+                        PUP(out) = PUP(from);
+                        if (len > 1)
+                            PUP(out) = PUP(from);
+                    }
+                }
+                else {
+                    from = out - dist;          /* copy direct from output */
+                    do {                        /* minimum length is three */
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        len -= 3;
+                    } while (len > 2);
+                    if (len) {
+                        PUP(out) = PUP(from);
+                        if (len > 1)
+                            PUP(out) = PUP(from);
+                    }
+                }
+            }
+            else if ((op & 64) == 0) {          /* 2nd level distance code */
+                this = dcode[this.val + (hold & ((1U << op) - 1))];
+                goto dodist;
+            }
+            else {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+        }
+        else if ((op & 64) == 0) {              /* 2nd level length code */
+            this = lcode[this.val + (hold & ((1U << op) - 1))];
+            goto dolen;
+        }
+        else if (op & 32) {                     /* end-of-block */
+            Tracevv((stderr, "inflate:         end of block\n"));
+            state->mode = TYPE;
+            break;
+        }
+        else {
+            strm->msg = (char *)"invalid literal/length code";
+            state->mode = BAD;
+            break;
+        }
+    } while (in < last && out < end);
+
+    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+    len = bits >> 3;
+    in -= len;
+    bits -= len << 3;
+    hold &= (1U << bits) - 1;
+
+    /* update state and return */
+    strm->next_in = in + OFF;
+    strm->next_out = out + OFF;
+    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+    strm->avail_out = (unsigned)(out < end ?
+                                 257 + (end - out) : 257 - (out - end));
+    state->hold = hold;
+    state->bits = bits;
+    return;
+}
+
+/*
+   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+   - Using bit fields for code structure
+   - Different op definition to avoid & for extra bits (do & for table bits)
+   - Three separate decoding do-loops for direct, window, and write == 0
+   - Special case for distance > 1 copies to do overlapped load and store copy
+   - Explicit branch predictions (based on measured branch probabilities)
+   - Deferring match copy and interspersed it with decoding subsequent codes
+   - Swapping literal/length else
+   - Swapping window/direct else
+   - Larger unrolled copy loops (three is about right)
+   - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
Index: /trunk/minix/lib/zlib-1.2.3/inffast.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/inffast.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/inffast.h	(revision 9)
@@ -0,0 +1,11 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+void inflate_fast OF((z_streamp strm, unsigned start));
Index: /trunk/minix/lib/zlib-1.2.3/inffixed.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/inffixed.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/inffixed.h	(revision 9)
@@ -0,0 +1,94 @@
+    /* inffixed.h -- table for decoding fixed codes
+     * Generated automatically by makefixed().
+     */
+
+    /* WARNING: this file should *not* be used by applications. It
+       is part of the implementation of the compression library and
+       is subject to change. Applications should only use zlib.h.
+     */
+
+    static const code lenfix[512] = {
+        {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+        {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+        {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+        {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+        {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+        {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+        {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+        {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+        {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+        {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+        {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+        {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+        {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+        {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+        {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+        {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+        {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+        {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+        {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+        {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+        {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+        {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+        {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+        {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+        {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+        {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+        {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+        {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+        {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+        {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+        {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+        {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+        {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+        {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+        {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+        {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+        {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+        {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+        {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+        {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+        {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+        {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+        {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+        {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+        {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+        {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+        {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+        {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+        {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+        {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+        {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+        {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+        {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+        {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+        {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+        {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+        {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+        {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+        {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+        {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+        {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+        {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+        {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+        {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+        {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+        {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+        {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+        {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+        {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+        {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+        {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+        {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+        {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+        {0,9,255}
+    };
+
+    static const code distfix[32] = {
+        {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+        {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+        {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+        {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+        {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+        {22,5,193},{64,5,0}
+    };
Index: /trunk/minix/lib/zlib-1.2.3/inflate.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/inflate.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/inflate.c	(revision 9)
@@ -0,0 +1,1368 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0    24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ *   creation of window when not needed, minimize use of window when it is
+ *   needed, make inffast.c even faster, implement gzip decoding, and to
+ *   improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1    25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2    4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ *   to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3    22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ *   buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4    1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common write == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ *   source file infback.c to provide a call-back interface to inflate for
+ *   programs like gzip and unzip -- uses window as output buffer to avoid
+ *   window copying
+ *
+ * 1.2.beta5    1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ *   input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6    4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ *   make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7    27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0        9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ *   for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ *   and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef MAKEFIXED
+#  ifndef BUILDFIXED
+#    define BUILDFIXED
+#  endif
+#endif
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, unsigned out));
+#ifdef BUILDFIXED
+   void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
+                              unsigned len));
+
+int ZEXPORT inflateReset(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    strm->total_in = strm->total_out = state->total = 0;
+    strm->msg = Z_NULL;
+    strm->adler = 1;        /* to support ill-conceived Java test suite */
+    state->mode = HEAD;
+    state->last = 0;
+    state->havedict = 0;
+    state->dmax = 32768U;
+    state->head = Z_NULL;
+    state->wsize = 0;
+    state->whave = 0;
+    state->write = 0;
+    state->hold = 0;
+    state->bits = 0;
+    state->lencode = state->distcode = state->next = state->codes;
+    Tracev((stderr, "inflate: reset\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflatePrime(strm, bits, value)
+z_streamp strm;
+int bits;
+int value;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+    value &= (1L << bits) - 1;
+    state->hold += value << state->bits;
+    state->bits += bits;
+    return Z_OK;
+}
+
+int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
+z_streamp strm;
+int windowBits;
+const char *version;
+int stream_size;
+{
+    struct inflate_state FAR *state;
+
+    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+        stream_size != (int)(sizeof(z_stream)))
+        return Z_VERSION_ERROR;
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+    strm->msg = Z_NULL;                 /* in case we return an error */
+    if (strm->zalloc == (alloc_func)0) {
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+    state = (struct inflate_state FAR *)
+            ZALLOC(strm, 1, sizeof(struct inflate_state));
+    if (state == Z_NULL) return Z_MEM_ERROR;
+    Tracev((stderr, "inflate: allocated\n"));
+    strm->state = (struct internal_state FAR *)state;
+    if (windowBits < 0) {
+        state->wrap = 0;
+        windowBits = -windowBits;
+    }
+    else {
+        state->wrap = (windowBits >> 4) + 1;
+#ifdef GUNZIP
+        if (windowBits < 48) windowBits &= 15;
+#endif
+    }
+    if (windowBits < 8 || windowBits > 15) {
+        ZFREE(strm, state);
+        strm->state = Z_NULL;
+        return Z_STREAM_ERROR;
+    }
+    state->wbits = (unsigned)windowBits;
+    state->window = Z_NULL;
+    return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit_(strm, version, stream_size)
+z_streamp strm;
+const char *version;
+int stream_size;
+{
+    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+/*
+   Return state with length and distance decoding tables and index sizes set to
+   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
+   If BUILDFIXED is defined, then instead this routine builds the tables the
+   first time it's called, and returns those tables the first time and
+   thereafter.  This reduces the size of the code by about 2K bytes, in
+   exchange for a little execution time.  However, BUILDFIXED should not be
+   used for threaded applications, since the rewriting of the tables and virgin
+   may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+    static int virgin = 1;
+    static code *lenfix, *distfix;
+    static code fixed[544];
+
+    /* build fixed huffman tables if first call (may not be thread safe) */
+    if (virgin) {
+        unsigned sym, bits;
+        static code *next;
+
+        /* literal/length table */
+        sym = 0;
+        while (sym < 144) state->lens[sym++] = 8;
+        while (sym < 256) state->lens[sym++] = 9;
+        while (sym < 280) state->lens[sym++] = 7;
+        while (sym < 288) state->lens[sym++] = 8;
+        next = fixed;
+        lenfix = next;
+        bits = 9;
+        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+        /* distance table */
+        sym = 0;
+        while (sym < 32) state->lens[sym++] = 5;
+        distfix = next;
+        bits = 5;
+        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+        /* do this just once */
+        virgin = 0;
+    }
+#else /* !BUILDFIXED */
+#   include "inffixed.h"
+#endif /* BUILDFIXED */
+    state->lencode = lenfix;
+    state->lenbits = 9;
+    state->distcode = distfix;
+    state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
+   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
+   those tables to stdout, which would be piped to inffixed.h.  A small program
+   can simply call makefixed to do this:
+
+    void makefixed(void);
+
+    int main(void)
+    {
+        makefixed();
+        return 0;
+    }
+
+   Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+    a.out > inffixed.h
+ */
+void makefixed()
+{
+    unsigned low, size;
+    struct inflate_state state;
+
+    fixedtables(&state);
+    puts("    /* inffixed.h -- table for decoding fixed codes");
+    puts("     * Generated automatically by makefixed().");
+    puts("     */");
+    puts("");
+    puts("    /* WARNING: this file should *not* be used by applications.");
+    puts("       It is part of the implementation of this library and is");
+    puts("       subject to change. Applications should only use zlib.h.");
+    puts("     */");
+    puts("");
+    size = 1U << 9;
+    printf("    static const code lenfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 7) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
+               state.lencode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+    size = 1U << 5;
+    printf("\n    static const code distfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 6) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+               state.distcode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+}
+#endif /* MAKEFIXED */
+
+/*
+   Update the window with the last wsize (normally 32K) bytes written before
+   returning.  If window does not exist yet, create it.  This is only called
+   when a window is already in use, or when output has been written during this
+   inflate call, but the end of the deflate stream has not been reached yet.
+   It is also called to create a window for dictionary data when a dictionary
+   is loaded.
+
+   Providing output buffers larger than 32K to inflate() should provide a speed
+   advantage, since only the last 32K of output is copied to the sliding window
+   upon return from inflate(), and since all distances after the first 32K of
+   output will fall in the output data, making match copies simpler and faster.
+   The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(strm, out)
+z_streamp strm;
+unsigned out;
+{
+    struct inflate_state FAR *state;
+    unsigned copy, dist;
+
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* if it hasn't been done already, allocate space for the window */
+    if (state->window == Z_NULL) {
+        state->window = (unsigned char FAR *)
+                        ZALLOC(strm, 1U << state->wbits,
+                               sizeof(unsigned char));
+        if (state->window == Z_NULL) return 1;
+    }
+
+    /* if window not in use yet, initialize */
+    if (state->wsize == 0) {
+        state->wsize = 1U << state->wbits;
+        state->write = 0;
+        state->whave = 0;
+    }
+
+    /* copy state->wsize or less output bytes into the circular window */
+    copy = out - strm->avail_out;
+    if (copy >= state->wsize) {
+        zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
+        state->write = 0;
+        state->whave = state->wsize;
+    }
+    else {
+        dist = state->wsize - state->write;
+        if (dist > copy) dist = copy;
+        zmemcpy(state->window + state->write, strm->next_out - copy, dist);
+        copy -= dist;
+        if (copy) {
+            zmemcpy(state->window, strm->next_out - copy, copy);
+            state->write = copy;
+            state->whave = state->wsize;
+        }
+        else {
+            state->write += dist;
+            if (state->write == state->wsize) state->write = 0;
+            if (state->whave < state->wsize) state->whave += dist;
+        }
+    }
+    return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+#  define UPDATE(check, buf, len) \
+    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+#  define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+#  define CRC2(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        check = crc32(check, hbuf, 2); \
+    } while (0)
+
+#  define CRC4(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        hbuf[2] = (unsigned char)((word) >> 16); \
+        hbuf[3] = (unsigned char)((word) >> 24); \
+        check = crc32(check, hbuf, 4); \
+    } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+    do { \
+        put = strm->next_out; \
+        left = strm->avail_out; \
+        next = strm->next_in; \
+        have = strm->avail_in; \
+        hold = state->hold; \
+        bits = state->bits; \
+    } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+    do { \
+        strm->next_out = put; \
+        strm->avail_out = left; \
+        strm->next_in = next; \
+        strm->avail_in = have; \
+        state->hold = hold; \
+        state->bits = bits; \
+    } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+    do { \
+        hold = 0; \
+        bits = 0; \
+    } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+   if there is no input available. */
+#define PULLBYTE() \
+    do { \
+        if (have == 0) goto inf_leave; \
+        have--; \
+        hold += (unsigned long)(*next++) << bits; \
+        bits += 8; \
+    } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator.  If there is
+   not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+    do { \
+        while (bits < (unsigned)(n)) \
+            PULLBYTE(); \
+    } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+    ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+    do { \
+        hold >>= (n); \
+        bits -= (unsigned)(n); \
+    } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+    do { \
+        hold >>= bits & 7; \
+        bits -= bits & 7; \
+    } while (0)
+
+/* Reverse the bytes in a 32-bit value */
+#define REVERSE(q) \
+    ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+     (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+/*
+   inflate() uses a state machine to process as much input data and generate as
+   much output data as possible before returning.  The state machine is
+   structured roughly as follows:
+
+    for (;;) switch (state) {
+    ...
+    case STATEn:
+        if (not enough input data or output space to make progress)
+            return;
+        ... make progress ...
+        state = STATEm;
+        break;
+    ...
+    }
+
+   so when inflate() is called again, the same case is attempted again, and
+   if the appropriate resources are provided, the machine proceeds to the
+   next state.  The NEEDBITS() macro is usually the way the state evaluates
+   whether it can proceed or should return.  NEEDBITS() does the return if
+   the requested bits are not available.  The typical use of the BITS macros
+   is:
+
+        NEEDBITS(n);
+        ... do something with BITS(n) ...
+        DROPBITS(n);
+
+   where NEEDBITS(n) either returns from inflate() if there isn't enough
+   input left to load n bits into the accumulator, or it continues.  BITS(n)
+   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
+   the low n bits off the accumulator.  INITBITS() clears the accumulator
+   and sets the number of available bits to zero.  BYTEBITS() discards just
+   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
+   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+   if there is no input available.  The decoding of variable length codes uses
+   PULLBYTE() directly in order to pull just enough bytes to decode the next
+   code, and no more.
+
+   Some states loop until they get enough input, making sure that enough
+   state information is maintained to continue the loop where it left off
+   if NEEDBITS() returns in the loop.  For example, want, need, and keep
+   would all have to actually be part of the saved state in case NEEDBITS()
+   returns:
+
+    case STATEw:
+        while (want < need) {
+            NEEDBITS(n);
+            keep[want++] = BITS(n);
+            DROPBITS(n);
+        }
+        state = STATEx;
+    case STATEx:
+
+   As shown above, if the next state is also the next case, then the break
+   is omitted.
+
+   A state may also return if there is not enough output space available to
+   complete that state.  Those states are copying stored data, writing a
+   literal byte, and copying a matching string.
+
+   When returning, a "goto inf_leave" is used to update the total counters,
+   update the check value, and determine whether any progress has been made
+   during that inflate() call in order to return the proper return code.
+   Progress is defined as a change in either strm->avail_in or strm->avail_out.
+   When there is a window, goto inf_leave will update the window with the last
+   output written.  If a goto inf_leave occurs in the middle of decompression
+   and there is no window currently, goto inf_leave will create one and copy
+   output to the window for the next call of inflate().
+
+   In this implementation, the flush parameter of inflate() only affects the
+   return code (per zlib.h).  inflate() always writes as much as possible to
+   strm->next_out, given the space available and the provided input--the effect
+   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
+   the allocation of and copying into a sliding window until necessary, which
+   provides the effect documented in zlib.h for Z_FINISH when the entire input
+   stream available.  So the only thing the flush parameter actually does is:
+   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
+   will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(strm, flush)
+z_streamp strm;
+int flush;
+{
+    struct inflate_state FAR *state;
+    unsigned char FAR *next;    /* next input */
+    unsigned char FAR *put;     /* next output */
+    unsigned have, left;        /* available input and output */
+    unsigned long hold;         /* bit buffer */
+    unsigned bits;              /* bits in bit buffer */
+    unsigned in, out;           /* save starting available input and output */
+    unsigned copy;              /* number of stored or match bytes to copy */
+    unsigned char FAR *from;    /* where to copy match bytes from */
+    code this;                  /* current decoding table entry */
+    code last;                  /* parent table entry */
+    unsigned len;               /* length to copy for repeats, bits to drop */
+    int ret;                    /* return code */
+#ifdef GUNZIP
+    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
+#endif
+    static const unsigned short order[19] = /* permutation of code lengths */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+    if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0))
+        return Z_STREAM_ERROR;
+
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
+    LOAD();
+    in = have;
+    out = left;
+    ret = Z_OK;
+    for (;;)
+        switch (state->mode) {
+        case HEAD:
+            if (state->wrap == 0) {
+                state->mode = TYPEDO;
+                break;
+            }
+            NEEDBITS(16);
+#ifdef GUNZIP
+            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
+                state->check = crc32(0L, Z_NULL, 0);
+                CRC2(state->check, hold);
+                INITBITS();
+                state->mode = FLAGS;
+                break;
+            }
+            state->flags = 0;           /* expect zlib header */
+            if (state->head != Z_NULL)
+                state->head->done = -1;
+            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
+#else
+            if (
+#endif
+                ((BITS(8) << 8) + (hold >> 8)) % 31) {
+                strm->msg = (char *)"incorrect header check";
+                state->mode = BAD;
+                break;
+            }
+            if (BITS(4) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            DROPBITS(4);
+            len = BITS(4) + 8;
+            if (len > state->wbits) {
+                strm->msg = (char *)"invalid window size";
+                state->mode = BAD;
+                break;
+            }
+            state->dmax = 1U << len;
+            Tracev((stderr, "inflate:   zlib header ok\n"));
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = hold & 0x200 ? DICTID : TYPE;
+            INITBITS();
+            break;
+#ifdef GUNZIP
+        case FLAGS:
+            NEEDBITS(16);
+            state->flags = (int)(hold);
+            if ((state->flags & 0xff) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            if (state->flags & 0xe000) {
+                strm->msg = (char *)"unknown header flags set";
+                state->mode = BAD;
+                break;
+            }
+            if (state->head != Z_NULL)
+                state->head->text = (int)((hold >> 8) & 1);
+            if (state->flags & 0x0200) CRC2(state->check, hold);
+            INITBITS();
+            state->mode = TIME;
+        case TIME:
+            NEEDBITS(32);
+            if (state->head != Z_NULL)
+                state->head->time = hold;
+            if (state->flags & 0x0200) CRC4(state->check, hold);
+            INITBITS();
+            state->mode = OS;
+        case OS:
+            NEEDBITS(16);
+            if (state->head != Z_NULL) {
+                state->head->xflags = (int)(hold & 0xff);
+                state->head->os = (int)(hold >> 8);
+            }
+            if (state->flags & 0x0200) CRC2(state->check, hold);
+            INITBITS();
+            state->mode = EXLEN;
+        case EXLEN:
+            if (state->flags & 0x0400) {
+                NEEDBITS(16);
+                state->length = (unsigned)(hold);
+                if (state->head != Z_NULL)
+                    state->head->extra_len = (unsigned)hold;
+                if (state->flags & 0x0200) CRC2(state->check, hold);
+                INITBITS();
+            }
+            else if (state->head != Z_NULL)
+                state->head->extra = Z_NULL;
+            state->mode = EXTRA;
+        case EXTRA:
+            if (state->flags & 0x0400) {
+                copy = state->length;
+                if (copy > have) copy = have;
+                if (copy) {
+                    if (state->head != Z_NULL &&
+                        state->head->extra != Z_NULL) {
+                        len = state->head->extra_len - state->length;
+                        zmemcpy(state->head->extra + len, next,
+                                len + copy > state->head->extra_max ?
+                                state->head->extra_max - len : copy);
+                    }
+                    if (state->flags & 0x0200)
+                        state->check = crc32(state->check, next, copy);
+                    have -= copy;
+                    next += copy;
+                    state->length -= copy;
+                }
+                if (state->length) goto inf_leave;
+            }
+            state->length = 0;
+            state->mode = NAME;
+        case NAME:
+            if (state->flags & 0x0800) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->name != Z_NULL &&
+                            state->length < state->head->name_max)
+                        state->head->name[state->length++] = len;
+                } while (len && copy < have);
+                if (state->flags & 0x0200)
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->name = Z_NULL;
+            state->length = 0;
+            state->mode = COMMENT;
+        case COMMENT:
+            if (state->flags & 0x1000) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->comment != Z_NULL &&
+                            state->length < state->head->comm_max)
+                        state->head->comment[state->length++] = len;
+                } while (len && copy < have);
+                if (state->flags & 0x0200)
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->comment = Z_NULL;
+            state->mode = HCRC;
+        case HCRC:
+            if (state->flags & 0x0200) {
+                NEEDBITS(16);
+                if (hold != (state->check & 0xffff)) {
+                    strm->msg = (char *)"header crc mismatch";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+            }
+            if (state->head != Z_NULL) {
+                state->head->hcrc = (int)((state->flags >> 9) & 1);
+                state->head->done = 1;
+            }
+            strm->adler = state->check = crc32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+            break;
+#endif
+        case DICTID:
+            NEEDBITS(32);
+            strm->adler = state->check = REVERSE(hold);
+            INITBITS();
+            state->mode = DICT;
+        case DICT:
+            if (state->havedict == 0) {
+                RESTORE();
+                return Z_NEED_DICT;
+            }
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+        case TYPE:
+            if (flush == Z_BLOCK) goto inf_leave;
+        case TYPEDO:
+            if (state->last) {
+                BYTEBITS();
+                state->mode = CHECK;
+                break;
+            }
+            NEEDBITS(3);
+            state->last = BITS(1);
+            DROPBITS(1);
+            switch (BITS(2)) {
+            case 0:                             /* stored block */
+                Tracev((stderr, "inflate:     stored block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = STORED;
+                break;
+            case 1:                             /* fixed block */
+                fixedtables(state);
+                Tracev((stderr, "inflate:     fixed codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = LEN;              /* decode codes */
+                break;
+            case 2:                             /* dynamic block */
+                Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = TABLE;
+                break;
+            case 3:
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
+            }
+            DROPBITS(2);
+            break;
+        case STORED:
+            BYTEBITS();                         /* go to byte boundary */
+            NEEDBITS(32);
+            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
+                break;
+            }
+            state->length = (unsigned)hold & 0xffff;
+            Tracev((stderr, "inflate:       stored length %u\n",
+                    state->length));
+            INITBITS();
+            state->mode = COPY;
+        case COPY:
+            copy = state->length;
+            if (copy) {
+                if (copy > have) copy = have;
+                if (copy > left) copy = left;
+                if (copy == 0) goto inf_leave;
+                zmemcpy(put, next, copy);
+                have -= copy;
+                next += copy;
+                left -= copy;
+                put += copy;
+                state->length -= copy;
+                break;
+            }
+            Tracev((stderr, "inflate:       stored end\n"));
+            state->mode = TYPE;
+            break;
+        case TABLE:
+            NEEDBITS(14);
+            state->nlen = BITS(5) + 257;
+            DROPBITS(5);
+            state->ndist = BITS(5) + 1;
+            DROPBITS(5);
+            state->ncode = BITS(4) + 4;
+            DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+            if (state->nlen > 286 || state->ndist > 30) {
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracev((stderr, "inflate:       table sizes ok\n"));
+            state->have = 0;
+            state->mode = LENLENS;
+        case LENLENS:
+            while (state->have < state->ncode) {
+                NEEDBITS(3);
+                state->lens[order[state->have++]] = (unsigned short)BITS(3);
+                DROPBITS(3);
+            }
+            while (state->have < 19)
+                state->lens[order[state->have++]] = 0;
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 7;
+            ret = inflate_table(CODES, state->lens, 19, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       code lengths ok\n"));
+            state->have = 0;
+            state->mode = CODELENS;
+        case CODELENS:
+            while (state->have < state->nlen + state->ndist) {
+                for (;;) {
+                    this = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                if (this.val < 16) {
+                    NEEDBITS(this.bits);
+                    DROPBITS(this.bits);
+                    state->lens[state->have++] = this.val;
+                }
+                else {
+                    if (this.val == 16) {
+                        NEEDBITS(this.bits + 2);
+                        DROPBITS(this.bits);
+                        if (state->have == 0) {
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
+                            break;
+                        }
+                        len = state->lens[state->have - 1];
+                        copy = 3 + BITS(2);
+                        DROPBITS(2);
+                    }
+                    else if (this.val == 17) {
+                        NEEDBITS(this.bits + 3);
+                        DROPBITS(this.bits);
+                        len = 0;
+                        copy = 3 + BITS(3);
+                        DROPBITS(3);
+                    }
+                    else {
+                        NEEDBITS(this.bits + 7);
+                        DROPBITS(this.bits);
+                        len = 0;
+                        copy = 11 + BITS(7);
+                        DROPBITS(7);
+                    }
+                    if (state->have + copy > state->nlen + state->ndist) {
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
+                        break;
+                    }
+                    while (copy--)
+                        state->lens[state->have++] = (unsigned short)len;
+                }
+            }
+
+            /* handle error breaks in while */
+            if (state->mode == BAD) break;
+
+            /* build code tables */
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 9;
+            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
+                break;
+            }
+            state->distcode = (code const FAR *)(state->next);
+            state->distbits = 6;
+            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+                            &(state->next), &(state->distbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       codes ok\n"));
+            state->mode = LEN;
+        case LEN:
+            if (have >= 6 && left >= 258) {
+                RESTORE();
+                inflate_fast(strm, out);
+                LOAD();
+                break;
+            }
+            for (;;) {
+                this = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(this.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if (this.op && (this.op & 0xf0) == 0) {
+                last = this;
+                for (;;) {
+                    this = state->lencode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(this.bits);
+            state->length = (unsigned)this.val;
+            if ((int)(this.op) == 0) {
+                Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+                        "inflate:         literal '%c'\n" :
+                        "inflate:         literal 0x%02x\n", this.val));
+                state->mode = LIT;
+                break;
+            }
+            if (this.op & 32) {
+                Tracevv((stderr, "inflate:         end of block\n"));
+                state->mode = TYPE;
+                break;
+            }
+            if (this.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
+                break;
+            }
+            state->extra = (unsigned)(this.op) & 15;
+            state->mode = LENEXT;
+        case LENEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->length += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+            Tracevv((stderr, "inflate:         length %u\n", state->length));
+            state->mode = DIST;
+        case DIST:
+            for (;;) {
+                this = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(this.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if ((this.op & 0xf0) == 0) {
+                last = this;
+                for (;;) {
+                    this = state->distcode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(this.bits);
+            if (this.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+            state->offset = (unsigned)this.val;
+            state->extra = (unsigned)(this.op) & 15;
+            state->mode = DISTEXT;
+        case DISTEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->offset += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+#ifdef INFLATE_STRICT
+            if (state->offset > state->dmax) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            if (state->offset > state->whave + out - left) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
+            state->mode = MATCH;
+        case MATCH:
+            if (left == 0) goto inf_leave;
+            copy = out - left;
+            if (state->offset > copy) {         /* copy from window */
+                copy = state->offset - copy;
+                if (copy > state->write) {
+                    copy -= state->write;
+                    from = state->window + (state->wsize - copy);
+                }
+                else
+                    from = state->window + (state->write - copy);
+                if (copy > state->length) copy = state->length;
+            }
+            else {                              /* copy from output */
+                from = put - state->offset;
+                copy = state->length;
+            }
+            if (copy > left) copy = left;
+            left -= copy;
+            state->length -= copy;
+            do {
+                *put++ = *from++;
+            } while (--copy);
+            if (state->length == 0) state->mode = LEN;
+            break;
+        case LIT:
+            if (left == 0) goto inf_leave;
+            *put++ = (unsigned char)(state->length);
+            left--;
+            state->mode = LEN;
+            break;
+        case CHECK:
+            if (state->wrap) {
+                NEEDBITS(32);
+                out -= left;
+                strm->total_out += out;
+                state->total += out;
+                if (out)
+                    strm->adler = state->check =
+                        UPDATE(state->check, put - out, out);
+                out = left;
+                if ((
+#ifdef GUNZIP
+                     state->flags ? hold :
+#endif
+                     REVERSE(hold)) != state->check) {
+                    strm->msg = (char *)"incorrect data check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   check matches trailer\n"));
+            }
+#ifdef GUNZIP
+            state->mode = LENGTH;
+        case LENGTH:
+            if (state->wrap && state->flags) {
+                NEEDBITS(32);
+                if (hold != (state->total & 0xffffffffUL)) {
+                    strm->msg = (char *)"incorrect length check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   length matches trailer\n"));
+            }
+#endif
+            state->mode = DONE;
+        case DONE:
+            ret = Z_STREAM_END;
+            goto inf_leave;
+        case BAD:
+            ret = Z_DATA_ERROR;
+            goto inf_leave;
+        case MEM:
+            return Z_MEM_ERROR;
+        case SYNC:
+        default:
+            return Z_STREAM_ERROR;
+        }
+
+    /*
+       Return from inflate(), updating the total counts and the check value.
+       If there was no progress during the inflate() call, return a buffer
+       error.  Call updatewindow() to create and/or update the window state.
+       Note: a memory error from inflate() is non-recoverable.
+     */
+  inf_leave:
+    RESTORE();
+    if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
+        if (updatewindow(strm, out)) {
+            state->mode = MEM;
+            return Z_MEM_ERROR;
+        }
+    in -= strm->avail_in;
+    out -= strm->avail_out;
+    strm->total_in += in;
+    strm->total_out += out;
+    state->total += out;
+    if (state->wrap && out)
+        strm->adler = state->check =
+            UPDATE(state->check, strm->next_out - out, out);
+    strm->data_type = state->bits + (state->last ? 64 : 0) +
+                      (state->mode == TYPE ? 128 : 0);
+    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+        ret = Z_BUF_ERROR;
+    return ret;
+}
+
+int ZEXPORT inflateEnd(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->window != Z_NULL) ZFREE(strm, state->window);
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+    Tracev((stderr, "inflate: end\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+const Bytef *dictionary;
+uInt dictLength;
+{
+    struct inflate_state FAR *state;
+    unsigned long id;
+
+    /* check state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->wrap != 0 && state->mode != DICT)
+        return Z_STREAM_ERROR;
+
+    /* check for correct dictionary id */
+    if (state->mode == DICT) {
+        id = adler32(0L, Z_NULL, 0);
+        id = adler32(id, dictionary, dictLength);
+        if (id != state->check)
+            return Z_DATA_ERROR;
+    }
+
+    /* copy dictionary to window */
+    if (updatewindow(strm, strm->avail_out)) {
+        state->mode = MEM;
+        return Z_MEM_ERROR;
+    }
+    if (dictLength > state->wsize) {
+        zmemcpy(state->window, dictionary + dictLength - state->wsize,
+                state->wsize);
+        state->whave = state->wsize;
+    }
+    else {
+        zmemcpy(state->window + state->wsize - dictLength, dictionary,
+                dictLength);
+        state->whave = dictLength;
+    }
+    state->havedict = 1;
+    Tracev((stderr, "inflate:   dictionary set\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(strm, head)
+z_streamp strm;
+gz_headerp head;
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+    /* save header structure */
+    state->head = head;
+    head->done = 0;
+    return Z_OK;
+}
+
+/*
+   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
+   or when out of input.  When called, *have is the number of pattern bytes
+   found in order so far, in 0..3.  On return *have is updated to the new
+   state.  If on return *have equals four, then the pattern was found and the
+   return value is how many bytes were read including the last byte of the
+   pattern.  If *have is less than four, then the pattern has not been found
+   yet and the return value is len.  In the latter case, syncsearch() can be
+   called again with more data and the *have state.  *have is initialized to
+   zero for the first call.
+ */
+local unsigned syncsearch(have, buf, len)
+unsigned FAR *have;
+unsigned char FAR *buf;
+unsigned len;
+{
+    unsigned got;
+    unsigned next;
+
+    got = *have;
+    next = 0;
+    while (next < len && got < 4) {
+        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+            got++;
+        else if (buf[next])
+            got = 0;
+        else
+            got = 4 - got;
+        next++;
+    }
+    *have = got;
+    return next;
+}
+
+int ZEXPORT inflateSync(strm)
+z_streamp strm;
+{
+    unsigned len;               /* number of bytes to look at or looked at */
+    unsigned long in, out;      /* temporary to save total_in and total_out */
+    unsigned char buf[4];       /* to restore bit buffer to byte string */
+    struct inflate_state FAR *state;
+
+    /* check parameters */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+    /* if first time, start search in bit buffer */
+    if (state->mode != SYNC) {
+        state->mode = SYNC;
+        state->hold <<= state->bits & 7;
+        state->bits -= state->bits & 7;
+        len = 0;
+        while (state->bits >= 8) {
+            buf[len++] = (unsigned char)(state->hold);
+            state->hold >>= 8;
+            state->bits -= 8;
+        }
+        state->have = 0;
+        syncsearch(&(state->have), buf, len);
+    }
+
+    /* search available input */
+    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+    strm->avail_in -= len;
+    strm->next_in += len;
+    strm->total_in += len;
+
+    /* return no joy or set up to restart inflate() on a new block */
+    if (state->have != 4) return Z_DATA_ERROR;
+    in = strm->total_in;  out = strm->total_out;
+    inflateReset(strm);
+    strm->total_in = in;  strm->total_out = out;
+    state->mode = TYPE;
+    return Z_OK;
+}
+
+/*
+   Returns true if inflate is currently at the end of a block generated by
+   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+   implementation to provide an additional safety check. PPP uses
+   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+   block. When decompressing, PPP checks that at the end of input packet,
+   inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(dest, source)
+z_streamp dest;
+z_streamp source;
+{
+    struct inflate_state FAR *state;
+    struct inflate_state FAR *copy;
+    unsigned char FAR *window;
+    unsigned wsize;
+
+    /* check input */
+    if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
+        source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)source->state;
+
+    /* allocate space */
+    copy = (struct inflate_state FAR *)
+           ZALLOC(source, 1, sizeof(struct inflate_state));
+    if (copy == Z_NULL) return Z_MEM_ERROR;
+    window = Z_NULL;
+    if (state->window != Z_NULL) {
+        window = (unsigned char FAR *)
+                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+        if (window == Z_NULL) {
+            ZFREE(source, copy);
+            return Z_MEM_ERROR;
+        }
+    }
+
+    /* copy state */
+    zmemcpy(dest, source, sizeof(z_stream));
+    zmemcpy(copy, state, sizeof(struct inflate_state));
+    if (state->lencode >= state->codes &&
+        state->lencode <= state->codes + ENOUGH - 1) {
+        copy->lencode = copy->codes + (state->lencode - state->codes);
+        copy->distcode = copy->codes + (state->distcode - state->codes);
+    }
+    copy->next = copy->codes + (state->next - state->codes);
+    if (window != Z_NULL) {
+        wsize = 1U << state->wbits;
+        zmemcpy(window, state->window, wsize);
+    }
+    copy->window = window;
+    dest->state = (struct internal_state FAR *)copy;
+    return Z_OK;
+}
Index: /trunk/minix/lib/zlib-1.2.3/inflate.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/inflate.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/inflate.h	(revision 9)
@@ -0,0 +1,115 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+   trailer decoding by inflate().  NO_GZIP would be used to avoid linking in
+   the crc code when it is not needed.  For shared libraries, gzip decoding
+   should be left enabled. */
+#ifndef NO_GZIP
+#  define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+    HEAD,       /* i: waiting for magic header */
+    FLAGS,      /* i: waiting for method and flags (gzip) */
+    TIME,       /* i: waiting for modification time (gzip) */
+    OS,         /* i: waiting for extra flags and operating system (gzip) */
+    EXLEN,      /* i: waiting for extra length (gzip) */
+    EXTRA,      /* i: waiting for extra bytes (gzip) */
+    NAME,       /* i: waiting for end of file name (gzip) */
+    COMMENT,    /* i: waiting for end of comment (gzip) */
+    HCRC,       /* i: waiting for header crc (gzip) */
+    DICTID,     /* i: waiting for dictionary check value */
+    DICT,       /* waiting for inflateSetDictionary() call */
+        TYPE,       /* i: waiting for type bits, including last-flag bit */
+        TYPEDO,     /* i: same, but skip check to exit inflate on new block */
+        STORED,     /* i: waiting for stored size (length and complement) */
+        COPY,       /* i/o: waiting for input or output to copy stored block */
+        TABLE,      /* i: waiting for dynamic block table lengths */
+        LENLENS,    /* i: waiting for code length code lengths */
+        CODELENS,   /* i: waiting for length/lit and distance code lengths */
+            LEN,        /* i: waiting for length/lit code */
+            LENEXT,     /* i: waiting for length extra bits */
+            DIST,       /* i: waiting for distance code */
+            DISTEXT,    /* i: waiting for distance extra bits */
+            MATCH,      /* o: waiting for output space to copy string */
+            LIT,        /* o: waiting for output space to write literal */
+    CHECK,      /* i: waiting for 32-bit check value */
+    LENGTH,     /* i: waiting for 32-bit length (gzip) */
+    DONE,       /* finished check, done -- remain here until reset */
+    BAD,        /* got a data error -- remain here until reset */
+    MEM,        /* got an inflate() memory error -- remain here until reset */
+    SYNC        /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+    State transitions between above modes -
+
+    (most modes can go to the BAD or MEM mode -- not shown for clarity)
+
+    Process header:
+        HEAD -> (gzip) or (zlib)
+        (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
+        NAME -> COMMENT -> HCRC -> TYPE
+        (zlib) -> DICTID or TYPE
+        DICTID -> DICT -> TYPE
+    Read deflate blocks:
+            TYPE -> STORED or TABLE or LEN or CHECK
+            STORED -> COPY -> TYPE
+            TABLE -> LENLENS -> CODELENS -> LEN
+    Read deflate codes:
+                LEN -> LENEXT or LIT or TYPE
+                LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+                LIT -> LEN
+    Process trailer:
+        CHECK -> LENGTH -> DONE
+ */
+
+/* state maintained between inflate() calls.  Approximately 7K bytes. */
+struct inflate_state {
+    inflate_mode mode;          /* current inflate mode */
+    int last;                   /* true if processing last block */
+    int wrap;                   /* bit 0 true for zlib, bit 1 true for gzip */
+    int havedict;               /* true if dictionary provided */
+    int flags;                  /* gzip header method and flags (0 if zlib) */
+    unsigned dmax;              /* zlib header max distance (INFLATE_STRICT) */
+    unsigned long check;        /* protected copy of check value */
+    unsigned long total;        /* protected copy of output count */
+    gz_headerp head;            /* where to save gzip header information */
+        /* sliding window */
+    unsigned wbits;             /* log base 2 of requested window size */
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned write;             /* window write index */
+    unsigned char FAR *window;  /* allocated sliding window, if needed */
+        /* bit accumulator */
+    unsigned long hold;         /* input bit accumulator */
+    unsigned bits;              /* number of bits in "in" */
+        /* for string and stored block copying */
+    unsigned length;            /* literal or length of data to copy */
+    unsigned offset;            /* distance back to copy string from */
+        /* for table and code decoding */
+    unsigned extra;             /* extra bits needed */
+        /* fixed and dynamic code tables */
+    code const FAR *lencode;    /* starting table for length/literal codes */
+    code const FAR *distcode;   /* starting table for distance codes */
+    unsigned lenbits;           /* index bits for lencode */
+    unsigned distbits;          /* index bits for distcode */
+        /* dynamic table building */
+    unsigned ncode;             /* number of code length code lengths */
+    unsigned nlen;              /* number of length code lengths */
+    unsigned ndist;             /* number of distance code lengths */
+    unsigned have;              /* number of code lengths in lens[] */
+    code FAR *next;             /* next available space in codes[] */
+    unsigned short lens[320];   /* temporary storage for code lengths */
+    unsigned short work[288];   /* work area for code table building */
+    code codes[ENOUGH];         /* space for code tables */
+};
Index: /trunk/minix/lib/zlib-1.2.3/inftrees.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/inftrees.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/inftrees.c	(revision 9)
@@ -0,0 +1,329 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+   " inflate 1.2.3 Copyright 1995-2005 Mark Adler ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/*
+   Build a set of tables to decode the provided canonical Huffman code.
+   The code lengths are lens[0..codes-1].  The result starts at *table,
+   whose indices are 0..2^bits-1.  work is a writable array of at least
+   lens shorts, which is used as a work area.  type is the type of code
+   to be generated, CODES, LENS, or DISTS.  On return, zero is success,
+   -1 is an invalid code, and +1 means that ENOUGH isn't enough.  table
+   on return points to the next available entry's address.  bits is the
+   requested root table index bits, and on return it is the actual root
+   table index bits.  It will differ if the request is greater than the
+   longest code or if it is less than the shortest code.
+ */
+int inflate_table(type, lens, codes, table, bits, work)
+codetype type;
+unsigned short FAR *lens;
+unsigned codes;
+code FAR * FAR *table;
+unsigned FAR *bits;
+unsigned short FAR *work;
+{
+    unsigned len;               /* a code's length in bits */
+    unsigned sym;               /* index of code symbols */
+    unsigned min, max;          /* minimum and maximum code lengths */
+    unsigned root;              /* number of index bits for root table */
+    unsigned curr;              /* number of index bits for current table */
+    unsigned drop;              /* code bits to drop for sub-table */
+    int left;                   /* number of prefix codes available */
+    unsigned used;              /* code entries in table used */
+    unsigned huff;              /* Huffman code */
+    unsigned incr;              /* for incrementing code, index */
+    unsigned fill;              /* index for replicating entries */
+    unsigned low;               /* low bits for current root entry */
+    unsigned mask;              /* mask for low root bits */
+    code this;                  /* table entry for duplication */
+    code FAR *next;             /* next available space in table */
+    const unsigned short FAR *base;     /* base value table to use */
+    const unsigned short FAR *extra;    /* extra bits table to use */
+    int end;                    /* use base and extra for symbol > end */
+    unsigned short count[MAXBITS+1];    /* number of codes of each length */
+    unsigned short offs[MAXBITS+1];     /* offsets in table for each length */
+    static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+    static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+        16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
+    static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577, 0, 0};
+    static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+        16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+        23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+        28, 28, 29, 29, 64, 64};
+
+    /*
+       Process a set of code lengths to create a canonical Huffman code.  The
+       code lengths are lens[0..codes-1].  Each length corresponds to the
+       symbols 0..codes-1.  The Huffman code is generated by first sorting the
+       symbols by length from short to long, and retaining the symbol order
+       for codes with equal lengths.  Then the code starts with all zero bits
+       for the first code of the shortest length, and the codes are integer
+       increments for the same length, and zeros are appended as the length
+       increases.  For the deflate format, these bits are stored backwards
+       from their more natural integer increment ordering, and so when the
+       decoding tables are built in the large loop below, the integer codes
+       are incremented backwards.
+
+       This routine assumes, but does not check, that all of the entries in
+       lens[] are in the range 0..MAXBITS.  The caller must assure this.
+       1..MAXBITS is interpreted as that code length.  zero means that that
+       symbol does not occur in this code.
+
+       The codes are sorted by computing a count of codes for each length,
+       creating from that a table of starting indices for each length in the
+       sorted table, and then entering the symbols in order in the sorted
+       table.  The sorted table is work[], with that space being provided by
+       the caller.
+
+       The length counts are used for other purposes as well, i.e. finding
+       the minimum and maximum length codes, determining if there are any
+       codes at all, checking for a valid set of lengths, and looking ahead
+       at length counts to determine sub-table sizes when building the
+       decoding tables.
+     */
+
+    /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+    for (len = 0; len <= MAXBITS; len++)
+        count[len] = 0;
+    for (sym = 0; sym < codes; sym++)
+        count[lens[sym]]++;
+
+    /* bound code lengths, force root to be within code lengths */
+    root = *bits;
+    for (max = MAXBITS; max >= 1; max--)
+        if (count[max] != 0) break;
+    if (root > max) root = max;
+    if (max == 0) {                     /* no symbols to code at all */
+        this.op = (unsigned char)64;    /* invalid code marker */
+        this.bits = (unsigned char)1;
+        this.val = (unsigned short)0;
+        *(*table)++ = this;             /* make a table to force an error */
+        *(*table)++ = this;
+        *bits = 1;
+        return 0;     /* no symbols, but wait for decoding to report error */
+    }
+    for (min = 1; min <= MAXBITS; min++)
+        if (count[min] != 0) break;
+    if (root < min) root = min;
+
+    /* check for an over-subscribed or incomplete set of lengths */
+    left = 1;
+    for (len = 1; len <= MAXBITS; len++) {
+        left <<= 1;
+        left -= count[len];
+        if (left < 0) return -1;        /* over-subscribed */
+    }
+    if (left > 0 && (type == CODES || max != 1))
+        return -1;                      /* incomplete set */
+
+    /* generate offsets into symbol table for each length for sorting */
+    offs[1] = 0;
+    for (len = 1; len < MAXBITS; len++)
+        offs[len + 1] = offs[len] + count[len];
+
+    /* sort symbols by length, by symbol order within each length */
+    for (sym = 0; sym < codes; sym++)
+        if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+    /*
+       Create and fill in decoding tables.  In this loop, the table being
+       filled is at next and has curr index bits.  The code being used is huff
+       with length len.  That code is converted to an index by dropping drop
+       bits off of the bottom.  For codes where len is less than drop + curr,
+       those top drop + curr - len bits are incremented through all values to
+       fill the table with replicated entries.
+
+       root is the number of index bits for the root table.  When len exceeds
+       root, sub-tables are created pointed to by the root entry with an index
+       of the low root bits of huff.  This is saved in low to check for when a
+       new sub-table should be started.  drop is zero when the root table is
+       being filled, and drop is root when sub-tables are being filled.
+
+       When a new sub-table is needed, it is necessary to look ahead in the
+       code lengths to determine what size sub-table is needed.  The length
+       counts are used for this, and so count[] is decremented as codes are
+       entered in the tables.
+
+       used keeps track of how many table entries have been allocated from the
+       provided *table space.  It is checked when a LENS table is being made
+       against the space in *table, ENOUGH, minus the maximum space needed by
+       the worst case distance code, MAXD.  This should never happen, but the
+       sufficiency of ENOUGH has not been proven exhaustively, hence the check.
+       This assumes that when type == LENS, bits == 9.
+
+       sym increments through all symbols, and the loop terminates when
+       all codes of length max, i.e. all codes, have been processed.  This
+       routine permits incomplete codes, so another loop after this one fills
+       in the rest of the decoding tables with invalid code markers.
+     */
+
+    /* set up for code type */
+    switch (type) {
+    case CODES:
+        base = extra = work;    /* dummy value--not used */
+        end = 19;
+        break;
+    case LENS:
+        base = lbase;
+        base -= 257;
+        extra = lext;
+        extra -= 257;
+        end = 256;
+        break;
+    default:            /* DISTS */
+        base = dbase;
+        extra = dext;
+        end = -1;
+    }
+
+    /* initialize state for loop */
+    huff = 0;                   /* starting code */
+    sym = 0;                    /* starting code symbol */
+    len = min;                  /* starting code length */
+    next = *table;              /* current table to fill in */
+    curr = root;                /* current table index bits */
+    drop = 0;                   /* current bits to drop from code for index */
+    low = (unsigned)(-1);       /* trigger new sub-table when len > root */
+    used = 1U << root;          /* use root table entries */
+    mask = used - 1;            /* mask for comparing low */
+
+    /* check available table space */
+    if (type == LENS && used >= ENOUGH - MAXD)
+        return 1;
+
+    /* process all codes and make table entries */
+    for (;;) {
+        /* create table entry */
+        this.bits = (unsigned char)(len - drop);
+        if ((int)(work[sym]) < end) {
+            this.op = (unsigned char)0;
+            this.val = work[sym];
+        }
+        else if ((int)(work[sym]) > end) {
+            this.op = (unsigned char)(extra[work[sym]]);
+            this.val = base[work[sym]];
+        }
+        else {
+            this.op = (unsigned char)(32 + 64);         /* end of block */
+            this.val = 0;
+        }
+
+        /* replicate for those indices with low len bits equal to huff */
+        incr = 1U << (len - drop);
+        fill = 1U << curr;
+        min = fill;                 /* save offset to next table */
+        do {
+            fill -= incr;
+            next[(huff >> drop) + fill] = this;
+        } while (fill != 0);
+
+        /* backwards increment the len-bit code huff */
+        incr = 1U << (len - 1);
+        while (huff & incr)
+            incr >>= 1;
+        if (incr != 0) {
+            huff &= incr - 1;
+            huff += incr;
+        }
+        else
+            huff = 0;
+
+        /* go to next symbol, update count, len */
+        sym++;
+        if (--(count[len]) == 0) {
+            if (len == max) break;
+            len = lens[work[sym]];
+        }
+
+        /* create new sub-table if needed */
+        if (len > root && (huff & mask) != low) {
+            /* if first time, transition to sub-tables */
+            if (drop == 0)
+                drop = root;
+
+            /* increment past last table */
+            next += min;            /* here min is 1 << curr */
+
+            /* determine length of next table */
+            curr = len - drop;
+            left = (int)(1 << curr);
+            while (curr + drop < max) {
+                left -= count[curr + drop];
+                if (left <= 0) break;
+                curr++;
+                left <<= 1;
+            }
+
+            /* check for enough space */
+            used += 1U << curr;
+            if (type == LENS && used >= ENOUGH - MAXD)
+                return 1;
+
+            /* point entry in root table to sub-table */
+            low = huff & mask;
+            (*table)[low].op = (unsigned char)curr;
+            (*table)[low].bits = (unsigned char)root;
+            (*table)[low].val = (unsigned short)(next - *table);
+        }
+    }
+
+    /*
+       Fill in rest of table for incomplete codes.  This loop is similar to the
+       loop above in incrementing huff for table indices.  It is assumed that
+       len is equal to curr + drop, so there is no loop needed to increment
+       through high index bits.  When the current sub-table is filled, the loop
+       drops back to the root table to fill in any remaining entries there.
+     */
+    this.op = (unsigned char)64;                /* invalid code marker */
+    this.bits = (unsigned char)(len - drop);
+    this.val = (unsigned short)0;
+    while (huff != 0) {
+        /* when done with sub-table, drop back to root table */
+        if (drop != 0 && (huff & mask) != low) {
+            drop = 0;
+            len = root;
+            next = *table;
+            this.bits = (unsigned char)len;
+        }
+
+        /* put invalid code marker in table */
+        next[huff >> drop] = this;
+
+        /* backwards increment the len-bit code huff */
+        incr = 1U << (len - 1);
+        while (huff & incr)
+            incr >>= 1;
+        if (incr != 0) {
+            huff &= incr - 1;
+            huff += incr;
+        }
+        else
+            huff = 0;
+    }
+
+    /* set return parameters */
+    *table += used;
+    *bits = root;
+    return 0;
+}
Index: /trunk/minix/lib/zlib-1.2.3/inftrees.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/inftrees.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/inftrees.h	(revision 9)
@@ -0,0 +1,55 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Structure for decoding tables.  Each entry provides either the
+   information needed to do the operation requested by the code that
+   indexed that table entry, or it provides a pointer to another
+   table that indexes more bits of the code.  op indicates whether
+   the entry is a pointer to another table, a literal, a length or
+   distance, an end-of-block, or an invalid code.  For a table
+   pointer, the low four bits of op is the number of index bits of
+   that table.  For a length or distance, the low four bits of op
+   is the number of extra bits to get after the code.  bits is
+   the number of bits in this code or part of the code to drop off
+   of the bit buffer.  val is the actual byte to output in the case
+   of a literal, the base length or distance, or the offset from
+   the current table to the next table.  Each entry is four bytes. */
+typedef struct {
+    unsigned char op;           /* operation, extra bits, table bits */
+    unsigned char bits;         /* bits in this part of the code */
+    unsigned short val;         /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+    00000000 - literal
+    0000tttt - table link, tttt != 0 is the number of table index bits
+    0001eeee - length or distance, eeee is the number of extra bits
+    01100000 - end of block
+    01000000 - invalid code
+ */
+
+/* Maximum size of dynamic tree.  The maximum found in a long but non-
+   exhaustive search was 1444 code structures (852 for length/literals
+   and 592 for distances, the latter actually the result of an
+   exhaustive search).  The true maximum is not known, but the value
+   below is more than safe. */
+#define ENOUGH 2048
+#define MAXD 592
+
+/* Type of code to build for inftable() */
+typedef enum {
+    CODES,
+    LENS,
+    DISTS
+} codetype;
+
+extern int inflate_table OF((codetype type, unsigned short FAR *lens,
+                             unsigned codes, code FAR * FAR *table,
+                             unsigned FAR *bits, unsigned short FAR *work));
Index: /trunk/minix/lib/zlib-1.2.3/make_vms.com
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/make_vms.com	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/make_vms.com	(revision 9)
@@ -0,0 +1,461 @@
+$! make libz under VMS written by
+$! Martin P.J. Zinser
+$! <zinser@zinser.no-ip.info or zinser@sysdev.deutsche-boerse.com>
+$!
+$ on error then goto err_exit
+$!
+$!
+$! Just some general constants...
+$!
+$ true  = 1
+$ false = 0
+$ tmpnam = "temp_" + f$getjpi("","pid")
+$ SAY = "WRITE SYS$OUTPUT"
+$!
+$! Setup variables holding "config" information
+$!
+$ Make     = ""
+$ name     = "Zlib"
+$ version  = "?.?.?"
+$ v_string = "ZLIB_VERSION"
+$ v_file   = "zlib.h"
+$ ccopt    = ""
+$ lopts    = ""
+$ linkonly = false
+$ optfile  = name + ".opt"
+$ its_decc = false
+$ its_vaxc = false
+$ its_gnuc = false
+$ axp      = f$getsyi("HW_MODEL").ge.1024
+$ s_case   = false
+$! Check for MMK/MMS
+$!
+$ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS"
+$ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK"
+$!
+$!
+$ gosub find_version
+$!
+$ gosub check_opts
+$!
+$! Look for the compiler used
+$!
+$ gosub check_compiler
+$ if its_decc
+$ then
+$   ccopt = "/prefix=all" + ccopt
+$   if f$trnlnm("SYS") .eqs. ""
+$   then
+$     if axp
+$     then
+$       define sys sys$library:
+$     else
+$       ccopt = "/decc" + ccopt
+$       define sys decc$library_include:
+$     endif
+$   endif
+$ endif
+$ if its_vaxc .or. its_gnuc
+$ then
+$    if f$trnlnm("SYS").eqs."" then define sys sys$library:
+$ endif
+$!
+$! Build the thing plain or with mms
+$!
+$ write sys$output "Compiling Zlib sources ..."
+$ if make.eqs.""
+$  then
+$   dele example.obj;*,minigzip.obj;*
+$   CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" -
+                adler32.c zlib.h zconf.h
+$   CALL MAKE compress.OBJ "CC ''CCOPT' compress" -
+                compress.c zlib.h zconf.h
+$   CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" -
+                crc32.c zlib.h zconf.h
+$   CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" -
+                deflate.c deflate.h zutil.h zlib.h zconf.h
+$   CALL MAKE gzio.OBJ "CC ''CCOPT' gzio" -
+                gzio.c zutil.h zlib.h zconf.h
+$   CALL MAKE infback.OBJ "CC ''CCOPT' infback" -
+                infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h
+$   CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" -
+                inffast.c zutil.h zlib.h zconf.h inffast.h
+$   CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" -
+                inflate.c zutil.h zlib.h zconf.h infblock.h
+$   CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" -
+                inftrees.c zutil.h zlib.h zconf.h inftrees.h
+$   CALL MAKE trees.OBJ "CC ''CCOPT' trees" -
+                trees.c deflate.h zutil.h zlib.h zconf.h
+$   CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" -
+                uncompr.c zlib.h zconf.h
+$   CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" -
+                zutil.c zutil.h zlib.h zconf.h
+$   write sys$output "Building Zlib ..."
+$   CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ
+$   write sys$output "Building example..."
+$   CALL MAKE example.OBJ "CC ''CCOPT' example" -
+                example.c zlib.h zconf.h
+$   call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb
+$   if f$search("x11vms:xvmsutils.olb") .nes. ""
+$   then
+$     write sys$output "Building minigzip..."
+$     CALL MAKE minigzip.OBJ "CC ''CCOPT' minigzip" -
+                minigzip.c zlib.h zconf.h
+$     call make minigzip.exe -
+                "LINK minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib" -
+                minigzip.obj libz.olb
+$   endif
+$  else
+$   gosub crea_mms
+$   SAY "Make ''name' ''version' with ''Make' "
+$   'make'
+$  endif
+$!
+$! Alpha gets a shareable image
+$!
+$ If axp
+$ Then
+$   gosub crea_olist
+$   write sys$output "Creating libzshr.exe"
+$   call anal_obj_axp modules.opt _link.opt
+$   if s_case
+$   then
+$      open/append optf modules.opt
+$      write optf "case_sensitive=YES"
+$      close optf
+$   endif
+$   LINK_'lopts'/SHARE=libzshr.exe modules.opt/opt,_link.opt/opt
+$ endif
+$ write sys$output "Zlib build completed"
+$ exit
+$CC_ERR:
+$ write sys$output "C compiler required to build ''name'"
+$ goto err_exit
+$ERR_EXIT:
+$ set message/facil/ident/sever/text
+$ write sys$output "Exiting..."
+$ exit 2
+$!
+$!
+$MAKE: SUBROUTINE   !SUBROUTINE TO CHECK DEPENDENCIES
+$ V = 'F$Verify(0)
+$! P1 = What we are trying to make
+$! P2 = Command to make it
+$! P3 - P8  What it depends on
+$
+$ If F$Search(P1) .Eqs. "" Then Goto Makeit
+$ Time = F$CvTime(F$File(P1,"RDT"))
+$arg=3
+$Loop:
+$       Argument = P'arg
+$       If Argument .Eqs. "" Then Goto Exit
+$       El=0
+$Loop2:
+$       File = F$Element(El," ",Argument)
+$       If File .Eqs. " " Then Goto Endl
+$       AFile = ""
+$Loop3:
+$       OFile = AFile
+$       AFile = F$Search(File)
+$       If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl
+$       If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit
+$       Goto Loop3
+$NextEL:
+$       El = El + 1
+$       Goto Loop2
+$EndL:
+$ arg=arg+1
+$ If arg .Le. 8 Then Goto Loop
+$ Goto Exit
+$
+$Makeit:
+$ VV=F$VERIFY(0)
+$ write sys$output P2
+$ 'P2
+$ VV='F$Verify(VV)
+$Exit:
+$ If V Then Set Verify
+$ENDSUBROUTINE
+$!------------------------------------------------------------------------------
+$!
+$! Check command line options and set symbols accordingly
+$!
+$ CHECK_OPTS:
+$ i = 1
+$ OPT_LOOP:
+$ if i .lt. 9
+$ then
+$   cparm = f$edit(p'i',"upcase")
+$   if cparm .eqs. "DEBUG"
+$   then
+$     ccopt = ccopt + "/noopt/deb"
+$     lopts = lopts + "/deb"
+$   endif
+$   if f$locate("CCOPT=",cparm) .lt. f$length(cparm)
+$   then
+$     start = f$locate("=",cparm) + 1
+$     len   = f$length(cparm) - start
+$     ccopt = ccopt + f$extract(start,len,cparm)
+$     if f$locate("AS_IS",f$edit(ccopt,"UPCASE")) .lt. f$length(ccopt) -
+         then s_case = true
+$   endif
+$   if cparm .eqs. "LINK" then linkonly = true
+$   if f$locate("LOPTS=",cparm) .lt. f$length(cparm)
+$   then
+$     start = f$locate("=",cparm) + 1
+$     len   = f$length(cparm) - start
+$     lopts = lopts + f$extract(start,len,cparm)
+$   endif
+$   if f$locate("CC=",cparm) .lt. f$length(cparm)
+$   then
+$     start  = f$locate("=",cparm) + 1
+$     len    = f$length(cparm) - start
+$     cc_com = f$extract(start,len,cparm)
+      if (cc_com .nes. "DECC") .and. -
+         (cc_com .nes. "VAXC") .and. -
+	 (cc_com .nes. "GNUC")
+$     then
+$       write sys$output "Unsupported compiler choice ''cc_com' ignored"
+$       write sys$output "Use DECC, VAXC, or GNUC instead"
+$     else
+$     	if cc_com .eqs. "DECC" then its_decc = true
+$     	if cc_com .eqs. "VAXC" then its_vaxc = true
+$     	if cc_com .eqs. "GNUC" then its_gnuc = true
+$     endif
+$   endif
+$   if f$locate("MAKE=",cparm) .lt. f$length(cparm)
+$   then
+$     start  = f$locate("=",cparm) + 1
+$     len    = f$length(cparm) - start
+$     mmks = f$extract(start,len,cparm)
+$     if (mmks .eqs. "MMK") .or. (mmks .eqs. "MMS")
+$     then
+$       make = mmks
+$     else
+$       write sys$output "Unsupported make choice ''mmks' ignored"
+$       write sys$output "Use MMK or MMS instead"
+$     endif
+$   endif
+$   i = i + 1
+$   goto opt_loop
+$ endif
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Look for the compiler used
+$!
+$CHECK_COMPILER:
+$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc))
+$ then
+$   its_decc = (f$search("SYS$SYSTEM:DECC$COMPILER.EXE") .nes. "")
+$   its_vaxc = .not. its_decc .and. (F$Search("SYS$System:VAXC.Exe") .nes. "")
+$   its_gnuc = .not. (its_decc .or. its_vaxc) .and. (f$trnlnm("gnu_cc") .nes. "")
+$ endif
+$!
+$! Exit if no compiler available
+$!
+$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc))
+$ then goto CC_ERR
+$ else
+$   if its_decc then write sys$output "CC compiler check ... Compaq C"
+$   if its_vaxc then write sys$output "CC compiler check ... VAX C"
+$   if its_gnuc then write sys$output "CC compiler check ... GNU C"
+$ endif
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! If MMS/MMK are available dump out the descrip.mms if required
+$!
+$CREA_MMS:
+$ write sys$output "Creating descrip.mms..."
+$ create descrip.mms
+$ open/append out descrip.mms
+$ copy sys$input: out
+$ deck
+# descrip.mms: MMS description file for building zlib on VMS
+# written by Martin P.J. Zinser
+# <zinser@zinser.no-ip.info or zinser@sysdev.deutsche-boerse.com>
+
+OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj, infback.obj\
+       deflate.obj, trees.obj, zutil.obj, inflate.obj, \
+       inftrees.obj, inffast.obj
+
+$ eod
+$ write out "CFLAGS=", ccopt
+$ write out "LOPTS=", lopts
+$ copy sys$input: out
+$ deck
+
+all : example.exe minigzip.exe libz.olb
+        @ write sys$output " Example applications available"
+
+libz.olb : libz.olb($(OBJS))
+	@ write sys$output " libz available"
+
+example.exe : example.obj libz.olb
+              link $(LOPTS) example,libz.olb/lib
+
+minigzip.exe : minigzip.obj libz.olb
+              link $(LOPTS) minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib
+
+clean :
+	delete *.obj;*,libz.olb;*,*.opt;*,*.exe;*
+
+
+# Other dependencies.
+adler32.obj  : adler32.c zutil.h zlib.h zconf.h
+compress.obj : compress.c zlib.h zconf.h
+crc32.obj    : crc32.c zutil.h zlib.h zconf.h
+deflate.obj  : deflate.c deflate.h zutil.h zlib.h zconf.h
+example.obj  : example.c zlib.h zconf.h
+gzio.obj     : gzio.c zutil.h zlib.h zconf.h
+inffast.obj  : inffast.c zutil.h zlib.h zconf.h inftrees.h inffast.h
+inflate.obj  : inflate.c zutil.h zlib.h zconf.h
+inftrees.obj : inftrees.c zutil.h zlib.h zconf.h inftrees.h
+minigzip.obj : minigzip.c zlib.h zconf.h
+trees.obj    : trees.c deflate.h zutil.h zlib.h zconf.h
+uncompr.obj  : uncompr.c zlib.h zconf.h
+zutil.obj    : zutil.c zutil.h zlib.h zconf.h
+infback.obj  : infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h
+$ eod
+$ close out
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Read list of core library sources from makefile.in and create options
+$! needed to build shareable image
+$!
+$CREA_OLIST:
+$ open/read min makefile.in
+$ open/write mod modules.opt
+$ src_check = "OBJS ="
+$MRLOOP:
+$ read/end=mrdone min rec
+$ if (f$extract(0,6,rec) .nes. src_check) then goto mrloop
+$ rec = rec - src_check
+$ gosub extra_filnam
+$ if (f$element(1,"\",rec) .eqs. "\") then goto mrdone
+$MRSLOOP:
+$ read/end=mrdone min rec
+$ gosub extra_filnam
+$ if (f$element(1,"\",rec) .nes. "\") then goto mrsloop
+$MRDONE:
+$ close min
+$ close mod
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Take record extracted in crea_olist and split it into single filenames
+$!
+$EXTRA_FILNAM:
+$ myrec = f$edit(rec - "\", "trim,compress")
+$ i = 0
+$FELOOP:
+$ srcfil = f$element(i," ", myrec)
+$ if (srcfil .nes. " ")
+$ then
+$   write mod f$parse(srcfil,,,"NAME"), ".obj"
+$   i = i + 1
+$   goto feloop
+$ endif
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Find current Zlib version number
+$!
+$FIND_VERSION:
+$ open/read h_in 'v_file'
+$hloop:
+$ read/end=hdone h_in rec
+$ rec = f$edit(rec,"TRIM")
+$ if (f$extract(0,1,rec) .nes. "#") then goto hloop
+$ rec = f$edit(rec - "#", "TRIM")
+$ if f$element(0," ",rec) .nes. "define" then goto hloop
+$ if f$element(1," ",rec) .eqs. v_string
+$ then
+$   version = 'f$element(2," ",rec)'
+$   goto hdone
+$ endif
+$ goto hloop
+$hdone:
+$ close h_in
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Analyze Object files for OpenVMS AXP to extract Procedure and Data
+$! information to build a symbol vector for a shareable image
+$! All the "brains" of this logic was suggested by Hartmut Becker
+$! (Hartmut.Becker@compaq.com). All the bugs were introduced by me
+$! (zinser@decus.de), so if you do have problem reports please do not
+$! bother Hartmut/HP, but get in touch with me
+$!
+$ ANAL_OBJ_AXP: Subroutine
+$ V = 'F$Verify(0)
+$ SAY := "WRITE_ SYS$OUTPUT"
+$
+$ IF F$SEARCH("''P1'") .EQS. ""
+$ THEN
+$    SAY "ANAL_OBJ_AXP-E-NOSUCHFILE:  Error, inputfile ''p1' not available"
+$    goto exit_aa
+$ ENDIF
+$ IF "''P2'" .EQS. ""
+$ THEN
+$    SAY "ANAL_OBJ_AXP:  Error, no output file provided"
+$    goto exit_aa
+$ ENDIF
+$
+$ open/read in 'p1
+$ create a.tmp
+$ open/append atmp a.tmp
+$ loop:
+$ read/end=end_loop in line
+$ f= f$search(line)
+$ if f .eqs. ""
+$ then
+$	write sys$output "ANAL_OBJ_AXP-w-nosuchfile, ''line'"
+$	goto loop
+$ endif
+$ define/user sys$output nl:
+$ define/user sys$error nl:
+$ anal/obj/gsd 'f /out=x.tmp
+$ open/read xtmp x.tmp
+$ XLOOP:
+$ read/end=end_xloop xtmp xline
+$ xline = f$edit(xline,"compress")
+$ write atmp xline
+$ goto xloop
+$ END_XLOOP:
+$ close xtmp
+$ goto loop
+$ end_loop:
+$ close in
+$ close atmp
+$ if f$search("a.tmp") .eqs. "" -
+	then $ exit
+$ ! all global definitions
+$ search a.tmp "symbol:","EGSY$V_DEF 1","EGSY$V_NORM 1"/out=b.tmp
+$ ! all procedures
+$ search b.tmp "EGSY$V_NORM 1"/wind=(0,1) /out=c.tmp
+$ search c.tmp "symbol:"/out=d.tmp
+$ define/user sys$output nl:
+$ edito/edt/command=sys$input d.tmp
+sub/symbol: "/symbol_vector=(/whole
+sub/"/=PROCEDURE)/whole
+exit
+$ ! all data
+$ search b.tmp "EGSY$V_DEF 1"/wind=(0,1) /out=e.tmp
+$ search e.tmp "symbol:"/out=f.tmp
+$ define/user sys$output nl:
+$ edito/edt/command=sys$input f.tmp
+sub/symbol: "/symbol_vector=(/whole
+sub/"/=DATA)/whole
+exit
+$ sort/nodupl d.tmp,f.tmp 'p2'
+$ delete a.tmp;*,b.tmp;*,c.tmp;*,d.tmp;*,e.tmp;*,f.tmp;*
+$ if f$search("x.tmp") .nes. "" -
+	then $ delete x.tmp;*
+$!
+$ EXIT_AA:
+$ if V then set verify
+$ endsubroutine
+$!------------------------------------------------------------------------------
Index: /trunk/minix/lib/zlib-1.2.3/minigzip.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/minigzip.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/minigzip.c	(revision 9)
@@ -0,0 +1,322 @@
+/* minigzip.c -- simulate gzip using the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * minigzip is a minimal implementation of the gzip utility. This is
+ * only an example of using zlib and isn't meant to replace the
+ * full-featured gzip. No attempt is made to deal with file systems
+ * limiting names to 14 or 8+3 characters, etc... Error checking is
+ * very limited. So use minigzip only for testing; use gzip for the
+ * real thing. On MSDOS, use only on file names without extension
+ * or in pipe mode.
+ */
+
+/* @(#) $Id: minigzip.c,v 1.1 2005/09/23 22:39:00 beng Exp $ */
+
+#include <stdio.h>
+#include "zlib.h"
+
+#ifdef STDC
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+
+#ifdef USE_MMAP
+#  include <sys/types.h>
+#  include <sys/mman.h>
+#  include <sys/stat.h>
+#endif
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
+#  include <fcntl.h>
+#  include <io.h>
+#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+#  define SET_BINARY_MODE(file)
+#endif
+
+#ifdef VMS
+#  define unlink delete
+#  define GZ_SUFFIX "-gz"
+#endif
+#ifdef RISCOS
+#  define unlink remove
+#  define GZ_SUFFIX "-gz"
+#  define fileno(file) file->__file
+#endif
+#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+#  include <unix.h> /* for fileno */
+#endif
+
+#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
+  extern int unlink OF((const char *));
+#endif
+
+#ifndef GZ_SUFFIX
+#  define GZ_SUFFIX ".gz"
+#endif
+#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
+
+#define BUFLEN      16384
+#define MAX_NAME_LEN 1024
+
+#ifdef MAXSEG_64K
+#  define local static
+   /* Needed for systems with limitation on stack size. */
+#else
+#  define local
+#endif
+
+char *prog;
+
+void error            OF((const char *msg));
+void gz_compress      OF((FILE   *in, gzFile out));
+#ifdef USE_MMAP
+int  gz_compress_mmap OF((FILE   *in, gzFile out));
+#endif
+void gz_uncompress    OF((gzFile in, FILE   *out));
+void file_compress    OF((char  *file, char *mode));
+void file_uncompress  OF((char  *file));
+int  main             OF((int argc, char *argv[]));
+
+/* ===========================================================================
+ * Display error message and exit
+ */
+void error(msg)
+    const char *msg;
+{
+    fprintf(stderr, "%s: %s\n", prog, msg);
+    exit(1);
+}
+
+/* ===========================================================================
+ * Compress input to output then close both files.
+ */
+
+void gz_compress(in, out)
+    FILE   *in;
+    gzFile out;
+{
+    local char buf[BUFLEN];
+    int len;
+    int err;
+
+#ifdef USE_MMAP
+    /* Try first compressing with mmap. If mmap fails (minigzip used in a
+     * pipe), use the normal fread loop.
+     */
+    if (gz_compress_mmap(in, out) == Z_OK) return;
+#endif
+    for (;;) {
+        len = (int)fread(buf, 1, sizeof(buf), in);
+        if (ferror(in)) {
+            perror("fread");
+            exit(1);
+        }
+        if (len == 0) break;
+
+        if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
+    }
+    fclose(in);
+    if (gzclose(out) != Z_OK) error("failed gzclose");
+}
+
+#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
+
+/* Try compressing the input file at once using mmap. Return Z_OK if
+ * if success, Z_ERRNO otherwise.
+ */
+int gz_compress_mmap(in, out)
+    FILE   *in;
+    gzFile out;
+{
+    int len;
+    int err;
+    int ifd = fileno(in);
+    caddr_t buf;    /* mmap'ed buffer for the entire input file */
+    off_t buf_len;  /* length of the input file */
+    struct stat sb;
+
+    /* Determine the size of the file, needed for mmap: */
+    if (fstat(ifd, &sb) < 0) return Z_ERRNO;
+    buf_len = sb.st_size;
+    if (buf_len <= 0) return Z_ERRNO;
+
+    /* Now do the actual mmap: */
+    buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
+    if (buf == (caddr_t)(-1)) return Z_ERRNO;
+
+    /* Compress the whole file at once: */
+    len = gzwrite(out, (char *)buf, (unsigned)buf_len);
+
+    if (len != (int)buf_len) error(gzerror(out, &err));
+
+    munmap(buf, buf_len);
+    fclose(in);
+    if (gzclose(out) != Z_OK) error("failed gzclose");
+    return Z_OK;
+}
+#endif /* USE_MMAP */
+
+/* ===========================================================================
+ * Uncompress input to output then close both files.
+ */
+void gz_uncompress(in, out)
+    gzFile in;
+    FILE   *out;
+{
+    local char buf[BUFLEN];
+    int len;
+    int err;
+
+    for (;;) {
+        len = gzread(in, buf, sizeof(buf));
+        if (len < 0) error (gzerror(in, &err));
+        if (len == 0) break;
+
+        if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
+            error("failed fwrite");
+        }
+    }
+    if (fclose(out)) error("failed fclose");
+
+    if (gzclose(in) != Z_OK) error("failed gzclose");
+}
+
+
+/* ===========================================================================
+ * Compress the given file: create a corresponding .gz file and remove the
+ * original.
+ */
+void file_compress(file, mode)
+    char  *file;
+    char  *mode;
+{
+    local char outfile[MAX_NAME_LEN];
+    FILE  *in;
+    gzFile out;
+
+    strcpy(outfile, file);
+    strcat(outfile, GZ_SUFFIX);
+
+    in = fopen(file, "rb");
+    if (in == NULL) {
+        perror(file);
+        exit(1);
+    }
+    out = gzopen(outfile, mode);
+    if (out == NULL) {
+        fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
+        exit(1);
+    }
+    gz_compress(in, out);
+
+    unlink(file);
+}
+
+
+/* ===========================================================================
+ * Uncompress the given file and remove the original.
+ */
+void file_uncompress(file)
+    char  *file;
+{
+    local char buf[MAX_NAME_LEN];
+    char *infile, *outfile;
+    FILE  *out;
+    gzFile in;
+    uInt len = (uInt)strlen(file);
+
+    strcpy(buf, file);
+
+    if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
+        infile = file;
+        outfile = buf;
+        outfile[len-3] = '\0';
+    } else {
+        outfile = file;
+        infile = buf;
+        strcat(infile, GZ_SUFFIX);
+    }
+    in = gzopen(infile, "rb");
+    if (in == NULL) {
+        fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
+        exit(1);
+    }
+    out = fopen(outfile, "wb");
+    if (out == NULL) {
+        perror(file);
+        exit(1);
+    }
+
+    gz_uncompress(in, out);
+
+    unlink(infile);
+}
+
+
+/* ===========================================================================
+ * Usage:  minigzip [-d] [-f] [-h] [-r] [-1 to -9] [files...]
+ *   -d : decompress
+ *   -f : compress with Z_FILTERED
+ *   -h : compress with Z_HUFFMAN_ONLY
+ *   -r : compress with Z_RLE
+ *   -1 to -9 : compression level
+ */
+
+int main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    int uncompr = 0;
+    gzFile file;
+    char outmode[20];
+
+    strcpy(outmode, "wb6 ");
+
+    prog = argv[0];
+    argc--, argv++;
+
+    while (argc > 0) {
+      if (strcmp(*argv, "-d") == 0)
+        uncompr = 1;
+      else if (strcmp(*argv, "-f") == 0)
+        outmode[3] = 'f';
+      else if (strcmp(*argv, "-h") == 0)
+        outmode[3] = 'h';
+      else if (strcmp(*argv, "-r") == 0)
+        outmode[3] = 'R';
+      else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
+               (*argv)[2] == 0)
+        outmode[2] = (*argv)[1];
+      else
+        break;
+      argc--, argv++;
+    }
+    if (outmode[3] == ' ')
+        outmode[3] = 0;
+    if (argc == 0) {
+        SET_BINARY_MODE(stdin);
+        SET_BINARY_MODE(stdout);
+        if (uncompr) {
+            file = gzdopen(fileno(stdin), "rb");
+            if (file == NULL) error("can't gzdopen stdin");
+            gz_uncompress(file, stdout);
+        } else {
+            file = gzdopen(fileno(stdout), outmode);
+            if (file == NULL) error("can't gzdopen stdout");
+            gz_compress(stdin, file);
+        }
+    } else {
+        do {
+            if (uncompr) {
+                file_uncompress(*argv);
+            } else {
+                file_compress(*argv, outmode);
+            }
+        } while (argv++, --argc);
+    }
+    return 0;
+}
Index: /trunk/minix/lib/zlib-1.2.3/msdos/Makefile.bor
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/msdos/Makefile.bor	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/msdos/Makefile.bor	(revision 9)
@@ -0,0 +1,109 @@
+# Makefile for zlib
+# Borland C++
+# Last updated: 15-Mar-2003
+
+# To use, do "make -fmakefile.bor"
+# To compile in small model, set below: MODEL=s
+
+# WARNING: the small model is supported but only for small values of
+# MAX_WBITS and MAX_MEM_LEVEL. For example:
+#    -DMAX_WBITS=11 -DDEF_WBITS=11 -DMAX_MEM_LEVEL=3
+# If you wish to reduce the memory requirements (default 256K for big
+# objects plus a few K), you can add to the LOC macro below:
+#   -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14
+# See zconf.h for details about the memory requirements.
+
+# ------------ Turbo C++, Borland C++ ------------
+
+#    Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7)
+#    should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added
+#    to the declaration of LOC here:
+LOC = $(LOCAL_ZLIB)
+
+# type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.
+CPU_TYP = 0
+
+# memory model: one of s, m, c, l (small, medium, compact, large)
+MODEL=l
+
+# replace bcc with tcc for Turbo C++ 1.0, with bcc32 for the 32 bit version
+CC=bcc
+LD=bcc
+AR=tlib
+
+# compiler flags
+# replace "-O2" by "-O -G -a -d" for Turbo C++ 1.0
+CFLAGS=-O2 -Z -m$(MODEL) $(LOC)
+
+LDFLAGS=-m$(MODEL) -f-
+
+
+# variables
+ZLIB_LIB = zlib_$(MODEL).lib
+
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
+OBJ2 = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infback.obj
+OBJP2 = +inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+
+
+# targets
+all: $(ZLIB_LIB) example.exe minigzip.exe
+
+.c.obj:
+	$(CC) -c $(CFLAGS) $*.c
+
+adler32.obj: adler32.c zlib.h zconf.h
+
+compress.obj: compress.c zlib.h zconf.h
+
+crc32.obj: crc32.c zlib.h zconf.h crc32.h
+
+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
+
+gzio.obj: gzio.c zutil.h zlib.h zconf.h
+
+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h
+
+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
+
+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
+
+uncompr.obj: uncompr.c zlib.h zconf.h
+
+zutil.obj: zutil.c zutil.h zlib.h zconf.h
+
+example.obj: example.c zlib.h zconf.h
+
+minigzip.obj: minigzip.c zlib.h zconf.h
+
+
+# the command line is cut to fit in the MS-DOS 128 byte limit:
+$(ZLIB_LIB): $(OBJ1) $(OBJ2)
+	-del $(ZLIB_LIB)
+	$(AR) $(ZLIB_LIB) $(OBJP1)
+	$(AR) $(ZLIB_LIB) $(OBJP2)
+
+example.exe: example.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) example.obj $(ZLIB_LIB)
+
+minigzip.exe: minigzip.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB)
+
+test: example.exe minigzip.exe
+	example
+	echo hello world | minigzip | minigzip -d
+
+clean:
+	-del *.obj
+	-del *.lib
+	-del *.exe
+	-del zlib_*.bak
+	-del foo.gz
Index: /trunk/minix/lib/zlib-1.2.3/msdos/Makefile.dj2
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/msdos/Makefile.dj2	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/msdos/Makefile.dj2	(revision 9)
@@ -0,0 +1,104 @@
+# Makefile for zlib.  Modified for djgpp v2.0 by F. J. Donahoe, 3/15/96.
+# Copyright (C) 1995-1998 Jean-loup Gailly.
+# For conditions of distribution and use, see copyright notice in zlib.h
+
+# To compile, or to compile and test, type:
+#
+#   make -fmakefile.dj2;  make test -fmakefile.dj2
+#
+# To install libz.a, zconf.h and zlib.h in the djgpp directories, type:
+#
+#    make install -fmakefile.dj2
+#
+# after first defining LIBRARY_PATH and INCLUDE_PATH in djgpp.env as
+# in the sample below if the pattern of the DJGPP distribution is to
+# be followed.  Remember that, while <sp>'es around <=> are ignored in
+# makefiles, they are *not* in batch files or in djgpp.env.
+# - - - - -
+# [make]
+# INCLUDE_PATH=%\>;INCLUDE_PATH%%\DJDIR%\include
+# LIBRARY_PATH=%\>;LIBRARY_PATH%%\DJDIR%\lib
+# BUTT=-m486
+# - - - - -
+# Alternately, these variables may be defined below, overriding the values
+# in djgpp.env, as
+# INCLUDE_PATH=c:\usr\include
+# LIBRARY_PATH=c:\usr\lib
+
+CC=gcc
+
+#CFLAGS=-MMD -O
+#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#CFLAGS=-MMD -g -DDEBUG
+CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+             -Wstrict-prototypes -Wmissing-prototypes
+
+# If cp.exe is available, replace "copy /Y" with "cp -fp" .
+CP=copy /Y
+# If gnu install.exe is available, replace $(CP) with ginstall.
+INSTALL=$(CP)
+# The default value of RM is "rm -f."  If "rm.exe" is found, comment out:
+RM=del
+LDLIBS=-L. -lz
+LD=$(CC) -s -o
+LDSHARED=$(CC)
+
+INCL=zlib.h zconf.h
+LIBS=libz.a
+
+AR=ar rcs
+
+prefix=/usr/local
+exec_prefix = $(prefix)
+
+OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
+       zutil.o inflate.o infback.o inftrees.o inffast.o
+
+OBJA =
+# to use the asm code: make OBJA=match.o
+
+TEST_OBJS = example.o minigzip.o
+
+all: example.exe minigzip.exe
+
+check: test
+test: all
+	./example
+	echo hello world | .\minigzip | .\minigzip -d
+
+%.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
+
+libz.a: $(OBJS) $(OBJA)
+	$(AR) $@ $(OBJS) $(OBJA)
+
+%.exe : %.o $(LIBS)
+	$(LD) $@ $< $(LDLIBS)
+
+# INCLUDE_PATH and LIBRARY_PATH were set for [make] in djgpp.env .
+
+.PHONY : uninstall clean
+
+install: $(INCL) $(LIBS)
+	-@if not exist $(INCLUDE_PATH)\nul mkdir $(INCLUDE_PATH)
+	-@if not exist $(LIBRARY_PATH)\nul mkdir $(LIBRARY_PATH)
+	$(INSTALL) zlib.h $(INCLUDE_PATH)
+	$(INSTALL) zconf.h $(INCLUDE_PATH)
+	$(INSTALL) libz.a $(LIBRARY_PATH)
+
+uninstall:
+	$(RM) $(INCLUDE_PATH)\zlib.h
+	$(RM) $(INCLUDE_PATH)\zconf.h
+	$(RM) $(LIBRARY_PATH)\libz.a
+
+clean:
+	$(RM) *.d
+	$(RM) *.o
+	$(RM) *.exe
+	$(RM) libz.a
+	$(RM) foo.gz
+
+DEPS := $(wildcard *.d)
+ifneq ($(DEPS),)
+include $(DEPS)
+endif
Index: /trunk/minix/lib/zlib-1.2.3/msdos/Makefile.emx
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/msdos/Makefile.emx	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/msdos/Makefile.emx	(revision 9)
@@ -0,0 +1,69 @@
+# Makefile for zlib.  Modified for emx 0.9c by Chr. Spieler, 6/17/98.
+# Copyright (C) 1995-1998 Jean-loup Gailly.
+# For conditions of distribution and use, see copyright notice in zlib.h
+
+# To compile, or to compile and test, type:
+#
+#   make -fmakefile.emx;  make test -fmakefile.emx
+#
+
+CC=gcc
+
+#CFLAGS=-MMD -O
+#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#CFLAGS=-MMD -g -DDEBUG
+CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+             -Wstrict-prototypes -Wmissing-prototypes
+
+# If cp.exe is available, replace "copy /Y" with "cp -fp" .
+CP=copy /Y
+# If gnu install.exe is available, replace $(CP) with ginstall.
+INSTALL=$(CP)
+# The default value of RM is "rm -f."  If "rm.exe" is found, comment out:
+RM=del
+LDLIBS=-L. -lzlib
+LD=$(CC) -s -o
+LDSHARED=$(CC)
+
+INCL=zlib.h zconf.h
+LIBS=zlib.a
+
+AR=ar rcs
+
+prefix=/usr/local
+exec_prefix = $(prefix)
+
+OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
+       zutil.o inflate.o infback.o inftrees.o inffast.o
+
+TEST_OBJS = example.o minigzip.o
+
+all: example.exe minigzip.exe
+
+test: all
+	./example
+	echo hello world | .\minigzip | .\minigzip -d
+
+%.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
+
+zlib.a: $(OBJS)
+	$(AR) $@ $(OBJS)
+
+%.exe : %.o $(LIBS)
+	$(LD) $@ $< $(LDLIBS)
+
+
+.PHONY : clean
+
+clean:
+	$(RM) *.d
+	$(RM) *.o
+	$(RM) *.exe
+	$(RM) zlib.a
+	$(RM) foo.gz
+
+DEPS := $(wildcard *.d)
+ifneq ($(DEPS),)
+include $(DEPS)
+endif
Index: /trunk/minix/lib/zlib-1.2.3/msdos/Makefile.msc
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/msdos/Makefile.msc	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/msdos/Makefile.msc	(revision 9)
@@ -0,0 +1,106 @@
+# Makefile for zlib
+# Microsoft C 5.1 or later
+# Last updated: 19-Mar-2003
+
+# To use, do "make makefile.msc"
+# To compile in small model, set below: MODEL=S
+
+# If you wish to reduce the memory requirements (default 256K for big
+# objects plus a few K), you can add to the LOC macro below:
+#   -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14
+# See zconf.h for details about the memory requirements.
+
+# ------------- Microsoft C 5.1 and later -------------
+
+#    Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7)
+#    should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added
+#    to the declaration of LOC here:
+LOC = $(LOCAL_ZLIB)
+
+# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.
+CPU_TYP = 0
+
+# Memory model: one of S, M, C, L (small, medium, compact, large)
+MODEL=L
+
+CC=cl
+CFLAGS=-nologo -A$(MODEL) -G$(CPU_TYP) -W3 -Oait -Gs $(LOC)
+#-Ox generates bad code with MSC 5.1
+LIB_CFLAGS=-Zl $(CFLAGS)
+
+LD=link
+LDFLAGS=/noi/e/st:0x1500/noe/farcall/packcode
+# "/farcall/packcode" are only useful for `large code' memory models
+# but should be a "no-op" for small code models.
+
+
+# variables
+ZLIB_LIB = zlib_$(MODEL).lib
+
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
+OBJ2 = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+
+
+# targets
+all:  $(ZLIB_LIB) example.exe minigzip.exe
+
+.c.obj:
+	$(CC) -c $(LIB_CFLAGS) $*.c
+
+adler32.obj: adler32.c zlib.h zconf.h
+
+compress.obj: compress.c zlib.h zconf.h
+
+crc32.obj: crc32.c zlib.h zconf.h crc32.h
+
+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
+
+gzio.obj: gzio.c zutil.h zlib.h zconf.h
+
+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h
+
+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
+
+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
+
+uncompr.obj: uncompr.c zlib.h zconf.h
+
+zutil.obj: zutil.c zutil.h zlib.h zconf.h
+
+example.obj: example.c zlib.h zconf.h
+	$(CC) -c $(CFLAGS) $*.c
+
+minigzip.obj: minigzip.c zlib.h zconf.h
+	$(CC) -c $(CFLAGS) $*.c
+
+
+# the command line is cut to fit in the MS-DOS 128 byte limit:
+$(ZLIB_LIB): $(OBJ1) $(OBJ2)
+	if exist $(ZLIB_LIB) del $(ZLIB_LIB)
+	lib $(ZLIB_LIB) $(OBJ1);
+	lib $(ZLIB_LIB) $(OBJ2);
+
+example.exe: example.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) example.obj,,,$(ZLIB_LIB);
+
+minigzip.exe: minigzip.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) minigzip.obj,,,$(ZLIB_LIB);
+
+test: example.exe minigzip.exe
+	example
+	echo hello world | minigzip | minigzip -d
+
+clean:
+	-del *.obj
+	-del *.lib
+	-del *.exe
+	-del *.map
+	-del zlib_*.bak
+	-del foo.gz
Index: /trunk/minix/lib/zlib-1.2.3/msdos/Makefile.tc
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/msdos/Makefile.tc	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/msdos/Makefile.tc	(revision 9)
@@ -0,0 +1,94 @@
+# Makefile for zlib
+# Turbo C 2.01, Turbo C++ 1.01
+# Last updated: 15-Mar-2003
+
+# To use, do "make -fmakefile.tc"
+# To compile in small model, set below: MODEL=s
+
+# WARNING: the small model is supported but only for small values of
+# MAX_WBITS and MAX_MEM_LEVEL. For example:
+#    -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
+# If you wish to reduce the memory requirements (default 256K for big
+# objects plus a few K), you can add to CFLAGS below:
+#   -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14
+# See zconf.h for details about the memory requirements.
+
+# ------------ Turbo C 2.01, Turbo C++ 1.01 ------------
+MODEL=l
+CC=tcc
+LD=tcc
+AR=tlib
+# CFLAGS=-O2 -G -Z -m$(MODEL) -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
+CFLAGS=-O2 -G -Z -m$(MODEL)
+LDFLAGS=-m$(MODEL) -f-
+
+
+# variables
+ZLIB_LIB = zlib_$(MODEL).lib
+
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
+OBJ2 = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infback.obj
+OBJP2 = +inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+
+
+# targets
+all: $(ZLIB_LIB) example.exe minigzip.exe
+
+.c.obj:
+	$(CC) -c $(CFLAGS) $*.c
+
+adler32.obj: adler32.c zlib.h zconf.h
+
+compress.obj: compress.c zlib.h zconf.h
+
+crc32.obj: crc32.c zlib.h zconf.h crc32.h
+
+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
+
+gzio.obj: gzio.c zutil.h zlib.h zconf.h
+
+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h
+
+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
+
+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
+
+uncompr.obj: uncompr.c zlib.h zconf.h
+
+zutil.obj: zutil.c zutil.h zlib.h zconf.h
+
+example.obj: example.c zlib.h zconf.h
+
+minigzip.obj: minigzip.c zlib.h zconf.h
+
+
+# the command line is cut to fit in the MS-DOS 128 byte limit:
+$(ZLIB_LIB): $(OBJ1) $(OBJ2)
+	-del $(ZLIB_LIB)
+	$(AR) $(ZLIB_LIB) $(OBJP1)
+	$(AR) $(ZLIB_LIB) $(OBJP2)
+
+example.exe: example.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) example.obj $(ZLIB_LIB)
+
+minigzip.exe: minigzip.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB)
+
+test: example.exe minigzip.exe
+	example
+	echo hello world | minigzip | minigzip -d
+
+clean:
+	-del *.obj
+	-del *.lib
+	-del *.exe
+	-del zlib_*.bak
+	-del foo.gz
Index: /trunk/minix/lib/zlib-1.2.3/old/Makefile.riscos
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/old/Makefile.riscos	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/old/Makefile.riscos	(revision 9)
@@ -0,0 +1,151 @@
+# Project:   zlib_1_03
+# Patched for zlib 1.1.2 rw@shadow.org.uk 19980430
+# test works out-of-the-box, installs `somewhere' on demand
+
+# Toolflags:
+CCflags = -c -depend !Depend -IC: -g -throwback  -DRISCOS  -fah
+C++flags = -c -depend !Depend -IC: -throwback
+Linkflags = -aif -c++ -o $@
+ObjAsmflags = -throwback -NoCache -depend !Depend
+CMHGflags =
+LibFileflags = -c -l -o $@
+Squeezeflags = -o $@
+
+# change the line below to where _you_ want the library installed.
+libdest = lib:zlib
+
+# Final targets:
+@.lib:   @.o.adler32 @.o.compress @.o.crc32 @.o.deflate @.o.gzio \
+        @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil @.o.trees \
+        @.o.uncompr @.o.zutil
+        LibFile $(LibFileflags) @.o.adler32 @.o.compress @.o.crc32 @.o.deflate \
+        @.o.gzio @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil \
+        @.o.trees @.o.uncompr @.o.zutil
+test:   @.minigzip @.example @.lib
+	@copy @.lib @.libc  A~C~DF~L~N~P~Q~RS~TV
+	@echo running tests: hang on.
+	@/@.minigzip -f -9 libc
+	@/@.minigzip -d libc-gz
+	@/@.minigzip -f -1 libc
+	@/@.minigzip -d libc-gz
+	@/@.minigzip -h -9 libc
+	@/@.minigzip -d libc-gz
+	@/@.minigzip -h -1 libc
+	@/@.minigzip -d libc-gz
+	@/@.minigzip -9 libc
+	@/@.minigzip -d libc-gz
+	@/@.minigzip -1 libc
+	@/@.minigzip -d libc-gz
+	@diff @.lib @.libc
+	@echo that should have reported '@.lib and @.libc identical' if you have diff.
+	@/@.example @.fred @.fred
+	@echo that will have given lots of hello!'s.
+
+@.minigzip:   @.o.minigzip @.lib C:o.Stubs
+        Link $(Linkflags) @.o.minigzip @.lib C:o.Stubs
+@.example:   @.o.example @.lib C:o.Stubs
+        Link $(Linkflags) @.o.example @.lib C:o.Stubs
+
+install: @.lib
+	cdir $(libdest)
+	cdir $(libdest).h
+	@copy @.h.zlib $(libdest).h.zlib A~C~DF~L~N~P~Q~RS~TV
+	@copy @.h.zconf $(libdest).h.zconf A~C~DF~L~N~P~Q~RS~TV
+	@copy @.lib $(libdest).lib  A~C~DF~L~N~P~Q~RS~TV
+	@echo okay, installed zlib in $(libdest)
+
+clean:; remove @.minigzip
+	remove @.example
+	remove @.libc
+	-wipe @.o.* F~r~cV
+	remove @.fred
+
+# User-editable dependencies:
+.c.o:
+        cc $(ccflags) -o $@ $<
+
+# Static dependencies:
+
+# Dynamic dependencies:
+o.example:	c.example
+o.example:	h.zlib
+o.example:	h.zconf
+o.minigzip:	c.minigzip
+o.minigzip:	h.zlib
+o.minigzip:	h.zconf
+o.adler32:	c.adler32
+o.adler32:	h.zlib
+o.adler32:	h.zconf
+o.compress:	c.compress
+o.compress:	h.zlib
+o.compress:	h.zconf
+o.crc32:	c.crc32
+o.crc32:	h.zlib
+o.crc32:	h.zconf
+o.deflate:	c.deflate
+o.deflate:	h.deflate
+o.deflate:	h.zutil
+o.deflate:	h.zlib
+o.deflate:	h.zconf
+o.gzio:	c.gzio
+o.gzio:	h.zutil
+o.gzio:	h.zlib
+o.gzio:	h.zconf
+o.infblock:	c.infblock
+o.infblock:	h.zutil
+o.infblock:	h.zlib
+o.infblock:	h.zconf
+o.infblock:	h.infblock
+o.infblock:	h.inftrees
+o.infblock:	h.infcodes
+o.infblock:	h.infutil
+o.infcodes:	c.infcodes
+o.infcodes:	h.zutil
+o.infcodes:	h.zlib
+o.infcodes:	h.zconf
+o.infcodes:	h.inftrees
+o.infcodes:	h.infblock
+o.infcodes:	h.infcodes
+o.infcodes:	h.infutil
+o.infcodes:	h.inffast
+o.inffast:	c.inffast
+o.inffast:	h.zutil
+o.inffast:	h.zlib
+o.inffast:	h.zconf
+o.inffast:	h.inftrees
+o.inffast:	h.infblock
+o.inffast:	h.infcodes
+o.inffast:	h.infutil
+o.inffast:	h.inffast
+o.inflate:	c.inflate
+o.inflate:	h.zutil
+o.inflate:	h.zlib
+o.inflate:	h.zconf
+o.inflate:	h.infblock
+o.inftrees:	c.inftrees
+o.inftrees:	h.zutil
+o.inftrees:	h.zlib
+o.inftrees:	h.zconf
+o.inftrees:	h.inftrees
+o.inftrees:	h.inffixed
+o.infutil:	c.infutil
+o.infutil:	h.zutil
+o.infutil:	h.zlib
+o.infutil:	h.zconf
+o.infutil:	h.infblock
+o.infutil:	h.inftrees
+o.infutil:	h.infcodes
+o.infutil:	h.infutil
+o.trees:	c.trees
+o.trees:	h.deflate
+o.trees:	h.zutil
+o.trees:	h.zlib
+o.trees:	h.zconf
+o.trees:	h.trees
+o.uncompr:	c.uncompr
+o.uncompr:	h.zlib
+o.uncompr:	h.zconf
+o.zutil:	c.zutil
+o.zutil:	h.zutil
+o.zutil:	h.zlib
+o.zutil:	h.zconf
Index: /trunk/minix/lib/zlib-1.2.3/old/README
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/old/README	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/old/README	(revision 9)
@@ -0,0 +1,3 @@
+This directory contains files that have not been updated for zlib 1.2.x
+
+(Volunteers are encouraged to help clean this up.  Thanks.)
Index: /trunk/minix/lib/zlib-1.2.3/old/descrip.mms
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/old/descrip.mms	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/old/descrip.mms	(revision 9)
@@ -0,0 +1,48 @@
+# descrip.mms: MMS description file for building zlib on VMS
+# written by Martin P.J. Zinser <m.zinser@gsi.de>
+
+cc_defs =
+c_deb =
+
+.ifdef __DECC__
+pref = /prefix=all
+.endif
+
+OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj,\
+       deflate.obj, trees.obj, zutil.obj, inflate.obj, infblock.obj,\
+       inftrees.obj, infcodes.obj, infutil.obj, inffast.obj
+
+CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF)
+
+all : example.exe minigzip.exe
+        @ write sys$output " Example applications available"
+libz.olb : libz.olb($(OBJS))
+	@ write sys$output " libz available"
+
+example.exe : example.obj libz.olb
+              link example,libz.olb/lib
+
+minigzip.exe : minigzip.obj libz.olb
+              link minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib
+
+clean :
+	delete *.obj;*,libz.olb;*
+
+
+# Other dependencies.
+adler32.obj : zutil.h zlib.h zconf.h
+compress.obj : zlib.h zconf.h
+crc32.obj : zutil.h zlib.h zconf.h
+deflate.obj : deflate.h zutil.h zlib.h zconf.h
+example.obj : zlib.h zconf.h
+gzio.obj : zutil.h zlib.h zconf.h
+infblock.obj : zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h
+infcodes.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h
+inffast.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h
+inflate.obj : zutil.h zlib.h zconf.h infblock.h
+inftrees.obj : zutil.h zlib.h zconf.h inftrees.h
+infutil.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h
+minigzip.obj : zlib.h zconf.h
+trees.obj : deflate.h zutil.h zlib.h zconf.h
+uncompr.obj : zlib.h zconf.h
+zutil.obj : zutil.h zlib.h zconf.h
Index: /trunk/minix/lib/zlib-1.2.3/old/os2/Makefile.os2
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/old/os2/Makefile.os2	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/old/os2/Makefile.os2	(revision 9)
@@ -0,0 +1,136 @@
+# Makefile for zlib under OS/2 using GCC (PGCC)
+# For conditions of distribution and use, see copyright notice in zlib.h
+
+# To compile and test, type:
+#   cp Makefile.os2 ..
+#   cd ..
+#   make -f Makefile.os2 test
+
+# This makefile will build a static library z.lib, a shared library
+# z.dll and a import library zdll.lib. You can use either z.lib or
+# zdll.lib by specifying either -lz or -lzdll on gcc's command line
+
+CC=gcc -Zomf -s
+
+CFLAGS=-O6 -Wall
+#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#CFLAGS=-g -DDEBUG
+#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+#           -Wstrict-prototypes -Wmissing-prototypes
+
+#################### BUG WARNING: #####################
+## infcodes.c hits a bug in pgcc-1.0, so you have to use either
+## -O# where # <= 4 or one of (-fno-ommit-frame-pointer or -fno-force-mem)
+## This bug is reportedly fixed in pgcc >1.0, but this was not tested
+CFLAGS+=-fno-force-mem
+
+LDFLAGS=-s -L. -lzdll -Zcrtdll
+LDSHARED=$(CC) -s -Zomf -Zdll -Zcrtdll
+
+VER=1.1.0
+ZLIB=z.lib
+SHAREDLIB=z.dll
+SHAREDLIBIMP=zdll.lib
+LIBS=$(ZLIB) $(SHAREDLIB) $(SHAREDLIBIMP)
+
+AR=emxomfar cr
+IMPLIB=emximp
+RANLIB=echo
+TAR=tar
+SHELL=bash
+
+prefix=/usr/local
+exec_prefix = $(prefix)
+
+OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
+       zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o
+
+TEST_OBJS = example.o minigzip.o
+
+DISTFILES = README INDEX ChangeLog configure Make*[a-z0-9] *.[ch] descrip.mms \
+  algorithm.txt zlib.3 msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \
+  nt/Makefile.nt nt/zlib.dnt  contrib/README.contrib contrib/*.txt \
+  contrib/asm386/*.asm contrib/asm386/*.c \
+  contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/iostream/*.cpp \
+  contrib/iostream/*.h  contrib/iostream2/*.h contrib/iostream2/*.cpp \
+  contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32
+
+all: example.exe minigzip.exe
+
+test: all
+	@LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
+	echo hello world | ./minigzip | ./minigzip -d || \
+	  echo '		*** minigzip test FAILED ***' ; \
+	if ./example; then \
+	  echo '		*** zlib test OK ***'; \
+	else \
+	  echo '		*** zlib test FAILED ***'; \
+	fi
+
+$(ZLIB): $(OBJS)
+	$(AR) $@ $(OBJS)
+	-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
+
+$(SHAREDLIB): $(OBJS) os2/z.def
+	$(LDSHARED) -o $@ $^
+
+$(SHAREDLIBIMP): os2/z.def
+	$(IMPLIB) -o $@ $^
+
+example.exe: example.o $(LIBS)
+	$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
+
+minigzip.exe: minigzip.o $(LIBS)
+	$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
+
+clean:
+	rm -f *.o *~ example minigzip libz.a libz.so* foo.gz
+
+distclean:	clean
+
+zip:
+	mv Makefile Makefile~; cp -p Makefile.in Makefile
+	rm -f test.c ztest*.c
+	v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\
+	zip -ul9 zlib$$v $(DISTFILES)
+	mv Makefile~ Makefile
+
+dist:
+	mv Makefile Makefile~; cp -p Makefile.in Makefile
+	rm -f test.c ztest*.c
+	d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\
+	rm -f $$d.tar.gz; \
+	if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \
+	files=""; \
+	for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \
+	cd ..; \
+	GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \
+	if test ! -d $$d; then rm -f $$d; fi
+	mv Makefile~ Makefile
+
+tags:
+	etags *.[ch]
+
+depend:
+	makedepend -- $(CFLAGS) -- *.[ch]
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+adler32.o: zlib.h zconf.h
+compress.o: zlib.h zconf.h
+crc32.o: zlib.h zconf.h
+deflate.o: deflate.h zutil.h zlib.h zconf.h
+example.o: zlib.h zconf.h
+gzio.o: zutil.h zlib.h zconf.h
+infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h
+infcodes.o: zutil.h zlib.h zconf.h
+infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h
+inffast.o: infblock.h infcodes.h infutil.h inffast.h
+inflate.o: zutil.h zlib.h zconf.h infblock.h
+inftrees.o: zutil.h zlib.h zconf.h inftrees.h
+infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h
+minigzip.o: zlib.h zconf.h
+trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
+uncompr.o: zlib.h zconf.h
+zutil.o: zutil.h zlib.h zconf.h
Index: /trunk/minix/lib/zlib-1.2.3/old/os2/zlib.def
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/old/os2/zlib.def	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/old/os2/zlib.def	(revision 9)
@@ -0,0 +1,51 @@
+;
+; Slightly modified version of ../nt/zlib.dnt :-)
+;
+
+LIBRARY		Z
+DESCRIPTION	"Zlib compression library for OS/2"
+CODE		PRELOAD MOVEABLE DISCARDABLE
+DATA		PRELOAD MOVEABLE MULTIPLE
+
+EXPORTS
+    adler32
+    compress
+    crc32
+    deflate
+    deflateCopy
+    deflateEnd
+    deflateInit2_
+    deflateInit_
+    deflateParams
+    deflateReset
+    deflateSetDictionary
+    gzclose
+    gzdopen
+    gzerror
+    gzflush
+    gzopen
+    gzread
+    gzwrite
+    inflate
+    inflateEnd
+    inflateInit2_
+    inflateInit_
+    inflateReset
+    inflateSetDictionary
+    inflateSync
+    uncompress
+    zlibVersion
+    gzprintf
+    gzputc
+    gzgetc
+    gzseek
+    gzrewind
+    gztell
+    gzeof
+    gzsetparams
+    zError
+    inflateSyncPoint
+    get_crc_table
+    compress2
+    gzputs
+    gzgets
Index: /trunk/minix/lib/zlib-1.2.3/old/visual-basic.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/old/visual-basic.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/old/visual-basic.txt	(revision 9)
@@ -0,0 +1,160 @@
+See below some functions declarations for Visual Basic.
+
+Frequently Asked Question:
+
+Q: Each time I use the compress function I get the -5 error (not enough
+   room in the output buffer).
+
+A: Make sure that the length of the compressed buffer is passed by
+   reference ("as any"), not by value ("as long"). Also check that
+   before the call of compress this length is equal to the total size of
+   the compressed buffer and not zero.
+
+
+From: "Jon Caruana" <jon-net@usa.net>
+Subject: Re: How to port zlib declares to vb?
+Date: Mon, 28 Oct 1996 18:33:03 -0600
+
+Got the answer! (I haven't had time to check this but it's what I got, and
+looks correct):
+
+He has the following routines working:
+        compress
+        uncompress
+        gzopen
+        gzwrite
+        gzread
+        gzclose
+
+Declares follow: (Quoted from Carlos Rios <c_rios@sonda.cl>, in Vb4 form)
+
+#If Win16 Then   'Use Win16 calls.
+Declare Function compress Lib "ZLIB.DLL" (ByVal compr As
+        String, comprLen As Any, ByVal buf As String, ByVal buflen
+        As Long) As Integer
+Declare Function uncompress Lib "ZLIB.DLL" (ByVal uncompr
+        As String, uncomprLen As Any, ByVal compr As String, ByVal
+        lcompr As Long) As Integer
+Declare Function gzopen Lib "ZLIB.DLL" (ByVal filePath As
+        String, ByVal mode As String) As Long
+Declare Function gzread Lib "ZLIB.DLL" (ByVal file As
+        Long, ByVal uncompr As String, ByVal uncomprLen As Integer)
+        As Integer
+Declare Function gzwrite Lib "ZLIB.DLL" (ByVal file As
+        Long, ByVal uncompr As String, ByVal uncomprLen As Integer)
+        As Integer
+Declare Function gzclose Lib "ZLIB.DLL" (ByVal file As
+        Long) As Integer
+#Else
+Declare Function compress Lib "ZLIB32.DLL"
+        (ByVal compr As String, comprLen As Any, ByVal buf As
+        String, ByVal buflen As Long) As Integer
+Declare Function uncompress Lib "ZLIB32.DLL"
+        (ByVal uncompr As String, uncomprLen As Any, ByVal compr As
+        String, ByVal lcompr As Long) As Long
+Declare Function gzopen Lib "ZLIB32.DLL"
+        (ByVal file As String, ByVal mode As String) As Long
+Declare Function gzread Lib "ZLIB32.DLL"
+        (ByVal file As Long, ByVal uncompr As String, ByVal
+        uncomprLen As Long) As Long
+Declare Function gzwrite Lib "ZLIB32.DLL"
+        (ByVal file As Long, ByVal uncompr As String, ByVal
+        uncomprLen As Long) As Long
+Declare Function gzclose Lib "ZLIB32.DLL"
+        (ByVal file As Long) As Long
+#End If
+
+-Jon Caruana
+jon-net@usa.net
+Microsoft Sitebuilder Network Level 1 Member - HTML Writer's Guild Member
+
+
+Here is another example from Michael <michael_borgsys@hotmail.com> that he
+says conforms to the VB guidelines, and that solves the problem of not
+knowing the uncompressed size by storing it at the end of the file:
+
+'Calling the functions:
+'bracket meaning: <parameter> [optional] {Range of possible values}
+'Call subCompressFile(<path with filename to compress> [, <path with
+filename to write to>, [level of compression {1..9}]])
+'Call subUncompressFile(<path with filename to compress>)
+
+Option Explicit
+Private lngpvtPcnSml As Long 'Stores value for 'lngPercentSmaller'
+Private Const SUCCESS As Long = 0
+Private Const strFilExt As String = ".cpr"
+Private Declare Function lngfncCpr Lib "zlib.dll" Alias "compress2" (ByRef
+dest As Any, ByRef destLen As Any, ByRef src As Any, ByVal srcLen As Long,
+ByVal level As Integer) As Long
+Private Declare Function lngfncUcp Lib "zlib.dll" Alias "uncompress" (ByRef
+dest As Any, ByRef destLen As Any, ByRef src As Any, ByVal srcLen As Long)
+As Long
+
+Public Sub subCompressFile(ByVal strargOriFilPth As String, Optional ByVal
+strargCprFilPth As String, Optional ByVal intLvl As Integer = 9)
+    Dim strCprPth As String
+    Dim lngOriSiz As Long
+    Dim lngCprSiz As Long
+    Dim bytaryOri() As Byte
+    Dim bytaryCpr() As Byte
+    lngOriSiz = FileLen(strargOriFilPth)
+    ReDim bytaryOri(lngOriSiz - 1)
+    Open strargOriFilPth For Binary Access Read As #1
+        Get #1, , bytaryOri()
+    Close #1
+    strCprPth = IIf(strargCprFilPth = "", strargOriFilPth, strargCprFilPth)
+'Select file path and name
+    strCprPth = strCprPth & IIf(Right(strCprPth, Len(strFilExt)) =
+strFilExt, "", strFilExt) 'Add file extension if not exists
+    lngCprSiz = (lngOriSiz * 1.01) + 12 'Compression needs temporary a bit
+more space then original file size
+    ReDim bytaryCpr(lngCprSiz - 1)
+    If lngfncCpr(bytaryCpr(0), lngCprSiz, bytaryOri(0), lngOriSiz, intLvl) =
+SUCCESS Then
+        lngpvtPcnSml = (1# - (lngCprSiz / lngOriSiz)) * 100
+        ReDim Preserve bytaryCpr(lngCprSiz - 1)
+        Open strCprPth For Binary Access Write As #1
+            Put #1, , bytaryCpr()
+            Put #1, , lngOriSiz 'Add the the original size value to the end
+(last 4 bytes)
+        Close #1
+    Else
+        MsgBox "Compression error"
+    End If
+    Erase bytaryCpr
+    Erase bytaryOri
+End Sub
+
+Public Sub subUncompressFile(ByVal strargFilPth As String)
+    Dim bytaryCpr() As Byte
+    Dim bytaryOri() As Byte
+    Dim lngOriSiz As Long
+    Dim lngCprSiz As Long
+    Dim strOriPth As String
+    lngCprSiz = FileLen(strargFilPth)
+    ReDim bytaryCpr(lngCprSiz - 1)
+    Open strargFilPth For Binary Access Read As #1
+        Get #1, , bytaryCpr()
+    Close #1
+    'Read the original file size value:
+    lngOriSiz = bytaryCpr(lngCprSiz - 1) * (2 ^ 24) _
+              + bytaryCpr(lngCprSiz - 2) * (2 ^ 16) _
+              + bytaryCpr(lngCprSiz - 3) * (2 ^ 8) _
+              + bytaryCpr(lngCprSiz - 4)
+    ReDim Preserve bytaryCpr(lngCprSiz - 5) 'Cut of the original size value
+    ReDim bytaryOri(lngOriSiz - 1)
+    If lngfncUcp(bytaryOri(0), lngOriSiz, bytaryCpr(0), lngCprSiz) = SUCCESS
+Then
+        strOriPth = Left(strargFilPth, Len(strargFilPth) - Len(strFilExt))
+        Open strOriPth For Binary Access Write As #1
+            Put #1, , bytaryOri()
+        Close #1
+    Else
+        MsgBox "Uncompression error"
+    End If
+    Erase bytaryCpr
+    Erase bytaryOri
+End Sub
+Public Property Get lngPercentSmaller() As Long
+    lngPercentSmaller = lngpvtPcnSml
+End Property
Index: /trunk/minix/lib/zlib-1.2.3/old/zlib.html
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/old/zlib.html	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/old/zlib.html	(revision 9)
@@ -0,0 +1,971 @@
+<html>
+<head>
+ <title>
+ zlib general purpose compression library version 1.1.4
+ </title>
+</head>
+<body bgcolor="White" text="Black" vlink="Red" alink="Navy" link="Red">
+<!-- background="zlibbg.gif" -->
+
+<h1> zlib 1.1.4 Manual </h1>
+<hr>
+<a name="Contents"><h2>Contents</h2>
+<ol type="I">
+<li> <a href="#Prologue">Prologue</a>
+<li> <a href="#Introduction">Introduction</a>
+<li> <a href="#Utility functions">Utility functions</a>
+<li> <a href="#Basic functions">Basic functions</a>
+<li> <a href="#Advanced functions">Advanced functions</a>
+<li> <a href="#Constants">Constants</a>
+<li> <a href="#struct z_stream_s">struct z_stream_s</a>
+<li> <a href="#Checksum functions">Checksum functions</a>
+<li> <a href="#Misc">Misc</a>
+</ol>
+<hr>
+<a name="Prologue"><h2> Prologue </h2>
+  'zlib' general purpose compression library version 1.1.4, March 11th, 2002
+  <p>
+  Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler
+  <p>
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+  <p>
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+  <ol>
+   <li> The origin of this software must not be misrepresented ; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+   <li> Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+   <li> This notice may not be removed or altered from any source distribution.
+  </ol>
+
+  <dl>
+  <dt>Jean-loup Gailly
+  <dd><a href="mailto:jloup@gzip.org">jloup@gzip.org</a>
+  <dt>Mark Adler
+  <dd><a href="mailto:madler@alumni.caltech.edu">madler@alumni.caltech.edu</a>
+  </dl>
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files
+  <a href="ftp://ds.internic.net/rfc/rfc1950.txt">
+  ftp://ds.internic.net/rfc/rfc1950.txt </a>
+  (zlib format),
+  <a href="ftp://ds.internic.net/rfc/rfc1951.txt">
+  rfc1951.txt </a>
+  (<a href="#deflate">deflate</a> format) and
+  <a href="ftp://ds.internic.net/rfc/rfc1952.txt">
+  rfc1952.txt </a>
+  (gzip format).
+  <p>
+  This manual is converted from zlib.h by
+  <a href="mailto:piaip@csie.ntu.edu.tw"> piaip </a>
+  <p>
+  Visit <a href="http://ftp.cdrom.com/pub/infozip/zlib/">
+  http://ftp.cdrom.com/pub/infozip/zlib/</a>
+  for the official zlib web page.
+  <p>
+
+<hr>
+<a name="Introduction"><h2> Introduction </h2>
+     The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed
+  data.  This version of the library supports only one compression method
+  (deflation) but other algorithms will be added later and will have the same
+  stream interface.
+  <p>
+
+     Compression can be done in a single step if the buffers are large
+  enough (for example if an input file is mmap'ed), or can be done by
+  repeated calls of the compression function.  In the latter case, the
+  application must provide more input and/or consume the output
+  (providing more output space) before each call.
+  <p>
+
+     The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio.
+  <p>
+
+     The library does not install any signal handler. The decoder checks
+  the consistency of the compressed data, so the library should never
+  crash even in case of corrupted input.
+  <p>
+
+<hr>
+<a name="Utility functions"><h2> Utility functions </h2>
+     The following utility functions are implemented on top of the
+   <a href="#Basic functions">basic stream-oriented functions</a>.
+   To simplify the interface, some
+   default options are assumed (compression level and memory usage,
+   standard memory allocation functions). The source code of these
+   utility functions can easily be modified if you need special options.
+<h3> Function list </h3>
+<ul>
+<li> int  <a href="#compress">compress</a> (Bytef *dest,   uLongf *destLen, const Bytef *source, uLong sourceLen);
+<li> int  <a href="#compress2">compress2</a> (Bytef *dest,   uLongf *destLen, const Bytef *source, uLong sourceLen, int level);
+<li> int  <a href="#uncompress">uncompress</a> (Bytef *dest,   uLongf *destLen, const Bytef *source, uLong sourceLen);
+<li> typedef voidp gzFile;
+<li>  gzFile  <a href="#gzopen">gzopen</a>  (const char *path, const char *mode);
+<li> gzFile  <a href="#gzdopen">gzdopen</a>  (int fd, const char *mode);
+<li> int  <a href="#gzsetparams">gzsetparams</a> (gzFile file, int level, int strategy);
+<li> int     <a href="#gzread">gzread</a>  (gzFile file, voidp buf, unsigned len);
+<li> int     <a href="#gzwrite">gzwrite</a> (gzFile file, const voidp buf, unsigned len);
+<li> int VA   <a href="#gzprintf">gzprintf</a> (gzFile file, const char *format, ...);
+<li> int  <a href="#gzputs">gzputs</a> (gzFile file, const char *s);
+<li> char *  <a href="#gzgets">gzgets</a> (gzFile file, char *buf, int len);
+<li> int     <a href="#gzputc">gzputc</a> (gzFile file, int c);
+<li> int     <a href="#gzgetc">gzgetc</a> (gzFile file);
+<li> int     <a href="#gzflush">gzflush</a> (gzFile file, int flush);
+<li> z_off_t     <a href="#gzseek">gzseek</a> (gzFile file, z_off_t offset, int whence);
+<li> z_off_t     <a href="#gztell">gztell</a> (gzFile file);
+<li> int     <a href="#gzrewind">gzrewind</a> (gzFile file);
+<li> int  <a href="#gzeof">gzeof</a> (gzFile file);
+<li> int     <a href="#gzclose">gzclose</a> (gzFile file);
+<li> const char *  <a href="#gzerror">gzerror</a> (gzFile file, int *errnum);
+</ul>
+<h3> Function description </h3>
+<dl>
+<font color="Blue"><dt> int  <a name="compress">compress</a> (Bytef *dest,   uLongf *destLen, const Bytef *source, uLong sourceLen);</font>
+<dd>
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be at least 0.1% larger than
+   sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
+   compressed buffer.<p>
+     This function can be used to <a href="#compress">compress</a> a whole file at once if the
+   input file is mmap'ed.<p>
+     <a href="#compress">compress</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not
+   enough memory, <a href="#Z_BUF_ERROR">Z_BUF_ERROR</a> if there was not enough room in the output
+   buffer.<p>
+
+<font color="Blue"><dt> int  <a name="compress2">compress2</a> (Bytef *dest,   uLongf *destLen, const Bytef *source, uLong sourceLen, int level);</font>
+<dd>
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in <a href="#deflateInit">deflateInit</a>.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least 0.1% larger than sourceLen plus
+   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+   <p>
+
+     <a href="#compress2">compress2</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not enough
+   memory, <a href="#Z_BUF_ERROR">Z_BUF_ERROR</a> if there was not enough room in the output buffer,
+   <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the level parameter is invalid.
+   <p>
+
+<font color="Blue"><dt> int  <a name="uncompress">uncompress</a> (Bytef *dest,   uLongf *destLen, const Bytef *source, uLong sourceLen);</font>
+<dd>
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer. <p>
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+   <p>
+
+     <a href="#uncompress">uncompress</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not
+   enough memory, <a href="#Z_BUF_ERROR">Z_BUF_ERROR</a> if there was not enough room in the output
+   buffer, or <a href="#Z_DATA_ERROR">Z_DATA_ERROR</a> if the input data was corrupted.
+   <p>
+
+<dt> typedef voidp gzFile;
+<dd> <p>
+
+<font color="Blue"><dt>  gzFile  <a name="gzopen">gzopen</a>  (const char *path, const char *mode);</font>
+<dd>
+     Opens a gzip (.gz) file for reading or writing. The mode parameter
+   is as in fopen ("rb" or "wb") but can also include a compression level
+   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+   Huffman only compression as in "wb1h". (See the description
+   of <a href="#deflateInit2">deflateInit2</a> for more information about the strategy parameter.)
+   <p>
+
+     <a href="#gzopen">gzopen</a> can be used to read a file which is not in gzip format ; in this
+   case <a href="#gzread">gzread</a> will directly read from the file without decompression.
+   <p>
+
+     <a href="#gzopen">gzopen</a> returns NULL if the file could not be opened or if there was
+   insufficient memory to allocate the (de)compression <a href="#state">state</a> ; errno
+   can be checked to distinguish the two cases (if errno is zero, the
+   zlib error is <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a>).
+   <p>
+
+<font color="Blue"><dt> gzFile  <a name="gzdopen">gzdopen</a>  (int fd, const char *mode);</font>
+<dd>
+     <a href="#gzdopen">gzdopen</a>() associates a gzFile with the file descriptor fd.  File
+   descriptors are obtained from calls like open, dup, creat, pipe or
+   fileno (in the file has been previously opened with fopen).
+   The mode parameter is as in <a href="#gzopen">gzopen</a>.
+   <p>
+     The next call of <a href="#gzclose">gzclose</a> on the returned gzFile will also close the
+   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+   descriptor fd. If you want to keep fd open, use <a href="#gzdopen">gzdopen</a>(dup(fd), mode).
+   <p>
+     <a href="#gzdopen">gzdopen</a> returns NULL if there was insufficient memory to allocate
+   the (de)compression <a href="#state">state</a>.
+   <p>
+
+<font color="Blue"><dt> int  <a name="gzsetparams">gzsetparams</a> (gzFile file, int level, int strategy);</font>
+<dd>
+     Dynamically update the compression level or strategy. See the description
+   of <a href="#deflateInit2">deflateInit2</a> for the meaning of these parameters.
+   <p>
+     <a href="#gzsetparams">gzsetparams</a> returns <a href="#Z_OK">Z_OK</a> if success, or <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the file was not
+   opened for writing.
+   <p>
+
+<font color="Blue"><dt> int     <a name="gzread">gzread</a>  (gzFile file, voidp buf, unsigned len);</font>
+<dd>
+     Reads the given number of uncompressed bytes from the compressed file.
+   If the input file was not in gzip format, <a href="#gzread">gzread</a> copies the given number
+   of bytes into the buffer.
+   <p>
+     <a href="#gzread">gzread</a> returns the number of uncompressed bytes actually read (0 for
+   end of file, -1 for error).
+   <p>
+
+<font color="Blue"><dt> int     <a name="gzwrite">gzwrite</a> (gzFile file, const voidp buf, unsigned len);</font>
+<dd>
+     Writes the given number of uncompressed bytes into the compressed file.
+   <a href="#gzwrite">gzwrite</a> returns the number of uncompressed bytes actually written
+   (0 in case of error).
+   <p>
+
+<font color="Blue"><dt> int VA   <a name="gzprintf">gzprintf</a> (gzFile file, const char *format, ...);</font>
+<dd>
+     Converts, formats, and writes the args to the compressed file under
+   control of the format string, as in fprintf. <a href="#gzprintf">gzprintf</a> returns the number of
+   uncompressed bytes actually written (0 in case of error).
+   <p>
+
+<font color="Blue"><dt> int  <a name="gzputs">gzputs</a> (gzFile file, const char *s);</font>
+<dd>
+      Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+   <p>
+      <a href="#gzputs">gzputs</a> returns the number of characters written, or -1 in case of error.
+      <p>
+
+<font color="Blue"><dt> char *  <a name="gzgets">gzgets</a> (gzFile file, char *buf, int len);</font>
+<dd>
+      Reads bytes from the compressed file until len-1 characters are read, or
+   a newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  The string is then terminated with a null
+   character.
+   <p>
+      <a href="#gzgets">gzgets</a> returns buf, or <a href="#Z_NULL">Z_NULL</a> in case of error.
+      <p>
+
+<font color="Blue"><dt> int     <a name="gzputc">gzputc</a> (gzFile file, int c);</font>
+<dd>
+      Writes c, converted to an unsigned char, into the compressed file.
+   <a href="#gzputc">gzputc</a> returns the value that was written, or -1 in case of error.
+   <p>
+
+<font color="Blue"><dt> int     <a name="gzgetc">gzgetc</a> (gzFile file);</font>
+<dd>
+      Reads one byte from the compressed file. <a href="#gzgetc">gzgetc</a> returns this byte
+   or -1 in case of end of file or error.
+   <p>
+
+<font color="Blue"><dt> int     <a name="gzflush">gzflush</a> (gzFile file, int flush);</font>
+<dd>
+     Flushes all pending output into the compressed file. The parameter
+   flush is as in the <a href="#deflate">deflate</a>() function. The return value is the zlib
+   error number (see function <a href="#gzerror">gzerror</a> below). <a href="#gzflush">gzflush</a> returns <a href="#Z_OK">Z_OK</a> if
+   the flush parameter is <a href="#Z_FINISH">Z_FINISH</a> and all output could be flushed.
+   <p>
+     <a href="#gzflush">gzflush</a> should be called only when strictly necessary because it can
+   degrade compression.
+   <p>
+
+<font color="Blue"><dt> z_off_t     <a name="gzseek">gzseek</a> (gzFile file, z_off_t offset, int whence);</font>
+<dd>
+      Sets the starting position for the next <a href="#gzread">gzread</a> or <a href="#gzwrite">gzwrite</a> on the
+   given compressed file. The offset represents a number of bytes in the
+   uncompressed data stream. The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+   <p>
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow. If the file is opened for writing, only forward seeks are
+   supported ; <a href="#gzseek">gzseek</a> then compresses a sequence of zeroes up to the new
+   starting position.
+   <p>
+      <a href="#gzseek">gzseek</a> returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+   <p>
+
+<font color="Blue"><dt> int     <a name="gzrewind">gzrewind</a> (gzFile file);</font>
+<dd>
+     Rewinds the given file. This function is supported only for reading.
+     <p>
+   <a href="#gzrewind">gzrewind</a>(file) is equivalent to (int)<a href="#gzseek">gzseek</a>(file, 0L, SEEK_SET)
+   <p>
+
+<font color="Blue"><dt> z_off_t     <a name="gztell">gztell</a> (gzFile file);</font>
+<dd>
+     Returns the starting position for the next <a href="#gzread">gzread</a> or <a href="#gzwrite">gzwrite</a> on the
+   given compressed file. This position represents a number of bytes in the
+   uncompressed data stream.
+   <p>
+
+   <a href="#gztell">gztell</a>(file) is equivalent to <a href="#gzseek">gzseek</a>(file, 0L, SEEK_CUR)
+   <p>
+
+<font color="Blue"><dt> int  <a name="gzeof">gzeof</a> (gzFile file);</font>
+<dd>
+     Returns 1 when EOF has previously been detected reading the given
+   input stream, otherwise zero.
+   <p>
+
+<font color="Blue"><dt> int     <a name="gzclose">gzclose</a> (gzFile file);</font>
+<dd>
+     Flushes all pending output if necessary, closes the compressed file
+   and deallocates all the (de)compression <a href="#state">state</a>. The return value is the zlib
+   error number (see function <a href="#gzerror">gzerror</a> below).
+   <p>
+
+<font color="Blue"><dt> const char *  <a name="gzerror">gzerror</a> (gzFile file, int *errnum);</font>
+<dd>
+     Returns the error message for the last error which occurred on the
+   given compressed file. errnum is set to zlib error number. If an
+   error occurred in the file system and not in the compression library,
+   errnum is set to <a href="#Z_ERRNO">Z_ERRNO</a> and the application may consult errno
+   to get the exact error code.
+   <p>
+</dl>
+<hr>
+<a name="Basic functions"><h2> Basic functions </h2>
+<h3> Function list </h3>
+<ul>
+<li>  const char *  <a href="#zlibVersion">zlibVersion</a> (void);
+<li>  int  <a href="#deflateInit">deflateInit</a> (<a href="#z_streamp">z_streamp</a> strm, int level);
+<li>  int  <a href="#deflate">deflate</a> (<a href="#z_streamp">z_streamp</a> strm, int flush);
+<li>  int  <a href="#deflateEnd">deflateEnd</a> (<a href="#z_streamp">z_streamp</a> strm);
+<li>  int  <a href="#inflateInit">inflateInit</a> (<a href="#z_streamp">z_streamp</a> strm);
+<li>  int  <a href="#inflate">inflate</a> (<a href="#z_streamp">z_streamp</a> strm, int flush);
+<li>  int  <a href="#inflateEnd">inflateEnd</a> (<a href="#z_streamp">z_streamp</a> strm);
+</ul>
+
+<h3> Function description </h3>
+<dl>
+<font color="Blue"><dt>  const char *  <a name="zlibVersion">zlibVersion</a> (void);</font>
+<dd> The application can compare <a href="#zlibVersion">zlibVersion</a> and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is
+   not compatible with the zlib.h header file used by the application.
+   This check is automatically made by <a href="#deflateInit">deflateInit</a> and <a href="#inflateInit">inflateInit</a>.
+   <p>
+
+<font color="Blue"><dt> int  <a name="deflateInit">deflateInit</a> (<a href="#z_streamp">z_streamp</a> strm, int level);</font>
+<dd>
+     Initializes the internal stream <a href="#state">state</a> for compression. The fields
+   <a href="#zalloc">zalloc</a>, <a href="#zfree">zfree</a> and <a href="#opaque">opaque</a> must be initialized before by the caller.
+   If <a href="#zalloc">zalloc</a> and <a href="#zfree">zfree</a> are set to <a href="#Z_NULL">Z_NULL</a>, <a href="#deflateInit">deflateInit</a> updates them to
+   use default allocation functions.
+   <p>
+
+     The compression level must be <a href="#Z_DEFAULT_COMPRESSION">Z_DEFAULT_COMPRESSION</a>, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at
+   all (the input data is simply copied a block at a time).
+   <p>
+
+   <a href="#Z_DEFAULT_COMPRESSION">Z_DEFAULT_COMPRESSION</a> requests a default compromise between speed and
+   compression (currently equivalent to level 6).
+   <p>
+
+     <a href="#deflateInit">deflateInit</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not
+   enough memory, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if level is not a valid compression level,
+   <a href="#Z_VERSION_ERROR">Z_VERSION_ERROR</a> if the zlib library version (<a href="#zlib_version">zlib_version</a>) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).
+   <a href="#msg">msg</a> is set to null if there is no error message.  <a href="#deflateInit">deflateInit</a> does not
+   perform any compression: this will be done by <a href="#deflate">deflate</a>().
+   <p>
+
+<font color="Blue"><dt>  int  <a name="deflate">deflate</a> (<a href="#z_streamp">z_streamp</a> strm, int flush);</font>
+<dd>
+    <a href="#deflate">deflate</a> compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may introduce some
+  output latency (reading input without producing any output) except when
+  forced to flush.<p>
+
+    The detailed semantics are as follows. <a href="#deflate">deflate</a> performs one or both of the
+  following actions:
+
+  <ul>
+  <li> Compress more input starting at <a href="#next_in">next_in</a> and update <a href="#next_in">next_in</a> and <a href="#avail_in">avail_in</a>
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), <a href="#next_in">next_in</a> and <a href="#avail_in">avail_in</a> are updated and
+    processing will resume at this point for the next call of <a href="#deflate">deflate</a>().
+
+  <li>
+    Provide more output starting at <a href="#next_out">next_out</a> and update <a href="#next_out">next_out</a> and <a href="#avail_out">avail_out</a>
+    accordingly. This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).
+    Some output may be provided even if flush is not set.
+  </ul> <p>
+
+  Before the call of <a href="#deflate">deflate</a>(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating <a href="#avail_in">avail_in</a> or <a href="#avail_out">avail_out</a> accordingly ; <a href="#avail_out">avail_out</a>
+  should never be zero before the call. The application can consume the
+  compressed output when it wants, for example when the output buffer is full
+  (<a href="#avail_out">avail_out</a> == 0), or after each call of <a href="#deflate">deflate</a>(). If <a href="#deflate">deflate</a> returns <a href="#Z_OK">Z_OK</a>
+  and with zero <a href="#avail_out">avail_out</a>, it must be called again after making room in the
+  output buffer because there might be more output pending.
+  <p>
+
+    If the parameter flush is set to <a href="#Z_SYNC_FLUSH">Z_SYNC_FLUSH</a>, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far. (In particular
+  <a href="#avail_in">avail_in</a> is zero after the call if enough output space has been provided
+  before the call.)  Flushing may degrade compression for some compression
+  algorithms and so it should be used only when necessary.
+  <p>
+
+    If flush is set to <a href="#Z_FULL_FLUSH">Z_FULL_FLUSH</a>, all output is flushed as with
+  <a href="#Z_SYNC_FLUSH">Z_SYNC_FLUSH</a>, and the compression <a href="#state">state</a> is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired. Using <a href="#Z_FULL_FLUSH">Z_FULL_FLUSH</a> too often can seriously degrade
+  the compression.
+  <p>
+
+    If <a href="#deflate">deflate</a> returns with <a href="#avail_out">avail_out</a> == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  <a href="#avail_out">avail_out</a>), until the flush is complete (<a href="#deflate">deflate</a> returns with non-zero
+  <a href="#avail_out">avail_out</a>).
+  <p>
+
+    If the parameter flush is set to <a href="#Z_FINISH">Z_FINISH</a>, pending input is processed,
+  pending output is flushed and <a href="#deflate">deflate</a> returns with <a href="#Z_STREAM_END">Z_STREAM_END</a> if there
+  was enough output space ; if <a href="#deflate">deflate</a> returns with <a href="#Z_OK">Z_OK</a>, this function must be
+  called again with <a href="#Z_FINISH">Z_FINISH</a> and more output space (updated <a href="#avail_out">avail_out</a>) but no
+  more input data, until it returns with <a href="#Z_STREAM_END">Z_STREAM_END</a> or an error. After
+  <a href="#deflate">deflate</a> has returned <a href="#Z_STREAM_END">Z_STREAM_END</a>, the only possible operations on the
+  stream are <a href="#deflateReset">deflateReset</a> or <a href="#deflateEnd">deflateEnd</a>.
+  <p>
+
+    <a href="#Z_FINISH">Z_FINISH</a> can be used immediately after <a href="#deflateInit">deflateInit</a> if all the compression
+  is to be done in a single step. In this case, <a href="#avail_out">avail_out</a> must be at least
+  0.1% larger than <a href="#avail_in">avail_in</a> plus 12 bytes.  If <a href="#deflate">deflate</a> does not return
+  <a href="#Z_STREAM_END">Z_STREAM_END</a>, then it must be called again as described above.
+  <p>
+
+    <a href="#deflate">deflate</a>() sets strm-&gt <a href="#adler">adler</a> to the <a href="#adler32">adler32</a> checksum of all input read
+  so far (that is, <a href="#total_in">total_in</a> bytes).
+  <p>
+
+    <a href="#deflate">deflate</a>() may update <a href="#data_type">data_type</a> if it can make a good guess about
+  the input data type (<a href="#Z_ASCII">Z_ASCII</a> or <a href="#Z_BINARY">Z_BINARY</a>). In doubt, the data is considered
+  binary. This field is only for information purposes and does not affect
+  the compression algorithm in any manner.
+  <p>
+
+    <a href="#deflate">deflate</a>() returns <a href="#Z_OK">Z_OK</a> if some progress has been made (more input
+  processed or more output produced), <a href="#Z_STREAM_END">Z_STREAM_END</a> if all input has been
+  consumed and all output has been produced (only when flush is set to
+  <a href="#Z_FINISH">Z_FINISH</a>), <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the stream <a href="#state">state</a> was inconsistent (for example
+  if <a href="#next_in">next_in</a> or <a href="#next_out">next_out</a> was NULL), <a href="#Z_BUF_ERROR">Z_BUF_ERROR</a> if no progress is possible
+  (for example <a href="#avail_in">avail_in</a> or <a href="#avail_out">avail_out</a> was zero).
+  <p>
+
+<font color="Blue"><dt>  int  <a name="deflateEnd">deflateEnd</a> (<a href="#z_streamp">z_streamp</a> strm);</font>
+<dd>
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+   <p>
+
+     <a href="#deflateEnd">deflateEnd</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the
+   stream <a href="#state">state</a> was inconsistent, <a href="#Z_DATA_ERROR">Z_DATA_ERROR</a> if the stream was freed
+   prematurely (some input or output was discarded). In the error case,
+   <a href="#msg">msg</a> may be set but then points to a static string (which must not be
+   deallocated).
+   <p>
+
+<font color="Blue"><dt>  int  <a name="inflateInit">inflateInit</a> (<a href="#z_streamp">z_streamp</a> strm);</font>
+<dd>
+	Initializes the internal stream <a href="#state">state</a> for decompression. The fields
+   <a href="#next_in">next_in</a>, <a href="#avail_in">avail_in</a>, <a href="#zalloc">zalloc</a>, <a href="#zfree">zfree</a> and <a href="#opaque">opaque</a> must be initialized before by
+   the caller. If <a href="#next_in">next_in</a> is not <a href="#Z_NULL">Z_NULL</a> and <a href="#avail_in">avail_in</a> is large enough (the exact
+   value depends on the compression method), <a href="#inflateInit">inflateInit</a> determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly ; otherwise the allocation will be deferred to the first call of
+   <a href="#inflate">inflate</a>.  If <a href="#zalloc">zalloc</a> and <a href="#zfree">zfree</a> are set to <a href="#Z_NULL">Z_NULL</a>, <a href="#inflateInit">inflateInit</a> updates them to
+   use default allocation functions.
+   <p>
+
+     <a href="#inflateInit">inflateInit</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not enough
+   memory, <a href="#Z_VERSION_ERROR">Z_VERSION_ERROR</a> if the zlib library version is incompatible with the
+   version assumed by the caller.  <a href="#msg">msg</a> is set to null if there is no error
+   message. <a href="#inflateInit">inflateInit</a> does not perform any decompression apart from reading
+   the zlib header if present: this will be done by <a href="#inflate">inflate</a>().  (So <a href="#next_in">next_in</a> and
+   <a href="#avail_in">avail_in</a> may be modified, but <a href="#next_out">next_out</a> and <a href="#avail_out">avail_out</a> are unchanged.)
+   <p>
+
+<font color="Blue"><dt>  int  <a name="inflate">inflate</a> (<a href="#z_streamp">z_streamp</a> strm, int flush);</font>
+<dd>
+    <a href="#inflate">inflate</a> decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may some
+  introduce some output latency (reading input without producing any output)
+  except when forced to flush.
+  <p>
+
+  The detailed semantics are as follows. <a href="#inflate">inflate</a> performs one or both of the
+  following actions:
+
+  <ul>
+  <li> Decompress more input starting at <a href="#next_in">next_in</a> and update <a href="#next_in">next_in</a> and <a href="#avail_in">avail_in</a>
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), <a href="#next_in">next_in</a> is updated and processing
+    will resume at this point for the next call of <a href="#inflate">inflate</a>().
+
+  <li> Provide more output starting at <a href="#next_out">next_out</a> and update <a href="#next_out">next_out</a> and
+    <a href="#avail_out">avail_out</a> accordingly.  <a href="#inflate">inflate</a>() provides as much output as possible,
+    until there is no more input data or no more space in the output buffer
+    (see below about the flush parameter).
+  </ul> <p>
+
+  Before the call of <a href="#inflate">inflate</a>(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating the next_* and avail_* values accordingly.
+  The application can consume the uncompressed output when it wants, for
+  example when the output buffer is full (<a href="#avail_out">avail_out</a> == 0), or after each
+  call of <a href="#inflate">inflate</a>(). If <a href="#inflate">inflate</a> returns <a href="#Z_OK">Z_OK</a> and with zero <a href="#avail_out">avail_out</a>, it
+  must be called again after making room in the output buffer because there
+  might be more output pending.
+  <p>
+
+    If the parameter flush is set to <a href="#Z_SYNC_FLUSH">Z_SYNC_FLUSH</a>, <a href="#inflate">inflate</a> flushes as much
+  output as possible to the output buffer. The flushing behavior of <a href="#inflate">inflate</a> is
+  not specified for values of the flush parameter other than <a href="#Z_SYNC_FLUSH">Z_SYNC_FLUSH</a>
+  and <a href="#Z_FINISH">Z_FINISH</a>, but the current implementation actually flushes as much output
+  as possible anyway.
+  <p>
+
+    <a href="#inflate">inflate</a>() should normally be called until it returns <a href="#Z_STREAM_END">Z_STREAM_END</a> or an
+  error. However if all decompression is to be performed in a single step
+  (a single call of <a href="#inflate">inflate</a>), the parameter flush should be set to
+  <a href="#Z_FINISH">Z_FINISH</a>. In this case all pending input is processed and all pending
+  output is flushed ; <a href="#avail_out">avail_out</a> must be large enough to hold all the
+  uncompressed data. (The size of the uncompressed data may have been saved
+  by the compressor for this purpose.) The next operation on this stream must
+  be <a href="#inflateEnd">inflateEnd</a> to deallocate the decompression <a href="#state">state</a>. The use of <a href="#Z_FINISH">Z_FINISH</a>
+  is never required, but can be used to inform <a href="#inflate">inflate</a> that a faster routine
+  may be used for the single <a href="#inflate">inflate</a>() call.
+  <p>
+
+     If a preset dictionary is needed at this point (see <a href="#inflateSetDictionary">inflateSetDictionary</a>
+  below), <a href="#inflate">inflate</a> sets strm-<a href="#adler">adler</a> to the <a href="#adler32">adler32</a> checksum of the
+  dictionary chosen by the compressor and returns <a href="#Z_NEED_DICT">Z_NEED_DICT</a> ; otherwise
+  it sets strm-&gt <a href="#adler">adler</a> to the <a href="#adler32">adler32</a> checksum of all output produced
+  so far (that is, <a href="#total_out">total_out</a> bytes) and returns <a href="#Z_OK">Z_OK</a>, <a href="#Z_STREAM_END">Z_STREAM_END</a> or
+  an error code as described below. At the end of the stream, <a href="#inflate">inflate</a>()
+  checks that its computed <a href="#adler32">adler32</a> checksum is equal to that saved by the
+  compressor and returns <a href="#Z_STREAM_END">Z_STREAM_END</a> only if the checksum is correct.
+  <p>
+
+    <a href="#inflate">inflate</a>() returns <a href="#Z_OK">Z_OK</a> if some progress has been made (more input processed
+  or more output produced), <a href="#Z_STREAM_END">Z_STREAM_END</a> if the end of the compressed data has
+  been reached and all uncompressed output has been produced, <a href="#Z_NEED_DICT">Z_NEED_DICT</a> if a
+  preset dictionary is needed at this point, <a href="#Z_DATA_ERROR">Z_DATA_ERROR</a> if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect
+  <a href="#adler32">adler32</a> checksum), <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the stream structure was inconsistent
+  (for example if <a href="#next_in">next_in</a> or <a href="#next_out">next_out</a> was NULL), <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not
+  enough memory, <a href="#Z_BUF_ERROR">Z_BUF_ERROR</a> if no progress is possible or if there was not
+  enough room in the output buffer when <a href="#Z_FINISH">Z_FINISH</a> is used. In the <a href="#Z_DATA_ERROR">Z_DATA_ERROR</a>
+  case, the application may then call <a href="#inflateSync">inflateSync</a> to look for a good
+  compression block.
+  <p>
+
+<font color="Blue"><dt>  int  <a name="inflateEnd">inflateEnd</a> (<a href="#z_streamp">z_streamp</a> strm);</font>
+<dd>
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+   <p>
+
+     <a href="#inflateEnd">inflateEnd</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the stream <a href="#state">state</a>
+   was inconsistent. In the error case, <a href="#msg">msg</a> may be set but then points to a
+   static string (which must not be deallocated).
+</dl>
+<hr>
+<a name="Advanced functions"><h2> Advanced functions </h2>
+    The following functions are needed only in some special applications.
+<h3> Function list </h3>
+<ul>
+<li>  int  <a href="#deflateInit2">deflateInit2</a> (<a href="#z_streamp">z_streamp</a> strm,
+<li> int  <a href="#deflateSetDictionary">deflateSetDictionary</a> (<a href="#z_streamp">z_streamp</a> strm, const Bytef *dictionary, uInt  dictLength);
+<li> int  <a href="#deflateCopy">deflateCopy</a> (<a href="#z_streamp">z_streamp</a> dest, <a href="#z_streamp">z_streamp</a> source);
+<li> int  <a href="#deflateReset">deflateReset</a> (<a href="#z_streamp">z_streamp</a> strm);
+<li> int  <a href="#deflateParams">deflateParams</a> (<a href="#z_streamp">z_streamp</a> strm, int level, int strategy);
+<li> int  <a href="#inflateInit2">inflateInit2</a> (<a href="#z_streamp">z_streamp</a> strm, int  windowBits);
+<li>  int  <a href="#inflateSetDictionary">inflateSetDictionary</a> (<a href="#z_streamp">z_streamp</a> strm, const Bytef *dictionary, uInt  dictLength);
+<li> int  <a href="#inflateSync">inflateSync</a> (<a href="#z_streamp">z_streamp</a> strm);
+<li> int  <a href="#inflateReset">inflateReset</a> (<a href="#z_streamp">z_streamp</a> strm);
+
+</ul>
+<h3> Function description </h3>
+<dl>
+<font color="Blue"><dt>  int  <a name="deflateInit2">deflateInit2</a> (<a href="#z_streamp">z_streamp</a> strm, int  level, int  method, int  windowBits, int  memLevel, int  strategy);</font>
+
+<dd> This is another version of <a href="#deflateInit">deflateInit</a> with more compression options. The
+   fields <a href="#next_in">next_in</a>, <a href="#zalloc">zalloc</a>, <a href="#zfree">zfree</a> and <a href="#opaque">opaque</a> must be initialized before by
+   the caller.<p>
+
+     The method parameter is the compression method. It must be <a href="#Z_DEFLATED">Z_DEFLATED</a> in
+   this version of the library.<p>
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer).  It should be in the range 8..15 for this
+   version of the library. Larger values of this parameter result in better
+   compression at the expense of memory usage. The default value is 15 if
+   <a href="#deflateInit">deflateInit</a> is used instead.<p>
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression <a href="#state">state</a>. memLevel=1 uses minimum memory but
+   is slow and reduces compression ratio ; memLevel=9 uses maximum memory
+   for optimal speed. The default value is 8. See zconf.h for total memory
+   usage as a function of windowBits and memLevel.<p>
+
+     The strategy parameter is used to tune the compression algorithm. Use the
+   value <a href="#Z_DEFAULT_STRATEGY">Z_DEFAULT_STRATEGY</a> for normal data, <a href="#Z_FILTERED">Z_FILTERED</a> for data produced by a
+   filter (or predictor), or <a href="#Z_HUFFMAN_ONLY">Z_HUFFMAN_ONLY</a> to force Huffman encoding only (no
+   string match).  Filtered data consists mostly of small values with a
+   somewhat random distribution. In this case, the compression algorithm is
+   tuned to <a href="#compress">compress</a> them better. The effect of <a href="#Z_FILTERED">Z_FILTERED</a> is to force more
+   Huffman coding and less string matching ; it is somewhat intermediate
+   between Z_DEFAULT and <a href="#Z_HUFFMAN_ONLY">Z_HUFFMAN_ONLY</a>. The strategy parameter only affects
+   the compression ratio but not the correctness of the compressed output even
+   if it is not set appropriately.<p>
+
+      <a href="#deflateInit2">deflateInit2</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not enough
+   memory, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if a parameter is invalid (such as an invalid
+   method). <a href="#msg">msg</a> is set to null if there is no error message.  <a href="#deflateInit2">deflateInit2</a> does
+   not perform any compression: this will be done by <a href="#deflate">deflate</a>().<p>
+
+<font color="Blue"><dt> int  <a name="deflateSetDictionary">deflateSetDictionary</a> (<a href="#z_streamp">z_streamp</a> strm, const Bytef *dictionary, uInt  dictLength);</font>
+<dd>
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output. This function must be called
+   immediately after <a href="#deflateInit">deflateInit</a>, <a href="#deflateInit2">deflateInit2</a> or <a href="#deflateReset">deflateReset</a>, before any
+   call of <a href="#deflate">deflate</a>. The compressor and decompressor must use exactly the same
+   dictionary (see <a href="#inflateSetDictionary">inflateSetDictionary</a>).<p>
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary. Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy ; the data can then be compressed better than
+   with the default empty dictionary.<p>
+
+     Depending on the size of the compression data structures selected by
+   <a href="#deflateInit">deflateInit</a> or <a href="#deflateInit2">deflateInit2</a>, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size in
+   <a href="#deflate">deflate</a> or deflate2. Thus the strings most likely to be useful should be
+   put at the end of the dictionary, not at the front.<p>
+
+     Upon return of this function, strm-&gt <a href="#adler">adler</a> is set to the Adler32 value
+   of the dictionary ; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor. (The Adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.)<p>
+
+     <a href="#deflateSetDictionary">deflateSetDictionary</a> returns <a href="#Z_OK">Z_OK</a> if success, or <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if a
+   parameter is invalid (such as NULL dictionary) or the stream <a href="#state">state</a> is
+   inconsistent (for example if <a href="#deflate">deflate</a> has already been called for this stream
+   or if the compression method is bsort). <a href="#deflateSetDictionary">deflateSetDictionary</a> does not
+   perform any compression: this will be done by <a href="#deflate">deflate</a>().<p>
+
+<font color="Blue"><dt> int  <a name="deflateCopy">deflateCopy</a> (<a href="#z_streamp">z_streamp</a> dest, <a href="#z_streamp">z_streamp</a> source);</font>
+<dd>
+     Sets the destination stream as a complete copy of the source stream.<p>
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter. The streams that will be discarded should then be freed
+   by calling <a href="#deflateEnd">deflateEnd</a>.  Note that <a href="#deflateCopy">deflateCopy</a> duplicates the internal
+   compression <a href="#state">state</a> which can be quite large, so this strategy is slow and
+   can consume lots of memory.<p>
+
+     <a href="#deflateCopy">deflateCopy</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not
+   enough memory, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the source stream <a href="#state">state</a> was inconsistent
+   (such as <a href="#zalloc">zalloc</a> being NULL). <a href="#msg">msg</a> is left unchanged in both source and
+   destination.<p>
+
+<font color="Blue"><dt> int  <a name="deflateReset">deflateReset</a> (<a href="#z_streamp">z_streamp</a> strm);</font>
+<dd>     This function is equivalent to <a href="#deflateEnd">deflateEnd</a> followed by <a href="#deflateInit">deflateInit</a>,
+   but does not free and reallocate all the internal compression <a href="#state">state</a>.
+   The stream will keep the same compression level and any other attributes
+   that may have been set by <a href="#deflateInit2">deflateInit2</a>.<p>
+
+      <a href="#deflateReset">deflateReset</a> returns <a href="#Z_OK">Z_OK</a> if success, or <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the source
+   stream <a href="#state">state</a> was inconsistent (such as <a href="#zalloc">zalloc</a> or <a href="#state">state</a> being NULL).<p>
+
+<font color="Blue"><dt> int  <a name="deflateParams">deflateParams</a> (<a href="#z_streamp">z_streamp</a> strm, int level, int strategy);</font>
+<dd>
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in <a href="#deflateInit2">deflateInit2</a>.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different
+   strategy. If the compression level is changed, the input available so far
+   is compressed with the old level (and may be flushed); the new level will
+   take effect only at the next call of <a href="#deflate">deflate</a>().<p>
+
+     Before the call of <a href="#deflateParams">deflateParams</a>, the stream <a href="#state">state</a> must be set as for
+   a call of <a href="#deflate">deflate</a>(), since the currently available input may have to
+   be compressed and flushed. In particular, strm-&gt <a href="#avail_out">avail_out</a> must be
+   non-zero.<p>
+
+     <a href="#deflateParams">deflateParams</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the source
+   stream <a href="#state">state</a> was inconsistent or if a parameter was invalid, <a href="#Z_BUF_ERROR">Z_BUF_ERROR</a>
+   if strm-&gtavail_out was zero.<p>
+
+<font color="Blue"><dt> int  <a name="inflateInit2">inflateInit2</a> (<a href="#z_streamp">z_streamp</a> strm, int  windowBits);</font>
+
+<dd>     This is another version of <a href="#inflateInit">inflateInit</a> with an extra parameter. The
+   fields <a href="#next_in">next_in</a>, <a href="#avail_in">avail_in</a>, <a href="#zalloc">zalloc</a>, <a href="#zfree">zfree</a> and <a href="#opaque">opaque</a> must be initialized
+   before by the caller.<p>
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library. The default value is 15 if <a href="#inflateInit">inflateInit</a> is used
+   instead. If a compressed stream with a larger window size is given as
+   input, <a href="#inflate">inflate</a>() will return with the error code <a href="#Z_DATA_ERROR">Z_DATA_ERROR</a> instead of
+   trying to allocate a larger window.<p>
+
+      <a href="#inflateInit2">inflateInit2</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not enough
+   memory, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if a parameter is invalid (such as a negative
+   memLevel). <a href="#msg">msg</a> is set to null if there is no error message.  <a href="#inflateInit2">inflateInit2</a>
+   does not perform any decompression apart from reading the zlib header if
+   present: this will be done by <a href="#inflate">inflate</a>(). (So <a href="#next_in">next_in</a> and <a href="#avail_in">avail_in</a> may be
+   modified, but <a href="#next_out">next_out</a> and <a href="#avail_out">avail_out</a> are unchanged.)<p>
+
+<font color="Blue"><dt>  int  <a name="inflateSetDictionary">inflateSetDictionary</a> (<a href="#z_streamp">z_streamp</a> strm, const Bytef *dictionary, uInt  dictLength);</font>
+<dd>
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence. This function must be called immediately after a call of <a href="#inflate">inflate</a>
+   if this call returned <a href="#Z_NEED_DICT">Z_NEED_DICT</a>. The dictionary chosen by the compressor
+   can be determined from the Adler32 value returned by this call of
+   <a href="#inflate">inflate</a>. The compressor and decompressor must use exactly the same
+   dictionary (see <a href="#deflateSetDictionary">deflateSetDictionary</a>).<p>
+
+     <a href="#inflateSetDictionary">inflateSetDictionary</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if a
+   parameter is invalid (such as NULL dictionary) or the stream <a href="#state">state</a> is
+   inconsistent, <a href="#Z_DATA_ERROR">Z_DATA_ERROR</a> if the given dictionary doesn't match the
+   expected one (incorrect Adler32 value). <a href="#inflateSetDictionary">inflateSetDictionary</a> does not
+   perform any decompression: this will be done by subsequent calls of
+   <a href="#inflate">inflate</a>().<p>
+
+<font color="Blue"><dt> int  <a name="inflateSync">inflateSync</a> (<a href="#z_streamp">z_streamp</a> strm);</font>
+
+<dd>    Skips invalid compressed data until a full flush point (see above the
+  description of <a href="#deflate">deflate</a> with <a href="#Z_FULL_FLUSH">Z_FULL_FLUSH</a>) can be found, or until all
+  available input is skipped. No output is provided.<p>
+
+    <a href="#inflateSync">inflateSync</a> returns <a href="#Z_OK">Z_OK</a> if a full flush point has been found, <a href="#Z_BUF_ERROR">Z_BUF_ERROR</a>
+  if no more input was provided, <a href="#Z_DATA_ERROR">Z_DATA_ERROR</a> if no flush point has been found,
+  or <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the stream structure was inconsistent. In the success
+  case, the application may save the current current value of <a href="#total_in">total_in</a> which
+  indicates where valid compressed data was found. In the error case, the
+  application may repeatedly call <a href="#inflateSync">inflateSync</a>, providing more input each time,
+  until success or end of the input data.<p>
+
+<font color="Blue"><dt> int  <a name="inflateReset">inflateReset</a> (<a href="#z_streamp">z_streamp</a> strm);</font>
+<dd>
+     This function is equivalent to <a href="#inflateEnd">inflateEnd</a> followed by <a href="#inflateInit">inflateInit</a>,
+   but does not free and reallocate all the internal decompression <a href="#state">state</a>.
+   The stream will keep attributes that may have been set by <a href="#inflateInit2">inflateInit2</a>.
+   <p>
+
+      <a href="#inflateReset">inflateReset</a> returns <a href="#Z_OK">Z_OK</a> if success, or <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the source
+   stream <a href="#state">state</a> was inconsistent (such as <a href="#zalloc">zalloc</a> or <a href="#state">state</a> being NULL).
+   <p>
+</dl>
+
+<hr>
+<a name="Checksum functions"><h2> Checksum functions </h2>
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the
+   compression library.
+<h3> Function list </h3>
+<ul>
+<li> uLong  <a href="#adler32">adler32</a> (uLong <a href="#adler">adler</a>, const Bytef *buf, uInt len);
+<li> uLong  <a href="#crc32">crc32</a>   (uLong crc, const Bytef *buf, uInt len);
+</ul>
+<h3> Function description </h3>
+<dl>
+<font color="Blue"><dt> uLong  <a name="adler32">adler32</a> (uLong <a href="#adler">adler</a>, const Bytef *buf, uInt len);</font>
+<dd>
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   <p>
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+   <pre>
+
+     uLong <a href="#adler">adler</a> = <a href="#adler32">adler32</a>(0L, <a href="#Z_NULL">Z_NULL</a>, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       <a href="#adler">adler</a> = <a href="#adler32">adler32</a>(<a href="#adler">adler</a>, buffer, length);
+     }
+     if (<a href="#adler">adler</a> != original_adler) error();
+   </pre>
+
+<font color="Blue"><dt> uLong  <a name="crc32">crc32</a>   (uLong crc, const Bytef *buf, uInt len);</font>
+<dd>
+     Update a running crc with the bytes buf[0..len-1] and return the updated
+   crc. If buf is NULL, this function returns the required initial value
+   for the crc. Pre- and post-conditioning (one's complement) is performed
+   within this function so it shouldn't be done by the application.
+   Usage example:
+   <pre>
+
+     uLong crc = <a href="#crc32">crc32</a>(0L, <a href="#Z_NULL">Z_NULL</a>, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = <a href="#crc32">crc32</a>(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+   </pre>
+</dl>
+<hr>
+<a name="struct z_stream_s"><h2> struct z_stream_s </h2>
+<font color="Blue">
+<a name="z_stream_s">
+<pre>
+typedef struct z_stream_s {
+    Bytef    *<a name="next_in">next_in</a>;  /* next input byte */
+    uInt     <a name="avail_in">avail_in</a>;  /* number of bytes available at <a href="#next_in">next_in</a> */
+    uLong    <a name="total_in">total_in</a>;  /* total nb of input bytes read so far */
+
+    Bytef    *<a name="next_out">next_out</a>; /* next output byte should be put there */
+    uInt     <a name="avail_out">avail_out</a>; /* remaining free space at <a href="#next_out">next_out</a> */
+    uLong    <a name="total_out">total_out</a>; /* total nb of bytes output so far */
+
+    char     *<a name="msg">msg</a>;      /* last error message, NULL if no error */
+    struct internal_state FAR *<a name="state">state</a>; /* not visible by applications */
+
+    alloc_func <a name="zalloc">zalloc</a>;  /* used to allocate the internal <a href="#state">state</a> */
+    free_func  <a name="zfree">zfree</a>;   /* used to free the internal <a href="#state">state</a> */
+    voidpf     <a name="opaque">opaque</a>;  /* private data object passed to <a href="#zalloc">zalloc</a> and <a href="#zfree">zfree</a> */
+
+    int     <a name="data_type">data_type</a>;  /* best guess about the data type: ascii or binary */
+    uLong   <a name="adler">adler</a>;      /* <a href="#adler32">adler32</a> value of the uncompressed data */
+    uLong   <a name="reserved">reserved</a>;   /* <a href="#reserved">reserved</a> for future use */
+} <a href="#z_stream_s">z_stream</a> ;
+
+typedef <a href="#z_stream_s">z_stream</a> FAR * <a name="z_streamp">z_streamp</a>;  ÿ
+</pre>
+</font>
+   The application must update <a href="#next_in">next_in</a> and <a href="#avail_in">avail_in</a> when <a href="#avail_in">avail_in</a> has
+   dropped to zero. It must update <a href="#next_out">next_out</a> and <a href="#avail_out">avail_out</a> when <a href="#avail_out">avail_out</a>
+   has dropped to zero. The application must initialize <a href="#zalloc">zalloc</a>, <a href="#zfree">zfree</a> and
+   <a href="#opaque">opaque</a> before calling the init function. All other fields are set by the
+   compression library and must not be updated by the application. <p>
+
+   The <a href="#opaque">opaque</a> value provided by the application will be passed as the first
+   parameter for calls of <a href="#zalloc">zalloc</a> and <a href="#zfree">zfree</a>. This can be useful for custom
+   memory management. The compression library attaches no meaning to the
+   <a href="#opaque">opaque</a> value. <p>
+
+   <a href="#zalloc">zalloc</a> must return <a href="#Z_NULL">Z_NULL</a> if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, <a href="#zalloc">zalloc</a> and <a href="#zfree">zfree</a> must be
+   thread safe. <p>
+
+   On 16-bit systems, the functions <a href="#zalloc">zalloc</a> and <a href="#zfree">zfree</a> must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+   pointers returned by <a href="#zalloc">zalloc</a> for objects of exactly 65536 bytes *must*
+   have their offset normalized to zero. The default allocation function
+   provided by this library ensures this (see zutil.c). To reduce memory
+   requirements and avoid any allocation of 64K objects, at the expense of
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+   <p>
+
+   The fields <a href="#total_in">total_in</a> and <a href="#total_out">total_out</a> can be used for statistics or
+   progress reports. After compression, <a href="#total_in">total_in</a> holds the total size of
+   the uncompressed data and may be saved for use in the decompressor
+   (particularly if the decompressor wants to decompress everything in
+   a single step). <p>
+
+<hr>
+<a name="Constants"><h2> Constants </h2>
+<font color="Blue">
+<pre>
+#define <a name="Z_NO_FLUSH">Z_NO_FLUSH</a>      0
+#define <a name="Z_PARTIAL_FLUSH">Z_PARTIAL_FLUSH</a> 1
+	/* will be removed, use <a href="#Z_SYNC_FLUSH">Z_SYNC_FLUSH</a> instead */
+#define <a name="Z_SYNC_FLUSH">Z_SYNC_FLUSH</a>    2
+#define <a name="Z_FULL_FLUSH">Z_FULL_FLUSH</a>    3
+#define <a name="Z_FINISH">Z_FINISH</a>        4
+/* Allowed flush values ; see <a href="#deflate">deflate</a>() below for details */
+
+#define <a name="Z_OK">Z_OK</a>            0
+#define <a name="Z_STREAM_END">Z_STREAM_END</a>    1
+#define <a name="Z_NEED_DICT">Z_NEED_DICT</a>     2
+#define <a name="Z_ERRNO">Z_ERRNO</a>        (-1)
+#define <a name="Z_STREAM_ERROR">Z_STREAM_ERROR</a> (-2)
+#define <a name="Z_DATA_ERROR">Z_DATA_ERROR</a>   (-3)
+#define <a name="Z_MEM_ERROR">Z_MEM_ERROR</a>    (-4)
+#define <a name="Z_BUF_ERROR">Z_BUF_ERROR</a>    (-5)
+#define <a name="Z_VERSION_ERROR">Z_VERSION_ERROR</a> (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define <a name="Z_NO_COMPRESSION">Z_NO_COMPRESSION</a>         0
+#define <a name="Z_BEST_SPEED">Z_BEST_SPEED</a>             1
+#define <a name="Z_BEST_COMPRESSION">Z_BEST_COMPRESSION</a>       9
+#define <a name="Z_DEFAULT_COMPRESSION">Z_DEFAULT_COMPRESSION</a>  (-1)
+/* compression levels */
+
+#define <a name="Z_FILTERED">Z_FILTERED</a>            1
+#define <a name="Z_HUFFMAN_ONLY">Z_HUFFMAN_ONLY</a>        2
+#define <a name="Z_DEFAULT_STRATEGY">Z_DEFAULT_STRATEGY</a>    0
+/* compression strategy ; see <a href="#deflateInit2">deflateInit2</a>() below for details */
+
+#define <a name="Z_BINARY">Z_BINARY</a>   0
+#define <a name="Z_ASCII">Z_ASCII</a>    1
+#define <a name="Z_UNKNOWN">Z_UNKNOWN</a>  2
+/* Possible values of the <a href="#data_type">data_type</a> field */
+
+#define <a name="Z_DEFLATED">Z_DEFLATED</a>   8
+/* The <a href="#deflate">deflate</a> compression method (the only one supported in this version) */
+
+#define <a name="Z_NULL">Z_NULL</a>  0  /* for initializing <a href="#zalloc">zalloc</a>, <a href="#zfree">zfree</a>, <a href="#opaque">opaque</a> */
+
+#define <a name="zlib_version">zlib_version</a> <a href="#zlibVersion">zlibVersion</a>()
+/* for compatibility with versions less than 1.0.2 */
+</pre>
+</font>
+
+<hr>
+<a name="Misc"><h2> Misc </h2>
+ <a href="#deflateInit">deflateInit</a> and <a href="#inflateInit">inflateInit</a> are macros to allow checking the zlib version
+ and the compiler's view of <a href="#z_stream_s">z_stream</a>.
+ <p>
+ Other functions:
+ <dl>
+ <font color="Blue"><dt> const char   *  <a name="zError">zError</a>           (int err);</font>
+ <font color="Blue"><dt> int             <a name="inflateSyncPoint">inflateSyncPoint</a> (<a href="#z_streamp">z_streamp</a> z);</font>
+ <font color="Blue"><dt> const uLongf *  <a name="get_crc_table">get_crc_table</a>    (void);</font>
+ </dl>
+ <hr>
+ <font size="-1">
+ Last update: Wed Oct 13 20:42:34 1999<br>
+ piapi@csie.ntu.edu.tw
+ </font>
+
+</body>
+</html>
Index: /trunk/minix/lib/zlib-1.2.3/projects/README.projects
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/projects/README.projects	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/projects/README.projects	(revision 9)
@@ -0,0 +1,41 @@
+This directory contains project files for building zlib under various
+Integrated Development Environments (IDE).
+
+If you wish to submit a new project to this directory, you should comply
+to the following requirements.  Otherwise (e.g. if you wish to integrate
+a custom piece of code that changes the zlib interface or its behavior),
+please consider submitting the project to the contrib directory.
+
+
+Requirements
+============
+
+- The project must build zlib using the source files from the official
+  zlib source distribution, exclusively.
+
+- If the project produces redistributable builds (e.g. shared objects
+  or DLL files), these builds must be compatible to those produced by
+  makefiles, if such makefiles exist in the zlib distribution.
+  In particular, if the project produces a DLL build for the Win32
+  platform, this build must comply to the officially-ammended Win32 DLL
+  Application Binary Interface (ABI), described in win32/DLL_FAQ.txt.
+
+- The project may provide additional build targets, which depend on
+  3rd-party (unofficially-supported) software, present in the contrib
+  directory.  For example, it is possible to provide an "ASM build",
+  besides the officially-supported build, and have ASM source files
+  among its dependencies.
+
+- If there are significant differences between the project files created
+  by different versions of an IDE (e.g. Visual C++ 6.0 vs. 7.0), the name
+  of the project directory should contain the version number of the IDE
+  for which the project is intended (e.g. "visualc6" for Visual C++ 6.0,
+  or "visualc7" for Visual C++ 7.0 and 7.1).
+
+
+Current projects
+================
+
+visualc6/   by Simon-Pierre Cadieux <methodex@methodex.ca>
+            and Cosmin Truta <cosmint@cs.ubbcluj.ro>
+        Project for Microsoft Visual C++ 6.0
Index: /trunk/minix/lib/zlib-1.2.3/projects/visualc6/README.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/projects/visualc6/README.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/projects/visualc6/README.txt	(revision 9)
@@ -0,0 +1,73 @@
+Microsoft Developer Studio Project Files, Format Version 6.00 for zlib.
+
+Copyright (C) 2000-2004 Simon-Pierre Cadieux.
+Copyright (C) 2004 Cosmin Truta.
+For conditions of distribution and use, see copyright notice in zlib.h.
+
+
+This project builds the zlib binaries as follows:
+
+* Win32_DLL_Release\zlib1.dll       DLL build
+* Win32_DLL_Debug\zlib1d.dll        DLL build (debug version)
+* Win32_DLL_ASM_Release\zlib1.dll   DLL build using ASM code
+* Win32_DLL_ASM_Debug\zlib1d.dll    DLL build using ASM code (debug version)
+* Win32_LIB_Release\zlib.lib        static build
+* Win32_LIB_Debug\zlibd.lib         static build (debug version)
+* Win32_LIB_ASM_Release\zlib.lib    static build using ASM code
+* Win32_LIB_ASM_Debug\zlibd.lib     static build using ASM code (debug version)
+
+
+For more information regarding the DLL builds, please see the DLL FAQ
+in ..\..\win32\DLL_FAQ.txt.
+
+
+To build and test:
+
+1) On the main menu, select "File | Open Workspace".
+   Open "zlib.dsw".
+
+2) Select "Build | Set Active Configuration".
+   Choose the configuration you wish to build.
+
+3) Select "Build | Clean".
+
+4) Select "Build | Build ... (F7)".  Ignore warning messages about
+   not being able to find certain include files (e.g. alloc.h).
+
+5) If you built one of the sample programs (example or minigzip),
+   select "Build | Execute ... (Ctrl+F5)".
+
+
+To use:
+
+1) Select "Project | Settings (Alt+F7)".
+   Make note of the configuration names used in your project.
+   Usually, these names are "Win32 Release" and "Win32 Debug".
+
+2) In the Workspace window, select the "FileView" tab.
+   Right-click on the root item "Workspace '...'".
+   Select "Insert Project into Workspace".
+   Switch on the checkbox "Dependency of:", and select the name
+   of your project.  Open "zlib.dsp".
+
+3) Select "Build | Configurations".
+   For each configuration of your project:
+   3.1) Choose the zlib configuration you wish to use.
+   3.2) Click on "Add".
+   3.3) Set the new zlib configuration name to the name used by
+        the configuration from the current iteration.
+
+4) Select "Build | Set Active Configuration".
+   Choose the configuration you wish to build.
+
+5) Select "Build | Build ... (F7)".
+
+6) If you built an executable program, select
+   "Build | Execute ... (Ctrl+F5)".
+
+
+Note:
+
+To build the ASM-enabled code, you need Microsoft Assembler
+(ML.EXE).  You can get it by downloading and installing the
+latest Processor Pack for Visual C++ 6.0.
Index: /trunk/minix/lib/zlib-1.2.3/projects/visualc6/example.dsp
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/projects/visualc6/example.dsp	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/projects/visualc6/example.dsp	(revision 9)
@@ -0,0 +1,278 @@
+# Microsoft Developer Studio Project File - Name="example" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=example - Win32 LIB Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "example.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "example.mak" CFG="example - Win32 LIB Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "example - Win32 DLL Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "example - Win32 DLL Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "example - Win32 DLL ASM Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "example - Win32 DLL ASM Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "example - Win32 LIB Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "example - Win32 LIB Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "example - Win32 LIB ASM Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "example - Win32 LIB ASM Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "example - Win32 DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "example___Win32_DLL_Release"
+# PROP BASE Intermediate_Dir "example___Win32_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Win32_DLL_Release"
+# PROP Intermediate_Dir "Win32_DLL_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "example - Win32 DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "example___Win32_DLL_Debug"
+# PROP BASE Intermediate_Dir "example___Win32_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Win32_DLL_Debug"
+# PROP Intermediate_Dir "Win32_DLL_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "example - Win32 DLL ASM Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "example___Win32_DLL_ASM_Release"
+# PROP BASE Intermediate_Dir "example___Win32_DLL_ASM_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Win32_DLL_ASM_Release"
+# PROP Intermediate_Dir "Win32_DLL_ASM_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "example - Win32 DLL ASM Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "example___Win32_DLL_ASM_Debug"
+# PROP BASE Intermediate_Dir "example___Win32_DLL_ASM_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Win32_DLL_ASM_Debug"
+# PROP Intermediate_Dir "Win32_DLL_ASM_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "example - Win32 LIB Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "example___Win32_LIB_Release"
+# PROP BASE Intermediate_Dir "example___Win32_LIB_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Win32_LIB_Release"
+# PROP Intermediate_Dir "Win32_LIB_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "example - Win32 LIB Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "example___Win32_LIB_Debug"
+# PROP BASE Intermediate_Dir "example___Win32_LIB_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Win32_LIB_Debug"
+# PROP Intermediate_Dir "Win32_LIB_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "example - Win32 LIB ASM Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "example___Win32_LIB_ASM_Release"
+# PROP BASE Intermediate_Dir "example___Win32_LIB_ASM_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Win32_LIB_ASM_Release"
+# PROP Intermediate_Dir "Win32_LIB_ASM_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "example - Win32 LIB ASM Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "example___Win32_LIB_ASM_Debug"
+# PROP BASE Intermediate_Dir "example___Win32_LIB_ASM_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Win32_LIB_ASM_Debug"
+# PROP Intermediate_Dir "Win32_LIB_ASM_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "example - Win32 DLL Release"
+# Name "example - Win32 DLL Debug"
+# Name "example - Win32 DLL ASM Release"
+# Name "example - Win32 DLL ASM Debug"
+# Name "example - Win32 LIB Release"
+# Name "example - Win32 LIB Debug"
+# Name "example - Win32 LIB ASM Release"
+# Name "example - Win32 LIB ASM Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\example.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\zconf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zlib.h
+# End Source File
+# End Group
+# End Target
+# End Project
Index: /trunk/minix/lib/zlib-1.2.3/projects/visualc6/minigzip.dsp
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/projects/visualc6/minigzip.dsp	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/projects/visualc6/minigzip.dsp	(revision 9)
@@ -0,0 +1,278 @@
+# Microsoft Developer Studio Project File - Name="minigzip" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=minigzip - Win32 LIB Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "minigzip.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "minigzip.mak" CFG="minigzip - Win32 LIB Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "minigzip - Win32 DLL Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "minigzip - Win32 DLL Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "minigzip - Win32 DLL ASM Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "minigzip - Win32 DLL ASM Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "minigzip - Win32 LIB Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "minigzip - Win32 LIB Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "minigzip - Win32 LIB ASM Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "minigzip - Win32 LIB ASM Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "minigzip - Win32 DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "minigzip___Win32_DLL_Release"
+# PROP BASE Intermediate_Dir "minigzip___Win32_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Win32_DLL_Release"
+# PROP Intermediate_Dir "Win32_DLL_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "minigzip - Win32 DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "minigzip___Win32_DLL_Debug"
+# PROP BASE Intermediate_Dir "minigzip___Win32_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Win32_DLL_Debug"
+# PROP Intermediate_Dir "Win32_DLL_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "minigzip - Win32 DLL ASM Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "minigzip___Win32_DLL_ASM_Release"
+# PROP BASE Intermediate_Dir "minigzip___Win32_DLL_ASM_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Win32_DLL_ASM_Release"
+# PROP Intermediate_Dir "Win32_DLL_ASM_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "minigzip - Win32 DLL ASM Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "minigzip___Win32_DLL_ASM_Debug"
+# PROP BASE Intermediate_Dir "minigzip___Win32_DLL_ASM_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Win32_DLL_ASM_Debug"
+# PROP Intermediate_Dir "Win32_DLL_ASM_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "minigzip - Win32 LIB Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "minigzip___Win32_LIB_Release"
+# PROP BASE Intermediate_Dir "minigzip___Win32_LIB_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Win32_LIB_Release"
+# PROP Intermediate_Dir "Win32_LIB_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "minigzip - Win32 LIB Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "minigzip___Win32_LIB_Debug"
+# PROP BASE Intermediate_Dir "minigzip___Win32_LIB_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Win32_LIB_Debug"
+# PROP Intermediate_Dir "Win32_LIB_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "minigzip - Win32 LIB ASM Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "minigzip___Win32_LIB_ASM_Release"
+# PROP BASE Intermediate_Dir "minigzip___Win32_LIB_ASM_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Win32_LIB_ASM_Release"
+# PROP Intermediate_Dir "Win32_LIB_ASM_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "minigzip - Win32 LIB ASM Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "minigzip___Win32_LIB_ASM_Debug"
+# PROP BASE Intermediate_Dir "minigzip___Win32_LIB_ASM_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Win32_LIB_ASM_Debug"
+# PROP Intermediate_Dir "Win32_LIB_ASM_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "minigzip - Win32 DLL Release"
+# Name "minigzip - Win32 DLL Debug"
+# Name "minigzip - Win32 DLL ASM Release"
+# Name "minigzip - Win32 DLL ASM Debug"
+# Name "minigzip - Win32 LIB Release"
+# Name "minigzip - Win32 LIB Debug"
+# Name "minigzip - Win32 LIB ASM Release"
+# Name "minigzip - Win32 LIB ASM Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\minigzip.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\zconf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zlib.h
+# End Source File
+# End Group
+# End Target
+# End Project
Index: /trunk/minix/lib/zlib-1.2.3/projects/visualc6/zlib.dsp
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/projects/visualc6/zlib.dsp	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/projects/visualc6/zlib.dsp	(revision 9)
@@ -0,0 +1,609 @@
+# Microsoft Developer Studio Project File - Name="zlib" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=zlib - Win32 LIB Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "zlib.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "zlib.mak" CFG="zlib - Win32 LIB Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "zlib - Win32 DLL Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "zlib - Win32 DLL Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "zlib - Win32 DLL ASM Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "zlib - Win32 DLL ASM Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "zlib - Win32 LIB Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "zlib - Win32 LIB Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "zlib - Win32 LIB ASM Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "zlib - Win32 LIB ASM Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF  "$(CFG)" == "zlib - Win32 DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "zlib___Win32_DLL_Release"
+# PROP BASE Intermediate_Dir "zlib___Win32_DLL_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Win32_DLL_Release"
+# PROP Intermediate_Dir "Win32_DLL_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+CPP=cl.exe
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX /Yc /Yu
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT CPP /YX /Yc /Yu
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 /nologo /dll /machine:I386 /out:"Win32_DLL_Release\zlib1.dll"
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "zlib___Win32_DLL_Debug"
+# PROP BASE Intermediate_Dir "zlib___Win32_DLL_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Win32_DLL_Debug"
+# PROP Intermediate_Dir "Win32_DLL_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+CPP=cl.exe
+# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT BASE CPP /YX /Yc /Yu
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT CPP /YX /Yc /Yu
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 /nologo /dll /debug /machine:I386 /out:"Win32_DLL_Debug\zlib1d.dll" /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "zlib___Win32_DLL_ASM_Release"
+# PROP BASE Intermediate_Dir "zlib___Win32_DLL_ASM_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Win32_DLL_ASM_Release"
+# PROP Intermediate_Dir "Win32_DLL_ASM_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+CPP=cl.exe
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX /Yc /Yu
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "ASMV" /D "ASMINF" /FD /c
+# SUBTRACT CPP /YX /Yc /Yu
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 /nologo /dll /machine:I386 /out:"Win32_DLL_ASM_Release\zlib1.dll"
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "zlib___Win32_DLL_ASM_Debug"
+# PROP BASE Intermediate_Dir "zlib___Win32_DLL_ASM_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Win32_DLL_ASM_Debug"
+# PROP Intermediate_Dir "Win32_DLL_ASM_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+CPP=cl.exe
+# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT BASE CPP /YX /Yc /Yu
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "ASMV" /D "ASMINF" /FD /GZ /c
+# SUBTRACT CPP /YX /Yc /Yu
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 /nologo /dll /debug /machine:I386 /out:"Win32_DLL_ASM_Debug\zlib1d.dll" /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "zlib___Win32_LIB_Release"
+# PROP BASE Intermediate_Dir "zlib___Win32_LIB_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Win32_LIB_Release"
+# PROP Intermediate_Dir "Win32_LIB_Release"
+# PROP Target_Dir ""
+CPP=cl.exe
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX /Yc /Yu
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT CPP /YX /Yc /Yu
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "zlib___Win32_LIB_Debug"
+# PROP BASE Intermediate_Dir "zlib___Win32_LIB_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Win32_LIB_Debug"
+# PROP Intermediate_Dir "Win32_LIB_Debug"
+# PROP Target_Dir ""
+CPP=cl.exe
+# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT BASE CPP /YX /Yc /Yu
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT CPP /YX /Yc /Yu
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"Win32_LIB_Debug\zlibd.lib"
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "zlib___Win32_LIB_ASM_Release"
+# PROP BASE Intermediate_Dir "zlib___Win32_LIB_ASM_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Win32_LIB_ASM_Release"
+# PROP Intermediate_Dir "Win32_LIB_ASM_Release"
+# PROP Target_Dir ""
+CPP=cl.exe
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
+# SUBTRACT BASE CPP /YX /Yc /Yu
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "ASMV" /D "ASMINF" /FD /c
+# SUBTRACT CPP /YX /Yc /Yu
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "zlib___Win32_LIB_ASM_Debug"
+# PROP BASE Intermediate_Dir "zlib___Win32_LIB_ASM_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Win32_LIB_ASM_Debug"
+# PROP Intermediate_Dir "Win32_LIB_ASM_Debug"
+# PROP Target_Dir ""
+CPP=cl.exe
+# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
+# SUBTRACT BASE CPP /YX /Yc /Yu
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "ASMV" /D "ASMINF" /FD /GZ /c
+# SUBTRACT CPP /YX /Yc /Yu
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"Win32_LIB_ASM_Debug\zlibd.lib"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "zlib - Win32 DLL Release"
+# Name "zlib - Win32 DLL Debug"
+# Name "zlib - Win32 DLL ASM Release"
+# Name "zlib - Win32 DLL ASM Debug"
+# Name "zlib - Win32 LIB Release"
+# Name "zlib - Win32 LIB Debug"
+# Name "zlib - Win32 LIB ASM Release"
+# Name "zlib - Win32 LIB ASM Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\adler32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\compress.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\crc32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\deflate.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\gzio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\infback.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\inffast.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\inflate.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\inftrees.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\trees.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\uncompr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\win32\zlib.def
+
+!IF  "$(CFG)" == "zlib - Win32 DLL Release"
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 DLL Debug"
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Release"
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Debug"
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Debug"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zutil.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\crc32.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\deflate.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\inffast.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\inffixed.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\inflate.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\inftrees.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\trees.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zconf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zutil.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=..\..\win32\zlib1.rc
+# End Source File
+# End Group
+# Begin Group "Assembler Files (Unsupported)"
+
+# PROP Default_Filter "asm;obj;c;cpp;cxx;h;hpp;hxx"
+# Begin Source File
+
+SOURCE=..\..\contrib\masmx86\gvmat32.asm
+
+!IF  "$(CFG)" == "zlib - Win32 DLL Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 DLL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Release"
+
+# Begin Custom Build - Assembling...
+IntDir=.\Win32_DLL_ASM_Release
+InputPath=..\..\contrib\masmx86\gvmat32.asm
+InputName=gvmat32
+
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	ml.exe /nologo /c /coff /Cx /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Debug"
+
+# Begin Custom Build - Assembling...
+IntDir=.\Win32_DLL_ASM_Debug
+InputPath=..\..\contrib\masmx86\gvmat32.asm
+InputName=gvmat32
+
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Release"
+
+# Begin Custom Build - Assembling...
+IntDir=.\Win32_LIB_ASM_Release
+InputPath=..\..\contrib\masmx86\gvmat32.asm
+InputName=gvmat32
+
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	ml.exe /nologo /c /coff /Cx /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Debug"
+
+# Begin Custom Build - Assembling...
+IntDir=.\Win32_LIB_ASM_Debug
+InputPath=..\..\contrib\masmx86\gvmat32.asm
+InputName=gvmat32
+
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
+
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\contrib\masmx86\gvmat32c.c
+
+!IF  "$(CFG)" == "zlib - Win32 DLL Release"
+
+# PROP Exclude_From_Build 1
+# ADD CPP /I "..\.."
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 DLL Debug"
+
+# PROP Exclude_From_Build 1
+# ADD CPP /I "..\.."
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Release"
+
+# ADD CPP /I "..\.."
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Debug"
+
+# ADD CPP /I "..\.."
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Release"
+
+# PROP Exclude_From_Build 1
+# ADD CPP /I "..\.."
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Debug"
+
+# PROP Exclude_From_Build 1
+# ADD CPP /I "..\.."
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Release"
+
+# ADD CPP /I "..\.."
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Debug"
+
+# ADD CPP /I "..\.."
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\contrib\masmx86\inffas32.asm
+
+!IF  "$(CFG)" == "zlib - Win32 DLL Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 DLL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Release"
+
+# Begin Custom Build - Assembling...
+IntDir=.\Win32_DLL_ASM_Release
+InputPath=..\..\contrib\masmx86\inffas32.asm
+InputName=inffas32
+
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	ml.exe /nologo /c /coff /Cx /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Debug"
+
+# Begin Custom Build - Assembling...
+IntDir=.\Win32_DLL_ASM_Debug
+InputPath=..\..\contrib\masmx86\inffas32.asm
+InputName=inffas32
+
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Release"
+
+# Begin Custom Build - Assembling...
+IntDir=.\Win32_LIB_ASM_Release
+InputPath=..\..\contrib\masmx86\inffas32.asm
+InputName=inffas32
+
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	ml.exe /nologo /c /coff /Cx /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Debug"
+
+# Begin Custom Build - Assembling...
+IntDir=.\Win32_LIB_ASM_Debug
+InputPath=..\..\contrib\masmx86\inffas32.asm
+InputName=inffas32
+
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
+
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\README.txt
+# End Source File
+# End Target
+# End Project
Index: /trunk/minix/lib/zlib-1.2.3/projects/visualc6/zlib.dsw
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/projects/visualc6/zlib.dsw	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/projects/visualc6/zlib.dsw	(revision 9)
@@ -0,0 +1,59 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "example"=.\example.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name zlib
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "minigzip"=.\minigzip.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name zlib
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "zlib"=.\zlib.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
Index: /trunk/minix/lib/zlib-1.2.3/qnx/package.qpg
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/qnx/package.qpg	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/qnx/package.qpg	(revision 9)
@@ -0,0 +1,141 @@
+<QPG:Generation>
+   <QPG:Options>
+      <QPG:User unattended="no" verbosity="2" listfiles="yes"/>
+      <QPG:Defaults type="qnx_package"/>
+      <QPG:Source></QPG:Source>
+      <QPG:Release number="+"/>
+      <QPG:Build></QPG:Build>
+      <QPG:FileSorting strip="yes"/>
+      <QPG:Package targets="combine"/>
+      <QPG:Repository generate="yes"/>
+      <QPG:FinalDir></QPG:FinalDir>
+      <QPG:Cleanup></QPG:Cleanup>
+   </QPG:Options>
+
+   <QPG:Responsible>
+      <QPG:Company></QPG:Company>
+      <QPG:Department></QPG:Department>
+      <QPG:Group></QPG:Group>
+      <QPG:Team></QPG:Team>
+      <QPG:Employee></QPG:Employee>
+      <QPG:EmailAddress></QPG:EmailAddress>
+   </QPG:Responsible>
+
+   <QPG:Values>
+      <QPG:Files>
+         <QPG:Add file="../zconf.h" install="/opt/include/" user="root:sys" permission="644"/>
+         <QPG:Add file="../zlib.h" install="/opt/include/" user="root:sys" permission="644"/>
+         <QPG:Add file="../libz.so.1.2.3" install="/opt/lib/" user="root:bin" permission="644"/>
+         <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.3"/>
+         <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.3"/>
+         <QPG:Add file="../libz.so.1.2.3" install="/opt/lib/" component="slib"/>
+      </QPG:Files>
+
+      <QPG:PackageFilter>
+         <QPM:PackageManifest>
+            <QPM:PackageDescription>
+               <QPM:PackageType>Library</QPM:PackageType>
+               <QPM:PackageReleaseNotes></QPM:PackageReleaseNotes>
+               <QPM:PackageReleaseUrgency>Medium</QPM:PackageReleaseUrgency>
+               <QPM:PackageRepository></QPM:PackageRepository>
+               <QPM:FileVersion>2.0</QPM:FileVersion>
+            </QPM:PackageDescription>
+
+            <QPM:ProductDescription>
+               <QPM:ProductName>zlib</QPM:ProductName>
+               <QPM:ProductIdentifier>zlib</QPM:ProductIdentifier>
+               <QPM:ProductEmail>alain.bonnefoy@icbt.com</QPM:ProductEmail>
+               <QPM:VendorName>Public</QPM:VendorName>
+               <QPM:VendorInstallName>public</QPM:VendorInstallName>
+               <QPM:VendorURL>www.gzip.org/zlib</QPM:VendorURL>
+               <QPM:VendorEmbedURL></QPM:VendorEmbedURL>
+               <QPM:VendorEmail></QPM:VendorEmail>
+               <QPM:AuthorName>Jean-Loup Gailly,Mark Adler</QPM:AuthorName>
+               <QPM:AuthorURL>www.gzip.org/zlib</QPM:AuthorURL>
+               <QPM:AuthorEmbedURL></QPM:AuthorEmbedURL>
+               <QPM:AuthorEmail>zlib@gzip.org</QPM:AuthorEmail>
+               <QPM:ProductIconSmall></QPM:ProductIconSmall>
+               <QPM:ProductIconLarge></QPM:ProductIconLarge>
+               <QPM:ProductDescriptionShort>A massively spiffy yet delicately unobtrusive compression library.</QPM:ProductDescriptionShort>
+               <QPM:ProductDescriptionLong>zlib is designed to be a free, general-purpose, legally unencumbered, lossless data compression library for use on virtually any computer hardware and operating system.</QPM:ProductDescriptionLong>
+               <QPM:ProductDescriptionURL>http://www.gzip.org/zlib</QPM:ProductDescriptionURL>
+               <QPM:ProductDescriptionEmbedURL></QPM:ProductDescriptionEmbedURL>
+            </QPM:ProductDescription>
+
+            <QPM:ReleaseDescription>
+               <QPM:ReleaseVersion>1.2.3</QPM:ReleaseVersion>
+               <QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency>
+               <QPM:ReleaseStability>Stable</QPM:ReleaseStability>
+               <QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor>
+               <QPM:ReleaseNoteMajor></QPM:ReleaseNoteMajor>
+               <QPM:ExcludeCountries>
+                  <QPM:Country></QPM:Country>
+               </QPM:ExcludeCountries>
+
+               <QPM:ReleaseCopyright>No License</QPM:ReleaseCopyright>
+            </QPM:ReleaseDescription>
+
+            <QPM:ContentDescription>
+               <QPM:ContentTopic xmlmultiple="true">Software Development/Libraries and Extensions/C Libraries</QPM:ContentTopic>
+               <QPM:ContentKeyword>zlib,compression</QPM:ContentKeyword>
+               <QPM:TargetOS>qnx6</QPM:TargetOS>
+               <QPM:HostOS>qnx6</QPM:HostOS>
+               <QPM:DisplayEnvironment xmlmultiple="true">None</QPM:DisplayEnvironment>
+               <QPM:TargetAudience xmlmultiple="true">Developer</QPM:TargetAudience>
+            </QPM:ContentDescription>
+         </QPM:PackageManifest>
+      </QPG:PackageFilter>
+
+      <QPG:PackageFilter proc="none" target="none">
+         <QPM:PackageManifest>
+            <QPM:ProductInstallationDependencies>
+               <QPM:ProductRequirements></QPM:ProductRequirements>
+            </QPM:ProductInstallationDependencies>
+
+            <QPM:ProductInstallationProcedure>
+               <QPM:Script xmlmultiple="true">
+                  <QPM:ScriptName></QPM:ScriptName>
+                  <QPM:ScriptType>Install</QPM:ScriptType>
+                  <QPM:ScriptTiming>Post</QPM:ScriptTiming>
+                  <QPM:ScriptBlocking>No</QPM:ScriptBlocking>
+                  <QPM:ScriptResult>Ignore</QPM:ScriptResult>
+                  <QPM:ShortDescription></QPM:ShortDescription>
+                  <QPM:UseBinaries>No</QPM:UseBinaries>
+                  <QPM:Priority>Optional</QPM:Priority>
+               </QPM:Script>
+            </QPM:ProductInstallationProcedure>
+         </QPM:PackageManifest>
+
+         <QPM:Launch>
+         </QPM:Launch>
+      </QPG:PackageFilter>
+
+      <QPG:PackageFilter type="core" component="none">
+         <QPM:PackageManifest>
+            <QPM:ProductInstallationProcedure>
+	       <QPM:OrderDependency xmlmultiple="true">
+	          <QPM:Order>InstallOver</QPM:Order>
+	          <QPM:Product>zlib</QPM:Product>
+	       </QPM:OrderDependency>
+            </QPM:ProductInstallationProcedure>
+         </QPM:PackageManifest>
+
+         <QPM:Launch>
+         </QPM:Launch>
+      </QPG:PackageFilter>
+
+      <QPG:PackageFilter type="core" component="dev">
+         <QPM:PackageManifest>
+            <QPM:ProductInstallationProcedure>
+	       <QPM:OrderDependency xmlmultiple="true">
+	          <QPM:Order>InstallOver</QPM:Order>
+	          <QPM:Product>zlib-dev</QPM:Product>
+	       </QPM:OrderDependency>
+            </QPM:ProductInstallationProcedure>
+         </QPM:PackageManifest>
+
+         <QPM:Launch>
+         </QPM:Launch>
+      </QPG:PackageFilter>
+   </QPG:Values>
+</QPG:Generation>
Index: /trunk/minix/lib/zlib-1.2.3/trees.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/trees.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/trees.c	(revision 9)
@@ -0,0 +1,1219 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-2005 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process uses several Huffman trees. The more
+ *      common source values are represented by shorter bit sequences.
+ *
+ *      Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values).  The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ *      Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ *      Storer, James A.
+ *          Data Compression:  Methods and Theory, pp. 49-50.
+ *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
+ *
+ *      Sedgewick, R.
+ *          Algorithms, p290.
+ *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id: trees.c,v 1.1 2005/09/23 22:39:00 beng Exp $ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef DEBUG
+#  include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6      16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10    17
+/* repeat a zero length 3-10 times  (3 bits of repeat count) */
+
+#define REPZ_11_138  18
+/* repeat a zero length 11-138 times  (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN  512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+#  include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+    const ct_data *static_tree;  /* static tree or NULL */
+    const intf *extra_bits;      /* extra bits for each code or NULL */
+    int     extra_base;          /* base index for extra_bits */
+    int     elems;               /* max number of elements in the tree */
+    int     max_length;          /* max bit length for the codes */
+};
+
+local static_tree_desc  static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local static_tree_desc  static_d_desc =
+{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};
+
+local static_tree_desc  static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block     OF((deflate_state *s));
+local void pqdownheap     OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen     OF((deflate_state *s, tree_desc *desc));
+local void gen_codes      OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree     OF((deflate_state *s, tree_desc *desc));
+local void scan_tree      OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));
+local int  build_bl_tree  OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+                              int blcodes));
+local void compress_block OF((deflate_state *s, ct_data *ltree,
+                              ct_data *dtree));
+local void set_data_type  OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup      OF((deflate_state *s));
+local void bi_flush       OF((deflate_state *s));
+local void copy_block     OF((deflate_state *s, charf *buf, unsigned len,
+                              int header));
+
+#ifdef GEN_TREES_H
+local void gen_trees_header OF((void));
+#endif
+
+#ifndef DEBUG
+#  define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+   /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+#  define send_code(s, c, tree) \
+     { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+       send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+    put_byte(s, (uch)((w) & 0xff)); \
+    put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG
+local void send_bits      OF((deflate_state *s, int value, int length));
+
+local void send_bits(s, value, length)
+    deflate_state *s;
+    int value;  /* value to send */
+    int length; /* number of bits */
+{
+    Tracevv((stderr," l %2d v %4x ", length, value));
+    Assert(length > 0 && length <= 15, "invalid length");
+    s->bits_sent += (ulg)length;
+
+    /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+     * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+     * unused bits in value.
+     */
+    if (s->bi_valid > (int)Buf_size - length) {
+        s->bi_buf |= (value << s->bi_valid);
+        put_short(s, s->bi_buf);
+        s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+        s->bi_valid += length - Buf_size;
+    } else {
+        s->bi_buf |= value << s->bi_valid;
+        s->bi_valid += length;
+    }
+}
+#else /* !DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+  if (s->bi_valid > (int)Buf_size - len) {\
+    int val = value;\
+    s->bi_buf |= (val << s->bi_valid);\
+    put_short(s, s->bi_buf);\
+    s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+    s->bi_valid += len - Buf_size;\
+  } else {\
+    s->bi_buf |= (value) << s->bi_valid;\
+    s->bi_valid += len;\
+  }\
+}
+#endif /* DEBUG */
+
+
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init()
+{
+#if defined(GEN_TREES_H) || !defined(STDC)
+    static int static_init_done = 0;
+    int n;        /* iterates over tree elements */
+    int bits;     /* bit counter */
+    int length;   /* length value */
+    int code;     /* code value */
+    int dist;     /* distance index */
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    if (static_init_done) return;
+
+    /* For some embedded targets, global variables are not initialized: */
+    static_l_desc.static_tree = static_ltree;
+    static_l_desc.extra_bits = extra_lbits;
+    static_d_desc.static_tree = static_dtree;
+    static_d_desc.extra_bits = extra_dbits;
+    static_bl_desc.extra_bits = extra_blbits;
+
+    /* Initialize the mapping length (0..255) -> length code (0..28) */
+    length = 0;
+    for (code = 0; code < LENGTH_CODES-1; code++) {
+        base_length[code] = length;
+        for (n = 0; n < (1<<extra_lbits[code]); n++) {
+            _length_code[length++] = (uch)code;
+        }
+    }
+    Assert (length == 256, "tr_static_init: length != 256");
+    /* Note that the length 255 (match length 258) can be represented
+     * in two different ways: code 284 + 5 bits or code 285, so we
+     * overwrite length_code[255] to use the best encoding:
+     */
+    _length_code[length-1] = (uch)code;
+
+    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+    dist = 0;
+    for (code = 0 ; code < 16; code++) {
+        base_dist[code] = dist;
+        for (n = 0; n < (1<<extra_dbits[code]); n++) {
+            _dist_code[dist++] = (uch)code;
+        }
+    }
+    Assert (dist == 256, "tr_static_init: dist != 256");
+    dist >>= 7; /* from now on, all distances are divided by 128 */
+    for ( ; code < D_CODES; code++) {
+        base_dist[code] = dist << 7;
+        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+            _dist_code[256 + dist++] = (uch)code;
+        }
+    }
+    Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+    /* Construct the codes of the static literal tree */
+    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+    n = 0;
+    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+    /* Codes 286 and 287 do not exist, but we must include them in the
+     * tree construction to get a canonical Huffman tree (longest code
+     * all ones)
+     */
+    gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+    /* The static distance tree is trivial: */
+    for (n = 0; n < D_CODES; n++) {
+        static_dtree[n].Len = 5;
+        static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+    }
+    static_init_done = 1;
+
+#  ifdef GEN_TREES_H
+    gen_trees_header();
+#  endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Genererate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+#  ifndef DEBUG
+#    include <stdio.h>
+#  endif
+
+#  define SEPARATOR(i, last, width) \
+      ((i) == (last)? "\n};\n\n" :    \
+       ((i) % (width) == (width)-1 ? ",\n" : ", "))
+
+void gen_trees_header()
+{
+    FILE *header = fopen("trees.h", "w");
+    int i;
+
+    Assert (header != NULL, "Can't open trees.h");
+    fprintf(header,
+            "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+    fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+    for (i = 0; i < L_CODES+2; i++) {
+        fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+                static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+    }
+
+    fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+    for (i = 0; i < D_CODES; i++) {
+        fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+                static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+    }
+
+    fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n");
+    for (i = 0; i < DIST_CODE_LEN; i++) {
+        fprintf(header, "%2u%s", _dist_code[i],
+                SEPARATOR(i, DIST_CODE_LEN-1, 20));
+    }
+
+    fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+    for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+        fprintf(header, "%2u%s", _length_code[i],
+                SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+    }
+
+    fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+    for (i = 0; i < LENGTH_CODES; i++) {
+        fprintf(header, "%1u%s", base_length[i],
+                SEPARATOR(i, LENGTH_CODES-1, 20));
+    }
+
+    fprintf(header, "local const int base_dist[D_CODES] = {\n");
+    for (i = 0; i < D_CODES; i++) {
+        fprintf(header, "%5u%s", base_dist[i],
+                SEPARATOR(i, D_CODES-1, 10));
+    }
+
+    fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void _tr_init(s)
+    deflate_state *s;
+{
+    tr_static_init();
+
+    s->l_desc.dyn_tree = s->dyn_ltree;
+    s->l_desc.stat_desc = &static_l_desc;
+
+    s->d_desc.dyn_tree = s->dyn_dtree;
+    s->d_desc.stat_desc = &static_d_desc;
+
+    s->bl_desc.dyn_tree = s->bl_tree;
+    s->bl_desc.stat_desc = &static_bl_desc;
+
+    s->bi_buf = 0;
+    s->bi_valid = 0;
+    s->last_eob_len = 8; /* enough lookahead for inflate */
+#ifdef DEBUG
+    s->compressed_len = 0L;
+    s->bits_sent = 0L;
+#endif
+
+    /* Initialize the first block of the first file: */
+    init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(s)
+    deflate_state *s;
+{
+    int n; /* iterates over tree elements */
+
+    /* Initialize the trees. */
+    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;
+    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;
+    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+    s->dyn_ltree[END_BLOCK].Freq = 1;
+    s->opt_len = s->static_len = 0L;
+    s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+    top = s->heap[SMALLEST]; \
+    s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+    pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+   (tree[n].Freq < tree[m].Freq || \
+   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(s, tree, k)
+    deflate_state *s;
+    ct_data *tree;  /* the tree to restore */
+    int k;               /* node to move down */
+{
+    int v = s->heap[k];
+    int j = k << 1;  /* left son of k */
+    while (j <= s->heap_len) {
+        /* Set j to the smallest of the two sons: */
+        if (j < s->heap_len &&
+            smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+            j++;
+        }
+        /* Exit if v is smaller than both sons */
+        if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+        /* Exchange v with the smallest son */
+        s->heap[k] = s->heap[j];  k = j;
+
+        /* And continue down the tree, setting j to the left son of k */
+        j <<= 1;
+    }
+    s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ *    above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ *     array bl_count contains the frequencies for each bit length.
+ *     The length opt_len is updated; static_len is also updated if stree is
+ *     not null.
+ */
+local void gen_bitlen(s, desc)
+    deflate_state *s;
+    tree_desc *desc;    /* the tree descriptor */
+{
+    ct_data *tree        = desc->dyn_tree;
+    int max_code         = desc->max_code;
+    const ct_data *stree = desc->stat_desc->static_tree;
+    const intf *extra    = desc->stat_desc->extra_bits;
+    int base             = desc->stat_desc->extra_base;
+    int max_length       = desc->stat_desc->max_length;
+    int h;              /* heap index */
+    int n, m;           /* iterate over the tree elements */
+    int bits;           /* bit length */
+    int xbits;          /* extra bits */
+    ush f;              /* frequency */
+    int overflow = 0;   /* number of elements with bit length too large */
+
+    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+    /* In a first pass, compute the optimal bit lengths (which may
+     * overflow in the case of the bit length tree).
+     */
+    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+        n = s->heap[h];
+        bits = tree[tree[n].Dad].Len + 1;
+        if (bits > max_length) bits = max_length, overflow++;
+        tree[n].Len = (ush)bits;
+        /* We overwrite tree[n].Dad which is no longer needed */
+
+        if (n > max_code) continue; /* not a leaf node */
+
+        s->bl_count[bits]++;
+        xbits = 0;
+        if (n >= base) xbits = extra[n-base];
+        f = tree[n].Freq;
+        s->opt_len += (ulg)f * (bits + xbits);
+        if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+    }
+    if (overflow == 0) return;
+
+    Trace((stderr,"\nbit length overflow\n"));
+    /* This happens for example on obj2 and pic of the Calgary corpus */
+
+    /* Find the first bit length which could increase: */
+    do {
+        bits = max_length-1;
+        while (s->bl_count[bits] == 0) bits--;
+        s->bl_count[bits]--;      /* move one leaf down the tree */
+        s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+        s->bl_count[max_length]--;
+        /* The brother of the overflow item also moves one step up,
+         * but this does not affect bl_count[max_length]
+         */
+        overflow -= 2;
+    } while (overflow > 0);
+
+    /* Now recompute all bit lengths, scanning in increasing frequency.
+     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+     * lengths instead of fixing only the wrong ones. This idea is taken
+     * from 'ar' written by Haruhiko Okumura.)
+     */
+    for (bits = max_length; bits != 0; bits--) {
+        n = s->bl_count[bits];
+        while (n != 0) {
+            m = s->heap[--h];
+            if (m > max_code) continue;
+            if ((unsigned) tree[m].Len != (unsigned) bits) {
+                Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+                s->opt_len += ((long)bits - (long)tree[m].Len)
+                              *(long)tree[m].Freq;
+                tree[m].Len = (ush)bits;
+            }
+            n--;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ *     zero code length.
+ */
+local void gen_codes (tree, max_code, bl_count)
+    ct_data *tree;             /* the tree to decorate */
+    int max_code;              /* largest code with non zero frequency */
+    ushf *bl_count;            /* number of codes at each bit length */
+{
+    ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+    ush code = 0;              /* running code value */
+    int bits;                  /* bit index */
+    int n;                     /* code index */
+
+    /* The distribution counts are first used to generate the code values
+     * without bit reversal.
+     */
+    for (bits = 1; bits <= MAX_BITS; bits++) {
+        next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+    }
+    /* Check that the bit counts in bl_count are consistent. The last code
+     * must be all ones.
+     */
+    Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+            "inconsistent bit counts");
+    Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+    for (n = 0;  n <= max_code; n++) {
+        int len = tree[n].Len;
+        if (len == 0) continue;
+        /* Now reverse the bits */
+        tree[n].Code = bi_reverse(next_code[len]++, len);
+
+        Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+    }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ *     and corresponding code. The length opt_len is updated; static_len is
+ *     also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(s, desc)
+    deflate_state *s;
+    tree_desc *desc; /* the tree descriptor */
+{
+    ct_data *tree         = desc->dyn_tree;
+    const ct_data *stree  = desc->stat_desc->static_tree;
+    int elems             = desc->stat_desc->elems;
+    int n, m;          /* iterate over heap elements */
+    int max_code = -1; /* largest code with non zero frequency */
+    int node;          /* new node being created */
+
+    /* Construct the initial heap, with least frequent element in
+     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+     * heap[0] is not used.
+     */
+    s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+    for (n = 0; n < elems; n++) {
+        if (tree[n].Freq != 0) {
+            s->heap[++(s->heap_len)] = max_code = n;
+            s->depth[n] = 0;
+        } else {
+            tree[n].Len = 0;
+        }
+    }
+
+    /* The pkzip format requires that at least one distance code exists,
+     * and that at least one bit should be sent even if there is only one
+     * possible code. So to avoid special checks later on we force at least
+     * two codes of non zero frequency.
+     */
+    while (s->heap_len < 2) {
+        node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+        tree[node].Freq = 1;
+        s->depth[node] = 0;
+        s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+        /* node is 0 or 1 so it does not have extra bits */
+    }
+    desc->max_code = max_code;
+
+    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+     * establish sub-heaps of increasing lengths:
+     */
+    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+    /* Construct the Huffman tree by repeatedly combining the least two
+     * frequent nodes.
+     */
+    node = elems;              /* next internal node of the tree */
+    do {
+        pqremove(s, tree, n);  /* n = node of least frequency */
+        m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+        s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+        s->heap[--(s->heap_max)] = m;
+
+        /* Create a new node father of n and m */
+        tree[node].Freq = tree[n].Freq + tree[m].Freq;
+        s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
+                                s->depth[n] : s->depth[m]) + 1);
+        tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+        if (tree == s->bl_tree) {
+            fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+        }
+#endif
+        /* and insert the new node in the heap */
+        s->heap[SMALLEST] = node++;
+        pqdownheap(s, tree, SMALLEST);
+
+    } while (s->heap_len >= 2);
+
+    s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+    /* At this point, the fields freq and dad are set. We can now
+     * generate the bit lengths.
+     */
+    gen_bitlen(s, (tree_desc *)desc);
+
+    /* The field len is now set, we can generate the bit codes */
+    gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (s, tree, max_code)
+    deflate_state *s;
+    ct_data *tree;   /* the tree to be scanned */
+    int max_code;    /* and its largest code of non zero frequency */
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    if (nextlen == 0) max_count = 138, min_count = 3;
+    tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            s->bl_tree[curlen].Freq += count;
+        } else if (curlen != 0) {
+            if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+            s->bl_tree[REP_3_6].Freq++;
+        } else if (count <= 10) {
+            s->bl_tree[REPZ_3_10].Freq++;
+        } else {
+            s->bl_tree[REPZ_11_138].Freq++;
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (s, tree, max_code)
+    deflate_state *s;
+    ct_data *tree; /* the tree to be scanned */
+    int max_code;       /* and its largest code of non zero frequency */
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    /* tree[max_code+1].Len = -1; */  /* guard already set */
+    if (nextlen == 0) max_count = 138, min_count = 3;
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+        } else if (curlen != 0) {
+            if (curlen != prevlen) {
+                send_code(s, curlen, s->bl_tree); count--;
+            }
+            Assert(count >= 3 && count <= 6, " 3_6?");
+            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+        } else if (count <= 10) {
+            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+        } else {
+            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(s)
+    deflate_state *s;
+{
+    int max_blindex;  /* index of last bit length code of non zero freq */
+
+    /* Determine the bit length frequencies for literal and distance trees */
+    scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+    scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+    /* Build the bit length tree: */
+    build_tree(s, (tree_desc *)(&(s->bl_desc)));
+    /* opt_len now includes the length of the tree representations, except
+     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+     */
+
+    /* Determine the number of bit length codes to send. The pkzip format
+     * requires that at least 4 bit length codes be sent. (appnote.txt says
+     * 3 but the actual value used is 4.)
+     */
+    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+        if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+    }
+    /* Update opt_len to include the bit length tree and counts */
+    s->opt_len += 3*(max_blindex+1) + 5+5+4;
+    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+            s->opt_len, s->static_len));
+
+    return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(s, lcodes, dcodes, blcodes)
+    deflate_state *s;
+    int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+    int rank;                    /* index in bl_order */
+
+    Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+    Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+            "too many codes");
+    Tracev((stderr, "\nbl counts: "));
+    send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+    send_bits(s, dcodes-1,   5);
+    send_bits(s, blcodes-4,  4); /* not -3 as stated in appnote.txt */
+    for (rank = 0; rank < blcodes; rank++) {
+        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+    }
+    Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+    send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+    send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+    Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void _tr_stored_block(s, buf, stored_len, eof)
+    deflate_state *s;
+    charf *buf;       /* input block */
+    ulg stored_len;   /* length of input block */
+    int eof;          /* true if this is the last block for a file */
+{
+    send_bits(s, (STORED_BLOCK<<1)+eof, 3);  /* send block type */
+#ifdef DEBUG
+    s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+    s->compressed_len += (stored_len + 4) << 3;
+#endif
+    copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ * The current inflate code requires 9 bits of lookahead. If the
+ * last two codes for the previous block (real code plus EOB) were coded
+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ * the last real code. In this case we send two empty static blocks instead
+ * of one. (There are no problems if the previous block is stored or fixed.)
+ * To simplify the code, we assume the worst case of last real code encoded
+ * on one bit only.
+ */
+void _tr_align(s)
+    deflate_state *s;
+{
+    send_bits(s, STATIC_TREES<<1, 3);
+    send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+    s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+    bi_flush(s);
+    /* Of the 10 bits for the empty block, we have already sent
+     * (10 - bi_valid) bits. The lookahead for the last real code (before
+     * the EOB of the previous block) was thus at least one plus the length
+     * of the EOB plus what we have just sent of the empty static block.
+     */
+    if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
+        send_bits(s, STATIC_TREES<<1, 3);
+        send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+        s->compressed_len += 10L;
+#endif
+        bi_flush(s);
+    }
+    s->last_eob_len = 7;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file.
+ */
+void _tr_flush_block(s, buf, stored_len, eof)
+    deflate_state *s;
+    charf *buf;       /* input block, or NULL if too old */
+    ulg stored_len;   /* length of input block */
+    int eof;          /* true if this is the last block for a file */
+{
+    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+    int max_blindex = 0;  /* index of last bit length code of non zero freq */
+
+    /* Build the Huffman trees unless a stored block is forced */
+    if (s->level > 0) {
+
+        /* Check if the file is binary or text */
+        if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN)
+            set_data_type(s);
+
+        /* Construct the literal and distance trees */
+        build_tree(s, (tree_desc *)(&(s->l_desc)));
+        Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+                s->static_len));
+
+        build_tree(s, (tree_desc *)(&(s->d_desc)));
+        Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+                s->static_len));
+        /* At this point, opt_len and static_len are the total bit lengths of
+         * the compressed block data, excluding the tree representations.
+         */
+
+        /* Build the bit length tree for the above two trees, and get the index
+         * in bl_order of the last bit length code to send.
+         */
+        max_blindex = build_bl_tree(s);
+
+        /* Determine the best encoding. Compute the block lengths in bytes. */
+        opt_lenb = (s->opt_len+3+7)>>3;
+        static_lenb = (s->static_len+3+7)>>3;
+
+        Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+                opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+                s->last_lit));
+
+        if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+    } else {
+        Assert(buf != (char*)0, "lost buf");
+        opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+    }
+
+#ifdef FORCE_STORED
+    if (buf != (char*)0) { /* force stored block */
+#else
+    if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+                       /* 4: two words for the lengths */
+#endif
+        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+         * Otherwise we can't have processed more than WSIZE input bytes since
+         * the last block flush, because compression would have been
+         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+         * transform a block into a stored block.
+         */
+        _tr_stored_block(s, buf, stored_len, eof);
+
+#ifdef FORCE_STATIC
+    } else if (static_lenb >= 0) { /* force static trees */
+#else
+    } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
+#endif
+        send_bits(s, (STATIC_TREES<<1)+eof, 3);
+        compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+#ifdef DEBUG
+        s->compressed_len += 3 + s->static_len;
+#endif
+    } else {
+        send_bits(s, (DYN_TREES<<1)+eof, 3);
+        send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+                       max_blindex+1);
+        compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+#ifdef DEBUG
+        s->compressed_len += 3 + s->opt_len;
+#endif
+    }
+    Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+    /* The above check is made mod 2^32, for files larger than 512 MB
+     * and uLong implemented on 32 bits.
+     */
+    init_block(s);
+
+    if (eof) {
+        bi_windup(s);
+#ifdef DEBUG
+        s->compressed_len += 7;  /* align on byte boundary */
+#endif
+    }
+    Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+           s->compressed_len-7*eof));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int _tr_tally (s, dist, lc)
+    deflate_state *s;
+    unsigned dist;  /* distance of matched string */
+    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+    s->d_buf[s->last_lit] = (ush)dist;
+    s->l_buf[s->last_lit++] = (uch)lc;
+    if (dist == 0) {
+        /* lc is the unmatched char */
+        s->dyn_ltree[lc].Freq++;
+    } else {
+        s->matches++;
+        /* Here, lc is the match length - MIN_MATCH */
+        dist--;             /* dist = match distance - 1 */
+        Assert((ush)dist < (ush)MAX_DIST(s) &&
+               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+               (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");
+
+        s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
+        s->dyn_dtree[d_code(dist)].Freq++;
+    }
+
+#ifdef TRUNCATE_BLOCK
+    /* Try to guess if it is profitable to stop the current block here */
+    if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
+        /* Compute an upper bound for the compressed length */
+        ulg out_length = (ulg)s->last_lit*8L;
+        ulg in_length = (ulg)((long)s->strstart - s->block_start);
+        int dcode;
+        for (dcode = 0; dcode < D_CODES; dcode++) {
+            out_length += (ulg)s->dyn_dtree[dcode].Freq *
+                (5L+extra_dbits[dcode]);
+        }
+        out_length >>= 3;
+        Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+               s->last_lit, in_length, out_length,
+               100L - out_length*100L/in_length));
+        if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+    }
+#endif
+    return (s->last_lit == s->lit_bufsize-1);
+    /* We avoid equality with lit_bufsize because of wraparound at 64K
+     * on 16 bit machines and because stored blocks are restricted to
+     * 64K-1 bytes.
+     */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(s, ltree, dtree)
+    deflate_state *s;
+    ct_data *ltree; /* literal tree */
+    ct_data *dtree; /* distance tree */
+{
+    unsigned dist;      /* distance of matched string */
+    int lc;             /* match length or unmatched char (if dist == 0) */
+    unsigned lx = 0;    /* running index in l_buf */
+    unsigned code;      /* the code to send */
+    int extra;          /* number of extra bits to send */
+
+    if (s->last_lit != 0) do {
+        dist = s->d_buf[lx];
+        lc = s->l_buf[lx++];
+        if (dist == 0) {
+            send_code(s, lc, ltree); /* send a literal byte */
+            Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+        } else {
+            /* Here, lc is the match length - MIN_MATCH */
+            code = _length_code[lc];
+            send_code(s, code+LITERALS+1, ltree); /* send the length code */
+            extra = extra_lbits[code];
+            if (extra != 0) {
+                lc -= base_length[code];
+                send_bits(s, lc, extra);       /* send the extra length bits */
+            }
+            dist--; /* dist is now the match distance - 1 */
+            code = d_code(dist);
+            Assert (code < D_CODES, "bad d_code");
+
+            send_code(s, code, dtree);       /* send the distance code */
+            extra = extra_dbits[code];
+            if (extra != 0) {
+                dist -= base_dist[code];
+                send_bits(s, dist, extra);   /* send the extra distance bits */
+            }
+        } /* literal or match pair ? */
+
+        /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+        Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
+               "pendingBuf overflow");
+
+    } while (lx < s->last_lit);
+
+    send_code(s, END_BLOCK, ltree);
+    s->last_eob_len = ltree[END_BLOCK].Len;
+}
+
+/* ===========================================================================
+ * Set the data type to BINARY or TEXT, using a crude approximation:
+ * set it to Z_TEXT if all symbols are either printable characters (33 to 255)
+ * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise.
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+local void set_data_type(s)
+    deflate_state *s;
+{
+    int n;
+
+    for (n = 0; n < 9; n++)
+        if (s->dyn_ltree[n].Freq != 0)
+            break;
+    if (n == 9)
+        for (n = 14; n < 32; n++)
+            if (s->dyn_ltree[n].Freq != 0)
+                break;
+    s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY;
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(code, len)
+    unsigned code; /* the value to invert */
+    int len;       /* its bit length */
+{
+    register unsigned res = 0;
+    do {
+        res |= code & 1;
+        code >>= 1, res <<= 1;
+    } while (--len > 0);
+    return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(s)
+    deflate_state *s;
+{
+    if (s->bi_valid == 16) {
+        put_short(s, s->bi_buf);
+        s->bi_buf = 0;
+        s->bi_valid = 0;
+    } else if (s->bi_valid >= 8) {
+        put_byte(s, (Byte)s->bi_buf);
+        s->bi_buf >>= 8;
+        s->bi_valid -= 8;
+    }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(s)
+    deflate_state *s;
+{
+    if (s->bi_valid > 8) {
+        put_short(s, s->bi_buf);
+    } else if (s->bi_valid > 0) {
+        put_byte(s, (Byte)s->bi_buf);
+    }
+    s->bi_buf = 0;
+    s->bi_valid = 0;
+#ifdef DEBUG
+    s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(s, buf, len, header)
+    deflate_state *s;
+    charf    *buf;    /* the input data */
+    unsigned len;     /* its length */
+    int      header;  /* true if block header must be written */
+{
+    bi_windup(s);        /* align on byte boundary */
+    s->last_eob_len = 8; /* enough lookahead for inflate */
+
+    if (header) {
+        put_short(s, (ush)len);
+        put_short(s, (ush)~len);
+#ifdef DEBUG
+        s->bits_sent += 2*16;
+#endif
+    }
+#ifdef DEBUG
+    s->bits_sent += (ulg)len<<3;
+#endif
+    while (len--) {
+        put_byte(s, *buf++);
+    }
+}
Index: /trunk/minix/lib/zlib-1.2.3/trees.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/trees.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/trees.h	(revision 9)
@@ -0,0 +1,128 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{  8}}, {{140},{  8}}, {{ 76},{  8}}, {{204},{  8}}, {{ 44},{  8}},
+{{172},{  8}}, {{108},{  8}}, {{236},{  8}}, {{ 28},{  8}}, {{156},{  8}},
+{{ 92},{  8}}, {{220},{  8}}, {{ 60},{  8}}, {{188},{  8}}, {{124},{  8}},
+{{252},{  8}}, {{  2},{  8}}, {{130},{  8}}, {{ 66},{  8}}, {{194},{  8}},
+{{ 34},{  8}}, {{162},{  8}}, {{ 98},{  8}}, {{226},{  8}}, {{ 18},{  8}},
+{{146},{  8}}, {{ 82},{  8}}, {{210},{  8}}, {{ 50},{  8}}, {{178},{  8}},
+{{114},{  8}}, {{242},{  8}}, {{ 10},{  8}}, {{138},{  8}}, {{ 74},{  8}},
+{{202},{  8}}, {{ 42},{  8}}, {{170},{  8}}, {{106},{  8}}, {{234},{  8}},
+{{ 26},{  8}}, {{154},{  8}}, {{ 90},{  8}}, {{218},{  8}}, {{ 58},{  8}},
+{{186},{  8}}, {{122},{  8}}, {{250},{  8}}, {{  6},{  8}}, {{134},{  8}},
+{{ 70},{  8}}, {{198},{  8}}, {{ 38},{  8}}, {{166},{  8}}, {{102},{  8}},
+{{230},{  8}}, {{ 22},{  8}}, {{150},{  8}}, {{ 86},{  8}}, {{214},{  8}},
+{{ 54},{  8}}, {{182},{  8}}, {{118},{  8}}, {{246},{  8}}, {{ 14},{  8}},
+{{142},{  8}}, {{ 78},{  8}}, {{206},{  8}}, {{ 46},{  8}}, {{174},{  8}},
+{{110},{  8}}, {{238},{  8}}, {{ 30},{  8}}, {{158},{  8}}, {{ 94},{  8}},
+{{222},{  8}}, {{ 62},{  8}}, {{190},{  8}}, {{126},{  8}}, {{254},{  8}},
+{{  1},{  8}}, {{129},{  8}}, {{ 65},{  8}}, {{193},{  8}}, {{ 33},{  8}},
+{{161},{  8}}, {{ 97},{  8}}, {{225},{  8}}, {{ 17},{  8}}, {{145},{  8}},
+{{ 81},{  8}}, {{209},{  8}}, {{ 49},{  8}}, {{177},{  8}}, {{113},{  8}},
+{{241},{  8}}, {{  9},{  8}}, {{137},{  8}}, {{ 73},{  8}}, {{201},{  8}},
+{{ 41},{  8}}, {{169},{  8}}, {{105},{  8}}, {{233},{  8}}, {{ 25},{  8}},
+{{153},{  8}}, {{ 89},{  8}}, {{217},{  8}}, {{ 57},{  8}}, {{185},{  8}},
+{{121},{  8}}, {{249},{  8}}, {{  5},{  8}}, {{133},{  8}}, {{ 69},{  8}},
+{{197},{  8}}, {{ 37},{  8}}, {{165},{  8}}, {{101},{  8}}, {{229},{  8}},
+{{ 21},{  8}}, {{149},{  8}}, {{ 85},{  8}}, {{213},{  8}}, {{ 53},{  8}},
+{{181},{  8}}, {{117},{  8}}, {{245},{  8}}, {{ 13},{  8}}, {{141},{  8}},
+{{ 77},{  8}}, {{205},{  8}}, {{ 45},{  8}}, {{173},{  8}}, {{109},{  8}},
+{{237},{  8}}, {{ 29},{  8}}, {{157},{  8}}, {{ 93},{  8}}, {{221},{  8}},
+{{ 61},{  8}}, {{189},{  8}}, {{125},{  8}}, {{253},{  8}}, {{ 19},{  9}},
+{{275},{  9}}, {{147},{  9}}, {{403},{  9}}, {{ 83},{  9}}, {{339},{  9}},
+{{211},{  9}}, {{467},{  9}}, {{ 51},{  9}}, {{307},{  9}}, {{179},{  9}},
+{{435},{  9}}, {{115},{  9}}, {{371},{  9}}, {{243},{  9}}, {{499},{  9}},
+{{ 11},{  9}}, {{267},{  9}}, {{139},{  9}}, {{395},{  9}}, {{ 75},{  9}},
+{{331},{  9}}, {{203},{  9}}, {{459},{  9}}, {{ 43},{  9}}, {{299},{  9}},
+{{171},{  9}}, {{427},{  9}}, {{107},{  9}}, {{363},{  9}}, {{235},{  9}},
+{{491},{  9}}, {{ 27},{  9}}, {{283},{  9}}, {{155},{  9}}, {{411},{  9}},
+{{ 91},{  9}}, {{347},{  9}}, {{219},{  9}}, {{475},{  9}}, {{ 59},{  9}},
+{{315},{  9}}, {{187},{  9}}, {{443},{  9}}, {{123},{  9}}, {{379},{  9}},
+{{251},{  9}}, {{507},{  9}}, {{  7},{  9}}, {{263},{  9}}, {{135},{  9}},
+{{391},{  9}}, {{ 71},{  9}}, {{327},{  9}}, {{199},{  9}}, {{455},{  9}},
+{{ 39},{  9}}, {{295},{  9}}, {{167},{  9}}, {{423},{  9}}, {{103},{  9}},
+{{359},{  9}}, {{231},{  9}}, {{487},{  9}}, {{ 23},{  9}}, {{279},{  9}},
+{{151},{  9}}, {{407},{  9}}, {{ 87},{  9}}, {{343},{  9}}, {{215},{  9}},
+{{471},{  9}}, {{ 55},{  9}}, {{311},{  9}}, {{183},{  9}}, {{439},{  9}},
+{{119},{  9}}, {{375},{  9}}, {{247},{  9}}, {{503},{  9}}, {{ 15},{  9}},
+{{271},{  9}}, {{143},{  9}}, {{399},{  9}}, {{ 79},{  9}}, {{335},{  9}},
+{{207},{  9}}, {{463},{  9}}, {{ 47},{  9}}, {{303},{  9}}, {{175},{  9}},
+{{431},{  9}}, {{111},{  9}}, {{367},{  9}}, {{239},{  9}}, {{495},{  9}},
+{{ 31},{  9}}, {{287},{  9}}, {{159},{  9}}, {{415},{  9}}, {{ 95},{  9}},
+{{351},{  9}}, {{223},{  9}}, {{479},{  9}}, {{ 63},{  9}}, {{319},{  9}},
+{{191},{  9}}, {{447},{  9}}, {{127},{  9}}, {{383},{  9}}, {{255},{  9}},
+{{511},{  9}}, {{  0},{  7}}, {{ 64},{  7}}, {{ 32},{  7}}, {{ 96},{  7}},
+{{ 16},{  7}}, {{ 80},{  7}}, {{ 48},{  7}}, {{112},{  7}}, {{  8},{  7}},
+{{ 72},{  7}}, {{ 40},{  7}}, {{104},{  7}}, {{ 24},{  7}}, {{ 88},{  7}},
+{{ 56},{  7}}, {{120},{  7}}, {{  4},{  7}}, {{ 68},{  7}}, {{ 36},{  7}},
+{{100},{  7}}, {{ 20},{  7}}, {{ 84},{  7}}, {{ 52},{  7}}, {{116},{  7}},
+{{  3},{  8}}, {{131},{  8}}, {{ 67},{  8}}, {{195},{  8}}, {{ 35},{  8}},
+{{163},{  8}}, {{ 99},{  8}}, {{227},{  8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch _dist_code[DIST_CODE_LEN] = {
+ 0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,
+ 8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+    0,     1,     2,     3,     4,     6,     8,    12,    16,    24,
+   32,    48,    64,    96,   128,   192,   256,   384,   512,   768,
+ 1024,  1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576
+};
+
Index: /trunk/minix/lib/zlib-1.2.3/uncompr.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/uncompr.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/uncompr.c	(revision 9)
@@ -0,0 +1,61 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: uncompr.c,v 1.1 2005/09/23 22:39:00 beng Exp $ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+int ZEXPORT uncompress (dest, destLen, source, sourceLen)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+{
+    z_stream stream;
+    int err;
+
+    stream.next_in = (Bytef*)source;
+    stream.avail_in = (uInt)sourceLen;
+    /* Check for source > 64K on 16-bit machine: */
+    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+
+    stream.next_out = dest;
+    stream.avail_out = (uInt)*destLen;
+    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+    stream.zalloc = (alloc_func)0;
+    stream.zfree = (free_func)0;
+
+    err = inflateInit(&stream);
+    if (err != Z_OK) return err;
+
+    err = inflate(&stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        inflateEnd(&stream);
+        if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
+            return Z_DATA_ERROR;
+        return err;
+    }
+    *destLen = stream.total_out;
+
+    err = inflateEnd(&stream);
+    return err;
+}
Index: /trunk/minix/lib/zlib-1.2.3/win32/DLL_FAQ.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/win32/DLL_FAQ.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/win32/DLL_FAQ.txt	(revision 9)
@@ -0,0 +1,397 @@
+
+            Frequently Asked Questions about ZLIB1.DLL
+
+
+This document describes the design, the rationale, and the usage
+of the official DLL build of zlib, named ZLIB1.DLL.  If you have
+general questions about zlib, you should see the file "FAQ" found
+in the zlib distribution, or at the following location:
+  http://www.gzip.org/zlib/zlib_faq.html
+
+
+ 1. What is ZLIB1.DLL, and how can I get it?
+
+  - ZLIB1.DLL is the official build of zlib as a DLL.
+    (Please remark the character '1' in the name.)
+
+    Pointers to a precompiled ZLIB1.DLL can be found in the zlib
+    web site at:
+      http://www.zlib.org/
+
+    Applications that link to ZLIB1.DLL can rely on the following
+    specification:
+
+    * The exported symbols are exclusively defined in the source
+      files "zlib.h" and "zlib.def", found in an official zlib
+      source distribution.
+    * The symbols are exported by name, not by ordinal.
+    * The exported names are undecorated.
+    * The calling convention of functions is "C" (CDECL).
+    * The ZLIB1.DLL binary is linked to MSVCRT.DLL.
+
+    The archive in which ZLIB1.DLL is bundled contains compiled
+    test programs that must run with a valid build of ZLIB1.DLL.
+    It is recommended to download the prebuilt DLL from the zlib
+    web site, instead of building it yourself, to avoid potential
+    incompatibilities that could be introduced by your compiler
+    and build settings.  If you do build the DLL yourself, please
+    make sure that it complies with all the above requirements,
+    and it runs with the precompiled test programs, bundled with
+    the original ZLIB1.DLL distribution.
+
+    If, for any reason, you need to build an incompatible DLL,
+    please use a different file name.
+
+
+ 2. Why did you change the name of the DLL to ZLIB1.DLL?
+    What happened to the old ZLIB.DLL?
+
+  - The old ZLIB.DLL, built from zlib-1.1.4 or earlier, required
+    compilation settings that were incompatible to those used by
+    a static build.  The DLL settings were supposed to be enabled
+    by defining the macro ZLIB_DLL, before including "zlib.h".
+    Incorrect handling of this macro was silently accepted at
+    build time, resulting in two major problems:
+
+    * ZLIB_DLL was missing from the old makefile.  When building
+      the DLL, not all people added it to the build options.  In
+      consequence, incompatible incarnations of ZLIB.DLL started
+      to circulate around the net.
+
+    * When switching from using the static library to using the
+      DLL, applications had to define the ZLIB_DLL macro and
+      to recompile all the sources that contained calls to zlib
+      functions.  Failure to do so resulted in creating binaries
+      that were unable to run with the official ZLIB.DLL build.
+
+    The only possible solution that we could foresee was to make
+    a binary-incompatible change in the DLL interface, in order to
+    remove the dependency on the ZLIB_DLL macro, and to release
+    the new DLL under a different name.
+
+    We chose the name ZLIB1.DLL, where '1' indicates the major
+    zlib version number.  We hope that we will not have to break
+    the binary compatibility again, at least not as long as the
+    zlib-1.x series will last.
+
+    There is still a ZLIB_DLL macro, that can trigger a more
+    efficient build and use of the DLL, but compatibility no
+    longer dependents on it.
+
+
+ 3. Can I build ZLIB.DLL from the new zlib sources, and replace
+    an old ZLIB.DLL, that was built from zlib-1.1.4 or earlier?
+
+  - In principle, you can do it by assigning calling convention
+    keywords to the macros ZEXPORT and ZEXPORTVA.  In practice,
+    it depends on what you mean by "an old ZLIB.DLL", because the
+    old DLL exists in several mutually-incompatible versions.
+    You have to find out first what kind of calling convention is
+    being used in your particular ZLIB.DLL build, and to use the
+    same one in the new build.  If you don't know what this is all
+    about, you might be better off if you would just leave the old
+    DLL intact.
+
+
+ 4. Can I compile my application using the new zlib interface, and
+    link it to an old ZLIB.DLL, that was built from zlib-1.1.4 or
+    earlier?
+
+  - The official answer is "no"; the real answer depends again on
+    what kind of ZLIB.DLL you have.  Even if you are lucky, this
+    course of action is unreliable.
+
+    If you rebuild your application and you intend to use a newer
+    version of zlib (post- 1.1.4), it is strongly recommended to
+    link it to the new ZLIB1.DLL.
+
+
+ 5. Why are the zlib symbols exported by name, and not by ordinal?
+
+  - Although exporting symbols by ordinal is a little faster, it
+    is risky.  Any single glitch in the maintenance or use of the
+    DEF file that contains the ordinals can result in incompatible
+    builds and frustrating crashes.  Simply put, the benefits of
+    exporting symbols by ordinal do not justify the risks.
+
+    Technically, it should be possible to maintain ordinals in
+    the DEF file, and still export the symbols by name.  Ordinals
+    exist in every DLL, and even if the dynamic linking performed
+    at the DLL startup is searching for names, ordinals serve as
+    hints, for a faster name lookup.  However, if the DEF file
+    contains ordinals, the Microsoft linker automatically builds
+    an implib that will cause the executables linked to it to use
+    those ordinals, and not the names.  It is interesting to
+    notice that the GNU linker for Win32 does not suffer from this
+    problem.
+
+    It is possible to avoid the DEF file if the exported symbols
+    are accompanied by a "__declspec(dllexport)" attribute in the
+    source files.  You can do this in zlib by predefining the
+    ZLIB_DLL macro.
+
+
+ 6. I see that the ZLIB1.DLL functions use the "C" (CDECL) calling
+    convention.  Why not use the STDCALL convention?
+    STDCALL is the standard convention in Win32, and I need it in
+    my Visual Basic project!
+
+    (For readability, we use CDECL to refer to the convention
+     triggered by the "__cdecl" keyword, STDCALL to refer to
+     the convention triggered by "__stdcall", and FASTCALL to
+     refer to the convention triggered by "__fastcall".)
+
+  - Most of the native Windows API functions (without varargs) use
+    indeed the WINAPI convention (which translates to STDCALL in
+    Win32), but the standard C functions use CDECL.  If a user
+    application is intrinsically tied to the Windows API (e.g.
+    it calls native Windows API functions such as CreateFile()),
+    sometimes it makes sense to decorate its own functions with
+    WINAPI.  But if ANSI C or POSIX portability is a goal (e.g.
+    it calls standard C functions such as fopen()), it is not a
+    sound decision to request the inclusion of <windows.h>, or to
+    use non-ANSI constructs, for the sole purpose to make the user
+    functions STDCALL-able.
+
+    The functionality offered by zlib is not in the category of
+    "Windows functionality", but is more like "C functionality".
+
+    Technically, STDCALL is not bad; in fact, it is slightly
+    faster than CDECL, and it works with variable-argument
+    functions, just like CDECL.  It is unfortunate that, in spite
+    of using STDCALL in the Windows API, it is not the default
+    convention used by the C compilers that run under Windows.
+    The roots of the problem reside deep inside the unsafety of
+    the K&R-style function prototypes, where the argument types
+    are not specified; but that is another story for another day.
+
+    The remaining fact is that CDECL is the default convention.
+    Even if an explicit convention is hard-coded into the function
+    prototypes inside C headers, problems may appear.  The
+    necessity to expose the convention in users' callbacks is one
+    of these problems.
+
+    The calling convention issues are also important when using
+    zlib in other programming languages.  Some of them, like Ada
+    (GNAT) and Fortran (GNU G77), have C bindings implemented
+    initially on Unix, and relying on the C calling convention.
+    On the other hand, the pre- .NET versions of Microsoft Visual
+    Basic require STDCALL, while Borland Delphi prefers, although
+    it does not require, FASTCALL.
+
+    In fairness to all possible uses of zlib outside the C
+    programming language, we choose the default "C" convention.
+    Anyone interested in different bindings or conventions is
+    encouraged to maintain specialized projects.  The "contrib/"
+    directory from the zlib distribution already holds a couple
+    of foreign bindings, such as Ada, C++, and Delphi.
+
+
+ 7. I need a DLL for my Visual Basic project.  What can I do?
+
+  - Define the ZLIB_WINAPI macro before including "zlib.h", when
+    building both the DLL and the user application (except that
+    you don't need to define anything when using the DLL in Visual
+    Basic).  The ZLIB_WINAPI macro will switch on the WINAPI
+    (STDCALL) convention.  The name of this DLL must be different
+    than the official ZLIB1.DLL.
+
+    Gilles Vollant has contributed a build named ZLIBWAPI.DLL,
+    with the ZLIB_WINAPI macro turned on, and with the minizip
+    functionality built in.  For more information, please read
+    the notes inside "contrib/vstudio/readme.txt", found in the
+    zlib distribution.
+
+
+ 8. I need to use zlib in my Microsoft .NET project.  What can I
+    do?
+
+  - Henrik Ravn has contributed a .NET wrapper around zlib.  Look
+    into contrib/dotzlib/, inside the zlib distribution.
+
+
+ 9. If my application uses ZLIB1.DLL, should I link it to
+    MSVCRT.DLL?  Why?
+
+  - It is not required, but it is recommended to link your
+    application to MSVCRT.DLL, if it uses ZLIB1.DLL.
+
+    The executables (.EXE, .DLL, etc.) that are involved in the
+    same process and are using the C run-time library (i.e. they
+    are calling standard C functions), must link to the same
+    library.  There are several libraries in the Win32 system:
+    CRTDLL.DLL, MSVCRT.DLL, the static C libraries, etc.
+    Since ZLIB1.DLL is linked to MSVCRT.DLL, the executables that
+    depend on it should also be linked to MSVCRT.DLL.
+
+
+10. Why are you saying that ZLIB1.DLL and my application should
+    be linked to the same C run-time (CRT) library?  I linked my
+    application and my DLLs to different C libraries (e.g. my
+    application to a static library, and my DLLs to MSVCRT.DLL),
+    and everything works fine.
+
+  - If a user library invokes only pure Win32 API (accessible via
+    <windows.h> and the related headers), its DLL build will work
+    in any context.  But if this library invokes standard C API,
+    things get more complicated.
+
+    There is a single Win32 library in a Win32 system.  Every
+    function in this library resides in a single DLL module, that
+    is safe to call from anywhere.  On the other hand, there are
+    multiple versions of the C library, and each of them has its
+    own separate internal state.  Standalone executables and user
+    DLLs that call standard C functions must link to a C run-time
+    (CRT) library, be it static or shared (DLL).  Intermixing
+    occurs when an executable (not necessarily standalone) and a
+    DLL are linked to different CRTs, and both are running in the
+    same process.
+
+    Intermixing multiple CRTs is possible, as long as their
+    internal states are kept intact.  The Microsoft Knowledge Base
+    articles KB94248 "HOWTO: Use the C Run-Time" and KB140584
+    "HOWTO: Link with the Correct C Run-Time (CRT) Library"
+    mention the potential problems raised by intermixing.
+
+    If intermixing works for you, it's because your application
+    and DLLs are avoiding the corruption of each of the CRTs'
+    internal states, maybe by careful design, or maybe by fortune.
+
+    Also note that linking ZLIB1.DLL to non-Microsoft CRTs, such
+    as those provided by Borland, raises similar problems.
+
+
+11. Why are you linking ZLIB1.DLL to MSVCRT.DLL?
+
+  - MSVCRT.DLL exists on every Windows 95 with a new service pack
+    installed, or with Microsoft Internet Explorer 4 or later, and
+    on all other Windows 4.x or later (Windows 98, Windows NT 4,
+    or later).  It is freely distributable; if not present in the
+    system, it can be downloaded from Microsoft or from other
+    software provider for free.
+
+    The fact that MSVCRT.DLL does not exist on a virgin Windows 95
+    is not so problematic.  Windows 95 is scarcely found nowadays,
+    Microsoft ended its support a long time ago, and many recent
+    applications from various vendors, including Microsoft, do not
+    even run on it.  Furthermore, no serious user should run
+    Windows 95 without a proper update installed.
+
+
+12. Why are you not linking ZLIB1.DLL to
+    <<my favorite C run-time library>> ?
+
+  - We considered and abandoned the following alternatives:
+
+    * Linking ZLIB1.DLL to a static C library (LIBC.LIB, or
+      LIBCMT.LIB) is not a good option.  People are using the DLL
+      mainly to save disk space.  If you are linking your program
+      to a static C library, you may as well consider linking zlib
+      in statically, too.
+
+    * Linking ZLIB1.DLL to CRTDLL.DLL looks appealing, because
+      CRTDLL.DLL is present on every Win32 installation.
+      Unfortunately, it has a series of problems: it does not
+      work properly with Microsoft's C++ libraries, it does not
+      provide support for 64-bit file offsets, (and so on...),
+      and Microsoft discontinued its support a long time ago.
+
+    * Linking ZLIB1.DLL to MSVCR70.DLL or MSVCR71.DLL, supplied
+      with the Microsoft .NET platform, and Visual C++ 7.0/7.1,
+      raises problems related to the status of ZLIB1.DLL as a
+      system component.  According to the Microsoft Knowledge Base
+      article KB326922 "INFO: Redistribution of the Shared C
+      Runtime Component in Visual C++ .NET", MSVCR70.DLL and
+      MSVCR71.DLL are not supposed to function as system DLLs,
+      because they may clash with MSVCRT.DLL.  Instead, the
+      application's installer is supposed to put these DLLs
+      (if needed) in the application's private directory.
+      If ZLIB1.DLL depends on a non-system runtime, it cannot
+      function as a redistributable system component.
+
+    * Linking ZLIB1.DLL to non-Microsoft runtimes, such as
+      Borland's, or Cygwin's, raises problems related to the
+      reliable presence of these runtimes on Win32 systems.
+      It's easier to let the DLL build of zlib up to the people
+      who distribute these runtimes, and who may proceed as
+      explained in the answer to Question 14.
+
+
+13. If ZLIB1.DLL cannot be linked to MSVCR70.DLL or MSVCR71.DLL,
+    how can I build/use ZLIB1.DLL in Microsoft Visual C++ 7.0
+    (Visual Studio .NET) or newer?
+
+  - Due to the problems explained in the Microsoft Knowledge Base
+    article KB326922 (see the previous answer), the C runtime that
+    comes with the VC7 environment is no longer considered a
+    system component.  That is, it should not be assumed that this
+    runtime exists, or may be installed in a system directory.
+    Since ZLIB1.DLL is supposed to be a system component, it may
+    not depend on a non-system component.
+
+    In order to link ZLIB1.DLL and your application to MSVCRT.DLL
+    in VC7, you need the library of Visual C++ 6.0 or older.  If
+    you don't have this library at hand, it's probably best not to
+    use ZLIB1.DLL.
+
+    We are hoping that, in the future, Microsoft will provide a
+    way to build applications linked to a proper system runtime,
+    from the Visual C++ environment.  Until then, you have a
+    couple of alternatives, such as linking zlib in statically.
+    If your application requires dynamic linking, you may proceed
+    as explained in the answer to Question 14.
+
+
+14. I need to link my own DLL build to a CRT different than
+    MSVCRT.DLL.  What can I do?
+
+  - Feel free to rebuild the DLL from the zlib sources, and link
+    it the way you want.  You should, however, clearly state that
+    your build is unofficial.  You should give it a different file
+    name, and/or install it in a private directory that can be
+    accessed by your application only, and is not visible to the
+    others (e.g. it's not in the SYSTEM or the SYSTEM32 directory,
+    and it's not in the PATH).  Otherwise, your build may clash
+    with applications that link to the official build.
+
+    For example, in Cygwin, zlib is linked to the Cygwin runtime
+    CYGWIN1.DLL, and it is distributed under the name CYGZ.DLL.
+
+
+15. May I include additional pieces of code that I find useful,
+    link them in ZLIB1.DLL, and export them?
+
+  - No.  A legitimate build of ZLIB1.DLL must not include code
+    that does not originate from the official zlib source code.
+    But you can make your own private DLL build, under a different
+    file name, as suggested in the previous answer.
+
+    For example, zlib is a part of the VCL library, distributed
+    with Borland Delphi and C++ Builder.  The DLL build of VCL
+    is a redistributable file, named VCLxx.DLL.
+
+
+16. May I remove some functionality out of ZLIB1.DLL, by enabling
+    macros like NO_GZCOMPRESS or NO_GZIP at compile time?
+
+  - No.  A legitimate build of ZLIB1.DLL must provide the complete
+    zlib functionality, as implemented in the official zlib source
+    code.  But you can make your own private DLL build, under a
+    different file name, as suggested in the previous answer.
+
+
+17. I made my own ZLIB1.DLL build.  Can I test it for compliance?
+
+  - We prefer that you download the official DLL from the zlib
+    web site.  If you need something peculiar from this DLL, you
+    can send your suggestion to the zlib mailing list.
+
+    However, in case you do rebuild the DLL yourself, you can run
+    it with the test programs found in the DLL distribution.
+    Running these test programs is not a guarantee of compliance,
+    but a failure can imply a detected problem.
+
+**
+
+This document is written and maintained by
+Cosmin Truta <cosmint@cs.ubbcluj.ro>
Index: /trunk/minix/lib/zlib-1.2.3/win32/Makefile.bor
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/win32/Makefile.bor	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/win32/Makefile.bor	(revision 9)
@@ -0,0 +1,107 @@
+# Makefile for zlib
+# Borland C++ for Win32
+#
+# Updated for zlib 1.2.x by Cosmin Truta, 11-Mar-2003
+# Last updated: 28-Aug-2003
+#
+# Usage:
+#  make -f win32/Makefile.bor
+#  make -f win32/Makefile.bor LOCAL_ZLIB=-DASMV OBJA=match.obj OBJPA=+match.obj
+
+# ------------ Borland C++ ------------
+
+# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7)
+# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or
+# added to the declaration of LOC here:
+LOC = $(LOCAL_ZLIB)
+
+CC = bcc32
+AS = bcc32
+LD = bcc32
+AR = tlib
+CFLAGS  = -a -d -k- -O2 $(LOC)
+ASFLAGS = $(LOC)
+LDFLAGS = $(LOC)
+
+
+# variables
+ZLIB_LIB = zlib.lib
+
+OBJ1  = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
+OBJ2  = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+#OBJA =
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infback.obj
+OBJP2 = +inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+#OBJPA=
+
+
+# targets
+all: $(ZLIB_LIB) example.exe minigzip.exe
+
+.c.obj:
+	$(CC) -c $(CFLAGS) $<
+
+.asm.obj:
+	$(AS) -c $(ASFLAGS) $<
+
+adler32.obj: adler32.c zlib.h zconf.h
+
+compress.obj: compress.c zlib.h zconf.h
+
+crc32.obj: crc32.c zlib.h zconf.h crc32.h
+
+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
+
+gzio.obj: gzio.c zutil.h zlib.h zconf.h
+
+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h
+
+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
+
+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
+
+uncompr.obj: uncompr.c zlib.h zconf.h
+
+zutil.obj: zutil.c zutil.h zlib.h zconf.h
+
+example.obj: example.c zlib.h zconf.h
+
+minigzip.obj: minigzip.c zlib.h zconf.h
+
+
+# For the sake of the old Borland make,
+# the command line is cut to fit in the MS-DOS 128 byte limit:
+$(ZLIB_LIB): $(OBJ1) $(OBJ2) $(OBJA)
+	-del $(ZLIB_LIB)
+	$(AR) $(ZLIB_LIB) $(OBJP1)
+	$(AR) $(ZLIB_LIB) $(OBJP2)
+	$(AR) $(ZLIB_LIB) $(OBJPA)
+
+
+# testing
+test: example.exe minigzip.exe
+	example
+	echo hello world | minigzip | minigzip -d
+
+example.exe: example.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) example.obj $(ZLIB_LIB)
+
+minigzip.exe: minigzip.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB)
+
+
+# cleanup
+clean:
+	-del *.obj
+	-del *.lib
+	-del *.exe
+	-del *.tds
+	-del zlib.bak
+	-del foo.gz
Index: /trunk/minix/lib/zlib-1.2.3/win32/Makefile.emx
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/win32/Makefile.emx	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/win32/Makefile.emx	(revision 9)
@@ -0,0 +1,69 @@
+# Makefile for zlib.  Modified for emx/rsxnt by Chr. Spieler, 6/16/98.
+# Copyright (C) 1995-1998 Jean-loup Gailly.
+# For conditions of distribution and use, see copyright notice in zlib.h
+
+# To compile, or to compile and test, type:
+#
+#   make -fmakefile.emx;  make test -fmakefile.emx
+#
+
+CC=gcc -Zwin32
+
+#CFLAGS=-MMD -O
+#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#CFLAGS=-MMD -g -DDEBUG
+CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+             -Wstrict-prototypes -Wmissing-prototypes
+
+# If cp.exe is available, replace "copy /Y" with "cp -fp" .
+CP=copy /Y
+# If gnu install.exe is available, replace $(CP) with ginstall.
+INSTALL=$(CP)
+# The default value of RM is "rm -f."  If "rm.exe" is found, comment out:
+RM=del
+LDLIBS=-L. -lzlib
+LD=$(CC) -s -o
+LDSHARED=$(CC)
+
+INCL=zlib.h zconf.h
+LIBS=zlib.a
+
+AR=ar rcs
+
+prefix=/usr/local
+exec_prefix = $(prefix)
+
+OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
+       zutil.o inflate.o infback.o inftrees.o inffast.o
+
+TEST_OBJS = example.o minigzip.o
+
+all: example.exe minigzip.exe
+
+test: all
+	./example
+	echo hello world | .\minigzip | .\minigzip -d
+
+%.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
+
+zlib.a: $(OBJS)
+	$(AR) $@ $(OBJS)
+
+%.exe : %.o $(LIBS)
+	$(LD) $@ $< $(LDLIBS)
+
+
+.PHONY : clean
+
+clean:
+	$(RM) *.d
+	$(RM) *.o
+	$(RM) *.exe
+	$(RM) zlib.a
+	$(RM) foo.gz
+
+DEPS := $(wildcard *.d)
+ifneq ($(DEPS),)
+include $(DEPS)
+endif
Index: /trunk/minix/lib/zlib-1.2.3/win32/Makefile.gcc
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/win32/Makefile.gcc	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/win32/Makefile.gcc	(revision 9)
@@ -0,0 +1,141 @@
+# Makefile for zlib, derived from Makefile.dj2.
+# Modified for mingw32 by C. Spieler, 6/16/98.
+# Updated for zlib 1.2.x by Christian Spieler and Cosmin Truta, Mar-2003.
+# Last updated: 1-Aug-2003.
+# Tested under Cygwin and MinGW.
+
+# Copyright (C) 1995-2003 Jean-loup Gailly.
+# For conditions of distribution and use, see copyright notice in zlib.h
+
+# To compile, or to compile and test, type:
+#
+#   make -fmakefile.gcc;  make test testdll -fmakefile.gcc
+#
+# To use the asm code, type:
+#   cp contrib/asm?86/match.S ./match.S
+#   make LOC=-DASMV OBJA=match.o -fmakefile.gcc
+#
+# To install libz.a, zconf.h and zlib.h in the system directories, type:
+#
+#   make install -fmakefile.gcc
+
+# Note:
+# If the platform is *not* MinGW (e.g. it is Cygwin or UWIN),
+# the DLL name should be changed from "zlib1.dll".
+
+STATICLIB = libz.a
+SHAREDLIB = zlib1.dll
+IMPLIB    = libzdll.a
+
+#LOC = -DASMV
+#LOC = -DDEBUG -g
+
+CC = gcc
+CFLAGS = $(LOC) -O3 -Wall
+
+AS = $(CC)
+ASFLAGS = $(LOC) -Wall
+
+LD = $(CC)
+LDFLAGS = $(LOC) -s
+
+AR = ar
+ARFLAGS = rcs
+
+RC = windres
+RCFLAGS = --define GCC_WINDRES
+
+CP = cp -fp
+# If GNU install is available, replace $(CP) with install.
+INSTALL = $(CP)
+RM = rm -f
+
+prefix = /usr/local
+exec_prefix = $(prefix)
+
+OBJS = adler32.o compress.o crc32.o deflate.o gzio.o infback.o \
+       inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o
+OBJA =
+
+all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) example minigzip example_d minigzip_d
+
+test: example minigzip
+	./example
+	echo hello world | ./minigzip | ./minigzip -d
+
+testdll: example_d minigzip_d
+	./example_d
+	echo hello world | ./minigzip_d | ./minigzip_d -d
+
+.c.o:
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+.S.o:
+	$(AS) $(ASFLAGS) -c -o $@ $<
+
+$(STATICLIB): $(OBJS) $(OBJA)
+	$(AR) $(ARFLAGS) $@ $(OBJS) $(OBJA)
+
+$(IMPLIB): $(SHAREDLIB)
+
+$(SHAREDLIB): win32/zlib.def $(OBJS) $(OBJA) zlibrc.o
+	dllwrap --driver-name $(CC) --def win32/zlib.def \
+	  --implib $(IMPLIB) -o $@ $(OBJS) $(OBJA) zlibrc.o
+	strip $@
+
+example: example.o $(STATICLIB)
+	$(LD) $(LDFLAGS) -o $@ example.o $(STATICLIB)
+
+minigzip: minigzip.o $(STATICLIB)
+	$(LD) $(LDFLAGS) -o $@ minigzip.o $(STATICLIB)
+
+example_d: example.o $(IMPLIB)
+	$(LD) $(LDFLAGS) -o $@ example.o $(IMPLIB)
+
+minigzip_d: minigzip.o $(IMPLIB)
+	$(LD) $(LDFLAGS) -o $@ minigzip.o $(IMPLIB)
+
+zlibrc.o: win32/zlib1.rc
+	$(RC) $(RCFLAGS) -o $@ win32/zlib1.rc
+
+
+# INCLUDE_PATH and LIBRARY_PATH must be set.
+
+.PHONY: install uninstall clean
+
+install: zlib.h zconf.h $(LIB)
+	-@if not exist $(INCLUDE_PATH)/nul mkdir $(INCLUDE_PATH)
+	-@if not exist $(LIBRARY_PATH)/nul mkdir $(LIBRARY_PATH)
+	-$(INSTALL) zlib.h $(INCLUDE_PATH)
+	-$(INSTALL) zconf.h $(INCLUDE_PATH)
+	-$(INSTALL) $(STATICLIB) $(LIBRARY_PATH)
+	-$(INSTALL) $(IMPLIB) $(LIBRARY_PATH)
+
+uninstall:
+	-$(RM) $(INCLUDE_PATH)/zlib.h
+	-$(RM) $(INCLUDE_PATH)/zconf.h
+	-$(RM) $(LIBRARY_PATH)/$(STATICLIB)
+	-$(RM) $(LIBRARY_PATH)/$(IMPLIB)
+
+clean:
+	-$(RM) $(STATICLIB)
+	-$(RM) $(SHAREDLIB)
+	-$(RM) $(IMPLIB)
+	-$(RM) *.o
+	-$(RM) *.exe
+	-$(RM) foo.gz
+
+adler32.o: zlib.h zconf.h
+compress.o: zlib.h zconf.h
+crc32.o: crc32.h zlib.h zconf.h
+deflate.o: deflate.h zutil.h zlib.h zconf.h
+example.o: zlib.h zconf.h
+gzio.o: zutil.h zlib.h zconf.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inftrees.o: zutil.h zlib.h zconf.h inftrees.h
+minigzip.o: zlib.h zconf.h
+trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
+uncompr.o: zlib.h zconf.h
+zutil.o: zutil.h zlib.h zconf.h
Index: /trunk/minix/lib/zlib-1.2.3/win32/Makefile.msc
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/win32/Makefile.msc	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/win32/Makefile.msc	(revision 9)
@@ -0,0 +1,126 @@
+# Makefile for zlib -- Microsoft (Visual) C
+#
+# Authors:
+#   Cosmin Truta, 11-Mar-2003
+#   Christian Spieler, 19-Mar-2003
+#
+# Last updated:
+#   Cosmin Truta, 27-Aug-2003
+#
+# Usage:
+#   nmake -f win32/Makefile.msc            (standard build)
+#   nmake -f win32/Makefile.msc LOC=-DFOO  (nonstandard build)
+#   nmake -f win32/Makefile.msc LOC=-DASMV OBJA=match.obj  (use ASM code)
+
+
+# optional build flags
+LOC =
+
+
+# variables
+STATICLIB = zlib.lib
+SHAREDLIB = zlib1.dll
+IMPLIB    = zdll.lib
+
+CC = cl
+AS = ml
+LD = link
+AR = lib
+RC = rc
+CFLAGS  = -nologo -MD -O2 $(LOC)
+ASFLAGS = -coff
+LDFLAGS = -nologo -release
+ARFLAGS = -nologo
+RCFLAGS = /dWIN32 /r
+
+OBJS = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj \
+       inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJA =
+
+
+# targets
+all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \
+     example.exe minigzip.exe example_d.exe minigzip_d.exe
+
+$(STATICLIB): $(OBJS) $(OBJA)
+	$(AR) $(ARFLAGS) -out:$@ $(OBJS) $(OBJA)
+
+$(IMPLIB): $(SHAREDLIB)
+
+$(SHAREDLIB): win32/zlib.def $(OBJS) $(OBJA) zlib1.res
+	$(LD) $(LDFLAGS) -def:win32/zlib.def -dll -implib:$(IMPLIB) \
+	  -out:$@ $(OBJS) $(OBJA) zlib1.res
+
+example.exe: example.obj $(STATICLIB)
+	$(LD) $(LDFLAGS) example.obj $(STATICLIB)
+
+minigzip.exe: minigzip.obj $(STATICLIB)
+	$(LD) $(LDFLAGS) minigzip.obj $(STATICLIB)
+
+example_d.exe: example.obj $(IMPLIB)
+	$(LD) $(LDFLAGS) -out:$@ example.obj $(IMPLIB)
+
+minigzip_d.exe: minigzip.obj $(IMPLIB)
+	$(LD) $(LDFLAGS) -out:$@ minigzip.obj $(IMPLIB)
+
+.c.obj:
+	$(CC) -c $(CFLAGS) $<
+
+.asm.obj:
+	$(AS) -c $(ASFLAGS) $<
+
+adler32.obj: adler32.c zlib.h zconf.h
+
+compress.obj: compress.c zlib.h zconf.h
+
+crc32.obj: crc32.c zlib.h zconf.h crc32.h
+
+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
+
+gzio.obj: gzio.c zutil.h zlib.h zconf.h
+
+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+             inffast.h inffixed.h
+
+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+             inffast.h
+
+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+             inffast.h inffixed.h
+
+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
+
+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
+
+uncompr.obj: uncompr.c zlib.h zconf.h
+
+zutil.obj: zutil.c zutil.h zlib.h zconf.h
+
+example.obj: example.c zlib.h zconf.h
+
+minigzip.obj: minigzip.c zlib.h zconf.h
+
+zlib1.res: win32/zlib1.rc
+	$(RC) $(RCFLAGS) /fo$@ win32/zlib1.rc
+
+
+# testing
+test: example.exe minigzip.exe
+	example
+	echo hello world | minigzip | minigzip -d
+
+testdll: example_d.exe minigzip_d.exe
+	example_d
+	echo hello world | minigzip_d | minigzip_d -d
+
+
+# cleanup
+clean:
+	-del $(STATICLIB)
+	-del $(SHAREDLIB)
+	-del $(IMPLIB)
+	-del *.obj
+	-del *.res
+	-del *.exp
+	-del *.exe
+	-del foo.gz
Index: /trunk/minix/lib/zlib-1.2.3/win32/VisualC.txt
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/win32/VisualC.txt	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/win32/VisualC.txt	(revision 9)
@@ -0,0 +1,3 @@
+
+To build zlib using the Microsoft Visual C++ environment,
+use the appropriate project from the projects/ directory.
Index: /trunk/minix/lib/zlib-1.2.3/win32/zlib.def
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/win32/zlib.def	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/win32/zlib.def	(revision 9)
@@ -0,0 +1,60 @@
+LIBRARY
+; zlib data compression library
+
+EXPORTS
+; basic functions
+    zlibVersion
+    deflate
+    deflateEnd
+    inflate
+    inflateEnd
+; advanced functions
+    deflateSetDictionary
+    deflateCopy
+    deflateReset
+    deflateParams
+    deflateBound
+    deflatePrime
+    inflateSetDictionary
+    inflateSync
+    inflateCopy
+    inflateReset
+    inflateBack
+    inflateBackEnd
+    zlibCompileFlags
+; utility functions
+    compress
+    compress2
+    compressBound
+    uncompress
+    gzopen
+    gzdopen
+    gzsetparams
+    gzread
+    gzwrite
+    gzprintf
+    gzputs
+    gzgets
+    gzputc
+    gzgetc
+    gzungetc
+    gzflush
+    gzseek
+    gzrewind
+    gztell
+    gzeof
+    gzclose
+    gzerror
+    gzclearerr
+; checksum functions
+    adler32
+    crc32
+; various hacks, don't look :)
+    deflateInit_
+    deflateInit2_
+    inflateInit_
+    inflateInit2_
+    inflateBackInit_
+    inflateSyncPoint
+    get_crc_table
+    zError
Index: /trunk/minix/lib/zlib-1.2.3/win32/zlib1.rc
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/win32/zlib1.rc	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/win32/zlib1.rc	(revision 9)
@@ -0,0 +1,39 @@
+#include <windows.h>
+
+#ifdef GCC_WINDRES
+VS_VERSION_INFO		VERSIONINFO
+#else
+VS_VERSION_INFO		VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
+#endif
+  FILEVERSION		1,2,2,0
+  PRODUCTVERSION	1,2,2,0
+  FILEFLAGSMASK		VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+  FILEFLAGS		1
+#else
+  FILEFLAGS		0
+#endif
+  FILEOS		VOS_DOS_WINDOWS32
+  FILETYPE		VFT_DLL
+  FILESUBTYPE		0	// not used
+BEGIN
+  BLOCK "StringFileInfo"
+  BEGIN
+    BLOCK "040904E4"
+    //language ID = U.S. English, char set = Windows, Multilingual
+    BEGIN
+      VALUE "FileDescription",	"zlib data compression library\0"
+      VALUE "FileVersion",	"1.2.3\0"
+      VALUE "InternalName",	"zlib1.dll\0"
+      VALUE "LegalCopyright",	"(C) 1995-2004 Jean-loup Gailly & Mark Adler\0"
+      VALUE "OriginalFilename",	"zlib1.dll\0"
+      VALUE "ProductName",	"zlib\0"
+      VALUE "ProductVersion",	"1.2.3\0"
+      VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
+    END
+  END
+  BLOCK "VarFileInfo"
+  BEGIN
+    VALUE "Translation", 0x0409, 1252
+  END
+END
Index: /trunk/minix/lib/zlib-1.2.3/zconf.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/zconf.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/zconf.h	(revision 9)
@@ -0,0 +1,332 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zconf.h,v 1.1 2005/09/23 22:39:00 beng Exp $ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+#  define deflateInit_          z_deflateInit_
+#  define deflate               z_deflate
+#  define deflateEnd            z_deflateEnd
+#  define inflateInit_          z_inflateInit_
+#  define inflate               z_inflate
+#  define inflateEnd            z_inflateEnd
+#  define deflateInit2_         z_deflateInit2_
+#  define deflateSetDictionary  z_deflateSetDictionary
+#  define deflateCopy           z_deflateCopy
+#  define deflateReset          z_deflateReset
+#  define deflateParams         z_deflateParams
+#  define deflateBound          z_deflateBound
+#  define deflatePrime          z_deflatePrime
+#  define inflateInit2_         z_inflateInit2_
+#  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateSync           z_inflateSync
+#  define inflateSyncPoint      z_inflateSyncPoint
+#  define inflateCopy           z_inflateCopy
+#  define inflateReset          z_inflateReset
+#  define inflateBack           z_inflateBack
+#  define inflateBackEnd        z_inflateBackEnd
+#  define compress              z_compress
+#  define compress2             z_compress2
+#  define compressBound         z_compressBound
+#  define uncompress            z_uncompress
+#  define adler32               z_adler32
+#  define crc32                 z_crc32
+#  define get_crc_table         z_get_crc_table
+#  define zError                z_zError
+
+#  define alloc_func            z_alloc_func
+#  define free_func             z_free_func
+#  define in_func               z_in_func
+#  define out_func              z_out_func
+#  define Byte                  z_Byte
+#  define uInt                  z_uInt
+#  define uLong                 z_uLong
+#  define Bytef                 z_Bytef
+#  define charf                 z_charf
+#  define intf                  z_intf
+#  define uIntf                 z_uIntf
+#  define uLongf                z_uLongf
+#  define voidpf                z_voidpf
+#  define voidp                 z_voidp
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+#  define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+#  define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#  ifndef WIN32
+#    define WIN32
+#  endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+#    ifndef SYS16BIT
+#      define SYS16BIT
+#    endif
+#  endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+#  ifndef STDC
+#    define STDC
+#  endif
+#  if __STDC_VERSION__ >= 199901L
+#    ifndef STDC99
+#      define STDC99
+#    endif
+#  endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+#  define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
+#  define STDC
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const       /* note: need a more gentle solution here */
+#  endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+#  define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+#  if defined(M_I86SM) || defined(M_I86MM)
+     /* MSC small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef _MSC_VER
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#  if (defined(__SMALL__) || defined(__MEDIUM__))
+     /* Turbo C small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef __BORLANDC__
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+   /* If building or using zlib as a DLL, define ZLIB_DLL.
+    * This is not mandatory, but it offers a little performance increase.
+    */
+#  ifdef ZLIB_DLL
+#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+#      ifdef ZLIB_INTERNAL
+#        define ZEXTERN extern __declspec(dllexport)
+#      else
+#        define ZEXTERN extern __declspec(dllimport)
+#      endif
+#    endif
+#  endif  /* ZLIB_DLL */
+   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+    * define ZLIB_WINAPI.
+    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+    */
+#  ifdef ZLIB_WINAPI
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+     /* No need for _export, use ZLIB.DEF instead. */
+     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+#    define ZEXPORT WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA WINAPIV
+#    else
+#      define ZEXPORTVA FAR CDECL
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  ifdef ZLIB_DLL
+#    ifdef ZLIB_INTERNAL
+#      define ZEXPORT   __declspec(dllexport)
+#      define ZEXPORTVA __declspec(dllexport)
+#    else
+#      define ZEXPORT   __declspec(dllimport)
+#      define ZEXPORTVA __declspec(dllimport)
+#    endif
+#  endif
+#endif
+
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void const *voidpc;
+   typedef void FAR   *voidpf;
+   typedef void       *voidp;
+#else
+   typedef Byte const *voidpc;
+   typedef Byte FAR   *voidpf;
+   typedef Byte       *voidp;
+#endif
+
+#if 0           /* HAVE_UNISTD_H -- this line is updated by ./configure */
+#  include <sys/types.h> /* for off_t */
+#  include <unistd.h>    /* for SEEK_* and off_t */
+#  ifdef VMS
+#    include <unixio.h>   /* for off_t */
+#  endif
+#  define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+#  define z_off_t long
+#endif
+
+#if defined(__OS400__)
+#  define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+#  define NO_vsnprintf
+#  ifdef FAR
+#    undef FAR
+#  endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+#   pragma map(deflateInit_,"DEIN")
+#   pragma map(deflateInit2_,"DEIN2")
+#   pragma map(deflateEnd,"DEEND")
+#   pragma map(deflateBound,"DEBND")
+#   pragma map(inflateInit_,"ININ")
+#   pragma map(inflateInit2_,"ININ2")
+#   pragma map(inflateEnd,"INEND")
+#   pragma map(inflateSync,"INSY")
+#   pragma map(inflateSetDictionary,"INSEDI")
+#   pragma map(compressBound,"CMBND")
+#   pragma map(inflate_table,"INTABL")
+#   pragma map(inflate_fast,"INFA")
+#   pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
Index: /trunk/minix/lib/zlib-1.2.3/zconf.in.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/zconf.in.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/zconf.in.h	(revision 9)
@@ -0,0 +1,332 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zconf.in.h,v 1.1 2005/09/23 22:39:00 beng Exp $ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+#  define deflateInit_          z_deflateInit_
+#  define deflate               z_deflate
+#  define deflateEnd            z_deflateEnd
+#  define inflateInit_          z_inflateInit_
+#  define inflate               z_inflate
+#  define inflateEnd            z_inflateEnd
+#  define deflateInit2_         z_deflateInit2_
+#  define deflateSetDictionary  z_deflateSetDictionary
+#  define deflateCopy           z_deflateCopy
+#  define deflateReset          z_deflateReset
+#  define deflateParams         z_deflateParams
+#  define deflateBound          z_deflateBound
+#  define deflatePrime          z_deflatePrime
+#  define inflateInit2_         z_inflateInit2_
+#  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateSync           z_inflateSync
+#  define inflateSyncPoint      z_inflateSyncPoint
+#  define inflateCopy           z_inflateCopy
+#  define inflateReset          z_inflateReset
+#  define inflateBack           z_inflateBack
+#  define inflateBackEnd        z_inflateBackEnd
+#  define compress              z_compress
+#  define compress2             z_compress2
+#  define compressBound         z_compressBound
+#  define uncompress            z_uncompress
+#  define adler32               z_adler32
+#  define crc32                 z_crc32
+#  define get_crc_table         z_get_crc_table
+#  define zError                z_zError
+
+#  define alloc_func            z_alloc_func
+#  define free_func             z_free_func
+#  define in_func               z_in_func
+#  define out_func              z_out_func
+#  define Byte                  z_Byte
+#  define uInt                  z_uInt
+#  define uLong                 z_uLong
+#  define Bytef                 z_Bytef
+#  define charf                 z_charf
+#  define intf                  z_intf
+#  define uIntf                 z_uIntf
+#  define uLongf                z_uLongf
+#  define voidpf                z_voidpf
+#  define voidp                 z_voidp
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+#  define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+#  define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#  ifndef WIN32
+#    define WIN32
+#  endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+#    ifndef SYS16BIT
+#      define SYS16BIT
+#    endif
+#  endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+#  ifndef STDC
+#    define STDC
+#  endif
+#  if __STDC_VERSION__ >= 199901L
+#    ifndef STDC99
+#      define STDC99
+#    endif
+#  endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+#  define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
+#  define STDC
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const       /* note: need a more gentle solution here */
+#  endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+#  define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+#  if defined(M_I86SM) || defined(M_I86MM)
+     /* MSC small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef _MSC_VER
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#  if (defined(__SMALL__) || defined(__MEDIUM__))
+     /* Turbo C small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef __BORLANDC__
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+   /* If building or using zlib as a DLL, define ZLIB_DLL.
+    * This is not mandatory, but it offers a little performance increase.
+    */
+#  ifdef ZLIB_DLL
+#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+#      ifdef ZLIB_INTERNAL
+#        define ZEXTERN extern __declspec(dllexport)
+#      else
+#        define ZEXTERN extern __declspec(dllimport)
+#      endif
+#    endif
+#  endif  /* ZLIB_DLL */
+   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+    * define ZLIB_WINAPI.
+    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+    */
+#  ifdef ZLIB_WINAPI
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+     /* No need for _export, use ZLIB.DEF instead. */
+     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+#    define ZEXPORT WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA WINAPIV
+#    else
+#      define ZEXPORTVA FAR CDECL
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  ifdef ZLIB_DLL
+#    ifdef ZLIB_INTERNAL
+#      define ZEXPORT   __declspec(dllexport)
+#      define ZEXPORTVA __declspec(dllexport)
+#    else
+#      define ZEXPORT   __declspec(dllimport)
+#      define ZEXPORTVA __declspec(dllimport)
+#    endif
+#  endif
+#endif
+
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void const *voidpc;
+   typedef void FAR   *voidpf;
+   typedef void       *voidp;
+#else
+   typedef Byte const *voidpc;
+   typedef Byte FAR   *voidpf;
+   typedef Byte       *voidp;
+#endif
+
+#if 0           /* HAVE_UNISTD_H -- this line is updated by ./configure */
+#  include <sys/types.h> /* for off_t */
+#  include <unistd.h>    /* for SEEK_* and off_t */
+#  ifdef VMS
+#    include <unixio.h>   /* for off_t */
+#  endif
+#  define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+#  define z_off_t long
+#endif
+
+#if defined(__OS400__)
+#  define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+#  define NO_vsnprintf
+#  ifdef FAR
+#    undef FAR
+#  endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+#   pragma map(deflateInit_,"DEIN")
+#   pragma map(deflateInit2_,"DEIN2")
+#   pragma map(deflateEnd,"DEEND")
+#   pragma map(deflateBound,"DEBND")
+#   pragma map(inflateInit_,"ININ")
+#   pragma map(inflateInit2_,"ININ2")
+#   pragma map(inflateEnd,"INEND")
+#   pragma map(inflateSync,"INSY")
+#   pragma map(inflateSetDictionary,"INSEDI")
+#   pragma map(compressBound,"CMBND")
+#   pragma map(inflate_table,"INTABL")
+#   pragma map(inflate_fast,"INFA")
+#   pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
Index: /trunk/minix/lib/zlib-1.2.3/zlib.3
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/zlib.3	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/zlib.3	(revision 9)
@@ -0,0 +1,159 @@
+.TH ZLIB 3 "18 July 2005"
+.SH NAME
+zlib \- compression/decompression library
+.SH SYNOPSIS
+[see
+.I zlib.h
+for full description]
+.SH DESCRIPTION
+The
+.I zlib
+library is a general purpose data compression library.
+The code is thread safe.
+It provides in-memory compression and decompression functions,
+including integrity checks of the uncompressed data.
+This version of the library supports only one compression method (deflation)
+but other algorithms will be added later
+and will have the same stream interface.
+.LP
+Compression can be done in a single step if the buffers are large enough
+(for example if an input file is mmap'ed),
+or can be done by repeated calls of the compression function.
+In the latter case,
+the application must provide more input and/or consume the output
+(providing more output space) before each call.
+.LP
+The library also supports reading and writing files in
+.IR gzip (1)
+(.gz) format
+with an interface similar to that of stdio.
+.LP
+The library does not install any signal handler.
+The decoder checks the consistency of the compressed data,
+so the library should never crash even in case of corrupted input.
+.LP
+All functions of the compression library are documented in the file
+.IR zlib.h .
+The distribution source includes examples of use of the library
+in the files
+.I example.c
+and
+.IR minigzip.c .
+.LP
+Changes to this version are documented in the file
+.I ChangeLog
+that accompanies the source,
+and are concerned primarily with bug fixes and portability enhancements.
+.LP
+A Java implementation of
+.I zlib
+is available in the Java Development Kit 1.1:
+.IP
+http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html
+.LP
+A Perl interface to
+.IR zlib ,
+written by Paul Marquess (pmqs@cpan.org),
+is available at CPAN (Comprehensive Perl Archive Network) sites,
+including:
+.IP
+http://www.cpan.org/modules/by-module/Compress/
+.LP
+A Python interface to
+.IR zlib ,
+written by A.M. Kuchling (amk@magnet.com),
+is available in Python 1.5 and later versions:
+.IP
+http://www.python.org/doc/lib/module-zlib.html
+.LP
+A
+.I zlib
+binding for
+.IR tcl (1),
+written by Andreas Kupries (a.kupries@westend.com),
+is availlable at:
+.IP
+http://www.westend.com/~kupries/doc/trf/man/man.html
+.LP
+An experimental package to read and write files in .zip format,
+written on top of
+.I zlib
+by Gilles Vollant (info@winimage.com),
+is available at:
+.IP
+http://www.winimage.com/zLibDll/unzip.html
+and also in the
+.I contrib/minizip
+directory of the main
+.I zlib
+web site.
+.SH "SEE ALSO"
+The
+.I zlib
+web site can be found at either of these locations:
+.IP
+http://www.zlib.org
+.br
+http://www.gzip.org/zlib/
+.LP
+The data format used by the zlib library is described by RFC
+(Request for Comments) 1950 to 1952 in the files:
+.IP
+http://www.ietf.org/rfc/rfc1950.txt (concerning zlib format)
+.br
+http://www.ietf.org/rfc/rfc1951.txt (concerning deflate format)
+.br
+http://www.ietf.org/rfc/rfc1952.txt (concerning gzip format)
+.LP
+These documents are also available in other formats from:
+.IP
+ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
+.LP
+Mark Nelson (markn@ieee.org) wrote an article about
+.I zlib
+for the Jan. 1997 issue of  Dr. Dobb's Journal;
+a copy of the article is available at:
+.IP
+http://dogma.net/markn/articles/zlibtool/zlibtool.htm
+.SH "REPORTING PROBLEMS"
+Before reporting a problem,
+please check the
+.I zlib
+web site to verify that you have the latest version of
+.IR zlib ;
+otherwise,
+obtain the latest version and see if the problem still exists.
+Please read the
+.I zlib
+FAQ at:
+.IP
+http://www.gzip.org/zlib/zlib_faq.html
+.LP
+before asking for help.
+Send questions and/or comments to zlib@gzip.org,
+or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
+.SH AUTHORS
+Version 1.2.3
+Copyright (C) 1995-2005 Jean-loup Gailly (jloup@gzip.org)
+and Mark Adler (madler@alumni.caltech.edu).
+.LP
+This software is provided "as-is,"
+without any express or implied warranty.
+In no event will the authors be held liable for any damages
+arising from the use of this software.
+See the distribution directory with respect to requirements
+governing redistribution.
+The deflate format used by
+.I zlib
+was defined by Phil Katz.
+The deflate and
+.I zlib
+specifications were written by L. Peter Deutsch.
+Thanks to all the people who reported problems and suggested various
+improvements in
+.IR zlib ;
+who are too numerous to cite here.
+.LP
+UNIX manual page by R. P. C. Rodgers,
+U.S. National Library of Medicine (rodgers@nlm.nih.gov).
+.\" end of man page
Index: /trunk/minix/lib/zlib-1.2.3/zlib.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/zlib.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/zlib.h	(revision 9)
@@ -0,0 +1,1357 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.2.3, July 18th, 2005
+
+  Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.3"
+#define ZLIB_VERNUM 0x1230
+
+/*
+     The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed
+  data.  This version of the library supports only one compression method
+  (deflation) but other algorithms will be added later and will have the same
+  stream interface.
+
+     Compression can be done in a single step if the buffers are large
+  enough (for example if an input file is mmap'ed), or can be done by
+  repeated calls of the compression function.  In the latter case, the
+  application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+     The compressed data format used by default by the in-memory functions is
+  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+  around a deflate stream, which is itself documented in RFC 1951.
+
+     The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio using the functions that start
+  with "gz".  The gzip format is different from the zlib format.  gzip is a
+  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+     This library can optionally read and write gzip streams in memory as well.
+
+     The zlib format was designed to be compact and fast for use in memory
+  and on communications channels.  The gzip format was designed for single-
+  file compression on file systems, has a larger header than zlib to maintain
+  directory information, and uses a different, slower check method than zlib.
+
+     The library does not install any signal handler. The decoder checks
+  the consistency of the compressed data, so the library should never
+  crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    Bytef    *next_in;  /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total nb of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: binary or text */
+    uLong   adler;      /* adler32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+     gzip header information passed to and from zlib routines.  See RFC 1952
+  for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+    int     text;       /* true if compressed data believed to be text */
+    uLong   time;       /* modification time */
+    int     xflags;     /* extra flags (not used when writing a gzip file) */
+    int     os;         /* operating system */
+    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */
+    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */
+    uInt    extra_max;  /* space at extra (only when reading header) */
+    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */
+    uInt    name_max;   /* space at name (only when reading header) */
+    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */
+    uInt    comm_max;   /* space at comment (only when reading header) */
+    int     hcrc;       /* true if there was or will be a header crc */
+    int     done;       /* true when done reading gzip header (not used
+                           when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+   The application must update next_in and avail_in when avail_in has
+   dropped to zero. It must update next_out and avail_out when avail_out
+   has dropped to zero. The application must initialize zalloc, zfree and
+   opaque before calling the init function. All other fields are set by the
+   compression library and must not be updated by the application.
+
+   The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree. This can be useful for custom
+   memory management. The compression library attaches no meaning to the
+   opaque value.
+
+   zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+   On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+   pointers returned by zalloc for objects of exactly 65536 bytes *must*
+   have their offset normalized to zero. The default allocation function
+   provided by this library ensures this (see zutil.c). To reduce memory
+   requirements and avoid any allocation of 64K objects, at the expense of
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+   The fields total_in and total_out can be used for statistics or
+   progress reports. After compression, total_in holds the total size of
+   the uncompressed data and may be saved for use in the decompressor
+   (particularly if the decompressor wants to decompress everything in
+   a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+#define Z_BLOCK         5
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_RLE                 3
+#define Z_FIXED               4
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_TEXT     1
+#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+                        /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is
+   not compatible with the zlib.h header file used by the application.
+   This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression. The fields
+   zalloc, zfree and opaque must be initialized before by the caller.
+   If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+   use default allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at
+   all (the input data is simply copied a block at a time).
+   Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+   compression (currently equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).
+   msg is set to null if there is no error message.  deflateInit does not
+   perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may introduce some
+  output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows. deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly. This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).
+    Some output may be provided even if flush is not set.
+
+  Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating avail_in or avail_out accordingly; avail_out
+  should never be zero before the call. The application can consume the
+  compressed output when it wants, for example when the output buffer is full
+  (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+  and with zero avail_out, it must be called again after making room in the
+  output buffer because there might be more output pending.
+
+    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+  decide how much data to accumualte before producing output, in order to
+  maximize compression.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far. (In particular
+  avail_in is zero after the call if enough output space has been provided
+  before the call.)  Flushing may degrade compression for some compression
+  algorithms and so it should be used only when necessary.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+  compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+  avail_out is greater than six to avoid repeated flush markers due to
+  avail_out == 0 on return.
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there
+  was enough output space; if deflate returns with Z_OK, this function must be
+  called again with Z_FINISH and more output space (updated avail_out) but no
+  more input data, until it returns with Z_STREAM_END or an error. After
+  deflate has returned Z_STREAM_END, the only possible operations on the
+  stream are deflateReset or deflateEnd.
+
+    Z_FINISH can be used immediately after deflateInit if all the compression
+  is to be done in a single step. In this case, avail_out must be at least
+  the value returned by deflateBound (see below). If deflate does not return
+  Z_STREAM_END, then it must be called again as described above.
+
+    deflate() sets strm->adler to the adler32 checksum of all input read
+  so far (that is, total_in bytes).
+
+    deflate() may update strm->data_type if it can make a good guess about
+  the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered
+  binary. This field is only for information purposes and does not affect
+  the compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
+  fatal, and deflate() can be called again with more input and more output
+  space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded). In the error case,
+   msg may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression. The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+   value depends on the compression method), inflateInit determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly; otherwise the allocation will be deferred to the first call of
+   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+   use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller.  msg is set to null if there is no error
+   message. inflateInit does not perform any decompression apart from reading
+   the zlib header if present: this will be done by inflate().  (So next_in and
+   avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+  The detailed semantics are as follows. inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing
+    will resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there
+    is no more input data or no more space in the output buffer (see below
+    about the flush parameter).
+
+  Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating the next_* and avail_* values accordingly.
+  The application can consume the uncompressed output when it wants, for
+  example when the output buffer is full (avail_out == 0), or after each
+  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+  must be called again after making room in the output buffer because there
+  might be more output pending.
+
+    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
+  Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
+  output as possible to the output buffer. Z_BLOCK requests that inflate() stop
+  if and when it gets to the next deflate block boundary. When decoding the
+  zlib or gzip format, this will cause inflate() to return immediately after
+  the header and before the first block. When doing a raw inflate, inflate()
+  will go ahead and process the first block, and will return when it gets to
+  the end of that block, or when it runs out of data.
+
+    The Z_BLOCK option assists in appending to or combining deflate streams.
+  Also to assist in this, on return inflate() will set strm->data_type to the
+  number of unused bits in the last byte taken from strm->next_in, plus 64
+  if inflate() is currently decoding the last block in the deflate stream,
+  plus 128 if inflate() returned immediately after decoding an end-of-block
+  code or decoding the complete header up to just before the first byte of the
+  deflate stream. The end-of-block will not be indicated until all of the
+  uncompressed data from that block has been written to strm->next_out.  The
+  number of unused bits may in general be greater than seven, except when
+  bit 7 of data_type is set, in which case the number of unused bits will be
+  less than eight.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error. However if all decompression is to be performed in a single step
+  (a single call of inflate), the parameter flush should be set to
+  Z_FINISH. In this case all pending input is processed and all pending
+  output is flushed; avail_out must be large enough to hold all the
+  uncompressed data. (The size of the uncompressed data may have been saved
+  by the compressor for this purpose.) The next operation on this stream must
+  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+  is never required, but can be used to inform inflate that a faster approach
+  may be used for the single inflate() call.
+
+     In this implementation, inflate() always flushes as much output as
+  possible to the output buffer, and always uses the faster approach on the
+  first call. So the only effect of the flush parameter in this implementation
+  is on the return value of inflate(), as noted below, or when it returns early
+  because Z_BLOCK is used.
+
+     If a preset dictionary is needed after this call (see inflateSetDictionary
+  below), inflate sets strm->adler to the adler32 checksum of the dictionary
+  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+  strm->adler to the adler32 checksum of all output produced so far (that is,
+  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+  below. At the end of the stream, inflate() checks that its computed adler32
+  checksum is equal to that saved by the compressor and returns Z_STREAM_END
+  only if the checksum is correct.
+
+    inflate() will decompress and check either zlib-wrapped or gzip-wrapped
+  deflate data.  The header type is detected automatically.  Any information
+  contained in the gzip header is not retained, so applications that need that
+  information should instead use raw inflate, see inflateInit2() below, or
+  inflateBack() and perform their own processing of the gzip header and
+  trailer.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect check
+  value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+  if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+  Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+  output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+  inflate() can be called again with more input and more output space to
+  continue decompressing. If Z_DATA_ERROR is returned, the application may then
+  call inflateSync() to look for a good compression block if a partial recovery
+  of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent. In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options. The
+   fields next_in, zalloc, zfree and opaque must be initialized before by
+   the caller.
+
+     The method parameter is the compression method. It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer). It should be in the range 8..15 for this
+   version of the library. Larger values of this parameter result in better
+   compression at the expense of memory usage. The default value is 15 if
+   deflateInit is used instead.
+
+     windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+   determines the window size. deflate() will then generate raw deflate data
+   with no zlib header or trailer, and will not compute an adler32 check value.
+
+     windowBits can also be greater than 15 for optional gzip encoding. Add
+   16 to windowBits to write a simple gzip header and trailer around the
+   compressed data instead of a zlib wrapper. The gzip header will have no
+   file name, no extra data, no comment, no modification time (set to zero),
+   no header crc, and the operating system will be set to 255 (unknown).  If a
+   gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state. memLevel=1 uses minimum memory but
+   is slow and reduces compression ratio; memLevel=9 uses maximum memory
+   for optimal speed. The default value is 8. See zconf.h for total memory
+   usage as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm. Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match), or Z_RLE to limit match distances to one (run-length
+   encoding). Filtered data consists mostly of small values with a somewhat
+   random distribution. In this case, the compression algorithm is tuned to
+   compress them better. The effect of Z_FILTERED is to force more Huffman
+   coding and less string matching; it is somewhat intermediate between
+   Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
+   Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
+   parameter only affects the compression ratio but not the correctness of the
+   compressed output even if it is not set appropriately.  Z_FIXED prevents the
+   use of dynamic Huffman codes, allowing for a simpler decoder for special
+   applications.
+
+      deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+   method). msg is set to null if there is no error message.  deflateInit2 does
+   not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output. This function must be called
+   immediately after deflateInit, deflateInit2 or deflateReset, before any
+   call of deflate. The compressor and decompressor must use exactly the same
+   dictionary (see inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary. Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size in
+   deflate or deflate2. Thus the strings most likely to be useful should be
+   put at the end of the dictionary, not at the front. In addition, the
+   current implementation of deflate will use at most the window size minus
+   262 bytes of the provided dictionary.
+
+     Upon return of this function, strm->adler is set to the adler32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor. (The adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.) If a raw deflate was requested, then the
+   adler32 value is not computed and strm->adler is not set.
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if the compression method is bsort). deflateSetDictionary does not
+   perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter. The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and
+   can consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being NULL). msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to deflateEnd followed by deflateInit,
+   but does not free and reallocate all the internal compression state.
+   The stream will keep the same compression level and any other attributes
+   that may have been set by deflateInit2.
+
+      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+                                      int level,
+                                      int strategy));
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different
+   strategy. If the compression level is changed, the input available so far
+   is compressed with the old level (and may be flushed); the new level will
+   take effect only at the next call of deflate().
+
+     Before the call of deflateParams, the stream state must be set as for
+   a call of deflate(), since the currently available input may have to
+   be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+   if strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+                                    int good_length,
+                                    int max_lazy,
+                                    int nice_length,
+                                    int max_chain));
+/*
+     Fine tune deflate's internal compression parameters.  This should only be
+   used by someone who understands the algorithm used by zlib's deflate for
+   searching for the best matching string, and even then only by the most
+   fanatic optimizer trying to squeeze out the last compressed bit for their
+   specific input data.  Read the deflate.c source code for the meaning of the
+   max_lazy, good_length, nice_length, and max_chain parameters.
+
+     deflateTune() can be called after deflateInit() or deflateInit2(), and
+   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+                                       uLong sourceLen));
+/*
+     deflateBound() returns an upper bound on the compressed size after
+   deflation of sourceLen bytes.  It must be called after deflateInit()
+   or deflateInit2().  This would be used to allocate an output buffer
+   for deflation in a single pass, and so would be called before deflate().
+*/
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     deflatePrime() inserts bits in the deflate output stream.  The intent
+  is that this function is used to start off the deflate output with the
+  bits leftover from a previous deflate stream when appending to it.  As such,
+  this function can only be used for raw deflate, and must be used before the
+  first deflate() call after a deflateInit2() or deflateReset().  bits must be
+  less than or equal to 16, and that many of the least significant bits of
+  value will be inserted in the output.
+
+      deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+      deflateSetHeader() provides gzip header information for when a gzip
+   stream is requested by deflateInit2().  deflateSetHeader() may be called
+   after deflateInit2() or deflateReset() and before the first call of
+   deflate().  The text, time, os, extra field, name, and comment information
+   in the provided gz_header structure are written to the gzip header (xflag is
+   ignored -- the extra flags are set according to the compression level).  The
+   caller must assure that, if not Z_NULL, name and comment are terminated with
+   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+   available there.  If hcrc is true, a gzip header crc is included.  Note that
+   the current versions of the command-line version of gzip (up through version
+   1.3.x) do not support header crc's, and will report that it is a "multi-part
+   gzip file" and give up.
+
+      If deflateSetHeader is not used, the default gzip header has text false,
+   the time set to zero, and os set to 255, with no extra, name, or comment
+   fields.  The gzip header is returned to the default state by deflateReset().
+
+      deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter. The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library. The default value is 15 if inflateInit is used
+   instead. windowBits must be greater than or equal to the windowBits value
+   provided to deflateInit2() while compressing, or it must be equal to 15 if
+   deflateInit2() was not used. If a compressed stream with a larger window
+   size is given as input, inflate() will return with the error code
+   Z_DATA_ERROR instead of trying to allocate a larger window.
+
+     windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+   determines the window size. inflate() will then process raw deflate data,
+   not looking for a zlib or gzip header, not generating a check value, and not
+   looking for any check values for comparison at the end of the stream. This
+   is for use with other formats that use the deflate compressed data format
+   such as zip.  Those formats provide their own check values. If a custom
+   format is developed using the raw deflate format for compressed data, it is
+   recommended that a check value such as an adler32 or a crc32 be applied to
+   the uncompressed data as is done in the zlib, gzip, and zip formats.  For
+   most applications, the zlib format should be used as is. Note that comments
+   above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+     windowBits can also be greater than 15 for optional gzip decoding. Add
+   32 to windowBits to enable zlib and gzip decoding with automatic header
+   detection, or add 16 to decode only the gzip format (the zlib format will
+   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is
+   a crc32 instead of an adler32.
+
+     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
+   is set to null if there is no error message.  inflateInit2 does not perform
+   any decompression apart from reading the zlib header if present: this will
+   be done by inflate(). (So next_in and avail_in may be modified, but next_out
+   and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence. This function must be called immediately after a call of inflate,
+   if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+   can be determined from the adler32 value returned by that call of inflate.
+   The compressor and decompressor must use exactly the same dictionary (see
+   deflateSetDictionary).  For raw inflate, this function can be called
+   immediately after inflateInit2() or inflateReset() and before any call of
+   inflate() to set the dictionary.  The application must insure that the
+   dictionary that was used for compression is provided.
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect adler32 value). inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+    Skips invalid compressed data until a full flush point (see above the
+  description of deflate with Z_FULL_FLUSH) can be found, or until all
+  available input is skipped. No output is provided.
+
+    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+  if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+  case, the application may save the current current value of total_in which
+  indicates where valid compressed data was found. In the error case, the
+  application may repeatedly call inflateSync, providing more input each time,
+  until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when randomly accessing a large stream.  The
+   first pass through the stream can periodically record the inflate state,
+   allowing restarting inflate at those points when randomly accessing the
+   stream.
+
+     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being NULL). msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.
+   The stream will keep attributes that may have been set by inflateInit2.
+
+      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     This function inserts bits in the inflate input stream.  The intent is
+  that this function is used to start inflating at a bit position in the
+  middle of a byte.  The provided bits will be used before any bytes are used
+  from next_in.  This function should only be used with raw inflate, and
+  should be used before the first inflate() call after inflateInit2() or
+  inflateReset().  bits must be less than or equal to 16, and that many of the
+  least significant bits of value will be inserted in the input.
+
+      inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+      inflateGetHeader() requests that gzip header information be stored in the
+   provided gz_header structure.  inflateGetHeader() may be called after
+   inflateInit2() or inflateReset(), and before the first call of inflate().
+   As inflate() processes the gzip stream, head->done is zero until the header
+   is completed, at which time head->done is set to one.  If a zlib stream is
+   being decoded, then head->done is set to -1 to indicate that there will be
+   no gzip header information forthcoming.  Note that Z_BLOCK can be used to
+   force inflate() to return immediately after header processing is complete
+   and before any actual data is decompressed.
+
+      The text, time, xflags, and os fields are filled in with the gzip header
+   contents.  hcrc is set to true if there is a header CRC.  (The header CRC
+   was valid if done is set to one.)  If extra is not Z_NULL, then extra_max
+   contains the maximum number of bytes to write to extra.  Once done is true,
+   extra_len contains the actual extra field length, and extra contains the
+   extra field, or that field truncated if extra_max is less than extra_len.
+   If name is not Z_NULL, then up to name_max characters are written there,
+   terminated with a zero unless the length is greater than name_max.  If
+   comment is not Z_NULL, then up to comm_max characters are written there,
+   terminated with a zero unless the length is greater than comm_max.  When
+   any of extra, name, or comment are not Z_NULL and the respective field is
+   not present in the header, then that field is set to Z_NULL to signal its
+   absence.  This allows the use of deflateSetHeader() with the returned
+   structure to duplicate the header.  However if those fields are set to
+   allocated memory, then the application will need to save those pointers
+   elsewhere so that they can be eventually freed.
+
+      If inflateGetHeader is not used, then the header information is simply
+   discarded.  The header is always checked for validity, including the header
+   CRC if present.  inflateReset() will reset the process to discard the header
+   information.  The application would need to call inflateGetHeader() again to
+   retrieve the header from the next gzip stream.
+
+      inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+                                        unsigned char FAR *window));
+
+     Initialize the internal stream state for decompression using inflateBack()
+   calls.  The fields zalloc, zfree and opaque in strm must be initialized
+   before the call.  If zalloc and zfree are Z_NULL, then the default library-
+   derived memory allocation routines are used.  windowBits is the base two
+   logarithm of the window size, in the range 8..15.  window is a caller
+   supplied buffer of that size.  Except for special applications where it is
+   assured that deflate was used with small window sizes, windowBits must be 15
+   and a 32K byte window must be supplied to be able to decompress general
+   deflate streams.
+
+     See inflateBack() for the usage of these routines.
+
+     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+   the paramaters are invalid, Z_MEM_ERROR if the internal state could not
+   be allocated, or Z_VERSION_ERROR if the version of the library does not
+   match the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+                                    in_func in, void FAR *in_desc,
+                                    out_func out, void FAR *out_desc));
+/*
+     inflateBack() does a raw inflate with a single call using a call-back
+   interface for input and output.  This is more efficient than inflate() for
+   file i/o applications in that it avoids copying between the output and the
+   sliding window by simply making the window itself the output buffer.  This
+   function trusts the application to not change the output buffer passed by
+   the output function, at least until inflateBack() returns.
+
+     inflateBackInit() must be called first to allocate the internal state
+   and to initialize the state with the user-provided window buffer.
+   inflateBack() may then be used multiple times to inflate a complete, raw
+   deflate stream with each call.  inflateBackEnd() is then called to free
+   the allocated state.
+
+     A raw deflate stream is one with no zlib or gzip header or trailer.
+   This routine would normally be used in a utility that reads zip or gzip
+   files and writes out uncompressed files.  The utility would decode the
+   header and process the trailer on its own, hence this routine expects
+   only the raw deflate stream to decompress.  This is different from the
+   normal behavior of inflate(), which expects either a zlib or gzip header and
+   trailer around the deflate stream.
+
+     inflateBack() uses two subroutines supplied by the caller that are then
+   called by inflateBack() for input and output.  inflateBack() calls those
+   routines until it reads a complete deflate stream and writes out all of the
+   uncompressed data, or until it encounters an error.  The function's
+   parameters and return types are defined above in the in_func and out_func
+   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the
+   number of bytes of provided input, and a pointer to that input in buf.  If
+   there is no input available, in() must return zero--buf is ignored in that
+   case--and inflateBack() will return a buffer error.  inflateBack() will call
+   out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].  out()
+   should return zero on success, or non-zero on failure.  If out() returns
+   non-zero, inflateBack() will return with an error.  Neither in() nor out()
+   are permitted to change the contents of the window provided to
+   inflateBackInit(), which is also the buffer that out() uses to write from.
+   The length written by out() will be at most the window size.  Any non-zero
+   amount of input may be provided by in().
+
+     For convenience, inflateBack() can be provided input on the first call by
+   setting strm->next_in and strm->avail_in.  If that input is exhausted, then
+   in() will be called.  Therefore strm->next_in must be initialized before
+   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called
+   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in
+   must also be initialized, and then if strm->avail_in is not zero, input will
+   initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+     The in_desc and out_desc parameters of inflateBack() is passed as the
+   first parameter of in() and out() respectively when they are called.  These
+   descriptors can be optionally used to pass any information that the caller-
+   supplied in() and out() functions need to do their job.
+
+     On return, inflateBack() will set strm->next_in and strm->avail_in to
+   pass back any unused input that was provided by the last in() call.  The
+   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+   if in() or out() returned an error, Z_DATA_ERROR if there was a format
+   error in the deflate stream (in which case strm->msg is set to indicate the
+   nature of the error), or Z_STREAM_ERROR if the stream was not properly
+   initialized.  In the case of Z_BUF_ERROR, an input or output error can be
+   distinguished using strm->next_in which will be Z_NULL only if in() returned
+   an error.  If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to
+   out() returning non-zero.  (in() will always be called before out(), so
+   strm->next_in is assured to be defined if out() returns non-zero.)  Note
+   that inflateBack() cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+     All memory allocated by inflateBackInit() is freed.
+
+     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+   state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+     1.0: size of uInt
+     3.2: size of uLong
+     5.4: size of voidpf (pointer)
+     7.6: size of z_off_t
+
+    Compiler, assembler, and debug options:
+     8: DEBUG
+     9: ASMV or ASMINF -- use ASM code
+     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+     11: 0 (reserved)
+
+    One-time table building (smaller code, but not thread-safe if true):
+     12: BUILDFIXED -- build static block decoding tables when needed
+     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+     14,15: 0 (reserved)
+
+    Library content (indicates missing functionality):
+     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+                          deflate code when not needed)
+     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+                    and decode gzip streams (to avoid linking crc code)
+     18-19: 0 (reserved)
+
+    Operation variations (changes in library functionality):
+     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+     21: FASTEST -- deflate algorithm with only one, lowest compression level
+     22,23: 0 (reserved)
+
+    The sprintf variant used by gzprintf (zero is best):
+     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+     26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+    Remainder:
+     27-31: 0 (reserved)
+ */
+
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the
+   basic stream-oriented functions. To simplify the interface, some
+   default options are assumed (compression level and memory usage,
+   standard memory allocation functions). The source code of these
+   utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
+                                 const Bytef *source, uLong sourceLen));
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be at least the value returned
+   by compressBound(sourceLen). Upon exit, destLen is the actual size of the
+   compressed buffer.
+     This function can be used to compress a whole file at once if the
+   input file is mmap'ed.
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
+                                  const Bytef *source, uLong sourceLen,
+                                  int level));
+/*
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least the value returned by
+   compressBound(sourceLen). Upon exit, destLen is the actual size of the
+   compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+     compressBound() returns an upper bound on the compressed size after
+   compress() or compress2() on sourceLen bytes.  It would be used before
+   a compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
+                                   const Bytef *source, uLong sourceLen));
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen  OF((const char *path, const char *mode));
+/*
+     Opens a gzip (.gz) file for reading or writing. The mode parameter
+   is as in fopen ("rb" or "wb") but can also include a compression level
+   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+   Huffman only compression as in "wb1h", or 'R' for run-length encoding
+   as in "wb1R". (See the description of deflateInit2 for more information
+   about the strategy parameter.)
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.
+
+     gzopen returns NULL if the file could not be opened or if there was
+   insufficient memory to allocate the (de)compression state; errno
+   can be checked to distinguish the two cases (if errno is zero, the
+   zlib error is Z_MEM_ERROR).  */
+
+ZEXTERN gzFile ZEXPORT gzdopen  OF((int fd, const char *mode));
+/*
+     gzdopen() associates a gzFile with the file descriptor fd.  File
+   descriptors are obtained from calls like open, dup, creat, pipe or
+   fileno (in the file has been previously opened with fopen).
+   The mode parameter is as in gzopen.
+     The next call of gzclose on the returned gzFile will also close the
+   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+   descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+     gzdopen returns NULL if there was insufficient memory to allocate
+   the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+     Dynamically update the compression level or strategy. See the description
+   of deflateInit2 for the meaning of these parameters.
+     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+   opened for writing.
+*/
+
+ZEXTERN int ZEXPORT    gzread  OF((gzFile file, voidp buf, unsigned len));
+/*
+     Reads the given number of uncompressed bytes from the compressed file.
+   If the input file was not in gzip format, gzread copies the given number
+   of bytes into the buffer.
+     gzread returns the number of uncompressed bytes actually read (0 for
+   end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT    gzwrite OF((gzFile file,
+                                   voidpc buf, unsigned len));
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes actually written
+   (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA   gzprintf OF((gzFile file, const char *format, ...));
+/*
+     Converts, formats, and writes the args to the compressed file under
+   control of the format string, as in fprintf. gzprintf returns the number of
+   uncompressed bytes actually written (0 in case of error).  The number of
+   uncompressed bytes written is limited to 4095. The caller should assure that
+   this limit is not exceeded. If it is exceeded, then gzprintf() will return
+   return an error (0) with nothing written. In this case, there may also be a
+   buffer overflow with unpredictable consequences, which is possible only if
+   zlib was compiled with the insecure functions sprintf() or vsprintf()
+   because the secure snprintf() or vsnprintf() functions were not available.
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+      Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+      gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+      Reads bytes from the compressed file until len-1 characters are read, or
+   a newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  The string is then terminated with a null
+   character.
+      gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT    gzputc OF((gzFile file, int c));
+/*
+      Writes c, converted to an unsigned char, into the compressed file.
+   gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT    gzgetc OF((gzFile file));
+/*
+      Reads one byte from the compressed file. gzgetc returns this byte
+   or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT    gzungetc OF((int c, gzFile file));
+/*
+      Push one character back onto the stream to be read again later.
+   Only one character of push-back is allowed.  gzungetc() returns the
+   character pushed, or -1 on failure.  gzungetc() will fail if a
+   character has been pushed but not read yet, or if c is -1. The pushed
+   character will be discarded if the stream is repositioned with gzseek()
+   or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT    gzflush OF((gzFile file, int flush));
+/*
+     Flushes all pending output into the compressed file. The parameter
+   flush is as in the deflate() function. The return value is the zlib
+   error number (see function gzerror below). gzflush returns Z_OK if
+   the flush parameter is Z_FINISH and all output could be flushed.
+     gzflush should be called only when strictly necessary because it can
+   degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT    gzseek OF((gzFile file,
+                                      z_off_t offset, int whence));
+/*
+      Sets the starting position for the next gzread or gzwrite on the
+   given compressed file. The offset represents a number of bytes in the
+   uncompressed data stream. The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow. If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+      gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+   gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+/*
+     Returns the starting position for the next gzread or gzwrite on the
+   given compressed file. This position represents a number of bytes in the
+   uncompressed data stream.
+
+   gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+     Returns 1 when EOF has previously been detected reading the given
+   input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+     Returns 1 if file is being read directly without decompression, otherwise
+   zero.
+*/
+
+ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
+/*
+     Flushes all pending output if necessary, closes the compressed file
+   and deallocates all the (de)compression state. The return value is the zlib
+   error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+     Returns the error message for the last error which occurred on the
+   given compressed file. errnum is set to zlib error number. If an
+   error occurred in the file system and not in the compression library,
+   errnum is set to Z_ERRNO and the application may consult errno
+   to get the exact error code.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+     Clears the error and end-of-file flags for file. This is analogous to the
+   clearerr() function in stdio. This is useful for continuing to read a gzip
+   file that is being written concurrently.
+*/
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the
+   compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+                                          z_off_t len2));
+/*
+     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
+   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
+   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
+*/
+
+ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
+/*
+     Update a running CRC-32 with the bytes buf[0..len-1] and return the
+   updated CRC-32. If buf is NULL, this function returns the required initial
+   value for the for the crc. Pre- and post-conditioning (one's complement) is
+   performed within this function so it shouldn't be done by the application.
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+/*
+     Combine two CRC-32 check values into one.  For two sequences of bytes,
+   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32
+   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+   len2.
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+                                         unsigned char FAR *window,
+                                         const char *version,
+                                         int stream_size));
+#define deflateInit(strm, level) \
+        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+        inflateBackInit_((strm), (windowBits), (window), \
+        ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+    struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char   * ZEXPORT zError           OF((int));
+ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table    OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
Index: /trunk/minix/lib/zlib-1.2.3/zutil.c
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/zutil.c	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/zutil.c	(revision 9)
@@ -0,0 +1,318 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zutil.c,v 1.1 2005/09/23 22:39:00 beng Exp $ */
+
+#include "zutil.h"
+
+#ifndef NO_DUMMY_DECL
+struct internal_state      {int dummy;}; /* for buggy compilers */
+#endif
+
+const char * const z_errmsg[10] = {
+"need dictionary",     /* Z_NEED_DICT       2  */
+"stream end",          /* Z_STREAM_END      1  */
+"",                    /* Z_OK              0  */
+"file error",          /* Z_ERRNO         (-1) */
+"stream error",        /* Z_STREAM_ERROR  (-2) */
+"data error",          /* Z_DATA_ERROR    (-3) */
+"insufficient memory", /* Z_MEM_ERROR     (-4) */
+"buffer error",        /* Z_BUF_ERROR     (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+
+const char * ZEXPORT zlibVersion()
+{
+    return ZLIB_VERSION;
+}
+
+uLong ZEXPORT zlibCompileFlags()
+{
+    uLong flags;
+
+    flags = 0;
+    switch (sizeof(uInt)) {
+    case 2:     break;
+    case 4:     flags += 1;     break;
+    case 8:     flags += 2;     break;
+    default:    flags += 3;
+    }
+    switch (sizeof(uLong)) {
+    case 2:     break;
+    case 4:     flags += 1 << 2;        break;
+    case 8:     flags += 2 << 2;        break;
+    default:    flags += 3 << 2;
+    }
+    switch (sizeof(voidpf)) {
+    case 2:     break;
+    case 4:     flags += 1 << 4;        break;
+    case 8:     flags += 2 << 4;        break;
+    default:    flags += 3 << 4;
+    }
+    switch (sizeof(z_off_t)) {
+    case 2:     break;
+    case 4:     flags += 1 << 6;        break;
+    case 8:     flags += 2 << 6;        break;
+    default:    flags += 3 << 6;
+    }
+#ifdef DEBUG
+    flags += 1 << 8;
+#endif
+#if defined(ASMV) || defined(ASMINF)
+    flags += 1 << 9;
+#endif
+#ifdef ZLIB_WINAPI
+    flags += 1 << 10;
+#endif
+#ifdef BUILDFIXED
+    flags += 1 << 12;
+#endif
+#ifdef DYNAMIC_CRC_TABLE
+    flags += 1 << 13;
+#endif
+#ifdef NO_GZCOMPRESS
+    flags += 1L << 16;
+#endif
+#ifdef NO_GZIP
+    flags += 1L << 17;
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+    flags += 1L << 20;
+#endif
+#ifdef FASTEST
+    flags += 1L << 21;
+#endif
+#ifdef STDC
+#  ifdef NO_vsnprintf
+        flags += 1L << 25;
+#    ifdef HAS_vsprintf_void
+        flags += 1L << 26;
+#    endif
+#  else
+#    ifdef HAS_vsnprintf_void
+        flags += 1L << 26;
+#    endif
+#  endif
+#else
+        flags += 1L << 24;
+#  ifdef NO_snprintf
+        flags += 1L << 25;
+#    ifdef HAS_sprintf_void
+        flags += 1L << 26;
+#    endif
+#  else
+#    ifdef HAS_snprintf_void
+        flags += 1L << 26;
+#    endif
+#  endif
+#endif
+    return flags;
+}
+
+#ifdef DEBUG
+
+#  ifndef verbose
+#    define verbose 0
+#  endif
+int z_verbose = verbose;
+
+void z_error (m)
+    char *m;
+{
+    fprintf(stderr, "%s\n", m);
+    exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(err)
+    int err;
+{
+    return ERR_MSG(err);
+}
+
+#if defined(_WIN32_WCE)
+    /* The Microsoft C Run-Time Library for Windows CE doesn't have
+     * errno.  We define it as a global variable to simplify porting.
+     * Its value is always 0 and should not be used.
+     */
+    int errno = 0;
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+    Bytef* dest;
+    const Bytef* source;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = *source++; /* ??? to be unrolled */
+    } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+    const Bytef* s1;
+    const Bytef* s2;
+    uInt  len;
+{
+    uInt j;
+
+    for (j = 0; j < len; j++) {
+        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+    }
+    return 0;
+}
+
+void zmemzero(dest, len)
+    Bytef* dest;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = 0;  /* ??? to be unrolled */
+    } while (--len != 0);
+}
+#endif
+
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+#  define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+    voidpf org_ptr;
+    voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+    voidpf buf = opaque; /* just to make some compilers happy */
+    ulg bsize = (ulg)items*size;
+
+    /* If we allocate less than 65520 bytes, we assume that farmalloc
+     * will return a usable pointer which doesn't have to be normalized.
+     */
+    if (bsize < 65520L) {
+        buf = farmalloc(bsize);
+        if (*(ush*)&buf != 0) return buf;
+    } else {
+        buf = farmalloc(bsize + 16L);
+    }
+    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+    table[next_ptr].org_ptr = buf;
+
+    /* Normalize the pointer to seg:0 */
+    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+    *(ush*)&buf = 0;
+    table[next_ptr++].new_ptr = buf;
+    return buf;
+}
+
+void  zcfree (voidpf opaque, voidpf ptr)
+{
+    int n;
+    if (*(ush*)&ptr != 0) { /* object < 64K */
+        farfree(ptr);
+        return;
+    }
+    /* Find the original pointer */
+    for (n = 0; n < next_ptr; n++) {
+        if (ptr != table[n].new_ptr) continue;
+
+        farfree(table[n].org_ptr);
+        while (++n < next_ptr) {
+            table[n-1] = table[n];
+        }
+        next_ptr--;
+        return;
+    }
+    ptr = opaque; /* just to make some compilers happy */
+    Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+#  define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+#  define _halloc  halloc
+#  define _hfree   hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    return _halloc((long)items, size);
+}
+
+void  zcfree (voidpf opaque, voidpf ptr)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp  malloc OF((uInt size));
+extern voidp  calloc OF((uInt items, uInt size));
+extern void   free   OF((voidpf ptr));
+#endif
+
+voidpf zcalloc (opaque, items, size)
+    voidpf opaque;
+    unsigned items;
+    unsigned size;
+{
+    if (opaque) items += size - size; /* make compiler happy */
+    return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+                              (voidpf)calloc(items, size);
+}
+
+void  zcfree (opaque, ptr)
+    voidpf opaque;
+    voidpf ptr;
+{
+    free(ptr);
+    if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
Index: /trunk/minix/lib/zlib-1.2.3/zutil.h
===================================================================
--- /trunk/minix/lib/zlib-1.2.3/zutil.h	(revision 9)
+++ /trunk/minix/lib/zlib-1.2.3/zutil.h	(revision 9)
@@ -0,0 +1,269 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: zutil.h,v 1.1 2005/09/23 22:39:00 beng Exp $ */
+
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+#ifdef STDC
+#  ifndef _WIN32_WCE
+#    include <stddef.h>
+#  endif
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+#   ifdef _WIN32_WCE
+      /* The Microsoft C Run-Time Library for Windows CE doesn't have
+       * errno.  We define it as a global variable to simplify porting.
+       * Its value is always 0 and should not be used.  We rename it to
+       * avoid conflict with other libraries that use the same workaround.
+       */
+#     define errno z_errno
+#   endif
+    extern int errno;
+#else
+#  ifndef _WIN32_WCE
+#    include <errno.h>
+#  endif
+#endif
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char  uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long  ulg;
+
+extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+  return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+        /* common constants */
+
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+        /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+#  define OS_CODE  0x00
+#  if defined(__TURBOC__) || defined(__BORLANDC__)
+#    if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+       /* Allow compilation with ANSI keywords only enabled */
+       void _Cdecl farfree( void *block );
+       void *_Cdecl farmalloc( unsigned long nbytes );
+#    else
+#      include <alloc.h>
+#    endif
+#  else /* MSC or DJGPP */
+#    include <malloc.h>
+#  endif
+#endif
+
+#ifdef AMIGA
+#  define OS_CODE  0x01
+#endif
+
+#if defined(VAXC) || defined(VMS)
+#  define OS_CODE  0x02
+#  define F_OPEN(name, mode) \
+     fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#if defined(ATARI) || defined(atarist)
+#  define OS_CODE  0x05
+#endif
+
+#ifdef OS2
+#  define OS_CODE  0x06
+#  ifdef M_I86
+     #include <malloc.h>
+#  endif
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+#  define OS_CODE  0x07
+#  if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+#    include <unix.h> /* for fdopen */
+#  else
+#    ifndef fdopen
+#      define fdopen(fd,mode) NULL /* No fdopen() */
+#    endif
+#  endif
+#endif
+
+#ifdef TOPS20
+#  define OS_CODE  0x0a
+#endif
+
+#ifdef WIN32
+#  ifndef __CYGWIN__  /* Cygwin is Unix, not Win32 */
+#    define OS_CODE  0x0b
+#  endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+#  define OS_CODE  0x0f
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+#  define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600))
+#  if defined(_WIN32_WCE)
+#    define fdopen(fd,mode) NULL /* No fdopen() */
+#    ifndef _PTRDIFF_T_DEFINED
+       typedef int ptrdiff_t;
+#      define _PTRDIFF_T_DEFINED
+#    endif
+#  else
+#    define fdopen(fd,type)  _fdopen(fd,type)
+#  endif
+#endif
+
+        /* common defaults */
+
+#ifndef OS_CODE
+#  define OS_CODE  0x03  /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+#  define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+         /* functions */
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+#  ifndef HAVE_VSNPRINTF
+#    define HAVE_VSNPRINTF
+#  endif
+#endif
+#if defined(__CYGWIN__)
+#  ifndef HAVE_VSNPRINTF
+#    define HAVE_VSNPRINTF
+#  endif
+#endif
+#ifndef HAVE_VSNPRINTF
+#  ifdef MSDOS
+     /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+        but for now we just assume it doesn't. */
+#    define NO_vsnprintf
+#  endif
+#  ifdef __TURBOC__
+#    define NO_vsnprintf
+#  endif
+#  ifdef WIN32
+     /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+#    if !defined(vsnprintf) && !defined(NO_vsnprintf)
+#      define vsnprintf _vsnprintf
+#    endif
+#  endif
+#  ifdef __SASC
+#    define NO_vsnprintf
+#  endif
+#endif
+#ifdef VMS
+#  define NO_vsnprintf
+#endif
+
+#if defined(pyr)
+#  define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+  * You may have to use the same strategy for Borland C (untested).
+  * The __SC__ check is for Symantec.
+  */
+#  define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+#  define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+#    define zmemcpy _fmemcpy
+#    define zmemcmp _fmemcmp
+#    define zmemzero(dest, len) _fmemset(dest, 0, len)
+#  else
+#    define zmemcpy memcpy
+#    define zmemcmp memcmp
+#    define zmemzero(dest, len) memset(dest, 0, len)
+#  endif
+#else
+   extern void zmemcpy  OF((Bytef* dest, const Bytef* source, uInt len));
+   extern int  zmemcmp  OF((const Bytef* s1, const Bytef* s2, uInt len));
+   extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  include <stdio.h>
+   extern int z_verbose;
+   extern void z_error    OF((char *m));
+#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
+#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
+#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+
+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+void   zcfree  OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+           (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* ZUTIL_H */
Index: /trunk/minix/man/Makefile
===================================================================
--- /trunk/minix/man/Makefile	(revision 9)
+++ /trunk/minix/man/Makefile	(revision 9)
@@ -0,0 +1,17 @@
+
+MAN=/usr/man
+
+all::
+
+clean::
+
+install::
+	-rm -rf $(MAN)
+	-mkdir $(MAN)
+	cpdir . $(MAN)
+	chown -R bin $(MAN)
+	chgrp -R operator $(MAN)
+	@rm -f $(MAN)/Makefile
+	find /usr/man -type f | xargs chmod 644
+	find /usr/man -type d | xargs chmod 755
+	makewhatis $(MAN)
Index: /trunk/minix/man/macros.9
===================================================================
--- /trunk/minix/man/macros.9	(revision 9)
+++ /trunk/minix/man/macros.9	(revision 9)
@@ -0,0 +1,1463 @@
+.\" Macro package for producing books (based on -ms)
+.nr PS 12
+.nr PZ 12
+.\"	RT -  reset everything to normal state
+.de RT
+.if !\\n(1T .BG
+.ce 0
+.if !\\n(IK .if !\\n(IF .if !\\n(IX .if !\\n(BE .di
+.ul 0
+.if \\n(QP \{\
+.	ll +\\n(QIu
+.	in -\\n(QIu
+.	nr QP -1\}
+.if \\n(NX<=1 .if \\n(AJ=0 .ll \\n(LLu
+.if \\n(IF=0 \{\
+.	ps \\n(PS
+.	if \\n(VS>=41 .vs \\n(VSu
+.	if \\n(VS<=40 .vs \\n(VSp\}
+.if \\n(IP .in -\\n(I\\n(IRu
+.if \\n(IP=0 .nr I0 \\n(PIu
+.if \\n(IP .nr IP -1
+.ft 1
+.bd 1
+.ta 5n 10n 15n 20n 25n 30n 35n 40n 45n 50n 55n 60n 65n 70n 75n 80n
+.fi
+..
+.	\"IZ - initialization
+.de IZ
+.nr TN 0
+.em EM
+.if n .ds [. [
+.if t .ds [. \s-2\v'-.4m'\f1
+.if n .ds .] ]
+.if t .ds .] \v'.4m'\s+2\fP
+.if n .ds [o ""
+.if n .ds [c ""
+.if t .ds [o ``
+.if t .ds [c ''
+.ch FO \\n(YYu
+.if \\n(FM=0 .nr FM 1i
+.nr YY -\\n(FMu
+.nr XX 0 1
+.nr IP 0
+.nr PI 5n
+.nr QI 5n
+.nr I0 \\n(PIu
+.nr PZ 12
+.nr VZ 13.8p
+.nr PS \n(PZ
+.nr VS \\n(VZu
+.if !\\n(PD .if n .nr PD 1v
+.if !\\n(PD .if t .nr PD 0.3v
+.nr ML 3v
+.ps \\n(PS
+.if \\n(VS>=41 .vs \\n(VSu
+.if \\n(VS<=40 .vs \\n(VSp
+.nr IR 0
+.nr TB 0
+.nr SJ \\n(.j
+.nr LL 6i
+.ll \\n(LLu
+.nr LT \\n(.l
+.lt \\n(LTu
+.ev 1
+.nr FL \\n(LLu*11u/12u
+.ll \\n(FLu
+.ps 10
+.vs 12p
+.ev
+.if \\*(CH .ds CH "\(hy \\\\n(PN \(hy
+.wh 0 NP
+.wh -\\n(FMu FO
+.ch FO 16i
+.wh -\\n(FMu FX
+.ch FO -\\n(FMu
+.if t .wh -\\n(FMu/2u BT
+.if n .wh -\\n(FMu/2u-1v BT
+..
+.	\"KS keep - for keep release features. As in IFM
+.de KS
+.nr KN \\n(.u
+.if \\n(IK=0 .if \\n(IF=0 .KQ
+.nr IK +1
+..
+.	\"KQ - real keep processor
+.de KQ
+.br
+.nr KI \\n(.i
+.ev 2
+.br
+.in \\n(KIu
+.ps \\n(PS
+.if \\n(VS>40 .vs \\n(VSu
+.if \\n(VS<=39 .vs \\n(VSp
+.ll \\n(LLu
+.lt \\n(LTu
+.if \\n(NX>1 .ll \\n(CWu
+.if \\n(NX>1 .lt \\n(CWu
+.di KK
+.nr TB 0
+.nr KV 0
+..
+.	\"KF - floating keep
+.de KF
+.nr KN \\n(.u
+.if !\\n(IK .FQ
+.nr IK +1
+..
+.	\"FQ real floating keep processor
+.de FQ
+.nr KI \\n(.i
+.ev 2
+.br
+.in \\n(KIu
+.ps \\n(PS
+.if \\n(VS>40 .vs \\n(VSu
+.if \\n(VS<=39 .vs \\n(VSp
+.ll \\n(LLu
+.lt \\n(LTu
+.if \\n(NX>1 .ll \\n(CWu
+.if \\n(NX>1 .lt \\n(CWu
+.di KK
+.nr TB 1
+.nr KV 0
+..
+.	\"KP - keep full page
+.de KP
+.nr KV 1
+..
+.	\"KE release - everything between keep and release is together
+.de KE
+.if \\n(IK .if !\\n(IK-1 .if \\n(IF=0 .RQ
+.if \\n(IK .nr IK -1
+..
+.	\"RQ real release
+.de RQ
+.br
+.di
+.nr NF 0
+.if \\n(dn-\\n(.t .nr NF 1
+.if \\n(TC .nr NF 1
+.if \\n(KV .nr NF 1 \" if KV on full page needed, doesn't fit
+.if \\n(NF .if !\\n(TB .sp 11i
+.if !\\n(NF .if \\n(TB .nr TB 0
+.nf
+.rs
+.nr TC 5
+.in 0
+.ls 1
+.if \\n(TB=0 .ev
+.if \\n(TB=0 .br
+.if \\n(TB=0 .ev 2
+.if \\n(TB=0 .KK
+.ls
+.ce 0
+.if \\n(TB=0 .rm KK
+.if \\n(TB .da KJ
+.if \\n(TB \!.KD \\n(dn \\n(KV
+.if \\n(TB .KK
+.if \\n(TB .di
+.nr TC \\n(TB
+.if \\n(KN .fi
+.in
+.ev
+..
+.de EQ  \"equation, breakout and display
+.nr EF \\n(.u
+.rm EE
+.nr LE 1	\" 1 is center
+.ds EL \\$1
+.if "\\$1"L" .ds EL \\$2
+.if "\\$1"L" .nr LE 0
+.if "\\$1"C" .ds EL \\$2
+.if "\\$1"I" .nr LE 0
+.if "\\$1"I" .ds EE \\h'|10n'
+.if "\\$1"I" .if !"\\$3"" .ds EE \\h'\\$3'
+.if "\\$1"I" .ds EL \\$2
+.if \\n(YE>0 .nf
+.di EZ
+..
+.de EN  \" end of a displayed equation
+.br
+.di
+.rm EZ
+.nr ZN \\n(dn
+.if \\n(ZN>0 .if \\n(YE=0 .LP
+.if \\n(ZN=0 .if !"\\*(EL"" .nr ZN 1
+.if "\\n(.z"" .if \\n(ZN>0 .if !\\n(nl=\\n(PE .if t .sp .5
+.if "\\n(.z"" .if \\n(ZN>0 .if !\\n(nl=\\n(PE .if n .sp 1
+.if !"\\n(.z"" .if \\n(ZN>0 .if !\\n(.d=\\n(PE .if t .sp .5
+.if !"\\n(.z"" .if \\n(ZN>0 .if !\\n(.d=\\n(PE .if n .sp 1
+'pc
+.if \\n(BD>0 .nr LE 0 \" can't mean centering in this case.
+.if \\n(MK>0 .if \\n(LE=1 .ds EE \\h'|10n'
+.if \\n(MK>0 .nr LE 0 \" don't center if mark/lineup
+'lt \\n(.lu
+.if \\n(EP=0 .if \\n(ZN>0 .if \\n(LE>0 .tl \(ts\(ts\\*(10\(ts\\*(EL\(ts
+.if \\n(EP=0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD=0 .tl \(ts\\*(EE\\*(10\(ts\(ts\\*(EL\(ts
+.if \\n(EP=0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD>0 .if \\n(BD<\\w\(ts\\*(10\(ts .nr BD \\w\(ts\\*(10\(ts
+.if \\n(EP=0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD>0 \!\\*(10\\t\\*(EL
+.if \\n(EP>0 .if \\n(ZN>0 .if \\n(LE>0 .tl \(ts\\*(EL\(ts\\*(10\(ts\(ts
+.if \\n(EP>0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD=0 .tl \(ts\\*(EL\\*(EE\\*(10\(ts\(ts\(ts
+.if \\n(EP>0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD>0 .if \\n(BD<\\w\(ts\\*(10\(ts .nr BD \\w\(ts\\*(10\(ts
+.if \\n(EP>0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD>0 \!\\h'-\\\\n(.iu'\\*(EL\\h'|0'\\*(10
+.\".di EZ \" GCOS patch
+.\"\\*(10 \" GCOS patch
+.\".br \" GCOS patch
+.\".di \" GCOS patch
+.\".rm EZ \" GCOS patch
+'lt \\n(LLu
+'pc %
+.if \\n(YE>0 .if \\n(EF>0 .fi
+.rm EL 10 11 12 13 14 15 16 17 18 19 20 21 22 23
+.rr 10 11 12 13 14 15 16 17 18 19 20 21 22 23
+.if \\n(ZN>0 .if t .sp .5
+.if \\n(ZN>0 .if n .sp
+.if "\\n(.z"" .nr PE \\n(nl
+.if !"\\n(.z"" .nr PE \\n(.d
+.nr z 72-((\\n(nl-\\n(HM)%72)
+.if \\n(nl<\\n(HM .nr z 0
+.if \\nz>0 .if \\nz<60 .sp \\nzu  \"force post equation text to whole line
+.if \\nz>59 .if \\nz<72 .sp \\nzu-72u   \"move backwards a fraction of a pica
+..
+.de ME
+.nr SJ \\n(.j
+.if \\n(LL>0 .nr LT \\n(LL
+.nr YE 1
+.if \\n(PO=0 .nr PO \\n(.o
+.if \\n(mo-0 .ds MO January
+.if \\n(mo-1 .ds MO February
+.if \\n(mo-2 .ds MO March
+.if \\n(mo-3 .ds MO April
+.if \\n(mo-4 .ds MO May
+.if \\n(mo-5 .ds MO June
+.if \\n(mo-6 .ds MO July
+.if \\n(mo-7 .ds MO August
+.if \\n(mo-8 .ds MO September
+.if \\n(mo-9 .ds MO October
+.if \\n(mo-10 .ds MO November
+.if \\n(mo-11 .ds MO December
+.if \\n(dw-0 .ds DW Sunday
+.if \\n(dw-1 .ds DW Monday
+.if \\n(dw-2 .ds DW Tuesday
+.if \\n(dw-3 .ds DW Wednesday
+.if \\n(dw-4 .ds DW Thursday
+.if \\n(dw-5 .ds DW Friday
+.if \\n(dw-6 .ds DW Saturday
+.if "\\*(DY"" .ds DY \\*(MO \\n(dy, 19\\n(yr
+.if "\\*(CF"" .if n .ds CF "\\*(DY
+..
+.	\"EM end up macro - process left over keep-release
+.de EM
+.br
+.if \\n(TB=0 .if t .wh -1p CM
+.if \\n(TB \&\c
+.if \\n(TB 'bp
+.if \\n(TB .NP
+.if \\n(TB .ch CM 160
+..
+.	\"NP new page
+.de NP
+.if \\n(FM+\\n(HM>=\\n(.p .tm Margins bigger than page length.
+.if \\n(FM+\\n(HM>=\\n(.p .ab
+.if \\n(FM+\\n(HM>=\\n(.p .ex
+.nr PX \\n(.s
+.nr PF \\n(.f
+.nr PV \\n(.v
+.if t .CM
+.if \\n(HM=0 .nr HM 1i
+'sp \\n(HMu/2u
+.lt \\n(LTu
+.ps \\n(PS
+.vs \\n(PS+2
+.ft 1
+.if \\n(PO>0 .po \\n(POu
+.PT
+.ps \\n(PX
+.vs \\n(PVu
+.ft \\n(PF
+'sp |\\n(HMu
+.nr XX 0 1
+.nr YY 0-\\n(FMu
+.ch FO 16i
+.ch FX 17i
+.ch FO \\n(.pu-\\n(FMu
+.ch FX \\n(.pu-\\n(FMu
+.if \\n(MF .FV
+.nr MF 0
+.mk
+.os
+.ev 1
+.if \\n(TD=0 .if \\n(TC<5  .XK
+.nr TC 0
+.ns
+.ev
+.nr TQ \\n(.i
+.nr TK \\n(.u
+.if \\n(IT>0 \{\
+.	in 0
+.	nf
+.	TT
+.	in \\n(TQu
+.	if \\n(TK .fi\
+\}
+.mk #T
+.if t .if \\n(.o+\\n(LL>7.75i .tm Offset (\\n(.o) + line length (\\n(LL) exceeds 7.75 inches, too wide
+..
+.de XK
+.nr TD 1
+.nf
+.ls 1
+.in 0
+.rn KJ KL
+.KL
+.rm KL
+.if "\\n(.z"KJ" .di
+.nr TB 0
+.if "\\n(.z"KJ" .nr TB 1
+.br
+.in
+.ls
+.fi
+.if (\\n(nl+1v)>(\\n(.p-\\n(FM) .if \\n(NX>1 .RC
+.if (\\n(nl+1v)>(\\n(.p-\\n(FM) .if \\n(NX<1 .bp
+.nr TD 0
+..
+.de KD
+.nr KM 0
+.if "\\n(.z"" .if \\$2>0 .if \\n(nl>\\n(HM .if (\\n(nl+1v)<(\\n(.p-\\n(FM) .di KJ
+.if "\\n(.z"" .if \\n(nl>\\n(HM .if \\$2>0 .sp 15i \" full page figure must have new page
+.if "\\n(.z"" .if \\n(nl>\\n(HM .if \\$2=0 .if (\\n(nl+1v)>(\\n(.p-\\n(FM) .sp 15i
+.if "\\n(.z"KJ" .nr KM 1 \" KM is 1 if in a rediversion of keeps
+.if \\n(KM>0 \!.KD \\$1 \\$2
+.nr KR \\n(.t
+.if \\n(nl<=\\n(HM .nr KR 32767
+.if \\n(KM=0 .if \\n(KR<\\$1 .di KJ
+.if \\n(KM=0 .if \\n(KR<\\$1 .nr KM 1
+.if \\n(KM=0 .if \\$2>0 .if (\\n(nl+1v)>(\\n(.p-\\n(FM) .sp 15i
+.rs
+.if \\n(KM=0 .if \\$2>0 .sp \\n(.tu-\\$1u
+..
+.de PT
+.lt \\n(LLu
+.pc %
+.nr PN \\n%
+....if \\n%-1 .tl '\\*(LH'\\*(CH'\\*(RH'
+.lt \\n(.lu
+..
+.	\"FO - footer of page
+.de FO
+.rn FO FZ
+.if \\n(K1>0 .tm This memo has a multi-page cover sheet.  You are
+.if \\n(K1>0 .tm rebuked in the name of the Committee on Technical Memoranda.
+.if \\n(IT>0 .nr T. 1
+.if \\n(IT>0 .if \\n(FC=0  .T# 1
+.if \\n(IT>0 .br
+.nr FC +1
+.if \\n(NX<2 .nr WF 0
+.nr dn 0
+.if \\n(FC<=1 .if \\n(XX .XF
+.rn FZ FO
+.nr MF 0
+.if \\n(dn  .nr MF 1
+.if !\\n(WF .nr YY 0-\\n(FMu
+.if !\\n(WF .ch FO \\n(YYu
+.if !\\n(dn .nr WF 0
+.if \\n(FC<=1 .if \\n(XX=0  .if \\n(NX>1 .RC
+.nr x 7176u-\\n(.d
+.if \nL=1 .if \\n(FC<=1 .if \\n(XX=0  .if \\n(NX<1 'tm Chap=\\na  page=\\n%   short=\\nx    
+.if \\n(FC<=1 .if \\n(XX=0  .if \\n(NX<1 'bp
+.nr FC -1
+.if \\n(ML>0 .ne \\n(MLu
+..
+.	\"2C - begin double column
+.de 2C
+.MC \" default MC is double column
+..
+.de MC \" multiple columns- arg is line length
+.nr L1 \\n(LL*7/15
+.if \\n(.$>0 .nr L1 \\$1n
+.nr GW 0-1
+.if \\n(.$>1 .nr GW \\$1n
+.nr NQ \\n(LL/\\n(L1
+.if \\n(NQ<1 .nr NQ 1
+.if \\n(NQ>2 .if (\\n(LL%\\n(L1)=0 .nr NQ -1
+.if \\n(1T=0 \{\
+.	BG
+.	if n .sp 4
+.	if t .sp 2\}
+.if \\n(NX=0 .nr NX 1
+.if !\\n(NX=\\n(NQ \{\
+.	RT
+.	if \\n(NX>1 .bp
+.	mk
+.	nr NC 1
+.	po \\n(POu\}
+.if \\n(NQ>1 .hy 14
+.nr NX \\n(NQ
+.nr CW \\n(L1
+.ll \\n(CWu
+.nr FL \\n(CWu*11u/12u
+.if \\n(NX>1 .nr GW (\\n(LL-(\\n(NX*\\n(CW))/(\\n(NX-1)
+.nr RO \\n(CW+\\n(GW
+.ns
+..
+.de RC
+.ie \\n(NC>=\\n(NX .C2
+.el .C1
+..
+.de C1
+.rt
+.po +\\n(ROu
+.nr NC +1
+.if \\n(NC>\\n(NX .nr NC 1
+.nr XX 0 1
+.if \\n(MF .FV
+.ch FX \\n(.pu-\\n(FMu
+.ev 1
+.if \\n(TB .XK
+.nr TC 0
+.ev
+.nr TQ \\n(.i
+.if \\n(IT>0 .in 0
+.if \\n(IT>0 .TT
+.if \\n(IT>0 .in \\n(TQu
+.mk #T
+.ns
+..
+.de C2
+.po \\n(POu
+.nr NC +1
+.if \\n(NC>\\n(NX .nr NC 1
+'bp
+..
+.	\"1C - return to single column format
+.de 1C
+.MC \\n(LLu
+.hy 14
+..
+.	\".de R3
+.	\".pl 102
+.	\".nr LT \\n(.l
+.	\"..
+.de BT
+.nr PX \\n(.s
+.nr PF \\n(.f
+.ft 1
+.ps \\n(PS
+'lt \\n(LTu
+.po \\n(POu
+.if \\n%>0 .tl '\\*(LF'\\*(CF'\\*(RF'
+.ft \\n(PF
+.ps \\n(PX
+..
+.	\"PP - paragraph
+.de PP
+.RT
+.if \\n(1T .sp \\n(PDu
+.ti +\\n(PIu
+..
+.	\"SH - (unnumbered) section heading
+.de SH
+.ti \\n(.iu
+.RT
+.if \\n(1T .sp 1
+.if !\\n(1T .BG
+.RT
+.ne 4
+.ft 3
+..
+.	\"NH - numbered heading
+.de NH
+.RT
+.if \\n(1T .sp 1
+.if !\\n(1T .BG
+.RT
+.ne 4
+.ft 3
+.nr NS \\$1
+.if !\\n(.$ .nr NS 1
+.if !\\n(NS .nr NS 1
+.nr H\\n(NS +1
+.if !\\n(NS-4 .nr H5 0
+.if !\\n(NS-3 .nr H4 0
+.if !\\n(NS-2 .nr H3 0
+.if !\\n(NS-1 .nr H2 0
+.if !\\$1 .if \\n(.$ .nr H1 1
+.ds SN \\n(H1.
+.if \\na=0 .ds SN \\*(CN.
+.ti \\n(.iu
+.if \\n(NS-1 .as SN \\n(H2.
+.if \\n(NS-2 .as SN \\n(H3.
+.if \\n(NS-3 .as SN \\n(H4.
+.if \\n(NS-4 .as SN \\n(H5.
+\\*(SN
+..
+.	\"BG - begin, execute at first PP
+.de BG
+.br
+.ME
+.rm ME
+.di
+.ce 0
+.nr KI 0
+.hy 14
+.nr 1T 1
+.S\\n(ST
+.rm S0
+.rm S1
+.rm S2
+.rm S3
+.rm OD
+.rm OK
+.rm TX
+.rm AX
+.rm WT
+.rm CS
+.rm TM
+.rm IM
+.rm MF
+.rm MR
+.rm RP
+.rm I1
+.rm I2
+.rm I3
+.rm I4
+.rm I5
+.rm CB
+.rm E1
+.rm E2
+.de TL
+.ft 3
+.sp
+.if n .ul 100
+.ce 100
+.ps +2
+\\..
+.de AU
+.ft 2
+.if n .ul 0
+.ce 100
+.sp
+.NL
+\\..
+.de AI
+.ft 1
+.ce 100
+.if n .ul 0
+.if n .sp
+.if t .sp .5
+.NL
+\\..
+.RA
+.rm RA
+.rn FJ FS
+.rn FK FE
+.nf
+.ev 1
+.ps \\n(PS-2
+.vs \\n(.s+2p
+.ev
+.if \\n(KG=0 .nr FP 0 
+.if \\n(GA>1 .if \\n(KG=0 .nr GA 0 \" next UNIX must be flagged.
+.nr KG 0 
+.if \\n(FP>0 .FS
+.if \\n(FP>0 .FG
+.if \\n(FP>0 .FE
+.br
+.if \\n(TV>0 .if n .sp 2
+.if \\n(TV>0 .if t .sp 1
+.fi
+.ll \\n(LLu
+..
+.de RA \"redefine abstract macros
+.de AB
+.br
+.if !\\n(1T .BG
+.ce 1
+.sp 1
+.if \\n(.$=0 ABSTRACT
+.if \\n(.$>0 .if !"\\$1"-" .if !"\\$1"no"  \\$1
+.if \\n(.$=0 .sp
+.if \\n(.$>0 .if !"\\$1"-" .if !"\\$1"no" .sp
+.sp 1
+.nr AJ 1
+.in +\\n(.lu/12u
+.ll -\\n(.lu/12u
+.RT
+\\..
+.de AE
+.nr AJ 0
+.br
+.in 0
+.ll \\n(LLu
+.if \\n(VS>=41 .vs \\n(VSu
+.if \\n(VS<=40 .vs \\n(VSp
+\\..
+..
+.	\"IP - indented paragraph
+.de IP
+.RT
+.if !\\n(IP .nr IP +1
+.sp \\n(PDu
+.if \\n(.$-1 .nr I\\n(IR \\$2n
+.in +\\n(I\\n(IRu
+.nr TY \\n(TZ-\\n(.i
+.ta \\n(I\\n(IRu \\n(TYuR
+.if \\n(.$>0 \{\
+.ti -\\n(I\\n(IRu
+\&\\$1\t\c\}
+..
+.	\"LP - left aligned (block) paragraph
+.de LP
+.ti \\n(.iu
+.RT
+.if \\n(1T .sp \\n(PDu
+..
+.de QP
+.ti \\n(.iu
+.RT
+.if \\n(1T .sp \\n(PDu
+.ne 1.1
+.nr QP 1
+.in +\\n(QIu
+.ll -\\n(QIu
+.ti \\n(.iu
+..
+.	\"IE - synonym for .LP
+.de IE
+.LP
+..
+.	\"LB - label paragraph
+.de LB
+.in +\\n(I\\n(IRu
+.ta \\n(I\\n(IRu
+.if \\n(.$ .ti -\\n(I\\n(IRu
+.if \\n(.$ \&\\$1\t\c
+..
+.de XP
+.RT
+.if !\\n(IP .nr IP +1
+.sp \\n(PDu
+.ne 3
+.if \\n(.$=3 .nr I\\n(IR \\$3n
+.if \\n(.$=4 .nr I\\n(IR \\$4n
+.nr J\\n(IR \\n(IRu/2u
+.if \\n(.$=4 .nr J\\n(IR \\$3n
+.in +\\n(I\\n(IRu
+.ta \\n(J\\n(IRu \\n(I\\n(IRu
+.ti -\\n(I\\n(IRu
+\0\\$1\t\\$2\t\c
+..
+.	\"RS - prepare for double indenting
+.de RS
+.nr IS \\n(IP
+.RT
+.nr IP \\n(IS
+.if \\n(IP>0 .in +\\n(I\\n(IRu
+.nr IR +1
+.nr I\\n(IR \\n(PIu
+.in +\\n(I\\n(IRu
+.nr TY \\n(TZ-\\n(.i
+.ta \\n(TYuR
+..
+.	\"RE - retreat to the left
+.de RE
+.nr IS \\n(IP
+.RT
+.nr IP \\n(IS
+.if \\n(IR>0 .nr IR -1
+.if \\n(IP<=0 .in -\\n(I\\n(IRu
+..
+.de TC
+.nr TZ \\n(.lu
+.if \\n(.$ .nr TZ \\$1n
+.ta \\n(TZuR
+..
+.de TD
+.LP
+.nr TZ 0
+..
+.	\"CM - cut mark
+.de CM
+.po 0
+.lt 7.6i
+.ft 1
+.ps 10
+.vs 4p
+.po
+.vs
+.lt
+.ps
+.ft
+..
+.	\"B - bold font
+.de B
+.nr PQ \\n(.f
+.if t .ft 3
+.if "\\$1"" .if n .ul 1000
+.if !"\\$1"" .if n .ul 1
+.if t .if !"\\$1"" \&\\$1\\f\\n(PQ\\$2
+.if n .if \\n(.$=1 \&\\$1
+.if n .if \\n(.$>1 \&\\$1\\c
+.if n .if \\n(.$>1 \\&\\$2
+..
+.	\"R - Roman font
+.de R
+.if n .ul 0
+.ft 1
+..
+.	\"I - italic font
+.de I
+.nr PQ \\n(.f
+.if t .ft 2
+.if "\\$1"" .if n .ul 1000
+.if !"\\$1"" .if n .ul 1
+.if t .if !"\\$1"" \&\\$1\\f\\n(PQ\\$2
+.if n .if \\n(.$=1 \&\\$1
+.if n .if \\n(.$>1 \&\\$1\\c
+.if n .if \\n(.$>1 \\&\\$2
+..
+.	\"TA - tabs set in ens or chars
+.de TA
+.ta \\$1n \\$2n \\$3n \\$4n \\$5n \\$6n \\$7n \\$8n \\$9n
+..
+.	\"SM - make smaller size
+.de SM
+.if \\n(.$>0 \&\\$3\s-2\\$1\s0\\$2
+.if \\n(.$=0 .ps -2
+..
+.	\"LG - make larger size
+.de LG
+.ps +2
+..
+.	\"NL - return to normal size
+.de NL
+.ps \\n(PS
+..
+.	\"DA - force date; ND - no date or new date.
+.de DA
+.if \\n(.$ .ds DY \\$1 \\$2 \\$3 \\$4
+.ds CF \\*(DY
+..
+.de ND
+.ME
+.rm ME
+.ds DY \\$1 \\$2 \\$3 \\$4
+.rm CF
+..
+.de FN
+.FS
+..
+.	\"FS - begin footnote
+.de FJ
+'ce 0
+.di
+.ev1
+.ll \\n(FLu
+.da FF
+.br
+.if \\n(IF>0 .tm Footnote within footnote-illegal.
+.nr IF 1
+.if !\\n+(XX-1 .FA
+..
+.	\"FE - footnote end
+.de FK
+.br
+.in 0
+.nr IF 0
+.di
+.ev
+.if !\\n(XX-1 .nr dn +\\n(.v
+.nr YY -\\n(dn
+.if \\n(NX=0 .nr WF 1
+.if \\n(dl>\\n(CW .nr WF 1
+.if (\\n(nl+\\n(.v)<=(\\n(.p+\\n(YY) .ch FO \\n(YYu
+.if (\\n(nl+\\n(.v)>(\\n(.p+\\n(YY) .if \\n(nl>(\\n(HM+1.5v) .ch FO \\n(nlu+\\n(.vu
+.if (\\n(nl+\\n(.v)>(\\n(.p+\\n(YY) .if \\n(nl+\\n(FM+1v>\\n(.p .ch FX \\n(.pu-\\n(FMu+2v
+.if (\\n(nl+\\n(.v)>(\\n(.p+\\n(YY) .if \\n(nl<=(\\n(HM+1.5v) .ch FO \\n(HMu+(4u*\\n(.vu)
+..
+.\"	First page footer.
+.de FS
+.ev1
+.br
+.ll \\n(FLu
+.da FG
+..
+.de FE
+.br
+.di
+.nr FP \\n(dn
+.if \\n(1T=0 .nr KG 1 \"not in abstract repeat next page.
+.if "\\n(.z"OD" .nr KG 0 \" if in OK, don't repeat.
+.ev
+..
+.de FA
+.if n __________________________
+.if t \l'1i'
+.br
+..
+.de FV
+.FS
+.nf
+.ls 1
+.FY
+.ls
+.fi
+.FE
+..
+.de FX
+.if \\n(XX>0 .di FY
+.if \\n(XX>0 .ns
+..
+.de XF
+.if \\n(nlu+1v>(\\n(.pu-\\n(FMu) .ch FX \\n(nlu+1.9v
+.ev1
+.nf
+.ls 1
+.FF
+.rm FF
+.nr XX 0 1
+.br
+.ls
+.di
+.fi
+.ev
+..
+.de FL
+.ev1
+.nr FL \\$1n
+.ll \\$1
+.ev
+..
+.de UL \" underline argument, don't italicize
+.if t \\$1\l'|0\(ul'\\$2
+.if n .I \\$1 \\$2
+..
+.de UX
+UNIX
+..
+.de US
+the
+.UX
+operating system
+..
+.de QS
+.br
+.LP
+.in +\\n(QIu
+.ll -\\n(QIu
+..
+.de QE
+.br
+.ll +\\n(QIu
+.in -\\n(QIu
+.LP
+..
+.de B1 \" begin boxed stuff
+.br
+.di BB
+.nr BC 0
+.if "\\$1"C" .nr BC 1
+.nr BE 1
+..
+.de B2 \" end boxed stuff
+.br
+.nr BI 1n
+.if \\n(.$>0 .nr BI \\$1n
+.di
+.nr BE 0
+.nr BW \\n(dl
+.nr BH \\n(dn
+.ne \\n(BHu+\\n(.Vu
+.nr BQ \\n(.j
+.nf
+.ti 0
+.if \\n(BC>0 .in +(\\n(.lu-\\n(BWu)/2u
+.in +\\n(BIu
+.BB
+.in -\\n(BIu
+.nr BW +2*\\n(BI
+.sp -1
+\l'\\n(BWu\(ul'\L'-\\n(BHu'\l'|0\(ul'\h'|0'\L'\\n(BHu'
+.if \\n(BC>0 .in -(\\n(.lu-\\n(BWu)/2u
+.if \\n(BQ .fi
+.br
+..
+.de AT
+.nf
+.sp
+.ne 2
+Attached:
+..
+.de CT
+.nf
+.sp
+.ne 2
+.ie \\n(.$ Copy to \\$1:
+.el Copy to:
+..
+.de BX
+.if t \(br\|\\$1\|\(br\l'|0\(rn'\l'|0\(ul'
+.if n \(br\\kA\|\\$1\|\\kB\(br\v'-1v'\h'|\\nBu'\l'|\\nAu'\v'1v'\l'|\\nAu'
+..
+.IZ
+.rm IZ
+.\" ------------------- VARIABLES ------------------------------
+.\" \na - Current chapter
+.\" \nb - Current section
+.\" \nc - Current subsection 
+.\" \nd - Set to 0 initially, 1 by PT,  2 by .PB  Used to control running head
+.\" \ne - Current equation number
+.\" \ng - Used to count items in numbered lists
+.\" \nh - Counts number of times CP has been invoked
+.\" \nj - Set to 1 iff footer page number needed
+.\" \nk - Last figure number used
+.\" \nL - 1 if depth printed for each page
+.\" \nl - 1 old Agfa length to be used
+.\" \np - Numbers end-of-chapter problems
+.\" \nq - 1 for double spaced text, smaller vert. margins
+.\" \ns - initial page number
+.\" \nt - Variable part of spacing inside .BI macro
+.\" \nv - Scratch register in lower case roman numerals
+.\" \nx - Scratch register
+.\" ------------------- GENERAL PARAMETERS ---------------------
+.nr BO 43		\" number of lines of text per page
+.nr PO 1.3i
+.po \n(PO
+.if \nq=1 .ls 2		\" -rq1 invokes double spacing
+.nr LL 5.67i
+.if t \{
+.nr PL 29.73c
+.nr PI 0.25i\}
+.if n \{
+.nr LL 80m
+.nr PL 11.0i
+.nr PI 3m\}
+.pl \n(PLu
+.nr HM (\n(PLu-(\n(BOu*\n(VSu))/2u
+.nr FM \n(PLu-(\n(HMu+((\n(BOu-1u)*\n(VSu)+1u)
+.nr xx \n(HMu%\n(VZu
+.nr HM \n(HMu-\n(xxu
+.nr FM \n(FMu+\n(xxu
+.nr t 0 0
+.\" ------------------- INITIALIZATION -------------------------
+.nr d 0 0
+.nr e 0 1
+.nr h 0 1
+.nr j 1 0
+.nr t 0 0
+.tr ~
+.ds CT "~	\"initially empty
+.ND		\"suppress date on bottom of page
+.af v i		\"register v is in lower case roman
+.ch FO -\n(FMu
+.ch BT -\n(FMu+0.5P
+.\" ------------------- ALIGN TEXT TO A WHOLE NUMBER OF PICAS ----
+.de AL
+'nr xx \\n(.du%\\n(VZu
+'nr xy \\n(VZu-\\n(xx
+'if \\n(xy=\\n(VZu .nr xy 0
+'sp \\n(xyu
+..
+.\" ------------------- DIVISION OF TEXT INTO LOGICAL UNITS ----
+.\"	Define chapter number
+.de CP
+.ds CN \\$1
+.ds CX CHAP.
+.if '\\$1'A' .ds CX APPENDIX
+.if '\\$1'B' .ds CX APPENDIX
+.if '\\$1'C' .ds CX APPENDIX
+.if '\\$1'D' .ds CX APPENDIX
+.if '\\$1'E' .ds CX APPENDIX
+.if '\\$1'F' .ds CX APPENDIX
+.if '\\$1'A' .nr a 0 0
+.if '\\$1'B' .nr a 0 0
+.if '\\$1'C' .nr a 0 0
+.if '\\$1'D' .nr a 0 0
+.if '\\$1'E' .nr a 0 0
+.if '\\$1'F' .nr a 0 0
+.nr H1 \\$1 0
+.nr H2 0 1
+.nr a \\$1 0
+.nr b 0 1
+.nr c 0 1
+.nr d 1 1
+.nr e 0 1
+.nr k 0 1
+.nr s \\n%
+.if \\nq=1 .PH 6
+.ll \\n(LLu
+.nr LT \\n(LLu
+.lt \\n(LLu
+.ll \\n(LLu
+.pl \n(PLu
+.po \n(POu
+.in 0
+.nr PS \\n(PZ
+.nr VS \\n(VZu
+.nr PD 0i
+.ds ST
+.ds CT \\$2
+.if !'\\$3'' .as CT " \\$3
+.if \\nh .bp
+.rs
+.sp 16P
+.B
+.ps 30
+.vs 32
+.ce 1
+\\$1
+.sp 4P
+.ps 18
+.vs 20
+.ce 1
+\\$2
+.sp 0.25i
+.if !'\\$3'' .ce 1
+.if !'\\$3'' \\$3
+.ps 10
+.vs 12
+.R
+.nr x \\n(.pu/2u
+.sp |\\nxu
+.nr h +1 1
+.tr _\\(ru
+.AL
+..
+.de SP
+.sp \\$1	\"used for temporary (page balancing ) fill
+..
+.de HS
+.sp 0.5
+..
+.\"	Major section (numbered)
+.de SE
+.nr b +1 1
+.nr c 0 1
+.ds ST \\$1
+.sp 1
+.NH 2
+\\$1
+.sp 1
+..
+.\"	Subsection (numbered)
+.de SS
+.nr c +1 1
+.NH 3
+\\$1
+.sp 1
+..
+.de UU
+.SH
+\\$1
+.sp 1
+..
+.\"-------------------- PAGE TRANSITION MACROS USED BY -MS ------
+.de PH	\"select special running heads
+.nr d \\$1
+.if \\$1=4 .nr j 1
+.ds CT \\$2
+..
+.de PT
+.AL
+.pc %
+.PN \\n%
+'sp |\\n(HMu-0.35i
+.ps 10
+.\"
+.\" nd = 0 means no running head this time, normal next time
+.if \\nd=0 \{\
+.tl ''''	\" no running head on initial page transition
+.nr j 1 0\}
+.\"
+.\" nd = 1 is normal case: chapter heading even (left) and section odd(right)
+.if \\nd=1\{\
+.if e .tl '\fB\s+2%\s-2\fR'\\*(CT'\\*(CX~ \\*(CN' \"normal case even page
+.if o .if \\nb>0 .tl 'SEC.~ \\*(CN.\\nb'\\*(ST'\fB\s+2%\s-2\fR'
+.if o .if \\nb=0 .tl '''\fB\s+2%\s-2\fR'\}
+.if o .if \\nb=-999 .tl '\\*(CX~ \\*(CN'\\*(CT'\fB\s+2%\s-2\fR'\}
+.\"
+.\" nd = 2 is for PROBLEMS; even normal, odd  CHAP. ... PROBLEMS %
+.if \\nd=2\{\
+.if e .tl '\fB\s+2%\s-2\fR'\\*(CT'\\*(CX~ \\*(CN' \"even page PROBLEMS
+.if o .if \\nd=2 .tl '\\*(CX~ \\*(CN'PROBLEMS'\fB\s+2%\s-2\fR' \}
+.\"
+.\" nd = 3 is for index, problem solutions & other cases with same odd even hd
+.if \\nd=3\{\
+.if e .tl '\fB\s+2%\s-2\fR'\\*(CT''
+.if o .tl ''\\*(CT'\fB\s+2%\s-2\fR'\}
+.\"
+.\" nd = 4 is like nd = 3, except page numbers are lower case roman
+.if \\nd=4\{\
+.nr v \\n%
+.if e .tl '\fB\s+2\\nv\s-2\fR'\\*(CT''
+.if o .tl ''\\*(CT'\fB\s+2\\nv\s-2\fR'\}
+.\"
+.\" nd = 5 suppresses running heads like nd=0, only it keeps them suppressed
+.if \\nd=5 .tl ''''
+.\" nd = 6 gives page number in right-hand corner only
+.if \\nd=6 .tl '''%'
+.if \\nd=0 .nr d 1 0	\" henceforth normal running heads
+..
+.de BT
+.if \\n%=\\ns\{\
+.nr x \\n(HMu+(\\n(BO*\\n(VSu)+2P
+'sp |\\nxu
+.nr v \\n%
+.ie \\nd=4 .tl ''\fB\s-1\\nv\s0\fP''
+.el .tl ''\fB\s-1\\n%\s0\fP''\}
+.nr j 0 0
+.if \\nd=0 .nr d 1 0
+..
+.\"--------------- CHECK FOR INITIAL PAGE NUMBER ---------------
+.de PC
+.if \n%<\\$1\{
+.tm You forgot to set the page number.  Run aborted. Use troff -n
+.ex\}
+.if \n%>\\$2\{
+.tm You forgot to set the page number.  Run aborted. Use troff -n
+.ex\}
+..
+.\"-------------------- LISTS OF THINGS ------------------------
+.\"	Start list
+.de LI
+.nr g 0 1
+.in +0.25i
+.nr LL -0.25i
+.ll -0.25i
+.ne 3v
+.HS
+..
+.\"	End list
+.de LX
+.sp 1
+.in -0.25i
+.nr LL +0.25i
+.ll +0.25i
+.LP
+..
+.\"	List item
+.de IT
+.HS
+.nr g \\ng+1 1
+.ie \\ng<10 .IP \0\\ng. 4
+.el .IP \\ng. 4
+..
+.\"Short unnumbered lines
+.de UN
+.HS
+..
+.\"-------------------- END OF CHAPTER EXERCISES ---------------
+.de PB
+.nr d 2 0
+.if \\nq=1 .PH 6
+.ne 1.5i
+.sp 0.5i
+.ce 1
+.B PROBLEMS
+.sp 1
+.nr p 0 1
+..
+.de PR
+.ps 11
+.vs 13
+.nr PS 11
+.nr VS 13.01p
+.HS
+.nr p +1 1
+.in \w'00.  'u
+.ti -\w'00.  'u
+.if \\np>9 \fB\\np.\fR~~\c
+.if \\np<10 \fB\0\\np.\fR~~\c
+..
+.de AA
+.sp 3
+.if n .nr LL 84m
+.nr PS \\n(PZ
+.nr VS \\n(VZu
+.nr a \\$1 1
+.nr b 0 0
+.nr p 0 1
+.ce 1
+.nr x 1
+.if '\\$1'A' .nr x 0
+.if '\\$1'B' .nr x 0
+.if '\\$1'C' .nr x 0
+.if \\nq=1 .PH 6
+.if \\nx\fBSOLUTIONS TO CHAPTER \\$1 PROBLEMS\fR
+.if !\\nx\fBSOLUTIONS TO APPENDIX \\$1 PROBLEMS\fR
+.sp 1v
+..
+.de AN
+.HS
+.ps \\n(PZ
+.vs \\n(VSu
+.nr PS \\n(PZ
+.nr VS \\n(VZu
+.nr p +1 1
+.in \w'00.  'u
+.ti -\w'00.  'u
+.if \\np>9 \fB\\np.\fR~~\c
+.if \\np<10 \fB\0\\np.\fR~~\c
+..
+.\"-------------------- BIBLIOGRAPHY ---------------------------
+.de BB
+.sp 2
+.in 0.25i
+..
+.de BI
+.ps 10
+.vs 12
+.sp \\ntu
+.HS
+.if n .HS
+.ti -0.30i
+.R
+..
+.\"-------------------- QUOTES ---------------------------------
+.ds OQ `\h'-1p'`
+.ds CQ '\h'-1p''
+.\"-------------------- FIGS.-----------------------------------
+.de FC 
+'sp 1v
+.ps 10
+.vs 12
+.in +0.5i
+.ll -0.5i
+.B
+.if '\\$1'C' .ce 1
+Fig.\|\|\|\\*(CN-\\n+k.~\c
+.R
+..
+.de BF
+.KF
+'sp 1v
+.nr TP \\n(.s
+.nr TV \\n(.v
+.nr TF \\n(.f
+.nr r 0 0
+.if \\nq=0 .if  "\\$1"PAGE" .KP
+.if \\nq=0 .if  "\\$1"PAGE" .nr r 1 0
+.if \\nq=0 .if !"\\$1"PAGE" .sp \\$1
+.if \\nq=1 .sp 0.5i
+.FC \\$2
+..
+.de EF
+.in -0.5i
+.ll +0.5i
+.ps \\n(TP
+.vs \\n(TV
+.ft \\n(TF
+'if \\nr==0 'sp 30u
+'AL
+.KE
+..
+.de NF
+.nr x \\nk+1
+.ie !'\\$1'X' Fig.~\\*(CN-\\nx\\$1
+.el Figure \\*(CN-\\nx\\$2
+..
+.de PF
+.ie !'\\$1'X' Fig.~\\*(CN-\\nk\\$1
+.el Figure \\*(CN-\\nk\\$2
+..
+.\"-------------------- MULTIPLE BLANK PAGES -------------------
+.de MP
+.if \\$1 \{\
+.KF
+.KP
+.KE
+.MP \\$1-1
+.if \\$1<2 .nr k +1 1
+\}
+..
+.\"-------------------- TABLE OF CONTENTS ----------------------
+.de XT
+.if t .ta 0.4i 0.8i 0.9i \\n(LLuR
+.if n .ta 0.3i 1.0i 1.1i 5.0iR
+.ps 11
+.vs 13
+.nr a \\$1 0
+.nr b 0 1
+.nr c 0 1
+.sp 0.40i
+.ne 0.3i
+.B
+\\s18\\$1\\s12	\\$2	\\$3\\fR\\s11
+.br
+.if !'\\$4''	\\fB\\$4\\fR
+.R
+.sp 0.5v
+..
+.de XE
+.nr b +1 1
+.nr c 0 1
+.HS
+	\\na.\\nb	\\$1   \\$2
+..
+.de XS
+.nr c +1 1
+		\\na.\\nb.\\nc   \\$1   \\$2
+..
+.\"------------------- INDEX -----------------------------------
+.de IL
+.nr PS \\n(PZ-2
+.nr VS 12.01p
+.LP
+.nf
+.na
+.sp 2v
+.ne 2
+\fB\s+4\\$1\\s0\fR
+.sp 1v
+..
+.\"------------------- NEW .B MACRO ----------------------------
+.rm B
+.de B
+.nr PQ \\n(.f
+.ft 3
+.if !"\\$1"" \&\\$1\\f\\n(PQ\\$2
+..
+.\"--------------------- FIXES NEEDED TO -MS -------------------
+.\" Remove .if n .ul 1000 from .NH
+.\" Remove .if n .ul 1000 from .SH
+.\" Fix to allow letters as chapter "numbers"
+.\"
+.\" Here is the b3mac file
+.nr Cs 10
+.fp 5 H
+.ds fm \(fm
+.ds em \(em
+.de F
+\\fI\\$1\\fR\\$2
+..
+.de CC
+.HS
+~~~~~\\s\\n(Cs\\f5\\$1\\fP\\s0
+.HS
+.LP
+..
+.de Cx
+~~~~~\\s\\n(Cs\\f5\\$1\\fP\\s0\\$2
+..
+.de Cb
+.in +0.25i
+\\s\\n(Cs
+.HS
+\\f5
+..
+.de Ce
+.HS
+\\fR
+.nr PS \\n(PZ
+.nr VS \\n(VZ
+.LP
+.in -0.25i
+..
+.de SY
+\\$3\s-2\\$1\s+2\\$2
+..
+.de SM
+\\$3\s-1\\$1\s+1\\$2
+..
+.de FN
+\&\\fI\\$1\\fR\\$2
+..
+.de DI
+\&\\fI\\$1\\fR\\$2
+..
+.de FI
+\&\\fI\\$1\\fR\\$2
+..
+.de LN
+.nr x \\$1+\\$2
+\\$4line
+.L4 \\nx \\$3
+..
+.de LS
+.nr x \\$1+\\$2
+.nr y \\$1+\\$3
+.nr z \\nx+1
+\\$5lines
+.L4 \\nx
+.ie \\ny=\\nz and
+.el to
+.L4 \\ny \\$4
+..
+.ds SQ \(fm\h'-0.05c'\(fm
+.de L4
+.ie \\$1<10 000\\$1\\$2
+.el .ie \\$1<100 00\\$1\\$2
+.el .ie \\$1<1000 0\\$1\\$2
+.el \\$1\\$2
+..
+.de KW
+\f5\\$1\\$2\fR
+..
+.ds M0 MINIX
+.ds M1 \\s-1MINIX\\s+1
+.ds M2 \\s-2MINIX\\s+2
+.ds M9 \\s-1MINIX\\s+1
+.ds m0 minix
+.de MX
+\s-2MINIX\s+2\\$1
+..
+.de Ux
+\s-2UNIX\s+2\\$1
+..
+.tr _\(ru
+.de UX
+\s-2UNIX\s+2\\$1
+..
+.ds Mx \\s-1MINIX\\s0
+.ds Mp \\s-1MINIX-PC\\s0
+.ds Ms \\s-1MINIX-ST\\s0
+.de CW
+\f5
+..
+.de Bu
+.HS
+.IP "\0\(bu" 4
+..
+.de CD
+.ne 2
+.if t .ta 0.9i 1.15i 2.75i 3.25i 3.75i
+.if n .ta 11m 15m 40m
+.nr x 0 0
+.nr y 0 0
+.nr z 0 0
+.if n #\\$1
+.if n .br
+\\fBCommand:\&	\\$1\\fR
+.br
+..
+.de SX
+.if \\nx<=0 \\fBSyntax:\&	\\$1
+.if \\nx>0 \&	\\fB\\$1
+.nr x 1 1
+.br
+..
+.de FL
+.if \\ny<=0 \\fBFlags:\&	\\fB\\$1	\\fR\\$2
+.if \\ny>0 \& 	\\fB\\$1	\\fR\\$2
+.nr y 1 1
+.br
+..
+.de EX
+.br
+.nf
+.if \\nz<=0 \\fB\&Examples:	\\fR\\$1	\\fR# \\$2
+.if \\nz>0 \&	\\fR\\$1	\\fR# \\$2
+.nr z 1 1
+.br
+..
+.de EY
+.br
+.nf
+.if \\nz<=0 \\fB\&Example:	\\fR\\$1	\\fR# \\$2
+.if \\nz>0 \&	\\fR\\$1	\\fR# \\$2
+.nr z 1 1
+.br
+..
Index: /trunk/minix/man/man1/M.1
===================================================================
--- /trunk/minix/man/man1/M.1	(revision 9)
+++ /trunk/minix/man/man1/M.1	(revision 9)
@@ -0,0 +1,35 @@
+.TH M 1
+.SH NAME
+M, U \- conveniently mount and unmount
+.SH SYNOPSIS
+\fBM \fIdevice\fR [\fB\-r\fR]\fR
+.br
+\fBU \fIdevice\fR\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-r" "Mount read-only"
+.SH EXAMPLES
+.EX "M root" "Mount the RAM image on /root"
+.EX "M 0" "Mount /dev/fd0 on /fd0"
+.EX "U fd1" "Unmount /dev/fd1 from /fd1"
+.SH DESCRIPTION
+.PP
+\fIM\fR and \fIU\fR allow easy mounting and unmounting of a device by using
+only an abbreviated device name or keyword.  Special keywords are
+\fBroot\fR, \fBtmp\fR, and \fBusr\fR for the three hard disk partitions
+MINIX 3 runs in.  Floppy devices are mounted on \fB/fd0\fR or \fB/fd1\fR.  You
+can use \fB0\fR and \fB1\fR instead of \fBfd0\fR and \fBfd1\fP.  A device it
+doesn't know about is mounted on \fB/mnt\fR.
+.SH "SEE ALSO"
+.BR mount (1),
+.BR umount (1).
Index: /trunk/minix/man/man1/acd.1
===================================================================
--- /trunk/minix/man/man1/acd.1	(revision 9)
+++ /trunk/minix/man/man1/acd.1	(revision 9)
@@ -0,0 +1,860 @@
+.TH ACD 1
+.SH NAME
+acd \- a compiler driver
+.SH SYNOPSIS
+.B acd
+\fB\-v\fR[\fIn\fR]
+\fB\-vn\fR[\fIn\fR]
+.BI \-name " name"
+.BI \-descr " descr"
+.BI \-T " dir"
+.RI [ arg " ...]"
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Acd
+is a compiler driver, a program that calls the several passes that are needed
+to compile a source file.  It keeps track of all the temporary files used
+between the passes.  It also defines the interface of the compiler, the
+options the user gets to see.
+.PP
+This text only describes
+.B acd
+itself, it says nothing about the different options the C-compiler accepts.
+(It has nothing to do with any language, other than being a tool to give
+a compiler a user interface.)
+.SH OPTIONS
+.B Acd
+itself takes five options:
+.TP
+\fB\-v\fR[\fIn\fR]
+Sets the diagnostic level to
+.I n
+(by default
+.BR 2 ).
+The higher
+.I n
+is, the more output
+.B acd
+generates:
+.B \-v0
+does not produce any output.
+.B \-v1
+prints the basenames of the programs called.
+.B \-v2
+prints names and arguments of the programs called.
+.B \-v3
+shows the commands executed from the description file too.
+.B \-v4
+shows the program read from the description file too.  Levels 3 and 4 use
+backspace overstrikes that look good when viewing the output with a smart
+pager.
+.TP
+\fB\-vn\fR[\fIn\fR]
+Like
+.B \-v
+except that no command is executed.  The driver is just play-acting.
+.TP
+.BI \-name " name"
+.B Acd
+is normally linked to the name the compiler is to be called with by the
+user.  The basename of this, say
+.BR cc ,
+is the call name of the driver.  It plays a role in selecting the proper
+description file.  With the
+.B \-name
+option one can change this.
+.B Acd \-name cc
+has the same effect as calling the program as
+.BR cc .
+.TP
+.BI \-descr " descr"
+Allows one to choose the pass description file of the driver.  By default
+.I descr
+is the same as
+.IR name ,
+the call name of the program.  If
+.I descr
+doesn't start with
+.BR / ,
+.BR ./ ,
+or
+.BR ../
+then the file
+.BI /usr/lib/ descr /descr
+will be used for the description, otherwise
+.I descr
+itself.  Thus
+.B cc \-descr newcc
+calls the C-compiler with a different description file without changing the
+call name.  Finally, if
+.I descr
+is \fB"\-"\fP, standard input is read.  (The default lib directory
+.BR /usr/lib ,
+may be changed to
+.I dir
+at compile time by \fB\-DLIB=\e"\fP\fIdir\fP\fB\e"\fP.  The default
+.I descr
+may be set with \fB\-DDESCR=\e"\fP\fIdescr\fP\fB\e"\fP for simple
+installations on a system without symlinks.)
+.TP
+.BI \-T " dir"
+Temporary files are made in
+.B /tmp
+by default, which may be overridden by the environment variable
+.BR TMPDIR ,
+which may be overridden by the
+.B \-T
+option.
+.SH "THE DESCRIPTION FILE"
+The description file is a program interpreted by the driver.  It has variables,
+lists of files, argument parsing commands, and rules for transforming input
+files.
+.SS Syntax
+There are four simple objects:
+.PP
+.RS
+Words, Substitutions, Letters, and Operators.
+.RE
+.PP
+And there are two ways to group objects:
+.PP
+.RS
+Lists, forming sequences of anything but letters,
+.SP
+Strings, forming sequences of anything but Words and Operators.
+.RE
+.PP
+Each object has the following syntax:
+.IP Words
+They are sequences of characters, like
+.BR cc ,
+.BR \-I/usr/include ,
+.BR /lib/cpp .
+No whitespace and no special characters.  The backslash character
+.RB ( \e )
+may be used to make special characters common, except whitespace.  A backslash
+followed by whitespace is completely removed from the input.  The sequence
+.B \en
+is changed to a newline.
+.IP Substitutions
+A substitution (henceforth called 'subst') is formed with a
+.BR $ ,
+e.g.
+.BR $opt ,
+.BR $PATH ,
+.BR ${lib} ,
+.BR $\(** .
+The variable name after the
+.B $
+is made of letters, digits and underscores, or any sequence of characters
+between parentheses or braces, or a single other character.  A subst indicates
+that the value of the named variable must be substituted in the list or string
+when fully evaluated.
+.IP Letters
+Letters are the single characters that would make up a word.
+.IP Operators
+The characters
+.BR = ,
+.BR + ,
+.BR \- ,
+.BR \(** ,
+.BR < ,
+and
+.B >
+are the operators.  The first four must be surrounded by whitespace if they
+are to be seen as special (they are often used in arguments).  The last two
+are always special.
+.IP Lists
+One line of objects in the description file forms a list.  Put parentheses
+around it and you have a sublist.  The values of variables are lists.
+.IP Strings
+Anything that is not yet a word is a string.  All it needs is that the substs
+in it are evaluated, e.g.
+.BR $LIBPATH/lib$key.a .
+A single subst doesn't make a string, it expands to a list.  You need at
+least one letter or other subst next to it.  Strings (and words) may also
+be formed by enclosing them in double quotes.  Only
+.B \e
+and
+.B $
+keep their special meaning within quotes.
+.SS Evaluation
+One thing has to be carefully understood: Substitutions are delayed until
+the last possible moment, and description files make heavy use of this.
+Only if a subst is tainted, either because its variable is declared local, or
+because a subst in its variable's value is tainted, is it immediately
+substituted.  So if a list is assigned to a variable then this list is only
+checked for tainted substs.  Those substs are replaced by the value
+of their variable.  This is called partial evaluation.
+.PP
+Full evaluation expands all substs, the list is flattened, i.e. all
+parentheses are removed from sublists.
+.PP
+Implosive evaluation is the last that has to be done to a list before it
+can be used as a command to execute.  The substs within a string have been
+evaluated to lists after full expansion, but a string must be turned into
+a single word, not a list.  To make this happen, a string is first exploded
+to all possible combinations of words choosing one member of the lists within
+the string.  These words are tried one by one to see if they exist as a
+file.  The first one that exists is taken, if none exists than the first
+choice is used.  As an example, assume
+.B LIBPATH
+equals
+.BR "(/lib /usr/lib)" ,
+.B key
+is
+.B (c)
+and
+.B key
+happens to be local.  Then we have:
+.PP
+.RS
+\fB"$LIBPATH/lib$key.a"\fP
+.RE
+.PP
+before evaluation,
+.PP
+.RS
+\fB"$LIBPATH/lib(c).a"\fP
+.RE
+.PP
+after partial evaluation,
+.PP
+.RS
+\fB"(/lib/libc.a /usr/lib/libc.a)"\fP
+.RE
+.PP
+after full evaluation, and finally
+.PP
+.RS
+.B /usr/lib/libc.a
+.RE
+.PP
+after implosion, if the file exists.
+.SS Operators
+The operators modify the way evaluation is done and perform a special
+function on a list:
+.TP
+.B \(**
+Forces full evaluation on all the list elements following it.  Use it to
+force substitution of the current value of a variable.  This is the only
+operator that forces immediate evaluation.
+.TP
+.B +
+When a
+.B +
+exists in a list that is fully evaluated, then all the elements before the
+.B +
+are imploded and all elements after the
+.B +
+are imploded and added to the list if they are not already in the list.  So
+this operator can be used either for set addition, or to force implosive
+expansion within a sublist.
+.TP
+.B \-
+Like
+.BR + ,
+except that elements after the
+.B \-
+are removed from the list.
+.PP
+The set operators can be used to gather options that exclude each other
+or for their side effect of implosive expansion.  You may want to write:
+.PP
+.RS
+\fBcpp \-I$LIBPATH/include\fP
+.RE
+.PP
+to call cpp with an extra include directory, but
+.B $LIBPATH
+is expanded using a filename starting with
+.B \-I
+so this won't work.  Given that any problem in Computer Science can be solved
+with an extra level of indirection, use this instead:
+.PP
+.RS
+.ft B
+cpp \-I$INCLUDE
+.br
+INCLUDE = $LIBPATH/include +
+.ft P
+.RE
+.SS "Special Variables"
+There are three special variables used in a description file:
+.BR $\(** ,
+.BR $< ,
+and
+.BR $> .
+These variables are always local and mostly read-only.  They will be
+explained later.
+.SS "A Program"
+The lists in a description file form a program that is executed from the
+first to the last list.  The first word in a list may be recognized as a
+builtin command (only if the first list element is indeed simply a word.)
+If it is not a builtin command then the list is imploded and used as a
+\s-2UNIX\s+2 command with arguments.
+.PP
+Indentation (by tabs or spaces) is not just makeup for a program, but are
+used to group lines together.  Some builtin commands need a body.  These
+bodies are simply lines at a deeper indentation.
+.PP
+Empty lines are not ignored either, they have the same indentation level as
+the line before it.  Comments (starting with a
+.B #
+and ending at end of line) have an indentation of their own and can be used
+as null commands.
+.PP
+.B Acd
+will complain about unexpected indentation shifts and empty bodies.  Commands
+can share the same body by placing them at the same indentation level before
+the indented body.  They are then "guards" to the same body, and are tried
+one by one until one succeeds, after which the body is executed.
+.PP
+Semicolons may be used to separate commands instead of newlines.  The commands
+are then all at the indentation level of the first.
+.SS "Execution phases"
+The driver runs in three phases: Initialization, Argument scanning, and
+Compilation.  Not all commands work in all phases.  This is further explained
+below.
+.SS "The Commands"
+The commands accept arguments that are usually generic expressions that
+implode to a word or a list of words.  When
+.I var
+is specified, then a single word or subst needs to be given, so
+an assignment can be either
+.I name
+.B =
+.IR value ,
+or
+.BI $ name
+.B =
+.IR value .
+.TP
+.IB "var " = " expr ..."
+The partially evaluated list of expressions is assigned to
+.IR var .
+During the evaluation is
+.I var
+marked as local, and after the assignment set from undefined to defined.
+.TP
+.BI unset " var"
+.I Var
+is set to null and is marked as undefined.
+.TP
+.BI import " var"
+If
+.I var
+is defined in the environment of
+.B acd
+then it is assigned to
+.IR var .
+The environment variable is split into words at whitespace and colons.  Empty
+space between two colons
+.RB ( :: )
+is changed to a dot.
+.TP
+.BI mktemp " var " [ suffix ]
+Assigns to
+.I var
+the name of a new temporary file, usually something like /tmp/acd12345x.  If
+.I suffix
+is present then it will be added to the temporary file's name.  (Use it
+because some programs require it, or just because it looks good.)
+.B Acd
+remembers this file, and will delete it as soon as you stop referencing it.
+.TP
+.BI temporary " word"
+Mark the file named by
+.I word
+as a temporary file.  You have to make sure that the name is stored in some
+list in imploded form, and not just temporarily created when
+.I word
+is evaluated, because then it will be immediately removed and forgotten.
+.TP
+.BI stop " suffix"
+Sets the target suffix for the compilation phase.  Something like
+.B stop .o
+means that the source files must be compiled to object files.  At least one
+.B stop
+command must be executed before the compilation phase begins.  It may not be
+changed during the compilation phase.  (Note: There is no restriction on
+.IR suffix ,
+it need not start with a dot.)
+.TP
+.BI treat " file suffix"
+Marks the file as having the given suffix for the compile phase.  Useful
+for sending a
+.B \-l
+option directly to the loader by treating it as having the
+.B .a
+suffix.
+.TP
+.BI numeric " arg"
+Checks if
+.I arg
+is a number.  If not then
+.B acd
+will exit with a nice error message.
+.TP
+.BI error " expr ..."
+Makes the driver print the error message
+.I "expr ..."
+and exit.
+.TP
+.BI if " expr " = " expr"
+.B If
+tests if the two expressions are equal using set comparison, i.e. each
+expression should contain all the words in the other expression.  If the
+test succeeds then the if-body is executed.
+.TP
+.BI ifdef " var"
+Executes the ifdef-body if
+.I var
+is defined.
+.TP
+.BI ifndef " var"
+Executes the ifndef-body if
+.I var
+is undefined.
+.TP
+.BI iftemp " arg"
+Executes the iftemp-body if
+.I arg
+is a temporary file.  Use it when a command has the same file as input and
+output and you don't want to clobber the source file:
+.SP
+.RS
+.nf
+.ft B
+transform .o .o
+	iftemp $\(**
+		$> = $\(**
+	else
+		cp $\(** $>
+	optimize $>
+.ft P
+.fi
+.RE
+.TP
+.BI ifhash " arg"
+Executes the ifhash-body if
+.I arg
+is an existing file with a '\fB#\fP' as the very first character.  This
+usually indicates that the file must be pre-processed:
+.SP
+.RS
+.nf
+.ft B
+transform .s .o
+	ifhash $\(**
+		mktemp ASM .s
+		$CPP $\(** > $ASM
+	else
+		ASM = $\(**
+	$AS \-o $> $ASM
+	unset ASM
+.ft P
+.fi
+.RE
+.TP
+.B else
+Executes the else-body if the last executed
+.BR if ,
+.BR ifdef ,
+.BR ifndef ,
+.BR iftemp ,
+or
+.B ifhash
+was unsuccessful.  Note that
+.B else
+need not immediately follow an if, but you are advised not to make use of
+this.  It is a "feature" that may not last.
+.TP
+.BI apply " suffix1 suffix2"
+Executed inside a transform rule body to transform the input file according
+to another transform rule that has the given input and output suffixes.  The
+file under
+.B $\(**
+will be replaced by the new file.  So if there is a
+.B .c .i
+preprocessor rule then the example of
+.B ifhash
+can be replaced by:
+.SP
+.RS
+.nf
+.ft B
+transform .s .o
+	ifhash $\(**
+		apply .c .i
+	$AS \-o $> $*
+.ft P
+.fi
+.RE
+.TP
+.BI include " descr"
+Reads another description file and replaces the
+.B include
+with it.  Execution continues with the first list in the new program.  The
+search for
+.I descr
+is the same as used for the
+.B \-descr
+option.  Use
+.B include
+to switch in different front ends or back ends, or to call a shared
+description file with a different initialization.  Note that
+.I descr
+is only evaluated the first time the
+.B include
+is called.  After that the
+.B include
+has been replaced with the included program, so changing its argument won't
+get you a different file.
+.TP
+.BI arg " string ..."
+.B Arg
+may be executed in the initialization and scanning phase to post an argument
+scanning rule, that's all the command itself does.  Like an
+.B if
+that fails it allows more guards to share the same body.
+.TP
+.BI transform " suffix1 suffix2"
+.BR Transform ,
+like
+.BR arg ,
+only posts a rule to transform a file with the suffix
+.I suffix1
+into a file with the suffix
+.IR suffix2 .
+.TP
+.BI prefer " suffix1 suffix2"
+Tells that the transformation rule from
+.I suffix1
+to
+.I suffix2
+is to be preferred when looking for a transformation path to the stop suffix.
+Normally the shortest route to the stop suffix is used.
+.B Prefer
+is ignored on a
+.BR combine ,
+because the special nature of combines does not allow ambiguity.
+.SP
+The two suffixes on a
+.B transform
+or
+.B prefer
+may be the same, giving a rule that is only executed when preferred.
+.TP
+.BI combine " suffix-list suffix"
+.B Combine
+is like
+.B transform
+except that it allows a list of input suffixes to match several types of
+input files that must be combined into one.
+.TP
+.B scan
+The scanning phase may be run early from the initialization phase with the
+.B scan
+command.  Use it if you need to make choices based on the arguments before
+posting the transformation rules.  After running this,
+.B scan
+and
+.B arg
+become no-ops.
+.TP
+.B compile
+Move on to the compilation phase early, so that you have a chance to run
+a few extra commands before exiting.  This command implies a
+.BR scan .
+.PP
+Any other command is seen as a \s-2UNIX\s+2 command.  This is where the
+.B <
+and
+.B >
+operators come into play.  They redirect standard input and standard output
+to the file mentioned after them, just like the shell.
+.B Acd
+will stop with an error if the command is not successful.
+.SS The Initialization Phase
+The driver starts by executing the program once from top to bottom to
+initialize variables and post argument scanning and transformation rules.
+.SS The Scanning Phase
+In this phase the driver makes a pass over the command line arguments to
+process options.  Each
+.B arg
+rule is tried one by one in the order they were posted against the front of
+the argument list.  If a match is made then the matched arguments are removed
+from the argument list and the arg-body is executed.  If no match can be made
+then the first argument is moved to the list of files waiting to be
+transformed and the scan is restarted.
+.PP
+The match is done as follows: Each of the strings after
+.B arg
+must match one argument at the front of the argument list.  A character
+in a string must match a character in an argument word, a subst in a string
+may match 1 to all remaining characters in the argument, preferring the
+shortest possible match.  The hyphen in a argument starting with a hyphen
+cannot be matched by a subst.  Therefore:
+.PP
+.RS
+.B arg \-i
+.RE
+.PP
+matches only the argument
+.BR \-i .
+.PP
+.RS
+.B arg \-O$n
+.RE
+.PP
+matches any argument that starts with
+.B \-O
+and is at least three characters long.  Lastly,
+.PP
+.RS
+.B arg \-o $out
+.RE
+.PP
+matches
+.B \-o
+and the argument following it, unless that argument starts with a hyphen.
+.PP
+The variable
+.B $\(**
+is set to all the matched arguments before the arg-body is executed.  All
+the substs in the arg strings are set to the characters they match.  The
+variable
+.B $>
+is set to null.  All the values of the variables are saved and the variables
+marked local.  All variables except
+.B $>
+are marked read-only.  After the arg-body is executed is the value of
+.B $>
+concatenated to the file list.  This allows one to stuff new files into the
+transformation phase.  These added names are not evaluated until the start
+of the next phase.
+.SS The Compilation Phase
+The files gathered in the file list in the scanning phase are now transformed
+one by one using the transformation rules.  The shortest, or preferred route
+is computed for each file all the way to the stop suffix.  Each file is
+transformed until it lands at the stop suffix, or at a combine rule.  After
+a while all files are either fully transformed or at a combine rule.
+.PP
+The driver chooses a combine rule that is not on a path from another combine
+rule and executes it.  The file that results is then transformed until it
+again lands at a combine rule or the stop suffix.  This continues until all
+files are at the stop suffix and the program exits.
+.PP
+The paths through transform rules may be ambiguous and have cycles, they will
+be resolved.  But paths through combines must be unambiguous, because of
+the many paths from the different files that meet there.  A description file
+will usually have only one combine rule for the loader.  However if you do
+have a combine conflict then put a no-op transform rule in front of one to
+resolve the problem.
+.PP
+If a file matches a long and a short suffix then the long suffix is preferred.
+By putting a null input suffix (\fB""\fP) in a rule one can match any file
+that no other rule matches.  You can send unknown files to the loader this
+way.
+.PP
+The variable
+.B $\(**
+is set to the file to be transformed or the files to be combined before the
+transform or combine-body is executed.
+.B $>
+is set to the output file name, it may again be modified.
+.B $<
+is set to the original name of the first file of
+.B $\(**
+with the leading directories and the suffix removed.
+.B $\(**
+will be made up of temporary files after the first rule.
+.B $>
+will be another temporary file or the name of the target file
+.RB ( $<
+plus the stop suffix), if the stop suffix is reached.
+.PP
+.B $>
+is passed to the next rule; it is imploded and checked to be a single word.
+This driver does not store intermediate object files in the current directory
+like most other compilers, but keeps them in
+.B /tmp
+too.  (Who knows if the current directory can have files created in?)  As an
+example, here is how you can express the "normal" method:
+.PP
+.RS
+.nf
+.ft B
+transform .s .o
+	if $> = $<.o
+		# Stop suffix is .o
+	else
+		$> = $<.o
+		temporary $>
+	$AS \-o $> $\(**
+.ft P
+.fi
+.RE
+.PP
+Note that
+.B temporary
+is not called if the target is already the object file, or you would lose
+the intended result!
+.B $>
+is known to be a word, because
+.B $<
+is local.  (Any string whose substs are all expanded changes to a word.)
+.SS "Predefined Variables"
+The driver has three variables predefined:
+.BR PROGRAM ,
+set to the call name of the driver,
+.BR VERSION ,
+the driver's version number, and
+.BR ARCH ,
+set to the name of the default output architecture.  The latter is optional,
+and only defined if
+.B acd
+was compiled with \fB\-DARCH=\e"\fP\fIarch-name\fP\fB\e"\fP.
+.SH EXAMPLE
+As an example a description file for a C compiler is given.  It has a
+front end (ccom), an intermediate code optimizer (opt), a code generator (cg),
+an assembler (as), and a loader (ld).  The compiler can pre-process, but
+there is also a separate cpp.  If the
+.B \-D
+and options like it are changed to look like
+.B \-o
+then this example is even as required by \s-2POSIX\s+2.
+.RS
+.nf
+
+# The compiler support search path.
+C =	/lib /usr/lib /usr/local/lib
+
+# Compiler passes.
+CPP =	$C/cpp $CPP_F
+CCOM =	$C/ccom $CPP_F
+OPT =	$C/opt
+CG =	$C/cg
+AS =	$C/as
+LD =	$C/ld
+
+# Predefined symbols.
+CPP_F =	\-D__EXAMPLE_CC__
+
+# Library path.
+LIBPATH = $USERLIBPATH $C
+
+# Default transformation target.
+stop .out
+
+# Preprocessor directives.
+arg \-D$name
+arg \-U$name
+arg \-I$dir
+	CPP_F = $CPP_F $\(**
+
+# Stop suffix.
+arg \-c
+	stop .o
+
+arg \-E
+	stop .E
+
+# Optimization.
+arg \-O
+	prefer .m .m
+	OPT = $OPT -O1
+
+arg \-O$n
+	numeric $n
+	prefer .m .m
+	OPT = $OPT $\(**
+
+# Add debug info to the executable.
+arg \-g
+	CCOM = $CCOM -g
+
+# Add directories to the library path.
+arg \-L$dir
+	USERLIBPATH = $USERLIBPATH $dir
+
+# \-llib must be searched in $LIBPATH later.
+arg \-l$lib
+	$> = $LIBPATH/lib$lib.a
+
+# Change output file.
+arg \-o$out
+arg \-o $out
+	OUT = $out
+
+# Complain about a missing argument.
+arg \-o
+	error "argument expected after '$\(**'"
+
+# Any other option (like \-s) are for the loader.
+arg \-$any
+	LD = $LD $\(**
+
+# Preprocess C-source.
+transform .c .i
+	$CPP $\(** > $>
+
+# Preprocess C-source and send it to standard output or $OUT.
+transform .c .E
+	ifndef OUT
+		$CPP $\(**
+	else
+		$CPP $\(** > $OUT
+
+# Compile C-source to intermediate code.
+transform .c .m
+transform .i .m
+	$CCOM $\(** $>
+
+# Intermediate code optimizer.
+transform .m .m
+	$OPT $\(** > $>
+
+# Intermediate to assembly.
+transform .m .s
+	$CG $\(** > $>
+
+# Assembler to object code.
+transform .s .o
+	if $> = $<.o
+		ifdef OUT
+			$> = $OUT
+	$AS \-o $> $\(**
+
+# Combine object files and libraries to an executable.
+combine (.o .a) .out
+	ifndef OUT
+		OUT = a.out
+	$LD \-o $OUT $C/crtso.o $\(** $C/libc.a
+.fi
+.RE
+.SH FILES
+.TP 25n
+.RI /usr/lib/ descr /descr
+\- compiler driver description file.
+.SH "SEE ALSO"
+.BR cc (1).
+.SH ACKNOWLEDGEMENTS
+Even though the end result doesn't look much like it, many ideas were
+nevertheless derived from the ACK compiler driver by Ed Keizer.
+.SH BUGS
+\s-2POSIX\s+2 requires that if compiling one source file to an object file
+fails then the compiler should continue with the next source file.  There is
+no way
+.B acd
+can do this, it always stops after error.  It doesn't even know what an
+object file is!  (The requirement is stupid anyhow.)
+.PP
+If you don't think that tabs are 8 spaces wide, then don't mix them with
+spaces for indentation.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/anm.1
===================================================================
--- /trunk/minix/man/man1/anm.1	(revision 9)
+++ /trunk/minix/man/man1/anm.1	(revision 9)
@@ -0,0 +1,63 @@
+.TH ANM 1
+.SH NAME
+anm \- print name list
+.SH SYNOPSIS
+\fBanm \fR[\fB\-gnoprus\fR] \fIfile\fR ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-g" "Global symbols only"
+.FL "\-n" "Sort numerically"
+.FL "\-o" "Prepend the filename to each line"
+.FL "\-p" "No sorting\(emuse symbol table order"
+.FL "\-r" "Sort in reverse order"
+.FL "\-u" "List undefined symbols only"
+.FL "\-s" "Sort in section order"
+.SH EXAMPLES
+.EX "anm  \-gn  test.o" "Print global symbols in numerical order"
+.SH DESCRIPTION
+.PP
+.I Anm
+prints the name list (symbol table) of each ACK format object
+.I file
+in the argument list.
+If no file name is given, \fIa.out\fR is used.
+Each symbol name is preceded by its value, a section indicator
+and a type indicator.
+The section indicators are:
+.PP
+.ta 0.25i 0.50i
+.nf
+	\fBU\fR	Undefined symbol
+	\fBA\fR	Absolute symbol
+	\fB\-\fR	Other symbol
+.sp
+The type indicators are:
+.PP
+	\fBF\fR	Filename
+	\fBM\fR	Module name
+	\fBS\fR	Section name
+	\fBE\fR	External (global) symbol
+	\fB\-\fR	Local symbol
+.fi
+.PP
+The output is sorted alphabetically, unless otherwise specified.
+Notice that \fIanm\fR can only be used on ACK format object files 
+(that is: \fI.o\fR and \fI.out\fR files). 
+If you want to get the name list of an executable program use 
+.I nm
+instead.
+.SH "SEE ALSO"
+.BR asize (1),
+.BR nm (1),
+.BR ar (1),
+.BR size (1).
Index: /trunk/minix/man/man1/ar.1
===================================================================
--- /trunk/minix/man/man1/ar.1	(revision 9)
+++ /trunk/minix/man/man1/ar.1	(revision 9)
@@ -0,0 +1,56 @@
+.TH AR 1
+.SH NAME
+ar, aal \- archivers
+.SH SYNOPSIS
+\fBar\fR [\fBdmpqrtx\fR][\fBabciluv\fR]\fR [\fIposname\fR] \fIarchive\fR [\fIfile \fR...]\fR
+.br
+\fBaal\fR [\fBdpqrtx\fR][\fBclv\fR]\fR \fIarchive\fR [\fIfile \fR...]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "ar r libc.a sort.s" "Replace \fIsort\fR.s in \fIlibc.a\fR"
+.EX "ar rb a.s libc.a b.s" "Insert \fIb.s\fR before \fIa.s\fR in \fIlibc.a\fR"
+.SH DESCRIPTION
+.PP
+\fIAr\fR allows groups of files to be put together into a single archive.
+It is normally used for libraries of compiled procedures.  \fIAal\fR is like
+\fIar\fP, but is to be used with the ACK compiler.  The following keys
+are allowed:
+.PP
+.ta 0.25i 0.50i
+.nf
+	\fBd\fR:	Delete. \fIAr\fR will delete the named members.
+	\fBm\fR:	Move named files. \fIAr\fR expects \fIa\fR, \fIb\fR, or \fIi\fR to be specified.
+	\fBp\fR:	Print the named files (list them on \fIstdout\fR)
+	\fBq\fR:	Quickly append to the end of the archive file.
+	\fBr\fR:	Replace (append when not in archive).
+	\fBt\fR:	Print the archive's table of contents.
+	\fBx\fR:	Extract
+.fi
+.PP
+\fBThe keys may optionally concatencated with one or more of the following\fR:
+.nf
+.PP
+	\fBa\fR:	After \fIposname\fR
+	\fBb\fR:	Before \fIposname\fR
+	\fBc\fR:	Create  (suppresses creation message)
+	\fBi\fR:	Before \fIposname\fR
+	\fBl\fR:	Local temporary file for work instead of \fI/tmp/ar.$$$$$\fR
+	\fBu\fR:	Replace only if dated later than member in archive
+	\fBv\fR:	Verbose
+.PP
+.fi
+.SH "SEE ALSO"
+.BR anm (1),
+.BR asize (1),
+.BR nm (1),
+.BR size (1).
Index: /trunk/minix/man/man1/ash.1
===================================================================
--- /trunk/minix/man/man1/ash.1	(revision 9)
+++ /trunk/minix/man/man1/ash.1	(revision 9)
@@ -0,0 +1,1124 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Kenneth Almquist.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)sh.1	5.1 (Berkeley) 3/7/91
+.\"
+.TH SH 1 "March 7, 1991"
+.UC 7
+.de h \" subheading
+.sp
+.ti -0.3i
+.B "\\$1"
+.PP
+..
+.de d \" begin display
+.sp
+.in +4
+.nf
+..
+.de e \" end display
+.in -4
+.fi
+.sp
+..
+.de c \" command, etc.
+.br
+.HP 3
+\fB\\$1\fR
+.br
+..
+.de b \" begin builtin command
+.HP 3
+.B \\$1
+..
+.SH NAME
+ash, sh, ., break, case, cd, command, continue, eval, exec, exit, export, for, getopts, hash, if, jobs, local, read, readonly, return, set, setvar, shift, trap, umask, unset, wait, while \- a shell
+.SH SYNOPSIS
+.B ash
+[
+.B -efIijnsxz
+] [
+.B +efIijnsxz
+] [
+.B -c
+.I command
+] [
+.I arg
+] ...
+.SH COPYRIGHT
+Copyright 1989 by Kenneth Almquist.
+.SH DESCRIPTION
+.I Ash
+is a version of
+.I sh
+with features similar to those of the System V shell.
+This manual page lists all the features of
+.I ash
+but concentrates on the ones not in other shells.
+.h "Invocation"
+If the
+.B -c
+options is given, then the shell executes the specified shell command.
+The
+.B -s
+flag cause the shell to read commands from the standard input (after
+executing any command specified with the
+.B -c
+option.
+If neither the
+.B -s
+or
+.B -c
+options are set, then the first
+.I arg
+is taken as the name of a file to read commands from.
+If this is impossible because there are no arguments following
+the options, then
+.I ash
+will set the
+.B -s
+flag and will read commands from the standard input.
+.PP
+The shell sets the initial value of the positional parameters from the
+.IR arg s
+remaining after any
+.I arg
+used as the name of a file of commands is deleted.
+.PP
+The flags (other than
+.BR -c )
+are set by preceding them with ``-'' and cleared by preceding them
+with ``+''; see the
+.I set
+builtin command for a list of flags.
+If no value is specified for the
+.B -i
+flag, the
+.B -s
+flag is set, and the standard input and output of the shell
+are connected to terminals, then the
+.B -i
+flag will be set.
+If no value is specified for the
+.B -j
+flag, then the
+.B -j
+flag will be set if the
+.B -i
+flag is set.
+.PP
+When the shell is invoked with the
+.B -c
+option, it is good practice to include the
+.I -i
+flag if the command was entered interactively by a user.
+For compatibility with the System V shell, the
+.I -i
+option should come after the
+.B -c
+option.
+.PP
+If the first character of argument zero to the shell is ``-'',
+the shell is assumed to be a login shell, and the files
+.B /etc/profile
+and
+.B .profile
+are read if they exist.
+If the environment variable SHINIT is set on entry to the shell,
+the commands in SHINIT are normally parsed and executed.  SHINIT is
+not examined if the shell is a login shell, or if it the shell is running a
+shell procedure.   (A shell is considered to be running a shell
+procedure if neither the
+.B -s
+nor the
+.B -c
+options are set.)
+.h "Control Structures"
+A
+.I list
+is a sequence of zero or more commands separated by newlines,
+semicolons, or ampersands, and optionally terminated by one of these
+three characters.  (This differs from the System V shell, which
+requires a list to contain at least one command in most cases.)  The
+commands in a list are executed in the order they are written.
+If command is followed by an ampersand, the shell starts the command
+and immediately proceed onto the next command; otherwise it waits
+for the command to terminate before proceeding to the next one.
+.PP
+``&&'' and ``||'' are binary operators.
+``&&'' executes the first command, and then executes the second command
+iff the exit status of the first command is zero.  ``||'' is similar,
+but executes the second command iff the exit status of the first command
+is nonzero.  ``&&'' and ``||'' both have the same priority.
+.PP
+The ``|'' operator is a binary operator which feeds the standard output
+of the first command into the standard input of the second command.
+The exit status of the ``|'' operator is the exit status of the second
+command.  ``|'' has a higher priority than ``||'' or ``&&''.
+.PP
+An
+.I if
+command looks like
+.d
+\fBif\fR list
+\fBthen\fR	list
+.ti -\w'[ 'u
+[ \fBelif\fR list
+  \fBthen\fR	list ] ...
+.ti -\w'[ 'u
+[ \fBelse\fR	list ]
+\fBfi\fR
+.e
+.PP
+A
+.I while
+command looks like
+.d
+\fBwhile\fR list
+\fBdo\fR	list
+\fBdone\fR
+.e
+The two lists are executed repeatedly while the exit status of the first
+list is zero.  The
+.I until
+command is similar, but has the word
+.B until
+in place of
+.B while
+ repeats until the exit status of the first list
+is zero.
+.PP
+The
+.I for
+command looks like
+.d
+\fBfor\fR variable \fBin\fR word...
+\fBdo\fR	list
+\fBdone\fR
+.e
+The words are expanded, and then the list is executed repeatedly with
+the variable set to each word in turn.
+.B do
+and
+.B done
+may be replaced with
+``{'' and ``}''.
+.PP
+The
+.I break
+and
+.I continue
+commands look like
+.d
+\fBbreak\fR [ num ]
+\fBcontinue\fR [ num ]
+.e
+.I Break
+terminates the
+.I num
+innermost
+.I for
+or
+.I while
+loops.
+.I Continue
+continues with the next iteration of the
+.IRnum'th
+innermost loop.
+These are implemented as builtin commands.
+.PP
+The
+.I case
+command looks like
+.d
+\fBcase\fR word \fBin\fR
+pattern\fB)\fR list \fB;;\fR
+\&...
+\fBesac\fR
+.e
+The pattern can actually be one or more patterns (see
+.I Patterns
+below), separated by ``|'' characters.
+.PP
+Commands may be grouped by writing either
+.d
+\fB(\fRlist\fB)\fR
+.e
+or
+.d
+\fB{\fR list; \fB}\fR
+.e
+The first of these executes the commands in a subshell.
+.PP
+A function definition looks like
+.d
+name \fB( )\fR command
+.e
+A function definition is an executable statement; when executed it installs
+a function named
+.B name
+and returns an exit status of zero.
+The command is normally a list enclosed between ``{'' and ``}''.
+.PP
+Variables may be declared to be local to a function by using a
+.I local
+command.  This should appear as the first staement of a function,
+and looks like
+.d
+\fBlocal\fR [ variable | \fB-\fR ] ...
+.e
+.I Local
+is implemented as a builtin command.
+.PP
+When a variable is made local, it inherits the initial value and
+exported and readonly flags from the variable with the same name in the
+surrounding scope, if there is one.  Otherwise, the variable is
+initially unset.
+.I Ash
+uses dynamic scoping, so that if you make the variable
+.B x
+local to function
+.IR f ,
+which then calls function
+.IR g ,
+references to the variable
+.B x
+made inside
+.I g
+will refer to the variable
+.B x
+declared inside
+.IR f ,
+not to the global variable named
+.BR x .
+.PP
+The only special parameter that can be made local is ``\fB-\fR''.
+Making ``\fB-\fR'' local any shell options that are changed via the
+.I set
+command inside the function to be restored to their original values
+when the function returns.
+.PP
+The
+.I return
+command looks like
+.d
+\fBreturn\fR [ exitstatus ]
+.e
+It terminates the currently executing function.
+.I Return
+is implemented as a builtin command.
+.h "Simple Commands"
+A simple command is a sequence of words.  The execution of a simple
+command proceeds as follows.  First, the leading words of the form
+``name=value'' are stripped off and assigned to the environment of
+the command.  Second, the words are expanded.  Third, the first
+remaining word is taken as the command name that command is located.
+Fourth, any redirections are performed.  Fifth, the command is
+executed.  We look at these operations in reverse order.
+.PP
+The execution of the command varies with the type of command.
+There are three types of commands:  shell functions, builtin commands,
+and normal programs.
+.PP
+When a shell function is executed, all of the shell positional parameters
+(except $0, which remains unchanged) are set to the parameters to the shell
+function.  The variables which are explicitly placed in the environment
+of the command (by placing assignments to them before the function name)
+are made local to the function and are set to values given.
+Then the command given in the function definition is executed.
+The positional parameters are restored to their original values when
+the command completes.
+.PP
+Shell builtins are executed internally to the shell, without spawning
+a new process.
+.PP
+When a normal program is executed, the shell runs the program, passing
+the parameters and the environment to the program.  If the program is
+a shell procedure, the shell will interpret the program in a subshell.
+The shell will reinitialize itself in this case, so that the effect
+will be as if a new shell had been invoked to handle the shell procedure,
+except that the location of commands located in the parent shell will
+be remembered by the child.  If the program is a file beginning with
+``#!'', the remainder of the first line specifies an interpreter for
+the program.  The shell (or the operating system, under Berkeley UNIX)
+will run the interpreter in this case.  The arguments to the interpreter
+will consist of any arguments given on the first line of the program,
+followed by the name of the program, followed by the arguments passed
+to the program.
+.h "Redirection"
+Input/output redirections can be intermixed with the words in a simple
+command and can be placed following any of the other commands.  When
+redirection occurs, the shell saves the old values of the file descriptors
+and restores them when the command completes.  The ``<'', ``>'', and ``>>''
+redirections open a file for input, output, and appending, respectively.
+The ``<&digit'' and ``>&digit'' makes the input or output a duplicate
+of the file descriptor numbered by the digit.  If a minus sign is used
+in place of a digit, the standard input or standard output are closed.
+.PP
+The ``<<\ word'' redirection
+takes input from a
+.I here
+document.
+As the shell encounters ``<<'' redirections, it collects them.  The
+next time it encounters an unescaped newline, it reads the documents
+in turn.  The word following the ``<<'' specifies the contents of the
+line that terminates the document.  If none of the quoting methods
+('', "", or \e) are used to enter the word, then the document is treated
+like a word inside double quotes:  ``$'' and backquote are expanded
+and backslash can be used to escape these and to continue long lines.
+The word cannot contain any variable or command substitutions, and
+its length (after quoting) must be in the range of 1 to 79 characters.
+If ``<<-'' is used in place of ``<<'', then leading tabs are deleted
+from the lines of the document.  (This is to allow you do indent shell
+procedures containing here documents in a natural fashion.)
+.PP
+Any of the preceding redirection operators may be preceded by a single
+digit specifying the file descriptor to be redirected.  There cannot
+be any white space between the digit and the redirection operator.
+.h "Path Search"
+When locating a command, the shell first looks to see if it has a
+shell function by that name.  Then, if PATH does not contain an
+entry for "%builtin", it looks for a builtin command by that name.
+Finally, it searches each entry in PATH in turn for the command.
+.PP
+The value of the PATH variable should be a series of entries separated
+by colons.
+Each entry consists of a directory name, or a directory name followed
+by a flag beginning with a percent sign.
+The current directory should be indicated by an empty directory name.
+.PP
+If no percent sign is present, then the entry causes the shell to
+search for the command in the specified directory.  If the flag is
+``%builtin'' then the list of shell builtin commands is searched.
+If the flag is ``%func'' then the directory is searched for a file which
+is read as input to the shell.  This file should define a function
+whose name is the name of the command being searched for.
+.PP
+Command names containing a slash are simply executed without performing
+any of the above searches.
+.h "The Environment"
+The environment of a command is a set of name/value pairs.  When the
+shell is invoked, it reads these names and values, sets the shell
+variables with these names to the corresponding values, and marks
+the variables as exported.  The
+.I export
+command can be used to mark additional variables as exported.
+.PP
+The environment of a command is constructed by constructing name/value
+pairs from all the exported shell variables, and then modifying this
+set by the assignments which precede the command, if any.
+.h "Expansion"
+The process of evaluating words when a shell procedure is executed is
+called
+.IR expansion .
+Expansion consists of four steps:  variable substitution, command
+substitution, word splitting, and file name generation.  If a word
+is the expression following the word
+.B case
+in a case statement, the file name
+which follows a redirection symbol, or an assignment to the environment
+of a command, then the word cannot be split into multiple words.  In
+these cases, the last two steps of the expansion process are omitted.
+.h "Variable Substitution"
+To be written.
+.h "Command Substitution"
+.I Ash
+accepts two syntaxes for command substitution:
+.d
+`\fIlist\fR`
+.e
+and
+.d
+$(\fIlist\fR)
+.e
+Either of these may be included in a word.
+During the command substitution process, the command (syntactly a
+.IR list )
+will be executed and anything that the command writes to the standard
+output will be captured by the shell.  The final newline (if any) of
+the output will be deleted; the rest of the output will be substituted
+for the command in the word.
+.h "Word Splitting"
+When the value of a variable or the output of a command is substituted,
+the resulting text is subject to word splitting, unless the dollar sign
+introducing the variable or backquotes containing the text were enclosed
+in double quotes.  In addition, ``$@'' is subject to a special type of
+splitting, even in the presence of double quotes.
+.PP
+Ash uses two different splitting algorithms.  The normal approach, which
+is intended for splitting text separated by which space, is used if the
+first character of the shell variable IFS is a space.  Otherwise an alternative
+experimental algorithm, which is useful for splitting (possibly empty)
+fields separated by a separator character, is used.
+.PP
+When performing splitting, the shell scans the replacement text looking
+for a character (when IFS does not begin with a space) or a sequence of
+characters (when IFS does begin with a space), deletes the character or
+sequence of characters, and spits the word into two strings at that
+point.  When IFS begins with a space, the shell deletes either of the
+strings if they are null.  As a special case, if the word containing
+the replacement text is the null string, the word is deleted.
+.PP
+The variable ``$@'' is special in two ways.  First, splitting takes
+place between the positional parameters, even if the text is enclosed
+in double quotes.  Second, if the word containing the replacement
+text is the null string and there are no positional parameters, then
+the word is deleted.  The result of these rules is that "$@" is
+equivalent to "$1" "$2" ... "$\fIn\fR", where \fIn\fR is the number of
+positional parameters.  (Note that this differs from the System V shell.
+The System V documentation claims that "$@" behaves this way; in fact
+on the System V shell "$@" is equivalent to "" when there are no
+positional paramteters.)
+.h "File Name Generation"
+Unless the
+.B -f
+flag is set, file name generation is performed after word splitting is
+complete.  Each word is viewed as a series of patterns, separated by
+slashes.  The process of expansion replaces the word with the names of
+all existing files whose names can be formed by replacing each pattern
+with a string that matches the specified pattern.  There are two
+restrictions on this:  first, a pattern cannot match a string containing
+a slash, and second, a pattern cannot match a string starting with a
+period unless the first character of the pattern is a period.
+.PP
+If a word fails to match any files and the
+.B -z
+flag is not set, then the word will be left unchanged (except that the
+meta-characters will be converted to normal characters).  If the
+.B -z
+flag is set, then the word is only left unchanged if none
+of the patterns contain a character that can match anything besides
+itself.  Otherwise the
+.B -z
+flag forces the word to be replaced with the names of the files that it
+matches, even if there are zero names.
+.h "Patterns"
+A
+.I pattern
+consists of normal characters, which match themselves, and meta-characters.
+The meta-characters are ``!'', ``*'', ``?'', and ``[''.  These characters lose
+there special meanings if they are quoted.  When command or variable
+substitution is performed and the dollar sign or back quotes are not
+double quoted, the value of the variable or the output of the command
+is scanned for these characters and they are turned into meta-characters.
+.PP
+Two exclamation points at the beginning of a pattern function as a ``not''
+operator, causing the pattern to match any string that the remainder of
+the pattern does
+.I not
+match.  Other occurances of exclamation points in a pattern match
+exclamation points.  Two exclamation points are required rather than one
+to decrease the incompatibility with the System V shell (which does not
+treat exclamation points specially).
+.PP
+An asterisk (``*'') matches any string of characters.
+A question mark matches any single character.
+A left bracket (``['') introduces a character class.  The end of the
+character class is indicated by a ``]''; if the ``]'' is missing then
+the ``['' matches a ``['' rather than introducing a character class.
+A character class matches any of the characters between the square
+brackets.  A range of characters may be specified using a minus sign.
+The character class may be complemented by making an exclamation point
+the first character of the character class.
+.PP
+To include a ``]'' in a character class, make it the first character listed
+(after the ``!'', if any).
+To include a minus sign, make it the first or last character listed.
+.h "The /u Directory"
+By convention, the name ``/u/user'' refers to the home directory of the
+specified user.  There are good reasons why this feature should be supported
+by the file system (using a feature such as symbolic links) rather than
+by the shell, but
+.I ash
+is capable of performing this mapping if the file system doesn't.
+If the mapping is done by
+.IR ash ,
+setting the
+.B -f
+flag will turn it off.
+.h "Character Set"
+.I Ash
+silently discards nul characters.  Any other character will be handled
+correctly by
+.IR ash ,
+including characters with the high order bit set.
+.h "Job Names and Job Control"
+The term
+.I job
+refers to a process created by a shell command, or in the case of a
+pipeline, to the set of processes in the pipeline.  The ways to refer
+to a job are:
+.d
+%\fInumber\fR
+%\fIstring\fR
+%%
+\fIprocess_id\fR
+.e
+The first form identifies a job by job number.
+When a command is run,
+.I ash
+assigns it a job number
+(the lowest unused number is assigned).
+The second form identifies a job by giving a prefix of the command used
+to create the job.  The prefix must be unique.  If there is only one job,
+then the null prefix will identify the job, so you can refer to the job
+by writing ``%''.  The third form refers to the \fIcurrent job\fR.  The
+current job is the last job to be stopped while it was in the foreground.
+(See the next paragraph.)  The last form identifies a job by giving the
+process id of the last process in the job.
+.PP
+If the operating system that
+.I ash
+is running on supports job control,
+.I ash
+will allow you to use it.
+In this case, typing the suspend character (typically ^Z) while running
+a command will return you to
+.I ash
+and will make the suspended command the current job.  You can then continue
+the job in the background by typing
+.IR bg ,
+or you can continue it in the foreground by typing
+.IR fg .
+.h "Atty"
+If the shell variable ATTY is set, and the shell variable TERM is not
+set to ``emacs'', then \fIash\fR generates appropriate escape sequences
+to talk to
+.IR atty (1).
+.h "Exit Statuses"
+By tradition, an exit status of zero means that a command has succeeded
+and a nonzero exit status indicates that the command failed.  This is
+better than no convention at all, but in practice it is extremely useful
+to allow commands that succeed to use the exit status to return information
+to the caller.  A variety of better conventions have been proposed, but
+none of them has met with universal approval.  The convention used by
+\fIash\fR and all the programs included in the \fIash\fR distribution is
+as follows:
+.ta 1i 2i
+.nf
+	0	Success.
+	1	Alternate success.
+	2	Failure.
+	129-...	Command terminated by a signal.
+.fi
+The \fIalternate success\fR return is used by commands to indicate various
+conditions which are not errors but which can, with a little imagination,
+be conceived of as less successful than plain success.  For example,
+.I test
+returns 1 when the tested condition is false and
+.I getopts
+returns 1 when there are no more options.
+Because this convention is not used universally, the
+.B -e
+option of
+.I ash
+causes the shell to exit when a command returns 1 even though that
+contradicts the convention described here.
+.PP
+When a command is terminated by a signal, the uses 128 plus the signal
+number as the exit code for the command.
+.h "Builtin Commands"
+This concluding section lists the builtin commands which are builtin
+because they need to perform some operation that can't be performed by a
+separate process.  In addition to these, there are several other commands
+.RI ( catf ,
+.IR echo ,
+.IR expr ,
+.IR line ,
+.IR nlecho ,
+.IR test ,
+.RI  `` : '',
+and
+.IR true )
+which can optionally be compiled into the shell.  The builtin
+commands described below that accept options use the System V Release 2
+.IR getopt (3)
+syntax.
+.sp
+.b bg
+[
+.I job
+] ...
+.br
+Continue the specified jobs (or the current job if no jobs are given)
+in the background.
+This command is only available on systems with Bekeley job control.
+.b command
+.IR "command arg" ...
+.br
+Execute the specified builtin command.  (This is useful when you have a
+shell function with the same name as a builtin command.)
+.b cd
+[
+.I directory
+]
+.br
+Switch to the specified directory (default $HOME).
+If the an entry for CDPATH appears in the environment of the cd command
+or the shell variable CDPATH is set and the directory name does not
+begin with a slash, then the directories listed in CDPATH will be
+searched for the specified directory.  The format of CDPATH is the
+same as that of PATH.
+In an interactive shell, the cd command will print out the name of the
+directory that it actually switched to if this is different from the
+name that the user gave.  These may be different either because
+the CDPATH mechanism was used or because a symbolic link was crossed.
+.\" .b ".\fI\h'0.1i'file"
+.\" Cawf can't do \h'0.1i'
+.b .
+.I file
+.br
+The commands in the specified file are read and executed by the shell.
+A path search is not done to find the file because the directories in
+PATH generally contain files that are intended to be executed, not read.
+.b eval
+.IR string ...
+.br
+The strings are parsed as shell commands and executed.
+(This differs from the System V shell, which concatenates the arguments
+(separated by spaces) and parses the result as a single command.)
+.b exec
+[
+.IR "command arg" ...
+]
+.br
+Unless
+.I command
+is omitted,
+the shell process is replaced with the specified program (which must be a real
+program, not a shell builtin or function).
+Any redirections on the exec command are marked as permanent, so that they
+are not undone when the exec command finishes.
+If the command is not found, the exec command causes the shell to exit.
+.b exit
+[
+.I exitstatus
+]
+.br
+Terminate the shell process.  If
+.I exitstatus
+is given it is used as the
+exit status of the shell; otherwise the exit status of the preceding
+command is used.
+.b export
+.IR name ...
+.br
+The specified names are exported so that they will appear in the environment
+of subsequent commands.  The only way to un-export a variable is to unset it.
+.I Ash
+allows the value of a variable to be set at the same time it is exported
+by writing
+.d
+\fBexport\fR name=value
+.e
+With no arguments the export command lists the names of all exported variables.
+.b fg
+[
+.I job
+]
+.br
+Move the specified job or the current job to the foreground.
+This command is only available on systems with Bekeley job control.
+.b getopts
+.I optstring
+.I var
+.br
+The System V
+.I getopts
+command.
+.b hash
+.B -rv
+.IR command ...
+.br
+The shell maintains a hash table which remembers the locations of
+commands.  With no arguments whatsoever, the hash command prints
+out the contents of this table.  Entries which have not been looked
+at since the last
+.I cd
+command are marked with an asterisk; it is possible for these entries
+to be invalid.
+.sp
+With arguments, the hash command removes the specified commands from
+the hash table (unless they are functions) and then locates them.
+With the
+.B -v
+option,
+.I hash
+prints the locations of the commands as it finds them.
+The
+.B -r
+option causes the
+.I hash
+command to delete all the entries in the hash table except for
+functions.
+.b jobid
+[
+.I job
+]
+.br
+Print the process id's of the processes in the job.  If the job argument
+is omitted, use the current job.
+.b jobs
+.br
+This command lists out all the background processes which are children
+of the current shell process.
+.b pwd
+.br
+Print the current directory.  The builtin command may differ from the
+program of the same name because the builtin command remembers what
+the current directory is rather than recomputing it each time.  This
+makes it faster.  However, if the current directory is renamed, the
+builtin version of pwd will continue to print the old name for the
+directory.
+.b read
+[
+.B -p
+.I prompt
+]
+[
+.B -e
+]
+.IR variable ...
+.br
+The prompt is printed if the
+.B -p
+option is specified and the standard input is a terminal.  Then a
+line is read from the standard input.  The trailing newline is deleted
+from the line and the line is split as described
+in the section on word splitting above, and the pieces are assigned to
+the variables in order.  If there are more pieces than variables, the
+remaining pieces (along with the characters in IFS that separated them)
+are assigned to the last variable.  If there are more variables than
+pieces, the remaining variables are assigned the null string.
+.sp
+The
+.B -e
+option causes any backslashes in the input to be treated specially.
+If a backslash is followed by a newline, the backslash and the newline
+will be deleted.  If a backslash is followed by any other character,
+the backslash will be deleted and the following character will be treated
+as though it were not in IFS, even if it is.
+.b readonly
+.IR name ...
+.br
+The specified names are marked as read only, so that they cannot be
+subsequently modified or unset.
+.I Ash
+allows the value of a variable to be set at the same time it is marked
+read only by writing
+.d
+\fBreadonly\fR name=value
+.e
+With no arguments the readonly command lists the names of all
+read only variables.
+.b set
+[
+{
+.BI - options
+|
+.BI + options
+|
+.B --
+}
+]
+.IR arg ...
+.br
+The
+.I set
+command performs three different functions.
+.sp
+With no arguments, it lists the values of all shell variables.
+.sp
+If options are given, it sets the specified option flags, or clears
+them if the option flags are introduced with a
+.B +
+rather than a
+.BR - .
+Only the first argument to
+.I set
+can contain options.
+The possible options are:
+.sp
+.ta 0.4i
+.in +0.4i
+.ti -0.4i
+\fB-e\fR	Causes the shell to exit when a command terminates with
+a nonzero exit status, except when the exit status of the command is
+explicitly tested.  The exit status of a command is considered to be
+explicitly tested if the command is used to control an
+.IR if ,
+.IR elif ,
+.IR while ,
+or
+.IR until ;
+or if the command is the left hand operand of an ``&&'' or ``||''
+operator.
+.sp
+.ti -0.4i
+\fB-f\fR	Turn off file name generation.
+.sp
+.ti -0.4i
+\fB-I\fR	Cause the shell to ignore end of file conditions.
+(This doesn't apply when the shell a script sourced using the ``.''
+command.)  The shell will in fact exit if it gets 50 eof's in a
+row.
+.sp
+.ti -0.4i
+\fB-i\fR	Make the shell interactive.  This causes the shell to
+prompt for input, to trap interrupts, to ignore quit and terminate signals,
+and to return to the main command loop rather than exiting on error.
+.sp
+.ti -0.4i
+\fB-j\fR	Turns on Berkeley job control, on systems that support it.
+When the shell starts up, the
+.B -j
+is set by default if the
+.B -i
+flag is set.
+.sp
+.ti -0.4i
+\fB-n\fR	Causes the shell to read commands but not execute them.
+(This is marginally useful for checking the syntax of scripts.)
+.sp
+.ti -0.4i
+\fB-s\fR	If this flag is set when the shell starts up, the shell
+reads commands from its standard input.  The shell doesn't examine the
+value of this flag any other time.
+.sp
+.ti -0.4i
+\fB-x\fR	If this flag is set, the shell will print out each
+command before executing it.
+.sp
+.ti -0.4i
+\fB-z\fR	If this flag is set, the file name generation process
+may generate zero files.  If it is not set, then a pattern which does
+not match any files will be replaced by a quoted version of the pattern.
+.in -0.4i
+.sp
+The third use of the set command is to set the values of the shell's
+positional parameters to the specified
+.IR args .
+To change the positional parameters without changing any options,
+use ``\fB--\fR'' as the first argument to
+.IR set .
+If no args are present, the set command will leave the value of the
+positional parameters unchanged, so to set the positional parameters
+to set of values that may be empty, execute the command
+.d
+shift $#
+.e
+first to clear out the old values of the positional parameters.
+.b setvar
+.I variable
+.I value
+.br
+Assigns
+.I value
+to
+.IR variable .
+(In general it is better to write
+.I variable=value
+rather than using
+.IR setvar .
+.I Setvar
+is intended to be used in functions that assign values to variables whose
+names are passed as parameters.)
+.b shift
+[
+.I n
+]
+.br
+Shift the positional parameters
+.I n
+times.
+A shift sets the value of $1 to the value of $2, the value of $2 to
+the value of $3, and so on, decreasing the value of $# by one.
+If there are zero positional parameters, shifting doesn't do anything.
+.b trap
+[
+.I action
+]
+.IR signal ...
+.br
+Cause the shell to parse and execute
+.I action
+when any of the specified signals are received.
+The signals are specified by signal number.
+.I Action
+may be null or omitted;
+the former causes the specified signal to be ignored and the latter
+causes the default action to be taken.
+When the shell forks off a subshell, it resets trapped (but not ignored)
+signals to the default action.
+The trap command has no effect on signals that were ignored on entry
+to the shell.
+.b umask
+[
+.I mask
+]
+.br
+Set the value of umask (see
+.IR umask (2))
+to the specified octal value.  If the argument is omitted, the umask
+value is printed.
+.b unset
+.IR name ...
+.br
+The specified variables and functions are unset and unexported.
+If a given name corresponds to both a variable and a function, both the
+variable and the function are unset.
+.b wait
+[
+.I job
+]
+.br
+Wait for the specified job to complete and return the exit status of the
+last process in the job.  If the argument is omitted, wait for all jobs
+to complete and the return an exit status of zero.
+.SH EXAMPLES
+The following function redefines the \fIcd\fR command:
+.d
+cd() {
+	if command cd "$@"
+	then	if test -f .enter
+		then	. .enter
+		else	return 0
+		fi
+	fi
+}
+.e
+This function causes the file ``.enter'' to be read when you enter a
+directory, if it exists.  The \fIcommand\fR command is used to access the
+real \fIcd\fR command.  The ``return 0'' ensures that the function will
+return an exit status of zero if it successfully changes to a directory
+that does not contain a ``.enter'' file.  Redefining existing commands
+is not always a good idea, but this example shows that you can do it if
+you want to.
+.PP
+The suspend function distributed with
+.I ash
+looks like
+.d
+# Copyright (C) 1989 by Kenneth Almquist.  All rights reserved.
+# This file is part of ash, which is distributed under the terms
+# specified by the Ash General Public License.
+
+suspend() {
+	local -
+	set +j
+	kill -TSTP 0
+}
+.e
+This turns off job control and then sends a stop signal to the current
+process group, which suspends the shell.  (When job control is turned
+on, the shell ignores the TSTP signal.)  Job control will be turned back
+on when the function returns because ``-'' is local to the function.
+As an example of what \fInot\fR to do, consider an earlier version of
+\fIsuspend\fR:
+.d
+suspend() {
+	suspend_flag=$-
+	set +j
+	kill -TSTP 0
+	set -$suspend_flag
+}
+.e
+There are two problems with this.  First, \fBsuspend_flag\fR is a global
+variable rather than a local one, which will cause problems in the
+(unlikely) circumstance that the user is using that variable for some
+other purpose.  Second, consider what happens if shell received an interrupt
+signal after it executes the first \fIset\fR command but before it executes
+the second one.  The interrupt signal will abort the shell function, so
+that the second \fIset\fR command will never be executed and job control
+will be left off.  The first version of \fIsuspend\fR avoids this problem
+by turning job control off only in a local copy of the shell options.  The
+local copy of the shell options is discarded when the function is terminated,
+no matter how it is terminated.
+.SH HINTS
+Shell variables can be used to provide abbreviations for things which
+you type frequently.  For example, I set
+.br
+.\" \h'1i'export h=$HOME
+.\" Cawf can't do \h'1i'
+.in +1i
+export h=$HOME
+.in -1i
+.br
+in my .profile so that I can type the name of my home directory simply
+by typing ``$h''.
+.PP
+When writing shell procedures, try not to make assumptions about what is
+imported from the environment.  Explicitly unset or initialize all variables,
+rather than assuming they will be unset.  If you use cd, it is a good idea
+to unset CDPATH.
+.PP
+People sometimes use ``<&-'' or ``>&-'' to provide no input to a command
+or to discard the output of a command.  A better way to do this is
+to redirect the input or output of the command to
+.BR /dev/null .
+.PP
+Word splitting and file name generation are performed by default,
+and you have to explicitly use double quotes to suppress it.  This is
+backwards, but you can learn to live with it.  Just get in the habit of
+writing double quotes around variable and command substitutions, and
+omit them only when you really want word splitting and file name generation.
+If you want word splitting but not file name generation, use the
+.B -f
+option.
+.SH AUTHORS
+Kenneth Almquist
+.SH "SEE ALSO"
+echo(1), expr(1), line(1), pwd(1), true(1).
+.SH BUGS
+When command substitution occurs inside a here document, the commands inside
+the here document are run with their standard input closed.  For example,
+the following will not work because the standard input of the
+.I line
+command will be closed when the command is run:
+.d
+cat <<-!
+Line 1: $(line)
+Line 2: $(line)
+!
+.e
+.PP
+Unsetting a function which is currently being executed may cause strange
+behavior.
+.PP
+The shell syntax allows a here document to be terminated by an end of file
+as well as by a line containing the terminator word which follows the ``<<''.
+What this means is that if you mistype the terminator line, the shell
+will silently swallow up the rest of your shell script and stick it
+in the here document.
+.\" several minor typos corrected -- ASW 2005-01-15
Index: /trunk/minix/man/man1/asize.1
===================================================================
--- /trunk/minix/man/man1/asize.1	(revision 9)
+++ /trunk/minix/man/man1/asize.1	(revision 9)
@@ -0,0 +1,37 @@
+.TH ASIZE 1
+.SH NAME
+asize \- report the size of an object file
+.SH SYNOPSIS
+\fBasize \fIfile\fR ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "asize test.o" "Give the size of \fItest.o\fR"
+.SH DESCRIPTION
+.PP
+.I Asize
+prints for each argument
+the (decimal) number of bytes used by the different sections,
+as well as their sum in decimal and hexadecimal.
+If no
+.I file
+is given \fIa.out\fR is used.
+.I Asize
+can only be used to obtain the size of a \(M2 \fI.o\fR or \fI.out\fR file. 
+To obtain the size of an executable, use
+.I size
+instead.
+.SH "SEE ALSO"
+.BR anm (1),
+.BR nm (1),
+.BR ar (1),
+.BR size (1).
Index: /trunk/minix/man/man1/at.1
===================================================================
--- /trunk/minix/man/man1/at.1	(revision 9)
+++ /trunk/minix/man/man1/at.1	(revision 9)
@@ -0,0 +1,34 @@
+.TH AT 1
+.SH NAME
+at \- execute commands at a later time
+.SH SYNOPSIS
+\fBat \fItime\fR [\fImonth day\fR] [\fIfile\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "at 2315 Jan 31 myfile" "Myfile executed Jan 31 at 11:15 pm"
+.EX "at 0900" "Job input read from \fIstdin\fR"
+.EX "at 0711 4 29 " "Read from \fIstdin\fR, exec on April 29"
+.SH DESCRIPTION
+.PP
+\fBAt\fR prepares a file to be executed later at the specified time by 
+creating a special entry in \fB/usr/spool/at\fR.  The \fBcron\fR daemon
+takes care of executing these jobs.  It checks to see if any
+files in \fB/usr/spool/at\fR should now be run, and if so, it runs them 
+and then puts them in \fB/usr/spool/at/past\fR.
+The name of the file created in \fB/usr/spool/at\fR by \fBat\fR is
+YY.DDD.HHMM.UU (where YY, DDD, HH, and MM give the time to execute and 
+UU is a unique number).  Note that when the command runs, it will not be able 
+to use standard input unless specifically redirected.  Standard output
+will be mailed to the owner of the job.
+.SH "SEE ALSO"
+.BR cron (8).
Index: /trunk/minix/man/man1/banner.1
===================================================================
--- /trunk/minix/man/man1/banner.1	(revision 9)
+++ /trunk/minix/man/man1/banner.1	(revision 9)
@@ -0,0 +1,22 @@
+.TH BANNER 1
+.SH NAME
+banner \- print a banner
+.SH SYNOPSIS
+\fBbanner \fIarg ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "banner happy birthday" "Print a banner saying happy birthday"
+.SH DESCRIPTION
+.PP
+\fIBanner\fR prints its arguments on \fIstdout\fR using a matrix 
+of 6 x 6 pixels per character.
Index: /trunk/minix/man/man1/basename.1
===================================================================
--- /trunk/minix/man/man1/basename.1	(revision 9)
+++ /trunk/minix/man/man1/basename.1	(revision 9)
@@ -0,0 +1,33 @@
+.TH BASENAME 1
+.SH NAME
+basename, dirname \- strip off file prefixes and suffixes
+.SH SYNOPSIS
+\fBbasename \fIfile\fR [\fIsuffix\fR]\fR
+.br
+\fBdirname \fIfile\fR
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "basename /user/ast/file.c" "Strips path to yield \fIfile.c\fP"
+.EX "basename /user/file.c .c" "Strips path and \fI.c\fP to yield \fIfile\fP"
+.EX "dirname /user/file.c" "Strips basename to yield \fI/user\fP"
+.SH DESCRIPTION
+.PP
+.I Basename
+removes the initial directory names (if any) yielding the name of the
+file itself.
+If a second argument is present, it is interpreted as a suffix and is
+also stripped, if present.
+.PP
+.I Dirname
+removes the final component of a path, yielding the directory a file is in.
+.PP
+These programs are primarily used in shell scripts.
Index: /trunk/minix/man/man1/bc.1
===================================================================
--- /trunk/minix/man/man1/bc.1	(revision 9)
+++ /trunk/minix/man/man1/bc.1	(revision 9)
@@ -0,0 +1,730 @@
+.\"
+.\" bc.1 - the *roff document processor source for the bc manual
+.\"
+.\" This file is part of bc written for MINIX.
+.\" Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License , or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License
+.\" along with this program; see the file COPYING.  If not, write to
+.\" the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+.\"
+.\" You may contact the author by:
+.\" e-mail: phil@cs.wwu.edu
+.\" us-mail: Philip A. Nelson
+.\" Computer Science Department, 9062
+.\" Western Washington University
+.\" Bellingham, WA 98226-9062
+.\"
+.\"
+.TH bc 1 .\" "Command Manual" v1.02 "Feb 3, 1992"
+.SH NAME
+bc - An arbitrary precision calculator language
+.SH SYNTAX
+\fBbc\fR [ \fB-lws\fR ] [ \fI file ...\fR ]
+.SH VERSION
+This man page documents GNU bc version 1.02.
+.SH DESCRIPTION
+\fBbc\fR is a language that supports arbitrary precision numbers
+with interactive execution of statements.  There are some similarities
+in the syntax to the C programming language. 
+A standard math library is available by command line option.
+If requested, the math library is defined before processing any files.
+\fBbc\fR starts by processing code from all the files listed
+on the command line in the order listed.  After all files have been
+processed, \fBbc\fR reads from the standard input.  All code is
+executed as it is read.  (If a file contains a command to halt the
+processor, \fBbc\fR will never read from the standard input.)
+.PP
+This version of \fBbc\fR contains several extensions beyond
+traditional \fBbc\fR implementations and the POSIX draft standard.
+Command line options can cause these extensions to print a warning 
+or to be rejected.  This 
+document describes the language accepted by this processor.
+Extensions will be identified as such.
+.SS OPTIONS
+.IP -l
+Define the standard math library.
+.IP -w
+Give warnings for extensions to POSIX \fBbc\fR.
+.IP -s
+Process exactly the POSIX \fBbc\fR language.
+.SS NUMBERS
+The most basic element in \fBbc\fR is the number.  Numbers are
+arbitrary precision numbers.  This precision is both in the integer
+part and the fractional part.  All numbers are represented internally
+in decimal and all computation is done in decimal.  (This version
+truncates results from divide and multiply operations.)  There are two
+attributes of numbers, the length and the scale.  The length is the
+total number of significant decimal digits in a number and the scale
+is the total number of decimal digits after the decimal point.  For
+example:
+.nf
+.RS
+ .000001 has a length of 6 and scale of 6.
+ 1935.000 has a length of 7 and a scale of 3.
+.RE
+.fi
+.SS VARIABLES
+Numbers are stored in two types of variables, simple variables and
+arrays.  Both simple variables and array variables are named.  Names
+begin with a letter followed by any number of letters, digits and
+underscores.  All letters must be lower case.  (Full alpha-numeric
+names are an extension. In POSIX \fBbc\fR all names are a single
+lower case letter.)  The type of variable is clear by the context
+because all array variable names will be followed by brackets ([]).
+.PP
+There are four special variables, \fBscale, ibase, obase,\fR and
+\fBlast\fR.  \fBscale\fR defines how some operations use digits after the
+decimal point.  The default value of \fBscale\fR is 0. \fBibase\fR
+and \fBobase\fR define the conversion base for input and output
+numbers.  The default for both input and output is base 10.
+\fBlast\fR (an extension) is a variable that has the value of the last
+printed number.  These will be discussed in further detail where
+appropriate.  All of these variables may have values assigned to them
+as well as used in expressions.
+.SS COMMENTS
+Comments in \fBbc\fR start with the characters \fB/*\fR and end with
+the characters \fB*/\fR.  Comments may start anywhere and appear as a
+single space in the input.  (This causes comments to delimit other
+input items.  For example, a comment can not be found in the middle of
+a variable name.)  Comments include any newlines (end of line) between
+the start and the end of the comment.
+.SS EXPRESSIONS
+The numbers are manipulated by expressions and statements.  Since
+the language was designed to be interactive, statements and expressions
+are executed as soon as possible.  There is no "main" program.  Instead,
+code is executed as it is encountered.  (Functions, discussed in
+detail later, are defined when encountered.)
+.PP
+A simple expression is just a constant. \fBbc\fR converts constants
+into internal decimal numbers using the current input base, specified
+by the variable \fBibase\fR. (There is an exception in functions.)
+The legal values of \fBibase\fR are 2 through 16 (F).  Assigning a
+value outside this range to \fBibase\fR will result in a value of 2
+or 16.  Input numbers may contain the characters 0-9 and A-F. (Note:
+They must be capitals.  Lower case letters are variable names.)
+Single digit numbers always have the value of the digit regardless of
+the value of \fBibase\fR. (i.e. A = 10.)  For multi-digit numbers,
+\fBbc\fR changes all input digits greater or equal to ibase to the
+value of \fBibase\fR-1.  This makes the number \fBFFF\fR always be
+the largest 3 digit number of the input base.
+.PP
+Full expressions are similar to many other high level languages.
+Since there is only one kind of number, there are no rules for mixing
+types.  Instead, there are rules on the scale of expressions.  Every
+expression has a scale.  This is derived from the scale of original
+numbers, the operation performed and in many cases, the value of the
+variable \fBscale\fR. Legal values of the variable \fBscale\fR are
+0 to the maximum number representable by a C integer.
+.PP
+In the following descriptions of legal expressions, "expr" refers to a
+complete expression and "var" refers to a simple or an array variable.
+A simple variable is just a
+.RS
+\fIname\fR
+.RE
+and an array variable is specified as
+.RS
+\fIname\fR[\fIexpr\fR]
+.RE
+Unless specifically
+mentioned the scale of the result is the maximum scale of the
+expressions involved.
+.IP "- expr"
+The result is the negation of the expression.
+.IP "++ var"
+The variable is incremented by one and the new value is the result of
+the expression.
+.IP "-- var"
+The variable
+is decremented by one and the new value is the result of the
+expression.
+.IP "var ++"
+ The result of the expression is the value of
+the variable and then the variable is incremented by one.
+.IP "var --"
+The result of the expression is the value of the variable and then
+the variable is decremented by one.
+.IP "expr + expr"
+The result of the expression is the sum of the two expressions.
+.IP "expr - expr"
+The result of the expression is the difference of the two expressions.
+.IP "expr * expr"
+The result of the expression is the product of the two expressions.
+.IP "expr / expr"
+The result of the expression is the quotient of the two expressions.
+The scale of the result is the value of the variable \fBscale\fR.
+.IP "expr % expr"
+The result of the expression is the "remainder" and it is computed in the
+following way.  To compute a%b, first a/b is computed to \fBscale\fR
+digits.  That result is used to compute a-(a/b)*b to the scale of the
+maximum of \fBscale\fR+scale(b) and scale(a).  If \fBscale\fR is set
+to zero and both expressions are integers this expression is the
+integer remainder function.
+.IP "expr ^ expr"
+The result of the expression is the value of the first raised to the
+second. The second expression must be an integer.  (If the second
+expression is not an integer, a warning is generated and the
+expression is truncated to get an integer value.)  The scale of the
+result is \fBscale\fR if the exponent is negative.  If the exponent
+is positive the scale of the result is the minimum of the scale of the
+first expression times the value of the exponent and the maximum of
+\fBscale\fR and the scale of the first expression.  (e.g. scale(a^b)
+= min(scale(a)*b, max( \fBscale,\fR scale(a))).)  It should be noted
+that expr^0 will always return the value of 1.
+.IP "( expr )"
+This alters the standard precedence to force the evaluation of the
+expression.
+.IP "var = expr"
+The variable is assigned the value of the expression.
+.IP "var <op>= expr"
+This is equivalent to "var = var <op> expr" with the exception that
+the "var" part is evaluated only once.  This can make a difference if
+"var" is an array.
+.PP
+ Relational expressions are a special kind of expression
+that always evaluate to 0 or 1, 0 if the relation is false and 1 if
+the relation is true.  These may appear in any legal expression.
+(POSIX bc requires that relational expressions are used only in if,
+while, and for statements and that only one relational test may be
+done in them.)  The relational operators are
+.IP "expr1 < expr2"
+The result is 1 if expr1 is strictly less than expr2.
+.IP "expr1 <= expr2"
+The result is 1 if expr1 is less than or equal to expr2.
+.IP "expr1 > expr2"
+The result is 1 if expr1 is strictly greater than expr2.
+.IP "expr1 >= expr2"
+The result is 1 if expr1 is greater than or equal to expr2.
+.IP "expr1 == expr2"
+The result is 1 if expr1 is equal to expr2.
+.IP "expr1 != expr2"
+The result is 1 if expr1 is not equal to expr2.
+.PP
+Boolean operations are also legal.  (POSIX \fBbc\fR does NOT have
+boolean operations). The result of all boolean operations are 0 and 1
+(for false and true) as in relational expressions.  The boolean
+operators are:
+.IP "!expr"
+The result is 1 if expr is 0.
+.IP "expr && expr"
+The result is 1 if both expressions are non-zero.
+.IP "expr || expr"
+The result is 1 if either expression is non-zero.
+.PP
+The expression precedence is as follows: (lowest to highest)
+.nf
+.RS
+|| operator, left associative
+&& operator, left associative
+! operator, nonassociative
+Relational operators, left associative
+Assignment operator, right associative
++ and - operators, left associative
+*, / and % operators, left associative
+^ operator, right associative
+unary - operator, nonassociative
+++ and -- operators, nonassociative
+.RE
+.fi
+.PP
+This precedence was chosen so that POSIX compliant \fBbc\fR programs
+will run correctly. This will cause the use of the relational and
+logical operators to have some unusual behavior when used with
+assignment expressions.  Consider the expression:
+.RS
+a = 3 < 5
+.RE
+.PP
+Most C programmers would assume this would assign the result of "3 <
+5" (the value 1) to the variable "a".  What this does in \fBbc\fR is
+assign the value 3 to the variable "a" and then compare 3 to 5.  It is
+best to use parenthesis when using relational and logical operators
+with the assignment operators.
+.PP
+There are a few more special expressions that are provided in \fBbc\fR.
+These have to do with user defined functions and standard
+functions.  They all appear as "\fIname\fB(\fIparameters\fB)\fR".
+See the section on functions for user defined functions.  The standard
+functions are:
+.IP "length ( expression )"
+The value of the length function is the number of significant digits in the
+expression.
+.IP "read ( )"
+The read function (an extension) will read a number from the standard
+input, regardless of where the function occurs.   Beware, this can
+cause problems with the mixing of data and program in the standard input.
+The best use for this function is in a previously written program that
+needs input from the user, but never allows program code to be input
+from the user.  The value of the read function is the number read from
+the standard input using the current value of the variable 
+\fBibase\fR for the conversion base.
+.IP "scale ( expression )"
+The value of the scale function is the number of digits after the decimal
+point in the expression.
+.IP "sqrt ( expression )"
+The value of the sqrt function is the square root of the expression.  If
+the expression is negative, a run time error is generated.
+.SS STATEMENTS
+Statements (as in most algebraic languages) provide the sequencing of
+expression evaluation.  In \fBbc\fR statements are executed "as soon
+as possible."  Execution happens when a newline in encountered and
+there is one or more complete statements.  Due to this immediate
+execution, newlines are very important in \fBbc\fR. In fact, both a
+semicolon and a newline are used as statement separators.  An
+improperly placed newline will cause a syntax error.  Because newlines
+are statement separators, it is possible to hide a newline by using
+the backslash character.  The sequence "\e<nl>", where <nl> is the
+newline appears to \fBbc\fR as whitespace instead of a newline.  A
+statement list is a series of statements separated by semicolons and
+newlines.  The following is a list of \fBbc\fR statements and what
+they do: (Things enclosed in brackets ([]) are optional parts of the
+statement.)
+.IP "expression"
+This statement does one of two things.  If the expression starts with
+"<variable> <assignment> ...", it is considered to be an assignment
+statement.  If the expression is not an assignment statement, the
+expression is evaluated and printed to the output.  After the number
+is printed, a newline is printed.  For example, "a=1" is an assignment
+statement and "(a=1)" is an expression that has an embedded
+assignment.  All numbers that are printed are printed in the base
+specified by the variable \fBobase\fR. The legal values for \fB
+obase\fR are 2 through BC_BASE_MAX.  (See the section LIMITS.)  For
+bases 2 through 16, the usual method of writing numbers is used.  For
+bases greater than 16, \fBbc\fR uses a multi-character digit method
+of printing the numbers where each higher base digit is printed as a
+base 10 number.  The multi-character digits are separated by spaces.
+Each digit contains the number of characters required to represent the
+base ten value of "obase-1".  Since numbers are of arbitrary
+precision, some numbers may not be printable on a single output line.
+These long numbers will be split across lines using the "\e" as the
+last character on a line.  The maximum number of characters printed
+per line is 70.  Due to the interactive nature of \fBbc\fR printing
+a number cause the side effect of assigning the printed value the the
+special variable \fBlast\fR. This allows the user to recover the
+last value printed without having to retype the expression that
+printed the number.  Assigning to \fBlast\fR is legal and will
+overwrite the last printed value with the assigned value.  The newly
+assigned value will remain until the next number is printed or another
+value is assigned to \fBlast\fR.
+.IP "string"
+The string is printed to the output.  Strings start with a double quote
+character and contain all characters until the next double quote character.
+All characters are take literally, including any newline.  No newline
+character is printed after the string.
+.IP "\fBprint\fR list"
+The print statement (an extension) provides another method of output.
+The "list" is a list of strings and expressions separated by commas.
+Each string or expression is printed in the order of the list.  No
+terminating newline is printed.  Expressions are evaluated and their
+value is printed and assigned the the variable \fBlast\fR. Strings
+in the print statement are printed to the output and may contain
+special characters.  Special characters start with the backslash
+character (\e).  The special characters recognized by \fBbc\fR are
+"b" (bell), "f" (form feed), "n" (newline), "r" (carriage return), "t"
+(tab), and "\e" (backslash).  Any other character following the
+backslash will be ignored.  This still does not allow the double quote
+character to be part of any string.
+.IP "{ statement_list }"
+This is the compound statement.  It allows multiple statements to be
+grouped together for execution.
+.IP "\fBif\fR ( expression ) \fBthen\fR statement1 [\fBelse\fR statement2]"
+The if statement evaluates the expression and executes statement1 or
+statement2 depending on the value of the expression.  If the expression
+is non-zero, statement1 is executed.  If statement2 is present and
+the value of the expression is 0, then statement2 is executed.  (The
+else clause is an extension.)
+.IP "\fBwhile\fR ( expression ) statement"
+The while statement will execute the statement while the expression
+is non-zero.  It evaluates the expression before each execution of
+the statement.   Termination of the loop is caused by a zero
+expression value or the execution of a break statement.
+.IP "\fBfor\fR ( [expression1] ; [expression2] ; [expression3] ) statement"
+The for statement controls repeated execution of the statement.  
+Expression1 is evaluated before the loop.  Expression2 is evaluated
+before each execution of the statement.  If it is non-zero, the statement
+is evaluated.  If it is zero, the loop is terminated.  After each
+execution of the statement, expression3 is evaluated before the reevaluation
+of expression2.  If expression1 or expression3 are missing, nothing is
+evaluated at the point they would be evaluated.
+If expression2 is missing, it is the same as substituting
+the value 1 for expression2.  (The optional expressions are an
+extension. POSIX \fBbc\fR requires all three expressions.)
+The following is equivalent code for the for statement:
+.nf
+.RS
+expression1;
+while (expression2) {
+   statement;
+   expression3;
+}
+.RE
+.fi
+.IP "\fBbreak\fR"
+This statement causes a forced exit of the most recent enclosing while
+statement or for statement.
+.IP "\fBcontinue\fR"
+The continue statement (an extension)  causes the most recent enclosing
+for statement to start the next iteration.
+.IP "\fBhalt\fR"
+The halt statement (an extension) is an executed statement that causes
+the \fBbc\fR processor to quit only when it is executed.  For example,
+"if (0 == 1) halt" will not cause \fBbc\fR to terminate because the halt is
+not executed.
+.IP "\fBreturn\fR"
+Return the value 0 from a function.  (See the section on functions.)
+.IP "\fBreturn\fR ( expression )"
+Return the value of the expression from a function.  (See the section on 
+functions.)
+.SS PSEUDO STATEMENTS
+These statements are not statements in the traditional sense.  They are
+not executed statements.  Their function is performed at "compile" time.
+.IP "\fBlimits\fR"
+Print the local limits enforced by the local version of \fBbc\fR.  This
+is an extension.
+.IP "\fBquit\fR"
+When the quit statement is read, the \fBbc\fR processor
+is terminated, regardless of where the quit statement is found.  For
+example, "if (0 == 1) quit" will cause \fBbc\fR to terminate.
+.IP "\fBwarranty\fR"
+Print a longer warranty notice.  This is an extension.
+.SS FUNCTIONS
+Functions provide a method of defining a computation that can be executed
+later.  Functions in 
+.B bc
+always compute a value and return it to the caller.  Function definitions
+are "dynamic" in the sense that a function is undefined until a definition
+is encountered in the input.  That definition is then used until another
+definition function for the same name is encountered.  The new definition
+then replaces the older definition.  A function is defined as follows:
+.nf
+.RS
+\fBdefine \fIname \fB( \fIparameters \fB) { \fInewline
+\fI    auto_list   statement_list \fB}\fR
+.RE
+.fi
+A function call is just an expression of the form
+"\fIname\fB(\fIparameters\fB)\fR".
+.PP
+Parameters are numbers or arrays (an extension).  In the function definition,
+zero or more parameters are defined by listing their names separated by
+commas.  Numbers are only call by value parameters.  Arrays are only
+call by variable.  Arrays are specified in the parameter definition by
+the notation "\fIname\fB[]\fR".   In the function call, actual parameters
+are full expressions for number parameters.  The same notation is used
+for passing arrays as for defining array parameters.  The named array is
+passed by variable to the function.  Since function definitions are dynamic,
+parameter numbers and types are checked when a function is called.  Any
+mismatch in number or types of parameters will cause a runtime error.
+A runtime error will also occur for the call to an undefined function.
+.PP
+The \fIauto_list\fR is an optional list of variables that are for
+"local" use.  The syntax of the auto list (if present) is "\fBauto
+\fIname\fR, ... ;".  (The semicolon is optional.)  Each \fIname\fR is
+the name of an auto variable.  Arrays may be specified by using the
+same notation as used in parameters.  These variables have their
+values pushed onto a stack at the start of the function.  The
+variables are then initialized to zero and used throughout the
+execution of the function.  At function exit, these variables are
+popped so that the original value (at the time of the function call)
+of these variables are restored.  The parameters are really auto
+variables that are initialized to a value provided in the function
+call.  Auto variables are different than traditional local variables
+in the fact that if function A calls function B, B may access function
+A's auto variables by just using the same name, unless function B has
+called them auto variables.  Due to the fact that auto variables and
+parameters are pushed onto a stack, \fBbc\fR supports recursive functions.
+.PP
+The function body is a list of \fBbc\fR statements.  Again, statements
+are separated by semicolons or newlines.  Return statements cause the
+termination of a function and the return of a value.  There are two
+versions of the return statement.  The first form, "\fBreturn\fR", returns
+the value 0 to the calling expression.  The second form, 
+"\fBreturn ( \fIexpression \fB)\fR", computes the value of the expression
+and returns that value to the calling expression.  There is an implied
+"\fBreturn (0)\fR" at the end of every function.  This allows a function
+to terminate and return 0 without an explicit return statement.
+.PP
+Functions also change the usage of the variable \fBibase\fR.  All
+constants in the function body will be converted using the value of
+\fBibase\fR at the time of the function call.  Changes of \fBibase\fR
+will be ignored during the execution of the function except for the
+standard function \fBread\fR, which will always use the current value
+of \fBibase\fR for conversion of numbers.
+.SS MATH LIBRARY
+If \fBbc\fR is invoked with the \fB-l\fR option, a math library is preloaded
+and the default scale is set to 20.   The math functions will calculate their
+results to the scale set at the time of their call.  
+The math library defines the following functions:
+.IP "s (\fIx\fR)"
+The sine of x in radians.
+.IP "c (\fIx\fR)"
+The cosine of x in radians.
+.IP "a (\fIx\fR)"
+The arctangent of x.
+.IP "l (\fIx\fR)"
+The natural logarithm of x.
+.IP "e (\fIx\fR)"
+The exponential function of raising e to the value x.
+.IP "j (\fIn,x\fR)"
+The bessel function of integer order n of x.
+.SS EXAMPLES
+In /bin/sh,  the following will assign the value of "pi" to the shell
+variable \fBpi\fR.
+.RS
+\fB
+pi=$(echo "scale=10; 4*a(1)" | bc -l)
+\fR
+.RE
+.PP
+The following is the definition of the exponential function used in the
+math library.  This function is written in POSIX \fBbc\fR.
+.nf
+.RS
+\fB
+scale = 20
+
+/* Uses the fact that e^x = (e^(x/2))^2
+   When x is small enough, we use the series:
+     e^x = 1 + x + x^2/2! + x^3/3! + ...
+*/
+
+define e(x) {
+  auto  a, d, e, f, i, m, v, z
+
+  /* Check the sign of x. */
+  if (x<0) {
+    m = 1
+    x = -x
+  } 
+
+  /* Precondition x. */
+  z = scale;
+  scale = 4 + z + .44*x;
+  while (x > 1) {
+    f += 1;
+    x /= 2;
+  }
+
+  /* Initialize the variables. */
+  v = 1+x
+  a = x
+  d = 1
+
+  for (i=2; 1; i++) {
+    e = (a *= x) / (d *= i)
+    if (e == 0) {
+      if (f>0) while (f--)  v = v*v;
+      scale = z
+      if (m) return (1/v);
+      return (v/1);
+    }
+    v += e
+  }
+}
+\fR
+.RE
+.fi
+.PP
+The following is code that uses the extended features of \fBbc\fR to
+implement a simple program for calculating checkbook balances.  This
+program is best kept in a file so that it can be used many times 
+without having to retype it at every use.
+.nf
+.RS
+\fB
+scale=2
+print "\enCheck book program!\en"
+print "  Remember, deposits are negative transactions.\en"
+print "  Exit by a 0 transaction.\en\en"
+
+print "Initial balance? "; bal = read()
+bal /= 1
+print "\en"
+while (1) {
+  "current balance = "; bal
+  "transaction? "; trans = read()
+  if (trans == 0) break;
+  bal -= trans
+  bal /= 1
+}
+quit
+\fR
+.RE
+.fi
+.PP
+The following is the definition of the recursive factorial function.
+.nf
+.RS
+\fB
+define f (x) {
+  if (x <= 1) return (1);
+  return (f(x-1) * x);
+}
+\fR
+.RE
+.fi
+.SS DIFFERENCES
+This version of 
+.B bc
+was implemented from the POSIX P1003.2/D11 draft and contains
+several differences and extensions relative to the draft and
+traditional implementations.
+It is not implemented in the traditional way using
+.I dc(1).
+This version is a single process which parses and runs a byte code
+translation of the program.  There is an "undocumented" option (-c)
+that causes the program to output the byte code to
+the standard output instead of running it.  It was mainly used for
+debugging the parser and preparing the math library.
+.PP
+A major source of differences is
+extensions, where a feature is extended to add more functionality and
+additions, where new features are added. 
+The following is the list of differences and extensions.
+.IP LANG 11n
+This version does not conform to the POSIX standard in the processing
+of the LANG environment variable and all environment variables starting
+with LC_.
+.IP names
+Traditional and POSIX
+.B bc
+have single letter names for functions, variables and arrays.  They have
+been extended to be multi-character names that start with a letter and
+may contain letters, numbers and the underscore character.
+.IP Strings
+Strings are not allowed to contain NUL characters.  POSIX says all characters
+must be included in strings.
+.IP last
+POSIX \fBbc\fR does not have a \fBlast\fR variable.  Some implementations
+of \fBbc\fR use the period (.) in a similar way.  
+.IP comparisons
+POSIX \fBbc\fR allows comparisons only in the if statement, the while
+statement, and the second expression of the for statement.  Also, only
+one relational operation is allowed in each of those statements.
+.IP "if statement, else clause"
+POSIX \fBbc\fR does not have an else clause.
+.IP "for statement"
+POSIX \fBbc\fR requires all expressions to be present in the for statement.
+.IP "&&, ||, !"
+POSIX \fBbc\fR does not have the logical operators.
+.IP "read function"
+POSIX \fBbc\fR does not have a read function.
+.IP "print statement"
+POSIX \fBbc\fR does not have a print statement .
+.IP "continue statement"
+POSIX \fBbc\fR does not have a continue statement.
+.IP "array parameters"
+POSIX \fBbc\fR does not have array parameters.  Other implementations
+of \fBbc\fR may have call by value array parameters.
+.IP "=+, =-, =*, =/, =%, =^"
+POSIX \fBbc\fR does not require these "old style" assignment operators to
+be defined.  This version may allow these "old style" assignments.  Use
+the limits statement to see if the installed version supports them.  If
+it does support the "old style" assignment operators, the statement
+"a =- 1" will decrement \fBa\fR by 1 instead of setting \fBa\fR to the
+value -1.
+.IP "spaces in numbers"
+Other implementations of \fBbc\fR allow spaces in numbers.  For example,
+"x=1 3" would assign the value 13 to the variable x.  The same statement
+would cause a syntax error in this version of \fBbc\fR.
+.IP "errors and execution"
+This implementation varies from other implementations in terms of what
+code will be executed when syntax and other errors are found in the
+program.  If a syntax error is found in a function definition, error
+recovery tries to find the beginning of a statement and continue to
+parse the function.  Once a syntax error is found in the function, the
+function will not be callable and becomes undefined.
+Syntax errors in the interactive execution code will invalidate the
+current execution block.  The execution block is terminated by an
+end of line that appears after a complete sequence of statements.
+For example, 
+.nf
+.RS
+a = 1
+b = 2
+.RE
+.fi
+has two execution blocks and
+.nf
+.RS
+{ a = 1
+  b = 2 }
+.RE
+.fi
+has one execution block.  Any runtime error will terminate the execution
+of the current execution block.  A runtime warning will not terminate the
+current execution block.
+.IP "Interrupts"
+During an interactive session, the SIGINT signal (usually generated by
+the control-C character from the terminal) will cause execution of the
+current execution block to be interrupted.  It will display a "runtime"
+error indicating which function was interrupted.  After all runtime
+structures have been cleaned up, a message will be printed to notify the
+user that \fBbc\fR is ready for more input.  All previously defined functions
+remain defined and the value of all non-auto variables are the value at
+the point of interruption.  All auto variables and function parameters
+are removed during the
+clean up process.  During a non-interactive
+session, the SIGINT signal will terminate the entire run of \fBbc\fR.
+.SS LIMITS
+The following are the limits currently in place for this 
+.B bc
+processor.  Some of them may have been changed by an installation.
+Use the limits statement to see the actual values.
+.IP BC_BASE_MAX
+The maximum output base is currently set at 999.  The maximum input base
+is 16.
+.IP BC_DIM_MAX
+This is currently an arbitrary limit of 65535 as distributed.  Your
+installation may be different.
+.IP BC_SCALE_MAX
+The number of digits after the decimal point is limited to INT_MAX digits.
+Also, the number of digits before the decimal point is limited to INT_MAX
+digits.
+.IP BC_STRING_MAX
+The limit on the number of characters in a string is INT_MAX characters.
+.IP exponent
+The value of the exponent in the raise operation (^) is limited to LONG_MAX.
+.IP multiply
+The multiply routine may yield incorrect results if a number
+has more than LONG_MAX / 90 total digits.  For 32 bit longs, this number is
+23,860,929 digits.
+.IP "code size"
+Each function and the "main" program are limited to 10240 bytes of
+compiled byte code each.  This limit (BC_MAX_SEGS) can be easily changed
+to have more than 10 segments of 1024 bytes.
+.IP "variable names"
+The current limit on the number of unique names is 32767 for each of
+simple variables, arrays and functions.
+.SH FILES
+In most installations, \fBbc\fR is completely self-contained.
+Where executable size is of importance or the C compiler does
+not deal with very long strings, \fBbc\fR will read
+the standard math library from the file /usr/local/lib/libmath.b.
+(The actual location may vary.  It may be /lib/libmath.b.)
+.SH DIAGNOSTICS
+If any file on the command line can not be opened, \fBbc\fR will report
+that the file is unavailable and terminate.  Also, there are compile
+and run time diagnostics that should be self-explanatory.
+.SH BUGS
+Error recovery is not very good yet.
+.SH AUTHOR
+.nf
+Philip A. Nelson
+phil@cs.wwu.edu
+.fi
+.SH ACKNOWLEDGEMENTS
+The author would like to thank Steve Sommars (sesv@iwtsf.att.com) for
+his extensive help in testing the implementation.  Many great suggestions
+were given.  This is a much better product due to his involvement.
Index: /trunk/minix/man/man1/bsfilt.1
===================================================================
--- /trunk/minix/man/man1/bsfilt.1	(revision 9)
+++ /trunk/minix/man/man1/bsfilt.1	(revision 9)
@@ -0,0 +1,86 @@
+.\"	manual page for bsfilt(1)
+.\"
+.\"
+.\"	Copyright (c) 1991 Purdue University Research Foundation,
+.\"	West Lafayette, Indiana 47907.  All rights reserved.
+.\"
+.\"	Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
+.\"	University Computing Center.  Not derived from licensed software;
+.\"	derived from awf(1) by Henry Spencer of the University of Toronto.
+.\"
+.\"	Permission is granted to anyone to use this software for any
+.\"	purpose on any computer system, and to alter it and redistribute
+.\"	it freely, subject to the following restrictions:
+.\"
+.\"	1. The author is not responsible for any consequences of use of
+.\"	   this software, even if they arise from flaws in it.
+.\"
+.\"	2. The origin of this software must not be misrepresented, either
+.\"	   by explicit claim or by omission.  Credits must appear in the
+.\"	   documentation.
+.\"
+.\"	3. Altered versions must be plainly marked as such, and must not
+.\"	   be misrepresented as being the original software.  Credits must
+.\"	   appear in the documentation.
+.\"
+.\"	4. This notice may not be removed or altered.
+.\"
+.TH BSFILT 1 "February, 1991"
+.BY "Purdue University"
+.SH NAME
+bsfilt, colcrt \- a colcrt-like backspace filter
+.SH SYNOPSIS
+.B bsfilt
+[
+.B -
+] [
+.B -U
+] [ file ... ]
+.SH DESCRIPTION
+.I Bsfilt
+filters backspace sequences from the input \fIfile\fR(s)
+(standard input if none)
+in an approximation of
+.IR colcrt (1).
+Both the backspace and the character it returns to are removed,
+unless they form an underline sequence.
+Underline sequences are treated according to the settings of
+the
+.B \-
+and
+.B \-U
+options.
+.SH OPTIONS
+.TP
+.B \-
+specifies that no underlining of any kind is to be propagated.
+Without this option or the
+.B \-U
+option,
+.I bsfilt
+approximates underlining with minus signs (`-') in following lines.
+.TP
+.B \-U
+specifies that underlining with underscore (`_') and backspace (`\b')
+character sequences is permitted.
+.SH SEE ALSO
+cawf(1), colcrt(1) and nroff(1).
+.SH DIAGNOSTICS
+Diagnostic messages are delivered to the standard error file.
+.SH HISTORY
+Vic Abell of Purdue University wrote
+.I bsfilt
+to have a backspace filter for
+.IR cawf (1)
+that is independent of licensed source code.
+.SH BUGS
+The maximum length of a line that can be underlined with minus signs is
+fixed.
+.LP
+.I Bsfilt
+does not examine the characters that are being overprinted via backspace
+operations.
+Thus, overprinting that is intended to form a new character from several
+different ones is ineffective and only the last character of the
+sequence is propagated \- e. g., ``o^H+'', intended to look like
+a bullet, is reduced to `+'.
Index: /trunk/minix/man/man1/cal.1
===================================================================
--- /trunk/minix/man/man1/cal.1	(revision 9)
+++ /trunk/minix/man/man1/cal.1	(revision 9)
@@ -0,0 +1,27 @@
+.TH CAL 1
+.SH NAME
+cal \- print a calendar
+.SH SYNOPSIS
+\fBcal\fR [\fImonth\fR] \fIyear\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "cal 3 1992" "Print March 1992"
+.SH DESCRIPTION
+.PP
+\fICal\fR prints a calendar for a month or year.  The year can be 
+between 1 and 9999.  
+Note that the year 91 is not a synonym for 1991, but is itself a
+valid year about 19 centuries ago.  The calendar produced is the one used
+by England and her colonies.  Try Sept. 1752, Feb 1900, and Feb 2000.  If
+you do not understand what is going on, look up \fICalendar, Gregorian\fR in a
+good encyclopedia.
Index: /trunk/minix/man/man1/calendar.1
===================================================================
--- /trunk/minix/man/man1/calendar.1	(revision 9)
+++ /trunk/minix/man/man1/calendar.1	(revision 9)
@@ -0,0 +1,44 @@
+.TH CALENDAR 1
+.SH NAME
+calendar \- reminder service
+.SH SYNOPSIS
+\fBcalendar [\fB\-\fR] [\fB\-r\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-" "Work for every user and send mail to him"
+.FL "\-r" "Restrict multiple execution on the same day"
+.SH EXAMPLES
+.EX "calendar" "Check \fIcalendar\fR file in current directory"
+.EX "calendar" "Normary used under the control of cron(8)"
+.EX "calendar \-r" " Normary used in /etc/rc file"
+.SH DESCRIPTION
+.PP
+Basically \fIcalendar\fR program consults the file \fIcalendar\fR in the 
+current directory and display lines which contain today's or tomorrow's date.
+Month-day formats such
+as '12/25', 'Dec. 25', 'december 25', '*/25', '12/*', '*/*' are
+recognized.  The asterisk
+means 'all' days or 'all' months.  On weekends 'tomorrow' extends through 
+next Monday without any consideration about holidays.
+To prevent ambiguity, the formats '25 Dec.' and '25/12' are not recognized.
+.PP
+When an argument \fB\-\fR is present, \fIcalendar\fR works for all users
+with a file \fIcalendar\fR in their login directories and sends them mail.
+Normally this is done daily under the control of \fIcron\fR.
+.PP
+The \fB\-r\fR option does its the same job as \fB\-\fR option, but touches
+the \fIcalendar\fR to prevents further access on the same day.
+Normally this is done in the \fI/etc/rc\fR file on a machine  which may be
+booted several times in one day.
+.SH "SEE ALSO"
+.BR cron (8).
Index: /trunk/minix/man/man1/cat.1
===================================================================
--- /trunk/minix/man/man1/cat.1	(revision 9)
+++ /trunk/minix/man/man1/cat.1	(revision 9)
@@ -0,0 +1,33 @@
+.TH CAT 1
+.SH NAME
+cat \- concatenate files and write them to stdout
+.SH SYNOPSIS
+\fBcat\fR [\fB\-u\fR]\fR [\fIfile\fR] ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-u" "Unbuffered output"
+.SH EXAMPLES
+.EX "cat file" "Display file on the terminal"
+.EX "cat file1 file2 | lp" "Concatenate 2 files and print result"
+.SH DESCRIPTION
+.PP
+.I Cat
+concatenates its input files and copies the result to \fIstdout\fR.
+If no input file is named, or \- is encountered as a file name, standard
+input is used.
+Output is buffered in 512 byte blocks unless the 
+.B \-u
+flag is given.
+If you just want to copy a file, \fIcp\fR should be used since it is faster.
+.SH "SEE ALSO"
+.BR cp (1).
Index: /trunk/minix/man/man1/cawf.1
===================================================================
--- /trunk/minix/man/man1/cawf.1	(revision 9)
+++ /trunk/minix/man/man1/cawf.1	(revision 9)
@@ -0,0 +1,760 @@
+.\"	manual page for cawf(1)
+.\"
+.\"
+.\"	Copyright (c) 1991 Purdue University Research Foundation,
+.\"	West Lafayette, Indiana 47907.  All rights reserved.
+.\"
+.\"	Written by Victor A. Abell <abe@cc.purdue.edu>,  Purdue
+.\"	University Computing Center.  Not derived from licensed software;
+.\"	derived from awf(1) by Henry Spencer of the University of Toronto.
+.\"
+.\"	Permission is granted to anyone to use this software for any
+.\"	purpose on any computer system, and to alter it and redistribute
+.\"	it freely, subject to the following restrictions:
+.\"
+.\"	1. The author is not responsible for any consequences of use of
+.\"	   this software, even if they arise from flaws in it.
+.\"
+.\"	2. The origin of this software must not be misrepresented, either
+.\"	   by explicit claim or by omission.  Credits must appear in the
+.\"	   documentation.
+.\"
+.\"	3. Altered versions must be plainly marked as such, and must not
+.\"	   be misrepresented as being the original software.  Credits must
+.\"	   appear in the documentation.
+.\"
+.\"	4. This notice may not be removed or altered.
+.\"
+.\" Some of the stuff in this file is a bit contorted, because it's also
+.\" the regression-test input.
+.nr ES 5n
+.de ES
+.PP
+.in +\\n(ESu
+.nf
+..
+.de EE
+.in -\\n(ESu
+.fi
+.PP
+..
+.de PT
+.ie \\n(.$>1 .TP "\\$2"
+.el .TP
+.ie !'\\$1'' \\$1
+.el \(bu
+..
+.ds Nr \fInroff\fR
+.TH CAWF 1 "November, 1992"
+.BY "Purdue University"
+.SH NAME
+cawf, nroff \- C version of the nroff-like, Amazingly Workable (text) Formatter
+.SH SYNOPSIS
+.B cawf
+.RB [ \-c\c
+.IR config ]
+.RB [ \-d\c
+.IR device ]
+.RB [ \-e ]
+.RB [ \-f\c
+.IR font ]
+.RB [ \-h ]
+.RB [ \-m\c
+.IR acros ]
+.RI [ file " ...]"
+.SH DESCRIPTION
+.I Cawf
+formats the text from the input \fIfile\fR(s)
+(standard input if none)
+in an approximation of \*(Nr.
+It comes closest to duplicating \*(Nr's
+.B man
+or
+.B ms
+macro package styles.
+It has some limited support for \*(Nr's
+.B me
+macros.
+.SH OPTIONS
+Options must precede file names.
+.TP
+.BI \-c config
+defines an alternate path to the device configuration file.
+Normally the device configuration file is found in
+.I device.cf
+in the
+.I cawf
+library (see the
+.B FILES
+section).
+.IP
+The device configuration file contains device character strings for
+selecting fonts and the bold or italic type faces.
+See the
+.B DEVICES
+section for more information.
+.TP
+.BI \-d device
+specifies the name of the output device.
+There are three built\-in devices \- ANSI, NONE and NORMAL \- and
+other devices may be defined in the device configuration file.
+See the
+.B DEVICES
+section for more information.
+.IP
+The NORMAL device is the default.
+.TP
+.B \-e
+directs
+.I cawf
+to issue an eject (FF or ^L) after the last page.
+.TP
+.BI \-f font
+specifies the one font for the device, declared with the
+.BI \-d device
+option, that is to be used for the
+entire document.
+.I Font
+must match a font associated with the device's stanza in the device
+configuration file.
+See the
+.B DEVICES
+section for more information.
+.IP
+No
+.I font
+may be specified for the built\-in devices ANSI, NONE or NORMAL.
+.TP
+.B \-h
+requests a help display.
+.TP
+.BI \-m acro
+specifies the macro file to be used.
+The standard
+.I cawf
+distribution supplies macro files to support ``\-man'', ``\-me'' or ``\-ms''.
+.I Cawf
+finds a macro file by constructing its name from `m',
+.I acro
+and
+.B .mac
+\- e. g.,
+.BI \-m an
+is converted to
+.BR man.mac .
+The default directory for macro files is defined when
+.I cawf
+is compiled; it's \fIC:\\SYS\\LIB\\CAWF\fP in the MS\-DOS environment;
+.I /usr/lib/cawf
+in the UNIX environment.
+.TP
+file ...
+are the names of files containing \*(Nr source text.
+.SH NROFF COMPATIBILITY
+.I Cawf
+accepts the following raw \*(Nr requests:
+.ES
+\&.\e"	.ad	.bp	.br	.ce	.de	.di	.ds
+\&.el	.fi	.fl	.ft	.i0	.ie	.if	.in
+\&.it	.lg	.li	.ll	.ls	.na	.ne	.nf
+\&.nr	.ns	.pl	.po	.ps	.rm	.rn	.rr
+\&.rs	.so	.sp	.ta	.ti	.tm	.tr
+.EE
+and the following in-text codes:
+.ES
+\e$	\e%	\e*	\e"	\ec	\ef	\eh	\ek
+\en	\es	\ew
+.EE
+plus the full list of \*(Nr/\c
+.I troff
+special characters in
+the original V7 \fItroff\fR manual.
+.PP
+Many restrictions are present; the behavior in general is a subset of
+\*(Nr's.  Of particular note are the following:
+.IP \(bu 2
+The fully supported nroff request control character is the period.
+There is limited support for the  non\-break, acute accent control
+character.
+.PT
+Point sizes do not exist;
+.B .ps
+is ignored.
+.PT
+Special vertical spacing \- the
+.B .vs
+request included \- is ignored.
+.PT
+Conditionals cover only the numeric comparisons >, =, <, >= and <= on
+.BR \en(.$ ;
+string com\%par\%isons between a macro parameter and a literal;
+.B n
+(always true);
+and
+.BR t
+(always false).
+Only single line input is accepted from conditionals;
+multi\-line input \- e.g., \\(\fIanything\fP\\) \- is not supported.
+.PT
+The handling of strings is generally primitive.
+.IP \(bu
+Horizontal motion via
+.B \eh
+must be supplied with a number register interpolation and must be
+positive - e. g.,
+.BR \ew\en(NN ,
+where the value in NN is >= 0.
+.IP \(bu
+The
+.B \ek
+function is reliable only after TAB characters, so it is useful only
+for measuring table positions.
+.IP \(bu
+The
+.B .di
+request only turns output on and off \- any macro name is ignored.
+.IP \(bu
+Expressions - e. g.,
+.B .sp
+- are reasonably general, but the
+.BR | ,
+.BR & ,
+and
+.BR :\&
+operators do not exist, there must be white space between the end of the \*(Nr
+function and the beginning of the expression, and 
+.B \ew
+requires that quote (') be used as the delimiters.
+.B \ew
+counts the characters inside the quotes and scales the result in ens,
+so that, for example, \ew'\e(bu' equals 4n, and \ew'\e(bu'/1n equals 4.
+.PT
+The only acceptable count for the
+.B .it
+request is one,
+and it is effective only with
+.BR man ,
+.B me
+or
+.B ms
+macros.
+.PT
+The default scaling factor is `v' for the
+.BR .ne ,
+.BR .sp ,
+and
+.B .pl
+raw \*(Nr requests; it is `u' for
+.BR .nr ;
+and `n' for
+.BR .in ,
+.BR .ll ,
+.BR .ls ,
+.BR .po ,
+.BR .ta
+and
+.BR .ti .
+(A different scaling factor may be specified with a trailing character.)
+.PT
+Some obsolete or meaningless requests \-
+.BR .i0 ,
+.B .lg
+and
+.B .li
+\&\- are silently ignored.
+.P
+White space at the beginning of lines,
+and embedded white space within lines is dealt with properly.
+Sentence terminators at ends of lines are understood to imply
+extra space afterward in filled lines.
+Tabs are im\%plemented crudely and not exactly, although
+usually they work as expected.
+Hyphenation is done only at explicit hyphens, em-dashes, and \*(Nr
+discretionary hyphens.
+By default bold and italic characters are emulated with backspacing and
+overprinting, but the
+.B \-d
+and
+.B \-f
+options, combined with the contents of the device configuration file,
+may be used to generate special codes for bold and italic characters.
+(See the
+.B DEVICES
+section for more information.)
+.SH "MAN MACROS"
+The
+.B man
+macro set replicates the full V7 manual macros,
+plus a few semi-random oddballs.
+The full list is:
+.ES
+\&.AT	.B	.BI	.BR	.BY	.DE	.DT	.HP
+\&.I	.IB	.IP	.IR	.IX	.LP	.NB	.P
+\&.PD	.PP	.RB	.RE	.RI	.RS	.SH	.SM
+\&.SS	.TH	.TP	.UC
+.EE
+.B .BY
+and
+.B .NB
+each take a single string argument (respectively, an indi\%cation of
+authorship and a note about the status of the manual page) and arrange
+to place it in the page footer.
+.B .AT
+and
+.B .IX
+do nothing.
+.SH "ME MACROS"
+The
+.B me
+macro subset has been derived from the
+.I cawf
+.B ms
+macros by Chet Creider <creider@csd.uwo.ca>.
+It includes:
+.ES
+\&.(l	.(q	.)l	.)q	.b	.bu	.i	.ip
+\&.lp	.np	.pp	.r	.sh	.sm	.u	.uh
+.EE
+The .(l C and .(l L options are supported.
+In addition, the .AB, .AE, .AI, .AU, .DA, .ND, .TL and .UX macros have
+been retained from the
+.B ms
+set, and the .XP macro has been borrowed from the Berkeley additions to the
+.B ms
+macro set.
+.SH "MS MACROS"
+The
+.B ms
+macro set is a substantial subset of the V7 manuscript macros.
+The macros are:
+.ES
+\&.AB	.AE	.AI	.AU	.B	.CD	.DA	.DE
+\&.DS	.I	.ID	.IP	.LD	.LG	.LP	.ND
+\&.NH	.NL	.PP	.QE	.QP	.QS	.R	.RE
+\&.RP	.RS	.SH	.SM	.TL	.TP	.UL	.UX
+.EE
+Size changes are recognized but ignored, as are
+.B .RP
+and
+.BR .ND .
+.B .UL
+just prints its argument in italics.
+.BR .DS / .DE
+does not do a keep,
+nor do any of the other macros that normally imply keeps.
+.LP
+The
+.B DY
+string variable is available.
+The
+.BR PD ,
+.BR PI ,
+and
+.BR LL
+number registers exist and can be changed.
+.SH "HEADERS AND FOOTERS"
+.I Cawf
+allows the placement of text into the five line header and
+footer sections from the
+.BR LH ,
+.BR CH ,
+.BR RF ,
+.BR LF ,
+.BR CF ,
+and
+.B RF
+string variables, via the control of the
+.B .^b
+request:
+.LP
+.ta \w'.^b HF 0'u+3n
+.nf
+\&.^b fh 1	enables header string placement on the first page
+\&.^b fh 0	disables header string placement on the first page
+\&.^b HF 1	enables header/footer string placement
+\&.^b HF 0	disables header/footer string placement
+.fi
+.LP
+There are appropriate
+.B .^b
+requests in the distribution
+.BR man ,
+.B me
+and
+.B ms
+macro files.
+(The
+.B me
+and
+.B ms
+macro files use another
+.B .^b
+request, \fB.^b NH\fP, to enable numbered header processing.)
+.SH OUTPUT
+The default output format supported by
+.IR cawf ,
+in its distributed form,
+is that appropriate to a dumb terminal,
+using overprinting for italics (via underlining) and bold.
+The \*(Nr special characters are printed as some vague approximation
+(it's sometimes extremely vague) to their correct appearance.
+.PP
+One part of
+.IR cawf 's
+knowledge of the output device, related to the formation of characters,
+is established by a device file, which is read before the user's input.
+The search for it begins in
+.IR cawf 's
+library directory, under the name \fIterm\fP.\fBdev\fP
+(where \fIterm\fR is the value of the TERM environment variable).
+Failing to find that,
+.I cawf
+searches for
+.BR dumb.dev .
+(See the
+.B FILES
+section for a description of the path to
+.IR cawf 's
+library directory.)
+The device file
+uses special internal requests
+to set up resolution, special characters 
+and more normal \*(Nr functions to set up page length, etc.
+.PP
+.I Cawf
+has limited support for fonts special forms of bold and italic characters.
+It is provided through the
+.B \-c
+.IR config ,
+.BI \-d device
+and
+.BI \-f font
+options.
+See the
+.B DEVICES
+section for more information.
+.PP
+Note the distinction between the device and the output device configuration
+files.
+The device file typically defines characters and constant output parameters.
+The output device configuration file defines font and type face codes.
+It is usually not necessary to define a separate device file for each
+device represented in the output device configuration file \- the
+.I dumb.dev
+device file will suffice for almost all representations.
+.SH DEVICES
+.I Cawf
+supports primitive output device configuration for font and type face
+control.
+One font may be selected for the entire document by directing
+.I cawf
+to issue a font selection control character string at the beginning
+of the document, and control character strings may be selected for
+switching between the bold, italic and Roman type faces.
+.PP
+The
+.B \-c
+.IR config,
+.BI \-d device
+and
+.BI \-f font
+options direct the font and type face selections.
+.PP
+The
+.BI \-d device
+option specifies the name of the device.
+.I Cawf
+has three built\-in devices \- ANSI, NONE and NORMAL.
+When the ANSI device is selected,
+.I cawf
+issues the ANSI shadow mode control codes, ``ESC [ 7 m'', to represent
+the bold face;
+the ANSI underscore control codes, ``ESC [ 4 m'', to represent the italic
+face;
+and the ANSI control codes, ``ESC [ 0 m'', to represent the ROMAN face.
+No
+.BI \-f font
+specification is permitted with the ANSI device.
+.PP
+When the NONE device is selected,
+.I cawf
+uses no special output codes to represent the type faces.
+No
+.BI \-f font
+specification is permitted with the ANSI device.
+.PP
+The NORMAL output device is the default.
+When it's selected,
+.I cawf
+overprints each bold character two times, using three issuances of each
+bold character, separated by backspace characters;
+it issues an underscore and backspace before each italic character.
+No
+.BI \-f font
+specification is permitted with the ANSI device.
+The
+.IR bsfilt (1)
+filter may be used to further process the backspace codes output for
+a NORMAL device.
+.PP
+All other devices named in the
+.BI \-d device
+option must be represented by a stanza in the device configuration file.
+The device configuration file is usually contained in
+.I device.cf
+in
+.IR cawf's
+library directory (see the
+.B FILES
+section for more information).
+An alternate device configuration file path may be specified with the
+.BI \-c config
+option.
+.PP
+The
+.B DEVICE CONFIGURATION FILE
+section describes the organization of the device configuration file.
+It is easy to add devices to the
+.I device.cf
+supplied in the
+.I cawf
+distribution.
+.PP
+The
+.BI \-f font
+option may be used with the
+.BI \-d device
+option, when the appropriate stanza in the device configuration file
+contains an entry for the named
+.IR font .
+The
+.B DEVICE CONFIGURATION FILE
+section describes how fonts are defined in device configuration file
+stanzas.
+.SH DEVICE CONFIGURATION FILE
+The device configuration file defines the special character codes
+necessary to direct output devices to select fonts and to produce
+bold, italic and Roman type faces.
+.PP
+The configuration file is usually found in
+.I device.cf
+in
+.IR cawf 's
+library directory (see the
+.B FILES
+section for more information).
+It is organized into two main parts \- comments and device stanzas.
+Comments are any lines that begin with the pound sign (`#') character.
+They are informational only and
+.I cawf
+ignores them.
+.I Cawf
+also ignores empty lines, so they may be used as vertical white space.
+.PP
+Stanzas name devices and define their font and type face control strings.
+A stanza begins with the name of the device, starting at the beginning
+of a line and occupying the entire line.
+The body of the stanza, defining fonts and type faces, is formed of
+lines beginning with white space (a TAB or space characters) that
+directly follow the device name.
+.PP
+Individual lines of the stanza body contain a key character, followed
+by a equal sign, followed by the font name (if a font key) and the
+output device control codes.
+.I Cawf
+issues the font control codes once, at the beginning of output, so
+only one font may be selected.
+The type face control codes are issued at each change of type face.
+.PP
+The key characters are:
+.ne 4
+.PP
+.RS
+.nf
+b	for bold
+f	for font definition
+i	for italic
+r	for Roman
+.fi
+.RE
+.PP
+The `b', `i' and `r' key codes are followed by an equal sign (`=') and
+their control code definition.
+The `f' key code is followed by an equal sign (`='), the font name,
+another equal sign and the font control code definition.
+.PP
+Control code definitions may contain any printable ASCII characters.
+Non\-printable characters may be encoded in octal notation with the `\\nnn'
+form or in hexadecimal with the `\\xnn' form.
+The special code, `\\E' (or `\\e') represents the ESC control
+character (\\033 or \\x1b).
+.PP
+Here's a sample showing the definition for the HP LaserJet III.
+The stanza name is ``lj3''.
+All its non\-printable characters are ESCs; the first is coded in
+octal form; the second with '\\E'; the rest, in hexadecimal form.
+TAB is used as the leading white space character for the stanza
+body lines.
+.PP
+.RS
+.nf
+# HP LaserJet III
+
+lj3
+        b=\\033(s7B
+        i=\\E(s1S
+        r=\\x1b(s0B\\x1b(s0S
+        f=c10=\x1b&l0O\x1b(8U\x1b(s0p12h10v0s0b3T
+        f=c12ibm=\x1b&l0O\x1b(10U\x1b(s0p10.00h12.0v0s0b3T
+        f=lg12=\x1b&l0O\x1b(8U\x1b(s12h12v0s0b6T
+.fi
+.RE
+.PP
+The distribution
+.I device.cf
+file defines the following devices and fonts.
+.LP
+.ta \w'kxp1180'u+3n +\w'Italic:'u+3n +\w'bps10'u+6n
+.nf
+.ne 3
+epson	dot matrix printer in Epson FX-86e/FX-800 mode
+	Bold:	Double-strike
+	Fonts:	none
+
+.ne 4
+ibmppds	IBM Personal Printer Data Stream (PPDS) protocol
+	Bold:	Double-strike
+	Italic:	Underline
+	Fonts:	none
+
+.ne 12
+kxp1124	Panasonic KX\-P1124 dot matrix printer in PGM mode
+	Bold:	Emphasized
+	Fonts:	c10	10 Characters Per Inch (CPI) Courier
+		c12	12 CPI Courier
+		bps10	10 CPI Bold PS
+		bps12	12 CPI Bold PS
+		p10	10 CPI Prestige
+		p12	12 CPI Prestige
+		s10	10 CPI Script
+		s12	12 CPI Script
+		ss10	10 CPI Sans Serif
+		ss12	12 CPI Sans Serif
+
+.ne 10
+kxp1180	Panasonic KX\-P1180 dot matrix printer in PGM mode
+	Bold:	Emphasized
+	Fonts:	c10	10 Characters Per Inch (CPI) Courier
+		c12	12 CPI Courier
+		bps10	10 CPI Bold PS
+		bps12	12 CPI Bold PS
+		p10	10 CPI Prestige
+		p12	12 CPI Prestige
+		ss10	10 CPI Sans Serif
+		ss12	12 CPI Sans Serif
+
+.ne 6
+lj3	HP LaserJet III
+	Fonts:	c10	10 point, 12 Characters Per Inch (CPI)
+			Courier
+		c12ibm	12 point, 10 CPI Courier, IBM\-PC
+			Symbol Set
+		lg12	12 point, 12 CPI Letter Gothic
+
+.ne 4
+vgamono	VGA monochrome monitor for MS\-DOS
+	(ANSI.SYS driver required for MS\-DOS)
+	Italic:	Reverse-video
+	Fonts:	none
+.SH FILES
+.I Cawf
+resource files are located in the
+.I cawf
+library directory \- \fI C:\\SYS\\LIB\\CAWF\fP, the MS\-DOS environment
+default;
+or
+.IR /usr/lib/cawf ,
+the UNIX environment default.
+These defaults can be overridden by the CAWFLIB environment variable,
+or changed in the cawflib.h header file.
+
+.ta \w'device.cf'u+3n
+.nf
+common	common device-independent initialization
+device.cf	output device configurations
+*.dev	device-specific initialization
+m*.mac	macro package files
+.SH DIAGNOSTICS
+Unlike
+.IR nroff ,
+.I cawf
+complains whenever it sees unknown requests.
+All diagnostics appear on the standard error file.
+.ad
+.SH HISTORY
+Vic Abell of Purdue University <abe@cc.purdue.edu> derived
+.I cawf
+from
+.IR awf ,
+\&``the Amazingly Workable (text) Formatter,'' 
+written by Henry Spencer of the University of Toronto.
+The Toronto work was a supplement to the C News project.
+The Purdue effort was aimed at producing a C language version that
+would run on small systems, particularly MS\-DOS ones.
+The adaptation of the
+.B me
+macros was done by Chet Creider <creider@csd.uwo.ca>.
+Chet also contributed ideas for device, font and type face support.
+.PP
+The MS\-DOS version of
+.I cawf
+has been compiled with version 2.5 of Microsoft's Quick-C compiler.
+It runs under the Mortis Kern Systems Toolkit KornShell,
+.IR ksh (1),
+and COMMAND.COM.
+.SH BUGS
+Nroff and troff mavens will have many complaints.
+Some may even represent bugs and not deliberate omissions.
+.PP
+Watch out for scaling factors - especially on requests like
+.BR \ew .
+.PP
+The overprinting required to create bold and italicized characters is
+tiresome on a slow printer.
+The
+.IR bsfilt (1)
+post\-filter from this distribution may be used to alleviate that
+nuisance by managing the backspacing codes from
+.IR cawf 's
+NORMAL device output.
+.PP
+The printing of bold and italic characters is sometimes better handled by
+special printer codes.
+Use
+.IR cawf 's
+.B \-c
+.IR config ,
+.BI \-d device
+and
+.BI \-f font
+options to produce special font and device output control codes.
+.PP
+.I Cawf
+has a small amount of built-in code for the 
+.BR man ,
+.B me
+and
+.B ms
+macro packages, but none for any others.
+.PP
+The stacking for the
+.B .so
+request is limited.
+.SH SEE ALSO
+bsfilt(1),
+colcrt(1),
+man(7),
+me(7),
+ms(7)
+and
+nroff(1).
Index: /trunk/minix/man/man1/cc.1
===================================================================
--- /trunk/minix/man/man1/cc.1	(revision 9)
+++ /trunk/minix/man/man1/cc.1	(revision 9)
@@ -0,0 +1,588 @@
+.TH CC 1
+.SH NAME
+cc, pc, m2 \- MINIX 3 C, Pascal, and Modula-2 compilers
+.SH SYNOPSIS
+.in +.5i
+.ti -.5i
+.BR cc |\c
+.BR pc |\c
+.BR m2
+.RB [ "\-D \fIname\fR[\fB=\fIvalue" ]]
+\&...
+.RB [ "\-U \fIname" ]
+\&...
+.RB [ "\-I \fIdirectory" ]
+\&...
+.RB [ \-.\fIsuffix ]
+\&...
+.RB [ \-c ]
+.RB [ \-E ]
+.RB [ \-P ]
+.RB [ \-S ]
+.RB [ \-c.\fIsuffix ]
+.RB [ \-O ]
+.RB [ \-O\fIlevel ]
+.RB [ \-OS ]
+.RB [ \-OT ]
+.RB [ \-g ]
+.RB [ \-n ]
+.RB [ \-a ]
+.RB [ \-R ]
+.RB [ \-A ]
+.RB [ \-s ]
+.RB [ \-fsoft ]
+.RB [ \-fnone ]
+.RB [ \-w ]
+.RB [ \-wo ]
+.RB [ \-ws ]
+.RB [ \-wa ]
+.RB [ \-3 ]
+.RB [ \-_ ]
+.RB [ \-W\fIname\fB\-\fIoption ]
+\&...
+.RB [ \-m\fIarch ]
+.RB [ "\-o \fIoutfile" ]
+.RB [ "\-L \fIdirectory" ]
+\&...
+.RB [ \-i ]
+.RB [ \-sep ]
+.RB [ \-com ]
+.RB [ \-r ]
+.RB [ "\-stack \fIsize" ]
+.I operand
+\&...
+.sp .4v
+.ti -.5i
+(Minix-86 subset:)
+.ti -.5i
+.BR cc |\c
+.BR pc |\c
+.BR m2
+.RB [ "\-D\fIname\fR[\fB=\fIvalue" ]]
+\&...
+.RB [ "\-U\fIname" ]
+\&...
+.RB [ "\-I\fIdirectory" ]
+\&...
+.RB [ \-.o ]
+\&...
+.RB [ \-c ]
+.RB [ \-E ]
+.RB [ \-P ]
+.RB [ \-S ]
+.RB [ \-c.\fIsuffix ]
+.RB [ \-O ]
+.RB [ \-O\fIlevel ]
+.RB [ \-n ]
+.RB [ \-a ]
+.RB [ \-R ]
+.RB [ \-A ]
+.RB [ \-s ]
+.RB [ \-f ]
+.RB [ \-w ]
+.RB [ \-wo ]
+.RB [ \-ws ]
+.RB [ \-wa ]
+.RB [ \-3 ]
+.RB [ \-_ ]
+\&...
+.RB [ \-m ]
+.RB [ "\-o \fIoutfile" ]
+.RB [ "\-L\fIdirectory" ]
+\&...
+.RB [ \-i ]
+.RB [ \-sep ]
+.RB [ \-com ]
+.I operand
+\&...
+.in -.5i
+.SH DESCRIPTION
+.BR Cc ,
+.BR pc ,
+and
+.BR m2
+are the call names of the MINIX 3 C, Pascal, and Modula-2 compilers from
+the Amsterdam Compiler Kit (ACK).
+.PP
+All these call names are links to the
+.B acd
+driver program.
+.B Acd
+uses the driver description file
+.B /usr/lib/descr
+that describes the steps necessary to compile a source file.  The
+.BR acd (1)
+manual page describes a few more flags, like
+.BR \-v ,
+that may be useful for debugging compiler problems.
+.PP
+Minix-86 uses a C program as the compiler driver.  This driver is not as
+flexible as the one implemented with the
+.B acd
+driver, and offers a smaller number of options.  The second line of
+the synopsis above shows the options that the Minix-86 driver supports.  The
+rest of this manual page is geared towards the
+.B acd
+driver.  People writing software for Minix-86, or that should be
+portable to all MINIX 3 versions should stick to the options listed under
+the Minix-86 compiler.
+.SH OPTIONS
+The transformations done by the compiler are modified by the following
+options.  They are a superset of the options required by \s-2POSIX\s+2,
+with the MINIX 3 or compiler specific ones are marked as such.  Options
+for one specific compiler are ignored for others.  Read the OPTIONS section
+of
+.BR acd (1)
+for the driver specific options.
+.PP
+.TP
+.BI \-D " name\fR[\fB=\fIvalue\fR]"
+Same as if
+.BI #define " name value"
+had been given.
+.B 1
+is assumed if
+.I value
+is omitted.  This argument, like all the other double arguments, may also
+be given as a single argument.  (I.e. either as
+.BI \-D "\0name"
+or
+.BI \-D name\fR.)
+(The Minix-86 driver is not so flexible, the proper form can be seen in
+the synopsis.)
+.TP
+.BI \-U " \fIname"
+Undefine the pre-defined symbol
+.IR name .
+.TP
+.BI \-I " directory"
+Extend the include directory path with the given directory.  These
+directories are searched for include files in the given order before the
+standard places.  The standard place for the C compiler is
+.BR /usr/include ,
+and for the Modula-2 compiler it is
+.BR /usr/lib/m2 .
+.TP
+.BI \-. suffix
+Act as if a source file with the given suffix is present on the command line.
+For each language found on the command line the appropriate libraries are
+selected.  The first language mentioned selects the runtime startoff.
+The call name of the driver also chooses the language, so \fBcc\fP is an
+implicit
+.BR \-.c .
+The runtime startoff can be omitted by specifying
+.B \-.o
+for those rare cases where you want to supply your own startoff.  (MINIX 3)
+.TP
+.B \-c
+Transform the input files to object files and stop.  The
+.B \-o
+option may be used under MINIX 3 to set the name of the object file.
+.BR Make (1)
+likes this, because
+.BI "cc \-c" " dir/file" .c
+puts
+.IB file .o
+in the current directory, but
+.BI "cc \-c" " dir/file" .c
+.BI \-o " dir/file" .o
+puts the
+.B .o
+file where
+.B make
+expects it to be by its builtin
+.B .c.o
+rule.
+(Minix-86 can only use
+.B \-o
+to name an executable.)
+.TP
+.B \-E
+Run the preprocessor over the input files and send the result to standard
+output or the file named by
+.BR \-o .
+Standard input is read if an input file is named "\fB\-\fR".
+.TP
+.B \-P
+Run the preprocessor over the input files and put the result to files
+with the suffix
+.BR .i .
+File and line number information is omitted from the output.  Use
+.B \-P \-E
+under MINIX 3 to omit this info for
+.B \-E
+too.
+.TP
+.B \-S
+Transform the input files to assembly files with suffix
+.BR .s .
+.TP
+.BI \-c. suffix
+Transform the input files to files with the given suffix.  This can only
+succeed if there is a valid transformation from the input file to the
+given suffix.  The same goes for
+.B \-c
+and other options that are just special cases of this option, except for
+.BR \-P ,
+.B \-c.i
+keeps the line number info.  The option
+.B \-c.a
+makes the driver transform the input files to object files and add them to a
+library.  (So you do not need to know how the archiver works.)  Note that you
+need to give object files as arguments if you want to replace old object
+files.  Transformed files are added under a (unique) temporary name.  With
+.B \-o
+you can name the library.  (MINIX 3)  (Minix-86 can't do
+.BR \-c.a .)
+.TP
+.B \-O
+Optimize code.  This option is a no-op, because all the compilers already
+use the
+.BR \-O1
+optimization level to get code of reasonable quality.  Use
+.BR \-O0
+to turn off optimization to speed up compilation at debug time.
+.TP
+.BI \-O level
+Compile with the given optimization level.  (MINIX 3)
+.PP
+.B \-OS
+.br
+.B \-OT
+.RS
+Optimize for space or for time.  (MINIX 3)
+.RE
+.TP
+.B \-g
+Compile the C source with debugging information.  (The way
+.BR \-g ,
+.B \-s
+and
+.B \-O
+interact is left unspecified.)
+.TP
+.B \-n
+Omit the file and line number tracking that is used for runtime error reports
+from Pascal or Modula-2 programs.  The
+.B \-n
+flag is normally used to compile library modules, but may also be useful to
+make a program smaller and faster once debugged.  (Pascal & Modula-2)
+.TP
+.B \-a
+Enable assertions, i.e. statements of the form \fBassert\fI\ test\fR
+that cause a descriptive runtime error if the boolean expression
+.I test
+evaluates false.  (Pascal & Modula-2)
+.TP
+.B \-R
+Disable runtime checks like overflow checking.  (Pascal & Modula-2)
+.TP
+.B \-A
+Enable array bound checks.  (Pascal & Modula-2)
+.TP
+.B \-s
+Strip the resulting executable of its symbol table.
+.PP
+.B \-fsoft
+.br
+.B \-f
+.RS
+Use software floating point instead of hardware floating point.  This is
+a loader flag, but in general it is best to specify this flag in all
+phases of the compilation.  (MINIX 3)
+.RE
+.TP
+.B \-fnone
+Ignored.  Used under Minix-vmd to omit floating point printing/scanning
+code.  The standard MINIX 3 compiler figures this out automatically using
+a special loader trick.  (MINIX 3)
+.TP
+.B \-w
+Do not produce warnings about dubious C language constructs.  Normally
+the compiler is configured to do the maximum amount of checking
+without being too annoying.  (MINIX 3)
+.TP
+.B \-wo
+Omit warnings about old (K&R) style.  (MINIX 3)
+.TP
+.B \-ws
+Omit strict warnings.  (MINIX 3)
+.TP
+.B \-wa
+Omit all warnings.  (MINIX 3)
+.TP
+.B \-3
+Only accept 3rd edition Modula-2.  (Modula-2)
+.TP
+.B \-_
+Allow underscores in Pascal or Modula-2 identifiers, but not at the beginning
+of an identifier.  (Pascal & Modula-2)
+.TP
+.BI \-W name \- option
+If
+.I name
+is the name of the compiler this driver is working for, then
+.I option
+is activated for that compiler.  See below for a per-compiler list.  Any other
+.B \-W
+option is ignored.  (\fB\-W\fP is described by \s-2POSIX\s+2 as an optional
+flag to send options to the different compiler passes with a totally
+different (and nicely ignored) syntax as described here.)  (Minix-86 ignores
+any
+.B \-W
+flag.)
+.TP
+.B \-m
+Under Minix-86 this option transforms the function declarations (prototypes)
+to the old K&R form, i.e. the arguments declarations are removed.  This saves
+a lot of memory in the compiler and may allow a large program to be compiled.
+One must make sure that function arguments are properly type-cast where
+necessary.  (MINIX 3)
+.TP
+.BI \-m arch
+Set the target architecture for a cross compiler.  Normally the compiler
+produces code for the same architecture it itself is compiled for.  The
+.B ARCH
+environment variable may also be used to set the architecture.  Architectures
+names are:
+.B i86
+(Intel 8086 and 286),
+.B i386
+(Intel 386, 486, ...),
+.B m68000
+(Motorola MC68000 & MC68010, 16-bit ints),
+.B m68010
+(Motorola MC68000 & MC68010, 32-bit ints),
+.B m68020
+(Motorola MC68020, 32-bit ints),
+.B sparc
+(Sun SPARC).  (MINIX 3)  (Ignored under Minix-86.)
+.TP
+.BI \-o " outfile"
+Set the output file for the
+.BR \-c ,
+.BR \-c.a ,
+and
+.BR \-E
+options, or choose the executable name instead of the default
+.BR a.out .
+(Minix-86 can only choose the executable name.)
+.TP
+.BI \-L " directory"
+Extend the library search path with
+.IR directory .
+These directories are searched for libraries named by
+.B \-l
+in the given order before the standard places.  The standard places are
+.B /lib/\c
+.IR arch ,
+and
+.B /usr/lib/\c
+.IR arch .
+The search for libaries in directories added with
+.B \-L
+looks in
+.IB directory /\c
+.IR arch
+and
+.I directory
+itself.
+.RI ( Arch
+is the machine architecture name.  This is
+MINIX 3 dependent, compilers on other systems usually only look in
+.IR directory .)
+(Minix-86 only has
+.B /lib
+and
+.B /usr/lib
+as the standard places.)
+.PP
+.B \-sep
+.br
+.B \-com
+.RS
+Create a Separate I&D or a common I&D executable.  The text segment of a
+separate I&D executable is read-only and shareable.  For an
+.B i86
+binary this also means that the text and data segment can each be 64
+kilobytes large instead of just 64 kilobytes together.  Separate I&D is the
+default.  Common I&D is probably only useful for the bootstraps.  The
+.B \-i
+option has the same meaning as
+.BR \-sep ,
+but should no longer be used.
+(MINIX 3)
+.RE
+.TP
+.B \-r
+Makes the loader produce a relocatable object file, i.e. a file that
+may be loaded again.  The runtime startoff and the default libraries are
+omitted, only the files mentioned are combined.  (MINIX 3)
+.TP
+.BI \-stack " size"
+Allow the process
+.I size
+bytes of heap and stack.
+.I Size
+is a C-style decimal, octal, or hexadecimal number, optionally followed by
+the multipliers
+.BR m ,
+.BR k ,
+.BR w ,
+and
+.B b
+for mega (1024*1024), kilo (1024), "word" (2 or 4), and byte (1).  Uppercase
+letters are accepted too.  A size of
+.B 32kw
+is used by default, translating to 64k for
+.BR i86 ,
+and 132k for other architectures.  Too large a size is rounded down to keep
+the data segment within 64 kilobytes for the
+.BR i86 .
+(MINIX 3)
+.SH OPERANDS
+All leftover operands are treated as files to be compiled, with one
+exception.  The construct
+.BI \-l " library"
+is used to denote a library, usually
+.BI lib library .a\fR,
+that is to be searched in the directories mentioned with
+.B \-L
+or the standard places.  These libraries keep their place among the
+(transformed) input files when presented to the loader.  (It is a common
+mistake to write
+.BR "cc\ \-lcurses\ x.c"
+instead of
+.BR "cc\ x.c\ \-lcurses" .)
+.SH IMPLEMENTATION
+The MINIX 3 compiler implementation uses the ACK compilers adapted for use
+under MINIX 3 as described below.  Read
+.BR ACK (7)
+for more detailed information on the ACK compilers themselves.
+.SS "Feature test macros"
+The preprocessors are given these arguments to define feature test macros:
+.B \-D__ACK__
+tells what compiler is used.
+.B \-D__minix
+tells that this is MINIX 3.
+.BI \-D__ arch
+tells the architecture.
+(More macros are defined, but they are only to be used in the include files.)
+.PP
+The symbols above are predefined by the preprocessor so that your program is
+able to "sense" the environment it is in.  It is also possible for your
+program to do the opposite, to tell what kind of environment it likes to
+have.  By default,
+.B cc
+compiles a standard C program.  If you want the extensions described in
+POSIX.1 to become visible, then you have to set
+.BR _POSIX_SOURCE " to " 1
+at the start of your program.
+To enable \s-2UNIX\s+2 or MINIX 3 extensions you need to also set
+.BR _MINIX " to " 1 .
+If you don't want to clutter your source files with these symbols then you
+can use
+.B cc \-D_MINIX \-D_POSIX_SOURCE
+to get the POSIX.1 and the MINIX 3 extensions.
+.SS "Preprocessing"
+Pascal, Modula-2, EM source (see below), and Assembly source are
+preprocessed by the C preprocessor if the very first character in the file
+is a '\fB#\fP' character.
+.SS "Assembly dialects"
+No two compilers use the same assembly language.  To be able to use the same
+assembly dialect for the low level support routines an assembly converter is
+provided.  The input of this converter can be of type
+.BR ack ,
+.BR ncc ,
+or
+.BR bas ,
+and the output can be of type
+.BR ack ,
+.BR ncc ,
+or
+.BR gnu .
+The suffix of the file tells the assembly dialect (see below), or one can
+use the option
+.BI \-Was\- dialect
+to tell the driver what the dialect of a plain
+.B .s
+file is.  The assembly converter is not as smart as the assembler, the
+translation is more or less a text substitution.  It leaves a lot of
+checking to the target assembler.  You have to restrict yourself to a subset
+that is understood by both assemblers.  The ACK assembler for instance
+doesn't care if you use `ax' or `eax' for a 32 bit register, it looks at the
+instruction type.  The GNU assembler doesn't like this, so you have to use
+the proper register name in ACK assembly that is to be translated to GNU
+assembly.  Expressions are converted as is, even if the operator precedence
+rules of the two assembly languages differ.  So use parentheses.  The
+converter does promise one thing: compiler output can be properly
+translated.  (Note that under Minix-86
+.B \-W
+is ignored.  All assembly should therefore be in the "ncc" dialect.)
+.SH FILES
+.TP 10
+.B /usr/lib/descr
+The compiler description file.
+.TP
+.B .c
+Suffix of a C source file.
+.TP
+.B .mod
+Modula-2.
+.TP
+.B .p
+Pascal.
+.TP
+.B .i
+Preprocessed C source.
+.TP
+.B .k
+ACK machine independent compact EM code produced by the C, Pascal, or
+Modula-2 front end (or any other ACK front end.)  The ACK compilers are
+based on the UNCOL idea where several front ends compile to a common
+intermediate language, and several back ends transform the intermediate
+language to the target machine language.  The ACK intermediate language
+is named "EM".
+.TP
+.B .m
+Peephole optimized EM.
+.TP
+.B .gk
+Result of the (optional) EM global optimizer.
+.TP
+.B .g
+Result of the second EM peephole optimizer used after the global optimizer.
+.TP
+.B .e
+Human readable EM.  (Human created or decoded compact EM.)
+.TP
+.B .s
+Target machine assembly.  (Current compiler dialect.)
+.TP
+.B .ack.s
+ACK assembly.
+.TP
+.B .ncc.s
+ACK Xenix style assembly.  This dialect is used by the 16 bit ACK ANSI C
+compiler.
+.TP
+.B .gnu.s
+GNU assembly.
+.TP
+.B .bas.s
+BCC assembly.  (Used by the Bruce Evans' BCC compiler, for many years the
+compiler for Minix-386.)
+.TP
+.B .o
+Object code.
+.TP
+.B .a
+Object code library.
+.TP
+.B a.out
+Default output executable.
+.SH "SEE ALSO"
+.BR acd (1),
+.BR ACK (7).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/cdiff.1
===================================================================
--- /trunk/minix/man/man1/cdiff.1	(revision 9)
+++ /trunk/minix/man/man1/cdiff.1	(revision 9)
@@ -0,0 +1,31 @@
+.TH CDIFF 1
+.SH NAME
+cdiff \- context diff
+.SH SYNOPSIS
+\fBcdiff\fR [\fB\-c\fIn\fR] \fIoldfile \fInewfile\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-c" "Provide \fIn\fR lines of context"
+.SH EXAMPLES
+.EX "cdiff old new >f" "Write context diff on \fIf\fR"
+.EX "cdiff \-c1 old new >f" "Use only 1 line of context"
+.SH DESCRIPTION
+.PP
+\fICdiff\fR produces a context diff by first running \fIdiff\fR and then 
+adding context.  
+Some update programs, like \fIpatch\fR, can use context diffs to update
+files, even in the presence of other, independent changes.
+.SH "SEE ALSO"
+.BR cmp (1),
+.BR diff (1),
+.BR patch (1).
Index: /trunk/minix/man/man1/cgrep.1
===================================================================
--- /trunk/minix/man/man1/cgrep.1	(revision 9)
+++ /trunk/minix/man/man1/cgrep.1	(revision 9)
@@ -0,0 +1,33 @@
+.TH CGREP 1
+.SH NAME
+cgrep \- grep and display context
+.SH SYNOPSIS
+\fBcgrep\fR [\fB\-a \fIn\fR]\fR [\fB\-b \fIn\fR] [\fB\-f\fR] [\fB\-l \fIn\fR]  [\fB\-n\fR] [\fB\-w \fIn\fR] \fIpattern\fR [\fIfile\fR] ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-a" "How many lines to display after the matching line"
+.FL "\-b" "How many lines to display before the matching line"
+.FL "\-f" "Suppress file name in the output"
+.FL "\-l" "Lines are truncated to this length before comparison"
+.FL "\-n" "Suppress line numbers in the output"
+.FL "\-w" "Sets window size (same as \fB\-a\fR n \fB\-b\fR n)"
+.SH EXAMPLES
+.EX "cgrep \-w 3 hello file1" "Print 3 lines of context each way"
+.SH DESCRIPTION
+.PP
+\fICgrep\fR is a program like \fIgrep\fR, except that it also can print
+a few lines above and/or below the matching lines.
+It also prints the line numbers of the output.
+.SH "SEE ALSO"
+.BR grep (1),
+.BR fgrep (1).
Index: /trunk/minix/man/man1/chgrp.1
===================================================================
--- /trunk/minix/man/man1/chgrp.1	(revision 9)
+++ /trunk/minix/man/man1/chgrp.1	(revision 9)
@@ -0,0 +1,38 @@
+.TH CHGRP 1
+.SH NAME
+chgrp \- change group
+.SH SYNOPSIS
+\fBchgrp [\fB\-R\fR] [\fIowner:\fR]\fIgroup \fIfile\fR ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-R" "Change directory hierarchies"
+.SH EXAMPLES
+.EX "chgrp system file1 file2" "Make \fIsystem\fR the group of the files"
+.EX "chrgp \-R other dir1" "Make \fIother\fR the group of all files below dir1"
+.SH DESCRIPTION
+.PP
+The group field (and optionally owner field) of the named files is changed to 
+.I group
+and
+.I owner .
+Alternatively, a decimal gid (uid) may be specified instead of a group name.
+If the \fB\-R\fR flag is used, the changes will be applied recursively to
+all files in named directories. Only the superuser may execute this command
+to set arbitrary groups. Normal users can only change the group if they own
+the file, and the group is their own group (MINIX 3), or one of their
+supplementary groups (Minix-vmd).
+.SH "SEE ALSO"
+.BR chown (8),
+.BR chmod (1),
+.BR ls (1),
+.BR chown (2).
Index: /trunk/minix/man/man1/chmem.1
===================================================================
--- /trunk/minix/man/man1/chmem.1	(revision 9)
+++ /trunk/minix/man/man1/chmem.1	(revision 9)
@@ -0,0 +1,65 @@
+.TH CHMEM 1
+.SH NAME
+chmem \- change memory allocation
+.SH SYNOPSIS
+\fBchmem\fR [\fB+\fR]\fR [\fB\-\fR] [\fB=\fR] \fIamount file\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "chmem =50000 a.out" "Give \fIa.out\fP 50K of stack space"
+.EX "chmem \-4000 a.out" "Reduce the stack space by 4000 bytes"
+.EX "chmem +1000 file1" "Increase each stack by 1000 bytes"
+.SH DESCRIPTION
+.PP
+When a program is loaded into memory, it is allocated enough memory
+for the text and data+bss segments, plus
+an area for the stack.
+Data segment growth using 
+.I malloc ,
+.I brk ,
+or
+.I sbrk 
+eats up stack space from the low end.
+The amount of stack space to allocate is derived
+from a field in the executable program's file header.
+If the combined stack and data segment growth exceeds the stack space
+allocated, the program will be terminated.
+.PP
+It is therefore important to set the amount of stack space carefully.
+If too little is provided, the program may crash.
+If too much is provided, memory will be wasted, and fewer programs will be able
+to fit in memory and run simultaneously.
+\s-1MINIX 3\s-1
+does not swap, so that when memory is full, subsequent attempts to fork will
+fail.
+The compiler sets the stack space
+to the largest possible value (for the Intel CPUs, 64K \- text \- data).
+For many programs, this value is far too large.
+Nonrecursive programs that do not call
+.I brk ,
+.I sbrk ,
+or
+.I malloc ,
+and do not have any local arrays usually do not need more than 8K of stack
+space.
+.PP
+The
+.I chmem
+command changes the value of the header field that determines the stack allocation, and
+thus indirectly the total memory required to run the program.
+The = option sets the stack size
+to a specific value; the + and \- options increment and decrement the
+current value by the indicated amount.
+The old and new stack sizes are printed.
+.SH "SEE ALSO"
+.BR install (1),
+.BR brk (2).
Index: /trunk/minix/man/man1/chmod.1
===================================================================
--- /trunk/minix/man/man1/chmod.1	(revision 9)
+++ /trunk/minix/man/man1/chmod.1	(revision 9)
@@ -0,0 +1,62 @@
+.TH CHMOD 1
+.SH NAME
+chmod \- change access mode for files
+.SH SYNOPSIS
+\fBchmod [\fB\-R\fR] \fImode \fIfile\fR ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-R" "Change hierarchies recursively"
+.SH EXAMPLES
+.EX "chmod 755 file" "Owner: rwx Group: r\-x Others: r\-x"
+.EX "chmod +x file1 file2" "Make \fIfile1\fR and \fIfile2\fR executable"
+.EX "chmod a\-w file" "Make \fIfile\fR read only"
+.EX "chmod u+s file" "Turn on SETUID for \fIfile\fR"
+.EX "chmod \-R o+w dir" "Allow writing for all files in dir"
+.SH DESCRIPTION
+.PP
+The given mode is applied to each file in the file list. If the \fB\-R\fR
+flag is present, the files in a directory will be changed as well.
+The mode can be either absolute or symbolic. Absolute modes are given as an
+octal number that represents the new file mode. The mode bits are defined as
+follows: 
+.ta 0.25i
+.nf
+.PP
+	4000    Set effective user id on execution to file's owner id
+	2000    Set effective group id on execution to file's group id
+	0400    file is readable by the owner of the file
+	0200    writeable by owner
+	0100    executable by owner
+	0070    same as above, for other users in the same group
+	0007    same as above, for all other users
+.PP
+.fi
+Symbolic modes modify the current file mode in a specified way. The form is:
+.PP
+	[who] op permissions { op permissions ...} {, [who] op ... }
+.PP
+The possibilities for \fIwho\fR are \fIu\fR, \fIg\fR, \fIo\fR, and \fIa\fR,
+standing for user, group, other and all, respectively.  
+If \fIwho\fR is omitted, \fIa\fR is assumed, but the current umask is used.  
+The op can be \fI+\fR, \fI-\fR, or \fI=\fR;  \fI+\fR turns on the 
+given permissions, \fI\- \fRturns them off; \fI=\fR sets the permissions 
+exclusively for the given \fIwho\fR.  
+For example \fIg=x\fR sets the group permissions to \fI--x\fR. 
+.PP
+The possible permissions are \fIr\fR, \fIw\fR, \fIx\fR; which stand for read, 
+write, and execute;  \fIs\fR turns on the set effective user/group id bits.  
+\fIs\fR only makes sense with \fIu\fR and \fIg\fR;\fR o+s\fR is 
+harmless.
+.SH "SEE ALSO"
+.BR ls (1),
+.BR chmod (2).
Index: /trunk/minix/man/man1/cksum.1
===================================================================
--- /trunk/minix/man/man1/cksum.1	(revision 9)
+++ /trunk/minix/man/man1/cksum.1	(revision 9)
@@ -0,0 +1,34 @@
+.TH CKSUM 1
+.SH NAME
+cksum \- display file checksum and size
+.SH SYNOPSIS
+\fBcksum \fR[\fIfile\fR ...]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "cksum" "Display CRC and size of \fIstdin\fR"
+.EX "cksum *.c" "Display CRC and size of \fI.c\fP files"
+.SH DESCRIPTION
+.PP
+.I Cksum
+calculates and writes to standard output the 32-bits CRC of the input
+.I files ,
+or of stdin if no
+.I files
+were specified. The size in bytes of each
+.I file
+will be displayed after a space. The name of each
+.I file
+will be displayed after another space.
+.SH "SEE ALSO"
+.BR crc (1),
+.BR sum (1).
Index: /trunk/minix/man/man1/clear.1
===================================================================
--- /trunk/minix/man/man1/clear.1	(revision 9)
+++ /trunk/minix/man/man1/clear.1	(revision 9)
@@ -0,0 +1,17 @@
+.TH CLEAR 1
+.SH NAME
+clear, clr \- clear the screen
+.SH SYNOPSIS
+.B clear
+.br
+.B clr
+.SH DESCRIPTION
+.B Clear
+or its synonym
+.B clr
+clears the screen.  It is exactly equivalent to
+.BR "tget -str cl" .
+.SH "SEE ALSO"
+.BR tget (1).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/cmp.1
===================================================================
--- /trunk/minix/man/man1/cmp.1	(revision 9)
+++ /trunk/minix/man/man1/cmp.1	(revision 9)
@@ -0,0 +1,34 @@
+.TH CMP 1
+.SH NAME
+cmp \- compare two files
+.SH SYNOPSIS
+\fBcmp\fR [\fB\-ls\fR] \fIfile1 file2\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-l" "Loud mode. Print bytes that differ (in octal)"
+.FL "\-s" "Silent mode.  Print nothing, just return exit status"
+.SH EXAMPLES
+.EX "cmp file1 file2" "Tell whether the files are the same"
+.EX "cmp \-l file1 file2" "Print all corresponding bytes that differ"
+.SH DESCRIPTION
+.PP
+Two files are compared.
+If they are identical, exit status 0 is returned.
+If they differ, exit status 1 is returned.
+If the files cannot be opened, exit status 2 is returned.
+If one of the file arguments is \-, then
+\fIstdin\fR is compared to 
+the other file.
+.SH "SEE ALSO"
+.BR comm (1),
+.BR diff (1).
Index: /trunk/minix/man/man1/comm.1
===================================================================
--- /trunk/minix/man/man1/comm.1	(revision 9)
+++ /trunk/minix/man/man1/comm.1	(revision 9)
@@ -0,0 +1,39 @@
+.TH COMM 1
+.SH NAME
+comm \- print lines common to two sorted files
+.SH SYNOPSIS
+\fBcomm\fR [\fB\-123\fR] \fIfile1 file2\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-1" "Suppress column 1 (lines present only in \fIfile1\fP)" 
+.FL "\-2" "Suppress column 2 (lines present only in \fIfile2\fP)" 
+.FL "\-3" "Suppress column 3 (lines present in both files)"
+.SH EXAMPLES
+.EX "comm file1 file2" "Print all three columns"
+.EX "comm \-12 file1 file2" "Print only lines common to both files"
+.SH DESCRIPTION
+.PP
+Two sorted files are read and compared.
+A three column listing is produced.
+Files only in 
+.I file1
+are in column 1;
+files only in
+.I file2
+are in column 2;
+files common to both files are in column 3.
+The file name \- means \fIstdin\fR. 
+.SH "SEE ALSO"
+.BR cmp (1),
+.BR diff (1),
+.BR sort (1).
Index: /trunk/minix/man/man1/compress.1
===================================================================
--- /trunk/minix/man/man1/compress.1	(revision 9)
+++ /trunk/minix/man/man1/compress.1	(revision 9)
@@ -0,0 +1,42 @@
+.TH COMPRESS 1
+.SH NAME
+compress, uncompress, zcat \- compress a file using modified Lempel-Ziv coding
+.SH SYNOPSIS
+\fBcompress\fR [\fB\-cdfv\fR]\fR [\fIfile\fR] ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-c" "Put output on \fIstdout\fR instead of on \fIfile.Z\fR"
+.FL "\-d" "Decompress instead of compress"
+.FL "\-f" "Force output even if there is no saving"
+.FL "\-v" "Verbose mode"
+.SH EXAMPLES
+.EX "compress <infile >outfile" "Compress 1 file"
+.EX "compress x y z" "Compress 3 files to \fIx.Z\fR, \fIy.Z\fR, and \fIz.Z\fR"
+.EX "compress \-d file.Z" "Decompress \fIfile.Z\fR to \fIfile\fR"
+.SH DESCRIPTION
+.PP
+The listed files (or \fIstdin\fR, if none are given) are compressed
+using the Ziv-Lempel algorithm.  If the output is smaller than the input,
+the output is put on \fIfile.Z\fR or \fIstdout\fR if no files are listed.  
+If \fIcompress\fR is linked to \fIuncompress\fR, the latter is the same 
+as giving the \fB\-d\fP flag.
+Similarly, a link to \fIzcat\fR decompresses to \fIstdout\fR.
+The
+\s-1MINIX 3\s-1
+version of \fIcompress\fR uses 13-bit compression.
+This means that when compressing files on other systems for transmission to
+\s-1MINIX 3\s-1,
+be sure that only 13-bit compression is used.
+On many systems, the default is 16-bit (too big).
+.SH "SEE ALSO"
+.BR tar (1).
Index: /trunk/minix/man/man1/cp.1
===================================================================
--- /trunk/minix/man/man1/cp.1	(revision 9)
+++ /trunk/minix/man/man1/cp.1	(revision 9)
@@ -0,0 +1,223 @@
+.TH CP 1
+.SH NAME
+cp, mv, rm, ln, cpdir, clone \- copy, move, remove, link
+.SH SYNOPSIS
+.B cp
+.RB [ \-pifsmrRvx ]
+.I file1 file2
+.br
+.B cp
+.RB [ \-pifsrRvx ]
+.IR file " ... " dir
+.PP
+.B mv
+.RB [ \-ifsmvx ]
+.I file1 file2
+.br
+.B mv
+.RB [ \-ifsvx ]
+.IR file " ... " dir
+.PP
+.B rm
+.RB [ \-ifrRvx ]
+.IR file " ..."
+.PP
+.B ln
+.RB [ \-ifsSmrRvx ]
+.I file1 file2
+.br
+.B ln
+.RB [ \-ifsSrRvx ]
+.IR file " ... " dir
+.PP
+.B cpdir
+.RB [ \-ifvx ]
+.I file1 file2
+.PP
+.B clone
+.RB [ \-ifsSvx ]
+.I file1 file2
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+The utilities
+.BR cp ,
+.BR mv ,
+.BR rm ,
+and
+.B ln
+do basic file management: copying, renaming or moving, deletion, and
+creating links.  (The
+.B cpdir
+and
+.B clone
+utilities are easy to use aliases for copying or linking whole trees.
+They are the same as
+.B cp \-psmr
+and
+.BR "ln \-fmr" )
+.PP
+The first synopsis form of the utilities
+.BR cp ,
+.BR mv ,
+and
+.B ln
+is used if only two arguments are given, and the second argument is not a
+directory.  The source and target file are then the two files given.
+.PP
+If the second synopsis form is used then the last argument must be a
+directory.  Each of the files is copied, moved or linked into this directory.
+.PP
+A file is by default copied by
+.B cp
+without looking at its type, so symlinks are followed and devices are opened
+and read from or written to.  Links between files are ignored.  This
+behavior can be changed by using the proper options.
+.PP
+The
+.B mv
+utility uses the
+.BR rename (2)
+call to rename or move files.  If source and target are on different devices
+however, then
+.B mv
+will use
+.B cp \-pr
+to copy the files or directory trees.
+.PP
+Each utility continues with the next file on errors, except on I/O errors.
+.SH OPTIONS
+.TP
+.B \-p
+Copy the file attributes like mode, owner, group and time of last
+modification.  Normally only the mode is copied to a new file with the file
+creation mask applied.  Setuid bits are cleared if setting the ownership
+fails.
+.TP
+.B \-i
+Ask if ok to overwrite, replace or remove.
+.B Mv
+and
+.B rm
+will ask this automatically if interactive and the target file is writable.
+.B Cp
+will fail if the target cannot be written,
+.B ln
+will always fail if the target exists.
+.TP
+.B \-f
+Makes
+.B cp
+remove a target file before copying if it is not writable,
+.B mv
+removes an existing target without asking,
+.B rm
+does not report any errors, and
+.B ln
+removes an existing target file before linking.  The last of
+.B \-i
+and
+.B \-f
+wins for
+.B mv
+if both flags are set, the other utilities do something sensible, like asking
+before forcefully removing.
+.TP
+.B \-s
+Make a symlink instead of a normal link.  For utilities other than
+.B ln
+this flag means "copy similar".  The modified time is always copied for
+.B cp \-s
+and the other attributes are copied if a new file is created.  The normal
+\s-2POSIX\s+2 required patronizing like applying the file creation mask or
+clearing setuid bits is not done.
+.TP
+.B \-S
+Make a symlink if a normal link cannot be made because source and target are
+on different devices.  The symlink is required to really refer back to the
+source, meaning that a/b must exist in the call
+.BR "ln \-S a/b c/d" ,
+and that the symlink from c/d must lead back to a/b.  So the symlink will be
+created as if
+.B "ln \-s ../a/b c/d"
+was called.  If the target is a full path, but the source is not then an
+error will be given saying that this is "too difficult."
+.TP
+.B \-m
+Merge trees.  The first synopsis form is assumed, and the files from one
+tree are merged into the other.  There is no "if it's a directory the put
+it into that directory" trickery here.
+.TP
+.BR \-r ", " \-R
+Recursively copy, remove, or link.  If the source is a directory then the
+files in this directory are copied to similarly named files in the target
+directory.  Special files are copied as new special files, they are not read
+or written.  Symlinks are still expanded and the link structure ignored with
+.BR \-R .
+The
+.B \-r
+flag does copy symlinks as symlinks and keeps the link structure intact.
+(Note that
+.B \-R
+is invented by \s-2POSIX\s+2 as a replacement for the classic
+.B \-r
+option of older copy commands that did read special files.  The standard
+says that
+.B \-r
+is implementation defined, so that's why this flag is better than
+.B \-R
+in this implementation of
+.BR cp .)
+For
+.B rm
+and
+.B ln
+both flags mean the same.
+.B Ln
+will recursively link the files in the trees, except symlinks, they are
+copied.  If symlinks are created with
+.B ln \-rs
+or
+.B ln \-rS
+then they are required "to work" as described with the
+.B \-S
+flag.
+.TP
+.B \-v
+Verbose.  Show what is done on standard output.
+.TP
+.B \-x
+Do not cross mount points.  Empty directories will be created if the source
+directory is a mount point on a copy, move or link.  A mount point will not
+be removed or traversed recursively.  This flag allows one to copy the root
+device, e.g.
+.BR "cpdir \-x / /mnt" .
+.SH "SEE ALSO"
+.BR cat (1),
+.BR mkdir (1),
+.BR rmdir (1),
+.BR mkdir (2),
+.BR rmdir (2),
+.BR link (2),
+.BR unlink (2),
+.BR rename (2),
+.BR open (2),
+.BR read (2),
+.BR write (2),
+.BR opendir (3).
+.SH NOTES
+All the utilities described are links to the same program.
+.SH BUGS
+.B Mv
+should first copy a tree across devices and then remove the source tree if
+there was no error.  Instead, each file in the tree is copied and
+immediately removed.  On error you may be left with two half-filled trees,
+together containing all of the files.  You may have to restart the move with
+.BR "mv \-m" .
+.PP
+.B Rm
+should be able to remove arbitrarily deep trees.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/crc.1
===================================================================
--- /trunk/minix/man/man1/crc.1	(revision 9)
+++ /trunk/minix/man/man1/crc.1	(revision 9)
@@ -0,0 +1,29 @@
+.TH CRC 1
+.SH NAME
+crc \- print the checksum of the file data
+.SH SYNOPSIS
+\fBcrc \fIfile\fR ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "crc *.c" "Print checksums of all the C programs"
+.SH DESCRIPTION
+.PP
+The checksum of each argument is computed and printed, along with the file
+length and its name, one file per line.
+This program is useful for seeing if a file transmitted to another machine
+has arrived correctly.
+It is conceptually similar to \fIsum\fR, except that it uses a stronger 
+checksum algorithm and also prints the length.
+.SH "SEE ALSO"
+.BR cksum (1),
+.BR sum (1).
Index: /trunk/minix/man/man1/crontab.1
===================================================================
--- /trunk/minix/man/man1/crontab.1	(revision 9)
+++ /trunk/minix/man/man1/crontab.1	(revision 9)
@@ -0,0 +1,93 @@
+.TH CRONTAB 1
+.SH NAME
+crontab \- User crontab manipulation
+.SH SYNOPSIS
+.B crontab \-c
+.RI [ user ]
+.I file
+.br
+.B crontab \-l
+.RI [ user ]
+.br
+.B crontab \-r
+.RI [ user ]
+.br
+.B crontab \-p
+.SH DESCRIPTION
+The
+.B crontab
+program allows users to manipulate their personal crontab files.  These
+files are hidden in
+.BI /usr/spool/crontabs/ user
+where
+.I user
+is the login name of a given user.  The system daemon
+.B cron
+uses these crontabs, among others, to run tasks that are to be repeated at
+regular intervals.  See
+.BR crontab (5)
+on what a good crontab file should look like.
+.PP
+Only the superuser can specify a user name to manipulate the crontab of a
+given user.  Any other user can only touch their own crontab file.
+.SH OPTIONS
+.TP
+\fB\-c\fR [\fIuser\fR] \fIfile\fR
+Install
+.I file
+as the crontab file of
+.IR user .
+.TP
+\fB\-l\fR [\fIuser\fR]
+List the crontab file of
+.I user
+to standard output.
+.TP
+\fB\-r\fR [\fIuser\fR]
+Remove the crontab file of
+.IR user .
+.TP
+\fB\-p\fR
+Tell cron to reload its tables.  Useful for system administrators to signal
+a change to any of the system crontab files.  Changes made by the
+.B crontab
+program are signalled automatically.  (Mnemonic: \-p = "ping".)
+.SH FILES
+.TP \w'/usr/spool/crontabs/user'u+5n
+.BI /usr/spool/crontabs/ user
+Per user personal crontab file.
+.SH "SEE ALSO"
+.BR crontab (5),
+.BR cron (8).
+.SH DIAGNOSTICS
+.B Crontab
+preparses a new crontab and only installs it if correct.  All errors are
+sent to standard error, messages about installing a new table and telling
+.B cron
+to reload are sent to standard output.
+.SH BUGS
+.B Crontab
+misses a
+.B \-e
+option that other implementations of this command allow one to edit the
+current crontab and install the result.  Seems quite handy until you try to
+install a new crontab from an automated script.  That's why this command
+has a
+.B \-c
+option that installs a prepared crontab file.  Use
+.PP
+.RS
+.nf
+crontab \-l >/tmp/tab
+${EDITOR\-vi} /tmp/tab
+crontab \-c /tmp/tab
+.fi
+.RE
+.PP
+to get the same effect as
+.BR "crontab \-e" .
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+
+.\"
+.\" $PchId: crontab.1,v 1.3 2000/07/17 18:51:04 philip Exp $
Index: /trunk/minix/man/man1/ctags.1
===================================================================
--- /trunk/minix/man/man1/ctags.1	(revision 9)
+++ /trunk/minix/man/man1/ctags.1	(revision 9)
@@ -0,0 +1,84 @@
+.TH CTAGS 1
+.SH NAME
+ctags - Generates "tags" and (optionally) "refs" files
+.SH SYNOPSIS
+\fBctags\fP [\fB-stvra\fP] \fIfilesnames\fP...
+.SH DESCRIPTION
+\fIctags\fP generates the "tags" and "refs" files
+from a group of C source files.
+The "tags" file is used by Elvis' ":tag" command,
+control-] command,
+and -t option.
+The "refs" file is sometimes used by the \fIref(1)\fP program.
+.PP
+Each C source file is scanned for #define statements and
+global function definitions.
+The name of the macro or function becomes the name of a tag.
+For each tag, a line is added to the "tags" file which contains:
+.RS
+.nf
+       - the name of the tag
+       - a tab character
+       - the name of the file containing the tag
+       - a tab character
+       - a way to find the particular line within the file.
+.RE
+.fi
+.PP
+The filenames list will typically be the names of all C source
+files in the current directory, like this:
+.RS
+.nf
+$ ctags -stv *.[ch]
+.RE
+.fi
+.SH OPTIONS
+.IP \fB-t\fR
+Include typedefs.
+A tag will be generated for each user-defined type.
+Also tags will be generated for struct and enum names.
+Types are considered to be global if they are defined in a header file,
+and static if they are defined in a C source file.
+.IP \fB-v\fR
+Include variable declarations.
+A tag will be generated for each variable, except for those that are declared
+inside the body of a function.
+.IP \fB-s\fR
+Include static tags.
+\fICtags\fR will normally put global tags in the "tags" file, and silently ignore
+the static tags.
+This flag causes both global and static tags to be added.
+The name of a static tag is generated by prefixing the name of the declared
+item with the name of the file where it is defined, with a colon in between.
+For example, "static foo(){}" in "bar.c" results in a tag named "bar.c:foo".
+.IP \fB-r\fP
+This causes \fIctags\fP to generate both "tags" and "refs".
+Without \fB-r\fP, it would only generate "tags".
+.IP \fB-a\fR
+Append to "tags", and maybe "refs".
+Normally, \fIctags\fR overwrites these files each time it is invoked.
+This flag is useful when you have to many files in the current directory
+for you to list them on a single command-line;
+it allows you to split the arguments among several invocations.
+.SH FILES
+.IP tags
+A cross-reference that lists each tag name, the name of the source file that
+contains it, and a way to locate a particular line in the source file.
+.IP refs
+The "refs" file contains the definitions for each tag in the "tags" file,
+and very little else.
+This file can be useful, for example, when licensing restrictions prevent
+you from making the source code to the standard C library readable by everybody,
+but you still everybody to know what arguments the library functions need.
+.SH BUGS
+.PP
+\fIctags\fR is sensitive to indenting and line breaks.
+Consequently, it might not discover all of the tags in a file that
+is formatted in an unusual way.
+.SH "SEE ALSO"
+elvis(1), refs(1)
+.SH AUTHOR
+.nf
+Steve Kirkendall
+kirkenda@cs.pdx.edu
+.fi
Index: /trunk/minix/man/man1/cut.1
===================================================================
--- /trunk/minix/man/man1/cut.1	(revision 9)
+++ /trunk/minix/man/man1/cut.1	(revision 9)
@@ -0,0 +1,46 @@
+.TH CUT 1
+.SH NAME
+cut \- select out columns of a file
+.SH SYNOPSIS
+\fBcut [ \fB \-b \fR|\fB \-c\fR] \fIlist\fR [\fIfile...\fR]\fR
+.br
+\fBcut \-f \fIlist\fR [\fB\-d \fIdelim\fR] [\fB \-s\fR]\fR [\fIfile...\fR]" 
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-b" "Cut specified bytes"
+.FL "\-c" "Select out specific characters"
+.FL "\-d" "Change the column delimiter to \fIdelim\fR"
+.FL "\-f" "Select out specific fields that are separated by the delimiter character ( see \fIdelim\fR)"
+.FL "\-i" "Runs of delimiters count as one"
+.FL "\-s" "Suppres lines with no delimiter characters, when used with the \-f option. Lines with no delimiters are passwd through untouched"
+.SH EXAMPLES
+.EX "cut \-f 2 file" "Extract field 2"
+.EX "cut \-c 1\-2,5 file" "Extract character columns 1, 2, and 5"
+.EX "cut \-c 1\-5,7\- file" "Extract all columns except 6"
+.SH DESCRIPTION
+.PP
+\fICut\fR extracts one or more fields or columns from a file and writes them on
+standard output.
+If the \fB\-f\fR flag is used, the fields are separated by a delimiter 
+character, normally a tab, but can be changed using the \fB\-d\fR flag.
+If the \fB\-c\fR flag is used, specific columns can be specified.
+The list can be comma or BLANK separated. The \fB\-f\fR and
+\fB\-c\fR flags  are mutually exclusive.
+Note: The POSIX1003.2 standard requires the option \-b to cut out
+specific bytes in a file. It is intended for systems with multi byte
+characters (e.g. kanji), since MINIX uses only one byte characters,
+this option is equivalent to \-c. For the same reason, the option
+\-n has no effect and is not listed in this manual page.
+.SH "SEE ALSO"
+.BR sed (1),
+.BR awk (9).
Index: /trunk/minix/man/man1/date.1
===================================================================
--- /trunk/minix/man/man1/date.1	(revision 9)
+++ /trunk/minix/man/man1/date.1	(revision 9)
@@ -0,0 +1,78 @@
+.TH DATE 1
+.SH NAME
+date \- print or set the date and time
+.SH SYNOPSIS
+\fBdate [\fB\-qsuS\fR] [\fB\-r\fI seconds\fR]
+[[\fIMMDDYY\fR]\fIhhmm\fR[\fIss\fR]] [\fI+format\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-q" "Read the date from \fIstdin\fR"
+.FL "\-s" "Set the time (implicit for \fB\-q\fR or a date string)"
+.FL "\-u" "Print the date as GMT"
+.FL "\-S" "Date within Eternal September"
+.FL "\-r" "Use this number of seconds instead of current time"
+.SH EXAMPLES
+.EX "date" "Print the date and time"
+.EX "date 0221921610" "Set date to Feb 21, 1992 at 4:10 p.m."
+.SH DESCRIPTION
+.PP
+With the \fB\-q\fR flag or a numeric argument,
+.I date
+sets the GMT time and date.
+.I MMDDYY
+refers to the month, day, and year;
+.I hhmmss
+refers to the hour, minute and second.
+Each of the six fields must be exactly two digits, no more and no less.
+.I date
+always display the date and time, with the default format for the system.
+The \fB\-u\fR flag request GMT time instead of local time.
+A format may be specified with a + followed by a printf-like string with
+the following options:
+.ta 0.25i
+.nf
+.PP
+	%%  % character
+	%A  Name of the day
+	%B  Name of the month
+	%D  mm/dd/yy
+	%H  Decimal hour on 2 digits
+	%I  Decimal hour modulo 12 on 2 digits
+	%M  Decimal minute on 2 digits
+	%S  Decimal seconds on 2 digits
+	%T  HH:MM:SS
+	%U  Decimal week number, Sunday being first day of week
+	%W  Decimal week number, Monday being first day of week
+	%X  Same as %T
+	%Y  Decimal year on 4 digits
+	%Z  Time Zone (if any)
+	%a  Abbreviated name of the day
+	%b  Abbreviated name of the month
+	%c  Appropriate date & time (default format)
+	%d  Decimal day of the month on 2 digits
+	%e  Same as %d, but a space replaces leading 0
+	%h  Same as %b
+	%j  Decimal dey of the year on 3 digits
+	%m  Decimal month on 2 digits
+	%n  Newline character
+	%p  AM or PM
+	%r  12-hour clock time with AM/PM
+	%s  Number of seconds since the epoch
+	%t  Tab character
+	%w  Decimal day of the week (0=Sunday)
+	%x  Same as %D
+	%y  Decimal year on 2 digits
+.SH "SEE ALSO"
+.BR time (2),
+.BR ctime (3),
+.BR readclock (8).
Index: /trunk/minix/man/man1/dd.1
===================================================================
--- /trunk/minix/man/man1/dd.1	(revision 9)
+++ /trunk/minix/man/man1/dd.1	(revision 9)
@@ -0,0 +1,62 @@
+.TH DD 1
+.SH NAME
+dd \- convert and copy a file
+.SH SYNOPSIS
+\fBdd\fR [\fIoption = value\fR] ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "dd if=/dev/fd0 of=/dev/fd1" "Copy disk 0 to disk 1"
+.EX "dd if=x of=y bs=1w skip=4" "Copy \fIx\fP to \fIy\fP, skipping 4 words"
+.EX "dd if=x of=y count=3" "Copy three 512\-byte blocks"
+.SH DESCRIPTION
+.PP
+This command is intended for copying partial files.
+The block size, skip count, and number of blocks to copy can be specified.
+The options are:
+.PP
+.ta 0.25i 1.5i
+	\fBif\fR = file	\- Input file (default is \fIstdin\fR)
+.br
+	\fBof\fR = file	\- Output file (default is standard output)
+.br
+	\fBibs\fR = n	\- Input block size (default 512 bytes)
+.br
+	\fBobs\fR = n	\- Output block size (default is 512 bytes)
+.br
+	\fBbs\fR = n	\- Block size; sets \fIibs\fP and \fIobs\fP (default is 512 bytes)
+.br
+	\fBskip\fR = n	\- Skip \fIn\fP input blocks before reading
+.br
+	\fBseek\fR = n	\- Skip \fIn\fP output blocks before writing
+.br
+	\fBcount\fR = n	\- Copy only \fIn\fP input blocks
+.br
+	\fBconv = lcase\fR	\- Convert upper case letters to lower case
+.br
+	\fBconv = ucase\fR	\- Convert lower case letters to upper case
+.br
+	\fBconv = swab\fR	\- Swap every pair of bytes
+.br
+	\fBconv = noerror\fR	\- Ignore errors and just keep going
+.br
+	\fBconv = silent\fR	\- Suppress statistics (MINIX 3 specific flag)
+.PP
+Where sizes are expected, they are in bytes.
+However, the letters \fBw\fR, \fBb\fR, or \fBk\fR may be appended to the
+number to indicate words (2 bytes), blocks (512 bytes), or K
+(1024 bytes), respectively.
+When
+.I dd
+is finished, it reports the number of full and partial blocks read and written.
+.SH "SEE ALSO"
+.BR vol (1).
Index: /trunk/minix/man/man1/df.1
===================================================================
--- /trunk/minix/man/man1/df.1	(revision 9)
+++ /trunk/minix/man/man1/df.1	(revision 9)
@@ -0,0 +1,75 @@
+.TH DF 1
+.SH NAME
+df \- report on free disk space
+.SH SYNOPSIS
+\fBdf\fP [\fB\-ikP\fP] [\fB\-t\fP \fItype\fP] [\fIfile\fP ...]
+.SH DESCRIPTION
+.B Df
+lists the amount of free space on the currently mounted devices (no arguments),
+or the devices given as arguments.  If the argument is not a device then the
+device it resides on is listed.
+.SH OPTIONS
+Without options,
+.B df
+will give a listing like this:
+.sp
+.nf
+.if t .ft C
+Filesystem    1k-Blocks     free     used    %  FUsed%  Mounted on
+/dev/c0d0p1s0      1440      635      805  56%    26%   /
+/dev/c0d0p1s1     32768    32390      378   2%     1%   /tmp
+/dev/c0d0p1s2    784657   517809   266848  35%    29%   /usr
+.if t .ft R
+.fi
+.PP
+The
+.B \-i
+option shifts the focus to the files:
+.sp
+.nf
+.if t .ft C
+Filesystem        Files     free     used    %  BUsed%  Mounted on
+/dev/c0d0p1s0      1024      759      265  26%    56%   /
+/dev/c0d0p1s1      5472     5468        4   1%     2%   /tmp
+/dev/c0d0p1s2     65535    46734    18801  29%    35%   /usr
+.if t .ft R
+.fi
+.PP
+Option
+.B \-P
+makes
+.B df
+use \s-2POSIX\s+2 defined output in 512 byte units:
+.sp
+.nf
+.if t .ft C
+Filesystem     512-blocks    Used  Available  Capacity  Mounted on
+/dev/c0d0p1s0      2880      1628     1252       57%    /
+/dev/c0d0p1s1     65536       756    64780        2%    /tmp
+/dev/c0d0p1s2   1569314    533748  1035566       35%    /usr
+.if t .ft R
+.fi
+.PP
+With
+.B \-k
+1024 byte units would be used.
+.PP
+The
+.B \-t
+option limits
+.BR df 's
+output to file systems of the given
+.IR type .
+.SH FILES
+.TP 15n
+.B /etc/mtab
+List of mounted file systems.
+.SH "SEE ALSO"
+.BR du (1),
+.BR fstab (5).
+.SH BUGS
+Default output should also be in 512 byte units says \s-2POSIX\s+2.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+.\"
+.\" $PchId: df.1,v 1.5 1998/07/27 19:48:47 philip Exp $
Index: /trunk/minix/man/man1/dhrystone.1
===================================================================
--- /trunk/minix/man/man1/dhrystone.1	(revision 9)
+++ /trunk/minix/man/man1/dhrystone.1	(revision 9)
@@ -0,0 +1,29 @@
+.TH DHRYSTONE 1
+.SH NAME
+dhrystone \- integer benchmark
+.SH SYNOPSIS
+\fBdhrystone\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "dhrystone" "Run the dhrystone benchmark"
+.SH DESCRIPTION
+.PP
+Many years ago, a floating-point benchmark called \fIwhetstone\fR was
+popular for benchmarking FORTRAN programs.
+Nowadays, an integer benchmark called \fIdhrystone\fR is widely used
+for benchmarking UNIX systems.
+This is it.
+Be warned, however, that \fIdhrystone\fR is entirely CPU bound, and
+goes blindingly fast on machines with high-speed caches.
+Although this is a good measure for programs that spend most of their
+time in some inner loop, it is a poor benchmark for I/O bound applications.
Index: /trunk/minix/man/man1/diff.1
===================================================================
--- /trunk/minix/man/man1/diff.1	(revision 9)
+++ /trunk/minix/man/man1/diff.1	(revision 9)
@@ -0,0 +1,47 @@
+.TH DIFF 1
+.SH NAME
+diff \- print differences between two files
+.SH SYNOPSIS
+\fBdiff  \fR [\fB\-c \fR|\fB \-e \fR|\fB \-C \fIn\fR\] [\fB\-br\fR]\fIfile1 file2\fR\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-C \fIn" "Produce output that contains \fIn\fR lines of context"
+.FL "\-b" "Ignore white space when comparing"
+.FL "\-c" "Produce output that contains three lines of context"
+.FL "\-e" "Produce an \fIed\fR-script to convert \fIfile1\fR into \fIfile2\fR"
+.FL "\-r" "Apply \fIdiff\fR recursively to files and directories of the same name, when \fIfile1\fR and \fIfile2\fR are both directories"
+.SH EXAMPLES
+.EX "diff file1 file2" "Print differences between 2 files"
+.EX "diff -C 0 file1 file2" "Same as above"
+.EX "diff -C 3 file1 file2" "Output three lines of context with every difference encountered"
+.EX "diff -c file1 file2" Same as above"
+.EX "diff /etc /dev" "Compares recursively the directories \fI/etc\fR and \fI/dev\fR"
+.EX "diff passwd /etc" "Compares \fI./passwd\fR to \fI/etc/passwd"
+.SH DESCRIPTION
+.PP
+\fIDiff\fR compares two files and generates a list of lines telling how
+the two files differ.  Lines may not be longer than 128 characters.
+If the two  arguments on the command line are both directories,
+\fIdiff\fR recursively steps through all subdirectories comparing
+files of the same name. If a file name is found only in one directory,
+a diagnostic message is written to \fIstdout\fR. A file that is of
+either block special, character special or FIFO special type, cannot
+be compared to any other file.
+On the other hand, if there is one directory and one file given on the
+command line, \fIdiff\fR tries to compare the file with the same name
+as \fIfile\fR in the directory \fIdirectory\fR.
+.SH "SEE ALSO"
+.BR cdiff (1),
+.BR cmp (1),
+.BR comm (1),
+.BR patch (1).
Index: /trunk/minix/man/man1/dosdir.1
===================================================================
--- /trunk/minix/man/man1/dosdir.1	(revision 9)
+++ /trunk/minix/man/man1/dosdir.1	(revision 9)
@@ -0,0 +1,44 @@
+.TH DOSDIR 1
+.SH NAME
+dosdir \- list an MS-DOS directory [IBM]
+.SH SYNOPSIS
+\fBdosdir\fR [\fB\-lr\fR] \fIdrive\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-l" "Long listing"
+.FL "\-r" "Recursively descend and print subdirectories"
+.SH EXAMPLES
+.EX "dosdir \-l A" "List root directory on drive A"
+.EX "dosdir \-r C x/y" "Recursively list directory \fIx/y\fR"
+.EX "dosdir \-r fd1" "List device \fI/dev/fd1\fR"
+.SH DESCRIPTION
+.PP
+.I Dosdir
+reads standard IBM PC diskettes or hard disk partitions in
+\s-2MS-DOS\s+2 format and lists their contents on standard output.
+Directory names should contain slashes to separate components, even though
+\s-2MS-DOS\s+2 uses backslashes.
+The names
+.I dosdir ,
+.I dosread ,
+and 
+.I doswrite
+are all links to the same program.
+The program sees which function to perform by seeing how it was called.
+A drive code of
+.I A
+causes the program to use \fI/dev/dosA\fR, for example, 
+a link to \fI/dev/fd0\fR.
+Similarly, to have hard disk partition 1 be DOS drive C, \fI/dev/dosC\fR 
+could be a link to \fI/dev/hd1\fR, and so on for other drive codes.
+A normal device name may also be used instead of a drive code.
Index: /trunk/minix/man/man1/dosread.1
===================================================================
--- /trunk/minix/man/man1/dosread.1	(revision 9)
+++ /trunk/minix/man/man1/dosread.1	(revision 9)
@@ -0,0 +1,30 @@
+.TH DOSREAD 1
+.SH NAME
+dosread \- read a file from an MS-DOS diskette [IBM]
+.SH SYNOPSIS
+\fBdosread\fR [\fB\-a\fR] \fIdrive \fIfile\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-a" "ASCII file"
+.SH EXAMPLES
+.EX "dosread C g/adv >adv" "Read file \fIg/adv\fR from hard disk"
+.EX "dosread \-a A prog.c >x" "Read ASCII file \fIprog.c\fR from drive A"
+.SH DESCRIPTION
+.PP
+.I Dosread
+reads one \s-2MS-DOS\s+2 file and writes it on standard output.
+The file name must use slash, not backslash as a separator.
+ASCII files have the final CTRL-Z stripped, and carriage return plus
+line feed are mapped to line feed only, the usual
+\s-1MINIX 3\s-1
+convention.  See \fBdosdir\fR on the use of single letter drive codes.
Index: /trunk/minix/man/man1/doswrite.1
===================================================================
--- /trunk/minix/man/man1/doswrite.1	(revision 9)
+++ /trunk/minix/man/man1/doswrite.1	(revision 9)
@@ -0,0 +1,28 @@
+.TH DOSWRITE 1
+.SH NAME
+doswrite \- write a file onto an MS-DOS diskette [IBM]
+.SH SYNOPSIS
+\fBdoswrite\fR [\fB\-a\fR] \fIdrive \fIfile\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-a" "ASCII file"
+.SH EXAMPLES
+.EX "doswrite A x/y <z" "Write file \fIz\fR to disk as \fIx/y\fR"
+.EX "doswrite \-a B f" "Copy \fIstdin\fR to \s-2MS-DOS\s+2 file \fIf\fR"
+.SH DESCRIPTION
+.PP
+.I Doswrite
+writes its \fIstdin\fR to an \s-2MS-DOS\s+2 file.
+The diskette or partition must be formatted and have an \s-2MS-DOS\s+2 file 
+system already in place, including all the directories leading up to the file.
+See \fBdosdir\fR on the use of single letter drive codes.
Index: /trunk/minix/man/man1/du.1
===================================================================
--- /trunk/minix/man/man1/du.1	(revision 9)
+++ /trunk/minix/man/man1/du.1	(revision 9)
@@ -0,0 +1,36 @@
+.TH DU 1
+.SH NAME
+du \- print disk usage
+.SH SYNOPSIS
+\fBdu\fR [\fB\-as\fR]\fR [\fB\-l \fIn\fR] \fIdir\fR ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-a" "Give usage for all files"
+.FL "\-l" "List up to \fIn\fR levels of subdirectories"
+.FL "\-d" "Do not cross file system boundaries"
+.FL "\-s" "Summary only"
+.SH EXAMPLES
+.EX "du dir" "List disk space used by files in dir"
+.EX "du \-s dir1 dir2" "Give summaries only"
+.EX "du \-d /" "Show only the root device"
+.SH DESCRIPTION
+.PP
+\fIDu\fR examines one or more directories and prints the amount of space 
+occupied by the files in those directories and their subdirectories.
+.SH BUGS
+\fIDu\fR calculates disk usage based on file size. It could be there
+are holes in the file, not occupying any actual disk blocks, causing
+\fIdu\fR to overestimate disk usage. (\fIDu\fR does recognize and correctly
+calculate disk usage when hard links are encountered.)
+.SH "SEE ALSO"
+.BR df (1).
Index: /trunk/minix/man/man1/easypack.1
===================================================================
--- /trunk/minix/man/man1/easypack.1	(revision 9)
+++ /trunk/minix/man/man1/easypack.1	(revision 9)
@@ -0,0 +1,37 @@
+.TH EASYPACK 1
+.SH NAME
+easypack \- Fetch and install a package
+.SH SYNOPSIS
+\fBeasypack\fR [\fB\-\fIo\fR]
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-\fIo\fR" "If package is already installed, overwrite it
+.SH EXAMPLES
+.EX "easypack gzip-1.2.4" "Fetch gzip-1.2.4 package"
+.EX "easypack -o  indent telnet" "Refetch these 2 packages"
+.SH DESCRIPTION
+.PP
+MINIX 3 user programs, such as emacs, kermit, and telnet are
+organized into packages. The complete list is avail\%able at
+\fIwww.minix3.org/software\fR. While most packages are included
+on the downloadable CD-ROM image, the larger ones are not.
+Any package can be easily downloaded and installed by just
+giving one simple easypack command listing the package names
+taken from the Website.
+Each package is a .tar.bz2 file that is fetched from \fIwww.minix3.org\fR,
+and then copied to \fI/usr/src/commands\fR, decompressed and untarred.
+Then the \fIbuild\fR script in the top-level directory is executed
+to install it. This command should be called when logged in as bin
+to provide write access to the relevant directories. A log file,
+\fILog\fR, is produced for debugging in case building fails.
+
Index: /trunk/minix/man/man1/echo.1
===================================================================
--- /trunk/minix/man/man1/echo.1	(revision 9)
+++ /trunk/minix/man/man1/echo.1	(revision 9)
@@ -0,0 +1,68 @@
+.TH ECHO 1
+.SH NAME \"	Copyright (C) 1989 by Kenneth Almquist.
+echo \- produce message in a shell script
+.SH SYNOPSIS
+.B echo
+[
+.B -n
+|
+.B -e
+]
+.I args...
+.SH DESCRIPTION
+.I Echo
+prints its arguments on the standard output, separated by spaces.
+Unless the
+.B -n
+option is present, a newline is output following the arguments.
+The
+.B -e
+option causes
+.I echo
+to treat the escape sequences specially, as described in the following
+paragraph.
+Only one of the options
+.B -n
+and
+.B -e
+may be given.
+.PP
+If any of the following sequences of characters is encountered during
+output, the sequence is not output.  Instead, the specified action is
+performed:
+.de i
+.IP "\\fB\\$1\\fR" 5
+..
+.i \eb
+A backspace character is output.
+.i \ec
+Subsequent output is suppressed.  This is normally used at the end of the
+last argument to suppress the trailing newline that
+.I echo
+would otherwise output.
+.i \ef
+Output a form feed.
+.i \en
+Output a newline character.
+.i \er
+Output a carriage return.
+.i \et
+Output a (horizontal) tab character.
+.i \ev
+Output a vertical tab.
+.i \e0\fIdigits\fR
+Output the character whose value is given by zero to three digits.
+If there are zero digits, a nul character is output.
+.i \e\e
+Output a backslash.
+.SH HINTS
+Remember that backslash is special to the shell and needs to be escaped.
+To output a message to standard error, say
+.sp
+.ti +1i
+echo message >&2
+.SH BUGS
+The octal character escape mechanism (\e0\fIdigits\fR) differs from the
+C language mechanism.
+.SH AUTHOR
+Kenneth Almquist.
Index: /trunk/minix/man/man1/ed.1
===================================================================
--- /trunk/minix/man/man1/ed.1	(revision 9)
+++ /trunk/minix/man/man1/ed.1	(revision 9)
@@ -0,0 +1,69 @@
+.TH ED 1
+.SH NAME
+ed \- editor
+.SH SYNOPSIS
+\fBed \fIfile\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-" "Suppress line/byte count messages (for in scripts)"
+.SH EXAMPLES
+.EX "ed prog.c" "Edit \fIprog.c\fR"
+.EX "echo '1,$p' | ed - file" "Odd way to write 'cat file'"
+.SH DESCRIPTION
+.PP
+\fIEd\fR is functionally equivalent to the standard V7 editor, ed.  
+It supports the following commands:
+.PP
+.nf
+.ta 0.5i 0.95i	
+	(.)	a: append
+	(.,.)	c: change
+	(.,.)	d: delete
+		e: edit new file"
+		f: print name of edited file"
+	(1,$)	g: global command
+	(.)	i: insert
+	(.,.+1)	j: join lines together
+	(.)	k: mark
+	(.)	l: print with special characters in octal
+	(.,.)	m: move
+	(.,.)	p: print
+		q: quit editor"
+	(.)	r: read in new file
+	(.,.)	s: substitute
+	(1,$)	v: like g, except select lines that do not match
+	(1,$)	w: write out edited file
+.fi
+Many of the commands can take one or two addresses, as indicated above.  The
+defaults are shown in parentheses.  Thus \fIa\fR appends to the current 
+line, and \fIg\fR works on the whole file as default.  
+The dot refers to the current line.
+Below is a sample editing session with comments given following the # symbol.
+.PP
+.nf
+.ta 0.5i 2.5i
+	ed prog.c	# Edit prog.c
+	3,20p	# Print lines 3 through 20
+	/whole/	# Find next occurence of \fIwhole\fR
+	s/whole/while/	# Replace \fIwhole\fR by \fIwhile\fR
+	g/Buf/s//BUF/g	# Replace \fIBuf\fR by \fIBUF\fR everywhere
+	w	# Write the file back
+	q	# Exit the editor
+.fi
+\fIEd\fR is provided for its sentimental value.
+If you want a line-oriented editor, try \fIex\fR.
+If you want a good editor, use \fIelle\fR, \fIelvis\fR, or \fImined\fR.
+.SH "SEE ALSO"
+.BR elvis (1),
+.BR elle (9),
+.BR mined (9).
Index: /trunk/minix/man/man1/eject.1
===================================================================
--- /trunk/minix/man/man1/eject.1	(revision 9)
+++ /trunk/minix/man/man1/eject.1	(revision 9)
@@ -0,0 +1,30 @@
+.TH EJECT 1
+.SH NAME
+eject \- eject removable media
+.SH SYNOPSIS
+.B eject
+.I device
+.SH DESCRIPTION
+.B Eject
+tells a device to eject removable media, usually a floppy or CD-ROM.
+.B Eject
+invokes the
+.B DIOCEJECT
+ioctl on the device.  The media will then be ejected, or allowed to be
+removed.  The call will fail if the device is still in use.
+.PP
+Tapes can't be unloaded with this command, use
+.B mt offline
+instead.
+.SH "SEE ALSO"
+.BR mt (1),
+.BR disk (4),
+.BR tape (4).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+
+.\" hd, sd changed to disk, tape -- ASW 2004-12-13
+
+
+
+
Index: /trunk/minix/man/man1/elvis.1
===================================================================
--- /trunk/minix/man/man1/elvis.1	(revision 9)
+++ /trunk/minix/man/man1/elvis.1	(revision 9)
@@ -0,0 +1,101 @@
+.TH ELVIS 1
+.SH NAME
+elvis, ex, vi \- The editor
+.SH SYNOPSIS
+\fBelvis\fP [\fIflags\fP] [\fB+\fP\fIcmd\fP] [\fIfiles\fP...]
+.SH DESCRIPTION
+\fBElvis\fP is a text editor which emulates \fBvi\fP/\fBex\fP.
+.PP
+On systems which pass the program name as an argument, such as UNIX and MINIX 3,
+you may also install \fBelvis\fP under the names "ex", "vi", "view", and "input".
+These extra names would normally be links to elvis;
+see the "ln" shell command.
+.PP
+When \fBelvis\fP is invoked as "vi",
+it behaves exactly as though it was invoked as "elvis".
+However, if you invoke \fBelvis\fP as "view",
+then the readonly option is set as though you had given it the "-R" flag.
+If you invoke \fBelvis\fP as "ex",
+then \fBelvis\fP will start up in the colon command mode
+instead of the visual command mode,
+as though you had given it the "-e" flag.
+If you invoke \fBelvis\fP as "input" or "edit",
+then \fBelvis\fP will start up in input mode,
+as though the "-i" flag was given.
+.SH OPTIONS
+.IP \fB-r\fP
+To the real vi, this flag means that a previous edit should be recovered.
+\fBElvis\fP, though, has a separate program, called \fIelvrec\fP(1), for recovering
+files.
+When you invoke \fBelvis\fP with -r, \fBelvis\fP will tell you to run \fBelvrec\fP.
+.IP \fB-R\fP
+This sets the "readonly" option,
+so you won't accidentally overwrite a file.
+.IP "\fB-t\fP \fItag\fP"
+This causes \fBelvis\fP to start editing at the given tag.
+.IP "\fB-m\fP [\fIfile\fP]"
+\fBElvis\fP will search through \fIfile\fP for something that looks like
+an error message from a compiler.
+It will then begin editing the source file that caused the error,
+with the cursor sitting on the line where the error was detected.
+If you don't explicitly name a \fIfile\fP, then "errlist" is assumed.
+.IP \fB-e\fP
+\fBElvis\fP will start up in colon command mode.
+.IP \fB-v\fP
+\fBElvis\fP will start up in visual command mode.
+.IP \fB-i\fP
+\fBElvis\fP will start up in input mode.
+.IP "\fB-w\fR \fIwinsize\fR"
+Sets the "window" option's value to \fIwinsize\fR.
+.IP "\fB+\fP\fIcommand\fP or \fB-c\fP \fIcommand\fP"
+If you use the +\fIcommand\fP parameter,
+then after the first file is loaded
+\fIcommand\fP is executed as an EX command.
+A typical example would be "elvis +237 foo",
+which would cause \fBelvis\fP to start editing foo and
+then move directly to line 237.
+The "-c \fIcommand\fP" variant was added for UNIX SysV compatibility.
+.SH FILES
+.IP /tmp/elv*
+During editing,
+\fBelvis\fP stores text in a temporary file.
+For UNIX, this file will usually be stored in the /tmp directory,
+and the first three characters will be "elv".
+For other systems, the temporary files may be stored someplace else;
+see the version-specific section of the documentation.
+.IP tags
+This is the database used by the \fB:tags\fP command and the \fB-t\fP option.
+It is usually created by the \fBctags\fP(1) program.
+.IP ".exrc or elvis.rc"
+On UNIX-like systems, a file called ".exrc" in your home directory
+is executed as a series of \fBex\fR commands.
+A file by the same name may be executed in the current directory, too.
+On non-UNIX systems, ".exrc" is usually an invalid file name;
+there, the initialization file is called "elvis.rc" instead.
+.SH "SEE ALSO"
+.BR ctags (1),
+.BR ref (1),
+.BR elvrec (1),
+.BR elvis (9).
+.PP
+\fIElvis - A Clone of Vi/Ex\fP, the complete \fBelvis\fP documentation.
+.SH BUGS
+There is no LISP support.
+Certain other features are missing, too.
+.PP
+Auto-indent mode is not quite compatible with the real vi.
+Among other things, 0^D and ^^D don't do what you might expect.
+.PP
+Long lines are displayed differently.
+The real vi wraps long lines onto multiple rows of the screen,
+but \fBelvis\fP scrolls sideways.
+.SH AUTHOR
+.nf
+Steve Kirkendall
+kirkenda@cs.pdx.edu
+.fi
+.PP
+Many other people have worked to port \fBelvis\fP to various operating systems.
+To see who deserves credit, run the \fB:version\fP command from within \fBelvis\fP,
+or look in the system-specific section of the complete documentation.
+.\" ref to virec chnaged to elvrec -- ASW 2004-12-13
Index: /trunk/minix/man/man1/elvrec.1
===================================================================
--- /trunk/minix/man/man1/elvrec.1	(revision 9)
+++ /trunk/minix/man/man1/elvrec.1	(revision 9)
@@ -0,0 +1,47 @@
+.TH ELVREC 1
+.SH NAME
+elvrec - Recover the modified version of a file after a crash
+.SH SYNOPSIS
+.nf
+\fBelvrec\fP [\fIpreservedfile\fP [\fInewfile\fR]]
+.fi
+.SH DESCRIPTION
+.PP
+If you're editing a file when \fIelvis\fP dies, the system crashes, or power fails,
+the most recent version of your text will be preserved.
+The preserved text is stored in a special directory; it does NOT overwrite
+your text file automatically.
+.PP
+The \fIelvrec\fP program locates the preserved version of a given file,
+and writes it over the top of your text file -- or to a new file, if you prefer.
+The recovered file will have nearly all of your changes.
+.PP
+To see a list of all recoverable files, run \fIelvrec\fP with no arguments.
+.SH FILES
+.IP /usr/preserve/p*
+The text that was preserved when \fIelvis\fP died.
+.IP /usr/preserve/Index
+A text file which lists the names of all preserved files, and the names
+of the /usr/preserve/p* files which contain their preserved text.
+.SH BUGS
+.PP
+\fIelvrec\fP is very picky about filenames.
+You must tell it to recover the file using exactly the same pathname as
+when you were editing it.
+The simplest way to do this is to go into the same directory that you were
+editing, and invoke \fIelvrec\fP with the same filename as \fIelvis\fP.
+If that doesn't work, then try running \fIelvrec\fP with no arguments,
+to see exactly which pathname it is using for the desired file.
+.PP
+Due to the permissions on the /usr/preserve directory, on UNIX systems
+\fIelvrec\fP must be run as superuser.
+This is accomplished by making the \fIelvrec\fP executable be owned by "root"
+and setting its "set user id" bit.
+.PP
+If you're editing a nameless buffer when \fIelvis\fP dies, then \fIelvrec\fP
+will pretend that the file was named "foo".
+.SH AUTHOR
+.nf
+Steve Kirkendall
+kirkenda@cs.pdx.edu
+.fi
Index: /trunk/minix/man/man1/env.1
===================================================================
--- /trunk/minix/man/man1/env.1	(revision 9)
+++ /trunk/minix/man/man1/env.1	(revision 9)
@@ -0,0 +1,93 @@
+.TH ENV 1
+.SH NAME
+env \- set environment for command
+.SH SYNOPSIS
+.B env
+.RB [ \-ia ]
+.RI [ name\fB=\fIvalue "] ..."
+.RI [ utility
+.RI [ argument "...]]"
+.SH DESCRIPTION
+.B Env
+modifies its environment according to the
+.IB name = value
+arguments, and executes
+.I utility
+with the given arguments and the modified environment.
+.PP
+If no utility is specified then the modified environment is printed as
+.IB name = value
+strings, one per line.
+.SH OPTIONS
+.TP
+.B \-i
+Use exactly the environment specified by the arguments; the inherited
+environment is ignored.
+.TP
+.B \-a
+Specify all arguments for the utility, i.e. the first of the arguments is
+used as
+.BR "argv[0]" ,
+the program name.  Normally the program name is
+.I utility
+itself.
+.SH ENVIRONMENT
+.TP 8n
+.B PATH
+The path used to find utility.  It is as modified by
+.BR env ,
+i.e.
+.B not
+the inherited
+.BR PATH .
+.SH "SEE ALSO"
+.BR sh (1),
+.BR execvp (3),
+.BR environ (5).
+.SH DIAGNOSTICS
+The return code is
+.B 0
+after successfully printing the environment,
+.B 1
+on an error within
+.BR env ,
+.B 126
+if the
+.I utility
+could not be executed, or
+.B 127
+if
+.I utility
+could not be found.  Appropriate diagnostic messages are printed on standard
+error.
+If
+.I utility
+can be executed then it replaces
+.BR env ,
+so the return code is then the return code of
+.IR utility .
+.SH NOTES
+When run from the standard shell
+.B env
+is only useful with options or without arguments.  Otherwise the shell can
+do exactly what
+.B env
+can do, simply omit the word "env" on the command line.
+.PP
+One interesting use of
+.B env
+is with #! on the first line of a script to forge a PATH search for an
+interpreter.  For example:
+.PP
+.RS
+#!/usr/bin/env perl
+.RE
+.PP
+This will find the Perl interpreter if it is within the user's PATH.  Most
+UNIX-like systems have
+.B env
+in /usr/bin, but
+.B perl
+may be anywhere.
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man1/expand.1
===================================================================
--- /trunk/minix/man/man1/expand.1	(revision 9)
+++ /trunk/minix/man/man1/expand.1	(revision 9)
@@ -0,0 +1,28 @@
+.TH EXPAND 1
+.SH NAME
+expand \- convert tabs to spaces
+.SH SYNOPSIS
+\fBexpand\fR [\fB\-\fIt1,t2, ...\fR]\fR [\fIfile\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-\fIt\fR" "Tab stop positions"
+.SH EXAMPLES
+.EX "expand \-16,32,48,64" "Expand \fIstdin\fR with tabs every 16 columns"
+.SH DESCRIPTION
+.PP
+\fIExpand\fR replaces tabs in the named files with the equivalent numbers
+of spaces.  If no files are listed, \fIstdin\fR is given.  If only one
+tab is given, the rest are multiples of it.  The default is a tab every 8
+spaces.
+.SH "SEE ALSO"
+.BR unexpand (1).
Index: /trunk/minix/man/man1/expr.1
===================================================================
--- /trunk/minix/man/man1/expr.1	(revision 9)
+++ /trunk/minix/man/man1/expr.1	(revision 9)
@@ -0,0 +1,243 @@
+.TH EXPR 1
+.SH NAME \"	Copyright (C) 1989 by Kenneth Almquist.
+expr, test, [ \- evaluate expressions
+.SH SYNOPSIS
+.B expr
+.I expression
+.br
+.B test
+.I expression
+.br
+.B [
+.I expression
+.B ]
+.SH DESCRIPTION
+.B Expr
+evaluates the expression and prints the result.
+.B Test
+evaluates the expression without printing the result.
+The ``[''
+command is a synonym for
+.BR test ;
+when invoked under this name
+the last argument to
+.B expr
+must be a ``]'', which is deleted and not considered part of the expression.
+.PP
+Three data types may occur in the
+.IR expression :
+string, integer, and boolean.
+The rules for conversion are as follows:
+.sp
+.nr i 2
+.ta \nii
+.in +\nii
+.ti -\nii
+\fIstring\fR\->\fIinteger\fR	Done via
+.BR atoi (3).
+.ti -\nii
+\fIinteger\fR\->\fIstring\fR	Convert to decimal representation.
+.ti -\nii
+\fIstring\fR\->\fIboolean\fR	"" \-> false, everything else to true.
+.ti -\nii
+\fIboolean\fR\->\fIstring\fR	false \-> "", true \-> "true".
+.ti -\nii
+\fIinteger\fR\->\fIboolean\fR	0 \-> false, everything else to true.
+.ti -\nii
+\fIboolean\fR\->\fIinteger\fR	false \-> 0, true \-> 1.
+.in -\nii
+.PP
+Any argument to
+.B expr
+which is not a legal operator is treated as a string operand of type
+.BR string .
+.PP
+As a special case, if
+.I expression
+is omitted, the result is false.
+.PP
+We now list the operators.  The syntax
+.sp
+.ti +8
+\fIinteger\fB op \fIinteger\fR \-> \fIboolean\fB (3)\fR
+.sp
+means that \fBop\fR is a binary operator which takes operands of type
+\fIinteger\fR and produces a result of type \fIboolean\fR.
+The ``(3)'' means that the priority of \fBop\fR is 3.
+Operands are automatically converted to the appropriate type.  The type
+\fIany\fR is used for operator that take operands of any type.
+.nr p 1
+.de b
+.TP 0.5i
+\fI\\$1\fB \\$2 \fI\\$3\fR \-> \\fI\\$4\\fR  (\\np)
+..
+.de u
+.TP 0.5i
+\\$1 \fI\\$2\fR \-> \\fI\\$3\\fR  (\\np)
+..
+.b any \-o any any
+Returns the value of the left hand operand if the left hand operand
+would yield
+.B true
+if converted to type
+.BR boolean ,
+and the value of the right hand operand otherwise.
+The right hand operand is evaluated only if necessary.
+``|'' is a synonym for ``\-o''.
+.nr p \np+1
+.b any -a any any
+Returns the value of the left hand operand if the left hand operand
+would yield
+.B false
+if converted to type
+.BR boolean ,
+and the value of the right hand operand otherwise.
+The right hand operand is evaluated only if necessary.
+``&'' is a synonym for ``\-a''.
+.nr p \np+1
+.u ! boolean boolean
+Returns true if the operand is false, and false if the operand is true.
+.nr p \np+1
+.b string = string boolean
+True if the two strings are equal.
+.b string != string boolean
+True if the two strings are not equal.
+.b integer \-eq integer boolean
+True if the two operands are equal.
+.b integer \-ne integer boolean
+True if the two operands are not equal.
+.b integer \-gt integer boolean
+True if the first operand is greater than the second one.
+.b integer \-lt integer boolean
+True if the first operand is less than the second one.
+.b integer \-ge integer boolean
+True if the first operand is greater than or equal to the second one.
+.b integer \-le integer boolean
+True if the first operand is less than or equal to the second one.
+.nr p \np+1
+.b integer + integer integer
+Add two integers.
+.b integer \- integer integer
+Subtract two integers.
+.nr p \np+1
+.b integer * integer integer
+Multiply two integers.  ``*'' is special to the shell, so you generally
+have to write this operator as ``\e*''.
+.b integer / integer integer
+Divide two integers.
+.b integer % integer integer
+Returns the remainder when the first operand is divided by the second one.
+.nr p \np+1
+.b string : string "integer or string"
+The second operand is interpreted as a regular expression (as in the
+System V
+.B ed
+program).
+This operator attempts to match part (or all) of the first operand
+with the regular expression.  The match must start at the beginning of
+the first operand.
+If the regular expression contains \e( \e) pairs, then the result
+of this operator is the string which is matched by the regular expression
+between these pairs, or the null string if no match occurred.  Otherwise,
+the result is the number of characters matched by the regular expression,
+or zero if no no match occurred.
+.nr p \np+1
+.u \-n string integer
+Returns the number of characters in the string.
+.u \-z string boolean
+Returns true if the string contains zero characters.
+.u \-t integer boolean
+Returns true if the specified file descriptor is associated with a tty.
+.PP
+The remaining operators all deal with files.  Except as noted, they return
+false if the
+specified file does not exist.  The ones dealing with permission use
+the effective user and group ids of the shell.
+.u \-r string boolean
+True if you have read permission on the file.
+.u \-w string boolean
+True if you have write permission on the file.
+.u \-x string boolean
+True if you have execute permission on the file.
+.u \-f string boolean
+True if the file is a regular file.
+.u \-d string boolean
+True if the file is a directory.
+.u \-c string boolean
+True if the file is a character special file.
+.u \-b string boolean
+True if the file is a block special file.
+.u \-p string boolean
+True if the file is a named pipe (i.e. a fifo).
+.u \-u string boolean
+True if the file is setuid.
+.u \-g string boolean
+True if the file is setgid.
+.u \-k string boolean
+True if the file has the sticky bit set.
+.u \-s string "integer or boolean"
+Returns the size of the file, or 0 if the file does not exist.
+.u \-h string boolean
+True if the file is a symlink.  This is the only file test operator that
+does not follow symlinks, all others do.  So ``\-d'' and ``\-h''
+are both true on a symlink pointing to a directory.
+``\-L'' is a synonym for ``\-h''.
+.SH "EXIT CODE"
+0 if the result of 
+.I expression
+would be
+.B true
+if the result were converted to
+.BR boolean .
+.br
+1 if the result of 
+.I expression
+would be
+.B false
+if the result were converted to
+.BR boolean .
+.br
+2 if
+.I expression
+is syntactically incorrect.
+.SH EXAMPLES
+.TP 0.5i
+filesize=`expr \-s file`
+Sets the shell variable
+.I filesize
+to the size of
+.IR file .
+.TP 0.5i
+if [ \-s file ]; then command; fi
+Execute
+.I command
+if
+.I file
+exists and is not empty.
+.TP 0.5i
+x=`expr "$x" : '.\\{4\\}\\(.\\{0,3\\}\\)'`
+Sets
+.I x
+to the substring of
+.I x
+beginning after the fourth character of
+.I x
+and continuing for three characters or until the end of the string,
+whichever comes first.
+.TP 0.5i
+x=`expr X"$x" : X'.\\{4\\}\\(.\\{0,3\\}\\)'`
+This example is the same as the previous one, but it uses a leading
+``X'' to make things work when the value of
+.I x
+looks like an operator.
+.SH BUGS
+The relational operators of the System V
+.B expr
+command are not implemented.
+.PP
+Certain features of this version of
+.B expr
+are not present in System V, so care should be used when writing
+portable code.
+.SH COPYRIGHT
+Kenneth Almquist.
Index: /trunk/minix/man/man1/factor.1
===================================================================
--- /trunk/minix/man/man1/factor.1	(revision 9)
+++ /trunk/minix/man/man1/factor.1	(revision 9)
@@ -0,0 +1,22 @@
+.TH FACTOR 1
+.SH NAME
+factor \- factor an integer less than 2**31
+.SH SYNOPSIS
+\fBfactor \fInumber\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "factor 450180" "Print the prime factors of 450180"
+.SH DESCRIPTION
+.PP
+\fIFactor\fR prints the prime factors of its argument in increasing order.
+Each factor is printed as many times as it appears in the number.
Index: /trunk/minix/man/man1/fgrep.1
===================================================================
--- /trunk/minix/man/man1/fgrep.1	(revision 9)
+++ /trunk/minix/man/man1/fgrep.1	(revision 9)
@@ -0,0 +1,35 @@
+.TH FGREP 1
+.SH NAME
+fgrep \- fixed grep
+.SH SYNOPSIS
+\fBfgrep\fR [\fB\-cfhlnsv\fR]\fR [\fIstring_file\fR] [\fIstring\fR] [\fIfile\fR] ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-c" "Count matching lines and only print count, not the lines"
+.FL "\-f" "Take strings from file named in following argument"
+.FL "\-h" "Omit file headers from printout"
+.FL "\-l" "List file names once only"
+.FL "\-n" "Each line is preceded by its line number"
+.FL "\-s" "Status only, no output"
+.FL "\-v" "Print only lines not matching"
+.SH EXAMPLES
+.EX "fgrep % prog.c" "Print lines containing % sign"
+.EX "fgrep \-f pattern prog.c" "Take strings from \fIpattern\fR"
+.SH DESCRIPTION
+.PP
+\fIFgrep\fR is essentially the same as grep, except that it only searches
+for lines containing literal strings (no wildcard characters).  The pattern
+may consist of several lines with one string to search on each line.
+.SH "SEE ALSO"
+.BR cgrep (1),
+.BR grep (1).
Index: /trunk/minix/man/man1/file.1
===================================================================
--- /trunk/minix/man/man1/file.1	(revision 9)
+++ /trunk/minix/man/man1/file.1	(revision 9)
@@ -0,0 +1,24 @@
+.TH FILE 1
+.SH NAME
+file \- make a guess as to a file's type based on contents
+.SH SYNOPSIS
+\fBfile \fIname ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "file a.out ar.h" "Guess at types"
+.SH DESCRIPTION
+.PP
+\fIFile\fR reads the first block of a file and tries to make an 
+intelligent guess about what kind of file it is.  
+It understands about archives, C
+source programs, executable binaries, shell scripts, and English text.
Index: /trunk/minix/man/man1/find.1
===================================================================
--- /trunk/minix/man/man1/find.1	(revision 9)
+++ /trunk/minix/man/man1/find.1	(revision 9)
@@ -0,0 +1,84 @@
+.TH FIND 1
+.SH NAME
+find \- find files meeting a given condition
+.SH SYNOPSIS
+\fBfind \fIdirectory \fIexpression\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "find /  \-name a.out \-print" "Print all \fIa.out\fR paths"
+.EX "find /usr/ast ! \-newer f \-ok rm {} \e;" "Ask before removing"
+.EX "find /usr \-size +20 \-exec mv {} /big \e^;" "move files > 10k"
+.EX "find / \e( \-name a.out \-o \-name \(fm*.o\(fm \e) \-exec rm {} \e;" "2 conds"
+.SH DESCRIPTION
+.PP
+\fIFind\fR descends the file tree starting at the given directory checking
+each file in that directory and its subdirectories against a predicate.
+If the predicate is true, an action is taken.  The predicates may be
+connected by \fB\-a\fR (Boolean and), \fB\-o\fR (Boolean or) and !
+(Boolean negation).
+Each predicate is true under the conditions specified below.  The integer 
+\fIn\fR may also be +\fIn\fR to mean any value greater than \fIn\fR, 
+\fI\-n\fR to mean any value less than
+\fIn\fR, or just \fIn\fR for exactly \fIn\fR.
+.PP
+.RS
+.ta +\w'\-mtime nmm'u
+.in +\w'\-mtime nmm'u
+.ti -\w'\-mtime nmm'u
+\-name s	true if current filename is \fIs\fR (include shell wild cards)
+.ti -\w'\-mtime nmm'u
+\-size n	true if file size is \fIn\fR blocks
+.ti -\w'\-mtime nmm'u
+\-inum n	true if the current file's i-node number is \fIn\fR
+.ti -\w'\-mtime nmm'u
+\-mtime n	true if modification time relative to today (in days) is \fIn\fR
+.ti -\w'\-mtime nmm'u
+\-links n	true if the number of links to the file is \fIn\fR
+.ti -\w'\-mtime nmm'u
+\-newer f	true if the file is newer than \fIf\fR
+.ti -\w'\-mtime nmm'u
+\-perm n	true if the file's permission bits = \fIn\fR (\fIn\fR is in octal)
+.ti -\w'\-mtime nmm'u
+\-user u	true if the uid = \fIu\fR (a numerical value, not a login name)
+.ti -\w'\-mtime nmm'u
+\-group g	true if the gid = \fIg\fR (a numerical value, not a group name)
+.ti -\w'\-mtime nmm'u
+\-type x	where \fIx\fR is \fBbcdfug\fR (block, char, dir, regular file, setuid, setgid)
+.ti -\w'\-mtime nmm'u
+\-xdev	do not cross devices to search mounted file systems
+.in -\w'\-mtime nmm'u
+.fi
+.RE
+.PP
+Following the expression can be one of the following, telling what to do
+when a file is found:
+.PP
+.RS
+.ta +\w'\-mtime nmm'u
+.in +\w'\-mtime nmm'u
+.ti -\w'\-mtime nmm'u
+\-print	print the file name on standard output
+.ti -\w'\-mtime nmm'u
+\-print0	print the file name terminated by a null character, to be
+used with
+.BR "xargs \-0" .
+(MINIX 3 extension).
+.ti -\w'\-mtime nmm'u
+\-exec	execute a command, {} stands for the file name
+.ti -\w'\-mtime nmm'u
+\-ok	prompts before executing the command
+.in -\w'\-mtime nmm'u
+.RE
+.SH "SEE ALSO"
+.BR test (1),
+.BR xargs (1).
Index: /trunk/minix/man/man1/finger.1
===================================================================
--- /trunk/minix/man/man1/finger.1	(revision 9)
+++ /trunk/minix/man/man1/finger.1	(revision 9)
@@ -0,0 +1,84 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)finger.1	6.4 (Berkeley) 5/10/86
+.\"
+.TH FINGER 1 "May 10, 1986"
+.UC 4
+.SH NAME
+finger \- user information lookup program
+.SH SYNOPSIS
+.B finger
+[
+options
+] name ...
+.SH DESCRIPTION
+By default
+.B finger
+lists the login name, full name, terminal name and write status
+(as a `*' before the terminal name if write permission is denied),
+idle time, login time, and office location and phone number
+(if they are known) for each current UNIX user.
+(Idle time is minutes if it is a single integer, hours and minutes if a ':'
+is present, or days and hours if a 'd' is present.)
+.PP
+A longer format also exists and is used by
+.B finger
+whenever a list of people's names is given.  (Account names as well as
+first and last names of users are accepted.)
+This format is multi-line, and includes all the information described above
+as well as the user's home
+directory and login shell, any plan which the person has placed in the file
+.B \&.plan
+in their home
+directory, and the project on which they are working from the file
+.B \&.project
+also in the home directory.
+.PP
+.B Finger
+may be used to lookup users on a remote machine.  The format is to specify
+the user as ``user@host.''  If the user name is left off, the
+standard format listing is provided on the remote machine.
+.PP
+.B Finger
+options include:
+.TP
+.B \-m
+Match arguments only on user name.
+.TP
+.B \-l
+Force long output format.
+.TP
+.B \-p
+Suppress printing of the
+.B \&.plan
+files
+.TP
+.B \-s
+Force short output format.
+.SH FILES
+.ta 2i
+/etc/utmp	who file
+.br
+/etc/passwd	for users names, offices, ...
+.br
+/usr/adm/lastlog	last login times
+.br
+~/.plan	plans
+.br
+~/.project	projects
+.SH "SEE ALSO"
+.BR chfn (1),
+.BR w (1),
+.BR who (1).
+.SH AUTHOR
+Earl T. Cohen
+.SH BUGS
+Only the first line of the
+.B .project
+file is printed.
+.PP
+There is no way to pass arguments to the remote machine as
+.B finger
+uses an internet standard port.
Index: /trunk/minix/man/man1/flex.1
===================================================================
--- /trunk/minix/man/man1/flex.1	(revision 9)
+++ /trunk/minix/man/man1/flex.1	(revision 9)
@@ -0,0 +1,780 @@
+.TH FLEX 1 "26 May 1990" "Version 2.3"
+.SH NAME
+flex, lex - fast lexical analyzer generator
+.SH SYNOPSIS
+.B flex
+.B [-bcdfinpstvFILT8 -C[efmF] -Sskeleton]
+.I [filename ...]
+.SH DESCRIPTION
+.I flex
+is a tool for generating
+.I scanners:
+programs which recognized lexical patterns in text.
+.I flex
+reads
+the given input files, or its standard input if no file names are given,
+for a description of a scanner to generate.  The description is in
+the form of pairs
+of regular expressions and C code, called
+.I rules.  flex
+generates as output a C source file,
+.B lex.yy.c,
+which defines a routine
+.B yylex().
+This file is compiled and linked with the
+.B -lfl
+library to produce an executable.  When the executable is run,
+it analyzes its input for occurrences
+of the regular expressions.  Whenever it finds one, it executes
+the corresponding C code.
+.LP
+For full documentation, see
+.B flexdoc(1).
+This manual entry is intended for use as a quick reference.
+.SH OPTIONS
+.I flex
+has the following options:
+.TP
+.B -b
+Generate backtracking information to
+.I lex.backtrack.
+This is a list of scanner states which require backtracking
+and the input characters on which they do so.  By adding rules one
+can remove backtracking states.  If all backtracking states
+are eliminated and
+.B -f
+or
+.B -F
+is used, the generated scanner will run faster.
+.TP
+.B -c
+is a do-nothing, deprecated option included for POSIX compliance.
+.IP
+.B NOTE:
+in previous releases of
+.I flex
+.B -c
+specified table-compression options.  This functionality is
+now given by the
+.B -C
+flag.  To ease the the impact of this change, when
+.I flex
+encounters
+.B -c,
+it currently issues a warning message and assumes that
+.B -C
+was desired instead.  In the future this "promotion" of
+.B -c
+to
+.B -C
+will go away in the name of full POSIX compliance (unless
+the POSIX meaning is removed first).
+.TP
+.B -d
+makes the generated scanner run in
+.I debug
+mode.  Whenever a pattern is recognized and the global
+.B yy_flex_debug
+is non-zero (which is the default), the scanner will
+write to
+.I stderr
+a line of the form:
+.nf
+
+    --accepting rule at line 53 ("the matched text")
+
+.fi
+The line number refers to the location of the rule in the file
+defining the scanner (i.e., the file that was fed to flex).  Messages
+are also generated when the scanner backtracks, accepts the
+default rule, reaches the end of its input buffer (or encounters
+a NUL; the two look the same as far as the scanner's concerned),
+or reaches an end-of-file.
+.TP
+.B -f
+specifies (take your pick)
+.I full table
+or
+.I fast scanner.
+No table compression is done.  The result is large but fast.
+This option is equivalent to
+.B -Cf
+(see below).
+.TP
+.B -i
+instructs
+.I flex
+to generate a
+.I case-insensitive
+scanner.  The case of letters given in the
+.I flex
+input patterns will
+be ignored, and tokens in the input will be matched regardless of case.  The
+matched text given in
+.I yytext
+will have the preserved case (i.e., it will not be folded).
+.TP
+.B -n
+is another do-nothing, deprecated option included only for
+POSIX compliance.
+.TP
+.B -p
+generates a performance report to stderr.  The report
+consists of comments regarding features of the
+.I flex
+input file which will cause a loss of performance in the resulting scanner.
+.TP
+.B -s
+causes the
+.I default rule
+(that unmatched scanner input is echoed to
+.I stdout)
+to be suppressed.  If the scanner encounters input that does not
+match any of its rules, it aborts with an error.
+.TP
+.B -t
+instructs
+.I flex
+to write the scanner it generates to standard output instead
+of
+.B lex.yy.c.
+.TP
+.B -v
+specifies that
+.I flex
+should write to
+.I stderr
+a summary of statistics regarding the scanner it generates.
+.TP
+.B -F
+specifies that the
+.I fast
+scanner table representation should be used.  This representation is
+about as fast as the full table representation
+.RB ( \-f ),
+and for some sets of patterns will be considerably smaller (and for
+others, larger).  See
+.B flexdoc(1)
+for details.
+.IP
+This option is equivalent to
+.B -CF
+(see below).
+.TP
+.B -I
+instructs
+.I flex
+to generate an
+.I interactive
+scanner, that is, a scanner which stops immediately rather than
+looking ahead if it knows
+that the currently scanned text cannot be part of a longer rule's match.
+Again, see
+.B flexdoc(1)
+for details.
+.IP
+Note,
+.B -I
+cannot be used in conjunction with
+.I full
+or
+.I fast tables,
+i.e., the
+.B -f, -F, -Cf,
+or
+.B -CF
+flags.
+.TP
+.B -L
+instructs
+.I flex
+not to generate
+.B #line
+directives in
+.B lex.yy.c.
+The default is to generate such directives so error
+messages in the actions will be correctly
+located with respect to the original
+.I flex
+input file, and not to
+the fairly meaningless line numbers of
+.B lex.yy.c.
+.TP
+.B -T
+makes
+.I flex
+run in
+.I trace
+mode.  It will generate a lot of messages to
+.I stdout
+concerning
+the form of the input and the resultant non-deterministic and deterministic
+finite automata.  This option is mostly for use in maintaining
+.I flex.
+.TP
+.B -8
+instructs
+.I flex
+to generate an 8-bit scanner.
+On some sites, this is the default.  On others, the default
+is 7-bit characters.  To see which is the case, check the verbose
+.B (-v)
+output for "equivalence classes created".  If the denominator of
+the number shown is 128, then by default
+.I flex
+is generating 7-bit characters.  If it is 256, then the default is
+8-bit characters.
+.TP 
+.B -C[efmF]
+controls the degree of table compression.
+.IP
+.B -Ce
+directs
+.I flex
+to construct
+.I equivalence classes,
+i.e., sets of characters
+which have identical lexical properties.
+Equivalence classes usually give
+dramatic reductions in the final table/object file sizes (typically
+a factor of 2-5) and are pretty cheap performance-wise (one array
+look-up per character scanned).
+.IP
+.B -Cf
+specifies that the
+.I full
+scanner tables should be generated -
+.I flex
+should not compress the
+tables by taking advantages of similar transition functions for
+different states.
+.IP
+.B -CF
+specifies that the alternate fast scanner representation (described in
+.B flexdoc(1))
+should be used.
+.IP
+.B -Cm
+directs
+.I flex
+to construct
+.I meta-equivalence classes,
+which are sets of equivalence classes (or characters, if equivalence
+classes are not being used) that are commonly used together.  Meta-equivalence
+classes are often a big win when using compressed tables, but they
+have a moderate performance impact (one or two "if" tests and one
+array look-up per character scanned).
+.IP
+A lone
+.B -C
+specifies that the scanner tables should be compressed but neither
+equivalence classes nor meta-equivalence classes should be used.
+.IP
+The options
+.B -Cf
+or
+.B -CF
+and
+.B -Cm
+do not make sense together - there is no opportunity for meta-equivalence
+classes if the table is not being compressed.  Otherwise the options
+may be freely mixed.
+.IP
+The default setting is
+.B -Cem,
+which specifies that
+.I flex
+should generate equivalence classes
+and meta-equivalence classes.  This setting provides the highest
+degree of table compression.  You can trade off
+faster-executing scanners at the cost of larger tables with
+the following generally being true:
+.nf
+
+    slowest & smallest
+          -Cem
+          -Cm
+          -Ce
+          -C
+          -C{f,F}e
+          -C{f,F}
+    fastest & largest
+
+.fi
+.IP
+.B -C
+options are not cumulative; whenever the flag is encountered, the
+previous -C settings are forgotten.
+.TP
+.B -Sskeleton_file
+overrides the default skeleton file from which
+.I flex
+constructs its scanners.  You'll never need this option unless you are doing
+.I flex
+maintenance or development.
+.SH SUMMARY OF FLEX REGULAR EXPRESSIONS
+The patterns in the input are written using an extended set of regular
+expressions.  These are:
+.nf
+
+    x          match the character 'x'
+    .          any character except newline
+    [xyz]      a "character class"; in this case, the pattern
+                 matches either an 'x', a 'y', or a 'z'
+    [abj-oZ]   a "character class" with a range in it; matches
+                 an 'a', a 'b', any letter from 'j' through 'o',
+                 or a 'Z'
+    [^A-Z]     a "negated character class", i.e., any character
+                 but those in the class.  In this case, any
+                 character EXCEPT an uppercase letter.
+    [^A-Z\\n]   any character EXCEPT an uppercase letter or
+                 a newline
+    r*         zero or more r's, where r is any regular expression
+    r+         one or more r's
+    r?         zero or one r's (that is, "an optional r")
+    r{2,5}     anywhere from two to five r's
+    r{2,}      two or more r's
+    r{4}       exactly 4 r's
+    {name}     the expansion of the "name" definition
+               (see above)
+    "[xyz]\\"foo"
+               the literal string: [xyz]"foo
+    \\X         if X is an 'a', 'b', 'f', 'n', 'r', 't', or 'v',
+                 then the ANSI-C interpretation of \\x.
+                 Otherwise, a literal 'X' (used to escape
+                 operators such as '*')
+    \\123       the character with octal value 123
+    \\x2a       the character with hexadecimal value 2a
+    (r)        match an r; parentheses are used to override
+                 precedence (see below)
+
+
+    rs         the regular expression r followed by the
+                 regular expression s; called "concatenation"
+
+
+    r|s        either an r or an s
+
+
+    r/s        an r but only if it is followed by an s.  The
+                 s is not part of the matched text.  This type
+                 of pattern is called as "trailing context".
+    ^r         an r, but only at the beginning of a line
+    r$         an r, but only at the end of a line.  Equivalent
+                 to "r/\\n".
+
+
+    <s>r       an r, but only in start condition s (see
+               below for discussion of start conditions)
+    <s1,s2,s3>r
+               same, but in any of start conditions s1,
+               s2, or s3
+
+
+    <<EOF>>    an end-of-file
+    <s1,s2><<EOF>>
+               an end-of-file when in start condition s1 or s2
+
+.fi
+The regular expressions listed above are grouped according to
+precedence, from highest precedence at the top to lowest at the bottom.
+Those grouped together have equal precedence.
+.LP
+Some notes on patterns:
+.IP -
+Negated character classes
+.I match newlines
+unless "\\n" (or an equivalent escape sequence) is one of the
+characters explicitly present in the negated character class
+(e.g., "[^A-Z\\n]").
+.IP -
+A rule can have at most one instance of trailing context (the '/' operator
+or the '$' operator).  The start condition, '^', and "<<EOF>>" patterns
+can only occur at the beginning of a pattern, and, as well as with '/' and '$',
+cannot be grouped inside parentheses.  The following are all illegal:
+.nf
+
+    foo/bar$
+    foo|(bar$)
+    foo|^bar
+    <sc1>foo<sc2>bar
+
+.fi
+.SH SUMMARY OF SPECIAL ACTIONS
+In addition to arbitrary C code, the following can appear in actions:
+.IP -
+.B ECHO
+copies yytext to the scanner's output.
+.IP -
+.B BEGIN
+followed by the name of a start condition places the scanner in the
+corresponding start condition.
+.IP -
+.B REJECT
+directs the scanner to proceed on to the "second best" rule which matched the
+input (or a prefix of the input).
+.B yytext
+and
+.B yyleng
+are set up appropriately.  Note that
+.B REJECT
+is a particularly expensive feature in terms scanner performance;
+if it is used in
+.I any
+of the scanner's actions it will slow down
+.I all
+of the scanner's matching.  Furthermore,
+.B REJECT
+cannot be used with the
+.I -f
+or
+.I -F
+options.
+.IP
+Note also that unlike the other special actions,
+.B REJECT
+is a
+.I branch;
+code immediately following it in the action will
+.I not
+be executed.
+.IP -
+.B yymore()
+tells the scanner that the next time it matches a rule, the corresponding
+token should be
+.I appended
+onto the current value of
+.B yytext
+rather than replacing it.
+.IP -
+.B yyless(n)
+returns all but the first
+.I n
+characters of the current token back to the input stream, where they
+will be rescanned when the scanner looks for the next match.
+.B yytext
+and
+.B yyleng
+are adjusted appropriately (e.g.,
+.B yyleng
+will now be equal to
+.I n
+).
+.IP -
+.B unput(c)
+puts the character
+.I c
+back onto the input stream.  It will be the next character scanned.
+.IP -
+.B input()
+reads the next character from the input stream (this routine is called
+.B yyinput()
+if the scanner is compiled using
+.B C++).
+.IP -
+.B yyterminate()
+can be used in lieu of a return statement in an action.  It terminates
+the scanner and returns a 0 to the scanner's caller, indicating "all done".
+.IP
+By default,
+.B yyterminate()
+is also called when an end-of-file is encountered.  It is a macro and
+may be redefined.
+.IP -
+.B YY_NEW_FILE
+is an action available only in <<EOF>> rules.  It means "Okay, I've
+set up a new input file, continue scanning".
+.IP -
+.B yy_create_buffer( file, size )
+takes a
+.I FILE
+pointer and an integer
+.I size.
+It returns a YY_BUFFER_STATE
+handle to a new input buffer large enough to accomodate
+.I size
+characters and associated with the given file.  When in doubt, use
+.B YY_BUF_SIZE
+for the size.
+.IP -
+.B yy_switch_to_buffer( new_buffer )
+switches the scanner's processing to scan for tokens from
+the given buffer, which must be a YY_BUFFER_STATE.
+.IP -
+.B yy_delete_buffer( buffer )
+deletes the given buffer.
+.SH VALUES AVAILABLE TO THE USER
+.IP -
+.B char *yytext
+holds the text of the current token.  It may not be modified.
+.IP -
+.B int yyleng
+holds the length of the current token.  It may not be modified.
+.IP -
+.B FILE *yyin
+is the file which by default
+.I flex
+reads from.  It may be redefined but doing so only makes sense before
+scanning begins.  Changing it in the middle of scanning will have
+unexpected results since
+.I flex
+buffers its input.  Once scanning terminates because an end-of-file
+has been seen,
+.B
+void yyrestart( FILE *new_file )
+may be called to point
+.I yyin
+at the new input file.
+.IP -
+.B FILE *yyout
+is the file to which
+.B ECHO
+actions are done.  It can be reassigned by the user.
+.IP -
+.B YY_CURRENT_BUFFER
+returns a
+.B YY_BUFFER_STATE
+handle to the current buffer.
+.SH MACROS THE USER CAN REDEFINE
+.IP -
+.B YY_DECL
+controls how the scanning routine is declared.
+By default, it is "int yylex()", or, if prototypes are being
+used, "int yylex(void)".  This definition may be changed by redefining
+the "YY_DECL" macro.  Note that
+if you give arguments to the scanning routine using a
+K&R-style/non-prototyped function declaration, you must terminate
+the definition with a semi-colon (;).
+.IP -
+The nature of how the scanner
+gets its input can be controlled by redefining the
+.B YY_INPUT
+macro.
+YY_INPUT's calling sequence is "YY_INPUT(buf,result,max_size)".  Its
+action is to place up to
+.I max_size
+characters in the character array
+.I buf
+and return in the integer variable
+.I result
+either the
+number of characters read or the constant YY_NULL (0 on Unix systems)
+to indicate EOF.  The default YY_INPUT reads from the
+global file-pointer "yyin".
+A sample redefinition of YY_INPUT (in the definitions
+section of the input file):
+.nf
+
+    %{
+    #undef YY_INPUT
+    #define YY_INPUT(buf,result,max_size) \\
+        { \\
+        int c = getchar(); \\
+        result = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \\
+        }
+    %}
+
+.fi
+.IP -
+When the scanner receives an end-of-file indication from YY_INPUT,
+it then checks the
+.B yywrap()
+function.  If
+.B yywrap()
+returns false (zero), then it is assumed that the
+function has gone ahead and set up
+.I yyin
+to point to another input file, and scanning continues.  If it returns
+true (non-zero), then the scanner terminates, returning 0 to its
+caller.
+.IP
+The default
+.B yywrap()
+always returns 1.  Presently, to redefine it you must first
+"#undef yywrap", as it is currently implemented as a macro.  It is
+likely that
+.B yywrap()
+will soon be defined to be a function rather than a macro.
+.IP -
+YY_USER_ACTION
+can be redefined to provide an action
+which is always executed prior to the matched rule's action.
+.IP -
+The macro
+.B YY_USER_INIT
+may be redefined to provide an action which is always executed before
+the first scan.
+.IP -
+In the generated scanner, the actions are all gathered in one large
+switch statement and separated using
+.B YY_BREAK,
+which may be redefined.  By default, it is simply a "break", to separate
+each rule's action from the following rule's.
+.SH FILES
+.TP
+.I flex.skel
+skeleton scanner.
+.TP
+.I lex.yy.c
+generated scanner (called
+.I lexyy.c
+on some systems).
+.TP
+.I lex.backtrack
+backtracking information for
+.B -b
+flag (called
+.I lex.bck
+on some systems).
+.TP
+.B -lfl
+library with which to link the scanners.
+.SH "SEE ALSO"
+.LP
+flexdoc(1), lex(1), yacc(1), sed(1), awk(9).
+.LP
+M. E. Lesk and E. Schmidt,
+.I LEX - Lexical Analyzer Generator
+.SH DIAGNOSTICS
+.I reject_used_but_not_detected undefined
+or
+.LP
+.I yymore_used_but_not_detected undefined -
+These errors can occur at compile time.  They indicate that the
+scanner uses
+.B REJECT
+or
+.B yymore()
+but that
+.I flex
+failed to notice the fact, meaning that
+.I flex
+scanned the first two sections looking for occurrences of these actions
+and failed to find any, but somehow you snuck some in (via a #include
+file, for example).  Make an explicit reference to the action in your
+.I flex
+input file.  (Note that previously
+.I flex
+supported a
+.B %used/%unused
+mechanism for dealing with this problem; this feature is still supported
+but now deprecated, and will go away soon unless the author hears from
+people who can argue compellingly that they need it.)
+.LP
+.I flex scanner jammed -
+a scanner compiled with
+.B -s
+has encountered an input string which wasn't matched by
+any of its rules.
+.LP
+.I flex input buffer overflowed -
+a scanner rule matched a string long enough to overflow the
+scanner's internal input buffer (16K bytes - controlled by
+.B YY_BUF_MAX
+in "flex.skel").
+.LP
+.I scanner requires -8 flag -
+Your scanner specification includes recognizing 8-bit characters and
+you did not specify the -8 flag (and your site has not installed flex
+with -8 as the default).
+.LP
+.I
+fatal flex scanner internal error--end of buffer missed -
+This can occur in an scanner which is reentered after a long-jump
+has jumped out (or over) the scanner's activation frame.  Before
+reentering the scanner, use:
+.nf
+
+    yyrestart( yyin );
+
+.fi
+.LP
+.I too many %t classes! -
+You managed to put every single character into its own %t class.
+.I flex
+requires that at least one of the classes share characters.
+.SH AUTHOR
+Vern Paxson, with the help of many ideas and much inspiration from
+Van Jacobson.  Original version by Jef Poskanzer.
+.LP
+See flexdoc(1) for additional credits and the address to send comments to.
+.SH DEFICIENCIES / BUGS
+.LP
+Some trailing context
+patterns cannot be properly matched and generate
+warning messages ("Dangerous trailing context").  These are
+patterns where the ending of the
+first part of the rule matches the beginning of the second
+part, such as "zx*/xy*", where the 'x*' matches the 'x' at
+the beginning of the trailing context.  (Note that the POSIX draft
+states that the text matched by such patterns is undefined.)
+.LP
+For some trailing context rules, parts which are actually fixed-length are
+not recognized as such, leading to the abovementioned performance loss.
+In particular, parts using '|' or {n} (such as "foo{3}") are always
+considered variable-length.
+.LP
+Combining trailing context with the special '|' action can result in
+.I fixed
+trailing context being turned into the more expensive
+.I variable
+trailing context.  For example, this happens in the following example:
+.nf
+
+    %%
+    abc      |
+    xyz/def
+
+.fi
+.LP
+Use of unput() invalidates yytext and yyleng.
+.LP
+Use of unput() to push back more text than was matched can
+result in the pushed-back text matching a beginning-of-line ('^')
+rule even though it didn't come at the beginning of the line
+(though this is rare!).
+.LP
+Pattern-matching of NUL's is substantially slower than matching other
+characters.
+.LP
+.I flex
+does not generate correct #line directives for code internal
+to the scanner; thus, bugs in
+.I flex.skel
+yield bogus line numbers.
+.LP
+Due to both buffering of input and read-ahead, you cannot intermix
+calls to <stdio.h> routines, such as, for example,
+.B getchar(),
+with
+.I flex
+rules and expect it to work.  Call
+.B input()
+instead.
+.LP
+The total table entries listed by the
+.B -v
+flag excludes the number of table entries needed to determine
+what rule has been matched.  The number of entries is equal
+to the number of DFA states if the scanner does not use
+.B REJECT,
+and somewhat greater than the number of states if it does.
+.LP
+.B REJECT
+cannot be used with the
+.I -f
+or
+.I -F
+options.
+.LP
+Some of the macros, such as
+.B yywrap(),
+may in the future become functions which live in the
+.B -lfl
+library.  This will doubtless break a lot of code, but may be
+required for POSIX-compliance.
+.LP
+The
+.I flex
+internal algorithms need documentation.
+.\" ref. to awk(9) man page corrected -- ASW 2005-01-15
Index: /trunk/minix/man/man1/flexdoc.1
===================================================================
--- /trunk/minix/man/man1/flexdoc.1	(revision 9)
+++ /trunk/minix/man/man1/flexdoc.1	(revision 9)
@@ -0,0 +1,2442 @@
+.TH FLEX 1 "26 May 1990" "Version 2.3"
+.SH NAME
+flexdoc - fast lexical analyzer generator
+.SH SYNOPSIS
+.B flex
+.B [-bcdfinpstvFILT8 -C[efmF] -Sskeleton]
+.I [filename ...]
+.SH DESCRIPTION
+.I flex
+is a tool for generating
+.I scanners:
+programs which recognized lexical patterns in text.
+.I flex
+reads
+the given input files, or its standard input if no file names are given,
+for a description of a scanner to generate.  The description is in
+the form of pairs
+of regular expressions and C code, called
+.I rules.  flex
+generates as output a C source file,
+.B lex.yy.c,
+which defines a routine
+.B yylex().
+This file is compiled and linked with the
+.B -lfl
+library to produce an executable.  When the executable is run,
+it analyzes its input for occurrences
+of the regular expressions.  Whenever it finds one, it executes
+the corresponding C code.
+.SH SOME SIMPLE EXAMPLES
+.LP
+First some simple examples to get the flavor of how one uses
+.I flex.
+The following
+.I flex
+input specifies a scanner which whenever it encounters the string
+"username" will replace it with the user's login name:
+.nf
+
+    %%
+    username    printf( "%s", getlogin() );
+
+.fi
+By default, any text not matched by a
+.I flex
+scanner
+is copied to the output, so the net effect of this scanner is
+to copy its input file to its output with each occurrence
+of "username" expanded.
+In this input, there is just one rule.  "username" is the
+.I pattern
+and the "printf" is the
+.I action.
+The "%%" marks the beginning of the rules.
+.LP
+Here's another simple example:
+.nf
+
+        int num_lines = 0, num_chars = 0;
+
+    %%
+    \\n    ++num_lines; ++num_chars;
+    .     ++num_chars;
+
+    %%
+    main()
+        {
+        yylex();
+        printf( "# of lines = %d, # of chars = %d\\n",
+                num_lines, num_chars );
+        }
+
+.fi
+This scanner counts the number of characters and the number
+of lines in its input (it produces no output other than the
+final report on the counts).  The first line
+declares two globals, "num_lines" and "num_chars", which are accessible
+both inside
+.B yylex()
+and in the
+.B main()
+routine declared after the second "%%".  There are two rules, one
+which matches a newline ("\\n") and increments both the line count and
+the character count, and one which matches any character other than
+a newline (indicated by the "." regular expression).
+.LP
+A somewhat more complicated example:
+.nf
+
+    /* scanner for a toy Pascal-like language */
+
+    %{
+    /* need this for the call to atof() below */
+    #include <math.h>
+    %}
+
+    DIGIT    [0-9]
+    ID       [a-z][a-z0-9]*
+
+    %%
+
+    {DIGIT}+    {
+                printf( "An integer: %s (%d)\\n", yytext,
+                        atoi( yytext ) );
+                }
+
+    {DIGIT}+"."{DIGIT}*        {
+                printf( "A float: %s (%g)\\n", yytext,
+                        atof( yytext ) );
+                }
+
+    if|then|begin|end|procedure|function        {
+                printf( "A keyword: %s\\n", yytext );
+                }
+
+    {ID}        printf( "An identifier: %s\\n", yytext );
+
+    "+"|"-"|"*"|"/"   printf( "An operator: %s\\n", yytext );
+
+    "{"[^}\\n]*"}"     /* eat up one-line comments */
+
+    [ \\t\\n]+          /* eat up whitespace */
+
+    .           printf( "Unrecognized character: %s\\n", yytext );
+
+    %%
+
+    main( argc, argv )
+    int argc;
+    char **argv;
+        {
+        ++argv, --argc;  /* skip over program name */
+        if ( argc > 0 )
+                yyin = fopen( argv[0], "r" );
+        else
+                yyin = stdin;
+        
+        yylex();
+        }
+
+.fi
+This is the beginnings of a simple scanner for a language like
+Pascal.  It identifies different types of
+.I tokens
+and reports on what it has seen.
+.LP
+The details of this example will be explained in the following
+sections.
+.SH FORMAT OF THE INPUT FILE
+The
+.I flex
+input file consists of three sections, separated by a line with just
+.B %%
+in it:
+.nf
+
+    definitions
+    %%
+    rules
+    %%
+    user code
+
+.fi
+The
+.I definitions
+section contains declarations of simple
+.I name
+definitions to simplify the scanner specification, and declarations of
+.I start conditions,
+which are explained in a later section.
+.LP
+Name definitions have the form:
+.nf
+
+    name definition
+
+.fi
+The "name" is a word beginning with a letter or an underscore ('_')
+followed by zero or more letters, digits, '_', or '-' (dash).
+The definition is taken to begin at the first non-white-space character
+following the name and continuing to the end of the line.
+The definition can subsequently be referred to using "{name}", which
+will expand to "(definition)".  For example,
+.nf
+
+    DIGIT    [0-9]
+    ID       [a-z][a-z0-9]*
+
+.fi
+defines "DIGIT" to be a regular expression which matches a
+single digit, and
+"ID" to be a regular expression which matches a letter
+followed by zero-or-more letters-or-digits.
+A subsequent reference to
+.nf
+
+    {DIGIT}+"."{DIGIT}*
+
+.fi
+is identical to
+.nf
+
+    ([0-9])+"."([0-9])*
+
+.fi
+and matches one-or-more digits followed by a '.' followed
+by zero-or-more digits.
+.LP
+The
+.I rules
+section of the
+.I flex
+input contains a series of rules of the form:
+.nf
+
+    pattern   action
+
+.fi
+where the pattern must be unindented and the action must begin
+on the same line.
+.LP
+See below for a further description of patterns and actions.
+.LP
+Finally, the user code section is simply copied to
+.B lex.yy.c
+verbatim.
+It is used for companion routines which call or are called
+by the scanner.  The presence of this section is optional;
+if it is missing, the second
+.B %%
+in the input file may be skipped, too.
+.LP
+In the definitions and rules sections, any
+.I indented
+text or text enclosed in
+.B %{
+and
+.B %}
+is copied verbatim to the output (with the %{}'s removed).
+The %{}'s must appear unindented on lines by themselves.
+.LP
+In the rules section,
+any indented or %{} text appearing before the
+first rule may be used to declare variables
+which are local to the scanning routine and (after the declarations)
+code which is to be executed whenever the scanning routine is entered.
+Other indented or %{} text in the rule section is still copied to the output,
+but its meaning is not well-defined and it may well cause compile-time
+errors (this feature is present for
+.I POSIX
+compliance; see below for other such features).
+.LP
+In the definitions section, an unindented comment (i.e., a line
+beginning with "/*") is also copied verbatim to the output up
+to the next "*/".  Also, any line in the definitions section
+beginning with '#' is ignored, though this style of comment is
+deprecated and may go away in the future.
+.SH PATTERNS
+The patterns in the input are written using an extended set of regular
+expressions.  These are:
+.nf
+
+    x          match the character 'x'
+    .          any character except newline
+    [xyz]      a "character class"; in this case, the pattern
+                 matches either an 'x', a 'y', or a 'z'
+    [abj-oZ]   a "character class" with a range in it; matches
+                 an 'a', a 'b', any letter from 'j' through 'o',
+                 or a 'Z'
+    [^A-Z]     a "negated character class", i.e., any character
+                 but those in the class.  In this case, any
+                 character EXCEPT an uppercase letter.
+    [^A-Z\\n]   any character EXCEPT an uppercase letter or
+                 a newline
+    r*         zero or more r's, where r is any regular expression
+    r+         one or more r's
+    r?         zero or one r's (that is, "an optional r")
+    r{2,5}     anywhere from two to five r's
+    r{2,}      two or more r's
+    r{4}       exactly 4 r's
+    {name}     the expansion of the "name" definition
+               (see above)
+    "[xyz]\\"foo"
+               the literal string: [xyz]"foo
+    \\X         if X is an 'a', 'b', 'f', 'n', 'r', 't', or 'v',
+                 then the ANSI-C interpretation of \\x.
+                 Otherwise, a literal 'X' (used to escape
+                 operators such as '*')
+    \\123       the character with octal value 123
+    \\x2a       the character with hexadecimal value 2a
+    (r)        match an r; parentheses are used to override
+                 precedence (see below)
+
+
+    rs         the regular expression r followed by the
+                 regular expression s; called "concatenation"
+
+
+    r|s        either an r or an s
+
+
+    r/s        an r but only if it is followed by an s.  The
+                 s is not part of the matched text.  This type
+                 of pattern is called as "trailing context".
+    ^r         an r, but only at the beginning of a line
+    r$         an r, but only at the end of a line.  Equivalent
+                 to "r/\\n".
+
+
+    <s>r       an r, but only in start condition s (see
+               below for discussion of start conditions)
+    <s1,s2,s3>r
+               same, but in any of start conditions s1,
+               s2, or s3
+
+
+    <<EOF>>    an end-of-file
+    <s1,s2><<EOF>>
+               an end-of-file when in start condition s1 or s2
+
+.fi
+The regular expressions listed above are grouped according to
+precedence, from highest precedence at the top to lowest at the bottom.
+Those grouped together have equal precedence.  For example,
+.nf
+
+    foo|bar*
+
+.fi
+is the same as
+.nf
+
+    (foo)|(ba(r*))
+
+.fi
+since the '*' operator has higher precedence than concatenation,
+and concatenation higher than alternation ('|').  This pattern
+therefore matches
+.I either
+the string "foo"
+.I or
+the string "ba" followed by zero-or-more r's.
+To match "foo" or zero-or-more "bar"'s, use:
+.nf
+
+    foo|(bar)*
+
+.fi
+and to match zero-or-more "foo"'s-or-"bar"'s:
+.nf
+
+    (foo|bar)*
+
+.fi
+.LP
+Some notes on patterns:
+.IP -
+A negated character class such as the example "[^A-Z]"
+above
+.I will match a newline
+unless "\\n" (or an equivalent escape sequence) is one of the
+characters explicitly present in the negated character class
+(e.g., "[^A-Z\\n]").  This is unlike how many other regular
+expression tools treat negated character classes, but unfortunately
+the inconsistency is historically entrenched.
+Matching newlines means that a pattern like [^"]* can match an entire
+input (overflowing the scanner's input buffer) unless there's another
+quote in the input.
+.IP -
+A rule can have at most one instance of trailing context (the '/' operator
+or the '$' operator).  The start condition, '^', and "<<EOF>>" patterns
+can only occur at the beginning of a pattern, and, as well as with '/' and '$',
+cannot be grouped inside parentheses.  A '^' which does not occur at
+the beginning of a rule or a '$' which does not occur at the end of
+a rule loses its special properties and is treated as a normal character.
+.IP
+The following are illegal:
+.nf
+
+    foo/bar$
+    <sc1>foo<sc2>bar
+
+.fi
+Note that the first of these, can be written "foo/bar\\n".
+.IP
+The following will result in '$' or '^' being treated as a normal character:
+.nf
+
+    foo|(bar$)
+    foo|^bar
+
+.fi
+If what's wanted is a "foo" or a bar-followed-by-a-newline, the following
+could be used (the special '|' action is explained below):
+.nf
+
+    foo      |
+    bar$     /* action goes here */
+
+.fi
+A similar trick will work for matching a foo or a
+bar-at-the-beginning-of-a-line.
+.SH HOW THE INPUT IS MATCHED
+When the generated scanner is run, it analyzes its input looking
+for strings which match any of its patterns.  If it finds more than
+one match, it takes the one matching the most text (for trailing
+context rules, this includes the length of the trailing part, even
+though it will then be returned to the input).  If it finds two
+or more matches of the same length, the
+rule listed first in the
+.I flex
+input file is chosen.
+.LP
+Once the match is determined, the text corresponding to the match
+(called the
+.I token)
+is made available in the global character pointer
+.B yytext,
+and its length in the global integer
+.B yyleng.
+The
+.I action
+corresponding to the matched pattern is then executed (a more
+detailed description of actions follows), and then the remaining
+input is scanned for another match.
+.LP
+If no match is found, then the
+.I default rule
+is executed: the next character in the input is considered matched and
+copied to the standard output.  Thus, the simplest legal
+.I flex
+input is:
+.nf
+
+    %%
+
+.fi
+which generates a scanner that simply copies its input (one character
+at a time) to its output.
+.SH ACTIONS
+Each pattern in a rule has a corresponding action, which can be any
+arbitrary C statement.  The pattern ends at the first non-escaped
+whitespace character; the remainder of the line is its action.  If the
+action is empty, then when the pattern is matched the input token
+is simply discarded.  For example, here is the specification for a program
+which deletes all occurrences of "zap me" from its input:
+.nf
+
+    %%
+    "zap me"
+
+.fi
+(It will copy all other characters in the input to the output since
+they will be matched by the default rule.)
+.LP
+Here is a program which compresses multiple blanks and tabs down to
+a single blank, and throws away whitespace found at the end of a line:
+.nf
+
+    %%
+    [ \\t]+        putchar( ' ' );
+    [ \\t]+$       /* ignore this token */
+
+.fi
+.LP
+If the action contains a '{', then the action spans till the balancing '}'
+is found, and the action may cross multiple lines.
+.I flex 
+knows about C strings and comments and won't be fooled by braces found
+within them, but also allows actions to begin with
+.B %{
+and will consider the action to be all the text up to the next
+.B %}
+(regardless of ordinary braces inside the action).
+.LP
+An action consisting solely of a vertical bar ('|') means "same as
+the action for the next rule."  See below for an illustration.
+.LP
+Actions can include arbitrary C code, including
+.B return
+statements to return a value to whatever routine called
+.B yylex().
+Each time
+.B yylex()
+is called it continues processing tokens from where it last left
+off until it either reaches
+the end of the file or executes a return.  Once it reaches an end-of-file,
+however, then any subsequent call to
+.B yylex()
+will simply immediately return, unless
+.B yyrestart()
+is first called (see below).
+.LP
+Actions are not allowed to modify yytext or yyleng.
+.LP
+There are a number of special directives which can be included within
+an action:
+.IP -
+.B ECHO
+copies yytext to the scanner's output.
+.IP -
+.B BEGIN
+followed by the name of a start condition places the scanner in the
+corresponding start condition (see below).
+.IP -
+.B REJECT
+directs the scanner to proceed on to the "second best" rule which matched the
+input (or a prefix of the input).  The rule is chosen as described
+above in "How the Input is Matched", and
+.B yytext
+and
+.B yyleng
+set up appropriately.
+It may either be one which matched as much text
+as the originally chosen rule but came later in the
+.I flex
+input file, or one which matched less text.
+For example, the following will both count the
+words in the input and call the routine special() whenever "frob" is seen:
+.nf
+
+            int word_count = 0;
+    %%
+
+    frob        special(); REJECT;
+    [^ \\t\\n]+   ++word_count;
+
+.fi
+Without the
+.B REJECT,
+any "frob"'s in the input would not be counted as words, since the
+scanner normally executes only one action per token.
+Multiple
+.B REJECT's
+are allowed, each one finding the next best choice to the currently
+active rule.  For example, when the following scanner scans the token
+"abcd", it will write "abcdabcaba" to the output:
+.nf
+
+    %%
+    a        |
+    ab       |
+    abc      |
+    abcd     ECHO; REJECT;
+    .|\\n     /* eat up any unmatched character */
+
+.fi
+(The first three rules share the fourth's action since they use
+the special '|' action.)
+.B REJECT
+is a particularly expensive feature in terms scanner performance;
+if it is used in
+.I any
+of the scanner's actions it will slow down
+.I all
+of the scanner's matching.  Furthermore,
+.B REJECT
+cannot be used with the
+.I -f
+or
+.I -F
+options (see below).
+.IP
+Note also that unlike the other special actions,
+.B REJECT
+is a
+.I branch;
+code immediately following it in the action will
+.I not
+be executed.
+.IP -
+.B yymore()
+tells the scanner that the next time it matches a rule, the corresponding
+token should be
+.I appended
+onto the current value of
+.B yytext
+rather than replacing it.  For example, given the input "mega-kludge"
+the following will write "mega-mega-kludge" to the output:
+.nf
+
+    %%
+    mega-    ECHO; yymore();
+    kludge   ECHO;
+
+.fi
+First "mega-" is matched and echoed to the output.  Then "kludge"
+is matched, but the previous "mega-" is still hanging around at the
+beginning of
+.B yytext
+so the
+.B ECHO
+for the "kludge" rule will actually write "mega-kludge".
+The presence of
+.B yymore()
+in the scanner's action entails a minor performance penalty in the
+scanner's matching speed.
+.IP -
+.B yyless(n)
+returns all but the first
+.I n
+characters of the current token back to the input stream, where they
+will be rescanned when the scanner looks for the next match.
+.B yytext
+and
+.B yyleng
+are adjusted appropriately (e.g.,
+.B yyleng
+will now be equal to
+.I n
+).  For example, on the input "foobar" the following will write out
+"foobarbar":
+.nf
+
+    %%
+    foobar    ECHO; yyless(3);
+    [a-z]+    ECHO;
+
+.fi
+An argument of 0 to
+.B yyless
+will cause the entire current input string to be scanned again.  Unless you've
+changed how the scanner will subsequently process its input (using
+.B BEGIN,
+for example), this will result in an endless loop.
+.IP -
+.B unput(c)
+puts the character
+.I c
+back onto the input stream.  It will be the next character scanned.
+The following action will take the current token and cause it
+to be rescanned enclosed in parentheses.
+.nf
+
+    {
+    int i;
+    unput( ')' );
+    for ( i = yyleng - 1; i >= 0; --i )
+        unput( yytext[i] );
+    unput( '(' );
+    }
+
+.fi
+Note that since each
+.B unput()
+puts the given character back at the
+.I beginning
+of the input stream, pushing back strings must be done back-to-front.
+.IP -
+.B input()
+reads the next character from the input stream.  For example,
+the following is one way to eat up C comments:
+.nf
+
+    %%
+    "/*"        {
+                register int c;
+
+                for ( ; ; )
+                    {
+                    while ( (c = input()) != '*' &&
+                            c != EOF )
+                        ;    /* eat up text of comment */
+
+                    if ( c == '*' )
+                        {
+                        while ( (c = input()) == '*' )
+                            ;
+                        if ( c == '/' )
+                            break;    /* found the end */
+                        }
+
+                    if ( c == EOF )
+                        {
+                        error( "EOF in comment" );
+                        break;
+                        }
+                    }
+                }
+
+.fi
+(Note that if the scanner is compiled using
+.B C++,
+then
+.B input()
+is instead referred to as
+.B yyinput(),
+in order to avoid a name clash with the
+.B C++
+stream by the name of
+.I input.)
+.IP -
+.B yyterminate()
+can be used in lieu of a return statement in an action.  It terminates
+the scanner and returns a 0 to the scanner's caller, indicating "all done".
+Subsequent calls to the scanner will immediately return unless preceded
+by a call to
+.B yyrestart()
+(see below).
+By default,
+.B yyterminate()
+is also called when an end-of-file is encountered.  It is a macro and
+may be redefined.
+.SH THE GENERATED SCANNER
+The output of
+.I flex
+is the file
+.B lex.yy.c,
+which contains the scanning routine
+.B yylex(),
+a number of tables used by it for matching tokens, and a number
+of auxiliary routines and macros.  By default,
+.B yylex()
+is declared as follows:
+.nf
+
+    int yylex()
+        {
+        ... various definitions and the actions in here ...
+        }
+
+.fi
+(If your environment supports function prototypes, then it will
+be "int yylex( void )".)  This definition may be changed by redefining
+the "YY_DECL" macro.  For example, you could use:
+.nf
+
+    #undef YY_DECL
+    #define YY_DECL float lexscan( a, b ) float a, b;
+
+.fi
+to give the scanning routine the name
+.I lexscan,
+returning a float, and taking two floats as arguments.  Note that
+if you give arguments to the scanning routine using a
+K&R-style/non-prototyped function declaration, you must terminate
+the definition with a semi-colon (;).
+.LP
+Whenever
+.B yylex()
+is called, it scans tokens from the global input file
+.I yyin
+(which defaults to stdin).  It continues until it either reaches
+an end-of-file (at which point it returns the value 0) or
+one of its actions executes a
+.I return
+statement.
+In the former case, when called again the scanner will immediately
+return unless
+.B yyrestart()
+is called to point
+.I yyin
+at the new input file.  (
+.B yyrestart()
+takes one argument, a
+.B FILE *
+pointer.)
+In the latter case (i.e., when an action
+executes a return), the scanner may then be called again and it
+will resume scanning where it left off.
+.LP
+By default (and for purposes of efficiency), the scanner uses
+block-reads rather than simple
+.I getc()
+calls to read characters from
+.I yyin.
+The nature of how it gets its input can be controlled by redefining the
+.B YY_INPUT
+macro.
+YY_INPUT's calling sequence is "YY_INPUT(buf,result,max_size)".  Its
+action is to place up to
+.I max_size
+characters in the character array
+.I buf
+and return in the integer variable
+.I result
+either the
+number of characters read or the constant YY_NULL (0 on Unix systems)
+to indicate EOF.  The default YY_INPUT reads from the
+global file-pointer "yyin".
+.LP
+A sample redefinition of YY_INPUT (in the definitions
+section of the input file):
+.nf
+
+    %{
+    #undef YY_INPUT
+    #define YY_INPUT(buf,result,max_size) \\
+        { \\
+        int c = getchar(); \\
+        result = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \\
+        }
+    %}
+
+.fi
+This definition will change the input processing to occur
+one character at a time.
+.LP
+You also can add in things like keeping track of the
+input line number this way; but don't expect your scanner to
+go very fast.
+.LP
+When the scanner receives an end-of-file indication from YY_INPUT,
+it then checks the
+.B yywrap()
+function.  If
+.B yywrap()
+returns false (zero), then it is assumed that the
+function has gone ahead and set up
+.I yyin
+to point to another input file, and scanning continues.  If it returns
+true (non-zero), then the scanner terminates, returning 0 to its
+caller.
+.LP
+The default
+.B yywrap()
+always returns 1.  Presently, to redefine it you must first
+"#undef yywrap", as it is currently implemented as a macro.  As indicated
+by the hedging in the previous sentence, it may be changed to
+a true function in the near future.
+.LP
+The scanner writes its
+.B ECHO
+output to the
+.I yyout
+global (default, stdout), which may be redefined by the user simply
+by assigning it to some other
+.B FILE
+pointer.
+.SH START CONDITIONS
+.I flex
+provides a mechanism for conditionally activating rules.  Any rule
+whose pattern is prefixed with "<sc>" will only be active when
+the scanner is in the start condition named "sc".  For example,
+.nf
+
+    <STRING>[^"]*        { /* eat up the string body ... */
+                ...
+                }
+
+.fi
+will be active only when the scanner is in the "STRING" start
+condition, and
+.nf
+
+    <INITIAL,STRING,QUOTE>\\.        { /* handle an escape ... */
+                ...
+                }
+
+.fi
+will be active only when the current start condition is
+either "INITIAL", "STRING", or "QUOTE".
+.LP
+Start conditions
+are declared in the definitions (first) section of the input
+using unindented lines beginning with either
+.B %s
+or
+.B %x
+followed by a list of names.
+The former declares
+.I inclusive
+start conditions, the latter
+.I exclusive
+start conditions.  A start condition is activated using the
+.B BEGIN
+action.  Until the next
+.B BEGIN
+action is executed, rules with the given start
+condition will be active and
+rules with other start conditions will be inactive.
+If the start condition is
+.I inclusive,
+then rules with no start conditions at all will also be active.
+If it is
+.I exclusive,
+then
+.I only
+rules qualified with the start condition will be active.
+A set of rules contingent on the same exclusive start condition
+describe a scanner which is independent of any of the other rules in the
+.I flex
+input.  Because of this,
+exclusive start conditions make it easy to specify "mini-scanners"
+which scan portions of the input that are syntactically different
+from the rest (e.g., comments).
+.LP
+If the distinction between inclusive and exclusive start conditions
+is still a little vague, here's a simple example illustrating the
+connection between the two.  The set of rules:
+.nf
+
+    %s example
+    %%
+    <example>foo           /* do something */
+
+.fi
+is equivalent to
+.nf
+
+    %x example
+    %%
+    <INITIAL,example>foo   /* do something */
+
+.fi
+.LP
+The default rule (to
+.B ECHO
+any unmatched character) remains active in start conditions.
+.LP
+.B BEGIN(0)
+returns to the original state where only the rules with
+no start conditions are active.  This state can also be
+referred to as the start-condition "INITIAL", so
+.B BEGIN(INITIAL)
+is equivalent to
+.B BEGIN(0).
+(The parentheses around the start condition name are not required but
+are considered good style.)
+.LP
+.B BEGIN
+actions can also be given as indented code at the beginning
+of the rules section.  For example, the following will cause
+the scanner to enter the "SPECIAL" start condition whenever
+.I yylex()
+is called and the global variable
+.I enter_special
+is true:
+.nf
+
+            int enter_special;
+
+    %x SPECIAL
+    %%
+            if ( enter_special )
+                BEGIN(SPECIAL);
+
+    <SPECIAL>blahblahblah
+    ...more rules follow...
+
+.fi
+.LP
+To illustrate the uses of start conditions,
+here is a scanner which provides two different interpretations
+of a string like "123.456".  By default it will treat it as
+as three tokens, the integer "123", a dot ('.'), and the integer "456".
+But if the string is preceded earlier in the line by the string
+"expect-floats"
+it will treat it as a single token, the floating-point number
+123.456:
+.nf
+
+    %{
+    #include <math.h>
+    %}
+    %s expect
+
+    %%
+    expect-floats        BEGIN(expect);
+
+    <expect>[0-9]+"."[0-9]+      {
+                printf( "found a float, = %f\\n",
+                        atof( yytext ) );
+                }
+    <expect>\\n           {
+                /* that's the end of the line, so
+                 * we need another "expect-number"
+                 * before we'll recognize any more
+                 * numbers
+                 */
+                BEGIN(INITIAL);
+                }
+
+    [0-9]+      {
+                printf( "found an integer, = %d\\n",
+                        atoi( yytext ) );
+                }
+
+    "."         printf( "found a dot\\n" );
+
+.fi
+Here is a scanner which recognizes (and discards) C comments while
+maintaining a count of the current input line.
+.nf
+
+    %x comment
+    %%
+            int line_num = 1;
+
+    "/*"         BEGIN(comment);
+
+    <comment>[^*\\n]*        /* eat anything that's not a '*' */
+    <comment>"*"+[^*/\\n]*   /* eat up '*'s not followed by '/'s */
+    <comment>\\n             ++line_num;
+    <comment>"*"+"/"        BEGIN(INITIAL);
+
+.fi
+Note that start-conditions names are really integer values and
+can be stored as such.  Thus, the above could be extended in the
+following fashion:
+.nf
+
+    %x comment foo
+    %%
+            int line_num = 1;
+            int comment_caller;
+
+    "/*"         {
+                 comment_caller = INITIAL;
+                 BEGIN(comment);
+                 }
+
+    ...
+
+    <foo>"/*"    {
+                 comment_caller = foo;
+                 BEGIN(comment);
+                 }
+
+    <comment>[^*\\n]*        /* eat anything that's not a '*' */
+    <comment>"*"+[^*/\\n]*   /* eat up '*'s not followed by '/'s */
+    <comment>\\n             ++line_num;
+    <comment>"*"+"/"        BEGIN(comment_caller);
+
+.fi
+One can then implement a "stack" of start conditions using an
+array of integers.  (It is likely that such stacks will become
+a full-fledged
+.I flex
+feature in the future.)  Note, though, that
+start conditions do not have their own name-space; %s's and %x's
+declare names in the same fashion as #define's.
+.SH MULTIPLE INPUT BUFFERS
+Some scanners (such as those which support "include" files)
+require reading from several input streams.  As
+.I flex
+scanners do a large amount of buffering, one cannot control
+where the next input will be read from by simply writing a
+.B YY_INPUT
+which is sensitive to the scanning context.
+.B YY_INPUT
+is only called when the scanner reaches the end of its buffer, which
+may be a long time after scanning a statement such as an "include"
+which requires switching the input source.
+.LP
+To negotiate these sorts of problems,
+.I flex
+provides a mechanism for creating and switching between multiple
+input buffers.  An input buffer is created by using:
+.nf
+
+    YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+
+.fi
+which takes a
+.I FILE
+pointer and a size and creates a buffer associated with the given
+file and large enough to hold
+.I size
+characters (when in doubt, use
+.B YY_BUF_SIZE
+for the size).  It returns a
+.B YY_BUFFER_STATE
+handle, which may then be passed to other routines:
+.nf
+
+    void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+
+.fi
+switches the scanner's input buffer so subsequent tokens will
+come from
+.I new_buffer.
+Note that
+.B yy_switch_to_buffer()
+may be used by yywrap() to sets things up for continued scanning, instead
+of opening a new file and pointing
+.I yyin
+at it.
+.nf
+
+    void yy_delete_buffer( YY_BUFFER_STATE buffer )
+
+.fi
+is used to reclaim the storage associated with a buffer.
+.LP
+.B yy_new_buffer()
+is an alias for
+.B yy_create_buffer(),
+provided for compatibility with the C++ use of
+.I new
+and
+.I delete
+for creating and destroying dynamic objects.
+.LP
+Finally, the
+.B YY_CURRENT_BUFFER
+macro returns a
+.B YY_BUFFER_STATE
+handle to the current buffer.
+.LP
+Here is an example of using these features for writing a scanner
+which expands include files (the
+.B <<EOF>>
+feature is discussed below):
+.nf
+
+    /* the "incl" state is used for picking up the name
+     * of an include file
+     */
+    %x incl
+
+    %{
+    #define MAX_INCLUDE_DEPTH 10
+    YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
+    int include_stack_ptr = 0;
+    %}
+
+    %%
+    include             BEGIN(incl);
+
+    [a-z]+              ECHO;
+    [^a-z\\n]*\\n?        ECHO;
+
+    <incl>[ \\t]*      /* eat the whitespace */
+    <incl>[^ \\t\\n]+   { /* got the include file name */
+            if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
+                {
+                fprintf( stderr, "Includes nested too deeply" );
+                exit( 1 );
+                }
+
+            include_stack[include_stack_ptr++] =
+                YY_CURRENT_BUFFER;
+
+            yyin = fopen( yytext, "r" );
+
+            if ( ! yyin )
+                error( ... );
+
+            yy_switch_to_buffer(
+                yy_create_buffer( yyin, YY_BUF_SIZE ) );
+
+            BEGIN(INITIAL);
+            }
+
+    <<EOF>> {
+            if ( --include_stack_ptr < 0 )
+                {
+                yyterminate();
+                }
+
+            else
+                yy_switch_to_buffer(
+                     include_stack[include_stack_ptr] );
+            }
+
+.fi
+.SH END-OF-FILE RULES
+The special rule "<<EOF>>" indicates
+actions which are to be taken when an end-of-file is
+encountered and yywrap() returns non-zero (i.e., indicates
+no further files to process).  The action must finish
+by doing one of four things:
+.IP -
+the special
+.B YY_NEW_FILE
+action, if
+.I yyin
+has been pointed at a new file to process;
+.IP -
+a
+.I return
+statement;
+.IP -
+the special
+.B yyterminate()
+action;
+.IP -
+or, switching to a new buffer using
+.B yy_switch_to_buffer()
+as shown in the example above.
+.LP
+<<EOF>> rules may not be used with other
+patterns; they may only be qualified with a list of start
+conditions.  If an unqualified <<EOF>> rule is given, it
+applies to
+.I all
+start conditions which do not already have <<EOF>> actions.  To
+specify an <<EOF>> rule for only the initial start condition, use
+.nf
+
+    <INITIAL><<EOF>>
+
+.fi
+.LP
+These rules are useful for catching things like unclosed comments.
+An example:
+.nf
+
+    %x quote
+    %%
+
+    ...other rules for dealing with quotes...
+
+    <quote><<EOF>>   {
+             error( "unterminated quote" );
+             yyterminate();
+             }
+    <<EOF>>  {
+             if ( *++filelist )
+                 {
+                 yyin = fopen( *filelist, "r" );
+                 YY_NEW_FILE;
+                 }
+             else
+                yyterminate();
+             }
+
+.fi
+.SH MISCELLANEOUS MACROS
+The macro
+.B YY_USER_ACTION
+can be redefined to provide an action
+which is always executed prior to the matched rule's action.  For example,
+it could be #define'd to call a routine to convert yytext to lower-case.
+.LP
+The macro
+.B YY_USER_INIT
+may be redefined to provide an action which is always executed before
+the first scan (and before the scanner's internal initializations are done).
+For example, it could be used to call a routine to read
+in a data table or open a logging file.
+.LP
+In the generated scanner, the actions are all gathered in one large
+switch statement and separated using
+.B YY_BREAK,
+which may be redefined.  By default, it is simply a "break", to separate
+each rule's action from the following rule's.
+Redefining
+.B YY_BREAK
+allows, for example, C++ users to
+#define YY_BREAK to do nothing (while being very careful that every
+rule ends with a "break" or a "return"!) to avoid suffering from
+unreachable statement warnings where because a rule's action ends with
+"return", the
+.B YY_BREAK
+is inaccessible.
+.SH INTERFACING WITH YACC
+One of the main uses of
+.I flex
+is as a companion to the
+.I yacc
+parser-generator.
+.I yacc
+parsers expect to call a routine named
+.B yylex()
+to find the next input token.  The routine is supposed to
+return the type of the next token as well as putting any associated
+value in the global
+.B yylval.
+To use
+.I flex
+with
+.I yacc,
+one specifies the
+.B -d
+option to
+.I yacc
+to instruct it to generate the file
+.B y.tab.h
+containing definitions of all the
+.B %tokens
+appearing in the
+.I yacc
+input.  This file is then included in the
+.I flex
+scanner.  For example, if one of the tokens is "TOK_NUMBER",
+part of the scanner might look like:
+.nf
+
+    %{
+    #include "y.tab.h"
+    %}
+
+    %%
+
+    [0-9]+        yylval = atoi( yytext ); return TOK_NUMBER;
+
+.fi
+.SH TRANSLATION TABLE
+In the name of POSIX compliance,
+.I flex
+supports a
+.I translation table
+for mapping input characters into groups.
+The table is specified in the first section, and its format looks like:
+.nf
+
+    %t
+    1        abcd
+    2        ABCDEFGHIJKLMNOPQRSTUVWXYZ
+    52       0123456789
+    6        \\t\\ \\n
+    %t
+
+.fi
+This example specifies that the characters 'a', 'b', 'c', and 'd'
+are to all be lumped into group #1, upper-case letters
+in group #2, digits in group #52, tabs, blanks, and newlines into
+group #6, and
+.I
+no other characters will appear in the patterns.
+The group numbers are actually disregarded by
+.I flex;
+.B %t
+serves, though, to lump characters together.  Given the above
+table, for example, the pattern "a(AA)*5" is equivalent to "d(ZQ)*0".
+They both say, "match any character in group #1, followed by
+zero-or-more pairs of characters
+from group #2, followed by a character from group #52."  Thus
+.B %t
+provides a crude way for introducing equivalence classes into
+the scanner specification.
+.LP
+Note that the
+.B -i
+option (see below) coupled with the equivalence classes which
+.I flex
+automatically generates take care of virtually all the instances
+when one might consider using
+.B %t.
+But what the hell, it's there if you want it.
+.SH OPTIONS
+.I flex
+has the following options:
+.TP
+.B -b
+Generate backtracking information to
+.I lex.backtrack.
+This is a list of scanner states which require backtracking
+and the input characters on which they do so.  By adding rules one
+can remove backtracking states.  If all backtracking states
+are eliminated and
+.B -f
+or
+.B -F
+is used, the generated scanner will run faster (see the
+.B -p
+flag).  Only users who wish to squeeze every last cycle out of their
+scanners need worry about this option.  (See the section on PERFORMANCE
+CONSIDERATIONS below.)
+.TP
+.B -c
+is a do-nothing, deprecated option included for POSIX compliance.
+.IP
+.B NOTE:
+in previous releases of
+.I flex
+.B -c
+specified table-compression options.  This functionality is
+now given by the
+.B -C
+flag.  To ease the the impact of this change, when
+.I flex
+encounters
+.B -c,
+it currently issues a warning message and assumes that
+.B -C
+was desired instead.  In the future this "promotion" of
+.B -c
+to
+.B -C
+will go away in the name of full POSIX compliance (unless
+the POSIX meaning is removed first).
+.TP
+.B -d
+makes the generated scanner run in
+.I debug
+mode.  Whenever a pattern is recognized and the global
+.B yy_flex_debug
+is non-zero (which is the default),
+the scanner will write to
+.I stderr
+a line of the form:
+.nf
+
+    --accepting rule at line 53 ("the matched text")
+
+.fi
+The line number refers to the location of the rule in the file
+defining the scanner (i.e., the file that was fed to flex).  Messages
+are also generated when the scanner backtracks, accepts the
+default rule, reaches the end of its input buffer (or encounters
+a NUL; at this point, the two look the same as far as the scanner's concerned),
+or reaches an end-of-file.
+.TP
+.B -f
+specifies (take your pick)
+.I full table
+or
+.I fast scanner.
+No table compression is done.  The result is large but fast.
+This option is equivalent to
+.B -Cf
+(see below).
+.TP
+.B -i
+instructs
+.I flex
+to generate a
+.I case-insensitive
+scanner.  The case of letters given in the
+.I flex
+input patterns will
+be ignored, and tokens in the input will be matched regardless of case.  The
+matched text given in
+.I yytext
+will have the preserved case (i.e., it will not be folded).
+.TP
+.B -n
+is another do-nothing, deprecated option included only for
+POSIX compliance.
+.TP
+.B -p
+generates a performance report to stderr.  The report
+consists of comments regarding features of the
+.I flex
+input file which will cause a loss of performance in the resulting scanner.
+Note that the use of
+.I REJECT
+and variable trailing context (see the BUGS section in flex(1))
+entails a substantial performance penalty; use of
+.I yymore(),
+the
+.B ^
+operator,
+and the
+.B -I
+flag entail minor performance penalties.
+.TP
+.B -s
+causes the
+.I default rule
+(that unmatched scanner input is echoed to
+.I stdout)
+to be suppressed.  If the scanner encounters input that does not
+match any of its rules, it aborts with an error.  This option is
+useful for finding holes in a scanner's rule set.
+.TP
+.B -t
+instructs
+.I flex
+to write the scanner it generates to standard output instead
+of
+.B lex.yy.c.
+.TP
+.B -v
+specifies that
+.I flex
+should write to
+.I stderr
+a summary of statistics regarding the scanner it generates.
+Most of the statistics are meaningless to the casual
+.I flex
+user, but the
+first line identifies the version of
+.I flex,
+which is useful for figuring
+out where you stand with respect to patches and new releases,
+and the next two lines give the date when the scanner was created
+and a summary of the flags which were in effect.
+.TP
+.B -F
+specifies that the
+.I fast
+scanner table representation should be used.  This representation is
+about as fast as the full table representation
+.RB ( \-f ),
+and for some sets of patterns will be considerably smaller (and for
+others, larger).  In general, if the pattern set contains both "keywords"
+and a catch-all, "identifier" rule, such as in the set:
+.nf
+
+    "case"    return TOK_CASE;
+    "switch"  return TOK_SWITCH;
+    ...
+    "default" return TOK_DEFAULT;
+    [a-z]+    return TOK_ID;
+
+.fi
+then you're better off using the full table representation.  If only
+the "identifier" rule is present and you then use a hash table or some such
+to detect the keywords, you're better off using
+.BR \-F .
+.IP
+This option is equivalent to
+.B -CF
+(see below).
+.TP
+.B -I
+instructs
+.I flex
+to generate an
+.I interactive
+scanner.  Normally, scanners generated by
+.I flex
+always look ahead one
+character before deciding that a rule has been matched.  At the cost of
+some scanning overhead,
+.I flex
+will generate a scanner which only looks ahead
+when needed.  Such scanners are called
+.I interactive
+because if you want to write a scanner for an interactive system such as a
+command shell, you will probably want the user's input to be terminated
+with a newline, and without
+.B -I
+the user will have to type a character in addition to the newline in order
+to have the newline recognized.  This leads to dreadful interactive
+performance.
+.IP
+If all this seems to confusing, here's the general rule: if a human will
+be typing in input to your scanner, use
+.B -I,
+otherwise don't; if you don't care about squeezing the utmost performance
+from your scanner and you
+don't want to make any assumptions about the input to your scanner,
+use
+.B -I.
+.IP
+Note,
+.B -I
+cannot be used in conjunction with
+.I full
+or
+.I fast tables,
+i.e., the
+.B -f, -F, -Cf,
+or
+.B -CF
+flags.
+.TP
+.B -L
+instructs
+.I flex
+not to generate
+.B #line
+directives.  Without this option,
+.I flex
+peppers the generated scanner
+with #line directives so error messages in the actions will be correctly
+located with respect to the original
+.I flex
+input file, and not to
+the fairly meaningless line numbers of
+.B lex.yy.c.
+(Unfortunately
+.I flex
+does not presently generate the necessary directives
+to "retarget" the line numbers for those parts of
+.B lex.yy.c
+which it generated.  So if there is an error in the generated code,
+a meaningless line number is reported.)
+.TP
+.B -T
+makes
+.I flex
+run in
+.I trace
+mode.  It will generate a lot of messages to
+.I stdout
+concerning
+the form of the input and the resultant non-deterministic and deterministic
+finite automata.  This option is mostly for use in maintaining
+.I flex.
+.TP
+.B -8
+instructs
+.I flex
+to generate an 8-bit scanner, i.e., one which can recognize 8-bit
+characters.  On some sites,
+.I flex
+is installed with this option as the default.  On others, the default
+is 7-bit characters.  To see which is the case, check the verbose
+.B (-v)
+output for "equivalence classes created".  If the denominator of
+the number shown is 128, then by default
+.I flex
+is generating 7-bit characters.  If it is 256, then the default is
+8-bit characters and the
+.B -8
+flag is not required (but may be a good idea to keep the scanner
+specification portable).  Feeding a 7-bit scanner 8-bit characters
+will result in infinite loops, bus errors, or other such fireworks,
+so when in doubt, use the flag.  Note that if equivalence classes
+are used, 8-bit scanners take only slightly more table space than
+7-bit scanners (128 bytes, to be exact); if equivalence classes are
+not used, however, then the tables may grow up to twice their
+7-bit size.
+.TP 
+.B -C[efmF]
+controls the degree of table compression.
+.IP
+.B -Ce
+directs
+.I flex
+to construct
+.I equivalence classes,
+i.e., sets of characters
+which have identical lexical properties (for example, if the only
+appearance of digits in the
+.I flex
+input is in the character class
+"[0-9]" then the digits '0', '1', ..., '9' will all be put
+in the same equivalence class).  Equivalence classes usually give
+dramatic reductions in the final table/object file sizes (typically
+a factor of 2-5) and are pretty cheap performance-wise (one array
+look-up per character scanned).
+.IP
+.B -Cf
+specifies that the
+.I full
+scanner tables should be generated -
+.I flex
+should not compress the
+tables by taking advantages of similar transition functions for
+different states.
+.IP
+.B -CF
+specifies that the alternate fast scanner representation (described
+above under the
+.B -F
+flag)
+should be used.
+.IP
+.B -Cm
+directs
+.I flex
+to construct
+.I meta-equivalence classes,
+which are sets of equivalence classes (or characters, if equivalence
+classes are not being used) that are commonly used together.  Meta-equivalence
+classes are often a big win when using compressed tables, but they
+have a moderate performance impact (one or two "if" tests and one
+array look-up per character scanned).
+.IP
+A lone
+.B -C
+specifies that the scanner tables should be compressed but neither
+equivalence classes nor meta-equivalence classes should be used.
+.IP
+The options
+.B -Cf
+or
+.B -CF
+and
+.B -Cm
+do not make sense together - there is no opportunity for meta-equivalence
+classes if the table is not being compressed.  Otherwise the options
+may be freely mixed.
+.IP
+The default setting is
+.B -Cem,
+which specifies that
+.I flex
+should generate equivalence classes
+and meta-equivalence classes.  This setting provides the highest
+degree of table compression.  You can trade off
+faster-executing scanners at the cost of larger tables with
+the following generally being true:
+.nf
+
+    slowest & smallest
+          -Cem
+          -Cm
+          -Ce
+          -C
+          -C{f,F}e
+          -C{f,F}
+    fastest & largest
+
+.fi
+Note that scanners with the smallest tables are usually generated and
+compiled the quickest, so
+during development you will usually want to use the default, maximal
+compression.
+.IP
+.B -Cfe
+is often a good compromise between speed and size for production
+scanners.
+.IP
+.B -C
+options are not cumulative; whenever the flag is encountered, the
+previous -C settings are forgotten.
+.TP
+.B -Sskeleton_file
+overrides the default skeleton file from which
+.I flex
+constructs its scanners.  You'll never need this option unless you are doing
+.I flex
+maintenance or development.
+.SH PERFORMANCE CONSIDERATIONS
+The main design goal of
+.I flex
+is that it generate high-performance scanners.  It has been optimized
+for dealing well with large sets of rules.  Aside from the effects
+of table compression on scanner speed outlined above,
+there are a number of options/actions which degrade performance.  These
+are, from most expensive to least:
+.nf
+
+    REJECT
+
+    pattern sets that require backtracking
+    arbitrary trailing context
+
+    '^' beginning-of-line operator
+    yymore()
+
+.fi
+with the first three all being quite expensive and the last two
+being quite cheap.
+.LP
+.B REJECT
+should be avoided at all costs when performance is important.
+It is a particularly expensive option.
+.LP
+Getting rid of backtracking is messy and often may be an enormous
+amount of work for a complicated scanner.  In principal, one begins
+by using the
+.B -b 
+flag to generate a
+.I lex.backtrack
+file.  For example, on the input
+.nf
+
+    %%
+    foo        return TOK_KEYWORD;
+    foobar     return TOK_KEYWORD;
+
+.fi
+the file looks like:
+.nf
+
+    State #6 is non-accepting -
+     associated rule line numbers:
+           2       3
+     out-transitions: [ o ]
+     jam-transitions: EOF [ \\001-n  p-\\177 ]
+
+    State #8 is non-accepting -
+     associated rule line numbers:
+           3
+     out-transitions: [ a ]
+     jam-transitions: EOF [ \\001-`  b-\\177 ]
+
+    State #9 is non-accepting -
+     associated rule line numbers:
+           3
+     out-transitions: [ r ]
+     jam-transitions: EOF [ \\001-q  s-\\177 ]
+
+    Compressed tables always backtrack.
+
+.fi
+The first few lines tell us that there's a scanner state in
+which it can make a transition on an 'o' but not on any other
+character, and that in that state the currently scanned text does not match
+any rule.  The state occurs when trying to match the rules found
+at lines 2 and 3 in the input file.
+If the scanner is in that state and then reads
+something other than an 'o', it will have to backtrack to find
+a rule which is matched.  With
+a bit of headscratching one can see that this must be the
+state it's in when it has seen "fo".  When this has happened,
+if anything other than another 'o' is seen, the scanner will
+have to back up to simply match the 'f' (by the default rule).
+.LP
+The comment regarding State #8 indicates there's a problem
+when "foob" has been scanned.  Indeed, on any character other
+than a 'b', the scanner will have to back up to accept "foo".
+Similarly, the comment for State #9 concerns when "fooba" has
+been scanned.
+.LP
+The final comment reminds us that there's no point going to
+all the trouble of removing backtracking from the rules unless
+we're using
+.B -f
+or
+.B -F,
+since there's no performance gain doing so with compressed scanners.
+.LP
+The way to remove the backtracking is to add "error" rules:
+.nf
+
+    %%
+    foo         return TOK_KEYWORD;
+    foobar      return TOK_KEYWORD;
+
+    fooba       |
+    foob        |
+    fo          {
+                /* false alarm, not really a keyword */
+                return TOK_ID;
+                }
+
+.fi
+.LP
+Eliminating backtracking among a list of keywords can also be
+done using a "catch-all" rule:
+.nf
+
+    %%
+    foo         return TOK_KEYWORD;
+    foobar      return TOK_KEYWORD;
+
+    [a-z]+      return TOK_ID;
+
+.fi
+This is usually the best solution when appropriate.
+.LP
+Backtracking messages tend to cascade.
+With a complicated set of rules it's not uncommon to get hundreds
+of messages.  If one can decipher them, though, it often
+only takes a dozen or so rules to eliminate the backtracking (though
+it's easy to make a mistake and have an error rule accidentally match
+a valid token.  A possible future
+.I flex
+feature will be to automatically add rules to eliminate backtracking).
+.LP
+.I Variable
+trailing context (where both the leading and trailing parts do not have
+a fixed length) entails almost the same performance loss as
+.I REJECT
+(i.e., substantial).  So when possible a rule like:
+.nf
+
+    %%
+    mouse|rat/(cat|dog)   run();
+
+.fi
+is better written:
+.nf
+
+    %%
+    mouse/cat|dog         run();
+    rat/cat|dog           run();
+
+.fi
+or as
+.nf
+
+    %%
+    mouse|rat/cat         run();
+    mouse|rat/dog         run();
+
+.fi
+Note that here the special '|' action does
+.I not
+provide any savings, and can even make things worse (see
+.B BUGS
+in flex(1)).
+.LP
+Another area where the user can increase a scanner's performance
+(and one that's easier to implement) arises from the fact that
+the longer the tokens matched, the faster the scanner will run.
+This is because with long tokens the processing of most input
+characters takes place in the (short) inner scanning loop, and
+does not often have to go through the additional work of setting up
+the scanning environment (e.g.,
+.B yytext)
+for the action.  Recall the scanner for C comments:
+.nf
+
+    %x comment
+    %%
+            int line_num = 1;
+
+    "/*"         BEGIN(comment);
+
+    <comment>[^*\\n]*
+    <comment>"*"+[^*/\\n]*
+    <comment>\\n             ++line_num;
+    <comment>"*"+"/"        BEGIN(INITIAL);
+
+.fi
+This could be sped up by writing it as:
+.nf
+
+    %x comment
+    %%
+            int line_num = 1;
+
+    "/*"         BEGIN(comment);
+
+    <comment>[^*\\n]*
+    <comment>[^*\\n]*\\n      ++line_num;
+    <comment>"*"+[^*/\\n]*
+    <comment>"*"+[^*/\\n]*\\n ++line_num;
+    <comment>"*"+"/"        BEGIN(INITIAL);
+
+.fi
+Now instead of each newline requiring the processing of another
+action, recognizing the newlines is "distributed" over the other rules
+to keep the matched text as long as possible.  Note that
+.I adding
+rules does
+.I not
+slow down the scanner!  The speed of the scanner is independent
+of the number of rules or (modulo the considerations given at the
+beginning of this section) how complicated the rules are with
+regard to operators such as '*' and '|'.
+.LP
+A final example in speeding up a scanner: suppose you want to scan
+through a file containing identifiers and keywords, one per line
+and with no other extraneous characters, and recognize all the
+keywords.  A natural first approach is:
+.nf
+
+    %%
+    asm      |
+    auto     |
+    break    |
+    ... etc ...
+    volatile |
+    while    /* it's a keyword */
+
+    .|\\n     /* it's not a keyword */
+
+.fi
+To eliminate the back-tracking, introduce a catch-all rule:
+.nf
+
+    %%
+    asm      |
+    auto     |
+    break    |
+    ... etc ...
+    volatile |
+    while    /* it's a keyword */
+
+    [a-z]+   |
+    .|\\n     /* it's not a keyword */
+
+.fi
+Now, if it's guaranteed that there's exactly one word per line,
+then we can reduce the total number of matches by a half by
+merging in the recognition of newlines with that of the other
+tokens:
+.nf
+
+    %%
+    asm\\n    |
+    auto\\n   |
+    break\\n  |
+    ... etc ...
+    volatile\\n |
+    while\\n  /* it's a keyword */
+
+    [a-z]+\\n |
+    .|\\n     /* it's not a keyword */
+
+.fi
+One has to be careful here, as we have now reintroduced backtracking
+into the scanner.  In particular, while
+.I we
+know that there will never be any characters in the input stream
+other than letters or newlines,
+.I flex
+can't figure this out, and it will plan for possibly needing backtracking
+when it has scanned a token like "auto" and then the next character
+is something other than a newline or a letter.  Previously it would
+then just match the "auto" rule and be done, but now it has no "auto"
+rule, only a "auto\\n" rule.  To eliminate the possibility of backtracking,
+we could either duplicate all rules but without final newlines, or,
+since we never expect to encounter such an input and therefore don't
+how it's classified, we can introduce one more catch-all rule, this
+one which doesn't include a newline:
+.nf
+
+    %%
+    asm\\n    |
+    auto\\n   |
+    break\\n  |
+    ... etc ...
+    volatile\\n |
+    while\\n  /* it's a keyword */
+
+    [a-z]+\\n |
+    [a-z]+   |
+    .|\\n     /* it's not a keyword */
+
+.fi
+Compiled with
+.B -Cf,
+this is about as fast as one can get a
+.I flex 
+scanner to go for this particular problem.
+.LP
+A final note:
+.I flex
+is slow when matching NUL's, particularly when a token contains
+multiple NUL's.
+It's best to write rules which match
+.I short
+amounts of text if it's anticipated that the text will often include NUL's.
+.SH INCOMPATIBILITIES WITH LEX AND POSIX
+.I flex
+is a rewrite of the Unix
+.I lex
+tool (the two implementations do not share any code, though),
+with some extensions and incompatibilities, both of which
+are of concern to those who wish to write scanners acceptable
+to either implementation.  At present, the POSIX
+.I lex
+draft is
+very close to the original
+.I lex
+implementation, so some of these
+incompatibilities are also in conflict with the POSIX draft.  But
+the intent is that except as noted below,
+.I flex
+as it presently stands will
+ultimately be POSIX conformant (i.e., that those areas of conflict with
+the POSIX draft will be resolved in
+.I flex's
+favor).  Please bear in
+mind that all the comments which follow are with regard to the POSIX
+.I draft
+standard of Summer 1989, and not the final document (or subsequent
+drafts); they are included so
+.I flex
+users can be aware of the standardization issues and those areas where
+.I flex
+may in the near future undergo changes incompatible with
+its current definition.
+.LP
+.I flex
+is fully compatible with
+.I lex
+with the following exceptions:
+.IP -
+The undocumented
+.I lex
+scanner internal variable
+.B yylineno
+is not supported.  It is difficult to support this option efficiently,
+since it requires examining every character scanned and reexamining
+the characters when the scanner backs up.
+Things get more complicated when the end of buffer or file is reached or a
+NUL is scanned (since the scan must then be restarted with the proper line
+number count), or the user uses the yyless(), unput(), or REJECT actions,
+or the multiple input buffer functions.
+.IP
+The fix is to add rules which, upon seeing a newline, increment
+yylineno.  This is usually an easy process, though it can be a drag if some
+of the patterns can match multiple newlines along with other characters.
+.IP
+yylineno is not part of the POSIX draft.
+.IP -
+The
+.B input()
+routine is not redefinable, though it may be called to read characters
+following whatever has been matched by a rule.  If
+.B input()
+encounters an end-of-file the normal
+.B yywrap()
+processing is done.  A ``real'' end-of-file is returned by
+.B input()
+as
+.I EOF.
+.IP
+Input is instead controlled by redefining the
+.B YY_INPUT
+macro.
+.IP
+The
+.I flex
+restriction that
+.B input()
+cannot be redefined is in accordance with the POSIX draft, but
+.B YY_INPUT
+has not yet been accepted into the draft (and probably won't; it looks
+like the draft will simply not specify any way of controlling the
+scanner's input other than by making an initial assignment to
+.I yyin).
+.IP -
+.I flex
+scanners do not use stdio for input.  Because of this, when writing an
+interactive scanner one must explicitly call fflush() on the
+stream associated with the terminal after writing out a prompt.
+With
+.I lex
+such writes are automatically flushed since
+.I lex
+scanners use
+.B getchar()
+for their input.  Also, when writing interactive scanners with
+.I flex,
+the
+.B -I
+flag must be used.
+.IP -
+.I flex
+scanners are not as reentrant as
+.I lex
+scanners.  In particular, if you have an interactive scanner and
+an interrupt handler which long-jumps out of the scanner, and
+the scanner is subsequently called again, you may get the following
+message:
+.nf
+
+    fatal flex scanner internal error--end of buffer missed
+
+.fi
+To reenter the scanner, first use
+.nf
+
+    yyrestart( yyin );
+
+.fi
+.IP -
+.B output()
+is not supported.
+Output from the
+.B ECHO
+macro is done to the file-pointer
+.I yyout
+(default
+.I stdout).
+.IP
+The POSIX draft mentions that an
+.B output()
+routine exists but currently gives no details as to what it does.
+.IP -
+.I lex
+does not support exclusive start conditions (%x), though they
+are in the current POSIX draft.
+.IP -
+When definitions are expanded,
+.I flex
+encloses them in parentheses.
+With lex, the following:
+.nf
+
+    NAME    [A-Z][A-Z0-9]*
+    %%
+    foo{NAME}?      printf( "Found it\\n" );
+    %%
+
+.fi
+will not match the string "foo" because when the macro
+is expanded the rule is equivalent to "foo[A-Z][A-Z0-9]*?"
+and the precedence is such that the '?' is associated with
+"[A-Z0-9]*".  With
+.I flex,
+the rule will be expanded to
+"foo([A-Z][A-Z0-9]*)?" and so the string "foo" will match.
+Note that because of this, the
+.B ^, $, <s>, /,
+and
+.B <<EOF>>
+operators cannot be used in a
+.I flex
+definition.
+.IP
+The POSIX draft interpretation is the same as
+.I flex's.
+.IP -
+To specify a character class which matches anything but a left bracket (']'),
+in
+.I lex
+one can use "[^]]" but with
+.I flex
+one must use "[^\\]]".  The latter works with
+.I lex,
+too.
+.IP -
+The
+.I lex
+.B %r
+(generate a Ratfor scanner) option is not supported.  It is not part
+of the POSIX draft.
+.IP -
+If you are providing your own yywrap() routine, you must include a
+"#undef yywrap" in the definitions section (section 1).  Note that
+the "#undef" will have to be enclosed in %{}'s.
+.IP
+The POSIX draft
+specifies that yywrap() is a function and this is very unlikely to change; so
+.I flex users are warned
+that
+.B yywrap()
+is likely to be changed to a function in the near future.
+.IP -
+After a call to
+.B unput(),
+.I yytext
+and
+.I yyleng
+are undefined until the next token is matched.  This is not the case with
+.I lex
+or the present POSIX draft.
+.IP -
+The precedence of the
+.B {}
+(numeric range) operator is different.
+.I lex
+interprets "abc{1,3}" as "match one, two, or
+three occurrences of 'abc'", whereas
+.I flex
+interprets it as "match 'ab'
+followed by one, two, or three occurrences of 'c'".  The latter is
+in agreement with the current POSIX draft.
+.IP -
+The precedence of the
+.B ^
+operator is different.
+.I lex
+interprets "^foo|bar" as "match either 'foo' at the beginning of a line,
+or 'bar' anywhere", whereas
+.I flex
+interprets it as "match either 'foo' or 'bar' if they come at the beginning
+of a line".  The latter is in agreement with the current POSIX draft.
+.IP -
+To refer to yytext outside of the scanner source file,
+the correct definition with
+.I flex
+is "extern char *yytext" rather than "extern char yytext[]".
+This is contrary to the current POSIX draft but a point on which
+.I flex
+will not be changing, as the array representation entails a
+serious performance penalty.  It is hoped that the POSIX draft will
+be emended to support the
+.I flex
+variety of declaration (as this is a fairly painless change to
+require of
+.I lex
+users).
+.IP -
+.I yyin
+is
+.I initialized
+by
+.I lex
+to be
+.I stdin;
+.I flex,
+on the other hand,
+initializes
+.I yyin
+to NULL
+and then
+.I assigns
+it to
+.I stdin
+the first time the scanner is called, providing
+.I yyin
+has not already been assigned to a non-NULL value.  The difference is
+subtle, but the net effect is that with
+.I flex
+scanners,
+.I yyin
+does not have a valid value until the scanner has been called.
+.IP -
+The special table-size declarations such as
+.B %a
+supported by
+.I lex
+are not required by
+.I flex
+scanners;
+.I flex
+ignores them.
+.IP -
+The name
+.B FLEX_SCANNER
+is #define'd so scanners may be written for use with either
+.I flex
+or
+.I lex.
+.LP
+The following
+.I flex
+features are not included in
+.I lex
+or the POSIX draft standard:
+.nf
+
+    yyterminate()
+    <<EOF>>
+    YY_DECL
+    #line directives
+    %{}'s around actions
+    yyrestart()
+    comments beginning with '#' (deprecated)
+    multiple actions on a line
+
+.fi
+This last feature refers to the fact that with
+.I flex
+you can put multiple actions on the same line, separated with
+semi-colons, while with
+.I lex,
+the following
+.nf
+
+    foo    handle_foo(); ++num_foos_seen;
+
+.fi
+is (rather surprisingly) truncated to
+.nf
+
+    foo    handle_foo();
+
+.fi
+.I flex
+does not truncate the action.  Actions that are not enclosed in
+braces are simply terminated at the end of the line.
+.SH DIAGNOSTICS
+.I reject_used_but_not_detected undefined
+or
+.I yymore_used_but_not_detected undefined -
+These errors can occur at compile time.  They indicate that the
+scanner uses
+.B REJECT
+or
+.B yymore()
+but that
+.I flex
+failed to notice the fact, meaning that
+.I flex
+scanned the first two sections looking for occurrences of these actions
+and failed to find any, but somehow you snuck some in (via a #include
+file, for example).  Make an explicit reference to the action in your
+.I flex
+input file.  (Note that previously
+.I flex
+supported a
+.B %used/%unused
+mechanism for dealing with this problem; this feature is still supported
+but now deprecated, and will go away soon unless the author hears from
+people who can argue compellingly that they need it.)
+.LP
+.I flex scanner jammed -
+a scanner compiled with
+.B -s
+has encountered an input string which wasn't matched by
+any of its rules.
+.LP
+.I flex input buffer overflowed -
+a scanner rule matched a string long enough to overflow the
+scanner's internal input buffer (16K bytes by default - controlled by
+.B YY_BUF_SIZE
+in "flex.skel".  Note that to redefine this macro, you must first
+.B #undefine
+it).
+.LP
+.I scanner requires -8 flag -
+Your scanner specification includes recognizing 8-bit characters and
+you did not specify the -8 flag (and your site has not installed flex
+with -8 as the default).
+.LP
+.I
+fatal flex scanner internal error--end of buffer missed -
+This can occur in an scanner which is reentered after a long-jump
+has jumped out (or over) the scanner's activation frame.  Before
+reentering the scanner, use:
+.nf
+
+    yyrestart( yyin );
+
+.fi
+.LP
+.I too many %t classes! -
+You managed to put every single character into its own %t class.
+.I flex
+requires that at least one of the classes share characters.
+.SH DEFICIENCIES / BUGS
+See flex(1).
+.SH "SEE ALSO"
+.LP
+flex(1), lex(1), yacc(1), sed(1), awk(9).
+.LP
+M. E. Lesk and E. Schmidt,
+.I LEX - Lexical Analyzer Generator
+.SH AUTHOR
+Vern Paxson, with the help of many ideas and much inspiration from
+Van Jacobson.  Original version by Jef Poskanzer.  The fast table
+representation is a partial implementation of a design done by Van
+Jacobson.  The implementation was done by Kevin Gong and Vern Paxson.
+.LP
+Thanks to the many
+.I flex
+beta-testers, feedbackers, and contributors, especially Casey
+Leedom, benson@odi.com, Keith Bostic,
+Frederic Brehm, Nick Christopher, Jason Coughlin,
+Scott David Daniels, Leo Eskin,
+Chris Faylor, Eric Goldman, Eric
+Hughes, Jeffrey R. Jones, Kevin B. Kenny, Ronald Lamprecht,
+Greg Lee, Craig Leres, Mohamed el Lozy, Jim Meyering, Marc Nozell, Esmond Pitt,
+Jef Poskanzer, Jim Roskind,
+Dave Tallman, Frank Whaley, Ken Yap, and those whose names
+have slipped my marginal mail-archiving skills but whose contributions
+are appreciated all the same.
+.LP
+Thanks to Keith Bostic, John Gilmore, Craig Leres, Bob
+Mulcahy, Rich Salz, and Richard Stallman for help with various distribution
+headaches.
+.LP
+Thanks to Esmond Pitt and Earle Horton for 8-bit character support;
+to Benson Margulies and Fred
+Burke for C++ support; to Ove Ewerlid for the basics of support for
+NUL's; and to Eric Hughes for the basics of support for multiple buffers.
+.LP
+Work is being done on extending
+.I flex
+to generate scanners in which the
+state machine is directly represented in C code rather than tables.
+These scanners may well be substantially faster than those generated
+using -f or -F.  If you are working in this area and are interested
+in comparing notes and seeing whether redundant work can be avoided,
+contact Ove Ewerlid (ewerlid@mizar.DoCS.UU.SE).
+.LP
+This work was primarily done when I was at the Real Time Systems Group
+at the Lawrence Berkeley Laboratory in Berkeley, CA.  Many thanks to all there
+for the support I received.
+.LP
+Send comments to:
+.nf
+
+     Vern Paxson
+     Computer Science Department
+     4126 Upson Hall
+     Cornell University
+     Ithaca, NY 14853-7501
+
+     vern@cs.cornell.edu
+     decvax!cornell!vern
+
+.fi
+.\" ref. to awk(9) man page corrected -- ASW 2005-01-15
Index: /trunk/minix/man/man1/fmt.1
===================================================================
--- /trunk/minix/man/man1/fmt.1	(revision 9)
+++ /trunk/minix/man/man1/fmt.1	(revision 9)
@@ -0,0 +1,26 @@
+.TH FMT 1
+.SH NAME
+fmt - adjust line-length for paragraphs of text
+.SH SYNOPSIS
+\fBfmt\fP [\-\fIwidth\fP] [\fIfiles\fP]...
+.SH DESCRIPTION
+\fIfmt\fR is a simple text formatter.
+It inserts or deletes newlines, as necessary, to make all lines in a
+paragraph be approximately the same width.
+It preserves indentation and word spacing.
+.PP
+The default line width is 72 characters.
+You can override this with the \-\fIwidth\fR flag.
+If you don't name any files on the command line,
+then \fIfmt\fR will read from stdin.
+.PP
+It is typically used from within \fIvi\fR to adjust the line breaks
+in a single paragraph.
+To do this, move the cursor to the top of the paragraph,
+type "!}fmt", and
+hit <Return>.
+.SH AUTHOR
+.nf
+Steve Kirkendall
+kirkenda@cs.pdx.edu
+.fi
Index: /trunk/minix/man/man1/fold.1
===================================================================
--- /trunk/minix/man/man1/fold.1	(revision 9)
+++ /trunk/minix/man/man1/fold.1	(revision 9)
@@ -0,0 +1,29 @@
+.TH FOLD 1
+.SH NAME
+fold \- fold long lines
+.SH SYNOPSIS
+\fBfold\fR [\fB\-\fIn\fR]\fR [\fIfile\fR] ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-\fIn\fR" "How long should the output lines be"
+.SH EXAMPLES
+.EX "fold \-60" "Fold \fIstdin\fR to 60 characters"
+.EX "fold file" "Fold \fIfile\fP to 80 characters"
+.SH DESCRIPTION
+.PP
+\fIFold\fR takes copies its input from the named file (or \fIstdin\fR,
+if none is specified) to standard output.
+However, lines longer than the given maximum (default 80) are broken
+into multiple lines of the maximum length by inserting new line characters.
+.SH "SEE ALSO"
+.BR width (1).
Index: /trunk/minix/man/man1/format.1
===================================================================
--- /trunk/minix/man/man1/format.1	(revision 9)
+++ /trunk/minix/man/man1/format.1	(revision 9)
@@ -0,0 +1,67 @@
+.TH FORMAT 1
+.SH NAME
+format \- format a PC floppy diskette
+.SH SYNOPSIS
+.B format
+.RB [ \-v ]
+.I device
+.RI [ media-size
+.RI [ drive-size ]]
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Format
+allows a user with read-write permission to
+.I device
+to format a floppy.  Either one of the special floppy devices must be used,
+see
+.BR fd (4),
+or an automatic device may be used with the size of the floppy specified on
+the command line.  Two sizes must be given when formatting a low density
+diskette in a high density drive.  For example:
+.PP
+.RS
+.ft B
+.nf
+format /dev/at1
+format /dev/fd1 1200
+format /dev/fd1 360 1200
+.fi
+.ft P
+.RE
+.PP
+The first two commands format a 1.2M diskette, the last formats a 360k
+diskette in a 1.2M drive.  A 1.44M drive knows when it's dealing with a low
+density floppy, so all these commands format a 720k diskette:
+.PP
+.RS
+.ft B
+.nf
+format /dev/fd0 720
+format /dev/fd0 720 1440
+format /dev/ps0
+.fi
+.ft P
+.RE
+.PP
+No sizes may be specified when using a special floppy device, a size must be
+specified when using an automatic device.
+.SH OPTIONS
+.TP
+.B \-v
+Verify the process by reading each track after formatting it.  Formatting is
+normally blind, the controller has no idea whether it succeeds or not.  Use
+.B \-v
+on a new box of cheap diskettes, or on a diskette that may have gone bad.
+Verifying will increase formatting time by 50%.
+.SH "SEE ALSO"
+.BR mkfs (1),
+.BR fd (4).
+.SH DIAGNOSTICS
+Numbers will be printed on standard output to show that it is busy.  The
+locations of bad sectors are printed on standard error when verifying.  The
+exit code is zero unless there are too many bad spots.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/fortune.1
===================================================================
--- /trunk/minix/man/man1/fortune.1	(revision 9)
+++ /trunk/minix/man/man1/fortune.1	(revision 9)
@@ -0,0 +1,23 @@
+.TH FORTUNE 1
+.SH NAME
+fortune \- print a fortune
+.SH SYNOPSIS
+\fBfortune\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "fortune" "Print a fortune"
+.SH DESCRIPTION
+.PP
+\fIFortune\fR prints a fortune at random from the fortunes file,  
+\fI/usr/lib/fortune.dat\fR.  This file consists of pieces
+of text separated by a line containing only %%.
Index: /trunk/minix/man/man1/fsck.1
===================================================================
--- /trunk/minix/man/man1/fsck.1	(revision 9)
+++ /trunk/minix/man/man1/fsck.1	(revision 9)
@@ -0,0 +1,52 @@
+.TH FSCK 1
+.SH NAME
+fsck, fsck1 \- perform file system consistency check
+.SH SYNOPSIS
+\fBfsck\fR [\fB\-aclmrs\fR]\fR [\fIdevice\fR] ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-a" "Automatically repair inconsistencies"
+.FL "\-c" "Check and list only the specified i-nodes
+.FL "\-l" "List the files and directories in the filesytem
+.FL "\-r" "Prompt user for repairs if inconsistencies are found
+.FL "\-s" "List the superblock of the file system"
+.SH EXAMPLES
+.EX "fsck /dev/c0d0p3" "Check file system on \fI/dev/c0d0p3\fR"
+.EX "fsck \-a /dev/at0" "Automatically fix errors on \fI/dev/at0\fR"
+.EX "fsck \-l /dev/fd0" "List the contents of \fI/dev/fd0\fR"
+.EX "fsck \-c 2 3 /dev/c0d0p2" "Check and list \fI/dev/c0d0p2\fR i-nodes 2 & 3"
+.SH DESCRIPTION
+.PP
+\fIFsck\fR performs consistency checks on the file systems which reside 
+on the specified devices.
+\fIFsck1\fR is an alternate version for use on obsolete V1 file systems.
+When either the \fB\-a\fR or \fB\-r\fR flags are given, the file system
+will be repaired if errors are found.
+Before running \fIfsck\fR on a mounted file system, it must first be unmounted.
+Trying to repair a mounted file system is dangerous and should not be 
+attempted.
+.PP
+To repair the root file system (which cannot be unmounted), first 
+type CTRL-F9 at the console to kill any and all processes.  Log back in
+as \fBroot\fR, type \fIsync\fR to force any buffered changes to disk,
+run \fIfsck\fR on the root file system and immediately reboot the
+computer by typing \fIreboot\fR.
+.PP
+It is necessary to kill all processes before repairing the root file system
+to prevent them from modifying any disk blocks while \fIfsck\fR is running.
+This is only necessary for the root file system, any other file system can
+simply be unmounted before it is checked.
+.SH "SEE ALSO"
+.BR mkfs (1),
+.BR mount (1).
+.\" disk name refs corrected, i.e., old hd1 now c0d0p0 -- ASW 2005-01-15
Index: /trunk/minix/man/man1/grep.1
===================================================================
--- /trunk/minix/man/man1/grep.1	(revision 9)
+++ /trunk/minix/man/man1/grep.1	(revision 9)
@@ -0,0 +1,50 @@
+.TH GREP 1
+.SH NAME
+grep \- search a file for lines containing a given pattern
+.SH SYNOPSIS
+\fBgrep\fR [\fB\-elnsv\fR] \fIpattern\fR [\fIfile\fR] ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-e" "\fB\-e \fIpattern\fR is the same as \fIpattern\fP
+.FL "\-c" "Print a count of lines matched"
+.FL "\-i" "Ignore case"
+.FL "\-l" "Print file names, no lines"
+.FL "\-n" "Print line numbers"
+.FL "\-s" "Status only, no printed output"
+.FL "\-v" "Select lines that do not match"
+.SH EXAMPLES
+.EX "grep mouse file " "Find lines in \fIfile\fP containing \fImouse\fP"
+.EX "grep [0\-9] file" "Print lines containing a digit"
+.SH DESCRIPTION
+.PP
+.I Grep
+searches one or more files (by default, \fIstdin\fR) and selects out
+all the lines that match the pattern.
+All the regular expressions accepted by
+.I ed
+and
+.I mined 
+are allowed.
+In addition, + can be used instead of \(** to mean 1 or more occurrences,
+? can be used to mean 0 or 1 occurrences, and
+| can be used between two regular expressions to mean either
+one of them.
+Parentheses can be used for grouping.
+If a match is found, exit status 0 is returned.
+If no match is found, exit status 1 is returned.
+If an error is detected, exit status 2 is returned.
+.SH "SEE ALSO"
+.BR cgrep (1),
+.BR fgrep (1),
+.BR sed (1),
+.BR awk (9).
Index: /trunk/minix/man/man1/head.1
===================================================================
--- /trunk/minix/man/man1/head.1	(revision 9)
+++ /trunk/minix/man/man1/head.1	(revision 9)
@@ -0,0 +1,28 @@
+.TH HEAD 1
+.SH NAME
+head \- print the first few lines of a file
+.SH SYNOPSIS
+\fBhead\fR [\fB\-\fIn\fR]\fR [\fIfile\fR] ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-\fIn\fR" "How many lines to print"
+.SH EXAMPLES
+.EX "head \-6" "Print first 6 lines of \fIstdin\fR"
+.EX "head \-1 file1 file2" "Print first line of two files"
+.SH DESCRIPTION
+.PP
+The first few lines of one or more files are printed.
+The default count is 10 lines.
+The default file is \fIstdin\fR.
+.SH "SEE ALSO"
+.BR tail (1).
Index: /trunk/minix/man/man1/host.1
===================================================================
--- /trunk/minix/man/man1/host.1	(revision 9)
+++ /trunk/minix/man/man1/host.1	(revision 9)
@@ -0,0 +1,207 @@
+.\" ++Copyright++ 1993
+.\" -
+.\" Copyright (c) 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\" 
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\" 	This product includes software developed by the University of
+.\" 	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\" 
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\" -
+.\" Portions Copyright (c) 1993 by Digital Equipment Corporation.
+.\" 
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies, and that
+.\" the name of Digital Equipment Corporation not be used in advertising or
+.\" publicity pertaining to distribution of the document or software without
+.\" specific, written prior permission.
+.\" 
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+.\" WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+.\" CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+.\" SOFTWARE.
+.\" -
+.\" --Copyright--
+.\" $Id: host.1,v 1.1 2005/05/02 13:01:39 beng Exp $
+.TH HOST 1
+.SH NAME
+host \- look up host names using domain server
+.SH SYNOPSIS 
+host [-l] [-v] [-w] [-r] [-d] [-t querytype] [-a] host [ server ] 
+.SH DESCRIPTION 
+.I Host
+looks for information about Internet hosts.  It gets this information
+from a set of interconnected servers that are spread across the
+country.  By default, it simply converts between host names and
+Internet addresses.  However with the -t or -a options, it can be used
+to find all of the information about this host that is maintained
+by the domain server.
+.PP
+The arguments can be either host names or host numbers.  The program
+first attempts to interpret them as host numbers.  If this fails,
+it will treat them as host names.  A host number consists of
+first decimal numbers separated by dots, e.g. 128.6.4.194
+A host name
+consists of names separated by dots, e.g. topaz.rutgers.edu.  
+Unless the name ends in a dot, the local domain
+is automatically tacked on the end.  Thus a Rutgers user can say
+"host topaz", and it will actually look up "topaz.rutgers.edu".
+If this fails, the name is tried unchanged (in this case, "topaz").
+This same convention is used for mail and other network utilities.
+The actual suffix to tack on the end is obtained
+by looking at the results of a "hostname" call, and using everything
+starting at the first dot.  (See below for a description of
+how to customize the host name lookup.) 
+.PP
+The first argument is the host name you want to look up.
+If this is a number, an "inverse query" is done, i.e. the domain
+system looks in a separate set of databases used to convert numbers
+to names.
+.PP
+The second argument is optional.  It
+allows you to specify a particular server to query.  If you don't
+specify this argument, the default server (normally the local machine)
+is used.
+.PP
+If a name is specified, you may see output of three different kinds.
+Here is an example that shows all of them:
+.br
+   % host sun4
+.br
+   sun4.rutgers.edu is a nickname for ATHOS.RUTGERS.EDU
+.br
+   ATHOS.RUTGERS.EDU has address 128.6.5.46
+.br
+   ATHOS.RUTGERS.EDU has address 128.6.4.4
+.br
+   ATHOS.RUTGERS.EDU mail is handled by ARAMIS.RUTGERS.EDU
+.br
+The user has typed the command "host sun4".  The first line indicates
+that the name "sun4.rutgers.edu" is actually a nickname.  The official
+host name is "ATHOS.RUTGERS.EDU'.  The next two lines show the
+address.  If a system has more than one network interface, there
+will be a separate address for each.  The last line indicates
+that ATHOS.RUTGERS.EDU does not receive its own mail.  Mail for
+it is taken by ARAMIS.RUTGERS.EDU.  There may be more than one
+such line, since some systems have more than one other system
+that will handle mail for them.  Technically, every system that
+can receive mail is supposed to have an entry of this kind.  If
+the system receives its own mail, there should be an entry
+the mentions the system itself, for example
+"XXX mail is handled by XXX".  However many systems that receive
+their own mail do not bother to mention that fact.  If a system
+has a "mail is handled by" entry, but no address, this indicates
+that it is not really part of the Internet, but a system that is
+on the network will forward mail to it.  Systems on Usenet, Bitnet,
+and a number of other networks have entries of this kind.
+.PP
+There are a number of options that can be used before the
+host name.  Most of these options are meaningful only to the
+staff who have to maintain the domain database.
+.PP
+The option -w causes host to wait forever for a response.  Normally
+it will time out after around a minute.
+.PP
+The option -v causes printout to be in a "verbose" format.  This
+is the official domain master file format, which is documented 
+in the man page for "named".  Without this option, output still follows
+this format in general terms, but some attempt is made to make it
+more intelligible to normal users.  Without -v,
+"a", "mx", and "cname" records
+are written out as "has address", "mail is handled by", and
+"is a nickname for", and TTL and class fields are not shown.
+.PP
+The option -r causes recursion to be turned off in the request.
+This means that the name server will return only data it has in
+its own database.  It will not ask other servers for more 
+information.
+.PP
+The option -d turns on debugging.  Network transactions are shown
+in detail.
+.PP
+The option -t allows you to specify a particular type of information
+to be looked up.  The arguments are defined in the man page for
+"named".  Currently supported types are a, ns, md, mf, cname,
+soa, mb, mg, mr, null, wks, ptr, hinfo, minfo, mx, uinfo,
+uid, gid, unspec, and the wildcard, which may be written
+as either "any" or "*".  Types must be given in lower case.
+Note that the default is to look first for "a", and then "mx", except
+that if the verbose option is turned on, the default is only "a".
+.PP
+The option -a (for "all") is equivalent to "-v -t any".
+.PP
+The option -l causes a listing of a complete domain.  E.g.
+.br
+   host -l rutgers.edu
+.br
+will give a listing of all hosts in the rutgers.edu domain.  The -t
+option is used to filter what information is presented, as you 
+would expect.  The default is address information, which also
+include PTR and NS records.  The command
+.br
+   host -l -v -t any rutgers.edu
+.br
+will give a complete download of the zone data for rutgers.edu,
+in the official master file format.  (However the SOA record is
+listed twice, for arcane reasons.)  NOTE: -l is implemented by
+doing a complete zone transfer and then filtering out the information
+the you have asked for.  This command should be used only if it
+is absolutely necessary.
+.SH CUSTOMIZING HOST NAME LOOKUP
+In general, if the name supplied by the user does not
+have any dots in it, a default domain is appended to the end.
+This domain can be defined in /etc/resolv.conf, but is normally derived
+by taking the local hostname after its first dot.  The user can override
+this, and specify a different default domain, using the environment
+variable
+.IR LOCALDOMAIN .
+In addition, the user can supply his own abbreviations for host names.
+They should be in a file consisting of one line per abbreviation.
+Each line contains an abbreviation, a space, and then the full
+host name.  This file must be pointed to by an environment variable
+.IR HOSTALIASES ,
+which is the name of the file.
+.SH "See Also"
+named (8)
+.SH BUGS
+Unexpected effects can happen when you type a name that is not
+part of the local domain.  Please always keep in mind the
+fact that the local domain name is tacked onto the end of every
+name, unless it ends in a dot.  Only if this fails is the name
+used unchanged.
+.PP
+The -l option only tries the first name server listed for the
+domain that you have requested.  If this server is dead, you
+may need to specify a server manually. E.g. to get a listing
+of foo.edu, you could try "host -t ns foo.edu" to get a list
+of all the name servers for foo.edu, and then try "host -l foo.edu xxx"
+for all xxx on the list of name servers, until you find one that
+works.
Index: /trunk/minix/man/man1/hostaddr.1
===================================================================
--- /trunk/minix/man/man1/hostaddr.1	(revision 9)
+++ /trunk/minix/man/man1/hostaddr.1	(revision 9)
@@ -0,0 +1,43 @@
+.TH HOSTADDR 1
+.SH NAME
+hostaddr \- show ethernet address, IP address or hostname
+.SH SYNOPSIS
+.B hostaddr
+.RB [ \-eiah ]
+.RB [ \-E
+.IR eth-device ]
+.RB [ \-I
+.IR ip-device ]
+.SH DESCRIPTION
+Without any of the
+.B \-eia
+options,
+.B hostaddr
+shows the ethernet address, IP address and hostname of the local host on one
+line in the given order.  With options only the wanted fields are shown,
+still in the same order, not in option order.
+.SH OPTIONS
+.TP
+.B \-e
+Show the ethernet address.
+.TP
+.B \-i
+Show the IP address.
+.TP
+.B \-a
+Show the fully qualified hostname.  The IP address is shown if it
+can't be translated to a host name.  This usually indicates that the
+DNS reverse address translation tables are incomplete or that
+the name daemon couldn't be contacted.
+.TP
+.B \-h
+Set the hostname of the machine if the caller is the superuser.  (Used at
+boot time by the network initialization scripts.)
+.SH "SEE ALSO"
+.BR ifconfig (8),
+.BR dhcpd (8),
+.BR nonamed (8),
+.BR inet (8),
+.BR boot (8).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/id.1
===================================================================
--- /trunk/minix/man/man1/id.1	(revision 9)
+++ /trunk/minix/man/man1/id.1	(revision 9)
@@ -0,0 +1,29 @@
+.TH ID 1
+.SH NAME
+id \- print the uid and gid
+.SH SYNOPSIS
+\fBid\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "id" "Print the uid and gid"
+.SH DESCRIPTION
+.PP
+\fIId\fR prints the current uid and gid, both numerically and symbolically.
+If the effective uid and gid are different from the real ones, all of them
+are printed.
+.PP
+Under Minix-vmd the supplementary group IDs are also printed.
+.SH "SEE ALSO"
+.BR getuid (2),
+.BR getgid (2),
+.BR getgroups (2).
Index: /trunk/minix/man/man1/ifdef.1
===================================================================
--- /trunk/minix/man/man1/ifdef.1	(revision 9)
+++ /trunk/minix/man/man1/ifdef.1	(revision 9)
@@ -0,0 +1,44 @@
+.TH IFDEF 1
+.SH NAME
+ifdef \- remove #ifdefs from a file
+.SH SYNOPSIS
+\fBifdef \fR[\fB\-t\fR] [\fB\-d\fIsymbol\fR] [\fB\-D\fIsymbol\fR] [\fB\-U\fIsymbol\fR] [\fB\-I\fIsymbol\fR] [file]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-D" "Define symbol permanently"
+.FL "\-I" "Ignore symbol"
+.FL "\-U" "Undefine symbol permanently"
+.FL "\-d" "Define symbol. It may be #undef'ed later"
+.FL "\-t" "Produce a table of the symbols on \fIstdout\fR"
+.SH EXAMPLES
+.EX "ifdef \-DUNIX file.c >newfile.c" "Define \fIUNIX\fR"
+.EX "ifdef \-D_MINIX \-UDOS <x.c >y.c "Define \fI_MINIX\fR, undefine \fIDOS\fR"
+.SH DESCRIPTION
+.PP
+\fIIfdef\fR
+allows conditional code [ #ifdef ... #endif ]
+to be selectively removed from C files, but at the same time leaving
+all other C preprocessor commands intact such as #define, #include etc.
+Input to
+.I ifdef
+is either the file named as the last argument, or \fIstdin\fR if no file
+is named.
+Output goes to \fIstdout\fR.
+.PP
+Symbols may be defined with the \fB\-d\fR or \fB\-D\fR flags just like
+\fIcpp\fR, except that the latter option ignores subsequent \fI#undefs\fR.
+It is not permitted to give values to symbols.
+Similarly, \fB\-U\fR undefines a symbol and ignores subsequent 
+\fI#defines\fRs.
+Symbols defined with \fB\-I\fR are ignored; any \fI#ifdef\fR using an
+ignored symbol will be left intact.
Index: /trunk/minix/man/man1/install.1
===================================================================
--- /trunk/minix/man/man1/install.1	(revision 9)
+++ /trunk/minix/man/man1/install.1	(revision 9)
@@ -0,0 +1,177 @@
+.TH INSTALL 1
+.SH NAME
+install \- install files
+.SH SYNOPSIS
+.in +5
+.ti -5
+.B install
+.RB [ \-lcsz\fIN\fP "] [" \-o
+.IR owner ]
+.RB [ \-g
+.IR group ]
+.RB [ \-m
+.IR mode ]
+.RB [ \-S
+.IR stack ]
+.RI [ file1 ]
+.I file2
+.br
+.ti -5
+.B install
+.RB [ \-lcsz\fIN\fP "] [" \-o
+.IR owner ]
+.RB [ \-g
+.IR group ]
+.RB [ \-m
+.IR mode ]
+.RB [ \-S
+.IR stack ]
+.IR file " ... " dir
+.br
+.ti -5
+.B install \-d
+.RB [ \-o
+.IR owner ]
+.RB [ \-g
+.IR group ]
+.RB [ \-m
+.IR mode ]
+.I directory
+.in -5
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Install
+puts executables, manual pages, and library files in their proper place
+in the bin, man, and lib directories.  The first two forms of the
+command are like
+.BR cp (1)
+copying either one file to another or copying several files to a
+directory.  The "\fB\-d\fP" form is like
+.BR mkdir (1)
+with the
+.B \-p
+flag.
+.I File1
+may be omitted if neither
+.B \-l
+nor
+.B \-c
+is given to change the attributes of
+.IR file2 .
+.PP
+Attributes are always copied from the source file, use the options to change.
+Note that the source file's attributes are changed with the destination file
+if they are linked.  So copy the file if you change it in a way that makes
+it read-only.  You would otherwise not be able to compile a command again.
+.SH OPTIONS
+.TP
+.B \-l
+Link the destination to the source file instead of copying it.  This is done
+to either save space on a file system with both the source and the bin
+directories on it, or to install synonyms to a command.
+.TP
+.B \-c
+Copy the source file to its proper place.  This option is the default if
+.B \-l
+is not given.  With
+.BR \-l ,
+the file is copied if the link fails.
+.TP
+.B \-s
+Strip the destination file of its symbol table,
+.I if
+it is an executable, and
+.I if
+it is actually copied.  It has no effect on a link or a non-executable.
+.TP
+.B \-z
+Compress the executable using
+.BR compress (1)
+and prepend a header line that calls
+.BR zexec (1)
+to decompress and execute the binary.  This will on average save 40% disk
+space at the expense of a slower startup time.  Like
+.B \-s
+the file must be actually copied for the flag to have effect.
+.TP
+.BI \- N
+Use
+.BI "gzip \-" N
+to compress the binary.  You may see up to 60% space savings, but it will
+take much longer.
+.I N
+is a digit from 1 to 9 telling the compression effort, see
+.BR gzip (1).
+.TP
+.B \-d
+Make a directory, usually to install files in a separate directory in a
+library.  Intermediate directories in the path are created with the same
+attributes as the final directory.  Only the attributes of the final
+directory are set if the directory exists.
+.TP
+.BI \-o " owner"
+Set the owner of the target.  This only works if the invoker is the
+super-user, or if
+.B install
+is run setuid root and the invoker is a member of group zero.  If
+.B \-o
+is omitted then the ownership is copied from the source file, or set to
+the id of the invoker if a directory is made.
+.TP
+.BI \-g " group"
+Like
+.BR \-o ,
+but for the group ownership of the target.
+.TP
+.BI \-m " mode"
+.I Mode
+is an octal number that specifies the mode the target should get.  The
+default is the source file's mode with a
+.B chmod a+rX
+applied to it, or 755 for a new directory.  Implies
+.BR "\-o 0" ,
+or
+.BR "\-g 0"
+if a file is to be set-uid or set-gid and the invoker has permission to
+change ownership.  This trick allows a group 0 member to install third party
+software, even though it expects to be installed by root.
+.TP
+.BI \-S " stack"
+Sets the maximum amount of heap + stack that an executable may have when
+running.  The argument is a C-style decimal, octal or hexadecimal
+number, optionally followed by the multipliers
+.BR m ,
+.BR k ,
+.BR w ,
+and
+.B b
+for mega (1024*1024), kilo (1024), "word" (2 or 4), and byte (1).  Uppercase
+.B M
+is also accepted for those who know what S.I. means.  The compilers use
+.B \-S 32kw
+by default, that translates to 64kb for an 8086, and 128kb for other
+architectures.  This option is ignored on a non-executable.
+.SH "SEE ALSO"
+.BR ln (1),
+.BR cp (1),
+.BR strip (1),
+.BR compress (1),
+.BR gzip (1),
+.BR zexec (1),
+.BR chown (8),
+.BR chgrp (1),
+.BR chmod (1),
+.BR chmem (1),
+.BR mkdir (1).
+.SH BUGS
+Uppercase
+.BR K ,
+.BR W ,
+and
+.B B
+are also accepted for those who don't know what S.I. means.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/isodir.1
===================================================================
--- /trunk/minix/man/man1/isodir.1	(revision 9)
+++ /trunk/minix/man/man1/isodir.1	(revision 9)
@@ -0,0 +1,29 @@
+.TH ISODIR 1
+.SH NAME
+isodir \- list ISO9660 or High Sierra directories
+.SH SYNOPSIS
+\fBisodir\fP \-[\fBlr\fP] \fIinput_file\fP [\fIdir\fP]
+.SH DESCRIPTION
+\fBIsodir\fP reads directories on a file system in ISO9660 or High Sierra
+Group format (usually residing on cdrom) and lists their contents on
+standard output.  Directory names should contain slashes to separate
+components. The names \fBisodir\fP, \fBisoread\fP, and \fBisoinfo\fP are all
+links to the same program.  The program sees which function to perform by
+looking how it was called.
+.PP
+.IP \-l 
+Lists all info on files and directories (size, date, time)
+.IP \-r 
+Recursively descend and print subdirectories
+.IP \-B
+List the byte offset and size of a file or directory.  (Useful in scripts that
+want to operate on an ISO image file.  To add a MINIX 3 partition table, for
+instance.)
+.SH "BUGS"
+Only Interchange level-1 is supported. The Red Rock extensions and Interchange
+level-2 are not implemented.
+.SH "SEE ALSO"
+.BR isoread (1),
+.BR isoinfo (1).
+.SH AUTHOR
+Michel R. Prevenier (mrpreve@cs.vu.nl)
Index: /trunk/minix/man/man1/isoinfo.1
===================================================================
--- /trunk/minix/man/man1/isoinfo.1	(revision 9)
+++ /trunk/minix/man/man1/isoinfo.1	(revision 9)
@@ -0,0 +1,19 @@
+.TH ISOINFO 1
+.SH NAME
+isoinfo \- list an ISO9660 or High Sierra volume descriptor
+.SH SYNOPSIS
+\fBisoinfo\fP [\fIinput_file\fP] 
+.SH DESCRIPTION
+\fBIsoinfo\fP reads the volume descriptor from an ISO9660 or High Sierra
+Group file system (usually residing on cdrom) and lists its contents on
+standard output.  \fBisodir\fP, \fBisoread\fP, and \fBisoinfo\fP are all
+links to the same program.  The program sees which function to perform by
+looking how it was called.
+.SH "BUGS"
+Only Interchange level-1 is supported. The Red Rock extensions and Interchange
+level-2 are not implemented.
+.SH "SEE ALSO"
+.BR isodir (1),
+.BR isoread (1).
+.SH AUTHOR
+Michel R. Prevenier (mrpreve@cs.vu.nl)
Index: /trunk/minix/man/man1/isoread.1
===================================================================
--- /trunk/minix/man/man1/isoread.1	(revision 9)
+++ /trunk/minix/man/man1/isoread.1	(revision 9)
@@ -0,0 +1,27 @@
+.TH ISOREAD 1
+.SH NAME
+isoread \- read a file in ISO9660 or High Sierra format
+.SH SYNOPSIS
+\fBisoread\fP \-[\fBa\fP] [\fIinput_file\fP] \fIfile\fP
+.SH DESCRIPTION
+\fBIsoread\fP reads a file in ISO9660 or High Sierra Group format (usually
+residing on cdrom) and lists its contents on standard output.  The file path
+should contain slashes to separate components. The names \fBisodir\fP,
+\fBisoread\fP, and \fBisoinfo\fP are all links to the same program. The
+program sees which function to perform by looking how it was called.
+.PP
+.IP \-a 
+(ASCII) -- convert MS-DOS text files to UNIX-style text files by dropping
+the ^M at the end of each line.
+.IP \-B
+List the byte offset and size of a file.  (Useful in scripts that
+want to operate on an ISO image file.  To add a MINIX 3 partition table, for
+instance.)
+.SH "BUGS"
+Only Interchange level-1 is supported. The Red Rock extensions and Interchange 
+level-2 are not implemented. 
+.SH "SEE ALSO"
+.BR isodir (1),
+.BR isoinfo (1).
+.SH AUTHOR
+Michel R. Prevenier (mrpreve@cs.vu.nl)
Index: /trunk/minix/man/man1/join.1
===================================================================
--- /trunk/minix/man/man1/join.1	(revision 9)
+++ /trunk/minix/man/man1/join.1	(revision 9)
@@ -0,0 +1,119 @@
+.\"	@(#)join.1	6.1 (Berkeley) 4/29/85
+.\"
+.TH JOIN 1 "April 29, 1985"
+.AT 3
+.SH NAME
+join \- relational database operator
+.SH SYNOPSIS
+.B join
+.RB [ \-a\fIn ]
+.RB [ \-e
+.IR s ]
+.RB [ \-o
+.IR list ]
+.RB [ \-t\fIc ]
+file1 file2
+.SH DESCRIPTION
+.B Join
+forms, on the standard output,
+a join
+of the two relations specified by the lines of
+.I file1
+and
+.IR file2 .
+If
+.I file1
+is `\-', the standard input is used.
+.PP
+.I File1
+and 
+.I file2
+must be sorted in increasing ASCII collating
+sequence on the fields
+on which they are to be joined,
+normally the first in each line.
+.PP
+There is one line in the output 
+for each pair of lines in 
+.I file1 
+and 
+.I file2
+that have identical join fields.
+The output line normally consists of the common field,
+then the rest of the line from 
+.IR file1 ,
+then the rest of the line from
+.IR file2 .
+.PP
+Fields are normally separated by blank, tab or newline.
+In this case, multiple separators count as one, and
+leading separators are discarded.
+.PP
+These options are recognized:
+.TP
+.BI \-a n
+In addition to the normal output,
+produce a line for each unpairable line in file
+.IR n ,
+where
+.I n
+is 1 or 2.
+.TP
+.BI \-e " s"
+Replace empty output fields by string
+.IR s .
+.ig
+.TP
+.BI \-j "n m"
+Join on the
+.IR m th
+field of file
+.IR n .
+If
+.I n
+is missing, use the
+.IR m th
+field in each file.
+..
+.TP
+.BI \-o " list"
+Each output line comprises the fields specified in
+.IR list ,
+each element of which has the form
+.IR n . m ,
+where
+.I n
+is a file number and
+.I m
+is a field number.
+.PP
+.TP
+.BI \-t c
+Use character
+.I c
+as a separator (tab character).
+Every appearance of
+.I c
+in a line is significant.
+.SH "SEE ALSO"
+.BR sort (1),
+.BR comm (1),
+.BR awk (9).
+.SH BUGS
+With default field separation,
+the collating sequence is that of
+.BR "sort \-b" ;
+with
+.BR \-t ,
+the sequence is that of a plain sort.
+.PP
+The conventions of
+.BR join ,
+.BR sort ,
+.BR comm ,
+.BR uniq ,
+.BR look
+and
+.BR awk (9)
+are wildly incongruous.
+.\" ref. to awk(9) man page corrected -- ASW 2005-01-15
Index: /trunk/minix/man/man1/kill.1
===================================================================
--- /trunk/minix/man/man1/kill.1	(revision 9)
+++ /trunk/minix/man/man1/kill.1	(revision 9)
@@ -0,0 +1,35 @@
+.TH KILL 1
+.SH NAME
+kill \- send a signal to a process
+.SH SYNOPSIS
+\fBkill\fR [\fB\-\fIn\fR] \fIprocess\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-\fIn\fR" "Signal number to send"
+.FL "\-\fINAME\fR" "Named signal to send"
+.SH EXAMPLES
+.EX "kill 35" "Send signal 15 to process 35"
+.EX "kill \-9 40" "Send signal 9 to process 40"
+.EX "kill \-2 0" "Send signal 2 to whole terminal process group"
+.EX "kill \-HUP -123" "Send a hangup to process group 123"
+.SH DESCRIPTION
+.PP
+A signal is sent to a given process.
+By default signal 15 (SIGTERM) is sent.
+Process 0 means all the processes in the sender's process group.
+A process group can be signalled by the negative value of the process
+group ID.
+Signals may be numerical, or the name of the signal without \fBSIG\fP.
+.SH "SEE ALSO"
+.BR kill (2),
+.BR sigaction (2).
Index: /trunk/minix/man/man1/last.1
===================================================================
--- /trunk/minix/man/man1/last.1	(revision 9)
+++ /trunk/minix/man/man1/last.1	(revision 9)
@@ -0,0 +1,44 @@
+.TH LAST 1
+.SH NAME
+last, uptime \- display recent on-line session records, show uptime
+.SH SYNOPSIS
+\fBlast\fR [\fB\-f \fIfile\fR]\fR [\fB\-r\fR] [\fB\-\fIn\fR] [\fIname\fR] [\fItty\fR] ...\fR
+.br
+\fBuptime\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-f" "Use \fIfile\fR instead of /usr/adm/wtmp"
+.FL "\-r" "Search backwards only to last reboot"
+.FL "\-u" "Print uptime since last reboot"
+.FL "\-\fIn\fP" "Print a maximum of \fIn\fR lines"
+.SH EXAMPLES
+.EX "last reboot" "When was the system last rebooted?"
+.EX "last ast" "When was the last login for ast?"
+.EX "last \-10 tty00 tty01" "Display last 10 logins on tty00 or tty01"
+.EX "uptime" "Display uptime (likewise \fBlast \-u\fR)"
+.SH DESCRIPTION
+.PP
+.I Last
+Searches backward through the login administration file (default is
+\fI/usr/adm/wtmp\fR), printing information about previous logins and
+reboots.
+During a long search, the SIGQUIT signal (CTRL-\\) causes \fIlast\fR to 
+display how far back it has gone; it then continues. 
+.PP
+.IR Uptime ,
+an alias for
+.IR "last \-u" ,
+displays the time the system is running since the last reboot.
+.SH "SEE ALSO"
+.BR who (1),
+.BR utmp (5).
Index: /trunk/minix/man/man1/leave.1
===================================================================
--- /trunk/minix/man/man1/leave.1	(revision 9)
+++ /trunk/minix/man/man1/leave.1	(revision 9)
@@ -0,0 +1,26 @@
+.TH LEAVE 1
+.SH NAME
+leave \- warn when it is time to go home
+.SH SYNOPSIS
+\fBleave\fR [\fR [\fB+\fR] \fIhh\fR[\fB:\fR]\fImm\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "leave 1500" "Issue a warning at 2:55 p.m."
+.EX "leave 10:00" "Issue a warning at 9:55 a.m."
+.EX "leave + 30" "Issue a warning in 25 minutes"
+.SH DESCRIPTION
+.PP
+\fILeave\fR sets an alarm clock to a specified time and issues a warning
+5 minutes before, 1 minute before, and at the time to leave.
+It then keeps issuing warnings every minute for 10 minutes, then quits.
+If no time is provided, the program prompts for one.
Index: /trunk/minix/man/man1/loadfont.1
===================================================================
--- /trunk/minix/man/man1/loadfont.1	(revision 9)
+++ /trunk/minix/man/man1/loadfont.1	(revision 9)
@@ -0,0 +1,37 @@
+.TH LOADFONT 1
+.SH NAME
+loadfont \- load a font into the video card
+.SH SYNOPSIS
+\fBloadfont \fIfontfile\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "loadfont iso1.fnt" "Loads the ISO 8859-1 (Latin-1) font"
+.SH DESCRIPTION
+.PP
+.I Loadfont
+loads a custom font into the video card (EGA or VGA).  The font character
+size has to be 8x16 pixels and the font file must contain 256 characters for
+a total size of 4 kilobytes.
+.PP
+.I Loadfont
+together with
+.I loadkeys
+allow the console and keyboard to be customized to national conventions.
+.PP
+If it exists, the file
+.I /etc/font
+is loaded as a custom font by
+.B /usr/etc/rc
+at boot time.
+.SH "SEE ALSO"
+.BR console (4).
Index: /trunk/minix/man/man1/loadkeys.1
===================================================================
--- /trunk/minix/man/man1/loadkeys.1	(revision 9)
+++ /trunk/minix/man/man1/loadkeys.1	(revision 9)
@@ -0,0 +1,30 @@
+.TH LOADKEYS 1
+.SH NAME
+loadkeys \- load a keyboard map into the keyboard driver
+.SH SYNOPSIS
+\fBloadkeys \fImapfile\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "loadkeys spanish.map" "Load a map for a Spanish keyboard"
+.SH DESCRIPTION
+.PP
+.I Loadkeys
+changes the key number to character mapping.  This is necessary for national
+keyboards that have different symbols on the keys that the standard U.S.
+English keyboard.  The file
+.I /etc/keymap
+is the first thing loaded by
+.I /etc/rc
+at boot time if it exists.
+.SH "SEE ALSO"
+.BR console (4).
Index: /trunk/minix/man/man1/logger.1
===================================================================
--- /trunk/minix/man/man1/logger.1	(revision 9)
+++ /trunk/minix/man/man1/logger.1	(revision 9)
@@ -0,0 +1,101 @@
+.\" Copyright (c) 1983, 1990, 1993
+.\" The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" from:	@(#)logger.1	8.1 (Berkeley) 6/6/93
+.\" Modified for Minix porting by G. Falzoni <gfalzoni@inwind.it>
+.\" $Id: logger.1,v 1.1 2006/04/03 14:59:51 beng Exp $
+.\"
+.\" Local macros
+.de Xr
+.BR \\$1 (\\$2)\\$3
+..
+.de LB
+.TP \\$1
+\\fB\\$2\\fR
+\\$3
+..
+.de LI
+.TP \\$1
+\\fI\\$2\\fR
+\\$3
+..
+.de LR
+.TP \\$1
+\\fR\\$2\\fR
+\\$3
+..
+.\" end local macros
+.DD June 6, 1993
+.TH LOGGER 1 "Jan. 18, 2000"
+.\"	Os BSD 4.3
+.SH NAME
+logger \- make entries in the system log
+.SH SYNOPSIS
+logger
+.RB [ \-i ]
+.RB [ \-f " " file ]
+.RB [ \-p " " pri ]
+.RB [ \-t " " tag ]
+.B message ...
+.SH DESCRIPTION
+Logger provides a shell command interface to the
+.Xr syslog 3
+system log module.
+.PP
+The following options are available to control message formatting:
+.PP
+.LB 9 -i "Log the process id of the logger process with each line."
+.\" LB 9 -s "Log the message to standard error, as well as the system log."
+.LB 9 "-f file" "Log the specified file."
+.LB 9 "-p pri" "Enter the message with the specified priority.
+The priority may be specified numerically or as a `facility.level'
+pair.  For example, `\-p local3.info' logs the message(s) as
+.BR info rmational
+level in the
+.B local3
+facility.  The default is `user.notice'.
+.LB 9 "-t tag" "Mark every line in the log with the specified
+.BR tag  .
+.LB 9 message "Write the message to log.  If not specified, and the"
+.B \-f
+flag is not provided, standard input is logged.
+.PP
+The logger utility exits 0 on success, and >0 if an error occurs.
+.SH EXAMPLES
+.PP
+logger System rebooted
+.PP
+logger \-p local0.notice \-t HOSTIDM \-f /dev/idmc
+.SH SEE ALSO
+.Xr syslog 3 , 
+.Xr syslogd 8 .
+.SH STANDARDS
+The logger command is expected to be IEEE Std1003.2 (`POSIX') compatible.
Index: /trunk/minix/man/man1/login.1
===================================================================
--- /trunk/minix/man/man1/login.1	(revision 9)
+++ /trunk/minix/man/man1/login.1	(revision 9)
@@ -0,0 +1,28 @@
+.TH LOGIN 1
+.SH NAME
+login \- log into the computer
+.SH SYNOPSIS
+\fBlogin\fR [\fIuser\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "login ast" "Login as ast"
+.SH DESCRIPTION
+.PP
+\fILogin\fR allows a logged in user to login as someone else without first
+logging out.
+If a password is needed, \fIlogin\fR will prompt for it.
+.SH "SEE ALSO"
+.BR su (1),
+.BR init (8),
+.BR getty (8),
+.BR rlogin (1).
Index: /trunk/minix/man/man1/look.1
===================================================================
--- /trunk/minix/man/man1/look.1	(revision 9)
+++ /trunk/minix/man/man1/look.1	(revision 9)
@@ -0,0 +1,38 @@
+.TH LOOK 1
+.SH NAME
+look \- find lines in a sorted list
+.SH SYNOPSIS
+.B look
+.RB [ \-df ]
+.I string
+.RI [ file ]
+.SH DESCRIPTION
+.B Look
+consults a sorted file and prints all lines that begin with
+.IR string .
+It uses binary search.  The options
+.B \-d
+and
+.B \-f
+affect comparisons as in
+.BR sort (1).
+If no file is specified,
+.B /usr/lib/dict/words
+is assumed with collating sequence
+.BR \-df .
+.SH OPTIONS
+.TP 5
+.B \-d
+Dictionary order: compare letters, digits and whitespace.
+.TP 5
+.B \-f
+Fold. Upper case letters compare equal to lower case.
+.SH FILES
+.TP 25
+.B /usr/lib/dict/words
+Sorted list of English words.
+.SH "SEE ALSO"
+.BR sort (1),
+.BR spell (1).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/lp.1
===================================================================
--- /trunk/minix/man/man1/lp.1	(revision 9)
+++ /trunk/minix/man/man1/lp.1	(revision 9)
@@ -0,0 +1,59 @@
+.TH LP 1
+.SH NAME
+lp, lpd \- copy a file to the line printer
+.SH SYNOPSIS
+.B lp
+.RI [ file " ...]"
+.SH DESCRIPTION
+Each file argument to
+.B lp
+is send to the line printer to be printed.  Standard input is read and
+printed if there are no arguments.
+.B Lp
+executes
+.B /usr/lib/lpd
+with each file as input.
+.B Lpd
+puts the file in
+.B /usr/spool/lpd
+and starts printing the jobs on
+.B /dev/lp
+unless another
+.B lpd
+is already running.  If
+.B lpd
+finds any character in the input that it doesn't know how to handle then it
+will print the rest of the file without any special treatment.  This also
+means that no formfeed is sent after the file has been printed to force out
+the page.
+.B Lpd
+simply assumes that you know what you are doing.  (dumb, eh?)
+.PP
+Note: Don't do anything with a file until it is printed,
+.B lpd
+only makes a copy of a file in the spool directory when it is not world
+readable.  If it can be read then it is printed directly.
+.SH FILES
+.TP 20
+.BI /usr/spool/lpd/job XXXXX
+Information about a job.
+.TP
+.BI /usr/spool/lpd/tmp XXXXX
+Associated file to be printed.
+.TP
+.B /etc/termcap
+The 'lp' entry describes the printer by the "li#" and "co#" fields.  By
+default 66 lines (li#66), and 80 columns (co#80).
+.SH "SEE ALSO"
+.BR lp (4),
+.BR termcap (5),
+.BR termcap (7).
+.SH BUGS
+Not spooling a world readable file may not be such a smart idea.
+.PP
+A formfeed should be printed and the printer reset after a job full of escape
+codes, but this may cost paper.
+.PP
+No banner page.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/ls.1
===================================================================
--- /trunk/minix/man/man1/ls.1	(revision 9)
+++ /trunk/minix/man/man1/ls.1	(revision 9)
@@ -0,0 +1,164 @@
+.TH LS 1
+.SH NAME
+ls \- list the contents of a directory
+.SH SYNOPSIS
+\fBls\fP [\fB\-acdfghilpqrstu1ACDFLMRTX\fP] [\fIname\fP...]
+.SH DESCRIPTION
+For each file argument, list it.  For each directory argument, list its
+contents.  The current working directory is listed when no files are named.
+Information is printed multicolumn on terminals, single column if the output
+is redirected.  The options control what information is shown and how.
+.PP
+.B Ls
+has two sources other then the command line to draw options from, one is
+the environment variable
+.B LSOPTS
+that is scanned for option letters when the output of
+.B ls
+is displayed on a terminal.  The other is the name of
+.B ls
+itself.  If
+.B ls
+is linked to another name, then all the characters after the l are used as
+flags too, except that d, f, r, t and x are translated to D, F, R, T and X.
+Useful links are
+.BR ll ,
+.BR lf ,
+.B lm
+and
+.BR lx .
+.PP
+Files whose names start with a dot are by default not listed.
+.PP
+Note that standard MINIX 3 doesn't have symbolic links or sockets and
+.B \-u
+and
+.B \-c
+are no-ops on a V1 file system, since only modified times are stored in V1
+inodes.
+.SH OPTIONS
+.TP
+.B \-a
+All entries are listed, even
+.B .
+and
+.B ..
+.TP
+.B \-c
+Use inode changed time for sorting, listing or searching.
+.TP
+.B \-d
+Do not list contents of directories, but list the directory itself.
+.TP
+.B \-f
+Do not sort (should also be: treat a file as a directory, but that
+can't be implemented portably).
+.TP
+.B \-g
+Suppress the owner name on a long listing (implies
+.BR \-l ).
+.TP
+.B \-h
+Show file sizes in kilo, mega or gigabytes.
+.TP
+.B \-i
+I-node number printed in the first column.
+.TP
+.B \-l
+Long listing: mode, links, owner, group, size and time.
+.RB ( "ls \-lC"
+uses columns in a wide enough window!)
+.TP
+.B \-n
+Print numerical user and group id's.
+.TP
+.B \-p
+Mark directories with a '\fB/\fP'.
+.TP
+.B \-q
+Print nongraphic characters as '\fB?\fP' (default on terminals).
+.TP
+.B \-r
+Reverse the sort order.
+.TP
+.B \-s
+Give the size in kilobytes in the first
+.RB ( \-s )
+or second column
+.RB ( \-is ).
+.TP
+.B \-t
+Sort by time (modified time default), latest first.
+.TP
+.B \-u
+Use last accessed time for sorting, listing or searching.
+.TP
+.B \-1
+Print in one column.
+.TP
+.B \-A
+List all entries, but not
+.B .
+and
+.B ..
+(This is the default for privileged users.)
+.TP
+.B \-C
+Print multicolumn (default on terminals).
+.TP
+.B \-D
+Distinguish files by type, i.e. regular files together, directories
+together, etc.
+.TP
+.B \-F
+Mark directories with a '\fB/\fP', executables with a '\fB*\fP', \s-2UNIX\s+2
+domain sockets with a '\fB=\fP', named pipes with a '\fB|\fP' and symbolic
+links with a '\fB@\fP' behind the name.
+.TP
+.B \-L
+Print the file referenced by a symbolic link instead of the link.
+.TP
+.B \-M
+List mode before name (implies
+.BR \-C ).
+.TP
+.B \-R
+List directory trees recursively.
+.TP
+.B \-T
+Print file times in a long format, e.g. "Oct 24 21:37:41 1996".
+.TP
+.B \-X
+Print crunched mode and size before name (implies
+.BR \-C ).
+Only the rwx permissions that its caller has on the file are shown, but they
+are in upper case if the caller owns the file and has given the permission
+to the callers group or other users.  The size is listed in bytes (<= 5K),
+or rounded up kilo, mega or gigabytes.
+.SH "SEE ALSO"
+.BR du (1),
+.BR stat (1),
+.BR stat (2).
+.SH BUGS
+Having to type
+.B ls \-C
+when viewing files through
+.BR more (1).
+.PP
+Is only portable to systems with the same
+.B st_mode
+(see
+.BR stat (2)).
+.PP
+The
+.B LSOPTS
+variable and the
+.BR -D ,
+.B -M
+and
+.B -X
+flags are not found on other
+.B ls
+implementations.  (They have their own nonstandard flags.)
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man1/mail.1
===================================================================
--- /trunk/minix/man/man1/mail.1	(revision 9)
+++ /trunk/minix/man/man1/mail.1	(revision 9)
@@ -0,0 +1,98 @@
+.TH MAIL 1
+.SH NAME
+mail \- send and receive electronic mail
+.SH SYNOPSIS
+\fBmail\fR [\fB\-epqr\fR] [\fB\-f\fR \fIfile\fR] 
+.br
+\fBmail\fR [\fB\-dtv\fR] [\fB\-s\fR \fIsubject\fR] \fIuser\fR [...]
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS 
+.FL "\-e" "Exit with status TRUE or FALSE to indicate if there is mail in mailbox"
+.FL "\-p" "Print all mail and then exit"
+.FL "\-q" "Quit program if SIGINT received"
+.FL "\-r" "Reverse print order, i.e., print oldest first"
+.FL "\-f" "Use \fIfile\fR instead of \fI/usr/spool/mail/user\fR as mailbox"
+.PP
+.FL "\-d" "Force use of the shell variable \fIMAILER\fR"
+.FL "\-t" "Show distribution list as Dist: header in message"
+.FL "\-v" "Verbose mode (passed on to \fIMAILER\fR)"
+.FL "\-s" "Use Subject: \fIsubject\fR"
+.SH EXAMPLES
+.EX "mail ast" "Send a message to \fIast\fR"
+.EX "mail" "Read your mail"
+.EX "cat mail.cdiff | mail -s ''Here's the diff!'' asw " "Pipe program output to mail with a subject line"
+.EX "mail -f /usr/spool/mail/asw" "How root can read asw's mail"
+.SH DESCRIPTION
+.PP
+\fIMail\fR is an extremely simple electronic mail program.  It can be used
+to send or receive email on a single 
+\s-1MINIX 3\s-1
+system, in which case it functions
+as user agent and local delivery agent.  
+If the flag \fIMAILER\fR is defined in \fImail.c\fR,
+it can also call a trans\%port agent to handle remote mail as well.
+No such agent is supplied with
+\s-1MINIX 3\s-1.
+.PP
+When called by \fIuser\fR with no arguments, it examines the mailbox
+\fI/usr/spool/mail/user\fR, prints one message (depending on the \fB\-r\fR
+flag), and waits for one of the following commands:
+.PP
+.nf
+.ta 0.25i 1.25i
+	<newline>	Go to the next message
+	\-	Print the previous message
+	!command	Fork off a shell and execute \fIcommand\fR
+	CTRL-D	Update the mailbox and quit (same as q)
+	d	Delete the current message and go to the next one
+	q	Update the mailbox and quit (same as CTRL-D)
+	p	Print the current message again
+	s [\fIfile\fR]	Save message in the named file
+	x	Exit without updating the mailbox
+.PP
+.PP
+To send mail, the program is called with the name of one or more recipients as
+arguments.  The mail is sent, along with a postmark line containing the date.
+For local delivery, a file named after each recipient in the directory
+\fI/usr/spool/mail\fR must be writable. If a spool file does not exist for
+a recipient it will be created.
+.PP
+If the directory \fI/usr/spool/mail\fR does not exist then the mail is
+dumped on the console, so that system programs have a way to notify
+a user on a system that does not have a mail spool.
+.PP
+The received mail contains a To: header showing the recipient. If there
+are multiple recipients and the \fB\-t\fR option is specified each recipient 
+will also see a Dist: header line showing the other recipients.
+.PP
+The \fB\-s\fR option allows a subject to be specified. The subject must be 
+quoted if it contains spaces. If no subject is specified the mail
+will be delivered with Subject: No subject.
+.SH NOTES
+The \fB\-s\fR option was added to make this simple mail program
+consistent with mail programs found in other *nix variants.  Many
+programs, including the version of cron distributed with MINIX 3 releases
+2.0.3 and later, report their outcome by piping output to the mail
+program in order to send a mail message to root in lieu of writing a
+log file.  Such programs often expect the mail program to accept a
+subject line using this option.
+.SH BUGS
+If an external \fIMAILER\fR is used it is likely the conditional code 
+supporting this will need some editing to be made to work correctly.
+.SH AUTHOR
+The original mail program for MINIX 3 was written by Peter B. Housel.
+The -e and -t options were added by C. W. Rose. The -s option was added
+by A. S. Woodhull. This man page revised by ASW 2003-07-18.
+
+
+
Index: /trunk/minix/man/man1/make.1
===================================================================
--- /trunk/minix/man/man1/make.1	(revision 9)
+++ /trunk/minix/man/man1/make.1	(revision 9)
@@ -0,0 +1,76 @@
+.TH MAKE 1
+.SH NAME
+make \- a program for maintaining large programs
+.SH SYNOPSIS
+\fBmake\fR [\fB\-f \fIfile\fR]\fR [\fB\-adeiknpqrst\fR] [\fIoption\fR] ... [\fItarget\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-f" "Use \fIfile\fP as the makefile"
+.FL "\-d" "Print debugging information"
+.FL "\-e" "Environment overrides makefile macros"
+.FL "\-i" "Ignore status returned by commands"
+.FL "\-k" "On error, skip to next command"
+.FL "\-n" "Report, but do not execute"
+.FL "\-p" "Print macros and targets"
+.FL "\-q" "Question up-to-dateness of target"
+.FL "\-r" "Rule inhibit; do not use default rules"
+.FL "\-s" "Silent mode"
+.FL "\-t" "Touch files instead of making them"
+.SH EXAMPLES
+.EX "make kernel" "Make \fIkernel\fP up to date"
+.EX "make \-n \-f mfile" "Tell what needs to be done"
+.SH DESCRIPTION
+.PP
+.I Make
+is a program that is normally used for developing large programs consisting of
+multiple files.
+It keeps track of which object files depend on which source and header files.
+When called, it does the minimum amount of recompilation to bring the target
+file up to date.
+.PP
+The file dependencies are expected in 
+.I makefile
+or
+.I Makefile ,
+unless another file is specified with \fB\-f\fR.
+.I Make
+has some default rules built in, for example, it knows how to make 
+.I .o
+files
+from 
+.I .c
+files.
+Here is a sample 
+.I makefile .
+.PP
+.nf
+.ta +0.2i +\w'program:'u+1m +\w'cc \-o program head.o tail.o'u+2m
+	d=/user/ast		# \fId\fP is a macro
+	program:	head.o tail.o	# \fIprogram\fR depends on these
+		cc \-o program head.o tail.o	# tells how to make \fIprogram\fP 
+		echo Program done.	# announce completion
+	head.o:	$d/def.h head.c	# \fIhead.o\fP depends on these
+.br
+	tail.o:	$d/var.h tail.c	# \fItail.o\fP depends on these
+.PP
+.fi
+A complete description of \fImake\fR would require too much space here.
+Many books on
+\s-2UNIX\s+2
+discuss
+.I make .
+Study the numerous \fIMakefiles\fR in the 
+\s-1MINIX 3\s-1
+source tree for examples.
+.SH "SEE ALSO"
+.BR cc (1).
Index: /trunk/minix/man/man1/makewhatis.1
===================================================================
--- /trunk/minix/man/man1/makewhatis.1	(revision 9)
+++ /trunk/minix/man/man1/makewhatis.1	(revision 9)
@@ -0,0 +1,28 @@
+.TH MAKEWHATIS 1
+.SH NAME
+makewhatis \- build the whatis(5) database
+.SH SYNOPSIS
+.B makewhatis
+.I directory
+.SH DESCRIPTION
+.B Makewhatis
+makes the
+.BR whatis (5)
+database in the given manual page directory.  This database is used by
+.BR man (1)
+to map titles to manual page names and by
+.BR whatis (1)
+to give one line descriptions.  See
+.BR whatis (5)
+for a description of what a whatis database should look like and the
+restrictions that are placed on the NAME sections so that
+.B makewhatis
+can make whatis lines out of the manual pages.
+.SH "SEE ALSO"
+.BR whatis (5).
+.SH BUGS
+Removing only font and size changes from the NAME section is often not
+enough.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+.\" minor correction -- ASW 2005-01-15
Index: /trunk/minix/man/man1/man.1
===================================================================
--- /trunk/minix/man/man1/man.1	(revision 9)
+++ /trunk/minix/man/man1/man.1	(revision 9)
@@ -0,0 +1,201 @@
+.TH MAN 1
+.SH NAME
+man \- display online manual pages
+.SH SYNOPSIS
+.B man
+.RB [ \-antkfq ]
+.RB [ \-M
+.IR path ]
+.RB [ \-s
+.IR section ]
+.IR title " ..."
+.SH DESCRIPTION
+.B Man
+displays the online manual pages for the specified titles in the specified
+sections.  The sections are as follows:
+.PP
+.TP
+.B 1
+User Commands
+.br
+Generic commands such as
+.BR ls ,
+.BR cp ,
+.BR grep .
+.TP
+.B 2
+System Calls
+.br
+Low level routines that directly interface with the kernel.
+.TP
+.B 3
+Library Routines
+.br
+Higher level C language subroutines.
+.TP
+.B 4
+Device Files
+.br
+Describes devices in
+.BR /dev .
+.TP
+.B 5
+File Formats
+.br
+Formats of files handled by various utilities and subroutines.
+.TP
+.B 6
+Games
+.br
+It's not \s-2UNIX\s+2 without an adventure game.
+.TP
+.B 7
+Miscellaneous
+.br
+Macro packages, miscellaneous tidbits.
+.TP
+.B 8
+System Utilities
+.br
+Commands for the System Administrator.
+.TP
+.B 9
+Documents
+.br
+Larger manuals explaining some commands in more detail.
+.PP
+(If you are new to MINIX 3 then try
+.BR "man hier" ,
+it will show you around the file system and give you many pointers to other
+manual pages.)
+.PP
+By default,
+.B man
+will try the following files in a manual page directory for the command
+.BR "man \-s 1 ls" :
+.PP
+.RS
+.ft B
+.nf
+cat1/ls.1
+cat1/ls.1.Z
+man1/ls.1
+man1/ls.1.Z
+.fi
+.ft P
+.RE
+.PP
+Files in the man[1\-8] directories are formatted with
+.BR "nroff \-man" .
+Those in man9 are formatted with
+.BR "nroff \-mnx" .
+Files in the cat? directories are preformatted.  Files with names ending in
+.B .Z
+are decompressed first with
+.B zcat
+(see
+.BR compress (1)).
+The end result is presented to the user using a pager if displaying on
+the screen.
+.PP
+For each manual page directory in its search path,
+.B man
+will first try all the subdirectories of the manual page directory for
+the files above, and then the directory itself.  The directory
+.B /usr/man
+contains the standard manual pages, with manual pages for optional
+packages installed in a subdirectory of /usr/man, with the same
+structure as /usr/man.  The directory
+.B /usr/local/man
+contains manual pages for locally added software.  By default
+/usr/local/man is searched first, then /usr/man.
+.PP
+A title is not simply used as a filename, because several titles may
+refer to the same manual page.  Each manual page directory contains a
+database of titles in the
+.BR whatis (5)
+file that is created by
+.BR makewhatis (1)
+from the NAME sections of all the manual pages.  A title is searched in
+this database and the first title on a whatis line is used as a filename.
+.SH OPTIONS
+The options may be interspersed with the titles to search, and take effect
+for the titles after them.
+.TP
+.B \-a
+Show all the manual pages or one line descriptions with the given title in
+all the specified sections in all the manual directories in the search path.
+Normally only the first page found is shown.
+.TP
+.B \-n
+Use
+.B nroff \-man
+to format manual pages (default).
+.TP
+.B \-t
+Use
+.B troff \-man
+to format manual pages.
+.TP
+.B \-f
+Use
+.BR whatis (1)
+to show a one line description of the title from the
+.BR whatis (5)
+file.
+.TP
+.B \-k
+Use
+.BR apropos (1)
+to show all the one line descriptions of the title anywhere in the
+.BR whatis (5)
+files (implies
+.BR \-a ).
+.TP
+.B \-q
+Quietly check if all requested manual pages exist.  No output, no errors,
+just an exit code.
+.TP
+.BI \-M " path"
+Use
+.I path
+as the search path for manual directories.
+.TP
+.BI \-s " section"
+.I Section
+is the section number the page is to be found in, or a comma separated
+list of sections to use.  Normally all sections are searched.  The
+search is always in numerical order no matter what your section list looks
+like.  A single digit is treated as a section number without the
+.B \-s
+for compatibility with BSD-style
+.B man
+commands.
+.SH ENVIRONMENT
+.TP 15n
+.B MANPATH
+This is a colon separated list of directories to search for manual
+pages, by default
+.BR /usr/local/man:/usr/man .
+.TP
+.B PAGER
+The program to use to display the manual page or one line descriptions on
+the screen page by page.  By default
+.BR more .
+.SH FILES
+.TP 25n
+/usr/man/whatis
+One of the
+.BR whatis (5)
+databases.
+.SH "SEE ALSO"
+.BR nroff (1),
+.BR troff (1),
+.BR more (1),
+.BR whatis (1),
+.BR makewhatis (1),
+.BR catman (1),
+.BR whatis (5),
+.BR man (7).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/mdb.1
===================================================================
--- /trunk/minix/man/man1/mdb.1	(revision 9)
+++ /trunk/minix/man/man1/mdb.1	(revision 9)
@@ -0,0 +1,154 @@
+.TH MDB 1
+.SH NAME
+mdb \- MINIX 3 debugger
+.SH SYNOPSIS
+.B mdb
+.RB [ \-fc ]
+.I file
+.br
+.B mdb 
+.BR [-L|-l]log\-file
+.I exec-file 
+.RI [ core\-file ]
+.RI [ @command\-file ]
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B mdb
+is the MINIX 3 debugger. 
+.SH OPTIONS
+Its command line options are:
+.TP
+.B \-f
+Just examine the specified file.
+.TP
+.B \-c
+Examine 'core' file. No exec-file will be supplied.
+.TP
+.B \-Llog\-file
+Log to file only
+.TP
+.B \-llog\-file
+Log to file.
+.SP 
+.IR exec\-file
+Unless the -c option has been specified, the exec-file is required.
+.SP
+.IR core\-file
+The core-file is optional.
+.SP
+If the core-file is supplied, 
+.B mdb
+assumes that the user wishes to examine the core file.
+Otherwise 
+.B mdb 
+assumes that the user will run the exec-file and trace it.
+.SP
+.IR @command\-file
+.B mdb 
+executes command from command-file.
+.SH OVERVIEW
+.br
+.B mdb 
+commands are of the form: 
+.I [ expression ]
+.I command
+.SP
+.I expression
+can be of the form:
+.IP
+.I address 
+which defaults to text segment
+.IP
+address 
+.I overriden
+by 
+.I T:
+for Text segment
+or 
+.I D:
+for Data segment
+or
+.I S:
+for Stack segment
+.IP
+.I symbol
+where 
+.B mdb 
+does a lookup for the symbol first as a 
+.I text 
+symbol and then as a 
+.I data 
+symbol.
+.SP
+.TP
+.I command
+.SP
+The help command is ?. 
+.SP
+For detailed help on a command type: 
+.I command ?.
+.SP
+A semi-colon can be used to separate commands on a line.
+.SP
+.SH MDB COMMANDS
+.SP
+! Shell escape
+.SP
+#  Set Variable or register
+.SP 
+Tt Current call / Backtrace all
+.SP
+/nsf Display for n size s with format f
+.SP
+Xx [n] Disasm / & display reg for n instructions
+.SP
+Rr a Run / with arguments a
+.SP
+Cc [n] Continue with current signal / no signal n times
+.SP
+Ii [n] Single step with / no signal for n instructions
+.SP
+Mm t n Trace until / Stop when modified t type for n instructions
+.SP
+k  Kill
+.SP
+Bb Display / Set Break-pt
+.SP
+Dd Delete all / one break-points
+.SP
+P Toggle Pagging
+.SP
+Ll name Log to file name / and to standard output
+.SP
+Vv Toggle debug flag / Version info
+.SP
+V Version info
+.SP
+e [t] List symbols for type t
+.SP
+y Print segment mappings
+.SP
+s [n] Dump stack for n words
+.SP
+z [a] Trace syscalls with address a
+.SP
+? Help - short help
+.SP
+@ file Execute commands from file
+.SP
+Qq Quit / and kill traced process
+.SP
+.SH "SEE ALSO"
+.SP
+trace(2).
+.SH DIAGNOSTICS
+
+.SH NOTES
+
+.SH BUGS
+
+.SH AUTHOR
+Philip Murton and others
Index: /trunk/minix/man/man1/mesg.1
===================================================================
--- /trunk/minix/man/man1/mesg.1	(revision 9)
+++ /trunk/minix/man/man1/mesg.1	(revision 9)
@@ -0,0 +1,38 @@
+.\"	@(#)mesg.1	6.1 (Berkeley) 4/29/85
+.\"
+.TH MESG 1 "April 29, 1985"
+.AT 3
+.SH NAME
+mesg \- permit or deny messages
+.SH SYNOPSIS
+.B mesg
+[
+.B n
+] [
+.B y
+]
+.SH DESCRIPTION
+.B Mesg
+with argument
+.B n
+forbids messages via
+.B write
+and
+.BR talk (1)
+by revoking non-user
+write permission on the user's terminal.
+.B Mesg
+with argument
+.B y
+reinstates permission.
+All by itself,
+.B mesg
+reports the current state without changing it.
+.SH FILES
+/dev/tty*
+.SH "SEE ALSO"
+.BR write (1),
+.BR talk (1).
+.SH DIAGNOSTICS
+Exit status is 0 if messages are receivable,
+1 if not, 2 on error.
Index: /trunk/minix/man/man1/mixer.1
===================================================================
--- /trunk/minix/man/man1/mixer.1	(revision 9)
+++ /trunk/minix/man/man1/mixer.1	(revision 9)
@@ -0,0 +1,24 @@
+.TH MIXER 1
+.SH NAME
+mixer \- manipulate mixer settings on a sound card 
+.SH SYNOPSIS
+\fBmixer\fP [\-\fBr\fP] 
+.SH DESCRIPTION
+\fBMixer\fP, invoked without arguments, turns the screen into a sound mixer.
+Levels can be changed with the cursor-left and cursor-right keys. Input and
+output settings can be toggled with the space bar. For every sound source 
+there are two, or one when mono, sliders.   
+The input controls have only effect when recording with the Dac. These 
+settings can also be used to switch the left and right channels or, when
+both channels are enabled on both Dac channels, record in mono. 
+To exit the mixer use the 'e' key. 
+
+Mixer settings can be stored and restored with the 's' (store) and 'r' keys.
+When the store function is used \fBMixer\fP will write the settings to a file
+in the user's home directory called \fI\.mixer\fP. The restore function reads
+this file to restore saved settings.  
+.SH OPTIONS
+.IP \-r 
+restore settings saved in \fI\.mixer\fP and exit immediately
+.SH AUTHOR
+Michel R. Prevenier (mrpreve@cs.vu.nl)
Index: /trunk/minix/man/man1/mkdir.1
===================================================================
--- /trunk/minix/man/man1/mkdir.1	(revision 9)
+++ /trunk/minix/man/man1/mkdir.1	(revision 9)
@@ -0,0 +1,33 @@
+.TH MKDIR 1
+.SH NAME
+mkdir \- make a directory
+.SH SYNOPSIS
+\fBmkdir [\fB\-p\fR] [\fB\-m \fImode\fR] \fIdirectory ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-m" "Create directory with mode"
+.FL "\-p" "Create missing intermediate directories"
+.SH EXAMPLES
+.EX "mkdir dir" "Create \fIdir\fP in the current directory"
+.EX "mkdir \-p /user/ast/dir" "Create the \fI/user/ast\fP and \fI/user/ast/dir\fP"
+.SH DESCRIPTION
+.PP
+The specified directory or directories are created and initialized. If any
+intermediate directory is missing and \fB\-p\fR is specified, the missing
+component will be created and no error displayed if directory already
+exists. If the \fB\-m\fR flag is used, this will be equivalent to a chmod
+on the directory after its creation.
+.SH "SEE ALSO"
+.BR chmod (1),
+.BR rmdir (1),
+.BR mkdir (2).
Index: /trunk/minix/man/man1/mkfifo.1
===================================================================
--- /trunk/minix/man/man1/mkfifo.1	(revision 9)
+++ /trunk/minix/man/man1/mkfifo.1	(revision 9)
@@ -0,0 +1,30 @@
+.TH MKFIFO 1
+.SH NAME
+mkfifo \- make a named pipe
+.SH SYNOPSIS
+\fBmkfifo [\fB\-m \fImode\fR] \fIfifo ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-m" "Create fifo with specified mode"
+.SH EXAMPLES
+.EX "mkfifo pipe" "Create \fIpipe\fP in the current directory"
+.EX "mkfifo -m a+w systatus" "Create the \fIsystatus\fP writable by all"
+.SH DESCRIPTION
+.PP
+The specified fifo special files are created.
+If the \fB\-m\fR flag is used, this will be equivalent to a chmod
+on the fifo special file after its creation.
+.SH "SEE ALSO"
+.BR chmod (1),
+.BR mknod (2),
+.BR mknod (8).
Index: /trunk/minix/man/man1/mkfs.1
===================================================================
--- /trunk/minix/man/man1/mkfs.1	(revision 9)
+++ /trunk/minix/man/man1/mkfs.1	(revision 9)
@@ -0,0 +1,88 @@
+.TH MKFS 1
+.SH NAME
+mkfs \- make a file system
+.SH SYNOPSIS
+\fBmkfs \fR[\fB\-Ldot\fR] [\fB\-B \fIblocksize\fR] [\fB\-i \fIinodes\fR] [\fB\-b \fIblocks\fR] \fIspecial \fIprototype\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-L" "Make a listing on standard output"
+.FL "\-d" "Use mod time of \fImkfs\fR binary for all files"
+.FL "\-o" "Use a drive other than 0 or 1 (safety precaution)"
+.FL "\-t" "Do not test if file system fits on the medium"
+.FL "\-1" "Make a version 1 file system (for backward compatibility)"
+.FL "\-i" "Number of i-nodes (files)"
+.FL "\-B" "Filesystem block size (in bytes)"
+.FL "\-b" "Filesystem size (in blocks)"
+.SH EXAMPLES
+.EX "mkfs /dev/fd1 proto" "Make a file system on \fI/dev/fd1\fR"
+.EX "mkfs -b 360 /dev/fd1" "Make empty 360 block file system"
+.EX "mkfs /dev/fd1 360" "Alternate way to specify the size"
+.SH DESCRIPTION
+.PP
+.I Mkfs
+builds a file system and copies specified files to it.
+The prototype file tells which directories and files to copy to it.
+If the prototype file cannot be opened, and its name is just a string of
+digits, an empty file system will be made with the specified number of
+blocks.
+A sample prototype file follows.
+The text following the \fI#\fR sign in the example below is comment.
+In real prototype files, comments are not allowed.
+.PP
+.nf
+.ta 0.20i 0.70i 1.10i 3i 3.5i 4i
+	boot			# boot block file (ignored)
+	360 63			# blocks and i-nodes
+	d--755 1 1		# root directory
+	   bin	d--755 \|2 1	# bin dir: mode (755), uid (2), gid (1)
+		sh	\|---755 2 1 /user/bin/shell	# shell has mode \fIrwxr-xr-x\fP
+		mv	-u-755 2 1 /user/bin/mv	# u = SETUID bit
+		login	-ug755 2 1 /user/bin/login	# SETUID and SETGID
+	   $			# end of \fI/bin\fP
+	   dev	d--755 2 1	# special files: tty (char), fd0 (block)
+		tty	c--777 2 1 4 0	# uid=2, gid=1, major=4, minor=0
+		fd0	b--644 2 1 2 0 360	# uid, gid, major, minor, blocks
+	   $			# end of \fI/dev\fP
+	   user	d--755 12 1	# user dir: mode (755), uid (12), gid (1)
+		ast	d--755 12 1	# \fI/user/ast\fP
+		$		# \fI/user/ast\fP is empty
+	   $			# end of \fI/user\fP
+	$			# end of root directory
+.PP
+.fi
+The first entry on each line (except the first 3 and the $ lines, which
+terminate directories) is the name the file or directory will get on the
+new file system.  
+Next comes its mode, with the first character being
+\fB\-dbc\fR for regular files, directories, block special files and character 
+special files, respectively.
+The next two characters are used to specify the SETUID and SETGID bits, as
+shown above.
+The last three characters of the mode are the 
+.I rwx
+protection bits.
+.PP
+Following the mode are the uid and gid.
+For special files, the major and minor devices are needed.
+.PP
+The maximum size of a file system is 1 Gb for a version 2 file system,
+and 64 Mb for a version 1 file system.  Alas the 8086
+.I fsck
+runs out of memory on a V2 file system larger than 128 Mb, so for the 8086
+version of
+\s-1MINIX 3\s-1
+you have to limit yourself to file systems of that size.
+.SH "SEE ALSO"
+.BR mkproto (1),
+.BR fsck (1),
+.BR mount (1).
Index: /trunk/minix/man/man1/mkproto.1
===================================================================
--- /trunk/minix/man/man1/mkproto.1	(revision 9)
+++ /trunk/minix/man/man1/mkproto.1	(revision 9)
@@ -0,0 +1,36 @@
+.TH MKPROTO 1
+.SH NAME
+mkproto \- create a MINIX 3 prototype file
+.SH SYNOPSIS
+\fBmkproto \fR[\fB\-b \fIn\fR] [\fB\-d \fIstr\fR] [\fB\-g \fIn\fR] [\fB\-i \fIn\fR] [\fB\-p \fInnn\fR] [\fB\-s\fR] [\fB\-t \fIroot\fR] [\fB\-u \fIn\fR] \fIsource_directory\fR [\fIprototype_file\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-b" "Number of blocks in the prototype is \fIn\fR"
+.FL "\-d" "Indent the prototype file using \fIstr\fR instead of tab"
+.FL "\-g" "Use \fIn\fR as the gid for all files and directories"
+.FL "\-i" "Number of i-nodes in the prototype is \fIn\fR"
+.FL "\-p" "Use \fInnn\fR (3 octal digits) as the protection mode"
+.FL "\-s" "Use the same uid, gid and mode as the source files have"
+.FL "\-t" "Use the string \fIroot\fR as the path prefix for every file"
+.FL "\-u" "Use \fIn\fR as the uid for all files and directories"
+.SH EXAMPLES
+.EX "mkproto \-b360" "Make a 360K prototype of this directory"
+.EX "mkproto \-u2 \-g1 \-p644" "Give all files uid 2, gid 1 and mode 644"
+.SH DESCRIPTION
+.PP
+\fIMkproto\fR creates an \fImkfs\fR prototype file for the specified
+source-directory. 
+The prototype file is either written to \fIstdout\fR or, if specified, 
+the proto-file.
+.SH "SEE ALSO"
+.BR mkfs (1).
Index: /trunk/minix/man/man1/modem.1
===================================================================
--- /trunk/minix/man/man1/modem.1	(revision 9)
+++ /trunk/minix/man/man1/modem.1	(revision 9)
@@ -0,0 +1,39 @@
+.TH MODEM 1
+.SH NAME
+modem \- switch the modem and getty state
+.SH SYNOPSIS
+\fBmodem \fR[\fB\-o\fR] [\fB\-i \fInum\fR] \fBtty\fIn\fR\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-o" "Turn getty off and set modem to dialout"
+.FL "\-i" "Set line to dialin"
+.SH EXAMPLES
+.EX "modem \-o tty00" "Set tty00 to dialout"
+.EX "modem \-i2 tty00" "Set tty00 to dialin (2 rings)"
+.SH DESCRIPTION
+.PP
+The \fIgetty\fR program allows a terminal port to be used for both dialin and
+dialout. 
+This little program switches the getty state, and also sends
+some commands to the modem attached to the specified line.
+If the \fB\-o\fR flag is presnt, \fImodem\fR will put the 
+getty process (if any) connected to the specified line into 
+SUSPEND state, which means that it
+will not pay attention to that line until it is reset to RESTART state.
+Also, \fImodem\fR will send some (Hayes) 
+commands to the attached modem to disable the auto-nanswer mode. 
+The \fB\-i\fR flag specifies the number of times the telephone has to 
+ring before the modem may answer the call (to give the operator a chance).
+.SH "SEE ALSO"
+.BR term (1),
+.BR getty (8).
Index: /trunk/minix/man/man1/mount.1
===================================================================
--- /trunk/minix/man/man1/mount.1	(revision 9)
+++ /trunk/minix/man/man1/mount.1	(revision 9)
@@ -0,0 +1,44 @@
+.TH MOUNT 1
+.SH NAME
+mount \- mount a file system
+.SH SYNOPSIS
+\fBmount [\fB\-r\fR] \fIspecial \fIfile\fR
+.br
+\fBmount [\fB\-s\fR] \fIswapfile\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-r" "File system is mounted read-only"
+.FL "\-s" "Mount swap space"
+.SH EXAMPLES
+.EX "mount /dev/fd1 /user" "Mount diskette 1 on \fI/user\fP"
+.SH DESCRIPTION
+.PP
+The file system contained on the special file is mounted on \fIfile\fP.
+In the example above, the root directory of the file system in drive 1
+can be accessed as
+.B /user
+after the mount.
+When the file system is no longer needed, it must be unmounted before being
+removed from the drive.
+.PP
+With the
+.B \-s
+flag a device or file is mounted as swap space.
+.SH "SEE ALSO"
+.BR df (1),
+.BR mkfs (1),
+.BR fsck (1),
+.BR mkswap (8),
+.BR umount (1),
+.BR mount (2),
+.BR fstab (5).
Index: /trunk/minix/man/man1/mt.1
===================================================================
--- /trunk/minix/man/man1/mt.1	(revision 9)
+++ /trunk/minix/man/man1/mt.1	(revision 9)
@@ -0,0 +1,109 @@
+.TH MT 1
+.SH NAME
+mt \- magnetic tape control
+.SH SYNOPSIS
+.B mt
+.RB [ \-f
+.IR device ]
+.RI [ count ]
+.SH DESCRIPTION
+.B Mt
+is a user interface to the magnetic tape commands described in
+.BR mtio (4).
+It allows one to space a tape forwards or backwards, write end of file
+markers, etc.
+.PP
+With the
+.B \-f
+option a tape device can be named, otherwise the environment variable
+.B TAPE
+is used if set.  Standard input is used if the tape name is a dash (\-).  The
+.I count
+argument is used to tell how many blocks or files to space or how many file
+markers to write.  It may be a C-style decimal, octal or hexadecimal constant,
+by default "1".
+.PP
+.I Command
+is the action to perform, it may be one of the following, or any
+unambiguous prefix (like
+.B st
+for
+.BR status ):
+.TP 15
+.B eof, weof
+Write
+.I count
+end-of-file markers.
+.TP
+.B fsf
+Forward space
+.I count
+file markers.
+.TP
+.B fsr
+Forward space
+.I count
+records.  (The size of a record depends on the tape, and may even be
+variable, depending on the size of the writes.)
+.TP
+.B bsf
+Backwards space
+.I count
+files.  The count may be zero to backspace to the start of the current file.
+(A tape device need not support backwards movement, or may be very slow
+doing it.  Rewinding and forward spacing may be better.)
+.TP
+.B bsr
+Backwards space
+.I count
+records.  The tape is positioned after the last block of the previous file
+if you hit a filemark when spacing backwards.  The block count is set to -1
+to indicate that the driver has no idea where it is on the previous file.
+.TP
+.B eom
+Forward space to the end of media.
+.TP
+.B rewind
+Rewind the tape.
+.TP
+.B offline, rewoffl
+Rewind and take offline.  This may cause some drives to eject the tape.
+.TP
+.B status
+Shows the status of the drive, the sense key of the last SCSI error,
+current file number, current record number, residual count if the last
+command that encountered end-of-file, and the current block size.
+.TP
+.B retension
+Removes tape tension by winding and rewinding the tape completely.
+.TP
+.B erase
+Erases the tape completely and rewinds it.
+.TP
+.B density
+Sets the density code to read or write the tape to
+.IR count .
+Density codes supported depend on the drive.  This command need not be
+used if the drive senses the proper density on read and can only write
+one density.
+.TP
+.B blksize, blocksize
+Sets the block size used to read or write the tape to
+.IR count .
+This command may be used to select a fixed block size for a variable block
+size tape.  This will speed up I/O for small block sizes.  Use a zero
+.I count
+to use variable sized blocks again.
+.SH ENVIRONMENT
+.TP 15n
+.B TAPE
+Tape drive to use if set.
+.SH FILES
+.TP 15n
+.B /dev/nrst4
+Default tape device.
+.SH "SEE ALSO"
+.BR mtio (4),
+.BR st (4).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/nice.1
===================================================================
--- /trunk/minix/man/man1/nice.1	(revision 9)
+++ /trunk/minix/man/man1/nice.1	(revision 9)
@@ -0,0 +1,26 @@
+.TH NICE 1
+.SH NAME
+nice \- invoke command with higher or lower scheduling priority
+.SH SYNOPSIS
+\fBnice\fP [\fB\-n\fP increment] \fIutility\fP [\fIargument\fP...]
+.SH DESCRIPTION
+The
+.B nice
+utility runs \fIutility\fP at a different scheduling priority than
+the default. The nicer the process is to others (the higher the
+increment), the less favourable the scheduling is. Super-users
+can give a negative increment, meaning scheduling is more favourable
+than the default.
+.SH OPTIONS
+.TP
+.B \-n \fIincrement
+the increment value sets how nice the invoked command will be. 0 is
+the same priority as regular processes. 10 is the default.
+The range is -20 to 20.
+.SH SEE ALSO
+getpriority(2), setpriority(2)
+.SH AUTHOR
+This
+.B nice
+utility was imported from FreeBSD. This manual page was written
+Ben Gras <beng@few.vu.nl>.
Index: /trunk/minix/man/man1/nm.1
===================================================================
--- /trunk/minix/man/man1/nm.1	(revision 9)
+++ /trunk/minix/man/man1/nm.1	(revision 9)
@@ -0,0 +1,40 @@
+.TH NM 1
+.SH NAME
+nm \- print name list
+.SH SYNOPSIS
+\fBnm\fR [\fB\-dgnopru\fR]\fR [\fIfile\fR] ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-d" "Print the offsets in decimal instead of in hex"
+.FL "\-g" "Print only external symbols"
+.FL "\-n" "Sort numerically rather than alphabetically"
+.FL "\-o" "Prepend file name to each line rather than only once"
+.FL "\-p" "Do not sort, print in symbol-table order"
+.FL "\-r" "Sort in reverse order"
+.FL "\-u" "Print only undefined symbols"
+.SH EXAMPLES
+.EX "nm \-n a.out" "Print all symbols in numerical order"
+.EX "nm \-dg a.out" "Print globals alphabetically in decimal"
+.SH DESCRIPTION
+.PP
+\fINm\fR prints the symbol table of executable files when it is available.
+If no file is given, the symbols in \fIa.out\fR are used.  
+The format of the table 
+is somewhat compatible with the one produced  by \fIasld\fR when used with 
+the \fB\-s\fR option. The symbol table can be added with \fIast\fR.  
+Assembly language files do not have symbol tables.
+.SH "SEE ALSO"
+.BR anm (1),
+.BR asize (1),
+.BR ar (1),
+.BR size (1).
Index: /trunk/minix/man/man1/od.1
===================================================================
--- /trunk/minix/man/man1/od.1	(revision 9)
+++ /trunk/minix/man/man1/od.1	(revision 9)
@@ -0,0 +1,38 @@
+.TH OD 1
+.SH NAME
+od \- octal dump
+.SH SYNOPSIS
+\fBod\fR [\fB\-bcdhox\fR]\fR [\fIfile\fR] [ [\fB+\fR] \fIoffset\fR [\fB.\fR][\fBb\fR]\fR ]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-b" "Dump bytes in octal"
+.FL "\-c" "Dump bytes as ASCII characters"
+.FL "\-d" "Dump words in decimal"
+.FL "\-h" "Print addresses in hex (default is octal)"
+.FL "\-o" "Dump words in octal (default)"
+.FL "\-v" "Verbose (list duplicate lines)"
+.FL "\-x" "Dump words in hex"
+.SH EXAMPLES
+.EX "od \-ox file" "Dump \fIfile\fP in octal and hex"
+.EX "od \-d file +1000" "Dump \fIfile\fP starting at byte 01000"
+.EX "od \-c file +10.b" "Dump \fIfile\fP starting at block 10"
+.SH DESCRIPTION
+.PP
+.I Od
+dumps a file in one or more formats.
+If \fIfile\fP is missing, \fIstdin\fR is dumped.
+The \fIoffset\fP argument tells
+.I od
+to skip a certain number of bytes or blocks before starting.
+The offset is in octal bytes, unless it is followed by a 
+\&'.\&' for decimal or \fBb\fP for blocks or both.
Index: /trunk/minix/man/man1/passwd.1
===================================================================
--- /trunk/minix/man/man1/passwd.1	(revision 9)
+++ /trunk/minix/man/man1/passwd.1	(revision 9)
@@ -0,0 +1,44 @@
+.TH PASSWD 1
+.SH NAME
+passwd, chfn, chsh \- change a login password, full name or shell
+.SH SYNOPSIS
+\fBpasswd\fR [\fIuser\fR]\fR
+.br
+\fBchfn\fR [\fIuser\fR] \fIfullname\fR\fR
+.br
+\fBchsh\fR [\fIuser\fR] \fIshell\fR\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "passwd" "Change current user's password"
+.EX "passwd ast" "Change ast's password (super\-user only)"
+.EX "chsh /usr/bin/mail" "For those who only read mail"
+.EX "chfn 'Jane Doe'" "Current user is Jane Doe"
+.SH DESCRIPTION
+.PP
+.I Passwd
+is used to change your password.
+It prompts for the old and new passwords.
+It asks for the new password twice, to reduce the effect of a typing error.
+.I Chfn
+changes the full name (GECOS field) in the password file.
+.I Chsh
+changes your login shell.
+Do not forget to copy the modified password file back to the root file system,
+or the changes will be lost when the system is rebooted.
+.SH "SEE ALSO"
+.BR login (1),
+.BR su (1),
+.BR crypt (3),
+.BR getpwent (3),
+.BR passwd (5),
+.BR adduser (8).
Index: /trunk/minix/man/man1/paste.1
===================================================================
--- /trunk/minix/man/man1/paste.1	(revision 9)
+++ /trunk/minix/man/man1/paste.1	(revision 9)
@@ -0,0 +1,40 @@
+.TH PASTE 1
+.SH NAME
+paste \- paste multiple files together
+.SH SYNOPSIS
+\fBpaste\fR [\fB\-s\fR]\fR [\fB\-d\fI list\fR] \fIfile...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-d" "Set delimiter used to separate columns to \fIlist\fR.
+.FL "\-s" "Print files sequentially, file \fIk\fR on line \fIk\fR.
+.SH EXAMPLES
+.EX "paste file1 file2" "Print \fIfile1\fR in col 1, \fIfile2\fR in col 2"
+.EX "paste \-s f1 f2" "Print \fIf1\fR on line 1 and \fIf2\fR on line 2"
+.EX "paste -d : file1 file2" "Print the lines separated by a colon"
+.SH DESCRIPTION
+.PP
+\fIPaste\fR concatenates corresponding lines of the given input files
+and writes them to standard output. The lines of the different files
+are separated by the delimiters given with the option \-s\fR. If
+no list is given, a tab is substituted for every linefeed, except the last one.
+If end-of-file is hit on an input file, subsequent lines are empty.
+Suppose a set of \fIk\fR files each has one word per line.  
+Then the \fIpaste\fR output will have \fIk\fR columns, 
+with the contents of file \fIj\fR in column \fIj\fR.  
+If the \fB\-s\fR flag is given, then the first
+file is on line 1, the second file on line 2, etc.  
+In effect, \fB\-s\fR turns the output sideways.
+.PP
+If a list of delimiters is given, they are used in turn.  The C escape
+sequences \\n, \\t, \\\\, and \\0 are used for linefeed, tab, backslash, and
+the null string, respectively.
Index: /trunk/minix/man/man1/patch.1
===================================================================
--- /trunk/minix/man/man1/patch.1	(revision 9)
+++ /trunk/minix/man/man1/patch.1	(revision 9)
@@ -0,0 +1,555 @@
+.\" -*- nroff -*-
+.rn '' }`
+'\" $Header: /cvsup/minix/src/man/man1/patch.1,v 1.1 2005/05/02 13:01:39 beng Exp $
+'\" 
+'\" $Log: patch.1,v $
+'\" Revision 1.1  2005/05/02 13:01:39  beng
+'\" Added man pages.
+'\"
+'\" Revision 2.0.1.2  88/06/22  20:47:18  lwall
+'\" patch12: now avoids Bell System Logo
+'\" 
+'\" Revision 2.0.1.1  88/06/03  15:12:51  lwall
+'\" patch10: -B switch was contributed.
+'\" 
+'\" Revision 2.0  86/09/17  15:39:09  lwall
+'\" Baseline for netwide release.
+'\" 
+'\" Revision 1.4  86/08/01  19:23:22  lwall
+'\" Documented -v, -p, -F.
+'\" Added notes to patch senders.
+'\" 
+'\" Revision 1.3  85/03/26  15:11:06  lwall
+'\" Frozen.
+'\" 
+'\" Revision 1.2.1.4  85/03/12  16:14:27  lwall
+'\" Documented -p.
+'\" 
+'\" Revision 1.2.1.3  85/03/12  16:09:41  lwall
+'\" Documented -D.
+'\" 
+'\" Revision 1.2.1.2  84/12/05  11:06:55  lwall
+'\" Added -l switch, and noted bistability bug.
+'\" 
+'\" Revision 1.2.1.1  84/12/04  17:23:39  lwall
+'\" Branch for sdcrdcf changes.
+'\" 
+'\" Revision 1.2  84/12/04  17:22:02  lwall
+'\" Baseline version.
+'\" 
+.de Sh
+.br
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+'\"
+'\"     Set up \*(-- to give an unbreakable dash;
+'\"     string Tr holds user defined translation string.
+'\"     Bell System Logo is used as a dummy character.
+'\"
+'\" Shut up a groff -ww warning.
+'\".if \n(.g .if !dTr .ds Tr
+'\".ie n \{\
+.tr \(*W-\*(Tr
+'\".ds -- \(*W-
+'\".if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+'\".if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+.ds L' '
+.ds R' '
+'\"'br \}
+'\".el \{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds L' `
+.ds R' '
+'\"'br\}
+.TH PATCH 1 LOCAL
+.SH NAME
+patch - apply a diff file to an original
+.SH SYNOPSIS
+.B patch
+[options] [origfile [patchfile]] [+ [options] [origfile]]...
+.sp
+but usually just
+.sp
+.B patch
+<patchfile
+.SH DESCRIPTION
+.I Patch
+will take a patch file containing any of the four forms of difference
+listing produced by the
+.I diff
+program and apply those differences to an original file, producing a patched
+version.
+By default, the patched version is put in place of the original, with
+the original file backed up to the same name with the
+extension \*(L".orig\*(R" (\*(L"~\*(R" on systems that do not
+support long filenames), or as specified by the
+.BR -b ,
+.BR -B ,
+or
+.B -V
+switches.
+The extension used for making backup files may also be specified in the
+.B SIMPLE_BACKUP_SUFFIX
+environment variable, which is overridden by above switches.
+.PP
+If the backup file already exists,
+.B patch
+creates a new backup file name by changing the first lowercase letter
+in the last component of the file's name into uppercase.  If there are
+no more lowercase letters in the name, it removes the first character
+from the name.  It repeats this process until it comes up with a
+backup file that does not already exist.
+.PP
+You may also specify where you want the output to go with a
+.B -o
+switch; if that file already exists, it is backed up first.
+.PP
+If
+.I patchfile
+is omitted, or is a hyphen, the patch will be read from standard input.
+.PP
+Upon startup, patch will attempt to determine the type of the diff listing,
+unless over-ruled by a
+.BR -c ,
+.BR -e ,
+.BR -n ,
+or
+.B -u
+switch.
+Context diffs (old-style, new-style, and unified) and
+normal diffs are applied by the
+.I patch
+program itself, while ed diffs are simply fed to the
+.I ed
+editor via a pipe.
+.PP
+.I Patch
+will try to skip any leading garbage, apply the diff,
+and then skip any trailing garbage.
+Thus you could feed an article or message containing a
+diff listing to
+.IR patch ,
+and it should work.
+If the entire diff is indented by a consistent amount,
+this will be taken into account.
+.PP
+With context diffs, and to a lesser extent with normal diffs,
+.I patch
+can detect when the line numbers mentioned in the patch are incorrect,
+and will attempt to find the correct place to apply each hunk of the patch.
+As a first guess, it takes the line number mentioned for the hunk, plus or
+minus any offset used in applying the previous hunk.
+If that is not the correct place,
+.I patch
+will scan both forwards and backwards for a set of lines matching the context
+given in the hunk.
+First
+.I patch
+looks for a place where all lines of the context match.
+If no such place is found, and it's a context diff, and the maximum fuzz factor
+is set to 1 or more, then another scan takes place ignoring the first and last
+line of context.
+If that fails, and the maximum fuzz factor is set to 2 or more,
+the first two and last two lines of context are ignored,
+and another scan is made.
+(The default maximum fuzz factor is 2.)
+If
+.I patch
+cannot find a place to install that hunk of the patch, it will put the
+hunk out to a reject file, which normally is the name of the output file
+plus \*(L".rej\*(R" (\*(L"#\*(R" on systems that do not support
+long filenames).
+(Note that the rejected hunk will come out in context diff form whether the
+input patch was a context diff or a normal diff.
+If the input was a normal diff, many of the contexts will simply be null.)
+The line numbers on the hunks in the reject file may be different than
+in the patch file: they reflect the approximate location patch thinks the
+failed hunks belong in the new file rather than the old one.
+.PP
+As each hunk is completed, you will be told whether the hunk succeeded or
+failed, and which line (in the new file)
+.I patch
+thought the hunk should go on.
+If this is different from the line number specified in the diff you will
+be told the offset.
+A single large offset MAY be an indication that a hunk was installed in the
+wrong place.
+You will also be told if a fuzz factor was used to make the match, in which
+case you should also be slightly suspicious.
+.PP
+If no original file is specified on the command line,
+.I patch
+will try to figure out from the leading garbage what the name of the file
+to edit is.
+In the header of a context diff, the filename is found from lines beginning
+with \*(L"***\*(R" or \*(L"---\*(R", with the shortest name of an existing
+file winning.
+Only context diffs have lines like that, but if there is an \*(L"Index:\*(R"
+line in the leading garbage,
+.I patch
+will try to use the filename from that line.
+The context diff header takes precedence over an Index line.
+If no filename can be intuited from the leading garbage, you will be asked
+for the name of the file to patch.
+.PP
+If the original file cannot be found or is read-only, but a suitable
+SCCS or RCS file is handy,
+.I patch
+will attempt to get or check out the file.
+.PP
+Additionally, if the leading garbage contains a \*(L"Prereq: \*(R" line,
+.I patch
+will take the first word from the prerequisites line (normally a version
+number) and check the input file to see if that word can be found.
+If not,
+.I patch
+will ask for confirmation before proceeding.
+.PP
+The upshot of all this is that you should be able to say, while in a news
+interface, the following:
+.Sp
+	| patch -d /usr/src/local/blurfl
+.Sp
+and patch a file in the blurfl directory directly from the article containing
+the patch.
+.PP
+If the patch file contains more than one patch,
+.I patch
+will try to apply each of them as if they came from separate patch files.
+This means, among other things, that it is assumed that the name of the file
+to patch must be determined for each diff listing,
+and that the garbage before each diff listing will
+be examined for interesting things such as filenames and revision level, as
+mentioned previously.
+You can give switches (and another original file name) for the second and
+subsequent patches by separating the corresponding argument lists
+by a \*(L'+\*(R'.
+(The argument list for a second or subsequent patch may not specify a new
+patch file, however.)
+.PP
+.I Patch
+recognizes the following switches:
+.TP 5
+.B \-b
+causes the next argument to be interpreted as the backup extension, to be
+used in place of \*(L".orig\*(R" or \*(L"~\*(R".
+.TP 5
+.B \-B
+causes the next argument to be interpreted as a prefix to the backup file
+name. If this argument is specified any argument from -b will be ignored.
+.TP 5
+.B \-c
+forces
+.I patch
+to interpret the patch file as a context diff.
+.TP 5
+.B \-d
+causes
+.I patch
+to interpret the next argument as a directory, and cd to it before doing
+anything else.
+.TP 5
+.B \-D
+causes
+.I patch
+to use the "#ifdef...#endif" construct to mark changes.
+The argument following will be used as the differentiating symbol.
+Note that, unlike the C compiler, there must be a space between the
+.B \-D
+and the argument.
+.TP 5
+.B \-e
+forces
+.I patch
+to interpret the patch file as an ed script.
+.TP 5
+.B \-E
+causes
+.I patch
+to remove output files that are empty after the patches have been applied.
+.TP 5
+.B \-f
+forces
+.I patch
+to assume that the user knows exactly what he or she is doing, and to not
+ask any questions.  It assumes the following: skip patches for which a
+file to patch can't be found; patch files even though they have the
+wrong version for the ``Prereq:'' line in the patch; and assume that
+patches are not reversed even if they look like they are.
+This option does not suppress commentary; use
+.B \-s
+for that.
+.TP 5
+.B \-t
+similar to
+.BR \-f ,
+in that it suppresses questions, but makes some different assumptions:
+skip patches for which a file to patch can't be found (the same as \fB\-f\fP);
+skip patches for which the file has the wrong version for the ``Prereq:'' line
+in the patch; and assume that patches are reversed if they look like
+they are.
+.TP 5
+.B \-F<number>
+sets the maximum fuzz factor.
+This switch only applies to context diffs, and causes
+.I patch
+to ignore up to that many lines in looking for places to install a hunk.
+Note that a larger fuzz factor increases the odds of a faulty patch.
+The default fuzz factor is 2, and it may not be set to more than
+the number of lines of context in the context diff, ordinarily 3.
+.TP 5
+.B \-l
+causes the pattern matching to be done loosely, in case the tabs and
+spaces have been munged in your input file.
+Any sequence of whitespace in the pattern line will match any sequence
+in the input file.
+Normal characters must still match exactly.
+Each line of the context must still match a line in the input file.
+.TP 5
+.B \-n
+forces
+.I patch
+to interpret the patch file as a normal diff.
+.TP 5
+.B \-N
+causes
+.I patch
+to ignore patches that it thinks are reversed or already applied.
+See also
+.B \-R .
+.TP 5
+.B \-o
+causes the next argument to be interpreted as the output file name.
+.TP 5
+.B \-p<number>
+sets the pathname strip count,
+which controls how pathnames found in the patch file are treated, in case
+the you keep your files in a different directory than the person who sent
+out the patch.
+The strip count specifies how many slashes are to be stripped from
+the front of the pathname.
+(Any intervening directory names also go away.)
+For example, supposing the filename in the patch file was
+.sp
+	/u/howard/src/blurfl/blurfl.c
+.sp
+setting
+.B \-p
+or
+.B \-p0
+gives the entire pathname unmodified,
+.B \-p1
+gives
+.sp
+	u/howard/src/blurfl/blurfl.c
+.sp
+without the leading slash,
+.B \-p4
+gives
+.sp
+	blurfl/blurfl.c
+.sp
+and not specifying
+.B \-p
+at all just gives you "blurfl.c", unless all of the directories in the
+leading path (u/howard/src/blurfl) exist and that path is relative,
+in which case you get the entire pathname unmodified.
+Whatever you end up with is looked for either in the current directory,
+or the directory specified by the
+.B \-d
+switch.
+.TP 5
+.B \-r
+causes the next argument to be interpreted as the reject file name.
+.TP 5
+.B \-R
+tells
+.I patch
+that this patch was created with the old and new files swapped.
+(Yes, I'm afraid that does happen occasionally, human nature being what it
+is.)
+.I Patch
+will attempt to swap each hunk around before applying it.
+Rejects will come out in the swapped format.
+The
+.B \-R
+switch will not work with ed diff scripts because there is too little
+information to reconstruct the reverse operation.
+.Sp
+If the first hunk of a patch fails,
+.I patch
+will reverse the hunk to see if it can be applied that way.
+If it can, you will be asked if you want to have the
+.B \-R
+switch set.
+If it can't, the patch will continue to be applied normally.
+(Note: this method cannot detect a reversed patch if it is a normal diff
+and if the first command is an append (i.e. it should have been a delete)
+since appends always succeed, due to the fact that a null context will match
+anywhere.
+Luckily, most patches add or change lines rather than delete them, so most
+reversed normal diffs will begin with a delete, which will fail, triggering
+the heuristic.)
+.TP 5
+.B \-s
+makes
+.I patch
+do its work silently, unless an error occurs.
+.TP 5
+.B \-S
+causes
+.I patch
+to ignore this patch from the patch file, but continue on looking
+for the next patch in the file.
+Thus
+.sp
+	patch -S + -S + <patchfile
+.sp
+will ignore the first and second of three patches.
+.TP 5
+.B \-u
+forces
+.I patch
+to interpret the patch file as a unified context diff (a unidiff).
+.TP 5
+.B \-v
+causes
+.I patch
+to print out its revision header and patch level.
+.TP 5
+.B \-V
+causes the next argument to be interpreted as a method for creating
+backup file names.  The type of backups made can also be given in the
+.B VERSION_CONTROL
+environment variable, which is overridden by this option.
+The
+.B -B
+option overrides this option, causing the prefix to always be used for
+making backup file names.
+The value of the
+.B VERSION_CONTROL
+environment variable and the argument to the
+.B -V
+option are like the GNU
+Emacs `version-control' variable; they also recognize synonyms that
+are more descriptive.  The valid values are (unique abbreviations are
+accepted):
+.RS
+.TP
+`t' or `numbered'
+Always make numbered backups.
+.TP
+`nil' or `existing'
+Make numbered backups of files that already
+have them, simple backups of the others.
+This is the default.
+.TP
+`never' or `simple'
+Always make simple backups.
+.RE
+.TP 5
+.B \-x<number>
+sets internal debugging flags, and is of interest only to
+.I patch
+patchers.
+.SH AUTHOR
+Larry Wall <lwall@netlabs.com>
+.br
+with many other contributors.
+.SH ENVIRONMENT
+.TP
+.B TMPDIR
+Directory to put temporary files in; default is /tmp.
+.TP
+.B SIMPLE_BACKUP_SUFFIX
+Extension to use for backup file names instead of \*(L".orig\*(R" or
+\*(L"~\*(R".
+.TP
+.B VERSION_CONTROL
+Selects when numbered backup files are made.
+.SH FILES
+$TMPDIR/patch*
+.SH SEE ALSO
+diff(1)
+.SH NOTES FOR PATCH SENDERS
+There are several things you should bear in mind if you are going to
+be sending out patches.
+First, you can save people a lot of grief by keeping a patchlevel.h file
+which is patched to increment the patch level as the first diff in the
+patch file you send out.
+If you put a Prereq: line in with the patch, it won't let them apply
+patches out of order without some warning.
+Second, make sure you've specified the filenames right, either in a
+context diff header, or with an Index: line.
+If you are patching something in a subdirectory, be sure to tell the patch
+user to specify a 
+.B \-p
+switch as needed.
+Third, you can create a file by sending out a diff that compares a
+null file to the file you want to create.
+This will only work if the file you want to create doesn't exist already in
+the target directory.
+Fourth, take care not to send out reversed patches, since it makes people wonder
+whether they already applied the patch.
+Fifth, while you may be able to get away with putting 582 diff listings into
+one file, it is probably wiser to group related patches into separate files in
+case something goes haywire.
+.SH DIAGNOSTICS
+Too many to list here, but generally indicative that
+.I patch
+couldn't parse your patch file.
+.PP
+The message \*(L"Hmm...\*(R" indicates that there is unprocessed text in
+the patch file and that
+.I patch
+is attempting to intuit whether there is a patch in that text and, if so,
+what kind of patch it is.
+.PP
+.I Patch
+will exit with a non-zero status if any reject files were created.
+When applying a set of patches in a loop it behooves you to check this
+exit status so you don't apply a later patch to a partially patched file.
+.SH CAVEATS
+.I Patch
+cannot tell if the line numbers are off in an ed script, and can only detect
+bad line numbers in a normal diff when it finds a \*(L"change\*(R" or
+a \*(L"delete\*(R" command.
+A context diff using fuzz factor 3 may have the same problem.
+Until a suitable interactive interface is added, you should probably do
+a context diff in these cases to see if the changes made sense.
+Of course, compiling without errors is a pretty good indication that the patch
+worked, but not always.
+.PP
+.I Patch
+usually produces the correct results, even when it has to do a lot of
+guessing.
+However, the results are guaranteed to be correct only when the patch is
+applied to exactly the same version of the file that the patch was
+generated from.
+.SH BUGS
+Could be smarter about partial matches, excessively \&deviant offsets and
+swapped code, but that would take an extra pass.
+.PP
+If code has been duplicated (for instance with #ifdef OLDCODE ... #else ...
+#endif),
+.I patch
+is incapable of patching both versions, and, if it works at all, will likely
+patch the wrong one, and tell you that it succeeded to boot.
+.PP
+If you apply a patch you've already applied,
+.I patch
+will think it is a reversed patch, and offer to un-apply the patch.
+This could be construed as a feature.
+.rn }` ''
Index: /trunk/minix/man/man1/playwave.1
===================================================================
--- /trunk/minix/man/man1/playwave.1	(revision 9)
+++ /trunk/minix/man/man1/playwave.1	(revision 9)
@@ -0,0 +1,16 @@
+.TH PLAYWAVE 1
+.SH NAME
+playwave \- play an audio file in MicroSoft PCM wave format
+.SH SYNOPSIS
+\fBplaywave\fP [\-\fBi\fP] file 
+.SH DESCRIPTION
+\fBPlaywave\fP writes the samples in a wave file to \fI/dev/audio\fP.
+The wave file must be in Microsoft PCM format.
+.SH OPTIONS
+.IP \-i 
+display information about wave file
+.SH BUGS
+The highest sample rate that can be used depends on the speed of the system 
+and the size of the DMA buffer used in the driver. (/usr/src/kernel/sb16.h)
+.SH AUTHOR
+Michel R. Prevenier (mrpreve@cs.vu.nl)
Index: /trunk/minix/man/man1/postmort.1
===================================================================
--- /trunk/minix/man/man1/postmort.1	(revision 9)
+++ /trunk/minix/man/man1/postmort.1	(revision 9)
@@ -0,0 +1,37 @@
+.TH POSTMORT 1
+.SH NAME
+postmort \- perform post-mortem on PC MINIX 3 core files
+.SH SYNOPSIS
+\fBpostmort\fR [\fB\-dpt\fR] \fB\-c \fIcorefile \fB\-s \fIsymbfile\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-c" "Use the named corefile"
+.FL "\-d" "Dump all text symbols and segment data"
+.FL "\-p" "Display the kernel process table"
+.FL "\-s" "Use the named symbol file"
+.FL "\-t" "Display a stack backtrace"
+.SH EXAMPLES
+.EX "postmort" "display the data from the file 'core'"
+.SH DESCRIPTION
+.PP
+.I Postmort
+does a simple static analysis of a PC MINIX 3 core file;
+By default, it looks for the
+file 'core' in the local directory and loads that for analysis; it
+also searches for the file 'symbol.out', and if that fails 'a.out',
+expecting them to contain symbol information for the core file.
+It is not a fatal error if the symbol files don't exist.
+.PP
+The stack backtrace is slightly tricky, and may go on longer
+than is really justified, since there's no easy way for it to
+know when to stop.  Treat its results with caution.
Index: /trunk/minix/man/man1/pr.1
===================================================================
--- /trunk/minix/man/man1/pr.1	(revision 9)
+++ /trunk/minix/man/man1/pr.1	(revision 9)
@@ -0,0 +1,37 @@
+.TH PR 1
+.SH NAME
+pr \- print a file
+.SH SYNOPSIS
+\fBpr\fR [\fB\-Mfnt\fR]\fR [\fB\-h \fIn\fR]  [\fB\-l \fIn\fR]  [\fB\-w \fIn\fR] [\fB\-\fRcolumns\fR] [\fB+\fIpage\fR] [\fIfile\fR] ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-M" "Use MINIX style line number"
+.FL "\-f" "Do not fold long lines"
+.FL "\-h" "Take next argument as page header"
+.FL "\-l" "Sets page length in lines"
+.FL "\-n" "Number the output lines"
+.FL "\-t" "Do not print page header or trailer"
+.FL "\-w" "Sets line length in characters"
+.SH EXAMPLES
+.EX "pr \-w85 \-l60 file" "Use 85 character line, 60 line page"
+.EX "pr \-3 file" "List \fIfile\fP three columns to a page"
+.EX "pr +4 file" "Start printing with page 4"
+.SH DESCRIPTION
+.PP
+.I Pr
+formats one or more files for printing.
+If no files are specified, \fIstdin\fR is printed.
+Options are provided for setting the width and height of the page, the
+number of columns to use (default 1), and the page to start with, among others.
+.SH "SEE ALSO"
+.BR lp (1).
Index: /trunk/minix/man/man1/prep.1
===================================================================
--- /trunk/minix/man/man1/prep.1	(revision 9)
+++ /trunk/minix/man/man1/prep.1	(revision 9)
@@ -0,0 +1,27 @@
+.TH PREP 1
+.SH NAME
+prep \- prepare a text file for statistical analysis
+.SH SYNOPSIS
+\fBprep\fR [\fIfile\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "prep infile >outfile" "Prepare \fIinfile\fR"
+.SH DESCRIPTION
+.PP
+\fIPrep\fR strips off most of the troff commands from a text file and then
+outputs all the words, one word per line, in the order they occur in the file.
+This file can then be sorted and compared to a dictionary (as a spelling
+checker), or used for statistical analyses.
+.SH "SEE ALSO"
+.BR nroff (1),
+.BR spell (1).
Index: /trunk/minix/man/man1/ps.1
===================================================================
--- /trunk/minix/man/man1/ps.1	(revision 9)
+++ /trunk/minix/man/man1/ps.1	(revision 9)
@@ -0,0 +1,83 @@
+.TH PS 1
+.SH NAME
+ps \- process status
+.SH SYNOPSIS
+\fBps \fR[\fR[\fB\-\fR]\fBalx\fR] 
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-a" "Print all processes with controlling terminals"
+.FL "\-l" "Give long listing"
+.FL "\-x" "Include processes without a terminal"
+.SH EXAMPLES
+.EX "ps " "Show user's own processes in short format"
+.EX "ps \-axl" "Print all processes and tasks in long format"
+.EX "ps \axl" "Same -- the '\-' is optional"
+.SH DESCRIPTION
+.PP
+\fIPs\fR prints the status of active processes.  Normally only the caller's own
+processes are listed in short format (the PID, TTY, TIME and CMD fields as
+explained below).  The long listing contains:
+.PP
+.ta 0.5i 1.0i
+  F	Kernel flags:
+		001: free slot
+		002: no memory map
+		004: sending;
+		010: receiving
+		020: inform on pending signals
+		040: pending signals
+		100: being traced.
+.PP
+  S
+	State:
+		R: runnable
+		W: waiting (on a message)
+		S: sleeping (i.e.,suspended on MM or FS)
+		Z: zombie
+		T: stopped
+.PP
+  UID, PID, PPID, PGRP
+	The user, process, parent process and process group ID's.
+.PP
+  SZ
+	Size of the process in kilobytes.
+.PP
+  RECV
+	Process/task on which a receiving process is waiting or sleeping.
+.PP
+  TTY	
+	Controlling tty for the process.
+.PP
+  TIME
+	Process' cumulative (user + system) execution time.
+.PP
+  CMD	Command line arguments of the process.
+.PP
+.PP
+The files \fI/dev/{mem,kmem}\fR are used to read the system tables and command
+line arguments from.  Terminal names in \fI/dev\fR are used to generate the 
+mnemonic names in the TTY column, so \fIps\fR is independent of terminal naming
+conventions.
+.SH NOTES
+The '\-' option prefix is not required.
+For marginal compatibility with System V usage, the hidden option
+.B \-e
+means the same as
+.BR \-ax ,
+and
+.B \-f
+is the same as
+.BR \-l .
+
+.\" edited by ASW 2004-12-14
+
Index: /trunk/minix/man/man1/pwd.1
===================================================================
--- /trunk/minix/man/man1/pwd.1	(revision 9)
+++ /trunk/minix/man/man1/pwd.1	(revision 9)
@@ -0,0 +1,23 @@
+.TH PWD 1
+.SH NAME
+pwd \- print working directory
+.SH SYNOPSIS
+\fBpwd\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "pwd     " "Print the name of the working directory"
+.SH DESCRIPTION
+.PP
+The full path name of the current working directory is printed.
+.SH "SEE ALSO"
+.BR getcwd (3).
Index: /trunk/minix/man/man1/rcp.1
===================================================================
--- /trunk/minix/man/man1/rcp.1	(revision 9)
+++ /trunk/minix/man/man1/rcp.1	(revision 9)
@@ -0,0 +1,90 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)rcp.1c	6.4 (Berkeley) 5/12/86
+.\"
+.TH RCP 1 "May 12, 1986"
+.UC 5
+.SH NAME
+rcp \- remote file copy
+.SH SYNOPSIS
+.B rcp
+.RB [ \-p ]
+.I file1 file2
+.br
+.B rcp
+.RB [ \-pr ]
+.I file
+\&...
+.I directory
+.SH DESCRIPTION
+.B Rcp
+copies files between machines.  Each
+.I file
+or
+.I directory
+argument is either a remote file name of the
+form ``rhost:path'', or a local file name (containing no `:' characters,
+or a `/' before any `:'s).
+.PP
+If the
+.B \-r
+option
+is specified and any of the source files are directories,
+.B rcp
+copies each subtree rooted at that name; in this case
+the destination must be a directory.
+.PP
+By default, the mode and owner of
+.I file2
+are preserved if it already existed; otherwise the mode of the source file
+modified by the
+.BR umask (2)
+on the destination host is used.
+The
+.B \-p
+option causes
+.B rcp
+to attempt to preserve (duplicate) in its copies the modification
+times and modes of the source files, ignoring the
+.BR umask .
+.PP
+If
+.I path
+is not a full path name, it is interpreted relative to
+your login directory on 
+.IR rhost .
+A 
+.I path
+on a remote host may be quoted (using \e, ", or \(aa)
+so that the metacharacters are interpreted remotely.
+.PP
+.B Rcp
+does not prompt for passwords; your current local user name
+must exist on
+.I rhost
+and allow remote command execution via
+.BR rsh (1).
+.PP
+.B Rcp
+handles third party copies, where neither source nor target files
+are on the current machine.
+Hostnames may also take the form ``rname@rhost'' to use
+.I rname
+rather than the current user name on the remote host.
+The destination hostname may also take the form ``rhost.rname'' to
+support destination machines that are running 4.2BSD
+versions of
+.BR rcp .
+.SH SEE ALSO
+.BR cp (1),
+.BR ftp (1),
+.BR rsh (1),
+.BR rlogin (1).
+.SH BUGS
+Doesn't detect all cases where the target of a copy might
+be a file in cases where only a directory should be legal.
+.br
+Is confused by any output generated by commands in a
+\&.profile, or \&.*shrc file on the remote host.
Index: /trunk/minix/man/man1/readall.1
===================================================================
--- /trunk/minix/man/man1/readall.1	(revision 9)
+++ /trunk/minix/man/man1/readall.1	(revision 9)
@@ -0,0 +1,36 @@
+.TH READALL 1
+.SH NAME
+readall \- read a device quickly to check for bad blocks
+.SH SYNOPSIS
+\fBreadall\fR [\fB\-bt\fR] \fIfile\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-b" "Produce shell script on \fIstdout\fR that calls \fIbadblocks\fR"
+.FL "\-t" "Just print device size"
+.SH EXAMPLES
+.EX "readall /dev/hd0" "Read all of \fI/dev/hd0\fR"
+.EX "readall -b /dev/hd1 >s" "Generate shell script on \fIs\fR"
+.SH DESCRIPTION
+.PP
+\fIReadall\fR reads all of the named device in large chunks.  
+It reports about blocks that it cannot read.  
+Unlike \fIdiskcheck\fR, it does not attempt to write on
+the disk, making it safer to use when one is worried about a sick system.
+When the \fB\-b\fR flag is given, the output is a shell script that
+calls the \fIbadblocks\fR program to marked all the bad blocks.
+Whenever installing 
+\s-1MINIX 3\s-1,
+it is wise to run \fIreadall\fR with the \fB\-b\fR flag first on all
+the hard disks.
+.SH "SEE ALSO"
+.BR badblocks (8).
Index: /trunk/minix/man/man1/readfs.1
===================================================================
--- /trunk/minix/man/man1/readfs.1	(revision 9)
+++ /trunk/minix/man/man1/readfs.1	(revision 9)
@@ -0,0 +1,31 @@
+.TH READFS 1
+.SH NAME
+readfs \- read a MINIX 3 file system
+.SH SYNOPSIS
+\fBreadfs\fR [\fB\-il\fR] \fIblock_special\fR [\fIdir\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-i" "Give information about the file, but do not extract files"
+.FL "\-l" "List the files extracted on standard output"
+.SH EXAMPLES
+.EX "readfs \-l /dev/fd0" "List contents of diskette"
+.SH DESCRIPTION
+.PP
+\fIReadfs\fR reads a diskette containing a 
+\s-1MINIX 3\s-1
+file system.  It can
+extract all the files from it, give a listing of them, or both.  The files
+extracted can be put in a user-specified directory (default: current
+directory).  If subdirectories are needed, they will be created automatically.
+.SH "SEE ALSO"
+.BR mkproto (1).
Index: /trunk/minix/man/man1/recwave.1
===================================================================
--- /trunk/minix/man/man1/recwave.1	(revision 9)
+++ /trunk/minix/man/man1/recwave.1	(revision 9)
@@ -0,0 +1,20 @@
+.TH RECWAVE 1
+.SH NAME
+recwave \- record an audio file in MicroSoft PCM wave format
+.SH SYNOPSIS
+\fBrecwave\fP [\-\fBb\fP \-\fBs\fP \-\fBr\fP] file 
+.SH DESCRIPTION
+\fBRecwav\fP takes samples from \fI/dev/audio\fP and writes them to \fIfile\fP
+in Microsoft PCM wave format.
+.SH OPTIONS
+.IP \-b 
+number of bits to use for one sample. Must be 8 or 16, default is 8
+.IP \-s 
+enable stereo sampling. 0 = mono (default), 1 = stereo 
+.IP \-r 
+sample rate in samples/sec. 4000 - 44100 (default 22050) 
+.SH BUGS
+The highest sample rate that can be used depends on the speed of the system 
+and the size of the DMA buffer used in the driver. (/usr/src/kernel/sb16.h)
+.SH AUTHOR
+Michel R. Prevenier (mrpreve@cs.vu.nl)
Index: /trunk/minix/man/man1/ref.1
===================================================================
--- /trunk/minix/man/man1/ref.1	(revision 9)
+++ /trunk/minix/man/man1/ref.1	(revision 9)
@@ -0,0 +1,88 @@
+.TH REF 1
+.SH NAME
+ref - Display a C function header
+.SH SYNOPSIS
+\fBref\fR [-t] [-c \fIclass\fR]... [-f \fIfile\fR]... \fItag\fR
+.SH DESCRIPTION
+\fIref\fP quickly locates and displays the header of a function.
+To do this, \fIref\fR
+looks in the "tags" file for the line that describes the function, and then 
+scans the source file for the function.
+When it locates the function, it displays an introductory comment
+(if there is one), the function's declaration, and the declarations of all
+arguments.
+.SH "SEARCH METHOD"
+.PP
+\fIref\fR uses a fairly sophisticated tag look-up algorithm.
+If you supply a filename via \fB-f\fR \fIfile\fR, then elvis first scans
+the tags file for a static tag from that file.
+This search is limited to the tags file in the current directory.
+.PP
+If you supply a classname via \fB-c\fR \fIclass\fR, then elvis searches
+for a tag from that class.
+This search is not limited to the current directory;
+You can supply a list of directories in the environment variable \fITAGPATH\fR,
+and \fIref\fR will search through the "tags" file in each directory until it finds
+a tag in the desired class.
+.PP
+If that fails, \fIref\fR will then try to look up an ordinary global tag.
+This search checks all of the directories listed in \fITAGPATH\fR, too.
+.PP
+If you've given the \fB-t\fR flag, then \fIref\fR will simply output the tag line that
+it found, and then exit.
+Without \fB-t\fR, though, \fIref\fR will search for the tag line.
+It will try to open the source file, which should be in the same directory
+as the tags file where the tag was discovered.
+If the source file doesn't exist, or is unreadable, then \fIref\fR will try to open
+a file called "\fIrefs\fR" in that directory.
+Either way, \fIref\fR will try to locate the tag, and display whatever it finds.
+.SH "INTERACTION WITH ELVIS"
+.PP
+\fIref\fP is used by \fIelvis\fR' shift-K command.
+If the cursor is located on a word such as "splat", in the file "foo.c",
+then \fIelvis\fR will invoke \fIref\fR with the command "ref -f foo.c splat".
+.PP
+If \fIelvis\fR has been compiled with the -DEXTERNAL_TAGS flag, then \fIelvis\fR will
+use \fIref\fR \fB\fRto scan the tags files.
+This is slower than the built-in tag searching, but it allows \fIelvis\fR to access
+the more sophisticated tag lookup provided by \fIref\fR.
+Other than that, external tags should act exactly like internal tags.
+.SH OPTIONS
+.IP \fB-t\fR
+Output tag info, instead of the function header.
+.IP "\fB-f\fR \fIfile\fR"
+The tag might be a static function in \fIfile\fR.
+You can use several -f flags to have \fIref\fR consider static tags from more than one file.
+.IP "\fB-c\fR \fIclass\fR"
+The tag might be a member of class \fIclass\fR.
+You can use several -c flags to have \fIref\fR consider tags from more than one class.
+.SH FILES
+.IP \fBtags\fR
+List of function names and their locations, generated by \fIctags\fR.
+.IP \fBrefs\fR
+Function headers extracted from source files (optional).
+.SH ENVIRONMENT
+.IP \fBTAGPATH\fR
+List of directories to be searched.
+The elements in the list are separated by either
+semicolons (for MS-DOS, Atari TOS, and AmigaDos), or
+by colons (every other operating system).
+For each operating system, \fIref\fR has a built-in default which is probably
+adequate.
+.SH NOTES
+.PP
+You might want to generate a "tags" file the directory that contains the
+source code for standard C library on your system.
+If licensing restrictions prevent you from making the library source readable
+by everybody, then you can have \fIctags\fR generate a "refs" file,
+and make "refs" readable by everybody.
+.PP
+If your system doesn't come with the library source code, then perhaps you
+can produce something workable from the \fIlint\fR libraries.
+.SH "SEE ALSO"
+elvis(1), ctags(1)
+.SH AUTHOR
+.nf
+Steve Kirkendall
+kirkenda@cs.pdx.edu
+.fi
Index: /trunk/minix/man/man1/remsync.1
===================================================================
--- /trunk/minix/man/man1/remsync.1	(revision 9)
+++ /trunk/minix/man/man1/remsync.1	(revision 9)
@@ -0,0 +1,184 @@
+.TH REMSYNC 1
+.SH NAME
+remsync - remotely synchronize file trees
+.SH SYNOPSIS
+.B remsync
+.B \-sxv
+.I tree
+.RI [ state-file ]
+.br
+.B remsync
+.B \-duxvD
+.I tree
+.RI [ state-file
+.RI [ diff-file ]]
+.br
+.B remsync
+.RB [ \-xv ]
+.I tree
+.RI [ diff-file ]
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Remsync
+synchronizes file trees of distant machines, i.e. machines that do not have
+a fast network between them.  It accomplishes this in three steps:
+.PP
+.RS
+Create a state file containing a description of the machine to be updated.
+.RE
+.PP
+.RS
+Compute a file of differences on the source machine using the state file to
+compare the two file trees.
+.RE
+.PP
+.RS
+Update the target machine using the data in the differences file.
+.RE
+.PP
+This process requires that you move two files, a state file from the target
+machine to the source machine, and a differences file from the source
+machine to the target machine.  The state file is an ASCII file that may be
+edited, usually to make
+.B remsync
+ignore some files or file trees.
+.PP
+The argument
+.I tree
+may be a single file or a directory.  A directory is traversed recursively.
+The
+.I state-file
+and
+.I diff-file
+arguments may be of any file type.  The differences file contains an end
+marker, so it may be followed by trailing junk.  Standard input or
+output is used if these arguments are omitted or replaced by a minus
+sign.
+.SS "State file format"
+A state file has a line for each file in a tree.  A line looks like this
+formally for a simple file:
+.PP
+.RS
+.I "name mode owner group length date"
+.RI [ link-number
+.RB [ last ]]
+.RE
+.PP
+The best way to show how each type of file is represented is by example:
+.PP
+.RS
+.nf
+.ta +10 +8 +4 +4 +6 +12 +4
+/	d755	0	0
+bin	d755	2	0
+.in +2
+[	644	2	0	233	759160857	1
+cat	755	2	0	3772	768742021
+test	755	2	0	233	759160857	1	last
+.in -2
+dev	d755	0	0
+.in +2
+fd0	b666	0	0	200
+console	c600	10	0	400
+sd2	b600	0	0	a02
+fifo	p700	2	0
+.in -2
+opt	->	usr/opt
+usr	ignore (Cross-device link)
+.fi
+.RE
+.PP
+The root of the tree is always represented by a /, no matter what type of
+file it may be.  Directory entries of the root follow at the same level.
+Files in subdirectories are indented by two spaces.  (Eight spaces are
+replaced by a TAB.)  Normal files have their length and modified time in the
+state file, devices have their device number in hex, etc.  If files are hard
+linked to each other then they all get an extra "link number" to bind them
+together.  The last link is marked with the word
+.BR last .
+.PP
+One usually only modifies a state file to ignore differences between two
+files.  One does this by replacing the file attributes with the word
+.BR ignore .
+.RB ( Remsync
+generates this keyword too, with the reason why added in parentheses.)
+.SH OPTIONS
+.TP
+.B \-s
+Generate a state file.
+.TP
+.B \-d
+Generate a differences file.  (The default is to apply a differences file.)
+.TP
+.B \-u
+Only add new files or update files with newer versions.
+.TP
+.B \-x
+Do not cross device boundaries.  This allows one to operate on the root file
+system for instance ignoring the
+.B /usr
+file system.
+.TP
+.B \-D
+Debug differences file generation.  With this flag no file contents are
+added to the differences file.  The result is then human readable.
+.TP
+.B \-v
+Lists the commands added to the differences file, or the actions done
+applying a differences file.  The output looks like \s-2UNIX\s+2 commands
+except for the words "add", "restore" and "update" indicating addition of a
+new file, replacing a file with an older version, or replacement by a newer
+version.
+.SH EXAMPLES
+Actions taken by the author to update his notebook "finiah" from his main
+machine "darask":
+.PP
+.RS
+.nf
+finiah# remsync -s /usr /tmp/finiah.state
+.SP
+Edit the state file to ignore .Xauthority files and /usr/var.
+.SP
+finiah# tar cvf /dev/fd0 /tmp/finiah.state
+.SP
+darask# tar xvf /dev/fd0
+.br
+darask# remsync -dv /usr /tmp/finiah.state | vol 1440 /dev/fd0
+.SP
+finiah# vol 1440 /dev/fd0 | remsync -v /usr
+.fi
+.RE
+.PP
+One could add a file compression/decompression program between
+.B remsync
+and
+.BR vol ,
+to reduce the number of floppies to move about, but that actually slows
+things down!  (Note that one only needs to shuffle two floppies about if the
+two machines are adjacent.  To update a remote machine it does make sense to
+use compression to reduce the number of floppies to carry.)
+.SH "SEE ALSO"
+.BR synctree (1),
+.BR vol (1),
+.BR tar (1).
+.SH NOTES
+Nothing stops you from using
+.B remsync
+over a fast network of course.
+.B Synctree
+can be a bit tedious if you only want to ignore a few files.  Editing a
+state file is then easier.
+.SH BUGS
+Files are overwritten, not removed, when they are updated.  This means
+that links outside the tree are also updated.  The less desirable
+alternative to this is to break the link before the update.
+.PP
+The verbose option may say that a link is to be created when making a
+differences file.  The link is often already there when the update takes
+place, so no action is taken, and thus no talk about it.  So you may miss a
+few mutterings about links if you compare the messages.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/rget.1
===================================================================
--- /trunk/minix/man/man1/rget.1	(revision 9)
+++ /trunk/minix/man/man1/rget.1	(revision 9)
@@ -0,0 +1,169 @@
+.TH RGET 1
+.SH NAME
+rget, rput \- network pipe
+.SH SYNOPSIS
+.B rget
+.RB [ \-lcio ]
+.RB [ \-h
+.IR host ]
+.I key
+.RI [ command
+.RI [ arg " ...]]"
+.br
+.B rput
+.RB [ \-lcio ]
+.RB [ \-h
+.IR host ]
+.I key
+.RI [ command
+.RI [ arg " ...]]"
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.de XS	\" Example start
+.SP
+.in +4m
+.nf
+..
+.de XE	\" Example end
+.fi
+.in -4m
+.SP
+..
+.B Rput
+and
+.B rget
+set up a TCP/IP channel to connect two processes together.  They can looked
+upon as a remote pipe.  Consider the well known method of copying a
+directory tree with
+.BR tar :
+.XS
+(cd src && tar cf \- .) | (cd dst && tar xfp \-)
+.XE
+If the directory tree is to be copied to another machine then one can
+use the following command on the source machine:
+.XS
+cd src && rput foo tar cf \- .
+.XE
+And on the destination machine:
+.XS
+cd dst && rget \-h \fIsource-machine\fP foo tar xfp \-
+.XE
+The
+.I key
+is either a port number in C style decimal, octal or hex, or a random string
+that is hashed to a port number.
+.B Rput
+uses this port number to open a TCP socket that
+.B rget
+using the same
+.I key
+can connect to.
+It is customary to start
+.B rput
+first, although
+.B rget
+will retry for 2 minutes trying to connect to the remote
+.BR rput.
+.PP
+After the connection is established either utility will execute
+.I command
+with the given arguments with the TCP channel as either standard output
+(rput) or standard input (rget).
+.B Rput
+and
+.B rget
+do not stay around for the command to finish, they simply overlay themselves
+with the command.  If no command is given then they will themselves copy
+standard input into the TCP channel (rput), or output from the TCP channel
+to standard output (rget).  So these two commands have the same effect:
+.XS
+rput foo tar cf \- .
+tar cf \- . | rput foo
+.XE
+The second form has two processes copying data instead of just
+.B tar
+directly writing its output into the TCP channel.  There is a better way to
+waste processor cycles, namely to save bandwidth:
+.XS
+cd src && tar cf \- . | rput foo compress
+.SP
+cd dst && rget \-h \fIsource-machine\fP foo uncompress | tar xfp \-
+.XE
+.B Rput
+and
+.B rget
+can be very useful in the windowed environments we use these days.  The
+.B rput
+can be typed into the window that has a shell running on one machine, and
+the
+.B rget
+is then typed into the window that has a shell running on another machine.
+This is easier than one of the two well known forms that use
+.BR rsh :
+.XS
+cd src && tar cf \- . | rsh dest-machine "cd dst && tar xfp \-"
+.SP
+cd dst && rsh source-machine "cd src && tar cf \- ." | tar xfp \-
+.XE
+Especially since these forms require that one must be able to use
+.B rsh
+without a password, which may not always be the case.
+.PP
+The
+.I key
+can be any string of characters of any length.  If its a number then it is
+used directly as the port number.  Otherwise the characters binary values
+are multiplied together, bit 15 is set and the result is truncated to 16
+bits to make it a port number in the anonymous port space (32768 \- 65535).
+The port may be in-use on the source machine, but there is a small chance
+of this happening, and if so simply choose another key.  (So if you use
+.B rput
+and
+.B rget
+in an unattended script then you should reserve a port number, otherwise
+a connection can't be guaranteed.)
+.SH OPTIONS
+.TP
+.B \-lcio
+These flags allow one to reverse the default connect/listen or input/output
+direction of
+.BR rput
+and
+.BR rget .
+Reversing the connection may be necessary if one of the two systems filters
+out connections to unknown ports.  For example:
+.XS
+rput \-c \-h \fIdestination-machine\fP foo tar cf \- .
+.SP
+rget \-l foo tar xfp \-
+.XE
+The
+.B \-io
+options can be used to choose which of standard input or output should be
+tied to the socket.  It's even possible to tie both input and output to the
+socket with
+.BR \-io,
+but only when executing a command.  This is probably the only use for these
+options, because one usually chooses the direction with the mnemonic put/get
+names.
+.TP
+.BI \-h " host"
+The name of the remote host that a connection must be made to.  It must be
+used with the program that is doing the connect, usually
+.BR rget .
+This option is currently mandatory.  The author is planning to increase
+ease of use by letting the programs find each other with UDP broadcasts
+or multicasts.
+.SH "SEE ALSO"
+.BR rsh (1).
+.SH DIAGNOSTICS
+.TP 5
+rput: Address in use
+If the port computed out of
+.I key
+is already in use.
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man1/rlogin.1
===================================================================
--- /trunk/minix/man/man1/rlogin.1	(revision 9)
+++ /trunk/minix/man/man1/rlogin.1	(revision 9)
@@ -0,0 +1,87 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)rlogin.1c	6.8 (Berkeley) 5/12/86
+.\"
+.TH RLOGIN 1 "May 12, 1986"
+.UC 5
+.SH NAME
+rlogin \- remote login
+.SH SYNOPSIS
+.B rlogin
+.RB [ \-8EL ]
+.RB [ \-e
+.IR char ]
+.RB [ \-l
+.IR username ]
+.I rhost
+.br
+.I rhost
+.RB [ \-8EL ]
+.RB [ \-e
+.IR char ]
+.RB [ \-l
+.IR username ]
+.SH DESCRIPTION
+.B Rlogin
+connects your terminal on the current local host system
+.I lhost
+to the remote host system
+.I rhost.
+.PP
+Each host has a file
+.B /etc/hosts.equiv
+which contains a list of \fIrhost\fR's with which it shares account names.
+(The host names must be the standard names as described in
+.BR rsh (1).)
+When you
+.B rlogin
+as the same user on an equivalent host, you don't need
+to give a password.
+Each user may also have a private equivalence list in a file \&.rhosts
+in his login directory.  Each line in this file should contain an \fIrhost\fP
+and a \fIusername\fP separated by a space, giving additional cases
+where logins without passwords are to be permitted.
+If the originating user is not equivalent to the remote user, then
+a login and password will be prompted for on the remote machine as in
+.BR login (1).
+To avoid some security problems, the \&.rhosts file must be owned by
+either the remote user or root.
+.PP
+The remote terminal type is the same as your local
+terminal type (as given in your environment TERM variable).
+The terminal or window size is also copied to the remote system
+if the server supports the option,
+and changes in size are reflected as well.
+All echoing takes place at the remote site, so that (except for
+delays) the rlogin is transparent.  Flow control via ^S and ^Q and
+flushing of input and output on interrupts are handled properly.
+The optional argument
+.B \-8
+allows an eight-bit input data path at all times;
+otherwise parity bits are stripped except when the remote side's
+stop and start characters are other than ^S/^Q.
+The argument
+.B \-L
+allows the rlogin session to be run in litout mode.
+A line of the form ``~.'' disconnects from the remote host, where
+``~'' is the escape character.
+Similarly, the line ``~^Z'' (where ^Z, control-Z, is the suspend character)
+will suspend the rlogin session.
+Substitution of the delayed-suspend character (normally ^Y)
+for the suspend character suspends the send portion of the rlogin,
+but allows output from the remote system.
+A different escape character may
+be specified by the
+.B \-e
+option.
+There is no space separating this option flag and the argument
+character.  With the
+.B \-E
+option the escape can be turned off.
+.SH SEE ALSO
+.BR rsh (1),
+.BR rhosts (5).
+.SH BUGS
+More of the environment should be propagated.
Index: /trunk/minix/man/man1/rmdir.1
===================================================================
--- /trunk/minix/man/man1/rmdir.1	(revision 9)
+++ /trunk/minix/man/man1/rmdir.1	(revision 9)
@@ -0,0 +1,27 @@
+.TH RMDIR 1
+.SH NAME
+rmdir \- remove a directory
+.SH SYNOPSIS
+\fBrmdir \fIdirectory ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "rmdir /user/ast/foobar" "Remove directory \fIfoobar\fP"
+.EX "rmdir /user/ast/f*" "Remove 0 or more directories"
+.SH DESCRIPTION
+.PP
+The specified directories are removed.
+Ordinary files are not removed.
+The directories must be empty.
+.SH "SEE ALSO"
+.BR mkdir (1),
+.BR rmdir (2).
Index: /trunk/minix/man/man1/rsh.1
===================================================================
--- /trunk/minix/man/man1/rsh.1	(revision 9)
+++ /trunk/minix/man/man1/rsh.1	(revision 9)
@@ -0,0 +1,94 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)rsh.1c	6.1 (Berkeley) 4/29/85
+.\"
+.TH RSH 1 "April 29, 1985"
+.UC 5
+.SH NAME
+rsh \- remote shell
+.SH SYNOPSIS
+.B rsh
+.RB [ \-n ]
+.RB [ \-l
+.IR username ]
+.I host
+.RI [ command ]
+.br
+.I host
+.RB [ \-n ]
+.RB [ \-l
+.IR username ]
+.RI [ command ]
+.SH DESCRIPTION
+.B Rsh
+connects to the specified
+.IR host ,
+and executes the specified \fIcommand\fR.
+.B Rsh
+copies its standard input to the remote command, the standard
+output of the remote command to its standard output, and the
+standard error of the remote command to its standard error.
+Interrupt, quit and terminate signals are propagated to the remote
+command; \fBrsh\fP normally terminates when the remote command does.
+.PP
+The remote username used is the same as your local username,
+unless you specify a different remote name with the
+.B \-l
+option.
+This remote name must be equivalent (in the sense of
+.BR rlogin (1))
+to the originating account; no provision
+is made for specifying a password with a command.
+.PP
+If you omit
+.IR command ,
+then instead of executing a single command, you will be logged in
+on the remote host using
+.BR rlogin (1).
+.PP
+Shell metacharacters which are not quoted are interpreted
+on local machine, while quoted metacharacters are interpreted on
+the remote machine.
+Thus the command
+.PP
+.RS
+rsh otherhost cat remotefile >> localfile
+.RE
+.PP
+appends the remote file
+.I remotefile
+to the localfile
+.IR localfile ,
+while
+.PP
+.RS
+rsh otherhost cat remotefile ">>" otherremotefile
+.RE
+.PP
+appends
+.I remotefile
+to
+.IR otherremotefile .
+.SH OPTIONS
+.TP
+.BI \-l " username"
+Specify the remote user name.
+.TP
+.B \-n
+Connect standard input of the remote command to /dev/null.  Do this if
+.B rsh
+should not inadvertently read from standard input.
+.SH SEE ALSO
+.BR rcp (1),
+.BR rlogin (1),
+.BR rhosts (5).
+.SH BUGS
+You cannot run an interactive command
+(like
+.BR rogue (6)
+or
+.BR vi (1));
+use
+.BR rlogin (1).
Index: /trunk/minix/man/man1/rz.1
===================================================================
--- /trunk/minix/man/man1/rz.1	(revision 9)
+++ /trunk/minix/man/man1/rz.1	(revision 9)
@@ -0,0 +1,95 @@
+.TH RZ 1
+.SH NAME
+rz \- receive a file using the zmodem protocol
+.SH SYNOPSIS
+\fBrz\fR [\-\fBabepqvy\fR]\fR [\fB\-t \fItimeout\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-a" "CP/M to UNIX conventions"
+.FL "\-b" "Binary file"
+.FL "\-e" "Escape for all control characters"
+.FL "\-p" "Protect file if it already exists"
+.FL "\-q" "Quiet; opposite of verbose"
+.FL "\-t" "Set \fItimeout\fR in tenths of a second"
+.FL "\-v" "Verbose; opposite of quiet"
+.FL "\-y" "Yes, clobber existing files"
+.SH EXAMPLES
+.EX "rz </dev/tty01 >/dev/tty01" "Receive a file"
+.SH DESCRIPTION
+.PP
+The XMODEM, YMODEM, and ZMODEM family of file transfer programs are widely
+used on personal computers.
+\s-1MINIX 3\s-1
+supports ZMODEM, the most advanced of the set.
+The programs \fIsz\fR and \fIrz\fR are used for sending and receiving,
+respectively.
+.PP
+\fIRz\fR and \fIsz\fR are programs that uses an error correcting protocol to 
+transfer files over a dial-in serial port from a variety of programs 
+running under various operating systems.
+\fIRz\fR (Receive ZMODEM) receives files with the ZMODEM batch
+protocol.  Pathnames are supplied by the sending program,
+and directories are made if necessary (and possible).
+The meanings of the available options are:
+.in +0.25i
+.ti -0.25i
+.B \-a
+.br
+Convert files to
+\s-2UNIX\s+2
+conventions by stripping carriage
+returns and all characters beginning with the first
+Control Z (CP/M end of file).
+.ti -0.25i
+.B \-b
+.br
+Binary (tell it like it is) file transfer override.
+.ti -0.25i
+.B \-c
+.br
+Request 16 bit CRC.  XMODEM file transfers default to 8
+bit checksum.  YMODEM and ZMODEM normally use 16 bit CRC.
+.ti -0.25i
+.B \-D
+.br
+Output file data to /dev/null; for testing. 
+.ti -0.25i
+.B \-e
+.br
+Force sender to escape all control characters; normally
+XON, XOFF, DLE, CR-@-CR, and Ctrl-X are escaped.
+.ti -0.25i
+.B \-p
+.br
+Protect: skip file if destination file exists.
+.ti -0.25i
+.B \-q
+.br
+Quiet suppresses verbosity.
+.ti -0.25i
+.B \-t
+.br
+Change timeout tenths of seconds (timeout follows flag).
+.ti -0.25i
+.B \-v 
+.br
+Verbose causes a list of file names to be appended to \fI/tmp/rzlog\fR. 
+More v's generate more output.
+.ti -0.25i
+.B \-y
+.br
+Yes, clobber any existing files with the same name.
+.in -0.25i
+.SH "SEE ALSO"
+.BR sz (1),
+.BR term (1).
Index: /trunk/minix/man/man1/sed.1
===================================================================
--- /trunk/minix/man/man1/sed.1	(revision 9)
+++ /trunk/minix/man/man1/sed.1	(revision 9)
@@ -0,0 +1,390 @@
+.TH sed 1 "November 19, 1995"
+.SH NAME
+sed \- the stream editor
+.SH SYNOPSIS
+.B sed
+.RB [ \-n ]
+.RB [ \-g ]
+.RB [ \-e
+.IR script ]
+.RB [ \-f
+.IR sfile ]
+.RI [ file " ...]"
+.SH DESCRIPTION
+Sed copies the named files (standard input default) to the standard
+output, edited according to a script of commands. 
+.P
+An
+.B \-e
+option supplies a single edit command from the next argument;
+if there are several of these they are executed in the order in which
+they appear. If there is just one
+.B \-e
+option and no
+.BR \-f "'s,"
+the
+.B \-e
+flag may be omitted.
+.P
+An
+.B \-f
+option causes commands to be taken from the file "sfile"; if
+there are several of these they are executed in the order in which
+they appear;
+.B \-e
+and
+.B \-f
+commands may be mixed.
+.P
+The
+.B \-g
+option causes
+.B sed
+to act as though every substitute command
+in the script has a
+.B g
+suffix.
+.P
+The
+.B \-n
+option suppresses the default output.
+.P
+A script consists of commands, one per line, of the following form:
+.PP
+	[address [, address] ] function [arguments]
+.PP
+Normally
+.B sed
+cyclically copies a line of input into a current text
+buffer, then applies all commands whose addresses select the buffer in
+sequence, then copies the buffer to standard output and clears it.
+.P
+The
+.B \-n
+option suppresses normal output (so that only
+.B p
+and
+.B w
+output is done).  Also, some commands
+.RB ( n ,
+.BR N )
+do their own line reads, and some others
+.RB ( d ,
+.BR D )
+cause all commands following in the script to be skipped (the
+.B D
+command also suppresses the clearing of the current text
+buffer that would normally occur before the next cycle).
+.P
+It is also helpful to know that there's a second buffer (called the `hold
+space' that can be copied or appended to or from or swapped with
+the current text buffer.
+.P
+An address is: a decimal numeral (which matches the line it numbers where line
+numbers start at 1 and run cumulatively across files), or a `$' that addresses
+the last line of input, or a context address, which is a `/regular
+expression/', in the style of
+.BR ed (1)
+modified thus:
+.P
+.TP 5
+(1)
+The escape sequence `\en' matches a newline embedded in the buffer,
+and `\et' matches a tab.
+.TP 5
+(2)
+A command line with no addresses selects every buffer.
+.TP 5
+(3)
+A command line with one address selects every buffer that matches
+that address.
+.TP 5
+(4)
+A command line with two addresses selects the inclusive range from
+the first input buffer that matches the first address through the
+next input buffer that matches the second.  (If the second address
+is a number less than or equal to the line number first selected,
+only one line is selected.)  Once the second address is matched
+.B sed
+starts looking for the first one again; thus, any number of these 
+ranges will be matched.
+.P
+The negation operator '!' can prefix a command to apply it to every
+line not selected by the address(es).
+.P
+In the following list of functions, the maximum number of addresses
+permitted for each function is indicated in parentheses.
+.P
+An argument denoted "text" consists of one or more lines, with all
+but the last ending with `\e' to hide the newline.
+.P
+Backslashes in text are treated like backslashes in the replacement
+string of an
+.B s
+command and may be used to protect initial whitespace (blanks and tabs)
+against the stripping that is done on every line of the script.
+.P
+An argument denoted "rfile" or "wfile" must be last on the command
+line.  Each wfile is created before processing begins.  There can be at
+most 10 distinct wfile arguments.
+.ta +\w'nm'u +\w'"command"m'u
+.TP 5
+a	"text"	(1)
+Append.  Place text on output before reading the next input line.
+.TP 5
+b	"label"	(2)
+Branch to the `:' command bearing the label.  If no label is  given,
+branch to the end of the script.
+.TP 5
+c	"text"	(2)
+Change.  Delete the current text buffer.  With 0 or 1 address, or at
+the end of a 2-address range, place text on the output.  Start the next
+cycle.
+.TP 5
+d		(2)
+Delete the current text buffer.  Start the next cycle.
+.TP 5
+D		(2)
+Delete the first line of the current text buffer (all chars up to the
+first newline).  Start the next cycle.
+.TP 5
+g		(2)
+Replace the contents of the current text buffer with the contents of
+the hold space.
+.TP 5
+G		(2)
+Append the contents of the hold space to the current text buffer.
+.TP 5
+h		(2)
+Copy the current text buffer into the hold space.
+.TP 5
+H		(2)
+Append a copy of the current text buffer to the hold space.
+.TP 5
+i	"text"	(1)
+Insert.  Place text on the standard output.
+.TP 5
+l		(2)
+List.  Sends the pattern space to standard output.  A "w" option may
+follow as in the
+.B s
+command below.  Non-printable characters expand to:
+.sp .4v
+.in +3
+.nf
+.ta +\w'xxxn'u +\w'nnnn'u +\w'backspace 'u
+\eb	\-\-	backspace	(ASCII 08)
+\et	\-\-	tab	(ASCII 09)
+\en	\-\-	newline	(ASCII 10)
+\er	\-\-	return	(ASCII 13)
+\ee	\-\-	escape	(ASCII 27)
+\exx	\-\-	the ASCII character corresponding to 2 hex digits xx.
+.fi
+.in -3
+.ta +\w'nm'u +\w'"command"m'u
+.TP 5
+n		(2)
+Copy the current text buffer to standard output.  Read the next line
+of input into it.
+.TP 5
+N		(2)
+Append the next line of input to the current text buffer, inserting
+an embedded newline between the two.  The current line number changes.
+.TP 5
+p		(2)
+Print.  Copy the current text buffer to the standard output.
+.TP 5
+P		(2)
+Copy the first line of the current text buffer (all chars up to the
+first newline) to standard output.
+.TP 5
+q		(1)
+Quit.  Branch to the end of the script.  Do not start a new cycle.
+.TP 5
+r	"rfile"	(1)
+Read the contents of rfile.  Place them on the output before reading
+the next input line.
+.TP 5
+s	/regular-expression/replacement/flags\0\0\0\0\0\0(2)
+Substitute the replacement for instances of the regular expression
+in the current text buffer.  Any character may be used instead of `/'.
+For a fuller description see ed (1).
+Flags is zero or more of the following:
+.sp .4v
+.ta +\w'gm'u +\w'nnm'u
+.in +\w'gmnnm'u
+.ti -\w'gmnnm'u
+g	\-\-	Global.  Substitute for all nonoverlapping instances of
+the string rather than just the first one.
+.sp .4v
+.ti -\w'gmnnm'u
+p	\-\-	Print the pattern space if a replacement was made.
+.sp .4v
+.ti -\w'gmnnm'u
+w	\-\-	Write.  Append the current text buffer to a file argument
+as in a w command if a replacement is made.  Standard output is used if no
+file argument is given
+.in -\w'gmnnm'u
+.ta +\w'nm'u +\w'"command"m'u
+.TP 5
+t	"label"	(2)
+Branch-if-test.  Branch to the
+.B :
+command with the given label if any
+substitutes have been made since the most recent read of an input line
+or execution of a
+.B t
+or
+.BR T .
+If no label is given, branch to the end of the script.
+.TP 5
+T	"label"	(2)
+Branch-on-error.  Branch to the
+.B :
+command with the given label if no substitutes have succeeded since the
+last input line or
+.B t
+or
+.B T
+command.  Branch to the end of the script if no label is given.
+.TP 5
+w	"wfile"	(2)
+Write.  Append the current text buffer to wfile.
+.TP 5
+W	"wfile"	(2)
+Write first line.  Append first line of the current text buffer
+to wfile.
+.TP 5
+x		(2)
+Exchange the contents of the current text buffer and hold space.
+.TP 5
+y	/string1/string2/\0\0\0\0\0\0(2)
+Translate.  Replace each occurrence of a character in string1 with
+the corresponding character in string2.  The lengths of these strings
+must be equal.
+.TP 5
+!	"command"	(2)
+All-but.  Apply the function (or group, if function is
+.BR { )
+only to lines not selected by the address(es).
+.TP 5
+:	"label"	(0)
+This command does nothing but hold a label for
+.B b
+and
+.B t
+commands to branch to.
+.TP 5
+=		(1)
+Place the current line number on the standard output as a line.
+.TP 5
+{		(2)
+Execute the following commands through a matching `}' only when the
+current line matches the address or address range given.
+.P
+An empty command is ignored.
+.P
+.SH PORTABILITY
+This tool was reverse-engineered from BSD 4.1 UNIX
+.BR sed ,
+and (as far
+as the author's knowledge and tests can determine) is compatible with
+it.  All documented features of BSD 4.1 sed are supported.
+.P
+One undocumented feature (a leading 'n' in the first comment having
+the same effect as an
+.B \-n
+command-line option) has been omitted.
+.P
+The following bugs and limitations have been fixed:
+.TP 5
+\(bu
+There is no hidden length limit (40 in BSD sed) on
+.B w
+file names.
+.TP 5
+\(bu
+There is no limit (8 in BSD sed) on the length of labels.
+.TP 5
+\(bu
+The exchange command now works for long pattern and hold spaces.
+.P
+The following enhancements to existing commands have been made:
+.TP 5
+\(bu
+.BR a ,
+.B i
+commands don't insist on a leading backslash-\en in the text.
+.TP 5
+\(bu
+.BR r ,
+.B w
+commands don't insist on whitespace before the filename.
+.TP 5
+\(bu
+The
+.BR g ,
+.B p
+and
+.B P
+options on
+.B s
+commands may be given in any order.
+.P
+Some enhancements to regular-expression syntax have been made:
+.TP 5
+\(bu
+\et is recognized in REs (and elsewhere) as an escape for tab.
+.TP 5
+\(bu
+In an RE, + calls for 1..n repeats of the previous pattern.
+.P
+The following are completely new features:
+.TP 5
+\(bu
+The
+.B l
+command (list, undocumented and weaker in BSD)
+.TP 5
+\(bu
+The
+.B W
+command (write first line of pattern space to file).
+.TP 5
+\(bu
+The
+.B T
+command (branch on last substitute failed).
+.TP 5
+\(bu
+Trailing comments are now allowed on command lines.
+.P
+In addition,
+.BR sed "'s"
+error messages have been made more specific and informative.
+.P
+The implementation is also significantly smaller and faster than 
+BSD 4.1 sed.  It uses only the standard I/O library and exit(3).
+.P
+.SH NOTE
+.P
+This is a freeware component of the GNU and MINIX operating systems.
+The user is hereby granted permission to use, modify, reproduce and
+distribute it subject to the following conditions:
+.P
+1. The authorship notice appearing in each source file may not be
+altered or deleted.
+.P
+2. The object form may not be distributed without source.
+.P
+.SH SEE ALSO
+.P
+.BR cgrep (1),
+.BR fgrep (1),
+.BR grep (1),
+.BR lex (1),
+.BR regexp (5),
+.BR awk (9).
+.P
+.SH AUTHOR
+Eric S. Raymond <esr@snark.thyrsus.com>
Index: /trunk/minix/man/man1/shar.1
===================================================================
--- /trunk/minix/man/man1/shar.1	(revision 9)
+++ /trunk/minix/man/man1/shar.1	(revision 9)
@@ -0,0 +1,40 @@
+.TH SHAR 1
+.SH NAME
+shar \- shell archiver
+.SH SYNOPSIS
+\fBshar \fIfile ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "shar *.c >s" "Collect C programs in shell archive"
+.EX "sh <s" "Extract files from a shell archive"
+.SH DESCRIPTION
+.PP
+The named files are collected together into a shell archive written onto
+standard output.
+The individual files can be extracted by redirecting the shell archive into
+the shell.
+The advantage of
+.I shar
+over
+.I ar
+is that \fIshar\fP archives can be read on almost any 
+\s-2UNIX\s+2
+system, whereas numerous, incompatible versions of
+.I ar
+are in widespread use.
+Extracting the files from a shell archive requires that 
+.I sed
+be accessible.
+.SH "SEE ALSO"
+.BR sh (1),
+.BR unshar (1).
Index: /trunk/minix/man/man1/size.1
===================================================================
--- /trunk/minix/man/man1/size.1	(revision 9)
+++ /trunk/minix/man/man1/size.1	(revision 9)
@@ -0,0 +1,39 @@
+.TH SIZE 1
+.SH NAME
+size \- print text, data, and bss size of a program
+.SH SYNOPSIS
+\fBsize\fR [\fIfile\fR] ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "size file" "Print the size of \fIfile\fP"
+.SH DESCRIPTION
+.PP
+The text, data, bss, and total sizes for each argument are printed.
+If no arguments are present, 
+.I a.out
+is assumed.
+The amount of memory available for combined stack and data segment growth
+is printed in the column \&'stack.\&'
+This is the value manipulated by the 
+.I chmem
+command.
+The total amount of memory allocated to the program when it is loaded is
+listed under \&'memory.\&'
+This value is just the sum of the other four columns.
+.SH "SEE ALSO"
+.BR anm (1),
+.BR asize (1),
+.BR ar (1),
+.BR chmem (1),
+.BR install (1),
+.BR nm (1).
Index: /trunk/minix/man/man1/sleep.1
===================================================================
--- /trunk/minix/man/man1/sleep.1	(revision 9)
+++ /trunk/minix/man/man1/sleep.1	(revision 9)
@@ -0,0 +1,24 @@
+.TH SLEEP 1
+.SH NAME
+sleep \- suspend execution for a given number of seconds
+.SH SYNOPSIS
+\fBsleep \fIseconds\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "sleep 10" "Suspend execution for 10 sec."
+.SH DESCRIPTION
+.PP
+The caller is suspended for the indicated number of seconds.
+This command is typically used in shell scripts.
+.SH "SEE ALSO"
+.BR sleep (3).
Index: /trunk/minix/man/man1/sort.1
===================================================================
--- /trunk/minix/man/man1/sort.1	(revision 9)
+++ /trunk/minix/man/man1/sort.1	(revision 9)
@@ -0,0 +1,50 @@
+.TH SORT 1
+.SH NAME
+sort \- sort a file of ASCII lines
+.SH SYNOPSIS
+\fBsort\fR [\fB\-bcdf\&imnru\fR]\fR [\fB\-t\fIc\fR]  [\fB\-o \fIname\fR] [\fB+\fIpos1\fR] [\fB\-\fIpos2\fR] \fIfile\fR ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-b" "Skip leading blanks when making comparisons"
+.FL "\-c" "Check to see if a file is sorted"
+.FL "\-d" "Dictionary order: ignore punctuation"
+.FL "\-f" "Fold upper case onto lower case"
+.FL "\-i" "Ignore nonASCII characters"
+.FL "\-m" "Merge presorted files"
+.FL "\-n" "Numeric sort order"
+.FL "\-o" "Next argument is output file"
+.FL "\-r" "Reverse the sort order"
+.FL "\-t" "Following character is field separator"
+.FL "\-u" "Unique mode (delete duplicate lines)"
+.SH EXAMPLES
+.EX "sort \-nr file" "Sort keys numerically, reversed"
+.EX "sort +2 \-4 file" "Sort using fields 2 and 3 as key"
+.EX "sort +2 \-t: \-o out" "Field separator is \fI:\fP"
+.EX "sort +.3 \-.6" "Characters 3 through 5 form the key"
+.SH DESCRIPTION
+.PP
+.I Sort
+sorts one or more files.
+If no files are specified, \fIstdin\fR is sorted.
+Output is written on standard output, unless \fB\-o\fP is specified.
+The options \fB+\fIpos1 \fB\-\fIpos2\fR use only fields \fIpos1\fR
+up to but not including \fIpos2\fR as the sort key, where a field is a
+string of characters delimited by spaces and tabs, unless a different field
+delimiter is specified with \fB\-t\fR.
+Both \fIpos1\fR and \fIpos2\fR have the form \fIm.n\fR where \fIm\fR tells
+the number of fields and \fIn\fR tells the number of characters.
+Either \fIm\fR or \fIn\fR may be omitted.
+.SH "SEE ALSO"
+.BR comm (1),
+.BR grep (1),
+.BR uniq (1).
Index: /trunk/minix/man/man1/spell.1
===================================================================
--- /trunk/minix/man/man1/spell.1	(revision 9)
+++ /trunk/minix/man/man1/spell.1	(revision 9)
@@ -0,0 +1,33 @@
+.TH SPELL 1
+.SH NAME
+spell \- print all words in a file not present in the dictionary
+.SH SYNOPSIS
+\fBspell \fIfile\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "spell document" "Print the spelling errors on \fIstdout\fR"
+.SH DESCRIPTION
+.PP
+\fISpell\fR is the 
+\s-1MINIX 3\s-1
+spelling checker.  
+It is actually a short shell script.
+First, the program \fIprep\fR strips off the \fIroff\fR, 
+\fInroff\fR, and \fItroff\fR control lines,
+and the punctuation, and lists each word on a separate line.  These words are
+then sorted.  The resulting output is then compared to the dictionary.  Words
+present in the file but not present in the dictionary are listed.  The
+dictionary must be located in \fI/usr/lib/dict/words\fR.
+.SH "SEE ALSO"
+.BR nroff (1),
+.BR prep (1).
Index: /trunk/minix/man/man1/split.1
===================================================================
--- /trunk/minix/man/man1/split.1	(revision 9)
+++ /trunk/minix/man/man1/split.1	(revision 9)
@@ -0,0 +1,30 @@
+.TH SPLIT 1
+.SH NAME
+split \- split a large file into several smaller files
+.SH SYNOPSIS
+\fBsplit\fR [\fB\-\fIn\fR]\fR [\fIfile \fR[\fIprefix\fR]\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-\fIn\fP" "Number of lines per piece (default: 1000)"
+.SH EXAMPLES
+.EX "split \-200 file" "Split \fIfile\fP into pieces of 200 lines each"
+.EX "split file z" "Split \fIfile\fP into \fIzaa\fP, \fIzab\fP, etc."
+.SH DESCRIPTION
+.PP
+.I Split 
+reads \fIfile\fP and writes it out in \fIn\fP-line pieces.
+By default, the pieces are called \fIxaa\fP, \fIxab\fP, etc.
+The optional second argument can be used to provide an alternative
+prefix for the output file names.
+.SH "SEE ALSO"
+.BR cat (1).
Index: /trunk/minix/man/man1/stat.1
===================================================================
--- /trunk/minix/man/man1/stat.1	(revision 9)
+++ /trunk/minix/man/man1/stat.1	(revision 9)
@@ -0,0 +1,111 @@
+.TH STAT 1
+.SH NAME
+stat, lstat, readlink \- provide a shell interface to the stat(2) system call
+.SH SYNOPSIS
+.B stat
+.RB [ - ]
+.RB [ -\fIfd ]
+.RB [ -all ]
+.RB [ -s ]
+.RB [ -\fIfield " ...]"
+.RI [ file1 " ...]"
+.SH DESCRIPTION
+.B Stat
+does little more than provide access to the fields in the
+.B struct stat
+as defined in the
+.BR stat (2)
+manual page.  Each field that is to be listed
+is specified as the field name without the leading
+.BR st_ .
+This and the other two options are described below.  All options are then
+applied to the files listed.  If
+.B stat
+is called as
+.B lstat
+then the
+.BR lstat (2)
+system call is used, if called as 
+.B stat
+symbolic links are expanded with
+.BR stat (2).
+If called as
+.B readlink
+then the output is only the contents of the symbolic link.
+.PP
+If no fields are named then all fields are printed.  If no files are listed
+then all open filedescriptors are printed.
+.SH OPTIONS
+.TP 
+.B \-
+If the first argument is ``\-'', the list of files is assumed to come from stdin.
+This is useful for things like ``ls | stat \-uid \-mtime.''
+.B \-\fIfd
+If an argument is a ``\-'' followed by a number then that number is used as
+a file descriptor whose information is to be printed.
+.TP 
+.B \-all
+List all fields for each file.
+.TP
+.B \-s
+Use
+.BR lstat (2).
+.TP
+.B \-mode
+List the
+.B mode
+field.  Similarly for
+.BR ino ,
+.BR dev ,
+.BR rdev ,
+.BR nlink ,
+.BR uid , 
+.BR gid ,
+.BR size ,
+.BR atime ,
+.BR mtime ,
+and
+.BR ctime .
+Under BSD derived systems you also have 
+.B blksize
+and
+.BR blocks .
+.PP 
+.B \-Atime
+.br
+.B \-Mtime
+.br
+.B \-Ctime
+.RS
+The lower case versions of these three options display the time as an integer
+that is the ``seconds since 00:00 Jan 1. 1970.''
+Listing the fields with the first letter
+in caps causes the times to be printed in
+.BR ctime (3)
+format (i.e., human readable).
+.RE
+.SH EXAMPLES
+.LP 
+# Find out the number of links to each file
+.br
+$ stat \-nlink *.c
+.LP
+# sort files by age (much like ls \-t)
+.br
+$ stat \-atime * | sort +1
+.LP
+# Find out which file is older in sh(1)
+.br
+if test `stat -mtime $1` -lt `stat -mtime $2`; then
+.br
+	echo $1 is older than $2
+.br
+else
+.br
+	echo $2 is older than $1
+.br
+fi
+.SH "SEE ALSO"
+.BR stat (2).
+.SH AUTHOR
+Larry McVoy (mcvoy@rsch.wisc.edu)
Index: /trunk/minix/man/man1/strings.1
===================================================================
--- /trunk/minix/man/man1/strings.1	(revision 9)
+++ /trunk/minix/man/man1/strings.1	(revision 9)
@@ -0,0 +1,29 @@
+.TH STRINGS 1
+.SH NAME
+strings \- print all the strings in a binary file
+.SH SYNOPSIS
+\fBstrings\fR [\fB\-\fR] [\fB\-o\fR]\fR [\fB\-\fIn\fR] \fIfile ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-" "search whole file, not just data seg"
+.FL "\-o" "Print octal offset of each string"
+.FL "\-\fIn" "\fIn\fR is minimum length string (default = 4)"
+.SH EXAMPLES
+.EX "strings \-5 a.out" "Print the strings > 4 chars in \fIa.out\fR"
+.EX "strings \- /bin/sh" "Search entire shell file (text and data)"
+.SH DESCRIPTION
+.PP
+\fIStrings\fR looks for sequences of ASCII characters followed by a zero 
+byte.
+These are usually strings.  This program is typically used to help identify
+unknown binary programs
Index: /trunk/minix/man/man1/strip.1
===================================================================
--- /trunk/minix/man/man1/strip.1	(revision 9)
+++ /trunk/minix/man/man1/strip.1	(revision 9)
@@ -0,0 +1,24 @@
+.TH STRIP 1
+.SH NAME
+strip \- remove symbol table from executable file
+.SH SYNOPSIS
+\fBstrip\fR [\fIfile\fR] ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "strip a.out" "Remove symbols from \fIa.out\fR"
+.SH DESCRIPTION
+.PP
+For each file argument, \fIstrip\fR removes the symbol table.  
+Strip makes a copy of the file being stripped, so links are lost.
+.SH "SEE ALSO"
+.BR install (1).
Index: /trunk/minix/man/man1/stty.1
===================================================================
--- /trunk/minix/man/man1/stty.1	(revision 9)
+++ /trunk/minix/man/man1/stty.1	(revision 9)
@@ -0,0 +1,250 @@
+.TH STTY 1
+.SH NAME
+stty \- set terminal parameters
+.SH SYNOPSIS
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.in +4n
+.ti -4n
+.B stty
+.RB [ \-ag]
+.SP
+.ti -4n
+.B stty
+.I encoded-form
+.SP
+.ti -4n
+.B stty
+.I speed
+.B ispeed
+.I speed
+.B ospeed
+.I speed
+.B "cs5 cs6 cs7 cs8"
+.RB [ \- ] parenb
+.RB [ \- ] parodd
+.RB [ \- ] hupcl
+.RB [ \- ] cstopb
+.RB [ \- ] cread
+.RB [ \- ] clocal
+.RB [ \- ] ignbrk
+.RB [ \- ] brkint
+.RB [ \- ] ignpar
+.RB [ \- ] parmrk
+.RB [ \- ] inpck
+.RB [ \- ] istrip
+.RB [ \- ] inlcr
+.RB [ \- ] igncr
+.RB [ \- ] icrnl
+.RB [ \- ] ixon
+.RB [ \- ] ixoff
+.RB [ \- ] ixany
+.RB [ \- ] opost
+.RB [ \- ] onlcr
+.RB [ \- ] xtabs
+.RB [ \- ] onoeot
+.RB [ \- ] isig
+.RB [ \- ] icanon
+.RB [ \- ] iexten
+.RB [ \- ] echo
+.RB [ \- ] echoe
+.RB [ \- ] echok
+.RB [ \- ] echonl
+.RB [ \- ] noflsh
+.RB [ \- ] tostop
+.RB [ \- ] lflusho
+.BR eof =\fIc
+.BR eol =\fIc
+.BR erase =\fIc
+.BR erase =\fIc
+.BR intr =\fIc
+.BR kill =\fIc
+.BR quit =\fIc
+.BR susp =\fIc
+.BR start =\fIc
+.BR stop =\fIc
+.BR rprnt =\fIc
+.BR lnext =\fIc
+.BR flush =\fIc
+.BR min =\fIn
+.BR time =\fIn
+.B rows
+.I n
+.B cols
+.I n
+.B xpixels
+.I n
+.B ypixels
+.I n
+.B cooked
+.B raw
+.RB [ \- ] evenp
+.RB [ \- ] parity
+.RB [ \- ] oddp
+.RB [ \- ] nl
+.B ek
+.B sane
+.in -4n
+.SH DESCRIPTION
+.B Stty
+shows or changes the parameters of the terminal connected to standard input.
+.B Stty
+takes a myriad of arguments most of which are mapped directly to
+the flags and special characters described in
+.BR tty (4),
+so we won't describe them here.
+.PP
+.B Stty
+has three forms of operation.  First, without any arguments
+.B stty
+shows all terminal attributes that are different from the default state.
+Option
+.B \-a
+makes
+.B stty
+print all terminal attributes, and
+.B \-g
+lets
+.B stty
+print the attributes in a special encoded form, a simple row of colon separated
+hexadecimal numbers.
+.PP
+In the second form of operation
+.B stty
+takes an encoded form as produced by the
+.B \-g
+option and sets the terminals attributes to its decoded value.
+.PP
+In the third form
+.B stty
+interprets a series of flags and parameters settings and modifies the
+terminal attributes accordingly.  Flags can be given as
+.B icanon
+or
+.B \-icanon
+for instance, either setting or clearing the
+.B ICANON
+flag.
+Special character values can by set like
+.B "intr=^C"
+for example, which sets the interrupt character to CTRL-C.  You can either
+use a real CTRL-C, or the two characters `^' and `C'.  In any case
+it is probably necessary to use quotes to guard it from the shell:
+.BR "intr='^C'" .
+.PP
+A number alone is interpreted as a baud rate setting for both the input and
+output rate.  The input or the output rate can be set separately with use
+of the
+.B ispeed
+and
+.B ospeed
+prefixes to the number.  The character size can be set with
+.BR cs5 ,
+.BR cs6 ,
+.BR cs7
+or
+.BR cs8 .
+.PP
+The
+.B MIN
+and
+.B TIME
+value, the number of rows and columns, and the xpixels and ypixels of the
+window can also be set using one of the keywords
+.BR min ,
+.BR time ,
+.BR rows ,
+.BR cols ,
+.BR xpixels
+or
+.BR ypixels ,
+followed by a decimal number that is the value of the setting.
+.PP
+.B Stty
+accepts several keywords that are not named by corresponding flags or
+parameters in
+.BR tty (4).
+They set several attributes at once:
+.TP
+.B cooked
+Same as
+.BR "icrnl ixon opost onlcr isig icanon iexten echo" ,
+setting all the attributes that are needed for line oriented mode.
+.TP
+.B raw
+Same as
+.BR "\-icrnl \-ixon \-opost \-onlcr \-isig \-icanon \-iexten \-echo" ,
+setting all the attributes for a raw data channel.
+.TP
+.B evenp parity
+These synonyms are equal to
+.BR "cs7 parenb \-parodd" ,
+setting the line to 7 bits even parity.
+.TP
+.B oddp
+Same as
+.BR "cs7 parenb parodd" ,
+setting the line to 7 bits odd parity.
+.TP
+.B "\-parity \-evenp \-oddp"
+All synonyms for
+.BR "cs8 \-parenb" ,
+setting the line to 8 bits, no parity.
+.TP
+.B nl
+Same as
+.BR icrnl ,
+setting carriage return to line feed input translation.
+.TP
+.B \-nl
+Same as
+.BR "\-icrnl \-inlcr \-igncr" ,
+disabling any carriage return or line feed handling.
+.TP
+.B ek
+Set the
+.B ERASE
+and
+.B KILL
+special characters back to the default.
+.TP
+.B sane
+Set all attributes to the default except things like the line speed and
+parity, because their "sane" value is probably what it is right now.
+The default values are compiled into
+.B stty
+from the <termios.h> include file.  Use
+.B "stty sane; stty -a"
+to know what they are.
+.SH FILES
+.TP 15n
+.B /etc/ttytab
+The
+.B init
+field of this file may contain an
+.B stty
+command to set the attributes to match an attached RS232 terminal or modem.
+.SH "SEE ALSO"
+.BR tty (4),
+.BR ttytab (5).
+.SH NOTES
+The
+.BR cooked ,
+.BR raw ,
+.BR rows ,
+.BR cols ,
+.BR xpixels
+and
+.BR ypixels
+keywords are MINIX 3 additions beyond the keywords defined by POSIX.
+.B Rows
+and
+.B cols
+are common UNIX extensions, however.
+There are more MINIX 3 specific flags that match the MINIX 3 specific attributes
+described in
+.BR tty (4).
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man1/su.1
===================================================================
--- /trunk/minix/man/man1/su.1	(revision 9)
+++ /trunk/minix/man/man1/su.1	(revision 9)
@@ -0,0 +1,58 @@
+.TH SU 1
+.SH NAME
+su \- temporary become superuser or another user
+.SH SYNOPSIS
+.B su
+.RB [ \- [ e ]]
+.RI [ user
+.RI [ shell-arguments " ...]]"
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Su
+can be used to temporarily run a shell under the identity of the superuser
+or another user.  Unless the caller is a member of the operator group, one
+is prompted for the password of the user-to-be.  Calls that need a password
+are logged, whether they succeed or not.  The default user is
+.BR root .
+Further arguments are handed to the shell.  By default the shell started is
+the shell of the invoker, and the environment is passed on as is.
+.PP
+The activities of
+.B su
+are logged through
+.BR syslog (3)
+under Minix-vmd.
+.SH OPTIONS
+.TP
+.B \-
+Constructs a new environment consisting of the
+.BR PATH ,
+.BR USER ,
+.BR LOGNAME ,
+.BR HOME ,
+.BR SHELL ,
+.BR TERM ,
+.BR TERMCAP ,
+and
+.BR TZ
+variables.  The environment is the same as on a normal login, except that
+.BR TERM ,
+.B TERMCAP
+and
+.B TZ
+are copied from the current environment if set.  The current working
+directory is changed to the user home directory, the shell of the user-to-be
+is run, and it is started as a login shell, with the first character a minus
+sign.
+.TP
+.B \-e
+Like above, but the shell is started normally, not as a login shell.
+.SH "SEE ALSO"
+.BR sh (1),
+.BR login (1),
+.BR syslog (3).
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man1/sum.1
===================================================================
--- /trunk/minix/man/man1/sum.1	(revision 9)
+++ /trunk/minix/man/man1/sum.1	(revision 9)
@@ -0,0 +1,29 @@
+.TH SUM 1
+.SH NAME
+sum \- compute the checksum and block count of a file
+.SH SYNOPSIS
+\fBsum \fIfile\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "sum /user/ast/xyz" "Checksum \fI/user/ast/xyz"
+.SH DESCRIPTION
+.PP
+.I Sum
+computes the checksum of one or more files.
+It is most often used to see if a file copied from another machine has
+been correctly received.
+This program works best when both machines use the same checksum algorithm.
+See also \fIcrc\fR.
+.SH "SEE ALSO"
+.BR cksum (1),
+.BR crc (1).
Index: /trunk/minix/man/man1/svc.1
===================================================================
--- /trunk/minix/man/man1/svc.1	(revision 9)
+++ /trunk/minix/man/man1/svc.1	(revision 9)
@@ -0,0 +1,47 @@
+.TH SVC 1
+.SH NAME
+svc, ci, co, svclog \- shell version control system
+.SH SYNOPSIS
+\fBci\fR [\fB\-lu\fR]\fR \fIfile\fR
+.br
+\fBco\fR [\fB\-l\fR]\fR [\fB\-r \fIrev\fR] \fIfile\fR
+.br
+\fBsvclog \fIfile\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-l" "For \fIci\fR, checkin, checkout again, and lock file"
+.FL "\-l" "For \fIco\fR, checkout file and then lock the archive"
+.FL "\-u" "After checking in, do not delete the file"
+.FL "\-r" "Check out revision \fIrev\fR instead most recent revision
+.SH EXAMPLES
+.EX "ci \-u file" "Check in \fIfile\fR"
+.EX "co \-l file" "Check out \fIfile\fR and lock archive"
+.EX "co \-r 2 file" "Check out version 2"
+.SH DESCRIPTION
+.PP
+\fISvc\fR is the Shell Version Control system, patterned on RCS.
+It maintains a sequence of versions in archive files, so that new versions
+can be checked in (added to the archive), and old versions can be checked
+out (made available).
+To create an archive for \fIfile\fR, check it in with the \fB\-u\fR flag.
+This action will prompt for a log message and then create an archive called
+\fIfile,S\fR in the current directory, or in the subdirectory \fISVC\fR if 
+it exists.  
+The file will not be deleted, but will be made unwritable.
+.PP
+To update the file, check it out with the \fB\-l\fR flag.
+Then modify it, and check it back in, giving a new message when prompted.
+After this process has been repeated many times, the archive will contain
+the entire history.
+Any version can be checked out using the \fB\-r\fR flag.
+To get a printout of the history, use \fIsvclog\fR.
Index: /trunk/minix/man/man1/synctree.1
===================================================================
--- /trunk/minix/man/man1/synctree.1	(revision 9)
+++ /trunk/minix/man/man1/synctree.1	(revision 9)
@@ -0,0 +1,76 @@
+.TH SYNCTREE 1
+.SH NAME
+synctree \- synchronize directory trees.
+.SH SYNOPSIS
+.nf
+\fBsynctree\fP [\fB\-iuf\fP] [[\fIuser1\fP@]\fImachine1\fP:]\fIdir1\fP [[\fIuser2\fP@]\fImachine2\fP:]\fIdir2\fP
+.fi
+.SH DESCRIPTION
+.B Synctree
+synchronizes the directory tree rooted at \fIdir2\fP with \fIdir1\fP. It
+walks recursively through both trees, and deletes and adds files in
+\fIdir2\fP to make it equal to \fIdir1\fP. Mode, owner and group are set for
+each file unless the \fB\-u\fP flag is given. In its normal mode of operation,
+synctree will ask if it may delete or add directories assuming that you don't
+want to. Non-directories are simply deleted or added, but synctree will ask if
+it needs to update a normal file with a default answer of 'y'. Simply typing
+return will choose the default answer, typing end-of-file is like typing
+return to this question and all other questions.
+.PP
+You can specify a hostname and user-id to be used to access \fIdir1\fP or
+\fIdir2\fP.  Synctree will use \fBrsh\fP(1) to run a copy of itself on
+the remote machine.  The call interface mimics that of \fBrcp\fP(1), but
+you can use more than one user@machine prefix if you want to make things
+really interesting.
+.PP
+Hard links are enforced, an update is done by first deleting the old file
+so that links to unknown files are broken.  Links to files within \fIdir2\fP
+will be restored.
+.PP
+If either directory contains the file \fB.backup\fP, then this file will
+be used as an alternate inode table.  This allows one to make a backup copy
+of a file tree full of special files and differing user-ids on a remote
+machine under an unpriviledged user-id.
+.PP
+.SH OPTIONS
+.TP 5
+.B \-i
+Ask for permission (with default answer 'n') to delete or
+add any file or directory.
+.TP 5
+.B \-u
+Only install newer files, i.e. merge the directory trees.
+.TP 5
+.B \-f
+Don't ask, think 'yes' on any question.
+.SH "SEE ALSO"
+.BR remsync (1),
+.BR cpdir (1),
+.BR rsh (1),
+.BR rcp (1),
+.BR perror (3).
+.SH DIAGNOSTICS
+Messages may come from three different processes.  One named "Slave" running
+in \fIdir1\fP, one named "Master" running in \fIdir2\fP, and synctree itself
+in a mediator role.  The mediator will also perform the task of either the
+master or the slave if one of them is running locally.  You need to know this
+to interpret the error messages coming from one of these processes.  The
+messages are normally based on \fBperror\fP(3).  Failure to contact a remote
+machine will be reported by \fBrsh\fP.  \fBSynctree\fP should have a zero
+exit status if no errors have been encountered.
+.SH BUGS
+Directory \fIdir2\fP will be created without asking.
+.PP
+The master and slave processes get their error output mixed up sometimes
+(nice puzzle).
+.PP
+The local and remote machine must use the same file type encoding.
+.PP
+The link replacement strategy may lead to lack of space on a small device.
+Let \fBsynctree\fP run to completion and then rerun it to pick up the pieces.
+.PP
+Letting the local process keep its "synctree" name may be a mistake.
+.PP
+It talks too much.
+.SH AUTHOR
+Kees J. Bot, (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/sysenv.1
===================================================================
--- /trunk/minix/man/man1/sysenv.1	(revision 9)
+++ /trunk/minix/man/man1/sysenv.1	(revision 9)
@@ -0,0 +1,27 @@
+.TH SYSENV 1
+.SH NAME
+sysenv \- request system boot parameter
+.SH SYNOPSIS
+.B sysenv
+.RI [ boot-variable "] ..."
+.SH DESCRIPTION
+.B Sysenv
+requests the value of one or more boot variables.  For example
+.B "sysenv\ memory"
+returns the list of free memory at system startup.  Note that some
+parameters have undergone "device translation" from a device name to
+a decimal device number.
+.PP
+If no variable names are given then the entire boot environment is
+listed.
+.SH "SEE ALSO"
+.BR svrctl (2),
+.BR monitor (8),
+.BR boot (8).
+.SH DIAGNOSTICS
+Exit code 0 with the variable's value printed to standard output if all
+requested variables exist in the boot environment, exit code 1 on any
+weird error, exit code 2 if one of the variables is not set, and exit
+code 3 if both kind of errors occurred.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/sz.1
===================================================================
--- /trunk/minix/man/man1/sz.1	(revision 9)
+++ /trunk/minix/man/man1/sz.1	(revision 9)
@@ -0,0 +1,235 @@
+.TH SZ 1
+.SH NAME
+sz \- send a file using the zmodem protocol
+.SH SYNOPSIS
+\fBsz\fR [\fB\-LNbdefnopqruvy+\fR]\fR [\fB\-ci \fIcommand\fR] [\fB\-Ll\fR n\fR] [\fB\-t \fItimeout\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-L" "Use \fIn\fR-byte packets"
+.FL "\-N" "Overwrite if source is newer/longer"
+.FL "\-b" "Binary file"
+.FL "\-c" "Send command for execution"
+.FL "\-d" "Convert dot to slash in names"
+.FL "\-e" "Escape for all control characters"
+.FL "\-f" "Send full path name"
+.FL "\-i" "Send command and return immediately"
+.FL "\-l" "Flow control every \fIn\fR packets"
+.FL "\-n" "Overwrite destination if source is newer"
+.FL "\-o" "Use old (16-bit) checksum"
+.FL "\-p" "Protect file if it already exists"
+.FL "\-q" "Quiet; opposite of verbose"
+.FL "\-r" "Resume interrupt file transfer"
+.FL "\-t" "Set \fItimeout\fR in tenths of a second"
+.FL "\-u" "Unlink file after successful transmission"
+.FL "\-v" "Verbose; opposite of quiet"
+.FL "\-y" "Yes, clobber existing files"
+.FL "\-+" "Append to an existing file"
+.SH EXAMPLES
+.EX "sz file </dev/tty01 >/dev/tty01" "Send \fIfile\fR"
+.SH DESCRIPTION
+.PP
+XMODEM, YMODEM, and ZMODEM are a family of protocols that are widely used
+is the \s-2MS-DOS\s0 world for transferring information reliably from one
+computer to another.  In all of these protocols, a series of bytes are sent
+from one computer to the other, and then an acknowledgement is sent back
+to confirm correct reception.  Checksums are used to detect errors so that
+transmission is reliable even in the face of noisy telephone lines.
+\fISz\fR is a program that sends a file sent from another computer using the
+zmodem protocol.
+The file can be received using \fIrz\fR.
+.PP
+\fISz\fR uses the ZMODEM error correcting
+protocol to send one or more files over a dial-in serial
+port to a variety of programs running under
+\s-1MINIX 3\s-1,
+\s-2UNIX\s+2, 
+\s-2MS-DOS\s0, \s-2CP/M\s0, \s-2VMS\s0, and other operating systems.
+It is the successor to XMODEM and YMODEM.
+.PP
+ZMODEM greatly simplifies file transfers compared to XMODEM.
+In addition to a friendly user interface, ZMODEM provides
+Personal Computer and other users an efficient, accurate,
+and robust file transfer method.
+.PP
+ZMODEM provides complete end-to-end data integrity between
+application programs.  ZMODEM's 32 bit CRC catches errors
+that sneak into even the most advanced networks.
+.PP
+Output from another program may be piped to \fIsz\fR for
+transmission by denoting standard input with \-:
+.PP
+.B "	""ls \-l | sz \-"
+.PP
+The program output is transmitted with the filename \fIsPID.sz\fR
+where PID is the process ID of the \fIsz\fR program.  If the
+environment variable \fIONAME\fR is set, that is used instead.  In
+this case, the command:
+.PP
+.B "	""ls \-l | ONAME=con sz \-ay \-"
+.PP
+will send a \&'file\&' to the PC-DOS console display.  
+The \fB\-y\fR option instructs the receiver to open the file for writing
+unconditionally.  
+The \fB\-a\fR option causes the receiver to
+convert 
+\s-2UNIX\s+2
+newlines to PC-DOS carriage returns and linefeeds.
+On
+\s-2UNIX\s+2
+systems, additional information about the file is
+transmitted.  If the receiving program uses this
+information, the transmitted file length controls the exact
+number of bytes written to the output dataset, and the
+modify time and file mode are set accordingly.
+.PP
+If \fIsz\fR is invoked with $SHELL set and if that variable
+contains the string \fIrsh\fR or \fIrksh\fR (restricted shell), \fIsz\fR
+operates in restricted mode.  Restricted mode restricts
+pathnames to the current directory and \fIPUBDIR\fR (usually
+\fI/usr/spool/uucppublic\fR) and/or subdirectories thereof.
+.PP
+The options and flags available are:
+.in +0.25i
+.ti -0.25i
+.B \-+
+.br
+Instruct the receiver to append transmitted data to an existing file.
+.ti -0.25i
+.B \-a
+.br
+Convert NL characters in the transmitted file to CR/LF.
+This is done by the sender for XMODEM and YMODEM, by the receiver for ZMODEM.
+.ti -0.25i
+.B \-b
+.br
+Binary override: transfer file without any translation.
+.ti -0.25i
+.B \-c
+.br
+Send COMMAND (follows \fIc\fR) to the receiver for execution, return with
+COMMAND's exit status.
+.ti -0.25i
+.B \-d
+.br
+Change all instances of \&'.\&' to \&'/\&' in the transmitted
+pathname.  Thus, C.omenB0000 (which is unacceptable to
+\s-2MS-DOS\s0 or CP/M) is transmitted as C/omenB0000.  If the
+resultant filename has more than 8 characters in the
+stem, a \&'.\&' is inserted to allow a total of eleven.
+.ti -0.25i
+.B \-e
+.br
+Escape all control characters; normally XON, XOFF, DLE,
+CR-@-CR, and Ctrl-X are escaped.
+.ti -0.25i
+.B \-f
+.br
+Send Full pathname.  Normally directory prefixes are stripped from 
+the transmitted filename.
+.ti -0.25i
+.B \-i
+.br
+Send COMMAND (follows \fIi\fR) to the receiver for execution, return
+Immediately upon the receiving program's successful reception of the command.
+.ti -0.25i
+.B \-L
+.br
+Use ZMODEM sub-packets of length \fIn\fR (follows \fIL\fR).  
+A larger \fIn\fR (32 <= \fIn\fR <= 1024) gives slightly higher throughput, a 
+smaller one speeds error recovery.  The default is 128 below 300
+baud, 256 above 300 baud, or 1024 above 2400 baud.
+.ti -0.25i
+.B \-l 
+.br
+Wait for the receiver to acknowledge correct data every
+\fIn\fR (32 <= \fIn\fR <= 1024) characters.  
+This may be used to avoid network overrun when XOFF flow control is lacking.
+.ti -0.25i
+.B \-n
+.br
+Send each file if destination file does not exist.  
+Overwrite destination file if source file is newer than the destination file.
+.ti -0.25i
+.B \-N
+.br
+ Send each file if destination file does not exist.  Overwrite destination 
+file if source file is newer or longer than the destination file.
+.ti -0.25i
+.B \-o
+.br
+Disable automatic selection of 32 bit CRC.
+.ti -0.25i
+.B \-p
+.br
+Protect existing destination files by skipping transfer if the destination 
+file exists.
+.ti -0.25i
+.B \-q
+.br
+Quiet suppresses verbosity.
+.ti -0.25i
+.B \-r
+.br
+Resume interrupted file transfer.  If the source file is longer than the 
+destination file, the transfer commences at the offset in the source file
+that equals the length of the destination file.
+.ti -0.25i
+.B \-t
+.br
+Change timeout.
+The timeout, in tenths of seconds, follows, the \fB\-t\fR flag.
+.ti -0.25i
+.B \-u
+.br
+Unlink the file after successful transmission.
+.ti -0.25i
+.B \-w
+.br
+Limit the transmit window size to \fIn\fR bytes (\fIn follows \fB(enw\fR).
+.ti -0.25i
+.B \-v
+.br
+Verbose causes a list of file names to be appended to \fI/tmp/szlog\fR.
+.ti -0.25i
+.B \-y
+.br
+Instruct a ZMODEM receiving program to overwrite any existing file with the 
+same name.
+.ti -0.25i
+.B \-Y
+.br
+Instruct a ZMODEM receiving program to overwrite any existing file with the 
+same name, and to skip any source files that do have a file with the same 
+pathname on the destination system.
+.in -0.25i
+.SS "Examples"
+.PP
+Below are some examples of the use of \fIsz\fR.
+.PP
+.B "	""sz \-a \d\s+2*\s0\u.c"
+.PP
+This single command transfers all .c files in the current
+directory with conversion (\fB\-a\fR) to end-of-line
+conventions appropriate to the receiving environment.
+.sp
+.B "	""sz \-Yan \d\s+2*\s0\u.c \d\s+2*\s0\u.h"
+.PP
+.LP
+Send only the \fI.c\fR and \fI.h\fR files that exist on both systems,
+and are newer on the sending system than the corresponding
+version on the receiving system, converting 
+\s-1MINIX 3\s-1
+to \s-2MS-DOS\s0 text format.
+.SH "SEE ALSO"
+.BR rz (1),
+.BR term (1).
Index: /trunk/minix/man/man1/tail.1
===================================================================
--- /trunk/minix/man/man1/tail.1	(revision 9)
+++ /trunk/minix/man/man1/tail.1	(revision 9)
@@ -0,0 +1,34 @@
+.TH TAIL 1
+.SH NAME
+tail \- print the last few lines of a file
+.SH SYNOPSIS
+\fBtail\fR [\fB\-c \fIn\fR] [\fB\-f] [\fB\-n \fIn\fR] [\fIfile\fR] ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-c" "The count refers to characters"
+.FL "\-f" "On FIFO or special file, keep reading after EOF"
+.FL "\-n" "The count refers to lines"
+.SH EXAMPLES
+.EX "tail \-n 6" "Print last 6 lines of \fIstdin\fR"
+.EX "tail \-c 20 file" "Print the last 20 characters of \fIfile\fR"
+.EX "tail \-n 1 file1 file2" "Print last line of two files"
+.EX "tail \-n +8 file" "Print the tail starting with line 8"
+.SH DESCRIPTION
+.PP
+The last few lines of one or more files are printed.
+The default count is 10 lines.
+The default file is \fIstdin\fR.
+If the value of \fIn\fR for the \fB\-c\fR or \fB\-n\fR flags starts with
+a + sign, counting starts at the beginning, rather than the end of the file.
+.SH "SEE ALSO"
+.BR head (1).
Index: /trunk/minix/man/man1/tar.1
===================================================================
--- /trunk/minix/man/man1/tar.1	(revision 9)
+++ /trunk/minix/man/man1/tar.1	(revision 9)
@@ -0,0 +1,50 @@
+.TH TAR 1
+.SH NAME
+tar \- tape archiver
+.SH SYNOPSIS
+\fBtar\fR [\fBFcotvxp\fR]\fR [\fBf\fR] \fItarfile \fIfile ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "F" "Force tar to continue after an error"
+.FL "c" "Create a new archive; add named files"
+.FL "o" "Set uid/gid to original values on extraction"
+.FL "f" "Next argument is name of tarfile"
+.FL "t" "Print a table listing the archive's contents"
+.FL "v" "Verbose mode-tell what is going on as it happens"
+.FL "x" "The named files are extracted from the archive"
+.FL "p" "Restore file modes, ignore creation mask"
+.FL "D" "Directory only, do not recurse"
+.SH EXAMPLES
+.EX "tar c /dev/fd1 ." "Back up current directory to \fI/dev/fd1\fR"
+.EX "tar xv /dev/fd1 file1 file2" "Extract two files from the archive"
+.EX "tar cf \- . | (cd dest; tar xf \-)" "Copy current directory to \fIdest\fR"
+.SH DESCRIPTION
+.PP
+\fITar\fR is a POSIX-compatible archiver, except that it does not use tape.
+It's primary advantage over
+.I ar
+is that the 
+.I tar
+format is somewhat more standardized than the
+.I ar 
+format, making it theoretically possible to transport 
+\s-1MINIX 3\s-1
+files to another computer, but do not bet on it.
+If the target machine runs
+\&MS-DOS ,
+try
+.I doswrite .
+.SH "SEE ALSO"
+.BR compress (1),
+.BR vol (1).
+.\" minor correction ASW 2005-01-15
Index: /trunk/minix/man/man1/tee.1
===================================================================
--- /trunk/minix/man/man1/tee.1	(revision 9)
+++ /trunk/minix/man/man1/tee.1	(revision 9)
@@ -0,0 +1,29 @@
+.TH TEE 1
+.SH NAME
+tee \- divert stdin to a file
+.SH SYNOPSIS
+\fBtee\fR [\fB\-ai\fR] \fIfile\fR ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-a" "Append to the files, rather than overwriting"
+.FL "\-i" "Ignore interrupts"
+.SH EXAMPLES
+.EX "cat file1 file2 | tee x" "Save and display two files"
+.EX "pr file | tee x | lp" "Save the output of \fIpr\fP on \fIx\fP"
+.SH DESCRIPTION
+.PP
+.I Tee
+copies \fIstdin\fR to standard output.
+It also makes copies on all the files listed as arguments.
+.SH "SEE ALSO"
+.BR cat (1).
Index: /trunk/minix/man/man1/telnet.1
===================================================================
--- /trunk/minix/man/man1/telnet.1	(revision 9)
+++ /trunk/minix/man/man1/telnet.1	(revision 9)
@@ -0,0 +1,587 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)telnet.1c	6.5 (Berkeley) 5/10/86
+.\"
+.TH TELNET 1 "May 10, 1986"
+.UC 5
+.SH NAME
+telnet \- user interface to the \s-1TELNET\s0 protocol
+.SH SYNOPSIS
+telnet [
+.I host
+[
+.I port
+] ]
+.SH DESCRIPTION
+.I Telnet
+is used to communicate with another host using the
+.B TELNET
+protocol.
+If 
+.I telnet
+is invoked without arguments, it enters command mode,
+indicated by its prompt (\*(lqtelnet>\*(rq).
+In this mode, it accepts and executes the commands listed below.
+If it is invoked with arguments, it performs an
+.B open
+command (see below) with those arguments.
+.PP
+Once a connection has been opened,
+.I telnet
+enters an input mode.
+The input mode entered will be either \*(lqcharacter at a time\*(rq
+or \*(lqline by line\*(rq
+depending on what the remote system supports.
+.PP
+In \*(lqcharacter at a time\*(rq mode, most
+text typed is immediately sent to the remote host for processing.
+.PP
+In \*(lqline by line\*(rq mode, all text is echoed locally,
+and (normally) only completed lines are sent to the remote host.
+The \*(lqlocal echo character\*(rq (initially \*(lq^E\*(rq) may be used
+to turn off and on the local echo
+(this would mostly be used to enter passwords
+without the password being echoed).
+.PP
+In either mode, if the
+.I localchars
+toggle is TRUE (the default in line mode; see below),
+the user's
+.IR quit ,
+.IR intr ,
+and
+.I flush
+characters are trapped locally, and sent as
+.B TELNET
+protocol sequences to the remote side.
+There are options (see
+.B toggle
+.I autoflush
+and
+.B toggle
+.I autosynch
+below)
+which cause this action to flush subsequent output to the terminal
+(until the remote host acknowledges the
+.B TELNET
+sequence) and flush previous terminal input
+(in the case of
+.I quit
+and
+.IR intr ).
+.PP
+While connected to a remote host,
+.I telnet
+command mode may be entered by typing the
+.I telnet
+\*(lqescape character\*(rq (initially \*(lq^]\*(rq).
+When in command mode, the normal terminal editing conventions are available.
+.PP
+.B COMMANDS
+.PP
+The following commands are available.
+Only enough of each command to uniquely identify it need be typed
+(this is also true for arguments to the
+.BR mode ,
+.BR set ,
+.BR toggle ,
+and
+.B display
+commands).
+.PP
+.TP
+.B open \fIhost\fP \fR[\fP \fIport\fP \fR]\fP
+.br
+Open a connection to the named host.
+If no port number
+is specified, 
+.I telnet
+will attempt to contact a
+.B TELNET
+server at the default port.
+The host specification may be either a host name (see 
+.IR hosts (5))
+or an Internet address specified in the \*(lqdot notation\*(rq (see
+.IR inet (3N)).
+.TP
+.B close
+.br
+Close a
+.B TELNET
+session and return to command mode.
+.TP
+.B quit
+.br
+Close any open
+.B TELNET
+session and exit 
+.IR telnet .
+An end of file (in command mode) will also close a session and exit.
+.TP
+.B z
+.br
+Suspend
+.IR telnet .
+This command only works when the user is using the 
+.IR csh (1).
+.TP
+.B mode \fItype\fP
+.br
+.I Type
+is either
+.I line
+(for \*(lqline by line\*(rq mode)
+or
+.I character
+(for \*(lqcharacter at a time\*(rq mode).
+The remote host is asked for permission to go into the requested mode.
+If the remote host is capable of entering that mode, the requested
+mode will be entered.
+.TP
+.B status
+.br
+Show the current status of 
+.IR telnet .
+This includes the peer one is connected to, as well
+as the current mode.
+.TP
+.B display \fR[\fP \fIargument...\fP \fR]\fP
+.br
+Displays all, or some, of the
+.B set
+and
+.B toggle
+values (see below).
+.TP
+.B ? \fR[\fP \fIcommand\fP \fR]\fP
+.br
+Get help.  With no arguments,
+.I telnet
+prints a help summary.
+If a command is specified, 
+.I telnet
+will print the help information for just that command.
+.TP
+.B send \fIarguments\fP
+.br
+Sends one or more special character sequences to the remote host.
+The following are the arguments which may be specified
+(more than one argument may be specified at a time):
+.RS
+.TP
+.I escape
+.br
+Sends the current
+.I telnet
+escape character (initially \*(lq^]\*(rq).
+.TP
+.I synch
+.br
+Sends the
+.B TELNET SYNCH
+sequence.
+This sequence causes the remote system to discard all previously typed
+(but not yet read) input.
+This sequence is sent as TCP urgent
+data (and may not work if the remote system is a 4.2 BSD system -- if
+it doesn't work, a lower case \*(lqr\*(rq may be echoed on the terminal).
+.TP
+.I brk
+.br
+Sends the
+.B TELNET BRK
+(Break) sequence, which may have significance to the remote
+system.
+.TP
+.I ip
+.br
+Sends the
+.B TELNET IP
+(Interrupt Process) sequence, which should cause the remote
+system to abort the currently running process.
+.TP
+.I ao
+.br
+Sends the
+.B TELNET AO
+(Abort Output) sequence, which should cause the remote system to flush
+all output
+.B from
+the remote system
+.B to
+the user's terminal.
+.TP
+.I ayt
+.br
+Sends the
+.B TELNET AYT
+(Are You There)
+sequence, to which the remote system may or may not choose to respond.
+.TP
+.I ec
+.br
+Sends the
+.B TELNET EC
+(Erase Character)
+sequence, which should cause the remote system to erase the last character
+entered.
+.TP
+.I el
+.br
+Sends the
+.B TELNET EL
+(Erase Line)
+sequence, which should cause the remote system to erase the line currently
+being entered.
+.TP
+.I ga
+.br
+Sends the
+.B TELNET GA
+(Go Ahead)
+sequence, which likely has no significance to the remote system.
+.TP
+.I nop
+.br
+Sends the
+.B TELNET NOP
+(No OPeration)
+sequence.
+.TP
+.I ?
+.br
+Prints out help information for the
+.B send
+command.
+.RE
+.TP
+.B set \fIargument value\fP
+.br
+Set any one of a number of
+.I telnet
+variables to a specific value.
+The special value \*(lqoff\*(rq turns off the function associated with
+the variable.
+The values of variables may be interrogated with the
+.B display
+command.
+The variables which may be specified are:
+.RS
+.TP
+.I echo
+.br
+This is the value (initially \*(lq^E\*(rq) which, when in
+\*(lqline by line\*(rq mode, toggles between doing local echoing
+of entered characters (for normal processing), and suppressing
+echoing of entered characters (for entering, say, a password).
+.TP
+.I escape
+.br
+This is the
+.I telnet
+escape character (initially \*(lq^[\*(rq) which causes entry
+into
+.I telnet
+command mode (when connected to a remote system).
+.TP
+.I interrupt
+.br
+If
+.I telnet
+is in
+.I localchars
+mode (see
+.B toggle
+.I localchars
+below)
+and the
+.I interrupt
+character is typed, a
+.B TELNET IP
+sequence (see
+.B send
+.I ip
+above)
+is sent to the remote host.
+The initial value for the interrupt character is taken to be
+the terminal's
+.B intr
+character.
+.TP
+.I quit
+.br
+If
+.I telnet
+is in
+.I localchars
+mode (see
+.B toggle
+.I localchars
+below)
+and the
+.I quit
+character is typed, a
+.B TELNET BRK
+sequence (see
+.B send
+.I brk
+above)
+is sent to the remote host.
+The initial value for the quit character is taken to be
+the terminal's
+.B quit
+character.
+.TP
+.I flushoutput
+.br
+If
+.I telnet
+is in
+.I localchars
+mode (see
+.B toggle
+.I localchars
+below)
+and the
+.I flushoutput
+character is typed, a
+.B TELNET AO
+sequence (see
+.B send
+.I ao
+above)
+is sent to the remote host.
+The initial value for the flush character is taken to be
+the terminal's
+.B flush
+character.
+.TP
+.I erase
+.br
+If
+.I telnet
+is in
+.I localchars
+mode (see
+.B toggle
+.I localchars
+below),
+.B and
+if
+.I telnet
+is operating in \*(lqcharacter at a time\*(rq mode, then when this
+character is typed, a
+.B TELNET EC
+sequence (see
+.B send
+.I ec
+above)
+is sent to the remote system.
+The initial value for the erase character is taken to be
+the terminal's
+.B erase
+character.
+.TP
+.I kill
+.br
+If
+.I telnet
+is in
+.I localchars
+mode (see
+.B toggle
+.I localchars
+below),
+.B and
+if
+.I telnet
+is operating in \*(lqcharacter at a time\*(rq mode, then when this
+character is typed, a
+.B TELNET EL
+sequence (see
+.B send
+.I el
+above)
+is sent to the remote system.
+The initial value for the kill character is taken to be
+the terminal's
+.B kill
+character.
+.TP
+.I eof
+.br
+If
+.I telnet
+is operating in \*(lqline by line\*(rq mode, entering this character
+as the first character on a line will cause this character to be
+sent to the remote system.
+The initial value of the eof character is taken to be the terminal's
+.B eof
+character.
+.RE
+.TP
+.B toggle \fIarguments...\fP
+.br
+Toggle (between
+TRUE
+and
+FALSE)
+various flags that control how
+.I telnet
+responds to events.
+More than one argument may be specified.
+The state of these flags may be interrogated with the
+.B display
+command.
+Valid arguments are:
+.RS
+.TP
+.I localchars
+.br
+If this is
+TRUE,
+then the
+.IR flush ,
+.IR interrupt ,
+.IR quit ,
+.IR erase ,
+and
+.I kill
+characters (see
+.B set
+above) are recognized locally, and transformed into (hopefully) appropriate
+.B TELNET
+control sequences
+(respectively
+.IR ao ,
+.IR ip ,
+.IR brk ,
+.IR ec ,
+and
+.IR el ;
+see
+.B send
+above).
+The initial value for this toggle is TRUE in \*(lqline by line\*(rq mode,
+and FALSE in \*(lqcharacter at a time\*(rq mode.
+.TP
+.I autoflush
+.br
+If
+.I autoflush
+and
+.I localchars
+are both
+TRUE,
+then when the
+.IR ao ,
+.IR intr ,
+or
+.I quit
+characters are recognized (and transformed into
+.B TELNET
+sequences; see
+.B set
+above for details),
+.I telnet
+refuses to display any data on the user's terminal
+until the remote system acknowledges (via a
+.B TELNET
+.I Timing Mark
+option)
+that it has processed those
+.B TELNET
+sequences.
+The initial value for this toggle is TRUE if the terminal user had not
+done an "stty noflsh", otherwise FALSE (see
+.IR stty(1)).
+.TP
+.I autosynch
+If
+.I autosynch
+and
+.I localchars
+are both
+TRUE,
+then when either the
+.I intr
+or
+.I quit
+characters is typed (see
+.B set
+above for descriptions of the
+.I intr
+and
+.I quit
+characters), the resulting
+.B TELNET
+sequence sent is followed by the
+.B TELNET SYNCH
+sequence.
+This procedure
+.B should
+cause the remote system to begin throwing away all previously
+typed input until both of the
+.B TELNET
+sequences have been read and acted upon.
+The initial value of this toggle is FALSE.
+.TP
+.I crmod
+.br
+Toggle carriage return mode.
+When this mode is enabled, most carriage return characters received from
+the remote host will be mapped into a carriage return followed by
+a line feed.
+This mode does not affect those characters typed by the user, only
+those received from the remote host.
+This mode is not very useful unless the remote host
+only sends carriage return, but never line feed.
+The initial value for this toggle is FALSE.
+.TP
+.I debug
+.br
+Toggles socket level debugging (useful only to the
+.IR super user ).
+The initial value for this toggle is FALSE.
+.TP
+.I options
+.br
+Toggles the display of some internal
+.I telnet
+protocol processing (having to do with
+.B TELNET
+options).
+The initial value for this toggle is FALSE.
+.TP
+.I netdata
+.br
+Toggles the display of all network data (in hexadecimal format).
+The initial value for this toggle is FALSE.
+.TP
+.I ?
+.br
+Displays the legal
+.B toggle
+commands.
+.RE
+.SH BUGS
+.PP
+There is no adequate way for dealing with flow control.
+.PP
+On some remote systems, echo has to be turned off manually when in
+\*(lqline by line\*(rq mode.
+.PP
+There is enough settable state to justify a
+.RI . telnetrc
+file.
+.PP
+No capability for a
+.RI . telnetrc
+file is provided.
+.PP
+In \*(lqline by line\*(rq mode, the terminal's
+.I eof
+character is only recognized (and sent to the remote system)
+when it is the first character on a line.
Index: /trunk/minix/man/man1/template.1
===================================================================
--- /trunk/minix/man/man1/template.1	(revision 9)
+++ /trunk/minix/man/man1/template.1	(revision 9)
@@ -0,0 +1,46 @@
+.TH TEMPLATE 1
+.SH NAME
+template, blueprint \- a blueprint for making manual pages
+.SH SYNOPSIS
+.B template
+.RB [ \-az ]
+.RI [ arguments " ...]"
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Template
+shows what a manual page should look like.  Options for instance:
+.SH OPTIONS
+.TP
+.B \-a
+Use boldface for characters that have to be typed as is.
+.TP
+.B \-z
+Italics for variable
+.IR arguments .
+.SH ENVIRONMENT
+.TP 15n
+.B MANPATH
+The path to knowledge.
+.SH FILES
+.TP 25n
+.B /usr/man/template.1
+This file.
+.SH "SEE ALSO"
+.BR man (7).
+.SH DIAGNOSTICS
+man: No manual on template.
+.SH NOTES
+Use at your own risk.
+.SH BUGS
+A lot.  The
+.BR whatis (5)
+database is usually generated automatically on most
+systems.  This fails if the "NAME" section has more n/troff fluff than just
+an "\e" before the '\-', or is more than one line.  Apply the KISS
+principle, try to use a minimum of smart macros, match your .RS and .RE's,
+etc.
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man1/term.1
===================================================================
--- /trunk/minix/man/man1/term.1	(revision 9)
+++ /trunk/minix/man/man1/term.1	(revision 9)
@@ -0,0 +1,70 @@
+.TH TERM 1
+.SH NAME
+term \- turn PC into a dumb terminal [IBM]
+.SH SYNOPSIS
+.in +.5i
+.ti -.5i
+\fBterm\fR [\fIbaudrate\fR]\fR [\fIparity\fR] [\fIbits_per_character\fR]
+[\fB\-\fIdial_string\fR] [\fB\-c\fIkcmd\fR] [\fIdevice\fR]\fR
+.in -.5i
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "term 2400" "Talk to modem at 2400 baud"
+.EX "term 1200 7 even" "1200 baud, 7 bits/char, even parity"
+.EX "term 8 9600 /dev/tty01" "9600 baud, 8 bits/char, no parity, use tty01"
+.EX "term -atdt12345 /dev/tty01" "Start with a command to dial out"
+.EX "term -cH'echo Hello World!' ..." "Bind a shell command to the 'H' key"
+.SH DESCRIPTION
+.PP
+\fITerm\fR allows 
+\s-1MINIX 3\s-1
+to talk to a terminal or modem over RS232 
+port 1.  The program first sets the baudrate, parity and character length, 
+and then forks.
+The parent sits in a loop copying from \fIstdin\fR (usually the console's
+keyboard), to the terminal or modem (\fI/dev/tty00\fR).  
+The child sits in a loop
+copying from the terminal or modem (\fI/dev/tty00\fR) to standard output.  
+Thus when
+RS232 port 1 is connected to a modem, every keystroke typed on the keyboard
+is sent to the modem, and every character arriving from the modem is displayed.
+Standard input and output may be redirected, to provide a primitive file
+transfer program, with no checking.  Any argument that starts with
+.B \-at
+is sent out to the modem, usually to dial out.  \fITerm\fP accepts
+several commands that are formed by typing the escape character, CTRL-],
+and a letter.  Type CTRL-]? to see a list of commands.  The subshell command
+is very important, it allows you to type in a ZMODEM command to transfer
+data.  Do not quit \fIterm\fR to do this, or your modem line will be reset!
+\fITerm\fP keeps the modem line open on file descriptor 9 while running the
+subshell, so you can type
+.PP
+.in +.5i
+<&9 >&9
+.in -.5i
+.PP
+at the end of your ZMODEM command to connect it to the modem.  With
+.BI \-c kcmd
+arguments you can bind shell commands to keys.  The character just after
+.BR \-c
+is the key to use, the rest of the characters form the command to bind to the
+key.  This command also has the modem open on file descriptor 9.
+.LP
+Important note: to use \fIterm\fR, it is essential that 
+\fI/etc/ttytab\fR is configured so
+that there is no login session started on the modem line.
+If there is, both the login session and
+term will try to read from the modem, and nothing will work.
+.SH "SEE ALSO"
+.BR rz (1),
+.BR sz (1).
Index: /trunk/minix/man/man1/termcap.1
===================================================================
--- /trunk/minix/man/man1/termcap.1	(revision 9)
+++ /trunk/minix/man/man1/termcap.1	(revision 9)
@@ -0,0 +1,26 @@
+.TH TERMCAP 1
+.SH NAME
+termcap \- print the current termcap entry
+.SH SYNOPSIS
+\fBtermcap\fR [\fItype\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "termcap" "Print the termcap entry"
+.SH DESCRIPTION
+.PP
+\fITermcap\fR reads the /etc/termcap entry corresponding to the 
+terminal type
+supplied as the argument.  If none is given, the current $TERM is used.
+It then prints out all the parameters that apply.
+.SH "SEE ALSO"
+.BR termcap (3).
Index: /trunk/minix/man/man1/tget.1
===================================================================
--- /trunk/minix/man/man1/tget.1	(revision 9)
+++ /trunk/minix/man/man1/tget.1	(revision 9)
@@ -0,0 +1,68 @@
+.TH TGET 1
+.SH NAME
+tget \- get termcap values
+.SH SYNOPSIS
+.B tget
+.RB [ \-flag
+.IR id ]
+.RB [ \-num
+.IR id ]
+.RB [ \-str
+.IR id ]
+.RB [ \-goto
+.IR "col line" ]
+.RB [[ \-echo ]
+.IR string ]
+.SH DESCRIPTION
+.B Tget
+allows shell scripts access to the
+.BR termcap (3)
+functions.  Flags, numbers and strings can be queried from the termcap
+database under the entry denoted by the environment variable
+.BR $TERM .
+.SH OPTIONS
+.TP
+.BI \-flag " id"
+Set the exit status to zero if the flag
+.I id
+is set.  All other options except
+.B \-echo
+set the exit status to
+.I id
+being available or not.  The last option sets the final exit code.
+.TP
+.BI \-num " id"
+Print the value of the numeric variable
+.IR id .
+.TP
+.BI \-str " id"
+Print the value of the string variable
+.IR id .
+.TP
+.BI \-goto " col line"
+Generates instructions to go to the given column and line if the
+.B cm
+capability exists.
+.TP
+.BI \-echo " string"
+Prints
+.IR string .
+Any other argument that does not start with a dash is also printed.
+.SH EXAMPLE
+Try this:
+.B "tget -str so 'Reverse Video' -str se"
+.SH ENVIRONMENT
+.TP 15n
+.B TERM
+Terminal type.
+.TP
+.B TERMCAP
+Path to the termcap database, by default /etc/termcap:/usr/etc/termcap.
+.SH "SEE ALSO"
+.BR termcap (3).
+.SH DIAGNOSTICS
+.B Tget
+will fail immediately with a descriptive message if the termcap entry
+can't be found.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/time.1
===================================================================
--- /trunk/minix/man/man1/time.1	(revision 9)
+++ /trunk/minix/man/man1/time.1	(revision 9)
@@ -0,0 +1,26 @@
+.TH TIME 1
+.SH NAME
+time \- report how long a command takes
+.SH SYNOPSIS
+\fBtime \fIcommand\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "time a.out" "Report how long \fIa.out\fR takes"
+.EX "time ls \-l *.c" "Report how long \fIls\fR takes"
+.SH DESCRIPTION
+.PP
+The command is executed and the real time, user time, and system time (in
+hours, minutes, and seconds) are printed.
+Shell scripts cannot be timed.
+.SH "SEE ALSO"
+.BR times (2).
Index: /trunk/minix/man/man1/top.1
===================================================================
--- /trunk/minix/man/man1/top.1	(revision 9)
+++ /trunk/minix/man/man1/top.1	(revision 9)
@@ -0,0 +1,64 @@
+.TH TOP 1
+.SH NAME
+top \- show processes sorted by CPU usage
+.SH SYNOPSIS
+.B top
+.SH DESCRIPTION
+Top displays a list of all running processes, once every update interval
+(currently 5 seconds). It is sorted by the CPU usage of the processes in
+the last interval. The first display is the CPU usage of processes since
+the boot time.
+
+At the top of the screen, top shows the current system load averages in
+the last 1-minute, 5-minute and 15-minute intervals. Then, over the
+last top interval it displays: the number of alive, active, and sleeping
+processes; memory free; and CPU usage. CPU usage is split into
+user, kernel, system and idle time. Kernel time is time spent by kernel tasks,
+that is tasks that run in kernel mode in kernel address space. System
+time are system user processes, such as drivers and servers. User
+time is all other CPU time.
+
+Then it displays all the alive processes sorted by CPU usage in the last
+interval, with a number of fields for every process. Currently the
+following fields are displayed:
+.PP
+  PID
+    The process id of the process. Some processes (so-called kernel
+    tasks) don't have a real process id, as they are not processes
+    that are managed by the process manager, and aren't visible to
+    other user processes by pid. They are shown by having their process
+    slot number in square brackets.
+  USERNAME
+    The username of the effective uid at which the process runs,
+    or a number if the username could not be looked up.
+  PRI
+    The system scheduling priority the process is currently running as.
+    A lower priority number gives a higher scheduling priority. The
+    lowest is 0. The scale is internal to the kernel.
+  NICE
+    The base scheduling priority the process has been given at startup.
+    0 is normal for a regular user process; the range is -20 to 20
+    (PRIO_MIN and PRIO_MAX in <sys/resource.h>. Most system processes
+    are given higher base priorities.
+  SIZE
+    Text + data size in kilobytes.
+  STATE
+    RUN if the process is runnable, empty if blocking. 
+  TIME
+    Total number of CPU time spent in the process itself. So-called
+    system time (CPU time spent on behalf of this process by another
+    process, generally a system process) is not seen here.
+  CPU
+    Percentage of time that the process was running in the last interval.
+  COMMAND
+    Name of the command that belongs to this process.
+
+.SH "SEE ALSO"
+.BR ps (1)
+.SH BUGS
+This is a from-scratch reimplementation of top for MINIX 3.
+Many features (such as interactive commands) are not implemented.
+Sorting is only done by CPU usage currently. Displayed state is
+only RUN or empty.
+.SH AUTHOR
+Ben Gras (beng@few.vu.nl)
Index: /trunk/minix/man/man1/touch.1
===================================================================
--- /trunk/minix/man/man1/touch.1	(revision 9)
+++ /trunk/minix/man/man1/touch.1	(revision 9)
@@ -0,0 +1,49 @@
+.TH TOUCH 1
+.SH NAME
+touch \- change file access and modification times
+.SH SYNOPSIS
+\fBtouch\fR [\fB\-c\fR] [\fB\-a\fR] [\fB\-m\fR] [\fB\-r\fR file] [\fB\-t\fR [CC[YY]]MMDDhhmm[.ss]] [MMDDhhmm[YY]] \fIfile\fR ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-c" "Do not create the file if it doesn't already exist"
+.FL "\-a" "Change access time"
+.FL "\-m" "Change modification time"
+.FL "\-r file" "Apply time of specified file"
+.FL "\-t [CC[YY]]MMDDhhmm[.ss]]" "Apply time specified"
+.FL "\-t [MMDDhhmm[YY]]" "Apply time specified (alternate form)"
+.SH EXAMPLES
+.EX "touch *.h" "Make the \fI.h\fP files look recent"
+.EX "touch -t 199610010000 *" "Change date and time of all files in current directory to midnight Oct 1, 1996"
+.SH DESCRIPTION
+.PP
+With no options specified, the times of last modification and last access 
+are set to the current time.
+This command is mostly used to trick
+.I make
+into thinking that a file is more recent than it really is.
+If the file being touched does not exist, it is created, unless the \fB\-c\fR
+flag is present.
+.PP
+The \fB\-a\fR or \fB\-m\fR flag may be used to change only the access or 
+modification time. The \fB\-r\fR or \fB\-t\fR flag may be used to change 
+the times to match the times of another file or to a specified time.
+.SH "SEE ALSO"
+.BR utime (2).
+.SH "AUTHOR"
+.PP
+Original author unknown.  Rewritten for POSIX by Peter Holzer
+(hp@vmars.tuwien.ac.at).
+.\" man page updated by A. S. Woodhull 2005-01-15
+
+
+
Index: /trunk/minix/man/man1/tr.1
===================================================================
--- /trunk/minix/man/man1/tr.1	(revision 9)
+++ /trunk/minix/man/man1/tr.1	(revision 9)
@@ -0,0 +1,47 @@
+.TH TR 1
+.SH NAME
+tr \- translate character codes
+.SH SYNOPSIS
+\fBtr\fR [\fB\-cds\fR]\fR [\fIstring1\fR] [\fIstring2\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-c" "Complement the set of characters in \fIstring1\fR"
+.FL "\-d" "Delete all characters specified in \fIstring1\fR"
+.FL "\-s" "Squeeze all runs of characters in \fIstring1\fR to one character"
+.SH EXAMPLES
+.EX "tr \(fmA\-Z\(fm \(fma\-z\(fm <x >y     " "Convert upper case to lower case"
+.EX "tr \-d \(fm0123456789\(fm <f1 >f2  " "Delete all digits from \fIf1\fR"
+.SH DESCRIPTION
+.PP
+.I Tr
+performs simple character translation.
+When no flag is specified, each character in 
+.I string1
+is mapped onto the corresponding character in
+.I string2 .
+.PP
+There are two types of
+.I tr
+out there, one that requires [ and ] for character classes, and one that does
+not.  Here is what the example above would look like for a
+.I tr
+that needs the brackets:
+.PP
+.RS
+.B "tr \(fm[A\-Z]\(fm \(fm[a\-z]\(fm <x >y"
+.RE
+.PP
+Use [ and ] if you want to be portable, because a
+.I tr
+that doesn't need them will still accept the syntax and mindlessly
+translate [ into [ and ] into ].
Index: /trunk/minix/man/man1/true.1
===================================================================
--- /trunk/minix/man/man1/true.1	(revision 9)
+++ /trunk/minix/man/man1/true.1	(revision 9)
@@ -0,0 +1,24 @@
+.TH TRUE 1
+.SH NAME
+true, false \- exit with the value true or false
+.SH SYNOPSIS
+\fBtrue\fR
+.br
+\fBfalse\fR
+.SH EXAMPLES
+.ta +20n
+.ft B
+.nf
+while true	\fR# List the directory until DEL is hit\fP
+do ls \-l
+done
+.fi
+.ft P
+.SH DESCRIPTION
+These commands return the value
+.I true
+or
+.I false .
+They are used for shell programming.
+.SH "SEE ALSO"
+.BR sh (1).
Index: /trunk/minix/man/man1/truncate.1
===================================================================
--- /trunk/minix/man/man1/truncate.1	(revision 9)
+++ /trunk/minix/man/man1/truncate.1	(revision 9)
@@ -0,0 +1,146 @@
+.\"
+.\" Copyright (c) 2000 Sheldon Hearn <sheldonh@FreeBSD.org>.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/usr.bin/truncate/truncate.1,v 1.12 2005/01/17 07:44:32 ru Exp $
+.\"
+.Dd July 4, 2000
+.Dt TRUNCATE 1
+.Os
+.SH NAME
+truncate \- truncate or extend the length of files
+.SH SYNOPSIS
+truncate
+.Op Fl c
+.Bk -words
+.Fl s Xo
+.Sm off
+.Op Cm + | -
+.Ar size
+.Op Cm K | k | M | m | G | g
+.Sm on
+.Xc
+.Ek
+.Ar
+truncate
+.Op Fl c
+.Bk -words
+.Fl r Ar rfile
+.Ek
+.Ar
+.SH DESCRIPTION
+The
+truncate
+utility adjusts the length of each regular file given on the command-line.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl c
+Do not create files if they do not exist.
+The
+truncate
+utility does not treat this as an error.
+No error messages are displayed
+and the exit value is not affected.
+.It Fl r Ar rfile
+Truncate files to the length of the file
+.Ar rfile .
+.It Fl s Xo
+.Sm off
+.Op Cm + | -
+.Ar size
+.Op Cm K | k | M | m | G | g
+.Sm on
+.Xc
+If the
+.Ar size
+argument is preceded by a plus sign
+.Pq Cm + ,
+files will be extended by this number of bytes.
+If the
+.Ar size
+argument is preceded by a dash
+.Pq Cm - ,
+file lengths will be reduced by no more than this number of bytes,
+to a minimum length of zero bytes.
+Otherwise, the
+.Ar size
+argument specifies an absolute length to which all files
+should be extended or reduced as appropriate.
+.Pp
+The
+.Ar size
+argument may be suffixed with one of
+.Cm K ,
+.Cm M
+or
+.Cm G
+(either upper or lower case) to indicate a multiple of
+Kilobytes, Megabytes or Gigabytes
+respectively.
+.El
+.Pp
+Exactly one of the
+.Fl r
+and
+.Fl s
+options must be specified.
+.Pp
+If a file is made smaller, its extra data is lost.
+If a file is made larger,
+it will be extended as if by writing bytes with the value zero.
+If the file does not exist,
+it is created unless the
+.Fl c
+option is specified.
+.Pp
+Note that,
+while truncating a file causes space on disk to be freed,
+extending a file does not cause space to be allocated.
+To extend a file and actually allocate the space,
+it is necessary to explicitly write data to it,
+using (for example) the shell's
+.Ql >>
+redirection syntax, or
+.Xr dd 1 .
+.SH EXIT STATUS
+.Ex -std
+If the operation fails for an argument,
+truncate
+will issue a diagnostic
+and continue processing the remaining arguments.
+.SH SEE ALSO
+.BR dd(1),
+.BR touch(1),
+.BR truncate(2)
+.SH STANDARDS
+The
+truncate
+utility conforms to no known standards.
+.SH HISTORY
+The
+truncate
+utility first appeared in FreeBSD 4.2.
+.SH AUTHORS
+The truncate utility was written by Sheldon Hearn <sheldonh@starjuice.net>.
Index: /trunk/minix/man/man1/tsort.1
===================================================================
--- /trunk/minix/man/man1/tsort.1	(revision 9)
+++ /trunk/minix/man/man1/tsort.1	(revision 9)
@@ -0,0 +1,23 @@
+.TH TSORT 1
+.SH NAME
+tsort \- topological sort [IBM]
+.SH SYNOPSIS
+\fBtsort \fIfile\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "lorder *.s | tsort" "Give library ordering"
+.EX "ar cr libc.a \`lorder *.s | tsort\`" "Build library"
+.SH DESCRIPTION
+.PP
+\fITsort\fR accepts a file of lines containing ordered pairs and builds a
+total ordering from the partial orderings.
Index: /trunk/minix/man/man1/tty.1
===================================================================
--- /trunk/minix/man/man1/tty.1	(revision 9)
+++ /trunk/minix/man/man1/tty.1	(revision 9)
@@ -0,0 +1,26 @@
+.TH TTY 1
+.SH NAME
+tty \- print the device name of this tty
+.SH SYNOPSIS
+\fBtty \fR[\fB\-s\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-s" "Silent mode, only the exit status is affected."
+.SH EXAMPLES
+.EX "tty   " "Print the tty name"
+.SH DESCRIPTION
+.PP
+Print the name of the controlling tty. If the flag \fB\-s\fR is given,
+\fItty\fR is equivalent to the call \fBtest \-t 0\fR.
+.SH "SEE ALSO"
+.BR ttyname (3).
Index: /trunk/minix/man/man1/umount.1
===================================================================
--- /trunk/minix/man/man1/umount.1	(revision 9)
+++ /trunk/minix/man/man1/umount.1	(revision 9)
@@ -0,0 +1,35 @@
+.TH UMOUNT 1
+.SH NAME
+umount \- unmount a mounted file system
+.SH SYNOPSIS
+\fBumount \fR[\fB\-s\fR] \fIspecial\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-s" "Unmount swapspace instead of a file system"
+.SH EXAMPLES
+.EX "umount /dev/fd1" "Unmount diskette 1"
+.SH DESCRIPTION
+.PP
+A mounted file system is unmounted after the cache has been flushed to disk.
+A diskette should never be removed while it is mounted.
+If this happens, and is discovered before another diskette is inserted, the
+original one can be replaced without harm.
+Attempts to unmount a file system holding working directories or open files
+will be rejected with a \&'device busy\&' message.
+.PP
+With the
+.B \-s
+flag one can unmount swap space.
+.SH "SEE ALSO"
+.BR mount (1),
+.BR umount (2).
Index: /trunk/minix/man/man1/uname.1
===================================================================
--- /trunk/minix/man/man1/uname.1	(revision 9)
+++ /trunk/minix/man/man1/uname.1	(revision 9)
@@ -0,0 +1,41 @@
+.TH UNAME 1
+.SH NAME
+uname, arch \- system info
+.SH SYNOPSIS
+\fBuname\fR [\fB\-snrvmpa\fR]\fR
+.br
+\fBarch\fR [\fB\-snrvmpa\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-s" "System name"
+.FL "\-n" "Node/network name"
+.FL "\-r" "Operating system release"
+.FL "\-v" "Operating system version"
+.FL "\-m" "Machine type"
+.FL "\-p" "Processor family"
+.FL "\-a" "Short for \fB\-snrvm\fR"
+.SH EXAMPLES
+.EX "uname -n" "Print the name of the system"
+.EX "arch" "Print the name of the system architecture"
+.SH DESCRIPTION
+.PP
+\fIUname\fP and \fIarch\fP give information about the system.  The options
+indicate which information strings must be printed.  These strings are always
+in the same order.  \fIUname\fP and \fIarch\fP only differ w.r.t. the default
+string to print, \fB\-s\fP and \fB\-p\fP respectively.
+.PP
+The strings are compiled into the commands except for the node name, it is
+obtained from the file \fI/etc/hostname.file\fP.  \fBUname \-m\fP should
+return the actual machine type, not the same string as with \fB\-p\fP.
+.SH "SEE ALSO"
+.BR uname (3).
Index: /trunk/minix/man/man1/unexpand.1
===================================================================
--- /trunk/minix/man/man1/unexpand.1	(revision 9)
+++ /trunk/minix/man/man1/unexpand.1	(revision 9)
@@ -0,0 +1,28 @@
+.TH UNEXPAND 1
+.SH NAME
+unexpand \- convert spaces to tabs
+.SH SYNOPSIS
+\fBunexpand\fR [\fB\-a\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-a" "All spaces are unexpanded"
+.SH EXAMPLES
+.EX "unexpand oldfile >newfile" "Convert leading spaces to tabs"
+.SH DESCRIPTION
+.PP
+\fIUnexpand\fR replaces spaces in the named files with tabs.
+If no files are listed, \fIstdin\fR is given.
+The \fB\-a\fR flag is used to force all sequences of spaces to be
+expanded, instead of just leading spaces (the default).
+.SH "SEE ALSO"
+.BR expand (1).
Index: /trunk/minix/man/man1/uniq.1
===================================================================
--- /trunk/minix/man/man1/uniq.1	(revision 9)
+++ /trunk/minix/man/man1/uniq.1	(revision 9)
@@ -0,0 +1,36 @@
+.TH UNIQ 1
+.SH NAME
+uniq \- delete consecutive identical lines in a file
+.SH SYNOPSIS
+\fBuniq\fR [\fB\-cdu\fR]\fR [\fB\-\fIn\fR] [\fB+\fIn\fR] [\fIinput [\fIoutput\fR]\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-c" "Give count of identical lines in the input"
+.FL "\-d" "Only duplicate lines are written to output"
+.FL "\-u" "Only unique lines are written to output"
+.FL "\-\fIn\fR" "Skip the first \fIn\fR columns when matching"
+.FL "+\fIn\fR" "Skip the first \fIn\fR fields when matching"
+.SH EXAMPLES
+.EX "uniq +2 file" "Ignore first 2 fields when comparing"
+.EX "uniq \-d inf outf" "Write duplicate lines to \fIoutf\fP"
+.SH DESCRIPTION
+.PP
+.I Uniq
+examines a file for consecutive lines that are identical.
+All but duplicate entries are deleted, and the file is written to output.
+The +\fIn\fR option skips the first \fIn\fR fields, where a field is defined
+as a run of characters separated by white space.
+The \-\fIn\fP option skips the first \fIn\fR spaces.
+Fields are skipped first.
+.SH "SEE ALSO"
+.BR sort (1).
Index: /trunk/minix/man/man1/uud.1
===================================================================
--- /trunk/minix/man/man1/uud.1	(revision 9)
+++ /trunk/minix/man/man1/uud.1	(revision 9)
@@ -0,0 +1,33 @@
+.TH UUD 1
+.SH NAME
+uud, uudecode \- decode a binary file encoded with uue
+.SH SYNOPSIS
+\fBuud\fR [\fB\-n\fR]\fR [\fB\-s \fIsrcdir\fR] [\fB\-t \fIdstdir/\fR] \fIfile\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-n" "Do not verify checksums"
+.FL "\-s" "Name of directory where \fI.uue\fR file is"
+.FL "\-t" "Name of directory where output goes"
+.SH EXAMPLES
+.EX "uud file.uue " "Re-create the original file"
+.EX "uud \- <file.uue" "The \- means use \fIstdin\fR"
+.SH DESCRIPTION
+.PP
+\fIUud\fR decodes a file encoded with \fIuue\fR or
+\s-2UNIX\s+2
+\fIuuencode\fR.
+The decoded file is given the name that the original file had.  
+The name information is part of the encoded file.
+Mail headers and other junk before the encoded file are skipped.
+.SH "SEE ALSO"
+.BR uue (1).
Index: /trunk/minix/man/man1/uue.1
===================================================================
--- /trunk/minix/man/man1/uue.1	(revision 9)
+++ /trunk/minix/man/man1/uue.1	(revision 9)
@@ -0,0 +1,43 @@
+.TH UUE 1
+.SH NAME
+uue, uuencode \- encode a binary file to ASCII (e.g., for mailing)
+.SH SYNOPSIS
+\fBuue\fR [\fB\-\fIn\fR] \fIfile\fR [\fB\-\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-\fIn\fR" "How many lines to put in each file"
+.SH EXAMPLES
+.EX "uue file" "Encode \fIfile\fR to \fIfile.uue\fR"
+.EX "uue file \- >x" "Encode \fIfile\fR and write on \fIstdout\fR"
+.EX "uue \-800 file" "Output on \fIfile.uaa\fR, \fIfile.uab\fR etc."
+.SH DESCRIPTION
+.PP
+\fIUuencode\fR is a famous program that converts an arbitrary (usually binary)
+file to an encoding using only 64 ASCII characters.
+\fIUudecode\fR converts it back to the original file.
+The \fIuue\fR and \fIuud\fR programs are the 
+\s-1MINIX 3\s-1
+versions of these programs, and are compatible with the \s-2UNIX\s0 ones.
+The files produced can even be sent successfully over BITNET, which is 
+notorious for mangling files.
+It is possible to have \fIuue\fR automatically split the encoded file up
+into small chunks.
+The output files then get the suffixes \fI.uaa\fR, \fI.uab\fR, etc., instead
+of \fI.uue\fR.
+When \fIuud\fR is given \fIfile.uaa\fR to decode, it automatically includes
+the subsequent pieces.
+The encoding takes 3 bytes (24 bits) from the input file and renders it 
+as 4 bytes in the output file.
+.SH "SEE ALSO"
+.BR btoa (1),
+.BR uud (1).
Index: /trunk/minix/man/man1/vol.1
===================================================================
--- /trunk/minix/man/man1/vol.1	(revision 9)
+++ /trunk/minix/man/man1/vol.1	(revision 9)
@@ -0,0 +1,125 @@
+.TH VOL 1
+.SH NAME
+vol \- split input on or combine output from several volumes
+.SH SYNOPSIS
+.B vol
+.RB [ \-rw1 ]
+.RB [ \-b
+.IR blocksize ]
+.RB [ \-m
+.IR multiple ]
+.RI [ size ]
+.I device
+.SH DESCRIPTION
+.B Vol
+either reads a large input stream from standard input and distributes it
+over several volumes or combines volumes and sends them to
+standard output.  The size of the volumes is determined automatically if
+the device supports this, but may be specified before the
+argument naming the device if automated detection is not possible or if
+only part of the physical volume is used.  The direction of the data is
+automatically determined by checking whether the input or output of
+.B vol
+is a file or pipe.  Use the
+.B \-r
+or
+.B \-w
+flag if you want to specify the direction explicitly, in shell scripts
+for instance.
+.PP
+.B Vol
+waits for each new volume to be inserted, typing return makes it continue.
+If no size is explicitely given then the size of the device is determined
+each time before it is read or written, so it is possible to mix floppies
+of different sizes.  If the size cannot be determined (probably a tape) then
+the device is assumed to be infinitely big.
+.B Vol
+can be used both for block or character devices.  It will buffer the data
+and use a block size appropriate for fixed or variable block sized tapes.
+.PP
+.B Vol
+reads or writes 8192 bytes to block devices, usually floppies.  Character
+devices are read or written using a multiple of 512 bytes.  This multiple
+has an upper limit of 32767 bytes (16-bit machine), 64 kb (32-bit), or even
+1 Mb (32-bit VM).  The last partial write to a character device is padded
+with zeros to the block size.  If a character device is a tape device that
+responds to the
+.BR mtio (4)
+status call then the reported tape block size will be used as the smallest
+unit.  If the tape is a variable block length device then it is read or
+written like a block device, 8192 bytes at the time, with a minimum unit
+of one byte.
+.PP
+All sizes may be suffixed by the letters
+.BR M ,
+.BR k ,
+.BR b
+or
+.BR w
+to multiply the number by mega, kilo, block (512), or word (2).  The volume
+size by default in kilobytes if there is no suffix.
+.SH OPTIONS
+.TP
+.B \-rw
+Explicitly specify reading or writing.  Almost mandatory in scripts.
+.TP
+.B \-1
+Just one volume, start immediately.
+.TP
+.BI \-b " blocksize"
+Specify the device block size.
+.TP
+.BI \-m " multiple"
+Specify the maximum read or write size of multiple blocks.  The
+.B \-b
+and
+.B \-m
+options allow one to modify the block size assumptions that are made above.
+These assumptions are
+.B "\-b 1 \-m 8192"
+for block devices or variable length tapes, and
+.B "\-b 512 \-m 65536"
+for character devices (32 bit machine.)  These options will not override the
+tape block size found out with an
+.BR mtio (4)
+call.  The multiple may be larger then the default if
+.B vol
+can allocate the memory required.
+.SH EXAMPLES
+To back up a tree to floppies as a compressed tarfile:
+.PP
+.RS
+tar cf \- . | compress | vol /dev/fd0
+.RE
+.PP
+To restore a tree from 720 kb images from possibly bigger floppies:
+.PP
+.RS
+vol 720 /dev/fd0 | uncompress | tar xfp \-
+.RE
+.PP
+Read or write a device with 1024 byte blocks:
+.PP
+.RS
+vol \-b 1k /dev/rsd15
+.RE
+.PP
+Read or write a variable block length tape using blocking factor 20 as used
+by default by many
+.BR tar (1)
+commands:
+.PP
+.RS
+vol \-m 20b /dev/rst5
+.RE
+.PP
+Note that
+.B \-m
+was used in the last example.  It sets the size to use to read or write,
+.B \-b
+sets the basic block size that may be written in multiples.
+.SH "SEE ALSO"
+.BR dd (1),
+.BR tar (1),
+.BR mt (1),
+.BR mtio (4).
Index: /trunk/minix/man/man1/wc.1
===================================================================
--- /trunk/minix/man/man1/wc.1	(revision 9)
+++ /trunk/minix/man/man1/wc.1	(revision 9)
@@ -0,0 +1,30 @@
+.TH WC 1
+.SH NAME
+wc \- count characters, words, and lines in a file
+.SH SYNOPSIS
+\fBwc\fR [\fB\-clw\fR] \fIfile\fR ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-c" "Print character count"
+.FL "\-l" "Print line count"
+.FL "\-w" "Print word count"
+.SH EXAMPLES
+.EX "wc file1 file2" "Print all three counts for both files"
+.EX "wc \-l file" "Print line count only"
+.SH DESCRIPTION
+.PP
+.I Wc
+reads each argument and computes the number of characters, words and lines
+it contains.
+A word is delimited by white space (space, tab, or line feed).
+If no flags are present, all three counts are printed.
Index: /trunk/minix/man/man1/whatis.1
===================================================================
--- /trunk/minix/man/man1/whatis.1	(revision 9)
+++ /trunk/minix/man/man1/whatis.1	(revision 9)
@@ -0,0 +1,32 @@
+.TH WHATIS 1
+.SH NAME
+whatis, apropos \- give single line descriptions for manual pages
+.SH SYNOPSIS
+.B whatis
+.RB [ \-a ]
+.I title
+.br
+.B apropos
+.I keyword
+.SH DESCRIPTION
+.B Whatis
+lists the one line description from the
+.BR whatis (5)
+database describing the title given.  It displays all the lines with
+the title from the first whatis file that has those titles.  It uses the
+same search path as
+.BR man (1).
+.PP
+.B Apropos
+searches through all whatis files for the given keywords.  It lists any
+line that has the keyword anywhere on the line.
+.SH OPTIONS
+.TP
+.B \-a
+Search all whatis files.
+.SH "SEE ALSO"
+.BR man (1),
+.BR grep (1),
+.BR whatis (5).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man1/whereis.1
===================================================================
--- /trunk/minix/man/man1/whereis.1	(revision 9)
+++ /trunk/minix/man/man1/whereis.1	(revision 9)
@@ -0,0 +1,26 @@
+.TH WHEREIS 1
+.SH NAME
+whereis \- examine system directories for a given file
+.SH SYNOPSIS
+\fBwhereis \fIfile\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "whereis stat.h" "Prints: \fI/usr/include/sys/stat.h\fR"
+.SH DESCRIPTION
+.PP
+\fIWhereis\fR searches a fixed set of system 
+directories, \fI/bin\fR, \fI/lib\fR, \fI/usr/bin\fR,
+and others, and prints all occurrences of the argument name in any of them.
+.SH "SEE ALSO"
+.BR man (1),
+.BR which (1).
Index: /trunk/minix/man/man1/which.1
===================================================================
--- /trunk/minix/man/man1/which.1	(revision 9)
+++ /trunk/minix/man/man1/which.1	(revision 9)
@@ -0,0 +1,32 @@
+.TH WHICH 1
+.SH NAME
+which \- examine $PATH to see which file will be executed
+.SH SYNOPSIS
+\fBwhich \fIname\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "which a.out" "Tells which \fIa.out\fR will be executed"
+.SH DESCRIPTION
+.PP
+The $PATH shell variable controls the 
+\s-1MINIX 3\s-1
+search rules. 
+If a command \fIa.out\fR is given, the shell first tries to find an 
+executable file in the working directory.  
+If that fails, it looks in various system directories, such as 
+\fI/bin\fR and \fI/usr/bin\fR.  
+The\fR which\fR command makes the same search and gives the absolute
+path of the program that will be chosen, followed by other occurrences
+of the file name along the path.
+.SH "SEE ALSO"
+.BR man (1).
Index: /trunk/minix/man/man1/who.1
===================================================================
--- /trunk/minix/man/man1/who.1	(revision 9)
+++ /trunk/minix/man/man1/who.1	(revision 9)
@@ -0,0 +1,31 @@
+.TH WHO 1
+.SH NAME
+who \- print list of currently logged in users
+.SH SYNOPSIS
+\fBwho\fR [\fIfile\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "who   " "Print user names, terminals and times"
+.SH DESCRIPTION
+.PP
+\fIWho\fR prints a list of currently logged in users.  For each one, 
+the user name, terminal, and login time is printed.  
+This program gets its information from the file \fI/etc/utmp\fR, which 
+is updated by init and login.  
+If the file does not exist, neither of these will create it, and 
+\fIwho\fR will not work.  Note that if you decide to create an empty  
+\fI/usr/adm/wtmp\fR to enable the login accounting, it will grow forever and 
+eventually fill up your disk unless you manually truncate it from time to time.
+If an optional file name is provided, the logins in that file will be printed.
+.SH "SEE ALSO"
+.BR utmp (5).
Index: /trunk/minix/man/man1/whoami.1
===================================================================
--- /trunk/minix/man/man1/whoami.1	(revision 9)
+++ /trunk/minix/man/man1/whoami.1	(revision 9)
@@ -0,0 +1,26 @@
+.TH WHOAMI 1
+.SH NAME
+whoami \- print current user name
+.SH SYNOPSIS
+\fBwhoami\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "whoami" "Print user name"
+.SH DESCRIPTION
+.PP
+In case you forget who you are logged in as, \fIwhoami\fR will tell you.  If
+you use \fIsu\fR to become somebody else, 
+\fIwhoami\fR will give the current effective user.
+.SH "SEE ALSO"
+.BR id (1),
+.BR who (1).
Index: /trunk/minix/man/man1/write.1
===================================================================
--- /trunk/minix/man/man1/write.1	(revision 9)
+++ /trunk/minix/man/man1/write.1	(revision 9)
@@ -0,0 +1,33 @@
+.TH WRITE 1
+.SH NAME
+write \- send a message to a logged-in user
+.SH SYNOPSIS
+\fBwrite\fR [\fB\-cv\fR] \fIuser\fR [\fItty\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-c" "Use cbreak mode"
+.FL "\-v" "Verbose mode"
+.SH EXAMPLES
+.EX "write ast" "Send a message to ast"
+.EX "write ast tty00" "Send a message to ast on tty00"
+.SH DESCRIPTION
+.PP
+\fIWrite\fR lets a user send messages to another logged-in user.  
+Lines typed by the user appear on the other user's screen a line at a time 
+(a character at a time in the case of cbreak mode).  
+The file \fI/usr/adm/wtmp\fR is searched to determine which tty to send to. 
+If the user is logged onto more than one terminal, the \fItty\fR argument
+selects the terminal.  Type CTRL- D to terminate the command.
+Use ! as a shell escape.
+.SH "SEE ALSO"
+.BR mail (1).
Index: /trunk/minix/man/man1/xargs.1
===================================================================
--- /trunk/minix/man/man1/xargs.1	(revision 9)
+++ /trunk/minix/man/man1/xargs.1	(revision 9)
@@ -0,0 +1,176 @@
+.\" Copyright (c) 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" John B. Roll Jr. and the Institute of Electrical and Electronics
+.\" Engineers, Inc.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)xargs.1	5.5 (Berkeley) 6/27/91
+.\"
+.TH XARGS 1 "June 27, 1991"
+.UC 7
+.SH NAME
+xargs \- construct argument list(s) and execute utility.
+.SH SYNOPSIS
+.B xargs
+.RB [ \-ft0 ]
+.RB [[ \-x ]
+.B \-n
+.IR number ]
+.RB [ \-s
+.IR size ]
+.RI [ utility
+.RI [ argument " ...]]"
+.SH DESCRIPTION
+The
+.B xargs
+utility reads space, tab, newline and end-of-file delimited arguments
+from the standard input and executes the specified
+.I utility
+with them as arguments.
+.PP
+The utility and any arguments specified on the command line are given
+to the
+.I utility
+upon each invocation, followed by some number of the arguments read
+from standard input.
+The
+.I utility
+is repeatedly executed until standard input is exhausted.
+.PP
+Spaces, tabs and newlines may be embedded in arguments using single (`` ' '')
+or double (``"'') quotes or backslashes (``\e'').
+Single quotes escape all non-single quote characters, excluding newlines,
+up to the matching single quote.
+Double quotes escape all non-double quote characters, excluding newlines,
+up to the matching double quote.
+Any single character, including newlines, may be escaped by a backslash.
+.PP
+The options are as follows:
+.TP
+.B \-f
+Force
+.B xargs
+to ignore the exit status returned by
+.IR utility .
+By default,
+.B xargs
+will exit immediately if
+.I utility
+exits with a non-zero exit status.
+This does not include ignoring
+.I utility
+exiting due to a signal or without calling
+.BR exit (2).
+.TP
+.BI \-n " number"
+Set the maximum number of arguments taken from standard input for each
+invocation of the utility.
+An invocation of
+.I utility
+will use less than
+.I number
+standard input arguments if the number of bytes accumulated (see the
+.I \-s
+option) exceeds the specified
+.I size
+or there are fewer than
+.I number
+arguments remaining for the last invocation of
+.IR utility .
+The current default value for
+.I number
+is 5000.
+.TP
+.BI \-s " size"
+Set the maximum number of bytes for the command line length provided to
+.IR utility .
+The sum of the length of the utility name and the arguments passed to
+.I utility
+(including NULL terminators) will be less than or equal to this number.
+The current default value for
+.I size
+is ARG_MAX - 2048.
+.TP
+.B \-t
+Echo the command to be executed to standard error immediately before it
+is executed.
+.TP
+.B \-x
+Force
+.B xargs
+to terminate immediately if a command line containing
+.I number
+arguments will not fit in the specified (or default) command line length.
+.TP
+.B \-0
+Read null-byte terminated pathnames from standard input as may have been
+produced by the
+.B \-print0
+option of
+.BR find (1).
+This is a MINIX 3 specific extension to
+.BR xargs .
+.PP
+If no
+.I utility
+is specified,
+.BR echo (1)
+is used.
+.PP
+Undefined behavior may occur if
+.I utility
+reads from the standard input.
+.PP
+.B Xargs
+exits with an exit status of 0 if no error occurs.
+If
+.I utility
+cannot be invoked, is terminated by a signal or terminates without
+calling
+.BR exit (2),
+.B xargs
+exits with an exit status of 127.
+If
+.I utility
+exits with an exit status other than 0,
+.B xargs
+exits with that exit status.
+Otherwise,
+.B xargs
+exits with an exit status of 1.
+.SH "SEE ALSO"
+.BR echo (1),
+.BR find (1).
+.SH STANDARDS
+The
+.B xargs
+utility is expected to be POSIX 1003.2 compliant.
Index: /trunk/minix/man/man1/yacc.1
===================================================================
--- /trunk/minix/man/man1/yacc.1	(revision 9)
+++ /trunk/minix/man/man1/yacc.1	(revision 9)
@@ -0,0 +1,111 @@
+.\"	%W%	%R% (Berkeley) %E%
+.\"
+.TH YACC 1 "July 15, 1990"
+.UC 6
+.SH NAME
+yacc \- an LALR(1) parser generator
+.SH SYNOPSIS
+.B yacc [ -dlrtv ] [ -b
+.I file_prefix
+.B ] [ -p
+.I symbol_prefix
+.B ]
+.I filename
+.SH DESCRIPTION
+.I Yacc
+reads the grammar specification in the file
+.I filename
+and generates an LR(1) parser for it.
+The parsers consist of a set of LALR(1) parsing tables and a driver routine
+written in the C programming language.
+.I Yacc
+normally writes the parse tables and the driver routine to the file
+.IR y.tab.c.
+.PP
+The following options are available:
+.RS
+.TP
+\fB-b \fIfile_prefix\fR
+The
+.B -b
+option changes the prefix prepended to the output file names to
+the string denoted by
+.IR file_prefix.
+The default prefix is the character
+.IR y.
+.TP
+.B -d
+The \fB-d\fR option causes the header file
+.IR y.tab.h
+to be written.
+.TP
+.B -l
+If the
+.B -l
+option is not specified,
+.I yacc
+will insert #line directives in the generated code.
+The #line directives let the C compiler relate errors in the
+generated code to the user's original code.
+If the \fB-l\fR option is specified,
+.I yacc
+will not insert the #line directives.
+\&#line directives specified by the user will be retained.
+.TP
+\fB-p \fIsymbol_prefix\fR
+The
+.B -p
+option changes the prefix prepended to yacc-generated symbols to
+the string denoted by
+.IR symbol_prefix.
+The default prefix is the string
+.IR yy.
+.TP
+.B -r
+The
+.B -r
+option causes
+.I yacc
+to produce separate files for code and tables.  The code file
+is named
+.IR y.code.c,
+and the tables file is named
+.IR y.tab.c.
+.TP
+.B -t
+The
+.B -t
+option changes the preprocessor directives generated by
+.I yacc
+so that debugging statements will be incorporated in the compiled code.
+.TP
+.B -v
+The
+.B -v
+option causes a human-readable description of the generated parser to
+be written to the file
+.IR y.output.
+.RE
+.PP
+If the environment variable TMPDIR is set, the string denoted by
+TMPDIR will be used as the name of the directory where the temporary
+files are created.
+.SH FILES
+.IR y.code.c
+.br
+.IR y.tab.c
+.br
+.IR y.tab.h
+.br
+.IR y.output
+.br
+.IR /tmp/yacc.aXXXXXX
+.br
+.IR /tmp/yacc.tXXXXXX
+.br
+.IR /tmp/yacc.uXXXXXX
+.SH DIAGNOSTICS
+If there are rules that are never reduced, the number of such rules is
+reported on standard error.
+If there are any LALR(1) conflicts, the number of conflicts is reported
+on standard error.
Index: /trunk/minix/man/man1/yap.1
===================================================================
--- /trunk/minix/man/man1/yap.1	(revision 9)
+++ /trunk/minix/man/man1/yap.1	(revision 9)
@@ -0,0 +1,391 @@
+.\" $Header: /cvsup/minix/src/man/man1/yap.1,v 1.1 2005/05/02 13:01:39 beng Exp $
+.\" nroff -man yap.1
+.tr ~
+.TH YAP 1 local
+.SH NAME
+yap, more \- yet another pager
+.SH SYNOPSIS
+.B yap
+.RB [ \-cnuq ]
+.RB [ \-\fIn\fP ]
+.RB [ +\fIcommand\fP ]
+.RI [ file " ...]"
+.SH DESCRIPTION
+.B Yap
+is a program allowing the user to examine a continuous text one screenful at
+a time on a video display terminal.
+It does so by
+pausing after each screenful, waiting for the user to type a command.
+The commands are enumerated later.
+.BR Yap 's
+main feature is, that it can page both forwards and backwards,
+even when reading from standard input.
+.PP
+The command line options are:
+.TP
+.I \-n
+An integer which is the size (in lines) of a page (the initial
+.IR page-size .
+.TP
+.B \-c
+Normally,
+.B yap
+will display each page by beginning at the top of the screen and erasing 
+each line just before it displays on it. If your terminal cannot erase a line,
+.B yap
+will clear the screen before it displays a page.
+.br
+This avoids scrolling the screen, making it easier to read while 
+.B yap 
+is writing.
+The
+.B -c
+option causes
+.B yap
+to scroll the screen instead of beginning at the top of the screen.
+This is also done if your terminal cannot either erase a line or clear the
+screen.
+.TP
+.B \-u
+Normally,
+.B yap
+handles underlining such as produced by nroff in a manner appropriate
+to the particular terminal: if the terminal can perform underlining well
+(t.i., the escape sequences for underlining do not occupy space on the
+screen),
+.B yap
+will underline underlined information in the input. The
+.B -u
+option supresses this underlining.
+.TP
+.B \-n
+Normally,
+.B yap
+also recognises escape sequences for stand-out mode or underlining mode
+in the input, and knows how much space these escape sequences will
+occupy on the screen, so that
+.B yap
+will not fold lines erroneously.
+The
+.B -n
+option supresses this pattern matching.
+.TP
+.B \-q
+This option will cause
+.B yap
+to exit only on the "quit" command.
+.TP
+.BI + command
+\fIcommand\fP is taken to be an initial command to
+.BR yap .
+.PP
+.B Yap
+looks in the
+.B YAP
+environment variable
+to pre-set flags.
+For instance, if you prefer the
+.B -c
+mode of operation, just set the
+.B YAP
+environment variable to
+.BR -c .
+.PP
+The commands of
+.B yap
+can be bound to sequences of keystrokes.
+The environment variable
+.B YAPKEYS
+may contain the bindings in the
+form of a list of colon-separated `name=sequence' pairs.
+The
+.I name
+is a short mnemonic for the command, the
+.I sequence
+is the sequence of keystrokes to be typed to invoke the command.
+This sequence may contain a ^X escape, which means control-X,
+and a \\X escape, which means X. The latter can be used to get
+the characters `^', `\\' and `:' in the sequence.
+There are two keymaps available, the default one and a user-defined one.
+You can switch between one and the other with the
+.I change keymap
+command.
+.PP
+The
+.B yap
+commands are described below.
+The mnemonics for the commands are given in parentheses. The default
+key sequences (if any) are given after the mnemonic.
+Every command takes an optional integer argument, which may be typed
+before the command. Some commands just ignore it. The integer argument
+is referred to as
+.IR i .
+Usually, if
+.I i
+is not given, it defaults to 1.
+.de Nc
+.PP
+\&\\$1
+.RI ( \\$2 )
+.BR \\$3
+.br
+.RS
+..
+.de Ec
+.RE
+..
+.Nc "visit previous file" bf P
+Visit the
+.IR i -th
+previous file given in the command line.
+.Ec
+.Nc "scroll one line up or go to line" bl "^K ~or~ k"
+If
+.I i
+is not given, scroll one line up. Otherwise,
+.I i
+will be interpreted as a line number. A page starting with the line
+indicated will then be displayed.
+.Ec
+.Nc "bottom" bot "l ~or~ $"
+Go to the last line of the input.
+.Ec
+.Nc "display previous page" bp -
+Display the previous page, consisting of
+.I i
+lines, (or
+.I page-size
+lines if no argument is given).
+.Ec
+.Nc "display previous page and set pagesize" bps Z
+Display the previous page, consisting of
+.I i
+lines, (or
+.I page-size
+lines if no argument is given).
+If
+.I i
+is given, the
+.I page-size
+is set to
+.IR i .
+.Ec
+.Nc "scroll up" bs ^B
+Scroll up
+.I i
+lines (or
+.I scroll-size
+lines if
+.I i
+is not given. Initially, the
+.I scroll-size
+is 11).
+.Ec
+.Nc "search backwards for pattern" bse ?
+Search backwards for the
+.IR i -th
+occurrence of a regular expression which will be prompted for.
+If there are less than
+.I i
+occurrences of the expression, the position in the file remains unchanged.
+Otherwise, a page is displayed, starting two lines before the place where the
+expression was found. The user's erase and kill characters may be used
+to edit the expression.
+Erasing back past the first character cancels the search command.
+.br
+Note: Some systems do not have
+.BR regex (3).
+On those systems, searches are still supported, but regular expressions
+are not.
+.Ec
+.Nc "skip lines backwards" bsl S
+Skip
+.I i
+lines backwards and display a page.
+.Ec
+.Nc "skip pages backwards" bsp F
+Skip
+.I i
+pages backwards and display a page.
+.Ec
+.Nc "scroll up and set scrollsize" bss b
+Scroll up
+.I i
+lines (or
+.I scroll-size
+lines if
+.I i
+is not given.
+If
+.I i
+is given, the
+.I scroll-size
+is set to
+.IR i .
+.Ec
+.Nc "change key map" chm X
+Change from the current key map to the other (if there is one).
+.Ec
+.Nc "exchange current page and mark" exg x
+Set the mark to the current page, and display the previously marked
+page.
+.Ec
+.Nc "visit next file" ff N
+Visit the
+.IR i -th
+next file given in the command line.
+.Ec
+.Nc "scroll one line down or go to line" fl "^J ~or~ ^M ~or~ j"
+If
+.I i
+is not given, scroll one line down. Otherwise,
+.I i
+will be interpreted as a line number. A page starting with the line
+indicated will then be displayed.
+.Ec
+.Nc "display next page" fp <space>
+Display the next page, consisting of
+.I i
+lines, (or
+.I page-size
+lines if no argument is given).
+.Ec
+.Nc "display next page and set pagesize" fps z
+Display the next page, consisting of
+.I i
+lines, (or
+.I page-size
+lines if no argument is given).
+If
+.I i
+is given, the
+.I page-size
+is set to
+.IR i .
+.Ec
+.Nc "scroll down" fs ^D
+Scroll down 
+.I i
+lines (or
+.I scroll-size
+lines if no argument is given).
+.Ec
+.Nc "search forwards for pattern" fse /
+Search forwards for the
+.IR i -th
+occurrence of a regular expression which will be prompted for.
+If there are less than
+.I i
+occurrences of the expression, the position in the file remains unchanged.
+Otherwise, a page is displayed, starting two lines before the place where the
+expression was found. The user's erase and kill characters may be used
+to edit the expression.
+Erasing back past the first character cancels the search command.
+.br
+Note: Some systems do not have
+.BR regex (3).
+On those systems, searches are still supported, but regular expressions
+are not.
+.Ec
+.Nc "skip lines forwards" fsl s
+Skip
+.I i
+lines and display a page.
+.Ec
+.Nc "skip pages forwards" fsp f
+Skip
+.I i
+pages and display a page.
+.Ec
+.Nc "scroll down and set scrollsize" fss d
+Scroll down
+.I i
+lines (or
+.I scroll-size
+lines if
+.I i
+is not given.
+If
+.I i
+is given, the
+.I scroll-size
+is set to
+.IR i .
+.Ec
+.Nc "help" hlp h
+Give a short description of all commands that are bound to a key sequence.
+.Ec
+.Nc "set a mark" mar m
+Set a mark on the current page.
+.Ec
+.Nc "repeat last search" nse n
+Search for the 
+.IR i -th
+occurrence of the last regular expression entered, in the direction of the
+last search.
+.Ec
+.Nc "repeat last search in other direction" nsr r
+Search for the
+.IR i -th
+occurrence of the last regular expression entered, but in the other direction.
+.Ec
+.Nc "quit" qui "Q ~or~ q"
+Exit from
+.BR yap .
+.Ec
+.Nc "redraw" red ^L
+Redraw the current page.
+.Ec
+.Nc "repeat" rep .
+Repeat the last command. This does not always make sense, so not all
+commands can be repeated.
+.Ec
+.Nc "shell escape" shl !
+Invoke the shell with a command that will be prompted for.
+In the command, the characters `%' and `!' are replaced with the
+current file name and the previous shell command respectively.
+The sequences `\\%' and `\\!' are replaced by `%' and `!' respectively.
+The user's erase and kill characters can be used to edit the command.
+Erasing back past the first character cancels the command.
+.Ec
+.Nc "pipe to shell command" pip |
+Pipe the current input file into a shell command that will be prompted for.
+The comments given in the description of the shell escape command apply here
+too.
+.Ec
+.Nc "go to mark" tom '
+Display the marked page.
+.Ec
+.Nc "top" top ^^
+Display a page starting with the first line of the input.
+.Ec
+.Nc "visit file" vis e
+Visit a new file. The filename will be prompted for. If you just
+type a return, the current file is revisited.
+.Ec
+.Nc "write input to a file" wrf w
+Write the input to a file, whose name will be prompted for.
+.Ec
+.PP
+The commands take effect immediately, i.e., it is not necessary to
+type a carriage return.
+Up to the time when the command sequence itself is given,
+the user may give an interrupt to cancel the command
+being formed.
+.SH AUTHOR
+Ceriel J.H. Jacobs
+.SH SEE ALSO
+.BR regex (3).
+.SH BUGS
+.B Yap
+will find your terminal very stupid and act like it,
+if it has no way of placing the
+cursor on the home position, or cannot either
+erase a line or
+insert one.
+.PP
+In lines longer than about 2000 characters, a linefeed is silently inserted.
+.PP
+The percentage, given in the prompt when
+.B yap
+reads from a file (and knows it), is not always very accurate.
Index: /trunk/minix/man/man1/yes.1
===================================================================
--- /trunk/minix/man/man1/yes.1	(revision 9)
+++ /trunk/minix/man/man1/yes.1	(revision 9)
@@ -0,0 +1,25 @@
+.TH YES 1
+.SH NAME
+yes \- an endless stream of the same word
+.SH SYNOPSIS
+\fByes\fR [\fIanswer\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "yes | script" "Answer yes to all questions from the script"
+.SH DESCRIPTION
+.PP
+\fIYes\fP sends out an endless stream of y's, each on one line.  One
+uses it to automatically say "yes" to all questions a command may ask.
+This is useful for commands that ask too many "Are you sure?" questions.
+The optional argument makes \fIyes\fP use \fIanswer\fP as the word to
+print instead of a single y character.
Index: /trunk/minix/man/man2/access.2
===================================================================
--- /trunk/minix/man/man2/access.2	(revision 9)
+++ /trunk/minix/man/man2/access.2	(revision 9)
@@ -0,0 +1,109 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)access.2	6.5 (Berkeley) 5/22/86
+.\"
+.TH ACCESS 2 "May 22, 1986"
+.UC 4
+.SH NAME
+access \- determine accessibility of file
+.SH SYNOPSIS
+.ft B
+.nf
+#include <sys/types.h>
+#include <unistd.h>
+.PP
+.ft B
+.ta 1.25i 1.6i
+.nf
+#define R_OK	4	/* test for read permission */
+#define W_OK	2	/* test for write permission */
+#define X_OK	1	/* test for execute (search) permission */
+#define F_OK	0	/* test for presence of file */
+.PP
+.ft B
+.nf
+int access(const char *\fIpath\fP, mode_t \fImode\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Access
+checks the given
+file
+.I path
+for accessibility according to
+.IR mode ,
+which is an inclusive or of the bits
+.BR R_OK ,
+.BR W_OK
+and
+.BR X_OK .
+Specifying
+.I mode
+as
+.B F_OK
+(i.e., 0)
+tests whether the directories leading to the file can be
+searched and the file exists.
+.PP
+The real user ID and the group access list
+(including the real group ID) are
+used in verifying permission, so this call
+is useful to set-UID programs.
+.PP
+Notice that only access bits are checked.
+A directory may be indicated as writable by
+.BR access ,
+but an attempt to open it for writing will fail
+(although files may be created there);
+a file may look executable, but
+.B execve
+will fail unless it is in proper format.
+.SH "RETURN VALUE
+If
+.I path
+cannot be found or if any of the desired access modes would
+not be granted, then a \-1 value is returned; otherwise
+a 0 value is returned.
+.SH "ERRORS
+Access to the file is denied if one or more of the following are true:
+.TP 15
+[ENOTDIR]
+A component of the path prefix is not a directory.
+.TP 15
+[ENAMETOOLONG]
+The path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+The named file does not exist.
+.TP 15
+[EACCES]
+Search permission is denied for a component of the path prefix.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating the pathname.
+(Minix-vmd)
+.TP 15
+[EROFS]
+Write access is requested for a file on a read-only file system.
+.TP 15
+[EACCES]
+Permission bits of the file mode do not permit the requested
+access, or search permission is denied on a component of the
+path prefix.  The owner of a file has permission checked with
+respect to the ``owner'' read, write, and execute mode bits,
+members of the file's group other than the owner have permission
+checked with respect to the ``group'' mode bits, and all
+others have permissions checked with respect to the ``other''
+mode bits.
+.TP 15
+[EFAULT]
+.I Path
+points outside the process's allocated address space.
+.TP 15
+[EIO]
+An I/O error occurred while reading from or writing to the file system.
+.SH "SEE ALSO
+.BR chmod (2),
+.BR stat (2).
Index: /trunk/minix/man/man2/alarm.2
===================================================================
--- /trunk/minix/man/man2/alarm.2	(revision 9)
+++ /trunk/minix/man/man2/alarm.2	(revision 9)
@@ -0,0 +1,38 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)alarm.3c	6.3 (Berkeley) 5/27/86
+.\"
+.TH ALARM 2  "May 27, 1986"
+.UC 4
+.SH NAME
+alarm \- schedule signal after specified time
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+unsigned int alarm(unsigned int \fIseconds\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Alarm
+causes signal SIGALRM, see
+.BR sigaction (2),
+to be sent to the invoking process
+in a number of seconds given by the argument.
+Unless caught or ignored, the signal terminates the process.
+.PP
+Alarm requests are not stacked; successive calls reset the alarm clock.
+If the argument is 0, any alarm request is canceled.
+Because of scheduling delays,
+resumption of execution of when the signal is
+caught may be delayed an arbitrary amount.
+.PP
+The return value is the amount of time previously remaining in the alarm clock.
+.SH "SEE ALSO"
+.BR pause (2),
+.BR sigsuspend (2),
+.BR sigaction (2),
+.BR sleep (3).
Index: /trunk/minix/man/man2/brk.2
===================================================================
--- /trunk/minix/man/man2/brk.2	(revision 9)
+++ /trunk/minix/man/man2/brk.2	(revision 9)
@@ -0,0 +1,86 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)brk.2	6.3 (Berkeley) 5/22/86
+.\"
+.TH BRK 2 "May 22, 1986"
+.UC 4
+.SH NAME
+brk, sbrk \- change data segment size
+.SH SYNOPSIS
+.nf
+#include <unistd.h>
+.PP
+.ft B
+int brk(char *\fIaddr\fP)
+.PP
+.ft B
+char *sbrk(int \fIincr\fP)
+.fi
+.SH DESCRIPTION
+.B Brk
+sets the system's idea of the lowest data segment 
+location not used by the program (called the break)
+to
+.IR addr .
+Locations greater than
+.I addr
+and below the stack pointer
+are not in the address space and will thus
+cause a memory violation if accessed.
+.PP
+In the alternate function
+.BR sbrk ,
+.I incr
+more bytes are added to the
+program's data space and a pointer to the
+start of the new area is returned.
+.PP
+When a program begins execution via
+.B execve
+the break is set at the
+highest location defined by the program
+and data storage areas.
+Ordinarily, therefore, only programs with growing
+data areas need to use
+.BR sbrk .
+.SH "RETURN VALUE
+The address of the new break is returned if
+.B brk
+succeeds;
+.B \-1
+if the program requests more
+memory than the system limit.
+.B Sbrk
+returns
+.B \-1
+if the break could not be set.
+.SH ERRORS
+.B Sbrk
+will fail and no additional memory will be allocated if
+one of the following are true:
+.TP 15
+[ENOMEM]
+The maximum possible size of a data segment (as set by
+.BR chmem (1))
+was exceeded.
+.TP 15
+[ENOMEM]
+Insufficient virtual memory space existed
+to support the expansion.  (Minix-vmd)
+.SH "SEE ALSO"
+.BR chmem (1),
+.BR execve (2),
+.BR malloc (3),
+.BR end (3).
+.SH NOTES
+Minix-vmd rounds a small data segment limit up to 3 megabytes.
+.SH BUGS
+Setting the break may fail due to a temporary lack of
+virtual memory under Minix-vmd.  It is not possible to distinguish this
+from a failure caused by exceeding the maximum size of
+the data segment.
+
+.\"
+.\" $PchId: brk.2,v 1.2 2000/08/11 20:05:51 philip Exp $
Index: /trunk/minix/man/man2/chdir.2
===================================================================
--- /trunk/minix/man/man2/chdir.2	(revision 9)
+++ /trunk/minix/man/man2/chdir.2	(revision 9)
@@ -0,0 +1,66 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)chdir.2	6.3 (Berkeley) 8/26/85
+.\"
+.TH CHDIR 2 "August 26, 1985"
+.UC 4
+.SH NAME
+chdir, fchdir \- change current working directory
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+int chdir(const char *\fIpath\fP)
+int fchdir(int \fIfd\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.I Path
+is the pathname of a directory.
+.I Fd
+is the file descriptor of a directory.
+
+.B Chdir
+causes this directory
+to become the current working directory,
+the starting point for path names not beginning with ``/''.
+.PP
+In order for a directory to become the current directory,
+a process must have execute (search) access to the directory.
+.SH "RETURN VALUE
+Upon successful completion, a value of 0 is returned.
+Otherwise, a value of \-1 is returned and \fBerrno\fP is set to indicate
+the error.
+.SH ERRORS
+.B Chdir
+will fail and the current working directory will be unchanged if
+one or more of the following are true:
+.TP 15
+[ENOTDIR]
+A component of the path prefix is not a directory.
+.TP 15
+[ENAMETOOLONG]
+The path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+The named directory does not exist.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating the pathname.
+(Minix-vmd)
+.TP 15
+[EACCES]
+Search permission is denied for any component of
+the path name.
+.TP 15
+[EFAULT]
+.I Path
+points outside the process's allocated address space.
+.TP 15
+[EIO]
+An I/O error occurred while reading from or writing to the file system.
+.SH "SEE ALSO"
+.BR chroot (2).
Index: /trunk/minix/man/man2/chmod.2
===================================================================
--- /trunk/minix/man/man2/chmod.2	(revision 9)
+++ /trunk/minix/man/man2/chmod.2	(revision 9)
@@ -0,0 +1,132 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)chmod.2	6.5 (Berkeley) 5/13/86
+.\"
+.TH CHMOD 2 "May 13, 1986"
+.UC 4
+.SH NAME
+chmod \- change mode of file
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <sys/stat.h>
+
+int chmod(const char *\fIpath\fP, mode_t \fImode\fP)
+.ig \" You never know
+.PP
+.ft B
+int fchmod(int \fIfd\fP, mode_t \fImode\fP)
+..
+.fi
+.SH DESCRIPTION
+The file whose name
+is given by \fIpath\fP
+.ig
+or referenced by the descriptor
+.I fd
+..
+has its mode changed to
+.IR mode .
+Modes are constructed by
+.IR or 'ing
+together some
+combination of the following, defined in
+.IR <sys/stat.h> :
+.PP
+.RS
+.nf
+.ta \w'S_ISUID\ \ 'u +\w'04000\ \ \ 'u
+S_ISUID	04000	set user ID on execution
+S_ISGID	02000	set group ID on execution
+S_ISVTX	01000	`sticky bit' (see below)
+S_IRWXU	00700	read, write, execute by owner
+S_IRUSR	00400	read by owner
+S_IWUSR	00200	write by owner
+S_IXUSR	00100	execute (search on directory) by owner
+S_IRWXG	00070	read, write, execute by group
+S_IRGRP	00040	read by group
+S_IWGRP	00020	write by group
+S_IXGRP	00010	execute (search on directory) by group
+S_IRWXO	00007	read, write, execute by others
+S_IROTH	00004	read by others
+S_IWOTH	00002	write by others
+S_IXOTH	00001	execute (search on directory) by others
+.fi
+.RE
+.PP
+If mode ISVTX (the `sticky bit') is set on a directory,
+an unprivileged user may not delete or rename
+files of other users in that directory.  (Minix-vmd)
+.PP
+Only the owner of a file (or the super-user) may change the mode.
+.PP
+Writing or changing the owner of a file
+turns off the set-user-id and set-group-id bits
+unless the user is the super-user.
+This makes the system somewhat more secure
+by protecting set-user-id (set-group-id) files
+from remaining set-user-id (set-group-id) if they are modified,
+at the expense of a degree of compatibility.
+.SH "RETURN VALUE
+Upon successful completion, a value of 0 is returned.
+Otherwise, a value of \-1 is returned and
+.B errno
+is set to indicate the error.
+.SH "ERRORS
+.B Chmod
+will fail and the file mode will be unchanged if:
+.TP 15
+[ENOTDIR]
+A component of the path prefix is not a directory.
+.TP 15
+[ENAMETOOLONG]
+The path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+The named file does not exist.
+.TP 15
+[EACCES]
+Search permission is denied for a component of the path prefix.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating the pathname.
+(Minix-vmd)
+.TP 15
+[EPERM]
+The effective user ID does not match the owner of the file and
+the effective user ID is not the super-user.
+.TP 15
+[EROFS]
+The named file resides on a read-only file system.
+.TP 15
+[EFAULT]
+.I Path
+points outside the process's allocated address space.
+.TP 15
+[EIO]
+An I/O error occurred while reading from or writing to the file system.
+.ig
+.PP
+.I Fchmod
+will fail if:
+.TP 15
+[EBADF]
+The descriptor is not valid.
+.TP 15
+[EROFS]
+The file resides on a read-only file system.
+.TP 15
+[EIO]
+An I/O error occurred while reading from or writing to the file system.
+..
+.SH "SEE ALSO"
+.BR chmod (1),
+.BR open (2),
+.BR chown (2),
+.BR stat (2).
+.SH NOTES
+The sticky bit was historically used to lock important executables into
+memory.
Index: /trunk/minix/man/man2/chown.2
===================================================================
--- /trunk/minix/man/man2/chown.2	(revision 9)
+++ /trunk/minix/man/man2/chown.2	(revision 9)
@@ -0,0 +1,102 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)chown.2	6.6 (Berkeley) 5/22/86
+.\"
+.TH CHOWN 2 "May 22, 1986"
+.UC 4
+.SH NAME
+chown \- change owner and group of a file
+.SH SYNOPSIS
+.nf
+.ft B
+int chown(const char *\fIpath\fP, int \fIowner\fP, int \fIgroup\fP)
+.ig \" You never know
+.PP
+.ft B
+int fchown(int \fIfd\fP, int \fIowner\fP, int \fIgroup\fP)
+..
+.fi
+.SH DESCRIPTION
+The file
+that is named by \fIpath\fP
+.ig
+or referenced by \fIfd\fP
+..
+has its
+.I owner
+and 
+.I group
+changed as specified.
+Only the super-user
+may change the owner of the file,
+because if users were able to give files away,
+they could defeat file-space accounting procedures.
+The owner of the file may change the group
+to a group of which he is a member.
+.PP
+On some systems,
+.I chown
+clears the set-user-id and set-group-id bits
+on the file
+to prevent accidental creation of
+set-user-id and set-group-id programs.
+.SH "RETURN VALUE
+Zero is returned if the operation was successful;
+\-1 is returned if an error occurs, with a more specific
+error code being placed in the global variable \fBerrno\fP.
+.SH "ERRORS
+.B Chown
+will fail and the file will be unchanged if:
+.TP 15
+[ENOTDIR]
+A component of the path prefix is not a directory.
+.TP 15
+[ENAMETOOLONG]
+The path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+The named file does not exist.
+.TP 15
+[EACCES]
+Search permission is denied for a component of the path prefix.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating the pathname.
+(Minix-vmd)
+.TP 15
+[EPERM]
+The effective user ID is not the super-user.
+.TP 15
+[EROFS]
+The named file resides on a read-only file system.
+.TP 15
+[EFAULT]
+.I Path
+points outside the process's allocated address space.
+.TP 15
+[EIO]
+An I/O error occurred while reading from or writing to the file system.
+.ig
+.PP
+.B Fchown
+will fail if:
+.TP 15
+[EBADF]
+.I Fd
+does not refer to a valid descriptor.
+.TP 15
+[EPERM]
+The effective user ID is not the super-user.
+.TP 15
+[EROFS]
+The named file resides on a read-only file system.
+.TP 15
+[EIO]
+An I/O error occurred while reading from or writing to the file system.
+..
+.SH "SEE ALSO"
+.BR chown (8),
+.BR chgrp (1),
+.BR chmod (2).
Index: /trunk/minix/man/man2/chroot.2
===================================================================
--- /trunk/minix/man/man2/chroot.2	(revision 9)
+++ /trunk/minix/man/man2/chroot.2	(revision 9)
@@ -0,0 +1,62 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)chroot.2	6.3 (Berkeley) 8/26/85
+.\"
+.TH CHROOT 2 "August 26, 1985"
+.UC 5
+.SH NAME
+chroot \- change root directory
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+int chroot(const char *\fIdirname\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.I Dirname
+is the address of the pathname of a directory, terminated by a null byte.
+.B Chroot
+causes this directory
+to become the root directory,
+the starting point for path names beginning with ``/''.
+.PP
+In order for a directory to become the root directory
+a process must have execute (search) access to the directory.
+.PP
+This call is restricted to the super-user.
+.SH "RETURN VALUE
+Upon successful completion, a value of 0 is returned.  Otherwise,
+a value of \-1 is returned and \fBerrno\fP is set to indicate an error.
+.SH ERRORS
+.B Chroot
+will fail and the root directory will be unchanged if
+one or more of the following are true:
+.TP 15
+[ENOTDIR]
+A component of the path name is not a directory.
+.TP 15
+[ENAMETOOLONG]
+The path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+The named directory does not exist.
+.TP 15
+[EACCES]
+Search permission is denied for any component of the path name.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating the pathname.
+(Minix-vmd)
+.TP 15
+[EFAULT]
+.I Path
+points outside the process's allocated address space.
+.TP 15
+[EIO]
+An I/O error occurred while reading from or writing to the file system.
+.SH "SEE ALSO"
+.BR chdir (2).
Index: /trunk/minix/man/man2/close.2
===================================================================
--- /trunk/minix/man/man2/close.2	(revision 9)
+++ /trunk/minix/man/man2/close.2	(revision 9)
@@ -0,0 +1,84 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)close.2	6.3 (Berkeley) 5/22/86
+.\"
+.TH CLOSE 2 "May 22, 1986"
+.UC 4
+.SH NAME
+close \- delete a descriptor
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+int close(int \fId\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+The
+.B close
+call deletes a descriptor from the per-process object
+reference table.
+If this is the last reference to the underlying object, then
+it will be deactivated.
+For example, on the last close of a file
+the current \fIseek\fP pointer associated with the file is lost;
+on the last close of a TCP/IP descriptor
+associated naming information and queued data are discarded;
+on the last close of a file holding an advisory lock
+the lock is released (see further
+.BR fcntl (2)).
+.PP
+A close of all of a process's descriptors is automatic on
+.IR exit ,
+but since
+there is a limit on the number of active descriptors per process,
+.B close
+is necessary for programs that deal with many descriptors.
+.PP
+When a process forks (see
+.BR fork (2)),
+all descriptors for the new child process reference the same
+objects as they did in the parent before the fork.
+If a new process is then to be run using
+.BR execve (2),
+the process would normally inherit these descriptors.  Most
+of the descriptors can be rearranged with
+.BR dup2 (2)
+or deleted with
+.B close
+before the
+.B execve
+is attempted, but if some of these descriptors will still
+be needed if the
+.B execve
+fails, it is necessary to arrange for them to be closed if the
+.B execve
+succeeds.
+For this reason, the call ``fcntl(d, F_SETFD, \fIflags\fR)'' is provided,
+that can be used to mark a descriptor "close on exec" by setting
+the
+.B FD_CLOEXEC
+flag:
+.PP
+.RS
+fcntl(d, F_SETFD, fcntl(d, F_GETFD) | FD_CLOEXEC);
+.RE
+.SH "RETURN VALUE
+Upon successful completion, a value of 0 is returned.
+Otherwise, a value of \-1 is returned and the global integer variable
+.B errno
+is set to indicate the error.
+.SH ERRORS
+.B Close
+will fail if:
+.TP 15
+[EBADF]
+\fID\fP is not an active descriptor.
+.SH "SEE ALSO"
+.BR open (2),
+.BR pipe (2),
+.BR execve (2),
+.BR fcntl (2).
Index: /trunk/minix/man/man2/creat.2
===================================================================
--- /trunk/minix/man/man2/creat.2	(revision 9)
+++ /trunk/minix/man/man2/creat.2	(revision 9)
@@ -0,0 +1,142 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)creat.2	6.6 (Berkeley) 5/22/86
+.\"
+.TH CREAT 2 "May 22, 1986"
+.UC 4
+.SH NAME
+creat \- create a new file
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <fcntl.h>
+
+int creat(const char *\fIname\fP, mode_t \fImode\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.ft B
+This interface is made obsolete by open(2), it is equivalent to
+.ft R
+.PP
+.RS
+open(\fIname\fP, O_WRONLY | O_CREAT | O_TRUNC, \fImode\fP)
+.RE
+.PP
+.B Creat
+creates a new file or prepares to rewrite an existing
+file called 
+.IR name ,
+given as the address of a null-terminated string.
+If the file did not exist, it is given
+mode
+.IR mode ,
+as modified by the process's mode mask (see
+.BR umask (2)).
+Also see
+.BR chmod (2)
+for the
+construction of the
+.I mode
+argument.
+.PP
+If the file did exist, its mode and owner remain unchanged
+but it is truncated to 0 length.
+.PP
+The file is also opened for writing, and its file descriptor
+is returned.
+.SH NOTES
+The
+.I mode
+given is arbitrary; it need not allow
+writing.
+This feature has been used in the past by
+programs to construct a simple, exclusive locking
+mechanism.  It is replaced by the O_EXCL open
+mode, or the advisory locking of the
+.BR fcntl (2)
+facility.  
+.SH "RETURN VALUE
+The value \-1 is returned if an error occurs.  Otherwise,
+the call returns a non-negative descriptor that only permits
+writing.
+.SH ERRORS
+.I Creat
+will fail and the file will not be created or truncated
+if one of the following occur:
+.TP 15
+[ENOTDIR]
+A component of the path prefix is not a directory.
+.TP 15
+[ENAMETOOLONG]
+The path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+The named file does not exist.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating the pathname.
+(Minix-vmd)
+.TP 15
+[EACCES]
+Search permission is denied for a component of the path prefix.
+.TP 15
+[EACCES]
+The file does not exist and the directory
+in which it is to be created is not writable.
+.TP 15
+[EACCES]
+The file exists, but it is unwritable.
+.TP 15
+[EISDIR]
+The file is a directory.
+.TP 15
+[EMFILE]
+There are already too many files open.
+.TP 15
+[ENFILE]
+The system file table is full.
+.TP 15
+[ENOSPC]
+The directory in which the entry for the new file is being placed
+cannot be extended because there is no space left on the file
+system containing the directory.
+.TP 15
+[ENOSPC]
+There are no free inodes on the file system on which the
+file is being created.
+.ig
+.TP 15
+[EDQUOT]
+The directory in which the entry for the new file
+is being placed cannot be extended because the
+user's quota of disk blocks on the file system
+containing the directory has been exhausted.
+.TP 15
+[EDQUOT]
+The user's quota of inodes on the file system on
+which the file is being created has been exhausted.
+..
+.TP 15
+[EROFS]
+The named file resides on a read-only file system.
+.TP 15
+[ENXIO]
+The file is a character special or block special file, and
+the associated device does not exist.
+.TP 15
+[EIO]
+An I/O error occurred while making the directory entry or allocating the inode.
+.TP 15
+[EFAULT]
+.I Name
+points outside the process's allocated address space.
+.SH "SEE ALSO"
+.BR open (2),
+.BR write (2),
+.BR close (2),
+.BR chmod (2),
+.BR umask (2).
Index: /trunk/minix/man/man2/dup.2
===================================================================
--- /trunk/minix/man/man2/dup.2	(revision 9)
+++ /trunk/minix/man/man2/dup.2	(revision 9)
@@ -0,0 +1,86 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)dup.2	6.3 (Berkeley) 5/13/86
+.\"
+.TH DUP 2 "May 13, 1986"
+.UC 4
+.SH NAME
+dup, dup2 \- duplicate a descriptor
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+int dup(int \fIoldd\fP)
+int dup2(int \fIoldd\fP, int \fInewd\fP)
+.SH DESCRIPTION
+.B Dup
+duplicates an existing descriptor.
+The argument \fIoldd\fP is a small non-negative integer index in
+the per-process descriptor table.  The value must be less
+than OPEN_MAX, the size of the table.
+The new descriptor returned by the call, let's name it
+.I newd,
+is the lowest numbered descriptor that is
+not currently in use by the process.
+.PP
+The object referenced by the descriptor does not distinguish
+between references using \fIoldd\fP and \fInewd\fP in any way.
+Thus if \fInewd\fP and \fIoldd\fP are duplicate references to an open
+file,
+.BR read (2),
+.BR write (2)
+and
+.BR lseek (2)
+calls all move a single pointer into the file,
+and append mode, non-blocking I/O and asynchronous I/O options
+are shared between the references.
+If a separate pointer into the file is desired, a different
+object reference to the file must be obtained by issuing an
+additional
+.BR open (2)
+call.
+The close-on-exec flag on the new file descriptor is unset.
+.PP
+In the second form of the call, the value of
+.IR newd
+desired is specified.  If this descriptor is already
+in use, the descriptor is first deallocated as if a
+.BR close (2)
+call had been done first.
+.I Newd
+is not closed if it equals
+.IR oldd .
+.SH "RETURN VALUE
+The value \-1 is returned if an error occurs in either call.
+The external variable
+.B errno
+indicates the cause of the error.
+.SH "ERRORS
+.B Dup
+and
+.B dup2
+fail if:
+.TP 15
+[EBADF]
+\fIOldd\fP or
+\fInewd\fP is not a valid active descriptor
+.TP 15
+[EMFILE]
+Too many descriptors are active.
+.SH NOTES
+.B Dup
+and
+.B dup2
+are now implemented using the
+.B F_DUPFD
+function of
+.BR fcntl (2),
+although the old system call interfaces still exist to support old programs.
+.SH "SEE ALSO"
+.BR open (2),
+.BR close (2),
+.BR fcntl (2),
+.BR pipe (2).
Index: /trunk/minix/man/man2/execve.2
===================================================================
--- /trunk/minix/man/man2/execve.2	(revision 9)
+++ /trunk/minix/man/man2/execve.2	(revision 9)
@@ -0,0 +1,206 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)execve.2	6.7 (Berkeley) 5/22/86
+.\"
+.TH EXECVE 2 "May 22, 1986"
+.UC 4
+.SH NAME
+execve \- execute a file
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+int execve(const char *\fIname\fP, char *const \fIargv\fP[], char *const \fIenvp\fP[])
+.ft R
+.fi
+.SH DESCRIPTION
+.B Execve
+transforms the calling process into a new process.
+The new process is constructed from an ordinary file
+called the \fInew process file\fP.
+This file is either an executable object file,
+or a file of data for an interpreter.
+An executable object file consists of an identifying header,
+followed by pages of data representing the initial program (text)
+and initialized data pages.  Additional pages may be specified
+by the header to be initialized with zero data.  See
+.BR a.out (5).
+.PP
+An interpreter file begins with a line of the form ``#! \fIinterpreter\fP''.
+When an interpreter file is
+.BR execve\| 'd,
+the system \fBexecve\fP\|'s the specified \fIinterpreter\fP, giving
+it the name of the originally exec'd file as an argument and
+shifting over the rest of the original arguments.
+.PP
+There can be no return from a successful \fBexecve\fP because the calling
+core image is lost.
+This is the mechanism whereby different process images become active.
+.PP
+The argument \fIargv\fP is a null-terminated array of character pointers
+to null-terminated character strings.  These strings constitute
+the argument list to be made available to the new
+process.  By convention, at least one argument must be present in
+this array, and the first element of this array should be
+the name of the executed program (i.e., the last component of \fIname\fP).
+.PP
+The argument \fIenvp\fP is also a null-terminated array of character pointers
+to null-terminated strings.  These strings pass information to the
+new process that is not directly an argument to the command (see
+.BR environ (7)).
+.PP
+Descriptors open in the calling process remain open in
+the new process, except for those for which the close-on-exec
+flag is set (see
+.BR close (2)).
+Descriptors that remain open are unaffected by
+.BR execve .
+.PP
+Ignored signals remain ignored across an
+.BR execve ,
+but signals that are caught are reset to their default values.
+Blocked signals remain blocked regardless of changes to the signal action.
+The signal stack is reset to be undefined (see
+.BR sigaction (2) 
+for more information).
+.PP
+Each process has
+.I real
+user and group IDs and an
+.I effective
+user and group IDs.  The
+.I real
+ID identifies the person using the system; the
+.I effective
+ID determines his access privileges.
+.B Execve
+changes the effective user and group ID to
+the owner of the executed file if the file has the \*(lqset-user-ID\*(rq
+or \*(lqset-group-ID\*(rq modes.  The
+.I real
+user ID is not affected.
+.PP
+The new process also inherits the following attributes from
+the calling process:
+.PP
+.in +5n
+.nf
+.ta +2i
+process ID	see \fBgetpid\fP\|(2)
+parent process ID	see \fBgetppid\fP\|(2)
+process group ID	see \fBgetpgrp\fP\|(2)
+access groups	see \fBgetgroups\fP\|(2)
+working directory	see \fBchdir\fP\|(2)
+root directory	see \fBchroot\fP\|(2)
+control terminal	see \fBtty\fP\|(4)
+alarm timer	see \fBalarm\fP\|(2)
+file mode mask	see \fBumask\fP\|(2)
+signal mask	see \fBsigaction\fP\|(2), \fBsigprocmask\fP\|(2)
+.in -5n
+.fi
+.PP
+When the executed program begins, it is called as follows:
+.PP
+.RS
+.ft B
+.nf
+int main(int \fIargc\fP, char *const \fIargv\fP[], char *const \fIenvp\fP[]);
+
+exit(main(\fIargc\fP, \fIargv\fP, \fIenvp\fP));
+.fi
+.ft R
+.RE
+.PP
+where
+.I argc
+is the number of elements in \fIargv\fP
+(the ``arg count'')
+and
+.I argv
+is the array of character pointers
+to the arguments themselves.
+.PP
+.I Envp
+is a pointer to an array of strings that constitute
+the
+.I environment
+of the process.
+A pointer to this array is also stored in the global variable ``environ''.
+Each string consists of a name, an \*(lq=\*(rq, and a null-terminated value.
+The array of pointers is terminated by a null pointer.
+The shell
+.BR sh (1)
+passes an environment entry for each global shell variable
+defined when the program is called.
+See
+.BR environ (7)
+for some conventionally
+used names.
+.SH "RETURN VALUE
+If
+.B execve
+returns to the calling process an error has occurred; the
+return value will be \-1 and the global variable
+.B errno
+will contain an error code.
+.SH ERRORS
+.B Execve
+will fail and return to the calling process if one or more
+of the following are true:
+.TP 15
+[ENOTDIR]
+A component of the path prefix is not a directory.
+.TP 15
+[ENAMETOOLONG]
+The path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+The new process file does not exist.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating the pathname.
+(Minix-vmd)
+.TP 15
+[EACCES]
+Search permission is denied for a component of the path prefix.
+.TP 15
+[EACCES]
+The new process file is not an ordinary file.
+.TP 15
+[EACCES]
+The new process file mode denies execute permission.
+.TP 15
+[ENOEXEC]
+The new process file has the appropriate access
+permission, but has an invalid magic number in its header.
+.TP 15
+[ENOMEM]
+The new process requires more (virtual) memory than
+is currently available.
+.TP 15
+[E2BIG]
+The number of bytes in the new process's argument list
+is larger than the system-imposed limit ARG_MAX.
+The limit in the system as released is 4096 bytes for
+16-bit MINIX 3, 16384 bytes for 32-bit Minix, and unlimited for Minix-vmd.
+.TP 15
+[EFAULT]
+\fIPath\fP\|, \fIargv\fP\|, or \fIenvp\fP point
+to an illegal address.
+.TP 15
+[EIO]
+An I/O error occurred while reading from the file system.
+.SH CAVEATS
+If a program is
+.I setuid
+to a non-super-user, but is executed when
+the real \fBuid\fP is ``root'', then the program has some of the powers
+of a super-user as well.
+.SH "SEE ALSO"
+.BR exit (2),
+.BR fork (2),
+.BR execl (3),
+.BR environ (7).
Index: /trunk/minix/man/man2/exit.2
===================================================================
--- /trunk/minix/man/man2/exit.2	(revision 9)
+++ /trunk/minix/man/man2/exit.2	(revision 9)
@@ -0,0 +1,57 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)exit.2	6.4 (Berkeley) 5/22/86
+.\"
+.TH EXIT 2 "May 22, 1986"
+.UC 4
+.SH NAME
+exit, _exit \- terminate a process
+.SH SYNOPSIS
+.nf
+.ft B
+void _exit(int \fIstatus\fP)
+.fi
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B _exit
+terminates a process with the following consequences:
+.RS
+.SP
+All of the descriptors open in the calling process are closed.
+This may entail delays, for example, waiting for output to drain;
+a process in this state may not be killed, as it is already dying.
+.SP
+If the parent process of the calling process is executing a
+.B wait
+or is interested in the SIGCHLD signal (Minix-vmd),
+then it is notified of the calling process's termination and
+the low-order eight bits of \fIstatus\fP are made available to it;
+see
+.BR wait (2).
+.SP
+The parent process ID of all of the calling process's existing child
+processes are also set to 1.  This means that the initialization process
+(see 
+.BR intro (2))
+inherits each of these processes as well.
+.ig
+Any stopped children are restarted with a hangup signal (SIGHUP).
+..
+.RE
+.PP
+Most C programs call the library routine
+.BR exit (3),
+which performs cleanup actions in the standard I/O library before
+calling \fI_exit\fP\|.
+.SH "RETURN VALUE"
+This call never returns.
+.SH "SEE ALSO"
+.BR fork (2),
+.BR sigaction (2),
+.BR wait (2),
+.BR exit (3).
Index: /trunk/minix/man/man2/fcntl.2
===================================================================
--- /trunk/minix/man/man2/fcntl.2	(revision 9)
+++ /trunk/minix/man/man2/fcntl.2	(revision 9)
@@ -0,0 +1,262 @@
+.TH FCNTL 2
+.SH NAME
+fcntl \- miscellaneous file descriptor control functions
+.SH SYNOPSIS
+.nf
+.ft B
+#include <fcntl.h>
+
+int fcntl(int \fIfd\fP, int \fIcmd\fP, \fR[\fP\fIdata\fP\fR]\fP)
+.ft P
+.fi
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Fcntl()
+performs several file descriptor related functions, like duplicating a file
+descriptor, setting the "close on exec" attribute, etc.  The
+.I fd
+argument is the file descriptor to operate on,
+.I cmd
+is the command code of the operation to perform, and
+.I data
+is an optional argument to give or receive parameters.  The command
+codes and other symbols and types are declared in <fcntl.h>.  The commands
+are:
+.SP
+.BI "fcntl(" fd ", F_DUPFD, int " fd2 ")"
+.RS
+Returns a new file descriptor that is a duplicate of file descriptor
+.IR fd .
+It shares the same file pointer and the same file status flags, but has
+separate file descriptor flags that are initially off.  The value of the
+duplicate file descriptor is the first free file descriptor greater than
+or equal to
+.IR fd2 .
+.RE
+.SP
+.BI "fcntl(" fd ", F_GETFD)"
+.RS
+Returns the file descriptor flags associated with file descriptor
+.IR fd .
+The flags are the "close on exec" flag
+.B FD_CLOEXEC
+that, when set, causes the file descriptor to be closed when the process
+executes another program.  The Minix-vmd specific
+.B FD_ASYNCHIO
+flag marks a file descriptor for asynchronous I/O operation.
+.RE
+.SP
+.BI "fcntl(" fd ", F_SETFD, int " flags ")"
+.RS
+Set the file descriptor flags of
+.I fd
+to
+.IR flags .
+.RE
+.SP
+.BI "fcntl(" fd ", F_GETFL)"
+.RS
+Return the file status flags and file access modes associated with the file
+associated with file descriptor
+.IR fd .
+The file status flags are
+.B O_NONBLOCK
+(non blocking I/O) and
+.B O_APPEND
+(append mode).  The file access modes are
+.B O_RDONLY
+(read-only),
+.B O_WRONLY
+(write-only) and
+.B O_RDWR
+(read-write).  These flags are also used in the second argument of
+.BR open (2).
+.RE
+.SP
+.BI "fcntl(" fd ", F_SETFL, int " flags ")"
+.RS
+Set the file status flags of the file referenced by
+.I fd
+to
+.IR flags .
+Only
+.B O_NONBLOCK
+and
+.B O_APPEND
+may be changed.  Access mode flags are ignored.
+.RE
+.SP
+The next four commands use a parameter of type
+.B struct flock
+that is defined in <fcntl.h> as:
+.SP
+.RS
+.nf
+.ta +4n +8n +12n
+struct flock {
+	short	l_type;	/* F_RDLCK, F_WRLCK, or F_UNLCK */
+	short	l_whence;	/* SEEK_SET, SEEK_CUR, or SEEK_END */
+	off_t	l_start;	/* byte offset to start of segment */
+	off_t	l_len;	/* length of segment */
+	pid_t	l_pid;	/* process id of the locks' owner */
+};
+.fi
+.RE
+.SP
+This structure describes a segment of a file.
+.B L_type
+is the lock operation performed on the file segment:
+.B F_RDLCK
+to set a read lock,
+.B F_WRLCK
+to set a write lock, and
+.B F_UNLCK
+to remove a lock.  Several processes may have a read lock on a segment, but
+only one process can have a write lock.
+.B L_whence
+tells if the
+.B l_start
+offset must be interpreted from the start of the file
+.RB ( SEEK_SET ),
+the current file position
+.RB ( SEEK_CUR ),
+or the end of the file
+.RB ( SEEK_END ).
+This is analogous to the third parameter of
+.BR lseek (2).
+These
+.B SEEK_*
+symbols are declared in <unistd.h>.
+.B L_start
+is the starting offset of the segment of the file.
+.B L_end
+is the length of the segment.  If zero then the segment extends until end of
+file.
+.B L_pid
+is the process-id of the process currently holding a lock on the segment.
+It is returned by
+.BR F_GETLK .
+.SP
+.BI "fcntl(" fd ", F_GETLK, struct flock *" lkp ")"
+.RS
+Find out if some other process has a lock on a segment of the file
+associated by file descriptor
+.I fd
+that overlaps with the segment described by the
+.B flock
+structure pointed to by
+.IR lkp .
+If the segment is not locked then
+.B l_type
+is set to
+.BR F_UNLCK .
+Otherwise an
+.B flock
+structure is returned through
+.I lkp
+that describes the lock held by the other process.
+.B L_start
+is set relative to the start of the file.
+.RE
+.SP
+.BI "fcntl(" fd ", F_SETLK, struct flock *" lkp ")"
+.RS
+Register a lock on a segment of the file associated with file descriptor
+.IR fd .
+The file segment is described by the
+.B struct flock
+pointed to by
+.IR lkp .
+This call returns an error if any part of the segment is already locked.
+.RE
+.SP
+.BI "fcntl(" fd ", F_SETLKW, struct flock *" lkp ")"
+.RS
+Register a lock on a segment of the file associated with file descriptor
+.IR fd .
+The file segment is described by the
+.B struct flock
+pointed to by
+.IR lkp .
+This call blocks waiting for the lock to be released if any part of the
+segment is already locked.
+.RE
+.SP
+.BI "fcntl(" fd ", F_FREESP, struct flock *" lkp ")"
+.RS
+This call frees a segment of disk space occupied by the
+file associated with file descriptor
+.IR fd .
+The segment is described by the
+.B struct flock
+pointed to by
+.IR lkp .
+The file is truncated in length to the byte position indicated by
+.B l_start
+if
+.B l_len
+is zero.  If
+.B l_len
+is nonzero then the file keeps its size, but the freed bytes now read as
+zeros.  (Other than sharing the flock structure, this call has nothing to do
+with locking.)  (This call is common among UNIX(-like) systems.)
+.RE
+.SP
+.BI "fcntl(" fd ", F_SEEK, u64_t " pos ")"
+.RS
+This Minix-vmd specific call sets the file position of the file associated
+with file descriptor
+.I fd
+to the byte offset indicated by the 64-bit number
+.IR pos .
+This is analogous to the call
+.SP
+.RS
+.BI "lseek(" fd ", " pos ", SEEK_SET)"
+.RE
+.SP
+except that
+.B F_SEEK
+can be used on devices larger than 4 gigabyte.
+.RE
+.SH "SEE ALSO"
+.BR open (2),
+.BR dup (2),
+.BR lseek (2),
+.BR ftruncate (3),
+.BR int64 (3).
+.SH DIAGNOSTICS
+.B Fcntl
+returns a file descriptor, flags, or
+.B 0
+to indicate success.  On error
+.B \-1
+is returned, with
+.B errno
+set to the appropriate error code.  The most notable errors are:
+.TP 5
+.B EINTR
+If a blocked
+.B F_SETLKW
+operation is interrupted by a signal that is caught.
+.TP
+.B EAGAIN
+By
+.B F_SETLK
+if a segment cannot be locked.
+.TP
+.B EBADF
+A bad file descriptor in general, or an attempt to place a write lock on a
+file that is not open for writing, etc.
+.TP
+.B ENOLCK
+No locks available, the file system code has run out of internal table
+space.
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
+
+.\"
+.\" $PchId: fcntl.2,v 1.2 2000/08/11 19:39:51 philip Exp $
Index: /trunk/minix/man/man2/fork.2
===================================================================
--- /trunk/minix/man/man2/fork.2	(revision 9)
+++ /trunk/minix/man/man2/fork.2	(revision 9)
@@ -0,0 +1,74 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)fork.2	6.4 (Berkeley) 5/22/86
+.\"
+.TH FORK 2 "May 22, 1986"
+.UC
+.SH NAME
+fork \- create a new process
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <unistd.h>
+
+pid_t fork(void)
+.ft R
+.fi
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Fork
+causes creation of a new process.
+The new process (child process) is an exact copy of the
+calling process except for the following:
+.RS
+.SP
+The child process has a unique process ID.
+.SP
+The child process has a different parent process ID (i.e.,
+the process ID of the parent process).
+.SP
+The child process has its own copy of the parent's descriptors.
+These descriptors reference the same underlying objects, so that,
+for instance, file pointers in file objects are shared between
+the child and the parent, so that an
+.BR lseek (2)
+on a descriptor in the child process can affect a subsequent
+.B read
+or
+.B write
+by the parent.
+This descriptor copying is also used by the shell to
+establish standard input and output for newly created processes
+as well as to set up pipes.
+.SP
+The child starts with no pending signals and an inactive alarm timer.
+.RE
+.SH "RETURN VALUE
+Upon successful completion, \fBfork\fP returns a value
+of 0 to the child process and returns the process ID of the child
+process to the parent process.  Otherwise, a value of \-1 is returned
+to the parent process, no child process is created, and the global
+variable \fBerrno\fP is set to indicate the error.
+.SH ERRORS
+.B Fork
+will fail and no child process will be created if one or more of the
+following are true:
+.TP 15
+[EAGAIN]
+The system-imposed limit on the total
+number of processes under execution would be exceeded.
+This limit is configuration-dependent.
+(The kernel variable NR_PROCS in <minix/config.h> (Minix), or
+<minix/const.h> (Minix-vmd).)
+.TP 15
+[ENOMEM]
+There is insufficient (virtual) memory for the new process.
+.SH "SEE ALSO"
+.BR execve (2),
+.BR wait (2).
Index: /trunk/minix/man/man2/getgid.2
===================================================================
--- /trunk/minix/man/man2/getgid.2	(revision 9)
+++ /trunk/minix/man/man2/getgid.2	(revision 9)
@@ -0,0 +1,34 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)getgid.2	6.2 (Berkeley) 1/7/86
+.\"
+.TH GETGID 2 "January 7, 1986"
+.UC 5
+.SH NAME
+getgid, getegid \- get group identity
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <unistd.h>
+
+gid_t getgid(void)
+gid_t getegid(void)
+.fi
+.SH DESCRIPTION
+.B Getgid
+returns the real group ID of the current process,
+.B getegid
+the effective group ID.
+.PP
+The real group ID is specified at login time.
+.PP
+The effective group ID is more transient, and determines
+additional access permission during execution of a
+``set-group-ID'' process, and it is for such processes
+that \fBgetgid\fP is most useful.
+.SH "SEE ALSO"
+.BR getuid (2),
+.BR setgid (2).
Index: /trunk/minix/man/man2/getpid.2
===================================================================
--- /trunk/minix/man/man2/getpid.2	(revision 9)
+++ /trunk/minix/man/man2/getpid.2	(revision 9)
@@ -0,0 +1,33 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)getpid.2	6.3 (Berkeley) 5/13/86
+.\"
+.TH GETPID 2 "May 13, 1986"
+.UC 4
+.SH NAME
+getpid, getppid \- get process identification
+.SH SYNOPSIS
+.ft B
+.nf
+#include <sys/types.h>
+#include <unistd.h>
+
+pid_t getpid(void)
+pid_t getppid(void)
+.fi
+.ft R
+.SH DESCRIPTION
+.B Getpid
+returns
+the process ID of
+the current process.
+Most often it is used
+to generate uniquely-named temporary files.
+.PP
+.B Getppid
+returns the process ID of the parent
+of the current process. 
+.SH "SEE ALSO
+.BR fork (2).
Index: /trunk/minix/man/man2/getpriority.2
===================================================================
--- /trunk/minix/man/man2/getpriority.2	(revision 9)
+++ /trunk/minix/man/man2/getpriority.2	(revision 9)
@@ -0,0 +1,37 @@
+.TH GETPRIORITY 2 "Jul 1, 2005"
+.UC 4
+.SH NAME
+getpriority, setpriority \- get and set scheduling priority
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/resource.h>
+
+int getpriority(int \fIwhich\fP, int \fIwho\fP)
+int setpriority(int \fIwhich\fP, int \fIwho\fP, int \fIprio\fP)
+.SH DESCRIPTION
+.B Getpriority
+returns the scheduling priority of the process, process group, or user
+referred to in \fIwho\fP. Which of the three is indicated in
+\fIwhich\fP, by PRIO_PROCESS, PRIO_PGRP and PRIO_USER, respectively.
+In MINIX 3, currently only PRIO_PROCESS is implemented.
+
+The range of the returned value is between PRIO_MIN and PRIO_MAX,
+currently between -20 and 20, and is the so-called nice value of
+a process. The higher the nice value, the less favourable the scheduling
+priority.
+
+.B Setpriority
+sets the priority indicated by \fIwho\fP and \fIwhich\fP to \fIprio\fP.
+\fIprio\fP, which is the nice value, may only be lowered by the super-user.
+.SH RETURN VALUES
+These functions both return -1 on failure, and set errno in this case.
+Because
+.B getpriority
+can return -1 as the real nice value, the caller has to reset errno
+and check errno afterwards to distinguish between an error condition
+and a negative nice value.
+.SH SEE ALSO
+nice(1)
+.SH AUTHOR
+Ben Gras <beng@few.vu.nl>
Index: /trunk/minix/man/man2/gettimeofday.2
===================================================================
--- /trunk/minix/man/man2/gettimeofday.2	(revision 9)
+++ /trunk/minix/man/man2/gettimeofday.2	(revision 9)
@@ -0,0 +1,22 @@
+.TH GETTIMEOFDAY 2 "July 6, 2005"
+.UC 4
+.SH NAME
+gettimeofday \- get date and time
+.SH SYNOPSIS
+.ft B
+.nf
+#include <sys/time.h>
+
+int gettimeofday(struct timeval *tp, struct timezone *tzp)
+.fi
+.ft R
+.SH DESCRIPTION
+.B Gettimeofday
+returns the time in seconds and microseconds since epoch in GMT
+(midnight, january 1st, 1970). The timezone argument tzp is expected
+to be NULL.
+.SH RETURNS
+0 on success, -1 on error. If -1 is returned, errno is set to indicate
+the error.
+.SH "SEE ALSO
+.BR ctime (3).
Index: /trunk/minix/man/man2/getuid.2
===================================================================
--- /trunk/minix/man/man2/getuid.2	(revision 9)
+++ /trunk/minix/man/man2/getuid.2	(revision 9)
@@ -0,0 +1,34 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)getuid.2	6.3 (Berkeley) 1/7/86
+.\"
+.TH GETUID 2 "January 7, 1986"
+.UC 4
+.SH NAME
+getuid, geteuid \- get user identity
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <unistd.h>
+
+uid_t getuid(void)
+uid_t geteuid(void)
+.fi
+.SH DESCRIPTION
+.B Getuid
+returns the real user ID of the current process,
+.B geteuid
+the effective user ID.
+.PP
+The real user ID identifies the person who is logged in.
+The effective user ID
+gives the process additional permissions during
+execution of \*(lqset-user-ID\*(rq mode processes, which use
+\fBgetuid\fP to determine the real-user-id of the process that
+invoked them.
+.SH "SEE ALSO"
+.BR getgid (2),
+.BR setuid (2).
Index: /trunk/minix/man/man2/intro.2
===================================================================
--- /trunk/minix/man/man2/intro.2	(revision 9)
+++ /trunk/minix/man/man2/intro.2	(revision 9)
@@ -0,0 +1,449 @@
+.\" Copyright (c) 1980,1983,1986 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)intro.2	6.7 (Berkeley) 5/23/86
+.\"
+.TH INTRO 2 "June 30, 1986"
+.UC 4
+.de en
+.HP
+\\$1  \\$2  \\$3
+.br
+..
+.SH NAME
+intro, errno \- introduction to system calls and error numbers
+.SH SYNOPSIS
+.B "#include <errno.h>"
+.SH DESCRIPTION
+This section describes all of the system calls.  Most
+of these calls have one or more error returns.
+An error condition is indicated by an otherwise impossible return
+value.  This is almost always \-1; the individual descriptions
+specify the details.
+Note that a number of system calls overload the meanings of these
+error numbers, and that the meanings must be interpreted according
+to the type and circumstances of the call.
+.PP
+As with normal arguments, all return codes and values from
+functions are of type integer unless otherwise noted.
+An error number is also made available in the external
+variable \fBerrno\fP, which is not cleared
+on successful calls.
+Thus \fBerrno\fP should be tested only after an error has occurred.
+.PP
+The following is a complete list of the errors and their
+names as given in
+.RI < sys/errno.h >:
+.en 0 OK "Error 0
+Unused.  (The symbol "OK" is only used inside the kernel source.)
+.en 1 EPERM "Not owner
+Typically this error indicates
+an attempt to modify a file in some way forbidden
+except to its owner or super-user.
+It is also returned for attempts
+by ordinary users to do things
+allowed only to the super-user.
+.en 2 ENOENT "No such file or directory
+This error occurs when a file name is specified
+and the file should exist but doesn't, or when one
+of the directories in a path name does not exist.
+.en 3 ESRCH "No such process
+The process or process group whose number was given
+does not exist, or any such process is already dead.
+.en 4 EINTR "Interrupted system call
+An asynchronous signal (such as interrupt or quit)
+that the user has elected to catch
+occurred during a system call.
+If execution is resumed
+after processing the signal
+and the system call is not restarted,
+it will appear as if the interrupted system call
+returned this error condition.
+.en 5 EIO "I/O error
+Some physical I/O error occurred during an I/O operation, usually
+.B read
+or
+.BR write .
+Operations on file descriptors that refer to devices that are forcefully
+taken away or in a bad state will also provoke this error.
+.en 6 ENXIO "No such device or address
+I/O on a special file refers to a subdevice that does not
+exist,
+or beyond the limits of the device.
+It may also occur when, for example, an illegal tape drive
+unit number is selected 
+or a disk pack is not loaded on a drive.
+.en 7 E2BIG "Arg list too long
+An argument list longer than ARG_MAX bytes is presented to
+.BR execve .
+ARG_MAX is set to 4096 bytes for 16-bit MINIX 3, 16384 bytes for 32-bit
+MINIX 3, and unlimited for Minix-vmd as these systems are released.
+.en 8 ENOEXEC "Exec format error
+A request is made to execute a file
+that, although it has the appropriate permissions,
+does not start with a valid magic number, (see
+.BR a.out (5)).
+.en 9 EBADF "Bad file number
+Either a file descriptor refers to no
+open file,
+or a read (resp. write) request is made to
+a file that is open only for writing (resp. reading).
+.en 10 ECHILD "No children
+.B Wait
+and the process has no
+living or unwaited-for children.
+.en 11 EAGAIN "Resource temporarily unavailable
+In a
+.B fork,
+the system's process table is full or the user is not allowed to create
+any more processes, otherwise an operation that would cause a process to
+block was attempted on an object in non-blocking mode (see \fBfcntl\fP(2)).
+.en 12 ENOMEM "Not enough core
+During an
+.B execve
+or
+.B brk,
+a program asks for more (virtual) memory than the system is
+able to supply,
+or a process size limit would be exceeded.
+The maximum size
+of the data+stack segment is set by the
+.BR chmem (1)
+program.  For Minix-vmd a small data+stack size is increased to 3 megabytes
+when a program is executed.
+.en 13 EACCES "Permission denied
+An attempt was made to access a file in a way forbidden
+by the protection system.  Also an attempt to open a device for writing
+that is physically write protected.
+.en 14 EFAULT "Bad address
+An argument of a system call is outside the address space allocated to a
+process.
+.en 15 ENOTBLK "Block device required
+A plain file was mentioned where a block device was required,
+e.g., in
+.BR mount .
+.en 16 EBUSY "Resource busy
+An attempt to mount a device that was already mounted or
+an attempt was made to dismount a device
+on which there is an active file
+(open file, current directory, mounted-on file, or active text segment).
+A request was made to an exclusive access device that was already in use.
+.en 17 EEXIST "File exists
+An existing file was mentioned in an inappropriate context,
+e.g.,
+.BR link .
+.en 18 EXDEV "Cross-device link
+A hard link to a file on another device
+was attempted.
+.en 19 ENODEV "No such device
+An attempt was made to access a device that is not configured by the system,
+i.e., there is no driver for the device.
+.en 20 ENOTDIR "Not a directory
+A non-directory was specified where a directory
+is required,
+for example, in a path name or
+as an argument to
+.BR chdir .
+.en 21 EISDIR "Is a directory
+An attempt to write on a directory.
+.en 22 EINVAL "Invalid argument
+Some invalid argument:
+dismounting a non-mounted
+device,
+mentioning an unknown signal in
+.B signal,
+or some other argument inappropriate for the call.
+Also set by math functions, (see 
+.BR math (3)).
+.en 23 ENFILE "File table overflow
+The system's table of open files is full,
+and temporarily no more
+.I opens
+can be accepted.
+.en 24 EMFILE "Too many open files
+The limit on the number of open files per process, OPEN_MAX, is reached.
+As released, this limit is 20 for MINIX 3, and 30 for Minix-vmd.
+.en 25 ENOTTY "Not a typewriter
+The file mentioned in an
+.B ioctl
+is not a terminal or one of the
+devices to which this call applies.  (Often seen error from programs with
+bugs in their error reporting code.)
+.en 26 ETXTBSY "Text file busy
+Attempt to execute a program that is open for writing.  Obsolete under MINIX 3.
+.en 27 EFBIG "File too large
+The size of a file exceeded the maximum (little over 64 megabytes for
+the V2 file system).
+.en 28 ENOSPC "No space left on device
+A
+.B write
+to an ordinary file, the creation of a
+directory or symbolic link, or the creation of a directory
+entry failed because no more disk blocks are available
+on the file system, or the allocation of an inode for a newly
+created file failed because no more inodes are available
+on the file system.
+.en 29 ESPIPE "Illegal seek
+An
+.B lseek
+was issued to a pipe or TCP/IP channel.
+This error may also be issued for
+other non-seekable devices.
+.en 30 EROFS "Read-only file system
+An attempt to modify a file or directory
+was made
+on a device mounted read-only.
+.en 31 EMLINK "Too many links
+An attempt to make more than a certain number of hard links to a file.  The
+advertized maximum, LINK_MAX, is 127, but Minix-vmd uses a much larger
+maximum of 32767 for the V2 file system.
+.en 32 EPIPE "Broken pipe
+A write on a pipe or TCP/IP channel for which there is no process
+to read the data.
+This condition normally generates the signal SIGPIPE;
+the error is returned if the signal is caught or ignored.
+.en 33 EDOM "Math argument
+The argument of a function in the math package
+is out of the domain of the function.
+.en 34 ERANGE "Result too large
+The value of a function in the math package
+is unrepresentable within machine precision.
+.en 35 EDEADLK "Resource deadlock avoided
+A process attempts to place a blocking lock on a file that is already
+locked by another process and that process is waiting for the first
+process to unlock a file that first process already has a lock on.
+(The classic "lock A, lock B" by process 1, and "lock B, lock A" by
+process 2.)
+.en 36 ENAMETOOLONG "File name too long"
+The path name exceeds PATH_MAX characters.  PATH_MAX equals 255 as
+distributed.
+.en 37 ENOLCK "No locks available
+The system's table of active locks is full.
+.en 38 ENOSYS "Function not implemented
+The system call is not supported.  Either an old program uses an obsolete
+call, or a program for a more capable system is run on a less capable
+system.
+.en 39 ENOTEMPTY "Directory not empty"
+A directory with entries other than \*(lq.\*(rq and \*(lq..\*(rq
+was supplied to a remove directory or rename call.
+.en 40 ELOOP "Too many symbolic links"
+A path name lookup involved more than SYMLOOP symbolic links.  SYMLOOP
+equals 8 as distributed.
+(Minix-vmd)
+.en 50 EPACKSIZE "Invalid packet size
+.en 51 EOUTOFBUFS "Not enough buffers left
+.en 52 EBADIOCTL "Illegal ioctl for device
+.en 53 EBADMODE "Bad mode in ioctl
+.en 54 EWOULDBLOCK "Would block
+.en 55 EBADDEST "Bad destination address
+.en 56 EDSTNOTRCH "Destination not reachable
+.en 57 EISCONN "Already connected
+.en 58 EADDRINUSE "Address in use
+.en 59 ECONNREFUSED "Connection refused
+.en 60 ECONNRESET "Connection reset
+.en 61 ETIMEDOUT "Connection timed out
+.en 62 EURG "Urgent data present
+.en 63 ENOURG "No urgent data present
+.en 64 ENOTCONN "No connection
+.en 65 ESHUTDOWN "Already shutdown
+.en 66 ENOCONN "No such connection
+.en 67 EINPROGRESS "Operation now in progress
+.en 68 EALREADY "Operation already in progress
+.ig
+.en XXX EDQUOT "Disc quota exceeded"
+A 
+.B write
+to an ordinary file, the creation of a
+directory or symbolic link, or the creation of a directory
+entry failed because the user's quota of disk blocks was
+exhausted, or the allocation of an inode for a newly
+created file failed because the user's quota of inodes
+was exhausted.
+.en XXX ESTALE "Stale NFS file handle"
+A client referenced a an open file, when the file has been deleted.
+.en XXX EREMOTE "Too many levels of remote in path"
+An attempt was made to remotely mount a file system into a path which
+already has a remotely mounted component.
+..
+.SH DEFINITIONS
+.TP 5
+Process ID
+.br
+Each active process in the system is uniquely identified by a positive
+integer called a process ID.  The range of this ID is from 1 to 29999.
+The special process with process ID 1 is
+.BR init ,
+the ancestor of all processes.
+.TP 5
+Parent process ID
+.br
+A new process is created by a currently active process; (see
+.BR fork (2)).
+The parent process ID of a process is the process ID of its creator,
+unless the creator dies, then
+.B init
+becomes the parent of the orphaned process.
+.TP 5
+Process Group ID
+.br
+Each active process is a member of a process group that is identified by
+a positive integer called the process group ID.  This is the process
+ID of the group leader.  This grouping permits the signaling of related
+processes (see
+.BR kill (2)).
+.TP 5
+Real User ID and Real Group ID
+.br
+Each user on the system is identified by a positive integer
+termed the real user ID.
+.IP
+Each user is also a member of one or more groups.
+One of these groups is distinguished from others and
+used in implementing accounting facilities.  The positive
+integer corresponding to this distinguished group is termed 
+the real group ID.
+(Under standard MINIX 3 this is the only group a process can be a member of.)
+.IP
+All processes have a real user ID and real group ID.
+These are initialized from the equivalent attributes
+of the process that created it.
+.TP 5
+Effective User Id, Effective Group Id, and Access Groups
+.br
+Access to system resources is governed by three values:
+the effective user ID, the effective group ID, and the
+group access list.
+.IP
+The effective user ID and effective group ID are initially the
+process's real user ID and real group ID respectively.  Either
+may be modified through execution of a set-user-ID or set-group-ID
+file (possibly by one its ancestors) (see
+.BR execve (2)).
+.IP
+The group access list is an additional set of group ID's
+used only in determining resource accessibility.  Access checks
+are performed as described below in ``File Access Permissions''.
+The maximum number of additional group ID's is NGROUPS_MAX.
+For MINIX 3 this is 0, but Minix-vmd supports a list of up to 16
+additional group ID's.  (Also known as ``supplemental'' group ID's.)
+.TP 5
+Super-user
+.br
+A process is recognized as a
+.I super-user
+process and is granted special privileges if its effective user ID is 0.
+.TP 5
+Descriptor
+.br
+An integer assigned by the system when a file or device is referenced
+by
+.BR open (2),
+.BR dup (2)
+or
+.BR fcntl (2)
+which uniquely identifies an access path to that file or device from
+a given process or any of its children.
+.TP 5
+File Descriptor
+Older, and often used name for a descriptor.
+.TP 5
+File Name
+.br
+Names consisting of up to NAME_MAX characters may be used to name
+an ordinary file, special file, or directory.  NAME_MAX is the maximum
+of the maximum file name lengths of the supported file systems.
+Excess characters are ignored when too long file names are used for
+files in a given file system.
+The maximum file name length of the V1 and V2 file systems
+is 14 characters.  The Minix-vmd "flex" variants of V1 and V2 have a
+60 character maximum.
+.IP
+The characters in a file name may assume any value representable in
+eight bits excluding 0 (null) and the ASCII code for / (slash).
+.IP
+Note that it is generally unwise to use one of \e'"<>();~$^&*|{}[]?
+as part of file names because of the special meaning attached to these
+characters by the shell.
+.TP 5
+Path Name
+.br
+A path name is a null-terminated character string starting with an
+optional slash (/), followed by zero or more directory names separated
+by slashes, optionally followed by a file name.
+The total length of a path name must be less than PATH_MAX characters
+(255 as distributed.)
+.IP
+If a path name begins with a slash, the path search begins at the
+.I root
+directory.
+Otherwise, the search begins from the current working directory.
+A slash by itself names the root directory.  A null pathname is
+illegal, use "." to refer to the current working directory.
+.TP 5
+Directory
+.br
+A directory is a special type of file that contains entries
+that are references to other files.
+Directory entries are called links.  By convention, a directory
+contains at least two links, . and .., referred to as
+.I dot
+and
+.I dot-dot
+respectively.  Dot refers to the directory itself and
+dot-dot refers to its parent directory.
+.TP 5
+Root Directory and Current Working Directory
+.br
+Each process has associated with it a concept of a root directory
+and a current working directory for the purpose of resolving path
+name searches.  A process's root directory need not be the root
+directory of the root file system.
+.TP 5
+File Access Permissions
+.br
+Every file in the file system has a set of access permissions.
+These permissions are used in determining whether a process
+may perform a requested operation on the file (such as opening
+a file for writing).  Access permissions are established at the
+time a file is created.  They may be changed at some later time
+through the 
+.BR chmod (2)
+call. 
+.IP
+File access is broken down according to whether a file may be: read,
+written, or executed.  Directory files use the execute
+permission to control if the directory may be searched. 
+.IP
+File access permissions are interpreted by the system as
+they apply to three different classes of users: the owner
+of the file, those users in the file's group, anyone else.
+Every file has an independent set of access permissions for
+each of these classes.  When an access check is made, the system
+decides if permission should be granted by checking the access
+information applicable to the caller.
+.IP
+Read, write, and execute/search permissions on
+a file are granted to a process if:
+.IP
+The process's effective user ID is that of the super-user.
+.IP
+The process's effective user ID matches the user ID of the owner
+of the file and the owner permissions allow the access.
+.IP
+The process's effective user ID does not match the user ID of the
+owner of the file, and either the process's effective
+group ID matches the group ID
+of the file, or the group ID of the file is in
+the process's group access list,
+and the group permissions allow the access.
+.IP
+Neither the effective user ID nor effective group ID
+and group access list of the process
+match the corresponding user ID and group ID of the file,
+but the permissions for ``other users'' allow access.
+.IP
+Otherwise, permission is denied.
+.SH SEE ALSO
+.BR intro (3),
+.BR strerror (3).
Index: /trunk/minix/man/man2/ioctl.2
===================================================================
--- /trunk/minix/man/man2/ioctl.2	(revision 9)
+++ /trunk/minix/man/man2/ioctl.2	(revision 9)
@@ -0,0 +1,69 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)ioctl.2	6.3 (Berkeley) 3/4/86
+.\"
+.TH IOCTL 2 "March 4, 1986"
+.UC 4
+.SH NAME
+ioctl \- control device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+.ta +54n
+int ioctl(int \fId\fP, int \fIrequest\fP, void *\fIargp\fP)	(Minix)
+int ioctl(int \fId\fP, ioreq_t \fIrequest\fP, void *\fIargp\fP)	(Minix-vmd)
+.DT
+.fi
+.ft R
+.SH DESCRIPTION
+.B Ioctl
+performs a variety of functions
+on open descriptors.  In particular, many operating
+characteristics of character special files (e.g. terminals)
+may be controlled with
+.B ioctl
+requests.
+The writeups of various devices in section 4 discuss how
+.B ioctl
+applies to them.
+.PP
+An  ioctl
+.I request
+has encoded in it whether the argument is an \*(lqin\*(rq parameter
+or \*(lqout\*(rq parameter, and the size of the argument \fIargp\fP in bytes.
+Macros and defines used in specifying an ioctl
+.I request
+are located in the file
+.IR <sys/ioctl.h> .
+.SH "RETURN VALUE
+If an error has occurred, a value of \-1 is returned and
+.B errno
+is set to indicate the error.
+.SH ERRORS
+.B Ioctl
+will fail if one or more of the following are true:
+.TP 15
+[EBADF]
+\fID\fP is not a valid descriptor.
+.TP 15
+[ENOTTY]
+\fID\fP is not associated with a character
+special device.
+.TP 15
+[ENOTTY]
+The specified request does not apply to the kind
+of object that the descriptor \fId\fP references.
+.TP 15
+[EINVAL]
+\fIRequest\fP or \fIargp\fP is not valid.
+.SH "SEE ALSO"
+.BR execve (2),
+.BR fcntl (2),
+.BR mt (4),
+.BR tty (4),
+.BR intro (4).
Index: /trunk/minix/man/man2/kill.2
===================================================================
--- /trunk/minix/man/man2/kill.2	(revision 9)
+++ /trunk/minix/man/man2/kill.2	(revision 9)
@@ -0,0 +1,93 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)kill.2	6.5 (Berkeley) 5/14/86
+.\"
+.TH KILL 2 "May 14, 1986"
+.UC 4
+.SH NAME
+kill \- send signal to a process
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <signal.h>
+
+int kill(pid_t \fIpid\fP, int \fIsig\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Kill
+sends the signal \fIsig\fP
+to a process, specified by the process number
+.IR pid .
+.I Sig
+may be one of the signals specified in
+.BR sigaction (2),
+or it may be 0, in which case
+error checking is performed but no
+signal is actually sent. 
+This can be used to check the validity of
+.IR pid .
+.PP
+The sending and receiving processes must
+have the same effective user ID, otherwise
+this call is restricted to the super-user.
+.ig
+A single exception is the signal SIGCONT, which may always be sent
+to any descendant of the current process.
+..
+.PP
+If the process number is 0,
+the signal is sent to all processes in the
+sender's process group.
+.PP
+If the process number is \-1
+and the user is the super-user,
+the signal is broadcast universally
+except to
+.B init
+and the process sending the signal.
+If the process number is \-1
+and the user is not the super-user,
+the signal is broadcast universally to
+all processes with the same uid as the user
+except the process sending the signal.
+No error is returned if any process could be signaled.
+.PP
+If the process number is negative but not \-1,
+the signal is sent to all processes whose process group ID
+is equal to the absolute value of the process number.
+.PP
+Processes may send signals to themselves.
+.SH "RETURN VALUE
+Upon successful completion, a value of 0 is returned.
+Otherwise, a value of \-1 is returned and
+.B errno
+is set to indicate the error.
+.SH "ERRORS
+.B Kill
+will fail and no signal will be sent if any of the following
+occur:
+.TP 15
+[EINVAL]
+\fISig\fP is not a valid signal number.
+.TP 15
+[ESRCH]
+No process can be found corresponding to that specified by \fIpid\fP.
+.TP 15
+[ESRCH]
+The process id was given as 0
+but the sending process does not have a process group.
+.TP 15
+[EPERM]
+The sending process is not the super-user and its effective
+user id does not match the effective user-id of the receiving process.
+When signaling a process group, this error was returned if any members
+of the group could not be signaled.
+.SH "SEE ALSO"
+.BR getpid (2),
+.BR getpgrp (2),
+.BR sigaction (2),
+.BR raise (3).
Index: /trunk/minix/man/man2/link.2
===================================================================
--- /trunk/minix/man/man2/link.2	(revision 9)
+++ /trunk/minix/man/man2/link.2	(revision 9)
@@ -0,0 +1,111 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)link.2	6.3 (Berkeley) 8/26/85
+.\"
+.TH LINK 2 "August 26, 1985"
+.UC 4
+.SH NAME
+link \- make a hard link to a file
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+int link(const char *\fIname1\fP, const char *\fIname2\fP)
+.fi
+.ft R
+.SH DESCRIPTION
+A hard link
+to
+.I name1
+is created;
+the link has the name
+.IR name2 .
+.I Name1
+must exist.
+.PP
+With hard links,
+both
+.I name1
+and
+.I name2
+must be in the same file system.
+.I Name1
+must not be a directory.
+Both the old and the new
+.I link
+share equal access and rights to
+the underlying object.
+.SH "RETURN VALUE
+Upon successful completion, a value of 0 is returned.  Otherwise,
+a value of \-1 is returned and
+.B errno
+is set to indicate the error.
+.SH "ERRORS
+.B Link
+will fail and no link will be created if one or more of the following
+are true:
+.TP 15
+[ENOTDIR]
+A component of either path prefix is not a directory.
+.TP 15
+[ENAMETOOLONG]
+A path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+A component of either path prefix does not exist.
+.TP 15
+[EACCES]
+A component of either path prefix denies search permission.
+.TP 15
+[EACCES]
+The requested link requires writing in a directory with a mode
+that denies write permission.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating one of the pathnames.
+(Minix-vmd)
+.TP 15
+[ENOENT]
+The file named by \fIname1\fP does not exist.
+.TP 15
+[EEXIST]
+The link named by \fIname2\fP does exist.
+.TP 15
+[EPERM]
+The file named by \fIname1\fP is a directory and the effective
+user ID is not super-user.
+.TP 15
+[EXDEV]
+The link named by \fIname2\fP and the file named by \fIname1\fP
+are on different file systems.
+.TP 15
+[ENOSPC]
+The directory in which the entry for the new link is being placed
+cannot be extended because there is no space left on the file
+system containing the directory.
+.ig
+.TP 15
+[EDQUOT]
+The directory in which the entry for the new link
+is being placed cannot be extended because the
+user's quota of disk blocks on the file system
+containing the directory has been exhausted.
+..
+.TP 15
+[EIO]
+An I/O error occurred while reading from or writing to 
+the file system to make the directory entry.
+.TP 15
+[EROFS]
+The requested link requires writing in a directory on a read-only file
+system.
+.TP 15
+[EFAULT]
+One of the pathnames specified
+is outside the process's allocated address space.
+.SH "SEE ALSO"
+.BR symlink (2),
+.BR unlink (2).
Index: /trunk/minix/man/man2/lseek.2
===================================================================
--- /trunk/minix/man/man2/lseek.2	(revision 9)
+++ /trunk/minix/man/man2/lseek.2	(revision 9)
@@ -0,0 +1,86 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)lseek.2	6.3 (Berkeley) 2/24/86
+.\"
+.TH LSEEK 2 "February 24, 1986"
+.UC 4
+.SH NAME
+lseek \- move read/write pointer
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <unistd.h>
+
+.ta +1.8i +0.6i
+#define SEEK_SET	0	/* offset is absolute */
+#define SEEK_CUR	1	/* relative to current position */
+#define SEEK_END	2	/* relative to end of file */
+
+off_t lseek(int d, off_t offset, int whence)
+.fi
+.ft R
+.SH DESCRIPTION
+The descriptor 
+.I d
+refers to a file or device open for reading and/or writing.
+.B Lseek
+sets the file pointer of
+.I d
+as follows:
+.IP
+If
+.I whence
+is SEEK_SET, the pointer is set to
+.I offset
+bytes.
+.IP
+If
+.I whence
+is SEEK_CUR, the pointer is set to its current location plus
+.IR offset .
+.IP
+If
+.I whence
+is SEEK_END, the pointer is set to the size of the
+file plus
+.IR offset .
+.PP
+Upon successful completion, the resulting pointer location
+as measured in bytes from beginning of the file is returned.
+Some devices are incapable of seeking.  The value of the pointer
+associated with such a device is undefined.
+.SH NOTES
+Seeking far beyond the end of a file, then writing,
+creates a gap or \*(lqhole\*(rq, which occupies no
+physical space and reads as zeros.
+.SH "RETURN VALUE
+Upon successful completion,
+the current file pointer value is returned.
+Otherwise,
+a value of \-1 is returned and \fBerrno\fP is set to indicate
+the error.
+.SH "ERRORS
+.B Lseek
+will fail and the file pointer will remain unchanged if:
+.TP 15
+[EBADF]
+.I Fildes
+is not an open file descriptor.
+.TP 15
+[ESPIPE]
+.I Fildes
+is associated with a pipe or a socket.
+.TP 15
+[EINVAL]
+.I Whence
+is not a proper value.
+.SH "SEE ALSO"
+.BR fcntl (2),
+.BR open (2).
+.SH BUGS
+This document's use of
+.I whence
+is incorrect English, but maintained for historical reasons.
Index: /trunk/minix/man/man2/mkdir.2
===================================================================
--- /trunk/minix/man/man2/mkdir.2	(revision 9)
+++ /trunk/minix/man/man2/mkdir.2	(revision 9)
@@ -0,0 +1,112 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)mkdir.2	6.4 (Berkeley) 8/26/85
+.\"
+.TH MKDIR 2 "August 26, 1985"
+.UC 5
+.SH NAME
+mkdir \- make a directory file
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <sys/stat.h>
+
+int mkdir(const char *\fIpath\fP, mode_t \fImode\fP)
+.fi
+.ft R
+.SH DESCRIPTION
+.B Mkdir
+creates a new directory file with name
+.IR path .
+The mode of the new file
+is initialized from
+.IR mode .
+(The protection part of the mode
+is modified by the process's mode mask; see
+.BR umask (2)).
+.PP
+The directory's owner ID is set to the process's effective user ID.
+The directory's group ID is set to that of the parent directory in
+which it is created.
+.PP
+The low-order 9 bits of mode are modified by the process's
+file mode creation mask: all bits set in the process's file mode
+creation mask are cleared.  See
+.BR umask (2).
+.SH "RETURN VALUE
+A 0 return value indicates success.  A \-1 return value
+indicates an error, and an error code is stored in
+.B errno.
+.SH "ERRORS
+.B Mkdir
+will fail and no directory will be created if:
+.TP 15
+[ENOTDIR]
+A component of the path prefix is not a directory.
+.TP 15
+[ENAMETOOLONG]
+The path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+A component of the path prefix does not exist.
+.TP 15
+[EACCES]
+Search permission is denied for a component of the path prefix.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating the pathname.
+(Minix-vmd)
+.TP 15
+[EROFS]
+The named file resides on a read-only file system.
+.TP 15
+[EEXIST]
+The named file exists.
+.TP 15
+[ENOSPC]
+The directory in which the entry for the new directory is being placed
+cannot be extended because there is no space left on the file
+system containing the directory.
+.TP 15
+[ENOSPC]
+The new directory cannot be created because there
+there is no space left on the file
+system that will contain the directory.
+.TP 15
+[ENOSPC]
+There are no free inodes on the file system on which the
+directory is being created.
+.ig
+.TP 15
+[EDQUOT]
+The directory in which the entry for the new directory
+is being placed cannot be extended because the
+user's quota of disk blocks on the file system
+containing the directory has been exhausted.
+.TP 15
+[EDQUOT]
+The new directory cannot be created because the user's
+quota of disk blocks on the file system that will
+contain the directory has been exhausted.
+.TP 15
+[EDQUOT]
+The user's quota of inodes on the file system on
+which the directory is being created has been exhausted.
+..
+.TP 15
+[EIO]
+An I/O error occurred while making the directory entry or allocating the inode.
+.TP 15
+[EIO]
+An I/O error occurred while reading from or writing to the file system.
+.TP 15
+[EFAULT]
+.I Path
+points outside the process's allocated address space.
+.SH "SEE ALSO"
+.BR chmod (2),
+.BR stat (2),
+.BR umask (2).
Index: /trunk/minix/man/man2/mknod.2
===================================================================
--- /trunk/minix/man/man2/mknod.2	(revision 9)
+++ /trunk/minix/man/man2/mknod.2	(revision 9)
@@ -0,0 +1,131 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)mknod.2	6.4 (Berkeley) 5/23/86
+.\"
+.TH MKNOD 2 "May 23, 1986"
+.UC 4
+.SH NAME
+mknod, mkfifo \- make a special file
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+int mknod(const char *\fIpath\fP, mode_t \fImode\fP, dev_t \fIdev\fP)
+int mkfifo(const char *\fIpath\fP, mode_t \fImode\fP)
+.fi
+.ft R
+.SH DESCRIPTION
+.B Mknod
+creates a new file
+whose name is
+.I path.
+The mode of the new file
+(including special file bits)
+is initialized from
+.IR mode ,
+as defined in
+.IR <sys/stat.h> .
+(The protection part of the mode
+is modified by the process's mode mask (see
+.BR umask (2))).
+The first block pointer of the i-node
+is initialized from
+.I dev 
+and is used to specify which device the special file
+refers to.
+.PP
+If mode indicates a block or character special file,
+.I dev
+is the device number of a character or block I/O device.
+The low eight bits of the device number hold the minor device number
+that selects a device among the devices governed by the same driver.
+The driver is selected by the major device number, the next eight bits
+of the device number.
+.PP
+If
+.I mode
+does not indicate a block special or character special device,
+.I dev
+is ignored.
+(For example, when creating a ``fifo'' special file.)
+.PP
+.B Mknod
+may be invoked only by the super-user,
+unless it is being used to create a fifo.
+.PP
+The call
+.BI "mkfifo(" path ", " mode ")"
+is equivalent to
+.PP
+.RS
+.BI "mknod(" path ", (" mode " & 0777) | S_IFIFO, 0)"
+.RE
+.SH "RETURN VALUE
+Upon successful completion a value of 0 is returned.
+Otherwise, a value of \-1 is returned and \fBerrno\fP
+is set to indicate the error.
+.SH ERRORS
+.B Mknod
+will fail and the file mode will be unchanged if:
+.TP 15
+[ENOTDIR]
+A component of the path prefix is not a directory.
+.TP 15
+[ENAMETOOLONG]
+The path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+A component of the path prefix does not exist.
+.TP 15
+[EACCES]
+Search permission is denied for a component of the path prefix.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating the pathname.
+(Minix-vmd)
+.TP 15
+[EPERM]
+The process's effective user ID is not super-user.
+.TP 15
+[EIO]
+An I/O error occurred while making the directory entry or allocating the inode.
+.TP 15
+[ENOSPC]
+The directory in which the entry for the new node is being placed
+cannot be extended because there is no space left on the file
+system containing the directory.
+.TP 15
+[ENOSPC]
+There are no free inodes on the file system on which the
+node is being created.
+.ig
+.TP 15
+[EDQUOT]
+The directory in which the entry for the new node
+is being placed cannot be extended because the
+user's quota of disk blocks on the file system
+containing the directory has been exhausted.
+.TP 15
+[EDQUOT]
+The user's quota of inodes on the file system on
+which the node is being created has been exhausted.
+..
+.TP 15
+[EROFS]
+The named file resides on a read-only file system.
+.TP 15
+[EEXIST]
+The named file exists.
+.TP 15
+[EFAULT]
+.I Path
+points outside the process's allocated address space.
+.SH "SEE ALSO"
+.BR chmod (2),
+.BR stat (2),
+.BR umask (2).
Index: /trunk/minix/man/man2/mount.2
===================================================================
--- /trunk/minix/man/man2/mount.2	(revision 9)
+++ /trunk/minix/man/man2/mount.2	(revision 9)
@@ -0,0 +1,51 @@
+.TH MOUNT 2
+.SH NAME
+mount, umount \- mount or umount a file system
+.SH SYNOPSIS
+.ft B
+.nf
+#include <unistd.h>
+#include <sys/mount.h>
+
+int mount(char *\fIspecial\fP, char *\fIname\fP, int \fIflag\fP)
+int umount(char *\fIname\fP)
+.fi
+.ft P
+.SH DESCRIPTION
+.B Mount()
+tells the system that the file system
+.I special
+is to be mounted on the file
+.IR name ,
+effectively overlaying
+.I name
+with the file tree on
+.IR special .
+.I Name
+may of any type, except that if the root of
+.I special
+is a directory, then
+.I name
+must also be a directory.
+.I Special
+must be a block special file, except for loopback mounts.  For loopback
+mounts a normal file or directory is used for
+.IR special ,
+which must be seen as the root of a virtual device.
+.I Flag
+is 0 for a read-write mount, 1 for read-only.
+.PP
+.B Umount()
+removes the connection between a device and a mount point,
+.I name
+may refer to either of them.  If more than one device is mounted on the
+same mount point then unmounting at the mount point removes the last mounted
+device, unmounting a device removes precisely that device.  The unmount will
+only succeed if none of the files on the device are in use.
+.PP
+Both calls may only be executed by the super-user.
+.SH "SEE ALSO"
+.BR mount (1),
+.BR umount (1).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man2/open.2
===================================================================
--- /trunk/minix/man/man2/open.2	(revision 9)
+++ /trunk/minix/man/man2/open.2	(revision 9)
@@ -0,0 +1,186 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)open.2	6.4 (Berkeley) 5/14/86
+.\"
+.TH OPEN 2 "May 14, 1986"
+.UC 4
+.SH NAME
+open \- open a file for reading or writing, or create a new file
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <fcntl.h>
+
+int open(const char *\fIpath\fP, int \fIflags\fP \fR[\fP, mode_t \fImode\fP\fR]\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Open
+opens the file
+.I path
+for reading and/or writing, as specified by the
+.I flags
+argument and returns a descriptor for that file.
+The
+.I flags
+argument may indicate the file is to be
+created if it does not already exist (by specifying the
+O_CREAT flag), in which case the file is created with mode
+.I mode
+as described in
+.BR chmod (2)
+and modified by the process' umask value (see
+.BR umask (2)).
+.PP
+.I Path
+is the address of a string of ASCII characters representing
+a path name, terminated by a null character.
+The flags specified are formed by
+.IR or 'ing
+the following values
+.PP
+.RS
+.ta +12n
+.nf
+O_RDONLY	open for reading only
+O_WRONLY	open for writing only
+O_RDWR	open for reading and writing
+O_NONBLOCK	do not block on open
+O_APPEND	append on each write
+O_CREAT	create file if it does not exist
+O_TRUNC	truncate size to 0
+O_EXCL	error if create and file exists
+.fi
+.DT
+.RE
+.PP
+Opening a file with O_APPEND set causes each write on the file
+to be appended to the end.  If O_TRUNC is specified and the
+file exists, the file is truncated to zero length.
+If O_EXCL is set with O_CREAT, then if the file already
+exists, the open returns an error.  This can be used to
+implement a simple exclusive access locking mechanism.
+If O_EXCL is set and the last component of the pathname is
+a symbolic link, the open will fail even if the symbolic
+link points to a non-existent name.
+If the O_NONBLOCK flag is specified and the open call would result
+in the process being blocked for some reason, the open returns immediately. 
+.PP
+Upon successful completion a non-negative integer termed a
+file descriptor is returned.
+The file pointer used to mark the current position within the
+file is set to the beginning of the file.
+.PP
+The new descriptor is set to remain open across
+.BR execve
+system calls; see
+.BR close (2).
+.PP
+The system imposes a limit on the number of descriptors
+open simultaneously by one process.
+.SH "ERRORS
+The named file is opened unless one or more of the
+following are true:
+.TP 15
+[ENOTDIR]
+A component of the path prefix is not a directory.
+.TP 15
+[ENAMETOOLONG]
+The path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+O_CREAT is not set and the named file does not exist.
+.TP 15
+[ENOENT]
+A component of the path name that must exist does not exist.
+.TP 15
+[EACCES]
+Search permission is denied for a component of the path prefix.
+.TP 15
+[EACCES]
+The required permissions (for reading and/or writing)
+are denied for the named file.
+.TP 15
+[EACCES]
+O_CREAT is specified,
+the file does not exist,
+and the directory in which it is to be created
+does not permit writing.
+.TP 15
+[EACCES]
+A device to be opened for writing is physically write protected.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating the pathname.
+(Minix-vmd)
+.TP 15
+[EISDIR]
+The named file is a directory, and the arguments specify
+it is to be opened for writing.
+.TP 15
+[EROFS]
+The named file resides on a read-only file system,
+and the file is to be modified.
+.TP 15
+[EMFILE]
+The system limit for open file descriptors per process has already been reached.
+.TP 15
+[ENFILE]
+The system file table is full.
+.TP 15
+[ENXIO]
+The named file is a character special or block
+special file, and the device associated with this special file
+does not exist.
+.TP 15
+[ENOSPC]
+O_CREAT is specified,
+the file does not exist,
+and the directory in which the entry for the new file is being placed
+cannot be extended because there is no space left on the file
+system containing the directory.
+.TP 15
+[ENOSPC]
+O_CREAT is specified,
+the file does not exist,
+and there are no free inodes on the file system on which the
+file is being created.
+.ig
+.TP 15
+[EDQUOT]
+O_CREAT is specified,
+the file does not exist,
+and the directory in which the entry for the new fie
+is being placed cannot be extended because the
+user's quota of disk blocks on the file system
+containing the directory has been exhausted.
+.TP 15
+[EDQUOT]
+O_CREAT is specified,
+the file does not exist,
+and the user's quota of inodes on the file system on
+which the file is being created has been exhausted.
+..
+.TP 15
+[EIO]
+An I/O error occurred while making the directory entry or
+allocating the inode for O_CREAT.
+.TP 15
+[EFAULT]
+.I Path
+points outside the process's allocated address space.
+.TP 15
+[EEXIST]
+O_CREAT and O_EXCL were specified and the file exists.
+.SH "SEE ALSO"
+.BR chmod (2),
+.BR close (2),
+.BR dup (2),
+.BR fcntl (2),
+.BR lseek (2),
+.BR read (2),
+.BR write (2),
+.BR umask (2).
Index: /trunk/minix/man/man2/pause.2
===================================================================
--- /trunk/minix/man/man2/pause.2	(revision 9)
+++ /trunk/minix/man/man2/pause.2	(revision 9)
@@ -0,0 +1,43 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)pause.3c	6.1 (Berkeley) 5/9/85
+.\"
+.TH PAUSE 2 "May 9, 1985"
+.UC 4
+.SH NAME
+pause \- stop until signal
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+int pause(void)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Pause
+never returns normally.
+It is used to give up control while waiting for
+a signal from
+.BR kill (2)
+or the alarm timer, see
+.BR alarm (2).
+Upon termination of a signal handler started during a
+.B pause,
+the
+.B pause
+call will return.
+.SH "RETURN VALUE
+Always returns \-1.
+.SH ERRORS
+.B Pause
+always returns:
+.TP 15
+[EINTR]
+The call was interrupted.
+.SH "SEE ALSO
+.BR alarm (2),
+.BR kill (2),
+.BR sigsuspend (2).
Index: /trunk/minix/man/man2/pipe.2
===================================================================
--- /trunk/minix/man/man2/pipe.2	(revision 9)
+++ /trunk/minix/man/man2/pipe.2	(revision 9)
@@ -0,0 +1,89 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)pipe.2	6.2 (Berkeley) 8/26/85
+.\"
+.TH PIPE 2 "August 26, 1985"
+.UC 4
+.SH NAME
+pipe \- create an interprocess communication channel
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+int pipe(int \fIfildes\fP[2])
+.fi
+.ft R
+.SH DESCRIPTION
+The
+.B pipe
+system call
+creates an I/O mechanism called a pipe.
+The file descriptors returned can
+be used in read and write operations.
+When the pipe is written using the descriptor
+.IR fildes [1]
+up to PIPE_MAX bytes of data are buffered
+before the writing process is suspended.
+A read using the descriptor
+.IR fildes [0]
+will pick up the data.
+.PP
+PIPE_MAX equals 7168 under MINIX 3, but note that most systems use 4096.
+.PP
+It is assumed that after the
+pipe has been set up,
+two (or more)
+cooperating processes
+(created by subsequent
+.B fork
+calls)
+will pass data through the
+pipe with
+.B read
+and
+.B write
+calls.
+.PP
+The shell has a syntax
+to set up a linear array of processes
+connected by pipes.
+.PP
+Read calls on an empty
+pipe (no buffered data) with only one end
+(all write file descriptors closed)
+returns an end-of-file.
+.PP
+The signal SIGPIPE is generated if a write on a pipe with only one end
+is attempted.
+.SH "RETURN VALUE
+The function value zero is returned if the
+pipe was created; \-1 if an error occurred.
+.SH ERRORS
+The \fBpipe\fP call will fail if:
+.TP 15
+[EMFILE]
+Too many descriptors are active.
+.TP 15
+[ENFILE]
+The system file table is full.
+.TP 15
+[ENOSPC]
+The pipe file system (usually the root file system) has no free inodes.
+.TP 15
+[EFAULT]
+The \fIfildes\fP buffer is in an invalid area of the process's address
+space.
+.SH "SEE ALSO"
+.BR sh (1),
+.BR read (2),
+.BR write (2),
+.BR fork (2).
+.SH NOTES
+Writes may return ENOSPC errors if no pipe data can be buffered, because
+the pipe file system is full.
+.SH BUGS
+Should more than PIPE_MAX bytes be necessary in any
+pipe among a loop of processes, deadlock will occur.
Index: /trunk/minix/man/man2/ptrace.2
===================================================================
--- /trunk/minix/man/man2/ptrace.2	(revision 9)
+++ /trunk/minix/man/man2/ptrace.2	(revision 9)
@@ -0,0 +1,231 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)ptrace.2	6.4 (Berkeley) 5/23/86
+.\"
+.TH PTRACE 2 "May 23, 1986"
+.UC 4
+.SH NAME
+ptrace \- process trace
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <sys/signal.h>
+#include <sys/ptrace.h>
+
+int ptrace(int \fIrequest\fP, pid_t \fIpid\fP, long \fIaddr\fP, long \fIdata\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.ft B
+Note: This manual page has no relation to MINIX 3.  Someone who knows ptrace()
+has to check, or rewrite, this page.  (kjb)
+.ft R
+.PP
+.B Ptrace
+provides a means by which a parent process
+may control the execution of a child process,
+and examine and change its core image.
+Its primary use is for the implementation of breakpoint debugging.
+There are four arguments whose interpretation
+depends on a
+.I request
+argument.
+Generally,
+.I pid
+is the process ID of the traced process,
+which must be a child (no more distant descendant)
+of the tracing process.
+A process being traced
+behaves normally until it encounters some signal
+whether internally generated
+like \*(lqillegal instruction\*(rq or externally
+generated like \*(lqinterrupt\*(rq.
+See
+.BR sigaction (2)
+for the list.
+Then the traced process enters a stopped state
+and its parent is notified via
+.BR  wait (2).
+When the child is in the stopped state,
+its core image can be examined and modified
+using
+.BR ptrace .
+If desired, another
+.B ptrace
+request can then cause the child either to terminate
+or to continue, possibly ignoring the signal.
+.PP
+The value of the
+.I request
+argument determines the precise
+action of the call:
+.TP 4
+PT_TRACE_ME
+This request is the only one used by the child process;
+it declares that the process is to be traced by its parent.
+All the other arguments are ignored.
+Peculiar results will ensue
+if the parent does not expect to trace the child.
+.TP 4
+PT_READ_I, PT_READ_D
+The
+word in the child process's address space
+at
+.I addr
+is returned.
+If I and D space are separated (e.g. historically
+on a pdp-11), request PT_READ_I indicates I space,
+PT_READ_D D space.
+.I Addr
+must be even on some machines.
+The child must be stopped.
+The input
+.I data
+is ignored.
+.TP 4
+PT_READ_U
+The word
+of the system's per-process data area corresponding to
+.I addr
+is returned.
+.I Addr
+must be even on some machines and less than 512.
+This space contains the registers and other information about
+the process;
+its layout corresponds to the
+.I user
+structure in the system.
+.TP 4
+PT_WRITE_I, PT_WRITE_D
+The
+given
+.I data
+is written at the word in the process's address space corresponding to
+.I addr,
+which must be even on some machines.
+No useful value is returned.
+If I and D space are separated, request PT_WRITE_I indicates I space, 
+PT_WRITE_D D space.
+Attempts to write in pure procedure
+fail if another process is executing the same file.
+.TP 4
+PT_WRITE_U
+The process's system data is written,
+as it is read with request PT_READ_U.
+Only a few locations can be written in this way:
+the general registers,
+the floating point status and registers,
+and certain bits of the processor status word.
+.TP 4
+PT_CONTINUE
+The
+.I data
+argument is taken as a signal number
+and the child's execution continues
+at location
+.I addr
+as if it had incurred that signal.
+Normally the signal number will be
+either 0 to indicate that the signal that caused the stop
+should be ignored,
+or that value fetched out of the
+process's image indicating which signal caused
+the stop.
+If
+.I addr
+is (int *)1 then execution continues from where it stopped.
+.TP 4
+PT_KILL
+The traced process terminates.
+.TP 4
+PT_STEP
+Execution continues as in request PT_CONTINUE;
+however, as soon as possible after execution of at least one instruction,
+execution stops again.
+The signal number from the stop is
+SIGTRAP.
+(On the VAX-11 the T-bit is used and just one instruction
+is executed.)
+This is part of the mechanism for implementing breakpoints.
+.PP
+As indicated,
+these calls
+(except for request PT_TRACE_ME)
+can be used only when the subject process has stopped.
+The
+.B wait
+call is used to determine
+when a process stops;
+in such a case the \*(lqtermination\*(rq status
+returned by
+.B wait
+has the value 0177 to indicate stoppage rather
+than genuine termination.
+.PP
+To forestall possible fraud,
+.B ptrace
+inhibits the set-user-id and set-group-id facilities
+on subsequent
+.BR  execve (2)
+calls.
+If a traced process calls
+.BR execve ,
+it will stop before executing the first instruction of the new image
+showing signal SIGTRAP.
+.PP
+On a VAX-11, \*(lqword\*(rq also means a 32-bit integer,
+but the \*(lqeven\*(rq
+restriction does not apply.
+.SH "RETURN VALUE
+A 0 value is returned if the call succeeds.  If the call fails
+then a \-1 is returned and the global variable \fIerrno\fP is
+set to indicate the error.
+.SH "ERRORS
+.TP 15
+[EIO]
+The request code is invalid.
+.TP 15
+[ESRCH]
+The specified process does not exist.
+.TP 15
+[EIO]
+The given signal number is invalid.
+.TP 15
+[EIO]
+The specified address is out of bounds.
+.TP 15
+[EPERM]
+The specified process cannot be traced.
+.SH "SEE ALSO"
+.BR wait (2),
+.BR sigaction (2),
+.BR mdb (1).
+.SH BUGS
+.B Ptrace
+is unique and arcane; it should be replaced with a special file that
+can be opened and read and written.  The control functions could then
+be implemented with
+.BR ioctl (2)
+calls on this file.  This would be simpler to understand and have much
+higher performance.
+.PP
+The request PT_TRACE_ME call should be able to specify
+signals that are to be treated normally and not cause a stop.
+In this way, for example,
+programs with simulated floating point (which
+use \*(lqillegal instruction\*(rq signals at a very high rate)
+could be efficiently debugged.
+.PP
+The error indication, \-1, is a legitimate function value;
+.BR errno ,
+(see
+.BR intro (2)),
+can be used to disambiguate.
+.PP
+It should be possible to stop a process on occurrence of a system
+call;
+in this way a completely controlled environment could
+be provided.
Index: /trunk/minix/man/man2/read.2
===================================================================
--- /trunk/minix/man/man2/read.2	(revision 9)
+++ /trunk/minix/man/man2/read.2	(revision 9)
@@ -0,0 +1,83 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)read.2	6.6 (Berkeley) 5/23/86
+.\"
+.TH READ 2 "May 23, 1986"
+.UC 4
+.SH NAME
+read \- read input
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <unistd.h>
+
+ssize_t read(int \fId\fP, void *\fIbuf\fP, size_t \fInbytes\fP)
+.fi
+.SH DESCRIPTION
+.B Read
+attempts to read
+.I nbytes
+of data from the object referenced by the descriptor
+.I d
+into the buffer pointed to by
+.IR buf .
+.PP
+On objects capable of seeking, the
+.B read
+starts at a position
+given by the pointer associated with
+.IR d 
+(see
+.BR lseek (2)).
+Upon return from
+.BR read ,
+the pointer is incremented by the number of bytes actually read.
+.PP
+Objects that are not capable of seeking always read from the current
+position.  The value of the pointer associated with such an
+object is undefined.
+.PP
+Upon successful completion,
+.B read
+return the number of bytes actually read and placed in the buffer.
+The system guarantees to read the number of bytes requested if
+the descriptor references a normal file that has that many bytes left
+before the end-of-file, but in no other case.
+.PP
+If the returned value is 0, then
+end-of-file has been reached.
+.SH "RETURN VALUE
+If successful, the
+number of bytes actually read is returned.
+Otherwise, a \-1 is returned and the global variable
+.B errno
+is set to indicate the error.
+.SH "ERRORS
+.B Read
+will fail if one or more of the following are true:
+.TP 15
+[EBADF]
+\fID\fP is not a valid descriptor open for reading.
+.TP 15
+[EFAULT]
+\fIBuf\fP points outside the allocated address space.
+.TP 15
+[EIO]
+An I/O error occurred while reading from the file system.
+.TP 15
+[EINTR]
+A read from a slow device was interrupted before
+any data arrived by the delivery of a signal.
+.TP 15
+[EAGAIN]
+The file was marked for non-blocking I/O,
+and no data were ready to be read.
+.SH "SEE ALSO"
+.BR dup (2),
+.BR fcntl (2),
+.BR open (2),
+.BR pipe (2),
+.BR write (2).
Index: /trunk/minix/man/man2/readlink.2
===================================================================
--- /trunk/minix/man/man2/readlink.2	(revision 9)
+++ /trunk/minix/man/man2/readlink.2	(revision 9)
@@ -0,0 +1,54 @@
+.TH READLINK 2 "March 17, 2006"
+.UC 4
+.SH NAME
+readlink \- read the contents of a symlink
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+int readlink(const char *\fIpath\fP, char *\fIbuf\fP, size_t bufsize)
+.fi
+.ft R
+.SH DESCRIPTION
+The 
+.I readlink
+call reads the contents of the symlink
+.I name1
+and returns it in
+.I buf
+up to a maximum of
+.I bufsize
+bytes. A terminating NUL byte is NOT put in the buffer.
+.SH "RETURN VALUE
+Upon successful completion, a value of 0 is returned.  Otherwise,
+a value of \-1 is returned and
+.B errno
+is set to indicate the error.
+.SH "ERRORS
+.B Readlink
+will fail if one or more of the following are true:
+.TP 15
+[ENOTDIR]
+A component of either path prefix is not a directory.
+.TP 15
+[ENAMETOOLONG]
+A path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+A component of the path does not exist.
+.TP 15
+[EACCES]
+A component of the path denies search permission.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating one of the pathnames.
+.TP 15
+[ENOENT]
+The link named by \fIpath\fP does not exist.
+.TP 15
+[EFAULT]
+The buffer specified is outside the process's allocated address space.
+.SH "SEE ALSO"
+.BR symlink (2),
+.BR unlink (2).
Index: /trunk/minix/man/man2/reboot.2
===================================================================
--- /trunk/minix/man/man2/reboot.2	(revision 9)
+++ /trunk/minix/man/man2/reboot.2	(revision 9)
@@ -0,0 +1,62 @@
+.TH REBOOT 2
+.SH NAME
+reboot \- close down the system or reboot
+.SH SYNTAX
+.ft B
+.nf
+#define _MINIX_SOURCE 1
+
+#include <unistd.h>
+
+int reboot(int \fIhow\fP, ...)
+.fi
+.ft P
+.SH DESCRIPTION
+.B Reboot()
+is used to close down the system.  It allows several ways of shutting
+down depending on
+.IR how :
+.PP
+.TP 5
+.BI "reboot(RBT_HALT)"
+Halt the system and return to the monitor prompt.
+.TP
+.BI "reboot(RBT_REBOOT)"
+Reboot the system by letting the monitor execute the "boot" command.
+.TP
+.BI "reboot(RBT_PANIC)"
+Cause a system panic.  This is not normally done from user mode, but by
+servers using the
+.B sys_abort()
+kernel call.
+.TP
+.BI "reboot(RBT_MONITOR" ", code, length" ")"
+Halt the system and let the monitor execute the given code of the given
+length.
+.RI ( code
+is of type
+.B "char *"
+and
+.I length
+of type
+.BR size_t .)
+.TP
+.BI "reboot(RBT_RESET)"
+Reboot the system with a hardware reset.
+.PP
+.B Reboot()
+may only be executed by the super-user.
+.SH DIAGNOSTICS
+If the call succeeds, it never returns.  If something went wrong,
+the return value is -1 and an error is indicated by
+.BR errno .
+.SH SEE ALSO
+.BR shutdown (8),
+.BR reboot (8),
+.BR halt (8),
+.BR sync (2).
+.SH NOTES
+MINIX 3 can not return to the monitor if running in real mode.  This means
+that most of the reboot functions will change to a system reset.
+.SH AUTHOR
+Edvard Tuinder (v892231@si.hhs.NL)
Index: /trunk/minix/man/man2/rename.2
===================================================================
--- /trunk/minix/man/man2/rename.2	(revision 9)
+++ /trunk/minix/man/man2/rename.2	(revision 9)
@@ -0,0 +1,135 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)rename.2	6.4 (Berkeley) 5/22/86
+.\"
+.TH RENAME 2 "May 22, 1986"
+.UC 5
+.SH NAME
+rename \- change the name of a file
+.SH SYNOPSIS
+.ft B
+.nf
+#include <stdio.h>
+
+int rename(const char *\fIfrom\fP, const char *\fIto\fP)
+.fi
+.ft R
+.SH DESCRIPTION
+.B Rename
+causes the link named
+.I from
+to be renamed as
+.IR to .
+If 
+.I to
+exists, then it is first removed.
+Both 
+.I from
+and
+.I to
+must be of the same type (that is, both directories or both
+non-directories), and must reside on the same file system.
+.PP
+.B Rename
+guarantees that an instance of
+.I to
+will always exist, even if the system should crash in
+the middle of the operation.
+.PP
+If the final component of
+.I from
+is a symbolic link,
+the symbolic link is renamed,
+not the file or directory to which it points.
+.SH "RETURN VALUE"
+A 0 value is returned if the operation succeeds, otherwise
+.B rename
+returns \-1 and the global variable 
+.B errno
+indicates the reason for the failure.
+.SH "ERRORS
+.B Rename
+will fail and neither of the argument files will be
+affected if any of the following are true:
+.TP 15
+[ENAMETOOLONG]
+A path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+A component of the \fIfrom\fP path does not exist,
+or a path prefix of \fIto\fP does not exist.
+.TP 15
+[EACCES]
+A component of either path prefix denies search permission.
+.TP 15
+[EACCES]
+The requested link requires writing in a directory with a mode
+that denies write permission.
+.TP 15
+[EPERM]
+The directory containing \fIfrom\fP is marked sticky,
+and neither the containing directory nor \fIfrom\fP
+are owned by the effective user ID.
+.TP 15
+[EPERM]
+The \fIto\fP file exists,
+the directory containing \fIto\fP is marked sticky,
+and neither the containing directory nor \fIto\fP
+are owned by the effective user ID.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating either pathname.
+(Minix-vmd)
+.TP 15
+[ENOTDIR]
+A component of either path prefix is not a directory.
+.TP 15
+[ENOTDIR]
+.I From
+is a directory, but \fIto\fP is not a directory.
+.TP 15
+[EISDIR]
+.I To
+is a directory, but \fIfrom\fP is not a directory.
+.TP 15
+[EXDEV]
+The link named by \fIto\fP and the file named by \fIfrom\fP
+are on different logical devices (file systems).
+.TP 15
+[ENOSPC]
+The directory in which the entry for the new name is being placed
+cannot be extended because there is no space left on the file
+system containing the directory.
+.ig
+.TP 15
+[EDQUOT]
+The directory in which the entry for the new name
+is being placed cannot be extended because the
+user's quota of disk blocks on the file system
+containing the directory has been exhausted.
+..
+.TP 15
+[EIO]
+An I/O error occurred while making or updating a directory entry.
+.TP 15
+[EROFS]
+The requested link requires writing in a directory on a read-only file
+system.
+.TP 15
+[EFAULT]
+.I Path
+points outside the process's allocated address space.
+.TP 15
+[EINVAL]
+.I From
+is a parent directory of
+.IR to ,
+or an attempt is made to rename ``.'' or ``..''.
+.TP 15
+[ENOTEMPTY]
+.I To
+is a directory and is not empty.
+.SH "SEE ALSO"
+.BR open (2)
Index: /trunk/minix/man/man2/rmdir.2
===================================================================
--- /trunk/minix/man/man2/rmdir.2	(revision 9)
+++ /trunk/minix/man/man2/rmdir.2	(revision 9)
@@ -0,0 +1,77 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)rmdir.2	6.3 (Berkeley) 8/26/85
+.\"
+.TH RMDIR 2 "August 26, 1985"
+.UC 5
+.SH NAME
+rmdir \- remove a directory file
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+int rmdir(const char *\fIpath\fP)
+.fi
+.ft R
+.SH DESCRIPTION
+.B Rmdir
+removes a directory file
+whose name is given by
+.I path.
+The directory must not have any entries other
+than \*(lq.\*(rq and \*(lq..\*(rq.
+.SH "RETURN VALUE
+A 0 is returned if the remove succeeds; otherwise a \-1 is
+returned and an error code is stored in the global location \fIerrno\fP\|.
+.SH ERRORS
+The named file is removed unless one or more of the
+following are true:
+.TP 15
+[ENOTDIR]
+A component of the path is not a directory.
+.TP 15
+[ENAMETOOLONG]
+The path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+The named directory does not exist.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating the pathname.
+(Minix-vmd)
+.TP 15
+[ENOTEMPTY]
+The named directory contains files other than ``.'' and ``..'' in it.
+.TP 15
+[EACCES]
+Search permission is denied for a component of the path prefix.
+.TP 15
+[EACCES]
+Write permission is denied on the directory containing the link
+to be removed.
+.TP 15
+[EPERM]
+The directory containing the directory to be removed is marked sticky,
+and neither the containing directory nor the directory to be removed
+are owned by the effective user ID.
+.TP 15
+[EBUSY]
+The directory to be removed is the mount point
+for a mounted file system.
+.TP 15
+[EIO]
+An I/O error occurred while deleting the directory entry
+or deallocating the inode.
+.TP 15
+[EROFS]
+The directory entry to be removed resides on a read-only file system.
+.TP 15
+[EFAULT]
+.I Path
+points outside the process's allocated address space.
+.SH "SEE ALSO"
+.BR mkdir (2),
+.BR unlink (2).
Index: /trunk/minix/man/man2/select.2
===================================================================
--- /trunk/minix/man/man2/select.2	(revision 9)
+++ /trunk/minix/man/man2/select.2	(revision 9)
@@ -0,0 +1,43 @@
+.TH SELECT 2 "Jun 9, 2005"
+.UC 4
+.SH NAME
+select, FD_CLR, FD_ISSET, FD_SET, FD_ZERO \- synchronous I/O multiplexing
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/select.h>
+
+int select(int \fInfds\fP, fd_set *\fIreadfds\fP, fd_set *\fIwritefds\fP, fd_set *\fIerrorfds\fP, struct timeval *\fItimeout\fP)
+
+void FD_CLR(int \fIfd\fP, fd_set *\fIfdset\fP)
+int FD_ISSET(int \fIfd\fP, fd_set *\fIfdset\fP)
+void FD_SET(int \fIfd\fP, fd_set *\fIfdset\fP)
+void FD_ZERO(fd_set *\fIfdset\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Select
+examines the file descriptors given in the sets 
+.IR readfds ,
+.IR writefds ,
+and
+.IR errorfds ,
+up to and including file descriptor
+.IR nfds -1
+, for reading, writing, or exceptional conditions, respectively.
+.B Select
+currently supports regular files, pipes, named pipes,
+inet, and tty file descriptors (including pty).
+
+If the 
+.I readfds 
+argument is not a null pointer, it points to an object of type fd_set
+that on input specifies the file descriptors to be checked for being
+ready to read, and on output indicates which file descriptors are ready
+to read.
+.I Writefds 
+and
+.I errorfds
+have an analogous meaning for file descriptors to be checked for being
+ready to read, respectively have pending exceptional (error) conditions.
+
Index: /trunk/minix/man/man2/setsid.2
===================================================================
--- /trunk/minix/man/man2/setsid.2	(revision 9)
+++ /trunk/minix/man/man2/setsid.2	(revision 9)
@@ -0,0 +1,40 @@
+.TH SETSID 2
+.SH NAME
+setsid, getpgrp \- create process group, get process group id
+.SH SYNOPSIS
+.ft B
+.nf
+#include <sys/types.h>
+#include <unistd.h>
+
+pid_t setsid(void)
+pid_t getpgrp(void)
+.fi
+.ft P
+.SH DESCRIPTION
+.B Setsid()
+creates a new session if the calling process is not already a session
+leader.  The calling process becomes the session leader of a new process
+group and the process group ID of this new process group will be equal to
+the process ID of the new session leader.  The process group ID is inherited
+on a
+.BR fork (2).
+.PP
+.B Getpgrp()
+returns the process group ID of the calling process.
+.SH "SEE ALSO"
+.BR kill (2),
+.BR termios (3),
+.BR tty (4).
+.SH DIAGNOSTICS
+.B Setsid()
+returns the new process group ID on success, or \-1 with
+.B errno
+set to
+.B EPERM
+if the process is already a session leader.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+
+.\"
+.\" $PchId: setsid.2,v 1.2 1996/04/11 06:06:36 philip Exp $
Index: /trunk/minix/man/man2/setuid.2
===================================================================
--- /trunk/minix/man/man2/setuid.2	(revision 9)
+++ /trunk/minix/man/man2/setuid.2	(revision 9)
@@ -0,0 +1,52 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)setreuid.2	6.1 (Berkeley) 5/9/85
+.\"
+.TH SETUID 2 "May 9, 1985"
+.UC 4
+.SH NAME
+setuid, seteuid, setgid, setegid \- set (effective) user or group ID's
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+
+int setuid(uid_t \fIuid\fP)
+int seteuid(uid_t \fIeuid\fP)
+int setgid(gid_t \fIgid\fP)
+int setegid(gid_t \fIegid\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Setuid
+sets the real and effective user ID's of the
+current process to
+.IR uid .
+Unprivileged users may only change both user ID's
+to the real user ID; only the super-user may
+make other changes.
+.B Setgid
+does the same for the real and effective group ID's.
+.PP
+Minix-vmd
+allows an unprivileged user to change ID's to the original real or effective
+ID as they were at the time the process was executed.
+.B Setgid
+may also set the group ID's to any of the additional group ID's.
+If one of the
+remembered user ID's was 0 then any user or group ID may be chosen.
+.SH "RETURN VALUE
+Upon successful completion, a value of 0 is returned.  Otherwise,
+a value of \-1 is returned and \fBerrno\fP is set to indicate the error.
+.SH "ERRORS
+.TP 15
+[EPERM]
+The current process is not the super-user and a change
+other than one of the allowed changes was attempted.
+.SH "SEE ALSO"
+.BR getuid (2),
+.BR geteuid (2),
+.BR getgid (2).
+.BR getegid (2).
Index: /trunk/minix/man/man2/sigaction.2
===================================================================
--- /trunk/minix/man/man2/sigaction.2	(revision 9)
+++ /trunk/minix/man/man2/sigaction.2	(revision 9)
@@ -0,0 +1,244 @@
+.TH SIGACTION 2
+.SH NAME
+sigaction, signal \- manage signal state and handlers
+.SH SYNOPSIS
+.ft B
+#include <signal.h>
+
+.in +5
+.ti -5
+int sigaction(int \fIsig\fP, const struct sigaction *\fIact\fP, struct sigaction *\fIoact\fP)
+.in -5
+.br
+void (*signal(int \fIsig\fP, void (*\fIhandler\fP)(int)))(int);
+.ft P
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Sigaction()
+is used to examine, set, or modify the attributes of a signal.  The argument
+.I sig
+is the signal in question.  The
+.I act
+argument points to a structure containing the new attributes of the signal,
+the structure pointed to by
+.I oact
+will receive the old attributes that were in effect before the call.
+.PP
+The
+.I act
+and
+.I oact
+arguments may be
+.B NULL
+to indicate that either no new attributes are to be set, or that the old
+attributes are not of interest.
+.PP
+The structure containing the signal attributes is defined in <signal.h> and
+looks like this:
+.PP
+.RS
+.nf
+.ft B
+.ta +4n +12n
+struct sigaction {
+	void	(*sa_handler)(int sig);
+	sigset_t	sa_mask;
+	int	sa_flags;
+};
+.ft R
+.fi
+.RE
+.PP
+The
+.B sa_handler
+field contains the address of a signal handler, a function that is called
+when the process is signalled, or one of these special constants:
+.PP
+.TP 12
+.B SIG_DFL
+Default signal handling is to be performed.  This usually means that the
+process is killed, but some signals may be ignored by default.
+.TP
+.B SIG_IGN
+Ignore the signal.
+.PP
+The
+.B sa_mask
+field indicates a set of signals that must be blocked when the signal is
+being handled.  Whether the signal
+.I sig
+itself is blocked when being handled is not controlled by this mask.  The
+mask is of a "signal set" type that is to be manipulated by the
+.BR sigset (3)
+functions.
+.PP
+How the signal is handled precisely is specified by bits in
+.BR sa_flags .
+If none of the flags is set then the handler is called when the signal
+arrives.  The signal is blocked during the call to the handler, and
+unblocked when the handler returns.  A system call that is interrupted
+returns
+.B \-1
+with
+.B errno
+set to
+.BR EINTR .
+The following bit flags can be set to modify this behaviour:
+.PP
+.TP 15
+.B SA_RESETHAND
+Reset the signal handler to
+.B SIG_DFL
+when the signal is caught.
+.TP
+.B SA_NODEFER
+Do not block the signal on entry to the handler.
+.TP
+.B SA_COMPAT
+Handle the signal in a way that is compatible with the the old
+.B signal()
+call.
+.PP
+The old
+.B signal()
+signal system call sets a signal handler for a given signal and returns the
+old signal handler.  No signals are blocked, the flags are
+.BR "SA_RESETHAND | SA_NODEFER | SA_COMPAT" .
+New code should not use
+.BR signal() .
+Note that
+.B signal()
+and all of the
+.B SA_*
+flags are MINIX 3 extensions.
+.PP
+Signal handlers are reset to
+.B SIG_DFL
+on an
+.BR execve (2).
+Signals that are ignored stay ignored.
+.SS Signals
+MINIX 3 knows about the following signals:
+.PP
+.nf
+.ta +11n +7n +8n
+signal	num	notes	description
+.SP
+SIGHUP	1	k	Hangup
+SIGINT	2	k	Interrupt (usually DEL or CTRL\-C)
+SIGQUIT	3	kc	Quit (usually CTRL\-\e)
+SIGILL	4	kc	Illegal instruction
+SIGTRAP	5	xkc	Trace trap
+SIGABRT	6	kc	Abort program
+SIGFPE	8	k	Floating point exception
+SIGKILL	9	k	Kill
+SIGUSR1	10	k	User defined signal #1
+SIGSEGV	11	kc	Segmentation fault
+SIGUSR2	12	k	User defined signal #2
+SIGPIPE	13	k	Write to a pipe with no reader
+SIGALRM	14	k	Alarm clock
+SIGTERM	15	k	Terminate (default for kill(1))
+SIGCHLD	17	pvi	Child process terminated
+SIGCONT	18	p	Continue if stopped
+SIGSTOP	19	ps	Stop signal
+SIGTSTP	20	ps	Interactive stop signal
+SIGTTIN	21	ps	Background read
+SIGTTOU	22	ps	Background write
+SIGWINCH	23	xvi	Window size change
+.ft R
+.fi
+.PP
+The letters in the notes column indicate:
+.PP
+.TP 5
+.B k
+The process is killed if the signal is not caught.
+.TP
+.B c
+The signal causes a core dump.
+.TP
+.B i
+The signal is ignored if not caught.
+.TP
+.B v
+Only Minix-vmd implements this signal.
+.TP
+.B x
+MINIX 3 extension, not defined by \s-2POSIX\s+2.
+.TP
+.B p
+These signals are not implemented, but \s-2POSIX\s+2 requires that they are
+defined.
+.TP
+.B s
+The process should be stopped, but is killed instead.
+.PP
+The
+.B SIGKILL
+signal cannot be caught or ignored.  The
+.B SIGILL
+and
+.B SIGTRAP
+signals cannot be automatically reset.  The system silently enforces these
+restrictions.  This may or may not be reflected by the attributes of these
+signals and the signal masks.
+.SS Types
+\s-2POSIX\s+2 prescribes that <sys/types.h> has the following definition:
+.PP
+.RS
+.B "typedef int (*sighandler_t)(int)"
+.RE
+.PP
+With this type the following declarations can be made:
+.PP
+.RS
+.ft B
+.nf
+sighandler_t sa_handler;
+sighandler_t signal(int \fIsig\fP, sighandler_t \fIhandler\fP);
+.fi
+.ft R
+.RE
+.PP
+This may help you to understand the earlier declarations better.  The
+.B sighandler_t
+type is also very useful in old style C code that is compiled by a compiler
+for standard C.
+.SH "SEE ALSO"
+.BR kill (1),
+.BR kill (2),
+.BR pause (2),
+.BR sigprocmask (2),
+.BR sigsuspend (2),
+.BR sigpending (2),
+.BR sigset (3).
+.SH DIAGNOSTICS
+.B Sigaction()
+returns
+.B 0
+on success or
+.B \-1
+on error.
+.B Signal()
+returns the old handler on success or
+.B SIG_ERR
+on error.  The error code may be:
+.PP
+.TP 10
+.B EINVAL
+Bad signal number.
+.TP
+.B EFAULT
+Bad
+.I act
+or
+.I oact
+addresses.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+
+.\"
+.\" $PchId: sigaction.2,v 1.2 1996/04/11 06:00:28 philip Exp $
Index: /trunk/minix/man/man2/sigpending.2
===================================================================
--- /trunk/minix/man/man2/sigpending.2	(revision 9)
+++ /trunk/minix/man/man2/sigpending.2	(revision 9)
@@ -0,0 +1,33 @@
+.TH SIGPENDING 2
+.SH NAME
+sigpending \- report pending signals
+.SH SYNOPSIS
+.ft B
+#include <signal.h>
+
+int sigpending(sigset_t *\fIset\fP)
+.ft P
+.SH DESCRIPTION
+.B Sigpending()
+returns the set of signals that are waiting to be delivered.  They are
+currently blocked by the signal mask.
+.SH "SEE ALSO"
+.BR sigaction (2),
+.BR sigprocmask (2),
+.BR sigsuspend (2),
+.BR sigset (3).
+.SH DIAGNOSTICS
+Returns
+.B 0
+on success and
+.B \-1
+on error.  The only possible error code is
+.B EFAULT
+for a bad
+.I set
+address.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+
+.\"
+.\" $PchId: sigpending.2,v 1.2 1996/04/11 06:01:22 philip Exp $
Index: /trunk/minix/man/man2/sigprocmask.2
===================================================================
--- /trunk/minix/man/man2/sigprocmask.2	(revision 9)
+++ /trunk/minix/man/man2/sigprocmask.2	(revision 9)
@@ -0,0 +1,75 @@
+.TH SIGPROCMASK 2
+.SH NAME
+sigprocmask \- manipulate the signal mask
+.SH SYNOPSIS
+.ft B
+#include <signal.h>
+
+int sigprocmask(int \fIhow\fP, const sigset_t *\fIset\fP, sigset_t *\fIoset\fP)
+.ft P
+.SH DESCRIPTION
+.B Sigprocmask()
+examines or manipulates the signal mask.  This mask is the set of signals
+that are currently blocked.  The
+.I how
+argument determines the action that must be performed.  In all cases the
+signal set referenced by
+.IR oset ,
+if not
+.BR NULL ,
+will be used to receive the old signal mask.  The
+.I set
+argument, if not
+.BR NULL ,
+will be used to set or modify the current signal mask.
+.PP
+.I How
+can be one of:
+.PP
+.TP 15
+.B SIG_BLOCK
+Add the signals referenced by
+.I set
+to the mask.
+.TP
+.B SIG_UNBLOCK
+Remove the signals referenced by
+.I set
+from the mask.
+.TP
+.B SIG_SETMASK
+Set the signal mask to the set referenced by
+.IR set .
+.PP
+The value of
+.I how
+is ignored if
+.I set
+is
+.BR NULL .
+.SH "SEE ALSO"
+.BR sigaction (2),
+.BR sigpending (2),
+.BR sigsuspend (2),
+.BR sigset (3).
+.SH DIAGNOSTICS
+Returns
+.B 0
+on success and
+.B \-1
+on error.  The error code is
+.B EFAULT
+for a bad
+.I set
+or
+.I oset
+address, or
+.B EINVAL
+for a bad
+.I how
+argument.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+
+.\"
+.\" $PchId: sigprocmask.2,v 1.2 1996/04/11 06:02:09 philip Exp $
Index: /trunk/minix/man/man2/sigsuspend.2
===================================================================
--- /trunk/minix/man/man2/sigsuspend.2	(revision 9)
+++ /trunk/minix/man/man2/sigsuspend.2	(revision 9)
@@ -0,0 +1,39 @@
+.TH SIGSUSPEND 2
+.SH NAME
+sigsuspend \- suspend until signalled
+.SH SYNOPSIS
+.ft B
+#include <signal.h>
+
+int sigsuspend(const sigset_t *\fIset\fP)
+.ft P
+.SH DESCRIPTION
+.B Sigsuspend()
+installs the signal mask referenced by
+.I set
+and suspends the process until signalled.  The signal is handled, the signal
+mask is restored to the value it had before the
+.B sigsuspend()
+call and call returns.
+.SH "SEE ALSO"
+.BR pause (2),
+.BR sigaction (2),
+.BR sigpending (2),
+.BR sigprocmask (2),
+.BR sigset (3).
+.SH DIAGNOSTICS
+.B Sigsuspend()
+never returns normally, so it always returns
+.BR \-1 .
+The error code is either
+.B EINTR
+indicating that a signal has arrived, or
+.B EFAULT
+for a bad
+.I set
+address.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+
+.\"
+.\" $PchId: sigsuspend.2,v 1.2 1996/04/11 06:02:41 philip Exp $
Index: /trunk/minix/man/man2/stat.2
===================================================================
--- /trunk/minix/man/man2/stat.2	(revision 9)
+++ /trunk/minix/man/man2/stat.2	(revision 9)
@@ -0,0 +1,179 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)stat.2	6.5 (Berkeley) 5/12/86
+.\"
+.TH STAT 2 "May 12, 1986"
+.UC 4
+.SH NAME
+stat, lstat, fstat \- get file status
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <sys/stat.h>
+
+.ta +54n
+int stat(const char *\fIpath\fP, struct stat *\fIbuf\fP)
+int lstat(const char *\fIpath\fP, struct stat *\fIbuf\fP)	
+int fstat(int \fIfd\fP, struct stat *\fIbuf\fP)
+.fi
+.ft R
+.SH DESCRIPTION
+.B Stat
+obtains information about the file
+.IR path .
+Read, write or execute
+permission of the named file is not required, but all directories
+listed in the path name leading to the file must be reachable.
+.PP
+.B Lstat
+is like \fBstat\fP except in the case where the named file is a symbolic link,
+in which case
+.B lstat
+returns information about the link,
+while
+.B stat
+returns information about the file the link references.
+.PP
+.B Fstat
+obtains the same information about an open file
+referenced by the argument descriptor, such as would
+be obtained by an \fBopen\fP call.  Pipe descriptors
+look like named pipes with a link count of zero.  The
+st_size field of pipes or named pipes shows the amount of
+bytes currently buffered in the pipe.
+.PP
+.I Buf
+is a pointer to a
+.B stat
+structure into which information is placed concerning the file.
+The contents of the structure pointed to by
+.I buf
+is as follows:
+.PP
+.if t .RS
+.nf
+.ta +0.4i +0.8i +1i
+struct stat {
+	dev_t	st_dev;	/* device inode resides on */
+	ino_t	st_ino;	/* this inode's number */
+	mode_t	st_mode;	/* file mode, protection bits, etc. */
+	nlink_t	st_nlink;	/* number or hard links to the file */
+	uid_t	st_uid;	/* user-id of the file's owner */
+	gid_t	st_gid;	/* group-id of the file's owner */
+	dev_t	st_rdev;	/* the device type, for inode that is device */
+	off_t	st_size;	/* total size of file */
+	time_t	st_atime;	/* time of last access */
+	time_t	st_mtime;	/* time of last data modification */
+	time_t	st_ctime;	/* time of last file status change */
+};
+.fi
+.if t .RE
+.DT
+.PP
+.TP 12
+st_atime
+Time when file data was last read or modified.  Changed by the following system
+calls:
+.BR mknod (2),
+.BR utime (2),
+.BR read (2),
+and
+.BR write (2).
+For reasons of efficiency, 
+st_atime is not set when a directory
+is searched, although this would be more logical.
+.TP 12
+st_mtime
+Time when data was last modified.
+It is not set by changes of owner, group, link count, or mode.
+Changed by the following system calls:
+.BR mknod (2),
+.BR utime (2),
+.BR write (2).
+.TP 12
+st_ctime
+Time when file status was last changed.
+It is set both both by writing and changing the i-node.
+Changed by the following system calls:
+.BR chmod (2)
+.BR chown (2),
+.BR link (2),
+.BR mknod (2),
+.BR rename (2),
+.BR unlink (2),
+.BR utime (2),
+.BR write (2).
+.PP
+The file type information in \fBst_mode\fP has bits:
+.PP
+.nf
+.in +5n
+.ta 1.6i 2.5i 3i
+#define S_IFMT	0170000	/* type of file */
+#define\ \ \ \ S_IFIFO	0010000	/* named pipe */
+#define\ \ \ \ S_IFCHR	0020000	/* character special */
+#define\ \ \ \ S_IFDIR	0040000	/* directory */
+#define\ \ \ \ S_IFBLK	0060000	/* block special */
+#define\ \ \ \ S_IFREG	0100000	/* regular */
+#define\ \ \ \ S_IFLNK	0120000	/* symbolic link */
+.fi
+.in -5n
+.PP
+The mode bits 0007777 encode set-uid/gid bits and
+permission bits (see
+.BR chmod (2)).
+.SH "RETURN VALUE
+Upon successful completion a value of 0 is returned.
+Otherwise, a value of \-1 is returned and
+.B errno
+is set to indicate the error.
+.SH "ERRORS
+.B Stat
+and
+.B lstat
+will fail if one or more of the following are true:
+.TP 15
+[ENOTDIR]
+A component of the path prefix is not a directory.
+.TP 15
+[ENAMETOOLONG]
+The path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+The named file does not exist.
+.TP 15
+[EACCES]
+Search permission is denied for a component of the path prefix.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating the pathname.
+.TP 15
+[EFAULT]
+.I Buf
+or
+.I name
+points to an invalid address.
+.TP 15
+[EIO]
+An I/O error occurred while reading from or writing to the file system.
+.PP
+.B Fstat
+will fail if one or both of the following are true:
+.TP 15
+[EBADF]
+.I Fildes
+is not a valid open file descriptor.
+.TP 15
+[EFAULT]
+.I Buf
+points to an invalid address.
+.TP 15
+[EIO]
+An I/O error occurred while reading from or writing to the file system.
+.SH "SEE ALSO"
+.BR chmod (2),
+.BR chown (2),
+.BR utime (2).
Index: /trunk/minix/man/man2/svrctl.2
===================================================================
--- /trunk/minix/man/man2/svrctl.2	(revision 9)
+++ /trunk/minix/man/man2/svrctl.2	(revision 9)
@@ -0,0 +1,59 @@
+.\" svrctl.2
+.\"
+.\" Created: July, 1994 by Philip Homburg <philip@cs.vu.nl>
+.TH svrctl 2
+.SH NAME
+svrctl \- special server control functions
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/svrctl.h>
+
+int svrctl(u32_t \fIrequest\fP, void *\fIdata\fP);
+.ft R
+.fi
+.SH DESCRIPTION
+.B Svrctl
+allows root to control the kernel in various ways, or implements some very
+MINIX 3 specific system calls that don't deserve their own system call number.
+.PP
+This system call makes it easy to add new ways of setting and getting kernel
+parameters, but at the same time, backwards compatibility is not guaranteed.
+Read the <sys/svrctl.h> include file to see what the struct's mentioned below
+look like.  Most calls are root-only, unless specified otherwise.
+.PP
+The only way to know how to properly use these calls is to study the
+associated kernel or server code, or the programs that already use these
+calls.
+.PP
+Current requests are:
+.TP 5
+.B MMSIGNON
+Inform MM that the current process wants to become a server.
+.TP
+.B MMSWAPON
+Instruct MM to mount a file or device as swapspace.
+.TP
+.B MMSWAPOFF
+Tell MM to stop using swapspace.
+.TP
+.B FSSIGNON
+Register a new device with FS.
+.ig
+.TP
+.B FSDEVMAP
+Translate a device number to a task number, minor device pair using a
+\fBstruct fsdevmap\fP
+..
+.TP
+.B SYSSIGNON
+Inform the kernel that the process want to become a server.
+The processes task number is filled-in in a \fBstruct systaskinfo\fP.
+.TP
+.B SYSGETENV
+Request the value of one or all boot parameters.  Can be used by non-root.
+.SH "RETURN VALUES"
+.B Svrctl
+returns 0 upon success and -1 upon failure.
+.SH AUTHOR
+Philip Homburg <philip@cs.vu.nl>
Index: /trunk/minix/man/man2/symlink.2
===================================================================
--- /trunk/minix/man/man2/symlink.2	(revision 9)
+++ /trunk/minix/man/man2/symlink.2	(revision 9)
@@ -0,0 +1,77 @@
+.TH SYMLINK 2 "March 17, 2006"
+.UC 4
+.SH NAME
+symlink \- make a symbolic link to a file
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+int symlink(const char *\fIname1\fP, const char *\fIname2\fP)
+.fi
+.ft R
+.SH DESCRIPTION
+A symbolic link
+.I name2
+is created.
+The link has the name
+.IR name1 .
+.SH "RETURN VALUE
+Upon successful completion, a value of 0 is returned.  Otherwise,
+a value of \-1 is returned and
+.B errno
+is set to indicate the error.
+.SH "ERRORS
+.B Symlink
+will fail and no link will be created if one or more of the following
+are true:
+.TP 15
+[ENOTDIR]
+A component of either path prefix is not a directory.
+.TP 15
+[ENAMETOOLONG]
+A path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+A component of either path prefix does not exist.
+.TP 15
+[EACCES]
+A component of either path prefix denies search permission.
+.TP 15
+[EACCES]
+The requested link requires writing in a directory with a mode
+that denies write permission.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating one of the pathnames.
+.TP 15
+[EEXIST]
+The link named by \fIname2\fP exists.
+.TP 15
+[ENOSPC]
+The directory in which the entry for the new link is being placed
+cannot be extended because there is no space left on the file
+system containing the directory.
+.ig
+.TP 15
+[EDQUOT]
+The directory in which the entry for the new link
+is being placed cannot be extended because the
+user's quota of disk blocks on the file system
+containing the directory has been exhausted.
+..
+.TP 15
+[EIO]
+An I/O error occurred while reading from or writing to 
+the file system to make the directory entry.
+.TP 15
+[EROFS]
+The requested link requires writing in a directory on a read-only file
+system.
+.TP 15
+[EFAULT]
+One of the pathnames specified
+is outside the process's allocated address space.
+.SH "SEE ALSO"
+.BR link (2),
+.BR unlink (2).
Index: /trunk/minix/man/man2/sync.2
===================================================================
--- /trunk/minix/man/man2/sync.2	(revision 9)
+++ /trunk/minix/man/man2/sync.2	(revision 9)
@@ -0,0 +1,32 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)sync.2	6.2 (Berkeley) 6/30/85
+.\"
+.TH SYNC 2 "June 30, 1985"
+.UC 4
+.SH NAME
+sync, fsync \- update dirty buffers and super-block
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+int sync(void)
+int fsync(fd)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Sync
+causes all information in the file system
+buffers that should be on disk to be written out.
+This includes modified super blocks,
+modified i-nodes, and delayed block I/O.
+.B
+Fsync
+does the same thing, but only for the blocks associated with a specific
+file descriptor. Under minix, currently the two calls do the same thing.
+.SH "SEE ALSO"
+.BR reboot (2),
+.BR sync (8).
Index: /trunk/minix/man/man2/time.2
===================================================================
--- /trunk/minix/man/man2/time.2	(revision 9)
+++ /trunk/minix/man/man2/time.2	(revision 9)
@@ -0,0 +1,62 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)gettimeofday.2	6.7 (Berkeley) 5/14/86
+.\"
+.TH TIME 2 "May 14, 1986"
+.UC 4
+.SH NAME
+time, stime \- get/set date and time
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <time.h>
+
+time_t time(time_t *\fItp\fP)
+int stime(time_t *\fItp\fP)
+.fi
+.SH DESCRIPTION
+The system's notion of the current Greenwich time
+is obtained with the
+.B time
+call, and set with the
+.B stime
+call.
+The time is expressed
+in seconds since midnight (0 hour), January 1, 1970.
+The time is both returned by
+.B time
+and stored in the variable pointed to by
+.I tp
+unless
+.I tp
+is the null pointer.
+.PP
+.B Stime
+obtains the time to set from the variable pointed to by
+.IR tp .
+.PP
+Only the super-user may set the time of day.
+.SH RETURN
+A 0 return value from
+.B stime
+indicates that the call succeeded.
+.B Time
+returns the current time on success.
+A \-1 return value indicates an error occurred, and in this
+case an error code is stored into the global variable \fBerrno\fP.
+.SH "ERRORS
+The following error codes may be set in \fBerrno\fP:
+.TP 15
+[EFAULT]
+The
+.I tp
+address referenced invalid memory.
+.TP 15
+[EPERM]
+A user other than the super-user attempted to set the time.
+.SH "SEE ALSO"
+.BR date (1),
+.BR ctime (3).
Index: /trunk/minix/man/man2/times.2
===================================================================
--- /trunk/minix/man/man2/times.2	(revision 9)
+++ /trunk/minix/man/man2/times.2	(revision 9)
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)times.3c	6.1 (Berkeley) 5/9/85
+.\"
+.TH TIMES 2 "May 9, 1985"
+.UC 4
+.SH NAME
+times \- get process times
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <sys/times.h>
+#include <time.h>
+
+int times(struct tms *\fIbuffer\fP)
+.fi
+.SH DESCRIPTION
+.B Times
+returns time-accounting information
+for the current process
+and for the terminated child processes
+of the current process.
+All times are in 1/CLOCKS_PER_SEC seconds.
+.PP
+This is the structure returned by
+.BR times :
+.PP
+.RS
+.nf
+.ta +0.4i +0.8i +1.2i
+struct tms {
+	clock_t	tms_utime;	/* user time for this process */
+	clock_t	tms_stime;	/* system time for this process */
+	clock_t	tms_cutime;	/* children's user time */
+	clock_t	tms_cstime;	/* children's system time */
+};
+.fi
+.RE
+.PP
+The user time is the number of clock ticks used by a process on
+its own computations.  The system time is the number of clock ticks
+spent inside the kernel on behalf of a process.  This does not
+include time spent waiting for I/O to happen, only actual CPU
+instruction times.
+.PP
+The children times are the sum
+of the children's process times and
+their children's times.
+.SH RETURN
+.B Times
+returns 0 on success, otherwise \-1 with the error code stored into the
+global variable
+.BR errno .
+.SH ERRORS
+The following error code may be set in
+.BR errno :
+.TP 15
+[EFAULT]
+The address specified by the
+.I buffer
+parameter is not in a valid part of the process address space.
+.SH "SEE ALSO"
+.BR time (1),
+.BR wait (2),
+.BR time (2).
Index: /trunk/minix/man/man2/truncate.2
===================================================================
--- /trunk/minix/man/man2/truncate.2	(revision 9)
+++ /trunk/minix/man/man2/truncate.2	(revision 9)
@@ -0,0 +1,30 @@
+.TH TRUNCATE 2 "Feb 13, 2006"
+.UC 4
+.SH NAME
+truncate, ftruncate \- truncate a file to a specified length (may extend)
+.SH SYNOPSIS
+.ft B
+.nf
+#include <unistd.h>
+
+int truncate(char *filename, off_t length);
+int ftruncate(int fd, off_t length);
+.fi
+.ft R
+.SH DESCRIPTION
+.B Truncate
+causes the file 
+.B filename
+to be set to the length
+.B length
+causing data after that size to be lost. If the file is set to a 
+length larger than the current file size, the new region can be
+written to but reads as zeroes. There will be no disk blocks reserved
+for it. This is a hole.
+.PP
+.B Ftruncate
+does the same thing as 
+.B truncate
+but operates on a file descriptor instead of a filename.
+.SH "SEE ALSO
+.BR fcntl (2)
Index: /trunk/minix/man/man2/umask.2
===================================================================
--- /trunk/minix/man/man2/umask.2	(revision 9)
+++ /trunk/minix/man/man2/umask.2	(revision 9)
@@ -0,0 +1,38 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)umask.2	6.1 (Berkeley) 5/9/85
+.\"
+.TH UMASK 2 "May 9, 1985"
+.UC 4
+.SH NAME
+umask \- set file creation mode mask
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <sys/stat.h>
+
+mode_t umask(mode_t \fImask\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Umask
+sets the process's file mode creation mask to \fImask\fP
+and returns the previous value of the mask.  The low-order
+9 bits of \fImask\fP are used whenever a file is created,
+clearing corresponding bits in the file mode
+(see
+.BR chmod (2)).
+This clearing allows each user to restrict the default access
+to his files.
+.PP
+The value is initially 022 (write access for owner only).
+The mask is inherited by child processes.
+.SH "RETURN VALUE
+The previous value of the file mode mask is returned by the call.
+.SH SEE ALSO
+.BR chmod (2),
+.BR mknod (2),
+.BR open (2).
Index: /trunk/minix/man/man2/uname.2
===================================================================
--- /trunk/minix/man/man2/uname.2	(revision 9)
+++ /trunk/minix/man/man2/uname.2	(revision 9)
@@ -0,0 +1,35 @@
+.TH UNAME 2
+.SH NAME
+uname \- get system info
+.SH SYNOPSIS
+.ft B
+.nf
+#include <sys/utsname.h>
+
+int uname(struct utsname *name)
+.fi
+.ft P
+.SH DESCRIPTION
+.B Uname()
+fills a struct utsname with system information.  This structure is described
+in <sys/utsname.h> as follows:
+.PP
+.nf
+.ta +4n +6n +25n
+struct utsname {
+	char	sysname[15+1];		/* System name */
+	char	nodename[255+1];	/* Node/Network name */
+	char	release[11+1];		/* O.S. release */
+	char	version[7+1];		/* O.S. version */
+	char	machine[11+1];		/* Machine hardware */
+	char	arch[11+1];		/* Architecture */
+};
+.fi
+.PP
+The strings are always null terminated, and may be of a different length then
+shown here.  The first five are required by \s-2POSIX\s+2, the last is
+MINIX 3 specific.
+.SH "SEE ALSO"
+.BR uname (1).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man2/unlink.2
===================================================================
--- /trunk/minix/man/man2/unlink.2	(revision 9)
+++ /trunk/minix/man/man2/unlink.2	(revision 9)
@@ -0,0 +1,84 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)unlink.2	6.2 (Berkeley) 5/22/85
+.\"
+.TH UNLINK 2 "May 22, 1985"
+.UC 4
+.SH NAME
+unlink \- remove directory entry
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+int unlink(const char *path)
+.fi
+.ft R
+.SH DESCRIPTION
+.B Unlink
+removes the entry for the file
+.I path
+from its directory.
+If this entry was the last link to the file,
+and no process has the file open, then
+all resources associated with the file are reclaimed.
+If, however, the file was open in any process, the actual
+resource reclamation is delayed until it is closed,
+even though the directory entry has disappeared.
+.SH "RETURN VALUE
+Upon successful completion, a value of 0 is returned.
+Otherwise, a value of \-1 is returned and
+.B errno
+is set to indicate the error.
+.SH "ERRORS
+The \fIunlink\fP succeeds unless:
+.TP 15
+[ENOTDIR]
+A component of the path prefix is not a directory.
+.TP 15
+[ENAMETOOLONG]
+The path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+The named file does not exist.
+.TP 15
+[EACCES]
+Search permission is denied for a component of the path prefix.
+.TP 15
+[EACCES]
+Write permission is denied on the directory containing the link
+to be removed.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating the pathname.
+(Minix-vmd)
+.TP 15
+[EPERM]
+The named file is a directory.
+.TP 15
+[EPERM]
+The directory containing the file is marked sticky,
+and neither the containing directory nor the file to be removed
+are owned by the effective user ID.
+(Minix-vmd)
+.TP 15
+[EBUSY]
+The entry to be unlinked is the mount point for a
+mounted file system.
+.TP 15
+[EIO]
+An I/O error occurred while deleting the directory entry
+or deallocating the inode.
+.TP 15
+[EROFS]
+The named file resides on a read-only file system.
+.TP 15
+[EFAULT]
+.I Path
+points outside the process's allocated address space.
+.SH "SEE ALSO"
+.BR close (2),
+.BR link (2),
+.BR rmdir (2).
Index: /trunk/minix/man/man2/utime.2
===================================================================
--- /trunk/minix/man/man2/utime.2	(revision 9)
+++ /trunk/minix/man/man2/utime.2	(revision 9)
@@ -0,0 +1,85 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)utimes.2	6.4 (Berkeley) 8/26/85
+.\"
+.TH UTIME 2 "August 26, 1985"
+.UC 4
+.SH NAME
+utime \- set file times
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <utime.h>
+
+int utime(const char *\fIfile\fP, struct utimbuf *\fItimes\fP)
+.fi
+.SH DESCRIPTION
+The
+.B utime
+call
+uses the
+\*(lqaccessed\*(rq and \*(lqupdated\*(rq times
+from the utimbuf structure pointed to by
+.I times
+to set the corresponding recorded times for
+.I file.
+.PP
+Struct utimbuf is defined in <utime.h> as follows:
+.PP
+.RS
+.nf
+.ta +0.4i +0.8i +1.0i
+struct utimbuf {
+	time_t	actime;	/* access time */
+	time_t	modtime;	/* modification time */
+};
+.fi
+.RE
+.PP
+The caller must be the owner of the file or the super-user.
+The \*(lqinode-changed\*(rq time of the file is set to the current time.
+.SH "RETURN VALUE
+Upon successful completion, a value of 0 is returned.
+Otherwise, a value of \-1 is returned and
+.B errno
+is set to indicate the error.
+.SH "ERRORS
+.B Utime
+will fail if one or more of the following are true:
+.TP 15
+[ENOTDIR]
+A component of the path prefix is not a directory.
+.TP 15
+[EINVAL]
+The pathname contains a character with the high-order bit set.
+.TP 15
+[ENAMETOOLONG]
+The path name exceeds PATH_MAX characters.
+.TP 15
+[ENOENT]
+The named file does not exist.
+.TP 15
+[ELOOP]
+Too many symbolic links were encountered in translating the pathname.
+(Minix-vmd)
+.TP 15
+[EPERM]
+The process is not super-user and not the owner of the file.
+.TP 15
+[EACCES]
+Search permission is denied for a component of the path prefix.
+.TP 15
+[EROFS]
+The file system containing the file is mounted read-only.
+.TP 15
+[EFAULT]
+.I File
+or \fItimes\fP points outside the process's allocated address space.
+.TP 15
+[EIO]
+An I/O error occurred while reading or writing the affected inode.
+.SH SEE ALSO
+.BR stat (2).
Index: /trunk/minix/man/man2/wait.2
===================================================================
--- /trunk/minix/man/man2/wait.2	(revision 9)
+++ /trunk/minix/man/man2/wait.2	(revision 9)
@@ -0,0 +1,162 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)wait.2	6.2 (Berkeley) 6/30/85
+.\"
+.TH WAIT 2 "June 30, 1985"
+.UC 4
+.SH NAME
+wait, waitpid \- wait for process to terminate
+.SH SYNOPSIS
+.ft B
+.nf
+#include <sys/types.h>
+#include <sys/wait.h>
+
+pid_t wait(int *\fIstatus\fP)
+pid_t waitpid(pid_t \fIpid\fP, int *\fIstatus\fP, int \fIoptions\fP)
+.fi
+.SH DESCRIPTION
+.B Wait
+causes its caller to delay until a signal is received or
+one of its child
+processes terminates.
+If any child has died since the last
+.BR wait ,
+return is immediate, returning the process id and
+exit status of one of the terminated
+children.
+If there are no children, return is immediate with
+the value \-1 returned.
+.PP
+On return from a successful 
+.B wait
+call, 
+.I status
+is nonzero, and the high byte of 
+.I status
+contains the low byte of the argument to
+.B exit
+supplied by the child process;
+the low byte of 
+.I status
+contains the termination status of the process.
+A more precise definition of the
+.I status
+word is given in
+.RI < sys/wait.h >.
+.B Wait
+can be called with a null pointer argument to indicate that no status need
+be returned.
+.PP
+.B Waitpid
+provides an alternate interface for programs
+that must not block when collecting the status
+of child processes, or that wish to wait for
+one particular child.  The pid parameter is
+the process ID of the child to wait for, \-1
+for any child.  The
+.I status
+parameter is defined as above.  The
+.I options
+parameter is used to indicate the call should not block if
+there are no processes that wish to report status (WNOHANG),
+and/or that children of the current process that are stopped
+due to a SIGTTIN, SIGTTOU, SIGTSTP, or SIGSTOP signal should also have
+their status reported (WUNTRACED).  (Job control is not implemented for
+MINIX 3, but these symbols and signals are.)
+.PP
+When the WNOHANG option is specified and no processes
+wish to report status, 
+.B waitpid
+either returns 0 under some implementations, or \-1 with
+.B errno
+set to
+.B EAGAIN
+under others.
+(Under MINIX 3 it returns 0.)
+The WNOHANG and WUNTRACED options may be combined by 
+.IR or 'ing
+the two values.
+.SH NOTES
+The call
+.BI "wait(&" status ")"
+is equivalent to
+.BI "waitpid(\-1, &" status ", 0)\fR."
+.PP
+See
+.BR sigaction (2)
+for a list of termination statuses (signals);
+0 status indicates normal termination.
+A special status (0177) is returned for a stopped process
+that has not terminated and can be restarted;
+see
+.BR ptrace (2).
+If the 0200 bit of the termination status
+is set,
+a core image of the process was produced
+by the system.
+.PP
+If the parent process terminates without
+waiting on its children,
+the initialization process
+(process ID = 1)
+inherits the children.
+.PP
+.I <sys/wait.h>
+defines a number of macros that operate on a status word:
+.TP 5
+.BI "WIFEXITED(" status ")"
+True if normal exit.
+.TP 5
+.BI "WEXITSTATUS(" status ")"
+Exit status if the process returned by a normal exit, zero otherwise.
+.TP 5
+.BI "WTERMSIG(" status ")"
+Signal number if the process died by a signal, zero otherwise.
+.TP 5
+.BI "WIFSIGNALED(" status ")"
+True if the process died by a signal.
+.TP 5
+.BI "WIFSTOPPED(" status ")"
+True if the process is stopped.  (Never true under MINIX 3.)
+.TP 5
+.BI "WSTOPSIG(" status ")"
+Signal number of the signal that stopped the process.
+.SH "RETURN VALUE
+If \fBwait\fP returns due to a stopped
+or terminated child process, the process ID of the child
+is returned to the calling process.  Otherwise, a value of \-1
+is returned and \fBerrno\fP is set to indicate the error.
+.PP
+.B Waitpid
+returns \-1 if there are no children not previously waited for or if
+the process that it wants to wait for doesn't exist.
+.PP
+.B Waitpid
+returns 0 if WNOHANG is specified and there are no stopped or exited
+children.  (Under other implementations it may return \-1 instead.  Portable
+code should test for both possibilities.)
+.SH ERRORS
+.B Wait
+will fail and return immediately if one or more of the following
+are true:
+.TP 15
+[ECHILD]
+The calling process has no existing unwaited-for
+child processes.
+.TP 15
+[EFAULT]
+The \fIstatus\fP argument points to an illegal address.
+.TP 15
+[EAGAIN]
+.B Waitpid
+is called with the WNOHANG option and no child has exited yet.  (Not under
+MINIX 3, it'll return 0 in this case and leave
+.B errno
+alone.)
+.SH "SEE ALSO"
+.BR execve (2),
+.BR exit (2),
+.BR sigaction (2).
Index: /trunk/minix/man/man2/write.2
===================================================================
--- /trunk/minix/man/man2/write.2	(revision 9)
+++ /trunk/minix/man/man2/write.2	(revision 9)
@@ -0,0 +1,97 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)write.2	6.5 (Berkeley) 5/14/86
+.\"
+.TH WRITE 2 "May 14, 1986"
+.UC 4
+.SH NAME
+write \- write output
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <unistd.h>
+
+ssize_t write(int \fId\fP, const void *\fIbuf\fP, size_t \fInbytes\fP)
+.fi
+.SH DESCRIPTION
+.B Write
+attempts to write
+.I nbytes
+of data to the object referenced by the descriptor
+.I d
+from the buffer pointed to by
+.IR buf .
+.PP
+On objects capable of seeking, the \fBwrite\fP starts at a position
+given by the pointer associated with
+.IR d ,
+see
+.BR lseek (2).
+Upon return from
+.BR write ,
+the pointer is incremented by the number of bytes actually written.
+.PP
+Objects that are not capable of seeking always write from the current
+position.  The value of the pointer associated with such an object
+is undefined.
+.PP
+When using non-blocking I/O on objects such as TCP/IP channels that are
+subject to flow control,
+.B write
+may write fewer bytes than requested;
+the return value must be noted,
+and the remainder of the operation should be retried when possible.
+.SH "RETURN VALUE
+Upon successful completion the number of bytes actually written
+is returned.  Otherwise a \-1 is returned and the global variable
+.B errno
+is set to indicate the error.
+.SH ERRORS
+.B Write
+will fail and the file pointer will remain unchanged if one or more
+of the following are true:
+.TP 15
+[EBADF]
+\fID\fP is not a valid descriptor open for writing.
+.TP 15
+[EPIPE]
+An attempt is made to write to a pipe that is not open
+for reading by any process.
+.TP 15
+[EPIPE]
+An attempt is made to write to a TCP channel
+that is not connected to a peer socket.
+.TP 15
+[EFBIG]
+An attempt was made to write a file that exceeds the process's
+file size limit or the maximum file size.
+.TP 15
+[EFAULT]
+Part of the data to be written to the file
+points outside the process's allocated address space.
+.TP 15
+[ENOSPC]
+There is no free space remaining on the file system
+containing the file.
+.ig
+.TP 15
+[EDQUOT]
+The user's quota of disk blocks on the file system
+containing the file has been exhausted.
+..
+.TP 15
+[EIO]
+An I/O error occurred while reading from or writing to the file system.
+.TP 15
+[EAGAIN]
+The file was marked for non-blocking I/O,
+and no data could be written immediately.
+.SH "SEE ALSO"
+.BR fcntl (2),
+.BR lseek (2),
+.BR open (2),
+.BR pipe (2),
+.BR read (2).
Index: /trunk/minix/man/man3/abort.3
===================================================================
--- /trunk/minix/man/man3/abort.3	(revision 9)
+++ /trunk/minix/man/man3/abort.3	(revision 9)
@@ -0,0 +1,27 @@
+.\"	@(#)abort.3	6.3 (Berkeley) 5/27/86
+.\"
+.TH ABORT 3 "May 27, 1986"
+.AT 3
+.SH NAME
+abort \- generate a fault
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdlib.h>
+
+void abort(void)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Abort
+executes an instruction which is illegal in user mode.
+This causes a signal that normally terminates
+the process with a core dump, which may be used for debugging.
+.SH SEE ALSO
+.BR sigaction (2),
+.BR exit (2).
+.SH DIAGNOSTICS
+Usually ``abort \- core dumped'' from the shell.
+.SH BUGS
+The abort() function does not flush standard I/O buffers.  Use
+.BR fflush (3).
Index: /trunk/minix/man/man3/abs.3
===================================================================
--- /trunk/minix/man/man3/abs.3	(revision 9)
+++ /trunk/minix/man/man3/abs.3	(revision 9)
@@ -0,0 +1,24 @@
+.\"	@(#)abs.3	6.1 (Berkeley) 5/15/85
+.\"
+.TH ABS 3 "May 15, 1985"
+.AT 3
+.SH NAME
+abs \- integer absolute value
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdlib.h>
+
+int abs(int \fIi\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Abs
+returns the absolute value of its integer operand.
+.SH SEE ALSO
+.BR floor (3).
+.SH BUGS
+Applying the \fIabs\fP function to the most negative integer generates a
+result which is the most negative integer.  That is, abs(0x80000000)
+returns 0x80000000 as a result on a machine with 32-bit ints.  Using the
+result in unsigned computations is sound however.
Index: /trunk/minix/man/man3/assert.3
===================================================================
--- /trunk/minix/man/man3/assert.3	(revision 9)
+++ /trunk/minix/man/man3/assert.3	(revision 9)
@@ -0,0 +1,42 @@
+.\"	@(#)assert.3	6.2 (Berkeley) 5/12/86
+.\"
+.TH ASSERT 3 "May 12, 1986"
+.AT 3
+.SH NAME
+assert \- program verification
+.SH SYNOPSIS
+.nf
+.ft B
+#include <assert.h>
+
+void assert(int \fIexpression\fP)
+.fi
+.SH DESCRIPTION
+.B Assert
+is a macro that indicates
+.I expression
+is expected to be true at this point in the program.
+It causes an
+.BR abort (3)
+with a diagnostic comment on the standard output when
+.I expression
+is false (0).
+Compiling with the 
+.BR cc (1)
+option
+.SM
+.B \-DNDEBUG
+effectively deletes
+.B assert
+from the program.
+.SH DIAGNOSTICS
+`Assertion "\fIexpression\fR" failed: file
+.I f
+line
+.IR n .'
+.I F
+is the source file and
+.I n
+the source line number of the
+.B assert
+statement.
Index: /trunk/minix/man/man3/atof.3
===================================================================
--- /trunk/minix/man/man3/atof.3	(revision 9)
+++ /trunk/minix/man/man3/atof.3	(revision 9)
@@ -0,0 +1,39 @@
+.\"	@(#)atof.3	6.1 (Berkeley) 5/15/85
+.\"
+.TH ATOF 3  "May 15, 1985"
+.AT 3
+.SH NAME
+atof, atoi, atol \- convert ASCII to numbers
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdlib.h>
+
+double atof(const char *\fInptr\fP)
+int atoi(const char *\fInptr\fP)
+long atol(const char *\fInptr\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+These functions convert a string pointed to by
+.I nptr
+to floating, integer, and long integer representation respectively.
+The first unrecognized character ends the string.
+.PP
+.B Atof
+recognizes an optional string of spaces, then an optional sign, then
+a string of digits optionally containing a decimal
+point, then an optional `e' or `E' followed by an optionally signed integer.
+.PP
+.B Atoi
+and
+.B atol
+recognize an optional string of spaces, then an optional sign, then a
+string of
+digits.
+.SH SEE ALSO
+.BR strtol (3),
+.BR strtod (3),
+.BR scanf (3).
+.SH BUGS
+There are no provisions for overflow.
Index: /trunk/minix/man/man3/bstring.3
===================================================================
--- /trunk/minix/man/man3/bstring.3	(revision 9)
+++ /trunk/minix/man/man3/bstring.3	(revision 9)
@@ -0,0 +1,84 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)bstring.3	6.1 (Berkeley) 5/15/85
+.\"
+.TH BSTRING 3  "May 15, 1985"
+.UC 5
+.SH NAME
+bstring, bcopy, bcmp, bzero, ffs \- bit and byte string operations
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <string.h>
+#include <unistd.h>
+
+void bcopy(const void *\fIsrc\fP, void *\fIdst\fP, size_t \fIlength\fP)
+int bcmp(const void *\fIb1\fP, const void *\fIb2\fP, size_t \fIlength\fP)
+void bzero(void *\fIdst\fP, size_t \fIlength\fP)
+int ffs(int \fIi\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+The functions
+.BR bcopy ,
+.BR bcmp ,
+and
+.B bzero
+operate on variable length strings of bytes.
+They do not check for null bytes as the routines in
+.BR string (3)
+do.
+.PP
+.B Bcopy
+copies 
+.I length
+bytes from string
+.I src
+to the string
+.IR dst .
+.PP
+.B Bcmp
+compares byte string
+.I b1
+against byte string
+.IR b2 ,
+returning zero if they are identical,
+non-zero otherwise.  Both strings are
+assumed to be
+.I length
+bytes long.
+.PP
+.B Bzero
+places
+.I length
+0 bytes in the string
+.IR b1 .
+.PP
+.B Ffs
+find the first bit set in the argument passed it and
+returns the index of that bit.  Bits are numbered
+starting at 1.  A return value of 0 indicates the
+value passed is zero.
+.SH BUGS
+The
+.BR bcopy ,
+.BR bcmp ,
+and
+.BR bzero
+functions are obsolete; new code should use
+.BR memmove ,
+.BR memcmp ,
+and
+.BR memset
+respectively.
+.PP
+The
+.B bcopy
+routine takes parameters backwards from
+.BR memcpy ,
+.BR memmove ,
+and
+.BR strcpy .
Index: /trunk/minix/man/man3/configfile.3
===================================================================
--- /trunk/minix/man/man3/configfile.3	(revision 9)
+++ /trunk/minix/man/man3/configfile.3	(revision 9)
@@ -0,0 +1,194 @@
+.TH CONFIGFILE 3
+.SH NAME
+configfile, config_read, config_delete, config_renewed, config_length, config_issub, config_isatom, config_isstring \- generic configuration file functions
+.SH SYNOPSIS
+.ft B
+.nf
+#include <configfile.h>
+
+config_t *config_read(const char *\fIfile\fP, int \fIflags\fP, config_t *\fIcfg\fP)
+void config_delete(config_t *\fIcfg\fP)
+int config_renewed(config_t *\fIcfg\fP)
+size_t config_length(config_t *\fIcfg\fP)
+int config_issub(config_t *\fIcfg\fP)
+int config_isatom(config_t *\fIcfg\fP)
+int config_isstring(config_t *\fIcfg\fP)
+.fi
+.ft P
+.SH DESCRIPTION
+The
+.B configfile
+routines operate on a generic configuration file that follows the syntax
+described in
+.BR configfile (5).
+.PP
+The interface presented by the functions above uses the following type and
+definitions from <configfile.h>:
+.PP
+.if n .in +2
+.if t .RS
+.nf
+.ta +\w'type'u +\w'const charmm'u +\w'word[];mm'u
+typedef const struct config {
+	config_t	*next;	/* Next configuration file thing. */
+	config_t	*list;	/* For a { sublist }. */
+	const char	*file;	/* File and line where this is found. */
+	unsigned	line;
+	int	flags;	/* Special flags. */
+	char	word[];	/* Payload. */
+} config_t;
+
+.ta +\w'#definem'u +\w'CFG_SUBLISTm'u +\w'0x0000mm'u
+#define	CFG_CLONG	0x0001	/* strtol(word, &end, 0) is valid. */
+#define	CFG_OLONG	0x0002	/* strtol(word, &end, 010). */
+#define	CFG_DLONG	0x0004	/* strtol(word, &end, 10). */
+#define	CFG_XLONG	0x0008	/* strtol(word, &end, 0x10). */
+#define	CFG_CULONG	0x0010	/* strtoul(word, &end, 0). */
+#define	CFG_OULONG	0x0020	/* strtoul(word, &end, 010). */
+#define	CFG_DULONG	0x0040	/* strtoul(word, &end, 10). */
+#define	CFG_XULONG	0x0080	/* strtoul(word, &end, 0x10). */
+#define	CFG_STRING	0x0100	/* The word is enclosed in quotes. */
+#define	CFG_SUBLIST	0x0200	/* This is a sublist, so no word. */
+#define	CFG_ESCAPED	0x0400	/* Escapes are still marked with \e. */
+.fi
+.if n .in -2
+.if t .RE
+.PP
+In memory a configuration file is represented as a list of
+.B config_t
+cells linked together with the
+.B next
+field ending with a null pointer.  A sublist between braces is attached to a
+cell at the
+.B list
+field.
+Words and strings are put in the
+.B word
+field, a null terminated string.  The
+.B flags
+field records the type and features of a cell.  The
+.B CFG_*LONG
+flags are set if a word is a number according to one of the
+.B strtol
+or
+.B strtoul
+calls.  Purely a number, no quotes or trailing garbage.  The
+.B CFG_STRING
+flag is set if the object was enclosed in double quotes.  Lastly
+.B CFG_SUBLIST
+tells if the cell is only a pointer to a sublist in braces.
+.PP
+Characters in a word or string may have been formed with the
+.B \e
+escape character.  They have been parsed and expanded, but the \e is still
+present if
+.B CFG_ESCAPED
+is set.  The
+.B word
+array may be changed, as long as it doesn't grow longer, so one may remove
+the \es like this:
+.PP
+.RS
+.ta +4n +4n
+.nf
+if (cfg->flags & CFG_ESCAPED) {
+	char *p, *q;
+	p= q= cfg->word;
+	for (;;) {
+		if ((*q = *p) == '\e\e') *q = *++p;
+		if (*q == 0) break;
+		p++;
+		q++;
+	}
+}
+.fi
+.RE
+.PP
+The low level syntax of a config file is checked when it is read.  If an
+error is encountered a message is printed and the program exits with exit
+code 1.  What the data means is not checked, that
+should be done by the program using the data.  Only the atom
+.B include
+at the beginning of a list is special.  It should be followed by a string.
+The string is seen as the name of a file, that is opened, read, and inserted
+in place of the
+.BR include .
+Unless the name of the file starts with a
+.BR / ,
+it is sought relative to the directory the current file is found in.
+Nonexistent files are treated as being empty.
+.PP
+The
+.B file
+and
+.B line
+fields in each cell tell where the cell was read.
+.SS Functions
+A configuration file is read with
+.BR config_read .
+The first argument is the file to read.  The second is either
+.B 0
+or
+.B CFG_ESCAPED
+to tell whether \e escapes should be fully expanded without leaving a trace,
+or if they should still be marked with a \e so that the caller knows where
+the excapes are.
+The third argument,
+.IR cfg ,
+should be a null pointer on the first call.  If you want to reread a config
+file that may have changed then
+.I cfg
+should be what you previously read.
+.PP
+With
+.B config_delete
+one can free up the memory that has been acquired with
+.BR malloc (3)
+to hold the contents of the configuration file.
+.PP
+To determine if the contents of configuration file has changed when reread
+one uses
+.BR config_renewed
+after
+.BR config_read .
+It returns a "changed" flag that is set when the configuration file changed
+and then clears that flag.  It returns true on the very first call.  For the
+function to work you need to feed the old data back into
+.BR config_read ,
+not delete and reread.
+.PP
+The length of a series of config structures is told by
+.BR config_length .
+It follows the
+.B next
+fields, so a sublist between braces counts as one extra.
+.PP
+The
+.BR config_issub ,
+.BR config_isatom
+and
+.BR config_isstring
+functions are just pretty macros to test if a cell references a sublist, is
+a word/string, or is just a string.
+.B CFG_SUBLIST
+and
+.B CFG_STRING
+tell the same story.
+.SH FILES
+.TP \w'*/etc/*.confmmmm'u
+.B */etc/*.conf
+Several files in several
+.B etc
+directories.
+.SH "SEE ALSO"
+.BR configfile (5).
+.SH NOTES
+The syntax of a config file puts some constraints on what you find in memory.
+The top level list consists entirely of sublist cells.  These point to lists
+that start with at least an atom, followed by a mix of atoms and sublist cells.
+These sublists in turn point to a list of only sublist cells (recurse now.)
+.PP
+The struct config shown above is not exactly proper C to aid
+readability, read <configfile.h> itself to see why.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man3/crypt.3
===================================================================
--- /trunk/minix/man/man3/crypt.3	(revision 9)
+++ /trunk/minix/man/man3/crypt.3	(revision 9)
@@ -0,0 +1,71 @@
+.TH CRYPT 3
+.SH NAME
+crypt \- one-way password encryption function
+.SH SYNOPSIS
+.ft B
+.nf
+#define _MINIX_SOURCE 1
+#include <unistd.h>
+
+char *crypt(const char *\fIkey\fP, const char *\fIsalt\fP)
+.fi
+.ft P
+.SH DESCRIPTION
+The first use of
+.B crypt()
+is to encrypt a password.  Its second use is to authenticate a shadow
+password.  In both cases
+.B crypt()
+calls
+.BR pwdauth (8)
+to do the real work.
+.PP
+.B Crypt()
+encrypts a password if called with a user typed key, and a salt
+whose first two characters are in the set [./0-9A-Za-z].  The result is a
+character string in the [./0-9A-Za-z] alphabet of which the first two
+characters are equal to the salt, and the rest is the result of encrypting
+the key and the salt.
+.PP
+If
+.B crypt()
+is called with a salt that has the form
+.BI "##" user
+then the key is encrypted and compared to the encrypted password of
+.I user
+in the shadow password file.  If they are equal then
+.B crypt()
+returns the
+.BI "##" user
+argument, if not then some other string is returned.  This trick assures
+that the normal way to authenticate a password still works:
+.PP
+.RS
+.nf
+if (strcmp(pw->pw_passwd, crypt(key, pw->pw_passwd))) ...
+.fi
+.RE
+.PP
+If
+.I key
+is a null string, and the shadow password is a null string or the salt is a
+null string then the result equals
+.IR salt .
+(This is because the caller can't tell if a password field is empty in the
+shadow password file.)
+.PP
+The key and salt are limited to 1024 bytes total including the null bytes.
+.SH FILES
+.TP 25
+/usr/lib/pwdauth
+The password authentication program
+.SH "SEE ALSO"
+.BR getpass (3),
+.BR getpwent (3),
+.BR passwd (5),
+.BR pwdauth (8).
+.SH NOTES
+The result of an encryption is returned in a static array that is
+overwritten by each call.  The return value should not be modified.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man3/ctime.3
===================================================================
--- /trunk/minix/man/man3/ctime.3	(revision 9)
+++ /trunk/minix/man/man3/ctime.3	(revision 9)
@@ -0,0 +1,109 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)ctime.3	6.8 (Berkeley) 4/2/87
+.\"
+.TH CTIME 3  "April 2, 1987"
+.UC 4
+.SH NAME
+ctime, localtime, gmtime, asctime, tzset \-  convert date and time to ASCII
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <time.h>
+
+void tzset(void)
+char *ctime(const time_t *\fIclock\fP)
+char *asctime(const struct tm *\fItm\fP)
+struct tm *localtime(const time_t *\fIclock\fP)
+struct tm *gmtime(const time_t *\fIclock\fP)
+.fi
+.SH DESCRIPTION
+\fBTzset\fP uses the value of the environment variable \fBTZ\fP to
+set up the time conversion information used by \fBlocaltime\fP.
+.PP
+If \fBTZ\fP does not appear in the environment, the \fBTZDEFAULT\fP
+file (as defined in \fI<tzfile.h>\fP) is used by \fBlocaltime\fP.  If
+this file fails for any reason, the GMT offset as provided by the
+kernel is used.  In this case, DST is ignored, resulting in the time
+being incorrect by some amount if DST is currently in effect.  If
+this fails for any reason, GMT is used.
+.PP
+If \fBTZ\fP appears in the environment but its value is a null string,
+Greenwich Mean Time is used; if \fBTZ\fP appears and begins with a
+slash, it is used as the absolute pathname of the \fBtzfile\fP(5)-format
+file from which to read the time conversion information; if \fBTZ\fP
+appears and begins with a character other than a slash, it's used as
+a pathname relative to the system time conversion information directory,
+defined as \fBTZDIR\fP in the include file \fBtzfile.h\fP.  If this file
+fails for any reason, the GMT offset as provided by the kernel is
+used, as described above.  If this fails for any reason, GMT is used.
+See
+.BR TZ (5)
+for a proper description of the
+.B TZ
+variable.
+.PP
+\fBCtime\fP converts a time value, pointed to by \fIclock\fP,
+such as returned by \fBtime\fP(2) into ASCII and returns a pointer
+to a 26-character string in the following form.  All the fields
+have constant width.
+.PP
+.RS
+.nf
+Sun Sep 16 01:03:52 1973\en\e0
+.fi
+.RE
+.PP
+.B Localtime
+and
+.B gmtime
+return pointers to structures containing
+the broken-down time.
+.B Localtime
+corrects for the time zone and possible daylight savings time;
+.B gmtime
+converts directly to GMT, which is the time UNIX uses.
+.B Asctime
+converts a broken-down time to ASCII and returns a pointer
+to a 26-character string.
+.PP
+The structure declaration from the include file is:
+.PP
+.RS
+.nf
+.nr .0 .8i+\w'int tm_isdst'u
+.ta .5i \n(.0u \n(.0u+\w'/* 0-000'u+1n
+struct tm {
+	int tm_sec;	/* 0-59	seconds */
+	int tm_min;	/* 0-59	minutes */
+	int tm_hour;	/* 0-23	hour */
+	int tm_mday;	/* 1-31	day of month */
+	int tm_mon;	/* 0-11	month */
+	int tm_year;	/* 0-	year \- 1900 */
+	int tm_wday;	/* 0-6	day of week (Sunday = 0) */
+	int tm_yday;	/* 0-365	day of year */
+	int tm_isdst;	/* flag:	daylight savings time in effect */
+};
+.fi
+.RE
+.PP
+\fBTm_isdst\fP is non-zero if a time zone adjustment such as Daylight
+Savings time is in effect.
+.SH FILES
+.ta \w'/usr/lib/zoneinfo\0\0'u
+/usr/lib/zoneinfo	time zone information directory
+.br
+/etc/localtime	local time zone file
+.SH SEE ALSO
+.BR time (2),
+.BR getenv (3),
+.BR tzfile (5),
+.BR TZ (5),
+.BR environ (7),
+.BR zic (8).
+.SH NOTE
+The return values point to static data whose content is overwritten by
+each call.  
Index: /trunk/minix/man/man3/ctype.3
===================================================================
--- /trunk/minix/man/man3/ctype.3	(revision 9)
+++ /trunk/minix/man/man3/ctype.3	(revision 9)
@@ -0,0 +1,95 @@
+.\"	@(#)ctype.3	6.4 (Berkeley) 5/12/86
+.\"
+.TH CTYPE 3  "May 12, 1986"
+.AT 3
+.SH NAME
+ctype, isalpha, isupper, islower, isdigit, isxdigit, isalnum, isspace, ispunct, isprint, isgraph, iscntrl, isascii, toupper, tolower, toascii \- character classification macros
+.SH SYNOPSIS
+.nf
+.ft B
+#include <ctype.h>
+
+int isalpha(int \fIc\fP)
+\&...
+.fi
+.SH DESCRIPTION
+These macros classify characters
+by table lookup.
+Each is a predicate returning nonzero for true,
+zero for false.
+.B Isascii
+and
+.B toascii
+are defined on all integer values; the rest
+are defined only on the range of
+.B "unsigned char"
+and on the special value
+EOF (see
+.BR stdio (3)).
+.TP 15n
+.B isalpha
+.I c
+is a letter
+.TP
+.B isupper
+.I c
+is an upper case letter
+.TP
+.B islower 
+.I c
+is a lower case letter
+.TP
+.B isdigit
+.I c
+is a digit
+.TP
+.B isxdigit
+.I c
+is a hex digit
+.TP
+.B isalnum
+.I c
+is an alphanumeric character
+.TP
+.B isspace
+.I c
+is a space, tab, carriage return, newline, vertical tab, or formfeed
+.TP
+.B ispunct
+.I c
+is a punctuation character (neither control nor alphanumeric)
+.TP
+.B isprint
+.I c
+is a printing character, code 040(8) (space) through 0176 (tilde)
+.TP
+.B isgraph
+.I c
+is a printing character, similar to
+.B isprint
+except false for space.
+.TP
+.B iscntrl
+.I c
+is a delete character (0177) or ordinary control character
+(less than 040).
+.TP
+.B isascii
+.I c
+is an ASCII character, code less than 0200
+.TP
+.B tolower
+.I c
+is converted to lower case.  Return value is undefined if not 
+.BR isupper (\fIc\fR).
+.TP
+.B toupper
+.I c
+is converted to upper case.  Return value is undefined if not 
+.BR islower (\fIc\fR).
+.TP
+.B toascii
+.I c
+is converted to be a valid ascii character.
+.SH "SEE ALSO"
+.BR ascii (7)
Index: /trunk/minix/man/man3/curses.3
===================================================================
--- /trunk/minix/man/man3/curses.3	(revision 9)
+++ /trunk/minix/man/man3/curses.3	(revision 9)
@@ -0,0 +1,248 @@
+.TH CURSES 3
+.SH NAME
+curses \- screen/window management library
+.SH SYNOPSIS
+cc demo.c -lcurses
+.SH DESCRIPTION
+Curses is a library of screen and window management routines.  It is modeled
+after the UNIX curses and ncurses libraries. Normally, programs written for
+curses should be easily ported to UNIX, and vice versa.
+.PP
+To use the routines, the function initscr() must first be called.
+This creates two 'windows' for the user: stdscr and curscr.  Stdscr is the
+default
+window for the user to make changes on, and curscr reflects the current
+contents of the physical display screen.  The user writes or edits the stdscr
+window to his liking, then calls the refresh() function to make curscr
+and the physical screen look like stdscr.  When the user program terminates,
+it should call the endwin() function to restore things to normal.
+.PP
+There are all sorts of window manipulation routines available to the
+programmer: auxiliary windows may be created, edited, moved and deleted.  The
+terminal may be set in many different modes, output text may be attributed
+with blink, blank, bold and reverse attributes.  Screen colors may also be 
+set, foreground and background.  There are window-specific
+printf- and scanf-like routines, routines for scrolling, box-drawing,
+window overlaying, clearing routines etc.
+.PP
+For more and detailed information, see the library source codes.  All curses
+functions are preceded by a complete description.
+.SH FUNCTIONS
+Below is a list over the available functions, together with a brief
+description of what they do.  In general, functions whose names start with 'w'
+differ from the one without 'w' (like wmove vs. move) signify that
+a specific window is used. Without a 'w', sdtscr is implied.  The functions
+that start with 'mv' before the 'genereic' function name signify that a
+cursor motion should be made before the actual work.  'mv' and 'w' combine
+as expected.
+.PP
+Most routines that return an int will return the manifest constant ERR if
+there is a failure during execution.  Routines that return a char actually
+return an int, so that ERR does not conflict with the character code 0xff.
+All characters from 0 to 0xff are allowed for usage with curses.
+.PP
+Some routines, like {mv}{w} printw() and {mv}{w}scanw() return a meaningful
+positive value if the operation is successful.
+.PP
+The curses package uses some predefined types, variables and manifest
+constants that are also available to the programmer.  There are also a few
+globally accessible variables that should not be touched by the application
+program.  Those untouchable variables have names starting with an
+underscore (_) to avoid conflicts.  The user-accessible types, variables
+and constants are (there are a number of other constants defining character
+attribute names and function key names - consult <curses.h> for details):
+.sp
+.nf
+.ta 3i
+(manifest constants)
+.RS
+TRUE	boolean true
+FALSE	boolean false
+ERR	unsuccessfull operation
+OK	successfull operation
+.RE
+.sp
+(types)
+.RS
+WINDOW	a window structure type
+bool	boolean flag type
+.RE
+.sp
+(variables)
+.RS
+WINDOW curscr	physical display image
+WINDOW stdscr	default user drawing board
+int LINES	terminal height
+int COLS	terminal width
+int NONL	\\n causes CR and LF when TRUE
+.RE
+.sp
+.fi
+The following is an alphabetical list of the curses functions, together
+with their types, parameters and a short comment for each (win is a window,
+ch, vc, hc are characters, buf is a character buffer, attrs is an
+attribute bit map, bf is a boolean flag.  Note that `characters' in this
+context usually can have 16 bits):
+.nf
+.sp
+int waddch(win,ch)	put char in stdscr
+int addch(ch)
+int mvaddch(y,x,ch)
+int mvwaddch(win,y,x,ch)
+
+int waddstr(win,str)	put string in stdscr
+int addstr(str)
+int mvaddstr(y,x,str)
+int mvwaddstr(win,y,x,str)
+
+void wattroff(win,attrs)	clear attribute(s) in window
+void attroff(attrs)
+
+void wattron(win,attrs)	add attribute(s) in window
+void attron(attrs)
+
+void wattrset(win,attrs)	set window char attributes
+void attrset(attrs)
+
+int baudrate()	dummy for compatibility
+
+void beep()	ring the bell or visible bell if no bell available
+
+void flash()	flash terminal screen or rings bell if no visible bell available
+
+void wbox(win,miny,minx,maxy,maxx,vc,hc)	box in a window, with given characters
+void box(win,vc,hc)
+
+void cbreak()	set terminal cbreak mode
+
+void wclear(win)	clear stdscr
+void clear()
+
+void clearok(win,bf)	marks window for screen clear
+
+int wclrtobot(win)	clear from cursor to end of line and all lines down this line
+int clrtobot()
+int mvclrtoeol(y,x)
+int mvwclrtobot(win,y,x)
+
+int wclrtoeol(win)	clear from cursor to end of line
+int clrtoeol()
+int mvclrtoeol(y,x)
+int mvwclrtoeol(win,y,x)
+
+int wdelch(win)	delete a char in a window
+int delch()
+int mvdelch(y,x)
+int mvwdelch(win,y,x)
+
+int wdeleteln(win)	delete a line in a window
+int deleteln()
+int mvdeleteln(y,x)
+int mvwdeleteln(win,y,x)
+
+void delwin(win)	delete a window or a subwindow
+void doupdate()	update physical screen
+void echo()	set terminal echo mode
+int endwin()	cleanup and curses finitialization
+
+void werase(win)	erase a window
+void erase()
+
+int erasechar()	return char delete character
+int fixterm()	dummy for compatibility
+void flushinp()	kill pending keyboard input
+
+int wgetch(win)	get char via a window
+int getch()
+int mvgetch(y,x)
+int mvwgetch(win,y,x)
+
+int wgetstr(win,str)	get string via window to a buffer
+int getstr(str)
+int mvgetstr(y,x,str)
+int mvwgetstr(win,y,x,str)
+
+void getyx(win,y,x)	get a window's cursor position
+
+int gettmode()	dummy for compatibility
+void idlok(win,bf)	dummy for compatibility
+WINDOW *initscr()	curses initialization (ret stdscr or NULL)
+
+int winch(win)	get char at window cursor
+int inch()
+int mvinch(y,x)
+int mvwinch(win,y,x)
+
+int winsch(win,ch)	insert character in a window
+int insch(ch)
+int mvinsch(y,x,ch)
+int mvwinsch(win,y,x,ch)
+
+int winsertln(win)	insert new line in a window
+int insertln()
+int mvinsertln(y,x)
+int mvwinsertln(win,y,x)
+
+void keypad(win,bf)	marks a window for keypad usage
+int killchar()	return line delete character
+char *longname()	returns terminal description string
+void leaveok(win,bf)	marks window for cursor 'update leave'
+void meta(win,bf)	marks window for meta
+int move(y,x)	move cursor in stdscr
+int mvcur(oldy,oldx,y,x)	move terminal cursor to <y,x>
+
+int mvprintw(y,x,fmt,args)	move & print string in stdscr
+
+int mvscanw(y,x,fmt,args)	move & get values via stdscr
+int mvwin(win,y,x)	move window on physical screen
+int mvwprintw(win,x,y,fmt,args)	move & print string in a window
+int mvwscanw(win,y,x,fmt,args)	move & get values via a window
+WINDOW *newwin(lines,cols,begy,begx)	create a new window
+void nl()	set terminal cr-crlf mapping mode
+void nocbreak()	unset terminal cbreak mod
+void nodelay(win,bf)	marks window for no input wait
+void noecho()	unset terminal echo mode
+void nonl()	unset terminal cr-crlf mapping mode
+void noraw()	unset raw terminal mode
+void overlay(win1,win2)	overlay one window on another
+void overwrite(win1,win2)	overwrite one window on another
+int printw(fmt,args)	print string in stdscr
+void raw()	set raw terminal mode
+void refrbrk(bf)	set screen update break mode
+void refresh()	refresh stdscr
+int resetterm()	dummy for compatibility
+int resetty()	restore terminal I/O modes
+int saveoldterm()	dummy for compatibility
+int saveterm()	dummy for compatibility
+int savetty()	save terminal I/O modes
+int scanw(fmt,args)	get values via stdscr
+void scroll(win)	scroll scrolling region of a window
+void scrollok(win,bf)	marks a window to allow scroll
+void setcolors(A_COLOR(for,back))	sets the forground and background
+	colors of stdscr
+void set_curs(visibility)	0 for invisible, 1 for visible, 2 for good
+	visible
+int setsrcreg(miny,maxy)	define stdscr's scroll region
+int setterm()	dummy for compatibility
+int setupterm(term,fd,errret)	set up terminal
+void standend()	start normal chars in stdscr
+void standout()	start standout chars in stdscr
+WINDOW *subwin(win,lines,cols,begy,begx)
+	create a sub-window in window win
+int tabsize(ts)	set/get tabsize of stdscr
+void touchwin(win)	mark a window as totally modified
+char *unctrl(ch)	char-to-string converter
+int wmove(win,y,x)	move cursor in a window
+void wnoutrefresh(win)	create internal screen image
+int wprintw(win,fmt,args)	print string in a window
+void wrefresh(win)	refresh window
+int wscanw(win,fmt,args)	get values via a window
+void wsetcolors(win,A_COLOR(for,back))	sets the forground and
+	background colors of the specified window
+int wsetsrcreg(win,miny,maxy)	define a window's scrolling region
+void wstandend(win)	start normal chars in window
+void wstandout(win)	start standout chars in window
+int wtabsize(win,ts)	set/get tabsize of a window
+.SH BUGS
+Function keys are not available under the MINIX version.
+.\" $PchId: curses.3,v 1.3 1996/02/22 21:26:28 philip Exp $
Index: /trunk/minix/man/man3/directory.3
===================================================================
--- /trunk/minix/man/man3/directory.3	(revision 9)
+++ /trunk/minix/man/man3/directory.3	(revision 9)
@@ -0,0 +1,89 @@
+.TH DIRECTORY 3
+.SH NAME
+directory, opendir, readdir, rewinddir, closedir, telldir, seekdir \- directory routines
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <dirent.h>
+
+DIR *opendir(const char *\fIdirname\fP)
+struct dirent *readdir(DIR *\fIdirp\fP)
+void rewinddir(DIR *\fIdirp\fP)
+int closedir(DIR *\fIdirp\fP)
+
+#define _MINIX  1
+#include <sys/types.h>
+#include <dirent.h>
+
+long telldir(DIR *\fIdirp\fP)
+int seekdir(DIR *\fIdirp\fP, long \fIpos\fP)
+.SH DESCRIPTION
+These routines form a system independent interface to access directories.
+.PP
+.B Opendir()
+opens the directory
+.I dirname
+and returns a pointer to this open directory stream.
+.PP
+.B Readdir()
+reads one entry from the directory as a pointer to a structure containing
+the field
+.BR d_name ,
+a character array containing the null-terminated name of the entry.
+.PP
+.B Rewinddir()
+allows the directory to be read again from the beginning.
+.PP
+.B Closedir()
+closes the directory and releases administrative data.
+.PP
+The MINIX 3 specific functions
+.B telldir()
+and
+.B seekdir()
+allow one to get the current position in the directory file and to return
+there later.
+.B Seekdir()
+may only be called with a position returned by
+.B telldir()
+or 0 (rewind).  These functions should not be used in portable programs.
+.SH "SEE ALSO"
+.BR dir (5).
+.SH DIAGNOSTICS
+.B Opendir()
+returns a null pointer if
+.I dirname
+can't be opened, or if it can't allocate enough memory for the
+.B DIR
+structure.
+.PP
+.B Readdir()
+returns null if there are no more directory entries or on error.
+.PP
+.B Closedir()
+and
+.B seekdir()
+returns 0 on success, -1 on error.
+.PP
+.B Telldir()
+returns -1 on error.
+.PP
+All of them set
+.B errno
+appropriately.
+.B Readdir()
+will only set
+.B errno
+on error, not on end-of-dir, so you should set
+.B errno
+to zero beforehand, and check its value if
+.B readdir()
+returns null.
+.SH NOTES
+The return value of
+.B readdir()
+needs to be copied before the next operation on the same directory if it is
+to be saved.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man3/editline.3
===================================================================
--- /trunk/minix/man/man3/editline.3	(revision 9)
+++ /trunk/minix/man/man3/editline.3	(revision 9)
@@ -0,0 +1,169 @@
+.\" $Revision: 1.1 $
+.TH EDITLINE 3
+.SH NAME
+editline \- command-line editing library with history
+.SH SYNOPSIS
+.ft B
+char *readline(char *\fIprompt\fP)
+.ft P
+.SH DESCRIPTION
+.I Editline
+is a library that provides an line-editing interface with text recall.
+It is intended to be compatible with the
+.I readline
+library provided by the Free Software Foundation, but much smaller.
+The bulk of this manual page describes the user interface.
+.PP
+The
+.I readline
+routine returns a line of text with the trailing newline removed.
+The data is returned in a buffer allocated with
+.IR malloc (3),
+so the space should be released with
+.IR free (3)
+when the calling program is done with it.
+Before accepting input from the user, the specified
+.I prompt
+is displayed on the terminal.
+.PP
+Each line returned is copied to the internal history list, unless it happens
+to be equal to the previous line.
+.SS "User Interface"
+A program that uses this library provides a simple emacs-like editing
+interface to its users.
+A line may be edited before it is sent to the calling program by typing either
+control characters or escape sequences.
+A control character, shown as a caret followed by a letter, is typed by
+holding down the ``control'' key while the letter is typed.
+For example, ``^A'' is a control-A.
+An escape sequence is entered by typing the ``escape'' key followed by one or
+more characters.
+The escape key is abbreviated as ``ESC.''
+Note that unlike control keys, case matters in escape sequences; ``ESC\ F''
+is not the same as ``ESC\ f''.
+.PP
+An editing command may be typed anywhere on the line, not just at the
+beginning.
+In addition, a return may also be typed anywhere on the line, not just at
+the end.
+.PP
+Most editing commands may be given a repeat count,
+.IR n ,
+where
+.I n
+is a number.
+To enter a repeat count, type the escape key, the number, and then
+the command to execute.
+For example, ``ESC\ 4\ ^f'' moves forward four characters.
+If a command may be given a repeat count then the text ``[n]'' is given at the
+end of its description.
+.PP
+The following control characters are accepted:
+.RS
+.nf
+.ta \w'ESC DEL  'u
+^A	Move to the beginning of the line
+^B	Move left (backwards) [n]
+^D	Delete character [n]
+^E	Move to end of line
+^F	Move right (forwards) [n]
+^G	Ring the bell
+^H	Delete character before cursor (backspace key) [n]
+^I	Complete filename (tab key); see below
+^J	Done with line (return key)
+^K	Kill to end of line (or column [n])
+^L	Redisplay line
+^M	Done with line (alternate return key)
+^N	Get next line from history [n]
+^P	Get previous line from history [n]
+^R	Search backward (forward if [n]) through history for text;
+\&	must start line if text begins with an uparrow
+^T	Transpose characters
+^V	Insert next character, even if it is an edit command
+^W	Wipe to the mark
+^X^X	Exchange current location and mark
+^Y	Yank back last killed text
+^[	Start an escape sequence (escape key)
+^]c	Move forward to next character ``c''
+^?	Delete character before cursor (delete key) [n]
+.fi
+.RE
+.PP
+The following escape sequences are provided.
+.RS
+.nf
+.ta \w'ESC DEL  'u
+ESC\ ^H	Delete previous word (backspace key) [n]
+ESC\ DEL	Delete previous word (delete key) [n]
+ESC\ SP	Set the mark (space key); see ^X^X and ^Y above
+ESC\ \.	Get the last (or [n]'th) word from previous line
+ESC\ \?	Show possible completions; see below
+ESC\ <	Move to start of history
+ESC\ >	Move to end of history
+ESC\ b	Move backward a word [n]
+ESC\ d	Delete word under cursor [n]
+ESC\ f	Move forward a word [n]
+ESC\ l	Make word lowercase [n]
+ESC\ m	Toggle if 8bit chars display normally or with ``M\-'' prefix
+ESC\ u	Make word uppercase [n]
+ESC\ y	Yank back last killed text
+ESC\ v	Show library version
+ESC\ w	Make area up to mark yankable
+ESC\ nn	Set repeat count to the number nn
+ESC\ C	Read from environment variable ``_C_'', where C is
+\&	an uppercase letter
+.fi
+.RE
+.PP
+The
+.I editline
+library has a small macro facility.
+If you type the escape key followed by an uppercase letter,
+.IR C ,
+then the contents of the environment variable
+.I _C_
+are read in as if you had typed them at the keyboard.
+For example, if the variable
+.I _L_
+contains the following:
+.RS
+^A^Kecho '^V^[[H^V^[[2J'^M
+.RE
+Then typing ``ESC L'' will move to the beginning of the line, kill the
+entire line, enter the echo command needed to clear the terminal (if your
+terminal is like a VT-100), and send the line back to the shell.
+.PP
+The
+.I editline
+library also does filename completion.
+Suppose the root directory has the following files in it:
+.RS
+.nf
+.ta \w'core   'u
+bin	vmunix
+core	vmunix.old
+.fi
+.RE
+If you type ``rm\ /v'' and then the tab key.
+.I Editline
+will then finish off as much of the name as possible by adding ``munix''.
+Because the name is not unique, it will then beep.
+If you type the escape key and a question mark, it will display the
+two choices.
+If you then type a period and a tab, the library will finish off the filename
+for you:
+.RS
+.nf
+.RI "rm /v[TAB]" munix .TAB old
+.fi
+.RE
+The tab key is shown by ``[TAB]'' and the automatically-entered text
+is shown in italics.
+.SH "BUGS AND LIMITATIONS"
+Doesn't know how to handle multiple lines.
+.SH AUTHORS
+Simmule R. Turner <uunet.uu.net!capitol!sysgo!simmy>
+and Rich $alz <rsalz@osf.org>.
+Original manual page by DaviD W. Sanderson <dws@ssec.wisc.edu>.
+
+.\" $PchId: editline.3,v 1.3 1996/02/22 21:18:51 philip Exp $
Index: /trunk/minix/man/man3/end.3
===================================================================
--- /trunk/minix/man/man3/end.3	(revision 9)
+++ /trunk/minix/man/man3/end.3	(revision 9)
@@ -0,0 +1,42 @@
+.\"	@(#)end.3	6.2 (Berkeley) 5/12/86
+.\"
+.TH END 3  "May 12, 1986"
+.AT 3
+.SH NAME
+end, etext, edata \- last locations in program
+.SH SYNOPSIS
+.nf
+.ft B
+extern int etext;
+extern int edata;
+extern int end, _end;
+.ft R
+.fi
+.SH DESCRIPTION
+These names refer neither to routines nor to locations with interesting
+contents.  The address of
+.B etext
+is the first address above the program text,
+.B edata
+above the initialized data region, and
+.B end
+above the uninitialized data region.
+.B _end
+is the same as
+.BR end ,
+but in the implementers name space, i.e. for use in libraries.
+.PP
+When execution begins, the program break coincides with
+.BR end ,
+but it is reset by the routines
+.BR brk (2),
+.BR malloc (3), 
+standard input/output
+.RB ( stdio (3)),
+etc.
+The current value of the program break is reliably returned by `sbrk(0)',
+see
+.BR brk (2).
+.SH "SEE ALSO"
+.BR brk (2),
+.BR malloc (3).
Index: /trunk/minix/man/man3/execl.3
===================================================================
--- /trunk/minix/man/man3/execl.3	(revision 9)
+++ /trunk/minix/man/man3/execl.3	(revision 9)
@@ -0,0 +1,196 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)execl.3	6.2 (Berkeley) 4/25/86
+.\"
+.TH EXECL 3 "April 25, 1986"
+.UC 5
+.SH NAME
+execl, execv, execle, execlp, execvp, exec, environ \- execute a file
+.SH SYNOPSIS
+.ft B
+#include <unistd.h>
+
+.in +.5i
+.ti -.5i
+int execl(const char *\fIname\fP, const char *\fIarg0\fP, ..., (char *) NULL)
+.ti -.5i
+int execv(const char *\fIname\fP, char *const \fIargv\fP[])
+.ti -.5i
+int execle(const char *\fIname\fP, const char *\fIarg0\fP, ..., (char *) NULL, char *const \fIenvp\fP[])
+.ti -.5i
+int execlp(const char *\fIname\fP, const char *\fIarg0\fP, ..., (char *) NULL)
+.ti -.5i
+int execvp(const char *\fIname\fP, char *const \fIargv\fP[])
+.in -.5i
+
+extern char *const *environ;
+.fi
+.SH DESCRIPTION
+These routines provide various interfaces to the
+.B execve 
+system call.  Refer to 
+.BR  execve (2)
+for a description of their properties; only
+brief descriptions are provided here.
+.PP
+.B Exec
+in all its forms
+overlays the calling process with the named file, then
+transfers to the
+entry point of the core image of the file.
+There can be no return from a successful exec; the calling
+core image is lost.
+.PP
+The
+.I name
+argument
+is a pointer to the name of the file
+to be executed.
+The pointers
+.IR arg [ 0 ],
+.IR arg [ 1 "] ..."
+address null-terminated strings.
+Conventionally
+.IR arg [ 0 ]
+is the name of the
+file.
+.PP
+Two interfaces are available.
+.B execl
+is useful when a known file with known arguments is
+being called;
+the arguments to
+.B execl
+are the character strings
+constituting the file and the arguments;
+the first argument is conventionally
+the same as the file name (or its last component).
+A null pointer argument must end the argument list.
+(Note that the
+.B execl*
+functions are variable argument functions.  This means that the type
+of the arguments beyond
+.I arg0
+is not checked.  So the null pointer requires an explicit cast to type
+.B "(char *)"
+if not of that type already.)
+.PP
+The
+.B execv
+version is useful when the number of arguments is unknown
+in advance;
+the arguments to
+.B execv
+are the name of the file to be
+executed and a vector of strings containing
+the arguments.
+The last argument string must be followed
+by a null pointer.
+.PP
+When a C program is executed,
+it is called as follows:
+.PP
+.RS
+.ft B
+.nf
+int main(int \fIargc\fP, char *const \fIargv\fP[], char *const \fIenvp\fP[]);
+
+exit(main(\fIargc\fP, \fIargv\fP, \fIenvp\fP));
+.fi
+.ft R
+.RE
+.PP
+where
+.I argc
+is the argument count
+and
+.I argv 
+is an array of character pointers
+to the arguments themselves.
+As indicated,
+.I argc
+is conventionally at least one
+and the first member of the array points to a
+string containing the name of the file.
+.PP
+.I Argv
+is directly usable in another
+.B execv
+because
+.IR argv [ argc ]
+is 0.
+.PP
+.I Envp
+is a pointer to an array of strings that constitute
+the
+.I environment
+of the process.
+Each string consists of a name, an \*(lq=\*(rq, and a null-terminated value.
+The array of pointers is terminated by a null pointer.
+The shell
+.BR sh (1)
+passes an environment entry for each global shell variable
+defined when the program is called.
+See
+.BR environ (7)
+for some conventionally
+used names.
+The C run-time start-off routine places a copy of
+.I envp
+in the global cell
+.BR environ ,
+which is used
+by
+.B execv
+and
+.B execl
+to pass the environment to any subprograms executed by the
+current program.
+.PP
+.B Execlp
+and
+.B execvp
+are called with the same arguments as
+.B execl
+and
+.BR execv ,
+but duplicate the shell's actions in searching for an executable
+file in a list of directories.
+The directory list is obtained from the environment variable
+.BR PATH .
+Under standard MINIX 3, if a file is found that is executable, but does
+not have the proper executable header then it is assumed to be
+a shell script.
+.B Execlp
+and
+.B execvp
+execute
+.B /bin/sh
+to interpret the script.
+Under Minix-vmd this does not happen, a script must begin with
+.B #!
+and the full path name of the interpreter if it is to be an
+executable script.
+.SH "SEE ALSO"
+.BR execve (2),
+.BR fork (2),
+.BR environ (7),
+.BR sh (1).
+.SH DIAGNOSTICS
+If the file cannot be found,
+if it is not executable,
+if it does not start with a valid magic number (see
+.BR a.out (5)),
+if maximum memory is exceeded,
+or if the arguments require too much space,
+a return
+constitutes the diagnostic;
+the return value is \-1 and
+.B errno
+is set as for
+.BR execve .
+Even for the super-user,
+at least one of the execute-permission bits must be set for
+a file to be executed.
Index: /trunk/minix/man/man3/exit.3
===================================================================
--- /trunk/minix/man/man3/exit.3	(revision 9)
+++ /trunk/minix/man/man3/exit.3	(revision 9)
@@ -0,0 +1,39 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)exit.3	6.2 (Berkeley) 5/12/86
+.\"
+.TH EXIT 3 "May 12, 1986"
+.UC 5
+.SH NAME
+exit, atexit \- terminate a process after flushing any pending output
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdlib.h>
+
+void exit(int \fIstatus\fP)
+int atexit(void (*\fIfunc\fP)(void))
+.ft R
+.fi
+.SH DESCRIPTION
+.B Exit
+first calls all functions registered by
+.BR atexit ,
+flushes all data buffered by the Standard I/O library, and finally
+terminates the process.
+.B Exit
+never returns.
+.PP
+.B Atexit
+registers the function
+.I func
+into a table of functions to be called on exit.
+.SH "SEE ALSO"
+.BR exit (2).
+.SH DIAGNOSTICS
+.B Atexit
+returns 0 on success, \-1 if
+.B malloc
+cannot allocate more memory for the list of registered functions.
Index: /trunk/minix/man/man3/fclose.3
===================================================================
--- /trunk/minix/man/man3/fclose.3	(revision 9)
+++ /trunk/minix/man/man3/fclose.3	(revision 9)
@@ -0,0 +1,45 @@
+.\"	@(#)fclose.3s	6.1 (Berkeley) 5/15/85
+.\"
+.TH FCLOSE 3  "May 15, 1985"
+.AT 3
+.SH NAME
+fclose, fflush \- close or flush a stream
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdio.h>
+
+int fclose(FILE *\fIstream\fP)
+int fflush(FILE *\fIstream\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Fclose
+causes any buffers for the named
+.I stream
+to be emptied, and the file to be closed.
+Buffers allocated by the standard input/output system
+are freed.
+.PP
+.B Fclose
+is performed automatically upon
+calling
+.BR  exit (3).
+.PP
+.B Fflush
+causes any buffered data for the named output
+.I stream
+to be written to that file.
+The stream remains open.
+.SH "SEE ALSO"
+.BR close (2),
+.BR fopen (3),
+.BR setbuf (3).
+.SH DIAGNOSTICS
+These routines return
+.SM
+.B EOF
+if
+.I stream
+is not associated with an output file, or
+if buffered data cannot be transferred to that file.
Index: /trunk/minix/man/man3/ferror.3
===================================================================
--- /trunk/minix/man/man3/ferror.3	(revision 9)
+++ /trunk/minix/man/man3/ferror.3	(revision 9)
@@ -0,0 +1,58 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)ferror.3s	6.3 (Berkeley) 5/14/86
+.\"
+.TH FERROR 3  "May 14, 1986"
+.UC 4
+.SH NAME
+ferror, feof, clearerr, fileno \- stream status inquiries
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdio.h>
+
+int feof(FILE *\fIstream\fP)
+int ferror(FILE *\fIstream\fP)
+int clearerr(FILE *\fIstream\fP)
+int fileno(FILE *\fIstream\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Feof
+returns non-zero when end of file is read on the named input
+.IR stream ,
+otherwise zero.
+Unless cleared by
+.BR clearerr ,
+the end-of-file indication lasts until
+the stream is closed.
+.PP
+.B Ferror
+returns non-zero when an error has occurred reading or writing
+the named
+.IR stream ,
+otherwise zero.
+Unless cleared by
+.BR clearerr ,
+the error indication lasts until
+the stream is closed.
+.PP
+.B Clearerr
+resets the error and end-of-file indicators on the named
+.IR stream .
+.PP
+.B Fileno
+returns the integer file descriptor
+associated with the
+.IR stream ,
+see
+.BR open (2).
+.PP
+Currently all of these functions
+are implemented as macros;
+they cannot be redeclared.
+.SH "SEE ALSO"
+.BR fopen (3),
+.BR open (2).
Index: /trunk/minix/man/man3/fopen.3
===================================================================
--- /trunk/minix/man/man3/fopen.3	(revision 9)
+++ /trunk/minix/man/man3/fopen.3	(revision 9)
@@ -0,0 +1,99 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)fopen.3s	6.3 (Berkeley) 5/27/86
+.\"
+.TH FOPEN 3  "May 27, 1986"
+.UC 4
+.SH NAME
+fopen, freopen, fdopen \- open a stream
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdio.h>
+
+FILE *fopen(const char *\fIfilename\fP, const char *\fItype\fP)
+FILE *freopen(const char *\fIfilename\fP, const char *\fItype\fP, FILE *\fIstream\fP)
+FILE *fdopen(int \fIfildes\fP, const char *\fItype\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Fopen
+opens the file named by
+.I filename
+and associates a stream with it.
+.B Fopen
+returns a pointer to be used to identify the stream in subsequent operations.
+.PP
+.I Type
+is a character string having one of the following values:
+.TP 5
+"r"
+open for reading
+.ns
+.TP 5
+"w"
+create for writing
+.ns
+.TP 5
+"a"
+append: open for writing at end of file, or create for writing
+.PP
+In addition, each
+.I type
+may be followed by a "+" to have the file opened for reading and writing.
+"r+" positions the stream at the beginning of the file, "w+" creates
+or truncates it, and "a+" positions it at the end.  Both reads and writes
+may be used on read/write streams, with the limitation that an
+.BR fseek ,
+.BR rewind ,
+or reading an end-of-file must be used between a read and a write or vice-versa.
+.PP
+.B Freopen
+substitutes the named file in place of the open
+.IR stream .
+It returns the original value of
+.IR stream .
+The original stream is closed.
+.PP
+.B Freopen
+is typically used to attach the preopened constant names,
+.B stdin, stdout, stderr,
+to specified files.
+.PP
+.B Fdopen
+associates a stream with a file descriptor obtained from
+.BR open ,
+.BR dup ,
+.BR creat ,
+or
+.BR pipe (2).
+The
+.I type
+of the stream must agree with the mode of the open file.
+.SH "SEE ALSO"
+.BR open (2),
+.BR fclose (3).
+.SH DIAGNOSTICS
+.B Fopen
+and 
+.B freopen
+return the pointer
+.SM
+.B NULL
+if
+.I filename
+cannot be accessed,
+if too many files are already open,
+or if other resources needed cannot be allocated.
+.SH BUGS
+.B Fdopen
+is not portable to systems other than UNIX.
+.PP
+The read/write 
+.I types
+do not exist on all systems.  Those systems without
+read/write modes will probably treat the 
+.I type
+as if the "+" was not present.  These are unreliable in any event.
Index: /trunk/minix/man/man3/fread.3
===================================================================
--- /trunk/minix/man/man3/fread.3	(revision 9)
+++ /trunk/minix/man/man3/fread.3	(revision 9)
@@ -0,0 +1,66 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)fread.3s	6.1 (Berkeley) 5/15/85
+.\"
+.TH FREAD 3  "May 15, 1985"
+.UC 4
+.SH NAME
+fread, fwrite \- buffered binary input/output
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <stdio.h>
+
+size_t fread(void *\fIptr\fP, size_t \fIitemsize\fP, size_t \fInitems\fP, FILE *\fIstream\fP)
+size_t fwrite(void *\fIptr\fP, size_t \fIitemsize\fP, size_t \fInitems\fP, FILE *\fIstream\fP)
+.SH DESCRIPTION
+.B Fread
+reads, into a block beginning at
+.IR ptr ,
+.I nitems
+of data of the type of
+.I *ptr
+from the named input
+.IR stream .
+It returns the number of items actually read.
+.PP
+If
+.I stream
+is
+.B stdin
+and the standard output is line buffered, then any partial output line
+will be flushed before any call to
+.BR read (2)
+to satisfy the
+.BR fread .
+.PP
+.B Fwrite
+appends at most
+.I nitems
+of data of the type of
+.I *ptr
+beginning at
+.I ptr
+to the named output
+.IR stream .
+It returns the number of items actually written.
+.SH "SEE ALSO"
+.BR read (2),
+.BR write (2),
+.BR fopen (3),
+.BR getc (3),
+.BR putc (3),
+.BR gets (3),
+.BR puts (3),
+.BR printf (3),
+.BR scanf (3).
+.SH DIAGNOSTICS
+.B Fread
+and
+.B fwrite
+return
+0
+upon end of file or error.
Index: /trunk/minix/man/man3/fseek.3
===================================================================
--- /trunk/minix/man/man3/fseek.3	(revision 9)
+++ /trunk/minix/man/man3/fseek.3	(revision 9)
@@ -0,0 +1,53 @@
+.\"	@(#)fseek.3s	6.3 (Berkeley) 2/24/86
+.\"
+.TH FSEEK 3  "February 24, 1986"
+.AT 3
+.SH NAME
+fseek, ftell, rewind \- reposition a stream
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdio.h>
+
+int fseek(FILE *\fIstream\fP, long \fIoffset\fP, int \fIptrname\fP)
+long ftell(FILE *\fIstream\fP)
+void rewind(FILE *\fIstream\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Fseek
+sets the position of the next input or output
+operation on the
+.IR stream .
+The new position is at the signed distance
+.I offset
+bytes
+from the beginning, the current position, or the end of the file,
+according as 
+.I ptrname
+has the value 0, 1, or 2.
+.PP
+.B Fseek
+undoes any effects of
+.BR  ungetc (3).
+.PP
+.B Ftell
+returns the current value of the offset relative to the beginning
+of the file associated with the named
+.IR stream .
+It is measured in bytes on UNIX;
+on some other systems it is a magic cookie,
+and the only foolproof way to obtain an 
+.I offset
+for
+.BR fseek .
+.PP
+.BR Rewind "(\fIstream\fR)"
+is equivalent to
+.BR fseek "(\fIstream\fR, 0L, 0)."
+.SH "SEE ALSO"
+.BR lseek (2),
+.BR fopen (3).
+.SH DIAGNOSTICS
+.B Fseek
+returns \-1 for improper seeks, otherwise zero.
Index: /trunk/minix/man/man3/g_h_b_n.3
===================================================================
--- /trunk/minix/man/man3/g_h_b_n.3	(revision 9)
+++ /trunk/minix/man/man3/g_h_b_n.3	(revision 9)
@@ -0,0 +1,165 @@
+.\" Copyright (c) 1983, 1987 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms are permitted provided
+.\" that: (1) source distributions retain this entire copyright notice and
+.\" comment, and (2) distributions including binaries display the following
+.\" acknowledgement:  ``This product includes software developed by the
+.\" University of California, Berkeley and its contributors'' in the
+.\" documentation or other materials provided with the distribution and in
+.\" all advertising materials mentioning features or use of this software.
+.\" Neither the name of the University nor the names of its contributors may
+.\" be used to endorse or promote products derived from this software without
+.\" specific prior written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\"	@(#)gethostbyname.3	6.12 (Berkeley) 6/23/90
+.\"
+.TH GETHOSTBYNAME 3 "June 23, 1990"
+.UC 5
+.SH NAME
+g_h_b_n, gethostbyname, gethostbyaddr, gethostent, sethostent, endhostent, herror \- get network host entry
+.SH SYNOPSIS
+.B "#include <net/gen/netdb.h>
+.PP
+.B "extern int h_errno;
+.PP
+.B "struct hostent *gethostbyname(name)
+.br
+.B "char *name;
+.PP
+.B "struct hostent *gethostbyaddr(addr, len, type)
+.br
+.B "char *addr; int len, type;
+.PP
+.B "struct hostent *gethostent()
+.PP
+.B "sethostent(stayopen)
+.br
+.B "int stayopen;
+.PP
+.B "endhostent()
+.PP
+.B "herror(string)
+.br
+.B "char *string;
+.PP
+.SH DESCRIPTION
+.I Gethostbyname
+and
+.I gethostbyaddr
+each return a pointer to an object with the
+following structure describing an internet host
+referenced by name or by address, respectively.
+This structure contains the information obtained from the name server.
+.PP
+.nf
+struct	hostent {
+	char	*h_name;	/* official name of host */
+	char	**h_aliases;	/* alias list */
+	int	h_addrtype;	/* host address type */
+	int	h_length;	/* length of address */
+	char	**h_addr_list;	/* list of addresses from name server */
+};
+#define	h_addr  h_addr_list[0]	/* address, for backward compatibility */
+.ft R
+.ad
+.fi
+.PP
+The members of this structure are:
+.TP \w'h_addr_list'u+2n
+h_name
+Official name of the host.
+.TP \w'h_addr_list'u+2n
+h_aliases
+A zero terminated array of alternate names for the host.
+.TP \w'h_addr_list'u+2n
+h_addrtype
+The type of address being returned; currently always AF_INET.
+.TP \w'h_addr_list'u+2n
+h_length
+The length, in bytes, of the address.
+.TP \w'h_addr_list'u+2n
+h_addr_list
+A zero terminated array of network addresses for the host.
+Host addresses are returned in network byte order.
+.TP \w'h_addr_list'u+2n
+h_addr
+The first address in h_addr_list; this is for backward compatiblity.
+.PP
+When using the nameserver,
+.I gethostbyname
+will search for the named host in the current domain and its parents
+unless the name ends in a dot.
+If the name contains no dot, and if the environment variable ``HOSTALAIASES''
+contains the name of an alias file, the alias file will first be searched
+for an alias matching the input name.
+See
+.IR hostname (7)
+for the domain search procedure and the alias file format.
+.PP
+.I Sethostent
+may be used to request the use of a connected TCP socket for queries.
+If the
+.I stayopen
+flag is non-zero,
+this sets the option to send all queries to the name server using TCP
+and to retain the connection after each call to 
+.I gethostbyname
+or
+.IR gethostbyaddr .
+Otherwise, queries are performed using UDP datagrams.
+.PP
+.I Endhostent
+closes the TCP connection.
+.SH DIAGNOSTICS
+.PP
+Error return status from 
+.I gethostbyname
+and
+.I gethostbyaddr
+is indicated by return of a null pointer.
+The external integer
+.IR h_errno
+may then be checked to see whether this is a temporary failure
+or an invalid or unknown host.
+The routine
+.I herror
+can be used to print an error message describing the failure.
+If its argument
+.I string
+is non-NULL, it is printed, followed by a colon and a space.
+The error message is printed with a trailing newline.
+.PP
+.IR h_errno
+can have the following values:
+.RS
+.IP HOST_NOT_FOUND \w'HOST_NOT_FOUND'u+2n
+No such host is known.
+.IP TRY_AGAIN \w'HOST_NOT_FOUND'u+2n
+This is usually a temporary error
+and means that the local server did not receive
+a response from an authoritative server.
+A retry at some later time may succeed.
+.IP NO_RECOVERY \w'HOST_NOT_FOUND'u+2n
+Some unexpected server failure was encountered.
+This is a non-recoverable error.
+.IP NO_DATA \w'HOST_NOT_FOUND'u+2n
+The requested name is valid but does not have an IP address; 
+this is not a temporary error.  
+This means that the name is known to the name server but there is no address
+associated with this name.
+Another type of request to the name server using this domain name
+will result in an answer;
+for example, a mail-forwarder may be registered for this domain.
+.RE
+.SH "SEE ALSO"
+resolver(3), hostname(7), nonamed(8), named(8)
+.SH BUGS
+All information
+is contained in a static area
+so it must be copied if it is
+to be saved.  Only the Internet
+address format is currently understood.
Index: /trunk/minix/man/man3/getc.3
===================================================================
--- /trunk/minix/man/man3/getc.3	(revision 9)
+++ /trunk/minix/man/man3/getc.3	(revision 9)
@@ -0,0 +1,79 @@
+.\"	@(#)getc.3s	6.2 (Berkeley) 5/14/86
+.\"
+.TH GETC 3  "May 14, 1986"
+.AT 3
+.SH NAME
+getc, getchar, fgetc, getw \- get character or word from stream
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdio.h>
+
+int getc(FILE *\fIstream\fP)
+int getchar(void)
+int fgetc(FILE *\fIstream\fP)
+int getw(FILE *\fIstream\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Getc
+returns the next character from the named input
+.IR stream .
+.PP
+.BR Getchar ()
+is identical to 
+.BR getc ( stdin ).
+.PP
+.B Fgetc
+behaves like 
+.BR getc ,
+but is a genuine function, not a macro;
+it may be used to save object text.
+.PP
+.B Getw
+returns the next
+.B int
+from the named input
+.IR stream .
+It returns the constant
+.SM
+.B EOF
+upon end of file or error, but since that is a good
+integer value,
+.B feof
+and
+.BR ferror (3)
+should be used to check the success of
+.BR getw .
+.B Getw
+assumes no special alignment in the file.
+.SH "SEE ALSO"
+.BR clearerr (3),
+.BR fopen (3),
+.BR putc (3),
+.BR gets (3),
+.BR scanf (3),
+.BR fread (3),
+.BR ungetc (3).
+.SH DIAGNOSTICS
+These functions return the integer constant
+.SM
+.B EOF
+at end of file, upon read error,
+or if an attempt is made to read a file not opened by
+.BR fopen .
+The end-of-file condition is remembered,
+even on a terminal,
+and all subsequent attempts to read will return
+.B EOF
+until the condition is cleared with
+.BR clearerr (3).
+.SH BUGS
+Because it is implemented as a macro,
+.B getc
+treats a
+.I stream
+argument with side effects incorrectly.
+In particular,
+`getc(*f++);'
+doesn't work sensibly.
Index: /trunk/minix/man/man3/getcwd.3
===================================================================
--- /trunk/minix/man/man3/getcwd.3	(revision 9)
+++ /trunk/minix/man/man3/getcwd.3	(revision 9)
@@ -0,0 +1,36 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)getwd.3	6.2 (Berkeley) 5/12/86
+.\"
+.TH GETCWD 3 "May 12, 1986"
+.UC 5
+.SH NAME
+getcwd \- get current working directory pathname
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+char *getcwd(char *\fIpathname\fP, size_t \fIlen\fP)
+.fi
+.SH DESCRIPTION
+.B Getcwd
+copies the absolute pathname of the current working directory to
+.I pathname
+and returns a pointer to the result.
+.I Pathname
+is a character array of length
+.IR len .
+.SH DIAGNOSTICS
+.B Getcwd
+returns a null pointer and sets
+.B errno
+if an error occurs.  The error will reflect the system call errors that
+may occur if the path to the current directory is searched upwards to
+the root directory.  The error
+.B ERANGE
+is returned if the result does not fit within
+.I len
+bytes.
Index: /trunk/minix/man/man3/getenv.3
===================================================================
--- /trunk/minix/man/man3/getenv.3	(revision 9)
+++ /trunk/minix/man/man3/getenv.3	(revision 9)
@@ -0,0 +1,29 @@
+.\"	@(#)getenv.3	6.1 (Berkeley) 5/15/85
+.\"
+.TH GETENV 3 "May 15, 1985"
+.AT 3
+.SH NAME
+getenv \- value for environment name
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdlib.h>
+
+char *getenv(const char *\fIname\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Getenv
+searches the environment list
+(see
+.BR environ (7))
+for a string of the form
+.IB name = value
+and returns a pointer to the string
+.I value
+if such a string is present, otherwise 
+.B getenv
+returns the null pointer.
+.SH SEE ALSO
+.BR environ (7),
+.BR execve (2).
Index: /trunk/minix/man/man3/getgrent.3
===================================================================
--- /trunk/minix/man/man3/getgrent.3	(revision 9)
+++ /trunk/minix/man/man3/getgrent.3	(revision 9)
@@ -0,0 +1,136 @@
+.TH GETGRENT 3
+.SH NAME
+getgrent, getgrnam, getgrgid, setgrent, endgrent, setgrfile \- group file routines
+.SH SYNOPSIS
+.ft B
+.nf
+#include <grp.h>
+
+struct group *getgrent(void)
+struct group *getgrnam(const char *\fIname\fP)
+struct group *getgrgid(gid_t \fIgid\fP)
+int setgrent(void)
+void endgrent(void)
+void setgrfile(const char *\fIfile\fP)
+.fi
+.ft P
+.SH DESCRIPTION
+These functions are used to obtain information from the group file.  They
+return this information in a
+.B struct group
+as defined by <grp.h>:
+.PP
+.nf
+.ta +4n +6n +15n
+struct group {
+	char	*gr_name;	/* login name */
+	char	*gr_passwd;	/* encrypted password */
+	gid_t	gr_gid;	/* numeric group id */
+	char	**gr_mem;	/* null-terminated list of group members */
+};
+.fi
+.PP
+.B Getgrent()
+reads the group file entry by entry.
+.B Getgrnam()
+scans the entire group file for the group with the given
+.IR name .
+.B Getgrgid()
+looks for the first group with the given
+.IR gid .
+The
+.B setgrent()
+and
+.B endgrent()
+functions are used to open and later close the group file.  With
+.B setgrfile()
+one can specify the file to read other than the normal group file.  This
+only sets the name, the next
+.B setgrent()
+call will open the file.  Do not touch the file name while it is active.
+Use
+.B setgrfile(NULL)
+to revert back to the normal group file.
+.PP
+The usual way to scan the group file is (error checking omitted):
+.PP
+.RS
+.nf
+.DT
+setgrent();
+while ((gr = getgrent()) != NULL)
+	if (appropriate_test(gr)) break;
+endgrent();
+.fi
+.RE
+.PP
+The
+.B gr
+variable contains the entry that is wanted if non-NULL.  The
+.B getgrnam()
+and
+.B getgrgid()
+functions are implemented as in this example, with error checking of course.
+.PP
+.B Getgrent()
+calls
+.B setgrent()
+if this has not yet been done.
+.B Setgrent()
+first calls
+.B endgrent()
+if the group file is still open.  (Other implementations may simply
+rewind the file.)
+.SH FILES
+.TP 15
+.B /etc/group
+The group file database.
+.SH "SEE ALSO"
+.BR getgroups (2),
+.BR initgroups (3),
+.BR getpwent (3),
+.BR passwd (5).
+.SH DIAGNOSTICS
+.B Setgrent()
+has the same return value and error codes as the
+.BR open (2)
+call it uses to open the group file.  The
+.BI get xxx ()
+functions return NULL on end of file, entry not found, or error.  You can
+set
+.B errno
+to zero before the call and check it after.
+.SH NOTES
+All
+.BI get xxx ()
+routines return a pointer to static storage that is overwritten in each call.
+.PP
+Only
+.B getgrnam()
+and
+.B getgrgid()
+are defined by \s-2POSIX\s+2.  The
+.B _MINIX_SOURCE
+macro must be defined before including <grp.h> to make the other functions
+visible.  The
+.B gr_passwd
+field is also not defined by \s-2POSIX\s+2, but is always visible.
+Portable code cannot reliably detect errors by setting
+.B errno
+to zero.  Under MINIX 3 it is better to make a
+.B getgrent()
+scan if you need to look up several group-id's or names, but portable code
+had better use several
+.B getgrgid()
+or
+.B getgrnam()
+calls.  The
+.B getgrent()
+is usually available on other systems, but may be very expensive.  See
+.BR initgroups (3)
+if you are after supplementary group id's.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+
+.\"
+.\" $PchId: getgrent.3,v 1.2 1996/04/11 06:35:01 philip Exp $
Index: /trunk/minix/man/man3/getloadavg.3
===================================================================
--- /trunk/minix/man/man3/getloadavg.3	(revision 9)
+++ /trunk/minix/man/man3/getloadavg.3	(revision 9)
@@ -0,0 +1,36 @@
+.\"	@(#)getloadavg.3
+.\"
+.TH GETLOADAVG 3 "Nov 14, 2005"
+.AT 3
+.SH NAME
+getloadavg \- system load average values
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdlib.h>
+
+int getloadavg(double *\fIaverages\fP, int \fInelem\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Getloadavg
+returns the system load average values as elements of 
+.IR averages
+up to
+a maximum of 
+.IR nelem
+elements.
+The system load average is the average number of
+runnable processes over a certain period. Currently the averages are
+delivered over the last 1, 5 and 15 minutes of system usage. So 
+currently the system maximum is 3.
+.SH RETURNS
+The returned value  of
+.B getloadavg
+is zero or more if the call was successful, or a negative value if the
+call was unsuccessful. If the call was successful, the number of
+elements entered into
+.IR averages
+is returned. 
+.SH SEE ALSO
+.BR uptime (1).
Index: /trunk/minix/man/man3/getlogin.3
===================================================================
--- /trunk/minix/man/man3/getlogin.3	(revision 9)
+++ /trunk/minix/man/man3/getlogin.3	(revision 9)
@@ -0,0 +1,45 @@
+.\"	@(#)getlogin.3	6.2 (Berkeley) 5/9/86
+.\"
+.TH GETLOGIN 3  "May 9, 1986"
+.AT 3
+.SH NAME
+getlogin \- get login name
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+char *getlogin(void)
+.fi
+.SH DESCRIPTION
+.B Getlogin
+returns a pointer to the login name as found in
+.BR /etc/utmp .
+It may be used in conjunction with
+.B getpwnam
+to locate the correct password file entry when the same user ID
+is shared by several login names.
+.PP
+If
+.B getlogin
+is called within a process that is not attached to a
+terminal, or if there is no entry in
+.B /etc/utmp
+for the process's terminal,
+.B getlogin
+returns a null pointer.
+A reasonable procedure for determining the login name is to first call
+.B getlogin
+and if it fails, to call
+.BR getpwuid ( getuid ()).
+.SH FILES
+/etc/utmp
+.SH "SEE ALSO"
+.BR getpwent (3),
+.BR utmp (5),
+.BR ttyslot (3)
+.SH DIAGNOSTICS
+Returns a null pointer if the name cannot be found.
+.SH BUGS
+The return values point to static data
+whose content is overwritten by each call.
Index: /trunk/minix/man/man3/getopt.3
===================================================================
--- /trunk/minix/man/man3/getopt.3	(revision 9)
+++ /trunk/minix/man/man3/getopt.3	(revision 9)
@@ -0,0 +1,150 @@
+.\" Copyright (c) 1985 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)getopt.3	6.4 (Berkeley) 5/27/86
+.\"
+.TH GETOPT 3 "May 27, 1986"
+.UC 6
+.SH NAME
+getopt \- get option letter from argv
+.SH SYNOPSIS
+.ft B
+int getopt(argc, argv, optstring)
+.br
+int argc;
+.br
+char **argv;
+.br
+char *optstring;
+.sp
+extern char *optarg;
+.br
+extern int optind;
+.ft
+.SH DESCRIPTION
+.I Getopt
+returns the next option letter in
+.I argv
+that matches a letter in
+.IR optstring .
+.I Optstring
+is a string of recognized option letters;
+if a letter is followed by a colon, the option is expected to have
+an argument that may or may not be separated from it by white space.
+.I Optarg
+is set to point to the start of the option argument on return from
+.IR getopt .
+.PP
+.I Getopt
+places in
+.I optind
+the
+.I argv
+index of the next argument to be processed.
+Because
+.I optind
+is external, it is normally initialized to zero automatically
+before the first call to 
+.IR getopt .
+.PP
+When all options have been processed (i.e., up to the first
+non-option argument),
+.I getopt
+returns
+.BR EOF .
+The special option
+.B \-\-
+may be used to delimit the end of the options;
+.B EOF
+will be returned, and
+.B \-\-
+will be skipped.
+.SH DIAGNOSTICS
+.I Getopt
+prints an error message on
+.I stderr
+and returns a question mark
+.RB ( ? )
+when it encounters an option letter not included in
+.IR optstring .
+.SH EXAMPLE
+The following code fragment shows how one might process the arguments
+for a command that can take the mutually exclusive options
+.B a
+and
+.BR b ,
+and the options
+.B f
+and
+.BR o ,
+both of which require arguments:
+.PP
+.RS
+.nf
+main(argc, argv)
+int argc;
+char **argv;
+{
+	int c;
+	extern int optind;
+	extern char *optarg;
+	\&.
+	\&.
+	\&.
+	while ((c = getopt(argc, argv, "abf:o:")) != EOF)
+		switch (c) {
+		case `a':
+			if (bflg)
+				errflg++;
+			else
+				aflg++;
+			break;
+		case `b':
+			if (aflg)
+				errflg++;
+			else
+				bproc();
+			break;
+		case `f':
+			ifile = optarg;
+			break;
+		case `o':
+			ofile = optarg;
+			break;
+		case `?':
+		default:
+			errflg++;
+			break;
+		}
+	if (errflg) {
+		fprintf(stderr, "Usage: ...");
+		exit(2);
+	}
+	for (; optind < argc; optind++) {
+		\&.
+		\&.
+		\&.
+	}
+	\&.
+	\&.
+	\&.
+}
+.RE
+.SH HISTORY
+Written by Henry Spencer, working from a Bell Labs manual page.
+Modified by Keith Bostic to behave more like the System V version.
+.SH BUGS
+It is not obvious how
+`\-'
+standing alone should be treated;  this version treats it as
+a non-option argument, which is not always right.
+.PP
+Option arguments are allowed to begin with `\-';
+this is reasonable but reduces the amount of error checking possible.
+.PP
+.I Getopt
+is quite flexible but the obvious price must be paid:  there is much
+it could do that it doesn't, like
+checking mutually exclusive options, checking type of
+option arguments, etc.
Index: /trunk/minix/man/man3/getpass.3
===================================================================
--- /trunk/minix/man/man3/getpass.3	(revision 9)
+++ /trunk/minix/man/man3/getpass.3	(revision 9)
@@ -0,0 +1,28 @@
+.\"	@(#)getpass.3	6.1 (Berkeley) 5/15/85
+.\"
+.TH GETPASS 3  "May 15, 1985"
+.AT 3
+.SH NAME
+getpass \- read a password
+.SH SYNOPSIS
+.nf
+.ft B
+#include <minix/minlib.h>
+
+char *getpass(const char *\fIprompt\fP)
+.fi
+.SH DESCRIPTION
+.B Getpass
+reads a password from the file
+.BR /dev/tty ,
+or if that cannot be opened, from the standard input,
+after prompting with the null-terminated string
+.I prompt
+and disabling echoing.
+A pointer is returned to a null-terminated string
+of at most 32 characters, excluding the null.
+.SH "SEE ALSO"
+.BR crypt (3).
+.SH BUGS
+The return value points to static data
+whose content is overwritten by each call.
Index: /trunk/minix/man/man3/getpwent.3
===================================================================
--- /trunk/minix/man/man3/getpwent.3	(revision 9)
+++ /trunk/minix/man/man3/getpwent.3	(revision 9)
@@ -0,0 +1,139 @@
+.TH GETPWENT 3
+.SH NAME
+getpwent, getpwnam, getpwuid, setpwent, endpwent, setpwfile \- password file routines
+.SH SYNOPSIS
+.ft B
+.nf
+#include <pwd.h>
+
+struct passwd *getpwent(void)
+struct passwd *getpwnam(const char *\fIname\fP)
+struct passwd *getpwuid(uid_t \fIuid\fP)
+int setpwent(void)
+void endpwent(void)
+void setpwfile(const char *\fIfile\fP)
+.fi
+.ft P
+.SH DESCRIPTION
+These functions are used to obtain information from the password file.  They
+return this information in a
+.B struct passwd
+as defined by <pwd.h>:
+.PP
+.nf
+.ta +4n +6n +15n
+struct passwd {
+	char	*pw_name;	/* login name */
+	char	*pw_passwd;	/* encrypted password */
+	uid_t	pw_uid;	/* numeric user id */
+	gid_t	pw_gid;	/* numeric group id */
+	char	*pw_gecos;	/* user full name and other info */
+	char	*pw_dir;	/* user's home directory */
+	char	*pw_shell;	/* name of the user's shell */
+};
+.fi
+.PP
+.B Getpwent()
+reads the password file entry by entry.
+.B Getpwnam()
+scans the entire password file for the user with the given
+.IR name .
+.B Getpwuid()
+looks for the first user with the given
+.IR uid .
+The
+.B setpwent()
+and
+.B endpwent()
+functions are used to open and later close the password file.  With
+.B setpwfile()
+one can specify the file to read other than the normal password file.  This
+only sets the name, the next
+.B setpwent()
+call will open the file.  Do not touch the file name while it is active.
+Use
+.B setpwfile(NULL)
+to revert back to the normal password file.
+.PP
+The usual way to scan the password file is (error checking omitted):
+.PP
+.RS
+.nf
+.DT
+setpwent();
+while ((pw = getpwent()) != NULL)
+	if (appropriate_test(pw)) break;
+endpwent();
+.fi
+.RE
+.PP
+The
+.B pw
+variable contains the entry that is wanted if non-NULL.  The
+.B getpwnam()
+and
+.B getpwuid()
+functions are implemented as in this example, with error checking of course.
+.PP
+.B Getpwent()
+calls
+.B setpwent()
+if this has not yet been done.
+.B Setpwent()
+first calls
+.B endpwent()
+if the password file is still open.  (Other implementations may simply
+rewind the file.)
+.SH FILES
+.TP 15
+.B /etc/passwd
+The password file database.
+.SH "SEE ALSO"
+.BR cuserid (3),
+.BR getlogin (3),
+.BR getgrent (3),
+.BR passwd (5).
+.SH DIAGNOSTICS
+.B Setpwent()
+has the same return value and error codes as the
+.BR open (2)
+call it uses to open the password file.  The
+.BI get xxx ()
+functions return NULL on end of file, entry not found, or error.  You can
+set
+.B errno
+to zero before the call and check it after.
+.SH NOTES
+All
+.BI get xxx ()
+routines return a pointer to static storage that is overwritten in each call.
+.PP
+Only
+.B getpwnam()
+and
+.B getpwuid()
+are defined by \s-2POSIX\s+2.  The
+.B _MINIX_SOURCE
+macro must be defined before including <pwd.h> to make the other functions
+visible.  The
+.B pw_passwd
+and
+.B pw_gecos
+fields are also not defined by \s-2POSIX\s+2, but are always visible.
+Portable code cannot reliably detect errors by setting
+.B errno
+to zero.  Under MINIX 3 it is better to make a
+.B getpwent()
+scan if you need to look up several user-id's or names, but portable code
+had better use several
+.B getpwuid()
+or
+.B getpwnam()
+calls.  The
+.B getpwent()
+is usually available on other systems, but may be very expensive.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+
+.\"
+.\" $PchId: getpwent.3,v 1.2 1996/04/11 06:37:43 philip Exp $
Index: /trunk/minix/man/man3/gets.3
===================================================================
--- /trunk/minix/man/man3/gets.3	(revision 9)
+++ /trunk/minix/man/man3/gets.3	(revision 9)
@@ -0,0 +1,68 @@
+.\"	@(#)gets.3s	6.1 (Berkeley) 5/15/85
+.\"
+.TH GETS 3  "May 15, 1985"
+.AT 3
+.SH NAME
+gets, fgets \- get a string from a stream
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdio.h>
+
+char *gets(char *\fIs\fP)
+char *fgets(char *\fIs\fP, int \fIn\fP, FILE *\fIstream\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Gets
+reads a string into
+.I s
+from the standard input stream
+.BR stdin .
+The string is terminated by a newline
+character, which is replaced in
+.I s
+by a null character.
+.B Gets
+returns its argument.
+.PP
+.B Fgets
+reads 
+.IR n \-1
+characters, or up through a newline
+character, whichever comes first,
+from the
+.I stream
+into the string
+.IR s .
+The last character read into
+.I s
+is followed by a null character.
+.B Fgets
+returns its first argument.
+.SH "SEE ALSO"
+.BR puts (3),
+.BR getc (3),
+.BR scanf (3),
+.BR fread (3),
+.BR ferror (3).
+.SH DIAGNOSTICS
+.B Gets
+and
+.B fgets
+return the constant pointer 
+.SM
+.B NULL
+upon end of file or error.
+.SH BUGS
+.B Gets
+deletes a newline,
+.B fgets
+keeps it,
+all in the name of backward compatibility.
+.PP
+.B Gets
+is not present in the Minix-vmd C library for reasons that should be obvious.
+Use
+.B fgets
+instead.
Index: /trunk/minix/man/man3/getservent.3
===================================================================
--- /trunk/minix/man/man3/getservent.3	(revision 9)
+++ /trunk/minix/man/man3/getservent.3	(revision 9)
@@ -0,0 +1,112 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)getservent.3n	6.3 (Berkeley) 5/19/86
+.\"
+.TH GETSERVENT 3 "May 19, 1986"
+.UC 5
+.SH NAME
+getservent, getservbyport, getservbyname, setservent, endservent \- get service entry
+.SH SYNOPSIS
+.nf
+.ft B
+#include <netdb.h>
+.PP
+.ft B
+struct servent *getservent()
+.PP
+.ft B
+struct servent *getservbyname(name, proto)
+char *name, *proto;
+.PP
+.ft B
+struct servent *getservbyport(port, proto)
+int port; char *proto;
+.PP
+.ft B
+setservent(stayopen)
+int stayopen
+.PP
+.ft B
+endservent()
+.fi
+.SH DESCRIPTION
+.IR Getservent ,
+.IR getservbyname ,
+and
+.I getservbyport
+each return a pointer to an object with the
+following structure
+containing the broken-out
+fields of a line in the network services data base,
+.IR /etc/services .
+.RS
+.PP
+.nf
+struct	servent {
+	char	*s_name;	/* official name of service */
+	char	**s_aliases;	/* alias list */
+	int	s_port;		/* port service resides at */
+	char	*s_proto;	/* protocol to use */
+};
+.ft R
+.ad
+.fi
+.RE
+.PP
+The members of this structure are:
+.TP \w's_aliases'u+2n
+s_name
+The official name of the service.
+.TP \w's_aliases'u+2n
+s_aliases
+A zero terminated list of alternate names for the service.
+.TP \w's_aliases'u+2n
+s_port
+The port number at which the service resides.
+Port numbers are returned in network byte order.
+.TP \w's_aliases'u+2n
+s_proto
+The name of the protocol to use when contacting the
+service.
+.PP
+.I Getservent
+reads the next line of the file, opening the file if necessary.
+.PP
+.I Setservent
+opens and rewinds the file.  If the
+.I stayopen
+flag is non-zero,
+the net data base will not be closed after each call to 
+.I getservbyname
+or
+.IR getservbyport .
+.PP
+.I Endservent
+closes the file.
+.PP
+.I Getservbyname
+and
+.I getservbyport
+sequentially search from the beginning
+of the file until a matching
+protocol name or
+port number is found,
+or until EOF is encountered.
+If a protocol name is also supplied (non-NULL),
+searches must also match the protocol.
+.SH FILES
+/etc/services
+.SH "SEE ALSO"
+getprotoent(3), services(5)
+.SH DIAGNOSTICS
+Null pointer
+(0) returned on EOF or error.
+.SH BUGS
+All information
+is contained in a static area
+so it must be copied if it is
+to be saved.  Expecting port
+numbers to fit in a 32 bit
+quantity is probably naive.
Index: /trunk/minix/man/man3/getttyent.3
===================================================================
--- /trunk/minix/man/man3/getttyent.3	(revision 9)
+++ /trunk/minix/man/man3/getttyent.3	(revision 9)
@@ -0,0 +1,107 @@
+.TH GETTTYENT 3
+.SH NAME
+getttyent, getttynam, setttyent, endttyent \- interface to /etc/ttytab
+.SH SYNOPSIS
+.ft B
+.nf
+#include <ttyent.h>
+
+struct ttyent *getttyent(void)
+struct ttyent *getttynam(const char *\fIname\fP)
+int setttyent(void)
+void endttyent(void)
+.fi
+.ft P
+.SH DESCRIPTION
+The
+.B getttyent
+functions provide an interface to the /etc/ttytab.  (See
+.BR ttytab (5)).
+.PP
+To read one of these files one calls
+.B getttyent()
+several times to read the entries in the table until NULL is returned for
+end-of-file.
+.PP
+.B Getttyname()
+searches the
+.B ttytab
+file for the given terminal device.  It is equivalent to a call to
+.BR setttyent(),
+several calls to
+.B getttyent()
+to locate the entry, and a final
+.B endttyent()
+to close the file.
+.PP
+.B Setttyent()
+opens or rewinds the ttytab database, and
+.B endttyent() closes it.
+.B Getttyent()
+opens the database if not already open, but does not close it.
+.PP
+The struct ttyent is defined by <ttyent.h> as follows:
+.sp
+.nf
+.ta +4n +6n +15n
+struct ttyent {
+	char	*ty_name;	/* Name of the terminal device. */
+	char	*ty_type;	/* Terminal type name (termcap(3)). */
+	char	**ty_getty;	/* Program to run, normally getty. */
+	char	**ty_init;	/* Initialization command, normally stty. */
+};
+.fi
+.PP
+A valid entry has at least two strings, so both
+.B ty_name
+and
+.B ty_type
+are filled in.  The optional
+.B ty_getty
+and
+.B ty_init
+may be NULL (field omitted), point to a pointer that is NULL (null lenght
+field, i.e. ""), or an array of strings terminated by a NULL (field
+present).  For now no useful distinction can be made between a omitted field
+and an empty field, so treat both cases as an omission.
+.SH FILES
+.TP 15
+.B /etc/ttytab
+The terminal device database
+.SH "SEE ALSO"
+.BR ttyname (3),
+.BR ttyslot (3),
+.BR ttytab (5),
+.BR init (8).
+.SH DIAGNOSTICS
+.B Setttyent()
+has the same return value and error codes as the
+.BR open (2)
+call it uses to open the ttytab file.  The
+.BI get xxx ()
+functions return NULL on end of file, entry not found, or error.  You can
+set
+.B errno
+to zero before the call and check it after.
+.SH NOTES
+.B Getttyent()
+and
+.B getttynam()
+return a pointer to static storage that is overwritten in each call.
+.PP
+The MINIX 3
+.B struct ttyent
+has only the
+.B ty_name
+and
+.B ty_type
+fields in common with the BSD implementation.  This does not seem to be a
+problem, because most third party software that need to know about terminals
+only look at the
+.B ty_name
+field.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+
+.\"
+.\" $PchId: getttyent.3,v 1.2 1996/04/11 06:57:26 philip Exp $
Index: /trunk/minix/man/man3/hton.3
===================================================================
--- /trunk/minix/man/man3/hton.3	(revision 9)
+++ /trunk/minix/man/man3/hton.3	(revision 9)
@@ -0,0 +1,60 @@
+.TH HTON 3
+.SH NAME
+hton, htons, htonl, ntohs, ntohl \- host to network byte order conversion
+.SH SYNOPSIS
+.ft B
+.nf
+#define _MINIX_SOURCE 1
+#include <stddef.h>
+#include <sys/types.h>
+
+#include <net/hton.h>
+
+u16_t htons(u16_t \fIhost_word\fP)
+u32_t htonl(u32_t \fIhost_dword\fP)
+u16_t ntohs(u16_t \fInetwork_word\fP)
+u32_t ntohl(u32_t \fInetwork_dword\fP)
+u16_t HTONS(u16_t \fIhost_word\fP)
+u32_t HTONL(u32_t \fIhost_dword\fP)
+u16_t NTOHS(u16_t \fInetwork_word\fP)
+u32_t NTOHL(u32_t \fInetwork_dword\fP)
+.fi
+.ft R
+.SH DESCRIPTION
+These macros convert 16-bit and 32-bit quantities to and from the network
+byte order used by the TCP/IP protocols.
+The function of the macros is encoded in their name.
+.B H
+means host byte order,
+.B n
+means network byte order,
+.B s
+means a 16-bit quantity and
+.B l
+means a 32-bit quantity.
+Thus
+.B htons
+converts a 16-bit quantity from host byte order to network byte order.
+The difference between the lower case and upper case variants is that
+the lower case variants evaluate the argument at most once and the
+upper case variants can be used for constant folding.
+That is,
+.PP
+.RS
+htonl(f(x))
+.RE
+.PP
+will call f(x) at most once and
+.PP
+.RS
+HTONS(0x10)
+.RE
+.PP
+will be equivalent to 0x10 on a big-endian machine and 0x1000 on a
+little-endian machine.
+.SH "SEE ALSO"
+.BR ip (4).
+.SH AUTHOR
+Philip Homburg (philip@cs.vu.nl)
+.\"
+.\" $PchId: hton.3,v 1.3 1996/02/22 21:10:01 philip Exp $
Index: /trunk/minix/man/man3/int64.3
===================================================================
--- /trunk/minix/man/man3/int64.3	(revision 9)
+++ /trunk/minix/man/man3/int64.3	(revision 9)
@@ -0,0 +1,193 @@
+.TH INT64 3
+.SH NAME
+int64, add64, add64u, add64ul, sub64, sub64u, sub64ul, diff64, cvu64, cvul64, cv64u, cv64ul, div64u, rem64u, mul64u, cmp64, cmp64u, cmp64ul, ex64lo, ex64hi, make64 \- 64 bit disk offset computations
+.SH SYNOPSIS
+.ft B
+.nf
+#include <minix/u64.h>
+
+u64_t add64(u64_t \fIi\fP, u64_t \fIj\fP)
+u64_t add64u(u64_t \fIi\fP, unsigned \fIj\fP)
+u64_t add64ul(u64_t \fIi\fP, unsigned long \fIj\fP)
+u64_t sub64(u64_t \fIi\fP, u64_t \fIj\fP)
+u64_t sub64u(u64_t \fIi\fP, unsigned \fIj\fP)
+u64_t sub64ul(u64_t \fIi\fP, unsigned long \fIj\fP)
+unsigned diff64(u64_t \fIi\fP, u64_t \fIj\fP)
+u64_t cvu64(unsigned \fIi\fP)
+u64_t cvul64(unsigned long \fIi\fP)
+unsigned cv64u(u64_t \fIi\fP)
+unsigned long cv64ul(u64_t \fIi\fP)
+unsigned long div64u(u64_t \fIi\fP, unsigned \fIj\fP)
+unsigned rem64u(u64_t \fIi\fP, unsigned \fIj\fP)
+u64_t mul64u(unsigned long \fIi\fP, unsigned \fIj\fP)
+int cmp64(u64_t \fIi\fP, u64_t \fIj\fP)
+int cmp64u(u64_t \fIi\fP, unsigned \fIj\fP)
+int cmp64ul(u64_t \fIi\fP, unsigned long \fIj\fP)
+unsigned long ex64lo(u64_t \fIi\fP)
+unsigned long ex64hi(u64_t \fIi\fP)
+u64_t make64(unsigned long \fIlo\fP, unsigned long \fIhi\fP)
+.fi
+.ft P
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+The
+.B int64
+family of functions allow MINIX 3 to handle disks of up to 4 terabytes using
+32 bit sector numbers and 64 bit byte offsets on a machine where the C type
+.B long
+is 32 bits.  The <minix/u64.h> include file defines a 64 bit data
+type,
+.BR u64_t ,
+and a number of functions to operate on them.  Note that these functions are
+geared towards common disk offset and block computations, and do not provide
+a full set of 64 bit operations.  They are:
+.PP
+.TP
+.B "u64_t add64(u64_t \fIi\fP, u64_t \fIj\fP)"
+Add the 64 bit numbers
+.I i
+and
+.I j
+forming a 64 bit result.
+.TP
+.B "u64_t add64u(u64_t \fIi\fP, unsigned \fIj\fP)"
+Add an unsigned
+.I j
+to a 64 bit number
+.I i
+forming a 64 bit result.
+.TP
+.B "u64_t add64ul(u64_t \fIi\fP, unsigned long \fIj\fP)"
+Add an unsigned long
+.I j
+to a 64 bit number
+.I i
+forming a 64 bit result.
+.TP
+.B "u64_t sub64(u64_t \fIi\fP, u64_t \fIj\fP)"
+Subtract the 64 bit number
+.I j
+from the 64 bit number
+.I i
+forming a 64 bit result.
+.TP
+.B "u64_t sub64u(u64_t \fIi\fP, unsigned \fIj\fP)"
+Subtract the unsigned
+.I j
+from the 64 bit number
+.I i
+forming a 64 bit result.
+.TP
+.B "u64_t sub64ul(u64_t \fIi\fP, unsigned long \fIj\fP)"
+Subtract the unsigned long
+.I j
+from the 64 bit number
+.I i
+forming a 64 bit result.
+.TP
+.B "unsigned diff64(u64_t \fIi\fP, u64_t \fIj\fP)"
+Subtract the 64 bit number
+.I j
+from the 64 bit number
+.I i
+forming an unsigned.  Overflow is not checked.
+.TP
+.B "u64_t cvu64(unsigned \fIi\fP)"
+Convert an unsigned to a 64 bit number.
+.TP
+.B "u64_t cvul64(unsigned long \fIi\fP)"
+Convert an unsigned long to a 64 bit number.
+.TP
+.B "unsigned cv64u(u64_t \fIi\fP)"
+Convert a 64 bit number to an unsigned if it fits, otherwise return
+.BR UINT_MAX .
+.TP
+.B "unsigned long cv64ul(u64_t \fIi\fP)"
+Convert a 64 bit number to an unsigned long if it fits, otherwise return
+.BR ULONG_MAX .
+.TP
+.B "unsigned long div64u(u64_t \fIi\fP, unsigned \fIj\fP)"
+Divide the 64 bit number
+.I i
+by the unsigned
+.I j
+giving an unsigned long.  Overflow is not checked.  (Typical "byte offset to
+block number" conversion.)
+.TP
+.B "unsigned rem64u(u64_t \fIi\fP, unsigned \fIj\fP)"
+Compute the remainder of the division of the 64 bit number
+.I i
+by the unsigned
+.I j
+as an unsigned.  (Typical "byte offset within a block" computation.)
+.TP
+.B "u64_t mul64u(unsigned long \fIi\fP, unsigned \fIj\fP)"
+Multiply the unsigned long
+.I i
+by the unsigned
+.I j
+giving a 64 bit number.  (Typical "block number to byte offset" conversion.)
+.TP
+.B "int cmp64(u64_t \fIi\fP, u64_t \fIj\fP)"
+Compare two 64 bit numbers.
+Returns
+.B -1
+if
+.I i
+<
+.IR j ,
+.B 0
+if
+.I i
+==
+.IR j ,
+and
+.B 1
+if
+.I i
+>
+.IR j .
+.TP
+.B "int cmp64u(u64_t \fIi\fP, unsigned \fIj\fP)"
+Likewise compare a 64 bit number with an unsigned.
+.TP
+.B "int cmp64ul(u64_t \fIi\fP, unsigned long \fIj\fP)"
+Likewise compare a 64 bit number with an unsigned long.
+.TP
+.B "unsigned long ex64lo(u64_t \fIi\fP)"
+Extract the low 32 bits of a 64 bit number.
+.TP
+.B "unsigned long ex64hi(u64_t \fIi\fP)"
+Extract the high 32 bits of a 64 bit number.
+.TP
+.B "u64_t make64(unsigned long \fIlo\fP, unsigned long \fIhi\fP)"
+Combine the low and high parts of a 64 bit number to a 64 bit number.  (The
+last three functions are used to pass 64 bit numbers in messages within the
+kernel.  They should not be used for anything else.)
+.SH "SEE ALSO"
+.BR fcntl (2),
+.BR controller (4).
+.SH NOTES
+With the usual disk block size of 512 bytes the maximum disk size is 512
+\(** 4 gigabytes = 2 terabytes.
+.PP
+Standard MINIX 3 only uses 64 bit computations within the disk drivers, so
+individual partitions are still limited to 4 gigabytes.  Minix-vmd has 64
+bit computations also in the file system code.
+.PP
+Special care must be taken when accessing disk devices.  For MINIX 3 one may
+have to temporarily change the start of the partition to go beyond 4 G.
+Minix-vmd can go beyond 4 G, but the
+.B lseek
+system call is still limited to a 32 bit offset.  One needs to use
+.PP
+.RS
+.BI "fcntl(" fd ", F_SEEK, u64_t " offset ")"
+.RE
+.PP
+to seek to a 64 bit position.
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man3/malloc.3
===================================================================
--- /trunk/minix/man/man3/malloc.3	(revision 9)
+++ /trunk/minix/man/man3/malloc.3	(revision 9)
@@ -0,0 +1,117 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)malloc.3	6.3 (Berkeley) 5/14/86
+.\"
+.TH MALLOC 3  "May 14, 1986"
+.UC 4
+.SH NAME
+malloc, free, realloc, calloc, alloca \- memory allocator
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <stdlib.h>
+#include <alloca.h>
+
+void *malloc(size_t \fIsize\fP)
+void free(void *\fIptr\fP)
+void *realloc(void *\fIptr\fP, size_t \fIsize\fP)
+void *calloc(size_t \fInelem\fP, size_t \fIelsize\fP)
+void *alloca(size_t \fIsize\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Malloc
+and
+.B free
+provide a general-purpose memory allocation package.
+.B Malloc
+returns a pointer to a block of at least
+.I size
+bytes beginning on a word boundary.
+.PP
+The argument to
+.B free
+is a pointer to a block previously allocated by
+.BR malloc ;
+this space is made available for further allocation,
+but its contents are left undisturbed.
+A call with a null
+.I ptr
+is legal and does nothing.
+.PP
+Needless to say, grave disorder will result if the space assigned by
+.B malloc
+is overrun or if some random number is handed to
+.BR free .
+.PP
+.B Malloc
+maintains multiple lists of free blocks according to size,
+allocating space from the appropriate list.
+It calls
+.B sbrk
+(see
+.BR brk (2))
+to get more memory from the system when there is no
+suitable space already free.
+.PP
+.B Realloc
+changes the size of the block pointed to by
+.I ptr
+to
+.I size
+bytes and returns a pointer to the (possibly moved) block.
+The contents will be unchanged up to the lesser of the new and old sizes.
+A call with a null
+.I ptr
+is legal and has the same result as
+.BI malloc( size )\fR.
+.PP
+.B Calloc
+allocates space for an array of
+.I nelem
+elements of size
+.I elsize.
+The space is initialized to zeros.
+.PP
+.B Alloca
+allocates 
+.I size
+bytes of space in the stack frame of the caller.
+This temporary space is automatically freed on
+return.
+.PP
+Each of the allocation routines returns a pointer
+to space suitably aligned (after possible pointer coercion)
+for storage of any type of object.
+.SH SEE ALSO
+.BR brk (2).
+.SH DIAGNOSTICS
+.BR Malloc ,
+.BR realloc
+and
+.B calloc
+return a null pointer if there is no available memory or if the arena
+has been detectably corrupted by storing outside the bounds of a block.
+.SH NOTES
+Other implementations of
+.BR malloc ,
+.BR realloc
+or
+.BR calloc
+may return a null pointer if the size of the requested block is zero.  This
+implementation will always return a zero length block at a unique address,
+but you should keep in mind that a null return is possible if the program
+is run to another system and that this should not be mistakenly seen as
+an error.
+.SH BUGS
+When
+.B realloc
+returns a null pointer, the block pointed to by
+.I ptr
+may be destroyed.
+.PP
+.B Alloca
+is machine dependent; its use is discouraged.
Index: /trunk/minix/man/man3/oneC_sum.3
===================================================================
--- /trunk/minix/man/man3/oneC_sum.3	(revision 9)
+++ /trunk/minix/man/man3/oneC_sum.3	(revision 9)
@@ -0,0 +1,45 @@
+.TH ONEC_SUM 3
+.SH NAME
+oneC_sum \- One's complement internet checksum
+.SH SYNOPSIS
+.ft B
+.nf
+#define _MINIX_SOURCE 1
+#include <stddef.h>
+#include <sys/types.h>
+
+#include <net/gen/oneCsum.h>
+
+u16_t oneC_sum(u16_t \fIprev\fP, void *\fIdata\fP, size_t \fIsize\fP)
+.fi
+.ft R
+.SH DESCRIPTION
+.B OneC_sum
+is used to calculate the one's complement checksum needed for IP network
+packets.
+A good document about the Internet Checksum is RFC-1071 (Computing the
+Internet checksum).
+.PP
+.B OneC_sum
+expects three parameters:
+.TP 10
+.I prev
+The checksum of previous blocks of data that are to be included in the
+checksum.
+The value of prev in first call to oneC_sum should be 0.
+.TP
+.I data
+A pointer to the block of data.
+The data is interpreted as a series of 16 bit numbers in network byte order, but
+an odd number of bytes is also allowed.
+.TP
+.I size
+The size of the data in bytes.
+.SH "SEE ALSO"
+.BR ip (4).
+.br
+.B RFC-1071
+.SH AUTHOR
+Philip Homburg (philip@cs.vu.nl)
+.\"
+.\" $PchId: oneC_sum.3,v 1.3 1996/02/22 21:05:31 philip Exp $
Index: /trunk/minix/man/man3/openpty.3
===================================================================
--- /trunk/minix/man/man3/openpty.3	(revision 9)
+++ /trunk/minix/man/man3/openpty.3	(revision 9)
@@ -0,0 +1,18 @@
+.TH OPENPTY 3 "May 15, 1985"
+.AT 3
+.SH NAME
+openpty \- library call to obtain a pty
+.SH SYNOPSIS
+.nf
+.ft B
+#include <libutil.h>
+
+int openpty(int *\fIamaster\fP, int *\fIaslave\fP, char *\fIname\fP, struct termios *\fItermp\fP, struct winsize *\fIwinp\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Openpty
+tries to obtain pty file descriptors by opening /dev/ttypX and
+/dev/ptypX, setting *\fIamaster\fP and *\fIaslave\fP to these fd's,
+changing ownership of the slave pty to the current process, and making
+it only group-writable by group tty.
Index: /trunk/minix/man/man3/popen.3
===================================================================
--- /trunk/minix/man/man3/popen.3	(revision 9)
+++ /trunk/minix/man/man3/popen.3	(revision 9)
@@ -0,0 +1,51 @@
+.\"	@(#)popen.3	6.1 (Berkeley) 5/15/85
+.\"
+.TH POPEN 3 "May 15, 1985"
+.AT 3
+.SH NAME
+popen, pclose \- initiate I/O to/from a process
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdio.h>
+
+FILE *popen(const char *command, const char *type)
+int pclose(FILE *stream)
+.SH DESCRIPTION
+The arguments to 
+.B popen
+are pointers to null-terminated strings containing respectively a
+shell command line and an I/O mode, either "r" for reading or "w" for
+writing.  It creates a pipe between the calling process and
+the command to be executed.  The value returned is a stream pointer that
+can be used (as appropriate) to write to the standard input
+of the command or read from its standard output.
+.PP
+A stream opened by
+.B popen
+should be closed by
+.BR pclose ,
+which waits for the associated process to terminate
+and returns the exit status of the command.
+.PP
+Because open files are shared, a type "r" command may be used as an input
+filter, and a type "w" as an output filter.
+.SH "SEE ALSO"
+.BR pipe (2),
+.BR fopen (3),
+.BR fclose (3),
+.BR system (3),
+.BR wait (2),
+.BR sh (1).
+.SH DIAGNOSTICS
+.B Popen
+returns a null pointer if files or processes cannot be created, or the shell 
+cannot be accessed.
+.SH BUGS
+Buffered reading before opening an input filter
+may leave the standard input of that filter mispositioned.
+Similar problems with an output filter may be
+forestalled by careful buffer flushing, for instance, with
+.BR fflush ,
+see
+.BR fclose (3).
Index: /trunk/minix/man/man3/printf.3
===================================================================
--- /trunk/minix/man/man3/printf.3	(revision 9)
+++ /trunk/minix/man/man3/printf.3	(revision 9)
@@ -0,0 +1,264 @@
+.\"	@(#)printf.3s	6.3 (Berkeley) 6/5/86
+.\"
+.TH PRINTF 3 "June 5, 1986"
+.AT 3
+.SH NAME
+printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf \- formatted output conversion
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+int printf(const char *\fIformat\fP \fR[\fP, \fIarg\fP\fR] ...\fP);
+int fprintf(FILE *\fIstream\fP, const char *\fIformat\fP \fR[\fP, \fIarg\fP\fR] ...\fP);
+int sprintf(char *\fIs\fP, const char *\fIformat\fP \fR[\fP, \fIarg\fP\fR] ...\fP);
+int snprintf(char *\fIs\fP, size_t \fIn\fP, const char *\fIformat\fP \fR[\fP, \fIarg\fP\fR] ...\fP);
+int vprintf(const char *\fIformat\fP, va_list \fIargs\fP);
+int vfprintf(FILE *\fIstream\fP, const char *\fIformat\fP, va_list \fIargs\fP);
+int vsprintf(char *\fIs\fP, const char *\fIformat\fP, va_list \fIargs\fP);
+int vsnprintf(char *\fIs\fP, size_t \fIn\fP, const char *\fIformat\fP, va_list \fIargs\fP);
+.ft R
+.fi
+.SH DESCRIPTION
+.B Printf
+places output on the standard output stream
+.BR stdout .
+.B Fprintf
+places output on the named output
+.IR stream .
+.B Sprintf
+places `output' in the string
+.IR s ,
+followed by the character `\e0'.
+.B Snprintf
+(Minix-vmd only)
+is like
+.B sprintf
+except that no more than
+.IR n \-1
+characters are written to
+.I s
+followed by a `\e0'.
+.PP
+The
+.B v*printf
+functions can be used to make functions like the first four by using the
+.BR stdarg (3)
+method to process the argument.
+.PP
+Each of these functions converts, formats, and prints its arguments after
+the first under control of the first argument.
+The first argument is a character string which contains two types of objects:
+plain characters, which are simply copied to the output stream,
+and conversion specifications, each of which causes conversion and printing
+of the next successive
+.IR arg .
+.PP
+Each conversion specification is introduced by the character
+.BR % .
+The remainder of the conversion specification includes
+in the following order
+.TP
+\(bu
+Zero or more of following flags:
+.RS
+.TP
+\(bu
+a `#' character
+specifying that the value should be converted to an ``alternate form''.
+For 
+.BR c ,
+.BR d ,
+.BR s ,
+and
+.BR u
+conversions, this option has no effect.  For 
+.B o
+conversions, the precision of the number is increased to force the first
+character of the output string to a zero.  For 
+.BR x ( X )
+conversion, a non-zero result has the string 
+.BR 0x ( 0X )
+prepended to it.  For 
+.BR e ,
+.BR E ,
+.BR f ,
+.BR g ,
+and
+.BR G
+conversions, the result will always contain a decimal point, even if no
+digits follow the point (normally, a decimal point only appears in the
+results of those conversions if a digit follows the decimal point).  For
+.B g
+and
+.B G
+conversions, trailing zeros are not removed from the result as they
+would otherwise be.
+.TP
+\(bu
+a minus sign `\-' which specifies
+.I "left adjustment"
+of the converted value in the indicated field;
+.TP
+\(bu
+a `+' character specifying that there should always be
+a sign placed before the number when using signed conversions.
+.TP
+\(bu
+a space specifying that a blank should be left before a positive number
+during a signed conversion.  A `+' overrides a space if both are used.
+.RE
+.TP
+\(bu
+an optional digit string specifying a
+.I "field width;"
+if the converted value has fewer characters than the field width
+it will be blank-padded on the left (or right,
+if the left-adjustment indicator has been given) to make up the field width;
+if the field width begins with a zero,
+zero-padding will be done instead of blank-padding;
+.TP
+\(bu
+an optional period
+.RB ` . '
+which serves to separate the field width from the next digit string;
+.TP
+\(bu
+an optional digit string specifying a
+.I precision
+which specifies the number of digits to appear after the
+decimal point, for e- and f-conversion, or the maximum number of characters
+to be printed from a string;
+.TP
+\(bu
+the character
+.B l
+specifying that a following
+.BR d ,
+.BR o ,
+.BR x ,
+or
+.B u
+corresponds to a long integer
+.IR arg .
+.TP
+\(bu
+a character which indicates the type of
+conversion to be applied.
+.PP
+A field width or precision may be `*' instead of a digit string.
+In this case an integer
+.I arg
+supplies
+the field width or precision.
+.PP
+The conversion characters
+and their meanings are
+.TP
+.B dox
+The integer
+.I arg
+is converted to decimal, octal, or
+hexadecimal notation respectively.
+.TP
+.B X
+Like
+.BR x ,
+but use upper case instead of lower case.
+.TP
+.B f
+The float or double
+.I arg
+is converted to decimal notation
+in the style `[\fB\-\fR]ddd.ddd'
+where the number of d's after the decimal point
+is equal to the precision specification
+for the argument.
+If the precision
+is missing,
+6 digits are given;
+if the precision is explicitly 0, no digits and
+no decimal point are printed.
+.TP
+.B e
+The float or double
+.I arg
+is converted in the style
+`[\fB\-\fR]d\fB.\fRddd\fBe\fR\(+-dd'
+where there is one digit before the decimal point and
+the number after is equal to the
+precision specification for the argument;
+when the precision is missing,
+6 digits are produced.
+.TP
+.B g
+The float or double
+.I arg
+is printed in style
+.BR d ,
+in style
+.BR f ,
+or in
+style
+.BR e ,
+whichever gives full precision in minimum space.
+.TP
+.B c
+The character
+.I arg
+is printed.
+.TP
+.B s
+.I Arg
+is taken to be a string (character pointer)
+and characters from the string are printed until
+a null character or until
+the number of characters indicated by the precision
+specification is reached;
+however if the precision is 0 or missing
+all characters up to a null are printed.
+.TP
+.B u
+The unsigned integer
+.I arg
+is converted to decimal
+and printed.
+.TP
+.B %
+Print a `%'; no argument is converted.
+.PP
+In no case does a non-existent or small field width
+cause truncation of a field;
+padding takes place only if the specified field
+width exceeds the actual width.
+Characters generated by
+.B printf
+are printed by 
+.BR putc (3).
+.PP
+.B Examples
+.br
+To print a date and time in the form `Sunday, July 3, 10:02',
+where
+.I weekday
+and
+.I month
+are pointers to null-terminated strings:
+.PP
+.RS
+printf("%s, %s %d, %02d:%02d", weekday, month, day, hour, min);
+.RE
+.PP
+To print
+.if n pi
+.if t \(*p
+to 5 decimals:
+.IP
+printf("pi = %.5f", 4*atan(1.0));
+.SH "SEE ALSO"
+.BR putc (3),
+.BR scanf (3),
+.BR ecvt (3),
+.BR stdarg (3).
Index: /trunk/minix/man/man3/putc.3
===================================================================
--- /trunk/minix/man/man3/putc.3	(revision 9)
+++ /trunk/minix/man/man3/putc.3	(revision 9)
@@ -0,0 +1,70 @@
+.\"	@(#)putc.3s	6.2 (Berkeley) 11/6/85
+.\"
+.TH PUTC 3  "November 6, 1985"
+.AT 3
+.SH NAME
+putc, putchar, fputc, putw \- put character or word on a stream
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdio.h>
+
+int putc(int \fIc\fP, FILE *\fIstream\fP)
+int putchar(int \fIc\fP)
+int fputc(int \fIc\fP, FILE *\fIstream\fP)
+int putw(int \fIw\fP, FILE *\fIstream\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Putc
+appends the character
+.I c
+to the named output
+.IR stream .
+It returns the character written.
+.PP
+.BI Putchar( c )
+is defined as 
+.BI putc( c ", stdout)\fR."
+.PP
+.B Fputc
+behaves like 
+.BR putc ,
+but is a genuine function rather than a macro.
+.PP
+.B Putw
+appends word (that is,
+.BR int )
+.I w
+to the output
+.IR stream .
+It returns the word written.
+.B Putw
+neither assumes nor causes special alignment in the file.
+.SH "SEE ALSO"
+.BR fopen (3),
+.BR fclose (3),
+.BR getc (3),
+.BR puts (3),
+.BR printf (3),
+.BR fread (3).
+.SH DIAGNOSTICS
+These functions return the constant
+.SM
+.B EOF
+upon error.  Since this is a good integer,
+.BR ferror (3)
+should be used to detect 
+.B putw
+errors.
+.SH BUGS
+Because it is implemented as a macro,
+.B putc
+treats a
+.I stream
+argument with side effects improperly.  In particular
+`putc(c,\ *f++);'
+doesn't work sensibly.
+.PP
+Errors can occur long after the call to
+.BR putc .
Index: /trunk/minix/man/man3/puts.3
===================================================================
--- /trunk/minix/man/man3/puts.3	(revision 9)
+++ /trunk/minix/man/man3/puts.3	(revision 9)
@@ -0,0 +1,43 @@
+.\"	@(#)puts.3s	6.1 (Berkeley) 5/15/85
+.\"
+.TH PUTS 3  "May 15, 1985"
+.AT 3
+.SH NAME
+puts, fputs \- put a string on a stream
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdio.h>
+
+int puts(char *\fIs\fP)
+int fputs(char *\fIs\fP, FILE *\fIstream\fP)
+.ft P
+.fi
+.SH DESCRIPTION
+.B Puts
+copies the null-terminated string
+.I s
+to the standard output stream
+.B stdout
+and appends a
+newline character.
+.PP
+.B Fputs
+copies the null-terminated string
+.I s
+to the named output
+.IR stream .
+.PP
+Neither routine copies the terminal null character.
+.SH "SEE ALSO"
+.BR fopen (3),
+.BR gets (3),
+.BR putc (3),
+.BR printf (3),
+.BR ferror (3),
+.BR fread (3).
+.SH BUGS
+.B Puts
+appends a newline,
+.B fputs
+does not, all in the name of backward compatibility.
Index: /trunk/minix/man/man3/qsort.3
===================================================================
--- /trunk/minix/man/man3/qsort.3	(revision 9)
+++ /trunk/minix/man/man3/qsort.3	(revision 9)
@@ -0,0 +1,36 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)qsort.3	6.1 (Berkeley) 5/15/85
+.\"
+.TH QSORT 3  "May 15, 1985"
+.UC 4
+.SH NAME
+qsort \- quicker sort
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <stdlib.h>
+
+.fi
+.in +.5i
+.ti -.5i
+void qsort(void *\fIbase\fP, size_t \fInel\fP, size_t \fIwidth\fP, int (*\fIcompar\fP)(const void *, const void *))
+.in -.5i
+.ft R
+.SH DESCRIPTION
+.B Qsort
+is an implementation of the quicker-sort algorithm.
+The first argument is a pointer to the base of the data;
+the second is the number of elements;
+the third is the width of an element in bytes;
+the last is the name of the comparison routine
+to be called with two arguments which are pointers
+to the elements being compared.
+The routine must return an integer less than, equal to, or greater than 0
+according as the first argument is to be considered
+less than, equal to, or greater than the second.
+.SH "SEE ALSO"
+.BR sort (1).
Index: /trunk/minix/man/man3/rand.3
===================================================================
--- /trunk/minix/man/man3/rand.3	(revision 9)
+++ /trunk/minix/man/man3/rand.3	(revision 9)
@@ -0,0 +1,33 @@
+.\"	@(#)rand.3c	6.2 (Berkeley) 9/29/85
+.\"
+.TH RAND 3 "September 29, 1985"
+.AT 3
+.SH NAME
+rand, srand \- random number generator
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdlib.h>
+
+void srand(unsigned \fIseed\fP)
+unsigned rand(void)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Rand
+uses a multiplicative congruential
+random number generator with period
+.if t 2\u\s732\s0\d
+.if n 2**32
+to return successive pseudo-random
+numbers in the range from 0 to
+.BR RAND_MAX .
+.PP
+The generator is reinitialized by calling
+.B srand
+with 1 as argument.
+It can be set to a random starting point by calling
+.B srand
+with whatever you like as argument.
+.SH "SEE ALSO"
+.BR random (3).
Index: /trunk/minix/man/man3/random.3
===================================================================
--- /trunk/minix/man/man3/random.3	(revision 9)
+++ /trunk/minix/man/man3/random.3	(revision 9)
@@ -0,0 +1,131 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)random.3	6.2 (Berkeley) 9/29/85
+.\"
+.TH RANDOM 3 "September 29, 1985"
+.UC 5
+.SH NAME
+random, srandom, initstate, setstate \- better random number generator; routines for changing generators
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdlib.h>
+
+long random(void)
+void srandom(unsigned \fIseed\fP)
+char *initstate(unsigned \fIseed\fP, char *\fIstate\fP, int \fIn\fP)
+char *setstate(char *\fIstate\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.PP
+.B Random
+uses a non-linear additive feedback random number generator employing a
+default table of size 31 long integers to return successive pseudo-random
+numbers in the range from 0 to
+.if t 2\u\s731\s10\d\(mi1.
+.if n (2**31)\(mi1.
+The period of this random number generator is very large, approximately
+.if t 16\(mu(2\u\s731\s10\d\(mi1).
+.if n 16*((2**31)\(mi1).
+.PP
+.B Random/srandom
+have (almost) the same calling sequence and initialization properties as
+.B rand/srand.
+The difference is that
+.BR rand (3)
+produces a much less random sequence \(em in fact, the low dozen bits
+generated by rand go through a cyclic pattern.  All the bits generated by
+.B random
+are usable.  For example, ``random()&01'' will produce a random binary
+value.
+.PP
+Unlike
+.BR srand ,
+.B srandom
+does not return the old seed; the reason for this is that the amount of
+state information used is much more than a single word.  (Two other
+routines are provided to deal with restarting/changing random
+number generators).  Like
+.BR rand (3),
+however,
+.B random
+will by default produce a sequence of numbers that can be duplicated
+by calling
+.B srandom
+with 
+.B 1
+as the seed.
+.PP
+The
+.B initstate
+routine allows a state array, passed in as an argument, to be initialized
+for future use.  The size of the state array (in bytes) is used by
+.B initstate
+to decide how sophisticated a random number generator it should use -- the
+more state, the better the random numbers will be.
+(Current "optimal" values for the amount of state information are
+8, 32, 64, 128, and 256 bytes; other amounts will be rounded down to
+the nearest known amount.  Using less than 8 bytes will cause an error).
+The seed for the initialization (which specifies a starting point for
+the random number sequence, and provides for restarting at the same
+point) is also an argument.
+.B Initstate
+returns a pointer to the previous state information array.
+.PP
+Once a state has been initialized, the
+.B setstate
+routine provides for rapid switching between states.
+.B Setstate
+returns a pointer to the previous state array; its
+argument state array is used for further random number generation
+until the next call to
+.B initstate
+or
+.BR setstate .
+.PP
+Once a state array has been initialized, it may be restarted at a
+different point either by calling
+.B initstate
+(with the desired seed, the state array, and its size) or by calling
+both
+.B setstate
+(with the state array) and
+.B srandom
+(with the desired seed).
+The advantage of calling both
+.B setstate
+and
+.B srandom
+is that the size of the state array does not have to be remembered after
+it is initialized.
+.PP
+With 256 bytes of state information, the period of the random number
+generator is greater than
+.if t 2\u\s769\s10\d,
+.if n 2**69
+which should be sufficient for most purposes.
+.SH AUTHOR
+Earl T. Cohen
+.SH DIAGNOSTICS
+.PP
+If
+.B initstate
+is called with less than 8 bytes of state information, or if
+.B setstate
+detects that the state information has been garbled, error
+messages are printed on the standard error output.
+.SH "SEE ALSO"
+.BR rand (3).
+.SH NOTES
+.B initstate
+and
+.B setstate
+are not declared in
+.IR <stdlib.h> ,
+programmers must provide their own declarations.
+.SH BUGS
+About 2/3 the speed of
+.BR rand (3).
Index: /trunk/minix/man/man3/rcmd.3
===================================================================
--- /trunk/minix/man/man3/rcmd.3	(revision 9)
+++ /trunk/minix/man/man3/rcmd.3	(revision 9)
@@ -0,0 +1,141 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)rcmd.3	6.7 (Berkeley) 5/14/86
+.\"
+.TH RCMD 3 "May 14, 1986"
+.UC 5
+.SH NAME
+rcmd, rresvport, ruserok \- routines for returning a stream to a remote command
+.SH SYNOPSIS
+.nf
+.B "#include <sys/types.h>"
+.B "#include <net/netlib.h>"
+.PP
+.B "rem = rcmd(ahost, inport, locuser, remuser, cmd, fd2p);"
+.B char **ahost;
+.B int inport;
+.B "char *locuser, *remuser, *cmd;"
+.B int *fd2p;
+.PP
+.B s = rresvport(port);
+.B int *port;
+.PP
+.B "ruserok(rhost, superuser, ruser, luser);"
+.B char *rhost;
+.B int superuser;
+.B char *ruser, *luser;
+.fi
+.SH DESCRIPTION
+.I Rcmd
+is a routine used by the super-user to execute a command on
+a remote machine using an authentication scheme based
+on reserved port numbers.
+.I Rresvport
+is a routine which returns a descriptor to a socket
+with an address in the privileged port space.
+.I Ruserok
+is a routine used by servers
+to authenticate clients requesting service with
+.IR rcmd .
+All three functions are present in the same file and are used
+by the
+.IR rshd (8)
+server (among others).
+.PP
+.I Rcmd
+looks up the host
+.I *ahost
+using
+.IR gethostbyname (3),
+returning \-1 if the host does not exist.
+Otherwise
+.I *ahost
+is set to the standard name of the host
+and a connection is established to a server
+residing at the well-known Internet port
+.IR inport .
+.PP
+If the connection succeeds,
+a socket in the Internet domain of type SOCK_STREAM
+is returned to the caller, and given to the remote
+command as 
+.B stdin
+and
+.BR stdout .
+If
+.I fd2p
+is non-zero, then an auxiliary channel to a control
+process will be set up, and a descriptor for it will be placed
+in
+.IR *fd2p .
+The control process will return diagnostic
+output from the command (unit 2) on this channel, and will also
+accept bytes on this channel as being UNIX signal numbers, to be
+forwarded to the process group of the command.
+If
+.I fd2p
+is 0, then the 
+.B stderr
+(unit 2 of the remote
+command) will be made the same as the 
+.B stdout
+and no
+provision is made for sending arbitrary signals to the remote process,
+although you may be able to get its attention by using out-of-band data.
+.PP
+The protocol is described in detail in
+.IR rshd (8).
+.PP
+The
+.I rresvport
+routine is used to obtain a socket with a privileged
+address bound to it.  This socket is suitable for use
+by 
+.I rcmd
+and several other routines.  Privileged Internet ports are those
+in the range 0 to 1023.  Only the super-user
+is allowed to bind an address of this sort to a socket.
+.PP
+.I Ruserok
+takes a remote host's name, as returned by a
+.IR gethostbyaddr (3)
+routine, two user names and a flag indicating whether
+the local user's name is that of the super-user.  It then
+checks the files 
+.I /etc/hosts.equiv
+and, possibly, 
+.I .rhosts
+in the current working directory (normally the local
+user's home directory) to see if the request for
+service is allowed.  A 0 is returned if the machine
+name is listed in the ``hosts.equiv'' file, or the
+host and remote user name are found in the ``.rhosts''
+file; otherwise 
+.I ruserok
+returns \-1.  If the
+.I superuser
+flag is 1, the checking of the ``host.equiv'' file is
+bypassed.
+If the local domain (as obtained from \fIgethostname\fP\|(3))
+is the same as the remote domain, only the machine name need be specified.
+.SH SEE ALSO
+rlogin(1),
+rsh(1),
+intro(2),
+rexec(3),
+rexecd(8),
+rlogind(8),
+rshd(8)
+.SH DIAGNOSTICS
+.I Rcmd
+returns a valid socket descriptor on success.
+It returns -1 on error and prints a diagnostic message on the standard error.
+.PP
+.I Rresvport
+returns a valid, bound socket descriptor on success.
+It returns -1 on error with the global value
+.I errno
+set according to the reason for failure.
+The error code EAGAIN is overloaded to mean ``All network ports in use.''
Index: /trunk/minix/man/man3/regex.3
===================================================================
--- /trunk/minix/man/man3/regex.3	(revision 9)
+++ /trunk/minix/man/man3/regex.3	(revision 9)
@@ -0,0 +1,541 @@
+.\" Copyright (c) 1992, 1993, 1994 Henry Spencer.
+.\" Copyright (c) 1992, 1993, 1994
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Henry Spencer.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)regex.3	8.4 (Berkeley) 3/20/94
+.\"
+.TH REGEX 3 "March 20, 1994"
+.de ZR
+.\" one other place knows this name:  the SEE ALSO section
+.BR re_format (7) \\$1
+..
+.SH NAME
+regex, regcomp, regexec, regerror, regfree \- regular-expression library
+.SH SYNOPSIS
+.ft B
+.\".na
+#include <sys/types.h>
+.br
+#include <regex.h>
+.sp
+.in +.5i
+.ti -.5i
+int regcomp(regex_t *\fIpreg\fP, const char *\fIpattern\fP, int \fIcflags\fP);
+.ti -.5i
+int regexec(const regex_t *\fIpreg\fP, const char *\fIstring\fP,
+size_t \fInmatch\fP, regmatch_t \fIpmatch\fP[], int \fIeflags\fP);
+.ti -.5i
+size_t regerror(int \fIerrcode\fP, const regex_t *\fIpreg\fP,
+char *\fIerrbuf\fP, size_t \fIerrbuf_size\fP);
+.ti -.5i
+void regfree(regex_t *\fIpreg\fP);
+.in -.5i
+.ft R
+.SH DESCRIPTION
+These routines implement POSIX 1003.2 regular expressions (``RE''s);
+see
+.ZR .
+.B Regcomp
+compiles an RE written as a string into an internal form,
+.B regexec
+matches that internal form against a string and reports results,
+.B regerror
+transforms error codes from either into human-readable messages,
+and
+.B regfree
+frees any dynamically-allocated storage used by the internal form
+of an RE.
+.PP
+The header
+.I <regex.h>
+declares two structure types,
+.B regex_t
+and
+.BR regmatch_t ,
+the former for compiled internal forms and the latter for match reporting.
+It also declares the four functions,
+a type
+.BR regoff_t ,
+and a number of constants with names starting with ``REG_''.
+.PP
+.B Regcomp
+compiles the regular expression contained in the
+.I pattern
+string,
+subject to the flags in
+.IR cflags ,
+and places the results in the
+.B regex_t
+structure pointed to by
+.IR preg .
+.I Cflags
+is the bitwise OR of zero or more of the following flags:
+.IP REG_EXTENDED \w'REG_EXTENDED'u+2n
+Compile modern (``extended'') REs,
+rather than the obsolete (``basic'') REs that
+are the default.
+.IP REG_BASIC
+This is a synonym for 0,
+provided as a counterpart to REG_EXTENDED to improve readability.
+.IP REG_NOSPEC
+Compile with recognition of all special characters turned off.
+All characters are thus considered ordinary,
+so the ``RE'' is a literal string.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+REG_EXTENDED and REG_NOSPEC may not be used
+in the same call to
+.IR regcomp .
+.IP REG_ICASE
+Compile for matching that ignores upper/lower case distinctions.
+See
+.ZR .
+.IP REG_NOSUB
+Compile for matching that need only report success or failure,
+not what was matched.
+.IP REG_NEWLINE
+Compile for newline-sensitive matching.
+By default, newline is a completely ordinary character with no special
+meaning in either REs or strings.
+With this flag,
+`[^' bracket expressions and `.' never match newline,
+a `^' anchor matches the null string after any newline in the string
+in addition to its normal function,
+and the `$' anchor matches the null string before any newline in the
+string in addition to its normal function.
+.IP REG_PEND
+The regular expression ends,
+not at the first NUL,
+but just before the character pointed to by the
+.B re_endp
+member of the structure pointed to by
+.IR preg .
+The
+.B re_endp
+member is of type
+.BR "const\ char\ *" .
+This flag permits inclusion of NULs in the RE;
+they are considered ordinary characters.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+.PP
+When successful,
+.B regcomp
+returns 0 and fills in the structure pointed to by
+.IR preg .
+One member of that structure
+(other than
+.BR re_endp )
+is publicized:
+.BR re_nsub ,
+of type
+.BR size_t ,
+contains the number of parenthesized subexpressions within the RE
+(except that the value of this member is undefined if the
+REG_NOSUB flag was used).
+If
+.B regcomp
+fails, it returns a non-zero error code;
+see DIAGNOSTICS.
+.PP
+.B Regexec
+matches the compiled RE pointed to by
+.I preg
+against the
+.IR string ,
+subject to the flags in
+.IR eflags ,
+and reports results using
+.IR nmatch ,
+.IR pmatch ,
+and the returned value.
+The RE must have been compiled by a previous invocation of
+.BR regcomp .
+The compiled form is not altered during execution of
+.BR regexec ,
+so a single compiled RE can be used simultaneously by multiple threads.
+.PP
+By default,
+the NUL-terminated string pointed to by
+.I string
+is considered to be the text of an entire line, minus any terminating
+newline.
+The
+.I eflags
+argument is the bitwise OR of zero or more of the following flags:
+.IP REG_NOTBOL \w'REG_STARTEND'u+2n
+The first character of
+the string
+is not the beginning of a line, so the `^' anchor should not match before it.
+This does not affect the behavior of newlines under REG_NEWLINE.
+.IP REG_NOTEOL
+The NUL terminating
+the string
+does not end a line, so the `$' anchor should not match before it.
+This does not affect the behavior of newlines under REG_NEWLINE.
+.IP REG_STARTEND
+The string is considered to start at
+\fIstring\fR\ + \fIpmatch\fR[0].\fBrm_so\fR
+and to have a terminating NUL located at
+\fIstring\fR\ + \fIpmatch\fR[0].\fBrm_eo\fR
+(there need not actually be a NUL at that location),
+regardless of the value of
+.IR nmatch .
+See below for the definition of
+.IR pmatch
+and
+.IR nmatch .
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+Note that a non-zero \fBrm_so\fR does not imply REG_NOTBOL;
+REG_STARTEND affects only the location of the string,
+not how it is matched.
+.PP
+See
+.ZR
+for a discussion of what is matched in situations where an RE or a
+portion thereof could match any of several substrings of
+.IR string .
+.PP
+Normally,
+.B regexec
+returns 0 for success and the non-zero code REG_NOMATCH for failure.
+Other non-zero error codes may be returned in exceptional situations;
+see DIAGNOSTICS.
+.PP
+If REG_NOSUB was specified in the compilation of the RE,
+or if
+.I nmatch
+is 0,
+.B regexec
+ignores the
+.I pmatch
+argument (but see below for the case where REG_STARTEND is specified).
+Otherwise,
+.I pmatch
+points to an array of
+.I nmatch
+structures of type
+.BR regmatch_t .
+Such a structure has at least the members
+.B rm_so
+and
+.BR rm_eo ,
+both of type
+.B regoff_t
+(a signed arithmetic type at least as large as an
+.B off_t
+and a
+.BR ssize_t ),
+containing respectively the offset of the first character of a substring
+and the offset of the first character after the end of the substring.
+Offsets are measured from the beginning of the
+.I string
+argument given to
+.BR regexec .
+An empty substring is denoted by equal offsets,
+both indicating the character following the empty substring.
+.PP
+The 0th member of the
+.I pmatch
+array is filled in to indicate what substring of
+.I string
+was matched by the entire RE.
+Remaining members report what substring was matched by parenthesized
+subexpressions within the RE;
+member
+.I i
+reports subexpression
+.IR i ,
+with subexpressions counted (starting at 1) by the order of their opening
+parentheses in the RE, left to right.
+Unused entries in the array\(emcorresponding either to subexpressions that
+did not participate in the match at all, or to subexpressions that do not
+exist in the RE (that is, \fIi\fR\ > \fIpreg\fR\->\fBre_nsub\fR)\(emhave both
+.B rm_so
+and
+.B rm_eo
+set to \-1.
+If a subexpression participated in the match several times,
+the reported substring is the last one it matched.
+(Note, as an example in particular, that when the RE `(b*)+' matches `bbb',
+the parenthesized subexpression matches each of the three `b's and then
+an infinite number of empty strings following the last `b',
+so the reported substring is one of the empties.)
+.PP
+If REG_STARTEND is specified,
+.I pmatch
+must point to at least one
+.B regmatch_t
+(even if
+.I nmatch
+is 0 or REG_NOSUB was specified),
+to hold the input offsets for REG_STARTEND.
+Use for output is still entirely controlled by
+.IR nmatch ;
+if
+.I nmatch
+is 0 or REG_NOSUB was specified,
+the value of
+.IR pmatch [0]
+will not be changed by a successful
+.BR regexec .
+.PP
+.B Regerror
+maps a non-zero
+.I errcode
+from either
+.B regcomp
+or
+.B regexec
+to a human-readable, printable message.
+If
+.I preg
+is non-NULL,
+the error code should have arisen from use of
+the
+.B regex_t
+pointed to by
+.IR preg ,
+and if the error code came from
+.BR regcomp ,
+it should have been the result from the most recent
+.B regcomp
+using that
+.BR regex_t .
+.RI ( Regerror
+may be able to supply a more detailed message using information
+from the
+.BR regex_t .)
+.B Regerror
+places the NUL-terminated message into the buffer pointed to by
+.IR errbuf ,
+limiting the length (including the NUL) to at most
+.I errbuf_size
+bytes.
+If the whole message won't fit,
+as much of it as will fit before the terminating NUL is supplied.
+In any case,
+the returned value is the size of buffer needed to hold the whole
+message (including terminating NUL).
+If
+.I errbuf_size
+is 0,
+.I errbuf
+is ignored but the return value is still correct.
+.PP
+If the
+.I errcode
+given to
+.B regerror
+is first ORed with REG_ITOA,
+the ``message'' that results is the printable name of the error code,
+e.g. ``REG_NOMATCH'',
+rather than an explanation thereof.
+If
+.I errcode
+is REG_ATOI,
+then
+.I preg
+shall be non-NULL and the
+.B re_endp
+member of the structure it points to
+must point to the printable name of an error code;
+in this case, the result in
+.I errbuf
+is the decimal digits of
+the numeric value of the error code
+(0 if the name is not recognized).
+REG_ITOA and REG_ATOI are intended primarily as debugging facilities;
+they are extensions,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+Be warned also that they are considered experimental and changes are possible.
+.PP
+.B Regfree
+frees any dynamically-allocated storage associated with the compiled RE
+pointed to by
+.IR preg .
+The remaining
+.B regex_t
+is no longer a valid compiled RE
+and the effect of supplying it to
+.B regexec
+or
+.B regerror
+is undefined.
+.PP
+None of these functions references global variables except for tables
+of constants;
+all are safe for use from multiple threads if the arguments are safe.
+.SH IMPLEMENTATION CHOICES
+There are a number of decisions that 1003.2 leaves up to the implementor,
+either by explicitly saying ``undefined'' or by virtue of them being
+forbidden by the RE grammar.
+This implementation treats them as follows.
+.PP
+See
+.ZR
+for a discussion of the definition of case-independent matching.
+.PP
+There is no particular limit on the length of REs,
+except insofar as memory is limited.
+Memory usage is approximately linear in RE size, and largely insensitive
+to RE complexity, except for bounded repetitions.
+See BUGS for one short RE using them
+that will run almost any system out of memory.
+.PP
+A backslashed character other than one specifically given a magic meaning
+by 1003.2 (such magic meanings occur only in obsolete [``basic''] REs)
+is taken as an ordinary character.
+.PP
+Any unmatched [ is a REG_EBRACK error.
+.PP
+Equivalence classes cannot begin or end bracket-expression ranges.
+The endpoint of one range cannot begin another.
+.PP
+RE_DUP_MAX, the limit on repetition counts in bounded repetitions, is 255.
+.PP
+A repetition operator (?, *, +, or bounds) cannot follow another
+repetition operator.
+A repetition operator cannot begin an expression or subexpression
+or follow `^' or `|'.
+.PP
+`|' cannot appear first or last in a (sub)expression or after another `|',
+i.e. an operand of `|' cannot be an empty subexpression.
+An empty parenthesized subexpression, `()', is legal and matches an
+empty (sub)string.
+An empty string is not a legal RE.
+.PP
+A `{' followed by a digit is considered the beginning of bounds for a
+bounded repetition, which must then follow the syntax for bounds.
+A `{' \fInot\fR followed by a digit is considered an ordinary character.
+.PP
+`^' and `$' beginning and ending subexpressions in obsolete (``basic'')
+REs are anchors, not ordinary characters.
+.SH SEE ALSO
+.BR grep (1),
+.BR re_format (7).
+.PP
+POSIX 1003.2, sections 2.8 (Regular Expression Notation)
+and
+B.5 (C Binding for Regular Expression Matching).
+.SH DIAGNOSTICS
+Non-zero error codes from
+.B regcomp
+and
+.B regexec
+include the following:
+.PP
+.nf
+.ta \w'REG_ECOLLATE'u+3n
+REG_NOMATCH	regexec() failed to match
+REG_BADPAT	invalid regular expression
+REG_ECOLLATE	invalid collating element
+REG_ECTYPE	invalid character class
+REG_EESCAPE	\e applied to unescapable character
+REG_ESUBREG	invalid backreference number
+REG_EBRACK	brackets [ ] not balanced
+REG_EPAREN	parentheses ( ) not balanced
+REG_EBRACE	braces { } not balanced
+REG_BADBR	invalid repetition count(s) in { }
+REG_ERANGE	invalid character range in [ ]
+REG_ESPACE	ran out of memory
+REG_BADRPT	?, *, or + operand invalid
+REG_EMPTY	empty (sub)expression
+REG_ASSERT	``can't happen''\(emyou found a bug
+REG_INVARG	invalid argument, e.g. negative-length string
+.fi
+.SH HISTORY
+Originally written by Henry Spencer.
+Altered for inclusion in the 4.4BSD distribution.
+.SH BUGS
+This is an alpha release with known defects.
+Please report problems.
+.PP
+There is one known functionality bug.
+The implementation of internationalization is incomplete:
+the locale is always assumed to be the default one of 1003.2,
+and only the collating elements etc. of that locale are available.
+.PP
+The back-reference code is subtle and doubts linger about its correctness
+in complex cases.
+.PP
+.B Regexec
+performance is poor.
+This will improve with later releases.
+.I Nmatch
+exceeding 0 is expensive;
+.I nmatch
+exceeding 1 is worse.
+.B Regexec
+is largely insensitive to RE complexity \fIexcept\fR that back
+references are massively expensive.
+RE length does matter; in particular, there is a strong speed bonus
+for keeping RE length under about 30 characters,
+with most special characters counting roughly double.
+.PP
+.B Regcomp
+implements bounded repetitions by macro expansion,
+which is costly in time and space if counts are large
+or bounded repetitions are nested.
+An RE like, say,
+`((((a{1,100}){1,100}){1,100}){1,100}){1,100}'
+will (eventually) run almost any existing machine out of swap space.
+.PP
+There are suspected problems with response to obscure error conditions.
+Notably,
+certain kinds of internal overflow,
+produced only by truly enormous REs or by multiply nested bounded repetitions,
+are probably not handled well.
+.PP
+Due to a mistake in 1003.2, things like `a)b' are legal REs because `)' is
+a special character only in the presence of a previous unmatched `('.
+This can't be fixed until the spec is fixed.
+.PP
+The standard's definition of back references is vague.
+For example, does
+`a\e(\e(b\e)*\e2\e)*d' match `abbbd'?
+Until the standard is clarified,
+behavior in such cases should not be relied on.
+.PP
+The implementation of word-boundary matching is a bit of a kludge,
+and bugs may lurk in combinations of word-boundary matching and anchoring.
Index: /trunk/minix/man/man3/resolver.3
===================================================================
--- /trunk/minix/man/man3/resolver.3	(revision 9)
+++ /trunk/minix/man/man3/resolver.3	(revision 9)
@@ -0,0 +1,280 @@
+.\" Copyright (c) 1985 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms are permitted provided
+.\" that: (1) source distributions retain this entire copyright notice and
+.\" comment, and (2) distributions including binaries display the following
+.\" acknowledgement:  ``This product includes software developed by the
+.\" University of California, Berkeley and its contributors'' in the
+.\" documentation or other materials provided with the distribution and in
+.\" all advertising materials mentioning features or use of this software.
+.\" Neither the name of the University nor the names of its contributors may
+.\" be used to endorse or promote products derived from this software without
+.\" specific prior written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\"	@(#)resolver.3	6.5 (Berkeley) 6/23/90
+.\"
+.TH RESOLVER 3 "June 23, 1990"
+.UC 4
+.SH NAME
+resolver, res_query, res_search, res_mkquery, res_send, res_init, dn_comp, dn_expand \- resolver routines
+.SH SYNOPSIS
+.B #include <sys/types.h>
+.br
+.B #include <net/gen/in.h>
+.br
+.B #include <net/gen/nameser.h>
+.br
+.B #include <net/gen/resolv.h>
+.PP
+.B "res_query(dname, class, type, answer, anslen)"
+.br
+.B char *dname;
+.br
+.B int class, type;
+.br
+.B u_char *answer;
+.br
+.B int anslen;
+.PP
+.B "res_search(dname, class, type, answer, anslen)"
+.br
+.B char *dname;
+.br
+.B int class, type;
+.br
+.B u_char *answer;
+.br
+.B int anslen;
+.PP
+.B "res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)"
+.br
+.B int op;
+.br
+.B char *dname;
+.br
+.B int class, type;
+.br
+.B char *data;
+.br
+.B int datalen;
+.br
+.B struct rrec *newrr;
+.br
+.B char *buf;
+.br
+.B int buflen;
+.PP
+.B res_send(msg, msglen, answer, anslen)
+.br
+.B char *msg;
+.br
+.B int msglen;
+.br
+.B char *answer;
+.br
+.B int anslen;
+.PP
+.B res_init()
+.PP
+.B dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
+.br
+.B char *exp_dn, *comp_dn;
+.br
+.B int length;
+.br
+.B char **dnptrs, **lastdnptr;
+.PP
+.B dn_expand(msg, eomorig, comp_dn, exp_dn, length)
+.br
+.B char *msg, *eomorig, *comp_dn, exp_dn;
+.br
+.B int  length;
+.SH DESCRIPTION
+These routines are used for making, sending and interpreting
+query and reply messages with Internet domain name servers.
+.PP
+Global configuration and state information that is used by the
+resolver routines is kept in the structure
+.IR _res .
+Most of the values have reasonable defaults and can be ignored.
+Options
+stored in
+.I _res.options
+are defined in
+.I resolv.h
+and are as follows.
+Options are stored as a simple bit mask containing the bitwise ``or''
+of the options enabled.
+.IP RES_INIT
+True if the initial name server address and default domain name are
+initialized (i.e.,
+.I res_init
+has been called).
+.IP RES_DEBUG
+Print debugging messages.
+.IP RES_AAONLY
+Accept authoritative answers only.
+With this option,
+.I res_send
+should continue until it finds an authoritative answer or finds an error.
+Currently this is not implemented.
+.IP RES_USEVC
+Use TCP connections for queries instead of UDP datagrams.
+.IP RES_STAYOPEN
+Used with RES_USEVC to keep the TCP connection open between
+queries.
+This is useful only in programs that regularly do many queries.
+UDP should be the normal mode used.
+.IP RES_IGNTC
+Unused currently (ignore truncation errors, i.e., don't retry with TCP).
+.IP RES_RECURSE
+Set the recursion-desired bit in queries.
+This is the default.
+(\c
+.I res_send
+does not do iterative queries and expects the name server
+to handle recursion.)
+.IP RES_DEFNAMES
+If set,
+.I res_search
+will append the default domain name to single-component names
+(those that do not contain a dot).
+This option is enabled by default.
+.IP RES_DNSRCH
+If this option is set,
+.I res_search
+will search for host names in the current domain and in parent domains; see
+.IR hostname (7).
+This is used by the standard host lookup routine
+.IR gethostbyname (3).
+This option is enabled by default.
+.PP
+The
+.I res_init
+routine
+reads the configuration file (if any; see
+.IR resolver (5))
+to get the default domain name,
+search list and
+the Internet address of the local name server(s).
+If no server is configured, the host running
+the resolver is tried.
+The current domain name is defined by the hostname
+if not specified in the configuration file;
+it can be overridden by the environment variable LOCALDOMAIN.
+Initialization normally occurs on the first call
+to one of the following routines.
+.PP
+The
+.I res_query
+function provides an interface to the server query mechanism.
+It constructs a query, sends it to the local server,
+awaits a response, and makes preliminary checks on the reply.
+The query requests information of the specified
+.I type
+and
+.I class
+for the specified fully-qualified domain name
+.I dname .
+The reply message is left in the
+.I answer
+buffer with length
+.I anslen
+supplied by the caller.
+.PP
+The
+.I res_search
+routine makes a query and awaits a response like
+.IR res_query ,
+but in addition, it implements the default and search rules
+controlled by the RES_DEFNAMES and RES_DNSRCH options.
+It returns the first successful reply.
+.PP
+The remaining routines are lower-level routines used by
+.IR res_query .
+The
+.I res_mkquery
+function
+constructs a standard query message and places it in
+.IR buf .
+It returns the size of the query, or \-1 if the query is
+larger than
+.IR buflen .
+The query type
+.I op
+is usually QUERY, but can be any of the query types defined in
+.IR <arpa/nameser.h> .
+The domain name for the query is given by
+.IR dname .
+.I Newrr
+is currently unused but is intended for making update messages.
+.PP
+The
+.I res_send
+routine
+sends a pre-formatted query and returns an answer.
+It will call
+.I res_init
+if RES_INIT is not set, send the query to the local name server, and
+handle timeouts and retries.
+The length of the reply message is returned, or
+\-1 if there were errors.
+.PP
+The
+.I dn_comp
+function
+compresses the domain name
+.I exp_dn
+and stores it in
+.IR comp_dn .
+The size of the compressed name is returned or \-1 if there were errors.
+The size of the array pointed to by
+.I comp_dn
+is given by
+.IR length .
+The compression uses
+an array of pointers
+.I dnptrs
+to previously-compressed names in the current message.
+The first pointer points to
+to the beginning of the message and the list ends with NULL.
+The limit to the array is specified by
+.IR lastdnptr .
+A side effect of
+.I dn_comp
+is to update the list of pointers for
+labels inserted into the message
+as the name is compressed.
+If
+.I dnptr
+is NULL, names are not compressed.
+If
+.I lastdnptr
+is NULL, the list of labels is not updated.
+.PP
+The
+.I dn_expand
+entry
+expands the compressed domain name
+.I comp_dn
+to a full domain name
+The compressed name is contained in a query or reply message;
+.I msg
+is a pointer to the beginning of the message.
+The uncompressed name is placed in the buffer indicated by
+.I exp_dn
+which is of size
+.IR length .
+The size of compressed name is returned or \-1 if there was an error.
+.SH FILES
+/etc/resolv.conf	see resolver(5)
+.SH "SEE ALSO"
+gethostbyname(3), named(8), resolver(5), hostname(7),
+.br
+RFC1032, RFC1033, RFC1034, RFC1035, RFC974, 
+.br
+SMM:11 Name Server Operations Guide for BIND
Index: /trunk/minix/man/man3/scanf.3
===================================================================
--- /trunk/minix/man/man3/scanf.3	(revision 9)
+++ /trunk/minix/man/man3/scanf.3	(revision 9)
@@ -0,0 +1,251 @@
+.\"	@(#)scanf.3s	6.1 (Berkeley) 5/15/85
+.\"
+.TH SCANF 3  "May 15, 1985"
+.AT 3
+.SH NAME
+scanf, fscanf, sscanf, vscanf, vfscanf, vsscanf \- formatted input conversion
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdio.h>
+#include <stdarg.h>
+
+int scanf(const char *\fIformat\fP \fR[\fP, \fIpointer\fP\fR] ...\fP)
+int fscanf(FILE *\fIstream\fP, const char *\fIformat\fP \fR[\fP, \fIpointer\fP\fR] ...\fP)
+int sscanf(const char *\fIs\fP, const char *\fIformat\fP \fR[\fP, \fIpointer\fP\fR] ...\fP)
+int vscanf(const char *\fIformat\fP, va_list \fIargs\fP)
+int vfscanf(FILE *\fIstream\fP, const char *\fIformat\fP, va_list \fIargs\fP)
+int vsscanf(const char *\fIs\fP, const char *\fIformat\fP, va_list \fIargs\fP)
+.SH DESCRIPTION
+.B Scanf
+reads from the standard input stream
+.BR stdin .
+.B Fscanf
+reads from the named input
+.IR stream .
+.B Sscanf
+reads from the character string
+.IR s .
+Each function reads characters, interprets
+them according to a format, and stores the results in its arguments.
+Each expects as arguments
+a control string
+.IR format ,
+described below,
+and a set of
+.I pointer
+arguments
+indicating where the converted input should be stored.
+.PP
+The
+.B v*scanf
+functions can be used to make functions like the first three by using the
+.BR stdarg (3)
+method to process the argument pointers.
+.PP
+The
+control string
+usually contains
+conversion specifications, which are used to direct interpretation
+of input sequences.
+The control string may contain:
+.TP 4
+1.
+Blanks, tabs or newlines,
+which match optional white space in the input.
+.TP 4
+2.
+An ordinary character (not %) which must match
+the next character of the input stream.
+.TP 4
+3.
+Conversion specifications, consisting of the
+character
+.BR % ,
+an optional assignment suppressing character
+.BR * ,
+an optional numerical maximum field width, and a conversion
+character.
+.PP
+A conversion specification directs the conversion of the
+next input field; the result
+is placed in the variable pointed to by the corresponding argument,
+unless assignment suppression was
+indicated by
+.BR * .
+An input field is defined as a string of non-space characters;
+it extends to the next inappropriate character or until the field
+width, if specified, is exhausted.
+.PP
+The conversion character indicates the interpretation of the
+input field; the corresponding pointer argument must
+usually be of a restricted type.
+The following conversion characters are legal:
+.TP 4
+.B  %
+a single `%' is expected
+in the input at this point;
+no assignment is done.
+.TP 4
+.B  d
+a decimal integer is expected;
+the corresponding argument should be an integer pointer.
+.TP 4
+.B  o
+an octal integer is expected;
+the corresponding argument should be a integer pointer.
+.TP 4
+.B  x
+a hexadecimal integer is expected;
+the corresponding argument should be an integer pointer.
+.ti -0.2i
+.TP 4
+.B  s
+a character string is expected;
+the corresponding argument should be a character pointer
+pointing to an array of characters large enough to accept the
+string and a terminating `\e0', which will be added.
+The input field is terminated by a space character
+or a newline.
+.TP 4
+.B  c
+a character is expected; the
+corresponding argument should be a character pointer.
+The normal skip over space characters is suppressed
+in this case;
+to read the next non-space character, try
+`%1s'.
+If a field width is given, the corresponding argument
+should refer to a character array, and the
+indicated number of characters is read.
+.TP 4
+.B efg
+a floating point number is expected;
+the next field is converted accordingly and stored through the
+corresponding argument, which should be a pointer to a
+.BR float .
+The input format for
+floating point numbers is
+an optionally signed
+string of digits
+possibly containing a decimal point, followed by an optional
+exponent field consisting of an E or e followed by an optionally signed integer.
+.TP 4
+.B  [
+indicates a string not to be delimited by space characters.
+The left bracket is followed by a set of characters and a right
+bracket; the characters between the brackets define a set
+of characters making up the string.
+If the first character
+is not circumflex (\|^\|), the input field
+is all characters until the first character not in the set between
+the brackets; if the first character
+after the left bracket is ^, the input field is all characters
+until the first character which is in the remaining set of characters
+between the brackets.
+The corresponding argument must point to a character array.
+.PP
+The conversion characters
+.BR d ,
+.B o
+and
+.B x
+may be capitalized or preceded by
+.B l
+to indicate that a pointer to
+.B long
+rather than to
+.B int
+is in the argument list.
+Similarly, the conversion characters
+.BR e ,
+.B f
+or
+.B g
+may be capitalized or
+preceded by
+.B l
+to indicate a pointer to 
+.B double
+rather than to 
+.BR float .
+The conversion characters
+.BR d ,
+.B o
+and
+.B x
+may be preceded by
+.B h
+to indicate a pointer to
+.B short
+rather than to
+.BR int .
+.PP
+The
+.B scanf
+functions return the number of successfully matched and assigned input
+items.
+This can be used to decide how many input items were found.
+The constant
+.SM
+.B EOF
+is returned upon end of input; note that this is different
+from 0, which means that no conversion was done;
+if conversion was intended, it was frustrated by an
+inappropriate character in the input.
+.PP
+For example, the call
+.IP "\&" 10
+int i; float x; char name[50];
+.br
+scanf("%d%f%s", &i, &x, name);
+.PP
+with the input line
+.IP
+25   54.32E\(mi1  thompson
+.PP
+will assign to
+.B i
+the value
+25,
+.B x
+the value 5.432, and
+.B name
+will contain `\fBthompson\e0\fP' .
+Or,
+.IP
+int i; float x; char name[50];
+.br
+scanf("%2d%f%*d%[1234567890]", &i, &x, name);
+.PP
+with input
+.IP
+56789 0123 56a72
+.PP
+will assign 56 to
+.BR i ,
+789.0 to
+.BR x ,
+skip `0123',
+and place the string `56\e0' in
+.BR name .
+The next call to
+.B getchar
+will return `a'.
+.SH "SEE ALSO"
+.BR atof (3),
+.BR getc (3),
+.BR printf (3),
+.BR stdarg (3).
+.SH DIAGNOSTICS
+The 
+.B scanf
+functions return
+.SM
+.B EOF
+on end of input,
+and a short count for missing or illegal data items.
+.SH BUGS
+The success of literal matches and suppressed
+assignments is not directly
+determinable.
Index: /trunk/minix/man/man3/servxcheck.3
===================================================================
--- /trunk/minix/man/man3/servxcheck.3	(revision 9)
+++ /trunk/minix/man/man3/servxcheck.3	(revision 9)
@@ -0,0 +1,120 @@
+.TH SERVXCHECK 3
+.SH NAME
+servxcheck \- Internet service access check
+.SH SYNOPSIS
+.ft B
+.nf
+#define _MINIX_SOURCE 1
+#include </net/gen/netdb.h>
+
+int servxcheck(ipaddr_t \fIpeer\fP, const char *\fIservice\fP,
+	void (*\fIlogf\fP)(int \fIpass\fP, const char *\fIname\fP));
+char *servxfile(const char *\fIfile\fP);
+.fi
+.ft R
+.SH DESCRIPTION
+.B Servxcheck()
+is used by programs like
+.B inetd
+to perform an access check on the host connected to the other end of the TCP
+channel that has IP address
+.IR peer .
+.PP
+.B Servxcheck()
+translates the IP address to the
+associated host name if necessary, and checks if the host is granted access
+as guided by the file
+.BR /etc/serv.access .
+(See
+.BR serv.access (5).)
+The service name used to search the access file is passed by the caller as
+.IR service .
+These names should be the same as the service names in
+.BR /etc/services .
+.PP
+The caller should use the NWIOGTCPCONF ioctl() call to find out what the
+IP address of the remote end is.  It is wise to bypass the
+.B servxcheck()
+call if the remote end happens to be the local machine (remaddr == locaddr),
+so that local connections aren't impeded by slow checks.
+.B Servxcheck()
+will itself allow connections from 127.0.0.1/8 immediately, so you
+don't have to check for that.  Example of use:
+.PP
+.RS
+.nf
+.ta +4n +4n +4n
+if (ioctl(fd, NWIOGTCPCONF, &tcpconf) < 0
+	|| tcpconf.nwtc_remaddr == tcpconf.nwtc_locaddr
+	|| servxcheck(tcpconf.nwtc_remaddr, service_name, NULL)
+) {
+	serve();
+}
+.fi
+.RE
+.PP
+An attempt to connect to a service is logged if the access is denied.  You
+can use the special checkword "\fBlog\fP" to also log if access is granted.
+Logging will be done with
+.B syslog()
+at the
+.B warning
+level.
+A syntax error in the access file may be logged under the
+.B err
+level.
+The caller must use
+.B openlog()
+to set the appropriate logging facility.  One may do one's own logging by
+supplying a
+.I logf
+function that will be called by
+.B servxcheck
+with a first argument that is true if access is granted, false if
+denied, and a second argument that is the name of the remote host whose
+access has been checked.
+.PP
+The default is to fail the check unless the access file says otherwise.
+Strange errors make the check succeed.  (We do not want
+remote access to fail because of some system error.)  Note that this
+function is not meant to check access to the system, that's what
+passwords and such are for, but only to limit access to those who are
+allowed to use the services the system offers.
+.PP
+Connections from a machine to itself are accepted immediately.  No further
+checks, no logging.
+.PP
+.B Servxfile()
+may be used to specify a file other than the default
+.BR /etc/serv.access .
+This is useful for programs started from
+.B inetd
+that want to handle the access check themselves, using a private access file.
+The return value of
+.B servxfile()
+is the pathname of the old access file.  Only a pointer to the new path is
+saved, the caller must keep the string it points to intact.
+.SH FILES
+.TP 25n
+.B /etc/serv.access
+Default access check file.
+.SH "SEE ALSO"
+.BR syslog (3),
+.BR serv.access (5),
+.BR services (5),
+.BR inetd (8).
+.SH DIAGNOSTICS
+.B Servxcheck()
+returns 0 if the access is denied, 1 if granted.
+.PP
+Typical syslog message:
+.PP
+.RS
+Jan 10 20:27:20 flotsam inetd[174]: service 'shell' granted to jetsam.cs.vu.nl
+.RE
+.SH BUGS
+IP and DNS based access checks will stop most crackers, but not the really
+determined ones.  Luckily MINIX 3 is sufficiently strange to thwart the well
+known cracking schemes.  But don't ever allow yourself to feel secure.
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man3/setbuf.3
===================================================================
--- /trunk/minix/man/man3/setbuf.3	(revision 9)
+++ /trunk/minix/man/man3/setbuf.3	(revision 9)
@@ -0,0 +1,112 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)setbuf.3s	6.2 (Berkeley) 5/12/86
+.\"
+.TH SETBUF 3  "May 12, 1986"
+.UC 4
+.SH NAME
+setbuf, setvbuf \- assign buffering to a stream
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdio.h>
+
+int setbuf(FILE *\fIstream\fP, char *\fIbuf\fP)
+int setvbuf(FILE *\fIstream\fP, char *\fIbuf\fP, int \fItype\fP, size_t \fIsize\fP)
+.SH DESCRIPTION
+The three types of buffering available are unbuffered, block buffered,
+and line buffered.
+When an output stream is unbuffered, information appears on the
+destination file or terminal as soon as written;
+when it is block buffered many characters are saved up and written as a block;
+when it is line buffered characters are saved up until a newline is
+encountered or input is read from stdin.
+.B Fflush
+(see 
+.BR fclose (3))
+may be used to force the block out early.
+Normally all files are block buffered.
+A buffer is obtained from
+.BR  malloc (3)
+upon the first
+.B getc
+or
+.BR  putc (3)
+on the file.
+If the standard stream
+.B stdout
+refers to a terminal it is line buffered.
+The standard stream
+.B stderr
+is always unbuffered.
+.PP
+.B Setbuf
+is used after a stream has been opened but before it is read or written.
+The character array
+.I buf
+is used instead of an automatically allocated buffer.  If
+.I buf
+is the constant pointer
+.SM
+.BR NULL ,
+input/output will be completely unbuffered.
+A manifest constant 
+.SM
+.B BUFSIZ
+tells how big an array is needed:
+.IP
+.B char
+buf[BUFSIZ];
+.PP
+.BR Setvbuf ,
+an alternate form of 
+.BR setbuf ,
+is used after a stream has been opened but before it is read or written.
+It has three uses, depending on the value of the
+.IR type
+argument:
+.TP 5
+.B "setvbuf(\fIstream\fP, \fIbuf\fP, _IOFBF, \fIsize\fP)"
+Causes input/output to be fully buffered using the character array
+.I buf
+whose size is determined by the 
+.I size
+argument.
+If
+.I buf
+is the constant pointer
+.SM
+.BR NULL ,
+then an automatically allocated buffer will be used.
+.TP 5
+.B "setvbuf(\fIstream\fP, \fIbuf\fP, _IOLBF, \fIsize\fP)"
+Like above, except that output will be line buffered, i.e. the buffer will
+be flushed when a newline is written, the buffer is full, or input is
+requested.
+.TP 5
+.B "setvbuf(\fIstream\fP, \fIbuf\fP, _IONBF, \fIsize\fP)"
+Causes input/output to be completely unbuffered.
+.I Buf
+and
+.I size
+are ignored.
+.PP
+A file can be changed between unbuffered, line buffered, or block buffered
+by using
+.B freopen
+(see
+.BR fopen (3))
+followed by the appropriate
+.B setvbuf
+call.
+.SH "SEE ALSO"
+.BR fopen (3),
+.BR getc (3),
+.BR putc (3),
+.BR malloc (3),
+.BR fclose (3),
+.BR puts (3),
+.BR printf (3),
+.BR fread (3).
Index: /trunk/minix/man/man3/sigset.3
===================================================================
--- /trunk/minix/man/man3/sigset.3	(revision 9)
+++ /trunk/minix/man/man3/sigset.3	(revision 9)
@@ -0,0 +1,85 @@
+.TH SIGSET 3
+.SH NAME
+sigset, sigaddset, sigdelset, sigemptyset, sigfillset, sigismember \- manipulate signal sets
+.SH SYNOPSIS
+.ft B
+#include <signal.h>
+
+.nf
+int sigaddset(sigset_t *\fIset\fP, int \fIsig\fP)
+int sigdelset(sigset_t *\fIset\fP, int \fIsig\fP)
+int sigemptyset(sigset_t *\fIset\fP)
+int sigfillset(sigset_t *\fIset\fP)
+int sigismember(const sigset_t *\fIset\fP, int \fIsig\fP)
+.fi
+.ft P
+.SH DESCRIPTION
+The system calls that handle signals, such as
+.BR sigaction (2)
+and
+.BR sigprocmask (2)
+use sets of signals to keep a process from being interrupted by those
+signals while executing a signal handler or a critical code segment.  These
+signal sets are manipulated by the following functions:
+.TP 5
+.B "int sigaddset(sigset_t *\fIset\fP, int \fIsig\fP)"
+Add signal
+.I sig
+to the signal set referenced by
+.IR set .
+.TP
+.B "int sigdelset(sigset_t *\fIset\fP, int \fIsig\fP)"
+Remove signal
+.I sig
+from the signal set referenced by
+.IR set .
+.TP
+.B "int sigemptyset(sigset_t *\fIset\fP)"
+Initialize the signal set referenced by
+.I set
+to an empty set.
+.TP
+.B "int sigfillset(sigset_t *\fIset\fP)"
+Initialize the signal set referenced by
+.I set
+to an full set, i.e. all signals are in the set.
+.TP
+.B "int sigismember(const sigset_t *\fIset\fP, int \fIsig\fP)"
+Return
+.B 1
+if the signal
+.I sig
+is present in the set referenced by
+.IR set ,
+.B 0
+otherwise.
+.SH "SEE ALSO"
+.BR sigaction (2),
+.BR sigpending (2),
+.BR sigprocmask (2),
+.BR sigsuspend (2).
+.SH DIAGNOSTICS
+All functions except
+.B sigismember
+return
+.B 0
+on success.
+.B Sigismember
+returns
+.B 0
+or
+.B 1
+on success.  They return
+.B \-1
+with error code
+.B EINVAL
+for an invalid signal number.  (They do not use
+.B EFAULT
+for a bad
+.I set
+address, but will simply cause a segmentation violation.)
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+
+.\"
+.\" $PchId: sigset.3,v 1.2 1996/04/11 06:39:09 philip Exp $
Index: /trunk/minix/man/man3/sleep.3
===================================================================
--- /trunk/minix/man/man3/sleep.3	(revision 9)
+++ /trunk/minix/man/man3/sleep.3	(revision 9)
@@ -0,0 +1,31 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)sleep.3	6.2 (Berkeley) 5/12/86
+.\"
+.TH SLEEP 3  "May 12, 1986"
+.UC 4
+.SH NAME
+sleep \- suspend execution for interval
+.SH SYNOPSIS
+.nf
+.ft B
+#include <unistd.h>
+
+unsigned int sleep(unsigned int \fIseconds\fP)
+.fi
+.SH DESCRIPTION
+The current process is suspended from execution for the number
+of seconds specified by the argument.
+.PP
+The routine is implemented by setting an alarm timer
+and pausing until it occurs.
+The previous state of this timer is saved and restored.
+If the sleep time exceeds the time to the expiration of the
+previous timer,
+the process sleeps only until the signal would have occurred, and the
+signal is sent 1 second later.
+.SH "SEE ALSO"
+.BR alarm (2),
+.BR pause (2).
Index: /trunk/minix/man/man3/stdarg.3
===================================================================
--- /trunk/minix/man/man3/stdarg.3	(revision 9)
+++ /trunk/minix/man/man3/stdarg.3	(revision 9)
@@ -0,0 +1,123 @@
+.\"	@(#)varargs.3	6.3 (Berkeley) 5/15/86
+.\"
+.TH STDARG 3  "May 15, 1986"
+.AT 3
+.SH NAME
+stdarg \- variable argument list
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdarg.h>
+
+void va_start(va_list \fIap\fP, \fIargtypeN\fP \fIparmN\fP)
+\fItype\fP va_arg(va_list \fIap\fP, \fItype\fP)
+void va_end(va_list \fIap\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+This set of macros provides a means of writing portable procedures that
+accept variable argument lists.
+Routines having variable argument lists (such as
+.BR printf (3))
+that do not use
+.B stdarg
+are inherently nonportable, since different
+machines use different argument passing conventions.
+.PP
+A function that accepts a variable argument list is declared with "..." at
+the end of its parameter list.  It must have at least one normal argument
+before the "...".  For example:
+.PP
+.RS
+.nf
+int printf(const char *format, ...) { /* code */ }
+int fprintf(FILE *stream, const char *format, ...) { /* code */ }
+.fi
+.RE
+.PP
+.B va_list
+is a type which is used for the variable
+.I ap
+within the body of a variable argument function which is used to traverse
+the list.
+.PP
+.B va_start\c
+.RI ( ap ,
+.IR parmN )
+is called to initialize
+.I ap
+to the beginning of the list.  The last true parameter of the function,
+.IR parmN ,
+must be supplied to allow
+.B va_start
+to compute the address of the first variable parameter.
+.PP
+.B va_arg\c
+.RI ( ap ,
+.IR type )
+will return the next argument in the list pointed to by
+.IR ap .
+.I Type
+is the type to which the expected argument will be converted
+when passed as an argument.
+.PP
+Different types can be mixed, but it is up
+to the routine to know what type of argument is
+expected, since it cannot be determined at runtime.
+.PP
+.B va_end\c
+.RI ( ap )
+must be used to finish up.
+.PP
+Multiple traversals, each bracketed by
+.B va_start
+\&...
+.B va_end,
+are possible.
+.SH EXAMPLE
+.nf
+.ta +4n +4n +4n +4n
+	\fB#include\fP <stdarg.h>
+.sp 0.4
+	execl(\fBconst char\fP *path, \fB...\fP)
+	{
+		\fBva_list\fP ap;
+		\fBchar\fP *args[100];
+		\fBint\fP argno = 0;
+
+		\fBva_start\fP(ap, path);
+		\fBwhile\fP ((args[argno++] = \fBva_arg\fP(ap, \fBchar\fP *)) != NULL) {}
+		\fBva_end\fP(ap);
+		\fBreturn\fP execv(path, args);
+	}
+.DT
+.fi
+.SH NOTES
+It is up to the calling routine to determine how many arguments
+there are, since it is not possible to determine this from the
+stack frame.  For example,
+.B execl
+passes a null pointer to signal the end of the list.
+.B Printf
+can tell how many arguments are supposed to be there by the format.
+.PP
+The macros
+.B va_start
+and
+.B va_end
+may be arbitrarily complex;
+for example,
+.B va_start
+might contain an opening brace,
+which is closed by a matching brace in
+.BR va_end .
+Thus, they should only be used where they could
+be placed within a single complex statement.
+.SH BUGS
+It is impossible to properly show the macros as C declarations as is
+done in the synopsis.  They can never be coded as C functions, because
+all three macros use their arguments by address, and the
+.I type
+field is certainly impossible.
+Just look at them as being part of the C language, like
+.BR sizeof .
Index: /trunk/minix/man/man3/stdio.3
===================================================================
--- /trunk/minix/man/man3/stdio.3	(revision 9)
+++ /trunk/minix/man/man3/stdio.3	(revision 9)
@@ -0,0 +1,199 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)stdio.3s	6.2 (Berkeley) 5/13/86
+.\"
+.TH STDIO 3 "May 13, 1986"
+.UC 4
+.SH NAME
+stdio \- standard buffered input/output package
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdio.h>
+
+FILE *stdin;
+FILE *stdout;
+FILE *stderr;
+.ft R
+.fi
+.SH DESCRIPTION
+The functions in the standard I/O library constitute a user-level buffering
+scheme.  The in-line macros
+.B getc
+and
+.BR  putc (3)
+handle characters quickly.  The higher level routines
+.BR gets ,
+.BR fgets ,
+.BR scanf ,
+.BR fscanf ,
+.BR fread ,
+.BR puts ,
+.BR fputs ,
+.BR printf ,
+.BR fprintf ,
+.BR fwrite
+all use
+.B getc
+and
+.BR putc ;
+they can be freely intermixed.
+.PP
+A file with associated buffering is called a
+.IR stream ,
+and is declared to be a pointer to a defined type
+.SM
+.BR FILE .
+.BR  Fopen (3)
+creates certain descriptive data for a stream
+and returns a pointer to designate the stream in all further transactions.
+There are three normally open streams with constant pointers declared in
+the include file and associated with the standard open files:
+.TP 10n
+.B stdin
+standard input file
+.br
+.ns
+.TP
+.B stdout
+standard output file
+.br
+.ns
+.TP
+.B stderr
+standard error file
+.PP
+A constant `pointer'
+.SM
+.B NULL
+(0)
+designates no stream at all.
+.PP
+An integer constant
+.SM
+.B EOF
+(\-1) is returned upon end of file or error by integer functions that
+deal with streams.
+.PP
+Any routine that uses the standard input/output package
+must include the header file
+.RI < stdio.h >
+of pertinent macro definitions.
+The functions and constants mentioned in the standard I/O manual pages
+are declared in the include file and need no further declaration.
+The constants, and the following `functions' are
+implemented as macros; redeclaration of these names is perilous:
+.BR clearerr ,
+.BR getc ,
+.BR getchar ,
+.BR putc ,
+.BR putchar ,
+.BR feof ,
+.BR ferror ,
+.BR fileno .
+.SH "SEE ALSO"
+.BR open (2),
+.BR close (2),
+.BR read (2),
+.BR write (2),
+.BR fclose (3),
+.BR ferror (3),
+.BR fopen (3),
+.BR fread (3),
+.BR fseek (3),
+.BR getc (3),
+.BR gets (3),
+.BR printf (3),
+.BR putc (3),
+.BR puts (3),
+.BR scanf (3),
+.BR setbuf (3),
+.BR ungetc (3).
+.SH DIAGNOSTICS
+The value
+.SM
+.B EOF
+is returned uniformly to indicate that a
+.SM
+.B FILE
+pointer has not been initialized with
+.BR fopen ,
+input (output) has been attempted on an output (input) stream, or a
+.SM
+.B FILE
+pointer designates corrupt or otherwise unintelligible
+.SM
+.B FILE
+data.
+.PP
+For purposes of efficiency, this implementation of the standard library
+has been changed to line buffer output to a terminal by default and attempts
+to do this transparently by flushing the output whenever a 
+.BR read (2)
+from the standard input is necessary.  This is almost always transparent,
+but may cause confusion or malfunctioning of programs which use
+standard i/o routines but use
+.BR read (2)
+themselves to read from the standard input.
+.PP
+In cases where a large amount of computation is done after printing
+part of a line on an output terminal, it is necessary to
+.BR fflush (3)
+the standard output before going off and computing so that the output
+will appear.
+.SH BUGS
+The standard buffered functions do not interact well with certain other
+library and system functions, especially \fBfork\fP and \fBabort\fP.
+.SH "LIST OF FUNCTIONS"
+.sp 2
+.nf
+.ta \w'setlinebuf'u+2n +\w'setbuf(3)'u+10n
+\fBName\fP	\fBAppears on Page\fP	\fBDescription\fP
+.ta \w'setlinebuf'u+4n +\w'setbuf(3)'u+4n
+.sp 5p
+clearerr	ferror(3)	stream status inquiries
+fclose	fclose(3)	close or flush a stream
+fdopen	fopen(3)	open a stream
+feof	ferror(3)	stream status inquiries
+ferror	ferror(3)	stream status inquiries
+fflush	fclose(3)	close or flush a stream
+fgetc	getc(3)	get character or word from stream
+fgets	gets(3)	get a string from a stream
+fileno	ferror(3)	stream status inquiries
+fopen	fopen(3)	open a stream
+fprintf	printf(3)	formatted output conversion
+fputc	putc(3)	put character or word on a stream
+fputs	puts(3)	put a string on a stream
+fread	fread(3)	buffered binary input/output
+freopen	fopen(3)	open a stream
+fscanf	scanf(3)	formatted input conversion
+fseek	fseek(3)	reposition a stream
+ftell	fseek(3)	reposition a stream
+fwrite	fread(3)	buffered binary input/output
+getc	getc(3)	get character or word from stream
+getchar	getc(3)	get character or word from stream
+gets	gets(3)	get a string from a stream
+getw	getc(3)	get character or word from stream
+printf	printf(3)	formatted output conversion
+putc	putc(3)	put character or word on a stream
+putchar	putc(3)	put character or word on a stream
+puts	puts(3)	put a string on a stream
+putw	putc(3)	put character or word on a stream
+rewind	fseek(3)	reposition a stream
+scanf	scanf(3)	formatted input conversion
+setbuf	setbuf(3)	assign buffering to a stream
+setvbuf	setbuf(3)	assign buffering to a stream
+snprintf	printf(3)	formatted output conversion
+sprintf	printf(3)	formatted output conversion
+sscanf	scanf(3)	formatted input conversion
+ungetc	ungetc(3)	push character back into input stream
+vfprintf	printf(3)	formatted output conversion
+vfscanf	scanf(3)	formatted input conversion
+vprintf	printf(3)	formatted output conversion
+vscanf	scanf(3)	formatted input conversion
+vsnprintf	printf(3)	formatted output conversion
+vsprintf	printf(3)	formatted output conversion
+vsscanf	scanf(3)	formatted input conversion
+.fi
Index: /trunk/minix/man/man3/string.3
===================================================================
--- /trunk/minix/man/man3/string.3	(revision 9)
+++ /trunk/minix/man/man3/string.3	(revision 9)
@@ -0,0 +1,149 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)string.3	6.1 (Berkeley) 5/15/85
+.\"
+.TH STRING 3  "May 15, 1985"
+.UC 4
+.SH NAME
+string, strcat, strncat, strcmp, strncmp, strcpy, strncpy, strlen, strchr, strrchr, strerror, memcmp, memcpy, memmove, memchr, memset, index, rindex \- string operations
+.SH SYNOPSIS
+.nf
+.ft B
+#include <string.h>
+
+char *strcat(char *\fIs1\fP, const char *\fIs2\fP)
+char *strncat(char *\fIs1\fP, const char *\fIs2\fP, size_t \fIn\fP)
+int strcmp(const char *\fIs1\fP, const char *\fIs2\fP)
+int strncmp(const char *\fIs1\fP, const char *\fIs2\fP, size_t \fIn\fP)
+char *strcpy(char *\fIs1\fP, const char *\fIs2\fP)
+char *strncpy(char *\fIs1\fP, const char *\fIs2\fP, size_t \fIn\fP)
+size_t strlen(const char *\fIs\fP)
+char *strchr(const char *\fIs\fP, int \fIc\fP)
+char *strrchr(const char *\fIs\fP, int \fIc\fP)
+char *strerror(int \fIerrnum\fP)
+int memcmp(const void *\fIs1\fP, const void *\fIs2\fP, size_t \fIn\fP)
+void *memcpy(void *\fIs1\fP, const void *\fIs2\fP, size_t \fIn\fP)
+void *memmove(void *\fIs1\fP, const void *\fIs2\fP, size_t \fIn\fP)
+void *memchr(const void *\fIs\fP, int \fIc\fP, size_t \fIn\fP)
+void *memset(void *\fIs\fP, int \fIc\fP, size_t \fIn\fP)
+char *index(const char *\fIs\fP, int \fIc\fP)
+char *rindex(const char *\fIs\fP, int \fIc\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+These functions operate on null-terminated strings.
+They do not check for overflow of any receiving string.
+.PP
+.B Strcat
+appends a copy of string
+.I s2
+to the end of string
+.IR s1 .
+.B Strncat
+copies at most
+.I n
+characters.  Both return a pointer to the null-terminated result.
+.PP
+.B Strcmp
+compares its arguments and returns an integer
+greater than, equal to, or less than 0, according as
+.I s1
+is lexicographically greater than, equal to, or less than
+.IR s2 .
+.B Strncmp
+makes the same comparison but looks at at most
+.I n
+characters.
+.PP
+.B Strcpy
+copies string
+.I s2
+to
+.IR s1 ,
+stopping after the null character has been moved.
+.B Strncpy
+copies exactly
+.I n
+characters, truncating or null-padding
+.I s2;
+the target may not be null-terminated if the length of
+.I s2
+is
+.I n
+or more.  Both return
+.IR s1 .
+.PP
+.B Strlen
+returns the number of non-null characters in
+.IR s .
+.PP
+.B Strchr
+.RB ( strrchr )
+returns a pointer to the first (last) occurrence of character 
+.I c
+in string
+.I s,
+or null if
+.I c
+does not occur in the string.
+.PP
+.B Strerror
+returns the error string for the system call error
+.IR errnum .
+See
+.BR intro (2).
+.PP
+.B Memcmp
+is like
+.B strcmp
+except that the strings are memory blocks of length
+.IR n .
+Null characters are treated as ordinary characters.
+.PP
+.B Memcpy
+copies
+.I n
+bytes from the location pointed to by
+.I s2
+to
+.IR s1 .
+.B Memmove
+is like memcpy, except that it can handle overlap between the two strings.
+Both functions return
+.IR s1 .
+.PP
+.B Memchr
+returns a pointer to the first occurrence of character
+.I c
+in string
+.I s,
+or null if
+.I c
+does not occur in the string.
+.PP
+.B Memset
+sets
+.I n
+bytes to
+.I c
+starting at location
+.IR s .
+It returns
+.IR s .
+.PP
+.B Index
+and
+.B rindex
+are obsolete versions of
+.B strchr
+and
+.BR strrchr .
+New code should avoid using them.
+.SH NOTES
+Characters are compared as
+.BR "unsigned char" ,
+whether
+.B char
+itself is signed or not.
Index: /trunk/minix/man/man3/syslog.3
===================================================================
--- /trunk/minix/man/man3/syslog.3	(revision 9)
+++ /trunk/minix/man/man3/syslog.3	(revision 9)
@@ -0,0 +1,198 @@
+.\" Written  Feb 1994 by Steve Greenland (stevegr@neosoft.com)
+.\"
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one
+.\" 
+.\" Since the Linux kernel and libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date.  The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein.  The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\" 
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\"
+.\" from SYSLOG 3 "15 Feb 1994" "Linux" "Linux Programmer's Manual"
+.\" Modified for Minix porting by G. Falzoni <gfalzoni@inwind.it>
+.\" $Id: syslog.3,v 1.1 2006/04/03 14:59:51 beng Exp $
+.\"
+.\" Local macros
+.de Xr
+.BR \\$1 (\\$2)\\$3
+..
+.de LB
+.TP \\$1
+\\fB\\$2\\fR
+\\$3
+..
+.de LI
+.TP \\$1
+\\fI\\$2\\fR
+\\$3
+..
+.de LR
+.TP \\$1
+\\fR\\$2\\fR
+\\$3
+..
+.\" end local macros
+.TH SYSLOG 3 "Jan. 18, 2000"
+.SH NAME
+openlog, syslog, closelog \- send messages to the system logger
+.SH SYNOPSIS
+.B #include <syslog.h>
+.sp
+.BI "void openlog(char " *ident ", int " option ", int  " facility)
+.sp
+.BI "void syslog(int " priority ", char " *format ", ...)"
+.sp
+.BI "void closelog(void)"
+.sp
+.SH DESCRIPTION
+.B openlog()
+opens a connection to the system logger for a program.  The string pointed to by
+.I ident 
+is added to each message, and is typically set to the program name.  Values for
+.I option
+and
+.I facility
+are given in the next section.  Its use is optional.  It will automatically be called by 
+.B syslog()
+if necessary, in which case 
+.I ident
+will default to "syslog".
+.sp
+.B syslog()
+generates a log message, which will be distributed by 
+.Xr syslogd 8 .
+.I priority
+is a combination of the
+.I facility
+and the 
+.IR level , 
+values for which are given in the next section.  The remaining arguments
+are a 
+.IR format ,
+as in 
+.Xr printf 3
+and any arguments required by the 
+.IR format . 
+.\" except that the two character %m will be replaced by the error message string 
+.\" RI ( strerror )
+.\" corresponding to the present value of 
+.\" IR errno .
+.sp
+.B closelog()
+closes the descriptor being used to write to the system logger.  Its use is optional.
+.SH "PARAMETERS"
+This section lists the parameters used to set the values of 
+.IR option , " facility" ", and " priority .
+.SS option
+The
+.I option
+argument to 
+.B openlog()
+is an OR of any of these:
+.TP
+.B LOG_CONS
+write directly to system console if there is an error while sending to
+system logger
+.TP
+.B LOG_NDELAY
+open the connection immediately (normally, the connection is opened when
+the first message is logged)
+.TP
+.B LOG_PERROR
+print to stderr as well
+.TP
+.B LOG_PID
+include PID with each message
+.SS facility 
+The 
+.I facility
+argument is used to specify what type of program is logging the message.
+This lets the configuration file specify that messages from different
+facilities will be handled differently.
+.TP
+.B LOG_AUTH
+security/authorization messages (DEPRECATED Use 
+.B LOG_AUTHPRIV 
+instead)
+.TP
+.B LOG_AUTHPRIV
+security/authorization messages (private) 
+.TP
+.B LOG_CRON
+clock daemon 
+.RB ( cron " and " at )
+.TP
+.B LOG_DAEMON
+other system daemons
+.TP
+.B LOG_KERN
+kernel messages
+.TP
+.BR LOG_LOCAL0 " through " LOG_LOCAL7
+reserved for local use
+.TP
+.B LOG_LPR
+line printer subsystem
+.TP
+.B LOG_MAIL
+mail subsystem
+.TP
+.B LOG_NEWS
+USENET news subsystem
+.TP
+.B LOG_SYSLOG
+messages generated internally by
+.B syslogd 
+.TP
+.BR LOG_USER (default)
+generic user-level messages 
+.TP
+.B LOG_UUCP
+UUCP subsystem
+.SS level
+This determines the importance of the message.  The levels are, in order
+of decreasing importance:
+.TP
+.B LOG_EMERG
+system is unusable
+.TP
+.B LOG_ALERT
+action must be taken immediately
+.TP
+.B LOG_CRIT
+critical conditions
+.TP
+.B LOG_ERR
+error conditions
+.TP
+.B LOG_WARNING
+warning conditions
+.TP
+.B LOG_NOTICE
+normal, but significant, condition
+.TP
+.B LOG_INFO
+informational message
+.TP
+.B LOG_DEBUG
+debug-level message
+.SH HISTORY
+A
+.B syslog
+function call appeared in BSD 4.2.
+.SH SEE ALSO
+.Xr logger 1 , 
+.Xr syslog.conf 5 , 
+.Xr syslogd 8 .
Index: /trunk/minix/man/man3/system.3
===================================================================
--- /trunk/minix/man/man3/system.3	(revision 9)
+++ /trunk/minix/man/man3/system.3	(revision 9)
@@ -0,0 +1,30 @@
+.\"	@(#)system.3	6.1 (Berkeley) 5/15/85
+.\"
+.TH SYSTEM 3 "May 15, 1985"
+.AT 3
+.SH NAME
+system \- issue a shell command
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdlib.h>
+
+int system(const char *\fIstring\fP)
+.fi
+.SH DESCRIPTION
+.B System
+causes the
+.I string
+to be given to
+.BR  sh (1)
+as input as if the string had been typed as a command
+at a terminal.
+The current process waits until the shell has
+completed, then returns the exit status of the shell.
+.SH "SEE ALSO"
+.BR sh (1),
+.BR popen (3),
+.BR execve (2),
+.BR wait (2).
+.SH DIAGNOSTICS
+Exit status 127 indicates the shell couldn't be executed.
Index: /trunk/minix/man/man3/termcap.3
===================================================================
--- /trunk/minix/man/man3/termcap.3	(revision 9)
+++ /trunk/minix/man/man3/termcap.3	(revision 9)
@@ -0,0 +1,167 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)termcap.3x	6.1 (Berkeley) 5/15/85
+.\"
+.TH TERMCAP 3 "May 15, 1985"
+.UC 4
+.SH NAME
+termcap, tgetent, tgetnum, tgetflag, tgetstr, tgoto, tputs \- terminal independent operation routines
+.SH SYNOPSIS
+.nf
+.ft B
+#include <termcap.h>
+
+int tgetent(char *\fIbp\fP, char *\fIname\fP)
+int tgetflag(char *\fIid\fP)
+int tgetnum(char *\fIid\fP)
+char *tgetstr(char *\fIid\fP, char **\fIarea\fP)
+char *tgoto(char *\fIcm\fP, int \fIdestcol\fP, int \fIdestline\fP)
+int tputs(char *\fIcp\fP, int \fIaffcnt\fP, void (*\fIoutc\fP)(int))
+.ft R
+.fi
+.SH DESCRIPTION
+These functions extract and use capabilities from the terminal capability data
+base
+.BR termcap (5).
+These are low level routines;
+see
+.BR curses (3)
+for a higher level package.
+.PP
+.B Tgetent
+extracts the entry for terminal
+.I name
+into the buffer at
+.IR bp .
+.I Bp
+should be a character buffer of size
+1024 and must be retained through all subsequent calls
+to
+.BR tgetnum ,
+.BR tgetflag ,
+and
+.BR tgetstr .
+.B Tgetent
+returns \-1 if it cannot find a termcap
+file, 0 if the terminal name given does not have an entry,
+and 1 if all goes well.
+.PP
+.B Tgetent
+uses the following recipe to find the termcap file and entry
+.IR name :
+.PP
+.in +5n
+if $TERMCAP is itself a termcap entry for
+.I name
+.br
+then
+.in +5n
+use $TERMCAP
+.in -5n
+elif $TERMCAP names a file
+.br
+then
+.in +5n
+use entry
+.I name
+found in that file
+.in -5n
+elif this is Minix-vmd
+.br
+then
+.in +5n
+if $TERMPATH is defined
+.br
+then
+.in +5n
+search the termcap files named in $TERMPATH for the first occurance of a
+.I name
+entry and use that entry
+.in -5n
+else
+.in +5n
+the path
+.B $HOME/.termcap:/etc/termcap:/usr/etc/termcap"
+is searched for entry
+.I name
+.in -5n
+fi
+.in -5n
+fi
+.in -5n
+.RE
+.PP
+.B Tgetnum
+gets the numeric value of capability
+.IR id ,
+returning \-1 if is not given for the terminal.
+.B Tgetflag
+returns 1 if the specified capability is present in
+the terminal's entry, 0 if it is not.
+.B Tgetstr
+returns the string value of the capability
+.IR id ,
+places it in the buffer at
+.IR area ,
+and advances the
+.I area
+pointer.
+It decodes the abbreviations for this field described in
+.BR termcap (5),
+except for cursor addressing and padding information.
+.B Tgetstr
+returns NULL if the capability was not found.
+.PP
+.B Tgoto
+returns a cursor addressing string decoded from
+.I cm
+to go to column
+.I destcol
+in line
+.IR destline .
+It uses the external variables
+.B UP
+(from the \fBup\fR capability)
+and
+.B BC
+(if \fBbc\fR is given rather than \fBbs\fR)
+if necessary to avoid placing \fB\en\fR, \fB^D\fR or \fB^@\fR in
+the returned string.
+(Programs which call tgoto should be sure to turn off the XTABS bit(s),
+since
+.B tgoto
+may now output a tab.
+Note that programs using termcap should in general turn off XTABS
+anyway since some terminals use CTRL-I for other functions,
+such as nondestructive space.)
+If a \fB%\fR sequence is given which is not understood, then
+.B tgoto
+returns \*(lqOOPS\*(rq.
+.PP
+.B Tputs
+decodes the leading padding information of the string
+.IR cp ;
+.I affcnt
+gives the number of lines affected by the operation, or 1 if this is
+not applicable,
+.I outc
+is a routine which is called with each character in turn.
+The external variable
+.B ospeed
+should contain the output speed of the terminal as encoded by
+.BR stty (3).
+The external variable
+.B PC
+should contain a pad character to be used (from the \fBpc\fR capability)
+if a null (\fB^@\fR) is inappropriate.
+.SH SEE ALSO
+.BR curses (3),
+.BR termcap (5).
+.SH AUTHOR
+William Joy
+.SH NOTES
+The MINIX 3 implementation does not support any of the external variables,
+only the functions calls.  The Minix-vmd termcap does support it all,
+although noone in his right mind meddles with those variables.
Index: /trunk/minix/man/man3/termios.3
===================================================================
--- /trunk/minix/man/man3/termios.3	(revision 9)
+++ /trunk/minix/man/man3/termios.3	(revision 9)
@@ -0,0 +1,155 @@
+.TH TERMIOS 3
+.SH NAME
+termios, tcgetattr, tcsetattr, cfgetispeed, cfgetospeed, cfsetispeed, cfsetospeed, tcsendbreak, tcdrain, tcflush, tcflow \- change terminal attributes
+.SH SYNOPSIS
+.ft B
+.nf
+#include <termios.h>
+
+int tcgetattr(int \fIfd\fP, struct termios *\fItp\fP)
+int tcsetattr(int \fIfd\fP, int \fIaction\fP, const struct termios *\fItp\fP)
+
+speed_t cfgetispeed(const struct termios *\fItp\fP)
+speed_t cfgetospeed(const struct termios *\fItp\fP)
+int cfsetispeed(struct termios *\fItp\fP, speed_t \fIspeed\fP)
+int cfsetospeed(struct termios *\fItp\fP, speed_t \fIspeed\fP)
+
+int tcsendbreak(int \fIfd\fP, int \fIduration\fP)
+int tcdrain(int \fIfd\fP)
+int tcflush(int \fIfd\fP, int \fIqueue_selector\fP)
+int tcflow(int \fIfd\fP, int \fIaction\fP)
+.fi
+.ft P
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+These are the user functions that modify the tty attributes mentioned in
+.BR tty (4).
+In the following,
+.I fd
+refers to an open terminal device file,
+.I tp
+is the address of a
+.BR "struct termios" ,
+and
+.I speed
+and values of type
+.B speed_t
+are equal to one of the
+.BR B0 ,
+.BR B50 ,
+etc. baud rate symbols.  All functions, symbols, and types are declared in
+.BR <termios.h> .
+.PP
+The effects of the tty functions are:
+.TP
+.B tcgetattr(\fIfd\fP, \fItp\fP)
+Get the current settings of the tty attributes.
+.TP
+.B tcsetattr(\fIfd\fP, TCSANOW, \fItp\fP)
+Set the terminal attributes.  The change occurs immediately.
+.TP
+.B tcsetattr(\fIfd\fP, TCSADRAIN, \fItp\fP)
+Set the terminal attributes.  The change occurs once all the output waiting
+in the output queues has been transmitted.  This should be used when options
+affecting output are changed.
+.TP
+.B tcsetattr(\fIfd\fP, TCSAFLUSH, \fItp\fP)
+Set the terminal attributes.  But first wait until all the output waiting
+in the output queues has been transmitted.  All input waiting in the input
+queues is then discarded and the change is made.  This should be used when
+switching from canonical to non-canonical mode or vice-versa.  (Oddly
+enough, this is seldom what you want, because it discards typeahead.  An
+editing shell does the Right Thing if it uses
+.B TCSANOW
+instead.  \s-2POSIX\s+2 may not guarantee good results, but in practice most
+systems make the canonical input available in raw mode.)
+.TP
+.B cfgetispeed(\fItp\fP)
+Return the input baud rate encoded in the termios structure.
+.TP
+.B cfgetospeed(\fItp\fP)
+Return the output baud rate encoded in the termios structure.
+.TP
+.B cfsetispeed(\fItp\fP, \fIspeed\fP)
+Encode the new input baud rate into the termios structure.
+.TP
+.B cfsetospeed(\fItp\fP, \fIspeed\fP)
+Encode the new output baud rate into the termios structure.
+.TP
+.B tcsendbreak(\fIfd\fP, \fIduration\fP)
+Emit a break condition on a serial line for a time indicated by
+.IR duration .
+(Always 0.4 seconds under MINIX 3,
+.I duration
+is ignored.)
+.TP
+.B tcdrain(\fIfd\fP)
+Wait until all output waiting in the output queues has been transmitted.
+.TP
+.B tcflush(\fIfd\fP, TCIFLUSH)
+Flush the input queue.  (I.e. discard it.)
+.TP
+.B tcflush(\fIfd\fP, TCOFLUSH)
+Flush the output queue.
+.TP
+.B tcflush(\fIfd\fP, TCIOFLUSH)
+Flush the input and output queues.
+.TP
+.B tcflow(\fIfd\fP, TCOOFF)
+Suspend output.  (Like the effect of
+.BR STOP .)
+.TP
+.B tcflow(\fIfd\fP, TCOON)
+Restart output.  (Like the effect of
+.BR START .)
+.TP
+.B tcflow(\fIfd\fP, TCIOFF)
+Transmit a
+.B STOP
+character intended to make the remote device stop transmitting data.
+.TP
+.B tcflow(\fIfd\fP, TCION)
+Transmit a
+.B START
+character to restart the remote device.
+.SH "SEE ALSO"
+.BR stty (1),
+.BR tty (4).
+.SH DIAGNOSTICS
+All functions return 0 unless otherwise specified, and \-1 on error with
+.B errno
+set to indicate the type of error.  The most notable errors are
+.B ENOTTY
+if
+.I fd
+does not refer to a terminal device, and
+.B EINTR
+if one of the functions waiting for output to drain is interrupted.
+.SH NOTES
+It may be interesting to know that the functions operating on the tty are
+directly translated into the following MINIX 3
+.B ioctl
+requests:
+.BR TCGETS ,
+.BR TCSETS
+(now),
+.BR TCSETSW
+(drain),
+.BR TCSETSF ,
+(flush),
+.BR TCSBRK ,
+.BR TCDRAIN ,
+.BR TCFLSH ,
+and
+.BR TCFLOW .
+You should only use this knowledge when trying to understand the tty driver
+code, of course.
+.SH BUGS
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+
+.\"
+.\" $PchId: termios.3,v 1.2 1996/04/11 06:41:24 philip Exp $
Index: /trunk/minix/man/man3/ttyname.3
===================================================================
--- /trunk/minix/man/man3/ttyname.3	(revision 9)
+++ /trunk/minix/man/man3/ttyname.3	(revision 9)
@@ -0,0 +1,28 @@
+.TH TTYNAME 3
+.SH NAME
+ttyname \- file descriptor to terminal device name
+.SH SYNOPSIS
+.nf
+.ft B
+#define _POSIX_SOURCE	1
+#include <unistd.h>
+
+char *ttyname(int \fIfd\fP)
+.ft P
+.fi
+.SH DESCRIPTION
+.B Ttyname
+searches through the
+.B /dev
+directory for the terminal device file that is associated with file
+descriptor
+.IR fd .
+It returns the full path name of the terminal file if found, NULL is
+returned otherwise.
+.SH "SEE ALSO"
+.BR ttyslot (3).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+
+.\"
+.\" $PchId: ttyname.3,v 1.2 1996/04/11 06:42:17 philip Exp $
Index: /trunk/minix/man/man3/ttyslot.3
===================================================================
--- /trunk/minix/man/man3/ttyslot.3	(revision 9)
+++ /trunk/minix/man/man3/ttyslot.3	(revision 9)
@@ -0,0 +1,56 @@
+.TH TTYSLOT 3
+.SH NAME
+ttyslot, fttyslot \- utmp slot number
+.SH SYNOPSIS
+.nf
+.ft B
+#define _MINIX_SOURCE 1
+#include <unistd.h>
+
+int ttyslot(void)
+int fttyslot(int \fIfd\fP)
+.fi
+.ft P
+.SH DESCRIPTION
+.B Ttyslot()
+returns the index of the login terminal in the
+.B utmp
+file.  It tries
+.B fttyslot()
+on file descriptors
+.BR 0,
+.BR 1,
+and
+.BR 2
+to find the index.
+.PP
+.B Fttyslot()
+returns the utmp index of the terminal associated with file descriptor
+.IR fd .
+First it tries to map
+.I fd
+to a terminal name with
+.BR ttyname (3),
+then it searches the
+.BR ttytab (5)
+database with the
+.BR getttyent (3)
+function for this terminal.  This means that the utmp slot number is the
+same as the ttytab entry number counting from 1.  The value 0 is returned if
+no slot number can be found for a file descriptor.
+.SH "SEE ALSO"
+.BR ttyname (3),
+.BR getttyent (3),
+.BR utmp (5),
+.BR ttytab (5),
+.BR init (8).
+.SH NOTES
+Since 0 is used as an error return this means that the first entry in the
+utmp file is not used.
+.PP
+.B Ttyslot()
+is often found in a UNIX implementation,
+.B fttyslot()
+is MINIX 3 specific.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man3/ungetc.3
===================================================================
--- /trunk/minix/man/man3/ungetc.3	(revision 9)
+++ /trunk/minix/man/man3/ungetc.3	(revision 9)
@@ -0,0 +1,41 @@
+.\"	@(#)ungetc.3s	6.1 (Berkeley) 5/15/85
+.\"
+.TH UNGETC 3  "May 15, 1985"
+.AT 3
+.SH NAME
+ungetc \- push character back into input stream
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdio.h>
+
+int ungetc(int \fIc\fP, FILE *\fIstream\fP)
+.ft R
+.fi
+.SH DESCRIPTION
+.B Ungetc
+pushes the character
+.I c
+back on an input stream.  That character will be returned by the next
+.B getc
+call on that stream.
+.B Ungetc 
+returns 
+.IR c .
+.PP
+One character of pushback is guaranteed provided
+something has been read from the stream and the stream is actually buffered.
+Attempts to push EOF are rejected.
+.PP
+.BR  Fseek (3)
+erases all memory of pushed back characters.
+.SH "SEE ALSO"
+.BR getc (3),
+.BR setbuf (3),
+.BR fseek (3).
+.SH DIAGNOSTICS
+.B Ungetc
+returns
+.SM
+.B EOF
+if it can't push a character back.
Index: /trunk/minix/man/man4/console.4
===================================================================
--- /trunk/minix/man/man4/console.4	(revision 9)
+++ /trunk/minix/man/man4/console.4	(revision 9)
@@ -0,0 +1,268 @@
+.TH CONSOLE 4
+.SH NAME
+console, keyboard, log \- system console
+.SH DESCRIPTION
+The TTY device driver manages two devices related to the main user
+interface, the system screen and the keyboard.  These two together are
+named "the Console".
+.SS "The Screen"
+The screen of a PC can be managed by a Monochrome Display Adapter, a
+Hercules card, a Color Graphics Adapter, an Enhanced Graphics Adapter,
+or a Video Graphics Array.  To the console driver these devices are
+seen as a block of video memory into which characters can be written to
+be displayed, an I/O register that sets the video memory origin to the
+character that is to be displayed on the top-left position of the
+screen, and an I/O register that sets the position of the hardware
+cursor.  Each character within video memory is a two-byte word.  The low
+byte is the character code, and the high byte is the "attribute byte",
+a set of bits that controls the way the character is displayed,
+character and background colours for a colour card, or
+intensity/underline/reverse video for monochrome.
+.PP
+These are the characteristics of the adapters in text mode:
+.PP
+.RS
+.nf
+.ta +15n +15n
+Adapter	Usable memory	Mono/Colour
+.ta +1n +15n +15n
+	MDA	4K	M
+	Hercules	4K	M
+	CGA	16K	C
+	EGA	32K	M or C
+	VGA	32K	M or C
+.fi
+.RE
+.PP
+MDA and Hercules are the same to the console driver, because the graphics
+mode of the Hercules is of no use to MINIX 3.  EGA and VGA are also mostly
+seen as the same in text mode.  An EGA adapter is either a monochrome or a
+colour device depending on the screen attached to it.  A VGA adapter can run
+in either monochrome or colour (grayscale) mode depending on how the Boot
+Monitor has initialized it.
+.PP
+The driver uses the video origin to avoid copying the screen contents when
+scrolling up or down.  Instead the origin is simply moved one line.  This is
+named "hardware scrolling", as opposed to copying memory: "software
+scrolling".
+.PP
+The video origin is also used to implement several virtual consoles inside
+the video memory of the adapter.  Each virtual console gets a segment of
+video memory.  The driver chooses which console to display by moving the
+video origin.  Note that an MDA or Hercules adapter can only support one
+console.  CGA can support up to four 80x25 consoles, and EGA and VGA can
+have eight.  It is best to configure one less console to leave some video
+memory free so that hardware scrolling has some space to work in.
+.PP
+Character codes are used as indices into a display font that is stored in the
+adapter.  The default font is the IBM character set, which is an ASCII
+character set in the low 128 codes, and a number of mathematical, greek,
+silly graphics, and accented characters in the upper 128 codes.  This font
+is fixed in the MDA, Hercules and CGA adapters, but can be replaced by a
+user selected font for the EGA and VGA adapters.
+.PP
+A number of control characters and escape sequences are implemented by the
+driver.  The result is upward compatible with the ANSI standard terminal.
+The
+.BR termcap (5)
+type is
+.BR minix .
+Normal characters written to the console are displayed at the cursor
+position and the cursor is advanced one column to the right.  If an entire
+line is filled then the cursor wraps to the first column of the next line
+when the next character must be displayed.  The screen is scrolled up if
+needed to start a new line.  Some characters have special effects when sent
+to the console.  Some even have arguments in the form of comma separated
+decimal numbers.  These numbers default to the lowest possible value when
+omitted.  The top-left character is at position (1, 1).  The following
+control characters and escape sequences are implemented by the console:
+.PP
+.ta +10n +20n
+Sequence	Name	Function
+.in +31n
+.ti -30n
+^@	Null	Ignored (padding character)
+.ti -30n
+^G	Bell	Produce a short tone from the speaker
+.ti -30n
+^H	Backspace	Move the cursor back one column, wrapping from the
+left edge up one line to the right edge
+.ti -30n
+^I	Horizontal Tab	Move to the next tab stop, with each tab stop at
+columns 1, 9, 25, etc.  Wrap to the next line if necessary.
+.ti -30n
+^J	Line Feed	Move one line down, scrolling the screen up if
+necessary
+.ti -30n
+^K	Vertical Tab	Same as LF
+.ti -30n
+^L	Form Feed	Same as LF
+.ti -30n
+^M	Carriage Return	Move to column 1
+.ti -30n
+^[	Escape	Start of an escape sequence
+.ti -30n
+^[M	Reverse Index	Move one line up, scrolling the screen down if
+necessary
+.ti -30n
+^[[\fIn\fPA	Cursor Up	Move the cursor up \fIn\fP lines
+.ti -30n
+^[[\fIn\fPB	Cursor Down	Move the cursor down \fIn\fP lines
+.ti -30n
+^[[\fIn\fPC	Cursor Forward	Move the cursor right \fIn\fP columns
+.ti -30n
+^[[\fIn\fPD	Cursor Backward	Move the cursor left \fIn\fP columns
+.ti -30n
+^[[\fIm\fP;\fIn\fPH	Cursor Position	Move the cursor to line \fIm\fP,
+column \fIn\fP
+.ti -30n
+^[[\fIs\fPJ	Erase in Display	Clear characters as follows:
+.br
+\fIs\fP = 0: From cursor to end of screen
+.br
+\fIs\fP = 1: From start of screen to cursor
+.br
+\fIs\fP = 2: Entire screen
+.ti -30n
+^[[\fIs\fPK	Erase in Line	Clear characters as follows:
+.br
+\fIs\fP = 0: From cursor to end of line
+.br
+\fIs\fP = 1: From start of line to cursor
+.br
+\fIs\fP = 2: Entire line
+.ti -30n
+^[[\fIn\fPL	Insert Lines	Insert \fIn\fP blank lines
+.ti -30n
+^[[\fIn\fPM	Delete Lines	Delete \fIn\fP lines
+.ti -30n
+^[[\fIn\fP@	Insert Characters	Insert \fIn\fP blank characters
+.ti -30n
+^[[\fIn\fPP	Delete Characters	Delete \fIn\fP characters
+.ti -30n
+^[[\fIn\fPm	Character Attribute	Set character attribute as follows:
+.br
+\fIn\fP = 0: Normal (default) attribute
+.br
+\fIn\fP = 1: Bold (high intensity fg colour)
+.br
+\fIn\fP = 4: Underline (mono) / Cyan (colour)
+.br
+\fIn\fP = 5: Blinking
+.br
+\fIn\fP = 7: Reverse Video
+.br
+\fIn\fP = 30: Black foreground colour
+.br
+\fIn\fP = 31: Red
+.br
+\fIn\fP = 32: Green
+.br
+\fIn\fP = 33: Brown
+.br
+\fIn\fP = 34: Blue
+.br
+\fIn\fP = 35: Magenta
+.br
+\fIn\fP = 36: Cyan
+.br
+\fIn\fP = 37: Light Gray
+.br
+\fIn\fP = 39: Default fg colour (lt gray)
+.br
+\fIn\fP = 40\-47: Same for background colour
+.br
+\fIn\fP = 49: Default bg colour (black)
+.br
+Note: The "bold" versions of black, brown and lt gray become dark gray,
+yellow and white.
+.in -31n
+.PP
+The console device implements the following ioctl to copy a font into
+font memory on EGA and VGA adapters:
+.PP
+.RS
+.BI "ioctl(" fd ", TIOCSFON, u8_t " font "[256][32]);"
+.RE
+.PP
+Font memory consists of 256 character definitions of 32 lines per character
+and 8 pixels per line.  The first line is the topmost line of the character.
+The leftmost pixel is lit if the most significant bit of a line is set, etc.
+How many lines are used depends on the current video mode.  The 80x25 video
+mode used by MINIX 3 has an 8x16 character cell, 80x28 has 8x14 characters,
+and 132x43 or 132x50 has 8x8 characters.  The boot variable
+.B console
+is used by both the Boot Monitor and the console driver to set the video
+mode, software scrolling on/off, and VGA screen blank timeout.  See
+.BR boot (8).
+.SS "The Keyboard"
+The keyboard produces key codes for each key that is pressed.  These keys
+are transformed into character codes or sequences according to the current
+keyboard translation table.  The format of this table is described in
+.BR keymap (5).
+The character codes can be read from the console device unless they map to
+special hotkeys.  The hotkeys are as follows:
+.PP
+.ta +17n
+Name	Key	Function
+.in +18n
+.ti -17n
+CTRL\-ALT\-DEL	Send an abort signal to process 1 (init).  Init then
+halts the system
+.ti -17n
+CTRL\-ALT\-KP-.	Likewise for keypad period
+.ti -17n
+F1	Process table dump
+.ti -17n
+F2	Show memory map
+.ti -17n
+F3	Toggle software/hardware scrolling
+.ti -17n
+F5	Show network statistics
+.ti -17n
+CTRL\-F7	Send a quit signal to all processes connected to the console
+.ti -17n
+CTRL\-F8	Send an interrupt signal
+.ti -17n
+CTRL\-F9	Send a kill signal.  If CTRL\-F8 or CTRL\-F7 don't get 'em,
+then this surely will.  These keys are for disaster recovery.  You would
+normally use DEL and CTRL\-\e to send interrupt and quit signals.
+.\" .ig VC
+.ti -17n
+ALT\-F1	Select virtual console 0 (/dev/console)
+.ti -17n
+ALT\-F2	Select virtual console 1 (/dev/ttyc1)
+.ti -17n
+ALT\-F(\fIn\fP+1)	Select virtual console \fIn\fP
+(/dev/ttyc\fIn\fP)
+.ti -17n
+ALT\-Left	Select previous virtual console
+.ti -17n
+ALT\-Right	Select next virtual console
+.\" ..
+.in -18n
+.PP
+.\"XXX
+The keyboard map is set with the
+.B KIOCSMAP
+ioctl whose precise details are currently hidden in the
+.B loadkeys
+utility.
+.SS "Log device"
+The
+.B log
+device can be used by processes to print debug messages onto the console.
+The console is a terminal type device, so it is taken from processes when a
+session leader exits.  This does not happen with the log device.
+.SH "SEE ALSO"
+.BR tty (4),
+.BR loadkeys (1),
+.BR keymap (5),
+.BR boot (8).
+.SH NOTES
+Output processing turns Line Feeds into CR LF sequences.  Don't let this
+surprise you.  Either turn off output processing or use one of the synonyms
+for LF.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+.\" minor editing of man page by asw 07.08.96
Index: /trunk/minix/man/man4/controller.4
===================================================================
--- /trunk/minix/man/man4/controller.4	(revision 9)
+++ /trunk/minix/man/man4/controller.4	(revision 9)
@@ -0,0 +1,387 @@
+.TH CONTROLLER 4
+.SH NAME
+controller, disk, tape, at, bios, esdi, aha1540, ncr810, dosfile, fatfile \- controllers, disks and tapes
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+The
+.BI c n *
+family of devices refer to drivers that control disks, disk like devices,
+and tapes.  MINIX 3 contains a number of drivers for several different
+controllers.  These controllers can have disks, cdroms and tapes attached to
+them.  Boot Monitor variables specify which drivers are activated using
+the variables
+.BR c0 ,
+.BR c1 ,
+etc.  The names of the devices in
+.BR /dev
+that correspond with the driver for controller 0 are all named beginning
+with
+.BR c0 .
+.PP
+For each controller, the minor device numbers are organized as follows:
+.PP
+.RS
+.nf
+.ta +\w'122-127nnmm'u +\w'd0p0s0nnmm'u +\w'disk 0, part 0, subpart 0nnmm'u
+.ft B
+minor	device	what?	obsolete
+.ft P
+0	d0	disk 0	hd0
+1	d0p0	disk 0, partition 0	hd1
+2	d0p1	disk 0, partition 1	hd2
+3	d0p2	disk 0, partition 2	hd3
+4	d0p3	disk 0, partition 3	hd4
+5	d1	disk 1	hd5
+6	d1p0	disk 1, partition 0	hd6
+7	d1p1	disk 1, partition 1	hd7
+8	d1p2	disk 1, partition 2	hd8
+9	d1p3	disk 1, partition 3	hd9
+\&...	...
+39	d7p3	disk 7, partition 3	hd39
+.SP
+64	t0n	tape 0, non-rewinding
+65	t0	tape 0, rewind on close
+66	t1n	tape 1, non-rewinding
+67	t1	tape 1, rewind on close
+\&...	...
+78	t7n	tape 7, non-rewinding
+79	t7	tape 7, rewind on close
+.SP
+120	r0	raw access device 0
+121	r1	raw access device 1
+\&...	...
+127	r7	raw access device 7
+.SP
+128	d0p0s0	disk 0, part 0, subpart 0	hd1a
+129	d0p0s1	disk 0, part 0, subpart 1	hd1b
+130	d0p0s2	disk 0, part 0, subpart 2	hd1c
+131	d0p0s3	disk 0, part 0, subpart 3	hd1d
+132	d0p1s0	disk 0, part 1, subpart 0	hd2a
+\&...	...
+144	d1p0s0	disk 1, part 0, subpart 0	hd6a
+\&...	...
+255	d7p3s3	disk 7, part 3, subpart 3	hd39d
+.fi
+.RE
+.PP
+The device names in
+.B /dev
+also name the controller, of course, so the usual place for the MINIX 3
+root device, the first subpartition of the second partition of disk 0 on
+controller 0 is
+.BR /dev/c0d0p1s0 .
+Note that everything is numbered from 0!  The first controller is controller
+0, the first disk is disk 0, etc.  So the second partition is
+.BR p1 .
+.PP
+The fourth column in the table above shows the disk devices names that were
+used by previous versions of MINIX 3 for what is now controller 0.  These
+devices are no longer present in
+.BR /dev .
+.SS Disks
+Most disks are arrays of 512 byte sectors.  The disk devices are normally
+block devices, which means they are block buffered by the MINIX 3 file system
+cache using 1024 byte blocks.  The FS cache allows I/O at any byte offset,
+and takes care of cutting and pasting incomplete blocks together.  If one
+creates a character device for a disk device, then I/O must be in multiples
+of the disk block size.
+.PP
+For each disk there is a device that covers the entire disk, these are named
+.BR c0d0 ,
+.BR c0d1 ,
+etc, up to
+.B c0d7
+for controller 0.  If a partition table is placed in the first sector of the
+disk, then the disk is subdivided into regions named partitions.  Up to four
+partitions may be defined, named
+.BR c0d0p0
+to
+.BR c0d0p3
+for disk 0 on controller 0.  To make things interesting you can also place a
+partition table in the first sector of a MINIX 3 partition, which divides the
+partition into up to four subpartitions.  Normally MINIX 3 is installed into a
+single partition, with the root, swap and /usr file systems in subpartitions.
+.PP
+If a partition is an extended partition then it contains a linked list of
+partition tables each of which may specify a logical partition.  Up to four
+of these logical partitions are presented by the driver as subpartitions of
+the extended partition.
+.PP
+A sector containing a partition table starts with 446 bytes of boot code,
+followed by four partition table entries of 16 bytes each, and ends with
+the magic number 0xAA55 (little endian, so first 0x55 then 0xAA.)  Partition
+table information is defined in <ibm/partition.h>:
+.PP
+.nf
+.ta +2n +29n +37n
+/* Description of entry in the partition table.  */
+
+struct part_entry {
+	unsigned char bootind;	/* boot indicator 0/ACTIVE_FLAG	*/
+	unsigned char start_head;	/* head value for first sector	*/
+	unsigned char start_sec;	/* sector value + high 2 cyl bits	*/
+	unsigned char start_cyl;	/* low 8 cylinder bits	*/
+	unsigned char sysind;	/* system indicator	*/
+	unsigned char last_head;	/* h/s/c for the last sector	*/
+	unsigned char last_sec;
+	unsigned char last_cyl;
+	unsigned long lowsec;	/* logical first sector	*/
+	unsigned long size;	/* size of partition in sectors	*/
+};
+
+.ta +24n +7n +37n
+#define ACTIVE_FLAG	0x80	/* value for active in bootind field	*/
+#define NR_PARTITIONS	4	/* number of entries in table	*/
+#define PART_TABLE_OFF	0x1BE	/* offset of table in boot sector	*/
+
+/* Partition types (sysind). */
+#define NO_PART	0x00	/* unused entry */
+#define MINIX_PART	0x81	/* MINIX 3 partition type */
+.fi
+.PP
+The cylinder numbers are encoded in a very strange way, bits 8 and 9 are
+in the high two bits of the sector number.  The sector numbers count from 1,
+not 0!  More useful are the lowsec and size fields however, they simply give
+the location of the partition as an absolute sector offset and length within
+the drive.
+.PP
+The partition table entry defined above is specific to IBM type disks.  The
+device drivers use another partition entry structure to pass information on
+a partition.  This is what <minix/partition.h> looks like:
+.sp
+.nf
+.ta +2n +25n
+struct partition {
+	u64_t base;	/* byte offset to the partition start */
+	u64_t size;	/* number of bytes in the partition */
+	unsigned cylinders;	/* disk geometry for partitioning */
+	unsigned heads;
+	unsigned sectors;
+};
+.fi
+.PP
+The base and size fields are the byte offset and length of a partition.
+The geometry of the disk is also given for the benefit of
+partition table editors.  This information can be obtained from an open disk
+device with the call:
+.sp
+.RS
+.ft B
+ioctl(\fIfd\fP, DIOCGETP, &\fIentry\fP);
+.ft R
+.RE
+.sp
+One can change the placement of the device to the lowsec and size fields of
+.I entry
+by using the
+.B DIOCSETP
+call instead.  Only the base and size fields are used for
+.BR DIOCSETP .
+.PP
+The partition tables when read from disk by the driver are checked and
+truncated to fit within the primary partition or drive.  The first sector
+is normally left free for the partition table.
+.PP
+The partition tables are read when the in-use count (opens and mounts)
+changes from 0 to 1.  So an idle disk is automatically repartitioned on the
+next access.  This means that DIOCSETP only has effect if the disk is in
+use.
+.SS "Disk-like devices"
+Devices like a CD-ROM are treated as read-only disks, and can be accessed
+using disk devices.  A CD-ROM usually has a block size of 2048 bytes, but
+the driver knows this, and allows one to read at any byte offset by reading
+what isn't needed into a scratch buffer.
+.SS Tapes
+There are two kinds of tape devices:  Non-rewinding, and rewind-on-close.
+The non-rewinding devices treat the tape as a series of files.  The
+rewind-on-close devices look at the tape as a single file, and when you close
+such a device the tape is told to rewind.
+See
+.BR mt (1),
+and
+.BR mtio (4)
+for a description of the commands that may be sent to the tape, either from
+the command prompt or from a program.
+.PP
+There are two kinds of tape drives:  Fixed and variable block size tape
+drives.  Examples of the first kind are cartridge
+tapes, with a fixed 512 bytes block size.  An Exabyte tape drive has a
+variable block size, with a minimum of 1 byte and a maximum of 245760 bytes
+(see the documentation of such devices.)
+The maximum is truncated to 32767 bytes for Minix-86 and 61440 bytes for
+Minix-vmd, because the driver can't move more bytes in a single request.
+.PP
+A read or write to a fixed block size tape must be a precise multiple of the
+block size, any other count gives results in an I/O error.  A read from a
+variable block sized tape must be large enough to accept the block that is
+read, otherwise an I/O error will be returned.  A write can be any size
+above the minimum, creating a block of that size.  If the write count is
+larger than the maximum block size then more blocks are written until the
+count becomes zero.  The last block must be larger than the minimum of
+course.  (This minimum is often as small as 1 byte, as for the Exabyte.)
+.PP
+The
+.B mt blksize
+command may be used to select a fixed block size for a variable block sized
+tape.  This will speed up I/O considerably for small block sizes.  (Some
+systems can only use fixed mode and will write an Exabyte tape with 1024
+byte blocks, which read very slow in variable mode.)
+.PP
+A tape is a sequence of blocks and filemarks.  A tape may be opened and
+blocks may be read from it upto a filemark, after that all further reads
+return 0.  After the tape is closed and reopened one can read the blocks
+following the filemark if using a non-rewinding device.  This makes the tape
+look like a sequence of files.
+.PP
+If a tape has been written to or opened in write-only mode, then a filemark
+is written if the tape is closed or if a space command is issued.  No extra
+filemark is written if the drive is instructed to write filemarks.
+.SS "Raw Access Devices"
+Under Minix-vmd one can use the raw access devices to program a SCSI
+device entirely from user mode.  The disk and tape devices probe for devices
+when opened, start disks and load tapes, but the raw access devices do
+nothing at all.  Given an open file descriptor to any SCSI character device
+(not just the raw access devices) one can use the following ioctl:
+.PP
+.RS
+ioctl(fd, SCIOCCMD, &scsicmd)
+.RE
+.PP
+The structure whose address is passed as the third argument is defined
+in <sys/scsi.h> as follows:
+.PP
+.RS
+.nf
+struct scsicmd {
+	void	*cmd;
+	size_t	cmdlen;
+	void	*buf;
+	size_t	buflen;
+	void	*sense;
+	size_t	senselen;
+	int	dir;
+};
+.fi
+.RE
+.PP
+.B Cmd
+and
+.B cmdlen
+hold the address and length of an object holding a Group 0 or Group 1
+SCSI command.  The next two fields describe a buffer of at most 8 kilobytes
+used in the data in or out phase.
+.B Dir
+is 0 if data is to be read from the device, 1 if data is written to the
+device.  If the ioctl succeeds then 0 is returned, otherwise -1 with
+.B errno
+set to
+.B EIO
+and the request sense info returned in the buffer described by the sense and
+senselen fields.  If the sense key is zero on error then a host adapter
+error occurred, this means that the device is most likely turned off or not
+present.
+.SH DRIVERS
+By setting the Boot variables
+.BR c0
+to
+.BR c3
+under MINIX 3, or
+.BR c0
+to
+.BR c4
+under Minix-vmd one attaches a set of disk and tape devices to a driver.
+See
+.BR boot (8)
+for a list of boot variables that configure each of these drivers.
+The following drivers are available:
+.SS at
+The standard IBM/AT disk driver that also supports IDE disks.  This is the
+default driver for controller 0 on AT class machines.  (Most PCs are in that
+class.)
+.SS bios
+A disk driver that uses BIOS calls to do disk I/O.  This is the default
+driver on anything but an AT.  (Old XTs and PS/2s.)  On an XT this is the
+best driver you can use, but on any other machine this driver may be
+somewhat slow, because the system has to switch out of protected mode to
+make a BIOS call.  On a fast enough machine with a high enough setting of
+DMA_SECTORS (see
+.BR config (8))
+it works well enough.
+.SS esdi
+A hard disk driver for use on some PS/2 models.
+.SS "xt \fR(MINIX 3 only)"
+A hard disk driver for IBM/XT type hard disks.  Useful for old 286 based
+machines that have such a disk.  On XTs you are better off with the
+.B bios
+driver.
+.SS aha1540
+A SCSI driver for the Adaptec 1540 host adapter family, which includes the
+1540, 1540A, 1540B, 1540C, 1540CF, 1640, and 1740.  Also supported is the
+compatible BusLogic 545.
+.SS ncr810
+This will eventually become a Symbios 810 SCSI driver.  (Formerly owned by
+NCR.)  KJB has read the docs on this card three times, but has still done
+nothing, the lazy bum.
+.SS dosfile
+The "DOS file as disk" driver that is used when MINIX 3 is running
+under DOS.  It treats a large DOS file as a MINIX 3 disk.  Only primary
+partitions are supported, there are no subpartitions.  This is the default
+driver when MINIX 3 is started under DOS.
+.SS fatfile
+Uses a large file on a FAT file system as a disk.  It needs one of the other
+disk drivers to do the actual I/O.  This driver only knows how to interpret
+a FAT file system to find the file to use.  With a fast native disk driver
+this driver is much faster than the
+.B dosfile
+driver.
+.SH FILES
+.TP 25
+/dev/c*d*
+Disks devices.
+.TP
+/dev/c*d*p*
+Partitions.
+.TP
+/dev/c*d*p*s*
+Subpartitions.
+.TP
+/dev/c*t*n, /dev/c*t*
+Tapes.
+.TP
+/dev/c*r*
+Raw access devices.
+.SH "SEE ALSO"
+.BR dd (1),
+.BR mt (1),
+.BR eject (1),
+.BR ioctl (2),
+.BR int64 (3),
+.BR mtio (4),
+.BR boot (8),
+.BR config (8),
+.BR monitor (8),
+.BR part (8),
+.BR repartition (8).
+.SH BUGS
+The subpartitioning is incompatible with the MS-DOS method of extended
+partitions.  The latter does not map well to the sparse minor device number
+space.
+.PP
+The primary partition table is sorted by lowsec like MS-DOS does, subpartition
+tables are not.  Just think about what happens when you delete a partition in
+the MS-DOS scheme.
+.PP
+Don't move a partition that is mounted or kept open by some process.  The
+file system may write cached blocks to the new location.
+.PP
+The BIOS driver is not slow at all on a buffered disk.
+.PP
+Some IDE disks send an interrupt when they spin down under hardware power
+management.  The driver acknowledges the interrupt as it is supposed to do by
+reading the status register.  The disk then spins up again...  You have to
+disable the spin down in the computer setup to fix the problem.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man4/dev.4
===================================================================
--- /trunk/minix/man/man4/dev.4	(revision 9)
+++ /trunk/minix/man/man4/dev.4	(revision 9)
@@ -0,0 +1,261 @@
+.TH DEV 4
+.SH NAME
+dev \- device files in /dev
+.SH DESCRIPTION
+Device files are the eyes and ears of the system.  Through the device files
+one has access to the disks, terminals and other parts of the machine.
+Single bytes or disk blocks may be transferred to or from a device with
+ordinary
+.BR read (2)
+or
+.BR write (2)
+calls, byte positions set with
+.BR lseek (2),
+or more complicated control functions performed with
+.BR ioctl(2).
+.PP
+Device files as found in
+.B /dev
+have several attributes that must be considered.  Here are two examples as
+.B "ls \-l"
+shows them:
+.PP
+.RS
+.nf
+.if t .ft C
+brw-rw-rw-  1 root     operator   2,   1 Jun 10  1995 fd1
+crw--w----  1 kjb      tty        4,   0 May 11 09:41 console
+.if t .ft P
+.fi
+.RE
+.PP
+Most attributes are the same as for a regular file and have the same
+function.  The file type and the major and minor device numbers are special
+to devices.
+.PP
+Character devices are marked with a
+.B c
+as a file type letter.  Any I/O on a character device is sent down to the
+device driver without any interpretation.  This means that a process doing
+the I/O must know the characteristics of the device and deal with them
+appropriately.
+.PP
+Block devices provoke the file system server into buffering the data on
+those devices.  Data read or written by processes is passed through the file
+system block cache.  Unaligned bytes read or written are extracted or
+reassembled by the file server from or to whole blocks in the cache.  The
+file server transfers data to or from the device driver as blocks to
+positions at block size boundaries.  These blocks are MINIX 3 blocks of 1024
+bytes, disk devices usually have a 512 byte block size.  Only block devices
+can be mounted as part of the file system tree if they contain a MINIX 3 file
+system.
+.PP
+The major device number (2 for
+.B fd1
+and 4 for
+.BR console )
+are used by FS to find the device driver that manages a device.  The minor
+device number (1 for
+.B fd1
+and 0 for
+.BR console )
+is passed to the driver to select a device among a number of related devices
+that are all managed by that driver.  The device drivers are usually kernel
+tasks under MINIX 3, small processes that are contained within the address
+space of the kernel.  The following tasks and associated devices exist:
+.SS "Memory (major 1)"
+The
+.BR ram ,
+.BR mem ,
+.BR kmem ,
+and
+.BR null
+devices are managed by the memory task.
+The
+.B ram
+device is a block device for a chunk of memory that is the RAM disk.  Any
+byte read from or written to the
+.B ram
+device is copied from or to that memory chunk.
+The
+.B mem
+device is a character device for the entire address space of the system, but
+.B kmem
+only for the kernel data area.  These two devices allow programs like
+.BR ps (1)
+to hunt around the system looking for interesting bits.
+The
+.B null
+device is a data sink.  It happily swallows any bytes written to it, and
+returns nothing on a read.
+.SS "Floppy disk (major 2)"
+The
+.BR fd0 ,
+.BR fd0p0 ,
+.BR fd0p1 ,
+.BR fd0p2 ,
+and
+.BR fd0p3
+block devices are the first floppy disk and the four partitions that may
+exist on a that floppy disk.  Likewise are
+.BR fd1
+and
+.BR fd1p[0\-3]
+the device and partitions for the second floppy disk.  The floppy disk
+devices are described in detail in
+.BR fd (4).
+Partitioning in general is explained in
+.BR controller (4).
+.SS "Controller 0 (major 3)"
+The first hard disk on controller 0 can be accessed by block device
+.BR c0d0 .
+This device addresses the entire hard disk from the first to the last
+sector.  A hard disk is normally partitioned in up to four primary
+partitions,
+.BR c0d0p0 ,
+.BR c0d0p1 ,
+.BR c0d0p2 ,
+and
+.BR c0d0p3 .
+Each of these devices accesses a range of sectors on the
+.B c0d0
+device.  It is customary to give each operating system on a disk a primary
+partition.  So the Windows C: "drive" can be on
+.BR c0d0p0 ,
+and MINIX 3 can be on
+.BR c0d0p1 .
+MINIX 3 wants to have several partitions on its own, so
+.B c0d0p1
+can be further subdivided into the subpartitions
+.BR c0d0p1s0 ,
+.BR c0d0p1s1 ,
+.BR c0d0p1s2 ,
+and
+.BR c0d0p1s3 .
+.B /dev
+contains devices for the first and second hard disk
+.RB ( c0d0
+and
+.BR c0d1 ),
+their primary partitions
+.RB ( c0d[01]p[0\-3] )
+and subpartitions thereof
+.RB ( c0d[01]p[0\-3]s[0\-3] ).
+More detail can be found in
+.BR controller (4).
+.SS "Terminals (minor 4)"
+The TTY driver manages the system console device, aptly named
+.BR console ,
+the serial lines,
+.BR tty00
+and
+.BR tty01 ,
+and the pseudo ttys.
+Through the console device one can display characters on a screen attached
+to a monochrome, Hercules, color, or VGA adapter.  The
+.BR ttyc1 ,
+.BR ttyc2 ,
+etc. devices are the so-called "virtual consoles" that share the one
+console display.  One can select which virtual console is to be visible on
+the screen and take input from the keyboard.
+To allow remote login the devices with minor numbers of 128 or higher offer
+virtual terminals.  These pseudo ttys come in tty, pty pairs that form a
+pipe between processes running under the tty, and a controlling process
+attached to the pty side.
+See also
+.BR console (4),
+and
+.BR tty (4).
+.SS "Anonymous TTY (major 5)"
+This is just one device named
+.BR tty
+that is a synonym for the controlling tty of a process.  This device is not
+managed by any device driver, but is handled by FS itself.  A process can
+get access to the terminal it is running under by using
+.BR /dev/tty .
+.SS "Line printer (major 6)"
+The
+.B lp
+device sends any bytes written to it to the printer.
+.SS "TCP/IP (major 7)"
+The TCP/IP task is not a kernel task, but a server like MM and FS.  It sits
+between FS and the DP8390 task that manages the ethernet boards.  Together
+they implement the TCP/IP protocol.  See also
+.BR ip (4).
+.SS "Controller 1 (major 8)"
+Like controller 0 (major 3), but managing a second controller with devices
+.BR /dev/c1* .
+.SS "Controller 2 (major 10)"
+Like controller 0.
+.SS "Controller 3 (major 12)"
+Like controller 0.
+.SS "Audio (major 13)"
+The
+.B audio
+device can be used to produce or record air vibrations using a Soundblaster
+16 type audio card.  See
+.BR audio (4).
+.SS "Mixer (major 14)"
+The
+.B mixer
+device is used to control the audio driver.
+.SH FILES
+.TP 10
+.B /dev/*
+All MINIX 3 devices
+.SH "SEE ALSO"
+.BR read (2),
+.BR write (2),
+.BR lseek (2),
+.BR ioctl (2),
+.BR console (4),
+.BR fd (4),
+.BR controller (4),
+.BR ip (4),
+.BR tty (4),
+.BR MAKEDEV (8).
+.SH DIAGNOSTICS
+There are five prominent errors that processes accessing device files may
+provoke:
+.IP "ENODEV \- No such device" 5
+There is no driver managing the device class this device belongs to.  Either
+the driver is configured out, or it is not loaded (inet).
+.IP "ENXIO \- No such device or address"
+This device is not available.  Either the driver does not support it at all,
+or the hardware isn't available, i.e. accessing the second disk on a system
+with only one disk.
+.IP "EACCES \- Permission denied"
+This error may cause a lot of head scratching if
+.B ls \-l
+shows a device file to be writable.  The media you are trying to access is
+simply physically write protected!
+.IP "EINVAL \- Invalid argument"
+Devices may not like reads or writes that are not block multiples, or very
+big transfers, etc.  The device manual page should list the limits.
+.IP "EIO \- I/O error"
+This may be a real I/O error, i.e. a read or write on the device failing due
+to a media error.  But it may also be the result of an operation that a
+device can't do, or an empty tape drive, etc.
+.SH NOTES
+Some devices are not present by default.  The
+.BR MAKEDEV
+script knows how to make them.
+.SS "MS-DOS/Windows equivalents"
+The names of MS-DOS/Windows devices probably map to MINIX 3 devices as follows:
+.PP
+.RS
+.nf
+.ta +\w'COM1mmm'u +\w'c0d1, c0d2, c0d3mmm'u
+A:	fd0
+B:	fd1
+C:	c0d0p0	(usually the first partition)
+D:	c0d1p0, c0d2p0	(if it's another disk)
+D:	c0d0p1s0	(if it's an extended partition)
+D:	c0d1, c0d2, c0d3	(if it's a CD-ROM)
+CON	console
+COM1	tty00	(UNIX counts from 0)
+LPT1	lp
+.fi
+.RE
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man4/fd.4
===================================================================
--- /trunk/minix/man/man4/fd.4	(revision 9)
+++ /trunk/minix/man/man4/fd.4	(revision 9)
@@ -0,0 +1,88 @@
+.TH FD 4
+.SH NAME
+fd \- floppy disk
+.SH DESCRIPTION
+The
+.B fd*
+devices refer to the Floppy disk driver using the NEC PD765 floppy disk
+controller.  These diskettes are arrays of 512 byte sectors, although MINIX 3
+always works with two sectors at a time due to its 1024 byte block size.  You
+can read or write any number of bytes however, MINIX 3 takes care of cutting
+and pasting incomplete blocks together.
+.PP
+The driver is normally configured for two floppy disk devices
+.B fd0
+and
+.BR fd1 .
+It can handle two more, but it is unlikely that the average PC can.
+.PP
+On the first access to an
+.B fd
+device (by
+.BR open (2)
+or
+.BR mount (2)),
+the driver will execute a series of read tests to determine the floppy type.
+This works ok for all floppy types except the true 360k type, because it
+is indistinguishable from the 720k type.  This only means that the size of
+the floppy is not estimated right.
+.PP
+Bits 2\-6 of the minor device number may be set to the floppy disk type
+to make it known to the driver what type of diskette it is reading or
+writing.  The non-auto devices should be used for formatting, or when one wants to
+be absolutely sure that the device is accessed right.  These devices exist for
+drive 0:
+.sp
+.nf
+.ta +4n +7n +9n +8n
+	type	device	minor	media
+.ta +5n +7n +9n +7n
+	0	fd0	0	autodetect
+	1	pc0	4	360k, 5.25"
+	2	at0	8	1.2M, 5.25"
+	3	qd0	12	360k in a 720k, 5.25" drive
+	4	ps0	16	720k, 3.5"
+	5	pat0	20	360k in a 1.2M, 5.25" drive
+	6	qh0	24	720k in a 1.2M, 5.25" drive
+	7	PS0	28	1.44M, 3.5"
+.fi
+.DT
+.PP
+Type 4 may also be used for the rarely seen 720k, 5.25" floppies (type 2 made
+them obsolete fast.)  Note that these "types" only describe the floppies from
+a software point of view, type 1 and 4 drives use the same parameters.
+.PP
+If the format bit (bit 7) is set, then the driver interprets write commands
+as track formatting requests.  This is used by the
+.BR format (1)
+command.
+.PP
+If the type bits are set to 28, 29, 30, or 31, then the driver uses a
+partition table found in sector 0 to partition the floppy.  The partitions
+of
+.B fd0
+may be accessed as
+.B fd0p0
+through
+.BR fd0p3 .
+See
+.BR controller (4)
+for a description of the partition table, and associated ioctl commands.
+.SH FILES
+/dev/fd[0\-3], /dev/pc[0\-3], /dev/at[0\-3], /dev/qd[0\-3], /dev/ps[0\-3],
+/dev/pat[0\-3], /dev/qh[0\-3], /dev/PS[0\-3], /dev/fd[0\-3]p[0\-3]
+.SH "SEE ALSO"
+.BR format (1),
+.BR controller (4),
+.BR part (8).
+.SH BUGS
+The driver does not know the size of a 360k diskette in a 360k 5.25"
+drive, because it uses the 720k parameters for it.  So it will happily try
+to read past the end making all kinds of interesting noises.  It's a good
+thing these drives are practically obsolete.
+.PP
+The partition table is only read when the drive motor is off and only for
+an auto or partition device.  The driver assumes that a floppy in a drive
+with a running motor can't have been replaced all of a sudden.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man4/ip.4
===================================================================
--- /trunk/minix/man/man4/ip.4	(revision 9)
+++ /trunk/minix/man/man4/ip.4	(revision 9)
@@ -0,0 +1,1466 @@
+.\"
+.\" Copyright 1994 Vrije Universiteit, The Netherlands.
+.\" For full copyright and restrictions on use see the file COPYRIGHT in the
+.\" top level of the Amoeba distribution.
+.\"
+.ig
+	Software: Philip Homburg, 1991
+	Document: Philip Homburg, Sept 3, 1991
+	Modified: Greg Sharp and Philip Homburg, March 1992
+		  - merged with udp(L) and made a little more complete.
+		  Greg Sharp, April 1992
+		  - updated keywords for auto index generation
+	Modified: Kees J. Bot, June 1994
+		  - changed to man(7) format for MINIX 3.
+..
+.TH IP 4
+.SH NAME
+ip, eth, psip, udp, tcp \- Internet Protocol server devices and definitions
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+The
+.BR ip* ,
+.BR eth* ,
+.BR psip* ,
+.BR tcp* ,
+and
+.B udp*
+devices give access to the Internet Protocol (IP) services in MINIX 3.
+There can be up to 16 different networks, with 4 network devices each
+(a network has either an
+.B eth*
+or a
+.B psip*
+device, not both.)
+The
+.B *
+in the device names is a decimal number, so one may see names from
+.B ip0
+to
+.BR ip15 .
+A program scanning all networks must try all 16, and not stop if one in
+between is missing.  One network is the default network.  Its devices are
+linked to names without numbers.
+.PP
+The
+.B eth*
+and
+.B psip*
+devices give direct access to the network packets at the lowest level.
+The
+.BR ip* ,
+.BR tcp* ,
+and
+.B udp*
+devices give access to IP, TCP, or UDP services.
+.PP
+Most programs that use TCP/IP use code like the following to access the
+proper devices:
+.PP
+.RS
+.nf
+if ((tcp_device= getenv("TCP_DEVICE")) == NULL)
+	tcp_device= "/dev/tcp";
+.fi
+.RE
+.PP
+The low level networking programs such as
+.BR ifconfig (8)
+also have options to select the device they are working with.  The
+convention is:
+.PP
+.RS
+.BI ETH_DEVICE= device
+.br
+.BI -E " device"
+.RS
+Device to use as raw ethernet device instead of the default /dev/eth.
+.RE
+.SP
+.BI PSIP_DEVICE= device
+.br
+.BI -P " device"
+.RS
+Pseudo IP device to use instead of
+.BR /dev/psip .
+.RE
+.SP
+.BI IP_DEVICE= device
+.br
+.BI -I " device"
+.RS
+IP device to use instead of
+.BR /dev/ip .
+.RE
+.SP
+.BI TCP_DEVICE= device
+.br
+.BI -T " device"
+.RS
+TCP device to use instead of
+.BR /dev/tcp .
+.RE
+.SP
+.BI UDP_DEVICE= device
+.br
+.BI -U " device"
+.RS
+UDP device to use instead of
+.BR /dev/udp .
+.RE
+.RE
+.SS Programming
+Access to the IP services is provided using filedescriptors to open IP
+devices.  These open IP channels can be configured with
+.BR ioctl (2)
+calls, and data can be transferred by calls to
+.BR read (2),
+and
+.BR write (2).
+.SS "Types (general)"
+.IP <sys/types.h>
+.br
+Defines
+.BR u8_t ,
+.BR u16_t ,
+.B u32_t
+and
+.B i32_t
+(and
+.BR U8_t ,
+.BR U16_t ,
+.B U32_t
+and
+.B I32_t
+for use in prototypes).
+.SS "Types (eth)"
+.IP <net/gen/ether.h>
+.br
+Defines struct ether_addr (\fBether_addr_t\fP) and
+.B ether_type_t
+and
+.B Ether_type_t
+for use in prototypes.
+.IP <net/gen/eth_io.h>
+.br
+Defines struct nwio_ethopt (\fBnwio_ethopt_t\fP) and
+struct nwio_ethstat (\fBnwio_ethstat_t\fP)
+.IP <net/gen/eth_hdr.h>
+.br
+Defines struct eth_hdr (\fBeth_hdr_t\fP)
+.SS "Types (psip)"
+.IP <net/gen/psip_hdr.h>
+.br
+[[[No description available yet.]]]
+.IP <net/gen/psip_io.h>
+.br
+[[[No description available yet.]]]
+.SS "Types (ip)"
+.IP <net/gen/in.h>
+.br
+Defines
+.BR ipaddr_t ,
+.BR ipproto_t
+and struct ip_hdropt (\fBip_hdropt_t\fP).
+.IP <net/gen/ip_io.h>
+.br
+Defines struct nwio_ipconf (\fBnwio_ipconf_t\fP) and
+struct nwio_ipopt (\fBnwio_ipopt_t\fP)
+.IP <net/gen/ip_hdr.h>
+.br
+Defines struct ip_hdr (\fBip_hdr_t\fP)
+.IP <net/gen/route.h>
+.br
+Defines struct nwio_route (\fBnwio_route_t\fP)
+.SS "Types (tcp)"
+.IP <net/gen/tcp.h>
+.br
+Defines
+.B tcpport_t
+and
+.B Tcpport_t
+for use in prototypes.
+.IP <net/gen/tcp_io.h>
+.br
+Defines struct nwio_tcpconf (\fBnwio_tcpconf_t\fP),
+struct nwio_tcpcl (\fBnwio_tcpcl_t\fP),
+struct nwio_tcpatt (\fBnwio_tcpatt_t\fP) and
+struct nwio_tcpopt (\fBnwio_tcpopt_t\fP).
+.IP <net/gen/tcp_hdr.h>
+.br
+Defines struct tcp_hdr (\fBtcp_hdr_t\fP) and struct tcp_hdropt
+(\fBtcp_hdropt_t\fP).
+.SS "Types (udp)"
+.IP <net/gen/udp.h>
+.br
+Defines
+.B udpport_t
+and
+.B Udpport_t
+for use in prototypes.
+.IP <net/gen/udp_io.h>
+.br
+Defines struct nwio_udpopt (\fBnwio_udpopt_t\fP).
+.IP <net/gen/udp_hdr.h>
+.br
+Defines struct udp_hdr (\fBudp_hdr_t\fP) and struct udp_io_hdr
+(\fBudp_io_hdr_t\fP).
+.SS "Byte Order Conversion"
+All 16-bit and 32-bit quantities in IP headers must be in network byte
+order.  The macros described in
+.BR hton (3)
+can be used to convert these values to and from the byte order used by
+the host machine.
+.SS "The Internet Checksum"
+The
+.B oneC_sum
+function (see
+.BR oneC_sum (3))
+is used to calculate the one's complement checksum needed for IP network
+packets.
+.SS "General Functions"
+.PP
+.ft B
+\fIfd\fP = open(\fItcpip_device\fP, O_RDWR)
+.ft R
+.PP
+This is how one normally obtains a filedescriptor for a new TCP/IP channel.
+.I tcpip_device
+names one of the TCP/IP devices.  The channel may be used both to send or to
+receive data.
+.PP
+.ft B
+\fIn\fP = read(\fIfd\fP, \fIbuf\fP, \fIsize\fP)
+.ft R
+.PP
+Receives one packet (low level devices) or a number of bytes (TCP stream).
+Returns the the number of bytes placed into
+.IR buf ,
+or returns -1 with an error code placed into
+.BR errno .
+.PP
+.ft B
+\fIn\fP = write(\fIfd\fP, \fIbuf\fP, \fIsize\fP)
+.ft R
+.PP
+Sends one packet (low level devices) or a number of bytes (TCP stream).
+Returns
+.I size
+or -1 with the error code placed into
+.BR errno .
+The TCP/IP
+.B read
+and
+.B write
+functions behave like reads and writes on pipes when it comes to signals.
+.SS "ETH Functions"
+.PP
+.ft B
+ioctl(\fIfd\fP, NWIOGETHSTAT, &struct nwio_ethstat)
+.ft R
+.PP
+The
+.B NWIOGETHSTAT
+ioctl
+returns the Ethernet address and some statistics of the Ethernet server of
+the channel
+.IR fd .
+The result is returned in the nwio_ethstat structure.
+The \fBstruct nwio_ethstat\fP is defined in <net/gen/eth_io.h>:
+.PP
+.RS
+.nf
+.if t .ft C
+typedef struct nwio_ethstat
+{
+        ether_addr_t nwes_addr;
+        eth_stat_t nwes_stat;
+} nwio_ethstat_t;
+.SP
+typedef struct eth_stat
+{
+    unsigned long ets_recvErr,  /* # receive errors */
+	ets_sendErr,            /* # send error */
+	ets_OVW,                /* # buffer overwrite warnings,
+                                   (packets arrive faster than
+                                    can be processed) */
+	ets_CRCerr,             /* # crc errors of read */
+	ets_frameAll,           /* # frames not aligned (# bits
+                                   not a multiple of 8) */
+	ets_missedP,            /* # packets missed due to too
+                                   slow packet processing */
+	ets_packetR,            /* # packets received */
+	ets_packetT,            /* # packets transmitted */
+	ets_transDef,           /* # transmission deferred (there
+                                   was a transmission of an
+                                   other station in progress */
+	ets_collision,          /* # collisions */
+	ets_transAb,            /* # transmissions aborted due
+                                   to excessive collisions */
+	ets_carrSense,          /* # carrier sense lost */
+	ets_fifoUnder,          /* # fifo underruns (processor
+                                   is too busy) */
+	ets_fifoOver,           /* # fifo overruns (processor is
+                                   too busy) */
+	ets_CDheartbeat,        /* # times unable to transmit
+                                   collision signal */
+	ets_OWC;                /* # times out of window
+                                   collision */
+} eth_stat_t;
+.if t .ft R
+.fi
+.RE
+.PP
+.ft B
+ioctl(\fIfd\fP, NWIOSETHOPT, &struct nwio_ethopt)
+.ft R
+.PP
+Before an Ethernet channel can be used to send or receive
+Ethernet packets, it has to be configured using the
+.B NWIOSETHOPT
+ioctl.
+The structure
+.B nwio_ethopt
+is defined in <net/gen/eth_io.h>:
+.PP
+.RS
+.nf
+.if t .ft C
+typedef struct nwio_ethopt
+{
+	u32_t nweo_flags;
+	ether_addr_t nweo_multi, nweo_rem;
+	ether_type_t nweo_type;
+} nwio_ethopt_t;
+.SP
+#define NWEO_NOFLAGS    0x0000L
+#define NWEO_ACC_MASK   0x0003L
+#       define NWEO_EXCL        0x00000001L
+#       define NWEO_SHARED      0x00000002L
+#       define NWEO_COPY        0x00000003L
+#define NWEO_LOC_MASK   0x0010L
+#       define NWEO_EN_LOC      0x00000010L
+#       define NWEO_DI_LOC      0x00100000L
+#define NWEO_BROAD_MASK 0x0020L
+#       define NWEO_EN_BROAD    0x00000020L
+#       define NWEO_DI_BROAD    0x00200000L
+#define NWEO_MULTI_MASK 0x0040L
+#       define NWEO_EN_MULTI    0x00000040L
+#       define NWEO_DI_MULTI    0x00400000L
+#define NWEO_PROMISC_MASK 0x0080L
+#       define NWEO_EN_PROMISC  0x00000080L
+#       define NWEO_DI_PROMISC  0x00800000L
+#define NWEO_REM_MASK   0x0100L
+#       define NWEO_REMSPEC     0x00000100L
+#       define NWEO_REMANY      0x01000000L
+#define NWEO_TYPE_MASK  0x0200L
+#       define NWEO_TYPESPEC    0x00000200L
+#       define NWEO_TYPEANY     0x02000000L
+#define NWEO_RW_MASK    0x1000L
+#       define NWEO_RWDATONLY   0x00001000L
+#       define NWEO_RWDATALL    0x10000000L
+.if t .ft R
+.fi
+.RE
+.PP
+The configuration is divided in a number of section (covered by the xx_MASK
+macros).
+Options can be set in the
+.B nweo_flags
+field.
+The first section (\fBNWEO_ACC_MASK\fP) controls the access to a certain
+Ethernet packet type.
+If
+.B NWEO_EXCL
+is selected then this is the only channel that can send or
+receive Ethernet packets of the selected type.
+If
+.B NWEO_SHARED
+is selected then multiple channels (which all have to
+select
+.BR NWEO_SHARED )
+can use the same Ethernet type, they all can send
+packets but incoming packets will be delivered to at most one of them.
+If
+.B NWEO_COPY
+is selected then multiple channels have access to the same
+Ethernet type and all receive a copy of an incoming packet.
+.LP
+The
+.B NWEO_LOC_MASK
+flags control the delivery of packets with a destination
+address equal to the Ethernet address of the machine.
+If
+.B NWEO_EN_LOC
+is selected then these packets will be delivered and with
+.B NWEO_DI_LOC
+they will be discarded.
+.PP
+.BR NWEO_BROAD_MASK ,
+.BR NWEO_MULTI_MASK ,
+and
+.B NWEO_PROMISC_MASK
+do the same to broadcast packets,
+multicast packets and promiscuous mode packets as
+.B NWEO_LOC_MASK
+does for local packets.
+Except that the precise multicast address is taken from the \fBnweo_multi\fP
+field.
+.LP
+The
+.B NWEO_REM_MASK
+flags control whether communication is restricted to
+single destination or not.
+.B NWEO_REMSPEC
+restricts sending and receiving of packets to the single
+remote computer specified in the \fBnweo_rem\fP field.
+.B NWEO_REMANY
+allows sending to and receiving from any remote computer.
+.PP
+.B NWEO_TYPESPEC
+restricts sending and receiving of packets to the type
+specified in \fBnweo_type\fP.
+The type has to be in network byte order (using
+.BR hton (3)).
+.B NWEO_TYPEANY
+allows any type.
+.PP
+If the Ethernet header is completely specified by the
+.B nweo_flags
+i.e., all of
+.BR NWEO_EN_LOC ,
+.BR NWEO_DI_BROAD ,
+.BR NWEO_DI_MULTI ,
+.BR NWEO_DI_PROMISC ,
+.BR NWEO_REMSPEC
+and
+.B NWEO_TYPESPEC
+are
+specified, then
+.B NWEO_RWDATONLY
+can be used to send and receive only the data part of an Ethernet packet.
+If
+.B NWEO_RWDATALL
+is specified then both Ethernet header and data are used.
+.SS "PSIP Functions"
+.PP
+[[[No description available yet.]]]
+.SS "IP Functions"
+.PP
+.ft B
+ioctl(\fIfd\fP, NWIOGIPCONF, &struct nwio_ipconf)
+.ft R
+.PP
+The
+.B NWIOGIPCONF
+ioctl reports the Internet Address and the netmask.
+For the \fInwio_ipconf\fP structure see the \fBNWIOSIPCONF\fP ioctl below.
+.PP
+.ft B
+ioctl(\fIfd\fP, NWIOGIPOROUTE, &struct nwio_route)
+.ft R
+.PP
+The
+.B NWIOGIPOROUTE
+ioctl can be used to query an IP server about its routing table.
+[[[NWIODIPOROUTE, NWIOGIPIROUTE, NWIODIPIROUTE?]]]
+The structure \fBnwio_route\fP is defined in <net/gen/route.h>:
+.PP
+.RS
+.nf
+.if t .ft C
+typedef struct nwio_route
+{
+        u32_t nwr_ent_no;
+        u32_t nwr_ent_count;
+        ipaddr_t nwr_dest;
+        ipaddr_t nwr_netmask;
+        ipaddr_t nwr_gateway;
+        u32_t nwr_dist;
+        u32_t nwr_flags;
+        u32_t nwr_pref;
+} nwio_route_t;
+.SP
+#define NWRF_EMPTY      0
+#define NWRF_INUSE      1
+#define NWRF_FIXED      2
+.if t .ft R
+.fi
+.RE
+.PP
+The requested entry is taken from \fBnwr_ent_no\fP.
+Entries are counted from 0, so the value 0 can be used for an initial query.
+The size of the routing table is returned in \fBnwr_ent_count\fP.
+The \fBnwr_flags\fP indicates if the entry is in use (\fBNWRF_INUSE\fP) and
+if the entry was inserted manually (using \fBNWIOSIPOROUTE\fP) or generated
+by the IP server itself.
+The route is described by
+.BR nwr_dest ,
+.BR nwr_netmask ,
+.BR nwr_gateway ,
+.BR nwr_dist ,
+and
+.BR nwr_pref .
+\fBNwr_dest\fP and \fBnwr_netmask\fP select the destination addresses.
+A value of 0.0.0.0 (0x0) in both \fBnwr_dest\fP and \fBnwr_netmask\fP means
+every host.
+A value of 255.255.255.255 (0xffffffff) in \fBnwr_netmask\fP means a single
+host.
+Other values of \fBnwr_netmask\fP are netmasks for the network specified
+by \fBnwr_dest\fP.
+\fBNwr_gateway\fP is gateway that should be used.
+\fBNwr_dist\fP is a minimal distance.
+Packets with a time to live smaller than \fBnwr_dist\fP will not reach the
+destination.
+If two routes have equal netmask and distance fields but different
+gateways then the gateway with highest value in \fBnwr_pref\fP is used.
+.PP
+.ft B
+ioctl(\fIfd\fP, NWIOSIPCONF, &struct nwio_ipconf)
+.ft R
+.PP
+The
+.B NWIOSIPCONF
+ioctl can be used to inform the IP server about its Internet Address
+and/or its netmask.
+Normally an IP server will discover its Internet Address using the RARP
+protocol.
+.B NWIOSIPCONF
+can be used in the case that the RARP failed, or the netmask has to be changed.
+Note that higher level protocols (TCP and UDP) assume that the Internet Address
+of an IP device does not change, therefore TCP and UDP stop functioning if
+the Internet Address is changed.
+.PP
+The structure \fBnwio_ipconf\fP is defined in <net/gen/ip_io.h>:
+.PP
+.RS
+.nf
+.if t .ft C
+typedef struct nwio_ipconf
+{
+	u32_t   nwic_flags;
+	ipaddr_t nwic_ipaddr;
+	ipaddr_t nwic_netmask;
+} nwio_ipconf_t;
+.SP
+#define NWIC_NOFLAGS            0x0
+#define NWIC_FLAGS              0x3
+#       define NWIC_IPADDR_SET          0x1
+#       define NWIC_NETMASK_SET         0x2
+.if t .ft R
+.fi
+.RE
+.PP
+The function of \fBnwio_ipconf\fP depends on the value of \fBnwic_flags\fP.
+If
+.B NWIC_IPADDR_SET
+is set then the Internet Address will be set to
+\fBnwic_ipaddr\fP.
+If
+.B NWIC_NETMASK_SET
+is set then the Internet Address will be set to
+\fBnwic_netmask\fP.
+.PP
+.ft B
+ioctl(\fIfd\fP, NWIOSIPOPT, &struct nwio_ipopt)
+.ft R
+.PP
+Before an IP channel can be used, it has to be configured using the
+.B NWIOSIPOPT
+ioctl.
+The structure \fBnwio_ipopt\fP is defined in <net/gen/ip_io.h>:
+.PP
+.RS
+.nf
+.if t .ft C
+typedef struct nwio_ipopt
+{
+        u32_t nwio_flags;
+        ipaddr_t nwio_rem;
+        ip_hdropt_t nwio_hdropt;
+        u8_t nwio_tos;
+        u8_t nwio_ttl;
+        u8_t nwio_df;
+        ipproto_t nwio_proto;
+} nwio_ipopt_t;
+.SP
+#define NWIO_NOFLAGS    0x0000L
+#define NWIO_ACC_MASK   0x0003L
+#       define NWIO_EXCL        0x00000001L
+#       define NWIO_SHARED      0x00000002L
+#       define NWIO_COPY        0x00000003L
+#define NWIO_LOC_MASK   0x0010L
+#       define NWIO_EN_LOC      0x00000010L
+#       define NWIO_DI_LOC      0x00100000L
+#define NWIO_BROAD_MASK 0x0020L
+#       define NWIO_EN_BROAD    0x00000020L
+#       define NWIO_DI_BROAD    0x00200000L
+#define NWIO_REM_MASK   0x0100L
+#       define NWIO_REMSPEC     0x00000100L
+#       define NWIO_REMANY      0x01000000L
+#define NWIO_PROTO_MASK 0x0200L
+#       define NWIO_PROTOSPEC   0x00000200L
+#       define NWIO_PROTOANY    0x02000000L
+#define NWIO_HDR_O_MASK 0x0400L
+#       define NWIO_HDR_O_SPEC  0x00000400L
+#       define NWIO_HDR_O_ANY   0x04000000L
+#define NWIO_RW_MASK    0x1000L
+#       define NWIO_RWDATONLY   0x00001000L
+#       define NWIO_RWDATALL    0x10000000L
+.if t .ft R
+.fi
+.RE
+.PP
+The options are divided in several categories:
+.BR NWIO_ACC_MASK ,
+.BR NWIO_LOC_MASK ,
+.BR NWIO_BROAD_MASK ,
+.BR NWIO_REM_MASK ,
+.BR NWIO_PROTO_MASK ,
+.B NWIO_HDR_O_MASK
+and
+.BR NWIO_RW_MASK .
+A channel is configured when one option of each category is set.
+.PP
+The options covered by
+.B NWIO_ACC_MASK
+control the number of channels that
+can use one IP protocol.
+If
+.B NWIO_EXCL
+is specified then only that channel can use a certain IP protocol.
+If
+.B NWIO_SHARED
+then multiple channels that all have to specify
+.B NWIO_SHARED
+can use the same IP protocol, but incoming packets will
+be delivered to a most one channel.
+.B NWIO_COPY
+does not impose any restrictions.
+Every channel gets a copy of an incoming packet.
+.PP
+.B NWIO_LOC_MASK
+and
+.B NWIO_BROAD_MASK
+control the delivery of packets.
+If
+.B NWIO_EN_LOC
+is specified then packets that are explicitly send to
+the IP server are delivered.
+If
+.B NWIO_EN_BROAD
+is specified then broadcast packets are delivered.
+Either one or both of them can be disabled with
+.B NWIO_DI_LOC
+and
+.BR NWIO_DI_BROAD .
+.PP
+.B NWIO_REMSPEC
+can be used to restrict communication to one remote host.
+This host is taken from the \fBnwio_rem\fP field.
+If any remote host is to be allowed then
+.B NWIO_REMANY
+can be used.
+.PP
+.B NWIO_PROTOSPEC
+restricts communication to one IP protocol, specified
+in \fBnwio_proto\fP.
+.B NWIO_PROTOANY
+allows any protocol to be sent or received.
+.PP
+.B NWIO_HDR_O_SPEC
+specifies all IP header options in advance.
+The values are taken from
+.BR nwio_hdropt ,
+.BR nwio_tos ,
+.BR nwio_ttl ,
+and
+.BR nwio_df .
+\fBNwio_hdropt\fP specifies the IP options that should be present in an
+outgoing packet.
+\fBIp_hdropt_t\fP is defined in <net/gen/in.h>:
+.PP
+.RS
+.nf
+.if t .ft C
+typedef struct ip_hdropt
+{
+        u8_t iho_opt_siz;
+        u8_t iho_data[IP_MAX_HDR_SIZE-IP_MIN_HDR_SIZE];
+} ip_hdropt_t;
+.if t .ft R
+.fi
+.RE
+.PP
+The bytes of size \fBiho_opt_siz\fP in \fBiho_data\fP are appended to the IP
+header.
+\fBNwio_tos\fP specifies the value of the ``type of service'' bits,
+\fBnwio_ttl\fP gives the value of the ``time to live'' field and \fBnwio_df\fP
+specifies whether fragmentation is disallowed or not.
+.B NWIO_HDR_O_ANY
+specifies that the header options should be specified at
+each write request.
+.PP
+.B NWIO_RWDATONLY
+specifies that the header should be omitted from a
+write request.
+This option can only be used when all header fields are specified in previous
+options:
+.BR NWIO_EN_LOC ,
+.BR NWIO_DI_BROAD ,
+.BR NWIO_REMSPEC ,
+.B NWIO_PROTOSPEC
+and
+.BR NWIO_HDR_O_SPEC .
+A read operation will also only return the data part, so the IP options will
+be lost.
+.PP
+.ft B
+ioctl(\fIfd\fP, NWIOSIPOROUTE, &struct nwio_route)
+.ft R
+.PP
+The
+.B NWIOSIPOROUTE
+ioctl adds a route to the routing table.
+See \fBNWIOGIPOROUTE\fP above for a description of the \fBnwio_route\fP
+structure.
+The fields \fBnwr_ent_no\fP and \fBnwr_ent_count\fP are ignored.
+.SS "TCP Functions"
+.PP
+.ft B
+ioctl(\fIfd\fP, NWIOTCPCONN, &struct nwio_tcpcl)
+.ft R
+.PP
+The
+.B NWIOTCPCONN
+ioctl tries to setup a connection with a remote TCP/IP server.
+The channel must be fully configured (see
+.BR NWIOSTCPCONF )
+and values for the local port, the remote port and the remote address have be
+specified using
+.B NWTC_LP_SET
+or
+.BR NWTC_LP_SEL ,
+.B NWTC_SET_RA
+and
+.BR NWTC_SET_RP .
+The struct nwio_tcpcl is defined in <net/gen/tcp_io.h> as:
+.PP
+.RS
+.nf
+.if t .ft C
+typedef struct nwio_tcpcl
+{
+	long nwtcl_flags;
+	long nwtcl_ttl;
+} nwio_tcpcl_t;
+.if t .ft R
+.fi
+.RE
+.PP
+Set the
+.B nwtcl_flags
+field to zero before the connect or listen call.  [[[Further explanation of
+nwio_tcpcl?]]]
+.PP
+.ft B
+ioctl(\fIfd\fP, NWIOGTCPCONF, &struct nwio_tcpconf)
+.ft R
+.PP
+This call reports the current configuration of a TCP channel.
+The
+.B nwtc_flags
+field shows the status of the
+.BR access ,
+.BR locport ,
+.B remaddr
+and
+.B remport
+fields.
+.B Nwtc_locaddr
+contains the Internet address of the TCP/IP server.
+.B Remaddr
+contains the Internet address of the remote TCP/IP server when set with
+.B NWTC_SET_RA
+or after a successful connect or listen (see
+.B NWIOTCPCONN
+or
+.BR NWIOTCPLISTEN ).
+.B Nwio_locport
+contains the local TCP/IP port set with
+.B NWTC_LP_SET
+or the selected port set with
+.BR NWTC_LP_SEL .
+.B Nwtc_remport
+contains the TCP port of the remote TCP/IP server as set with
+.B NWIO_SET_RP
+or after a successful connect or listen.
+.PP
+A value of 0 (zero) is reported for
+.BR nwtc_remaddr ,
+.B nwtc_locport
+or
+.B nwtc_remport
+when no value is set either explicitly or implicitly.
+.PP
+.ft B
+ioctl(\fIfd\fP, NWIOTCPLISTEN, &struct nwio_tcpcl)
+.ft R
+.PP
+The
+.B NWIOTCPLISTEN
+ioctl waits until a remote TCP/IP server tries to connect to this channel.
+The channel has to be configured (see
+.BR NWIOSTCPCONF ).
+An additional restriction is that the local port
+must be set (with
+.BR NWTC_LP_SET )
+or selected (with
+.BR NWTC_LP_SEL ).
+When a remote address is set only connections for that host are accepted, and
+when a remote port is set only connections from that port are accepted.
+After a successful listen
+.B NWIOGTCPCONF
+can be used to find out what the address and port of the other side are.
+.PP
+.ft B
+ioctl(\fIfd\fP, NWIOSTCPCONF, &struct nwio_tcpconf)
+.ft R
+.PP
+Before a TCP channel can be used it must configured using the
+.B NWIOSTCPCONF
+ioctl.
+The parameters to
+.B NWIOSTCPCONF
+are the channel file descriptor and a
+.B struct nwio_tcpconf
+as defined in <net/gen/tcp_io.h>:
+.PP
+.RS
+.nf
+.if t .ft C
+typedef struct nwio_tcpconf
+{
+	u32_t nwtc_flags;
+	ipaddr_t nwtc_locaddr;
+	ipaddr_t nwtc_remaddr;
+	tcpport_t nwtc_locport;
+	tcpport_t nwtc_remport;
+} nwio_tcpconf_t;
+.SP
+#define NWTC_NOFLAGS    0x0000L
+#define NWTC_ACC_MASK   0x0003L
+#       define NWTC_EXCL        0x00000001L
+#       define NWTC_SHARED      0x00000002L
+#       define NWTC_COPY        0x00000003L
+#define NWTC_LOCPORT_MASK       0x0030L
+#       define NWTC_LP_UNSET    0x00000010L
+#       define NWTC_LP_SET      0x00000020L
+#       define NWTC_LP_SEL      0x00000030L
+#define NWTC_REMADDR_MASK       0x0100L
+#       define NWTC_SET_RA      0x00000100L
+#       define NWTC_UNSET_RA    0x01000000L
+#define NWTC_REMPORT_MASK       0x0200L
+#       define NWTC_SET_RP      0x00000200L
+#       define NWTC_UNSET_RP    0x02000000L
+.if t .ft R
+.fi
+.RE
+.PP
+A tcp channel is considered configured when one flag in each category has
+been selected.
+Thus one of
+.BR NWTC_EXCL ,
+.B NWTC_SHARED
+or
+.BR NWTC_COPY ,
+one of
+.BR NWTC_LP_UNSET ,
+.B NWTC_LP_SET
+or
+.BR NWTC_LP_SEL ,
+one of
+.B NWTC_SET_RA
+or
+.BR NWTC_UNSET_RA ,
+and one of
+.B NWTC_SET_RP
+or
+.BR NWTC_UNSET_RP .
+.PP
+The acc flags control the access to a certain TCP port.
+.B NWTC_EXCL
+means exclusive access.
+An attempt to configure a channel will be denied if the same port is specified
+as that of a channel that requested exclusive access.
+.B NWTC_SHARED
+indicates that several channels use the same port but cooperate.
+If the shared mode is specified for one channel than all other channel that
+use the same port should also be configured with the
+.B NWTC_SHARED
+flag.
+.B NWTC_COPY
+is specified when the programmer does not care about other channels.
+This is the default.
+.PP
+The locport flags control which TCP port is used for communication.
+.B NWTC_LP_UNSET
+indicates the absence of a local port.
+This is the default.
+.B NWTC_LP_SET
+means that the
+.B nwtc_locport
+field contains the local port to be used by TCP.
+This value must be in network byte order (see
+.BR hton (3).)
+.B NWTC_LP_SEL
+requests the TCP server to pick a port.
+This port will be in the range from 32768 to 65535 and will be unique.
+.LP
+The
+.B remaddr
+flags specify which hosts are acceptable for connections.
+.B NWTC_SET_RA
+indicates that only connection to the host specified in
+.B nwtc_remaddr
+are acceptable.
+.B Nwtc_remaddr
+should be in network byte order (see
+.BR hton (3).)
+.B NWTC_UNSET_RA
+allows every host on the other side of a connection.
+This is the default.
+.PP
+The
+.B remport
+flags specify which remote ports are acceptable for connections.
+.B NWTC_SET_RP
+indicates that only the port specified in
+.B nwtc_remport
+is acceptable.
+.B NWTC_UNSET_RP
+allows every port on the other side of a connection.
+This is the default.
+.PP
+.ft B
+ioctl(\fIfd\fP, NWIOTCPSHUTDOWN)
+.ft R
+.PP
+The
+.B NWIOTCPSHUTDOWN
+tells the TCP/IP server that no more data will be sent over the channel
+specified by
+.IR fd .
+This command can be issued when the channel is connected to a remote TCP/IP
+server.
+The TCP/IP server will tell the remote TCP/IP server and the client of the
+remote TCP/IP server will receive an end-of-file indication.
+.PP
+.ft B
+ioctl(\fIfd\fP, NWIOGTCPOPT, &struct nwio_tcpopt)
+.br
+ioctl(\fIfd\fP, NWIOSTCPOPT, &struct nwio_tcpopt)
+.ft R
+.PP
+The behaviour of a TCP channel may be changed by setting a number of
+options.  The TCP options can be obtained with the
+.B NWIOGTCPOPT
+ioctl and set with the
+.B NWIOSTCPOPT
+ioctl.  The options are passed in a
+.B struct nwio_tcpopt
+as defined in <net/gen/tcp_io.h>:
+.PP
+.RS
+.nf
+.if t .ft C
+typedef struct nwio_tcpopt
+{
+	u32_t nwto_flags;
+} nwio_tcpopt_t;
+.SP
+#define NWTO_NOFLAG     0x0000L
+#define NWTO_SND_URG_MASK       0x0001L
+#       define NWTO_SND_URG     0x00000001L
+#       define NWTO_SND_NOTURG  0x00010000L
+#define NWTO_RCV_URG_MASK       0x0002L
+#       define NWTO_RCV_URG     0x00000002L
+#       define NWTO_RCV_NOTURG  0x00020000L
+#define NWTO_BSD_URG_MASK       0x0004L
+#       define NWTO_BSD_URG     0x00000004L
+#define NWTO_DEL_RST_MASK       0x0008L
+#       define NWTO_DEL_RST     0x00000008L
+.if t .ft R
+.fi
+.RE
+.PP
+The
+.B NWTO_SND_URG
+option causes bytes written to the channel to be send out as urgent data.
+On receiving an
+.B EURG
+error the
+.B NWTO_RCV_URG
+option must be set to switch over to reading urgent data.  When all urgent
+data has been read an
+.B ENOURG
+error will follow,
+indicating that the option must be cleared with
+.BR NWTO_RCV_NOTURG .
+Alas the BSD implementation of urgent data disagrees with the RFC's, so to
+be BSD compatible one must set the
+.B NWTO_BSD_URG
+option beforehand on a channel that is to send or receive urgent data.
+Given that the BSD implementation is the regarded as the TCP/IP standard one
+should always use the BSD style.  The
+.B NWTO_DEL_RST
+option delays a failure response on a connect to the same port as the
+current open connection.  Without this option a connect would fail if
+a server is not yet listening.  With this option a connect will linger
+on until the server starts listening.  This option is useful for a server
+that opens a connection, tells the remote end the local port number and
+then listens (FTP), or for a program that forks off servers for incoming
+connections (TELNET).  A new connection may come in before a new listen
+can be started, so it is nice if the new connect doesn't fail.  Use this
+option only when it is clearly needed.
+.SS "UDP Functions"
+.PP
+.ft B
+ioctl(\fIfd\fP, NWIOGUDPOPT, &struct nwio_udpopt)
+.ft R
+.PP
+The
+.B NWIOGUDPOPT
+ioctl returns the current options that result from the default options
+and the options set with
+.BR NWIOSUDPOPT .
+When
+.B NWUO_LP_SEL
+or
+.B NWUO_LP_SET
+is selected the local port is returned in
+.BR nwuo_locport .
+When
+.B NWUO_RP_SET
+is selected the remote port is returned in
+.BR nwuo_remport .
+The local address is always returned in
+.BR nwuo_locaddr ,
+and when
+.B NWUO_RA_SET
+is selected the remote address is returned in
+.BR nwuo_remaddr .
+.PP
+.ft B
+ioctl(\fIfd\fP, NWIOSUDPOPT, &struct nwio_udpopt)
+.ft R
+.PP
+A UDP channel must be configured using the
+.B NWIOSUDPOPT
+ioctl before any data can be read or written.
+.B NWIOSUDPOPT
+takes two parameters, a file descriptor to an open UDP device and
+pointer to a
+.B nwio_udpopt
+structure that describes the requested configuration.
+The
+.B nwio_udpopt
+structure is defined in <net/gen/udp_io.h> as:
+.PP
+.RS
+.nf
+.if t .ft C
+typedef struct nwio_udpopt
+{
+	unsigned long nwuo_flags;
+	udpport_t nwuo_locport;
+	udpport_t nwuo_remport;
+	ipaddr_t nwuo_locaddr;
+	ipaddr_t nwuo_remaddr;
+} nwio_udpopt_t;
+.SP
+#define NWUO_NOFLAGS            0x0000L
+#define NWUO_ACC_MASK           0x0003L
+#define         NWUO_EXCL               0x00000001L
+#define         NWUO_SHARED             0x00000002L
+#define         NWUO_COPY               0x00000003L
+#define NWUO_LOCPORT_MASK       0x000CL
+#define         NWUO_LP_SEL             0x00000004L
+#define         NWUO_LP_SET             0x00000008L
+#define         NWUO_LP_ANY             0x0000000CL
+#define NWUO_LOCADDR_MASK       0x0010L
+#define         NWUO_EN_LOC             0x00000010L
+#define         NWUO_DI_LOC             0x00100000L
+#define NWUO_BROAD_MASK         0x0020L
+#define         NWUO_EN_BROAD           0x00000020L
+#define         NWUO_DI_BROAD           0x00200000L
+#define NWUO_REMPORT_MASK       0x0100L
+#define         NWUO_RP_SET             0x00000100L
+#define         NWUO_RP_ANY             0x01000000L
+#define NWUO_REMADDR_MASK       0x0200L
+#define         NWUO_RA_SET             0x00000200L
+#define         NWUO_RA_ANY             0x02000000L
+#define NWUO_RW_MASK            0x1000L
+#define         NWUO_RWDATONLY          0x00001000L
+#define         NWUO_RWDATALL           0x10000000L
+#define NWUO_IPOPT_MASK         0x2000L
+#define         NWUO_EN_IPOPT           0x00002000L
+#define         NWUO_DI_IPOPT           0x20000000L
+.if t .ft R
+.fi
+.RE
+.PP
+A UDP channel is considered configured when one flag in each category has been
+selected.
+Thus one of
+.BR NWUO_EXCL ,
+.B NWUO_SHARED
+or
+.BR NWUO_COPY ,
+one of
+.BR NWUO_LP_SEL ,
+.B NWUO_LP_SET
+or
+.BR NWUO_LP_ANY ,
+one of
+.B NWUO_EN_LOC
+or
+.BR NWUO_DI_LOC ,
+one of
+.BR NWUO_EN_BROAD ,
+or
+.BR NWUO_DI_BROAD ,
+one of
+.BR NWUO_RP_SET ,
+or
+.BR NWUO_RP_ANY ,
+one of
+.BR NWUO_RA_SET ,
+or
+.BR NWUO_RA_ANY ,
+one of
+.BR NWUO_RWDATONLY ,
+or
+.BR NWUO_RWDATALL ,
+and one of
+.BR NWUO_EN_IPOPT ,
+or
+.BR NWUO_DI_IPOPT .
+The acc flags control the access to a certain UDP port.
+.B NWUO_EXCL
+means exclusive access:
+no other channel can use this port.
+.B NWUO_SHARED
+means shared access:
+only channels that specify shared access can use this port
+and all packets that are received are handed to at most one channel.
+.B NWUO_COPY
+imposes no access restriction and all channels get a copy of every received
+packet for that port.
+.PP
+The
+.B locport
+flags control the selection of the UDP port for this channel.
+.B NWUO_LP_SEL
+requests the server to pick a port.
+This port will be in the range from 32768 to 65535 and it will be unique.
+.B NWUO_LP_SET
+sets the local port to the value of the
+.B nwuo_locport
+field.
+.B NWUO_LP_ANY
+does not select a port.
+Reception of data is therefore not possible but it is
+possible to send data.
+.PP
+The
+.B locaddr
+flags control the reception of packets.
+.B NWUO_EN_LOC
+enables the reception of packets with the local IP address as destination.
+.B NWUO_DI_LOC
+disables the reception of packet for the local IP address.
+.PP
+The
+.B broad
+flags control the reception of broadcast packets.
+.B NWUO_EN_BROAD
+enables the reception of broadcast packets and
+.B NWUO_DI_BROAD
+disables the reception of broadcast packets.
+.PP
+The
+.B remport
+flags let the client to specify one specific remote UDP port or
+to allow any remote port.
+.B NWUO_RP_SET
+sets the remote UDP port to the value of
+.BR nwuo_remport .
+Only packets with a matching remote port will be delivered
+and all packets will be sent to that port.
+.B NWUO_RP_ANY
+allows reception of packets form any port and when transmitting packets the
+remote port has to be specified.
+.PP
+The
+.B remaddr
+flags control the remote IP address.
+.B NWUO_RA_SET
+sets the remote IP address the value of
+.BR nwuo_remaddr .
+Only packets from that address will be delivered and all packets will be sent
+to that address.
+.B NWUO_RA_ANY
+allows reception of packets from any host and when transmitting packets the
+remote host has to be specified.
+.PP
+The
+.B rw
+flags control the format of the data to be sent or received.
+With
+.B NWUO_RWDATONLY
+only the data part of a UDP packet is sent to the server and only the data
+part is received from the server.
+The
+.B NWUO_RWDATALL
+mode presents the data part of a UDP packet with a header that contains
+the source and destination IP address, source and destination UDP ports,
+the IP options, etc.
+The server expects such a header in front of the data to be transmitted.
+.ig \" Some for Philip to explain properly:
+The header is defined in <net/gen/udp_hdr.h> and looks like this:
+.PP
+.RS
+.nf
+.if t .ft C
+typedef struct udp_io_hdr
+{
+	ipaddr_t uih_src_addr;
+	ipaddr_t uih_dst_addr;
+	udpport_t uih_src_port;
+	udpport_t uih_dst_port;
+	u16_t uih_ip_opt_len;
+	u16_t uih_data_len;
+} udp_io_hdr_t;
+.if t .ft R
+.fi
+.RE
+.PP
+The first four fields are the source and destination IP addresses and
+ports.
+.B Uih_ip_opt_len
+is ???.
+.B Uih_data_len
+should equal the length of the packet data (packet lenght minus the
+header.) ???
+..
+.PP
+The
+.B ipopt
+flags control the delivery and transmission of IP options.
+When
+.B NWUO_EN_IPOPT
+is set IP, options will be delivered and sent.
+When
+.B NWUO_DI_IPOPT
+is set IP option will be stripped from received packets and no IP options will
+be sent.
+.ig \" MINIX 3 doesn't have this stuff (yet? ever?)
+.SS "UDP Library Functions"
+.PP
+The following routines provide an somewhat easier to use interface to UDP than
+the routines described above (\fBtcpip_open\fP, \fBudp_ioc_setopt\fP,
+\fBtcpip_read\fP and \fBtcpip_write\fP).
+.LP
+.sC
+errstat
+udp_connect(udp_cap, chan_cap, srcport, dstport, dstaddr, flags)
+capability *udp_cap;
+capability *chan_cap;
+udpport_t srcport;
+udpport_t dstport;
+ipaddr_t dstaddr;
+int flags;
+.eC
+.kW "\fIudp_connect\fP"
+\fIUdp_connect\fP combines the functionality of \fItcpip_open\fP and
+\fIudp_ioc_setopt\fP.
+A pointer to a UDP server capability should be passed in \fIudp_cap\fP, and
+the channel capability will be returned in the capability pointed to by
+\fIchan_cap\fP.
+If \fIsrcport\fP is 0 then an unused port will be selected, otherwise the local
+port will be set to \fIsrcport\fP.
+If \fIdstport\fP is non-zero then communication will be restricted to remote ports
+that equal to \fIdstport\fP, otherwise any data can be sent to or received from
+any remote port.
+The same thing applies to \fIdstaddr\fP; if \fIdstaddr\fP is non-zero then
+only \fIdstaddr\fP can be reached.
+Currently no flags are defined so \fIflags\fP should be 0.
+.sH
+udp_reconnect
+.LP
+.sC
+errstat
+udp_reconnect(chan_cap, srcport, dstport, dstaddr, flags)
+capability *chan_cap;
+udpport_t srcport;
+udpport_t dstport;
+ipaddr_t dstaddr;
+int flags;
+.eC
+.kW "\fIudp_reconnect\fP"
+\fIUdp_reconnect\fP is the same as \fIudp_connect\fP except that an existing
+channel capability is (re)used.
+.sH
+udp_read_msg
+.LP
+.sC
+errstat
+udp_read_msg(chan_cap, msg, msglen, actlen, flags)
+capability *chan_cap;
+char *msg;
+int msglen;
+int *actlen;
+int flags;
+.eC
+.kW "\fIudp_read_msg\fP"
+\fIUdp_read_msg\fP delivers a UDP packet.
+The data part of the UDP packet is
+prepended with an \fIudp_io_hdr\fP.
+The actual length of the possibly truncated packet is returned in \fIactlen\fP.
+No flags are defined so \fIflags\fP should be 0.
+.sH
+udp_write_msg
+.LP
+.sC
+errstat
+udp_write_msg(chan_cap, msg, msglen, flags)
+capability *chan_cap;
+char *msg;
+int msglen;
+int flags;
+.eC
+.kW "\fIudp_write_msg\fP"
+A UDP packet can be sent with \fIudp_write_msg\fP.
+\fIMsg\fP should point to a \fIudp_io_hdr\fP followed by the data part of the
+UDP packet.
+The \fIuih_dst_addr\fP and \fIuih_dst_port\fP fields of the \fIudp_io_hdr\fP
+should be filled in if no values are specified in the \fIudp_connect\fP,
+or \fIudp_reconnect\fP.
+.sH
+udp_close
+.LP
+.sC
+errstat
+udp_close(chan_cap, flags)
+capability *chan_cap;
+int flags;
+.eC
+.kW "\fIudp_close\fP"
+\fIUdp_close\fP cleans up the administration kept by the UDP library but does
+not destroy the capability.
+The function should be used if the capability is passed to another process
+and should continue to exist.
+No flags are defined so \fIflags\fP should be 0.
+.sH
+udp_destroy
+.LP
+.sC
+errstat
+udp_destroy(chan_cap, flags)
+capability *chan_cap;
+int flags;
+.eC
+.kW "\fIudp_destroy\fP"
+\fIUdp_destroy\fP not only cleans up the administration kept by the UDP library
+but also destroys the channel capability.
+..
+.SH FILES
+.IP /dev/eth* \w'/dev/psip*mmm'u
+Raw ethernet.  The numbers in the device names are decimal, so one may see
+names from
+.B eth0
+to
+.BR eth15 .
+
+.IP /dev/psip*
+First and second Pseudo IP network.
+.IP /dev/ip*
+IP devices for two ethernets and two Pseudo IP networks.
+.IP /dev/tcp*
+TCP devices for same four networks.
+.IP /dev/udp*
+UDP devices.
+.IP "/dev/eth, /dev/psip, /dev/ip, /dev/tcp, /dev/udp"
+Devices for the default network, links to the devices above.
+.B Eth
+is only present if ethernet is the default,
+.B psip
+only for pseudo IP.
+.SH "SEE ALSO"
+.BR hton (3),
+.BR oneC_sum (3),
+.BR inet (8),
+.BR boot (8).
+.SH DIAGNOSTICS
+Several errors may be returned by the TCP/IP server.  The error code
+is found in the
+.B errno
+variable if the
+.BR read ,
+.BR write ,
+or
+.B ioctl
+call returns -1.  The TCP/IP error codes defined in <errno.h> are:
+.IP EPACKSIZE 5c
+This indicates an attempt to read or write with a buffer that is too
+large or too small.
+.IP EOUTOFBUFS
+The TCP/IP server has insufficient memory to execute the request.
+.IP EBADIOCTL
+This indicates an attempt to execute a command the particular server
+does not understand.
+For example, a
+.B NWIOGTCPCONF
+on an ETH channel.
+.IP EBADMODE
+The request is refused because the channel is not fully configured, in the
+wrong state or the parameters are invalid.
+.IP EBADDEST
+This indicates an illegal destination address for a packet.
+.IP EDSTNORCH
+The destination is not reachable.
+.IP EISCONN
+The channel is already connected so a second request is refused.
+.IP EADDRINUSE
+This address is in use.
+.IP ECONNREFUSED
+The connection is refused by the other side.
+.IP ECONNRESET
+The connection is reset (non-gracefully terminated) by the other side.
+.IP ETIMEDOUT
+The connection is terminated due to an expired timer.
+.IP EURG
+Urgent data is present and the current receive mode does not allow urgent data
+to be transferred.
+.IP ENOURG
+No urgent data is present and a request came for urgent data.
+.IP ENOTCONN
+The request requires a connected channel and the channel is not connected.
+.IP ESHUTDOWN
+The connection is shut down.
+That is, a
+.B NWIOTCPSHUTDOWN
+has been executed so no more data can be transmitted.
+.IP ENOCONN
+The connection does not exist.
+.IP EGENERIC
+A generic error code for extremely weird cases.
+.SH AUTHOR
+Philip Homburg (philip@cs.vu.nl)
+
+.\"
+.\" $PchId: ip.4,v 1.4 2001/01/08 19:58:14 philip Exp $
Index: /trunk/minix/man/man4/lp.4
===================================================================
--- /trunk/minix/man/man4/lp.4	(revision 9)
+++ /trunk/minix/man/man4/lp.4	(revision 9)
@@ -0,0 +1,28 @@
+.TH LP 4
+.SH NAME
+lp \- line printer
+.SH DESCRIPTION
+The
+.B lp
+device refers to the line printer attached to the parallel port.  Any byte
+written to this device is printed.  Only one process may have the device
+open.
+.PP
+The
+.B write (2)
+call may return with a smaller count then the number of bytes requested to
+write.  The next write call is then likely to fail with the error code
+.B EAGAIN
+if the printer is out of paper, or
+.B EIO
+if the printer is turned off.
+.SH FILES
+.TP 10
+/dev/lp
+Parallel port device.
+.SH "SEE ALSO"
+.BR lp (1).
+.SH BUGS
+Only one parallel port is supported.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man4/mtio.4
===================================================================
--- /trunk/minix/man/man4/mtio.4	(revision 9)
+++ /trunk/minix/man/man4/mtio.4	(revision 9)
@@ -0,0 +1,98 @@
+.TH MTIO 4
+.SH NAME
+mtio \- magnetic tape commands
+.SH SYNOPSIS
+.B "#include <sys/types.h>"
+.br
+.B "#include <sys/mtio.h>"
+.br
+.B "#include <sys/ioctl.h>"
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+The magnetic tape devices described in
+.BR sd (4)
+may be sent commands or queried for their status using the following ioctl
+calls:
+.PP
+.RS
+.BR ioctl ( \fIfd ,
+.BR MTIOCTOP ,
+.RB & "struct mtop" )
+.br
+.BR ioctl ( \fIfd ,
+.BR MTIOCGET ,
+.RB & "struct mtget" )
+.RE
+.PP
+The struct mtop, struct mtget and associated definitions are defined in
+<sys/mtio.h> as follows:
+.PP
+.nf
+
+/* Tape operations: ioctl(fd, MTIOCTOP, &struct mtop) */
+
+.ta +4n +7n +15n
+struct mtop {
+	short	mt_op;	/* Operation (MTWEOF, etc.) */
+	int	mt_count;	/* Repeat count. */
+};
+
+.ta +17n +5n
+#define MTWEOF	0	/* Write End-Of-File Marker */
+#define MTFSF	1	/* Forward Space File mark */
+#define MTBSF	2	/* Backward Space File mark */
+#define MTFSR	3	/* Forward Space Record */
+#define MTBSR	4	/* Backward Space Record */
+#define MTREW	5	/* Rewind tape */
+#define MTOFFL	6	/* Rewind and take Offline */
+#define MTNOP	7	/* No-Operation, set status only */
+#define MTRETEN	8	/* Retension (completely wind and rewind) */
+#define MTERASE	9	/* Erase the tape and rewind */
+#define MTEOM	10	/* Position at End-Of-Media */
+#define MTMODE	11	/* Select tape density */
+#define MTBLKZ	12	/* Select tape block size */
+
+/* Tape status: ioctl(fd, MTIOCGET, &struct mtget) */
+
+.ta +4n +7n +15n
+struct mtget {
+	short	mt_type;	/* Type of tape device. */
+
+	/* Device dependent "registers". */
+	short	mt_dsreg;	/* Drive status register. */
+	short	mt_erreg;	/* Error register. */
+
+	/* Misc info. */
+	off_t	mt_resid;	/* Residual count. */
+	off_t	mt_fileno;	/* Current File Number. */
+	off_t	mt_blkno;	/* Current Block Number within file. */
+	off_t	mt_blksize;	/* Current block size. */
+};
+
+.fi
+.PP
+See
+.BR mt (1)
+for a detailed description on what each operation does.  The mt_type field
+is always zero, there is no use for it yet.  Mt_dsreg is 0 (OK), 1 (Error),
+or 2 (EOF encountered.)  Mt_erreg holds the SCSI sense key of the last
+operation.  Mt_blksize is the current tape block size in bytes, zero if the
+block size is variable.
+.PP
+Note that one can issue these commands on a file descriptor that is in use
+to read or write data, something that
+.B mt
+can't do.  So you can add eof markers in the middle of an output stream,
+or get the status of a device before a rewind-on-close tape rewinds.
+.PP
+The driver will automatically add an end of file marker to a tape that is
+written to if you execute a space command.  If you write eof markers
+yourself then the driver will not add one extra on close.
+.SH "SEE ALSO"
+.BR mt (1),
+.BR sd (4).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man4/tty.4
===================================================================
--- /trunk/minix/man/man4/tty.4	(revision 9)
+++ /trunk/minix/man/man4/tty.4	(revision 9)
@@ -0,0 +1,736 @@
+.TH TTY 4
+.SH NAME
+tty, termios \- terminals
+.SH DESCRIPTION
+The
+.B tty
+driver family takes care of all user input and output.  It governs the
+keyboard, the console, the serial lines, and pseudo ttys.  Input on any of
+these devices undergoes "input processing", and output undergoes "output
+processing" according to the standard termios terminal interface.
+.SS "Input processing"
+Each terminal device has an input queue.  This queue is used to store
+preprocessed input characters, and to perform the backspacing and erase
+functions.  Some special characters like a newline make the contents of the
+queue available to a process reading from the terminal.  Characters up to
+and including the newline, or another so-called "line break", may be read by
+a process.  The process need not read all characters at once.  An input line
+may be read byte by byte if one wants to.  A line break just makes
+characters available for reading, thats all.
+.PP
+When data is made available depends on whether the tty is in canonical mode
+or not.  In canonical mode the terminal processes input line by line.  A
+line ends with a newline
+.RB ( NL ),
+end-of-file
+.RB ( EOF ),
+or end-of-line
+.RB ( EOL ).
+Characters that have not been delimited by such a line break may be erased
+one by one with the
+.B ERASE
+character or all at once with the
+.B KILL
+character.  Once a line break is typed the characters become available to a
+reading process and can no longer be erased.  Once read they are removed
+from the input queue.  Several lines may be gathered in the input queue if
+no reader is present to read them, but a new reader will only receive one
+line.  Two line breaks are never returned in one read call.  The input queue
+has a maximum length of
+.B MAX_CANON
+characters.  Any more characters are discarded.  One must use
+.B ERASE
+or
+.B KILL
+to make the terminal functioning again if the input queue fills up.  If
+nonblocking I/O is set then \-1 is returned with
+.B errno
+set to
+.B EAGAIN
+if the reader would otherwise be blocked.
+.PP
+In non-canonical mode (raw mode for short) all characters are immediately
+available to the reader in principle.  One may however tune the terminal to
+bursty input with the
+.B MIN
+and
+.B TIME
+parameters, see the raw I/O parameters section below.  In raw mode no
+characters are discarded if the input queue threatens to overflow if the
+device supports flow control.
+.SS "Output processing"
+Characters written to a terminal device may undergo output processing, which
+is usually just inserting a carriage returns before newlines.  A writer
+may return before all characters are output if the characters can be stored
+in the output buffers.  If not then the writer may be blocked until space is
+available.  If non-blocking I/O is set then only the count of the number of
+bytes that can be processed immediately is returned.  If no characters can
+be written at all then \-1 is returned with
+.B errno
+set to
+.BR EAGAIN .
+.SS "Special characters"
+Some characters have special functions in some of the terminal modes.  These
+characters are as follows, with the MINIX 3 defaults shown in parentheses:
+.TP 5
+.BR INTR " (^?)"
+Special input character that is recognized if
+.B ISIG
+is set.  (For
+.B ISIG
+and other flags see the various modes sections below.)  It causes a
+.B SIGINT
+signal to be sent to all processes in the terminal process group.  (See the
+section on session leaders below.)
+.TP
+.BR QUIT " (^\e)"
+Special input character if
+.B ISIG
+is set.  Causes a
+.B SIGQUIT
+signal to be sent to the terminal process group.
+.TP
+.BR ERASE " (^H)"
+Special input character if
+.B ICANON
+is set.  Erases the last character in the current line.
+.TP
+.BR KILL " (^U)"
+Special input character if
+.B ICANON
+is set.  Erases the entire line.
+.TP
+.BR EOF " (^D)"
+Special input character if
+.B ICANON
+is set.  It is a line break character that is not itself returned to a
+reader.  If EOF is typed with no input present then the read returns zero,
+which normally causes the reader to assume that end-of-file is reached.
+.TP
+.BR CR " (^M)"
+Special input character if
+.B IGNCR
+or
+.B ICRNL
+is set.  It is a carriage return ('\er').  If
+.B IGNCR
+is set then
+.B CR
+is discarded.  If
+.B ICRNL
+is set and
+.B IGNCR
+is not set then
+.B CR
+is changed into an
+.B NL
+and has the same function as
+.BR NL.
+.TP
+.BR NL " (^J)"
+Special input character if
+.B ICANON
+is set.  It is both a newline ('\en') and a line break.
+.br
+Special output character if
+.B OPOST
+and
+.B ONLCR
+are set.  A
+.B CR NL
+sequence is output instead of just
+.BR NL .
+(MINIX 3 specific, but almost mandatory on any UNIX-like system.)
+.TP
+.BR TAB " (^I)"
+Special character on output if
+.B OPOST
+and
+.B XTABS
+are set.  It is transformed into the number of spaces necessary to reach a
+column position that is a multiple of eight.  (Only needed for terminals
+without hardware tabs.)
+.TP
+.BR EOL " (undefined)"
+Special input character if
+.B ICANON
+is set.  It is an additional line break.
+.TP
+.BR SUSP " (^Z)"
+Special input character if job control is implemented and
+.B ISIG
+is set.  It causes a
+.B SIGTSTP
+signal to be send to the terminal process group.  (MINIX 3 does not have job
+control.)
+.TP
+.BR STOP " (^S)"
+Special input character if
+.B IXON
+is set.  It suspends terminal output and is then discarded.
+.TP
+.BR START " (^Q)"
+Special output character if
+.B IXON
+is set.  It starts terminal output if suspended and is then discarded.  If
+.B IXANY
+is also set then any other character also starts terminal output, but they
+are not discarded.
+.TP
+.BR REPRINT " (^R)"
+Special input character if
+.B IEXTEN
+and
+.B ECHO
+are set.  Reprints the input queue from the last line break onwards.  A
+reprint also happens automatically if the echoed input has been messed up by
+other output and
+.B ERASE
+is typed.
+.TP
+.BR LNEXT " (^V)"
+Special input character if
+.B IEXTEN
+is set.  It is the "literal next" character that causes the next character
+to be input without any special processing.
+.TP
+.BR DISCARD " (^O)"
+Special input character if
+.B IEXTEN
+is set.  Causes output to be discarded until it is typed again.  (Implemented
+only under Minix-vmd.)
+.PP
+All of these characters except
+.BR CR ,
+.B NL
+and
+.B TAB
+may be changed or disabled under MINIX 3.  (Changes to
+.B START
+and
+.B STOP
+may be ignored under other termios implementations.)  The
+.B REPRINT
+and
+.B LNEXT
+characters are MINIX 3 extensions that are commonly present in other
+implementations.  \s-2POSIX\s+2 is unclear on whether
+.BR IEXTEN,
+.BR IGNCR
+and
+.BR ICRNL
+should be active in non-canonical mode, but under MINIX 3 they are.
+.SS "Terminal attributes"
+The attributes of a terminal, such as whether the mode should be canonical or
+non-canonical, are controlled by routines that use the
+.B termios
+structure as defined in
+.BR <termios.h> :
+.PP
+.RS
+.nf
+.ta +4n +10n +15n
+struct termios {
+	tcflag_t	c_iflag;	/* input modes */
+	tcflag_t	c_oflag;	/* output modes */
+	tcflag_t	c_cflag;	/* control modes */
+	tcflag_t	c_lflag;	/* local modes */
+	speed_t	c_ispeed;	/* input speed */
+	speed_t	c_ospeed;	/* output speed */
+	cc_t	c_cc[NCCS];	/* control characters */
+};
+.fi
+.RE
+.PP
+The types
+.BR tcflag ,
+.B speed_t
+and
+.B cc_t
+are defined in
+.B <termios.h>
+as unsigned integral types.
+.SS "Input Modes"
+The
+.B c_iflag
+field contains the following single bit flags that control input processing:
+.TP 5
+.B ICRNL
+Map
+.B CR
+to
+.B NL
+on input.
+.TP
+.B IGNCR
+Ignore
+.B CR
+on input.  This flag overrides
+.BR ICRNL .
+.TP
+.B INLCR
+Map
+.B NL
+to
+.B CR
+on input.  This is done after the
+.B IGNCR
+check.
+.TP
+.B IXON
+Enable start/stop output control.
+.TP
+.B IXOFF
+Enable start/stop input control.  (Not implemented.)
+.TP
+.B IXANY
+Allow any character to restart output.  (MINIX 3 specific.)
+.TP
+.B ISTRIP
+Strip characters to seven bits.
+.TP
+.B IGNPAR
+Ignore characters with parity errors.  (Not implemented.)
+.TP
+.B INPCK
+Enable input parity checking.  (Not implemented.)
+.TP
+.B PARMRK
+Mark parity errors by preceding the faulty character with '\e377', '\e0'.
+The character '\e377' is preceded by another '\e377' to avoid ambiguity.
+(Not implemented.)
+.TP
+.B BRKINT
+Send the signal
+.B SIGINT
+to the terminal process group when receiving a break condition.  (Not
+implemented.)
+.TP
+.B IGNBRK
+Ignore break condition.  If neither
+.B BRKINT
+or
+.B IGNBRK
+is set a break is input as a single '\e0', or if
+.B PARMRK
+is set as '\e377', '\e0', '\e0'.
+(Breaks are always ignored.)
+.SS "Output Modes"
+The
+.B c_oflag
+field contains the following single bit flags that control output processing:
+.TP
+.B OPOST
+Perform output processing.  This flag is the "main switch" on output
+processing.  All other flags are MINIX 3 specific.
+.TP
+.B ONLCR
+Transform an
+.B NL
+to a
+.B CR NL
+sequence on output.  Note that a key labeled "RETURN" or "ENTER" usually
+sends a
+.BR CR .
+In line oriented mode this is normally transformed into
+.B NL
+by
+.BR ICRNL .
+.B NL
+is the normal UNIX line delimiter ('\en').  On output an
+.B NL
+is transformed into the
+.B CR NL
+sequence that is necessary to reach the first column of the next line.
+(This is a common output processing function for UNIX-like systems, but not
+always separately switchable by an
+.B ONLCR
+flag.)
+.TP
+.B XTABS
+Transform a
+.B TAB
+into the number of spaces necessary to reach a column position that is a
+multiple of eight.
+.TP
+.B ONOEOT
+Discard
+.B EOT
+(^D) characters.  (Minix-vmd only.)
+.SS "Control Modes"
+The
+.B c_cflag
+field contains the following single bit flags and bit field for basic
+hardware control:
+.TP
+.B CLOCAL
+Ignore modem status lines.
+.TP
+.B CREAD
+Enable receiver.  (The receiver is always enabled.)
+.TP
+.B CSIZE
+Number of bits per byte.
+.B CSIZE
+masks off the values
+.BR CS5 ,
+.BR CS6 ,
+.BR CS7
+and
+.BR CS8
+that indicate that 5, 6, 7 or 8 bits are used.
+.TP
+.B CSTOPB
+Send two stop bits instead of one.  Two stop bits are normally used at 110
+baud or less.
+.TP
+.B PARENB
+Enable parity generation.
+.TP
+.B PARODD
+Generate odd parity if parity is generated, otherwise even parity.
+.TP
+.B HUPCL
+Drop the modem control lines on the last close of the terminal line.  (Not
+implemented.)
+.SS "Local Modes"
+The
+.B c_lflag
+field contains the following single bit flags that control various functions:
+.TP
+.B ECHO
+Enable echoing of input characters.  Most input characters are echoed as
+they are.  Control characters are echoed as 
+.BI "^" X
+where
+.I X
+is the letter used to say that the control character is
+.BI CTRL\- X\fR.
+The
+.BR CR ,
+.BR NL
+and
+.BR TAB
+characters are echoed with their normal effect unless they are escaped by
+.BR LNEXT .
+.TP
+.B ECHOE
+If
+.B ICANON
+and
+.B ECHO
+are set then echo
+.B ERASE
+and
+.B KILL
+as one or more backspace-space-backspace sequences to wipe out the last
+character or the entire line, otherwise they are echoed as they are.
+.TP
+.B ECHOK
+If
+.B ICANON
+and
+.B ECHO
+are set and
+.B ECHOE
+is not set then output an
+.B NL
+after the
+.B KILL
+character.  (For hardcopy terminals it is best to unset
+.B ECHOE
+and to set
+.BR ECHOK .)
+.TP
+.B ECHONL
+Echo
+.B NL
+even if
+.B ECHO
+is not set, but
+.B ICANON
+is set.
+.TP
+.B ICANON
+Canonical input.  This enables line oriented input and erase and kill
+processing.
+.TP
+.B IEXTEN
+Enable implementation defined input extensions.
+.TP
+.B ISIG
+Enable the signal characters
+.BR INTR ,
+.BR QUIT
+and
+.BR SUSP .
+.TP
+.B NOFLSH
+Disable the flushing of the input and output queues that is normally done if
+a signal is sent.
+.TP
+.B TOSTOP
+Send a
+.B SIGTTOU
+signal if job control is implemented and a background process tries to
+write.  (MINIX 3 has no job control.)
+.SS "Input and output speed"
+The input and output speed are encoded into the
+.B c_ispeed
+and
+.B c_ospeed
+fields.
+.B <termios.h>
+defines the symbols
+.BR B0 ,
+.BR B50 ,
+.BR B75 ,
+.BR B110 ,
+.BR B134 ,
+.BR B150 ,
+.BR B200 ,
+.BR B300 ,
+.BR B600 ,
+.BR B1200 ,
+.BR B1800 ,
+.BR B2400 ,
+.BR B4800 ,
+.BR B9600 ,
+.BR B19200 ,
+.BR B38400 ,
+.BR B57600
+and
+.BR B115200
+as values used to indicate the given baud rates.  The zero baud rate,
+.BR B0 ,
+if used for the input speed causes the input speed to be equal to the
+output speed.  Setting the output speed to zero hangs up the line.  One
+should use the functions
+.BR cfgetispeed() ,
+.BR cfgetospeed() ,
+.BR cfsetispeed()
+and
+.BR cfsetospeed()
+to get or set a speed, because the
+.B c_ispeed
+and
+.B c_ospeed
+fields may not be visible under other implementations.  (The
+.B c_ispeed
+and
+.B c_ospeed
+fields and the
+.B B57600
+and
+.B B115200
+symbols are MINIX 3 specific.)
+.SS "Special characters"
+The
+.B c_cc
+array contains the special characters that can be modified.  The array has
+length
+.B NCCS
+and is subscripted by the symbols
+.BR VEOF ,
+.BR VEOL ,
+.BR VERASE ,
+.BR VINTR ,
+.BR VKILL ,
+.BR VMIN ,
+.BR VQUIT ,
+.BR VTIME ,
+.BR VSUSP ,
+.BR VSTART ,
+.BR VSTOP ,
+.BR VREPRINT ,
+.BR VLNEXT
+and
+.BR VDISCARD .
+All these symbols are defined in
+.BR <termios.h> .
+Some implementations may give the same values to the
+.B VMIN
+and
+.B VTIME
+subscripts and the
+.B VEOF
+and
+.B VEOL
+subscripts respectively, and may ignore changes to
+.B START
+and
+.BR STOP .
+(Under MINIX 3 all special characters have their own
+.I c_cc
+slot and can all be modified.)
+.SS "Raw I/O Parameters"
+The
+.B MIN
+and
+.B TIME
+parameters can be used to adjust a raw connection to bursty input.
+.B MIN
+represents a minimum number of bytes that must be received before a read
+call returns.
+.B TIME
+is a timer of 0.1 second granularity that can be used to time out a read.
+Setting either of these parameters to zero has special meaning, which leads
+to the following four possibilities:
+.TP 5
+.B "MIN > 0, TIME > 0"
+.B TIME
+is an inter-byte timer that is started (and restarted) when a byte is
+received.  A read succeeds when either the minimum number of characters
+is received or the timer expires.  Note that the timer starts
+.B after
+the first character, so the read returns at least one byte.
+.TP
+.B "MIN > 0, TIME = 0"
+Now the timer is disabled, and a reader blocks indefinitely until at least
+.B MIN
+characters are received.
+.TP
+.B "MIN = 0, TIME > 0"
+.B TIME
+is now a read timer that is started when a read is executed.  The read will
+return if the read timer expires or if at least one byte is input.  (Note
+that a value of zero may be returned to the reader.)
+.TP
+.B "MIN = 0, TIME = 0"
+The bytes currently available are returned.  Zero is returned if no bytes
+are available.
+.SS "User Level Functions"
+Termios attributes are set or examined, and special functions can be
+performed by using the functions described in
+.BR termios (3).
+.SS "Session Leaders and Process Groups"
+With the use of the
+.B setsid()
+function can a process become a session leader.  A session leader forms a
+process group with a process group id equal to the process id of the session
+leader.  If a session leader opens a terminal device file then this terminal
+becomes the controlling tty of the session leader.  Unless the terminal is
+already the controlling tty of another process, or unless the
+.B O_NOCTTY
+flag is used to prevent the allocation of a controlling tty.  The process
+group of the session leader is now remembered as the terminal process group
+for signals sent by the terminal driver.  All the children and grandchildren
+of the session leader inherit the controlling terminal and process group
+until they themselves use
+.BR setsid() .
+.PP
+The controlling tty becomes inaccessible to the children of the session
+leader when the session leader exits, and a hangup signal is sent to all
+the members of the process group.  The input and output queues are flushed
+on the last close of a terminal and all attributes are reset to the default
+state.
+.PP
+A special device
+.B /dev/tty
+is a synonym for the controlling tty of a process.  It allows a process to
+reach the terminal even when standard input, output and error are
+redirected.  Opening this device can also be used as a test to see if a
+process has a controlling tty or not.
+.PP
+For MINIX 3 a special write-only device
+.B /dev/log
+exists for processes that want to write messages to the system console.
+Unlike the console this device is still accessible when a session leader
+exits.
+.PP
+Minix-vmd also has a
+.B /dev/log
+device, but this device is read-write.  All messages written to the log
+device or to the console when X11 is active can be read from
+.BR /dev/log .
+The system tries to preserve the log buffer over a reboot so that panic
+messages reappear in the log if the system happens to crash.
+.SS "Pseudo Terminals"
+Pseudo ttys allow a process such as a remote login daemon to set up a
+terminal for a remote login session.  The login session uses a device like
+.B /dev/ttyp0
+for input and output, and the remote login daemon uses the device
+.B /dev/ptyp0
+to supply input to or take output from the login session and transfer this
+to or from the originating system.  So the character flow may be:  Local
+user input sent to the remote system is written to
+.B /dev/ptyp0
+by the remote login daemon, undergoes input processing and appears on
+.B /dev/ttyp0
+as input to the login session.  Output from the login session to
+.B /dev/ttyp0
+undergoes output processing, is read from
+.B /dev/ptyp0
+by the remote login daemon and is send over to the local system to be
+displayed for the user.  (So there are only four data streams to worry about
+in a pseudo terminal.)
+.PP
+A pseudo terminal can be allocated by trying to open all the controlling
+devices
+.BI /dev/pty nn
+one by one until it succeeds.  Further opens will fail once a pty is open.
+The process should now fork, the child should become session leader, open
+the tty side of the pty and start a login session.
+.PP
+If the tty side is eventually closed down then reads from the pty side will
+return zero and writes return \-1 with
+.B errno
+set to
+.BR EIO .
+If the pty side is closed first then a
+.B SIGHUP
+signal is sent to the session leader and further reads from the tty side
+return zero and writes return \-1 with
+.B errno
+set to
+.BR EIO .
+(Special note:  A line erase may cause up to three times the size of the
+tty input queue to be sent to the pty reader as backspace overstrikes.  Some
+of this output may get lost if the pty reader cannot accept it all at once
+in a single read call.)
+.SS "Backwards compatibility"
+The
+.BR TIOCGETP ,
+.BR TIOCSETP ,
+.BR TIOCGETC
+and
+.BR TIOCSETC
+ioctl functions that are used by the old
+.B sgtty
+terminal interface are still supported by the terminal driver by emulation.
+Note that these old functions cannot control all termios attributes, so the
+terminal must be in a relatively sane state to avoid problems.
+.SH FILES
+The list below shows all devices that MINIX 3 and Minix-vmd have.  Not all of
+these devices are configured in by default, as indicated by the numbers
+(i/j/k, l/m/n) that tell the minimum, default and maximum possible number of
+these devices for MINIX 3 (i/j/k) and Minix-vmd (l/m/n).
+.TP 20
+.B /dev/console
+System console.
+.TP
+.B /dev/ttyc[1-7]
+Virtual consoles.  (0/1/7, 0/1/7)
+.TP
+.BR /dev/log
+Console log device.
+.TP
+.B /dev/tty0[0-3]
+Serial lines.  (0/2/2, 4/4/4)
+.TP
+.B /dev/tty[p-w][0-f]
+Pseudo ttys.  (0/0/64, 1/32/128)
+.TP
+.B /dev/pty[p-w][0-f]
+Associated pseudo tty controllers.
+.SH "SEE ALSO"
+.BR stty (1),
+.BR termios (3),
+.BR setsid (2),
+.BR read (2),
+.BR write (2).
+.SH BUGS
+A fair number of flags are not implemented under MINIX 3 (yet).  Luckily they
+are very limited utility and only apply to RS-232, not to the user interface.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man5/TZ.5
===================================================================
--- /trunk/minix/man/man5/TZ.5	(revision 9)
+++ /trunk/minix/man/man5/TZ.5	(revision 9)
@@ -0,0 +1,138 @@
+.TH TZ 5
+.SH NAME
+TZ \- Time zone environment variable
+.SH SYNOPSIS
+\fBTZ=\fIzone\fR[\fB\-\fR]\fIoffset\fR[\fIdst\fR[\fIoffset\fR][\fB,\fIstart\fR[\fB/\fItime\fR]\fB,\fIend\fR[\fB/\fItime\fR]]]
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+The
+.B TZ
+environment variable tells functions such as the
+.BR ctime (3)
+family and programs like
+.B date
+what the time zone and daylight saving rule is.  The value of
+.B TZ
+has the \s-2POSIX\s+2 standardized form shown in the synopsis.  This form
+specifies the zone names, offsets from GMT, and daylight saving changeover
+times for at least the current year.
+.TP
+.I zone
+A three or more letter name for the time zone in normal (winter) time.
+.TP
+.BI [\-] offset
+A signed time telling the offset of the time zone westwards from Greenwich.
+The time has the form
+.I hh[:mm[:ss]]
+with a one of two digit hour, and optional two digit minutes and seconds.
+.TP
+.I dst
+The name of the time zone when daylight saving is in effect.  It may
+be followed by an offset telling how big the clock correction is other than
+the default of 1 hour.
+.TP
+\fIstart\fR/\fItime\fR,\fIend\fR/\fItime\fR
+Specifies the start and end of the daylight saving period.  The
+.I start
+and
+.I end
+fields indicate on what day the changeover occurs.  They must be in one of
+the following formats:
+.SP
+.ta +5
+.in +5
+.ti -5
+\fBJ\fIn\fR	The Julian day
+.I n
+(1 <=
+.I n
+<= 365) ignoring leap days, i.e. there is no February 29.
+.SP
+.ti -5
+\fIn\fR	The zero-based Julian day
+(0 <=
+.I n
+<= 365).  Leap days are not ignored.
+.SP
+.ti -5
+.BI M m . n . d
+.br
+This indicates month
+.IR m ,
+the
+.IR n -th
+occurrence of day
+.I d
+(1 <=
+.I m
+<= 12, 1 <=
+.I n
+<= 5, 0 <=
+.I d
+<= 6, 0=Sunday).  The 5-th occurrence means the last occurrence of that day
+in a month.  So
+.B M4.1.0
+is the first Sunday in April,
+.B M9.5.0
+is the last Sunday in September.
+.in -5
+.SP
+The
+.I time
+field indicates the time the changeover occurs on the given day.
+.SH EXAMPLES
+Greenwich Mean Time:
+.PP
+.RS
+.B TZ=GMT0
+.RE
+.PP
+Central European Time, 1 hour east from Greenwich, daylight saving starts on
+the last Sunday in March at 2 AM and ends on the last Sunday in October
+at 3 AM:
+.PP
+.RS
+.B TZ='CET\-1CEST,M3.5.0/2,M10.5.0/3'
+.RE
+.PP
+British time, daylight saving starts and ends at the same moment as CET,
+but in an earlier time zone:
+.PP
+.RS
+.B TZ=GMT0BST,M3.5.0/1,M10.5.0/2
+.RE
+.PP
+The eastern european time zones also have the changeovers at the same
+absolute time as British time and CET.
+.PP
+U.S. Eastern Standard Time, 5 hours west from Greenwich, daylight saving
+starts on the first Sunday in April at 2 AM and ends on the last Sunday in
+October at 2 AM:
+.PP
+.RS
+.B TZ=EST5EDT,M4.1.0/2,M10.5.0/2
+.RE
+.PP
+It shouldn't surprise you that daylight saving in New Zealand is observed
+in the months opposite from the previous examples.  It starts on the first
+Sunday in October at 2 AM and ends on the third Sunday in March at 3 AM:
+.PP
+.RS
+.B TZ=NZST\-12NZDT,M10.1.0/2,M3.3.0/3
+.RE
+.SH "SEE ALSO"
+.BR readclock (8),
+.BR date (1).
+.SH BUGS
+You may have noticed that many fields are optional.  Do no omit them,
+because the defaults are bogus.  If you need daylight saving then fully
+specify the changeovers.
+.PP
+West is negative, east is positive, ask any sailor.
+.PP
+Next year's time zone and daylight saving time are determined by politicians.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man5/configfile.5
===================================================================
--- /trunk/minix/man/man5/configfile.5	(revision 9)
+++ /trunk/minix/man/man5/configfile.5	(revision 9)
@@ -0,0 +1,83 @@
+.TH CONFIGFILE 5
+.SH NAME
+configfile \- generic configuration file format
+.SH SYNOPSIS
+.B */etc/*.conf
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+The syntax of the generic configuration file format is as follows:
+.PP
+.RS
+.nf
+.ta +16n
+configfile:	empty
+.ta +8n +8n
+	|	configline configfile
+	;
+
+.ta +16n
+configline:	wordlist '\fB;\fR'
+.ta +8n +8n
+	|	\fBinclude\fR string '\fB;\fR'
+	;
+
+.ta +16n
+wordlist:	empty
+.ta +8n +8n
+	|	word wordlist
+	|	string wordlist
+	|	'\fB{\fR' configfile '\fB}\fR' wordlist
+	;
+
+empty:	;
+.fi
+.RE
+.PP
+A word is a sequence of letters, numbers, and characters from the set
+.BR "!#$%&*+-./<=>?[\e]^_|~" .
+A backslash
+.RB ( \e )
+may be followed by a character in the set
+.B abefnrstv
+to form a BEL, BS, ESC, FF, NL, CR, SP, TAB, or VT character.  Followed by
+up to three octal digits a character of that value is formed, and likewise
+for an
+.B x
+followed by up to two hexadecimal digits.  Any other character is left
+as-is.  A backslash followed by whitespace is completely removed from the
+input.  (This includes comments.)
+.PP
+A string is started by a single or double quote, a series of characters, and
+ended by the same type of quote it started with.  Any character or
+escape with
+.B \e
+may be found in a string.  Strings may not span lines.
+.PP
+Tokens are separated by whitespace, being the usual whitespace characters
+and comments.  A comment starts with the
+.B #
+character, and ends at a newline.
+.PP
+The special word
+.B include
+tells that the file mentioned in the following string must be read and
+included at that point.  The file is found relative to the directory the
+current configuration file is found in, unless its name starts with a
+.BR / .
+A file that doesn't exist is seen as empty.
+.PP
+A generic configuration file can be read with the functions described in
+.BR configfile (3).
+.SH EXAMPLES
+Have a look at
+.BR /etc/dhcp.conf .
+.SH "SEE ALSO"
+.BR configfile (3).
+.SH NOTES
+Inspired by the configuration file of Paul Vixie's
+.BR bind .
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man5/crontab.5
===================================================================
--- /trunk/minix/man/man5/crontab.5	(revision 9)
+++ /trunk/minix/man/man5/crontab.5	(revision 9)
@@ -0,0 +1,137 @@
+.TH CRONTAB 5
+.SH NAME
+crontab \- table of jobs to be performed by cron
+.SH SYNOPSIS
+.nf
+.ft B
+/usr/lib/crontab
+/usr/local/lib/crontab
+/var/lib/crontab
+/var/opt/\fIname\fP/lib/crontab\ \ \fR(Minix-vmd only)\fB
+/usr/spool/crontabs/\fIuser\fP
+.ft R
+.fi
+.SH DESCRIPTION
+The
+.BR cron (8)
+daemon runs jobs at regular intervals.  These jobs are listed in
+.B crontab
+files.  The format of entries in a crontab file are five fields of numbers
+specifying the minute (0\-59), hour (0\-23), day of the month (1\-31), month
+(1\-12), and day of the week (0\-6 with 0 = Sunday) that a task must be
+executed.  The task to be executed follows as a shell command.
+.PP
+The time numbers can be given as a comma separated list of simple numbers,
+ranges ("2\-5" is the same as "2,3,4,5"), and repeats ("2:5" means
+"2,7,12,17,22" in the hour field).  A repeat is cyclic affair, i.e. 2:5
+and 12:5 are the same thing.  A single "*" can be used in a field to
+indicate all valid numbers in that field, so it translates to "always".  In
+the minute field you can use "?" for the current minute that the crontab
+file is loaded.  It can be used in a repeat, i.e. "?:10" for every 10
+minutes.  This keeps machines with identical crontabs from executing tasks
+at exactly the same time, causing a burst of traffic if anything is done
+over a network.
+.PP
+If a given time is valid in all five fields then a command is executed.
+Here are a few examples that illustrate the possibilities:
+.PP
+.if t .RS
+.if t .ft C
+.nf
+# min hour mday mon wday command
+   ?   3    *    *   *   /usr/etc/daily  # Daily system cleanup
+   0   *    *    *   *   date            # Print date on the hour
+  30   4    *    *  2\-6  /var/etc/backup # After workdays on 4:30
+   0   9   25   12   *   \-u ast sing     # Andy sings on Xmas morning
+   0   0   13    *   5   echo Beware!    # For the superstitious
+.fi
+.if t .ft P
+.if t .RE
+.PP
+The command may optionally be prefixed by
+.BI \-u " user"
+to specify under which user the command should be run.  Commands from
+crontabs in the spool directory are always run under the id of the crontab's
+owner, the
+.B \-u
+flag is ignored.
+.PP
+A command can be placed on the same line as the time fields, or on the next
+line indented by one TAB character.  (A TAB, not eight spaces.)  More TAB
+indented lines can be added for a multiline command.  The tabs are removed
+from the command when passed to the shell.  If a command is put on the same
+line as the time fields then percent characters are changed into newlines,
+this is not done for a TAB indented command.  The following three entries
+give the same output:
+.PP
+.RS
+.if t .ft C
+.nf
+.ta +8n
+0 12  *  *  *   echo 'Hello'; echo '  World!'
+#1
+0 12  *  *  *   echo 'Hello%  World!'  #2
+0 12  *  *  *        #3
+	cat <<EOF    #4
+	Hello
+	\&  World!
+	EOF
+.fi
+.if t .ft P
+.RE
+.PP
+Comments start with a "#" character and continue until end of line.  They,
+excess whitespace, and empty lines are ignored.  Of the comments in the
+example above #1 and #3 are ignored by
+.BR cron ,
+but #2 and #4 are not recognized as comments, but are seen as part of a
+command and are passed to the shell who then happens to ignore them.  There
+is no interpretation of command characters other than the percent in a
+oneliner.  The time fields must all be on the same line.
+.SH FILES
+.TP 25n
+.B /usr/lib/crontab
+Main MINIX 3 crontab file.
+.TP
+.B /usr/local/lib/crontab
+Local jobs for all systems in an organization.
+.TP
+.B /var/lib/crontab
+System specific jobs.
+.TP
+.B /var/opt/\fIname\fP/lib/crontab
+Per package jobs for Minix-vmd.
+.TP
+.B /usr/lib/packages
+List of installed packages.
+.TP
+.B /usr/spool/crontabs/\fIuser\fP
+Per user jobs.
+.SH "SEE ALSO"
+.BR crontab (1),
+.BR cron (8).
+.SH NOTES
+The "?" in the minute field, the repeat field (e.g. "2:5"), TAB indented
+multiline commands and the
+.B \-u
+option are unique to this cron implementation.  This doesn't mean you
+shouldn't use these features, but just that you should be aware of the
+differences with other systems.  You are even advised to use these features
+and avoid the percent hack for multiline commands.
+.PP
+Other crons allow one to specify input to a job in some way, something this
+cron can't.  Simply use the << shell feature to do that.  Other crons often
+choke on empty lines.
+.PP
+It is a common bug to use 0 for Sunday instead of 7.  This cron, like most
+other crons out there accepts this without comment.
+.PP
+A job is not reissued until a previous instance of it has exited.  The next
+time to execute is computed from the previous time it ran.  If job issuing
+lags behind on the system time then the next time to run it is computed from
+the current system time.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+
+.\"
+.\" $PchId: crontab.5,v 1.3 2000/07/17 18:53:05 philip Exp $
Index: /trunk/minix/man/man5/dhcp.conf.5
===================================================================
--- /trunk/minix/man/man5/dhcp.conf.5	(revision 9)
+++ /trunk/minix/man/man5/dhcp.conf.5	(revision 9)
@@ -0,0 +1,498 @@
+.TH DHCP.CONF 5
+.SH NAME
+dhcp.conf \- dynamic host configuration protocol configuration
+.SH SYNOPSIS
+.B /etc/dhcp.conf
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+The file
+.B /etc/dhcp.conf
+contains the configuration for the DHCP client/server program
+.BR dhcpd .
+This text is a long summation of all the elements that can be found in this
+configuration file.  For a more "just tell me what to do" approach see
+.BR boot (8).
+.PP
+The syntax used is that of the common configuration file described in
+.BR configfile (5).
+.PP
+To find information for a client we first need its IP address.  Occasionally
+this IP address is already known (the special "INFORM" query), but normally
+we have to make a first pass through the configuration file for a
+.B client
+entry.  If that fails then we use an IP address from the pool file.  If we
+now have an IP address then the real information gathering can begin.
+.PP
+The DHCP daemon reads the configuration file from beginning to end and
+gathers all information that matches, and information from all macros that
+are mentioned within the elements that match.  If we end up with DHCP
+information that includes at least a netmask definition, and is good for the
+network the request came in from, then it is returned to the client.  If a
+DHCP tag is specified twice then the last one wins.
+.PP
+In the description below we use [ and ] to denote optional things, and | to
+show a choice between two things.
+.PP
+Client IDs can be either ordinary Ethernet addresses, that are treated as a
+seven octet string (01 followed by the Ethernet address), or any random
+octet string in hexadecimal.
+.PP
+IP addresses can be simply that, or host names.  These host names are
+searched in
+.B /etc/hosts
+by
+.B dhcpd
+itself using a domain based prefix match, i.e. you can use "flotsam" for
+"flotsam.example.com", but not "alpha" for "alphabeta".  Once the program
+decides to be a server it will also look up names normally in the DNS.
+If a host has more than one IP address then the address on the network the
+query was seen on is used.
+.PP
+Case isn't important in the configuration file, "client", "CLIENT" and
+"ClIeNt" are all treated the same.
+.PP
+Some elements may optionally name a macro or a curly braces enclosed
+parameter list of more elements.  If the element matches then the data
+in the macro body or parameter list is gathered.
+.PP
+The following elements can be used:
+.PP
+.B client
+.I client-ID
+.RB [ ip #]
+.I host
+.RI [ macro |{ params }];
+.PP
+.RS
+Defines a client with a given client ID that is to have the IP address
+denoted by
+.I host .
+On the first pass only the client ID is matched looking for an IP address
+that lies on the network the request came in on.  On the
+information gathering pass both client ID and IP address must match.  If
+a machine has the same Ethernet address on two or more interfaces then the
+IP address given out is the one on the same network as the request came in
+on.  The optional interface name
+.RB ( ip #)
+must be used if the DHCP daemon is gathering data for itself at boot time
+to differentiate interfaces with the same ethernet addresses.  This is
+only necessary under Minix-vmd when ethernets on different VLANs share
+the same physical ethernet.  The interface name is only used for a machine's
+own networks, it ignored on entries for other hosts.
+.RE
+.PP
+.B class
+.IR class-name " ..."
+.IR macro |{ params };
+.PP
+.RS
+Includes the macro or parameters if one of the class names is matched.  A
+host normally includes a class ID in its request.  MINIX 3 and Minix-vmd
+use "Minix" as the class name.  For Windows the class ID starts with
+"MSFT", and Solaris' starts with "SUNW".
+(Use
+.B dhcpd \-d3
+to find out what the full IDs are exactly.)  The class names are matched if a
+.I class-name
+is a prefix of the class ID sent by the client.
+.RE
+.PP
+.B host
+.I host-spec
+.IR macro |{ params };
+.PP
+.RS
+Includes the macro or parameters if the IP address of the client matches the
+host specification.  This can either be an ordinary hostname, or a netblock
+in CIDR notation, e.g. 172.35.0.0/16.  The example includes all IP addresses
+whose top 16 bits are the same as the top 16 bits of 172.35.0.0.  Such a
+netblock automatically defines a netmask (255.255.0.0 in the example) if no
+netmask has been specified yet.
+.RE
+.PP
+.B interface
+.BR ip #
+.I host
+.RI [ macro |{ params }];
+.PP
+.RS
+Makes
+.B dhcpd
+set the IP address of interface
+.BR ip #
+(where # is a number) to the IP address denoted by
+.IR host .
+This element should only be used for interfaces that are not true Ethernets,
+and so do not have a unique Ethernet address that can be used for a client
+element.  If the machine has at least one true Ethernet then all interface
+elements should be added to the parameter list of a host or client element
+for that Ethernet interface.  This binds them to that machine and allows a
+single configuration file to be shared among machines.  Especially a server
+should never have "free" interface elements.  The macro or parameters are
+only evaluated if data is gathered for the given interface.  (Note that they
+will be hidden by a client element for another interface.)
+.RE
+.PP
+.B macro
+.IR macro-name ;
+.PP
+.RS
+Include the parameter list of the macro named
+.I macro-name
+defined elsewhere.  (This means that "host flotsam stuff" is just short
+for "host flotsam { macro stuff; }".)
+.RE
+.PP
+.B macro
+.I macro-name
+.RI { params };
+.PP
+.RS
+Defines a macro with the given parameter list.  Whenever the macro is used
+the parameter list is substituted instead.  A macro can not be defined
+within another parameter list.
+.RE
+.PP
+.B option
+.RB [ ip #]
+.B server
+.RB [ inform ];
+.br
+.B option
+.RB [ ip #]
+.B relay
+.IR host ;
+.br
+.B option
+.RB [ ip #]
+.BR possessive ;
+.br
+.B option
+.RB [ ip #]
+.B hostname
+.IR name ;
+.PP
+.RS
+Makes
+.B dhcpd
+set special options for the interface that it is gathering data for, or the
+interface denoted by the optional
+.BR ip #
+argument.  The options are:
+.SP
+.B server
+.RB [ inform ]
+.RS
+Be a DHCP server on the network connected to the interface.  Add the word
+.B inform
+if DHCPINFORM requests must be answered for hosts we don't have an address
+for.
+.RE
+.SP
+.B relay
+.I host
+.RS
+Be a DHCP relay to the indicated host.
+.RE
+.SP
+.B possessive
+.RS
+Do not disable the interface if the DHCP lease expires.  Useful if the
+DHCP server of the provider is unreliable, crashing a lot and causing the
+lease to expire.  (Think twice before turning this option on.  You have to
+be absolutely sure that it's the DHCP server that's the culprit and not
+a flaky network.  You don't want an IP address conflict to be your fault.)
+.RE
+.SP
+.B hostname
+.I name
+.RS
+Use the given name as our hostname in the DHCP queries.  Some sites key on
+that bit of information instead of a client ID.
+.RE
+.RE
+.PP
+.B tag
+.I number name type granularity
+.IR max ;
+.PP
+.RS
+Defines a DHCP tag for the given tag number and gives it a name.  The name can
+be used in the configuration file to set tag values when gathering data.
+The
+.I type
+field can be one of
+.BR ascii ,
+.BR boolean ,
+.BR ip ,
+.BR number
+or
+.BR octet
+to specify the type of the tag as a simple string, a boolean, an IP address,
+a number, or a string of octet values.
+The
+.I granularity
+field specifies that that number of items must be given or a multiple
+thereof, unless the type is a number, then it is the size of the number (1,
+2 or 4).
+The
+.I max
+field tells the maximum number of items that may be used with the tag, with
+0 meaning "unlimited".
+.SP
+Three tags, the ones that MINIX 3 really cares about, have been predefined,
+and there are also a few pseudotags predefined for the static fields in a
+DHCP packet that one may want to set:
+.SP
+.RS
+.nf
+tag ? siaddr ip 1 1;
+tag ? sname ascii 1 64;
+tag ? file ascii 1 128;
+tag 1 netmask ip 1 1;
+tag 3 gateway ip 1 0;
+tag 6 DNSserver ip 1 0;
+.fi
+.RE
+.SP
+The file
+.B /usr/etc/dhcptags.conf
+contains tag definitions for all standard DHCP tags.  It is wise to include
+this file at the top of any DHCP configuration file.
+.RE
+.PP
+.B no
+.IR tag-name ;
+.PP
+.RS
+Removes a tag with the given name from the data gathered at this point.
+Useful if one host is different from all others, for instance if it doesn't
+need a gateway definition, because it happens to be the gateway.
+.RE
+.PP
+.IR "ascii-tag string" ;
+.PP
+.RS
+Adds an ASCII tag to the gathered data.  The string can be a simple word, or
+a quoted string.
+.RE
+.PP
+.I boolean-tag
+.BR false | true ;
+.PP
+.RS
+Set a boolean tag to be false or true.  (Encoded as a octet of value 0 or 1.
+Note that if you prefer to use 0 or 1 instead of false or true then you can
+define a boolean tag as a size 1 number instead.)
+.RE
+.PP
+.IR "ip-tag host" " ...;"
+.PP
+.RS
+Sets a tag that needs one or more IP addresses.  The host names are
+translated as usual.  To make it easier to specify netmasks one can use a
+slash followed by a number, e.g.
+.BR "netmask /27" ,
+which is a handy alternative for
+.BR "netmask 255.255.255.224" .
+.RE
+.PP
+.IR "number-tag number" " ...;"
+.PP
+.RS
+Set a number tag.
+.RE
+.PP
+.IR "octet-tag hexdigits" ;
+.PP
+.RS
+Set an octet string tag.
+.I Hexdigits
+is a series of hexadecimal digits that are two by two used to set the
+octets.
+.RE
+.PP
+.SH EXAMPLE
+As an example the DHCP configuration used by the author of this document is
+included.  His network at home consists of a number of PCs, an ISDN router
+named rhone and a PC named saone serving as router/tunnel to/via a cable
+ISP.  Both the rhone and the saone connect the home net to the network of
+the Vrije Universiteit, but the rhone is only active if the cable doesn't
+work.
+.PP
+The saone is a DHCP server, and one of the ordinary PCs is a backup DHCP
+server.  Both use the same configuration file, which is added below, with
+extra commentary introduced by
+.B ##
+at a deeper indent level:
+.RS
+.de xS	\" Example start
+.sp
+.nf
+.ft C
+..
+.de xE	\" Example end
+.fi
+.ft R
+..
+.de cS	\" Commentary start
+.sp
+.in +12m
+.ti -\w'## 'u
+##\ \c
+..
+.de cE	\" Commentary end
+.in -12m
+..
+.xS
+.ta +8m +16m
+include /usr/etc/dhcptags.conf;
+.xE
+.cS
+With the help of the tag definitions we can use tags like "DHCPlease".
+.cE
+.xS
+host 130.37.102.64/27 {
+	DNSserver saone darask;
+	host 130.37.102.88/29 { DHCPlease 259200; }
+};
+.xE
+.cS
+This defines the network 130.37.102.64/27, with netmask 255.255.255.224
+(implicit from the network definition).  The DNS servers for this net are
+saone and darask.  A smaller subrange of addresses is used as an address
+pool on the saone, so a lease of 259200 seconds (3 days) is defined.  The
+netmask is still /27, as set by the outer network definition.
+.cE
+.xS
+host 130.37.102.248/30 {};
+.xE
+.cS
+A network of two addresses for routing tests.
+.cE
+.xS
+host saone {
+	option server;
+	option ip1 possessive;
+	interface ip2 saone-net2;
+	DNSserver 130.37.24.3 130.37.24.6;
+};
+.xE
+.cS
+With the network definitions done we turn our attention to the hosts.  Saone
+is a DHCP server on its main interface.  The second interface
+.RB ( ip1 )
+is connected to the cable modem.  It gets its address from the cableco's
+DHCP server, and if that server decides to go deaf then the saone keeps
+the interface up ("possessive") even if the lease expires.  The pseudo IP
+interface
+.B ip2
+is set to the IP address of
+.BR saone-net2 ,
+one side of the encrypted tunnel over the cable to a Minix-vmd box at the VU.
+The DNS servers specified override the default setting for the network, naming
+two external servers at the VU that know the world.
+.cE
+.xS
+host darask {
+	option server;
+	DNSserver saone;
+	class MINIX 3 { DNSserver saone 130.37.24.3 130.37.24.6; };
+};
+.xE
+.cS
+The darask is also a server, the backup for saone on the odd chance that it
+is unavailable.  It uses saone and the external name servers, but only
+when it is running MINIX 3.  When running Windows it only uses saone.
+.cE
+.xS
+.ta +32m +16m
+client 0:1:1b:a:68:ce	darask;	# NE2000
+client 0:1:1b:a:77:23	burask;	# NE2000
+#lient 0:0:c0:b0:da:64	burask;	# WD8013EWC
+client 8:0:5a:38:b2:f	finiah;	# PCMCIA NE2000
+client 0:0:c0:3a:12:10	bardelask;	# WD8003
+#lient 2:60:8c:ab:8a:6d	bardelask;	# 3C503
+client 0:a0:c5:20:9:6d	rhone;
+client 0:1:1b:a:4c:3b	saone;	# NE2000
+#lient 0:0:c0:fb:2:6a	saone-net1;	# WD8013EWC
+.xE
+.cS
+Lastly the ethernet addresses of all the hosts are listed, so that they can
+be translated to IP addresses.  The lines that are commented out are for
+extra network cards that are currently unused.  The last is used to connect
+to the cable modem, so it's only here because it's nice to have the ethernet
+address written down somewhere.
+.cE
+.RE
+.PP
+The host names shown above are translated by DHCP using this
+.BR /etc/hosts :
+.RS
+.xS
+.ta +\w'130.37.102.249mm'u
+604800	%ttl
+2419200	%stale
+
+130.37.102.65	darask.kjb.upwind.org
+130.37.102.66	burask.kjb.upwind.org
+130.37.102.67	finiah.kjb.upwind.org
+130.37.102.68	bardelask.kjb.upwind.org
+130.37.102.69	roniah.kjb.upwind.org
+
+130.37.102.70	saone.kjb.upwind.org
+130.37.102.2	saone-net2.kjb.upwind.org
+
+130.37.102.88	rhone.kjb.upwind.org
+130.37.102.89	dyn89.kjb.upwind.org
+130.37.102.90	dyn90.kjb.upwind.org
+130.37.102.91	dyn91.kjb.upwind.org
+130.37.102.92	dyn92.kjb.upwind.org
+130.37.102.93	dyn93.kjb.upwind.org
+130.37.102.94	dyn94.kjb.upwind.org
+
+130.37.102.249	tst1.kjb.upwind.org
+130.37.102.250	tst2.kjb.upwind.org
+.xE
+.RE
+.SH FILES
+.TP
+.B /usr/etc/dhcptags.conf
+A supplied list of standard tag definitions as per RFC-1533.  (Well, the
+tag numbers and their meaning are standard, the names are made up.)
+.SH "SEE ALSO"
+.BR RFC-2131 ,
+.BR RFC-1533 ,
+.BR configfile (5),
+.BR hosts (5),
+.BR boot (8),
+.BR dhcpd (8).
+.SH NOTES
+The amount of memory
+.B dhcpd
+needs increases with the size of configuration file.  MINIX 3 can
+handle
+.B dhcptags.conf
+and a modest sized
+.BR dhcp.conf .
+You have to increase the stack size to accommodate more.  (No problem under
+Minix-vmd, of course.)
+.SH NOTES
+Items that are only necessary for a certain host should only be specified
+for that host.  Items for a whole network are best added to a netblock
+specification.  Use class elements for a certain type of host, and macros
+for exceptions.  Try to limit information as much as possibly to those hosts
+that need it.  (Don't go overboard.  A MINIX 3 machine won't be bothered by a
+few NetBIOS tags.)
+.PP
+DHCPINFORM requests should always be answered when being a server, but
+J. Random Sysadmin trying to diagnose problems doesn't like it when little
+MINIX 3 machines show up in a packet trace unexpectedly.  It's best to be
+inconspicuous on a network you don't own.
+.SH BUGS
+There are a few too many subtle mistakes one can make.
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man5/dir.5
===================================================================
--- /trunk/minix/man/man5/dir.5	(revision 9)
+++ /trunk/minix/man/man5/dir.5	(revision 9)
@@ -0,0 +1,43 @@
+.TH DIR 5
+.SH NAME
+dir \- directory layout
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <sys/dir.h>
+.SH DESCRIPTION
+The directories of the V1 and V2 file systems are arrays of the
+following structure defined in <sys/dir.h>:
+.PP
+.nf
+.ta +5n +15n +15n
+struct direct {
+	ino_t	d_ino;	/* I-node number */
+	char	d_name[14];	/* Name of up to 14 characters */
+};
+.fi
+.DT
+.PP
+The
+.B d_ino
+field is the inode number of the file named by
+.BR d_name .
+.B D_ino
+is zero if the directory slot isn't allocated.  This number is the same as
+.B st_ino
+returned by
+.BR stat (2)
+unless the entry is mounted on.
+.B D_name
+is the name of up to 14 characters, null-terminated only if less then 14
+in length.  Any character other than null or '\fB/\fP' is allowed.
+.PP
+See
+.BR directory (3)
+for a portable way to access directories, MINIX 3 is probably the last system
+with these old V7 format directories.
+.SH "SEE ALSO"
+.BR directory (3).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man5/ethers.5
===================================================================
--- /trunk/minix/man/man5/ethers.5	(revision 9)
+++ /trunk/minix/man/man5/ethers.5	(revision 9)
@@ -0,0 +1,36 @@
+.TH ETHERS 5
+.SH NAME
+ethers \- ethernet address to hostname database
+.SH SYNOPSIS
+.B /etc/ethers
+.SH DESCRIPTION
+The ethers database translates ethernet addresses to hostnames for use by
+the RARP daemon (see
+.BR rarpd (8).)
+.B /etc/ethers
+may look like this:
+.PP
+.RS
+.ta +20n +10n
+0:0:c0:a:77:23	flotsam
+.br
+0:0:c0:a:68:ce	jetsam
+.RE
+.PP
+The six octet ethernet numbers must be entered as shown above, the hex
+constants must use lowercase letters and may not have leading zeros.
+Comments are marked with '#'.
+.PP
+See
+.BR rarpd (8)
+on why you shouldn't list Sun hosts in this file.
+.SH FILES
+.TP 15n
+/etc/ethers
+Ethernet addresses database.
+.SH "SEE ALSO"
+.BR hosts (5),
+.BR rarpd (8),
+.BR boot (8).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man5/fstab.5
===================================================================
--- /trunk/minix/man/man5/fstab.5	(revision 9)
+++ /trunk/minix/man/man5/fstab.5	(revision 9)
@@ -0,0 +1,87 @@
+.TH FSTAB 5
+.SH NAME
+fstab, mtab \- list of file systems to mount, mounted file system table.
+.SH SYNOPSIS
+.B /etc/fstab
+.sp
+.B /etc/mtab
+.SH DESCRIPTION
+.B /etc/fstab
+is a table of file system to mount at boot time,
+.B /etc/mtab
+is a table of currently mounted file systems as maintained by
+.B mount
+and
+.BR umount .
+.PP
+.B /etc/fstab
+is not read by
+.B mount
+as it should be.  It is instead a simple shell script listing the two or
+three devices that MINIX 3 needs to operate:  The device names of the root
+file system, the swap file system (optional), and the file system for
+.BR /usr .
+.PP
+.B /etc/mtab
+contains lines of four fields.  The layout is:
+.sp
+.RS
+.nf
+.ft B
+.ta +10n +13n +8n
+device	directory	type	options
+.ft P
+.fi
+.RE
+.PP
+These fields may be explained as follows:
+.sp
+.B device
+.br
+.RS
+A block special device.
+.RE
+.sp
+.B directory
+.br
+.RS
+Mount point.
+.RE
+.sp
+.B type
+.br
+.RS
+Either
+.BR 1 ,
+.BR 2 ,
+or
+.BR swap ,
+indicating a V1 or a V2 file system, or swap space.
+.RE
+.sp
+.B options
+.br
+.RS
+Either
+.BR ro ,
+or
+.BR rw ,
+indicating a read-only or read-write mounted file system.
+.RE
+.SH FILES
+.TP 15n
+.B /etc/fstab
+Shell script naming three important file systems.
+.TP
+.B /etc/mtab
+List of mounted file systems.
+.SH "SEE ALSO"
+.BR printroot (8),
+.BR mount (1),
+.BR fsck (1),
+.BR mkfs (1).
+.SH BUGS
+.B /etc/fstab
+is a joke.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man5/hosts.5
===================================================================
--- /trunk/minix/man/man5/hosts.5	(revision 9)
+++ /trunk/minix/man/man5/hosts.5	(revision 9)
@@ -0,0 +1,57 @@
+.TH HOSTS 5
+.SH NAME
+hosts \- hostname to IP address database
+.SH SYNOPSIS
+.B /etc/hosts
+.SH DESCRIPTION
+The hosts database lists the IP addresses and the hostnames that translate
+to these IP addresses.  It is used by
+.BR nonamed (8)
+in a network without name servers.  A simple
+.B /etc/hosts
+may look like this:
+.PP
+.RS
+.ta +15n
+.nf
+10.0.0.1	flotsam
+10.0.0.2	jetsam
+.fi
+.RE
+.PP
+These two entries give names to two IP addresses.  The file may contain
+comments marked with '#'.
+.PP
+You can have aliases (more hostnames on the same line) to give a machine
+more than one name, like
+.BR www ,
+if you run a web server on one.
+.PP
+If your PC is Internet connected then you can specify the name server(s)
+to get more information from with %nameserver entries:
+.PP
+.RS
+.ta +\w'172.16.24.3'u+4m +\w'%nameserver'u+4m
+.nf
+172.16.24.3	%nameserver	# dns1.example.com
+172.16.24.6	%nameserver	# dns2.example.com
+.fi
+.RE
+.PP
+Read
+.BR nonamed (8)
+for all the details on special host file entries that configure
+.B nonamed
+for use on the Internet, and on home machines that are occasionally
+connected to the Internet.
+.SH FILES
+.TP 15n
+/etc/hosts
+Hosts database.
+.SH "SEE ALSO"
+.BR ethers (5),
+.BR nonamed (8),
+.BR dhcpd (8),
+.BR boot (8).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man5/keymap.5
===================================================================
--- /trunk/minix/man/man5/keymap.5	(revision 9)
+++ /trunk/minix/man/man5/keymap.5	(revision 9)
@@ -0,0 +1,167 @@
+.TH KEYMAP 5
+.SH NAME
+keymap \- keyboard maps
+.SH SYNOPSIS
+.B /etc/keymap
+.SH DESCRIPTION
+.B /etc/keymap 
+is the compressed mapping from keyboard scan codes to ASCII.
+It is made from a keymap source file consisting of MAP_COLS columns
+(MINIX assigns the value 6 to MAX_COLS, corresponding to key pressed,
+key+SHIFT, key+LEFT_ALT, key+RIGHT_ALT, key+ALT+SHIFT and key+CTRL) and 
+NR_SCAN_CODES rows (MINIX assigns the value 0x80 to NR_SCAN_CODES, 
+corresponding to the number of scan codes to be provided by the keyboard),
+and each element is 2 bytes in length (see u16_t in type definitions). 
+The low order byte corresponds to the character represented by the scan 
+code, and the high order byte corresponds to the special meaning (when 
+CAPS LOCK has effect, if it is a function key, etc.), which is converted to
+binary keymap format using the
+.BR genmap  
+utility. 
+.PP
+.SS "Types (general): <sys/types.h>"
+<sys/types.h> defines the
+.B u8_t
+and
+.B u16_t
+types, corresponding to 8 and 16 bit values.
+.SS "Macros: <minix/keymap.h>"
+.TP
+.BI "C(" c ") - Control"
+Maps to control code
+.TP
+.BI "A(" c ") - Alt"
+Sets the eight bit
+.TP
+.BI "CA(" c ") - Control-Alt"
+Short for
+.BI "A(C(" c "))"
+.TP
+.BI "L(" c ") - Caps Lock"
+Adds Caps Lock effect
+.PP
+These macros are used in a keymap source file to help define keys.  So
+instead of writing
+.B 032
+to put a CTRL-Z in the map you write
+.BR "C('Z')" .
+The
+.BI "L(" c ")"
+macro is used in column 0 to tell that the Caps Lock key is active for this
+key.  (Caps Lock should only have effect on letters.)
+.SS "Definitions: <minix/keymap.h>"
+<minix/keymap.h> contains a large number of definitions for special keys,
+like function keys, and keys on the numeric keypad.  They are:
+.PP
+Escape key and modifiers:
+.BR EXT ,
+.BR CTRL ,
+.BR SHIFT ,
+.BR ALT .
+.PP
+Numeric keypad keys:
+.BR HOME ,
+.BR END ,
+.BR UP ,
+.BR DOWN ,
+.BR LEFT ,
+.BR RIGHT ,
+.BR PGUP ,
+.BR PGDN ,
+.BR MID " (numeric '5'),"
+.BR PLUS ,
+.BR INSRT .
+.PP
+ALT + numpad key:
+.BR AHOME ,
+.BR AEND ", ...,"
+.BR AINSRT .
+.PP
+CTRL + numpad:
+.BR CHOME ,
+.BR CEND ", ...,"
+.BR CINSRT .
+.PP
+Lock keys:
+.BR CALOCK " (Caps Lock),"
+.BR NLOCK " (Num Lock),"
+.BR SLOCK " (Scroll Lock)."
+.PP
+Function keys:
+.BR F1 ", ...,"
+.BR F12 .
+.PP
+ALT - function key:
+.BR AF1 ", ...,"
+.BR AF12 .
+.PP
+CTRL - function key:
+.BR CF1 ", ...,"
+.BR CF12 .
+.PP
+SHIFT - function key:
+.BR SF1 ", ...,"
+.BR SF12 .
+.PP
+ALT - SHIFT - function key:
+.BR ASF1 ", ...,"
+.BR ASF12 .
+.PP
+There is one key definition that isn't a key at all:
+.BR EXTKEY .
+This keycode is sent by the keyboard as an indicator that the next keycode
+is special.  For instance both ALT keys have the same keycode, but the right
+ALT key is sent by the keyboard preceded by the EXTKEY keycode.  The same is
+true for the '/' key on the numeric pad versus the other '/' key on the US
+keyboard.  (On other keyboards this key may have a different symbol.)  The
+keyboard driver knows that a different key is presses if it is preceded by
+EXTKEY.
+.SS "Creating/changing keyboard mapping"
+You can create your own keyboard mapping by copying one of the existing
+keymap source files (Standard Minix:
+.BR kernel/keymaps/*.src ,
+Minix-vmd:
+.BR kernel/ibm/keymaps/*.src )
+and modifying the desired keys. Once this has been done, you need to
+recompile the genmap.c file, either by adding a new entry to the Makefile,
+or by running the following commands:
+.PP
+.RS
+.ft B
+cc -DKEYSRC=\e"\fIkeymap\fP.src\e" genmap.c
+.ft P
+.RE
+.PP
+After this, the 
+.BR keymap 
+file can be generated by running:
+.PP
+.RS
+.BI "a.out > " keymap .map
+.RE
+.PP
+The keymap can be loaded in the keyboard driver by:
+.PP
+.RS
+.BI "loadkeys " keymap .map
+.RE
+.PP
+It is wise to first run
+.B loadkeys
+on one of the maps in
+.B /usr/lib/keymaps
+so that you can easily revert back to a known keymap with a few taps on the
+up-arrow key and pressing return.  You will otherwise have to fix the keymap
+with a faulty keymap loaded into the keyboard driver, which is no fun.
+.PP
+When the keymap is to your satisfaction you can copy it to
+.B /etc/keymap
+to have it loaded automatically at reboot.
+.SH FILES
+.TP 15
+.B /etc/keymap
+Default keymap file
+.SH "SEE ALSO"
+.B loadkeys (1).
+.SH AUTHOR
+Victor A. Rodriguez - El bit Fantasma (Bit-Man@Tasa.Com.AR)
Index: /trunk/minix/man/man5/passwd.5
===================================================================
--- /trunk/minix/man/man5/passwd.5	(revision 9)
+++ /trunk/minix/man/man5/passwd.5	(revision 9)
@@ -0,0 +1,200 @@
+.TH PASSWD 5
+.SH NAME
+passwd, group, shadow \- user and group databases, shadow passwords
+.SH SYNOPSIS
+.B /etc/passwd
+.br
+.B /etc/group
+.br
+.B /etc/shadow
+.SH DESCRIPTION
+.B /etc/passwd
+lists all the users of the system, and
+.B /etc/group
+lists all the groups the users may belong to.  Both files also contain
+encrypted passwords, numeric ID's etc.  Encrypted passwords may be hidden
+in the file
+.B /etc/shadow
+if extra protection is warranted.
+.PP
+Each file is an text file containing one line per user or group.  The data
+fields on a line are separated by colons.  Each line in the password file
+has the following form:
+.PP
+.RS
+.I name:passwd:uid:gid:gecos:dir:shell
+.RE
+.PP
+The
+.I name
+field is the login name of a user, it is up to 8 letters or numbers long
+starting with a letter.  The login name must be unique.
+The
+.I password
+field is either empty (no password), a 13 character encrypted password as
+returned by
+.BR crypt (3),
+or a login name preceded by two number signs (#) to index the shadow
+password file.  Anything else (usually \(**) is invalid.
+The
+.I uid
+and
+.I gid
+fields are two numbers indicating the users user-id and group-id.  These
+id's do not have to be unique, there may be more than one name with the same
+id's.
+The
+.I gecos
+field can be set by the user.  It is expected to be a comma separated list
+of personal data where the first item is the full name of the user.
+The
+.I dir
+field
+is the path name of the users home directory.
+Lastly the
+.I shell
+field is the path name of the users login shell, it may be empty to indicate
+.BR /bin/sh .
+A MINIX 3 specific extension allows the shell field to contain extra space
+separated arguments for the shell.
+.PP
+Lines in the group file consist of four fields:
+.PP
+.RS
+.I name:passwd:gid:mem
+.RE
+.PP
+The
+.I name
+field is the name of the group, same restrictions as a login name.
+The
+.I passwd
+field may be used to let users change groups.
+The
+.I gid
+field is a number telling the group-id.  The group-id is unique for a group.
+The
+.I mem
+field is a comma separated list of login names that are special members of
+the group.  If a system supports supplementary group id's then a user's set
+of supplementary group id's is set to all the groups they are a member of.
+If a system allows one to change groups then one can change to a group one
+is a member of without using the group's password.
+.PP
+The shadow password file has precisely the same form as the password file,
+except that only the
+.I name
+or
+.I passwd
+fields are used as yet.  The other fields are zero or empty.  A password in
+the password file may have the form
+.BI "##" user
+to indicate the entry
+.I user
+in the shadow password file.  The password in this entry is then used for
+authentication of the user.  The shadow file can only be read by the
+privileged utility
+.BR pwdauth (8),
+so that the encrypted passwords in the shadow file are kept secret, and thus
+safe from a dictionary attack.
+.SS "Special password and group file entries"
+There are several entries in the password and group files that are
+preallocated for current or future use.  All id's less than 10 are reserved.
+The special password file entries are:
+.PP
+.RS
+.nf
+root:##root:0:0:Big Brother:/usr/src:
+daemon:*:1:1:The Deuce:/etc:
+bin:##root:2:0:Binaries:/usr/src:
+uucp:*:5:5:UNIX to UNIX copy:/usr/spool/uucp:/usr/sbin/uucico
+news:*:6:6:Usenet news:/usr/spool/news:
+ftp:*:7:7:Anonymous FTP:/usr/ftp:
+nobody:*:9999:99::/tmp:
+ast:*:8:3:Andrew S. Tanenbaum:/usr/ast:
+.fi
+.RE
+.PP
+The
+.B root
+id is of course the super user.
+The
+.B daemon
+id is used by some daemons.  Some devices are protected so that only those
+daemons can access them.
+The
+.B bin
+id owns all sources and most binaries.
+The
+.BR uucp ,
+.BR news
+and
+.BR ftp
+id's are for serial line data transfer, usenet news, or ftp if so needed.
+The
+.B nobody
+id is used in those cases that a program may not have any privileges at all.
+The
+.B ast
+id is the honorary home directory for Andrew S. Tanenbaum, the creator of
+MINIX 3.  You can also find the initial contents for a new home directory
+there.
+.PP
+The special group file entries are:
+.PP
+.RS
+.nf
+operator:*:0:
+daemon:*:1:
+bin:*:2:
+other:*:3:
+tty:*:4:
+uucp:*:5:
+news:*:6:
+ftp:*:7:
+kmem:*:8:
+nogroup:*:99:
+.fi
+.RE
+.PP
+Groups with the same name as special user id are used with those id's.
+The
+.B operator
+group is for the administrators of the system.  Users in this group are
+granted special privileges.
+The
+.B other
+group is for ordinary users.
+The
+.B tty
+group is for terminal devices, and associated set-gid commands.
+Same thing with the
+.B kmem
+group and memory devices.
+.SH FILES
+.TP 15n
+.B /etc/passwd
+The user database.
+.TP
+.B /etc/group
+The group database.
+.TP
+.B /etc/shadow
+The shadow password file.
+.SH "SEE ALSO"
+.BR login (1),
+.BR passwd (1),
+.BR su (1),
+.BR crypt (3),
+.BR getpwent (3),
+.BR getgrent (3),
+.BR pwdauth (8).
+.SH NOTES
+The
+.B nobody
+and
+.B nogroup
+id's are likely to be renumbered to the highest possible id's once it is
+figured out what they are.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man5/resolv.conf.5
===================================================================
--- /trunk/minix/man/man5/resolv.conf.5	(revision 9)
+++ /trunk/minix/man/man5/resolv.conf.5	(revision 9)
@@ -0,0 +1,48 @@
+.TH RESOLV.CONF 5
+.SH NAME
+resolv.conf \- Domain Name System resolver configuration
+.SH SYNOPSIS
+.B /etc/resolv.conf
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+The
+.B /etc/resolv.conf
+is used to configure how the host will use the Domain Name System to resolve
+hostnames to IP addresses.  It may contain these two lines:
+.PP
+.RS
+.ta +15n
+nameserver	\fIIP-address\fP
+.br
+domain	\fIdomain-name\fP
+.RE
+.PP
+The nameserver entry tells the IP address of the host to use for DNS
+queries.  If it is set to 127.0.0.1 (which is the default) then the local
+name daemon is used that may use the
+.B /etc/hosts
+database to translate host names.  You normally only need a nameserver entry
+if the name server is at the other side of a router.  The default
+.B nonamed
+name server can't look beyond the local network.
+.PP
+The domain entry tells the default domain to use for unqualified hostnames.
+This entry is usually not given in which case the domain of the local host
+is used.
+.PP
+The long version of this story can be found in
+.BR resolver (5).
+.SH FILES
+.TP 20n
+/etc/resolv.conf
+DNS resolver configuration file.
+.SH "SEE ALSO"
+.BR resolver (5),
+.BR hosts (5),
+.BR nonamed (8),
+.BR boot (8).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man5/resolver.5
===================================================================
--- /trunk/minix/man/man5/resolver.5	(revision 9)
+++ /trunk/minix/man/man5/resolver.5	(revision 9)
@@ -0,0 +1,98 @@
+.\" Copyright (c) 1986 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms are permitted
+.\" provided that the above copyright notice and this paragraph are
+.\" duplicated in all such forms and that any documentation,
+.\" advertising materials, and other materials related to such
+.\" distribution and use acknowledge that the software was developed
+.\" by the University of California, Berkeley.  The name of the
+.\" University may not be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\"	@(#)resolver.5	5.9 (Berkeley) 12/14/89
+.\"
+.TH RESOLVER 5 "December 14, 1989"
+.UC 4
+.SH NAME
+resolver \- resolver configuration file
+.SH SYNOPSIS
+/etc/resolv.conf
+.SH DESCRIPTION
+.LP
+The
+.I resolver
+is a set of routines in the C library (\c
+.IR resolv (3))
+that provide access to the Internet Domain Name System.
+The resolver configuration file contains information that is read
+by the resolver routines the first time they are invoked by a process.
+The file is designed to be human readable and contains a list of
+keywords with values that provide various types of resolver information.
+.LP
+On a normally configured system this file should not be necessary.
+The only name server to be queried will be on the local machine,
+the domain name is determined from the host name,
+and the domain search path is constructed from the domain name.
+.LP
+The different configuration options are:
+.TP
+\fBnameserver\fP
+Internet address (in dot notation) of a name server
+that the resolver should query.
+Up to MAXNS (currently 3) name servers may be listed,
+one per keyword.
+If there are multiple servers,
+the resolver library queries them in the order listed.
+If no \fBnameserver\fP entries are present,
+the default is to use the name server on the local machine.
+(The algorithm used is to try a name server, and if the query times out,
+try the next, until out of name servers,
+then repeat trying all the name servers
+until a maximum number of retries are made).
+.TP
+\fBdomain\fP
+Local domain name.
+Most queries for names within this domain can use short names
+relative to the local domain.
+If no \fBdomain\fP entry is present, the domain is determined
+from the local host name returned by
+\fIgethostname\fP\|(2);
+the domain part is taken to be everything after the first `.'.
+Finally, if the host name does not contain a domain part, the root
+domain is assumed.
+.TP
+\fBsearch\fP
+Search list for host-name lookup.
+The search list is normally determined from the local domain name;
+by default, it begins with the local domain name, then successive
+parent domains that have at least two components in their names.
+This may be changed by listing the desired domain search path
+following the \fIsearch\fP keyword with spaces or tabs separating
+the names.
+Most resolver queries will be attempted using each component
+of the search path in turn until a match is found.
+Note that this process may be slow and will generate a lot of network
+traffic if the servers for the listed domains are not local,
+and that queries will time out if no server is available
+for one of the domains.
+.IP
+The search list is currently limited to six domains
+with a total of 256 characters.
+.LP
+The \fIdomain\fP and \fIsearch\fP keywords are mutually exclusive.
+If more than one instance of these keywords is present,
+the last instance will override.
+.LP
+The keyword and value must appear on a single line, and the keyword
+(e.g. \fBnameserver\fP) must start the line.  The value follows
+the keyword, separated by white space.
+.SH FILES
+.I /etc/resolv.conf
+.SH SEE ALSO
+gethostbyname(3N), resolver(3), hostname(7), named(8)
+.br
+Name Server Operations Guide for BIND
Index: /trunk/minix/man/man5/rhosts.5
===================================================================
--- /trunk/minix/man/man5/rhosts.5	(revision 9)
+++ /trunk/minix/man/man5/rhosts.5	(revision 9)
@@ -0,0 +1,59 @@
+.TH RHOSTS 5
+.SH NAME
+rhosts, hosts.equiv \- trusted remote users or hosts
+.SH SYNOPSIS
+.BI ~ user /.rhosts
+.br
+.B /etc/hosts.equiv
+.SH DESCRIPTION
+The per user
+.B .rhosts
+and the per system
+.B hosts.equiv
+files can be used to allow users to use
+.B rlogin
+or
+.B rsh
+without a password.  The remote login services first check the system wide
+.B /etc/hosts.equiv
+file and then the
+.BI ~ user /.rhosts
+of the intended user.  Both files contain lines of one of two forms:
+.PP
+.RS
+.I host
+.br
+.I host ruser
+.RE
+.PP
+The first form tells that any user from
+.I host
+is allowed to login to this system under the same name.  The second form
+allows
+.I ruser
+from
+.I host
+to login.
+.PP
+Under MINIX 3
+.I host
+may be a pattern using
+.B "*"
+as a wildcard.  One can use this, carefully one may hope, to allow an
+entire domain to log in.
+.I Host
+may also be an IP address, or a network specification in CIDR form, e.g.
+172.16.102.64/27.
+.SH "SEE ALSO"
+.BR rlogin (1),
+.BR rsh (1).
+.SH NOTES
+MINIX 3 has no restrictions on becoming super-user remotely.  Other systems
+usually require one to log in as a user and then use
+.BR su
+to become root.
+.PP
+You must use fully qualified hostnames, it is not possible to
+omit the domain part.
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man5/serv.access.5
===================================================================
--- /trunk/minix/man/man5/serv.access.5	(revision 9)
+++ /trunk/minix/man/man5/serv.access.5	(revision 9)
@@ -0,0 +1,166 @@
+.TH SERV.ACCESS 5
+.SH NAME
+serv.access \- Internet service access list
+.SH SYNOPSIS
+.B /etc/serv.access
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+The
+.B serv.access
+file contains a list of rules that guide the access checks made by the
+.BR servxcheck (3)
+function.  The file is a text file containing entries that look as follows:
+.PP
+.RS
+.I service1 service2
+.RB ... :
+.I check1 check2
+.RB ... ;
+.RE
+.PP
+Each of the service names is a service name from the
+.B /etc/services
+file.  The same names are used in the
+.B /etc/inetd.conf
+configuration file that guides
+.BR inetd (8).
+.PP
+The checks may look as follows:
+.PP
+.BI +
+.br
+.BI -
+.RS
+Allow all, or allow none.  Used to explicitly set the initial state.
+.RE
+.PP
+.BI + name
+.RS
+Grant access to one of the services if the host name of the remote system
+matches
+.BR name .
+.RE
+.SP
+.BI \- name
+.RS
+Deny access to one of the services if the host name of the remote system
+matches
+.BR name .
+.RE
+.PP
+.BI + ipaddr
+.br
+.BI \- ipaddr
+.br
+.BI + netaddr / len
+.br
+.BI \- netaddr / len
+.RS
+Grants or denies access to a remote host with IP address
+.IR ipaddr ,
+or the remote host whose IP address is within the network
+.IR netaddr .
+.I Len
+tells the number of bits used for the network address, i.e. the top
+.I len
+bits of the network address must equal the host address.
+.RE
+.PP
+.BR log
+.RS
+This is not a check, but a flag that instruct
+.B servxcheck()
+to log the result of the access check whether it succeeds or not to
+.BR /usr/adm/log .
+By default only failure is logged.
+.RE
+.PP
+The first "+" or "\-" access check sets the tone.  Read it as "access denied
+unless +...", or "access granted unless \-...".  An access check will
+therefore almost always start with a "+" check.  To make the initial state
+clear you can start with a lone "+" or "\-".  Checks are done from left
+to right.  A check that doesn't match does not change the outcome.  A check
+that can't change the outcome is skipped.
+.PP
+Both the service and the host names may contain the
+.B "\(**"
+wildcard that matches any number of characters including none.  Letters are
+compared ignoring case.  A service name may appear in more than one rule,
+but a service mentioned explicitly is not matched by wildcard patterns in
+later rules.
+.PP
+A check for a hostname causes
+.B servxcheck()
+to do a reverse lookup on the IP address of the remote host to find its
+name.  This name is then looked up to find the host's IP address(es).
+If those lookups fail then all
+.BI \- name
+checks cause access to be denied, and no
+.BI + name
+check grants access.
+The DNS lookup failures may be a
+misconfiguration, but could indicate a break-in attempt from a badly
+maintained host.  You can use a simple "+*" in an otherwise empty list to
+just deny misconfigured hosts.
+.PP
+An IP or network address check is simply done on the remote hosts IP
+address.  Such a check has no overhead, but a
+.B log
+flag will cause a reverse lookup anyway.
+.PP
+Comments start with "#" and continue until end of line.
+.SH EXAMPLES
+Example access file on a machine that offers most services only to hosts within
+the cs.vu.nl domain, and news (nntp) only to two machines and a specific
+network.
+.PP
+.RS
+.nf
+.ta +2.2i +.4i
+# Service	# Access list
+login shell:	+*.cs.vu.nl log;
+telnet pop smtp finger:	+ log;
+nntp:	+flotsam.cs.vu.nl +jetsam.cs.vu.nl
+		+172.16.102.0/24 log;
+*:	+*.cs.vu.nl;
+.fi
+.RE
+.PP
+More paranoid example that limits all services by default, but allows ftp and
+http to the world:
+.PP
+.RS
+.nf
+.ta +2.2i +.4i
+# Service	# Access list
+ftp http:	+;
+smtp finger:	+ log;
+nntp:	+flotsam.cs.vu.nl +jetsam.cs.vu.nl
+		+172.16.102.0/24 log;
+*:	+*.cs.vu.nl log;
+.fi
+.RE
+.PP
+(Note that the last rule doesn't match any of the services mentioned
+explicitly earlier.)
+.SH FILES
+.TP 25n
+.B /etc/serv.access
+The service access check file.
+.SH "SEE ALSO"
+.BR servxcheck (3),
+.BR services (5),
+.BR inetd.conf (5).
+.SH NOTES
+It may be wise not to put checks on telnet.  It is reasonably secure, since
+it always requires a password, and your only way in if things are seriously
+hosed.
+.SH BUGS
+IP and DNS based access checks will stop most crackers, but not the really
+determined ones.  Luckily MINIX 3 is sufficiently strange to thwart the well
+known cracking schemes.  But don't ever allow yourself to feel secure.
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man5/syslog.conf.5
===================================================================
--- /trunk/minix/man/man5/syslog.conf.5	(revision 9)
+++ /trunk/minix/man/man5/syslog.conf.5	(revision 9)
@@ -0,0 +1,246 @@
+.\" syslog.conf - syslogd(8) configuration file
+.\" Copyright (c) 1995  Martin Schulze <Martin.Schulze@Linux.DE>
+.\" Modified for Minix porting by G. Falzoni <gfalzoni@inwind.it>
+.\" $Id: syslog.conf.5,v 1.1 2006/04/03 14:59:52 beng Exp $
+.\" 
+.\" This file is part of the sysklogd package, a kernel and system log daemon.
+.\" 
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\" 
+.\" This program is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+.\" GNU General Public License for more details.
+.\" 
+.\" You should have received a copy of the GNU General Public License
+.\" along with this program; if not, write to the Free Software
+.\" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+.\"
+.\" Local macros
+.de Xr
+.BR \\$1 (\\$2)\\$3
+..
+.de LB
+.TP \\$1
+\\fB\\$2\\fR
+\\$3
+..
+.de LI
+.TP \\$1
+\\fI\\$2\\fR
+\\$3
+..
+.de LR
+.TP \\$1
+\\fR\\$2\\fR
+\\$3
+..
+.\" end local macros
+.TH SYSLOG.CONF 5 "1 January 1998"
+.SH NAME
+syslog.conf \- syslogd(8) configuration file
+.SH DESCRIPTION
+The
+.I syslog.conf
+file is the main configuration file for the
+.Xr syslogd 8
+which logs system messages on *nix systems. This file specifies rules
+for logging. For special features see the
+.Xr syslogd 8
+manpage.
+Every rule consists of two fields, a 
+.I selector
+field and an
+.I action 
+field. These two fields are separated by one or more tabs.
+The selector field specifies a pattern of facilities and
+priorities belonging to the specified action.
+Lines starting with a hash mark (``#'') and empty lines are ignored.
+.SH SELECTORS
+The selector field itself again consists of two parts, a
+.I facility
+and a 
+.IR priority ,
+separated by a period (``.'').
+Both parts are case insensitive and can also be specified as decimal
+numbers, but don't do that, you have been warned. Both facilities and
+priorities are described in 
+.BR syslog (3).
+The names mentioned below correspond to the similar 
+.BR LOG_ -values
+in
+.IR /usr/include/syslog.h .
+The
+.I facility
+is one of the following keywords:
+.BR auth ", " authpriv ", " cron ", " daemon ", " kern ", " lpr ", "
+.BR mail ", " mark ", " news ", " security " (same as " auth "), "
+.BR syslog ", " user ", " uucp " and " local0 " through " local7 .
+The keyword 
+.B security
+should not be used anymore and
+.B mark
+is only for internal use and therefore should not be used in
+applications. Anyway, you may want to specify and redirect these
+messages here. The
+.I facility
+specifies the subsystem that produced the message, i.e. all mail
+programs log with the mail facility
+.BR "" ( LOG_MAIL )
+if they log using syslog.
+
+The
+.I priority
+is one of the following keywords, in ascending order: 
+.BR debug ", " info ", " notice ", " warning ", " warn " (same as "
+.BR warning "), " err ", " error " (same as " err "), " crit ", "
+.BR alert ", " emerg ", " panic " (same as " emerg ).
+The keywords
+.BR error ", " warn " and " panic
+are deprecated and should not be used anymore. The
+.I priority
+defines the severity of the message
+.PP
+The behavior of the original BSD syslogd is that all messages of the
+specified priority and higher are logged according to the given
+action. This
+.BR syslogd (8)
+behaves the same, but has some extensions.
+.PP
+In addition to the above mentioned names the
+.BR syslogd (8)
+understands the following extensions:
+.LB 5 "*" "An asterisk (``*'') before the period stands for all facilities.
+.LB 5 "none" "The keyword none stands for no priority of the given facility.
+.PP
+Multiple selectors may be specified for a single
+.I action
+using the semicolon (``;'') separator.  Remember that each selector in
+the 
+.I selector
+field is capable to overwrite the preceding ones. Using this
+behavior you can exclude some priorities from the pattern.
+.SH ACTIONS
+The action field of a rule describes the abstract term
+``logfile''. A ``logfile'' need not to be a real file, btw. The
+.Xr syslogd 8
+provides the following actions.
+.SS Regular File
+Typically messages are logged to real files. The file has to be
+specified with full pathname, beginning with a slash ``/''.
+.SS Terminal and Console
+If the file you specified is a tty, special tty-handling is done, same
+with
+.IR /dev/console .
+.SS Remote Machine
+This release does not implement 
+remote logging, i.e. the ability to send messages to a remote host running 
+.Xr syslogd 8 .
+To forward messages to another host, prepend the hostname
+with the at sign (``@'').
+.SS List of Users
+Usually critical messages are also directed to ``root'' on that
+machine. You can specify a list of users that shall get the message by
+simply writing the login. You may specify more than one user by
+separating them with commas (``,''). If they're logged in they
+get the message. Don't think a mail would be sent, that might be too
+late.
+.SS Everyone logged on
+Emergency messages often go to all users currently online to notify
+them that something strange is happening with the system. To specify
+this
+.IR wall (1)-feature
+use an asterisk (``*'').
+.SH EXAMPLES
+Here are some example, partially taken from a real existing site and
+configuration. Hopefully they rub out all questions to the
+configuration, if not, drop me (Joey) a line.
+.IP
+.nf
+# Store critical stuff in critical
+#
+*.crit            /var/adm/critical
+.fi
+.LP
+This will store all messages with the priority
+.B crit
+in the file
+.IR /var/adm/critical .
+.IP
+.nf
+# The tcp wrapper loggs with mail.info, we display
+# all the connections on tty12
+#
+mail.info                   /dev/tty12
+.fi
+.LP
+This directs all messages that uses 
+.BR mail.info " (in source " LOG_MAIL " | " LOG_INFO )
+to
+.IR /dev/tty12 , 
+the 12th console.
+.IP
+.nf
+# Log all mail.info and news.info messages to info
+#
+mail,news.info              /var/adm/info
+.fi
+.LP
+This will extract all messages that come either with
+.BR mail.info " or with " news.info 
+and store them in the file
+.IR /var/adm/info .
+.IP
+.nf
+# Emergency messages will be displayed using wall
+#
+*.emerg                     *
+.fi
+.LP
+This rule tells the
+.B syslogd
+to write all emergency messages to all currently logged in users. This
+is the wall action.
+.IP
+.nf
+# Messages of the priority alert will be directed
+# to the operator
+#
+*.alert                      root,joey
+.fi
+.LP
+This rule directs all messages with a priority of
+.B alert
+or higher to the terminals of the operator, i.e. of the users ``root''
+and ``joey'' if they're logged in.
+.IP
+.nf
+*.*                          @finlandia
+.fi
+.LP
+This rule would redirect all messages to a remote host called
+finlandia. This is useful especially in a cluster of machines where
+all syslog messages will be stored on only one machine.
+.SH FILES
+.I /etc/syslog.conf
+Configuration file for
+.B syslogd
+.SH BUGS
+The effects of multiple selectors are sometimes not intuitive. For
+example ``mail.crit,*.err'' will select ``mail'' facility messages at
+the level of ``err'' or higher, not at the level of ``crit'' or
+higher.
+
+.SH SEE ALSO
+.BR syslogd (8),
+.BR logger (1),
+.BR syslog (3)
+.SH AUTHORS
+The
+.B syslogd
+is taken from BSD sources, Greg Wettstein (greg@wind.rmcc.com)
+performed the port to Linux, Martin Schulze (joey@linux.de)
+made some bugfixes and added some new features.
Index: /trunk/minix/man/man5/termcap.5
===================================================================
--- /trunk/minix/man/man5/termcap.5	(revision 9)
+++ /trunk/minix/man/man5/termcap.5	(revision 9)
@@ -0,0 +1,1865 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)termcap.5	6.4 (Berkeley) 5/15/86
+.\"
+.tr ||
+.tr *\(**
+.TH TERMCAP 5 "1 November 1985"
+.UC
+.SH NAME
+termcap \- terminal capability data base
+.SH SYNOPSIS
+.B /etc/termcap
+.SH DESCRIPTION
+.B Termcap\^
+is a data base describing terminals,
+used,
+.IR e.g. ,
+by
+.BR vi\^ (1)
+and
+.BR curses\^ (3).
+Terminals are described in
+.B termcap\^
+by giving a set of capabilities that they have and by describing
+how operations are performed.
+Padding requirements and initialization sequences
+are included in
+.BR termcap\^ .
+.PP
+Entries in
+.B termcap\^
+consist of a number of `:'-separated fields.
+The first entry for each terminal gives the names that are known for the
+terminal, separated by `|' characters.
+The first name is always two characters
+long and is used by older systems which store the terminal type
+in a 16-bit word in a system-wide data base.
+The second name given is the most common abbreviation for the terminal,
+the last name given should be a long name fully identifying the terminal,
+and all others are understood as synonyms for the terminal name.
+All names but the first and last
+should be in lower case and contain no blanks;
+the last name may well contain
+upper case and blanks for readability.
+.PP
+Terminal names (except for the last, verbose entry)
+should be chosen using the following conventions.
+The particular piece of hardware making up the terminal
+should have a root name chosen, thus \*(lqhp2621\*(rq.
+This name should not contain hyphens.
+Modes that the hardware can be in
+or user preferences
+should be indicated by appending a hyphen and an indicator of the mode.
+Therefore, a \*(lqvt100\*(rq in 132-column mode would be \*(lqvt100-w\*(rq.
+The following suffixes should be used where possible:
+.sp
+.ta
+.if t .ta \w'\fBSuffix\fP\ \ \ 'u +\w'With automatic margins (usually default)\ \ 'u
+.if n .ta \w'Suffix\ \ \ 'u +\w'With automatic margins (usually default)\ \ 'u
+.nf
+.if t .nr Xx \n(.lu-\n(.i-\w'\fBSuffix\fP\ \ \ With automatic margins (usually default)\ \ vt100-am'u
+.if t .in +\n(Xxu/2u
+\fBSuffix	Meaning	Example\fP
+-w	Wide mode (more than 80 columns)	vt100-w
+-am	With automatic margins (usually default)	vt100-am
+-nam	Without automatic margins	vt100-nam
+-\fIn\fP	Number of lines on the screen	aaa-60
+-na	No arrow keys (leave them in local)	concept100-na
+-\fIn\^\fPp	Number of pages of memory	concept100-4p
+-rv	Reverse video	concept100-rv
+.fi
+.SH CAPABILITIES
+.PP
+The characters in the
+.B Notes
+field in the table have the following meanings
+(more than one may apply to a capability):
+.PP
+.ta
+.ta \w'N\ \ \ 'u
+.nr fi \w'N\ \ \ '
+.in +\n(fiu
+.ti -\n(fiu
+N	indicates numeric parameter(s)
+.ti -\n(fiu
+P	indicates that padding may be specified
+.ti -\n(fiu
+*	indicates that padding may be based on the number of lines affected
+.ti -\n(fiu
+o	indicates capability is obsolete
+.in +\n(fiu
+.PP
+\*(lqObsolete\*(rq capabilities have no
+.B terminfo\^
+equivalents,
+since they were considered useless,
+or are subsumed by other capabilities.
+New software should not rely on them at all.
+.PP
+.if t .ta \w'\fBName  \fP'u +\w'\fBType  \fP'u +\w'\fBNotes  \fP'u
+.if n .ta \w'Name  'u +\w'Type  'u +\w'Notes  'u  \" Cawf troubled by \w'\fB
+.if t .nr fi \w'\fBName  Type  Notes  \fP'
+.if n .nr fi \w'Name  Type  Notes  '
+.in +\n(fiu
+.ti -\n(fiu
+\fBName	Type	Notes	Description\fP
+.ti -\n(fiu
+ae	str	(P)	End alternate character set
+.ti -\n(fiu
+AL	str	(NP*)	Add \fIn\^\fP new blank lines
+.ti -\n(fiu
+al	str	(P*)	Add new blank line
+.ti -\n(fiu
+am	bool		Terminal has automatic margins
+.ti -\n(fiu
+as	str	(P)	Start alternate character set
+.ti -\n(fiu
+bc	str	(o)	Backspace if not \fB^H\fP
+.ti -\n(fiu
+bl	str	(P)	Audible signal (bell)
+.ti -\n(fiu
+bs	bool	(o)	Terminal can backspace with \fB^H\fP
+.ti -\n(fiu
+bt	str	(P)	Back tab
+.ti -\n(fiu
+bw	bool		\fBle\fP (backspace) wraps from column 0 to last column
+.ti -\n(fiu
+CC	str		Terminal settable command character in prototype
+.ti -\n(fiu
+cd	str	(P*)	Clear to end of display
+.ti -\n(fiu
+ce	str	(P)	Clear to end of line
+.ti -\n(fiu
+ch	str	(NP)	Set cursor column (horizontal position)
+.ti -\n(fiu
+cl	str	(P*)	Clear screen and home cursor
+.ti -\n(fiu
+CM	str	(NP)	Memory-relative cursor addressing
+.ti -\n(fiu
+cm	str	(NP)	Screen-relative cursor motion
+.ti -\n(fiu
+co	num		Number of columns in a line (See BUGS section below)
+.ti -\n(fiu
+cr	str	(P)	Carriage return
+.ti -\n(fiu
+cs	str	(NP)	Change scrolling region (VT100)
+.ti -\n(fiu
+ct	str	(P)	Clear all tab stops
+.ti -\n(fiu
+cv	str	(NP)	Set cursor row (vertical position)
+.ti -\n(fiu
+da	bool		Display may be retained above the screen
+.ti -\n(fiu
+dB	num	(o)	Milliseconds of \fBbs\fP delay needed (default 0)
+.ti -\n(fiu
+db	bool		Display may be retained below the screen
+.ti -\n(fiu
+DC	str	(NP*)	Delete \fIn\^\fP characters
+.ti -\n(fiu
+dC	num	(o)	Milliseconds of \fBcr\fP delay needed (default 0)
+.ti -\n(fiu
+dc	str	(P*)	Delete character
+.ti -\n(fiu
+dF	num	(o)	Milliseconds of \fBff\fP delay needed (default 0)
+.ti -\n(fiu
+DL	str	(NP*)	Delete \fIn\^\fP lines
+.ti -\n(fiu
+dl	str	(P*)	Delete line
+.ti -\n(fiu
+dm	str		Enter delete mode
+.ti -\n(fiu
+dN	num	(o)	Milliseconds of \fBnl\fP delay needed (default 0)
+.ti -\n(fiu
+DO	str	(NP*)	Move cursor down \fIn\^\fP lines
+.ti -\n(fiu
+do	str		Down one line
+.ti -\n(fiu
+ds	str		Disable status line
+.ti -\n(fiu
+dT	num	(o)	Milliseconds of horizontal tab delay needed (default 0)
+.ti -\n(fiu
+dV	num	(o)	Milliseconds of vertical tab delay needed (default 0)
+.ti -\n(fiu
+ec	str	(NP)	Erase \fIn\^\fP characters
+.ti -\n(fiu
+ed	str		End delete mode
+.ti -\n(fiu
+ei	str		End insert mode
+.ti -\n(fiu
+eo	bool		Can erase overstrikes with a blank
+.ti -\n(fiu
+EP	bool	(o)	Even parity
+.ti -\n(fiu
+es	bool		Escape can be used on the status line
+.ti -\n(fiu
+ff	str	(P*)	Hardcopy terminal page eject
+.ti -\n(fiu
+fs	str		Return from status line
+.ti -\n(fiu
+gn	bool		Generic line type (\fIe.g.\fP dialup, switch)
+.ti -\n(fiu
+hc	bool		Hardcopy terminal
+.ti -\n(fiu
+HD	bool	(o)	Half-duplex
+.ti -\n(fiu
+hd	str		Half-line down (forward 1/2 linefeed)
+.ti -\n(fiu
+ho	str	(P)	Home cursor
+.ti -\n(fiu
+hs	bool		Has extra \*(lqstatus line\*(rq
+.ti -\n(fiu
+hu	str		Half-line up (reverse 1/2 linefeed)
+.ti -\n(fiu
+hz	bool		Cannot print ~s (Hazeltine)
+.ti -\n(fiu
+i1-i3	str		Terminal initialization strings (\fBterminfo\^\fP only)
+.ti -\n(fiu
+IC	str	(NP*)	Insert \fIn\^\fP blank characters
+.ti -\n(fiu
+ic	str	(P*)	Insert character
+.ti -\n(fiu
+if	str		Name of file containing initialization string
+.ti -\n(fiu
+im	str		Enter insert mode
+.ti -\n(fiu
+in	bool		Insert mode distinguishes nulls
+.ti -\n(fiu
+iP	str		Pathname of program for initialization (\fBterminfo\^\fP only)
+.ti -\n(fiu
+ip	str	(P*)	Insert pad after character inserted
+.ti -\n(fiu
+is	str		Terminal initialization string (\fBtermcap\^\fP only)
+.ti -\n(fiu
+it	num		Tabs initially every \fIn\^\fP positions
+.ti -\n(fiu
+K1	str		Sent by keypad upper left
+.ti -\n(fiu
+K2	str		Sent by keypad upper right
+.ti -\n(fiu
+K3	str		Sent by keypad center
+.ti -\n(fiu
+K4	str		Sent by keypad lower left
+.ti -\n(fiu
+K5	str		Sent by keypad lower right
+.ti -\n(fiu
+k0-k9	str		Sent by function keys 0-9
+.ti -\n(fiu
+kA	str		Sent by insert-line key
+.ti -\n(fiu
+ka	str		Sent by clear-all-tabs key
+.ti -\n(fiu
+kb	str		Sent by backspace key
+.ti -\n(fiu
+kC	str		Sent by clear-screen or erase key
+.ti -\n(fiu
+kD	str		Sent by delete-character key
+.ti -\n(fiu
+kd	str		Sent by down-arrow key
+.ti -\n(fiu
+kE	str		Sent by clear-to-end-of-line key
+.ti -\n(fiu
+ke	str		Out of \*(lqkeypad transmit\*(rq mode
+.ti -\n(fiu
+kF	str		Sent by scroll-forward/down key
+.ti -\n(fiu
+kH	str		Sent by home-down key
+.ti -\n(fiu
+kh	str		Sent by home key
+.ti -\n(fiu
+kI	str		Sent by insert-character or enter-insert-mode key
+.ti -\n(fiu
+kL	str		Sent by delete-line key
+.ti -\n(fiu
+kl	str		Sent by left-arrow key
+.ti -\n(fiu
+kM	str		Sent by insert key while in insert mode
+.ti -\n(fiu
+km	bool		Has a \*(lqmeta\*(rq key (shift, sets parity bit)
+.ti -\n(fiu
+kN	str		Sent by next-page key
+.ti -\n(fiu
+kn	num	(o)	Number of function (\fBk0\fP\-\fBk9\fP) keys (default 0)
+.ti -\n(fiu
+ko	str	(o)	Termcap entries for other non-function keys
+.ti -\n(fiu
+kP	str		Sent by previous-page key
+.ti -\n(fiu
+kR	str		Sent by scroll-backward/up key
+.ti -\n(fiu
+kr	str		Sent by right-arrow key
+.ti -\n(fiu
+kS	str		Sent by clear-to-end-of-screen key
+.ti -\n(fiu
+ks	str		Put terminal in \*(lqkeypad transmit\*(rq mode
+.ti -\n(fiu
+kT	str		Sent by set-tab key
+.ti -\n(fiu
+kt	str		Sent by clear-tab key
+.ti -\n(fiu
+ku	str		Sent by up-arrow key
+.ti -\n(fiu
+l0-l9	str		Labels on function keys if not \*(lqf\fIn\^\fP\*(rq
+.ti -\n(fiu
+LC	bool	(o)	Lower-case only
+.ti -\n(fiu
+LE	str	(NP)	Move cursor left \fIn\^\fP positions
+.ti -\n(fiu
+le	str	(P)	Move cursor left one position
+.ti -\n(fiu
+li	num		Number of lines on screen or page (See BUGS section below)
+.ti -\n(fiu
+ll	str		Last line, first column
+.ti -\n(fiu
+lm	num		Lines of memory if > \fBli\fP (0 means varies)
+.ti -\n(fiu
+ma	str	(o)	Arrow key map (used by \fBvi\^\fP version 2 only)
+.ti -\n(fiu
+mb	str		Turn on blinking attribute
+.ti -\n(fiu
+md	str		Turn on bold (extra bright) attribute
+.ti -\n(fiu
+me	str		Turn off all attributes
+.ti -\n(fiu
+mh	str		Turn on half-bright attribute
+.ti -\n(fiu
+mi	bool		Safe to move while in insert mode
+.ti -\n(fiu
+mk	str		Turn on blank attribute (characters invisible)
+.ti -\n(fiu
+ml	str	(o)	Memory lock on above cursor
+.ti -\n(fiu
+mm	str		Turn on \*(lqmeta mode\*(rq (8th bit)
+.ti -\n(fiu
+mo	str		Turn off \*(lqmeta mode\*(rq
+.ti -\n(fiu
+mp	str		Turn on protected attribute
+.ti -\n(fiu
+mr	str		Turn on reverse-video attibute
+.ti -\n(fiu
+ms	bool		Safe to move in standout modes
+.ti -\n(fiu
+mu	str	(o)	Memory unlock (turn off memory lock)
+.ti -\n(fiu
+nc	bool	(o)	No correctly-working \fBcr\fP (Datamedia 2500, Hazeltine 2000)
+.ti -\n(fiu
+nd	str		Non-destructive space (cursor right)
+.ti -\n(fiu
+NL	bool	(o)	\fB\\n\fP is newline, not line feed
+.ti -\n(fiu
+nl	str	(o)	Newline character if not \fB\\n\fP
+.ti -\n(fiu
+ns	bool	(o)	Terminal is a \s-1CRT\s0 but doesn't scroll
+.ti -\n(fiu
+nw	str	(P)	Newline (behaves like \fBcr\fP followed by \fBdo\fP)
+.ti -\n(fiu
+OP	bool	(o)	Odd parity
+.ti -\n(fiu
+os	bool		Terminal overstrikes
+.ti -\n(fiu
+pb	num		Lowest baud where delays are required
+.ti -\n(fiu
+pc	str		Pad character (default \s-2NUL\s0)
+.ti -\n(fiu
+pf	str		Turn off the printer
+.ti -\n(fiu
+pk	str		Program function key \fIn\^\fP to type string \fIs\fP (\fBterminfo\^\fP only)
+.ti -\n(fiu
+pl	str		Program function key \fIn\^\fP to execute string \fIs\fP (\fBterminfo\^\fP only)
+.ti -\n(fiu
+pO	str	(N)	Turn on the printer for \fIn\^\fP bytes
+.ti -\n(fiu
+po	str		Turn on the printer
+.ti -\n(fiu
+ps	str		Print contents of the screen
+.ti -\n(fiu
+pt	bool	(o)	Has hardware tabs (may need to be set with \fBis\fP)
+.ti -\n(fiu
+px	str		Program function key \fIn\^\fP to transmit string \fIs\fP (\fBterminfo\^\fP only)
+.ti -\n(fiu
+r1-r3	str		Reset terminal completely to sane modes (\fBterminfo\^\fP only)
+.ti -\n(fiu
+rc	str	(P)	Restore cursor to position of last \fBsc\fP
+.ti -\n(fiu
+rf	str		Name of file containing reset codes
+.ti -\n(fiu
+RI	str	(NP)	Move cursor right \fIn\^\fP positions
+.ti -\n(fiu
+rp	str	(NP*)	Repeat character \fIc n\^\fP times
+.ti -\n(fiu
+rs	str		Reset terminal completely to sane modes (\fBtermcap\^\fP only)
+.ti -\n(fiu
+sa	str	(NP)	Define the video attributes
+.ti -\n(fiu
+sc	str	(P)	Save cursor position
+.ti -\n(fiu
+se	str		End standout mode
+.ti -\n(fiu
+SF	str	(NP*)	Scroll forward \fIn\^\fP lines
+.ti -\n(fiu
+sf	str	(P)	Scroll text up
+.ti -\n(fiu
+sg	num		Number of garbage chars left by \fBso\fP or \fBse\fP (default 0)
+.ti -\n(fiu
+so	str		Begin standout mode
+.ti -\n(fiu
+SR	str	(NP*)	Scroll backward \fIn\^\fP lines
+.ti -\n(fiu
+sr	str	(P)	Scroll text down
+.ti -\n(fiu
+st	str		Set a tab in all rows, current column
+.ti -\n(fiu
+ta	str	(P)	Tab to next 8-position hardware tab stop
+.ti -\n(fiu
+tc	str		Entry of similar terminal \- must be last
+.ti -\n(fiu
+te	str		String to end programs that use \fBtermcap\fP
+.ti -\n(fiu
+ti	str		String to begin programs that use \fBtermcap\fP
+.ti -\n(fiu
+ts	str	(N)	Go to status line, column \fIn\^\fP
+.ti -\n(fiu
+UC	bool	(o)	Upper-case only
+.ti -\n(fiu
+uc	str		Underscore one character and move past it
+.ti -\n(fiu
+ue	str		End underscore mode
+.ti -\n(fiu
+ug	num		Number of garbage chars left by \fBus\fP or \fBue\fP (default 0)
+.ti -\n(fiu
+ul	bool		Underline character overstrikes
+.ti -\n(fiu
+UP	str	(NP*)	Move cursor up \fIn\^\fP lines
+.ti -\n(fiu
+up	str		Upline (cursor up)
+.ti -\n(fiu
+us	str		Start underscore mode
+.ti -\n(fiu
+vb	str		Visible bell (must not move cursor)
+.ti -\n(fiu
+ve	str		Make cursor appear normal (undo \fBvs\fP/\fBvi\fP)
+.ti -\n(fiu
+vi	str		Make cursor invisible
+.ti -\n(fiu
+vs	str		Make cursor very visible
+.ti -\n(fiu
+vt	num		Virtual terminal number (not supported on all systems)
+.ti -\n(fiu
+wi	str	(N)	Set current window
+.ti -\n(fiu
+ws	num		Number of columns in status line
+.ti -\n(fiu
+xb	bool		Beehive (f1=\s-2ESC\s0, f2=^C)
+.ti -\n(fiu
+xn	bool		Newline ignored after 80 cols (Concept)
+.ti -\n(fiu
+xo	bool		Terminal uses xoff/xon (\s-2DC3\s0/\s-2DC1\s0) handshaking
+.ti -\n(fiu
+xr	bool	(o)	Return acts like \fBce cr nl\fP (Delta Data)
+.ti -\n(fiu
+xs	bool		Standout not erased by overwriting (Hewlett-Packard)
+.ti -\n(fiu
+xt	bool		Tabs ruin, magic \fBso\fP char (Teleray 1061)
+.ti -\n(fiu
+xx	bool	(o)	Tektronix 4025 insert-line
+.in -\n(fiu
+.PP
+.B A Sample Entry
+.PP
+The following entry, which describes the Concept\-100, is among the more
+complex entries in the
+.B termcap\^
+file as of this writing.
+.PP
+.nf
+.if t .ta 8n +8n
+.if n .ta 2n +2n
+ca\||\|concept100\||\|c100\||\|concept\||\|c104\||\|concept100-4p\||\|HDS Concept\-100:\e
+	:al=3*\eE^R:am:bl=^G:cd=16*\eE^C:ce=16\eE^U:cl=2*^L:cm=\eEa%+ %+ :\e
+	:co#80:.cr=9^M:db:dc=16\eE^A:dl=3*\eE^B:do=^J:ei=\eE\e200:eo:im=\eE^P:in:\e
+	:ip=16*:is=\eEU\eEf\eE7\eE5\eE8\eEl\eENH\eEK\eE\e200\eEo&\e200\eEo\e47\eE:k1=\eE5:\e
+	:k2=\eE6:k3=\eE7:kb=^h:kd=\eE<:ke=\eEx:kh=\eE?:kl=\eE>:kr=\eE=:ks=\eEX:\e
+	:ku=\eE;:le=^H:li#24:mb=\eEC:me=\eEN\e200:mh=\eEE:mi:mk=\eEH:mp=\eEI:\e
+	:mr=\eED:nd=\eE=:pb#9600:rp=0.2*\eEr%.%+ :se=\eEd\eEe:sf=^J:so=\eEE\eED:\e
+	:.ta=8\et:te=\eEv    \e200\e200\e200\e200\e200\e200\eEp\er\en:\e
+	:ti=\eEU\eEv  8p\eEp\er:ue=\eEg:ul:up=\eE;:us=\eEG:\e
+	:vb=\eEk\e200\e200\e200\e200\e200\e200\e200\e200\e200\e200\e200\e200\e200\e200\eEK:\e
+	:ve=\eEw:vs=\eEW:vt#8:xn:\e
+	:bs:cr=^M:dC#9:dT#8:nl=^J:ta=^I:pt:
+.fi
+.PP
+Entries may continue onto multiple lines by giving a \e as the last
+character of a line, and empty fields
+may be included for readability (here between the last field on a line
+and the first field on the next).
+Comments may be included on lines beginning with \*(lq#\*(rq.
+.br
+.ne 5
+.PP
+.B Types of Capabilities
+.PP
+Capabilities in
+.B termcap\^
+are of three types: Boolean capabilities,
+which indicate particular features that the terminal has;
+numeric capabilities,
+giving the size of the display or the size of other attributes;
+and string capabilities,
+which give character sequences that can be used to perform particular
+terminal operations.
+All capabilities have two-letter codes.
+For instance, the fact that
+the Concept has
+.I automatic margins
+.RI ( i.e. ,
+an automatic return and linefeed
+when the end of a line is reached) is indicated by the Boolean capability
+.BR am .
+Hence the description of the Concept includes
+.BR am .
+.PP
+Numeric capabilities are followed by the character `#' then the value.
+In the example above
+.BR co ,
+which indicates the number of columns the display has,
+gives the value `80' for the Concept.
+.PP
+Finally, string-valued capabilities, such as
+.B ce
+(clear-to-end-of-line
+sequence) are given by the two-letter code, an `=', then a string
+ending at the next following `:'.
+A delay in milliseconds may appear after
+the `=' in such a capability,
+which causes padding characters to be supplied by
+.B tputs\^
+after the remainder of the string is sent to provide this delay.
+The delay can be either a number,
+.I e.g.
+`20', or a number followed by
+an `*',
+.IR i.e. ,
+`3*'.
+An `*' indicates that the padding required is proportional
+to the number of lines affected by the operation, and the amount given is
+the per-affected-line padding required.
+(In the case of insert-character,
+the factor is still the number of
+.I lines\^
+affected;
+this is always 1 unless the terminal has
+.B in
+and the software uses it.)
+When an `*' is specified, it is sometimes useful to give a delay of the form
+`3.5' to specify a delay per line to tenths of milliseconds.
+(Only one decimal place is allowed.)
+.PP
+A number of escape sequences are provided in the string-valued capabilities
+for easy encoding of control characters there.
+.B \eE
+maps to an \s-2ESC\s0
+character,
+.B ^X
+maps to a control-X for any appropriate X,
+and the sequences
+.B \en
+.B \er
+.B \et
+.B \eb
+.B \ef
+map to linefeed, return, tab, backspace, and formfeed, respectively.
+Finally, characters may be given as three octal digits after a
+.BR \e ,
+and the characters
+.B ^
+and
+.B \e
+may be given as
+.B \e^
+and
+.BR \e\e .
+If it is necessary to place a
+.B :
+in a capability it must be escaped in
+octal as
+.BR \e072 .
+If it is necessary to place a \s-2NUL\s0
+character in a string capability it
+must be encoded as
+.BR \e200 .
+(The routines that deal with
+.B termcap\^
+use C strings and strip the high bits of the output very late, so that
+a
+.B \e200
+comes out as a
+.B \e000
+would.)
+.PP
+Sometimes individual capabilities must be commented out.
+To do this, put a period before the capability name.
+For example, see the first
+.B cr
+and
+.B ta
+in the example above.
+.br
+.ne 5
+.PP
+.B Preparing Descriptions
+.PP
+We now outline how to prepare descriptions of terminals.
+The most effective way to prepare a terminal description is by imitating
+the description of a similar terminal in
+.B termcap\^
+and to build up a description gradually, using partial descriptions
+with
+.B vi\^
+to check that they are correct.
+Be aware that a very unusual terminal may expose deficiencies in
+the ability of the
+.B termcap\^
+file to describe it
+or bugs in
+.BR vi\^ .
+To easily test a new terminal description you can set the environment variable
+.B
+.SM TERMCAP
+to the absolute pathname of a file containing the description you are working
+on and programs will look there rather than in
+.BR /etc/termcap\^ .
+.B
+.SM TERMCAP
+can also be set to the
+.B termcap\^
+entry itself
+to avoid reading the file when starting up a program.
+.PP
+To get the padding for insert-line right
+(if the terminal manufacturer did not document it),
+a severe test is to use
+.B vi\^
+to edit
+.B /etc/passwd\^
+at 9600 baud, delete roughly 16 lines from the middle of the screen,
+then hit the `u' key several times quickly.
+If the display messes up, more padding is usually needed.
+A similar test can be used for insert-character.
+.br
+.ne 5
+.PP
+.B Basic Capabilities
+.PP
+The number of columns on each line of the display is given by the
+.B co
+numeric capability.
+If the display is a \s-1CRT\s0, then the
+number of lines on the screen is given by the
+.B li
+capability.
+If the display wraps around to the beginning of the next line when
+the cursor reaches the right margin, then it should have the
+.B am
+capability.
+If the terminal can clear its screen,
+the code to do this is given by the
+.B cl
+string capability.
+If the terminal overstrikes
+(rather than clearing the position when a character is overwritten),
+it should have the
+.B os
+capability.
+If the terminal is a printing terminal,
+with no soft copy unit,
+give it both
+.B hc
+and
+.BR os .
+.RB ( os
+applies to storage scope terminals,
+such as the Tektronix 4010 series,
+as well as to hard copy and
+.SM APL
+terminals.)
+If there is a code to move the cursor to the left edge of the current row,
+give this as
+.BR cr .
+(Normally this will be carriage-return,
+.BR ^M .)
+If there is a code to produce an audible signal (bell, beep,
+.IR etc.\^ ),
+give this as
+.BR bl .
+.PP
+If there is a code (such as backspace)
+to move the cursor one position to the left,
+that capability should be given as
+.BR le .
+Similarly,
+codes to move to the right, up, and down
+should be given as
+.BR nd ,
+.BR up ,
+and
+.BR do ,
+respectively.
+These
+.I local cursor motions\^
+should not alter the text they pass over;
+for example, you would not normally use
+\*(lqnd=\ \*(rq
+unless the terminal has the
+.B os
+capability,
+because the space would erase the character moved over.
+.PP
+A very important point here is that the local cursor motions encoded
+in
+.B termcap\^
+have undefined behavior at the left and top edges of a
+.SM CRT
+display.
+Programs should never attempt to backspace around the left edge,
+unless
+.B bw
+is given, and never attempt to go up off the top
+using local cursor motions.
+.PP
+In order to scroll text up,
+a program goes to the bottom left corner of the screen and sends the
+.B sf
+(index) string.
+To scroll text down,
+a program goes to the top left corner of the screen and sends the
+.B sr
+(reverse index) string.
+The strings
+.B sf
+and
+.B sr
+have undefined behavior
+when not on their respective corners of the screen.
+Parameterized versions of the scrolling sequences are
+.B SF
+and
+.BR SR ,
+which have the same semantics as
+.B sf
+and
+.B sr
+except that they take one parameter
+and scroll that many lines.
+They also have undefined behavior
+except at the appropriate corner of the screen.
+.PP
+The
+.B am
+capability tells whether the cursor sticks at the right
+edge of the screen when text is output there,
+but this does not necessarily apply to
+.B nd
+from the last column.
+Leftward local motion is defined from the left edge only when
+.B bw
+is given; then an
+.B le
+from the left edge will move to the right edge of the previous row.
+This is useful for drawing a box around the edge of the screen,
+for example.
+If the terminal has switch-selectable automatic margins,
+the
+.B termcap\^
+description usually assumes that this feature is on,
+.IR i.e. ,
+.BR am .
+If the terminal has a command
+that moves to the first column of the next line,
+that command can be given as
+.B nw
+(newline).
+It is permissible for this to clear the remainder of the current line,
+so if the terminal has no correctly-working \s-2CR\s0 and \s-2LF\s0
+it may still be possible to craft a working
+.B nw
+out of one or both of them.
+.PP
+These capabilities suffice to describe hardcopy and \*(lqglass-tty\*(rq terminals.
+Thus the Teletype model 33 is described as
+.PP
+.nf
+	T3\||\|tty33\||\|33\||\|tty\||\|Teletype model 33:\e
+		:bl=^G:co#72:cr=^M:do=^J:hc:os:
+.fi
+.PP
+and the Lear Siegler \s-1ADM\s0\-3 is described as
+.PP
+.nf
+	l3\||\|adm3\||\|3\||\|LSI \s-1ADM\s0-3:\e
+		:am:bl=^G:cl=^Z:co#80:cr=^M:do=^J:le=^H:li#24:sf=^J:
+.fi
+.br
+.ne 5
+.PP
+.B Parameterized Strings
+.PP
+Cursor addressing and other strings requiring parameters
+are described by a
+parameterized string capability, with 
+.BR printf\^ (3)-like
+escapes
+.B %x
+in it,
+while other characters are passed through unchanged.
+For example, to address the cursor the
+.B cm
+capability is given, using two parameters: the row and column to move to.
+(Rows and columns are numbered from zero and refer to the physical screen
+visible to the user, not to any unseen memory.
+If the terminal has memory-relative cursor addressing,
+that can be indicated by an analogous
+.B CM
+capability.)
+.PP
+The
+.B %
+encodings have the following meanings:
+.PP
+.in +16n
+.ta +8n
+.ti -8n
+%%	output `%'
+.ti -8n
+%d	output value as in \fBprintf\^\fP %d
+.ti -8n
+%2	output value as in \fBprintf\^\fP %2d
+.ti -8n
+%3	output value as in \fBprintf\^\fP %3d
+.ti -8n
+%.	output value as in \fBprintf\^\fP %c
+.ti -8n
+%+\fIx\fP	add \fIx\^\fP to value, then do %.
+.ti -8n
+%>\fIxy\fP	if value > \fIx\^\fP then add \fIy\^\fP, no output
+.ti -8n
+%r	reverse order of two parameters, no output
+.ti -8n
+%i	increment by one, no output
+.ti -8n
+%n	exclusive-or all parameters with 0140 (Datamedia 2500)
+.ti -8n
+%B	BCD (16*(value/10)) + (value%10), no output
+.ti -8n
+%D	Reverse coding (value \- 2*(value%16)), no output (Delta Data)
+.ti -16n
+.fi
+.PP
+Consider the Hewlett-Packard 2645, which, to get to row 3 and column 12, needs
+to be sent \*(lq\eE&a12c03Y\*(rq padded for 6 milliseconds.
+Note that the order
+of the row and column coordinates is reversed here
+and that the row and column
+are sent as two-digit integers.
+Thus its
+.B cm
+capability is \*(lqcm=6\eE&%r%2c%2Y\*(rq.
+.PP
+The Microterm
+.SM ACT-IV
+needs the current row and column sent
+simply encoded in binary
+preceded by a
+.BR ^T ,
+\*(lqcm=^T%.%.\*(rq.
+Terminals that use \*(lq%.\*(rq need to be able to
+backspace the cursor
+.RB ( le )
+and to move the cursor up one line on the screen
+.RB ( up ).
+This is necessary because it is not always safe to transmit
+.BR \en ,
+.BR ^D ,
+and
+.BR \er ,
+as the system may change or discard them.
+(Programs using
+.B termcap\^
+must set terminal modes so that tabs are not expanded, so
+.B \et
+is safe to send.
+This turns out to be essential for the Ann Arbor 4080.)
+.PP
+A final example is the Lear Siegler \s-1ADM\s0\-3a,
+which offsets row and column
+by a blank character, thus \*(lqcm=\eE=%+ %+ \*(rq.
+.PP
+Row or column absolute cursor addressing
+can be given as single parameter capabilities
+.B ch
+(horizontal position absolute) and
+.B cv
+(vertical position absolute).
+Sometimes these are shorter than the more general two-parameter sequence
+(as with the Hewlett-Packard 2645) and can be used in preference to
+.BR cm .
+If there are parameterized local motions
+.RI ( e.g. ,
+move
+.I n\^
+positions to the right)
+these can be given as
+.BR DO ,
+.BR LE ,
+.BR RI ,
+and
+.B UP
+with a single parameter indicating how many positions to move.
+These are primarily useful if the terminal does not have
+.BR cm ,
+such as the Tektronix 4025.
+.br
+.ne 5
+.PP
+.B Cursor Motions
+.PP
+If the terminal has a fast way to home the cursor
+(to the very upper left corner of the screen), this can be given as
+.BR ho .
+Similarly, a fast way of getting to the lower left-hand corner
+can be given as
+.BR ll ;
+this may involve going up with
+.B up
+from the home position,
+but a program should never do this itself (unless
+.B ll
+does), because it can
+make no assumption about the effect of moving up from the home position.
+Note that the home position is the same as
+cursor address (0,0): to the top left corner of the screen, not of memory.
+(Therefore, the \*(lq\eEH\*(rq sequence on Hewlett-Packard terminals
+cannot be used for
+.BR ho .)
+.br
+.ne 5
+.PP
+.B Area Clears
+.PP
+If the terminal can clear from the current position to the end of the
+line, leaving the cursor where it is, this should be given as
+.BR ce .
+If the terminal can clear from the current position to the end of the
+display, this should be given as
+.BR cd .
+.B cd
+must only be invoked from the first column of a line.
+(Therefore,
+it can be simulated by a request to delete a large number of lines,
+if a true
+.B cd
+is not available.)
+.br
+.ne 5
+.PP
+.B Insert/Delete Line
+.PP
+If the terminal can open a new blank line
+before the line containing the cursor,
+this should be given as
+.BR al ;
+this must be invoked only from the first
+position of a line.
+The cursor must then appear at the left of the newly blank line.
+If the terminal can delete the line that the cursor is on, this
+should be given as
+.BR dl ;
+this must only be used from the first position on
+the line to be deleted.
+Versions of
+.B al
+and
+.B dl
+which take a single parameter
+and insert or delete that many lines
+can be given as
+.B AL
+and
+.BR DL .
+If the terminal has a settable scrolling region
+(like the VT100),
+the command to set this can be described with the
+.B cs
+capability,
+which takes two parameters: the top and bottom lines of the scrolling region.
+The cursor position is, alas, undefined after using this command.
+It is possible to get the effect of insert or delete line
+using this command \(em the
+.B sc
+and
+.B rc
+(save and restore cursor) commands are also useful.
+Inserting lines at the top or bottom of the screen can also be done using
+.B sr
+or
+.B sf
+on many terminals without a true insert/delete line,
+and is often faster even on terminals with those features.
+.PP
+If the terminal has the ability to define a window as part of memory
+which all commands affect, it should be given as the parameterized string
+.BR wi .
+The four parameters are the starting and ending lines in memory
+and the starting and ending columns in memory, in that order.
+(This
+.B terminfo\^
+capability is described for completeness.
+It is unlikely that any
+.BR termcap\^ -using
+program will support it.)
+.PP
+If the terminal can retain display memory above the screen, then the
+.B da
+capability should be given;
+if display memory can be retained
+below, then
+.B db
+should be given.
+These indicate
+that deleting a line or scrolling may bring non-blank lines up from below
+or that scrolling back with
+.B sr
+may bring down non-blank lines.
+.br
+.ne 5
+.PP
+.B Insert/Delete Character
+.PP
+There are two basic kinds of intelligent terminals with respect to
+insert/delete character that can be described using
+.BR termcap\^ .
+The most common insert/delete character operations affect only the characters
+on the current line and shift characters off the end of the line rigidly.
+Other terminals, such as the Concept\-100 and the Perkin Elmer Owl, make
+a distinction between typed and untyped blanks on the screen, shifting
+upon an insert or delete only to an untyped blank on the screen which is
+either eliminated or expanded to two untyped blanks.
+You can determine
+the kind of terminal you have by clearing the screen then typing
+text separated by cursor motions.
+Type \*(lqabc\ \ \ \ def\*(rq using local
+cursor motions (not spaces) between the \*(lqabc\*(rq and the \*(lqdef\*(rq.
+Then position the cursor before the \*(lqabc\*(rq and put the terminal in insert
+mode.
+If typing characters causes the rest of the line to shift
+rigidly and characters to fall off the end, then your terminal does
+not distinguish between blanks and untyped positions.
+If the \*(lqabc\*(rq
+shifts over to the \*(lqdef\*(rq which then move together around the end of the
+current line and onto the next as you insert, then you have the second type of
+terminal and should give the capability \fBin\fP, which stands for
+\*(lqinsert null\*(rq.
+While these are two logically separate attributes
+(one line
+.I vs.
+multi-line insert mode,
+and special treatment of untyped spaces),
+we have seen no terminals whose insert
+mode cannot be described with the single attribute.
+.PP
+.B Termcap\^
+can describe both terminals that have an insert mode and terminals
+that send a simple sequence to open a blank position on the current line.
+Give as
+.B im
+the sequence to get into insert mode.
+Give as
+.B ei
+the sequence to leave insert mode.
+Now give as
+.B ic
+any sequence that needs to be sent just before
+each character to be inserted.
+Most terminals with a true insert mode
+will not give
+.BR ic ;
+terminals that use a sequence to open a screen
+position should give it here.
+(If your terminal has both,
+insert mode is usually preferable to
+.BR ic .
+Do not give both unless the terminal actually requires both to be used
+in combination.)
+If post-insert padding is needed, give this as a number of milliseconds
+in
+.B ip
+(a string option).
+Any other sequence that may need to be
+sent after insertion of a single character can also be given in
+.BR ip .
+If your terminal needs to be placed into an `insert mode'
+and needs a special code preceding each inserted character,
+then both
+.BR im / ei
+and
+.B ic
+can be given, and both will be used.
+The
+.B IC
+capability, with one parameter
+.IR n\^ ,
+will repeat the effects of
+.B ic
+.I n\^
+times.
+.PP
+It is occasionally necessary to move around while in insert mode
+to delete characters on the same line
+.RI ( e.g. ,
+if there is a tab after
+the insertion position).
+If your terminal allows motion while in
+insert mode, you can give the capability
+.B mi
+to speed up inserting
+in this case.
+Omitting
+.B mi
+will affect only speed.
+Some terminals
+(notably Datamedia's) must not have
+.B mi
+because of the way their
+insert mode works.
+.PP
+Finally, you can specify
+.B dc
+to delete a single character,
+.B DC
+with one parameter
+.I n\^
+to delete
+.I n\^
+characters,
+and delete mode by giving
+.B dm
+and
+.B ed
+to enter and exit delete mode
+(which is any mode the terminal needs to be placed in for
+.B dc
+to work).
+.br
+.ne 5
+.PP
+.B Highlighting, Underlining, and Visible Bells
+.PP
+If your terminal has one or more kinds of display attributes,
+these can be represented in a number of different ways.
+You should choose one display form as
+.IR "standout mode" ,
+representing a good high-contrast, easy-on-the-eyes format
+for highlighting error messages and other attention getters.
+(If you have a choice, reverse video plus half-bright is good,
+or reverse video alone.)
+The sequences to enter and exit standout mode
+are given as
+.B so
+and
+.BR se ,
+respectively.
+If the code to change into or out of standout
+mode leaves one or even two blank spaces or garbage characters on the screen,
+as the TVI 912 and Teleray 1061 do,
+then
+.B sg
+should be given to tell how many characters are left.
+.PP
+Codes to begin underlining and end underlining can be given as
+.B us
+and
+.BR ue ,
+respectively.
+Underline mode change garbage is specified by
+.BR ug ,
+similar to
+.BR sg .
+If the terminal has a code to underline the current character and move
+the cursor one position to the right, 
+such as the Microterm Mime,
+this can be given as
+.BR uc .
+.PP
+Other capabilities to enter various highlighting modes include
+.B mb
+(blinking),
+.B md
+(bold or extra bright),
+.B mh
+(dim or half-bright),
+.B mk
+(blanking or invisible text),
+.B mp
+(protected),
+.B mr
+(reverse video),
+.B me
+(turn off
+.I all
+attribute modes),
+.B as
+(enter alternate character set mode), and
+.B ae
+(exit alternate character set mode).
+Turning on any of these modes singly may or may not turn off other modes.
+.PP
+If there is a sequence to set arbitrary combinations of mode,
+this should be given as
+.B sa
+(set attributes), taking 9 parameters.
+Each parameter is either 0 or 1,
+as the corresponding attributes is on or off.
+The 9 parameters are, in order: standout, underline, reverse, blink,
+dim, bold, blank, protect, and alternate character set.
+Not all modes need be supported by
+.BR sa ,
+only those for which corresponding attribute commands exist.
+(It is unlikely that a
+.BR termcap\^ -using
+program will support this capability, which is defined for compatibility
+with
+.BR terminfo\^ .)
+.PP
+Terminals with the \*(lqmagic cookie\*(rq glitches
+.RB ( sg
+and
+.BR ug ),
+rather than maintaining extra attribute bits for each character cell,
+instead deposit special \*(lqcookies\*(rq,
+or \*(lqgarbage characters\*(rq,
+when they receive mode-setting sequences,
+which affect the display algorithm.
+.PP
+Some terminals,
+such as the Hewlett-Packard 2621,
+automatically leave standout
+mode when they move to a new line or when the cursor is addressed.
+Programs using standout mode
+should exit standout mode on such terminals
+before moving the cursor or sending a newline.
+On terminals where this is not a problem,
+the
+.B ms
+capability should be present
+to say that this overhead is unnecessary.
+.PP
+If the terminal has
+a way of flashing the screen to indicate an error quietly
+(a bell replacement),
+this can be given as
+.BR vb ;
+it must not move the cursor.
+.PP
+If the cursor needs to be made more visible than normal
+when it is not on the bottom line
+(to change, for example, a non-blinking underline into an easier-to-find
+block or blinking underline),
+give this sequence as
+.BR vs .
+If there is a way to make the cursor completely invisible, give that as
+.BR vi .
+The capability
+.BR ve ,
+which undoes the effects of both of these modes,
+should also be given.
+.PP
+If your terminal correctly displays underlined characters
+(with no special codes needed)
+even though it does not overstrike,
+then you should give the capability
+.BR ul .
+If overstrikes are erasable with a blank,
+this should be indicated by giving
+.BR eo .
+.br
+.ne 5
+.PP
+.B Keypad
+.PP
+If the terminal has a keypad that transmits codes when the keys are pressed,
+this information can be given.
+Note that it is not possible to handle
+terminals where the keypad only works in local mode
+(this applies, for example, to the unshifted Hewlett-Packard 2621 keys).
+If the keypad can be set to transmit or not transmit,
+give these codes as
+.B ks
+and
+.BR ke .
+Otherwise the keypad is assumed to always transmit.
+The codes sent by the left-arrow, right-arrow, up-arrow, down-arrow,
+and home keys can be given as
+.BR kl ,
+.BR kr ,
+.BR ku ,
+.BR kd ,
+and
+.BR kh ,
+respectively.
+If there are function keys such as f0, f1, ..., f9, the codes they send
+can be given as
+.BR k0 ,
+.BR k1 , "" ...,
+.BR k9 .
+If these keys have labels other than the default f0 through f9, the labels
+can be given as
+.BR l0 ,
+.BR l1 , "" ...,
+.BR l9 .
+The codes transmitted by certain other special keys can be given:
+.B kH
+(home down),
+.B kb
+(backspace),
+.B ka
+(clear all tabs),
+.B kt
+(clear the tab stop in this column),
+.B kC
+(clear screen or erase),
+.B kD
+(delete character),
+.B kL
+(delete line),
+.B kM
+(exit insert mode),
+.B kE
+(clear to end of line),
+.B kS
+(clear to end of screen),
+.B kI
+(insert character or enter insert mode),
+.B kA
+(insert line),
+.B kN
+(next page),
+.B kP
+(previous page),
+.B kF
+(scroll forward/down),
+.B kR
+(scroll backward/up), and
+.B kT
+(set a tab stop in this column).
+In addition, if the keypad has a 3 by 3 array of keys
+including the four arrow keys, then the other five keys can be given as
+.BR K1 ,
+.BR K2 ,
+.BR K3 ,
+.BR K4 ,
+and
+.BR K5 .
+These keys are useful when the effects of a 3 by 3 directional pad are needed.
+The obsolete
+.B ko
+capability formerly used to describe \*(lqother\*(rq function keys has been
+completely supplanted by the above capabilities.
+.PP
+The
+.B ma
+entry is also used to indicate arrow keys on terminals that have
+single-character arrow keys.
+It is obsolete but still in use in
+version 2 of
+.B vi\^
+which must be run on some minicomputers due to
+memory limitations.
+This field is redundant with
+.BR kl ,
+.BR kr ,
+.BR ku ,
+.BR kd ,
+and
+.BR kh .
+It consists of groups of two characters.
+In each group, the first character is what an arrow key sends, and the
+second character is the corresponding
+.B vi\^
+command.
+These commands are
+.B h
+for
+.BR kl ,
+.B j
+for
+.BR kd ,
+.B k
+for
+.BR ku ,
+.B l
+for
+.BR kr ,
+and
+.B H
+for
+.BR kh .
+For example, the Mime would have \*(lqma=^Hh^Kj^Zk^Xl\*(rq
+indicating arrow keys left (^H), down (^K), up (^Z), and right (^X).
+(There is no home key on the Mime.)
+.br
+.ne 5
+.PP
+.B Tabs and Initialization
+.PP
+If the terminal needs to be in a special mode when running
+a program that uses these capabilities,
+the codes to enter and exit this mode can be given as
+.B ti
+and
+.BR te .
+This arises, for example, from terminals like the Concept with more than
+one page of memory.
+If the terminal has only memory-relative cursor addressing and not
+screen-relative cursor addressing,
+a screen-sized window must be fixed into
+the display for cursor addressing to work properly.
+This is also used for the Tektronix 4025, where
+.B ti
+sets the command character to be the one used by
+.BR termcap\^ .
+.PP
+Other capabilities
+include
+.BR is ,
+an initialization string for the terminal,
+and
+.BR if ,
+the name of a file containing long initialization strings.
+These strings are expected to set the terminal into modes
+consistent with the rest of the
+.B termcap\^
+description.
+They are normally sent to the terminal by the
+.B tset\^
+program each time the user logs in.
+They will be printed in the following order:
+.BR is ;
+setting tabs using
+.B ct
+and
+.BR st ;
+and finally
+.BR if .
+.RI ( Terminfo\^
+uses
+.B i1-i2
+instead of
+.B is
+and runs the program
+.B iP
+and prints
+.B i3
+after the other initializations.)
+A pair of sequences that does a harder reset from a totally unknown state
+can be analogously given as
+.B rs
+and
+.BR if .
+These strings are output by the
+.B reset\^
+program, which is used when the terminal gets into a wedged state.
+.RI ( Terminfo\^
+uses
+.B r1-r3
+instead of
+.BR rs .)
+Commands are normally placed in
+.B rs
+and
+.B rf
+only if they produce annoying effects on the screen and are not necessary
+when logging in.
+For example, the command to set the VT100 into 80-column mode
+would normally be part of
+.BR is ,
+but it causes an annoying glitch of the screen and is not normally needed
+since the terminal is usually already in 80-column mode.
+.PP
+If the terminal has hardware tabs,
+the command to advance to the next tab stop can be given as
+.B ta
+(usually
+.BR ^I ).
+A \*(lqbacktab\*(rq command which moves leftward to the previous tab stop
+can be given as
+.BR bt .
+By convention,
+if the terminal driver modes indicate that tab stops are being expanded
+by the computer rather than being sent to the terminal,
+programs should not use
+.B ta
+or
+.B bt
+even if they are present,
+since the user may not have the tab stops properly set.
+If the terminal has hardware tabs that are initially set every
+.I n\^
+positions when the terminal is powered up, then the numeric parameter
+.B it
+is given, showing the number of positions between tab stops.
+This is normally used by the
+.B tset\^
+command to determine whether to set the driver mode for hardware tab
+expansion, and whether to set the tab stops.
+If the terminal has tab stops that can be saved in nonvolatile memory, the
+.B termcap\^
+description can assume that they are properly set.
+.PP
+If there are commands to set and clear tab stops, they can be given as
+.B ct
+(clear all tab stops) and
+.B st
+(set a tab stop in the current column of every row).
+If a more complex sequence is needed to set the tabs than can be
+described by this, the sequence can be placed in
+.B is
+or
+.BR if .
+.br
+.ne 5
+.PP
+.B Delays
+.PP
+Certain capabilities control padding in the terminal driver.
+These are primarily needed by hardcopy terminals and are used by the
+.B tset\^
+program to set terminal driver modes appropriately.
+Delays embedded in the capabilities
+.BR cr ,
+.BR sf ,
+.BR le ,
+.BR ff ,
+and
+.B ta
+will cause the appropriate delay bits to be set in the terminal driver.
+If
+.B pb
+(padding baud rate) is given, these values can be ignored at baud rates
+below the value of
+.BR pb .
+For 4.2BSD
+.BR tset\^ ,
+the delays are given as numeric capabilities
+.BR dC ,
+.BR dN ,
+.BR dB ,
+.BR dF ,
+and
+.BR dT
+instead.
+.br
+.ne 5
+.PP
+.B Miscellaneous
+.PP
+If the terminal requires other than a \s-2NUL\s0 (zero) character as a pad,
+this can be given as
+.BR pc .
+Only the first character of the
+.B pc
+string is used.
+.PP
+If the terminal has commands to save and restore the position of the
+cursor, give them as
+.B sc
+and
+.BR rc .
+.PP
+If the terminal has an extra \*(lqstatus line\*(rq that is not normally used by
+software, this fact can be indicated.
+If the status line is viewed as an extra line below the bottom line,
+then the capability
+.B hs
+should be given.
+Special strings to go to a position in the status line and to return
+from the status line can be given as
+.B ts
+and
+.BR fs .
+.RB ( fs
+must leave the cursor position in the same place that it was before
+.BR ts .
+If necessary, the
+.B sc
+and
+.B rc
+strings can be included in
+.B ts
+and
+.B fs
+to get this effect.)
+The capability
+.B ts
+takes one parameter, which is the column number of the status line
+to which the cursor is to be moved.
+If escape sequences and other special commands such as tab work while in
+the status line, the flag
+.B es
+can be given.
+A string that turns off the status line (or otherwise erases its contents)
+should be given as
+.BR ds .
+The status line is normally assumed to be the same width as the
+rest of the screen,
+.IR i.e. ,
+.BR co .
+If the status line is a different width (possibly because the terminal
+does not allow an entire line to be loaded), then its width in columns
+can be indicated with the numeric parameter
+.BR ws .
+.PP
+If the terminal can move up or down half a line, this can be
+indicated with
+.B hu
+(half-line up) and
+.B hd
+(half-line down).
+This is primarily useful for superscripts and subscripts on hardcopy
+terminals.
+If a hardcopy terminal can eject to the next page (form feed),
+give this as
+.B ff
+(usually
+.BR ^L ).
+.PP
+If there is a command to repeat a given character a given number of times
+(to save time transmitting a large number of identical characters),
+this can be indicated with the parameterized string
+.BR rp .
+The first parameter is the character to be repeated and the second is
+the number of times to repeat it.
+(This is a
+.B terminfo\^
+feature that is unlikely to be supported by a program that uses
+.BR termcap\^ .)
+.PP
+If the terminal has a settable command character, such as the
+Tektronix 4025, this can be indicated with
+.BR CC .
+A prototype command character is chosen which is used in all capabilities.
+This character is given in the
+.B CC
+capability to identify it.
+The following convention is supported on some UNIX systems:
+The environment is to be searched for a
+.B
+.SM CC
+variable,
+and if found,
+all occurrences of the prototype character are replaced by the character
+in the environment variable.
+This use of the
+.B
+.SM CC
+environment variable
+is a very bad idea, as it conflicts with
+.BR make\^ (1).
+.PP
+Terminal descriptions that do not represent a specific kind of known
+terminal, such as
+.BR switch\^ ,
+.BR dialup\^ ,
+.BR patch\^ ,
+and
+.BR network\^ ,
+should include the
+.B gn
+(generic) capability so that programs can complain that they do not know
+how to talk to the terminal.
+(This capability does not apply to
+.I virtual\^
+terminal descriptions for which the escape sequences are known.)
+.PP
+If the terminal uses xoff/xon (\s-2DC3\s0/\s-2DC1\s0)
+handshaking for flow control, give
+.BR xo .
+Padding information should still be included so that routines can make
+better decisions about costs, but actual pad characters will not be
+transmitted.
+.PP
+If the terminal has a \*(lqmeta key\*(rq which acts as a shift key, setting the
+8th bit of any character transmitted, then this fact can be indicated with
+.BR km .
+Otherwise, software will assume that the 8th bit is parity and it will
+usually be cleared.
+If strings exist to turn this \*(lqmeta mode\*(rq on and off, they can be given as
+.B mm
+and
+.BR mo .
+.PP
+If the terminal has more lines of memory than will fit on the screen at once,
+the number of lines of memory can be indicated with
+.BR lm .
+An explicit value of 0 indicates that the number of lines is not fixed,
+but that there is still more memory than fits on the screen.
+.PP
+If the terminal is one of those supported by the UNIX system virtual
+terminal protocol, the terminal number can be given as
+.BR vt .
+.PP
+Media copy strings which control an auxiliary printer
+connected to the terminal can be given as
+.BR ps :
+print the contents of the screen;
+.BR pf :
+turn off the printer; and
+.BR po :
+turn on the printer.
+When the printer is on, all text sent to the terminal will be sent to the
+printer.
+It is undefined whether the text is also displayed on the terminal screen
+when the printer is on.
+A variation
+.B pO
+takes one parameter and leaves the printer on for as many characters as the
+value of the parameter, then turns the printer off.
+The parameter should not exceed 255.
+All text, including
+.BR pf ,
+is transparently passed to the printer while
+.B pO
+is in effect.
+.PP
+Strings to program function keys can be given as
+.BR pk ,
+.BR pl ,
+and
+.BR px .
+Each of these strings takes two parameters: the function key number
+to program (from 0 to 9) and the string to program it with.
+Function key numbers out of this range may program undefined keys
+in a terminal-dependent manner.
+The differences among the capabilities are that
+.B pk
+causes pressing the given key to be the same as the user typing the given
+string;
+.B pl
+causes the string to be executed by the terminal in local mode;
+and
+.B px
+causes the string to be transmitted to the computer.
+Unfortunately, due to lack of a definition for string parameters in
+.BR termcap\^ ,
+only
+.B terminfo\^
+supports these capabilities.
+.br
+.ne 5
+.PP
+.B Glitches and Braindamage
+.PP
+Hazeltine terminals, which do not allow `~' characters to be displayed,
+should indicate
+.BR hz .
+.PP
+The
+.B nc
+capability, now obsolete, formerly indicated Datamedia terminals,
+which echo
+.B \er \en
+for
+carriage return then ignore a following linefeed.
+.PP
+Terminals that ignore a linefeed immediately after an
+.B am
+wrap, such as the Concept, should indicate
+.BR xn .
+.PP
+If
+.B ce
+is required to get rid of standout
+(instead of merely writing normal text on top of it),
+.B xs
+should be given.
+.PP
+Teleray terminals, where tabs turn all characters moved over to blanks,
+should indicate
+.B xt
+(destructive tabs).
+This glitch is also taken to mean that it is not possible
+to position the cursor on top of a \*(lqmagic cookie\*(rq, and that
+to erase standout mode it is necessary to use delete and insert line.
+.PP
+The Beehive Superbee, which is unable to correctly transmit the
+\s-2ESC\s0 or ^C characters, has
+.BR xb ,
+indicating that the \*(lqf1\*(rq key is used for \s-2ESC\s0 and \*(lqf2\*(rq for ^C.
+(Only certain Superbees have this problem, depending on the ROM.)
+.PP
+Other specific terminal problems may be corrected by adding more
+capabilities of the form \fBx\fIx\^\fP.
+.br
+.ne 5
+.PP
+.B Similar Terminals
+.PP
+If there are two very similar terminals,
+one can be defined as being just like the other with certain exceptions.
+The string capability
+.B tc
+can be given
+with the name of the similar terminal.
+This capability must be
+.IR last\^ ,
+and the combined length of the entries
+must not exceed 1024.
+The capabilities given before
+.B tc
+override those in the terminal type invoked by
+.BR tc .
+A capability can be canceled by placing
+.B xx@
+to the left of the
+.B tc
+invocation, where
+.I xx\^
+is the capability.
+For example, the entry
+.PP
+	hn\||\|2621\-nl:ks@:ke@:tc=2621:
+.PP
+defines a \*(lq2621\-nl\*(rq that does not have the
+.B ks
+or
+.B ke
+capabilities,
+hence does not turn on the function key labels when in visual mode.
+This is useful for different modes for a terminal, or for different
+user preferences.
+.SH AUTHOR
+William Joy
+.br
+Mark Horton added underlining and keypad support
+.SH FILES
+.TP 15
+.B /etc/termcap
+file containing terminal descriptions
+.B /usr/etc/termcap
+file containing more terminal descriptions (Minix-vmd)
+.SH SEE ALSO
+.BR elvis (1),
+.BR more (1),
+.BR termcap (3),
+.BR printf (3).
+.SH "CAVEATS AND BUGS"
+Lines and columns are now stored by the kernel as well as in the termcap
+entry.
+Most programs now use the kernel information primarily; the information
+in this file is used only if the kernel does not have any information.
+.PP
+Not all programs support all entries.
+.PP
+The MINIX 3
+.BR termcap (3)
+does not understand everything described here, unlike the one Minix-vmd uses.
Index: /trunk/minix/man/man5/ttytab.5
===================================================================
--- /trunk/minix/man/man5/ttytab.5	(revision 9)
+++ /trunk/minix/man/man5/ttytab.5	(revision 9)
@@ -0,0 +1,95 @@
+.TH TTYTAB
+.SH NAME
+ttytab \- table of login terminals
+.SH SYNOPSIS
+.B /etc/ttytab
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+The
+.B ttytab
+file lists all the terminal devices that one can login on.  It is a simple
+text file that contains lines of the form:
+.PP
+.RS
+.ft I
+.ta +\w'namennn'u +\w'typennn'u +\w'"getty"nnn'u
+name	type	"getty"	"init"
+.DT
+.ft R
+.RE
+.PP
+The
+.I name
+and
+.I type
+fields are simple words,
+.I name
+is the name of the terminal device with
+.B /dev
+stripped off, and
+.I type
+tells the type of terminal to initialize the
+.B TERM
+environment variable.
+.PP
+The
+.I getty
+and
+.I init
+fields may name commands that are run to allow one to login on the line, or
+to initialize the line.  Both these fields may be more than one word if
+the whole field is enclosed in double quotes.
+.I Getty
+is usually simply the word
+.BR getty ,
+the command that prints a system identification banner and allows on to type
+a name to log in.
+.I Init
+is usually an
+.B stty
+command to set the baud rate and parity of a serial line.
+.PP
+The
+.I init
+field may be omitted to indicate that no initialization is necessary, and the
+.I getty
+field may be left out to not start a login process.  Terminals should not be
+left out, because their place in the
+.B ttytab
+file determines their slot number as returned by
+.BR ttyslot (3).
+.PP
+Comments (introduced by #) and empty lines are ignored.
+.SH EXAMPLE
+A
+.B ttytab
+for the console, two serial lines, and a pseudo tty entry:
+.PP
+.RS
+.nf
+.ta +\w'consolennn'u +\w'networknnn'u +\w'gettynnnn'u
+console	minix	getty
+tty00	vt100	getty	"stty 9600"
+tty01	dialup	getty	"stty 38400"
+ttyp0	network
+.DT
+.fi
+.RE
+.SH ENVIRONMENT
+.TP 15n
+.B TERM
+Terminal type
+.SH NOTES
+It is customary to set the type to
+.B dialup
+for a dialin line.  One can check for that name in one's
+.BR .profile .
+.SH "SEE ALSO"
+.BR getttyent (3),
+.BR ttyslot (3),
+.BR init (8).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man5/utmp.5
===================================================================
--- /trunk/minix/man/man5/utmp.5	(revision 9)
+++ /trunk/minix/man/man5/utmp.5	(revision 9)
@@ -0,0 +1,70 @@
+.TH UTMP 5
+.SH NAME
+utmp, wtmp \- logged in users, login and logout history
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <utmp.h>
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+The files
+.B /etc/utmp
+and
+.B /usr/adm/wtmp
+respectively contain the currently logged in users, and the history of
+logins and logouts.
+.PP
+Each file is an array of the following structure defined in <utmp.h>:
+.PP
+.nf
+.ta +5n +15n +15n
+struct utmp {
+	char	ut_user[8];	/* user name */
+	char	ut_line[12];	/* terminal name */
+	char	ut_host[16];	/* host name, when remote */
+	time_t	ut_time;	/* login/logout time */
+};
+.SP
+.ta +15n
+#define ut_name ut_user	/* for compatibility with other systems */
+.fi
+.DT
+.PP
+The structure contains more fields than those listed, but they are only of
+interest to
+.B init
+and
+.BR login .
+Note that the
+.B ut_name
+field is a compatibility alias for
+.BR ut_user ,
+it is actually better to use it.
+.PP
+A login entry is completely specified.  A logout entry has a null string for
+.BR ut_name .
+A shutdown or reboot entry has an
+.B ut_line
+field containing a "~" (tilde).  The
+.B ut_name
+field is usually the name of the program that did the shutdown, or "reboot"
+at reboot.  This is a bit confusing, but note that there should always be
+two such entries.  If you see just one entry then the system has crashed, if
+you see two entries then the system was properly shut down and later
+rebooted.
+.SH FILES
+.TP 25n
+.B /etc/utmp
+Currently logged in users.
+.TP
+.B /usr/adm/wtmp
+History of logins and logouts.
+.SH "SEE ALSO"
+.BR who (1),
+.BR ttyslot (3).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man5/whatis.5
===================================================================
--- /trunk/minix/man/man5/whatis.5	(revision 9)
+++ /trunk/minix/man/man5/whatis.5	(revision 9)
@@ -0,0 +1,57 @@
+.TH WHATIS 5
+.SH NAME
+whatis \- database of online manual pages
+.SH SYNOPSIS
+.B /usr/man/*/whatis
+.br
+.B /usr/man/whatis
+.SH DESCRIPTION
+The
+.B whatis
+file in each manual page directory is a database of titles for manual pages.
+This database is used by
+.BR man (1)
+to map titles to manual pages names.  The database is created by
+.BR makewhatis (1)
+from the NAME sections of the manual pages.
+.PP
+The NAME secions must be simple lines with no troff fluff but one
+backslash like these two:
+.PP
+.RS
+whatis \e\- database of online manual pages
+.br
+cawf, nroff \e\- C version of the nroff-like, Amazingly Workable (text)
+Formatter
+.RE
+.PP
+These lines are transformed by
+.B makewhatis
+to these two lines for the database:
+.PP
+.RS
+cawf, nroff (1) \- C version of the nroff-like, Amazingly Workable (text)
+Formatter
+.br
+whatis (5) \- database of online manual pages
+.RE
+.PP
+As you can see they are in section number order, so that
+.B man
+searches them in section order.
+.PP
+Each entry is just a single line, restricting the NAME section to a single
+line too with just one dash, and commas and spaces before the dash as you
+see above.
+.SH "SEE ALSO"
+.BR man (1),
+.BR whatis (1),
+.BR makewhatis (1),
+.BR man (7).
+.SH BUGS
+It seems to be impossible for many manual page writers to keep the NAME
+section simple.  They also like to use every font available in their
+documents.  My simple scripts can't read their NAME sections, my simple
+me can't read their texts.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man6/advent.6
===================================================================
--- /trunk/minix/man/man6/advent.6	(revision 9)
+++ /trunk/minix/man/man6/advent.6	(revision 9)
@@ -0,0 +1,22 @@
+.\"	@(#)adventure.6	6.2 (Berkeley) 5/6/86
+.\"
+.TH ADVENT 6 "May 6, 1986"
+.AT 3
+.SH NAME
+advent, adventure \- an exploration game
+.SH SYNOPSIS
+.B advent
+.SH DESCRIPTION
+The object of the game is to
+locate and explore Colossal Cave, find the treasures hidden there,
+and bring them back to the building with you.
+The program is self-descriptive to a point, but part of the game is to discover
+its rules.
+.PP
+To terminate a game, type `quit';
+to save a game for later resumption, type `save' now, and `restore' when
+you resume.
+.SH FILES
+.TP 15
+.B advent.sav
+A saved adventure game.
Index: /trunk/minix/man/man6/ttt.6
===================================================================
--- /trunk/minix/man/man6/ttt.6	(revision 9)
+++ /trunk/minix/man/man6/ttt.6	(revision 9)
@@ -0,0 +1,23 @@
+.TH TTT 6
+.SH NAME
+ttt \- tic tac toe
+.SH SYNOPSIS
+\fBttt\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "ttt   " "Start the game"
+.SH DESCRIPTION
+.PP
+This program allows the user to engage in a game of tic tac toe (noughts and
+crosses) with the computer.
+The program uses the alpha-beta algorithm, so the user had better be sharp.
Index: /trunk/minix/man/man7/ACK.7
===================================================================
--- /trunk/minix/man/man7/ACK.7	(revision 9)
+++ /trunk/minix/man/man7/ACK.7	(revision 9)
@@ -0,0 +1,2090 @@
+.TH ACK 7
+.SH NAME
+ACK \- Additional information on the Amsterdam Compiler Kit compilers
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.de XS
+.SP
+.in +.5i
+.nf
+..
+.de XE
+.fi
+.in -.5i
+.SP
+..
+.de NS
+.PP
+.B ANS\ \\$1
+..
+.de UX
+\s-2UNIX\s+2
+..
+.de MX
+.if n MINIX 3
+.if t \s-1MINIX 3\s-1
+..
+.if n .ds Mx MINIX 3
+.if t .ds Mx \s-1MINIX 3\s-1
+.if n .ds Mp Minix-PC
+.if t .ds Mx \s-2MINIX-PC\s+2
+.if n .ds Mv Minix-vmd
+.if t .ds Mv \s-1MINIX 3\s-1-vmd
+.if n .ds Cw \fR
+.if t .ds Cw \fC
+.de CW
+.if n .ft R
+.if t .ft C
+..
+.\"
+These are the details on the Amsterdam Compiler Kit compilers for the
+languages C, Modula-2, and Pascal.  The design decisions that were made
+where the respective standards allowed or mandated this, and the extensions
+that were implemented.
+.SH "ANSI C REPORT"
+This section specifies the implementation-defined behavior of the ANSI-C
+compiler as required by ANS X3.159-1989.
+.NS A.6.3.1
+.IP \(bu
+Diagnostics are placed on the standard error output.  They have the
+following specification:
+.XS
+"<file>", line <nr>: [(<class>)] <diagnostic>
+.XE
+There are three classes of diagnostics: 'error', 'strict' and 'warning'.
+When the class is 'error', the class specification is absent.
+The class 'strict' is used for violations of the standard which are
+not severe enough to stop compilation, for example the occurrence
+of non white-space after an '#endif' preprocessing
+directive.  The class 'warning' is used for legal but dubious
+constructions, for example the declaration of a structure-tag in a
+parameter type list.
+.NS A.6.3.2
+.IP \(bu
+The function 'main' can have zero or two parameters.  When it has two
+parameters, the first parameter is an integer specifying the number of
+arguments on the command line (including the command).  The second
+parameter is a pointer to an array of pointers to the arguments
+(as strings).
+.IP \(bu
+Interactive devices are terminals.
+.NS A.6.3.3
+.IP \(bu
+The number of significant characters is 64.
+Corresponding upper-case and lower-case letters are different.
+.NS A.6.3.4
+.IP \(bu
+The compiler assumes ASCII-characters in both the source and execution
+character set.
+.IP \(bu
+There are no multibyte characters.
+.IP \(bu
+There are 8 bits in a character.
+.IP \(bu
+Character constants that cannot be represented in 8 bits
+are truncated.
+.IP \(bu
+Character constants that are more than 1 character wide will have the
+first character specified in the least significant byte.
+.IP \(bu
+The only supported locale is 'C'.
+.IP \(bu
+A plain 'char' has the same range of values as 'signed char'.
+.NS A.6.3.5
+.IP \(bu
+The i80x86 and 68000 both have a two's complement binary-number system.
+Shorts are 2 bytes; ints are 2 bytes under 16-bits \*(Mp and 68000 \*(Mx, 4
+bytes under 32-bits \*(Mp; longs occupy 4 bytes.
+.IP \(bu
+Converting an integer to a shorter signed integer is implemented by
+ignoring the high-order byte(s) of the former.
+Converting a unsigned integer to a signed integer of the same type is
+only done in administration.  This means that the bit-pattern remains
+unchanged.
+.IP \(bu
+The result of bitwise operations on signed integers are what can be
+expected on a two's complement machine.
+.IP \(bu
+When either operand is negative, the result of the / operator is the
+largest integer less than or equal to the algebraic quotient.
+The sign of the remainder on integer division is the sign of the
+enumerator.
+.IP \(bu
+The right-shift of a negative value is negative.
+.NS A.6.3.6
+.IP \(bu
+The compiler uses IEEE format for floating-point numbers.
+High-precision floating-point is used for constant folding.
+.IP \(bu
+Truncation is done to the nearest floating-point number that can
+be represented.
+.NS A.6.3.7
+.IP \(bu
+The type of the sizeof-operator (also known as size_t) is 'unsigned int'.
+.IP \(bu
+Casting an integer to a pointer or vice versa has no effect in
+bit-pattern when the sizes are equal.  Otherwise the value will be
+truncated or zero-extended (depending on the direction of the
+conversion and the relative sizes).
+.IP \(bu
+The type of a 'ptrdiff_t' is 'int' on \*(Mp, and 'long' on the 68000
+\*(Mx versions.
+.NS A.6.3.8
+.IP \(bu
+Since the front end has only limited control over the registers, it can
+only make it more likely that variables that are declared as
+registers also end up in registers.  The only things that can possibly be
+put into registers are plain ints and pointers.
+.NS A.6.3.9
+.IP \(bu
+When a member of a union object is accessed using a member of a
+different type, the resulting value will usually be garbage.  The
+compiler makes no effort to catch these errors.
+.IP \(bu
+The alignment of types under 16-bit \*(Mp is 1 byte for characters and 2
+bytes for all other types.  Under other MINIX 3 versions 'int' and smaller
+types are aligned to a multiple of their size, bigger scalar types are
+aligned like 'int'.  Arrays have the same alignment as their elements;
+structs and unions are aligned like their field with the worst alignment.
+.IP \(bu
+A plain 'int' bit-field is taken as a 'signed int'.  This means that
+a field with a size 1 bit-field can only store the values 0 and \(mi1.
+.IP \(bu
+In bit-fields, high-order bits are allocated first.
+.IP \(bu
+An enum has the same size as a plain 'int'.
+.NS A.6.3.10
+.IP \(bu
+An access to a volatile object is either a load or a store.  Just
+mentioning a volatile variable is not enough.
+E.g. the statement 'x;' where x is declared volatile, does not
+constitute an access.  When a volatile object should be read, but its
+value ignored, 'if (x);' should do the trick.
+.NS A.6.3.11
+.IP \(bu
+There is no fixed limit on the number of declarators that may modify an
+arithmetic, structure or union type, although specifying too many may
+cause the compiler to run out of memory.
+.NS A.6.3.12
+.IP \(bu
+The maximum number of cases in a switch-statement is in the order of
+1e9, although the compiler may run out of memory somewhat earlier.
+.NS A.6.3.13
+.IP \(bu
+Since both the preprocessor and the compiler assume ASCII-characters, 
+a single character constant in a conditional-inclusion directive
+matches the same value in the execution character set.
+.IP \(bu
+The preprocessor recognizes \fI\(enI...\fR command-line options.  The
+directories thus specified are searched first.  After that, /usr/include is
+visited.
+.IP \(bu
+Quoted names are first looked for in the directory in which the file
+which does the include resides.
+.IP \(bu
+The characters in a h- or q- char-sequence are taken to be
+.UX
+paths.
+.IP \(bu
+Neither the front-end nor the preprocessor know any pragmas.
+.IP \(bu
+Since the compiler runs on 
+.MX ,
+_\^_DATE_\^_ and _\^_TIME_\^_ will always be
+defined.
+.NS A.6.3.14
+.IP \(bu
+NULL is defined as ((void *)0).  This in order to detect dubious
+constructions like 'int x = NULL;'.
+.IP \(bu
+The diagnostic printed by 'assert' is as follows:
+.XS
+Assertion "<expr>" failed, file "<file>", line <line>
+.XE
+where <expr> is the argument to the assert macro, printed as string.
+(the <file> and <line> should be clear)
+.IP \(bu
+The sets for character test macros for the C locale are as follows:
+.XS
+.ta +\w'isalnum    'u
+\fBName	Set\fR
+\fIisalnum\fR	0-9A-Za-z
+\fIisalpha\fR	A-Za-z
+\fIiscntrl\fR	\e000-\e037\e177
+\fIislower\fR	a-z
+\fIisupper\fR	A-Z
+\fIisprint\fR	\e040-\e176
+.DT
+.XE
+As an addition, there is an \fIisascii\fR macro, which tests whether a character
+is an ASCII character.  Characters in the range from \e000 to \e177 are ASCII
+characters.
+.IP \(bu
+The behavior of ACK mathematical functions on domain error is as follows:
+.XS
+.ta +\w'log10   'u
+\fBName	Returns\fR
+\fIasin\fR	0.0
+\fIacos\fR	0.0
+\fIatan2\fR	0.0
+\fIfmod\fR	0.0
+\fIlog\fR	\(miHUGE_VAL
+\fIlog10\fR	\(miHUGE_VAL
+\fIpow\fR	0.0
+\fIsqrt\fR	0.0
+.DT
+.XE
+\*(Mv uses the BSD4.4 C library and the Sun FDLIBM C math library instead
+of the ACK library.  See
+.BR math (3)
+for details about the math functions.  The \*(Mv libraries offer at
+least the same functionality as the ACK library.
+.IP \(bu
+Underflow range errors do not cause \fIerrno\fR to be set.
+.IP \(bu
+The function \fIfmod\fR returns 0.0 and sets \fIerrno\fR to EDOM when the second
+argument is 0.0.
+.IP \(bu
+The set of signals for the \fIsignal\fR function is as described by
+.BR sigaction (2).
+.IP \(bu
+A text-stream need not end in a new-line character.
+.IP \(bu
+White space characters before a new-line appear when read in.
+.IP \(bu
+There may be any number of null characters appended to a binary
+stream.
+.IP \(bu
+The file position indicator of an append mode stream is initially
+positioned at the beginning of the file.
+.IP \(bu
+A write on a text stream does not cause the associated file to be
+truncated beyond that point.
+.IP \(bu
+The buffering intended by the standard is fully supported.
+.IP \(bu
+A zero-length file actually exists.
+.IP \(bu
+A file name can consist of any character, except for the '\e0' and
+the '/'.
+.IP \(bu
+A file can be open multiple times.
+.IP \(bu
+When a \fIremove\fR is done on an open file, reading and writing behave
+just as can be expected from a non-removed file.  When the associated
+stream is closed, however, all written data will be lost.
+.IP \(bu
+When a file exists prior to a call to \fIrename\fR, it is removed.
+.IP \(bu
+The %p conversion in \fIfprintf\fR has the same effect as %#x on \*(Mp and
+%#lx on the 68000 versions of \*(Mx.
+.IP \(bu
+The %p conversion in \fIfscanf\fR has the same effect as %x on \*(Mp and
+%lx on the 68000 versions of \*(Mx.
+.IP \(bu
+A \(mi character that is neither the first nor the last character in the
+scanlist for %[ conversion is taken to be a range indicator.  When the
+first character has a higher ASCII-value than the second, the \(mi will
+just be put into the scanlist.
+.IP \(bu
+The value of \fIerrno\fR when \fIfgetpos\fR or \fIftell\fR failed is that of \fIlseek\fR.
+This means:
+.XS
+.ta +\w'ESPIPE   'u +\w'\- 'u
+EBADF	\-	when the stream is not valid
+ESPIPE	\-	when fildes is associated with a pipe
+EINVAL	\-	the resulting file pointer would be negative
+.XE
+.IP \(bu
+The messages generated by \fIperror\fR depend on the value of \fIerrno\fR.
+The mapping of errors to strings is done by \fIstrerror\fR.
+.IP \(bu
+When the requested size is zero, \fImalloc\fR, \fIcalloc\fR and \fIrealloc\fR
+return a null-pointer under \*(Mx.  Under \*(Mv a unique non-null pointer is
+returned.
+.IP \(bu
+When \fIabort\fR is called, output buffers will be flushed.  Temporary files
+(made with the \fItmpfile\fR function) will have disappeared when SIGABRT
+is not caught or ignored.
+.IP \(bu
+The \fIexit\fR function returns the low-order eight bits of its argument
+to the environment.
+.IP \(bu
+The predefined environment names are controlled by the user.
+Setting environment variables is done through the \fIputenv\fR function.
+This function accepts a pointer to char as its argument.
+To set, for example, the environment variable TERM to a230 one writes
+.XS
+static char terminal[] = "TERM=a230";
+putenv(terminal);
+.XE
+The argument to \fIputenv\fR is stored in an internal table, so malloc'ed
+strings cannot be freed until another call to \fIputenv\fR (which sets the
+same environment variable) is made.  The argument to \fIputenv\fR must be
+writable, which means that officially, the argument cannot be a string
+constant.
+The function returns 1 if it fails, 0 otherwise.
+.LP
+.IP \(bu
+The argument to \fIsystem\fR is passed as argument to \fI/bin/sh \(enc\fR.
+.IP \(bu
+The strings returned by \fIstrerror\fR depend on \fIerrno\fR.  They are
+listed in
+.BR intro (2).
+Everything else causes \fIstrerror\fR to return "unknown error" under \*(Mx,
+or the result of sprintf("Error %d", errno) under \*(Mv.
+.IP \(bu
+The local time zone is per default GMT.  This can be
+changed through the TZ environment variable, e.g. TZ=EST6.
+See
+.BR TZ (5).
+.IP \(bu
+The \fIclock\fR function returns the number of ticks since process
+startup.
+.SS References
+.IP [1]
+ANS X3.159-1989
+.ft I
+American National Standard for Information Systems -
+Programming Language C
+.ft R
+.SH "THE MINIX MODULA-2 COMPILER"
+This section describes the implementation-specific features of the
+.MX
+Modula-2 compiler.
+It is not intended to teach Modula-2 programming.
+For a description of the Modula-2 language,
+the reader is referred to [1].
+.SS "The language implemented"
+.PP
+This paragraph discusses the deviations from the Modula-2 language as described
+in the 'Report on The Programming Language Modula-2',
+as it appeared in [1],
+from now on referred to as 'the Report'.
+Also,
+the Report sometimes leaves room for interpretation.
+The section numbers
+mentioned are the section numbers of the Report.
+.SS "Syntax (section 2)"
+.PP
+The syntax recognized is that of the Report,
+with some extensions to
+also recognize the syntax of an earlier definition,
+given in [2].
+Only one compilation unit per file is accepted.
+.SS "Vocabulary and Representation (section 3)"
+.PP
+The input '\*(Cw10..\fR' is parsed as two tokens: '\*(Cw10\fR' and '\*(Cw..\fR'.
+.PP
+The empty string \*(Cw""\fR has type
+.XS
+.CW
+ARRAY [0 .. 0] OF CHAR
+.ft P
+.XE
+and contains one character: \*(Cw0C\fR.
+.PP
+When the text of a comment starts with a '\*(Cw$\fR',
+it may be a pragma.
+Currently,
+the following pragmas exist:
+.nf
+.SP
+.CW
+(*$F      (F stands for Foreign) *)
+(*$R[+|-] (Runtime checks, on or off, default on) *)
+(*$A[+|-] (Array bound checks, on or off, default off) *)
+(*$U      (Allow for underscores within identifiers) *)
+.ft P
+.SP
+.fi
+The Foreign pragma is only meaningful in a \*(CwDEFINITION MODULE\fR,
+and indicates that this
+\*(CwDEFINITION MODULE\fR describes an interface to a module written in another
+language (for instance C or Pascal).
+Runtime checks that can be disabled are:
+range checks,
+\*(CwCARDINAL\fR overflow checks,
+checks when assigning a \*(CwCARDINAL\fR to an \*(CwINTEGER\fR and vice versa,
+and checks that \*(CwFOR\fR-loop control-variables are not changed
+in the body of the loop.
+Array bound checks can be enabled,
+because many EM implementations do not
+implement the array bound checking of the EM array instructions.
+When enabled,
+the compiler generates a check before generating an
+EM array instruction.
+Even when underscores are enabled,
+they still may not start an identifier.
+.PP
+Constants of type \*(CwLONGINT\fR are integers with a suffix letter \*(CwD\fR
+(for instance \*(Cw1987D\fR).
+Constants of type \*(CwLONGREAL\fR have suffix \*(CwD\fR if a scale factor is missing,
+or have \*(CwD\fR in place of \*(CwE\fR in the scale factor (f.i. \*(Cw1.0D\fR,
+\*(Cw0.314D1\fR).
+This addition was made,
+because there was no way to indicate long constants,
+and also because the addition was made in Wirth's newest Modula-2 compiler.
+.SS "Declarations and scope rules (section 4)"
+.PP
+Standard identifiers are predeclared,
+and valid in all
+parts of a program.
+They are called \fIpervasive\fR.
+Unfortunately,
+the Report does not state how this pervasiveness is accomplished.
+However,
+page 87 of [1] states: 'Standard identifiers are automatically
+imported into all modules'.
+Our implementation therefore allows
+redeclarations of standard identifiers within procedures,
+but not within
+modules.
+.SS "Constant expressions (section 5)"
+.PP
+Each operand of a constant expression must be a constant:
+a string,
+a number,
+a set,
+an enumeration literal,
+a qualifier denoting a
+constant expression,
+a type transfer with a constant argument,
+or one of the standard procedures
+\*(CwABS\fR,
+\*(CwCAP\fR,
+\*(CwCHR\fR,
+\*(CwLONG\fR,
+\*(CwMAX\fR,
+\*(CwMIN\fR,
+\*(CwODD\fR,
+\*(CwORD\fR,
+\*(CwSIZE\fR,
+\*(CwSHORT\fR,
+\*(CwTSIZE\fR,
+or \*(CwVAL\fR,
+with constant argument(s);
+\*(CwTSIZE\fR and \*(CwSIZE\fR may also have a variable as argument.
+.SS "Type declarations (section 6)"
+.LP
+.ft I
+1. Basic types (section 6.1)
+.PP
+The type \*(CwCHAR\fR includes the ASCII character set as a subset.
+Values range from
+\*(Cw0C\fR to \*(Cw377C\fR,
+not from \*(Cw0C\fR to \*(Cw177C\fR.
+.LP
+.ft I
+2. Enumerations (section 6.2)
+.PP
+The maximum number of enumeration literals in any one enumeration type
+is \*(CwMAX(INTEGER)\fR.
+.LP
+.ft I
+3. Record types (section 6.5)
+.PP
+The syntax of variant sections in [1] is different from the one in [2].
+Our implementation recognizes both,
+giving a warning for the older one.
+.LP
+.ft I
+4. Set types (section 6.6)
+.PP
+The only limitation imposed by the compiler is that the base type of the
+set must be a subrange type,
+an enumeration type,
+\*(CwCHAR\fR,
+or \*(CwBOOLEAN\fR.
+So,
+the lower bound may be negative.
+However,
+if a negative lower bound is used,
+the compiler gives a warning of the \fIrestricted\fR class.
+.PP
+The standard type \*(CwBITSET\fR is defined as
+.XS
+.CW
+TYPE BITSET = SET OF [0 .. 8*SIZE(INTEGER)-1];
+.ft P
+.XE
+.SS "Expressions (section 8)"
+.LP
+.ft I
+1. Operators (section 8.2)
+.LP
+.ft I
+1.1. Arithmetic operators (section 8.2.1)
+.PP
+The Report does not specify the priority of the unary
+operators \*(Cw+\fR or \*(Cw-\fR:
+It does not specify whether
+.XS
+.CW
+- 1 + 1
+.ft P
+.XE
+means
+.XS
+.CW
+- (1 + 1)
+.ft P
+.XE
+or
+.XS
+.CW
+(-1) + 1
+.ft P
+.XE
+The
+.MX
+Modula-2 compiler implements the second alternative.
+.SS "Statements (section 9)"
+.LP
+.ft I
+1. Assignments (section 9.1)
+.PP
+The Report does not define the evaluation order in an assignment.
+Our compiler certainly chooses an evaluation order,
+but it is explicitly left undefined.
+Therefore,
+programs that depend on it may cease to work later.
+.PP
+The types \*(CwINTEGER\fR and \*(CwCARDINAL\fR are assignment-compatible with
+\*(CwLONGINT\fR,
+and \*(CwREAL\fR is assignment-compatible with \*(CwLONGREAL\fR.
+.LP
+.ft I
+2. Case statements (section 9.5)
+.PP
+The size of the type of the case-expression must be less than or equal to
+the word-size.
+.PP
+The Report does not specify what happens if the value of the case-expression
+does not occur as a label of any case,
+and there is no \*(CwELSE\fR-part.
+In our implementation,
+this results in a runtime error.
+.LP
+.ft I
+3. For statements (section 9.8)
+.PP
+The Report does not specify the legal types for a control variable.
+Our implementation allows the basic types (except \*(CwREAL\fR),
+enumeration types,
+and subranges.
+A runtime warning is generated when the value of the control variable
+is changed by the statement sequence that forms the body of the loop,
+unless runtime checking is disabled.
+.LP
+.ft I
+4. Return and exit statements (section 9.11)
+.PP
+The Report does not specify which result-types are legal.
+Our implementation allows any result type.
+.SS "Procedure declarations (section 10)"
+.PP
+Function procedures must exit through a RETURN statement,
+or a runtime error occurs.
+.LP
+.ft I
+1. Standard procedures (section 10.2)
+.PP
+Our implementation supports \*(CwNEW\fR and \*(CwDISPOSE\fR
+for backwards compatibility,
+but issues warnings for their use.
+.PP
+Also,
+some new standard procedures were added,
+similar to the new standard procedures in Wirth's newest compiler:
+.IP \-
+\*(CwLONG\fR converts an argument of type \*(CwINTEGER\fR or \*(CwREAL\fR to the
+types \*(CwLONGINT\fR or \*(CwLONGREAL\fR.
+.IP \-
+\*(CwSHORT\fR performs the inverse transformation,
+without range checks.
+.IP \-
+\*(CwFLOATD\fR is analogous to \*(CwFLOAT\fR,
+but yields a result of type
+\*(CwLONGREAL\fR.
+.IP \-
+\*(CwTRUNCD\fR is analogous to \*(CwTRUNC\fR,
+but yields a result of type
+\*(CwLONGINT\fR.
+.SS "System-dependent facilities (section 12)"
+.PP
+The type \*(CwBYTE\fR is added to the \*(CwSYSTEM\fR module.
+It occupies a storage unit of 8 bits.
+\*(CwARRAY OF BYTE\fR has a similar effect to \*(CwARRAY OF WORD\fR,
+but is safer.
+In some obscure cases the \*(CwARRAY OF WORD\fR mechanism does not quite
+work properly.
+.PP
+The procedure \*(CwIOTRANSFER\fR is not implemented.
+.SS "Backwards compatibility"
+.PP
+Besides recognizing the language as described in [1],
+the compiler recognizes most of the language described in [2],
+for backwards compatibility.
+It warns the user for old-fashioned
+constructions (constructions that [1] does not allow).
+If the \fI\(en3\fR option is passed to \fIm2\fR,
+this backwards compatibility feature is disabled.
+.SS "Compile time errors"
+.PP
+The compile time error messages are intended to be self-explanatory,
+and not listed here.
+The compiler also sometimes issues warnings,
+recognizable by a warning-classification between parentheses.
+There are 3 classifications:
+.IP "(old-fashioned use)"
+.br
+These warnings are given on constructions that are not allowed by [1],
+but are allowed by [2].
+.IP (strict)
+.br
+These warnings are given on constructions that are supported by the
+.MX
+Modula-2 compiler,
+but might not be supported by others.
+Examples: functions returning structured types,
+SET types of subranges with
+negative lower bound.
+.IP (warning)
+.br
+The other warnings,
+such as warnings about variables that are never assigned,
+never used,
+etc.
+.SS "Runtime errors"
+.PP
+The \fITraps\fR module enables the user to install his own runtime
+error handler.
+The default one just displays what happened and exits.
+Basically,
+a trap handler is just a procedure that takes an INTEGER as
+parameter.
+The INTEGER is the trap number.
+This INTEGER can be one of the
+EM trap numbers,
+listed in [3],
+or one of the numbers listed in the
+\fITraps\fR definition module.
+.PP
+The following runtime errors may occur:
+.IP "array bound error"
+.br
+This error is detected if the \fI\(enA\fR option is given to \fIm2\fR.
+.IP "range bound error"
+.br
+Range bound errors are always detected,
+unless runtime checks are disabled.
+.IP "set bound error"
+.IP "cardinal overflow"
+.br
+This error is detected,
+unless runtime checks are disabled.
+.IP "cardinal underflow"
+.br
+This error is detected,
+unless runtime checks are disabled.
+.IP "divide by 0"
+.IP "divide by 0.0"
+.IP "conversion error"
+.br
+This error occurs when assigning a negative value of type INTEGER to a
+variable of type CARDINAL,
+or when assigning a value of CARDINAL that is > MAX(INTEGER),
+to a variable of type INTEGER.
+It is detected,
+unless runtime checking is disabled.
+.IP "heap overflow"
+.br
+This might happen when ALLOCATE fails.
+.IP "case error"
+.br
+This error occurs when non of the cases in a CASE statement are selected,
+and the CASE statement has no ELSE part.
+.IP "stack size of process too large"
+.br
+This is most likely to happen if the reserved space for a coroutine stack
+is too small.
+In this case,
+increase the size of the area given to
+\*(CwNEWPROCESS\fR.
+It can also happen if the stack needed for the main
+process is too large and there are coroutines.
+In this case,
+the only fix is to reduce the stack size needed by the main process,
+f.i. by avoiding local arrays.
+.IP "too many nested traps + handlers"
+.br
+This error can only occur when the user has installed his own trap handler.
+It means that during execution of the trap handler another trap has occurred,
+and that several times.
+In some cases,
+this is an error because of overflow of some internal tables.
+.IP "no RETURN from function procedure"
+.br
+This error occurs when a function procedure does not return properly
+('falls' through).
+.IP "illegal instruction"
+.br
+This error might occur when you use floating point operations on an
+implementation that does not have floating point.
+.PP
+In addition,
+some of the library modules may give error messages.
+The \fBTraps\fR-module has a suitable mechanism for this.
+.SS "The procedure call interface"
+.PP
+Parameters are pushed on the stack in reversed order.
+For VAR parameters,
+its address is passed,
+for value parameters its value.
+The only exception to this rule is with conformant arrays.
+For conformant arrays,
+the address is passed,
+and an array descriptor is
+passed.
+The descriptor is an EM array descriptor.
+It consists of three
+fields: the lower bound (always 0),
+upper bound \(mi lower bound,
+and the size of the elements.
+The descriptor is pushed first.
+If the parameter is a value parameter,
+the called routine must make sure
+that its value is never changed,
+for instance by making its own copy
+of the array.
+.PP
+When the size of the return value of a function procedure is larger than
+the maximum of \*(CwSIZE(LONGREAL)\fR and twice the pointer-size,
+the caller reserves this space on the stack,
+above the parameters.
+Callee then stores
+its result there,
+and returns no other value.
+.SS "The Modula-2 runtime library"
+.PP
+The definition modules of the modules available in the
+.MX
+Modula-2 runtime library reside in the directory \fI/usr/lib/ack/m2\fR.
+.SS References
+.IP [1]
+Niklaus Wirth,
+.ft I
+Programming in Modula-2, third, corrected edition,
+.ft R
+Springer-Verlag, Berlin (1985)
+.IP [2]
+Niklaus Wirth,
+.ft I
+Programming in Modula-2,
+.ft R
+Stringer-Verlag, Berlin (1983)
+.IP [3]
+A.S.Tanenbaum, J.W.Stevenson, Hans van Staveren, E.G.Keizer,
+.ft I
+Description of a machine architecture for use with block structured languages,
+.ft R
+Informatica rapport IR-81, Vrije Universiteit, Amsterdam
+.SH "THE MINIX PASCAL COMPILER"
+.PP
+.de IT
+.PP
+.B BS\ \\$1:
+..
+.de IS
+.PP
+.in +.5i
+..
+.PP
+This section refers to the (1982) BSI standard for Pascal [1].
+.MX
+Pascal complies with the requirements of level 1 of BS 6192: 1982, with
+the exceptions as listed in this section.
+.PP
+The standard requires an accompanying document describing the
+implementation-defined and implementation-dependent features,
+the reaction on errors and the extensions to standard Pascal.
+These four items will be treated in the rest of this section.
+.SS "Implementation-defined features"
+.PP
+For each implementation-defined feature mentioned in the BSI standard
+we give the section number, the quotation from that section and the definition.
+First we quote the definition of implementation-defined:
+.PP
+.RS
+Possibly differing between processors, but defined for any particular
+processor.
+.RE
+.IT 6.1.7
+Each string-character shall denote an implementation-defined value of the
+required char-type.
+.IS
+All 7-bit ASCII characters except linefeed LF (10) are allowed.
+.IT 6.4.2.2
+The values of type real shall be an implementation-defined subset
+of the real numbers denoted as specified by 6.1.5 by the signed-real values.
+.IS
+The set of real values range from a low of \(mi1.7976931348623157e+308 to
+a high of 1.7976931348623157e+308.
+.IT 6.4.2.2
+The type char shall be the enumeration of a set of implementation-defined
+characters, some possibly without graphic representations.
+.IS
+The 7-bit ASCII character set is used, where LF (10) denotes the
+end-of-line marker on text-files.
+.IT 6.4.2.2
+The ordinal numbers of the character values shall be values of integer-type,
+that are implementation-defined, and that are determined by mapping
+the character values on to consecutive non-negative integer values
+starting at zero.
+.IS
+The normal ASCII ordering is used: ord('0')=48, ord('A')=65, ord('a')=97, etc.
+.IT 6.6.5.2
+The post-assertions imply corresponding activities on the external entities,
+if any, to which the file-variables are bound.
+These activities, and the
+point at which they are actually performed, shall be
+implementation-defined.
+.IS
+The reading and writing writing of objects on files is buffered.
+This means that when a program terminates abnormally, I/O may be
+unfinished.
+Terminal I/O is unbuffered.
+Files are closed whenever they are rewritten or reset, or on
+program termination.
+.IT 6.7.2.2
+The predefined constant \fImaxint\fR shall be of integer-type and shall denote
+an implementation-defined value, that satisfies the following conditions:
+.IP (a)
+All integral values in the closed interval from \fI\(mimaxint\fR to \fI+maxint\fR
+shall be values of the integer-type.
+.IP (b)
+Any monadic operation performed on an integer value in this interval
+shall be correctly performed according to the mathematical rules for
+integer arithmetic.
+.IP (c)
+Any dyadic integer operation on two integer values in this same interval
+shall be correctly performed according to the mathematical rules for
+integer arithmetic, provided that the result is also in this interval.
+.IP (d)
+Any relational operation on two integer values in this same interval
+shall be correctly performed according to the mathematical rules for
+integer arithmetic.
+.SP
+The representation of integers under 16-bit \*(Mp or under 68000 \*(Mx
+is a 16-bit word using two's complement arithmetic.  The integers range
+from \(mi32768 to +32767.  Under 32-bit \*(Mp a 32-bit integer is used
+ranging from \(mi2147483648 to +2147483647.
+.IT 6.7.2.2
+The result of the real arithmetic operators and functions shall be
+approximations to the corresponding mathematical results.
+The accuracy of
+this approximation shall be implementation-defined
+.IS
+The default size of reals is 8 bytes, the accuracy is 11 bits for the exponent,
+and 53 bits for the mantissa.
+This gives an accuracy of about 16 digits.
+and exponents ranging from \(mi307 to +307.
+.IT 6.9.3.1
+The default TotalWidth values for integer, Boolean and real types
+shall be implementation-defined.
+.IS
+The defaults are:
+.XS
+.ta +\w'Boolean   'u +\w'14  'u
+integer	6	(16-bit)
+integer	11	(32-bit)
+Boolean	5
+real	14
+.DT
+.XE
+.IT 6.9.3.4.1
+ExpDigits, the number of digits written in an exponent part of a real,
+shall be implementation-defined.
+.IS
+ExpDigits is defined as 3.
+.IT 6.9.3.4.1
+The character written as part of the representation of
+a real to indicate the beginning of the exponent part shall be
+implementation-defined, either 'E' or 'e'.
+.IS
+The exponent part starts with 'e'.
+.IT 6.9.3.5
+The case of the characters written as representation of the
+Boolean values shall be implementation-defined.
+.IS
+The representations of true and false are 'true' and 'false'.
+.IT 6.9.5
+The effect caused by the standard procedure page
+on a text file shall be implementation-defined.
+.IS
+The ASCII character form feed FF (12) is written.
+.IT 6.10
+The binding of the variables denoted by the program-parameters
+to entities external to the program shall be implementation-defined if
+the variable is of a file-type.
+.IS
+The program parameters must be files and all, except input and output,
+must be declared as such in the program block.
+.PP
+The program parameters input and output, if specified, will correspond
+with the UNIX streams 'standard input' and 'standard output'.
+.PP
+The other program parameters will be mapped to the argument strings
+provided by the caller of this program.
+The argument strings are supposed to be path names of the files to be
+opened or created.
+The order of the program parameters determines the mapping:
+the first parameter is mapped onto the first argument string, etc.
+Note that input and output are ignored in this mapping.
+.PP
+The mapping is recalculated each time a program parameter
+is opened for reading or writing by a call to the standard procedures
+reset or rewrite.
+This gives the programmer the opportunity to manipulate the list
+of string arguments using the external procedures argc, argv and argshift
+available in the Pascal library.
+.IT 6.10
+The effect of an explicit use of reset or rewrite
+on the standard text files input or output shall be implementation-defined.
+.IS
+The procedures reset and rewrite are no-ops
+if applied to input or output.
+.in 0
+.SS "Implementation-dependent features"
+.PP
+For each implementation-dependent feature mentioned in the BSI standard,
+we give the section number, the quotation from that section and the way
+this feature is treated by the 
+.MX
+Pascal system.
+First we quote the definition of 'implementation-dependent':
+.PP
+.RS
+Possibly differing between processors and not necessarily defined for any
+particular processor.
+.RE
+.IT 6.7.2.1
+The order of evaluation of the operands of a dyadic operator
+shall be implementation-dependent.
+.IS
+Operands are always evaluated, so the program part
+.XS
+if (p<>nil) and (p^.value<>0) then
+.XE
+is probably incorrect.
+.PP
+The left-hand operand of a dyadic operator is almost always evaluated
+before the right-hand side.
+Some peculiar evaluations exist for the following cases:
+.IP 1.
+The modulo operation is performed by a library routine to
+check for negative values of the right operand.
+.IP 2.
+The expression
+.XS
+set1 <= set2
+.XE
+where set1 and set2 are compatible set types is evaluated in the
+following steps:
+.XS
+.ta +\w'\-  'u
+\-	evaluate set2;
+\-	evaluate set1;
+\-	compute set2+set1;
+\-	test set2 and set2+set1 for equality.
+.DT
+.XE
+.IP 3.
+The expression
+.XS
+set1 >= set2
+.XE
+where set1 and set2 are compatible set types is evaluated in the following steps:
+.XS
+.ta +\w'\-  'u
+\-	evaluate set1;
+\-	evaluate set2;
+\-	compute set1+set2;
+\-	test set1 and set1+set2 for equality.
+.DT
+.XE
+.IT 6.7.3
+The order of evaluation, accessing and binding
+of the actual-parameters for functions
+shall be implementation-dependent.
+.IS
+The order of evaluation is from right to left.
+.IT 6.8.2.2
+The decision as to the order of accessing the variable and evaluating
+the expression in an assignment-statement, shall be
+implementation-dependent.
+.IS
+The expression is evaluated first.
+.IT 6.8.2.3
+The order of evaluation and binding of the actual-parameters for procedures
+shall be implementation-dependent.
+.IS
+The same as for functions.
+.IT 6.9.5
+The effect of inspecting a text file to which the page
+procedure was applied during generation is
+implementation-dependent.
+.IS
+The formfeed character written by page is
+treated like a normal character, with ordinal value 12.
+.IT 6.10
+The binding of the variables denoted by the program-parameters
+to entities external to the program shall be implementation-dependent unless
+the variable is of a file-type.
+.IS
+Only variables of a file-type are allowed as program parameters.
+.in 0
+.SS "Error handling"
+.PP
+There are three classes of errors to be distinguished.
+In the first class are the error messages generated by the compiler.
+The second class consists of the occasional errors generated by the other
+programs involved in the compilation process.
+Errors of the third class are the errors as defined in the standard by:
+.PP
+.RS
+An error is a violation by a program of the requirements of this standard
+that a processor is permitted to leave undetected.
+.RE
+.LP
+.ft I
+Compiler errors
+.PP
+Error are written on the standard error output.
+Each line has the form:
+.XS
+<file>, line <number>: <description>
+.XE
+Every time the compiler detects an error that does not have influence
+on the code produced by the compiler or on the syntax decisions, a warning
+messages is given.
+If only warnings are generated, compilation proceeds and probably results
+in a correctly compiled program.
+.PP
+Sometimes the compiler produces several errors for the same line.
+They are only shown up to a maximum of 5 errors per line.
+Warning are also shown up to a maximum of 5 per line.
+.PP
+Extensive treatment of these errors is outside the scope of this manual.
+.LP
+.ft I
+Runtime errors
+.PP
+Errors detected at run time cause an error message to be generated on the
+diagnostic output stream (UNIX file descriptor 2).
+The message consists of the name of the program followed by a message
+describing the error, possibly followed by the source line number.
+Unless the \fI\(enn\fR option is turned on, the compiler generates code to keep track
+of which source line causes which instructions to be generated.
+.PP
+For each error mentioned in the standard we give the section number,
+the quotation from that section and the way it is processed by the
+Pascal-compiler or runtime system.
+.PP
+For detected errors the corresponding message
+and trap number are given.
+Trap numbers are useful for exception-handling routines.
+Normally, each error causes the program to terminate.
+By using exception-handling routines one can
+ignore errors or perform alternate actions.
+Only some of the errors can be ignored
+by restarting the failing instruction.
+These errors are marked as non-fatal,
+all others as fatal.
+A list of errors with trap number between 0 and 63
+(EM errors) can be found in [2].
+Errors with trap number between 64 and 127 (Pascal errors) are listed below.
+.IT 6.4.6
+It shall be an error if a value of type T2 must be
+assignment-compatible with type T1, while
+T1 and T2 are compatible ordinal-types and the value of
+type T2 is not in the closed interval specified by T1.
+.IS
+The compiler distinguishes between array-index expressions and the other
+places where assignment-compatibility is required.
+.PP
+Array subscripting errors are only detected when the 'A' option is used.
+In the other cases, a range bound error occurs when the value of type T2
+is not in the closed interval specified by T1, unless range checks are
+disabled.
+.IT 6.4.6
+It shall be an error if a value of type T2 must be
+assignment-compatible with type T1, while T1 and T2 are compatible
+set-types and any member of the value of type T2
+is not in the closed interval specified by the base-type
+of the type T1.
+.IS
+This error is not detected.
+.IT 6.5.3.3
+It shall be an error if a component of a variant-part of a variant,
+where the selector of the variant-part is not a field,
+is accessed unless the variant is active for the entirety of each
+reference and access to each component of the variant.
+.IS
+This error is not detected.
+.IT 6.5.4
+It shall be an error if
+the pointer-variable of an identified-variable either denotes a
+nil-value or is undefined.
+.IS
+This error is not detected.
+.IT 6.5.4
+It shall be an error to remove the identifying-value of an identified
+variable from its pointer-type when a reference to the variable exists.
+.IS
+When the identified variable is an element of the record-variable-list of
+a with-statement, a warning is given at compile-time.
+Otherwise, this error is not detected.
+.IT 6.5.5
+It shall be an error to alter the value of a file-variable f when a
+reference to the buffer-variable f^ exists.
+.IS
+When f is altered when it is an element of the record-variable-list of a
+with-statement, a warning is given.
+When a buffer-variable is used as a
+variable-parameter, an error is given.
+This is done at compile-time.
+.IT 6.6.5.2
+It shall be an error if
+the stated pre-assertion does not hold immediately
+prior to any use of the file handling procedures
+rewrite, put, reset and get.
+.IS
+For each of these four operations the pre-assertions
+can be reformulated as:
+.XS
+.ta +\w'rewrite(f):  'u
+rewrite(f):	no pre-assertion.
+put(f):	f is opened for writing and f^ is not undefined.
+reset(f):	f exists.
+get(f):	f is opened for reading and eof(f) is false.
+.DT
+.XE
+The following errors are detected for these operations:
+.SP
+rewrite(f):
+.in +6
+.ti -3
+more args expected, trap 64, fatal:
+.br
+f is a program-parameter and the corresponding
+file name is not supplied by the caller of the program.
+.ti -3
+rewrite error, trap 101, fatal:
+.br
+the caller of the program lacks the necessary
+access rights to create the file in the file system
+or operating system problems like table overflow
+prevent creation of the file.
+.in -6
+.SP
+put(f):
+.in +6
+.ti -3
+file not yet open, trap 72, fatal:
+.br
+reset or rewrite are never applied to the file.
+The checks performed by the run time system are not foolproof.
+.ti -3
+not writable, trap 96, fatal:
+.br
+f is opened for reading.
+.ti -3
+write error, trap 104, fatal:
+.br
+probably caused by file system problems.
+For instance, the file storage is exhausted.
+Because I/O is buffered to improve performance,
+it might happen that this error occurs if the
+file is closed.
+Files are closed whenever they are rewritten or reset, or on
+program termination.
+.in -6
+.SP
+reset(f):
+.in +6
+.ti -3
+more args expected, trap 64, fatal:
+.br
+same as for rewrite(f).
+.ti -3
+reset error, trap 100, fatal:
+.br
+f does not exist, or the caller has insufficient access rights, or
+operating system tables are exhausted.
+.in -6
+.SP
+get(f):
+.in +6
+.ti -3
+file not yet open, trap 72, fatal:
+.br
+as for put(f).
+.ti -3
+not readable, trap 97, fatal:
+.br
+f is opened for writing.
+.ti -3
+end of file, trap 98, fatal:
+.br
+eof(f) is true just before the call to get(f).
+.ti -3
+read error, trap 103, fatal:
+.br
+unlikely to happen.
+Probably caused by hardware problems
+or by errors elsewhere in your program that destroyed
+the file information maintained by the run time system.
+.ti -3
+truncated, trap 99, fatal:
+.br
+the file is not properly formed by an integer
+number of file elements.
+For instance, the size of a file of integer is odd.
+.ti -3
+non-ASCII char read, trap 106, non-fatal:
+.br
+the character value of the next character-type
+file element is out of range (0..127).
+Only for text files.
+.in -6
+.IT 6.6.5.3
+It shall be an error if a variant of a variant-part within the new
+variable becomes active and a different variant of the variant-part is
+one of the specified variants.
+.IS
+This error is not detected.
+.IT 6.6.5.3
+It shall be an error to use dispose(q) if the identifying variable has been
+allocated using the form new(p,c1,...,cn).
+.IS
+This error is not detected.
+However, this error can cause more memory
+to be freed then was allocated.
+Dispose causes a fatal trap 73 when memory already on the free
+list is freed again.
+.IT 6.6.5.3
+It shall be an error to use dispose(q,k1,...,km) if the identifying
+variable has been allocated using the form new(p,c1,...,cn) and m is not
+equal to n.
+.IS
+This error is not detected.
+However, this error can cause more memory
+to be freed then was allocated.
+Dispose causes a fatal trap 73 when memory already on the free
+list is freed again.
+.IT 6.6.5.3
+It shall be an error if the variants of a variable to be disposed
+are different from those specified by the case-constants to dispose.
+.IS
+This error is not detected.
+.IT 6.6.5.3
+It shall be an error if the value of the pointer parameter of dispose has
+nil-value or is undefined.
+.IS
+This error is detected for nil-value (dispose error, trap 73, fatal).
+.IT 6.6.5.3
+It shall be an error if a variable created using the second form of new is
+accessed by the identified variable of the variable-access of a factor,
+of an assignment-statement, or of an actual-parameter.
+.IS
+This error is not detected.
+.IT 6.6.6.2
+It shall be an error if the value of sqr(x) does not exist.
+.IS
+This error is detected for real-type arguments (real overflow,
+trap 4, non-fatal).
+.IT 6.6.6.2
+It shall be an error if x in ln(x) is smaller than or equal to 0.
+.IS
+This error is detected (error in ln, trap 66, non-fatal)
+.IT 6.6.6.2
+It shall be an error if x in sqrt(x) is smaller than 0.
+.IS
+This error is detected (error in sqrt, trap 67, non-fatal)
+.SP
+In addition to these errors, overflow in the expression exp(x) is
+detected (error in exp, trap 65, non-fatal; real overflow, trap 4, non-fatal)
+.IT 6.6.6.3
+It shall be an error if
+the integer value of trunc(x) does not exist.
+.IS
+This error is detected (conversion error, trap 10, non-fatal).
+.IT 6.6.6.3
+It shall be an error if
+the integer value of round(x) does not exist.
+.IS
+This error is detected (conversion error, trap 10, non-fatal).
+.IT 6.6.6.4
+It shall be an error if
+the integer value of ord(x) does not exist.
+.IS
+This error can not occur, because the compiler will not allow
+such ordinal types.
+.IT 6.6.6.4
+It shall be an error if
+the character value of chr(x) does not exist.
+.IS
+This error is detected (range bound error, trap 1, non-fatal).
+.IT 6.6.6.4
+It shall be an error if the value of succ(x) does not exist.
+.IS
+Same comments as for chr(x).
+.IT 6.6.6.4
+It shall be an error if the value of pred(x) does not exist.
+.IS
+Same comments as for chr(x).
+.IT 6.6.6.5
+It shall be an error if f in eof(f) is undefined.
+.IS
+This error is detected (file not yet open, trap 72, fatal).
+.IT 6.6.6.5
+It shall be an error if
+f in eoln(f) is undefined, or if eof(f) is true at that time.
+.IS
+The following errors may occur:
+.IS
+file not yet open, trap 72, fatal;
+.br
+not readable, trap 97, fatal;
+.br
+end of file, trap 98, fatal.
+.IT 6.7.1
+It shall be an error if a variable-access used as an operand
+in an expression is undefined at the time of its use.
+.IS
+The compiler performs some limited checks to see if identifiers are
+used before they are set.
+Since it can not always be sure (one could, for
+instance, jump out of a loop), only a warning is generated.
+When an
+expression contains a function-call, an error occurs if the
+function is not assigned at run-time.
+.IT 6.7.2.2
+A term of the form x/y shall be an error if y is zero.
+.IS
+This error is detected (divide by 0.0, trap 7, non-fatal).
+.IT 6.7.2.2
+It shall be an error if j is zero in 'i div j'.
+.IS
+This error is detected (divide by 0, trap 6, non-fatal).
+.IT 6.7.2.2
+It shall be an error if
+j is zero or negative in i MOD j.
+.IS
+This error is detected (only positive j in 'i mod j', trap 71, non-fatal).
+.IT 6.7.2.2
+It shall be an error if the result of any operation on integer
+operands is not performed according to the mathematical
+rules for integer arithmetic.
+.IS
+This implementation does not detect integer overflow.
+.IT 6.8.3.5
+It shall be an error if none of the case-constants is equal to the
+value of the case-index upon entry to the case-statement.
+.IS
+This error is detected (case error, trap 20, fatal).
+.IT 6.9.1
+It shall be an error if the sequence of characters read looking for an
+integer does not form a signed-integer as specified in 6.1.5.
+.IS
+This error is detected (digit expected, trap 105, non-fatal).
+.IT 6.9.1
+It shall be an error if the sequence of characters read looking for a
+real does not form a signed-number as specified in 6.1.5.
+.IS
+This error is detected (digit expected, trap 105, non-fatal).
+.IT 6.9.1
+When read is applied to f, it shall be an error if the buffer-variable f^
+is undefined or the pre-assertions for get do not hold.
+.IS
+This error is detected (see get(f)).
+.IT 6.9.3
+When write is applied to a text file f, it shall be an error if f is
+undefined or f is opened for reading.
+.IS
+This error is detected (see put(f)).
+Furthermore, this error is also
+detected when f is not a text file.
+.IT 6.9.3.1
+The values of TotalWidth or FracDigits shall be greater than or equal to
+one; it shall be an error if either value is less then one.
+.IS
+When either value is less than zero, an error (illegal field width, trap
+75, non-fatal) occurs.
+Zero values are allowed, in order to maintain some
+compatibility with the old 
+.MX
+Pascal compiler.
+.IT 6.9.5
+It shall be an error if the pre-assertion required for writeln(f) doe not
+hold prior to the invocation of page(f);
+.IS
+This error is detected (see put(f)).
+.in 0
+.SS "Extensions to the standard"
+.LP
+.ft I
+1. External routines
+.LP
+Except for the required directive 'forward' the 
+.MX
+Pascal compiler recognizes
+the directive 'extern'.
+This directive tells the compiler that the procedure block of this
+procedure will not be present in the current program.
+The code for the body of this procedure must be included at a later
+stage of the compilation process.
+.PP
+This feature allows one to build libraries containing often used routines.
+These routines do not have to be included in all the programs using them.
+Maintenance is much simpler if there is only one library module to be
+changed instead of many Pascal programs.
+.PP
+Another advantage is that these library modules may be written in a different
+language, for instance C.
+.PP
+The use of external routines, however, is dangerous.
+The compiler normally checks for the correct number and type of parameters
+when a procedure is called and for the result type of functions.
+If an external routine is called these checks are not sufficient,
+because the compiler can not check whether the procedure heading of the
+external routine as given in the Pascal program matches the actual routine
+implementation.
+It should be the loader's task to check this.
+However, the current loaders are not that smart.
+.PP
+For those who wish the use the interface between C and Pascal we
+give an incomplete list of corresponding formal parameters in C and Pascal.
+.SP
+.XS
+.ta +\w'function a(pars):type   'u
+\fBPascal	C\fR
+a:integer	int a
+a:char	int a
+a:boolean	int a
+a:real	double a
+a:^type	type *a
+var a:type	type *a
+procedure a(pars)	struct {
+	     void (*a)() ;
+	     char *static_link ;
+	}
+function a(pars):type	struct {
+	     type (*a)() ;
+	     char *static_link ;
+	}
+.DT
+.XE
+The Pascal runtime system uses the following algorithm when calling
+function/procedures passed as parameters.
+.XS
+if (static_link) {
+	(*a)(static_link, pars);
+} else {
+	(*a)(pars);
+}
+.XE
+.LP
+.ft I
+2. Separate compilation.
+.LP
+The compiler is able to (separately) compile a collection of declarations,
+procedures and functions to form a library.
+The library may be linked with the main program, compiled later.
+The syntax of these modules is
+.XS
+.in +\w'module = 'u
+.ti -\w'module = 'u
+module = [constant-definition-part]
+[type-definition-part]
+[var-declaration-part]
+[procedure-and-function-declaration-part]
+.in -\w'module = 'u
+.XE
+The compiler accepts a program or a module:
+.XS
+unit = program | module
+.XE
+All variables declared outside a module must be imported
+by parameters, even the files input and output.
+Access to a variable declared in a module is only possible
+using the procedures and functions declared in that same module.
+By giving the correct procedure/function heading followed by the
+directive 'extern' you may use procedures and functions declared in
+other units.
+.LP
+.ft I
+3. Assertions.
+.LP
+When the s-option is off, 
+.MX
+Pascal compiler recognizes an additional
+statement, the assertion.
+Assertions can be used as an aid in debugging
+and documentation.
+The syntax is:
+.XS
+assertion = 'assert' Boolean-expression
+.XE
+An assertion is a simple-statement, so
+.XS
+.in +\w'simple-statement = ['u
+.ti -\w'simple-statement = ['u
+simple-statement = [assignment-statement |
+procedure-statement |
+goto-statement |
+assertion
+.in -\w'['u
+]
+.in -\w'simple-statement = 'u
+.XE
+An assertion causes an error if the Boolean-expression is false.
+That is its only purpose.
+It does not change any of the variables, at least it should not.
+Therefore, do not use functions with side-effects in the Boolean-expression.
+If the a-option is turned on, then assertions are skipped by the
+compiler. 'assert' is not a word-symbol (keyword) and may be used as identifier.
+However, assignment to a variable and calling of a procedure with that
+name will be impossible.
+If the s-option is turned on, the compiler will not know a thing about
+assertions, so using assertions will then give a parse error.
+.LP
+.ft I
+4. Additional procedures.
+.LP
+Three additional standard procedures are available:
+.IP "halt:"
+a call of this procedure is equivalent to jumping to the
+end of your program.
+It is always the last statement executed.
+The exit status of the program may be supplied
+as optional argument.
+If not, it will be zero.
+.IP release:
+.IP mark:
+for most applications it is sufficient to use the heap as second stack.
+Mark and release are suited for this type of use, more suited than dispose.
+mark(p), with p of type pointer, stores the current value of the
+heap pointer in p. release(p), with p initialized by a call
+of mark(p), restores the heap pointer to its old value.
+All the heap objects, created by calls of new between the call of
+mark and the call of release, are removed and the space they used
+can be reallocated.
+Never use mark and release together with dispose!
+.RE
+.LP
+.ft I
+5. UNIX interfacing.
+.LP
+If the c-option is turned on, then some special features are available
+to simplify an interface with the UNIX environment.
+First of all, the compiler allows you to use a different type
+of string constants.
+These string constants are delimited by double quotes ('"').
+To put a double quote into these strings, you must repeat the double quote,
+like the single quote in normal string constants.
+These special string constants are terminated by a zero byte (chr(0)).
+The type of these constants is a pointer to a packed array of characters,
+with lower bound 1 and unknown upper bound.
+.br
+Secondly, the compiler predefines a new type identifier 'string' denoting
+this just described string type.
+.PP
+The only thing you can do with these features is declaration of
+constants and variables of type 'string'.
+String objects may not be allocated on the heap and string pointers
+may not be de-referenced.
+Still these strings are very useful in combination with external routines.
+The procedure write is extended to print these zero-terminated
+strings correctly.
+.LP
+.ft I
+6. Double length (32 bit) integers.
+.LP
+If the d-option is turned on, then the additional type 'long' is known
+to the compiler.
+Long variables have integer values in the
+range \(mi2147483648 .. +2147483647.
+Long constants can not be declared.
+Longs can not be used as control-variables.
+It is not allowed to form subranges of type long.
+All operations allowed on integers are also
+allowed on longs and are indicated by the same
+operators: '+', '-', '*', '/', 'div', 'mod'.
+The procedures read and write have been extended to handle long
+arguments correctly.
+It is possible to read longs from a file of integers
+and vice-versa, but only if longs and integers have the same size.
+The default width for longs is 11.
+The standard procedures 'abs' and 'sqr' have been extended to work
+on long arguments.
+Conversion from integer to long, long to real,
+real to long and long to integer are automatic, like the conversion
+from integer to real.
+These conversions may cause a
+.PP
+.RS
+conversion error, trap 10, non-fatal
+.RE
+.LP
+.ft I
+7. Underscore as letter.
+.LP
+The character '_' may be used in forming identifiers, if the u- or U-option
+is turned on.
+It is forbidden to start identifiers with underscores, since
+this may cause name-clashes with run-time routines.
+.LP
+.ft I
+8. Zero field width in write.
+.LP
+Zero TotalWidth arguments are allowed.
+In this case, no characters are written for
+character, string or Boolean type arguments.
+A zero FracDigits
+argument for fixed-point representation of reals causes the fraction and
+the character '.' to be suppressed.
+.LP
+.ft I
+9. Pre-processing.
+.LP
+If the very first character of a file containing a Pascal
+program is the sharp ('#', ASCII 23(hex)) the file is preprocessed
+in the same way as C programs.
+Lines beginning with a '#' are taken as preprocessor command lines
+and not fed to the Pascal compiler proper.
+C style comments, /*......*/, are removed by the C preprocessor,
+thus C comments inside Pascal programs are also removed when they
+are fed through the preprocessor.
+.in 0
+.SS "Deviations from the standard"
+.PP
+.MX
+Pascal deviates from the standard in the following ways:
+.IP 1.
+Standard procedures and functions are not allowed as parameters in 
+.MX
+Pascal.
+You can obtain the same result with negligible loss of performance
+by declaring some user routines like:
+.XS
+.CW
+function sine(x:real):real;
+begin
+    sine:=sin(x)
+end;
+.ft R
+.XE
+.IP 2.
+The standard procedures read, readln, write and writeln are implemented as
+word-symbols, and can therefore not be redeclared.
+.SS "Compiler options"
+.PP
+Some options of the compiler may be controlled by using '{$....}'.
+Each option consists of a lower case letter followed by +, \(mi or an unsigned
+number.
+Options are separated by commas.
+The following options exist:
+.IP a+/\(mi
+This option switches assertions on and off.
+If this option is on, then code is included to test these assertions
+at run time.
+Default +.
+.IP c+/\(mi
+This option, if on, allows you to use C-type string constants
+surrounded by double quotes.
+Moreover, a new type identifier 'string' is predefined.
+Default \(mi.
+.IP d+/\(mi
+This option, if on, allows you to use variables of type 'long'.
+Default \(mi.
+.IP i<num>
+.br
+With this flag the setsize for a set of integers can be
+manipulated.
+The number must be the number of bits per set.
+The default value is 16.
+.IP l+/\(mi
+If + then code is inserted to keep track of the source line number.
+When this flag is switched on and off, an incorrect line number may appear
+if the error occurs in a part of your program for which this flag is off.
+Default +.
+.IP r+/\(mi
+If + then code is inserted to check subrange variables against
+lower and upper subrange limits.
+Default +.
+.IP s+/\(mi
+If + then the compiler will hunt for places in your program
+where non-standard features are used, and for each place found
+it will generate a warning.
+Default \(mi.
+.IP t+/\(mi
+If + then each time a procedure is entered, the routine 'procentry' is
+called, and each time a procedure exits, the procedure 'procexit' is
+called.
+Both 'procentry' and 'procexit' have a 'string' as parameter.
+This means that when a user specifies his or her own procedures, the c-option
+must be used.
+Default procedures are present in the run time library.
+Default \(mi.
+.IP u+/\(mi
+If + then the character '_' is treated like a letter,
+so that it may be used in identifiers.
+Procedure and function identifiers are not allowed to start with an
+underscore because they may collide with library routine names.
+Default \(mi.
+.PP
+Some of these flags (c, d, i, s, u, C and U) are only effective when
+they appear before the 'program' symbol.
+The others may be switched
+on and off.
+.PP
+A very powerful debugging tool is the knowledge that inaccessible statements
+and useless tests are removed by the optimizer.
+For instance, a statement like:
+.XS
+.CW
+if debug then
+    writeln('initialization done');
+.ft R
+.XE
+is completely removed by the optimizer if debug is a constant with
+value false.
+The first line is removed if debug is a constant with value true.
+Of course, if debug is a variable nothing can be removed.
+.SS "Library routines"
+.PP
+The following library of external routines for Pascal programs is available:
+.nf
+.SP
+.CW
+.ta 12n
+const	bufsize = ?;
+type	br1 =  1..bufsize;
+	br2 =  0..bufsize;
+	br3 = -1..bufsize;
+	ok = -1..0;
+	buf = packed array[br1] of char;
+	alfa = packed array[1..8] of char;
+	string = ^packed array[1..?] of char;
+	filetype = file of ?;
+	long = ?;
+.SP
+{all routines must be declared extern}
+.SP
+function	argc:integer;
+function	argv(i:integer):string;
+function	environ(i:integer):string;
+procedure	argshift;
+.SP
+procedure	buff(var f:filetype);
+procedure	nobuff(var f:filetype);
+procedure	notext(var f:text);
+procedure	diag(var f:text);
+procedure	pcreat(var f:text; s:string);
+procedure	popen(var f:text; s:string);
+procedure	pclose(var f:filetype);
+.SP
+procedure	trap(err:integer);
+procedure	encaps(procedure p; procedure q(n:integer));
+.SP
+function	perrno:integer;
+function	uread(fd:integer; var b:buf; len:br1):br3;
+function	uwrite(fd:integer; var b:buf; len:br1):br3;
+.SP
+function	strbuf(var b:buf):string;
+function	strtobuf(s:string; var b:buf; len:br1):br2;
+function	strlen(s:string):integer;
+function	strfetch(s:string; i:integer):char;
+procedure	strstore(s:string; i:integer; c:char);
+.SP
+function	clock:integer;
+.fi
+.ft R
+.PP
+This library contains some often used external routines for Pascal programs.
+The routines can be divided into several categories:
+.PP
+.ti -2
+Argument control:
+.RS
+.IP argc 10
+Gives the number of arguments provided when the program is called.
+.IP argv
+Selects the specified argument from the argument list and returns a
+pointer to it.
+This pointer is nil if the index is out of bounds (<0 or >=argc).
+.IP environ
+Returns a pointer to the i-th environment string (i>=0).
+Returns nil
+if i is beyond the end of the environment list (UNIX version 7).
+.IP argshift
+Effectively deletes the first argument from the argument list.
+Its function is equivalent to \fIshift\fR in the UNIX shell: argv[2] becomes
+argv[1], argv[3] becomes argv[2], etc.
+It is a useful procedure to skip optional flag arguments.
+Note that the matching of arguments and files
+is done at the time a file is opened by a call to reset or rewrite.
+.PP
+.ti -2
+Additional file handling routines:
+.IP buff
+Turn on buffering of a file.
+Not very useful, because all
+files are buffered except standard output to a terminal and diagnostic output.
+Input files are always buffered.
+.IP nobuff
+Turn off buffering of an output file.
+It causes the current contents of the
+buffer to be flushed.
+.IP notext
+Only useful for input files.
+End of line characters are not replaced by a space and character codes out of
+the ASCII range (0..127) do not cause an error message.
+.IP diag
+Initialize a file for output on the diagnostic output stream (fd=2).
+Output is not buffered.
+.IP pcreat
+The same as rewrite(f), except that you must provide the file name yourself.
+The name must be zero terminated.
+Only text files are allowed.
+.IP popen
+The same as reset(f), except that you must provide the file name yourself.
+The name must be zero terminated.
+Only text files are allowed.
+.IP pclose
+Gives you the opportunity to close files hidden in records or arrays.
+All other files are closed automatically.
+.PP
+.ti -2
+String handling:
+.IP strbuf
+Type conversion from character array to string.
+It is your own responsibility that the string is zero terminated.
+.IP strtobuf
+Copy string into buffer until the string terminating zero byte
+is found or until the buffer if full, whatever comes first.
+The zero byte is also copied.
+The number of copied characters, excluding the zero byte, is returned.
+So if
+the result is equal to the buffer length, then the end of buffer is reached
+before the end of string.
+.IP strlen
+Returns the string length excluding the terminating zero byte.
+.IP strfetch
+Fetches the i-th character from a string.
+There is no check against the string length.
+.IP strstore
+Stores a character in a string.
+There is no check against
+string length, so this is a dangerous procedure.
+.PP
+.ti -2
+Trap handling:
+.PP
+These routines allow you to handle almost all
+the possible error situations yourself.
+You may define your own trap handler, replacing the
+default handler that produces an error message and quits.
+You may also generate traps yourself.
+.IP trap
+Trap generates the trap passed as argument (0..252).
+The trap numbers 128..252 may be used freely.
+The others are reserved.
+.IP encaps
+Encapsulate the execution of \fIp\fR with the trap handler \fIq\fR.
+Encaps replaces the previous trap handler by \fIq\fR, calls \fIp\fR
+and restores
+the previous handler when \fIp\fR returns.
+If, during the execution of \fIp\fR, a trap occurs,
+then \fIq\fR is called with the trap number as parameter.
+For the duration of \fIq\fR the previous trap handler is restored, so that
+you may handle only some of the errors in \fIq\fR.
+All the other errors must
+then be raised again by a call to \fItrap\fR.
+.br
+Encapsulations may be nested: you may encapsulate a procedure while executing
+an encapsulated routine.
+.br
+Jumping out of an encapsulated procedure (non-local goto) is dangerous,
+because the previous trap handler must be restored.
+Therefore, you may only jump out of procedure \fIp\fR from inside \fIq\fR and
+you may only jump out of one level of encapsulation.
+If you want to exit several levels of encapsulation, use traps.
+See pc_prlib(7) for lists of trap numbers
+for EM machine errors and Pascal run time system errors.
+Note that \fIp\fR may not have parameters.
+.PP
+.ti -2
+UNIX system calls:
+.IP uread
+Equal to the read system call.
+Its normal name is blocked by the standard Pascal routine read.
+.IP uwrite
+As above but for write(2).
+.IP perrno
+Because external data references are not possible in Pascal,
+this routine returns the global variable \fIerrno\fR, indicating the result of
+the last system call.
+.PP
+.ti -2
+Miscellaneous:
+.IP clock
+Return the number of ticks of user and system time consumed by the program.
+.PP
+The following program presents an example of how these routines can be used.
+This program is equivalent to the UNIX command cat(1).
+.nf
+.SP
+.CW
+{$c+}
+.CW
+program cat(input,inp,output);
+.CW
+var	inp:text;
+.CW
+	s:string;
+.SP
+.CW
+function argc:integer; extern;
+.CW
+function argv(i:integer):string; extern;
+.CW
+procedure argshift; extern;
+.CW
+function strlen(s:string):integer; extern;
+.CW
+function strfetch(s:string; i:integer):char; extern;
+.SP
+.CW
+procedure copy(var fi:text);
+.CW
+var c:char;
+.CW
+begin reset(fi);
+.CW
+  while not eof(fi) do
+.CW
+  begin
+.CW
+    while not eoln(fi) do
+.CW
+    begin
+.CW
+      read(fi,c);
+.CW
+      write(c)
+.CW
+    end;
+.CW
+    readln(fi);
+.CW
+    writeln
+.CW
+  end
+.CW
+end;
+.SP
+.CW
+begin  {main}
+.CW
+  if argc = 1 then
+.CW
+    	copy(input)
+.CW
+  else
+.CW
+    repeat
+.CW
+      s := argv(1);
+.CW
+      if (strlen(s) = 1) and (strfetch(s,1) = '-')
+.CW
+      then copy(input)
+.CW
+      else copy(inp);
+.CW
+      argshift;
+.CW
+    until argc <= 1;
+.CW
+end.
+.fi
+.ft R
+.PP
+Another example gives some idea of the way to manage trap handling:
+.nf
+.SP
+.CW
+program bigreal(output);
+.CW
+const EFOVFL=4;
+.CW
+var trapped:boolean;
+.CW
+.SP
+.CW
+procedure encaps(procedure p; procedure q(n:integer)); extern;
+.CW
+procedure trap(n:integer); extern;
+.CW
+.SP
+.CW
+procedure traphandler(n:integer);
+.CW
+begin if n=EFOVFL then trapped:=true else trap(n) end;
+.CW
+.SP
+.CW
+procedure work;
+.CW
+var i,j:real;
+.CW
+begin trapped:=false; i:=1;
+.CW
+  while not trapped do
+.CW
+    begin j:=i; i:=i*2 end;
+.CW
+  writeln('bigreal = ',j);
+.CW
+end;
+.CW
+.SP
+.CW
+begin
+.CW
+  encaps(work,traphandler);
+.CW
+end.
+.fi
+.ft R
+.PP
+Two routines may cause fatal error messages to be generated.
+These are:
+.IP pcreat
+Rewrite error (trap 77) if the file cannot be created.
+.IP popen
+Reset error (trap 76) if the file cannot be opened for reading
+.SS References
+.IP [1]
+BSI standard BS 6192: 1982 (ISO 7185).
+.IP [2]
+A.S.Tanenbaum, J.W.Stevenson, Hans van Staveren, E.G.Keizer,
+"Description of a machine architecture for use with block structured languages",
+Informatica rapport IR-81.
Index: /trunk/minix/man/man7/ascii.7
===================================================================
--- /trunk/minix/man/man7/ascii.7	(revision 9)
+++ /trunk/minix/man/man7/ascii.7	(revision 9)
@@ -0,0 +1,76 @@
+.TH ASCII 7
+.SH NAME
+ascii \- the ASCII character set.
+.SH DESCRIPTION
+The ASCII character set is as follows:
+.PP
+.nf
+.if t .ft C
+|000 nul|001 soh|002 stx|003 etx|004 eot|005 enq|006 ack|007 bel|
+|010 bs |011 ht |012 nl |013 vt |014 np |015 cr |016 so |017 si |
+|020 dle|021 dc1|022 dc2|023 dc3|024 dc4|025 nak|026 syn|027 etb|
+|030 can|031 em |032 sub|033 esc|034 fs |035 gs |036 rs |037 us |
+|040 sp |041  ! |042  " |043  # |044  $ |045  % |046  & |047  ' |
+|050  ( |051  ) |052  * |053  + |054  , |055  - |056  . |057  / |
+|060  0 |061  1 |062  2 |063  3 |064  4 |065  5 |066  6 |067  7 |
+|070  8 |071  9 |072  : |073  ; |074  < |075  = |076  > |077  ? |
+|100  @ |101  A |102  B |103  C |104  D |105  E |106  F |107  G |
+|110  H |111  I |112  J |113  K |114  L |115  M |116  N |117  O |
+|120  P |121  Q |122  R |123  S |124  T |125  U |126  V |127  W |
+|130  X |131  Y |132  Z |133  [ |134  \e |135  ] |136  ^ |137  _ |
+|140  ` |141  a |142  b |143  c |144  d |145  e |146  f |147  g |
+|150  h |151  i |152  j |153  k |154  l |155  m |156  n |157  o |
+|160  p |161  q |162  r |163  s |164  t |165  u |166  v |167  w |
+|170  x |171  y |172  z |173  { |174  | |175  } |176  ~ |177 del|
+
+|00 nul|01 soh|02 stx|03 etx|04 eot|05 enq|06 ack|07 bel|
+|08 bs |09 ht |0A nl |0B vt |0C np |0D cr |0E so |0F si |
+|10 dle|11 dc1|12 dc2|13 dc3|14 dc4|15 nak|16 syn|17 etb|
+|18 can|19 em |1A sub|1B esc|1C fs |1D gs |1E rs |1F us |
+|20 sp |21  ! |22  " |23  # |24  $ |25  % |26  & |27  ' |
+|28  ( |29  ) |2A  * |2B  + |2C  , |2D  - |2E  . |2F  / |
+|30  0 |31  1 |32  2 |33  3 |34  4 |35  5 |36  6 |37  7 |
+|38  8 |39  9 |3A  : |3B  ; |3C  < |3D  = |3E  > |3F  ? |
+|40  @ |41  A |42  B |43  C |44  D |45  E |46  F |47  G |
+|48  H |49  I |4A  J |4B  K |4C  L |4D  M |4E  N |4F  O |
+|50  P |51  Q |52  R |53  S |54  T |55  U |56  V |57  W |
+|58  X |59  Y |5A  Z |5B  [ |5C  \e |5D  ] |5E  ^ |5F  _ |
+|60  ` |61  a |62  b |63  c |64  d |65  e |66  f |67  g |
+|68  h |69  i |6A  j |6B  k |6C  l |6D  m |6E  n |6F  o |
+|70  p |71  q |72  r |73  s |74  t |75  u |76  v |77  w |
+|78  x |79  y |7A  z |7B  { |7C  | |7D  } |7E  ~ |7F del|
+
+.if t .ft P
+.nf
+.bp
+These are what your terminal shows for the top 96 codes:
+.PP
+.nf
+.if t .ft C
+|240    |241  ¡ |242  ¢ |243  £ |244  € |245  ¥ |246  Š |247  § |
+|250  š |251  © |252  ª |253  « |254  ¬ |255  ­ |256  ® |257  ¯ |
+|260  ° |261  ± |262  ² |263  ³ |264  Ž |265  µ |266  ¶ |267  · |
+|270  ž |271  ¹ |272  º |273  » |274  Œ |275  œ |276  Ÿ |277  ¿ |
+|300  À |301  Á |302  Â |303  Ã |304  Ä |305  Å |306  Æ |307  Ç |
+|310  È |311  É |312  Ê |313  Ë |314  Ì |315  Í |316  Î |317  Ï |
+|320  Ð |321  Ñ |322  Ò |323  Ó |324  Ô |325  Õ |326  Ö |327  × |
+|330  Ø |331  Ù |332  Ú |333  Û |334  Ü |335  Ý |336  Þ |337  ß |
+|340  à |341  á |342  â |343  ã |344  ä |345  å |346  æ |347  ç |
+|350  è |351  é |352  ê |353  ë |354  ì |355  í |356  î |357  ï |
+|360  ð |361  ñ |362  ò |363  ó |364  ô |365  õ |366  ö |367  ÷ |
+|370  ø |371  ù |372  ú |373  û |374  ü |375  ý |376  þ |377  ÿ |
+
+|A0    |A1  ¡ |A2  ¢ |A3  £ |A4  € |A5  ¥ |A6  Š |A7  § |
+|A8  š |A9  © |AA  ª |AB  « |AC  ¬ |AD  ­ |AE  ® |AF  ¯ |
+|B0  ° |B1  ± |B2  ² |B3  ³ |B4  Ž |B5  µ |B6  ¶ |B7  · |
+|B8  ž |B9  ¹ |BA  º |BB  » |BC  Œ |BD  œ |BE  Ÿ |BF  ¿ |
+|C0  À |C1  Á |C2  Â |C3  Ã |C4  Ä |C5  Å |C6  Æ |C7  Ç |
+|C8  È |C9  É |CA  Ê |CB  Ë |CC  Ì |CD  Í |CE  Î |CF  Ï |
+|D0  Ð |D1  Ñ |D2  Ò |D3  Ó |D4  Ô |D5  Õ |D6  Ö |D7  × |
+|D8  Ø |D9  Ù |DA  Ú |DB  Û |DC  Ü |DD  Ý |DE  Þ |DF  ß |
+|E0  à |E1  á |E2  â |E3  ã |E4  ä |E5  å |E6  æ |E7  ç |
+|E8  è |E9  é |EA  ê |EB  ë |EC  ì |ED  í |EE  î |EF  ï |
+|F0  ð |F1  ñ |F2  ò |F3  ó |F4  ô |F5  õ |F6  ö |F7  ÷ |
+|F8  ø |F9  ù |FA  ú |FB  û |FC  ü |FD  ý |FE  þ |FF  ÿ |
+.if t .ft P
+.nf
Index: /trunk/minix/man/man7/environ.7
===================================================================
--- /trunk/minix/man/man7/environ.7	(revision 9)
+++ /trunk/minix/man/man7/environ.7	(revision 9)
@@ -0,0 +1,111 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)environ.7	6.1 (Berkeley) 5/20/85
+.\"
+.TH ENVIRON 7 "May 20, 1985"
+.UC 5
+.SH NAME
+environ \- user environment
+.SH SYNOPSIS
+.B "extern char *const *environ;"
+.SH DESCRIPTION
+An array of strings called the `environment' is made available by
+.BR execve (2)
+when a process begins.  By convention these strings have the form
+.RI ` name = value '.
+The following names are used by various commands:
+.TP "\w'TERMCAP 'u"
+.B PATH
+The sequence of directory prefixes that
+.BR sh ,
+.BR time ,
+.BR nice (1),
+etc., apply in searching for a file known by an incomplete path name.
+The prefixes are separated by `:'.
+Login shells set
+.BR PATH=:/bin:/usr/bin .
+Note that the empty space between the `=' and the `:' indicates the current
+directory.  Security aware people move the extra `:' to the end of their
+path or omit it.
+.TP
+.B HOME
+A user's login directory, set by
+.BR login (1)
+from the password file
+.BR passwd (5).
+.TP
+.B TERM
+The kind of terminal for which output is to be prepared.
+This information is used by programs that wish to exploit special
+terminal capabilities, a screen oriented text editor for instance.
+The terminal type is set by
+.BR login (1)
+from the tty database
+.BR ttytab (5).
+.TP
+.B SHELL
+The file name of the users login shell, set by
+.BR login (1)
+from the password file
+.BR passwd (5).
+.TP
+.B TERMCAP
+The string describing the terminal in TERM, or the name of the termcap file,
+see
+.BR termcap (5),
+.BR termcap (3).
+.TP
+.B EXINIT
+A startup list of commands read by
+.BR elvis (1).
+.TP
+.B USER
+The login name of the user, set by
+.BR login (1)
+from the password file
+.BR passwd (5).
+.TP
+.B LOGNAME
+Set to the same value as
+.BR USER .
+BSD derived systems have
+.BR USER ,
+System V has
+.BR LOGNAME ,
+so modern systems have both to avoid problems.
+.TP
+.PP
+Further names may be placed in the environment by the
+.B export
+command and
+.RI ` name = value '
+arguments in
+.BR sh (1).
+Arguments may also be placed in their environment by
+programs if they use
+.BR putenv (3).
+Or in the environment of another program by building a new environment
+for one of the exec functions that accepts an environment list, like
+.BR execle (2)
+or
+.BR execve (2).
+It is unwise to conflict with certain 
+.BR sh (1)
+variables that are frequently set and/or exported by `.profile' files:
+.BR MAIL ,
+.BR PS1 ,
+.BR PS2 ,
+.BR IFS .
+.SH SEE ALSO
+.BR elvis (1),
+.BR login (1),
+.BR sh (1),
+.BR execl (3),
+.BR execve (2),
+.BR system (3),
+.BR termcap (3),
+.BR termcap (5),
+.BR passwd (5),
+.BR ttytab (5).
Index: /trunk/minix/man/man7/hier.7
===================================================================
--- /trunk/minix/man/man7/hier.7	(revision 9)
+++ /trunk/minix/man/man7/hier.7	(revision 9)
@@ -0,0 +1,195 @@
+.TH HIER 7
+.SH NAME
+hier \- file system hierarchy
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+A tour through the MINIX 3 directory hierarchy.
+.nf
+.SP
+/	root
+.SP
+/bin/	Utility programs, cf /usr/bin/ (1)
+	cat	Show files, \fBcat\fP(1)
+	sh	Shell, \fBsh\fP(1)
+	mount	Mount file systems, \fBmount\fP(8)
+	...
+.SP
+/boot	Boot Monitor, \fBmonitor\fP(8)
+.SP
+/dev/	devices (4)
+	console
+		Main console, \fBtty\fP(4)
+	tty*	Terminals, \fBtty\fP(4)
+	hd*	Hard disk, \fBhd\fP(4)
+	fd*	Floppy disk, \fBfd\fP(4)
+	...
+.SP
+/etc/	System configuration and data files, cf /usr/etc/ (1,5,8)
+	ethers	Ethernet addresses database, \fBethers\fP(5)
+	fstab	File system table, \fBfstab\fP(5)
+	group	Groups database, \fBgroup\fP(5)
+	hostname.file
+		Name of the local system, \fBusage\fP(5)
+	hosts	TCP/IP hosts database, \fBhosts\fP(5)
+	hosts.equiv
+		Network equivalent hosts, \fBhosts.equiv\fP(5)
+	inet.conf
+		Inet server config file, \fBinet\fP(8)
+	keymap	Keymap for custom keyboard, \fBloadkeys\fP(8)
+	motd	Message of the day, \fBlogin\fP(1)
+	mtab	Mounted file system table, \fBfstab\fP(5)
+	passwd	User database, \fBpasswd\fP(5)
+	profile
+		System wide shell profile, \fBsh\fP(1)
+	rc	System startup script, \fBboot\fP(8)
+	resolv.conf
+		TCP/IP domain name system, \fBresolv.conf\fP(5)
+	services
+		TCP/IP names to services, \fBservices\fP(5)
+	serv.access
+		Internet service access control, \fBserv.access\fP(5)
+	shadow	Shadow password database, \fBpasswd\fP(5)
+	termcap
+		Terminal type descriptions, \fBtermcap\fP(5)
+	ttytab	Terminals device table, \fBttytab\fP(5)
+	utmp	User login database, \fBlogin\fP(1)
+	...
+.SP
+/minix
+	MINIX 3 kernel image, \fBmonitor\fP(8)
+.SP
+/tmp/	Small, short-lived temporary files, cf /usr/tmp/
+.SP
+/usr/	Home directories and more system files
+.SP
+	adm/	System administration files (1,5,8)
+		lastlog
+			Last logins, \fBlogin\fP(1)
+		log
+			Default log file
+		old
+			Last weeks log files
+		wtmp
+			User logins and logouts, \fBlogin\fP(1)
+		*.cache
+			Cached data of some programs
+		...
+.SP
+	ast/	Honorary home directory of Andrew S. Tanenbaum
+		Also new user initial files
+.SP
+	\fIuser\fP/	Home directory of \fIuser\fP
+		.ashrc	Ash (shell) startup, \fBash\fP(1)
+		.ellepro.b1
+			Elle (editor) startup (compiled), \fBelle\fP(1)
+		.ellepro.e
+			Elle (editor) startup (text), \fBelle\fP(1)
+		.exrc	Ex/vi (editor) startup, \fBex\fP(1)
+		.profile
+			Custom user shell profile, \fBsh\fP(1)
+		.rhosts	Remote user permission file, \fBrhosts\fP(5)
+		...
+.SP
+	bin/	User programs
+		cc	C compiler, \fBcc\fP(1)
+		cp	Copy files, \fBcp\fP(1)
+		ls	List files, \fBls\fP(1)
+		man	Show manual pages, \fBman\fP(1)
+		...
+.SP
+	etc/	More system data files, cf /etc (8)
+		rc	Continued system startup, \fBboot\fP(8)
+		daily
+			Daily system cleanup
+		...
+.SP
+	include/
+		C-compiler include files
+		minix/	MINIX 3 kernel include files
+			...
+		...
+.SP
+	lib/	Compiler libraries and other support stuff
+		cawf/	Text formatter support files, \fBcawf\fP(1)
+		crontab
+			Cron jobs, \fBcron\fP(8)
+		dict/	Word lists
+			words	American English word list, \fBlook\fP(1)
+			...
+		libc.a	C library (Minix-8086 only), \fBcc\fP(1)
+		\fIarch\fP	Per architecture compiler binaries and
+			libaries, \fBcc\fP(1)
+		...
+.SP
+	local/	Local software, cf /usr/
+		bin/	Local utilities
+		etc/	Local data files
+			rc	Local system startup
+			...
+		man/	Local manual pages
+		src/	Local sources
+		...
+.SP
+	man/	Manual pages, \fBman\fP(1)
+		cat*/	Preformatted manual pages
+		man0/	Section 0, Book style user commands
+		man1/	User commands
+		man2/	System calls
+		man3/	Library routines
+		man4/	Device files
+		man5/	File formats
+		man6/	Games
+		man7/	Miscellaneous
+		man8/	System utilities
+		whatis	Table of manual pages, \fBwhatis\fP(5)
+		...
+.SP
+	mdec/
+		boot	Bootstrap code, \fBinstallboot\fP(8)
+		...
+.SP
+	preserve/
+		Saved elvis editor buffers, \fBelvprsv\fP(8), \fBelvrec\fP(1)
+.SP
+	spool/	Mail and command spooling
+		at/	At jobs, \fBat\fP(1)
+			past/	Completed at jobs
+		mail/	Mail drops, \fBmail\fP(1)
+			\fIuser\fP	Mailbox of \fIuser\fP
+			...
+		...
+.SP
+	src/	System and command sources (home of bin)
+		LICENSE
+			MINIX 3 license to use
+		commands/
+			Utility sources
+		crclist
+			CRC checksums of the source tree, \fBsrccrc\fP(8)
+		lib/	Library sources
+		fs/	File system
+		inet/	TCP/IP task
+		kernel/
+			Kernel
+		mm/	Memory manager
+		boot/	Boot Monitor
+		tools/	Kernel image making tools, \fBtools\fP(8)
+.SP
+	tmp/	Large temporary files
+.fi
+.SH "SEE ALSO"
+.BR ls (1),
+.BR man (1),
+.BR find (1),
+.BR grep (1),
+.BR checkhier (8).
+.SH NOTES
+Not all of the directories and files shown are present.  They must be
+created as needed.
+.SH BUGS
+Many of the listed manual references do not yet exist.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man7/man.7
===================================================================
--- /trunk/minix/man/man7/man.7	(revision 9)
+++ /trunk/minix/man/man7/man.7	(revision 9)
@@ -0,0 +1,278 @@
+.\" man(7) manpage by rosenkra@hall.cray.com (Bill Rosenkranz)
+.\" Modified a bit for MINIX 3 by Kees J. Bot (kjb@cs.vu.nl)
+.\"
+.TH MAN 7
+.SH NAME
+man - nroff macro package for manual pages
+.SH SYNOPSIS
+.B nroff \-man
+.IR file " ..."
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+These macros are used to lay out reference pages for manuals.
+.PP
+Any text argument
+.I t
+may be zero to six words.  Quotes may be used to include blanks in a 'word'.
+.I Text
+can be empty, but unlike normal \s-2UNIX\s+2 macros, the next line is not used.
+.PP
+A prevailing indent distance is remembered between successive
+indented paragraphs, and is reset to default value upon
+reaching a non-indented paragraph (i.e. at .SH or .SS).
+.SH FILES
+.TP 25n
+/usr/lib/tmac/tmac.an
+For standard MINIX 3 nroff.
+.TP
+/usr/lib/cawf/man.mac
+For cawf.
+.SH SEE ALSO
+.BR nroff (1),
+.BR man (1).
+.SH "REQUEST SUMMARY"
+.nf
+.ta +15n +9n
+Request	Cause	Explanation
+	Break? 
+
+\&.B t	no	Text t is bold. Quote to imbed blanks.
+\&.I t	no	Text t is italic. Quote to imbed blanks.
+\&.IP x	yes	Set prevailing indent to 5. Begin
+		indented paragraph with hanging tag
+		given by first argument.	Tag x is
+		always placed on a separate line.
+\&.LP	yes	Same as .PP.
+\&.PP	yes	Begin paragraph.	Set prevailing
+		indent to 5.
+\&.RE	yes	End of relative indent.	Set prevailing
+		indent to amount of starting .RS.
+\&.RS	yes	Start relative indent, move left margin
+		in distance 5.
+\&.SH t	yes	Subhead. Quote to imbed blanks.
+\&.SS t	yes	Subsection. Quote to imbed blanks. No
+		indent for t.
+\&.TH n s c v d	yes	Begin page named n of chapter s; c is
+		the chapter name; d is the date of the
+		most recent change; v is version number.
+		Sets prevailing indent and tabs to 5.
+.fi
+.SH EXAMPLE
+The following illustrates some of the requests available
+with this macro package:
+.RS
+.nf
+\&.\e" this is a comment
+\&.TH DEMO 1
+\&.SH NAME
+demo \e- show how to use \e-man package
+\&.SH SYNOPSIS
+\&.B demo
+\&.RI [ options ]
+\&.IR file " ..."
+\&.SH DESCRIPTION
+This is a test for showing how to use the
+\&.BR nroff (1)
+man package. It shows how to use .TH, .SH, .PP, .B, .I, and .IP
+commands.
+\&.PP
+This will be a new paragraph. You can also use normal
+\&.BR nroff (1)
+commands in the text.
+\&.SS Nroff Commands
+\&.IP '\ee"'
+This is the comment command.  \e" You won't see this.
+\&.IP nf
+No fill mode (the normal mode is fill mode where things
+get justified right and left).
+\&.IP fi
+Re-enter fill mode.
+\&.IP br
+Break line here no matter what.
+\&.IP sp
+Vertical space (also causes a break to occur).
+\&.sp
+Note that to continue an indent and make a new paragraph (as
+is the case here), just put in a space (.sp).
+\&.PP
+Now we should be at a new paragraph.
+.fi
+.RE
+.PP
+Executing
+.B nroff \-man demo.man
+results in the following output:  (Ignoring page headers and footers)
+.PP
+.RS
+.B NAME
+.RS
+demo \e- show how to use \e-man package
+.RE
+.SP
+.B SYNOPSIS
+.RS
+.B demo
+.RI [ options ]
+.IR file " ..."
+.RE
+.SP
+.B DESCRIPTION
+.RS
+This is a test for showing how to use the
+.BR nroff (1)
+man package. It shows how to use .TH, .SH, .PP, .B, .I, and .IP
+commands.
+.SP
+This will be a new paragraph. You can also use normal
+.BR nroff (1)
+commands in the text.
+.RE
+.SP
+.ti +2n
+.B Nroff Commands
+.RS
+.RS
+.ta +5n
+.SP
+.ti -5n
+\&'\e"'	This is the comment command.
+.SP
+.ti -5n
+nf	No fill mode (the normal mode is fill mode where things
+get justified right and left).
+.SP
+.ti -5n
+fi	Re-enter fill mode.
+.SP
+.ti -5n
+br	Break line here no matter what.
+.SP
+.ti -5n
+sp	Vertical space (also causes a break to occur).
+.sp
+Note that to continue an indent and make a new paragraph (as
+is the case here), just put in a space (.sp).
+.RE
+.SP
+Now we should be at a new paragraph.
+.RE
+.RE
+.SH CONVENTIONS
+A typical manual page for a command or function is laid out as follows:
+.nf
+
+     .TH TITLE [1-8]
+          The name of the command or function in upper-case,
+          which serves as the title of the manual page. This is
+          followed by the number of the section in which it
+          appears.
+
+     .SH NAME
+          name - one-line summary
+
+          The name, or list of names, by which the command is
+          called, followed by a dash and then a one-line summary
+          of the action performed.  All in roman font, this sec-
+          tion contains no troff(1) commands or escapes, and no
+          macro requests.  It is used to generate the whatis(1)
+          database.
+
+     .SH SYNOPSIS
+
+          Commands:
+
+               The syntax of the command and its arguments as
+               typed on the command line.  When in boldface, a
+               word must be typed exactly as printed.  When in
+               italics, a word can be replaced with text that you
+               supply.  Syntactic symbols appear in roman face:
+
+               [ ]  An argument, when surrounded by brackets is
+                    optional.
+
+               |    Arguments separated by a vertical bar are
+                    exclusive.  You can supply only item from
+                    such a list.
+
+               ...  Arguments followed by an elipsis can be
+                    repeated.  When an elipsis follows a brack-
+                    eted set, the expression within the brackets
+                    can be repeated.
+
+          Functions:
+
+               If required, the data declaration, or #include
+               directive, is shown first, followed by the  func-
+               tion declaration. Otherwise, the function declara-
+               tion is shown.
+
+     .SH DESCRIPTION
+          A narrative description of the command or function in
+          detail, including how it interacts with files or data,
+          and how it handles the standard input, standard output
+          and standard error.
+
+          Filenames, and references to commands or functions
+          described elswhere in the manual, are italicised.  The
+          names of options, variables and other literal terms are
+          in boldface.
+
+     .SH OPTIONS
+          The list of options along with a description of how
+          each affects the commands operation.
+
+     .SH ENVIRONMENT
+          Environment variables used.
+
+     .SH FILES
+          A list of files associated with the command or func-
+          tion.
+
+     .SH "SEE ALSO"
+          A comma-separated list of related manual pages,
+          followed by references to other published materials.
+          This section contains no troff(1) escapes or commands,
+          and no macro requests.
+
+     .SH DIAGNOSTICS
+          A list of diagnostic messages and an explanation of
+          each.
+
+     .SH NOTES
+          Any additional notes such as installation-dependent
+          functionality.
+
+     .SH BUGS
+          A description of limitations, known defects, and possi-
+          ble problems associated with the command or function.
+
+     .SH AUTHOR
+          The program's author and any pertinent release info.
+
+     .SH VERSION
+          The program's current version number and release date.
+.fi
+.SH BUGS
+Even though
+.BR cawf (1)
+has a better chance at formatting a random manual page then the standard
+MINIX 3 nroff, it has two annoying bugs in its macro set.  Both .PP and .IP 
+reset the indentation level to the level set by .SH.  This means that
+you can't use them in a piece of text indented by .RS.  For .IP this is
+troublesome, you can see why in the unformatted source of this text.  .PP
+can simply be replaced by .sp, or better yet, by .SP with the following
+macro defined somewhere in your text:
+.PP
+.RS
+.nf
+\&.de SP
+\&.if t .sp 0.4
+\&.if n .sp
+\&..
+.fi
+.RE
+.PP
+This will make .SP use 4/10 of a line if formatted by troff, just like .PP.
Index: /trunk/minix/man/man7/re_format.7
===================================================================
--- /trunk/minix/man/man7/re_format.7	(revision 9)
+++ /trunk/minix/man/man7/re_format.7	(revision 9)
@@ -0,0 +1,269 @@
+.\" Copyright (c) 1992, 1993, 1994 Henry Spencer.
+.\" Copyright (c) 1992, 1993, 1994
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Henry Spencer.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)re_format.7	8.3 (Berkeley) 3/20/94
+.\"
+.TH RE_FORMAT 7 "March 20, 1994"
+.SH NAME
+re_format \- POSIX 1003.2 regular expressions
+.SH DESCRIPTION
+Regular expressions (``RE''s),
+as defined in POSIX 1003.2, come in two forms:
+modern REs (roughly those of
+.BR egrep ;
+1003.2 calls these ``extended'' REs)
+and obsolete REs (roughly those of
+.BR ed ;
+1003.2 ``basic'' REs).
+Obsolete REs mostly exist for backward compatibility in some old programs;
+they will be discussed at the end.
+1003.2 leaves some aspects of RE syntax and semantics open;
+`\(dg' marks decisions on these aspects that
+may not be fully portable to other 1003.2 implementations.
+.PP
+A (modern) RE is one\(dg or more non-empty\(dg \fIbranches\fR,
+separated by `|'.
+It matches anything that matches one of the branches.
+.PP
+A branch is one\(dg or more \fIpieces\fR, concatenated.
+It matches a match for the first, followed by a match for the second, etc.
+.PP
+A piece is an \fIatom\fR possibly followed
+by a single\(dg `*', `+', `?', or \fIbound\fR.
+An atom followed by `*' matches a sequence of 0 or more matches of the atom.
+An atom followed by `+' matches a sequence of 1 or more matches of the atom.
+An atom followed by `?' matches a sequence of 0 or 1 matches of the atom.
+.PP
+A \fIbound\fR is `{' followed by an unsigned decimal integer,
+possibly followed by `,'
+possibly followed by another unsigned decimal integer,
+always followed by `}'.
+The integers must lie between 0 and RE_DUP_MAX (255\(dg) inclusive,
+and if there are two of them, the first may not exceed the second.
+An atom followed by a bound containing one integer \fIi\fR
+and no comma matches
+a sequence of exactly \fIi\fR matches of the atom.
+An atom followed by a bound
+containing one integer \fIi\fR and a comma matches
+a sequence of \fIi\fR or more matches of the atom.
+An atom followed by a bound
+containing two integers \fIi\fR and \fIj\fR matches
+a sequence of \fIi\fR through \fIj\fR (inclusive) matches of the atom.
+.PP
+An atom is a regular expression enclosed in `()' (matching a match for the
+regular expression),
+an empty set of `()' (matching the null string)\(dg,
+a \fIbracket expression\fR (see below), `.'
+(matching any single character), `^' (matching the null string at the
+beginning of a line), `$' (matching the null string at the
+end of a line), a `\e' followed by one of the characters
+`^.[$()|*+?{\e'
+(matching that character taken as an ordinary character),
+a `\e' followed by any other character\(dg
+(matching that character taken as an ordinary character,
+as if the `\e' had not been present\(dg),
+or a single character with no other significance (matching that character).
+A `{' followed by a character other than a digit is an ordinary
+character, not the beginning of a bound\(dg.
+It is illegal to end an RE with `\e'.
+.PP
+A \fIbracket expression\fR is a list of characters enclosed in `[]'.
+It normally matches any single character from the list (but see below).
+If the list begins with `^',
+it matches any single character
+(but see below) \fInot\fR from the rest of the list.
+If two characters in the list are separated by `\-', this is shorthand
+for the full \fIrange\fR of characters between those two (inclusive) in the
+collating sequence,
+e.g. `[0-9]' in ASCII matches any decimal digit.
+It is illegal\(dg for two ranges to share an
+endpoint, e.g. `a-c-e'.
+Ranges are very collating-sequence-dependent,
+and portable programs should avoid relying on them.
+.PP
+To include a literal `]' in the list, make it the first character
+(following a possible `^').
+To include a literal `\-', make it the first or last character,
+or the second endpoint of a range.
+To use a literal `\-' as the first endpoint of a range,
+enclose it in `[.' and `.]' to make it a collating element (see below).
+With the exception of these and some combinations using `[' (see next
+paragraphs), all other special characters, including `\e', lose their
+special significance within a bracket expression.
+.PP
+Within a bracket expression, a collating element (a character,
+a multi-character sequence that collates as if it were a single character,
+or a collating-sequence name for either)
+enclosed in `[.' and `.]' stands for the
+sequence of characters of that collating element.
+The sequence is a single element of the bracket expression's list.
+A bracket expression containing a multi-character collating element 
+can thus match more than one character,
+e.g. if the collating sequence includes a `ch' collating element,
+then the RE `[[.ch.]]*c' matches the first five characters
+of `chchcc'.
+.PP
+Within a bracket expression, a collating element enclosed in `[=' and
+`=]' is an equivalence class, standing for the sequences of characters
+of all collating elements equivalent to that one, including itself.
+(If there are no other equivalent collating elements,
+the treatment is as if the enclosing delimiters were `[.' and `.]'.)
+For example, if o and \o'o^' are the members of an equivalence class,
+then `[[=o=]]', `[[=\o'o^'=]]', and `[o\o'o^']' are all synonymous.
+An equivalence class may not\(dg be an endpoint
+of a range.
+.PP
+Within a bracket expression, the name of a \fIcharacter class\fR enclosed
+in `[:' and `:]' stands for the list of all characters belonging to that
+class.
+Standard character class names are:
+.PP
+.RS
+.nf
+.ta 3c 6c 9c
+alnum	digit	punct
+alpha	graph	space
+blank	lower	upper
+cntrl	print	xdigit
+.fi
+.RE
+.PP
+These stand for the character classes defined in
+.BR ctype (3).
+A locale may provide others.
+A character class may not be used as an endpoint of a range.
+.PP
+There are two special cases\(dg of bracket expressions:
+the bracket expressions `[[:<:]]' and `[[:>:]]' match the null string at
+the beginning and end of a word respectively.
+A word is defined as a sequence of
+word characters
+which is neither preceded nor followed by
+word characters.
+A word character is an
+.B alnum
+character (as defined by
+.BR ctype (3))
+or an underscore.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+.PP
+In the event that an RE could match more than one substring of a given
+string,
+the RE matches the one starting earliest in the string.
+If the RE could match more than one substring starting at that point,
+it matches the longest.
+Subexpressions also match the longest possible substrings, subject to
+the constraint that the whole match be as long as possible,
+with subexpressions starting earlier in the RE taking priority over
+ones starting later.
+Note that higher-level subexpressions thus take priority over
+their lower-level component subexpressions.
+.PP
+Match lengths are measured in characters, not collating elements.
+A null string is considered longer than no match at all.
+For example,
+`bb*' matches the three middle characters of `abbbc',
+`(wee|week)(knights|nights)' matches all ten characters of `weeknights',
+when `(.*).*' is matched against `abc' the parenthesized subexpression
+matches all three characters, and
+when `(a*)*' is matched against `bc' both the whole RE and the parenthesized
+subexpression match the null string.
+.PP
+If case-independent matching is specified,
+the effect is much as if all case distinctions had vanished from the
+alphabet.
+When an alphabetic that exists in multiple cases appears as an
+ordinary character outside a bracket expression, it is effectively
+transformed into a bracket expression containing both cases,
+e.g. `x' becomes `[xX]'.
+When it appears inside a bracket expression, all case counterparts
+of it are added to the bracket expression, so that (e.g.) `[x]'
+becomes `[xX]' and `[^x]' becomes `[^xX]'.
+.PP
+No particular limit is imposed on the length of REs\(dg.
+Programs intended to be portable should not employ REs longer
+than 256 bytes,
+as an implementation can refuse to accept such REs and remain
+POSIX-compliant.
+.PP
+Obsolete (``basic'') regular expressions differ in several respects.
+`|', `+', and `?' are ordinary characters and there is no equivalent
+for their functionality.
+The delimiters for bounds are `\e{' and `\e}',
+with `{' and `}' by themselves ordinary characters.
+The parentheses for nested subexpressions are `\e(' and `\e)',
+with `(' and `)' by themselves ordinary characters.
+`^' is an ordinary character except at the beginning of the
+RE or\(dg the beginning of a parenthesized subexpression,
+`$' is an ordinary character except at the end of the
+RE or\(dg the end of a parenthesized subexpression,
+and `*' is an ordinary character if it appears at the beginning of the
+RE or the beginning of a parenthesized subexpression
+(after a possible leading `^').
+Finally, there is one new type of atom, a \fIback reference\fR:
+`\e' followed by a non-zero decimal digit \fId\fR
+matches the same sequence of characters
+matched by the \fId\fRth parenthesized subexpression
+(numbering subexpressions by the positions of their opening parentheses,
+left to right),
+so that (e.g.) `\e([bc]\e)\e1' matches `bb' or `cc' but not `bc'.
+.SH SEE ALSO
+regex(3)
+.PP
+POSIX 1003.2, section 2.8 (Regular Expression Notation).
+.SH BUGS
+Having two kinds of REs is a botch.
+.PP
+The current 1003.2 spec says that `)' is an ordinary character in
+the absence of an unmatched `(';
+this was an unintentional result of a wording error,
+and change is likely.
+Avoid relying on it.
+.PP
+Back references are a dreadful botch,
+posing major problems for efficient implementations.
+They are also somewhat vaguely defined
+(does
+`a\e(\e(b\e)*\e2\e)*d' match `abbbd'?).
+Avoid using them.
+.PP
+1003.2's specification of case-independent matching is vague.
+The ``one case implies all cases'' definition given above
+is current consensus among implementors as to the right interpretation.
+.PP
+The syntax for word boundaries is incredibly ugly.
Index: /trunk/minix/man/man8/MAKEDEV.8
===================================================================
--- /trunk/minix/man/man8/MAKEDEV.8	(revision 9)
+++ /trunk/minix/man/man8/MAKEDEV.8	(revision 9)
@@ -0,0 +1,53 @@
+.TH MAKEDEV 8
+.SH NAME
+MAKEDEV, DESCRIBE \- make/describe device files
+.SH SYNOPSIS
+.B MAKEDEV
+.RB [ \-n ]
+.IR key " ..."
+.br
+.B DESCRIBE
+.RI [ device "] ..."
+.SH DESCRIPTION
+.B MAKEDEV
+may be used to create the device files normally found in the
+.B /dev
+directory.  The
+.I key
+arguments are simply the names of the devices you want.
+.B MAKEDEV
+knows about all supported devices and will create them in the current
+directory with the proper owner and mode.  For many devices
+.B MAKEDEV
+will not only create the device you want, but also the devices related
+to it that you will probably want too.  Naming one floppy device will
+create all floppy devices for the same drive for instance.
+.PP
+Call
+.B MAKEDEV
+without arguments to see a list of keys that it understands.  Then use
+the
+.B \-n
+flag to make the script echo the commands it will execute the next time
+when you call it without that flag.
+.PP
+The special key
+.B std
+must be given alone to
+.BR MAKEDEV .
+This key will create all standard devices.
+.PP
+The command
+.B DESCRIBE
+will give you a one-line description of a given device.  It will by
+default list all devices in
+.BR /dev .
+.SH "SEE ALSO"
+.BR dev (4),
+.BR mknod (8).
+.SH BUGS
+.BR MAKEDEV "'s"
+eagerness to create devices may cause many "File exists" errors from
+.BR mknod .
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/add_route.8
===================================================================
--- /trunk/minix/man/man8/add_route.8	(revision 9)
+++ /trunk/minix/man/man8/add_route.8	(revision 9)
@@ -0,0 +1,78 @@
+.TH ADD_ROUTE 8
+.SH NAME
+add_route, del_route \- configure IP routing.
+.SH SYNOPSIS
+.B add_route
+.RB \-g 
+.RI gateway
+.RB [ \-d 
+.RI destination 
+.RB [ \-n
+.RI netmask " ]]"
+.RB [ \-I 
+.RI "ip device]"
+.B del_route
+.RB [ \-o "]"
+.RB [ \-D "]"
+.RB \-g
+.RI gateway
+.RB [ \-d
+.RI destination "]"
+.RB [ \-n
+.RI netmask " ]]"
+.RB [ \-I
+.RI ipdev "]"
+.RB [ \-v "]"
+
+.B del_route
+.RB \-i
+.RB [ \-D "]"
+.RB \-g
+.RI gateway 
+.RB \-d
+.RI dst 
+.RB [ \-n
+.RI netmask "]"
+.RB [ \-I
+.RI ipdev "]"
+.RB [ \-v "]"
+
+
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Add_route
+and
+.B del_route
+are used for manual maintenance of routes in the IP routing table.
+
+.SH OPTIONS
+.TP
+.B \-g 
+.I gateway 
+specifies the gateway IP address to use.
+.TP
+.B \-d
+.I destination
+specifies the destination(s) reached via this gateway.
+.TP
+.B \-n
+.I netmask
+specifies a netmask when the destination is a net.
+.TP
+.B \-I
+.I "ip device"
+specifies the ip device. 
+.SH "SEE ALSO"
+.BR irdp (8),
+.BR pr_routes (8).
+.SH AUTHOR
+.I Add_route.c 
+was created August 7, 1991 by Philip Homburg. 
+This manual page by A. S. Woodhull, last revised 13.02.96. Added
+alias for del_route 17.11.05.
+
+
+
Index: /trunk/minix/man/man8/adduser.8
===================================================================
--- /trunk/minix/man/man8/adduser.8	(revision 9)
+++ /trunk/minix/man/man8/adduser.8	(revision 9)
@@ -0,0 +1,43 @@
+.TH ADDUSER 8
+.SH NAME
+adduser \- add a new user to the system
+.SH SYNOPSIS
+\fBadduser \fIuser group home-dir\fR\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "adduser ast other /usr/ast" "How user ast could be added"
+.EX "adduser bin operator /usr/src" "How user bin could be added"
+.SH DESCRIPTION
+.PP
+.I Adduser
+adds a new user to the system by making new entries in
+.B /etc/passwd
+and
+.B /etc/shadow
+for the new user, creating a new home directory, and copying the contents
+of the template home directory
+.B /usr/ast
+into it.  The user-id of this new user will be the first free number not less
+than 10.  The password is initially empty, the full name must be set, and
+the shell is the Bourne Shell,
+.B /bin/sh .
+Use
+.I passwd ,
+.I chfn ,
+and
+.I chsh
+to change.
+.SH "SEE ALSO"
+.BR login (1),
+.BR passwd (1),
+.BR passwd (5).
Index: /trunk/minix/man/man8/backup.8
===================================================================
--- /trunk/minix/man/man8/backup.8	(revision 9)
+++ /trunk/minix/man/man8/backup.8	(revision 9)
@@ -0,0 +1,52 @@
+.TH BACKUP 8
+.SH NAME
+backup \- backup files
+.SH SYNOPSIS
+\fBbackup\fR [\fB\-djmnorstvz\fR] \fIdir1 dir2\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-d" "At top level, only directories are backed up"
+.FL "\-j" "Do not copy junk: \fI *.Z, *.bak, a.out, core\fR, etc"
+.FL "\-m" "If device full, prompt for new diskette"
+.FL "\-n" "Do not backup top-level directories"
+.FL "\-o" "Do not copy \fI*.o\fR files"
+.FL "\-r" "Restore files"
+.FL "\-s" "Do not copy \fI*.s\fR files"
+.FL "\-t" "Preserve creation times"
+.FL "\-v" "Verbose; list files being backed up"
+.FL "\-z" "Compress the files on the backup medium"
+.SH EXAMPLES
+.EX "backup \-mz . /f0" "Backup current directory compressed"
+.EX "backup /bin /usr/bin" "Backup bin from RAM disk to hard disk"
+.SH DESCRIPTION
+.PP
+\fIBackup\fR (recursively) backs up the contents of a given directory and its
+subdirectories to another part of the file system.
+It has two typical uses.
+First, some portion of the file system can be backed up onto 1 or more
+diskettes.
+When a diskette fills up, the user is prompted for a new one.
+The backups are in the form of mountable file systems.
+Second, a directory on RAM disk can be backed up onto hard disk.
+If the target directory is empty, the entire source directory is copied
+there, optionally compressed to save space.
+If the target directory is an old backup, only those files in the target
+directory that are older than similar names in the source directory are
+replaced.
+\fIBackup\fR uses times for this purpose, like \fImake\fR.
+Calling \fIBackup\fR as \fIRestore\fR is equivalent to using the -r option; 
+this replaces newer files in the target directory with older files from the
+source directory, uncompressing them if necessary.  The target directory
+contents are thus returned to some previous state.
+.SH "SEE ALSO"
+.BR tar (1).
Index: /trunk/minix/man/man8/badblocks.8
===================================================================
--- /trunk/minix/man/man8/badblocks.8	(revision 9)
+++ /trunk/minix/man/man8/badblocks.8	(revision 9)
@@ -0,0 +1,34 @@
+.TH BADBLOCKS 8
+.SH NAME
+badblocks \- put a list of bad blocks in a file
+.SH SYNOPSIS
+\fBbadblocks \fIblock_special\fR [\fIblock\fR] ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "badblocks /dev/hd1       " "Handle bad blocks on \fI/dev/hd1\fP"
+.EX "badblocks /dev/hd3 310 570 1680 " "Three bad blocks on \fI/dev/hd3\fP"
+.SH DESCRIPTION
+.PP
+If a device contains bad sectors, it is important to not have them
+allocated to important files.  This program makes it possible to collect
+up to 7 bad blocks into a dummy file, so they will not be allocated for a 
+\&'real\&' file.  
+When the program starts up, it asks for a list of bad blocks, unless
+they are provided as arguments.
+Then it creates a file whose name is of the
+form \fI.Bad_xxxxx\fR, where \fIxxxxx\fR is a pid.
+.SH "SEE ALSO"
+.BR readall (1).
+
+.\"
+.\" $PchId: badblocks.8,v 1.2 1998/07/27 19:47:04 philip Exp $
Index: /trunk/minix/man/man8/boot.8
===================================================================
--- /trunk/minix/man/man8/boot.8	(revision 9)
+++ /trunk/minix/man/man8/boot.8	(revision 9)
@@ -0,0 +1,524 @@
+.TH BOOT 8
+.SH NAME
+boot \- from power on to the login prompt
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+At power on the machine reads the first sector of the boot device into memory
+and executes it.  This bootstrap code loads
+.BR /boot/boot ,
+the MINIX 3 Boot Monitor.  The monitor loads the kernel binaries from
+.BR /boot/image ,
+or the newest file in
+.B /boot/image
+if it is a directory.
+.PP
+The MINIX 3 system is now running, the different tasks initialize themselves
+and control is transferred to the last one,
+.BR init .
+.PP
+.B Init
+is the grandparent of all MINIX 3 processes, it is responsible for starting
+login processes on each terminal, but first it runs
+.BR /etc/rc .
+.PP
+.B /etc/rc
+checks the state of the system and starts daemons.  First it sets the
+keyboard translation to the mapping in
+.B /etc/keymap
+if present, followed by a call to
+.BR readclock (8)
+to set MINIX 3 time from the hardware clock.  Next the file systems are checked
+if necessary and the
+.B /usr
+file system is mounted.
+.PP
+The system is now ready for multiuser startup,
+.B /etc/rc
+calls
+.B /usr/etc/rc
+that cleans out /tmp, /usr/tmp, and resets or cycles log files by running
+.BR /usr/etc/daily ,
+starts the
+.BR update (8)
+and
+.BR cron (8)
+daemons, and initializes the network services.
+.B /etc/rc
+finally runs
+.BR /usr/local/etc
+to initialize the system in a site or host dependent way.
+.PP
+.B Init
+reads
+.B /etc/ttytab
+and starts a
+.BR getty (8)
+for each enabled terminal line to allow a user to log in.
+.SH OPTIONS
+.TP
+.B bootopts=\-s
+The value of the boot variable
+.B bootopts
+is passed to
+.BR /etc/rc .
+If it contains
+.B \-s
+then the system will run a single user shell before continuing with multiuser
+startup.  (Note that one normally uses
+.B boot \-s
+instead of setting
+.BR bootopts .)
+.TP
+.B bootopts=\-a
+This flag tells that
+.B /etc/fstab
+must be ignored.  The system asks for a device to use as /usr instead.  This
+will also be done if the root device is not as mentioned in
+.BR /etc/fstab .
+.TP
+.B bootopts=\-f
+Force a file system check, even if the system was shut down properly.  (Do
+this once in a while to be sure about the state of the file systems.)
+.TP
+.BI servers= program\fR[,\fIprogram\fR...]
+Names the special servers that must be started in /usr/etc/rc.  The setting
+.BR "servers=inet"
+will start the TCP/IP server.
+.SH "BOOT ENVIRONMENT"
+Many features of the drivers inside the kernel are controlled by settings in
+the boot environmenti, like
+.B bootopts
+above does for
+.BR /etc/rc .
+The values of these variables are usually colon or comma separated
+numbers configuring the driver.
+.B "DPETH0 = 300:10"
+tells the DP ethernet driver to use I/O address 0x300, interrupt request
+10, and the default memory address (0xD0000, values may be omitted) for the
+first ethernet board.  (Note that IRQ 2 is redirected to IRQ 9 on AT's and
+PS/2's, so use 9 if a device is jumpered for 2.)
+.PP
+Variables that are special to both the monitor and the kernel are described
+in
+.BR monitor (8).
+This section lists extra variables or variable settings:
+.TP
+\fBc\fIn\fR = \fBat\fR | \fBbios\fR | \fBesdi\fR | \fBxt\fR | \fBaha1540\fR | \fBdosfile\fR | \fBfatfile\fR
+Choose the driver that is to be used as controller
+.IR n ,
+in order: IBM/AT (classic AT or newer IDE), BIOS (any disk), ESDI
+(some PS/2s), IBM/XT, Adaptec 154x, MINIX 3 under DOS "file as disk",
+FAT file system "file as disk".
+By default
+.B at
+is used on AT bus systems,
+.B bios
+on PS/2s and XTs, and
+.B dosfile
+when running under DOS.
+Most drivers are present in the kernel as distributed, but may be taken out
+by modifying
+.BR /usr/include/minix/config.h .
+See
+.BR controller (4).
+(An XT should always use the BIOS driver, not the XT driver, because BIOS
+calls are cheap on an XT.  The XT driver can be used on AT machines with an
+old XT controller.)
+.TP
+\fBDPETH\fIn\fR = \fBon\fR | \fBoff\fR
+Turn an ethernet board on or off.  The driver is by default in "sink" mode
+for all boards.  The sink mode allows one to use the driver without an
+ethernet board installed.  The driver will play /dev/null for that device,
+i.e. nothing comes in, and anything send out is dropped on the floor.  If
+the board is turned on then the driver will use it to send out packets, if
+it is turned off then the driver will fail for that board.
+.PP
+.if n .ta \w'DPETHn = I/O-addr:irq:mem_addr:mem_size'u+2m
+.if t .ta \w'\fBDPETH\fIn\fR = \fII/O-addr\fR:\fIirq\fR:\fImem_addr\fR:\fImem_size\fR'u+2m
+\fBDPETH\fIn\fR = \fII/O-addr\fR:\fIirq\fR:\fImem_addr\fR:\fImem_size\fR	(WD80x3)
+.br
+\fBDPETH\fIn\fR = \fII/O-addr\fR:\fIirq\fR:\fB0\fR	(NE2000)
+.br
+\fBDPETH\fIn\fR = \fII/O-addr\fR:\fIirq\fR:\fIflags\fR	(3c503)
+.RS
+Set the I/O address (hex), IRQ (decimal), memory address (hex), memory
+size (hex), or flags (hex) of the
+.IR n -th
+ethernet board and turn it on.  By default they are configured as
+280:3:D0000 and 300:5:C8000 with the memory size set to 2000, 4000, or 8000
+depending on the type of board found.
+For the Western Digital cards the IRQ must be what the board expects,
+but the memory address is programmed into the board by the driver.
+The SMC EtherEZ board, a WD8013 successor, has only 8K
+memory.  This confuses the driver, so you need to explicitly specify the
+board size as being 2000.
+The memory address and size have no meaning for the Novell ethernet boards,
+but the address may be explicitly set to zero to indicate that the board
+.B is
+a Novell ethernet board.
+For the 3Com 3c503 the third parameter are flags, with the low bit indicates
+that the on-board tranceiver must be used if 0 (thin ethernet), or that an
+external tranceiver is used on the AUI port if set to 1.
+The IRQ is software settable, and must be specified as 2 (XT), 3, 4, 5,
+or 9 (AT).  The memory address is set on the board by jumpers.  The driver
+does not support I/O mode for the 3c503.
+(Note the little differences between board types.  For the 8003/8013 and
+NE1000/NE2000 the IRQ is fixed and the memory address variable, for the
+3c503 the IRQ is variable and the memory address is fixed, but need not be
+specified.  Messy.)
+.RE
+.TP
+\fBDPETH\fIn\fB_EA\fR = \fIe0\fR:\fIe1\fR:\fIe2\fR:\fIe3\fR:\fIe4\fR:\fIe5\fR
+Set the ethernet address of the
+.IR n -th
+ethernet board.  The address is normally obtained from the ethernet board,
+so only in exceptional circumstances is this setting ever needed.  (Use the
+address of the main server if you want a career change.)
+.TP
+\fBAHA0\fR = \fII/O-addr\fR:\fIbus-on\fR:\fIbus-off\fR:\fItr-speed\fR
+Configure the Adaptec 154xA SCSI host adapter to use the given I/O address
+(hex), Bus-on time (decimal), Bus-off time (decimal) and transfer speed
+(hex).  The default is 330:15:1:00.  The default transfer speed is always
+5.0 Mb/s (code 00) ignoring the jumper settings.
+.TP
+\fBaha1540-d\fIn\fR = \fIsleep-time\fR:\fItarget\fR,\fIlun\fR
+Program SCSI disk
+.I n
+to have the given target and logical unit number.  The target and lun
+of a tape or other SCSI device may be changed by setting the
+.BI aha1540-d n
+variable that would be used had it been a disk.  So tape device c0t7 can be
+set to target 4, lun 1 with aha1540-d7=:4,1.
+(The
+.I sleep-time
+parameter is present but ignored to be compatible with Minix-vmd.)
+.TP
+\fBdosfile-d\fIn\fR = \fIfile\fR
+Tells the DOS virtual disk driver for disk
+.I n
+to use a given file as a disk.  The file is a DOS file name that the
+boot monitor must be able to open.
+.TP
+\fBfatfile-d\fIn\fR = \fIdriver:minor:file\fR
+Tells the FAT virtual disk driver for disk
+.I n
+to use a given file as a disk.  The
+.I driver
+parameter is the name of driver that handles the disk, and
+.I minor
+is the device number of the partition where the file is found.  See
+.BR controller (4)
+for names and numbers.
+The
+.I file
+argument is the path to the file from the root directory down.  The driver
+named must also be tied to a controller with a
+.BI c n
+variable, so that the FAT file driver can find it.
+A handy way to find the proper minor number is to run
+.B "ls\ \-l"
+on the device where the file is found.  As a example, we assume the most
+common situation of a disk file on the first partition of the first drive
+on an ATA (IDE) controller:
+.SP
+.in +5
+.ft B
+.nf
+c0 = fatfile
+c1 = at
+fatfile-d0 = at:1:/minix/minix.mnx
+.fi
+.ft P
+.in -5
+.TP
+.BR TZ " = " GMT0
+This sets the time zone the hardware clock is running in.
+.B Readclock
+uses this to correctly obtain the time of the clock.  The timezone of the
+system is set in
+.BR /etc/profile .
+This boot variable is normally not set, only a few UNIX die-hards who
+don't care about the time Windows sees and don't want to change the clock
+twice a year for daylight savings use this option.  (Set Windows time to the
+time zone of Casablanca to match.)
+.SH "TCP/IP CONFIGURATION"
+To use TCP/IP you need to run the
+.B inet
+server, and unless you are running standalone you have to enable the
+ethernet driver.  See the
+.B servers
+and
+.BI DPETH n
+boot variables above.  The driver supports these ethernet cards:  Western
+Digital 8003, Western Digital 8013, SMC Elite Ultra 16,
+Novell NE1000 and NE2000, 3Com Etherlink II (3c503).  Many newer
+variants of the WD8013, now under the SMC brand, may also work.
+A common PCI reimplementation of the NE2000 using the Realtek 80 chipset is
+also supported.  Make sure it's just a 10 mbit device and that it has a
+chip marked "RTL 8029".
+.PP
+You are likely to use TCP/IP in one of three situations:
+.PP
+.RS
+Standalone with no connection to a network.
+.SP
+In a small network with no support from a "big" host.
+.SP
+Connected to a large network with address and name servers.
+.RE
+.PP
+In each situation you need a different set of configuration files.
+.SS Standalone
+All you need is a name and an IP address.  Suppose the name is "flotsam"
+and the IP address is 192.168.0.1 from the private IP space, then this is
+put in
+.BR /etc/hosts :
+.PP
+.RS
+.ta +\w'192.168.0.1'u+3n
+192.168.0.1	flotsam
+.RE
+.PP
+And this in
+.BR /etc/dhcp.conf :
+.PP
+.RS
+.nf
+host 192.168.0.0/24 {};
+interface ip0 flotsam;
+.fi
+.RE
+.SS "Small Network"
+A network requires an ethernet driver.  You need to enable one in
+<minix/config.h> and you need to tell
+.B inet
+that it should use that driver by making
+.B /etc/inet.conf
+look like this:
+.PP
+.RS
+.nf
+eth0 DP8390 0 { default; };
+.fi
+.RE
+.PP
+The second word (DP8390) must the name of the ethernet driver you've enabled.
+It can also be seen among the drivers in the output of
+.BR "ps ax" .
+See also
+.BR inet (8).
+.PP
+In a small network there may not be a DHCP server for MINIX 3 to obtain its IP
+address and name from, so you need specify the ethernet address of your machine
+and host names of all machines in the hosts and DHCP configuration files.
+Suppose your machine is to be named "flotsam", and another machine in the
+network is named "jetsam", and let's use network 192.168.0.0/24 again.  The
+file
+.B /etc/hosts
+now looks like this:
+.PP
+.RS
+.ta +\w'192.168.0.1'u+3n
+.nf
+192.168.0.1	flotsam
+192.168.0.2	jetsam
+.fi
+.RE
+.PP
+And
+.B /etc/dhcp.conf
+like this:
+.PP
+.RS
+.nf
+host 192.168.0.0/24 {};
+client 0:1:1b:a:68:ce flotsam;
+.fi
+.RE
+.PP
+Use
+.B hostaddr \-e
+to find out what the ethernet address of your network card is.  (The address
+above is an example.)
+.PP
+A host needs to have all hostnames used on your little network in its
+host file.  In the DHCP configuration you only need the client entry of the
+system itself, but it may be useful to add all client entries to make them all
+the same.
+.PP
+If one of the machines is always on when any of the others is, then you can let
+it be a DHCP server.  The other machines don't need a hosts or DHCP file
+anymore.  If flotsam is the server then its
+.BR /etc/dhcp.conf
+looks like this:
+.PP
+.RS
+.nf
+.ta +4m
+host 192.168.0.0/24 {
+	DNSserver flotsam;
+};
+client 0:1:1b:a:68:ce flotsam { option server; };
+client 0:0:c0:3a:12:10 jetsam;
+.fi
+.RE
+.SS "Large Network"
+In a network with a central network administration your machine's IP address
+and name are given by the DHCP server.  You don't need any configuration
+files.  If you want your machine to do more, like being a router or
+something, then see
+.BR inet (8)
+on setting up more than one network interface.
+.PP
+.SS "Simpler configuration tools"
+The
+.BR dhcpd
+and
+.BR nonamed
+daemons are complex little programs that try to obtain information about
+their surroundings automatically to tell the machine what its place in the
+network is.  It should come as no surprise that there are simpler utilities
+to configure a machine.  On a memory starved machine it may even be wise to
+configure a machine statically to get rid of the daemons.  The first daemon,
+.BR dhcpd ,
+can be replaced by:
+.PP
+.RS
+.B ifconfig \-h
+.I host-IP-address
+.B \-n
+.I netmask
+.br
+.B add_route \-g
+.I gateway-IP-address
+.RE
+.PP
+to set the IP address and netmask of the machine.  Note that you can only
+do this if the machine has a static IP address, or chaos will follow.  Remove
+.BR /usr/adm/dhcp.cache
+if the DHCP daemon has run before.
+.PP
+The name daemon,
+.BR nonamed ,
+can be replaced by an entry in
+.B /etc/resolv.conf
+that specifies an external name daemon:
+.PP
+.RS
+.B nameserver
+.I nameserver-IP-address
+.RE
+.PP
+The
+.B ifconfig
+and
+.B add_route
+calls can be placed in the file
+.BR /etc/rc.net .
+Check
+.B /usr/etc/rc
+to see how
+.BR /etc/rc.net
+can be used to override running the normal series of network deamons.
+Note that
+.BR /etc/rc.net
+is sourced, so you can use the same variables and functions that
+.BR /usr/etc/rc
+uses.
+These changes undo all the efforts to make MINIX 3 TCP/IP
+autoconfigurable.  Make very sure that all the IP addresses are correct, and
+that the IP address of your machine is unique.  (Mistakenly using the
+address of a main server will make all other machines look at your machine,
+and will make all the users of all other machines look at you.)
+.SH FILES
+.TP 20n
+/boot
+MINIX 3 Boot Monitor.
+.TP
+/minix
+Kernel image, or directory containing them.
+.TP
+/etc/rc
+Basic system initialization.
+.TP
+/usr/etc/rc
+Complete system initialization.
+.TP
+/etc/rc.net
+Specialized network initialization.
+.TP
+/usr/local/etc/rc
+Per site initialization.
+.TP
+/etc/hosts
+Name to IP address mapping.
+.TP
+/etc/dhcp.conf
+Network initialization.
+.TP
+/etc/resolv.conf
+Name resolver configuration.
+.SH "SEE ALSO"
+.BR monitor (8),
+.BR init (8),
+.BR inet (8),
+.BR loadkeys (8),
+.BR readclock (8),
+.BR fsck (1),
+.BR fstab (5),
+.BR update (8),
+.BR cron (8),
+.BR ttytab (5),
+.BR getty (8),
+.BR hostaddr (1),
+.BR ifconfig (8),
+.BR dhcpd (8),
+.BR nonamed (8),
+.BR tcpd (8),
+.BR hosts (5),
+.BR ethers (5),
+.BR resolv.conf (5),
+.BR inet (8).
+.SH DIAGNOSTICS
+.TP 5n
+Checking File Systems.
+If the system has crashed then
+.B fsck
+is called for the root and /usr file systems.  It is wise to reboot if the
+root file system must be fixed.
+.TP
+Finish the name of device to mount as /usr: /dev/
+The prompt for the
+.B \-a
+option, or if the name of the /usr file system has not been set in /etc/fstab.
+You can type a device name, say
+.BR fd0 .
+.TP
+Unable to obtain an IP address after 10 seconds.
+TCP/IP misconfiguration.  The DHCP daemon may have failed because the ethernet
+address of the machine is not known to the DHCP server, the DHCP
+configuration is not filled in properly, or the DHCP server can not be reached.
+Either talk to your Network Administrator, or make a dhcp.conf
+and a hosts file.
+.TP
+1.2.3.4 login:
+If you see an IP address instead of a host name then the system failed to
+translate the IP address.  Either talk to your Network Administrator to
+have the reverse address translation tables fixed, or make a hosts file.
+.SH NOTES
+The 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16 networks can be used for
+private networks.  (This so-called CIDR notation names an IP address and
+the number of bits in the network number.  So 172.16.0.0/12 includes all
+addresses from 172.16.0.0 to 172.31.255.255.)
+RFC-1597 will tell you why private networks are good, and RFC-1627 why
+they are bad.
+.SH BUGS
+Indefinite hangs are possible if I/O addresses or IRQ's are wrong.  A driver
+may babble about addresses and IRQ's, but that does not mean that what it
+says is true, it may just be configured that way.  It is very difficult to
+find peripherals on a PC automatically, and MINIX 3 doesn't even try.
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man8/checkhier.8
===================================================================
--- /trunk/minix/man/man8/checkhier.8	(revision 9)
+++ /trunk/minix/man/man8/checkhier.8	(revision 9)
@@ -0,0 +1,29 @@
+.TH CHECKHIER 8
+.SH NAME
+checkhier \- check the directory hierarchy
+.SH SYNOPSIS
+.B checkhier
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Checkhier
+checks a number of files and directories that make up the top level file
+system hierarchy.  The output of the command is a script that could be
+applied to fix things like bad mode, wrong owner or group, etc.
+.PP
+The script should never be executed without checking.  I might be better to
+examine the differences oneself and to fix any problems by hand.
+.PP
+.B Checkhier
+must be run by the superuser.
+.SH "SEE ALSO"
+.BR chmod (1),
+.BR chown (8),
+.BR hier (7).
+.SH DIAGNOSTICS
+The exit code is 0 if all checks out right, otherwise a script is output and
+the exit code is 1.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/chown.8
===================================================================
--- /trunk/minix/man/man8/chown.8	(revision 9)
+++ /trunk/minix/man/man8/chown.8	(revision 9)
@@ -0,0 +1,35 @@
+.TH CHOWN 8
+.SH NAME
+chown \- change owner
+.SH SYNOPSIS
+\fBchown [\fB\-R\fR] \fIowner\fR[:\fIgroup\fR] \fIfile\fR ...\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-R" "Change directory hierarchies"
+.SH EXAMPLES
+.EX "chown ast file1 file2" "Make \fIast\fR the owner of the files"
+.EX "chown \-R ast:other dir" "Change the owner and group of all files in dir"
+.SH DESCRIPTION
+.PP
+The owner field (and optionally group field) of the named files is changed
+to
+.I owner 
+(i.e., login name specified) and
+.I group .
+Alternatively, a decimal uid(gid) may be specified instead of a user name.
+Only the superuser may execute this command.
+.SH "SEE ALSO"
+.BR chgrp (1),
+.BR chmod (1),
+.BR ls (1),
+.BR chown (2).
Index: /trunk/minix/man/man8/cleantmp.8
===================================================================
--- /trunk/minix/man/man8/cleantmp.8	(revision 9)
+++ /trunk/minix/man/man8/cleantmp.8	(revision 9)
@@ -0,0 +1,65 @@
+.TH CLEANTMP 8
+.SH NAME
+cleantmp \- clean out a tmp dir
+.SH SYNOPSIS
+.B cleantmp
+.RB [ \-d "[\fIlevel\fR]]"
+.RB [ \-i
+.IR file "] ..."
+.BR \-\fIdays\fB | \-f
+.RI [ directory " ...]"
+.SH DESCRIPTION
+.B Cleantmp
+removes all files in each of the given directories and their subdirectories
+that have not been accessed for at least
+.I 'days'
+days.  Empty subdirectories are removed if their modified times are more
+than
+.I 'days'
+days old.
+.B Cleantmp
+looks at days as humans do, i.e. they last from midnight to midnight.
+Meaning that
+.B cleantmp -1 /tmp
+removes all files that were not touched after midnight last night. This may
+be very helpful, because in many cases that big file that clogs up
+.B /tmp
+was created yesterday, but less than 24 hours ago.
+.PP
+The 'days' flag may be replaced by
+.B \-f
+causing
+.B cleantmp
+to remove all files in the directory no matter what age.  Specifying zero
+days doesn't work, because it is assumed to be a mistake.
+.PP
+.B Cleantmp
+knows that files and directories that have a name starting with a '.' are
+special and will not delete them or files within them if they are not at
+least 14 days old.
+.SH OPTIONS
+.TP 5
+.BR \-d "[\fIlevel\fR]]"
+Set the debug level to
+.I level
+(by default 1).  Normally only errors are reported.  Debug level 1 lists the
+actions taken on standard error, level 2 also prints the file times used,
+and level 3 makes
+.B cleantmp
+playact, i.e. nothing is really removed.
+.TP
+.BI \-i " file "
+One or more
+.B \-i
+options name files to be ignored.  Files are not removed if they are in the
+list of ignored files by either a directory entry match, or a full pathname
+match.  This option is useful to keep things like named pipes that some
+longlived programs foolishly put in temporary directories.
+.SH "SEE ALSO"
+.BR find (1).
+.SH BUGS
+Don't use '\fBcleantmp -1\fP' shortly after midnight.
+.PP
+It would be nice if one could delete files that are, say, 2 hours old.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/config.8
===================================================================
--- /trunk/minix/man/man8/config.8	(revision 9)
+++ /trunk/minix/man/man8/config.8	(revision 9)
@@ -0,0 +1,334 @@
+.TH CONFIG 8
+.SH NAME
+config \- configuring MINIX 3 tasks and servers
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+MINIX 3 has a number of configuration files containing parameters that can
+be changed to enable or disable a device driver, to change the number of
+times a resource can be used, or to tune the performance of the system.
+We will name the file that contains the parameter, the name of the
+parameter, and the values it can be set to.  Some comments are prefixed by
+"8086" for MINIX 3 running in 16-bit real mode, "286" for 16-bit protected
+mode, and "386" for 32-bit protected mode.
+Configuration file names can be
+.RI < file.h >
+for a file in
+.BR /usr/include/ ,
+or a simple file name for a file in
+.BR /usr/src/ .
+.PP
+There may be several definitions for a parameter with only one that is
+active.  Which one this is is easy to find if you know that
+.B "(\s-2CPU\s+2\ ==\ \s-2INTEL\s+2)"
+is true, and
+.SB _WORD_SIZE
+equals
+.B 2
+in 16-bit mode, and
+.B 4
+in 32-bit mode.
+.PP
+.ti 2m
+.RB < minix/config.h >
+.br
+This is the main configuration file for the MINIX 3.  It contains lots of
+boolean variables to enable or disable drivers and a number of parameters
+that specify the sizes of system data structures:
+.TP
+.SB NR_PROCS
+The number of slots in the process table, and thus the maximum number of
+processes that can be run concurrently.  Should be increased from the
+default
+.B 32
+if networking is enabled (add
+.B 8
+for deamons), and if more users are using the system (add
+.B 4
+for each active session).  There are a lot of
+loops in the kernel scanning the process table, so setting
+.SB NR_PROCS
+too high will slow things down a little bit, so don't overdo it.
+.TP
+.SB NR_BUFS
+The number of disk buffers in the file system server.  It is used to keep
+frequently used disk blocks in memory.
+.BR 8086 " & " 286 :
+The default is
+.BR 40 ,
+and that's about as high as it can be set.
+.BR 386 :
+The default is
+.BR 80 ,
+which is best increased to
+.B 1024
+if you can spare the memory.  More will help, but the effect won't be as
+pronounced as
+.B 1024
+is more than enough to contain the working set of one active user.
+.TP
+.SB NR_CTRLRS
+Number of tasks used for disk or tape controllers.  By default 2, maximum 4.
+You need a controller task for each device class to be handled through a
+.BI /dev/c n "*"
+set of devices.
+.TP
+.SB ENABLE_CACHE2
+If set to 1 allows the RAM disk to be used as a second level file system
+cache.  Any block that is evicted from the normal cache is both written to
+disk (if dirty), and copied to the second level cache.  If it is needed
+again then the block is reloaded from the RAM disk if it is still there.
+.BR 8086 :
+Forget it, you don't have any memory for it.
+.BR 286 :
+Turn it on and set the boot environment variable
+.B ramsize
+to
+.B 512
+if you have the memory.  That's enough to contain the working set of
+one active user, and is also the maximum FS can handle.
+.BR 386 :
+The installation scripts sets
+.B ramsize
+to
+.B 1024
+if there is enough memory.  Your first point of call is to compile a
+new kernel with
+.SB ENABLE_CACHE2
+off,
+.SB NR_BUFS
+set to a large value, and
+.B ramsize
+set back to zero.  A normal block cache works much better than a two level
+arrangement.
+.TP
+.SB ENABLE_AT_WINI
+Enables the AT or IDE disk driver.  (The IDE interface grew out of the old
+AT disk interface.)  Any run of the mill PC needs this driver.  You need to
+assign a driver like this one to a controller task using one of the
+.BI c n
+boot variables.  See
+.BR boot (8).
+.TP
+.SB ENABLE_BIOS_WINI
+Enables the BIOS disk driver.  The BIOS driver uses the system BIOS to read
+or write disk blocks.
+.BR 8086 :
+The preferred disk driver for XT class machines.
+.BR 286 " & " 386 :
+Use a native driver if possible to avoid switching back to real mode to make
+BIOS calls.  Especially on the 286 this is a painful affair.
+.TP
+.SB ENABLE_ESDI_WINI
+Enables the ESDI disk driver.  Some PS/2 models have this disk.
+.TP
+.SB ENABLE_XT_WINI
+Enables the XT disk driver.  Useful for early IBM/AT machines that have XT
+disks.  In real mode it is best to use the BIOS driver.
+.TP
+.SB ENABLE_AHA1540_SCSI
+Enables the Adaptec 1540 series SCSI driver.
+.TP
+.SB ENABLE_DOSFILE
+Enable the "DOS file as disk" driver that is used when MINIX 3 is run from
+MS-DOS to access a large file as a disk.
+.TP
+.SB ENABLE_FATFILE
+Enable the "FAT file as disk" driver that interprets a FAT file system
+to find a large file to use as a disk.  This driver combined with a fast
+native MINIX 3 disk driver is a better choice then the previous driver.  (And
+it works when MINIX 3 is not started from MS-DOS.)  This is the last driver
+that needs to be assigned to a controller task.
+.TP
+.SB ENABLE_SB16
+Enable the Soundblaster-16 audio driver.
+.TP
+.SB ENABLE_PRINTER
+Enable the Printer driver.
+.TP
+.SB DMA_SECTORS
+The size of the DMA buffer for drivers that use DMA or other drivers that
+can only do I/O to a single chunk of memory.  (BIOS, ESDI, XT, DOSFILE.)
+Choose a number between
+.B 1
+and
+.B 128
+for the sector size of this buffer.  The memory cost is twice this amount,
+because of trouble getting it aligned in memory properly.  A value of
+.B 16
+is the minimum to work well, choose
+.B 64
+if you have enough memory.
+.TP
+.SB NR_CONSOLES
+Number of virtual consoles.  By default
+.BR 2 ,
+so you can have two login sessions that can be switched to by ALT-F1,
+ALT-F2 or ALT-left/rightarrow.  If you have an EGA screen then you can
+specify up to
+.B 4
+virtual consoles, for VGA you can have
+.BR 8 .
+It is best to choose one less to leave some video memory to keep text
+scrolling fast.  You really should read
+.BR console (4)
+on this.  Note also the
+.B console
+boot variable, you can use it to put more characters on the screen, at
+the cost of video memory.
+.TP
+.SB ENABLE_DP8390
+Master switch to enable the network drivers.  They are required by the
+network server,
+.BR inet .
+See
+.BR boot (8)
+for information on configuring network support.
+.TP
+.SB ENABLE_WDETH
+Enable code for the WD8003 and WD8013 cards in the network driver.
+.TP
+.SB ENABLE_NE2000
+Enable code for the NE1000 and NE2000 cards.
+.TP
+.SB ENABLE_3C503
+Enable code for the 3Com Etherlink II (3C503).
+.TP
+.SB NR_PTYS
+Number of pseudo terminals supported, by default
+.BR 0 ,
+which disables the driver.  Pseudo terminals are used for incoming network
+logins by telnet or rlogin.  One pty is needed per session.
+.TP
+.SB NR_RS_LINES
+Number of RS-232 lines supported.  By default
+.B 2
+for a normal kernel, but
+.B 0
+for a tiny kernel used for XT installation.  You can save a bit of memory by
+setting this parameter to zero if you don't need serial lines.
+.PP
+.ti 2m
+.BR fs/const.h
+.br
+This file contains most of the parameters used by the file system code.
+Most of these cannot be changed, with the exception of these four:
+.TP
+.SB NR_FILPS
+Maximum number of open file descriptors for all processes combined.  A "File
+table overflow" error might indicate that this number must be increased.
+.TP
+.SB NR_INODES
+Maximum number of in-use files for all processes combined.  Like above a
+"File table overflow" error may also indicate that this number should be
+increased.  In cases like these one usually doubles both parameters.  (If
+one table runs out then the other one is likely to run out also anyway.)
+.TP
+.SB NR_SUPERS
+Number of file systems that can be mounted.  Again a "file table overflow"
+error is given if this table is full, but it will be produced by the
+.B mount
+command, so you know what's wrong in this case.
+.TP
+.SB NR_LOCKS
+Number of active file locks by
+.BR fcntl (2).
+These locks are often used by programs that update a shared file, like mail
+programs do with mail boxes.  A "no locks available" error indicates that
+this table has run out.
+.PP
+.ti 2m
+.B kernel/bios_wini.c
+.ti 2m
+.B kernel/dosfile.c
+.ti 2m
+.B kernel/fatfile.c
+.br
+The number of disks each of these drivers can handle is specified by:
+.TP
+.B MAX_DRIVES
+This parameter is set to
+.B 4
+for the BIOS and "DOS file" drivers, and to
+.B 2
+for the "FAT file" driver.  It can be set as high as you need to allow for
+more disks, or files as disks.  (The "FAT" driver needs quite some memory per
+disk, which is why it by default only allows 2 disks.)  You will need to run
+.BR MAKEDEV (8)
+to create the extra disk devices in
+.BR /dev/ .
+.PP
+.ti 2m
+.B inet/inet_config.h
+.br
+The maximum number of TCP/IP networks is:
+.TP
+.B IP_PORT_MAX
+Sets the maximum number of networks that can be defined in
+.BR /etc/inet.conf .
+.BR 8086 ,
+.BR 286 :
+By default 2.
+.BR 386 :
+By default 4.
+.PP
+.ti 2m
+.B inet/buf.c
+.br
+The number of 512 byte buffers allocated for data within the TCP/IP server is:
+.TP
+.B BUF512_NR
+These buffers are a shared resource used by the server for any data it wants
+to play with.  For incoming data this number of buffers determines the time
+packets are kept around, with each new packet evicting an old packet.  It's
+no big deal if packets get lost before a user process reads them, packets
+get lost all the time.  The only real problem is outgoing TCP data.  The
+default setting for
+.SB BUF512_NR
+allows up to four backlogged TCP streams, i.e. when data is output faster
+then it is read.  If more buffers are needed then one of the TCP connections
+is shut down.  When this happens you will see a "not enough buffers left"
+error.  This could happen for instance if a MINIX 3 web server is assaulted by
+a browser that likes to open several connections to the server
+simultaneously.  The fix is to increase
+.SB BUF512_NR
+to allow more slow outgoing TCP streams.
+.BR 86 :
+The default of
+.B 32
+buffers can be increased up to
+.BR 64 .
+(The "TCP window size" has been limited in 16-bit mode to keep the buffer
+use by TCP down.)
+.BR 386 :
+The default of
+.B 128
+can be increased to any value you like, but
+.B 512
+seems to be more than enough.  Minix-vmd uses 512 by default, and it seems
+happy that way.
+.SH "SEE ALSO"
+.BR controller (4),
+.BR usage (8),
+.BR boot (8),
+.BR MAKEDEV (8).
+.SH NOTES
+Associated with drivers there are device files to access the devices
+controlled by the drivers that may have to be created.  Let's simplify this
+sentence:  Type
+.BR "ls /dev" ,
+note that there are only
+.B c0*
+and
+.B c1*
+devices, and only for two disks each.  Some devices, like the audio devices,
+are not even present.  So if you enable a driver, or increase some limits, you
+also need to use
+.BR MAKEDEV (8)
+in
+.B /dev
+to allow programs to talk to the drivers.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/cron.8
===================================================================
--- /trunk/minix/man/man8/cron.8	(revision 9)
+++ /trunk/minix/man/man8/cron.8	(revision 9)
@@ -0,0 +1,165 @@
+.TH CRON 8
+.SH NAME
+cron \- clock daemon
+.SH SYNOPSIS
+.B cron
+.RB [ \-d\c
+.RI [ level ]]
+.SH DESCRIPTION
+The
+.B cron
+daemon executes tasks that must be repeated every now and then (cron jobs),
+and tasks that must be run just once (at jobs).  It is normally used to run
+daily or weekly system maintenance scripts.  What it needs to run and when
+is specified in a number of "cron tables", or crontab files for short.
+These tables are:
+.PP
+.RS
+.nf
+.ft B
+/usr/lib/crontab
+/usr/local/lib/crontab
+/var/lib/crontab
+/var/opt/\fIname\fP/lib/crontab\ \ \fR(Minix-vmd only)\fB
+/usr/spool/crontabs/\fIuser\fP
+.ft R
+.fi
+.RE
+.PP
+These files follow the usual pattern:  One for the standard things, one for
+local tasks per organization, one for tasks per system, and one crontab per
+installed package.  (Cron reads
+.B /usr/lib/packages
+to find names of installed packages, it doesn't just grab everything in
+.BR /var/opt .)
+The last set of files fall outside the normal pattern, they are per user
+crontabs that one can create with the
+.BR crontab (1)
+command.  The file names in
+.B /usr/spool/crontabs/
+are login names of the file owners.
+.PP
+The format of a crontab file is described in
+.BR crontab (5).
+.SS "AT jobs"
+.B Cron
+also takes care of the execution of jobs issued by
+.BR at (1)
+that are found in
+.BR /usr/spool/at/ .
+Cron simply runs the AT job as if there were an "sh at-job" as a cron job at
+the appropriate time under the user-id of the owner of the script.  The
+script takes care of the rest.  See
+.BR at (1)
+for the details.
+.SS "Job I/O"
+Standard input, output and error are the same as cron's if the job is
+started by the system crontabs or from package crontabs.  This means that
+output from system jobs usually ends up on the console and in the log file.
+Output from personal cron jobs or at jobs are mailed to the owner of the
+job.  No mail is sent if the job is silent.
+.SH OPTIONS
+.TP 5
+[\fB\-d\fR[\fIlevel\fR]]
+Set the debug level, by default 1.  Makes
+.B cron
+print info on what it happens to be doing.  Level 1 just tells about sleep
+times and what job is executed, level 2 also shows the internal crontab
+data on a table load.  (With time fields translated to match those of
+.BR "struct tm" ,
+see
+.BR ctime (3).)
+.SS SIGNALS
+.B Cron
+takes the following actions when sent one of the following signals:
+.TP 12
+.B SIGHUP
+Reload the crontab tables if they changed since the last time they were
+loaded, and reexamine the AT job spool.  Used by
+.BR at (1)
+and
+.BR crontab (1).
+.TP
+.B SIGUSR1
+Increase the debug level by 1.
+.TP
+.B SIGUSR2
+Turn debugging off.
+.SH ENVIRONMENT
+.B Cron
+sets the environment variables
+.BR USER ,
+.BR LOGNAME ,
+.BR HOME ,
+and
+.BR SHELL
+to the user's login name (2x), home directory, and shell if a job is
+executed for a given user.  The working directory is set to the user's home
+directory.  Everything else is inherited from
+.BR cron ,
+exactly as
+.B cron
+got it when it started.  Note that commands are always passed to
+.BR /bin/sh ,
+not to the user's shell.
+.PP
+System cron jobs are in principle executed with
+.BR cron 's
+environment, use
+.B "\-u root"
+or the crontab file
+.B /usr/spool/crontabs/root
+if you want to give root the same treatment as ordinary users.
+.SH FILES
+.TP 25n
+.B /usr/lib/crontab
+Main MINIX 3 crontab file.
+.TP
+.B /usr/local/lib/crontab
+Local jobs for all systems in an organization.
+.TP
+.B /var/lib/crontab
+System specific jobs.
+.TP
+.B /var/opt/\fIname\fP/lib/crontab
+Per package jobs for Minix-vmd.
+.TP
+.B /usr/lib/packages
+List of installed packages.
+.TP
+.B /usr/spool/crontabs/\fIuser\fP
+Per user jobs.
+.TP
+.B /usr/spool/at/*
+Jobs issued by
+.BR at (1).
+.TP
+.B /usr/run/cron.pid
+Process id of cron when cron is running.  Used by
+.BR at (1)
+and
+.BR crontab (1)
+to send cron a hangup signal.
+.SH "SEE ALSO"
+.BR at (1),
+.BR crontab (1).
+.SH NOTES
+A job is not reissued until a previous instance of it has exited.  The next
+time to execute is computed from the previous time it ran.  If job issuing
+lags behind on the system time then the next time to run it is computed from
+the current system time.
+.SH BUGS
+.B Cron
+doesn't like it if the system time is changed.  If set forward then cron
+will react when it next wakes up by running all jobs within the skipped time
+once or twice before it catches up.  Setting the clock backwards makes cron
+play dead until the system time passes the old time.  (Changing the system
+time is bad idea anyway, and not just because of cron.)
+.PP
+Jobs that fall in the missing hour in a change to Daylight Saving Time are
+skipped.  Nothing is done in the extra hour on the change out of DST.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+
+.\"
+.\" $PchId: cron.8,v 1.3 2000/07/17 18:49:18 philip Exp $
Index: /trunk/minix/man/man8/dhcpd.8
===================================================================
--- /trunk/minix/man/man8/dhcpd.8	(revision 9)
+++ /trunk/minix/man/man8/dhcpd.8	(revision 9)
@@ -0,0 +1,208 @@
+.TH DHCPD 8
+.SH NAME
+dhcpd \- dynamic host configuration protocol daemon
+.SH SYNOPSIS
+.in +.5i
+.ti -.5i
+.B dhdpd
+.RB [ \-qar ]
+.RB [ \-t [\fIlevel\fP]]
+.RB [ \-d [\fIlevel\fP]]
+.RB [ \-f
+.IR configfile ]
+.RB [ \-c
+.IR cachefile ]
+.RB [ \-p
+.IR poolfile ]
+.RI [ host " ...]"
+.in -.5i
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Dhcpd
+is a client and a server for the Dynamic Host Configuration Protocol.  As a
+client it collects DHCP data to configure the Ethernet networks with, and as
+a server it answers DHCP queries from other machines.
+.PP
+This manual page describes the operation of
+.BR dhcpd ,
+the associated configuration file is described in
+.BR dhcp.conf (5).
+(The latter, together with
+.BR boot (8),
+is of more practical value when it comes to getting a machine's networks
+interfaces up and running.  See the options section below for debugging DCHP
+problems.)
+.SS Initialization
+On a normal startup, i.e. none of the
+.BR \-q ,
+.BR \-a
+or
+.BR \-r
+options are given,
+.B dhcpd
+determines what IP devices are present, and which of those are Ethernets.
+For each network it looks for information in the configuration file as if
+it were a server answering a query for that network.  If any information is
+found then the IP address is configured and the information stored in the
+cache file.
+.SS "Client Operation"
+For each still unconfigured network a DHCP DISCOVER request is broadcast on
+that network.  If a DHCP OFFER reply is received then a DHCP REQUEST is
+broadcast for the IP address offered, and if a DHCP ACK is received then the
+network is configured and the information stored in the cache file.
+.PP
+If no reply is received then another query is sent after 4 seconds, and then
+again after 8 seconds, doubling each time until 64 seconds.  Every 64
+seconds thereafter a request is broadcast until a reply is received.
+.PP
+Once configured the DHCP lease, rebind and renew times are computed.  At the
+renew time a DHCP REQUEST is sent to the DHCP server to extend the lease.
+Normally we get an answer and refresh our information, but if no reply is
+received we wait for half the remaining time until the rebind time and keep
+retrying and halving the remaining time.  When the rebind time is reached
+the DHCP REQUEST is broadcast to try and reach some other DHCP server.
+Halving the remaining time again and again until the lease expires.  At that
+point we go back to square one and broadcast a DHCP DISCOVER.
+.PP
+If at any point a DHCP NAK is received we start over completely.  After a
+DHCP OFFER an ARP request is transmitted just before the DHCP REQUEST to
+check if the address offered is already in use.  If an ARP reply is received
+before the DHCP ACK then after the ACK we send a DHCP DECLINE to the server
+to tell that the address isn't what we want and again we start over.
+.SS "Router Discovery"
+The gateway offered by the DHCP server is made known to the TCP/IP server by
+sending an ICMP router advertisement to the local interface with a short
+lifetime and a low priority.  Then up to three router solicitations are
+broadcast three seconds apart to look for a router.  If a router answers
+with a router advertisement then we no longer worry about routing for that
+interface.  Otherwise the router information is refreshed before it expires
+and another solicitation is sent out.  This happens about twice an hour.
+.SS "Server Operation"
+Once all networks so marked are configured the daemon starts answering
+requests by other machines or relaying requests to other DHCP servers.
+DHCP requests are answered if information for a client
+can be found in the configuration file, or if a free address can be found in
+the pool file, or if a client rerequests an address it already owns.
+.PP
+If the daemon is both a server and a relay for a network then it will try
+to answer a request and only relay if it has no answer.
+.SS "Nothing more to do?"
+If the daemon finds out that all networks have an infinite lease (configured
+with a fixed address), there is no router information to keep warm, and
+it isn't a server then it simply exits.
+.SS "Asynchronous I/O?"
+MINIX 3 doesn't have the asynchronous I/O that Minix-vmd has, so under MINIX 3
+the daemon only works with one network at a time.  If it's stuck on the same
+network for 32 seconds then that network is closed and another network is
+tried for 32 seconds.  This usually works ok as a client, but as a server it
+can only handle one network.
+.SH OPTIONS
+.TP
+.B \-q
+Read and print the cache and pool file contents, showing DHCP information
+for each network, and the IP addresses in the pool with lease times and
+current/last owners of those addresses.
+.TP
+.B \-a
+Add the named hosts (or IP addresses) to the pool file.
+.TP
+.B \-r
+Remove hosts from the pool file.
+.TP
+.RB [ \-t [\fIlevel\fP]]
+Set the test level (by default 1).  At test level 1 all networks are seen as
+unconfigured, will not be configured and no data will be put in the cache.
+The program will just act as-if.  At test level 2 the interfaces will not be
+configured from the configuration file, the data must come from a remote
+server.  At level 3 the renewal, rebind and lease time will be 60, 120
+and 180 seconds.  At level 4 these times will be 60, 60, and 120.  At
+level 5 these times will be 60, 60, and 60.  These test levels are meant
+to debug the DHCP client code, and are best used with a high debug level.
+.TP
+.RB [ \-d [\fIlevel\fP]]
+Set the debug level (by default 1).  At debug level 1 the program shows
+Ethernet and IP addresses as they are determined or configured, DHCP
+messages sent and received with little detail (one line per message), and
+memory use.  At debug level 2 each DHCP packet is decoded and shown in
+detail.  At debug level 3 device opens and closes are shown.  The debugging
+level may also be increased by 1 at runtime by sending signal
+.BR SIGUSR1
+or turned off (set to 0) with
+.BR SIGUSR2 .
+.TP
+.BI \-f " configfile"
+Names the configuration file, by default
+.BR /etc/dhcp.conf .
+.TP
+.BI \-c " cachefile"
+Names the cache file, by default
+.BR /usr/adm/dhcp.cache .
+.TP
+.BI \-p " poolfile"
+Names the IP address pool, by default
+.BR /usr/adm/dhcp.pool .
+.SH "SEE ALSO"
+.BR RFC-2131 ,
+.BR RFC-1533 ,
+.BR dhcp.conf (5),
+.BR hosts (5),
+.BR ifconfig (8),
+.BR inet (8),
+.BR boot (8),
+.BR inetd (8),
+.BR nonamed (8).
+.SH DIAGNOSTICS
+.TP
+"'/etc/dhcp.conf', line ..."
+The program exits on any configuration file error.  You have to correct the
+error and restart the program.
+.TP
+"No lease set for address ..."
+There must be a lease time defined for addresses in the pool.  Correct and
+restart the program.
+.TP
+"###### declines #.#.#.# saying '...'"
+A client with the given client identifier (usually 01 followed by the client's
+Ethernet address) declines an IP address, hopefully with a message telling
+why.  This usually means that the IP address is already in use by another
+host.  This program, acting as a client, will tell what other host in its
+message, but Windows has no additional info alas.
+.TP
+"Got a NAK from #.#.#.# [through #.#.#.#] saying '...'"
+The server with the given IP address doesn't want us to have or keep the IP
+address we were offered or are rerequesting.  This could mean that the server
+has forgotten about us and has given our address to another machine.  This
+is bad if our lease hasn't yet expired.  There may be a relay involved, and
+there may even be a text message with precise information.
+.TP
+"#.#.#.# offered by #.#.#.# is already in use by #:#:#:#:#:#"
+We got an ARP reply for an offered address.  We won't accept it, and send
+out a DECLINE when we get an ACK.
+.TP
+"DHCP packet too big, ..."
+You've got way to much information in the configuration file, more than fits
+in a minimum size DHCP packet.  (Notify the author if you really need to send
+more information.  He doesn't think anyone needs to.)
+.TP
+"Pool table is corrupt"
+You will have to remove and refill the pool file.  Chaos may ensue if
+there are active clients and they don't use ARP to detect each other.
+(Most do.)
+.SH BUGS
+There is no randomization of timers.  Modern systems don't blink under the
+load of several clients broadcasting a few packets in sync.
+.PP
+There is no extra time spent waiting for an ARP reply.  It is assumed that
+any IP stack will immediately respond, so that the DHCP server can't
+possibly beat it at sending out an ACK.  (The DHCP server has to commit the
+lease to stable storage first anyway.)
+.PP
+Way more nonsense can be sent in a DHCP packet that MINIX 3 could do
+something with, but nobody does so we don't bother.
+.PP
+DHCP was invented by a rabid gerbil on speed.
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man8/dosminix.8
===================================================================
--- /trunk/minix/man/man8/dosminix.8	(revision 9)
+++ /trunk/minix/man/man8/dosminix.8	(revision 9)
@@ -0,0 +1,287 @@
+.TH DOSMINIX 8
+.SH NAME
+dosminix, mkfile \- Running MINIX 3 under DOS
+.SH SYNOPSIS
+.RB "C:\eMINIX> " "boot disk0.mnx" "\0\0\0\0\0(Typical example)"
+.br
+.RB "C:\eMINIX> " "mkfile \fIsize disk"
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+This text describes running MINIX 3
+.\" or Minix-vmd
+under DOS.  The DOS version
+of the Boot Monitor, described in
+.BR monitor (8),
+grabs as much memory as DOS is willing to give, loads MINIX 3 into that memory
+from the active partition of a "file as disk", and jumps to the MINIX 3 kernel
+to let MINIX 3 take control.  As far as DOS is concerned MINIX 3 is just a part
+of the
+.B boot.com
+program.
+.PP
+In the example above
+.B disk0.mnx
+is the "file as disk".  It is a file of many megabytes that is used by MINIX 3
+as a disk of four partitions.  These partitions will normally be
+.B /dev/dosd1
+through
+.BR /dev/dosd4 ,
+with
+.BR /dev/dosd0
+for the whole "disk".  The Boot Monitor will set the
+.B dosd0
+boot variable to the name of the disk (its first argument), the root file
+system will be the active partition, usually
+.BR dosd1 .
+It is better to use the special name
+.B bootdev
+to indicate this device, usually in the setting
+.BR rootdev = bootdev .
+.PP
+Once MINIX 3 is running it will operate the same as if started from a regular
+disk partition until it is shut down.  On shutdown from protected mode it
+will return to the Boot Monitor prompt, and with the
+.B exit
+command you leave the Boot Monitor and return to DOS.  Shutting down from
+real mode will reboot the machine, just like when run from a disk partition.
+(This more or less crashes DOS, but DOS is used to such abuse.)
+.SS EMM386
+MINIX 3 can't run in protected mode (286 or 386 mode) if DOS is using a memory
+manager like
+.BR EMM386 .
+You can either temporarily comment out EMM386 from
+.BR CONFIG.SYS ,
+or you can press
+.B F8
+on startup to bypass CONFIG.SYS.  This is only possible with the later DOS
+versions.
+.SS "Windows 95"
+Press F8 at startup to make the boot menu visible.  Choose
+"\fBCommand prompt\fP", or "\fBSafe mode command prompt\fP" to run DOS.
+Use the "safe mode" if EMM386 is started in CONFIG.SYS.
+.PP
+Typing F8 at the right moment isn't easy, so you may want to change the way
+Windows boots by editing the
+.B MSDOS.SYS
+file found in the root directory of your Windows system.  This is alas not
+trivial.
+Open a window on your main drive, click on "\fBView\fP" and choose
+"\fBOptions\fP."  In the Options window choose "\fBView\fP" and enable
+"\fBShow all files\fP".  The MSDOS.SYS file should now be visible, among
+several other hidden files.  Right-click on the MSDOS.SYS icon, choose
+"\fBProperties\fP" and disable "\fBRead-only\fP".  Bring MSDOS.SYS into a
+simple text editor such as Notepad.  In the
+.B "[Options]"
+segment add the following lines (or change existing lines into):
+.PP
+.RS
+.nf
+BootMenu=2
+BootMenuDelay=5
+.fi
+.RE
+.PP
+The first setting makes the Windows boot menu always visible, and the second
+line changes the delay before booting to 5 seconds.  Take care not to change
+anything else, or things will go horribly wrong.  Save MSDOS.SYS and exit.
+Don't forget to make MSDOS.SYS read-only again, and also hide all the hidden
+files again, unless you like it this way.
+.SS "DOS compatibility box"
+The 16-bit version of standard MINIX 3 can be run in real mode in a DOS box.
+This is somewhat surprising, because it means Windows 95 simulates devices
+like the keyboard, timer, and interrupt controller well enough to fool MINIX 3
+into thinking that all is well.  Alas it doesn't work as well under Windows
+NT.  Keypresses get lost if you type to fast, and using the floppy
+occasionally locks MINIX 3 up.  This is a bit disappointing, because it is the
+only way to run MINIX 3 under NT.  Under Windows 95 one is better off
+putting the system in DOS at boot and then to run MINIX 3 in protected mode.
+.PP
+One thing that is better under NT is that the Boot Monitor is able to get a
+so-called "Upper Memory Block", thereby raising useful memory to about 750K.
+Windows 95 however hogs leftover UMB memory in a process named
+.BR vmm32 ,
+whatever that may be.  To get
+some of this memory you can put
+.B "BOOT /U"
+at the start of
+.BR autoexec.bat .
+The monitor will grab a 64K UMB if it can get it, and keep that memory safe
+for use by MINIX 3 when it is later started from Windows.
+.PP
+The easiest way to start MINIX 3 is to give all MINIX 3 disk files the suffix
+.BR MNX .
+Doubleclick on the disk you want to run to make the "\fBOpen With\fP" window
+appear.  Click on "\fBOther\fP" and browse to the
+.B BOOT.COM
+program.  Set the name of the .mnx files to "\fBMINIX 3 "disk" file\fP" in the
+description box if you want everything right.  In the future you can
+just click on a MINIX 3 disk file to run it, you don't have to start a DOS
+box first.  (To make it perfect use "View", "Options", "File Types", choose
+"MINIX 3 "disk" file", "Edit", "Change Icon", "Browse", select MINIX.ICO.)
+.PP
+When MINIX 3 shuts down it will try to reboot what it thinks is a PC.  Windows
+seems to assume that the DOS session has exited.  Right-click on the
+BOOT.COM program, "Properties", "Program", and enable "Close on exit" to make
+the DOS box disappear automatically when MINIX 3 thinks it reboots.  You may
+also want to lock the font to
+.BR 7x12 ,
+or any other font that isn't ugly.
+.PP
+MINIX 3 disk files are opened in a write-exclusive mode.  A second MINIX 3
+session can only open it read-only, which may lead to a "can't open
+root device" error.
+.SS "Mkfile"
+MINIX 3 disk files can be created or resized with the
+.B mkfile
+utility.  Its two arguments are the size and name of the disk file.  The
+size is a number optionally followed by the letter
+.BR k ,
+.BR m
+or
+.BR g
+to specify kilobytes, megabytes, or even gigabytes.  So the call
+.PP
+.RS
+.B "mkfile 50m disk5.mnx"
+.RE
+.PP
+will create a 50 megabyte file named
+.BR disk5.mnx .
+If the file already exist then it is shrunk or grown to 50 megabytes.  No
+data is lost if the file is grown.  If the file is shrunk then only the data
+that is cut off is lost.  These features allow one to inrease the size of a
+MINIX 3 /usr partition with the following recipe:
+.PP
+.RS
+.ta +24n+2m
+.nf
+copy disk0.mnx disk0.new	Copy the disk to disk0.new
+mkfile 100M disk0.new	Enlarge to 100 megabytes
+boot disk0.mnx	Boot the old "disk"
+[ESC]	Get the attention of the monitor
+dosd5=disk0.new	/dev/dosd5 becomes disk0.new
+boot
+\&...
+login: root
+.fi
+.in +(24n+2m)
+.ti -(24n+2m)
+part	Choose dosd5, move to the Size field of dosd7
+partition, hit 'm' to fill it out to the end of the "disk".  Write and quit.
+.in -(24n+2m)
+.nf
+mkfs /dev/dosd7	Recreate the file system, but larger
+mount /dev/dosd7 /mnt
+cpdir -v /usr /mnt	Copy /usr to the new disk's /usr to be
+shutdown	Back to the monitor
+exit	Back to DOS
+ren disk0.mnx disk0.old
+ren disk0.new disk0.mnx	Replace old by new
+boot disk0.mnx	Run the larger system
+.fi
+.RE
+.PP
+Now MINIX 3 runs from a larger "disk".  Don't worry if it claims to have
+crashed, there wasn't a "shutdown" entry in /usr/adm/wtmp at the time it was
+copied.
+.PP
+The above recipe is for a ordinary standard MINIX 3 installation with /usr on
+the second and last partition.
+.\" Minix-vmd usually has /usr on the third and
+.\" last partition (dosd3 / dosd8), its
+.\" .B mkfs
+.\" command requires a
+.\" .B "-t\ 2f"
+.\" option to specify the file system type as "V2 flex", and it knows if
+.\" it has crashed or not.
+.SS Backups
+In the recipe above you saw how simple it is to create a new system, just
+copy a disk file.  It is equally simple to make a backup, you just copy the
+disk file.  To make a test system: copy the disk file.  To make another test
+system: copy the disk file.  Let friends have their own MINIX 3: copy the disk
+file again.  (Exciting, eh?)
+.PP
+You may want to save a MINIX 3 disk file in a ZIP file to save space.  It may
+look as a good idea to first run
+.B "make clean"
+in
+.B /usr/src
+to remove all the binary junk, but alas that has no effect at all.
+The disk file is compressed under DOS, and there it is unknown which blocks
+are in use and which are free.  With the following trick you can make those
+deleted blocks compress really well:
+.PP
+.RS
+.nf
+cd /usr/tmp
+echo >junk
+while cat junk >>junk; do :; done
+sync
+rm junk
+.fi
+.RE
+.PP
+After these commands all free blocks contain newlines.  Long runs of the
+same byte happen to compress by a factor 1000, so the unused disk blocks
+will almost disappear in the ZIP file.
+.\" Under Minix-vmd you can use
+.\" .PP
+.\" .RS
+.\" cp /dev/zero junk
+.\" .RE
+.\" .PP
+.\" instead of the echo/while pair of lines above.  Standard MINIX 3 doesn't have
+.\" /dev/zero.
+.SS "FAT driver"
+The dos disk driver, described in
+.BR dosd (4),
+has two identities.  By default you get the "\fBfile\fP" driver, that uses
+DOS file I/O calls to access a large DOS file as a disk.  The other
+alternative is the "\fBFAT\fP" driver.  The FAT driver sits on top of an
+ordinary MINIX 3 disk driver, and interprets a partition as a FAT (File Access
+Table) file system to find a file to use as a MINIX 3 disk.  The result
+has the same effect as the file driver, except that no costly calls to DOS
+are made.  To enable this feature you have to use the following Boot
+environment settings:
+.PP
+.RS
+.nf
+dosd = fat
+dosd0 = hd1:\eminix\edisk0.mnx
+.fi
+.RE
+.PP
+The
+.B dosd
+setting tells MINIX 3 to use the FAT driver, and the
+.B dosd0
+setting tells the MINIX 3 device and DOS file name to use.  Disk I/O should
+be sped up nicely by this change, although typical use of MINIX 3 doesn't
+require fast disk I/O, so the difference won't be too noticable.
+.PP
+Support for FAT-32 (big file system support added in the later Windows 95
+releases) has not been tested very well.  The FAT-12 and FAT-16 code has
+been used a lot, and seems safe.  Note the risks inherent in these
+drivers:  The file driver uses simple DOS file I/O calls, leaving it to
+DOS to know its own file system.  The FAT driver interprets FAT file system
+structures by itself.  MINIX 3 booted from a real hard disk partition can
+only use DOS disk files through the FAT driver.
+.SH "SEE ALSO"
+.BR dosd (4),
+.BR monitor (8),
+.BR usage (8).
+.SH NOTES
+Use at your own risk.
+.SH BUGS
+Hasn't been tried under Windows 98 yet.
+.PP
+Pray the deity of your choice will forgive you for running a UNIX-like
+system as an ordinary DOS program.  The author of this code is already
+doomed.  When his time comes the daemons wi*(&%*$%*&
+.br
+Memory fault \- core dumped
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/elvprsv.8
===================================================================
--- /trunk/minix/man/man8/elvprsv.8	(revision 9)
+++ /trunk/minix/man/man8/elvprsv.8	(revision 9)
@@ -0,0 +1,54 @@
+.TH ELVPRSV 8
+.SH NAME
+elvprsv - Preserve the the modified version of a file after a crash.
+.SH SYNOPSIS
+.nf
+\fB\fBelvprsv\fP ["-\fIwhy elvis died\fP"] /tmp/\fIfilename\fP...
+\fB\fBelvprsv\fP -R /tmp/\fIfilename\fP...
+.fi
+.SH DESCRIPTION
+.PP
+\fIelvprsv\fP preserves your edited text after \fIelvis\fP dies.
+The text can be recovered later, via the \fIelvprsv\fP program.
+.PP
+For UNIX-like systems,
+you should never need to run this program from the command line.
+It is run automatically when \fIelvis\fP is about to die,
+and it should be run (via /etc/rc) when the computer is booted.
+THAT'S ALL!
+.PP
+For non-UNIX systems such as MS-DOS, you can either use \fIelvprsv\fP
+the same way as under UNIX systems (by running it from your AUTOEXEC.BAT file),
+or you can run it separately with the "-R" flag to recover the files
+in one step.
+.PP
+If you're editing a file when \fIelvis\fP dies
+(due to a bug, system crash, power failure, etc.)
+then \fIelvprsv\fP will preserve the most recent version of your text.
+The preserved text is stored in a special directory; it does NOT overwrite
+your text file automatically.
+.PP
+\fIelvprsv\fP will send mail to any user whose work it preserves,
+if your operating system normally supports mail.
+.SH FILES
+.IP /tmp/elv*
+The temporary file that \fIelvis\fP was using when it died.
+.IP /usr/preserve/p*
+The text that is preserved by \fIelvprsv\fP.
+.IP /usr/preserve/Index
+A text file which lists the names of all preserved files, and the names
+of the /usr/preserve/p* files which contain their preserved text.
+.SH BUGS
+.PP
+Due to the permissions on the /usr/preserve directory, on UNIX systems
+\fIelvprsv\fP must be run as superuser.
+This is accomplished by making the \fIelvprsv\fP executable be owned by "root"
+and turning on its "set user id" bit.
+.PP
+If you're editing a nameless buffer when \fIelvis\fP dies, then \fIelvprsv\fP will pretend
+that the file was named "foo".
+.SH AUTHOR
+.nf
+Steve Kirkendall
+kirkenda@cs.pdx.edu
+.fi
Index: /trunk/minix/man/man8/fdisk.8
===================================================================
--- /trunk/minix/man/man8/fdisk.8	(revision 9)
+++ /trunk/minix/man/man8/fdisk.8	(revision 9)
@@ -0,0 +1,58 @@
+.TH FDISK 8
+.SH NAME
+fdisk \- partition a hard disk [IBM]
+.SH SYNOPSIS
+\fBfdisk\fR [\fB\-h\fIm\fR]\fR [\fB\-s\fIn\fR]\fR [\fIfile\fR]\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\fB\-h" "Number of disk heads is \fIm\fR"
+.FL "\fB\-s" "Number of sectors per track is \fIn\fR"
+.SH EXAMPLES
+.EX "fdisk /dev/hd0" "Examine disk partitions"
+.EX "fdisk \-h9 /dev/hd0" "Examine disk with 9 heads"
+.SH DESCRIPTION
+.PP
+When \fIfdisk\fR starts up, it reads in the partition table and displays 
+it.
+It then presents a menu to allow the user to modify partitions, store the
+partition table on a file, or load it from a file.  Partitions can be marked
+as 
+\s-1MINIX 3\s-1,
+DOS or other, as well as active or not.
+Using \fIfdisk\fR is self-explanatory.  
+However, be aware that
+repartitioning a disk will cause information on it to be lost.  
+Rebooting the system \fIimmediately\fR 
+is mandatory after changing partition sizes and parameters.
+\s-1MINIX 3\s-1, 
+\&\s-2XENIX\s0, \s-2PC-IX\s0, and \s-2MS-DOS\s0 all have different 
+partition numbering schemes.
+Thus when using multiple systems on the same disk, be careful.
+.PP
+Note that
+\s-1MINIX 3\s-1,
+unlike
+\&MS-DOS ,
+cannot access the last sector in a partition with an odd number of sectors.
+The reason that odd partition sizes do not cause a problem with
+\s-2MS-DOS\s0 is that \s-2MS-DOS\s0 allocates disk space in units of
+512-byte sectors, whereas 
+\s-1MINIX 3\s-1
+uses 1K blocks.
+\fIFdisk\fR has a variety of other features that can be seen by typing \fIh\fR.
+.PP
+.I Fdisk
+normally knows the geometry of the device by asking the driver.  You can use
+the \fB\-h\fP and \fB\-s\fP options to override the numbers found.
+.SH "SEE ALSO"
+.BR part (8).
Index: /trunk/minix/man/man8/fingerd.8
===================================================================
--- /trunk/minix/man/man8/fingerd.8	(revision 9)
+++ /trunk/minix/man/man8/fingerd.8	(revision 9)
@@ -0,0 +1,53 @@
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)fingerd.8c	6.1 (Berkeley) 5/23/86
+.\"
+.TH FINGERD 8 "May 23, 1986"
+.UC 6
+.SH NAME
+fingerd, in.fingerd \- remote user information server
+.SH SYNOPSIS
+.B "finger stream tcp nowait nobody /usr/sbin/in.fingerd in.fingerd"
+.br
+.B "tcpd finger /usr/sbin/in.fingerd in.fingerd"
+.SH DESCRIPTION
+.B Fingerd
+is a simple protocol based on RFC742 that provides an interface to the
+Name and Finger programs at several network sites.
+The program is supposed to return a friendly,
+human-oriented status report on either the system at the moment
+or a particular person in depth.
+There is no required format and the
+protocol consists mostly of specifying a single ``command line''.
+.PP
+.B Fingerd
+listens for TCP requests at port 79.
+Once connected it reads a single command line
+terminated by a <CRLF> which is passed to
+.BR finger (1).
+.B Fingerd
+closes its connections as soon as the output is finished.
+.PP
+If the line is null (i.e. just a <CRLF> is sent) then 
+.B finger
+returns a ``default'' report that lists all people logged into
+the system at that moment.
+.PP
+If a user name is specified (e.g. eric<CRLF>) then the
+response lists more extended information for only that particular user,
+whether logged in or not.
+Allowable ``names'' in the command line include both ``login names''
+and ``user names''.
+If a name is ambiguous, all possible derivations are returned.
+.SH SEE ALSO
+.BR finger (1).
+.SH BUGS
+Connecting directly to the server from a TIP
+or an equally narrow-minded TELNET-protocol user program can result
+in meaningless attempts at option negotiation being sent to the
+server, which will foul up the command line interpretation.
+.B Fingerd
+should be taught to filter out IAC's and perhaps even respond
+negatively (IAC WON'T) to all option commands received.
Index: /trunk/minix/man/man8/ftpd.8
===================================================================
--- /trunk/minix/man/man8/ftpd.8	(revision 9)
+++ /trunk/minix/man/man8/ftpd.8	(revision 9)
@@ -0,0 +1,145 @@
+.\" Copyright (c) 1985 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)ftpd.8c	6.4 (Berkeley) 5/28/86
+.\"
+.TH FTPD 8
+.SH NAME
+ftpd, in.ftpd, setup.anonftp \- DARPA Internet File Transfer Protocol server
+.SH SYNOPSIS
+.B "ftp stream tcp nowait root /usr/sbin/in.ftpd in.ftpd"
+.br
+.B "tcpd ftp /usr/sbin/in.ftpd"
+.SH DESCRIPTION
+.B Ftpd
+is the DARPA Internet File Transfer Prototocol
+server process.  The server uses the TCP protocol
+and listens at the port specified in the ``ftp''
+service specification; see
+.BR services (5).
+.PP
+The ftp server currently supports the following ftp
+requests;  case is not distinguished.
+.PP
+.nf
+.ta \w'Request        'u
+\fBRequest	Description\fP
+ABOR	abort previous command
+ACCT	specify account (ignored)
+ALLO	allocate storage (vacuously)
+APPE	append to a file
+CDUP	change to parent of current working directory
+CWD	change working directory
+DELE	delete a file
+HELP	give help information
+LIST	give list files in a directory (``ls -lA'')
+MKD	make a directory
+MODE	specify data transfer \fImode\fP
+NLST	give name list of files in directory (``ls'')
+NOOP	do nothing
+PASS	specify password
+PASV	prepare for server-to-server transfer
+PORT	specify data connection port
+PWD	print the current working directory
+QUIT	terminate session
+RETR	retrieve a file
+RMD	remove a directory
+RNFR	specify rename-from file name
+RNTO	specify rename-to file name
+STOR	store a file
+STOU	store a file with a unique name
+STRU	specify data transfer \fIstructure\fP
+TYPE	specify data transfer \fItype\fP
+USER	specify user name
+XCUP	change to parent of current working directory
+XCWD	change working directory
+XMKD	make a directory
+XPWD	print the current working directory
+XRMD	remove a directory
+.fi
+.PP
+The remaining ftp requests specified in Internet RFC 959 are
+recognized, but not implemented.
+.PP
+The ftp server will abort an active file transfer only when the
+ABOR command is preceded by a Telnet "Interrupt Process" (IP)
+signal and a Telnet "Synch" signal in the command Telnet stream,
+as described in Internet RFC 959.
+.PP
+.B Ftpd
+interprets file names according to the ``globbing''
+conventions used by
+.BR csh (1).
+This allows users to utilize the metacharacters ``*?[]{}~''.
+.PP
+.B Ftpd
+authenticates users according to three rules. 
+.IP 1)
+The user name must be in the password data base,
+.BR /etc/passwd ,
+and not have a null password.  In this case a password
+must be provided by the client before any file operations
+may be performed.
+.IP 2)
+The user name must not appear in the file
+.BR /etc/ftpusers .
+.IP 3)
+If the user name is ``anonymous'' or ``ftp'', an
+anonymous ftp account must be present in the password
+file (user ``ftp'').  In this case the user is allowed
+to log in by specifying any password (by convention this
+is given as the client host's name).
+.PP
+In the last case, 
+.B ftpd
+takes special measures to restrict the client's access privileges.
+The server performs a 
+.BR chroot (2)
+command to the home directory of the ``ftp'' user.
+In order that system security is not breached, it is recommended
+that the ``ftp'' subtree be constructed with care;  the following
+rules are recommended.
+.IP ~ftp)
+Make the home directory owned by ``ftp'' and unwritable by anyone.
+.IP ~ftp/bin)
+Make this directory owned by the super-user and unwritable by
+anyone.  The program
+.BR ls (1)
+must be present to support the list commands.  This
+program should have mode 111.
+.IP ~ftp/etc)
+This directory could be created, and could have
+.BR passwd (5)
+and
+.BR group (5)
+databases in it so that
+.B ls
+can show file ownership, but outsiders will grab your password file and
+misuse it to spam you.  So don't bother.
+.IP ~ftp/pub)
+Make this directory mode 755 and owned by the super-user.  Create
+directories in it owned by users if those users want to manage an
+anonymous ftp directory.
+.IP ~ftp/pub/incoming)
+Optionally create this directory for anonymous uploads.  Make it mode
+777.  The FTP daemon will create files with mode 266, so remote users
+can write a file, but only local users can do something with it.
+.PP
+The script
+.B setup.anonftp
+can be used to create or check an anonymous FTP tree.
+.SH "SEE ALSO"
+.BR ftp (1).
+.SH BUGS
+The anonymous account is inherently dangerous and should
+avoided when possible.
+.ig \" MINIX 3 doesn't have privileged port numbers (yet?)
+.PP
+The server must run as the super-user
+to create sockets with privileged port numbers.  It maintains
+an effective user id of the logged in user, reverting to
+the super-user only when binding addresses to sockets.  The
+possible security holes have been extensively
+scrutinized, but are possibly incomplete.
+..
Index: /trunk/minix/man/man8/getty.8
===================================================================
--- /trunk/minix/man/man8/getty.8	(revision 9)
+++ /trunk/minix/man/man8/getty.8	(revision 9)
@@ -0,0 +1,40 @@
+.TH GETTY 8
+.SH NAME
+getty \- system login banner
+.SH SYNOPSIS
+.B getty
+.RI [ banner " ...]"
+.SH DESCRIPTION
+.B Getty
+displays a system identification banner, reads a user name from standard
+input and executes
+.B login
+with that name as argument.
+.PP
+.B Getty
+uses its arguments separated by spaces as a login banner.  The character
+sequences
+.BR \en ,
+.BR \es
+and
+.BR \et
+are printed as newline, space and tab.  Any other
+.BI \e x
+prints that
+.IR x .
+The character sequences
+.BR %s ,
+.BR %n ,
+etc. produce the same output as
+.BR "uname \-s" ,
+.BR "uname \-n" ,
+etc.  The default banner is
+.PP
+.RS
+%s\es\esRelease\es%r\esVersion\es%v\en\en%n\eslogin:\es
+.RE
+.SH "SEE ALSO"
+.BR ttytab (5),
+.BR init (8).
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man8/halt.8
===================================================================
--- /trunk/minix/man/man8/halt.8	(revision 9)
+++ /trunk/minix/man/man8/halt.8	(revision 9)
@@ -0,0 +1,33 @@
+.TH HALT 8
+.SH NAME
+halt \- abruptly stop the system
+.SH SYNOPSIS
+\fBhalt\fP [\fB\-f\fP]
+.SH DESCRIPTION
+.B Halt
+stops the system almost immediately.  The users are not informed about
+the things to come.
+.B Halt
+is logged in
+.B /usr/adm/wtmp
+and in 
+.BR /usr/adm/log ,
+if these files exist.
+.B Halt
+should only be run by the super-user, any other caller will be refused.
+.PP
+.B Halt
+is a rather rude program.
+.BR Shutdown (8)
+is preferred for it performs a more gentle halt routine.
+.PP
+.B Halt \-f
+is even worse, it omits the terminate signals that are normally
+sent first to all processes to give them a chance to die peacefully.
+.SH "SEE ALSO"
+.BR reboot (2),
+.BR shutdown (8),
+.BR reboot (8),
+.BR boot (8).
+.SH AUTHOR
+Edvard Tuinder (v892231@si.hhs.NL)
Index: /trunk/minix/man/man8/ifconfig.8
===================================================================
--- /trunk/minix/man/man8/ifconfig.8	(revision 9)
+++ /trunk/minix/man/man8/ifconfig.8	(revision 9)
@@ -0,0 +1,50 @@
+.TH IFCONFIG 8
+.SH NAME
+ifconfig \- configure a TCP/IP device
+.SH SYNOPSIS
+.B ifconfig
+.RB [ \-I
+.IR ip-device ]
+.RB [ \-h
+.IR ipaddr ]
+.RB [ \-n
+.IR netmask ]
+.RB [ \-m
+.IR mtu ]
+.RB [ \-iva ]
+.SH DESCRIPTION
+.B Ifconfig
+initializes a TCP/IP device setting the IP address and/or netmask.  It will
+report the address and netmask set.  This command may be used if the system
+has not been configured properly yet.  It is only used at boot time to set a
+fixed address for a system without a physical ethernet.  Normally the
+.B inet
+task will find it out by itself from the RARP server.
+.SH OPTIONS
+.TP
+.B \-h
+The decimal TCP/IP address to set.
+.TP
+.B \-n
+The netmask to set.
+.TP
+.B \-m
+The mtu to set.  (Minix-vmd only.)
+.TP
+.B \-i
+Don't set the IP address or netmask if already set.  This way ifconfig cannot
+interfere if the numbers have been found out by RARP.
+.TP
+.B \-v
+Report IP address and netmask.  This is the default action if there are no
+other options.
+.TP
+.B \-a
+Report the IP addresses and netmasks of all configured interfaces.
+.SH "SEE ALSO"
+.BR hostaddr (1),
+.BR rarpd (8),
+.BR inet (8),
+.BR boot (8).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/inet.8
===================================================================
--- /trunk/minix/man/man8/inet.8	(revision 9)
+++ /trunk/minix/man/man8/inet.8	(revision 9)
@@ -0,0 +1,146 @@
+.TH INET 8
+.SH NAME
+inet, inet.conf \- TCP/IP server
+.SH SYNOPSIS
+.B inet
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Inet
+is the TCP/IP server.  It is a device driver that interfaces between the
+file server and the low level ethernet device driver.  The interface to this
+server is described in
+.BR ip (4).
+.PP
+.B Inet
+starts as a normal process, reads a the configuration file
+.B /etc/inet.conf
+to see what it should do, and uses a few special low level system calls 
+to turn itself into a server.  The format of the configuration file is as
+follows:
+.SS Configuration
+The inet configuration file is fairly simple, here is an example:
+.PP
+.RS
+.ft C
+.nf
+eth0 DP8390 0 { default; };
+psip1;
+.fi
+.ft P
+.RS
+.PP
+It tells that network 0 (the one containing devices
+.BR eth0 ,
+.BR ip0 ,
+.BR tcp0
+and
+.BR udp0 )
+uses the ethernet device driver handled
+by task "DP8390" at port 0.  This network is marked as the default
+network, so most programs use it through the unnumbered devices like
+.B /dev/tcp
+or
+.BR /dev/udp .
+Network 1 is a Pseudo IP network that can be used for
+a serial IP over a modem for instance.
+.PP
+The configuration file may look like a common configuration file as
+described by
+.BR configfile (5),
+but it is currently just a simple subset allowing only what you see here.
+The following network definitions are possible:
+.PP
+.BI eth N
+.I task port
+.RI { options };
+.RS
+This sets up an ethernet with device name
+.BI /dev/eth N\fR,
+built on the given ethernet device driver at the given port at that driver.
+(If a network driver manages two network
+cards then they are at port 0 and 1.)
+.br
+.RE
+.PP
+.BI eth N
+.B vlan
+.I id
+.BI eth M
+.RI { options };
+\0\0\0\0
+.RS
+The ethernet
+.BI eth N
+uses VLAN number
+.I id
+and is built on ethernet
+.BI eth M\fR.
+A packet given to this network has a VLAN tag prefixed to it and is then
+handed over to another ethernet for transmission.  Likewise a packet on
+that ethernet carrying the appropriate VLAN tag has this tag removed and is
+sent on to this network.  The VLAN ethernet behaves like an ordinary ethernet
+as far as applications are concerned.
+.RE
+.PP
+.BI psip N
+.RI { options };
+.RS
+Creates pseudo IP network
+.BI /dev/psip N\fR,
+usable for IP over serial lines, tunnels and whatnot.
+.RE
+.SH OPTIONS
+Some options can be given between braces. 
+.PP
+.BR default ;
+.RS
+Mark this network as the default network.  Exactly one of the networks must
+be so marked.
+When
+.B inet
+is started it will check and create all the necessary network devices before
+becoming a server.  To know what major device number to use it checks
+.BR /dev/ip ,
+so that device must already exist.  It can be created by
+.B MAKEDEV
+if need be.
+.RE
+.PP
+.BR "no ip" ;
+.br
+.BR "no tcp" ;
+.br
+.BR "no udp" ;
+.RS
+These options turn the IP, TCP, or UDP layer off.  Inet will not enable the
+devices for these layers, and will deactivate code for these layers.
+Disabling IP will also disable TCP or UDP, because they need IP to function.
+An ethernet without an IP layer can be used as for stealth listening.  An IP
+network without TCP or UDP can be used to pester students into creating the
+missing functionality.  Keeps them off the streets, and maybe they'll learn
+something.
+.RE
+.SH "SEE ALSO"
+.BR ip (4),
+.BR boot (8).
+.SH NOTES
+The number of networks that can be defined are 2 (Minix-86), 4 (Minix-386)
+or 16 (Minix-vmd).  This limits both the total number and the highest
+device number you can use.
+.PP
+Getting a network administrator to give you a trunk or multi-VLAN port to
+run multiple networks on can be a challenge.  It questions their idea that
+VLANs are separate networks, while in reality it is just one big ethernet.
+.SH ACKNOWLEDGMENTS
+Cindy Crawford, for providing invaluable help debugging this server.
+.SH AUTHOR
+.ta \w'Manual:'u+2n
+Code:	Philip Homburg <philip@cs.vu.nl>
+.br
+Manual:	Kees J. Bot <kjb@cs.vu.nl>
+
+.\"
+.\" $PchId: inet.8,v 1.6 2001/10/08 19:01:35 philip Exp $
Index: /trunk/minix/man/man8/init.8
===================================================================
--- /trunk/minix/man/man8/init.8	(revision 9)
+++ /trunk/minix/man/man8/init.8	(revision 9)
@@ -0,0 +1,141 @@
+.TH INIT 8
+.SH NAME
+init \- grandparent of all processes
+.SH DESCRIPTION
+The first program started by MINIX 3 is
+.BR init .
+The actions performed by
+.B init
+can be summarized by this pseudo shell program:
+.RS
+.nf
+.if t .ft C
+
+# Open 0, 1, 2.
+exec </dev/null >/dev/log 2>&1
+
+# Run the system initialization script.
+sh /etc/rc $bootopts
+
+>/etc/utmp
+echo reboot >>/usr/adm/wtmp
+
+while :; do
+	# Wait for a process to exit, but don't always block.
+	wait
+
+	# Record logout.  (Not in this dumb way, of course.)
+	if "pid is in my tables" $pid
+	then
+		echo "logout $pid" >/etc/utmp
+		echo "logout $pid" >>/usr/adm/wtmp
+	fi
+
+	# Start a new session.
+	while read line type getty init
+	do
+		if idle $line
+		then
+			$init ... <$tty >$tty
+			$getty <$tty >$tty 2>&1 &
+			pid=$!
+			"add pid to tables" $pid
+			echo "login $line $pid" >/etc/utmp
+			echo "login $line $pid" >>/usr/adm/wtmp
+		fi
+	done < /dev/ttytab
+done
+
+.if t .ft R
+.fi
+.RE
+The first action of
+.B init
+is to run
+.B /etc/rc
+to initialize the system as described in
+.BR boot (8).
+.B Init
+then enters its main loop where it waits for processes to exit, and starts
+processes on each enabled terminal line.  The file
+.B /etc/ttytab
+contains a list of terminal devices, their terminal types, the program to
+execute on them to allow one to login (usually
+.BR getty (8)),
+and the program to execute first to initialize the line (usually
+.BR stty (1)).
+These fields may be left out to indicate that a line is disabled or that
+initialization is not necessary.  The commands are searched using the path
+.BR /sbin:/bin:/usr/sbin:/usr/bin .
+.PP
+.B Init
+accepts several signals that must be sent to process id 1.  (It is the first
+process, so natually its process id is 1.)  The signals are:
+.TP
+.B SIGHUP
+When receiving a hangup signal,
+.B init
+will forget about errors and rescan
+.B ttytab
+for processes to execute.
+.B Init
+normally rescans
+.B ttytab
+each time it feels the need to respawn a process, so the hangup signal is only
+needed if a line has been shut down, or after a terminate signal.  Note
+that after turning a line off you will have to kill the process running on
+that line manually,
+.B init
+doesn't do that for you.
+.TP
+.B SIGTERM
+Normally sent by programs that halt or reboot MINIX 3.  Causes
+.B init
+to stop spawning new processes.
+.TP
+.B SIGABRT
+Sent by the keyboard driver when the
+.B CTRL-ALT-DEL
+key combination is typed.  Causes
+.B init
+to run the
+.B shutdown
+command.  A second abort signal makes
+.B init
+halt the system directly with a system call.  The keyboard driver halts the
+system, without a sync, after the third CTRL-ALT-DEL.
+.SS "MINIX 3 vs. Minix-vmd"
+There are a few differences between standard MINIX 3 and Minix-vmd on how
+.B init
+is run.  The
+.B /etc/rc
+file is executed under standard MINIX 3 with input connected to
+.BR /dev/console ,
+but under Minix-vmd this is still
+.BR /dev/null .
+This means that under Minix-vmd processes must be reconnected to
+.B /dev/console
+with the
+.BR intr (8)
+program if they need user interaction.
+Minix-vmd passes the value of the
+.B bootopts
+boot variable to /etc/rc.  Standard MINIX 3 does not.
+.SH FILES
+.TP 25n
+.B /etc/ttytab
+List of terminals devices.
+.TP
+.B /etc/utmp
+List of currently logged in users.
+.TP
+.B /usr/adm/wtmp
+Login/logout history.
+.SH "SEE ALSO"
+.BR ttytab (5),
+.BR utmp (5),
+.BR getty (8),
+.BR stty (1),
+.BR boot (8).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/installboot.8
===================================================================
--- /trunk/minix/man/man8/installboot.8	(revision 9)
+++ /trunk/minix/man/man8/installboot.8	(revision 9)
@@ -0,0 +1,395 @@
+.TH INSTALLBOOT 8
+.SH NAME
+installboot \- make a device bootable
+.SH SYNOPSIS
+.B installboot \-i(mage)
+.I image
+.RI [ label :] kernel
+.IR "mm fs" " ... " init
+.br
+.B installboot \-(e)x(tract)
+.I image
+.br
+.B installboot \-d(evice)
+.I device bootblock boot
+.RI [[ label :] image
+\&...]
+.br
+.B installboot \-b(oot)
+.I device bootblock boot
+.RI [ label :] image
+\&...
+.br
+.B installboot \-m(aster)
+.I device masterboot
+.RI [ keys " [" logical ]]
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Installboot
+may be used to make a device bootable by constructing a kernel image and
+installing bootstrap code into the boot block of a MINIX 3 file system.  To
+understand how this can be done one first has to know what happens when a
+PC is booted.
+.PP
+When the power is turned on the typical PC will try to read the first sector
+from the first floppy disk or from the first hard disk into memory and execute
+it.  The code obtained from the hard disk (from the so-called master boot
+sector) will immediately replace itself by the code found in the first sector
+of the active partition.  Thus the PC is now executing the bootstrap code found
+in the first sector of /dev/fd0, /dev/c0d0p0, /dev/c0d0p1, /dev/c0d0p2, or
+/dev/c0d0p3 (assuming the boot disk is attached to controller 0.)
+The bootstrap will locate the operating system on the device it itself was
+loaded from, load it, and execute it.
+.PP
+To make a MINIX 3 file system
+.B /dev/fd0
+mounted on
+.B /mnt
+bootable, enter the following:
+.SP
+.RS
+.ft B
+cp /usr/mdec/boot /mnt/boot
+.SP
+installboot \-i /mnt/minix kernel mm fs init
+.SP
+installboot \-d /dev/fd0 /usr/mdec/bootblock boot
+.ft P
+.RE
+.PP
+The "boot" program in the example is named the "Boot Monitor".  It is loaded
+by the bootblock code placed in the boot sector of /dev/fd0 and it will take
+care of loading the kernel image "minix" from the root directory of the
+file system.  See
+.BR monitor (8)
+for a description of the Boot Monitor.  Note that
+.B boot
+is a name in the file system on
+.B /dev/fd0
+in this example, the same file as
+.BR /mnt/boot .
+Making
+.B /mnt/minix
+is normally not necessary, there is usually a kernel image in the
+.B tools
+directory.
+.SH OPTIONS
+.B \-i(mage)
+.I image
+.RI [ label :] kernel
+.IR "mm fs" " ... " init
+.RS
+The
+.B \-image
+option (or the
+.B \-i
+shorthand) combines the executable files needed to run MINIX 3 in one file.
+Only the names and a few zero bytes are inserted into the image.  The name
+is for identification and the zeros are used to pad separate pieces to
+sector boundaries for fast loading.
+.SP
+An executable may be prefixed by a label.  The Monitor may be instructed to
+load processes by label.  So more than one kernel process may be included in
+the image, each with a different winchester driver for instance.  So if you
+have compiled two different kernels with an AT or XT driver then
+.SP
+.RS
+.BI "installboot \-i" " image AT:at_kernel XT:xt_kernel mm fs init"
+.RE
+.SP
+will make an image with two different labeled kernels and one
+unlabeled set of the other binaries.
+.RE
+.PP
+.B \-(e)x(tract)
+.I image
+.RS
+Extract the binaries from
+.I image
+under the names stored in the image.  (The name includes the optional label.)
+.RE
+.PP
+.B \-d(evice)
+.I device bootblock boot
+.RI [[ label :] image
+\&...]
+.RS
+Installs
+.I bootblock
+in the boot sector of
+.I device
+together with the disk addresses to
+.IR boot .
+These disk addresses are needed to load
+.I boot
+from the file system at boot time.  The argument
+.I boot
+is first searched in the file system on
+.IR device .
+If it is not found then it is read as a normal file and added at the end of
+the file system.  The file system should be smaller than the device it is on
+to allow this.  Any extra images are also added to the end as described
+under
+.BR \-boot .
+(Make sure you understand all this.)
+.SP
+The device need not be mounted when
+.B installboot
+is run, nor does it matter if it is.
+.SP
+.B Installboot
+needs to be run again if
+.I boot
+is rewritten, because it will then occupy a new place on the disk.
+.SP
+Old boot parameters are kept if there are no images added.
+.RE
+.PP
+.B \-b(oot)
+.I device bootblock boot
+.RI [ label :] image
+\&...
+.RS
+This option fills a blank floppy in
+.I device
+with boot code and kernel images.  This "boot disk" does not have a root
+file system, only the Boot Monitor and MINIX 3 kernels.  The boot parameters
+sector is filled with code that enables menu options for selecting an
+image.  After loading an image, the Monitor will ask you to insert a root
+file system diskette before starting MINIX 3.
+.SP
+The labels used on the images should match those on the executables used
+inside the image.  You can put a comma separated list of labels on an image
+for each label used within the image.  For the image created earlier one
+would create a boot floppy like this:
+.SP
+.RS
+.nf
+.BI "installboot \-b /dev/fd0 bootblock boot" " AT,XT:image"
+.fi
+.RE
+.SP
+If a label-list is omitted on an image, then that image will be selected by
+default.  (Like in the normal one image, no labels case.)
+.SP
+Note that
+.B \-device
+and
+.B \-boot
+together allow you to make a boot floppy with or without a root file system.
+With the boot code in the file system, attached to the end of it, or after
+the boot block.  And with one or more kernel images in the file system or
+at the end of the device.  Somewhat confusing.
+.RE
+.PP
+.B \-m(aster)
+.I device masterboot
+.RI [ keys " [" logical ]]
+.RS
+This option installs the
+.I masterboot
+program into the boot sector of the given device.  If another device is
+given instead of
+.I masterboot
+then its bootstrap code is copied to
+.IR device .
+The master bootstrap on a hard disk boots the active partition on that disk
+at boot time.  The MS-DOS fdisk command normally puts a master bootstrap on
+the hard disk.  MINIX 3 has two bootstraps that can be used as a master
+bootstrap,
+.B masterboot
+and
+.BR jumpboot.
+.SP
+.B Masterboot
+is a fairly normal master bootstrap that works as follows:
+.RS
+.SP
+If installed on a hard disk then it will load the bootstrap of the active
+partition and run it.
+.B Masterboot
+can be put in the first sector of a hard disk to boot the active partition,
+or in the first sector of a MINIX 3 partition to boot the active subpartition.
+.SP
+If installed on a MINIX 3 floppy then it will try to boot the next floppy or
+the first hard disk.  Ideal for floppies with just data on it, they will no
+longer obstruct the boot process if left in the drive.  Also a very useful
+trick to boot from floppy drive 1.
+.RE
+.SP
+The other bootstrap named
+.B jumpboot
+is used for the weird cases:
+.SP
+.RS
+If your default operating system is installed on another disk then
+.B jumpboot
+can be installed on the first disk and instructed to boot the disk,
+partition or subpartition that must be booted by default.
+.SP
+If one of your operating systems insists on being active when booted then use
+.B jumpboot
+to ignore the active flag and boot your preferred O.S. instead.  The Boot
+Monitor's "\fBboot\ \(**\fP" trick to activate the partition to boot is
+useful here.
+.SP
+To boot a logical partition within an extended partition.  Note that you can
+put
+.B jumpboot
+in the first sector of the extended partition in this case, with the
+extended partition marked active.
+.SP
+If you hold down the ALT key while
+.B jumpboot
+is being executed, then you can type the disk, partition or subpartition
+you want to boot as one to three digits followed by typing ENTER.
+.RE
+.SP
+.B Jumpboot
+can be programmed to boot a certain partition with the
+.I keys
+argument and optionally also the
+.I logical
+argument.
+.I Keys
+are one to three digits naming the disk, partition or subpartition.  If the
+device to boot is
+.BR /dev/c0d1p3s0 ,
+then
+.I keys
+is
+.BR 130 .
+These are the same three digits you can type manually if you hold down ALT
+at boot.  To program
+.B jumpboot
+to boot a logical partition within an extended partition, let
+.I keys
+be just a disk number, and specify
+.I logical
+as the name of the logical partition on that disk that is to be booted.
+(Actually
+.I logical
+can be any device name, but this form should be avoided because it offers
+less checking to see if the device is still there after a disk
+rearrangement.)
+.SP
+A backup copy of the current master bootstrap (including the partition
+table) can be made with:
+.RS
+.SP
+dd if=\fIdevice\fP of=\fIbackup-file\fP count=1
+.SP
+.RE
+A simple 'cp \fIbackup-file\fP \fIdevice\fP' will put it back.  You can
+also use
+.B fdisk /mbr
+under MS-DOS 5.0 (or newer) to restore the master bootstrap.
+.RE
+.RE
+.SH FILES
+.TP 25
+.B /usr/mdec/bootblock
+MINIX 3 bootstrap for the Minix root device.  To be placed in the boot sector.
+.TP
+.B /usr/mdec/boot
+MINIX 3 Boot Monitor.  Can usually be found in the root directory of a bootable
+device.
+.TP
+.B /usr/mdec/masterboot
+Master bootstrap.  Can be placed in the first sector of a disk to select the
+active partition.  In a MINIX 3 primary partition it selects the active
+subpartition.
+.TP
+.B /usr/mdec/jumpboot
+Special "boot this" bootstrap.
+.SH "SEE ALSO"
+.BR part (8),
+.BR monitor (8).
+.SH DIAGNOSTICS
+.I File
+is not an executable
+.RS
+What you think is boot code or part of the kernel isn't.
+.RE
+.SP
+.I Program
+will crash, text/data segment larger then 64K
+.RS
+One of the 16-bit programs added to an image has a text or data segment
+that is larger than 64K.  You probably enabled too many drivers, or
+configured too many buffers.
+.RE
+.SP
+.I File
+can't be attached to
+.I device
+.RS
+You are trying to put the boot monitor or an image after a file system, but
+there is no or not enough space.  Did you specify the full path of the
+monitor instead of just "boot"?
+.RE
+.SP
+.I Device
+is not a MINIX 3 file system
+.RS
+You are using
+.B \-device
+on a device that doesn't contain a file system.  Maybe you specified the
+wrong device, maybe you should make a file system, or maybe you should use
+.BR \-boot .
+.RE
+.SP
+.I Device
+contains a file system
+.RS
+You are about to destroy a file system with
+.BR \-boot .
+Maybe you meant to use
+.BR \-device ?
+You have 10 seconds to make up your mind...
+.RE
+.SP
+.I File
+is too big
+.RS
+Several types of messages like these will tell you that
+.I file
+can't be installed in a boot sector, or that there is no room to add some
+parameters, etc.  Is
+.I file
+really a bootstrap?
+.RE
+.SS "Bootstrap errors"
+Read error
+.RS
+A read error trying to get the next bit of boot code.  You may even get the
+BIOS error code in hex.  Either the device has a bad block, or jumpboot is
+told to read a nonexistent disk.
+.RE
+.SP
+No active partition
+.RS
+None of the partitions in a partition table is marked active.
+.RE
+.SP
+Not bootable
+.RS
+Partition does not exist (jumpboot), or it's bootstrap isn't executable.
+.RE
+.SH NOTES
+The MINIX 3 bootstraps can boot beyond the 8G disk size limit if the BIOS
+supports the IBM/MS INT 13 Extensions.  Alas only Minix-vmd can make use of
+this, standard MINIX 3 has a 4G disk size limit.
+.SH BUGS
+It has four more options than the SunOS installboot program it is modeled
+after.
+.PP
+The bootblock code has been crunched to such ugliness that you can use it
+to scare little kids out of your garden.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+.\"
+.\" $PchId: installboot.8,v 1.7 2000/08/13 22:09:31 philip Exp $
Index: /trunk/minix/man/man8/intr.8
===================================================================
--- /trunk/minix/man/man8/intr.8	(revision 9)
+++ /trunk/minix/man/man8/intr.8	(revision 9)
@@ -0,0 +1,71 @@
+.TH INTR 8
+.SH NAME
+intr \- run a command with interrupts enabled
+.SH SYNOPSIS
+.B intr
+.RB [ \-d ]
+.RB [ \-t
+.IR seconds ]
+.I command
+.RI [arg "...]"
+.SH DESCRIPTION
+.B Intr
+executes a command with keyboard interrupts enabled, and standard input,
+output and error redirected to the terminal or the console.  It may also
+be used for the opposite: to detach a process from the terminal.
+.PP
+There are three situations where intr may be used:  From a process that has
+no controlling tty, like the shell running
+.B /etc/rc
+at boot time, from a script that runs in the background, or by the System
+Administrator to restart a daemon.
+.PP
+In the first case
+.B intr
+will use
+.B /dev/console
+as a controlling tty and as standard input, output and error.  In the
+second case
+.B intr
+will use
+.B /dev/tty
+to connect the command to the controlling tty.  In the third case the
+process will be removed from the process group, and will have I/O redirected
+to
+.B /dev/null
+as input, and
+.B /dev/log
+for output.
+.SH OPTIONS
+.TP
+.B \-d
+Daemonize a process instead of bringing it to the foreground.  Don't forget
+to use '&' to make the shell not wait for the process, because you won't be
+able to kill it with the interrupt key.
+.TP
+.BI \-t " seconds"
+Schedule an alarm to kill the process in the given number of seconds.
+Use it for a process that may wait indefinitely for a service that may
+not be available.
+.SH FILES
+.TP 20
+.B /dev/console
+Main computer console.
+.TP
+.B /dev/log
+Message logging device.
+.TP
+.B /dev/tty
+Name for the controlling tty.
+.SH "SEE ALSO"
+.BR boot (8),
+.BR tty (4),
+.BR setsid (2),
+.BR alarm (2).
+.SH BUGS
+Maybe
+.B intr \-d
+should fork to daemonize a process, but the author likes it if the process
+stays in the jobs list of his shell.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/irdpd.8
===================================================================
--- /trunk/minix/man/man8/irdpd.8	(revision 9)
+++ /trunk/minix/man/man8/irdpd.8	(revision 9)
@@ -0,0 +1,74 @@
+.TH IRDPD 8
+.SH NAME
+irdpd \- internet router discovery protocol daemon
+.SH SYNOPSIS
+.B irdpd
+.RB [ \-bd ]
+.RB [ \-U
+.IR udp-device ]
+.RB [ \-I
+.IR ip-device ]
+.RB [ \-o
+.IR priority-offset ]
+.SH DESCRIPTION
+.B Irdpd
+looks for routers.  This should be a simple task, but some routers are hard
+to find because they do not implement the router discovery protocol.  This
+daemon collects information that routers do send out and makes it available.
+.PP
+At startup
+.B irdpd
+sends out several router solicitation broadcasts.  A good router should
+respond to this with a router advertisement.
+.PP
+If a router advertisement arrives then no more solicitations are sent.  The
+TCP/IP server has filled its routing table with the info from the
+advertisement, so it now has at least one router.  If the advertisement is
+sent by a genuine router (the sender is in the table) then the
+.B irdpd
+daemon goes dormant for the time the advert is valid.  Routers send new
+adverts periodically, keeping the daemon silent.
+.PP
+Otherwise
+.B irdpd
+will listen for RIP (Router Information Protocol) packets.  These packets
+are sent between routers to exchange routing information.
+.B Irdpd
+uses this information to build a routing table.
+.PP
+Every now and then a router advertisement is sent to the local host to give
+it router information build from the RIP packets.
+.SH OPTIONS
+.TP
+.B \-b
+Broadcast advertisements instead of sending them to the local host only.
+This may be used to keep (non-Minix) hosts alive on a net without adverts.
+.TP
+.B \-d
+Debug mode, tell where info is coming from and where it is sent.  Debugging
+can also be turned on at runtime by sending signal
+.B SIGUSR1
+or turned off with
+.BR SIGUSR2 .
+.TP
+.BI \-o " priority-offset
+Offset used to make the gateway's preferences collected from RIP packets look
+worse than those found in genuine router adverts.  By default
+.BR -1024 .
+.SH "SEE ALSO"
+.BR inet (8),
+.BR boot (8),
+.BR dhcpd (8),
+.BR inetd (8),
+.BR nonamed (8).
+.SH BUGS
+This daemon has gone out of favour thanks to
+.BR dhcpd ,
+that also does router solicitations among other things.
+.PP
+Under standard MINIX 3 this daemon can't listen to both IRDP and RIP
+at the same time, so it starts out with IRDP.  It switches over to RIP
+if it can't find a router, or if it threatens to lose its router.  It
+does not switch back.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/mkdist.8
===================================================================
--- /trunk/minix/man/man8/mkdist.8	(revision 9)
+++ /trunk/minix/man/man8/mkdist.8	(revision 9)
@@ -0,0 +1,30 @@
+.TH MKDIST 8
+.SH NAME
+mkdist \- make a MINIX 3 distribution
+.SH SYNOPSIS
+.B mkdist
+.SH DESCRIPTION
+.B Mkdist
+makes a MINIX 3 distribution on floppies.  Run the command as
+.B root
+and follow the instructions.  It will make one or two bootable installation
+floppies and a compressed tar file of
+.B /usr
+on several floppies using
+.BR vol (1).
+.PP
+The result can be installed on another system as described in
+.BR usage (8),
+except that all of
+.B /usr
+is saved on one set of floppies instead of being nicely split in binary
+and source packages.
+.SH "SEE ALSO"
+.BR tar (1),
+.BR compress (1),
+.BR vol (1),
+.BR usage (8).
+.SH NOTES
+Also very useful for making backups.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/mknod.8
===================================================================
--- /trunk/minix/man/man8/mknod.8	(revision 9)
+++ /trunk/minix/man/man8/mknod.8	(revision 9)
@@ -0,0 +1,33 @@
+.TH MKNOD 8
+.SH NAME
+mknod \- create a special file
+.SH SYNOPSIS
+\fBmknod \fIfile\fR [\fBb\fR] [\fBc\fR] \fImajor \fIminor\fR
+.br
+\fBmknod \fIfile\fR \fBp\fR\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "mknod /dev/plotter c 7 0" "Create special file for a plotter"
+.EX "mknod /dev/fd3 b 2 3" "Create a device for diskette drive 3"
+.EX "mknod /tmp/stream p" "Create a named pipe"
+.SH DESCRIPTION
+.PP
+.I Mknod
+creates a special file named
+.I file ,
+with the indicated major and minor device numbers.
+The second argument specifies a block special, a character special, or a
+named pipe.  Named pipes do not have device numbers so they are omitted.
+.SH "SEE ALSO"
+.BR mkfifo (1),
+.BR mknod (2).
Index: /trunk/minix/man/man8/monitor.8
===================================================================
--- /trunk/minix/man/man8/monitor.8	(revision 9)
+++ /trunk/minix/man/man8/monitor.8	(revision 9)
@@ -0,0 +1,606 @@
+.TH MONITOR 8
+.SH NAME
+monitor, edparams \- load and start MINIX 3, modify boot parameters
+.SH SYNOPSIS
+.B /boot
+.br
+.B edparams
+.I device
+.RI [ command " ...]"
+.br
+.B boot.com
+.I virdisk
+.RI [ command " ...]"
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+This text describes the Boot Monitor, a boot time interactive program designed
+not only to load and start MINIX 3, its most important task, but to also
+provide an interface to configure MINIX 3 and to boot other operating systems.
+.PP
+The monitor is controlled with an environment that is modeled after the
+Bourne shell.  This environment is filled at startup with default values
+that depend on the machine the monitor is running on and the environment
+settings saved into the boot parameters sector (the second sector on a
+device).  When the environment is loaded, the monitor executes the function
+named
+.BR main ,
+which by default starts a simple menu.
+.PP
+The environment can be manipulated at boot time from the monitor prompt,
+but may also be edited using
+.B edparams
+on a given device.
+.B Edparams
+simulates the monitor as much as it can, echoing commands it can't execute
+between brackets.  It can also be used in Makefiles and scripts by giving
+it commands as arguments.
+.PP
+The DOS version of the monitor, usually named
+.B boot.com
+under DOS, boots MINIX 3 from a "DOS virtual disk".
+.B Boot.com
+is a simple COM program that interprets a DOS
+file as a disk, loads a MINIX 3 kernel from the active partition in the same
+way as the BIOS based monitor, and executes it to start MINIX 3.  All the
+monitor commands function in the same way, except for the
+.B boot
+command, it can only load MINIX 3.  The monitor grabs as much free memory as
+it can for MINIX 3 to work in, as the
+.B memory
+variable shows.  Further details on how to run MINIX 3 under DOS, Windows 95,
+or even Windows NT are written down in
+.BR dosminix (8).
+.SH COMMANDS
+The monitor is best described by the commands you can type to the '>'
+prompt.  This is known as the "monitor mode".  You can enter this mode by
+hitting the Escape key.  These are the monitor commands:
+.PP
+\fIname\fP = [\fBdevice\fP] \fIvalue\fP
+.SP
+.RS
+Set environment variable.
+.br
+Changes the value of
+.I name
+to
+.IR value .
+The optional word
+.B device
+marks
+.I name
+as being subject to device translation.  (See the section on devices.)  These
+(name, value) pairs are passed to the kernel who uses them to configure
+itself.  These variables are passed by default:
+.SP
+.B rootdev
+.RS
+This is the device used as your root device.  It is by default set to
+.BR ram,
+which means that the device specified by
+.B ramimagedev
+will be loaded into the RAM disk and used as root.  If you change this
+variable then a physical device will be used as root, and the RAM disk will
+be uninitialized and have the size specified by
+.BR ramsize .
+.RE
+.SP
+.B ramimagedev
+.RS
+Describes the device to use to initialize the RAM disk if
+.B rootdev
+is set to
+.BR ram .
+It's by default set to
+.BR bootdev ,
+a special name for the device the monitor booted from.
+.RE
+.SP
+.B ramsize
+.RS
+The size of the RAM disk.  If the RAM disk is used for the root file system
+then the root file system is stretched out to
+.B ramsize
+if possible.
+.RE
+.SP
+.B processor
+.RS
+Set by default to
+.BR 86 ,
+.BR 186 ,
+.BR 286 ,
+.BR 386 ,
+.BR 486 ", ..."
+depending on the hardware you have.  You can set it to a smaller value to
+test your kernel in a more limited environment.
+.RE
+.SP
+.B bus
+.RS
+The type of system bus, either
+.BR xt ,
+.BR at
+or
+.BR mca .
+This answers basic questions like: "How many interrupt controllers and how
+to initialize?"  Or: "Does the keyboard have LEDs?"
+.RE
+.SP
+.B memory
+.RS
+List of memory free for use by MINIX 3.  It is a comma separated list of
+.IR base:size
+pairs denoting the byte offsets and sizes of free memory in hexadecimal.
+.B "800:925E0,100000:F00000"
+is a typical example of about 585K starting at 2K, and 15M starting at 1M.
+(The first 2K are BIOS parameters and the 53K under the 640K boundary is
+the monitor itself.)  The very last number you can play with if you know
+what you are doing.  Either increase it if the monitor has it wrong, or
+decrease it to test if MINIX 3 still runs with less memory then normal.
+.RE
+.SP
+.B video
+.RS
+Describes capabilities of the VDU:
+.BR mda ,
+.BR cga ,
+.B ega
+or
+.BR vga .
+.RE
+.SP
+.B chrome
+.RS
+Either
+.B color
+or
+.BR mono .
+.RE
+.SP
+.B c0
+.RS
+By default
+.B at
+(AT compatibles),
+.B bios
+(XT or PS/2), or
+.B dosfile
+(running under DOS).
+The
+.B c0
+variable binds a driver to the first controller, i.e. the
+.B /dev/c0*
+devices.  The monitor sets
+.B c0
+to a suitable default, so that most machines can find their disk.
+.RE
+.SP
+.B console
+.RS
+If set to a hexadecimal value it makes the monitor set the BIOS video mode to
+this value when MINIX 3 is started.
+This allows the use of video modes with more rows or colums than the
+standard 80x25 mode.  You can use any text mode in the 00-FF range, and VESA
+extended modes in the 100-FFF range.  Most text modes use a 9x16 font with
+400 scanlines on screen, so you see 400/16 = 25 lines.  The text mode can be
+modified by adding special flags to the console setting.  Add
+2000 to switch to 480 scan lines, adding 20% more lines to the screen.  Add
+4000 to select a 9x14 font, so 28 or 34 lines are shown.  Add 8000 instead
+to select an 8x8 font showing 50 or 60 lines.  Each setting has drawbacks.
+Using 480 scanlines implies a 60 Hz refresh, so the screen may flicker.  The
+8x8 font looks squashed.  More letters on screen require more memory, so there
+is less for virtual consoles.  Interesting modes to try are 4003 (80x28),
+2003 (80x30), 6003 (80x34), 8003 (80x50), A003 (80x60), 109 (132x25),
+10A (132x43), 10B (132x50), 10C (132x60).  The 109 VESA mode is often
+available, and can be modified like mode 3.  Use mode 7 instead of 3 for
+monochrome.  Which modes and flags work can only be found out by experiment.
+More parameters may follow the mode number that are of interest
+to the console driver, see
+.BR boot (8).
+.RE
+.SP
+.B dosfile-d0
+.RS
+Set by the DOS version of the monitor to the name of the virtual disk, i.e.
+the
+.I virdisk
+argument as shown above.  The "dosfile" driver
+will use this as the name of the file to use as a disk.
+.RE
+.SP
+Two variables are only used by the monitor, even though they are passed to the
+kernel too:
+.SP
+.B image
+.RS
+The name of the file containing the kernel image, by default
+.BR minix .
+If it refers to a directory however then the newest file inside the
+directory is chosen to be the kernel image.  The names inside
+.B /minix/
+are best set to the MINIX 3 version you are using, which looks good when the
+monitor prints its name.  Rules for pretty printing image names:
+.RS
+.SP
+A '/' or '_' is changed to a space.
+.SP
+The first letter is changed from lowercase to uppercase.
+.SP
+An 'r' if followed by a digit changes to " revision ".
+.RE
+.RE
+.SP
+.B label
+.RS
+If set then only processes marked with this label or without a label are
+loaded from the image.
+.RE
+.SP
+.B Installboot \-boot
+will create functions to select images and labels.  These functions will set
+.B label
+and
+.B image
+and echo what you selected.  The two numbers separated by a colon used as an
+image name tell the starting sector and sector count of the image on disk.
+.RE
+.SP
+\fIname\fP() \fIcommand\fP
+.RS
+Define function.
+.br
+Functions may be used to bundle a set of commands, so that you can easily
+boot MINIX 3 with a different set of parameters then normal.  E.g.
+.SP
+.RS
+ram() { rootdev=ram; boot }
+.RE
+.SP
+will allow you to run MINIX 3 with the root device on RAM for a change, if you
+normally use a real device as root.  There are three predefined functions,
+.BR leader ,
+with default value an
+.B echo
+command that shows the monitor's startup banner,
+.BR main ,
+with default value
+.BR menu ,
+and
+.BR trailer ,
+with default value a command that clears the screen.
+The monitor executes
+.B leader;main
+at startup to show the banner message and a menu.  The
+.B trailer
+function is executed just before MINIX 3 is started.  These three functions can
+be redefined as you please.
+.RE
+.SP
+\fIname\fP(\fIkey\fP) \fIcommand\fP
+.RS
+Define kernel selecting function.
+.br
+The menu command uses functions like these to add menu entries to select
+a different kernel from a boot disk.
+.B Installboot \-boot
+produces these functions when the images are labeled.  The label
+.B AT
+would give:
+.SP
+.RS
+AT(a) {label=AT;image=42:626;echo AT kernel selected;menu}
+.RE
+.SP
+With the menu option:
+.SP
+.RS
+a	Select AT kernel
+.RE
+.SP
+Typing
+.B a
+will then execute the
+.B AT
+function above.
+.RE
+.SP
+\fIname\fP(\fIkey\fP,\fItext\fP) \fIcommand\fP
+.RS
+User defined menu option.
+.br
+This variant may be used to make any menu entry you like:
+.SP
+.RS
+dos(d,Boot MS-DOS) boot d0p0
+.RE
+.SP
+.I Text
+may be anything, even parentheses if they match.
+.RE
+.SP
+.I name
+.RS
+Call function.
+.br
+If
+.I name
+is a user defined function then its value is expanded and executed in place of
+.IR name .
+Try a recursive one like 'rec() {rec;xx}' one day.  You can see the monitor
+run out of space with nice messages about using
+.BR chmem (1)
+to increase it's heap.
+.RE
+.SP
+\fBboot\fP [\fB\-\fP\fIopts\fP]
+.br
+\fBboot\fP \fIdevice\fP
+.RS
+Boot MINIX 3 or another O.S.
+.br
+Without an argument,
+.B boot
+will load and execute the MINIX 3 image named by the
+.B image
+variable.  With options the variable
+.B bootopts
+is first set to
+.BI \- opts
+before MINIX 3 is started, and unset when Minix returns.  With a
+.I device
+argument,
+.B boot
+loads the boot sector of
+.I device
+into memory and jumps to it, starting another operating system.  You would
+normally use partitions on the first hard disk for this command (d0p[0\-3]),
+using d0 will also work (choosing the active partition).  One can also boot
+devices on the second hard disk (d1, d1p[0\-3]) if the bootstrap writer did
+not hardwire the disk number to disk 0.
+.br
+Some Operating Systems can only be booted from the active partition, if
+you use a '*', e.g.
+.BR "boot *d0p2" ,
+then partition 2 is first made active.  You'll then need to use
+.SP
+.RS
+.BI "installboot \-m /dev/c0d0 /usr/mdec/jumpboot" " keys"
+.RE
+.SP
+with
+.I keys
+chosen so that MINIX 3 is booted at startup.  (See
+.BR installboot (8).)
+.RE
+.SP
+\fBctty\fP \fIn\fP
+.RS
+Copies output to and takes input from serial line
+.I n
+(0-3) at 9600 baud, 8 bits, no parity.
+This allows you to control a MINIX 3 system remotely through an RS-232
+connection.
+.RE
+.SP
+\fBdelay\fP [\fImsec\fP]
+.RS
+Delay (500 msec default).
+.br
+Fast booting speed was one of the objectives when this program was created,
+so a hard disk boot usually takes only a fraction of a second.  If you need
+some time (to hit Escape, or stare at the numbers) you can use
+.B delay
+to make the monitor pause for a specified number of milliseconds.
+.RE
+.SP
+\fBecho\fP \fIword\fP ...
+.RS
+Print these words.
+.br
+Used to display messages, like the startup banner.  Echo normally prints
+the words with spaces in between and a newline at the end.  Echo understands
+special '\e' escape sequences as follows:
+.RS
+.SP
+\e	(At the end) Don't print a newline.
+.br
+\en	Print a newline.
+.br
+\ev	Print the monitor's version numbers.
+.br
+\ec	Clear the screen.
+.br
+\ew	Wait until a RETURN is typed
+.br
+\e\e	Print a backslash.
+.RE
+.RE
+.SP
+\fBls\fP [\fIdirectory\fP]
+.RS
+List contents of a directory.
+.br
+Useful when looking for kernel images.
+.RE
+.SP
+.B menu
+.RS
+Menu driven startup.
+.br
+This command allows you to execute functions defined with a
+.IR key .
+If no menu functions have been defined then
+.B menu
+will use this one hidden built-in function:
+.SP
+.RS
+*(=,Start Minix) boot
+.SP
+.RE
+Kernel selecting functions only add new options to this set, but if you
+define a two argument function yourself then the above one is no longer
+shown, allowing you to customize the menu completely.  Your first
+function definition should therefore be one that starts MINIX 3.
+.SP
+Menu entries are shown in the same order as
+.B set
+shows them.  If you don't like the order then you have to unset the
+functions and retype them in the proper order.
+.SP
+If you type a key then a scheduled trap is killed and the appropriate menu
+function is executed.  If you need more time to choose then hit the
+spacebar.  A key not on the menu also kills a trap, but does nothing more.
+.RE
+.SP
+.B save
+.RS
+Save environment.
+.br
+This will save all the environment variables and functions with nondefault
+values to the parameter sector (the second sector on the boot device), so
+they are automatically set the next time you boot the monitor.
+.RE
+.SP
+.B set
+.RS
+Show environment.
+.br
+Show the current values of the environment variables and functions.  Default
+values are shown between parentheses to distinguish them from values that
+were explicitly set.
+.RE
+.SP
+\fBtrap\fP \fImsec\fP \fIfunction\fP
+.RS
+Schedule function.
+.br
+Schedules a function to be executed after
+.I msec
+milliseconds.  Only the monitor mode cannot be interrupted, a scheduled trap
+is killed when the prompt is printed.  Example:
+.SP
+.RS
+main() {trap 10000 boot; menu}
+.RE
+.SP
+This gives you 10 seconds to choose a menu option before MINIX 3 is booted.
+.RE
+.SP
+\fBunset\fP \fIname\fP ...
+.RS
+Unset environment variables.
+.br
+Removes the named variables and functions from the environment, and sets
+special variables back to their default values.  This is also the only way
+to remove the "device name translation" property from a variable.
+.RE
+.SP
+\fBexit\fP
+.RS
+Exit the monitor.
+.br
+Reboot the machine, exit to MINIX 3 or exit to DOS as appropriate.
+.RE
+.SP
+\fBoff\fP
+.RS
+Turn the PC off.
+.br
+If the PC supports power management then turn it off, otherwise
+print some error messages and do nothing.
+.RE
+.SP
+\fB{\fP \fIcommand\fP; ... \fB}\fP
+.RS
+Bundle commands.
+.br
+Treat a number of commands as a single command.  Used for function
+definitions when a function body must contain more than one command.
+.RE
+.SH DEVICES
+The MINIX 3 kernel can't do anything with device names, so they have to be
+translated to device numbers before they are passed to the kernel.  This
+number is found under the st_rdev field (see
+.BR stat (2))
+of the file on the boot file system.  The monitor will look for the device
+file with the working directory set to '/dev'.  If it can't find the device
+name then it will translate names like 'ram', 'fd1', 'c0d1p0', 'c1d0p2s0',
+and even the obsolete 'hd2a' to what it itself thinks the numbers should be.
+.PP
+The special name
+.B bootdev
+is translated to the name of the device booted from, like 'fd0',
+or 'c0d0p1s0', and then searched for in /dev.
+.B Bootdev
+can only be translated to a device for the first controller, and only if
+the disks on that controller are numbered without "gaps".  (The master
+device on the second IDE channel is always d2 on MINIX 3.  The BIOS will
+call it disk 0, 1, or 2 depending on the number of disks on the first
+IDE channel.)
+.SP
+Controller numbers are meaningless to the BIOS, so everything is assumed to
+be attached to controller 0.  You can omit
+.B c0
+for device names, and it is best to always omit
+.B c0
+for the
+.B boot
+command, and to always use the full name for variables passed to MINIX 3.
+.SH EXTENSIONS
+A few extensions have been made to this program for kernel hackers.  They
+may be triggered by setting bits in the flags word in the kernel startup
+code (the mpx file.)  The flag bits are:
+.TP 10
+0x0001
+Call kernel in 386 mode.
+.TP
+0x0002
+Do not make space for the bss areas of processes other than the kernel.
+.TP
+0x0004
+Use the stack size set by
+.BR chmem (1).
+.TP
+0x0008
+Load MM, FS, etc. into extended memory.
+.TP
+0x0010
+No need to patch process sizes into the kernel.
+.TP
+0x0020
+The kernel can return to the monitor on halt or reboot.
+.TP
+0x0040
+Offer generic BIOS support instead of just INT 13 (disk I/O).
+.TP
+0x0080
+Pass memory lists for free and used memory (processes).
+.TP
+0x0100
+Kernel returns monitor code on shutdown in boot parameters array.
+.SH "SEE ALSO"
+.BR controller (4),
+.BR installboot (8),
+.BR usage (8),
+.BR boot (8),
+.BR dosminix (8).
+.SH BUGS
+The
+.B delay
+command will hang forever on the original IBM PC (not the XT!).  Not that it
+matters, as everything takes forever on that box.
+.PP
+By redefining
+.B leader
+one can easily hide the identity of this program.
+.SH ACKNOWLEDGMENTS
+Earl Chew, for the inspiration his ShoeLace package provided, unless he wants
+to file a "look and feel" suit against me, then I will say I modeled it after
+the Sun ROM boot monitor, which is also true.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+.\"
+.\" $PchId: monitor.8,v 1.11 2002/02/27 19:36:34 philip Exp $
Index: /trunk/minix/man/man8/nonamed.8
===================================================================
--- /trunk/minix/man/man8/nonamed.8	(revision 9)
+++ /trunk/minix/man/man8/nonamed.8	(revision 9)
@@ -0,0 +1,306 @@
+.\" These numbers should match those in nonamed.c:
+.ds ST "two seconds"
+.ds MT "four seconds"
+.ds LT "five minutes"
+.ds HT "one hour"
+.ds NI "256"
+.TH NONAMED 8
+.SH NAME
+nonamed \- not a name daemon, but acts like one
+.SH SYNOPSIS
+.B nonamed
+.RB [ \-qs ]
+.RB [ \-d [\fIlevel\fP]]
+.RB [ \-p
+.IR port ]
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Nonamed
+is not a name daemon.  It can answer simple queries from
+.BR /etc/hosts ,
+but anything else is relayed to a real name daemon.
+.B Nonamed
+maintaines a small cache of replies it has seen from a name daemon, and will
+use this cache to minimize traffic if the machine is permanently connected
+to the Internet, or to answer requests if the machine is often disconnected
+from the Internet, i.e. a computer at home.
+.PP
+On startup
+.B nonamed
+sends a simple query to each of its name servers to see if one is up.  This
+is repeated every \*(LT in an "at home" situation, or when necessary if the
+current name daemon doesn't respond.  The first name server to answer is
+used as the current name server to answer queries.
+.PP
+If no name servers are found in the DHCP data or
+.BR /etc/hosts
+then only the hosts file is used to answer queries, and any query for a name
+not in that file gets a failure response.
+.PP
+.B Nonamed
+accepts both UDP and TCP queries under Minix-vmd.  Under standard MINIX 3
+only UDP queries are accepted.  \*(NI relayed UDP queries can be outstanding
+before it forgets where the first one came from.
+.PP
+Using the hosts file,
+.B nonamed
+can answer simple DNS queries to translate a host name to an IP address, or
+an IP address to a host name.  Suppose
+.B /etc/hosts
+looks like this:
+.PP
+.RS
+.ta +15n
+.nf
+10.0.0.1	flotsam.cs.vu.nl\0www
+10.0.0.2	jetsam.cs.vu.nl
+.fi
+.RE
+.PP
+Then queries for the host names listed can be answered with the IP addresses
+to the left of them.  An alias like "www" above is seen as a CNAME for the
+first host name on the line, in the same domain as the first host name if
+unqualified (no dots).  A reverse lookup for an IP address on the left is
+answered by the first host name on the right.  If more than one match is
+possible then all matches are put in the answer, so all IP addresses of
+multihomed hosts can be listed by multiple entries in the hosts file.
+.PP
+Requests for names like "flotsam.cs.vu.nl.cs.vu.nl" that are often generated
+on a domain search for an already fully qualified domain name
+are recognized and made to fail.  This kludge avoids a lot of unnecessary
+requests to possibly unreachable name servers and client timeouts.
+.PP
+The name "localhost" in any domain is given the IP address 127.0.0.1.
+.PP
+.B Nonamed
+employs several timeouts for efficient operation:
+.PP
+If no UDP reply is seen in \*(MT then a new search is started for a name
+server in the hope of finding one that does work.
+A failing TCP connection will also invoke a search, the
+TCP connection is then made to the new name server.  A client using UDP will
+retry eventually, a client using TCP will notice nothing but a short delay.
+If a TCP connection fails after 5 tries then an answer is sought in the
+hosts file, and failing that the connection is closed.
+.PP
+Any TCP operation is given \*(LT to show any action before the connection is
+aborted.
+.PP
+UDP replies from a name server are put in a cache of by default 8 (16-bit
+system) or 16 kilobytes (32-bit system).  New queries are
+first sought in the cache, and if found answered from the cache.  An entry
+in the cache is expired when the resource record with the smallest TTL (time
+to live) expires, unless its expire time is artificially extended by the
+"%stale" parameter (see below).  An answer from the cache has all TTLs
+appropriately lowered, and the AA bit ("answer authoritive") is cleared.
+Any request answered by stale data is refreshed as soon as
+.B nonamed
+notices that one of the external name daemons is reachable.
+.PP
+Data is only cached if it is has "no error" result code, or a "no such
+domain" result code with a SOA record in the name server section, and all
+records have a nonzero TTL.  The %stale parameter has no effect on the
+decision to cache a result.
+.PP
+The cache is rewritten to the cache file \*(LT after a new entry has been
+added.  Mere changes to the order in the cache don't cause a rewrite.
+.SS Configuration through /etc/hosts
+The real name servers, stale data extension, and cache size can be
+configured by special entries in the hosts file.  For example:
+.PP
+.RS
+.ta +\w'172.16.24.3'u+2m +\w'%nameserver'u+2m
+.nf
+86400	%ttl	# Answers from this file get this TTL
+2419200	%stale	# Stale data may linger on for 4 weeks
+32768	%memory	# 32k cache size
+10.0.0.1	%nameserver	# flotsam
+172.16.24.3	%nameserver	# dns1.example.com
+172.16.24.6	%nameserver	# dns2.example.com
+.SP
+10.0.0.1	flotsam.home.example.com\0www
+10.0.0.2	jetsam.home.example.com
+.fi
+.RE
+.PP
+In this example we have two machines, flotsam and jetsam, that are at home.
+Answers from the hosts file get a TTL of one day, by default this is \*(HT.
+Normally there is no connection to the Internet, so any stale data in the
+cache is allowed to linger on for 2419200 seconds (4 weeks) before it is
+finally discarded.  The cache size is set to 32 kilobytes.  The first name
+server is the flotsam.  On the flotsam itself this entry is ignored, but the
+jetsam will now run its requests through flotsam if possible.  This means
+that both flotsam and jetsam use the cache of the flotsam.  The other
+nameserver entries are external name servers of the Internet provider.
+.PP
+If no nameservers are listed in the hosts file then they are obtained from
+data gathered by DHCP.  This is the preferred situation.
+.PP
+If the hosts file contains a line that says:
+.PP
+.RS
+.BI include " file"
+.RE
+.PP
+Then the current hosts file is closed and the file named is read next.
+.SS "Automatic calling"
+If your connection to the Internet is set up on demand, either in software
+on the machine that has the modem, or by a special box such as an ISDN
+router, then you need to filter the name server probes that
+.B nonamed
+sends out every \*(LT to see if a real name daemon is reachable.  These
+probes need to be recognized as packets that must not trigger a call, and
+that must not keep the line up.  You can either filter all IP packets
+destined for port 53 decimal (the
+.B domain
+port).  This may be a bit too much, the first packet out is often a normal
+DNS request (not a probe), so you may want to do better.  A probe by
+.B nonamed
+is a nonrecursive request for the name servers of the root domain.  You
+can recognize them by looking at the flags, they are all off.  Here is a
+typical probe in hex (twenty octets per line), followed by the names of
+interesting fields, and the octets values you should look for:
+.PP
+.RS
+.nf
+45 00 00 2D C8 19 00 00 1D 11 53 18 AC 10 66 41 AC 10 18 03
+00 35 00 35 00 19 79 93 00 00 00 00 00 01 00 00 00 00 00 00
+00 00 02 00 01
+.SP
+ip ip ip ip ip ip ip ip ip ip ip ip si si si si di di di di
+sp sp dp dp xx xx xx xx id id fl fl qd qd an an ns ns ar ar
+dn ty ty cl cl
+.SP
+45 xx xx xx xx xx xx xx xx 11 xx xx xx xx xx xx xx xx xx xx
+xx xx 00 35 xx xx xx xx xx xx 00 00 xx xx xx xx xx xx xx xx
+xx xx xx xx xx
+.SP
+.fi
+(ip = IP header, si = source IP, di = dest IP, sp = source port, dp = dest
+port, id = DNS ID, fl = DNS flags, qd = query count, an = answer count, ns =
+nameserver count, ar = additional records count, dn = domain (""), ty = type
+(NS), cl = class (IN).)
+.RE
+.PP
+So if a packet has octets 45, 11, 00 35, and 00 00 at the appropriate places
+then don't let it cause a call.  Read the documentation of your software/router
+to find out how to do this.  Hopefully it is possible to view the contents of
+the packet that triggered the last call.  If so you simply let
+.B nonamed
+bring up the line once with a probe.
+.SS "Remote information"
+The program version and name servers it is working with can be obtained with:
+.PP
+.RS
+host \-r \-v \-c chaos \-t txt version.bind. \fIserver\fP
+.RE
+.PP
+.I Server
+is the name or IP address of the host whose name server you want to know
+this of.
+(This call is really an undocumented hack to ask the version numbers of the
+BIND name daemon.  It just had to be implemented for
+.B nonamed
+as well.)
+.PP
+The % variables in the hosts file can be viewed like this:
+.PP
+.RS
+host \-r \-t a %nameserver. \fIserver\fP
+.RE
+.PP
+Don't forget the dot at the end of the name.  %ttl and %stale will be shown
+as a dotted quad, e.g. 0.36.234.0.  The proper value can be computed as 36 *
+65536 + 234 * 256 + 0 = 2419200.
+.SH OPTIONS
+The options are only useful when debugging
+.BR nonamed ,
+although it can be very instructive to watch DNS queries being done.
+.TP
+.BR \-d [\fIlevel\fP]
+Set debugging level to
+.I level
+(by default
+.BR 1 .)
+Debug mode 1 makes
+.B nonamed
+decode and display the DNS queries and replies that it receives, sends and
+relays.  In debug mode 2 it prints tracing information about the internal
+jobs it executes.  In debug mode 3 it core dumps when an error causes it to
+exit.  The debugging level may also be increased by 1 at runtime by sending
+signal
+.B SIGUSR1
+or turned off (set to 0) with
+.BR SIGUSR2 .
+.TP
+.RB [ \-p " \fIport\fP]
+Port to listen on instead of the normal
+.B domain
+port.
+.TP
+.RB [ \-q ]
+Read the cache file with the debug level set to 2, causing its contents to
+be printed, then exit.
+.TP
+.RB [ \-s ]
+Run single: ignore hosts or cache file, only use the DHCP information.  This
+allows another
+.B nonamed
+to be run on a different interface to serve a few programs that run there.
+.SH FILES
+.TP 15n
+/etc/hosts
+Hosts to address translation table and configuration file.
+.TP
+/usr/run/nonamed.pid
+Process ID of the currently running
+.BR nonamed .
+.TP
+/usr/adm/nonamed.cache
+Copy of the cache.  Read when the program starts, written \*(LT after
+something has been added to it, and written when a SIGTERM signal is
+received, which is normally sent at system shutdown.
+.TP
+/usr/adm/dhcp.cache
+Data gathered by the DHCP daemon.  Among lots of other junk it lists name
+servers that we should use.
+.SH "SEE ALSO"
+.BR gethostbyname (3),
+.BR resolver (3),
+.BR hosts (5),
+.BR inet (8),
+.BR boot (8),
+.BR inetd (8),
+.BR dhcpd (8).
+.SP
+.BR RFC-1034
+and
+.BR RFC-1035 .
+.SH NOTES
+Do not use the %stale parameter for a PC that is directly connected to the
+Internet.  You run the risk of getting wrong answers, a risk that is only
+worth taking for a system that is mostly disconnected from the Internet.
+.PP
+You can specify one or more remote name servers in
+.B /etc/resolv.conf
+so that nonamed isn't needed.  This will save memory, but you'll lose
+.BR nonamed 's
+cache and its "offline" tricks.  That's no problem if you can use a
+neighbouring name daemon on another PC at home.
+.PP
+The default cache size seems to be more than enough for normal use, but if
+you do decide to make it larger then don't forget to increase the stack size
+of the program under standard MINIX 3.
+.PP
+Don't let two
+.BR nonamed 's
+forward queries to each other.  They will pingpong a query over the
+network as fast as they can.
+.SH BUGS
+The idea of serving "stale DNS data" will probably make some purists
+violently sick...
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/part.8
===================================================================
--- /trunk/minix/man/man8/part.8	(revision 9)
+++ /trunk/minix/man/man8/part.8	(revision 9)
@@ -0,0 +1,116 @@
+.TH PART 8
+.SH NAME
+part \- partition table editor
+.SH SYNOPSIS
+.B part
+.RI [ device "] ..."
+.SH DESCRIPTION
+.B Part
+is a screen oriented partition table editor.
+.PP
+While editing you will see six lines of numbers, the first line shows the
+device name and its geometry (number of cylinders, heads and sectors), the
+second shows the start and end of the drive or partition you are working on,
+the last four lines show the different partitions or subpartitions.  All
+numbers except those on the second line can be edited.  Question marks are
+showed instead of numbers if the partition table is not loaded yet.  You
+have to select a device and type 'r'.
+.PP
+Editing is a simple matter of moving around with the arrow keys and changing
+the values with + and \- (or PgUp and PgDn), or by typing the desired value.
+The '?' key will give a small list of commands, the '!' key gives advice on
+how to make a new entry.
+.PP
+The spacebar toggles between showing the size of the partition and the last
+sector on the partition.  Useful to check if a partition is adjacent to the
+next.
+.PP
+The 'm' key is "magical", it lets you cycle through a set of interesting
+values for the base or size of a partition.  These values are: Aligned to a
+cylinder, taped to other partitions (inside or outside), or filling out holes.
+.BR "Use this key" !
+.PP
+MINIX 3 subpartition tables or extended partitions may be edited after hitting
+the '>' key.  The number of this partition will be shown after the device
+name on the second row, e.g.
+.BR /dev/hd0:2 .
+MINIX 3 subpartition tables are shown as is, but extended partition bases are
+translated to absolute offsets on the screen to hide the gory details of their
+implementation from the innocent user.  (Hit 'p' if you dare.)  The '<' key
+will bring you back to the enclosing partition table.
+.PP
+With arguments,
+.B part
+will use the given devices or files.  Without arguments,
+.B part
+will use all interesting block devices in
+.B /dev
+sorted by device number and starting with
+.BR /dev/hd0 .
+.PP
+Values that are out of range, overlapping, or otherwise strange are shown in
+reverse video.  Values that may possibly be a problem for operating systems
+other then MINIX 3 are shown in bold characters.
+.PP
+The name of the device is highlighted when it has not been read yet.
+.PP
+Head or sector numbers are highlighted if the partition does not start or
+end at a cylinder boundary.
+.PP
+The base and/or size field is highlighted if they fall outside the device,
+if they are inside some other partition, if the base equals the device's base
+(no room for the boot sector), or if the size is zero.
+.PP
+.B Part
+complies with the good old \s-2UNIX\s+2 tradition of trusting the user.
+It will write any table, no matter how bad.  You have been warned.
+.PP
+By the way, as far as MINIX 3 is concerned there is absolutely no reason to
+make partitions start precisely on a cylinder or track nor does it have to
+be an exact number of cylinders long.  MINIX 3 only looks at the base and size
+of a partition, the geometry of the drive doesn't have to be correct.  Other
+Operating systems can be very picky about partitions that are not aligned.
+Some partition editors may refuse to edit a table, others may even make a
+mess of the table.  The only exception is the first partition, it
+traditionally starts on the first track, not the first cylinder.  All
+editors must understand this.  (Subpartition tables are MINIX 3 specific, so
+there is no reason at all for any alignment.)
+.SS "Extended Partitions"
+Extended partitions are a mess that is only made slightly better by
+.B part
+by translating the base offsets to absolute numbers.  It is better to use DOS
+.B fdisk
+to create them, but if you insist on using
+.B part
+then this is what they should look like:
+.RS
+.sp
+The extended partition entry in the primary partition table must cover the
+whole logical partition space within it.
+.sp
+The area thus created is split in segments, each segment contains a partition
+table in sector 0 and one (just one) logical partition.
+.sp
+The first entry of a segment's partition table describes this logical
+partition: it's partition ID, base and size.
+.sp
+The second entry is an extended partition that describes base and size of
+the next segment (partition table and logical partition).  The last segment's
+partition table is empty, or contains one logical partition.
+.SH "SEE ALSO"
+.BR mkfs (1),
+.BR fd (4),
+.BR hd (4).
+.SH BUGS
+You can have a table read, messed up, and written in no time, be careful.
+.PP
+You can't type head or sector numbers directly.
+.PP
+Sectors are counted from 0 for consistency, but the partition table counts
+from 1 like DOS addresses them.  Most confusing.
+.PP
+You can't write a backup copy to a file, that's what
+.BR dd (1)
+with count=1 is for.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/partition.8
===================================================================
--- /trunk/minix/man/man8/partition.8	(revision 9)
+++ /trunk/minix/man/man8/partition.8	(revision 9)
@@ -0,0 +1,66 @@
+.TH PARTITION 8
+.SH NAME
+partition \- make a partition table
+.SH SYNOPSIS
+.B partition
+.RB [ \-mfn ]
+.I device
+[\fItype\fP:]\fIlength\fP[\fB+*\fP] ...
+.SH DESCRIPTION
+.B Partition
+makes a partition table on
+.I device
+using the types and sizes given.  It may be used in combination with
+.BR repartition (8)
+for automatic installation of MINIX 3.  
+.PP
+You may give up to four \fItype\fP:\fIlength\fP[\fB+*\fP] specifications
+for the partitions.  You may also specify holes before, between, and after
+the partitions.  A hole differs from a partition specification by not having
+a type.
+.PP
+The first hole is by default 1 sector to make space for the primary
+bootstrap and the partition table.  The other holes are 0.
+.PP
+The
+.I type
+field is the type of the partitition in hexadecimal.  The
+.I length
+field is the partition's size in sectors.  The
+.B +
+or
+.B *
+may optionally be added to indicate that the partition must be expanded
+to contain any leftover space on the device or to mark the partition active.
+.PP
+Instead of a length you may use the word
+.B exist
+to indicate that an existing partition of the given type must be kept
+from the old partition table.
+.PP
+Partitions are padded out to cylinder boundaries, except for the first one,
+it starts on track 1.  Some operating systems care about this.  MINIX 3 and
+MS-DOS do not.
+.SH OPTIONS
+.TP
+.B \-m
+MINIX 3 only, no need to pad partitions.  This is the default for subpartition
+tables.
+.TP
+.B \-f
+Force making a partition table even if the device is too small.
+.TP
+.B \-n
+Play-act, don't write the new table, just show what it would look like.
+.SH EXAMPLE
+.B "partition /dev/hd0 01:16384 81:40000 81:2880* 06:20000+"
+.PP
+Partitions disk 0 into an 8 Mb DOS partition, 20 Mb MINIX 3 /usr, 1.44 Mb MINIX 3
+/ (active), and a DOS partition of at least 10 Mb at the end of the disk.
+(06:0+ would have been ok too, it's just a sanity check.)
+.SH "SEE ALSO"
+.BR hd (4),
+.BR part (8),
+.BR repartition (8).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/pr_routes.8
===================================================================
--- /trunk/minix/man/man8/pr_routes.8	(revision 9)
+++ /trunk/minix/man/man8/pr_routes.8	(revision 9)
@@ -0,0 +1,26 @@
+.TH PR_ROUTE 8
+.SH NAME
+pr_routes \- show IP routing.
+.SH SYNOPSIS
+.B pr_routes
+.RB [ \-i 
+.RI "ip device]"
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Pr_routes
+displays the IP routing table.
+.SH OPTIONS
+.TP
+.B \-i
+.I "ip device"
+specifies the ip device. 
+.SH "SEE ALSO"
+.BR add_route (8), 
+.BR irdp (8).
+.SH AUTHOR
+.I Pr_routes.c 
+was written by Philip Homburg. 
+This manual page by A. S. Woodhull, last revised 13.02.96.
Index: /trunk/minix/man/man8/printroot.8
===================================================================
--- /trunk/minix/man/man8/printroot.8	(revision 9)
+++ /trunk/minix/man/man8/printroot.8	(revision 9)
@@ -0,0 +1,29 @@
+.TH PRINTROOT 8
+.SH NAME
+printroot \- print the name of the root device on standard output
+.SH SYNOPSIS
+\fBprintroot\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.FL "\-r" "Print only the root device, not a full mtab line"
+.SH EXAMPLES
+.EX "printroot" "Print the name of the root device"
+.SH DESCRIPTION
+.PP
+.I Printroot 
+is useful for initializing the \fI/etc/mtab\fR when the system is booted.
+It figures out what the root device is by searching \fI/dev\fR until it
+finds a block special file with the right major/minor device numbers.
+.SH "SEE ALSO"
+.BR fstab (5),
+.BR boot (8).
Index: /trunk/minix/man/man8/pwdauth.8
===================================================================
--- /trunk/minix/man/man8/pwdauth.8	(revision 9)
+++ /trunk/minix/man/man8/pwdauth.8	(revision 9)
@@ -0,0 +1,58 @@
+.TH PWDAUTH
+.SH NAME
+pwdauth \- password authentication program
+.SH SYNOPSIS
+.B /usr/lib/pwdauth
+.SH DESCRIPTION
+.B Pwdauth
+is a program that is used by the
+.BR crypt (3)
+function to do the hard work.  It is a setuid root utility so that it is
+able to read the shadow password file.
+.PP
+.B Pwdauth
+expects on standard input two null terminated strings, the
+password typed by the user, and the salt.  That is, the two arguments of
+the
+.B crypt
+function.  The input read in a single read call must be 1024 characters or
+less including the nulls.
+.B Pwdauth
+takes one of two actions depending on the salt.
+.PP
+If the salt has the form "\fB##\fIuser\fR" then the
+.I user
+is used to index the shadow password file to obtain the encrypted password.
+The input password is encrypted with the one-way encryption function
+contained within
+.B pwdauth
+and compared to the encrypted password from the shadow password file.  If
+equal then
+.B pwdauth
+returns the string "\fB##\fIuser\fR" with exit code 0, otherwise exit
+code 2 to signal failure.  The string "\fB##\fIuser\fR" is also returned
+if both the shadow password and the input password are null strings to
+allow a password-less login.
+.PP
+If the salt is not of the form "\fB##\fIuser\fR" then the password is
+encrypted and the result of the encryption is returned.  If salt and
+password are null strings then a null string is returned.
+.PP
+The return value is written to standard output as a null terminated string
+of 1024 characters or less including the null.
+.PP
+The exit code is 1 on any error.
+.SH "SEE ALSO"
+.BR crypt (3),
+.BR passwd (5).
+.SH NOTES
+A password must be checked like in this example:
+.PP
+.RS
+pw_ok = (strcmp(crypt(key, pw->pw_passwd), pw->pw_passwd) == 0);
+.RE
+.PP
+The second argument of crypt must be the entire encrypted password and
+not just the two character salt.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/rarpd.8
===================================================================
--- /trunk/minix/man/man8/rarpd.8	(revision 9)
+++ /trunk/minix/man/man8/rarpd.8	(revision 9)
@@ -0,0 +1,75 @@
+.TH RARPD 8
+.SH NAME
+rarpd \- reverse address resolution protocol daemon
+.SH SYNOPSIS
+.B rarpd
+.RB [ \-d [\fIlevel\fR]]
+.I network-name
+\&...
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Rarpd
+listens on the given networks for broadcast packets asking for reverse address
+resolution.  These packets are sent by hosts at boot time to find out their
+IP address.
+.B Rarpd
+looks up the six octet ethernet number in the
+.B /etc/ethers
+file finding a host name.  This name is translated to the IP address of the
+host by a DNS lookup.  The IP address is then sent to the host.
+.PP
+Under MINIX 3 the program forks as needed to give each network its own server.
+Under Minix-vmd all networks are handled in the same program using async I/O.
+.SS "Private Ethernet Addresses"
+For VU practical work, where students have to create their own IP stack
+starting at the bottom with RARP, this implementation recognizes Ethernet
+addresses starting with octet 0x76 as special.  The next octet is used as a
+additional host number and the next and last four octets as an IP address
+that this Ethernet address is additional for.  The IP address is translated
+back to a name, and the first component of that name gets a dash and the
+additional host number added to it.  That hostname is then looked up and its
+IP address returned in a RARP reply.  Example:
+.PP
+.RS
+.ta +\w'flotsam-3.example.commmm'u
+76:3:c0:a8:e7:fa	Additional 3, IP 192.168.231.250
+.SP
+flotsam.example.com	Reverse lookup on 192.168.231.250
+.SP
+flotsam-3.example.com	Splicing in additional number
+.SP
+192.168.231.42		Forward lookup
+.RE
+.PP
+In this example a RARP query for 76:3:c0:a8:e7:fa gets 192.168.231.42 as reply.
+.SH OPTIONS
+.TP
+.BR \-d [\fIlevel\fP]
+Turns on debugging messages at the given level, by default 1.  At level 1 you
+will be shown what answers are sent, and at level 2 or higher you will be told
+about queries from unknown hosts or host on the wrong network.
+The debug level can also be increased by 1 at runtime by sending signal
+.B SIGUSR1
+or turned off (set to 0) with
+.BR SIGUSR2 .
+.SH "SEE ALSO"
+.BR ifconfig (8),
+.BR ethers (5),
+.BR hosts (5),
+.BR inet (8),
+.BR boot (8),
+.BR dhcpd (8),
+.BR irdpd (8),
+.BR inetd (8),
+.BR nonamed (8).
+.SH NOTES
+A "network name" is the device name of the IP device of a network, i.e.
+.BR ip0 ,
+.BR ip1 ", ..."
+.PP
+The RARP protocol has gone out of fashion in favour of DHCP.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/rdate.8
===================================================================
--- /trunk/minix/man/man8/rdate.8	(revision 9)
+++ /trunk/minix/man/man8/rdate.8	(revision 9)
@@ -0,0 +1,20 @@
+.TH RDATE 8
+.SH NAME
+rdate \- set time and date from a remote host
+.SH SYNOPSIS
+.B rdate
+.IR host " ..."
+.SH DESCRIPTION
+.B Rdate
+obtains the current time from a remote time server.  If run by the
+super-user then local time is set to that time.  The time of the remote host
+is printed on standard output.
+.PP
+More than one host name may be specified.  They are tried one by one until
+one responds.
+.SH "SEE ALSO"
+.BR date (1),
+.BR readclock (8),
+.BR inet (8).
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/readclock.8
===================================================================
--- /trunk/minix/man/man8/readclock.8	(revision 9)
+++ /trunk/minix/man/man8/readclock.8	(revision 9)
@@ -0,0 +1,61 @@
+.TH READCLOCK 8
+.SH NAME
+readclock \- read the AT's real time clock
+.SH SYNOPSIS
+\fBreadclock\fP [\fB\-nwW2\fP]
+.SH DESCRIPTION
+.B Readclock
+reads the AT's real time clock and sets the machine's time.  It is usually
+the second thing done in
+.BR /etc/rc ,
+the first thing is setting the time zone by sourcing
+.BR /etc/profile .
+This means that the clock is assumed to tell the wall clock time.  If you
+want to run the clock in GMT then you can put
+.B "TZ=GMT"
+(or any other TZ value) in front of the readclock command.
+.SH OPTIONS
+.TP
+.B \-n
+Play-act, don't set the time nor change the calibration data, just show what
+would be done.
+.TP
+.B \-w
+Write the current time to the CMOS clock.  Dangerous, see
+.BR BUGS .
+Don't forget to use
+.B "TZ=GMT"
+in front of readclock if the clock should run in GMT.
+.TP
+.B \-W
+Like
+.BR \-w ,
+but also sets the status registers of the CMOS clock to their proper values.
+(For if the clock suddenly runs at an odd pace or has stopped and the BIOS
+doesn't repair it.)
+.TP
+.BR \-2 ,
+Add 20 to any year before 2000.  If your CMOS clock year can't run past 2000,
+then you can set it to 1980 and use
+.B \-2
+to correct the year.  Together with
+.B \-w
+the year minus 20 is written to the clock.
+.SH FILES
+.TP 20n
+/etc/profile
+Timezone and other shell initialization code.
+.SH "SEE ALSO"
+.BR date (1),
+.BR utime (1).
+.SH BUGS
+Reported to not work on some AT's.
+.PP
+May mess up the clock royally when setting it
+.RB ( \-w ).
+Only if you have a very standard AT and you are not afraid of having your
+CMOS setup reset to the default with a "checksum error" should you use
+.BR readclock
+to set the time of the CMOS clock.  You have been warned.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/reboot.8
===================================================================
--- /trunk/minix/man/man8/reboot.8	(revision 9)
+++ /trunk/minix/man/man8/reboot.8	(revision 9)
@@ -0,0 +1,49 @@
+.TH REBOOT 8
+.SH NAME
+reboot \- reboot the system immediately
+.SH SYNOPSIS
+\fBreboot\fP [\fB\-f\fP]
+.SH DESCRIPTION
+.B Reboot
+can be used to reboot the system after installing a new kernel.  It does
+not inform the users, but does log it's actions in
+.B /usr/adm/wtmp
+and
+.BR /usr/adm/log .
+The system is then rebooted with the
+.BR reboot (2)
+systemcall.
+.PP
+If the
+.B \-f
+flag is not given then all processes are sent terminate
+signals to give them a chance to die peacefully before the
+.B reboot()
+call.
+.PP
+If the wtmp file exists,
+.B reboot
+logs itself as if it were a shutdown.  This is done to prevent
+.BR last (1)
+from talking about system-crashes.
+.B Reboot
+is registered as is in the log file.
+.PP
+.B Reboot
+can only be executed by the super-user.  Any other caller will be
+refused, either by
+.BR reboot (8)
+or by
+.BR reboot (2).
+.SH "SEE ALSO"
+.BR reboot (2),
+.BR shutdown (8),
+.BR halt(8),
+.BR boot (8).
+.SH BUGS
+The error message's given by
+.B reboot
+are not always useful.  There are several routines that can fail, but which
+are not fatal for the program. 
+.SH AUTHOR
+Edvard Tuinder (v892231@si.hhs.NL)
Index: /trunk/minix/man/man8/repartition.8
===================================================================
--- /trunk/minix/man/man8/repartition.8	(revision 9)
+++ /trunk/minix/man/man8/repartition.8	(revision 9)
@@ -0,0 +1,41 @@
+.TH REPARTITION 8
+.SH NAME
+repartition \- load a partition table
+.SH SYNOPSIS
+\fBrepartition\fP \fIdevice\fP [\fIpartition-file\fP]
+.SH DESCRIPTION
+.B Repartition
+uploads a new partition table for the partitions of
+.IR device .
+The table is obtained from the first sector of
+.I partition-file
+if given,
+.I device
+otherwise.
+.I Device
+may refer to the whole drive or a primary partition, depending on whether you
+want to upload a partition or a subpartition table.  The partitions will be
+truncated to fit within the enclosing device like the disk driver does,
+unless the numbers are coming from
+.IR partition-file .
+.SH EXAMPLES
+repartition /dev/hd0
+.br
+repartition /dev/hd4 /etc/hd4.table
+.PP
+Reload the partition table of drive 0 setting /dev/hd[1\-4], and the
+subpartition table of /dev/hd4 setting /dev/hd4[a\-d] using a file.
+The latter may be useful if you need more than the 4 subpartitions a
+single MINIX 3 partition gives you.
+.SH DIAGNOSTICS
+The new table is printed on standard output.
+.SH FILES
+/dev/hd[0-9]
+.SH "SEE ALSO"
+.BR hd (4),
+.BR part (8).
+.SH BUGS
+The disk must be in use for the changes to stick.  The partition table of
+an idle disk will be reloaded on the first open.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/rlogind.8
===================================================================
--- /trunk/minix/man/man8/rlogind.8	(revision 9)
+++ /trunk/minix/man/man8/rlogind.8	(revision 9)
@@ -0,0 +1,103 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)rlogind.8c	6.3 (Berkeley) 5/24/86
+.\"
+.TH RLOGIND 8 "May 24, 1986"
+.UC 5
+.SH NAME
+rlogind, in.rlogind \- remote login server
+.SH SYNOPSIS
+.B "login stream tcp nowait root /usr/sbin/in.rlogind in.rlogind"
+.br
+.B "tcpd login /usr/sbin/in.rlogind"
+.SH DESCRIPTION
+.B Rlogind
+is the server for the 
+.BR rlogin (1)
+program.  The server provides a remote login facility
+with authentication based on privileged port numbers from trusted hosts.
+.PP
+.B Rlogind
+listens for service requests at the port indicated in
+the ``login'' service specification; see
+.BR services (5).
+When a service request is received the following protocol
+is initiated:
+.IP 1)
+The server checks the client's source port.
+If the port is not in the range 0-1023, the server
+aborts the connection.
+.IP 2)
+The server checks the client's source address
+and requests the corresponding host name (see
+.BR gethostbyaddr (3),
+.BR hosts (5)
+and
+.BR named (8)).
+If the hostname cannot be determined,
+the dot-notation representation of the host address is used.
+.PP
+Once the source port and address have been checked, 
+.B rlogind
+allocates a pseudo terminal (see 
+.BR tty (4)),
+and manipulates file descriptors so that the slave
+half of the pseudo terminal becomes the 
+.B stdin ,
+.B stdout ,
+and
+.B stderr 
+for a login process.
+The login process is an instance of the
+.BR login (1)
+program, invoked with the
+.B \-r
+option.  The login process then proceeds with the authentication
+process as described in
+.BR rshd (8),
+but if automatic authentication fails, it reprompts the user
+to login as one finds on a standard terminal line.
+.PP
+The parent of the login process manipulates the master side of
+the pseduo terminal, operating as an intermediary
+between the login process and the client instance of the
+.B rlogin
+program.  In normal operation, the packet protocol described
+in
+.BR tty (4)
+is invoked to provide ^S/^Q type facilities and propagate
+interrupt signals to the remote programs.  The login process
+propagates the client terminal's baud rate and terminal type,
+as found in the environment variable, ``TERM''; see
+.BR environ (7).
+The screen or window size of the terminal is requested from the client,
+and window size changes from the client are propagated to the pseudo terminal.
+.SH "SEE ALSO"
+.BR rlogin (1).
+.SH DIAGNOSTICS
+All diagnostic messages are returned on the connection
+associated with the
+.BR stderr ,
+after which any network connections are closed.
+An error is indicated by a leading byte with a value of 1.
+.PP
+.B ``Try again.''
+.br
+A
+.B fork
+by the server failed.
+.PP
+.B ``/bin/sh: ...''
+.br
+The user's login shell could not be started.
+.SH BUGS
+The authentication procedure used here assumes the integrity
+of each client machine and the connecting medium.  This is
+insecure, but is useful in an ``open'' environment.
+.PP
+A facility to allow all data exchanges to be encrypted should be
+present.
+.PP
+A more extensible protocol should be used.
Index: /trunk/minix/man/man8/rshd.8
===================================================================
--- /trunk/minix/man/man8/rshd.8	(revision 9)
+++ /trunk/minix/man/man8/rshd.8	(revision 9)
@@ -0,0 +1,166 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)rshd.8c	6.3 (Berkeley) 5/24/86
+.\"
+.TH RSHD 8 "May 24, 1986"
+.UC 5
+.SH NAME
+rshd \- remote shell server
+.SH SYNOPSIS
+.B "shell stream tcp nowait root /usr/sbin/in.rshd in.rshd"
+.br
+.B "tcpd shell /usr/sbin/in.rshd"
+.SH DESCRIPTION
+.B Rshd
+is the server for the 
+.BR rcmd (3)
+routine and, consequently, for the
+.BR rsh (1)
+program.  The server provides remote execution facilities
+with authentication based on privileged port numbers from trusted hosts.
+.PP
+.B Rshd
+listens for service requests at the port indicated in
+the ``cmd'' service specification; see
+.BR services (5).
+When a service request is received the following protocol
+is initiated:
+.IP 1)
+The server checks the client's source port.
+If the port is not in the range 0-1023, the server
+aborts the connection.
+.IP 2)
+The server reads characters from the socket up
+to a null (`\e0') byte.  The resultant string is
+interpreted as an ASCII number, base 10.
+.IP 3)
+If the number received in step 1 is non-zero,
+it is interpreted as the port number of a secondary
+stream to be used for the 
+.BR stderr .
+A second connection is then created to the specified
+port on the client's machine.  The source port of this
+second connection is also in the range 0-1023.
+.IP 4)
+The server checks the client's source address
+and requests the corresponding host name (see
+.BR gethostbyaddr (3N),
+.BR hosts (5)
+and
+.BR named (8)).
+If the hostname cannot be determined,
+the dot-notation representation of the host address is used.
+.IP 5)
+A null terminated user name of at most 16 characters
+is retrieved on the initial socket.  This user name
+is interpreted as the user identity on the
+.BR client 's
+machine.
+.IP 6)
+A null terminated user name of at most 16 characters
+is retrieved on the initial socket.  This user name
+is interpreted as a user identity to use on the
+.BR server 's
+machine.
+.IP 7)
+A null terminated command to be passed to a
+shell is retrieved on the initial socket.  The length of
+the command is limited by the upper bound on the size of
+the system's argument list.  
+.IP 8)
+.B Rshd
+then validates the user according to the following steps.
+The local (server-end) user name is looked up in the password file
+and a
+.B chdir
+is performed to the user's home directory.  If either
+the lookup or 
+.B chdir
+fail, the connection is terminated.
+If the user is not the super-user, (user id 0), the file 
+.B /etc/hosts.equiv
+is consulted for a list of hosts considered ``equivalent''.
+If the client's host name is present in this file, the
+authentication is considered successful.  If the lookup
+fails, or the user is the super-user, then the file
+.B .rhosts
+in the home directory of the remote user is checked for
+the machine name and identity of the user on the client's
+machine.  If this lookup fails, the connection is terminated.
+.IP 9)
+A null byte is returned on the initial socket
+and the command line is passed to the normal login
+shell of the user.  The
+shell inherits the network connections established
+by
+.IR rshd .
+.SH DIAGNOSTICS
+Except for the last one listed below,
+all diagnostic messages
+are returned on the initial socket,
+after which any network connections are closed.
+An error is indicated by a leading byte with a value of
+1 (0 is returned in step 9 above upon successful completion
+of all the steps prior to the execution of the login shell).
+.PP
+.B ``locuser too long''
+.br
+The name of the user on the client's machine is
+longer than 16 characters.
+.PP
+.B ``remuser too long''
+.br
+The name of the user on the remote machine is
+longer than 16 characters.
+.PP
+.B ``command too long ''
+.br
+The command line passed exceeds the size of the argument
+list (as configured into the system).
+.PP
+.B ``Login incorrect.''
+.br
+No password file entry for the user name existed.
+.PP
+.B ``No remote directory.''
+.br
+The 
+.B chdir
+command to the home directory failed.
+.PP
+.B ``Permission denied.''
+.br
+The authentication procedure described above failed.
+.PP
+.B ``Can't make pipe.''
+.br
+The pipe needed for the 
+.BR stderr ,
+wasn't created.
+.PP
+.B ``Try again.''
+.br
+A
+.B fork
+by the server failed.
+.PP
+.B ``<shellname>: ...''
+.br
+The user's login shell could not be started.  This message is returned
+on the connection associated with the
+.BR stderr ,
+and is not preceded by a flag byte.
+.SH SEE ALSO
+.BR rsh (1),
+.BR rcmd (3).
+.SH BUGS
+The authentication procedure used here assumes the integrity
+of each client machine and the connecting medium.  This is
+insecure, but is useful in an ``open'' environment.
+.PP
+A facility to allow all data exchanges to be encrypted should be
+present.
+.PP
+A more extensible protocol should be used.
Index: /trunk/minix/man/man8/screendump.8
===================================================================
--- /trunk/minix/man/man8/screendump.8	(revision 9)
+++ /trunk/minix/man/man8/screendump.8	(revision 9)
@@ -0,0 +1,35 @@
+.TH SCREENDUMP 8
+.SH NAME
+screendump \- write current console screen to standard output
+.SH SYNOPSIS
+.B screendump
+.SH DESCRIPTION
+.B Screendump
+prints the contents of the console screen to standard output.  It does this
+by reading the screen memory, skipping over attribute bytes, omitting
+trailing blanks and inserting a newline character at the end of each line.
+.SH NOTES
+The most common use of 
+.BR screendump
+is with output redirected to a file. This allows screen displays (including 
+output of F-keys) to be captured for inclusion in other documents.
+.PP
+This version is for IBM-PC architecture only. 
+.SH BUGS
+A network user captures an image of the main console, not his or her own
+screen.  The output will usually not be what you expect if the display is in
+hardware scrolling mode, since in that mode the order of the lines in screen
+memory may not be the same as what appears on the screen.
+If you expect to use 
+.BR screendump
+to send notes to someone about problems that occur while using 
+.BR MINIX
+you must remember to toggle to software scrolling before you make the dump.
+It will also be necessary to use
+.BR su ,
+because
+.BR /dev/mem
+is normally not world readable.
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
+.\" preliminary man file by Al Woodhull (awoodhull@hampshire.edu) 01.08.95
Index: /trunk/minix/man/man8/serial-ip.8
===================================================================
--- /trunk/minix/man/man8/serial-ip.8	(revision 9)
+++ /trunk/minix/man/man8/serial-ip.8	(revision 9)
@@ -0,0 +1,232 @@
+.TH SERIAL-IP 8
+.SH NAME
+serial-ip \- Serial IP (SLIP or PPP) setup
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+\-\-\-\-\-\-\-
+.br
+.B Note:
+This text and the serial IP code is not finished.  Code needs to be added to
+.B nonamed
+to allow it to be used both with and without a connection to the Internet,
+and by now there is a PPP program for standard MINIX 3 "out there" that will
+change everything that is said in this text.  So much to do, so little
+time...
+.br
+\-\-\-\-\-\-\-
+.PP
+This manual page describes the MINIX 3 network setup to use serial line IP.
+The serial IP protocol used can either be the older SLIP by means of the
+.BR slip (8)
+program, or PPP (Point-to-Point Protocol), the newer and better serial IP
+protocol implemented by the
+.BR ppp (8)
+program.  Alas standard MINIX 3 only supports SLIP.
+.PP
+In the following text all descriptions and examples will name SLIP or the
+.BR slip
+program, but one may just as well read PPP or
+.BR ppp .
+Where necessary the differences will be noted.
+.PP
+A typical use of the
+.B slip
+program is like this:
+.PP
+.RS
+.B "slip /dev/psip2 </dev/tty01 >/dev/tty01"
+.RE
+.PP
+The argument of the program, the
+.B /dev/psip2
+device, is one of the so-called "Pseudo IP" devices that the MINIX 3 TCP/IP
+driver
+.BR inet (8)
+offers to implement a virtual network on.  On an ethernet IP packets are
+received or transmitted by the ethernet card, but packets on a pseudo IP
+network are channeled back to or received from a program running in user
+space, such as
+.BR slip .
+Standard input and output are used by
+.B slip
+to exchange packets with another SLIP implementation.  This is normally
+through an RS-232 serial line like the second serial line
+.B /dev/tty01
+as used in the example above.
+.PP
+If we look at the flow of data over normal ethernet then this is what a TCP
+connection between two MINIX 3 machines,
+.B telnet
+for instance, looks like:
+.PP
+.in 0
+.ce 13
+[telnet]
+|
+/dev/tcp0
+|
+inet
+|
+[ethernet]
+|
+inet
+|
+/dev/tcp0
+|
+[in.telnetd]
+.PP
+One-half (!) of a SLIP connection would look like this:
+.PP
+.in 0
+.ce 12
+[telnet]
+|
+/dev/tcp2
+|
+inet
+|
+/dev/psip2
+|
+slip
+|
+[serial line]
+\&...
+.SS "Configuration for a SLIP network only"
+It is important to know that as far as
+.B inet
+is concerned the pseudo IP network is just another network, nothing special.
+So you have to convince
+.B inet
+that it has to send packets out over that network.  One does this by
+setting a default route that makes
+.B inet
+believe that there is a router somewhere on the pseudo-IP network.
+.PP
+Assume your machine has been given the IP address
+.B 192.168.0.13
+by your service provider.  Let's choose another address on that network,
+.B 192.168.0.1
+for instance.  (You can use the address of the SLIP gateway if you want
+to make it look pretty, but it doesn't really matter, anything "out there"
+is ok.)
+To make MINIX 3 aware of the situation you have to configure the pseudo IP
+network.  For Minix-vmd you need to look for the
+.B if-then-else-fi
+code in
+.B /usr/etc/rc
+that tests if
+.B /etc/rc.net
+should be run.  Copy the lines in the
+.B else
+clause that starts network daemons to
+.B /etc/rc.net
+and add the following lines to make it look like this:
+.PP
+.RS
+.nf
+# My SLIP interface address.
+ifconfig -h 192.168.0.13 -n 255.255.255.0
+.SP
+# Standard network daemons.
+daemonize rarpd $named irdpd rip inetd
+.SP
+# Default route to the outside world.
+add_route -g 192.168.0.1
+.fi
+.RE
+.PP
+For standard MINIX 3 one has to edit
+.B /etc/rc
+instead at the point of the XXX comments.  The
+.B ifconfig
+goes at the first XXX, the
+.B add_route
+at the second XXX.  The result is conceptually the same as the example
+above.  The important thing is the order: Configuration, Daemons, Routes.
+(First give addresses to the networks, let the daemons meditate over the
+results and possibly configure more networks (rarpd), then add routes to
+the configured networks.)
+.PP
+Just one thing left to do.  The system uses the first ethernet network
+.RB ( eth0 ,
+.BR ip0 ,
+.BR tcp0 ,
+and
+.BR udp0 )
+as the default network.  With the program
+.BR netdefault (8)
+you have to change the links to the default devices
+.RB ( eth / psip ,
+.BR ip ,
+.BR tcp ,
+and
+.BR udp )
+to point to the first pseudo IP network
+.RB ( psip2 ,
+.BR ip2 ,
+.BR tcp2 ,
+and
+.BR udp2 ):
+.PP
+.RS
+.B "netdefault psip2"
+.RE
+.PP
+In
+.B /etc/hosts
+list at least
+.B localhost
+and the name of your machine with its SLIP address.  This way your machine
+will boot and know its own name.  Now you need to find a way to let your
+system know the addresses of other machines.  There are three ways:
+.PP
+.RS
+List the names and addresses of any other machine you wish to talk
+to in
+.BR /etc/hosts .
+Drawback: This will quickly become a pretty long list.
+.SP
+Create an
+.B /etc/resolv.conf
+that lists a nameserver at your ISP and
+.B 127.0.0.1
+(localhost).  Drawback:  With the SLIP link down it takes 5 to 10 seconds for
+a name lookup to time out on the remote name server before the local name
+server is tried.
+.SP
+Install the above
+.B /etc/resolv.conf
+when
+.B slip
+is started, and remove it when
+.B slip
+exits.  Drawback: Long running programs only read
+.B /etc/resolv.conf
+at startup, so they don't notice it changing.
+.SP
+Run a real Internet name daemon from the
+.B named
+package.  Drawback: Nontrivial to set up.
+.SS "Configuration for a SLIP - Ethernet router (simple case)"
+XXX
+.SS "Configuration for a SLIP - Ethernet router (complex case)"
+XXX
+.SH FILES
+.TP \w'/dev/psip*'u+5n
+.B /dev/psip*
+Pseudo-IP devices for use by
+.BR slip
+and
+.BR ppp .
+.SH "SEE ALSO"
+.BR boot (8),
+.BR inet (8),
+.BR netdefault (8),
+.BR term (1),
+.BR chat (1).
+.SH BUGS
+.SH AUTHOR
+Kees J. Bot (kjb@cs.vu.nl)
Index: /trunk/minix/man/man8/service.8
===================================================================
--- /trunk/minix/man/man8/service.8	(revision 9)
+++ /trunk/minix/man/man8/service.8	(revision 9)
@@ -0,0 +1,61 @@
+.TH SERVICE 8
+.SH NAME
+service \- Start or stop an operating system server or device driver.
+.SH SYNOPSIS
+.PP
+\fBservice up\fR \fI<service>\fR [\fB-args\fR \fIargs\fR]
+[\fB-dev\fR \fIspecial\fR] [\fB-period\fR \fIticks\fR]
+.PP
+\fBservice down\fR \fI<pid>\fR
+.PP
+\fBservice refresh\fR \fI<pid>\fR
+.PP
+\fBservice rescue\fR \fI<dir>\fR
+.PP
+\fBservice shutdown\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.SH DESCRIPTION
+.PP
+Tells the reincarnation server to start or stop a system service, such as a
+server or device driver. The device driver will be automatically restarted when
+it unexpectedly exits, e.g., if it is killed because of a bad pointer. 
+Starting requires an absoluate path to the binary to be executed.
+.PP
+When an optional period is specified, the reincarnation server sends a status
+request to the system service after every period. If there the response does 
+not arrive in time, the reincarnation server will kill the misbehaving process
+and restart a new one. The period must be specified in ticks, but can be 
+appended with 'HZ' to make it seconds.
+.PP
+Stopping a system service requires the process id of a running system service. 
+Issuing a kill command from the shell will not work, since the reincarnation
+server interprets this as an unexpected exit and will automatically restart
+a fresh copy of the process. The clean way to restart a process is using the
+'refresh' option of the service utility.
+.PP
+The rescue call can be used to set the current working directory of the reincarnation server. By using a trusted rescue driver to shadow certain binaries in RAM the reincarnation server can check that rescue directory for binaries if the normal execution of the absolute path fails. This allows recovery from failures of the root file system driver.
+.PP
+If the system is to be shutdown, the reincarnation server should know about this event to prevent it from restarting services that are killed during the shutdown
+sequence.
+.SH EXAMPLES
+.EX "service up /sbin/is -period 5HZ" "Start the IS server and check its status every 5 seconds."
+.br
+.EX "service up /usr/sbin/dp8390 -args DPETH0=pci" "Start the DP8390 ethernet driver, passing one argument."
+.br
+.EX "service down 117" "Stop the system service with process id 117."
+.br
+.SH "SEE ALSO"
+.PP
+.BR boot (8),
+.BR monitor (8)
+
Index: /trunk/minix/man/man8/setup.8
===================================================================
--- /trunk/minix/man/man8/setup.8	(revision 9)
+++ /trunk/minix/man/man8/setup.8	(revision 9)
@@ -0,0 +1,399 @@
+.TH SETUP 8
+.SH NAME
+setup \- Install MINIX 3 on a hard disk
+.SH SYNOPSIS
+setup
+.SH DESCRIPTION
+.tr ~ 
+.nr a 0 +1
+.de CB
+.sp 0.5v
+\s-1\\f5\\c
+..
+.de CE
+\\fR\\s0\\c
+.sp 0.5v
+..
+.de IT
+.ti -0.25i
+.PP
+..
+.PP
+This appendix explains how to install MINIX 3.
+Standard MINIX 3 requires a Pentium (or compatible) with at least
+16-MB of RAM, at least 200-MB of free disk space, an IDE CD-ROM and an
+IDE hard disk. Serial ATA, USB, and SCSI disks are not supported at present.
+For USB CD-ROMS, see the Website: \fIwww.minix3.org\fR.
+
+\fBPREPARATION\fR
+.PP
+If you already have the CD-ROM (e.g., from the book), you can skip steps 1 and
+2, but it is wise to check \fIwww.minix3.org\fR to see if a newer version
+is available.
+If you want to run MINIX 3 on a simulator instead of native, see Part V first.
+If you do not have an IDE CD-ROM, 
+either get the special USB CD-ROM boot image or use a simulator.
+
+.IT "Download the MINIX 3 CD-ROM image"
+Download the MINIX 3 CD-ROM image from the MINIX 3 Website
+at \fIwww.minix3.org\fR.
+
+.IT "Create a bootable MINIX 3 CD-ROM"
+Decompress the downloaded file.
+You will get a CD-ROM image file with extension \fI.iso\fR and this manual.
+The \fI.iso\fR file is a bit-for-bit CD-ROM image.
+Burn it to a CD-ROM to make a bootable CD-ROM.
+.PP
+If you are using \fIEasy CD Creator 5\fR, select \*(OQRecord CD from CD image\*(CQ from the File
+menu and change the file type from \fI.cif\fR to \fI.iso\fR in the dialog box that
+appears. Select the image file and click \*(OQOpen.\*(CQ Then click \*(OQStart Recording.\*(CQ
+.PP
+If you are using \fINero Express 5\fR, choose \*(OQDisc Image or Saved Project\*(CQ and
+change the type to \*(OQImage Files,\*(CQ select the image file and click \*(OQOpen.\*(CQ
+Select your CD recorder and click on \*(OQNext.\*(CQ
+.PP
+If you are running Windows and do not have a CD-ROM burning program, take a look at
+.br
+\fIalexfeinman.brinkster.net/isorecorder.htm\fR
+.br
+for a free one and use it to create
+a CD image.
+
+.IT "Determine which Ethernet Chip you have"
+.PP
+MINIX 3 supports several Ethernet chips for networking over LAN, ADSL, and
+cable. These include Intel Pro/100, RealTek 8029 and 8139, AMD LANCE,
+and several 3Com chips.
+During setup
+you will be asked which Ethernet chip you have, if any. Determine that now by
+looking at your documentation. Alternatively, if you are using Windows, go to
+the device manager as follows:
+.sp 1
+.ta 0.9i
+Windows 2000:	
+.br
+Start> Settings> Control Panel> System> Hardware> Device Mgr
+.sp 1
+Windows XP:	
+.br
+Start> Control Panel> System> Hardware> Device Mgr\s0
+.ll -1i
+.sp 1
+System requires double clicking; the rest are single. Expand the + next to
+\*(OQNetwork adapters\*(CQ to see what you have. Write it down. If you do not have
+a supported chip, you can still run MINIX 3, but without Ethernet.
+
+.IT "Partition your hard disk"
+.PP
+You can boot the computer from your CD-ROM if
+you like and MINIX 3 will start, but to do anything useful, you have to create a
+partition for it on your hard disk.
+But before partitioning, be sure to \fBback up your data to an external med\%ium
+like CD-ROM or DVD\fR as a safety precaution, just in case something goes wrong.
+Your files are valuable; protect them.
+.PP
+Unless you are sure you are an expert on disk partitioning with much experience, it is strongly suggested that you
+read the online tutorial on disk partitioning
+at \fIwww.minix3.org/doc/partitions.html.\fR
+If you already know how to manage partitions, create a contiguous chunk of free
+disk space of at least 200 MB (even better: 400 MB or more).
+If you do not know how to manage partitions but have a partitioning program
+like \fIPartition Magic\fR, use it to create a region of free disk space of at
+least 200 MB. Also make sure there is at least one primary partition (i.e.,
+Master Boot Record slot) free.
+The MINIX 3 setup script will guide you through creating a MINIX partition in the 
+free space, which can be on either the first or second IDE disk.
+.PP
+If you are running Windows 95, 98, ME, or 2000 \fIand\fR your disk consists of a single
+FAT partition, you can use the \fIpresz134.exe\fR program on the CD-ROM
+(also available at \fIzeleps.com\fR) to reduce its size to leave room for MINIX.
+In all other cases, please read the online tutorial cited above.
+.PP
+\fBWARNING: If you make a mistake during disk partitioning, you can lose all the data
+on the disk, so be sure to back it up to CD-ROM or DVD before starting.
+Disk partitioning requires great care, so proceed with caution.\fR
+
+\fBBOOTING\fR
+.nr a 0 
+.PP
+By now you should have allocated at least 200 MB of free space on your disk.
+If you have not done so yet, please do it now unless there is an existing
+200-MB (or larger) partition you are willing to convert to MINIX 3.
+
+.IT "Boot from the CD-ROM"
+Insert the CD-ROM into your CD-ROM drive and boot the computer from it.
+If you have 16 MB of RAM or more, choose \*(OQRegular;\*(CQ 
+if you have only 8 MB choose \*(OQsmall.\*(CQ
+If the computer boots from the hard disk instead of the CD-ROM, boot again and enter the
+BIOS setup program to change the order of boot devices, putting the CD-ROM before
+the hard disk.
+
+.IT "Login as root"
+When the \fIlogin\fR prompt appears, login as \fIroot.\fR
+After a successful login as root, you will see the shell prompt (#).
+At this point you are running fully-operational MINIX 3. If you type:
+.PP
+   ls /usr/bin | more
+.PP
+you can see what software is available.
+Hit space to scroll the list. 
+To see what program \fIfoo\fR does, type:
+.PP
+   man foo
+.PP
+The manual pages are also available at
+.br
+\fIwww.minix3.org/manpages\fR. 
+
+.IT "Start the setup script"
+To start the installation of MINIX 3 on the hard disk, type
+.PP
+   setup
+.PP
+After this and all other commands, be sure to type ENTER (RETURN).
+When the installation script ends a screen with a colon, hit ENTER to
+continue. If the screen suddenly goes blank, press CTRL-F3 to select
+software scrolling (should only be needed on very old computers).
+Note that CTRL-key means depress the CTRL key and while holding it down,
+press \*(OQkey.\*(CQ
+
+\fBINSTALLING TO THE HARD DISK\fR
+.nr a 0
+.PP
+These steps correspond to the steps on the screen.
+
+.IT "Select keyboard type"
+When you are asked to select your national keyboard, do so. 
+This and other steps have a default choice, in square brackets.
+If you agree with it, just hit ENTER. In most steps, the default is generally
+a good choice for beginners.
+The us-swap keyboard interchanges the CAPS LOCK and CTRL keys, as is conventional
+on UNIX systems.
+
+.IT "Select your Ethernet chip"
+You will now be asked which of the available Ethernet driver you want
+in\%stalled (or none). Please choose one of the options.
+
+.IT "Basic minimal or full install?"
+If you are tight on disk space, select M for a minimal installation
+which includes all the binaries but only the system sources installed.
+200 MB is enough for a bare-bones system. If you have 400 MB or more,
+choose F for a full installation.
+
+.IT "Create or select a partition for MINIX 3"
+You will first be asked if you are an expert in MINIX 3 disk partitioning.
+If so, you will be placed in the \fIpart\fR program to give you full power to
+edit the Master Boot Record (and enough rope to hang yourself).
+If you are not an expert, press ENTER for the default action, which is an
+automated step-by-step guide to formatting a disk partition for MINIX 3.
+
+\fBSubstep 4.1: Select a disk to install MINIX 3\fR
+.PP
+An IDE controller may have up to four disks. The \fIsetup\fR script will now
+look for each one. Just ignore an error messages.
+When the drives are listed, select one. and confirm your choice.
+If you have two hard disks and you decide to install MINIX 3 to the second one and have
+trouble booting from it, please see \fIwww.minix3.org/doc/using2disks.html\fR
+for the solution.
+
+\fBSubstep 4.2: Select a disk region\fR
+.PP
+Now choose a region to install MINIX 3 into. You have three choices:
+.sp 0.5v
+   (1) Select a free region
+   (2) Select a partition to overwrite
+   (3) Delete an existing partition to free up space and merge with adjacent free 
+space
+.sp 0.5v
+For choices (1) and (2), type the region number. For (3) type
+.sp -0.25v
+.PP
+   delete
+.PP
+.sp -0.25v
+then give the region number when asked. 
+This region will be overwritten and its previous contents lost forever.
+
+\fBSubstep 4.3: Confirm your choices\fR
+.PP
+You have now reached the point of no return. You will be asked if you want to
+continue. \fBIf you do, the data in the selected region will be lost forever.\fR
+If you are sure, type:
+.PP
+   yes
+.PP
+and then ENTER. To exit the setup script without changing the
+partition table, hit CTRL-C.
+
+.IT "Reinstallation choice"
+If you chose an existing MINIX 3 partition, in this step you will be
+offered a choice between a Full install, which erases everything in the
+partition, and a Reinstall, which does not affect your existing \fI/home\fR
+partition. This design means that you can put your personal files on
+\fI/home\fR and reinstall a newer version of MINIX 3 when it is available
+without losing your personal files.
+
+.IT "Select the size of /home"
+The selected partition will be divided into three subpartitions: root, \fI/usr\fR,
+and \fI/home\fR. The latter is for your own personal files. Specify how much of the
+partition should be set aside for your files.
+You will be asked to confirm your choice.
+
+.IT "Select a block size"
+Disk block sizes of 1-KB, 2-KB, 4-KB, and 8-KB are supported, but
+to use a size larger than 4-KB you have to change a constant and recompile
+the system. If your memory is 16 MB or more, use the default (4 KB); 
+otherwise, use 1 KB.
+
+.IT "Wait for bad block detection"
+The setup script will now scan each partition for bad disk blocks. This will take
+several minutes, possibly 10 minutes or more on a large partition.
+Please be patient.
+If you are absolutely certain there are no bad blocks, you can kill each scan
+by hitting CTRL-C.
+
+.IT "Wait for files to be copied"
+When the scan finishes, files will be automatically copied from the CD-ROM to
+the hard disk. Every file will be announced as it is copied. 
+When the copying is complete, MINIX 3 is installed.
+Shut the system down by typing
+.PP
+   shutdown
+.PP
+Always stop MINIX 3 this way to avoid data loss as MINIX 3 keeps some files on
+the RAM disk and only copies them back to the hard disk at shutdown time.
+
+
+\fBTESTING\fR
+.nr a 0
+.PP
+This section tells you how to test your installation, rebuild the system after
+modifying it, and boot it later. To start, boot your new MINIX 3 system.
+For example, if you used controller 0, disk 0, partition 3, type
+.PP
+   boot c0d0p3
+.PP
+and log in as root. Under very rare conditions the drive number seen by the
+BIOS (and used by the boot monitor) may not agree with the one used by
+MINIX 3, in which case try other drive numbers.
+This is a good time to create a root password. See \fIman passwd\fR for help.
+
+.IT "Compile the test suite"
+To test MINIX 3, at the command prompt (#) type
+.PP
+   cd /usr/src/test
+.br
+   make
+.PP
+and wait until it completes all 40 compilations.
+Log out by typing CTRL-D,
+
+.IT "Run the test suite"
+To test the system, log in as bin (required) and type
+.PP
+   cd /usr/src/test
+.br
+   ./run
+.PP
+to run the test programs. They should all run correctly but they can take
+20 min on a fast machine and over an hour on a slow one.
+\fINote\fR: It is necessary to compile the test suite when running as root
+but execute it as bin in order to see if the setuid bit works correctly.
+
+.IT "Rebuild the entire operating system"
+If all the tests work correctly, you can now rebuild the system.
+Doing so is not necessary since it comes prebuilt, but
+if you plan to modify the system, you will need to know how to rebuild it.
+Besides, rebuilding the system is a good test to see if it works. Type:
+.PP
+   cd /usr/src/tools
+.br
+   make
+.PP
+to see the various options available. Now make a new bootable image by typing
+.PP
+   su
+   make clean
+   time make image
+.PP
+You just rebuilt the operating system, including all the kernel and user-mode
+parts. That did not take very long, did it?
+If you have a legacy floppy disk drive, you can make a
+bootable floppy for use later by inserting a formatted floppy and typing
+.PP
+   make fdboot
+.PP
+When you are asked to complete the path, type:
+.PP
+   fd0
+.PP
+This approach does not currently work with USB floppies since there is no MINIX 3 USB
+floppy disk driver yet. 
+To update the boot image currently installed on the hard disk, type
+.PP
+   make hdboot
+.PP
+
+.IT "Shut down and reboot the new system"
+To boot the new system, first shut down by typing:
+.PP
+   shutdown
+.PP
+This command saves certain files and returns you to the MINIX 3 boot monitor.
+To get a summary of what the boot monitor can do, while in it, type:
+.PP
+   help
+.PP
+For more details, see \fIwww.minix3.org/manpages/man8/boot.8.html\fR.
+You can now remove any CD-ROM or floppy disk and turn off the computer.
+
+.IT "Booting Tomorrow"
+.PP
+If you have a legacy floppy disk drive, the simplest way to boot MINIX 3 is by
+inserting your new boot floppy and turning on the power. It takes only a few seconds.
+Alternatively, boot from the MINIX 3 CD-ROM, login as bin and type:
+.PP
+   shutdown
+.PP
+to get back to the MINIX 3 boot monitor. Now type:
+.PP
+   boot c0d0p0
+.PP
+to boot from the operating system image file on
+controller 0, driver 0, partition 0.
+Of course, if you put MINIX 3 on drive 0 partition 1, use:
+.PP
+   boot c0d0p1
+.PP
+and so on.
+.PP
+A third possibility for booting is to make the MINIX 3 partition the active one,
+and use the MINIX 3 boot monitor to start MINIX 3 or any other operating system.
+For details
+see \fIwww.minix3.org/manpages/man8/boot.8.html\fR.
+.PP
+Finally, a fourth option is for you to install a multiboot loader such as
+LILO or GRUB (\fIwww.gnu.org/software/grub\fR).
+Then you can boot any of your operating systems easily. 
+Discussion of multiboot loaders is beyond the scope of this guide, but there
+is some information of the subject at \fIwww.minix3.org/doc\fR.
+
+\fBUSING A SIMULATOR\fR
+.nr a 0
+.PP
+A completely different approach to running MINIX 3 is to run it
+on top of another operating system instead of native on the bare
+metal. Various virtual machines, simulators, and emulators are
+available for this purpose. Some of the most popular ones are:
+
+   \(bu VMware (www.vmware.com)
+.br
+   \(bu Bochs (www.bochs.org)
+.br
+   \(bu QEMU (www.qemu.org)
+.sp 1v
+See the documentation for each of them. Running a program on a
+simulator is similar to running it on the actual machine, so you
+should go back to Part I and acquire the latest CD-ROM and continue
+from there.
+
Index: /trunk/minix/man/man8/shutdown.8
===================================================================
--- /trunk/minix/man/man8/shutdown.8	(revision 9)
+++ /trunk/minix/man/man8/shutdown.8	(revision 9)
@@ -0,0 +1,88 @@
+.TH SHUTDOWN 8
+.SH NAME
+shutdown \- graciously close the system down
+.SH SYNOPSIS
+.B shutdown
+.RB [ \-hrRmk ]
+.RB [ \-x
+.IR code ]
+.RI [ time-specification
+.RI [ message ]]
+.SH DESCRIPTION
+.B Shutdown
+is a program which allows a system operator to close down the system
+in an nice way. 
+.B Shutdown
+informs the users why and when the system is going down.  This warning
+is issued 10 minutes before shutdown time and every minute in the last
+5 minutes.  At this time (5 minutes),
+.B shutdown
+creates a file
+.B /etc/nologin
+to prevent new users from logging in.
+.PP
+.B Shutdown
+keeps a logfile of shutdowns.  Every shutdown is registered in 
+.BR /usr/adm/wtmp ,
+if this file exists, and by
+.BR syslog (3)
+(level
+.BR auth . notice ).
+After these actions, a call is done to
+.BR reboot (2)
+which actually brings the system down.
+.PP
+.I Time-specification
+may be something like
+.BR 15:00 ,
+.BR 15.00 ,
+.BR +15 ,
+or
+.B now
+for a shutdown at 3pm (twice), 15 minutes from now, or immediately.
+.PP
+The message may be used to describe why the system is going down, it may
+also be typed on standard input with the
+.B \-m
+option.
+.SH OPTIONS
+.TP
+.B \-h
+This flag prevents the system from rebooting after the shutdown.  The
+system can now be powered off.  This is the default.
+.TP
+.B \-r
+This flag indicates that the system should reboot after shutting down.
+.TP
+.B \-R
+Reboot the system by resetting it.  Normally the kernel will try to return
+to the Boot Monitor.  With
+.B \-R
+the system will receive a hardware reset.
+.TP
+.BI \-x " code"
+Halt the system and let the Monitor execute the given code as if typed at
+the monitor prompt.  You can for instance use
+.B "\-x 'boot hd0'"
+as a very fast way to reboot "from the top."
+.TP
+.B \-m
+Allows the operator to type a shutdown message on standard input, that will
+be added to the messages displayed on all terminals.
+.TP
+.B \-k
+This option gives the possibility of terminating an already started
+shutdown.  This is only possible if shutdown time has not yet arrived.
+.TP
+.B \-C
+Check if the system crashed.  This option is not used at shutdown time,
+but at reboot time.  It tells if the file systems should be checked by
+testing if the last entry in the wtmp file is a shutdown entry.  (A
+crude replacement for a file system clean flag.)
+.SH "SEE ALSO"
+.BR reboot (2),
+.BR syslog (3),
+.BR halt (8),
+.BR boot (8).
+.SH AUTHOR
+Edvard Tuinder (v892231@si.hhs.NL)
Index: /trunk/minix/man/man8/slip.8
===================================================================
--- /trunk/minix/man/man8/slip.8	(revision 9)
+++ /trunk/minix/man/man8/slip.8	(revision 9)
@@ -0,0 +1,82 @@
+.TH SLIP 8
+.SH NAME
+slip \- Serial Line IP
+.SH SYNOPSIS
+.B slip
+.I pseudo-ip-device
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+The
+.B slip
+program implements an Internet network connection over a bidirectional 8-bit
+transport, usually a serial line.  The protocol used for this connection is
+the Serial Line Internet Protocol, SLIP for short.
+.PP
+The
+.I pseudo-ip-device
+argument names one of the
+.B /dev/psip*
+devices that is offered by the MINIX 3 TCP/IP driver
+.BR inet (8).
+The
+.B slip
+program reads IP packets from standard input and writes them to the pseudo
+IP device, and reads packets from the pseudo IP device and writes them to
+standard output.  A typical use is like this:
+.PP
+.RS
+.nf
+.ft B
+{
+	stty raw 115200
+	slip /dev/psip2 &
+} </dev/tty01 >/dev/tty01
+.ft P
+.fi
+.RE
+.PP
+The SLIP protocol is just a very simple packet framing protocol.  It defines
+two characters as markers on a byte stream to frame packets.  SLIP does
+not implement any higher level addressing, error detection, or compression.
+Thanks to its simplicity it can be used under MINIX 3, any other system would
+prefer to use the Point-to-Point protocol: PPP.
+.PP
+The SLIP packet framing protocol as defined in RFC-1055 is as follows:
+.IP "\-"
+Packets are delimited by an END character, octal 300.  END is often send at
+the start of a packet too to reset the logic of the receiver, so that random
+noise isn't added to the beginning of a packet.
+.IP "\-"
+An ESC character (octal 333) is used to escape any END or ESC characters
+that may occur in an IP packet.  END and ESC are changed to ESC 334 and ESC
+335 in the data stream.  (Note that END doesn't occur within the data stream
+at all by escaping it this way, making finding the framing END easier.)
+.ig
+.PP
+The manual page
+.BR serial-ip (8)
+describes how to configure the MINIX 3 network devices to be used with a
+serial IP connection.
+..
+.SH FILES
+.TP \w'/dev/psip*'u+5n
+.B /dev/psip*
+Pseudo-IP devices for use by
+.BR slip .
+.SH "SEE ALSO"
+.ig
+.BR ppp (8).
+.br
+..
+.BR RFC-1055 .
+.SH NOTES
+Under MINIX 3
+.B slip
+forks in two to handle the two data streams in or out of the serial line.
+Under Minix-vmd it uses asynchronous I/O to handle the two streams within
+one program.
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man8/srccrc.8
===================================================================
--- /trunk/minix/man/man8/srccrc.8	(revision 9)
+++ /trunk/minix/man/man8/srccrc.8	(revision 9)
@@ -0,0 +1,33 @@
+.TH SRCCRC 8
+.SH NAME
+srccrc \- compute CRC checksums of the entire source tree
+.SH SYNOPSIS
+\fBsrccrc\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH OPTIONS
+.SH EXAMPLES
+.SH DESCRIPTION
+.PP
+\fISrccrc\fP traverses the entire /usr/include and /usr/src tree to run
+the crc command on all files found.  The result is a long list of
+filenames with their checksums.  The filenames are relative to /usr.
+.PP
+The command makes an effort to remove most junk files such as .o, .bak
+and files in bin directories.  It cannot find single binaries however, so
+you will have to run \fBmake clean\fP in /usr/src to be able to make a crc
+list that contains only source files.
+.PP
+Two crc files can be compared easily with the \fIdiff\fP command.  A crc
+list of the original source tree can be found in /usr/src/crclist.
+.SH "SEE ALSO"
+.BR crc (1).
Index: /trunk/minix/man/man8/sync.8
===================================================================
--- /trunk/minix/man/man8/sync.8	(revision 9)
+++ /trunk/minix/man/man8/sync.8	(revision 9)
@@ -0,0 +1,33 @@
+.TH SYNC 8
+.SH NAME
+sync \- flush the cache to disk
+.SH SYNOPSIS
+\fBsync\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "sync" "Write out all modified cache blocks"
+.SH DESCRIPTION
+.PP
+\s-1MINIX 3\s-1
+maintains a cache of recently used disk blocks.
+The 
+.I sync
+command writes any modified cache blocks back to the disk.
+This is essential before stopping the system, and should be done before
+running any
+.I a.out
+program that might crash.
+.SH "SEE ALSO"
+.BR sync (2),
+.BR update (8),
+.BR shutdown (8).
Index: /trunk/minix/man/man8/syslogd.8
===================================================================
--- /trunk/minix/man/man8/syslogd.8	(revision 9)
+++ /trunk/minix/man/man8/syslogd.8	(revision 9)
@@ -0,0 +1,211 @@
+.\" Copyright 1994 Dr. Greg Wettstein, Enjellic Systems Development.
+.\" May be distributed under the GNU General Public License
+.\" Sun Aug 30 11:35:55 MET: Martin Schulze: Updates
+.\"
+.\" from SYSKLOGD 8 "13 December 1995" "Version 1.3" "Linux System Administration"
+.\" Modified for Minix porting by G. Falzoni <gfalzoni@inwind.it>
+.\" $Id: syslogd.8,v 1.1 2006/04/03 14:59:51 beng Exp $
+.\"
+.\" Local macros
+.de Xr
+.BR \\$1 (\\$2)\\$3
+..
+.de LB
+.TP \\$1
+\\fB\\$2\\fR
+\\$3
+..
+.de LI
+.TP \\$1
+\\fI\\$2\\fR
+\\$3
+..
+.de LR
+.TP \\$1
+\\fR\\$2\\fR
+\\$3
+..
+.\" end local macros
+.TH SYSLOGD 8 "Jan. 23, 2000"
+.SH NAME
+.PP
+syslogd \- system logging daemon.
+.SH SYNOPSIS
+.PP
+.B syslogd
+.RB [ " \-d " ]
+.RB [ " \-f "
+.I config file
+]
+.RB [ " \-m "
+.I interval
+] 
+.RB [ " \-p"
+.IB port 
+]
+.RB [ " \-v " ]
+.LP
+.SH DESCRIPTION
+.PP
+System logging is provided by a version of 
+.BR syslogd (8)
+derived from the
+stock BSD sources.
+.B Syslogd
+provides the kind of logging that many modern programs use. Every logged
+message contains at least a time, a hostname field and a
+program name field, but that depends on how trusty the logging
+program is.
+.PP
+While the syslogd sources have been heavily modified a couple of notes
+are necessary.  First of all there has been a systematic attempt to
+insure that syslogd follows the default, standard BSD behavior.
+The second important concept to note is that this version of syslogd
+interacts transparently with the version of syslog found in the
+standard libraries, so you must insure that the correct versions are installed.
+.PP
+The main configuration file
+.I /etc/syslog.conf
+or an alternative file, given with the 
+.B "\-f"
+option, is read at startup.  Any line that begins with the hash mark
+(``#'') and empty lines are ignored. If an error occurs during parsing
+the whole line is ignored.
+.SH OPTIONS
+.PP
+.LB 9 "-d" "Turns on debug mode.
+When using debug mode, the daemon will not proceed to 
+.BR fork (2)
+to set itself in the background, but will stay in the
+foreground and write much debug information on the current tty. See the
+DEBUGGING section for more information.
+.LB 9 "\-f config file" "Specify an alternative configuration file instead of
+.IR /etc/syslog.conf ","
+which is the default.
+.LB 9 "\-m interval" "The syslogd logs a mark timestamp regularly. The default
+.I interval
+between two
+.I \-\- MARK \-\-
+lines is 20 minutes. This can be changed with this option.
+.LB 9 "\-p port" "You can specify an alternative port instead of
+.I syslog/udp
+default service.
+.LB 9 "\-v" "Print version and exit.
+.SH SIGNALS
+.PP
+.B Syslogd
+reacts to a set of signals. You may easily send a signal to it
+using the following:
+.IP
+kill -SIGNAL `cat /usr/run/syslogd.pid`
+.LB 9 SIGHUP "This lets syslogd perform a re-initialization.
+All open files are closed, the configuration file (default
+is '/etc/syslog.conf') will be reread.
+.LB 9 SIGTERM "The syslogd will die.
+.LB 9 "SIGINT SIGQUIT" "If debugging is enabled these are ignored, otherwise 
+syslogd will die.
+.LB 9 SIGALRM "Every time syslogd receives this signal it will log
+the mark line.  Normally this is done by 
+.Xr alarm 2 .
+.SH CONFIGURATION FILE SYNTAX DIFFERENCES
+.PP
+.B Syslogd
+uses a slightly different syntax for its configuration file than
+the original BSD sources. Originally all messages of a specific priority
+and above were forwarded to the log file.
+.PP
+For example see the following sample file 
+.IP
+## Sample syslog.conf
+
+##  Emergency messages (system may be unusable)
+.br
+*.emerg                                 *
+.br
+*.alert                                 /dev/log
+
+## High severity errors
+.br
+*.alert;*.crit                          /usr/adm/syslog
+
+## every other message (errors/warning and informational)
+.br
+*.info;*.notice;*.warning;*.err         /usr/adm/messages
+.br
+*.debug					/usr/adm/debug 
+
+.SH SUPPORT FOR REMOTE LOGGING
+.PP
+Not implemented.
+.SH OUTPUT TO NAMED PIPES (FIFOs)
+.PP
+Not implemented.
+.SH INSTALLATION CONCERNS
+.PP
+There is probably one important consideration when installing this
+version of syslogd.  This version of syslogd is dependent on proper
+formatting of messages by the syslog function.
+.PP
+.B Syslogd
+should be started by the rc sequence.
+.SH DEBUGGING
+.PP
+When debugging is turned on using
+.B "\-d"
+option and syslogd is compiled with debug=1 then syslogd 
+will be very verbose by writing much of what it does on stdout. 
+Whenever
+the configuration file is reread and re-parsed you'll see a tabular,
+corresponding to the internal data structure. This tabular consists of
+four fields:
+.TP
+.I number
+This field contains a serial number starting by zero. This number
+represents the position in the internal data structure (i.e. the
+array). If one number is left out then there might be an error in the
+corresponding line in
+.IR /etc/syslog.conf .
+.TP
+.I pattern
+This field is tricky and represents the internal structure
+exactly. Every column stands for a facility (refer to
+.BR syslog (3)).
+As you can see, there are still some facilities left free for former
+use, only the left most are used. Every field in a column represents
+the priorities (refer to
+.BR syslog (3)).
+.TP
+.I action
+This field describes the particular action that takes place whenever a
+message is received that matches the pattern. Refer to the
+.BR syslog.conf (5)
+manpage for all possible actions.
+.TP
+.I arguments
+This field shows additional arguments to the actions in the last
+field. For file-logging this is the filename for the logfile; for
+user-logging this is a list of users; for remote logging this is the
+hostname of the machine to log to; for console-logging this is the
+used console; for tty-logging this is the specified tty; wall has no
+additional arguments.
+.PP
+Note that if syslogd is compiled with debug=0 only a subset is printed.
+.SH FILES
+.PP
+.LR 28 /etc/syslog.conf "Configuration file for syslogd.  See
+.Xr syslog.conf 5
+for exact information.
+.LR 28 /dev/log "The log device (console) for Minix.
+.LR 28 /usr/run/syslogd.pid "The file containing the process id of syslogd.
+.SH BUGS
+.PP
+If an error occurs in one line the whole rule is ignored.
+.B Syslogd
+doesn't change the filemode of opened logfiles at any stage of
+process. If a file is created it is world readable. If you want to
+avoid this, you have to create it and change permissions on your own.
+.SH SEE ALSO
+.BR syslog.conf (5),
+.BR logger (1),
+.BR syslog (3).
+.\" .BR services (5),
Index: /trunk/minix/man/man8/update.8
===================================================================
--- /trunk/minix/man/man8/update.8	(revision 9)
+++ /trunk/minix/man/man8/update.8	(revision 9)
@@ -0,0 +1,29 @@
+.TH UPDATE 8
+.SH NAME
+update \- periodically write the buffer cache to disk
+.SH SYNOPSIS
+\fBupdate\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH EXAMPLES
+.EX "update &" "Start a process that flushes the cache"
+.SH DESCRIPTION
+.PP
+When the system is booted,
+.I update
+is started up in the background from 
+.I /etc/rc
+to issue a 
+\&SYNC
+system call every 30 sec.
+.SH "SEE ALSO"
+.BR boot (8).
Index: /trunk/minix/man/man8/usage.8
===================================================================
--- /trunk/minix/man/man8/usage.8	(revision 9)
+++ /trunk/minix/man/man8/usage.8	(revision 9)
@@ -0,0 +1,969 @@
+.TH USAGE 8
+.SH NAME
+usage \- installing and using MINIX
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.de XB	\" An example in bold print.
+.RS
+.nf
+.ft B
+\&\\$1
+.ft R
+.fi
+.RE
+..
+.de 3A	\" Three Letter Acronym at 1 point size smaller.
+\&\\$3\s-1\\$1\s+1\\$2
+..
+.de 3B	\" TLA in bold.
+\&\\$3\fB\s-1\\$1\s+1\fR\\$2
+..
+This manual page describes the installation and use of MINIX from a
+System Administrators point of view.  It contains an installation guide,
+instructions on how to do the initial configuration and some other info.
+Please read this document entirely before attempting to install MINIX.
+The installation steps are in the proper order, but not all the
+information you may need is presented at the right moment.
+Other detailed information that may be useful can be found in
+.BR boot (8),
+.BR hier (7),
+and in
+.BR dosminix (8)
+if you run MINIX under DOS.
+.SS "1. MINIX UNDER DOS"
+Installation of MINIX to run under DOS is a nonevent.  Chances are, you are
+reading this manual page from an already running MINIX system, but if not
+then the setup goes like this:
+.PP
+Unpack the DOSMINIX.ZIP file using one of the popular ZIP utilities, such as
+PKZIP or WinZIP.  Next reboot Windows and hit F8 just when you see the
+"Booting Windows" message.  From the menu that appears choose "Command
+prompt only", or if that doesn't work "Safe mode command prompt only".  Under
+Windows Me you can use a startup disk to boot the PC into DOS.  Move
+to the directory containing the MINIX files and type:
+.PP
+.XB "boot minix.mnx"
+.PP
+Type '=' and presto, you are running MINIX.  Most of the rest of this manual,
+which deals mainly with running MINIX in a true hard disk partition, does
+not apply to you.  Your system is already installed completely, with all
+binaries and sources present, so all the talk about getting MINIX on your
+disk can be skimmed over.  Pay attention again when the focus shifts to the
+configuration of the system.  Section 9 is where this happens first.  (The
+main challange to a DOS installation is to figure out which parts of the
+installation manual do not apply.)
+.SS "2. REQUIREMENTS"
+The minimum system MINIX can be installed on comfortably is an IBM PC/AT
+or PS/2 with a 286 processor, 2 MB memory, a 720 kb diskette drive, and 35
+MB free space on an AT,
+ESDI, or SCSI hard disk (the latter controlled by an Adaptec 1540.)  MINIX
+for the 386 (MINIX-386 for short) can be installed on a machine with at
+least a 386sx processor, 3 MB memory and at least 35 MB of disk space.
+.PP
+The minimum system MINIX can be installed on
+.BR un comfortably
+is an IBM PC/XT with 640 kb memory.  MINIX-386 can more or less run in 2
+MB memory.  See sections 16 and 17 on "low memory" issues.
+.SS "3. MINIX INSTALLATION BACKGROUND"
+The objective of the installation is to create a partition on your disk
+and to put MINIX into it.  MINIX really requires at least two partitions
+however, so the single "primary" partition is split into two or three
+subpartitions.
+The
+.B s0
+subpartition will contain the root file system, the
+.B s1
+subpartition may optionally contain swapspace, and the
+.B s2
+subpartition will contain the
+.B /usr
+file system.  What Windows calls
+"drives", i.e C:, D:, E:, MINIX calls "file systems".  MINIX does not use
+drive letters, but requires that one file system is made a part of another
+file system by "mounting" one on the other.  The "root" file system is
+always present and starts with the directory "/", the root of the directory
+tree.  The root file system contains a few programs in
+.BR /bin ,
+device files in
+.BR /dev ,
+and configuration files in
+.BR /etc .
+This is just enough to get the system started.  MINIX will soon extend
+its directory tree by mounting a file system on the
+.B /usr
+directory.  What is henceforth known as the /usr file system contains all
+MINIX programs in
+.BR /usr/bin ,
+file system sources in
+.BR /usr/src ,
+etc, etc.
+The \s-2ROOT.MNX\s+2 image contains the complete MINIX root file system, but
+\s-2USR\s+2 contains just a small subset of the /usr file system, with just
+enough utilities to install MINIX.  The complete /usr file system is
+split up into the \s-2USR.TAZ\s+2, \s-2SYS.TAZ\s+2 and \s-2CMD.TAZ\s+2
+archives that are installed later to fill /usr.
+.PP
+Let's suppose your first hard disk, which has
+device name
+.BR /dev/c0d0 ,
+has Windows already present in the first primary partition
+.RB ( /dev/c0d0p0 ),
+and some free space left after that.  After MINIX is installed in that
+free space the disk will look like this:
+.PP
+.nf
+.in +4n
+.ta +\w'/dev/c0d0p1s0mmmm'u
+/dev/c0d0	Whole hard disk #0
+/dev/c0d0p0	Windows C: drive
+/dev/c0d0p1	MINIX primary partition
+/dev/c0d0p1s0	MINIX root partition
+/dev/c0d0p1s1	MINIX swap partition (optional)
+/dev/c0d0p1s2	MINIX /usr partition
+.in -8n
+.fi
+.PP
+/dev/c0d0 is the sum of a partition table, /dev/c0d0p0 and /dev/c0d0p1.
+Likewise is /dev/c0d0p1 the sum of a subpartition table, /dev/c0d0p1s0 and
+/dev/c0d0p1s2.  Read the "DEVICES" sections for more information on MINIX
+devices.
+.SS "4. INSTALLATION"
+.ig \" Only relevant when on CD-ROM.
+If you have not already copied MINIX to floppy disks, please read
+the README.TXT file in the MINIX directory now, for it tells how to do this.
+You should also print out EXAMPLE.TXT and read it in parallel with this
+document.  This one tells you what to do; that one shows you what the
+screen is supposed to look like at each step, so you can see if everything
+is OK.
+.PP
+..
+You can install MINIX automatically or manually as described in the sections
+below.  The end result is the same, but manual installation allows
+one to deviate from the preconfigured choices.  You may wish to read the
+manual pages of the programs used below before you start.  You may especially
+want to read
+.BR boot (8)
+if your machine is different from what the majority buys, because you
+may need to set a few boot parameters to configure drivers.  To do this type
+.B ESC
+to get to the Boot Monitor prompt, set the appropriate variables, use
+.B save
+to store the settings and
+.B menu
+to continue where you left off.
+.PP
+To install the system you need two diskettes: a bootable root diskette and a
+diskette full of binaries to use as
+.BR /usr .
+These diskettes are named
+.B \s-2ROOT\s+2
+and
+.BR \s-2USR\s+2 .
+These two diskettes may also be combined on a single high density diskette.
+In that case the \s-2USR\s+2 part is on the
+.B p2
+partition.
+.PP
+Insert the \s-2ROOT\s+2 diskette, boot the machine and type '=' to the menu.
+The MINIX kernel is loaded and takes control when you see the copyright
+banner.  After loading the root diskette into the RAM disk you will be asked
+to finish the name of the device to mount on
+.BR /usr .
+Type
+.BR fd0p2
+for a diskette that contains both \s-2ROOT\s+2 and \s-2USR\s+2, otherwise
+replace \s-2ROOT\s+2 by \s-2USR\s+2 and type
+.BR fd0 .
+Login as
+.BR root .
+.SS "5. AUTOMATIC INSTALLATION"
+Before starting the installation, you must either have a free partition
+available or have at least 35 MB not in any partition so you can create
+a MINIX partition.
+.PP
+Type
+.B setup
+to start the installation script.  First it offers to install a national
+keyboard map.  The names should be clear, except for
+.BR us-swap ,
+which swaps the CTRL and CAPS LOCK keys of a standard US style keyboard
+for people who believe that the natural place of CTRL is next to A.
+The default suggested between [ and ] is the US standard keyboard.
+.PP
+The next thing to do is to make a partition, for this you are placed in a
+partition table editor named
+.BR part .
+This partition table editor is very easy to use (in the author's opinion),
+but you will probably hate it.  You can move all over the place with the
+arrow keys, change values, and make a mess of your partition table real quick.
+So if you get into trouble, type 'q' to quit, 'n' to not write the table,
+and RETURN to start over.  Use the '?' key to get help.
+.PP
+With the '+' and '\-' keys you can select the disk device to install on,
+probably
+.BR /dev/c0d0 ,
+the first hard disk.  Type 'r' to load the partition table of the selected
+disk.  Either create one new partition by modifying a partition marked
+"None", or reuse an existing partition by changing its type to "MINIX" (hex
+code 81).  DO NOT use part to shrink an existing partition!  It will destroy
+all data in that partition.  MINIX needs a partition of at least 20 MB, but
+not larger than 128 MB (MINIX-86) or 1 GB (MINIX-386).  The system needs 35
+MB in compiled state.
+.PP
+The script then wants to know the name of the partition you've created.  The
+partition name is probably still visible on the screen.  Combined with the
+drive name you have to type c0d0p1, c0d2p0 or something.
+.PP
+The next question is the amount of swapspace you want to give MINIX.  There
+will be a suggested value based on the amount of memory your system has.
+If you have more then enough memory then don't bother with swap.  MINIX
+doesn't handle it very well yet, or ever, only memory starved systems need it
+so that
+.B "make world"
+can run.
+.PP
+The new partition table is reloaded into the disk driver, and the
+new MINIX partition is carved up into two or three subpartitions, a 1440 kb
+root, maybe some amount of swap, and the rest for /usr.
+.PP
+After making /usr, it is immediately put to use to replace the installation
+/usr file system so that you can remove the \s-2USR\s+2 diskette and insert
+the \s-2ROOT\s+2 diskette (unless they are one and the same).  The root file
+system is filled with the contents of the \s-2ROOT\s+2 diskette and slightly
+patched up to work on the hard disk (/etc/fstab.)
+.PP
+You can now skip the next section and move to "TESTING", but it may be
+instructive to read it anyway.
+.SS "6. MANUAL INSTALLATION"
+The instructions that follow are at a very low level and require you to be
+very careful.  The big advantage is that you know precisely what
+tools have been used and how everything works.  The disadvantage is that
+you may easily make a mistake that either forces you to start over if you
+are lucky, or wipes out the contents of your hard disk if you are not.
+Only if you really want to do something different should you use a manual
+installation.  Slavishly following the steps shown below will only make
+you end up with the same result as an automatic installation.
+.PP
+Run
+.B part
+to make partitions to load the system into.  The best thing to do is to make
+one large primary partition of type "MINIX" and to carve this partition up
+into three subpartitions for root, swap and /usr.  The assumption is that you
+will use the second partition on the first hard disk,
+.BR /dev/c0d0p1 ,
+and that
+.B c0d0p1s0
+is the root subpartition,
+.B c0d0p1s1
+is swap and
+.B c0d0p1s2
+is /usr.  If you want to use the first partition on
+the second hard disk for instance, then substitute c0d1p0 and c0d1p0s[012] for
+the above.  See the section on devices below, and the manual
+pages of
+.BR part (8)
+and
+.BR controller (4).
+Start
+.B part
+and select the disk that you
+want to install MINIX onto.  In our example it will be
+.BR /dev/c0d0 .
+.PP
+Use
+.B part
+to make a single partition in the primary partition table of type "MINIX",
+then hit '>' on this new partition to make a subpartition table.
+.PP
+For the root subpartition you are advised to use 1440 kb exactly.  You can
+make it larger if you want to, but it is advisable never to let the contents
+outgrow a floppy.  (The \s-2ROOT\s+2 diskette is a copy of a root file
+system, and will be used to fill your root subpartition.)
+.PP
+The second subpartition is for swapspace.  You can use it to enlarge the
+amount of total memory (real + swap) if your system has less than 2M
+(16-bit mode) or 4M (32-bit mode).  Note that only one MINIX swap partition
+is needed on your system, so if you have another MINIX partition then you can
+use its swap partition instead.
+.PP
+Use the rest of the partition for
+.BR s2 ,
+the /usr subpartition.
+.PP
+When you are done check that /dev/c0d0p1s0 is active (the * after the partition
+number) so you can boot from it later.
+.PP
+If your disk has bad blocks then don't put the root or swap subpartition
+on top of them.  Make sure the inode tables in the other partitions don't
+have bad blocks either.  You can put the subpartitions out of order on the
+disk if that helps.  Subpartition tables, unlike the main partition
+table, are not sorted by the driver.
+.PP
+After making the partitions you do not have to reboot.  The disk driver
+reloads the partition tables on the next access if the disk is not in use.
+(Open or mounted.)
+.PP
+To be able to boot from /dev/c0d0p1s0 you must place a master bootstrap in
+/dev/c0d0p1.  It has been placed there by
+.B part
+if it told you that it was creating a new partition table, but
+.PP
+.XB "installboot\0\-m\0/dev/c0d0p1\0/usr/mdec/masterboot"
+.RE
+.PP
+will put it there for sure.
+.PP
+Let's start by initializing the swap partition first, if you allocated one.
+We may need it already, so mount it.
+.PP
+.XB "mkswap\0/dev/c0d0p1s1"
+.XB "mount\0\-s\0/dev/c0d0p1s1"
+.PP
+Next make a file system for on-disk /usr and copy the floppy /usr on to it.
+.PP
+.XB "mkfs\0/dev/c0d0p1s2"
+.XB "readall\0\-b\0/dev/c0d0p1s2 | sh"
+.XB "mount\0/dev/c0d0p1s2\0/mnt"
+.XB "cpdir\0\-v\0/usr\0/mnt"
+.PP
+This will create a file system on /dev/c0d0p1s2, mount it on /mnt, and copy the
+contents of the \s-2USR\s+2 floppy onto it.  The call to
+.B readall
+marks bad blocks on the file system as unusable, you can omit this on a
+drive known to be spotless (\s-2IDE\s+2 or \s-2SCSI\s+2.)
+.PP
+You can now use the new /usr in place of the \s-2USR\s+2 floppy:
+.PP
+.XB "umount\0/dev/c0d0p1s2"
+.XB "umount\0/dev/fd0\0\0\0\0\0\0\0\0\0# fd0p2 if combined"
+.XB "mount\0/dev/c0d0p1s2\0/usr"
+.PP
+This little dance has freed up your floppy drive, so please remove the
+\s-2USR\s+2 diskette and replace it by the \s-2ROOT\s+2 diskette.  Make a
+file system for the root with at least 512 inodes (files), and
+fill it from the floppy:
+.PP
+.XB "mkfs\0\-i\0512\0/dev/c0d0p1s0"
+.XB "mount\0/dev/fd0\0/fd0"
+.XB "mount\0/dev/c0d0p1s0\0/mnt"
+.XB "cpdir\0\-v\0/fd0\0/mnt"
+.XB "umount\0/dev/fd0"
+.PP
+Remove
+.B /mnt/etc/issue
+to get rid of the "use setup" message that greets you when you boot, and
+edit the file
+.B /mnt/etc/fstab
+to name the devices MINIX has been installed on.  In our example it
+should look like this:
+.PP
+.XB "root=/dev/c0d0p1s0"
+.XB "swap=/dev/c0d0p1s1"
+.XB "usr=/dev/c0d0p1s2"
+.PP
+Unmount the new root:
+.PP
+.XB "umount\0/dev/c0d0p1s0"
+.PP
+Make it bootable:
+.PP
+.XB "installboot\0\-d\0/dev/c0d0p1s0\0/usr/mdec/bootblock\0boot"
+.PP
+The automatic script would now set the
+.B rootdev
+and
+.B ramimagedev
+boot variables.  You can do this now using the
+.B edparams
+command, but it is easier to postpone it until the testing phase.  The
+settings should be:
+.PP
+.XB "rootdev=c0d0p1s0"
+.XB "ramimagedev=c0d0p1s0"
+.SS "7. TESTING"
+By now a new MINIX system is present on your hard disk.  Time to see if
+it works.  Leave the \s-2ROOT\s+2 diskette in the drive and type
+.BR halt .
+You are now going to use the power of the Boot Monitor on the diskette to
+boot the MINIX partition on the hard disk.  Use the monitor command
+.B boot c0d0p1
+to boot the primary partition MINIX has been installed in.  (It is "c0d0p1" in
+our example.)
+.PP
+The hard disk bootstrap is now showing the menu again.  You can type '='
+to start MINIX, but you probably want to change the boot parameters.
+Hit
+.B ESC
+once more to get to the command prompt.  The command
+.B set
+shows what the current parameters are.  Here is an example that shows how
+to make a menu to either start MINIX or boot Windows:
+.PP
+.XB "minix(=,Minix)\0boot"
+.XB "win(w,Windows)\0boot\0c0d0p0"
+.XB "save"
+.PP
+Windows is assumed to be in the first partition in the example above (c0d0p0).
+When finished type
+.B menu
+to see if the menu looks right.  If so hit '=' to start MINIX.  Log in as
+root.
+.SS "8. ADDING PROGRAMS AND SOURCES TO /usr"
+The
+.B setup
+command can also be used to add files from floppy sets to the system.  The
+.B \s-2USR.TAZ\s+2
+(programs and stuff),
+.B \s-2SYS.TAZ\s+2
+(system sources), and
+.B \s-2CMD.TAZ\s+2
+(commands sources)
+are all installed relative to the
+.B /usr
+directory, so the command to use three times is
+.PP
+.XB setup\0/usr
+.PP
+.B Setup
+will ask for the size of data on the floppies, which is by default simply
+the entire floppy.  You will see some "Cannot make directory" errors
+while extracting, as some directories already exist.  Ignore these messages.
+You need the
+.B \s-2USR.TAZ\s+2
+set if you want a working MINIX system,
+.B \s-2SYS.TAZ\s+2
+if you want recompile the system or study it, and
+.B \s-2CMD.TAZ\s+2
+if you also want the sources of the commands.  On a disk space
+starved machine you could opt to do without the commands sources, as they
+are not absolutely necessary to understand MINIX.
+.PP
+If your machine does not have enough memory to run
+.B setup\0/usr
+then type these commands manually:
+.PP
+.XB "cd\0/usr"
+.XB "vol\0/dev/fd0 | zcat | tar\0xvfp\0\-"
+.PP
+If
+.3B USR.TAZ
+is already present on the hard disk in an
+.3A DOS
+or Windows partition, then this command can be used under MINIX-386 to
+extract it to avoid the floppy detour:
+.PP
+.XB "cd\0/usr"
+.XB "mtools\0copy\0c0d0p0:USR.TAZ\0\- | setup\0/usr"
+.PP
+In 16-bit mode you don't have mtools, but maybe dosread will work:
+.PP
+.XB "cd\0/usr"
+.XB "dosread\0c0d0p0\0USR.TAZ | setup\0/usr"
+.PP
+The file doesn't have to be in the root directory of
+.BR c0d0p0 ,
+of course,
+.B "c0d1p0:/TMP/USR.TAZ"
+would name a file on the first partition of the second hard disk in the
+directory
+.BR \eTMP .
+.PP
+The /usr file system can also be filled through a network from a remote host
+if MINIX if you can get networking going with the NET.TAZ supplement.  Use
+.B "setup\0/"
+to install NET.TAZ (note that it goes into / instead of /usr), then
+follow the instructions in
+.BR boot (8)
+to configure TCP/IP and boot MINIX.  There are now two ways to fill
+/usr.  One is to add the host name and login name of a remote host and a
+remote user to
+.BR /.rhosts ,
+as root, and to use the following command on the remote host:
+.PP
+.XB "rsh\0\-l\0root\0\fIminix-box\fP\0setup\0/usr\0< USR.TAZ"
+.PP
+Two is to use
+.B urlget
+to copy the data directly from a Web or FTP site by using these
+commands under MINIX:
+.PP
+.XB "cd\0/usr"
+.XB "urlget\0\fIurl\fP.../USR.TAZ | setup\0/usr"
+.PP
+The sources may be installed using exactly the same commands, but with
+.3B USR.TAZ
+replaced by
+.3B SRC.TAZ .
+Note that this means that the sources must also be extracted relative to
+.BR /usr .
+.SS "9. NAMES"
+A standalone machine will have to be given a name.  As
+.B root
+type
+.PP
+.XB "echo\0\fIname\fB\0>/etc/hostname.file"
+.PP
+to change the host name of your machine to
+.IR name .
+.SS "10. ACTIVE ON BOOT"
+You may want to make the MINIX partition active so that it is automatically
+booted.  With Windows
+.B fdisk
+or MINIX
+.BR part ,
+mark the primary partition that contains MINIX active.  Using the menu you
+made earlier you can boot either MINIX or Windows at a keypress.  You can even
+set timeouts.  To boot MINIX automatically after 5 seconds:
+.PP
+.XB "main()\0{trap\05000\0minix;\0menu}"
+.PP
+See
+.BR monitor (8)
+for all the details on the monitor.
+.PP
+If you don't trust this then you can rig up a diskette that boots the MINIX
+partition when left in the drive:
+.PP
+.XB "installboot\0\-m\0/dev/fd0\0/usr/mdec/jumpboot\0010"
+.PP
+The numbers 010 indicate the device (disk or partition) that must be booted,
+i.e.
+.B /dev/c0d0p1s0
+in this example.  Take the name of the device, and use the disk, partition
+and subpartition numbers, or less.  So c0d1p2s0 -> 120, c0d3 -> 3,
+c0d2p0 -> 20.)
+.SS "11. DEVICES"
+A crash course on the MINIX devices in
+.BR /dev :
+The first two hard disks are named
+.BR c0d0
+and
+.BR c0d1 .
+These devices address the entire hard disk, from the
+first to the last byte.  Each disk has four partitions, for disk 0 they are
+.BR c0d0p0 ,
+.BR c0d0p1 ,
+.BR c0d0p2 ,
+and
+.BR c0d0p3 .
+And for disk 1 they are named
+.BR c0d1p0
+to
+.BR c0d1p3 .
+These partitions may contain file systems,
+.B c0d0p0
+often contains the
+.3A MS-DOS
+or Windows "C:" file system.  MINIX can use these partitions
+for file systems too, but you can also partition one of these "primary
+partitions" into four so-called "subpartitions".  The subpartitions of
+.B c0d0p0
+are named
+.BR c0d0p0s0 ,
+.BR c0d0p0s1 ,
+.BR c0d0p0s2 ,
+and
+.BR c0d0p0s3 .
+The other partitions may have four subpartitions that are named in the same
+way.  See
+.BR controller (4)
+for an elaborate description.
+.PP
+You may need to add devices to
+.BR /dev ,
+because not all devices are present to keep down the clutter.
+The command
+.3B MAKEDEV
+knows how to make devices, and
+.3B DESCRIBE
+can tell you what an unknown device may be, or even what all devices in
+.B /dev
+may be if called without arguments.  Devices are described in
+.BR dev (4),
+with pointers to more specific pages.
+.SS "12. EDITORS"
+The editors available are
+.B elvis
+(a
+.B vi
+clone),
+.B elle
+(a simple
+.B emacs
+clone),
+and the old MINIX
+.B mined
+editor.  Of these editors only elvis can recover your file after a system
+crash.  Only
+.B mined
+is available at installation time.  (All you need to know about mined right
+now is that CTRL-X gets you out of it.)
+.SS "13. BOOT MONITOR VS. MINIX"
+The Boot Monitor uses the
+.3A BIOS
+to address disks, so it has no idea of controllers, it just lumps everything
+together and ignores controller numbers.  So what the monitor thinks are
+.BR d0 ,
+.BR d1 ,
+and
+.BR d2 ,
+may be
+.BR c0d0
+(IDE primary master),
+.BR c0d2
+(IDE secondary master), and
+.BR c1d3
+(SCSI disk at target 3).
+One must keep this in mind when MINIX is installed on a disk other than the
+very first.  So if MINIX is installed in the third partition of the SCSI disk,
+then
+.B "boot d2p2"
+will boot it, and
+.B "rootdev=c1d3p2s0"
+will tell MINIX where its root file system is.
+.SS "14. NATIONAL KEYBOARDS"
+The directory
+.B /usr/lib/keymaps
+contains keymap tables for several national keyboards.  If you have a German
+keyboard for instance, then
+.PP
+.XB "loadkeys\0/usr/lib/keymaps/german.map"
+.PP
+will load the German key translation table into the keyboard driver.  Copy
+the map to
+.B /etc/keymap
+once MINIX is installed on the hard disk, because having to type a key
+sequence like one of these:
+.PP
+.XB "loadkezs\0\-usr\-lib\-kezmaps\-german.map"
+.XB "loqdkeys\0=usr=lib=key,qps=french.,qp"
+.PP
+on a reboot gets a bit annoying after a while.  Send corrections and new
+keymaps to the person named below.  (Do not send a Dutch keymap, buy
+yourself a real keyboard instead.)
+.SH SUGGESTIONS
+Below are a few useful suggestions.  Some of the information can be of use
+in other situations than described here.
+.SS "15. VIRTUAL CONSOLES"
+Hold down the ALT key and press the left or right arrow key, F1, or F2.
+This switches the console between two login sessions.  (Unless you have
+an old mono adapter, because virtual consoles sit in video memory, and
+a mono adapter only has memory for one.)
+.PP
+Note that kernel messages, including function key output, only appear on
+the first console.  This may be confusing, but it keeps the other consoles
+clean.
+.SS "16. LOW ON MEMORY"
+The normal installation requires that you have enough memory for a large RAM
+disk.  You can still install MINIX normally if you either have a high density
+diskette drive for a combined root+usr floppy, or you have two floppy drives
+of at least 720 kb.  Before booting you have to set the variable
+.B rootdev
+to the same value as
+.BR ramimagedev .
+This is slower then a RAM disk, but saves a lot of memory.
+.PP
+The automatic installation script knows how to handle this new situation.
+If you install manually then you have to use
+.PP
+.XB "cpdir\0\-vx\0/\0/mnt"
+.PP
+to copy the root device to disk.  When it is time to fill /usr and you only
+have one floppy drive then hit DEL to get out of the installation script and
+reboot as described in "TESTING".  You can then finish the installation
+manually.
+.ig
+See the XT640K.TXT file for more advice on small machines.
+..
+.SS "17. LOW ON MEMORY AND ONLY ONE 720 KB FLOPPY DRIVE"
+If you only have one 720 kb floppy drive and your system is low on memory
+then you can use the \s-2TINYROOT.MNX\s+2 boot image.  This image contains a
+small kernel with only the BIOS disk driver, and a small root file system.
+You can use this disk to boot your machine.  Use the normal \s-2ROOT.MNX\s+2 to
+install the root file system.  Keep booting your machine with
+\s-2TINYROOT\s+2 until you have compiled a small kernel for your system.
+Use the
+.B rootdev
+boot variable to select the hard disk root file system.  Do
+.B not
+use \s-2TINYROOT\s+2 for anything other than booting, always use
+\s-2ROOT\s+2 when mentioned.
+.SS "18. FLOPPY DRIVE 1 IS A HIGH DENSITY DRIVE"
+If you would like to install from floppy drive 1 then you need to copy at
+least one sector from the \s-2USR\s+2 image onto a diskette for drive 0.
+The \s-2USR\s+2 bootstrap has been rigged to boot the other drive.
+.SS "19. INSTALLING ON A SECOND HARD DISK"
+MINIX doesn't care if it is installed on the second disk of a system with
+two disks.  The only problem is to get it booted.  You can either rig up
+a diskette to boot MINIX as shown earlier, or you can use the same trick
+on the first disk.  The command
+.PP
+.XB "installboot\0\-m\0/dev/c0d0\0/usr/mdec/jumpboot\01"
+.PP
+will lock the first disk into booting the second disk.  Note that this
+command modifies the disk outside a MINIX partition, overwriting a bit of
+code that has likely been put there by Windows fdisk.  First verify that the
+Boot Monitor can boot a Windows partition, because then the MINIX master
+bootstrap can do it too.
+.SS "20. LOTS OF MEMORY ON A 286"
+You will have a hard time making MINIX use up 3 MB memory.  Memory you
+can spare can be used for a "second level block cache" on the RAM disk.  The
+File System uses the second level cache to store copies of disk blocks that
+are pushed out of the normal (primary) block cache.  The size of the primary
+cache is compiled into the FS server, but the size of the second level cache
+can be set with the
+.B ramsize
+boot variable.  Set it to a number between 0 and 512.  512 kilobytes is
+enough to keep most of the compiler cached.
+.SS "21. LOTS OF MEMORY ON A 386+"
+Processes can be as big as you would like on a 386, but in practice 4 MB is
+a lot, and 8 MB is infinite.
+The installation script sets up a second level cache for MINIX-386
+of up to 1024 kilobytes.  This is because the default file system cache
+is only 80 kb.  Your first point of call is to get rid of the poorly
+performing second level cache by setting
+.B ENABLE_CACHE2
+to 0 and to assign the memory used by it to the
+normal block cache by enlarging the appropriate
+.B NR_BUFS
+and
+.B NR_BUF_HASH
+constants in <minix/config.h> with as much as you can spare.  (1024 for
+NR_BUFS is the minimum to keep
+.B "cc \-c"
+cached.  2048 is then a nice value for NR_BUF_HASH.)
+Disable the second level cache, compile a new kernel, reboot and set
+.B ramsize
+to 0.
+.SS "22. LOTS OF DISK SPACE"
+The maximum file system size is 1 GB for MINIX-386 and 128 MB for
+MINIX-86.  (MINIX-86 can handle larger file systems, but
+.B fsck
+can't check them.)  Note that a MINIX file system can only contain 65535
+inodes (files), so the average file should be 16 kb to completely fill it.
+It may be better to make two smaller file systems.  Besides, fsck takes
+forever on a large file system.
+.SH SYSTEM ADMINISTRATION
+The system has been set up with the idea that working as root is a bad thing
+to do.  As root you are in no way protected from doing stupid things.  So
+don't do development as root, but work as
+.BR bin !
+Only in exceptional cases do you want to become root.  Being root is fun for
+wannabe hackers; administrators know better.
+.PP
+To make life easier for bin, some programs like
+.BR su (1),
+.BR install (1)
+and
+.BR shutdown (8)
+treat bin and other members of the operator group as special and allow them
+the privileges of root.  (One is an operator if one's
+group id is zero.)  Operators should share the shadow password of root by
+having
+.B ##root
+in their password field.  This way they all have one face (password)
+to the outside world, forming no greater security risk than root alone.
+.PP
+The home directory of bin contains one important Makefile.  You can use it
+to recompile all the commands and libraries of the system.  Type
+.B make
+to see the usage message.  If you want to compile just one command then you
+can simply type
+.B make
+to do so.  To put it in its proper place you have to type
+.BR "make install" .
+Read the Makefiles in the
+.B commands
+and
+.B lib
+subdirectories to understand how everything is put together.  If you are
+tight on memory then
+.B make
+may fail to traverse down the source tree and also compile things.  You will
+have to type
+.B make
+in each subdirectory.  You can run make in /usr/src at the end to see if
+you've missed something or not.
+.PP
+The shell used by MINIX is a minimal version of
+.BR ash ,
+the BSD shell.  It has been modified to offer simple line editing using the
+.BR editline (3)
+library.
+.PP
+The kernel is not compiled from the master Makefile.  To make a new kernel
+you have to step into the
+.B tools
+directory.  There you can run four different make commands:
+.PP
+.TP
+.B make
+This makes all the different kernel parts and combines them in the file
+named
+.BR image .
+.TP
+.B make fdboot
+As above and then makes a boot floppy that you can use to restart your
+system with.  You are prompted for the floppy device name.
+.TP
+.B make hdboot
+First makes the image file and then copies it into the directory
+.BR /minix .
+If there are already two images in that directory then the newest image will
+be removed to make space for this newer image.  It is assumed that the
+oldest image is the most stable system image, one that always works, and
+that the newest image is experimental.  Check beforehand what
+.B /minix
+contains before you run
+.BR "make hdboot" .
+Remove the oldest image if you want another image to become the stable
+image.  The Boot Monitor chooses the newest image in
+.B /minix
+to boot.  You can use the monitor command
+.B ls minix
+to view the images present, and set the
+.B image
+variable to the full name of the image you want to use instead if the newest
+doesn't work.  The images in
+.B /minix
+are named using the MINIX release and version numbers with an extra revision
+number added to distinguish the images.
+.PP
+The first new kernel you would like to make is one configured for your
+system.  The kernel you are running now contains several drivers
+you don't need, or may be missing drivers that you might want.
+In <minix/config.h> you can find a number of
+.BI ENABLE_ XXX
+variables that can be set to
+.B 0
+to exclude, or
+.B 1
+to include a particular driver.  The full list of configurable parameters
+and what they do are described in
+.BR config (8).
+It is invaluable in figuring out what to change and how in <minix/config.h>.
+.PP
+Configuring a new kernel is sometimes not enough to enable new devices, you
+sometimes need to use the
+.B MAKEDEV
+command to make new device files in
+.BR /dev .
+For pseudo-ttys you also have to check if
+.B /etc/ttytab
+mentiones the new devices.
+.PP
+New additions to the system can be made in the
+.B /usr/local
+tree.  An empty directory tree has been set up for you and binaries and
+manual pages are already in the search paths.  You can make a new user entry
+with the
+.B adduser
+command.
+.PP
+The
+.B TZ
+variable in
+.B /etc/profile
+tells the time zone offset from the wall clock time to GMT.  You have to
+change it for your time zone.  (See
+.BR TZ (5).)
+.PP
+The function keys produce debug dumps, showing various interesting data
+about the system.  F1 lists processes and F5 shows ethernet stats, which
+may be of use now.  Read
+.BR console (4)
+to know all the details of the screen and keyboard.
+.SS "23. SYSTEM SHUTDOWN"
+You can't just turn a MINIX system off.  MINIX must be told to flush the
+modified data in the file system cache first.  The following
+commands/keystrokes can be used to exit MINIX properly:
+.TP
+.B shutdown
+First alert all users and then all processes of the impending shutdown
+then halt or reboot the system in one of various ways.  See
+.BR shutdown (8).
+.TP
+.B reboot / halt
+Alert all processes of the system shutdown then reboot or halt.
+.TP
+.B \s-2CTRL\-ALT\-DEL\s+2
+Halt the system by running
+.BR "shutdown \-h now" .
+.PP
+MINIX halts by returning to the Boot Monitor, MINIX reboots by instructing
+the monitor to reboot MINIX.  (MINIX is just a subprocess to the monitor.)
+Either halt MINIX and use monitor commands to escape MINIX, or use
+.B shutdown \-R
+to reset the system.
+.PP
+When exiting MINIX running under DOS the Boot Monitor's
+.B exit
+command will return you to the DOS prompt.  The Boot Monitor and MINIX
+are together just a pretty big DOS program as far DOS is concerned.
+.SH FILES
+.TP 12
+.B /usr/ast
+Honorary home directory of Andrew S. Tanenbaum.  Doubles as the place where
+the default setup for a new user is found.
+.SH "SEE ALSO"
+.BR dosminix (8),
+.BR monitor (8),
+.BR boot (8),
+.BR part (8),
+.BR mkfs (1),
+.BR mount (8),
+.BR M (8),
+.BR fstab (5),
+.BR hier (7),
+.BR config (8),
+.BR console (4),
+.BR dev (4),
+.BR adduser (8),
+.BR TZ (5),
+.BR mkdist (8),
+.BR shutdown (8).
+.br
+"Operating Systems \- Design and Implementation 2/e" by Andrew S. Tanenbaum
+and Albert S. Woodhull.
+.SH NOTES
+The notation
+.BI < file .h>
+refers to a C language include file in /usr/include.
+.PP
+.B Root
+and
+.B bin
+do not have the current directory in their program search path to avoid
+executing programs left around by malicious people.  This means that to run
+.B foo
+from the current directory,
+.B ./foo
+must be typed.
+.SH BUGS
+There are many PS/2 models, all different.  Some will run MINIX, some won't,
+some crippled if you lie to MINIX by setting
+.B processor
+to
+.BR 86 .
+Almost no PS/2 has a standard disk, so setting
+.B c0
+to
+.B esdi
+or
+.B bios
+will be necessary.
+.PP
+Except for the floppy driver, none of the DMA based drivers know about DMA
+being limited to a 24 bits address, i.e. the first 16 MB.  So under MINIX-386
+you run a slight risk that a
+.B tar
+or
+.B dd
+command may use a buffer above 16 MB for reading or writing to a character
+device.  This only happens if the low 16 MB is taken by some huge processes,
+and you have more than 16 MB, of course.
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/man/man9/as.9
===================================================================
--- /trunk/minix/man/man9/as.9	(revision 9)
+++ /trunk/minix/man/man9/as.9	(revision 9)
@@ -0,0 +1,412 @@
+.so mnx.mac
+.TH AS 9
+.\" unchecked (kjb)
+.CD "as \(en assembler"
+.SE "AS\(emASSEMBLER [IBM]"
+.SP 1
+.PP
+This document describes the language accepted by the 80386 assembler
+that is part of the Amsterdam Compiler Kit.  Note that only the syntax is
+described, only a few 386 instructions are shown as examples.
+.SS "Tokens, Numbers, Character Constants, and Strings"
+.PP
+The syntax of numbers is the same as in C.
+The constants 32, 040, and 0x20 all represent the same number, but are
+written in decimal, octal, and hex, respectively.
+The rules for character constants and strings are also the same as in C.
+For example, \(fma\(fm is a character constant.
+A typical string is "string".
+Expressions may be formed with C operators, but must use [ and ] for
+parentheses.  (Normal parentheses are claimed by the operand syntax.)
+.SS "Symbols"
+.PP
+Symbols contain letters and digits, as well as three special characters:
+dot, tilde, and underscore.
+The first character may not be a digit or tilde.
+.PP
+The names of the 80386 registers are reserved.  These are:
+.HS
+~~~al, bl, cl, dl
+.br
+~~~ah, bh, ch, dh
+.br
+~~~ax, bx, cx, dx, eax, ebx, ecx, edx
+.br
+~~~si, di, bp, sp, esi, edi, ebp, esp
+.br
+~~~cs, ds, ss, es, fs, gs
+.HS
+The xx and exx variants of the eight general registers are treated as
+synonyms by the assembler.  Normally "ax" is the 16-bit low half of the
+32-bit "eax" register.  The assembler determines if a 16 or 32 bit
+operation is meant solely by looking at the instruction or the
+instruction prefixes.  It is however best to use the proper registers
+when writing assembly to not confuse those who read the code.
+.HS
+The last group of 6 segment registers are used for selector + offset mode
+addressing, in which the effective address is at a given offset in one of
+the 6 segments.
+.PP
+Names of instructions and pseudo-ops are not reserved.  
+Alphabetic characters in opcodes and pseudo-ops must be in lower case.
+.SS "Separators"
+.PP
+Commas, blanks, and tabs are separators and can be interspersed freely 
+between tokens, but not within tokens.
+Commas are only legal between operands.
+.SS "Comments"
+.PP
+The comment character is \*(OQ!\*(CQ.  
+The rest of the line is ignored.
+.SS "Opcodes"
+.PP
+The opcodes are listed below.
+Notes: (1) Different names for the same instruction are separated by \*(OQ/\*(CQ.
+(2) Square brackets ([]) indicate that 0 or 1 of the enclosed characters 
+can be included.
+(3) Curly brackets ({}) work similarly, except that one of the
+enclosed characters \fImust\fR be included.
+Thus square brackets indicate an option, whereas curly brackets indicate
+that a choice must be made.
+.sp
+.if t .ta 0.25i 1.2i 3i
+.if n .ta 2 10 24
+.nf
+.B "Data Transfer"
+.HS
+	mov[b]	dest, source	! Move word/byte from source to dest
+	pop	dest	! Pop stack 
+	push	source	! Push stack 
+	xchg[b]	op1, op2	! Exchange word/byte 
+	xlat		! Translate 
+	o16		! Operate on a 16 bit object instead of 32 bit
+
+.B "Input/Output"
+.HS
+	in[b]	source	! Input from source I/O port
+	in[b]		! Input from DX I/O port
+	out[b]	dest	! Output to dest I/O port
+	out[b]		! Output to DX I/O port
+
+.B "Address Object"
+.HS
+	lds	reg,source	! Load reg and DS from source
+	les	reg,source	! Load reg and ES from source
+	lea	reg,source	! Load effect address of source to reg and DS
+	{cdsefg}seg		! Specify seg register for next instruction
+	a16		! Use 16 bit addressing mode instead of 32 bit
+
+.B "Flag Transfer"
+.HS
+	lahf		! Load AH from flag register
+	popf		! Pop flags 
+	pushf		! Push flags 
+	sahf		! Store AH in flag register
+
+.B "Addition"
+.HS
+	aaa		! Adjust result of BCD addition
+	add[b]	dest,source	! Add 
+	adc[b]	dest,source	! Add with carry 
+	daa		! Decimal Adjust after addition
+	inc[b]	dest	! Increment by 1
+
+.B "Subtraction"
+.HS
+	aas		! Adjust result of BCD subtraction
+	sub[b]	dest,source	! Subtract 
+	sbb[b]	dest,source	! Subtract with borrow from dest
+	das		! Decimal adjust after subtraction
+	dec[b]	dest	! Decrement by one
+	neg[b]	dest	! Negate 
+	cmp[b]	dest,source	! Compare
+
+.B "Multiplication"
+.HS
+	aam		! Adjust result of BCD multiply
+	imul[b]	source	! Signed multiply
+	mul[b]	source	! Unsigned multiply
+
+.B "Division"
+.HS
+	aad		! Adjust AX for BCD division
+	o16 cbw		! Sign extend AL into AH
+	o16 cwd		! Sign extend AX into DX
+	cwde		! Sign extend AX into EAX
+	cdq		! Sign extend EAX into EDX
+	idiv[b]	source	! Signed divide
+	div[b]	source	! Unsigned divide
+
+.B "Logical"
+.HS
+	and[b]	dest,source	! Logical and
+	not[b]	dest	! Logical not
+	or[b]	dest,source	! Logical inclusive or
+	test[b]	dest,source	! Logical test
+	xor[b]	dest,source	! Logical exclusive or
+
+.B "Shift"
+.HS
+	sal[b]/shl[b]	dest,CL	! Shift logical left
+	sar[b]	dest,CL	! Shift arithmetic right
+	shr[b]	dest,CL	! Shift logical right
+
+.B "Rotate"
+.HS
+	rcl[b]	dest,CL	! Rotate left, with carry
+	rcr[b]	dest,CL	! Rotate right, with carry
+	rol[b]	dest,CL	! Rotate left
+	ror[b]	dest,CL	! Rotate right
+
+.B "String Manipulation"
+.HS
+	cmps[b]		! Compare string element ds:esi with es:edi
+	lods[b]		! Load from ds:esi into AL, AX, or EAX
+	movs[b]		! Move from ds:esi to es:edi
+	rep		! Repeat next instruction until ECX=0
+	repe/repz		! Repeat next instruction until ECX=0 and ZF=1
+	repne/repnz		! Repeat next instruction until ECX!=0 and ZF=0
+	scas[b]		! Compare ds:esi with AL/AX/EAX
+	stos[b]		! Store AL/AX/EAX in es:edi
+
+.fi
+.B "Control Transfer"
+.PP
+\fIAs\fR accepts a number of special jump opcodes that can assemble to
+instructions with either a byte displacement, which can only reach to targets
+within \(mi126 to +129 bytes of the branch, or an instruction with a 32-bit
+displacement.  The assembler automatically chooses a byte or word displacement
+instruction.
+.PP
+The English translation of the opcodes should be obvious, with
+\*(OQl(ess)\*(CQ and \*(OQg(reater)\*(CQ for signed comparisions, and
+\*(OQb(elow)\*(CQ and \*(OQa(bove)*(CQ for unsigned comparisions.  There are
+lots of synonyms to allow you to write "jump if not that" instead of "jump
+if this".
+.PP
+The \*(OQcall\*(CQ, \*(OQjmp\*(CQ, and \*(OQret\*(CQ instructions can be 
+either intrasegment or
+intersegment.  The intersegment versions are indicated with 
+the suffix \*(OQf\*(CQ.
+
+.if t .ta 0.25i 1.2i 3i
+.if n .ta 2 10 24
+.nf
+.B Unconditional
+.HS
+	jmp[f]	dest	! jump to dest (8 or 32-bit displacement)
+	call[f]	dest	! call procedure
+	ret[f]		! return from procedure
+
+.B "Conditional"
+.HS
+	ja/jnbe		! if above/not below or equal (unsigned)
+	jae/jnb/jnc		! if above or equal/not below/not carry (uns.)
+	jb/jnae/jc		! if not above nor equal/below/carry (unsigned)
+	jbe/jna		! if below or equal/not above (unsigned)
+	jg/jnle		! if greater/not less nor equal (signed)
+	jge/jnl		! if greater or equal/not less (signed)
+	jl/jnqe		! if less/not greater nor equal (signed)
+	jle/jgl		! if less or equal/not greater (signed)
+	je/jz		! if equal/zero
+	jne/jnz		! if not equal/not zero
+	jno		! if overflow not set
+	jo		! if overflow set
+	jnp/jpo		! if parity not set/parity odd
+	jp/jpe		! if parity set/parity even
+	jns		! if sign not set
+	js		! if sign set
+
+.B "Iteration Control"
+.HS
+	jcxz	dest	! jump if ECX = 0
+	loop	dest	! Decrement ECX and jump if CX != 0
+	loope/loopz	dest	! Decrement ECX and jump if ECX = 0 and ZF = 1
+	loopne/loopnz	dest	! Decrement ECX and jump if ECX != 0 and ZF = 0
+
+.B "Interrupt"
+.HS
+	int	n	! Software interrupt n
+	into		! Interrupt if overflow set
+	iretd		! Return from interrupt
+
+.B "Flag Operations"
+.HS
+	clc		! Clear carry flag
+	cld		! Clear direction flag
+	cli		! Clear interrupt enable flag
+	cmc		! Complement carry flag
+	stc		! Set carry flag
+	std		! Set direction flag
+	sti		! Set interrupt enable flag
+
+.fi
+.SS "Location Counter"
+.PP
+The special symbol \*(OQ.\*(CQ is the location counter and its value 
+is the address of the first byte of the instruction in which the symbol 
+appears and can be used in expressions.
+.SS "Segments"
+.PP
+There are four different assembly segments: text, rom, data and bss.
+Segments are declared and selected by the \fI.sect\fR pseudo-op.  It is
+customary to declare all segments at the top of an assembly file like
+this:
+.HS
+~~~.sect .text; .sect .rom; .sect .data; .sect .bss
+.HS
+The assembler accepts up to 16 different segments, but
+.MX
+expects only four to be used.  Anything can in principle be assembled
+into any segment, but the
+.MX
+bss segment may only contain uninitialized data.
+Note that the \*(OQ.\*(CQ symbol refers to the location in the current
+segment.
+.SS "Labels"
+.PP
+There are two types: name and numeric.  Name labels consist of a name
+followed by a colon (:).
+.PP
+The numeric labels are single digits.  The nearest 0: label may be
+referenced as 0f in the forward direction, or 0b backwards.
+.SS "Statement Syntax"
+.PP
+Each line consists of a single statement.
+Blank or comment lines are allowed.
+.SS "Instruction Statements"
+.PP
+The most general form of an instruction is
+.HS
+~~~label: opcode operand1, operand2    ! comment
+.HS
+.SS "Expression Semantics"
+.PP
+.tr ~~
+The following operators can be used:
++ \(mi * / & | ^ ~ << (shift left) >> (shift right) \(mi (unary minus).
+.tr ~
+32-bit integer arithmetic is used.  
+Division produces a truncated quotient.
+.SS "Addressing Modes"
+.PP
+Below is a list of the addressing modes supported.
+Each one is followed by an example.
+.HS
+.ta 0.25i 3i
+.nf
+	constant	mov eax, 123456
+	direct access	mov eax, (counter)
+	register	mov eax, esi
+	indirect	mov eax, (esi)
+	base + disp.	mov eax, 6(ebp)
+	scaled index	mov eax, (4*esi)
+	base + index	mov eax, (ebp)(2*esi)
+	base + index + disp.	mov eax, 10(edi)(1*esi)
+.HS
+.fi
+Any of the constants or symbols may be replacement by expressions.  Direct
+access, constants and displacements may be any type of expression.  A scaled
+index with scale 1 may be written without the \*(OQ1*\*(CQ.
+.SS "Call and Jmp"
+.PP
+The \*(OQcall\*(CQ and \*(OQjmp\*(CQ instructions can be interpreted
+as a load into the instruction pointer.
+.HS
+.ta 0.25i 3i
+.nf
+	call _routine	! Direct, intrasegment
+	call (subloc)	! Indirect, intrasegment
+	call 6(ebp)	! Indirect, intrasegment
+	call ebx	! Direct, intrasegment
+	call (ebx)	! Indirect, intrasegment
+	callf (subloc)	! Indirect, intersegment
+	callf seg:offs	! Direct, intersegment
+.HS
+.fi
+.SP 1
+.SS "Symbol Assigment"
+.SP 1
+.PP
+Symbols can acquire values in one of two ways.
+Using a symbol as a label sets it to \*(OQ.\*(CQ for the current
+segment with type relocatable.  
+Alternative, a symbol may be given a name via an assignment of the form
+.HS
+~~~symbol = expression 
+.HS
+in which the symbol is assigned the value and type of its arguments.
+.SP 1
+.SS "Storage Allocation"
+.SP 1
+.PP
+Space can be reserved for bytes, words, and longs using pseudo-ops.
+They take one or more operands, and for each generate a value
+whose size is a byte, word (2 bytes) or long (4 bytes).  For example:
+.HS
+.if t .ta 0.25i 3i
+.if n .ta 2 24
+	.data1 2, 6	! allocate 2 bytes initialized to 2 and 6
+.br
+	.data2 3, 0x10	! allocate 2 words initialized to 3 and 16
+.br
+	.data4 010	! allocate a longword initialized to 8
+.br
+	.space 40	! allocates 40 bytes of zeros
+.HS
+allocates 50 (decimal) bytes of storage, initializing the first two
+bytes to 2 and 6, the next two words to 3 and 16, then one longword with
+value 8 (010 octal), last 40 bytes of zeros.
+.SS "String Allocation"
+.PP
+The pseudo-ops \fI.ascii\fR and \fI.asciz\fR
+take one string argument and generate the ASCII character
+codes for the letters in the string. 
+The latter automatically terminates the string with a null (0) byte.
+For example,
+.HS
+~~~.ascii "hello"
+.br
+~~~.asciz "world\en"
+.HS
+.SS "Alignment"
+.PP
+Sometimes it is necessary to force the next item to begin at a word, longword
+or even a 16 byte address boundary.
+The \fI.align\fR pseudo-op zero or more null byte if the current location
+is a multiple of the argument of .align.
+.SS "Segment Control"
+.PP
+Every item assembled goes in one of the four segments: text, rom, data,
+or bss.  By using the \fI.sect\fR pseudo-op with argument
+\fI.text, .rom, .data\fR or \fI.bss\fR, the programmer can force the
+next items to go in a particular segment.
+.SS "External Names"
+.PP
+A symbol can be given global scope by including it in a \fI.define\fR pseudo-op.
+Multiple names may be listed, separate by commas.
+It must be used to export symbols defined in the current program.
+Names not defined in the current program are treated as "undefined
+external" automatically, although it is customary to make this explicit
+with the \fI.extern\fR pseudo-op.
+.SS "Common"
+.PP
+The \fI.comm\fR pseudo-op declares storage that can be common to more than 
+one module.  There are two arguments: a name and an absolute expression giving
+the size in bytes of the area named by the symbol.  
+The type of the symbol becomes
+external.  The statement can appear in any segment.
+If you think this has something to do with FORTRAN, you are right.
+.SS "Examples"
+.PP
+In the kernel directory, there are several assembly code files that are
+worth inspecting as examples.
+However, note that these files, are designed to first be
+run through the C preprocessor.  (The very first character is a # to signal
+this.)  Thus they contain numerous constructs
+that are not pure assembler.
+For true assembler examples, compile any C program provided with 
+.MX
+using the \fB\(enS\fR flag.
+This will result in an assembly language file with a suffix with the same
+name as the C source file, but ending with the .s suffix.
Index: /trunk/minix/man/man9/awk.9
===================================================================
--- /trunk/minix/man/man9/awk.9	(revision 9)
+++ /trunk/minix/man/man9/awk.9	(revision 9)
@@ -0,0 +1,248 @@
+.so mnx.mac
+.TH AWK 9
+.CD "awk \(en pattern matching language"
+.SX "awk \fIrules\fR [\fIfile\fR] ...
+.FL "\fR(none)"
+.EX "awk rules input" "Process \fIinput\fR according to \fIrules\fR"
+.EX "awk rules \(en  >out" "Input from terminal, output to \fIout\fR"
+.PP
+AWK is a programming language devised by Aho, Weinberger, and Kernighan
+at Bell Labs (hence the name).
+\fIAwk\fR programs search files for
+specific patterns and performs \*(OQactions\*(CQ for every occurrence
+of these patterns.  The patterns can be \*(OQregular expressions\*(CQ
+as used in the \fIed\fR editor.  The actions are expressed
+using a subset of the C language.
+.PP
+The patterns and actions are usually placed in a \*(OQrules\*(CQ file
+whose name must be the first argument in the command line,
+preceded by the flag \fB\(enf\fR.  Otherwise, the first argument on the
+command line is taken to be a string containing the rules
+themselves. All other arguments are taken to be the names of text
+files on which the rules are to be applied, with \fB\(en\fR being the
+standard input.  To take rules from the standard input, use \fB\(enf \(en\fR.
+.PP
+The command:
+.HS
+.Cx "awk  rules  prog.\d\s+2*\s0\u"
+.HS
+would read the patterns and actions rules from the file \fIrules\fR
+and apply them to all the arguments.
+.PP
+The general format of a rules file is:
+.HS
+~~~<pattern> { <action> }
+~~~<pattern> { <action> }
+~~~...
+.HS
+There may be any number of these <pattern> { <action> }
+sequences in the rules file.  \fIAwk\fR reads a line of input from
+the current input file and applies every <pattern> { <action> }
+in sequence to the line.
+.PP
+If the <pattern> corresponding to any { <action> } is missing,
+the action is applied to every line of input.  The default
+{ <action> } is to print the matched input line.
+.SS "Patterns"
+.PP
+The <pattern>s may consist of any valid C expression.  If the
+<pattern> consists of two expressions separated by a comma, it
+is taken to be a range and the <action> is performed on all
+lines of input that match the range.  <pattern>s may contain
+\*(OQregular expressions\*(CQ delimited by an @ symbol.  Regular
+expressions can be thought of as a generalized \*(OQwildcard\*(CQ
+string matching mechanism, similar to that used by many
+operating systems to specify file names.  Regular expressions
+may contain any of the following characters:
+.HS
+.in +0.75i
+.ta +0.5i
+.ti -0.5i
+x	An ordinary character
+.ti -0.5i
+\\	The backslash quotes any character
+.ti -0.5i
+^	A circumflex at the beginning of an expr matches the beginning of a line.
+.ti -0.5i
+$	A dollar-sign at the end of an expression matches the end of a line.
+.ti -0.5i
+\&.	A period matches any single character except newline.
+.ti -0.5i
+*	An expression followed by an asterisk matches zero or more occurrences
+of that expression: \*(OQfo*\*(CQ matches \*(OQf\*(CQ, \*(OQfo\*(CQ, \*(OQfoo\*(CQ, \*(OQfooo\*(CQ, etc.
+.ti -0.5i
++	An expression followed by a plus sign matches one or more occurrences 
+of that expression: \*(OQfo+\*(CQ matches \*(OQfo\*(CQ, \*(OQfoo\*(CQ, \*(OQfooo\*(CQ, etc.
+.ti -0.5i
+[]	A string enclosed in square brackets matches any single character in that 
+string, but no others.  If the first character in the string is a circumflex, the 
+expression matches any character except newline and the characters in the 
+string.  For example, \*(OQ[xyz]\*(CQ matches \*(OQxx\*(CQ and \*(OQzyx\*(CQ, while 
+\*(OQ[^xyz]\*(CQ matches \*(OQabc\*(CQ but not \*(OQaxb\*(CQ.  A range of characters may be 
+specified by two characters separated by \*(OQ-\*(CQ.
+.in -0.75i
+.SS "Actions"
+.PP
+Actions are expressed as a subset of the C language.  All
+variables are global and default to int's if not formally
+declared.  
+Only char's and int's and pointers and arrays of
+char and int are allowed.  \fIAwk\fR allows only decimal integer
+constants to be used\(emno hex (0xnn) or octal (0nn). String
+and character constants may contain all of the special C
+escapes (\\n, \\r, etc.).
+.PP
+\fIAwk\fR supports the \*(OQif\*(CQ, \*(OQelse\*(CQ, 
+\*(OQwhile\*(CQ and \*(OQbreak\*(CQ flow of
+control constructs, which behave exactly as in C.
+.PP
+Also supported are the following unary and binary operators,
+listed in order from highest to lowest precedence:
+.HS
+.ta 0.25i 1.75i 3.0i
+.nf
+\fB	Operator	Type	Associativity\fR
+	() []	unary	left to right
+.tr ~~
+	! ~ ++ \(en\(en \(en * &	unary	right to left
+.tr ~
+	* / %	binary	left to right
+	+ \(en	binary	left to right
+	<< >>	binary	left to right
+	< <= > >=	binary	left to right
+	== !=	binary	left to right
+	&	binary	left to right
+	^	binary	left to right
+	|	binary	left to right
+	&&	binary	left to right
+	||	binary	left to right
+	=	binary	right to left
+.fi
+.HS
+Comments are introduced by a '#' symbol and are terminated by
+the first newline character.  The standard \*(OQ/*\*(CQ and \*(OQ*/\*(CQ
+comment delimiters are not supported and will result in a
+syntax error.
+.SP 0.5
+.SS "Fields"
+.SP 0.5
+.PP
+When \fIawk\fR reads a line from the current input file, the
+record is automatically separated into \*(OQfields.\*(CQ  A field is
+simply a string of consecutive characters delimited by either
+the beginning or end of line, or a \*(OQfield separator\*(CQ character.
+Initially, the field separators are the space and tab character.
+The special unary operator '$' is used to reference one of the
+fields in the current input record (line).  The fields are
+numbered sequentially starting at 1.  The expression \*(OQ$0\*(CQ
+references the entire input line.
+.PP
+Similarly, the \*(OQrecord separator\*(CQ is used to determine the end
+of an input \*(OQline,\*(CQ initially the newline character.  The field
+and record separators may be changed programatically by one of
+the actions and will remain in effect until changed again.
+.PP
+Multiple (up to 10) field separators are allowed at a time, but
+only one record separator.
+.PP
+Fields behave exactly like strings; and can be used in the same
+context as a character array.  These \*(OQarrays\*(CQ can be considered
+to have been declared as:
+.SP 0.15
+.HS
+~~~~~char ($n)[ 128 ];
+.HS
+.SP 0.15
+In other words, they are 128 bytes long.  Notice that the
+parentheses are necessary because the operators [] and $
+associate from right to left; without them, the statement
+would have parsed as:
+.HS
+.SP 0.15
+~~~~~char $(1[ 128 ]);
+.HS
+.SP 0.15
+which is obviously ridiculous.
+.PP
+If the contents of one of these field arrays is altered, the
+\*(OQ$0\*(CQ field will reflect this change.  For example, this
+expression:
+.HS
+.SP 0.15
+~~~~~*$4 = 'A';
+.HS
+.SP 0.15
+will change the first character of the fourth field to an upper-
+case letter 'A'.  Then, when the following input line:
+.HS
+.SP 0.15
+~~~~~120 PRINT "Name         address        Zip"
+.SP 0.15
+.HS
+is processed, it would be printed as:
+.HS
+.SP 0.15
+~~~~~120 PRINT "Name         Address        Zip"
+.HS
+.SP 0.15
+Fields may also be modified with the strcpy() function (see
+below).  For example, the expression:
+.HS
+~~~~~strcpy( $4, "Addr." );
+.HS
+applied to the same line above would yield:
+.HS
+~~~~~120 PRINT "Name         Addr.        Zip"
+.HS
+.SS "Predefined Variables"
+.PP
+The following variables are pre-defined:
+.HS
+.in +1.5i
+.ta +1.25i
+.ti -1.25i
+FS	Field separator (see below).
+.ti -1.25i
+RS	Record separator (see below also).
+.ti -1.25i
+NF	Number of fields in current input record (line).
+.ti -1.25i
+NR	Number of records processed thus far.
+.ti -1.25i
+FILENAME	Name of current input file.
+.ti -1.25i
+BEGIN	A special <pattern> that matches the beginning of input text.
+.ti -1.25i
+END	A special <pattern> that matches the end of input text.
+.in -1.5i
+.HS
+\fIAwk\fR also provides some useful built-in functions for string
+manipulation and printing:
+.HS
+.in +1.5i
+.ta +1.25i
+.ti -1.25i
+print(arg)	Simple printing of strings only, terminated by '\\n'.
+.ti -1.25i
+printf(arg...)	Exactly the printf() function from C.
+.ti -1.25i
+getline()	Reads the next record and returns 0 on end of file.
+.ti -1.25i
+nextfile()	Closes the current input file and begins processing the next file
+.ti -1.25i
+strlen(s)	Returns the length of its string argument.
+.ti -1.25i
+strcpy(s,t)	Copies the string \*(OQt\*(CQ to the string \*(OQs\*(CQ.
+.ti -1.25i
+strcmp(s,t)	Compares the \*(OQs\*(CQ to \*(OQt\*(CQ and returns 0 if they match.
+.ti -1.25i
+toupper(c)	Returns its character argument converted to upper-case.
+.ti -1.25i
+tolower(c)	Returns its character argument converted to lower-case.
+.ti -1.25i
+match(s,@re@)	Compares the string \*(OQs\*(CQ to the regular expression \*(OQre\*(CQ and 
+returns the number of matches found (zero if none).
+.in -1.5i
+.SS "Authors"
+.PP
+\fIAwk\fR was written by Saeko Hirabauashi and Kouichi Hirabayashi.
Index: /trunk/minix/man/man9/de.9
===================================================================
--- /trunk/minix/man/man9/de.9	(revision 9)
+++ /trunk/minix/man/man9/de.9	(revision 9)
@@ -0,0 +1,313 @@
+.so mnx.mac
+.TH DE 9
+.CD "de \(en disk editor"
+.SX "de\fR [\fB\(enw\fR] \fIblock_device"
+.SX "de \(enr \fIfile
+.FL "\(enr" "Recover a file that has been removed"
+.FL "\(enw" "Enable writing, so device can be modified"
+.EX "de \(enr /usr/ast/prog.c" "Undo the effects of: \fIrm /usr/ast/prog.c\fR"
+.EX "de \(enw /dev/fd0" "Edit \fI/dev/fd0\fR for writing"
+.PP
+The \fIde\fR program allows a system administrator to examine and modify
+a \s-2MINIX\s0 file system device. 
+Commands are available to move to any address on the disk
+and display the disk block contents. This information may
+be presented in one of three visual modes: as two-byte words,
+as ASCII characters or as a bit map. The disk may be searched
+for a string of characters. If the \fB\(enw\fR option is given,
+\fIde\fR will open the device for writing and words may be
+modified.
+Without this flag, writing is prohibited.
+Lost blocks and files can be recovered using a variety of
+commands. The \fB\(enr\fR option supports automated recovery of
+files removed by \fIunlink\fR.
+.SS "Positioning"
+.PP
+Disks are divided into blocks (also called \*(OQzones\*(CQ) of 1024
+bytes. \fIDe\fR keeps a current address on the disk as a
+block number and a byte offset within the block. In some
+visual modes the offset is rounded off, for example, in
+\*(OQword\*(CQ mode the offset must be even.
+.PP
+There are different types of blocks on a file system device,
+including a super block, bit maps, i-nodes and data blocks.
+\fIDe\fR knows the type of the current block, but will allow
+most positioning commands and visual modes to function
+anywhere on the disk.
+.PP
+The \fIf\fR command (or PGDN on the keypad) moves forward to the
+next block, similarly \fIb\fR (PGUP) moves backwards one block.
+\fIF\fR (END) moves to the last block and \fIB\fR (HOME) moves to the
+first block.
+.PP
+The arrow keys (or 
+\fIu\fR, \fId\fR, \fIl\fR, and \fIr\fR) change the current
+address by small increments. The size of the increment
+depends on the current display mode, as shown below. The
+various sizes suit each display and pointers move on the
+screen to follow each press of an arrow key.
+.HS
+.if t .ta .75iR 1.5iR 2.25iR 3.0iR 3.75iR
+.if n .ta .75i 1.5i 2.25i 3.0i 3.75i
+.nf
+\fB	Mode	Up	Down	Left	Right\fR
+	Word	\(mi2	+2	\(mi32	+32
+	Block	\(mi64	+64	\(mi1	+1
+	Map	\(mi256	+256	\(mi4	+4
+.fi
+.HS
+The \fIg\fR command allows movement to any specified block.
+Like all commands that take arguments, a prompt and
+subsequent input are written to the bottom line of the
+screen. Numerical entry may be decimal, octal or
+hexadecimal, for example 234, \(mi1, 070, 0xf3, \(miX3C.
+.PP
+While checking an i-node one may want to move to a block
+listed as a zone of the file. The \fIG\fR command takes the
+contents at the current address in the device as a block
+number and indirectly jumps to that block.
+.PP
+The address may be set to the start of any i-node using
+the \fI\fR command and supplying an i-node number. The \fII\fR
+command maps a given file name into an i-node address.
+The file must exist on the current device and this
+device must be mounted.
+.SS "The Display"
+.PP
+The first line of the display contains the device name,
+the name of the current output file (if one is open) and
+the current search string. If \fIde\fR is being run with
+the \fB\(enw\fR option then the device name is flagged with \*(OQ(w).\*(CQ
+If a string is too long to fit on the line it is marked with \*(OQ...\*(CQ.
+.PP
+The second line contains the current block number, the
+total number of blocks, and the type of the current block.
+The types are: boot, super, i-node bit map, zone bit map,
+i-nodes and data block.
+If the current address is
+within a data block then the string \*(OQin use\*(CQ is displayed
+if the block corresponds to a set in the zone bit map.
+.PP
+The third line shows the offset in the current block. If
+the current address is within either the i-node or zone bit
+maps then the i-node or block number corresponding to the
+current bit is shown. If the current address is within an
+i-node then the i-node number and \*(OQin use\*(CQ status is displayed.
+If the address is within a bit map or i-node block, but past
+the last usable entry, then the string \*(OQpadding\*(CQ is shown.
+.PP
+The rest of the screen is used to display data from the
+current block. There are three visual display modes:
+\*(OQword,\*(CQ \*(OQblock,\*(CQ and \*(OQmap.\*(CQ 
+The \fIv\fR command followed by
+\fIw\fR, \fIb\fR, or \fIm\fR sets the current display mode.
+.PP
+In \*(OQword\*(CQ mode 16 words, of two bytes each, are shown in
+either base 2, 8, 10 or 16. The current base is displayed
+to the far right of the screen. It can be changed using the
+\fIo\fR command followed by either an \fIh\fR (hexadecimal), \fId\fR
+(decimal), \fIo\fR (octal) or \fIb\fR (binary).
+.PP
+\fIDe\fR knows where i-nodes are, and will display the
+contents in a readable format, including the \fIrwx\fR bits,
+the user name and the time field. If the current page
+is at the beginning of the super block, or an executable
+file or an \fIar\fR archive, then \fIde\fR will also inform
+the user. In all other cases the contents of the 16
+words are shown to the right as equivalent ASCII
+characters.
+.PP
+In \*(OQblock\*(CQ mode a whole block of 1024 bytes is displayed
+as ASCII characters, 64 columns by 16 lines. Control codes
+are shown as highlighted characters. If the high order bit
+is set in any of the 1024 bytes then an \*(OQMSB\*(CQ flag is shown
+on the far right of the screen, but these bytes are not
+individually marked.
+.PP
+In \*(OQmap\*(CQ mode 2048 bits (256 bytes) are displayed from the
+top to the bottom (32 bits) and from the left to the right
+of the screen. Bit zero of a byte is towards the top of the
+screen. This visual mode is generally used to observe
+the bit map blocks. The number of set bits displayed is
+written on the far right of the screen.
+.SS "Searching"
+.PP
+A search for an ASCII string is initiated by the \fI/\fR command.
+Control characters not used for other purposes may be
+entered in the search string, for example CTRL-J is an end-of-line 
+character. The search is from the current position to
+the end of the current device.
+.PP
+Once a search string has been defined by a use of \fI/\fR, the
+next search may be initiated with the \fIn\fR command, (a \fI/\fR
+followed immediately by an ENTER is equivalent to an \fIn\fR).
+.PP
+Whenever a search is in progress \fIde\fR will append
+one \fI.\fR to the prompt line for every 500 blocks searched. If the
+string is found between the end of the file system and the
+actual end of the device, then the current address is set to
+the end of the file system.
+.PP
+Some of the positioning commands push the current address
+and visual mode in a stack before going to a new address.
+These commands are 
+\fIB\fR, \fIF\fR, \fIg\fR, \fIG\fR, \fIi\fR, \fII\fR, \fIn\fR, \fIx\fR and 
+\fI/\fR. 
+The \fIp\fR
+(previous) command pops the last address and visual mode
+from the stack. This stack is eight entries deep.
+.SS "Modifying the File System"
+.PP
+The \fIs\fR command will prompt for a data word and store it at
+the current address on the disk. This is used to change
+information that can not be easily changed by any other
+means.
+.PP
+The data word is 16 bits wide, it may be entered in decimal,
+octal or hexadecimal. Remember that the \fB\(enw\fR option must
+be specified for the \fIs\fR command to operate. Be careful
+when modifying a mounted file system.
+.SS "Recovering Files"
+.PP
+Any block on the disk may be written to an output file.
+This is used to recover blocks marked as free on the
+disk. A write command will request a file name the first
+time it is used, on subsequent writes the data is appended
+to the current output file.
+.PP
+The name of the current output file is changed using the
+\fIc\fR command. This file should be on a different file system,
+to avoid overwriting an i-node or block before it is
+recovered.
+.PP
+An ASCII block is usually recovered using the \fIw\fR command.
+All bytes will have their most significant bit cleared before
+being written to the output file. Bytes containing '\\0'
+or '\\177' are not copied. The \fIW\fR command writes the current
+block (1024 bytes exactly) to the output file.
+.PP
+When a file is deleted using \fIunlink\fR the i-node number
+in the directory is zeroed, but before its removal, it is
+copied into the end of the file name field. This allows
+the i-node of a deleted file to be found by searching
+through a directory. The \fIx\fR command asks for the path
+name of a lost file, extracts the old i-node number and
+changes the current disk address to the start of the
+i-node.
+.PP
+Once an i-node is found, all of the freed blocks may be
+recovered by checking the i-node zone fields, using 'G'
+to go to a block, writing it back out using 'w', going
+back to the i-node with \fIp\fR and advancing to the next
+block. This file extraction process is automated by using
+the \fIX\fR command, which goes through the i-node, indirect
+and double indirect blocks finding all the block pointers
+and recovering all the blocks of the file.
+.PP
+The \fIX\fR command closes the current output file and asks
+for the name of a new output file. All of the disk blocks
+must be marked as free, if they are not the command stops
+and the file must be recovered manually.
+.PP
+When extracting lost blocks \fIde\fR will maintain \*(OQholes\*(CQ in
+the file. Thus, a recovered sparse file does not allocate
+unused blocks and will keep its efficient storage scheme.
+This property of the \fIX\fR command may be used to move a sparse
+file from one device to another.
+.PP
+Automatic recovery may be initiated by the \fB\(enr\fR option on
+the command line. Also specified is the path name of a
+file just removed by \fIunlink\fR. \fIDe\fR determines which
+mounted file system device held the file and opens it for
+reading. The lost i-node is found and the file extracted by
+automatically performing an \fIx\fR and an \fIX\fR command.
+.PP
+The recovered file will be written to \fI/tmp\fR. \fIDe\fR will
+refuse to automatically recover a file on the same file
+system as \fI/tmp\fR. The lost file must have belonged to the
+user. If automatic recovery will not complete, then manual
+recovery may be performed.
+.SS "Miscellaneous"
+.PP
+The user can terminate a session with \fIde\fR by typing
+\fIq\fR, CTRL-D, or the key associated with SIGQUIT.
+.PP
+The \fIm\fR command invokes the \s-2MINIX\s0 \fIsh\fR shell as a subprocess.
+.PP
+For help while using \fIde\fR use \fIh\fR.
+.SS "Command Summary"
+.LP
+.ta 0.25i 1.0i 1.5i
+.nf
+.sp
+	PGUP	b	Back one block
+	PGDN	f	Forward one block
+	HOME	B	Goto first block
+	END	F	Goto last block
+	UP	u	Move back 2/64/256 bytes
+	DOWN	d	Move forward 2/64/256 bytes
+	LEFT	l	Move back 32/1/4 bytes
+	RIGHT	r	Move forward 32/1/4 bytes
+		g	Goto specified block
+		G	Goto block indirectly
+		i	Goto specified i-node
+		I	Filename to i-node
+		/	Search
+		n	Next occurrence
+		p	Previous address
+		h	Help
+	EOF	q	Quit
+		m	\s-2MINIX\s0 shell
+		v	Visual mode (w b m)
+		o	Output base (h d o b)
+		c	Change file name
+		w	Write ASCII block
+		W	Write block exactly
+		x	Extract lost directory entry
+		X	Extract lost file blocks
+		s	Store word
+.fi
+.sp
+NOTES:
+When entering a line in response to a prompt from \fIde\fR
+there are a couple of editing characters available. The
+previous character may be erased by typing CTRL-H and the
+whole line may be erased by typing CTRL-U. ENTER terminates
+the input. If DELETE or a non-ASCII character is typed
+then the command requesting the input is aborted.
+.PP
+The commands \fIG\fR, \fIs\fR and \fIX\fR will only function if
+the current visual display mode is \*(OQword.\*(CQ 
+The commands
+\fIi\fR, \fII\fR and \fIx\fR change the mode to \*(OQword\*(CQ on
+completion. The commands \fIG\fR and \fI/\fR change the mode
+to \*(OQblock\*(CQ. These restrictions and automatic mode
+conversions are intended to aid the user.
+.PP
+The \*(OQmap\*(CQ mode uses special graphic characters, and
+only functions if the user is at the console.
+.PP
+\fIDe\fR generates warnings for illegal user input or if
+erroneous data is found on the disk, for example a
+corrupted magic number. Warnings appear in the middle
+of the screen for two seconds, then the current page
+is redrawn. Some minor errors, for example, setting
+an unknown visual mode, simply ring the bell. Major
+errors, for example I/O problems on the file system
+device cause an immediate exit from \fIde\fR.
+.PP
+The i-node and zone bit maps are read from the device
+when \fIde\fR starts up. These determine whether \*(OQin use\*(CQ
+or \*(OQnot in use\*(CQ is displayed in the status field at
+the top of the screen. The bit maps are not re-read
+while using \fIde\fR and will become out-of-date if
+observing a mounted file system.
+.PP
+\fIDe\fR requires termcap definitions for \*(OQcm\*(CQ and \*(OQcl\*(CQ.
+Furthermore, \*(OQso\*(CQ and \*(OQse\*(CQ will also be used if available. 
+The ANSI strings generated by the keypad arrows are recognized,
+as well as any single character codes defined by \*(OQku\*(CQ,
+\*(OQkd\*(CQ, \*(OQkl\*(CQ and \*(OQkr\*(CQ.
+.SS "Author"
+.PP
+The \fIde\fR program was written by Terrence Holm.
Index: /trunk/minix/man/man9/dis88.9
===================================================================
--- /trunk/minix/man/man9/dis88.9	(revision 9)
+++ /trunk/minix/man/man9/dis88.9	(revision 9)
@@ -0,0 +1,84 @@
+.so mnx.mac
+.TH DIS88 9
+.CD "dis88 \(en disassembler [IBM]"
+.SX "dis88\fR [\fB\(eno\fR] \fIinfile\fR [\fIoutfile\fR]"
+.FL "\(eno" "List the object code along with the assembly code"
+.EX "dis88 a.out >listing" "Disassemble \fIa.out\fR"
+.EX "dis88 \(eno a.out listing" "Ditto, but with object code"
+.PP
+\fIDis88\fR disassembles 8088 object code to the assembly language format
+used by 
+.MX  .
+It makes full use of
+symbol table information, supports separate 
+instruction and data space, and generates synthetic labels when needed. 
+It does not support 8087 mnemonics, symbolic data segment references, or 
+the ESC mnemonic.
+.PP
+The program is invoked by:
+.HS
+.Cx "dis88 [\(eno] infile [outfile]"
+.HS
+The \(eno flag causes object code to be listed. 
+If no outfile is given, \fIstdout\fR is used.
+.PP
+The text segment of an object file is always padded to an even address.
+In addition, if the file has split I/D space, the text segment will be padded
+to a paragraph boundary (i.e., an address divisible by 16). Due to padding, the
+disassembler may produce a few spurious, but harmless, instructions at the end
+of the text segment.
+.PP
+Because the information to which initialized data refers cannot generally
+be inferred from context, the data segment is treated literally. Byte values
+(in hexadecimal) are output, and long stretches of null data are represented by
+appropriate \fI.zerow\fR pseudo-ops. 
+Disassembly of the bss segment, on the other
+hand, is quite straightforward, because uninitialized data is all zero by 
+definition. 
+No data is output in the bss segment, but symbolic labels are output
+as appropriate.
+.PP
+The output of operands in symbolic form is complicated somewhat by the
+existence of assembler symbolic constants and segment override opcodes. Thus,
+the program's symbol lookup routine attempts to apply a certain amount of
+intelligence when it is asked to find a symbol. If it cannot match on a symbol
+of the preferred type, it may output a symbol of some other type, depending on
+preassigned (and somewhat arbitrary) rankings within each type. Finally, if
+all else fails, it will output a string containing the address sought as a hex
+constant. For user convenience, the targets of branches are also output, in
+comments, as hexadecimal constants.
+.SS "Error Messages"
+.PP
+Various error messages may be generated as a result of problems encountered
+during the disassembly.
+They are listed below
+.HS.
+.in +3.20i
+.ta +2.75i +0.2i
+.ti -2.95i
+Cannot access input file	\(en	Input file cannot be opened or read
+.ti -2.95i
+Cannot open output file	\(en	Output file cannot be created
+.ti -2.95i
+Input file not in object format	\(en	Bad magic number
+.ti -2.95i
+Not an 8086/8088 object file	\(en	CPU ID of the file header is incorrect
+.ti -2.95i
+Reloc table overflow	\(en	Relocation table exceeds 1500 entries
+.ti -2.95i
+Symbol table overflow	\(en	Symbol table exceeds 1500 entries
+.ti -2.95i
+Lseek error	\(en	Input file corrupted (should never happen)
+.ti -2.95i
+Warning: no symbols	\(en	Symbol table is missing (use ast)
+.ti -2.95i
+Cannot reopen input file	\(en	Input file was removed during execution
+.in -3.20i
+.SS "Author"
+.PP
+\fIDis88\fR  was written and
+copyrighted by G. M. Harding and is included here by permission. It may be
+freely redistributed provided that complete source code, with all copyright
+notices, accompanies any redistribution. This provision also applies to any
+modifications you may make. You are urged to comment such changes, giving,
+as a minimum, your name and complete address.
Index: /trunk/minix/man/man9/elle.9
===================================================================
--- /trunk/minix/man/man9/elle.9	(revision 9)
+++ /trunk/minix/man/man9/elle.9	(revision 9)
@@ -0,0 +1,557 @@
+.so mnx.mac
+.TH ELLE 9
+.CD "elle \(en ELLE Looks Like Emacs"
+.SX "elle \fIfile\fR [\fIfile2\fR]"
+.FL "\fR(none)"
+.EY "elle file.c" "Start the editor"
+.PP
+\fIELLE\fR (ELLE Looks Like Emacs) is an Emacs clone for 
+.MX .  
+ELLE is not full Emacs but it has about 80 commands and is quite fast.
+.SP 0.5
+.SS "Key bindings"
+.SP 0.5
+.PP
+\fIMined\fR only has a small number of commands.  All of them are either of
+the form CTRL-x or are on the numeric keypad.  Emacs, in contrast, has so
+many commands, that not only are all the CTRL-x commands used up, but so
+are all the ESC x (escape followed by x; escape is not a shift character,
+like CTRL).  Even this is not enough, so CTRL-X is used as a prefix for
+additional commands.  Thus CTRL-X CTRL-L is a command, and so is CTRL-X K.
+Note that what is conventionally written as CTRL-X K really means CTRL-X k.
+In some contexts it is traditional to write CTRL-X as ^X.
+Please note that they mean the same thing.
+.PP
+As a result, many Emacs commands need three or four key strokes to 
+execute.  Some people think 3-4 key strokes is too many.
+For this reason, Emacs and ELLE allow users to assign their own key bindings.
+In ELLE this is done with \*(OQuser profiles.\*(CQ  A user profile is a file listing
+which function is invoked by which key stroke.  The user profile is then
+compiled by a program called ellec into binary form.  When ELLE starts up
+it checks to see if a file .ellepro.b1 exists in $HOME.  If it does, this
+file is read in and overrides the default bindings.  
+.PP
+A user profile that simulates the \fImined\fR commands fairly
+well is provided.  
+Its installation is described later.  If you have never used Emacs, 
+it is suggested that you use the \fImined\fR profile.  
+If you normally use Emacs, then
+do not install the \fImined\fR profile.  You can also make your own using
+\fIellec\fR.
+There is no Mock Lisp.
+.PP
+ELLE has a character-oriented view of the world, not a line oriented
+view, like \fIed\fR.  
+It does not have magic characters for searching.
+However, you can use line feed in search patterns.  
+For example, to find a line consisting of the three characters
+\*(OQfoo\*(CQ all by themselves on a line, using the mined
+bindings (see below), use the pattern: CTRL-\\ CTRL-J f o o CTRL-\\ CTRL-J.
+The CTRL-\ means to interpret the next character literally, in this case it
+is CTRL-J, which is line feed.  You can also search for patterns involving 
+multiple lines.  For example, to find a line ending in an \*(OQx\*(CQ followed by a
+line beginning with a \*(OQy\*(CQ, use as pattern: x CTRL-\ CTRL-J y.
+.SS "Mined Key Bindings"
+.PP
+These are the key bindings if the binary user profile, \fI.ellepro.b1\fR,
+is installed in $HOME.  The ESCAPE key followed by a number followed by a
+command causes that command to be executed \*(OQnumber\*(CQ times.  This applies
+both to control characters and insertable characters.  CTRL-X refers to a
+\*(OQcontrol character.\*(CQ  ESC x refers to an escape character 
+followed by x.
+In other words, ^X is a synonym for CTRL-X.
+^X Y refers to CTRL-X followed by y.  To abort the current command and go
+back to the main loop of the editor, type CTRL-G, rather than CTRL-\\.
+.PP
+Only a few commands are of the form CTRL-X Y.  All of these are also
+bound to CTRL-X CTRL-Y, so you can hold down CTRL and then hit X Y, or
+release control after the X, as you prefer.
+.PP
+The key bindings that are not listed should not be used.
+Some of them actually do things.
+For example, the ANSI escape codes ESC [ x are bound 
+to ^X Y for a variety of y.
+.PP
+Some commands work on regions.
+A region is defined as the text between the most recently set mark 
+and the cursor.
+.SP 0.5
+.SS "Mined Commands"
+.SP 0.5
+.PP
+If the \fImined\fR profile,
+.I .ellepro.b1 
+is installed in your home directory, the following commands will work.
+.sp
+.in +1.75i
+.ta +1.25i
+.ti -1.5i
+\fBCURSOR MOTION\fR
+.ti -1.25i
+arrows	Move the cursor in the indicated direction
+.ti -1.25i
+CTRL-A	Move cursor to start of current line
+.ti -1.25i
+CTRL-Z	Move cursor to end of current line
+.ti -1.25i
+CTRL-F	Move cursor forward word 
+.ti -1.25i
+CTRL-B	Move cursor backward to start of previous word 
+.sp
+.ti -1.5i
+\fBSCREEN MOTION\fR
+.ti -1.25i
+Home key	Move to first character of the file
+.ti -1.25i
+End key	Move to last character of the file
+.ti -1.25i
+PgUp key	Scroll window up 22 lines (closer to start of the file)
+.ti -1.25i
+PgDn key	Scroll window down 22 lines (closer to end of the file)
+.ti -1.25i
+CTRL-U	Scroll window up 1 line
+.ti -1.25i
+CTRL-D	Scroll window down 1 line
+.ti -1.25i
+ESC ,	Move to top of screen
+.ti -1.25i
+CTRL-_	Move to bottom of screen
+.sp
+.ti -1.5i
+\fBMODIFYING TEXT\fR
+.ti -1.25i
+DEL key	Delete the character under the cursor
+.ti -1.25i
+Backsp	Delete the character to left of the cursor
+.ti -1.25i
+CTRL-N	Delete the next word
+.ti -1.25i
+CTRL-P	Delete the previous word
+.ti -1.25i
+CTRL-T	Delete tail of line (all characters from cursor to end of line)
+.ti -1.25i
+CTRL-O	Open up the line (insert line feed and back up)
+.ti -1.25i
+ESC G	Get and insert a file at the cursor position (CTRL-G in mined)
+.sp
+.ti -1.5i
+\fBREGIONS\fR
+.ti -1.25i
+CTRL-^	Set mark at current position for use with CTRL-C and CTRL-K
+.ti -1.25i
+CTRL-C	Copy the text between the mark and the cursor into the buffer
+.ti -1.25i
+CTRL-K	Delete text between mark and cursor; also copy it to the buffer
+.ti -1.25i
+CTRL-Y	Yank contents of the buffer out and insert it at the cursor
+.sp
+.ti -1.5i
+\fBMISCELLANEOUS\fR
+.ti -1.25i
+numeric +	Search forward (prompts for expression)
+.ti -1.25i
+numeric \(mi	Search backward (prompts for expression)
+.ti -1.25i
+CTRL-]	ESC n CTRL-[ goes to line n (slightly different syntax than mined)
+.ti -1.25i
+CTRL-R	Global replace pattern with string (from cursor to end)
+.ti -1.25i
+CTRL-L	Replace pattern with string within the current line only
+.ti -1.25i
+CTRL-W	Write the edited file back to the disk
+.ti -1.25i
+CTRL-S	Fork off a shell (use CTRL-D to get back to the editor)
+.ti -1.25i
+CTRL-G	Abort whatever the editor was doing and wait for command (CTRL-\)
+.ti -1.25i
+CTRL-E	Redraw screen with cursor line positioned in the middle
+.ti -1.25i
+CTRL-V	Visit (edit) a new file
+.ti -1.25i
+CTRL-Q	Write buffer to a file
+.ti -1.25i
+ESC X	Exit the editor
+.SP 0.5
+.in -1.75i
+.SS "Non-Mined Commands"
+.LP
+.SP 0.5
+.in +1.75i
+.ta +1.25i
+.ti -1.5i
+\fBCURSOR MOTION\fR
+.ti -1.25i
+ESC P	Forward paragraph (a paragraph is a line beginning with a dot)
+.ti -1.25i
+ESC ]	Backward paragraph
+.ti -1.25i
+ESC .	Indent this line as much as the previous one
+.sp
+.ti -1.5i
+\fBMODIFYING TEXT\fR
+.ti -1.25i
+CTRL-\\	Insert the next character (used for inserting control characters)
+.ti -1.25i
+ESC T	Transpose characters
+.ti -1.25i
+ESC W	Transpose words
+.ti -1.25i
+ESC =	Delete white space (horizontal space)
+.ti -1.25i
+ESC |	Delete blank lines (vertical space)
+.sp
+.ti -1.5i
+\fBREGIONS\fR
+.ti -1.25i
+ESC M	Mark current paragraph
+.ti -1.25i
+ESC ^	Exchange cursor and mark
+.ti -1.25i
+ESC Y	Yank back the next-to-the-last kill (CTRL-Y yanks the last one)
+.ti -1.25i
+ESC A	Append next kill to kill buffer
+.sp
+.ti -1.5i
+\fBKEYBOARD MACROS\fR
+.ti -1.25i
+ESC /	Start Keyboard Macro
+.ti -1.25i
+ESC \\	End Keyboard Macro
+.ti -1.25i
+ESC *	View Keyboard Macro (the PrtSc key on the numeric pad is also a *)
+.ti -1.25i
+ESC E	Execute Keyboard Macro
+.sp
+.ti -1.5i
+\fBWINDOW MANAGEMENT\fR
+.ti -1.25i
+^X 1	Enter one window mode
+.ti -1.25i
+^X 2	Enter two window mode
+.ti -1.25i
+^X L	Make the current window larger
+.ti -1.25i
+^X P	Make the window more petit/petite (Yes, Virginia, they are English)
+.ti -1.25i
+^X N	Next window
+.ti -1.25i
+^X W	New window
+.sp
+.ti -1.5i
+\fBBUFFER MANAGEMENT\fR
+.ti -1.25i
+numeric 5	Display the list of current files and buffers
+.ti -1.25i
+ESC B	Select a buffer
+.ti -1.25i
+ESC S	Select an existing buffer
+.ti -1.25i
+ESC N	Mark a buffer as NOT modified (even if it really is)
+.sp
+.ti -1.5i
+\fBUPPER AND LOW CASE MANIPULATION\fR
+.ti -1.25i
+ESC I	Set first character of word to upper case
+.ti -1.25i
+ESC C	Capitalize current word
+.ti -1.25i
+ESC O	Make current word ordinary (i.e., lower case)
+.ti -1.25i
+ESC U	Set entire region between mark and cursor to upper case
+.ti -1.25i
+ESC L	Set entire region between mark and cursor to lower case
+.sp
+.ti -1.5i
+\fBMISCELLANEOUS\fR
+.ti -1.25i
+ESC F	Find file and read it into its own buffer
+.ti -1.25i
+ESC Z	Incremental search
+.ti -1.25i
+ESC Q	Like CTRL-R, but queries at each occurrence (type ? for options)
+.ti -1.25i
+ESC R	Reset the user profile from a file
+.ti -1.25i
+ESC H	Help (ELLE prompts for the 1 or 2 character command to describe)
+.ti -1.25i
+ESC ;	Insert a comment in a C program (generates /* */ for you)
+.ti -1.25i
+^X X	Exit the editor (same as ESC X and CTRL-X CTRL-X)
+.in -1.75i
+.fi
+.sp
+The major differences between ELLE 
+with the \fImined\fR profile and \fImined\fR itself are:
+.sp
+.nf
+.in +0.25i
+1. The definition of a \*(OQword\*(CQ is different for forward and backward word
+2. The mark is set with CTRL-^ instead of CTRL-@
+3. Use CTRL-G to abort a command instead of CTRL-\\
+4. Use CTRL-\ to literally insert the next character, instead of ALT
+5. CTRL-E adjusts the window to put the cursor in the middle of it
+6. To get and insert a file, use ESC G instead of CTRL-G
+7. To go to line n, type ESC n CTRL-[ instead of CTRL-[ n
+8. You exit with CTRL-X CTRL-X and then answer the question with \*(OQy\*(CQ.
+9. There are many new commands, windows, larger files, etc.
+.fi
+.in -0.25i
+.sp
+.SS "Emacs Key Bindings"
+.PP
+If you do not have the \fImined\fR profile installed, you get the standard
+Emacs key bindings.
+These are listed below. 
+Commands not listed are not implemented.
+.sp
+.in +1.75i
+.ta +1.25i
+.ti -1.5i
+\fBCURSOR MOVEMENT\fR
+.ti -1.25i
+CTRL-F	Forward one character.
+.ti -1.25i
+CTRL-B	Backward one character.
+.ti -1.25i
+CTRL-H	Same as CTRL-B: move backward one character.
+.ti -1.25i
+ESC F	Forward one word.
+.ti -1.25i
+ESC B	Backward one word.
+.ti -1.25i
+CTRL-A	Beginning of current line.
+.ti -1.25i
+CTRL-E	End of current line.
+.ti -1.25i
+CTRL-N	Next line (goes to the next line).
+.ti -1.25i
+CTRL-P	Previous line (goes to the previous line).
+.ti -1.25i
+CTRL-V	Beginning of next screenful.
+.ti -1.25i
+ESC V	Beginning of previous screenful.
+.ti -1.25i
+ESC ]~	Forward Paragraph.
+.ti -1.25i
+ESC [~	Backward Paragraph.
+.ti -1.25i
+ESC <	Beginning of whole buffer.
+.ti -1.25i
+ESC >	End of whole buffer.
+.sp
+.ti -1.5i
+\fBDELETING\fR
+.ti -1.25i
+CTRL-D	Deletes forward one character (the one the cursor is under).
+.ti -1.25i
+DELETE	Deletes backward one character (the one to left of cursor).
+.ti -1.25i
+ESC D	Kills forward one word.
+.ti -1.25i
+ESC DEL	Kills backward one word.
+.ti -1.25i
+CTRL-K	Kills the rest of the line (to the right of the cursor).
+.ti -1.25i
+ESC \\	Deletes spaces around the cursor.
+.ti -1.25i
+^X CTRL-O	Deletes blank lines around the cursor.
+.sp
+.ti -1.5i
+\fBCASE CHANGE\fR
+.ti -1.25i
+ESC C	Capitalizes word : first letter becomes uppercase; rest lower
+.ti -1.25i
+ESC L	Makes the whole next word lowercase.
+.ti -1.25i
+ESC U	Makes the whole next word uppercase.
+.ti -1.25i
+^X CTRL-L	Makes whole region lowercase.
+.ti -1.25i
+^X CTRL-U	Makes whole region uppercase.
+.sp
+.ti -1.5i
+\fBSEARCHING\fR (If no string is given, previous string is used)
+.ti -1.25i
+CTRL-S	Incremental Search forward; prompts \*(OQI-search:\*(CQ
+.ti -1.25i
+CTRL-R	Reverse Incremental Search; prompts \*(OQR-search:\*(CQ
+.HS
+During an incremental search, the following characters have special effects:
+.HS
+.in +1.2i
+.ta +1.0i +0.2i
+.ti -1.2i
+\*(OQnormal\*(CQ 	-	Begin searching immediately.
+.ti -1.2i
+^G	-	Cancel I-search, return to start.
+.ti -1.2i
+DEL	-	Erase last char, return to last match.
+.ti -1.2i
+^S, ^R	-	Repeat search (or change direction).
+.ti -1.2i
+ESC or CR	-	Exit I-search at current point.
+.sp
+.in -1.2i
+.ta +1.25i
+.ti -1.25i
+ESC %	Query Replace. Interactive replace. Type \*(OQ?\*(CQ to see options.
+.ti -1.25i
+^X %	Replace String.	Like Query Replace, but not interactive
+.sp
+.ti -1.5i
+\fBMARKING AREAS\fR
+.ti -1.25i
+CTRL-^	Set mark
+.ti -1.25i
+^X CTRL-X	Exchange cursor and mark.
+.ti -1.25i
+ESC H	Mark Paragraph. Sets mark and cursor to surround a para.
+.ti -1.25i
+CTRL-W	Wipe-out -- kills a \*(OQregion\*(CQ:
+.ti -1.25i
+ESC W	Copy region. Like CTRL-W then CTRL-Y but modifies buffer
+.ti -1.25i
+CTRL-Y	Yanks-back (un-kills) whatever you have most recently killed.
+.ti -1.25i
+ESC Y	Yanks-back (un-kills) the next most recently killed text.
+.ti -1.25i
+ESC CTRL-W	Append Next Kill. Accumulates stuff from several kills
+.sp
+.ti -1.5i
+\fBFILLING TEXT\fR
+.ti -1.25i
+ESC Q	Fill the paragraph to the size of the Fill Column.
+.ti -1.25i
+ESC G	Fill the region.
+.ti -1.25i
+^X F	Set Fill Column. ESC Q will use this line size.
+.ti -1.25i
+^X .	Set Fill Prefix. Asks for prefix string 
+.ti -1.25i
+^X T	Toggles Auto Fill Mode.
+.sp
+.ti -1.5i
+\fBWINDOWS\fR
+.ti -1.25i
+^X 2	Make two windows (split screen).
+.ti -1.25i
+^X 1	Make one window (delete window) (make one screen).
+.ti -1.25i
+^X O	Go to Other window.
+.ti -1.25i
+^X ^	Grow window: makes current window bigger.
+.sp
+.ti -1.5i
+\fBBUFFERS\fR
+.ti -1.25i
+^X CTRL-F	Find a file and make a buffer for it.
+.ti -1.25i
+^X B	Select Buffer: goes to specified buffer or makes new one
+.ti -1.25i
+^X CTRL-B	Show the names of the buffers used in this editing session.
+.ti -1.25i
+^X K	Kill Buffer.
+.ti -1.25i
+ESC tilde	Say buffer is not modified.
+.ti -1.25i
+^X CTRL-M	Toggle EOL mode (per-buffer flag).
+.sp
+.ti -1.5i
+\fBKEYBOARD MACRO\fR
+.ti -1.25i
+^X (	Start collecting a keyboard macro.
+.ti -1.25i
+^X )	Stop collecting.
+.ti -1.25i
+^X E	Execute the collected macro.
+.ti -1.25i
+^X *	Display the collected macro.
+.sp
+.ti -1.5i
+\fBFILES\fR
+.ti -1.25i
+^X CTRL-I	Insert a file where cursor is.
+.ti -1.25i
+^X CTRL-R	Read a new file into current buffer.
+.ti -1.25i
+^X CTRL-V	Same as ^X ^R above (reads a file).
+.ti -1.25i
+^X CTRL-W	Write buffer out to new file name.
+.ti -1.25i
+^X CTRL-S	Save file: write out buffer to its file name.
+.ti -1.25i
+^X CTRL-E	Write region out to new file name.
+.sp
+.ti -1.5i
+\fBMISCELLANEOUS\fR
+.ti -1.25i
+^X CTRL-Z	Exit from ELLE.  
+.ti -1.25i
+^X !	Escape to shell (CTRL-D to return)
+.ti -1.25i
+CTRL-O	Open up line	
+.ti -1.25i
+LINEFEED	Same as typing RETURN and TAB.
+.ti -1.25i
+CTRL-T	Transposes characters.
+.ti -1.25i
+ESC T	Transposes words.
+.ti -1.25i
+CTRL-U	Makes the next command happen four times.
+.ti -1.25i
+CTRL-U number	Makes the next command happen \*(OQnumber\*(CQ times.  
+.ti -1.25i
+ESC number	Same as CTRL-U number.
+.ti -1.25i
+CTRL-L	Refreshes screen.
+.ti -1.25i
+CTRL-U CTRL-L	Refresh only the line cursor is on.
+.ti -1.25i
+CTRL-U n CTRL-L Change window so the cursor is on line n
+.ti -1.25i
+CTRL-Q	Quote: insert the next character no matter what it is.
+.ti -1.25i
+CTRL-G	Quit: use to avoid answering a question.
+.ti -1.25i
+ESC ;	Inserts comment (for writing C programs).
+.ti -1.25i
+ESC I	Inserts indentation equal to previous line.
+.ti -1.25i
+ESC M	Move to end of this line's indentation.
+.ti -1.25i
+CTRL-_	Describe a command (if the command database is online)
+.sp
+.ti -1.5i
+\fBUNUSED CONTROLS\fR
+.ti -1.25i
+CTRL-C	Not used.
+.ti -1.25i
+CTRL-Z	Not used.
+.ti -1.25i
+CTRL-]	Not used.
+.fi
+.in -1.75i
+.sp	
+.SP 0.5
+.SS "ELLE profile"
+.PP
+It is possible to create your own user profile.
+The mechanism is different from Emacs, since ELLE does not have Mock Lisp.
+Proceed as follows.
+.LI
+.IT
+Modify \fI.ellepro.e\fR to suit your taste.
+.IT
+Install \fI.ellepro.e\fR in your home directory.
+.IT
+Type:
+.HS
+.Cx "ellec \(enProfile"
+.HS
+.IT
+Check to see if \fI.ellepro.b1\fR has been created.
+If it has, you are ready to go.
+.LX
+.SS "Author"
+.PP
+ELLE was written by Ken Harrenstien of SRI (klh@sri.com).
Index: /trunk/minix/man/man9/elvis.9
===================================================================
--- /trunk/minix/man/man9/elvis.9	(revision 9)
+++ /trunk/minix/man/man9/elvis.9	(revision 9)
@@ -0,0 +1,1258 @@
+.so mnx.mac
+.TH ELVIS 9
+.CD "elvis \(en clone of the Berkeley vi editor"
+.SX "elvis \fR[\fB\(enRerv\fR] [\fB\(ent \fItag\fR] \fR[\fIfile\fR] ..."
+.FL "\(enR" "Set the read-only option"
+.FL "\(ene" "Start up emulating \fIex\fR"
+.FL "\(enr" "Tell the user to use \fIelvrec\fR instead
+.FL "\(ent" "Start editing at the given tag"
+.FL "\(env" "Start up emulating \fIvi\fR"
+.EX "elvis" "Call the editor"
+.EX "elvis prog.c" "edit \fIprog.c\fR"
+.PP
+\fIElvis\fR is a full-screen editor closely modeled on the famous Berkeley
+\fIvi\fR editor.
+It provides essentially the same interface to the user as \fIvi\fR, but the 
+code is completely new, written from scratch.
+This document provides a brief introduction to \fIvi\fR.
+It is not intended as a tutorial for beginners.
+Most books on
+.Ux
+cover \fIvi\fR.
+.PP
+Like \fIvi\fR, \fIelvis\fR can operate as a screen editor
+(\fIvi\fR mode) or as a line editor (\fIex\fR) mode.  
+It can be called either as \fIelvis\fR \fIvi\fR,or as \fIex\fR, 
+depending on which is desired.
+They are all links to the same file.
+.SS "Vi Commands"
+.PP
+Below is a list of the \fIvi\fR commands supported.
+The following symbols are used in the table:
+.HS
+.in +1.25i
+.ta +1.0i
+.ti -1.0i
+count	Integer parameter telling how many or how much
+.ti -1.0i
+key	One character parameter to the command
+.ti -1.0i
+inp	Interactive input expected
+.ti -1.0i
+mv	Indicates how much for commands like \fIdelete\fR and \fIchange\fR:
+.in +0.8i
+.ta +0.3i
+.ti -0.3i
+(	Previous sentence
+.ti -0.3i
+)	Next sentence
+.ti -0.3i
+{	Previous paragraph
+.ti -0.3i
+}	Next paragraph (delimited by blank line, \fI.PP, .LP, .IP\fR etc.)
+.ti -0.3i
+[	Previous section (delimited by \fI.SH\fR or \fI.NH\fR)
+.br
+A repeated command character means the scope is this line
+.in -0.8i
+.ta +1.0i
+.ti -1.0i
+MOVE	Indicates commands that may also be used where \fImv\fR is specified
+.ti -1.0i
+EDIT	These commands affect text and may be repeated by the \fI.\fR command
+.in -1.25i
+.HS
+In addition to the above notation, the caret (^) is used as an abbreviation
+for CTRL.
+For example, ^A means CTRL-A.
+.HS
+.in +2i
+.ta +1i +1i +3.3i
+.ti -2i
+\fBCount~~~~	Command	Description	Type\fR
+.ti -2i
+	^A	(Not defined)
+.ti -2i
+	^B	Move toward the top of the file by 1 screenful
+.ti -2i
+	^C	(Not defined)
+.ti -2i
+count	^D	Scroll down \fIcount\fR lines (default 1/2 screen)
+.ti -2i
+count	^E	Scroll up \fIcount\fR lines
+.ti -2i
+	^F	Move toward the bottom of the file by 1 screenful
+.ti -2i
+	^G	Show file status, and the current line 
+.ti -2i
+count	^H	Move left, like \fIh\fR	MOVE
+.ti -2i
+	^I	(Not defined)
+.ti -2i
+count	^J	Move down	MOVE
+.ti -2i
+	^K	(Not defined)
+.ti -2i
+	^l	Redraw the screen
+.ti -2i
+count	^M	Move to the front of the next line	MOVE
+.ti -2i
+count	^N	Move down	MOVE
+.ti -2i
+	^O	(Not defined)
+.ti -2i
+count	^P	Move up	MOVE
+.ti -2i
+	^Q	(Not defined)
+.ti -2i
+	^R	Redraw the screen
+.ti -2i
+	^S	(Not defined)
+.ti -2i
+	^T	(Not defined)
+.ti -2i
+count	^U	Scroll up \fIcount\fR lines (default 1/2 screen)
+.ti -2i
+	^V	(Not defined)
+.ti -2i
+	^W	(Not defined)
+.ti -2i
+	^X	(Not defined)
+.ti -2i
+count	^Y	Scroll down \fIcount\fR lines
+.ti -2i
+	^Z	(Not defined)
+.ti -2i
+	ESC	(Not defined)
+.ti -2i
+	^\e	(Not defined)
+.ti -2i
+	^]	If the cursor is on a tag name, go to that tag
+.ti -2i
+	^^	Save this file and edit the previous file
+.ti -2i
+	^_	(Not defined)
+.ti -2i
+count	SPACE	Move right,like \fIl\fR	MOVE
+.ti -2i
+	! mv	Run the selected lines thru an external filter program
+.ti -2i
+	" key	Select which cut buffer to use next
+.ti -2i
+	#	(Not defined)
+.ti -2i
+	$	Move to the rear of the current line	MOVE
+.ti -2i
+	%	move to the matching (){}[] character	MOVE
+.ti -2i
+	&	(Not defined)
+.ti -2i
+	' key	Move to a marked line	MOVE
+.ti -2i
+count	(	Move backward \fIcount\fR sentences	MOVE
+.ti -2i
+count	)	Move forward \fIcount\fR sentences	MOVE
+.ti -2i
+	*	(Not defined)
+.ti -2i
+count	+	Move to the front of the next line	MOVE
+.ti -2i
+count	,	Repeat the previous [\fIfFtT\fR] but the other way	MOVE
+.ti -2i
+count	\(en	Move to the front of the preceding line	MOVE
+.ti -2i
+	.	Repeat the previous \*(OQedit\*(CQ command
+.ti -2i
+	 /	Text search forward for a given regular expr	MOVE
+.ti -2i
+	0	If not part of count, move to 1st char of this line	MOVE
+.ti -2i
+	1	Part of count
+.ti -2i
+	2	Part of count
+.ti -2i
+	3	Part of count
+.ti -2i
+	4	Part of count
+.ti -2i
+	5	Part of count
+.ti -2i
+	6	Part of count
+.ti -2i
+	7	Part of count
+.ti -2i
+	8	Part of count
+.ti -2i
+	9	Part of count
+.ti -2i
+	:	Text. Run single \fIex\fR cmd
+.ti -2i
+count	;	Repeat the previous [fFtT] cmd	MOVE
+.ti -2i
+count	< mv	Shift text left	EDIT
+.ti -2i
+	=	(Not defined)
+.ti -2i
+count	> mv	Shift text right	EDIT
+.ti -2i
+	? text	Search backward for a given regular expression	MOVE
+.ti -2i
+	@	(Not defined)
+.ti -2i
+count	A inp	Append at end of the line	EDIT
+.ti -2i
+count	B	Move back Word	MOVE
+.ti -2i
+	C inp	Change text from cursor through end of line	EDIT
+.ti -2i
+	D	Delete text from  cursor through end of line	EDIT
+.ti -2i
+count	E	Move end of Word	MOVE
+.ti -2i
+count	F key	Move leftward to a given character	MOVE
+.ti -2i
+count	G	Move to line #\fIcount\fR (default is the bottom line)	MOVE
+.ti -2i
+count	H	Move to home row (the line at the top of the screen)
+.ti -2i
+count	I inp	Insert at the front of the line (after indents)	EDIT
+.ti -2i
+count	J	Join lines, to form one big line	EDIT
+.ti -2i
+	K	Look up keyword
+.ti -2i
+count	L	Move to last row (the line at the bottom of the screen)
+.ti -2i
+	M	Move to middle row (the line in the middle)
+.ti -2i
+	N	Repeat previous search, but the opposite way	MOVE
+.ti -2i
+count	O inp	Open up a new line above the current line	EDIT
+.ti -2i
+	P	Paste text before the cursor
+.ti -2i
+	Q	Quit to EX mode
+.ti -2i
+	R inp	Overtype	EDIT
+.ti -2i
+count	S inp	Change lines, like \fIcount\fRcc
+.ti -2i
+count	T key	Move leftward \fIalmost\fR to a given character	MOVE
+.ti -2i
+	U	Undo all recent changes to the current line
+.ti -2i
+	V	(Not defined)
+.ti -2i
+count	W	Move forward \fIcount\fR Words	MOVE
+.ti -2i
+count	X	Delete the character(s) to the left of the cursor	EDIT
+.ti -2i
+count	Y	Yank text line(s) (copy them into a cut buffer)
+.ti -2i
+	Z Z	Save the file & exit
+.ti -2i
+	[ [	Move back 1 section	MOVE
+.ti -2i
+	\e	(Not defined)
+.ti -2i
+	] ]	Move forward 1 section					MOVE
+.ti -2i
+	^	Move to the front of the current line (after indent)	MOVE
+.ti -2i
+	\(ul	(Not defined)
+.ti -2i
+	` key	Move to a marked character	MOVE
+.ti -2i
+count	a inp	Insert text after the cursor	EDIT
+.ti -2i
+count	b	Move back \fIcount\fR words	MOVE
+.ti -2i
+	c mv	Change text	EDIT
+.ti -2i
+	d mv	Delete text	EDIT
+.ti -2i
+count	e	Move forward to the end of the current word	MOVE
+.ti -2i
+count	f key	Move rightward to a given character	MOVE
+.ti -2i
+	g	(Not defined)
+.ti -2i
+count	h	Move left	MOVE
+.ti -2i
+count	i inp	Insert text at the cursor	EDIT
+.ti -2i
+count	j	Move down	MOVE
+.ti -2i
+count	k	Move up	MOVE
+.ti -2i
+count	l	Move right	MOVE
+.ti -2i
+	m key	Mark a line or character
+.ti -2i
+	n	Repeat the previous search	MOVE
+.ti -2i
+count	o inp	Open a new line below the current line	EDIT
+.ti -2i
+	p	Paste text after the cursor
+.ti -2i
+	q	(Not defined)
+.ti -2i
+count	r key	Replace \fIcount\fR chars by a given character	EDIT
+.ti -2i
+count	s inp	Replace \fIcount\fR chars with text from the user	EDIT
+.ti -2i
+count	t key	Move rightward \fIalmost\fR to a given character	MOVE
+.ti -2i
+	u	Undo the previous edit command
+.ti -2i
+	v	(Not defined)
+.ti -2i
+count	w	Move forward \fIcount\fR words	MOVE
+.ti -2i
+count	x	Delete the character that the cursor's on	EDIT
+.ti -2i
+	y mv	Yank text (copy it into a cut buffer)
+.ti -2i
+	z key	Scroll current line to the screen's +=top -=bottom .=middle
+.ti -2i
+count	{	Move back \fIcount\fR paragraphs	MOVE
+.ti -2i
+count	|	Move to column \fIcount\fR (the leftmost column is 1)
+.ti -2i
+count	}	Move forward \fIcount\fR paragraphs	MOVE
+.ti -2i
+.tr ~~
+count	\(ap	Switch a character between upper & lower case	EDIT
+.tr ~
+.ti -2i
+	DEL	(Not defined)
+.in -2i
+.SS "Ex Commands"
+.PP
+Below is a list of the \fIex\fR commands supported.  All can be abbreviated.
+.UU "General"
+.LP
+.nf
+.ta 1.2i 2.4i
+[line]	append
+	args	[files]
+	cd	[directory]
+	chdir	[directory]
+[line][,line]	change
+[line][,line]	copy	line
+[line][,line]	debug[!]
+[line][,line]	Delete	[\*(CQx]
+	edit[!]	[file]
+	ex[!]	[file]
+	file
+[line][,line]	global	/regexp/ command
+[line]	Insert
+[line][,line]	join
+[line][,line]	list
+	map[!]	key mapped_to
+[line]	mark	x
+	mkexrc
+[line][,line]	Move	line
+	next[!]	[files]
+	Next[!]
+	previous[!]
+[line][,line]	print
+[line]	put	[\*(CQx]
+	quit[!]
+[line]	read	file
+	rewind[!]
+	set	[options]
+[line][,line]	substitute	/regexp/replacement/[p][g]
+	tag[!]	tagname
+[line][,line]	to	line
+	Undo
+	unmap[!]	key
+	validate[!]
+	version
+[line][,line]	vglobal	/regexp/ command
+	visual
+	wq
+[line][,line]	write[!]	[[>>]file]
+	xit[!]
+[line][,line]	yank	[\*(CQx]
+[line][,line]	!	command
+[line][,line]	<
+[line][,line]	=
+[line][,line]	>
+.SP 0.25
+.UU "Text Entry"
+.SP 0.25
+.LP
+.ta 1.2i 2.4i
+.nf
+[line]	append
+[line][,line]	change [\*(CQx]
+[line]	Insert
+.fi
+
+The (a)ppend command inserts text after the specified line.
+
+The (i)nsert command inserts text before the specified line.
+
+The (c)hange command copies the range of lines into a cut buffer,
+deletes them, and inserts new text where the old text used to be.
+
+For all of these commands, you indicate the end of the text you're
+inserting by hitting ^D or by entering a line which contains only
+a period.
+.SP 0.25
+.UU "Cut & Paste"
+.SP 0.25
+.LP
+.ta 1.2i 2.4i
+.nf
+[line][,line]	Delete [\*(CQx]
+[line][,line]	yank [\*(CQx]
+[line]	put[!] [\*(CQx]
+[line][,line]	copy line
+[line][,line]	to line
+[line][,line]	Move line
+
+.fi
+The (d)elete command copies the specified range of lines into a
+cut buffer, and then deletes them.
+
+The (y)ank command copies the specified range of lines into a cut
+buffer, but does \fInot\fR delete them.
+
+The (pu)t command inserts text from a cut buffer after the specified
+line\(emor before it if the ! is present.
+
+The (co)py and (t)o commands yank the specified range of lines and then
+immediately paste them after some other line.
+
+The (m)ove command deletes the specified range of lines and then
+immediately pastes them after some other line.  If the destination
+line comes after the deleted text, then it will be adjusted
+automatically to account for the deleted lines.
+.UU "Displaying Text"
+.LP
+.ta 1.2i 2.4i
+.nf
+[line][,line]	print
+[line][,line]	list
+
+.fi
+The (p)rint command displays the specified range of lines.
+
+The (l)ist command also displays them, but it is careful to make
+control characters visible.
+.UU "Global Operations"
+.LP
+.ta 1.2i 2.4i
+.nf
+[line][,line]	global /regexp/ command
+[line][,line]	vglobal /regexp/ command
+
+.fi
+The (g)lobal command searches through the lines of the specified range
+(or through the whole file if no range is specified) for lines that
+contain a given regular expression.  It then moves the cursor to each
+of these lines and runs some other command on them.
+
+The (v)global command is similar, but it searches for lines that
+\fIdo not\fR contain the regular expression.
+.UU "Line Editing"
+.LP
+.ta 1.2i 2.4i
+.nf
+[line][,line]	join
+[line][,line]	! program
+[line][,line]	<
+[line][,line]	>
+[line][,line]	substitute /regexp/replacement/[p][g]
+
+.fi
+The (j)oin command concatenates all lines in the specified range together
+to form one big line.  If only a single line is specified, then the
+following line is catenated onto it.
+
+The ! command runs an external filter program, and feeds the specified
+range of lines to it's stdin.  The lines are then replaced by the
+output of the filter.  A typical example would be \*(OQ:'a,'z!sort -n\*(CQ to
+sort the lines 'a,'z according to their numeric values.
+
+The < and > commands shift the specified range of lines left or right,
+normally by the width of 1 tab character.  The \*(OQshiftwidth\*(CQ option
+determines the shifting amount.
+
+The (s)ubstitute command finds the regular expression in each line,
+and replaces it with the replacement text.  The \*(OQp\*(CQ option causes
+the altered lines to be printed, and the \*(OQg\*(CQ option permits all
+instances of the regular expression to be found & replaced.  (Without
+\*(OQg\*(CQ, only the first occurrence is replaced.)
+.SP 0.25
+.UU "Undo"
+.SP 0.25
+.LP
+.ta 1.2i 2.4i
+.nf
+	undo
+
+.fi
+The (u)ndo command restores the file to the state it was in before your
+most recent command which changed text.
+.SP 0.25
+.UU "Configuration & Status"
+.SP 0.25
+.LP
+.ta 1.2i 2.4i
+.nf
+	map[!] [key mapped_to]
+	unmap[!] key
+	set [options]
+	mkexrc
+[line]	mark x
+	visual
+	version
+[line][,line]	=
+	file
+
+.fi
+The (ma)p command allows you to configure \fIelvis\fR to recognize your
+function keys, and treat them as though they transmitted some other
+sequence of characters.  Normally this mapping is done only when in
+the visual command mode, but with the [!]	present it will map keys
+under all contexts.  When this command is given with no arguments,
+it prints a table showing all mappings currently in effect.  When
+called with two arguments, the first is the sequence that your
+function key really sends, and the second is the sequence that you
+want \fIelvis\fR to treat it as having sent.
+
+The (unm)ap command removes key definitions that were made via the
+map command.
+
+The (se)t command allows you examine or set various options.  With
+no arguments, it displays the values of options that have been
+changed.  With the single argument \*(OQall\*(CQ it displays the values of
+all options, regardless of whether they've been explicitly set or
+not.  Otherwise, the arguments are treated as options to be set.
+
+The (mk)exrc command saves the current configuration to a file
+called \fI.exrc\fR in the current directory.
+
+The mar(k) command defines a named mark to refer to a specific place
+in the file.  This mark may be used later to specify lines for other
+commands.
+
+The (vi)sual command puts the editor into visual mode.  Instead of
+emulating ex, \fIelvis\fR will start emulating vi.
+
+The (ve)rsion command tells you that what version of \fIelvis\fR this is.
+
+The = command tells you what line you specified, or, if you specified
+a range of lines, it will tell you both endpoints and the number of
+lines included in the range.
+
+The file command tells you the name of the file, whether it has been
+modified, the number of lines in the file, and the current line number.
+.UU "Multiple Files"
+.LP
+.ta 1.2i 2.4i
+.nf
+	args [files]
+	next[!] [files]
+	Next[!]
+	previous[!]
+	rewind[!]
+
+.fi
+When you invoke \fIelvis\fR from your shell's command line, any filenames
+that you give to \fIelvis\fR as arguments are stored in the args list.  The
+(ar)gs command will display this list, or define a new one.
+
+The (n)ext command switches from the current file to the next one in
+the args list.  You may specify a new args list here, too.
+
+The (N)ext and (pre)vious commands (they're really aliases for the same
+command) switch from the current file to the preceding file in the
+args list.
+
+The (rew)ind command switches from the current file to the first file
+in the args list.
+.SP 1
+.UU "Switching Files"
+.SP 1
+.LP
+.ta 1.2i 2.4i
+.nf
+	edit[!] [file]
+	tag[!] tagname
+
+.fi
+The (e)dit command allows to switch from the current file to some other
+file.  This has nothing to do with the args list, by the way.
+
+The (ta)g command looks up a given tagname in a file called \*(OQtags".
+This tells it which file the tag is in, and how to find it in that file.
+\fIElvis\fR then switches to the tag's file and finds the tag.
+.SP 1
+.UU "Exiting"
+.SP 1
+.LP
+.ta 1.2i 2.4i
+.nf
+	quit[!]
+	wq
+	xit
+
+.fi
+The (q)uit command exits from the editor without saving your file.
+
+The (wq) and (x)it commands (really two names for the same command)
+both write the file before exiting.
+.UU "File I/O"
+.LP
+.ta 1.2i 2.4i
+.nf
+[line]	read file
+[line][,line]	write[!][[>>]file]
+
+.fi
+The (r)ead command gets text from another file and inserts it after
+the specified line.
+
+.fi
+The (w)rite command writes the whole file, or just part of it, to
+some other file.  The !, if present, will permit the lines to be
+written even if you've set the readonly option.  If you precede the
+filename by >> then the lies will be appended to the file.
+.UU "Directory"
+.LP
+.ta 1.2i 2.4i
+.nf
+	cd [directory]
+	chdir [directory]
+	shell
+
+.fi
+The (cd) and (chd)ir commands (really two names for one command)
+switch the current working directory.
+
+The (sh)ell command starts an interactive shell.
+.SP 0.5
+.UU "Debugging"
+.SP 0.5
+.LP
+.ta 1.2i 2.4i
+.nf
+[line][,line]	debug[!]
+	validate[!]
+
+.fi
+These commands are only available if you compile \fIelvis\fR with the
+\fB-DDEBUG\fR flag.
+
+The de(b)ug command lists stats for the blocks which contain the
+specified range of lines.  If the ! is present, then the contents
+of those blocks is displayed, too.
+
+The (va)lidate command checks certain variables for internal
+consistency.  Normally it does not output anything unless it detects
+a problem.  With the !, though, it will always produce *some*
+output.
+.SP 0.5
+.SS "Extensions"
+.SP 0.5
+.PP.
+.ta 1i
+.in +0.25i
+In addition to the standard commands, a variety of extra features are
+present in \fIelvis\fR that are not present in \fIvi\fR.
+They are described below.
+
+.ti -0.25i
+.B .exrc
+.br
+\fIElvis\fR first runs a \fI.exrc\fR file (if there is one) from your $HOME
+directory. After that, it runs a \fI.exrc\fR (if there is one) from the
+current directory.  The one in the current directory may override
+settings made by the one in the $HOME directory.
+
+.ti -0.25i
+.B :mkexrc
+.ti -0.25i
+.B :mk
+.br
+This EX command saves the current :set and :map configurations in
+the \*(OQ.exrc\*(CQ file in your current directory.
+
+.ti -0.25i
+.B :args
+.ti -0.25i
+.B :ar
+.br
+You can use the :args command to define a new args list, as in:
+
+	:args *.h
+
+After you have defined a new args list, the next time you issue a
+:next command \fIelvis\fR will switch to the first file of the new list.
+
+.ti -0.25i
+.B :Next
+.ti -0.25i
+.B :previous
+.ti -0.25i
+.B :N
+.ti -0.25i
+.B :pre
+.br
+These commands move backwards through the args list.
+
+.ti -0.25i
+.B zz
+.br
+In VI, the (lowercase) \*(OQzz\*(CQ command will center the current line on
+the screen, like \*(OQz="
+
+.ti -0.25i
+.B .
+.br
+The default count value for . is the same as the previous command
+which . is meant to repeat.  However, you can supply a new count
+if you wish.  
+For example, after \*(OQ3dw\*(CQ, \*(OQ.\*(CQ will delete 3 words,
+but \*(OQ5.\*(CQ will delete 5 words.
+
+.ti -0.25i
+\fB"\fR
+.br
+The text which was most recently input (via a \*(OQcw\*(CQ command, or
+something similar) is saved in a cut buffer called ". (which is a
+pretty hard name to write in an English sentence).  You can use this
+with the \*(OQp\*(CQ or \*(OQP\*(CQ commands thusly:
+.HS
+	".p
+.HS
+.ti -0.25i
+.B K
+.br
+You can move the cursor onto a word and press shift-K to have \fIelvis\fR
+run a reference program to look that word up.  This command alone is
+worth the price of admission!  See the ctags and ref programs.
+
+.ti -0.25i
+.B input
+.br
+You can backspace back past the beginning of the line.
+If you type CTRL-A, then the text that you input last time is
+inserted.  You will remain in input mode, so you can backspace over
+part of it, or add more to it.  (This is sort of like CTRL-@ on
+the real vi, except that CTRL-A really works.)
+
+Real \fIvi\fR can only remember up to 128 characters of input, but \fIelvis\fR
+can remember any amount.
+
+.ti -0.25i
+.B :set
+charattr
+.ti -0.25i
+.B :se
+ca
+.br
+\fIElvis\fR can display \*(OQbackslash-f\*(CQ style character attributes on the
+screen as you edit.  The following example shows the recognized
+attributes:
+
+	normal \fBboldface\fR \fIitalics\fR 
+
+NOTE: you must compile \fIelvis\fR without the \(enDSET_NOCHARATTR flag for
+this to work.
+.in -0.25i
+.SS "Omissions"
+.PP
+A few \fIvi\fR features are missing.
+The replace mode is a hack.  It does not save the text that it overwrites.
+.PP
+Long lines are displayed differently\(emwhere the real vi would wrap a long
+line onto several rows of the screen, \fIelvis\fR simply displays part of the line,
+and allows you to scroll the screen sideways to see the rest of it.
+.PP
+The \*(OQ:preserve\*(CQ and \*(OQ:recover\*(CQ commands are missing, as 
+is the \fB\(enr\fR flag.
+\*(OQ:Preserve" is practically never used and since use of \*(OQ:recover\\*(CQ
+is so rare, it was decided to implement it as a separate program.  There's no
+need to load the recovery code into memory every time you edit a file.
+.PP
+LISP support is missing.
+The \*(OQ@\*(CQ and \*(OQ:@\*(CQ commands are missing.
+You cannot APPEND to a cut buffer.
+.SS "Options"
+.PP
+A variety of options can be set as described below:
+.HS
+.nf
+.in +0.25i
+.ta 0.9i 1.35i 2.1i 3.0i
+\fBName	Abbr	Type	Default	Description\fR
+autoindent	as	Bool	FALSE	autoindent during input?
+autowrite	aw	Bool	FALSE	write file for :n command?
+charattr	ca	Bool	FALSE	display bold & underline chars?
+columns	co	Number	80	width of screen, in characters
+directory	dir	String	/usr/tmp	where tmp files are kept
+errorbells	eb	Bool	TRUE	ring bell on error?
+exrefresh	er	Bool	TRUE	EX mode calls write() often?
+ignorecase	ic	Bool	FALSE	searches: upper/lowercase OK?
+keytime	kt	Number	1	allow slow receipt of ESC seq?
+keywordprg	kp	String	/usr/bin/ref	program to run for shift-K
+lines	ln	Number	25	height of screen, in lines
+list	li	Bool	FALSE	show tabs as \*(OQ^I\*(CQ?
+magic	ma	Bool	TRUE	searches: allow metacharacters?
+paragraphs	pa	String	PPppPApa	paragraphs start with .PP, etc.
+readonly	ro	Bool	FALSE	no file should be written back?
+report	re	Number	5	report changes to X lines?
+scroll	sc	Number	12	default #lines for ^U and ^D
+sections	se	String	SEseSHsh	sections start with .SE, etc.
+shell	sh	String	\fI/bin/sh\fR	shell program, from environment
+shiftwidth	sw	Number	8	width of < or > commands
+sidescroll	ss	Number	8	#chars to scroll sideways by
+sync	sy	Bool	FALSE	call sync() after each change?
+tabstop	ts	Number	8	width of a tab character
+term	te	String	"?"	terminal type, from environment
+vbell	vb	Bool	TRUE	use visible bell if possible?
+warn	wa	Bool	TRUE	warn if file not saved for :!cmd
+wrapmargin	wm	Number	0	Insert newline after which col?
+wrapscan	ws	Bool	TRUE	searches: wrap at EOF?
+
+.fi
+.ti -0.25i
+.B autoindent
+.br
+During input mode, the autoindent option will cause each added line
+to begin with the same amount of leading whitespace as the line above
+it.  Without autoindent, added lines are initially empty.
+
+.ti -0.25i
+.B autowrite
+.br
+When you're editing one file and decide to switch to another\(emvia
+the :tag command, or :next command, perhaps\(emif your current
+file has been modified, then \fIelvis\fR will normally print an error
+message and refuse to switch.
+
+However, if the autowrite option is on, then \fIelvis\fR will write the
+modified version of the current file and successfully switch to the
+new file.
+
+.ti -0.25i
+.B charattr
+.br
+Many text formatting programs allow you to designate portions of
+your text to be underlined, italicized, or boldface by embedding
+the special strings \\fU, \\fI, and \\fB in your text.  The special
+string \\fR marks the end of underlined or boldface text.
+
+\fIElvis\fR normally treats those special strings just like any other
+text.
+However, if the \fIcharattr\fR option is on, then \fIelvis\fR will interpret
+those special strings correctly, to display underlined or boldface
+text on the screen.  (This only works, of course, if your terminal
+can display underlined and boldface, and if the TERMCAP entry says
+how to do it.)
+
+.ti -0.25i
+.B columns
+.br
+This is a \*(OQread only\*(CQ option.  You cannot change its value, but you
+can have \fIelvis\fR print it.  It shows how wide your screen is.
+
+.ti -0.25i
+.B directory
+.br
+Elvis uses temporary files to store changed text.
+This option allows you to control where those temporary files will be.
+Ideally, you should store them on in fast non-volatile memory,
+such as a hard disk.
+
+This option can only be set in the ".exrc" file.
+
+.ti -0.25i
+.B errorbells
+.br
+Normally, \fIelvis\fR will ring your terminal's bell if you make an error.
+However, in noerrorbells mode, your terminal will remain silent.
+
+.ti -0.25i
+.B exrefresh
+.br
+The EX mode of \fIelvis\fR writes many lines to the screen.  You can make
+\fIelvis\fR either write each line to the screen separately, or save up
+many lines and write them all at once.
+
+The exrefresh option is normally on, so each line is written to the
+screen separately.
+
+You may wish to turn the exrefresh option off (:se noer) if the
+\*(OQwrite\*(CQ system call is costly on your machine, or if you're using a
+windowing environment.  (Windowing environments scroll text a lot
+faster when you write many lines at once.)
+
+This option has no effect in \fIvi\fR mode.
+
+.ti -0.25i
+.B ignorecase
+.br
+Normally, when \fIelvis\fR searches for text, it treats uppercase letters
+as being different for lowercase letters.
+
+When the ignorecase option is on, uppercase and lowercase are treated
+as equal.
+
+.ti -0.25i
+.B keytime
+.br
+The arrow keys of most terminals send a multi-character sequence.
+It takes a measurable amount of time for these sequences to be
+transmitted.  The keytime option allows you to control the maximum
+amount of time to allow for an arrow key (or other mapped key) to
+be received in full.
+
+The default keytime value is 2.  Because of the way 
+.Ux
+timekeeping works, the actual amount of time allowed will vary slightly, but it
+will always be between 1 and 2 seconds.
+
+If you set keytime to 1, then the actual amount of time allowed will
+be between 0 and 1 second.  This will generally make the keyboard's
+response be a little faster (mostly for the ESC key), but on those
+occasions where the time allowed happens to be closer to 0 than 1
+second, \fIelvis\fR may fail to allow enough time for an arrow key's
+sequence to be received fully.  Ugh.
+
+As a special case, you can set keytime to 0 to disable this time
+limit stuff altogether.  The big problem here is:  If your arrow
+keys' sequences start with an ESC, then every time you hit your ESC
+key \fIelvis\fR will wait... and wait... to see if maybe that ESC was
+part of an arrow key's sequence.
+
+NOTE: this option is a generalization of the timeout option of the
+real vi.
+
+.ti -0.25i
+.B keywordprg
+.br
+\fIElvis\fR has a special keyword lookup feature.  You move the cursor
+onto a word, and hit shift-K, and \fIelvis\fR uses another program to
+look up the word and display information about it.
+
+This option says which program gets run.  It should contain the full
+pathname of the program; your whole execution path is \fInot\fR checked.
+
+The default value of this option is \fI/usr/bin/ref\fR, which is a
+program that looks up the definition of a function in C.  It looks
+up the function name in a file called \*(OQrefs\*(CQ which is created by
+ctags.
+
+You can substitute other programs, such as an English dictionary
+program or the online manual.  \fIelvis\fR runs the program, using the
+keyword as its only argument.  The program should write information
+to stdout.  The program's exit status should be 0, unless you want
+\fIelvis\fR to print \*(OQ<<< failed >>>".
+
+.ti -0.25i
+.B lines
+.br
+This \*(OQread only\*(CQ option shows how many lines you screen has.
+
+.ti -0.25i
+.B list
+.br
+Normally (in \*(OQnolist" mode) \fIelvis\fR will expand tabs to the proper
+number of spaces on the screen, so that the file appears the same would it would
+be if you printed it or looked at it with \fImore\fR.
+
+Sometimes, though, it can be handy to have the tabs displayed as \*(OQ^I".
+In \*(OQlist" mode, \fIelvis\fR does this, and also displays a \*(OQ$"
+after the end of the line.
+
+.ti -0.25i
+.B magic
+.br
+The search mechanism in \fIelvis\fR can accept \*(OQregular 
+expressions\*(CQ\(emstrings in which certain characters have special meaning.
+The magic option is normally on, which causes these characters to
+be treated specially.
+If you turn the magic option off (:se noma), then all characters
+except ^ and $ are treated literally.   ^ and $ retain their special
+meanings regardless of the setting of magic.
+
+.ti -0.25i
+.B paragraphs
+.br
+The { and } commands move the cursor forward or backward in increments
+of one paragraph.  Paragraphs may be separated by blank lines, or by
+a \*(OQdot\*(CQ command of a text formatter.  Different text formatters use
+different \*(OQdot\*(CQ commands.  This option allows you to configure \fIelvis\fR
+to work with your text formatter.
+
+It is assumed that your formatter uses commands that start with a
+".\*(CQ character at the front of a line, and then have a one- or
+two-character command name.
+
+The value of the paragraphs option is a string in which each pair
+of characters is one possible form of your text formatter's paragraph
+command.
+
+.ti -0.25i
+.B readonly
+.br
+Normally, \fIelvis\fR will let you write back any file to which you have
+write permission.  If you do not have write permission, then you
+can only write the changed version of the file to a \fIdifferent\fR
+file.
+
+If you set the readonly option, then \fIelvis\fR will pretend you do not
+have write permission to \fIany\fR file you edit.  It is useful when
+you really only mean to use \fIelvis\fR to look at a file, not to change
+it.  This way you cannot change it accidentally.
+
+This option is normally off, unless you use the \*(OQview\*(CQ alias of \fIelvis\fR.
+\*(OQView\*(CQ is like \fIvi\fR except that the readonly option is on.
+
+.ti -0.25i
+.B report
+.br
+Commands in \fIelvis\fR may affect many lines.  For commands that affect
+a lot of lines, \fIelvis\fR will output a message saying what was done and
+how many lines were affected.  This option allows you to define
+what \*(OQa lot of lines\*(CQ means.  The default is 5, so any command which
+affects 5 or more lines will cause a message to be shown.
+
+.ti -0.25i
+.B scroll
+.br
+The CTRL-U and CTRL-D keys normally scroll backward or forward
+by half a screenful, but this is adjustable.  The value of this option
+says how many lines those keys should scroll by.
+
+.ti -0.25i
+.B sections
+.br
+The [[ and ]] commands move the cursor backward or forward in
+increment of 1 section.  Sections may be delimited by a { character
+in column 1 (which is useful for C source code) or by means of
+a text formatter's \*(OQdot\*(CQ commands.
+
+This option allows you to configure \fIelvis\fR to work with your text
+formatter's \*(OQsection\*(CQ command, in exactly the same way that the
+paragraphs option makes it work with the formatter's \*(OQparagraphs"
+command.
+
+.ti -0.25i
+.B shell
+.br
+When \fIelvis\fR forks a shell (perhaps for the :! or :shell commands)
+this is the program that is uses as a shell.  This is \fI/bin/sh\fR
+by default, unless you have set the SHELL environment variable,
+it which case the default value is copied from the environment.
+
+.ti -0.25i
+.B shiftwidth
+.br
+The < and > commands shift text left or right by some uniform number
+of columns.  The shiftwidth option defines that uniform number.
+The default is 8.
+
+.ti -0.25i
+.B sidescroll
+.br
+For long lines, \fIelvis\fR scrolls sideways.  (This is different from
+the real \fIvi\fR, which wraps a single long line onto several rows of
+the screen.)
+To minimize the number of scrolls needed, \fIelvis\fR moves the screen
+sideways by several characters at a time.  The value of this option
+says how many characters' widths to scroll at a time.
+Generally, the faster your screen can be redrawn, the lower the value
+you will want in this option.
+
+.ti -0.25i
+.B sync
+.br
+If the system crashes during an edit session, then most of your work
+can be recovered from the temporary file that \fIelvis\fR uses to store
+changes.  However, sometimes 
+.MX
+will not copy changes to the
+hard disk immediately, so recovery might not be possible.  The [no]sync
+option lets you control this.
+In nosync mode (which is the default), \fIelvis\fR lets the operating system
+control when data is written to the disk.  This is generally faster.
+In sync mode, \fIelvis\fR forces all changes out to disk every time you make
+a change.  This is generally safer, but slower.
+
+.ti -0.25i
+.B tabstop
+.br
+Tab characters are normally 8 characters wide, but you can change
+their widths by means of this option.
+
+.ti -0.25i
+.B term
+.br
+This \*(OQread only\*(CQ option shows the name of the termcap entry that
+\fIelvis\fR is using for your terminal.
+
+.ti -0.25i
+.B vbell
+.br
+If your termcap entry describes a visible alternative to ringing
+your terminal's bell, then this option will say whether the visible
+version gets used or not.  Normally it will be.
+
+If your termcap does NOT include a visible bell capability, then
+the vbell option will be off, and you cannot turn it on.
+
+.ti -0.25i
+.B warn
+.br
+\fIElvis\fR will normally warn you if you run a shell command without saving
+your changed version of a file.
+The \*(OQnowarn" option prevents this warning.
+
+.ti -0.25i
+.B wrapmargin
+.br
+Normally (with wrapmargin=0) \fIelvis\fR will let you type in extremely long
+lines, if you wish.
+However, with wrapmargin set to something other that 0 (wrapmargin=65
+is nice), \fIelvis\fR will automatically cause long lines to be \*(OQwrapped"
+on a word break for lines longer than wrapmargin's setting.
+
+.ti -0.25i
+.B wrapscan
+.br
+Normally, when you search for something, \fIelvis\fR will find it no matter
+where it is in the file.  \fIelvis\fR starts at the cursor position, and
+searches forward.  If \fIelvis\fR hits EOF without finding what you're
+looking for, then it wraps around to continue searching from line 1.
+
+If you turn off the wrapscan option (:se nows), then when \fIelvis\fR hits
+EOF during a search, it will stop and say so.
+.in -0.25i
+.SS "Cflags"
+.PP
+\fIElvis\fR uses many preprocessor symbols to control compilation.
+Most of these flags allow you to disable small sets of features.
+\s-2MINIX\s0-ST users will probably want all features enabled, but
+\s-2MINIX\s0-PC users will have to disable one or two feature sets
+because otherwise \fIelvis\fR would be too large to compile and run.
+
+These symbols can be defined via flags passed to the compiler.
+The best way to do this is to edit the Makefile, and append the flag
+to the \*(OQCFLAGS=\*(CQ line.
+After you do that, you must recompile elvis completely by saying
+.HS
+.Cx "make  clean"
+.br
+.Cx "make"
+.HS
+.in +0.25i
+.ti -0.25i
+.B \(enDM_SYSV
+.br
+This flag causes \fIelvis\fR to use System-V ioctl() calls for controlling
+your terminal; normally it uses v7/BSD/\s-2MINIX\s0 ioctl() calls.
+
+.ti -0.25i
+.B \(enDDATE
+.br
+The symbol DATE should be defined to look like a string constant,
+giving the date when \fIelvis\fR was compiled.
+This date is reported by the \*(OQ:version\*(CQ command.
+
+You can also leave DATE undefined, in which case \*(OQ:version\*(CQ will not
+report the compilation date.
+
+.ti -0.25i
+.B \(enDCRUNCH
+.br
+This flag causes several large often-used macros to be replaced by
+equivalent functions.
+This saves about 4K of space in the \*(OQ.text\*(CQ segment, and it does not
+cost you any features.
+
+.ti -0.25i
+.B \(enDDEBUG
+.br
+This adds many internal consistency checks and the \*(OQ:debug\*(CQ 
+and \*(OQ:validate\*(CQ
+commands.  It increases the size of \*(OQtext\*(CQ by about 5K bytes.
+
+.ti -0.25i
+.B \(enDNO_CHARATTR
+.br
+This permanenently disables the \*(OQcharattr\*(CQ option.
+It reduces the size of \*(OQ.text\*(CQ by about 850 bytes.
+
+.ti -0.25i
+.B \(enDNO_RECYCLE
+.br
+Normally, \fIelvis\fR will recycle space in the temporary file which contains
+totally obsolete text.
+The \fB\(enDNO_RECYCLE\fR option disables this, making your \*(OQ.text\*(CQ  segment 
+smaller by about 1K but also permitting the temporary file to grow very 
+quickly.
+If you have less than two megabytes of free space on your disk,
+then do not even consider using this flag.
+
+.ti -0.25i
+.B \(enDNO_SENTENCE
+.br
+This leaves out the \*(OQ(\*(CQ and \*(OQ)\*(CQ visual commands, and 
+removes the code that allows the \*(OQ[[\*(CQ, \*(OQ]]\*(CQ, \*(OQ{\*(CQ, 
+and \*(OQ}\*(CQ commands to recognize \fRnroff\fR macros.
+The \*(OQ[[\*(CQ and \*(OQ]]\*(CQ commands will still move to the start of 
+the previous/next C function source code, though, and \*(OQ{\*(CQ 
+and \*(OQ}\*(CQ will move to the previous/next blank line.
+This saves about 650 bytes from the \*(OQ.text\*(CQ segment.
+
+.ti -0.25i
+.B \(enDNO_CHARSEARCH
+.br
+This leaves out the visual commands which locate a given character in the
+current line: \*(OQf\*(CQ, \*(OQt\*(CQ, \*(OQF\*(CQ, \*(OQT\*(CQ, \*(OQ;\*(CQ, and \*(OQ,\*(CQ.
+This saves about 900 bytes.
+
+.ti -0.25i
+.B \(enDNO_EXTENSIONS
+.br
+This leaves out the \*(OQ:mkexrc\*(CQ command, and the \*(OQK\*(CQ and \*(OQ#\*(CQ visual commands.
+Other extensions are either inherent in the design of \fIelvis\fR,
+or are too tiny to be worth removing.
+This saves about 500 bytes.
+
+.ti -0.25i
+.B \(enDNO_MAGIC
+.br
+This permanently disables the \*(OQmagic\*(CQ option, so that most 
+meta-characters in a regular expression are not recognized.  
+This saves about 3K bytes from the \*(OQ.text\*(CQ segment.
+.HS
+.in -0.25i
+.SS "Termcap"
+\fIElvis\fR can use standard termcap entries,
+but it also recognizes and uses several extra capabilities, if you give them.
+All of these are optional.
+.nf
+.in +0.25i
+.ta 1.5i
+.HS
+\fBCapability	Description\fR
+:PU=:	sequence received from the <PgUp> key
+:PD=:	sequence received from the <PgDn> key
+:HM=:	sequence received from the <Home> key
+:EN=:	sequence received from the <End> key
+:VB=:	sequence sent to start bold printing
+:Vb=:	sequence sent to end bold printing
+.in -0.25i
+.SS "Author"
+.PP
+\fIElvis\fR was written by Steve Kirkendall.
+He can be reached by email at: kirkenda@cs.pdx.edu
+for comments regarding \fIelvis\fR.
Index: /trunk/minix/man/man9/kermit.9
===================================================================
--- /trunk/minix/man/man9/kermit.9	(revision 9)
+++ /trunk/minix/man/man9/kermit.9	(revision 9)
@@ -0,0 +1,130 @@
+.so mnx.mac
+.TH KERMIT 9
+.CD "kermit \(en transfer a file using the kermit protocol"
+.SX "kermit"
+.FL "\fR(many)"
+.EY "kermit" "Start kermit"
+.PP
+This is a slightly lobotomized \fIkermit\fR.
+The help command, the script facility, and the automatic dial support
+have been removed.  
+The ? and ESC commands still work, so there is still reasonable built-in help.
+The only V7 \fIkermit\fR feature that does not work is the ability to see
+whether there are input characters waiting.  This means that you will not
+be able to ask for status during a file transfer (though
+this is not critical, because \fIkermit\fR prints a dot every so often and
+other special characters whenever there is an error or timeout).
+.PP
+Start \fIkermit\fR, and then type the following to open a 2400 baud session,
+for example:
+.HS
+.nf
+.Cx "set line /dev/tty1"
+.Cx "set speed 2400"
+.Cx "connect"
+.HS
+.fi
+(It is more convenient if you put these commands in \fI.kermrc\fR in your
+home directory, so that they get done automatically whenever you
+run \fIkermit\fR.)  This will connect you to the modem or whatever on
+the serial port.  Now log into the other system.
+.PP
+When you want to transfer files, run \fIkermit\fR on the other system.
+To it, type
+.HS
+.Cx "server"
+.HS
+This puts its \fIkermit\fR into a sort of \*(OQslave mode\*(CQ where it expects
+commands from the \fIkermit\fR running on your \s-2MINIX\s0 system.  Now come back
+to the command level on \s-2MINIX\s0 \fIkermit\fR, by typing the escape character
+followed by \fIc\fR.  (\fIKermit\fR will tell you 
+the current escape character when
+you do the connect command.)  At this point you can issue various
+commands. 
+Your \fIkermit\fR will coordinate things with \fIkermit\fR on the other
+machine so that you only have to type commands at one end.  Common
+commands are
+.HS
+.Cx "get \fI\s+2filename\fP\s0"
+.br
+.Cx "put \fI\s+2filename\fP\s0"
+.br
+.Cx "remote \fI\s+2dir\fP\s0"
+.HS
+\fRFilenames can include wildcards.  By default, \fIkermit\fR works in a
+system-independent, text mode.  (In effect it assumes that the
+whole world is \s-2MS-DOS\s0 and converts end of line and file names
+accordingly.)  To send binary files, you will want to type
+.HS
+.Cx "set file type bin"
+.HS
+on both ends before starting any transfers.  This disables
+CR LF to newline conversion.  If both of your systems are some
+flavor of \s-2UNIX\s0, you might as well put this in \fI.kermrc\fR on both
+ends and run in binary mode all the time.  Also, if both systems
+are \s-2UNIX\s0 it is recommended that you use
+.HS
+.Cx "set file name lit"
+.HS
+on both ends.  This causes it to keep file names unchanged,
+rather than mapping to legal \s-2MS-DOS\s0 names.
+.PP
+Here is a typical \fI.kermrc\fR for use on
+.MX :
+.HS
+.nf
+.Cx "set line /dev/tty1"
+.Cx "set speed 1200"
+.Cx "set esc 29"
+.Cx "set file type bin"
+.Cx "set file name lit"
+.Cx "set retry 90"
+.Cx "set prompt MINIX kermit>"
+.Cx "connect"
+.fi
+.PP
+On the other end of the line, for example, the host at your local computer
+center to which you want to transfer files, a typical profile might be:
+.HS
+.nf
+.Cx "set rec packet 1000"
+.Cx "set fil name lit"
+.Cx "set fil type bin"
+.Cx "server"
+.fi
+.HS
+.PP
+\fIKermit\fR has many other options and features.  For a pleasant and
+highly readable description of it, see the following book:
+.HS
+.in +0.25i
+.nf
+Title: Kermit: A File Transfer Protocol
+Author: Frank da Cruz
+Publisher: Digital Press
+Date: 1987
+ISBN: 0-932376-88
+.fi
+.in -0.25i
+.HS
+.PP
+For information about recent \fIkermit\fR developments, versions for other
+systems, and so forth, please contact:
+.nf
+.HS
+.in +0.25i
+Christine M. Gianone
+Manager, Kermit Development and Distribution
+University Center for Computing Activities
+Columbia University
+612 West 115th Street
+New York, N.Y. 10025
+.in -0.25i
+.HS
+.fi
+Over 400 versions of \fIkermit\fR are available, so it is likely there is one
+for any computer your
+.MX
+system might want to talk to.
+Columbia University also publishes a newsletter about \fIkermit\fR that can be
+requested from the above address.
Index: /trunk/minix/man/man9/m4.9
===================================================================
--- /trunk/minix/man/man9/m4.9	(revision 9)
+++ /trunk/minix/man/man9/m4.9	(revision 9)
@@ -0,0 +1,185 @@
+.so mnx.mac
+.TH M4 9
+.CD "m4 \(en macro processor"
+.SX "m4\fR [\fB\(enD \fIname\fR = \fIvalue\fR]\fR [\fB\(enU \fIname\fR] 
+.FL "\(enD" "Define a symbol"
+.FL "\(enU" "Undefine a symbol"
+.EY "m4 <m4test" "Run M4"
+.PP
+\fIM4\fR is a macro processor intended as a front end
+for Ratfor, Pascal, and other languages that do not have a built-in macro 
+processing capability.  M4 reads standard input, the processed text is 
+written on the standard output.
+.PP
+The options and their effects are as follows:
+
+.in +0.5i
+.ta 1.25i
+\(enD name[=val]	Defines name to val, or to null in val's absence.
+.br
+\(enU name	Undefines name.
+.in -0.5i
+
+.PP
+Macro calls have the form: name(arg1,arg2, ..., argn)
+
+The \*(OQ(\*(CQ must immediately follow the name of the macro.  
+If the name of a 
+defined macro is not followed by a ( it is taken to be a call of that macro 
+with no arguments, i.e. name().  Potential macro names consist of alphabetic 
+letters and digits.
+.PP
+Leading unquoted blanks, tabs and newlines are ignored while collecting 
+arguments.  Left and right single quotes are used to quote strings.  The value 
+of a quoted string is the string stripped of the quotes.
+.PP
+When a macro name is recognized, its arguments are collected by searching 
+for a matching ).  If fewer arguments are supplied than are in the macro 
+definition, the trailing arguments are taken to be null.  Macro evaluation 
+proceeds normally during the collection of the arguments, and any commas or 
+right parentheses which happen to turn up within the value of a nested call 
+are as effective as those in the original input text.  (This is typically 
+referred as  inside-out macro expansion.)  After argument collection, the 
+value of the macro is pushed back onto the input stream and rescanned.  
+.PP
+M4 makes available the following built-in macros.  They may be 
+redefined, but once this is done the original meaning is lost.  Their values 
+are null unless otherwise stated.
+.PP
+\fBdefine "(name [, val])"\fR the second argument is installed as the value of 
+the macro whose name is the first argument.  If there is no second argument, 
+the value is null.  Each occurrence of $ n in the replacement text, where n is 
+a digit, is replaced by the n -th argument.  Argument 0 is the name of the 
+macro; missing arguments are replaced by the null string.
+.PP
+\fBdefn "(name [, name ...])"\fR returns the quoted definition of its 
+argument(s). Useful in renaming macros.
+.PP
+\fBundefine "(name [, name ...])"\fR removes the definition of the macro(s) 
+named. If there is more than one definition for the named macro, (due to 
+previous use of pushdef) all definitions are removed.
+.PP
+\fBpushdef "(name [, val])"\fR like define, but saves any previous definition 
+by stacking the current definition.
+.PP
+\fBpopdef "(name [, name ...])"\fR removes current definition of its 
+argument(s), exposing the previous one if any.
+.PP
+\fBifdef "(name, if-def [, ifnot-def])"\fR if the first argument is defined, 
+the value is the second argument, otherwise the third.  If there is no third 
+argument, the value is null.  A word indicating the current operating system 
+is predefined.  (e.g. unix or vms).
+.PP
+\fBshift "(arg, arg, arg, ...)"\fR returns all but its first argument.  The 
+other arguments are quoted and pushed back with commas in between.  The 
+quoting nullifies the effect of the extra scan that will subsequently be 
+performed.
+.PP
+\fBchangequote "(lqchar, rqchar)"\fR change quote symbols to the first and 
+second arguments.  With no arguments, the quotes are reset back to the default 
+characters. (i.e., `').
+.PP
+\fBchangecom "(lcchar, rcchar)"\fR change left and right comment markers from 
+the default # and newline.  With no arguments, the comment mechanism is reset 
+back to the default characters.  With one argument, the left marker becomes 
+the argument and the right marker becomes newline.  With two arguments, both 
+markers are affected.
+.PP
+\fBdivert "(divnum)"\fR maintains 10 output streams, numbered 0-9.  Initially 
+stream 0 is the current stream. The divert macro changes the current output 
+stream to its (digit-string) argument.  Output diverted to a stream other than 
+0 through 9 is lost.
+.PP
+\fBundivert "([divnum [, divnum ...]])"\fR causes immediate output of text from 
+diversions named as argument(s), or all diversions if no argument.  Text may 
+be undiverted into another diversion.  Undiverting discards the diverted text. 
+At the end of input processing, M4 forces an automatic undivert unless is 
+defined.
+.PP
+\fBdivnum "()"\fR returns the value of the current output stream.
+.PP
+\fBdnl "()"\fR reads and discards characters up to and including the next 
+newline.
+.PP
+\fBifelse "(arg, arg, if-same [, ifnot-same | arg, arg ...])"\fR has three or 
+more arguments.  If the first argument is the same string as the second, then 
+the value is the third argument.  If not, and if there are more than four 
+arguments, the process is repeated with arguments 4, 5, 6 and 7.  Otherwise, 
+the value is either the fourth string, or, if it is not present, null.
+.PP
+\fBincr "(num)"\fR returns the value of its argument incremented by 1.  The 
+value of the argument is calculated by interpreting an initial digit-string as 
+a decimal number.
+.PP
+\fBdecr "(num)"\fR returns the value of its argument decremented by 1.
+.PP
+\fBeval "(expression)"\fR evaluates its argument as a constant expression, 
+using integer arithmetic.  The evaluation mechanism is very similar to that of 
+cpp (#if expression).  The expression can involve only integer constants and 
+character constants, possibly connected by the binary operators
+.HS
+.in +0.5i
+*    /    %    +    -    >>   <<    <    >   <=   >=   ==   !=   &    ^    |     &&   ||
+.in -0.5i
+.HS
+or the unary operators - ! or tilde or by the ternary operator ? : .  
+Parentheses may be used for grouping. Octal numbers may be specified as in C.
+.PP
+\fBlen "(string)"\fR returns the number of characters in its argument.
+.PP
+\fBindex "(search-string, string)"\fR returns the position in its first 
+argument where the second argument begins (zero origin), or 1 if the second 
+argument does not occur.
+.PP
+\fBsubstr "(string, index [, length])"\fR returns a substring of its first 
+argument. The second argument is a zero origin number selecting the first 
+character (internally treated as an expression); the third argument indicates 
+the length of the substring.  A missing third argument is taken to be large 
+enough to extend to the end of the first string. 
+.PP
+\fBtranslit  "(source, from [, to])"\fR transliterates the characters in its 
+first argument from the set given by the second argument to the set given by 
+the third.  If the third argument is shorter than the second, all extra 
+characters in the second argument are deleted from the first argument. If the 
+third argument is missing altogether, all characters in the second argument 
+are deleted from the first argument.
+.PP
+\fBinclude "(filename)"\fR returns the contents of the file that is 
+named in the argument.
+.PP
+\fBsinclude "(filename)"\fRis identical to include, except that it says nothing 
+if the file is inaccessable.
+.PP
+\fBpaste "(filename)"\fR returns the contents of the file named in the argument
+without any processing, unlike include.
+.PP
+\fBspaste "(filename)"\fR is identical to paste, except that it says nothing if
+the file is inaccessibl[De.
+.PP
+\fBsyscmd "(command)"\fR executes the 
+.Ux
+command given in the first argument.  
+No value is returned.
+.PP
+\fBsysval "()"\fR is the return code from the last call to syscmd.
+ .PP
+\fBmaketemp \*(OQ(string)"\fR fills in a string of XXXXXX in its argument with the 
+current process ID.
+.PP
+\fBm4exit "([exitcode])"\fR causes immediate exit from M4.  Argument 1, if 
+given, is the exit code; the default is 0.
+.PP
+\fBm4wrap "(m4-macro-or-built-n)"\fR argument 1 will be pushed back at final 
+EOF; example: m4wrap(`dumptable()').
+.PP
+\fBerrprint "(str [, str, str, ...])"\fR prints its argument(s) on stderr. If 
+there is more than one argument, each argument is separated by a space during 
+the output.  An arbitrary number of arguments may be supplied.
+.PP
+\fBdumpdef "([name, name, ...])"\fR prints current names and definitions, for 
+the named items, or for all if no arguments are given.
+.SP 1
+.SS "Author"
+.SP 1
+.PP
+\fIM4\fR was written by Ozan S. Yigif.
Index: /trunk/minix/man/man9/macros.9
===================================================================
--- /trunk/minix/man/man9/macros.9	(revision 9)
+++ /trunk/minix/man/man9/macros.9	(revision 9)
@@ -0,0 +1,1465 @@
+.so mnx.mac
+.TH MACROS 9
+.\" Macro package for producing books (based on -ms)
+.nr PS 12
+.nr PZ 12
+.\"	RT -  reset everything to normal state
+.de RT
+.if !\\n(1T .BG
+.ce 0
+.if !\\n(IK .if !\\n(IF .if !\\n(IX .if !\\n(BE .di
+.ul 0
+.if \\n(QP \{\
+.	ll +\\n(QIu
+.	in -\\n(QIu
+.	nr QP -1\}
+.if \\n(NX<=1 .if \\n(AJ=0 .ll \\n(LLu
+.if \\n(IF=0 \{\
+.	ps \\n(PS
+.	if \\n(VS>=41 .vs \\n(VSu
+.	if \\n(VS<=40 .vs \\n(VSp\}
+.if \\n(IP .in -\\n(I\\n(IRu
+.if \\n(IP=0 .nr I0 \\n(PIu
+.if \\n(IP .nr IP -1
+.ft 1
+.bd 1
+.ta 5n 10n 15n 20n 25n 30n 35n 40n 45n 50n 55n 60n 65n 70n 75n 80n
+.fi
+..
+.	\"IZ - initialization
+.de IZ
+.nr TN 0
+.em EM
+.if n .ds [. [
+.if t .ds [. \s-2\v'-.4m'\f1
+.if n .ds .] ]
+.if t .ds .] \v'.4m'\s+2\fP
+.if n .ds [o ""
+.if n .ds [c ""
+.if t .ds [o ``
+.if t .ds [c ''
+.ch FO \\n(YYu
+.if \\n(FM=0 .nr FM 1i
+.nr YY -\\n(FMu
+.nr XX 0 1
+.nr IP 0
+.nr PI 5n
+.nr QI 5n
+.nr I0 \\n(PIu
+.nr PZ 12
+.nr VZ 13.8p
+.nr PS \n(PZ
+.nr VS \\n(VZu
+.if !\\n(PD .if n .nr PD 1v
+.if !\\n(PD .if t .nr PD 0.3v
+.nr ML 3v
+.ps \\n(PS
+.if \\n(VS>=41 .vs \\n(VSu
+.if \\n(VS<=40 .vs \\n(VSp
+.nr IR 0
+.nr TB 0
+.nr SJ \\n(.j
+.nr LL 6i
+.ll \\n(LLu
+.nr LT \\n(.l
+.lt \\n(LTu
+.ev 1
+.nr FL \\n(LLu*11u/12u
+.ll \\n(FLu
+.ps 10
+.vs 12p
+.ev
+.if \\*(CH .ds CH "\(hy \\\\n(PN \(hy
+.wh 0 NP
+.wh -\\n(FMu FO
+.ch FO 16i
+.wh -\\n(FMu FX
+.ch FO -\\n(FMu
+.if t .wh -\\n(FMu/2u BT
+.if n .wh -\\n(FMu/2u-1v BT
+..
+.	\"KS keep - for keep release features. As in IFM
+.de KS
+.nr KN \\n(.u
+.if \\n(IK=0 .if \\n(IF=0 .KQ
+.nr IK +1
+..
+.	\"KQ - real keep processor
+.de KQ
+.br
+.nr KI \\n(.i
+.ev 2
+.br
+.in \\n(KIu
+.ps \\n(PS
+.if \\n(VS>40 .vs \\n(VSu
+.if \\n(VS<=39 .vs \\n(VSp
+.ll \\n(LLu
+.lt \\n(LTu
+.if \\n(NX>1 .ll \\n(CWu
+.if \\n(NX>1 .lt \\n(CWu
+.di KK
+.nr TB 0
+.nr KV 0
+..
+.	\"KF - floating keep
+.de KF
+.nr KN \\n(.u
+.if !\\n(IK .FQ
+.nr IK +1
+..
+.	\"FQ real floating keep processor
+.de FQ
+.nr KI \\n(.i
+.ev 2
+.br
+.in \\n(KIu
+.ps \\n(PS
+.if \\n(VS>40 .vs \\n(VSu
+.if \\n(VS<=39 .vs \\n(VSp
+.ll \\n(LLu
+.lt \\n(LTu
+.if \\n(NX>1 .ll \\n(CWu
+.if \\n(NX>1 .lt \\n(CWu
+.di KK
+.nr TB 1
+.nr KV 0
+..
+.	\"KP - keep full page
+.de KP
+.nr KV 1
+..
+.	\"KE release - everything between keep and release is together
+.de KE
+.if \\n(IK .if !\\n(IK-1 .if \\n(IF=0 .RQ
+.if \\n(IK .nr IK -1
+..
+.	\"RQ real release
+.de RQ
+.br
+.di
+.nr NF 0
+.if \\n(dn-\\n(.t .nr NF 1
+.if \\n(TC .nr NF 1
+.if \\n(KV .nr NF 1 \" if KV on full page needed, doesn't fit
+.if \\n(NF .if !\\n(TB .sp 11i
+.if !\\n(NF .if \\n(TB .nr TB 0
+.nf
+.rs
+.nr TC 5
+.in 0
+.ls 1
+.if \\n(TB=0 .ev
+.if \\n(TB=0 .br
+.if \\n(TB=0 .ev 2
+.if \\n(TB=0 .KK
+.ls
+.ce 0
+.if \\n(TB=0 .rm KK
+.if \\n(TB .da KJ
+.if \\n(TB \!.KD \\n(dn \\n(KV
+.if \\n(TB .KK
+.if \\n(TB .di
+.nr TC \\n(TB
+.if \\n(KN .fi
+.in
+.ev
+..
+.de EQ  \"equation, breakout and display
+.nr EF \\n(.u
+.rm EE
+.nr LE 1	\" 1 is center
+.ds EL \\$1
+.if "\\$1"L" .ds EL \\$2
+.if "\\$1"L" .nr LE 0
+.if "\\$1"C" .ds EL \\$2
+.if "\\$1"I" .nr LE 0
+.if "\\$1"I" .ds EE \\h'|10n'
+.if "\\$1"I" .if !"\\$3"" .ds EE \\h'\\$3'
+.if "\\$1"I" .ds EL \\$2
+.if \\n(YE>0 .nf
+.di EZ
+..
+.de EN  \" end of a displayed equation
+.br
+.di
+.rm EZ
+.nr ZN \\n(dn
+.if \\n(ZN>0 .if \\n(YE=0 .LP
+.if \\n(ZN=0 .if !"\\*(EL"" .nr ZN 1
+.if "\\n(.z"" .if \\n(ZN>0 .if !\\n(nl=\\n(PE .if t .sp .5
+.if "\\n(.z"" .if \\n(ZN>0 .if !\\n(nl=\\n(PE .if n .sp 1
+.if !"\\n(.z"" .if \\n(ZN>0 .if !\\n(.d=\\n(PE .if t .sp .5
+.if !"\\n(.z"" .if \\n(ZN>0 .if !\\n(.d=\\n(PE .if n .sp 1
+'pc
+.if \\n(BD>0 .nr LE 0 \" can't mean centering in this case.
+.if \\n(MK>0 .if \\n(LE=1 .ds EE \\h'|10n'
+.if \\n(MK>0 .nr LE 0 \" don't center if mark/lineup
+'lt \\n(.lu
+.if \\n(EP=0 .if \\n(ZN>0 .if \\n(LE>0 .tl \(ts\(ts\\*(10\(ts\\*(EL\(ts
+.if \\n(EP=0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD=0 .tl \(ts\\*(EE\\*(10\(ts\(ts\\*(EL\(ts
+.if \\n(EP=0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD>0 .if \\n(BD<\\w\(ts\\*(10\(ts .nr BD \\w\(ts\\*(10\(ts
+.if \\n(EP=0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD>0 \!\\*(10\\t\\*(EL
+.if \\n(EP>0 .if \\n(ZN>0 .if \\n(LE>0 .tl \(ts\\*(EL\(ts\\*(10\(ts\(ts
+.if \\n(EP>0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD=0 .tl \(ts\\*(EL\\*(EE\\*(10\(ts\(ts\(ts
+.if \\n(EP>0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD>0 .if \\n(BD<\\w\(ts\\*(10\(ts .nr BD \\w\(ts\\*(10\(ts
+.if \\n(EP>0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD>0 \!\\h'-\\\\n(.iu'\\*(EL\\h'|0'\\*(10
+.\".di EZ \" GCOS patch
+.\"\\*(10 \" GCOS patch
+.\".br \" GCOS patch
+.\".di \" GCOS patch
+.\".rm EZ \" GCOS patch
+'lt \\n(LLu
+'pc %
+.if \\n(YE>0 .if \\n(EF>0 .fi
+.rm EL 10 11 12 13 14 15 16 17 18 19 20 21 22 23
+.rr 10 11 12 13 14 15 16 17 18 19 20 21 22 23
+.if \\n(ZN>0 .if t .sp .5
+.if \\n(ZN>0 .if n .sp
+.if "\\n(.z"" .nr PE \\n(nl
+.if !"\\n(.z"" .nr PE \\n(.d
+.nr z 72-((\\n(nl-\\n(HM)%72)
+.if \\n(nl<\\n(HM .nr z 0
+.if \\nz>0 .if \\nz<60 .sp \\nzu  \"force post equation text to whole line
+.if \\nz>59 .if \\nz<72 .sp \\nzu-72u   \"move backwards a fraction of a pica
+..
+.de ME
+.nr SJ \\n(.j
+.if \\n(LL>0 .nr LT \\n(LL
+.nr YE 1
+.if \\n(PO=0 .nr PO \\n(.o
+.if \\n(mo-0 .ds MO January
+.if \\n(mo-1 .ds MO February
+.if \\n(mo-2 .ds MO March
+.if \\n(mo-3 .ds MO April
+.if \\n(mo-4 .ds MO May
+.if \\n(mo-5 .ds MO June
+.if \\n(mo-6 .ds MO July
+.if \\n(mo-7 .ds MO August
+.if \\n(mo-8 .ds MO September
+.if \\n(mo-9 .ds MO October
+.if \\n(mo-10 .ds MO November
+.if \\n(mo-11 .ds MO December
+.if \\n(dw-0 .ds DW Sunday
+.if \\n(dw-1 .ds DW Monday
+.if \\n(dw-2 .ds DW Tuesday
+.if \\n(dw-3 .ds DW Wednesday
+.if \\n(dw-4 .ds DW Thursday
+.if \\n(dw-5 .ds DW Friday
+.if \\n(dw-6 .ds DW Saturday
+.if "\\*(DY"" .ds DY \\*(MO \\n(dy, 19\\n(yr
+.if "\\*(CF"" .if n .ds CF "\\*(DY
+..
+.	\"EM end up macro - process left over keep-release
+.de EM
+.br
+.if \\n(TB=0 .if t .wh -1p CM
+.if \\n(TB \&\c
+.if \\n(TB 'bp
+.if \\n(TB .NP
+.if \\n(TB .ch CM 160
+..
+.	\"NP new page
+.de NP
+.if \\n(FM+\\n(HM>=\\n(.p .tm Margins bigger than page length.
+.if \\n(FM+\\n(HM>=\\n(.p .ab
+.if \\n(FM+\\n(HM>=\\n(.p .ex
+.nr PX \\n(.s
+.nr PF \\n(.f
+.nr PV \\n(.v
+.if t .CM
+.if \\n(HM=0 .nr HM 1i
+'sp \\n(HMu/2u
+.lt \\n(LTu
+.ps \\n(PS
+.vs \\n(PS+2
+.ft 1
+.if \\n(PO>0 .po \\n(POu
+.PT
+.ps \\n(PX
+.vs \\n(PVu
+.ft \\n(PF
+'sp |\\n(HMu
+.nr XX 0 1
+.nr YY 0-\\n(FMu
+.ch FO 16i
+.ch FX 17i
+.ch FO \\n(.pu-\\n(FMu
+.ch FX \\n(.pu-\\n(FMu
+.if \\n(MF .FV
+.nr MF 0
+.mk
+.os
+.ev 1
+.if \\n(TD=0 .if \\n(TC<5  .XK
+.nr TC 0
+.ns
+.ev
+.nr TQ \\n(.i
+.nr TK \\n(.u
+.if \\n(IT>0 \{\
+.	in 0
+.	nf
+.	TT
+.	in \\n(TQu
+.	if \\n(TK .fi\
+\}
+.mk #T
+.if t .if \\n(.o+\\n(LL>7.75i .tm Offset (\\n(.o) + line length (\\n(LL) exceeds 7.75 inches, too wide
+..
+.de XK
+.nr TD 1
+.nf
+.ls 1
+.in 0
+.rn KJ KL
+.KL
+.rm KL
+.if "\\n(.z"KJ" .di
+.nr TB 0
+.if "\\n(.z"KJ" .nr TB 1
+.br
+.in
+.ls
+.fi
+.if (\\n(nl+1v)>(\\n(.p-\\n(FM) .if \\n(NX>1 .RC
+.if (\\n(nl+1v)>(\\n(.p-\\n(FM) .if \\n(NX<1 .bp
+.nr TD 0
+..
+.de KD
+.nr KM 0
+.if "\\n(.z"" .if \\$2>0 .if \\n(nl>\\n(HM .if (\\n(nl+1v)<(\\n(.p-\\n(FM) .di KJ
+.if "\\n(.z"" .if \\n(nl>\\n(HM .if \\$2>0 .sp 15i \" full page figure must have new page
+.if "\\n(.z"" .if \\n(nl>\\n(HM .if \\$2=0 .if (\\n(nl+1v)>(\\n(.p-\\n(FM) .sp 15i
+.if "\\n(.z"KJ" .nr KM 1 \" KM is 1 if in a rediversion of keeps
+.if \\n(KM>0 \!.KD \\$1 \\$2
+.nr KR \\n(.t
+.if \\n(nl<=\\n(HM .nr KR 32767
+.if \\n(KM=0 .if \\n(KR<\\$1 .di KJ
+.if \\n(KM=0 .if \\n(KR<\\$1 .nr KM 1
+.if \\n(KM=0 .if \\$2>0 .if (\\n(nl+1v)>(\\n(.p-\\n(FM) .sp 15i
+.rs
+.if \\n(KM=0 .if \\$2>0 .sp \\n(.tu-\\$1u
+..
+.de PT
+.lt \\n(LLu
+.pc %
+.nr PN \\n%
+....if \\n%-1 .tl '\\*(LH'\\*(CH'\\*(RH'
+.lt \\n(.lu
+..
+.	\"FO - footer of page
+.de FO
+.rn FO FZ
+.if \\n(K1>0 .tm This memo has a multi-page cover sheet.  You are
+.if \\n(K1>0 .tm rebuked in the name of the Committee on Technical Memoranda.
+.if \\n(IT>0 .nr T. 1
+.if \\n(IT>0 .if \\n(FC=0  .T# 1
+.if \\n(IT>0 .br
+.nr FC +1
+.if \\n(NX<2 .nr WF 0
+.nr dn 0
+.if \\n(FC<=1 .if \\n(XX .XF
+.rn FZ FO
+.nr MF 0
+.if \\n(dn  .nr MF 1
+.if !\\n(WF .nr YY 0-\\n(FMu
+.if !\\n(WF .ch FO \\n(YYu
+.if !\\n(dn .nr WF 0
+.if \\n(FC<=1 .if \\n(XX=0  .if \\n(NX>1 .RC
+.nr x 7176u-\\n(.d
+.if \nL=1 .if \\n(FC<=1 .if \\n(XX=0  .if \\n(NX<1 'tm Chap=\\na  page=\\n%   short=\\nx    
+.if \\n(FC<=1 .if \\n(XX=0  .if \\n(NX<1 'bp
+.nr FC -1
+.if \\n(ML>0 .ne \\n(MLu
+..
+.	\"2C - begin double column
+.de 2C
+.MC \" default MC is double column
+..
+.de MC \" multiple columns- arg is line length
+.nr L1 \\n(LL*7/15
+.if \\n(.$>0 .nr L1 \\$1n
+.nr GW 0-1
+.if \\n(.$>1 .nr GW \\$1n
+.nr NQ \\n(LL/\\n(L1
+.if \\n(NQ<1 .nr NQ 1
+.if \\n(NQ>2 .if (\\n(LL%\\n(L1)=0 .nr NQ -1
+.if \\n(1T=0 \{\
+.	BG
+.	if n .sp 4
+.	if t .sp 2\}
+.if \\n(NX=0 .nr NX 1
+.if !\\n(NX=\\n(NQ \{\
+.	RT
+.	if \\n(NX>1 .bp
+.	mk
+.	nr NC 1
+.	po \\n(POu\}
+.if \\n(NQ>1 .hy 14
+.nr NX \\n(NQ
+.nr CW \\n(L1
+.ll \\n(CWu
+.nr FL \\n(CWu*11u/12u
+.if \\n(NX>1 .nr GW (\\n(LL-(\\n(NX*\\n(CW))/(\\n(NX-1)
+.nr RO \\n(CW+\\n(GW
+.ns
+..
+.de RC
+.ie \\n(NC>=\\n(NX .C2
+.el .C1
+..
+.de C1
+.rt
+.po +\\n(ROu
+.nr NC +1
+.if \\n(NC>\\n(NX .nr NC 1
+.nr XX 0 1
+.if \\n(MF .FV
+.ch FX \\n(.pu-\\n(FMu
+.ev 1
+.if \\n(TB .XK
+.nr TC 0
+.ev
+.nr TQ \\n(.i
+.if \\n(IT>0 .in 0
+.if \\n(IT>0 .TT
+.if \\n(IT>0 .in \\n(TQu
+.mk #T
+.ns
+..
+.de C2
+.po \\n(POu
+.nr NC +1
+.if \\n(NC>\\n(NX .nr NC 1
+'bp
+..
+.	\"1C - return to single column format
+.de 1C
+.MC \\n(LLu
+.hy 14
+..
+.	\".de R3
+.	\".pl 102
+.	\".nr LT \\n(.l
+.	\"..
+.de BT
+.nr PX \\n(.s
+.nr PF \\n(.f
+.ft 1
+.ps \\n(PS
+'lt \\n(LTu
+.po \\n(POu
+.if \\n%>0 .tl '\\*(LF'\\*(CF'\\*(RF'
+.ft \\n(PF
+.ps \\n(PX
+..
+.	\"PP - paragraph
+.de PP
+.RT
+.if \\n(1T .sp \\n(PDu
+.ti +\\n(PIu
+..
+.	\"SH - (unnumbered) section heading
+.de SH
+.ti \\n(.iu
+.RT
+.if \\n(1T .sp 1
+.if !\\n(1T .BG
+.RT
+.ne 4
+.ft 3
+..
+.	\"NH - numbered heading
+.de NH
+.RT
+.if \\n(1T .sp 1
+.if !\\n(1T .BG
+.RT
+.ne 4
+.ft 3
+.nr NS \\$1
+.if !\\n(.$ .nr NS 1
+.if !\\n(NS .nr NS 1
+.nr H\\n(NS +1
+.if !\\n(NS-4 .nr H5 0
+.if !\\n(NS-3 .nr H4 0
+.if !\\n(NS-2 .nr H3 0
+.if !\\n(NS-1 .nr H2 0
+.if !\\$1 .if \\n(.$ .nr H1 1
+.ds SN \\n(H1.
+.if \\na=0 .ds SN \\*(CN.
+.ti \\n(.iu
+.if \\n(NS-1 .as SN \\n(H2.
+.if \\n(NS-2 .as SN \\n(H3.
+.if \\n(NS-3 .as SN \\n(H4.
+.if \\n(NS-4 .as SN \\n(H5.
+\\*(SN
+..
+.	\"BG - begin, execute at first PP
+.de BG
+.br
+.ME
+.rm ME
+.di
+.ce 0
+.nr KI 0
+.hy 14
+.nr 1T 1
+.S\\n(ST
+.rm S0
+.rm S1
+.rm S2
+.rm S3
+.rm OD
+.rm OK
+.rm TX
+.rm AX
+.rm WT
+.rm CS
+.rm TM
+.rm IM
+.rm MF
+.rm MR
+.rm RP
+.rm I1
+.rm I2
+.rm I3
+.rm I4
+.rm I5
+.rm CB
+.rm E1
+.rm E2
+.de TL
+.ft 3
+.sp
+.if n .ul 100
+.ce 100
+.ps +2
+\\..
+.de AU
+.ft 2
+.if n .ul 0
+.ce 100
+.sp
+.NL
+\\..
+.de AI
+.ft 1
+.ce 100
+.if n .ul 0
+.if n .sp
+.if t .sp .5
+.NL
+\\..
+.RA
+.rm RA
+.rn FJ FS
+.rn FK FE
+.nf
+.ev 1
+.ps \\n(PS-2
+.vs \\n(.s+2p
+.ev
+.if \\n(KG=0 .nr FP 0 
+.if \\n(GA>1 .if \\n(KG=0 .nr GA 0 \" next UNIX must be flagged.
+.nr KG 0 
+.if \\n(FP>0 .FS
+.if \\n(FP>0 .FG
+.if \\n(FP>0 .FE
+.br
+.if \\n(TV>0 .if n .sp 2
+.if \\n(TV>0 .if t .sp 1
+.fi
+.ll \\n(LLu
+..
+.de RA \"redefine abstract macros
+.de AB
+.br
+.if !\\n(1T .BG
+.ce 1
+.sp 1
+.if \\n(.$=0 ABSTRACT
+.if \\n(.$>0 .if !"\\$1"-" .if !"\\$1"no"  \\$1
+.if \\n(.$=0 .sp
+.if \\n(.$>0 .if !"\\$1"-" .if !"\\$1"no" .sp
+.sp 1
+.nr AJ 1
+.in +\\n(.lu/12u
+.ll -\\n(.lu/12u
+.RT
+\\..
+.de AE
+.nr AJ 0
+.br
+.in 0
+.ll \\n(LLu
+.if \\n(VS>=41 .vs \\n(VSu
+.if \\n(VS<=40 .vs \\n(VSp
+\\..
+..
+.	\"IP - indented paragraph
+.de IP
+.RT
+.if !\\n(IP .nr IP +1
+.sp \\n(PDu
+.if \\n(.$-1 .nr I\\n(IR \\$2n
+.in +\\n(I\\n(IRu
+.nr TY \\n(TZ-\\n(.i
+.ta \\n(I\\n(IRu \\n(TYuR
+.if \\n(.$>0 \{\
+.ti -\\n(I\\n(IRu
+\&\\$1\t\c\}
+..
+.	\"LP - left aligned (block) paragraph
+.de LP
+.ti \\n(.iu
+.RT
+.if \\n(1T .sp \\n(PDu
+..
+.de QP
+.ti \\n(.iu
+.RT
+.if \\n(1T .sp \\n(PDu
+.ne 1.1
+.nr QP 1
+.in +\\n(QIu
+.ll -\\n(QIu
+.ti \\n(.iu
+..
+.	\"IE - synonym for .LP
+.de IE
+.LP
+..
+.	\"LB - label paragraph
+.de LB
+.in +\\n(I\\n(IRu
+.ta \\n(I\\n(IRu
+.if \\n(.$ .ti -\\n(I\\n(IRu
+.if \\n(.$ \&\\$1\t\c
+..
+.de XP
+.RT
+.if !\\n(IP .nr IP +1
+.sp \\n(PDu
+.ne 3
+.if \\n(.$=3 .nr I\\n(IR \\$3n
+.if \\n(.$=4 .nr I\\n(IR \\$4n
+.nr J\\n(IR \\n(IRu/2u
+.if \\n(.$=4 .nr J\\n(IR \\$3n
+.in +\\n(I\\n(IRu
+.ta \\n(J\\n(IRu \\n(I\\n(IRu
+.ti -\\n(I\\n(IRu
+\0\\$1\t\\$2\t\c
+..
+.	\"RS - prepare for double indenting
+.de RS
+.nr IS \\n(IP
+.RT
+.nr IP \\n(IS
+.if \\n(IP>0 .in +\\n(I\\n(IRu
+.nr IR +1
+.nr I\\n(IR \\n(PIu
+.in +\\n(I\\n(IRu
+.nr TY \\n(TZ-\\n(.i
+.ta \\n(TYuR
+..
+.	\"RE - retreat to the left
+.de RE
+.nr IS \\n(IP
+.RT
+.nr IP \\n(IS
+.if \\n(IR>0 .nr IR -1
+.if \\n(IP<=0 .in -\\n(I\\n(IRu
+..
+.de TC
+.nr TZ \\n(.lu
+.if \\n(.$ .nr TZ \\$1n
+.ta \\n(TZuR
+..
+.de TD
+.LP
+.nr TZ 0
+..
+.	\"CM - cut mark
+.de CM
+.po 0
+.lt 7.6i
+.ft 1
+.ps 10
+.vs 4p
+.po
+.vs
+.lt
+.ps
+.ft
+..
+.	\"B - bold font
+.de B
+.nr PQ \\n(.f
+.if t .ft 3
+.if "\\$1"" .if n .ul 1000
+.if !"\\$1"" .if n .ul 1
+.if t .if !"\\$1"" \&\\$1\\f\\n(PQ\\$2
+.if n .if \\n(.$=1 \&\\$1
+.if n .if \\n(.$>1 \&\\$1\\c
+.if n .if \\n(.$>1 \\&\\$2
+..
+.	\"R - Roman font
+.de R
+.if n .ul 0
+.ft 1
+..
+.	\"I - italic font
+.de I
+.nr PQ \\n(.f
+.if t .ft 2
+.if "\\$1"" .if n .ul 1000
+.if !"\\$1"" .if n .ul 1
+.if t .if !"\\$1"" \&\\$1\\f\\n(PQ\\$2
+.if n .if \\n(.$=1 \&\\$1
+.if n .if \\n(.$>1 \&\\$1\\c
+.if n .if \\n(.$>1 \\&\\$2
+..
+.	\"TA - tabs set in ens or chars
+.de TA
+.ta \\$1n \\$2n \\$3n \\$4n \\$5n \\$6n \\$7n \\$8n \\$9n
+..
+.	\"SM - make smaller size
+.de SM
+.if \\n(.$>0 \&\\$3\s-2\\$1\s0\\$2
+.if \\n(.$=0 .ps -2
+..
+.	\"LG - make larger size
+.de LG
+.ps +2
+..
+.	\"NL - return to normal size
+.de NL
+.ps \\n(PS
+..
+.	\"DA - force date; ND - no date or new date.
+.de DA
+.if \\n(.$ .ds DY \\$1 \\$2 \\$3 \\$4
+.ds CF \\*(DY
+..
+.de ND
+.ME
+.rm ME
+.ds DY \\$1 \\$2 \\$3 \\$4
+.rm CF
+..
+.de FN
+.FS
+..
+.	\"FS - begin footnote
+.de FJ
+'ce 0
+.di
+.ev1
+.ll \\n(FLu
+.da FF
+.br
+.if \\n(IF>0 .tm Footnote within footnote-illegal.
+.nr IF 1
+.if !\\n+(XX-1 .FA
+..
+.	\"FE - footnote end
+.de FK
+.br
+.in 0
+.nr IF 0
+.di
+.ev
+.if !\\n(XX-1 .nr dn +\\n(.v
+.nr YY -\\n(dn
+.if \\n(NX=0 .nr WF 1
+.if \\n(dl>\\n(CW .nr WF 1
+.if (\\n(nl+\\n(.v)<=(\\n(.p+\\n(YY) .ch FO \\n(YYu
+.if (\\n(nl+\\n(.v)>(\\n(.p+\\n(YY) .if \\n(nl>(\\n(HM+1.5v) .ch FO \\n(nlu+\\n(.vu
+.if (\\n(nl+\\n(.v)>(\\n(.p+\\n(YY) .if \\n(nl+\\n(FM+1v>\\n(.p .ch FX \\n(.pu-\\n(FMu+2v
+.if (\\n(nl+\\n(.v)>(\\n(.p+\\n(YY) .if \\n(nl<=(\\n(HM+1.5v) .ch FO \\n(HMu+(4u*\\n(.vu)
+..
+.\"	First page footer.
+.de FS
+.ev1
+.br
+.ll \\n(FLu
+.da FG
+..
+.de FE
+.br
+.di
+.nr FP \\n(dn
+.if \\n(1T=0 .nr KG 1 \"not in abstract repeat next page.
+.if "\\n(.z"OD" .nr KG 0 \" if in OK, don't repeat.
+.ev
+..
+.de FA
+.if n __________________________
+.if t \l'1i'
+.br
+..
+.de FV
+.FS
+.nf
+.ls 1
+.FY
+.ls
+.fi
+.FE
+..
+.de FX
+.if \\n(XX>0 .di FY
+.if \\n(XX>0 .ns
+..
+.de XF
+.if \\n(nlu+1v>(\\n(.pu-\\n(FMu) .ch FX \\n(nlu+1.9v
+.ev1
+.nf
+.ls 1
+.FF
+.rm FF
+.nr XX 0 1
+.br
+.ls
+.di
+.fi
+.ev
+..
+.de FL
+.ev1
+.nr FL \\$1n
+.ll \\$1
+.ev
+..
+.de UL \" underline argument, don't italicize
+.if t \\$1\l'|0\(ul'\\$2
+.if n .I \\$1 \\$2
+..
+.de UX
+UNIX
+..
+.de US
+the
+.UX
+operating system
+..
+.de QS
+.br
+.LP
+.in +\\n(QIu
+.ll -\\n(QIu
+..
+.de QE
+.br
+.ll +\\n(QIu
+.in -\\n(QIu
+.LP
+..
+.de B1 \" begin boxed stuff
+.br
+.di BB
+.nr BC 0
+.if "\\$1"C" .nr BC 1
+.nr BE 1
+..
+.de B2 \" end boxed stuff
+.br
+.nr BI 1n
+.if \\n(.$>0 .nr BI \\$1n
+.di
+.nr BE 0
+.nr BW \\n(dl
+.nr BH \\n(dn
+.ne \\n(BHu+\\n(.Vu
+.nr BQ \\n(.j
+.nf
+.ti 0
+.if \\n(BC>0 .in +(\\n(.lu-\\n(BWu)/2u
+.in +\\n(BIu
+.BB
+.in -\\n(BIu
+.nr BW +2*\\n(BI
+.sp -1
+\l'\\n(BWu\(ul'\L'-\\n(BHu'\l'|0\(ul'\h'|0'\L'\\n(BHu'
+.if \\n(BC>0 .in -(\\n(.lu-\\n(BWu)/2u
+.if \\n(BQ .fi
+.br
+..
+.de AT
+.nf
+.sp
+.ne 2
+Attached:
+..
+.de CT
+.nf
+.sp
+.ne 2
+.ie \\n(.$ Copy to \\$1:
+.el Copy to:
+..
+.de BX
+.if t \(br\|\\$1\|\(br\l'|0\(rn'\l'|0\(ul'
+.if n \(br\\kA\|\\$1\|\\kB\(br\v'-1v'\h'|\\nBu'\l'|\\nAu'\v'1v'\l'|\\nAu'
+..
+.IZ
+.rm IZ
+.\" ------------------- VARIABLES ------------------------------
+.\" \na - Current chapter
+.\" \nb - Current section
+.\" \nc - Current subsection 
+.\" \nd - Set to 0 initially, 1 by PT,  2 by .PB  Used to control running head
+.\" \ne - Current equation number
+.\" \ng - Used to count items in numbered lists
+.\" \nh - Counts number of times CP has been invoked
+.\" \nj - Set to 1 iff footer page number needed
+.\" \nk - Last figure number used
+.\" \nL - 1 if depth printed for each page
+.\" \nl - 1 old Agfa length to be used
+.\" \np - Numbers end-of-chapter problems
+.\" \nq - 1 for double spaced text, smaller vert. margins
+.\" \ns - initial page number
+.\" \nt - Variable part of spacing inside .BI macro
+.\" \nv - Scratch register in lower case roman numerals
+.\" \nx - Scratch register
+.\" ------------------- GENERAL PARAMETERS ---------------------
+.nr BO 43		\" number of lines of text per page
+.nr PO 1.3i
+.po \n(PO
+.if \nq=1 .ls 2		\" -rq1 invokes double spacing
+.nr LL 5.67i
+.if t \{
+.nr PL 29.73c
+.nr PI 0.25i\}
+.if n \{
+.nr LL 80m
+.nr PL 11.0i
+.nr PI 3m\}
+.pl \n(PLu
+.nr HM (\n(PLu-(\n(BOu*\n(VSu))/2u
+.nr FM \n(PLu-(\n(HMu+((\n(BOu-1u)*\n(VSu)+1u)
+.nr xx \n(HMu%\n(VZu
+.nr HM \n(HMu-\n(xxu
+.nr FM \n(FMu+\n(xxu
+.nr t 0 0
+.\" ------------------- INITIALIZATION -------------------------
+.nr d 0 0
+.nr e 0 1
+.nr h 0 1
+.nr j 1 0
+.nr t 0 0
+.tr ~
+.ds CT "~	\"initially empty
+.ND		\"suppress date on bottom of page
+.af v i		\"register v is in lower case roman
+.ch FO -\n(FMu
+.ch BT -\n(FMu+0.5P
+.\" ------------------- ALIGN TEXT TO A WHOLE NUMBER OF PICAS ----
+.de AL
+'nr xx \\n(.du%\\n(VZu
+'nr xy \\n(VZu-\\n(xx
+'if \\n(xy=\\n(VZu .nr xy 0
+'sp \\n(xyu
+..
+.\" ------------------- DIVISION OF TEXT INTO LOGICAL UNITS ----
+.\"	Define chapter number
+.de CP
+.ds CN \\$1
+.ds CX CHAP.
+.if '\\$1'A' .ds CX APPENDIX
+.if '\\$1'B' .ds CX APPENDIX
+.if '\\$1'C' .ds CX APPENDIX
+.if '\\$1'D' .ds CX APPENDIX
+.if '\\$1'E' .ds CX APPENDIX
+.if '\\$1'F' .ds CX APPENDIX
+.if '\\$1'A' .nr a 0 0
+.if '\\$1'B' .nr a 0 0
+.if '\\$1'C' .nr a 0 0
+.if '\\$1'D' .nr a 0 0
+.if '\\$1'E' .nr a 0 0
+.if '\\$1'F' .nr a 0 0
+.nr H1 \\$1 0
+.nr H2 0 1
+.nr a \\$1 0
+.nr b 0 1
+.nr c 0 1
+.nr d 1 1
+.nr e 0 1
+.nr k 0 1
+.nr s \\n%
+.if \\nq=1 .PH 6
+.ll \\n(LLu
+.nr LT \\n(LLu
+.lt \\n(LLu
+.ll \\n(LLu
+.pl \n(PLu
+.po \n(POu
+.in 0
+.nr PS \\n(PZ
+.nr VS \\n(VZu
+.nr PD 0i
+.ds ST
+.ds CT \\$2
+.if !'\\$3'' .as CT " \\$3
+.if \\nh .bp
+.rs
+.sp 16P
+.B
+.ps 30
+.vs 32
+.ce 1
+\\$1
+.sp 4P
+.ps 18
+.vs 20
+.ce 1
+\\$2
+.sp 0.25i
+.if !'\\$3'' .ce 1
+.if !'\\$3'' \\$3
+.ps 10
+.vs 12
+.R
+.nr x \\n(.pu/2u
+.sp |\\nxu
+.nr h +1 1
+.tr _\\(ru
+.AL
+..
+.de SP
+.sp \\$1	\"used for temporary (page balancing ) fill
+..
+.de HS
+.sp 0.5
+..
+.\"	Major section (numbered)
+.de SE
+.nr b +1 1
+.nr c 0 1
+.ds ST \\$1
+.sp 1
+.NH 2
+\\$1
+.sp 1
+..
+.\"	Subsection (numbered)
+.de SS
+.nr c +1 1
+.NH 3
+\\$1
+.sp 1
+..
+.de UU
+.SH
+\\$1
+.sp 1
+..
+.\"-------------------- PAGE TRANSITION MACROS USED BY -MS ------
+.de PH	\"select special running heads
+.nr d \\$1
+.if \\$1=4 .nr j 1
+.ds CT \\$2
+..
+.de PT
+.AL
+.pc %
+.PN \\n%
+'sp |\\n(HMu-0.35i
+.ps 10
+.\"
+.\" nd = 0 means no running head this time, normal next time
+.if \\nd=0 \{\
+.tl ''''	\" no running head on initial page transition
+.nr j 1 0\}
+.\"
+.\" nd = 1 is normal case: chapter heading even (left) and section odd(right)
+.if \\nd=1\{\
+.if e .tl '\fB\s+2%\s-2\fR'\\*(CT'\\*(CX~ \\*(CN' \"normal case even page
+.if o .if \\nb>0 .tl 'SEC.~ \\*(CN.\\nb'\\*(ST'\fB\s+2%\s-2\fR'
+.if o .if \\nb=0 .tl '''\fB\s+2%\s-2\fR'\}
+.if o .if \\nb=-999 .tl '\\*(CX~ \\*(CN'\\*(CT'\fB\s+2%\s-2\fR'\}
+.\"
+.\" nd = 2 is for PROBLEMS; even normal, odd  CHAP. ... PROBLEMS %
+.if \\nd=2\{\
+.if e .tl '\fB\s+2%\s-2\fR'\\*(CT'\\*(CX~ \\*(CN' \"even page PROBLEMS
+.if o .if \\nd=2 .tl '\\*(CX~ \\*(CN'PROBLEMS'\fB\s+2%\s-2\fR' \}
+.\"
+.\" nd = 3 is for index, problem solutions & other cases with same odd even hd
+.if \\nd=3\{\
+.if e .tl '\fB\s+2%\s-2\fR'\\*(CT''
+.if o .tl ''\\*(CT'\fB\s+2%\s-2\fR'\}
+.\"
+.\" nd = 4 is like nd = 3, except page numbers are lower case roman
+.if \\nd=4\{\
+.nr v \\n%
+.if e .tl '\fB\s+2\\nv\s-2\fR'\\*(CT''
+.if o .tl ''\\*(CT'\fB\s+2\\nv\s-2\fR'\}
+.\"
+.\" nd = 5 suppresses running heads like nd=0, only it keeps them suppressed
+.if \\nd=5 .tl ''''
+.\" nd = 6 gives page number in right-hand corner only
+.if \\nd=6 .tl '''%'
+.if \\nd=0 .nr d 1 0	\" henceforth normal running heads
+..
+.de BT
+.if \\n%=\\ns\{\
+.nr x \\n(HMu+(\\n(BO*\\n(VSu)+2P
+'sp |\\nxu
+.nr v \\n%
+.ie \\nd=4 .tl ''\fB\s-1\\nv\s0\fP''
+.el .tl ''\fB\s-1\\n%\s0\fP''\}
+.nr j 0 0
+.if \\nd=0 .nr d 1 0
+..
+.\"--------------- CHECK FOR INITIAL PAGE NUMBER ---------------
+.de PC
+.if \n%<\\$1\{
+.tm You forgot to set the page number.  Run aborted. Use troff -n
+.ex\}
+.if \n%>\\$2\{
+.tm You forgot to set the page number.  Run aborted. Use troff -n
+.ex\}
+..
+.\"-------------------- LISTS OF THINGS ------------------------
+.\"	Start list
+.de LI
+.nr g 0 1
+.in +0.25i
+.nr LL -0.25i
+.ll -0.25i
+.ne 3v
+.HS
+..
+.\"	End list
+.de LX
+.sp 1
+.in -0.25i
+.nr LL +0.25i
+.ll +0.25i
+.LP
+..
+.\"	List item
+.de IT
+.HS
+.nr g \\ng+1 1
+.ie \\ng<10 .IP \0\\ng. 4
+.el .IP \\ng. 4
+..
+.\"Short unnumbered lines
+.de UN
+.HS
+..
+.\"-------------------- END OF CHAPTER EXERCISES ---------------
+.de PB
+.nr d 2 0
+.if \\nq=1 .PH 6
+.ne 1.5i
+.sp 0.5i
+.ce 1
+.B PROBLEMS
+.sp 1
+.nr p 0 1
+..
+.de PR
+.ps 11
+.vs 13
+.nr PS 11
+.nr VS 13.01p
+.HS
+.nr p +1 1
+.in \w'00.  'u
+.ti -\w'00.  'u
+.if \\np>9 \fB\\np.\fR~~\c
+.if \\np<10 \fB\0\\np.\fR~~\c
+..
+.de AA
+.sp 3
+.if n .nr LL 84m
+.nr PS \\n(PZ
+.nr VS \\n(VZu
+.nr a \\$1 1
+.nr b 0 0
+.nr p 0 1
+.ce 1
+.nr x 1
+.if '\\$1'A' .nr x 0
+.if '\\$1'B' .nr x 0
+.if '\\$1'C' .nr x 0
+.if \\nq=1 .PH 6
+.if \\nx\fBSOLUTIONS TO CHAPTER \\$1 PROBLEMS\fR
+.if !\\nx\fBSOLUTIONS TO APPENDIX \\$1 PROBLEMS\fR
+.sp 1v
+..
+.de AN
+.HS
+.ps \\n(PZ
+.vs \\n(VSu
+.nr PS \\n(PZ
+.nr VS \\n(VZu
+.nr p +1 1
+.in \w'00.  'u
+.ti -\w'00.  'u
+.if \\np>9 \fB\\np.\fR~~\c
+.if \\np<10 \fB\0\\np.\fR~~\c
+..
+.\"-------------------- BIBLIOGRAPHY ---------------------------
+.de BB
+.sp 2
+.in 0.25i
+..
+.de BI
+.ps 10
+.vs 12
+.sp \\ntu
+.HS
+.if n .HS
+.ti -0.30i
+.R
+..
+.\"-------------------- QUOTES ---------------------------------
+.ds OQ `\h'-1p'`
+.ds CQ '\h'-1p''
+.\"-------------------- FIGS.-----------------------------------
+.de FC 
+'sp 1v
+.ps 10
+.vs 12
+.in +0.5i
+.ll -0.5i
+.B
+.if '\\$1'C' .ce 1
+Fig.\|\|\|\\*(CN-\\n+k.~\c
+.R
+..
+.de BF
+.KF
+'sp 1v
+.nr TP \\n(.s
+.nr TV \\n(.v
+.nr TF \\n(.f
+.nr r 0 0
+.if \\nq=0 .if  "\\$1"PAGE" .KP
+.if \\nq=0 .if  "\\$1"PAGE" .nr r 1 0
+.if \\nq=0 .if !"\\$1"PAGE" .sp \\$1
+.if \\nq=1 .sp 0.5i
+.FC \\$2
+..
+.de EF
+.in -0.5i
+.ll +0.5i
+.ps \\n(TP
+.vs \\n(TV
+.ft \\n(TF
+'if \\nr==0 'sp 30u
+'AL
+.KE
+..
+.de NF
+.nr x \\nk+1
+.ie !'\\$1'X' Fig.~\\*(CN-\\nx\\$1
+.el Figure \\*(CN-\\nx\\$2
+..
+.de PF
+.ie !'\\$1'X' Fig.~\\*(CN-\\nk\\$1
+.el Figure \\*(CN-\\nk\\$2
+..
+.\"-------------------- MULTIPLE BLANK PAGES -------------------
+.de MP
+.if \\$1 \{\
+.KF
+.KP
+.KE
+.MP \\$1-1
+.if \\$1<2 .nr k +1 1
+\}
+..
+.\"-------------------- TABLE OF CONTENTS ----------------------
+.de XT
+.if t .ta 0.4i 0.8i 0.9i \\n(LLuR
+.if n .ta 0.3i 1.0i 1.1i 5.0iR
+.ps 11
+.vs 13
+.nr a \\$1 0
+.nr b 0 1
+.nr c 0 1
+.sp 0.40i
+.ne 0.3i
+.B
+\\s18\\$1\\s12	\\$2	\\$3\\fR\\s11
+.br
+.if !'\\$4''	\\fB\\$4\\fR
+.R
+.sp 0.5v
+..
+.de XE
+.nr b +1 1
+.nr c 0 1
+.HS
+	\\na.\\nb	\\$1   \\$2
+..
+.de XS
+.nr c +1 1
+		\\na.\\nb.\\nc   \\$1   \\$2
+..
+.\"------------------- INDEX -----------------------------------
+.de IL
+.nr PS \\n(PZ-2
+.nr VS 12.01p
+.LP
+.nf
+.na
+.sp 2v
+.ne 2
+\fB\s+4\\$1\\s0\fR
+.sp 1v
+..
+.\"------------------- NEW .B MACRO ----------------------------
+.rm B
+.de B
+.nr PQ \\n(.f
+.ft 3
+.if !"\\$1"" \&\\$1\\f\\n(PQ\\$2
+..
+.\"--------------------- FIXES NEEDED TO -MS -------------------
+.\" Remove .if n .ul 1000 from .NH
+.\" Remove .if n .ul 1000 from .SH
+.\" Fix to allow letters as chapter "numbers"
+.\"
+.\" Here is the b3mac file
+.nr Cs 10
+.fp 5 H
+.ds fm \(fm
+.ds em \(em
+.de F
+\\fI\\$1\\fR\\$2
+..
+.de CC
+.HS
+~~~~~\\s\\n(Cs\\f5\\$1\\fP\\s0
+.HS
+.LP
+..
+.de Cx
+~~~~~\\s\\n(Cs\\f5\\$1\\fP\\s0\\$2
+..
+.de Cb
+.in +0.25i
+\\s\\n(Cs
+.HS
+\\f5
+..
+.de Ce
+.HS
+\\fR
+.nr PS \\n(PZ
+.nr VS \\n(VZ
+.LP
+.in -0.25i
+..
+.de SY
+\\$3\s-2\\$1\s+2\\$2
+..
+.de SM
+\\$3\s-1\\$1\s+1\\$2
+..
+.de FN
+\&\\fI\\$1\\fR\\$2
+..
+.de DI
+\&\\fI\\$1\\fR\\$2
+..
+.de FI
+\&\\fI\\$1\\fR\\$2
+..
+.de LN
+.nr x \\$1+\\$2
+\\$4line
+.L4 \\nx \\$3
+..
+.de LS
+.nr x \\$1+\\$2
+.nr y \\$1+\\$3
+.nr z \\nx+1
+\\$5lines
+.L4 \\nx
+.ie \\ny=\\nz and
+.el to
+.L4 \\ny \\$4
+..
+.ds SQ \(fm\h'-0.05c'\(fm
+.de L4
+.ie \\$1<10 000\\$1\\$2
+.el .ie \\$1<100 00\\$1\\$2
+.el .ie \\$1<1000 0\\$1\\$2
+.el \\$1\\$2
+..
+.de KW
+\f5\\$1\\$2\fR
+..
+.ds M0 MINIX
+.ds M1 \\s-1MINIX\\s+1
+.ds M2 \\s-2MINIX\\s+2
+.ds M9 \\s-1MINIX\\s+1
+.ds m0 minix
+.de MX
+\s-1MINIX 3\s-1\\$1
+..
+.de Ux
+\s-2UNIX\s+2\\$1
+..
+.tr _\(ru
+.de UX
+\s-2UNIX\s+2\\$1
+..
+.ds Mx \\s-1MINIX\\s0
+.ds Mp \\s-1MINIX-PC\\s0
+.ds Ms \\s-1MINIX-ST\\s0
+.de CW
+\f5
+..
+.de Bu
+.HS
+.IP "\0\(bu" 4
+..
+.de CD
+.ne 2
+.if t .ta 0.9i 1.15i 2.75i 3.25i 3.75i
+.if n .ta 11m 15m 40m
+.nr x 0 0
+.nr y 0 0
+.nr z 0 0
+.if n #\\$1
+.if n .br
+\\fBCommand:\&	\\$1\\fR
+.br
+..
+.de SX
+.if \\nx<=0 \\fBSyntax:\&	\\$1
+.if \\nx>0 \&	\\fB\\$1
+.nr x 1 1
+.br
+..
+.de FL
+.if \\ny<=0 \\fBFlags:\&	\\fB\\$1	\\fR\\$2
+.if \\ny>0 \& 	\\fB\\$1	\\fR\\$2
+.nr y 1 1
+.br
+..
+.de EX
+.br
+.nf
+.if \\nz<=0 \\fB\&Examples:	\\fR\\$1	\\fR# \\$2
+.if \\nz>0 \&	\\fR\\$1	\\fR# \\$2
+.nr z 1 1
+.br
+..
+.de EY
+.br
+.nf
+.if \\nz<=0 \\fB\&Example:	\\fR\\$1	\\fR# \\$2
+.if \\nz>0 \&	\\fR\\$1	\\fR# \\$2
+.nr z 1 1
+.br
+..
Index: /trunk/minix/man/man9/mined.9
===================================================================
--- /trunk/minix/man/man9/mined.9	(revision 9)
+++ /trunk/minix/man/man9/mined.9	(revision 9)
@@ -0,0 +1,200 @@
+.so mnx.mac
+.TH MINED 9
+.CD "mined \(en \*(M2 editor"
+.SX "mined\fR [\fIfile\fR]
+.FL "\fR(none)"
+.EX "mined /user/ast/book.3" "Edit an existing file"
+.EX "mined" "Call editor to create a new file"
+.EX "ls \(enl | mined" "Use \fImined\fR as a pager to inspect listing"
+.PP
+\fIMined\fR is a simple screen editor.
+At any instant, a window of 24 lines is visible on the screen.
+The current position in the file is shown by the cursor.
+Ordinary characters typed in are inserted at the cursor.
+Control characters and keys on the numeric keypad (at the right-hand side
+of the keyboard) are used to move the cursor and perform other functions.
+.PP
+Commands exist to move forward and backward a word, and delete words
+either in front of the cursor or behind it.
+A word in this context is a sequence of characters delimited on both ends by
+white space (space, tab, line feed, start of file, or end of file).
+The commands for deleting characters and words also work on line feeds, making
+it possible to join two consecutive lines by deleting the line feed between them.
+.PP
+The editor maintains one save buffer (not displayed).
+Commands are present to move text from the file to the buffer, from the buffer
+to the file, and to write the buffer onto a new file.
+If the edited text cannot be written out due to a full disk, it may still
+be possible to copy the whole text to the save buffer and then write it to a
+different file on a different disk with CTRL-Q.
+It may also be possible to escape from the editor with CTRL-S and remove
+some files.
+.PP
+Some of the commands prompt for arguments (file names, search patterns, etc.).
+All commands that might result in loss of the file being edited prompt to ask
+for confirmation.
+.PP
+A key (command or ordinary character) can be repeated
+.I n
+times by typing
+.I "ESC n key"
+where 
+.I ESC
+is the \*(OQescape\*(CQ key.
+.PP
+Forward and backward searching requires a regular expression as the search
+pattern.
+Regular expressions follow the same rules as in the 
+.Ux
+editor,
+.I ed .
+These rules can be stated as:
+.LI
+.IT
+Any displayable character matches itself.
+.IT
+\&. (period) matches any character except line feed.
+.IT
+\&^ (circumflex) matches the start of the line.
+.IT
+\&$ (dollar sign) matches the end of the line.
+.IT
+\&\\c matches the character \fIc\fR (including period, circumflex, etc).
+.IT
+[\fIstring\fR] matches any of the characters in the string.
+.IT
+[^string] matches any of the characters except those in the string.
+.IT
+[\fIx\(eny\fR] matches any characters between \fIx\fR and \fIy\fR (e.g., [\fIa\(enz\fR]).
+.IT
+Pattern\(** matches any number of occurrences of \fIpattern\fR.
+.LX
+Some examples of regular expressions are:
+.HS
+.in +1.25i
+.ta +1.0i
+.ti -1.0i
+The boy	matches the string \*(OQThe boy\*(CQ
+.ti -1.0i
+^$	matches any empty line.
+.ti -1.0i
+^.$	matches any line containing exactly 1 character
+.ti -1.0i
+^A.*\\.$	matches any line starting with an \fIA\fR, ending with a period.
+.ti -1.0i
+^[A\(enZ]*$	matches any line containing only capital letters (or empty).
+.ti -1.0i
+[A\(enZ0\(en9]	matches any line containing either a capital letter or a digit.
+.ti -1.0i
+\&.*X$	matches any line ending in \*(OQX\*(CQ
+.ti -1.0i
+A.*B	matches any line containing an \*(OQA\*(CQ and then a \*(OQB\*(CQ
+.in -1.25i
+.sp
+.PP
+Control characters cannot be entered into a file simply by typing them because
+all of them are editor commands.
+To enter a control character, depress the ALT key, and then while holding it
+down, hit the ESC key.
+Release both ALT and ESC and type the control character.
+Control characters are displayed in reverse video.
+.PP
+The 
+.I mined
+commands are as follows.
+.sp
+.in +1.25i
+.ta +1.0i
+.ti -1.25i
+\fBCURSOR MOTION\fR
+.ti -1.0i
+\fBarrows\fR	Move the cursor in the indicated direction
+.ti -1.0i
+\fBCTRL-A\fR	Move cursor to start of current line
+.ti -1.0i
+\fBCTRL-Z\fR	Move cursor to end of current line
+.ti -1.0i
+\fBCTRL-^\fR	Move cursor to top of screen
+.ti -1.0i
+\fBCTRL-_\fR	Move cursor to end of screen
+.ti -1.0i
+\fBCTRL-F\fR	Move cursor forward to start of next word 
+.ti -1.0i
+\fBCTRL-B\fR	Move cursor backward to start of previous word 
+
+.ti -1.25i
+\fBSCREEN MOTION\fR
+.ti -1.0i
+\fBHome key\fR	Move to first character of the file
+.ti -1.0i
+\fBEnd key\fR	Move to last character of the file
+.ti -1.0i
+\fBPgUp key\fR	Scroll window up 23 lines (closer to start of the file)
+.ti -1.0i
+\fBPgDn key\fR	Scroll window down 23 lines (closer to end of the file)
+.ti -1.0i
+\fBCTRL-U\fR	Scroll window up 1 line
+.ti -1.0i
+\fBCTRL-D\fR	Scroll window down 1 line
+
+.ti -1.25i
+\fBMODIFYING TEXT\fR
+.ti -1.0i
+\fBDel key\fR	Delete the character under the cursor
+.ti -1.0i
+\fBBackspace\fR	Delete the character to left of the cursor
+.ti -1.0i
+\fBCTRL-N\fR	Delete the next word
+.ti -1.0i
+\fBCTRL-P\fR	Delete the previous word
+.ti -1.0i
+\fBCTRL-T\fR	Delete tail of line (all characters from cursor to end of line)
+.ti -1.0i
+\fBCTRL-O\fR	Open up the line (insert line feed and back up)
+.ti -1.0i
+\fBCTRL-G\fR	Get and insert a file at the cursor position
+
+.ti -1.25i
+\fBBUFFER OPERATIONS\fR
+.ti -1.0i
+\fBCTRL-@\fR	Set mark at current position for use with CTRL-C and CTRL-K
+.ti -1.0i
+\fBCTRL-C\fR	Copy the text between the mark and the cursor into the buffer
+.ti -1.0i
+\fBCTRL-K\fR	Delete text between mark and cursor; also copy it to the buffer
+.ti -1.0i
+\fBCTRL-Y\fR	Yank contents of the buffer out and insert it at the cursor
+.ti -1.0i
+\fBCTRL-Q\fR	Write the contents of the buffer onto a file
+
+.ti -1.25i
+\fBMISCELLANEOUS\fR
+.ti -1.0i
+\fBnumeric +\fR	Search forward (prompts for regular expression)
+.ti -1.0i
+\fBnumeric \(mi\fR	Search backward (prompts for regular expression)
+.ti -1.0i
+\fBnumeric 5\fR	Display the file status
+.ti -1.0i
+\fBCTRL-]\fR	Go to specific line
+.ti -1.0i
+\fBCTRL-R\fR	Global replace \fIpattern\fR with \fIstring\fR (from cursor to end)
+.ti -1.0i
+\fBCTRL-L\fR	Line replace \fIpattern\fR with \fIstring\fR 
+.ti -1.0i
+\fBCTRL-W\fR	Write the edited file back to the disk
+.ti -1.0i
+\fBCTRL-X\fR	Exit the editor
+.ti -1.0i
+\fBCTRL-S\fR	Fork off a shell (use CTRL-D to get back to the editor)
+.ti -1.0i
+\fBCTRL-\\\fR	Abort whatever the editor was doing and wait for command
+.ti -1.0i
+\fBCTRL-E\fR	Erase screen and redraw it
+.ti -1.0i
+\fBCTRL-V\fR	Visit (edit) a new file
+.in -1.25i
+
+.SS "Author"
+.PP
+\fIMined\fR was designed by Andy Tanenbaum and written by Michiel Huisjes.
Index: /trunk/minix/man/template.1
===================================================================
--- /trunk/minix/man/template.1	(revision 9)
+++ /trunk/minix/man/template.1	(revision 9)
@@ -0,0 +1,46 @@
+.TH TEMPLATE 1
+.SH NAME
+template, blueprint \- a blueprint for making manual pages
+.SH SYNOPSIS
+.B template
+.RB [ \-az ]
+.RI [ arguments " ...]"
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B Template
+shows what a manual page should look like.  Options for instance:
+.SH OPTIONS
+.TP
+.B \-a
+Use boldface for characters that have to be typed as is.
+.TP
+.B \-z
+Italics for variable
+.IR arguments .
+.SH ENVIRONMENT
+.TP 15n
+.B MANPATH
+The path to knowledge.
+.SH FILES
+.TP 25n
+.B /usr/man/template.1
+This file.
+.SH "SEE ALSO"
+.BR man (7).
+.SH DIAGNOSTICS
+man: No manual on template.
+.SH NOTES
+Use at your own risk.
+.SH BUGS
+A lot.  The
+.BR whatis (5)
+database is usually generated automatically on most
+systems.  This fails if the "NAME" section has more n/troff fluff than just
+an "\e" before the '\-', or is more than one line.  Apply the KISS
+principle, try to use a minimum of smart macros, match your .RS and .RE's,
+etc.
+.SH AUTHOR
+Kees J. Bot <kjb@cs.vu.nl>
Index: /trunk/minix/servers/Makefile
===================================================================
--- /trunk/minix/servers/Makefile	(revision 9)
+++ /trunk/minix/servers/Makefile	(revision 9)
@@ -0,0 +1,33 @@
+# Makefile for all system servers.
+#
+MAKE = exec make -$(MAKEFLAGS)
+
+usage:
+	@echo "" >&2
+	@echo "Makefile for all system servers." >&2
+	@echo "Usage:" >&2
+	@echo "	make build    # Compile all system servers locally" >&2
+	@echo "	make image    # Compile servers in boot image" >&2
+	@echo "	make clean    # Remove local compiler results" >&2
+	@echo "	make install  # Install servers to /etc/servers/" >&2
+	@echo "	                (requires root privileges)" >&2
+	@echo "" >&2
+
+build: all
+all install depend clean:
+	cd ./pm && $(MAKE) $@
+	cd ./fs && $(MAKE) $@
+	cd ./rs && $(MAKE) $@
+	cd ./ds && $(MAKE) $@
+	cd ./is && $(MAKE) $@
+	cd ./init && $(MAKE) $@
+	cd ./inet && $(MAKE) $@
+
+image:
+	cd ./pm && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
+	cd ./fs && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
+	cd ./rs && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
+	cd ./ds && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
+	cd ./init && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
+
+
Index: /trunk/minix/servers/ds/.depend
===================================================================
--- /trunk/minix/servers/ds/.depend	(revision 9)
+++ /trunk/minix/servers/ds/.depend	(revision 9)
@@ -0,0 +1,56 @@
+
+main.o:	/usr/include/ansi.h
+main.o:	/usr/include/errno.h
+main.o:	/usr/include/limits.h
+main.o:	/usr/include/minix/bitmap.h
+main.o:	/usr/include/minix/callnr.h
+main.o:	/usr/include/minix/com.h
+main.o:	/usr/include/minix/config.h
+main.o:	/usr/include/minix/const.h
+main.o:	/usr/include/minix/devio.h
+main.o:	/usr/include/minix/ipc.h
+main.o:	/usr/include/minix/keymap.h
+main.o:	/usr/include/minix/sys_config.h
+main.o:	/usr/include/minix/syslib.h
+main.o:	/usr/include/minix/sysutil.h
+main.o:	/usr/include/minix/type.h
+main.o:	/usr/include/signal.h
+main.o:	/usr/include/stdio.h
+main.o:	/usr/include/stdlib.h
+main.o:	/usr/include/string.h
+main.o:	/usr/include/sys/dir.h
+main.o:	/usr/include/sys/types.h
+main.o:	/usr/include/unistd.h
+main.o:	glo.h
+main.o:	inc.h
+main.o:	main.c
+main.o:	proto.h
+main.o:	store.h
+
+store.o:	/usr/include/ansi.h
+store.o:	/usr/include/errno.h
+store.o:	/usr/include/limits.h
+store.o:	/usr/include/minix/bitmap.h
+store.o:	/usr/include/minix/callnr.h
+store.o:	/usr/include/minix/com.h
+store.o:	/usr/include/minix/config.h
+store.o:	/usr/include/minix/const.h
+store.o:	/usr/include/minix/devio.h
+store.o:	/usr/include/minix/ipc.h
+store.o:	/usr/include/minix/keymap.h
+store.o:	/usr/include/minix/sys_config.h
+store.o:	/usr/include/minix/syslib.h
+store.o:	/usr/include/minix/sysutil.h
+store.o:	/usr/include/minix/type.h
+store.o:	/usr/include/signal.h
+store.o:	/usr/include/stdio.h
+store.o:	/usr/include/stdlib.h
+store.o:	/usr/include/string.h
+store.o:	/usr/include/sys/dir.h
+store.o:	/usr/include/sys/types.h
+store.o:	/usr/include/unistd.h
+store.o:	glo.h
+store.o:	inc.h
+store.o:	proto.h
+store.o:	store.c
+store.o:	store.h
Index: /trunk/minix/servers/ds/Makefile
===================================================================
--- /trunk/minix/servers/ds/Makefile	(revision 9)
+++ /trunk/minix/servers/ds/Makefile	(revision 9)
@@ -0,0 +1,42 @@
+# Makefile for Data Store Server (DS)
+SERVER = ds
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+k = $u/src/kernel
+p = $u/src/servers/pm
+f = $u/src/servers/fs
+
+# programs, flags, etc.
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsys -lsysutil 
+
+OBJ = main.o store.o 
+
+# build local binary
+all build:	$(SERVER)
+$(SERVER):	$(OBJ)
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+	install -S 16k $@
+
+# install with other servers
+install: $(SERVER)
+	install -o root -c $? /sbin/$(SERVER)
+#	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f $(SERVER) *.o *.bak 
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/servers/ds/glo.h
===================================================================
--- /trunk/minix/servers/ds/glo.h	(revision 9)
+++ /trunk/minix/servers/ds/glo.h	(revision 9)
@@ -0,0 +1,7 @@
+/* Global variables. */
+
+/* The parameters of the call are kept here. */
+extern int who;			/* caller's proc number */
+extern int callnr;		/* system call number */
+extern int dont_reply;		/* normally 0; set to 1 to inhibit reply */
+
Index: /trunk/minix/servers/ds/inc.h
===================================================================
--- /trunk/minix/servers/ds/inc.h	(revision 9)
+++ /trunk/minix/servers/ds/inc.h	(revision 9)
@@ -0,0 +1,30 @@
+/* Header file including all needed system headers. */
+
+#define _SYSTEM            1    /* get OK and negative error codes */
+#define _MINIX             1	/* tell headers to include MINIX stuff */
+
+#include <ansi.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <errno.h>
+
+#include <minix/callnr.h>
+#include <minix/config.h>
+#include <minix/type.h>
+#include <minix/const.h>
+#include <minix/com.h>
+#include <minix/syslib.h>
+#include <minix/sysutil.h>
+#include <minix/keymap.h>
+#include <minix/bitmap.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "proto.h"
+#include "glo.h"
+#include "store.h"
+
Index: /trunk/minix/servers/ds/main.c
===================================================================
--- /trunk/minix/servers/ds/main.c	(revision 9)
+++ /trunk/minix/servers/ds/main.c	(revision 9)
@@ -0,0 +1,151 @@
+/* Data Store Server. 
+ * This service implements a little publish/subscribe data store that is 
+ * crucial for the system's fault tolerance. Components that require state
+ * can store it here, for later retrieval, e.g., after a crash and subsequent
+ * restart by the reincarnation server. 
+ * 
+ * Created:
+ *   Oct 19, 2005	by Jorrit N. Herder
+ */
+
+#include "inc.h"	/* include master header file */
+
+/* Allocate space for the global variables. */
+int who_e;		/* caller's proc number */
+int callnr;		/* system call number */
+int sys_panic;		/* flag to indicate system-wide panic */
+
+extern int errno;	/* error number set by system library */
+
+/* Declare some local functions. */
+FORWARD _PROTOTYPE(void init_server, (int argc, char **argv)		);
+FORWARD _PROTOTYPE(void exit_server, (void)				);
+FORWARD _PROTOTYPE(void sig_handler, (void)				);
+FORWARD _PROTOTYPE(void get_work, (message *m_ptr)			);
+FORWARD _PROTOTYPE(void reply, (int whom, message *m_ptr)		);
+
+/*===========================================================================*
+ *				main                                         *
+ *===========================================================================*/
+PUBLIC int main(int argc, char **argv)
+{
+/* This is the main routine of this service. The main loop consists of 
+ * three major activities: getting new work, processing the work, and
+ * sending the reply. The loop never terminates, unless a panic occurs.
+ */
+  message m;
+  int result;                 
+  sigset_t sigset;
+
+  /* Initialize the server, then go to work. */
+  init_server(argc, argv);
+
+  /* Main loop - get work and do it, forever. */         
+  while (TRUE) {              
+
+      /* Wait for incoming message, sets 'callnr' and 'who'. */
+      get_work(&m);
+
+      switch (callnr) {
+      case PROC_EVENT:
+	  sig_handler();
+          continue;
+      case DS_PUBLISH:
+          result = do_publish(&m);
+          break;
+      case DS_RETRIEVE:
+	  result = do_retrieve(&m);
+	  break;
+      case DS_SUBSCRIBE:
+	  result = do_subscribe(&m);
+	  break;
+      case GETSYSINFO:
+	  result = do_getsysinfo(&m);
+	  break;
+      default: 
+          report("DS","warning, got illegal request from:", m.m_source);
+          result = EINVAL;
+      }
+
+      /* Finally send reply message, unless disabled. */
+      if (result != EDONTREPLY) {
+          m.m_type = result;  		/* build reply message */
+	  reply(who_e, &m);		/* send it away */
+      }
+  }
+  return(OK);				/* shouldn't come here */
+}
+
+/*===========================================================================*
+ *				 init_server                                 *
+ *===========================================================================*/
+PRIVATE void init_server(int argc, char **argv)
+{
+/* Initialize the data store server. */
+  int i, s;
+  struct sigaction sigact;
+
+  /* Install signal handler. Ask PM to transform signal into message. */
+  sigact.sa_handler = SIG_MESS;
+  sigact.sa_mask = ~0;			/* block all other signals */
+  sigact.sa_flags = 0;			/* default behaviour */
+  if (sigaction(SIGTERM, &sigact, NULL) < 0) 
+      report("DS","warning, sigaction() failed", errno);
+}
+
+/*===========================================================================*
+ *				 sig_handler                                 *
+ *===========================================================================*/
+PRIVATE void sig_handler()
+{
+/* Signal handler. */
+  sigset_t sigset;
+  int sig;
+
+  /* Try to obtain signal set from PM. */
+  if (getsigset(&sigset) != 0) return;
+
+  /* Check for known signals. */
+  if (sigismember(&sigset, SIGTERM)) {
+      exit_server();
+  }
+}
+
+/*===========================================================================*
+ *				exit_server                                  *
+ *===========================================================================*/
+PRIVATE void exit_server()
+{
+/* Shut down the information service. */
+
+  /* Done. Now exit. */
+  exit(0);
+}
+
+/*===========================================================================*
+ *				get_work                                     *
+ *===========================================================================*/
+PRIVATE void get_work(m_ptr)
+message *m_ptr;				/* message buffer */
+{
+    int status = 0;
+    status = receive(ANY, m_ptr);   /* this blocks until message arrives */
+    if (OK != status)
+        panic("DS","failed to receive message!", status);
+    who_e = m_ptr->m_source;        /* message arrived! set sender */
+    callnr = m_ptr->m_type;       /* set function call number */
+}
+
+/*===========================================================================*
+ *				reply					     *
+ *===========================================================================*/
+PRIVATE void reply(who_e, m_ptr)
+int who_e;                           	/* destination */
+message *m_ptr;				/* message buffer */
+{
+    int s;
+    s = send(who_e, m_ptr);    /* send the message */
+    if (OK != s)
+        panic("DS", "unable to send reply!", s);
+}
+
Index: /trunk/minix/servers/ds/proto.h
===================================================================
--- /trunk/minix/servers/ds/proto.h	(revision 9)
+++ /trunk/minix/servers/ds/proto.h	(revision 9)
@@ -0,0 +1,10 @@
+/* Function prototypes. */
+
+/* main.c */
+_PROTOTYPE(int main, (int argc, char **argv));
+
+/* store.c */
+_PROTOTYPE(int do_publish, (message *m_ptr));
+_PROTOTYPE(int do_retrieve, (message *m_ptr));
+_PROTOTYPE(int do_subscribe, (message *m_ptr));
+_PROTOTYPE(int do_getsysinfo, (message *m_ptr));
Index: /trunk/minix/servers/ds/store.c
===================================================================
--- /trunk/minix/servers/ds/store.c	(revision 9)
+++ /trunk/minix/servers/ds/store.c	(revision 9)
@@ -0,0 +1,163 @@
+/* Implementation of the Data Store. */
+
+#include "inc.h"
+
+/* Allocate space for the data store. */
+PRIVATE struct data_store ds_store[NR_DS_KEYS];
+PRIVATE int nr_in_use;
+
+PRIVATE _PROTOTYPE(int find_key, (int key, struct data_store **dsp));
+PRIVATE _PROTOTYPE(int set_owner, (struct data_store *dsp, void *auth_ptr));
+PRIVATE _PROTOTYPE(int is_authorized, (struct data_store *dsp, void *auth_ptr));
+
+
+PRIVATE int set_owner(dsp, ap)
+struct data_store *dsp;				/* data store structure */
+void *ap;					/* authorization pointer */
+{
+  /* Authorize the caller. */
+  return(TRUE);
+}
+
+
+PRIVATE int is_authorized(dsp, ap)
+struct data_store *dsp;				/* data store structure */
+void *ap;					/* authorization pointer */
+{
+  /* Authorize the caller. */
+  return(TRUE);
+}
+
+
+PRIVATE int find_key(key, dsp)
+int key;					/* key to look up */
+struct data_store **dsp;			/* store pointer here */
+{
+  register int i;
+
+  *dsp = NULL;
+  for (i=0; i<NR_DS_KEYS; i++) {
+      if ((ds_store[i].ds_flags & DS_IN_USE) && ds_store[i].ds_key == key) {
+	  *dsp = &ds_store[i];
+          return(TRUE);				/* report success */
+      }
+  }
+  return(FALSE);				/* report not found */
+}
+
+
+PUBLIC int do_publish(m_ptr)
+message *m_ptr;					/* request message */
+{
+  struct data_store *dsp;
+
+  /* Store (key,value)-pair. First see if key already exists. If so, 
+   * check if the caller is allowed to overwrite the value. Otherwise
+   * find a new slot and store the new value. 
+   */
+  if (find_key(m_ptr->DS_KEY, &dsp)) {			/* look up key */
+      if (! is_authorized(dsp,m_ptr->DS_AUTH)) {	/* check if owner */
+          return(EPERM);
+      }
+  } 
+  else {						/* find a new slot */
+      if (nr_in_use >= NR_DS_KEYS) {
+	  return(EAGAIN);				/* store is full */
+      } else {
+          dsp = &ds_store[nr_in_use];			/* new slot found */
+	  dsp->ds_key = m_ptr->DS_KEY;
+	  if (! set_owner(dsp,m_ptr->DS_AUTH)) {	/* associate owner */
+	      return(EINVAL);
+	  }
+	  dsp->ds_nr_subs = 0;				/* nr of subscribers */
+	  dsp->ds_flags = DS_IN_USE;			/* initialize slot */
+	  nr_in_use ++;
+      }
+  }
+
+  /* At this point we have a data store pointer and know the caller is 
+   * authorize to write to it. Set all fields as requested.
+   */
+  dsp->ds_val_l1 = m_ptr->DS_VAL_L1;		/* store all data */
+  dsp->ds_val_l2 = m_ptr->DS_VAL_L2;	
+
+  /* If the data is public. Check if there are any subscribers to this key. 
+   * If so, notify all subscribers so that they can retrieve the data, if 
+   * they're still interested.
+   */
+  if ((dsp->ds_flags & DS_PUBLIC) && dsp->ds_nr_subs > 0) {
+
+      /* Subscriptions are not yet implemented. */
+  }
+
+  return(OK);
+}
+
+
+PUBLIC int do_retrieve(m_ptr)
+message *m_ptr;					/* request message */
+{
+  struct data_store *dsp;
+
+  /* Retrieve data. Look up the key in the data store. Return an error if it
+   * is not found. If this data is private, only the owner may retrieve it.
+   */ 
+  if (find_key(m_ptr->DS_KEY, &dsp)) {			/* look up key */
+
+      /* If the data is not public, the caller must be authorized. */
+      if (! dsp->ds_flags & DS_PUBLIC) {		/* check if private */
+          if (! is_authorized(dsp,m_ptr->DS_AUTH)) {	/* authorize call */
+              return(EPERM);				/* not allowed */
+          }
+      }
+
+      /* Data is public or the caller is authorized to retrieve it. */
+      printf("DS retrieves data: key %d (found %d), l1 %u, l2 %u\n",
+		m_ptr->DS_KEY, dsp->ds_key, dsp->ds_val_l1, dsp->ds_val_l2);
+      m_ptr->DS_VAL_L1 = dsp->ds_val_l1;		/* return value */
+      m_ptr->DS_VAL_L2 = dsp->ds_val_l2;		/* return value */
+      return(OK);					/* report success */
+  }
+  return(ESRCH);					/* key not found */
+}
+
+
+PUBLIC int do_subscribe(m_ptr)
+message *m_ptr;					/* request message */
+{
+  /* Subscribe to a key of interest. Only existing and public keys can be
+   * subscribed to. All updates to the key will cause a notification message
+   * to be sent to the subscribed. On success, directly return a copy of the
+   * data for the given key. 
+   */
+  return(ENOSYS);
+}
+
+
+/*===========================================================================*
+ *				do_getsysinfo				     *
+ *===========================================================================*/
+PUBLIC int do_getsysinfo(m_ptr)
+message *m_ptr;
+{
+  vir_bytes src_addr, dst_addr;
+  int dst_proc;
+  size_t len;
+  int s;
+
+  switch(m_ptr->m1_i1) {
+  case SI_DATA_STORE:
+  	src_addr = (vir_bytes) ds_store;
+  	len = sizeof(struct data_store) * NR_DS_KEYS;
+  	break; 
+  default:
+  	return(EINVAL);
+  }
+
+  dst_proc = m_ptr->m_source;
+  dst_addr = (vir_bytes) m_ptr->m1_p1;
+  if (OK != (s=sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)))
+  	return(s);
+  return(OK);
+}
+
Index: /trunk/minix/servers/ds/store.h
===================================================================
--- /trunk/minix/servers/ds/store.h	(revision 9)
+++ /trunk/minix/servers/ds/store.h	(revision 9)
@@ -0,0 +1,19 @@
+/* Type definitions for the Data Store Server. */
+struct data_store {
+  int ds_flags;			/* flags for this store */
+  int ds_key;			/* key to lookup information */
+  long ds_val_l1;		/* data associated with key */
+  long ds_val_l2;		/* data associated with key */
+  long ds_auth;			/* secret given by owner of data */
+  int ds_nr_subs;		/* number of subscribers for key */ 
+};
+
+/* Flag values. */
+#define DS_IN_USE	0x01
+#define DS_PUBLIC	0x02
+
+/* Constants for the Data Store Server. */
+#define NR_DS_KEYS	  64	/* reserve space for so many items */
+
+
+
Index: /trunk/minix/servers/fs/.depend
===================================================================
--- /trunk/minix/servers/fs/.depend	(revision 9)
+++ /trunk/minix/servers/fs/.depend	(revision 9)
@@ -0,0 +1,786 @@
+
+cache.o:	/usr/include/ansi.h
+cache.o:	/usr/include/dirent.h
+cache.o:	/usr/include/errno.h
+cache.o:	/usr/include/limits.h
+cache.o:	/usr/include/minix/com.h
+cache.o:	/usr/include/minix/config.h
+cache.o:	/usr/include/minix/const.h
+cache.o:	/usr/include/minix/devio.h
+cache.o:	/usr/include/minix/dmap.h
+cache.o:	/usr/include/minix/ipc.h
+cache.o:	/usr/include/minix/sys_config.h
+cache.o:	/usr/include/minix/syslib.h
+cache.o:	/usr/include/minix/sysutil.h
+cache.o:	/usr/include/minix/type.h
+cache.o:	/usr/include/string.h
+cache.o:	/usr/include/sys/dir.h
+cache.o:	/usr/include/sys/select.h
+cache.o:	/usr/include/sys/time.h
+cache.o:	/usr/include/sys/types.h
+cache.o:	/usr/include/timers.h
+cache.o:	buf.h
+cache.o:	cache.c
+cache.o:	const.h
+cache.o:	file.h
+cache.o:	fproc.h
+cache.o:	fs.h
+cache.o:	glo.h
+cache.o:	proto.h
+cache.o:	super.h
+cache.o:	type.h
+
+cache2.o:	/usr/include/ansi.h
+cache2.o:	/usr/include/dirent.h
+cache2.o:	/usr/include/errno.h
+cache2.o:	/usr/include/limits.h
+cache2.o:	/usr/include/minix/com.h
+cache2.o:	/usr/include/minix/config.h
+cache2.o:	/usr/include/minix/const.h
+cache2.o:	/usr/include/minix/devio.h
+cache2.o:	/usr/include/minix/dmap.h
+cache2.o:	/usr/include/minix/ipc.h
+cache2.o:	/usr/include/minix/sys_config.h
+cache2.o:	/usr/include/minix/syslib.h
+cache2.o:	/usr/include/minix/sysutil.h
+cache2.o:	/usr/include/minix/type.h
+cache2.o:	/usr/include/sys/dir.h
+cache2.o:	/usr/include/sys/types.h
+cache2.o:	/usr/include/timers.h
+cache2.o:	buf.h
+cache2.o:	cache2.c
+cache2.o:	const.h
+cache2.o:	fs.h
+cache2.o:	glo.h
+cache2.o:	proto.h
+cache2.o:	type.h
+
+device.o:	/usr/include/ansi.h
+device.o:	/usr/include/errno.h
+device.o:	/usr/include/fcntl.h
+device.o:	/usr/include/limits.h
+device.o:	/usr/include/minix/callnr.h
+device.o:	/usr/include/minix/com.h
+device.o:	/usr/include/minix/config.h
+device.o:	/usr/include/minix/const.h
+device.o:	/usr/include/minix/devio.h
+device.o:	/usr/include/minix/dmap.h
+device.o:	/usr/include/minix/endpoint.h
+device.o:	/usr/include/minix/ipc.h
+device.o:	/usr/include/minix/sys_config.h
+device.o:	/usr/include/minix/syslib.h
+device.o:	/usr/include/minix/sysutil.h
+device.o:	/usr/include/minix/type.h
+device.o:	/usr/include/string.h
+device.o:	/usr/include/sys/dir.h
+device.o:	/usr/include/sys/select.h
+device.o:	/usr/include/sys/time.h
+device.o:	/usr/include/sys/types.h
+device.o:	/usr/include/timers.h
+device.o:	const.h
+device.o:	device.c
+device.o:	file.h
+device.o:	fproc.h
+device.o:	fs.h
+device.o:	glo.h
+device.o:	inode.h
+device.o:	param.h
+device.o:	proto.h
+device.o:	super.h
+device.o:	type.h
+
+dmap.o:	/usr/include/ansi.h
+dmap.o:	/usr/include/ctype.h
+dmap.o:	/usr/include/errno.h
+dmap.o:	/usr/include/limits.h
+dmap.o:	/usr/include/minix/com.h
+dmap.o:	/usr/include/minix/config.h
+dmap.o:	/usr/include/minix/const.h
+dmap.o:	/usr/include/minix/devio.h
+dmap.o:	/usr/include/minix/dmap.h
+dmap.o:	/usr/include/minix/ipc.h
+dmap.o:	/usr/include/minix/sys_config.h
+dmap.o:	/usr/include/minix/syslib.h
+dmap.o:	/usr/include/minix/sysutil.h
+dmap.o:	/usr/include/minix/type.h
+dmap.o:	/usr/include/stdlib.h
+dmap.o:	/usr/include/string.h
+dmap.o:	/usr/include/sys/dir.h
+dmap.o:	/usr/include/sys/select.h
+dmap.o:	/usr/include/sys/time.h
+dmap.o:	/usr/include/sys/types.h
+dmap.o:	/usr/include/timers.h
+dmap.o:	/usr/include/unistd.h
+dmap.o:	const.h
+dmap.o:	dmap.c
+dmap.o:	fproc.h
+dmap.o:	fs.h
+dmap.o:	glo.h
+dmap.o:	param.h
+dmap.o:	proto.h
+dmap.o:	type.h
+
+filedes.o:	/usr/include/ansi.h
+filedes.o:	/usr/include/errno.h
+filedes.o:	/usr/include/limits.h
+filedes.o:	/usr/include/minix/config.h
+filedes.o:	/usr/include/minix/const.h
+filedes.o:	/usr/include/minix/devio.h
+filedes.o:	/usr/include/minix/dmap.h
+filedes.o:	/usr/include/minix/ipc.h
+filedes.o:	/usr/include/minix/sys_config.h
+filedes.o:	/usr/include/minix/syslib.h
+filedes.o:	/usr/include/minix/sysutil.h
+filedes.o:	/usr/include/minix/type.h
+filedes.o:	/usr/include/string.h
+filedes.o:	/usr/include/sys/dir.h
+filedes.o:	/usr/include/sys/select.h
+filedes.o:	/usr/include/sys/time.h
+filedes.o:	/usr/include/sys/types.h
+filedes.o:	/usr/include/timers.h
+filedes.o:	const.h
+filedes.o:	file.h
+filedes.o:	filedes.c
+filedes.o:	fproc.h
+filedes.o:	fs.h
+filedes.o:	glo.h
+filedes.o:	inode.h
+filedes.o:	proto.h
+filedes.o:	type.h
+
+inode.o:	/usr/include/ansi.h
+inode.o:	/usr/include/dirent.h
+inode.o:	/usr/include/errno.h
+inode.o:	/usr/include/limits.h
+inode.o:	/usr/include/minix/config.h
+inode.o:	/usr/include/minix/const.h
+inode.o:	/usr/include/minix/devio.h
+inode.o:	/usr/include/minix/dmap.h
+inode.o:	/usr/include/minix/ipc.h
+inode.o:	/usr/include/minix/sys_config.h
+inode.o:	/usr/include/minix/syslib.h
+inode.o:	/usr/include/minix/sysutil.h
+inode.o:	/usr/include/minix/type.h
+inode.o:	/usr/include/string.h
+inode.o:	/usr/include/sys/dir.h
+inode.o:	/usr/include/sys/select.h
+inode.o:	/usr/include/sys/time.h
+inode.o:	/usr/include/sys/types.h
+inode.o:	/usr/include/timers.h
+inode.o:	buf.h
+inode.o:	const.h
+inode.o:	file.h
+inode.o:	fproc.h
+inode.o:	fs.h
+inode.o:	glo.h
+inode.o:	inode.c
+inode.o:	inode.h
+inode.o:	proto.h
+inode.o:	super.h
+inode.o:	type.h
+
+link.o:	/usr/include/ansi.h
+link.o:	/usr/include/dirent.h
+link.o:	/usr/include/errno.h
+link.o:	/usr/include/limits.h
+link.o:	/usr/include/minix/callnr.h
+link.o:	/usr/include/minix/com.h
+link.o:	/usr/include/minix/config.h
+link.o:	/usr/include/minix/const.h
+link.o:	/usr/include/minix/devio.h
+link.o:	/usr/include/minix/dmap.h
+link.o:	/usr/include/minix/ipc.h
+link.o:	/usr/include/minix/sys_config.h
+link.o:	/usr/include/minix/syslib.h
+link.o:	/usr/include/minix/sysutil.h
+link.o:	/usr/include/minix/type.h
+link.o:	/usr/include/string.h
+link.o:	/usr/include/sys/dir.h
+link.o:	/usr/include/sys/select.h
+link.o:	/usr/include/sys/stat.h
+link.o:	/usr/include/sys/time.h
+link.o:	/usr/include/sys/types.h
+link.o:	/usr/include/timers.h
+link.o:	buf.h
+link.o:	const.h
+link.o:	file.h
+link.o:	fproc.h
+link.o:	fs.h
+link.o:	glo.h
+link.o:	inode.h
+link.o:	link.c
+link.o:	param.h
+link.o:	proto.h
+link.o:	super.h
+link.o:	type.h
+
+lock.o:	/usr/include/ansi.h
+lock.o:	/usr/include/errno.h
+lock.o:	/usr/include/fcntl.h
+lock.o:	/usr/include/limits.h
+lock.o:	/usr/include/minix/com.h
+lock.o:	/usr/include/minix/config.h
+lock.o:	/usr/include/minix/const.h
+lock.o:	/usr/include/minix/devio.h
+lock.o:	/usr/include/minix/dmap.h
+lock.o:	/usr/include/minix/ipc.h
+lock.o:	/usr/include/minix/sys_config.h
+lock.o:	/usr/include/minix/syslib.h
+lock.o:	/usr/include/minix/sysutil.h
+lock.o:	/usr/include/minix/type.h
+lock.o:	/usr/include/string.h
+lock.o:	/usr/include/sys/dir.h
+lock.o:	/usr/include/sys/select.h
+lock.o:	/usr/include/sys/time.h
+lock.o:	/usr/include/sys/types.h
+lock.o:	/usr/include/timers.h
+lock.o:	/usr/include/unistd.h
+lock.o:	const.h
+lock.o:	file.h
+lock.o:	fproc.h
+lock.o:	fs.h
+lock.o:	glo.h
+lock.o:	inode.h
+lock.o:	lock.c
+lock.o:	lock.h
+lock.o:	param.h
+lock.o:	proto.h
+lock.o:	type.h
+
+main.o:	/usr/include/ansi.h
+main.o:	/usr/include/dirent.h
+main.o:	/usr/include/errno.h
+main.o:	/usr/include/fcntl.h
+main.o:	/usr/include/limits.h
+main.o:	/usr/include/minix/callnr.h
+main.o:	/usr/include/minix/com.h
+main.o:	/usr/include/minix/config.h
+main.o:	/usr/include/minix/const.h
+main.o:	/usr/include/minix/devio.h
+main.o:	/usr/include/minix/dmap.h
+main.o:	/usr/include/minix/endpoint.h
+main.o:	/usr/include/minix/ioctl.h
+main.o:	/usr/include/minix/ipc.h
+main.o:	/usr/include/minix/keymap.h
+main.o:	/usr/include/minix/sys_config.h
+main.o:	/usr/include/minix/syslib.h
+main.o:	/usr/include/minix/sysutil.h
+main.o:	/usr/include/minix/type.h
+main.o:	/usr/include/signal.h
+main.o:	/usr/include/stdio.h
+main.o:	/usr/include/stdlib.h
+main.o:	/usr/include/string.h
+main.o:	/usr/include/sys/dir.h
+main.o:	/usr/include/sys/ioc_memory.h
+main.o:	/usr/include/sys/select.h
+main.o:	/usr/include/sys/svrctl.h
+main.o:	/usr/include/sys/time.h
+main.o:	/usr/include/sys/types.h
+main.o:	/usr/include/timers.h
+main.o:	buf.h
+main.o:	const.h
+main.o:	file.h
+main.o:	fproc.h
+main.o:	fs.h
+main.o:	glo.h
+main.o:	inode.h
+main.o:	main.c
+main.o:	param.h
+main.o:	proto.h
+main.o:	super.h
+main.o:	type.h
+
+misc.o:	/usr/include/ansi.h
+misc.o:	/usr/include/dirent.h
+misc.o:	/usr/include/errno.h
+misc.o:	/usr/include/fcntl.h
+misc.o:	/usr/include/limits.h
+misc.o:	/usr/include/minix/callnr.h
+misc.o:	/usr/include/minix/com.h
+misc.o:	/usr/include/minix/config.h
+misc.o:	/usr/include/minix/const.h
+misc.o:	/usr/include/minix/devio.h
+misc.o:	/usr/include/minix/dmap.h
+misc.o:	/usr/include/minix/endpoint.h
+misc.o:	/usr/include/minix/ioctl.h
+misc.o:	/usr/include/minix/ipc.h
+misc.o:	/usr/include/minix/sys_config.h
+misc.o:	/usr/include/minix/syslib.h
+misc.o:	/usr/include/minix/sysutil.h
+misc.o:	/usr/include/minix/type.h
+misc.o:	/usr/include/string.h
+misc.o:	/usr/include/sys/dir.h
+misc.o:	/usr/include/sys/select.h
+misc.o:	/usr/include/sys/svrctl.h
+misc.o:	/usr/include/sys/time.h
+misc.o:	/usr/include/sys/types.h
+misc.o:	/usr/include/timers.h
+misc.o:	/usr/include/unistd.h
+misc.o:	buf.h
+misc.o:	const.h
+misc.o:	file.h
+misc.o:	fproc.h
+misc.o:	fs.h
+misc.o:	glo.h
+misc.o:	inode.h
+misc.o:	misc.c
+misc.o:	param.h
+misc.o:	proto.h
+misc.o:	super.h
+misc.o:	type.h
+
+mount.o:	/usr/include/ansi.h
+mount.o:	/usr/include/dirent.h
+mount.o:	/usr/include/errno.h
+mount.o:	/usr/include/fcntl.h
+mount.o:	/usr/include/limits.h
+mount.o:	/usr/include/minix/com.h
+mount.o:	/usr/include/minix/config.h
+mount.o:	/usr/include/minix/const.h
+mount.o:	/usr/include/minix/devio.h
+mount.o:	/usr/include/minix/dmap.h
+mount.o:	/usr/include/minix/ipc.h
+mount.o:	/usr/include/minix/sys_config.h
+mount.o:	/usr/include/minix/syslib.h
+mount.o:	/usr/include/minix/sysutil.h
+mount.o:	/usr/include/minix/type.h
+mount.o:	/usr/include/string.h
+mount.o:	/usr/include/sys/dir.h
+mount.o:	/usr/include/sys/select.h
+mount.o:	/usr/include/sys/stat.h
+mount.o:	/usr/include/sys/time.h
+mount.o:	/usr/include/sys/types.h
+mount.o:	/usr/include/timers.h
+mount.o:	buf.h
+mount.o:	const.h
+mount.o:	file.h
+mount.o:	fproc.h
+mount.o:	fs.h
+mount.o:	glo.h
+mount.o:	inode.h
+mount.o:	mount.c
+mount.o:	param.h
+mount.o:	proto.h
+mount.o:	super.h
+mount.o:	type.h
+
+open.o:	/usr/include/ansi.h
+open.o:	/usr/include/dirent.h
+open.o:	/usr/include/errno.h
+open.o:	/usr/include/fcntl.h
+open.o:	/usr/include/limits.h
+open.o:	/usr/include/minix/callnr.h
+open.o:	/usr/include/minix/com.h
+open.o:	/usr/include/minix/config.h
+open.o:	/usr/include/minix/const.h
+open.o:	/usr/include/minix/devio.h
+open.o:	/usr/include/minix/dmap.h
+open.o:	/usr/include/minix/ipc.h
+open.o:	/usr/include/minix/sys_config.h
+open.o:	/usr/include/minix/syslib.h
+open.o:	/usr/include/minix/sysutil.h
+open.o:	/usr/include/minix/type.h
+open.o:	/usr/include/string.h
+open.o:	/usr/include/sys/dir.h
+open.o:	/usr/include/sys/select.h
+open.o:	/usr/include/sys/stat.h
+open.o:	/usr/include/sys/time.h
+open.o:	/usr/include/sys/types.h
+open.o:	/usr/include/timers.h
+open.o:	/usr/include/unistd.h
+open.o:	buf.h
+open.o:	const.h
+open.o:	file.h
+open.o:	fproc.h
+open.o:	fs.h
+open.o:	glo.h
+open.o:	inode.h
+open.o:	lock.h
+open.o:	open.c
+open.o:	param.h
+open.o:	proto.h
+open.o:	super.h
+open.o:	type.h
+
+path.o:	/usr/include/ansi.h
+path.o:	/usr/include/dirent.h
+path.o:	/usr/include/errno.h
+path.o:	/usr/include/limits.h
+path.o:	/usr/include/minix/callnr.h
+path.o:	/usr/include/minix/config.h
+path.o:	/usr/include/minix/const.h
+path.o:	/usr/include/minix/devio.h
+path.o:	/usr/include/minix/dmap.h
+path.o:	/usr/include/minix/ipc.h
+path.o:	/usr/include/minix/sys_config.h
+path.o:	/usr/include/minix/syslib.h
+path.o:	/usr/include/minix/sysutil.h
+path.o:	/usr/include/minix/type.h
+path.o:	/usr/include/string.h
+path.o:	/usr/include/sys/dir.h
+path.o:	/usr/include/sys/select.h
+path.o:	/usr/include/sys/stat.h
+path.o:	/usr/include/sys/time.h
+path.o:	/usr/include/sys/types.h
+path.o:	/usr/include/timers.h
+path.o:	buf.h
+path.o:	const.h
+path.o:	file.h
+path.o:	fproc.h
+path.o:	fs.h
+path.o:	glo.h
+path.o:	inode.h
+path.o:	path.c
+path.o:	proto.h
+path.o:	super.h
+path.o:	type.h
+
+pipe.o:	/usr/include/ansi.h
+pipe.o:	/usr/include/errno.h
+pipe.o:	/usr/include/fcntl.h
+pipe.o:	/usr/include/limits.h
+pipe.o:	/usr/include/minix/callnr.h
+pipe.o:	/usr/include/minix/com.h
+pipe.o:	/usr/include/minix/config.h
+pipe.o:	/usr/include/minix/const.h
+pipe.o:	/usr/include/minix/devio.h
+pipe.o:	/usr/include/minix/dmap.h
+pipe.o:	/usr/include/minix/endpoint.h
+pipe.o:	/usr/include/minix/ipc.h
+pipe.o:	/usr/include/minix/sys_config.h
+pipe.o:	/usr/include/minix/syslib.h
+pipe.o:	/usr/include/minix/sysutil.h
+pipe.o:	/usr/include/minix/type.h
+pipe.o:	/usr/include/signal.h
+pipe.o:	/usr/include/string.h
+pipe.o:	/usr/include/sys/dir.h
+pipe.o:	/usr/include/sys/select.h
+pipe.o:	/usr/include/sys/time.h
+pipe.o:	/usr/include/sys/types.h
+pipe.o:	/usr/include/timers.h
+pipe.o:	const.h
+pipe.o:	file.h
+pipe.o:	fproc.h
+pipe.o:	fs.h
+pipe.o:	glo.h
+pipe.o:	inode.h
+pipe.o:	param.h
+pipe.o:	pipe.c
+pipe.o:	proto.h
+pipe.o:	select.h
+pipe.o:	super.h
+pipe.o:	type.h
+
+protect.o:	/usr/include/ansi.h
+protect.o:	/usr/include/dirent.h
+protect.o:	/usr/include/errno.h
+protect.o:	/usr/include/limits.h
+protect.o:	/usr/include/minix/callnr.h
+protect.o:	/usr/include/minix/config.h
+protect.o:	/usr/include/minix/const.h
+protect.o:	/usr/include/minix/devio.h
+protect.o:	/usr/include/minix/dmap.h
+protect.o:	/usr/include/minix/ipc.h
+protect.o:	/usr/include/minix/sys_config.h
+protect.o:	/usr/include/minix/syslib.h
+protect.o:	/usr/include/minix/sysutil.h
+protect.o:	/usr/include/minix/type.h
+protect.o:	/usr/include/string.h
+protect.o:	/usr/include/sys/dir.h
+protect.o:	/usr/include/sys/select.h
+protect.o:	/usr/include/sys/time.h
+protect.o:	/usr/include/sys/types.h
+protect.o:	/usr/include/timers.h
+protect.o:	/usr/include/unistd.h
+protect.o:	buf.h
+protect.o:	const.h
+protect.o:	file.h
+protect.o:	fproc.h
+protect.o:	fs.h
+protect.o:	glo.h
+protect.o:	inode.h
+protect.o:	param.h
+protect.o:	protect.c
+protect.o:	proto.h
+protect.o:	super.h
+protect.o:	type.h
+
+read.o:	/usr/include/ansi.h
+read.o:	/usr/include/dirent.h
+read.o:	/usr/include/errno.h
+read.o:	/usr/include/fcntl.h
+read.o:	/usr/include/limits.h
+read.o:	/usr/include/minix/com.h
+read.o:	/usr/include/minix/config.h
+read.o:	/usr/include/minix/const.h
+read.o:	/usr/include/minix/devio.h
+read.o:	/usr/include/minix/dmap.h
+read.o:	/usr/include/minix/ipc.h
+read.o:	/usr/include/minix/sys_config.h
+read.o:	/usr/include/minix/syslib.h
+read.o:	/usr/include/minix/sysutil.h
+read.o:	/usr/include/minix/type.h
+read.o:	/usr/include/string.h
+read.o:	/usr/include/sys/dir.h
+read.o:	/usr/include/sys/select.h
+read.o:	/usr/include/sys/time.h
+read.o:	/usr/include/sys/types.h
+read.o:	/usr/include/timers.h
+read.o:	/usr/include/unistd.h
+read.o:	buf.h
+read.o:	const.h
+read.o:	file.h
+read.o:	fproc.h
+read.o:	fs.h
+read.o:	glo.h
+read.o:	inode.h
+read.o:	param.h
+read.o:	proto.h
+read.o:	read.c
+read.o:	super.h
+read.o:	type.h
+
+select.o:	/usr/include/ansi.h
+select.o:	/usr/include/errno.h
+select.o:	/usr/include/limits.h
+select.o:	/usr/include/minix/com.h
+select.o:	/usr/include/minix/config.h
+select.o:	/usr/include/minix/const.h
+select.o:	/usr/include/minix/devio.h
+select.o:	/usr/include/minix/dmap.h
+select.o:	/usr/include/minix/ipc.h
+select.o:	/usr/include/minix/sys_config.h
+select.o:	/usr/include/minix/syslib.h
+select.o:	/usr/include/minix/sysutil.h
+select.o:	/usr/include/minix/type.h
+select.o:	/usr/include/string.h
+select.o:	/usr/include/sys/dir.h
+select.o:	/usr/include/sys/select.h
+select.o:	/usr/include/sys/time.h
+select.o:	/usr/include/sys/types.h
+select.o:	/usr/include/timers.h
+select.o:	const.h
+select.o:	file.h
+select.o:	fs.h
+select.o:	glo.h
+select.o:	inode.h
+select.o:	proto.h
+select.o:	select.c
+select.o:	select.h
+select.o:	type.h
+
+stadir.o:	/usr/include/ansi.h
+stadir.o:	/usr/include/dirent.h
+stadir.o:	/usr/include/errno.h
+stadir.o:	/usr/include/limits.h
+stadir.o:	/usr/include/minix/com.h
+stadir.o:	/usr/include/minix/config.h
+stadir.o:	/usr/include/minix/const.h
+stadir.o:	/usr/include/minix/devio.h
+stadir.o:	/usr/include/minix/dmap.h
+stadir.o:	/usr/include/minix/ipc.h
+stadir.o:	/usr/include/minix/sys_config.h
+stadir.o:	/usr/include/minix/syslib.h
+stadir.o:	/usr/include/minix/sysutil.h
+stadir.o:	/usr/include/minix/type.h
+stadir.o:	/usr/include/string.h
+stadir.o:	/usr/include/sys/dir.h
+stadir.o:	/usr/include/sys/select.h
+stadir.o:	/usr/include/sys/stat.h
+stadir.o:	/usr/include/sys/statfs.h
+stadir.o:	/usr/include/sys/time.h
+stadir.o:	/usr/include/sys/types.h
+stadir.o:	/usr/include/timers.h
+stadir.o:	buf.h
+stadir.o:	const.h
+stadir.o:	file.h
+stadir.o:	fproc.h
+stadir.o:	fs.h
+stadir.o:	glo.h
+stadir.o:	inode.h
+stadir.o:	param.h
+stadir.o:	proto.h
+stadir.o:	stadir.c
+stadir.o:	super.h
+stadir.o:	type.h
+
+super.o:	/usr/include/ansi.h
+super.o:	/usr/include/dirent.h
+super.o:	/usr/include/errno.h
+super.o:	/usr/include/limits.h
+super.o:	/usr/include/minix/com.h
+super.o:	/usr/include/minix/config.h
+super.o:	/usr/include/minix/const.h
+super.o:	/usr/include/minix/devio.h
+super.o:	/usr/include/minix/dmap.h
+super.o:	/usr/include/minix/ipc.h
+super.o:	/usr/include/minix/sys_config.h
+super.o:	/usr/include/minix/syslib.h
+super.o:	/usr/include/minix/sysutil.h
+super.o:	/usr/include/minix/type.h
+super.o:	/usr/include/string.h
+super.o:	/usr/include/sys/dir.h
+super.o:	/usr/include/sys/types.h
+super.o:	/usr/include/timers.h
+super.o:	buf.h
+super.o:	const.h
+super.o:	fs.h
+super.o:	glo.h
+super.o:	inode.h
+super.o:	proto.h
+super.o:	super.c
+super.o:	super.h
+super.o:	type.h
+
+table.o:	/usr/include/ansi.h
+table.o:	/usr/include/dirent.h
+table.o:	/usr/include/errno.h
+table.o:	/usr/include/limits.h
+table.o:	/usr/include/minix/callnr.h
+table.o:	/usr/include/minix/com.h
+table.o:	/usr/include/minix/config.h
+table.o:	/usr/include/minix/const.h
+table.o:	/usr/include/minix/devio.h
+table.o:	/usr/include/minix/dmap.h
+table.o:	/usr/include/minix/ipc.h
+table.o:	/usr/include/minix/sys_config.h
+table.o:	/usr/include/minix/syslib.h
+table.o:	/usr/include/minix/sysutil.h
+table.o:	/usr/include/minix/type.h
+table.o:	/usr/include/string.h
+table.o:	/usr/include/sys/dir.h
+table.o:	/usr/include/sys/select.h
+table.o:	/usr/include/sys/time.h
+table.o:	/usr/include/sys/types.h
+table.o:	/usr/include/timers.h
+table.o:	buf.h
+table.o:	const.h
+table.o:	file.h
+table.o:	fproc.h
+table.o:	fs.h
+table.o:	glo.h
+table.o:	inode.h
+table.o:	lock.h
+table.o:	proto.h
+table.o:	super.h
+table.o:	table.c
+table.o:	type.h
+
+time.o:	/usr/include/ansi.h
+time.o:	/usr/include/errno.h
+time.o:	/usr/include/limits.h
+time.o:	/usr/include/minix/callnr.h
+time.o:	/usr/include/minix/com.h
+time.o:	/usr/include/minix/config.h
+time.o:	/usr/include/minix/const.h
+time.o:	/usr/include/minix/devio.h
+time.o:	/usr/include/minix/dmap.h
+time.o:	/usr/include/minix/ipc.h
+time.o:	/usr/include/minix/sys_config.h
+time.o:	/usr/include/minix/syslib.h
+time.o:	/usr/include/minix/sysutil.h
+time.o:	/usr/include/minix/type.h
+time.o:	/usr/include/string.h
+time.o:	/usr/include/sys/dir.h
+time.o:	/usr/include/sys/select.h
+time.o:	/usr/include/sys/time.h
+time.o:	/usr/include/sys/types.h
+time.o:	/usr/include/timers.h
+time.o:	const.h
+time.o:	file.h
+time.o:	fproc.h
+time.o:	fs.h
+time.o:	glo.h
+time.o:	inode.h
+time.o:	param.h
+time.o:	proto.h
+time.o:	time.c
+time.o:	type.h
+
+timers.o:	/usr/include/ansi.h
+timers.o:	/usr/include/errno.h
+timers.o:	/usr/include/limits.h
+timers.o:	/usr/include/minix/com.h
+timers.o:	/usr/include/minix/config.h
+timers.o:	/usr/include/minix/const.h
+timers.o:	/usr/include/minix/devio.h
+timers.o:	/usr/include/minix/dmap.h
+timers.o:	/usr/include/minix/ipc.h
+timers.o:	/usr/include/minix/sys_config.h
+timers.o:	/usr/include/minix/syslib.h
+timers.o:	/usr/include/minix/sysutil.h
+timers.o:	/usr/include/minix/type.h
+timers.o:	/usr/include/sys/dir.h
+timers.o:	/usr/include/sys/types.h
+timers.o:	/usr/include/timers.h
+timers.o:	const.h
+timers.o:	fs.h
+timers.o:	glo.h
+timers.o:	proto.h
+timers.o:	timers.c
+timers.o:	type.h
+
+utility.o:	/usr/include/ansi.h
+utility.o:	/usr/include/dirent.h
+utility.o:	/usr/include/errno.h
+utility.o:	/usr/include/limits.h
+utility.o:	/usr/include/minix/com.h
+utility.o:	/usr/include/minix/config.h
+utility.o:	/usr/include/minix/const.h
+utility.o:	/usr/include/minix/devio.h
+utility.o:	/usr/include/minix/dmap.h
+utility.o:	/usr/include/minix/endpoint.h
+utility.o:	/usr/include/minix/ipc.h
+utility.o:	/usr/include/minix/sys_config.h
+utility.o:	/usr/include/minix/syslib.h
+utility.o:	/usr/include/minix/sysutil.h
+utility.o:	/usr/include/minix/type.h
+utility.o:	/usr/include/string.h
+utility.o:	/usr/include/sys/dir.h
+utility.o:	/usr/include/sys/select.h
+utility.o:	/usr/include/sys/time.h
+utility.o:	/usr/include/sys/types.h
+utility.o:	/usr/include/timers.h
+utility.o:	/usr/include/unistd.h
+utility.o:	buf.h
+utility.o:	const.h
+utility.o:	file.h
+utility.o:	fproc.h
+utility.o:	fs.h
+utility.o:	glo.h
+utility.o:	inode.h
+utility.o:	param.h
+utility.o:	proto.h
+utility.o:	type.h
+utility.o:	utility.c
+
+write.o:	/usr/include/ansi.h
+write.o:	/usr/include/dirent.h
+write.o:	/usr/include/errno.h
+write.o:	/usr/include/limits.h
+write.o:	/usr/include/minix/config.h
+write.o:	/usr/include/minix/const.h
+write.o:	/usr/include/minix/devio.h
+write.o:	/usr/include/minix/dmap.h
+write.o:	/usr/include/minix/ipc.h
+write.o:	/usr/include/minix/sys_config.h
+write.o:	/usr/include/minix/syslib.h
+write.o:	/usr/include/minix/sysutil.h
+write.o:	/usr/include/minix/type.h
+write.o:	/usr/include/string.h
+write.o:	/usr/include/sys/dir.h
+write.o:	/usr/include/sys/select.h
+write.o:	/usr/include/sys/time.h
+write.o:	/usr/include/sys/types.h
+write.o:	/usr/include/timers.h
+write.o:	buf.h
+write.o:	const.h
+write.o:	file.h
+write.o:	fproc.h
+write.o:	fs.h
+write.o:	glo.h
+write.o:	inode.h
+write.o:	proto.h
+write.o:	super.h
+write.o:	type.h
+write.o:	write.c
Index: /trunk/minix/servers/fs/Makefile
===================================================================
--- /trunk/minix/servers/fs/Makefile	(revision 9)
+++ /trunk/minix/servers/fs/Makefile	(revision 9)
@@ -0,0 +1,35 @@
+# Makefile for File System (FS)
+SERVER = fs
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+h = $i/minix
+
+# programs, flags, etc.
+CC =	exec cc
+CFLAGS = -I$i $(EXTRA_OPTS)
+LDFLAGS = -i
+LIBS = -lsys -lsysutil -ltimers
+
+OBJ =	main.o open.o read.o write.o pipe.o dmap.o \
+	device.o path.o mount.o link.o super.o inode.o \
+	cache.o cache2.o filedes.o stadir.o protect.o time.o \
+	lock.o misc.o utility.o select.o timers.o table.o
+
+# build local binary 
+install all build:	$(SERVER)
+$(SERVER):	$(OBJ)
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+	install -S 512w $@
+
+# clean up local files
+clean:
+	rm -f $(SERVER) *.o *.bak 
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
Index: /trunk/minix/servers/fs/buf.h
===================================================================
--- /trunk/minix/servers/fs/buf.h	(revision 9)
+++ /trunk/minix/servers/fs/buf.h	(revision 9)
@@ -0,0 +1,75 @@
+/* Buffer (block) cache.  To acquire a block, a routine calls get_block(),
+ * telling which block it wants.  The block is then regarded as "in use"
+ * and has its 'b_count' field incremented.  All the blocks that are not
+ * in use are chained together in an LRU list, with 'front' pointing
+ * to the least recently used block, and 'rear' to the most recently used
+ * block.  A reverse chain, using the field b_prev is also maintained.
+ * Usage for LRU is measured by the time the put_block() is done.  The second
+ * parameter to put_block() can violate the LRU order and put a block on the
+ * front of the list, if it will probably not be needed soon.  If a block
+ * is modified, the modifying routine must set b_dirt to DIRTY, so the block
+ * will eventually be rewritten to the disk.
+ */
+
+#include <sys/dir.h>			/* need struct direct */
+#include <dirent.h>
+
+EXTERN struct buf {
+  /* Data portion of the buffer. */
+  union {
+    char b__data[_MAX_BLOCK_SIZE];		     /* ordinary user data */
+/* directory block */
+    struct direct b__dir[NR_DIR_ENTRIES(_MAX_BLOCK_SIZE)];    
+/* V1 indirect block */
+    zone1_t b__v1_ind[V1_INDIRECTS];	     
+/* V2 indirect block */
+    zone_t  b__v2_ind[V2_INDIRECTS(_MAX_BLOCK_SIZE)];	     
+/* V1 inode block */
+    d1_inode b__v1_ino[V1_INODES_PER_BLOCK]; 
+/* V2 inode block */
+    d2_inode b__v2_ino[V2_INODES_PER_BLOCK(_MAX_BLOCK_SIZE)]; 
+/* bit map block */
+    bitchunk_t b__bitmap[FS_BITMAP_CHUNKS(_MAX_BLOCK_SIZE)];  
+  } b;
+
+  /* Header portion of the buffer. */
+  struct buf *b_next;		/* used to link all free bufs in a chain */
+  struct buf *b_prev;		/* used to link all free bufs the other way */
+  struct buf *b_hash;		/* used to link bufs on hash chains */
+  block_t b_blocknr;		/* block number of its (minor) device */
+  dev_t b_dev;			/* major | minor device where block resides */
+  char b_dirt;			/* CLEAN or DIRTY */
+  char b_count;			/* number of users of this buffer */
+} buf[NR_BUFS];
+
+/* A block is free if b_dev == NO_DEV. */
+
+#define NIL_BUF ((struct buf *) 0)	/* indicates absence of a buffer */
+
+/* These defs make it possible to use to bp->b_data instead of bp->b.b__data */
+#define b_data   b.b__data
+#define b_dir    b.b__dir
+#define b_v1_ind b.b__v1_ind
+#define b_v2_ind b.b__v2_ind
+#define b_v1_ino b.b__v1_ino
+#define b_v2_ino b.b__v2_ino
+#define b_bitmap b.b__bitmap
+
+EXTERN struct buf *buf_hash[NR_BUF_HASH];	/* the buffer hash table */
+
+EXTERN struct buf *front;	/* points to least recently used free block */
+EXTERN struct buf *rear;	/* points to most recently used free block */
+EXTERN int bufs_in_use;		/* # bufs currently in use (not on free list)*/
+
+/* When a block is released, the type of usage is passed to put_block(). */
+#define WRITE_IMMED   0100 /* block should be written to disk now */
+#define ONE_SHOT      0200 /* set if block not likely to be needed soon */
+
+#define INODE_BLOCK        0				 /* inode block */
+#define DIRECTORY_BLOCK    1				 /* directory block */
+#define INDIRECT_BLOCK     2				 /* pointer block */
+#define MAP_BLOCK          3				 /* bit map */
+#define FULL_DATA_BLOCK    5		 	 	 /* data, fully used */
+#define PARTIAL_DATA_BLOCK 6 				 /* data, partly used*/
+
+#define HASH_MASK (NR_BUF_HASH - 1)	/* mask for hashing block numbers */
Index: /trunk/minix/servers/fs/cache.c
===================================================================
--- /trunk/minix/servers/fs/cache.c	(revision 9)
+++ /trunk/minix/servers/fs/cache.c	(revision 9)
@@ -0,0 +1,444 @@
+/* The file system maintains a buffer cache to reduce the number of disk
+ * accesses needed.  Whenever a read or write to the disk is done, a check is
+ * first made to see if the block is in the cache.  This file manages the
+ * cache.
+ *
+ * The entry points into this file are:
+ *   get_block:	  request to fetch a block for reading or writing from cache
+ *   put_block:	  return a block previously requested with get_block
+ *   alloc_zone:  allocate a new zone (to increase the length of a file)
+ *   free_zone:	  release a zone (when a file is removed)
+ *   invalidate:  remove all the cache blocks on some device
+ *
+ * Private functions:
+ *   rw_block:    read or write a block from the disk itself
+ */
+
+#include "fs.h"
+#include <minix/com.h>
+#include "buf.h"
+#include "file.h"
+#include "fproc.h"
+#include "super.h"
+
+FORWARD _PROTOTYPE( void rm_lru, (struct buf *bp) );
+FORWARD _PROTOTYPE( int rw_block, (struct buf *, int) );
+
+/*===========================================================================*
+ *				get_block				     *
+ *===========================================================================*/
+PUBLIC struct buf *get_block(dev, block, only_search)
+register dev_t dev;		/* on which device is the block? */
+register block_t block;		/* which block is wanted? */
+int only_search;		/* if NO_READ, don't read, else act normal */
+{
+/* Check to see if the requested block is in the block cache.  If so, return
+ * a pointer to it.  If not, evict some other block and fetch it (unless
+ * 'only_search' is 1).  All the blocks in the cache that are not in use
+ * are linked together in a chain, with 'front' pointing to the least recently
+ * used block and 'rear' to the most recently used block.  If 'only_search' is
+ * 1, the block being requested will be overwritten in its entirety, so it is
+ * only necessary to see if it is in the cache; if it is not, any free buffer
+ * will do.  It is not necessary to actually read the block in from disk.
+ * If 'only_search' is PREFETCH, the block need not be read from the disk,
+ * and the device is not to be marked on the block, so callers can tell if
+ * the block returned is valid.
+ * In addition to the LRU chain, there is also a hash chain to link together
+ * blocks whose block numbers end with the same bit strings, for fast lookup.
+ */
+
+  int b;
+  register struct buf *bp, *prev_ptr;
+
+  /* Search the hash chain for (dev, block). Do_read() can use 
+   * get_block(NO_DEV ...) to get an unnamed block to fill with zeros when
+   * someone wants to read from a hole in a file, in which case this search
+   * is skipped
+   */
+  if (dev != NO_DEV) {
+	b = (int) block & HASH_MASK;
+	bp = buf_hash[b];
+	while (bp != NIL_BUF) {
+		if (bp->b_blocknr == block && bp->b_dev == dev) {
+			/* Block needed has been found. */
+			if (bp->b_count == 0) rm_lru(bp);
+			bp->b_count++;	/* record that block is in use */
+
+			return(bp);
+		} else {
+			/* This block is not the one sought. */
+			bp = bp->b_hash; /* move to next block on hash chain */
+		}
+	}
+  }
+
+  /* Desired block is not on available chain.  Take oldest block ('front'). */
+  if ((bp = front) == NIL_BUF) panic(__FILE__,"all buffers in use", NR_BUFS);
+  rm_lru(bp);
+
+  /* Remove the block that was just taken from its hash chain. */
+  b = (int) bp->b_blocknr & HASH_MASK;
+  prev_ptr = buf_hash[b];
+  if (prev_ptr == bp) {
+	buf_hash[b] = bp->b_hash;
+  } else {
+	/* The block just taken is not on the front of its hash chain. */
+	while (prev_ptr->b_hash != NIL_BUF)
+		if (prev_ptr->b_hash == bp) {
+			prev_ptr->b_hash = bp->b_hash;	/* found it */
+			break;
+		} else {
+			prev_ptr = prev_ptr->b_hash;	/* keep looking */
+		}
+  }
+
+  /* If the block taken is dirty, make it clean by writing it to the disk.
+   * Avoid hysteresis by flushing all other dirty blocks for the same device.
+   */
+  if (bp->b_dev != NO_DEV) {
+	if (bp->b_dirt == DIRTY) flushall(bp->b_dev);
+#if ENABLE_CACHE2
+	put_block2(bp);
+#endif
+  }
+
+  /* Fill in block's parameters and add it to the hash chain where it goes. */
+  bp->b_dev = dev;		/* fill in device number */
+  bp->b_blocknr = block;	/* fill in block number */
+  bp->b_count++;		/* record that block is being used */
+  b = (int) bp->b_blocknr & HASH_MASK;
+  bp->b_hash = buf_hash[b];
+  buf_hash[b] = bp;		/* add to hash list */
+
+  /* Go get the requested block unless searching or prefetching. */
+  if (dev != NO_DEV) {
+#if ENABLE_CACHE2
+	if (get_block2(bp, only_search)) /* in 2nd level cache */;
+	else
+#endif
+	if (only_search == PREFETCH) bp->b_dev = NO_DEV;
+	else
+	if (only_search == NORMAL) {
+		rw_block(bp, READING);
+	}
+  }
+  return(bp);			/* return the newly acquired block */
+}
+
+/*===========================================================================*
+ *				put_block				     *
+ *===========================================================================*/
+PUBLIC void put_block(bp, block_type)
+register struct buf *bp;	/* pointer to the buffer to be released */
+int block_type;			/* INODE_BLOCK, DIRECTORY_BLOCK, or whatever */
+{
+/* Return a block to the list of available blocks.   Depending on 'block_type'
+ * it may be put on the front or rear of the LRU chain.  Blocks that are
+ * expected to be needed again shortly (e.g., partially full data blocks)
+ * go on the rear; blocks that are unlikely to be needed again shortly
+ * (e.g., full data blocks) go on the front.  Blocks whose loss can hurt
+ * the integrity of the file system (e.g., inode blocks) are written to
+ * disk immediately if they are dirty.
+ */
+  if (bp == NIL_BUF) return;	/* it is easier to check here than in caller */
+
+  bp->b_count--;		/* there is one use fewer now */
+  if (bp->b_count != 0) return;	/* block is still in use */
+
+  bufs_in_use--;		/* one fewer block buffers in use */
+
+  /* Put this block back on the LRU chain.  If the ONE_SHOT bit is set in
+   * 'block_type', the block is not likely to be needed again shortly, so put
+   * it on the front of the LRU chain where it will be the first one to be
+   * taken when a free buffer is needed later.
+   */
+  if (bp->b_dev == DEV_RAM || (block_type & ONE_SHOT)) {
+	/* Block probably won't be needed quickly. Put it on front of chain.
+  	 * It will be the next block to be evicted from the cache.
+  	 */
+	bp->b_prev = NIL_BUF;
+	bp->b_next = front;
+	if (front == NIL_BUF)
+		rear = bp;	/* LRU chain was empty */
+	else
+		front->b_prev = bp;
+	front = bp;
+  } else {
+	/* Block probably will be needed quickly.  Put it on rear of chain.
+  	 * It will not be evicted from the cache for a long time.
+  	 */
+	bp->b_prev = rear;
+	bp->b_next = NIL_BUF;
+	if (rear == NIL_BUF)
+		front = bp;
+	else
+		rear->b_next = bp;
+	rear = bp;
+  }
+
+  /* Some blocks are so important (e.g., inodes, indirect blocks) that they
+   * should be written to the disk immediately to avoid messing up the file
+   * system in the event of a crash.
+   */
+  if ((block_type & WRITE_IMMED) && bp->b_dirt==DIRTY && bp->b_dev != NO_DEV) {
+		rw_block(bp, WRITING);
+  } 
+}
+
+/*===========================================================================*
+ *				alloc_zone				     *
+ *===========================================================================*/
+PUBLIC zone_t alloc_zone(dev, z)
+dev_t dev;			/* device where zone wanted */
+zone_t z;			/* try to allocate new zone near this one */
+{
+/* Allocate a new zone on the indicated device and return its number. */
+
+  int major, minor;
+  bit_t b, bit;
+  struct super_block *sp;
+
+  /* Note that the routine alloc_bit() returns 1 for the lowest possible
+   * zone, which corresponds to sp->s_firstdatazone.  To convert a value
+   * between the bit number, 'b', used by alloc_bit() and the zone number, 'z',
+   * stored in the inode, use the formula:
+   *     z = b + sp->s_firstdatazone - 1
+   * Alloc_bit() never returns 0, since this is used for NO_BIT (failure).
+   */
+  sp = get_super(dev);
+
+  /* If z is 0, skip initial part of the map known to be fully in use. */
+  if (z == sp->s_firstdatazone) {
+	bit = sp->s_zsearch;
+  } else {
+	bit = (bit_t) z - (sp->s_firstdatazone - 1);
+  }
+  b = alloc_bit(sp, ZMAP, bit);
+  if (b == NO_BIT) {
+	err_code = ENOSPC;
+	major = (int) (sp->s_dev >> MAJOR) & BYTE;
+	minor = (int) (sp->s_dev >> MINOR) & BYTE;
+	printf("No space on %sdevice %d/%d\n",
+		sp->s_dev == root_dev ? "root " : "", major, minor);
+	return(NO_ZONE);
+  }
+  if (z == sp->s_firstdatazone) sp->s_zsearch = b;	/* for next time */
+  return(sp->s_firstdatazone - 1 + (zone_t) b);
+}
+
+/*===========================================================================*
+ *				free_zone				     *
+ *===========================================================================*/
+PUBLIC void free_zone(dev, numb)
+dev_t dev;				/* device where zone located */
+zone_t numb;				/* zone to be returned */
+{
+/* Return a zone. */
+
+  register struct super_block *sp;
+  bit_t bit;
+
+  /* Locate the appropriate super_block and return bit. */
+  sp = get_super(dev);
+  if (numb < sp->s_firstdatazone || numb >= sp->s_zones) return;
+  bit = (bit_t) (numb - (sp->s_firstdatazone - 1));
+  free_bit(sp, ZMAP, bit);
+  if (bit < sp->s_zsearch) sp->s_zsearch = bit;
+}
+
+/*===========================================================================*
+ *				rw_block				     *
+ *===========================================================================*/
+PRIVATE int rw_block(bp, rw_flag)
+register struct buf *bp;	/* buffer pointer */
+int rw_flag;			/* READING or WRITING */
+{
+/* Read or write a disk block. This is the only routine in which actual disk
+ * I/O is invoked. If an error occurs, a message is printed here, but the error
+ * is not reported to the caller.  If the error occurred while purging a block
+ * from the cache, it is not clear what the caller could do about it anyway.
+ */
+
+  int r, op;
+  off_t pos;
+  dev_t dev;
+  int block_size;
+
+  block_size = get_block_size(bp->b_dev);
+
+  if ( (dev = bp->b_dev) != NO_DEV) {
+	pos = (off_t) bp->b_blocknr * block_size;
+	op = (rw_flag == READING ? DEV_READ : DEV_WRITE);
+	r = dev_io(op, dev, FS_PROC_NR, bp->b_data, pos, block_size, 0);
+	if (r != block_size) {
+	    if (r >= 0) r = END_OF_FILE;
+	    if (r != END_OF_FILE)
+	      printf("Unrecoverable disk error on device %d/%d, block %ld\n",
+			(dev>>MAJOR)&BYTE, (dev>>MINOR)&BYTE, bp->b_blocknr);
+		bp->b_dev = NO_DEV;	/* invalidate block */
+
+		/* Report read errors to interested parties. */
+		if (rw_flag == READING) rdwt_err = r;
+	}
+  }
+
+  bp->b_dirt = CLEAN;
+
+  return OK;
+}
+
+/*===========================================================================*
+ *				invalidate				     *
+ *===========================================================================*/
+PUBLIC void invalidate(device)
+dev_t device;			/* device whose blocks are to be purged */
+{
+/* Remove all the blocks belonging to some device from the cache. */
+
+  register struct buf *bp;
+
+  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++)
+	if (bp->b_dev == device) bp->b_dev = NO_DEV;
+
+#if ENABLE_CACHE2
+  invalidate2(device);
+#endif
+}
+
+/*===========================================================================*
+ *				flushall				     *
+ *===========================================================================*/
+PUBLIC void flushall(dev)
+dev_t dev;			/* device to flush */
+{
+/* Flush all dirty blocks for one device. */
+
+  register struct buf *bp;
+  static struct buf *dirty[NR_BUFS];	/* static so it isn't on stack */
+  int ndirty;
+
+  for (bp = &buf[0], ndirty = 0; bp < &buf[NR_BUFS]; bp++)
+	if (bp->b_dirt == DIRTY && bp->b_dev == dev) dirty[ndirty++] = bp;
+  rw_scattered(dev, dirty, ndirty, WRITING);
+}
+
+/*===========================================================================*
+ *				rw_scattered				     *
+ *===========================================================================*/
+PUBLIC void rw_scattered(dev, bufq, bufqsize, rw_flag)
+dev_t dev;			/* major-minor device number */
+struct buf **bufq;		/* pointer to array of buffers */
+int bufqsize;			/* number of buffers */
+int rw_flag;			/* READING or WRITING */
+{
+/* Read or write scattered data from a device. */
+
+  register struct buf *bp;
+  int gap;
+  register int i;
+  register iovec_t *iop;
+  static iovec_t iovec[NR_IOREQS];  /* static so it isn't on stack */
+  int j, r;
+  int block_size;
+
+  block_size = get_block_size(dev);
+
+  /* (Shell) sort buffers on b_blocknr. */
+  gap = 1;
+  do
+	gap = 3 * gap + 1;
+  while (gap <= bufqsize);
+  while (gap != 1) {
+	gap /= 3;
+	for (j = gap; j < bufqsize; j++) {
+		for (i = j - gap;
+		     i >= 0 && bufq[i]->b_blocknr > bufq[i + gap]->b_blocknr;
+		     i -= gap) {
+			bp = bufq[i];
+			bufq[i] = bufq[i + gap];
+			bufq[i + gap] = bp;
+		}
+	}
+  }
+
+  /* Set up I/O vector and do I/O.  The result of dev_io is OK if everything
+   * went fine, otherwise the error code for the first failed transfer.
+   */  
+  while (bufqsize > 0) {
+	for (j = 0, iop = iovec; j < NR_IOREQS && j < bufqsize; j++, iop++) {
+		bp = bufq[j];
+		if (bp->b_blocknr != bufq[0]->b_blocknr + j) break;
+		iop->iov_addr = (vir_bytes) bp->b_data;
+		iop->iov_size = block_size;
+	}
+	r = dev_io(rw_flag == WRITING ? DEV_SCATTER : DEV_GATHER,
+		dev, FS_PROC_NR, iovec,
+		(off_t) bufq[0]->b_blocknr * block_size, j, 0);
+
+	/* Harvest the results.  Dev_io reports the first error it may have
+	 * encountered, but we only care if it's the first block that failed.
+	 */
+	for (i = 0, iop = iovec; i < j; i++, iop++) {
+		bp = bufq[i];
+		if (iop->iov_size != 0) {
+			/* Transfer failed. An error? Do we care? */
+			if (r != OK && i == 0) {
+				printf(
+				"fs: I/O error on device %d/%d, block %lu\n",
+					(dev>>MAJOR)&BYTE, (dev>>MINOR)&BYTE,
+					bp->b_blocknr);
+				bp->b_dev = NO_DEV;	/* invalidate block */
+			}
+			break;
+		}
+		if (rw_flag == READING) {
+			bp->b_dev = dev;	/* validate block */
+			put_block(bp, PARTIAL_DATA_BLOCK);
+		} else {
+			bp->b_dirt = CLEAN;
+		}
+	}
+	bufq += i;
+	bufqsize -= i;
+	if (rw_flag == READING) {
+		/* Don't bother reading more than the device is willing to
+		 * give at this time.  Don't forget to release those extras.
+		 */
+		while (bufqsize > 0) {
+			put_block(*bufq++, PARTIAL_DATA_BLOCK);
+			bufqsize--;
+		}
+	}
+	if (rw_flag == WRITING && i == 0) {
+		/* We're not making progress, this means we might keep
+		 * looping. Buffers remain dirty if un-written. Buffers are
+		 * lost if invalidate()d or LRU-removed while dirty. This
+		 * is better than keeping unwritable blocks around forever..
+		 */
+		break;
+	}
+  }
+}
+
+/*===========================================================================*
+ *				rm_lru					     *
+ *===========================================================================*/
+PRIVATE void rm_lru(bp)
+struct buf *bp;
+{
+/* Remove a block from its LRU chain. */
+  struct buf *next_ptr, *prev_ptr;
+
+  bufs_in_use++;
+  next_ptr = bp->b_next;	/* successor on LRU chain */
+  prev_ptr = bp->b_prev;	/* predecessor on LRU chain */
+  if (prev_ptr != NIL_BUF)
+	prev_ptr->b_next = next_ptr;
+  else
+	front = next_ptr;	/* this block was at front of chain */
+
+  if (next_ptr != NIL_BUF)
+	next_ptr->b_prev = prev_ptr;
+  else
+	rear = prev_ptr;	/* this block was at rear of chain */
+}
Index: /trunk/minix/servers/fs/cache2.c
===================================================================
--- /trunk/minix/servers/fs/cache2.c	(revision 9)
+++ /trunk/minix/servers/fs/cache2.c	(revision 9)
@@ -0,0 +1,126 @@
+/* Second level block cache to supplement the file system cache.  The block
+ * cache of a 16-bit Minix system is very small, too small to prevent trashing.
+ * A generic 32-bit system also doesn't have a very large cache to allow it
+ * to run on systems with little memory.  On a system with lots of memory one
+ * can use the RAM disk as a read-only second level cache.  Any blocks pushed
+ * out of the primary cache are cached on the RAM disk.  This code manages the
+ * second level cache.  The cache is a simple FIFO where old blocks are put
+ * into and drop out at the other end.  Must be searched backwards.
+ *
+ * The entry points into this file are:
+ *   init_cache2: initialize the second level cache
+ *   get_block2:  get a block from the 2nd level cache
+ *   put_block2:  store a block in the 2nd level cache
+ *   invalidate2: remove all the cache blocks on some device
+ */
+
+#include "fs.h"
+#include <minix/com.h>
+#include "buf.h"
+
+#if ENABLE_CACHE2
+
+#define MAX_BUF2	(256 * sizeof(char *))
+
+PRIVATE struct buf2 {	/* 2nd level cache per block administration */
+  block_t b2_blocknr;		/* block number */
+  dev_t b2_dev;			/* device number */
+  u16_t b2_count;		/* count of in-cache block groups */
+} buf2[MAX_BUF2];
+
+PRIVATE unsigned nr_buf2;		/* actual cache size */
+PRIVATE unsigned buf2_idx;		/* round-robin reuse index */
+
+#define hash2(block)	((unsigned) ((block) & (MAX_BUF2 - 1)))
+
+/*===========================================================================*
+ *				init_cache2				     *
+ *===========================================================================*/
+PUBLIC void init_cache2(size)
+unsigned long size;
+{
+/* Initialize the second level disk buffer cache of 'size' blocks. */
+
+  nr_buf2 = size > MAX_BUF2 ? MAX_BUF2 : (unsigned) size;
+}
+
+/*===========================================================================*
+ *				get_block2				     *
+ *===========================================================================*/
+PUBLIC int get_block2(bp, only_search)
+struct buf *bp;			/* buffer to get from the 2nd level cache */
+int only_search;		/* if NO_READ, do nothing, else act normal */
+{
+/* Fill a buffer from the 2nd level cache.  Return true iff block acquired. */
+  unsigned b;
+  struct buf2 *bp2;
+
+  /* If the block wanted is in the RAM disk then our game is over. */
+  if (bp->b_dev == DEV_RAM) nr_buf2 = 0;
+
+  /* Cache enabled?  NO_READ?  Any blocks with the same hash key? */
+  if (nr_buf2 == 0 || only_search == NO_READ
+  			|| buf2[hash2(bp->b_blocknr)].b2_count == 0) return(0);
+
+  /* Search backwards (there may be older versions). */
+  b = buf2_idx;
+  for (;;) {
+	if (b == 0) b = nr_buf2;
+	bp2 = &buf2[--b];
+	if (bp2->b2_blocknr == bp->b_blocknr && bp2->b2_dev == bp->b_dev) break;
+	if (b == buf2_idx) return(0);
+  }
+
+  /* Block is in the cache, get it. */
+  if (dev_io(DEV_READ, DEV_RAM, FS_PROC_NR, bp->b_data,
+			(off_t) b * BLOCK_SIZE, BLOCK_SIZE, 0) == BLOCK_SIZE) {
+	return(1);
+  }
+  return(0);
+}
+
+/*===========================================================================*
+ *				put_block2				     *
+ *===========================================================================*/
+PUBLIC void put_block2(bp)
+struct buf *bp;			/* buffer to store in the 2nd level cache */
+{
+/* Store a buffer into the 2nd level cache. */
+  unsigned b;
+  struct buf2 *bp2;
+
+  if (nr_buf2 == 0) return;	/* no 2nd level cache */
+
+  b = buf2_idx++;
+  if (buf2_idx == nr_buf2) buf2_idx = 0;
+
+  bp2 = &buf2[b];
+
+  if (dev_io(DEV_WRITE, DEV_RAM, FS_PROC_NR, bp->b_data,
+			(off_t) b * BLOCK_SIZE, BLOCK_SIZE, 0) == BLOCK_SIZE) {
+	if (bp2->b2_dev != NO_DEV) buf2[hash2(bp2->b2_blocknr)].b2_count--;
+	bp2->b2_dev = bp->b_dev;
+	bp2->b2_blocknr = bp->b_blocknr;
+	buf2[hash2(bp2->b2_blocknr)].b2_count++;
+  }
+}
+
+/*===========================================================================*
+ *				invalidate2				     *
+ *===========================================================================*/
+PUBLIC void invalidate2(device)
+dev_t device;
+{
+/* Invalidate all blocks from a given device in the 2nd level cache. */
+  unsigned b;
+  struct buf2 *bp2;
+
+  for (b = 0; b < nr_buf2; b++) {
+	bp2 = &buf2[b];
+	if (bp2->b2_dev == device) {
+		bp2->b2_dev = NO_DEV;
+		buf2[hash2(bp2->b2_blocknr)].b2_count--;
+	}
+  }
+}
+#endif /* ENABLE_CACHE2 */
Index: /trunk/minix/servers/fs/const.h
===================================================================
--- /trunk/minix/servers/fs/const.h	(revision 9)
+++ /trunk/minix/servers/fs/const.h	(revision 9)
@@ -0,0 +1,105 @@
+/* Tables sizes */
+#define V1_NR_DZONES       7	/* # direct zone numbers in a V1 inode */
+#define V1_NR_TZONES       9	/* total # zone numbers in a V1 inode */
+#define V2_NR_DZONES       7	/* # direct zone numbers in a V2 inode */
+#define V2_NR_TZONES      10	/* total # zone numbers in a V2 inode */
+
+#define NR_FILPS         256	/* # slots in filp table */
+#define NR_INODES        256	/* # slots in "in core" inode table */
+#define NR_SUPERS         12	/* # slots in super block table */
+#define NR_LOCKS           8	/* # slots in the file locking table */
+
+/* The type of sizeof may be (unsigned) long.  Use the following macro for
+ * taking the sizes of small objects so that there are no surprises like
+ * (small) long constants being passed to routines expecting an int.
+ */
+#define usizeof(t) ((unsigned) sizeof(t))
+
+/* File system types. */
+#define SUPER_MAGIC   0x137F	/* magic number contained in super-block */
+#define SUPER_REV     0x7F13	/* magic # when 68000 disk read on PC or vv */
+#define SUPER_V2      0x2468	/* magic # for V2 file systems */
+#define SUPER_V2_REV  0x6824	/* V2 magic written on PC, read on 68K or vv */
+#define SUPER_V3      0x4d5a	/* magic # for V3 file systems */
+
+#define V1		   1	/* version number of V1 file systems */ 
+#define V2		   2	/* version number of V2 file systems */ 
+#define V3		   3	/* version number of V3 file systems */ 
+
+/* Miscellaneous constants */
+#define SU_UID 	 ((uid_t) 0)	/* super_user's uid_t */
+#define SERVERS_UID ((uid_t) 11) /* who may do FSSIGNON */
+#define SYS_UID  ((uid_t) 0)	/* uid_t for processes MM and INIT */
+#define SYS_GID  ((gid_t) 0)	/* gid_t for processes MM and INIT */
+#define NORMAL	           0	/* forces get_block to do disk read */
+#define NO_READ            1	/* prevents get_block from doing disk read */
+#define PREFETCH           2	/* tells get_block not to read or mark dev */
+
+#define XPIPE   (-NR_TASKS-1)	/* used in fp_task when susp'd on pipe */
+#define XLOCK   (-NR_TASKS-2)	/* used in fp_task when susp'd on lock */
+#define XPOPEN  (-NR_TASKS-3)	/* used in fp_task when susp'd on pipe open */
+#define XSELECT (-NR_TASKS-4)	/* used in fp_task when susp'd on select */
+
+#define NO_BIT   ((bit_t) 0)	/* returned by alloc_bit() to signal failure */
+
+#define DUP_MASK        0100	/* mask to distinguish dup2 from dup */
+
+#define LOOK_UP            0 /* tells search_dir to lookup string */
+#define ENTER              1 /* tells search_dir to make dir entry */
+#define DELETE             2 /* tells search_dir to delete entry */
+#define IS_EMPTY           3 /* tells search_dir to ret. OK or ENOTEMPTY */  
+
+/* write_map() args */
+#define WMAP_FREE	(1 << 0)
+
+#define PATH_TRANSPARENT 000   /* parse_path stops at final object */
+#define PATH_PENULTIMATE 001   /* parse_path stops at last but one name */
+#define PATH_OPAQUE      002   /* parse_path stops at final name */
+#define PATH_NONSYMBOLIC 004   /* parse_path scans final name if symbolic */
+#define PATH_STRIPDOT    010   /* parse_path strips /. from path */
+#define EAT_PATH         PATH_TRANSPARENT
+#define EAT_PATH_OPAQUE  PATH_OPAQUE 
+#define LAST_DIR         PATH_PENULTIMATE
+#define LAST_DIR_NOTDOT  PATH_PENULTIMATE | PATH_STRIPDOT
+#define LAST_DIR_EATSYM  PATH_NONSYMBOLIC
+#define SYMLOOP		16
+
+#define CLEAN              0	/* disk and memory copies identical */
+#define DIRTY              1	/* disk and memory copies differ */
+#define ATIME            002	/* set if atime field needs updating */
+#define CTIME            004	/* set if ctime field needs updating */
+#define MTIME            010	/* set if mtime field needs updating */
+
+#define BYTE_SWAP          0	/* tells conv2/conv4 to swap bytes */
+
+#define END_OF_FILE   (-104)	/* eof detected */
+
+#define ROOT_INODE         1		/* inode number for root directory */
+#define BOOT_BLOCK  ((block_t) 0)	/* block number of boot block */
+#define SUPER_BLOCK_BYTES (1024)	/* bytes offset */
+#define START_BLOCK 	2		/* first block of FS (not counting SB) */
+
+#define DIR_ENTRY_SIZE       usizeof (struct direct)  /* # bytes/dir entry   */
+#define NR_DIR_ENTRIES(b)   ((b)/DIR_ENTRY_SIZE)  /* # dir entries/blk   */
+#define SUPER_SIZE      usizeof (struct super_block)  /* super_block size    */
+#define PIPE_SIZE(b)          (V1_NR_DZONES*(b))  /* pipe size in bytes  */
+
+#define FS_BITMAP_CHUNKS(b) ((b)/usizeof (bitchunk_t))/* # map chunks/blk   */
+#define FS_BITCHUNK_BITS		(usizeof(bitchunk_t) * CHAR_BIT)
+#define FS_BITS_PER_BLOCK(b)	(FS_BITMAP_CHUNKS(b) * FS_BITCHUNK_BITS)
+
+/* Derived sizes pertaining to the V1 file system. */
+#define V1_ZONE_NUM_SIZE           usizeof (zone1_t)  /* # bytes in V1 zone  */
+#define V1_INODE_SIZE             usizeof (d1_inode)  /* bytes in V1 dsk ino */
+
+/* # zones/indir block */
+#define V1_INDIRECTS (_STATIC_BLOCK_SIZE/V1_ZONE_NUM_SIZE)  
+
+/* # V1 dsk inodes/blk */
+#define V1_INODES_PER_BLOCK (_STATIC_BLOCK_SIZE/V1_INODE_SIZE)
+
+/* Derived sizes pertaining to the V2 file system. */
+#define V2_ZONE_NUM_SIZE            usizeof (zone_t)  /* # bytes in V2 zone  */
+#define V2_INODE_SIZE             usizeof (d2_inode)  /* bytes in V2 dsk ino */
+#define V2_INDIRECTS(b)   ((b)/V2_ZONE_NUM_SIZE)  /* # zones/indir block */
+#define V2_INODES_PER_BLOCK(b) ((b)/V2_INODE_SIZE)/* # V2 dsk inodes/blk */
Index: /trunk/minix/servers/fs/device.c
===================================================================
--- /trunk/minix/servers/fs/device.c	(revision 9)
+++ /trunk/minix/servers/fs/device.c	(revision 9)
@@ -0,0 +1,630 @@
+/* When a needed block is not in the cache, it must be fetched from the disk.
+ * Special character files also require I/O.  The routines for these are here.
+ *
+ * The entry points in this file are:
+ *   dev_open:   FS opens a device
+ *   dev_close:  FS closes a device
+ *   dev_io:	 FS does a read or write on a device
+ *   dev_status: FS processes callback request alert
+ *   gen_opcl:   generic call to a task to perform an open/close
+ *   gen_io:     generic call to a task to perform an I/O operation
+ *   no_dev:     open/close processing for devices that don't exist
+ *   no_dev_io:  i/o processing for devices that don't exist
+ *   tty_opcl:   perform tty-specific processing for open/close
+ *   ctty_opcl:  perform controlling-tty-specific processing for open/close
+ *   ctty_io:    perform controlling-tty-specific processing for I/O
+ *   do_ioctl:	 perform the IOCTL system call
+ *   do_setsid:	 perform the SETSID system call (FS side)
+ */
+
+#include "fs.h"
+#include <fcntl.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/endpoint.h>
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "param.h"
+#include "super.h"
+
+#define ELEMENTS(a) (sizeof(a)/sizeof((a)[0]))
+
+extern int dmap_size;
+PRIVATE int dummyproc;
+
+/*===========================================================================*
+ *				dev_open				     *
+ *===========================================================================*/
+PUBLIC int dev_open(dev, proc, flags)
+dev_t dev;			/* device to open */
+int proc;			/* process to open for */
+int flags;			/* mode bits and flags */
+{
+  int major, r;
+  struct dmap *dp;
+
+  /* Determine the major device number call the device class specific
+   * open/close routine.  (This is the only routine that must check the
+   * device number for being in range.  All others can trust this check.)
+   */
+  major = (dev >> MAJOR) & BYTE;
+  if (major >= NR_DEVICES) major = 0;
+  dp = &dmap[major];
+  if (dp->dmap_driver == NONE) 
+	return ENXIO;
+  r = (*dp->dmap_opcl)(DEV_OPEN, dev, proc, flags);
+  if (r == SUSPEND) panic(__FILE__,"suspend on open from", dp->dmap_driver);
+  return(r);
+}
+
+/*===========================================================================*
+ *				dev_close				     *
+ *===========================================================================*/
+PUBLIC void dev_close(dev)
+dev_t dev;			/* device to close */
+{
+  /* See if driver is roughly valid. */
+  if (dmap[(dev >> MAJOR)].dmap_driver == NONE) {
+	return;
+  }
+  (void) (*dmap[(dev >> MAJOR) & BYTE].dmap_opcl)(DEV_CLOSE, dev, 0, 0);
+}
+
+/*===========================================================================*
+ *				dev_status					*
+ *===========================================================================*/
+PUBLIC void dev_status(message *m)
+{
+	message st;
+	int d, get_more = 1;
+
+	for(d = 0; d < NR_DEVICES; d++)
+		if (dmap[d].dmap_driver != NONE &&
+		    dmap[d].dmap_driver == m->m_source)
+			break;
+
+	if (d >= NR_DEVICES)
+		return;
+
+	do {
+		int r;
+		st.m_type = DEV_STATUS;
+		if ((r=sendrec(m->m_source, &st)) != OK) {
+			printf("DEV_STATUS failed to %d: %d\n", m->m_source, r);
+			if (r == EDEADSRCDST) return;
+			if (r == EDSTDIED) return;
+			if (r == ESRCDIED) return;
+			panic(__FILE__,"couldn't sendrec for DEV_STATUS", r);
+		}
+
+		switch(st.m_type) {
+			case DEV_REVIVE:
+				revive(st.REP_ENDPT, st.REP_STATUS);
+				break;
+			case DEV_IO_READY:
+				select_notified(d, st.DEV_MINOR, st.DEV_SEL_OPS);
+				break;
+			default:
+				printf("FS: unrecognized reply %d to DEV_STATUS\n", st.m_type);
+				/* Fall through. */
+			case DEV_NO_STATUS:
+				get_more = 0;
+				break;
+		}
+	} while(get_more);
+
+	return;
+}
+
+/*===========================================================================*
+ *				dev_io					     *
+ *===========================================================================*/
+PUBLIC int dev_io(op, dev, proc_e, buf, pos, bytes, flags)
+int op;				/* DEV_READ, DEV_WRITE, DEV_IOCTL, etc. */
+dev_t dev;			/* major-minor device number */
+int proc_e;			/* in whose address space is buf? */
+void *buf;			/* virtual address of the buffer */
+off_t pos;			/* byte position */
+int bytes;			/* how many bytes to transfer */
+int flags;			/* special flags, like O_NONBLOCK */
+{
+/* Read or write from a device.  The parameter 'dev' tells which one. */
+  struct dmap *dp;
+  message dev_mess;
+
+  /* Determine task dmap. */
+  dp = &dmap[(dev >> MAJOR) & BYTE];
+
+  /* See if driver is roughly valid. */
+  if (dp->dmap_driver == NONE) {
+	printf("FS: dev_io: no driver for dev %x\n", dev);
+	return ENXIO;
+  }
+
+  if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
+	printf("FS: dev_io: old driver for dev %x (%d)\n",
+		dev, dp->dmap_driver);
+	return ENXIO;
+  }
+
+  /* Set up the message passed to task. */
+  dev_mess.m_type   = op;
+  dev_mess.DEVICE   = (dev >> MINOR) & BYTE;
+  dev_mess.POSITION = pos;
+  dev_mess.IO_ENDPT = proc_e;
+  dev_mess.ADDRESS  = buf;
+  dev_mess.COUNT    = bytes;
+  dev_mess.TTY_FLAGS = flags;
+
+  /* Call the task. */
+  (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
+
+  if(dp->dmap_driver == NONE) {
+  	/* Driver has vanished. */
+	return EIO;
+  }
+
+  /* Task has completed.  See if call completed. */
+  if (dev_mess.REP_STATUS == SUSPEND) {
+	if (flags & O_NONBLOCK) {
+		/* Not supposed to block. */
+		dev_mess.m_type = CANCEL;
+		dev_mess.IO_ENDPT = proc_e;
+		dev_mess.DEVICE = (dev >> MINOR) & BYTE;
+		(*dp->dmap_io)(dp->dmap_driver, &dev_mess);
+		if (dev_mess.REP_STATUS == EINTR) dev_mess.REP_STATUS = EAGAIN;
+	} else {
+		/* Suspend user. */
+		suspend(dp->dmap_driver);
+		return(SUSPEND);
+	}
+  }
+  return(dev_mess.REP_STATUS);
+}
+
+/*===========================================================================*
+ *				gen_opcl				     *
+ *===========================================================================*/
+PUBLIC int gen_opcl(op, dev, proc_e, flags)
+int op;				/* operation, DEV_OPEN or DEV_CLOSE */
+dev_t dev;			/* device to open or close */
+int proc_e;			/* process to open/close for */
+int flags;			/* mode bits and flags */
+{
+/* Called from the dmap struct in table.c on opens & closes of special files.*/
+  struct dmap *dp;
+  message dev_mess;
+
+  /* Determine task dmap. */
+  dp = &dmap[(dev >> MAJOR) & BYTE];
+
+  dev_mess.m_type   = op;
+  dev_mess.DEVICE   = (dev >> MINOR) & BYTE;
+  dev_mess.IO_ENDPT = proc_e;
+  dev_mess.COUNT    = flags;
+
+  if (dp->dmap_driver == NONE) {
+	printf("FS: gen_opcl: no driver for dev %x\n", dev);
+	return ENXIO;
+  }
+  if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
+	printf("FS: gen_opcl: old driver for dev %x (%d)\n",
+		dev, dp->dmap_driver);
+	return ENXIO;
+  }
+
+  /* Call the task. */
+  (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
+
+  return(dev_mess.REP_STATUS);
+}
+
+/*===========================================================================*
+ *				tty_opcl				     *
+ *===========================================================================*/
+PUBLIC int tty_opcl(op, dev, proc_e, flags)
+int op;				/* operation, DEV_OPEN or DEV_CLOSE */
+dev_t dev;			/* device to open or close */
+int proc_e;			/* process to open/close for */
+int flags;			/* mode bits and flags */
+{
+/* This procedure is called from the dmap struct on tty open/close. */
+ 
+  int r;
+  register struct fproc *rfp;
+
+  /* Add O_NOCTTY to the flags if this process is not a session leader, or
+   * if it already has a controlling tty, or if it is someone elses
+   * controlling tty.
+   */
+  if (!fp->fp_sesldr || fp->fp_tty != 0) {
+	flags |= O_NOCTTY;
+  } else {
+	for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
+		if(rfp->fp_pid == PID_FREE) continue;
+		if (rfp->fp_tty == dev) flags |= O_NOCTTY;
+	}
+  }
+
+  r = gen_opcl(op, dev, proc_e, flags);
+
+  /* Did this call make the tty the controlling tty? */
+  if (r == 1) {
+	fp->fp_tty = dev;
+	r = OK;
+  }
+  return(r);
+}
+
+/*===========================================================================*
+ *				ctty_opcl				     *
+ *===========================================================================*/
+PUBLIC int ctty_opcl(op, dev, proc_e, flags)
+int op;				/* operation, DEV_OPEN or DEV_CLOSE */
+dev_t dev;			/* device to open or close */
+int proc_e;			/* process to open/close for */
+int flags;			/* mode bits and flags */
+{
+/* This procedure is called from the dmap struct in table.c on opening/closing
+ * /dev/tty, the magic device that translates to the controlling tty.
+ */
+ 
+  return(fp->fp_tty == 0 ? ENXIO : OK);
+}
+
+/*===========================================================================*
+ *				do_setsid				     *
+ *===========================================================================*/
+PUBLIC int do_setsid()
+{
+/* Perform the FS side of the SETSID call, i.e. get rid of the controlling
+ * terminal of a process, and make the process a session leader.
+ */
+  register struct fproc *rfp;
+  int slot;
+
+  /* Only MM may do the SETSID call directly. */
+  if (who_e != PM_PROC_NR) return(ENOSYS);
+
+  /* Make the process a session leader with no controlling tty. */
+  okendpt(m_in.endpt1, &slot);
+  rfp = &fproc[slot];
+  rfp->fp_sesldr = TRUE;
+  rfp->fp_tty = 0;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_ioctl				     *
+ *===========================================================================*/
+PUBLIC int do_ioctl()
+{
+/* Perform the ioctl(ls_fd, request, argx) system call (uses m2 fmt). */
+
+  struct filp *f;
+  register struct inode *rip;
+  dev_t dev;
+
+  if ( (f = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code);
+  rip = f->filp_ino;		/* get inode pointer */
+  if ( (rip->i_mode & I_TYPE) != I_CHAR_SPECIAL
+	&& (rip->i_mode & I_TYPE) != I_BLOCK_SPECIAL) return(ENOTTY);
+  dev = (dev_t) rip->i_zone[0];
+
+#if ENABLE_BINCOMPAT
+  if ((m_in.TTY_REQUEST >> 8) == 't') {
+	/* Obsolete sgtty ioctl, message contains more than is sane. */
+	struct dmap *dp;
+	message dev_mess;
+
+	dp = &dmap[(dev >> MAJOR) & BYTE];
+
+	dev_mess = m;	/* Copy full message with all the weird bits. */
+	dev_mess.m_type   = DEV_IOCTL;
+	dev_mess.PROC_NR  = who_e;
+	dev_mess.TTY_LINE = (dev >> MINOR) & BYTE;	
+
+	/* Call the task. */
+
+  if (dp->dmap_driver == NONE) {
+	printf("FS: do_ioctl: no driver for dev %x\n", dev);
+	return ENXIO;
+  }
+
+  if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
+	printf("FS: do_ioctl: old driver for dev %x (%d)\n",
+		dev, dp->dmap_driver);
+	return ENXIO;
+  }
+
+	(*dp->dmap_io)(dp->dmap_driver, &dev_mess);
+
+	m_out.TTY_SPEK = dev_mess.TTY_SPEK;	/* erase and kill */
+	m_out.TTY_FLAGS = dev_mess.TTY_FLAGS;	/* flags */
+	return(dev_mess.REP_STATUS);
+  }
+#endif
+
+  return(dev_io(DEV_IOCTL, dev, who_e, m_in.ADDRESS, 0L, 
+  	m_in.REQUEST, f->filp_flags));
+}
+
+/*===========================================================================*
+ *				gen_io					     *
+ *===========================================================================*/
+PUBLIC int gen_io(task_nr, mess_ptr)
+int task_nr;			/* which task to call */
+message *mess_ptr;		/* pointer to message for task */
+{
+/* All file system I/O ultimately comes down to I/O on major/minor device
+ * pairs.  These lead to calls on the following routines via the dmap table.
+ */
+
+  int r, proc_e;
+
+  proc_e = mess_ptr->IO_ENDPT;
+
+#if DEAD_CODE
+  while ((r = sendrec(task_nr, mess_ptr)) == ELOCKED) {
+	/* sendrec() failed to avoid deadlock. The task 'task_nr' is
+	 * trying to send a REVIVE message for an earlier request.
+	 * Handle it and go try again.
+	 */
+	if ((r = receive(task_nr, &local_m)) != OK) {
+		break;
+	}
+
+	/* If we're trying to send a cancel message to a task which has just
+	 * sent a completion reply, ignore the reply and abort the cancel
+	 * request. The caller will do the revive for the process.
+	 */
+	if (mess_ptr->m_type == CANCEL && local_m.REP_ENDPT == proc_e) {
+		return OK;
+	}
+
+	/* Otherwise it should be a REVIVE. */
+	if (local_m.m_type != REVIVE) {
+		printf(
+		"fs: strange device reply from %d, type = %d, proc = %d (1)\n",
+			local_m.m_source,
+			local_m.m_type, local_m.REP_ENDPT);
+		continue;
+	}
+
+	revive(local_m.REP_ENDPT, local_m.REP_STATUS);
+  }
+#endif
+
+  /* The message received may be a reply to this call, or a REVIVE for some
+   * other process.
+   */
+  r = sendrec(task_nr, mess_ptr);
+  for(;;) {
+	if (r != OK) {
+		if (r == EDEADSRCDST || r == EDSTDIED || r == ESRCDIED) {
+			printf("fs: dead driver %d\n", task_nr);
+			dmap_unmap_by_endpt(task_nr);
+			return r;
+		}
+		if (r == ELOCKED) {
+			printf("fs: ELOCKED talking to %d\n", task_nr);
+			return r;
+		}
+		panic(__FILE__,"call_task: can't send/receive", r);
+	}
+
+  	/* Did the process we did the sendrec() for get a result? */
+  	if (mess_ptr->REP_ENDPT == proc_e) {
+  		break;
+	} else if (mess_ptr->m_type == REVIVE) {
+		/* Otherwise it should be a REVIVE. */
+		revive(mess_ptr->REP_ENDPT, mess_ptr->REP_STATUS);
+	} else {
+		printf(
+		"fs: strange device reply from %d, type = %d, proc = %d (2) ignored\n",
+			mess_ptr->m_source,
+			mess_ptr->m_type, mess_ptr->REP_ENDPT);
+	}
+	r = receive(task_nr, mess_ptr);
+  }
+
+  return OK;
+}
+
+/*===========================================================================*
+ *				ctty_io					     *
+ *===========================================================================*/
+PUBLIC int ctty_io(task_nr, mess_ptr)
+int task_nr;			/* not used - for compatibility with dmap_t */
+message *mess_ptr;		/* pointer to message for task */
+{
+/* This routine is only called for one device, namely /dev/tty.  Its job
+ * is to change the message to use the controlling terminal, instead of the
+ * major/minor pair for /dev/tty itself.
+ */
+
+  struct dmap *dp;
+
+  if (fp->fp_tty == 0) {
+	/* No controlling tty present anymore, return an I/O error. */
+	mess_ptr->REP_STATUS = EIO;
+  } else {
+	/* Substitute the controlling terminal device. */
+	dp = &dmap[(fp->fp_tty >> MAJOR) & BYTE];
+	mess_ptr->DEVICE = (fp->fp_tty >> MINOR) & BYTE;
+
+  if (dp->dmap_driver == NONE) {
+	printf("FS: ctty_io: no driver for dev\n");
+	return EIO;
+  }
+
+	if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
+		printf("FS: ctty_io: old driver %d\n",
+			dp->dmap_driver);
+		return EIO;
+	}
+
+	(*dp->dmap_io)(dp->dmap_driver, mess_ptr);
+  }
+  return OK;
+}
+
+/*===========================================================================*
+ *				no_dev					     *
+ *===========================================================================*/
+PUBLIC int no_dev(op, dev, proc, flags)
+int op;				/* operation, DEV_OPEN or DEV_CLOSE */
+dev_t dev;			/* device to open or close */
+int proc;			/* process to open/close for */
+int flags;			/* mode bits and flags */
+{
+/* Called when opening a nonexistent device. */
+  return(ENODEV);
+}
+
+/*===========================================================================*
+ *				no_dev_io				     *
+ *===========================================================================*/
+PUBLIC int no_dev_io(int proc, message *m)
+{
+/* Called when doing i/o on a nonexistent device. */
+  printf("FS: I/O on unmapped device number\n");
+  return EIO;
+}
+
+/*===========================================================================*
+ *				clone_opcl				     *
+ *===========================================================================*/
+PUBLIC int clone_opcl(op, dev, proc_e, flags)
+int op;				/* operation, DEV_OPEN or DEV_CLOSE */
+dev_t dev;			/* device to open or close */
+int proc_e;			/* process to open/close for */
+int flags;			/* mode bits and flags */
+{
+/* Some devices need special processing upon open.  Such a device is "cloned",
+ * i.e. on a succesful open it is replaced by a new device with a new unique
+ * minor device number.  This new device number identifies a new object (such
+ * as a new network connection) that has been allocated within a task.
+ */
+  struct dmap *dp;
+  int r, minor;
+  message dev_mess;
+
+  /* Determine task dmap. */
+  dp = &dmap[(dev >> MAJOR) & BYTE];
+  minor = (dev >> MINOR) & BYTE;
+
+  dev_mess.m_type   = op;
+  dev_mess.DEVICE   = minor;
+  dev_mess.IO_ENDPT = proc_e;
+  dev_mess.COUNT    = flags;
+
+
+  if (dp->dmap_driver == NONE) {
+	printf("FS: clone_opcl: no driver for dev %x\n", dev);
+	return ENXIO;
+  }
+
+  if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
+  	printf("FS: clone_opcl: old driver for dev %x (%d)\n",
+  		dev, dp->dmap_driver);
+  	return ENXIO;
+  }
+
+  /* Call the task. */
+  r= (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
+  if (r != OK)
+	return r;
+
+  if (op == DEV_OPEN && dev_mess.REP_STATUS >= 0) {
+	if (dev_mess.REP_STATUS != minor) {
+		/* A new minor device number has been returned.  Create a
+		 * temporary device file to hold it.
+		 */
+		struct inode *ip;
+
+		/* Device number of the new device. */
+		dev = (dev & ~(BYTE << MINOR)) | (dev_mess.REP_STATUS << MINOR);
+
+		ip = alloc_inode(root_dev, ALL_MODES | I_CHAR_SPECIAL);
+		if (ip == NIL_INODE) {
+			/* Oops, that didn't work.  Undo open. */
+			(void) clone_opcl(DEV_CLOSE, dev, proc_e, 0);
+			return(err_code);
+		}
+		ip->i_zone[0] = dev;
+
+		put_inode(fp->fp_filp[m_in.fd]->filp_ino);
+		fp->fp_filp[m_in.fd]->filp_ino = ip;
+	}
+	dev_mess.REP_STATUS = OK;
+  }
+  return(dev_mess.REP_STATUS);
+}
+
+/*===========================================================================*
+ *				dev_up					     *
+ *===========================================================================*/
+PUBLIC void dev_up(int maj)
+{
+	/* A new device driver has been mapped in. This function
+	 * checks if any filesystems are mounted on it, and if so,
+	 * dev_open()s them so the filesystem can be reused.
+	 */
+	struct super_block *sb;
+	struct filp *fp;
+	int r;
+
+	/* Open a device once for every filp that's opened on it,
+	 * and once for every filesystem mounted from it.
+	 */
+
+	for(sb = super_block; sb < &super_block[NR_SUPERS]; sb++) {
+		int minor;
+		if(sb->s_dev == NO_DEV)
+			continue;
+		if(((sb->s_dev >> MAJOR) & BYTE) != maj)
+			continue;
+		minor = ((sb->s_dev >> MINOR) & BYTE);
+		printf("FS: remounting dev %d/%d\n", maj, minor);
+		if((r = dev_open(sb->s_dev, FS_PROC_NR,
+		   sb->s_rd_only ? R_BIT : (R_BIT|W_BIT))) != OK) {
+			printf("FS: mounted dev %d/%d re-open failed: %d.\n",
+				maj, minor, r);
+		}
+	}
+
+	for(fp = filp; fp < &filp[NR_FILPS]; fp++) {
+		struct inode *in;
+		int minor;
+
+		if(fp->filp_count < 1 || !(in=fp->filp_ino)) continue;
+		if(((in->i_zone[0] >> MAJOR) & BYTE) != maj) continue;
+		if(!(in->i_mode & (I_BLOCK_SPECIAL|I_CHAR_SPECIAL))) continue;
+		
+		minor = ((in->i_zone[0] >> MINOR) & BYTE);
+
+		printf("FS: reopening special %d/%d..\n", maj, minor);
+
+		if((r = dev_open(in->i_zone[0], FS_PROC_NR,
+		   in->i_mode & (R_BIT|W_BIT))) != OK) {
+			int n;
+			/* This function will set the fp_filp[]s of processes
+			 * holding that fp to NULL, but _not_ clear
+			 * fp_filp_inuse, so that fd can't be recycled until
+			 * it's close()d.
+			 */
+			n = inval_filp(fp);
+			if(n != fp->filp_count)
+				printf("FS: warning: invalidate/count "
+				 "discrepancy (%d, %d)\n", n, fp->filp_count);
+			fp->filp_count = 0;
+			printf("FS: file on dev %d/%d re-open failed: %d; "
+				"invalidated %d fd's.\n", maj, minor, r, n);
+		}
+	}
+
+	return;
+}
+
Index: /trunk/minix/servers/fs/dmap.c
===================================================================
--- /trunk/minix/servers/fs/dmap.c	(revision 9)
+++ /trunk/minix/servers/fs/dmap.c	(revision 9)
@@ -0,0 +1,250 @@
+/* This file contains the table with device <-> driver mappings. It also
+ * contains some routines to dynamically add and/ or remove device drivers
+ * or change mappings.  
+ */
+
+#include "fs.h"
+#include "fproc.h"
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <minix/com.h>
+#include "param.h"
+
+/* Some devices may or may not be there in the next table. */
+#define DT(enable, opcl, io, driver, flags) \
+  { (enable?(opcl):no_dev), (enable?(io):0), \
+  	(enable?(driver):0), (flags) },
+#define NC(x) (NR_CTRLRS >= (x))
+
+/* The order of the entries here determines the mapping between major device
+ * numbers and tasks.  The first entry (major device 0) is not used.  The
+ * next entry is major device 1, etc.  Character and block devices can be
+ * intermixed at random.  The ordering determines the device numbers in /dev/.
+ * Note that FS knows the device number of /dev/ram/ to load the RAM disk.
+ * Also note that the major device numbers used in /dev/ are NOT the same as 
+ * the process numbers of the device drivers. 
+ */
+/*
+  Driver enabled     Open/Cls  I/O     Driver #     Flags Device  File
+  --------------     --------  ------  -----------  ----- ------  ----       
+ */
+struct dmap dmap[NR_DEVICES];				/* actual map */ 
+PRIVATE struct dmap init_dmap[] = {
+  DT(1, no_dev,   0,       0,       	0) 	  	/* 0 = not used   */
+  DT(1, gen_opcl, gen_io,  MEM_PROC_NR, 0)	        /* 1 = /dev/mem   */
+  DT(0, no_dev,   0,       0,           DMAP_MUTABLE)	/* 2 = /dev/fd0   */
+  DT(0, no_dev,   0,       0,           DMAP_MUTABLE)	/* 3 = /dev/c0    */
+  DT(1, tty_opcl, gen_io,  TTY_PROC_NR, 0)    	  	/* 4 = /dev/tty00 */
+  DT(1, ctty_opcl,ctty_io, TTY_PROC_NR, 0)     	   	/* 5 = /dev/tty   */
+  DT(0, no_dev,   0,       NONE,	DMAP_MUTABLE)	/* 6 = /dev/lp    */
+
+#if (MACHINE == IBM_PC)
+  DT(1, no_dev,   0,       0,   	DMAP_MUTABLE)   /* 7 = /dev/ip    */
+  DT(0, no_dev,   0,       NONE,        DMAP_MUTABLE)   /* 8 = /dev/c1    */
+  DT(0, 0,        0,       0,   	DMAP_MUTABLE)   /* 9 = not used   */
+  DT(0, no_dev,   0,       0,           DMAP_MUTABLE)   /*10 = /dev/c2    */
+  DT(0, 0,        0,       0,   	DMAP_MUTABLE)   /*11 = not used   */
+  DT(0, no_dev,   0,       NONE,     	DMAP_MUTABLE)   /*12 = /dev/c3    */
+  DT(0, no_dev,   0,       NONE,	DMAP_MUTABLE)   /*13 = /dev/audio */
+  DT(0, no_dev,   0,       NONE,	DMAP_MUTABLE)   /*14 = /dev/mixer */
+  DT(1, gen_opcl, gen_io,  LOG_PROC_NR, 0)  	        /*15 = /dev/klog  */
+  DT(0, no_dev,   0,       NONE,	DMAP_MUTABLE)   /*16 = /dev/random*/
+  DT(0, no_dev,   0,       NONE,	DMAP_MUTABLE)   /*17 = /dev/cmos  */
+#endif /* IBM_PC */
+};
+
+/*===========================================================================*
+ *				do_devctl		 		     *
+ *===========================================================================*/
+PUBLIC int do_devctl()
+{
+  int result, proc_nr_e, proc_nr_n;
+
+  switch(m_in.ctl_req) {
+  case DEV_MAP:
+      /* Check process number of new driver. */
+      proc_nr_e= m_in.driver_nr;
+      if (isokendpt(proc_nr_e, &proc_nr_n) != OK)
+	return(EINVAL);
+
+      /* Try to update device mapping. */
+      result = map_driver(m_in.dev_nr, proc_nr_e, m_in.dev_style);
+      if (result == OK)
+      {
+	/* If a driver has completed its exec(), it can be announced to be
+	 * up.
+	 */
+	if(fproc[proc_nr_n].fp_execced) {
+		dev_up(m_in.dev_nr);
+	} else {
+		dmap[m_in.dev_nr].dmap_flags |= DMAP_BABY;
+	}
+      }
+      break;
+  case DEV_UNMAP:
+      result = map_driver(m_in.dev_nr, NONE, 0);
+      break;
+  default:
+      result = EINVAL;
+  }
+  return(result);
+}
+
+/*===========================================================================*
+ *				map_driver		 		     *
+ *===========================================================================*/
+PUBLIC int map_driver(major, proc_nr_e, style)
+int major;			/* major number of the device */
+int proc_nr_e;			/* process number of the driver */
+int style;			/* style of the device */
+{
+/* Set a new device driver mapping in the dmap table. Given that correct 
+ * arguments are given, this only works if the entry is mutable and the 
+ * current driver is not busy.  If the proc_nr is set to NONE, we're supposed
+ * to unmap it.
+ *
+ * Normal error codes are returned so that this function can be used from
+ * a system call that tries to dynamically install a new driver.
+ */
+  struct dmap *dp;
+  int proc_nr_n;
+
+  /* Get pointer to device entry in the dmap table. */
+  if (major < 0 || major >= NR_DEVICES) return(ENODEV);
+  dp = &dmap[major];		
+
+  /* Check if we're supposed to unmap it. If so, do it even
+   * if busy or unmutable, as unmap is called when driver has
+   * exited.
+   */
+ if(proc_nr_e == NONE) {
+	dp->dmap_opcl = no_dev;
+	dp->dmap_io = no_dev_io;
+	dp->dmap_driver = NONE;
+	dp->dmap_flags = DMAP_MUTABLE;	/* When gone, not busy or reserved. */
+	return(OK);
+  }
+	
+  /* See if updating the entry is allowed. */
+  if (! (dp->dmap_flags & DMAP_MUTABLE))  return(EPERM);
+  if (dp->dmap_flags & DMAP_BUSY)  return(EBUSY);
+
+  /* Check process number of new driver. */
+  if (isokendpt(proc_nr_e, &proc_nr_n) != OK)
+	return(EINVAL);
+
+  /* Try to update the entry. */
+  switch (style) {
+  case STYLE_DEV:	dp->dmap_opcl = gen_opcl;	break;
+  case STYLE_TTY:	dp->dmap_opcl = tty_opcl;	break;
+  case STYLE_CLONE:	dp->dmap_opcl = clone_opcl;	break;
+  default:		return(EINVAL);
+  }
+  dp->dmap_io = gen_io;
+  dp->dmap_driver = proc_nr_e;
+
+  return(OK); 
+}
+
+/*===========================================================================*
+ *				dmap_unmap_by_endpt	 		     *
+ *===========================================================================*/
+PUBLIC void dmap_unmap_by_endpt(int proc_nr_e)
+{
+	int i, r;
+	for (i=0; i<NR_DEVICES; i++)
+	  if(dmap[i].dmap_driver && dmap[i].dmap_driver == proc_nr_e)
+	    if((r=map_driver(i, NONE, 0)) != OK)
+		printf("FS: unmap of p %d / d %d failed: %d\n", proc_nr_e,i,r);
+
+	return;
+
+}
+
+/*===========================================================================*
+ *				build_dmap		 		     *
+ *===========================================================================*/
+PUBLIC void build_dmap()
+{
+/* Initialize the table with all device <-> driver mappings. Then, map  
+ * the boot driver to a controller and update the dmap table to that
+ * selection. The boot driver and the controller it handles are set at 
+ * the boot monitor.  
+ */
+  int i;
+  struct dmap *dp;
+
+  /* Build table with device <-> driver mappings. */
+  for (i=0; i<NR_DEVICES; i++) {
+      dp = &dmap[i];		
+      if (i < sizeof(init_dmap)/sizeof(struct dmap) && 
+              init_dmap[i].dmap_opcl != no_dev) {	/* a preset driver */
+          dp->dmap_opcl = init_dmap[i].dmap_opcl;
+          dp->dmap_io = init_dmap[i].dmap_io;
+          dp->dmap_driver = init_dmap[i].dmap_driver;
+          dp->dmap_flags = init_dmap[i].dmap_flags;
+      } else {						/* no default */
+          dp->dmap_opcl = no_dev;
+          dp->dmap_io = no_dev_io;
+          dp->dmap_driver = NONE;
+          dp->dmap_flags = DMAP_MUTABLE;
+      }
+  }
+
+#if 0
+  /* Get settings of 'controller' and 'driver' at the boot monitor. */
+  if ((s = env_get_param("label", driver, sizeof(driver))) != OK) 
+      panic(__FILE__,"couldn't get boot monitor parameter 'driver'", s);
+  if ((s = env_get_param("controller", controller, sizeof(controller))) != OK) 
+      panic(__FILE__,"couldn't get boot monitor parameter 'controller'", s);
+
+  /* Determine major number to map driver onto. */
+  if (controller[0] == 'f' && controller[1] == 'd') {
+      major = FLOPPY_MAJOR;
+  } 
+  else if (controller[0] == 'c' && isdigit(controller[1])) {
+      if ((nr = (unsigned) atoi(&controller[1])) > NR_CTRLRS)
+          panic(__FILE__,"monitor 'controller' maximum 'c#' is", NR_CTRLRS);
+      major = CTRLR(nr);
+  } 
+  else {
+      panic(__FILE__,"monitor 'controller' syntax is 'c#' of 'fd'", NO_NUM); 
+  }
+  
+  /* Now try to set the actual mapping and report to the user. */
+  if ((s=map_driver(major, DRVR_PROC_NR, STYLE_DEV)) != OK)
+      panic(__FILE__,"map_driver failed",s);
+  printf("Boot medium driver: %s driver mapped onto controller %s.\n",
+      driver, controller);
+#endif
+}
+
+/*===========================================================================*
+ *				dmap_driver_match	 		     *
+ *===========================================================================*/ 
+PUBLIC int dmap_driver_match(int proc, int major)
+{
+	if (major < 0 || major >= NR_DEVICES) return(0);
+	if(dmap[major].dmap_driver != NONE && dmap[major].dmap_driver == proc)
+		return 1;
+	return 0;
+}
+
+/*===========================================================================*
+ *				dmap_endpt_up		 		     *
+ *===========================================================================*/ 
+PUBLIC void dmap_endpt_up(int proc_e)
+{
+	int i;
+	for (i=0; i<NR_DEVICES; i++) {
+		if(dmap[i].dmap_driver != NONE
+			&& dmap[i].dmap_driver == proc_e
+			&& (dmap[i].dmap_flags & DMAP_BABY)) {
+			dmap[i].dmap_flags &= ~DMAP_BABY;
+			dev_up(i);
+		}
+	}
+	return;
+}
Index: /trunk/minix/servers/fs/file.h
===================================================================
--- /trunk/minix/servers/fs/file.h	(revision 9)
+++ /trunk/minix/servers/fs/file.h	(revision 9)
@@ -0,0 +1,24 @@
+/* This is the filp table.  It is an intermediary between file descriptors and
+ * inodes.  A slot is free if filp_count == 0.
+ */
+
+EXTERN struct filp {
+  mode_t filp_mode;		/* RW bits, telling how file is opened */
+  int filp_flags;		/* flags from open and fcntl */
+  int filp_count;		/* how many file descriptors share this slot?*/
+  struct inode *filp_ino;	/* pointer to the inode */
+  off_t filp_pos;		/* file position */
+
+  /* the following fields are for select() and are owned by the generic
+   * select() code (i.e., fd-type-specific select() code can't touch these).
+   */
+  int filp_selectors;		/* select()ing processes blocking on this fd */
+  int filp_select_ops;		/* interested in these SEL_* operations */
+
+  /* following are for fd-type-specific select() */
+  int filp_pipe_select_ops;
+} filp[NR_FILPS];
+
+#define FILP_CLOSED	0	/* filp_mode: associated device closed */
+
+#define NIL_FILP (struct filp *) 0	/* indicates absence of a filp slot */
Index: /trunk/minix/servers/fs/filedes.c
===================================================================
--- /trunk/minix/servers/fs/filedes.c	(revision 9)
+++ /trunk/minix/servers/fs/filedes.c	(revision 9)
@@ -0,0 +1,117 @@
+/* This file contains the procedures that manipulate file descriptors.
+ *
+ * The entry points into this file are
+ *   get_fd:	 look for free file descriptor and free filp slots
+ *   get_filp:	 look up the filp entry for a given file descriptor
+ *   find_filp:	 find a filp slot that points to a given inode
+ *   inval_filp: invalidate a filp and associated fd's, only let close()
+ *               happen on it
+ */
+
+#include <sys/select.h>
+
+#include "fs.h"
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+
+/*===========================================================================*
+ *				get_fd					     *
+ *===========================================================================*/
+PUBLIC int get_fd(int start, mode_t bits, int *k, struct filp **fpt)
+{
+/* Look for a free file descriptor and a free filp slot.  Fill in the mode word
+ * in the latter, but don't claim either one yet, since the open() or creat()
+ * may yet fail.
+ */
+
+  register struct filp *f;
+  register int i;
+
+  *k = -1;			/* we need a way to tell if file desc found */
+
+  /* Search the fproc fp_filp table for a free file descriptor. */
+  for (i = start; i < OPEN_MAX; i++) {
+	if (fp->fp_filp[i] == NIL_FILP && !FD_ISSET(i, &fp->fp_filp_inuse)) {
+		/* A file descriptor has been located. */
+		*k = i;
+		break;
+	}
+  }
+
+  /* Check to see if a file descriptor has been found. */
+  if (*k < 0) return(EMFILE);	/* this is why we initialized k to -1 */
+
+  /* Now that a file descriptor has been found, look for a free filp slot. */
+  for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
+	if (f->filp_count == 0) {
+		f->filp_mode = bits;
+		f->filp_pos = 0L;
+		f->filp_selectors = 0;
+		f->filp_select_ops = 0;
+		f->filp_pipe_select_ops = 0;
+		f->filp_flags = 0;
+		*fpt = f;
+		return(OK);
+	}
+  }
+
+  /* If control passes here, the filp table must be full.  Report that back. */
+  return(ENFILE);
+}
+
+/*===========================================================================*
+ *				get_filp				     *
+ *===========================================================================*/
+PUBLIC struct filp *get_filp(fild)
+int fild;			/* file descriptor */
+{
+/* See if 'fild' refers to a valid file descr.  If so, return its filp ptr. */
+
+  err_code = EBADF;
+  if (fild < 0 || fild >= OPEN_MAX ) return(NIL_FILP);
+  return(fp->fp_filp[fild]);	/* may also be NIL_FILP */
+}
+
+/*===========================================================================*
+ *				find_filp				     *
+ *===========================================================================*/
+PUBLIC struct filp *find_filp(register struct inode *rip, mode_t bits)
+{
+/* Find a filp slot that refers to the inode 'rip' in a way as described
+ * by the mode bit 'bits'. Used for determining whether somebody is still
+ * interested in either end of a pipe.  Also used when opening a FIFO to
+ * find partners to share a filp field with (to shared the file position).
+ * Like 'get_fd' it performs its job by linear search through the filp table.
+ */
+
+  register struct filp *f;
+
+  for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
+	if (f->filp_count != 0 && f->filp_ino == rip && (f->filp_mode & bits)){
+		return(f);
+	}
+  }
+
+  /* If control passes here, the filp wasn't there.  Report that back. */
+  return(NIL_FILP);
+}
+
+/*===========================================================================*
+ *				inval_filp				     *
+ *===========================================================================*/
+PUBLIC int inval_filp(struct filp *fp)
+{
+	int f, fd, n = 0;
+	for(f = 0; f < NR_PROCS; f++) {
+		if(fproc[f].fp_pid == PID_FREE) continue;
+		for(fd = 0; fd < OPEN_MAX; fd++) {
+			if(fproc[f].fp_filp[fd] && fproc[f].fp_filp[fd] == fp) {
+				fproc[f].fp_filp[fd] = NIL_FILP;
+				n++;
+			}
+		}
+	}
+
+	return n;
+}
Index: /trunk/minix/servers/fs/fproc.h
===================================================================
--- /trunk/minix/servers/fs/fproc.h	(revision 9)
+++ /trunk/minix/servers/fs/fproc.h	(revision 9)
@@ -0,0 +1,41 @@
+#include <sys/select.h>
+
+/* This is the per-process information.  A slot is reserved for each potential
+ * process. Thus NR_PROCS must be the same as in the kernel. It is not 
+ * possible or even necessary to tell when a slot is free here.
+ */
+EXTERN struct fproc {
+  mode_t fp_umask;		/* mask set by umask system call */
+  struct inode *fp_workdir;	/* pointer to working directory's inode */
+  struct inode *fp_rootdir;	/* pointer to current root dir (see chroot) */
+  struct filp *fp_filp[OPEN_MAX];/* the file descriptor table */
+  fd_set fp_filp_inuse;		/* which fd's are in use? */
+  uid_t fp_realuid;		/* real user id */
+  uid_t fp_effuid;		/* effective user id */
+  gid_t fp_realgid;		/* real group id */
+  gid_t fp_effgid;		/* effective group id */
+  dev_t fp_tty;			/* major/minor of controlling tty */
+  int fp_fd;			/* place to save fd if rd/wr can't finish */
+  char *fp_buffer;		/* place to save buffer if rd/wr can't finish*/
+  int  fp_nbytes;		/* place to save bytes if rd/wr can't finish */
+  int  fp_cum_io_partial;	/* partial byte count if rd/wr can't finish */
+  char fp_suspended;		/* set to indicate process hanging */
+  char fp_revived;		/* set to indicate process being revived */
+  int fp_task;			/* which task is proc suspended on */
+  char fp_sesldr;		/* true if proc is a session leader */
+  char fp_execced;		/* true if proc has exec()ced after fork */
+  pid_t fp_pid;			/* process id */
+  long fp_cloexec;		/* bit map for POSIX Table 6-2 FD_CLOEXEC */
+  int fp_endpoint;		/* kernel endpoint number of this process */
+} fproc[NR_PROCS];
+
+/* Field values. */
+#define NOT_SUSPENDED      0	/* process is not suspended on pipe or task */
+#define SUSPENDED          1	/* process is suspended on pipe or task */
+#define NOT_REVIVING       0	/* process is not being revived */
+#define REVIVING           1	/* process is being revived from suspension */
+#define PID_FREE	   0	/* process slot free */
+
+/* Check is process number is acceptable - includes system processes. */
+#define isokprocnr(n)	((unsigned)((n)+NR_TASKS) < NR_PROCS + NR_TASKS)
+
Index: /trunk/minix/servers/fs/fs.h
===================================================================
--- /trunk/minix/servers/fs/fs.h	(revision 9)
+++ /trunk/minix/servers/fs/fs.h	(revision 9)
@@ -0,0 +1,27 @@
+/* This is the master header for fs.  It includes some other files
+ * and defines the principal constants.
+ */
+#define _POSIX_SOURCE      1	/* tell headers to include POSIX stuff */
+#define _MINIX             1	/* tell headers to include MINIX stuff */
+#define _SYSTEM            1	/* tell headers that this is the kernel */
+
+#define VERBOSE		   0    /* show messages during initialization? */
+
+/* The following are so basic, all the *.c files get them automatically. */
+#include <minix/config.h>	/* MUST be first */
+#include <ansi.h>		/* MUST be second */
+#include <sys/types.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include <minix/dmap.h>
+
+#include <limits.h>
+#include <errno.h>
+
+#include <minix/syslib.h>
+#include <minix/sysutil.h>
+
+#include "const.h"
+#include "type.h"
+#include "proto.h"
+#include "glo.h"
Index: /trunk/minix/servers/fs/glo.h
===================================================================
--- /trunk/minix/servers/fs/glo.h	(revision 9)
+++ /trunk/minix/servers/fs/glo.h	(revision 9)
@@ -0,0 +1,32 @@
+/* EXTERN should be extern except for the table file */
+#ifdef _TABLE
+#undef EXTERN
+#define EXTERN
+#endif
+
+/* File System global variables */
+EXTERN struct fproc *fp;	/* pointer to caller's fproc struct */
+EXTERN int super_user;		/* 1 if caller is super_user, else 0 */
+EXTERN int susp_count;		/* number of procs suspended on pipe */
+EXTERN int nr_locks;		/* number of locks currently in place */
+EXTERN int reviving;		/* number of pipe processes to be revived */
+EXTERN off_t rdahedpos;		/* position to read ahead */
+EXTERN struct inode *rdahed_inode;	/* pointer to inode to read ahead */
+EXTERN Dev_t root_dev;		/* device number of the root device */
+EXTERN time_t boottime;		/* time in seconds at system boot */
+
+/* The parameters of the call are kept here. */
+EXTERN message m_in;		/* the input message itself */
+EXTERN message m_out;		/* the output message used for reply */
+EXTERN int who_p, who_e;	/* caller's proc number, endpoint */
+EXTERN int call_nr;		/* system call number */
+EXTERN char user_path[PATH_MAX];/* storage for user path name */
+
+/* The following variables are used for returning results to the caller. */
+EXTERN int err_code;		/* temporary storage for error number */
+EXTERN int rdwt_err;		/* status of last disk i/o request */
+
+/* Data initialized elsewhere. */
+extern _PROTOTYPE (int (*call_vec[]), (void) ); /* sys call table */
+extern char dot1[2];   /* dot1 (&dot1[0]) and dot2 (&dot2[0]) have a special */
+extern char dot2[3];   /* meaning to search_dir: no access permission check. */
Index: /trunk/minix/servers/fs/inode.c
===================================================================
--- /trunk/minix/servers/fs/inode.c	(revision 9)
+++ /trunk/minix/servers/fs/inode.c	(revision 9)
@@ -0,0 +1,366 @@
+/* This file manages the inode table.  There are procedures to allocate and
+ * deallocate inodes, acquire, erase, and release them, and read and write
+ * them from the disk.
+ *
+ * The entry points into this file are
+ *   get_inode:	   search inode table for a given inode; if not there,
+ *                 read it
+ *   put_inode:	   indicate that an inode is no longer needed in memory
+ *   alloc_inode:  allocate a new, unused inode
+ *   wipe_inode:   erase some fields of a newly allocated inode
+ *   free_inode:   mark an inode as available for a new file
+ *   update_times: update atime, ctime, and mtime
+ *   rw_inode:	   read a disk block and extract an inode, or corresp. write
+ *   old_icopy:	   copy to/from in-core inode struct and disk inode (V1.x)
+ *   new_icopy:	   copy to/from in-core inode struct and disk inode (V2.x)
+ *   dup_inode:	   indicate that someone else is using an inode table entry
+ */
+
+#include "fs.h"
+#include "buf.h"
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "super.h"
+
+FORWARD _PROTOTYPE( void old_icopy, (struct inode *rip, d1_inode *dip,
+						int direction, int norm));
+FORWARD _PROTOTYPE( void new_icopy, (struct inode *rip, d2_inode *dip,
+						int direction, int norm));
+
+/*===========================================================================*
+ *				get_inode				     *
+ *===========================================================================*/
+PUBLIC struct inode *get_inode(dev, numb)
+dev_t dev;			/* device on which inode resides */
+int numb;			/* inode number (ANSI: may not be unshort) */
+{
+/* Find a slot in the inode table, load the specified inode into it, and
+ * return a pointer to the slot.  If 'dev' == NO_DEV, just return a free slot.
+ */
+
+  register struct inode *rip, *xp;
+
+  /* Search the inode table both for (dev, numb) and a free slot. */
+  xp = NIL_INODE;
+  for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) {
+	if (rip->i_count > 0) { /* only check used slots for (dev, numb) */
+		if (rip->i_dev == dev && rip->i_num == numb) {
+			/* This is the inode that we are looking for. */
+			rip->i_count++;
+			return(rip);	/* (dev, numb) found */
+		}
+	} else {
+		xp = rip;	/* remember this free slot for later */
+	}
+  }
+
+  /* Inode we want is not currently in use.  Did we find a free slot? */
+  if (xp == NIL_INODE) {	/* inode table completely full */
+	err_code = ENFILE;
+	return(NIL_INODE);
+  }
+
+  /* A free inode slot has been located.  Load the inode into it. */
+  xp->i_dev = dev;
+  xp->i_num = numb;
+  xp->i_count = 1;
+  if (dev != NO_DEV) rw_inode(xp, READING);	/* get inode from disk */
+  xp->i_update = 0;		/* all the times are initially up-to-date */
+
+  return(xp);
+}
+
+/*===========================================================================*
+ *				put_inode				     *
+ *===========================================================================*/
+PUBLIC void put_inode(rip)
+register struct inode *rip;	/* pointer to inode to be released */
+{
+/* The caller is no longer using this inode.  If no one else is using it either
+ * write it back to the disk immediately.  If it has no links, truncate it and
+ * return it to the pool of available inodes.
+ */
+
+  if (rip == NIL_INODE) return;	/* checking here is easier than in caller */
+  if (--rip->i_count == 0) {	/* i_count == 0 means no one is using it now */
+	if (rip->i_nlinks == 0) {
+		/* i_nlinks == 0 means free the inode. */
+		truncate_inode(rip, 0);	/* return all the disk blocks */
+		rip->i_mode = I_NOT_ALLOC;	/* clear I_TYPE field */
+		rip->i_dirt = DIRTY;
+		free_inode(rip->i_dev, rip->i_num);
+	} else {
+		if (rip->i_pipe == I_PIPE) truncate_inode(rip, 0);
+	}
+	rip->i_pipe = NO_PIPE;  /* should always be cleared */
+	if (rip->i_dirt == DIRTY) rw_inode(rip, WRITING);
+  }
+}
+
+/*===========================================================================*
+ *				alloc_inode				     *
+ *===========================================================================*/
+PUBLIC struct inode *alloc_inode(dev_t dev, mode_t bits)
+{
+/* Allocate a free inode on 'dev', and return a pointer to it. */
+
+  register struct inode *rip;
+  register struct super_block *sp;
+  int major, minor, inumb;
+  bit_t b;
+
+  sp = get_super(dev);	/* get pointer to super_block */
+  if (sp->s_rd_only) {	/* can't allocate an inode on a read only device. */
+	err_code = EROFS;
+	return(NIL_INODE);
+  }
+
+  /* Acquire an inode from the bit map. */
+  b = alloc_bit(sp, IMAP, sp->s_isearch);
+  if (b == NO_BIT) {
+	err_code = ENFILE;
+	major = (int) (sp->s_dev >> MAJOR) & BYTE;
+	minor = (int) (sp->s_dev >> MINOR) & BYTE;
+	printf("Out of i-nodes on %sdevice %d/%d\n",
+		sp->s_dev == root_dev ? "root " : "", major, minor);
+	return(NIL_INODE);
+  }
+  sp->s_isearch = b;		/* next time start here */
+  inumb = (int) b;		/* be careful not to pass unshort as param */
+
+  /* Try to acquire a slot in the inode table. */
+  if ((rip = get_inode(NO_DEV, inumb)) == NIL_INODE) {
+	/* No inode table slots available.  Free the inode just allocated. */
+	free_bit(sp, IMAP, b);
+  } else {
+	/* An inode slot is available. Put the inode just allocated into it. */
+	rip->i_mode = bits;		/* set up RWX bits */
+	rip->i_nlinks = 0;		/* initial no links */
+	rip->i_uid = fp->fp_effuid;	/* file's uid is owner's */
+	rip->i_gid = fp->fp_effgid;	/* ditto group id */
+	rip->i_dev = dev;		/* mark which device it is on */
+	rip->i_ndzones = sp->s_ndzones;	/* number of direct zones */
+	rip->i_nindirs = sp->s_nindirs;	/* number of indirect zones per blk*/
+	rip->i_sp = sp;			/* pointer to super block */
+
+	/* Fields not cleared already are cleared in wipe_inode().  They have
+	 * been put there because truncate() needs to clear the same fields if
+	 * the file happens to be open while being truncated.  It saves space
+	 * not to repeat the code twice.
+	 */
+	wipe_inode(rip);
+  }
+
+  return(rip);
+}
+
+/*===========================================================================*
+ *				wipe_inode				     *
+ *===========================================================================*/
+PUBLIC void wipe_inode(rip)
+register struct inode *rip;	/* the inode to be erased */
+{
+/* Erase some fields in the inode.  This function is called from alloc_inode()
+ * when a new inode is to be allocated, and from truncate(), when an existing
+ * inode is to be truncated.
+ */
+
+  register int i;
+
+  rip->i_size = 0;
+  rip->i_update = ATIME | CTIME | MTIME;	/* update all times later */
+  rip->i_dirt = DIRTY;
+  for (i = 0; i < V2_NR_TZONES; i++) rip->i_zone[i] = NO_ZONE;
+}
+
+/*===========================================================================*
+ *				free_inode				     *
+ *===========================================================================*/
+PUBLIC void free_inode(dev, inumb)
+dev_t dev;			/* on which device is the inode */
+ino_t inumb;			/* number of inode to be freed */
+{
+/* Return an inode to the pool of unallocated inodes. */
+
+  register struct super_block *sp;
+  bit_t b;
+
+  /* Locate the appropriate super_block. */
+  sp = get_super(dev);
+  if (inumb <= 0 || inumb > sp->s_ninodes) return;
+  b = inumb;
+  free_bit(sp, IMAP, b);
+  if (b < sp->s_isearch) sp->s_isearch = b;
+}
+
+/*===========================================================================*
+ *				update_times				     *
+ *===========================================================================*/
+PUBLIC void update_times(rip)
+register struct inode *rip;	/* pointer to inode to be read/written */
+{
+/* Various system calls are required by the standard to update atime, ctime,
+ * or mtime.  Since updating a time requires sending a message to the clock
+ * task--an expensive business--the times are marked for update by setting
+ * bits in i_update.  When a stat, fstat, or sync is done, or an inode is 
+ * released, update_times() may be called to actually fill in the times.
+ */
+
+  time_t cur_time;
+  struct super_block *sp;
+
+  sp = rip->i_sp;		/* get pointer to super block. */
+  if (sp->s_rd_only) return;	/* no updates for read-only file systems */
+
+  cur_time = clock_time();
+  if (rip->i_update & ATIME) rip->i_atime = cur_time;
+  if (rip->i_update & CTIME) rip->i_ctime = cur_time;
+  if (rip->i_update & MTIME) rip->i_mtime = cur_time;
+  rip->i_update = 0;		/* they are all up-to-date now */
+}
+
+/*===========================================================================*
+ *				rw_inode				     *
+ *===========================================================================*/
+PUBLIC void rw_inode(rip, rw_flag)
+register struct inode *rip;	/* pointer to inode to be read/written */
+int rw_flag;			/* READING or WRITING */
+{
+/* An entry in the inode table is to be copied to or from the disk. */
+
+  register struct buf *bp;
+  register struct super_block *sp;
+  d1_inode *dip;
+  d2_inode *dip2;
+  block_t b, offset;
+
+  /* Get the block where the inode resides. */
+  sp = get_super(rip->i_dev);	/* get pointer to super block */
+  rip->i_sp = sp;		/* inode must contain super block pointer */
+  offset = sp->s_imap_blocks + sp->s_zmap_blocks + 2;
+  b = (block_t) (rip->i_num - 1)/sp->s_inodes_per_block + offset;
+  bp = get_block(rip->i_dev, b, NORMAL);
+  dip  = bp->b_v1_ino + (rip->i_num - 1) % V1_INODES_PER_BLOCK;
+  dip2 = bp->b_v2_ino + (rip->i_num - 1) %
+  	 V2_INODES_PER_BLOCK(sp->s_block_size);
+
+  /* Do the read or write. */
+  if (rw_flag == WRITING) {
+	if (rip->i_update) update_times(rip);	/* times need updating */
+	if (sp->s_rd_only == FALSE) bp->b_dirt = DIRTY;
+  }
+
+  /* Copy the inode from the disk block to the in-core table or vice versa.
+   * If the fourth parameter below is FALSE, the bytes are swapped.
+   */
+  if (sp->s_version == V1)
+	old_icopy(rip, dip,  rw_flag, sp->s_native);
+  else
+	new_icopy(rip, dip2, rw_flag, sp->s_native);
+  
+  put_block(bp, INODE_BLOCK);
+  rip->i_dirt = CLEAN;
+}
+
+/*===========================================================================*
+ *				old_icopy				     *
+ *===========================================================================*/
+PRIVATE void old_icopy(rip, dip, direction, norm)
+register struct inode *rip;	/* pointer to the in-core inode struct */
+register d1_inode *dip;		/* pointer to the d1_inode inode struct */
+int direction;			/* READING (from disk) or WRITING (to disk) */
+int norm;			/* TRUE = do not swap bytes; FALSE = swap */
+
+{
+/* The V1.x IBM disk, the V1.x 68000 disk, and the V2 disk (same for IBM and
+ * 68000) all have different inode layouts.  When an inode is read or written
+ * this routine handles the conversions so that the information in the inode
+ * table is independent of the disk structure from which the inode came.
+ * The old_icopy routine copies to and from V1 disks.
+ */
+
+  int i;
+
+  if (direction == READING) {
+	/* Copy V1.x inode to the in-core table, swapping bytes if need be. */
+	rip->i_mode    = conv2(norm, (int) dip->d1_mode);
+	rip->i_uid     = conv2(norm, (int) dip->d1_uid );
+	rip->i_size    = conv4(norm,       dip->d1_size);
+	rip->i_mtime   = conv4(norm,       dip->d1_mtime);
+	rip->i_atime   = rip->i_mtime;
+	rip->i_ctime   = rip->i_mtime;
+	rip->i_nlinks  = dip->d1_nlinks;		/* 1 char */
+	rip->i_gid     = dip->d1_gid;			/* 1 char */
+	rip->i_ndzones = V1_NR_DZONES;
+	rip->i_nindirs = V1_INDIRECTS;
+	for (i = 0; i < V1_NR_TZONES; i++)
+		rip->i_zone[i] = conv2(norm, (int) dip->d1_zone[i]);
+  } else {
+	/* Copying V1.x inode to disk from the in-core table. */
+	dip->d1_mode   = conv2(norm, (int) rip->i_mode);
+	dip->d1_uid    = conv2(norm, (int) rip->i_uid );
+	dip->d1_size   = conv4(norm,       rip->i_size);
+	dip->d1_mtime  = conv4(norm,       rip->i_mtime);
+	dip->d1_nlinks = rip->i_nlinks;			/* 1 char */
+	dip->d1_gid    = rip->i_gid;			/* 1 char */
+	for (i = 0; i < V1_NR_TZONES; i++)
+		dip->d1_zone[i] = conv2(norm, (int) rip->i_zone[i]);
+  }
+}
+
+/*===========================================================================*
+ *				new_icopy				     *
+ *===========================================================================*/
+PRIVATE void new_icopy(rip, dip, direction, norm)
+register struct inode *rip;	/* pointer to the in-core inode struct */
+register d2_inode *dip;	/* pointer to the d2_inode struct */
+int direction;			/* READING (from disk) or WRITING (to disk) */
+int norm;			/* TRUE = do not swap bytes; FALSE = swap */
+
+{
+/* Same as old_icopy, but to/from V2 disk layout. */
+
+  int i;
+
+  if (direction == READING) {
+	/* Copy V2.x inode to the in-core table, swapping bytes if need be. */
+	rip->i_mode    = conv2(norm,dip->d2_mode);
+	rip->i_uid     = conv2(norm,dip->d2_uid);
+	rip->i_nlinks  = conv2(norm,dip->d2_nlinks);
+	rip->i_gid     = conv2(norm,dip->d2_gid);
+	rip->i_size    = conv4(norm,dip->d2_size);
+	rip->i_atime   = conv4(norm,dip->d2_atime);
+	rip->i_ctime   = conv4(norm,dip->d2_ctime);
+	rip->i_mtime   = conv4(norm,dip->d2_mtime);
+	rip->i_ndzones = V2_NR_DZONES;
+	rip->i_nindirs = V2_INDIRECTS(rip->i_sp->s_block_size);
+	for (i = 0; i < V2_NR_TZONES; i++)
+		rip->i_zone[i] = conv4(norm, (long) dip->d2_zone[i]);
+  } else {
+	/* Copying V2.x inode to disk from the in-core table. */
+	dip->d2_mode   = conv2(norm,rip->i_mode);
+	dip->d2_uid    = conv2(norm,rip->i_uid);
+	dip->d2_nlinks = conv2(norm,rip->i_nlinks);
+	dip->d2_gid    = conv2(norm,rip->i_gid);
+	dip->d2_size   = conv4(norm,rip->i_size);
+	dip->d2_atime  = conv4(norm,rip->i_atime);
+	dip->d2_ctime  = conv4(norm,rip->i_ctime);
+	dip->d2_mtime  = conv4(norm,rip->i_mtime);
+	for (i = 0; i < V2_NR_TZONES; i++)
+		dip->d2_zone[i] = conv4(norm, (long) rip->i_zone[i]);
+  }
+}
+
+/*===========================================================================*
+ *				dup_inode				     *
+ *===========================================================================*/
+PUBLIC void dup_inode(ip)
+struct inode *ip;		/* The inode to be duplicated. */
+{
+/* This routine is a simplified form of get_inode() for the case where
+ * the inode pointer is already known.
+ */
+
+  ip->i_count++;
+}
Index: /trunk/minix/servers/fs/inode.h
===================================================================
--- /trunk/minix/servers/fs/inode.h	(revision 9)
+++ /trunk/minix/servers/fs/inode.h	(revision 9)
@@ -0,0 +1,44 @@
+/* Inode table.  This table holds inodes that are currently in use.  In some
+ * cases they have been opened by an open() or creat() system call, in other
+ * cases the file system itself needs the inode for one reason or another,
+ * such as to search a directory for a path name.
+ * The first part of the struct holds fields that are present on the
+ * disk; the second part holds fields not present on the disk.
+ * The disk inode part is also declared in "type.h" as 'd1_inode' for V1
+ * file systems and 'd2_inode' for V2 file systems.
+ */
+
+EXTERN struct inode {
+  mode_t i_mode;		/* file type, protection, etc. */
+  nlink_t i_nlinks;		/* how many links to this file */
+  uid_t i_uid;			/* user id of the file's owner */
+  gid_t i_gid;			/* group number */
+  off_t i_size;			/* current file size in bytes */
+  time_t i_atime;		/* time of last access (V2 only) */
+  time_t i_mtime;		/* when was file data last changed */
+  time_t i_ctime;		/* when was inode itself changed (V2 only)*/
+  zone_t i_zone[V2_NR_TZONES]; /* zone numbers for direct, ind, and dbl ind */
+  
+  /* The following items are not present on the disk. */
+  dev_t i_dev;			/* which device is the inode on */
+  ino_t i_num;			/* inode number on its (minor) device */
+  int i_count;			/* # times inode used; 0 means slot is free */
+  int i_ndzones;		/* # direct zones (Vx_NR_DZONES) */
+  int i_nindirs;		/* # indirect zones per indirect block */
+  struct super_block *i_sp;	/* pointer to super block for inode's device */
+  char i_dirt;			/* CLEAN or DIRTY */
+  char i_pipe;			/* set to I_PIPE if pipe */
+  char i_mount;			/* this bit is set if file mounted on */
+  char i_seek;			/* set on LSEEK, cleared on READ/WRITE */
+  char i_update;		/* the ATIME, CTIME, and MTIME bits are here */
+} inode[NR_INODES];
+
+#define NIL_INODE (struct inode *) 0	/* indicates absence of inode slot */
+
+/* Field values.  Note that CLEAN and DIRTY are defined in "const.h" */
+#define NO_PIPE            0	/* i_pipe is NO_PIPE if inode is not a pipe */
+#define I_PIPE             1	/* i_pipe is I_PIPE if inode is a pipe */
+#define NO_MOUNT           0	/* i_mount is NO_MOUNT if file not mounted on*/
+#define I_MOUNT            1	/* i_mount is I_MOUNT if file mounted on */
+#define NO_SEEK            0	/* i_seek = NO_SEEK if last op was not SEEK */
+#define ISEEK              1	/* i_seek = ISEEK if last op was SEEK */
Index: /trunk/minix/servers/fs/link.c
===================================================================
--- /trunk/minix/servers/fs/link.c	(revision 9)
+++ /trunk/minix/servers/fs/link.c	(revision 9)
@@ -0,0 +1,616 @@
+/* This file handles the LINK and UNLINK system calls.  It also deals with
+ * deallocating the storage used by a file when the last UNLINK is done to a
+ * file and the blocks must be returned to the free block pool.
+ *
+ * The entry points into this file are
+ *   do_link:         perform the LINK system call
+ *   do_unlink:	      perform the UNLINK and RMDIR system calls
+ *   do_rename:	      perform the RENAME system call
+ *   do_truncate:     perform the TRUNCATE system call
+ *   do_ftruncate:    perform the FTRUNCATE system call
+ *   truncate_inode:  release the blocks associated with an inode up to a size
+ *   freesp_inode:    release a range of blocks without setting the size
+ */
+
+#include "fs.h"
+#include <sys/stat.h>
+#include <string.h>
+#include <minix/com.h>
+#include <minix/callnr.h>
+#include "buf.h"
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "param.h"
+#include "super.h"
+
+#define SAME 1000
+
+FORWARD _PROTOTYPE( int remove_dir, (struct inode *rldirp, struct inode *rip,
+			char dir_name[NAME_MAX])			);
+FORWARD _PROTOTYPE( int unlink_file, (struct inode *dirp, struct inode *rip,
+			char file_name[NAME_MAX])			);
+FORWARD _PROTOTYPE( off_t nextblock, (off_t pos, int zonesize)		);
+FORWARD _PROTOTYPE( void zeroblock_half, (struct inode *i, off_t p, int l));
+FORWARD _PROTOTYPE( void zeroblock_range, (struct inode *i, off_t p, off_t h));
+
+/* Args to zeroblock_half() */
+#define FIRST_HALF	0
+#define LAST_HALF	1
+
+/*===========================================================================*
+ *				do_link					     *
+ *===========================================================================*/
+PUBLIC int do_link()
+{
+/* Perform the link(name1, name2) system call. */
+
+  struct inode *ip, *rip;
+  register int r;
+  char string[NAME_MAX];
+  struct inode *new_ip;
+
+  /* See if 'name' (file to be linked) exists. */
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+  if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
+
+  /* Check to see if the file has maximum number of links already. */
+  r = OK;
+  if (rip->i_nlinks >= (rip->i_sp->s_version == V1 ? CHAR_MAX : SHRT_MAX))
+	r = EMLINK;
+
+  /* Only super_user may link to directories. */
+  if (r == OK)
+	if ( (rip->i_mode & I_TYPE) == I_DIRECTORY && !super_user) r = EPERM;
+
+  /* If error with 'name', return the inode. */
+  if (r != OK) {
+	put_inode(rip);
+	return(r);
+  }
+
+  /* Does the final directory of 'name2' exist? */
+  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
+	put_inode(rip);
+	return(err_code);
+  }
+  if ( (ip = last_dir(user_path, string)) == NIL_INODE) r = err_code;
+
+  /* If 'name2' exists in full (even if no space) set 'r' to error. */
+  if (r == OK) {
+	if ( (new_ip = advance(&ip, string)) == NIL_INODE) {
+		r = err_code;
+		if (r == ENOENT) r = OK;
+	} else {
+		put_inode(new_ip);
+		r = EEXIST;
+	}
+  }
+
+  /* Check for links across devices. */
+  if (r == OK)
+	if (rip->i_dev != ip->i_dev) r = EXDEV;
+
+  /* Try to link. */
+  if (r == OK)
+	r = search_dir(ip, string, &rip->i_num, ENTER);
+
+  /* If success, register the linking. */
+  if (r == OK) {
+	rip->i_nlinks++;
+	rip->i_update |= CTIME;
+	rip->i_dirt = DIRTY;
+  }
+
+  /* Done.  Release both inodes. */
+  put_inode(rip);
+  put_inode(ip);
+  return(r);
+}
+
+/*===========================================================================*
+ *				do_unlink				     *
+ *===========================================================================*/
+PUBLIC int do_unlink()
+{
+/* Perform the unlink(name) or rmdir(name) system call. The code for these two
+ * is almost the same.  They differ only in some condition testing.  Unlink()
+ * may be used by the superuser to do dangerous things; rmdir() may not.
+ */
+
+  register struct inode *rip;
+  struct inode *rldirp;
+  int r;
+  char string[NAME_MAX];
+
+  /* Get the last directory in the path. */
+  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
+  if ( (rldirp = last_dir(user_path, string)) == NIL_INODE)
+	return(err_code);
+
+  /* The last directory exists.  Does the file also exist? */
+  r = OK;
+  if ( (rip = advance(&rldirp, string)) == NIL_INODE) r = err_code;
+
+  /* If error, return inode. */
+  if (r != OK) {
+	put_inode(rldirp);
+	return(r);
+  }
+
+  /* Do not remove a mount point. */
+  if (rip->i_num == ROOT_INODE) {
+	put_inode(rldirp);
+	put_inode(rip);
+	return(EBUSY);
+  }
+
+  /* Now test if the call is allowed, separately for unlink() and rmdir(). */
+  if (call_nr == UNLINK) {
+	/* Only the su may unlink directories, but the su can unlink any dir.*/
+	if ( (rip->i_mode & I_TYPE) == I_DIRECTORY && !super_user) r = EPERM;
+
+	/* Don't unlink a file if it is the root of a mounted file system. */
+	if (rip->i_num == ROOT_INODE) r = EBUSY;
+
+	/* Actually try to unlink the file; fails if parent is mode 0 etc. */
+	if (r == OK) r = unlink_file(rldirp, rip, string);
+
+  } else {
+	r = remove_dir(rldirp, rip, string); /* call is RMDIR */
+  }
+
+  /* If unlink was possible, it has been done, otherwise it has not. */
+  put_inode(rip);
+  put_inode(rldirp);
+  return(r);
+}
+
+/*===========================================================================*
+ *				do_rename				     *
+ *===========================================================================*/
+PUBLIC int do_rename()
+{
+/* Perform the rename(name1, name2) system call. */
+
+  struct inode *old_dirp, *old_ip;	/* ptrs to old dir, file inodes */
+  struct inode *new_dirp, *new_ip;	/* ptrs to new dir, file inodes */
+  struct inode *new_superdirp, *next_new_superdirp;
+  int r = OK;				/* error flag; initially no error */
+  int odir, ndir;			/* TRUE iff {old|new} file is dir */
+  int same_pdir;			/* TRUE iff parent dirs are the same */
+  char old_name[NAME_MAX], new_name[NAME_MAX];
+  ino_t numb;
+  int r1;
+  
+  /* See if 'name1' (existing file) exists.  Get dir and file inodes. */
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+  if ( (old_dirp = last_dir(user_path, old_name))==NIL_INODE) return(err_code);
+
+  if ( (old_ip = advance(&old_dirp, old_name)) == NIL_INODE) r = err_code;
+
+  /* See if 'name2' (new name) exists.  Get dir and file inodes. */
+  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) r = err_code;
+  if ( (new_dirp = last_dir(user_path, new_name)) == NIL_INODE) r = err_code;
+  new_ip = advance(&new_dirp, new_name);	/* not required to exist */
+
+  if (old_ip != NIL_INODE)
+	odir = ((old_ip->i_mode & I_TYPE) == I_DIRECTORY);  /* TRUE iff dir */
+
+  /* If it is ok, check for a variety of possible errors. */
+  if (r == OK) {
+	same_pdir = (old_dirp == new_dirp);
+
+	/* The old inode must not be a superdirectory of the new last dir. */
+	if (odir && !same_pdir) {
+		dup_inode(new_superdirp = new_dirp);
+		while (TRUE) {		/* may hang in a file system loop */
+			if (new_superdirp == old_ip) {
+				r = EINVAL;
+				break;
+			}
+			next_new_superdirp = advance(&new_superdirp, dot2);
+			put_inode(new_superdirp);
+			if (next_new_superdirp == new_superdirp)
+				break;	/* back at system root directory */
+			new_superdirp = next_new_superdirp;
+			if (new_superdirp == NIL_INODE) {
+				/* Missing ".." entry.  Assume the worst. */
+				r = EINVAL;
+				break;
+			}
+		} 	
+		put_inode(new_superdirp);
+	}	
+
+	/* The old or new name must not be . or .. */
+	if (strcmp(old_name, ".")==0 || strcmp(old_name, "..")==0 ||
+	    strcmp(new_name, ".")==0 || strcmp(new_name, "..")==0) r = EINVAL;
+
+	/* Both parent directories must be on the same device. */
+	if (old_dirp->i_dev != new_dirp->i_dev) r = EXDEV;
+
+	/* Parent dirs must be writable, searchable and on a writable device */
+	if ((r1 = forbidden(old_dirp, W_BIT | X_BIT)) != OK ||
+	    (r1 = forbidden(new_dirp, W_BIT | X_BIT)) != OK) r = r1;
+
+	/* Some tests apply only if the new path exists. */
+	if (new_ip == NIL_INODE) {
+		/* don't rename a file with a file system mounted on it. */
+		if (old_ip->i_dev != old_dirp->i_dev) r = EXDEV;
+		if (odir && new_dirp->i_nlinks >=
+		    (new_dirp->i_sp->s_version == V1 ? CHAR_MAX : SHRT_MAX) &&
+		    !same_pdir && r == OK) r = EMLINK;
+	} else {
+		if (old_ip == new_ip) r = SAME; /* old=new */
+
+		/* has the old file or new file a file system mounted on it? */
+		if (old_ip->i_dev != new_ip->i_dev) r = EXDEV;
+
+		ndir = ((new_ip->i_mode & I_TYPE) == I_DIRECTORY); /* dir ? */
+		if (odir == TRUE && ndir == FALSE) r = ENOTDIR;
+		if (odir == FALSE && ndir == TRUE) r = EISDIR;
+	}
+  }
+
+  /* If a process has another root directory than the system root, we might
+   * "accidently" be moving it's working directory to a place where it's
+   * root directory isn't a super directory of it anymore. This can make
+   * the function chroot useless. If chroot will be used often we should
+   * probably check for it here.
+   */
+
+  /* The rename will probably work. Only two things can go wrong now:
+   * 1. being unable to remove the new file. (when new file already exists)
+   * 2. being unable to make the new directory entry. (new file doesn't exists)
+   *     [directory has to grow by one block and cannot because the disk
+   *      is completely full].
+   */
+  if (r == OK) {
+	if (new_ip != NIL_INODE) {
+		  /* There is already an entry for 'new'. Try to remove it. */
+		if (odir) 
+			r = remove_dir(new_dirp, new_ip, new_name);
+		else 
+			r = unlink_file(new_dirp, new_ip, new_name);
+	}
+	/* if r is OK, the rename will succeed, while there is now an
+	 * unused entry in the new parent directory.
+	 */
+  }
+
+  if (r == OK) {
+	/* If the new name will be in the same parent directory as the old one,
+	 * first remove the old name to free an entry for the new name,
+	 * otherwise first try to create the new name entry to make sure
+	 * the rename will succeed.
+	 */
+	numb = old_ip->i_num;		/* inode number of old file */
+
+  	if (same_pdir) {
+		r = search_dir(old_dirp, old_name, (ino_t *) 0, DELETE);
+						/* shouldn't go wrong. */
+		if (r==OK) (void) search_dir(old_dirp, new_name, &numb, ENTER);
+	} else {
+		r = search_dir(new_dirp, new_name, &numb, ENTER);
+		if (r == OK)
+		    (void) search_dir(old_dirp, old_name, (ino_t *) 0, DELETE);
+	}
+  }
+  /* If r is OK, the ctime and mtime of old_dirp and new_dirp have been marked
+   * for update in search_dir.
+   */
+
+  if (r == OK && odir && !same_pdir) {
+	/* Update the .. entry in the directory (still points to old_dirp). */
+	numb = new_dirp->i_num;
+	(void) unlink_file(old_ip, NIL_INODE, dot2);
+	if (search_dir(old_ip, dot2, &numb, ENTER) == OK) {
+		/* New link created. */
+		new_dirp->i_nlinks++;
+		new_dirp->i_dirt = DIRTY;
+	}
+  }
+	
+  /* Release the inodes. */
+  put_inode(old_dirp);
+  put_inode(old_ip);
+  put_inode(new_dirp);
+  put_inode(new_ip);
+  return(r == SAME ? OK : r);
+}
+
+/*===========================================================================*
+ *				do_truncate				     *
+ *===========================================================================*/
+PUBLIC int do_truncate()
+{
+/* truncate_inode() does the actual work of do_truncate() and do_ftruncate().
+ * do_truncate() and do_ftruncate() have to get hold of the inode, either
+ * by name or fd, do checks on it, and call truncate_inode() to do the
+ * work.
+ */
+	int r;
+	struct inode *rip;	/* pointer to inode to be truncated */
+
+	if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK)
+		return err_code;
+	if( (rip = eat_path(user_path)) == NIL_INODE)
+		return err_code;
+	if ( (rip->i_mode & I_TYPE) != I_REGULAR)
+		r = EINVAL;
+	else
+		r = truncate_inode(rip, m_in.m2_l1); 
+	put_inode(rip);
+
+	return r;
+}
+
+/*===========================================================================*
+ *				do_ftruncate				     *
+ *===========================================================================*/
+PUBLIC int do_ftruncate()
+{
+/* As with do_truncate(), truncate_inode() does the actual work. */
+	struct filp *rfilp;
+	if ( (rfilp = get_filp(m_in.m2_i1)) == NIL_FILP)
+		return err_code;
+	if ( (rfilp->filp_ino->i_mode & I_TYPE) != I_REGULAR)
+		return EINVAL;
+	return truncate_inode(rfilp->filp_ino, m_in.m2_l1);
+}
+
+/*===========================================================================*
+ *				truncate_inode				     *
+ *===========================================================================*/
+PUBLIC int truncate_inode(rip, newsize)
+register struct inode *rip;	/* pointer to inode to be truncated */
+off_t newsize;			/* inode must become this size */
+{
+/* Set inode to a certain size, freeing any zones no longer referenced
+ * and updating the size in the inode. If the inode is extended, the
+ * extra space is a hole that reads as zeroes.
+ *
+ * Nothing special has to happen to file pointers if inode is opened in
+ * O_APPEND mode, as this is different per fd and is checked when 
+ * writing is done.
+ */
+  zone_t zone_size;
+  int scale, file_type, waspipe;
+  dev_t dev;
+
+  file_type = rip->i_mode & I_TYPE;	/* check to see if file is special */
+  if (file_type == I_CHAR_SPECIAL || file_type == I_BLOCK_SPECIAL)
+	return EINVAL;
+  if(newsize > rip->i_sp->s_max_size)	/* don't let inode grow too big */
+	return EFBIG;
+
+  dev = rip->i_dev;		/* device on which inode resides */
+  scale = rip->i_sp->s_log_zone_size;
+  zone_size = (zone_t) rip->i_sp->s_block_size << scale;
+
+  /* Pipes can shrink, so adjust size to make sure all zones are removed. */
+  waspipe = rip->i_pipe == I_PIPE;	/* TRUE if this was a pipe */
+  if (waspipe) {
+	if(newsize != 0)
+		return EINVAL;	/* Only truncate pipes to 0. */
+	rip->i_size = PIPE_SIZE(rip->i_sp->s_block_size);
+  }
+
+  /* Free the actual space if relevant. */
+  if(newsize < rip->i_size)
+	  freesp_inode(rip, newsize, rip->i_size);
+
+  /* Next correct the inode size. */
+  if(!waspipe) rip->i_size = newsize;
+  else wipe_inode(rip);	/* Pipes can only be truncated to 0. */
+  rip->i_dirt = DIRTY;
+
+  return OK;
+}
+
+/*===========================================================================*
+ *				freesp_inode				     *
+ *===========================================================================*/
+PUBLIC int freesp_inode(rip, start, end)
+register struct inode *rip;	/* pointer to inode to be partly freed */
+off_t start, end;		/* range of bytes to free (end uninclusive) */
+{
+/* Cut an arbitrary hole in an inode. The caller is responsible for checking
+ * the reasonableness of the inode type of rip. The reason is this is that
+ * this function can be called for different reasons, for which different
+ * sets of inode types are reasonable. Adjusting the final size of the inode
+ * is to be done by the caller too, if wished.
+ *
+ * Consumers of this function currently are truncate_inode() (used to
+ * free indirect and data blocks for any type of inode, but also to
+ * implement the ftruncate() and truncate() system calls) and the F_FREESP
+ * fcntl().
+ */
+	off_t p, e;
+	int zone_size, dev;
+
+	if(end > rip->i_size)		/* freeing beyond end makes no sense */
+		end = rip->i_size;
+	if(end <= start)		/* end is uninclusive, so start<end */
+		return EINVAL;
+        zone_size = rip->i_sp->s_block_size << rip->i_sp->s_log_zone_size;
+	dev = rip->i_dev;             /* device on which inode resides */
+
+	/* If freeing doesn't cross a zone boundary, then we may only zero
+	 * a range of the block.
+	 */
+	if(start/zone_size == (end-1)/zone_size) {
+		zeroblock_range(rip, start, end-start);
+	} else { 
+		/* First zero unused part of partly used blocks. */
+		if(start%zone_size)
+			zeroblock_half(rip, start, LAST_HALF);
+		if(end%zone_size && end < rip->i_size)
+			zeroblock_half(rip, end, FIRST_HALF);
+	}
+
+	/* Now completely free the completely unused blocks.
+	 * write_map() will free unused (double) indirect
+	 * blocks too. Converting the range to zone numbers avoids
+	 * overflow on p when doing e.g. 'p += zone_size'.
+	 */
+	e = end/zone_size;
+	if(end == rip->i_size && (end % zone_size)) e++;
+	for(p = nextblock(start, zone_size)/zone_size; p < e; p ++)
+		write_map(rip, p*zone_size, NO_ZONE, WMAP_FREE);
+
+	return OK;
+}
+
+/*===========================================================================*
+ *				nextblock				     *
+ *===========================================================================*/
+PRIVATE off_t nextblock(pos, zone_size)
+off_t pos;
+int zone_size;
+{
+/* Return the first position in the next block after position 'pos'
+ * (unless this is the first position in the current block).
+ * This can be done in one expression, but that can overflow pos.
+ */
+	off_t p;
+	p = (pos/zone_size)*zone_size;
+	if((pos % zone_size)) p += zone_size;	/* Round up. */
+	return p;
+}
+
+/*===========================================================================*
+ *				zeroblock_half				     *
+ *===========================================================================*/
+PRIVATE void zeroblock_half(rip, pos, half)
+struct inode *rip;
+off_t pos;
+int half;
+{
+/* Zero the upper or lower 'half' of a block that holds position 'pos'.
+ * half can be FIRST_HALF or LAST_HALF.
+ *
+ * FIRST_HALF: 0..pos-1 will be zeroed
+ * LAST_HALF:  pos..blocksize-1 will be zeroed
+ */
+	int offset, len;
+
+	 /* Offset of zeroing boundary. */
+	 offset = pos % rip->i_sp->s_block_size;
+
+	 if(half == LAST_HALF)  {
+	   	len = rip->i_sp->s_block_size - offset;
+	 } else {
+		len = offset;
+		pos -= offset;
+		offset = 0;
+	 }
+
+	zeroblock_range(rip, pos, len);
+}
+
+/*===========================================================================*
+ *				zeroblock_range				     *
+ *===========================================================================*/
+PRIVATE void zeroblock_range(rip, pos, len)
+struct inode *rip;
+off_t pos;
+off_t len;
+{
+/* Zero a range in a block.
+ * This function is used to zero a segment of a block, either 
+ * FIRST_HALF of LAST_HALF.
+ * 
+ */
+	block_t b;
+	struct buf *bp;
+	off_t offset;
+
+	if(!len) return; /* no zeroing to be done. */
+	if( (b = read_map(rip, pos)) == NO_BLOCK) return;
+	if( (bp = get_block(rip->i_dev, b, NORMAL)) == NIL_BUF)
+	   panic(__FILE__, "zeroblock_range: no block", NO_NUM);
+	offset = pos % rip->i_sp->s_block_size;
+	if(offset + len > rip->i_sp->s_block_size)
+	   panic(__FILE__, "zeroblock_range: len too long", len);
+	memset(bp->b_data + offset, 0, len);
+	bp->b_dirt = DIRTY;
+	put_block(bp, FULL_DATA_BLOCK);
+}
+
+/*===========================================================================*
+ *				remove_dir				     *
+ *===========================================================================*/
+PRIVATE int remove_dir(rldirp, rip, dir_name)
+struct inode *rldirp;		 	/* parent directory */
+struct inode *rip;			/* directory to be removed */
+char dir_name[NAME_MAX];		/* name of directory to be removed */
+{
+  /* A directory file has to be removed. Five conditions have to met:
+   * 	- The file must be a directory
+   *	- The directory must be empty (except for . and ..)
+   *	- The final component of the path must not be . or ..
+   *	- The directory must not be the root of a mounted file system
+   *	- The directory must not be anybody's root/working directory
+   */
+
+  int r;
+  register struct fproc *rfp;
+
+  /* search_dir checks that rip is a directory too. */
+  if ((r = search_dir(rip, "", (ino_t *) 0, IS_EMPTY)) != OK) return r;
+
+  if (strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0)return(EINVAL);
+  if (rip->i_num == ROOT_INODE) return(EBUSY); /* can't remove 'root' */
+  
+  for (rfp = &fproc[INIT_PROC_NR + 1]; rfp < &fproc[NR_PROCS]; rfp++)
+	if (rfp->fp_pid != PID_FREE &&
+	     (rfp->fp_workdir == rip || rfp->fp_rootdir == rip))
+		return(EBUSY); /* can't remove anybody's working dir */
+
+  /* Actually try to unlink the file; fails if parent is mode 0 etc. */
+  if ((r = unlink_file(rldirp, rip, dir_name)) != OK) return r;
+
+  /* Unlink . and .. from the dir. The super user can link and unlink any dir,
+   * so don't make too many assumptions about them.
+   */
+  (void) unlink_file(rip, NIL_INODE, dot1);
+  (void) unlink_file(rip, NIL_INODE, dot2);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				unlink_file				     *
+ *===========================================================================*/
+PRIVATE int unlink_file(dirp, rip, file_name)
+struct inode *dirp;		/* parent directory of file */
+struct inode *rip;		/* inode of file, may be NIL_INODE too. */
+char file_name[NAME_MAX];	/* name of file to be removed */
+{
+/* Unlink 'file_name'; rip must be the inode of 'file_name' or NIL_INODE. */
+
+  ino_t numb;			/* inode number */
+  int	r;
+
+  /* If rip is not NIL_INODE, it is used to get faster access to the inode. */
+  if (rip == NIL_INODE) {
+  	/* Search for file in directory and try to get its inode. */
+	err_code = search_dir(dirp, file_name, &numb, LOOK_UP);
+	if (err_code == OK) rip = get_inode(dirp->i_dev, (int) numb);
+	if (err_code != OK || rip == NIL_INODE) return(err_code);
+  } else {
+	dup_inode(rip);		/* inode will be returned with put_inode */
+  }
+
+  r = search_dir(dirp, file_name, (ino_t *) 0, DELETE);
+
+  if (r == OK) {
+	rip->i_nlinks--;	/* entry deleted from parent's dir */
+	rip->i_update |= CTIME;
+	rip->i_dirt = DIRTY;
+  }
+
+  put_inode(rip);
+  return(r);
+}
Index: /trunk/minix/servers/fs/lock.c
===================================================================
--- /trunk/minix/servers/fs/lock.c	(revision 9)
+++ /trunk/minix/servers/fs/lock.c	(revision 9)
@@ -0,0 +1,186 @@
+/* This file handles advisory file locking as required by POSIX.
+ *
+ * The entry points into this file are
+ *   lock_op:	perform locking operations for FCNTL system call
+ *   lock_revive: revive processes when a lock is released
+ */
+
+#include "fs.h"
+#include <minix/com.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "lock.h"
+#include "param.h"
+
+/*===========================================================================*
+ *				lock_op					     *
+ *===========================================================================*/
+PUBLIC int lock_op(f, req)
+struct filp *f;
+int req;			/* either F_SETLK or F_SETLKW */
+{
+/* Perform the advisory locking required by POSIX. */
+
+  int r, ltype, i, conflict = 0, unlocking = 0;
+  mode_t mo;
+  off_t first, last;
+  struct flock flock;
+  vir_bytes user_flock;
+  struct file_lock *flp, *flp2, *empty;
+
+  /* Fetch the flock structure from user space. */
+  user_flock = (vir_bytes) m_in.name1;
+  r = sys_datacopy(who_e, (vir_bytes) user_flock,
+	FS_PROC_NR, (vir_bytes) &flock, (phys_bytes) sizeof(flock));
+  if (r != OK) return(EINVAL);
+
+  /* Make some error checks. */
+  ltype = flock.l_type;
+  mo = f->filp_mode;
+  if (ltype != F_UNLCK && ltype != F_RDLCK && ltype != F_WRLCK) return(EINVAL);
+  if (req == F_GETLK && ltype == F_UNLCK) return(EINVAL);
+  if ( (f->filp_ino->i_mode & I_TYPE) != I_REGULAR) return(EINVAL);
+  if (req != F_GETLK && ltype == F_RDLCK && (mo & R_BIT) == 0) return(EBADF);
+  if (req != F_GETLK && ltype == F_WRLCK && (mo & W_BIT) == 0) return(EBADF);
+
+  /* Compute the first and last bytes in the lock region. */
+  switch (flock.l_whence) {
+	case SEEK_SET:	first = 0; break;
+	case SEEK_CUR:	first = f->filp_pos; break;
+	case SEEK_END:	first = f->filp_ino->i_size; break;
+	default:	return(EINVAL);
+  }
+  /* Check for overflow. */
+  if (((long)flock.l_start > 0) && ((first + flock.l_start) < first))
+	return(EINVAL);
+  if (((long)flock.l_start < 0) && ((first + flock.l_start) > first))
+	return(EINVAL);
+  first = first + flock.l_start;
+  last = first + flock.l_len - 1;
+  if (flock.l_len == 0) last = MAX_FILE_POS;
+  if (last < first) return(EINVAL);
+
+  /* Check if this region conflicts with any existing lock. */
+  empty = (struct file_lock *) 0;
+  for (flp = &file_lock[0]; flp < & file_lock[NR_LOCKS]; flp++) {
+	if (flp->lock_type == 0) {
+		if (empty == (struct file_lock *) 0) empty = flp;
+		continue;	/* 0 means unused slot */
+	}
+	if (flp->lock_inode != f->filp_ino) continue;	/* different file */
+	if (last < flp->lock_first) continue;	/* new one is in front */
+	if (first > flp->lock_last) continue;	/* new one is afterwards */
+	if (ltype == F_RDLCK && flp->lock_type == F_RDLCK) continue;
+	if (ltype != F_UNLCK && flp->lock_pid == fp->fp_pid) continue;
+  
+	/* There might be a conflict.  Process it. */
+	conflict = 1;
+	if (req == F_GETLK) break;
+
+	/* If we are trying to set a lock, it just failed. */
+	if (ltype == F_RDLCK || ltype == F_WRLCK) {
+		if (req == F_SETLK) {
+			/* For F_SETLK, just report back failure. */
+			return(EAGAIN);
+		} else {
+			/* For F_SETLKW, suspend the process. */
+			suspend(XLOCK);
+			return(SUSPEND);
+		}
+	}
+
+	/* We are clearing a lock and we found something that overlaps. */
+	unlocking = 1;
+	if (first <= flp->lock_first && last >= flp->lock_last) {
+		flp->lock_type = 0;	/* mark slot as unused */
+		nr_locks--;		/* number of locks is now 1 less */
+		continue;
+	}
+
+	/* Part of a locked region has been unlocked. */
+	if (first <= flp->lock_first) {
+		flp->lock_first = last + 1;
+		continue;
+	}
+
+	if (last >= flp->lock_last) {
+		flp->lock_last = first - 1;
+		continue;
+	}
+	
+	/* Bad luck. A lock has been split in two by unlocking the middle. */
+	if (nr_locks == NR_LOCKS) return(ENOLCK);
+	for (i = 0; i < NR_LOCKS; i++)
+		if (file_lock[i].lock_type == 0) break;
+	flp2 = &file_lock[i];
+	flp2->lock_type = flp->lock_type;
+	flp2->lock_pid = flp->lock_pid;
+	flp2->lock_inode = flp->lock_inode;
+	flp2->lock_first = last + 1;
+	flp2->lock_last = flp->lock_last;
+	flp->lock_last = first - 1;
+	nr_locks++;
+  }
+  if (unlocking) lock_revive();
+
+  if (req == F_GETLK) {
+	if (conflict) {
+		/* GETLK and conflict. Report on the conflicting lock. */
+		flock.l_type = flp->lock_type;
+		flock.l_whence = SEEK_SET;
+		flock.l_start = flp->lock_first;
+		flock.l_len = flp->lock_last - flp->lock_first + 1;
+		flock.l_pid = flp->lock_pid;
+
+	} else {
+		/* It is GETLK and there is no conflict. */
+		flock.l_type = F_UNLCK;
+	}
+
+	/* Copy the flock structure back to the caller. */
+	r = sys_datacopy(FS_PROC_NR, (vir_bytes) &flock,
+		who_e, (vir_bytes) user_flock, (phys_bytes) sizeof(flock));
+	return(r);
+  }
+
+  if (ltype == F_UNLCK) return(OK);	/* unlocked a region with no locks */
+
+  /* There is no conflict.  If space exists, store new lock in the table. */
+  if (empty == (struct file_lock *) 0) return(ENOLCK);	/* table full */
+  empty->lock_type = ltype;
+  empty->lock_pid = fp->fp_pid;
+  empty->lock_inode = f->filp_ino;
+  empty->lock_first = first;
+  empty->lock_last = last;
+  nr_locks++;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				lock_revive				     *
+ *===========================================================================*/
+PUBLIC void lock_revive()
+{
+/* Go find all the processes that are waiting for any kind of lock and 
+ * revive them all.  The ones that are still blocked will block again when 
+ * they run.  The others will complete.  This strategy is a space-time 
+ * tradeoff.  Figuring out exactly which ones to unblock now would take 
+ * extra code, and the only thing it would win would be some performance in 
+ * extremely rare circumstances (namely, that somebody actually used 
+ * locking).
+ */
+
+  int task;
+  struct fproc *fptr;
+
+  for (fptr = &fproc[INIT_PROC_NR + 1]; fptr < &fproc[NR_PROCS]; fptr++){
+	if(fptr->fp_pid == PID_FREE) continue;
+	task = -fptr->fp_task;
+	if (fptr->fp_suspended == SUSPENDED && task == XLOCK) {
+		revive(fptr->fp_endpoint, 0);
+	}
+  }
+}
Index: /trunk/minix/servers/fs/lock.h
===================================================================
--- /trunk/minix/servers/fs/lock.h	(revision 9)
+++ /trunk/minix/servers/fs/lock.h	(revision 9)
@@ -0,0 +1,10 @@
+/* This is the file locking table.  Like the filp table, it points to the
+ * inode table, however, in this case to achieve advisory locking.
+ */
+EXTERN struct file_lock {
+  short lock_type;		/* F_RDLOCK or F_WRLOCK; 0 means unused slot */
+  pid_t lock_pid;		/* pid of the process holding the lock */
+  struct inode *lock_inode;	/* pointer to the inode locked */
+  off_t lock_first;		/* offset of first byte locked */
+  off_t lock_last;		/* offset of last byte locked */
+} file_lock[NR_LOCKS];
Index: /trunk/minix/servers/fs/main.c
===================================================================
--- /trunk/minix/servers/fs/main.c	(revision 9)
+++ /trunk/minix/servers/fs/main.c	(revision 9)
@@ -0,0 +1,293 @@
+/* This file contains the main program of the File System.  It consists of
+ * a loop that gets messages requesting work, carries out the work, and sends
+ * replies.
+ *
+ * The entry points into this file are:
+ *   main:	main program of the File System
+ *   reply:	send a reply to a process after the requested work is done
+ *
+ */
+
+struct super_block;		/* proto.h needs to know this */
+
+#include "fs.h"
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/ioc_memory.h>
+#include <sys/svrctl.h>
+#include <sys/select.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/keymap.h>
+#include <minix/const.h>
+#include <minix/endpoint.h>
+#include "buf.h"
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "param.h"
+#include "super.h"
+
+FORWARD _PROTOTYPE( void fs_init, (void)				);
+FORWARD _PROTOTYPE( void get_work, (void)				);
+FORWARD _PROTOTYPE( void init_root, (void)				);
+
+/*===========================================================================*
+ *				main					     *
+ *===========================================================================*/
+PUBLIC int main()
+{
+/* This is the main program of the file system.  The main loop consists of
+ * three major activities: getting new work, processing the work, and sending
+ * the reply.  This loop never terminates as long as the file system runs.
+ */
+  int error;
+
+  fs_init();
+
+
+  /* This is the main loop that gets work, processes it, and sends replies. */
+  while (TRUE) {
+	get_work();		/* sets who and call_nr */
+	fp = &fproc[who_p];	/* pointer to proc table struct */
+	super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE);   /* su? */
+
+ 	/* Check for special control messages first. */
+	if (call_nr == PROC_EVENT) {
+		/* Assume FS got signal. Synchronize, but don't exit. */
+		do_sync();
+        } else if (call_nr == SYN_ALARM) {
+        	/* Alarm timer expired. Used only for select(). Check it. */
+        	fs_expire_timers(m_in.NOTIFY_TIMESTAMP);
+        } else if ((call_nr & NOTIFY_MESSAGE)) {
+        	/* Device notifies us of an event. */
+        	dev_status(&m_in);
+        } else {
+		/* Call the internal function that does the work. */
+		if (call_nr < 0 || call_nr >= NCALLS) { 
+			error = ENOSYS;
+		/* Not supposed to happen. */
+			printf("FS, warning illegal %d system call by %d\n", call_nr, who_e);
+		} else if (fp->fp_pid == PID_FREE) {
+			error = ENOSYS;
+			printf("FS, bad process, who = %d, call_nr = %d, endpt1 = %d\n",
+				 who_e, call_nr, m_in.endpt1);
+		} else {
+			error = (*call_vec[call_nr])();
+		}
+
+		/* Copy the results back to the user and send reply. */
+		if (error != SUSPEND) { reply(who_e, error); }
+		if (rdahed_inode != NIL_INODE) {
+			read_ahead(); /* do block read ahead */
+		}
+	}
+  }
+  return(OK);				/* shouldn't come here */
+}
+
+/*===========================================================================*
+ *				get_work				     *
+ *===========================================================================*/
+PRIVATE void get_work()
+{  
+  /* Normally wait for new input.  However, if 'reviving' is
+   * nonzero, a suspended process must be awakened.
+   */
+  register struct fproc *rp;
+
+  if (reviving != 0) {
+	/* Revive a suspended process. */
+	for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++) 
+		if (rp->fp_pid != PID_FREE && rp->fp_revived == REVIVING) {
+			who_p = (int)(rp - fproc);
+			who_e = rp->fp_endpoint;
+			call_nr = rp->fp_fd & BYTE;
+			m_in.fd = (rp->fp_fd >>8) & BYTE;
+			m_in.buffer = rp->fp_buffer;
+			m_in.nbytes = rp->fp_nbytes;
+			rp->fp_suspended = NOT_SUSPENDED; /*no longer hanging*/
+			rp->fp_revived = NOT_REVIVING;
+			reviving--;
+			return;
+		}
+	panic(__FILE__,"get_work couldn't revive anyone", NO_NUM);
+  }
+
+  for(;;) {
+    /* Normal case.  No one to revive. */
+    if (receive(ANY, &m_in) != OK)
+	panic(__FILE__,"fs receive error", NO_NUM);
+    who_e = m_in.m_source;
+    who_p = _ENDPOINT_P(who_e);
+    if(who_p < -NR_TASKS || who_p >= NR_PROCS)
+     	panic(__FILE__,"receive process out of range", who_p);
+    if(who_p >= 0 && fproc[who_p].fp_endpoint == NONE) {
+    	printf("FS: ignoring request from %d, endpointless slot %d (%d)\n",
+		m_in.m_source, who_p, m_in.m_type);
+	continue;
+    }
+    if(who_p >= 0 && fproc[who_p].fp_endpoint != who_e) {
+    	printf("FS: receive endpoint inconsistent (%d, %d, %d).\n",
+		who_e, fproc[who_p].fp_endpoint, who_e);
+	panic(__FILE__, "FS: inconsistent endpoint ", NO_NUM);
+	continue;
+    }
+    call_nr = m_in.m_type;
+    return;
+  }
+}
+
+/*===========================================================================*
+ *				buf_pool				     *
+ *===========================================================================*/
+PRIVATE void buf_pool(void)
+{
+/* Initialize the buffer pool. */
+
+  register struct buf *bp;
+
+  bufs_in_use = 0;
+  front = &buf[0];
+  rear = &buf[NR_BUFS - 1];
+
+  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) {
+	bp->b_blocknr = NO_BLOCK;
+	bp->b_dev = NO_DEV;
+	bp->b_next = bp + 1;
+	bp->b_prev = bp - 1;
+  }
+  buf[0].b_prev = NIL_BUF;
+  buf[NR_BUFS - 1].b_next = NIL_BUF;
+
+  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) bp->b_hash = bp->b_next;
+  buf_hash[0] = front;
+
+}
+
+/*===========================================================================*
+ *				reply					     *
+ *===========================================================================*/
+PUBLIC void reply(whom, result)
+int whom;			/* process to reply to */
+int result;			/* result of the call (usually OK or error #) */
+{
+/* Send a reply to a user process.  If the send fails, just ignore it. */
+  int s;
+  m_out.reply_type = result;
+  s = send(whom, &m_out);
+  if (s != OK) printf("FS: couldn't send reply %d to %d: %d\n",
+	result, whom, s);
+}
+
+/*===========================================================================*
+ *				fs_init					     *
+ *===========================================================================*/
+PRIVATE void fs_init()
+{
+/* Initialize global variables, tables, etc. */
+  register struct inode *rip;
+  register struct fproc *rfp;
+  message mess;
+  int s;
+
+  /* Initialize the process table with help of the process manager messages. 
+   * Expect one message for each system process with its slot number and pid. 
+   * When no more processes follow, the magic process number NONE is sent. 
+   * Then, stop and synchronize with the PM.
+   */
+  do {
+  	if (OK != (s=receive(PM_PROC_NR, &mess)))
+  		panic(__FILE__,"FS couldn't receive from PM", s);
+  	if (NONE == mess.PR_ENDPT) break; 
+
+	rfp = &fproc[mess.PR_SLOT];
+	rfp->fp_pid = mess.PR_PID;
+	rfp->fp_endpoint = mess.PR_ENDPT;
+	rfp->fp_realuid = (uid_t) SYS_UID;
+	rfp->fp_effuid = (uid_t) SYS_UID;
+	rfp->fp_realgid = (gid_t) SYS_GID;
+	rfp->fp_effgid = (gid_t) SYS_GID;
+	rfp->fp_umask = ~0;
+   
+  } while (TRUE);			/* continue until process NONE */
+  mess.m_type = OK;			/* tell PM that we succeeded */
+  s=send(PM_PROC_NR, &mess);		/* send synchronization message */
+
+  /* All process table entries have been set. Continue with FS initialization.
+   * Certain relations must hold for the file system to work at all. Some 
+   * extra block_size requirements are checked at super-block-read-in time.
+   */
+  if (OPEN_MAX > 127) panic(__FILE__,"OPEN_MAX > 127", NO_NUM);
+  if (NR_BUFS < 6) panic(__FILE__,"NR_BUFS < 6", NO_NUM);
+  if (V1_INODE_SIZE != 32) panic(__FILE__,"V1 inode size != 32", NO_NUM);
+  if (V2_INODE_SIZE != 64) panic(__FILE__,"V2 inode size != 64", NO_NUM);
+  if (OPEN_MAX > 8 * sizeof(long))
+  	 panic(__FILE__,"Too few bits in fp_cloexec", NO_NUM);
+
+  /* The following initializations are needed to let dev_opcl succeed .*/
+  fp = (struct fproc *) NULL;
+  who_e = who_p = FS_PROC_NR;
+
+  buf_pool();			/* initialize buffer pool */
+  build_dmap();			/* build device table and map boot driver */
+  init_root();			/* init root device and load super block */
+  init_select();		/* init select() structures */
+
+  /* The root device can now be accessed; set process directories. */
+  for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
+	FD_ZERO(&(rfp->fp_filp_inuse));
+  	if (rfp->fp_pid != PID_FREE) {
+		rip = get_inode(root_dev, ROOT_INODE);
+		dup_inode(rip);
+		rfp->fp_rootdir = rip;
+		rfp->fp_workdir = rip;
+  	} else  rfp->fp_endpoint = NONE;
+  }
+}
+
+/*===========================================================================*
+ *				init_root				     *
+ *===========================================================================*/
+PRIVATE void init_root()
+{
+  int bad;
+  register struct super_block *sp;
+  register struct inode *rip = NIL_INODE;
+  int s;
+
+  /* Open the root device. */
+  root_dev = DEV_IMGRD;
+  if ((s=dev_open(root_dev, FS_PROC_NR, R_BIT|W_BIT)) != OK)
+	panic(__FILE__,"Cannot open root device", s);
+
+#if ENABLE_CACHE2
+  /* The RAM disk is a second level block cache while not otherwise used. */
+  init_cache2(ram_size);
+#endif
+
+  /* Initialize the super_block table. */
+  for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
+  	sp->s_dev = NO_DEV;
+
+  /* Read in super_block for the root file system. */
+  sp = &super_block[0];
+  sp->s_dev = root_dev;
+
+  /* Check super_block for consistency. */
+  bad = (read_super(sp) != OK);
+  if (!bad) {
+	rip = get_inode(root_dev, ROOT_INODE);	/* inode for root dir */
+	if ( (rip->i_mode & I_TYPE) != I_DIRECTORY || rip->i_nlinks < 3) bad++;
+  }
+  if (bad) panic(__FILE__,"Invalid root file system", NO_NUM);
+
+  sp->s_imount = rip;
+  dup_inode(rip);
+  sp->s_isup = rip;
+  sp->s_rd_only = 0;
+  return;
+}
Index: /trunk/minix/servers/fs/misc.c
===================================================================
--- /trunk/minix/servers/fs/misc.c	(revision 9)
+++ /trunk/minix/servers/fs/misc.c	(revision 9)
@@ -0,0 +1,590 @@
+/* This file contains a collection of miscellaneous procedures.  Some of them
+ * perform simple system calls.  Some others do a little part of system calls
+ * that are mostly performed by the Memory Manager.
+ *
+ * The entry points into this file are
+ *   do_dup:	  perform the DUP system call
+ *   do_fcntl:	  perform the FCNTL system call
+ *   do_sync:	  perform the SYNC system call
+ *   do_fsync:	  perform the FSYNC system call
+ *   do_reboot:	  sync disks and prepare for shutdown
+ *   do_fork:	  adjust the tables after MM has performed a FORK system call
+ *   do_exec:	  handle files with FD_CLOEXEC on after MM has done an EXEC
+ *   do_exit:	  a process has exited; note that in the tables
+ *   do_set:	  set uid or gid for some process
+ *   do_revive:	  revive a process that was waiting for something (e.g. TTY)
+ *   do_svrctl:	  file system control
+ *   do_getsysinfo:	request copy of FS data structure
+ */
+
+#include "fs.h"
+#include <fcntl.h>
+#include <unistd.h>	/* cc runs out of memory with unistd.h :-( */
+#include <minix/callnr.h>
+#include <minix/endpoint.h>
+#include <minix/com.h>
+#include <sys/svrctl.h>
+#include "buf.h"
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "param.h"
+#include "super.h"
+
+FORWARD _PROTOTYPE( int free_proc, (struct fproc *freed, int flags));
+
+#define FP_EXITING	1
+
+/*===========================================================================*
+ *				do_getsysinfo				     *
+ *===========================================================================*/
+PUBLIC int do_getsysinfo()
+{
+  struct fproc *proc_addr;
+  vir_bytes src_addr, dst_addr;
+  size_t len;
+  int s;
+
+  switch(m_in.info_what) {
+  case SI_PROC_ADDR:
+  	proc_addr = &fproc[0];
+  	src_addr = (vir_bytes) &proc_addr;
+  	len = sizeof(struct fproc *);
+  	break; 
+  case SI_PROC_TAB:
+  	src_addr = (vir_bytes) fproc;
+  	len = sizeof(struct fproc) * NR_PROCS;
+  	break; 
+  case SI_DMAP_TAB:
+  	src_addr = (vir_bytes) dmap;
+  	len = sizeof(struct dmap) * NR_DEVICES;
+  	break; 
+  default:
+  	return(EINVAL);
+  }
+
+  dst_addr = (vir_bytes) m_in.info_where;
+  if (OK != (s=sys_datacopy(SELF, src_addr, who_e, dst_addr, len)))
+  	return(s);
+  return(OK);
+
+}
+
+/*===========================================================================*
+ *				do_dup					     *
+ *===========================================================================*/
+PUBLIC int do_dup()
+{
+/* Perform the dup(fd) or dup2(fd,fd2) system call. These system calls are
+ * obsolete.  In fact, it is not even possible to invoke them using the
+ * current library because the library routines call fcntl().  They are
+ * provided to permit old binary programs to continue to run.
+ */
+
+  register int rfd;
+  register struct filp *f;
+  struct filp *dummy;
+  int r;
+
+  /* Is the file descriptor valid? */
+  rfd = m_in.fd & ~DUP_MASK;		/* kill off dup2 bit, if on */
+  if ((f = get_filp(rfd)) == NIL_FILP) return(err_code);
+
+  /* Distinguish between dup and dup2. */
+  if (m_in.fd == rfd) {			/* bit not on */
+	/* dup(fd) */
+	if ( (r = get_fd(0, 0, &m_in.fd2, &dummy)) != OK) return(r);
+  } else {
+	/* dup2(fd, fd2) */
+	if (m_in.fd2 < 0 || m_in.fd2 >= OPEN_MAX) return(EBADF);
+	if (rfd == m_in.fd2) return(m_in.fd2);	/* ignore the call: dup2(x, x) */
+	m_in.fd = m_in.fd2;		/* prepare to close fd2 */
+	(void) do_close();	/* cannot fail */
+  }
+
+  /* Success. Set up new file descriptors. */
+  f->filp_count++;
+  fp->fp_filp[m_in.fd2] = f;
+  FD_SET(m_in.fd2, &fp->fp_filp_inuse);
+  return(m_in.fd2);
+}
+
+/*===========================================================================*
+ *				do_fcntl				     *
+ *===========================================================================*/
+PUBLIC int do_fcntl()
+{
+/* Perform the fcntl(fd, request, ...) system call. */
+
+  register struct filp *f;
+  int new_fd, r, fl;
+  long cloexec_mask;		/* bit map for the FD_CLOEXEC flag */
+  long clo_value;		/* FD_CLOEXEC flag in proper position */
+  struct filp *dummy;
+
+  /* Is the file descriptor valid? */
+  if ((f = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
+
+  switch (m_in.request) {
+     case F_DUPFD:
+	/* This replaces the old dup() system call. */
+	if (m_in.addr < 0 || m_in.addr >= OPEN_MAX) return(EINVAL);
+	if ((r = get_fd(m_in.addr, 0, &new_fd, &dummy)) != OK) return(r);
+	f->filp_count++;
+	fp->fp_filp[new_fd] = f;
+	return(new_fd);
+
+     case F_GETFD:
+	/* Get close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
+	return( ((fp->fp_cloexec >> m_in.fd) & 01) ? FD_CLOEXEC : 0);
+
+     case F_SETFD:
+	/* Set close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
+	cloexec_mask = 1L << m_in.fd;	/* singleton set position ok */
+	clo_value = (m_in.addr & FD_CLOEXEC ? cloexec_mask : 0L);
+	fp->fp_cloexec = (fp->fp_cloexec & ~cloexec_mask) | clo_value;
+	return(OK);
+
+     case F_GETFL:
+	/* Get file status flags (O_NONBLOCK and O_APPEND). */
+	fl = f->filp_flags & (O_NONBLOCK | O_APPEND | O_ACCMODE);
+	return(fl);	
+
+     case F_SETFL:
+	/* Set file status flags (O_NONBLOCK and O_APPEND). */
+	fl = O_NONBLOCK | O_APPEND;
+	f->filp_flags = (f->filp_flags & ~fl) | (m_in.addr & fl);
+	return(OK);
+
+     case F_GETLK:
+     case F_SETLK:
+     case F_SETLKW:
+	/* Set or clear a file lock. */
+	r = lock_op(f, m_in.request);
+	return(r);
+
+     case F_FREESP:
+     {
+	/* Free a section of a file. Preparation is done here,
+	 * actual freeing in freesp_inode().
+	 */
+	off_t start, end;
+	struct flock flock_arg;
+	signed long offset;
+
+	/* Check if it's a regular file. */
+	if((f->filp_ino->i_mode & I_TYPE) != I_REGULAR) {
+		return EINVAL;
+	}
+
+	/* Copy flock data from userspace. */
+	if((r = sys_datacopy(who_e, (vir_bytes) m_in.name1, 
+	  SELF, (vir_bytes) &flock_arg,
+	  (phys_bytes) sizeof(flock_arg))) != OK)
+		return r;
+
+	/* Convert starting offset to signed. */
+	offset = (signed long) flock_arg.l_start;
+
+	/* Figure out starting position base. */
+	switch(flock_arg.l_whence) {
+		case SEEK_SET: start = 0; if(offset < 0) return EINVAL; break;
+		case SEEK_CUR: start = f->filp_pos; break;
+		case SEEK_END: start = f->filp_ino->i_size; break;
+		default: return EINVAL;
+	}
+
+	/* Check for overflow or underflow. */
+	if(offset > 0 && start + offset < start) { return EINVAL; }
+	if(offset < 0 && start + offset > start) { return EINVAL; }
+	start += offset;
+	if(flock_arg.l_len > 0) {
+		end = start + flock_arg.l_len;
+		if(end <= start) {
+			return EINVAL;
+		}
+		r = freesp_inode(f->filp_ino, start, end);
+	} else {
+		r = truncate_inode(f->filp_ino, start);
+	}
+	return r;
+     }
+
+     default:
+	return(EINVAL);
+  }
+}
+
+/*===========================================================================*
+ *				do_sync					     *
+ *===========================================================================*/
+PUBLIC int do_sync()
+{
+/* Perform the sync() system call.  Flush all the tables. 
+ * The order in which the various tables are flushed is critical.  The
+ * blocks must be flushed last, since rw_inode() leaves its results in
+ * the block cache.
+ */
+  register struct inode *rip;
+  register struct buf *bp;
+
+  /* Write all the dirty inodes to the disk. */
+  for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
+	if (rip->i_count > 0 && rip->i_dirt == DIRTY) rw_inode(rip, WRITING);
+
+  /* Write all the dirty blocks to the disk, one drive at a time. */
+  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++)
+	if (bp->b_dev != NO_DEV && bp->b_dirt == DIRTY) flushall(bp->b_dev);
+
+  return(OK);		/* sync() can't fail */
+}
+
+/*===========================================================================*
+ *				do_fsync				     *
+ *===========================================================================*/
+PUBLIC int do_fsync()
+{
+/* Perform the fsync() system call. For now, don't be unnecessarily smart. */
+
+  do_sync();
+
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_reboot				     *
+ *===========================================================================*/
+PUBLIC int do_reboot()
+{
+  /* Perform the FS side of the reboot call. */
+  int i;
+  struct super_block *sp;
+  struct inode dummy;
+
+  /* Only PM may make this call directly. */
+  if (who_e != PM_PROC_NR) return(EGENERIC);
+
+  /* Do exit processing for all leftover processes and servers,
+   * but don't actually exit them (if they were really gone, PM
+   * will tell us about it).
+   */
+  for (i = 0; i < NR_PROCS; i++)
+	if((m_in.endpt1 = fproc[i].fp_endpoint) != NONE)
+		free_proc(&fproc[i], 0);
+
+  /* The root file system is mounted onto itself, which keeps it from being
+   * unmounted.  Pull an inode out of thin air and put the root on it.
+   */
+  put_inode(super_block[0].s_imount);
+  super_block[0].s_imount= &dummy;
+  dummy.i_count = 2;			/* expect one "put" */
+
+  /* Unmount all filesystems.  File systems are mounted on other file systems,
+   * so you have to pull off the loose bits repeatedly to get it all undone.
+   */
+  for (i= 0; i < NR_SUPERS; i++) {
+	/* Unmount at least one. */
+	for (sp= &super_block[0]; sp < &super_block[NR_SUPERS]; sp++) {
+		if (sp->s_dev != NO_DEV) (void) unmount(sp->s_dev);
+	}
+  }
+
+  /* Sync any unwritten buffers. */
+  do_sync();
+
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_fork					     *
+ *===========================================================================*/
+PUBLIC int do_fork()
+{
+/* Perform those aspects of the fork() system call that relate to files.
+ * In particular, let the child inherit its parent's file descriptors.
+ * The parent and child parameters tell who forked off whom. The file
+ * system uses the same slot numbers as the kernel.  Only MM makes this call.
+ */
+
+  register struct fproc *cp;
+  int i, parentno, childno;
+
+  /* Only PM may make this call directly. */
+  if (who_e != PM_PROC_NR) return(EGENERIC);
+
+  /* Check up-to-dateness of fproc. */
+  okendpt(m_in.parent_endpt, &parentno);
+
+  /* PM gives child endpoint, which implies process slot information.
+   * Don't call isokendpt, because that will verify if the endpoint
+   * number is correct in fproc, which it won't be.
+   */
+  childno = _ENDPOINT_P(m_in.child_endpt);
+  if(childno < 0 || childno >= NR_PROCS)
+	panic(__FILE__, "FS: bogus child for forking", m_in.child_endpt);
+  if(fproc[childno].fp_pid != PID_FREE)
+	panic(__FILE__, "FS: forking on top of in-use child", childno);
+
+  /* Copy the parent's fproc struct to the child. */
+  fproc[childno] = fproc[parentno];
+
+  /* Increase the counters in the 'filp' table. */
+  cp = &fproc[childno];
+  for (i = 0; i < OPEN_MAX; i++)
+	if (cp->fp_filp[i] != NIL_FILP) cp->fp_filp[i]->filp_count++;
+
+  /* Fill in new process and endpoint id. */
+  cp->fp_pid = m_in.pid;
+  cp->fp_endpoint = m_in.child_endpt;
+
+  /* A child is not a process leader. */
+  cp->fp_sesldr = 0;
+
+  /* This child has not exec()ced yet. */
+  cp->fp_execced = 0;
+#if 0
+printf("do_fork: child %d, slot %d\n", m_in.child_endpt, cp-fproc);
+#endif
+
+  /* Record the fact that both root and working dir have another user. */
+  dup_inode(cp->fp_rootdir);
+  dup_inode(cp->fp_workdir);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_exec					     *
+ *===========================================================================*/
+PUBLIC int do_exec()
+{
+/* Files can be marked with the FD_CLOEXEC bit (in fp->fp_cloexec).  When
+ * MM does an EXEC, it calls FS to allow FS to find these files and close them.
+ */
+
+  int i, proc;
+  long bitmap;
+
+  /* Only PM may make this call directly. */
+  if (who_e != PM_PROC_NR) return(EGENERIC);
+
+  /* The array of FD_CLOEXEC bits is in the fp_cloexec bit map. */
+  okendpt(m_in.endpt1, &proc);
+  fp = &fproc[proc];		/* get_filp() needs 'fp' */
+  bitmap = fp->fp_cloexec;
+  if (bitmap) {
+    /* Check the file desriptors one by one for presence of FD_CLOEXEC. */
+    for (i = 0; i < OPEN_MAX; i++) {
+	  m_in.fd = i;
+	  if ( (bitmap >> i) & 01) (void) do_close();
+    }
+  }
+
+  /* This child has now exec()ced. */
+  fp->fp_execced = 1;
+
+  /* Reply to caller (PM) directly. */
+  reply(who_e, OK);
+
+  /* Check if this is a driver that can now be useful. */
+  dmap_endpt_up(fp->fp_endpoint);
+
+  /* Suppress reply to caller (caller already replied to). */
+  return SUSPEND;
+}
+
+/*===========================================================================*
+ *				free_proc				     *
+ *===========================================================================*/
+PRIVATE int free_proc(struct fproc *exiter, int flags)
+{
+  int i, task;
+  register struct fproc *rfp;
+  register struct filp *rfilp;
+  register struct inode *rip;
+  dev_t dev;
+
+  fp = exiter;		/* get_filp() needs 'fp' */
+
+  if (fp->fp_suspended == SUSPENDED) {
+	task = -fp->fp_task;
+	if (task == XPIPE || task == XPOPEN) susp_count--;
+	m_in.ENDPT = fp->fp_endpoint;
+	(void) do_unpause();	/* this always succeeds for MM */
+	fp->fp_suspended = NOT_SUSPENDED;
+  }
+
+  /* Loop on file descriptors, closing any that are open. */
+  for (i = 0; i < OPEN_MAX; i++) {
+	m_in.fd = i;
+	(void) do_close();
+  }
+
+  /* Release root and working directories. */
+  put_inode(fp->fp_rootdir);
+  put_inode(fp->fp_workdir);
+  fp->fp_rootdir = NIL_INODE;
+  fp->fp_workdir = NIL_INODE;
+
+  /* Check if any process is SUSPENDed on this driver.
+   * If a driver exits, unmap its entries in the dmap table.
+   * (unmapping has to be done after the first step, because the
+   * dmap table is used in the first step.)
+   */
+  unsuspend_by_endpt(fp->fp_endpoint);
+
+  /* The rest of these actions is only done when processes actually
+   * exit.
+   */
+  if(!(flags & FP_EXITING))
+	return OK;
+
+  dmap_unmap_by_endpt(fp->fp_endpoint);
+  /* Invalidate endpoint number for error and sanity checks. */
+  fp->fp_endpoint = NONE;
+
+  /* If a session leader exits and it has a controlling tty, then revoke 
+   * access to its controlling tty from all other processes using it.
+   */
+  if (fp->fp_sesldr && fp->fp_tty != 0) {
+
+      dev = fp->fp_tty;
+
+      for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
+	  if(rfp->fp_pid == PID_FREE) continue;
+          if (rfp->fp_tty == dev) rfp->fp_tty = 0;
+
+          for (i = 0; i < OPEN_MAX; i++) {
+		if ((rfilp = rfp->fp_filp[i]) == NIL_FILP) continue;
+		if (rfilp->filp_mode == FILP_CLOSED) continue;
+		rip = rfilp->filp_ino;
+		if ((rip->i_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
+		if ((dev_t) rip->i_zone[0] != dev) continue;
+		dev_close(dev);
+		rfilp->filp_mode = FILP_CLOSED;
+          }
+      }
+  }
+
+  /* Exit done. Mark slot as free. */
+  fp->fp_pid = PID_FREE;
+  return(OK);
+
+}
+
+/*===========================================================================*
+ *				do_exit					     *
+ *===========================================================================*/
+PUBLIC int do_exit()
+{
+  int exitee_p, exitee_e;
+/* Perform the file system portion of the exit(status) system call. */
+
+  /* Only PM may do the EXIT call directly. */
+  if (who_e != PM_PROC_NR) return(EGENERIC);
+
+  /* Nevertheless, pretend that the call came from the user. */
+  exitee_e = m_in.endpt1;
+  okendpt(exitee_e, &exitee_p);
+  return free_proc(&fproc[exitee_p], FP_EXITING);
+}
+
+/*===========================================================================*
+ *				do_set					     *
+ *===========================================================================*/
+PUBLIC int do_set()
+{
+/* Set uid_t or gid_t field. */
+
+  register struct fproc *tfp;
+  int proc;
+
+  /* Only PM may make this call directly. */
+  if (who_e != PM_PROC_NR) return(EGENERIC);
+
+  okendpt(m_in.endpt1, &proc);
+  tfp = &fproc[proc];
+  if (call_nr == SETUID) {
+	tfp->fp_realuid = (uid_t) m_in.real_user_id;
+	tfp->fp_effuid =  (uid_t) m_in.eff_user_id;
+  }
+  if (call_nr == SETGID) {
+	tfp->fp_effgid =  (gid_t) m_in.eff_grp_id;
+	tfp->fp_realgid = (gid_t) m_in.real_grp_id;
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_revive				     *
+ *===========================================================================*/
+PUBLIC int do_revive()
+{
+/* A driver, typically TTY, has now gotten the characters that were needed for 
+ * a previous read.  The process did not get a reply when it made the call.
+ * Instead it was suspended.  Now we can send the reply to wake it up.  This
+ * business has to be done carefully, since the incoming message is from
+ * a driver (to which no reply can be sent), and the reply must go to a process
+ * that blocked earlier.  The reply to the caller is inhibited by returning the
+ * 'SUSPEND' pseudo error, and the reply to the blocked process is done
+ * explicitly in revive().
+ */
+  revive(m_in.REP_ENDPT, m_in.REP_STATUS);
+  return(SUSPEND);		/* don't reply to the TTY task */
+}
+
+/*===========================================================================*
+ *				do_svrctl				     *
+ *===========================================================================*/
+PUBLIC int do_svrctl()
+{
+  switch (m_in.svrctl_req) {
+  case FSSIGNON: {
+	/* A server in user space calls in to manage a device. */
+	struct fssignon device;
+	int r, major, proc_nr_n;
+
+	if (fp->fp_effuid != SU_UID && fp->fp_effuid != SERVERS_UID)
+		return(EPERM);
+
+	/* Try to copy request structure to FS. */
+	if ((r = sys_datacopy(who_e, (vir_bytes) m_in.svrctl_argp,
+		FS_PROC_NR, (vir_bytes) &device,
+		(phys_bytes) sizeof(device))) != OK) 
+	    return(r);
+
+	if (isokendpt(who_e, &proc_nr_n) != OK)
+		return(EINVAL);
+
+	/* Try to update device mapping. */
+	major = (device.dev >> MAJOR) & BYTE;
+	r=map_driver(major, who_e, device.style);
+	if (r == OK)
+	{
+		/* If a driver has completed its exec(), it can be announced
+		 * to be up.
+		*/
+		if(fproc[proc_nr_n].fp_execced) {
+			dev_up(major);
+		} else {
+			dmap[major].dmap_flags |= DMAP_BABY;
+		}
+	}
+
+	return(r);
+  }
+  case FSDEVUNMAP: {
+	struct fsdevunmap fdu;
+	int r, major;
+	/* Try to copy request structure to FS. */
+	if ((r = sys_datacopy(who_e, (vir_bytes) m_in.svrctl_argp,
+		FS_PROC_NR, (vir_bytes) &fdu,
+		(phys_bytes) sizeof(fdu))) != OK) 
+	    return(r);
+	major = (fdu.dev >> MAJOR) & BYTE;
+	r=map_driver(major, NONE, 0);
+	return(r);
+  }
+  default:
+	return(EINVAL);
+  }
+}
Index: /trunk/minix/servers/fs/mount.c
===================================================================
--- /trunk/minix/servers/fs/mount.c	(revision 9)
+++ /trunk/minix/servers/fs/mount.c	(revision 9)
@@ -0,0 +1,353 @@
+/* This file performs the MOUNT and UMOUNT system calls.
+ *
+ * The entry points into this file are
+ *   do_mount:	perform the MOUNT system call
+ *   do_umount:	perform the UMOUNT system call
+ */
+
+#include "fs.h"
+#include <fcntl.h>
+#include <string.h>
+#include <minix/com.h>
+#include <sys/stat.h>
+#include "buf.h"
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "param.h"
+#include "super.h"
+
+/* Allow the root to be replaced before the first 'real' mount. */
+PRIVATE int allow_newroot= 1;
+
+FORWARD _PROTOTYPE( dev_t name_to_dev, (char *path)			);
+
+/*===========================================================================*
+ *				do_mount				     *
+ *===========================================================================*/
+PUBLIC int do_mount()
+{
+/* Perform the mount(name, mfile, rd_only) system call. */
+
+  register struct inode *rip, *root_ip;
+  struct super_block *xp, *sp;
+  dev_t dev;
+  mode_t bits;
+  int rdir, mdir;		/* TRUE iff {root|mount} file is dir */
+  int i, r, found;
+  struct fproc *tfp;
+
+  /* Only the super-user may do MOUNT. */
+  if (!super_user) return(EPERM);
+
+  /* If 'name' is not for a block special file, return error. */
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+  if ( (dev = name_to_dev(user_path)) == NO_DEV) return(err_code);
+
+  /* Scan super block table to see if dev already mounted & find a free slot.*/
+  sp = NIL_SUPER;
+  found = FALSE;
+  for (xp = &super_block[0]; xp < &super_block[NR_SUPERS]; xp++) {
+	if (xp->s_dev == dev)
+	{
+		/* is it mounted already? */
+		found = TRUE;
+		sp= xp;
+		break;
+	}
+	if (xp->s_dev == NO_DEV) sp = xp;	/* record free slot */
+  }
+  if (found)
+  {
+	printf(
+"do_mount: s_imount = 0x%x (%x, %d), s_isup = 0x%x (%x, %d), fp_rootdir = 0x%x\n",
+		xp->s_imount, xp->s_imount->i_dev, xp->s_imount->i_num,
+		xp->s_isup, xp->s_isup->i_dev, xp->s_isup->i_num,
+		fproc[FS_PROC_NR].fp_rootdir);
+	/* It is possible that we have an old root lying around that 
+	 * needs to be remounted.
+	 */
+	if (xp->s_imount != xp->s_isup ||
+		xp->s_isup == fproc[FS_PROC_NR].fp_rootdir)
+	{
+		/* Normally, s_imount refers to the mount point. For a root
+		 * filesystem, s_imount is equal to the root inode. We assume
+		 * that the root of FS is always the real root. If the two
+		 * inodes are different or if the root of FS is equal two the
+		 * root of the filesystem we found, we found a filesystem that
+		 * is in use.
+		 */
+		return(EBUSY);	/* already mounted */
+	}
+
+	if (root_dev == xp->s_dev)
+	{
+		panic("fs", "inconsistency remounting old root",
+			NO_NUM);
+	}
+
+	/* Now get the inode of the file to be mounted on. */
+	if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
+		return(err_code);
+	}
+
+	if ( (rip = eat_path(user_path)) == NIL_INODE) {
+		return(err_code);
+	}
+
+	r = OK;
+
+	/* It may not be special. */
+	bits = rip->i_mode & I_TYPE;
+	if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL)
+		r = ENOTDIR;
+
+	/* Get the root inode of the mounted file system. */
+	root_ip= sp->s_isup;
+
+	/* File types of 'rip' and 'root_ip' may not conflict. */
+	if (r == OK) {
+		mdir = ((rip->i_mode & I_TYPE) == I_DIRECTORY); 
+						/* TRUE iff dir */
+		rdir = ((root_ip->i_mode & I_TYPE) == I_DIRECTORY);
+		if (!mdir && rdir) r = EISDIR;
+	}
+
+	/* If error, return the mount point. */
+	if (r != OK) {
+		put_inode(rip);
+		return(r);
+	}
+
+	/* Nothing else can go wrong.  Perform the mount. */
+	rip->i_mount = I_MOUNT;	/* this bit says the inode is
+				 * mounted on
+				 */
+	put_inode(sp->s_imount);
+	sp->s_imount = rip;
+	sp->s_rd_only = m_in.rd_only;
+	allow_newroot= 0;		/* The root is now fixed */
+	return(OK);
+  }
+  if (sp == NIL_SUPER) return(ENFILE);	/* no super block available */
+
+  /* Open the device the file system lives on. */
+  if (dev_open(dev, who_e, m_in.rd_only ? R_BIT : (R_BIT|W_BIT)) != OK) 
+  	return(EINVAL);
+
+  /* Make the cache forget about blocks it has open on the filesystem */
+  (void) do_sync();
+  invalidate(dev);
+
+  /* Fill in the super block. */
+  sp->s_dev = dev;		/* read_super() needs to know which dev */
+  r = read_super(sp);
+
+  /* Is it recognized as a Minix filesystem? */
+  if (r != OK) {
+	dev_close(dev);
+	sp->s_dev = NO_DEV;
+	return(r);
+  }
+
+  /* Now get the inode of the file to be mounted on. */
+  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
+	dev_close(dev);
+	sp->s_dev = NO_DEV;
+	return(err_code);
+  }
+
+  if (strcmp(user_path, "/") == 0 && allow_newroot)
+  {
+	printf("Replacing root\n");
+
+	/* Get the root inode of the mounted file system. */
+	if ( (root_ip = get_inode(dev, ROOT_INODE)) == NIL_INODE) r = err_code;
+	if (root_ip != NIL_INODE && root_ip->i_mode == 0) {
+		r = EINVAL;
+	}
+
+	/* If error, return the super block and both inodes; release the
+	 * maps.
+	 */
+	if (r != OK) {
+		put_inode(root_ip);
+		(void) do_sync();
+		invalidate(dev);
+		dev_close(dev);
+		sp->s_dev = NO_DEV;
+		return(r);
+	}
+
+	/* Nothing else can go wrong.  Perform the mount. */
+	sp->s_imount = root_ip;
+	dup_inode(root_ip);
+	sp->s_isup = root_ip;
+	sp->s_rd_only = m_in.rd_only;
+	root_dev= dev;
+
+	/* Replace all root and working directories */
+	for (i= 0, tfp= fproc; i<NR_PROCS; i++, tfp++)
+	{
+		if (tfp->fp_pid == PID_FREE)
+			continue;
+		if (tfp->fp_rootdir == NULL)
+			panic("fs", "do_mount: null rootdir", i);
+		put_inode(tfp->fp_rootdir);
+		dup_inode(root_ip);
+		tfp->fp_rootdir= root_ip;
+
+		if (tfp->fp_workdir == NULL)
+			panic("fs", "do_mount: null workdir", i);
+		put_inode(tfp->fp_workdir);
+		dup_inode(root_ip);
+		tfp->fp_workdir= root_ip;
+	}
+
+	/* Leave the old filesystem lying around. */
+	return(OK);
+  }
+
+  if ( (rip = eat_path(user_path)) == NIL_INODE) {
+	dev_close(dev);
+	sp->s_dev = NO_DEV;
+	return(err_code);
+  }
+
+  /* It may not be busy. */
+  r = OK;
+  if (rip->i_count > 1) r = EBUSY;
+
+  /* It may not be special. */
+  bits = rip->i_mode & I_TYPE;
+  if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR;
+
+  /* Get the root inode of the mounted file system. */
+  root_ip = NIL_INODE;		/* if 'r' not OK, make sure this is defined */
+  if (r == OK) {
+	if ( (root_ip = get_inode(dev, ROOT_INODE)) == NIL_INODE) r = err_code;
+  }
+  if (root_ip != NIL_INODE && root_ip->i_mode == 0) {
+  	r = EINVAL;
+  }
+
+  /* File types of 'rip' and 'root_ip' may not conflict. */
+  if (r == OK) {
+	mdir = ((rip->i_mode & I_TYPE) == I_DIRECTORY);  /* TRUE iff dir */
+	rdir = ((root_ip->i_mode & I_TYPE) == I_DIRECTORY);
+	if (!mdir && rdir) r = EISDIR;
+  }
+
+  /* If error, return the super block and both inodes; release the maps. */
+  if (r != OK) {
+	put_inode(rip);
+	put_inode(root_ip);
+	(void) do_sync();
+	invalidate(dev);
+	dev_close(dev);
+	sp->s_dev = NO_DEV;
+	return(r);
+  }
+
+  /* Nothing else can go wrong.  Perform the mount. */
+  rip->i_mount = I_MOUNT;	/* this bit says the inode is mounted on */
+  sp->s_imount = rip;
+  sp->s_isup = root_ip;
+  sp->s_rd_only = m_in.rd_only;
+  allow_newroot= 0;		/* The root is now fixed */
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_umount				     *
+ *===========================================================================*/
+PUBLIC int do_umount()
+{
+/* Perform the umount(name) system call. */
+  dev_t dev;
+
+  /* Only the super-user may do UMOUNT. */
+  if (!super_user) return(EPERM);
+
+  /* If 'name' is not for a block special file, return error. */
+  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
+  if ( (dev = name_to_dev(user_path)) == NO_DEV) return(err_code);
+
+  return(unmount(dev));
+}
+
+/*===========================================================================*
+ *				unmount					     *
+ *===========================================================================*/
+PUBLIC int unmount(dev)
+Dev_t dev;
+{
+/* Unmount a file system by device number. */
+  register struct inode *rip;
+  struct super_block *sp, *sp1;
+  int count;
+
+  /* See if the mounted device is busy.  Only 1 inode using it should be
+   * open -- the root inode -- and that inode only 1 time.
+   */
+  count = 0;
+  for (rip = &inode[0]; rip< &inode[NR_INODES]; rip++)
+	if (rip->i_count > 0 && rip->i_dev == dev) count += rip->i_count;
+  if (count > 1) return(EBUSY);	/* can't umount a busy file system */
+
+  /* Find the super block. */
+  sp = NIL_SUPER;
+  for (sp1 = &super_block[0]; sp1 < &super_block[NR_SUPERS]; sp1++) {
+	if (sp1->s_dev == dev) {
+		sp = sp1;
+		break;
+	}
+  }
+
+  /* Sync the disk, and invalidate cache. */
+  (void) do_sync();		/* force any cached blocks out of memory */
+  invalidate(dev);		/* invalidate cache entries for this dev */
+  if (sp == NIL_SUPER) {
+  	return(EINVAL);
+  }
+
+  /* Close the device the file system lives on. */
+  dev_close(dev);
+
+  /* Finish off the unmount. */
+  sp->s_imount->i_mount = NO_MOUNT;	/* inode returns to normal */
+  put_inode(sp->s_imount);	/* release the inode mounted on */
+  put_inode(sp->s_isup);	/* release the root inode of the mounted fs */
+  sp->s_imount = NIL_INODE;
+  sp->s_dev = NO_DEV;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				name_to_dev				     *
+ *===========================================================================*/
+PRIVATE dev_t name_to_dev(path)
+char *path;			/* pointer to path name */
+{
+/* Convert the block special file 'path' to a device number.  If 'path'
+ * is not a block special file, return error code in 'err_code'.
+ */
+
+  register struct inode *rip;
+  register dev_t dev;
+
+  /* If 'path' can't be opened, give up immediately. */
+  if ( (rip = eat_path(path)) == NIL_INODE) return(NO_DEV);
+
+  /* If 'path' is not a block special file, return error. */
+  if ( (rip->i_mode & I_TYPE) != I_BLOCK_SPECIAL) {
+	err_code = ENOTBLK;
+	put_inode(rip);
+	return(NO_DEV);
+  }
+
+  /* Extract the device number. */
+  dev = (dev_t) rip->i_zone[0];
+  put_inode(rip);
+  return(dev);
+}
Index: /trunk/minix/servers/fs/open.c
===================================================================
--- /trunk/minix/servers/fs/open.c	(revision 9)
+++ /trunk/minix/servers/fs/open.c	(revision 9)
@@ -0,0 +1,563 @@
+/* This file contains the procedures for creating, opening, closing, and
+ * seeking on files.
+ *
+ * The entry points into this file are
+ *   do_creat:	perform the CREAT system call
+ *   do_open:	perform the OPEN system call
+ *   do_mknod:	perform the MKNOD system call
+ *   do_mkdir:	perform the MKDIR system call
+ *   do_close:	perform the CLOSE system call
+ *   do_lseek:  perform the LSEEK system call
+ */
+
+#include "fs.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include "buf.h"
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "lock.h"
+#include "param.h"
+#include "super.h"
+
+#define offset m2_l1
+
+PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
+
+FORWARD _PROTOTYPE( int common_open, (int oflags, mode_t omode)		);
+FORWARD _PROTOTYPE( int pipe_open, (struct inode *rip,mode_t bits,int oflags));
+FORWARD _PROTOTYPE( struct inode *new_node, (struct inode **ldirp, 
+	char *path, mode_t bits, zone_t z0, int opaque, char *string));
+
+/*===========================================================================*
+ *				do_creat				     *
+ *===========================================================================*/
+PUBLIC int do_creat()
+{
+/* Perform the creat(name, mode) system call. */
+  int r;
+
+  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
+  r = common_open(O_WRONLY | O_CREAT | O_TRUNC, (mode_t) m_in.mode);
+  return(r);
+}
+
+/*===========================================================================*
+ *				do_open					     *
+ *===========================================================================*/
+PUBLIC int do_open()
+{
+/* Perform the open(name, flags,...) system call. */
+
+  int create_mode = 0;		/* is really mode_t but this gives problems */
+  int r;
+
+  /* If O_CREAT is set, open has three parameters, otherwise two. */
+  if (m_in.mode & O_CREAT) {
+	create_mode = m_in.c_mode;	
+	r = fetch_name(m_in.c_name, m_in.name1_length, M1);
+  } else {
+	r = fetch_name(m_in.name, m_in.name_length, M3);
+  }
+
+  if (r != OK) return(err_code); /* name was bad */
+  r = common_open(m_in.mode, create_mode);
+  return(r);
+}
+
+/*===========================================================================*
+ *				common_open				     *
+ *===========================================================================*/
+PRIVATE int common_open(register int oflags, mode_t omode)
+{
+/* Common code from do_creat and do_open. */
+
+  struct inode *rip, *ldirp;
+  int r, b, exist = TRUE;
+  dev_t dev;
+  mode_t bits;
+  off_t pos;
+  struct filp *fil_ptr, *filp2;
+
+  /* Remap the bottom two bits of oflags. */
+  bits = (mode_t) mode_map[oflags & O_ACCMODE];
+
+  /* See if file descriptor and filp slots are available. */
+  if ( (r = get_fd(0, bits, &m_in.fd, &fil_ptr)) != OK) return(r);
+
+  /* If O_CREATE is set, try to make the file. */ 
+  if (oflags & O_CREAT) {
+  	/* Create a new inode by calling new_node(). */
+        omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
+    	rip = new_node(&ldirp, user_path, omode, NO_ZONE, oflags&O_EXCL, NULL);
+    	r = err_code;
+        put_inode(ldirp);
+    	if (r == OK) exist = FALSE;      /* we just created the file */
+	else if (r != EEXIST) return(r); /* other error */
+	else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL 
+					    flag is set this is an error */
+  } else {
+	 /* Scan path name. */
+    	if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
+  }
+
+  /* Claim the file descriptor and filp slot and fill them in. */
+  fp->fp_filp[m_in.fd] = fil_ptr;
+  FD_SET(m_in.fd, &fp->fp_filp_inuse);
+  fil_ptr->filp_count = 1;
+  fil_ptr->filp_ino = rip;
+  fil_ptr->filp_flags = oflags;
+
+  /* Only do the normal open code if we didn't just create the file. */
+  if (exist) {
+  	/* Check protections. */
+  	if ((r = forbidden(rip, bits)) == OK) {
+  		/* Opening reg. files directories and special files differ. */
+	  	switch (rip->i_mode & I_TYPE) {
+    		   case I_REGULAR: 
+			/* Truncate regular file if O_TRUNC. */
+			if (oflags & O_TRUNC) {
+				if ((r = forbidden(rip, W_BIT)) !=OK) break;
+				truncate_inode(rip, 0);
+				wipe_inode(rip);
+				/* Send the inode from the inode cache to the
+				 * block cache, so it gets written on the next
+				 * cache flush.
+				 */
+				rw_inode(rip, WRITING);
+			}
+			break;
+ 
+	    	   case I_DIRECTORY: 
+			/* Directories may be read but not written. */
+			r = (bits & W_BIT ? EISDIR : OK);
+			break;
+
+	     	   case I_CHAR_SPECIAL:
+     		   case I_BLOCK_SPECIAL:
+			/* Invoke the driver for special processing. */
+			dev = (dev_t) rip->i_zone[0];
+			r = dev_open(dev, who_e, bits | (oflags & ~O_ACCMODE));
+			break;
+
+		   case I_NAMED_PIPE:
+			oflags |= O_APPEND;	/* force append mode */
+			fil_ptr->filp_flags = oflags;
+			r = pipe_open(rip, bits, oflags);
+			if (r != ENXIO) {
+				/* See if someone else is doing a rd or wt on
+				 * the FIFO.  If so, use its filp entry so the
+				 * file position will be automatically shared.
+				 */
+				b = (bits & R_BIT ? R_BIT : W_BIT);
+				fil_ptr->filp_count = 0; /* don't find self */
+				if ((filp2 = find_filp(rip, b)) != NIL_FILP) {
+					/* Co-reader or writer found. Use it.*/
+					fp->fp_filp[m_in.fd] = filp2;
+					filp2->filp_count++;
+					filp2->filp_ino = rip;
+					filp2->filp_flags = oflags;
+
+					/* i_count was incremented incorrectly
+					 * by eatpath above, not knowing that
+					 * we were going to use an existing
+					 * filp entry.  Correct this error.
+					 */
+					rip->i_count--;
+				} else {
+					/* Nobody else found.  Restore filp. */
+					fil_ptr->filp_count = 1;
+					if (b == R_BIT)
+					     pos = rip->i_zone[V2_NR_DZONES+0];
+					else
+					     pos = rip->i_zone[V2_NR_DZONES+1];
+					fil_ptr->filp_pos = pos;
+				}
+			}
+			break;
+ 		}
+  	}
+  }
+
+  /* If error, release inode. */
+  if (r != OK) {
+	if (r == SUSPEND) return(r);		/* Oops, just suspended */
+	fp->fp_filp[m_in.fd] = NIL_FILP;
+  	FD_CLR(m_in.fd, &fp->fp_filp_inuse);
+	fil_ptr->filp_count= 0;
+	put_inode(rip);
+	return(r);
+  }
+  
+  return(m_in.fd);
+}
+
+/*===========================================================================*
+ *				new_node				     *
+ *===========================================================================*/
+PRIVATE struct inode *new_node(struct inode **ldirp,
+	char *path, mode_t bits, zone_t z0, int opaque, char *parsed)
+{
+/* New_node() is called by common_open(), do_mknod(), and do_mkdir().  
+ * In all cases it allocates a new inode, makes a directory entry for it on 
+ * the path 'path', and initializes it.  It returns a pointer to the inode if 
+ * it can do this; otherwise it returns NIL_INODE.  It always sets 'err_code'
+ * to an appropriate value (OK or an error code).
+ * 
+ * The parsed path rest is returned in 'parsed' if parsed is nonzero. It
+ * has to hold at least NAME_MAX bytes.
+ */
+
+  register struct inode *rip;
+  register int r;
+  char string[NAME_MAX];
+
+  *ldirp = parse_path(path, string, opaque ? LAST_DIR : LAST_DIR_EATSYM);       
+  if (*ldirp == NIL_INODE) return(NIL_INODE);
+
+  /* The final directory is accessible. Get final component of the path. */
+  rip = advance(ldirp, string);
+
+  if (S_ISDIR(bits) && 
+      (*ldirp)->i_nlinks >= ((*ldirp)->i_sp->s_version == V1 ?
+      CHAR_MAX : SHRT_MAX)) {
+        /* New entry is a directory, alas we can't give it a ".." */
+        put_inode(rip);
+        err_code = EMLINK;
+        return(NIL_INODE);
+  }
+
+  if ( rip == NIL_INODE && err_code == ENOENT) {
+	/* Last path component does not exist.  Make new directory entry. */
+	if ( (rip = alloc_inode((*ldirp)->i_dev, bits)) == NIL_INODE) {
+		/* Can't creat new inode: out of inodes. */
+		return(NIL_INODE);
+	}
+
+	/* Force inode to the disk before making directory entry to make
+	 * the system more robust in the face of a crash: an inode with
+	 * no directory entry is much better than the opposite.
+	 */
+	rip->i_nlinks++;
+	rip->i_zone[0] = z0;		/* major/minor device numbers */
+	rw_inode(rip, WRITING);		/* force inode to disk now */
+
+	/* New inode acquired.  Try to make directory entry. */
+	if ((r = search_dir(*ldirp, string, &rip->i_num,ENTER)) != OK) {
+		rip->i_nlinks--;	/* pity, have to free disk inode */
+		rip->i_dirt = DIRTY;	/* dirty inodes are written out */
+		put_inode(rip);	/* this call frees the inode */
+		err_code = r;
+		return(NIL_INODE);
+	}
+
+  } else {
+	/* Either last component exists, or there is some problem. */
+	if (rip != NIL_INODE)
+		r = EEXIST;
+	else
+		r = err_code;
+  }
+
+  if(parsed) { /* Give the caller the parsed string if requested. */
+	strncpy(parsed, string, NAME_MAX-1);
+	parsed[NAME_MAX-1] = '\0';
+  }
+
+  /* The caller has to return the directory inode (*ldirp).  */
+  err_code = r;
+  return(rip);
+}
+
+/*===========================================================================*
+ *				pipe_open				     *
+ *===========================================================================*/
+PRIVATE int pipe_open(register struct inode *rip, register mode_t bits,
+	register int oflags)
+{
+/*  This function is called from common_open. It checks if
+ *  there is at least one reader/writer pair for the pipe, if not
+ *  it suspends the caller, otherwise it revives all other blocked
+ *  processes hanging on the pipe.
+ */
+
+  rip->i_pipe = I_PIPE; 
+
+  if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) {
+	printf("pipe opened RW.\n");
+	return ENXIO;
+  }
+
+  if (find_filp(rip, bits & W_BIT ? R_BIT : W_BIT) == NIL_FILP) { 
+	if (oflags & O_NONBLOCK) {
+		if (bits & W_BIT) return(ENXIO);
+	} else {
+		suspend(XPOPEN);	/* suspend caller */
+		return(SUSPEND);
+	}
+  } else if (susp_count > 0) {/* revive blocked processes */
+	release(rip, OPEN, susp_count);
+	release(rip, CREAT, susp_count);
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_mknod				     *
+ *===========================================================================*/
+PUBLIC int do_mknod()
+{
+/* Perform the mknod(name, mode, addr) system call. */
+
+  register mode_t bits, mode_bits;
+  struct inode *ip, *ldirp;
+
+  /* Only the super_user may make nodes other than fifos. */
+  mode_bits = (mode_t) m_in.mk_mode;		/* mode of the inode */
+  if (!super_user && ((mode_bits & I_TYPE) != I_NAMED_PIPE)) return(EPERM);
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+  bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask);
+  ip = new_node(&ldirp, user_path, bits, (zone_t) m_in.mk_z0, TRUE, NULL);
+  put_inode(ip);
+  put_inode(ldirp);
+  return(err_code);
+}
+
+/*===========================================================================*
+ *				do_mkdir				     *
+ *===========================================================================*/
+PUBLIC int do_mkdir()
+{
+/* Perform the mkdir(name, mode) system call. */
+
+  int r1, r2;			/* status codes */
+  ino_t dot, dotdot;		/* inode numbers for . and .. */
+  mode_t bits;			/* mode bits for the new inode */
+  char string[NAME_MAX];	/* last component of the new dir's path name */
+  struct inode *rip, *ldirp;
+
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+
+  /* Next make the inode. If that fails, return error code. */
+  bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask);
+  rip = new_node(&ldirp, user_path, bits, (zone_t) 0, TRUE, string);
+  if (rip == NIL_INODE || err_code == EEXIST) {
+	put_inode(rip);		/* can't make dir: it already exists */
+	put_inode(ldirp);
+	return(err_code);
+  }
+
+  /* Get the inode numbers for . and .. to enter in the directory. */
+  dotdot = ldirp->i_num;	/* parent's inode number */
+  dot = rip->i_num;		/* inode number of the new dir itself */
+
+  /* Now make dir entries for . and .. unless the disk is completely full. */
+  /* Use dot1 and dot2, so the mode of the directory isn't important. */
+  rip->i_mode = bits;	/* set mode */
+  r1 = search_dir(rip, dot1, &dot, ENTER);	/* enter . in the new dir */
+  r2 = search_dir(rip, dot2, &dotdot, ENTER);	/* enter .. in the new dir */
+
+  /* If both . and .. were successfully entered, increment the link counts. */
+  if (r1 == OK && r2 == OK) {
+	/* Normal case.  It was possible to enter . and .. in the new dir. */
+	rip->i_nlinks++;	/* this accounts for . */
+	ldirp->i_nlinks++;	/* this accounts for .. */
+	ldirp->i_dirt = DIRTY;	/* mark parent's inode as dirty */
+  } else {
+	/* It was not possible to enter . or .. probably disk was full -
+	 * links counts haven't been touched.
+	 */
+	if(search_dir(ldirp, string, (ino_t *) 0, DELETE) != OK)
+		panic(__FILE__, "Dir disappeared ", rip->i_num);
+	rip->i_nlinks--;	/* undo the increment done in new_node() */
+  }
+  rip->i_dirt = DIRTY;		/* either way, i_nlinks has changed */
+
+  put_inode(ldirp);		/* return the inode of the parent dir */
+  put_inode(rip);		/* return the inode of the newly made dir */
+  return(err_code);		/* new_node() always sets 'err_code' */
+}
+
+/*===========================================================================*
+ *				do_close				     *
+ *===========================================================================*/
+PUBLIC int do_close()
+{
+/* Perform the close(fd) system call. */
+
+  register struct filp *rfilp;
+  register struct inode *rip;
+  struct file_lock *flp;
+  int rw, mode_word, lock_count;
+  dev_t dev;
+
+  /* First locate the inode that belongs to the file descriptor. */
+  if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
+  rip = rfilp->filp_ino;	/* 'rip' points to the inode */
+
+  if (rfilp->filp_count - 1 == 0 && rfilp->filp_mode != FILP_CLOSED) {
+	/* Check to see if the file is special. */
+	mode_word = rip->i_mode & I_TYPE;
+	if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) {
+		dev = (dev_t) rip->i_zone[0];
+		if (mode_word == I_BLOCK_SPECIAL)  {
+			/* Invalidate cache entries unless special is mounted
+			 * or ROOT
+			 */
+			if (!mounted(rip)) {
+			        (void) do_sync();	/* purge cache */
+				invalidate(dev);
+			}    
+		}
+		/* Do any special processing on device close. */
+		dev_close(dev);
+	}
+  }
+
+  /* If the inode being closed is a pipe, release everyone hanging on it. */
+  if (rip->i_pipe == I_PIPE) {
+	rw = (rfilp->filp_mode & R_BIT ? WRITE : READ);
+	release(rip, rw, NR_PROCS);
+  }
+
+  /* If a write has been done, the inode is already marked as DIRTY. */
+  if (--rfilp->filp_count == 0) {
+	if (rip->i_pipe == I_PIPE && rip->i_count > 1) {
+		/* Save the file position in the i-node in case needed later.
+		 * The read and write positions are saved separately.  The
+		 * last 3 zones in the i-node are not used for (named) pipes.
+		 */
+		if (rfilp->filp_mode == R_BIT)
+			rip->i_zone[V2_NR_DZONES+0] = (zone_t) rfilp->filp_pos;
+		else
+			rip->i_zone[V2_NR_DZONES+1] = (zone_t) rfilp->filp_pos;
+	}
+	put_inode(rip);
+  }
+
+  fp->fp_cloexec &= ~(1L << m_in.fd);	/* turn off close-on-exec bit */
+  fp->fp_filp[m_in.fd] = NIL_FILP;
+  FD_CLR(m_in.fd, &fp->fp_filp_inuse);
+
+  /* Check to see if the file is locked.  If so, release all locks. */
+  if (nr_locks == 0) return(OK);
+  lock_count = nr_locks;	/* save count of locks */
+  for (flp = &file_lock[0]; flp < &file_lock[NR_LOCKS]; flp++) {
+	if (flp->lock_type == 0) continue;	/* slot not in use */
+	if (flp->lock_inode == rip && flp->lock_pid == fp->fp_pid) {
+		flp->lock_type = 0;
+		nr_locks--;
+	}
+  }
+  if (nr_locks < lock_count) lock_revive();	/* lock released */
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_lseek				     *
+ *===========================================================================*/
+PUBLIC int do_lseek()
+{
+/* Perform the lseek(ls_fd, offset, whence) system call. */
+
+  register struct filp *rfilp;
+  register off_t pos;
+
+  /* Check to see if the file descriptor is valid. */
+  if ( (rfilp = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code);
+
+  /* No lseek on pipes. */
+  if (rfilp->filp_ino->i_pipe == I_PIPE) return(ESPIPE);
+
+  /* The value of 'whence' determines the start position to use. */
+  switch(m_in.whence) {
+	case SEEK_SET: pos = 0;	break;
+	case SEEK_CUR: pos = rfilp->filp_pos;	break;
+	case SEEK_END: pos = rfilp->filp_ino->i_size;	break;
+	default: return(EINVAL);
+  }
+
+  /* Check for overflow. */
+  if (((long)m_in.offset > 0) && ((long)(pos + m_in.offset) < (long)pos)) 
+  	return(EINVAL);
+  if (((long)m_in.offset < 0) && ((long)(pos + m_in.offset) > (long)pos)) 
+  	return(EINVAL);
+  pos = pos + m_in.offset;
+
+  if (pos != rfilp->filp_pos)
+	rfilp->filp_ino->i_seek = ISEEK;	/* inhibit read ahead */
+  rfilp->filp_pos = pos;
+  m_out.reply_l1 = pos;		/* insert the long into the output message */
+  return(OK);
+}
+
+/*===========================================================================*
+ *                             do_slink					     *
+ *===========================================================================*/
+PUBLIC int do_slink()
+{
+/* Perform the symlink(name1, name2) system call. */
+
+  register int r;              /* error code */
+  char string[NAME_MAX];       /* last component of the new dir's path name */
+  struct inode *sip;           /* inode containing symbolic link */
+  struct buf *bp;              /* disk buffer for link */
+  struct inode *ldirp;         /* directory containing link */
+
+  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK)
+       return(err_code);
+
+  if (m_in.name1_length <= 1 || m_in.name1_length >= _MIN_BLOCK_SIZE)
+       return(ENAMETOOLONG);
+
+  /* Create the inode for the symlink. */
+  sip = new_node(&ldirp, user_path, (mode_t) (I_SYMBOLIC_LINK | RWX_MODES),
+                 (zone_t) 0, TRUE, string);
+
+  /* Allocate a disk block for the contents of the symlink.
+   * Copy contents of symlink (the name pointed to) into first disk block.
+   */
+  if ((r = err_code) == OK) {
+       r = (bp = new_block(sip, (off_t) 0)) == NIL_BUF
+           ? err_code
+           : sys_vircopy(who_e, D, (vir_bytes) m_in.name1,
+                       SELF, D, (vir_bytes) bp->b_data,
+		       (vir_bytes) m_in.name1_length-1);
+
+	if(r == OK) {
+		bp->b_data[_MIN_BLOCK_SIZE-1] = '\0';
+		sip->i_size = strlen(bp->b_data);
+		if(sip->i_size != m_in.name1_length-1) {
+			/* This can happen if the user provides a buffer
+			 * with a \0 in it. This can cause a lot of trouble
+			 * when the symlink is used later. We could just use
+			 * the strlen() value, but we want to let the user
+			 * know he did something wrong. ENAMETOOLONG doesn't
+			 * exactly describe the error, but there is no
+			 * ENAMETOOWRONG.
+			 */
+			r = ENAMETOOLONG;
+		}
+	}
+  
+       put_block(bp, DIRECTORY_BLOCK); 	/* put_block() accepts NIL_BUF. */
+  
+       if (r != OK) {
+               sip->i_nlinks = 0;
+               if (search_dir(ldirp, string, (ino_t *) 0, DELETE) != OK)
+                       panic(__FILE__, "Symbolic link vanished", NO_NUM);
+       } 
+  }
+
+  /* put_inode() accepts NIL_INODE as a noop, so the below are safe. */
+  put_inode(sip);
+  put_inode(ldirp);
+
+  return(r);
+}
+
Index: /trunk/minix/servers/fs/param.h
===================================================================
--- /trunk/minix/servers/fs/param.h	(revision 9)
+++ /trunk/minix/servers/fs/param.h	(revision 9)
@@ -0,0 +1,64 @@
+/* The following names are synonyms for the variables in the input message. */
+#define acc_time      m2_l1
+#define addr	      m1_i3
+#define buffer	      m1_p1
+#define child_endpt      m1_i2
+#define co_mode	      m1_i1
+#define eff_grp_id    m1_i3
+#define eff_user_id   m1_i3
+#define erki          m1_p1
+#define fd	      m1_i1
+#define fd2	      m1_i2
+#define ioflags       m1_i3
+#define group	      m1_i3
+#define real_grp_id   m1_i2
+#define ls_fd	      m2_i1
+#define mk_mode	      m1_i2
+#define mk_z0	      m1_i3
+#define mode	      m3_i2
+#define c_mode        m1_i3
+#define c_name        m1_p1
+#define name	      m3_p1
+#define name1	      m1_p1
+#define name2	      m1_p2
+#define	name_length   m3_i1
+#define name1_length  m1_i1
+#define name2_length  m1_i2
+#define nbytes        m1_i2
+#define owner	      m1_i2
+#define parent_endpt      m1_i1
+#define pathname      m3_ca1
+#define pid	      m1_i3
+#define ENDPT	      m1_i1
+#define ctl_req       m4_l1
+#define driver_nr     m4_l2
+#define dev_nr	      m4_l3
+#define dev_style     m4_l4
+#define rd_only	      m1_i3
+#define real_user_id  m1_i2
+#define request       m1_i2
+#define sig	      m1_i2
+#define endpt1	      m1_i1
+#define tp	      m2_l1
+#define utime_actime  m2_l1
+#define utime_modtime m2_l2
+#define utime_file    m2_p1
+#define utime_length  m2_i1
+#define utime_strlen  m2_i2
+#define whence	      m2_i2
+#define svrctl_req    m2_i1
+#define svrctl_argp   m2_p1
+#define pm_stime      m1_i1
+#define info_what     m1_i1
+#define info_where    m1_p1
+
+/* The following names are synonyms for the variables in the output message. */
+#define reply_type    m_type
+#define reply_l1      m2_l1
+#define reply_i1      m1_i1
+#define reply_i2      m1_i2
+#define reply_t1      m4_l1
+#define reply_t2      m4_l2
+#define reply_t3      m4_l3
+#define reply_t4      m4_l4
+#define reply_t5      m4_l5
Index: /trunk/minix/servers/fs/path.c
===================================================================
--- /trunk/minix/servers/fs/path.c	(revision 9)
+++ /trunk/minix/servers/fs/path.c	(revision 9)
@@ -0,0 +1,486 @@
+/* This file contains the procedures that look up path names in the directory
+ * system and determine the inode number that goes with a given path name.
+ *
+ *  The entry points into this file are
+ *   eat_path:	 the 'main' routine of the path-to-inode conversion mechanism
+ *   last_dir:	 find the final directory on a given path
+ *   advance:	 parse one component of a path name
+ *   search_dir: search a directory for a string and return its inode number
+ *
+ */
+
+#include "fs.h"
+#include <string.h>
+#include <minix/callnr.h>
+#include <sys/stat.h>
+#include "buf.h"
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "super.h"
+
+PUBLIC char dot1[2] = ".";	/* used for search_dir to bypass the access */
+PUBLIC char dot2[3] = "..";	/* permissions for . and ..		    */
+
+FORWARD _PROTOTYPE( char *get_name, (char *old_name, char string [NAME_MAX]) );
+
+FORWARD _PROTOTYPE( struct inode *ltraverse, (struct inode *rip,
+                       char *path, char *suffix, struct inode *ldip)   );
+
+/*===========================================================================*
+ *                             parse_path				     *
+ *===========================================================================*/
+PUBLIC struct inode *parse_path(path, string, action)
+char *path;                    /* the path name to be parsed */
+char string[NAME_MAX];         /* the final component is returned here */
+int action;                    /* action on last part of path */
+{
+/* This is the actual code for last_dir and eat_path. Return the inode of
+ * the last directory and the name of object within that directory, or the
+ * inode of the last object (an empty name will be returned). Names are
+ * returned in string. If string is null the name is discarded. The action
+ * code determines how "last" is defined. If an error occurs, NIL_INODE
+ * will be returned with an error code in err_code.
+ */
+
+  struct inode *rip, *dir_ip;
+  char *new_name;
+  int symloop;
+  char lstring[NAME_MAX];
+
+  /* Is the path absolute or relative?  Initialize 'rip' accordingly. */
+  rip = (*path == '/' ? fp->fp_rootdir : fp->fp_workdir);
+
+  /* If dir has been removed or path is empty, return ENOENT. */
+  if (rip->i_nlinks == 0 || *path == '\0') {
+	err_code = ENOENT;
+	return(NIL_INODE);
+  }
+
+  dup_inode(rip);		/* inode will be returned with put_inode */
+
+  symloop = 0;                 /* symbolic link traversal count */
+  if (string == (char *) 0) string = lstring;
+
+  /* Scan the path component by component. */
+  while (TRUE) {
+	/* Extract one component. */
+	if ( (new_name = get_name(path, string)) == (char*) 0) {
+		put_inode(rip);	/* bad path in user space */
+		return(NIL_INODE);
+	}
+	if (*new_name == '\0' && (action & PATH_PENULTIMATE)) {
+		if ( (rip->i_mode & I_TYPE) == I_DIRECTORY) {
+			return(rip);	/* normal exit */
+		} else {
+			/* last file of path prefix is not a directory */
+			put_inode(rip);
+			err_code = ENOTDIR;			
+			return(NIL_INODE);
+		}
+        }
+
+	/* There is more path.  Keep parsing. */
+	dir_ip = rip;
+	rip = advance(&dir_ip, string);
+
+       if (rip == NIL_INODE) {
+               if (*new_name == '\0' && (action & PATH_NONSYMBOLIC) != 0)
+                       return(dir_ip);
+               else {
+                       put_inode(dir_ip);
+                       return(NIL_INODE);
+               }
+       }
+
+       /* The call to advance() succeeded.  Fetch next component. */
+       if (S_ISLNK(rip->i_mode)) {
+               if (*new_name != '\0' || (action & PATH_OPAQUE) == 0) {
+                       if (*new_name != '\0') new_name--;
+                       rip = ltraverse(rip, path, new_name, dir_ip);
+                       put_inode(dir_ip);
+                       if (++symloop > SYMLOOP) {
+                               err_code = ELOOP;
+                               put_inode(rip);
+                               rip = NIL_INODE;
+                       }
+                       if (rip == NIL_INODE) return(NIL_INODE);
+                       continue;
+               }
+       } else if (*new_name != '\0') {
+               put_inode(dir_ip);
+               path = new_name;
+               continue;
+	}
+      
+       /* Either last name reached or symbolic link is opaque */
+       if ((action & PATH_NONSYMBOLIC) != 0) {
+               put_inode(rip);
+               return(dir_ip);
+       } else {
+               put_inode(dir_ip);
+               return(rip);
+       }
+  }
+}
+
+/*===========================================================================*
+ *                             eat_path					     *
+ *===========================================================================*/
+PUBLIC struct inode *eat_path(path)
+char *path;                    /* the path name to be parsed */
+{
+ /* Parse the path 'path' and put its inode in the inode table. If not possible,
+  * return NIL_INODE as function value and an error code in 'err_code'.
+  */
+  
+  return parse_path(path, (char *) 0, EAT_PATH);
+}
+
+/*===========================================================================*
+ *                             last_dir					     *
+ *===========================================================================*/
+PUBLIC struct inode *last_dir(path, string)
+char *path;                    /* the path name to be parsed */
+char string[NAME_MAX];         /* the final component is returned here */
+{
+/* Given a path, 'path', located in the fs address space, parse it as
+ * far as the last directory, fetch the inode for the last directory into
+ * the inode table, and return a pointer to the inode.  In
+ * addition, return the final component of the path in 'string'.
+ * If the last directory can't be opened, return NIL_INODE and
+ * the reason for failure in 'err_code'.
+ */
+  
+  return parse_path(path, string, LAST_DIR);
+}
+
+/*===========================================================================*
+ *                             ltraverse				     *
+ *===========================================================================*/
+PRIVATE struct inode *ltraverse(rip, path, suffix, ldip)
+register struct inode *rip;    /* symbolic link */
+char *path;                    /* path containing link */
+char *suffix;                  /* suffix following link within path */
+register struct inode *ldip;   /* directory containing link */
+{
+/* Traverse a symbolic link. Copy the link text from the inode and insert
+ * the text into the path. Return the inode of base directory and the
+ * ammended path. The symbolic link inode is always freed. The inode
+ * returned is already duplicated. NIL_INODE is returned on error.
+ */
+  
+  block_t b;                   /* block containing link text */
+  struct inode *bip;           /* inode of base directory */
+  struct buf *bp;              /* buffer containing link text */
+  size_t sl;                   /* length of link */
+  size_t tl;                   /* length of suffix */
+  char *sp;                    /* start of link text */
+
+  bip = NIL_INODE;
+  bp  = NIL_BUF;
+
+  if ((b = read_map(rip, (off_t) 0)) != NO_BLOCK) {
+       bp = get_block(rip->i_dev, b, NORMAL);
+       sl = rip->i_size;
+       sp = bp->b_data;
+
+       /* Insert symbolic text into path name. */
+       tl = strlen(suffix);
+       if (sl > 0 && sl + tl <= PATH_MAX-1) {
+               memmove(path+sl, suffix, tl);
+               memmove(path, sp, sl);
+               path[sl+tl] = 0;
+               dup_inode(bip = path[0] == '/' ? fp->fp_rootdir : ldip);
+       }
+  }
+  
+  put_block(bp, DIRECTORY_BLOCK);
+  put_inode(rip);
+  if (bip == NIL_INODE)
+  {
+       err_code = ENOENT;
+  }
+  return (bip);
+}
+
+/*===========================================================================*
+ *				get_name				     *
+ *===========================================================================*/
+PRIVATE char *get_name(old_name, string)
+char *old_name;			/* path name to parse */
+char string[NAME_MAX];		/* component extracted from 'old_name' */
+{
+/* Given a pointer to a path name in fs space, 'old_name', copy the next
+ * component to 'string' and pad with zeros.  A pointer to that part of
+ * the name as yet unparsed is returned.  Roughly speaking,
+ * 'get_name' = 'old_name' - 'string'.
+ *
+ * This routine follows the standard convention that /usr/ast, /usr//ast,
+ * //usr///ast and /usr/ast/ are all equivalent.
+ */
+
+  register int c;
+  register char *np, *rnp;
+
+  np = string;			/* 'np' points to current position */
+  rnp = old_name;		/* 'rnp' points to unparsed string */
+  while ( (c = *rnp) == '/') rnp++;	/* skip leading slashes */
+
+  /* Copy the unparsed path, 'old_name', to the array, 'string'. */
+  while ( rnp < &old_name[PATH_MAX]  &&  c != '/'   &&  c != '\0') {
+	if (np < &string[NAME_MAX]) *np++ = c;
+	c = *++rnp;		/* advance to next character */
+  }
+
+  /* To make /usr/ast/ equivalent to /usr/ast, skip trailing slashes. */
+  while (c == '/' && rnp < &old_name[PATH_MAX]) c = *++rnp;
+
+  if (np < &string[NAME_MAX]) *np = '\0';	/* Terminate string */
+
+  if (rnp >= &old_name[PATH_MAX]) {
+	err_code = ENAMETOOLONG;
+	return((char *) 0);
+  }
+  return(rnp);
+}
+
+/*===========================================================================*
+ *				advance					     *
+ *===========================================================================*/
+PUBLIC struct inode *advance(pdirp, string)
+struct inode **pdirp;		/* inode for directory to be searched */
+char string[NAME_MAX];		/* component name to look for */
+{
+/* Given a directory and a component of a path, look up the component in
+ * the directory, find the inode, open it, and return a pointer to its inode
+ * slot.  If it can't be done, return NIL_INODE.
+ */
+
+  register struct inode *rip, *dirp;
+  register struct super_block *sp;
+  int r, inumb;
+  dev_t mnt_dev;
+  ino_t numb;
+
+  dirp = *pdirp;
+
+  /* If 'string' is empty, yield same inode straight away. */
+  if (string[0] == '\0') { return(get_inode(dirp->i_dev, (int) dirp->i_num)); }
+
+  /* Check for NIL_INODE. */
+  if (dirp == NIL_INODE) { return(NIL_INODE); }
+
+  /* If 'string' is not present in the directory, signal error. */
+  if ( (r = search_dir(dirp, string, &numb, LOOK_UP)) != OK) {
+	err_code = r;
+	return(NIL_INODE);
+  }
+
+  /* Don't go beyond the current root directory, unless the string is dot2. */
+  if (dirp == fp->fp_rootdir && strcmp(string, "..") == 0 && string != dot2)
+		return(get_inode(dirp->i_dev, (int) dirp->i_num));
+
+  /* The component has been found in the directory.  Get inode. */
+  if ( (rip = get_inode(dirp->i_dev, (int) numb)) == NIL_INODE)  {
+	return(NIL_INODE);
+	}
+
+  /* The following test is for "mountpoint/.." where mountpoint is a
+   * mountpoint. ".." will refer to the root of the mounted filesystem,
+   * but has to become a reference to the parent of the 'mountpoint'
+   * directory.
+   *
+   * This case is recognized by the looked up name pointing to a
+   * root inode, and the directory in which it is held being a
+   * root inode, _and_ the name[1] being '.'. (This is a test for '..'
+   * and excludes '.'.)
+   */
+  if (rip->i_num == ROOT_INODE)
+	if (dirp->i_num == ROOT_INODE) {
+	    if (string[1] == '.') {
+		sp= rip->i_sp;
+		if (sp->s_imount != sp->s_isup)
+		{
+			/* Release the root inode.  Replace by the
+			 * inode mounted on. Update parent.
+			 */
+			put_inode(rip);
+			put_inode(dirp);
+			mnt_dev = sp->s_imount->i_dev;
+			inumb = (int) sp->s_imount->i_num;
+			dirp = *pdirp = get_inode(mnt_dev, inumb);
+			rip = advance(pdirp, string);
+		}
+	    }
+	}
+  if (rip == NIL_INODE) return(NIL_INODE);
+
+  /* See if the inode is mounted on.  If so, switch to root directory of the
+   * mounted file system.  The super_block provides the linkage between the
+   * inode mounted on and the root directory of the mounted file system.
+   */
+  while (rip != NIL_INODE && rip->i_mount == I_MOUNT) {
+	/* The inode is indeed mounted on. */
+	for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++) {
+		if (sp->s_imount == rip) {
+			/* Release the inode mounted on.  Replace by the
+			 * inode of the root inode of the mounted device.
+			 */
+			put_inode(rip);
+			rip = get_inode(sp->s_dev, ROOT_INODE);
+			break;
+		}
+	}
+  }
+  return(rip);		/* return pointer to inode's component */
+}
+
+/*===========================================================================*
+ *				search_dir				     *
+ *===========================================================================*/
+PUBLIC int search_dir(ldir_ptr, string, numb, flag)
+register struct inode *ldir_ptr; /* ptr to inode for dir to search */
+char string[NAME_MAX];		 /* component to search for */
+ino_t *numb;			 /* pointer to inode number */
+int flag;			 /* LOOK_UP, ENTER, DELETE or IS_EMPTY */
+{
+/* This function searches the directory whose inode is pointed to by 'ldip':
+ * if (flag == ENTER)  enter 'string' in the directory with inode # '*numb';
+ * if (flag == DELETE) delete 'string' from the directory;
+ * if (flag == LOOK_UP) search for 'string' and return inode # in 'numb';
+ * if (flag == IS_EMPTY) return OK if only . and .. in dir else ENOTEMPTY;
+ *
+ *    if 'string' is dot1 or dot2, no access permissions are checked.
+ */
+
+  register struct direct *dp = NULL;
+  register struct buf *bp = NULL;
+  int i, r, e_hit, t, match;
+  mode_t bits;
+  off_t pos;
+  unsigned new_slots, old_slots;
+  block_t b;
+  struct super_block *sp;
+  int extended = 0;
+
+  /* If 'ldir_ptr' is not a pointer to a dir inode, error. */
+  if ( (ldir_ptr->i_mode & I_TYPE) != I_DIRECTORY)  {
+	return(ENOTDIR);
+   }
+
+  r = OK;
+
+  if (flag != IS_EMPTY) {
+	bits = (flag == LOOK_UP ? X_BIT : W_BIT | X_BIT);
+
+	if (string == dot1 || string == dot2) {
+		if (flag != LOOK_UP) r = read_only(ldir_ptr);
+				     /* only a writable device is required. */
+        }
+	else r = forbidden(ldir_ptr, bits); /* check access permissions */
+  }
+  if (r != OK) return(r);
+  
+  /* Step through the directory one block at a time. */
+  old_slots = (unsigned) (ldir_ptr->i_size/DIR_ENTRY_SIZE);
+  new_slots = 0;
+  e_hit = FALSE;
+  match = 0;			/* set when a string match occurs */
+
+  for (pos = 0; pos < ldir_ptr->i_size; pos += ldir_ptr->i_sp->s_block_size) {
+	b = read_map(ldir_ptr, pos);	/* get block number */
+
+	/* Since directories don't have holes, 'b' cannot be NO_BLOCK. */
+	bp = get_block(ldir_ptr->i_dev, b, NORMAL);	/* get a dir block */
+
+	if (bp == NO_BLOCK)
+		panic(__FILE__,"get_block returned NO_BLOCK", NO_NUM);
+
+	/* Search a directory block. */
+	for (dp = &bp->b_dir[0];
+		dp < &bp->b_dir[NR_DIR_ENTRIES(ldir_ptr->i_sp->s_block_size)];
+		dp++) {
+		if (++new_slots > old_slots) { /* not found, but room left */
+			if (flag == ENTER) e_hit = TRUE;
+			break;
+		}
+
+		/* Match occurs if string found. */
+		if (flag != ENTER && dp->d_ino != 0) {
+			if (flag == IS_EMPTY) {
+				/* If this test succeeds, dir is not empty. */
+				if (strcmp(dp->d_name, "." ) != 0 &&
+				    strcmp(dp->d_name, "..") != 0) match = 1;
+			} else {
+				if (strncmp(dp->d_name, string, NAME_MAX) == 0) {
+					match = 1;
+				}
+			}
+		}
+
+		if (match) {
+			/* LOOK_UP or DELETE found what it wanted. */
+			r = OK;
+			if (flag == IS_EMPTY) r = ENOTEMPTY;
+			else if (flag == DELETE) {
+				/* Save d_ino for recovery. */
+				t = NAME_MAX - sizeof(ino_t);
+				*((ino_t *) &dp->d_name[t]) = dp->d_ino;
+				dp->d_ino = 0;	/* erase entry */
+				bp->b_dirt = DIRTY;
+				ldir_ptr->i_update |= CTIME | MTIME;
+				ldir_ptr->i_dirt = DIRTY;
+			} else {
+				sp = ldir_ptr->i_sp;	/* 'flag' is LOOK_UP */
+				*numb = conv4(sp->s_native, (int) dp->d_ino);
+			}
+			put_block(bp, DIRECTORY_BLOCK);
+			return(r);
+		}
+
+		/* Check for free slot for the benefit of ENTER. */
+		if (flag == ENTER && dp->d_ino == 0) {
+			e_hit = TRUE;	/* we found a free slot */
+			break;
+		}
+	}
+
+	/* The whole block has been searched or ENTER has a free slot. */
+	if (e_hit) break;	/* e_hit set if ENTER can be performed now */
+	put_block(bp, DIRECTORY_BLOCK);	/* otherwise, continue searching dir */
+  }
+
+  /* The whole directory has now been searched. */
+  if (flag != ENTER) {
+  	return(flag == IS_EMPTY ? OK : ENOENT);
+  }
+
+  /* This call is for ENTER.  If no free slot has been found so far, try to
+   * extend directory.
+   */
+  if (e_hit == FALSE) { /* directory is full and no room left in last block */
+	new_slots++;		/* increase directory size by 1 entry */
+	if (new_slots == 0) return(EFBIG); /* dir size limited by slot count */
+	if ( (bp = new_block(ldir_ptr, ldir_ptr->i_size)) == NIL_BUF)
+		return(err_code);
+	dp = &bp->b_dir[0];
+	extended = 1;
+  }
+
+  /* 'bp' now points to a directory block with space. 'dp' points to slot. */
+  (void) memset(dp->d_name, 0, (size_t) NAME_MAX); /* clear entry */
+  for (i = 0; string[i] && i < NAME_MAX; i++) dp->d_name[i] = string[i];
+  sp = ldir_ptr->i_sp; 
+  dp->d_ino = conv4(sp->s_native, (int) *numb);
+  bp->b_dirt = DIRTY;
+  put_block(bp, DIRECTORY_BLOCK);
+  ldir_ptr->i_update |= CTIME | MTIME;	/* mark mtime for update later */
+  ldir_ptr->i_dirt = DIRTY;
+  if (new_slots > old_slots) {
+	ldir_ptr->i_size = (off_t) new_slots * DIR_ENTRY_SIZE;
+	/* Send the change to disk if the directory is extended. */
+	if (extended) rw_inode(ldir_ptr, WRITING);
+  }
+  return(OK);
+}
Index: /trunk/minix/servers/fs/pipe.c
===================================================================
--- /trunk/minix/servers/fs/pipe.c	(revision 9)
+++ /trunk/minix/servers/fs/pipe.c	(revision 9)
@@ -0,0 +1,426 @@
+/* This file deals with the suspension and revival of processes.  A process can
+ * be suspended because it wants to read or write from a pipe and can't, or
+ * because it wants to read or write from a special file and can't.  When a
+ * process can't continue it is suspended, and revived later when it is able
+ * to continue.
+ *
+ * The entry points into this file are
+ *   do_pipe:	  perform the PIPE system call
+ *   pipe_check:  check to see that a read or write on a pipe is feasible now
+ *   suspend:	  suspend a process that cannot do a requested read or write
+ *   release:	  check to see if a suspended process can be released and do
+ *                it
+ *   revive:	  mark a suspended process as able to run again
+ *   unsuspend_by_endpt: revive all processes blocking on a given process
+ *   do_unpause:  a signal has been sent to a process; see if it suspended
+ */
+
+#include "fs.h"
+#include <fcntl.h>
+#include <signal.h>
+#include <minix/callnr.h>
+#include <minix/endpoint.h>
+#include <minix/com.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "param.h"
+#include "super.h"
+#include "select.h"
+
+/*===========================================================================*
+ *				do_pipe					     *
+ *===========================================================================*/
+PUBLIC int do_pipe()
+{
+/* Perform the pipe(fil_des) system call. */
+
+  register struct fproc *rfp;
+  register struct inode *rip;
+  int r;
+  struct filp *fil_ptr0, *fil_ptr1;
+  int fil_des[2];		/* reply goes here */
+
+  /* Acquire two file descriptors. */
+  rfp = fp;
+  if ( (r = get_fd(0, R_BIT, &fil_des[0], &fil_ptr0)) != OK) return(r);
+  rfp->fp_filp[fil_des[0]] = fil_ptr0;
+  FD_SET(fil_des[0], &rfp->fp_filp_inuse);
+  fil_ptr0->filp_count = 1;
+  if ( (r = get_fd(0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) {
+	rfp->fp_filp[fil_des[0]] = NIL_FILP;
+  	FD_CLR(fil_des[0], &rfp->fp_filp_inuse);
+	fil_ptr0->filp_count = 0;
+	return(r);
+  }
+  rfp->fp_filp[fil_des[1]] = fil_ptr1;
+  FD_SET(fil_des[1], &rfp->fp_filp_inuse);
+  fil_ptr1->filp_count = 1;
+
+  /* Make the inode on the pipe device. */
+  if ( (rip = alloc_inode(root_dev, I_REGULAR) ) == NIL_INODE) {
+	rfp->fp_filp[fil_des[0]] = NIL_FILP;
+  	FD_CLR(fil_des[0], &rfp->fp_filp_inuse);
+	fil_ptr0->filp_count = 0;
+	rfp->fp_filp[fil_des[1]] = NIL_FILP;
+  	FD_CLR(fil_des[1], &rfp->fp_filp_inuse);
+	fil_ptr1->filp_count = 0;
+	return(err_code);
+  }
+
+  if (read_only(rip) != OK) 
+  	panic(__FILE__,"pipe device is read only", NO_NUM);
+ 
+  rip->i_pipe = I_PIPE;
+  rip->i_mode &= ~I_REGULAR;
+  rip->i_mode |= I_NAMED_PIPE;	/* pipes and FIFOs have this bit set */
+  fil_ptr0->filp_ino = rip;
+  fil_ptr0->filp_flags = O_RDONLY;
+  dup_inode(rip);		/* for double usage */
+  fil_ptr1->filp_ino = rip;
+  fil_ptr1->filp_flags = O_WRONLY;
+  rw_inode(rip, WRITING);	/* mark inode as allocated */
+  m_out.reply_i1 = fil_des[0];
+  m_out.reply_i2 = fil_des[1];
+  rip->i_update = ATIME | CTIME | MTIME;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				pipe_check				     *
+ *===========================================================================*/
+PUBLIC int pipe_check(rip, rw_flag, oflags, bytes, position, canwrite, notouch)
+register struct inode *rip;	/* the inode of the pipe */
+int rw_flag;			/* READING or WRITING */
+int oflags;			/* flags set by open or fcntl */
+register int bytes;		/* bytes to be read or written (all chunks) */
+register off_t position;	/* current file position */
+int *canwrite;			/* return: number of bytes we can write */
+int notouch;			/* check only */
+{
+/* Pipes are a little different.  If a process reads from an empty pipe for
+ * which a writer still exists, suspend the reader.  If the pipe is empty
+ * and there is no writer, return 0 bytes.  If a process is writing to a
+ * pipe and no one is reading from it, give a broken pipe error.
+ */
+
+  /* If reading, check for empty pipe. */
+  if (rw_flag == READING) {
+	if (position >= rip->i_size) {
+		/* Process is reading from an empty pipe. */
+		int r = 0;
+		if (find_filp(rip, W_BIT) != NIL_FILP) {
+			/* Writer exists */
+			if (oflags & O_NONBLOCK) {
+				r = EAGAIN;
+			} else {
+				if (!notouch)
+					suspend(XPIPE);	/* block reader */
+				r = SUSPEND;
+			}
+			/* If need be, activate sleeping writers. */
+			if (susp_count > 0 && !notouch)
+				release(rip, WRITE, susp_count);
+		}
+		return(r);
+	}
+  } else {
+	/* Process is writing to a pipe. */
+	if (find_filp(rip, R_BIT) == NIL_FILP) {
+		/* Tell kernel to generate a SIGPIPE signal. */
+		if (!notouch) {
+			sys_kill(fp->fp_endpoint, SIGPIPE);
+		}
+		return(EPIPE);
+	}
+
+	if (position + bytes > PIPE_SIZE(rip->i_sp->s_block_size)) {
+		if ((oflags & O_NONBLOCK)
+		 && bytes < PIPE_SIZE(rip->i_sp->s_block_size))
+			return(EAGAIN);
+		else if ((oflags & O_NONBLOCK)
+		&& bytes > PIPE_SIZE(rip->i_sp->s_block_size)) {
+		if ( (*canwrite = (PIPE_SIZE(rip->i_sp->s_block_size) 
+			- position)) > 0)  {
+				/* Do a partial write. Need to wakeup reader */
+				if (!notouch)
+					release(rip, READ, susp_count);
+				return(1);
+			} else {
+				return(EAGAIN);
+			}
+		     }
+		if (bytes > PIPE_SIZE(rip->i_sp->s_block_size)) {
+			if ((*canwrite = PIPE_SIZE(rip->i_sp->s_block_size) 
+				- position) > 0) {
+				/* Do a partial write. Need to wakeup reader
+				 * since we'll suspend ourself in read_write()
+				 */
+				if (!notouch)
+					release(rip, READ, susp_count);
+				return(1);
+			}
+		}
+		if (!notouch)
+			suspend(XPIPE);	/* stop writer -- pipe full */
+		return(SUSPEND);
+	}
+
+	/* Writing to an empty pipe.  Search for suspended reader. */
+	if (position == 0 && !notouch)
+		release(rip, READ, susp_count);
+  }
+
+  *canwrite = 0;
+  return(1);
+}
+
+/*===========================================================================*
+ *				suspend					     *
+ *===========================================================================*/
+PUBLIC void suspend(task)
+int task;			/* who is proc waiting for? (PIPE = pipe) */
+{
+/* Take measures to suspend the processing of the present system call.
+ * Store the parameters to be used upon resuming in the process table.
+ * (Actually they are not used when a process is waiting for an I/O device,
+ * but they are needed for pipes, and it is not worth making the distinction.)
+ * The SUSPEND pseudo error should be returned after calling suspend().
+ */
+
+  if (task == XPIPE || task == XPOPEN) susp_count++;/* #procs susp'ed on pipe*/
+  fp->fp_suspended = SUSPENDED;
+  fp->fp_fd = m_in.fd << 8 | call_nr;
+  if(task == NONE)
+	panic(__FILE__,"suspend on NONE",NO_NUM);
+  fp->fp_task = -task;
+  if (task == XLOCK) {
+	fp->fp_buffer = (char *) m_in.name1;	/* third arg to fcntl() */
+	fp->fp_nbytes = m_in.request;		/* second arg to fcntl() */
+  } else {
+	fp->fp_buffer = m_in.buffer;		/* for reads and writes */
+	fp->fp_nbytes = m_in.nbytes;
+  }
+}
+
+/*===========================================================================*
+ *				unsuspend_by_endpt			     *
+ *===========================================================================*/
+PUBLIC void unsuspend_by_endpt(int proc_e)
+{
+  struct fproc *rp;
+  int client = 0;
+
+  /* Revive processes waiting for drivers (SUSPENDed) that have
+   * disappeared with return code EAGAIN.
+   */
+  for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++, client++)
+	if(rp->fp_pid != PID_FREE &&
+	   rp->fp_suspended == SUSPENDED && rp->fp_task == -proc_e) {
+		revive(rp->fp_endpoint, EAGAIN);
+	}
+
+  /* Revive processes waiting in drivers on select()s
+   * with EAGAIN too.
+   */
+  select_unsuspend_by_endpt(proc_e);
+
+  return;
+}
+
+
+/*===========================================================================*
+ *				release					     *
+ *===========================================================================*/
+PUBLIC void release(ip, call_nr, count)
+register struct inode *ip;	/* inode of pipe */
+int call_nr;			/* READ, WRITE, OPEN or CREAT */
+int count;			/* max number of processes to release */
+{
+/* Check to see if any process is hanging on the pipe whose inode is in 'ip'.
+ * If one is, and it was trying to perform the call indicated by 'call_nr',
+ * release it.
+ */
+
+  register struct fproc *rp;
+  struct filp *f;
+
+  /* Trying to perform the call also includes SELECTing on it with that
+   * operation.
+   */
+  if (call_nr == READ || call_nr == WRITE) {
+  	  int op;
+  	  if (call_nr == READ)
+  	  	op = SEL_RD;
+  	  else
+  	  	op = SEL_WR;
+	  for(f = &filp[0]; f < &filp[NR_FILPS]; f++) {
+  		if (f->filp_count < 1 || !(f->filp_pipe_select_ops & op) ||
+  		   f->filp_ino != ip)
+  			continue;
+  		 select_callback(f, op);
+		f->filp_pipe_select_ops &= ~op;
+  	}
+  }
+
+  /* Search the proc table. */
+  for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++) {
+	if (rp->fp_pid != PID_FREE && rp->fp_suspended == SUSPENDED &&
+			rp->fp_revived == NOT_REVIVING &&
+			(rp->fp_fd & BYTE) == call_nr &&
+			rp->fp_filp[rp->fp_fd>>8]->filp_ino == ip) {
+		revive(rp->fp_endpoint, 0);
+		susp_count--;	/* keep track of who is suspended */
+		if (--count == 0) return;
+	}
+  }
+}
+
+/*===========================================================================*
+ *				revive					     *
+ *===========================================================================*/
+PUBLIC void revive(proc_nr_e, returned)
+int proc_nr_e;			/* process to revive */
+int returned;			/* if hanging on task, how many bytes read */
+{
+/* Revive a previously blocked process. When a process hangs on tty, this
+ * is the way it is eventually released.
+ */
+
+  register struct fproc *rfp;
+  register int task;
+  int proc_nr;
+
+  if(isokendpt(proc_nr_e, &proc_nr) != OK)
+	return;
+
+  rfp = &fproc[proc_nr];
+  if (rfp->fp_suspended == NOT_SUSPENDED || rfp->fp_revived == REVIVING)return;
+
+  /* The 'reviving' flag only applies to pipes.  Processes waiting for TTY get
+   * a message right away.  The revival process is different for TTY and pipes.
+   * For select and TTY revival, the work is already done, for pipes it is not:
+   *  the proc must be restarted so it can try again.
+   */
+  task = -rfp->fp_task;
+  if (task == XPIPE || task == XLOCK) {
+	/* Revive a process suspended on a pipe or lock. */
+	rfp->fp_revived = REVIVING;
+	reviving++;		/* process was waiting on pipe or lock */
+  } else {
+	rfp->fp_suspended = NOT_SUSPENDED;
+	if (task == XPOPEN) /* process blocked in open or create */
+		reply(proc_nr_e, rfp->fp_fd>>8);
+	else if (task == XSELECT) {
+		reply(proc_nr_e, returned);
+	} else {
+		/* Revive a process suspended on TTY or other device. */
+		rfp->fp_nbytes = returned;	/*pretend it wants only what there is*/
+		reply(proc_nr_e, returned);	/* unblock the process */
+	}
+  }
+}
+
+/*===========================================================================*
+ *				do_unpause				     *
+ *===========================================================================*/
+PUBLIC int do_unpause()
+{
+/* A signal has been sent to a user who is paused on the file system.
+ * Abort the system call with the EINTR error message.
+ */
+
+  register struct fproc *rfp;
+  int proc_nr_e, proc_nr_p, task, fild;
+  struct filp *f;
+  dev_t dev;
+  message mess;
+
+  if (who_e != PM_PROC_NR) return(EPERM);
+  proc_nr_e = m_in.ENDPT;
+  okendpt(proc_nr_e, &proc_nr_p);
+  rfp = &fproc[proc_nr_p];
+  if (rfp->fp_suspended == NOT_SUSPENDED) return(OK);
+  task = -rfp->fp_task;
+
+  switch (task) {
+	case XPIPE:		/* process trying to read or write a pipe */
+		break;
+
+	case XLOCK:		/* process trying to set a lock with FCNTL */
+		break;
+
+	case XSELECT:		/* process blocking on select() */
+		select_forget(proc_nr_e);
+		break;
+
+	case XPOPEN:		/* process trying to open a fifo */
+		break;
+
+	default:		/* process trying to do device I/O (e.g. tty)*/
+		fild = (rfp->fp_fd >> 8) & BYTE;/* extract file descriptor */
+		if (fild < 0 || fild >= OPEN_MAX)
+			panic(__FILE__,"unpause err 2",NO_NUM);
+		f = rfp->fp_filp[fild];
+		dev = (dev_t) f->filp_ino->i_zone[0];	/* device hung on */
+		mess.TTY_LINE = (dev >> MINOR) & BYTE;
+		mess.IO_ENDPT = proc_nr_e;
+
+		/* Tell kernel R or W. Mode is from current call, not open. */
+		mess.COUNT = (rfp->fp_fd & BYTE) == READ ? R_BIT : W_BIT;
+		mess.m_type = CANCEL;
+		fp = rfp;	/* hack - ctty_io uses fp */
+		(*dmap[(dev >> MAJOR) & BYTE].dmap_io)(task, &mess);
+  }
+
+  rfp->fp_suspended = NOT_SUSPENDED;
+  reply(proc_nr_e, EINTR);	/* signal interrupted call */
+  return(OK);
+}
+
+/*===========================================================================*
+ *				select_request_pipe			     *
+ *===========================================================================*/
+PUBLIC int select_request_pipe(struct filp *f, int *ops, int block)
+{
+	int orig_ops, r = 0, err, canwrite;
+	orig_ops = *ops;
+	if ((*ops & (SEL_RD|SEL_ERR))) {
+		if ((err = pipe_check(f->filp_ino, READING, 0,
+			1, f->filp_pos, &canwrite, 1)) != SUSPEND && err > 0)
+			r |= SEL_RD;
+		if (err < 0 && err != SUSPEND)
+			r |= SEL_ERR;
+	}
+	if ((*ops & (SEL_WR|SEL_ERR))) {
+		if ((err = pipe_check(f->filp_ino, WRITING, 0,
+			1, f->filp_pos, &canwrite, 1)) != SUSPEND &&
+			err > 0 && canwrite > 0)
+			r |= SEL_WR;
+		if (err < 0 && err != SUSPEND)
+			r |= SEL_ERR;
+	}
+
+	/* Some options we collected might not be requested. */
+	*ops = r & orig_ops;
+
+	if (!*ops && block) {
+		f->filp_pipe_select_ops |= orig_ops;
+	}
+
+	return SEL_OK;
+}
+
+/*===========================================================================*
+ *				select_match_pipe			     *
+ *===========================================================================*/
+PUBLIC int select_match_pipe(struct filp *f)
+{
+	/* recognize either pipe or named pipe (FIFO) */
+	if (f && f->filp_ino && (f->filp_ino->i_mode & I_NAMED_PIPE))
+		return 1;
+	return 0;
+}
+
Index: /trunk/minix/servers/fs/protect.c
===================================================================
--- /trunk/minix/servers/fs/protect.c	(revision 9)
+++ /trunk/minix/servers/fs/protect.c	(revision 9)
@@ -0,0 +1,211 @@
+/* This file deals with protection in the file system.  It contains the code
+ * for four system calls that relate to protection.
+ *
+ * The entry points into this file are
+ *   do_chmod:	perform the CHMOD system call
+ *   do_chown:	perform the CHOWN system call
+ *   do_umask:	perform the UMASK system call
+ *   do_access:	perform the ACCESS system call
+ *   forbidden:	check to see if a given access is allowed on a given inode
+ */
+
+#include "fs.h"
+#include <unistd.h>
+#include <minix/callnr.h>
+#include "buf.h"
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "param.h"
+#include "super.h"
+
+/*===========================================================================*
+ *				do_chmod				     *
+ *===========================================================================*/
+PUBLIC int do_chmod()
+{
+/* Perform the chmod(name, mode) system call. */
+
+  register struct inode *rip;
+  register int r;
+
+  /* Temporarily open the file. */
+  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
+  if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
+
+  /* Only the owner or the super_user may change the mode of a file.
+   * No one may change the mode of a file on a read-only file system.
+   */
+  if (rip->i_uid != fp->fp_effuid && !super_user)
+	r = EPERM;
+  else
+	r = read_only(rip);
+
+  /* If error, return inode. */
+  if (r != OK)	{
+	put_inode(rip);
+	return(r);
+  }
+
+  /* Now make the change. Clear setgid bit if file is not in caller's grp */
+  rip->i_mode = (rip->i_mode & ~ALL_MODES) | (m_in.mode & ALL_MODES);
+  if (!super_user && rip->i_gid != fp->fp_effgid)rip->i_mode &= ~I_SET_GID_BIT;
+  rip->i_update |= CTIME;
+  rip->i_dirt = DIRTY;
+
+  put_inode(rip);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_chown				     *
+ *===========================================================================*/
+PUBLIC int do_chown()
+{
+/* Perform the chown(name, owner, group) system call. */
+
+  register struct inode *rip;
+  register int r;
+
+  /* Temporarily open the file. */
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+  if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
+
+  /* Not permitted to change the owner of a file on a read-only file sys. */
+  r = read_only(rip);
+  if (r == OK) {
+	/* FS is R/W.  Whether call is allowed depends on ownership, etc. */
+	if (super_user) {
+		/* The super user can do anything. */
+		rip->i_uid = m_in.owner;	/* others later */
+	} else {
+		/* Regular users can only change groups of their own files. */
+		if (rip->i_uid != fp->fp_effuid) r = EPERM;
+		if (rip->i_uid != m_in.owner) r = EPERM;  /* no giving away */
+		if (fp->fp_effgid != m_in.group) r = EPERM;
+	}
+  }
+  if (r == OK) {
+	rip->i_gid = m_in.group;
+	rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT);
+	rip->i_update |= CTIME;
+	rip->i_dirt = DIRTY;
+  }
+
+  put_inode(rip);
+  return(r);
+}
+
+/*===========================================================================*
+ *				do_umask				     *
+ *===========================================================================*/
+PUBLIC int do_umask()
+{
+/* Perform the umask(co_mode) system call. */
+  register mode_t r;
+
+  r = ~fp->fp_umask;		/* set 'r' to complement of old mask */
+  fp->fp_umask = ~(m_in.co_mode & RWX_MODES);
+  return(r);			/* return complement of old mask */
+}
+
+/*===========================================================================*
+ *				do_access				     *
+ *===========================================================================*/
+PUBLIC int do_access()
+{
+/* Perform the access(name, mode) system call. */
+
+  struct inode *rip;
+  register int r;
+
+  /* First check to see if the mode is correct. */
+  if ( (m_in.mode & ~(R_OK | W_OK | X_OK)) != 0 && m_in.mode != F_OK)
+	return(EINVAL);
+
+  /* Temporarily open the file whose access is to be checked. */
+  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
+  if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
+
+  /* Now check the permissions. */
+  r = forbidden(rip, (mode_t) m_in.mode);
+  put_inode(rip);
+  return(r);
+}
+
+/*===========================================================================*
+ *				forbidden				     *
+ *===========================================================================*/
+PUBLIC int forbidden(register struct inode *rip, mode_t access_desired)
+{
+/* Given a pointer to an inode, 'rip', and the access desired, determine
+ * if the access is allowed, and if not why not.  The routine looks up the
+ * caller's uid in the 'fproc' table.  If access is allowed, OK is returned
+ * if it is forbidden, EACCES is returned.
+ */
+
+  register struct inode *old_rip = rip;
+  register struct super_block *sp;
+  register mode_t bits, perm_bits;
+  int r, shift, test_uid, test_gid, type;
+
+  if (rip->i_mount == I_MOUNT)	/* The inode is mounted on. */
+	for (sp = &super_block[1]; sp < &super_block[NR_SUPERS]; sp++)
+		if (sp->s_imount == rip) {
+			rip = get_inode(sp->s_dev, ROOT_INODE);
+			break;
+		} /* if */
+
+  /* Isolate the relevant rwx bits from the mode. */
+  bits = rip->i_mode;
+  test_uid = (call_nr == ACCESS ? fp->fp_realuid : fp->fp_effuid);
+  test_gid = (call_nr == ACCESS ? fp->fp_realgid : fp->fp_effgid);
+  if (test_uid == SU_UID) {
+	/* Grant read and write permission.  Grant search permission for
+	 * directories.  Grant execute permission (for non-directories) if
+	 * and only if one of the 'X' bits is set.
+	 */
+	if ( (bits & I_TYPE) == I_DIRECTORY ||
+	     bits & ((X_BIT << 6) | (X_BIT << 3) | X_BIT))
+		perm_bits = R_BIT | W_BIT | X_BIT;
+	else
+		perm_bits = R_BIT | W_BIT;
+  } else {
+	if (test_uid == rip->i_uid) shift = 6;		/* owner */
+	else if (test_gid == rip->i_gid ) shift = 3;	/* group */
+	else shift = 0;					/* other */
+	perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
+  }
+
+  /* If access desired is not a subset of what is allowed, it is refused. */
+  r = OK;
+  if ((perm_bits | access_desired) != perm_bits) r = EACCES;
+
+  /* Check to see if someone is trying to write on a file system that is
+   * mounted read-only.
+   */
+  type = rip->i_mode & I_TYPE;
+  if (r == OK)
+	if (access_desired & W_BIT)
+	 	r = read_only(rip);
+
+  if (rip != old_rip) put_inode(rip);
+
+  return(r);
+}
+
+/*===========================================================================*
+ *				read_only				     *
+ *===========================================================================*/
+PUBLIC int read_only(ip)
+struct inode *ip;		/* ptr to inode whose file sys is to be cked */
+{
+/* Check to see if the file system on which the inode 'ip' resides is mounted
+ * read only.  If so, return EROFS, else return OK.
+ */
+
+  register struct super_block *sp;
+
+  sp = ip->i_sp;
+  return(sp->s_rd_only ? EROFS : OK);
+}
Index: /trunk/minix/servers/fs/proto.h
===================================================================
--- /trunk/minix/servers/fs/proto.h	(revision 9)
+++ /trunk/minix/servers/fs/proto.h	(revision 9)
@@ -0,0 +1,216 @@
+/* Function prototypes. */
+
+#include "timers.h"
+
+/* Structs used in prototypes must be declared as such first. */
+struct buf;
+struct filp;		
+struct inode;
+struct super_block;
+
+/* cache.c */
+_PROTOTYPE( zone_t alloc_zone, (Dev_t dev, zone_t z)			);
+_PROTOTYPE( void flushall, (Dev_t dev)					);
+_PROTOTYPE( void free_zone, (Dev_t dev, zone_t numb)			);
+_PROTOTYPE( struct buf *get_block, (Dev_t dev, block_t block,int only_search));
+_PROTOTYPE( void invalidate, (Dev_t device)				);
+_PROTOTYPE( void put_block, (struct buf *bp, int block_type)		);
+_PROTOTYPE( void rw_scattered, (Dev_t dev,
+			struct buf **bufq, int bufqsize, int rw_flag)	);
+
+#if ENABLE_CACHE2
+/* cache2.c */
+_PROTOTYPE( void init_cache2, (unsigned long size)			);
+_PROTOTYPE( int get_block2, (struct buf *bp, int only_search)		);
+_PROTOTYPE( void put_block2, (struct buf *bp)				);
+_PROTOTYPE( void invalidate2, (Dev_t device)				);
+#endif
+
+/* device.c */
+_PROTOTYPE( int dev_open, (Dev_t dev, int proc, int flags)		);
+_PROTOTYPE( void dev_close, (Dev_t dev)					);
+_PROTOTYPE( int dev_io, (int op, Dev_t dev, int proc, void *buf,
+			off_t pos, int bytes, int flags)		);
+_PROTOTYPE( int gen_opcl, (int op, Dev_t dev, int proc, int flags)	);
+_PROTOTYPE( int gen_io, (int task_nr, message *mess_ptr)		);
+_PROTOTYPE( int no_dev, (int op, Dev_t dev, int proc, int flags)	);
+_PROTOTYPE( int no_dev_io, (int, message *)				);
+_PROTOTYPE( int tty_opcl, (int op, Dev_t dev, int proc, int flags)	);
+_PROTOTYPE( int ctty_opcl, (int op, Dev_t dev, int proc, int flags)	);
+_PROTOTYPE( int clone_opcl, (int op, Dev_t dev, int proc, int flags)	);
+_PROTOTYPE( int ctty_io, (int task_nr, message *mess_ptr)		);
+_PROTOTYPE( int do_ioctl, (void)					);
+_PROTOTYPE( int do_setsid, (void)					);
+_PROTOTYPE( void dev_status, (message *)				);
+_PROTOTYPE( void dev_up, (int major)					);
+
+/* dmp.c */
+_PROTOTYPE( int do_fkey_pressed, (void)					);
+
+/* dmap.c */
+_PROTOTYPE( int do_devctl, (void)					);
+_PROTOTYPE( void build_dmap, (void)					);
+_PROTOTYPE( int map_driver, (int major, int proc_nr, int dev_style)	);
+_PROTOTYPE( int dmap_driver_match, (int proc, int major)		);
+_PROTOTYPE( void dmap_unmap_by_endpt, (int proc_nr)			);
+_PROTOTYPE( void dmap_endpt_up, (int proc_nr)				);
+
+/* filedes.c */
+_PROTOTYPE( struct filp *find_filp, (struct inode *rip, mode_t bits)	);
+_PROTOTYPE( int get_fd, (int start, mode_t bits, int *k, struct filp **fpt) );
+_PROTOTYPE( struct filp *get_filp, (int fild)				);
+_PROTOTYPE( int inval_filp, (struct filp *)				);
+
+/* inode.c */
+_PROTOTYPE( struct inode *alloc_inode, (dev_t dev, mode_t bits)		);
+_PROTOTYPE( void dup_inode, (struct inode *ip)				);
+_PROTOTYPE( void free_inode, (Dev_t dev, Ino_t numb)			);
+_PROTOTYPE( struct inode *get_inode, (Dev_t dev, int numb)		);
+_PROTOTYPE( void put_inode, (struct inode *rip)				);
+_PROTOTYPE( void update_times, (struct inode *rip)			);
+_PROTOTYPE( void rw_inode, (struct inode *rip, int rw_flag)		);
+_PROTOTYPE( void wipe_inode, (struct inode *rip)			);
+
+/* link.c */
+_PROTOTYPE( int do_link, (void)						);
+_PROTOTYPE( int do_unlink, (void)					);
+_PROTOTYPE( int do_rename, (void)					);
+_PROTOTYPE( int do_truncate, (void)					);
+_PROTOTYPE( int do_ftruncate, (void)					);
+_PROTOTYPE( int truncate_inode, (struct inode *rip, off_t len)		);
+_PROTOTYPE( int freesp_inode, (struct inode *rip, off_t st, off_t end)	);
+
+/* lock.c */
+_PROTOTYPE( int lock_op, (struct filp *f, int req)			);
+_PROTOTYPE( void lock_revive, (void)					);
+
+/* main.c */
+_PROTOTYPE( int main, (void)						);
+_PROTOTYPE( void reply, (int whom, int result)				);
+
+/* misc.c */
+_PROTOTYPE( int do_dup, (void)						);
+_PROTOTYPE( int do_exit, (void)						);
+_PROTOTYPE( int do_fcntl, (void)					);
+_PROTOTYPE( int do_fork, (void)						);
+_PROTOTYPE( int do_exec, (void)						);
+_PROTOTYPE( int do_revive, (void)					);
+_PROTOTYPE( int do_set, (void)						);
+_PROTOTYPE( int do_sync, (void)						);
+_PROTOTYPE( int do_fsync, (void)					);
+_PROTOTYPE( int do_reboot, (void)					);
+_PROTOTYPE( int do_svrctl, (void)					);
+_PROTOTYPE( int do_getsysinfo, (void)					);
+
+/* mount.c */
+_PROTOTYPE( int do_mount, (void)					);
+_PROTOTYPE( int do_umount, (void)					);
+_PROTOTYPE( int unmount, (Dev_t dev)					);
+
+/* open.c */
+_PROTOTYPE( int do_close, (void)					);
+_PROTOTYPE( int do_creat, (void)					);
+_PROTOTYPE( int do_lseek, (void)					);
+_PROTOTYPE( int do_mknod, (void)					);
+_PROTOTYPE( int do_mkdir, (void)					);
+_PROTOTYPE( int do_open, (void)						);
+_PROTOTYPE( int do_slink, (void)                                       );
+
+/* path.c */
+_PROTOTYPE( struct inode *advance,(struct inode **dirp, char string[NAME_MAX]));
+_PROTOTYPE( int search_dir, (struct inode *ldir_ptr,
+			char string [NAME_MAX], ino_t *numb, int flag)	);
+_PROTOTYPE( struct inode *eat_path, (char *path)			);
+_PROTOTYPE( struct inode *last_dir, (char *path, char string [NAME_MAX]));
+_PROTOTYPE( struct inode *parse_path, (char *path, char string[NAME_MAX], 
+                                                       int action)     );
+
+/* pipe.c */
+_PROTOTYPE( int do_pipe, (void)						);
+_PROTOTYPE( int do_unpause, (void)					);
+_PROTOTYPE( int pipe_check, (struct inode *rip, int rw_flag,
+			int oflags, int bytes, off_t position, int *canwrite, int notouch));
+_PROTOTYPE( void release, (struct inode *ip, int call_nr, int count)	);
+_PROTOTYPE( void revive, (int proc_nr, int bytes)			);
+_PROTOTYPE( void suspend, (int task)					);
+_PROTOTYPE( int select_request_pipe, (struct filp *f, int *ops, int bl)	);
+_PROTOTYPE( int select_cancel_pipe, (struct filp *f)			);
+_PROTOTYPE( int select_match_pipe, (struct filp *f)			);
+_PROTOTYPE( void unsuspend_by_endpt, (int)				);
+
+/* protect.c */
+_PROTOTYPE( int do_access, (void)					);
+_PROTOTYPE( int do_chmod, (void)					);
+_PROTOTYPE( int do_chown, (void)					);
+_PROTOTYPE( int do_umask, (void)					);
+_PROTOTYPE( int forbidden, (struct inode *rip, mode_t access_desired)	);
+_PROTOTYPE( int read_only, (struct inode *ip)				);
+
+/* read.c */
+_PROTOTYPE( int do_read, (void)						);
+_PROTOTYPE( struct buf *rahead, (struct inode *rip, block_t baseblock,
+			off_t position, unsigned bytes_ahead)		);
+_PROTOTYPE( void read_ahead, (void)					);
+_PROTOTYPE( block_t read_map, (struct inode *rip, off_t pos)		);
+_PROTOTYPE( int read_write, (int rw_flag)				);
+_PROTOTYPE( zone_t rd_indir, (struct buf *bp, int index)		);
+
+/* stadir.c */
+_PROTOTYPE( int do_chdir, (void)					);
+_PROTOTYPE( int do_fchdir, (void)					);
+_PROTOTYPE( int do_chroot, (void)					);
+_PROTOTYPE( int do_fstat, (void)					);
+_PROTOTYPE( int do_stat, (void)						);
+_PROTOTYPE( int do_fstatfs, (void)					);
+_PROTOTYPE( int do_rdlink, (void)                                      );
+_PROTOTYPE( int do_lstat, (void)                                       );
+
+/* super.c */
+_PROTOTYPE( bit_t alloc_bit, (struct super_block *sp, int map, bit_t origin));
+_PROTOTYPE( void free_bit, (struct super_block *sp, int map,
+						bit_t bit_returned)	);
+_PROTOTYPE( struct super_block *get_super, (Dev_t dev)			);
+_PROTOTYPE( int mounted, (struct inode *rip)				);
+_PROTOTYPE( int read_super, (struct super_block *sp)			);
+_PROTOTYPE( int get_block_size, (dev_t dev)				);
+
+/* time.c */
+_PROTOTYPE( int do_stime, (void)					);
+_PROTOTYPE( int do_utime, (void)					);
+
+/* utility.c */
+_PROTOTYPE( time_t clock_time, (void)					);
+_PROTOTYPE( unsigned conv2, (int norm, int w)				);
+_PROTOTYPE( long conv4, (int norm, long x)				);
+_PROTOTYPE( int fetch_name, (char *path, int len, int flag)		);
+_PROTOTYPE( int no_sys, (void)						);
+_PROTOTYPE( int isokendpt_f, (char *f, int l, int e, int *p, int ft));
+_PROTOTYPE( void panic, (char *who, char *mess, int num)		);
+
+#define okendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 1)
+#define isokendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 0)
+
+/* write.c */
+_PROTOTYPE( void clear_zone, (struct inode *rip, off_t pos, int flag)	);
+_PROTOTYPE( int do_write, (void)					);
+_PROTOTYPE( struct buf *new_block, (struct inode *rip, off_t position)	);
+_PROTOTYPE( void zero_block, (struct buf *bp)				);
+_PROTOTYPE( int write_map, (struct inode *, off_t, zone_t, int)		);
+
+/* select.c */
+_PROTOTYPE( int do_select, (void)					);
+_PROTOTYPE( int select_callback, (struct filp *, int ops)		);
+_PROTOTYPE( void select_forget, (int fproc)				);
+_PROTOTYPE( void select_timeout_check, (timer_t *)			);
+_PROTOTYPE( void init_select, (void)					);
+_PROTOTYPE( void select_unsuspend_by_endpt, (int proc)			);
+_PROTOTYPE( int select_notified, (int major, int minor, int ops)	);
+
+/* timers.c */
+_PROTOTYPE( void fs_set_timer, (timer_t *tp, int delta, tmr_func_t watchdog, int arg));
+_PROTOTYPE( void fs_expire_timers, (clock_t now)			);
+_PROTOTYPE( void fs_cancel_timer, (timer_t *tp)				);
+_PROTOTYPE( void fs_init_timer, (timer_t *tp)				);
+
+/* cdprobe.c */
+_PROTOTYPE( int cdprobe, (void)						);
Index: /trunk/minix/servers/fs/read.c
===================================================================
--- /trunk/minix/servers/fs/read.c	(revision 9)
+++ /trunk/minix/servers/fs/read.c	(revision 9)
@@ -0,0 +1,560 @@
+/* This file contains the heart of the mechanism used to read (and write)
+ * files.  Read and write requests are split up into chunks that do not cross
+ * block boundaries.  Each chunk is then processed in turn.  Reads on special
+ * files are also detected and handled.
+ *
+ * The entry points into this file are
+ *   do_read:	 perform the READ system call by calling read_write
+ *   read_write: actually do the work of READ and WRITE
+ *   read_map:	 given an inode and file position, look up its zone number
+ *   rd_indir:	 read an entry in an indirect block 
+ *   read_ahead: manage the block read ahead business
+ */
+
+#include "fs.h"
+#include <fcntl.h>
+#include <unistd.h>
+#include <minix/com.h>
+#include "buf.h"
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "param.h"
+#include "super.h"
+
+FORWARD _PROTOTYPE( int rw_chunk, (struct inode *rip, off_t position,
+	unsigned off, int chunk, unsigned left, int rw_flag,
+	char *buff, int seg, int usr, int block_size, int *completed));
+
+/*===========================================================================*
+ *				do_read					     *
+ *===========================================================================*/
+PUBLIC int do_read()
+{
+  return(read_write(READING));
+}
+
+/*===========================================================================*
+ *				read_write				     *
+ *===========================================================================*/
+PUBLIC int read_write(rw_flag)
+int rw_flag;			/* READING or WRITING */
+{
+/* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */
+
+  register struct inode *rip;
+  register struct filp *f;
+  off_t bytes_left, f_size, position;
+  unsigned int off, cum_io;
+  int op, oflags, r, chunk, usr, seg, block_spec, char_spec;
+  int regular, partial_pipe = 0, partial_cnt = 0;
+  mode_t mode_word;
+  struct filp *wf;
+  int block_size;
+  int completed, r2 = OK;
+  phys_bytes p;
+
+  /* PM loads segments by putting funny things in other bits of the
+   * message, indicated by a high bit in fd.
+   */
+  if (who_e == PM_PROC_NR && (m_in.fd & _PM_SEG_FLAG)) {
+	seg = (int) m_in.m1_p2;
+	usr = (int) m_in.m1_p3;
+	m_in.fd &= ~(_PM_SEG_FLAG);	/* get rid of flag bit */
+  } else {
+	usr = who_e;		/* normal case */
+	seg = D;
+  }
+
+  /* If the file descriptor is valid, get the inode, size and mode. */
+  if (m_in.nbytes < 0) return(EINVAL);
+  if ((f = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
+  if (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) {
+	return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);
+  }
+  if (m_in.nbytes == 0)
+  	 return(0);	/* so char special files need not check for 0*/
+
+  /* check if user process has the memory it needs.
+   * if not, copying will fail later.
+   * do this after 0-check above because umap doesn't want to map 0 bytes.
+   */
+  if ((r = sys_umap(usr, seg, (vir_bytes) m_in.buffer, m_in.nbytes, &p)) != OK) {
+	printf("FS: read_write: umap failed for process %d\n", usr);
+	return r;
+  }
+  position = f->filp_pos;
+  oflags = f->filp_flags;
+  rip = f->filp_ino;
+  f_size = rip->i_size;
+  r = OK;
+  if (rip->i_pipe == I_PIPE) {
+	/* fp->fp_cum_io_partial is only nonzero when doing partial writes */
+	cum_io = fp->fp_cum_io_partial; 
+  } else {
+	cum_io = 0;
+  }
+  op = (rw_flag == READING ? DEV_READ : DEV_WRITE);
+  mode_word = rip->i_mode & I_TYPE;
+  regular = mode_word == I_REGULAR || mode_word == I_NAMED_PIPE;
+
+  if ((char_spec = (mode_word == I_CHAR_SPECIAL ? 1 : 0))) {
+  	if (rip->i_zone[0] == NO_DEV)
+  		panic(__FILE__,"read_write tries to read from "
+  			"character device NO_DEV", NO_NUM);
+  	block_size = get_block_size(rip->i_zone[0]);
+  }
+  if ((block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0))) {
+  	f_size = ULONG_MAX;
+  	if (rip->i_zone[0] == NO_DEV)
+  		panic(__FILE__,"read_write tries to read from "
+  		" block device NO_DEV", NO_NUM);
+  	block_size = get_block_size(rip->i_zone[0]);
+  }
+
+  if (!char_spec && !block_spec)
+  	block_size = rip->i_sp->s_block_size;
+
+  rdwt_err = OK;		/* set to EIO if disk error occurs */
+
+  /* Check for character special files. */
+  if (char_spec) {
+  	dev_t dev;
+	dev = (dev_t) rip->i_zone[0];
+	r = dev_io(op, dev, usr, m_in.buffer, position, m_in.nbytes, oflags);
+	if (r >= 0) {
+		cum_io = r;
+		position += r;
+		r = OK;
+	}
+  } else {
+	if (rw_flag == WRITING && block_spec == 0) {
+		/* Check in advance to see if file will grow too big. */
+		if (position > rip->i_sp->s_max_size - m_in.nbytes) 
+			return(EFBIG);
+
+		/* Check for O_APPEND flag. */
+		if (oflags & O_APPEND) position = f_size;
+
+		/* Clear the zone containing present EOF if hole about
+		 * to be created.  This is necessary because all unwritten
+		 * blocks prior to the EOF must read as zeros.
+		 */
+		if (position > f_size) clear_zone(rip, f_size, 0);
+	}
+
+	/* Pipes are a little different.  Check. */
+	if (rip->i_pipe == I_PIPE) {
+	       r = pipe_check(rip, rw_flag, oflags,
+	       		m_in.nbytes, position, &partial_cnt, 0);
+	       if (r <= 0) return(r);
+	}
+
+	if (partial_cnt > 0) partial_pipe = 1;
+
+	/* Split the transfer into chunks that don't span two blocks. */
+	while (m_in.nbytes != 0) {
+
+		off = (unsigned int) (position % block_size);/* offset in blk*/
+		if (partial_pipe) {  /* pipes only */
+			chunk = MIN(partial_cnt, block_size - off);
+		} else
+			chunk = MIN(m_in.nbytes, block_size - off);
+		if (chunk < 0) chunk = block_size - off;
+
+		if (rw_flag == READING) {
+			bytes_left = f_size - position;
+			if (position >= f_size) break;	/* we are beyond EOF */
+			if (chunk > bytes_left) chunk = (int) bytes_left;
+		}
+
+		/* Read or write 'chunk' bytes. */
+		r = rw_chunk(rip, position, off, chunk, (unsigned) m_in.nbytes,
+			     rw_flag, m_in.buffer, seg, usr, block_size, &completed);
+
+		if (r != OK) break;	/* EOF reached */
+		if (rdwt_err < 0) break;
+
+		/* Update counters and pointers. */
+		m_in.buffer += chunk;	/* user buffer address */
+		m_in.nbytes -= chunk;	/* bytes yet to be read */
+		cum_io += chunk;	/* bytes read so far */
+		position += chunk;	/* position within the file */
+
+		if (partial_pipe) {
+			partial_cnt -= chunk;
+			if (partial_cnt <= 0)  break;
+		}
+	}
+  }
+
+  /* On write, update file size and access time. */
+  if (rw_flag == WRITING) {
+	if (regular || mode_word == I_DIRECTORY) {
+		if (position > f_size) rip->i_size = position;
+	}
+  } else {
+	if (rip->i_pipe == I_PIPE) {
+		if ( position >= rip->i_size) {
+			/* Reset pipe pointers. */
+			rip->i_size = 0;	/* no data left */
+			position = 0;		/* reset reader(s) */
+			wf = find_filp(rip, W_BIT);
+			if (wf != NIL_FILP) wf->filp_pos = 0;
+		}
+	}
+  }
+  f->filp_pos = position;
+
+  /* Check to see if read-ahead is called for, and if so, set it up. */
+  if (rw_flag == READING && rip->i_seek == NO_SEEK && position % block_size== 0
+		&& (regular || mode_word == I_DIRECTORY)) {
+	rdahed_inode = rip;
+	rdahedpos = position;
+  }
+  rip->i_seek = NO_SEEK;
+
+  if (rdwt_err != OK) r = rdwt_err;	/* check for disk error */
+  if (rdwt_err == END_OF_FILE) r = OK;
+
+  /* if user-space copying failed, read/write failed. */
+  if (r == OK && r2 != OK) {
+	r = r2;
+  }
+  if (r == OK) {
+	if (rw_flag == READING) rip->i_update |= ATIME;
+	if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;
+	rip->i_dirt = DIRTY;		/* inode is thus now dirty */
+	if (partial_pipe) {
+		partial_pipe = 0;
+			/* partial write on pipe with */
+		/* O_NONBLOCK, return write count */
+		if (!(oflags & O_NONBLOCK)) {
+			fp->fp_cum_io_partial = cum_io;
+			suspend(XPIPE);   /* partial write on pipe with */
+			return(SUSPEND);  /* nbyte > PIPE_SIZE - non-atomic */
+		}
+	}
+	fp->fp_cum_io_partial = 0;
+	return(cum_io);
+  }
+  return(r);
+}
+
+/*===========================================================================*
+ *				rw_chunk				     *
+ *===========================================================================*/
+PRIVATE int rw_chunk(rip, position, off, chunk, left, rw_flag, buff,
+ seg, usr, block_size, completed)
+register struct inode *rip;	/* pointer to inode for file to be rd/wr */
+off_t position;			/* position within file to read or write */
+unsigned off;			/* off within the current block */
+int chunk;			/* number of bytes to read or write */
+unsigned left;			/* max number of bytes wanted after position */
+int rw_flag;			/* READING or WRITING */
+char *buff;			/* virtual address of the user buffer */
+int seg;			/* T or D segment in user space */
+int usr;			/* which user process */
+int block_size;			/* block size of FS operating on */
+int *completed;			/* number of bytes copied */
+{
+/* Read or write (part of) a block. */
+
+  register struct buf *bp;
+  register int r = OK;
+  int n, block_spec;
+  block_t b;
+  dev_t dev;
+
+  *completed = 0;
+
+  block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL;
+  if (block_spec) {
+	b = position/block_size;
+	dev = (dev_t) rip->i_zone[0];
+  } else {
+	b = read_map(rip, position);
+	dev = rip->i_dev;
+  }
+
+  if (!block_spec && b == NO_BLOCK) {
+	if (rw_flag == READING) {
+		/* Reading from a nonexistent block.  Must read as all zeros.*/
+		bp = get_block(NO_DEV, NO_BLOCK, NORMAL);    /* get a buffer */
+		zero_block(bp);
+	} else {
+		/* Writing to a nonexistent block. Create and enter in inode.*/
+		if ((bp= new_block(rip, position)) == NIL_BUF)return(err_code);
+	}
+  } else if (rw_flag == READING) {
+	/* Read and read ahead if convenient. */
+	bp = rahead(rip, b, position, left);
+  } else {
+	/* Normally an existing block to be partially overwritten is first read
+	 * in.  However, a full block need not be read in.  If it is already in
+	 * the cache, acquire it, otherwise just acquire a free buffer.
+	 */
+	n = (chunk == block_size ? NO_READ : NORMAL);
+	if (!block_spec && off == 0 && position >= rip->i_size) n = NO_READ;
+	bp = get_block(dev, b, n);
+  }
+
+  /* In all cases, bp now points to a valid buffer. */
+  if (bp == NIL_BUF) {
+  	panic(__FILE__,"bp not valid in rw_chunk, this can't happen", NO_NUM);
+  }
+  if (rw_flag == WRITING && chunk != block_size && !block_spec &&
+					position >= rip->i_size && off == 0) {
+	zero_block(bp);
+  }
+
+  if (rw_flag == READING) {
+	/* Copy a chunk from the block buffer to user space. */
+	r = sys_vircopy(FS_PROC_NR, D, (phys_bytes) (bp->b_data+off),
+			usr, seg, (phys_bytes) buff,
+			(phys_bytes) chunk);
+  } else {
+	/* Copy a chunk from user space to the block buffer. */
+	r = sys_vircopy(usr, seg, (phys_bytes) buff,
+			FS_PROC_NR, D, (phys_bytes) (bp->b_data+off),
+			(phys_bytes) chunk);
+	bp->b_dirt = DIRTY;
+  }
+  n = (off + chunk == block_size ? FULL_DATA_BLOCK : PARTIAL_DATA_BLOCK);
+  put_block(bp, n);
+
+  return(r);
+}
+
+
+/*===========================================================================*
+ *				read_map				     *
+ *===========================================================================*/
+PUBLIC block_t read_map(rip, position)
+register struct inode *rip;	/* ptr to inode to map from */
+off_t position;			/* position in file whose blk wanted */
+{
+/* Given an inode and a position within the corresponding file, locate the
+ * block (not zone) number in which that position is to be found and return it.
+ */
+
+  register struct buf *bp;
+  register zone_t z;
+  int scale, boff, dzones, nr_indirects, index, zind, ex;
+  block_t b;
+  long excess, zone, block_pos;
+  
+  scale = rip->i_sp->s_log_zone_size;	/* for block-zone conversion */
+  block_pos = position/rip->i_sp->s_block_size;	/* relative blk # in file */
+  zone = block_pos >> scale;	/* position's zone */
+  boff = (int) (block_pos - (zone << scale) ); /* relative blk # within zone */
+  dzones = rip->i_ndzones;
+  nr_indirects = rip->i_nindirs;
+
+  /* Is 'position' to be found in the inode itself? */
+  if (zone < dzones) {
+	zind = (int) zone;	/* index should be an int */
+	z = rip->i_zone[zind];
+	if (z == NO_ZONE) return(NO_BLOCK);
+	b = ((block_t) z << scale) + boff;
+	return(b);
+  }
+
+  /* It is not in the inode, so it must be single or double indirect. */
+  excess = zone - dzones;	/* first Vx_NR_DZONES don't count */
+
+  if (excess < nr_indirects) {
+	/* 'position' can be located via the single indirect block. */
+	z = rip->i_zone[dzones];
+  } else {
+	/* 'position' can be located via the double indirect block. */
+	if ( (z = rip->i_zone[dzones+1]) == NO_ZONE) return(NO_BLOCK);
+	excess -= nr_indirects;			/* single indir doesn't count*/
+	b = (block_t) z << scale;
+	bp = get_block(rip->i_dev, b, NORMAL);	/* get double indirect block */
+	index = (int) (excess/nr_indirects);
+	z = rd_indir(bp, index);		/* z= zone for single*/
+	put_block(bp, INDIRECT_BLOCK);		/* release double ind block */
+	excess = excess % nr_indirects;		/* index into single ind blk */
+  }
+
+  /* 'z' is zone num for single indirect block; 'excess' is index into it. */
+  if (z == NO_ZONE) return(NO_BLOCK);
+  b = (block_t) z << scale;			/* b is blk # for single ind */
+  bp = get_block(rip->i_dev, b, NORMAL);	/* get single indirect block */
+  ex = (int) excess;				/* need an integer */
+  z = rd_indir(bp, ex);				/* get block pointed to */
+  put_block(bp, INDIRECT_BLOCK);		/* release single indir blk */
+  if (z == NO_ZONE) return(NO_BLOCK);
+  b = ((block_t) z << scale) + boff;
+  return(b);
+}
+
+/*===========================================================================*
+ *				rd_indir				     *
+ *===========================================================================*/
+PUBLIC zone_t rd_indir(bp, index)
+struct buf *bp;			/* pointer to indirect block */
+int index;			/* index into *bp */
+{
+/* Given a pointer to an indirect block, read one entry.  The reason for
+ * making a separate routine out of this is that there are four cases:
+ * V1 (IBM and 68000), and V2 (IBM and 68000).
+ */
+
+  struct super_block *sp;
+  zone_t zone;			/* V2 zones are longs (shorts in V1) */
+
+  if(bp == NIL_BUF)
+	panic(__FILE__, "rd_indir() on NIL_BUF", NO_NUM);
+
+  sp = get_super(bp->b_dev);	/* need super block to find file sys type */
+
+  /* read a zone from an indirect block */
+  if (sp->s_version == V1)
+	zone = (zone_t) conv2(sp->s_native, (int)  bp->b_v1_ind[index]);
+  else
+	zone = (zone_t) conv4(sp->s_native, (long) bp->b_v2_ind[index]);
+
+  if (zone != NO_ZONE &&
+		(zone < (zone_t) sp->s_firstdatazone || zone >= sp->s_zones)) {
+	printf("Illegal zone number %ld in indirect block, index %d\n",
+	       (long) zone, index);
+	panic(__FILE__,"check file system", NO_NUM);
+  }
+  return(zone);
+}
+
+/*===========================================================================*
+ *				read_ahead				     *
+ *===========================================================================*/
+PUBLIC void read_ahead()
+{
+/* Read a block into the cache before it is needed. */
+  int block_size;
+  register struct inode *rip;
+  struct buf *bp;
+  block_t b;
+
+  rip = rdahed_inode;		/* pointer to inode to read ahead from */
+  block_size = get_block_size(rip->i_dev);
+  rdahed_inode = NIL_INODE;	/* turn off read ahead */
+  if ( (b = read_map(rip, rdahedpos)) == NO_BLOCK) return;	/* at EOF */
+  bp = rahead(rip, b, rdahedpos, block_size);
+  put_block(bp, PARTIAL_DATA_BLOCK);
+}
+
+/*===========================================================================*
+ *				rahead					     *
+ *===========================================================================*/
+PUBLIC struct buf *rahead(rip, baseblock, position, bytes_ahead)
+register struct inode *rip;	/* pointer to inode for file to be read */
+block_t baseblock;		/* block at current position */
+off_t position;			/* position within file */
+unsigned bytes_ahead;		/* bytes beyond position for immediate use */
+{
+/* Fetch a block from the cache or the device.  If a physical read is
+ * required, prefetch as many more blocks as convenient into the cache.
+ * This usually covers bytes_ahead and is at least BLOCKS_MINIMUM.
+ * The device driver may decide it knows better and stop reading at a
+ * cylinder boundary (or after an error).  Rw_scattered() puts an optional
+ * flag on all reads to allow this.
+ */
+  int block_size;
+/* Minimum number of blocks to prefetch. */
+# define BLOCKS_MINIMUM		(NR_BUFS < 50 ? 18 : 32)
+  int block_spec, scale, read_q_size;
+  unsigned int blocks_ahead, fragment;
+  block_t block, blocks_left;
+  off_t ind1_pos;
+  dev_t dev;
+  struct buf *bp;
+  static struct buf *read_q[NR_BUFS];
+
+  block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL;
+  if (block_spec) {
+	dev = (dev_t) rip->i_zone[0];
+  } else {
+	dev = rip->i_dev;
+  }
+  block_size = get_block_size(dev);
+
+  block = baseblock;
+  bp = get_block(dev, block, PREFETCH);
+  if (bp->b_dev != NO_DEV) return(bp);
+
+  /* The best guess for the number of blocks to prefetch:  A lot.
+   * It is impossible to tell what the device looks like, so we don't even
+   * try to guess the geometry, but leave it to the driver.
+   *
+   * The floppy driver can read a full track with no rotational delay, and it
+   * avoids reading partial tracks if it can, so handing it enough buffers to
+   * read two tracks is perfect.  (Two, because some diskette types have
+   * an odd number of sectors per track, so a block may span tracks.)
+   *
+   * The disk drivers don't try to be smart.  With todays disks it is
+   * impossible to tell what the real geometry looks like, so it is best to
+   * read as much as you can.  With luck the caching on the drive allows
+   * for a little time to start the next read.
+   *
+   * The current solution below is a bit of a hack, it just reads blocks from
+   * the current file position hoping that more of the file can be found.  A
+   * better solution must look at the already available zone pointers and
+   * indirect blocks (but don't call read_map!).
+   */
+
+  fragment = position % block_size;
+  position -= fragment;
+  bytes_ahead += fragment;
+
+  blocks_ahead = (bytes_ahead + block_size - 1) / block_size;
+
+  if (block_spec && rip->i_size == 0) {
+	blocks_left = NR_IOREQS;
+  } else {
+	blocks_left = (rip->i_size - position + block_size - 1) / block_size;
+
+	/* Go for the first indirect block if we are in its neighborhood. */
+	if (!block_spec) {
+		scale = rip->i_sp->s_log_zone_size;
+		ind1_pos = (off_t) rip->i_ndzones * (block_size << scale);
+		if (position <= ind1_pos && rip->i_size > ind1_pos) {
+			blocks_ahead++;
+			blocks_left++;
+		}
+	}
+  }
+
+  /* No more than the maximum request. */
+  if (blocks_ahead > NR_IOREQS) blocks_ahead = NR_IOREQS;
+
+  /* Read at least the minimum number of blocks, but not after a seek. */
+  if (blocks_ahead < BLOCKS_MINIMUM && rip->i_seek == NO_SEEK)
+	blocks_ahead = BLOCKS_MINIMUM;
+
+  /* Can't go past end of file. */
+  if (blocks_ahead > blocks_left) blocks_ahead = blocks_left;
+
+  read_q_size = 0;
+
+  /* Acquire block buffers. */
+  for (;;) {
+	read_q[read_q_size++] = bp;
+
+	if (--blocks_ahead == 0) break;
+
+	/* Don't trash the cache, leave 4 free. */
+	if (bufs_in_use >= NR_BUFS - 4) break;
+
+	block++;
+
+	bp = get_block(dev, block, PREFETCH);
+	if (bp->b_dev != NO_DEV) {
+		/* Oops, block already in the cache, get out. */
+		put_block(bp, FULL_DATA_BLOCK);
+		break;
+	}
+  }
+  rw_scattered(dev, read_q, read_q_size, READING);
+  return(get_block(dev, baseblock, NORMAL));
+}
Index: /trunk/minix/servers/fs/select.c
===================================================================
--- /trunk/minix/servers/fs/select.c	(revision 9)
+++ /trunk/minix/servers/fs/select.c	(revision 9)
@@ -0,0 +1,702 @@
+/* Implement entry point to select system call.
+ *
+ * The entry points into this file are
+ *   do_select:	       perform the SELECT system call
+ *   select_callback:  notify select system of possible fd operation 
+ *   select_notified:  low-level entry for device notifying select
+ *   select_unsuspend_by_endpt: cancel a blocking select on exiting driver
+ * 
+ * Changes:
+ *   6 june 2005  Created (Ben Gras)
+ */
+
+#define DEBUG_SELECT 0
+
+#include "fs.h"
+#include "select.h"
+#include "file.h"
+#include "inode.h"
+
+#include <sys/time.h>
+#include <sys/select.h>
+#include <minix/com.h>
+#include <string.h>
+
+/* max. number of simultaneously pending select() calls */
+#define MAXSELECTS 25
+
+PRIVATE struct selectentry {
+	struct fproc *requestor;	/* slot is free iff this is NULL */
+	int req_endpt;
+	fd_set readfds, writefds, errorfds;
+	fd_set ready_readfds, ready_writefds, ready_errorfds;
+	fd_set *vir_readfds, *vir_writefds, *vir_errorfds;
+	struct filp *filps[FD_SETSIZE];
+	int type[FD_SETSIZE];
+	int nfds, nreadyfds;
+	clock_t expiry;
+	timer_t timer;	/* if expiry > 0 */
+} selecttab[MAXSELECTS];
+
+#define SELFD_FILE	0
+#define SELFD_PIPE	1
+#define SELFD_TTY	2
+#define SELFD_INET	3
+#define SELFD_LOG	4
+#define SEL_FDS		5
+
+FORWARD _PROTOTYPE(int select_reevaluate, (struct filp *fp));
+
+FORWARD _PROTOTYPE(int select_request_file,
+	 (struct filp *f, int *ops, int block));
+FORWARD _PROTOTYPE(int select_match_file, (struct filp *f));
+
+FORWARD _PROTOTYPE(int select_request_general,
+	 (struct filp *f, int *ops, int block));
+FORWARD _PROTOTYPE(int select_major_match,
+	(int match_major, struct filp *file));
+
+FORWARD _PROTOTYPE(void select_cancel_all, (struct selectentry *e));
+FORWARD _PROTOTYPE(void select_wakeup, (struct selectentry *e, int r));
+FORWARD _PROTOTYPE(void select_return, (struct selectentry *, int));
+
+/* The Open Group:
+ * "The pselect() and select() functions shall support
+ * regular files, terminal and pseudo-terminal devices,
+ * STREAMS-based files, FIFOs, pipes, and sockets."
+ */
+
+PRIVATE struct fdtype {
+	int (*select_request)(struct filp *, int *ops, int block);	
+	int (*select_match)(struct filp *);
+	int select_major;
+} fdtypes[SEL_FDS] = {
+		/* SELFD_FILE */
+	{ select_request_file, select_match_file, 0 },
+		/* SELFD_TTY (also PTY) */
+	{ select_request_general, NULL, TTY_MAJOR },
+		/* SELFD_INET */
+	{ select_request_general, NULL, INET_MAJOR },
+		/* SELFD_PIPE (pipe(2) pipes and FS FIFOs) */
+	{ select_request_pipe, select_match_pipe, 0 },
+		/* SELFD_LOG (/dev/klog) */
+	{ select_request_general, NULL, LOG_MAJOR },
+};
+
+/* Open Group:
+ * "File descriptors associated with regular files shall always select true
+ * for ready to read, ready to write, and error conditions."
+ */
+
+/*===========================================================================*
+ *				select_request_file			     *
+ *===========================================================================*/
+PRIVATE int select_request_file(struct filp *f, int *ops, int block)
+{
+	/* output *ops is input *ops */
+	return SEL_OK;
+}
+
+/*===========================================================================*
+ *				select_match_file			     *
+ *===========================================================================*/
+PRIVATE int select_match_file(struct filp *file)
+{
+	if (file && file->filp_ino && (file->filp_ino->i_mode & I_REGULAR))
+		return 1;
+	return 0;
+}
+
+/*===========================================================================*
+ *				select_request_general			     *
+ *===========================================================================*/
+PRIVATE int select_request_general(struct filp *f, int *ops, int block)
+{
+	int rops = *ops;
+	if (block) rops |= SEL_NOTIFY;
+	*ops = dev_io(DEV_SELECT, f->filp_ino->i_zone[0], rops, NULL, 0, 0, 0);
+	if (*ops < 0)
+		return SEL_ERR;
+	return SEL_OK;
+}
+
+/*===========================================================================*
+ *				select_major_match			     *
+ *===========================================================================*/
+PRIVATE int select_major_match(int match_major, struct filp *file)
+{
+	int major;
+	if (!(file && file->filp_ino &&
+		(file->filp_ino->i_mode & I_TYPE) == I_CHAR_SPECIAL))
+		return 0;
+	major = (file->filp_ino->i_zone[0] >> MAJOR) & BYTE;
+	if (major == match_major)
+		return 1;
+	return 0;
+}
+
+/*===========================================================================*
+ *				tab2ops					     *
+ *===========================================================================*/
+PRIVATE int tab2ops(int fd, struct selectentry *e)
+{
+	return (FD_ISSET(fd, &e->readfds) ? SEL_RD : 0) |
+		(FD_ISSET(fd, &e->writefds) ? SEL_WR : 0) |
+		(FD_ISSET(fd, &e->errorfds) ? SEL_ERR : 0);
+}
+
+/*===========================================================================*
+ *				ops2tab					     *
+ *===========================================================================*/
+PRIVATE void ops2tab(int ops, int fd, struct selectentry *e)
+{
+	if ((ops & SEL_RD) && e->vir_readfds && FD_ISSET(fd, &e->readfds)
+	        && !FD_ISSET(fd, &e->ready_readfds)) {
+		FD_SET(fd, &e->ready_readfds);
+		e->nreadyfds++;
+	}
+	if ((ops & SEL_WR) && e->vir_writefds && FD_ISSET(fd, &e->writefds) 
+		&& !FD_ISSET(fd, &e->ready_writefds)) {
+		FD_SET(fd, &e->ready_writefds);
+		e->nreadyfds++;
+	}
+	if ((ops & SEL_ERR) && e->vir_errorfds && FD_ISSET(fd, &e->errorfds)
+		&& !FD_ISSET(fd, &e->ready_errorfds)) {
+		FD_SET(fd, &e->ready_errorfds);
+		e->nreadyfds++;
+	}
+
+	return;
+}
+
+/*===========================================================================*
+ *				copy_fdsets				     *
+ *===========================================================================*/
+PRIVATE void copy_fdsets(struct selectentry *e)
+{
+	if (e->vir_readfds)
+		sys_vircopy(SELF, D, (vir_bytes) &e->ready_readfds,
+		e->req_endpt, D, (vir_bytes) e->vir_readfds, sizeof(fd_set));
+	if (e->vir_writefds)
+		sys_vircopy(SELF, D, (vir_bytes) &e->ready_writefds,
+		e->req_endpt, D, (vir_bytes) e->vir_writefds, sizeof(fd_set));
+	if (e->vir_errorfds)
+		sys_vircopy(SELF, D, (vir_bytes) &e->ready_errorfds,
+		e->req_endpt, D, (vir_bytes) e->vir_errorfds, sizeof(fd_set));
+
+	return;
+}
+
+/*===========================================================================*
+ *				do_select				      *
+ *===========================================================================*/
+PUBLIC int do_select(void)
+{
+	int r, nfds, is_timeout = 1, nonzero_timeout = 0,
+		fd, s, block = 0;
+	struct timeval timeout;
+	nfds = m_in.SEL_NFDS;
+
+	if (nfds < 0 || nfds > FD_SETSIZE)
+		return EINVAL;
+
+	for(s = 0; s < MAXSELECTS; s++)
+		if (!selecttab[s].requestor)
+			break;
+
+	if (s >= MAXSELECTS)
+		return ENOSPC;
+
+	selecttab[s].req_endpt = who_e;
+	selecttab[s].nfds = 0;
+	selecttab[s].nreadyfds = 0;
+	memset(selecttab[s].filps, 0, sizeof(selecttab[s].filps));
+
+	/* defaults */
+	FD_ZERO(&selecttab[s].readfds);
+	FD_ZERO(&selecttab[s].writefds);
+	FD_ZERO(&selecttab[s].errorfds);
+	FD_ZERO(&selecttab[s].ready_readfds);
+	FD_ZERO(&selecttab[s].ready_writefds);
+	FD_ZERO(&selecttab[s].ready_errorfds);
+
+	selecttab[s].vir_readfds = (fd_set *) m_in.SEL_READFDS;
+	selecttab[s].vir_writefds = (fd_set *) m_in.SEL_WRITEFDS;
+	selecttab[s].vir_errorfds = (fd_set *) m_in.SEL_ERRORFDS;
+
+	/* copy args */
+	if (selecttab[s].vir_readfds
+	 && (r=sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_READFDS,
+		SELF, D, (vir_bytes) &selecttab[s].readfds, sizeof(fd_set))) != OK)
+		return r;
+
+	if (selecttab[s].vir_writefds
+	 && (r=sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_WRITEFDS,
+		SELF, D, (vir_bytes) &selecttab[s].writefds, sizeof(fd_set))) != OK)
+		return r;
+
+	if (selecttab[s].vir_errorfds
+	 && (r=sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_ERRORFDS,
+		SELF, D, (vir_bytes) &selecttab[s].errorfds, sizeof(fd_set))) != OK)
+		return r;
+
+	if (!m_in.SEL_TIMEOUT)
+		is_timeout = nonzero_timeout = 0;
+	else
+		if ((r=sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_TIMEOUT,
+			SELF, D, (vir_bytes) &timeout, sizeof(timeout))) != OK)
+			return r;
+
+	/* No nonsense in the timeval please. */
+	if (is_timeout && (timeout.tv_sec < 0 || timeout.tv_usec < 0))
+		return EINVAL;
+
+	/* if is_timeout if 0, we block forever. otherwise, if nonzero_timeout
+	 * is 0, we do a poll (don't block). otherwise, we block up to the
+	 * specified time interval.
+	 */
+	if (is_timeout && (timeout.tv_sec > 0 || timeout.tv_usec > 0))
+		nonzero_timeout = 1;
+
+	if (nonzero_timeout || !is_timeout)
+		block = 1;
+	else
+		block = 0; /* timeout set as (0,0) - this effects a poll */
+
+	/* no timeout set (yet) */
+	selecttab[s].expiry = 0;
+
+	for(fd = 0; fd < nfds; fd++) {
+		int orig_ops, ops, t, type = -1, r;
+		struct filp *filp;
+	
+		if (!(orig_ops = ops = tab2ops(fd, &selecttab[s])))
+			continue;
+		if (!(filp = selecttab[s].filps[fd] = get_filp(fd))) {
+			select_cancel_all(&selecttab[s]);
+			return EBADF;
+		}
+
+		for(t = 0; t < SEL_FDS; t++) {
+			if (fdtypes[t].select_match) {
+			   if (fdtypes[t].select_match(filp)) {
+#if DEBUG_SELECT
+				printf("select: fd %d is type %d ", fd, t);
+#endif
+				if (type != -1)
+					printf("select: double match\n");
+				type = t;
+			  }
+	 		} else if (select_major_match(fdtypes[t].select_major, filp)) {
+				type = t;
+			}
+		}
+
+		/* Open Group:
+		 * "The pselect() and select() functions shall support
+		 * regular files, terminal and pseudo-terminal devices,
+		 * STREAMS-based files, FIFOs, pipes, and sockets. The
+		 * behavior of pselect() and select() on file descriptors
+		 * that refer to other types of file is unspecified."
+		 *
+		 * If all types are implemented, then this is another
+		 * type of file and we get to do whatever we want.
+		 */
+		if (type == -1)
+		{
+#if DEBUG_SELECT
+			printf("do_select: bad type\n");
+#endif
+			return EBADF;
+		}
+
+		selecttab[s].type[fd] = type;
+
+		if ((selecttab[s].filps[fd]->filp_select_ops & ops) != ops) {
+			int wantops;
+			/* Request the select on this fd.  */
+#if DEBUG_SELECT
+			printf("%p requesting ops %d -> ",
+				selecttab[s].filps[fd],
+				selecttab[s].filps[fd]->filp_select_ops);
+#endif
+			wantops = (selecttab[s].filps[fd]->filp_select_ops |= ops);
+#if DEBUG_SELECT
+			printf("%d\n", selecttab[s].filps[fd]->filp_select_ops);
+#endif
+			if ((r = fdtypes[type].select_request(filp,
+				&wantops, block)) != SEL_OK) {
+				/* error or bogus return code.. backpaddle */
+				select_cancel_all(&selecttab[s]);
+				printf("select: select_request returned error\n");
+				return EINVAL;
+			}
+			if (wantops) {
+				if (wantops & ops) {
+					/* operations that were just requested
+					 * are ready to go right away
+					 */
+					ops2tab(wantops, fd, &selecttab[s]);
+				}
+				/* if there are any other select()s blocking
+				 * on these operations of this fp, they can
+				 * be awoken too
+				 */
+				select_callback(filp, ops);
+			}
+#if DEBUG_SELECT
+			printf("select request ok; ops returned %d\n", wantops);
+#endif
+		} else {
+#if DEBUG_SELECT
+			printf("select already happening on that filp\n");
+#endif
+		}
+
+		selecttab[s].nfds = fd+1;
+		selecttab[s].filps[fd]->filp_selectors++;
+
+#if DEBUG_SELECT
+		printf("[fd %d ops: %d] ", fd, ops);
+#endif
+	}
+
+	if (selecttab[s].nreadyfds > 0 || !block) {
+		/* fd's were found that were ready to go right away, and/or
+		 * we were instructed not to block at all. Must return
+		 * immediately.
+		 */
+		copy_fdsets(&selecttab[s]);
+		select_cancel_all(&selecttab[s]);
+		selecttab[s].requestor = NULL;
+
+		/* Open Group:
+		 * "Upon successful completion, the pselect() and select()
+		 * functions shall return the total number of bits
+		 * set in the bit masks."
+		 */
+#if DEBUG_SELECT
+		printf("returning\n");
+#endif
+
+		return selecttab[s].nreadyfds;
+	}
+#if DEBUG_SELECT
+		printf("not returning (%d, %d)\n", selecttab[s].nreadyfds, block);
+#endif
+ 
+	/* Convert timeval to ticks and set the timer. If it fails, undo
+	 * all, return error.
+	 */
+	if (is_timeout) {
+		int ticks;
+		/* Open Group:
+		 * "If the requested timeout interval requires a finer
+		 * granularity than the implementation supports, the
+		 * actual timeout interval shall be rounded up to the next
+		 * supported value."
+		 */
+#define USECPERSEC 1000000
+		while(timeout.tv_usec >= USECPERSEC) {
+			/* this is to avoid overflow with *HZ below */
+			timeout.tv_usec -= USECPERSEC;
+			timeout.tv_sec++;
+		}
+		ticks = timeout.tv_sec * HZ +
+			(timeout.tv_usec * HZ + USECPERSEC-1) / USECPERSEC;
+		selecttab[s].expiry = ticks;
+		fs_set_timer(&selecttab[s].timer, ticks, select_timeout_check, s);
+#if DEBUG_SELECT
+		printf("%d: blocking %d ticks\n", s, ticks);
+#endif
+	}
+
+	/* if we're blocking, the table entry is now valid. */
+	selecttab[s].requestor = fp;
+
+	/* process now blocked */
+	suspend(XSELECT);
+	return SUSPEND;
+}
+
+/*===========================================================================*
+ *				select_cancel_all			     *
+ *===========================================================================*/
+PRIVATE void select_cancel_all(struct selectentry *e)
+{
+	int fd;
+
+	for(fd = 0; fd < e->nfds; fd++) {
+		struct filp *fp;
+		fp = e->filps[fd];
+		if (!fp) {
+#if DEBUG_SELECT
+			printf("[ fd %d/%d NULL ] ", fd, e->nfds);
+#endif
+			continue;
+		}
+		if (fp->filp_selectors < 1) {
+#if DEBUG_SELECT
+			printf("select: %d selectors?!\n", fp->filp_selectors);
+#endif
+			continue;
+		}
+		fp->filp_selectors--;
+		e->filps[fd] = NULL;
+		select_reevaluate(fp);
+	}
+
+	if (e->expiry > 0) {
+#if DEBUG_SELECT
+		printf("cancelling timer %d\n", e - selecttab);
+#endif
+		fs_cancel_timer(&e->timer); 
+		e->expiry = 0;
+	}
+
+	return;
+}
+
+/*===========================================================================*
+ *				select_wakeup				     *
+ *===========================================================================*/
+PRIVATE void select_wakeup(struct selectentry *e, int r)
+{
+	revive(e->req_endpt, r);
+}
+
+/*===========================================================================*
+ *				select_reevaluate			     *
+ *===========================================================================*/
+PRIVATE int select_reevaluate(struct filp *fp)
+{
+	int s, remain_ops = 0, fd, type = -1;
+
+	if (!fp) {
+		printf("fs: select: reevalute NULL fp\n");
+		return 0;
+	}
+
+	for(s = 0; s < MAXSELECTS; s++) {
+		if (!selecttab[s].requestor)
+			continue;
+		for(fd = 0; fd < selecttab[s].nfds; fd++)
+			if (fp == selecttab[s].filps[fd]) {
+				remain_ops |= tab2ops(fd, &selecttab[s]);
+				type = selecttab[s].type[fd];
+			}
+	}
+
+	/* If there are any select()s open that want any operations on
+	 * this fd that haven't been satisfied by this callback, then we're
+	 * still in the market for it.
+	 */
+	fp->filp_select_ops = remain_ops;
+#if DEBUG_SELECT
+	printf("remaining operations on fp are %d\n", fp->filp_select_ops);
+#endif
+
+	return remain_ops;
+}
+
+/*===========================================================================*
+ *				select_return				     *
+ *===========================================================================*/
+PRIVATE void select_return(struct selectentry *s, int r)
+{
+	select_cancel_all(s);
+	copy_fdsets(s);
+	select_wakeup(s, r ? r : s->nreadyfds);
+	s->requestor = NULL;
+}
+
+/*===========================================================================*
+ *				select_callback			             *
+ *===========================================================================*/
+PUBLIC int select_callback(struct filp *fp, int ops)
+{
+	int s, fd, want_ops, type;
+
+	/* We are being notified that file pointer fp is available for
+	 * operations 'ops'. We must re-register the select for
+	 * operations that we are still interested in, if any.
+	 */
+
+	want_ops = 0;
+	type = -1;
+	for(s = 0; s < MAXSELECTS; s++) {
+		int wakehim = 0;
+		if (!selecttab[s].requestor)
+			continue;
+		for(fd = 0; fd < selecttab[s].nfds; fd++) {
+			if (!selecttab[s].filps[fd])
+				continue;
+			if (selecttab[s].filps[fd] == fp) {
+				int this_want_ops;
+				this_want_ops = tab2ops(fd, &selecttab[s]);
+				want_ops |= this_want_ops;
+				if (this_want_ops & ops) {
+					/* this select() has been satisfied. */
+					ops2tab(ops, fd, &selecttab[s]);
+					wakehim = 1;
+				}
+				type = selecttab[s].type[fd];
+			}
+		}
+		if (wakehim)
+			select_return(&selecttab[s], 0);
+	}
+
+	return 0;
+}
+
+/*===========================================================================*
+ *				select_notified			             *
+ *===========================================================================*/
+PUBLIC int select_notified(int major, int minor, int selected_ops)
+{
+	int s, f, t;
+
+#if DEBUG_SELECT
+	printf("select callback: %d, %d: %d\n", major, minor, selected_ops);
+#endif
+
+	for(t = 0; t < SEL_FDS; t++)
+		if (!fdtypes[t].select_match && fdtypes[t].select_major == major)
+		    	break;
+
+	if (t >= SEL_FDS) {
+#if DEBUG_SELECT
+		printf("select callback: no fdtype found for device %d\n", major);
+#endif
+		return OK;
+	}
+
+	/* We have a select callback from major device no.
+	 * d, which corresponds to our select type t.
+	 */
+
+	for(s = 0; s < MAXSELECTS; s++) {
+		int s_minor, ops;
+		if (!selecttab[s].requestor)
+			continue;
+		for(f = 0; f < selecttab[s].nfds; f++) {
+			if (!selecttab[s].filps[f] ||
+			   !select_major_match(major, selecttab[s].filps[f]))
+			   	continue;
+			ops = tab2ops(f, &selecttab[s]);
+			s_minor =
+			(selecttab[s].filps[f]->filp_ino->i_zone[0] >> MINOR)
+				& BYTE;
+			if ((s_minor == minor) &&
+				(selected_ops & ops)) {
+				select_callback(selecttab[s].filps[f], (selected_ops & ops));
+			}
+		}
+	}
+
+	return OK;
+}
+
+/*===========================================================================*
+ *				init_select  				     *
+ *===========================================================================*/
+PUBLIC void init_select(void)
+{
+	int s;
+
+	for(s = 0; s < MAXSELECTS; s++)
+		fs_init_timer(&selecttab[s].timer);
+}
+
+/*===========================================================================*
+ *				select_forget			             *
+ *===========================================================================*/
+PUBLIC void select_forget(int proc_e)
+{
+	/* something has happened (e.g. signal delivered that interrupts
+	 * select()). totally forget about the select().
+	 */
+	int s;
+
+	for(s = 0; s < MAXSELECTS; s++) {
+		if (selecttab[s].requestor &&
+			selecttab[s].req_endpt == proc_e) {
+			break;
+		}
+
+	}
+
+	if (s >= MAXSELECTS) {
+#if DEBUG_SELECT
+		printf("select: cancelled select() not found");
+#endif
+		return;
+	}
+
+	select_cancel_all(&selecttab[s]);
+	selecttab[s].requestor = NULL;
+
+	return;
+}
+
+/*===========================================================================*
+ *				select_timeout_check	  	     	     *
+ *===========================================================================*/
+PUBLIC void select_timeout_check(timer_t *timer)
+{
+	int s;
+
+	s = tmr_arg(timer)->ta_int;
+
+	if (s < 0 || s >= MAXSELECTS) {
+#if DEBUG_SELECT
+		printf("select: bogus slot arg to watchdog %d\n", s);
+#endif
+		return;
+	}
+
+	if (!selecttab[s].requestor) {
+#if DEBUG_SELECT
+		printf("select: no requestor in watchdog\n");
+#endif
+		return;
+	}
+
+	if (selecttab[s].expiry <= 0) {
+#if DEBUG_SELECT
+		printf("select: strange expiry value in watchdog\n", s);
+#endif
+		return;
+	}
+
+	selecttab[s].expiry = 0;
+	select_return(&selecttab[s], 0);
+
+	return;
+}
+
+/*===========================================================================*
+ *				select_unsuspend_by_endpt  	     	     *
+ *===========================================================================*/
+PUBLIC void select_unsuspend_by_endpt(int proc_e)
+{
+	int fd, s;
+
+	for(s = 0; s < MAXSELECTS; s++) {
+	  if (!selecttab[s].requestor)
+		  continue;
+	  for(fd = 0; fd < selecttab[s].nfds; fd++) {
+	    int maj;
+	    if (!selecttab[s].filps[fd] || !selecttab[s].filps[fd]->filp_ino)
+		continue;
+	    maj = (selecttab[s].filps[fd]->filp_ino->i_zone[0] >> MAJOR)&BYTE;
+	    if(dmap_driver_match(proc_e, maj)) {
+			select_return(&selecttab[s], EAGAIN);
+	    }
+	  }
+	}
+
+	return;
+}
+
Index: /trunk/minix/servers/fs/select.h
===================================================================
--- /trunk/minix/servers/fs/select.h	(revision 9)
+++ /trunk/minix/servers/fs/select.h	(revision 9)
@@ -0,0 +1,9 @@
+#ifndef _FS_SELECT_H
+#define _FS_SELECT_H 1
+
+/* return codes for select_request_* and select_cancel_* */
+#define SEL_OK		0	/* ready */
+#define SEL_ERROR	1	/* failed */
+
+#endif
+
Index: /trunk/minix/servers/fs/stadir.c
===================================================================
--- /trunk/minix/servers/fs/stadir.c	(revision 9)
+++ /trunk/minix/servers/fs/stadir.c	(revision 9)
@@ -0,0 +1,303 @@
+/* This file contains the code for performing four system calls relating to
+ * status and directories.
+ *
+ * The entry points into this file are
+ *   do_chdir:	perform the CHDIR system call
+ *   do_chroot:	perform the CHROOT system call
+ *   do_stat:	perform the STAT system call
+ *   do_fstat:	perform the FSTAT system call
+ *   do_fstatfs: perform the FSTATFS system call
+ *   do_lstat:  perform the LSTAT system call
+ *   do_rdlink: perform the RDLNK system call
+ */
+
+#include "fs.h"
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <minix/com.h>
+#include <string.h>
+#include "buf.h"
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "param.h"
+#include "super.h"
+
+FORWARD _PROTOTYPE( int change, (struct inode **iip, char *name_ptr, int len));
+FORWARD _PROTOTYPE( int change_into, (struct inode **iip, struct inode *ip));
+FORWARD _PROTOTYPE( int stat_inode, (struct inode *rip, struct filp *fil_ptr,
+			char *user_addr)				);
+
+/*===========================================================================*
+ *				do_fchdir				     *
+ *===========================================================================*/
+PUBLIC int do_fchdir()
+{
+	/* Change directory on already-opened fd. */
+	struct filp *rfilp;
+
+	/* Is the file descriptor valid? */
+	if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
+	dup_inode(rfilp->filp_ino);
+	return change_into(&fp->fp_workdir, rfilp->filp_ino);
+}
+
+/*===========================================================================*
+ *				do_chdir				     *
+ *===========================================================================*/
+PUBLIC int do_chdir()
+{
+/* Change directory.  This function is  also called by MM to simulate a chdir
+ * in order to do EXEC, etc.  It also changes the root directory, the uids and
+ * gids, and the umask. 
+ */
+
+  int r;
+  register struct fproc *rfp;
+
+  if (who_e == PM_PROC_NR) {
+	int slot;
+	if(isokendpt(m_in.endpt1, &slot) != OK)
+		return EINVAL;
+	rfp = &fproc[slot];
+	put_inode(fp->fp_rootdir);
+	dup_inode(fp->fp_rootdir = rfp->fp_rootdir);
+	put_inode(fp->fp_workdir);
+	dup_inode(fp->fp_workdir = rfp->fp_workdir);
+
+	/* MM uses access() to check permissions.  To make this work, pretend
+	 * that the user's real ids are the same as the user's effective ids.
+	 * FS calls other than access() do not use the real ids, so are not
+	 * affected.
+	 */
+	fp->fp_realuid =
+	fp->fp_effuid = rfp->fp_effuid;
+	fp->fp_realgid =
+	fp->fp_effgid = rfp->fp_effgid;
+	fp->fp_umask = rfp->fp_umask;
+	return(OK);
+  }
+
+  /* Perform the chdir(name) system call. */
+  r = change(&fp->fp_workdir, m_in.name, m_in.name_length);
+  return(r);
+}
+
+/*===========================================================================*
+ *				do_chroot				     *
+ *===========================================================================*/
+PUBLIC int do_chroot()
+{
+/* Perform the chroot(name) system call. */
+
+  register int r;
+
+  if (!super_user) return(EPERM);	/* only su may chroot() */
+  r = change(&fp->fp_rootdir, m_in.name, m_in.name_length);
+  return(r);
+}
+
+/*===========================================================================*
+ *				change					     *
+ *===========================================================================*/
+PRIVATE int change(iip, name_ptr, len)
+struct inode **iip;		/* pointer to the inode pointer for the dir */
+char *name_ptr;			/* pointer to the directory name to change to */
+int len;			/* length of the directory name string */
+{
+/* Do the actual work for chdir() and chroot(). */
+  struct inode *rip;
+
+  /* Try to open the new directory. */
+  if (fetch_name(name_ptr, len, M3) != OK) return(err_code);
+  if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
+  return change_into(iip, rip);
+}
+
+/*===========================================================================*
+ *				change_into				     *
+ *===========================================================================*/
+PRIVATE int change_into(iip, rip)
+struct inode **iip;		/* pointer to the inode pointer for the dir */
+struct inode *rip;		/* this is what the inode has to become */
+{
+  register int r;
+
+  /* It must be a directory and also be searchable. */
+  if ( (rip->i_mode & I_TYPE) != I_DIRECTORY)
+	r = ENOTDIR;
+  else
+	r = forbidden(rip, X_BIT);	/* check if dir is searchable */
+
+  /* If error, return inode. */
+  if (r != OK) {
+	put_inode(rip);
+	return(r);
+  }
+
+  /* Everything is OK.  Make the change. */
+  put_inode(*iip);		/* release the old directory */
+  *iip = rip;			/* acquire the new one */
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_stat					     *
+ *===========================================================================*/
+PUBLIC int do_stat()
+{
+/* Perform the stat(name, buf) system call. */
+
+  register struct inode *rip;
+  register int r;
+
+  /* Both stat() and fstat() use the same routine to do the real work.  That
+   * routine expects an inode, so acquire it temporarily.
+   */
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+  if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
+  r = stat_inode(rip, NIL_FILP, m_in.name2);	/* actually do the work.*/
+  put_inode(rip);		/* release the inode */
+  return(r);
+}
+
+/*===========================================================================*
+ *				do_fstat				     *
+ *===========================================================================*/
+PUBLIC int do_fstat()
+{
+/* Perform the fstat(fd, buf) system call. */
+
+  register struct filp *rfilp;
+
+  /* Is the file descriptor valid? */
+  if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
+
+  return(stat_inode(rfilp->filp_ino, rfilp, m_in.buffer));
+}
+
+/*===========================================================================*
+ *				stat_inode				     *
+ *===========================================================================*/
+PRIVATE int stat_inode(rip, fil_ptr, user_addr)
+register struct inode *rip;	/* pointer to inode to stat */
+struct filp *fil_ptr;		/* filp pointer, supplied by 'fstat' */
+char *user_addr;		/* user space address where stat buf goes */
+{
+/* Common code for stat and fstat system calls. */
+
+  struct stat statbuf;
+  mode_t mo;
+  int r, s;
+
+  /* Update the atime, ctime, and mtime fields in the inode, if need be. */
+  if (rip->i_update) update_times(rip);
+
+  /* Fill in the statbuf struct. */
+  mo = rip->i_mode & I_TYPE;
+
+  /* true iff special */
+  s = (mo == I_CHAR_SPECIAL || mo == I_BLOCK_SPECIAL);
+
+  statbuf.st_dev = rip->i_dev;
+  statbuf.st_ino = rip->i_num;
+  statbuf.st_mode = rip->i_mode;
+  statbuf.st_nlink = rip->i_nlinks;
+  statbuf.st_uid = rip->i_uid;
+  statbuf.st_gid = rip->i_gid;
+  statbuf.st_rdev = (dev_t) (s ? rip->i_zone[0] : NO_DEV);
+  statbuf.st_size = rip->i_size;
+
+  if (rip->i_pipe == I_PIPE) {
+	statbuf.st_mode &= ~I_REGULAR;	/* wipe out I_REGULAR bit for pipes */
+	if (fil_ptr != NIL_FILP && fil_ptr->filp_mode & R_BIT) 
+		statbuf.st_size -= fil_ptr->filp_pos;
+  }
+
+  statbuf.st_atime = rip->i_atime;
+  statbuf.st_mtime = rip->i_mtime;
+  statbuf.st_ctime = rip->i_ctime;
+
+  /* Copy the struct to user space. */
+  r = sys_datacopy(FS_PROC_NR, (vir_bytes) &statbuf,
+  		who_e, (vir_bytes) user_addr, (phys_bytes) sizeof(statbuf));
+  return(r);
+}
+
+/*===========================================================================*
+ *				do_fstatfs				     *
+ *===========================================================================*/
+PUBLIC int do_fstatfs()
+{
+  /* Perform the fstatfs(fd, buf) system call. */
+  struct statfs st;
+  register struct filp *rfilp;
+  int r;
+
+  /* Is the file descriptor valid? */
+  if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
+
+  st.f_bsize = rfilp->filp_ino->i_sp->s_block_size;
+
+  r = sys_datacopy(FS_PROC_NR, (vir_bytes) &st,
+  		who_e, (vir_bytes) m_in.buffer, (phys_bytes) sizeof(st));
+
+   return(r);
+}
+
+/*===========================================================================*
+ *                             do_lstat                                     *
+ *===========================================================================*/
+PUBLIC int do_lstat()
+{
+/* Perform the lstat(name, buf) system call. */
+
+  register int r;              /* return value */
+  register struct inode *rip;  /* target inode */
+
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+  if ((rip = parse_path(user_path, (char *) 0, EAT_PATH_OPAQUE)) == NIL_INODE)
+       return(err_code);
+  r = stat_inode(rip, NIL_FILP, m_in.name2);
+  put_inode(rip);
+  return(r);
+}
+
+/*===========================================================================*
+ *                             do_rdlink                                    *
+ *===========================================================================*/
+PUBLIC int do_rdlink()
+{
+/* Perform the readlink(name, buf) system call. */
+
+  register int r;              /* return value */
+  block_t b;                   /* block containing link text */
+  struct buf *bp;              /* buffer containing link text */
+  register struct inode *rip;  /* target inode */
+  int copylen;
+  copylen = m_in.m1_i2;
+  if(copylen < 0) return EINVAL;
+
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+  if ((rip = parse_path(user_path, (char *) 0, EAT_PATH_OPAQUE)) == NIL_INODE)
+       return(err_code);
+
+  r = EACCES;
+  if (S_ISLNK(rip->i_mode) && (b = read_map(rip, (off_t) 0)) != NO_BLOCK) {
+       if (m_in.name2_length <= 0) r = EINVAL;
+       else if (m_in.name2_length < rip->i_size) r = ERANGE;
+       else {
+	       if(rip->i_size < copylen) copylen = rip->i_size;
+               bp = get_block(rip->i_dev, b, NORMAL);
+               r = sys_vircopy(SELF, D, (vir_bytes) bp->b_data,
+		who_e, D, (vir_bytes) m_in.name2, (vir_bytes) copylen);
+
+               if (r == OK) r = copylen;
+               put_block(bp, DIRECTORY_BLOCK);
+       }
+  }
+
+  put_inode(rip);
+  return(r);
+}
+
Index: /trunk/minix/servers/fs/super.c
===================================================================
--- /trunk/minix/servers/fs/super.c	(revision 9)
+++ /trunk/minix/servers/fs/super.c	(revision 9)
@@ -0,0 +1,319 @@
+/* This file manages the super block table and the related data structures,
+ * namely, the bit maps that keep track of which zones and which inodes are
+ * allocated and which are free.  When a new inode or zone is needed, the
+ * appropriate bit map is searched for a free entry.
+ *
+ * The entry points into this file are
+ *   alloc_bit:       somebody wants to allocate a zone or inode; find one
+ *   free_bit:        indicate that a zone or inode is available for allocation
+ *   get_super:       search the 'superblock' table for a device
+ *   mounted:         tells if file inode is on mounted (or ROOT) file system
+ *   read_super:      read a superblock
+ */
+
+#include "fs.h"
+#include <string.h>
+#include <minix/com.h>
+#include "buf.h"
+#include "inode.h"
+#include "super.h"
+#include "const.h"
+
+/*===========================================================================*
+ *				alloc_bit				     *
+ *===========================================================================*/
+PUBLIC bit_t alloc_bit(sp, map, origin)
+struct super_block *sp;		/* the filesystem to allocate from */
+int map;			/* IMAP (inode map) or ZMAP (zone map) */
+bit_t origin;			/* number of bit to start searching at */
+{
+/* Allocate a bit from a bit map and return its bit number. */
+
+  block_t start_block;		/* first bit block */
+  bit_t map_bits;		/* how many bits are there in the bit map? */
+  unsigned bit_blocks;		/* how many blocks are there in the bit map? */
+  unsigned block, word, bcount;
+  struct buf *bp;
+  bitchunk_t *wptr, *wlim, k;
+  bit_t i, b;
+
+  if (sp->s_rd_only)
+	panic(__FILE__,"can't allocate bit on read-only filesys.", NO_NUM);
+
+  if (map == IMAP) {
+	start_block = START_BLOCK;
+	map_bits = sp->s_ninodes + 1;
+	bit_blocks = sp->s_imap_blocks;
+  } else {
+	start_block = START_BLOCK + sp->s_imap_blocks;
+	map_bits = sp->s_zones - (sp->s_firstdatazone - 1);
+	bit_blocks = sp->s_zmap_blocks;
+  }
+
+  /* Figure out where to start the bit search (depends on 'origin'). */
+  if (origin >= map_bits) origin = 0;	/* for robustness */
+
+  /* Locate the starting place. */
+  block = origin / FS_BITS_PER_BLOCK(sp->s_block_size);
+  word = (origin % FS_BITS_PER_BLOCK(sp->s_block_size)) / FS_BITCHUNK_BITS;
+
+  /* Iterate over all blocks plus one, because we start in the middle. */
+  bcount = bit_blocks + 1;
+  do {
+	bp = get_block(sp->s_dev, start_block + block, NORMAL);
+	wlim = &bp->b_bitmap[FS_BITMAP_CHUNKS(sp->s_block_size)];
+
+	/* Iterate over the words in block. */
+	for (wptr = &bp->b_bitmap[word]; wptr < wlim; wptr++) {
+
+		/* Does this word contain a free bit? */
+		if (*wptr == (bitchunk_t) ~0) continue;
+
+		/* Find and allocate the free bit. */
+		k = conv2(sp->s_native, (int) *wptr);
+		for (i = 0; (k & (1 << i)) != 0; ++i) {}
+
+		/* Bit number from the start of the bit map. */
+		b = ((bit_t) block * FS_BITS_PER_BLOCK(sp->s_block_size))
+		    + (wptr - &bp->b_bitmap[0]) * FS_BITCHUNK_BITS
+		    + i;
+
+		/* Don't allocate bits beyond the end of the map. */
+		if (b >= map_bits) break;
+
+		/* Allocate and return bit number. */
+		k |= 1 << i;
+		*wptr = conv2(sp->s_native, (int) k);
+		bp->b_dirt = DIRTY;
+		put_block(bp, MAP_BLOCK);
+		return(b);
+	}
+	put_block(bp, MAP_BLOCK);
+	if (++block >= bit_blocks) block = 0;	/* last block, wrap around */
+	word = 0;
+  } while (--bcount > 0);
+  return(NO_BIT);		/* no bit could be allocated */
+}
+
+/*===========================================================================*
+ *				free_bit				     *
+ *===========================================================================*/
+PUBLIC void free_bit(sp, map, bit_returned)
+struct super_block *sp;		/* the filesystem to operate on */
+int map;			/* IMAP (inode map) or ZMAP (zone map) */
+bit_t bit_returned;		/* number of bit to insert into the map */
+{
+/* Return a zone or inode by turning off its bitmap bit. */
+
+  unsigned block, word, bit;
+  struct buf *bp;
+  bitchunk_t k, mask;
+  block_t start_block;
+
+  if (sp->s_rd_only)
+	panic(__FILE__,"can't free bit on read-only filesys.", NO_NUM);
+
+  if (map == IMAP) {
+	start_block = START_BLOCK;
+  } else {
+	start_block = START_BLOCK + sp->s_imap_blocks;
+  }
+  block = bit_returned / FS_BITS_PER_BLOCK(sp->s_block_size);
+  word = (bit_returned % FS_BITS_PER_BLOCK(sp->s_block_size))
+  	 / FS_BITCHUNK_BITS;
+
+  bit = bit_returned % FS_BITCHUNK_BITS;
+  mask = 1 << bit;
+
+  bp = get_block(sp->s_dev, start_block + block, NORMAL);
+
+  k = conv2(sp->s_native, (int) bp->b_bitmap[word]);
+  if (!(k & mask)) {
+	panic(__FILE__,map == IMAP ? "tried to free unused inode" :
+	      "tried to free unused block", bit_returned);
+  }
+
+  k &= ~mask;
+  bp->b_bitmap[word] = conv2(sp->s_native, (int) k);
+  bp->b_dirt = DIRTY;
+
+  put_block(bp, MAP_BLOCK);
+}
+
+/*===========================================================================*
+ *				get_super				     *
+ *===========================================================================*/
+PUBLIC struct super_block *get_super(dev)
+dev_t dev;			/* device number whose super_block is sought */
+{
+/* Search the superblock table for this device.  It is supposed to be there. */
+
+  register struct super_block *sp;
+
+  if (dev == NO_DEV)
+  	panic(__FILE__,"request for super_block of NO_DEV", NO_NUM);
+
+  for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
+	if (sp->s_dev == dev) return(sp);
+
+  /* Search failed.  Something wrong. */
+  panic(__FILE__,"can't find superblock for device (in decimal)", (int) dev);
+
+  return(NIL_SUPER);		/* to keep the compiler and lint quiet */
+}
+
+/*===========================================================================*
+ *				get_block_size				     *
+ *===========================================================================*/
+PUBLIC int get_block_size(dev_t dev)
+{
+/* Search the superblock table for this device. */
+
+  register struct super_block *sp;
+
+  if (dev == NO_DEV)
+  	panic(__FILE__,"request for block size of NO_DEV", NO_NUM);
+
+  for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++) {
+	if (sp->s_dev == dev) {
+		return(sp->s_block_size);
+	}
+  }
+
+  /* no mounted filesystem? use this block size then. */
+  return _MIN_BLOCK_SIZE;
+}
+
+/*===========================================================================*
+ *				mounted					     *
+ *===========================================================================*/
+PUBLIC int mounted(rip)
+register struct inode *rip;	/* pointer to inode */
+{
+/* Report on whether the given inode is on a mounted (or ROOT) file system. */
+
+  register struct super_block *sp;
+  register dev_t dev;
+
+  dev = (dev_t) rip->i_zone[0];
+  if (dev == root_dev) return(TRUE);	/* inode is on root file system */
+
+  for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
+	if (sp->s_dev == dev) return(TRUE);
+
+  return(FALSE);
+}
+
+/*===========================================================================*
+ *				read_super				     *
+ *===========================================================================*/
+PUBLIC int read_super(sp)
+register struct super_block *sp; /* pointer to a superblock */
+{
+/* Read a superblock. */
+  dev_t dev;
+  int magic;
+  int version, native, r;
+  static char sbbuf[_MIN_BLOCK_SIZE];
+
+  dev = sp->s_dev;		/* save device (will be overwritten by copy) */
+  if (dev == NO_DEV)
+  	panic(__FILE__,"request for super_block of NO_DEV", NO_NUM);
+  r = dev_io(DEV_READ, dev, FS_PROC_NR,
+  	sbbuf, SUPER_BLOCK_BYTES, _MIN_BLOCK_SIZE, 0);
+  if (r != _MIN_BLOCK_SIZE) {
+  	return EINVAL;
+  }
+  memcpy(sp, sbbuf, sizeof(*sp));
+  sp->s_dev = NO_DEV;		/* restore later */
+  magic = sp->s_magic;		/* determines file system type */
+
+  /* Get file system version and type. */
+  if (magic == SUPER_MAGIC || magic == conv2(BYTE_SWAP, SUPER_MAGIC)) {
+	version = V1;
+	native  = (magic == SUPER_MAGIC);
+  } else if (magic == SUPER_V2 || magic == conv2(BYTE_SWAP, SUPER_V2)) {
+	version = V2;
+	native  = (magic == SUPER_V2);
+  } else if (magic == SUPER_V3) {
+	version = V3;
+  	native = 1;
+  } else {
+	return(EINVAL);
+  }
+
+  /* If the super block has the wrong byte order, swap the fields; the magic
+   * number doesn't need conversion. */
+  sp->s_ninodes =       conv4(native, sp->s_ninodes);
+  sp->s_nzones =        conv2(native, (int) sp->s_nzones);
+  sp->s_imap_blocks =   conv2(native, (int) sp->s_imap_blocks);
+  sp->s_zmap_blocks =   conv2(native, (int) sp->s_zmap_blocks);
+  sp->s_firstdatazone = conv2(native, (int) sp->s_firstdatazone);
+  sp->s_log_zone_size = conv2(native, (int) sp->s_log_zone_size);
+  sp->s_max_size =      conv4(native, sp->s_max_size);
+  sp->s_zones =         conv4(native, sp->s_zones);
+
+  /* In V1, the device size was kept in a short, s_nzones, which limited
+   * devices to 32K zones.  For V2, it was decided to keep the size as a
+   * long.  However, just changing s_nzones to a long would not work, since
+   * then the position of s_magic in the super block would not be the same
+   * in V1 and V2 file systems, and there would be no way to tell whether
+   * a newly mounted file system was V1 or V2.  The solution was to introduce
+   * a new variable, s_zones, and copy the size there.
+   *
+   * Calculate some other numbers that depend on the version here too, to
+   * hide some of the differences.
+   */
+  if (version == V1) {
+  	sp->s_block_size = _STATIC_BLOCK_SIZE;
+	sp->s_zones = sp->s_nzones;	/* only V1 needs this copy */
+	sp->s_inodes_per_block = V1_INODES_PER_BLOCK;
+	sp->s_ndzones = V1_NR_DZONES;
+	sp->s_nindirs = V1_INDIRECTS;
+  } else {
+  	if (version == V2)
+  		sp->s_block_size = _STATIC_BLOCK_SIZE;
+  	if (sp->s_block_size < _MIN_BLOCK_SIZE)
+  		return EINVAL;
+	sp->s_inodes_per_block = V2_INODES_PER_BLOCK(sp->s_block_size);
+	sp->s_ndzones = V2_NR_DZONES;
+	sp->s_nindirs = V2_INDIRECTS(sp->s_block_size);
+  }
+
+  if (sp->s_block_size < _MIN_BLOCK_SIZE) {
+  	return EINVAL;
+  }
+  if (sp->s_block_size > _MAX_BLOCK_SIZE) {
+  	printf("Filesystem block size is %d kB; maximum filesystem\n"
+ 	"block size is %d kB. This limit can be increased by recompiling.\n",
+  	sp->s_block_size/1024, _MAX_BLOCK_SIZE/1024);
+  	return EINVAL;
+  }
+  if ((sp->s_block_size % 512) != 0) {
+  	return EINVAL;
+  }
+  if (SUPER_SIZE > sp->s_block_size) {
+  	return EINVAL;
+  }
+  if ((sp->s_block_size % V2_INODE_SIZE) != 0 ||
+     (sp->s_block_size % V1_INODE_SIZE) != 0) {
+  	return EINVAL;
+  }
+
+  sp->s_isearch = 0;		/* inode searches initially start at 0 */
+  sp->s_zsearch = 0;		/* zone searches initially start at 0 */
+  sp->s_version = version;
+  sp->s_native  = native;
+
+  /* Make a few basic checks to see if super block looks reasonable. */
+  if (sp->s_imap_blocks < 1 || sp->s_zmap_blocks < 1
+				|| sp->s_ninodes < 1 || sp->s_zones < 1
+				|| (unsigned) sp->s_log_zone_size > 4) {
+  	printf("not enough imap or zone map blocks, \n");
+  	printf("or not enough inodes, or not enough zones, "
+  		"or zone size too large\n");
+	return(EINVAL);
+  }
+  sp->s_dev = dev;		/* restore device number */
+  return(OK);
+}
Index: /trunk/minix/servers/fs/super.h
===================================================================
--- /trunk/minix/servers/fs/super.h	(revision 9)
+++ /trunk/minix/servers/fs/super.h	(revision 9)
@@ -0,0 +1,59 @@
+/* Super block table.  The root file system and every mounted file system
+ * has an entry here.  The entry holds information about the sizes of the bit
+ * maps and inodes.  The s_ninodes field gives the number of inodes available
+ * for files and directories, including the root directory.  Inode 0 is 
+ * on the disk, but not used.  Thus s_ninodes = 4 means that 5 bits will be
+ * used in the bit map, bit 0, which is always 1 and not used, and bits 1-4
+ * for files and directories.  The disk layout is:
+ *
+ *    Item        # blocks
+ *    boot block      1
+ *    super block     1    (offset 1kB)
+ *    inode map     s_imap_blocks
+ *    zone map      s_zmap_blocks
+ *    inodes        (s_ninodes + 'inodes per block' - 1)/'inodes per block'
+ *    unused        whatever is needed to fill out the current zone
+ *    data zones    (s_zones - s_firstdatazone) << s_log_zone_size
+ *
+ * A super_block slot is free if s_dev == NO_DEV. 
+ */
+
+EXTERN struct super_block {
+  ino_t s_ninodes;		/* # usable inodes on the minor device */
+  zone1_t  s_nzones;		/* total device size, including bit maps etc */
+  short s_imap_blocks;		/* # of blocks used by inode bit map */
+  short s_zmap_blocks;		/* # of blocks used by zone bit map */
+  zone1_t s_firstdatazone;	/* number of first data zone */
+  short s_log_zone_size;	/* log2 of blocks/zone */
+  short s_pad;			/* try to avoid compiler-dependent padding */
+  off_t s_max_size;		/* maximum file size on this device */
+  zone_t s_zones;		/* number of zones (replaces s_nzones in V2) */
+  short s_magic;		/* magic number to recognize super-blocks */
+
+  /* The following items are valid on disk only for V3 and above */
+
+  /* The block size in bytes. Minimum MIN_BLOCK SIZE. SECTOR_SIZE
+   * multiple. If V1 or V2 filesystem, this should be
+   * initialised to STATIC_BLOCK_SIZE. Maximum MAX_BLOCK_SIZE.
+   */
+  short s_pad2;			/* try to avoid compiler-dependent padding */
+  unsigned short s_block_size;	/* block size in bytes. */
+  char s_disk_version;		/* filesystem format sub-version */
+
+  /* The following items are only used when the super_block is in memory. */
+  struct inode *s_isup;		/* inode for root dir of mounted file sys */
+  struct inode *s_imount;	/* inode mounted on */
+  unsigned s_inodes_per_block;	/* precalculated from magic number */
+  dev_t s_dev;			/* whose super block is this? */
+  int s_rd_only;		/* set to 1 iff file sys mounted read only */
+  int s_native;			/* set to 1 iff not byte swapped file system */
+  int s_version;		/* file system version, zero means bad magic */
+  int s_ndzones;		/* # direct zones in an inode */
+  int s_nindirs;		/* # indirect zones per indirect block */
+  bit_t s_isearch;		/* inodes below this bit number are in use */
+  bit_t s_zsearch;		/* all zones below this bit number are in use*/
+} super_block[NR_SUPERS];
+
+#define NIL_SUPER (struct super_block *) 0
+#define IMAP		0	/* operating on the inode bit map */
+#define ZMAP		1	/* operating on the zone bit map */
Index: /trunk/minix/servers/fs/table.c
===================================================================
--- /trunk/minix/servers/fs/table.c	(revision 9)
+++ /trunk/minix/servers/fs/table.c	(revision 9)
@@ -0,0 +1,118 @@
+/* This file contains the table used to map system call numbers onto the
+ * routines that perform them.
+ */
+
+#define _TABLE
+
+#include "fs.h"
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include "buf.h"
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "lock.h"
+#include "super.h"
+
+PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
+	no_sys,		/*  0 = unused	*/
+	do_exit,	/*  1 = exit	*/
+	do_fork,	/*  2 = fork	*/
+	do_read,	/*  3 = read	*/
+	do_write,	/*  4 = write	*/
+	do_open,	/*  5 = open	*/
+	do_close,	/*  6 = close	*/
+	no_sys,		/*  7 = wait	*/
+	do_creat,	/*  8 = creat	*/
+	do_link,	/*  9 = link	*/
+	do_unlink,	/* 10 = unlink	*/
+	no_sys,		/* 11 = waitpid	*/
+	do_chdir,	/* 12 = chdir	*/
+	no_sys,		/* 13 = time	*/
+	do_mknod,	/* 14 = mknod	*/
+	do_chmod,	/* 15 = chmod	*/
+	do_chown,	/* 16 = chown	*/
+	no_sys,		/* 17 = break	*/
+	do_stat,	/* 18 = stat	*/
+	do_lseek,	/* 19 = lseek	*/
+	no_sys,		/* 20 = getpid	*/
+	do_mount,	/* 21 = mount	*/
+	do_umount,	/* 22 = umount	*/
+	do_set,		/* 23 = setuid	*/
+	no_sys,		/* 24 = getuid	*/
+	do_stime,	/* 25 = stime	*/
+	no_sys,		/* 26 = ptrace	*/
+	no_sys,		/* 27 = alarm	*/
+	do_fstat,	/* 28 = fstat	*/
+	no_sys,		/* 29 = pause	*/
+	do_utime,	/* 30 = utime	*/
+	no_sys,		/* 31 = (stty)	*/
+	no_sys,		/* 32 = (gtty)	*/
+	do_access,	/* 33 = access	*/
+	no_sys,		/* 34 = (nice)	*/
+	no_sys,		/* 35 = (ftime)	*/
+	do_sync,	/* 36 = sync	*/
+	no_sys,		/* 37 = kill	*/
+	do_rename,	/* 38 = rename	*/
+	do_mkdir,	/* 39 = mkdir	*/
+	do_unlink,	/* 40 = rmdir	*/
+	do_dup,		/* 41 = dup	*/
+	do_pipe,	/* 42 = pipe	*/
+	no_sys,		/* 43 = times	*/
+	no_sys,		/* 44 = (prof)	*/
+	do_slink,	/* 45 = symlink	*/
+	do_set,		/* 46 = setgid	*/
+	no_sys,		/* 47 = getgid	*/
+	no_sys,		/* 48 = (signal)*/
+	do_rdlink,	/* 49 = readlink*/
+	do_lstat,	/* 50 = lstat	*/
+	no_sys,		/* 51 = (acct)	*/
+	no_sys,		/* 52 = (phys)	*/
+	no_sys,		/* 53 = (lock)	*/
+	do_ioctl,	/* 54 = ioctl	*/
+	do_fcntl,	/* 55 = fcntl	*/
+	no_sys,		/* 56 = (mpx)	*/
+	no_sys,		/* 57 = unused	*/
+	no_sys,		/* 58 = unused	*/
+	do_exec,	/* 59 = execve	*/
+	do_umask,	/* 60 = umask	*/
+	do_chroot,	/* 61 = chroot	*/
+	do_setsid,	/* 62 = setsid	*/
+	no_sys,		/* 63 = getpgrp	*/
+
+	no_sys,		/* 64 = KSIG: signals originating in the kernel	*/
+	do_unpause,	/* 65 = UNPAUSE	*/
+	no_sys, 	/* 66 = unused  */
+	do_revive,	/* 67 = REVIVE	*/
+	no_sys,		/* 68 = TASK_REPLY	*/
+	no_sys,		/* 69 = unused */
+	no_sys,		/* 70 = unused */
+	no_sys,		/* 71 = si */
+	no_sys,		/* 72 = sigsuspend */
+	no_sys,		/* 73 = sigpending */
+	no_sys,		/* 74 = sigprocmask */
+	no_sys,		/* 75 = sigreturn */
+	do_reboot,	/* 76 = reboot */
+	do_svrctl,	/* 77 = svrctl */
+
+	no_sys,		/* 78 = unused */
+	do_getsysinfo,  /* 79 = getsysinfo */
+	no_sys,		/* 80 = unused */
+	do_devctl,	/* 81 = devctl */
+	do_fstatfs,	/* 82 = fstatfs */
+	no_sys,		/* 83 = memalloc */
+	no_sys,		/* 84 = memfree */
+	do_select,	/* 85 = select */
+	do_fchdir,	/* 86 = fchdir */
+	do_fsync,	/* 87 = fsync */
+	no_sys,		/* 88 = getpriority */
+	no_sys,		/* 89 = setpriority */
+	no_sys,		/* 90 = gettimeofday */
+	no_sys,		/* 91 = seteuid */
+	no_sys,		/* 92 = setegid */
+	do_truncate,	/* 93 = truncate */
+	do_ftruncate,	/* 94 = truncate */
+};
+/* This should not fail with "array size is negative": */
+extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
+
Index: /trunk/minix/servers/fs/time.c
===================================================================
--- /trunk/minix/servers/fs/time.c	(revision 9)
+++ /trunk/minix/servers/fs/time.c	(revision 9)
@@ -0,0 +1,66 @@
+/* This file takes care of those system calls that deal with time.
+ *
+ * The entry points into this file are
+ *   do_utime:		perform the UTIME system call
+ *   do_stime:		PM informs FS about STIME system call
+ */
+
+#include "fs.h"
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "param.h"
+
+/*===========================================================================*
+ *				do_utime				     *
+ *===========================================================================*/
+PUBLIC int do_utime()
+{
+/* Perform the utime(name, timep) system call. */
+
+  register struct inode *rip;
+  register int len, r;
+
+  /* Adjust for case of 'timep' being NULL;
+   * utime_strlen then holds the actual size: strlen(name)+1.
+   */
+  len = m_in.utime_length;
+  if (len == 0) len = m_in.utime_strlen;
+
+  /* Temporarily open the file. */
+  if (fetch_name(m_in.utime_file, len, M1) != OK) return(err_code);
+  if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
+
+  /* Only the owner of a file or the super_user can change its time. */
+  r = OK;
+  if (rip->i_uid != fp->fp_effuid && !super_user) r = EPERM;
+  if (m_in.utime_length == 0 && r != OK) r = forbidden(rip, W_BIT);
+  if (read_only(rip) != OK) r = EROFS;	/* not even su can touch if R/O */
+  if (r == OK) {
+	if (m_in.utime_length == 0) {
+		rip->i_atime = clock_time();
+		rip->i_mtime = rip->i_atime;
+	} else {
+		rip->i_atime = m_in.utime_actime;
+		rip->i_mtime = m_in.utime_modtime;
+	}
+	rip->i_update = CTIME;	/* discard any stale ATIME and MTIME flags */
+	rip->i_dirt = DIRTY;
+  }
+
+  put_inode(rip);
+  return(r);
+}
+
+/*===========================================================================*
+ *				do_stime				     *
+ *===========================================================================*/
+PUBLIC int do_stime()
+{
+/* Perform the stime(tp) system call. */
+  boottime = (long) m_in.pm_stime; 
+  return(OK);
+}
+
Index: /trunk/minix/servers/fs/timers.c
===================================================================
--- /trunk/minix/servers/fs/timers.c	(revision 9)
+++ /trunk/minix/servers/fs/timers.c	(revision 9)
@@ -0,0 +1,66 @@
+/* FS timers library
+ */
+
+#include "fs.h"
+
+#include <timers.h>
+#include <minix/syslib.h>
+#include <minix/com.h>
+
+PRIVATE timer_t *fs_timers = NULL;
+
+PUBLIC void fs_set_timer(timer_t *tp, int ticks, tmr_func_t watchdog, int arg)
+{
+	int r;
+	clock_t now, old_head = 0, new_head;
+
+	if ((r = getuptime(&now)) != OK)
+		panic(__FILE__, "FS couldn't get uptime from system task.", NO_NUM);
+
+	tmr_arg(tp)->ta_int = arg;
+
+	old_head = tmrs_settimer(&fs_timers, tp, now+ticks, watchdog, &new_head);
+
+	/* reschedule our synchronous alarm if necessary */
+	if (!old_head || old_head > new_head) {
+		if (sys_setalarm(new_head, 1) != OK)
+			panic(__FILE__, "FS set timer "
+			"couldn't set synchronous alarm.", NO_NUM);
+	}
+
+	return;
+}
+
+PUBLIC void fs_expire_timers(clock_t now)
+{
+	clock_t new_head;
+	tmrs_exptimers(&fs_timers, now, &new_head);
+	if (new_head > 0) {
+		if (sys_setalarm(new_head, 1) != OK)
+			panic(__FILE__, "FS expire timer couldn't set "
+				"synchronous alarm.", NO_NUM);
+	}
+}
+
+PUBLIC void fs_init_timer(timer_t *tp)
+{
+	tmr_inittimer(tp);
+}
+
+PUBLIC void fs_cancel_timer(timer_t *tp)
+{
+	clock_t new_head, old_head;
+	old_head = tmrs_clrtimer(&fs_timers, tp, &new_head);
+
+	/* if the earliest timer has been removed, we have to set
+	 * the synalarm to the next timer, or cancel the synalarm
+	 * altogether if th last time has been cancelled (new_head
+	 * will be 0 then).
+	 */
+	if (old_head < new_head || !new_head) {
+		if (sys_setalarm(new_head, 1) != OK)
+			panic(__FILE__,
+			"FS expire timer couldn't set synchronous alarm.",
+				 NO_NUM);
+	}
+}
Index: /trunk/minix/servers/fs/type.h
===================================================================
--- /trunk/minix/servers/fs/type.h	(revision 9)
+++ /trunk/minix/servers/fs/type.h	(revision 9)
@@ -0,0 +1,23 @@
+/* Declaration of the V1 inode as it is on the disk (not in core). */
+typedef struct {		/* V1.x disk inode */
+  mode_t d1_mode;		/* file type, protection, etc. */
+  uid_t d1_uid;			/* user id of the file's owner */
+  off_t d1_size;		/* current file size in bytes */
+  time_t d1_mtime;		/* when was file data last changed */
+  u8_t d1_gid;			/* group number */
+  u8_t d1_nlinks;		/* how many links to this file */
+  u16_t d1_zone[V1_NR_TZONES];	/* block nums for direct, ind, and dbl ind */
+} d1_inode;
+
+/* Declaration of the V2 inode as it is on the disk (not in core). */
+typedef struct {		/* V2.x disk inode */
+  mode_t d2_mode;		/* file type, protection, etc. */
+  u16_t d2_nlinks;		/* how many links to this file. HACK! */
+  uid_t d2_uid;			/* user id of the file's owner. */
+  u16_t d2_gid;			/* group number HACK! */
+  off_t d2_size;		/* current file size in bytes */
+  time_t d2_atime;		/* when was file data last accessed */
+  time_t d2_mtime;		/* when was file data last changed */
+  time_t d2_ctime;		/* when was inode data last changed */
+  zone_t d2_zone[V2_NR_TZONES];	/* block nums for direct, ind, and dbl ind */
+} d2_inode;
Index: /trunk/minix/servers/fs/utility.c
===================================================================
--- /trunk/minix/servers/fs/utility.c	(revision 9)
+++ /trunk/minix/servers/fs/utility.c	(revision 9)
@@ -0,0 +1,165 @@
+/* This file contains a few general purpose utility routines.
+ *
+ * The entry points into this file are
+ *   clock_time:  ask the clock task for the real time
+ *   copy:	  copy a block of data
+ *   fetch_name:  go get a path name from user space
+ *   no_sys:      reject a system call that FS does not handle
+ *   panic:       something awful has occurred;  MINIX cannot continue
+ *   conv2:	  do byte swapping on a 16-bit int
+ *   conv4:	  do byte swapping on a 32-bit long
+ */
+
+#include "fs.h"
+#include <minix/com.h>
+#include <minix/endpoint.h>
+#include <unistd.h>
+#include "buf.h"
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "param.h"
+
+PRIVATE int panicking;		/* inhibits recursive panics during sync */
+
+/*===========================================================================*
+ *				clock_time				     *
+ *===========================================================================*/
+PUBLIC time_t clock_time()
+{
+/* This routine returns the time in seconds since 1.1.1970.  MINIX is an
+ * astrophysically naive system that assumes the earth rotates at a constant
+ * rate and that such things as leap seconds do not exist.
+ */
+
+  register int k;
+  clock_t uptime;
+
+  if ( (k=getuptime(&uptime)) != OK) panic(__FILE__,"clock_time err", k);
+  return( (time_t) (boottime + (uptime/HZ)));
+}
+
+/*===========================================================================*
+ *				fetch_name				     *
+ *===========================================================================*/
+PUBLIC int fetch_name(path, len, flag)
+char *path;			/* pointer to the path in user space */
+int len;			/* path length, including 0 byte */
+int flag;			/* M3 means path may be in message */
+{
+/* Go get path and put it in 'user_path'.
+ * If 'flag' = M3 and 'len' <= M3_STRING, the path is present in 'message'.
+ * If it is not, go copy it from user space.
+ */
+  register char *rpu, *rpm;
+  int r;
+
+  /* Check name length for validity. */
+  if (len <= 0) {
+	err_code = EINVAL;
+	return(EGENERIC);
+  }
+
+  if (len > PATH_MAX) {
+	err_code = ENAMETOOLONG;
+	return(EGENERIC);
+  }
+
+  if (flag == M3 && len <= M3_STRING) {
+	/* Just copy the path from the message to 'user_path'. */
+	rpu = &user_path[0];
+	rpm = m_in.pathname;		/* contained in input message */
+	do { *rpu++ = *rpm++; } while (--len);
+	r = OK;
+  } else {
+	/* String is not contained in the message.  Get it from user space. */
+	r = sys_datacopy(who_e, (vir_bytes) path,
+		FS_PROC_NR, (vir_bytes) user_path, (phys_bytes) len);
+  }
+  return(r);
+}
+
+/*===========================================================================*
+ *				no_sys					     *
+ *===========================================================================*/
+PUBLIC int no_sys()
+{
+/* Somebody has used an illegal system call number */
+  return(EINVAL);
+}
+
+/*===========================================================================*
+ *				panic					     *
+ *===========================================================================*/
+PUBLIC void panic(who, mess, num)
+char *who;			/* who caused the panic */
+char *mess;			/* panic message string */
+int num;			/* number to go with it */
+{
+/* Something awful has happened.  Panics are caused when an internal
+ * inconsistency is detected, e.g., a programming error or illegal value of a
+ * defined constant.
+ */
+  if (panicking) return;	/* do not panic during a sync */
+  panicking = TRUE;		/* prevent another panic during the sync */
+
+  printf("FS panic (%s): %s ", who, mess);
+  if (num != NO_NUM) printf("%d",num); 
+  (void) do_sync();		/* flush everything to the disk */
+  sys_exit(SELF);
+}
+
+/*===========================================================================*
+ *				conv2					     *
+ *===========================================================================*/
+PUBLIC unsigned conv2(norm, w)
+int norm;			/* TRUE if no swap, FALSE for byte swap */
+int w;				/* promotion of 16-bit word to be swapped */
+{
+/* Possibly swap a 16-bit word between 8086 and 68000 byte order. */
+  if (norm) return( (unsigned) w & 0xFFFF);
+  return( ((w&BYTE) << 8) | ( (w>>8) & BYTE));
+}
+
+/*===========================================================================*
+ *				conv4					     *
+ *===========================================================================*/
+PUBLIC long conv4(norm, x)
+int norm;			/* TRUE if no swap, FALSE for byte swap */
+long x;				/* 32-bit long to be byte swapped */
+{
+/* Possibly swap a 32-bit long between 8086 and 68000 byte order. */
+  unsigned lo, hi;
+  long l;
+  
+  if (norm) return(x);			/* byte order was already ok */
+  lo = conv2(FALSE, (int) x & 0xFFFF);	/* low-order half, byte swapped */
+  hi = conv2(FALSE, (int) (x>>16) & 0xFFFF);	/* high-order half, swapped */
+  l = ( (long) lo <<16) | hi;
+  return(l);
+}
+
+/*===========================================================================*
+ *				isokendpt_f				     *
+ *===========================================================================*/
+PUBLIC int isokendpt_f(char *file, int line, int endpoint, int *proc, int fatal)
+{
+	int failed = 0;
+	*proc = _ENDPOINT_P(endpoint);
+	if(*proc < 0 || *proc >= NR_PROCS) {
+		printf("FS:%s:%d: proc (%d) from endpoint (%d) out of range\n",
+			file, line, *proc, endpoint);
+		failed = 1;
+	} else if(fproc[*proc].fp_endpoint != endpoint) {
+		printf("FS:%s:%d: proc (%d) from endpoint (%d) doesn't match "
+			"known endpoint (%d)\n",
+			file, line, *proc, endpoint, fproc[*proc].fp_endpoint);
+		failed = 1;
+	}
+
+	if(failed && fatal)
+		panic(__FILE__, "isokendpt_f failed", NO_NUM);
+
+	return failed ? EDEADSRCDST : OK;
+}
+
Index: /trunk/minix/servers/fs/write.c
===================================================================
--- /trunk/minix/servers/fs/write.c	(revision 9)
+++ /trunk/minix/servers/fs/write.c	(revision 9)
@@ -0,0 +1,338 @@
+/* This file is the counterpart of "read.c".  It contains the code for writing
+ * insofar as this is not contained in read_write().
+ *
+ * The entry points into this file are
+ *   do_write:     call read_write to perform the WRITE system call
+ *   clear_zone:   erase a zone in the middle of a file
+ *   new_block:    acquire a new block
+ */
+
+#include "fs.h"
+#include <string.h>
+#include "buf.h"
+#include "file.h"
+#include "fproc.h"
+#include "inode.h"
+#include "super.h"
+
+FORWARD _PROTOTYPE( void wr_indir, (struct buf *bp, int index, zone_t zone) );
+FORWARD _PROTOTYPE( int empty_indir, (struct buf *, struct super_block *) );
+
+/*===========================================================================*
+ *				do_write				     *
+ *===========================================================================*/
+PUBLIC int do_write()
+{
+/* Perform the write(fd, buffer, nbytes) system call. */
+
+  return(read_write(WRITING));
+}
+
+/*===========================================================================*
+ *				write_map				     *
+ *===========================================================================*/
+PUBLIC int write_map(rip, position, new_zone, op)
+struct inode *rip;		/* pointer to inode to be changed */
+off_t position;			/* file address to be mapped */
+zone_t new_zone;		/* zone # to be inserted */
+int op;				/* special actions */
+{
+/* Write a new zone into an inode.
+ *
+ * If op includes WMAP_FREE, free the data zone corresponding to that position
+ * in the inode ('new_zone' is ignored then). Also free the indirect block
+ * if that was the last entry in the indirect block.
+ * Also free the double indirect block if that was the last entry in the
+ * double indirect block.
+ */
+  int scale, ind_ex, new_ind, new_dbl, zones, nr_indirects, single, zindex, ex;
+  zone_t z, z1, z2 = NO_ZONE, old_zone;
+  register block_t b;
+  long excess, zone;
+  struct buf *bp_dindir = NIL_BUF, *bp = NIL_BUF;
+
+  rip->i_dirt = DIRTY;		/* inode will be changed */
+  scale = rip->i_sp->s_log_zone_size;		/* for zone-block conversion */
+  	/* relative zone # to insert */
+  zone = (position/rip->i_sp->s_block_size) >> scale;
+  zones = rip->i_ndzones;	/* # direct zones in the inode */
+  nr_indirects = rip->i_nindirs;/* # indirect zones per indirect block */
+
+  /* Is 'position' to be found in the inode itself? */
+  if (zone < zones) {
+	zindex = (int) zone;	/* we need an integer here */
+	if(rip->i_zone[zindex] != NO_ZONE && (op & WMAP_FREE)) {
+		free_zone(rip->i_dev, rip->i_zone[zindex]);
+		rip->i_zone[zindex] = NO_ZONE;
+	} else {
+		rip->i_zone[zindex] = new_zone;
+	}
+	return(OK);
+  }
+
+  /* It is not in the inode, so it must be single or double indirect. */
+  excess = zone - zones;	/* first Vx_NR_DZONES don't count */
+  new_ind = FALSE;
+  new_dbl = FALSE;
+
+  if (excess < nr_indirects) {
+	/* 'position' can be located via the single indirect block. */
+	z1 = rip->i_zone[zones];	/* single indirect zone */
+	single = TRUE;
+  } else {
+	/* 'position' can be located via the double indirect block. */
+	if ( (z2 = z = rip->i_zone[zones+1]) == NO_ZONE &&
+	    !(op & WMAP_FREE)) {
+		/* Create the double indirect block. */
+		if ( (z = alloc_zone(rip->i_dev, rip->i_zone[0])) == NO_ZONE)
+			return(err_code);
+		rip->i_zone[zones+1] = z;
+		new_dbl = TRUE;	/* set flag for later */
+	}
+
+	/* 'z' is zone number for double indirect block, either old
+	 * or newly created.
+	 * If there wasn't one and WMAP_FREE is set, 'z' is NO_ZONE.
+	 */
+	excess -= nr_indirects;	/* single indirect doesn't count */
+	ind_ex = (int) (excess / nr_indirects);
+	excess = excess % nr_indirects;
+	if (ind_ex >= nr_indirects) return(EFBIG);
+
+	if(z == NO_ZONE) {
+		/* WMAP_FREE and no double indirect block - then no
+		 * single indirect block either.
+		 */
+		z1 = NO_ZONE;
+	} else {
+		b = (block_t) z << scale;
+		bp_dindir = get_block(rip->i_dev, b, (new_dbl?NO_READ:NORMAL));
+		if (new_dbl) zero_block(bp_dindir);
+		z1 = rd_indir(bp_dindir, ind_ex);
+	}
+	single = FALSE;
+  }
+
+  /* z1 is now single indirect zone, or NO_ZONE; 'excess' is index.
+   * We have to create the indirect zone if it's NO_ZONE. Unless
+   * we're freeing (WMAP_FREE).
+   */
+  if (z1 == NO_ZONE && !(op & WMAP_FREE)) {
+	z1 = alloc_zone(rip->i_dev, rip->i_zone[0]);
+	if (single)
+		rip->i_zone[zones] = z1; /* update inode w. single indirect */
+	else
+		wr_indir(bp_dindir, ind_ex, z1);	/* update dbl indir */
+
+	new_ind = TRUE;
+	/* If double ind, it is dirty. */
+	if (bp_dindir != NIL_BUF) bp_dindir->b_dirt = DIRTY;
+	if (z1 == NO_ZONE) {
+		/* Release dbl indirect blk. */
+		put_block(bp_dindir, INDIRECT_BLOCK);
+		return(err_code);	/* couldn't create single ind */
+	}
+  }
+
+  /* z1 is indirect block's zone number (unless it's NO_ZONE when we're
+   * freeing).
+   */
+  if(z1 != NO_ZONE) {
+  	ex = (int) excess;			/* we need an int here */
+	b = (block_t) z1 << scale;
+	bp = get_block(rip->i_dev, b, (new_ind ? NO_READ : NORMAL) );
+	if (new_ind) zero_block(bp);
+	if(op & WMAP_FREE) {
+		if((old_zone = rd_indir(bp, ex)) != NO_ZONE) {
+			free_zone(rip->i_dev, old_zone);
+			wr_indir(bp, ex, NO_ZONE);
+		}
+
+		/* Last reference in the indirect block gone? Then
+		 * Free the indirect block.
+		 */
+		if(empty_indir(bp, rip->i_sp)) {
+			free_zone(rip->i_dev, z1);
+			z1 = NO_ZONE;
+			/* Update the reference to the indirect block to
+			 * NO_ZONE - in the double indirect block if there
+			 * is one, otherwise in the inode directly.
+			 */
+			if(single) {
+				rip->i_zone[zones] = z1;
+			} else {
+				wr_indir(bp_dindir, ind_ex, z1);
+				bp_dindir->b_dirt = DIRTY;
+			}
+		}
+	} else {
+		wr_indir(bp, ex, new_zone);
+	}
+	bp->b_dirt = DIRTY;
+	put_block(bp, INDIRECT_BLOCK);
+  }
+
+  /* If the single indirect block isn't there (or was just freed),
+   * see if we have to keep the double indirect block.
+   */
+  if(z1 == NO_ZONE && !single && empty_indir(bp_dindir, rip->i_sp) &&
+     z2 != NO_ZONE) {
+	free_zone(rip->i_dev, z2);
+	rip->i_zone[zones+1] = NO_ZONE;
+  }
+
+  put_block(bp_dindir, INDIRECT_BLOCK);	/* release double indirect blk */
+
+  return(OK);
+}
+
+/*===========================================================================*
+ *				wr_indir				     *
+ *===========================================================================*/
+PRIVATE void wr_indir(bp, index, zone)
+struct buf *bp;			/* pointer to indirect block */
+int index;			/* index into *bp */
+zone_t zone;			/* zone to write */
+{
+/* Given a pointer to an indirect block, write one entry. */
+
+  struct super_block *sp;
+
+  if(bp == NIL_BUF)
+	panic(__FILE__, "wr_indir() on NIL_BUF", NO_NUM);
+
+  sp = get_super(bp->b_dev);	/* need super block to find file sys type */
+
+  /* write a zone into an indirect block */
+  if (sp->s_version == V1)
+	bp->b_v1_ind[index] = (zone1_t) conv2(sp->s_native, (int)  zone);
+  else
+	bp->b_v2_ind[index] = (zone_t)  conv4(sp->s_native, (long) zone);
+}
+
+/*===========================================================================*
+ *				empty_indir				     *
+ *===========================================================================*/
+PRIVATE int empty_indir(bp, sb)
+struct buf *bp;			/* pointer to indirect block */
+struct super_block *sb;		/* superblock of device block resides on */
+{
+/* Return nonzero if the indirect block pointed to by bp contains
+ * only NO_ZONE entries.
+ */
+	int i;
+	if(sb->s_version == V1) {
+		for(i = 0; i < V1_INDIRECTS; i++)
+			if(bp->b_v1_ind[i] != NO_ZONE)
+				return 0;
+	} else {
+		for(i = 0; i < V2_INDIRECTS(sb->s_block_size); i++)
+			if(bp->b_v2_ind[i] != NO_ZONE)
+				return 0;
+	}
+
+	return 1;
+}
+
+/*===========================================================================*
+ *				clear_zone				     *
+ *===========================================================================*/
+PUBLIC void clear_zone(rip, pos, flag)
+register struct inode *rip;	/* inode to clear */
+off_t pos;			/* points to block to clear */
+int flag;			/* 0 if called by read_write, 1 by new_block */
+{
+/* Zero a zone, possibly starting in the middle.  The parameter 'pos' gives
+ * a byte in the first block to be zeroed.  Clearzone() is called from 
+ * read_write and new_block().
+ */
+
+  register struct buf *bp;
+  register block_t b, blo, bhi;
+  register off_t next;
+  register int scale;
+  register zone_t zone_size;
+
+  /* If the block size and zone size are the same, clear_zone() not needed. */
+  scale = rip->i_sp->s_log_zone_size;
+  if (scale == 0) return;
+
+  zone_size = (zone_t) rip->i_sp->s_block_size << scale;
+  if (flag == 1) pos = (pos/zone_size) * zone_size;
+  next = pos + rip->i_sp->s_block_size - 1;
+
+  /* If 'pos' is in the last block of a zone, do not clear the zone. */
+  if (next/zone_size != pos/zone_size) return;
+  if ( (blo = read_map(rip, next)) == NO_BLOCK) return;
+  bhi = (  ((blo>>scale)+1) << scale)   - 1;
+
+  /* Clear all the blocks between 'blo' and 'bhi'. */
+  for (b = blo; b <= bhi; b++) {
+	bp = get_block(rip->i_dev, b, NO_READ);
+	zero_block(bp);
+	put_block(bp, FULL_DATA_BLOCK);
+  }
+}
+
+/*===========================================================================*
+ *				new_block				     *
+ *===========================================================================*/
+PUBLIC struct buf *new_block(rip, position)
+register struct inode *rip;	/* pointer to inode */
+off_t position;			/* file pointer */
+{
+/* Acquire a new block and return a pointer to it.  Doing so may require
+ * allocating a complete zone, and then returning the initial block.
+ * On the other hand, the current zone may still have some unused blocks.
+ */
+
+  register struct buf *bp;
+  block_t b, base_block;
+  zone_t z;
+  zone_t zone_size;
+  int scale, r;
+  struct super_block *sp;
+
+  /* Is another block available in the current zone? */
+  if ( (b = read_map(rip, position)) == NO_BLOCK) {
+	/* Choose first zone if possible. */
+	/* Lose if the file is nonempty but the first zone number is NO_ZONE
+	 * corresponding to a zone full of zeros.  It would be better to
+	 * search near the last real zone.
+	 */
+	if (rip->i_zone[0] == NO_ZONE) {
+		sp = rip->i_sp;
+		z = sp->s_firstdatazone;
+	} else {
+		z = rip->i_zone[0];	/* hunt near first zone */
+	}
+	if ( (z = alloc_zone(rip->i_dev, z)) == NO_ZONE) return(NIL_BUF);
+	if ( (r = write_map(rip, position, z, 0)) != OK) {
+		free_zone(rip->i_dev, z);
+		err_code = r;
+		return(NIL_BUF);
+	}
+
+	/* If we are not writing at EOF, clear the zone, just to be safe. */
+	if ( position != rip->i_size) clear_zone(rip, position, 1);
+	scale = rip->i_sp->s_log_zone_size;
+	base_block = (block_t) z << scale;
+	zone_size = (zone_t) rip->i_sp->s_block_size << scale;
+	b = base_block + (block_t)((position % zone_size)/rip->i_sp->s_block_size);
+  }
+
+  bp = get_block(rip->i_dev, b, NO_READ);
+  zero_block(bp);
+  return(bp);
+}
+
+/*===========================================================================*
+ *				zero_block				     *
+ *===========================================================================*/
+PUBLIC void zero_block(bp)
+register struct buf *bp;	/* pointer to buffer to zero */
+{
+/* Zero a block. */
+  memset(bp->b_data, 0, _MAX_BLOCK_SIZE);
+  bp->b_dirt = DIRTY;
+}
Index: /trunk/minix/servers/inet/.depend
===================================================================
--- /trunk/minix/servers/inet/.depend	(revision 9)
+++ /trunk/minix/servers/inet/.depend	(revision 9)
@@ -0,0 +1,1567 @@
+
+buf.o:	/usr/include/ansi.h
+buf.o:	/usr/include/errno.h
+buf.o:	/usr/include/minix/com.h
+buf.o:	/usr/include/minix/config.h
+buf.o:	/usr/include/minix/const.h
+buf.o:	/usr/include/minix/devio.h
+buf.o:	/usr/include/minix/ioctl.h
+buf.o:	/usr/include/minix/ipc.h
+buf.o:	/usr/include/minix/sys_config.h
+buf.o:	/usr/include/minix/syslib.h
+buf.o:	/usr/include/minix/sysutil.h
+buf.o:	/usr/include/minix/type.h
+buf.o:	/usr/include/net/gen/arp_io.h
+buf.o:	/usr/include/net/gen/eth_hdr.h
+buf.o:	/usr/include/net/gen/eth_io.h
+buf.o:	/usr/include/net/gen/ether.h
+buf.o:	/usr/include/net/gen/icmp.h
+buf.o:	/usr/include/net/gen/icmp_hdr.h
+buf.o:	/usr/include/net/gen/in.h
+buf.o:	/usr/include/net/gen/ip_hdr.h
+buf.o:	/usr/include/net/gen/ip_io.h
+buf.o:	/usr/include/net/gen/oneCsum.h
+buf.o:	/usr/include/net/gen/psip_hdr.h
+buf.o:	/usr/include/net/gen/psip_io.h
+buf.o:	/usr/include/net/gen/route.h
+buf.o:	/usr/include/net/gen/tcp.h
+buf.o:	/usr/include/net/gen/tcp_hdr.h
+buf.o:	/usr/include/net/gen/tcp_io.h
+buf.o:	/usr/include/net/gen/udp.h
+buf.o:	/usr/include/net/gen/udp_hdr.h
+buf.o:	/usr/include/net/gen/udp_io.h
+buf.o:	/usr/include/net/hton.h
+buf.o:	/usr/include/net/ioctl.h
+buf.o:	/usr/include/stddef.h
+buf.o:	/usr/include/stdlib.h
+buf.o:	/usr/include/string.h
+buf.o:	/usr/include/sys/ioc_file.h
+buf.o:	/usr/include/sys/time.h
+buf.o:	/usr/include/sys/types.h
+buf.o:	/usr/include/unistd.h
+buf.o:	buf.c
+buf.o:	const.h
+buf.o:	generic/assert.h
+buf.o:	generic/buf.h
+buf.o:	generic/type.h
+buf.o:	inet.h
+buf.o:	inet_config.h
+
+clock.o:	/usr/include/ansi.h
+clock.o:	/usr/include/errno.h
+clock.o:	/usr/include/minix/com.h
+clock.o:	/usr/include/minix/config.h
+clock.o:	/usr/include/minix/const.h
+clock.o:	/usr/include/minix/devio.h
+clock.o:	/usr/include/minix/ioctl.h
+clock.o:	/usr/include/minix/ipc.h
+clock.o:	/usr/include/minix/sys_config.h
+clock.o:	/usr/include/minix/syslib.h
+clock.o:	/usr/include/minix/sysutil.h
+clock.o:	/usr/include/minix/type.h
+clock.o:	/usr/include/net/gen/arp_io.h
+clock.o:	/usr/include/net/gen/eth_hdr.h
+clock.o:	/usr/include/net/gen/eth_io.h
+clock.o:	/usr/include/net/gen/ether.h
+clock.o:	/usr/include/net/gen/icmp.h
+clock.o:	/usr/include/net/gen/icmp_hdr.h
+clock.o:	/usr/include/net/gen/in.h
+clock.o:	/usr/include/net/gen/ip_hdr.h
+clock.o:	/usr/include/net/gen/ip_io.h
+clock.o:	/usr/include/net/gen/oneCsum.h
+clock.o:	/usr/include/net/gen/psip_hdr.h
+clock.o:	/usr/include/net/gen/psip_io.h
+clock.o:	/usr/include/net/gen/route.h
+clock.o:	/usr/include/net/gen/tcp.h
+clock.o:	/usr/include/net/gen/tcp_hdr.h
+clock.o:	/usr/include/net/gen/tcp_io.h
+clock.o:	/usr/include/net/gen/udp.h
+clock.o:	/usr/include/net/gen/udp_hdr.h
+clock.o:	/usr/include/net/gen/udp_io.h
+clock.o:	/usr/include/net/hton.h
+clock.o:	/usr/include/net/ioctl.h
+clock.o:	/usr/include/stddef.h
+clock.o:	/usr/include/stdlib.h
+clock.o:	/usr/include/string.h
+clock.o:	/usr/include/sys/ioc_file.h
+clock.o:	/usr/include/sys/time.h
+clock.o:	/usr/include/sys/types.h
+clock.o:	/usr/include/unistd.h
+clock.o:	clock.c
+clock.o:	const.h
+clock.o:	generic/assert.h
+clock.o:	generic/buf.h
+clock.o:	generic/clock.h
+clock.o:	generic/type.h
+clock.o:	inet.h
+clock.o:	inet_config.h
+clock.o:	proto.h
+
+inet.o:	/usr/include/ansi.h
+inet.o:	/usr/include/errno.h
+inet.o:	/usr/include/fcntl.h
+inet.o:	/usr/include/minix/com.h
+inet.o:	/usr/include/minix/config.h
+inet.o:	/usr/include/minix/const.h
+inet.o:	/usr/include/minix/devio.h
+inet.o:	/usr/include/minix/dmap.h
+inet.o:	/usr/include/minix/ioctl.h
+inet.o:	/usr/include/minix/ipc.h
+inet.o:	/usr/include/minix/sys_config.h
+inet.o:	/usr/include/minix/syslib.h
+inet.o:	/usr/include/minix/sysutil.h
+inet.o:	/usr/include/minix/type.h
+inet.o:	/usr/include/net/gen/arp_io.h
+inet.o:	/usr/include/net/gen/eth_hdr.h
+inet.o:	/usr/include/net/gen/eth_io.h
+inet.o:	/usr/include/net/gen/ether.h
+inet.o:	/usr/include/net/gen/icmp.h
+inet.o:	/usr/include/net/gen/icmp_hdr.h
+inet.o:	/usr/include/net/gen/in.h
+inet.o:	/usr/include/net/gen/ip_hdr.h
+inet.o:	/usr/include/net/gen/ip_io.h
+inet.o:	/usr/include/net/gen/oneCsum.h
+inet.o:	/usr/include/net/gen/psip_hdr.h
+inet.o:	/usr/include/net/gen/psip_io.h
+inet.o:	/usr/include/net/gen/route.h
+inet.o:	/usr/include/net/gen/tcp.h
+inet.o:	/usr/include/net/gen/tcp_hdr.h
+inet.o:	/usr/include/net/gen/tcp_io.h
+inet.o:	/usr/include/net/gen/udp.h
+inet.o:	/usr/include/net/gen/udp_hdr.h
+inet.o:	/usr/include/net/gen/udp_io.h
+inet.o:	/usr/include/net/hton.h
+inet.o:	/usr/include/net/ioctl.h
+inet.o:	/usr/include/stddef.h
+inet.o:	/usr/include/stdlib.h
+inet.o:	/usr/include/string.h
+inet.o:	/usr/include/sys/ioc_file.h
+inet.o:	/usr/include/sys/svrctl.h
+inet.o:	/usr/include/sys/time.h
+inet.o:	/usr/include/sys/types.h
+inet.o:	/usr/include/time.h
+inet.o:	/usr/include/unistd.h
+inet.o:	const.h
+inet.o:	generic/arp.h
+inet.o:	generic/assert.h
+inet.o:	generic/buf.h
+inet.o:	generic/clock.h
+inet.o:	generic/eth.h
+inet.o:	generic/event.h
+inet.o:	generic/ip.h
+inet.o:	generic/psip.h
+inet.o:	generic/rand256.h
+inet.o:	generic/sr.h
+inet.o:	generic/tcp.h
+inet.o:	generic/type.h
+inet.o:	generic/udp.h
+inet.o:	inet.c
+inet.o:	inet.h
+inet.o:	inet_config.h
+inet.o:	mq.h
+inet.o:	proto.h
+inet.o:	qp.h
+
+inet_config.o:	/usr/include/ansi.h
+inet_config.o:	/usr/include/errno.h
+inet_config.o:	/usr/include/fcntl.h
+inet_config.o:	/usr/include/minix/devio.h
+inet_config.o:	/usr/include/minix/ipc.h
+inet_config.o:	/usr/include/minix/sys_config.h
+inet_config.o:	/usr/include/minix/syslib.h
+inet_config.o:	/usr/include/minix/sysutil.h
+inet_config.o:	/usr/include/minix/type.h
+inet_config.o:	/usr/include/stdlib.h
+inet_config.o:	/usr/include/string.h
+inet_config.o:	/usr/include/sys/stat.h
+inet_config.o:	/usr/include/sys/types.h
+inet_config.o:	/usr/include/unistd.h
+inet_config.o:	inet_config.c
+inet_config.o:	inet_config.h
+
+mnx_eth.o:	/usr/include/ansi.h
+mnx_eth.o:	/usr/include/errno.h
+mnx_eth.o:	/usr/include/minix/com.h
+mnx_eth.o:	/usr/include/minix/config.h
+mnx_eth.o:	/usr/include/minix/const.h
+mnx_eth.o:	/usr/include/minix/devio.h
+mnx_eth.o:	/usr/include/minix/ioctl.h
+mnx_eth.o:	/usr/include/minix/ipc.h
+mnx_eth.o:	/usr/include/minix/sys_config.h
+mnx_eth.o:	/usr/include/minix/syslib.h
+mnx_eth.o:	/usr/include/minix/sysutil.h
+mnx_eth.o:	/usr/include/minix/type.h
+mnx_eth.o:	/usr/include/net/gen/arp_io.h
+mnx_eth.o:	/usr/include/net/gen/eth_hdr.h
+mnx_eth.o:	/usr/include/net/gen/eth_io.h
+mnx_eth.o:	/usr/include/net/gen/ether.h
+mnx_eth.o:	/usr/include/net/gen/icmp.h
+mnx_eth.o:	/usr/include/net/gen/icmp_hdr.h
+mnx_eth.o:	/usr/include/net/gen/in.h
+mnx_eth.o:	/usr/include/net/gen/ip_hdr.h
+mnx_eth.o:	/usr/include/net/gen/ip_io.h
+mnx_eth.o:	/usr/include/net/gen/oneCsum.h
+mnx_eth.o:	/usr/include/net/gen/psip_hdr.h
+mnx_eth.o:	/usr/include/net/gen/psip_io.h
+mnx_eth.o:	/usr/include/net/gen/route.h
+mnx_eth.o:	/usr/include/net/gen/tcp.h
+mnx_eth.o:	/usr/include/net/gen/tcp_hdr.h
+mnx_eth.o:	/usr/include/net/gen/tcp_io.h
+mnx_eth.o:	/usr/include/net/gen/udp.h
+mnx_eth.o:	/usr/include/net/gen/udp_hdr.h
+mnx_eth.o:	/usr/include/net/gen/udp_io.h
+mnx_eth.o:	/usr/include/net/hton.h
+mnx_eth.o:	/usr/include/net/ioctl.h
+mnx_eth.o:	/usr/include/stddef.h
+mnx_eth.o:	/usr/include/stdlib.h
+mnx_eth.o:	/usr/include/string.h
+mnx_eth.o:	/usr/include/sys/ioc_file.h
+mnx_eth.o:	/usr/include/sys/time.h
+mnx_eth.o:	/usr/include/sys/types.h
+mnx_eth.o:	/usr/include/unistd.h
+mnx_eth.o:	const.h
+mnx_eth.o:	generic/assert.h
+mnx_eth.o:	generic/buf.h
+mnx_eth.o:	generic/clock.h
+mnx_eth.o:	generic/eth.h
+mnx_eth.o:	generic/eth_int.h
+mnx_eth.o:	generic/event.h
+mnx_eth.o:	generic/sr.h
+mnx_eth.o:	generic/type.h
+mnx_eth.o:	inet.h
+mnx_eth.o:	inet_config.h
+mnx_eth.o:	mnx_eth.c
+mnx_eth.o:	osdep_eth.h
+mnx_eth.o:	proto.h
+
+mq.o:	/usr/include/ansi.h
+mq.o:	/usr/include/errno.h
+mq.o:	/usr/include/minix/com.h
+mq.o:	/usr/include/minix/config.h
+mq.o:	/usr/include/minix/const.h
+mq.o:	/usr/include/minix/devio.h
+mq.o:	/usr/include/minix/ioctl.h
+mq.o:	/usr/include/minix/ipc.h
+mq.o:	/usr/include/minix/sys_config.h
+mq.o:	/usr/include/minix/syslib.h
+mq.o:	/usr/include/minix/sysutil.h
+mq.o:	/usr/include/minix/type.h
+mq.o:	/usr/include/net/gen/arp_io.h
+mq.o:	/usr/include/net/gen/eth_hdr.h
+mq.o:	/usr/include/net/gen/eth_io.h
+mq.o:	/usr/include/net/gen/ether.h
+mq.o:	/usr/include/net/gen/icmp.h
+mq.o:	/usr/include/net/gen/icmp_hdr.h
+mq.o:	/usr/include/net/gen/in.h
+mq.o:	/usr/include/net/gen/ip_hdr.h
+mq.o:	/usr/include/net/gen/ip_io.h
+mq.o:	/usr/include/net/gen/oneCsum.h
+mq.o:	/usr/include/net/gen/psip_hdr.h
+mq.o:	/usr/include/net/gen/psip_io.h
+mq.o:	/usr/include/net/gen/route.h
+mq.o:	/usr/include/net/gen/tcp.h
+mq.o:	/usr/include/net/gen/tcp_hdr.h
+mq.o:	/usr/include/net/gen/tcp_io.h
+mq.o:	/usr/include/net/gen/udp.h
+mq.o:	/usr/include/net/gen/udp_hdr.h
+mq.o:	/usr/include/net/gen/udp_io.h
+mq.o:	/usr/include/net/hton.h
+mq.o:	/usr/include/net/ioctl.h
+mq.o:	/usr/include/stddef.h
+mq.o:	/usr/include/stdlib.h
+mq.o:	/usr/include/string.h
+mq.o:	/usr/include/sys/ioc_file.h
+mq.o:	/usr/include/sys/time.h
+mq.o:	/usr/include/sys/types.h
+mq.o:	/usr/include/unistd.h
+mq.o:	const.h
+mq.o:	generic/assert.h
+mq.o:	inet.h
+mq.o:	inet_config.h
+mq.o:	mq.c
+mq.o:	mq.h
+
+qp.o:	/usr/include/ansi.h
+qp.o:	/usr/include/errno.h
+qp.o:	/usr/include/minix/com.h
+qp.o:	/usr/include/minix/config.h
+qp.o:	/usr/include/minix/const.h
+qp.o:	/usr/include/minix/devio.h
+qp.o:	/usr/include/minix/dmap.h
+qp.o:	/usr/include/minix/ioctl.h
+qp.o:	/usr/include/minix/ipc.h
+qp.o:	/usr/include/minix/sys_config.h
+qp.o:	/usr/include/minix/syslib.h
+qp.o:	/usr/include/minix/sysutil.h
+qp.o:	/usr/include/minix/type.h
+qp.o:	/usr/include/net/gen/arp_io.h
+qp.o:	/usr/include/net/gen/eth_hdr.h
+qp.o:	/usr/include/net/gen/eth_io.h
+qp.o:	/usr/include/net/gen/ether.h
+qp.o:	/usr/include/net/gen/icmp.h
+qp.o:	/usr/include/net/gen/icmp_hdr.h
+qp.o:	/usr/include/net/gen/in.h
+qp.o:	/usr/include/net/gen/ip_hdr.h
+qp.o:	/usr/include/net/gen/ip_io.h
+qp.o:	/usr/include/net/gen/oneCsum.h
+qp.o:	/usr/include/net/gen/psip_hdr.h
+qp.o:	/usr/include/net/gen/psip_io.h
+qp.o:	/usr/include/net/gen/route.h
+qp.o:	/usr/include/net/gen/tcp.h
+qp.o:	/usr/include/net/gen/tcp_hdr.h
+qp.o:	/usr/include/net/gen/tcp_io.h
+qp.o:	/usr/include/net/gen/udp.h
+qp.o:	/usr/include/net/gen/udp_hdr.h
+qp.o:	/usr/include/net/gen/udp_io.h
+qp.o:	/usr/include/net/hton.h
+qp.o:	/usr/include/net/ioctl.h
+qp.o:	/usr/include/stddef.h
+qp.o:	/usr/include/stdlib.h
+qp.o:	/usr/include/string.h
+qp.o:	/usr/include/sys/ioc_file.h
+qp.o:	/usr/include/sys/svrctl.h
+qp.o:	/usr/include/sys/time.h
+qp.o:	/usr/include/sys/types.h
+qp.o:	/usr/include/unistd.h
+qp.o:	const.h
+qp.o:	generic/buf.h
+qp.o:	generic/clock.h
+qp.o:	generic/event.h
+qp.o:	generic/sr.h
+qp.o:	generic/tcp_int.h
+qp.o:	generic/type.h
+qp.o:	generic/udp_int.h
+qp.o:	inet.h
+qp.o:	inet_config.h
+qp.o:	minix3/queryparam.h
+qp.o:	mq.h
+qp.o:	qp.c
+qp.o:	qp.h
+qp.o:	sr_int.h
+
+sha2.o:	/usr/include/ansi.h
+sha2.o:	/usr/include/assert.h
+sha2.o:	/usr/include/minix/u64.h
+sha2.o:	/usr/include/string.h
+sha2.o:	/usr/include/sys/types.h
+sha2.o:	sha2.c
+sha2.o:	sha2.h
+
+sr.o:	/usr/include/ansi.h
+sr.o:	/usr/include/errno.h
+sr.o:	/usr/include/limits.h
+sr.o:	/usr/include/minix/callnr.h
+sr.o:	/usr/include/minix/com.h
+sr.o:	/usr/include/minix/config.h
+sr.o:	/usr/include/minix/const.h
+sr.o:	/usr/include/minix/devio.h
+sr.o:	/usr/include/minix/dmap.h
+sr.o:	/usr/include/minix/ioctl.h
+sr.o:	/usr/include/minix/ipc.h
+sr.o:	/usr/include/minix/sys_config.h
+sr.o:	/usr/include/minix/syslib.h
+sr.o:	/usr/include/minix/sysutil.h
+sr.o:	/usr/include/minix/type.h
+sr.o:	/usr/include/net/gen/arp_io.h
+sr.o:	/usr/include/net/gen/eth_hdr.h
+sr.o:	/usr/include/net/gen/eth_io.h
+sr.o:	/usr/include/net/gen/ether.h
+sr.o:	/usr/include/net/gen/icmp.h
+sr.o:	/usr/include/net/gen/icmp_hdr.h
+sr.o:	/usr/include/net/gen/in.h
+sr.o:	/usr/include/net/gen/ip_hdr.h
+sr.o:	/usr/include/net/gen/ip_io.h
+sr.o:	/usr/include/net/gen/oneCsum.h
+sr.o:	/usr/include/net/gen/psip_hdr.h
+sr.o:	/usr/include/net/gen/psip_io.h
+sr.o:	/usr/include/net/gen/route.h
+sr.o:	/usr/include/net/gen/tcp.h
+sr.o:	/usr/include/net/gen/tcp_hdr.h
+sr.o:	/usr/include/net/gen/tcp_io.h
+sr.o:	/usr/include/net/gen/udp.h
+sr.o:	/usr/include/net/gen/udp_hdr.h
+sr.o:	/usr/include/net/gen/udp_io.h
+sr.o:	/usr/include/net/hton.h
+sr.o:	/usr/include/net/ioctl.h
+sr.o:	/usr/include/stddef.h
+sr.o:	/usr/include/stdlib.h
+sr.o:	/usr/include/string.h
+sr.o:	/usr/include/sys/dir.h
+sr.o:	/usr/include/sys/ioc_file.h
+sr.o:	/usr/include/sys/select.h
+sr.o:	/usr/include/sys/svrctl.h
+sr.o:	/usr/include/sys/time.h
+sr.o:	/usr/include/sys/types.h
+sr.o:	/usr/include/unistd.h
+sr.o:	const.h
+sr.o:	generic/assert.h
+sr.o:	generic/buf.h
+sr.o:	generic/event.h
+sr.o:	generic/sr.h
+sr.o:	generic/type.h
+sr.o:	inet.h
+sr.o:	inet_config.h
+sr.o:	mq.h
+sr.o:	proto.h
+sr.o:	qp.h
+sr.o:	sr.c
+sr.o:	sr_int.h
+
+stacktrace.o:	/usr/include/ansi.h
+stacktrace.o:	/usr/include/errno.h
+stacktrace.o:	/usr/include/minix/com.h
+stacktrace.o:	/usr/include/minix/config.h
+stacktrace.o:	/usr/include/minix/const.h
+stacktrace.o:	/usr/include/minix/devio.h
+stacktrace.o:	/usr/include/minix/ioctl.h
+stacktrace.o:	/usr/include/minix/ipc.h
+stacktrace.o:	/usr/include/minix/sys_config.h
+stacktrace.o:	/usr/include/minix/syslib.h
+stacktrace.o:	/usr/include/minix/sysutil.h
+stacktrace.o:	/usr/include/minix/type.h
+stacktrace.o:	/usr/include/net/gen/arp_io.h
+stacktrace.o:	/usr/include/net/gen/eth_hdr.h
+stacktrace.o:	/usr/include/net/gen/eth_io.h
+stacktrace.o:	/usr/include/net/gen/ether.h
+stacktrace.o:	/usr/include/net/gen/icmp.h
+stacktrace.o:	/usr/include/net/gen/icmp_hdr.h
+stacktrace.o:	/usr/include/net/gen/in.h
+stacktrace.o:	/usr/include/net/gen/ip_hdr.h
+stacktrace.o:	/usr/include/net/gen/ip_io.h
+stacktrace.o:	/usr/include/net/gen/oneCsum.h
+stacktrace.o:	/usr/include/net/gen/psip_hdr.h
+stacktrace.o:	/usr/include/net/gen/psip_io.h
+stacktrace.o:	/usr/include/net/gen/route.h
+stacktrace.o:	/usr/include/net/gen/tcp.h
+stacktrace.o:	/usr/include/net/gen/tcp_hdr.h
+stacktrace.o:	/usr/include/net/gen/tcp_io.h
+stacktrace.o:	/usr/include/net/gen/udp.h
+stacktrace.o:	/usr/include/net/gen/udp_hdr.h
+stacktrace.o:	/usr/include/net/gen/udp_io.h
+stacktrace.o:	/usr/include/net/hton.h
+stacktrace.o:	/usr/include/net/ioctl.h
+stacktrace.o:	/usr/include/stddef.h
+stacktrace.o:	/usr/include/stdlib.h
+stacktrace.o:	/usr/include/string.h
+stacktrace.o:	/usr/include/sys/ioc_file.h
+stacktrace.o:	/usr/include/sys/time.h
+stacktrace.o:	/usr/include/sys/types.h
+stacktrace.o:	/usr/include/unistd.h
+stacktrace.o:	const.h
+stacktrace.o:	inet.h
+stacktrace.o:	inet_config.h
+stacktrace.o:	stacktrace.c
+
+version.o:	/usr/include/ansi.h
+version.o:	/usr/include/errno.h
+version.o:	/usr/include/minix/com.h
+version.o:	/usr/include/minix/config.h
+version.o:	/usr/include/minix/const.h
+version.o:	/usr/include/minix/devio.h
+version.o:	/usr/include/minix/ioctl.h
+version.o:	/usr/include/minix/ipc.h
+version.o:	/usr/include/minix/sys_config.h
+version.o:	/usr/include/minix/syslib.h
+version.o:	/usr/include/minix/sysutil.h
+version.o:	/usr/include/minix/type.h
+version.o:	/usr/include/net/gen/arp_io.h
+version.o:	/usr/include/net/gen/eth_hdr.h
+version.o:	/usr/include/net/gen/eth_io.h
+version.o:	/usr/include/net/gen/ether.h
+version.o:	/usr/include/net/gen/icmp.h
+version.o:	/usr/include/net/gen/icmp_hdr.h
+version.o:	/usr/include/net/gen/in.h
+version.o:	/usr/include/net/gen/ip_hdr.h
+version.o:	/usr/include/net/gen/ip_io.h
+version.o:	/usr/include/net/gen/oneCsum.h
+version.o:	/usr/include/net/gen/psip_hdr.h
+version.o:	/usr/include/net/gen/psip_io.h
+version.o:	/usr/include/net/gen/route.h
+version.o:	/usr/include/net/gen/tcp.h
+version.o:	/usr/include/net/gen/tcp_hdr.h
+version.o:	/usr/include/net/gen/tcp_io.h
+version.o:	/usr/include/net/gen/udp.h
+version.o:	/usr/include/net/gen/udp_hdr.h
+version.o:	/usr/include/net/gen/udp_io.h
+version.o:	/usr/include/net/hton.h
+version.o:	/usr/include/net/ioctl.h
+version.o:	/usr/include/stddef.h
+version.o:	/usr/include/stdlib.h
+version.o:	/usr/include/string.h
+version.o:	/usr/include/sys/ioc_file.h
+version.o:	/usr/include/sys/time.h
+version.o:	/usr/include/sys/types.h
+version.o:	/usr/include/unistd.h
+version.o:	const.h
+version.o:	inet.h
+version.o:	inet_config.h
+version.o:	version.c
+
+generic/arp.o:	/usr/include/ansi.h
+generic/arp.o:	/usr/include/errno.h
+generic/arp.o:	/usr/include/minix/com.h
+generic/arp.o:	/usr/include/minix/config.h
+generic/arp.o:	/usr/include/minix/const.h
+generic/arp.o:	/usr/include/minix/devio.h
+generic/arp.o:	/usr/include/minix/ioctl.h
+generic/arp.o:	/usr/include/minix/ipc.h
+generic/arp.o:	/usr/include/minix/sys_config.h
+generic/arp.o:	/usr/include/minix/syslib.h
+generic/arp.o:	/usr/include/minix/sysutil.h
+generic/arp.o:	/usr/include/minix/type.h
+generic/arp.o:	/usr/include/net/gen/arp_io.h
+generic/arp.o:	/usr/include/net/gen/eth_hdr.h
+generic/arp.o:	/usr/include/net/gen/eth_io.h
+generic/arp.o:	/usr/include/net/gen/ether.h
+generic/arp.o:	/usr/include/net/gen/icmp.h
+generic/arp.o:	/usr/include/net/gen/icmp_hdr.h
+generic/arp.o:	/usr/include/net/gen/in.h
+generic/arp.o:	/usr/include/net/gen/ip_hdr.h
+generic/arp.o:	/usr/include/net/gen/ip_io.h
+generic/arp.o:	/usr/include/net/gen/oneCsum.h
+generic/arp.o:	/usr/include/net/gen/psip_hdr.h
+generic/arp.o:	/usr/include/net/gen/psip_io.h
+generic/arp.o:	/usr/include/net/gen/route.h
+generic/arp.o:	/usr/include/net/gen/tcp.h
+generic/arp.o:	/usr/include/net/gen/tcp_hdr.h
+generic/arp.o:	/usr/include/net/gen/tcp_io.h
+generic/arp.o:	/usr/include/net/gen/udp.h
+generic/arp.o:	/usr/include/net/gen/udp_hdr.h
+generic/arp.o:	/usr/include/net/gen/udp_io.h
+generic/arp.o:	/usr/include/net/hton.h
+generic/arp.o:	/usr/include/net/ioctl.h
+generic/arp.o:	/usr/include/stddef.h
+generic/arp.o:	/usr/include/stdlib.h
+generic/arp.o:	/usr/include/string.h
+generic/arp.o:	/usr/include/sys/ioc_file.h
+generic/arp.o:	/usr/include/sys/time.h
+generic/arp.o:	/usr/include/sys/types.h
+generic/arp.o:	/usr/include/unistd.h
+generic/arp.o:	const.h
+generic/arp.o:	generic/arp.c
+generic/arp.o:	generic/arp.h
+generic/arp.o:	generic/assert.h
+generic/arp.o:	generic/buf.h
+generic/arp.o:	generic/clock.h
+generic/arp.o:	generic/eth.h
+generic/arp.o:	generic/event.h
+generic/arp.o:	generic/io.h
+generic/arp.o:	generic/sr.h
+generic/arp.o:	generic/type.h
+generic/arp.o:	inet.h
+generic/arp.o:	inet_config.h
+
+generic/eth.o:	/usr/include/ansi.h
+generic/eth.o:	/usr/include/errno.h
+generic/eth.o:	/usr/include/minix/com.h
+generic/eth.o:	/usr/include/minix/config.h
+generic/eth.o:	/usr/include/minix/const.h
+generic/eth.o:	/usr/include/minix/devio.h
+generic/eth.o:	/usr/include/minix/ioctl.h
+generic/eth.o:	/usr/include/minix/ipc.h
+generic/eth.o:	/usr/include/minix/sys_config.h
+generic/eth.o:	/usr/include/minix/syslib.h
+generic/eth.o:	/usr/include/minix/sysutil.h
+generic/eth.o:	/usr/include/minix/type.h
+generic/eth.o:	/usr/include/net/gen/arp_io.h
+generic/eth.o:	/usr/include/net/gen/eth_hdr.h
+generic/eth.o:	/usr/include/net/gen/eth_io.h
+generic/eth.o:	/usr/include/net/gen/ether.h
+generic/eth.o:	/usr/include/net/gen/icmp.h
+generic/eth.o:	/usr/include/net/gen/icmp_hdr.h
+generic/eth.o:	/usr/include/net/gen/in.h
+generic/eth.o:	/usr/include/net/gen/ip_hdr.h
+generic/eth.o:	/usr/include/net/gen/ip_io.h
+generic/eth.o:	/usr/include/net/gen/oneCsum.h
+generic/eth.o:	/usr/include/net/gen/psip_hdr.h
+generic/eth.o:	/usr/include/net/gen/psip_io.h
+generic/eth.o:	/usr/include/net/gen/route.h
+generic/eth.o:	/usr/include/net/gen/tcp.h
+generic/eth.o:	/usr/include/net/gen/tcp_hdr.h
+generic/eth.o:	/usr/include/net/gen/tcp_io.h
+generic/eth.o:	/usr/include/net/gen/udp.h
+generic/eth.o:	/usr/include/net/gen/udp_hdr.h
+generic/eth.o:	/usr/include/net/gen/udp_io.h
+generic/eth.o:	/usr/include/net/hton.h
+generic/eth.o:	/usr/include/net/ioctl.h
+generic/eth.o:	/usr/include/stddef.h
+generic/eth.o:	/usr/include/stdlib.h
+generic/eth.o:	/usr/include/string.h
+generic/eth.o:	/usr/include/sys/ioc_file.h
+generic/eth.o:	/usr/include/sys/time.h
+generic/eth.o:	/usr/include/sys/types.h
+generic/eth.o:	/usr/include/unistd.h
+generic/eth.o:	const.h
+generic/eth.o:	generic/assert.h
+generic/eth.o:	generic/buf.h
+generic/eth.o:	generic/clock.h
+generic/eth.o:	generic/eth.c
+generic/eth.o:	generic/eth.h
+generic/eth.o:	generic/eth_int.h
+generic/eth.o:	generic/event.h
+generic/eth.o:	generic/io.h
+generic/eth.o:	generic/sr.h
+generic/eth.o:	generic/type.h
+generic/eth.o:	inet.h
+generic/eth.o:	inet_config.h
+generic/eth.o:	osdep_eth.h
+
+generic/event.o:	/usr/include/ansi.h
+generic/event.o:	/usr/include/errno.h
+generic/event.o:	/usr/include/minix/com.h
+generic/event.o:	/usr/include/minix/config.h
+generic/event.o:	/usr/include/minix/const.h
+generic/event.o:	/usr/include/minix/devio.h
+generic/event.o:	/usr/include/minix/ioctl.h
+generic/event.o:	/usr/include/minix/ipc.h
+generic/event.o:	/usr/include/minix/sys_config.h
+generic/event.o:	/usr/include/minix/syslib.h
+generic/event.o:	/usr/include/minix/sysutil.h
+generic/event.o:	/usr/include/minix/type.h
+generic/event.o:	/usr/include/net/gen/arp_io.h
+generic/event.o:	/usr/include/net/gen/eth_hdr.h
+generic/event.o:	/usr/include/net/gen/eth_io.h
+generic/event.o:	/usr/include/net/gen/ether.h
+generic/event.o:	/usr/include/net/gen/icmp.h
+generic/event.o:	/usr/include/net/gen/icmp_hdr.h
+generic/event.o:	/usr/include/net/gen/in.h
+generic/event.o:	/usr/include/net/gen/ip_hdr.h
+generic/event.o:	/usr/include/net/gen/ip_io.h
+generic/event.o:	/usr/include/net/gen/oneCsum.h
+generic/event.o:	/usr/include/net/gen/psip_hdr.h
+generic/event.o:	/usr/include/net/gen/psip_io.h
+generic/event.o:	/usr/include/net/gen/route.h
+generic/event.o:	/usr/include/net/gen/tcp.h
+generic/event.o:	/usr/include/net/gen/tcp_hdr.h
+generic/event.o:	/usr/include/net/gen/tcp_io.h
+generic/event.o:	/usr/include/net/gen/udp.h
+generic/event.o:	/usr/include/net/gen/udp_hdr.h
+generic/event.o:	/usr/include/net/gen/udp_io.h
+generic/event.o:	/usr/include/net/hton.h
+generic/event.o:	/usr/include/net/ioctl.h
+generic/event.o:	/usr/include/stddef.h
+generic/event.o:	/usr/include/stdlib.h
+generic/event.o:	/usr/include/string.h
+generic/event.o:	/usr/include/sys/ioc_file.h
+generic/event.o:	/usr/include/sys/time.h
+generic/event.o:	/usr/include/sys/types.h
+generic/event.o:	/usr/include/unistd.h
+generic/event.o:	const.h
+generic/event.o:	generic/assert.h
+generic/event.o:	generic/event.c
+generic/event.o:	generic/event.h
+generic/event.o:	inet.h
+generic/event.o:	inet_config.h
+
+generic/icmp.o:	/usr/include/ansi.h
+generic/icmp.o:	/usr/include/errno.h
+generic/icmp.o:	/usr/include/minix/com.h
+generic/icmp.o:	/usr/include/minix/config.h
+generic/icmp.o:	/usr/include/minix/const.h
+generic/icmp.o:	/usr/include/minix/devio.h
+generic/icmp.o:	/usr/include/minix/ioctl.h
+generic/icmp.o:	/usr/include/minix/ipc.h
+generic/icmp.o:	/usr/include/minix/sys_config.h
+generic/icmp.o:	/usr/include/minix/syslib.h
+generic/icmp.o:	/usr/include/minix/sysutil.h
+generic/icmp.o:	/usr/include/minix/type.h
+generic/icmp.o:	/usr/include/net/gen/arp_io.h
+generic/icmp.o:	/usr/include/net/gen/eth_hdr.h
+generic/icmp.o:	/usr/include/net/gen/eth_io.h
+generic/icmp.o:	/usr/include/net/gen/ether.h
+generic/icmp.o:	/usr/include/net/gen/icmp.h
+generic/icmp.o:	/usr/include/net/gen/icmp_hdr.h
+generic/icmp.o:	/usr/include/net/gen/in.h
+generic/icmp.o:	/usr/include/net/gen/ip_hdr.h
+generic/icmp.o:	/usr/include/net/gen/ip_io.h
+generic/icmp.o:	/usr/include/net/gen/oneCsum.h
+generic/icmp.o:	/usr/include/net/gen/psip_hdr.h
+generic/icmp.o:	/usr/include/net/gen/psip_io.h
+generic/icmp.o:	/usr/include/net/gen/route.h
+generic/icmp.o:	/usr/include/net/gen/tcp.h
+generic/icmp.o:	/usr/include/net/gen/tcp_hdr.h
+generic/icmp.o:	/usr/include/net/gen/tcp_io.h
+generic/icmp.o:	/usr/include/net/gen/udp.h
+generic/icmp.o:	/usr/include/net/gen/udp_hdr.h
+generic/icmp.o:	/usr/include/net/gen/udp_io.h
+generic/icmp.o:	/usr/include/net/hton.h
+generic/icmp.o:	/usr/include/net/ioctl.h
+generic/icmp.o:	/usr/include/stddef.h
+generic/icmp.o:	/usr/include/stdlib.h
+generic/icmp.o:	/usr/include/string.h
+generic/icmp.o:	/usr/include/sys/ioc_file.h
+generic/icmp.o:	/usr/include/sys/time.h
+generic/icmp.o:	/usr/include/sys/types.h
+generic/icmp.o:	/usr/include/unistd.h
+generic/icmp.o:	const.h
+generic/icmp.o:	generic/assert.h
+generic/icmp.o:	generic/buf.h
+generic/icmp.o:	generic/clock.h
+generic/icmp.o:	generic/event.h
+generic/icmp.o:	generic/icmp.c
+generic/icmp.o:	generic/icmp.h
+generic/icmp.o:	generic/icmp_lib.h
+generic/icmp.o:	generic/io.h
+generic/icmp.o:	generic/ip.h
+generic/icmp.o:	generic/ip_int.h
+generic/icmp.o:	generic/ipr.h
+generic/icmp.o:	generic/type.h
+generic/icmp.o:	inet.h
+generic/icmp.o:	inet_config.h
+
+generic/io.o:	/usr/include/ansi.h
+generic/io.o:	/usr/include/errno.h
+generic/io.o:	/usr/include/minix/com.h
+generic/io.o:	/usr/include/minix/config.h
+generic/io.o:	/usr/include/minix/const.h
+generic/io.o:	/usr/include/minix/devio.h
+generic/io.o:	/usr/include/minix/ioctl.h
+generic/io.o:	/usr/include/minix/ipc.h
+generic/io.o:	/usr/include/minix/sys_config.h
+generic/io.o:	/usr/include/minix/syslib.h
+generic/io.o:	/usr/include/minix/sysutil.h
+generic/io.o:	/usr/include/minix/type.h
+generic/io.o:	/usr/include/net/gen/arp_io.h
+generic/io.o:	/usr/include/net/gen/eth_hdr.h
+generic/io.o:	/usr/include/net/gen/eth_io.h
+generic/io.o:	/usr/include/net/gen/ether.h
+generic/io.o:	/usr/include/net/gen/icmp.h
+generic/io.o:	/usr/include/net/gen/icmp_hdr.h
+generic/io.o:	/usr/include/net/gen/in.h
+generic/io.o:	/usr/include/net/gen/ip_hdr.h
+generic/io.o:	/usr/include/net/gen/ip_io.h
+generic/io.o:	/usr/include/net/gen/oneCsum.h
+generic/io.o:	/usr/include/net/gen/psip_hdr.h
+generic/io.o:	/usr/include/net/gen/psip_io.h
+generic/io.o:	/usr/include/net/gen/route.h
+generic/io.o:	/usr/include/net/gen/tcp.h
+generic/io.o:	/usr/include/net/gen/tcp_hdr.h
+generic/io.o:	/usr/include/net/gen/tcp_io.h
+generic/io.o:	/usr/include/net/gen/udp.h
+generic/io.o:	/usr/include/net/gen/udp_hdr.h
+generic/io.o:	/usr/include/net/gen/udp_io.h
+generic/io.o:	/usr/include/net/hton.h
+generic/io.o:	/usr/include/net/ioctl.h
+generic/io.o:	/usr/include/stddef.h
+generic/io.o:	/usr/include/stdlib.h
+generic/io.o:	/usr/include/string.h
+generic/io.o:	/usr/include/sys/ioc_file.h
+generic/io.o:	/usr/include/sys/time.h
+generic/io.o:	/usr/include/sys/types.h
+generic/io.o:	/usr/include/unistd.h
+generic/io.o:	const.h
+generic/io.o:	generic/io.c
+generic/io.o:	generic/io.h
+generic/io.o:	inet.h
+generic/io.o:	inet_config.h
+
+generic/ip.o:	/usr/include/ansi.h
+generic/ip.o:	/usr/include/errno.h
+generic/ip.o:	/usr/include/minix/com.h
+generic/ip.o:	/usr/include/minix/config.h
+generic/ip.o:	/usr/include/minix/const.h
+generic/ip.o:	/usr/include/minix/devio.h
+generic/ip.o:	/usr/include/minix/ioctl.h
+generic/ip.o:	/usr/include/minix/ipc.h
+generic/ip.o:	/usr/include/minix/sys_config.h
+generic/ip.o:	/usr/include/minix/syslib.h
+generic/ip.o:	/usr/include/minix/sysutil.h
+generic/ip.o:	/usr/include/minix/type.h
+generic/ip.o:	/usr/include/net/gen/arp_io.h
+generic/ip.o:	/usr/include/net/gen/eth_hdr.h
+generic/ip.o:	/usr/include/net/gen/eth_io.h
+generic/ip.o:	/usr/include/net/gen/ether.h
+generic/ip.o:	/usr/include/net/gen/icmp.h
+generic/ip.o:	/usr/include/net/gen/icmp_hdr.h
+generic/ip.o:	/usr/include/net/gen/in.h
+generic/ip.o:	/usr/include/net/gen/ip_hdr.h
+generic/ip.o:	/usr/include/net/gen/ip_io.h
+generic/ip.o:	/usr/include/net/gen/oneCsum.h
+generic/ip.o:	/usr/include/net/gen/psip_hdr.h
+generic/ip.o:	/usr/include/net/gen/psip_io.h
+generic/ip.o:	/usr/include/net/gen/route.h
+generic/ip.o:	/usr/include/net/gen/tcp.h
+generic/ip.o:	/usr/include/net/gen/tcp_hdr.h
+generic/ip.o:	/usr/include/net/gen/tcp_io.h
+generic/ip.o:	/usr/include/net/gen/udp.h
+generic/ip.o:	/usr/include/net/gen/udp_hdr.h
+generic/ip.o:	/usr/include/net/gen/udp_io.h
+generic/ip.o:	/usr/include/net/hton.h
+generic/ip.o:	/usr/include/net/ioctl.h
+generic/ip.o:	/usr/include/stddef.h
+generic/ip.o:	/usr/include/stdlib.h
+generic/ip.o:	/usr/include/string.h
+generic/ip.o:	/usr/include/sys/ioc_file.h
+generic/ip.o:	/usr/include/sys/time.h
+generic/ip.o:	/usr/include/sys/types.h
+generic/ip.o:	/usr/include/unistd.h
+generic/ip.o:	const.h
+generic/ip.o:	generic/arp.h
+generic/ip.o:	generic/assert.h
+generic/ip.o:	generic/buf.h
+generic/ip.o:	generic/clock.h
+generic/ip.o:	generic/eth.h
+generic/ip.o:	generic/event.h
+generic/ip.o:	generic/icmp.h
+generic/ip.o:	generic/icmp_lib.h
+generic/ip.o:	generic/io.h
+generic/ip.o:	generic/ip.c
+generic/ip.o:	generic/ip.h
+generic/ip.o:	generic/ip_int.h
+generic/ip.o:	generic/ipr.h
+generic/ip.o:	generic/sr.h
+generic/ip.o:	generic/type.h
+generic/ip.o:	inet.h
+generic/ip.o:	inet_config.h
+
+generic/ip_eth.o:	/usr/include/ansi.h
+generic/ip_eth.o:	/usr/include/errno.h
+generic/ip_eth.o:	/usr/include/minix/com.h
+generic/ip_eth.o:	/usr/include/minix/config.h
+generic/ip_eth.o:	/usr/include/minix/const.h
+generic/ip_eth.o:	/usr/include/minix/devio.h
+generic/ip_eth.o:	/usr/include/minix/ioctl.h
+generic/ip_eth.o:	/usr/include/minix/ipc.h
+generic/ip_eth.o:	/usr/include/minix/sys_config.h
+generic/ip_eth.o:	/usr/include/minix/syslib.h
+generic/ip_eth.o:	/usr/include/minix/sysutil.h
+generic/ip_eth.o:	/usr/include/minix/type.h
+generic/ip_eth.o:	/usr/include/net/gen/arp_io.h
+generic/ip_eth.o:	/usr/include/net/gen/eth_hdr.h
+generic/ip_eth.o:	/usr/include/net/gen/eth_io.h
+generic/ip_eth.o:	/usr/include/net/gen/ether.h
+generic/ip_eth.o:	/usr/include/net/gen/icmp.h
+generic/ip_eth.o:	/usr/include/net/gen/icmp_hdr.h
+generic/ip_eth.o:	/usr/include/net/gen/in.h
+generic/ip_eth.o:	/usr/include/net/gen/ip_hdr.h
+generic/ip_eth.o:	/usr/include/net/gen/ip_io.h
+generic/ip_eth.o:	/usr/include/net/gen/oneCsum.h
+generic/ip_eth.o:	/usr/include/net/gen/psip_hdr.h
+generic/ip_eth.o:	/usr/include/net/gen/psip_io.h
+generic/ip_eth.o:	/usr/include/net/gen/route.h
+generic/ip_eth.o:	/usr/include/net/gen/tcp.h
+generic/ip_eth.o:	/usr/include/net/gen/tcp_hdr.h
+generic/ip_eth.o:	/usr/include/net/gen/tcp_io.h
+generic/ip_eth.o:	/usr/include/net/gen/udp.h
+generic/ip_eth.o:	/usr/include/net/gen/udp_hdr.h
+generic/ip_eth.o:	/usr/include/net/gen/udp_io.h
+generic/ip_eth.o:	/usr/include/net/hton.h
+generic/ip_eth.o:	/usr/include/net/ioctl.h
+generic/ip_eth.o:	/usr/include/stddef.h
+generic/ip_eth.o:	/usr/include/stdlib.h
+generic/ip_eth.o:	/usr/include/string.h
+generic/ip_eth.o:	/usr/include/sys/ioc_file.h
+generic/ip_eth.o:	/usr/include/sys/time.h
+generic/ip_eth.o:	/usr/include/sys/types.h
+generic/ip_eth.o:	/usr/include/unistd.h
+generic/ip_eth.o:	const.h
+generic/ip_eth.o:	generic/arp.h
+generic/ip_eth.o:	generic/assert.h
+generic/ip_eth.o:	generic/buf.h
+generic/ip_eth.o:	generic/clock.h
+generic/ip_eth.o:	generic/eth.h
+generic/ip_eth.o:	generic/event.h
+generic/ip_eth.o:	generic/icmp_lib.h
+generic/ip_eth.o:	generic/io.h
+generic/ip_eth.o:	generic/ip.h
+generic/ip_eth.o:	generic/ip_eth.c
+generic/ip_eth.o:	generic/ip_int.h
+generic/ip_eth.o:	generic/type.h
+generic/ip_eth.o:	inet.h
+generic/ip_eth.o:	inet_config.h
+
+generic/ip_ioctl.o:	/usr/include/ansi.h
+generic/ip_ioctl.o:	/usr/include/errno.h
+generic/ip_ioctl.o:	/usr/include/minix/com.h
+generic/ip_ioctl.o:	/usr/include/minix/config.h
+generic/ip_ioctl.o:	/usr/include/minix/const.h
+generic/ip_ioctl.o:	/usr/include/minix/devio.h
+generic/ip_ioctl.o:	/usr/include/minix/ioctl.h
+generic/ip_ioctl.o:	/usr/include/minix/ipc.h
+generic/ip_ioctl.o:	/usr/include/minix/sys_config.h
+generic/ip_ioctl.o:	/usr/include/minix/syslib.h
+generic/ip_ioctl.o:	/usr/include/minix/sysutil.h
+generic/ip_ioctl.o:	/usr/include/minix/type.h
+generic/ip_ioctl.o:	/usr/include/net/gen/arp_io.h
+generic/ip_ioctl.o:	/usr/include/net/gen/eth_hdr.h
+generic/ip_ioctl.o:	/usr/include/net/gen/eth_io.h
+generic/ip_ioctl.o:	/usr/include/net/gen/ether.h
+generic/ip_ioctl.o:	/usr/include/net/gen/icmp.h
+generic/ip_ioctl.o:	/usr/include/net/gen/icmp_hdr.h
+generic/ip_ioctl.o:	/usr/include/net/gen/in.h
+generic/ip_ioctl.o:	/usr/include/net/gen/ip_hdr.h
+generic/ip_ioctl.o:	/usr/include/net/gen/ip_io.h
+generic/ip_ioctl.o:	/usr/include/net/gen/oneCsum.h
+generic/ip_ioctl.o:	/usr/include/net/gen/psip_hdr.h
+generic/ip_ioctl.o:	/usr/include/net/gen/psip_io.h
+generic/ip_ioctl.o:	/usr/include/net/gen/route.h
+generic/ip_ioctl.o:	/usr/include/net/gen/tcp.h
+generic/ip_ioctl.o:	/usr/include/net/gen/tcp_hdr.h
+generic/ip_ioctl.o:	/usr/include/net/gen/tcp_io.h
+generic/ip_ioctl.o:	/usr/include/net/gen/udp.h
+generic/ip_ioctl.o:	/usr/include/net/gen/udp_hdr.h
+generic/ip_ioctl.o:	/usr/include/net/gen/udp_io.h
+generic/ip_ioctl.o:	/usr/include/net/hton.h
+generic/ip_ioctl.o:	/usr/include/net/ioctl.h
+generic/ip_ioctl.o:	/usr/include/stddef.h
+generic/ip_ioctl.o:	/usr/include/stdlib.h
+generic/ip_ioctl.o:	/usr/include/string.h
+generic/ip_ioctl.o:	/usr/include/sys/ioc_file.h
+generic/ip_ioctl.o:	/usr/include/sys/time.h
+generic/ip_ioctl.o:	/usr/include/sys/types.h
+generic/ip_ioctl.o:	/usr/include/unistd.h
+generic/ip_ioctl.o:	const.h
+generic/ip_ioctl.o:	generic/arp.h
+generic/ip_ioctl.o:	generic/assert.h
+generic/ip_ioctl.o:	generic/buf.h
+generic/ip_ioctl.o:	generic/clock.h
+generic/ip_ioctl.o:	generic/event.h
+generic/ip_ioctl.o:	generic/icmp_lib.h
+generic/ip_ioctl.o:	generic/ip.h
+generic/ip_ioctl.o:	generic/ip_int.h
+generic/ip_ioctl.o:	generic/ip_ioctl.c
+generic/ip_ioctl.o:	generic/ipr.h
+generic/ip_ioctl.o:	generic/type.h
+generic/ip_ioctl.o:	inet.h
+generic/ip_ioctl.o:	inet_config.h
+
+generic/ip_lib.o:	/usr/include/ansi.h
+generic/ip_lib.o:	/usr/include/errno.h
+generic/ip_lib.o:	/usr/include/minix/com.h
+generic/ip_lib.o:	/usr/include/minix/config.h
+generic/ip_lib.o:	/usr/include/minix/const.h
+generic/ip_lib.o:	/usr/include/minix/devio.h
+generic/ip_lib.o:	/usr/include/minix/ioctl.h
+generic/ip_lib.o:	/usr/include/minix/ipc.h
+generic/ip_lib.o:	/usr/include/minix/sys_config.h
+generic/ip_lib.o:	/usr/include/minix/syslib.h
+generic/ip_lib.o:	/usr/include/minix/sysutil.h
+generic/ip_lib.o:	/usr/include/minix/type.h
+generic/ip_lib.o:	/usr/include/net/gen/arp_io.h
+generic/ip_lib.o:	/usr/include/net/gen/eth_hdr.h
+generic/ip_lib.o:	/usr/include/net/gen/eth_io.h
+generic/ip_lib.o:	/usr/include/net/gen/ether.h
+generic/ip_lib.o:	/usr/include/net/gen/icmp.h
+generic/ip_lib.o:	/usr/include/net/gen/icmp_hdr.h
+generic/ip_lib.o:	/usr/include/net/gen/in.h
+generic/ip_lib.o:	/usr/include/net/gen/ip_hdr.h
+generic/ip_lib.o:	/usr/include/net/gen/ip_io.h
+generic/ip_lib.o:	/usr/include/net/gen/oneCsum.h
+generic/ip_lib.o:	/usr/include/net/gen/psip_hdr.h
+generic/ip_lib.o:	/usr/include/net/gen/psip_io.h
+generic/ip_lib.o:	/usr/include/net/gen/route.h
+generic/ip_lib.o:	/usr/include/net/gen/tcp.h
+generic/ip_lib.o:	/usr/include/net/gen/tcp_hdr.h
+generic/ip_lib.o:	/usr/include/net/gen/tcp_io.h
+generic/ip_lib.o:	/usr/include/net/gen/udp.h
+generic/ip_lib.o:	/usr/include/net/gen/udp_hdr.h
+generic/ip_lib.o:	/usr/include/net/gen/udp_io.h
+generic/ip_lib.o:	/usr/include/net/hton.h
+generic/ip_lib.o:	/usr/include/net/ioctl.h
+generic/ip_lib.o:	/usr/include/stddef.h
+generic/ip_lib.o:	/usr/include/stdlib.h
+generic/ip_lib.o:	/usr/include/string.h
+generic/ip_lib.o:	/usr/include/sys/ioc_file.h
+generic/ip_lib.o:	/usr/include/sys/time.h
+generic/ip_lib.o:	/usr/include/sys/types.h
+generic/ip_lib.o:	/usr/include/unistd.h
+generic/ip_lib.o:	const.h
+generic/ip_lib.o:	generic/assert.h
+generic/ip_lib.o:	generic/buf.h
+generic/ip_lib.o:	generic/event.h
+generic/ip_lib.o:	generic/io.h
+generic/ip_lib.o:	generic/ip_int.h
+generic/ip_lib.o:	generic/ip_lib.c
+generic/ip_lib.o:	generic/type.h
+generic/ip_lib.o:	inet.h
+generic/ip_lib.o:	inet_config.h
+
+generic/ip_ps.o:	/usr/include/ansi.h
+generic/ip_ps.o:	/usr/include/errno.h
+generic/ip_ps.o:	/usr/include/minix/com.h
+generic/ip_ps.o:	/usr/include/minix/config.h
+generic/ip_ps.o:	/usr/include/minix/const.h
+generic/ip_ps.o:	/usr/include/minix/devio.h
+generic/ip_ps.o:	/usr/include/minix/ioctl.h
+generic/ip_ps.o:	/usr/include/minix/ipc.h
+generic/ip_ps.o:	/usr/include/minix/sys_config.h
+generic/ip_ps.o:	/usr/include/minix/syslib.h
+generic/ip_ps.o:	/usr/include/minix/sysutil.h
+generic/ip_ps.o:	/usr/include/minix/type.h
+generic/ip_ps.o:	/usr/include/net/gen/arp_io.h
+generic/ip_ps.o:	/usr/include/net/gen/eth_hdr.h
+generic/ip_ps.o:	/usr/include/net/gen/eth_io.h
+generic/ip_ps.o:	/usr/include/net/gen/ether.h
+generic/ip_ps.o:	/usr/include/net/gen/icmp.h
+generic/ip_ps.o:	/usr/include/net/gen/icmp_hdr.h
+generic/ip_ps.o:	/usr/include/net/gen/in.h
+generic/ip_ps.o:	/usr/include/net/gen/ip_hdr.h
+generic/ip_ps.o:	/usr/include/net/gen/ip_io.h
+generic/ip_ps.o:	/usr/include/net/gen/oneCsum.h
+generic/ip_ps.o:	/usr/include/net/gen/psip_hdr.h
+generic/ip_ps.o:	/usr/include/net/gen/psip_io.h
+generic/ip_ps.o:	/usr/include/net/gen/route.h
+generic/ip_ps.o:	/usr/include/net/gen/tcp.h
+generic/ip_ps.o:	/usr/include/net/gen/tcp_hdr.h
+generic/ip_ps.o:	/usr/include/net/gen/tcp_io.h
+generic/ip_ps.o:	/usr/include/net/gen/udp.h
+generic/ip_ps.o:	/usr/include/net/gen/udp_hdr.h
+generic/ip_ps.o:	/usr/include/net/gen/udp_io.h
+generic/ip_ps.o:	/usr/include/net/hton.h
+generic/ip_ps.o:	/usr/include/net/ioctl.h
+generic/ip_ps.o:	/usr/include/stddef.h
+generic/ip_ps.o:	/usr/include/stdlib.h
+generic/ip_ps.o:	/usr/include/string.h
+generic/ip_ps.o:	/usr/include/sys/ioc_file.h
+generic/ip_ps.o:	/usr/include/sys/time.h
+generic/ip_ps.o:	/usr/include/sys/types.h
+generic/ip_ps.o:	/usr/include/unistd.h
+generic/ip_ps.o:	const.h
+generic/ip_ps.o:	generic/assert.h
+generic/ip_ps.o:	generic/buf.h
+generic/ip_ps.o:	generic/event.h
+generic/ip_ps.o:	generic/ip.h
+generic/ip_ps.o:	generic/ip_int.h
+generic/ip_ps.o:	generic/ip_ps.c
+generic/ip_ps.o:	generic/psip.h
+generic/ip_ps.o:	generic/type.h
+generic/ip_ps.o:	inet.h
+generic/ip_ps.o:	inet_config.h
+
+generic/ip_read.o:	/usr/include/ansi.h
+generic/ip_read.o:	/usr/include/errno.h
+generic/ip_read.o:	/usr/include/minix/com.h
+generic/ip_read.o:	/usr/include/minix/config.h
+generic/ip_read.o:	/usr/include/minix/const.h
+generic/ip_read.o:	/usr/include/minix/devio.h
+generic/ip_read.o:	/usr/include/minix/ioctl.h
+generic/ip_read.o:	/usr/include/minix/ipc.h
+generic/ip_read.o:	/usr/include/minix/sys_config.h
+generic/ip_read.o:	/usr/include/minix/syslib.h
+generic/ip_read.o:	/usr/include/minix/sysutil.h
+generic/ip_read.o:	/usr/include/minix/type.h
+generic/ip_read.o:	/usr/include/net/gen/arp_io.h
+generic/ip_read.o:	/usr/include/net/gen/eth_hdr.h
+generic/ip_read.o:	/usr/include/net/gen/eth_io.h
+generic/ip_read.o:	/usr/include/net/gen/ether.h
+generic/ip_read.o:	/usr/include/net/gen/icmp.h
+generic/ip_read.o:	/usr/include/net/gen/icmp_hdr.h
+generic/ip_read.o:	/usr/include/net/gen/in.h
+generic/ip_read.o:	/usr/include/net/gen/ip_hdr.h
+generic/ip_read.o:	/usr/include/net/gen/ip_io.h
+generic/ip_read.o:	/usr/include/net/gen/oneCsum.h
+generic/ip_read.o:	/usr/include/net/gen/psip_hdr.h
+generic/ip_read.o:	/usr/include/net/gen/psip_io.h
+generic/ip_read.o:	/usr/include/net/gen/route.h
+generic/ip_read.o:	/usr/include/net/gen/tcp.h
+generic/ip_read.o:	/usr/include/net/gen/tcp_hdr.h
+generic/ip_read.o:	/usr/include/net/gen/tcp_io.h
+generic/ip_read.o:	/usr/include/net/gen/udp.h
+generic/ip_read.o:	/usr/include/net/gen/udp_hdr.h
+generic/ip_read.o:	/usr/include/net/gen/udp_io.h
+generic/ip_read.o:	/usr/include/net/hton.h
+generic/ip_read.o:	/usr/include/net/ioctl.h
+generic/ip_read.o:	/usr/include/stddef.h
+generic/ip_read.o:	/usr/include/stdlib.h
+generic/ip_read.o:	/usr/include/string.h
+generic/ip_read.o:	/usr/include/sys/ioc_file.h
+generic/ip_read.o:	/usr/include/sys/time.h
+generic/ip_read.o:	/usr/include/sys/types.h
+generic/ip_read.o:	/usr/include/unistd.h
+generic/ip_read.o:	const.h
+generic/ip_read.o:	generic/assert.h
+generic/ip_read.o:	generic/buf.h
+generic/ip_read.o:	generic/clock.h
+generic/ip_read.o:	generic/event.h
+generic/ip_read.o:	generic/icmp_lib.h
+generic/ip_read.o:	generic/io.h
+generic/ip_read.o:	generic/ip.h
+generic/ip_read.o:	generic/ip_int.h
+generic/ip_read.o:	generic/ip_read.c
+generic/ip_read.o:	generic/ipr.h
+generic/ip_read.o:	generic/type.h
+generic/ip_read.o:	inet.h
+generic/ip_read.o:	inet_config.h
+
+generic/ip_write.o:	/usr/include/ansi.h
+generic/ip_write.o:	/usr/include/errno.h
+generic/ip_write.o:	/usr/include/minix/com.h
+generic/ip_write.o:	/usr/include/minix/config.h
+generic/ip_write.o:	/usr/include/minix/const.h
+generic/ip_write.o:	/usr/include/minix/devio.h
+generic/ip_write.o:	/usr/include/minix/ioctl.h
+generic/ip_write.o:	/usr/include/minix/ipc.h
+generic/ip_write.o:	/usr/include/minix/sys_config.h
+generic/ip_write.o:	/usr/include/minix/syslib.h
+generic/ip_write.o:	/usr/include/minix/sysutil.h
+generic/ip_write.o:	/usr/include/minix/type.h
+generic/ip_write.o:	/usr/include/net/gen/arp_io.h
+generic/ip_write.o:	/usr/include/net/gen/eth_hdr.h
+generic/ip_write.o:	/usr/include/net/gen/eth_io.h
+generic/ip_write.o:	/usr/include/net/gen/ether.h
+generic/ip_write.o:	/usr/include/net/gen/icmp.h
+generic/ip_write.o:	/usr/include/net/gen/icmp_hdr.h
+generic/ip_write.o:	/usr/include/net/gen/in.h
+generic/ip_write.o:	/usr/include/net/gen/ip_hdr.h
+generic/ip_write.o:	/usr/include/net/gen/ip_io.h
+generic/ip_write.o:	/usr/include/net/gen/oneCsum.h
+generic/ip_write.o:	/usr/include/net/gen/psip_hdr.h
+generic/ip_write.o:	/usr/include/net/gen/psip_io.h
+generic/ip_write.o:	/usr/include/net/gen/route.h
+generic/ip_write.o:	/usr/include/net/gen/tcp.h
+generic/ip_write.o:	/usr/include/net/gen/tcp_hdr.h
+generic/ip_write.o:	/usr/include/net/gen/tcp_io.h
+generic/ip_write.o:	/usr/include/net/gen/udp.h
+generic/ip_write.o:	/usr/include/net/gen/udp_hdr.h
+generic/ip_write.o:	/usr/include/net/gen/udp_io.h
+generic/ip_write.o:	/usr/include/net/hton.h
+generic/ip_write.o:	/usr/include/net/ioctl.h
+generic/ip_write.o:	/usr/include/stddef.h
+generic/ip_write.o:	/usr/include/stdlib.h
+generic/ip_write.o:	/usr/include/string.h
+generic/ip_write.o:	/usr/include/sys/ioc_file.h
+generic/ip_write.o:	/usr/include/sys/time.h
+generic/ip_write.o:	/usr/include/sys/types.h
+generic/ip_write.o:	/usr/include/unistd.h
+generic/ip_write.o:	const.h
+generic/ip_write.o:	generic/arp.h
+generic/ip_write.o:	generic/assert.h
+generic/ip_write.o:	generic/buf.h
+generic/ip_write.o:	generic/clock.h
+generic/ip_write.o:	generic/eth.h
+generic/ip_write.o:	generic/event.h
+generic/ip_write.o:	generic/icmp_lib.h
+generic/ip_write.o:	generic/io.h
+generic/ip_write.o:	generic/ip.h
+generic/ip_write.o:	generic/ip_int.h
+generic/ip_write.o:	generic/ip_write.c
+generic/ip_write.o:	generic/ipr.h
+generic/ip_write.o:	generic/type.h
+generic/ip_write.o:	inet.h
+generic/ip_write.o:	inet_config.h
+
+generic/ipr.o:	/usr/include/ansi.h
+generic/ipr.o:	/usr/include/errno.h
+generic/ipr.o:	/usr/include/minix/com.h
+generic/ipr.o:	/usr/include/minix/config.h
+generic/ipr.o:	/usr/include/minix/const.h
+generic/ipr.o:	/usr/include/minix/devio.h
+generic/ipr.o:	/usr/include/minix/ioctl.h
+generic/ipr.o:	/usr/include/minix/ipc.h
+generic/ipr.o:	/usr/include/minix/sys_config.h
+generic/ipr.o:	/usr/include/minix/syslib.h
+generic/ipr.o:	/usr/include/minix/sysutil.h
+generic/ipr.o:	/usr/include/minix/type.h
+generic/ipr.o:	/usr/include/net/gen/arp_io.h
+generic/ipr.o:	/usr/include/net/gen/eth_hdr.h
+generic/ipr.o:	/usr/include/net/gen/eth_io.h
+generic/ipr.o:	/usr/include/net/gen/ether.h
+generic/ipr.o:	/usr/include/net/gen/icmp.h
+generic/ipr.o:	/usr/include/net/gen/icmp_hdr.h
+generic/ipr.o:	/usr/include/net/gen/in.h
+generic/ipr.o:	/usr/include/net/gen/ip_hdr.h
+generic/ipr.o:	/usr/include/net/gen/ip_io.h
+generic/ipr.o:	/usr/include/net/gen/oneCsum.h
+generic/ipr.o:	/usr/include/net/gen/psip_hdr.h
+generic/ipr.o:	/usr/include/net/gen/psip_io.h
+generic/ipr.o:	/usr/include/net/gen/route.h
+generic/ipr.o:	/usr/include/net/gen/tcp.h
+generic/ipr.o:	/usr/include/net/gen/tcp_hdr.h
+generic/ipr.o:	/usr/include/net/gen/tcp_io.h
+generic/ipr.o:	/usr/include/net/gen/udp.h
+generic/ipr.o:	/usr/include/net/gen/udp_hdr.h
+generic/ipr.o:	/usr/include/net/gen/udp_io.h
+generic/ipr.o:	/usr/include/net/hton.h
+generic/ipr.o:	/usr/include/net/ioctl.h
+generic/ipr.o:	/usr/include/stddef.h
+generic/ipr.o:	/usr/include/stdlib.h
+generic/ipr.o:	/usr/include/string.h
+generic/ipr.o:	/usr/include/sys/ioc_file.h
+generic/ipr.o:	/usr/include/sys/time.h
+generic/ipr.o:	/usr/include/sys/types.h
+generic/ipr.o:	/usr/include/unistd.h
+generic/ipr.o:	const.h
+generic/ipr.o:	generic/assert.h
+generic/ipr.o:	generic/buf.h
+generic/ipr.o:	generic/clock.h
+generic/ipr.o:	generic/event.h
+generic/ipr.o:	generic/io.h
+generic/ipr.o:	generic/ip_int.h
+generic/ipr.o:	generic/ipr.c
+generic/ipr.o:	generic/ipr.h
+generic/ipr.o:	generic/type.h
+generic/ipr.o:	inet.h
+generic/ipr.o:	inet_config.h
+
+generic/psip.o:	/usr/include/ansi.h
+generic/psip.o:	/usr/include/errno.h
+generic/psip.o:	/usr/include/minix/com.h
+generic/psip.o:	/usr/include/minix/config.h
+generic/psip.o:	/usr/include/minix/const.h
+generic/psip.o:	/usr/include/minix/devio.h
+generic/psip.o:	/usr/include/minix/ioctl.h
+generic/psip.o:	/usr/include/minix/ipc.h
+generic/psip.o:	/usr/include/minix/sys_config.h
+generic/psip.o:	/usr/include/minix/syslib.h
+generic/psip.o:	/usr/include/minix/sysutil.h
+generic/psip.o:	/usr/include/minix/type.h
+generic/psip.o:	/usr/include/net/gen/arp_io.h
+generic/psip.o:	/usr/include/net/gen/eth_hdr.h
+generic/psip.o:	/usr/include/net/gen/eth_io.h
+generic/psip.o:	/usr/include/net/gen/ether.h
+generic/psip.o:	/usr/include/net/gen/icmp.h
+generic/psip.o:	/usr/include/net/gen/icmp_hdr.h
+generic/psip.o:	/usr/include/net/gen/in.h
+generic/psip.o:	/usr/include/net/gen/ip_hdr.h
+generic/psip.o:	/usr/include/net/gen/ip_io.h
+generic/psip.o:	/usr/include/net/gen/oneCsum.h
+generic/psip.o:	/usr/include/net/gen/psip_hdr.h
+generic/psip.o:	/usr/include/net/gen/psip_io.h
+generic/psip.o:	/usr/include/net/gen/route.h
+generic/psip.o:	/usr/include/net/gen/tcp.h
+generic/psip.o:	/usr/include/net/gen/tcp_hdr.h
+generic/psip.o:	/usr/include/net/gen/tcp_io.h
+generic/psip.o:	/usr/include/net/gen/udp.h
+generic/psip.o:	/usr/include/net/gen/udp_hdr.h
+generic/psip.o:	/usr/include/net/gen/udp_io.h
+generic/psip.o:	/usr/include/net/hton.h
+generic/psip.o:	/usr/include/net/ioctl.h
+generic/psip.o:	/usr/include/stddef.h
+generic/psip.o:	/usr/include/stdlib.h
+generic/psip.o:	/usr/include/string.h
+generic/psip.o:	/usr/include/sys/ioc_file.h
+generic/psip.o:	/usr/include/sys/time.h
+generic/psip.o:	/usr/include/sys/types.h
+generic/psip.o:	/usr/include/unistd.h
+generic/psip.o:	const.h
+generic/psip.o:	generic/assert.h
+generic/psip.o:	generic/buf.h
+generic/psip.o:	generic/event.h
+generic/psip.o:	generic/ip_int.h
+generic/psip.o:	generic/psip.c
+generic/psip.o:	generic/psip.h
+generic/psip.o:	generic/sr.h
+generic/psip.o:	generic/type.h
+generic/psip.o:	inet.h
+generic/psip.o:	inet_config.h
+
+generic/rand256.o:	/usr/include/ansi.h
+generic/rand256.o:	/usr/include/assert.h
+generic/rand256.o:	/usr/include/errno.h
+generic/rand256.o:	/usr/include/minix/com.h
+generic/rand256.o:	/usr/include/minix/config.h
+generic/rand256.o:	/usr/include/minix/const.h
+generic/rand256.o:	/usr/include/minix/devio.h
+generic/rand256.o:	/usr/include/minix/ioctl.h
+generic/rand256.o:	/usr/include/minix/ipc.h
+generic/rand256.o:	/usr/include/minix/sys_config.h
+generic/rand256.o:	/usr/include/minix/syslib.h
+generic/rand256.o:	/usr/include/minix/sysutil.h
+generic/rand256.o:	/usr/include/minix/type.h
+generic/rand256.o:	/usr/include/minix/u64.h
+generic/rand256.o:	/usr/include/net/gen/arp_io.h
+generic/rand256.o:	/usr/include/net/gen/eth_hdr.h
+generic/rand256.o:	/usr/include/net/gen/eth_io.h
+generic/rand256.o:	/usr/include/net/gen/ether.h
+generic/rand256.o:	/usr/include/net/gen/icmp.h
+generic/rand256.o:	/usr/include/net/gen/icmp_hdr.h
+generic/rand256.o:	/usr/include/net/gen/in.h
+generic/rand256.o:	/usr/include/net/gen/ip_hdr.h
+generic/rand256.o:	/usr/include/net/gen/ip_io.h
+generic/rand256.o:	/usr/include/net/gen/oneCsum.h
+generic/rand256.o:	/usr/include/net/gen/psip_hdr.h
+generic/rand256.o:	/usr/include/net/gen/psip_io.h
+generic/rand256.o:	/usr/include/net/gen/route.h
+generic/rand256.o:	/usr/include/net/gen/tcp.h
+generic/rand256.o:	/usr/include/net/gen/tcp_hdr.h
+generic/rand256.o:	/usr/include/net/gen/tcp_io.h
+generic/rand256.o:	/usr/include/net/gen/udp.h
+generic/rand256.o:	/usr/include/net/gen/udp_hdr.h
+generic/rand256.o:	/usr/include/net/gen/udp_io.h
+generic/rand256.o:	/usr/include/net/hton.h
+generic/rand256.o:	/usr/include/net/ioctl.h
+generic/rand256.o:	/usr/include/stddef.h
+generic/rand256.o:	/usr/include/stdlib.h
+generic/rand256.o:	/usr/include/string.h
+generic/rand256.o:	/usr/include/sys/ioc_file.h
+generic/rand256.o:	/usr/include/sys/time.h
+generic/rand256.o:	/usr/include/sys/types.h
+generic/rand256.o:	/usr/include/unistd.h
+generic/rand256.o:	const.h
+generic/rand256.o:	generic/rand256.c
+generic/rand256.o:	generic/rand256.h
+generic/rand256.o:	inet.h
+generic/rand256.o:	inet_config.h
+generic/rand256.o:	sha2.h
+
+generic/tcp.o:	/usr/include/ansi.h
+generic/tcp.o:	/usr/include/errno.h
+generic/tcp.o:	/usr/include/minix/com.h
+generic/tcp.o:	/usr/include/minix/config.h
+generic/tcp.o:	/usr/include/minix/const.h
+generic/tcp.o:	/usr/include/minix/devio.h
+generic/tcp.o:	/usr/include/minix/ioctl.h
+generic/tcp.o:	/usr/include/minix/ipc.h
+generic/tcp.o:	/usr/include/minix/sys_config.h
+generic/tcp.o:	/usr/include/minix/syslib.h
+generic/tcp.o:	/usr/include/minix/sysutil.h
+generic/tcp.o:	/usr/include/minix/type.h
+generic/tcp.o:	/usr/include/net/gen/arp_io.h
+generic/tcp.o:	/usr/include/net/gen/eth_hdr.h
+generic/tcp.o:	/usr/include/net/gen/eth_io.h
+generic/tcp.o:	/usr/include/net/gen/ether.h
+generic/tcp.o:	/usr/include/net/gen/icmp.h
+generic/tcp.o:	/usr/include/net/gen/icmp_hdr.h
+generic/tcp.o:	/usr/include/net/gen/in.h
+generic/tcp.o:	/usr/include/net/gen/ip_hdr.h
+generic/tcp.o:	/usr/include/net/gen/ip_io.h
+generic/tcp.o:	/usr/include/net/gen/oneCsum.h
+generic/tcp.o:	/usr/include/net/gen/psip_hdr.h
+generic/tcp.o:	/usr/include/net/gen/psip_io.h
+generic/tcp.o:	/usr/include/net/gen/route.h
+generic/tcp.o:	/usr/include/net/gen/tcp.h
+generic/tcp.o:	/usr/include/net/gen/tcp_hdr.h
+generic/tcp.o:	/usr/include/net/gen/tcp_io.h
+generic/tcp.o:	/usr/include/net/gen/udp.h
+generic/tcp.o:	/usr/include/net/gen/udp_hdr.h
+generic/tcp.o:	/usr/include/net/gen/udp_io.h
+generic/tcp.o:	/usr/include/net/hton.h
+generic/tcp.o:	/usr/include/net/ioctl.h
+generic/tcp.o:	/usr/include/stddef.h
+generic/tcp.o:	/usr/include/stdlib.h
+generic/tcp.o:	/usr/include/string.h
+generic/tcp.o:	/usr/include/sys/ioc_file.h
+generic/tcp.o:	/usr/include/sys/time.h
+generic/tcp.o:	/usr/include/sys/types.h
+generic/tcp.o:	/usr/include/unistd.h
+generic/tcp.o:	const.h
+generic/tcp.o:	generic/assert.h
+generic/tcp.o:	generic/buf.h
+generic/tcp.o:	generic/clock.h
+generic/tcp.o:	generic/event.h
+generic/tcp.o:	generic/io.h
+generic/tcp.o:	generic/ip.h
+generic/tcp.o:	generic/rand256.h
+generic/tcp.o:	generic/sr.h
+generic/tcp.o:	generic/tcp.c
+generic/tcp.o:	generic/tcp.h
+generic/tcp.o:	generic/tcp_int.h
+generic/tcp.o:	generic/type.h
+generic/tcp.o:	inet.h
+generic/tcp.o:	inet_config.h
+
+generic/tcp_lib.o:	/usr/include/ansi.h
+generic/tcp_lib.o:	/usr/include/errno.h
+generic/tcp_lib.o:	/usr/include/minix/com.h
+generic/tcp_lib.o:	/usr/include/minix/config.h
+generic/tcp_lib.o:	/usr/include/minix/const.h
+generic/tcp_lib.o:	/usr/include/minix/devio.h
+generic/tcp_lib.o:	/usr/include/minix/ioctl.h
+generic/tcp_lib.o:	/usr/include/minix/ipc.h
+generic/tcp_lib.o:	/usr/include/minix/sys_config.h
+generic/tcp_lib.o:	/usr/include/minix/syslib.h
+generic/tcp_lib.o:	/usr/include/minix/sysutil.h
+generic/tcp_lib.o:	/usr/include/minix/type.h
+generic/tcp_lib.o:	/usr/include/net/gen/arp_io.h
+generic/tcp_lib.o:	/usr/include/net/gen/eth_hdr.h
+generic/tcp_lib.o:	/usr/include/net/gen/eth_io.h
+generic/tcp_lib.o:	/usr/include/net/gen/ether.h
+generic/tcp_lib.o:	/usr/include/net/gen/icmp.h
+generic/tcp_lib.o:	/usr/include/net/gen/icmp_hdr.h
+generic/tcp_lib.o:	/usr/include/net/gen/in.h
+generic/tcp_lib.o:	/usr/include/net/gen/ip_hdr.h
+generic/tcp_lib.o:	/usr/include/net/gen/ip_io.h
+generic/tcp_lib.o:	/usr/include/net/gen/oneCsum.h
+generic/tcp_lib.o:	/usr/include/net/gen/psip_hdr.h
+generic/tcp_lib.o:	/usr/include/net/gen/psip_io.h
+generic/tcp_lib.o:	/usr/include/net/gen/route.h
+generic/tcp_lib.o:	/usr/include/net/gen/tcp.h
+generic/tcp_lib.o:	/usr/include/net/gen/tcp_hdr.h
+generic/tcp_lib.o:	/usr/include/net/gen/tcp_io.h
+generic/tcp_lib.o:	/usr/include/net/gen/udp.h
+generic/tcp_lib.o:	/usr/include/net/gen/udp_hdr.h
+generic/tcp_lib.o:	/usr/include/net/gen/udp_io.h
+generic/tcp_lib.o:	/usr/include/net/hton.h
+generic/tcp_lib.o:	/usr/include/net/ioctl.h
+generic/tcp_lib.o:	/usr/include/stddef.h
+generic/tcp_lib.o:	/usr/include/stdlib.h
+generic/tcp_lib.o:	/usr/include/string.h
+generic/tcp_lib.o:	/usr/include/sys/ioc_file.h
+generic/tcp_lib.o:	/usr/include/sys/time.h
+generic/tcp_lib.o:	/usr/include/sys/types.h
+generic/tcp_lib.o:	/usr/include/unistd.h
+generic/tcp_lib.o:	const.h
+generic/tcp_lib.o:	generic/assert.h
+generic/tcp_lib.o:	generic/buf.h
+generic/tcp_lib.o:	generic/clock.h
+generic/tcp_lib.o:	generic/event.h
+generic/tcp_lib.o:	generic/io.h
+generic/tcp_lib.o:	generic/tcp_int.h
+generic/tcp_lib.o:	generic/tcp_lib.c
+generic/tcp_lib.o:	generic/type.h
+generic/tcp_lib.o:	inet.h
+generic/tcp_lib.o:	inet_config.h
+
+generic/tcp_recv.o:	/usr/include/ansi.h
+generic/tcp_recv.o:	/usr/include/errno.h
+generic/tcp_recv.o:	/usr/include/minix/com.h
+generic/tcp_recv.o:	/usr/include/minix/config.h
+generic/tcp_recv.o:	/usr/include/minix/const.h
+generic/tcp_recv.o:	/usr/include/minix/devio.h
+generic/tcp_recv.o:	/usr/include/minix/ioctl.h
+generic/tcp_recv.o:	/usr/include/minix/ipc.h
+generic/tcp_recv.o:	/usr/include/minix/sys_config.h
+generic/tcp_recv.o:	/usr/include/minix/syslib.h
+generic/tcp_recv.o:	/usr/include/minix/sysutil.h
+generic/tcp_recv.o:	/usr/include/minix/type.h
+generic/tcp_recv.o:	/usr/include/net/gen/arp_io.h
+generic/tcp_recv.o:	/usr/include/net/gen/eth_hdr.h
+generic/tcp_recv.o:	/usr/include/net/gen/eth_io.h
+generic/tcp_recv.o:	/usr/include/net/gen/ether.h
+generic/tcp_recv.o:	/usr/include/net/gen/icmp.h
+generic/tcp_recv.o:	/usr/include/net/gen/icmp_hdr.h
+generic/tcp_recv.o:	/usr/include/net/gen/in.h
+generic/tcp_recv.o:	/usr/include/net/gen/ip_hdr.h
+generic/tcp_recv.o:	/usr/include/net/gen/ip_io.h
+generic/tcp_recv.o:	/usr/include/net/gen/oneCsum.h
+generic/tcp_recv.o:	/usr/include/net/gen/psip_hdr.h
+generic/tcp_recv.o:	/usr/include/net/gen/psip_io.h
+generic/tcp_recv.o:	/usr/include/net/gen/route.h
+generic/tcp_recv.o:	/usr/include/net/gen/tcp.h
+generic/tcp_recv.o:	/usr/include/net/gen/tcp_hdr.h
+generic/tcp_recv.o:	/usr/include/net/gen/tcp_io.h
+generic/tcp_recv.o:	/usr/include/net/gen/udp.h
+generic/tcp_recv.o:	/usr/include/net/gen/udp_hdr.h
+generic/tcp_recv.o:	/usr/include/net/gen/udp_io.h
+generic/tcp_recv.o:	/usr/include/net/hton.h
+generic/tcp_recv.o:	/usr/include/net/ioctl.h
+generic/tcp_recv.o:	/usr/include/stddef.h
+generic/tcp_recv.o:	/usr/include/stdlib.h
+generic/tcp_recv.o:	/usr/include/string.h
+generic/tcp_recv.o:	/usr/include/sys/ioc_file.h
+generic/tcp_recv.o:	/usr/include/sys/time.h
+generic/tcp_recv.o:	/usr/include/sys/types.h
+generic/tcp_recv.o:	/usr/include/unistd.h
+generic/tcp_recv.o:	const.h
+generic/tcp_recv.o:	generic/assert.h
+generic/tcp_recv.o:	generic/buf.h
+generic/tcp_recv.o:	generic/clock.h
+generic/tcp_recv.o:	generic/event.h
+generic/tcp_recv.o:	generic/io.h
+generic/tcp_recv.o:	generic/sr.h
+generic/tcp_recv.o:	generic/tcp.h
+generic/tcp_recv.o:	generic/tcp_int.h
+generic/tcp_recv.o:	generic/tcp_recv.c
+generic/tcp_recv.o:	generic/type.h
+generic/tcp_recv.o:	inet.h
+generic/tcp_recv.o:	inet_config.h
+
+generic/tcp_send.o:	/usr/include/ansi.h
+generic/tcp_send.o:	/usr/include/errno.h
+generic/tcp_send.o:	/usr/include/minix/com.h
+generic/tcp_send.o:	/usr/include/minix/config.h
+generic/tcp_send.o:	/usr/include/minix/const.h
+generic/tcp_send.o:	/usr/include/minix/devio.h
+generic/tcp_send.o:	/usr/include/minix/ioctl.h
+generic/tcp_send.o:	/usr/include/minix/ipc.h
+generic/tcp_send.o:	/usr/include/minix/sys_config.h
+generic/tcp_send.o:	/usr/include/minix/syslib.h
+generic/tcp_send.o:	/usr/include/minix/sysutil.h
+generic/tcp_send.o:	/usr/include/minix/type.h
+generic/tcp_send.o:	/usr/include/net/gen/arp_io.h
+generic/tcp_send.o:	/usr/include/net/gen/eth_hdr.h
+generic/tcp_send.o:	/usr/include/net/gen/eth_io.h
+generic/tcp_send.o:	/usr/include/net/gen/ether.h
+generic/tcp_send.o:	/usr/include/net/gen/icmp.h
+generic/tcp_send.o:	/usr/include/net/gen/icmp_hdr.h
+generic/tcp_send.o:	/usr/include/net/gen/in.h
+generic/tcp_send.o:	/usr/include/net/gen/ip_hdr.h
+generic/tcp_send.o:	/usr/include/net/gen/ip_io.h
+generic/tcp_send.o:	/usr/include/net/gen/oneCsum.h
+generic/tcp_send.o:	/usr/include/net/gen/psip_hdr.h
+generic/tcp_send.o:	/usr/include/net/gen/psip_io.h
+generic/tcp_send.o:	/usr/include/net/gen/route.h
+generic/tcp_send.o:	/usr/include/net/gen/tcp.h
+generic/tcp_send.o:	/usr/include/net/gen/tcp_hdr.h
+generic/tcp_send.o:	/usr/include/net/gen/tcp_io.h
+generic/tcp_send.o:	/usr/include/net/gen/udp.h
+generic/tcp_send.o:	/usr/include/net/gen/udp_hdr.h
+generic/tcp_send.o:	/usr/include/net/gen/udp_io.h
+generic/tcp_send.o:	/usr/include/net/hton.h
+generic/tcp_send.o:	/usr/include/net/ioctl.h
+generic/tcp_send.o:	/usr/include/stddef.h
+generic/tcp_send.o:	/usr/include/stdlib.h
+generic/tcp_send.o:	/usr/include/string.h
+generic/tcp_send.o:	/usr/include/sys/ioc_file.h
+generic/tcp_send.o:	/usr/include/sys/time.h
+generic/tcp_send.o:	/usr/include/sys/types.h
+generic/tcp_send.o:	/usr/include/unistd.h
+generic/tcp_send.o:	const.h
+generic/tcp_send.o:	generic/assert.h
+generic/tcp_send.o:	generic/buf.h
+generic/tcp_send.o:	generic/clock.h
+generic/tcp_send.o:	generic/event.h
+generic/tcp_send.o:	generic/io.h
+generic/tcp_send.o:	generic/ip.h
+generic/tcp_send.o:	generic/sr.h
+generic/tcp_send.o:	generic/tcp.h
+generic/tcp_send.o:	generic/tcp_int.h
+generic/tcp_send.o:	generic/tcp_send.c
+generic/tcp_send.o:	generic/type.h
+generic/tcp_send.o:	inet.h
+generic/tcp_send.o:	inet_config.h
+
+generic/udp.o:	/usr/include/ansi.h
+generic/udp.o:	/usr/include/errno.h
+generic/udp.o:	/usr/include/minix/com.h
+generic/udp.o:	/usr/include/minix/config.h
+generic/udp.o:	/usr/include/minix/const.h
+generic/udp.o:	/usr/include/minix/devio.h
+generic/udp.o:	/usr/include/minix/ioctl.h
+generic/udp.o:	/usr/include/minix/ipc.h
+generic/udp.o:	/usr/include/minix/sys_config.h
+generic/udp.o:	/usr/include/minix/syslib.h
+generic/udp.o:	/usr/include/minix/sysutil.h
+generic/udp.o:	/usr/include/minix/type.h
+generic/udp.o:	/usr/include/net/gen/arp_io.h
+generic/udp.o:	/usr/include/net/gen/eth_hdr.h
+generic/udp.o:	/usr/include/net/gen/eth_io.h
+generic/udp.o:	/usr/include/net/gen/ether.h
+generic/udp.o:	/usr/include/net/gen/icmp.h
+generic/udp.o:	/usr/include/net/gen/icmp_hdr.h
+generic/udp.o:	/usr/include/net/gen/in.h
+generic/udp.o:	/usr/include/net/gen/ip_hdr.h
+generic/udp.o:	/usr/include/net/gen/ip_io.h
+generic/udp.o:	/usr/include/net/gen/oneCsum.h
+generic/udp.o:	/usr/include/net/gen/psip_hdr.h
+generic/udp.o:	/usr/include/net/gen/psip_io.h
+generic/udp.o:	/usr/include/net/gen/route.h
+generic/udp.o:	/usr/include/net/gen/tcp.h
+generic/udp.o:	/usr/include/net/gen/tcp_hdr.h
+generic/udp.o:	/usr/include/net/gen/tcp_io.h
+generic/udp.o:	/usr/include/net/gen/udp.h
+generic/udp.o:	/usr/include/net/gen/udp_hdr.h
+generic/udp.o:	/usr/include/net/gen/udp_io.h
+generic/udp.o:	/usr/include/net/hton.h
+generic/udp.o:	/usr/include/net/ioctl.h
+generic/udp.o:	/usr/include/stddef.h
+generic/udp.o:	/usr/include/stdlib.h
+generic/udp.o:	/usr/include/string.h
+generic/udp.o:	/usr/include/sys/ioc_file.h
+generic/udp.o:	/usr/include/sys/time.h
+generic/udp.o:	/usr/include/sys/types.h
+generic/udp.o:	/usr/include/unistd.h
+generic/udp.o:	const.h
+generic/udp.o:	generic/assert.h
+generic/udp.o:	generic/buf.h
+generic/udp.o:	generic/clock.h
+generic/udp.o:	generic/icmp_lib.h
+generic/udp.o:	generic/io.h
+generic/udp.o:	generic/ip.h
+generic/udp.o:	generic/sr.h
+generic/udp.o:	generic/type.h
+generic/udp.o:	generic/udp.c
+generic/udp.o:	generic/udp.h
+generic/udp.o:	generic/udp_int.h
+generic/udp.o:	inet.h
+generic/udp.o:	inet_config.h
Index: /trunk/minix/servers/inet/Makefile
===================================================================
--- /trunk/minix/servers/inet/Makefile	(revision 9)
+++ /trunk/minix/servers/inet/Makefile	(revision 9)
@@ -0,0 +1,45 @@
+# Makefile for inet.
+
+# Directories
+g = generic
+
+# Programs, flags, and libraries
+CC =		cc
+CPPFLAGS =	-I. -D_MINIX
+CFLAGS =	$(OPT) $(CPPFLAGS)
+LDFLAGS =
+LIBS =		-lsys -lsysutil
+
+.c.o:
+	$(CC) $(CFLAGS) -o $@ -c $<
+
+OBJ = 	buf.o clock.o inet.o inet_config.o \
+	mnx_eth.o mq.o qp.o sr.o stacktrace.o \
+	$g/udp.o $g/arp.o $g/eth.o $g/event.o \
+	$g/icmp.o $g/io.o $g/ip.o $g/ip_ioctl.o \
+	$g/ip_lib.o $g/ip_read.o $g/ip_write.o \
+	$g/ipr.o $g/rand256.o $g/tcp.o $g/tcp_lib.o \
+	$g/tcp_recv.o $g/tcp_send.o $g/ip_eth.o \
+	$g/ip_ps.o $g/psip.o \
+	minix3/queryparam.o sha2.o
+
+all:	inet
+
+inet:	$(OBJ)
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) version.c $(LIBS)
+
+install: inet
+	install -c $? /usr/sbin/inet
+
+clean:
+	rm -f $(OBJ) inet *.bak
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c generic/*.c > .depend
+
+# Include generated dependencies.
+include .depend
+
+#
+# $PchId: Makefile.mnx3,v 1.1 2005/06/28 14:28:45 philip Exp $
+#
Index: /trunk/minix/servers/inet/buf.c
===================================================================
--- /trunk/minix/servers/inet/buf.c	(revision 9)
+++ /trunk/minix/servers/inet/buf.c	(revision 9)
@@ -0,0 +1,1256 @@
+/*
+This file contains routines for buffer management.
+
+Copyright 1995 Philip Homburg
+*/
+
+#define BUF_IMPLEMENTATION	1	/* Avoid some macros */
+
+#include "inet.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "generic/assert.h"
+#include "generic/buf.h"
+#include "generic/type.h"
+
+THIS_FILE
+
+#ifndef BUF_USEMALLOC
+#define BUF_USEMALLOC	0
+#endif
+
+#ifndef BUF512_NR
+#define BUF512_NR	512
+#endif
+#ifndef BUF2K_NR
+#define BUF2K_NR	0
+#endif
+#ifndef BUF32K_NR
+#define BUF32K_NR	0
+#endif
+
+#define ACC_NR		((BUF512_NR+BUF2K_NR+BUF32K_NR)*3)
+#define CLIENT_NR	7
+
+#define DECLARE_TYPE(Tag, Type, Size)					\
+	typedef struct Tag						\
+	{								\
+		buf_t buf_header;					\
+		char buf_data[Size];					\
+	} Type
+
+#if BUF_USEMALLOC
+#define DECLARE_STORAGE(Type, Ident, Nitems)				\
+	PRIVATE Type *Ident
+
+#define ALLOC_STORAGE(Ident, Nitems, Label)				\
+	do								\
+	{								\
+		printf("buf.c: malloc %d %s\n", Nitems, Label);		\
+		Ident= malloc(sizeof(*Ident) * Nitems);			\
+		if (!Ident)						\
+			ip_panic(( "unable to alloc %s", Label ));	\
+	} while(0)
+#else
+#define DECLARE_STORAGE(Type, Ident, Nitems)				\
+	PRIVATE Type Ident[Nitems]
+
+#define ALLOC_STORAGE(Ident, Nitems, Label)				\
+	(void)0
+#endif
+
+#if BUF512_NR
+DECLARE_TYPE(buf512, buf512_t, 512);
+PRIVATE acc_t *buf512_freelist;
+DECLARE_STORAGE(buf512_t, buffers512, BUF512_NR);
+FORWARD void bf_512free ARGS(( acc_t *acc ));
+#endif
+#if BUF2K_NR
+DECLARE_TYPE(buf2K, buf2K_t, (2*1024));
+PRIVATE acc_t *buf2K_freelist;
+DECLARE_STORAGE(buf2K_t, buffers2K, BUF2K_NR);
+FORWARD void bf_2Kfree ARGS(( acc_t *acc ));
+#endif
+#if BUF32K_NR
+DECLARE_TYPE(buf32K, buf32K_t, (32*1024));
+PRIVATE acc_t *buf32K_freelist;
+DECLARE_STORAGE(buf32K_t, buffers32K, BUF32K_NR);
+FORWARD void bf_32Kfree ARGS(( acc_t *acc ));
+#endif
+
+PRIVATE acc_t *acc_freelist;
+DECLARE_STORAGE(acc_t, accessors, ACC_NR);
+
+PRIVATE bf_freereq_t freereq[CLIENT_NR];
+PRIVATE size_t bf_buf_gran;
+
+PUBLIC size_t bf_free_bufsize;
+PUBLIC acc_t *bf_temporary_acc;
+PUBLIC acc_t *bf_linkcheck_acc;
+
+#ifdef BUF_CONSISTENCY_CHECK
+int inet_buf_debug;
+unsigned buf_generation; 
+PRIVATE bf_checkreq_t checkreq[CLIENT_NR];
+#endif
+
+#ifndef BUF_TRACK_ALLOC_FREE
+FORWARD acc_t *bf_small_memreq ARGS(( size_t size ));
+#else
+FORWARD acc_t *_bf_small_memreq ARGS(( char *clnt_file, int clnt_line,
+								size_t size ));
+#define bf_small_memreq(a) _bf_small_memreq(clnt_file, clnt_line, a)
+#endif
+FORWARD void free_accs ARGS(( void ));
+#ifdef BUF_CONSISTENCY_CHECK
+FORWARD void count_free_bufs ARGS(( acc_t *list ));
+FORWARD int report_buffer ARGS(( buf_t *buf, char *label, int i ));
+#endif
+
+PUBLIC void bf_init()
+{
+	int i;
+	size_t buf_s;
+	acc_t *acc;
+
+	bf_buf_gran= BUF_S;
+	buf_s= 0;
+
+	for (i=0;i<CLIENT_NR;i++)
+		freereq[i]=0;
+#ifdef BUF_CONSISTENCY_CHECK
+	for (i=0;i<CLIENT_NR;i++)
+		checkreq[i]=0;
+#endif
+
+#if BUF512_NR
+	ALLOC_STORAGE(buffers512, BUF512_NR, "512B-buffers");
+#endif
+#if BUF2K_NR
+	ALLOC_STORAGE(buffers2K, BUF2K_NR, "2K-buffers");
+#endif
+#if BUF32K_NR
+	ALLOC_STORAGE(buffers32K, BUF32K_NR, "32K-buffers");
+#endif
+	ALLOC_STORAGE(accessors, ACC_NR, "accs");
+
+	acc_freelist= NULL;
+	for (i=0;i<ACC_NR;i++)
+	{
+		memset(&accessors[i], '\0', sizeof(accessors[i]));
+
+		accessors[i].acc_linkC= 0;
+		accessors[i].acc_next= acc_freelist;
+		acc_freelist= &accessors[i];
+	}
+
+#define INIT_BUFFERS(Ident, Nitems, Freelist, Freefunc)			\
+	do								\
+	{								\
+		Freelist= NULL;						\
+		for (i=0;i<Nitems;i++)					\
+		{							\
+			acc= acc_freelist;				\
+			if (!acc)					\
+				ip_panic(( "fewer accessors than buffers")); \
+			acc_freelist= acc->acc_next;			\
+			acc->acc_linkC= 0;				\
+									\
+			memset(&Ident[i], '\0', sizeof(Ident[i]));	\
+			Ident[i].buf_header.buf_linkC= 0;		\
+			Ident[i].buf_header.buf_free= Freefunc;		\
+			Ident[i].buf_header.buf_size=			\
+				sizeof(Ident[i].buf_data);		\
+			Ident[i].buf_header.buf_data_p=			\
+				Ident[i].buf_data;			\
+									\
+			acc->acc_buffer= &Ident[i].buf_header;		\
+			acc->acc_next= Freelist;			\
+			Freelist= acc;					\
+		}							\
+		if (sizeof(Ident[0].buf_data) < bf_buf_gran)		\
+			bf_buf_gran= sizeof(Ident[0].buf_data);		\
+		if (sizeof(Ident[0].buf_data) > buf_s)			\
+			buf_s= sizeof(Ident[0].buf_data);		\
+	} while(0)
+
+#if BUF512_NR
+	INIT_BUFFERS(buffers512, BUF512_NR, buf512_freelist, bf_512free);
+#endif
+#if BUF2K_NR
+	INIT_BUFFERS(buffers2K, BUF2K_NR, buf2K_freelist, bf_2Kfree);
+#endif
+#if BUF32K_NR
+	INIT_BUFFERS(buffers32K, BUF32K_NR, buf32K_freelist, bf_32Kfree);
+#endif
+
+#undef INIT_BUFFERS
+
+	assert (buf_s == BUF_S);
+}
+
+#ifndef BUF_CONSISTENCY_CHECK
+PUBLIC void bf_logon(func)
+bf_freereq_t func;
+#else
+PUBLIC void bf_logon(func, checkfunc)
+bf_freereq_t func;
+bf_checkreq_t checkfunc;
+#endif
+{
+	int i;
+
+	for (i=0;i<CLIENT_NR;i++)
+		if (!freereq[i])
+		{
+			freereq[i]=func;
+#ifdef BUF_CONSISTENCY_CHECK
+			checkreq[i]= checkfunc;
+#endif
+			return;
+		}
+
+	ip_panic(( "buf.c: too many clients" ));
+}
+
+/*
+bf_memreq
+*/
+
+#ifndef BUF_TRACK_ALLOC_FREE
+PUBLIC acc_t *bf_memreq(size)
+#else
+PUBLIC acc_t *_bf_memreq(clnt_file, clnt_line, size)
+char *clnt_file;
+int clnt_line;
+#endif
+size_t size;
+{
+	acc_t *head, *tail, *new_acc;
+	buf_t *buf;
+	int i,j;
+	size_t count;
+
+	assert (size>0);
+
+	head= NULL;
+	tail= NULL;
+	while (size)
+	{
+		new_acc= NULL;
+
+		/* Note the tricky dangling else... */
+#define ALLOC_BUF(Freelist, Bufsize)					\
+	if (Freelist && (Bufsize == BUF_S || size <= Bufsize))		\
+	{								\
+		new_acc= Freelist;					\
+		Freelist= new_acc->acc_next;				\
+									\
+		assert(new_acc->acc_linkC == 0);			\
+		new_acc->acc_linkC= 1;					\
+		buf= new_acc->acc_buffer;				\
+		assert(buf->buf_linkC == 0);				\
+		buf->buf_linkC= 1;					\
+	}								\
+	else
+
+		/* Sort attempts by buffer size */
+#if BUF512_NR
+		ALLOC_BUF(buf512_freelist, 512)
+#endif
+#if BUF2K_NR
+		ALLOC_BUF(buf2K_freelist, 2*1024)
+#endif
+#if BUF32K_NR
+		ALLOC_BUF(buf32K_freelist, 32*1024)
+#endif
+#undef ALLOC_BUF
+		{
+			DBLOCK(2, printf("freeing buffers\n"));
+
+			bf_free_bufsize= 0;
+			for (i=0; bf_free_bufsize<size && i<MAX_BUFREQ_PRI;
+				i++)
+			{
+				for (j=0; j<CLIENT_NR; j++)
+				{
+					if (freereq[j])
+						(*freereq[j])(i);
+				}
+#if DEBUG && 0
+ { acc_t *acc;
+   j= 0; for(acc= buf512_freelist; acc; acc= acc->acc_next) j++;
+   printf("# of free 512-bytes buffer is now %d\n", j); }
+#endif
+			}
+#if DEBUG && 0
+ { printf("last level was level %d\n", i-1); }
+#endif
+			if (bf_free_bufsize<size)
+				ip_panic(( "not enough buffers freed" ));
+
+			continue;
+		}
+
+#ifdef BUF_TRACK_ALLOC_FREE
+		new_acc->acc_alloc_file= clnt_file;
+		new_acc->acc_alloc_line= clnt_line;
+		buf->buf_alloc_file= clnt_file;
+		buf->buf_alloc_line= clnt_line;
+#endif
+
+		if (!head)
+			head= new_acc;
+		else
+			tail->acc_next= new_acc;
+		tail= new_acc;
+
+		count= tail->acc_buffer->buf_size;
+		if (count > size)
+			count= size;
+
+		tail->acc_offset= 0;
+		tail->acc_length=  count;
+		size -= count;
+	}
+	tail->acc_next= NULL;
+
+	return head;
+}
+
+/*
+bf_small_memreq
+*/
+
+#ifndef BUF_TRACK_ALLOC_FREE
+PRIVATE acc_t *bf_small_memreq(size)
+#else
+PRIVATE acc_t *_bf_small_memreq(clnt_file, clnt_line, size)
+char *clnt_file;
+int clnt_line;
+#endif
+size_t size;
+{
+	return bf_memreq(size);
+}
+
+#ifndef BUF_TRACK_ALLOC_FREE
+PUBLIC void bf_afree(acc)
+#else
+PUBLIC void _bf_afree(clnt_file, clnt_line, acc)
+char *clnt_file;
+int clnt_line;
+#endif
+acc_t *acc;
+{
+	acc_t *next_acc;
+	buf_t *buf;
+
+	while (acc)
+	{
+#if defined(bf_afree)
+		DIFBLOCK(1, (acc->acc_linkC <= 0),
+			printf("clnt_file= %s, clnt_line= %d\n", 
+			clnt_file, clnt_line));
+#endif
+		assert (acc->acc_linkC>0);
+		if (--acc->acc_linkC > 0)
+			break;
+
+#ifdef BUF_TRACK_ALLOC_FREE
+		acc->acc_free_file= clnt_file;
+		acc->acc_free_line= clnt_line;
+#endif
+		buf= acc->acc_buffer;
+		assert (buf);
+
+#if defined(bf_afree)
+		DIFBLOCK(1, (buf->buf_linkC == 0),
+			printf("clnt_file= %s, clnt_line= %d\n", 
+			clnt_file, clnt_line));
+#endif
+		assert (buf->buf_linkC>0);
+		if (--buf->buf_linkC > 0)
+		{
+			acc->acc_buffer= NULL;
+			next_acc= acc->acc_next;
+			acc->acc_next= acc_freelist;
+			acc_freelist= acc;
+#ifdef BUF_CONSISTENCY_CHECK
+			if (inet_buf_debug)
+			{
+				acc->acc_offset= 0xdeadbeaf;
+				acc->acc_length= 0xdeadbeaf;
+				acc->acc_buffer= (buf_t *)0xdeadbeaf;
+				acc->acc_ext_link= (acc_t *)0xdeadbeaf;
+			}
+#endif
+			acc= next_acc;
+			continue;
+		}
+
+		bf_free_bufsize += buf->buf_size;
+#ifdef BUF_TRACK_ALLOC_FREE
+		buf->buf_free_file= clnt_file;
+		buf->buf_free_line= clnt_line;
+#endif
+		next_acc= acc->acc_next;
+		buf->buf_free(acc);
+		acc= next_acc;
+		continue;
+	}
+}
+
+#ifndef BUF_TRACK_ALLOC_FREE
+PUBLIC acc_t *bf_dupacc(acc_ptr)
+#else
+PUBLIC acc_t *_bf_dupacc(clnt_file, clnt_line, acc_ptr)
+char *clnt_file;
+int clnt_line;
+#endif
+register acc_t *acc_ptr;
+{
+	register acc_t *new_acc;
+
+	if (!acc_freelist)
+	{
+		free_accs();
+		if (!acc_freelist)
+			ip_panic(( "buf.c: out of accessors" ));
+	}
+	new_acc= acc_freelist;
+	acc_freelist= new_acc->acc_next;
+
+	*new_acc= *acc_ptr;
+	if (acc_ptr->acc_next)
+		acc_ptr->acc_next->acc_linkC++;
+	if (acc_ptr->acc_buffer)
+		acc_ptr->acc_buffer->buf_linkC++;
+	new_acc->acc_linkC= 1;
+#ifdef BUF_TRACK_ALLOC_FREE
+	new_acc->acc_alloc_file= clnt_file;
+	new_acc->acc_alloc_line= clnt_line;
+#endif
+	return new_acc;
+}
+
+PUBLIC size_t bf_bufsize(acc_ptr)
+register acc_t *acc_ptr;
+{
+	register size_t size;
+
+assert(acc_ptr);
+
+	size=0;
+
+	while (acc_ptr)
+	{
+assert(acc_ptr >= accessors && acc_ptr <= &accessors[ACC_NR-1]);
+		size += acc_ptr->acc_length;
+		acc_ptr= acc_ptr->acc_next;
+	}
+	return size;
+}
+
+#ifndef BUF_TRACK_ALLOC_FREE
+PUBLIC acc_t *bf_packIffLess(pack, min_len)
+#else
+PUBLIC acc_t *_bf_packIffLess(clnt_file, clnt_line, pack, min_len)
+char *clnt_file;
+int clnt_line;
+#endif
+acc_t *pack;
+int min_len;
+{
+	if (!pack || pack->acc_length >= min_len)
+		return pack;
+
+#if DEBUG
+#ifdef bf_packIffLess
+ { where(); printf("calling bf_pack because of %s %d: %d\n", bf_pack_file,
+	bf_pack_line, min_len); }
+#endif
+#endif
+	return bf_pack(pack);
+}
+
+#ifndef BUF_TRACK_ALLOC_FREE
+PUBLIC acc_t *bf_pack(old_acc)
+#else
+PUBLIC acc_t *_bf_pack(clnt_file, clnt_line, old_acc)
+char *clnt_file;
+int clnt_line;
+#endif
+acc_t *old_acc;
+{
+	acc_t *new_acc, *acc_ptr_old, *acc_ptr_new;
+	size_t size, offset_old, offset_new, block_size, block_size_old;
+
+	/* Check if old acc is good enough. */
+	if (!old_acc || (!old_acc->acc_next && old_acc->acc_linkC == 1 && 
+		old_acc->acc_buffer->buf_linkC == 1))
+	{
+		return old_acc;
+	}
+
+	size= bf_bufsize(old_acc);
+	assert(size > 0);
+	new_acc= bf_memreq(size);
+	acc_ptr_old= old_acc;
+	acc_ptr_new= new_acc;
+	offset_old= 0;
+	offset_new= 0;
+	while (size)
+	{
+		assert (acc_ptr_old);
+		if (offset_old == acc_ptr_old->acc_length)
+		{
+			offset_old= 0;
+			acc_ptr_old= acc_ptr_old->acc_next;
+			continue;
+		}
+		assert (offset_old < acc_ptr_old->acc_length);
+		block_size_old= acc_ptr_old->acc_length - offset_old;
+		assert (acc_ptr_new);
+		if (offset_new == acc_ptr_new->acc_length)
+		{
+			offset_new= 0;
+			acc_ptr_new= acc_ptr_new->acc_next;
+			continue;
+		}
+		assert (offset_new < acc_ptr_new->acc_length);
+		block_size= acc_ptr_new->acc_length - offset_new;
+		if (block_size > block_size_old)
+			block_size= block_size_old;
+		memcpy(ptr2acc_data(acc_ptr_new)+offset_new,
+			ptr2acc_data(acc_ptr_old)+offset_old, block_size);
+		offset_new += block_size;
+		offset_old += block_size;
+		size -= block_size;
+	}
+	bf_afree(old_acc);
+	return new_acc;
+}
+
+#ifndef BUF_TRACK_ALLOC_FREE
+PUBLIC acc_t *bf_cut (data, offset, length)
+#else
+PUBLIC acc_t *_bf_cut (clnt_file, clnt_line, data, offset, length)
+char *clnt_file;
+int clnt_line;
+#endif
+register acc_t *data;
+register unsigned offset;
+register unsigned length;
+{
+	register acc_t *head, *tail;
+
+	if (!data && !offset && !length)
+		return NULL;
+#ifdef BUF_TRACK_ALLOC_FREE
+	assert(data ||
+		(printf("from %s, %d: %u, %u\n",
+		clnt_file, clnt_line, offset, length), 0));
+#else
+	assert(data);
+#endif
+
+	assert(data);
+
+	if (!length)
+	{
+		head= bf_dupacc(data);
+		bf_afree(head->acc_next);
+		head->acc_next= NULL;
+		head->acc_length= 0;
+		return head;
+	}
+	while (data && offset>=data->acc_length)
+	{
+		offset -= data->acc_length;
+		data= data->acc_next;
+	}
+
+	assert (data);
+
+	head= bf_dupacc(data);
+	bf_afree(head->acc_next);
+	head->acc_next= NULL;
+	head->acc_offset += offset;
+	head->acc_length -= offset;
+	if (length >= head->acc_length)
+		length -= head->acc_length;
+	else
+	{
+		head->acc_length= length;
+		length= 0;
+	}
+	tail= head;
+	data= data->acc_next;
+	while (data && length && length>=data->acc_length)
+	{
+		tail->acc_next= bf_dupacc(data);
+		tail= tail->acc_next;
+		bf_afree(tail->acc_next);
+		tail->acc_next= NULL;
+		data= data->acc_next;
+		length -= tail->acc_length;
+	}
+	if (length)
+	{
+#ifdef bf_cut
+		assert (data ||
+			(printf("bf_cut called from %s:%d\n",
+			clnt_file, clnt_line), 0));
+#else
+		assert (data);
+#endif
+		tail->acc_next= bf_dupacc(data);
+		tail= tail->acc_next;
+		bf_afree(tail->acc_next);
+		tail->acc_next= NULL;
+		tail->acc_length= length;
+	}
+	return head;
+}
+
+#ifndef BUF_TRACK_ALLOC_FREE
+PUBLIC acc_t *bf_delhead (data, offset)
+#else
+PUBLIC acc_t *_bf_delhead (clnt_file, clnt_line, data, offset)
+char *clnt_file;
+int clnt_line;
+#endif
+register acc_t *data;
+register unsigned offset;
+{
+	acc_t *new_acc;
+
+	assert(data);
+
+	/* Find the acc we need to modify. */
+	new_acc= data;
+	while(offset >= new_acc->acc_length)
+	{
+		offset -= new_acc->acc_length;
+		new_acc= new_acc->acc_next;
+#ifdef BUF_TRACK_ALLOC_FREE
+		assert(new_acc || (printf("called from %s, %d\n",
+			clnt_file, clnt_line),0));
+#else
+		assert(new_acc);
+#endif
+	}
+
+	/* Discard the old acc(s) */
+	if (new_acc != data)
+	{
+		new_acc->acc_linkC++;
+		bf_afree(data);
+		data= new_acc;
+	}
+
+	/* Make sure that acc_linkC == 1 */
+	if (data->acc_linkC != 1)
+	{
+		new_acc= bf_dupacc(data);
+		bf_afree(data);
+		data= new_acc;
+	}
+
+	/* Delete the last bit by modifying acc_offset and acc_length */
+	data->acc_offset += offset;
+	data->acc_length -= offset;
+	return data;
+}
+
+/*
+bf_append
+*/
+
+#ifndef BUF_TRACK_ALLOC_FREE
+PUBLIC acc_t *bf_append(data_first, data_second)
+#else
+PUBLIC acc_t *_bf_append(clnt_file, clnt_line, data_first, data_second)
+char *clnt_file;
+int clnt_line;
+#endif
+acc_t *data_first;
+acc_t  *data_second;
+{
+	acc_t *head, *tail, *new_acc, *acc_ptr_new, tmp_acc, *curr;
+	char *src_ptr, *dst_ptr;
+	size_t size, offset_old, offset_new, block_size_old, block_size;
+
+	if (!data_first)
+		return data_second;
+	if (!data_second)
+		return data_first;
+
+	head= NULL;
+	tail= NULL;
+	while (data_first)
+	{
+		if (data_first->acc_linkC == 1)
+			curr= data_first;
+		else
+		{
+			curr= bf_dupacc(data_first);
+			assert (curr->acc_linkC == 1);
+			bf_afree(data_first);
+		}
+		data_first= curr->acc_next;
+		if (!curr->acc_length)
+		{
+			curr->acc_next= NULL;
+			bf_afree(curr);
+			continue;
+		}
+		if (!head)
+			head= curr;
+		else
+			tail->acc_next= curr;
+		tail= curr;
+	}
+	if (!head)
+		return data_second;
+	tail->acc_next= NULL;
+
+	while (data_second && !data_second->acc_length)
+	{
+		curr= data_second;
+		data_second= data_second->acc_next;
+		if (data_second)
+			data_second->acc_linkC++;
+		bf_afree(curr);
+	}
+	if (!data_second)
+		return head;
+
+	if (tail->acc_length + data_second->acc_length >
+		tail->acc_buffer->buf_size)
+	{
+		tail->acc_next= data_second;
+		return head;
+	}
+
+	if (tail->acc_buffer->buf_size == bf_buf_gran && 
+		tail->acc_buffer->buf_linkC == 1)
+	{
+		if (tail->acc_offset)
+		{
+			memmove(tail->acc_buffer->buf_data_p,
+				ptr2acc_data(tail), tail->acc_length);
+			tail->acc_offset= 0;
+		}
+		dst_ptr= ptr2acc_data(tail) + tail->acc_length;
+		src_ptr= ptr2acc_data(data_second);
+		memcpy(dst_ptr, src_ptr, data_second->acc_length);
+		tail->acc_length += data_second->acc_length;
+		tail->acc_next= data_second->acc_next;
+		if (data_second->acc_next)
+			data_second->acc_next->acc_linkC++;
+		bf_afree(data_second);
+		return head;
+	}
+
+	new_acc= bf_small_memreq(tail->acc_length+data_second->acc_length);
+	acc_ptr_new= new_acc;
+	offset_old= 0;
+	offset_new= 0;
+	size= tail->acc_length;
+	while (size)
+	{
+assert (acc_ptr_new);
+		if (offset_new == acc_ptr_new->acc_length)
+		{
+			offset_new= 0;
+			acc_ptr_new= acc_ptr_new->acc_next;
+			continue;
+		}
+assert (offset_new < acc_ptr_new->acc_length);
+assert (offset_old < tail->acc_length);
+		block_size_old= tail->acc_length - offset_old;
+		block_size= acc_ptr_new->acc_length - offset_new;
+		if (block_size > block_size_old)
+			block_size= block_size_old;
+		memcpy(ptr2acc_data(acc_ptr_new)+offset_new,
+			ptr2acc_data(tail)+offset_old, block_size);
+		offset_new += block_size;
+		offset_old += block_size;
+		size -= block_size;
+	}
+	offset_old= 0;
+	size= data_second->acc_length;
+	while (size)
+	{
+assert (acc_ptr_new);
+		if (offset_new == acc_ptr_new->acc_length)
+		{
+			offset_new= 0;
+			acc_ptr_new= acc_ptr_new->acc_next;
+			continue;
+		}
+assert (offset_new < acc_ptr_new->acc_length);
+assert (offset_old < data_second->acc_length);
+		block_size_old= data_second->acc_length - offset_old;
+		block_size= acc_ptr_new->acc_length - offset_new;
+		if (block_size > block_size_old)
+			block_size= block_size_old;
+		memcpy(ptr2acc_data(acc_ptr_new)+offset_new,
+			ptr2acc_data(data_second)+offset_old, block_size);
+		offset_new += block_size;
+		offset_old += block_size;
+		size -= block_size;
+	}
+	tmp_acc= *tail;
+	*tail= *new_acc;
+	*new_acc= tmp_acc;
+
+	bf_afree(new_acc);
+	while (tail->acc_next)
+		tail= tail->acc_next;
+
+	tail->acc_next= data_second->acc_next;
+	if (data_second->acc_next)
+		data_second->acc_next->acc_linkC++;
+	bf_afree(data_second);
+	return head;
+}
+
+#if BUF512_NR
+PRIVATE void bf_512free(acc)
+acc_t *acc;
+{
+#ifdef BUF_CONSISTENCY_CHECK 
+	if (inet_buf_debug)
+		memset(acc->acc_buffer->buf_data_p, 0xa5, 512);
+#endif
+	acc->acc_next= buf512_freelist;
+	buf512_freelist= acc;
+}
+#endif
+#if BUF2K_NR
+PRIVATE void bf_2Kfree(acc)
+acc_t *acc;
+{
+#ifdef BUF_CONSISTENCY_CHECK 
+	if (inet_buf_debug)
+		memset(acc->acc_buffer->buf_data_p, 0xa5, 2*1024);
+#endif
+	acc->acc_next= buf2K_freelist;
+	buf2K_freelist= acc;
+}
+#endif
+#if BUF32K_NR
+PRIVATE void bf_32Kfree(acc)
+acc_t *acc;
+{
+#ifdef BUF_CONSISTENCY_CHECK 
+	if (inet_buf_debug)
+		memset(acc->acc_buffer->buf_data_p, 0xa5, 32*1024);
+#endif
+	acc->acc_next= buf32K_freelist;
+	buf32K_freelist= acc;
+}
+#endif
+
+#ifdef BUF_CONSISTENCY_CHECK
+PUBLIC int bf_consistency_check()
+{
+	acc_t *acc;
+	int silent;
+	int error;
+	int i;
+
+	buf_generation++;
+
+	for (i=0; i<CLIENT_NR; i++)
+	{
+		if (checkreq[i])
+			(*checkreq[i])();
+	}
+
+	/* Add information about free accessors */
+	for(acc= acc_freelist; acc; acc= acc->acc_next)
+	{
+		if (acc->acc_generation == buf_generation-1)
+		{
+			acc->acc_generation= buf_generation;
+			acc->acc_check_linkC= 0;
+		}
+		else
+		{
+			assert(acc->acc_generation == buf_generation &&
+				acc->acc_check_linkC > 0);
+			acc->acc_check_linkC= -acc->acc_check_linkC;
+		}
+	}
+
+#if BUF512_NR
+	count_free_bufs(buf512_freelist);
+#endif
+#if BUF2K_NR
+	count_free_bufs(buf2K_freelist);
+#endif
+#if BUF32K_NR
+	count_free_bufs(buf32K_freelist);
+#endif
+
+	error= 0;
+
+	/* Report about accessors */
+	silent= 0;
+	for (i=0, acc= accessors; i<ACC_NR; i++, acc++)
+	{
+		if (acc->acc_generation != buf_generation)
+		{
+			error++;
+			assert(acc->acc_generation == buf_generation-1);
+			acc->acc_generation= buf_generation;
+			if (!silent)
+			{
+				printf(
+"acc[%d] (%p) has been lost with count %d, last allocated at %s, %d\n",
+	i, acc, acc->acc_linkC, acc->acc_alloc_file, acc->acc_alloc_line);
+#if 0
+				silent= 1;
+#endif
+			}
+			continue;
+		}
+		if (acc->acc_check_linkC == acc->acc_linkC)
+			continue;
+		error++;
+		if (acc->acc_check_linkC < 0)
+		{
+			if (!silent)
+			{
+				printf(
+"acc[%d] is freed but still in use, allocated at %s, %d, freed at %s, %d\n",
+				i, acc->acc_alloc_file, acc->acc_alloc_line, 
+				acc->acc_free_file, acc->acc_free_line);
+			}
+			acc->acc_check_linkC= -acc->acc_check_linkC;
+			if (acc->acc_check_linkC == acc->acc_linkC)
+			{
+				silent= 1;
+				continue;
+			}
+		}
+		if (!silent)
+		{
+			printf(
+"# of tracked links (%d) for acc[%d] don't match with stored link count %d\n",
+				acc->acc_check_linkC, i, acc->acc_linkC);
+			printf("acc[%d] was allocated at %s, %d\n",
+				i, acc->acc_alloc_file, acc->acc_alloc_line);
+			silent=1;
+		}
+	}
+
+	/* Report about buffers */
+#if BUF512_NR
+	{
+		for (i= 0; i<BUF512_NR; i++)
+		{
+			error |= report_buffer(&buffers512[i].buf_header,
+				"512-buffer", i);
+		}
+	}
+#endif
+#if BUF2K_NR
+	{
+		for (i= 0; i<BUF2K_NR; i++)
+		{
+			error |= report_buffer(&buffers2K[i].buf_header,
+				"2K-buffer", i);
+		}
+	}
+#endif
+#if BUF32K_NR
+	{
+		for (i= 0; i<BUF32K_NR; i++)
+		{
+			error |= report_buffer(&buffers32K[i].buf_header,
+				"32K-buffer", i);
+		}
+	}
+#endif
+
+	return !error;
+}
+
+PRIVATE void count_free_bufs(list)
+acc_t *list;
+{
+	acc_t *acc;
+	buf_t *buf;
+
+	for(acc= list; acc; acc= acc->acc_next)
+	{
+		if (acc->acc_generation != buf_generation-1)
+		{
+			assert(acc->acc_generation == buf_generation &&
+				acc->acc_check_linkC > 0);
+			acc->acc_check_linkC= -acc->acc_check_linkC;
+			continue;
+		}
+		acc->acc_generation= buf_generation;
+		acc->acc_check_linkC= 0;
+
+		buf= acc->acc_buffer;
+		if (buf->buf_generation == buf_generation-1)
+		{
+			buf->buf_generation= buf_generation;
+			buf->buf_check_linkC= 0;
+			continue;
+		}
+		assert(buf->buf_generation == buf_generation &&
+			buf->buf_check_linkC > 0);
+		buf->buf_check_linkC= -buf->buf_check_linkC;
+	}
+}
+
+PRIVATE int report_buffer(buf, label, i)
+buf_t *buf;
+char *label;
+int i;
+{
+	if (buf->buf_generation != buf_generation)
+	{
+		assert(buf->buf_generation == buf_generation-1);
+		buf->buf_generation= buf_generation;
+		printf(
+"%s[%d] (%p) has been lost with count %d, last allocated at %s, %d\n",
+			label, i, buf,
+			buf->buf_linkC, buf->buf_alloc_file,
+			buf->buf_alloc_line);
+		return 1;
+	}
+	if (buf->buf_check_linkC == buf->buf_linkC)
+		return 0;
+	if (buf->buf_check_linkC < 0)
+	{
+		printf(
+"%s[%d] is freed but still in use, allocated at %s, %d, freed at %s, %d\n",
+			label, i, buf->buf_alloc_file, buf->buf_alloc_line, 
+			buf->buf_free_file, buf->buf_free_line);
+		buf->buf_check_linkC= -buf->buf_check_linkC;
+		if (buf->buf_check_linkC == buf->buf_linkC)
+			return 1;
+	}
+	printf(
+"# of tracked links (%d) for %s[%d] don't match with stored link count %d\n",
+			buf->buf_check_linkC, label, i, buf->buf_linkC);
+	printf("%s[%d] was allocated at %s, %d\n",
+		label, i, buf->buf_alloc_file, buf->buf_alloc_line);
+	return 1;
+}
+
+PUBLIC void bf_check_acc(acc)
+acc_t *acc;
+{
+	buf_t *buf;
+
+	while(acc != NULL)
+	{
+		if (acc->acc_generation == buf_generation)
+		{
+			assert(acc->acc_check_linkC > 0);
+			acc->acc_check_linkC++;
+			return;
+		}
+		assert(acc->acc_generation == buf_generation-1);
+		acc->acc_generation= buf_generation;
+		acc->acc_check_linkC= 1;
+
+		buf= acc->acc_buffer;
+		if (buf->buf_generation == buf_generation)
+		{
+			assert(buf->buf_check_linkC > 0);
+			buf->buf_check_linkC++;
+		}
+		else
+		{
+			assert(buf->buf_generation == buf_generation-1);
+			buf->buf_generation= buf_generation;
+			buf->buf_check_linkC= 1;
+		}
+
+		acc= acc->acc_next;
+	}
+}
+
+PUBLIC void _bf_mark_1acc(clnt_file, clnt_line, acc)
+char *clnt_file;
+int clnt_line;
+acc_t *acc;
+{
+	acc->acc_alloc_file= clnt_file;
+	acc->acc_alloc_line= clnt_line;
+}
+
+PUBLIC void _bf_mark_acc(clnt_file, clnt_line, acc)
+char *clnt_file;
+int clnt_line;
+acc_t *acc;
+{
+	buf_t *buf;
+
+	for (; acc; acc= acc->acc_next)
+	{
+		acc->acc_alloc_file= clnt_file;
+		acc->acc_alloc_line= clnt_line;
+		buf= acc->acc_buffer;
+		buf->buf_alloc_file= clnt_file;
+		buf->buf_alloc_line= clnt_line;
+	}
+}
+#endif
+
+PUBLIC int bf_linkcheck(acc)
+acc_t *acc;
+{
+	int i;
+
+	buf_t *buffer;
+	for (i= 0; i<ACC_NR && acc; i++, acc= acc->acc_next)
+	{
+		if (acc->acc_linkC <= 0)
+		{
+			printf("wrong acc_linkC (%d) for acc %p\n", 
+				acc->acc_linkC, acc);
+			return 0;
+		}
+		if (acc->acc_offset < 0)
+		{
+			printf("wrong acc_offset (%d) for acc %p\n",
+				acc->acc_offset, acc);
+			return 0;
+		}
+		if (acc->acc_length < 0)
+		{
+			printf("wrong acc_length (%d) for acc %p\n",
+				acc->acc_length, acc);
+			return 0;
+		}
+		buffer= acc->acc_buffer;
+		if (buffer == NULL)
+		{
+			printf("no buffer for acc %p\n", acc);
+			return 0;
+		}
+		if (buffer->buf_linkC <= 0)
+		{
+			printf(
+			"wrong buf_linkC (%d) for buffer %p, from acc %p\n",
+				buffer->buf_linkC, buffer, acc);
+			return 0;
+		}
+		if (acc->acc_offset + acc->acc_length > buffer->buf_size)
+		{
+			printf("%d + %d > %d for buffer %p, and acc %p\n",
+				acc->acc_offset, acc->acc_length, 
+				buffer->buf_size, buffer, acc);
+			return 0;
+		}
+	}
+	if (acc != NULL)
+	{
+		printf("loop\n");
+		return 0;
+	}
+	return 1;
+}
+
+PRIVATE void free_accs()
+{
+	int i, j;
+
+	DBLOCK(1, printf("free_accs\n"));
+
+assert(bf_linkcheck(bf_linkcheck_acc));
+	for (i=0; !acc_freelist && i<MAX_BUFREQ_PRI; i++)
+	{
+		for (j=0; j<CLIENT_NR; j++)
+		{
+			bf_free_bufsize= 0;
+			if (freereq[j])
+			{
+				(*freereq[j])(i);
+				assert(bf_linkcheck(bf_linkcheck_acc) ||
+					(printf("just called %p\n",
+					freereq[i]),0));
+			}
+		}
+	}
+#if DEBUG
+	printf("last level was level %d\n", i-1);
+#endif
+}
+
+#ifndef BUF_TRACK_ALLOC_FREE
+PUBLIC acc_t *bf_align(acc, size, alignment)
+#else
+PUBLIC acc_t *_bf_align(clnt_file, clnt_line, acc, size, alignment)
+char *clnt_file;
+int clnt_line;
+#endif
+acc_t *acc;
+size_t size;
+size_t alignment;
+{
+	char *ptr;
+	size_t buf_size;
+	acc_t *head, *tail;
+
+	/* Fast check if the buffer is aligned already. */
+	if (acc->acc_length >= size)
+	{
+		ptr= ptr2acc_data(acc);
+		if (((unsigned)ptr & (alignment-1)) == 0)
+			return acc;
+	}
+	buf_size= bf_bufsize(acc);
+#ifdef bf_align
+	assert((size != 0 && buf_size != 0) ||
+		(printf("bf_align(..., %d, %d) from %s, %d\n",
+			size, alignment, clnt_file, clnt_line),0));
+#else
+	assert(size != 0 && buf_size != 0);
+#endif
+	if (buf_size <= size)
+	{
+		acc= bf_pack(acc);
+		return acc;
+	}
+	head= bf_cut(acc, 0, size);
+	tail= bf_cut(acc, size, buf_size-size);
+	bf_afree(acc);
+	head= bf_pack(head);
+	assert(head->acc_next == NULL);
+	head->acc_next= tail;
+	return head;
+}
+
+#if 0
+int chk_acc(acc)
+acc_t *acc;
+{
+	int acc_nr;
+
+	if (!acc)
+		return 1;
+	if (acc < accessors || acc >= &accessors[ACC_NR])
+		return 0;
+	acc_nr= acc-accessors;
+	return acc == &accessors[acc_nr];
+}
+#endif
+
+/*
+ * $PchId: buf.c,v 1.19 2003/09/10 08:54:23 philip Exp $
+ */
Index: /trunk/minix/servers/inet/clock.c
===================================================================
--- /trunk/minix/servers/inet/clock.c	(revision 9)
+++ /trunk/minix/servers/inet/clock.c	(revision 9)
@@ -0,0 +1,231 @@
+/*
+clock.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "proto.h"
+#include "generic/assert.h"
+#include "generic/buf.h"
+#include "generic/clock.h"
+#include "generic/type.h"
+
+THIS_FILE
+
+PUBLIC int clck_call_expire;
+
+PRIVATE time_t curr_time;
+PRIVATE time_t prev_time;
+PRIVATE timer_t *timer_chain;
+PRIVATE time_t next_timeout;
+#ifdef __minix_vmd
+PRIVATE int clck_tasknr= ANY;
+#endif
+
+FORWARD _PROTOTYPE( void clck_fast_release, (timer_t *timer) );
+FORWARD _PROTOTYPE( void set_timer, (void) );
+
+PUBLIC void clck_init()
+{
+	int r;
+
+	clck_call_expire= 0;
+	curr_time= 0;
+	prev_time= 0;
+	next_timeout= 0;
+	timer_chain= 0;
+
+#ifdef __minix_vmd
+	r= sys_findproc(CLOCK_NAME, &clck_tasknr, 0);
+	if (r != OK)
+		ip_panic(( "unable to find clock task: %d\n", r ));
+#endif
+}
+
+PUBLIC time_t get_time()
+{
+	if (!curr_time)
+	{
+#ifdef __minix_vmd
+		static message mess;
+
+		mess.m_type= GET_UPTIME;
+		if (sendrec (clck_tasknr, &mess) < 0)
+			ip_panic(("unable to sendrec"));
+		if (mess.m_type != OK)
+			ip_panic(("can't read clock"));
+		curr_time= mess.NEW_TIME;
+#else /* Minix 3 */
+		int s;
+		if ((s=getuptime(&curr_time)) != OK)
+			ip_panic(("can't read clock"));
+#endif
+		assert(curr_time >= prev_time);
+	}
+	return curr_time;
+}
+
+PUBLIC void set_time (tim)
+time_t tim;
+{
+	if (!curr_time && tim >= prev_time)
+	{
+		/* Some code assumes that no time elapses while it is
+		 * running.
+		 */
+		curr_time= tim;
+	}
+	else if (!curr_time)
+	{
+		DBLOCK(0x20, printf("set_time: new time %ld < prev_time %ld\n",
+			tim, prev_time));
+	}
+}
+
+PUBLIC void reset_time()
+{
+	prev_time= curr_time;
+	curr_time= 0;
+}
+
+PUBLIC void clck_timer(timer, timeout, func, fd)
+timer_t *timer;
+time_t timeout;
+timer_func_t func;
+int fd;
+{
+	timer_t *timer_index;
+
+	if (timer->tim_active)
+		clck_fast_release(timer);
+	assert(!timer->tim_active);
+
+	timer->tim_next= 0;
+	timer->tim_func= func;
+	timer->tim_ref= fd;
+	timer->tim_time= timeout;
+	timer->tim_active= 1;
+
+	if (!timer_chain)
+		timer_chain= timer;
+	else if (timeout < timer_chain->tim_time)
+	{
+		timer->tim_next= timer_chain;
+		timer_chain= timer;
+	}
+	else
+	{
+		timer_index= timer_chain;
+		while (timer_index->tim_next &&
+			timer_index->tim_next->tim_time < timeout)
+			timer_index= timer_index->tim_next;
+		timer->tim_next= timer_index->tim_next;
+		timer_index->tim_next= timer;
+	}
+	if (next_timeout == 0 || timer_chain->tim_time < next_timeout)
+		set_timer();
+}
+
+PUBLIC void clck_tick (mess)
+message *mess;
+{
+	next_timeout= 0;
+	set_timer();
+}
+
+PRIVATE void clck_fast_release (timer)
+timer_t *timer;
+{
+	timer_t *timer_index;
+
+	if (!timer->tim_active)
+		return;
+
+	if (timer == timer_chain)
+		timer_chain= timer_chain->tim_next;
+	else
+	{
+		timer_index= timer_chain;
+		while (timer_index && timer_index->tim_next != timer)
+			timer_index= timer_index->tim_next;
+		assert(timer_index);
+		timer_index->tim_next= timer->tim_next;
+	}
+	timer->tim_active= 0;
+}
+
+PRIVATE void set_timer()
+{
+	time_t new_time;
+	time_t curr_time;
+
+	if (!timer_chain)
+		return;
+
+	curr_time= get_time();
+	new_time= timer_chain->tim_time;
+	if (new_time <= curr_time)
+	{
+		clck_call_expire= 1;
+		return;
+	}
+
+	if (next_timeout == 0 || new_time < next_timeout)
+	{
+#ifdef __minix_vmd
+		static message mess;
+
+		next_timeout= new_time;
+
+		new_time -= curr_time;
+
+		mess.m_type= SET_SYNC_AL;
+		mess.CLOCK_PROC_NR= this_proc;
+		mess.DELTA_TICKS= new_time;
+		if (sendrec (clck_tasknr, &mess) < 0)
+			ip_panic(("unable to sendrec"));
+		if (mess.m_type != OK)
+			ip_panic(("can't set timer"));
+#else /* Minix 3 */
+		next_timeout= new_time;
+		new_time -= curr_time;
+
+		if (sys_setalarm(new_time, 0) != OK)
+  			ip_panic(("can't set timer"));
+#endif
+	}
+}
+
+PUBLIC void clck_untimer (timer)
+timer_t *timer;
+{
+	clck_fast_release (timer);
+	set_timer();
+}
+
+PUBLIC void clck_expire_timers()
+{
+	time_t curr_time;
+	timer_t *timer_index;
+
+	clck_call_expire= 0;
+
+	if (timer_chain == NULL)
+		return;
+
+	curr_time= get_time();
+	while (timer_chain && timer_chain->tim_time<=curr_time)
+	{
+		assert(timer_chain->tim_active);
+		timer_chain->tim_active= 0;
+		timer_index= timer_chain;
+		timer_chain= timer_chain->tim_next;
+		(*timer_index->tim_func)(timer_index->tim_ref, timer_index);
+	}
+	set_timer();
+}
+
+/*
+ * $PchId: clock.c,v 1.10 2005/06/28 14:23:40 philip Exp $
+ */
Index: /trunk/minix/servers/inet/const.h
===================================================================
--- /trunk/minix/servers/inet/const.h	(revision 9)
+++ /trunk/minix/servers/inet/const.h	(revision 9)
@@ -0,0 +1,34 @@
+/*
+inet/const.h
+
+Created:	Dec 30, 1991 by Philip Homburg
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef INET__CONST_H
+#define INET__CONST_H
+
+#ifndef DEBUG
+#define DEBUG	0
+#endif
+
+#ifndef NDEBUG
+#define NDEBUG	0
+#endif
+
+#define CLOCK_GRAN	1	/* in HZ */
+
+#define where()	printf("%s, %d: ", __FILE__, __LINE__)
+
+#define NW_SUSPEND	SUSPEND
+#define NW_WOULDBLOCK	EWOULDBLOCK
+#define NW_OK		OK
+
+#define BUF_S		512
+
+#endif /* INET__CONST_H */
+
+/*
+ * $PchId: const.h,v 1.7 2000/08/12 09:21:44 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/arp.c
===================================================================
--- /trunk/minix/servers/inet/generic/arp.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/arp.c	(revision 9)
@@ -0,0 +1,1359 @@
+/*
+arp.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "type.h"
+
+#include "arp.h"
+#include "assert.h"
+#include "buf.h"
+#include "clock.h"
+#include "event.h"
+#include "eth.h"
+#include "io.h"
+#include "sr.h"
+
+THIS_FILE
+
+#define ARP_CACHE_NR	 256
+#define AP_REQ_NR	  32
+
+#define ARP_HASH_NR	256
+#define ARP_HASH_MASK	0xff
+#define ARP_HASH_WIDTH	4
+
+#define MAX_ARP_RETRIES		5
+#define ARP_TIMEOUT		(HZ/2+1)	/* .5 seconds */
+#ifndef ARP_EXP_TIME
+#define ARP_EXP_TIME		(20L*60L*HZ)	/* 20 minutes */
+#endif
+#define ARP_NOTRCH_EXP_TIME	(30*HZ)		/* 30 seconds */
+#define ARP_INUSE_OFFSET	(60*HZ)	/* an entry in the cache can be deleted
+					   if its not used for 1 minute */
+
+typedef struct arp46
+{
+	ether_addr_t a46_dstaddr;
+	ether_addr_t a46_srcaddr;
+	ether_type_t a46_ethtype;
+	union
+	{
+		struct
+		{
+			u16_t a_hdr, a_pro;
+			u8_t a_hln, a_pln;
+			u16_t a_op;
+			ether_addr_t a_sha;
+			u8_t a_spa[4];
+			ether_addr_t a_tha;
+			u8_t a_tpa[4];
+		} a46_data;
+		char    a46_dummy[ETH_MIN_PACK_SIZE-ETH_HDR_SIZE];
+	} a46_data;
+} arp46_t;
+
+#define a46_hdr a46_data.a46_data.a_hdr
+#define a46_pro a46_data.a46_data.a_pro
+#define a46_hln a46_data.a46_data.a_hln
+#define a46_pln a46_data.a46_data.a_pln
+#define a46_op a46_data.a46_data.a_op
+#define a46_sha a46_data.a46_data.a_sha
+#define a46_spa a46_data.a46_data.a_spa
+#define a46_tha a46_data.a46_data.a_tha
+#define a46_tpa a46_data.a46_data.a_tpa
+
+typedef struct arp_port
+{
+	int ap_flags;
+	int ap_state;
+	int ap_eth_port;
+	int ap_ip_port;
+	int ap_eth_fd;
+
+	ether_addr_t ap_ethaddr;	/* Ethernet address of this port */
+	ipaddr_t ap_ipaddr;		/* IP address of this port */
+
+	struct arp_req
+	{
+		timer_t ar_timer;
+		int ar_entry;
+		int ar_req_count;
+	} ap_req[AP_REQ_NR];
+
+	arp_func_t ap_arp_func;
+
+	acc_t *ap_sendpkt;
+	acc_t *ap_sendlist;
+	acc_t *ap_reclist;
+	event_t ap_event;
+} arp_port_t;
+
+#define APF_EMPTY	0x00
+#define APF_ARP_RD_IP	0x01
+#define APF_ARP_RD_SP	0x02
+#define APF_ARP_WR_IP	0x04
+#define APF_ARP_WR_SP	0x08
+#define APF_INADDR_SET	0x10
+#define APF_SUSPEND	0x20
+
+#define APS_INITIAL	1
+#define	APS_GETADDR	2
+#define	APS_ARPSTART	3
+#define	APS_ARPPROTO	4
+#define	APS_ARPMAIN	5
+#define	APS_ERROR	6
+
+typedef struct arp_cache
+{
+	int ac_flags;
+	int ac_state;
+	ether_addr_t ac_ethaddr;
+	ipaddr_t ac_ipaddr;
+	arp_port_t *ac_port;
+	time_t ac_expire;
+	time_t ac_lastuse;
+} arp_cache_t;
+
+#define ACF_EMPTY	0
+#define ACF_PERM	1
+#define ACF_PUB		2
+
+#define ACS_UNUSED	0
+#define ACS_INCOMPLETE	1
+#define ACS_VALID	2
+#define ACS_UNREACHABLE	3
+
+PRIVATE struct arp_hash_ent
+{
+	arp_cache_t *ahe_row[ARP_HASH_WIDTH];
+} arp_hash[ARP_HASH_NR];
+
+PRIVATE arp_port_t *arp_port_table;
+PRIVATE	arp_cache_t *arp_cache;
+PRIVATE int arp_cache_nr;
+
+FORWARD acc_t *arp_getdata ARGS(( int fd, size_t offset,
+	size_t count, int for_ioctl ));
+FORWARD int arp_putdata ARGS(( int fd, size_t offset,
+	acc_t *data, int for_ioctl ));
+FORWARD void arp_main ARGS(( arp_port_t *arp_port ));
+FORWARD void arp_timeout ARGS(( int ref, timer_t *timer ));
+FORWARD void setup_write ARGS(( arp_port_t *arp_port ));
+FORWARD void setup_read ARGS(( arp_port_t *arp_port ));
+FORWARD void do_reclist ARGS(( event_t *ev, ev_arg_t ev_arg ));
+FORWARD void process_arp_pkt ARGS(( arp_port_t *arp_port, acc_t *data ));
+FORWARD void client_reply ARGS(( arp_port_t *arp_port,
+	ipaddr_t ipaddr, ether_addr_t *ethaddr ));
+FORWARD arp_cache_t *find_cache_ent ARGS(( arp_port_t *arp_port,
+	ipaddr_t ipaddr ));
+FORWARD arp_cache_t *alloc_cache_ent ARGS(( int flags ));
+FORWARD void arp_buffree ARGS(( int priority ));
+#ifdef BUF_CONSISTENCY_CHECK
+FORWARD void arp_bufcheck ARGS(( void ));
+#endif
+
+PUBLIC void arp_prep()
+{
+	arp_port_table= alloc(eth_conf_nr * sizeof(arp_port_table[0]));
+
+	arp_cache_nr= ARP_CACHE_NR;
+	if (arp_cache_nr < (eth_conf_nr+1)*AP_REQ_NR)
+	{
+		arp_cache_nr= (eth_conf_nr+1)*AP_REQ_NR;
+		printf("arp: using %d cache entries instead of %d\n",
+			arp_cache_nr, ARP_CACHE_NR);
+	}
+	arp_cache= alloc(arp_cache_nr * sizeof(arp_cache[0]));
+}
+
+PUBLIC void arp_init()
+{
+	arp_port_t *arp_port;
+	arp_cache_t *cache;
+	int i;
+
+	assert (BUF_S >= sizeof(struct nwio_ethstat));
+	assert (BUF_S >= sizeof(struct nwio_ethopt));
+	assert (BUF_S >= sizeof(arp46_t));
+
+	for (i=0, arp_port= arp_port_table; i<eth_conf_nr; i++, arp_port++)
+	{
+		arp_port->ap_state= APS_ERROR;	/* Mark all ports as
+						 * unavailable */
+	}
+
+	cache= arp_cache;
+	for (i=0; i<arp_cache_nr; i++, cache++)
+	{
+		cache->ac_state= ACS_UNUSED;
+		cache->ac_flags= ACF_EMPTY;
+		cache->ac_expire= 0;
+		cache->ac_lastuse= 0;
+	}
+
+#ifndef BUF_CONSISTENCY_CHECK
+	bf_logon(arp_buffree);
+#else
+	bf_logon(arp_buffree, arp_bufcheck);
+#endif
+}
+
+PRIVATE void arp_main(arp_port)
+arp_port_t *arp_port;
+{
+	int result;
+
+	switch (arp_port->ap_state)
+	{
+	case APS_INITIAL:
+		arp_port->ap_eth_fd= eth_open(arp_port->ap_eth_port,
+			arp_port->ap_eth_port, arp_getdata, arp_putdata,
+			0 /* no put_pkt */, 0 /* no select_res */);
+
+		if (arp_port->ap_eth_fd<0)
+		{
+			DBLOCK(1, printf("arp[%d]: unable to open eth[%d]\n",
+				arp_port-arp_port_table,
+				arp_port->ap_eth_port));
+			return;
+		}
+
+		arp_port->ap_state= APS_GETADDR;
+
+		result= eth_ioctl (arp_port->ap_eth_fd, NWIOGETHSTAT);
+
+		if ( result == NW_SUSPEND)
+		{
+			arp_port->ap_flags |= APF_SUSPEND;
+			return;
+		}
+		assert(result == NW_OK);
+
+		/* fall through */
+	case APS_GETADDR:
+		/* Wait for IP address */
+		if (!(arp_port->ap_flags & APF_INADDR_SET))
+			return;
+
+		/* fall through */
+	case APS_ARPSTART:
+		arp_port->ap_state= APS_ARPPROTO;
+
+		result= eth_ioctl (arp_port->ap_eth_fd, NWIOSETHOPT);
+
+		if (result==NW_SUSPEND)
+		{
+			arp_port->ap_flags |= APF_SUSPEND;
+			return;
+		}
+		assert(result == NW_OK);
+
+		/* fall through */
+	case APS_ARPPROTO:
+		arp_port->ap_state= APS_ARPMAIN;
+		setup_write(arp_port);
+		setup_read(arp_port);
+		return;
+
+	default:
+		ip_panic((
+		 "arp_main(&arp_port_table[%d]) called but ap_state=0x%x\n",
+			arp_port->ap_eth_port, arp_port->ap_state ));
+	}
+}
+
+PRIVATE acc_t *arp_getdata (fd, offset, count, for_ioctl)
+int fd;
+size_t offset;
+size_t count;
+int for_ioctl;
+{
+	arp_port_t *arp_port;
+	acc_t *data;
+	int result;
+
+	arp_port= &arp_port_table[fd];
+
+	switch (arp_port->ap_state)
+	{
+	case APS_ARPPROTO:
+		if (!count)
+		{
+			result= (int)offset;
+			if (result<0)
+			{
+				arp_port->ap_state= APS_ERROR;
+				break;
+			}
+			if (arp_port->ap_flags & APF_SUSPEND)
+			{
+				arp_port->ap_flags &= ~APF_SUSPEND;
+				arp_main(arp_port);
+			}
+			return NW_OK;
+		}
+		assert ((!offset) && (count == sizeof(struct nwio_ethopt)));
+		{
+			struct nwio_ethopt *ethopt;
+			acc_t *acc;
+
+			acc= bf_memreq(sizeof(*ethopt));
+			ethopt= (struct nwio_ethopt *)ptr2acc_data(acc);
+			ethopt->nweo_flags= NWEO_COPY|NWEO_EN_BROAD|
+				NWEO_TYPESPEC;
+			ethopt->nweo_type= HTONS(ETH_ARP_PROTO);
+			return acc;
+		}
+	case APS_ARPMAIN:
+		assert (arp_port->ap_flags & APF_ARP_WR_IP);
+		if (!count)
+		{
+			data= arp_port->ap_sendpkt;
+			arp_port->ap_sendpkt= NULL;
+			assert(data);
+			bf_afree(data); data= NULL;
+
+			result= (int)offset;
+			if (result<0)
+			{
+				DIFBLOCK(1, (result != NW_SUSPEND),
+					printf(
+				"arp[%d]: write error on port %d: error %d\n",
+					fd, arp_port->ap_eth_fd, result));
+
+				arp_port->ap_state= APS_ERROR;
+				break;
+			}
+			arp_port->ap_flags &= ~APF_ARP_WR_IP;
+			if (arp_port->ap_flags & APF_ARP_WR_SP)
+				setup_write(arp_port);
+			return NW_OK;
+		}
+		assert (offset+count <= sizeof(arp46_t));
+		data= arp_port->ap_sendpkt;
+		assert(data);
+		data= bf_cut(data, offset, count);
+
+		return data;
+	default:
+		printf("arp_getdata(%d, 0x%d, 0x%d) called but ap_state=0x%x\n",
+			fd, offset, count, arp_port->ap_state);
+		break;
+	}
+	return 0;
+}
+
+PRIVATE int arp_putdata (fd, offset, data, for_ioctl)
+int fd;
+size_t offset;
+acc_t *data;
+int for_ioctl;
+{
+	arp_port_t *arp_port;
+	int result;
+	struct nwio_ethstat *ethstat;
+	ev_arg_t ev_arg;
+	acc_t *tmpacc;
+
+	arp_port= &arp_port_table[fd];
+
+	if (arp_port->ap_flags & APF_ARP_RD_IP)
+	{
+		if (!data)
+		{
+			result= (int)offset;
+			if (result<0)
+			{
+				DIFBLOCK(1, (result != NW_SUSPEND), printf(
+				"arp[%d]: read error on port %d: error %d\n",
+					fd, arp_port->ap_eth_fd, result));
+
+				return NW_OK;
+			}
+			if (arp_port->ap_flags & APF_ARP_RD_SP)
+			{
+				arp_port->ap_flags &= ~(APF_ARP_RD_IP|
+					APF_ARP_RD_SP);
+				setup_read(arp_port);
+			}
+			else
+				arp_port->ap_flags &= ~(APF_ARP_RD_IP|
+					APF_ARP_RD_SP);
+			return NW_OK;
+		}
+		assert (!offset);
+		/* Warning: the above assertion is illegal; puts and gets of
+		   data can be brokenup in any piece the server likes. However
+		   we assume that the server is eth.c and it transfers only
+		   whole packets.
+		   */
+		data= bf_packIffLess(data, sizeof(arp46_t));
+		if (data->acc_length >= sizeof(arp46_t))
+		{
+			if (!arp_port->ap_reclist)
+			{
+				ev_arg.ev_ptr= arp_port;
+				ev_enqueue(&arp_port->ap_event, do_reclist,
+					ev_arg);
+			}
+			if (data->acc_linkC != 1)
+			{
+				tmpacc= bf_dupacc(data);
+				bf_afree(data);
+				data= tmpacc;
+				tmpacc= NULL;
+			}
+			data->acc_ext_link= arp_port->ap_reclist;
+			arp_port->ap_reclist= data;
+		}
+		else
+			bf_afree(data);
+		return NW_OK;
+	}
+	switch (arp_port->ap_state)
+	{
+	case APS_GETADDR:
+		if (!data)
+		{
+			result= (int)offset;
+			if (result<0)
+			{
+				arp_port->ap_state= APS_ERROR;
+				break;
+			}
+			if (arp_port->ap_flags & APF_SUSPEND)
+			{
+				arp_port->ap_flags &= ~APF_SUSPEND;
+				arp_main(arp_port);
+			}
+			return NW_OK;
+		}
+		compare (bf_bufsize(data), ==, sizeof(*ethstat));
+		data= bf_packIffLess(data, sizeof(*ethstat));
+		compare (data->acc_length, ==, sizeof(*ethstat));
+		ethstat= (struct nwio_ethstat *)ptr2acc_data(data);
+		arp_port->ap_ethaddr= ethstat->nwes_addr;
+		bf_afree(data);
+		return NW_OK;
+	default:
+		printf("arp_putdata(%d, 0x%d, 0x%lx) called but ap_state=0x%x\n",
+			fd, offset, (unsigned long)data, arp_port->ap_state);
+		break;
+	}
+	return EGENERIC;
+}
+
+PRIVATE void setup_read(arp_port)
+arp_port_t *arp_port;
+{
+	int result;
+
+	while (!(arp_port->ap_flags & APF_ARP_RD_IP))
+	{
+		arp_port->ap_flags |= APF_ARP_RD_IP;
+		result= eth_read (arp_port->ap_eth_fd, ETH_MAX_PACK_SIZE);
+		if (result == NW_SUSPEND)
+		{
+			arp_port->ap_flags |= APF_ARP_RD_SP;
+			return;
+		}
+		DIFBLOCK(1, (result != NW_OK),
+			printf("arp[%d]: eth_read(..,%d)=%d\n",
+			arp_port-arp_port_table, ETH_MAX_PACK_SIZE, result));
+	}
+}
+
+PRIVATE void setup_write(arp_port)
+arp_port_t *arp_port;
+{
+	int result;
+	acc_t *data;
+
+	for(;;)
+	{
+		data= arp_port->ap_sendlist;
+		if (!data)
+			break;
+		arp_port->ap_sendlist= data->acc_ext_link;
+
+		if (arp_port->ap_ipaddr == HTONL(0x00000000))
+		{
+			/* Interface is down */
+			printf(
+		"arp[%d]: not sending ARP packet, interface is down\n",
+				arp_port-arp_port_table);
+			bf_afree(data); data= NULL;
+			continue;
+		}
+
+		assert(!arp_port->ap_sendpkt);
+		arp_port->ap_sendpkt= data; data= NULL;
+			
+		arp_port->ap_flags= (arp_port->ap_flags & ~APF_ARP_WR_SP) |
+			APF_ARP_WR_IP;
+		result= eth_write(arp_port->ap_eth_fd, sizeof(arp46_t));
+		if (result == NW_SUSPEND)
+		{
+			arp_port->ap_flags |= APF_ARP_WR_SP;
+			break;
+		}
+		if (result<0)
+		{
+			DIFBLOCK(1, (result != NW_SUSPEND),
+				printf("arp[%d]: eth_write(..,%d)=%d\n",
+				arp_port-arp_port_table, sizeof(arp46_t),
+				result));
+			return;
+		}
+	}
+}
+
+PRIVATE void do_reclist(ev, ev_arg)
+event_t *ev;
+ev_arg_t ev_arg;
+{
+	arp_port_t *arp_port;
+	acc_t *data;
+
+	arp_port= ev_arg.ev_ptr;
+	assert(ev == &arp_port->ap_event);
+
+	while (data= arp_port->ap_reclist, data != NULL)
+	{
+		arp_port->ap_reclist= data->acc_ext_link;
+		process_arp_pkt(arp_port, data);
+		bf_afree(data);
+	}
+}
+
+PRIVATE void process_arp_pkt (arp_port, data)
+arp_port_t *arp_port;
+acc_t *data;
+{
+	int i, entry, do_reply;
+	arp46_t *arp;
+	u16_t *p;
+	arp_cache_t *ce, *cache;
+	struct arp_req *reqp;
+	time_t curr_time;
+	ipaddr_t spa, tpa;
+
+	curr_time= get_time();
+
+	arp= (arp46_t *)ptr2acc_data(data);
+	memcpy(&spa, arp->a46_spa, sizeof(ipaddr_t));
+	memcpy(&tpa, arp->a46_tpa, sizeof(ipaddr_t));
+
+	if (arp->a46_hdr != HTONS(ARP_ETHERNET) ||
+		arp->a46_hln != 6 ||
+		arp->a46_pro != HTONS(ETH_IP_PROTO) ||
+		arp->a46_pln != 4)
+		return;
+	if (arp_port->ap_ipaddr == HTONL(0x00000000))
+	{
+		/* Interface is down */
+#if DEBUG
+		printf("arp[%d]: dropping ARP packet, interface is down\n",
+			arp_port-arp_port_table);
+#endif
+		return;
+	}
+
+	ce= find_cache_ent(arp_port, spa);
+	cache= NULL;	/* lint */
+
+	do_reply= 0;
+	if (arp->a46_op != HTONS(ARP_REQUEST))
+		;	/* No need to reply */
+	else if (tpa == arp_port->ap_ipaddr)
+		do_reply= 1;
+	else
+	{
+		/* Look for a published entry */
+		cache= find_cache_ent(arp_port, tpa);
+		if (cache)
+		{
+			if (cache->ac_flags & ACF_PUB)
+			{
+				/* Published entry */
+				do_reply= 1;
+			}
+			else
+			{
+				/* Nothing to do */
+				cache= NULL;
+			}
+		}
+	}
+
+	if (ce == NULL)
+	{
+		if (!do_reply)
+			return;
+
+		DBLOCK(0x10, printf("arp[%d]: allocating entry for ",
+			arp_port-arp_port_table);
+			writeIpAddr(spa); printf("\n"));
+
+		ce= alloc_cache_ent(ACF_EMPTY);
+		ce->ac_flags= ACF_EMPTY;
+		ce->ac_state= ACS_VALID;
+		ce->ac_ethaddr= arp->a46_sha;
+		ce->ac_ipaddr= spa;
+		ce->ac_port= arp_port;
+		ce->ac_expire= curr_time+ARP_EXP_TIME;
+		ce->ac_lastuse= curr_time-ARP_INUSE_OFFSET; /* never used */
+	}
+
+	if (ce->ac_state == ACS_INCOMPLETE || ce->ac_state == ACS_UNREACHABLE)
+	{
+		ce->ac_ethaddr= arp->a46_sha;
+		if (ce->ac_state == ACS_INCOMPLETE)
+		{
+			/* Find request entry */
+			entry= ce-arp_cache;
+			for (i= 0, reqp= arp_port->ap_req; i<AP_REQ_NR; 
+				i++, reqp++)
+			{
+				if (reqp->ar_entry == entry)
+					break;
+			}
+			assert(i < AP_REQ_NR);
+			clck_untimer(&reqp->ar_timer);
+			reqp->ar_entry= -1;
+			
+			ce->ac_state= ACS_VALID;
+			client_reply(arp_port, spa, &arp->a46_sha);
+		}
+		else
+			ce->ac_state= ACS_VALID;
+	}
+
+	/* Update fields in the arp cache. */
+	if (memcmp(&ce->ac_ethaddr, &arp->a46_sha,
+		sizeof(ce->ac_ethaddr)) != 0)
+	{
+		printf("arp[%d]: ethernet address for IP address ",
+			arp_port-arp_port_table);
+		writeIpAddr(spa);
+		printf(" changed from ");
+		writeEtherAddr(&ce->ac_ethaddr);
+		printf(" to ");
+		writeEtherAddr(&arp->a46_sha);
+		printf("\n");
+		ce->ac_ethaddr= arp->a46_sha;
+	}
+	ce->ac_expire= curr_time+ARP_EXP_TIME;
+
+	if (do_reply)
+	{
+		data= bf_memreq(sizeof(arp46_t));
+		arp= (arp46_t *)ptr2acc_data(data);
+
+		/* Clear padding */
+		assert(sizeof(arp->a46_data.a46_dummy) % sizeof(*p) == 0);
+		for (i= 0, p= (u16_t *)arp->a46_data.a46_dummy;
+			i < sizeof(arp->a46_data.a46_dummy)/sizeof(*p);
+			i++, p++)
+		{
+			*p= 0xdead;
+		}
+
+		arp->a46_dstaddr= ce->ac_ethaddr;
+		arp->a46_hdr= HTONS(ARP_ETHERNET);
+		arp->a46_pro= HTONS(ETH_IP_PROTO);
+		arp->a46_hln= 6;
+		arp->a46_pln= 4;
+
+		arp->a46_op= htons(ARP_REPLY);
+		if (tpa == arp_port->ap_ipaddr)
+		{
+			arp->a46_sha= arp_port->ap_ethaddr;
+		}
+		else
+		{
+			assert(cache);
+			arp->a46_sha= cache->ac_ethaddr;
+		}
+		memcpy (arp->a46_spa, &tpa, sizeof(ipaddr_t));
+		arp->a46_tha= ce->ac_ethaddr;
+		memcpy (arp->a46_tpa, &ce->ac_ipaddr, sizeof(ipaddr_t));
+
+		assert(data->acc_linkC == 1);
+		data->acc_ext_link= arp_port->ap_sendlist;
+		arp_port->ap_sendlist= data; data= NULL;
+
+		if (!(arp_port->ap_flags & APF_ARP_WR_IP))
+			setup_write(arp_port);
+	}
+}
+
+PRIVATE void client_reply (arp_port, ipaddr, ethaddr)
+arp_port_t *arp_port;
+ipaddr_t ipaddr;
+ether_addr_t *ethaddr;
+{
+	(*arp_port->ap_arp_func)(arp_port->ap_ip_port, ipaddr, ethaddr);
+}
+
+PRIVATE arp_cache_t *find_cache_ent (arp_port, ipaddr)
+arp_port_t *arp_port;
+ipaddr_t ipaddr;
+{
+	arp_cache_t *ce;
+	int i;
+	unsigned hash;
+
+	hash= (ipaddr >> 24) ^ (ipaddr >> 16) ^ (ipaddr >> 8) ^ ipaddr;
+	hash &= ARP_HASH_MASK;
+
+	ce= arp_hash[hash].ahe_row[0];
+	if (ce && ce->ac_ipaddr == ipaddr && ce->ac_port == arp_port &&
+		ce->ac_state != ACS_UNUSED)
+	{
+		return ce;
+	}
+	for (i= 1; i<ARP_HASH_WIDTH; i++)
+	{
+		ce= arp_hash[hash].ahe_row[i];
+		if (!ce || ce->ac_ipaddr != ipaddr || ce->ac_port != arp_port
+			|| ce->ac_state == ACS_UNUSED)
+		{
+			continue;
+		}
+		arp_hash[hash].ahe_row[i]= arp_hash[hash].ahe_row[0];
+		arp_hash[hash].ahe_row[0]= ce;
+		return ce;
+	}
+
+	for (i=0, ce= arp_cache; i<arp_cache_nr; i++, ce++)
+	{
+		if (ce->ac_state != ACS_UNUSED &&
+			ce->ac_port == arp_port &&
+			ce->ac_ipaddr == ipaddr)
+		{
+			for (i= ARP_HASH_WIDTH-1; i>0; i--)
+			{
+				arp_hash[hash].ahe_row[i]=
+					arp_hash[hash].ahe_row[i-1];
+			}
+			assert(i == 0);
+			arp_hash[hash].ahe_row[0]= ce;
+			return ce;
+		}
+	}
+	return NULL;
+}
+
+PRIVATE arp_cache_t *alloc_cache_ent(flags)
+int flags;
+{
+	arp_cache_t *cache, *old;
+	int i;
+
+	old= NULL;
+	for (i=0, cache= arp_cache; i<arp_cache_nr; i++, cache++)
+	{
+		if (cache->ac_state == ACS_UNUSED)
+		{
+			old= cache;
+			break;
+		}
+		if (cache->ac_state == ACS_INCOMPLETE)
+			continue;
+		if (cache->ac_flags & ACF_PERM)
+			continue;
+		if (!old || cache->ac_lastuse < old->ac_lastuse)
+			old= cache;
+	}
+	assert(old);
+
+	if (!flags)
+		return old;
+
+	/* Get next permanent entry */
+	for (i=0, cache= arp_cache; i<arp_cache_nr; i++, cache++)
+	{
+		if (cache->ac_state == ACS_UNUSED)
+			break;
+		if (cache->ac_flags & ACF_PERM)
+			continue;
+		break;
+	}
+	if (i >= arp_cache_nr/2)
+		return NULL; /* Too many entries */
+	if (cache != old)
+	{
+		assert(old > cache);
+		*old= *cache;
+		old= cache;
+	}
+
+	if (!(flags & ACF_PUB))
+		return old;
+
+	/* Get first nonpublished entry */
+	for (i=0, cache= arp_cache; i<arp_cache_nr; i++, cache++)
+	{
+		if (cache->ac_state == ACS_UNUSED)
+			break;
+		if (cache->ac_flags & ACF_PUB)
+			continue;
+		break;
+	}
+	if (cache != old)
+	{
+		assert(old > cache);
+		*old= *cache;
+		old= cache;
+	}
+	return old;
+}
+
+PUBLIC void arp_set_ipaddr (eth_port, ipaddr)
+int eth_port;
+ipaddr_t ipaddr;
+{
+	arp_port_t *arp_port;
+
+	if (eth_port < 0 || eth_port >= eth_conf_nr)
+		return;
+	arp_port= &arp_port_table[eth_port];
+
+	arp_port->ap_ipaddr= ipaddr;
+	arp_port->ap_flags |= APF_INADDR_SET;
+	arp_port->ap_flags &= ~APF_SUSPEND;
+	if (arp_port->ap_state == APS_GETADDR)
+		arp_main(arp_port);
+}
+
+PUBLIC int arp_set_cb(eth_port, ip_port, arp_func)
+int eth_port;
+int ip_port;
+arp_func_t arp_func;
+{
+	int i;
+	arp_port_t *arp_port;
+
+	assert(eth_port >= 0);
+	if (eth_port >= eth_conf_nr)
+		return ENXIO;
+
+	arp_port= &arp_port_table[eth_port];
+	arp_port->ap_eth_port= eth_port;
+	arp_port->ap_ip_port= ip_port;
+	arp_port->ap_state= APS_INITIAL;
+	arp_port->ap_flags= APF_EMPTY;
+	arp_port->ap_arp_func= arp_func;
+	arp_port->ap_sendpkt= NULL;
+	arp_port->ap_sendlist= NULL;
+	arp_port->ap_reclist= NULL;
+	for (i= 0; i<AP_REQ_NR; i++)
+		arp_port->ap_req[i].ar_entry= -1;
+	ev_init(&arp_port->ap_event);
+
+	arp_main(arp_port);
+
+	return NW_OK;
+}
+
+PUBLIC int arp_ip_eth (eth_port, ipaddr, ethaddr)
+int eth_port;
+ipaddr_t ipaddr;
+ether_addr_t *ethaddr;
+{
+	int i, ref;
+	arp_port_t *arp_port;
+	struct arp_req *reqp;
+	arp_cache_t *ce;
+	time_t curr_time;
+
+	assert(eth_port >= 0 && eth_port < eth_conf_nr);
+	arp_port= &arp_port_table[eth_port];
+	assert(arp_port->ap_state == APS_ARPMAIN ||
+		(printf("arp[%d]: ap_state= %d\n", arp_port-arp_port_table,
+		arp_port->ap_state), 0));
+
+	curr_time= get_time();
+
+	ce= find_cache_ent (arp_port, ipaddr);
+	if (ce && ce->ac_expire < curr_time)
+	{
+		assert(ce->ac_state != ACS_INCOMPLETE);
+
+		/* Check whether there is enough space for an ARP
+		 * request or not.
+		 */
+		for (i= 0, reqp= arp_port->ap_req; i<AP_REQ_NR; i++, reqp++)
+		{
+			if (reqp->ar_entry < 0)
+				break;
+		}
+		if (i < AP_REQ_NR)
+		{
+			/* Okay, expire this entry. */
+			ce->ac_state= ACS_UNUSED;
+			ce= NULL;
+		}
+		else
+		{
+			/* Continue using this entry for a while */
+			printf("arp[%d]: Overloaded! Keeping entry for ",
+				arp_port-arp_port_table);
+			writeIpAddr(ipaddr);
+			printf("\n");
+			ce->ac_expire= curr_time+ARP_NOTRCH_EXP_TIME;
+		}
+	}
+	if (ce)
+	{
+		/* Found an entry. This entry should be valid, unreachable
+		 * or incomplete.
+		 */
+		ce->ac_lastuse= curr_time;
+		if (ce->ac_state == ACS_VALID)
+		{
+			*ethaddr= ce->ac_ethaddr;
+			return NW_OK;
+		}
+		if (ce->ac_state == ACS_UNREACHABLE)
+			return EDSTNOTRCH;
+		assert(ce->ac_state == ACS_INCOMPLETE);
+
+		return NW_SUSPEND;
+	}
+
+	/* Find an empty slot for an ARP request */
+	for (i= 0, reqp= arp_port->ap_req; i<AP_REQ_NR; i++, reqp++)
+	{
+		if (reqp->ar_entry < 0)
+			break;
+	}
+	if (i >= AP_REQ_NR)
+	{
+		/* We should be able to report that this ARP request
+		 * cannot be accepted. At the moment we just return SUSPEND.
+		 */
+		return NW_SUSPEND;
+	}
+	ref= (eth_port*AP_REQ_NR + i);
+
+	ce= alloc_cache_ent(ACF_EMPTY);
+	ce->ac_flags= 0;
+	ce->ac_state= ACS_INCOMPLETE;
+	ce->ac_ipaddr= ipaddr;
+	ce->ac_port= arp_port;
+	ce->ac_expire= curr_time+ARP_EXP_TIME;
+	ce->ac_lastuse= curr_time;
+
+	reqp->ar_entry= ce-arp_cache;
+	reqp->ar_req_count= -1;
+
+	/* Send the first packet by expiring the timer */
+	clck_timer(&reqp->ar_timer, 1, arp_timeout, ref);
+
+	return NW_SUSPEND;
+}
+
+PUBLIC int arp_ioctl (eth_port, fd, req, get_userdata, put_userdata)
+int eth_port;
+int fd;
+ioreq_t req;
+get_userdata_t get_userdata;
+put_userdata_t put_userdata;
+{
+	arp_port_t *arp_port;
+	arp_cache_t *ce, *cache;
+	acc_t *data;
+	nwio_arp_t *arp_iop;
+	int entno, result, ac_flags;
+	u32_t flags;
+	ipaddr_t ipaddr;
+	time_t curr_time;
+
+	assert(eth_port >= 0 && eth_port < eth_conf_nr);
+	arp_port= &arp_port_table[eth_port];
+	assert(arp_port->ap_state == APS_ARPMAIN ||
+		(printf("arp[%d]: ap_state= %d\n", arp_port-arp_port_table,
+		arp_port->ap_state), 0));
+
+	switch(req)
+	{
+	case NWIOARPGIP:
+		data= (*get_userdata)(fd, 0, sizeof(*arp_iop), TRUE);
+		if (data == NULL)
+			return EFAULT;
+		data= bf_packIffLess(data, sizeof(*arp_iop));
+		arp_iop= (nwio_arp_t *)ptr2acc_data(data);
+		ipaddr= arp_iop->nwa_ipaddr;
+		ce= NULL;	/* lint */
+		for (entno= 0; entno < arp_cache_nr; entno++)
+		{
+			ce= &arp_cache[entno];
+			if (ce->ac_state == ACS_UNUSED ||
+				ce->ac_port != arp_port)
+			{
+				continue;
+			}
+			if (ce->ac_ipaddr == ipaddr)
+				break;
+		}
+		if (entno == arp_cache_nr)
+		{
+			/* Also report the address of this interface */
+			if (ipaddr != arp_port->ap_ipaddr)
+			{
+				bf_afree(data);
+				return ENOENT;
+			}
+			arp_iop->nwa_entno= arp_cache_nr;
+			arp_iop->nwa_ipaddr= ipaddr;
+			arp_iop->nwa_ethaddr= arp_port->ap_ethaddr;
+			arp_iop->nwa_flags= NWAF_PERM | NWAF_PUB;
+		}
+		else
+		{
+			arp_iop->nwa_entno= entno+1;
+			arp_iop->nwa_ipaddr= ce->ac_ipaddr;
+			arp_iop->nwa_ethaddr= ce->ac_ethaddr;
+			arp_iop->nwa_flags= 0;
+			if (ce->ac_state == ACS_INCOMPLETE)
+				arp_iop->nwa_flags |= NWAF_INCOMPLETE;
+			if (ce->ac_state == ACS_UNREACHABLE)
+				arp_iop->nwa_flags |= NWAF_DEAD;
+			if (ce->ac_flags & ACF_PERM)
+				arp_iop->nwa_flags |= NWAF_PERM;
+			if (ce->ac_flags & ACF_PUB)
+				arp_iop->nwa_flags |= NWAF_PUB;
+		}
+
+		result= (*put_userdata)(fd, 0, data, TRUE);
+		return result;
+
+	case NWIOARPGNEXT:
+		data= (*get_userdata)(fd, 0, sizeof(*arp_iop), TRUE);
+		if (data == NULL)
+			return EFAULT;
+		data= bf_packIffLess(data, sizeof(*arp_iop));
+		arp_iop= (nwio_arp_t *)ptr2acc_data(data);
+		entno= arp_iop->nwa_entno;
+		if (entno < 0)
+			entno= 0;
+		ce= NULL;	/* lint */
+		for (; entno < arp_cache_nr; entno++)
+		{
+			ce= &arp_cache[entno];
+			if (ce->ac_state == ACS_UNUSED ||
+				ce->ac_port != arp_port)
+			{
+				continue;
+			}
+			break;
+		}
+		if (entno == arp_cache_nr)
+		{
+			bf_afree(data);
+			return ENOENT;
+		}
+		arp_iop->nwa_entno= entno+1;
+		arp_iop->nwa_ipaddr= ce->ac_ipaddr;
+		arp_iop->nwa_ethaddr= ce->ac_ethaddr;
+		arp_iop->nwa_flags= 0;
+		if (ce->ac_state == ACS_INCOMPLETE)
+			arp_iop->nwa_flags |= NWAF_INCOMPLETE;
+		if (ce->ac_state == ACS_UNREACHABLE)
+			arp_iop->nwa_flags |= NWAF_DEAD;
+		if (ce->ac_flags & ACF_PERM)
+			arp_iop->nwa_flags |= NWAF_PERM;
+		if (ce->ac_flags & ACF_PUB)
+			arp_iop->nwa_flags |= NWAF_PUB;
+
+		result= (*put_userdata)(fd, 0, data, TRUE);
+		return result;
+
+	case NWIOARPSIP:
+		data= (*get_userdata)(fd, 0, sizeof(*arp_iop), TRUE);
+		if (data == NULL)
+			return EFAULT;
+		data= bf_packIffLess(data, sizeof(*arp_iop));
+		arp_iop= (nwio_arp_t *)ptr2acc_data(data);
+		ipaddr= arp_iop->nwa_ipaddr;
+		if (find_cache_ent(arp_port, ipaddr))
+		{
+			bf_afree(data);
+			return EEXIST;
+		}
+
+		flags= arp_iop->nwa_flags;
+		ac_flags= ACF_EMPTY;
+		if (flags & NWAF_PERM)
+			ac_flags |= ACF_PERM;
+		if (flags & NWAF_PUB)
+			ac_flags |= ACF_PUB|ACF_PERM;
+
+		/* Allocate a cache entry */
+		ce= alloc_cache_ent(ac_flags);
+		if (ce == NULL)
+		{
+			bf_afree(data);
+			return ENOMEM;
+		}
+
+		ce->ac_flags= ac_flags;
+		ce->ac_state= ACS_VALID;
+		ce->ac_ethaddr= arp_iop->nwa_ethaddr;
+		ce->ac_ipaddr= arp_iop->nwa_ipaddr;
+		ce->ac_port= arp_port;
+
+		curr_time= get_time();
+		ce->ac_expire= curr_time+ARP_EXP_TIME;
+		ce->ac_lastuse= curr_time;
+
+		bf_afree(data);
+		return 0;
+
+	case NWIOARPDIP:
+		data= (*get_userdata)(fd, 0, sizeof(*arp_iop), TRUE);
+		if (data == NULL)
+			return EFAULT;
+		data= bf_packIffLess(data, sizeof(*arp_iop));
+		arp_iop= (nwio_arp_t *)ptr2acc_data(data);
+		ipaddr= arp_iop->nwa_ipaddr;
+		bf_afree(data); data= NULL;
+		ce= find_cache_ent(arp_port, ipaddr);
+		if (!ce)
+			return ENOENT;
+		if (ce->ac_state == ACS_INCOMPLETE)
+			return EINVAL;
+
+		ac_flags= ce->ac_flags;
+		if (ac_flags & ACF_PUB)
+		{
+			/* Make sure entry is at the end of published
+			 * entries.
+			 */
+			for (entno= 0, cache= arp_cache;
+				entno<arp_cache_nr; entno++, cache++)
+			{
+				if (cache->ac_state == ACS_UNUSED)
+					break;
+				if (cache->ac_flags & ACF_PUB)
+					continue;
+				break;
+			}
+			assert(cache > arp_cache);
+			cache--;
+			if (cache != ce)
+			{
+				assert(cache > ce);
+				*ce= *cache;
+				ce= cache;
+			}
+		}
+		if (ac_flags & ACF_PERM)
+		{
+			/* Make sure entry is at the end of permanent
+			 * entries.
+			 */
+			for (entno= 0, cache= arp_cache;
+				entno<arp_cache_nr; entno++, cache++)
+			{
+				if (cache->ac_state == ACS_UNUSED)
+					break;
+				if (cache->ac_flags & ACF_PERM)
+					continue;
+				break;
+			}
+			assert(cache > arp_cache);
+			cache--;
+			if (cache != ce)
+			{
+				assert(cache > ce);
+				*ce= *cache;
+				ce= cache;
+			}
+		}
+
+		/* Clear entry */
+		ce->ac_state= ACS_UNUSED;
+
+		return 0;
+
+	default:
+		ip_panic(("arp_ioctl: unknown request 0x%lx",
+			(unsigned long)req));
+	}
+	return 0;
+}
+
+PRIVATE void arp_timeout (ref, timer)
+int ref;
+timer_t *timer;
+{
+	int i, port, reqind, acind;
+	arp_port_t *arp_port;
+	arp_cache_t *ce;
+	struct arp_req *reqp;
+	time_t curr_time;
+	acc_t *data;
+	arp46_t *arp;
+	u16_t *p;
+
+	port= ref / AP_REQ_NR;
+	reqind= ref % AP_REQ_NR;
+
+	assert(port >= 0 && port <eth_conf_nr);
+	arp_port= &arp_port_table[port];
+
+	reqp= &arp_port->ap_req[reqind];
+	assert (timer == &reqp->ar_timer);
+
+	acind= reqp->ar_entry;
+
+	assert(acind >= 0 && acind < arp_cache_nr);
+	ce= &arp_cache[acind];
+
+	assert(ce->ac_port == arp_port);
+	assert(ce->ac_state == ACS_INCOMPLETE);
+
+	if (++reqp->ar_req_count >= MAX_ARP_RETRIES)
+	{
+		curr_time= get_time();
+		ce->ac_state= ACS_UNREACHABLE;
+		ce->ac_expire= curr_time+ ARP_NOTRCH_EXP_TIME;
+		ce->ac_lastuse= curr_time;
+
+		clck_untimer(&reqp->ar_timer);
+		reqp->ar_entry= -1;
+		client_reply(arp_port, ce->ac_ipaddr, NULL);
+		return;
+	}
+
+	data= bf_memreq(sizeof(arp46_t));
+	arp= (arp46_t *)ptr2acc_data(data);
+
+	/* Clear padding */
+	assert(sizeof(arp->a46_data.a46_dummy) % sizeof(*p) == 0);
+	for (i= 0, p= (u16_t *)arp->a46_data.a46_dummy;
+		i < sizeof(arp->a46_data.a46_dummy)/sizeof(*p);
+		i++, p++)
+	{
+		*p= 0xdead;
+	}
+
+	arp->a46_dstaddr.ea_addr[0]= 0xff;
+	arp->a46_dstaddr.ea_addr[1]= 0xff;
+	arp->a46_dstaddr.ea_addr[2]= 0xff;
+	arp->a46_dstaddr.ea_addr[3]= 0xff;
+	arp->a46_dstaddr.ea_addr[4]= 0xff;
+	arp->a46_dstaddr.ea_addr[5]= 0xff;
+	arp->a46_hdr= HTONS(ARP_ETHERNET);
+	arp->a46_pro= HTONS(ETH_IP_PROTO);
+	arp->a46_hln= 6;
+	arp->a46_pln= 4;
+	arp->a46_op= HTONS(ARP_REQUEST);
+	arp->a46_sha= arp_port->ap_ethaddr;
+	memcpy (arp->a46_spa, &arp_port->ap_ipaddr, sizeof(ipaddr_t));
+	memset(&arp->a46_tha, '\0', sizeof(ether_addr_t));
+	memcpy (arp->a46_tpa, &ce->ac_ipaddr, sizeof(ipaddr_t));
+
+	assert(data->acc_linkC == 1);
+	data->acc_ext_link= arp_port->ap_sendlist;
+	arp_port->ap_sendlist= data; data= NULL;
+
+	if (!(arp_port->ap_flags & APF_ARP_WR_IP))
+		setup_write(arp_port);
+
+	clck_timer(&reqp->ar_timer, get_time() + ARP_TIMEOUT,
+		arp_timeout, ref);
+}
+
+PRIVATE void arp_buffree(priority)
+int priority;
+{
+	int i;
+	acc_t *pack, *next_pack;
+	arp_port_t *arp_port;
+
+	for (i= 0, arp_port= arp_port_table; i<eth_conf_nr; i++, arp_port++)
+	{
+		if (priority == ARP_PRI_REC)
+		{
+			next_pack= arp_port->ap_reclist;
+			while(next_pack && next_pack->acc_ext_link)
+			{
+				pack= next_pack;
+				next_pack= pack->acc_ext_link;
+				bf_afree(pack);
+			}
+			if (next_pack)
+			{
+				if (ev_in_queue(&arp_port->ap_event))
+				{
+					DBLOCK(1, printf(
+			"not freeing ap_reclist, ap_event enqueued\n"));
+				}
+				else
+				{
+					bf_afree(next_pack);
+					next_pack= NULL;
+				}
+			}
+			arp_port->ap_reclist= next_pack;
+		}
+		if (priority == ARP_PRI_SEND)
+		{
+			next_pack= arp_port->ap_sendlist;
+			while(next_pack && next_pack->acc_ext_link)
+			{
+				pack= next_pack;
+				next_pack= pack->acc_ext_link;
+				bf_afree(pack);
+			}
+			if (next_pack)
+			{
+				if (ev_in_queue(&arp_port->ap_event))
+				{
+					DBLOCK(1, printf(
+			"not freeing ap_sendlist, ap_event enqueued\n"));
+				}
+				else
+				{
+					bf_afree(next_pack);
+					next_pack= NULL;
+				}
+			}
+			arp_port->ap_sendlist= next_pack;
+		}
+	}
+}
+
+#ifdef BUF_CONSISTENCY_CHECK
+PRIVATE void arp_bufcheck()
+{
+	int i;
+	arp_port_t *arp_port;
+	acc_t *pack;
+
+	for (i= 0, arp_port= arp_port_table; i<eth_conf_nr; i++, arp_port++)
+	{
+		for (pack= arp_port->ap_reclist; pack;
+			pack= pack->acc_ext_link)
+		{
+			bf_check_acc(pack);
+		}
+		for (pack= arp_port->ap_sendlist; pack;
+			pack= pack->acc_ext_link)
+		{
+			bf_check_acc(pack);
+		}
+	}
+}
+#endif /* BUF_CONSISTENCY_CHECK */
+
+/*
+ * $PchId: arp.c,v 1.22 2005/06/28 14:15:06 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/arp.h
===================================================================
--- /trunk/minix/servers/inet/generic/arp.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/arp.h	(revision 9)
@@ -0,0 +1,32 @@
+/*
+arp.h
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef ARP_H
+#define ARP_H
+
+#define ARP_ETHERNET	1
+
+#define ARP_REQUEST	1
+#define ARP_REPLY	2
+
+/* Prototypes */
+typedef void (*arp_func_t) ARGS(( int fd, ipaddr_t ipaddr,
+	ether_addr_t *ethaddr ));
+
+void arp_prep ARGS(( void ));
+void arp_init ARGS(( void ));
+void arp_set_ipaddr ARGS(( int eth_port, ipaddr_t ipaddr ));
+int arp_set_cb ARGS(( int eth_port, int ip_port, arp_func_t arp_func ));
+int arp_ip_eth ARGS(( int eth_port, ipaddr_t ipaddr, ether_addr_t *ethaddr ));
+
+int arp_ioctl ARGS(( int eth_port, int fd, ioreq_t req,
+	get_userdata_t get_userdata, put_userdata_t put_userdata ));
+
+#endif /* ARP_H */
+
+/*
+ * $PchId: arp.h,v 1.7 2001/04/19 18:58:17 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/assert.h
===================================================================
--- /trunk/minix/servers/inet/generic/assert.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/assert.h	(revision 9)
@@ -0,0 +1,31 @@
+/*
+assert.h
+
+Copyright 1995 Philip Homburg
+*/
+#ifndef INET_ASSERT_H
+#define INET_ASSERT_H
+
+#if !NDEBUG
+
+void bad_assertion(char *file, int line, char *what) _NORETURN;
+void bad_compare(char *file, int line, int lhs, char *what, int rhs) _NORETURN;
+
+#define assert(x)	((void)(!(x) ? bad_assertion(this_file, __LINE__, \
+			#x),0 : 0))
+#define compare(a,t,b)	(!((a) t (b)) ? bad_compare(this_file, __LINE__, \
+				(a), #a " " #t " " #b, (b)) : (void) 0)
+
+#else /* NDEBUG */
+
+#define assert(x)		0
+#define compare(a,t,b)		0
+
+#endif /* NDEBUG */
+
+#endif /* INET_ASSERT_H */
+
+
+/*
+ * $PchId: assert.h,v 1.8 2002/03/18 21:50:32 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/buf.h
===================================================================
--- /trunk/minix/servers/inet/generic/buf.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/buf.h	(revision 9)
@@ -0,0 +1,249 @@
+/*
+buf.h
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef BUF_H
+#define BUF_H
+
+/* Note: BUF_S should be defined in const.h */
+
+#define MAX_BUFREQ_PRI	10
+
+#define ARP_PRI_REC		3
+#define ARP_PRI_SEND		3
+
+#define ETH_PRI_PORTBUFS	3
+#define ETH_PRI_FDBUFS_EXTRA	5
+#define ETH_PRI_FDBUFS		6
+
+#define IP_PRI_PORTBUFS		3
+#define IP_PRI_ASSBUFS		4
+#define IP_PRI_FDBUFS_EXTRA	5
+#define IP_PRI_FDBUFS		6
+
+#define ICMP_PRI_QUEUE		1
+
+#define TCP_PRI_FRAG2SEND	4
+#define TCP_PRI_CONN_EXTRA	5
+#define TCP_PRI_CONNwoUSER	7
+#define TCP_PRI_CONN_INUSE	9
+
+#define UDP_PRI_FDBUFS_EXTRA	5
+#define UDP_PRI_FDBUFS		6
+
+#define PSIP_PRI_EXP_PROMISC	2
+
+struct acc;
+typedef void (*buffree_t) ARGS(( struct acc *acc ));
+typedef void (*bf_freereq_t) ARGS(( int priority ));
+
+#ifdef BUF_CONSISTENCY_CHECK
+typedef void (*bf_checkreq_t) ARGS(( void ));
+#endif
+
+typedef struct buf
+{
+	int buf_linkC;
+	buffree_t buf_free;
+	size_t buf_size;
+	char *buf_data_p;
+
+#ifdef BUF_TRACK_ALLOC_FREE
+	char *buf_alloc_file;
+	int buf_alloc_line;
+	char *buf_free_file;
+	int buf_free_line;
+#endif
+#ifdef BUF_CONSISTENCY_CHECK
+	unsigned buf_generation;
+	int buf_check_linkC;
+#endif
+} buf_t;
+
+typedef struct acc
+{
+	int acc_linkC;
+	int acc_offset, acc_length;
+	buf_t *acc_buffer;
+	struct acc *acc_next, *acc_ext_link;
+
+#ifdef BUF_TRACK_ALLOC_FREE
+	char *acc_alloc_file;
+	int acc_alloc_line;
+	char *acc_free_file;
+	int acc_free_line;
+#endif
+#ifdef BUF_CONSISTENCY_CHECK
+	unsigned acc_generation;
+	int acc_check_linkC;
+#endif
+} acc_t;
+
+extern acc_t *bf_temporary_acc;
+extern acc_t *bf_linkcheck_acc;
+
+/* For debugging... */
+
+#ifdef BUF_TRACK_ALLOC_FREE
+
+#ifndef BUF_IMPLEMENTATION
+
+#define bf_memreq(a) _bf_memreq(this_file, __LINE__, a)
+#define bf_cut(a,b,c) _bf_cut(this_file, __LINE__, a, b, c)
+#define bf_delhead(a,b) _bf_delhead(this_file, __LINE__, a, b)
+#define bf_packIffLess(a,b) _bf_packIffLess(this_file, __LINE__, \
+									a, b)
+#define bf_afree(a) _bf_afree(this_file, __LINE__, a)
+#define bf_pack(a) _bf_pack(this_file, __LINE__, a)
+#define bf_append(a,b) _bf_append(this_file, __LINE__, a, b)
+#define bf_dupacc(a) _bf_dupacc(this_file, __LINE__, a)
+#if 0
+#define bf_mark_1acc(a) _bf_mark_1acc(this_file, __LINE__, a)
+#define bf_mark_acc(a) _bf_mark_acc(this_file, __LINE__, a)
+#endif
+#define bf_align(a,s,al) _bf_align(this_file, __LINE__, a, s, al)
+
+#else /* BUF_IMPLEMENTATION */
+
+#define bf_afree(a) _bf_afree(clnt_file, clnt_line, a)
+#define bf_pack(a) _bf_pack(clnt_file, clnt_line, a)
+#define bf_memreq(a) _bf_memreq(clnt_file, clnt_line, a)
+#define bf_dupacc(a) _bf_dupacc(clnt_file, clnt_line, a)
+#define bf_cut(a,b,c) _bf_cut(clnt_file, clnt_line, a, b, c)
+#define bf_delhead(a,b) _bf_delhead(clnt_file, clnt_line, a, b)
+#define bf_align(a,s,al) _bf_align(clnt_file, clnt_line, a, s, al)
+
+#endif /* !BUF_IMPLEMENTATION */
+
+#else
+
+#define bf_mark_1acc(acc)	((void)0)
+#define bf_mark_acc(acc)	((void)0)
+
+#endif /* BUF_TRACK_ALLOC_FREE */
+
+/* Prototypes */
+
+void bf_init ARGS(( void ));
+#ifndef BUF_CONSISTENCY_CHECK
+void bf_logon ARGS(( bf_freereq_t func ));
+#else
+void bf_logon ARGS(( bf_freereq_t func, bf_checkreq_t checkfunc ));
+#endif
+
+#ifndef BUF_TRACK_ALLOC_FREE
+acc_t *bf_memreq ARGS(( unsigned size));
+#else
+acc_t *_bf_memreq ARGS(( char *clnt_file, int clnt_line,
+			unsigned size));
+#endif
+/* the result is an acc with linkC == 1 */
+
+#ifndef BUF_TRACK_ALLOC_FREE
+acc_t *bf_dupacc ARGS(( acc_t *acc ));
+#else
+acc_t *_bf_dupacc ARGS(( char *clnt_file, int clnt_line,
+			acc_t *acc ));
+#endif
+/* the result is an acc with linkC == 1 identical to the given one */
+
+#ifndef BUF_TRACK_ALLOC_FREE
+void bf_afree ARGS(( acc_t *acc));
+#else
+void _bf_afree ARGS(( char *clnt_file, int clnt_line,
+			acc_t *acc));
+#endif
+/* this reduces the linkC off the given acc with one */
+
+#ifndef BUF_TRACK_ALLOC_FREE
+acc_t *bf_pack ARGS(( acc_t *pack));
+#else
+acc_t *_bf_pack ARGS(( char *clnt_file, int clnt_line,
+			acc_t *pack));
+#endif
+/* this gives a packed copy of the given acc, the linkC of the given acc is
+   reduced by one, the linkC of the result == 1 */
+
+#ifndef BUF_TRACK_ALLOC_FREE
+acc_t *bf_packIffLess ARGS(( acc_t *pack, int min_len ));
+#else
+acc_t *_bf_packIffLess ARGS(( char *clnt_file, int clnt_line,
+				acc_t *pack, int min_len ));
+#endif
+/* this performs a bf_pack iff pack->acc_length<min_len */
+
+size_t bf_bufsize ARGS(( acc_t *pack));
+/* this gives the length of the buffer specified by the given acc. The linkC
+   of the given acc remains the same */
+
+#ifndef BUF_TRACK_ALLOC_FREE
+acc_t *bf_cut ARGS(( acc_t *data, unsigned offset, unsigned length ));
+#else
+acc_t *_bf_cut ARGS(( char *clnt_file, int clnt_line,
+			acc_t *data, unsigned offset, unsigned length ));
+#endif
+/* the result is a cut of the buffer from offset with length length.
+   The linkC of the result == 1, the linkC of the given acc remains the
+   same. */
+
+#ifndef BUF_TRACK_ALLOC_FREE
+acc_t *bf_delhead ARGS(( acc_t *data, unsigned offset ));
+#else
+acc_t *_bf_delhead ARGS(( char *clnt_file, int clnt_line,
+			acc_t *data, unsigned offset ));
+#endif
+/* the result is a cut of the buffer from offset until the end.
+   The linkC of the result == 1, the linkC of the given acc is
+   decremented. */
+
+#ifndef BUF_TRACK_ALLOC_FREE
+acc_t *bf_append ARGS(( acc_t *data_first, acc_t  *data_second ));
+#else
+acc_t *_bf_append ARGS(( char *clnt_file, int clnt_line,
+			acc_t *data_first, acc_t  *data_second ));
+#endif
+/* data_second is appended after data_first, a link is returned to the
+	result and the linkCs of data_first and data_second are reduced.
+	further more, if the contents of the last part of data_first and
+	the first part of data_second fit in a buffer, both parts are
+	copied into a (possibly fresh) buffer
+*/
+
+#ifndef BUF_TRACK_ALLOC_FREE
+acc_t *bf_align ARGS(( acc_t *acc, size_t size, size_t alignment ));
+#else
+acc_t *_bf_align ARGS(( char *clnt_file, int clnt_line,
+			acc_t *acc, size_t size, size_t alignment ));
+#endif
+/* size bytes of acc (or all bytes of acc if the size buffer is smaller
+	than size) are aligned on an address that is multiple of alignment.
+	Size must be less than or equal to BUF_S.
+*/
+
+int bf_linkcheck ARGS(( acc_t *acc ));
+/* check if all link count are positive, and offsets and sizes are within 
+ * the underlying buffer.
+ */
+
+#define ptr2acc_data(/* acc_t * */ a) (bf_temporary_acc=(a), \
+	(&bf_temporary_acc->acc_buffer->buf_data_p[bf_temporary_acc-> \
+		acc_offset]))
+
+#define bf_chkbuf(buf) ((buf)? (compare((buf)->acc_linkC,>,0), \
+	compare((buf)->acc_buffer, !=, 0), \
+	compare((buf)->acc_buffer->buf_linkC,>,0)) : (void)0)
+
+#ifdef BUF_CONSISTENCY_CHECK
+int bf_consistency_check ARGS(( void ));
+void bf_check_acc ARGS(( acc_t *acc ));
+void _bf_mark_1acc ARGS(( char *clnt_file, int clnt_line, acc_t *acc ));
+void _bf_mark_acc ARGS(( char *clnt_file, int clnt_line, acc_t *acc ));
+#endif
+
+#endif /* BUF_H */
+
+/*
+ * $PchId: buf.h,v 1.13 2003/09/10 08:52:09 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/clock.h
===================================================================
--- /trunk/minix/servers/inet/generic/clock.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/clock.h	(revision 9)
@@ -0,0 +1,39 @@
+/*
+clock.h
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef CLOCK_H
+#define CLOCK_H
+
+struct timer;
+
+typedef void (*timer_func_t) ARGS(( int fd, struct timer *timer ));
+
+typedef struct timer
+{
+	struct timer *tim_next;
+	timer_func_t tim_func;
+	int tim_ref;
+	time_t tim_time;
+	int tim_active;
+} timer_t;
+
+extern int clck_call_expire;	/* Call clck_expire_timer from the mainloop */
+
+void clck_init ARGS(( void ));
+void set_time ARGS(( time_t time ));
+time_t get_time ARGS(( void ));
+void reset_time ARGS(( void ));
+/* set a timer to go off at the time specified by timeout */
+void clck_timer ARGS(( struct timer *timer, time_t timeout, timer_func_t func,
+								int fd ));
+void clck_untimer ARGS(( struct timer *timer ));
+void clck_expire_timers ARGS(( void ));
+
+#endif /* CLOCK_H */
+
+/*
+ * $PchId: clock.h,v 1.5 1995/11/21 06:45:27 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/eth.c
===================================================================
--- /trunk/minix/servers/inet/generic/eth.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/eth.c	(revision 9)
@@ -0,0 +1,1226 @@
+/*
+eth.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "buf.h"
+#include "clock.h"
+#include "event.h"
+#include "osdep_eth.h"
+#include "type.h"
+
+#include "assert.h"
+#include "buf.h"
+#include "eth.h"
+#include "eth_int.h"
+#include "io.h"
+#include "sr.h"
+
+THIS_FILE
+
+#define ETH_FD_NR	(4*IP_PORT_MAX)
+#define EXPIRE_TIME	60*HZ	/* seconds */
+
+typedef struct eth_fd
+{
+	int ef_flags;
+	nwio_ethopt_t ef_ethopt;
+	eth_port_t *ef_port;
+	struct eth_fd *ef_type_next;
+	struct eth_fd *ef_send_next;
+	int ef_srfd;
+	acc_t *ef_rdbuf_head;
+	acc_t *ef_rdbuf_tail;
+	get_userdata_t ef_get_userdata;
+	put_userdata_t ef_put_userdata;
+	put_pkt_t ef_put_pkt;
+	time_t ef_exp_time;
+	size_t ef_write_count;
+	ioreq_t ef_ioctl_req;
+} eth_fd_t;
+
+#define EFF_FLAGS	0xf
+#	define EFF_EMPTY	0x0
+#	define EFF_INUSE	0x1
+#	define EFF_BUSY		0xE
+#		define	EFF_READ_IP	0x2
+#		define 	EFF_WRITE_IP	0x4
+#		define 	EFF_IOCTL_IP	0x8
+#	define EFF_OPTSET       0x10
+
+/* Note that the vh_type field is normally considered part of the ethernet
+ * header.
+ */
+typedef struct 
+{
+	u16_t vh_type;
+	u16_t vh_vlan;
+} vlan_hdr_t;
+
+FORWARD int eth_checkopt ARGS(( eth_fd_t *eth_fd ));
+FORWARD void hash_fd ARGS(( eth_fd_t *eth_fd ));
+FORWARD void unhash_fd ARGS(( eth_fd_t *eth_fd ));
+FORWARD void eth_buffree ARGS(( int priority ));
+#ifdef BUF_CONSISTENCY_CHECK
+FORWARD void eth_bufcheck ARGS(( void ));
+#endif
+FORWARD void packet2user ARGS(( eth_fd_t *fd, acc_t *pack, time_t exp_time ));
+FORWARD void reply_thr_get ARGS(( eth_fd_t *eth_fd,
+	size_t result, int for_ioctl ));
+FORWARD void reply_thr_put ARGS(( eth_fd_t *eth_fd,
+	size_t result, int for_ioctl ));
+FORWARD void do_rec_conf ARGS(( eth_port_t *eth_port ));
+FORWARD u32_t compute_rec_conf ARGS(( eth_port_t *eth_port ));
+FORWARD acc_t *insert_vlan_hdr ARGS(( eth_port_t *eth_port, acc_t *pack ));
+
+PUBLIC eth_port_t *eth_port_table;
+PUBLIC int no_ethWritePort= 0;
+
+PRIVATE eth_fd_t eth_fd_table[ETH_FD_NR];
+PRIVATE ether_addr_t broadcast= { { 255, 255, 255, 255, 255, 255 } };
+
+PUBLIC void eth_prep()
+{
+	eth_port_table= alloc(eth_conf_nr * sizeof(eth_port_table[0]));
+}
+
+PUBLIC void eth_init()
+{
+	int i, j;
+
+	assert (BUF_S >= sizeof(nwio_ethopt_t));
+	assert (BUF_S >= ETH_HDR_SIZE);	/* these are in fact static assertions,
+					   thus a good compiler doesn't
+					   generate any code for this */
+
+
+	for (i=0; i<ETH_FD_NR; i++)
+		eth_fd_table[i].ef_flags= EFF_EMPTY;
+	for (i=0; i<eth_conf_nr; i++)
+	{
+		eth_port_table[i].etp_flags= EFF_EMPTY;
+		eth_port_table[i].etp_sendq_head= NULL;
+		eth_port_table[i].etp_sendq_tail= NULL;
+		eth_port_table[i].etp_type_any= NULL;
+		ev_init(&eth_port_table[i].etp_sendev);
+		for (j= 0; j<ETH_TYPE_HASH_NR; j++)
+			eth_port_table[i].etp_type[j]= NULL;
+		for (j= 0; j<ETH_VLAN_HASH_NR; j++)
+			eth_port_table[i].etp_vlan_tab[j]= NULL;
+	}
+
+#ifndef BUF_CONSISTENCY_CHECK
+	bf_logon(eth_buffree);
+#else
+	bf_logon(eth_buffree, eth_bufcheck);
+#endif
+
+	osdep_eth_init();
+}
+
+PUBLIC int eth_open(port, srfd, get_userdata, put_userdata, put_pkt,
+	select_res)
+int port, srfd;
+get_userdata_t get_userdata;
+put_userdata_t put_userdata;
+put_pkt_t put_pkt;
+select_res_t select_res;
+{
+	int i;
+	eth_port_t *eth_port;
+	eth_fd_t *eth_fd;
+
+	DBLOCK(0x20, printf("eth_open (%d, %d, %lx, %lx)\n", port, srfd, 
+		(unsigned long)get_userdata, (unsigned long)put_userdata));
+	eth_port= &eth_port_table[port];
+	if (!(eth_port->etp_flags & EPF_ENABLED))
+		return EGENERIC;
+
+	for (i=0; i<ETH_FD_NR && (eth_fd_table[i].ef_flags & EFF_INUSE);
+		i++);
+
+	if (i>=ETH_FD_NR)
+	{
+		DBLOCK(1, printf("out of fds\n"));
+		return EAGAIN;
+	}
+
+	eth_fd= &eth_fd_table[i];
+
+	eth_fd->ef_flags= EFF_INUSE;
+	eth_fd->ef_ethopt.nweo_flags=NWEO_DEFAULT;
+	eth_fd->ef_port= eth_port;
+	eth_fd->ef_srfd= srfd;
+	assert(eth_fd->ef_rdbuf_head == NULL);
+	eth_fd->ef_get_userdata= get_userdata;
+	eth_fd->ef_put_userdata= put_userdata;
+	eth_fd->ef_put_pkt= put_pkt;
+
+	return i;
+}
+
+PUBLIC int eth_ioctl(fd, req)
+int fd;
+ioreq_t req;
+{
+	acc_t *data;
+	eth_fd_t *eth_fd;
+	eth_port_t *eth_port;
+
+	DBLOCK(0x20, printf("eth_ioctl (%d, 0x%lx)\n", fd, (unsigned long)req));
+	eth_fd= &eth_fd_table[fd];
+	eth_port= eth_fd->ef_port;
+
+	assert (eth_fd->ef_flags & EFF_INUSE);
+
+	switch (req)
+	{
+	case NWIOSETHOPT:
+		{
+			nwio_ethopt_t *ethopt;
+			nwio_ethopt_t oldopt, newopt;
+			int result;
+			u32_t new_en_flags, new_di_flags,
+				old_en_flags, old_di_flags;
+
+			data= (*eth_fd->ef_get_userdata)(eth_fd->
+				ef_srfd, 0, sizeof(nwio_ethopt_t), TRUE);
+
+                        ethopt= (nwio_ethopt_t *)ptr2acc_data(data);
+			oldopt= eth_fd->ef_ethopt;
+			newopt= *ethopt;
+
+			old_en_flags= oldopt.nweo_flags & 0xffff;
+			old_di_flags= (oldopt.nweo_flags >> 16) & 0xffff;
+			new_en_flags= newopt.nweo_flags & 0xffff;
+			new_di_flags= (newopt.nweo_flags >> 16) & 0xffff;
+			if (new_en_flags & new_di_flags)
+			{
+				bf_afree(data);
+				reply_thr_get (eth_fd, EBADMODE, TRUE);
+				return NW_OK;
+			}	
+
+			/* NWEO_ACC_MASK */
+			if (new_di_flags & NWEO_ACC_MASK)
+			{
+				bf_afree(data);
+				reply_thr_get (eth_fd, EBADMODE, TRUE);
+				return NW_OK;
+			}	
+					/* you can't disable access modes */
+
+			if (!(new_en_flags & NWEO_ACC_MASK))
+				new_en_flags |= (old_en_flags & NWEO_ACC_MASK);
+
+
+			/* NWEO_LOC_MASK */
+			if (!((new_en_flags | new_di_flags) & NWEO_LOC_MASK))
+			{
+				new_en_flags |= (old_en_flags & NWEO_LOC_MASK);
+				new_di_flags |= (old_di_flags & NWEO_LOC_MASK);
+			}
+
+			/* NWEO_BROAD_MASK */
+			if (!((new_en_flags | new_di_flags) & NWEO_BROAD_MASK))
+			{
+				new_en_flags |= (old_en_flags & NWEO_BROAD_MASK);
+				new_di_flags |= (old_di_flags & NWEO_BROAD_MASK);
+			}
+
+			/* NWEO_MULTI_MASK */
+			if (!((new_en_flags | new_di_flags) & NWEO_MULTI_MASK))
+			{
+				new_en_flags |= (old_en_flags & NWEO_MULTI_MASK);
+				new_di_flags |= (old_di_flags & NWEO_MULTI_MASK);
+				newopt.nweo_multi= oldopt.nweo_multi;
+			}
+
+			/* NWEO_PROMISC_MASK */
+			if (!((new_en_flags | new_di_flags) & NWEO_PROMISC_MASK))
+			{
+				new_en_flags |= (old_en_flags & NWEO_PROMISC_MASK);
+				new_di_flags |= (old_di_flags & NWEO_PROMISC_MASK);
+			}
+
+			/* NWEO_REM_MASK */
+			if (!((new_en_flags | new_di_flags) & NWEO_REM_MASK))
+			{
+				new_en_flags |= (old_en_flags & NWEO_REM_MASK);
+				new_di_flags |= (old_di_flags & NWEO_REM_MASK);
+				newopt.nweo_rem= oldopt.nweo_rem;
+			}
+
+			/* NWEO_TYPE_MASK */
+			if (!((new_en_flags | new_di_flags) & NWEO_TYPE_MASK))
+			{
+				new_en_flags |= (old_en_flags & NWEO_TYPE_MASK);
+				new_di_flags |= (old_di_flags & NWEO_TYPE_MASK);
+				newopt.nweo_type= oldopt.nweo_type;
+			}
+
+			/* NWEO_RW_MASK */
+			if (!((new_en_flags | new_di_flags) & NWEO_RW_MASK))
+			{
+				new_en_flags |= (old_en_flags & NWEO_RW_MASK);
+				new_di_flags |= (old_di_flags & NWEO_RW_MASK);
+			}
+
+			if (eth_fd->ef_flags & EFF_OPTSET)
+				unhash_fd(eth_fd);
+
+			newopt.nweo_flags= ((unsigned long)new_di_flags << 16) |
+				new_en_flags;
+			eth_fd->ef_ethopt= newopt;
+
+			result= eth_checkopt(eth_fd);
+
+			if (result<0)
+				eth_fd->ef_ethopt= oldopt;
+			else
+			{
+				unsigned long opt_flags;
+				unsigned changes;
+				opt_flags= oldopt.nweo_flags ^
+					eth_fd->ef_ethopt.nweo_flags;
+				changes= ((opt_flags >> 16) | opt_flags) &
+					0xffff;
+				if (changes & (NWEO_BROAD_MASK |
+					NWEO_MULTI_MASK | NWEO_PROMISC_MASK))
+				{
+					do_rec_conf(eth_port);
+				}
+			}
+
+			if (eth_fd->ef_flags & EFF_OPTSET)
+				hash_fd(eth_fd);
+
+			bf_afree(data);
+			reply_thr_get (eth_fd, result, TRUE);
+			return NW_OK;	
+		}
+
+	case NWIOGETHOPT:
+		{
+			nwio_ethopt_t *ethopt;
+			acc_t *acc;
+			int result;
+
+			acc= bf_memreq(sizeof(nwio_ethopt_t));
+
+			ethopt= (nwio_ethopt_t *)ptr2acc_data(acc);
+
+			*ethopt= eth_fd->ef_ethopt;
+
+			result= (*eth_fd->ef_put_userdata)(eth_fd->
+				ef_srfd, 0, acc, TRUE);
+			if (result >= 0)
+				reply_thr_put(eth_fd, NW_OK, TRUE);
+			return result;
+		}
+	case NWIOGETHSTAT:
+		{
+			nwio_ethstat_t *ethstat;
+			acc_t *acc;
+			int result;
+
+			assert (sizeof(nwio_ethstat_t) <= BUF_S);
+
+			eth_port= eth_fd->ef_port;
+			if (!(eth_port->etp_flags & EPF_ENABLED))
+			{
+				reply_thr_put(eth_fd, EGENERIC, TRUE);
+				return NW_OK;
+			}
+
+			if (!(eth_port->etp_flags & EPF_GOT_ADDR))
+			{
+				printf(
+				"eth_ioctl: suspending NWIOGETHSTAT ioctl\n");
+
+				eth_fd->ef_ioctl_req= req;
+				assert(!(eth_fd->ef_flags & EFF_IOCTL_IP));
+				eth_fd->ef_flags |= EFF_IOCTL_IP;
+				return NW_SUSPEND;
+			}
+
+			acc= bf_memreq(sizeof(nwio_ethstat_t));
+			compare (bf_bufsize(acc), ==, sizeof(*ethstat));
+
+			ethstat= (nwio_ethstat_t *)ptr2acc_data(acc);
+			ethstat->nwes_addr= eth_port->etp_ethaddr;
+
+			if (!eth_port->etp_vlan)
+			{
+				result= eth_get_stat(eth_port,
+					&ethstat->nwes_stat);
+				if (result != NW_OK)
+				{
+					bf_afree(acc);
+					reply_thr_put(eth_fd, result, TRUE);
+					return NW_OK;
+				}
+			}
+			else
+			{
+				/* No statistics */
+				memset(&ethstat->nwes_stat, '\0',
+					sizeof(ethstat->nwes_stat));
+			}
+
+			result= (*eth_fd->ef_put_userdata)(eth_fd->
+				ef_srfd, 0, acc, TRUE);
+			if (result >= 0)
+				reply_thr_put(eth_fd, NW_OK, TRUE);
+			return result;
+		}
+	default:
+		break;
+	}
+	reply_thr_put(eth_fd, EBADIOCTL, TRUE);
+	return NW_OK;
+}
+
+PUBLIC int eth_write(fd, count)
+int fd;
+size_t count;
+{
+	eth_fd_t *eth_fd;
+	eth_port_t *eth_port, *rep;
+	acc_t *user_data;
+	int r;
+
+	eth_fd= &eth_fd_table[fd];
+	eth_port= eth_fd->ef_port;
+
+	if (!(eth_fd->ef_flags & EFF_OPTSET))
+	{
+		reply_thr_get (eth_fd, EBADMODE, FALSE);
+		return NW_OK;
+	}
+
+	assert (!(eth_fd->ef_flags & EFF_WRITE_IP));
+
+	eth_fd->ef_write_count= count;
+	if (eth_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY)
+		count += ETH_HDR_SIZE;
+
+	if (count<ETH_MIN_PACK_SIZE || count>ETH_MAX_PACK_SIZE)
+	{
+		DBLOCK(1, printf("illegal packetsize (%d)\n",count));
+		reply_thr_get (eth_fd, EPACKSIZE, FALSE);
+		return NW_OK;
+	}
+	eth_fd->ef_flags |= EFF_WRITE_IP;
+
+	/* Enqueue at the real ethernet port */
+	rep= eth_port->etp_vlan_port;
+	if (!rep)
+		rep= eth_port;
+	if (rep->etp_wr_pack)
+	{
+		eth_fd->ef_send_next= NULL;
+		if (rep->etp_sendq_head)
+			rep->etp_sendq_tail->ef_send_next= eth_fd;
+		else
+			rep->etp_sendq_head= eth_fd;
+		rep->etp_sendq_tail= eth_fd;
+		return NW_SUSPEND;
+	}
+
+	user_data= (*eth_fd->ef_get_userdata)(eth_fd->ef_srfd, 0,
+		eth_fd->ef_write_count, FALSE);
+	if (!user_data)
+	{
+		eth_fd->ef_flags &= ~EFF_WRITE_IP;
+		reply_thr_get (eth_fd, EFAULT, FALSE);
+		return NW_OK;
+	}
+	r= eth_send(fd, user_data, eth_fd->ef_write_count);
+	assert(r == NW_OK);
+
+	eth_fd->ef_flags &= ~EFF_WRITE_IP;
+	reply_thr_get(eth_fd, eth_fd->ef_write_count, FALSE);
+	return NW_OK;
+}
+
+PUBLIC int eth_send(fd, data, data_len)
+int fd;
+acc_t *data;
+size_t data_len;
+{
+	eth_fd_t *eth_fd;
+	eth_port_t *eth_port, *rep;
+	eth_hdr_t *eth_hdr;
+	acc_t *eth_pack;
+	unsigned long nweo_flags;
+	size_t count;
+	ev_arg_t ev_arg;
+
+	eth_fd= &eth_fd_table[fd];
+	eth_port= eth_fd->ef_port;
+
+	if (!(eth_fd->ef_flags & EFF_OPTSET))
+		return EBADMODE;
+
+	count= data_len;
+	if (eth_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY)
+		count += ETH_HDR_SIZE;
+
+	if (count<ETH_MIN_PACK_SIZE || count>ETH_MAX_PACK_SIZE)
+	{
+		DBLOCK(1, printf("illegal packetsize (%d)\n",count));
+		return EPACKSIZE;
+	}
+	rep= eth_port->etp_vlan_port;
+	if (!rep)
+		rep= eth_port;
+
+	if (rep->etp_wr_pack)
+		return NW_WOULDBLOCK;
+	
+	nweo_flags= eth_fd->ef_ethopt.nweo_flags;
+	if (nweo_flags & NWEO_RWDATONLY)
+	{
+		eth_pack= bf_memreq(ETH_HDR_SIZE);
+		eth_pack->acc_next= data;
+	}
+	else
+		eth_pack= bf_packIffLess(data, ETH_HDR_SIZE);
+
+	eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);
+
+	if (nweo_flags & NWEO_REMSPEC)
+		eth_hdr->eh_dst= eth_fd->ef_ethopt.nweo_rem;
+
+	if (!(eth_port->etp_flags & EPF_GOT_ADDR))
+	{
+		/* No device, discard packet */
+		bf_afree(eth_pack);
+		return NW_OK;
+	}
+
+	if (!(nweo_flags & NWEO_EN_PROMISC))
+		eth_hdr->eh_src= eth_port->etp_ethaddr;
+
+	if (nweo_flags & NWEO_TYPESPEC)
+		eth_hdr->eh_proto= eth_fd->ef_ethopt.nweo_type;
+
+	if (eth_addrcmp(eth_hdr->eh_dst, eth_port->etp_ethaddr) == 0)
+	{
+		/* Local loopback. */
+		eth_port->etp_wr_pack= eth_pack;
+		ev_arg.ev_ptr= eth_port;
+		ev_enqueue(&eth_port->etp_sendev, eth_loop_ev, ev_arg);
+		return NW_OK;
+	}
+
+	if (rep != eth_port)
+	{
+		eth_pack= insert_vlan_hdr(eth_port, eth_pack);
+		if (!eth_pack)
+		{
+			/* Packet is silently discarded */
+			return NW_OK;
+		}
+	}
+
+	eth_write_port(rep, eth_pack);
+	return NW_OK;
+}
+
+PUBLIC int eth_read (fd, count)
+int fd;
+size_t count;
+{
+	eth_fd_t *eth_fd;
+	acc_t *pack;
+
+	eth_fd= &eth_fd_table[fd];
+	if (!(eth_fd->ef_flags & EFF_OPTSET))
+	{
+		reply_thr_put(eth_fd, EBADMODE, FALSE);
+		return NW_OK;
+	}
+	if (count < ETH_MAX_PACK_SIZE)
+	{
+		reply_thr_put(eth_fd, EPACKSIZE, FALSE);
+		return NW_OK;
+	}
+
+	assert(!(eth_fd->ef_flags & EFF_READ_IP));
+	eth_fd->ef_flags |= EFF_READ_IP;
+
+	while (eth_fd->ef_rdbuf_head)
+	{
+		pack= eth_fd->ef_rdbuf_head;
+		eth_fd->ef_rdbuf_head= pack->acc_ext_link;
+		if (get_time() <= eth_fd->ef_exp_time)
+		{
+			packet2user(eth_fd, pack, eth_fd->ef_exp_time);
+			if (!(eth_fd->ef_flags & EFF_READ_IP))
+				return NW_OK;
+		}
+		else
+			bf_afree(pack);
+	}
+	return NW_SUSPEND;
+}
+
+PUBLIC int eth_cancel(fd, which_operation)
+int fd;
+int which_operation;
+{
+	eth_fd_t *eth_fd, *prev, *loc_fd;
+	eth_port_t *eth_port;
+
+	DBLOCK(2, printf("eth_cancel (%d)\n", fd));
+	eth_fd= &eth_fd_table[fd];
+
+	switch (which_operation)
+	{
+	case SR_CANCEL_READ:
+		assert (eth_fd->ef_flags & EFF_READ_IP);
+		eth_fd->ef_flags &= ~EFF_READ_IP;
+		reply_thr_put(eth_fd, EINTR, FALSE);
+		break;
+	case SR_CANCEL_WRITE:
+		assert (eth_fd->ef_flags & EFF_WRITE_IP);
+		eth_fd->ef_flags &= ~EFF_WRITE_IP;
+
+		/* Remove fd from send queue */
+		eth_port= eth_fd->ef_port;
+		if (eth_port->etp_vlan_port)
+			eth_port= eth_port->etp_vlan_port;
+		for (prev= 0, loc_fd= eth_port->etp_sendq_head; loc_fd != NULL;
+			prev= loc_fd, loc_fd= loc_fd->ef_send_next)
+		{
+			if (loc_fd == eth_fd)
+				break;
+		}
+		assert(loc_fd == eth_fd);
+		if (prev == NULL)
+			eth_port->etp_sendq_head= loc_fd->ef_send_next;
+		else
+			prev->ef_send_next= loc_fd->ef_send_next;
+		if (loc_fd->ef_send_next == NULL)
+			eth_port->etp_sendq_tail= prev;
+			
+		reply_thr_get(eth_fd, EINTR, FALSE);
+		break;
+	case SR_CANCEL_IOCTL:
+		assert (eth_fd->ef_flags & EFF_IOCTL_IP);
+		eth_fd->ef_flags &= ~EFF_IOCTL_IP;
+		reply_thr_get(eth_fd, EINTR, TRUE);
+		break;
+	default:
+		ip_panic(( "got unknown cancel request" ));
+	}
+	return NW_OK;
+}
+
+PUBLIC int eth_select(fd, operations)
+int fd;
+unsigned operations;
+{
+	printf("eth_select: not implemented\n");
+	return 0;
+}
+
+PUBLIC void eth_close(fd)
+int fd;
+{
+	eth_fd_t *eth_fd;
+	eth_port_t *eth_port;
+	acc_t *pack;
+
+	eth_fd= &eth_fd_table[fd];
+
+	assert ((eth_fd->ef_flags & EFF_INUSE) &&
+		!(eth_fd->ef_flags & EFF_BUSY));
+
+	if (eth_fd->ef_flags & EFF_OPTSET)
+		unhash_fd(eth_fd);
+	while (eth_fd->ef_rdbuf_head != NULL)
+	{
+		pack= eth_fd->ef_rdbuf_head;
+		eth_fd->ef_rdbuf_head= pack->acc_ext_link;
+		bf_afree(pack);
+	}
+	eth_fd->ef_flags= EFF_EMPTY;
+
+	eth_port= eth_fd->ef_port;
+	do_rec_conf(eth_port);
+}
+
+PUBLIC void eth_loop_ev(ev, ev_arg)
+event_t *ev;
+ev_arg_t ev_arg;
+{
+	acc_t *pack;
+	eth_port_t *eth_port;
+
+	eth_port= ev_arg.ev_ptr;
+	assert(ev == &eth_port->etp_sendev);
+
+	pack= eth_port->etp_wr_pack;
+
+	assert(!no_ethWritePort);
+	no_ethWritePort= 1;
+	eth_arrive(eth_port, pack, bf_bufsize(pack));
+	assert(no_ethWritePort);
+	no_ethWritePort= 0;
+
+	eth_port->etp_wr_pack= NULL;
+	eth_restart_write(eth_port);
+}
+
+PRIVATE int eth_checkopt (eth_fd)
+eth_fd_t *eth_fd;
+{
+/* bug: we don't check access modes yet */
+
+	unsigned long flags;
+	unsigned int en_di_flags;
+	eth_port_t *eth_port;
+	acc_t *pack;
+
+	eth_port= eth_fd->ef_port;
+	flags= eth_fd->ef_ethopt.nweo_flags;
+	en_di_flags= (flags >>16) | (flags & 0xffff);
+
+	if ((en_di_flags & NWEO_ACC_MASK) &&
+		(en_di_flags & NWEO_LOC_MASK) &&
+		(en_di_flags & NWEO_BROAD_MASK) &&
+		(en_di_flags & NWEO_MULTI_MASK) &&
+		(en_di_flags & NWEO_PROMISC_MASK) &&
+		(en_di_flags & NWEO_REM_MASK) &&
+		(en_di_flags & NWEO_TYPE_MASK) &&
+		(en_di_flags & NWEO_RW_MASK))
+	{
+		eth_fd->ef_flags |= EFF_OPTSET;
+	}
+	else
+		eth_fd->ef_flags &= ~EFF_OPTSET;
+
+	while (eth_fd->ef_rdbuf_head != NULL)
+	{
+		pack= eth_fd->ef_rdbuf_head;
+		eth_fd->ef_rdbuf_head= pack->acc_ext_link;
+		bf_afree(pack);
+	}
+
+	return NW_OK;
+}
+
+PRIVATE void hash_fd(eth_fd)
+eth_fd_t *eth_fd;
+{
+	eth_port_t *eth_port;
+	int hash;
+
+	eth_port= eth_fd->ef_port;
+	if (eth_fd->ef_ethopt.nweo_flags & NWEO_TYPEANY)
+	{
+		eth_fd->ef_type_next= eth_port->etp_type_any;
+		eth_port->etp_type_any= eth_fd;
+	}
+	else
+	{
+		hash= eth_fd->ef_ethopt.nweo_type;
+		hash ^= (hash >> 8);
+		hash &= (ETH_TYPE_HASH_NR-1);
+
+		eth_fd->ef_type_next= eth_port->etp_type[hash];
+		eth_port->etp_type[hash]= eth_fd;
+	}
+}
+
+PRIVATE void unhash_fd(eth_fd)
+eth_fd_t *eth_fd;
+{
+	eth_port_t *eth_port;
+	eth_fd_t *prev, *curr, **eth_fd_p;
+	int hash;
+
+	eth_port= eth_fd->ef_port;
+	if (eth_fd->ef_ethopt.nweo_flags & NWEO_TYPEANY)
+	{
+		eth_fd_p= &eth_port->etp_type_any;
+	}
+	else
+	{
+		hash= eth_fd->ef_ethopt.nweo_type;
+		hash ^= (hash >> 8);
+		hash &= (ETH_TYPE_HASH_NR-1);
+
+		eth_fd_p= &eth_port->etp_type[hash];
+	}
+	for (prev= NULL, curr= *eth_fd_p; curr;
+		prev= curr, curr= curr->ef_type_next)
+	{
+		if (curr == eth_fd)
+			break;
+	}
+	assert(curr);
+	if (prev)
+		prev->ef_type_next= curr->ef_type_next;
+	else
+		*eth_fd_p= curr->ef_type_next;
+}
+
+PUBLIC void eth_restart_write(eth_port)
+eth_port_t *eth_port;
+{
+	eth_fd_t *eth_fd;
+	int r;
+
+	assert(eth_port->etp_wr_pack == NULL);
+	while (eth_fd= eth_port->etp_sendq_head, eth_fd != NULL)
+	{
+		if (eth_port->etp_wr_pack)
+			return;
+		eth_port->etp_sendq_head= eth_fd->ef_send_next;
+
+		assert(eth_fd->ef_flags & EFF_WRITE_IP);
+		eth_fd->ef_flags &= ~EFF_WRITE_IP;
+		r= eth_write(eth_fd-eth_fd_table, eth_fd->ef_write_count);
+		assert(r == NW_OK);
+	}
+}
+
+PUBLIC void eth_arrive (eth_port, pack, pack_size)
+eth_port_t *eth_port;
+acc_t *pack;
+size_t pack_size;
+{
+
+	eth_hdr_t *eth_hdr;
+	ether_addr_t *dst_addr;
+	int pack_stat;
+	ether_type_t type;
+	eth_fd_t *eth_fd, *first_fd, *share_fd;
+	int hash, i;
+	u16_t vlan, temp;
+	time_t exp_time;
+	acc_t *vlan_pack, *hdr_acc, *tmp_acc;
+	eth_port_t *vp;
+	vlan_hdr_t vh;
+	u32_t *p;
+
+	exp_time= get_time() + EXPIRE_TIME;
+
+	pack= bf_packIffLess(pack, ETH_HDR_SIZE);
+
+	eth_hdr= (eth_hdr_t*)ptr2acc_data(pack);
+	dst_addr= &eth_hdr->eh_dst;
+
+	DIFBLOCK(0x20, dst_addr->ea_addr[0] != 0xFF &&
+		(dst_addr->ea_addr[0] & 0x1),
+		printf("got multicast packet\n"));
+
+	if (dst_addr->ea_addr[0] & 0x1)
+	{
+		/* multi cast or broadcast */
+		if (eth_addrcmp(*dst_addr, broadcast) == 0)
+			pack_stat= NWEO_EN_BROAD;
+		else
+			pack_stat= NWEO_EN_MULTI;
+	}
+	else
+	{
+		assert(eth_port->etp_flags & EPF_GOT_ADDR);
+		if (eth_addrcmp (*dst_addr, eth_port->etp_ethaddr) == 0)
+			pack_stat= NWEO_EN_LOC;
+		else
+			pack_stat= NWEO_EN_PROMISC;
+	}
+	type= eth_hdr->eh_proto;
+	hash= type;
+	hash ^= (hash >> 8);
+	hash &= (ETH_TYPE_HASH_NR-1);
+
+	if (type == HTONS(ETH_VLAN_PROTO))
+	{
+		/* VLAN packet. Extract original ethernet packet */
+
+		vlan_pack= pack;
+		vlan_pack->acc_linkC++;
+		hdr_acc= bf_cut(vlan_pack, 0, 2*sizeof(ether_addr_t));
+		vlan_pack= bf_delhead(vlan_pack, 2*sizeof(ether_addr_t));
+		vlan_pack= bf_packIffLess(vlan_pack, sizeof(vh));
+		vh= *(vlan_hdr_t *)ptr2acc_data(vlan_pack);
+		vlan_pack= bf_delhead(vlan_pack, sizeof(vh));
+		hdr_acc= bf_append(hdr_acc, vlan_pack);
+		vlan_pack= hdr_acc; hdr_acc= NULL;
+		if (bf_bufsize(vlan_pack) < ETH_MIN_PACK_SIZE)
+		{
+			tmp_acc= bf_memreq(sizeof(vh));
+
+			/* Clear padding */
+			assert(sizeof(vh) <= sizeof(*p));
+			p= (u32_t *)ptr2acc_data(tmp_acc);
+			*p= 0xdeadbeef;
+
+			vlan_pack= bf_append(vlan_pack, tmp_acc);
+			tmp_acc= NULL;
+		}
+		vlan= ntohs(vh.vh_vlan);
+		if (vlan & ETH_TCI_CFI)
+		{
+			/* No support for extended address formats */
+			bf_afree(vlan_pack); vlan_pack= NULL;
+		}
+		vlan &= ETH_TCI_VLAN_MASK;
+	}
+	else
+	{
+		/* No VLAN processing */
+		vlan_pack= NULL;
+		vlan= 0;	/* lint */
+	}
+
+	first_fd= NULL;
+	for (i= 0; i<2; i++)
+	{
+		share_fd= NULL;
+
+		eth_fd= (i == 0) ? eth_port->etp_type_any :
+			eth_port->etp_type[hash];
+		for (; eth_fd; eth_fd= eth_fd->ef_type_next)
+		{
+			if (i && eth_fd->ef_ethopt.nweo_type != type)
+				continue;
+			if (!(eth_fd->ef_ethopt.nweo_flags & pack_stat))
+				continue;
+			if (eth_fd->ef_ethopt.nweo_flags & NWEO_REMSPEC &&
+				eth_addrcmp(eth_hdr->eh_src,
+				eth_fd->ef_ethopt.nweo_rem) != 0)
+			{
+					continue;
+			}
+			if ((eth_fd->ef_ethopt.nweo_flags & NWEO_ACC_MASK) ==
+				NWEO_SHARED)
+			{
+				if (!share_fd)
+				{
+					share_fd= eth_fd;
+					continue;
+				}
+				if (!eth_fd->ef_rdbuf_head)
+					share_fd= eth_fd;
+				continue;
+			}
+			if (!first_fd)
+			{
+				first_fd= eth_fd;
+				continue;
+			}
+			pack->acc_linkC++;
+			packet2user(eth_fd, pack, exp_time);
+		}
+		if (share_fd)
+		{
+			pack->acc_linkC++;
+			packet2user(share_fd, pack, exp_time);
+		}
+	}
+	if (first_fd)
+	{
+		if (first_fd->ef_put_pkt &&
+			(first_fd->ef_flags & EFF_READ_IP) &&
+			!(first_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY))
+		{
+			(*first_fd->ef_put_pkt)(first_fd->ef_srfd, pack,
+				pack_size);
+		}
+		else
+			packet2user(first_fd, pack, exp_time);
+	}
+	else
+	{
+		if (pack_stat == NWEO_EN_LOC)
+		{
+			DBLOCK(0x01,
+			printf("eth_arrive: dropping packet for proto 0x%x\n",
+				ntohs(type)));
+		}
+		else
+		{
+			DBLOCK(0x20, printf("dropping packet for proto 0x%x\n",
+				ntohs(type)));
+		}			
+		bf_afree(pack);
+	}
+	if (vlan_pack)
+	{
+		hash= ETH_HASH_VLAN(vlan, temp);
+		for (vp= eth_port->etp_vlan_tab[hash]; vp;
+			vp= vp->etp_vlan_next)
+		{
+			if (vp->etp_vlan == vlan)
+				break;
+		}
+		if (vp)
+		{
+			eth_arrive(vp, vlan_pack, pack_size-sizeof(vh));
+			vlan_pack= NULL;
+		}
+		else
+		{
+			/* No device for VLAN */
+			bf_afree(vlan_pack);
+			vlan_pack= NULL;
+		}
+	}
+}
+
+PUBLIC void eth_reg_vlan(eth_port, vlan_port)
+eth_port_t *eth_port;
+eth_port_t *vlan_port;
+{
+	u16_t t, vlan;
+	int h;
+
+	vlan= vlan_port->etp_vlan;
+	h= ETH_HASH_VLAN(vlan, t);
+	vlan_port->etp_vlan_next= eth_port->etp_vlan_tab[h];
+	eth_port->etp_vlan_tab[h]= vlan_port;
+}
+
+PUBLIC void eth_restart_ioctl(eth_port)
+eth_port_t *eth_port;
+{
+	int i;
+	eth_fd_t *eth_fd;
+
+	for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
+	{
+		if (!(eth_fd->ef_flags & EFF_INUSE))
+			continue;
+		if (eth_fd->ef_port != eth_port)
+			continue;
+		if (!(eth_fd->ef_flags & EFF_IOCTL_IP))
+			continue;
+		if (eth_fd->ef_ioctl_req != NWIOGETHSTAT)
+			continue;
+
+		eth_fd->ef_flags &= ~EFF_IOCTL_IP;
+		eth_ioctl(i, eth_fd->ef_ioctl_req);
+	}
+}
+
+PRIVATE void packet2user (eth_fd, pack, exp_time)
+eth_fd_t *eth_fd;
+acc_t *pack;
+time_t exp_time;
+{
+	int result;
+	acc_t *tmp_pack;
+	size_t size;
+
+	assert (eth_fd->ef_flags & EFF_INUSE);
+	if (!(eth_fd->ef_flags & EFF_READ_IP))
+	{
+		if (pack->acc_linkC != 1)
+		{
+			tmp_pack= bf_dupacc(pack);
+			bf_afree(pack);
+			pack= tmp_pack;
+			tmp_pack= NULL;
+		}
+		pack->acc_ext_link= NULL;
+		if (eth_fd->ef_rdbuf_head == NULL)
+		{
+			eth_fd->ef_rdbuf_head= pack;
+			eth_fd->ef_exp_time= exp_time;
+		}
+		else
+			eth_fd->ef_rdbuf_tail->acc_ext_link= pack;
+		eth_fd->ef_rdbuf_tail= pack;
+		return;
+	}
+
+	if (eth_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY)
+		pack= bf_delhead(pack, ETH_HDR_SIZE);
+
+	size= bf_bufsize(pack);
+
+	if (eth_fd->ef_put_pkt)
+	{
+		(*eth_fd->ef_put_pkt)(eth_fd->ef_srfd, pack, size);
+		return;
+	}
+
+	eth_fd->ef_flags &= ~EFF_READ_IP;
+	result= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, (size_t)0, pack,
+		FALSE);
+	if (result >=0)
+		reply_thr_put(eth_fd, size, FALSE);
+	else
+		reply_thr_put(eth_fd, result, FALSE);
+}
+
+PRIVATE void eth_buffree (priority)
+int priority;
+{
+	int i;
+	eth_fd_t *eth_fd;
+	acc_t *pack;
+
+	if (priority == ETH_PRI_FDBUFS_EXTRA)
+	{
+		for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
+		{
+			while (eth_fd->ef_rdbuf_head &&
+				eth_fd->ef_rdbuf_head->acc_ext_link)
+			{
+				pack= eth_fd->ef_rdbuf_head;
+				eth_fd->ef_rdbuf_head= pack->acc_ext_link;
+				bf_afree(pack);
+			}
+		}
+	}
+	if (priority == ETH_PRI_FDBUFS)
+	{
+		for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
+		{
+			while (eth_fd->ef_rdbuf_head)
+			{
+				pack= eth_fd->ef_rdbuf_head;
+				eth_fd->ef_rdbuf_head= pack->acc_ext_link;
+				bf_afree(pack);
+			}
+		}
+	}
+}
+
+#ifdef BUF_CONSISTENCY_CHECK
+PRIVATE void eth_bufcheck()
+{
+	int i;
+	eth_fd_t *eth_fd;
+	acc_t *pack;
+
+	for (i= 0; i<eth_conf_nr; i++)
+	{
+		bf_check_acc(eth_port_table[i].etp_rd_pack);
+		bf_check_acc(eth_port_table[i].etp_wr_pack);
+	}
+	for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
+	{
+		for (pack= eth_fd->ef_rdbuf_head; pack;
+			pack= pack->acc_ext_link)
+		{
+			bf_check_acc(pack);
+		}
+	}
+}
+#endif
+
+PRIVATE void do_rec_conf(eth_port)
+eth_port_t *eth_port;
+{
+	int i;
+	u32_t flags;
+	eth_port_t *vp;
+
+	if (eth_port->etp_vlan)
+	{
+		/* Configure underlying device */
+		eth_port= eth_port->etp_vlan_port;
+	}
+	flags= compute_rec_conf(eth_port);
+	for (i= 0; i<ETH_VLAN_HASH_NR; i++)
+	{
+		for (vp= eth_port->etp_vlan_tab[i]; vp; vp= vp->etp_vlan_next)
+			flags |= compute_rec_conf(vp);
+	}
+	eth_set_rec_conf(eth_port, flags);
+}
+
+PRIVATE u32_t compute_rec_conf(eth_port)
+eth_port_t *eth_port;
+{
+	eth_fd_t *eth_fd;
+	u32_t flags;
+	int i;
+
+	flags= NWEO_NOFLAGS;
+	for (i=0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
+	{
+		if ((eth_fd->ef_flags & (EFF_INUSE|EFF_OPTSET)) !=
+			(EFF_INUSE|EFF_OPTSET))
+		{
+			continue;
+		}
+		if (eth_fd->ef_port != eth_port)
+			continue;
+		flags |= eth_fd->ef_ethopt.nweo_flags;
+	}
+	return flags;
+}
+
+PRIVATE void reply_thr_get (eth_fd, result, for_ioctl)
+eth_fd_t *eth_fd;
+size_t result;
+int for_ioctl;
+{
+	acc_t *data;
+
+	data= (*eth_fd->ef_get_userdata)(eth_fd->ef_srfd, result, 0, for_ioctl);
+	assert (!data);	
+}
+
+PRIVATE void reply_thr_put (eth_fd, result, for_ioctl)
+eth_fd_t *eth_fd;
+size_t result;
+int for_ioctl;
+{
+	int error;
+
+	error= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, result, (acc_t *)0,
+		for_ioctl);
+	assert(error == NW_OK);
+}
+
+PRIVATE acc_t *insert_vlan_hdr(eth_port, pack)
+eth_port_t *eth_port;
+acc_t *pack;
+{
+	acc_t *head_acc, *vh_acc;
+	u16_t type, vlan;
+	vlan_hdr_t *vp;
+
+	head_acc= bf_cut(pack, 0, 2*sizeof(ether_addr_t));
+	pack= bf_delhead(pack, 2*sizeof(ether_addr_t));
+	pack= bf_packIffLess(pack, sizeof(type));
+	type= *(u16_t *)ptr2acc_data(pack);
+	if (type == HTONS(ETH_VLAN_PROTO))
+	{
+		/* Packeted is already tagged. Should update vlan number.
+		 * For now, just discard packet.
+		 */
+		printf("insert_vlan_hdr: discarding vlan packet\n");
+		bf_afree(head_acc); head_acc= NULL;
+		bf_afree(pack); pack= NULL;
+		return NULL;
+	}
+	vlan= eth_port->etp_vlan;	/* priority and CFI are zero */
+
+	vh_acc= bf_memreq(sizeof(vlan_hdr_t));
+	vp= (vlan_hdr_t *)ptr2acc_data(vh_acc);
+	vp->vh_type= HTONS(ETH_VLAN_PROTO);
+	vp->vh_vlan= htons(vlan);
+
+	head_acc= bf_append(head_acc, vh_acc); vh_acc= NULL;
+	head_acc= bf_append(head_acc, pack); pack= NULL;
+	pack= head_acc; head_acc= NULL;
+	return pack;
+}
+
+/*
+ * $PchId: eth.c,v 1.23 2005/06/28 14:15:58 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/eth.h
===================================================================
--- /trunk/minix/servers/inet/generic/eth.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/eth.h	(revision 9)
@@ -0,0 +1,39 @@
+/*
+eth.h
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef ETH_H
+#define ETH_H
+
+#define NWEO_DEFAULT    (NWEO_EN_LOC | NWEO_DI_BROAD | NWEO_DI_MULTI | \
+	NWEO_DI_PROMISC | NWEO_REMANY | NWEO_RWDATALL)
+
+#define eth_addrcmp(a,b) (memcmp((_VOIDSTAR)&a, (_VOIDSTAR)&b, \
+	sizeof(a)))
+
+/* Forward declatations */
+
+struct acc;
+
+/* prototypes */
+
+void eth_prep ARGS(( void ));
+void eth_init ARGS(( void ));
+int eth_open ARGS(( int port, int srfd,
+	get_userdata_t get_userdata, put_userdata_t put_userdata,
+	put_pkt_t put_pkt, select_res_t sel_res ));
+int eth_ioctl ARGS(( int fd, ioreq_t req));
+int eth_read ARGS(( int port, size_t count ));
+int eth_write ARGS(( int port, size_t count ));
+int eth_cancel ARGS(( int fd, int which_operation ));
+int eth_select ARGS(( int fd, unsigned operations ));
+void eth_close ARGS(( int fd ));
+int eth_send ARGS(( int port, struct acc *data, size_t data_len ));
+
+#endif /* ETH_H */
+
+/*
+ * $PchId: eth.h,v 1.8 2005/06/28 14:16:10 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/eth_int.h
===================================================================
--- /trunk/minix/servers/inet/generic/eth_int.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/eth_int.h	(revision 9)
@@ -0,0 +1,63 @@
+/*
+eth_int.h
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef ETH_INT_H
+#define ETH_INT_H
+
+#define ETH_TYPE_HASH_NR	16
+#define ETH_VLAN_HASH_NR	16
+
+/* Assume that the arguments are a local variable */
+#define ETH_HASH_VLAN(v,t)	\
+	((t)= (((v) >> 8) ^ (v)), \
+	(t)= (((t) >> 4) ^ (t)), \
+	(t) & (ETH_VLAN_HASH_NR-1))
+	
+typedef struct eth_port
+{
+	int etp_flags;
+	ether_addr_t etp_ethaddr;
+	acc_t *etp_wr_pack, *etp_rd_pack;
+	struct eth_fd *etp_sendq_head;
+	struct eth_fd *etp_sendq_tail;
+	struct eth_fd *etp_type_any;
+	struct eth_fd *etp_type[ETH_TYPE_HASH_NR];
+	event_t etp_sendev;
+
+	/* VLAN support */
+	u16_t etp_vlan;
+	struct eth_port *etp_vlan_port;
+	struct eth_port *etp_vlan_tab[ETH_VLAN_HASH_NR];
+	struct eth_port *etp_vlan_next;
+
+	osdep_eth_port_t etp_osdep;
+} eth_port_t;
+
+#define EPF_EMPTY	 0x0
+#define EPF_ENABLED	 0x1
+#define EPF_GOT_ADDR	 0x2	/* Got ethernet address from device */
+#define EPF_READ_IP	0x20
+#define EPF_READ_SP	0x40
+
+extern eth_port_t *eth_port_table;
+
+extern int no_ethWritePort;	/* debug, consistency check */
+
+void osdep_eth_init ARGS(( void ));
+int eth_get_stat ARGS(( eth_port_t *eth_port, eth_stat_t *eth_stat ));
+void eth_write_port ARGS(( eth_port_t *eth_port, acc_t *pack ));
+void eth_arrive ARGS(( eth_port_t *port, acc_t *pack, size_t pack_size ));
+void eth_set_rec_conf ARGS(( eth_port_t *eth_port, u32_t flags ));
+void eth_restart_write ARGS(( eth_port_t *eth_port ));
+void eth_loop_ev ARGS(( event_t *ev, ev_arg_t ev_arg ));
+void eth_reg_vlan ARGS(( eth_port_t *eth_port, eth_port_t *vlan_port ));
+void eth_restart_ioctl ARGS(( eth_port_t *eth_port ));
+
+#endif /* ETH_INT_H */
+
+/*
+ * $PchId: eth_int.h,v 1.9 2001/04/23 08:04:06 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/event.c
===================================================================
--- /trunk/minix/servers/inet/generic/event.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/event.c	(revision 9)
@@ -0,0 +1,69 @@
+/*
+inet/generic/event.c
+
+Created:	April 1995 by Philip Homburg <philip@f-mnx.phicoh.com>
+
+Implementation of an event queue.
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "assert.h"
+#include "event.h"
+
+THIS_FILE
+
+event_t *ev_head;
+static event_t *ev_tail;
+
+void ev_init(ev)
+event_t *ev;
+{
+	ev->ev_func= 0;
+	ev->ev_next= NULL;
+}
+
+void ev_enqueue(ev, func, ev_arg)
+event_t *ev;
+ev_func_t func;
+ev_arg_t ev_arg;
+{
+	assert(ev->ev_func == 0);
+	ev->ev_func= func;
+	ev->ev_arg= ev_arg;
+	ev->ev_next= NULL;
+	if (ev_head == NULL)
+		ev_head= ev;
+	else
+		ev_tail->ev_next= ev;
+	ev_tail= ev;
+}
+
+void ev_process()
+{
+	ev_func_t func;
+	event_t *curr;
+
+	while (ev_head)
+	{
+		curr= ev_head;
+		ev_head= curr->ev_next;
+		func= curr->ev_func;
+		curr->ev_func= 0;
+
+		assert(func != 0);
+		func(curr, curr->ev_arg);
+	}
+}
+
+int ev_in_queue(ev)
+event_t *ev;
+{
+	return ev->ev_func != 0;
+}
+
+
+/*
+ * $PchId: event.c,v 1.6 2004/08/03 16:23:32 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/event.h
===================================================================
--- /trunk/minix/servers/inet/generic/event.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/event.h	(revision 9)
@@ -0,0 +1,42 @@
+/*
+inet/generic/event.h
+
+Created:	April 1995 by Philip Homburg <philip@f-mnx.phicoh.com>
+
+Header file for an event mechanism.
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef INET__GENERIC__EVENT_H
+#define INET__GENERIC__EVENT_H
+
+struct event;
+
+typedef union ev_arg
+{
+	int ev_int;
+	void *ev_ptr;
+} ev_arg_t;
+
+typedef void (*ev_func_t) ARGS(( struct event *ev, union ev_arg eva ));
+
+typedef struct event
+{
+	ev_func_t ev_func;
+	ev_arg_t ev_arg;
+	struct event *ev_next;
+} event_t;
+
+extern event_t *ev_head;
+
+void ev_init ARGS(( event_t *ev ));
+void ev_enqueue ARGS(( event_t *ev, ev_func_t func, ev_arg_t ev_arg ));
+void ev_process ARGS(( void ));
+int ev_in_queue ARGS(( event_t *ev ));
+
+#endif /* INET__GENERIC__EVENT_H */
+
+/*
+ * $PchId: event.h,v 1.5 2004/08/03 16:23:49 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/icmp.c
===================================================================
--- /trunk/minix/servers/inet/generic/icmp.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/icmp.c	(revision 9)
@@ -0,0 +1,1229 @@
+/*
+icmp.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "buf.h"
+#include "event.h"
+#include "type.h"
+
+#include "assert.h"
+#include "clock.h"
+#include "icmp.h"
+#include "icmp_lib.h"
+#include "io.h"
+#include "ip.h"
+#include "ip_int.h"
+#include "ipr.h"
+
+THIS_FILE
+
+typedef struct icmp_port
+{
+	int icp_flags;
+	int icp_state;
+	int icp_ipport;
+	int icp_ipfd;
+	unsigned icp_rate_count;
+	unsigned icp_rate_report;
+	time_t icp_rate_lasttime;
+	acc_t *icp_head_queue;
+	acc_t *icp_tail_queue;
+	acc_t *icp_write_pack;
+	event_t icp_event;
+} icmp_port_t;
+
+#define ICPF_EMPTY	0x0
+#define ICPF_SUSPEND	0x1
+#define ICPF_READ_IP	0x2
+#define ICPF_READ_SP	0x4
+#define ICPF_WRITE_IP	0x8
+#define ICPF_WRITE_SP	0x10
+
+#define ICPS_BEGIN	0
+#define ICPS_IPOPT	1
+#define ICPS_MAIN	2
+#define ICPS_ERROR	3
+
+PRIVATE icmp_port_t *icmp_port_table;
+
+FORWARD void icmp_main ARGS(( icmp_port_t *icmp_port ));
+FORWARD acc_t *icmp_getdata ARGS(( int port, size_t offset,
+	size_t count, int for_ioctl ));
+FORWARD int icmp_putdata ARGS(( int port, size_t offset,
+	acc_t *data, int for_ioctl ));
+FORWARD void icmp_read ARGS(( icmp_port_t *icmp_port ));
+FORWARD void process_data ARGS(( icmp_port_t *icmp_port,
+	acc_t *data ));
+FORWARD u16_t icmp_pack_oneCsum ARGS(( acc_t *ip_pack ));
+FORWARD void icmp_echo_request ARGS(( icmp_port_t *icmp_port,
+	acc_t *ip_pack, int ip_hdr_len, ip_hdr_t *ip_hdr,
+	acc_t *icmp_pack, int icmp_len, icmp_hdr_t *icmp_hdr ));
+FORWARD void icmp_dst_unreach ARGS(( icmp_port_t *icmp_port,
+	acc_t *ip_pack, int ip_hdr_len, ip_hdr_t *ip_hdr,
+	acc_t *icmp_pack, int icmp_len, icmp_hdr_t *icmp_hdr ));
+FORWARD void icmp_time_exceeded ARGS(( icmp_port_t *icmp_port,
+	acc_t *ip_pack, int ip_hdr_len, ip_hdr_t *ip_hdr,
+	acc_t *icmp_pack, int icmp_len, icmp_hdr_t *icmp_hdr ));
+FORWARD void icmp_router_advertisement ARGS(( icmp_port_t *icmp_port,
+	acc_t *icmp_pack, int icmp_len, icmp_hdr_t *icmp_hdr ));
+FORWARD void icmp_redirect ARGS(( icmp_port_t *icmp_port,
+	ip_hdr_t *ip_hdr, acc_t *icmp_pack, int icmp_len,
+	icmp_hdr_t *icmp_hdr ));
+FORWARD acc_t *make_repl_ip ARGS(( ip_hdr_t *ip_hdr,
+	int ip_len ));
+FORWARD void enqueue_pack ARGS(( icmp_port_t *icmp_port,
+	acc_t *reply_ip_hdr ));
+FORWARD int icmp_rate_limit ARGS(( icmp_port_t *icmp_port,
+	acc_t *reply_ip_hdr ));
+FORWARD void icmp_write ARGS(( event_t *ev, ev_arg_t ev_arg ));
+FORWARD void icmp_buffree ARGS(( int priority ));
+FORWARD acc_t *icmp_err_pack ARGS(( acc_t *pack, icmp_hdr_t **icmp_hdr_pp ));
+#ifdef BUF_CONSISTENCY_CHECK
+FORWARD void icmp_bufcheck ARGS(( void ));
+#endif
+
+PUBLIC void icmp_prep()
+{
+	icmp_port_table= alloc(ip_conf_nr * sizeof(icmp_port_table[0]));
+}
+
+PUBLIC void icmp_init()
+{
+	int i;
+	icmp_port_t *icmp_port;
+
+	assert (BUF_S >= sizeof (nwio_ipopt_t));
+
+	for (i= 0, icmp_port= icmp_port_table; i<ip_conf_nr; i++, icmp_port++)
+	{
+		icmp_port->icp_flags= ICPF_EMPTY;
+		icmp_port->icp_state= ICPS_BEGIN;
+		icmp_port->icp_ipport= i;
+		icmp_port->icp_rate_count= 0;
+		icmp_port->icp_rate_report= ICMP_MAX_RATE;
+		icmp_port->icp_rate_lasttime= 0;
+		ev_init(&icmp_port->icp_event);
+	}
+
+#ifndef BUF_CONSISTENCY_CHECK
+	bf_logon(icmp_buffree);
+#else
+	bf_logon(icmp_buffree, icmp_bufcheck);
+#endif
+
+	for (i= 0, icmp_port= icmp_port_table; i<ip_conf_nr; i++, icmp_port++)
+	{
+		icmp_main (icmp_port);
+	}
+}
+
+PRIVATE void icmp_main(icmp_port)
+icmp_port_t *icmp_port;
+{
+	int result;
+	switch (icmp_port->icp_state)
+	{
+	case ICPS_BEGIN:
+		icmp_port->icp_head_queue= 0;
+		icmp_port->icp_ipfd= ip_open(icmp_port->icp_ipport,
+			icmp_port->icp_ipport, icmp_getdata, icmp_putdata,
+			0 /* no put_pkt */, 0 /* no select_res */);
+		if (icmp_port->icp_ipfd<0)
+		{
+			DBLOCK(1, printf("unable to open ip_port %d\n",
+				icmp_port->icp_ipport));
+			break;
+		}
+		icmp_port->icp_state= ICPS_IPOPT;
+		icmp_port->icp_flags &= ~ICPF_SUSPEND;
+		result= ip_ioctl (icmp_port->icp_ipfd, NWIOSIPOPT);
+		if (result == NW_SUSPEND)
+		{
+			icmp_port->icp_flags |= ICPF_SUSPEND;
+			break;
+		}
+		assert(result == NW_OK);
+
+		/* falls through */
+	case ICPS_IPOPT:
+		icmp_port->icp_state= ICPS_MAIN;
+		icmp_port->icp_flags &= ~ICPF_SUSPEND;
+		icmp_read(icmp_port);
+		break;
+	default:
+		DBLOCK(1, printf("unknown state %d\n",
+			icmp_port->icp_state));
+		break;
+	}
+}
+
+PRIVATE acc_t *icmp_getdata(port, offset, count, for_ioctl)
+int port;
+size_t offset, count;
+int for_ioctl;
+{
+	icmp_port_t *icmp_port;
+	nwio_ipopt_t *ipopt;
+	acc_t *data;
+	int result;
+	ev_arg_t ev_arg;
+
+	icmp_port= &icmp_port_table[port];
+
+	if (icmp_port->icp_flags & ICPF_WRITE_IP)
+	{
+		if (!count)
+		{
+			bf_afree(icmp_port->icp_write_pack);
+			icmp_port->icp_write_pack= 0;
+
+			result= (int)offset;
+			if (result<0)
+			{
+				DBLOCK(1, printf("got write error %d\n",
+					result));
+			}
+			if (icmp_port->icp_flags & ICPF_WRITE_SP)
+			{
+				icmp_port->icp_flags &= ~ICPF_WRITE_SP;
+				ev_arg.ev_ptr= icmp_port;
+				ev_enqueue(&icmp_port->icp_event, icmp_write,
+					ev_arg);
+			}
+			return NW_OK;
+		}
+		return bf_cut(icmp_port->icp_write_pack, offset, count);
+	}
+	switch (icmp_port->icp_state)
+	{
+	case ICPS_IPOPT:
+		if (!count)
+		{
+			result= (int)offset;
+			assert(result == NW_OK);
+			if (result < 0)
+			{
+				icmp_port->icp_state= ICPS_ERROR;
+				break;
+			}
+			if (icmp_port->icp_flags & ICPF_SUSPEND)
+				icmp_main(icmp_port);
+			return NW_OK;
+		}
+
+		data= bf_memreq (sizeof (*ipopt));
+		ipopt= (nwio_ipopt_t *)ptr2acc_data(data);
+		ipopt->nwio_flags= NWIO_COPY | NWIO_EN_LOC |
+			NWIO_EN_BROAD |
+			NWIO_REMANY | NWIO_PROTOSPEC |
+			NWIO_HDR_O_ANY | NWIO_RWDATALL;
+		ipopt->nwio_proto= IPPROTO_ICMP;
+		return data;
+	default:
+		break;
+	}
+	DBLOCK(1, printf("unknown state %d\n", icmp_port->icp_state));
+	return NULL;
+}
+
+PRIVATE int icmp_putdata(port, offset, data, for_ioctl)
+int port;
+size_t offset;
+acc_t *data;
+int for_ioctl;
+{
+	icmp_port_t *icmp_port;
+	int result;
+
+	icmp_port= &icmp_port_table[port];
+
+	if (icmp_port->icp_flags & ICPF_READ_IP)
+	{
+		if (!data)
+		{
+			result= (int)offset;
+			if (result<0)
+			{
+				DBLOCK(1, printf("got read error %d\n",
+					result));
+			}
+			if (icmp_port->icp_flags & ICPF_READ_SP)
+			{
+				icmp_port->icp_flags &=
+					~(ICPF_READ_IP|ICPF_READ_SP);
+				icmp_read (icmp_port);
+			}
+			return NW_OK;
+		}
+		process_data(icmp_port, data);
+		return NW_OK;
+	}
+	switch (icmp_port->icp_state)
+	{
+	default:
+		DBLOCK(1, printf("unknown state %d\n",
+			icmp_port->icp_state));
+		return 0;
+	}
+}
+
+PRIVATE void icmp_read(icmp_port)
+icmp_port_t *icmp_port;
+{
+	int result;
+
+	for (;;)
+	{
+		icmp_port->icp_flags |= ICPF_READ_IP;
+		icmp_port->icp_flags &= ~ICPF_READ_SP;
+
+		result= ip_read(icmp_port->icp_ipfd, ICMP_MAX_DATAGRAM);
+		if (result == NW_SUSPEND)
+		{
+			icmp_port->icp_flags |= ICPF_READ_SP;
+			return;
+		}
+	}
+}
+
+PUBLIC void icmp_snd_time_exceeded(port_nr, pack, code)
+int port_nr;
+acc_t *pack;
+int code;
+{
+	icmp_hdr_t *icmp_hdr;
+	icmp_port_t *icmp_port;
+
+	if (port_nr >= 0 && port_nr < ip_conf_nr)
+		icmp_port= &icmp_port_table[port_nr];
+	else
+	{
+		printf("icmp_snd_time_exceeded: strange port %d\n", port_nr);
+		bf_afree(pack);
+		return;
+	}
+	pack= icmp_err_pack(pack, &icmp_hdr);
+	if (pack == NULL)
+		return;
+	icmp_hdr->ih_type= ICMP_TYPE_TIME_EXCEEDED;
+	icmp_hdr->ih_code= code;
+	icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,
+		(u16_t *)&icmp_hdr->ih_type, 2);
+	enqueue_pack(icmp_port, pack);
+}
+
+PUBLIC void icmp_snd_redirect(port_nr, pack, code, gw)
+int port_nr;
+acc_t *pack;
+int code;
+ipaddr_t gw;
+{
+	icmp_hdr_t *icmp_hdr;
+	icmp_port_t *icmp_port;
+
+	if (port_nr >= 0 && port_nr < ip_conf_nr)
+		icmp_port= &icmp_port_table[port_nr];
+	else
+	{
+		printf("icmp_snd_redirect: strange port %d\n", port_nr);
+		bf_afree(pack);
+		return;
+	}
+	pack= icmp_err_pack(pack, &icmp_hdr);
+	if (pack == NULL)
+		return;
+	icmp_hdr->ih_type= ICMP_TYPE_REDIRECT;
+	icmp_hdr->ih_code= code;
+	icmp_hdr->ih_hun.ihh_gateway= gw;
+	icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,
+		(u16_t *)&icmp_hdr->ih_type, 2);
+	icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,
+		(u16_t *)&icmp_hdr->ih_hun.ihh_gateway, 4);
+	enqueue_pack(icmp_port, pack);
+}
+
+PUBLIC void icmp_snd_unreachable(port_nr, pack, code)
+int port_nr;
+acc_t *pack;
+int code;
+{
+	icmp_hdr_t *icmp_hdr;
+	icmp_port_t *icmp_port;
+
+	if (port_nr >= 0 && port_nr < ip_conf_nr)
+		icmp_port= &icmp_port_table[port_nr];
+	else
+	{
+		printf("icmp_snd_unreachable: strange port %d\n", port_nr);
+		bf_afree(pack);
+		return;
+	}
+	pack= icmp_err_pack(pack, &icmp_hdr);
+	if (pack == NULL)
+		return;
+	icmp_hdr->ih_type= ICMP_TYPE_DST_UNRCH;
+	icmp_hdr->ih_code= code;
+	icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,
+		(u16_t *)&icmp_hdr->ih_type, 2);
+	enqueue_pack(icmp_port, pack);
+}
+
+PUBLIC void icmp_snd_mtu(port_nr, pack, mtu)
+int port_nr;
+acc_t *pack;
+u16_t mtu;
+{
+	icmp_hdr_t *icmp_hdr;
+	icmp_port_t *icmp_port;
+
+	if (port_nr >= 0 && port_nr < ip_conf_nr)
+		icmp_port= &icmp_port_table[port_nr];
+	else
+	{
+		printf("icmp_snd_mtu: strange port %d\n", port_nr);
+		bf_afree(pack);
+		return;
+	}
+
+	pack= icmp_err_pack(pack, &icmp_hdr);
+	if (pack == NULL)
+		return;
+	icmp_hdr->ih_type= ICMP_TYPE_DST_UNRCH;
+	icmp_hdr->ih_code= ICMP_FRAGM_AND_DF;
+	icmp_hdr->ih_hun.ihh_mtu.im_mtu= htons(mtu);
+	icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,
+		(u16_t *)&icmp_hdr->ih_type, 2);
+	icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,
+		(u16_t *)&icmp_hdr->ih_hun.ihh_mtu.im_mtu, 2);
+	enqueue_pack(icmp_port, pack);
+}
+
+PRIVATE void process_data(icmp_port, data)
+icmp_port_t *icmp_port;
+acc_t *data;
+{
+	ip_hdr_t *ip_hdr;
+	icmp_hdr_t *icmp_hdr;
+	acc_t *icmp_data;
+	int ip_hdr_len;
+	size_t pack_len;
+
+	/* Align entire packet */
+	data= bf_align(data, BUF_S, 4);
+
+	data= bf_packIffLess(data, IP_MIN_HDR_SIZE);
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
+	DIFBLOCK(0x10, (ip_hdr->ih_dst & HTONL(0xf0000000)) == HTONL(0xe0000000),
+		printf("got multicast packet\n"));
+	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
+
+	if (ip_hdr_len>IP_MIN_HDR_SIZE)
+	{
+		data= bf_packIffLess(data, ip_hdr_len);
+		ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
+	}
+
+	pack_len= bf_bufsize(data);
+	pack_len -= ip_hdr_len;
+	if (pack_len < ICMP_MIN_HDR_SIZE)
+	{
+		if (pack_len == 0 && ip_hdr->ih_proto == 0)
+		{
+			/* IP layer reports new ip address, which can be
+			 * ignored.
+			 */
+		}
+		else
+			DBLOCK(1, printf("got an incomplete icmp packet\n"));
+		bf_afree(data);
+		return;
+	}
+
+	icmp_data= bf_cut(data, ip_hdr_len, pack_len);
+
+	icmp_data= bf_packIffLess (icmp_data, ICMP_MIN_HDR_SIZE);
+	icmp_hdr= (icmp_hdr_t *)ptr2acc_data(icmp_data);
+
+	if ((u16_t)~icmp_pack_oneCsum(icmp_data))
+	{
+		DBLOCK(1, printf(
+			"got packet with bad checksum (= 0x%x, 0x%x)\n",
+			icmp_hdr->ih_chksum,
+			(u16_t)~icmp_pack_oneCsum(icmp_data)));
+		bf_afree(data);
+		bf_afree(icmp_data);
+		return;
+	}
+
+	switch (icmp_hdr->ih_type)
+	{
+	case ICMP_TYPE_ECHO_REPL:
+		break;
+	case ICMP_TYPE_DST_UNRCH:
+		icmp_dst_unreach (icmp_port, data, ip_hdr_len, ip_hdr,
+			icmp_data, pack_len, icmp_hdr);
+		break;
+	case ICMP_TYPE_SRC_QUENCH:
+		/* Ignore src quench ICMPs */
+		DBLOCK(2, printf("ignoring SRC QUENCH ICMP.\n"));
+		break;
+	case ICMP_TYPE_REDIRECT:
+		icmp_redirect (icmp_port, ip_hdr, icmp_data, pack_len,
+			icmp_hdr);
+		break;
+	case ICMP_TYPE_ECHO_REQ:
+		icmp_echo_request(icmp_port, data, ip_hdr_len, ip_hdr,
+			icmp_data, pack_len, icmp_hdr);
+		return;
+	case ICMP_TYPE_ROUTER_ADVER:
+		icmp_router_advertisement(icmp_port, icmp_data, pack_len, 
+			icmp_hdr);
+		break;
+	case ICMP_TYPE_ROUTE_SOL:
+		break;	/* Should be handled by a routing deamon. */
+	case ICMP_TYPE_TIME_EXCEEDED:
+		icmp_time_exceeded (icmp_port, data, ip_hdr_len, ip_hdr,
+			icmp_data, pack_len, icmp_hdr);
+		break;
+	default:
+		DBLOCK(1, printf("got an unknown icmp (%d) from ",
+			icmp_hdr->ih_type); 
+			writeIpAddr(ip_hdr->ih_src); printf("\n"));
+		break;
+	}
+	bf_afree(data);
+	bf_afree(icmp_data);
+}
+
+PRIVATE void icmp_echo_request(icmp_port, ip_data, ip_len, ip_hdr,
+	icmp_data, icmp_len, icmp_hdr)
+icmp_port_t *icmp_port;
+acc_t *ip_data, *icmp_data;
+int ip_len, icmp_len;
+ip_hdr_t *ip_hdr;
+icmp_hdr_t *icmp_hdr;
+{
+	acc_t *repl_ip_hdr, *repl_icmp;
+	ipaddr_t tmpaddr, locaddr, netmask;
+	icmp_hdr_t *repl_icmp_hdr;
+	i32_t tmp_chksum;
+	ip_port_t *ip_port;
+
+	if (icmp_hdr->ih_code != 0)
+	{
+		DBLOCK(1,
+		printf("got an icmp echo request with unknown code (%d)\n",
+			icmp_hdr->ih_code));
+		bf_afree(ip_data);
+		bf_afree(icmp_data);
+		return;
+	}
+	if (icmp_len < ICMP_MIN_HDR_SIZE + sizeof(icmp_id_seq_t))
+	{
+		DBLOCK(1, printf("got an incomplete icmp echo request\n"));
+		bf_afree(ip_data);
+		bf_afree(icmp_data);
+		return;
+	}
+	tmpaddr= ntohl(ip_hdr->ih_dst);
+	if ((tmpaddr & 0xe0000000) == 0xe0000000 &&
+		tmpaddr != 0xffffffff)
+	{
+		/* Respond only to the all hosts multicast address until
+		 * a decent listening service has been implemented
+		 */
+		if (tmpaddr != 0xe0000001)
+		{
+			bf_afree(ip_data);
+			bf_afree(icmp_data);
+			return;
+		}
+	}
+
+	/* Limit subnet broadcasts to the local net */
+	ip_port= &ip_port_table[icmp_port->icp_ipport];
+	locaddr= ip_port->ip_ipaddr;
+	netmask= ip_port->ip_subnetmask;
+	if (ip_hdr->ih_dst == (locaddr | ~netmask) &&
+		(ip_port->ip_flags & IPF_SUBNET_BCAST) &&
+		((ip_hdr->ih_src ^ locaddr) & netmask) != 0)
+	{
+		/* Directed broadcast */
+		bf_afree(ip_data);
+		bf_afree(icmp_data);
+		return;
+	}
+
+	repl_ip_hdr= make_repl_ip(ip_hdr, ip_len);
+	repl_icmp= bf_memreq (ICMP_MIN_HDR_SIZE);
+	repl_icmp_hdr= (icmp_hdr_t *)ptr2acc_data(repl_icmp);
+	repl_icmp_hdr->ih_type= ICMP_TYPE_ECHO_REPL;
+	repl_icmp_hdr->ih_code= 0;
+
+	DBLOCK(2,
+	printf("ih_chksum= 0x%x, ih_type= 0x%x, repl->ih_type= 0x%x\n",
+		icmp_hdr->ih_chksum, *(u16_t *)&icmp_hdr->ih_type, 
+		*(u16_t *)&repl_icmp_hdr->ih_type));
+	tmp_chksum= (~icmp_hdr->ih_chksum & 0xffff) - 
+		(i32_t)*(u16_t *)&icmp_hdr->ih_type+
+		*(u16_t *)&repl_icmp_hdr->ih_type;
+	tmp_chksum= (tmp_chksum >> 16) + (tmp_chksum & 0xffff);
+	tmp_chksum= (tmp_chksum >> 16) + (tmp_chksum & 0xffff);
+	repl_icmp_hdr->ih_chksum= ~tmp_chksum;
+	DBLOCK(2, printf("sending chksum 0x%x\n", repl_icmp_hdr->ih_chksum));
+
+	repl_ip_hdr->acc_next= repl_icmp;
+	repl_icmp->acc_next= bf_cut (icmp_data, ICMP_MIN_HDR_SIZE,
+		icmp_len - ICMP_MIN_HDR_SIZE);
+
+	bf_afree(ip_data);
+	bf_afree(icmp_data);
+
+	enqueue_pack(icmp_port, repl_ip_hdr);
+}
+
+PRIVATE u16_t icmp_pack_oneCsum(icmp_pack)
+acc_t *icmp_pack;
+{
+	u16_t prev;
+	int odd_byte;
+	char *data_ptr;
+	int length;
+	char byte_buf[2];
+
+	prev= 0;
+
+	odd_byte= FALSE;
+	for (; icmp_pack; icmp_pack= icmp_pack->acc_next)
+	{
+		data_ptr= ptr2acc_data(icmp_pack);
+		length= icmp_pack->acc_length;
+
+		if (!length)
+			continue;
+		if (odd_byte)
+		{
+			byte_buf[1]= *data_ptr;
+			prev= oneC_sum(prev, (u16_t *)byte_buf, 2);
+			data_ptr++;
+			length--;
+			odd_byte= FALSE;
+		}
+		if (length & 1)
+		{
+			odd_byte= TRUE;
+			length--;
+			byte_buf[0]= data_ptr[length];
+		}
+		if (!length)
+			continue;
+		prev= oneC_sum (prev, (u16_t *)data_ptr, length);
+	}
+	if (odd_byte)
+		prev= oneC_sum (prev, (u16_t *)byte_buf, 1);
+	return prev;
+}
+
+PRIVATE acc_t *make_repl_ip(ip_hdr, ip_len)
+ip_hdr_t *ip_hdr;
+int ip_len;
+{
+	ip_hdr_t *repl_ip_hdr;
+	acc_t *repl;
+	int repl_hdr_len;
+
+	if (ip_len>IP_MIN_HDR_SIZE)
+	{
+		DBLOCK(1, printf("ip_hdr options NOT supported (yet?)\n"));
+		ip_len= IP_MIN_HDR_SIZE;
+	}
+
+	repl_hdr_len= IP_MIN_HDR_SIZE;
+
+	repl= bf_memreq(repl_hdr_len);
+
+	repl_ip_hdr= (ip_hdr_t *)ptr2acc_data(repl);
+
+	repl_ip_hdr->ih_vers_ihl= repl_hdr_len >> 2;
+	repl_ip_hdr->ih_tos= ip_hdr->ih_tos;
+	repl_ip_hdr->ih_ttl= ICMP_DEF_TTL;
+	repl_ip_hdr->ih_proto= IPPROTO_ICMP;
+	repl_ip_hdr->ih_dst= ip_hdr->ih_src;
+	repl_ip_hdr->ih_flags_fragoff= 0;
+
+	return repl;
+}
+
+PRIVATE void enqueue_pack(icmp_port, reply_ip_hdr)
+icmp_port_t *icmp_port;
+acc_t *reply_ip_hdr;
+{
+	int r;
+	ev_arg_t ev_arg;
+
+	/* Check rate */
+	if (icmp_port->icp_rate_count >= ICMP_MAX_RATE)
+	{
+		/* Something is going wrong; check policy */
+		r= icmp_rate_limit(icmp_port, reply_ip_hdr);
+		if (r == -1)
+		{
+			bf_afree(reply_ip_hdr);
+			reply_ip_hdr= NULL;
+			return;
+		}
+
+		/* OK, continue */
+	}
+	icmp_port->icp_rate_count++;
+
+	reply_ip_hdr->acc_ext_link= 0;
+
+	if (icmp_port->icp_head_queue)
+	{
+		icmp_port->icp_tail_queue->acc_ext_link=
+			reply_ip_hdr;
+	}
+	else
+	{
+		icmp_port->icp_head_queue= reply_ip_hdr;
+	}
+	reply_ip_hdr->acc_ext_link= NULL;
+	icmp_port->icp_tail_queue= reply_ip_hdr;
+
+	if (!(icmp_port->icp_flags & ICPF_WRITE_IP))
+	{
+		icmp_port->icp_flags |= ICPF_WRITE_IP;
+		ev_arg.ev_ptr= icmp_port;
+		ev_enqueue(&icmp_port->icp_event, icmp_write, ev_arg);
+	}
+}
+
+PRIVATE int icmp_rate_limit(icmp_port, reply_ip_hdr)
+icmp_port_t *icmp_port;
+acc_t *reply_ip_hdr;
+{
+	time_t t;
+	acc_t *pack;
+	ip_hdr_t *ip_hdr;
+	icmp_hdr_t *icmp_hdr;
+	int hdrlen, icmp_hdr_len, type;
+
+	/* Check the time first */
+	t= get_time();
+	if (t >= icmp_port->icp_rate_lasttime + ICMP_RATE_INTERVAL)
+	{
+		icmp_port->icp_rate_lasttime= t;
+		icmp_port->icp_rate_count= 0;
+		return 0;
+	}
+
+	icmp_port->icp_rate_count++;
+
+	/* Adjust report limit if necessary */
+	if (icmp_port->icp_rate_count >
+		icmp_port->icp_rate_report+ICMP_RATE_WARN)
+	{
+		icmp_port->icp_rate_report *= 2;
+		return -1;
+	}
+
+	/* Do we need to report */
+	if (icmp_port->icp_rate_count < icmp_port->icp_rate_report)
+		return -1;
+
+	pack= bf_dupacc(reply_ip_hdr);
+	pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
+	printf("icmp[%d]: dropping ICMP packet #%d to ",
+		icmp_port->icp_ipport, icmp_port->icp_rate_count);
+	writeIpAddr(ip_hdr->ih_dst);
+	hdrlen= (ip_hdr->ih_vers_ihl & IH_IHL_MASK)*4;
+	pack= bf_packIffLess(pack, hdrlen+ICMP_MIN_HDR_SIZE);
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
+	icmp_hdr= (icmp_hdr_t *)(ptr2acc_data(pack)+hdrlen);
+	type= icmp_hdr->ih_type;
+	printf(" type %d, code %d\n", type, icmp_hdr->ih_code);
+	switch(type)
+	{
+	case ICMP_TYPE_DST_UNRCH:
+	case ICMP_TYPE_SRC_QUENCH:
+	case ICMP_TYPE_REDIRECT:
+	case ICMP_TYPE_TIME_EXCEEDED:
+	case ICMP_TYPE_PARAM_PROBLEM:
+		icmp_hdr_len= offsetof(struct icmp_hdr, ih_dun);
+		pack= bf_packIffLess(pack,
+			hdrlen+icmp_hdr_len+IP_MIN_HDR_SIZE);
+		ip_hdr= (ip_hdr_t *)(ptr2acc_data(pack)+hdrlen+icmp_hdr_len);
+		icmp_hdr= (icmp_hdr_t *)(ptr2acc_data(pack)+hdrlen);
+		printf("\tinfo %08x, original dst ",
+			ntohs(icmp_hdr->ih_hun.ihh_unused));
+		writeIpAddr(ip_hdr->ih_dst);
+		printf(", proto %d, length %u\n",
+			ip_hdr->ih_proto, ntohs(ip_hdr->ih_length));
+		break;
+	default:
+		break;
+	}
+	bf_afree(pack); pack= NULL;
+
+	return -1;
+}
+
+PRIVATE void icmp_write(ev, ev_arg)
+event_t *ev;
+ev_arg_t ev_arg;
+{
+	int result;
+	icmp_port_t *icmp_port;
+	acc_t *data;
+
+	icmp_port= ev_arg.ev_ptr;
+	assert(ev == &icmp_port->icp_event);
+
+	assert (icmp_port->icp_flags & ICPF_WRITE_IP);
+	assert (!(icmp_port->icp_flags & ICPF_WRITE_SP));
+
+	while (icmp_port->icp_head_queue != NULL)
+	{
+		data= icmp_port->icp_head_queue;
+		icmp_port->icp_head_queue= data->acc_ext_link;
+
+		result= ip_send(icmp_port->icp_ipfd, data,
+			bf_bufsize(data));
+		if (result != NW_WOULDBLOCK)
+		{
+			if (result == NW_OK)
+				continue;
+			DBLOCK(1, printf("icmp_write: error %d\n", result););
+			continue;
+		}
+
+		assert(icmp_port->icp_write_pack == NULL);
+		icmp_port->icp_write_pack= data;
+			
+		result= ip_write(icmp_port->icp_ipfd,
+			bf_bufsize(icmp_port->icp_write_pack));
+		if (result == NW_SUSPEND)
+		{
+			icmp_port->icp_flags |= ICPF_WRITE_SP;
+			return;
+		}
+	}
+	icmp_port->icp_flags &= ~ICPF_WRITE_IP;
+}
+
+PRIVATE void icmp_buffree(priority)
+int priority;
+{
+	acc_t *tmp_acc;
+	int i;
+	icmp_port_t *icmp_port;
+
+	if (priority == ICMP_PRI_QUEUE)
+	{
+		for (i=0, icmp_port= icmp_port_table; i<ip_conf_nr;
+			i++, icmp_port++)
+		{
+			while(icmp_port->icp_head_queue)
+			{
+				tmp_acc= icmp_port->icp_head_queue;
+				icmp_port->icp_head_queue=
+					tmp_acc->acc_ext_link;
+				bf_afree(tmp_acc);
+			}
+		}
+	}
+}
+
+#ifdef BUF_CONSISTENCY_CHECK
+PRIVATE void icmp_bufcheck()
+{
+	int i;
+	icmp_port_t *icmp_port;
+	acc_t *pack;
+
+	for (i= 0, icmp_port= icmp_port_table; i<ip_conf_nr; i++, icmp_port++)
+	{
+		for (pack= icmp_port->icp_head_queue; pack; 
+			pack= pack->acc_ext_link)
+		{
+			bf_check_acc(pack);
+		}
+		bf_check_acc(icmp_port->icp_write_pack);
+	}
+}
+#endif
+
+PRIVATE void icmp_dst_unreach(icmp_port, ip_pack, ip_hdr_len, ip_hdr, icmp_pack,
+	icmp_len, icmp_hdr)
+icmp_port_t *icmp_port;
+acc_t *ip_pack;
+int ip_hdr_len;
+ip_hdr_t *ip_hdr;
+acc_t *icmp_pack;
+int icmp_len;
+icmp_hdr_t *icmp_hdr;
+{
+	acc_t *old_ip_pack;
+	ip_hdr_t *old_ip_hdr;
+	int ip_port_nr;
+	ipaddr_t dst, mask;
+	size_t old_pack_size;
+	u16_t new_mtu;
+
+	if (icmp_len < 8 + IP_MIN_HDR_SIZE)
+	{
+		DBLOCK(1, printf("dest unrch with wrong size\n"));
+		return;
+	}
+	old_ip_pack= bf_cut (icmp_pack, 8, icmp_len-8);
+	old_ip_pack= bf_packIffLess(old_ip_pack, IP_MIN_HDR_SIZE);
+	old_ip_hdr= (ip_hdr_t *)ptr2acc_data(old_ip_pack);
+
+	if (old_ip_hdr->ih_src != ip_hdr->ih_dst)
+	{
+		DBLOCK(1, printf("dest unrch based on wrong packet\n"));
+		bf_afree(old_ip_pack);
+		return;
+	}
+
+	ip_port_nr= icmp_port->icp_ipport;
+
+	switch(icmp_hdr->ih_code)
+	{
+	case ICMP_NET_UNRCH:
+		dst= old_ip_hdr->ih_dst;
+		mask= ip_get_netmask(dst);
+		ipr_destunrch (ip_port_nr, dst & mask, mask,
+			IPR_UNRCH_TIMEOUT);
+		break;
+	case ICMP_HOST_UNRCH:
+		ipr_destunrch (ip_port_nr, old_ip_hdr->ih_dst, (ipaddr_t)-1,
+			IPR_UNRCH_TIMEOUT);
+		break;
+	case ICMP_PORT_UNRCH:
+		/* At the moment we don't do anything with this information.
+		 * It should be handed to the appropriate transport layer.
+		 */
+		break;
+	case ICMP_FRAGM_AND_DF:
+
+		DBLOCK(1, printf("icmp_dst_unreach: got mtu icmp from ");
+			writeIpAddr(ip_hdr->ih_src);
+			printf("; original destination: ");
+			writeIpAddr(old_ip_hdr->ih_dst);
+			printf("; protocol: %d\n",
+			old_ip_hdr->ih_proto));
+		old_pack_size= ntohs(old_ip_hdr->ih_length);
+		if (!old_pack_size)
+			break;
+		new_mtu= ntohs(icmp_hdr->ih_hun.ihh_mtu.im_mtu);
+		if (!new_mtu || new_mtu > old_pack_size)
+			new_mtu= old_pack_size-1;
+		ipr_mtu(ip_port_nr, old_ip_hdr->ih_dst, new_mtu,
+			IPR_MTU_TIMEOUT);
+		break;
+
+	default:
+		DBLOCK(1, printf("icmp_dst_unreach: got strange code %d from ",
+			icmp_hdr->ih_code);
+			writeIpAddr(ip_hdr->ih_src);
+			printf("; original destination: ");
+			writeIpAddr(old_ip_hdr->ih_dst);
+			printf("; protocol: %d\n",
+			old_ip_hdr->ih_proto));
+		break;
+	}
+	bf_afree(old_ip_pack);
+}
+
+PRIVATE void icmp_time_exceeded(icmp_port, ip_pack, ip_hdr_len, ip_hdr,
+	icmp_pack, icmp_len, icmp_hdr)
+icmp_port_t *icmp_port;
+acc_t *ip_pack;
+int ip_hdr_len;
+ip_hdr_t *ip_hdr;
+acc_t *icmp_pack;
+int icmp_len;
+icmp_hdr_t *icmp_hdr;
+{
+	acc_t *old_ip_pack;
+	ip_hdr_t *old_ip_hdr;
+	int ip_port_nr;
+
+	if (icmp_len < 8 + IP_MIN_HDR_SIZE)
+	{
+		DBLOCK(1, printf("time exceeded with wrong size\n"));
+		return;
+	}
+	old_ip_pack= bf_cut (icmp_pack, 8, icmp_len-8);
+	old_ip_pack= bf_packIffLess(old_ip_pack, IP_MIN_HDR_SIZE);
+	old_ip_hdr= (ip_hdr_t *)ptr2acc_data(old_ip_pack);
+
+	if (old_ip_hdr->ih_src != ip_hdr->ih_dst)
+	{
+		DBLOCK(1, printf("time exceeded based on wrong packet\n"));
+		bf_afree(old_ip_pack);
+		return;
+	}
+
+	ip_port_nr= icmp_port->icp_ipport;
+
+	switch(icmp_hdr->ih_code)
+	{
+	case ICMP_TTL_EXC:
+		ipr_ttl_exc (ip_port_nr, old_ip_hdr->ih_dst, (ipaddr_t)-1,
+			IPR_TTL_TIMEOUT);
+		break;
+	case ICMP_FRAG_REASSEM:
+		/* Ignore reassembly time-outs. */
+		break;
+	default:
+		DBLOCK(1, printf("got strange code: %d\n",
+			icmp_hdr->ih_code));
+		break;
+	}
+	bf_afree(old_ip_pack);
+}
+
+PRIVATE void icmp_router_advertisement(icmp_port, icmp_pack, icmp_len, icmp_hdr)
+icmp_port_t *icmp_port;
+acc_t *icmp_pack;
+int icmp_len;
+icmp_hdr_t *icmp_hdr;
+{
+	int entries;
+	int entry_size;
+	u32_t addr;
+	i32_t pref;
+	u16_t lifetime;
+	int i;
+	char *bufp;
+	ip_port_t *ip_port;
+
+	if (icmp_len < 8)
+	{
+		DBLOCK(1,
+		printf("router advertisement with wrong size (%d)\n",
+			icmp_len));
+		return;
+	}
+	if (icmp_hdr->ih_code != 0)
+	{
+		DBLOCK(1,
+		printf("router advertisement with wrong code (%d)\n", 
+			icmp_hdr->ih_code));
+		return;
+	}
+	entries= icmp_hdr->ih_hun.ihh_ram.iram_na;
+	entry_size= icmp_hdr->ih_hun.ihh_ram.iram_aes * 4;
+	if (entries < 1)
+	{
+		DBLOCK(1, printf(
+		"router advertisement with wrong number of entries (%d)\n", 
+			entries));
+		return;
+	}
+	if (entry_size < 8)
+	{
+		DBLOCK(1, printf(
+		"router advertisement with wrong entry size (%d)\n", 
+			entry_size));
+		return;
+	}
+	if (icmp_len < 8 + entries * entry_size)
+	{
+		DBLOCK(1,
+			printf("router advertisement with wrong size\n"); 
+			printf(
+			"\t(entries= %d, entry_size= %d, icmp_len= %d)\n",
+			entries, entry_size, icmp_len));
+		return;
+	}
+	lifetime= ntohs(icmp_hdr->ih_hun.ihh_ram.iram_lt);
+	if (lifetime > 9000)
+	{
+		DBLOCK(1, printf(
+			"router advertisement with wrong lifetime (%d)\n",
+			lifetime));
+		return;
+	}
+	ip_port= &ip_port_table[icmp_port->icp_ipport];
+	for (i= 0, bufp= (char *)&icmp_hdr->ih_dun.uhd_data[0]; i< entries; i++,
+		bufp += entry_size)
+	{
+		addr= *(ipaddr_t *)bufp;
+		pref= ntohl(*(u32_t *)(bufp+4));
+		ipr_add_oroute(icmp_port->icp_ipport, HTONL(0L), HTONL(0L), 
+			addr, lifetime ? lifetime * HZ : 1,
+			1, 0, 0, pref, NULL);
+	}
+}
+		
+PRIVATE void icmp_redirect(icmp_port, ip_hdr, icmp_pack, icmp_len, icmp_hdr)
+icmp_port_t *icmp_port;
+ip_hdr_t *ip_hdr;
+acc_t *icmp_pack;
+int icmp_len;
+icmp_hdr_t *icmp_hdr;
+{
+	acc_t *old_ip_pack;
+	ip_hdr_t *old_ip_hdr;
+	int ip_port_nr;
+	ipaddr_t dst, mask;
+
+	if (icmp_len < 8 + IP_MIN_HDR_SIZE)
+	{
+		DBLOCK(1, printf("redirect with wrong size\n"));
+		return;
+	}
+	old_ip_pack= bf_cut (icmp_pack, 8, icmp_len-8);
+	old_ip_pack= bf_packIffLess(old_ip_pack, IP_MIN_HDR_SIZE);
+	old_ip_hdr= (ip_hdr_t *)ptr2acc_data(old_ip_pack);
+
+	ip_port_nr= icmp_port->icp_ipport;
+
+	switch(icmp_hdr->ih_code)
+	{
+	case ICMP_REDIRECT_NET:
+		dst= old_ip_hdr->ih_dst;
+		mask= ip_get_netmask(dst);
+		ipr_redirect (ip_port_nr, dst & mask, mask,
+			ip_hdr->ih_src, icmp_hdr->ih_hun.ihh_gateway, 
+			IPR_REDIRECT_TIMEOUT);
+		break;
+	case ICMP_REDIRECT_HOST:
+		ipr_redirect (ip_port_nr, old_ip_hdr->ih_dst, (ipaddr_t)-1,
+			ip_hdr->ih_src, icmp_hdr->ih_hun.ihh_gateway, 
+			IPR_REDIRECT_TIMEOUT);
+		break;
+	default:
+		DBLOCK(1, printf("got strange code: %d\n",
+			icmp_hdr->ih_code));
+		break;
+	}
+	bf_afree(old_ip_pack);
+}
+
+PRIVATE acc_t *icmp_err_pack(pack, icmp_hdr_pp)
+acc_t *pack;
+icmp_hdr_t **icmp_hdr_pp;
+{
+	ip_hdr_t *ip_hdr;
+	icmp_hdr_t *icmp_hdr_p;
+	acc_t *ip_pack, *icmp_pack, *tmp_pack;
+	int ip_hdr_len, icmp_hdr_len, ih_type;
+	size_t size, pack_len;
+	ipaddr_t dest, netmask;
+	nettype_t nettype;
+
+	pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
+	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
+	pack_len= bf_bufsize(pack);
+
+	/* If the IP protocol is ICMP (except echo request/reply) or the
+	 * fragment offset is non-zero,
+	 * drop the packet. Also check if the source address is valid.
+	 */
+	if ((ntohs(ip_hdr->ih_flags_fragoff) & IH_FRAGOFF_MASK) != 0)
+	{
+		bf_afree(pack);
+		return NULL;
+	}
+	if (ip_hdr->ih_proto == IPPROTO_ICMP)
+	{
+		if (ip_hdr_len>IP_MIN_HDR_SIZE)
+		{
+			pack= bf_packIffLess(pack, ip_hdr_len);
+			ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
+		}
+
+		if (pack_len < ip_hdr_len+ICMP_MIN_HDR_SIZE)
+		{
+			bf_afree(pack);
+			return NULL;
+		}
+		icmp_pack= bf_cut(pack, ip_hdr_len, ICMP_MIN_HDR_SIZE);
+		icmp_pack= bf_packIffLess (icmp_pack, ICMP_MIN_HDR_SIZE);
+		icmp_hdr_p= (icmp_hdr_t *)ptr2acc_data(icmp_pack);
+		ih_type= icmp_hdr_p->ih_type;
+		bf_afree(icmp_pack); icmp_pack= NULL;
+
+		if (ih_type != ICMP_TYPE_ECHO_REQ &&
+			ih_type != ICMP_TYPE_ECHO_REPL)
+		{
+			bf_afree(pack);
+			return NULL;
+		}
+	}
+	dest= ip_hdr->ih_src;
+	nettype= ip_nettype(dest);
+	netmask= ip_netmask(nettype);
+	if (nettype != IPNT_CLASS_A && nettype != IPNT_LOCAL &&
+		nettype != IPNT_CLASS_B && nettype != IPNT_CLASS_C)
+	{
+		printf("icmp_err_pack: invalid source address: ");
+		writeIpAddr(dest);
+		printf("\n");
+		bf_afree(pack);
+		return NULL;
+	}
+
+	/* Take the IP header and the first 64 bits of user data. */
+	size= ntohs(ip_hdr->ih_length);
+	if (size < ip_hdr_len || pack_len < size)
+	{
+		printf("icmp_err_pack: wrong packet size:\n");
+		printf("\thdrlen= %d, ih_length= %d, bufsize= %d\n",
+			ip_hdr_len, size, pack_len);
+		bf_afree(pack);
+		return NULL;
+	}
+	if (ip_hdr_len + 8 < size)
+		size= ip_hdr_len+8;
+	tmp_pack= bf_cut(pack, 0, size);
+	bf_afree(pack);
+	pack= tmp_pack;
+	tmp_pack= NULL;
+
+	/* Create a minimal size ICMP hdr. */
+	icmp_hdr_len= offsetof(icmp_hdr_t, ih_dun);
+	icmp_pack= bf_memreq(icmp_hdr_len);
+	pack= bf_append(icmp_pack, pack);
+	size += icmp_hdr_len;
+	pack= bf_packIffLess(pack, icmp_hdr_len);
+	icmp_hdr_p= (icmp_hdr_t *)ptr2acc_data(pack);
+	icmp_hdr_p->ih_type= 0;
+	icmp_hdr_p->ih_code= 0;
+	icmp_hdr_p->ih_chksum= 0;
+	icmp_hdr_p->ih_hun.ihh_unused= 0;
+	icmp_hdr_p->ih_chksum= ~icmp_pack_oneCsum(pack);
+	*icmp_hdr_pp= icmp_hdr_p;
+
+	/* Create an IP header */
+	ip_hdr_len= IP_MIN_HDR_SIZE;
+
+	ip_pack= bf_memreq(ip_hdr_len);
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_pack);
+
+	ip_hdr->ih_vers_ihl= ip_hdr_len >> 2;
+	ip_hdr->ih_tos= 0;
+	ip_hdr->ih_length= htons(ip_hdr_len + size);
+	ip_hdr->ih_flags_fragoff= 0;
+	ip_hdr->ih_ttl= ICMP_DEF_TTL;
+	ip_hdr->ih_proto= IPPROTO_ICMP;
+	ip_hdr->ih_dst= dest;
+
+	assert(ip_pack->acc_next == NULL);
+	ip_pack->acc_next= pack;
+	return ip_pack;
+}
+
+/*
+ * $PchId: icmp.c,v 1.23 2005/06/28 14:16:56 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/icmp.h
===================================================================
--- /trunk/minix/servers/inet/generic/icmp.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/icmp.h	(revision 9)
@@ -0,0 +1,30 @@
+/*
+icmp.h
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef ICMP_H
+#define ICMP_H
+
+#define ICMP_MAX_DATAGRAM	8196
+#define ICMP_DEF_TTL		96
+
+/* Rate limit. The implementation is a bit sloppy and may send twice the
+ * number of packets. 
+ */
+#define ICMP_MAX_RATE		100	/* This many per interval */
+#define ICMP_RATE_INTERVAL	(1*HZ)	/* Interval in ticks */
+#define ICMP_RATE_WARN		10	/* Report this many dropped packets */
+
+/* Prototypes */
+
+void icmp_prep ARGS(( void ));
+void icmp_init ARGS(( void ));
+
+
+#endif /* ICMP_H */
+
+/*
+ * $PchId: icmp.h,v 1.7 2001/04/19 19:06:18 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/icmp_lib.h
===================================================================
--- /trunk/minix/servers/inet/generic/icmp_lib.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/icmp_lib.h	(revision 9)
@@ -0,0 +1,25 @@
+/*
+icmp_lib.h
+
+Created Sept 30, 1991 by Philip Homburg
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef ICMP_LIB_H
+#define ICMP_LIB_H
+
+/* Prototypes */
+
+void icmp_snd_parmproblem ARGS(( acc_t *pack ));
+void icmp_snd_time_exceeded ARGS(( int port_nr, acc_t *pack, int code ));
+void icmp_snd_unreachable ARGS(( int port_nr, acc_t *pack, int code ));
+void icmp_snd_redirect ARGS(( int port_nr, acc_t *pack, int code,
+							ipaddr_t gw ));
+void icmp_snd_mtu ARGS(( int port_nr, acc_t *pack, U16_t mtu ));
+
+#endif /* ICMP_LIB_H */
+
+/*
+ * $PchId: icmp_lib.h,v 1.6 2002/06/08 21:32:44 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/io.c
===================================================================
--- /trunk/minix/servers/inet/generic/io.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/io.c	(revision 9)
@@ -0,0 +1,34 @@
+/*
+io.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include <stdlib.h>
+
+#include "inet.h"
+#include "io.h"
+
+PUBLIC void writeIpAddr(addr)
+ipaddr_t addr;
+{
+#define addrInBytes ((u8_t *)&addr)
+
+	printf("%d.%d.%d.%d", addrInBytes[0], addrInBytes[1],
+		addrInBytes[2], addrInBytes[3]);
+#undef addrInBytes
+}
+
+PUBLIC void writeEtherAddr(addr)
+ether_addr_t *addr;
+{
+#define addrInBytes ((u8_t *)addr->ea_addr)
+
+	printf("%x:%x:%x:%x:%x:%x", addrInBytes[0], addrInBytes[1],
+		addrInBytes[2], addrInBytes[3], addrInBytes[4], addrInBytes[5]);
+#undef addrInBytes
+}
+
+/*
+ * $PchId: io.c,v 1.6 1998/10/23 20:24:34 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/io.h
===================================================================
--- /trunk/minix/servers/inet/generic/io.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/io.h	(revision 9)
@@ -0,0 +1,21 @@
+/*
+io.h
+
+Created Sept 30, 1991 by Philip Homburg
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef IO_H
+#define IO_H
+
+/* Prototypes */
+
+void writeIpAddr ARGS(( ipaddr_t addr ));
+void writeEtherAddr ARGS(( ether_addr_t *addr ));
+
+#endif /* IO_H */
+
+/*
+ * $PchId: io.h,v 1.4 1995/11/21 06:45:27 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/ip.c
===================================================================
--- /trunk/minix/servers/inet/generic/ip.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/ip.c	(revision 9)
@@ -0,0 +1,470 @@
+/*
+ip.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "buf.h"
+#include "event.h"
+#include "type.h"
+
+#include "arp.h"
+#include "assert.h"
+#include "clock.h"
+#include "eth.h"
+#include "icmp.h"
+#include "icmp_lib.h"
+#include "io.h"
+#include "ip.h"
+#include "ip_int.h"
+#include "ipr.h"
+#include "sr.h"
+
+THIS_FILE
+
+FORWARD void ip_close ARGS(( int fd ));
+FORWARD int ip_cancel ARGS(( int fd, int which_operation ));
+FORWARD int ip_select ARGS(( int fd, unsigned operations ));
+
+FORWARD void ip_buffree ARGS(( int priority ));
+#ifdef BUF_CONSISTENCY_CHECK
+FORWARD void ip_bufcheck ARGS(( void ));
+#endif
+FORWARD void ip_bad_callback ARGS(( struct ip_port *ip_port ));
+
+PUBLIC ip_port_t *ip_port_table;
+PUBLIC ip_fd_t ip_fd_table[IP_FD_NR];
+PUBLIC ip_ass_t ip_ass_table[IP_ASS_NR];
+
+PUBLIC void ip_prep()
+{
+	ip_port_table= alloc(ip_conf_nr * sizeof(ip_port_table[0]));
+	icmp_prep();
+}
+
+PUBLIC void ip_init()
+{
+	int i, j, result;
+	ip_ass_t *ip_ass;
+	ip_fd_t *ip_fd;
+	ip_port_t *ip_port;
+	struct ip_conf *icp;
+
+	assert (BUF_S >= sizeof(struct nwio_ethopt));
+	assert (BUF_S >= IP_MAX_HDR_SIZE + ETH_HDR_SIZE);
+	assert (BUF_S >= sizeof(nwio_ipopt_t));
+	assert (BUF_S >= sizeof(nwio_route_t));
+
+	for (i=0, ip_ass= ip_ass_table; i<IP_ASS_NR; i++, ip_ass++)
+	{
+		ip_ass->ia_frags= 0;
+		ip_ass->ia_first_time= 0;
+		ip_ass->ia_port= 0;
+	}
+
+	for (i=0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
+	{
+		ip_fd->if_flags= IFF_EMPTY;
+		ip_fd->if_rdbuf_head= 0;
+	}
+
+	for (i=0, ip_port= ip_port_table, icp= ip_conf;
+		i<ip_conf_nr; i++, ip_port++, icp++)
+	{
+		ip_port->ip_port= i;
+		ip_port->ip_flags= IPF_EMPTY;
+		ip_port->ip_dev_main= (ip_dev_t)ip_bad_callback;
+		ip_port->ip_dev_set_ipaddr= (ip_dev_t)ip_bad_callback;
+		ip_port->ip_dev_send= (ip_dev_send_t)ip_bad_callback;
+		ip_port->ip_dl_type= icp->ic_devtype;
+		ip_port->ip_mtu= IP_DEF_MTU;
+		ip_port->ip_mtu_max= IP_MAX_PACKSIZE;
+
+		switch(ip_port->ip_dl_type)
+		{
+		case IPDL_ETH:
+			ip_port->ip_dl.dl_eth.de_port= icp->ic_port;
+			result= ipeth_init(ip_port);
+			if (result == -1)
+				continue;
+			assert(result == NW_OK);
+			break;
+		case IPDL_PSIP:
+			ip_port->ip_dl.dl_ps.ps_port= icp->ic_port;
+			result= ipps_init(ip_port);
+			if (result == -1)
+				continue;
+			assert(result == NW_OK);
+			break;
+		default:
+			ip_panic(( "unknown ip_dl_type %d", 
+							ip_port->ip_dl_type ));
+			break;
+		}
+		ip_port->ip_loopb_head= NULL;
+		ip_port->ip_loopb_tail= NULL;
+		ev_init(&ip_port->ip_loopb_event);
+		ip_port->ip_routeq_head= NULL;
+		ip_port->ip_routeq_tail= NULL;
+		ev_init(&ip_port->ip_routeq_event);
+		ip_port->ip_flags |= IPF_CONFIGURED;
+		ip_port->ip_proto_any= NULL;
+		for (j= 0; j<IP_PROTO_HASH_NR; j++)
+			ip_port->ip_proto[j]= NULL;
+	}
+
+#ifndef BUF_CONSISTENCY_CHECK
+	bf_logon(ip_buffree);
+#else
+	bf_logon(ip_buffree, ip_bufcheck);
+#endif
+
+	icmp_init();
+	ipr_init();
+
+	for (i=0, ip_port= ip_port_table; i<ip_conf_nr; i++, ip_port++)
+	{
+		if (!(ip_port->ip_flags & IPF_CONFIGURED))
+			continue;
+		ip_port->ip_frame_id= (u16_t)get_time();
+
+		sr_add_minor(if2minor(ip_conf[i].ic_ifno, IP_DEV_OFF),
+			i, ip_open, ip_close, ip_read,
+			ip_write, ip_ioctl, ip_cancel, ip_select);
+
+		(*ip_port->ip_dev_main)(ip_port);
+	}
+}
+
+PRIVATE int ip_cancel (fd, which_operation)
+int fd;
+int which_operation;
+{
+	ip_fd_t *ip_fd;
+	acc_t *repl_res;
+	int result;
+
+	ip_fd= &ip_fd_table[fd];
+
+	switch (which_operation)
+	{
+	case SR_CANCEL_IOCTL:
+		assert (ip_fd->if_flags & IFF_IOCTL_IP);
+		ip_fd->if_flags &= ~IFF_IOCTL_IP;
+		repl_res= (*ip_fd->if_get_userdata)(ip_fd->if_srfd, 
+			(size_t)EINTR, (size_t)0, TRUE);
+		assert (!repl_res);
+		break;
+	case SR_CANCEL_READ:
+		assert (ip_fd->if_flags & IFF_READ_IP);
+		ip_fd->if_flags &= ~IFF_READ_IP;
+		result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd, 
+			(size_t)EINTR, (acc_t *)0, FALSE);
+		assert (!result);
+		break;
+#if 0
+	case SR_CANCEL_WRITE:
+		assert(0);
+		assert (ip_fd->if_flags & IFF_WRITE_MASK);
+		ip_fd->if_flags &= ~IFF_WRITE_MASK;
+		repl_res= (*ip_fd->if_get_userdata)(ip_fd->if_srfd, 
+			(size_t)EINTR, (size_t)0, FALSE);
+		assert (!repl_res);
+		break;
+#endif
+	default:
+		ip_panic(( "unknown cancel request" ));
+		break;
+	}
+	return NW_OK;
+}
+
+PRIVATE int ip_select(fd, operations)
+int fd;
+unsigned operations;
+{
+	printf("ip_select: not implemented\n");
+	return 0;
+}
+
+PUBLIC int ip_open (port, srfd, get_userdata, put_userdata, put_pkt,
+	select_res)
+int port;
+int srfd;
+get_userdata_t get_userdata;
+put_userdata_t put_userdata;
+put_pkt_t put_pkt;
+select_res_t select_res;
+{
+	int i;
+	ip_fd_t *ip_fd;
+	ip_port_t *ip_port;
+
+	ip_port= &ip_port_table[port];
+	if (!(ip_port->ip_flags & IPF_CONFIGURED))
+		return ENXIO;
+
+	for (i=0; i<IP_FD_NR && (ip_fd_table[i].if_flags & IFF_INUSE);
+		i++);
+
+	if (i>=IP_FD_NR)
+	{
+		DBLOCK(1, printf("out of fds\n"));
+		return EAGAIN;
+	}
+
+	ip_fd= &ip_fd_table[i];
+
+	ip_fd->if_flags= IFF_INUSE;
+
+	ip_fd->if_ipopt.nwio_flags= NWIO_DEFAULT;
+	ip_fd->if_ipopt.nwio_tos= 0;
+	ip_fd->if_ipopt.nwio_df= FALSE;
+	ip_fd->if_ipopt.nwio_ttl= 255;
+	ip_fd->if_ipopt.nwio_hdropt.iho_opt_siz= 0;
+
+	ip_fd->if_port= ip_port;
+	ip_fd->if_srfd= srfd;
+	assert(ip_fd->if_rdbuf_head == NULL);
+	ip_fd->if_get_userdata= get_userdata;
+	ip_fd->if_put_userdata= put_userdata;
+	ip_fd->if_put_pkt= put_pkt;
+
+	return i;
+}
+
+PRIVATE void ip_close (fd)
+int fd;
+{
+	ip_fd_t *ip_fd;
+	acc_t *pack;
+
+	ip_fd= &ip_fd_table[fd];
+
+	assert ((ip_fd->if_flags & IFF_INUSE) &&
+		!(ip_fd->if_flags & IFF_BUSY));
+
+	if (ip_fd->if_flags & IFF_OPTSET)
+		ip_unhash_proto(ip_fd);
+	while (ip_fd->if_rdbuf_head)
+	{
+		pack= ip_fd->if_rdbuf_head;
+		ip_fd->if_rdbuf_head= pack->acc_ext_link;
+		bf_afree(pack);
+	}
+	ip_fd->if_flags= IFF_EMPTY;
+}
+
+PRIVATE void ip_buffree(priority)
+int priority;
+{
+	int i;
+	ip_port_t *ip_port;
+	ip_fd_t *ip_fd;
+	ip_ass_t *ip_ass;
+	acc_t *pack, *next_pack;
+
+	for (i= 0, ip_port= ip_port_table; i<ip_conf_nr; i++, ip_port++)
+	{
+		if (ip_port->ip_dl_type == IPDL_ETH)
+		{
+			/* Can't free de_frame.
+			 * bf_check_acc(ip_port->ip_dl.dl_eth.de_frame);
+			 */
+			if (priority == IP_PRI_PORTBUFS)
+			{
+				next_pack= ip_port->ip_dl.dl_eth.de_arp_head;
+				while(next_pack != NULL)
+				{
+					pack= next_pack;
+					next_pack= pack->acc_ext_link;
+					bf_afree(pack);
+				}
+				ip_port->ip_dl.dl_eth.de_arp_head= next_pack;
+
+				next_pack= ip_port->ip_dl.dl_eth.de_q_head;
+				while(next_pack != NULL)
+				{
+					pack= next_pack;
+					next_pack= pack->acc_ext_link;
+					bf_afree(pack);
+				}
+				ip_port->ip_dl.dl_eth.de_q_head= next_pack;
+			}
+		}
+		else if (ip_port->ip_dl_type == IPDL_PSIP)
+		{
+			if (priority == IP_PRI_PORTBUFS)
+			{
+				next_pack= ip_port->ip_dl.dl_ps.ps_send_head;
+				while (next_pack != NULL)
+				{
+					pack= next_pack;
+					next_pack= pack->acc_ext_link;
+					bf_afree(pack);
+				}
+				ip_port->ip_dl.dl_ps.ps_send_head= next_pack;
+			}
+		}
+		if (priority == IP_PRI_PORTBUFS)
+		{
+			next_pack= ip_port->ip_loopb_head;
+			while(next_pack && next_pack->acc_ext_link)
+			{
+				pack= next_pack;
+				next_pack= pack->acc_ext_link;
+				bf_afree(pack);
+			}
+			if (next_pack)
+			{
+				if (ev_in_queue(&ip_port->ip_loopb_event))
+				{
+#if DEBUG
+					printf(
+"not freeing ip_loopb_head, ip_loopb_event enqueued\n");
+#endif
+				}
+				else
+				{
+					bf_afree(next_pack);
+					next_pack= NULL;
+				}
+			}
+			ip_port->ip_loopb_head= next_pack;
+
+			next_pack= ip_port->ip_routeq_head;
+			while(next_pack && next_pack->acc_ext_link)
+			{
+				pack= next_pack;
+				next_pack= pack->acc_ext_link;
+				bf_afree(pack);
+			}
+			if (next_pack)
+			{
+				if (ev_in_queue(&ip_port->ip_routeq_event))
+				{
+#if DEBUG
+					printf(
+"not freeing ip_loopb_head, ip_routeq_event enqueued\n");
+#endif
+				}
+				else
+				{
+					bf_afree(next_pack);
+					next_pack= NULL;
+				}
+			}
+			ip_port->ip_routeq_head= next_pack;
+		}
+	}
+	if (priority == IP_PRI_FDBUFS_EXTRA)
+	{
+		for (i= 0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
+		{
+			while (ip_fd->if_rdbuf_head &&
+				ip_fd->if_rdbuf_head->acc_ext_link)
+			{
+				pack= ip_fd->if_rdbuf_head;
+				ip_fd->if_rdbuf_head= pack->acc_ext_link;
+				bf_afree(pack);
+			}
+		}
+	}
+	if (priority == IP_PRI_FDBUFS)
+	{
+		for (i= 0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
+		{
+			while (ip_fd->if_rdbuf_head)
+			{
+				pack= ip_fd->if_rdbuf_head;
+				ip_fd->if_rdbuf_head= pack->acc_ext_link;
+				bf_afree(pack);
+			}
+		}
+	}
+	if (priority == IP_PRI_ASSBUFS)
+	{
+		for (i= 0, ip_ass= ip_ass_table; i<IP_ASS_NR; i++, ip_ass++)
+		{
+			next_pack= ip_ass->ia_frags;
+			while(ip_ass->ia_frags != NULL)
+			{
+				pack= ip_ass->ia_frags;
+				ip_ass->ia_frags= pack->acc_ext_link;
+				bf_afree(pack);
+			}
+			ip_ass->ia_first_time= 0;
+		}
+	}
+}
+
+#ifdef BUF_CONSISTENCY_CHECK
+PRIVATE void ip_bufcheck()
+{
+	int i;
+	ip_port_t *ip_port;
+	ip_fd_t *ip_fd;
+	ip_ass_t *ip_ass;
+	acc_t *pack;
+
+	for (i= 0, ip_port= ip_port_table; i<ip_conf_nr; i++, ip_port++)
+	{
+		if (ip_port->ip_dl_type == IPDL_ETH)
+		{
+			bf_check_acc(ip_port->ip_dl.dl_eth.de_frame);
+			for (pack= ip_port->ip_dl.dl_eth.de_q_head; pack;
+				pack= pack->acc_ext_link)
+			{
+				bf_check_acc(pack);
+			}
+			for (pack= ip_port->ip_dl.dl_eth.de_arp_head; pack;
+				pack= pack->acc_ext_link)
+			{
+				bf_check_acc(pack);
+			}
+		}
+		else if (ip_port->ip_dl_type == IPDL_PSIP)
+		{
+			for (pack= ip_port->ip_dl.dl_ps.ps_send_head; pack;
+				pack= pack->acc_ext_link)
+			{
+				bf_check_acc(pack);
+			}
+		}
+		for (pack= ip_port->ip_loopb_head; pack;
+			pack= pack->acc_ext_link)
+		{
+			bf_check_acc(pack);
+		}
+		for (pack= ip_port->ip_routeq_head; pack;
+			pack= pack->acc_ext_link)
+		{
+			bf_check_acc(pack);
+		}
+	}
+	for (i= 0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
+	{
+		for (pack= ip_fd->if_rdbuf_head; pack;
+			pack= pack->acc_ext_link)
+		{
+			bf_check_acc(pack);
+		}
+	}
+	for (i= 0, ip_ass= ip_ass_table; i<IP_ASS_NR; i++, ip_ass++)
+	{
+		for (pack= ip_ass->ia_frags; pack; pack= pack->acc_ext_link)
+			bf_check_acc(pack);
+	}
+}
+#endif /* BUF_CONSISTENCY_CHECK */
+
+PRIVATE void ip_bad_callback(ip_port)
+struct ip_port *ip_port;
+{
+	ip_panic(( "no callback filled in for port %d", ip_port->ip_port ));
+}
+
+/*
+ * $PchId: ip.c,v 1.19 2005/06/28 14:17:40 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/ip.h
===================================================================
--- /trunk/minix/servers/inet/generic/ip.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/ip.h	(revision 9)
@@ -0,0 +1,28 @@
+/*
+ip.h
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef INET_IP_H
+#define INET_IP_H
+
+/* Prototypes */
+
+struct acc;
+
+void ip_prep ARGS(( void ));
+void ip_init ARGS(( void ));
+int  ip_open ARGS(( int port, int srfd,
+	get_userdata_t get_userdata, put_userdata_t put_userdata,
+	put_pkt_t put_pkt, select_res_t select_res ));
+int ip_ioctl ARGS(( int fd, ioreq_t req ));
+int ip_read ARGS(( int fd, size_t count ));
+int ip_write ARGS(( int fd, size_t count ));
+int ip_send ARGS(( int fd, struct acc *data, size_t data_len ));
+
+#endif /* INET_IP_H */
+
+/*
+ * $PchId: ip.h,v 1.8 2005/06/28 14:17:57 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/ip_eth.c
===================================================================
--- /trunk/minix/servers/inet/generic/ip_eth.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/ip_eth.c	(revision 9)
@@ -0,0 +1,722 @@
+/*
+generic/ip_eth.c
+
+Ethernet specific part of the IP implementation
+
+Created:	Apr 22, 1993 by Philip Homburg
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "type.h"
+#include "arp.h"
+#include "assert.h"
+#include "buf.h"
+#include "clock.h"
+#include "eth.h"
+#include "event.h"
+#include "icmp_lib.h"
+#include "io.h"
+#include "ip.h"
+#include "ip_int.h"
+
+THIS_FILE
+
+typedef struct xmit_hdr
+{
+	time_t xh_time;
+	ipaddr_t xh_ipaddr;
+} xmit_hdr_t;
+
+PRIVATE ether_addr_t broadcast_ethaddr=
+{
+	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
+};
+PRIVATE ether_addr_t ipmulticast_ethaddr=
+{
+	{ 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }
+};
+
+FORWARD void do_eth_read ARGS(( ip_port_t *port ));
+FORWARD acc_t *get_eth_data ARGS(( int fd, size_t offset,
+	size_t count, int for_ioctl ));
+FORWARD int put_eth_data ARGS(( int fd, size_t offset,
+	acc_t *data, int for_ioctl ));
+FORWARD void ipeth_main ARGS(( ip_port_t *port ));
+FORWARD void ipeth_set_ipaddr ARGS(( ip_port_t *port ));
+FORWARD void ipeth_restart_send ARGS(( ip_port_t *ip_port ));
+FORWARD int ipeth_send ARGS(( struct ip_port *ip_port, ipaddr_t dest, 
+	acc_t *pack, int type ));
+FORWARD void ipeth_arp_reply ARGS(( int ip_port_nr, ipaddr_t ipaddr,
+	ether_addr_t *dst_ether_ptr ));
+FORWARD int ipeth_update_ttl ARGS(( time_t enq_time, time_t now,
+	acc_t *eth_pack ));
+FORWARD void ip_eth_arrived ARGS(( int port, acc_t *pack,
+	size_t pack_size ));
+
+
+PUBLIC int ipeth_init(ip_port)
+ip_port_t *ip_port;
+{
+	assert(BUF_S >= sizeof(xmit_hdr_t));
+	assert(BUF_S >= sizeof(eth_hdr_t));
+
+	ip_port->ip_dl.dl_eth.de_fd= eth_open(ip_port->
+		ip_dl.dl_eth.de_port, ip_port->ip_port,
+		get_eth_data, put_eth_data, ip_eth_arrived,
+		0 /* no select_res */);
+	if (ip_port->ip_dl.dl_eth.de_fd < 0)
+	{
+		DBLOCK(1, printf("ip.c: unable to open eth port\n"));
+		return -1;
+	}
+	ip_port->ip_dl.dl_eth.de_state= IES_EMPTY;
+	ip_port->ip_dl.dl_eth.de_flags= IEF_EMPTY;
+	ip_port->ip_dl.dl_eth.de_q_head= NULL;
+	ip_port->ip_dl.dl_eth.de_q_tail= NULL;
+	ip_port->ip_dl.dl_eth.de_arp_head= NULL;
+	ip_port->ip_dl.dl_eth.de_arp_tail= NULL;
+	ip_port->ip_dev_main= ipeth_main;
+	ip_port->ip_dev_set_ipaddr= ipeth_set_ipaddr;
+	ip_port->ip_dev_send= ipeth_send;
+	ip_port->ip_mtu= ETH_MAX_PACK_SIZE-ETH_HDR_SIZE;
+	ip_port->ip_mtu_max= ip_port->ip_mtu;
+	return 0;
+}
+
+PRIVATE void ipeth_main(ip_port)
+ip_port_t *ip_port;
+{
+	int result;
+
+	switch (ip_port->ip_dl.dl_eth.de_state)
+	{
+	case IES_EMPTY:
+		ip_port->ip_dl.dl_eth.de_state= IES_SETPROTO;
+
+		result= eth_ioctl(ip_port->ip_dl.dl_eth.de_fd, NWIOSETHOPT);
+		if (result == NW_SUSPEND)
+			ip_port->ip_dl.dl_eth.de_flags |= IEF_SUSPEND;
+		if (result<0)
+		{
+			DBLOCK(1, printf("eth_ioctl(..,0x%lx)=%d\n",
+				(unsigned long)NWIOSETHOPT, result));
+			return;
+		}
+		if (ip_port->ip_dl.dl_eth.de_state != IES_SETPROTO)
+			return;
+		/* drops through */
+	case IES_SETPROTO:
+		result= arp_set_cb(ip_port->ip_dl.dl_eth.de_port,
+			ip_port->ip_port,
+			ipeth_arp_reply);
+		if (result != NW_OK)
+		{
+			printf("ipeth_main: arp_set_cb failed: %d\n",
+				result);
+			return;
+		}
+
+		/* Wait until the interface is configured up. */
+		ip_port->ip_dl.dl_eth.de_state= IES_GETIPADDR;
+		if (!(ip_port->ip_flags & IPF_IPADDRSET))
+		{
+			ip_port->ip_dl.dl_eth.de_flags |= IEF_SUSPEND;
+			return;
+		}
+
+		/* fall through */
+	case IES_GETIPADDR:
+		ip_port->ip_dl.dl_eth.de_state= IES_MAIN;
+		do_eth_read(ip_port);
+		return;
+	default:
+		ip_panic(( "unknown state: %d",
+			ip_port->ip_dl.dl_eth.de_state));
+	}
+}
+
+PRIVATE acc_t *get_eth_data (fd, offset, count, for_ioctl)
+int fd;
+size_t offset;
+size_t count;
+int for_ioctl;
+{
+	ip_port_t *ip_port;
+	acc_t *data;
+	int result;
+
+	ip_port= &ip_port_table[fd];
+
+	switch (ip_port->ip_dl.dl_eth.de_state)
+	{
+	case IES_SETPROTO:
+		if (!count)
+		{
+			result= (int)offset;
+			if (result<0)
+			{
+				ip_port->ip_dl.dl_eth.de_state= IES_ERROR;
+				break;
+			}
+			if (ip_port->ip_dl.dl_eth.de_flags & IEF_SUSPEND)
+				ipeth_main(ip_port);
+			return NW_OK;
+		}
+		assert ((!offset) && (count == sizeof(struct nwio_ethopt)));
+		{
+			struct nwio_ethopt *ethopt;
+			acc_t *acc;
+
+			acc= bf_memreq(sizeof(*ethopt));
+			ethopt= (struct nwio_ethopt *)ptr2acc_data(acc);
+			ethopt->nweo_flags= NWEO_COPY|NWEO_EN_BROAD|
+				NWEO_EN_MULTI|NWEO_TYPESPEC;
+			ethopt->nweo_type= HTONS(ETH_IP_PROTO);
+			return acc;
+		}
+
+	case IES_MAIN:
+		if (!count)
+		{
+			result= (int)offset;
+			if (result<0)
+				ip_warning(( "error on write: %d\n", result ));
+			bf_afree (ip_port->ip_dl.dl_eth.de_frame);
+			ip_port->ip_dl.dl_eth.de_frame= 0;
+
+			if (ip_port->ip_dl.dl_eth.de_flags & IEF_WRITE_SP)
+			{
+				ip_port->ip_dl.dl_eth.de_flags &=
+					~IEF_WRITE_SP;
+				ipeth_restart_send(ip_port);
+			}
+			return NW_OK;
+		}
+		data= bf_cut (ip_port->ip_dl.dl_eth.de_frame, offset, count);
+		assert (data);
+		return data;
+	default:
+		printf(
+		"get_eth_data(%d, 0x%d, 0x%d) called but ip_state=0x%x\n",
+			fd, offset, count, ip_port->ip_dl.dl_eth.de_state);
+		break;
+	}
+	return 0;
+}
+
+PRIVATE int put_eth_data (port, offset, data, for_ioctl)
+int port;
+size_t offset;
+acc_t *data;
+int for_ioctl;
+{
+	ip_port_t *ip_port;
+	int result;
+
+	ip_port= &ip_port_table[port];
+
+	assert(0);
+
+	if (ip_port->ip_dl.dl_eth.de_flags & IEF_READ_IP)
+	{
+		if (!data)
+		{
+			result= (int)offset;
+			if (result<0)
+			{
+				DBLOCK(1, printf(
+				"ip.c: put_eth_data(..,%d,..)\n", result));
+				return NW_OK;
+			}
+			if (ip_port->ip_dl.dl_eth.de_flags & IEF_READ_SP)
+			{
+				ip_port->ip_dl.dl_eth.de_flags &= 
+						~(IEF_READ_IP|IEF_READ_SP);
+				do_eth_read(ip_port);
+			}
+			else
+				ip_port->ip_dl.dl_eth.de_flags &= ~IEF_READ_IP;
+			return NW_OK;
+		}
+		assert (!offset);
+		/* Warning: the above assertion is illegal; puts and
+		   gets of data can be brokenup in any piece the server
+		   likes. However we assume that the server is eth.c
+		   and it transfers only whole packets. */
+		ip_eth_arrived(port, data, bf_bufsize(data));
+		return NW_OK;
+	}
+	printf("ip_port->ip_dl.dl_eth.de_state= 0x%x",
+		ip_port->ip_dl.dl_eth.de_state);
+	ip_panic (( "strange status" ));
+}
+
+PRIVATE void ipeth_set_ipaddr(ip_port)
+ip_port_t *ip_port;
+{
+	arp_set_ipaddr (ip_port->ip_dl.dl_eth.de_port, ip_port->ip_ipaddr);
+	if (ip_port->ip_dl.dl_eth.de_state == IES_GETIPADDR)
+		ipeth_main(ip_port);
+}
+
+PRIVATE int ipeth_send(ip_port, dest, pack, type)
+struct ip_port *ip_port;
+ipaddr_t dest;
+acc_t *pack;
+int type;
+{
+	int i, r;
+	acc_t *eth_pack, *tail;
+	size_t pack_size;
+	eth_hdr_t *eth_hdr;
+	xmit_hdr_t *xmit_hdr;
+	ipaddr_t hostpart, tmpaddr;
+	time_t t;
+	u32_t *p;
+
+	/* Start optimistic: the arp will succeed without blocking and the
+	 * ethernet packet can be sent without blocking also. Start with
+	 * the allocation of the ethernet header.
+	 */
+	eth_pack= bf_memreq(sizeof(*eth_hdr));
+	assert(eth_pack->acc_next == NULL);
+	eth_pack->acc_next= pack;
+	pack_size= bf_bufsize(eth_pack);
+	if (pack_size<ETH_MIN_PACK_SIZE)
+	{
+		tail= bf_memreq(ETH_MIN_PACK_SIZE-pack_size);
+
+		/* Clear padding */
+		for (i= (ETH_MIN_PACK_SIZE-pack_size)/sizeof(*p),
+			p= (u32_t *)ptr2acc_data(tail);
+			i >= 0; i--, p++)
+		{
+			*p= 0xdeadbeef;
+		}
+
+		eth_pack= bf_append(eth_pack, tail);
+	}
+	eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);
+
+	/* Lookup the ethernet address */
+	if (type != IP_LT_NORMAL)
+	{
+		if (type == IP_LT_BROADCAST)
+			eth_hdr->eh_dst= broadcast_ethaddr;
+		else
+		{
+			tmpaddr= ntohl(dest);
+			eth_hdr->eh_dst= ipmulticast_ethaddr;
+			eth_hdr->eh_dst.ea_addr[5]= tmpaddr & 0xff;
+			eth_hdr->eh_dst.ea_addr[4]= (tmpaddr >> 8) & 0xff;
+			eth_hdr->eh_dst.ea_addr[3]= (tmpaddr >> 16) & 0x7f;
+		}
+	}
+	else
+	{
+		if ((dest ^ ip_port->ip_ipaddr) & ip_port->ip_subnetmask)
+		{
+			ip_panic(( "invalid destination" ));
+		}
+
+		hostpart= (dest & ~ip_port->ip_subnetmask);
+		assert(dest != ip_port->ip_ipaddr);
+
+		r= arp_ip_eth(ip_port->ip_dl.dl_eth.de_port,
+			dest, &eth_hdr->eh_dst);
+		if (r == NW_SUSPEND)
+		{
+			/* Unfortunately, the arp takes some time, use
+			 * the ethernet header to store the next hop
+			 * ip address and the current time.
+			 */
+			xmit_hdr= (xmit_hdr_t *)eth_hdr;
+			xmit_hdr->xh_time= get_time();
+			xmit_hdr->xh_ipaddr= dest;
+			eth_pack->acc_ext_link= NULL;
+			if (ip_port->ip_dl.dl_eth.de_arp_head == NULL)
+				ip_port->ip_dl.dl_eth.de_arp_head= eth_pack;
+			else
+			{
+				ip_port->ip_dl.dl_eth.de_arp_tail->
+					acc_ext_link= eth_pack;
+			}
+			ip_port->ip_dl.dl_eth.de_arp_tail= eth_pack;
+			return NW_OK;
+		}
+		if (r == EDSTNOTRCH)
+		{
+			bf_afree(eth_pack);
+			return EDSTNOTRCH;
+		}
+		assert(r == NW_OK);
+	}
+
+	/* If we have no write in progress, we can try to send the ethernet
+	 * packet using eth_send. If the IP packet is larger than mtu,
+	 * enqueue the packet and let ipeth_restart_send deal with it. 
+	 */
+	pack_size= bf_bufsize(eth_pack);
+	if (ip_port->ip_dl.dl_eth.de_frame == NULL && pack_size <=
+		ip_port->ip_mtu + sizeof(*eth_hdr))
+	{
+		r= eth_send(ip_port->ip_dl.dl_eth.de_fd,
+			eth_pack, pack_size);
+		if (r == NW_OK)
+			return NW_OK;
+
+		/* A non-blocking send is not possible, start a regular
+		 * send.
+		 */
+		assert(r == NW_WOULDBLOCK);
+		ip_port->ip_dl.dl_eth.de_frame= eth_pack;
+		r= eth_write(ip_port->ip_dl.dl_eth.de_fd, pack_size);
+		if (r == NW_SUSPEND)
+		{
+			assert(!(ip_port->ip_dl.dl_eth.de_flags &
+				IEF_WRITE_SP));
+			ip_port->ip_dl.dl_eth.de_flags |= IEF_WRITE_SP;
+		}
+		assert(r == NW_OK || r == NW_SUSPEND);
+		return NW_OK;
+	}
+
+	/* Enqueue the packet, and store the current time, in the
+	 * space for the ethernet source address.
+	 */
+	t= get_time();
+	assert(sizeof(t) <= sizeof(eth_hdr->eh_src));
+	memcpy(&eth_hdr->eh_src, &t, sizeof(t));
+
+	eth_pack->acc_ext_link= NULL;
+	if (ip_port->ip_dl.dl_eth.de_q_head == NULL)
+		ip_port->ip_dl.dl_eth.de_q_head= eth_pack;
+	else
+	{
+		ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link= eth_pack;
+	}
+	ip_port->ip_dl.dl_eth.de_q_tail= eth_pack;
+	if (ip_port->ip_dl.dl_eth.de_frame == NULL)
+		ipeth_restart_send(ip_port);
+	return NW_OK;
+}
+
+PRIVATE void ipeth_restart_send(ip_port)
+ip_port_t *ip_port;
+{
+	time_t now, enq_time;
+	int i, r;
+	acc_t *eth_pack, *ip_pack, *next_eth_pack, *next_part, *tail;
+	size_t pack_size;
+	eth_hdr_t *eth_hdr, *next_eth_hdr;
+	u32_t *p;
+
+	now= get_time();
+
+	while (ip_port->ip_dl.dl_eth.de_q_head != NULL)
+	{
+		eth_pack= ip_port->ip_dl.dl_eth.de_q_head;
+		ip_port->ip_dl.dl_eth.de_q_head= eth_pack->acc_ext_link;
+
+		eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);
+
+		pack_size= bf_bufsize(eth_pack);
+
+		if (pack_size > ip_port->ip_mtu+sizeof(*eth_hdr))
+		{
+			/* Split the IP packet */
+			assert(eth_pack->acc_linkC == 1);
+			ip_pack= eth_pack->acc_next; eth_pack->acc_next= NULL;
+			next_part= ip_pack; ip_pack= NULL;
+			ip_pack= ip_split_pack(ip_port, &next_part, 
+							ip_port->ip_mtu);
+			if (ip_pack == NULL)
+			{
+				bf_afree(eth_pack);
+				continue;
+			}
+
+			eth_pack->acc_next= ip_pack; ip_pack= NULL;
+
+			/* Allocate new ethernet header */
+			next_eth_pack= bf_memreq(sizeof(*next_eth_hdr));
+			next_eth_hdr= (eth_hdr_t *)ptr2acc_data(next_eth_pack);
+			*next_eth_hdr= *eth_hdr;
+			next_eth_pack->acc_next= next_part;
+
+			next_eth_pack->acc_ext_link= NULL;
+			if (ip_port->ip_dl.dl_eth.de_q_head == NULL)
+				ip_port->ip_dl.dl_eth.de_q_head= next_eth_pack;
+			else
+			{
+				ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link= 
+								next_eth_pack;
+			}
+			ip_port->ip_dl.dl_eth.de_q_tail= next_eth_pack;
+
+			pack_size= bf_bufsize(eth_pack);
+		}
+
+		memcpy(&enq_time, &eth_hdr->eh_src, sizeof(enq_time));
+		if (enq_time + HZ < now)
+		{
+			r= ipeth_update_ttl(enq_time, now, eth_pack);
+			if (r == ETIMEDOUT)
+			{	
+				ip_pack= bf_delhead(eth_pack, sizeof(*eth_hdr));
+				eth_pack= NULL;
+				icmp_snd_time_exceeded(ip_port->ip_port,
+					ip_pack, ICMP_TTL_EXC);
+				continue;
+			}
+			assert(r == NW_OK);
+		}
+
+		if (pack_size<ETH_MIN_PACK_SIZE)
+		{
+			tail= bf_memreq(ETH_MIN_PACK_SIZE-pack_size);
+
+			/* Clear padding */
+			for (i= (ETH_MIN_PACK_SIZE-pack_size)/sizeof(*p),
+				p= (u32_t *)ptr2acc_data(tail);
+				i >= 0; i--, p++)
+			{
+				*p= 0xdeadbeef;
+			}
+
+			eth_pack= bf_append(eth_pack, tail);
+			pack_size= ETH_MIN_PACK_SIZE;
+		}
+
+		assert(ip_port->ip_dl.dl_eth.de_frame == NULL);
+
+		r= eth_send(ip_port->ip_dl.dl_eth.de_fd, eth_pack, pack_size);
+		if (r == NW_OK)
+			continue;
+
+		/* A non-blocking send is not possible, start a regular
+		 * send.
+		 */
+		assert(r == NW_WOULDBLOCK);
+		ip_port->ip_dl.dl_eth.de_frame= eth_pack;
+		r= eth_write(ip_port->ip_dl.dl_eth.de_fd, pack_size);
+		if (r == NW_SUSPEND)
+		{
+			assert(!(ip_port->ip_dl.dl_eth.de_flags &
+				IEF_WRITE_SP));
+			ip_port->ip_dl.dl_eth.de_flags |= IEF_WRITE_SP;
+			return;
+		}
+		assert(r == NW_OK);
+	}
+}
+
+
+PRIVATE void ipeth_arp_reply(ip_port_nr, ipaddr, eth_addr)
+int ip_port_nr;
+ipaddr_t ipaddr;
+ether_addr_t *eth_addr;
+{
+	acc_t *prev, *eth_pack;
+	int r;
+	xmit_hdr_t *xmit_hdr;
+	ip_port_t *ip_port;
+	time_t t;
+	eth_hdr_t *eth_hdr;
+	ether_addr_t tmp_eth_addr;
+
+	assert (ip_port_nr >= 0 && ip_port_nr < ip_conf_nr);
+	ip_port= &ip_port_table[ip_port_nr];
+
+	for (;;)
+	{
+		for (prev= 0, eth_pack= ip_port->ip_dl.dl_eth.de_arp_head;
+			eth_pack;
+			prev= eth_pack, eth_pack= eth_pack->acc_ext_link)
+		{
+			xmit_hdr= (xmit_hdr_t *)ptr2acc_data(eth_pack);
+			if (xmit_hdr->xh_ipaddr == ipaddr)
+				break;
+		}
+
+		if (eth_pack == NULL)
+		{
+			/* No packet found. */
+			break;
+		}
+
+		/* Delete packet from the queue. */
+		if (prev == NULL)
+		{
+			ip_port->ip_dl.dl_eth.de_arp_head=
+				eth_pack->acc_ext_link;
+		}
+		else
+		{
+			prev->acc_ext_link= eth_pack->acc_ext_link;
+			if (prev->acc_ext_link == NULL)
+				ip_port->ip_dl.dl_eth.de_arp_tail= prev;
+		}
+
+		if (eth_addr == NULL)
+		{
+			/* Destination is unreachable, delete packet. */
+			bf_afree(eth_pack);
+			continue;
+		}
+
+		/* Fill in the ethernet address and put the packet on the 
+		 * transmit queue.
+		 */
+		t= xmit_hdr->xh_time;
+		eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);
+		eth_hdr->eh_dst= *eth_addr;
+		memcpy(&eth_hdr->eh_src, &t, sizeof(t));
+
+		eth_pack->acc_ext_link= NULL;
+		if (ip_port->ip_dl.dl_eth.de_q_head == NULL)
+			ip_port->ip_dl.dl_eth.de_q_head= eth_pack;
+		else
+		{
+			ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link=
+				eth_pack;
+		}
+		ip_port->ip_dl.dl_eth.de_q_tail= eth_pack;
+	}
+
+	/* Try to get some more ARPs in progress. */
+	while (ip_port->ip_dl.dl_eth.de_arp_head)
+	{
+		eth_pack= ip_port->ip_dl.dl_eth.de_arp_head;
+		xmit_hdr= (xmit_hdr_t *)ptr2acc_data(eth_pack);
+		r= arp_ip_eth(ip_port->ip_dl.dl_eth.de_port,
+			xmit_hdr->xh_ipaddr, &tmp_eth_addr);
+		if (r == NW_SUSPEND)
+			break;				/* Normal case */
+
+		/* Dequeue the packet */
+		ip_port->ip_dl.dl_eth.de_arp_head= eth_pack->acc_ext_link;
+
+		if (r == EDSTNOTRCH)
+		{
+			bf_afree(eth_pack);
+			continue;
+		}
+		assert(r == NW_OK);
+
+		/* Fill in the ethernet address and put the packet on the 
+		 * transmit queue.
+		 */
+		t= xmit_hdr->xh_time;
+		eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);
+		eth_hdr->eh_dst= tmp_eth_addr;
+		memcpy(&eth_hdr->eh_src, &t, sizeof(t));
+
+		eth_pack->acc_ext_link= NULL;
+		if (ip_port->ip_dl.dl_eth.de_q_head == NULL)
+			ip_port->ip_dl.dl_eth.de_q_head= eth_pack;
+		else
+		{
+			ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link=
+				eth_pack;
+		}
+		ip_port->ip_dl.dl_eth.de_q_tail= eth_pack;
+	}
+
+	/* Restart sending ethernet packets. */
+	if (ip_port->ip_dl.dl_eth.de_frame == NULL)
+		ipeth_restart_send(ip_port);
+}
+
+PRIVATE int ipeth_update_ttl(enq_time, now, eth_pack)
+time_t enq_time;
+time_t now;
+acc_t *eth_pack;
+{
+	int ttl_diff;
+	ip_hdr_t *ip_hdr;
+	u32_t sum;
+	u16_t word;
+	acc_t *ip_pack;
+
+	ttl_diff= (now-enq_time)/HZ;
+	enq_time += ttl_diff*HZ;
+	assert(enq_time <= now && enq_time + HZ > now);
+
+	ip_pack= eth_pack->acc_next;
+	assert(ip_pack->acc_length >= sizeof(*ip_hdr));
+	assert(ip_pack->acc_linkC == 1 &&
+		ip_pack->acc_buffer->buf_linkC == 1);
+
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_pack);
+	if (ip_hdr->ih_ttl <= ttl_diff)
+		return ETIMEDOUT;
+	sum= (u16_t)~ip_hdr->ih_hdr_chk;
+	word= *(u16_t *)&ip_hdr->ih_ttl;
+	if (word > sum)
+		sum += 0xffff - word;
+	else
+		sum -= word;
+	ip_hdr->ih_ttl -= ttl_diff;
+	word= *(u16_t *)&ip_hdr->ih_ttl;
+	sum += word;
+	if (sum > 0xffff)
+		sum -= 0xffff;
+	assert(!(sum & 0xffff0000));
+	ip_hdr->ih_hdr_chk= ~sum;
+	assert(ip_hdr->ih_ttl > 0);
+	return NW_OK;
+}
+
+PRIVATE void do_eth_read(ip_port)
+ip_port_t *ip_port;
+{
+	int result;
+
+	assert(!(ip_port->ip_dl.dl_eth.de_flags & IEF_READ_IP));
+
+	for (;;)
+	{
+		ip_port->ip_dl.dl_eth.de_flags |= IEF_READ_IP;
+
+		result= eth_read (ip_port->ip_dl.dl_eth.de_fd,
+			ETH_MAX_PACK_SIZE);
+		if (result == NW_SUSPEND)
+		{
+			assert(!(ip_port->ip_dl.dl_eth.de_flags & 
+								IEF_READ_SP));
+			ip_port->ip_dl.dl_eth.de_flags |= IEF_READ_SP;
+			return;
+		}
+		ip_port->ip_dl.dl_eth.de_flags &= ~IEF_READ_IP;
+		if (result<0)
+		{
+			return;
+		}
+	}
+}
+
+PRIVATE void ip_eth_arrived(port, pack, pack_size)
+int port;
+acc_t *pack;
+size_t pack_size;
+{
+	int broadcast;
+	ip_port_t *ip_port;
+
+	ip_port= &ip_port_table[port];
+	broadcast= (*(u8_t *)ptr2acc_data(pack) & 1);
+
+	pack= bf_delhead(pack, ETH_HDR_SIZE);
+
+	if (broadcast)
+		ip_arrived_broadcast(ip_port, pack);
+	else
+		ip_arrived(ip_port, pack);
+}
+
+/*
+ * $PchId: ip_eth.c,v 1.25 2005/06/28 14:18:10 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/ip_int.h
===================================================================
--- /trunk/minix/servers/inet/generic/ip_int.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/ip_int.h	(revision 9)
@@ -0,0 +1,189 @@
+/*
+ip_int.h
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef INET_IP_INT_H
+#define INET_IP_INT_H
+
+#define IP_FD_NR	(8*IP_PORT_MAX)
+#define IP_ASS_NR	3
+
+#define IP_42BSD_BCAST		1	/* hostnumber 0 is also network
+					   broadcast */
+
+#define IP_LT_NORMAL		0	/* Normal */
+#define IP_LT_BROADCAST		1	/* Broadcast */
+#define IP_LT_MULTICAST		2	/* Multicast */
+
+struct ip_port;
+struct ip_fd;
+typedef void (*ip_dev_t) ARGS(( struct ip_port *ip_port ));
+typedef int (*ip_dev_send_t) ARGS(( struct ip_port *ip_port, ipaddr_t dest, 
+						acc_t *pack, int type ));
+
+#define IP_PROTO_HASH_NR	32
+
+typedef struct ip_port
+{
+	int ip_flags, ip_dl_type;
+	int ip_port;
+	union
+	{
+		struct
+		{
+			int de_state;
+			int de_flags;
+			int de_port;
+			int de_fd;
+			acc_t *de_frame;
+			acc_t *de_q_head;
+			acc_t *de_q_tail;
+			acc_t *de_arp_head;
+			acc_t *de_arp_tail;
+		} dl_eth;
+		struct
+		{
+			int ps_port;
+			acc_t *ps_send_head;
+			acc_t *ps_send_tail;
+		} dl_ps;
+	} ip_dl;
+	ipaddr_t ip_ipaddr;
+	ipaddr_t ip_subnetmask;
+	ipaddr_t ip_classfulmask;
+	u16_t ip_frame_id;
+	u16_t ip_mtu;
+	u16_t ip_mtu_max;		/* Max MTU for this kind of network */
+	ip_dev_t ip_dev_main;
+	ip_dev_t ip_dev_set_ipaddr;
+	ip_dev_send_t ip_dev_send;
+	acc_t *ip_loopb_head;
+	acc_t *ip_loopb_tail;
+	event_t ip_loopb_event;
+	acc_t *ip_routeq_head;
+	acc_t *ip_routeq_tail;
+	event_t ip_routeq_event;
+	struct ip_fd *ip_proto_any;
+	struct ip_fd *ip_proto[IP_PROTO_HASH_NR];
+} ip_port_t;
+
+#define IES_EMPTY	0x0
+#define	IES_SETPROTO	0x1
+#define	IES_GETIPADDR	0x2
+#define	IES_MAIN	0x3
+#define	IES_ERROR	0x4
+
+#define IEF_EMPTY	0x1
+#define IEF_SUSPEND	0x8
+#define IEF_READ_IP	0x10
+#define IEF_READ_SP	0x20
+#define IEF_WRITE_SP	0x80
+
+#define IPF_EMPTY		0x0
+#define IPF_CONFIGURED		0x1
+#define IPF_IPADDRSET		0x2
+#define IPF_NETMASKSET		0x4
+#define IPF_SUBNET_BCAST	0x8	/* Subset support subnet broadcasts  */
+
+#define IPDL_ETH	NETTYPE_ETH
+#define IPDL_PSIP	NETTYPE_PSIP
+
+typedef struct ip_ass
+{
+	acc_t *ia_frags;
+	int ia_min_ttl;
+	ip_port_t *ia_port;
+	time_t ia_first_time;
+	ipaddr_t ia_srcaddr, ia_dstaddr;
+	int ia_proto, ia_id;
+} ip_ass_t;
+
+typedef struct ip_fd
+{
+	int if_flags;
+	struct nwio_ipopt if_ipopt;
+	ip_port_t *if_port;
+	struct ip_fd *if_proto_next;
+	int if_srfd;
+	acc_t *if_rdbuf_head;
+	acc_t *if_rdbuf_tail;
+	get_userdata_t if_get_userdata;
+	put_userdata_t if_put_userdata;
+	put_pkt_t if_put_pkt;
+	time_t if_exp_time;
+	size_t if_rd_count;
+	ioreq_t if_ioctl;
+} ip_fd_t;
+
+#define IFF_EMPTY	0x00
+#define IFF_INUSE	0x01
+#define IFF_OPTSET	0x02
+#define IFF_BUSY	0x1C
+#	define IFF_READ_IP	0x04
+#	define IFF_IOCTL_IP	0x08
+
+typedef enum nettype
+{
+	IPNT_ZERO,		/*   0.xx.xx.xx */
+	IPNT_CLASS_A,		/*   1.xx.xx.xx .. 126.xx.xx.xx */
+	IPNT_LOCAL,		/* 127.xx.xx.xx */
+	IPNT_CLASS_B,		/* 128.xx.xx.xx .. 191.xx.xx.xx */
+	IPNT_CLASS_C,		/* 192.xx.xx.xx .. 223.xx.xx.xx */
+	IPNT_CLASS_D,		/* 224.xx.xx.xx .. 239.xx.xx.xx */
+	IPNT_CLASS_E,		/* 240.xx.xx.xx .. 247.xx.xx.xx */
+	IPNT_MARTIAN,		/* 248.xx.xx.xx .. 254.xx.xx.xx + others */
+	IPNT_BROADCAST		/* 255.255.255.255 */
+} nettype_t;
+
+struct nwio_ipconf;
+
+/* ip_eth.c */
+int ipeth_init ARGS(( ip_port_t *ip_port ));
+
+/* ip_ioctl.c */
+void ip_hash_proto ARGS(( ip_fd_t *ip_fd ));
+void ip_unhash_proto ARGS(( ip_fd_t *ip_fd ));
+int ip_setconf ARGS(( int ip_port, struct nwio_ipconf *ipconfp ));
+
+/* ip_lib.c */
+ipaddr_t ip_get_netmask ARGS(( ipaddr_t hostaddr ));
+ipaddr_t ip_get_ifaddr ARGS(( int ip_port_nr ));
+int ip_chk_hdropt ARGS(( u8_t *opt, int optlen ));
+void ip_print_frags ARGS(( acc_t *acc ));
+nettype_t ip_nettype ARGS(( ipaddr_t ipaddr ));
+ipaddr_t ip_netmask ARGS(( nettype_t nettype ));
+char *ip_nettoa ARGS(( nettype_t nettype ));
+
+/* ip_ps.c */
+int ipps_init ARGS(( ip_port_t *ip_port ));
+void ipps_get ARGS(( int ip_port_nr ));
+void ipps_put ARGS(( int ip_port_nr, ipaddr_t nexthop, acc_t *pack ));
+
+/* ip_read.c */
+void ip_port_arrive ARGS(( ip_port_t *port, acc_t *pack, ip_hdr_t *ip_hdr ));
+void ip_arrived ARGS(( ip_port_t *port, acc_t *pack ));
+void ip_arrived_broadcast ARGS(( ip_port_t *port, acc_t *pack ));
+void ip_process_loopb ARGS(( event_t *ev, ev_arg_t arg ));
+void ip_packet2user ARGS(( ip_fd_t *ip_fd, acc_t *pack, time_t exp_time,
+	size_t data_len ));
+
+/* ip_write.c */
+void dll_eth_write_frame ARGS(( ip_port_t *port ));
+acc_t *ip_split_pack ARGS(( ip_port_t *ip_port, acc_t **ref_last, int mtu ));
+void ip_hdr_chksum ARGS(( ip_hdr_t *ip_hdr, int ip_hdr_len ));
+
+
+extern ip_fd_t ip_fd_table[IP_FD_NR];
+extern ip_port_t *ip_port_table;
+extern ip_ass_t ip_ass_table[IP_ASS_NR];
+
+#define NWIO_DEFAULT    (NWIO_EN_LOC | NWIO_EN_BROAD | NWIO_REMANY | \
+	NWIO_RWDATALL | NWIO_HDR_O_SPEC)
+
+#endif /* INET_IP_INT_H */
+
+/*
+ * $PchId: ip_int.h,v 1.19 2004/08/03 16:24:23 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/ip_ioctl.c
===================================================================
--- /trunk/minix/servers/inet/generic/ip_ioctl.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/ip_ioctl.c	(revision 9)
@@ -0,0 +1,671 @@
+/*
+ip_ioctl.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "buf.h"
+#include "event.h"
+#include "type.h"
+
+#include "arp.h"
+#include "assert.h"
+#include "clock.h"
+#include "icmp_lib.h"
+#include "ip.h"
+#include "ip_int.h"
+#include "ipr.h"
+
+THIS_FILE
+
+FORWARD int ip_checkopt ARGS(( ip_fd_t *ip_fd ));
+FORWARD void reply_thr_get ARGS(( ip_fd_t *ip_fd, size_t
+	reply, int for_ioctl ));
+FORWARD void report_addr ARGS(( ip_port_t *ip_port ));
+
+PUBLIC int ip_ioctl (fd, req)
+int fd;
+ioreq_t req;
+{
+	ip_fd_t *ip_fd;
+	ip_port_t *ip_port;
+	nwio_ipopt_t *ipopt;
+	nwio_ipopt_t oldopt, newopt;
+	nwio_ipconf2_t *ipconf2;
+	nwio_ipconf_t *ipconf;
+	nwio_route_t *route_ent;
+	acc_t *data;
+	int result;
+	unsigned int new_en_flags, new_di_flags,
+		old_en_flags, old_di_flags;
+	unsigned long new_flags;
+	int ent_no, r;
+	nwio_ipconf_t ipconf_var;
+
+	assert (fd>=0 && fd<=IP_FD_NR);
+	ip_fd= &ip_fd_table[fd];
+
+	assert (ip_fd->if_flags & IFF_INUSE);
+
+	switch (req)
+	{
+	case NWIOSIPOPT:
+		ip_port= ip_fd->if_port;
+
+		if (!(ip_port->ip_flags & IPF_IPADDRSET))
+		{
+			ip_fd->if_ioctl= NWIOSIPOPT;
+			ip_fd->if_flags |= IFF_IOCTL_IP;
+			return NW_SUSPEND;
+		}
+		ip_fd->if_flags &= ~IFF_IOCTL_IP;
+
+		data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd, 0,
+			sizeof(nwio_ipopt_t), TRUE);
+
+		data= bf_packIffLess (data, sizeof(nwio_ipopt_t));
+		assert (data->acc_length == sizeof(nwio_ipopt_t));
+
+		ipopt= (nwio_ipopt_t *)ptr2acc_data(data);
+		oldopt= ip_fd->if_ipopt;
+		newopt= *ipopt;
+
+		old_en_flags= oldopt.nwio_flags & 0xffff;
+		old_di_flags= (oldopt.nwio_flags >> 16) & 0xffff;
+		new_en_flags= newopt.nwio_flags & 0xffff;
+		new_di_flags= (newopt.nwio_flags >> 16) & 0xffff;
+		if (new_en_flags & new_di_flags)
+		{
+			bf_afree(data);
+			reply_thr_get (ip_fd, EBADMODE, TRUE);
+			return NW_OK;
+		}
+
+		/* NWIO_ACC_MASK */
+		if (new_di_flags & NWIO_ACC_MASK)
+		{
+			bf_afree(data);
+			reply_thr_get (ip_fd, EBADMODE, TRUE);
+			return NW_OK;
+			/* access modes can't be disable */
+		}
+
+		if (!(new_en_flags & NWIO_ACC_MASK))
+			new_en_flags |= (old_en_flags & NWIO_ACC_MASK);
+
+		/* NWIO_LOC_MASK */
+		if (!((new_en_flags|new_di_flags) & NWIO_LOC_MASK))
+		{
+			new_en_flags |= (old_en_flags & NWIO_LOC_MASK);
+			new_di_flags |= (old_di_flags & NWIO_LOC_MASK);
+		}
+
+		/* NWIO_BROAD_MASK */
+		if (!((new_en_flags|new_di_flags) & NWIO_BROAD_MASK))
+		{
+			new_en_flags |= (old_en_flags & NWIO_BROAD_MASK);
+			new_di_flags |= (old_di_flags & NWIO_BROAD_MASK);
+		}
+
+		/* NWIO_REM_MASK */
+		if (!((new_en_flags|new_di_flags) & NWIO_REM_MASK))
+		{
+			new_en_flags |= (old_en_flags & NWIO_REM_MASK);
+			new_di_flags |= (old_di_flags & NWIO_REM_MASK);
+			newopt.nwio_rem= oldopt.nwio_rem;
+		}
+
+		/* NWIO_PROTO_MASK */
+		if (!((new_en_flags|new_di_flags) & NWIO_PROTO_MASK))
+		{
+			new_en_flags |= (old_en_flags & NWIO_PROTO_MASK);
+			new_di_flags |= (old_di_flags & NWIO_PROTO_MASK);
+			newopt.nwio_proto= oldopt.nwio_proto;
+		}
+
+		/* NWIO_HDR_O_MASK */
+		if (!((new_en_flags|new_di_flags) & NWIO_HDR_O_MASK))
+		{
+			new_en_flags |= (old_en_flags & NWIO_HDR_O_MASK);
+			new_di_flags |= (old_di_flags & NWIO_HDR_O_MASK);
+			newopt.nwio_tos= oldopt.nwio_tos;
+			newopt.nwio_ttl= oldopt.nwio_ttl;
+			newopt.nwio_df= oldopt.nwio_df;
+			newopt.nwio_hdropt= oldopt.nwio_hdropt;
+		}
+
+		/* NWIO_RW_MASK */
+		if (!((new_en_flags|new_di_flags) & NWIO_RW_MASK))
+		{
+			new_en_flags |= (old_en_flags & NWIO_RW_MASK);
+			new_di_flags |= (old_di_flags & NWIO_RW_MASK);
+		}
+
+		new_flags= ((unsigned long)new_di_flags << 16) | new_en_flags;
+
+		if ((new_flags & NWIO_RWDATONLY) && (new_flags &
+			(NWIO_REMANY|NWIO_PROTOANY|NWIO_HDR_O_ANY)))
+		{
+			bf_afree(data);
+			reply_thr_get(ip_fd, EBADMODE, TRUE);
+			return NW_OK;
+		}
+
+		if (ip_fd->if_flags & IFF_OPTSET)
+			ip_unhash_proto(ip_fd);
+
+		newopt.nwio_flags= new_flags;
+		ip_fd->if_ipopt= newopt;
+
+		result= ip_checkopt(ip_fd);
+
+		if (result<0)
+			ip_fd->if_ipopt= oldopt;
+
+		bf_afree(data);
+		reply_thr_get (ip_fd, result, TRUE);
+		return NW_OK;
+
+	case NWIOGIPOPT:
+		data= bf_memreq(sizeof(nwio_ipopt_t));
+
+		ipopt= (nwio_ipopt_t *)ptr2acc_data(data);
+
+		*ipopt= ip_fd->if_ipopt;
+
+		result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd, 0, data, 
+									TRUE);
+		return (*ip_fd->if_put_userdata)(ip_fd->if_srfd, result, 
+							(acc_t *)0, TRUE);
+
+	case NWIOSIPCONF2:
+	case NWIOSIPCONF:
+		ip_port= ip_fd->if_port;
+
+		if (req == NWIOSIPCONF2)
+		{
+			data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd, 0, 
+				sizeof(*ipconf2), TRUE);
+			data= bf_packIffLess (data, sizeof(*ipconf2));
+			assert (data->acc_length == sizeof(*ipconf2));
+
+			ipconf2= (nwio_ipconf2_t *)ptr2acc_data(data);
+
+			ipconf= &ipconf_var;
+			ipconf->nwic_flags= ipconf2->nwic_flags;
+			ipconf->nwic_ipaddr= ipconf2->nwic_ipaddr;
+			ipconf->nwic_netmask= ipconf2->nwic_netmask;
+			ipconf->nwic_flags &= ~NWIC_MTU_SET;
+		}
+		else
+		{
+			data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd, 0, 
+				sizeof(*ipconf), TRUE);
+			data= bf_packIffLess (data, sizeof(*ipconf));
+			assert (data->acc_length == sizeof(*ipconf));
+
+			ipconf= (nwio_ipconf_t *)ptr2acc_data(data);
+		}
+		r= ip_setconf(ip_port-ip_port_table, ipconf);
+		bf_afree(data);
+		return (*ip_fd->if_put_userdata)(ip_fd-> if_srfd, r, 
+							(acc_t *)0, TRUE);
+
+	case NWIOGIPCONF2:
+		ip_port= ip_fd->if_port;
+
+		if (!(ip_port->ip_flags & IPF_IPADDRSET))
+		{
+			ip_fd->if_ioctl= NWIOGIPCONF2;
+			ip_fd->if_flags |= IFF_IOCTL_IP;
+			return NW_SUSPEND;
+		}
+		ip_fd->if_flags &= ~IFF_IOCTL_IP;
+		data= bf_memreq(sizeof(nwio_ipconf_t));
+		ipconf2= (nwio_ipconf2_t *)ptr2acc_data(data);
+		ipconf2->nwic_flags= NWIC_IPADDR_SET;
+		ipconf2->nwic_ipaddr= ip_port->ip_ipaddr;
+		ipconf2->nwic_netmask= ip_port->ip_subnetmask;
+		if (ip_port->ip_flags & IPF_NETMASKSET)
+			ipconf2->nwic_flags |= NWIC_NETMASK_SET;
+
+		result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd, 0, data, 
+									TRUE);
+		return (*ip_fd->if_put_userdata)(ip_fd->if_srfd, result, 
+							(acc_t *)0, TRUE);
+	
+	case NWIOGIPCONF:
+		ip_port= ip_fd->if_port;
+
+		if (!(ip_port->ip_flags & IPF_IPADDRSET))
+		{
+			ip_fd->if_ioctl= NWIOGIPCONF;
+			ip_fd->if_flags |= IFF_IOCTL_IP;
+			return NW_SUSPEND;
+		}
+		ip_fd->if_flags &= ~IFF_IOCTL_IP;
+		data= bf_memreq(sizeof(*ipconf));
+		ipconf= (nwio_ipconf_t *)ptr2acc_data(data);
+		ipconf->nwic_flags= NWIC_IPADDR_SET;
+		ipconf->nwic_ipaddr= ip_port->ip_ipaddr;
+		ipconf->nwic_netmask= ip_port->ip_subnetmask;
+		if (ip_port->ip_flags & IPF_NETMASKSET)
+			ipconf->nwic_flags |= NWIC_NETMASK_SET;
+		ipconf->nwic_mtu= ip_port->ip_mtu;
+
+		result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd, 0, data, 
+									TRUE);
+		return (*ip_fd->if_put_userdata)(ip_fd->if_srfd, result, 
+							(acc_t *)0, TRUE);
+
+	case NWIOGIPOROUTE:
+		data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
+			0, sizeof(nwio_route_t), TRUE);
+		if (data == NULL)
+		{
+			return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
+				EFAULT, NULL, TRUE);
+		}
+
+		data= bf_packIffLess (data, sizeof(nwio_route_t) );
+		route_ent= (nwio_route_t *)ptr2acc_data(data);
+		ent_no= route_ent->nwr_ent_no;
+		bf_afree(data);
+
+		data= bf_memreq(sizeof(nwio_route_t));
+		route_ent= (nwio_route_t *)ptr2acc_data(data);
+		result= ipr_get_oroute(ent_no, route_ent);
+		if (result < 0)
+			bf_afree(data);
+		else
+		{
+			assert(result == NW_OK);
+			result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd, 0,
+				data, TRUE);
+		}
+		return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
+			result, (acc_t *)0, TRUE);
+
+	case NWIOSIPOROUTE:
+		data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
+			0, sizeof(nwio_route_t), TRUE);
+		if (data == NULL)
+		{
+			return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
+				EFAULT, NULL, TRUE);
+		}
+		if (!(ip_fd->if_port->ip_flags & IPF_IPADDRSET))
+		{
+			/* Interface is down, no changes allowed */
+			return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
+				EINVAL, NULL, TRUE);
+		}
+
+		data= bf_packIffLess (data, sizeof(nwio_route_t) );
+		route_ent= (nwio_route_t *)ptr2acc_data(data);
+		result= ipr_add_oroute(ip_fd->if_port-ip_port_table, 
+			route_ent->nwr_dest, route_ent->nwr_netmask, 
+			route_ent->nwr_gateway, (time_t)0, 
+			route_ent->nwr_dist, route_ent->nwr_mtu,
+			!!(route_ent->nwr_flags & NWRF_STATIC), 
+			route_ent->nwr_pref, NULL);
+		bf_afree(data);
+
+		return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
+			result, (acc_t *)0, TRUE);
+
+	case NWIODIPOROUTE:
+		data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
+			0, sizeof(nwio_route_t), TRUE);
+		if (data == NULL)
+		{
+			return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
+				EFAULT, NULL, TRUE);
+		}
+
+		data= bf_packIffLess (data, sizeof(nwio_route_t) );
+		route_ent= (nwio_route_t *)ptr2acc_data(data);
+		result= ipr_del_oroute(ip_fd->if_port-ip_port_table, 
+			route_ent->nwr_dest, route_ent->nwr_netmask, 
+			route_ent->nwr_gateway,
+			!!(route_ent->nwr_flags & NWRF_STATIC));
+		bf_afree(data);
+
+		return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
+			result, (acc_t *)0, TRUE);
+
+	case NWIOGIPIROUTE:
+		data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
+			0, sizeof(nwio_route_t), TRUE);
+		if (data == NULL)
+		{
+			return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
+				EFAULT, NULL, TRUE);
+		}
+
+		data= bf_packIffLess (data, sizeof(nwio_route_t) );
+		route_ent= (nwio_route_t *)ptr2acc_data(data);
+		ent_no= route_ent->nwr_ent_no;
+		bf_afree(data);
+
+		data= bf_memreq(sizeof(nwio_route_t));
+		route_ent= (nwio_route_t *)ptr2acc_data(data);
+		result= ipr_get_iroute(ent_no, route_ent);
+		if (result < 0)
+			bf_afree(data);
+		else
+		{
+			assert(result == NW_OK);
+			result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd, 0,
+				data, TRUE);
+		}
+		return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
+			result, (acc_t *)0, TRUE);
+
+	case NWIOSIPIROUTE:
+		data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
+			0, sizeof(nwio_route_t), TRUE);
+		if (data == NULL)
+		{
+			return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
+				EFAULT, NULL, TRUE);
+		}
+		if (!(ip_fd->if_port->ip_flags & IPF_IPADDRSET))
+		{
+			/* Interface is down, no changes allowed */
+			return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
+				EINVAL, NULL, TRUE);
+		}
+
+		data= bf_packIffLess (data, sizeof(nwio_route_t) );
+		route_ent= (nwio_route_t *)ptr2acc_data(data);
+		result= ipr_add_iroute(ip_fd->if_port-ip_port_table, 
+			route_ent->nwr_dest, route_ent->nwr_netmask, 
+			route_ent->nwr_gateway,
+			(route_ent->nwr_flags & NWRF_UNREACHABLE) ? 
+				IRTD_UNREACHABLE : route_ent->nwr_dist,
+			route_ent->nwr_mtu,
+			!!(route_ent->nwr_flags & NWRF_STATIC), NULL);
+		bf_afree(data);
+
+		return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
+			result, (acc_t *)0, TRUE);
+
+	case NWIODIPIROUTE:
+		data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,
+			0, sizeof(nwio_route_t), TRUE);
+		if (data == NULL)
+		{
+			return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
+				EFAULT, NULL, TRUE);
+		}
+
+		data= bf_packIffLess (data, sizeof(nwio_route_t) );
+		route_ent= (nwio_route_t *)ptr2acc_data(data);
+		result= ipr_del_iroute(ip_fd->if_port-ip_port_table, 
+			route_ent->nwr_dest, route_ent->nwr_netmask, 
+			route_ent->nwr_gateway,
+			!!(route_ent->nwr_flags & NWRF_STATIC));
+		bf_afree(data);
+
+		return (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
+			result, (acc_t *)0, TRUE);
+
+		/* The following ARP ioctls are only valid if the
+		 * underlying device is an ethernet.
+		 */
+	case NWIOARPGIP:
+	case NWIOARPGNEXT:
+	case NWIOARPSIP:
+	case NWIOARPDIP:
+		ip_port= ip_fd->if_port;
+
+		if (ip_port->ip_dl_type != IPDL_ETH)
+		{
+			return (*ip_fd->if_put_userdata)(ip_fd->if_srfd, 
+				EBADIOCTL, (acc_t *)0, TRUE);
+		}
+		result= arp_ioctl(ip_port->ip_dl.dl_eth.de_port,
+			ip_fd->if_srfd, req, ip_fd->if_get_userdata,
+			ip_fd->if_put_userdata);
+		assert (result != SUSPEND);
+		return (*ip_fd->if_put_userdata)(ip_fd->if_srfd, result,
+			(acc_t *)0, TRUE);
+
+	default:
+		break;
+	}
+	DBLOCK(1, printf("replying EBADIOCTL: 0x%x\n", req));
+	return (*ip_fd->if_put_userdata)(ip_fd->if_srfd, EBADIOCTL,
+		(acc_t *)0, TRUE);
+}
+
+PUBLIC void ip_hash_proto(ip_fd)
+ip_fd_t *ip_fd;
+{
+	ip_port_t *ip_port;
+	int hash;
+
+	ip_port= ip_fd->if_port;
+	if (ip_fd->if_ipopt.nwio_flags & NWIO_PROTOANY)
+	{
+		ip_fd->if_proto_next= ip_port->ip_proto_any;
+		ip_port->ip_proto_any= ip_fd;
+	}
+	else
+	{
+		hash= ip_fd->if_ipopt.nwio_proto & (IP_PROTO_HASH_NR-1);
+		ip_fd->if_proto_next= ip_port->ip_proto[hash];
+		ip_port->ip_proto[hash]= ip_fd;
+	}
+}
+
+PUBLIC void ip_unhash_proto(ip_fd)
+ip_fd_t *ip_fd;
+{
+	ip_port_t *ip_port;
+	ip_fd_t *prev, *curr, **ip_fd_p;
+	int hash;
+
+	ip_port= ip_fd->if_port;
+	if (ip_fd->if_ipopt.nwio_flags & NWIO_PROTOANY)
+	{
+		ip_fd_p= &ip_port->ip_proto_any;
+	}
+	else
+	{
+		hash= ip_fd->if_ipopt.nwio_proto & (IP_PROTO_HASH_NR-1);
+		ip_fd_p= &ip_port->ip_proto[hash];
+	}
+	for (prev= NULL, curr= *ip_fd_p; curr;
+		prev= curr, curr= curr->if_proto_next)
+	{
+		if (curr == ip_fd)
+			break;
+	}
+	assert(curr);
+	if (prev)
+		prev->if_proto_next= curr->if_proto_next;
+	else
+		*ip_fd_p= curr->if_proto_next;
+}
+
+PUBLIC int ip_setconf(ip_port_nr, ipconf)
+int ip_port_nr;
+nwio_ipconf_t *ipconf;
+{
+	int i, old_ip_flags, do_report;
+	ip_port_t *ip_port;
+	ip_fd_t *ip_fd;
+	ipaddr_t ipaddr;
+	u32_t mtu;
+
+	ip_port= &ip_port_table[ip_port_nr];
+
+	old_ip_flags= ip_port->ip_flags;
+
+	if (ipconf->nwic_flags & ~NWIC_FLAGS)
+		return EBADMODE;
+
+	do_report= 0;
+	if (ipconf->nwic_flags & NWIC_MTU_SET)
+	{
+		mtu= ipconf->nwic_mtu;
+		if (mtu < IP_MIN_MTU || mtu > ip_port->ip_mtu_max)
+			return EINVAL;
+		ip_port->ip_mtu= mtu;
+		do_report= 1;
+	}
+
+	if (ipconf->nwic_flags & NWIC_NETMASK_SET)
+	{
+		ip_port->ip_subnetmask= ipconf->nwic_netmask;
+		ip_port->ip_flags |= IPF_NETMASKSET|IPF_SUBNET_BCAST;
+		if (ntohl(ip_port->ip_subnetmask) >= 0xfffffffe)
+			ip_port->ip_flags &= ~IPF_SUBNET_BCAST;
+		do_report= 1;
+	}
+	if (ipconf->nwic_flags & NWIC_IPADDR_SET)
+	{
+		ipaddr= ipconf->nwic_ipaddr;
+		ip_port->ip_ipaddr= ipaddr;
+		ip_port->ip_flags |= IPF_IPADDRSET;
+		ip_port->ip_classfulmask=
+			ip_netmask(ip_nettype(ipaddr));
+		if (!(ip_port->ip_flags & IPF_NETMASKSET))
+		{
+		    ip_port->ip_subnetmask= ip_port->ip_classfulmask;
+		}
+		if (ipaddr == HTONL(0x00000000))
+		{
+			/* Special case. Use 0.0.0.0 to shutdown interface. */
+			ip_port->ip_flags &= ~(IPF_IPADDRSET|IPF_NETMASKSET);
+			ip_port->ip_subnetmask= HTONL(0x00000000);
+		}
+		(*ip_port->ip_dev_set_ipaddr)(ip_port);
+
+		/* revive calls waiting for an ip addresses */
+		for (i=0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
+		{
+			if (!(ip_fd->if_flags & IFF_INUSE))
+				continue;
+			if (ip_fd->if_port != ip_port)
+				continue;
+			if (ip_fd->if_flags & IFF_IOCTL_IP)
+				ip_ioctl (i, ip_fd->if_ioctl);
+		}
+		
+		do_report= 1;
+	}
+
+	ipr_chk_itab(ip_port-ip_port_table, ip_port->ip_ipaddr,
+		ip_port->ip_subnetmask);
+	ipr_chk_otab(ip_port-ip_port_table, ip_port->ip_ipaddr,
+		ip_port->ip_subnetmask);
+	if (do_report)
+		report_addr(ip_port);
+
+	return 0;
+}
+
+PRIVATE int ip_checkopt (ip_fd)
+ip_fd_t *ip_fd;
+{
+/* bug: we don't check access modes yet */
+
+	unsigned long flags;
+	unsigned int en_di_flags;
+	acc_t *pack;
+	int result;
+
+	flags= ip_fd->if_ipopt.nwio_flags;
+	en_di_flags= (flags >>16) | (flags & 0xffff);
+
+	if (flags & NWIO_HDR_O_SPEC)
+	{
+		result= ip_chk_hdropt (ip_fd->if_ipopt.nwio_hdropt.iho_data,
+			ip_fd->if_ipopt.nwio_hdropt.iho_opt_siz);
+		if (result<0)
+			return result;
+	}
+	if ((en_di_flags & NWIO_ACC_MASK) &&
+		(en_di_flags & NWIO_LOC_MASK) &&
+		(en_di_flags & NWIO_BROAD_MASK) &&
+		(en_di_flags & NWIO_REM_MASK) &&
+		(en_di_flags & NWIO_PROTO_MASK) &&
+		(en_di_flags & NWIO_HDR_O_MASK) &&
+		(en_di_flags & NWIO_RW_MASK))
+	{
+		ip_fd->if_flags |= IFF_OPTSET;
+
+		ip_hash_proto(ip_fd);
+	}
+
+	else
+		ip_fd->if_flags &= ~IFF_OPTSET;
+
+	while (ip_fd->if_rdbuf_head)
+	{
+		pack= ip_fd->if_rdbuf_head;
+		ip_fd->if_rdbuf_head= pack->acc_ext_link;
+		bf_afree(pack);
+	}
+	return NW_OK;
+}
+
+PRIVATE void reply_thr_get(ip_fd, reply, for_ioctl)
+ip_fd_t *ip_fd;
+size_t reply;
+int for_ioctl;
+{
+	acc_t *result;
+	result= (ip_fd->if_get_userdata)(ip_fd->if_srfd, reply,
+		(size_t)0, for_ioctl);
+	assert (!result);
+}
+
+PRIVATE void report_addr(ip_port)
+ip_port_t *ip_port;
+{
+	int i, hdr_len;
+	ip_fd_t *ip_fd;
+	acc_t *pack;
+	ip_hdr_t *ip_hdr;
+
+	pack= bf_memreq(IP_MIN_HDR_SIZE);
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
+
+	hdr_len= IP_MIN_HDR_SIZE;
+	ip_hdr->ih_vers_ihl= (IP_VERSION << 4) | (hdr_len/4);
+	ip_hdr->ih_tos= 0;
+	ip_hdr->ih_length= htons(ip_port->ip_mtu);
+	ip_hdr->ih_id= 0;
+	ip_hdr->ih_flags_fragoff= 0;
+	ip_hdr->ih_ttl= 0;
+	ip_hdr->ih_proto= 0;
+	ip_hdr->ih_src= ip_port->ip_ipaddr;
+	ip_hdr->ih_dst= ip_port->ip_subnetmask;
+	ip_hdr_chksum(ip_hdr, hdr_len);
+
+	for (i=0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)
+	{
+		if (!(ip_fd->if_flags & IFF_INUSE))
+		{
+			continue;
+		}
+		if (ip_fd->if_port != ip_port)
+		{
+			continue;
+		}
+
+		/* Deliver packet to user */
+		pack->acc_linkC++;
+		ip_packet2user(ip_fd, pack, 255, IP_MIN_HDR_SIZE);
+	}
+	bf_afree(pack); pack= NULL;
+}
+
+/*
+ * $PchId: ip_ioctl.c,v 1.22 2004/08/03 11:10:08 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/ip_lib.c
===================================================================
--- /trunk/minix/servers/inet/generic/ip_lib.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/ip_lib.c	(revision 9)
@@ -0,0 +1,237 @@
+/*
+ip_lib.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "buf.h"
+#include "event.h"
+#include "type.h"
+
+#include "assert.h"
+#include "io.h"
+#include "ip_int.h"
+
+THIS_FILE
+
+PUBLIC ipaddr_t ip_get_netmask (hostaddr)
+ipaddr_t hostaddr;
+{
+	return ip_netmask(ip_nettype(hostaddr));
+}
+
+PUBLIC int ip_chk_hdropt (opt, optlen)
+u8_t *opt;
+int optlen;
+{
+	int i, security_present= FALSE, lose_source_present= FALSE,
+		strict_source_present= FALSE, record_route_present= FALSE,
+		timestamp_present= FALSE;
+
+	assert (!(optlen & 3));
+	i= 0;
+	while (i<optlen)
+	{
+		DBLOCK(2, printf("*opt= %d\n", *opt));
+
+		switch (*opt)
+		{
+		case IP_OPT_EOL:	/* End of Option list */
+			return NW_OK;
+		case IP_OPT_NOP:	/* No Operation */
+			i++;
+			opt++;
+			break;
+		case IP_OPT_SEC:	/* Security */
+			if (security_present)
+				return EINVAL;
+			security_present= TRUE;
+			if (opt[1] != 11)
+				return EINVAL;
+			i += opt[1];
+			opt += opt[1];
+			break;
+		case IP_OPT_LSRR:	/* Lose Source and Record Route */
+			if (lose_source_present)
+			{
+				DBLOCK(1, printf("2nd lose soruce route\n"));
+				return EINVAL;
+			}
+			lose_source_present= TRUE;
+			if (opt[1]<3)
+			{
+				DBLOCK(1,
+				printf("wrong length in source route\n"));
+				return EINVAL;
+			}
+			i += opt[1];
+			opt += opt[1];
+			break;
+		case IP_OPT_SSRR:	/* Strict Source and Record Route */
+			if (strict_source_present)
+				return EINVAL;
+			strict_source_present= TRUE;
+			if (opt[1]<3)
+				return EINVAL;
+			i += opt[1];
+			opt += opt[1];
+			break;
+		case IP_OPT_RR:		/* Record Route */
+			if (record_route_present)
+				return EINVAL;
+			record_route_present= TRUE;
+			if (opt[1]<3)
+				return EINVAL;
+			i += opt[1];
+			opt += opt[1];
+			break;
+		case IP_OPT_TS:		/* Timestamp */
+			if (timestamp_present)
+				return EINVAL;
+			timestamp_present= TRUE;
+			if (opt[1] != 4)
+				return EINVAL;
+			switch (opt[3] & 0xff)
+			{
+			case 0:
+			case 1:
+			case 3:
+				break;
+			default:
+				return EINVAL;
+			}
+			i += opt[1];
+			opt += opt[1];
+			break;
+		case IP_OPT_RTRALT:
+			if (opt[1] != 4)
+				return EINVAL;
+			i += opt[1];
+			opt += opt[1];
+			break;
+		default:
+			return EINVAL;
+		}
+	}
+	if (i > optlen)
+	{
+		DBLOCK(1, printf("option of wrong length\n"));
+		return EINVAL;
+	}
+	return NW_OK;
+}
+
+PUBLIC void ip_print_frags(acc)
+acc_t *acc;
+{
+#if DEBUG
+	ip_hdr_t *ip_hdr;
+	int first;
+
+	if (!acc)
+		printf("(null)");
+
+	for (first= 1; acc; acc= acc->acc_ext_link, first= 0)
+	{
+assert (acc->acc_length >= IP_MIN_HDR_SIZE);
+		ip_hdr= (ip_hdr_t *)ptr2acc_data(acc);
+		if (first)
+		{
+			writeIpAddr(ip_hdr->ih_src);
+			printf(" > ");
+			writeIpAddr(ip_hdr->ih_dst);
+		}
+		printf(" {%x:%d@%d%c}", ntohs(ip_hdr->ih_id),
+			ntohs(ip_hdr->ih_length), 
+			(ntohs(ip_hdr->ih_flags_fragoff) & IH_FRAGOFF_MASK)*8,
+			(ntohs(ip_hdr->ih_flags_fragoff) & IH_MORE_FRAGS) ?
+			'+' : '\0');
+	}
+#endif
+}
+
+PUBLIC ipaddr_t ip_get_ifaddr(port_nr)
+int port_nr;
+{
+	assert(port_nr >= 0 && port_nr < ip_conf_nr);
+
+	return ip_port_table[port_nr].ip_ipaddr;
+}
+
+PUBLIC nettype_t ip_nettype(ipaddr)
+ipaddr_t ipaddr;
+{
+	u8_t highbyte;
+	nettype_t nettype;
+
+	ipaddr= ntohl(ipaddr);
+	highbyte= (ipaddr >> 24) & 0xff;
+	if (highbyte == 0)
+	{
+		if (ipaddr == 0)
+			nettype= IPNT_ZERO;
+		else
+			nettype= IPNT_MARTIAN;
+	}
+	else if (highbyte < 127)
+		nettype= IPNT_CLASS_A;
+	else if (highbyte == 127)
+		nettype= IPNT_LOCAL;
+	else if (highbyte < 192)
+		nettype= IPNT_CLASS_B;
+	else if (highbyte < 224)
+		nettype= IPNT_CLASS_C;
+	else if (highbyte < 240)
+		nettype= IPNT_CLASS_D;
+	else if (highbyte < 248)
+		nettype= IPNT_CLASS_E;
+	else if (highbyte < 255)
+		nettype= IPNT_MARTIAN;
+	else
+	{
+		if (ipaddr == (ipaddr_t)-1)
+			nettype= IPNT_BROADCAST;
+		else
+			nettype= IPNT_MARTIAN;
+	}
+	return nettype;
+}
+
+PUBLIC ipaddr_t ip_netmask(nettype)
+nettype_t nettype;
+{
+	switch(nettype)
+	{
+	case IPNT_ZERO:		return HTONL(0x00000000);
+	case IPNT_CLASS_A:
+	case IPNT_LOCAL:	return HTONL(0xff000000);
+	case IPNT_CLASS_B:	return HTONL(0xffff0000);
+	case IPNT_CLASS_C:	return HTONL(0xffffff00);
+	default:		return HTONL(0xffffffff);
+	}
+}
+
+#if 0
+PUBLIC char *ip_nettoa(nettype)
+nettype_t nettype;
+{
+	switch(nettype)
+	{
+	case IPNT_ZERO:		return "zero";
+	case IPNT_CLASS_A:	return "class A";
+	case IPNT_LOCAL:	return "local";
+	case IPNT_CLASS_B:	return "class B";
+	case IPNT_CLASS_C:	return "class C";
+	case IPNT_CLASS_D:	return "class D";
+	case IPNT_CLASS_E:	return "class E";
+	case IPNT_MARTIAN:	return "martian";
+	case IPNT_BROADCAST:	return "broadcast";
+	default:		return "<unknown>";
+	}
+}
+#endif
+
+/*
+ * $PchId: ip_lib.c,v 1.10 2002/06/08 21:35:52 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/ip_ps.c
===================================================================
--- /trunk/minix/servers/inet/generic/ip_ps.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/ip_ps.c	(revision 9)
@@ -0,0 +1,275 @@
+/*
+generic/ip_ps.c
+
+pseudo IP specific part of the IP implementation
+
+Created:	Apr 23, 1993 by Philip Homburg
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "assert.h"
+#include "type.h"
+#include "buf.h"
+#include "event.h"
+#include "ip.h"
+#include "ip_int.h"
+#include "psip.h"
+
+THIS_FILE
+
+FORWARD void ipps_main ARGS(( ip_port_t *ip_port ));
+FORWARD void ipps_set_ipaddr ARGS(( ip_port_t *ip_port ));
+FORWARD int ipps_send ARGS(( struct ip_port *ip_port, ipaddr_t dest, 
+					acc_t *pack, int type ));
+
+PUBLIC int ipps_init(ip_port)
+ip_port_t *ip_port;
+{
+	int result;
+
+	result= psip_enable(ip_port->ip_dl.dl_ps.ps_port, ip_port->ip_port);
+	if (result == -1)
+		return -1;
+	ip_port->ip_dl.dl_ps.ps_send_head= NULL;
+	ip_port->ip_dl.dl_ps.ps_send_tail= NULL;
+	ip_port->ip_dev_main= ipps_main;
+	ip_port->ip_dev_set_ipaddr= ipps_set_ipaddr;
+	ip_port->ip_dev_send= ipps_send;
+	return result;
+}
+
+PUBLIC void ipps_get(ip_port_nr)
+int ip_port_nr;
+{
+	int result;
+	ipaddr_t dest;
+	acc_t *acc, *pack, *next_part;
+	ip_port_t *ip_port;
+
+	assert(ip_port_nr >= 0 && ip_port_nr < ip_conf_nr);
+	ip_port= &ip_port_table[ip_port_nr];
+	assert(ip_port->ip_dl_type == IPDL_PSIP);
+
+	while (ip_port->ip_dl.dl_ps.ps_send_head != NULL)
+	{
+		pack= ip_port->ip_dl.dl_ps.ps_send_head;
+		ip_port->ip_dl.dl_ps.ps_send_head= pack->acc_ext_link;
+
+		/* Extract nexthop address */
+		pack= bf_packIffLess(pack, sizeof(dest));
+		dest= *(ipaddr_t *)ptr2acc_data(pack);
+		pack= bf_delhead(pack, sizeof(dest));
+
+		if (bf_bufsize(pack) > ip_port->ip_mtu)
+		{
+			next_part= pack;
+			pack= ip_split_pack(ip_port, &next_part, 
+				ip_port->ip_mtu);
+			if (pack == NULL)
+				continue;
+
+			/* Prepend nexthop address */
+			acc= bf_memreq(sizeof(dest));
+			*(ipaddr_t *)(ptr2acc_data(acc))= dest;
+			acc->acc_next= next_part;
+			next_part= acc; acc= NULL;
+
+			assert(next_part->acc_linkC == 1);
+			next_part->acc_ext_link= NULL;
+			if (ip_port->ip_dl.dl_ps.ps_send_head)
+			{
+				ip_port->ip_dl.dl_ps.ps_send_tail->
+					acc_ext_link= next_part;
+			}
+			else
+			{
+				ip_port->ip_dl.dl_ps.ps_send_head=
+					next_part;
+			}
+			ip_port->ip_dl.dl_ps.ps_send_tail= next_part;
+		}
+
+		result= psip_send(ip_port->ip_dl.dl_ps.ps_port, dest, pack);
+		if (result != NW_SUSPEND)
+		{
+			assert(result == NW_OK);
+			continue;
+		}
+
+		/* Prepend nexthop address */
+		acc= bf_memreq(sizeof(dest));
+		*(ipaddr_t *)(ptr2acc_data(acc))= dest;
+		acc->acc_next= pack;
+		pack= acc; acc= NULL;
+
+		pack->acc_ext_link= ip_port->ip_dl.dl_ps.ps_send_head;
+		ip_port->ip_dl.dl_ps.ps_send_head= pack;
+		if (pack->acc_ext_link == NULL)
+			ip_port->ip_dl.dl_ps.ps_send_tail= pack;
+		break;
+	}
+}
+
+PUBLIC void ipps_put(ip_port_nr, nexthop, pack)
+int ip_port_nr;
+ipaddr_t nexthop;
+acc_t *pack;
+{
+	ip_port_t *ip_port;
+
+	assert(ip_port_nr >= 0 && ip_port_nr < ip_conf_nr);
+	ip_port= &ip_port_table[ip_port_nr];
+	assert(ip_port->ip_dl_type == IPDL_PSIP);
+	if (nexthop == HTONL(0xffffffff))
+		ip_arrived_broadcast(ip_port, pack);
+	else
+		ip_arrived(ip_port, pack);
+}
+
+PRIVATE void ipps_main(ip_port)
+ip_port_t *ip_port;
+{
+	/* nothing to do */
+}
+
+PRIVATE void ipps_set_ipaddr(ip_port)
+ip_port_t *ip_port;
+{
+}
+
+PRIVATE int ipps_send(ip_port, dest, pack, type)
+struct ip_port *ip_port;
+ipaddr_t dest;
+acc_t *pack;
+int type;
+{
+	int result;
+	acc_t *acc, *next_part;
+
+	if (type != IP_LT_NORMAL)
+	{
+		ip_arrived_broadcast(ip_port, bf_dupacc(pack));
+
+		/* Map all broadcasts to the on-link broadcast address.
+		 * This saves the application from having to to find out
+		 * if the destination is a subnet broadcast.
+		 */
+		dest= HTONL(0xffffffff);
+	}
+
+	/* Note that allocating a packet may trigger a cleanup action,
+	 * which may cause the send queue to become empty.
+	 */
+	while (ip_port->ip_dl.dl_ps.ps_send_head != NULL)
+	{
+		acc= bf_memreq(sizeof(dest));
+
+		if (ip_port->ip_dl.dl_ps.ps_send_head == NULL)
+		{
+			bf_afree(acc); acc= NULL;
+			continue;
+		}
+
+		/* Prepend nexthop address */
+		*(ipaddr_t *)(ptr2acc_data(acc))= dest;
+		acc->acc_next= pack;
+		pack= acc; acc= NULL;
+
+		assert(pack->acc_linkC == 1);
+		pack->acc_ext_link= NULL;
+
+		ip_port->ip_dl.dl_ps.ps_send_tail->acc_ext_link= pack;
+		ip_port->ip_dl.dl_ps.ps_send_tail= pack;
+
+		return NW_OK;
+	}
+
+	while (pack)
+	{
+		if (bf_bufsize(pack) > ip_port->ip_mtu)
+		{
+			next_part= pack;
+			pack= ip_split_pack(ip_port, &next_part, 
+				ip_port->ip_mtu);
+			if (pack == NULL)
+			{
+				return NW_OK;
+			}
+
+			/* Prepend nexthop address */
+			acc= bf_memreq(sizeof(dest));
+			*(ipaddr_t *)(ptr2acc_data(acc))= dest;
+			acc->acc_next= next_part;
+			next_part= acc; acc= NULL;
+
+			assert(next_part->acc_linkC == 1);
+			next_part->acc_ext_link= NULL;
+			ip_port->ip_dl.dl_ps.ps_send_head= next_part;
+			ip_port->ip_dl.dl_ps.ps_send_tail= next_part;
+		}
+		result= psip_send(ip_port->ip_dl.dl_ps.ps_port, dest, pack);
+		if (result == NW_SUSPEND)
+		{
+			/* Prepend nexthop address */
+			acc= bf_memreq(sizeof(dest));
+			*(ipaddr_t *)(ptr2acc_data(acc))= dest;
+			acc->acc_next= pack;
+			pack= acc; acc= NULL;
+
+			assert(pack->acc_linkC == 1);
+			pack->acc_ext_link= ip_port->ip_dl.dl_ps.ps_send_head;
+			ip_port->ip_dl.dl_ps.ps_send_head= pack;
+			if (!pack->acc_ext_link)
+				ip_port->ip_dl.dl_ps.ps_send_tail= pack;
+			break;
+		}
+		assert(result == NW_OK);
+		pack= ip_port->ip_dl.dl_ps.ps_send_head;
+		if (!pack)
+			break;
+		ip_port->ip_dl.dl_ps.ps_send_head= pack->acc_ext_link;
+
+		/* Extract nexthop address */
+		pack= bf_packIffLess(pack, sizeof(dest));
+		dest= *(ipaddr_t *)ptr2acc_data(pack);
+		pack= bf_delhead(pack, sizeof(dest));
+	}
+
+	return NW_OK;
+}
+
+#if 0
+int ipps_check(ip_port_t *ip_port)
+{
+	int n, bad;
+	acc_t *prev, *curr;
+
+	for (n= 0, prev= NULL, curr= ip_port->ip_dl.dl_ps.ps_send_head_;
+		curr; prev= curr, curr= curr->acc_ext_link)
+	{
+		n++;
+	}
+	bad= 0;
+	if (prev != NULL && prev != ip_port->ip_dl.dl_ps.ps_send_tail_)
+	{
+		printf("ipps_check, ip[%d]: wrong tail: got %p, expected %p\n",
+			ip_port-ip_port_table,
+			ip_port->ip_dl.dl_ps.ps_send_tail_, prev);
+		bad++;
+	}
+	if (n != ip_port->ip_dl.dl_ps.ps_send_nr)
+	{
+		printf("ipps_check, ip[%d]: wrong count: got %d, expected %d\n",
+			ip_port-ip_port_table,
+			ip_port->ip_dl.dl_ps.ps_send_nr, n);
+		bad++;
+	}
+	return bad == 0;
+}
+#endif
+
+/*
+ * $PchId: ip_ps.c,v 1.15 2003/01/21 15:57:52 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/ip_read.c
===================================================================
--- /trunk/minix/servers/inet/generic/ip_read.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/ip_read.c	(revision 9)
@@ -0,0 +1,1049 @@
+/*
+ip_read.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "buf.h"
+#include "clock.h"
+#include "event.h"
+#include "type.h"
+
+#include "assert.h"
+#include "icmp_lib.h"
+#include "io.h"
+#include "ip.h"
+#include "ip_int.h"
+#include "ipr.h"
+
+THIS_FILE
+
+FORWARD ip_ass_t *find_ass_ent ARGS(( ip_port_t *ip_port, U16_t id,
+	int proto, ipaddr_t src, ipaddr_t dst ));
+FORWARD acc_t *merge_frags ARGS(( acc_t *first, acc_t *second ));
+FORWARD int ip_frag_chk ARGS(( acc_t *pack ));
+FORWARD acc_t *reassemble ARGS(( ip_port_t *ip_port, acc_t *pack, 
+	ip_hdr_t *ip_hdr ));
+FORWARD void route_packets ARGS(( event_t *ev, ev_arg_t ev_arg ));
+FORWARD int broadcast_dst ARGS(( ip_port_t *ip_port, ipaddr_t dest ));
+
+PUBLIC int ip_read (fd, count)
+int fd;
+size_t count;
+{
+	ip_fd_t *ip_fd;
+	acc_t *pack;
+
+	ip_fd= &ip_fd_table[fd];
+	if (!(ip_fd->if_flags & IFF_OPTSET))
+	{
+		return (*ip_fd->if_put_userdata)(ip_fd->if_srfd, EBADMODE,
+			(acc_t *)0, FALSE);
+	}
+
+	ip_fd->if_rd_count= count;
+
+	ip_fd->if_flags |= IFF_READ_IP;
+	if (ip_fd->if_rdbuf_head)
+	{
+		if (get_time() <= ip_fd->if_exp_time)
+		{
+			pack= ip_fd->if_rdbuf_head;
+			ip_fd->if_rdbuf_head= pack->acc_ext_link;
+			ip_packet2user (ip_fd, pack, ip_fd->if_exp_time,
+				bf_bufsize(pack));
+			assert(!(ip_fd->if_flags & IFF_READ_IP));
+			return NW_OK;
+		}
+		while (ip_fd->if_rdbuf_head)
+		{
+			pack= ip_fd->if_rdbuf_head;
+			ip_fd->if_rdbuf_head= pack->acc_ext_link;
+			bf_afree(pack);
+		}
+	}
+	return NW_SUSPEND;
+}
+
+PRIVATE acc_t *reassemble (ip_port, pack, pack_hdr)
+ip_port_t *ip_port;
+acc_t *pack;
+ip_hdr_t *pack_hdr;
+{
+	ip_ass_t *ass_ent;
+	size_t pack_hdr_len, pack_data_len, pack_offset, tmp_offset;
+	u16_t pack_flags_fragoff;
+	acc_t *prev_acc, *curr_acc, *next_acc, *head_acc, *tmp_acc;
+	ip_hdr_t *tmp_hdr;
+	time_t first_time;
+
+	ass_ent= find_ass_ent (ip_port, pack_hdr->ih_id,
+		pack_hdr->ih_proto, pack_hdr->ih_src, pack_hdr->ih_dst);
+
+	pack_flags_fragoff= ntohs(pack_hdr->ih_flags_fragoff);
+	pack_hdr_len= (pack_hdr->ih_vers_ihl & IH_IHL_MASK) * 4;
+	pack_data_len= ntohs(pack_hdr->ih_length)-pack_hdr_len;
+	pack_offset= (pack_flags_fragoff & IH_FRAGOFF_MASK)*8;
+	pack->acc_ext_link= NULL;
+
+	head_acc= ass_ent->ia_frags;
+	ass_ent->ia_frags= NULL;
+	if (head_acc == NULL)
+	{
+		ass_ent->ia_frags= pack;
+		return NULL;
+	}
+
+	prev_acc= NULL;
+	curr_acc= NULL;
+	next_acc= head_acc;
+
+	while(next_acc)
+	{
+		tmp_hdr= (ip_hdr_t *)ptr2acc_data(next_acc);
+		tmp_offset= (ntohs(tmp_hdr->ih_flags_fragoff) &
+			IH_FRAGOFF_MASK)*8;
+
+		if (pack_offset < tmp_offset)
+			break;
+
+		prev_acc= curr_acc;
+		curr_acc= next_acc;
+		next_acc= next_acc->acc_ext_link;
+	}
+	if (curr_acc == NULL)
+	{
+		assert(prev_acc == NULL);
+		assert(next_acc != NULL);
+
+		curr_acc= merge_frags(pack, next_acc);
+		head_acc= curr_acc;
+	}
+	else
+	{
+		curr_acc= merge_frags(curr_acc, pack);
+		if (next_acc != NULL)
+			curr_acc= merge_frags(curr_acc, next_acc);
+		if (prev_acc != NULL)
+			prev_acc->acc_ext_link= curr_acc;
+		else
+			head_acc= curr_acc;
+	}
+	ass_ent->ia_frags= head_acc;
+
+	pack= ass_ent->ia_frags;
+	pack_hdr= (ip_hdr_t *)ptr2acc_data(pack);
+	pack_flags_fragoff= ntohs(pack_hdr->ih_flags_fragoff);
+
+	if (!(pack_flags_fragoff & (IH_FRAGOFF_MASK|IH_MORE_FRAGS)))
+		/* it's now a complete packet */
+	{
+		first_time= ass_ent->ia_first_time;
+
+		ass_ent->ia_frags= 0;
+		ass_ent->ia_first_time= 0;
+
+		while (pack->acc_ext_link)
+		{
+			tmp_acc= pack->acc_ext_link;
+			pack->acc_ext_link= tmp_acc->acc_ext_link;
+			bf_afree(tmp_acc);
+		}
+		if ((ass_ent->ia_min_ttl) * HZ + first_time <
+			get_time())
+		{
+			if (broadcast_dst(ip_port, pack_hdr->ih_dst))
+			{
+				DBLOCK(1, printf(
+	"ip_read'reassemble: reassembly timeout for broadcast packet\n"););
+				bf_afree(pack); pack= NULL;
+				return NULL;
+			}
+			icmp_snd_time_exceeded(ip_port->ip_port, pack,
+				ICMP_FRAG_REASSEM);
+		}
+		else
+			return pack;
+	}
+	return NULL;
+}
+
+PRIVATE acc_t *merge_frags (first, second)
+acc_t *first, *second;
+{
+	ip_hdr_t *first_hdr, *second_hdr;
+	size_t first_hdr_size, second_hdr_size, first_datasize, second_datasize,
+		first_offset, second_offset;
+	acc_t *cut_second, *tmp_acc;
+
+	if (!second)
+	{
+		first->acc_ext_link= NULL;
+		return first;
+	}
+
+assert (first->acc_length >= IP_MIN_HDR_SIZE);
+assert (second->acc_length >= IP_MIN_HDR_SIZE);
+
+	first_hdr= (ip_hdr_t *)ptr2acc_data(first);
+	first_offset= (ntohs(first_hdr->ih_flags_fragoff) &
+		IH_FRAGOFF_MASK) * 8;
+	first_hdr_size= (first_hdr->ih_vers_ihl & IH_IHL_MASK) * 4;
+	first_datasize= ntohs(first_hdr->ih_length) - first_hdr_size;
+
+	second_hdr= (ip_hdr_t *)ptr2acc_data(second);
+	second_offset= (ntohs(second_hdr->ih_flags_fragoff) &
+		IH_FRAGOFF_MASK) * 8;
+	second_hdr_size= (second_hdr->ih_vers_ihl & IH_IHL_MASK) * 4;
+	second_datasize= ntohs(second_hdr->ih_length) - second_hdr_size;
+
+	assert (first_hdr_size + first_datasize == bf_bufsize(first));
+	assert (second_hdr_size + second_datasize == bf_bufsize(second));
+	assert (second_offset >= first_offset);
+
+	if (second_offset > first_offset+first_datasize)
+	{
+		DBLOCK(1, printf("ip fragments out of order\n"));
+		first->acc_ext_link= second;
+		return first;
+	}
+
+	if (second_offset + second_datasize <= first_offset +
+		first_datasize)
+	{
+		/* May cause problems if we try to merge. */
+		bf_afree(first);
+		return second;
+	}
+
+	if (!(second_hdr->ih_flags_fragoff & HTONS(IH_MORE_FRAGS)))
+		first_hdr->ih_flags_fragoff &= ~HTONS(IH_MORE_FRAGS);
+
+	second_datasize= second_offset+second_datasize-(first_offset+
+		first_datasize);
+	cut_second= bf_cut(second, second_hdr_size + first_offset+
+		first_datasize-second_offset, second_datasize);
+	tmp_acc= second->acc_ext_link;
+	bf_afree(second);
+	second= tmp_acc;
+
+	first_datasize += second_datasize;
+	first_hdr->ih_length= htons(first_hdr_size + first_datasize);
+
+	first= bf_append (first, cut_second);
+	first->acc_ext_link= second;
+
+assert (first_hdr_size + first_datasize == bf_bufsize(first));
+
+	return first;
+}
+
+PRIVATE ip_ass_t *find_ass_ent (ip_port, id, proto, src, dst)
+ip_port_t *ip_port;
+u16_t id;
+ipproto_t proto;
+ipaddr_t src;
+ipaddr_t dst;
+{
+	ip_ass_t *new_ass_ent, *tmp_ass_ent;
+	int i;
+	acc_t *tmp_acc, *curr_acc;
+
+	new_ass_ent= 0;
+
+	for (i=0, tmp_ass_ent= ip_ass_table; i<IP_ASS_NR; i++,
+		tmp_ass_ent++)
+	{
+		if (!tmp_ass_ent->ia_frags && tmp_ass_ent->ia_first_time)
+		{
+			DBLOCK(1,
+		printf("strange ip_ass entry (can be a race condition)\n"));
+			continue;
+		}
+
+		if ((tmp_ass_ent->ia_srcaddr == src) &&
+			(tmp_ass_ent->ia_dstaddr == dst) &&
+			(tmp_ass_ent->ia_proto == proto) &&
+			(tmp_ass_ent->ia_id == id) &&
+			(tmp_ass_ent->ia_port == ip_port))
+		{
+			return tmp_ass_ent;
+		}
+		if (!new_ass_ent || tmp_ass_ent->ia_first_time <
+			new_ass_ent->ia_first_time)
+		{
+			new_ass_ent= tmp_ass_ent;
+		}
+	}
+
+	if (new_ass_ent->ia_frags)
+	{
+		DBLOCK(2, printf("old frags id= %u, proto= %u, src= ",
+			ntohs(new_ass_ent->ia_id),
+			new_ass_ent->ia_proto);
+			writeIpAddr(new_ass_ent->ia_srcaddr); printf(" dst= ");
+			writeIpAddr(new_ass_ent->ia_dstaddr); printf(": ");
+			ip_print_frags(new_ass_ent->ia_frags); printf("\n"));
+		curr_acc= new_ass_ent->ia_frags->acc_ext_link;
+		while (curr_acc)
+		{
+			tmp_acc= curr_acc->acc_ext_link;
+			bf_afree(curr_acc);
+			curr_acc= tmp_acc;
+		}
+		curr_acc= new_ass_ent->ia_frags;
+		new_ass_ent->ia_frags= 0;
+		if (broadcast_dst(ip_port, new_ass_ent->ia_dstaddr))
+		{
+			DBLOCK(1, printf(
+	"ip_read'find_ass_ent: reassembly timeout for broadcast packet\n"));
+			bf_afree(curr_acc); curr_acc= NULL;
+		}
+		else
+		{
+			icmp_snd_time_exceeded(ip_port->ip_port,
+				curr_acc, ICMP_FRAG_REASSEM);
+		}
+	}
+	new_ass_ent->ia_min_ttl= IP_MAX_TTL;
+	new_ass_ent->ia_port= ip_port;
+	new_ass_ent->ia_first_time= get_time();
+	new_ass_ent->ia_srcaddr= src;
+	new_ass_ent->ia_dstaddr= dst;
+	new_ass_ent->ia_proto= proto;
+	new_ass_ent->ia_id= id;
+
+	return new_ass_ent;
+}
+
+PRIVATE int ip_frag_chk(pack)
+acc_t *pack;
+{
+	ip_hdr_t *ip_hdr;
+	int hdr_len;
+
+	if (pack->acc_length < sizeof(ip_hdr_t))
+	{
+		DBLOCK(1, printf("wrong length\n"));
+		return FALSE;
+	}
+
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
+
+	hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) * 4;
+	if (pack->acc_length < hdr_len)
+	{
+		DBLOCK(1, printf("wrong length\n"));
+
+		return FALSE;
+	}
+
+	if (((ip_hdr->ih_vers_ihl >> 4) & IH_VERSION_MASK) !=
+		IP_VERSION)
+	{
+		DBLOCK(1, printf("wrong version (ih_vers_ihl=0x%x)\n",
+			ip_hdr->ih_vers_ihl));
+		return FALSE;
+	}
+	if (ntohs(ip_hdr->ih_length) != bf_bufsize(pack))
+	{
+		DBLOCK(1, printf("wrong size\n"));
+
+		return FALSE;
+	}
+	if ((u16_t)~oneC_sum(0, (u16_t *)ip_hdr, hdr_len))
+	{
+		DBLOCK(1, printf("packet with wrong checksum (= %x)\n", 
+			(u16_t)~oneC_sum(0, (u16_t *)ip_hdr, hdr_len)));
+		return FALSE;
+	}
+	if (hdr_len>IP_MIN_HDR_SIZE && ip_chk_hdropt((u8_t *)
+		(ptr2acc_data(pack) + IP_MIN_HDR_SIZE),
+		hdr_len-IP_MIN_HDR_SIZE))
+	{
+		DBLOCK(1, printf("packet with wrong options\n"));
+		return FALSE;
+	}
+	return TRUE;
+}
+
+PUBLIC void ip_packet2user (ip_fd, pack, exp_time, data_len)
+ip_fd_t *ip_fd;
+acc_t *pack;
+time_t exp_time;
+size_t data_len;
+{
+	acc_t *tmp_pack;
+	ip_hdr_t *ip_hdr;
+	int result, ip_hdr_len;
+	size_t transf_size;
+
+	assert (ip_fd->if_flags & IFF_INUSE);
+	if (!(ip_fd->if_flags & IFF_READ_IP))
+	{
+		if (pack->acc_linkC != 1)
+		{
+			tmp_pack= bf_dupacc(pack);
+			bf_afree(pack);
+			pack= tmp_pack;
+			tmp_pack= NULL;
+		}
+		pack->acc_ext_link= NULL;
+		if (ip_fd->if_rdbuf_head == NULL)
+		{
+			ip_fd->if_rdbuf_head= pack;
+			ip_fd->if_exp_time= exp_time;
+		}
+		else
+			ip_fd->if_rdbuf_tail->acc_ext_link= pack;
+		ip_fd->if_rdbuf_tail= pack;
+		return;
+	}
+
+	assert (pack->acc_length >= IP_MIN_HDR_SIZE);
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
+
+	if (ip_fd->if_ipopt.nwio_flags & NWIO_RWDATONLY)
+	{
+		ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) * 4;
+
+		assert (data_len > ip_hdr_len);
+		data_len -= ip_hdr_len;
+		pack= bf_delhead(pack, ip_hdr_len);
+	}
+
+	if (data_len > ip_fd->if_rd_count)
+	{
+		tmp_pack= bf_cut (pack, 0, ip_fd->if_rd_count);
+		bf_afree(pack);
+		pack= tmp_pack;
+		transf_size= ip_fd->if_rd_count;
+	}
+	else
+		transf_size= data_len;
+
+	if (ip_fd->if_put_pkt)
+	{
+		(*ip_fd->if_put_pkt)(ip_fd->if_srfd, pack, transf_size);
+		return;
+	}
+
+	result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd,
+		(size_t)0, pack, FALSE);
+	if (result >= 0)
+	{
+		if (data_len > transf_size)
+			result= EPACKSIZE;
+		else
+			result= transf_size;
+	}
+
+	ip_fd->if_flags &= ~IFF_READ_IP;
+	result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd, result,
+			(acc_t *)0, FALSE);
+	assert (result >= 0);
+}
+
+PUBLIC void ip_port_arrive (ip_port, pack, ip_hdr)
+ip_port_t *ip_port;
+acc_t *pack;
+ip_hdr_t *ip_hdr;
+{
+	ip_fd_t *ip_fd, *first_fd, *share_fd;
+	unsigned long ip_pack_stat;
+	unsigned size;
+	int i;
+	int hash, proto;
+	time_t exp_time;
+
+	assert (pack->acc_linkC>0);
+	assert (pack->acc_length >= IP_MIN_HDR_SIZE);
+
+	if (ntohs(ip_hdr->ih_flags_fragoff) & (IH_FRAGOFF_MASK|IH_MORE_FRAGS))
+	{
+		pack= reassemble (ip_port, pack, ip_hdr);
+		if (!pack)
+			return;
+		assert (pack->acc_length >= IP_MIN_HDR_SIZE);
+		ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
+		assert (!(ntohs(ip_hdr->ih_flags_fragoff) &
+			(IH_FRAGOFF_MASK|IH_MORE_FRAGS)));
+	}
+	size= ntohs(ip_hdr->ih_length);
+	if (size > bf_bufsize(pack))
+	{
+		/* Should discard packet */
+		assert(0);
+		bf_afree(pack); pack= NULL;
+		return;
+	}
+
+	exp_time= get_time() + (ip_hdr->ih_ttl+1) * HZ;
+
+	if (ip_hdr->ih_dst == ip_port->ip_ipaddr)
+		ip_pack_stat= NWIO_EN_LOC;
+	else
+		ip_pack_stat= NWIO_EN_BROAD;
+
+	proto= ip_hdr->ih_proto;
+	hash= proto & (IP_PROTO_HASH_NR-1);
+
+	first_fd= NULL;
+	for (i= 0; i<2; i++)
+	{
+		share_fd= NULL;
+
+		ip_fd= (i == 0) ? ip_port->ip_proto_any :
+			ip_port->ip_proto[hash];
+		for (; ip_fd; ip_fd= ip_fd->if_proto_next)
+		{
+			if (i && ip_fd->if_ipopt.nwio_proto != proto)
+				continue;
+			if (!(ip_fd->if_ipopt.nwio_flags & ip_pack_stat))
+				continue;
+			if ((ip_fd->if_ipopt.nwio_flags & NWIO_REMSPEC) &&
+				ip_hdr->ih_src != ip_fd->if_ipopt.nwio_rem)
+			{
+				continue;
+			}
+			if ((ip_fd->if_ipopt.nwio_flags & NWIO_ACC_MASK) ==
+				NWIO_SHARED)
+			{
+				if (!share_fd)
+				{
+					share_fd= ip_fd;
+					continue;
+				}
+				if (!ip_fd->if_rdbuf_head)
+					share_fd= ip_fd;
+				continue;
+			}
+			if (!first_fd)
+			{
+				first_fd= ip_fd;
+				continue;
+			}
+			pack->acc_linkC++;
+			ip_packet2user(ip_fd, pack, exp_time, size);
+
+		}
+		if (share_fd)
+		{
+			pack->acc_linkC++;
+			ip_packet2user(share_fd, pack, exp_time, size);
+		}
+	}
+	if (first_fd)
+	{
+		if (first_fd->if_put_pkt &&
+			(first_fd->if_flags & IFF_READ_IP) &&
+			!(first_fd->if_ipopt.nwio_flags & NWIO_RWDATONLY))
+		{
+			(*first_fd->if_put_pkt)(first_fd->if_srfd, pack,
+				size);
+		}
+		else
+			ip_packet2user(first_fd, pack, exp_time, size);
+	}
+	else
+	{
+		if (ip_pack_stat == NWIO_EN_LOC)
+		{
+			DBLOCK(0x01,
+			printf("ip_port_arrive: dropping packet for proto %d\n",
+				proto));
+		}
+		else
+		{
+			DBLOCK(0x20, printf("dropping packet for proto %d\n",
+				proto));
+		}
+		bf_afree(pack);
+	}
+}
+
+PUBLIC void ip_arrived(ip_port, pack)
+ip_port_t *ip_port;
+acc_t *pack;
+{
+	ip_hdr_t *ip_hdr;
+	ipaddr_t dest;
+	int ip_frag_len, ip_hdr_len, highbyte;
+	size_t pack_size;
+	acc_t *tmp_pack, *hdr_pack;
+	ev_arg_t ev_arg;
+
+	pack_size= bf_bufsize(pack);
+
+	if (pack_size < IP_MIN_HDR_SIZE)
+	{
+		DBLOCK(1, printf("wrong acc_length\n"));
+		bf_afree(pack);
+		return;
+	}
+	pack= bf_align(pack, IP_MIN_HDR_SIZE, 4);
+	pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);
+assert (pack->acc_length >= IP_MIN_HDR_SIZE);
+
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
+	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
+	if (ip_hdr_len>IP_MIN_HDR_SIZE)
+	{
+		pack= bf_packIffLess(pack, ip_hdr_len);
+		ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
+	}
+	ip_frag_len= ntohs(ip_hdr->ih_length);
+	if (ip_frag_len != pack_size)
+	{
+		if (pack_size < ip_frag_len)
+		{
+			/* Sent ICMP? */
+			DBLOCK(1, printf("wrong acc_length\n"));
+			bf_afree(pack);
+			return;
+		}
+		assert(ip_frag_len<pack_size);
+		tmp_pack= pack;
+		pack= bf_cut(tmp_pack, 0, ip_frag_len);
+		bf_afree(tmp_pack);
+		pack_size= ip_frag_len;
+	}
+
+	if (!ip_frag_chk(pack))
+	{
+		DBLOCK(1, printf("fragment not allright\n"));
+		bf_afree(pack);
+		return;
+	}
+
+	/* Decide about local delivery or routing. Local delivery can happen
+	 * when the destination is the local ip address, or one of the 
+	 * broadcast addresses and the packet happens to be delivered 
+	 * point-to-point.
+	 */
+
+	dest= ip_hdr->ih_dst;
+
+	if (dest == ip_port->ip_ipaddr)
+	{
+		ip_port_arrive (ip_port, pack, ip_hdr);
+		return;
+	}
+	if (broadcast_dst(ip_port, dest))
+	{
+		ip_port_arrive (ip_port, pack, ip_hdr);
+		return;
+	}
+
+	if (pack->acc_linkC != 1 || pack->acc_buffer->buf_linkC != 1)
+	{
+		/* Get a private copy of the IP header */
+		hdr_pack= bf_memreq(ip_hdr_len);
+		memcpy(ptr2acc_data(hdr_pack), ip_hdr, ip_hdr_len);
+		pack= bf_delhead(pack, ip_hdr_len);
+		hdr_pack->acc_next= pack;
+		pack= hdr_pack; hdr_pack= NULL;
+		ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
+	}
+	assert(pack->acc_linkC == 1);
+	assert(pack->acc_buffer->buf_linkC == 1);
+
+	/* Try to decrement the ttl field with one. */
+	if (ip_hdr->ih_ttl < 2)
+	{
+		icmp_snd_time_exceeded(ip_port->ip_port, pack,
+			ICMP_TTL_EXC);
+		return;
+	}
+	ip_hdr->ih_ttl--;
+	ip_hdr_chksum(ip_hdr, ip_hdr_len);
+
+	/* Avoid routing to bad destinations. */
+	highbyte= ntohl(dest) >> 24;
+	if (highbyte == 0 || highbyte == 127 ||
+		(highbyte == 169 && (((ntohl(dest) >> 16) & 0xff) == 254)) ||
+		highbyte >= 0xe0)
+	{
+		/* Bogus destination address */
+		bf_afree(pack);
+		return;
+	}
+
+	/* Further processing from an event handler */
+	if (pack->acc_linkC != 1)
+	{
+		tmp_pack= bf_dupacc(pack);
+		bf_afree(pack);
+		pack= tmp_pack;
+		tmp_pack= NULL;
+	}
+	pack->acc_ext_link= NULL;
+	if (ip_port->ip_routeq_head)
+	{
+		ip_port->ip_routeq_tail->acc_ext_link= pack;
+		ip_port->ip_routeq_tail= pack;
+		return;
+	}
+
+	ip_port->ip_routeq_head= pack;
+	ip_port->ip_routeq_tail= pack;
+	ev_arg.ev_ptr= ip_port;
+	ev_enqueue(&ip_port->ip_routeq_event, route_packets, ev_arg);
+}
+
+PUBLIC void ip_arrived_broadcast(ip_port, pack)
+ip_port_t *ip_port;
+acc_t *pack;
+{
+	ip_hdr_t *ip_hdr;
+	int ip_frag_len, ip_hdr_len;
+	size_t pack_size;
+	acc_t *tmp_pack;
+
+	pack_size= bf_bufsize(pack);
+
+	if (pack_size < IP_MIN_HDR_SIZE)
+	{
+		DBLOCK(1, printf("wrong acc_length\n"));
+		bf_afree(pack);
+		return;
+	}
+	pack= bf_align(pack, IP_MIN_HDR_SIZE, 4);
+	pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);
+assert (pack->acc_length >= IP_MIN_HDR_SIZE);
+
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
+
+	DIFBLOCK(0x20, (ip_hdr->ih_dst & HTONL(0xf0000000)) == HTONL(0xe0000000),
+		printf("got multicast packet\n"));
+
+	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
+	if (ip_hdr_len>IP_MIN_HDR_SIZE)
+	{
+		pack= bf_align(pack, IP_MIN_HDR_SIZE, 4);
+		pack= bf_packIffLess(pack, ip_hdr_len);
+		ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
+	}
+	ip_frag_len= ntohs(ip_hdr->ih_length);
+	if (ip_frag_len<pack_size)
+	{
+		tmp_pack= pack;
+		pack= bf_cut(tmp_pack, 0, ip_frag_len);
+		bf_afree(tmp_pack);
+	}
+
+	if (!ip_frag_chk(pack))
+	{
+		DBLOCK(1, printf("fragment not allright\n"));
+		bf_afree(pack);
+		return;
+	}
+
+	if (!broadcast_dst(ip_port, ip_hdr->ih_dst))
+	{
+#if 0
+		printf(
+		"ip[%d]: broadcast packet for ip-nonbroadcast addr, src=",
+			ip_port->ip_port);
+		writeIpAddr(ip_hdr->ih_src);
+		printf(" dst=");
+		writeIpAddr(ip_hdr->ih_dst);
+		printf("\n");
+#endif
+		bf_afree(pack);
+		return;
+	}
+
+	ip_port_arrive (ip_port, pack, ip_hdr);
+}
+
+PRIVATE void route_packets(ev, ev_arg)
+event_t *ev;
+ev_arg_t ev_arg;
+{
+	ip_port_t *ip_port;
+	ipaddr_t dest;
+	acc_t *pack;
+	iroute_t *iroute;
+	ip_port_t *next_port;
+	int r, type;
+	ip_hdr_t *ip_hdr;
+	size_t req_mtu;
+
+	ip_port= ev_arg.ev_ptr;
+	assert(&ip_port->ip_routeq_event == ev);
+
+	while (pack= ip_port->ip_routeq_head, pack != NULL)
+	{
+		ip_port->ip_routeq_head= pack->acc_ext_link;
+
+		ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
+		dest= ip_hdr->ih_dst;
+
+		iroute= iroute_frag(ip_port->ip_port, dest);
+		if (iroute == NULL || iroute->irt_dist == IRTD_UNREACHABLE)
+		{
+			/* Also unreachable */
+			/* Finding out if we send a network unreachable is too
+			 * much trouble.
+			 */
+			if (iroute == NULL)
+			{
+				printf("ip[%d]: no route to ",
+					ip_port-ip_port_table);
+				writeIpAddr(dest);
+				printf("\n");
+			}
+			icmp_snd_unreachable(ip_port->ip_port, pack,
+				ICMP_HOST_UNRCH);
+			continue;
+		}
+		next_port= &ip_port_table[iroute->irt_port];
+
+		if (ip_hdr->ih_flags_fragoff & HTONS(IH_DONT_FRAG))
+		{
+			req_mtu= bf_bufsize(pack);
+			if (req_mtu > next_port->ip_mtu ||
+				(iroute->irt_mtu && req_mtu>iroute->irt_mtu))
+			{
+				icmp_snd_mtu(ip_port->ip_port, pack,
+					next_port->ip_mtu);
+				continue;
+			}
+		}
+
+		if (next_port != ip_port)
+		{
+			if (iroute->irt_gateway != 0)
+			{
+				/* Just send the packet to the next gateway */
+				pack->acc_linkC++; /* Extra ref for ICMP */
+				r= next_port->ip_dev_send(next_port,
+					iroute->irt_gateway,
+					pack, IP_LT_NORMAL);
+				if (r == EDSTNOTRCH)
+				{
+					printf("ip[%d]: gw ",
+						ip_port-ip_port_table);
+					writeIpAddr(iroute->irt_gateway);
+					printf(" on ip[%d] is down for dest ",
+						next_port-ip_port_table);
+					writeIpAddr(dest);
+					printf("\n");
+					icmp_snd_unreachable(next_port-
+						ip_port_table, pack,
+						ICMP_HOST_UNRCH);
+					pack= NULL;
+				}
+				else
+				{
+					assert(r == 0);
+					bf_afree(pack); pack= NULL;
+				}
+				continue;
+			}
+			/* The packet is for the attached network. Special
+			 * addresses are the ip address of the interface and
+			 * net.0 if no IP_42BSD_BCAST.
+			 */
+			if (dest == next_port->ip_ipaddr)
+			{
+				ip_port_arrive (next_port, pack, ip_hdr);
+				continue;
+			}
+			if (dest == iroute->irt_dest)
+			{
+				/* Never forward obsolete directed broadcasts */
+#if IP_42BSD_BCAST && 0
+				type= IP_LT_BROADCAST;
+#else
+				/* Bogus destination address */
+				DBLOCK(1, printf(
+			"ip[%d]: dropping old-fashioned directed broadcast ",
+						ip_port-ip_port_table);
+					writeIpAddr(dest);
+					printf("\n"););
+				icmp_snd_unreachable(next_port-ip_port_table,
+					pack, ICMP_HOST_UNRCH);
+				continue;
+#endif
+			}
+			else if (dest == (iroute->irt_dest |
+				~iroute->irt_subnetmask))
+			{
+				if (!ip_forward_directed_bcast)
+				{
+					/* Do not forward directed broadcasts */
+					DBLOCK(1, printf(
+					"ip[%d]: dropping directed broadcast ",
+							ip_port-ip_port_table);
+						writeIpAddr(dest);
+						printf("\n"););
+					icmp_snd_unreachable(next_port-
+						ip_port_table, pack,
+						ICMP_HOST_UNRCH);
+					continue;
+				}
+				else
+					type= IP_LT_BROADCAST;
+			}
+			else
+				type= IP_LT_NORMAL;
+
+			/* Just send the packet to it's destination */
+			pack->acc_linkC++; /* Extra ref for ICMP */
+			r= next_port->ip_dev_send(next_port, dest, pack, type);
+			if (r == EDSTNOTRCH)
+			{
+				DBLOCK(1, printf("ip[%d]: next hop ",
+					ip_port-ip_port_table);
+					writeIpAddr(dest);
+					printf(" on ip[%d] is down\n",
+					next_port-ip_port_table););
+				icmp_snd_unreachable(next_port-ip_port_table,
+					pack, ICMP_HOST_UNRCH);
+				pack= NULL;
+			}
+			else
+			{
+				assert(r == 0 || (printf("r = %d\n", r), 0));
+				bf_afree(pack); pack= NULL;
+			}
+			continue;
+		}
+
+		/* Now we know that the packet should be routed over the same
+		 * network as it came from. If there is a next hop gateway,
+		 * we can send the packet to that gateway and send a redirect
+		 * ICMP to the sender if the sender is on the attached
+		 * network. If there is no gateway complain.
+		 */
+		if (iroute->irt_gateway == 0)
+		{
+			printf("ip_arrived: packet should not be here, src=");
+			writeIpAddr(ip_hdr->ih_src);
+			printf(" dst=");
+			writeIpAddr(ip_hdr->ih_dst);
+			printf("\n");
+			bf_afree(pack);
+			continue;
+		}
+		if (((ip_hdr->ih_src ^ ip_port->ip_ipaddr) &
+			ip_port->ip_subnetmask) == 0)
+		{
+			/* Finding out if we can send a network redirect
+			 * instead of a host redirect is too much trouble.
+			 */
+			pack->acc_linkC++;
+			icmp_snd_redirect(ip_port->ip_port, pack,
+				ICMP_REDIRECT_HOST, iroute->irt_gateway);
+		}
+		else
+		{
+			printf("ip_arrived: packet is wrongly routed, src=");
+			writeIpAddr(ip_hdr->ih_src);
+			printf(" dst=");
+			writeIpAddr(ip_hdr->ih_dst);
+			printf("\n");
+			printf("in port %d, output %d, dest net ",
+				ip_port->ip_port, 
+				iroute->irt_port);
+			writeIpAddr(iroute->irt_dest);
+			printf("/");
+			writeIpAddr(iroute->irt_subnetmask);
+			printf(" next hop ");
+			writeIpAddr(iroute->irt_gateway);
+			printf("\n");
+			bf_afree(pack);
+			continue;
+		}
+		/* No code for unreachable ICMPs here. The sender should
+		 * process the ICMP redirect and figure it out.
+		 */
+		ip_port->ip_dev_send(ip_port, iroute->irt_gateway, pack,
+			IP_LT_NORMAL);
+	}
+}
+
+PRIVATE int broadcast_dst(ip_port, dest)
+ip_port_t *ip_port;
+ipaddr_t dest;
+{
+	ipaddr_t my_ipaddr, netmask, classmask;
+
+	/* Treat class D (multicast) address as broadcasts. */
+	if ((dest & HTONL(0xF0000000)) == HTONL(0xE0000000))
+	{
+		return 1;
+	}
+
+	/* Accept without complaint if netmask not yet configured. */
+	if (!(ip_port->ip_flags & IPF_NETMASKSET))
+	{
+		return 1;
+	}
+	/* Two possibilities, 0 (iff IP_42BSD_BCAST) and -1 */
+	if (dest == HTONL((ipaddr_t)-1))
+		return 1;
+#if IP_42BSD_BCAST
+	if (dest == HTONL((ipaddr_t)0))
+		return 1;
+#endif
+	netmask= ip_port->ip_subnetmask;
+	my_ipaddr= ip_port->ip_ipaddr;
+
+	if (((my_ipaddr ^ dest) & netmask) != 0)
+	{
+		classmask= ip_port->ip_classfulmask;
+
+		/* Not a subnet broadcast, maybe a classful broadcast */
+		if (((my_ipaddr ^ dest) & classmask) != 0)
+		{
+			return 0;
+		}
+		/* Two possibilities, net.0 (iff IP_42BSD_BCAST) and net.-1 */
+		if ((dest & ~classmask) == ~classmask)
+		{
+			return 1;
+		}
+#if IP_42BSD_BCAST
+		if ((dest & ~classmask) == 0)
+			return 1;
+#endif
+		return 0;
+	}
+
+	if (!(ip_port->ip_flags & IPF_SUBNET_BCAST))
+		return 0;	/* No subnet broadcasts on this network */
+
+	/* Two possibilities, subnet.0 (iff IP_42BSD_BCAST) and subnet.-1 */
+	if ((dest & ~netmask) == ~netmask)
+		return 1;
+#if IP_42BSD_BCAST
+	if ((dest & ~netmask) == 0)
+		return 1;
+#endif
+	return 0;
+}
+
+void ip_process_loopb(ev, arg)
+event_t *ev;
+ev_arg_t arg;
+{
+	ip_port_t *ip_port;
+	acc_t *pack;
+
+	ip_port= arg.ev_ptr;
+	assert(ev == &ip_port->ip_loopb_event);
+
+	while(pack= ip_port->ip_loopb_head, pack != NULL)
+	{
+		ip_port->ip_loopb_head= pack->acc_ext_link;
+		ip_arrived(ip_port, pack);
+	}
+}
+
+/*
+ * $PchId: ip_read.c,v 1.33 2005/06/28 14:18:50 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/ip_write.c
===================================================================
--- /trunk/minix/servers/inet/generic/ip_write.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/ip_write.c	(revision 9)
@@ -0,0 +1,515 @@
+/*
+ip_write.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "buf.h"
+#include "event.h"
+#include "type.h"
+
+#include "arp.h"
+#include "assert.h"
+#include "clock.h"
+#include "eth.h"
+#include "icmp_lib.h"
+#include "io.h"
+#include "ip.h"
+#include "ip_int.h"
+#include "ipr.h"
+
+THIS_FILE
+
+FORWARD void error_reply ARGS(( ip_fd_t *fd, int error ));
+
+PUBLIC int ip_write (fd, count)
+int fd;
+size_t count;
+{
+	ip_fd_t *ip_fd;
+	acc_t *pack;
+	int r;
+
+	ip_fd= &ip_fd_table[fd];
+	if (count > IP_MAX_PACKSIZE)
+	{
+		error_reply (ip_fd, EPACKSIZE);
+		return NW_OK;
+	}
+	pack= (*ip_fd->if_get_userdata)(ip_fd->if_srfd, (size_t)0,
+		count, FALSE);
+	if (!pack)
+		return NW_OK;
+	r= ip_send(fd, pack, count);
+	assert(r != NW_WOULDBLOCK);
+
+	if (r == NW_OK)
+		error_reply (ip_fd, count);
+	else
+		error_reply (ip_fd, r);
+	return NW_OK;
+}
+
+PUBLIC int ip_send(fd, data, data_len)
+int fd;
+acc_t *data;
+size_t data_len;
+{
+	ip_port_t *ip_port;
+	ip_fd_t *ip_fd;
+	ip_hdr_t *ip_hdr, *tmp_hdr;
+	ipaddr_t dstaddr, nexthop, hostrep_dst, my_ipaddr, netmask;
+	u8_t *addrInBytes;
+	acc_t *tmp_pack, *tmp_pack1;
+	int hdr_len, hdr_opt_len, r;
+	int type, ttl;
+	size_t req_mtu;
+	ev_arg_t arg;
+
+	ip_fd= &ip_fd_table[fd];
+	ip_port= ip_fd->if_port;
+
+	if (!(ip_fd->if_flags & IFF_OPTSET))
+	{
+		bf_afree(data);
+		return EBADMODE;
+	}
+
+	if (!(ip_fd->if_port->ip_flags & IPF_IPADDRSET))
+	{
+		/* Interface is down. What kind of error do we want? For
+		 * the moment, we return OK.
+		 */
+		bf_afree(data);
+		return NW_OK;
+	}
+
+	data_len= bf_bufsize(data);
+
+	if (ip_fd->if_ipopt.nwio_flags & NWIO_RWDATONLY)
+	{
+		tmp_pack= bf_memreq(IP_MIN_HDR_SIZE);
+		tmp_pack->acc_next= data;
+		data= tmp_pack;
+		data_len += IP_MIN_HDR_SIZE;
+	}
+	if (data_len<IP_MIN_HDR_SIZE)
+	{
+		bf_afree(data);
+		return EPACKSIZE;
+	}
+
+	data= bf_packIffLess(data, IP_MIN_HDR_SIZE);
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
+	if (data->acc_linkC != 1 || data->acc_buffer->buf_linkC != 1)
+	{
+		tmp_pack= bf_memreq(IP_MIN_HDR_SIZE);
+		tmp_hdr= (ip_hdr_t *)ptr2acc_data(tmp_pack);
+		*tmp_hdr= *ip_hdr;
+		tmp_pack->acc_next= bf_cut(data, IP_MIN_HDR_SIZE,
+			data_len-IP_MIN_HDR_SIZE);
+		bf_afree(data);
+		ip_hdr= tmp_hdr;
+		data= tmp_pack;
+		assert (data->acc_length >= IP_MIN_HDR_SIZE);
+	}
+
+	if (ip_fd->if_ipopt.nwio_flags & NWIO_HDR_O_SPEC)
+	{
+		hdr_opt_len= ip_fd->if_ipopt.nwio_hdropt.iho_opt_siz;
+		if (hdr_opt_len)
+		{
+			tmp_pack= bf_cut(data, 0, IP_MIN_HDR_SIZE);
+			tmp_pack1= bf_cut (data, IP_MIN_HDR_SIZE,
+				data_len-IP_MIN_HDR_SIZE);
+			bf_afree(data);
+			data= bf_packIffLess(tmp_pack, IP_MIN_HDR_SIZE);
+			ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
+			tmp_pack= bf_memreq (hdr_opt_len);
+			memcpy (ptr2acc_data(tmp_pack), ip_fd->if_ipopt.
+				nwio_hdropt.iho_data, hdr_opt_len);
+			data->acc_next= tmp_pack;
+			tmp_pack->acc_next= tmp_pack1;
+			hdr_len= IP_MIN_HDR_SIZE+hdr_opt_len;
+		}
+		else
+			hdr_len= IP_MIN_HDR_SIZE;
+		ip_hdr->ih_vers_ihl= hdr_len/4;
+		ip_hdr->ih_tos= ip_fd->if_ipopt.nwio_tos;
+		ip_hdr->ih_flags_fragoff= 0;
+		if (ip_fd->if_ipopt.nwio_df)
+			ip_hdr->ih_flags_fragoff |= HTONS(IH_DONT_FRAG);
+		ip_hdr->ih_ttl= ip_fd->if_ipopt.nwio_ttl;
+		ttl= ORTD_UNREACHABLE+1;		/* Don't check TTL */
+	}
+	else
+	{
+		hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK)*4;
+		r= NW_OK;
+		if (hdr_len<IP_MIN_HDR_SIZE)
+			r= EINVAL;
+		else if (hdr_len>data_len)
+			r= EPACKSIZE;
+		else if (!ip_hdr->ih_ttl)
+			r= EINVAL;
+		if (r != NW_OK)
+		{
+			bf_afree(data);
+			return r;
+		}
+
+		data= bf_packIffLess(data, hdr_len);
+		ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
+		if (hdr_len != IP_MIN_HDR_SIZE)
+		{
+			r= ip_chk_hdropt((u8_t *)(ptr2acc_data(data) +
+				IP_MIN_HDR_SIZE),
+				hdr_len-IP_MIN_HDR_SIZE);
+			if (r != NW_OK)
+			{
+				bf_afree(data);
+				return r;
+			}
+		}
+		ttl= ip_hdr->ih_ttl;
+	}
+	
+	ip_hdr->ih_vers_ihl= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) |
+		(IP_VERSION << 4);
+	ip_hdr->ih_length= htons(data_len);
+	ip_hdr->ih_flags_fragoff &= ~HTONS(IH_FRAGOFF_MASK |
+		IH_FLAGS_UNUSED | IH_MORE_FRAGS);
+	if (ip_fd->if_ipopt.nwio_flags & NWIO_PROTOSPEC)
+		ip_hdr->ih_proto= ip_fd->if_ipopt.nwio_proto;
+	ip_hdr->ih_id= htons(ip_port->ip_frame_id++);
+	ip_hdr->ih_src= ip_fd->if_port->ip_ipaddr;
+	if (ip_fd->if_ipopt.nwio_flags & NWIO_REMSPEC)
+		ip_hdr->ih_dst= ip_fd->if_ipopt.nwio_rem;
+
+	netmask= ip_port->ip_subnetmask;
+	my_ipaddr= ip_port->ip_ipaddr;
+
+	dstaddr= ip_hdr->ih_dst;
+	hostrep_dst= ntohl(dstaddr);
+	r= 0;
+	if (hostrep_dst == (ipaddr_t)-1)
+		;	/* OK, local broadcast */
+	else if ((hostrep_dst & 0xe0000000l) == 0xe0000000l)
+		;	/* OK, Multicast */
+	else if ((hostrep_dst & 0xf0000000l) == 0xf0000000l)
+		r= EBADDEST;	/* Bad class */
+	else if ((dstaddr ^ my_ipaddr) & netmask)
+		;	/* OK, remote destination */
+	else if (!(dstaddr & ~netmask) &&
+		(ip_port->ip_flags & IPF_SUBNET_BCAST))
+	{
+		r= EBADDEST;	/* Zero host part */
+	}
+	if (r<0)
+	{
+		DIFBLOCK(1, r == EBADDEST,
+			printf("bad destination: ");
+			writeIpAddr(ip_hdr->ih_dst);
+			printf("\n"));
+		bf_afree(data);
+		return r;
+	}
+	ip_hdr_chksum(ip_hdr, hdr_len);
+
+	data= bf_packIffLess(data, IP_MIN_HDR_SIZE);
+	assert (data->acc_length >= IP_MIN_HDR_SIZE);
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
+
+	if (ip_hdr->ih_flags_fragoff & HTONS(IH_DONT_FRAG))
+	{
+		req_mtu= bf_bufsize(data);
+		if (req_mtu > ip_port->ip_mtu)
+		{
+			DBLOCK(1, printf(
+			"packet is larger than link MTU and DF is set\n"));
+			bf_afree(data);
+			return EPACKSIZE;
+		}
+	}
+	else
+		req_mtu= 0;
+
+	addrInBytes= (u8_t *)&dstaddr;
+
+	if ((addrInBytes[0] & 0xff) == 0x7f)	/* local loopback */
+	{
+		assert (data->acc_linkC == 1);
+		dstaddr= ip_hdr->ih_dst;	/* swap src and dst 
+						 * addresses */
+		ip_hdr->ih_dst= ip_hdr->ih_src;
+		ip_hdr->ih_src= dstaddr;
+		data->acc_ext_link= NULL;
+		if (ip_port->ip_loopb_head == NULL)
+		{
+			ip_port->ip_loopb_head= data;
+			arg.ev_ptr= ip_port;
+			ev_enqueue(&ip_port->ip_loopb_event,
+				ip_process_loopb, arg);
+		}
+		else
+			ip_port->ip_loopb_tail->acc_ext_link= data;
+		ip_port->ip_loopb_tail= data;
+
+		return NW_OK;
+	}
+
+	if ((dstaddr & HTONL(0xe0000000)) == HTONL(0xe0000000))
+	{
+		if (dstaddr == (ipaddr_t)-1)
+		{
+			r= (*ip_port->ip_dev_send)(ip_port, dstaddr, data,
+				IP_LT_BROADCAST);
+			return r;
+		}
+		if (ip_nettype(dstaddr) == IPNT_CLASS_D)
+		{
+			/* Multicast, what about multicast routing? */
+			r= (*ip_port->ip_dev_send)(ip_port, dstaddr, data,
+				IP_LT_MULTICAST);
+			return r;
+		}
+	}
+
+	if (dstaddr == my_ipaddr)
+	{
+		assert (data->acc_linkC == 1);
+
+		data->acc_ext_link= NULL;
+		if (ip_port->ip_loopb_head == NULL)
+		{
+			ip_port->ip_loopb_head= data;
+			arg.ev_ptr= ip_port;
+			ev_enqueue(&ip_port->ip_loopb_event,
+				ip_process_loopb, arg);
+		}
+		else
+			ip_port->ip_loopb_tail->acc_ext_link= data;
+		ip_port->ip_loopb_tail= data;
+
+		return NW_OK;
+	}
+
+	if (((dstaddr ^ my_ipaddr) & netmask) == 0)
+	{
+		type= ((dstaddr == (my_ipaddr | ~netmask) &&
+			(ip_port->ip_flags & IPF_SUBNET_BCAST)) ?
+			IP_LT_BROADCAST : IP_LT_NORMAL);
+
+		r= (*ip_port->ip_dev_send)(ip_port, dstaddr, data, type);
+		return r;
+	}
+
+	r= oroute_frag (ip_port - ip_port_table, dstaddr, ttl, req_mtu, 
+		&nexthop);
+
+	if (r == NW_OK)
+	{
+		if (nexthop == ip_port->ip_ipaddr)
+		{
+			data->acc_ext_link= NULL;
+			if (ip_port->ip_loopb_head == NULL)
+			{
+				ip_port->ip_loopb_head= data;
+				arg.ev_ptr= ip_port;
+				ev_enqueue(&ip_port->ip_loopb_event,
+					ip_process_loopb, arg);
+			}
+			else
+				ip_port->ip_loopb_tail->acc_ext_link= data;
+			ip_port->ip_loopb_tail= data;
+		}
+		else
+		{
+			r= (*ip_port->ip_dev_send)(ip_port,
+				nexthop, data, IP_LT_NORMAL);
+		}
+	}
+	else
+	{
+		DBLOCK(0x10, printf("got error %d\n", r));
+		bf_afree(data);
+	}
+	return r;
+}
+
+PUBLIC void ip_hdr_chksum(ip_hdr, ip_hdr_len)
+ip_hdr_t *ip_hdr;
+int ip_hdr_len;
+{
+	ip_hdr->ih_hdr_chk= 0;
+	ip_hdr->ih_hdr_chk= ~oneC_sum (0, (u16_t *)ip_hdr, ip_hdr_len);
+}
+
+PUBLIC acc_t *ip_split_pack (ip_port, ref_last, mtu)
+ip_port_t *ip_port;
+acc_t **ref_last;
+int mtu;
+{
+	int pack_siz;
+	ip_hdr_t *first_hdr, *second_hdr;
+	int first_hdr_len, second_hdr_len;
+	int first_data_len, second_data_len;
+	int data_len, max_data_len, nfrags, new_first_data_len;
+	int first_opt_size, second_opt_size;
+	acc_t *first_pack, *second_pack, *tmp_pack;
+	u8_t *first_optptr, *second_optptr;
+	int i, optlen;
+
+	first_pack= *ref_last;
+	*ref_last= 0;
+	second_pack= 0;
+
+	first_pack= bf_align(first_pack, IP_MIN_HDR_SIZE, 4);
+	first_pack= bf_packIffLess(first_pack, IP_MIN_HDR_SIZE);
+	assert (first_pack->acc_length >= IP_MIN_HDR_SIZE);
+
+	first_hdr= (ip_hdr_t *)ptr2acc_data(first_pack);
+	first_hdr_len= (first_hdr->ih_vers_ihl & IH_IHL_MASK) * 4;
+	if (first_hdr_len>IP_MIN_HDR_SIZE)
+	{
+		first_pack= bf_packIffLess(first_pack, first_hdr_len);
+		first_hdr= (ip_hdr_t *)ptr2acc_data(first_pack);
+	}
+
+	pack_siz= bf_bufsize(first_pack);
+	assert(pack_siz > mtu);
+
+	assert (!(first_hdr->ih_flags_fragoff & HTONS(IH_DONT_FRAG)));
+
+	if (first_pack->acc_linkC != 1 ||
+		first_pack->acc_buffer->buf_linkC != 1)
+	{
+		/* Get a private copy of the IP header */
+		tmp_pack= bf_memreq(first_hdr_len);
+		memcpy(ptr2acc_data(tmp_pack), first_hdr, first_hdr_len);
+		first_pack= bf_delhead(first_pack, first_hdr_len);
+		tmp_pack->acc_next= first_pack;
+		first_pack= tmp_pack; tmp_pack= NULL;
+		first_hdr= (ip_hdr_t *)ptr2acc_data(first_pack);
+	}
+
+	data_len= ntohs(first_hdr->ih_length) - first_hdr_len;
+
+	/* Try to split the packet evenly. */
+	assert(mtu > first_hdr_len);
+	max_data_len= mtu-first_hdr_len;
+	nfrags= (data_len/max_data_len)+1;
+	new_first_data_len= data_len/nfrags;
+	if (new_first_data_len < 8)
+	{
+		/* Special case for extremely small MTUs */
+		new_first_data_len= 8;
+	}
+	new_first_data_len &= ~7; /* data goes in 8 byte chuncks */
+
+	assert(new_first_data_len >= 8);
+	assert(new_first_data_len+first_hdr_len <= mtu);
+
+	second_data_len= data_len-new_first_data_len;
+	second_pack= bf_cut(first_pack, first_hdr_len+
+		new_first_data_len, second_data_len);
+	tmp_pack= first_pack;
+	first_data_len= new_first_data_len;
+	first_pack= bf_cut (tmp_pack, 0, first_hdr_len+first_data_len);
+	bf_afree(tmp_pack);
+	tmp_pack= bf_memreq(first_hdr_len);
+	tmp_pack->acc_next= second_pack;
+	second_pack= tmp_pack;
+	second_hdr= (ip_hdr_t *)ptr2acc_data(second_pack);
+	*second_hdr= *first_hdr;
+	second_hdr->ih_flags_fragoff= htons(
+		ntohs(first_hdr->ih_flags_fragoff)+(first_data_len/8));
+
+	first_opt_size= first_hdr_len-IP_MIN_HDR_SIZE;
+	second_opt_size= 0;
+	if (first_opt_size)
+	{
+		first_pack= bf_packIffLess (first_pack,
+			first_hdr_len);
+		first_hdr= (ip_hdr_t *)ptr2acc_data(first_pack);
+		assert (first_pack->acc_length>=first_hdr_len);
+		first_optptr= (u8_t *)ptr2acc_data(first_pack)+
+			IP_MIN_HDR_SIZE;
+		second_optptr= (u8_t *)ptr2acc_data(
+			second_pack)+IP_MIN_HDR_SIZE;
+		i= 0;
+		while (i<first_opt_size)
+		{
+			switch (*first_optptr & IP_OPT_NUMBER)
+			{
+			case 0:
+			case 1:
+				optlen= 1;
+				break;
+			default:
+				optlen= first_optptr[1];
+				break;
+			}
+			assert (i + optlen <= first_opt_size);
+			i += optlen;
+			if (*first_optptr & IP_OPT_COPIED)
+			{
+				second_opt_size += optlen;
+				while (optlen--)
+					*second_optptr++=
+						*first_optptr++;
+			}
+			else
+				first_optptr += optlen;
+		}
+		while (second_opt_size & 3)
+		{
+			*second_optptr++= 0;
+			second_opt_size++;
+		}
+	}
+	second_hdr_len= IP_MIN_HDR_SIZE + second_opt_size;
+
+	second_hdr->ih_vers_ihl= (second_hdr->ih_vers_ihl & 0xf0)
+		+ (second_hdr_len/4);
+	second_hdr->ih_length= htons(second_data_len+
+		second_hdr_len);
+	second_pack->acc_length= second_hdr_len;
+
+	assert(first_pack->acc_linkC == 1);
+	assert(first_pack->acc_buffer->buf_linkC == 1);
+
+	first_hdr->ih_flags_fragoff |= HTONS(IH_MORE_FRAGS);
+	first_hdr->ih_length= htons(first_data_len+
+		first_hdr_len);
+	assert (!(second_hdr->ih_flags_fragoff & HTONS(IH_DONT_FRAG)));
+
+	ip_hdr_chksum(first_hdr, first_hdr_len);
+	if (second_data_len+second_hdr_len <= mtu)
+	{
+		/* second_pack will not be split any further, so we have to
+		 * calculate the header checksum.
+		 */
+		ip_hdr_chksum(second_hdr, second_hdr_len);
+	}
+
+	*ref_last= second_pack;
+
+	return first_pack;
+}
+
+PRIVATE void error_reply (ip_fd, error)
+ip_fd_t *ip_fd;
+int error;
+{
+	if ((*ip_fd->if_get_userdata)(ip_fd->if_srfd, (size_t)error,
+		(size_t)0, FALSE))
+	{
+		ip_panic(( "can't error_reply" ));
+	}
+}
+
+/*
+ * $PchId: ip_write.c,v 1.22 2004/08/03 11:11:04 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/ipr.c
===================================================================
--- /trunk/minix/servers/inet/generic/ipr.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/ipr.c	(revision 9)
@@ -0,0 +1,1246 @@
+/*
+ipr.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "clock.h"
+
+#include "type.h"
+#include "assert.h"
+#include "buf.h"
+#include "event.h"
+#include "io.h"
+#include "ip_int.h"
+#include "ipr.h"
+
+THIS_FILE
+
+#define OROUTE_NR		128
+#define OROUTE_STATIC_NR	16
+#define OROUTE_HASH_ASS_NR	 4
+#define OROUTE_HASH_NR		32
+#define OROUTE_HASH_MASK	(OROUTE_HASH_NR-1)
+
+#define hash_oroute(port_nr, ipaddr, hash_tmp) (hash_tmp= (ipaddr), \
+	hash_tmp= (hash_tmp >> 20) ^ hash_tmp, \
+	hash_tmp= (hash_tmp >> 10) ^ hash_tmp, \
+	hash_tmp= (hash_tmp >> 5) ^ hash_tmp, \
+	(hash_tmp + (port_nr)) & OROUTE_HASH_MASK)
+
+typedef struct oroute_hash
+{
+	ipaddr_t orh_addr;
+	oroute_t *orh_route;
+} oroute_hash_t;
+
+PRIVATE oroute_t oroute_table[OROUTE_NR];
+PRIVATE oroute_t *oroute_head;
+PRIVATE int static_oroute_nr;
+PRIVATE oroute_hash_t oroute_hash_table[OROUTE_HASH_NR][OROUTE_HASH_ASS_NR];
+
+#define IROUTE_NR		512
+#define IROUTE_HASH_ASS_NR	 4
+#define IROUTE_HASH_NR		32
+#define IROUTE_HASH_MASK	(IROUTE_HASH_NR-1)
+
+#define hash_iroute(port_nr, ipaddr, hash_tmp) (hash_tmp= (ipaddr), \
+	hash_tmp= (hash_tmp >> 20) ^ hash_tmp, \
+	hash_tmp= (hash_tmp >> 10) ^ hash_tmp, \
+	hash_tmp= (hash_tmp >> 5) ^ hash_tmp, \
+	(hash_tmp + (port_nr)) & IROUTE_HASH_MASK)
+
+typedef struct iroute_hash
+{
+	ipaddr_t irh_addr;
+	iroute_t *irh_route;
+} iroute_hash_t;
+
+PRIVATE iroute_t iroute_table[IROUTE_NR];
+PRIVATE iroute_hash_t iroute_hash_table[IROUTE_HASH_NR][IROUTE_HASH_ASS_NR];
+
+FORWARD oroute_t *oroute_find_ent ARGS(( int port_nr, ipaddr_t dest ));
+FORWARD void oroute_del ARGS(( oroute_t *oroute ));
+FORWARD oroute_t *sort_dists ARGS(( oroute_t *oroute ));
+FORWARD oroute_t *sort_gws ARGS(( oroute_t *oroute ));
+FORWARD	void oroute_uncache_nw ARGS(( ipaddr_t dest, ipaddr_t netmask ));
+FORWARD	void iroute_uncache_nw ARGS(( ipaddr_t dest, ipaddr_t netmask ));
+
+PUBLIC void ipr_init()
+{
+	int i;
+	oroute_t *oroute;
+	iroute_t *iroute;
+
+	for (i= 0, oroute= oroute_table; i<OROUTE_NR; i++, oroute++)
+		oroute->ort_flags= ORTF_EMPTY;
+	static_oroute_nr= 0;
+	assert(OROUTE_HASH_ASS_NR == 4);
+
+	for (i= 0, iroute= iroute_table; i<IROUTE_NR; i++, iroute++)
+		iroute->irt_flags= IRTF_EMPTY;
+	assert(IROUTE_HASH_ASS_NR == 4);
+}
+
+
+PUBLIC iroute_t *iroute_frag(port_nr, dest)
+int port_nr;
+ipaddr_t dest;
+{
+	int hash, i;
+	iroute_hash_t *iroute_hash;
+	iroute_hash_t tmp_hash;
+	iroute_t *iroute, *bestroute;
+	unsigned long hash_tmp;
+	u32_t tmp_mask;
+
+	hash= hash_iroute(port_nr, dest, hash_tmp);
+	iroute_hash= &iroute_hash_table[hash][0];
+	if (iroute_hash[0].irh_addr == dest)
+		iroute= iroute_hash[0].irh_route;
+	else if (iroute_hash[1].irh_addr == dest)
+	{
+		tmp_hash= iroute_hash[1];
+		iroute_hash[1]= iroute_hash[0];
+		iroute_hash[0]= tmp_hash;
+		iroute= tmp_hash.irh_route;
+	}
+	else if (iroute_hash[2].irh_addr == dest)
+	{
+		tmp_hash= iroute_hash[2];
+		iroute_hash[2]= iroute_hash[1];
+		iroute_hash[1]= iroute_hash[0];
+		iroute_hash[0]= tmp_hash;
+		iroute= tmp_hash.irh_route;
+	}
+	else if (iroute_hash[3].irh_addr == dest)
+	{
+		tmp_hash= iroute_hash[3];
+		iroute_hash[3]= iroute_hash[2];
+		iroute_hash[2]= iroute_hash[1];
+		iroute_hash[1]= iroute_hash[0];
+		iroute_hash[0]= tmp_hash;
+		iroute= tmp_hash.irh_route;
+	}
+	else
+		iroute= NULL;
+	if (iroute)
+		return iroute;
+
+	bestroute= NULL;
+	for (i= 0, iroute= iroute_table; i < IROUTE_NR; i++, iroute++)
+	{
+		if (!(iroute->irt_flags & IRTF_INUSE))
+			continue;
+		if (((dest ^ iroute->irt_dest) & iroute->irt_subnetmask) != 0)
+			continue;
+		if (!bestroute)
+		{
+			bestroute= iroute;
+			continue;
+		}
+
+		/* More specific netmasks are better */
+		if (iroute->irt_subnetmask != bestroute->irt_subnetmask)
+		{
+			/* Using two ntohl macros in one expression
+			 * is not allowed (tmp_l is modified twice)
+			 */
+			tmp_mask= ntohl(iroute->irt_subnetmask);
+			if (tmp_mask > ntohl(bestroute->irt_subnetmask))
+				bestroute= iroute;
+			continue;
+		}
+			
+		/* Dynamic routes override static routes */
+		if ((iroute->irt_flags & IRTF_STATIC) != 
+			(bestroute->irt_flags & IRTF_STATIC))
+		{
+			if (bestroute->irt_flags & IRTF_STATIC)
+				bestroute= iroute;
+			continue;
+		}
+
+		/* A route to the local interface give an opportunity
+		 * to send redirects.
+		 */
+		if (iroute->irt_port != bestroute->irt_port)
+		{
+			if (iroute->irt_port == port_nr)
+				bestroute= iroute;
+			continue;
+		}
+	}
+	if (bestroute == NULL)
+		return NULL;
+
+	iroute_hash[3]= iroute_hash[2];
+	iroute_hash[2]= iroute_hash[1];
+	iroute_hash[1]= iroute_hash[0];
+	iroute_hash[0].irh_addr= dest;
+	iroute_hash[0].irh_route= bestroute;
+
+	return bestroute;
+}
+
+PUBLIC int oroute_frag(port_nr, dest, ttl, msgsize, nexthop)
+int port_nr;
+ipaddr_t dest;
+int ttl;
+size_t msgsize;
+ipaddr_t *nexthop;
+{
+	oroute_t *oroute;
+
+	oroute= oroute_find_ent(port_nr, dest);
+	if (!oroute || oroute->ort_dist > ttl)
+		return EDSTNOTRCH;
+	if (msgsize && oroute->ort_mtu && 
+		oroute->ort_mtu < msgsize)
+	{
+		return EPACKSIZE;
+	}
+
+	*nexthop= oroute->ort_gateway;
+	return NW_OK;
+}
+
+
+PUBLIC int ipr_add_oroute(port_nr, dest, subnetmask, gateway, 
+	timeout, dist, mtu, static_route, preference, oroute_p)
+int port_nr;
+ipaddr_t dest;
+ipaddr_t subnetmask;
+ipaddr_t gateway;
+time_t timeout;
+int dist;
+int mtu;
+int static_route;
+i32_t preference;
+oroute_t **oroute_p;
+{
+	int i;
+	ip_port_t *ip_port;
+	oroute_t *oroute, *oldest_route, *prev, *nw_route, *gw_route, 
+		*prev_route;
+	time_t currtim, exp_tim, exp_tim_orig;
+
+	oldest_route= 0;
+	currtim= get_time();
+	if (timeout)
+		exp_tim= timeout+currtim;
+	else
+		exp_tim= 0;
+
+	DBLOCK(0x10, 
+		printf("ip[%d]: adding oroute to ", port_nr);
+		writeIpAddr(dest);
+		printf("["); writeIpAddr(subnetmask); printf("] through ");
+		writeIpAddr(gateway);
+		printf(" timeout: %lds, distance %d, pref %ld, mtu %d\n",
+			(long)timeout/HZ, dist, (long)preference, mtu));
+
+	ip_port= &ip_port_table[port_nr];
+
+	/* Validate gateway */
+	if (((gateway ^ ip_port->ip_ipaddr) & ip_port->ip_subnetmask) != 0)
+	{
+		DBLOCK(1, printf("ip[%d]: (ipr_add_oroute) invalid gateway: ",
+			port_nr); writeIpAddr(gateway); printf("\n"));
+		return EINVAL;
+	}
+
+	if (static_route)
+	{
+		if (static_oroute_nr >= OROUTE_STATIC_NR)
+			return ENOMEM;
+		static_oroute_nr++;
+	}
+	else
+	{
+		/* Try to track down any old routes. */
+		for(oroute= oroute_head; oroute; oroute= oroute->ort_nextnw)
+		{
+			if (oroute->ort_port != port_nr)
+				continue;
+			if (oroute->ort_dest == dest &&
+				oroute->ort_subnetmask == subnetmask)
+			{
+				break;
+			}
+		}
+		for(; oroute; oroute= oroute->ort_nextgw)
+		{
+			if (oroute->ort_gateway == gateway)
+				break;
+		}
+		for(; oroute; oroute= oroute->ort_nextdist)
+		{
+			if ((oroute->ort_flags & ORTF_STATIC) != 0)
+				continue;
+			if (oroute->ort_dist > dist)
+				continue;
+			break;
+		}
+		if (oroute)
+		{
+			assert(oroute->ort_port == port_nr);
+			if (dest != 0)
+			{
+				/* The new expire should not be later
+				 * than the old expire time. Except for
+				 * default routes, where the expire time
+				 * is simple set to the new value.
+				 */
+				exp_tim_orig= oroute->ort_exp_tim;
+				if (!exp_tim)
+					exp_tim= exp_tim_orig;
+				else if (exp_tim_orig &&
+					exp_tim > exp_tim_orig)
+				{
+					exp_tim= exp_tim_orig;
+				}
+			}
+			oroute_del(oroute);
+			oroute->ort_flags= 0;
+			oldest_route= oroute;
+		}
+	}
+
+	if (oldest_route == NULL)
+	{
+		/* Look for an unused entry, or remove an existing one */
+		for (i= 0, oroute= oroute_table; i<OROUTE_NR; i++, oroute++)
+		{
+			if ((oroute->ort_flags & ORTF_INUSE) == 0)
+				break;
+			if (oroute->ort_exp_tim && oroute->ort_exp_tim < 
+				currtim)
+			{
+				oroute_del(oroute);
+				oroute->ort_flags= 0;
+				break;
+			}
+			if (oroute->ort_flags & ORTF_STATIC)
+				continue;
+			if (oroute->ort_dest == 0)
+			{
+				/* Never remove default routes. */
+				continue;
+			}
+			if (oldest_route == NULL)
+			{
+				oldest_route= oroute;
+				continue;
+			}
+			if (oroute->ort_timestamp < oldest_route->ort_timestamp)
+			{
+				oldest_route= oroute;
+			}
+		}
+		if (i < OROUTE_NR)
+			oldest_route= oroute;
+		else
+		{
+			assert(oldest_route);
+			oroute_del(oldest_route);
+			oldest_route->ort_flags= 0;
+		}
+	}
+
+	oldest_route->ort_dest= dest;
+	oldest_route->ort_gateway= gateway;
+	oldest_route->ort_subnetmask= subnetmask;
+	oldest_route->ort_exp_tim= exp_tim;
+	oldest_route->ort_timestamp= currtim;
+	oldest_route->ort_dist= dist;
+	oldest_route->ort_mtu= mtu;
+	oldest_route->ort_port= port_nr;
+	oldest_route->ort_flags= ORTF_INUSE;
+	oldest_route->ort_pref= preference;
+	if (static_route)
+		oldest_route->ort_flags |= ORTF_STATIC;
+	
+	/* Insert the route by tearing apart the routing table, 
+	 * and insert the entry during the reconstruction.
+	 */
+	for (prev= 0, nw_route= oroute_head; nw_route; 
+		prev= nw_route, nw_route= nw_route->ort_nextnw)
+	{
+		if (nw_route->ort_port != port_nr)
+			continue;
+		if (nw_route->ort_dest == dest &&
+			nw_route->ort_subnetmask == subnetmask)
+		{
+			if (prev)
+				prev->ort_nextnw= nw_route->ort_nextnw;
+			else
+				oroute_head= nw_route->ort_nextnw;
+			break;
+		}
+	}
+	prev_route= nw_route;
+	for(prev= NULL, gw_route= nw_route; gw_route; 
+		prev= gw_route, gw_route= gw_route->ort_nextgw)
+	{
+		if (gw_route->ort_gateway == gateway)
+		{
+			if (prev)
+				prev->ort_nextgw= gw_route->ort_nextgw;
+			else
+				nw_route= gw_route->ort_nextgw;
+			break;
+		}
+	}
+	oldest_route->ort_nextdist= gw_route;
+	gw_route= oldest_route;
+	gw_route= sort_dists(gw_route);
+	gw_route->ort_nextgw= nw_route;
+	nw_route= gw_route;
+	nw_route= sort_gws(nw_route);
+	nw_route->ort_nextnw= oroute_head;
+	oroute_head= nw_route;
+	if (nw_route != prev_route)
+		oroute_uncache_nw(nw_route->ort_dest, nw_route->ort_subnetmask);
+	if (oroute_p != NULL)
+		*oroute_p= oldest_route;
+	return NW_OK;
+}
+
+PUBLIC int ipr_del_oroute(port_nr, dest, subnetmask, gateway, static_route)
+int port_nr;
+ipaddr_t dest;
+ipaddr_t subnetmask;
+ipaddr_t gateway;
+int static_route;
+{
+	int i;
+	oroute_t *oroute;
+
+	for(i= 0, oroute= oroute_table; i<OROUTE_NR; i++, oroute++)
+	{
+		if ((oroute->ort_flags & ORTF_INUSE) == 0)
+			continue;
+		if (oroute->ort_port != port_nr ||
+			oroute->ort_dest != dest ||
+			oroute->ort_subnetmask != subnetmask ||
+			oroute->ort_gateway != gateway)
+		{
+			continue;
+		}
+		if (!!(oroute->ort_flags & ORTF_STATIC) != static_route)
+			continue;
+		break;
+	}
+
+	if (i == OROUTE_NR)
+		return ESRCH;
+
+	if (static_route)
+		static_oroute_nr--;
+
+	oroute_del(oroute);
+	oroute->ort_flags &= ~ORTF_INUSE;
+	return NW_OK;
+}
+
+
+
+PUBLIC void ipr_chk_otab(port_nr, addr, mask)
+int port_nr;
+ipaddr_t addr;
+ipaddr_t mask;
+{
+	int i;
+	oroute_t *oroute;
+
+	DBLOCK(1,
+		printf("ip[%d] (ipr_chk_otab): addr ", port_nr);
+		writeIpAddr(addr);
+		printf(" mask ");
+		writeIpAddr(mask);
+		printf("\n");
+	);
+
+	if (addr == 0)
+	{
+		/* Special hack to flush entries for an interface that
+		 * goes down.
+		 */
+		addr= mask= HTONL(0xffffffff);
+	}
+
+	for(i= 0, oroute= oroute_table; i<OROUTE_NR; i++, oroute++)
+	{
+		if ((oroute->ort_flags & ORTF_INUSE) == 0)
+			continue;
+		if (oroute->ort_port != port_nr ||
+			((oroute->ort_gateway ^ addr) & mask) == 0)
+		{
+			continue;
+		}
+		DBLOCK(1, printf("ip[%d] (ipr_chk_otab): deleting route to ",
+				port_nr);
+			writeIpAddr(oroute->ort_dest);
+			printf(" gw ");
+			writeIpAddr(oroute->ort_gateway);
+			printf("\n"));
+
+		if (oroute->ort_flags & ORTF_STATIC)
+			static_oroute_nr--;
+		oroute_del(oroute);
+		oroute->ort_flags &= ~ORTF_INUSE;
+	}
+}
+
+
+PUBLIC void ipr_gateway_down(port_nr, gateway, timeout)
+int port_nr;
+ipaddr_t gateway;
+time_t timeout;
+{
+	oroute_t *route_ind;
+	time_t currtim;
+	int i;
+	int result;
+
+	currtim= get_time();
+	for (i= 0, route_ind= oroute_table; i<OROUTE_NR; i++, route_ind++)
+	{
+		if (!(route_ind->ort_flags & ORTF_INUSE))
+			continue;
+		if (route_ind->ort_gateway != gateway)
+			continue;
+		if (route_ind->ort_exp_tim && route_ind->ort_exp_tim < currtim)
+			continue;
+		result= ipr_add_oroute(port_nr, route_ind->ort_dest, 
+			route_ind->ort_subnetmask, gateway, 
+			timeout, ORTD_UNREACHABLE, route_ind->ort_mtu,
+			FALSE, 0, NULL);
+		assert(result == NW_OK);
+	}
+}
+
+
+PUBLIC void ipr_destunrch(port_nr, dest, netmask, timeout)
+int port_nr;
+ipaddr_t dest;
+ipaddr_t netmask;
+time_t timeout;
+{
+	oroute_t *oroute;
+	int result;
+
+	oroute= oroute_find_ent(port_nr, dest);
+
+	if (!oroute)
+	{
+		DBLOCK(1, printf("ip[%d]: got a dest unreachable for ",
+			port_nr);
+			writeIpAddr(dest); printf("but no route present\n"));
+
+		return;
+	}
+	result= ipr_add_oroute(port_nr, dest, netmask, oroute->ort_gateway, 
+		timeout, ORTD_UNREACHABLE, oroute->ort_mtu, FALSE, 0, NULL);
+	assert(result == NW_OK);
+}
+
+
+PUBLIC void ipr_redirect(port_nr, dest, netmask, old_gateway, new_gateway, 
+	timeout)
+int port_nr;
+ipaddr_t dest;
+ipaddr_t netmask;
+ipaddr_t old_gateway;
+ipaddr_t new_gateway;
+time_t timeout;
+{
+	oroute_t *oroute;
+	ip_port_t *ip_port;
+	int result;
+
+	ip_port= &ip_port_table[port_nr];
+	oroute= oroute_find_ent(port_nr, dest);
+
+	if (!oroute)
+	{
+		DBLOCK(1, printf("ip[%d]: got a redirect for ", port_nr);
+			writeIpAddr(dest); printf("but no route present\n"));
+		return;
+	}
+	if (oroute->ort_gateway != old_gateway)
+	{
+		DBLOCK(1, printf("ip[%d]: got a redirect from ", port_nr);
+			writeIpAddr(old_gateway); printf(" for ");
+			writeIpAddr(dest); printf(" but curr gateway is ");
+			writeIpAddr(oroute->ort_gateway); printf("\n"));
+		return;
+	}
+	if ((new_gateway ^ ip_port->ip_ipaddr) & ip_port->ip_subnetmask)
+	{
+		DBLOCK(1, printf("ip[%d]: redirect from ", port_nr);
+			writeIpAddr(old_gateway); printf(" for ");
+			writeIpAddr(dest); printf(" but new gateway ");
+			writeIpAddr(new_gateway);
+			printf(" is not on local subnet\n"));
+		return;
+	}
+	if (oroute->ort_flags & ORTF_STATIC)
+	{
+		if (oroute->ort_dest == dest)
+		{
+			DBLOCK(1, printf("ip[%d]: got a redirect for ",
+				port_nr);
+				writeIpAddr(dest);
+				printf("but route is fixed\n"));
+			return;
+		}
+	}
+	else
+	{
+		result= ipr_add_oroute(port_nr, dest, netmask, 
+			oroute->ort_gateway, HZ, ORTD_UNREACHABLE, 
+			oroute->ort_mtu, FALSE, 0, NULL);
+		assert(result == NW_OK);
+	}
+	result= ipr_add_oroute(port_nr, dest, netmask, new_gateway,
+		timeout, 1, oroute->ort_mtu, FALSE, 0, NULL);
+	assert(result == NW_OK);
+}
+
+
+PUBLIC void ipr_ttl_exc(port_nr, dest, netmask, timeout)
+int port_nr;
+ipaddr_t dest;
+ipaddr_t netmask;
+time_t timeout;
+{
+	oroute_t *oroute;
+	int new_dist;
+	int result;
+
+	oroute= oroute_find_ent(port_nr, dest);
+
+	if (!oroute)
+	{
+		DBLOCK(1, printf("ip[%d]: got a ttl exceeded for ",
+			port_nr);
+			writeIpAddr(dest); printf("but no route present\n"));
+		return;
+	}
+
+	new_dist= oroute->ort_dist * 2;
+	if (new_dist > IP_DEF_TTL)
+	{
+		new_dist= oroute->ort_dist+1;
+		if (new_dist >= IP_DEF_TTL)
+		{
+			DBLOCK(1, printf("ip[%d]: got a ttl exceeded for ",
+				port_nr);
+				writeIpAddr(dest);
+				printf(" but dist is %d\n",
+				oroute->ort_dist));
+			return;
+		}
+	}
+
+	result= ipr_add_oroute(port_nr, dest, netmask, oroute->ort_gateway, 
+		timeout, new_dist, oroute->ort_mtu, FALSE, 0, NULL);
+	assert(result == NW_OK);
+}
+
+PUBLIC void ipr_mtu(port_nr, dest, mtu, timeout)
+int port_nr;
+ipaddr_t dest;
+u16_t mtu;
+time_t timeout;
+{
+	oroute_t *oroute;
+	int result;
+
+	oroute= oroute_find_ent(port_nr, dest);
+
+	if (!oroute)
+	{
+		DBLOCK(1, printf("ip[%d]: got a mtu exceeded for ",
+			port_nr);
+			writeIpAddr(dest); printf("but no route present\n"));
+		return;
+	}
+
+	if (mtu <  IP_MIN_MTU)
+		return;
+	if (oroute->ort_mtu && mtu >= oroute->ort_mtu)
+		return;		/* Only decrease mtu */
+
+	result= ipr_add_oroute(port_nr, dest, HTONL(0xffffffff),
+		oroute->ort_gateway, timeout, oroute->ort_dist, mtu,
+		FALSE, 0, NULL);
+	assert(result == NW_OK);
+}
+
+
+PUBLIC int ipr_get_oroute(ent_no, route_ent)
+int ent_no;
+nwio_route_t *route_ent;
+{
+	oroute_t *oroute;
+
+	if (ent_no<0 || ent_no>= OROUTE_NR)
+		return ENOENT;
+
+	oroute= &oroute_table[ent_no];
+	if ((oroute->ort_flags & ORTF_INUSE) && oroute->ort_exp_tim &&
+					oroute->ort_exp_tim < get_time())
+	{
+		oroute_del(oroute);
+		oroute->ort_flags &= ~ORTF_INUSE;
+	}
+
+	route_ent->nwr_ent_no= ent_no;
+	route_ent->nwr_ent_count= OROUTE_NR;
+	route_ent->nwr_dest= oroute->ort_dest;
+	route_ent->nwr_netmask= oroute->ort_subnetmask;
+	route_ent->nwr_gateway= oroute->ort_gateway;
+	route_ent->nwr_dist= oroute->ort_dist;
+	route_ent->nwr_flags= NWRF_EMPTY;
+	if (oroute->ort_flags & ORTF_INUSE)
+	{
+		route_ent->nwr_flags |= NWRF_INUSE;
+		if (oroute->ort_flags & ORTF_STATIC)
+			route_ent->nwr_flags |= NWRF_STATIC;
+	}
+	route_ent->nwr_pref= oroute->ort_pref;
+	route_ent->nwr_mtu= oroute->ort_mtu;
+	route_ent->nwr_ifaddr= ip_get_ifaddr(oroute->ort_port);
+	return NW_OK;
+}
+
+
+PRIVATE oroute_t *oroute_find_ent(port_nr, dest)
+int port_nr;
+ipaddr_t dest;
+{
+	int hash;
+	oroute_hash_t *oroute_hash;
+	oroute_hash_t tmp_hash;
+	oroute_t *oroute, *bestroute;
+	time_t currtim;
+	unsigned long hash_tmp;
+	u32_t tmp_mask;
+
+	currtim= get_time();
+
+	hash= hash_oroute(port_nr, dest, hash_tmp);
+	oroute_hash= &oroute_hash_table[hash][0];
+	if (oroute_hash[0].orh_addr == dest)
+		oroute= oroute_hash[0].orh_route;
+	else if (oroute_hash[1].orh_addr == dest)
+	{
+		tmp_hash= oroute_hash[1];
+		oroute_hash[1]= oroute_hash[0];
+		oroute_hash[0]= tmp_hash;
+		oroute= tmp_hash.orh_route;
+	}
+	else if (oroute_hash[2].orh_addr == dest)
+	{
+		tmp_hash= oroute_hash[2];
+		oroute_hash[2]= oroute_hash[1];
+		oroute_hash[1]= oroute_hash[0];
+		oroute_hash[0]= tmp_hash;
+		oroute= tmp_hash.orh_route;
+	}
+	else if (oroute_hash[3].orh_addr == dest)
+	{
+		tmp_hash= oroute_hash[3];
+		oroute_hash[3]= oroute_hash[2];
+		oroute_hash[2]= oroute_hash[1];
+		oroute_hash[1]= oroute_hash[0];
+		oroute_hash[0]= tmp_hash;
+		oroute= tmp_hash.orh_route;
+	}
+	else
+		oroute= NULL;
+	if (oroute)
+	{
+		assert(oroute->ort_port == port_nr);
+		if (oroute->ort_exp_tim && oroute->ort_exp_tim<currtim)
+		{
+			oroute_del(oroute);
+			oroute->ort_flags &= ~ORTF_INUSE;
+		}
+		else
+			return oroute;
+	}
+
+	bestroute= NULL;
+	for (oroute= oroute_head; oroute; oroute= oroute->ort_nextnw)
+	{
+		if (((dest ^ oroute->ort_dest) & oroute->ort_subnetmask) != 0)
+			continue;
+		if (oroute->ort_port != port_nr)
+			continue;
+		if (!bestroute)
+		{
+			bestroute= oroute;
+			continue;
+		}
+		assert(oroute->ort_dest != bestroute->ort_dest);
+		/* Using two ntohl macros in one expression
+		 * is not allowed (tmp_l is modified twice)
+		 */
+		tmp_mask= ntohl(oroute->ort_subnetmask);
+		if (tmp_mask > ntohl(bestroute->ort_subnetmask))
+		{
+			bestroute= oroute;
+			continue;
+		}
+	}
+	if (bestroute == NULL)
+		return NULL;
+
+	oroute_hash[3]= oroute_hash[2];
+	oroute_hash[2]= oroute_hash[1];
+	oroute_hash[1]= oroute_hash[0];
+	oroute_hash[0].orh_addr= dest;
+	oroute_hash[0].orh_route= bestroute;
+
+	return bestroute;
+}
+
+
+PRIVATE void oroute_del(oroute)
+oroute_t *oroute;
+{
+	oroute_t *prev, *nw_route, *gw_route, *dist_route, *prev_route;
+
+	DBLOCK(0x10, 
+		printf("ip[%d]: deleting oroute to ", oroute->ort_port);
+		writeIpAddr(oroute->ort_dest);
+		printf("["); writeIpAddr(oroute->ort_subnetmask);
+		printf("] through ");
+		writeIpAddr(oroute->ort_gateway);
+		printf(
+	" timestamp %lds, timeout: %lds, distance %d pref %ld mtu %ld ",
+			(long)oroute->ort_timestamp/HZ,
+			(long)oroute->ort_exp_tim/HZ, oroute->ort_dist,
+			(long)oroute->ort_pref, (long)oroute->ort_mtu);
+		printf("flags 0x%x\n", oroute->ort_flags));
+
+	for (prev= NULL, nw_route= oroute_head; nw_route; 
+				prev= nw_route, nw_route= nw_route->ort_nextnw)
+	{
+		if (oroute->ort_port == nw_route->ort_port &&
+			oroute->ort_dest == nw_route->ort_dest &&
+			oroute->ort_subnetmask == nw_route->ort_subnetmask)
+		{
+			break;
+		}
+	}
+	assert(nw_route);
+	if (prev)
+		prev->ort_nextnw= nw_route->ort_nextnw;
+	else
+		oroute_head= nw_route->ort_nextnw;
+	prev_route= nw_route;
+	for (prev= NULL, gw_route= nw_route; gw_route; 
+				prev= gw_route, gw_route= gw_route->ort_nextgw)
+	{
+		if (oroute->ort_gateway == gw_route->ort_gateway)
+			break;
+	}
+	assert(gw_route);
+	if (prev)
+		prev->ort_nextgw= gw_route->ort_nextgw;
+	else
+		nw_route= gw_route->ort_nextgw;
+	for (prev= NULL, dist_route= gw_route; dist_route; 
+			prev= dist_route, dist_route= dist_route->ort_nextdist)
+	{
+		if (oroute == dist_route)
+			break;
+	}
+	assert(dist_route);
+	if (prev)
+		prev->ort_nextdist= dist_route->ort_nextdist;
+	else
+		gw_route= dist_route->ort_nextdist;
+	gw_route= sort_dists(gw_route);
+	if (gw_route != NULL)
+	{
+		gw_route->ort_nextgw= nw_route;
+		nw_route= gw_route;
+	}
+	nw_route= sort_gws(nw_route);
+	if (nw_route != NULL)
+	{
+		nw_route->ort_nextnw= oroute_head;
+		oroute_head= nw_route;
+	}
+	if (nw_route != prev_route)
+	{
+		oroute_uncache_nw(prev_route->ort_dest, 
+			prev_route->ort_subnetmask);
+	}
+}
+
+
+PRIVATE oroute_t *sort_dists(oroute)
+oroute_t *oroute;
+{
+	oroute_t *r, *prev, *best, *best_prev;
+	int best_dist, best_pref;
+
+	best= NULL;
+	best_dist= best_pref= 0;
+	best_prev= NULL;
+	for (prev= NULL, r= oroute; r; prev= r, r= r->ort_nextdist)
+	{
+		if (best == NULL)
+			;	/* Force assignment to best */
+		else if (r->ort_dist != best_dist)
+		{
+			if (r->ort_dist > best_dist)
+				continue;
+		}
+		else
+		{
+			if (r->ort_pref <= best_pref)
+				continue;
+		}
+		best= r;
+		best_prev= prev;
+		best_dist= r->ort_dist;
+		best_pref= r->ort_pref;
+	}
+	if (!best)
+	{
+		assert(oroute == NULL);
+		return oroute;
+	}
+	if (!best_prev)
+	{
+		assert(best == oroute);
+		return oroute;
+	}
+	best_prev->ort_nextdist= best->ort_nextdist;
+	best->ort_nextdist= oroute;
+	return best;
+}
+
+
+PRIVATE oroute_t *sort_gws(oroute)
+oroute_t *oroute;
+{
+	oroute_t *r, *prev, *best, *best_prev;
+	int best_dist, best_pref;
+
+	best= NULL;
+	best_dist= best_pref= 0;
+	best_prev= NULL;
+	for (prev= NULL, r= oroute; r; prev= r, r= r->ort_nextgw)
+	{
+		if (best == NULL)
+			;	/* Force assignment to best */
+		else if (r->ort_dist != best_dist)
+		{
+			if (r->ort_dist > best_dist)
+				continue;
+		}
+		else
+		{
+			if (r->ort_pref <= best_pref)
+				continue;
+		}
+		best= r;
+		best_prev= prev;
+		best_dist= r->ort_dist;
+		best_pref= r->ort_pref;
+	}
+	if (!best)
+	{
+		assert(oroute == NULL);
+		return oroute;
+	}
+	if (!best_prev)
+	{
+		assert(best == oroute);
+		return oroute;
+	}
+	best_prev->ort_nextgw= best->ort_nextgw;
+	best->ort_nextgw= oroute;
+	return best;
+}
+
+
+PRIVATE	void oroute_uncache_nw(dest, netmask)
+ipaddr_t dest;
+ipaddr_t netmask;
+{
+	int i, j;
+	oroute_hash_t *oroute_hash;
+
+	for (i= 0, oroute_hash= &oroute_hash_table[0][0];
+		i<OROUTE_HASH_NR; i++, oroute_hash += OROUTE_HASH_ASS_NR)
+	{
+		for (j= 0; j<OROUTE_HASH_ASS_NR; j++)
+		{
+			if (((oroute_hash[j].orh_addr ^ dest) & netmask) == 0)
+			{
+				oroute_hash[j].orh_addr= 0;
+				oroute_hash[j].orh_route= NULL;
+			}
+		}
+	}
+}
+
+
+/*
+ * Input routing
+ */
+
+PUBLIC int ipr_get_iroute(ent_no, route_ent)
+int ent_no;
+nwio_route_t *route_ent;
+{
+	iroute_t *iroute;
+
+	if (ent_no<0 || ent_no>= IROUTE_NR)
+		return ENOENT;
+
+	iroute= &iroute_table[ent_no];
+
+	route_ent->nwr_ent_no= ent_no;
+	route_ent->nwr_ent_count= IROUTE_NR;
+	route_ent->nwr_dest= iroute->irt_dest;
+	route_ent->nwr_netmask= iroute->irt_subnetmask;
+	route_ent->nwr_gateway= iroute->irt_gateway;
+	route_ent->nwr_dist= iroute->irt_dist;
+	route_ent->nwr_flags= NWRF_EMPTY;
+	if (iroute->irt_flags & IRTF_INUSE)
+	{
+		route_ent->nwr_flags |= NWRF_INUSE;
+		if (iroute->irt_flags & IRTF_STATIC)
+			route_ent->nwr_flags |= NWRF_STATIC;
+		if (iroute->irt_dist == IRTD_UNREACHABLE)
+			route_ent->nwr_flags |= NWRF_UNREACHABLE;
+	}
+	route_ent->nwr_pref= 0;
+	route_ent->nwr_mtu= iroute->irt_mtu;
+	route_ent->nwr_ifaddr= ip_get_ifaddr(iroute->irt_port);
+	return NW_OK;
+}
+
+
+PUBLIC int ipr_add_iroute(port_nr, dest, subnetmask, gateway, 
+	dist, mtu, static_route, iroute_p)
+int port_nr;
+ipaddr_t dest;
+ipaddr_t subnetmask;
+ipaddr_t gateway;
+int dist;
+int mtu;
+int static_route;
+iroute_t **iroute_p;
+{
+	int i;
+	iroute_t *iroute, *unused_route;
+	ip_port_t *ip_port;
+
+	ip_port= &ip_port_table[port_nr];
+
+	/* Check gateway */
+	if (((gateway ^ ip_port->ip_ipaddr) & ip_port->ip_subnetmask) != 0 &&
+		gateway != 0)
+	{
+		DBLOCK(1, printf("ip[%d] (ipr_add_iroute): invalid gateway: ",
+			port_nr);
+			writeIpAddr(gateway); printf("\n"));
+		return EINVAL;
+	}
+
+	unused_route= NULL;
+	if (static_route)
+	{
+		/* Static routes are not reused automatically, so we look 
+		 * for an unused entry.
+		 */
+		for(i= 0, iroute= iroute_table; i<IROUTE_NR; i++, iroute++)
+		{
+			if ((iroute->irt_flags & IRTF_INUSE) == 0)
+				break;
+		}
+		if (i != IROUTE_NR)
+			unused_route= iroute;
+	}
+	else
+	{
+		/* Try to track down any old routes, and look for an
+		 * unused one.
+		 */
+		for(i= 0, iroute= iroute_table; i<IROUTE_NR; i++, iroute++)
+		{
+			if ((iroute->irt_flags & IRTF_INUSE) == 0)
+			{
+				unused_route= iroute;
+				continue;
+			}
+			if ((iroute->irt_flags & IRTF_STATIC) != 0)
+				continue;
+			if (iroute->irt_port != port_nr ||
+				iroute->irt_dest != dest ||
+				iroute->irt_subnetmask != subnetmask ||
+				iroute->irt_gateway != gateway)
+			{
+				continue;
+			}
+			break;
+		}
+		if (i != IROUTE_NR)
+			unused_route= iroute;
+	}
+
+	if (unused_route == NULL)
+		return ENOMEM;
+	iroute= unused_route;
+
+	iroute->irt_port= port_nr;
+	iroute->irt_dest= dest;
+	iroute->irt_subnetmask= subnetmask;
+	iroute->irt_gateway= gateway;
+	iroute->irt_dist= dist;
+	iroute->irt_mtu= mtu;
+	iroute->irt_flags= IRTF_INUSE;
+	if (static_route)
+		iroute->irt_flags |= IRTF_STATIC;
+	
+	iroute_uncache_nw(iroute->irt_dest, iroute->irt_subnetmask);
+	if (iroute_p != NULL)
+		*iroute_p= iroute;
+	return NW_OK;
+}
+
+
+PUBLIC int ipr_del_iroute(port_nr, dest, subnetmask, gateway, static_route)
+int port_nr;
+ipaddr_t dest;
+ipaddr_t subnetmask;
+ipaddr_t gateway;
+int static_route;
+{
+	int i;
+	iroute_t *iroute;
+
+	/* Try to track down any old routes, and look for an
+	 * unused one.
+	 */
+	for(i= 0, iroute= iroute_table; i<IROUTE_NR; i++, iroute++)
+	{
+		if ((iroute->irt_flags & IRTF_INUSE) == 0)
+			continue;
+		if (iroute->irt_port != port_nr ||
+			iroute->irt_dest != dest ||
+			iroute->irt_subnetmask != subnetmask ||
+			iroute->irt_gateway != gateway)
+		{
+			continue;
+		}
+		if (!!(iroute->irt_flags & IRTF_STATIC) != static_route)
+			continue;
+		break;
+	}
+
+	if (i == IROUTE_NR)
+		return ESRCH;
+
+	iroute_uncache_nw(iroute->irt_dest, iroute->irt_subnetmask);
+	iroute->irt_flags= IRTF_EMPTY;
+	return NW_OK;
+}
+
+
+PUBLIC void ipr_chk_itab(port_nr, addr, mask)
+int port_nr;
+ipaddr_t addr;
+ipaddr_t mask;
+{
+	int i;
+	iroute_t *iroute;
+
+	DBLOCK(1,
+		printf("ip[%d] (ipr_chk_itab): addr ", port_nr);
+		writeIpAddr(addr);
+		printf(" mask ");
+		writeIpAddr(mask);
+		printf("\n");
+	);
+
+	if (addr == 0)
+	{
+		/* Special hack to flush entries for an interface that
+		 * goes down.
+		 */
+		addr= mask= HTONL(0xffffffff);
+	}
+
+	for(i= 0, iroute= iroute_table; i<IROUTE_NR; i++, iroute++)
+	{
+		if ((iroute->irt_flags & IRTF_INUSE) == 0)
+			continue;
+		if (iroute->irt_port != port_nr)
+			continue;
+		if (iroute->irt_gateway == 0)
+		{
+			/* Special case: attached network. */
+			if (iroute->irt_subnetmask == mask &&
+				iroute->irt_dest == (addr & mask))
+			{
+				/* Nothing changed. */
+				continue;
+			}
+		}
+		if (((iroute->irt_gateway ^ addr) & mask) == 0)
+			continue;
+
+		DBLOCK(1, printf("ip[%d] (ipr_chk_itab): deleting route to ",
+				port_nr);
+		    writeIpAddr(iroute->irt_dest);
+		    printf(" gw ");
+		    writeIpAddr(iroute->irt_gateway);
+		    printf("\n"));
+
+		iroute_uncache_nw(iroute->irt_dest, iroute->irt_subnetmask);
+		iroute->irt_flags &= ~IRTF_INUSE;
+	}
+}
+
+
+PRIVATE	void iroute_uncache_nw(dest, netmask)
+ipaddr_t dest;
+ipaddr_t netmask;
+{
+	int i, j;
+	iroute_hash_t *iroute_hash;
+
+	for (i= 0, iroute_hash= &iroute_hash_table[0][0];
+		i<IROUTE_HASH_NR; i++, iroute_hash += IROUTE_HASH_ASS_NR)
+	{
+		for (j= 0; j<IROUTE_HASH_ASS_NR; j++)
+		{
+			if (((iroute_hash[j].irh_addr ^ dest) &
+				netmask) == 0)
+			{
+				iroute_hash[j].irh_addr= 0;
+				iroute_hash[j].irh_route= NULL;
+			}
+		}
+	}
+}
+
+
+
+/*
+ * $PchId: ipr.c,v 1.23 2003/01/22 11:49:58 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/ipr.h
===================================================================
--- /trunk/minix/servers/inet/generic/ipr.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/ipr.h	(revision 9)
@@ -0,0 +1,90 @@
+/*
+ipr.h
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef IPR_H
+#define IPR_H
+
+typedef struct oroute
+{
+	int ort_port;
+	ipaddr_t ort_dest;
+	ipaddr_t ort_subnetmask;
+	int ort_dist;
+	i32_t ort_pref;
+	u32_t ort_mtu;
+	ipaddr_t ort_gateway;
+	time_t ort_exp_tim;
+	time_t ort_timestamp;
+	int ort_flags;
+
+	struct oroute *ort_nextnw;
+	struct oroute *ort_nextgw;
+	struct oroute *ort_nextdist;
+} oroute_t;
+
+#define ORTD_UNREACHABLE	512
+
+#define ORTF_EMPTY		0
+#define ORTF_INUSE		1
+#define ORTF_STATIC		2
+
+typedef struct iroute
+{
+	ipaddr_t irt_dest;
+	ipaddr_t irt_gateway;
+	ipaddr_t irt_subnetmask;
+	int irt_dist;
+	u32_t irt_mtu;
+	int irt_port;
+	int irt_flags;
+} iroute_t;
+
+#define IRTD_UNREACHABLE	512
+
+#define IRTF_EMPTY		0
+#define IRTF_INUSE		1
+#define IRTF_STATIC		2
+
+#define IPR_UNRCH_TIMEOUT	(60L * HZ)
+#define IPR_TTL_TIMEOUT		(60L * HZ)
+#define IPR_REDIRECT_TIMEOUT	(20 * 60L * HZ)
+#define IPR_GW_DOWN_TIMEOUT	(60L * HZ)
+#define IPR_MTU_TIMEOUT		(10*60L * HZ)	/* RFC-1191 */
+
+/* Prototypes */
+
+iroute_t *iroute_frag ARGS(( int port_nr, ipaddr_t dest ));
+int oroute_frag ARGS(( int port_nr, ipaddr_t dest, int ttl, size_t msgsize,
+							ipaddr_t *nexthop ));
+void ipr_init ARGS(( void ));
+int ipr_get_iroute ARGS(( int ent_no, nwio_route_t *route_ent ));
+int ipr_add_iroute ARGS(( int port_nr, ipaddr_t dest, ipaddr_t subnetmask, 
+	ipaddr_t gateway, int dist, int mtu, int static_route,
+	iroute_t **route_p ));
+int ipr_del_iroute ARGS(( int port_nr, ipaddr_t dest, ipaddr_t subnetmask, 
+	ipaddr_t gateway, int static_route ));
+void ipr_chk_itab ARGS(( int port_nr, ipaddr_t addr, ipaddr_t mask ));
+int ipr_get_oroute ARGS(( int ent_no, nwio_route_t *route_ent ));
+int ipr_add_oroute ARGS(( int port_nr, ipaddr_t dest, ipaddr_t subnetmask, 
+	ipaddr_t gateway, time_t timeout, int dist, int mtu, int static_route,
+	i32_t preference, oroute_t **route_p ));
+int ipr_del_oroute ARGS(( int port_nr, ipaddr_t dest, ipaddr_t subnetmask, 
+	ipaddr_t gateway, int static_route ));
+void ipr_chk_otab ARGS(( int port_nr, ipaddr_t addr, ipaddr_t mask ));
+void ipr_gateway_down ARGS(( int port_nr, ipaddr_t gateway, time_t timeout ));
+void ipr_redirect ARGS(( int port_nr, ipaddr_t dest, ipaddr_t subnetmask,
+	ipaddr_t old_gateway, ipaddr_t new_gateway, time_t timeout ));
+void ipr_destunrch ARGS(( int port_nr, ipaddr_t dest, ipaddr_t subnetmask,
+	time_t timeout ));
+void ipr_ttl_exc ARGS(( int port_nr, ipaddr_t dest, ipaddr_t subnetmask,
+	time_t timeout ));
+void ipr_mtu ARGS(( int port_nr, ipaddr_t dest, U16_t mtu, time_t timeout ));
+
+#endif /* IPR_H */
+
+/*
+ * $PchId: ipr.h,v 1.8 2002/06/09 07:48:11 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/psip.c
===================================================================
--- /trunk/minix/servers/inet/generic/psip.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/psip.c	(revision 9)
@@ -0,0 +1,818 @@
+/*
+generic/psip.c
+
+Implementation of a pseudo IP device.
+
+Created:	Apr 22, 1993 by Philip Homburg
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "assert.h"
+#include "buf.h"
+#include "event.h"
+#include "type.h"
+#include "ip_int.h"
+#include "psip.h"
+#include "sr.h"
+
+THIS_FILE
+
+typedef struct psip_port
+{
+	int pp_flags;
+	int pp_ipdev;
+	int pp_opencnt;
+	struct psip_fd *pp_rd_head;
+	struct psip_fd *pp_rd_tail;
+	acc_t *pp_promisc_head;
+	acc_t *pp_promisc_tail;
+} psip_port_t;
+
+#define PPF_EMPTY	0
+#define PPF_CONFIGURED	1
+#define PPF_ENABLED	2
+#define PPF_PROMISC	4
+
+#define PSIP_FD_NR	(1*IP_PORT_MAX)
+
+typedef struct psip_fd
+{
+	int pf_flags;
+	int pf_srfd;
+	psip_port_t *pf_port;
+	get_userdata_t pf_get_userdata;
+	put_userdata_t pf_put_userdata;
+	struct psip_fd *pf_rd_next;
+	size_t pf_rd_count;
+	nwio_psipopt_t pf_psipopt;
+} psip_fd_t;
+
+#define PFF_EMPTY	0
+#define PFF_INUSE	1
+#define PFF_READ_IP	2
+#define PFF_PROMISC	4
+#define PFF_NEXTHOP	8
+
+PRIVATE psip_port_t *psip_port_table;
+PRIVATE psip_fd_t psip_fd_table[PSIP_FD_NR];
+
+FORWARD int psip_open ARGS(( int port, int srfd,
+	get_userdata_t get_userdata, put_userdata_t put_userdata,
+	put_pkt_t pkt_pkt, select_res_t select_res ));
+FORWARD int psip_ioctl ARGS(( int fd, ioreq_t req ));
+FORWARD int psip_read ARGS(( int fd, size_t count ));
+FORWARD int psip_write ARGS(( int fd, size_t count ));
+FORWARD int psip_select ARGS(( int port_nr, unsigned operations ));
+FORWARD void psip_close ARGS(( int fd ));
+FORWARD int psip_cancel ARGS(( int fd, int which_operation ));
+FORWARD void promisc_restart_read ARGS(( psip_port_t *psip_port ));
+FORWARD int psip_setopt ARGS(( psip_fd_t *psip_fd, nwio_psipopt_t *newoptp ));
+FORWARD void psip_buffree ARGS(( int priority ));
+FORWARD void check_promisc ARGS(( psip_port_t *psip_port ));
+#ifdef BUF_CONSISTENCY_CHECK
+FORWARD void psip_bufcheck ARGS(( void ));
+#endif
+FORWARD void reply_thr_put ARGS(( psip_fd_t *psip_fd, int reply,
+	int for_ioctl ));
+FORWARD void reply_thr_get ARGS(( psip_fd_t *psip_fd, int reply,
+	int for_ioctl ));
+
+PUBLIC void psip_prep()
+{
+	psip_port_table= alloc(psip_conf_nr * sizeof(psip_port_table[0]));
+}
+
+PUBLIC void psip_init()
+{
+	int i;
+	psip_port_t *psip_port;
+	psip_fd_t *psip_fd;
+
+	for (i=0, psip_port= psip_port_table; i<psip_conf_nr; i++, psip_port++)
+		psip_port->pp_flags= PPF_EMPTY;
+
+	for (i=0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)
+		psip_fd->pf_flags= PFF_EMPTY;
+
+	for (i=0, psip_port= psip_port_table; i<psip_conf_nr; i++, psip_port++)
+	{
+		psip_port->pp_flags |= PPF_CONFIGURED;
+		psip_port->pp_opencnt= 0;
+		psip_port->pp_rd_head= NULL;
+		psip_port->pp_promisc_head= NULL;
+	}
+
+#ifndef BUF_CONSISTENCY_CHECK
+	bf_logon(psip_buffree);
+#else
+	bf_logon(psip_buffree, psip_bufcheck);
+#endif
+}
+
+PUBLIC int psip_enable(port_nr, ip_port_nr)
+int port_nr;
+int ip_port_nr;
+{
+	psip_port_t *psip_port;
+
+	assert(port_nr >= 0);
+	if (port_nr >= psip_conf_nr)
+		return -1;
+
+	psip_port= &psip_port_table[port_nr];
+	if (!(psip_port->pp_flags &PPF_CONFIGURED))
+		return -1;
+
+	psip_port->pp_ipdev= ip_port_nr;
+	psip_port->pp_flags |= PPF_ENABLED;
+
+	sr_add_minor(if2minor(psip_conf[port_nr].pc_ifno, PSIP_DEV_OFF),
+		port_nr, psip_open, psip_close, psip_read,
+		psip_write, psip_ioctl, psip_cancel, psip_select);
+
+	return NW_OK;
+}
+
+PUBLIC int psip_send(port_nr, dest, pack)
+int port_nr;
+ipaddr_t dest;
+acc_t *pack;
+{
+	psip_port_t *psip_port;
+	psip_fd_t *psip_fd, *mark_fd;
+	int i, result, result1;
+	size_t buf_size, extrasize;
+	acc_t *hdr_pack, *acc;
+	psip_io_hdr_t *hdr;
+
+	assert(port_nr >= 0 && port_nr < psip_conf_nr);
+	psip_port= &psip_port_table[port_nr];
+
+	if (psip_port->pp_opencnt == 0)
+	{
+		bf_afree(pack);
+		return NW_OK;
+	}
+
+	for(;;)
+	{
+		mark_fd= psip_port->pp_rd_tail;
+
+		for(i= 0; i<PSIP_FD_NR; i++)
+		{
+			psip_fd= psip_port->pp_rd_head;
+			if (!psip_fd)
+				return NW_SUSPEND;
+			psip_port->pp_rd_head= psip_fd->pf_rd_next;
+			if (!(psip_fd->pf_flags & PFF_PROMISC))
+				break;
+			psip_fd->pf_rd_next= NULL;
+			if (psip_port->pp_rd_head == NULL)
+				psip_port->pp_rd_head= psip_fd;
+			else
+				psip_port->pp_rd_tail->pf_rd_next= psip_fd;
+			psip_port->pp_rd_tail= psip_fd;
+			if (psip_fd == mark_fd)
+				return NW_SUSPEND;
+		}
+		if (i == PSIP_FD_NR)
+			ip_panic(( "psip_send: loop" ));
+
+		assert(psip_fd->pf_flags & PFF_READ_IP);
+		psip_fd->pf_flags &= ~PFF_READ_IP;
+
+		if (psip_fd->pf_flags & PFF_NEXTHOP)
+			extrasize= sizeof(dest);
+		else
+			extrasize= 0;
+
+		buf_size= bf_bufsize(pack);
+		if (buf_size+extrasize <= psip_fd->pf_rd_count)
+		{
+			if (psip_port->pp_flags & PPF_PROMISC)
+			{
+				/* Deal with promiscuous mode. */
+				hdr_pack= bf_memreq(sizeof(*hdr));
+				hdr= (psip_io_hdr_t *)ptr2acc_data(hdr_pack);
+				memset(hdr, '\0', sizeof(*hdr));
+				hdr->pih_flags |= PF_LOC2REM;
+				hdr->pih_nexthop= dest;
+
+				pack->acc_linkC++;
+				hdr_pack->acc_next= pack;
+				hdr_pack->acc_ext_link= NULL;
+				if (psip_port->pp_promisc_head)
+				{
+					/* Append at the end. */
+					psip_port->pp_promisc_tail->
+						acc_ext_link= hdr_pack;
+					psip_port->pp_promisc_tail= hdr_pack;
+				}
+				else
+				{
+					/* First packet. */
+					psip_port->pp_promisc_head= hdr_pack;
+					psip_port->pp_promisc_tail= hdr_pack;
+					if (psip_port->pp_rd_head)
+					    promisc_restart_read(psip_port);
+				}
+			}
+
+			if (extrasize)
+			{
+				/* Prepend nexthop address */
+				acc= bf_memreq(sizeof(dest));
+				*(ipaddr_t *)(ptr2acc_data(acc))= dest;
+				acc->acc_next= pack;
+				pack= acc; acc= NULL;
+				buf_size += extrasize;
+			}
+
+			result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, 
+				(size_t)0, pack, FALSE);
+			if (result == NW_OK)
+				result= buf_size;
+		}
+		else
+			result= EPACKSIZE;
+
+		result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
+				(size_t)result, NULL, FALSE);
+		assert(result1 == NW_OK);
+		if (result == EPACKSIZE)
+			continue;
+		return NW_OK;
+	}
+	return NW_SUSPEND;
+}
+
+PRIVATE int psip_open(port, srfd, get_userdata, put_userdata, put_pkt,
+	select_res)
+int port;
+int srfd;
+get_userdata_t get_userdata;
+put_userdata_t put_userdata;
+put_pkt_t put_pkt;
+select_res_t select_res;
+{
+	psip_port_t *psip_port;
+	psip_fd_t *psip_fd;
+	int i;
+
+	assert(port >= 0 && port < psip_conf_nr);
+	psip_port= &psip_port_table[port];
+
+	if (!(psip_port->pp_flags & PPF_ENABLED))
+		return ENXIO;
+
+	for (i= 0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)
+	{
+		if (psip_fd->pf_flags & PFF_INUSE)
+			continue;
+		break;
+	}
+	if (i == PSIP_FD_NR)
+		return ENFILE;
+	psip_fd->pf_flags |= PFF_INUSE;
+	psip_fd->pf_srfd= srfd;
+	psip_fd->pf_port= psip_port;
+	psip_fd->pf_get_userdata= get_userdata;
+	psip_fd->pf_put_userdata= put_userdata;
+	psip_port->pp_opencnt++;
+
+	return i;
+}
+
+PRIVATE int psip_ioctl(fd, req)
+int fd;
+ioreq_t req;
+{
+	int result;
+	psip_fd_t *psip_fd;
+	acc_t *data;
+	nwio_ipconf_t *ipconfp;
+	nwio_psipopt_t *psip_opt, *newoptp;
+
+	assert(fd >= 0 && fd < PSIP_FD_NR);
+	psip_fd= &psip_fd_table[fd];
+
+	switch(req)
+	{
+	case NWIOSIPCONF:
+		data= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, 0, 
+			sizeof(*ipconfp), TRUE);
+		if (!data)
+		{
+			result= EFAULT;
+			break;
+		}
+		data= bf_packIffLess(data, sizeof(*ipconfp));
+		assert (data->acc_length == sizeof(*ipconfp));
+
+		ipconfp= (nwio_ipconf_t *)ptr2acc_data(data);
+		result= ip_setconf(psip_fd->pf_port->pp_ipdev, ipconfp);
+		bf_afree(data);
+		reply_thr_get(psip_fd, result, TRUE);
+		break;
+	case NWIOSPSIPOPT:
+		data= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, 0, 
+			sizeof(*psip_opt), TRUE);
+		if (!data)
+		{
+			result= EFAULT;
+			break;
+		}
+		data= bf_packIffLess(data, sizeof(*psip_opt));
+		assert (data->acc_length == sizeof(*psip_opt));
+
+		newoptp= (nwio_psipopt_t *)ptr2acc_data(data);
+		result= psip_setopt(psip_fd, newoptp);
+		bf_afree(data);
+		if (result == NW_OK)
+		{
+			if (psip_fd->pf_psipopt.nwpo_flags & NWPO_EN_PROMISC)
+			{
+				psip_fd->pf_flags |= PFF_PROMISC;
+				psip_fd->pf_port->pp_flags |= PPF_PROMISC;
+			}
+			else
+			{
+				psip_fd->pf_flags &= ~PFF_PROMISC;
+				check_promisc(psip_fd->pf_port);
+			}
+			if (psip_fd->pf_psipopt.nwpo_flags & NWPO_EN_NEXTHOP)
+			{
+				psip_fd->pf_flags |= PFF_NEXTHOP;
+			}
+			else
+			{
+				psip_fd->pf_flags &= ~PFF_NEXTHOP;
+			}
+		}
+		reply_thr_get(psip_fd, result, TRUE);
+		break;
+	case NWIOGPSIPOPT:
+		data= bf_memreq(sizeof(*psip_opt));
+		psip_opt= (nwio_psipopt_t *)ptr2acc_data(data);
+
+		*psip_opt= psip_fd->pf_psipopt;
+		result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, 0,
+			data, TRUE);
+		if (result == NW_OK)
+			reply_thr_put(psip_fd, NW_OK, TRUE);
+		break;
+	default:
+		reply_thr_put(psip_fd, ENOTTY, TRUE);
+		break;
+	}
+	return NW_OK;
+}
+
+PRIVATE int psip_read(fd, count)
+int fd;
+size_t count;
+{
+	psip_port_t *psip_port;
+	psip_fd_t *psip_fd;
+	acc_t *pack;
+	size_t buf_size;
+	int result, result1;
+
+	assert(fd >= 0 && fd < PSIP_FD_NR);
+	psip_fd= &psip_fd_table[fd];
+	psip_port= psip_fd->pf_port;
+
+	if ((psip_fd->pf_flags & PFF_PROMISC) && psip_port->pp_promisc_head)
+	{
+		/* Deliver a queued packet. */
+		pack= psip_port->pp_promisc_head;
+		buf_size= bf_bufsize(pack);
+		if (buf_size <= count)
+		{
+			psip_port->pp_promisc_head= pack->acc_ext_link;
+			result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, 
+				(size_t)0, pack, FALSE);
+			if (result == NW_OK)
+				result= buf_size;
+		}
+		else
+			result= EPACKSIZE;
+
+		result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
+				(size_t)result, NULL, FALSE);
+		assert(result1 == NW_OK);
+		return NW_OK;
+	}
+
+	psip_fd->pf_rd_count= count;
+	if (psip_port->pp_rd_head == NULL)
+		psip_port->pp_rd_head= psip_fd;
+	else
+		psip_port->pp_rd_tail->pf_rd_next= psip_fd;
+	psip_fd->pf_rd_next= NULL;
+	psip_port->pp_rd_tail= psip_fd;
+
+	psip_fd->pf_flags |= PFF_READ_IP;
+	if (!(psip_fd->pf_flags & PFF_PROMISC))
+		ipps_get(psip_port->pp_ipdev);
+	if (psip_fd->pf_flags & PFF_READ_IP)
+		return NW_SUSPEND;
+	return NW_OK;
+}
+
+PRIVATE int psip_write(fd, count)
+int fd;
+size_t count;
+{
+	psip_port_t *psip_port;
+	psip_fd_t *psip_fd;
+	acc_t *pack, *hdr_pack;
+	psip_io_hdr_t *hdr;
+	size_t pack_len;
+	ipaddr_t nexthop;
+
+	assert(fd >= 0 && fd < PSIP_FD_NR);
+	psip_fd= &psip_fd_table[fd];
+	psip_port= psip_fd->pf_port;
+
+	pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, (size_t)0,
+		count, FALSE);
+	if (pack == NULL)
+	{
+		pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, 
+			(size_t)EFAULT, (size_t)0, FALSE);
+		assert(pack == NULL);
+		return NW_OK;
+	}
+
+	if (psip_fd->pf_flags & PFF_NEXTHOP)
+	{
+		pack_len= bf_bufsize(pack);
+		if (pack_len <= sizeof(nexthop))
+		{
+			/* Something strange */
+			bf_afree(pack); pack= NULL;
+			pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd,
+				(size_t)EPACKSIZE, (size_t)0, FALSE);
+			assert(pack == NULL);
+			return NW_OK;
+		}
+		pack= bf_packIffLess(pack, sizeof(nexthop));
+		nexthop= *(ipaddr_t *)ptr2acc_data(pack);
+		pack= bf_delhead(pack, sizeof(nexthop));
+
+		/* Map multicast to broadcast */
+		if ((nexthop & HTONL(0xE0000000)) == HTONL(0xE0000000))
+			nexthop= HTONL(0xffffffff);
+	}
+	else
+	{
+		/* Assume point to point */
+		nexthop= HTONL(0x00000000);
+	}
+
+	if (psip_port->pp_flags & PPF_PROMISC)
+	{
+		/* Deal with promiscuous mode. */
+		hdr_pack= bf_memreq(sizeof(*hdr));
+		hdr= (psip_io_hdr_t *)ptr2acc_data(hdr_pack);
+		memset(hdr, '\0', sizeof(*hdr));
+		hdr->pih_flags |= PF_REM2LOC;
+		hdr->pih_nexthop= nexthop;
+
+		pack->acc_linkC++;
+		hdr_pack->acc_next= pack;
+		hdr_pack->acc_ext_link= NULL;
+		if (psip_port->pp_promisc_head)
+		{
+			/* Append at the end. */
+			psip_port->pp_promisc_tail->acc_ext_link= hdr_pack;
+			psip_port->pp_promisc_tail= hdr_pack;
+		}
+		else
+		{
+			/* First packet. */
+			psip_port->pp_promisc_head= hdr_pack;
+			psip_port->pp_promisc_tail= hdr_pack;
+			if (psip_port->pp_rd_head)
+				promisc_restart_read(psip_port);
+		}
+	}
+	ipps_put(psip_port->pp_ipdev, nexthop, pack);
+	pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, (size_t)count,
+		(size_t)0, FALSE);
+	assert(pack == NULL);
+	return NW_OK;
+}
+
+PRIVATE int psip_select(fd, operations)
+int fd;
+unsigned operations;
+{
+	printf("psip_select: not implemented\n");
+	return 0;
+}
+
+PRIVATE void psip_close(fd)
+int fd;
+{
+	psip_port_t *psip_port;
+	psip_fd_t *psip_fd;
+
+	assert(fd >= 0 && fd < PSIP_FD_NR);
+	psip_fd= &psip_fd_table[fd];
+	psip_port= psip_fd->pf_port;
+
+	if (psip_fd->pf_flags & PFF_PROMISC)
+	{
+		/* Check if the port should still be in promiscuous mode.
+		 */
+		psip_fd->pf_flags &= ~PFF_PROMISC;
+		check_promisc(psip_fd->pf_port);
+	}
+
+	assert(psip_port->pp_opencnt >0);
+	psip_port->pp_opencnt--;
+	psip_fd->pf_flags= PFF_EMPTY;
+	ipps_get(psip_port->pp_ipdev);
+
+}
+
+PRIVATE int psip_cancel(fd, which_operation)
+int fd;
+int which_operation;
+{
+	psip_port_t *psip_port;
+	psip_fd_t *psip_fd, *prev_fd, *tmp_fd;
+	int result;
+
+	DBLOCK(1, printf("psip_cancel(%d, %d)\n", fd, which_operation));
+
+	assert(fd >= 0 && fd < PSIP_FD_NR);
+	psip_fd= &psip_fd_table[fd];
+	psip_port= psip_fd->pf_port;
+
+	switch(which_operation)
+	{
+	case SR_CANCEL_IOCTL:
+		ip_panic(( "should not be here" ));
+	case SR_CANCEL_READ:
+		assert(psip_fd->pf_flags & PFF_READ_IP);
+		for (prev_fd= NULL, tmp_fd= psip_port->pp_rd_head; tmp_fd;
+			prev_fd= tmp_fd, tmp_fd= tmp_fd->pf_rd_next)
+		{
+			if (tmp_fd == psip_fd)
+				break;
+		}
+		if (tmp_fd == NULL)
+			ip_panic(( "unable to find to request to cancel" ));
+		if (prev_fd == NULL)
+			psip_port->pp_rd_head= psip_fd->pf_rd_next;
+		else
+			prev_fd->pf_rd_next= psip_fd->pf_rd_next;
+		if (psip_fd->pf_rd_next == NULL)
+			psip_port->pp_rd_tail= prev_fd;
+		psip_fd->pf_flags &= ~PFF_READ_IP;
+		result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
+						(size_t)EINTR, NULL, FALSE);
+		assert(result == NW_OK);
+		break;
+	case SR_CANCEL_WRITE:
+		ip_panic(( "should not be here" ));
+	default:
+		ip_panic(( "invalid operation for cancel" ));
+	}
+	return NW_OK;
+}
+
+PRIVATE void promisc_restart_read(psip_port)
+psip_port_t *psip_port;
+{
+	psip_fd_t *psip_fd, *prev, *next;
+	acc_t *pack;
+	size_t buf_size;
+	int result, result1;
+
+	/* Overkill at the moment: just one reader in promiscious mode is
+	 * allowed.
+	 */
+	pack= psip_port->pp_promisc_head;
+	if (!pack)
+		return;
+	assert(pack->acc_ext_link == NULL);
+
+	for(psip_fd= psip_port->pp_rd_head, prev= NULL; psip_fd;
+		prev= psip_fd, psip_fd= psip_fd->pf_rd_next)
+	{
+again:
+		if (!(psip_fd->pf_flags & PFF_PROMISC))
+			continue;
+		next= psip_fd->pf_rd_next;
+		if (prev)
+			prev->pf_rd_next= next;
+		else
+			psip_port->pp_rd_head= next;
+		if (!next)
+			psip_port->pp_rd_tail= prev;
+
+		assert(psip_fd->pf_flags & PFF_READ_IP);
+		psip_fd->pf_flags &= ~PFF_READ_IP;
+
+		buf_size= bf_bufsize(pack);
+		if (buf_size <= psip_fd->pf_rd_count)
+		{
+			psip_port->pp_promisc_head= pack->acc_ext_link;
+			result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, 
+				(size_t)0, pack, FALSE);
+			if (result == NW_OK)
+				result= buf_size;
+		}
+		else
+			result= EPACKSIZE;
+
+		result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
+				(size_t)result, NULL, FALSE);
+		assert(result1 == NW_OK);
+
+		if (psip_port->pp_promisc_head)
+		{
+			/* Restart from the beginning */
+			assert(result == EPACKSIZE);
+			psip_fd= psip_port->pp_rd_head;
+			prev= NULL;
+			goto again;
+		}
+		break;
+	}
+}
+
+PRIVATE int psip_setopt(psip_fd, newoptp)
+psip_fd_t *psip_fd;
+nwio_psipopt_t *newoptp;
+{
+	nwio_psipopt_t oldopt;
+	unsigned int new_en_flags, new_di_flags, old_en_flags, old_di_flags;
+	unsigned long new_flags;
+
+	oldopt= psip_fd->pf_psipopt;
+
+	old_en_flags= oldopt.nwpo_flags & 0xffff;
+	old_di_flags= (oldopt.nwpo_flags >> 16) & 0xffff;
+
+	new_en_flags= newoptp->nwpo_flags & 0xffff;
+	new_di_flags= (newoptp->nwpo_flags >> 16) & 0xffff;
+
+	if (new_en_flags & new_di_flags)
+		return EBADMODE;
+
+	/* NWUO_LOCADDR_MASK */
+	if (!((new_en_flags | new_di_flags) & NWPO_PROMISC_MASK))
+	{
+		new_en_flags |= (old_en_flags & NWPO_PROMISC_MASK);
+		new_di_flags |= (old_di_flags & NWPO_PROMISC_MASK);
+	}
+
+	new_flags= ((unsigned long)new_di_flags << 16) | new_en_flags;
+	if ((new_flags & NWPO_EN_PROMISC) &&
+		(psip_fd->pf_port->pp_flags & PPF_PROMISC))
+	{
+		printf("psip_setopt: EBUSY for port %d, flags 0x%x\n",
+			psip_fd->pf_port - psip_port_table,
+			psip_fd->pf_port->pp_flags);
+		/* We can support only one at a time. */
+		return EBUSY;
+	}
+
+	psip_fd->pf_psipopt= *newoptp;
+	psip_fd->pf_psipopt.nwpo_flags= new_flags;
+
+	return NW_OK;
+}
+
+PRIVATE void check_promisc(psip_port)
+psip_port_t *psip_port;
+{
+	int i;
+	psip_fd_t *psip_fd;
+	acc_t *acc, *acc_next;
+
+	/* Check if the port should still be in promiscuous mode.  Overkill
+	 * at the moment.
+	 */
+	if (!(psip_port->pp_flags & PPF_PROMISC))
+		return;
+
+	psip_port->pp_flags &= ~PPF_PROMISC;
+	for (i= 0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)
+	{
+		if ((psip_fd->pf_flags & (PFF_INUSE|PFF_PROMISC)) !=
+			(PFF_INUSE|PFF_PROMISC))
+		{
+			continue;
+		}
+		if (psip_fd->pf_port != psip_port)
+			continue;
+		printf("check_promisc: setting PROMISC for port %d\n",
+			psip_port-psip_port_table);
+		psip_port->pp_flags |= PPF_PROMISC;
+		break;
+	}
+	if (!(psip_port->pp_flags & PPF_PROMISC))
+	{
+		/* Delete queued packets. */
+		acc= psip_port->pp_promisc_head;
+		psip_port->pp_promisc_head= NULL;
+		while (acc)
+		{
+			acc_next= acc->acc_ext_link;
+			bf_afree(acc);
+			acc= acc_next;
+		}
+	}
+}
+
+PRIVATE void psip_buffree (priority)
+int priority;
+{
+	int i;
+	psip_port_t *psip_port;
+	acc_t *tmp_acc, *next_acc;
+
+	if (priority == PSIP_PRI_EXP_PROMISC)
+	{
+		for (i=0, psip_port= psip_port_table; i<psip_conf_nr;
+			i++, psip_port++)
+		{
+			if (!(psip_port->pp_flags & PPF_CONFIGURED) )
+				continue;
+			if (psip_port->pp_promisc_head)
+			{
+				tmp_acc= psip_port->pp_promisc_head;
+				while(tmp_acc)
+				{
+					next_acc= tmp_acc->acc_ext_link;
+					bf_afree(tmp_acc);
+					tmp_acc= next_acc;
+				}
+				psip_port->pp_promisc_head= NULL;
+			}
+		}
+	}
+}
+
+#ifdef BUF_CONSISTENCY_CHECK
+PRIVATE void psip_bufcheck()
+{
+	int i;
+	psip_port_t *psip_port;
+	acc_t *tmp_acc;
+
+	for (i= 0, psip_port= psip_port_table; i<psip_conf_nr;
+		i++, psip_port++)
+	{
+		for (tmp_acc= psip_port->pp_promisc_head; tmp_acc; 
+			tmp_acc= tmp_acc->acc_ext_link)
+		{
+			bf_check_acc(tmp_acc);
+		}
+	}
+}
+#endif
+
+/*
+reply_thr_put
+*/
+
+PRIVATE void reply_thr_put(psip_fd, reply, for_ioctl)
+psip_fd_t *psip_fd;
+int reply;
+int for_ioctl;
+{
+	int result;
+
+	result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, reply,
+		(acc_t *)0, for_ioctl);
+	assert(result == NW_OK);
+}
+
+/*
+reply_thr_get
+*/
+
+PRIVATE void reply_thr_get(psip_fd, reply, for_ioctl)
+psip_fd_t *psip_fd;
+int reply;
+int for_ioctl;
+{
+	acc_t *result;
+	result= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, reply,
+		(size_t)0, for_ioctl);
+	assert (!result);
+}
+
+
+/*
+ * $PchId: psip.c,v 1.15 2005/06/28 14:19:29 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/psip.h
===================================================================
--- /trunk/minix/servers/inet/generic/psip.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/psip.h	(revision 9)
@@ -0,0 +1,23 @@
+/*
+generic/psip.h
+
+Public interface to the pseudo IP module
+
+Created:	Apr 22, 1993 by Philip Homburg
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef PSIP_H
+#define PSIP_H
+
+void psip_prep ARGS(( void ));
+void psip_init ARGS(( void ));
+int psip_enable ARGS(( int port_nr, int ip_port_nr ));
+int psip_send ARGS(( int port_nr, ipaddr_t dest, acc_t *pack ));
+
+#endif /* PSIP_H */
+
+/*
+ * $PchId: psip.h,v 1.6 2001/04/19 21:16:22 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/rand256.c
===================================================================
--- /trunk/minix/servers/inet/generic/rand256.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/rand256.c	(revision 9)
@@ -0,0 +1,37 @@
+/*
+rand256.c
+
+Created:	Oct 2000 by Philip Homburg <philip@f-mnx.phicoh.com>
+
+Generate 256-bit random numbers 
+*/
+
+#include <sha2.h>
+#include "inet.h"
+#include "rand256.h"
+
+PRIVATE u32_t base_bits[8];
+
+PUBLIC void init_rand256(bits)
+u8_t bits[32];
+{
+	memcpy(base_bits, bits, sizeof(base_bits));
+}
+
+PUBLIC void rand256(bits)
+u8_t bits[32];
+{
+	u32_t a;
+	SHA256_CTX ctx;
+
+	a= ++base_bits[0];
+	if (a == 0)
+		base_bits[1]++;
+	SHA256_Init(&ctx);
+	SHA256_Update(&ctx, (unsigned char *)base_bits, sizeof(base_bits));
+	SHA256_Final(bits, &ctx);
+}
+
+/*
+ * $PchId: rand256.c,v 1.1 2005/06/28 14:13:43 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/rand256.h
===================================================================
--- /trunk/minix/servers/inet/generic/rand256.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/rand256.h	(revision 9)
@@ -0,0 +1,16 @@
+/*
+rand256.h
+
+Created:	Oct 2000 by Philip Homburg <philip@f-mnx.phicoh.com>
+
+Provide 256-bit random numbers
+*/
+
+#define RAND256_BUFSIZE	32
+
+void init_rand256 ARGS(( u8_t bits[RAND256_BUFSIZE] ));
+void rand256 ARGS(( u8_t bits[RAND256_BUFSIZE] ));
+
+/*
+ * $PchId: rand256.h,v 1.1 2005/06/28 14:14:05 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/sr.h
===================================================================
--- /trunk/minix/servers/inet/generic/sr.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/sr.h	(revision 9)
@@ -0,0 +1,49 @@
+/*
+sr.h
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef SR_H
+#define SR_H
+
+#define MAX_IOCTL_S	512
+
+#define SR_CANCEL_IOCTL	1
+#define SR_CANCEL_READ	2
+#define SR_CANCEL_WRITE	3
+
+#define SR_SELECT_READ		0x01
+#define SR_SELECT_WRITE		0x02
+#define SR_SELECT_EXCEPTION	0x04
+#define SR_SELECT_POLL		0x10
+
+/* Forward struct declarations */
+
+struct acc;
+
+/* prototypes */
+
+typedef int  (*sr_open_t) ARGS(( int port, int srfd,
+	get_userdata_t get_userdata, put_userdata_t put_userdata,
+	put_pkt_t put_pkt, select_res_t select_res ));
+typedef void (*sr_close_t) ARGS(( int fd ));
+typedef int (*sr_read_t) ARGS(( int fd, size_t count ));
+typedef int (*sr_write_t) ARGS(( int fd, size_t count ));
+typedef int  (*sr_ioctl_t) ARGS(( int fd, ioreq_t req ));
+typedef int  (*sr_cancel_t) ARGS(( int fd, int which_operation ));
+typedef int  (*sr_select_t) ARGS(( int fd, unsigned operations ));
+
+void sr_init ARGS(( void  ));
+void sr_add_minor ARGS(( int minor, int port, sr_open_t openf,
+	sr_close_t closef, sr_read_t sr_read, sr_write_t sr_write,
+	sr_ioctl_t ioctlf, sr_cancel_t cancelf, sr_select_t selectf ));
+
+#endif /* SR_H */
+
+/* Track TCP connections back into sr (for lsof, identd, etc.) */
+EXTERN sr_cancel_t tcp_cancel_f;
+
+/*
+ * $PchId: sr.h,v 1.9 2005/06/28 14:19:51 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/tcp.c
===================================================================
--- /trunk/minix/servers/inet/generic/tcp.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/tcp.c	(revision 9)
@@ -0,0 +1,2723 @@
+/*
+tcp.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "buf.h"
+#include "clock.h"
+#include "event.h"
+#include "type.h"
+
+#include "io.h"
+#include "ip.h"
+#include "sr.h"
+#include "assert.h"
+#include "rand256.h"
+#include "tcp.h"
+#include "tcp_int.h"
+
+THIS_FILE
+
+#define NOT_IMPLEMENTED 0
+
+PUBLIC tcp_port_t *tcp_port_table;
+PUBLIC tcp_fd_t tcp_fd_table[TCP_FD_NR];
+PUBLIC tcp_conn_t tcp_conn_table[TCP_CONN_NR];
+PUBLIC sr_cancel_t tcp_cancel_f;
+
+FORWARD void tcp_main ARGS(( tcp_port_t *port ));
+FORWARD int tcp_select ARGS(( int fd, unsigned operations ));
+FORWARD acc_t *tcp_get_data ARGS(( int fd, size_t offset,
+	size_t count, int for_ioctl ));
+FORWARD int tcp_put_data ARGS(( int fd, size_t offset,
+	acc_t *data, int for_ioctl ));
+FORWARD void tcp_put_pkt ARGS(( int fd, acc_t *data, size_t datalen ));
+FORWARD void read_ip_packets ARGS(( tcp_port_t *port ));
+FORWARD int tcp_setconf ARGS(( tcp_fd_t *tcp_fd ));
+FORWARD int tcp_setopt ARGS(( tcp_fd_t *tcp_fd ));
+FORWARD int tcp_connect ARGS(( tcp_fd_t *tcp_fd ));
+FORWARD int tcp_listen ARGS(( tcp_fd_t *tcp_fd, int do_listenq ));
+FORWARD int tcp_acceptto ARGS(( tcp_fd_t *tcp_fd ));
+FORWARD tcpport_t find_unused_port ARGS(( int fd ));
+FORWARD int is_unused_port ARGS(( Tcpport_t port ));
+FORWARD int reply_thr_put ARGS(( tcp_fd_t *tcp_fd, int reply,
+	int for_ioctl ));
+FORWARD void reply_thr_get ARGS(( tcp_fd_t *tcp_fd, int reply,
+	int for_ioctl ));
+FORWARD tcp_conn_t *find_conn_entry ARGS(( Tcpport_t locport,
+	ipaddr_t locaddr, Tcpport_t remport, ipaddr_t readaddr ));
+FORWARD tcp_conn_t *find_empty_conn ARGS(( void ));
+FORWARD tcp_conn_t *find_best_conn ARGS(( ip_hdr_t *ip_hdr, 
+	tcp_hdr_t *tcp_hdr ));
+FORWARD tcp_conn_t *new_conn_for_queue ARGS(( tcp_fd_t *tcp_fd ));
+FORWARD int maybe_listen ARGS(( ipaddr_t locaddr, Tcpport_t locport,
+				ipaddr_t remaddr, Tcpport_t remport ));
+FORWARD int tcp_su4connect ARGS(( tcp_fd_t *tcp_fd ));
+FORWARD void tcp_buffree ARGS(( int priority ));
+#ifdef BUF_CONSISTENCY_CHECK
+FORWARD void tcp_bufcheck ARGS(( void ));
+#endif
+FORWARD void tcp_setup_conn ARGS(( tcp_port_t *tcp_port,
+					tcp_conn_t *tcp_conn ));
+FORWARD u32_t tcp_rand32 ARGS(( void ));
+
+PUBLIC void tcp_prep()
+{
+	tcp_port_table= alloc(tcp_conf_nr * sizeof(tcp_port_table[0]));
+}
+
+PUBLIC void tcp_init()
+{
+	int i, j, k, ifno;
+	tcp_fd_t *tcp_fd;
+	tcp_port_t *tcp_port;
+	tcp_conn_t *tcp_conn;
+
+	assert (BUF_S >= sizeof(struct nwio_ipopt));
+	assert (BUF_S >= sizeof(struct nwio_ipconf));
+	assert (BUF_S >= sizeof(struct nwio_tcpconf));
+	assert (BUF_S >= IP_MAX_HDR_SIZE + TCP_MAX_HDR_SIZE);
+
+	for (i=0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++, tcp_fd++)
+	{
+		tcp_fd->tf_flags= TFF_EMPTY;
+	}
+
+	for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
+		tcp_fd++)
+	{
+		tcp_conn->tc_flags= TCF_EMPTY;
+		tcp_conn->tc_busy= 0;
+	}
+
+#ifndef BUF_CONSISTENCY_CHECK
+	bf_logon(tcp_buffree);
+#else
+	bf_logon(tcp_buffree, tcp_bufcheck);
+#endif
+
+	for (i=0, tcp_port= tcp_port_table; i<tcp_conf_nr; i++, tcp_port++)
+	{
+		tcp_port->tp_ipdev= tcp_conf[i].tc_port;
+
+		tcp_port->tp_flags= TPF_EMPTY;
+		tcp_port->tp_state= TPS_EMPTY;
+		tcp_port->tp_snd_head= NULL;
+		tcp_port->tp_snd_tail= NULL;
+		ev_init(&tcp_port->tp_snd_event);
+		for (j= 0; j<TCP_CONN_HASH_NR; j++)
+		{
+			for (k= 0; k<4; k++)
+			{
+				tcp_port->tp_conn_hash[j][k]=
+					&tcp_conn_table[0];
+			}
+		}
+
+		ifno= ip_conf[tcp_port->tp_ipdev].ic_ifno;
+		sr_add_minor(if2minor(ifno, TCP_DEV_OFF),
+			i, tcp_open, tcp_close, tcp_read,
+			tcp_write, tcp_ioctl, tcp_cancel, tcp_select);
+
+		tcp_main(tcp_port);
+	}
+	tcp_cancel_f= tcp_cancel;
+}
+
+PRIVATE void tcp_main(tcp_port)
+tcp_port_t *tcp_port;
+{
+	int result, i;
+	tcp_conn_t *tcp_conn;
+	tcp_fd_t *tcp_fd;
+
+	switch (tcp_port->tp_state)
+	{
+	case TPS_EMPTY:
+		tcp_port->tp_state= TPS_SETPROTO;
+		tcp_port->tp_ipfd= ip_open(tcp_port->tp_ipdev,
+			tcp_port->tp_ipdev, tcp_get_data,
+			tcp_put_data, tcp_put_pkt, 0 /* no select_res */);
+		if (tcp_port->tp_ipfd < 0)
+		{
+			tcp_port->tp_state= TPS_ERROR;
+			DBLOCK(1, printf("%s, %d: unable to open ip port\n",
+				__FILE__, __LINE__));
+			return;
+		}
+
+		result= ip_ioctl(tcp_port->tp_ipfd, NWIOSIPOPT);
+		if (result == NW_SUSPEND)
+			tcp_port->tp_flags |= TPF_SUSPEND;
+		if (result < 0)
+		{
+			return;
+		}
+		if (tcp_port->tp_state != TPS_GETCONF)
+			return;
+		/* drops through */
+	case TPS_GETCONF:
+		tcp_port->tp_flags &= ~TPF_SUSPEND;
+
+		result= ip_ioctl(tcp_port->tp_ipfd, NWIOGIPCONF);
+		if (result == NW_SUSPEND)
+			tcp_port->tp_flags |= TPF_SUSPEND;
+		if (result < 0)
+		{
+			return;
+		}
+		if (tcp_port->tp_state != TPS_MAIN)
+			return;
+		/* drops through */
+	case TPS_MAIN:
+		tcp_port->tp_flags &= ~TPF_SUSPEND;
+		tcp_port->tp_pack= 0;
+
+		tcp_conn= &tcp_conn_table[tcp_port->tp_ipdev];
+		tcp_conn->tc_flags= TCF_INUSE;
+		assert(!tcp_conn->tc_busy);
+		tcp_conn->tc_locport= 0;
+		tcp_conn->tc_locaddr= tcp_port->tp_ipaddr;
+		tcp_conn->tc_remport= 0;
+		tcp_conn->tc_remaddr= 0;
+		tcp_conn->tc_state= TCS_CLOSED;
+		tcp_conn->tc_fd= 0;
+		tcp_conn->tc_connInprogress= 0;
+		tcp_conn->tc_orglisten= FALSE;
+		tcp_conn->tc_senddis= 0;
+		tcp_conn->tc_ISS= 0;
+		tcp_conn->tc_SND_UNA= tcp_conn->tc_ISS;
+		tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;
+		tcp_conn->tc_SND_NXT= tcp_conn->tc_ISS;
+		tcp_conn->tc_SND_UP= tcp_conn->tc_ISS;
+		tcp_conn->tc_IRS= 0;
+		tcp_conn->tc_RCV_LO= tcp_conn->tc_IRS;
+		tcp_conn->tc_RCV_NXT= tcp_conn->tc_IRS;
+		tcp_conn->tc_RCV_HI= tcp_conn->tc_IRS;
+		tcp_conn->tc_RCV_UP= tcp_conn->tc_IRS;
+		tcp_conn->tc_port= tcp_port;
+		tcp_conn->tc_rcvd_data= NULL;
+		tcp_conn->tc_adv_data= NULL;
+		tcp_conn->tc_send_data= 0;
+		tcp_conn->tc_remipopt= NULL;
+		tcp_conn->tc_tcpopt= NULL;
+		tcp_conn->tc_frag2send= 0;
+		tcp_conn->tc_tos= TCP_DEF_TOS;
+		tcp_conn->tc_ttl= IP_MAX_TTL;
+		tcp_conn->tc_rcv_wnd= TCP_MAX_RCV_WND_SIZE;
+		tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD;
+		tcp_conn->tc_stt= 0;
+		tcp_conn->tc_0wnd_to= 0;
+		tcp_conn->tc_artt= TCP_DEF_RTT*TCP_RTT_SCALE;
+		tcp_conn->tc_drtt= 0;
+		tcp_conn->tc_rtt= TCP_DEF_RTT;
+		tcp_conn->tc_max_mtu= tcp_port->tp_mtu;
+		tcp_conn->tc_mtu= tcp_conn->tc_max_mtu;
+		tcp_conn->tc_mtutim= 0;
+		tcp_conn->tc_error= NW_OK;
+		tcp_conn->tc_snd_wnd= TCP_MAX_SND_WND_SIZE;
+		tcp_conn->tc_snd_cinc=
+			(long)TCP_DEF_MSS*TCP_DEF_MSS/TCP_MAX_SND_WND_SIZE+1;
+
+		tcp_conn->tc_rt_time= 0;
+		tcp_conn->tc_rt_seq= 0;
+		tcp_conn->tc_rt_threshold= tcp_conn->tc_ISS;
+
+		for (i=0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++,
+			tcp_fd++)
+		{
+			if (!(tcp_fd->tf_flags & TFF_INUSE))
+				continue;
+			if (tcp_fd->tf_port != tcp_port)
+				continue;
+			if (tcp_fd->tf_flags & TFF_IOC_INIT_SP)
+			{
+				tcp_fd->tf_flags &= ~TFF_IOC_INIT_SP;
+				tcp_ioctl(i, tcp_fd->tf_ioreq);
+			}
+		}
+		read_ip_packets(tcp_port);
+		return;
+
+	default:
+		ip_panic(( "unknown state" ));
+		break;
+	}
+}
+
+PRIVATE int tcp_select(fd, operations)
+int fd;
+unsigned operations;
+{
+	int i;
+	unsigned resops;
+	tcp_fd_t *tcp_fd;
+	tcp_conn_t *tcp_conn;
+
+	tcp_fd= &tcp_fd_table[fd];
+	assert (tcp_fd->tf_flags & TFF_INUSE);
+
+	resops= 0;
+	if (tcp_fd->tf_flags & TFF_LISTENQ)
+	{
+		/* Special case for LISTENQ */
+		if (operations & SR_SELECT_READ)
+		{
+			for (i= 0; i<TFL_LISTEN_MAX; i++)
+			{
+				if (tcp_fd->tf_listenq[i] == NULL)
+					continue;
+				if (tcp_fd->tf_listenq[i]->tc_connInprogress
+					== 0)
+				{
+					break;
+				}
+			}
+			if (i >= TFL_LISTEN_MAX)
+				tcp_fd->tf_flags |= TFF_SEL_READ;
+			else
+				resops |= SR_SELECT_READ;
+		}
+		if (operations & SR_SELECT_WRITE)
+		{
+			/* We can't handles writes. Just return the error
+			 * when the user tries to write.
+			 */
+			resops |= SR_SELECT_WRITE;
+		}
+		return resops;
+	}
+	if (tcp_fd->tf_flags & TFF_CONNECTING)
+	{
+		/* Special case for CONNECTING */
+		if (operations & SR_SELECT_WRITE)
+			tcp_fd->tf_flags |= TFF_SEL_WRITE;
+		return 0;
+	}
+	if (operations & SR_SELECT_READ)
+	{
+		tcp_conn= tcp_fd->tf_conn;
+
+		if (!(tcp_fd->tf_flags & TFF_CONNECTED))
+		{
+			/* We can't handle reads until a connection has been
+			 * established. Return the error when the user tries
+			 * to read.
+			 */
+			resops |= SR_SELECT_READ;
+		}
+		else if (tcp_conn->tc_state == TCS_CLOSED ||
+			tcp_sel_read(tcp_conn))
+		{
+			resops |= SR_SELECT_READ;
+		}
+		else if (!(operations & SR_SELECT_POLL))
+				tcp_fd->tf_flags |= TFF_SEL_READ;
+	}
+	if (operations & SR_SELECT_WRITE)
+	{
+		tcp_conn= tcp_fd->tf_conn;
+		if (!(tcp_fd->tf_flags & TFF_CONNECTED))
+		{
+			/* We can't handle writes until a connection has been
+			 * established. Return the error when the user tries
+			 * to write.
+			 */
+			resops |= SR_SELECT_WRITE;
+		}
+		else if (tcp_conn->tc_state == TCS_CLOSED ||
+			tcp_conn->tc_flags & TCF_FIN_SENT ||
+			tcp_sel_write(tcp_conn))
+		{
+			resops |= SR_SELECT_WRITE;
+		}
+		else if (!(operations & SR_SELECT_POLL))
+			tcp_fd->tf_flags |= TFF_SEL_WRITE;
+	}
+	if (operations & SR_SELECT_EXCEPTION)
+	{
+		/* Should add code for exceptions */
+	}
+	return resops;
+}
+
+PRIVATE acc_t *tcp_get_data (port, offset, count, for_ioctl)
+int port;
+size_t offset;
+size_t count;
+int for_ioctl;
+{
+	tcp_port_t *tcp_port;
+	int result;
+
+	tcp_port= &tcp_port_table[port];
+
+	switch (tcp_port->tp_state)
+	{
+	case TPS_SETPROTO:
+		if (!count)
+		{
+			result= (int)offset;
+			if (result<0)
+			{
+				tcp_port->tp_state= TPS_ERROR;
+				break;
+			}
+			tcp_port->tp_state= TPS_GETCONF;
+			if (tcp_port->tp_flags & TPF_SUSPEND)
+				tcp_main(tcp_port);
+			return NW_OK;
+		}
+assert (!offset);
+assert (count == sizeof(struct nwio_ipopt));
+		{
+			struct nwio_ipopt *ipopt;
+			acc_t *acc;
+
+			acc= bf_memreq(sizeof(*ipopt));
+			ipopt= (struct nwio_ipopt *)ptr2acc_data(acc);
+			ipopt->nwio_flags= NWIO_COPY |
+				NWIO_EN_LOC | NWIO_DI_BROAD |
+				NWIO_REMANY | NWIO_PROTOSPEC |
+				NWIO_HDR_O_ANY | NWIO_RWDATALL;
+			ipopt->nwio_proto= IPPROTO_TCP;
+			return acc;
+		}
+	case TPS_MAIN:
+		assert(tcp_port->tp_flags & TPF_WRITE_IP);
+		if (!count)
+		{
+			result= (int)offset;
+			if (result<0)
+			{
+				if (result == EDSTNOTRCH)
+				{
+					if (tcp_port->tp_snd_head)
+					{
+						tcp_notreach(tcp_port->
+							tp_snd_head);
+					}
+				}
+				else
+				{
+					ip_warning((
+					"ip_write failed with error: %d\n", 
+								result ));
+				}
+			}
+			assert (tcp_port->tp_pack);
+			bf_afree (tcp_port->tp_pack);
+			tcp_port->tp_pack= 0;
+
+			if (tcp_port->tp_flags & TPF_WRITE_SP)
+			{
+				tcp_port->tp_flags &= ~(TPF_WRITE_SP|
+					TPF_WRITE_IP);
+				if (tcp_port->tp_snd_head)
+					tcp_port_write(tcp_port);
+			}
+			else
+				tcp_port->tp_flags &= ~TPF_WRITE_IP;
+		}
+		else
+		{
+			return bf_cut (tcp_port->tp_pack, offset,
+				count);
+		}
+		break;
+	default:
+		printf("tcp_get_data(%d, 0x%x, 0x%x) called but tp_state= 0x%x\n",
+			port, offset, count, tcp_port->tp_state);
+		break;
+	}
+	return NW_OK;
+}
+
+PRIVATE int tcp_put_data (fd, offset, data, for_ioctl)
+int fd;
+size_t offset;
+acc_t *data;
+int for_ioctl;
+{
+	tcp_port_t *tcp_port;
+	int result;
+
+	tcp_port= &tcp_port_table[fd];
+
+	switch (tcp_port->tp_state)
+	{
+	case TPS_GETCONF:
+		if (!data)
+		{
+			result= (int)offset;
+			if (result<0)
+			{
+				tcp_port->tp_state= TPS_ERROR;
+				return NW_OK;
+			}
+			tcp_port->tp_state= TPS_MAIN;
+			if (tcp_port->tp_flags & TPF_SUSPEND)
+				tcp_main(tcp_port);
+		}
+		else
+		{
+			struct nwio_ipconf *ipconf;
+
+			data= bf_packIffLess(data, sizeof(*ipconf));
+			ipconf= (struct nwio_ipconf *)ptr2acc_data(data);
+assert (ipconf->nwic_flags & NWIC_IPADDR_SET);
+			tcp_port->tp_ipaddr= ipconf->nwic_ipaddr;
+			tcp_port->tp_subnetmask= ipconf->nwic_netmask;
+			tcp_port->tp_mtu= ipconf->nwic_mtu;
+			bf_afree(data);
+		}
+		break;
+	case TPS_MAIN:
+		assert(tcp_port->tp_flags & TPF_READ_IP);
+		if (!data)
+		{
+			result= (int)offset;
+			if (result<0)
+				ip_panic(( "ip_read() failed" ));
+
+			if (tcp_port->tp_flags & TPF_READ_SP)
+			{
+				tcp_port->tp_flags &= ~(TPF_READ_SP|
+					TPF_READ_IP);
+				read_ip_packets(tcp_port);
+			}
+			else
+				tcp_port->tp_flags &= ~TPF_READ_IP;
+		}
+		else
+		{
+			assert(!offset);	
+			/* this is an invalid assertion but ip sends
+			  * only whole datagrams up */
+			tcp_put_pkt(fd, data, bf_bufsize(data));
+		}
+		break;
+	default:
+		printf(
+		"tcp_put_data(%d, 0x%x, %p) called but tp_state= 0x%x\n",
+			fd, offset, data, tcp_port->tp_state);
+		break;
+	}
+	return NW_OK;
+}
+
+/*
+tcp_put_pkt
+*/
+
+PRIVATE void tcp_put_pkt(fd, data, datalen)
+int fd;
+acc_t *data;
+size_t datalen;
+{
+	tcp_port_t *tcp_port;
+	tcp_conn_t *tcp_conn, **conn_p;
+	ip_hdr_t *ip_hdr;
+	tcp_hdr_t *tcp_hdr;
+	acc_t *ip_pack, *tcp_pack;
+	size_t ip_datalen, tcp_datalen, ip_hdr_len, tcp_hdr_len;
+	u16_t sum, mtu;
+	u32_t bits;
+	int i, hash;
+	ipaddr_t srcaddr, dstaddr, ipaddr, mask;
+	tcpport_t srcport, dstport;
+
+	tcp_port= &tcp_port_table[fd];
+
+	/* Extract the IP header. */
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
+	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
+	ip_datalen= datalen - ip_hdr_len;
+	if (ip_datalen == 0)
+	{
+		if (ip_hdr->ih_proto == 0)
+		{
+			/* IP layer reports new IP address */
+			ipaddr= ip_hdr->ih_src;
+			mask= ip_hdr->ih_dst;
+			mtu= ntohs(ip_hdr->ih_length);
+			tcp_port->tp_ipaddr= ipaddr;
+			tcp_port->tp_subnetmask= mask;
+			tcp_port->tp_mtu= mtu;
+			DBLOCK(1, printf("tcp_put_pkt: using address ");
+				writeIpAddr(ipaddr);
+				printf(", netmask ");
+				writeIpAddr(mask);
+				printf(", mtu %u\n", mtu));
+			for (i= 0, tcp_conn= tcp_conn_table+i;
+				i<TCP_CONN_NR; i++, tcp_conn++)
+			{
+				if (!(tcp_conn->tc_flags & TCF_INUSE))
+					continue;
+				if (tcp_conn->tc_port != tcp_port)
+					continue;
+				tcp_conn->tc_locaddr= ipaddr;
+			}
+		}
+		else
+			DBLOCK(1, printf("tcp_put_pkt: no TCP header\n"));
+		bf_afree(data);
+		return;
+	}
+	data->acc_linkC++;
+	ip_pack= data;
+	ip_pack= bf_align(ip_pack, ip_hdr_len, 4);
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_pack);
+	data= bf_delhead(data, ip_hdr_len);
+
+	/* Compute the checksum */
+	sum= tcp_pack_oneCsum(ip_hdr, data);
+
+	/* Extract the TCP header */
+	if (ip_datalen < TCP_MIN_HDR_SIZE)
+	{
+		DBLOCK(1, printf("truncated TCP header\n"));
+		bf_afree(ip_pack);
+		bf_afree(data);
+		return;
+	}
+	data= bf_packIffLess(data, TCP_MIN_HDR_SIZE);
+	tcp_hdr= (tcp_hdr_t *)ptr2acc_data(data);
+	tcp_hdr_len= (tcp_hdr->th_data_off & TH_DO_MASK) >> 2;
+		/* actualy (>> 4) << 2 */
+	if (ip_datalen < tcp_hdr_len || tcp_hdr_len < TCP_MIN_HDR_SIZE)
+	{
+		if (tcp_hdr_len < TCP_MIN_HDR_SIZE)
+		{
+			DBLOCK(1, printf("strange tcp header length %d\n",
+				tcp_hdr_len));
+		}
+		else
+		{
+			DBLOCK(1, printf("truncated TCP header\n"));
+		}
+		bf_afree(ip_pack);
+		bf_afree(data);
+		return;
+	}
+	data->acc_linkC++;
+	tcp_pack= data;
+	tcp_pack= bf_align(tcp_pack, tcp_hdr_len, 4);
+	tcp_hdr= (tcp_hdr_t *)ptr2acc_data(tcp_pack);
+	if (ip_datalen == tcp_hdr_len)
+	{
+		bf_afree(data);
+		data= NULL;
+	}
+	else
+		data= bf_delhead(data, tcp_hdr_len);
+	tcp_datalen= ip_datalen-tcp_hdr_len;
+
+	if ((u16_t)~sum)
+	{
+		DBLOCK(1, printf("checksum error in tcp packet\n");
+			printf("tcp_pack_oneCsum(...)= 0x%x length= %d\n", 
+			(u16_t)~sum, tcp_datalen);
+			printf("src ip_addr= "); writeIpAddr(ip_hdr->ih_src);
+			printf("\n"));
+		bf_afree(ip_pack);
+		bf_afree(tcp_pack);
+		bf_afree(data);
+		return;
+	}
+
+	srcaddr= ip_hdr->ih_src;
+	dstaddr= ip_hdr->ih_dst;
+	srcport= tcp_hdr->th_srcport;
+	dstport= tcp_hdr->th_dstport;
+	bits= srcaddr ^ dstaddr ^ srcport ^ dstport;
+	bits= (bits >> 16) ^ bits;
+	bits= (bits >> 8) ^ bits;
+	hash= ((bits >> TCP_CONN_HASH_SHIFT) ^ bits) & (TCP_CONN_HASH_NR-1);
+	conn_p= tcp_port->tp_conn_hash[hash];
+	if (conn_p[0]->tc_locport == dstport &&
+		conn_p[0]->tc_remport == srcport &&
+		conn_p[0]->tc_remaddr == srcaddr &&
+		conn_p[0]->tc_locaddr == dstaddr)
+	{
+		tcp_conn= conn_p[0];
+	}
+	else if (conn_p[1]->tc_locport == dstport &&
+		conn_p[1]->tc_remport == srcport &&
+		conn_p[1]->tc_remaddr == srcaddr &&
+		conn_p[1]->tc_locaddr == dstaddr)
+	{
+		tcp_conn= conn_p[1];
+		conn_p[1]= conn_p[0];
+		conn_p[0]= tcp_conn;
+	}
+	else if (conn_p[2]->tc_locport == dstport &&
+		conn_p[2]->tc_remport == srcport &&
+		conn_p[2]->tc_remaddr == srcaddr &&
+		conn_p[2]->tc_locaddr == dstaddr)
+	{
+		tcp_conn= conn_p[2];
+		conn_p[2]= conn_p[1];
+		conn_p[1]= conn_p[0];
+		conn_p[0]= tcp_conn;
+	}
+	else if (conn_p[3]->tc_locport == dstport &&
+		conn_p[3]->tc_remport == srcport &&
+		conn_p[3]->tc_remaddr == srcaddr &&
+		conn_p[3]->tc_locaddr == dstaddr)
+	{
+		tcp_conn= conn_p[3];
+		conn_p[3]= conn_p[2];
+		conn_p[2]= conn_p[1];
+		conn_p[1]= conn_p[0];
+		conn_p[0]= tcp_conn;
+	}
+	else
+		tcp_conn= NULL;
+	if ((tcp_conn != NULL && tcp_conn->tc_state == TCS_CLOSED) ||
+		(tcp_hdr->th_flags & THF_SYN))
+	{
+		tcp_conn= NULL;
+	}
+
+	if (tcp_conn == NULL)
+	{
+		tcp_conn= find_best_conn(ip_hdr, tcp_hdr);
+		if (!tcp_conn)
+		{
+			/* listen backlog hack */
+			bf_afree(ip_pack);
+			bf_afree(tcp_pack);
+			bf_afree(data);
+			return;
+		}
+		if (tcp_conn->tc_state != TCS_CLOSED)
+		{
+			conn_p[3]= conn_p[2];
+			conn_p[2]= conn_p[1];
+			conn_p[1]= conn_p[0];
+			conn_p[0]= tcp_conn;
+		}
+	}
+	assert(tcp_conn->tc_busy == 0);
+	tcp_conn->tc_busy++;
+	tcp_frag2conn(tcp_conn, ip_hdr, tcp_hdr, data, tcp_datalen);
+	tcp_conn->tc_busy--;
+	bf_afree(ip_pack);
+	bf_afree(tcp_pack);
+}
+
+
+PUBLIC int tcp_open (port, srfd, get_userdata, put_userdata, put_pkt,
+	select_res)
+int port;
+int srfd;
+get_userdata_t get_userdata;
+put_userdata_t put_userdata;
+put_pkt_t put_pkt;
+select_res_t select_res;
+{
+	int i, j;
+
+	tcp_fd_t *tcp_fd;
+
+	for (i=0; i<TCP_FD_NR && (tcp_fd_table[i].tf_flags & TFF_INUSE);
+		i++);
+	if (i>=TCP_FD_NR)
+	{
+		return EAGAIN;
+	}
+
+	tcp_fd= &tcp_fd_table[i];
+
+	tcp_fd->tf_flags= TFF_INUSE;
+	tcp_fd->tf_flags |= TFF_PUSH_DATA;
+
+	tcp_fd->tf_port= &tcp_port_table[port];
+	tcp_fd->tf_srfd= srfd;
+	tcp_fd->tf_tcpconf.nwtc_flags= TCP_DEF_CONF;
+	tcp_fd->tf_tcpconf.nwtc_remaddr= 0;
+	tcp_fd->tf_tcpconf.nwtc_remport= 0;
+	tcp_fd->tf_tcpopt.nwto_flags= TCP_DEF_OPT;
+	tcp_fd->tf_get_userdata= get_userdata;
+	tcp_fd->tf_put_userdata= put_userdata;
+	tcp_fd->tf_select_res= select_res;
+	tcp_fd->tf_conn= 0;
+	tcp_fd->tf_error= 0;
+	for (j= 0; j<TFL_LISTEN_MAX; j++)
+		tcp_fd->tf_listenq[j]= NULL;
+	return i;
+}
+
+/*
+tcp_ioctl
+*/
+PUBLIC int tcp_ioctl (fd, req)
+int fd;
+ioreq_t req;
+{
+	tcp_fd_t *tcp_fd;
+	tcp_port_t *tcp_port;
+	tcp_conn_t *tcp_conn;
+	nwio_tcpconf_t *tcp_conf;
+	nwio_tcpopt_t *tcp_opt;
+	tcp_cookie_t *cookiep;
+	acc_t *acc, *conf_acc, *opt_acc;
+	int result, *bytesp;
+	u8_t rndbits[RAND256_BUFSIZE];
+
+	tcp_fd= &tcp_fd_table[fd];
+
+	assert (tcp_fd->tf_flags & TFF_INUSE);
+
+	tcp_port= tcp_fd->tf_port;
+	tcp_fd->tf_flags |= TFF_IOCTL_IP;
+	tcp_fd->tf_ioreq= req;
+
+	if (tcp_port->tp_state != TPS_MAIN)
+	{
+		tcp_fd->tf_flags |= TFF_IOC_INIT_SP;
+		return NW_SUSPEND;
+	}
+
+	switch (req)
+	{
+	case NWIOSTCPCONF:
+		if ((tcp_fd->tf_flags & TFF_CONNECTED) ||
+			(tcp_fd->tf_flags & TFF_CONNECTING) ||
+			(tcp_fd->tf_flags & TFF_LISTENQ))
+		{
+			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+			reply_thr_get (tcp_fd, EISCONN, TRUE);
+			result= NW_OK;
+			break;
+		}
+		result= tcp_setconf(tcp_fd);
+		break;
+	case NWIOGTCPCONF:
+		conf_acc= bf_memreq(sizeof(*tcp_conf));
+assert (conf_acc->acc_length == sizeof(*tcp_conf));
+		tcp_conf= (nwio_tcpconf_t *)ptr2acc_data(conf_acc);
+
+		*tcp_conf= tcp_fd->tf_tcpconf;
+		if (tcp_fd->tf_flags & TFF_CONNECTED)
+		{
+			tcp_conn= tcp_fd->tf_conn;
+			tcp_conf->nwtc_locport= tcp_conn->tc_locport;
+			tcp_conf->nwtc_remaddr= tcp_conn->tc_remaddr;
+			tcp_conf->nwtc_remport= tcp_conn->tc_remport;
+		}
+		tcp_conf->nwtc_locaddr= tcp_fd->tf_port->tp_ipaddr;
+		result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
+			0, conf_acc, TRUE);
+		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+		reply_thr_put(tcp_fd, result, TRUE);
+		result= NW_OK;
+		break;
+	case NWIOSTCPOPT:
+		result= tcp_setopt(tcp_fd);
+		break;
+	case NWIOGTCPOPT:
+		opt_acc= bf_memreq(sizeof(*tcp_opt));
+		assert (opt_acc->acc_length == sizeof(*tcp_opt));
+		tcp_opt= (nwio_tcpopt_t *)ptr2acc_data(opt_acc);
+
+		*tcp_opt= tcp_fd->tf_tcpopt;
+		result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
+			0, opt_acc, TRUE);
+		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+		reply_thr_put(tcp_fd, result, TRUE);
+		result= NW_OK;
+		break;
+	case NWIOTCPCONN:
+		if (tcp_fd->tf_flags & TFF_CONNECTING)
+		{
+			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+			reply_thr_get (tcp_fd, EALREADY, TRUE);
+			result= NW_OK;
+			break;
+		}
+		if (tcp_fd->tf_flags & TFF_CONNECTED)
+		{
+			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+			reply_thr_get (tcp_fd, EISCONN, TRUE);
+			result= NW_OK;
+			break;
+		}
+		result= tcp_connect(tcp_fd);
+		if (result == NW_OK)
+			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+		break;
+	case NWIOTCPLISTEN:
+	case NWIOTCPLISTENQ:
+		if ((tcp_fd->tf_flags & TFF_CONNECTED) ||
+			(tcp_fd->tf_flags & TFF_LISTENQ) ||
+			(tcp_fd->tf_flags & TFF_CONNECTING))
+		{
+			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+			reply_thr_get (tcp_fd, EISCONN, TRUE);
+			result= NW_OK;
+			break;
+		}
+		result= tcp_listen(tcp_fd, (req == NWIOTCPLISTENQ));
+		break;
+	case NWIOTCPSHUTDOWN:
+		if (!(tcp_fd->tf_flags & TFF_CONNECTED))
+		{
+			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+			reply_thr_get (tcp_fd, ENOTCONN, TRUE);
+			result= NW_OK;
+			break;
+		}
+		tcp_fd->tf_flags |= TFF_IOCTL_IP;
+		tcp_fd->tf_ioreq= req;
+		tcp_conn= tcp_fd->tf_conn;
+
+		tcp_conn->tc_busy++;
+		tcp_fd_write(tcp_conn);
+		tcp_conn->tc_busy--;
+		tcp_conn_write(tcp_conn, 0);
+		if (!(tcp_fd->tf_flags & TFF_IOCTL_IP))
+			result= NW_OK;
+		else
+			result= NW_SUSPEND;
+		break;
+	case NWIOTCPPUSH:
+		if (!(tcp_fd->tf_flags & TFF_CONNECTED))
+		{
+			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+			reply_thr_get (tcp_fd, ENOTCONN, TRUE);
+			result= NW_OK;
+			break;
+		}
+		tcp_conn= tcp_fd->tf_conn;
+		tcp_conn->tc_SND_PSH= tcp_conn->tc_SND_NXT;
+		tcp_conn->tc_flags &= ~TCF_NO_PUSH;
+		tcp_conn->tc_flags |= TCF_PUSH_NOW;
+
+		/* Start the timer (if necessary) */
+		if (tcp_conn->tc_SND_TRM == tcp_conn->tc_SND_UNA)
+			tcp_set_send_timer(tcp_conn);
+
+		tcp_conn_write(tcp_conn, 0);
+		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+		reply_thr_get (tcp_fd, NW_OK, TRUE);
+		result= NW_OK;
+		break;
+	case NWIOGTCPCOOKIE:
+		if (!(tcp_fd->tf_flags & TFF_COOKIE))
+		{
+			tcp_fd->tf_cookie.tc_ref= fd;
+			rand256(rndbits);
+			assert(sizeof(tcp_fd->tf_cookie.tc_secret) <=
+				RAND256_BUFSIZE);
+			memcpy(tcp_fd->tf_cookie.tc_secret, 
+				rndbits, sizeof(tcp_fd->tf_cookie.tc_secret));
+			tcp_fd->tf_flags |= TFF_COOKIE;
+		}
+		acc= bf_memreq(sizeof(*cookiep));
+		cookiep= (tcp_cookie_t *)ptr2acc_data(acc);
+
+		*cookiep= tcp_fd->tf_cookie;
+		result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
+			0, acc, TRUE);
+		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+		reply_thr_put(tcp_fd, result, TRUE);
+		result= NW_OK;
+		break;
+	case NWIOTCPACCEPTTO:
+		result= tcp_acceptto(tcp_fd);
+		break;
+	case FIONREAD:
+		acc= bf_memreq(sizeof(*bytesp));
+		bytesp= (int *)ptr2acc_data(acc);
+		tcp_bytesavailable(tcp_fd, bytesp);
+		result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
+			0, acc, TRUE);
+		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+		reply_thr_put(tcp_fd, result, TRUE);
+		result= NW_OK;
+		break;
+
+	case NWIOTCPGERROR:
+		acc= bf_memreq(sizeof(*bytesp));
+		bytesp= (int *)ptr2acc_data(acc);
+		*bytesp= -tcp_fd->tf_error;	/* Errors are positive in
+						 * user space.
+						 */
+		tcp_fd->tf_error= 0;
+		result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
+			0, acc, TRUE);
+		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+		reply_thr_put(tcp_fd, result, TRUE);
+		result= NW_OK;
+		break;
+
+	default:
+		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+		reply_thr_get(tcp_fd, EBADIOCTL, TRUE);
+		result= NW_OK;
+		break;
+	}
+	return result;
+}
+
+
+/*
+tcp_setconf
+*/
+
+PRIVATE int tcp_setconf(tcp_fd)
+tcp_fd_t *tcp_fd;
+{
+	nwio_tcpconf_t *tcpconf;
+	nwio_tcpconf_t oldconf, newconf;
+	acc_t *data;
+	tcp_fd_t *fd_ptr;
+	unsigned int new_en_flags, new_di_flags,
+		old_en_flags, old_di_flags, all_flags, flags;
+	int i;
+
+	data= (*tcp_fd->tf_get_userdata)
+		(tcp_fd->tf_srfd, 0,
+		sizeof(nwio_tcpconf_t), TRUE);
+
+	if (!data)
+		return EFAULT;
+
+	data= bf_packIffLess(data, sizeof(nwio_tcpconf_t));
+assert (data->acc_length == sizeof(nwio_tcpconf_t));
+
+	tcpconf= (nwio_tcpconf_t *)ptr2acc_data(data);
+	oldconf= tcp_fd->tf_tcpconf;
+	newconf= *tcpconf;
+
+	old_en_flags= oldconf.nwtc_flags & 0xffff;
+	old_di_flags= (oldconf.nwtc_flags >> 16) &
+		0xffff;
+	new_en_flags= newconf.nwtc_flags & 0xffff;
+	new_di_flags= (newconf.nwtc_flags >> 16) &
+		0xffff;
+	if (new_en_flags & new_di_flags)
+	{
+		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+		reply_thr_get(tcp_fd, EBADMODE, TRUE);
+		bf_afree(data);
+		return NW_OK;
+	}
+
+	/* NWTC_ACC_MASK */
+	if (new_di_flags & NWTC_ACC_MASK)
+	{
+		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+		reply_thr_get(tcp_fd, EBADMODE, TRUE);
+		bf_afree(data);
+		return NW_OK;
+		/* access modes can't be disabled */
+	}
+
+	if (!(new_en_flags & NWTC_ACC_MASK))
+		new_en_flags |= (old_en_flags & NWTC_ACC_MASK);
+	
+	/* NWTC_LOCPORT_MASK */
+	if (new_di_flags & NWTC_LOCPORT_MASK)
+	{
+		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+		reply_thr_get(tcp_fd, EBADMODE, TRUE);
+		bf_afree(data);
+		return NW_OK;
+		/* the loc ports can't be disabled */
+	}
+	if (!(new_en_flags & NWTC_LOCPORT_MASK))
+	{
+		new_en_flags |= (old_en_flags &
+			NWTC_LOCPORT_MASK);
+		newconf.nwtc_locport= oldconf.nwtc_locport;
+	}
+	else if ((new_en_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SEL)
+	{
+		newconf.nwtc_locport= find_unused_port(tcp_fd-
+			tcp_fd_table);
+	}
+	else if ((new_en_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET)
+	{
+		if (!newconf.nwtc_locport)
+		{
+			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+			reply_thr_get(tcp_fd, EBADMODE, TRUE);
+			bf_afree(data);
+			return NW_OK;
+		}
+	}
+	
+	/* NWTC_REMADDR_MASK */
+	if (!((new_en_flags | new_di_flags) &
+		NWTC_REMADDR_MASK))
+	{
+		new_en_flags |= (old_en_flags &
+			NWTC_REMADDR_MASK);
+		new_di_flags |= (old_di_flags &
+			NWTC_REMADDR_MASK);
+		newconf.nwtc_remaddr= oldconf.nwtc_remaddr;
+	}
+	else if (new_en_flags & NWTC_SET_RA)
+	{
+		if (!newconf.nwtc_remaddr)
+		{
+			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+			reply_thr_get(tcp_fd, EBADMODE, TRUE);
+			bf_afree(data);
+			return NW_OK;
+		}
+	}
+	else
+	{
+assert (new_di_flags & NWTC_REMADDR_MASK);
+		newconf.nwtc_remaddr= 0;
+	}
+
+	/* NWTC_REMPORT_MASK */
+	if (!((new_en_flags | new_di_flags) & NWTC_REMPORT_MASK))
+	{
+		new_en_flags |= (old_en_flags &
+			NWTC_REMPORT_MASK);
+		new_di_flags |= (old_di_flags &
+			NWTC_REMPORT_MASK);
+		newconf.nwtc_remport=
+			oldconf.nwtc_remport;
+	}
+	else if (new_en_flags & NWTC_SET_RP)
+	{
+		if (!newconf.nwtc_remport)
+		{
+			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+			reply_thr_get(tcp_fd, EBADMODE, TRUE);
+			bf_afree(data);
+			return NW_OK;
+		}
+	}
+	else
+	{
+assert (new_di_flags & NWTC_REMPORT_MASK);
+		newconf.nwtc_remport= 0;
+	}
+
+	newconf.nwtc_flags= ((unsigned long)new_di_flags
+		<< 16) | new_en_flags;
+	all_flags= new_en_flags | new_di_flags;
+
+	/* check the access modes */
+	if ((all_flags & NWTC_LOCPORT_MASK) != NWTC_LP_UNSET)
+	{
+		for (i=0, fd_ptr= tcp_fd_table; i<TCP_FD_NR; i++, fd_ptr++)
+		{
+			if (fd_ptr == tcp_fd)
+				continue;
+			if (!(fd_ptr->tf_flags & TFF_INUSE))
+				continue;
+			if (fd_ptr->tf_port != tcp_fd->tf_port)
+				continue;
+			flags= fd_ptr->tf_tcpconf.nwtc_flags;
+			if ((flags & NWTC_LOCPORT_MASK) == NWTC_LP_UNSET)
+				continue;
+			if (fd_ptr->tf_tcpconf.nwtc_locport !=
+				newconf.nwtc_locport)
+				continue;
+			if ((flags & NWTC_ACC_MASK) != (all_flags  &
+				NWTC_ACC_MASK) ||
+				(all_flags & NWTC_ACC_MASK) == NWTC_EXCL)
+			{
+				tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+				reply_thr_get(tcp_fd, EADDRINUSE, TRUE);
+				bf_afree(data);
+				return NW_OK;
+			}
+		}
+	}
+				
+	tcp_fd->tf_tcpconf= newconf;
+
+	if ((all_flags & NWTC_ACC_MASK) &&
+		((all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET ||
+		(all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SEL) &&
+		(all_flags & NWTC_REMADDR_MASK) &&
+		(all_flags & NWTC_REMPORT_MASK))
+		tcp_fd->tf_flags |= TFF_CONF_SET;
+	else
+	{
+		tcp_fd->tf_flags &= ~TFF_CONF_SET;
+	}
+	bf_afree(data);
+	tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+	reply_thr_get(tcp_fd, NW_OK, TRUE);
+	return NW_OK;
+}
+
+
+/*
+tcp_setopt
+*/
+
+PRIVATE int tcp_setopt(tcp_fd)
+tcp_fd_t *tcp_fd;
+{
+	nwio_tcpopt_t *tcpopt;
+	nwio_tcpopt_t oldopt, newopt;
+	acc_t *data;
+	unsigned int new_en_flags, new_di_flags,
+		old_en_flags, old_di_flags;
+
+	data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0,
+		sizeof(nwio_tcpopt_t), TRUE);
+
+	if (!data)
+		return EFAULT;
+
+	data= bf_packIffLess(data, sizeof(nwio_tcpopt_t));
+assert (data->acc_length == sizeof(nwio_tcpopt_t));
+
+	tcpopt= (nwio_tcpopt_t *)ptr2acc_data(data);
+	oldopt= tcp_fd->tf_tcpopt;
+	newopt= *tcpopt;
+
+	old_en_flags= oldopt.nwto_flags & 0xffff;
+	old_di_flags= (oldopt.nwto_flags >> 16) & 0xffff;
+	new_en_flags= newopt.nwto_flags & 0xffff;
+	new_di_flags= (newopt.nwto_flags >> 16) & 0xffff;
+	if (new_en_flags & new_di_flags)
+	{
+		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+		reply_thr_get(tcp_fd, EBADMODE, TRUE);
+		return NW_OK;
+	}
+
+	/* NWTO_SND_URG_MASK */
+	if (!((new_en_flags | new_di_flags) & NWTO_SND_URG_MASK))
+	{
+		new_en_flags |= (old_en_flags & NWTO_SND_URG_MASK);
+		new_di_flags |= (old_di_flags & NWTO_SND_URG_MASK);
+	}
+
+	/* NWTO_RCV_URG_MASK */
+	if (!((new_en_flags | new_di_flags) & NWTO_RCV_URG_MASK))
+	{
+		new_en_flags |= (old_en_flags & NWTO_RCV_URG_MASK);
+		new_di_flags |= (old_di_flags & NWTO_RCV_URG_MASK);
+	}
+
+	/* NWTO_BSD_URG_MASK */
+	if (!((new_en_flags | new_di_flags) & NWTO_BSD_URG_MASK))
+	{
+		new_en_flags |= (old_en_flags & NWTO_BSD_URG_MASK);
+		new_di_flags |= (old_di_flags & NWTO_BSD_URG_MASK);
+	}
+	else
+	{
+		if (tcp_fd->tf_conn == NULL)
+		{
+			bf_afree(data);
+			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+			reply_thr_get(tcp_fd, EINVAL, TRUE);
+			return NW_OK;
+		}
+	}
+
+	/* NWTO_DEL_RST_MASK */
+	if (!((new_en_flags | new_di_flags) & NWTO_DEL_RST_MASK))
+	{
+		new_en_flags |= (old_en_flags & NWTO_DEL_RST_MASK);
+		new_di_flags |= (old_di_flags & NWTO_DEL_RST_MASK);
+	}
+
+	/* NWTO_BULK_MASK */
+	if (!((new_en_flags | new_di_flags) & NWTO_BULK_MASK))
+	{
+		new_en_flags |= (old_en_flags & NWTO_BULK_MASK);
+		new_di_flags |= (old_di_flags & NWTO_BULK_MASK);
+	}
+
+	newopt.nwto_flags= ((unsigned long)new_di_flags << 16) |
+		new_en_flags;
+	tcp_fd->tf_tcpopt= newopt;
+	if (newopt.nwto_flags & NWTO_SND_URG)
+		tcp_fd->tf_flags |= TFF_WR_URG;
+	else
+		tcp_fd->tf_flags &= ~TFF_WR_URG;
+
+	if (newopt.nwto_flags & NWTO_RCV_URG)
+		tcp_fd->tf_flags |= TFF_RECV_URG;
+	else
+		tcp_fd->tf_flags &= ~TFF_RECV_URG;
+
+	if (tcp_fd->tf_conn)
+	{
+		if (newopt.nwto_flags & NWTO_BSD_URG)
+			tcp_fd->tf_conn->tc_flags |= TCF_BSD_URG;
+		else
+			tcp_fd->tf_conn->tc_flags &= ~TCF_BSD_URG;
+	}
+
+	if (newopt.nwto_flags & NWTO_DEL_RST)
+		tcp_fd->tf_flags |= TFF_DEL_RST;
+	else
+		tcp_fd->tf_flags &= ~TFF_DEL_RST;
+
+	if (newopt.nwto_flags & NWTO_BULK)
+		tcp_fd->tf_flags &= ~TFF_PUSH_DATA;
+	else
+		tcp_fd->tf_flags |= TFF_PUSH_DATA;
+
+	bf_afree(data);
+	tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+	reply_thr_get(tcp_fd, NW_OK, TRUE);
+	return NW_OK;
+}
+
+
+PRIVATE tcpport_t find_unused_port(fd)
+int fd;
+{
+	tcpport_t port, nw_port;
+
+	for (port= 0x8000+fd; port < 0xffff-TCP_FD_NR; port+= TCP_FD_NR)
+	{
+		nw_port= htons(port);
+		if (is_unused_port(nw_port))
+			return nw_port;
+	}
+	for (port= 0x8000; port < 0xffff; port++)
+	{
+		nw_port= htons(port);
+		if (is_unused_port(nw_port))
+			return nw_port;
+	}
+	ip_panic(( "unable to find unused port (shouldn't occur)" ));
+	return 0;
+}
+
+PRIVATE int is_unused_port(port)
+tcpport_t port;
+{
+	int i;
+	tcp_fd_t *tcp_fd;
+	tcp_conn_t *tcp_conn;
+
+	for (i= 0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++,
+		tcp_fd++)
+	{
+		if (!(tcp_fd->tf_flags & TFF_CONF_SET))
+			continue;
+		if (tcp_fd->tf_tcpconf.nwtc_locport == port)
+			return FALSE;
+	}
+	for (i= tcp_conf_nr, tcp_conn= tcp_conn_table+i;
+		i<TCP_CONN_NR; i++, tcp_conn++)
+		/* the first tcp_conf_nr ports are special */
+	{
+		if (!(tcp_conn->tc_flags & TCF_INUSE))
+			continue;
+		if (tcp_conn->tc_locport == port)
+			return FALSE;
+	}
+	return TRUE;
+}
+
+PRIVATE int reply_thr_put(tcp_fd, reply, for_ioctl)
+tcp_fd_t *tcp_fd;
+int reply;
+int for_ioctl;
+{
+	assert (tcp_fd);
+
+	return (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd, reply,
+		(acc_t *)0, for_ioctl);
+}
+
+PRIVATE void reply_thr_get(tcp_fd, reply, for_ioctl)
+tcp_fd_t *tcp_fd;
+int reply;
+int for_ioctl;
+{
+	acc_t *result;
+
+	result= (*tcp_fd->tf_get_userdata)(tcp_fd->tf_srfd, reply,
+		(size_t)0, for_ioctl);
+	assert (!result);
+}
+
+PUBLIC int tcp_su4listen(tcp_fd, tcp_conn, do_listenq)
+tcp_fd_t *tcp_fd;
+tcp_conn_t *tcp_conn;
+int do_listenq;
+{
+	tcp_conn->tc_locport= tcp_fd->tf_tcpconf.nwtc_locport;
+	tcp_conn->tc_locaddr= tcp_fd->tf_port->tp_ipaddr;
+	if (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP)
+		tcp_conn->tc_remport= tcp_fd->tf_tcpconf.nwtc_remport;
+	else
+		tcp_conn->tc_remport= 0;
+	if (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA)
+		tcp_conn->tc_remaddr= tcp_fd->tf_tcpconf.nwtc_remaddr;
+	else
+		tcp_conn->tc_remaddr= 0;
+
+	tcp_setup_conn(tcp_fd->tf_port, tcp_conn);
+	tcp_conn->tc_fd= tcp_fd;
+	tcp_conn->tc_connInprogress= 1;
+	tcp_conn->tc_orglisten= TRUE;
+	tcp_conn->tc_state= TCS_LISTEN;
+	tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_LISTEN;
+	if (do_listenq)
+	{
+		tcp_fd->tf_flags |= TFF_LISTENQ;
+		tcp_reply_ioctl(tcp_fd, NW_OK);
+		return NW_OK;
+	}
+	return NW_SUSPEND;
+}
+
+/*
+find_empty_conn
+
+This function returns a connection that is not inuse.
+This includes connections that are never used, and connections without a
+user that are not used for a while.
+*/
+
+PRIVATE tcp_conn_t *find_empty_conn()
+{
+	int i;
+	tcp_conn_t *tcp_conn;
+
+	for (i=tcp_conf_nr, tcp_conn= tcp_conn_table+i;
+		i<TCP_CONN_NR; i++, tcp_conn++)
+		/* the first tcp_conf_nr connections are reserved for
+		 * RSTs
+		 */
+	{
+		if (tcp_conn->tc_flags == TCF_EMPTY)
+		{
+			tcp_conn->tc_connInprogress= 0;
+			tcp_conn->tc_fd= NULL;
+			return tcp_conn;
+		}
+		if (tcp_conn->tc_fd)
+			continue;
+		if (tcp_conn->tc_senddis > get_time())
+			continue;
+		if (tcp_conn->tc_state != TCS_CLOSED)
+		{
+			 tcp_close_connection (tcp_conn, ENOCONN);
+		}
+		tcp_conn->tc_flags= 0;
+		return tcp_conn;
+	}
+	return NULL;
+}
+
+
+/*
+find_conn_entry
+
+This function return a connection matching locport, locaddr, remport, remaddr.
+If no such connection exists NULL is returned.
+If a connection exists without mainuser it is closed.
+*/
+
+PRIVATE tcp_conn_t *find_conn_entry(locport, locaddr, remport, remaddr)
+tcpport_t locport;
+ipaddr_t locaddr;
+tcpport_t remport;
+ipaddr_t remaddr;
+{
+	tcp_conn_t *tcp_conn;
+	int i, state;
+
+	assert(remport);
+	assert(remaddr);
+	for (i=tcp_conf_nr, tcp_conn= tcp_conn_table+i; i<TCP_CONN_NR;
+		i++, tcp_conn++)
+		/* the first tcp_conf_nr connections are reserved for
+			RSTs */
+	{
+		if (tcp_conn->tc_flags == TCF_EMPTY)
+			continue;
+		if (tcp_conn->tc_locport != locport ||
+			tcp_conn->tc_locaddr != locaddr ||
+			tcp_conn->tc_remport != remport ||
+			tcp_conn->tc_remaddr != remaddr)
+			continue;
+		if (tcp_conn->tc_fd)
+			return tcp_conn;
+		state= tcp_conn->tc_state;
+		if (state != TCS_CLOSED)
+		{
+			tcp_close_connection(tcp_conn, ENOCONN);
+		}
+		return tcp_conn;
+	}
+	return NULL;
+}
+
+PRIVATE void read_ip_packets(tcp_port)
+tcp_port_t *tcp_port;
+{
+	int result;
+
+	do
+	{
+		tcp_port->tp_flags |= TPF_READ_IP;
+		result= ip_read(tcp_port->tp_ipfd, TCP_MAX_DATAGRAM);
+		if (result == NW_SUSPEND)
+		{
+			tcp_port->tp_flags |= TPF_READ_SP;
+			return;
+		}
+		assert(result == NW_OK);
+		tcp_port->tp_flags &= ~TPF_READ_IP;
+	} while(!(tcp_port->tp_flags & TPF_READ_IP));
+}
+
+/*
+find_best_conn
+*/
+
+PRIVATE tcp_conn_t *find_best_conn(ip_hdr, tcp_hdr)
+ip_hdr_t *ip_hdr;
+tcp_hdr_t *tcp_hdr;
+{
+	
+	int best_level, new_level;
+	tcp_conn_t *best_conn, *listen_conn, *tcp_conn;
+	tcp_fd_t *tcp_fd;
+	int i;
+	ipaddr_t locaddr;
+	ipaddr_t remaddr;
+	tcpport_t locport;
+	tcpport_t remport;
+
+	locaddr= ip_hdr->ih_dst;
+	remaddr= ip_hdr->ih_src;
+	locport= tcp_hdr->th_dstport;
+	remport= tcp_hdr->th_srcport;
+	if (!remport)	/* This can interfere with a listen, so we reject it
+			 * by clearing the requested port 
+			 */
+		locport= 0;
+		
+	best_level= 0;
+	best_conn= NULL;
+	listen_conn= NULL;
+	for (i= tcp_conf_nr, tcp_conn= tcp_conn_table+i;
+		i<TCP_CONN_NR; i++, tcp_conn++)
+		/* the first tcp_conf_nr connections are reserved for
+			RSTs */
+	{
+		if (!(tcp_conn->tc_flags & TCF_INUSE))
+			continue;
+		/* First fast check for open connections. */
+		if (tcp_conn->tc_locaddr == locaddr && 
+			tcp_conn->tc_locport == locport &&
+			tcp_conn->tc_remport == remport &&
+			tcp_conn->tc_remaddr == remaddr &&
+			tcp_conn->tc_fd)
+		{
+			return tcp_conn;
+		}
+
+		/* Now check for listens and abandoned connections. */
+		if (tcp_conn->tc_locaddr != locaddr)
+		{
+			continue;
+		}
+		new_level= 0;
+		if (tcp_conn->tc_locport)
+		{
+			if (tcp_conn->tc_locport != locport)
+			{
+				continue;
+			}
+			new_level += 4;
+		}
+		if (tcp_conn->tc_remport)
+		{
+			if (tcp_conn->tc_remport != remport)
+			{
+				continue;
+			}
+			new_level += 1;
+		}
+		if (tcp_conn->tc_remaddr)
+		{
+			if (tcp_conn->tc_remaddr != remaddr)
+			{
+				continue;
+			}
+			new_level += 2;
+		}
+		if (new_level<best_level)
+			continue;
+		if (new_level != 7 && tcp_conn->tc_state != TCS_LISTEN)
+			continue;
+		if (new_level == 7)
+			/* We found an abandoned connection */
+		{
+		 	assert(!tcp_conn->tc_fd);
+			if (best_conn && tcp_Lmod4G(tcp_conn->tc_ISS,
+				best_conn->tc_ISS))
+			{
+				continue;
+			}
+			best_conn= tcp_conn;
+			continue;
+		}
+		if (!(tcp_hdr->th_flags & THF_SYN))
+			continue;
+		best_level= new_level;
+		listen_conn= tcp_conn;
+		assert(listen_conn->tc_fd != NULL);
+	}
+
+	if (listen_conn && listen_conn->tc_fd->tf_flags & TFF_LISTENQ &&
+		listen_conn->tc_fd->tf_conn == listen_conn)
+	{
+		/* Special processing for listen queues. Only accept the 
+		 * connection if there is empty space in the queue and
+		 * there are empty connections as well.
+		 */
+		listen_conn= new_conn_for_queue(listen_conn->tc_fd);
+	}
+	
+	if (!best_conn && !listen_conn)
+	{
+		if ((tcp_hdr->th_flags & THF_SYN) &&
+			maybe_listen(locaddr, locport, remaddr, remport))
+		{
+			/* Quick hack to implement listen back logs:
+			 * if a SYN arrives and there is no listen waiting
+			 * for that packet, then no reply is sent.
+			 */
+			return NULL;
+		}
+
+		for (i=0, tcp_conn= tcp_conn_table; i<tcp_conf_nr;
+			i++, tcp_conn++)
+		{
+			/* find valid port to send RST */
+			if ((tcp_conn->tc_flags & TCF_INUSE) &&
+				tcp_conn->tc_locaddr==locaddr)
+			{
+				break;
+			}
+		}
+		assert (tcp_conn);
+		assert (tcp_conn->tc_state == TCS_CLOSED);
+
+		tcp_conn->tc_locport= locport;
+		tcp_conn->tc_locaddr= locaddr;
+		tcp_conn->tc_remport= remport;
+		tcp_conn->tc_remaddr= remaddr;
+		assert (!tcp_conn->tc_fd);
+		return tcp_conn;
+	}
+
+	if (best_conn)
+	{
+		if (!listen_conn)
+		{
+			assert(!best_conn->tc_fd);
+			return best_conn;
+		}
+
+		assert(listen_conn->tc_connInprogress);
+		tcp_fd= listen_conn->tc_fd;
+		assert(tcp_fd);
+		assert((tcp_fd->tf_flags & TFF_LISTENQ) ||
+			 tcp_fd->tf_conn == listen_conn);
+
+		if (best_conn->tc_state != TCS_CLOSED)
+			tcp_close_connection(best_conn, ENOCONN);
+
+		listen_conn->tc_ISS= best_conn->tc_ISS;
+		if (best_conn->tc_senddis > listen_conn->tc_senddis)
+			listen_conn->tc_senddis= best_conn->tc_senddis;
+		return listen_conn;
+	}
+	assert (listen_conn);
+	return listen_conn;
+}
+
+/*
+new_conn_for_queue
+*/
+PRIVATE tcp_conn_t *new_conn_for_queue(tcp_fd)
+tcp_fd_t *tcp_fd;
+{
+	int i;
+	tcp_conn_t *tcp_conn;
+
+	assert(tcp_fd->tf_flags & TFF_LISTENQ);
+
+	for (i= 0; i<TFL_LISTEN_MAX; i++)
+	{
+		if (tcp_fd->tf_listenq[i] == NULL)
+			break;
+	}
+	if (i >= TFL_LISTEN_MAX)
+		return NULL;
+
+	tcp_conn= find_empty_conn();
+	if (!tcp_conn)
+		return NULL;
+	tcp_fd->tf_listenq[i]= tcp_conn;
+	(void)tcp_su4listen(tcp_fd, tcp_conn, 0 /* !do_listenq */);
+	return tcp_conn;
+}
+
+/*
+maybe_listen
+*/
+PRIVATE int maybe_listen(locaddr, locport, remaddr, remport)
+ipaddr_t locaddr;
+tcpport_t locport;
+ipaddr_t remaddr;
+tcpport_t remport;
+{
+	int i;
+	tcp_conn_t *tcp_conn;
+	tcp_fd_t *fd;
+
+	for (i= tcp_conf_nr, tcp_conn= tcp_conn_table+i;
+		i<TCP_CONN_NR; i++, tcp_conn++)
+	{
+		if (!(tcp_conn->tc_flags & TCF_INUSE))
+			continue;
+
+		if (tcp_conn->tc_locaddr != locaddr)
+		{
+			continue;
+		}
+		if (tcp_conn->tc_locport != locport )
+		{
+			continue;
+		}
+		if (!tcp_conn->tc_orglisten)
+			continue;
+		fd= tcp_conn->tc_fd;
+		if (!fd)
+			continue;
+		if ((fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP) &&
+			tcp_conn->tc_remport != remport)
+		{
+			continue;
+		}
+		if ((fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA) &&
+			tcp_conn->tc_remaddr != remaddr)
+		{
+			continue;
+		}
+		if (!(fd->tf_flags & TFF_DEL_RST))
+			continue;
+		return 1;
+
+	}
+	return 0;
+}
+
+
+PUBLIC void tcp_reply_ioctl(tcp_fd, reply)
+tcp_fd_t *tcp_fd;
+int reply;
+{
+	assert (tcp_fd->tf_flags & TFF_IOCTL_IP);
+	assert (tcp_fd->tf_ioreq == NWIOTCPSHUTDOWN ||
+		tcp_fd->tf_ioreq == NWIOTCPLISTEN ||
+		tcp_fd->tf_ioreq == NWIOTCPLISTENQ ||
+		tcp_fd->tf_ioreq == NWIOTCPACCEPTTO ||
+		tcp_fd->tf_ioreq == NWIOTCPCONN);
+	
+	tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+	reply_thr_get (tcp_fd, reply, TRUE);
+}
+
+PUBLIC void tcp_reply_write(tcp_fd, reply)
+tcp_fd_t *tcp_fd;
+size_t reply;
+{
+	assert (tcp_fd->tf_flags & TFF_WRITE_IP);
+
+	tcp_fd->tf_flags &= ~TFF_WRITE_IP;
+	reply_thr_get (tcp_fd, reply, FALSE);
+}
+
+PUBLIC void tcp_reply_read(tcp_fd, reply)
+tcp_fd_t *tcp_fd;
+size_t reply;
+{
+	assert (tcp_fd->tf_flags & TFF_READ_IP);
+
+	tcp_fd->tf_flags &= ~TFF_READ_IP;
+	reply_thr_put (tcp_fd, reply, FALSE);
+}
+
+PUBLIC int tcp_write(fd, count)
+int fd;
+size_t count;
+{
+	tcp_fd_t *tcp_fd;
+	tcp_conn_t *tcp_conn;
+
+	tcp_fd= &tcp_fd_table[fd];
+
+	assert (tcp_fd->tf_flags & TFF_INUSE);
+
+	if (!(tcp_fd->tf_flags & TFF_CONNECTED))
+	{
+		reply_thr_get (tcp_fd, ENOTCONN, FALSE);
+		return NW_OK;
+	}
+	tcp_conn= tcp_fd->tf_conn;
+	if (tcp_conn->tc_state == TCS_CLOSED)
+	{
+		reply_thr_get(tcp_fd, tcp_conn->tc_error, FALSE);
+		return NW_OK;
+	}
+	if (tcp_conn->tc_flags & TCF_FIN_SENT)
+	{
+		reply_thr_get (tcp_fd, ESHUTDOWN, FALSE);
+		return NW_OK;
+	}
+
+	tcp_fd->tf_flags |= TFF_WRITE_IP;
+	tcp_fd->tf_write_offset= 0;
+	tcp_fd->tf_write_count= count;
+
+	/* New data may cause a segment to be sent. Clear PUSH_NOW
+	 * from last NWIOTCPPUSH ioctl.
+	 */
+	tcp_conn->tc_flags &= ~(TCF_NO_PUSH|TCF_PUSH_NOW);
+
+	/* Start the timer (if necessary) */
+	if (tcp_conn->tc_SND_TRM == tcp_conn->tc_SND_UNA)
+		tcp_set_send_timer(tcp_conn);
+
+	assert(tcp_conn->tc_busy == 0);
+	tcp_conn->tc_busy++;
+	tcp_fd_write(tcp_conn);
+	tcp_conn->tc_busy--;
+	tcp_conn_write(tcp_conn, 0);
+
+	if (!(tcp_fd->tf_flags & TFF_WRITE_IP))
+		return NW_OK;
+	else
+		return NW_SUSPEND;
+}
+
+PUBLIC int
+tcp_read(fd, count)
+int fd;
+size_t count;
+{
+	tcp_fd_t *tcp_fd;
+	tcp_conn_t *tcp_conn;
+
+	tcp_fd= &tcp_fd_table[fd];
+
+	assert (tcp_fd->tf_flags & TFF_INUSE);
+
+	if (!(tcp_fd->tf_flags & TFF_CONNECTED))
+	{
+		reply_thr_put (tcp_fd, ENOTCONN, FALSE);
+		return NW_OK;
+	}
+	tcp_conn= tcp_fd->tf_conn;
+
+	tcp_fd->tf_flags |= TFF_READ_IP;
+	tcp_fd->tf_read_offset= 0;
+	tcp_fd->tf_read_count= count;
+
+	assert(tcp_conn->tc_busy == 0);
+	tcp_conn->tc_busy++;
+	tcp_fd_read(tcp_conn, 0);
+	tcp_conn->tc_busy--;
+	if (!(tcp_fd->tf_flags & TFF_READ_IP))
+		return NW_OK;
+	else
+		return NW_SUSPEND;
+}
+
+/*
+tcp_restart_connect
+
+reply the success or failure of a connect to the user.
+*/
+
+
+PUBLIC void tcp_restart_connect(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	tcp_fd_t *tcp_fd;
+	int reply;
+
+	assert(tcp_conn->tc_connInprogress);
+	tcp_conn->tc_connInprogress= 0;
+
+	tcp_fd= tcp_conn->tc_fd;
+	assert(tcp_fd);
+	if (tcp_fd->tf_flags & TFF_LISTENQ)
+	{
+		/* Special code for listen queues */
+		assert(tcp_conn->tc_state != TCS_CLOSED);
+
+		/* Reply for select */
+		if ((tcp_fd->tf_flags & TFF_SEL_READ) &&
+			tcp_fd->tf_select_res)
+		{
+			tcp_fd->tf_flags &= ~TFF_SEL_READ;
+			tcp_fd->tf_select_res(tcp_fd->tf_srfd,
+				SR_SELECT_READ);
+		}
+
+		/* Reply for acceptto */
+		if (tcp_fd->tf_flags & TFF_IOCTL_IP)
+			(void) tcp_acceptto(tcp_fd);
+
+		return;
+	}
+
+	if (tcp_conn->tc_state == TCS_CLOSED)
+	{
+		reply= tcp_conn->tc_error;
+		assert(tcp_conn->tc_fd == tcp_fd);
+		tcp_fd->tf_conn= NULL;
+		tcp_conn->tc_fd= NULL;
+		tcp_fd->tf_error= reply;
+	}
+	else
+	{
+		tcp_fd->tf_flags |= TFF_CONNECTED;
+		reply= NW_OK;
+	}
+
+	if (tcp_fd->tf_flags & TFF_CONNECTING)
+	{
+		/* Special code for asynchronous connects */
+		tcp_fd->tf_flags &= ~TFF_CONNECTING;
+
+		/* Reply for select */
+		if ((tcp_fd->tf_flags & TFF_SEL_WRITE) &&
+			tcp_fd->tf_select_res)
+		{
+			tcp_fd->tf_flags &= ~TFF_SEL_WRITE;
+			tcp_fd->tf_select_res(tcp_fd->tf_srfd,
+				SR_SELECT_WRITE);
+		}
+
+		return;
+	}
+
+	assert(tcp_fd->tf_flags & TFF_IOCTL_IP);
+	assert(tcp_fd->tf_ioreq == NWIOTCPLISTEN ||
+		tcp_fd->tf_ioreq == NWIOTCPCONN);
+
+	tcp_reply_ioctl (tcp_fd, reply);
+}
+
+/*
+tcp_close
+*/
+
+PUBLIC void tcp_close(fd)
+int fd;
+{
+	int i;
+	tcp_fd_t *tcp_fd;
+	tcp_conn_t *tcp_conn;
+
+	tcp_fd= &tcp_fd_table[fd];
+
+	assert (tcp_fd->tf_flags & TFF_INUSE);
+	assert (!(tcp_fd->tf_flags &
+		(TFF_IOCTL_IP|TFF_READ_IP|TFF_WRITE_IP)));
+
+	if (tcp_fd->tf_flags & TFF_LISTENQ)
+	{
+		/* Special code for listen queues */
+		for (i= 0; i<TFL_LISTEN_MAX; i++)
+		{
+			tcp_conn= tcp_fd->tf_listenq[i];
+			if (!tcp_conn)
+				continue;
+
+			tcp_fd->tf_listenq[i]= NULL;
+			assert(tcp_conn->tc_fd == tcp_fd);
+			tcp_conn->tc_fd= NULL;
+
+			if (tcp_conn->tc_connInprogress)
+			{
+				tcp_conn->tc_connInprogress= 0;
+				tcp_close_connection(tcp_conn, ENOCONN);
+				continue;
+			}
+
+			tcp_shutdown (tcp_conn);
+			if (tcp_conn->tc_state == TCS_ESTABLISHED)
+				tcp_conn->tc_state= TCS_CLOSING;
+
+			/* Set the retransmission timeout a bit smaller. */
+			tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_CLOSING;
+
+			/* If all data has been acknowledged, close the connection. */
+			if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
+				tcp_close_connection(tcp_conn, ENOTCONN);
+		}
+
+		tcp_conn= tcp_fd->tf_conn;
+		assert(tcp_conn->tc_fd == tcp_fd);
+		assert (tcp_conn->tc_connInprogress);
+		tcp_conn->tc_connInprogress= 0;
+		tcp_conn->tc_fd= NULL;
+		tcp_fd->tf_conn= NULL;
+		tcp_close_connection(tcp_conn, ENOCONN);
+	}
+	for (i= 0; i<TFL_LISTEN_MAX; i++)
+	{
+		assert(tcp_fd->tf_listenq[i] == NULL);
+	}
+
+	if (tcp_fd->tf_flags & TFF_CONNECTING)
+	{
+		tcp_conn= tcp_fd->tf_conn;
+		assert(tcp_conn != NULL);
+
+		assert (tcp_conn->tc_connInprogress);
+		tcp_conn->tc_connInprogress= 0;
+		tcp_conn->tc_fd= NULL;
+		tcp_fd->tf_conn= NULL;
+		tcp_close_connection(tcp_conn, ENOCONN);
+
+		tcp_fd->tf_flags &= ~TFF_CONNECTING;
+	}
+
+	tcp_fd->tf_flags &= ~TFF_INUSE;
+	if (!tcp_fd->tf_conn)
+		return;
+
+
+	tcp_conn= tcp_fd->tf_conn;
+	assert(tcp_conn->tc_fd == tcp_fd);
+	tcp_conn->tc_fd= NULL;
+
+	assert (!tcp_conn->tc_connInprogress);
+
+	tcp_shutdown (tcp_conn);
+	if (tcp_conn->tc_state == TCS_ESTABLISHED)
+	{
+		tcp_conn->tc_state= TCS_CLOSING;
+	}
+
+	/* Set the retransmission timeout a bit smaller. */
+	tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_CLOSING;
+
+	/* If all data has been acknowledged, close the connection. */
+	if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
+		tcp_close_connection(tcp_conn, ENOTCONN);
+}
+
+PUBLIC int tcp_cancel(fd, which_operation)
+int fd;
+int which_operation;
+{
+	tcp_fd_t *tcp_fd;
+	tcp_conn_t *tcp_conn;
+
+	tcp_fd= &tcp_fd_table[fd];
+
+	assert (tcp_fd->tf_flags & TFF_INUSE);
+
+	tcp_conn= tcp_fd->tf_conn;
+
+	switch (which_operation)
+	{
+	case SR_CANCEL_WRITE:
+		assert (tcp_fd->tf_flags & TFF_WRITE_IP);
+		tcp_fd->tf_flags &= ~TFF_WRITE_IP;
+
+		if (tcp_fd->tf_write_offset)
+			reply_thr_get (tcp_fd, tcp_fd->tf_write_offset, FALSE);
+		else
+			reply_thr_get (tcp_fd, EINTR, FALSE);
+		break;
+	case SR_CANCEL_READ:
+		assert (tcp_fd->tf_flags & TFF_READ_IP);
+		tcp_fd->tf_flags &= ~TFF_READ_IP;
+		if (tcp_fd->tf_read_offset)
+			reply_thr_put (tcp_fd, tcp_fd->tf_read_offset, FALSE);
+		else
+			reply_thr_put (tcp_fd, EINTR, FALSE);
+		break;
+	case SR_CANCEL_IOCTL:
+assert (tcp_fd->tf_flags & TFF_IOCTL_IP);
+		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+
+		if (tcp_fd->tf_flags & TFF_IOC_INIT_SP)
+		{
+			tcp_fd->tf_flags &= ~TFF_IOC_INIT_SP;
+			reply_thr_put (tcp_fd, EINTR, TRUE);
+			break;
+		}
+
+		switch (tcp_fd->tf_ioreq)
+		{
+		case NWIOGTCPCONF:
+			reply_thr_put (tcp_fd, EINTR, TRUE);
+			break;
+		case NWIOSTCPCONF:
+		case NWIOTCPSHUTDOWN:
+			reply_thr_get (tcp_fd, EINTR, TRUE);
+			break;
+		case NWIOTCPCONN:
+		case NWIOTCPLISTEN:
+			assert (tcp_conn->tc_connInprogress);
+			tcp_conn->tc_connInprogress= 0;
+			tcp_conn->tc_fd= NULL;
+			tcp_fd->tf_conn= NULL;
+			tcp_close_connection(tcp_conn, ENOCONN);
+			reply_thr_get (tcp_fd, EINTR, TRUE);
+			break;
+		default:
+			ip_warning(( "unknown ioctl inprogress: 0x%x",
+				tcp_fd->tf_ioreq ));
+			reply_thr_get (tcp_fd, EINTR, TRUE);
+			break;
+		}
+		break;
+	default:
+		ip_panic(( "unknown cancel request" ));
+		break;
+	}
+	return NW_OK;
+}
+
+/*
+tcp_connect
+*/
+
+PRIVATE int tcp_connect(tcp_fd)
+tcp_fd_t *tcp_fd;
+{
+	tcp_conn_t *tcp_conn;
+	nwio_tcpcl_t *tcpcl;
+	long nwtcl_flags;
+	int r, do_asynch;
+	acc_t *data;
+
+	if (!(tcp_fd->tf_flags & TFF_CONF_SET))
+	{
+		tcp_reply_ioctl(tcp_fd, EBADMODE);
+		return NW_OK;
+	}
+	assert (!(tcp_fd->tf_flags & TFF_CONNECTED) &&
+		!(tcp_fd->tf_flags & TFF_CONNECTING) &&
+		!(tcp_fd->tf_flags & TFF_LISTENQ));
+	if ((tcp_fd->tf_tcpconf.nwtc_flags & (NWTC_SET_RA|NWTC_SET_RP))
+		!= (NWTC_SET_RA|NWTC_SET_RP))
+	{
+		tcp_reply_ioctl(tcp_fd, EBADMODE);
+		return NW_OK;
+	}
+
+	data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0,
+		sizeof(*tcpcl), TRUE);
+	if (!data)
+		return EFAULT;
+
+	data= bf_packIffLess(data, sizeof(*tcpcl));
+	assert (data->acc_length == sizeof(*tcpcl));
+	tcpcl= (nwio_tcpcl_t *)ptr2acc_data(data);
+
+	nwtcl_flags= tcpcl->nwtcl_flags;
+	bf_afree(data); data= NULL; tcpcl= NULL;
+
+	if (nwtcl_flags == TCF_ASYNCH)
+		do_asynch= 1;
+	else if (nwtcl_flags == TCF_DEFAULT)
+		do_asynch= 0;
+	else
+	{
+		tcp_reply_ioctl(tcp_fd, EINVAL);
+		return NW_OK;
+	}
+
+	assert(!tcp_fd->tf_conn);
+	tcp_conn= find_conn_entry(tcp_fd->tf_tcpconf.nwtc_locport,
+		tcp_fd->tf_port->tp_ipaddr,
+		tcp_fd->tf_tcpconf.nwtc_remport,
+		tcp_fd->tf_tcpconf.nwtc_remaddr);
+	if (tcp_conn)
+	{
+		if (tcp_conn->tc_fd)
+		{
+			tcp_reply_ioctl(tcp_fd, EADDRINUSE);
+			return NW_OK;
+		}
+	}
+	else
+	{
+		tcp_conn= find_empty_conn();
+		if (!tcp_conn)
+		{
+			tcp_reply_ioctl(tcp_fd, EAGAIN);
+			return NW_OK;
+		}
+	}
+	tcp_fd->tf_conn= tcp_conn;
+
+	r= tcp_su4connect(tcp_fd);
+	if (r == NW_SUSPEND && do_asynch)
+	{
+		tcp_fd->tf_flags |= TFF_CONNECTING;
+		tcp_reply_ioctl(tcp_fd, EINPROGRESS);
+		r= NW_OK;
+	}
+	return r;
+}
+
+/*
+tcp_su4connect
+*/
+
+PRIVATE int tcp_su4connect(tcp_fd)
+tcp_fd_t *tcp_fd;
+{
+	tcp_conn_t *tcp_conn;
+
+	tcp_conn= tcp_fd->tf_conn;
+
+	tcp_conn->tc_locport= tcp_fd->tf_tcpconf.nwtc_locport;
+	tcp_conn->tc_locaddr= tcp_fd->tf_port->tp_ipaddr;
+
+	assert (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP);
+	assert (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA);
+	tcp_conn->tc_remport= tcp_fd->tf_tcpconf.nwtc_remport;
+	tcp_conn->tc_remaddr= tcp_fd->tf_tcpconf.nwtc_remaddr;
+
+	tcp_setup_conn(tcp_fd->tf_port, tcp_conn);
+
+	tcp_conn->tc_fd= tcp_fd;
+	tcp_conn->tc_connInprogress= 1;
+	tcp_conn->tc_orglisten= FALSE;
+	tcp_conn->tc_state= TCS_SYN_SENT;
+	tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_CONNECT;
+
+	/* Start the timer (if necessary) */
+	tcp_set_send_timer(tcp_conn);
+
+	tcp_conn_write(tcp_conn, 0);
+
+	if (tcp_conn->tc_connInprogress)
+		return NW_SUSPEND;
+	else
+		return NW_OK;
+}
+
+
+/*
+tcp_listen
+*/
+
+PRIVATE int tcp_listen(tcp_fd, do_listenq)
+tcp_fd_t *tcp_fd;
+int do_listenq;
+{
+	tcp_conn_t *tcp_conn;
+
+	if (!(tcp_fd->tf_flags & TFF_CONF_SET))
+	{
+		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+		reply_thr_get(tcp_fd, EBADMODE, TRUE);
+		return NW_OK;
+	}
+	assert (!(tcp_fd->tf_flags & TFF_CONNECTED) &&
+		!(tcp_fd->tf_flags & TFF_CONNECTING) &&
+		!(tcp_fd->tf_flags & TFF_LISTENQ));
+	tcp_conn= tcp_fd->tf_conn;
+	assert(!tcp_conn);
+
+	if ((tcp_fd->tf_tcpconf.nwtc_flags & (NWTC_SET_RA|NWTC_SET_RP))
+		== (NWTC_SET_RA|NWTC_SET_RP))
+	{
+		tcp_conn= find_conn_entry(
+			tcp_fd->tf_tcpconf.nwtc_locport,
+			tcp_fd->tf_port->tp_ipaddr,
+			tcp_fd->tf_tcpconf.nwtc_remport,
+			tcp_fd->tf_tcpconf.nwtc_remaddr);
+		if (tcp_conn)
+		{
+			if (tcp_conn->tc_fd)
+			{
+				tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+				reply_thr_get (tcp_fd, EADDRINUSE, TRUE);
+				return NW_OK;
+			}
+			tcp_fd->tf_conn= tcp_conn;
+			return tcp_su4listen(tcp_fd, tcp_conn, do_listenq);
+		}
+	}
+	tcp_conn= find_empty_conn();
+	if (!tcp_conn)
+	{
+		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
+		reply_thr_get (tcp_fd, EAGAIN, TRUE);
+		return NW_OK;
+	}
+	tcp_fd->tf_conn= tcp_conn;
+	return tcp_su4listen(tcp_fd, tcp_conn, do_listenq);
+}
+
+/*
+tcp_acceptto
+*/
+
+PRIVATE int tcp_acceptto(tcp_fd)
+tcp_fd_t *tcp_fd;
+{
+	int i, dst_nr;
+	tcp_fd_t *dst_fd;
+	tcp_conn_t *tcp_conn;
+	tcp_cookie_t *cookiep;
+	acc_t *data;
+	tcp_cookie_t cookie;
+
+	if (!(tcp_fd->tf_flags & TFF_LISTENQ))
+	{
+		tcp_reply_ioctl(tcp_fd, EINVAL);
+		return NW_OK;
+	}
+	for (i= 0; i<TFL_LISTEN_MAX; i++)
+	{
+		tcp_conn= tcp_fd->tf_listenq[i];
+		if (tcp_conn && !tcp_conn->tc_connInprogress)
+			break;
+	}
+	if (i >= TFL_LISTEN_MAX)
+	{
+		/* Nothing, suspend caller */
+		return NW_SUSPEND;
+	}
+
+	data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0,
+		sizeof(*cookiep), TRUE);
+	if (!data)
+		return EFAULT;
+
+	data= bf_packIffLess(data, sizeof(*cookiep));
+	cookiep= (tcp_cookie_t *)ptr2acc_data(data);
+	cookie= *cookiep;
+
+	bf_afree(data); data= NULL;
+
+	dst_nr= cookie.tc_ref;
+	if (dst_nr < 0 || dst_nr >= TCP_FD_NR)
+	{
+		printf("tcp_acceptto: bad fd %d\n", dst_nr);
+		tcp_reply_ioctl(tcp_fd, EINVAL);
+		return NW_OK;
+	}
+	dst_fd= &tcp_fd_table[dst_nr];
+	if (!(dst_fd->tf_flags & TFF_INUSE) ||
+		(dst_fd->tf_flags & (TFF_READ_IP|TFF_WRITE_IP|TFF_IOCTL_IP)) ||
+		dst_fd->tf_conn != NULL ||
+		!(dst_fd->tf_flags & TFF_COOKIE))
+	{
+		printf("tcp_acceptto: bad flags 0x%x or conn %p for fd %d\n",
+			dst_fd->tf_flags, dst_fd->tf_conn, dst_nr);
+		tcp_reply_ioctl(tcp_fd, EINVAL);
+		return NW_OK;
+	}
+	if (memcmp(&cookie, &dst_fd->tf_cookie, sizeof(cookie)) != 0)
+	{
+		printf("tcp_acceptto: bad cookie\n");
+		return NW_OK;
+	}
+
+	/* Move connection */
+	tcp_fd->tf_listenq[i]= NULL;
+	tcp_conn->tc_fd= dst_fd;
+	dst_fd->tf_conn= tcp_conn;
+	dst_fd->tf_flags |= TFF_CONNECTED;
+
+	tcp_reply_ioctl(tcp_fd, NW_OK);
+	return NW_OK;
+}
+
+
+PRIVATE void tcp_buffree (priority)
+int priority;
+{
+	int i;
+	tcp_conn_t *tcp_conn;
+
+	if (priority == TCP_PRI_FRAG2SEND)
+	{
+		for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
+			tcp_conn++)
+		{
+			if (!(tcp_conn->tc_flags & TCF_INUSE))
+				continue;
+			if (!tcp_conn->tc_frag2send)
+				continue;
+			if (tcp_conn->tc_busy)
+				continue;
+			bf_afree(tcp_conn->tc_frag2send);
+			tcp_conn->tc_frag2send= 0;
+		}
+	}
+
+	if (priority == TCP_PRI_CONN_EXTRA)
+	{
+		for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
+			tcp_conn++)
+		{
+			if (!(tcp_conn->tc_flags & TCF_INUSE))
+				continue;
+			if (tcp_conn->tc_busy)
+				continue;
+			if (tcp_conn->tc_adv_data)
+			{
+				bf_afree(tcp_conn->tc_adv_data);
+				tcp_conn->tc_adv_data= NULL;
+			}
+		}
+	}
+
+	if (priority == TCP_PRI_CONNwoUSER)
+	{
+		for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
+			tcp_conn++)
+		{
+			if (!(tcp_conn->tc_flags & TCF_INUSE))
+				continue;
+			if (tcp_conn->tc_busy)
+				continue;
+			if (tcp_conn->tc_fd)
+				continue;
+			if (tcp_conn->tc_state == TCS_CLOSED)
+				continue;
+			if (tcp_conn->tc_rcvd_data == NULL &&
+				tcp_conn->tc_send_data == NULL)
+			{
+				continue;
+			}
+			tcp_close_connection (tcp_conn, EOUTOFBUFS);
+		}
+	}
+
+	if (priority == TCP_PRI_CONN_INUSE)
+	{
+		for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
+			tcp_conn++)
+		{
+			if (!(tcp_conn->tc_flags & TCF_INUSE))
+				continue;
+			if (tcp_conn->tc_busy)
+				continue;
+			if (tcp_conn->tc_state == TCS_CLOSED)
+				continue;
+			if (tcp_conn->tc_rcvd_data == NULL &&
+				tcp_conn->tc_send_data == NULL)
+			{
+				continue;
+			}
+			tcp_close_connection (tcp_conn, EOUTOFBUFS);
+		}
+	}
+}
+
+#ifdef BUF_CONSISTENCY_CHECK
+PRIVATE void tcp_bufcheck()
+{
+	int i;
+	tcp_conn_t *tcp_conn;
+	tcp_port_t *tcp_port;
+
+	for (i= 0, tcp_port= tcp_port_table; i<tcp_conf_nr; i++, tcp_port++)
+	{
+		if (tcp_port->tp_pack)
+			bf_check_acc(tcp_port->tp_pack);
+	}
+	for (i= 0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++, tcp_conn++)
+	{
+		assert(!tcp_conn->tc_busy);
+		if (tcp_conn->tc_rcvd_data)
+			bf_check_acc(tcp_conn->tc_rcvd_data);
+		if (tcp_conn->tc_adv_data)
+			bf_check_acc(tcp_conn->tc_adv_data);
+		if (tcp_conn->tc_send_data)
+			bf_check_acc(tcp_conn->tc_send_data);
+		if (tcp_conn->tc_remipopt)
+			bf_check_acc(tcp_conn->tc_remipopt);
+		if (tcp_conn->tc_tcpopt)
+			bf_check_acc(tcp_conn->tc_tcpopt);
+		if (tcp_conn->tc_frag2send)
+			bf_check_acc(tcp_conn->tc_frag2send);
+	}
+}
+#endif
+
+PUBLIC void tcp_notreach(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	int new_ttl;
+
+	new_ttl= tcp_conn->tc_ttl;
+	if (new_ttl == IP_MAX_TTL)
+	{
+		if (tcp_conn->tc_state == TCS_SYN_SENT)
+			tcp_close_connection(tcp_conn, EDSTNOTRCH);
+		return;
+	}
+	else if (new_ttl < TCP_DEF_TTL_NEXT)
+		new_ttl= TCP_DEF_TTL_NEXT;
+	else
+	{
+		new_ttl *= 2;
+		if (new_ttl> IP_MAX_TTL)
+			new_ttl= IP_MAX_TTL;
+	}
+	tcp_conn->tc_ttl= new_ttl;
+	tcp_conn->tc_stt= 0;
+	tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
+	tcp_conn_write(tcp_conn, 1);
+}
+
+FORWARD u32_t mtu_table[]=
+{	/* From RFC-1191 */
+/*	Plateau    MTU    Comments                      Reference	*/
+/*	------     ---    --------                      ---------	*/
+/*		  65535  Official maximum MTU          RFC 791		*/
+/*		  65535  Hyperchannel                  RFC 1044		*/
+	65535,
+	32000,    /*     Just in case					*/
+/*		  17914  16Mb IBM Token Ring           ref. [6]		*/
+	17914,
+/*		  8166   IEEE 802.4                    RFC 1042		*/
+	8166,
+/*		  4464   IEEE 802.5 (4Mb max)          RFC 1042		*/
+/*		  4352   FDDI (Revised)                RFC 1188		*/
+	4352, /* (1%) */
+/*		  2048   Wideband Network              RFC 907		*/
+/*		  2002   IEEE 802.5 (4Mb recommended)  RFC 1042		*/
+	2002, /* (2%) */
+/*		  1536   Exp. Ethernet Nets            RFC 895		*/
+/*		  1500   Ethernet Networks             RFC 894		*/
+/*		  1500   Point-to-Point (default)      RFC 1134		*/
+/*		  1492   IEEE 802.3                    RFC 1042		*/
+	1492, /* (3%) */
+/*		  1006   SLIP                          RFC 1055		*/
+/*		  1006   ARPANET                       BBN 1822		*/
+	1006,
+/*		  576    X.25 Networks                 RFC 877		*/
+/*		  544    DEC IP Portal                 ref. [10]	*/
+/*		  512    NETBIOS                       RFC 1088		*/
+/*		  508    IEEE 802/Source-Rt Bridge     RFC 1042		*/
+/*		  508    ARCNET                        RFC 1051		*/
+	508, /* (13%) */
+/*		  296    Point-to-Point (low delay)    RFC 1144		*/
+	296,
+	68,       /*     Official minimum MTU          RFC 791		*/
+	0,        /*     End of list					*/
+};
+
+PUBLIC void tcp_mtu_exceeded(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	u16_t mtu;
+	int i;
+	clock_t curr_time;
+
+	if (!(tcp_conn->tc_flags & TCF_PMTU))
+	{
+		/* Strange, got MTU exceeded but DF is not set. Ignore
+		 * the error. If the problem persists, the connection will
+		 * time-out.
+		 */
+		return;
+	}
+	curr_time= get_time();
+
+	/* We get here in cases. Either were are trying to find an MTU 
+	 * that works at all, or we are trying see how far we can increase
+	 * the current MTU. If the last change to the MTU was a long time 
+	 * ago, we assume the second case. 
+	 */
+	if (curr_time >= tcp_conn->tc_mtutim + TCP_PMTU_INCR_IV)
+	{
+		mtu= tcp_conn->tc_mtu;
+		mtu -= mtu/TCP_PMTU_INCR_FRAC;
+		tcp_conn->tc_mtu= mtu;
+		tcp_conn->tc_mtutim= curr_time;
+		DBLOCK(1, printf(
+			"tcp_mtu_exceeded: new (lowered) mtu %d for conn %d\n",
+			mtu, tcp_conn-tcp_conn_table));
+		tcp_conn->tc_stt= 0;
+		tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
+		tcp_conn_write(tcp_conn, 1);
+		return;
+	}
+
+	tcp_conn->tc_mtutim= curr_time;
+	mtu= tcp_conn->tc_mtu;
+	for (i= 0; mtu_table[i] >= mtu; i++)
+		;	/* Nothing to do */
+	mtu= mtu_table[i];
+	if (mtu >= TCP_MIN_PATH_MTU)
+	{
+		tcp_conn->tc_mtu= mtu;
+	}
+	else
+	{
+		/* Small MTUs can be used for denial-of-service attacks.
+		 * Switch-off PMTU if the MTU becomes too small.
+		 */
+		tcp_conn->tc_flags &= ~TCF_PMTU;
+		tcp_conn->tc_mtu= TCP_MIN_PATH_MTU;
+		DBLOCK(1, printf(
+			"tcp_mtu_exceeded: clearing TCF_PMTU for conn %d\n",
+			tcp_conn-tcp_conn_table););
+
+	}
+	DBLOCK(1, printf("tcp_mtu_exceeded: new mtu %d for conn %d\n",
+		mtu, tcp_conn-tcp_conn_table););
+	tcp_conn->tc_stt= 0;
+	tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
+	tcp_conn_write(tcp_conn, 1);
+}
+
+PUBLIC void tcp_mtu_incr(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	clock_t curr_time;
+	u32_t mtu;
+
+	assert(tcp_conn->tc_mtu < tcp_conn->tc_max_mtu);
+	if (!(tcp_conn->tc_flags & TCF_PMTU))
+	{
+		/* Use a much longer time-out for retrying PMTU discovery
+		 * after is has been disabled. Note that PMTU discovery
+		 * can be disabled during a short loss of connectivity.
+		 */
+		curr_time= get_time();
+		if (curr_time > tcp_conn->tc_mtutim+TCP_PMTU_EN_IV)
+		{
+			tcp_conn->tc_flags |= TCF_PMTU;
+			DBLOCK(1, printf(
+				"tcp_mtu_incr: setting TCF_PMTU for conn %d\n",
+				tcp_conn-tcp_conn_table););
+		}
+		return;
+	}
+
+	mtu= tcp_conn->tc_mtu;
+	mtu += mtu/TCP_PMTU_INCR_FRAC;
+	if (mtu > tcp_conn->tc_max_mtu)
+		mtu= tcp_conn->tc_max_mtu;
+	tcp_conn->tc_mtu= mtu;
+	DBLOCK(0x1, printf("tcp_mtu_incr: new mtu %ld for conn %d\n",
+		mtu, tcp_conn-tcp_conn_table););
+}
+
+/*
+tcp_setup_conn
+*/
+
+PRIVATE void tcp_setup_conn(tcp_port, tcp_conn)
+tcp_port_t *tcp_port;
+tcp_conn_t *tcp_conn;
+{
+	u16_t mss;
+
+	assert(!tcp_conn->tc_connInprogress);
+	tcp_conn->tc_port= tcp_port;
+	if (tcp_conn->tc_flags & TCF_INUSE)
+	{
+		assert (tcp_conn->tc_state == TCS_CLOSED);
+		assert (!tcp_conn->tc_send_data);
+		if (tcp_conn->tc_senddis < get_time())
+			tcp_conn->tc_ISS= 0;
+	}
+	else
+	{
+		assert(!tcp_conn->tc_busy);
+		tcp_conn->tc_senddis= 0;
+		tcp_conn->tc_ISS= 0;
+		tcp_conn->tc_tos= TCP_DEF_TOS;
+		tcp_conn->tc_ttl= TCP_DEF_TTL;
+		tcp_conn->tc_rcv_wnd= TCP_MAX_RCV_WND_SIZE;
+		tcp_conn->tc_fd= NULL;
+	}
+	if (!tcp_conn->tc_ISS)
+	{
+		tcp_conn->tc_ISS= tcp_rand32();
+	}
+	tcp_conn->tc_SND_UNA= tcp_conn->tc_ISS;
+	tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;
+	tcp_conn->tc_SND_NXT= tcp_conn->tc_ISS+1;
+	tcp_conn->tc_SND_UP= tcp_conn->tc_ISS;
+	tcp_conn->tc_SND_PSH= tcp_conn->tc_ISS+1;
+	tcp_conn->tc_IRS= 0;
+	tcp_conn->tc_RCV_LO= tcp_conn->tc_IRS;
+	tcp_conn->tc_RCV_NXT= tcp_conn->tc_IRS;
+	tcp_conn->tc_RCV_HI= tcp_conn->tc_IRS;
+	tcp_conn->tc_RCV_UP= tcp_conn->tc_IRS;
+
+	assert(tcp_conn->tc_rcvd_data == NULL);
+	assert(tcp_conn->tc_adv_data == NULL);
+	assert(tcp_conn->tc_send_data == NULL);
+
+	tcp_conn->tc_ka_time= TCP_DEF_KEEPALIVE;
+
+	tcp_conn->tc_remipopt= NULL;
+	tcp_conn->tc_tcpopt= NULL;
+
+	assert(tcp_conn->tc_frag2send == NULL);
+
+	tcp_conn->tc_stt= 0;
+	tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD;
+	tcp_conn->tc_0wnd_to= 0;
+	tcp_conn->tc_artt= TCP_DEF_RTT*TCP_RTT_SCALE;
+	tcp_conn->tc_drtt= 0;
+	tcp_conn->tc_rtt= TCP_DEF_RTT;
+	tcp_conn->tc_max_mtu= tcp_conn->tc_port->tp_mtu;
+	tcp_conn->tc_mtu= tcp_conn->tc_max_mtu;
+	tcp_conn->tc_mtutim= 0;
+	tcp_conn->tc_error= NW_OK;
+	mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
+	tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + 2*mss;
+	tcp_conn->tc_snd_cthresh= TCP_MAX_SND_WND_SIZE;
+	tcp_conn->tc_snd_cinc=
+		(long)TCP_DEF_MSS*TCP_DEF_MSS/TCP_MAX_SND_WND_SIZE+1;
+	tcp_conn->tc_snd_wnd= TCP_MAX_SND_WND_SIZE;
+	tcp_conn->tc_rt_time= 0;
+	tcp_conn->tc_rt_seq= 0;
+	tcp_conn->tc_rt_threshold= tcp_conn->tc_ISS;
+	tcp_conn->tc_flags= TCF_INUSE;
+	tcp_conn->tc_flags |= TCF_PMTU;
+
+	clck_untimer(&tcp_conn->tc_transmit_timer);
+	tcp_conn->tc_transmit_seq= 0;
+}
+
+PRIVATE u32_t tcp_rand32()
+{
+	u8_t bits[RAND256_BUFSIZE];
+
+	rand256(bits);
+	return bits[0] | (bits[1] << 8) | (bits[2] << 16) | (bits[3] << 24);
+}
+
+/*
+ * $PchId: tcp.c,v 1.34 2005/06/28 14:20:27 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/tcp.h
===================================================================
--- /trunk/minix/servers/inet/generic/tcp.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/tcp.h	(revision 9)
@@ -0,0 +1,95 @@
+/*
+tcp.h
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef TCP_H
+#define TCP_H
+
+#define TCP_MAX_DATAGRAM	8192
+
+#ifndef TCP_MAX_SND_WND_SIZE
+#define TCP_MAX_SND_WND_SIZE	(32*1024)
+#endif
+
+#ifndef TCP_MIN_RCV_WND_SIZE
+#define TCP_MIN_RCV_WND_SIZE	(4*1024)
+#endif
+
+#ifndef TCP_MAX_RCV_WND_SIZE
+#define TCP_MAX_RCV_WND_SIZE	(TCP_MIN_RCV_WND_SIZE + 28*1024)
+#endif
+
+#define TCP_DEF_TOS		0
+#define TCP_DEF_TTL		5	/* hops/seconds */
+#define TCP_DEF_TTL_NEXT	30	/* hops/seconds */
+
+/* An established  TCP connection times out if no communication is possible
+ * for TCP_DEF_RT_DEAD clock ticks
+ */
+#ifndef TCP_DEF_RT_DEAD
+#define TCP_DEF_RT_DEAD		(20L*60*HZ)
+#endif
+
+#define TCP_DEF_RT_MAX_CONNECT	(5L*60*HZ) /* 5 minutes in ticks */
+#define TCP_DEF_RT_MAX_LISTEN	(1L*60*HZ) /* 1 minute in ticks */
+#define TCP_DEF_RT_MAX_CLOSING	(1L*60*HZ) /* 1 minute in ticks */
+
+/* Minimum and maximum intervals for zero window probes. */
+#define TCP_0WND_MIN		(HZ)
+#define TCP_0WND_MAX		(5*60*HZ)
+
+#define TCP_DEF_RTT		15	/* initial retransmission time in
+					 * ticks
+					 */
+#define TCP_RTT_GRAN		5	/* minimal value of the rtt is
+					 * TCP_RTT_GRAN * CLOCK_GRAN
+					 */
+#define TCP_RTT_MAX		(10*HZ)	/* The maximum retransmission interval
+					 * is TCP_RTT_MAX ticks
+					 */
+#define TCP_RTT_SMOOTH		 16	/* weight is 15/16 */
+#define TCP_DRTT_MULT		  4	/* weight of the deviation */
+#define TCP_RTT_SCALE		256	/* Scaled values for more accuracy */
+
+#ifndef TCP_DEF_KEEPALIVE
+#define TCP_DEF_KEEPALIVE	(20L*60*HZ)	/* Keepalive interval */
+#endif
+
+#ifndef TCP_DEF_MSS
+#define TCP_DEF_MSS		1400
+#endif
+
+#define TCP_MIN_PATH_MTU	 500
+#define TCP_PMTU_INCR_IV	(1L*60*HZ)	/* 1 minute in ticks */
+#define TCP_PMTU_EN_IV		(10L*60*HZ)	/* 10 minutes in ticks */
+#define TCP_PMTU_INCR_FRAC	100		/* Add 1% each time */
+#define TCP_PMTU_BLACKHOLE	(10*HZ)		/* Assume a PMTU blackhole
+						 * after 10 seconds.
+						 */
+
+#define TCP_DEF_CONF		(NWTC_COPY | NWTC_LP_UNSET | NWTC_UNSET_RA | \
+					NWTC_UNSET_RP)
+#define TCP_DEF_OPT		(NWTO_NOFLAG)
+
+#define TCP_DACK_RETRANS	3	/* # dup ACKs to start fast retrans. */
+
+struct acc;
+
+void tcp_prep ARGS(( void ));
+void tcp_init ARGS(( void ));
+int tcp_open ARGS(( int port, int srfd,
+	get_userdata_t get_userdata, put_userdata_t put_userdata, 
+	put_pkt_t put_pkt, select_res_t select_res ));
+int tcp_read ARGS(( int fd, size_t count));
+int tcp_write ARGS(( int fd, size_t count));
+int tcp_ioctl ARGS(( int fd, ioreq_t req));
+int tcp_cancel ARGS(( int fd, int which_operation ));
+void tcp_close ARGS(( int fd));
+
+#endif /* TCP_H */
+
+/*
+ * $PchId: tcp.h,v 1.17 2005/06/28 14:20:54 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/tcp_int.h
===================================================================
--- /trunk/minix/servers/inet/generic/tcp_int.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/tcp_int.h	(revision 9)
@@ -0,0 +1,266 @@
+/*
+tcp_int.h
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef TCP_INT_H
+#define TCP_INT_H
+
+#define IP_TCP_MIN_HDR_SIZE	(IP_MIN_HDR_SIZE+TCP_MIN_HDR_SIZE)
+
+#define TCP_CONN_HASH_SHIFT	4
+#define TCP_CONN_HASH_NR	(1 << TCP_CONN_HASH_SHIFT)
+
+typedef struct tcp_port
+{
+	int tp_ipdev;
+	int tp_flags;
+	int tp_state;
+	int tp_ipfd;
+	acc_t *tp_pack;
+	ipaddr_t tp_ipaddr;
+	ipaddr_t tp_subnetmask;
+	u16_t tp_mtu;
+	struct tcp_conn *tp_snd_head;
+	struct tcp_conn *tp_snd_tail;
+	event_t tp_snd_event;
+	struct tcp_conn *tp_conn_hash[TCP_CONN_HASH_NR][4];
+} tcp_port_t;
+
+#define TPF_EMPTY	0x0
+#define TPF_SUSPEND	0x1
+#define TPF_READ_IP	0x2
+#define TPF_READ_SP	0x4
+#define TPF_WRITE_IP	0x8
+#define TPF_WRITE_SP	0x10
+#define TPF_DELAY_TCP	0x40
+
+#define TPS_EMPTY	0
+#define TPS_SETPROTO	1
+#define TPS_GETCONF	2
+#define TPS_MAIN	3
+#define TPS_ERROR	4
+
+#define TFL_LISTEN_MAX	5
+
+typedef struct tcp_fd
+{
+	unsigned long tf_flags;
+	tcp_port_t *tf_port;
+	int tf_srfd;
+	ioreq_t tf_ioreq;
+	nwio_tcpconf_t tf_tcpconf;
+	nwio_tcpopt_t tf_tcpopt;
+	get_userdata_t tf_get_userdata;
+	put_userdata_t tf_put_userdata;
+	select_res_t tf_select_res;
+	struct tcp_conn *tf_conn;
+	struct tcp_conn *tf_listenq[TFL_LISTEN_MAX];
+	size_t tf_write_offset;
+	size_t tf_write_count;
+	size_t tf_read_offset;
+	size_t tf_read_count;
+	int tf_error;			/* Error for nonblocking connect */
+	tcp_cookie_t tf_cookie;
+} tcp_fd_t;
+
+#define TFF_EMPTY	    0x0
+#define TFF_INUSE	    0x1
+#define TFF_READ_IP	    0x2
+#define TFF_WRITE_IP	    0x4
+#define TFF_IOCTL_IP	    0x8
+#define TFF_CONF_SET	   0x10
+#define TFF_IOC_INIT_SP	   0x20
+#define TFF_LISTENQ	   0x40
+#define TFF_CONNECTING	   0x80
+#define TFF_CONNECTED	  0x100
+#define TFF_WR_URG	  0x200
+#define TFF_PUSH_DATA	  0x400
+#define TFF_RECV_URG	  0x800
+#define TFF_SEL_READ	 0x1000
+#define TFF_SEL_WRITE	 0x2000
+#define TFF_SEL_EXCEPT	 0x4000
+#define TFF_DEL_RST	 0x8000
+#define TFF_COOKIE	0x10000
+
+typedef struct tcp_conn
+{
+	int tc_flags;
+	int tc_state;
+	int tc_busy;		/* do not steal buffer when a connection is 
+				 * busy
+				 */
+	tcp_port_t *tc_port;
+	tcp_fd_t *tc_fd;
+
+	tcpport_t tc_locport;
+	ipaddr_t tc_locaddr;
+	tcpport_t tc_remport;
+	ipaddr_t tc_remaddr;
+
+	int tc_connInprogress;
+	int tc_orglisten;
+	clock_t tc_senddis;
+
+	/* Sending side */
+	u32_t tc_ISS;		/* initial sequence number */
+	u32_t tc_SND_UNA;	/* least unacknowledged sequence number */
+	u32_t tc_SND_TRM;	/* next sequence number to be transmitted */
+	u32_t tc_SND_NXT;	/* next sequence number for new data */
+	u32_t tc_SND_UP;	/* urgent pointer, first sequence number not 
+				 * urgent */
+	u32_t tc_SND_PSH;	/* push pointer, data should be pushed until
+				 * the push pointer is reached */
+
+	u32_t tc_snd_cwnd;	/* highest sequence number to be sent */
+	u32_t tc_snd_cthresh;	/* threshold for send window */
+	u32_t tc_snd_cinc;	/* increment for send window threshold */
+	u16_t tc_snd_wnd;	/* max send queue size */
+	u16_t tc_snd_dack;	/* # of duplicate ACKs */
+
+	/* round trip calculation. */
+	clock_t tc_rt_time;
+	u32_t tc_rt_seq;
+	u32_t tc_rt_threshold;
+	clock_t tc_artt;	/* Avg. retransmission time. Scaled. */
+	clock_t tc_drtt;	/* Diviation, also scaled. */
+	clock_t tc_rtt;		/* Computed retrans time */
+
+	acc_t *tc_send_data;
+	acc_t *tc_frag2send;
+	struct tcp_conn *tc_send_link;
+
+	/* Receiving side */
+	u32_t tc_IRS;
+	u32_t tc_RCV_LO;
+	u32_t tc_RCV_NXT;
+	u32_t tc_RCV_HI;
+	u32_t tc_RCV_UP;
+
+	u16_t tc_rcv_wnd;
+	acc_t *tc_rcvd_data;
+	acc_t *tc_adv_data;
+	u32_t tc_adv_seq;
+
+	/* Keep alive. Record SDN_NXT and RCV_NXT in tc_ka_snd and
+	 * tc_ka_rcv when setting the keepalive timer to detect
+	 * any activity that may have happend before the timer
+	 * expired.
+	 */
+	u32_t tc_ka_snd;
+	u32_t tc_ka_rcv;
+	clock_t tc_ka_time;
+
+	acc_t *tc_remipopt;
+	acc_t *tc_tcpopt;
+	u8_t tc_tos;
+	u8_t tc_ttl;
+	u16_t tc_max_mtu;	/* Max. negotiated (or selected) MTU */
+	u16_t tc_mtu;		/* discovered PMTU */
+	clock_t tc_mtutim;	/* Last time MTU/TCF_PMTU flag was changed */
+
+	struct timer tc_transmit_timer;
+	u32_t tc_transmit_seq;
+	clock_t tc_0wnd_to;
+	clock_t tc_stt;		/* time of first send after last ack */
+	clock_t tc_rt_dead;
+
+	int tc_error;
+	int tc_inconsistent; 
+} tcp_conn_t;
+
+#define TCF_EMPTY		0x0
+#define TCF_INUSE		0x1
+#define TCF_FIN_RECV		0x2
+#define TCF_RCV_PUSH		0x4
+#define TCF_MORE2WRITE		0x8
+#define TCF_SEND_ACK		0x10
+#define TCF_FIN_SENT		0x20
+#define TCF_BSD_URG		0x40
+#define TCF_NO_PUSH		0x80
+#define TCF_PUSH_NOW		0x100
+#define TCF_PMTU		0x200
+
+#if DEBUG & 0x200
+#define TCF_DEBUG		0x1000
+#endif
+
+#define TCS_CLOSED		0
+#define TCS_LISTEN		1
+#define TCS_SYN_RECEIVED	2
+#define TCS_SYN_SENT		3
+#define TCS_ESTABLISHED		4
+#define TCS_CLOSING		5
+
+/* tcp_recv.c */
+void tcp_frag2conn ARGS(( tcp_conn_t *tcp_conn, ip_hdr_t *ip_hdr,
+	tcp_hdr_t *tcp_hdr, acc_t *tcp_data, size_t data_len ));
+void tcp_fd_read ARGS(( tcp_conn_t *tcp_conn, int enq ));
+unsigned tcp_sel_read ARGS(( tcp_conn_t *tcp_conn ));
+void tcp_rsel_read ARGS(( tcp_conn_t *tcp_conn ));
+void tcp_bytesavailable ARGS(( tcp_fd_t *tcp_fd, int *bytesp ));
+
+/* tcp_send.c */
+void tcp_conn_write ARGS(( tcp_conn_t *tcp_conn, int enq ));
+void tcp_release_retrans ARGS(( tcp_conn_t *tcp_conn, u32_t seg_ack,
+	U16_t new_win ));
+void tcp_fast_retrans ARGS(( tcp_conn_t *tcp_conn ));
+void tcp_set_send_timer ARGS(( tcp_conn_t *tcp_conn ));
+void tcp_fd_write ARGS(( tcp_conn_t *tcp_conn ));
+unsigned tcp_sel_write ARGS(( tcp_conn_t *tcp_conn ));
+void tcp_rsel_write ARGS(( tcp_conn_t *tcp_conn ));
+void tcp_close_connection ARGS(( tcp_conn_t *tcp_conn,
+	int error ));
+void tcp_port_write ARGS(( tcp_port_t *tcp_port ));
+void tcp_shutdown ARGS(( tcp_conn_t *tcp_conn ));
+
+/* tcp_lib.c */
+void tcp_extract_ipopt ARGS(( tcp_conn_t *tcp_conn,
+	ip_hdr_t *ip_hdr ));
+void tcp_extract_tcpopt ARGS(( tcp_conn_t *tcp_conn,
+	tcp_hdr_t *tcp_hdr, size_t *mssp ));
+void tcp_get_ipopt ARGS(( tcp_conn_t *tcp_conn, ip_hdropt_t
+	*ip_hdropt ));
+void tcp_get_tcpopt ARGS(( tcp_conn_t *tcp_conn, tcp_hdropt_t
+	*tcp_hdropt ));
+acc_t *tcp_make_header ARGS(( tcp_conn_t *tcp_conn,
+	ip_hdr_t **ref_ip_hdr, tcp_hdr_t **ref_tcp_hdr, acc_t *data ));
+u16_t tcp_pack_oneCsum ARGS(( ip_hdr_t *ip_hdr, acc_t *tcp_pack ));
+int tcp_check_conn ARGS(( tcp_conn_t *tcp_conn ));
+void tcp_print_pack ARGS(( ip_hdr_t *ip_hdr, tcp_hdr_t *tcp_hdr ));
+void tcp_print_state ARGS(( tcp_conn_t *tcp_conn ));
+void tcp_print_conn ARGS(( tcp_conn_t *tcp_conn ));
+int tcp_LEmod4G ARGS(( u32_t n1, u32_t n2 ));
+int tcp_Lmod4G ARGS(( u32_t n1, u32_t n2 ));
+int tcp_GEmod4G ARGS(( u32_t n1, u32_t n2 ));
+int tcp_Gmod4G ARGS(( u32_t n1, u32_t n2 ));
+
+/* tcp.c */
+void tcp_restart_connect ARGS(( tcp_conn_t *tcp_conn ));
+int tcp_su4listen ARGS(( tcp_fd_t *tcp_fd, tcp_conn_t *tcp_conn,
+	int do_listenq ));
+void tcp_reply_ioctl ARGS(( tcp_fd_t *tcp_fd, int reply ));
+void tcp_reply_write ARGS(( tcp_fd_t *tcp_fd, size_t reply ));
+void tcp_reply_read ARGS(( tcp_fd_t *tcp_fd, size_t reply ));
+void tcp_notreach ARGS(( tcp_conn_t *tcp_conn ));
+void tcp_mtu_exceeded ARGS(( tcp_conn_t *tcp_conn ));
+void tcp_mtu_incr ARGS(( tcp_conn_t *tcp_conn ));
+
+#define TCP_FD_NR	(10*IP_PORT_MAX)
+#define TCP_CONN_NR	(2*TCP_FD_NR)
+
+EXTERN tcp_port_t *tcp_port_table;
+EXTERN tcp_conn_t tcp_conn_table[TCP_CONN_NR];
+EXTERN tcp_fd_t tcp_fd_table[TCP_FD_NR];
+
+#define tcp_Lmod4G(n1,n2)	(!!(((n1)-(n2)) & 0x80000000L))
+#define tcp_GEmod4G(n1,n2)	(!(((n1)-(n2)) & 0x80000000L))
+#define tcp_Gmod4G(n1,n2)	(!!(((n2)-(n1)) & 0x80000000L))
+#define tcp_LEmod4G(n1,n2)	(!(((n2)-(n1)) & 0x80000000L))
+
+#endif /* TCP_INT_H */
+
+/*
+ * $PchId: tcp_int.h,v 1.17 2005/06/28 14:21:08 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/tcp_lib.c
===================================================================
--- /trunk/minix/servers/inet/generic/tcp_lib.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/tcp_lib.c	(revision 9)
@@ -0,0 +1,592 @@
+/*
+tcp_lib.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "buf.h"
+#include "clock.h"
+#include "event.h"
+#include "io.h"
+#include "type.h"
+
+#include "assert.h"
+#include "tcp_int.h"
+
+THIS_FILE
+
+#undef tcp_LEmod4G
+PUBLIC int tcp_LEmod4G(n1, n2)
+u32_t n1;
+u32_t n2;
+{
+	return !((u32_t)(n2-n1) & 0x80000000L);
+}
+
+#undef tcp_GEmod4G
+PUBLIC int tcp_GEmod4G(n1, n2)
+u32_t n1;
+u32_t n2;
+{
+	return !((u32_t)(n1-n2) & 0x80000000L);
+}
+
+#undef tcp_Lmod4G
+PUBLIC int tcp_Lmod4G(n1, n2)
+u32_t n1;
+u32_t n2;
+{
+	return !!((u32_t)(n1-n2) & 0x80000000L);
+}
+
+#undef tcp_Gmod4G
+PUBLIC int tcp_Gmod4G(n1, n2)
+u32_t n1;
+u32_t n2;
+{
+	return !!((u32_t)(n2-n1) & 0x80000000L);
+}
+
+PUBLIC void tcp_extract_ipopt(tcp_conn, ip_hdr)
+tcp_conn_t *tcp_conn;
+ip_hdr_t *ip_hdr;
+{
+	int ip_hdr_len;
+
+	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
+	if (ip_hdr_len == IP_MIN_HDR_SIZE)
+		return;
+
+	DBLOCK(1, printf("ip_hdr options NOT supported (yet?)\n"));
+}
+
+PUBLIC void tcp_extract_tcpopt(tcp_conn, tcp_hdr, mssp)
+tcp_conn_t *tcp_conn;
+tcp_hdr_t *tcp_hdr;
+size_t *mssp;
+{
+	int i, tcp_hdr_len, type, len;
+	u8_t *cp;
+	u16_t mss;
+
+	*mssp= 0;	/* No mss */
+
+	tcp_hdr_len= (tcp_hdr->th_data_off & TH_DO_MASK) >> 2;
+	if (tcp_hdr_len == TCP_MIN_HDR_SIZE)
+		return;
+	i= TCP_MIN_HDR_SIZE;
+	while (i<tcp_hdr_len)
+	{
+		cp= ((u8_t *)tcp_hdr)+i;
+		type= cp[0];
+		if (type == TCP_OPT_NOP)
+		{
+			i++;
+			continue;
+		}
+		if (type == TCP_OPT_EOL)
+			break;
+		if (i+2 > tcp_hdr_len)
+			break;	/* No length field */
+		len= cp[1];
+		if (i+len > tcp_hdr_len)
+			break;	/* Truncated option */
+		i += len;
+		switch(type)
+		{
+		case TCP_OPT_MSS:
+			if (len != 4)
+				break;
+			mss= (cp[2] << 8) | cp[3];
+			DBLOCK(1, printf("tcp_extract_tcpopt: got mss %d\n",
+				mss););
+			*mssp= mss;
+			break;
+		case TCP_OPT_WSOPT:	/* window scale option */
+		case TCP_OPT_SACKOK:	/* SACK permitted */
+		case TCP_OPT_TS:	/* Timestamps option */
+		case TCP_OPT_CCNEW:	/* new connection count */
+			/* Ignore this option. */
+			break;
+		default:
+			DBLOCK(0x1,
+				printf(
+			"tcp_extract_tcpopt: unknown option %d, len %d\n",
+					type, len));
+			break;
+		}
+	}
+}
+
+PUBLIC u16_t tcp_pack_oneCsum(ip_hdr, tcp_pack)
+ip_hdr_t *ip_hdr;
+acc_t *tcp_pack;
+{
+	size_t ip_hdr_len;
+	acc_t *pack;
+	u16_t sum;
+	u16_t word_buf[6];
+	int odd_length;
+	char *data_ptr;
+	int length;
+
+	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
+	word_buf[0]= ip_hdr->ih_src & 0xffff;
+	word_buf[1]= (ip_hdr->ih_src >> 16) & 0xffff;
+	word_buf[2]= ip_hdr->ih_dst & 0xffff;
+	word_buf[3]= (ip_hdr->ih_dst >> 16) & 0xffff;
+	word_buf[4]= HTONS(IPPROTO_TCP);
+	word_buf[5]= htons(ntohs(ip_hdr->ih_length)-ip_hdr_len);
+	sum= oneC_sum(0, word_buf, sizeof(word_buf));
+
+	pack= tcp_pack;
+	odd_length= 0;
+	for (; pack; pack= pack->acc_next)
+	{
+		
+		data_ptr= ptr2acc_data(pack);
+		length= pack->acc_length;
+
+		if (!length)
+			continue;
+		sum= oneC_sum (sum, (u16_t *)data_ptr, length);
+		if (length & 1)
+		{
+			odd_length= !odd_length;
+			sum= ((sum >> 8) & 0xff) | ((sum & 0xff) << 8);
+		}
+	}
+	if (odd_length)
+	{
+		/* Undo the last swap */
+		sum= ((sum >> 8) & 0xff) | ((sum & 0xff) << 8);
+	}
+	return sum;
+}
+
+PUBLIC void tcp_get_ipopt(tcp_conn, ip_hdropt)
+tcp_conn_t *tcp_conn;
+ip_hdropt_t *ip_hdropt;
+{
+	if (!tcp_conn->tc_remipopt)
+	{
+		ip_hdropt->iho_opt_siz= 0;
+		return;
+	}
+	DBLOCK(1, printf("ip_hdr options NOT supported (yet?)\n"));
+	ip_hdropt->iho_opt_siz= 0;
+	return;
+}
+
+PUBLIC void tcp_get_tcpopt(tcp_conn, tcp_hdropt)
+tcp_conn_t *tcp_conn;
+tcp_hdropt_t *tcp_hdropt;
+{
+	int optsiz;
+
+	if (!tcp_conn->tc_tcpopt)
+	{
+		tcp_hdropt->tho_opt_siz= 0;
+		return;
+	}
+	tcp_conn->tc_tcpopt= bf_pack(tcp_conn->tc_tcpopt);
+	optsiz= bf_bufsize(tcp_conn->tc_tcpopt);
+	memcpy(tcp_hdropt->tho_data, ptr2acc_data(tcp_conn->tc_tcpopt),
+		optsiz);
+	if ((optsiz & 3) != 0)
+	{
+		tcp_hdropt->tho_data[optsiz]= TCP_OPT_EOL;
+		optsiz= (optsiz+3) & ~3;
+	}
+	tcp_hdropt->tho_opt_siz= optsiz;
+
+	return;
+}
+
+PUBLIC acc_t *tcp_make_header(tcp_conn, ref_ip_hdr, ref_tcp_hdr, data)
+tcp_conn_t *tcp_conn;
+ip_hdr_t **ref_ip_hdr;
+tcp_hdr_t **ref_tcp_hdr;
+acc_t *data;
+{
+	ip_hdropt_t ip_hdropt;
+	tcp_hdropt_t tcp_hdropt;
+	ip_hdr_t *ip_hdr;
+	tcp_hdr_t *tcp_hdr;
+	acc_t *hdr_acc;
+	char *ptr2hdr;
+	int closed_connection;
+
+	closed_connection= (tcp_conn->tc_state == TCS_CLOSED);
+
+	if (tcp_conn->tc_remipopt || tcp_conn->tc_tcpopt)
+	{
+		tcp_get_ipopt (tcp_conn, &ip_hdropt);
+		tcp_get_tcpopt (tcp_conn, &tcp_hdropt);
+		assert (!(ip_hdropt.iho_opt_siz & 3));
+		assert (!(tcp_hdropt.tho_opt_siz & 3));
+
+		hdr_acc= bf_memreq(IP_MIN_HDR_SIZE+
+			ip_hdropt.iho_opt_siz+TCP_MIN_HDR_SIZE+
+			tcp_hdropt.tho_opt_siz);
+		ptr2hdr= ptr2acc_data(hdr_acc);
+
+		ip_hdr= (ip_hdr_t *)ptr2hdr;
+		ptr2hdr += IP_MIN_HDR_SIZE;
+
+		if (ip_hdropt.iho_opt_siz)
+		{
+			memcpy(ptr2hdr, (char *)ip_hdropt.iho_data,
+				ip_hdropt.iho_opt_siz);
+		}
+		ptr2hdr += ip_hdropt.iho_opt_siz;
+
+		tcp_hdr= (tcp_hdr_t *)ptr2hdr;
+		ptr2hdr += TCP_MIN_HDR_SIZE;
+
+		if (tcp_hdropt.tho_opt_siz)
+		{
+			memcpy (ptr2hdr, (char *)tcp_hdropt.tho_data,
+				tcp_hdropt.tho_opt_siz);
+		}
+		hdr_acc->acc_next= data;
+
+		ip_hdr->ih_vers_ihl= (IP_MIN_HDR_SIZE+
+			ip_hdropt.iho_opt_siz) >> 2;
+		tcp_hdr->th_data_off= (TCP_MIN_HDR_SIZE+
+			tcp_hdropt.tho_opt_siz) << 2;
+	}
+	else
+	{
+		hdr_acc= bf_memreq(IP_MIN_HDR_SIZE+TCP_MIN_HDR_SIZE);
+		ip_hdr= (ip_hdr_t *)ptr2acc_data(hdr_acc);
+		tcp_hdr= (tcp_hdr_t *)&ip_hdr[1];
+		hdr_acc->acc_next= data;
+
+		ip_hdr->ih_vers_ihl= IP_MIN_HDR_SIZE >> 2;
+		tcp_hdr->th_data_off= TCP_MIN_HDR_SIZE << 2;
+	}
+
+	if (!closed_connection && (tcp_conn->tc_state == TCS_CLOSED))
+	{
+		DBLOCK(1, printf("connection closed while inuse\n"));
+		bf_afree(hdr_acc);
+		return 0;
+	}
+
+	ip_hdr->ih_tos= tcp_conn->tc_tos;
+	ip_hdr->ih_ttl= tcp_conn->tc_ttl;
+	ip_hdr->ih_proto= IPPROTO_TCP;
+	ip_hdr->ih_src= tcp_conn->tc_locaddr;
+	ip_hdr->ih_dst= tcp_conn->tc_remaddr;
+	ip_hdr->ih_flags_fragoff= 0;
+	if (tcp_conn->tc_flags & TCF_PMTU)
+		ip_hdr->ih_flags_fragoff |= HTONS(IH_DONT_FRAG);
+
+	tcp_hdr->th_srcport= tcp_conn->tc_locport;
+	tcp_hdr->th_dstport= tcp_conn->tc_remport;
+	tcp_hdr->th_seq_nr= tcp_conn->tc_RCV_NXT;
+	tcp_hdr->th_flags= 0;
+	tcp_hdr->th_window= htons(tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_LO);
+	tcp_hdr->th_chksum= 0;
+	*ref_ip_hdr= ip_hdr;
+	*ref_tcp_hdr= tcp_hdr;
+	return hdr_acc;
+}
+
+PUBLIC void tcp_print_state (tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+#if DEBUG
+	printf("tcp_conn_table[%d]->tc_state= ", tcp_conn-
+		tcp_conn_table);
+	if (!(tcp_conn->tc_flags & TCF_INUSE))
+	{
+		printf("not inuse\n");
+		return;
+	}
+	switch (tcp_conn->tc_state)
+	{
+	case TCS_CLOSED: printf("CLOSED"); break;
+	case TCS_LISTEN: printf("LISTEN"); break;
+	case TCS_SYN_RECEIVED: printf("SYN_RECEIVED"); break;
+	case TCS_SYN_SENT: printf("SYN_SENT"); break;
+	case TCS_ESTABLISHED: printf("ESTABLISHED"); break;
+	case TCS_CLOSING: printf("CLOSING"); break;
+	default: printf("unknown (=%d)", tcp_conn->tc_state); break;
+	}
+#endif
+}
+
+PUBLIC int tcp_check_conn(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	int allright;
+	u32_t lo_queue, hi_queue;
+	int size;
+
+	allright= TRUE;
+	if (tcp_conn->tc_inconsistent)
+	{
+		assert(tcp_conn->tc_inconsistent == 1);
+		printf("tcp_check_conn: connection is inconsistent\n");
+		return allright;
+	}
+
+	/* checking receive queue */
+	lo_queue= tcp_conn->tc_RCV_LO;
+	if (lo_queue == tcp_conn->tc_IRS)
+		lo_queue++;
+	if (lo_queue == tcp_conn->tc_RCV_NXT && (tcp_conn->tc_flags &
+		TCF_FIN_RECV))
+		lo_queue--;
+	hi_queue= tcp_conn->tc_RCV_NXT;
+	if (hi_queue == tcp_conn->tc_IRS)
+		hi_queue++;
+	if (tcp_conn->tc_flags & TCF_FIN_RECV)
+		hi_queue--;
+
+	size= hi_queue-lo_queue;
+	if (size<0)
+	{
+		printf("rcv hi_queue-lo_queue < 0\n");
+		printf("SND_NXT= 0x%lx, SND_UNA= 0x%lx\n", 
+			(unsigned long)tcp_conn->tc_SND_NXT,
+			(unsigned long)tcp_conn->tc_SND_UNA);
+		printf("lo_queue= 0x%lx, hi_queue= 0x%lx\n", 
+			(unsigned long)lo_queue,
+			(unsigned long)hi_queue);
+		printf("size= %d\n", size);
+		allright= FALSE;
+	}
+	else if (!tcp_conn->tc_rcvd_data)
+	{
+		if (size)
+		{
+			printf("RCV_NXT-RCV_LO != 0\n");
+			tcp_print_conn(tcp_conn);
+			printf("lo_queue= %lu, hi_queue= %lu\n",
+				lo_queue, hi_queue);
+			allright= FALSE;
+		}
+	}
+	else if (size != bf_bufsize(tcp_conn->tc_rcvd_data))
+	{
+		printf("RCV_NXT-RCV_LO != sizeof tc_rcvd_data\n");
+		tcp_print_conn(tcp_conn);
+		printf(
+		"lo_queue= %lu, hi_queue= %lu, sizeof tc_rcvd_data= %d\n",
+			lo_queue, hi_queue, bf_bufsize(tcp_conn->tc_rcvd_data));
+		allright= FALSE;
+	}
+	else if (size != 0 && (tcp_conn->tc_state == TCS_CLOSED ||
+		tcp_conn->tc_state == TCS_LISTEN ||
+		tcp_conn->tc_state == TCS_SYN_RECEIVED ||
+		tcp_conn->tc_state ==  TCS_SYN_SENT))
+	{
+		printf("received data but not connected\n");
+		tcp_print_conn(tcp_conn);
+		allright= FALSE;
+	}
+	if (tcp_Lmod4G(tcp_conn->tc_RCV_HI, tcp_conn->tc_RCV_NXT))
+	{
+		printf("tc_RCV_HI (0x%lx) < tc_RCV_NXT (0x%lx)\n", 
+			(unsigned long)tcp_conn->tc_RCV_HI,
+			(unsigned long)tcp_conn->tc_RCV_NXT);
+		allright= FALSE;
+	}
+
+	/* checking send data */
+	lo_queue= tcp_conn->tc_SND_UNA;
+	if (lo_queue == tcp_conn->tc_ISS)
+		lo_queue++;
+	if (lo_queue == tcp_conn->tc_SND_NXT &&
+		(tcp_conn->tc_flags & TCF_FIN_SENT))
+	{
+		lo_queue--;
+	}
+	hi_queue= tcp_conn->tc_SND_NXT;
+	if (hi_queue == tcp_conn->tc_ISS)
+		hi_queue++;
+	if (tcp_conn->tc_flags & TCF_FIN_SENT)
+		hi_queue--;
+
+	size= hi_queue-lo_queue;
+	if (size<0)
+	{
+		printf("snd hi_queue-lo_queue < 0\n");
+		printf("SND_ISS= 0x%lx, SND_UNA= 0x%lx, SND_NXT= 0x%lx\n",
+			(unsigned long)tcp_conn->tc_ISS,
+			(unsigned long)tcp_conn->tc_SND_UNA,
+			(unsigned long)tcp_conn->tc_SND_NXT);
+		printf("hi_queue= 0x%lx, lo_queue= 0x%lx, size= %d\n",
+			(unsigned long)hi_queue, (unsigned long)lo_queue,
+			size);
+		allright= FALSE;
+	}
+	else if (!tcp_conn->tc_send_data)
+	{
+		if (size)
+		{
+			printf("SND_NXT-SND_UNA != 0\n");
+			printf("SND_NXT= 0x%lx, SND_UNA= 0x%lx\n", 
+				(unsigned long)tcp_conn->tc_SND_NXT,
+				(unsigned long)tcp_conn->tc_SND_UNA);
+			printf("lo_queue= 0x%lx, hi_queue= 0x%lx\n", 
+				(unsigned long)lo_queue,
+				(unsigned long)hi_queue);
+			allright= FALSE;
+		}
+	}
+	else if (size != bf_bufsize(tcp_conn->tc_send_data))
+	{
+		printf("SND_NXT-SND_UNA != sizeof tc_send_data\n");
+		printf("SND_NXT= 0x%lx, SND_UNA= 0x%lx\n", 
+			(unsigned long)tcp_conn->tc_SND_NXT,
+			(unsigned long)tcp_conn->tc_SND_UNA);
+		printf("lo_queue= 0x%lx, lo_queue= 0x%lx\n", 
+			(unsigned long)lo_queue,
+			(unsigned long)hi_queue);
+		printf("bf_bufsize(data)= %d\n", 
+			bf_bufsize(tcp_conn->tc_send_data));
+		
+		allright= FALSE;
+	}
+
+	/* checking counters */
+	if (!tcp_GEmod4G(tcp_conn->tc_SND_UNA, tcp_conn->tc_ISS))
+	{
+		printf("SND_UNA < ISS\n");
+		allright= FALSE;
+	}
+	if (!tcp_GEmod4G(tcp_conn->tc_SND_NXT, tcp_conn->tc_SND_UNA))
+	{
+		printf("SND_NXT<SND_UNA\n");
+		allright= FALSE;
+	}
+	if (!tcp_GEmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_SND_UNA))
+	{
+		printf("SND_TRM<SND_UNA\n");
+		allright= FALSE;
+	}
+	if (!tcp_GEmod4G(tcp_conn->tc_SND_NXT, tcp_conn->tc_SND_TRM))
+	{
+		printf("SND_NXT<SND_TRM\n");
+		allright= FALSE;
+	}
+
+	DIFBLOCK(1, (!allright), printf("tcp_check_conn: not allright\n"));
+	return allright;
+}
+
+PUBLIC void tcp_print_pack(ip_hdr, tcp_hdr)
+ip_hdr_t *ip_hdr;
+tcp_hdr_t *tcp_hdr;
+{
+	int tcp_hdr_len;
+
+	assert(tcp_hdr);
+	if (ip_hdr)
+		writeIpAddr(ip_hdr->ih_src);
+	else
+		printf("???");
+	printf(",%u ", ntohs(tcp_hdr->th_srcport));
+	if (ip_hdr)
+		writeIpAddr(ip_hdr->ih_dst);
+	else
+		printf("???");
+	printf(",%u ", ntohs(tcp_hdr->th_dstport));
+	printf(" 0x%lx", ntohl(tcp_hdr->th_seq_nr));
+	if (tcp_hdr->th_flags & THF_FIN)
+		printf(" <FIN>");
+	if (tcp_hdr->th_flags & THF_SYN)
+		printf(" <SYN>");
+	if (tcp_hdr->th_flags & THF_RST)
+		printf(" <RST>");
+	if (tcp_hdr->th_flags & THF_PSH)
+		printf(" <PSH>");
+	if (tcp_hdr->th_flags & THF_ACK)
+		printf(" <ACK 0x%lx %u>", ntohl(tcp_hdr->th_ack_nr),
+			ntohs(tcp_hdr->th_window));
+	if (tcp_hdr->th_flags & THF_URG)
+		printf(" <URG %u>", tcp_hdr->th_urgptr);
+	tcp_hdr_len= (tcp_hdr->th_data_off & TH_DO_MASK) >> 2;
+	if (tcp_hdr_len != TCP_MIN_HDR_SIZE)
+		printf(" <options %d>", tcp_hdr_len-TCP_MIN_HDR_SIZE);
+}
+
+PUBLIC void tcp_print_conn(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	u32_t iss, irs;
+	tcp_fd_t *tcp_fd;
+
+	iss= tcp_conn->tc_ISS;
+	irs= tcp_conn->tc_IRS;
+
+	tcp_print_state (tcp_conn);
+	printf(
+	" ISS 0x%lx UNA +0x%lx(0x%lx) TRM +0x%lx(0x%lx) NXT +0x%lx(0x%lx)",
+		iss, tcp_conn->tc_SND_UNA-iss, tcp_conn->tc_SND_UNA, 
+		tcp_conn->tc_SND_TRM-iss, tcp_conn->tc_SND_TRM,
+		tcp_conn->tc_SND_NXT-iss, tcp_conn->tc_SND_NXT);
+	printf(
+	" UP +0x%lx(0x%lx) PSH +0x%lx(0x%lx) ",
+		tcp_conn->tc_SND_UP-iss, tcp_conn->tc_SND_UP,
+		tcp_conn->tc_SND_PSH-iss, tcp_conn->tc_SND_PSH);
+	printf(" snd_cwnd +0x%lx(0x%lx)",
+		tcp_conn->tc_snd_cwnd-tcp_conn->tc_SND_UNA,
+		tcp_conn->tc_snd_cwnd);
+	printf(" transmit_seq ");
+	if (tcp_conn->tc_transmit_seq == 0)
+		printf("0");
+	else
+	{
+		printf("+0x%lx(0x%lx)", tcp_conn->tc_transmit_seq-iss,
+			tcp_conn->tc_transmit_seq);
+	}
+	printf(" IRS 0x%lx LO +0x%lx(0x%lx) NXT +0x%lx(0x%lx) HI +0x%lx(0x%lx)",
+		irs, tcp_conn->tc_RCV_LO-irs, tcp_conn->tc_RCV_LO,
+		tcp_conn->tc_RCV_NXT-irs, tcp_conn->tc_RCV_NXT,
+		tcp_conn->tc_RCV_HI-irs, tcp_conn->tc_RCV_HI);
+	if (tcp_conn->tc_flags & TCF_INUSE)
+		printf(" TCF_INUSE");
+	if (tcp_conn->tc_flags & TCF_FIN_RECV)
+		printf(" TCF_FIN_RECV");
+	if (tcp_conn->tc_flags & TCF_RCV_PUSH)
+		printf(" TCF_RCV_PUSH");
+	if (tcp_conn->tc_flags & TCF_MORE2WRITE)
+		printf(" TCF_MORE2WRITE");
+	if (tcp_conn->tc_flags & TCF_SEND_ACK)
+		printf(" TCF_SEND_ACK");
+	if (tcp_conn->tc_flags & TCF_FIN_SENT)
+		printf(" TCF_FIN_SENT");
+	if (tcp_conn->tc_flags & TCF_BSD_URG)
+		printf(" TCF_BSD_URG");
+	if (tcp_conn->tc_flags & TCF_NO_PUSH)
+		printf(" TCF_NO_PUSH");
+	if (tcp_conn->tc_flags & TCF_PUSH_NOW)
+		printf(" TCF_PUSH_NOW");
+	if (tcp_conn->tc_flags & TCF_PMTU)
+		printf(" TCF_PMTU");
+	printf("\n");
+	writeIpAddr(tcp_conn->tc_locaddr);
+	printf(", %u -> ", ntohs(tcp_conn->tc_locport));
+	writeIpAddr(tcp_conn->tc_remaddr);
+	printf(", %u\n", ntohs(tcp_conn->tc_remport));
+	tcp_fd= tcp_conn->tc_fd;
+	if (!tcp_fd)
+		printf("tc_fd NULL");
+	else
+	{
+		printf("tc_fd #%d: flags 0x%x, r %u@%u, w %u@%u",
+			tcp_fd-tcp_fd_table, tcp_fd->tf_flags,
+			tcp_fd->tf_read_count, tcp_fd->tf_read_offset,
+			tcp_fd->tf_write_count, tcp_fd->tf_write_offset);
+	}
+}
+
+/*
+ * $PchId: tcp_lib.c,v 1.14 2005/01/31 21:41:38 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/tcp_recv.c
===================================================================
--- /trunk/minix/servers/inet/generic/tcp_recv.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/tcp_recv.c	(revision 9)
@@ -0,0 +1,1485 @@
+/*
+tcp_recv.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "buf.h"
+#include "clock.h"
+#include "event.h"
+#include "type.h"
+#include "sr.h"
+
+#include "io.h"
+#include "tcp_int.h"
+#include "tcp.h"
+#include "assert.h"
+
+THIS_FILE
+
+FORWARD void create_RST ARGS(( tcp_conn_t *tcp_conn,
+	ip_hdr_t *ip_hdr, tcp_hdr_t *tcp_hdr, int data_len ));
+FORWARD void process_data ARGS(( tcp_conn_t *tcp_conn,
+	tcp_hdr_t *tcp_hdr, acc_t *tcp_data, int data_len ));
+FORWARD void process_advanced_data ARGS(( tcp_conn_t *tcp_conn,
+	tcp_hdr_t *tcp_hdr, acc_t *tcp_data, int data_len ));
+
+PUBLIC void tcp_frag2conn(tcp_conn, ip_hdr, tcp_hdr, tcp_data, data_len)
+tcp_conn_t *tcp_conn;
+ip_hdr_t *ip_hdr;
+tcp_hdr_t *tcp_hdr;
+acc_t *tcp_data;
+size_t data_len;
+{
+	tcp_fd_t *connuser;
+	int tcp_hdr_flags;
+	int ip_hdr_len, tcp_hdr_len;
+	u32_t seg_ack, seg_seq, rcv_hi, snd_una, snd_nxt;
+	u16_t seg_wnd, mtu;
+	size_t mss;
+	int acceptable_ACK, segm_acceptable, send_rst, close_connection;
+
+	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
+	tcp_hdr_len= (tcp_hdr->th_data_off & TH_DO_MASK) >> 2;
+
+	tcp_hdr_flags= tcp_hdr->th_flags & TH_FLAGS_MASK;
+	seg_ack= ntohl(tcp_hdr->th_ack_nr);
+	seg_seq= ntohl(tcp_hdr->th_seq_nr);
+	seg_wnd= ntohs(tcp_hdr->th_window);
+
+#if 0
+ { where(); tcp_print_conn(tcp_conn); printf("\n");
+	tcp_print_pack(ip_hdr, tcp_hdr); printf("\n"); }
+#endif
+
+	switch (tcp_conn->tc_state)
+	{
+	case TCS_CLOSED:
+/*
+CLOSED:
+	discard all data.
+	!RST ?
+		ACK ?
+			<SEQ=SEG.ACK><CTL=RST>
+			exit
+		:
+			<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>
+			exit
+	:
+		discard packet
+		exit
+*/
+
+		if (!(tcp_hdr_flags & THF_RST))
+		{
+			create_RST(tcp_conn, ip_hdr, tcp_hdr, data_len);
+			tcp_conn_write(tcp_conn, 1);
+		}
+		break;
+	case TCS_LISTEN:
+/*
+LISTEN:
+	RST ?
+		discard packet
+		exit
+	ACK ?
+		<SEQ=SEG.ACK><CTL=RST>
+		exit
+	SYN ?
+		BUG: no security check
+		RCV.NXT= SEG.SEQ+1
+		IRS= SEG.SEQ
+		ISS should already be selected
+		<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
+		SND.NXT=ISS+1
+		SND.UNA=ISS
+		state= SYN-RECEIVED
+		exit
+	:
+		shouldnot occur
+		discard packet
+		exit
+*/
+		if (tcp_hdr_flags & THF_RST)
+			break;
+		if (tcp_hdr_flags & THF_ACK)
+		{
+			create_RST (tcp_conn, ip_hdr, tcp_hdr, data_len);
+			tcp_conn_write(tcp_conn, 1);
+			break;
+		}
+		if (tcp_hdr_flags & THF_SYN)
+		{
+			tcp_extract_ipopt(tcp_conn, ip_hdr);
+			tcp_extract_tcpopt(tcp_conn, tcp_hdr, &mss);
+			mtu= mss+IP_TCP_MIN_HDR_SIZE;
+			if (mtu < IP_MIN_MTU)
+			{
+				/* No or unrealistic mss, use default MTU */
+				mtu= IP_DEF_MTU;
+			}
+			if (mtu < tcp_conn->tc_max_mtu)
+			{
+				tcp_conn->tc_max_mtu= mtu;
+				tcp_conn->tc_mtu= mtu;
+				DBLOCK(1, printf(
+					"tcp[%d]: conn[%d]: mtu = %d\n",
+					tcp_conn->tc_port-tcp_port_table,
+					tcp_conn-tcp_conn_table, 
+					mtu););
+			}
+
+			tcp_conn->tc_RCV_LO= seg_seq+1;
+			tcp_conn->tc_RCV_NXT= seg_seq+1;
+			tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO+
+				tcp_conn->tc_rcv_wnd;
+			tcp_conn->tc_RCV_UP= seg_seq;
+			tcp_conn->tc_IRS= seg_seq;
+			tcp_conn->tc_SND_UNA= tcp_conn->tc_ISS;
+			tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;
+			tcp_conn->tc_SND_NXT= tcp_conn->tc_ISS+1;
+			tcp_conn->tc_SND_UP= tcp_conn->tc_ISS-1;
+			tcp_conn->tc_SND_PSH= tcp_conn->tc_ISS-1;
+			tcp_conn->tc_state= TCS_SYN_RECEIVED;
+			tcp_conn->tc_stt= 0;
+			assert (tcp_check_conn(tcp_conn));
+			tcp_conn->tc_locaddr= ip_hdr->ih_dst;
+			tcp_conn->tc_locport= tcp_hdr->th_dstport;
+			tcp_conn->tc_remaddr= ip_hdr->ih_src;
+			tcp_conn->tc_remport= tcp_hdr->th_srcport;
+			tcp_conn_write(tcp_conn, 1);
+
+			DIFBLOCK(0x10, seg_seq == 0,
+				printf("warning got 0 IRS from ");
+				writeIpAddr(tcp_conn->tc_remaddr);
+				printf("\n"));
+
+			/* Start the timer (if necessary) */
+			tcp_set_send_timer(tcp_conn);
+
+			break;
+		}
+		/* do nothing */
+		break;
+	case TCS_SYN_SENT:
+/*
+SYN-SENT:
+	ACK ?
+		SEG.ACK <= ISS || SEG.ACK > SND.NXT ?
+			RST ?
+				discard packet
+				exit
+			:
+				<SEQ=SEG.ACK><CTL=RST>
+				exit
+		SND.UNA <= SEG.ACK && SEG.ACK <= SND.NXT ?
+			ACK is acceptable
+		:
+			ACK is !acceptable
+	:
+		ACK is !acceptable
+	RST ?
+		ACK acceptable ?
+			discard segment
+			state= CLOSED
+			error "connection refused"
+			exit
+		:
+			discard packet
+			exit
+	BUG: no security check
+	SYN ?
+		IRS= SEG.SEQ
+		RCV.NXT= IRS+1
+		ACK ?
+			SND.UNA= SEG.ACK
+		SND.UNA > ISS ?
+			state= ESTABLISHED
+			<SEQ=SND.NXT><ACK= RCV.NXT><CTL=ACK>
+			process ev. URG and text
+			exit
+		:
+			state= SYN-RECEIVED
+			SND.WND= SEG.WND
+			SND.WL1= SEG.SEQ
+			SND.WL2= SEG.ACK
+			<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
+			exit
+	:
+		discard segment
+		exit
+*/
+		if (tcp_hdr_flags & THF_ACK)
+		{
+			if (tcp_LEmod4G(seg_ack, tcp_conn->tc_ISS) ||
+				tcp_Gmod4G(seg_ack, tcp_conn->tc_SND_NXT))
+				if (tcp_hdr_flags & THF_RST)
+					break;
+				else
+				{
+					/* HACK: force sending a RST,
+					 * normally, RSTs are not send
+					 * if the segment is an ACK.
+					 */
+					create_RST (tcp_conn, ip_hdr,
+						tcp_hdr, data_len+1);
+					tcp_conn_write(tcp_conn, 1);
+					break;
+				}
+			acceptable_ACK= (tcp_LEmod4G(tcp_conn->tc_SND_UNA,
+				seg_ack) && tcp_LEmod4G(seg_ack,
+				tcp_conn->tc_SND_NXT));
+		}
+		else
+			acceptable_ACK= FALSE;
+		if (tcp_hdr_flags & THF_RST)
+		{
+			if (acceptable_ACK)
+			{
+				DBLOCK(1, printf(
+					"calling tcp_close_connection\n"));
+
+				tcp_close_connection(tcp_conn,
+					ECONNREFUSED);
+			}
+			break;
+		}
+		if (tcp_hdr_flags & THF_SYN)
+		{
+			tcp_extract_ipopt(tcp_conn, ip_hdr);
+			tcp_extract_tcpopt(tcp_conn, tcp_hdr, &mss);
+			mtu= mss+IP_TCP_MIN_HDR_SIZE;
+			if (mtu < IP_MIN_MTU)
+			{
+				/* No or unrealistic mss, use default MTU */
+				mtu= IP_DEF_MTU;
+			}
+			if (mtu < tcp_conn->tc_max_mtu)
+			{
+				tcp_conn->tc_max_mtu= mtu;
+				tcp_conn->tc_mtu= mtu;
+				DBLOCK(1, printf(
+					"tcp[%d]: conn[%d]: mtu = %d\n",
+					tcp_conn->tc_port-tcp_port_table,
+					tcp_conn-tcp_conn_table, 
+					mtu););
+			}
+			tcp_conn->tc_RCV_LO= seg_seq+1;
+			tcp_conn->tc_RCV_NXT= seg_seq+1;
+			tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO +
+				tcp_conn->tc_rcv_wnd;
+			tcp_conn->tc_RCV_UP= seg_seq;
+			tcp_conn->tc_IRS= seg_seq;
+			if (tcp_hdr_flags & THF_ACK)
+				tcp_conn->tc_SND_UNA= seg_ack;
+			if (tcp_Gmod4G(tcp_conn->tc_SND_UNA,
+				tcp_conn->tc_ISS))
+			{
+				tcp_conn->tc_state= TCS_ESTABLISHED;
+				tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD;
+
+				assert (tcp_check_conn(tcp_conn));
+				assert(tcp_conn->tc_connInprogress);
+
+				tcp_restart_connect(tcp_conn);
+
+				tcp_conn->tc_flags |= TCF_SEND_ACK;
+				tcp_conn_write(tcp_conn, 1);
+				if (data_len != 0)
+				{
+					tcp_frag2conn(tcp_conn, ip_hdr,
+						tcp_hdr, tcp_data, data_len);
+					/* tcp_data is already freed */
+					return;
+				}
+				break;
+			}
+			tcp_conn->tc_state= TCS_SYN_RECEIVED;
+
+			assert (tcp_check_conn(tcp_conn));
+
+			tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;
+			tcp_conn_write(tcp_conn, 1);
+		}
+		break;
+
+	case TCS_SYN_RECEIVED:
+/*
+SYN-RECEIVED:
+	test if segment is acceptable:
+
+	Segment	Receive	Test
+	Length	Window
+	0	0	SEG.SEQ == RCV.NXT
+	0	>0	RCV.NXT <= SEG.SEQ && SEG.SEQ < RCV.NXT+RCV.WND
+	>0	0	not acceptable
+	>0	>0	(RCV.NXT <= SEG.SEQ && SEG.SEQ < RCV.NXT+RCV.WND)
+			|| (RCV.NXT <= SEG.SEQ+SEG.LEN-1 &&
+			SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND)
+	for urgent data: use RCV.WND+1 for RCV.WND
+
+	Special: Send RST if SEG.SEQ < IRS or SEG.SEQ > RCV.NXT+64K (and
+		 the packet is not a RST packet itself).
+*/
+		rcv_hi= tcp_conn->tc_RCV_HI;
+		if (tcp_hdr_flags & THF_URG)
+			rcv_hi++;
+		send_rst= tcp_Lmod4G(seg_seq, tcp_conn->tc_IRS) ||
+			tcp_Gmod4G(seg_seq, tcp_conn->tc_RCV_NXT+0x10000);
+		close_connection= 0;
+
+		if (!data_len)
+		{
+			if (rcv_hi == tcp_conn->tc_RCV_NXT)
+				segm_acceptable= (seg_seq == rcv_hi);
+			else
+			{
+				assert (tcp_Gmod4G(rcv_hi,
+					tcp_conn->tc_RCV_NXT));
+				segm_acceptable= (tcp_LEmod4G(tcp_conn->
+					tc_RCV_NXT, seg_seq) &&
+					tcp_Lmod4G(seg_seq, rcv_hi));
+			}
+		}
+		else
+		{
+			if (tcp_Gmod4G(rcv_hi, tcp_conn->tc_RCV_NXT))
+			{
+				segm_acceptable= (tcp_LEmod4G(tcp_conn->
+					tc_RCV_NXT, seg_seq) &&
+					tcp_Lmod4G(seg_seq, rcv_hi)) ||
+					(tcp_LEmod4G(tcp_conn->tc_RCV_NXT,
+					seg_seq+data_len-1) &&
+					tcp_Lmod4G(seg_seq+data_len-1,
+					rcv_hi));
+			}
+			else
+			{
+				segm_acceptable= FALSE;
+			}
+		}
+/*
+	!segment acceptable ?
+		RST ?
+			discard packet
+			exit
+		:
+			<SEG=SND.NXT><ACK=RCV.NXT><CTL=ACK>
+			exit
+*/
+		if (!segm_acceptable)
+		{
+			if (tcp_hdr_flags & THF_RST)
+				; /* do nothing */
+			else if (send_rst)
+			{
+				create_RST(tcp_conn, ip_hdr, tcp_hdr,
+					data_len);
+				tcp_conn_write(tcp_conn, 1);
+			}
+			else
+			{
+				tcp_conn->tc_flags |= TCF_SEND_ACK;
+				tcp_conn_write(tcp_conn, 1);
+			}
+			break;
+		}
+/*
+	RST ?
+		initiated by a LISTEN ?
+			state= LISTEN
+			exit
+		:
+			state= CLOSED
+			error "connection refused"
+			exit
+*/
+
+		if (tcp_hdr_flags & THF_RST)
+			close_connection= 1;
+
+/*
+	SYN in window ?
+		initiated by a LISTEN ?
+			state= LISTEN
+			exit
+		:
+			state= CLOSED
+			error "connection reset"
+			exit
+*/
+		if ((tcp_hdr_flags & THF_SYN) && tcp_GEmod4G(seg_seq,
+			tcp_conn->tc_RCV_NXT))
+		{
+			close_connection= 1;
+		}
+
+		if (close_connection)
+		{
+			if (!tcp_conn->tc_orglisten)
+			{
+				tcp_close_connection(tcp_conn, ECONNREFUSED);
+				break;
+			}
+
+			connuser= tcp_conn->tc_fd;
+			assert(connuser);
+			if (connuser->tf_flags & TFF_LISTENQ)
+			{
+				tcp_close_connection (tcp_conn,
+					ECONNREFUSED);
+			}
+			else
+			{
+				tcp_conn->tc_connInprogress= 0;
+				tcp_conn->tc_fd= NULL;
+
+				tcp_close_connection (tcp_conn,
+					ECONNREFUSED);
+
+				/* Pick a new ISS next time */
+				tcp_conn->tc_ISS= 0;
+
+				(void)tcp_su4listen(connuser, tcp_conn,
+					0 /* !do_listenq */);
+			}
+			break;
+		}
+/*
+	!ACK ?
+		discard packet
+		exit
+*/
+		if (!(tcp_hdr_flags & THF_ACK))
+			break;
+/*
+	SND.UNA < SEG.ACK <= SND.NXT ?
+		state= ESTABLISHED
+	:
+		<SEG=SEG.ACK><CTL=RST>
+		exit
+*/
+		if (tcp_Lmod4G(tcp_conn->tc_SND_UNA, seg_ack) &&
+			tcp_LEmod4G(seg_ack, tcp_conn->tc_SND_NXT))
+		{
+			tcp_conn->tc_state= TCS_ESTABLISHED;
+			tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD;
+
+			tcp_release_retrans(tcp_conn, seg_ack, seg_wnd);
+
+			assert (tcp_check_conn(tcp_conn));
+			assert(tcp_conn->tc_connInprogress);
+
+			tcp_restart_connect(tcp_conn);
+			tcp_frag2conn(tcp_conn, ip_hdr, tcp_hdr, tcp_data,
+				data_len);
+			/* tcp_data is already freed */
+			return;
+		}
+		else
+		{
+			create_RST (tcp_conn, ip_hdr, tcp_hdr, data_len);
+			tcp_conn_write(tcp_conn, 1);
+			break;
+		}
+		break;
+
+	case TCS_ESTABLISHED:
+	case TCS_CLOSING:
+/*
+ESTABLISHED:
+FIN-WAIT-1:
+FIN-WAIT-2:
+CLOSE-WAIT:
+CLOSING:
+LAST-ACK:
+TIME-WAIT:
+	test if segment is acceptable:
+	Segment	Receive	Test
+	Length	Window
+	0	0	SEG.SEQ == RCV.NXT
+	0	>0	RCV.NXT <= SEG.SEQ && SEG.SEQ < RCV.NXT+RCV.WND
+	>0	0	not acceptable
+	>0	>0	(RCV.NXT <= SEG.SEQ && SEG.SEQ < RCV.NXT+RCV.WND)
+			|| (RCV.NXT <= SEG.SEQ+SEG.LEN-1 &&
+			SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND)
+	for urgent data: use RCV.WND+1 for RCV.WND
+*/
+		rcv_hi= tcp_conn->tc_RCV_HI;
+		if (tcp_hdr_flags & THF_URG)
+			rcv_hi++;
+		if (!data_len)
+		{
+			if (rcv_hi == tcp_conn->tc_RCV_NXT)
+				segm_acceptable= (seg_seq == rcv_hi);
+			else
+			{
+				assert (tcp_Gmod4G(rcv_hi,
+					tcp_conn->tc_RCV_NXT));
+				segm_acceptable= (tcp_LEmod4G(tcp_conn->
+					tc_RCV_NXT, seg_seq) &&
+					tcp_Lmod4G(seg_seq, rcv_hi));
+			}
+		}
+		else
+		{
+			if (tcp_Gmod4G(rcv_hi, tcp_conn->tc_RCV_NXT))
+			{
+				segm_acceptable= (tcp_LEmod4G(tcp_conn->
+					tc_RCV_NXT, seg_seq) &&
+					tcp_Lmod4G(seg_seq, rcv_hi)) ||
+					(tcp_LEmod4G(tcp_conn->tc_RCV_NXT,
+					seg_seq+data_len-1) &&
+					tcp_Lmod4G(seg_seq+data_len-1,
+					rcv_hi));
+			}
+			else
+			{
+				segm_acceptable= FALSE;
+			}
+		}
+/*
+	!segment acceptable ?
+		RST ?
+			discard packet
+			exit
+		:
+			<SEG=SND.NXT><ACK=RCV.NXT><CTL=ACK>
+			exit
+*/
+		if (!segm_acceptable)
+		{
+			if (!(tcp_hdr_flags & THF_RST))
+			{
+				DBLOCK(0x20,
+					printf("segment is not acceptable\n");
+					printf("\t");
+					tcp_print_pack(ip_hdr, tcp_hdr);
+					printf("\n\t");
+					tcp_print_conn(tcp_conn);
+					printf("\n"));
+				tcp_conn->tc_flags |= TCF_SEND_ACK;
+				tcp_conn_write(tcp_conn, 1);
+
+				/* Sometimes, a retransmission sets the PSH
+				 * flag (Solaris 2.4)
+				 */
+				if (tcp_conn->tc_rcvd_data != NULL &&
+					(tcp_hdr_flags & THF_PSH))
+				{
+					tcp_conn->tc_flags |= TCF_RCV_PUSH;
+					if (tcp_conn->tc_fd &&
+						(tcp_conn->tc_fd->tf_flags &
+						TFF_READ_IP))
+					{
+						tcp_fd_read(tcp_conn, 1);
+					}
+					if (tcp_conn->tc_fd &&
+						(tcp_conn->tc_fd->tf_flags &
+						TFF_SEL_READ))
+					{
+						tcp_rsel_read(tcp_conn);
+					}
+				}
+			}
+			break;
+		}
+/*
+	RST ?
+		state == CLOSING || state == LAST-ACK ||
+			state == TIME-WAIT ?
+			state= CLOSED
+			exit
+		:
+			state= CLOSED
+			error "connection reset"
+			exit
+*/
+		if (tcp_hdr_flags & THF_RST)
+		{
+			if ((tcp_conn->tc_flags &
+				(TCF_FIN_SENT|TCF_FIN_RECV)) ==
+				(TCF_FIN_SENT|TCF_FIN_RECV) &&
+				tcp_conn->tc_send_data == NULL)
+			{
+				/* Clean shutdown, but the other side
+				 * doesn't want to ACK our FIN.
+				 */
+				tcp_close_connection (tcp_conn, 0);
+			}
+			else
+				tcp_close_connection(tcp_conn, ECONNRESET);
+			break;
+		}
+/*
+	SYN in window ?
+		state= CLOSED
+		error "connection reset"
+		exit
+*/
+		if ((tcp_hdr_flags & THF_SYN) && tcp_GEmod4G(seg_seq,
+			tcp_conn->tc_RCV_NXT))
+		{
+			tcp_close_connection(tcp_conn, ECONNRESET);
+			break;
+		}
+/*
+	!ACK ?
+		discard packet
+		exit
+*/
+		if (!(tcp_hdr_flags & THF_ACK))
+			break;
+
+/*
+	SND.UNA < SEG.ACK <= SND.NXT ?
+		SND.UNA= SEG.ACK
+		reply "send ok"
+		SND.WL1 < SEG.SEQ || (SND.WL1 == SEG.SEQ &&
+			SND.WL2 <= SEG.ACK ?
+			SND.WND= SEG.WND
+			SND.Wl1= SEG.SEQ
+			SND.WL2= SEG.ACK
+	SEG.ACK <= SND.UNA ?
+		ignore ACK
+	SEG.ACK > SND.NXT ?
+		<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
+		discard packet
+		exit
+*/
+
+		/* Always reset the send timer after a valid ack is
+		 * received. The assumption is that either the ack really
+		 * acknowledges some data (normal case), contains a zero
+		 * window, or the remote host has another reason not
+		 * to accept any data. In all cases, the remote host is
+		 * alive, so the connection should stay alive too.
+		 * Do not reset stt if the state is CLOSING, i.e. if
+		 * the user closed the connection and we still have
+		 * some data to deliver. We don't want a zero window
+		 * to keep us from closing the connection.
+		 */
+		if (tcp_conn->tc_state != TCS_CLOSING)
+			tcp_conn->tc_stt= 0;
+
+		snd_una= tcp_conn->tc_SND_UNA;
+		snd_nxt= tcp_conn->tc_SND_NXT;
+		if (seg_ack == snd_una)
+		{
+			
+			if (tcp_Gmod4G(snd_nxt, snd_una))
+			{
+				/* Duplicate ACK */
+				if (++tcp_conn->tc_snd_dack ==
+					TCP_DACK_RETRANS)
+				{
+					tcp_fast_retrans(tcp_conn);
+				}
+			}
+
+			/* This ACK doesn't acknowledge any new data, this
+			 * is a likely situation if we are only receiving
+			 * data. We only update the window if we are
+			 * actually sending or if we currently have a
+			 * zero window.
+			 */
+			if (tcp_conn->tc_snd_cwnd == snd_una &&
+				seg_wnd != 0)
+			{
+				DBLOCK(2, printf("zero window opened\n"));
+				/* The other side opened up its receive
+				 * window. */
+				mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
+				if (seg_wnd > 2*mss)
+					seg_wnd= 2*mss;
+				tcp_conn->tc_snd_cwnd= snd_una+seg_wnd;
+				tcp_conn_write(tcp_conn, 1);
+			}
+			if (seg_wnd == 0)
+			{
+				tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_TRM=
+					snd_una;
+			}
+		}
+		else if (tcp_Lmod4G(snd_una, seg_ack) &&
+			tcp_LEmod4G(seg_ack, snd_nxt))
+		{
+			tcp_release_retrans(tcp_conn, seg_ack, seg_wnd);
+			if (tcp_conn->tc_state == TCS_CLOSED)
+				break;
+		}
+		else if (tcp_Gmod4G(seg_ack,
+			snd_nxt))
+		{
+			tcp_conn->tc_flags |= TCF_SEND_ACK;
+			tcp_conn_write(tcp_conn, 1);
+			DBLOCK(1, printf(
+			"got an ack of something I haven't send\n");
+				printf( "seg_ack= %lu, SND_NXT= %lu\n",
+				seg_ack, snd_nxt));
+			break;
+		}
+
+/*
+	process data...
+*/
+		tcp_extract_ipopt(tcp_conn, ip_hdr);
+		tcp_extract_tcpopt(tcp_conn, tcp_hdr, &mss);
+
+		if (data_len)
+		{
+			if (tcp_LEmod4G(seg_seq, tcp_conn->tc_RCV_NXT))
+			{
+				process_data (tcp_conn, tcp_hdr,
+					tcp_data, data_len);
+			}
+			else
+			{
+				process_advanced_data (tcp_conn,
+					tcp_hdr, tcp_data, data_len);
+			}
+			tcp_conn->tc_flags |= TCF_SEND_ACK;
+			tcp_conn_write(tcp_conn, 1);
+
+			/* Don't process a FIN if we got new data */
+			break;
+		}
+/*
+	FIN ?
+		reply pending receives
+		advace RCV.NXT over the FIN
+		<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
+
+		state == ESTABLISHED ?
+			state= CLOSE-WAIT
+		state == FIN-WAIT-1 ?
+			state= CLOSING
+		state == FIN-WAIT-2 ?
+			state= TIME-WAIT
+		state == TIME-WAIT ?
+			restart the TIME-WAIT timer
+	exit
+*/
+		if ((tcp_hdr_flags & THF_FIN) && tcp_LEmod4G(seg_seq,
+			tcp_conn->tc_RCV_NXT))
+		{
+			if (!(tcp_conn->tc_flags & TCF_FIN_RECV) &&
+				tcp_Lmod4G(tcp_conn->tc_RCV_NXT,
+				tcp_conn->tc_RCV_HI))
+			{
+				tcp_conn->tc_RCV_NXT++;
+				tcp_conn->tc_flags |= TCF_FIN_RECV;
+			}
+			tcp_conn->tc_flags |= TCF_SEND_ACK;
+			tcp_conn_write(tcp_conn, 1);
+			if (tcp_conn->tc_fd &&
+				(tcp_conn->tc_fd->tf_flags & TFF_READ_IP))
+			{
+				tcp_fd_read(tcp_conn, 1);
+			}
+			if (tcp_conn->tc_fd &&
+				(tcp_conn->tc_fd->tf_flags & TFF_SEL_READ))
+			{
+				tcp_rsel_read(tcp_conn);
+			}
+		}
+		break;
+	default:
+		printf("tcp_frag2conn: unknown state ");
+		tcp_print_state(tcp_conn);
+		break;
+	}
+	if (tcp_data != NULL)
+		bf_afree(tcp_data);
+}
+
+
+PRIVATE void
+process_data(tcp_conn, tcp_hdr, tcp_data, data_len)
+tcp_conn_t *tcp_conn;
+tcp_hdr_t *tcp_hdr;
+acc_t *tcp_data;
+int data_len;
+{
+	u32_t lo_seq, hi_seq, urg_seq, seq_nr, adv_seq, nxt;
+	u32_t urgptr;
+	int tcp_hdr_flags;
+	unsigned int offset;
+	acc_t *tmp_data, *rcvd_data, *adv_data;
+	int len_diff;
+
+	assert(tcp_conn->tc_busy);
+
+	/* Note, tcp_data will be freed by the caller. */
+	assert (!(tcp_hdr->th_flags & THF_SYN));
+
+	seq_nr= ntohl(tcp_hdr->th_seq_nr);
+	urgptr= ntohs(tcp_hdr->th_urgptr);
+
+	tcp_data->acc_linkC++;
+
+	lo_seq= seq_nr;
+	tcp_hdr_flags= tcp_hdr->th_flags & TH_FLAGS_MASK;
+
+	if (tcp_Lmod4G(lo_seq, tcp_conn->tc_RCV_NXT))
+	{
+		DBLOCK(0x10,
+			printf("segment is a retransmission\n"));
+		offset= tcp_conn->tc_RCV_NXT-lo_seq;
+		tcp_data= bf_delhead(tcp_data, offset);
+		lo_seq += offset;
+		data_len -= offset;
+		if (tcp_hdr_flags & THF_URG)
+		{
+			printf("process_data: updating urgent pointer\n");
+			if (urgptr >= offset)
+				urgptr -= offset;
+			else
+				tcp_hdr_flags &= ~THF_URG;
+		}
+	}
+	assert (lo_seq == tcp_conn->tc_RCV_NXT);
+
+	if (tcp_hdr_flags & THF_URG)
+	{
+		if (!(tcp_conn->tc_flags & TCF_BSD_URG))
+		{
+			/* Update urgent pointer to point past the urgent
+			 * data
+			 */
+			urgptr++;
+		}
+		if (urgptr == 0)
+			tcp_hdr_flags &= ~THF_URG;
+	}
+
+	if (tcp_hdr_flags & THF_URG)
+	{
+		if (urgptr > data_len)
+			urgptr= data_len;
+		urg_seq= lo_seq+urgptr;
+
+		if (tcp_GEmod4G(urg_seq, tcp_conn->tc_RCV_HI))
+			urg_seq= tcp_conn->tc_RCV_HI;
+		if (tcp_conn->tc_flags & TCF_BSD_URG)
+		{
+			if (tcp_Gmod4G(tcp_conn->tc_RCV_NXT,
+				tcp_conn->tc_RCV_LO))
+			{
+				DBLOCK(1, printf(
+					"ignoring urgent data\n"));
+
+				bf_afree(tcp_data);
+				/* Should set advertised window to
+				 * zero */
+
+				/* Flush */
+				tcp_conn->tc_flags |= TCF_RCV_PUSH;
+				if (tcp_conn->tc_fd &&
+					(tcp_conn->tc_fd->tf_flags &
+					TFF_READ_IP))
+				{
+					tcp_fd_read(tcp_conn, 1);
+				}
+				if (tcp_conn->tc_fd &&
+					(tcp_conn->tc_fd->tf_flags &
+					TFF_SEL_READ))
+				{
+					tcp_rsel_read(tcp_conn);
+				}
+				return;
+			}
+		}
+		if (tcp_Gmod4G(urg_seq, tcp_conn->tc_RCV_UP))
+			tcp_conn->tc_RCV_UP= urg_seq;
+#if 0
+		if (urgptr < data_len)
+		{
+			data_len= urgptr;
+			tmp_data= bf_cut(tcp_data, 0, data_len);
+			bf_afree(tcp_data);
+			tcp_data= tmp_data;
+			tcp_hdr_flags &= ~THF_FIN;
+		}
+#endif
+		tcp_conn->tc_flags |= TCF_RCV_PUSH;
+	}
+	else
+	{
+		/* Normal data. */
+	}
+
+	if (tcp_hdr_flags & THF_PSH)
+	{
+		tcp_conn->tc_flags |= TCF_RCV_PUSH;
+	}
+
+	hi_seq= lo_seq+data_len;
+	if (tcp_Gmod4G(hi_seq, tcp_conn->tc_RCV_HI))
+	{
+		data_len= tcp_conn->tc_RCV_HI-lo_seq;
+		tmp_data= bf_cut(tcp_data, 0, data_len);
+		bf_afree(tcp_data);
+		tcp_data= tmp_data;
+		hi_seq= lo_seq+data_len;
+		tcp_hdr_flags &= ~THF_FIN;
+	}
+	assert (tcp_LEmod4G (hi_seq, tcp_conn->tc_RCV_HI));
+
+	rcvd_data= tcp_conn->tc_rcvd_data;
+	tcp_conn->tc_rcvd_data= 0;
+	tmp_data= bf_append(rcvd_data, tcp_data);
+	tcp_conn->tc_rcvd_data= tmp_data;
+	tcp_conn->tc_RCV_NXT= hi_seq;
+
+	if ((tcp_hdr_flags & THF_FIN) && 
+		tcp_Lmod4G(tcp_conn->tc_RCV_NXT, tcp_conn->tc_RCV_HI) &&
+		!(tcp_conn->tc_flags & TCF_FIN_RECV))
+	{
+		tcp_conn->tc_RCV_NXT++;
+		tcp_conn->tc_flags |= TCF_FIN_RECV;
+	}
+
+	if (tcp_conn->tc_fd && (tcp_conn->tc_fd->tf_flags & TFF_READ_IP))
+		tcp_fd_read(tcp_conn, 1);
+	if (tcp_conn->tc_fd && (tcp_conn->tc_fd->tf_flags & TFF_SEL_READ))
+		tcp_rsel_read(tcp_conn);
+
+	DIFBLOCK(2, (tcp_conn->tc_RCV_NXT == tcp_conn->tc_RCV_HI),
+		printf("conn[[%d] full receive buffer\n", 
+		tcp_conn-tcp_conn_table));
+
+	if (tcp_conn->tc_adv_data == NULL)
+		return;
+	if (tcp_hdr_flags & THF_FIN)
+	{
+		printf("conn[%d]: advanced data after FIN\n",
+			tcp_conn-tcp_conn_table);
+		tcp_data= tcp_conn->tc_adv_data;
+		tcp_conn->tc_adv_data= NULL;
+		bf_afree(tcp_data);
+		return;
+	}
+
+	lo_seq= tcp_conn->tc_adv_seq;
+	if (tcp_Gmod4G(lo_seq, tcp_conn->tc_RCV_NXT))
+		return;		/* Not yet */
+
+	tcp_data= tcp_conn->tc_adv_data;
+	tcp_conn->tc_adv_data= NULL;
+
+	data_len= bf_bufsize(tcp_data);
+	if (tcp_Lmod4G(lo_seq, tcp_conn->tc_RCV_NXT))
+	{
+		offset= tcp_conn->tc_RCV_NXT-lo_seq;
+		if (offset >= data_len)
+		{
+			bf_afree(tcp_data);
+			return;
+		}
+		tcp_data= bf_delhead(tcp_data, offset);
+		lo_seq += offset;
+		data_len -= offset;
+	}
+	assert (lo_seq == tcp_conn->tc_RCV_NXT);
+
+	hi_seq= lo_seq+data_len;
+	assert (tcp_LEmod4G (hi_seq, tcp_conn->tc_RCV_HI));
+
+	rcvd_data= tcp_conn->tc_rcvd_data;
+	tcp_conn->tc_rcvd_data= 0;
+	tmp_data= bf_append(rcvd_data, tcp_data);
+	tcp_conn->tc_rcvd_data= tmp_data;
+	tcp_conn->tc_RCV_NXT= hi_seq;
+
+	assert (tcp_conn->tc_RCV_LO + bf_bufsize(tcp_conn->tc_rcvd_data) ==
+		tcp_conn->tc_RCV_NXT ||
+		(tcp_print_conn(tcp_conn), printf("\n"), 0));
+
+	if (tcp_conn->tc_fd && (tcp_conn->tc_fd->tf_flags & TFF_READ_IP))
+		tcp_fd_read(tcp_conn, 1);
+	if (tcp_conn->tc_fd && (tcp_conn->tc_fd->tf_flags & TFF_SEL_READ))
+		tcp_rsel_read(tcp_conn);
+
+	adv_data= tcp_conn->tc_adv_data;
+	if (adv_data != NULL)
+	{
+		/* Try to use advanced data. */
+		adv_seq= tcp_conn->tc_adv_seq;
+		nxt= tcp_conn->tc_RCV_NXT;
+
+		if (tcp_Gmod4G(adv_seq, nxt))
+			return;		/* not yet */
+
+		tcp_conn->tc_adv_data= NULL;
+		data_len= bf_bufsize(adv_data);
+
+		if (tcp_Lmod4G(adv_seq, nxt))
+		{
+			if (tcp_LEmod4G(adv_seq+data_len, nxt))
+			{
+				/* Data is not needed anymore. */
+				bf_afree(adv_data);
+				return;
+			}
+
+			len_diff= nxt-adv_seq;
+			adv_data= bf_delhead(adv_data, len_diff);
+			data_len -= len_diff;
+		}
+
+		DBLOCK(1, printf("using advanced data\n"));
+
+		/* Append data to the input buffer */
+		if (tcp_conn->tc_rcvd_data == NULL)
+		{
+			tcp_conn->tc_rcvd_data= adv_data;
+		}
+		else
+		{
+			tcp_conn->tc_rcvd_data=
+				bf_append(tcp_conn->tc_rcvd_data, adv_data);
+		}
+		tcp_conn->tc_SND_NXT += data_len;
+		assert(tcp_check_conn(tcp_conn));
+
+		if (tcp_conn->tc_fd &&
+			(tcp_conn->tc_fd->tf_flags & TFF_READ_IP))
+		{
+			tcp_fd_read(tcp_conn, 1);
+		}
+		if (tcp_conn->tc_fd &&
+			(tcp_conn->tc_fd->tf_flags & TFF_SEL_READ))
+		{
+			tcp_rsel_read(tcp_conn);
+		}
+	}
+}
+
+PRIVATE void process_advanced_data(tcp_conn, tcp_hdr, tcp_data, data_len)
+tcp_conn_t *tcp_conn;
+tcp_hdr_t *tcp_hdr;
+acc_t *tcp_data;
+int data_len;
+{
+	u32_t seq, adv_seq;
+	acc_t *adv_data;
+
+	assert(tcp_conn->tc_busy);
+
+	/* Note, tcp_data will be freed by the caller. */
+
+	/* Always send an ACK, this allows the sender to do a fast
+	 * retransmit.
+	 */
+	tcp_conn->tc_flags |= TCF_SEND_ACK;
+	tcp_conn_write(tcp_conn, 1);
+
+	if (tcp_hdr->th_flags & THF_URG)
+		return;	/* Urgent data is to complicated */
+
+	if (tcp_hdr->th_flags & THF_PSH)
+		tcp_conn->tc_flags |= TCF_RCV_PUSH;
+	seq= ntohl(tcp_hdr->th_seq_nr);
+
+	/* Make sure that the packet doesn't fall outside of the window
+	 * we offered.
+	 */
+	if (tcp_Gmod4G(seq+data_len, tcp_conn->tc_RCV_HI))
+		return;
+
+	adv_data= tcp_conn->tc_adv_data;
+	adv_seq= tcp_conn->tc_adv_seq;
+	tcp_conn->tc_adv_data= NULL;
+
+	tcp_data->acc_linkC++;
+	if (adv_data == NULL)
+	{
+		adv_seq= seq;
+		adv_data= tcp_data;
+	}
+	else if (seq + data_len == adv_seq)
+	{
+		/* New data fits right before exiting data. */
+		adv_data= bf_append(tcp_data, adv_data);
+		adv_seq= seq;
+	}
+	else if (adv_seq + bf_bufsize(adv_data) == seq)
+	{
+		/* New data fits right after exiting data. */
+		adv_data= bf_append(adv_data, tcp_data);
+	}
+	else
+	{
+		/* New data doesn't fit. */
+		bf_afree(tcp_data);
+	}
+	tcp_conn->tc_adv_data= adv_data;
+	tcp_conn->tc_adv_seq= adv_seq;
+}
+				
+PRIVATE void create_RST(tcp_conn, ip_hdr, tcp_hdr, data_len)
+tcp_conn_t *tcp_conn;
+ip_hdr_t *ip_hdr;
+tcp_hdr_t *tcp_hdr;
+int data_len;
+{
+	acc_t *tmp_ipopt, *tmp_tcpopt, *tcp_pack;
+	acc_t *RST_acc;
+	ip_hdr_t *RST_ip_hdr;
+	tcp_hdr_t *RST_tcp_hdr;
+	size_t pack_size, ip_hdr_len, mss;
+
+	DBLOCK(0x10, printf("in create_RST, bad pack is:\n"); 
+		tcp_print_pack(ip_hdr, tcp_hdr); tcp_print_state(tcp_conn);
+		printf("\n"));
+
+	assert(tcp_conn->tc_busy);
+
+	/* Only send RST packets in reponse to actual data (or SYN, FIN)
+	 * this solves a problem during connection shutdown. The problem
+	 * is the follow senario: a senders closes the connection instead
+	 * of doing a shutdown and waiting for the receiver to shutdown.
+	 * The receiver is slow in processing the last data. After the
+	 * sender has completely closed the connection, the receiver
+	 * sends a window update which triggers the sender to send a
+	 * RST. The receiver closes the connection in reponse to the RST.
+	 */
+	if ((tcp_hdr->th_flags & (THF_FIN|THF_SYN)) == 0 &&
+		data_len == 0)
+	{
+#if DEBUG
+ { printf("tcp_recv`create_RST: no data, no RST\n"); }
+#endif
+		return;
+	}
+
+	tmp_ipopt= tcp_conn->tc_remipopt;
+	if (tmp_ipopt)
+		tmp_ipopt->acc_linkC++;
+	tmp_tcpopt= tcp_conn->tc_tcpopt;
+	if (tmp_tcpopt)
+		tmp_tcpopt->acc_linkC++;
+
+	tcp_extract_ipopt (tcp_conn, ip_hdr);
+	tcp_extract_tcpopt (tcp_conn, tcp_hdr, &mss);
+
+	RST_acc= tcp_make_header (tcp_conn, &RST_ip_hdr, &RST_tcp_hdr,
+		(acc_t *)0);
+
+	if (tcp_conn->tc_remipopt)
+		bf_afree(tcp_conn->tc_remipopt);
+	tcp_conn->tc_remipopt= tmp_ipopt;
+	if (tcp_conn->tc_tcpopt)
+		bf_afree(tcp_conn->tc_tcpopt);
+	tcp_conn->tc_tcpopt= tmp_tcpopt;
+
+	RST_ip_hdr->ih_src= ip_hdr->ih_dst;
+	RST_ip_hdr->ih_dst= ip_hdr->ih_src;
+
+	RST_tcp_hdr->th_srcport= tcp_hdr->th_dstport;
+	RST_tcp_hdr->th_dstport= tcp_hdr->th_srcport;
+	if (tcp_hdr->th_flags & THF_ACK)
+	{
+		RST_tcp_hdr->th_seq_nr= tcp_hdr->th_ack_nr;
+		RST_tcp_hdr->th_flags= THF_RST;
+	}
+	else
+	{
+		RST_tcp_hdr->th_seq_nr= 0;
+		RST_tcp_hdr->th_ack_nr=
+			htonl(
+				ntohl(tcp_hdr->th_seq_nr)+
+				data_len +
+				(tcp_hdr->th_flags & THF_SYN ? 1 : 0) +
+				(tcp_hdr->th_flags & THF_FIN ? 1 : 0));
+		RST_tcp_hdr->th_flags= THF_RST|THF_ACK;
+	}
+
+	pack_size= bf_bufsize(RST_acc);
+	RST_ip_hdr->ih_length= htons(pack_size);
+	RST_tcp_hdr->th_window= htons(tcp_conn->tc_rcv_wnd);
+	RST_tcp_hdr->th_chksum= 0;
+
+	RST_acc->acc_linkC++;
+	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
+	tcp_pack= bf_delhead(RST_acc, ip_hdr_len);
+	RST_tcp_hdr->th_chksum= ~tcp_pack_oneCsum (RST_ip_hdr, tcp_pack);
+	bf_afree(tcp_pack);
+	
+	DBLOCK(2, tcp_print_pack(ip_hdr, tcp_hdr); printf("\n");
+		tcp_print_pack(RST_ip_hdr, RST_tcp_hdr); printf("\n"));
+
+	if (tcp_conn->tc_frag2send)
+		bf_afree(tcp_conn->tc_frag2send);
+	tcp_conn->tc_frag2send= RST_acc;
+	tcp_conn_write(tcp_conn, 1);
+}
+
+PUBLIC void
+tcp_fd_read(tcp_conn, enq)
+tcp_conn_t *tcp_conn;
+int enq;					/* Enqueue writes. */
+{
+	tcp_fd_t *tcp_fd;
+	size_t data_size, read_size;
+	acc_t *data;
+	int fin_recv, urg, push, result;
+	i32_t old_window, new_window;
+	u16_t mss;
+
+	assert(tcp_conn->tc_busy);
+
+	tcp_fd= tcp_conn->tc_fd;
+
+	assert (tcp_fd->tf_flags & TFF_READ_IP);
+	if (tcp_conn->tc_state == TCS_CLOSED)
+	{
+		if (tcp_fd->tf_read_offset)
+			tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);
+		else
+			tcp_reply_read (tcp_fd, tcp_conn->tc_error);
+		return;
+	}
+
+	urg= tcp_Gmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);
+	push= (tcp_conn->tc_flags & TCF_RCV_PUSH);
+	fin_recv= (tcp_conn->tc_flags & TCF_FIN_RECV);
+
+	data_size= tcp_conn->tc_RCV_NXT-tcp_conn->tc_RCV_LO;
+	if (fin_recv)
+		data_size--;
+	if (urg)
+	{
+#if DEBUG
+		printf("tcp_fd_read: RCV_UP = 0x%x, RCV_LO = 0x%x\n",
+			tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);
+#endif
+		read_size= tcp_conn->tc_RCV_UP-tcp_conn->tc_RCV_LO;
+	}
+	else
+		read_size= data_size;
+
+	if (read_size >= tcp_fd->tf_read_count)
+		read_size= tcp_fd->tf_read_count;
+	else if (!push && !fin_recv && !urg &&
+		data_size < TCP_MIN_RCV_WND_SIZE)
+	{
+		/* Defer the copy out until later. */
+		return;
+	}
+	else if (data_size == 0 && !fin_recv)
+	{
+		/* No data, and no end of file. */
+		return;
+	}
+
+	if (read_size)
+	{
+		if (urg && !(tcp_fd->tf_flags & TFF_RECV_URG))
+		{
+			if (tcp_fd->tf_read_offset)
+			{
+				tcp_reply_read (tcp_fd,
+					tcp_fd->tf_read_offset);
+			}
+			else
+			{
+				tcp_reply_read (tcp_fd, EURG);
+			}
+			return;
+		}
+		else if (!urg && (tcp_fd->tf_flags & TFF_RECV_URG))
+		{
+			if (tcp_fd->tf_read_offset)
+			{
+				tcp_reply_read (tcp_fd,
+					tcp_fd->tf_read_offset);
+			}
+			else
+			{
+				tcp_reply_read(tcp_fd, ENOURG);
+			}
+			return;
+		}
+
+		if (read_size == data_size)
+		{
+			data= tcp_conn->tc_rcvd_data;
+			data->acc_linkC++;
+		}
+		else
+		{
+			data= bf_cut(tcp_conn->tc_rcvd_data, 0, read_size);
+		}
+		result= (*tcp_fd->tf_put_userdata) (tcp_fd->tf_srfd,
+			tcp_fd->tf_read_offset, data, FALSE);
+		if (result<0)
+		{
+			if (tcp_fd->tf_read_offset)
+				tcp_reply_read(tcp_fd, tcp_fd->
+					tf_read_offset);
+			else
+				tcp_reply_read(tcp_fd, result);
+			return;
+		}
+		tcp_fd->tf_read_offset += read_size;
+		tcp_fd->tf_read_count -= read_size;
+
+		if (data_size == read_size)
+		{
+			bf_afree(tcp_conn->tc_rcvd_data);
+			tcp_conn->tc_rcvd_data= 0;
+		}
+		else
+		{
+			tcp_conn->tc_rcvd_data=
+				bf_delhead(tcp_conn->tc_rcvd_data,
+				read_size);
+		}
+		tcp_conn->tc_RCV_LO += read_size;
+		data_size -= read_size;
+	}
+
+	/* Update IRS and often RCV_UP every 0.5GB */
+	if (tcp_conn->tc_RCV_LO - tcp_conn->tc_IRS > 0x40000000)
+	{
+		tcp_conn->tc_IRS += 0x20000000;
+		DBLOCK(1, printf("tcp_fd_read: updating IRS to 0x%lx\n",
+			(unsigned long)tcp_conn->tc_IRS););
+		if (tcp_Lmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_IRS))
+		{
+			tcp_conn->tc_RCV_UP= tcp_conn->tc_IRS;
+			DBLOCK(1, printf(
+				"tcp_fd_read: updating RCV_UP to 0x%lx\n",
+				(unsigned long)tcp_conn->tc_RCV_UP););
+		}
+		DBLOCK(1, printf("tcp_fd_read: RCP_LO = 0x%lx\n",
+			(unsigned long)tcp_conn->tc_RCV_LO););
+	}
+
+	mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
+	if (tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_LO <=
+		tcp_conn->tc_rcv_wnd-mss)
+	{
+		old_window= tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_NXT;
+		tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO + 
+			tcp_conn->tc_rcv_wnd;
+		new_window= tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_NXT;
+		assert(old_window >=0 && new_window >= old_window);
+		if (old_window < mss && new_window >= mss)
+		{
+			tcp_conn->tc_flags |= TCF_SEND_ACK;
+			DBLOCK(2, printf("opening window\n"));
+			tcp_conn_write(tcp_conn, 1);
+		}
+	}
+	if (tcp_conn->tc_rcvd_data == NULL &&
+		tcp_conn->tc_adv_data == NULL)
+	{
+		/* Out of data, clear PUSH flag and reply to a read. */
+		tcp_conn->tc_flags &= ~TCF_RCV_PUSH;
+	}
+	if (fin_recv || urg || tcp_fd->tf_read_offset ||
+		!tcp_fd->tf_read_count)
+	{
+		tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);
+		return;
+	}
+}
+
+PUBLIC unsigned
+tcp_sel_read(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	tcp_fd_t *tcp_fd;
+	size_t data_size;
+	int fin_recv, urg, push;
+
+	tcp_fd= tcp_conn->tc_fd;
+
+	if (tcp_conn->tc_state == TCS_CLOSED)
+		return 1;
+
+	fin_recv= (tcp_conn->tc_flags & TCF_FIN_RECV);
+	if (fin_recv)
+		return 1;
+
+	data_size= tcp_conn->tc_RCV_NXT-tcp_conn->tc_RCV_LO;
+	if (data_size == 0)
+	{
+		/* No data, and no end of file. */
+		return 0;
+	}
+
+	urg= tcp_Gmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);
+	push= (tcp_conn->tc_flags & TCF_RCV_PUSH);
+
+	if (!push && !urg && data_size < TCP_MIN_RCV_WND_SIZE)
+	{
+		/* Defer until later. */
+		return 0;
+	}
+
+	return 1;
+}
+
+PUBLIC void
+tcp_rsel_read(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	tcp_fd_t *tcp_fd;
+
+	if (tcp_sel_read(tcp_conn) == 0)
+		return;
+
+	tcp_fd= tcp_conn->tc_fd;
+	tcp_fd->tf_flags &= ~TFF_SEL_READ;
+	if (tcp_fd->tf_select_res)
+		tcp_fd->tf_select_res(tcp_fd->tf_srfd, SR_SELECT_READ);
+	else
+		printf("tcp_rsel_read: no select_res\n");
+}
+
+PUBLIC void tcp_bytesavailable(tcp_fd, bytesp)
+tcp_fd_t *tcp_fd;
+int *bytesp;
+{
+	tcp_conn_t *tcp_conn;
+	size_t data_size, read_size;
+	acc_t *data;
+	int fin_recv, urg, push, result;
+	i32_t old_window, new_window;
+	u16_t mss;
+
+	*bytesp= 0;	/* The default is that nothing is available */
+
+	if (!(tcp_fd->tf_flags & TFF_CONNECTED))
+		return;
+	tcp_conn= tcp_fd->tf_conn;
+
+	if (tcp_conn->tc_state == TCS_CLOSED)
+		return;
+
+	urg= tcp_Gmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);
+	push= (tcp_conn->tc_flags & TCF_RCV_PUSH);
+	fin_recv= (tcp_conn->tc_flags & TCF_FIN_RECV);
+
+	data_size= tcp_conn->tc_RCV_NXT-tcp_conn->tc_RCV_LO;
+	if (fin_recv)
+		data_size--;
+	if (urg)
+		data_size= tcp_conn->tc_RCV_UP-tcp_conn->tc_RCV_LO;
+
+	if (urg && !(tcp_fd->tf_flags & TFF_RECV_URG))
+		return;
+	else if (!urg && (tcp_fd->tf_flags & TFF_RECV_URG))
+		return;
+
+	*bytesp= data_size;
+}
+
+/*
+ * $PchId: tcp_recv.c,v 1.30 2005/06/28 14:21:35 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/tcp_send.c
===================================================================
--- /trunk/minix/servers/inet/generic/tcp_send.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/tcp_send.c	(revision 9)
@@ -0,0 +1,1443 @@
+/*
+tcp_send.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "buf.h"
+#include "clock.h"
+#include "event.h"
+#include "type.h"
+#include "sr.h"
+
+#include "assert.h"
+#include "io.h"
+#include "ip.h"
+#include "tcp.h"
+#include "tcp_int.h"
+
+THIS_FILE
+
+FORWARD acc_t *make_pack ARGS(( tcp_conn_t *tcp_conn ));
+FORWARD void tcp_send_timeout ARGS(( int conn, struct timer *timer ));
+FORWARD void do_snd_event ARGS(( event_t *ev, ev_arg_t arg ));
+
+PUBLIC void tcp_conn_write (tcp_conn, enq)
+tcp_conn_t *tcp_conn;
+int enq;				/* Writes need to be enqueued. */
+{
+	tcp_port_t *tcp_port;
+	ev_arg_t snd_arg;
+
+	assert (tcp_conn->tc_flags & TCF_INUSE);
+
+	tcp_port= tcp_conn->tc_port;
+	if (tcp_conn->tc_flags & TCF_MORE2WRITE)
+		return;
+
+	/* Do we really have something to send here? */
+	if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT &&
+		!(tcp_conn->tc_flags & TCF_SEND_ACK) &&
+		!tcp_conn->tc_frag2send)
+	{
+		return;
+	}
+
+	tcp_conn->tc_flags |= TCF_MORE2WRITE;
+	tcp_conn->tc_send_link= NULL;
+	if (!tcp_port->tp_snd_head)
+	{
+		tcp_port->tp_snd_head= tcp_conn;
+		tcp_port->tp_snd_tail= tcp_conn;
+		if (enq)
+		{
+			snd_arg.ev_ptr= tcp_port;
+			if (!ev_in_queue(&tcp_port->tp_snd_event))
+			{
+				ev_enqueue(&tcp_port->tp_snd_event,
+					do_snd_event, snd_arg);
+			}
+		}
+		else
+			tcp_port_write(tcp_port);
+	}
+	else
+	{
+		tcp_port->tp_snd_tail->tc_send_link= tcp_conn;
+		tcp_port->tp_snd_tail= tcp_conn;
+	}
+}
+
+PRIVATE void do_snd_event(ev, arg)
+event_t *ev;
+ev_arg_t arg;
+{
+	tcp_port_t *tcp_port;
+
+	tcp_port= arg.ev_ptr;
+
+	assert(ev == &tcp_port->tp_snd_event);
+	tcp_port_write(tcp_port);
+}
+
+PUBLIC void tcp_port_write(tcp_port)
+tcp_port_t *tcp_port;
+{
+	tcp_conn_t *tcp_conn;
+	acc_t *pack2write;
+	int r;
+
+	assert (!(tcp_port->tp_flags & TPF_WRITE_IP));
+
+	while(tcp_port->tp_snd_head)
+	{
+		tcp_conn= tcp_port->tp_snd_head;
+		assert(tcp_conn->tc_flags & TCF_MORE2WRITE);
+
+		for(;;)
+		{
+			if (tcp_conn->tc_frag2send)
+			{
+				pack2write= tcp_conn->tc_frag2send;
+				tcp_conn->tc_frag2send= 0;
+			}
+			else
+			{
+				tcp_conn->tc_busy++;
+				pack2write= make_pack(tcp_conn);
+				tcp_conn->tc_busy--;
+				if (!pack2write)
+					break;
+			}
+			r= ip_send(tcp_port->tp_ipfd, pack2write,
+				bf_bufsize(pack2write));
+			if (r != NW_OK)
+			{
+				if (r == NW_WOULDBLOCK)
+					break;
+				if (r == EPACKSIZE)
+				{
+					tcp_mtu_exceeded(tcp_conn);
+					continue;
+				}
+				if (r == EDSTNOTRCH)
+				{
+					tcp_notreach(tcp_conn);
+					continue;
+				}
+				if (r == EBADDEST)
+					continue;
+			}
+			assert(r == NW_OK ||
+				(printf("ip_send failed, error %d\n", r),0));
+		}
+
+		if (pack2write)
+		{
+			tcp_port->tp_flags |= TPF_WRITE_IP;
+			tcp_port->tp_pack= pack2write;
+
+			r= ip_write (tcp_port->tp_ipfd,
+				bf_bufsize(pack2write));
+			if (r == NW_SUSPEND)
+			{
+				tcp_port->tp_flags |= TPF_WRITE_SP;
+				return;
+			}
+			assert(r == NW_OK);
+			tcp_port->tp_flags &= ~TPF_WRITE_IP;
+			assert(!(tcp_port->tp_flags &
+				(TPF_WRITE_IP|TPF_WRITE_SP)));
+			continue;
+		}
+		tcp_conn->tc_flags &= ~TCF_MORE2WRITE;
+		tcp_port->tp_snd_head= tcp_conn->tc_send_link;
+
+	}
+}
+
+PRIVATE acc_t *make_pack(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	acc_t *pack2write, *tmp_pack, *tcp_pack;
+	tcp_hdr_t *tcp_hdr;
+	ip_hdr_t *ip_hdr;
+	int tot_hdr_size, ip_hdr_len, no_push, head, more2write;
+	u32_t seg_seq, seg_lo_data, queue_lo_data, seg_hi, seg_hi_data;
+	u16_t seg_up, mss;
+	u8_t seg_flags;
+	size_t pack_size;
+	clock_t curr_time, new_dis;
+	u8_t *optptr;
+
+	mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
+
+	assert(tcp_conn->tc_busy);
+	curr_time= get_time();
+	switch (tcp_conn->tc_state)
+	{
+	case TCS_CLOSED:
+	case TCS_LISTEN:
+		return NULL;
+	case TCS_SYN_RECEIVED:
+	case TCS_SYN_SENT:
+
+		if (tcp_conn->tc_SND_TRM == tcp_conn->tc_SND_NXT &&
+			!(tcp_conn->tc_flags & TCF_SEND_ACK))
+		{
+			return 0;
+		}
+
+		tcp_conn->tc_flags &= ~TCF_SEND_ACK;
+
+		/* Advertise a mss based on the port mtu. The current mtu may
+		 * be lower if the other side sends a smaller mss.
+		 */
+		mss= tcp_conn->tc_port->tp_mtu-IP_TCP_MIN_HDR_SIZE;
+
+		/* Include a max segment size option. */
+		assert(tcp_conn->tc_tcpopt == NULL);
+		tcp_conn->tc_tcpopt= bf_memreq(4);
+		optptr= (u8_t *)ptr2acc_data(tcp_conn->tc_tcpopt);
+		optptr[0]= TCP_OPT_MSS;
+		optptr[1]= 4;
+		optptr[2]= mss >> 8;
+		optptr[3]= mss & 0xFF;
+
+		pack2write= tcp_make_header(tcp_conn, &ip_hdr, &tcp_hdr, 
+			(acc_t *)0);
+
+		bf_afree(tcp_conn->tc_tcpopt);
+		tcp_conn->tc_tcpopt= NULL;
+
+		if (!pack2write)
+		{
+			DBLOCK(1, printf("connection closed while inuse\n"));
+			return 0;
+		}
+		tot_hdr_size= bf_bufsize(pack2write);
+		seg_seq= tcp_conn->tc_SND_TRM;
+		if (tcp_conn->tc_state == TCS_SYN_SENT)
+			seg_flags= 0;
+		else
+			seg_flags= THF_ACK;	/* except for TCS_SYN_SENT
+						 * ack is always present */
+
+		if (seg_seq == tcp_conn->tc_ISS)
+		{
+			assert(tcp_conn->tc_transmit_timer.tim_active ||
+				(tcp_print_conn(tcp_conn), printf("\n"), 0));
+			seg_flags |= THF_SYN;
+			tcp_conn->tc_SND_TRM++;
+		}
+
+		tcp_hdr->th_seq_nr= htonl(seg_seq);
+		tcp_hdr->th_ack_nr= htonl(tcp_conn->tc_RCV_NXT);
+		tcp_hdr->th_flags= seg_flags;
+		tcp_hdr->th_window= htons(mss);
+			/* Initially we allow one segment */
+
+		ip_hdr->ih_length= htons(tot_hdr_size);
+
+		pack2write->acc_linkC++;
+		ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
+		tcp_pack= bf_delhead(pack2write, ip_hdr_len);
+		tcp_hdr->th_chksum= ~tcp_pack_oneCsum(ip_hdr, tcp_pack);
+		bf_afree(tcp_pack);
+
+		new_dis= curr_time + 2*HZ*tcp_conn->tc_ttl;
+		if (new_dis > tcp_conn->tc_senddis)
+			tcp_conn->tc_senddis= new_dis;
+		return pack2write;
+
+	case TCS_ESTABLISHED:
+	case TCS_CLOSING:
+		seg_seq= tcp_conn->tc_SND_TRM;
+
+		seg_flags= 0;
+		pack2write= 0;
+		seg_up= 0;
+		if (tcp_conn->tc_flags & TCF_SEND_ACK)
+		{
+			seg_flags= THF_ACK;
+			tcp_conn->tc_flags &= ~TCF_SEND_ACK;
+
+			pack2write= tcp_make_header (tcp_conn, &ip_hdr, 
+				&tcp_hdr, (acc_t *)0);
+			if (!pack2write)
+			{
+				return NULL;
+			}
+		}
+
+		if (tcp_conn->tc_SND_UNA != tcp_conn->tc_SND_NXT)
+		{
+			assert(tcp_LEmod4G(seg_seq, tcp_conn->tc_SND_NXT));
+
+			if (seg_seq == tcp_conn->tc_snd_cwnd)
+			{
+				DBLOCK(2,
+					printf("no data: window is closed\n"));
+				goto after_data;
+			}
+
+			/* Assert that our SYN has been ACKed. */
+			assert(tcp_conn->tc_SND_UNA != tcp_conn->tc_ISS);
+
+			seg_lo_data= seg_seq;
+			queue_lo_data= tcp_conn->tc_SND_UNA;
+
+			seg_hi= tcp_conn->tc_SND_NXT;
+			seg_hi_data= seg_hi;
+			if (tcp_conn->tc_flags & TCF_FIN_SENT)
+			{
+				if (seg_seq != seg_hi)
+					seg_flags |= THF_FIN;
+				if (queue_lo_data == seg_hi_data)
+					queue_lo_data--;
+				if (seg_lo_data == seg_hi_data)
+					seg_lo_data--;
+				seg_hi_data--;
+			}
+
+			if (!pack2write)
+			{
+				pack2write= tcp_make_header (tcp_conn,
+					&ip_hdr, &tcp_hdr, (acc_t *)0);
+				if (!pack2write)
+				{
+					return NULL;
+				}
+			}
+
+			tot_hdr_size= bf_bufsize(pack2write);
+
+			no_push= (tcp_LEmod4G(tcp_conn->tc_SND_PSH, seg_seq));
+			head= (seg_seq == tcp_conn->tc_SND_UNA);
+			if (no_push)
+			{
+				/* Shutdown sets SND_PSH */
+				seg_flags &= ~THF_FIN;
+				if (seg_hi_data-seg_lo_data <= 1)
+				{
+					/* Allways keep at least one byte
+					 * for a future push.
+					 */
+					DBLOCK(0x20,
+					    printf("no data: no push\n"));
+					if (head)
+					{
+						DBLOCK(0x1, printf(
+					"no data: setting TCF_NO_PUSH\n"));
+						tcp_conn->tc_flags |=
+							TCF_NO_PUSH;
+					}
+					goto after_data;
+				}
+				seg_hi_data--;
+			}
+
+			if (tot_hdr_size != IP_TCP_MIN_HDR_SIZE)
+			{
+				printf(
+				"tcp_write`make_pack: tot_hdr_size = %d\n",
+					tot_hdr_size);
+				mss= tcp_conn->tc_mtu-tot_hdr_size;
+			}
+			if (seg_hi_data - seg_lo_data > mss)
+			{
+				/* Truncate to at most one segment */
+				seg_hi_data= seg_lo_data + mss;
+				seg_hi= seg_hi_data;
+				seg_flags &= ~THF_FIN;
+			}
+
+			if (no_push &&
+				seg_hi_data-seg_lo_data != mss)
+			{
+				DBLOCK(0x20, printf(
+				"no data: no push for partial segment\n"));
+				more2write= (tcp_conn->tc_fd &&
+					(tcp_conn->tc_fd->tf_flags &
+					TFF_WRITE_IP));
+				DIFBLOCK(2, more2write, 
+					printf(
+			"tcp_send`make_pack: more2write -> !TCF_NO_PUSH\n");
+				);
+				if (head && !more2write)
+				{
+					DBLOCK(0x1, printf(
+				"partial segment: setting TCF_NO_PUSH\n"));
+					tcp_conn->tc_flags |= TCF_NO_PUSH;
+				}
+				goto after_data;
+			}
+
+
+			if (tcp_Gmod4G(seg_hi, tcp_conn->tc_snd_cwnd))
+			{
+				seg_hi_data= tcp_conn->tc_snd_cwnd;
+				seg_hi= seg_hi_data;
+				seg_flags &= ~THF_FIN;
+			}
+
+			if (!head &&
+				seg_hi_data-seg_lo_data < mss)
+			{
+				if (tcp_conn->tc_flags & TCF_PUSH_NOW)
+				{
+					DBLOCK(0x20,
+					printf("push: no Nagle\n"));
+				}
+				else
+				{
+				DBLOCK(0x20,
+					printf("no data: partial packet\n"));
+				seg_flags &= ~THF_FIN;
+				goto after_data;
+				}
+			}
+
+			if (seg_hi-seg_seq == 0)
+			{
+				DBLOCK(0x20,
+				printf("no data: no data available\n"));
+				goto after_data;
+			}
+
+			if (tcp_GEmod4G(tcp_conn->tc_SND_UP, seg_lo_data))
+			{
+				extern int killer_inet;
+
+				if (tcp_GEmod4G(tcp_conn->tc_SND_UP,
+					seg_hi_data))
+				{
+					seg_up= seg_hi_data-seg_seq;
+				}
+				else
+				{
+					seg_up= tcp_conn->tc_SND_UP-seg_seq;
+				}
+				seg_flags |= THF_URG;
+				if (!killer_inet &&
+					(tcp_conn->tc_flags & TCF_BSD_URG) &&
+					seg_up == 0)
+				{
+					/* A zero urgent pointer doesn't mean
+					 * anything when BSD semantics are
+					 * used (urgent pointer points to the
+					 * first no urgent byte). The use of
+					 * a zero urgent pointer also crashes
+					 * a Solaris 2.3 kernel. If urgent
+					 * pointer doesn't have BSD semantics
+					 * then an urgent pointer of zero
+					 * simply indicates that there is one
+					 * urgent byte.
+					 */
+					seg_flags &= ~THF_URG;
+				}
+			}
+			else
+				seg_up= 0;
+
+			if (tcp_Gmod4G(tcp_conn->tc_SND_PSH, seg_lo_data) &&
+				tcp_LEmod4G(tcp_conn->tc_SND_PSH, seg_hi_data))
+			{
+				seg_flags |= THF_PSH;
+			}
+
+			tcp_conn->tc_SND_TRM= seg_hi;
+
+			assert(tcp_conn->tc_transmit_timer.tim_active ||
+				(tcp_print_conn(tcp_conn), printf("\n"), 0));
+			if (tcp_conn->tc_rt_seq == 0 && 
+				tcp_Gmod4G(seg_seq, tcp_conn->tc_rt_threshold))
+			{
+				tcp_conn->tc_rt_time= curr_time;
+				tcp_conn->tc_rt_seq=
+					tcp_conn->tc_rt_threshold= seg_seq;
+			}
+
+			if (seg_hi_data-seg_lo_data)
+			{
+#if DEBUG & 0
+				assert(tcp_check_conn(tcp_conn));
+				assert((seg_hi_data-queue_lo_data <=
+					bf_bufsize(tcp_conn->tc_send_data) &&
+					seg_lo_data-queue_lo_data <=
+					bf_bufsize(tcp_conn->tc_send_data) &&
+					seg_hi_data>seg_lo_data)||
+					(tcp_print_conn(tcp_conn),
+					printf(
+		" seg_hi_data= 0x%x, seg_lo_data= 0x%x, queue_lo_data= 0x%x\n",
+					seg_hi_data, seg_lo_data,
+					queue_lo_data), 0));
+#endif
+
+				tmp_pack= pack2write;
+				while (tmp_pack->acc_next)
+					tmp_pack= tmp_pack->acc_next;
+				tmp_pack->acc_next=
+					bf_cut(tcp_conn->tc_send_data, 
+					(unsigned)(seg_lo_data-queue_lo_data), 
+					(unsigned) (seg_hi_data-seg_lo_data));
+			}
+			seg_flags |= THF_ACK;
+		}
+
+after_data:
+		if (!(seg_flags & THF_ACK))
+		{
+			if (pack2write)
+				bf_afree(pack2write);
+			return NULL;
+		}
+
+		tcp_hdr->th_seq_nr= htonl(seg_seq);
+		tcp_hdr->th_ack_nr= htonl(tcp_conn->tc_RCV_NXT);
+		tcp_hdr->th_flags= seg_flags;
+		tcp_hdr->th_window= htons(tcp_conn->tc_RCV_HI -
+			tcp_conn->tc_RCV_NXT);
+		tcp_hdr->th_urgptr= htons(seg_up);
+
+		pack_size= bf_bufsize(pack2write);
+		ip_hdr->ih_length= htons(pack_size);
+
+		pack2write->acc_linkC++;
+		ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
+		tcp_pack= bf_delhead(pack2write, ip_hdr_len);
+		tcp_hdr->th_chksum= ~tcp_pack_oneCsum(ip_hdr, tcp_pack);
+		bf_afree(tcp_pack);
+
+		new_dis= curr_time + 2*HZ*tcp_conn->tc_ttl;
+		if (new_dis > tcp_conn->tc_senddis)
+			tcp_conn->tc_senddis= new_dis;
+
+		return pack2write;
+	default:
+		DBLOCK(1, tcp_print_conn(tcp_conn); printf("\n"));
+		ip_panic(( "Illegal state" ));
+	}
+	assert(0);
+	return NULL;
+}
+
+/*
+tcp_release_retrans
+*/
+
+PUBLIC void tcp_release_retrans(tcp_conn, seg_ack, new_win)
+tcp_conn_t *tcp_conn;
+u32_t seg_ack;
+u16_t new_win;
+{
+	tcp_fd_t *tcp_fd;
+	size_t size, offset;
+	acc_t *pack;
+	clock_t retrans_time, curr_time, rtt, artt, drtt, srtt;
+	u32_t queue_lo, queue_hi;
+	u16_t mss, cthresh;
+	unsigned window;
+
+	DBLOCK(0x10, printf("tcp_release_retrans, conn[%d]: ack %lu, win %u\n",
+		tcp_conn-tcp_conn_table, (unsigned long)seg_ack, new_win););
+
+	assert(tcp_conn->tc_busy);
+	assert (tcp_GEmod4G(seg_ack, tcp_conn->tc_SND_UNA));
+	assert (tcp_LEmod4G(seg_ack, tcp_conn->tc_SND_NXT));
+
+	tcp_conn->tc_snd_dack= 0;
+	mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
+
+	curr_time= get_time();
+	if (tcp_conn->tc_rt_seq != 0 && 
+		tcp_Gmod4G(seg_ack, tcp_conn->tc_rt_seq))
+	{
+		assert(curr_time >= tcp_conn->tc_rt_time);
+		retrans_time= curr_time-tcp_conn->tc_rt_time;
+		rtt= tcp_conn->tc_rtt;
+
+		tcp_conn->tc_rt_seq= 0;
+
+		if (rtt == TCP_RTT_GRAN*CLOCK_GRAN &&
+			retrans_time <= TCP_RTT_GRAN*CLOCK_GRAN)
+		{
+			/* Common in fast networks. Nothing to do. */
+		}
+		else
+		{
+			srtt= retrans_time * TCP_RTT_SCALE;
+
+			artt= tcp_conn->tc_artt;
+			artt= ((TCP_RTT_SMOOTH-1)*artt+srtt)/TCP_RTT_SMOOTH;
+
+			srtt -= artt;
+			if (srtt < 0)
+				srtt= -srtt;
+			drtt= tcp_conn->tc_drtt;
+			drtt= ((TCP_RTT_SMOOTH-1)*drtt+srtt)/TCP_RTT_SMOOTH;
+
+			rtt= (artt+TCP_DRTT_MULT*drtt-1)/TCP_RTT_SCALE+1;
+			if (rtt < TCP_RTT_GRAN*CLOCK_GRAN)
+			{
+				rtt= TCP_RTT_GRAN*CLOCK_GRAN;
+			}
+			else if (rtt > TCP_RTT_MAX)
+			{
+#if DEBUG
+				static int warned /* = 0 */;
+
+				if (!warned)
+				{
+					printf(
+"tcp_release_retrans: warning retransmission time is limited to %d ms\n",
+						TCP_RTT_MAX*1000/HZ);
+					warned= 1;
+				}
+#endif
+				rtt= TCP_RTT_MAX;
+			}
+			DBLOCK(0x10, printf(
+	"tcp_release_retrans, conn[%d]: retrans_time= %ld ms, rtt = %ld ms\n",
+				tcp_conn-tcp_conn_table,
+				retrans_time*1000/HZ,
+				rtt*1000/HZ));
+
+			DBLOCK(0x10, printf(
+	"tcp_release_retrans: artt= %ld -> %ld, drtt= %ld -> %ld\n",
+				tcp_conn->tc_artt, artt,
+				tcp_conn->tc_drtt, drtt));
+
+			tcp_conn->tc_artt= artt;
+			tcp_conn->tc_drtt= drtt;
+			tcp_conn->tc_rtt= rtt;
+		}
+
+		if (tcp_conn->tc_mtu != tcp_conn->tc_max_mtu &&
+			curr_time > tcp_conn->tc_mtutim+TCP_PMTU_INCR_IV)
+		{
+			tcp_mtu_incr(tcp_conn);
+		}
+	}
+
+	/* Update the current window. */
+	window= tcp_conn->tc_snd_cwnd-tcp_conn->tc_SND_UNA;
+	assert(seg_ack != tcp_conn->tc_SND_UNA);
+
+	/* For every real ACK we try to increase the current window
+	 * with 1 mss.
+	 */
+	window += mss;
+
+	/* If the window becomes larger than the current threshold,
+	 * increment the threshold by a small amount and set the
+	 * window to the threshold.
+	 */
+	cthresh= tcp_conn->tc_snd_cthresh;
+	if (window > cthresh)
+	{
+		cthresh += tcp_conn->tc_snd_cinc;
+		tcp_conn->tc_snd_cthresh= cthresh;
+		window= cthresh;
+	}
+
+	/* If the window is larger than the window advertised by the
+	 * receiver, set the window size to the advertisement.
+	 */
+	if (window > new_win)
+		window= new_win;
+
+	tcp_conn->tc_snd_cwnd= seg_ack+window;
+
+	/* Release data queued for retransmissions. */
+	queue_lo= tcp_conn->tc_SND_UNA;
+	queue_hi= tcp_conn->tc_SND_NXT;
+
+	tcp_conn->tc_SND_UNA= seg_ack;
+	if (tcp_Lmod4G(tcp_conn->tc_SND_TRM, seg_ack))
+	{
+		tcp_conn->tc_SND_TRM= seg_ack;
+	}
+	assert(tcp_GEmod4G(tcp_conn->tc_snd_cwnd, seg_ack));
+
+	/* Advance ISS every 0.5GB to avoid problem with wrap around */
+	if (tcp_conn->tc_SND_UNA - tcp_conn->tc_ISS > 0x40000000)
+	{
+		tcp_conn->tc_ISS += 0x20000000;
+		DBLOCK(1, printf(
+			"tcp_release_retrans: updating ISS to 0x%lx\n",
+			(unsigned long)tcp_conn->tc_ISS););
+		if (tcp_Lmod4G(tcp_conn->tc_SND_UP, tcp_conn->tc_ISS))
+		{
+			tcp_conn->tc_SND_UP= tcp_conn->tc_ISS;
+			DBLOCK(1, printf(
+			"tcp_release_retrans: updating SND_UP to 0x%lx\n",
+				(unsigned long)tcp_conn->tc_SND_UP););
+		}
+	}
+
+	if (queue_lo == tcp_conn->tc_ISS)
+		queue_lo++;
+
+	if (tcp_conn->tc_flags & TCF_FIN_SENT)
+	{
+		if (seg_ack == queue_hi)
+			seg_ack--;
+		if (queue_lo == queue_hi)
+			queue_lo--;
+		queue_hi--;
+	}
+
+	offset= seg_ack - queue_lo;
+	size= queue_hi - seg_ack;
+	pack= tcp_conn->tc_send_data;
+	tcp_conn->tc_send_data= 0;
+
+	if (!size)
+	{
+		bf_afree(pack);
+	}
+	else
+	{
+		pack= bf_delhead(pack, offset);
+		tcp_conn->tc_send_data= pack;
+	}
+
+	if (tcp_Gmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_snd_cwnd))
+		tcp_conn->tc_SND_TRM= tcp_conn->tc_snd_cwnd;
+
+	/* Copy in new data if an ioctl is pending or if a write request is
+	 * pending and either the write can be completed or at least one
+	 * mss buffer space is available.
+	 */
+	tcp_fd= tcp_conn->tc_fd;
+	if (tcp_fd)
+	{
+		if (tcp_fd->tf_flags & TFF_IOCTL_IP) 
+		{
+			tcp_fd_write(tcp_conn);
+		}
+		if ((tcp_fd->tf_flags & TFF_WRITE_IP) &&
+			(size+tcp_fd->tf_write_count <= TCP_MAX_SND_WND_SIZE ||
+			size <= TCP_MAX_SND_WND_SIZE-mss))
+		{
+			tcp_fd_write(tcp_conn);
+		}
+		if (tcp_fd->tf_flags & TFF_SEL_WRITE) 
+			tcp_rsel_write(tcp_conn);
+	}
+	else
+	{
+		if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
+		{
+			assert(tcp_conn->tc_state == TCS_CLOSING);
+			DBLOCK(0x10,
+			printf("all data sent in abondoned connection\n"));
+			tcp_close_connection(tcp_conn, ENOTCONN);
+			return;
+		}
+	}
+
+	if (!size && !tcp_conn->tc_send_data)
+	{
+		/* Reset window if a write is completed */
+		tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + mss;
+	}
+
+	DIFBLOCK(2, (tcp_conn->tc_snd_cwnd == tcp_conn->tc_SND_TRM),
+		printf("not sending: zero window\n"));
+
+	if (tcp_conn->tc_snd_cwnd != tcp_conn->tc_SND_TRM &&
+		tcp_conn->tc_SND_NXT != tcp_conn->tc_SND_TRM)
+	{
+		tcp_conn_write(tcp_conn, 1);
+	}
+
+}
+
+/*
+tcp_fast_retrans
+*/
+
+PUBLIC void tcp_fast_retrans(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	u16_t mss, mss2;
+
+	/* Update threshold sequence number for retransmission calculation. */
+	if (tcp_Gmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_rt_threshold))
+		tcp_conn->tc_rt_threshold= tcp_conn->tc_SND_TRM;
+
+	tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
+
+	mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
+	mss2= 2*mss;
+
+	if (tcp_conn->tc_snd_cwnd == tcp_conn->tc_SND_UNA)
+		tcp_conn->tc_snd_cwnd++;
+	if (tcp_Gmod4G(tcp_conn->tc_snd_cwnd, tcp_conn->tc_SND_UNA + mss2))
+	{
+		tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + mss2;
+		if (tcp_Gmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_snd_cwnd))
+			tcp_conn->tc_SND_TRM= tcp_conn->tc_snd_cwnd;
+
+		tcp_conn->tc_snd_cthresh /= 2;
+		if (tcp_conn->tc_snd_cthresh < mss2)
+			tcp_conn->tc_snd_cthresh= mss2;
+	}
+
+	tcp_conn_write(tcp_conn, 1);
+}
+
+#if 0
+PUBLIC void do_tcp_timeout(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	tcp_send_timeout(tcp_conn-tcp_conn_table,
+		&tcp_conn->tc_transmit_timer);
+}
+#endif
+
+/*
+tcp_send_timeout
+*/
+
+PRIVATE void tcp_send_timeout(conn, timer)
+int conn;
+struct timer *timer;
+{
+	tcp_conn_t *tcp_conn;
+	u16_t mss, mss2;
+	u32_t snd_una, snd_nxt;
+	clock_t curr_time, rtt, stt, timeout;
+	acc_t *pkt;
+	int new_ttl, no_push;
+
+	DBLOCK(0x20, printf("tcp_send_timeout: conn[%d]\n", conn));
+
+	curr_time= get_time();
+
+	tcp_conn= &tcp_conn_table[conn];
+	assert(tcp_conn->tc_flags & TCF_INUSE);
+	assert(tcp_conn->tc_state != TCS_CLOSED);
+	assert(tcp_conn->tc_state != TCS_LISTEN);
+
+	snd_una= tcp_conn->tc_SND_UNA;
+	snd_nxt= tcp_conn->tc_SND_NXT;
+	no_push= (tcp_conn->tc_flags & TCF_NO_PUSH);
+	if (snd_nxt == snd_una || no_push)
+	{
+		/* Nothing more to send */
+		assert(tcp_conn->tc_SND_TRM == snd_una || no_push);
+
+		/* A new write sets the timer if tc_transmit_seq == SND_UNA */
+		tcp_conn->tc_transmit_seq= tcp_conn->tc_SND_UNA;
+		tcp_conn->tc_stt= 0;
+		tcp_conn->tc_0wnd_to= 0;
+		assert(!tcp_conn->tc_fd ||
+			!(tcp_conn->tc_fd->tf_flags & TFF_WRITE_IP) ||
+			(tcp_print_conn(tcp_conn), printf("\n"), 0));
+
+		if (snd_nxt != snd_una)
+		{
+			assert(no_push);
+			DBLOCK(1, printf("not setting keepalive timer\n"););
+
+			/* No point in setting the keepalive timer if we
+			 * still have to send more data.
+			 */
+			return;
+		}
+
+		assert(tcp_conn->tc_send_data == NULL);
+		DBLOCK(0x20, printf("keep alive timer\n"));
+		if (tcp_conn->tc_ka_snd != tcp_conn->tc_SND_NXT ||
+			tcp_conn->tc_ka_rcv != tcp_conn->tc_RCV_NXT)
+		{
+			tcp_conn->tc_ka_snd= tcp_conn->tc_SND_NXT;
+			tcp_conn->tc_ka_rcv= tcp_conn->tc_RCV_NXT;
+			DBLOCK(0x20, printf(
+"tcp_send_timeout: conn[%d] setting keepalive timer (+%ld ms)\n",
+				tcp_conn-tcp_conn_table,
+				tcp_conn->tc_ka_time*1000/HZ));
+			clck_timer(&tcp_conn->tc_transmit_timer,
+				curr_time+tcp_conn->tc_ka_time,
+				tcp_send_timeout,
+				tcp_conn-tcp_conn_table);
+			return;
+		}
+		DBLOCK(0x10, printf(
+		"tcp_send_timeout, conn[%d]: triggering keep alive probe\n",
+			tcp_conn-tcp_conn_table));
+		tcp_conn->tc_ka_snd--;
+		if (!(tcp_conn->tc_flags & TCF_FIN_SENT))
+		{
+			pkt= bf_memreq(1);
+			*ptr2acc_data(pkt)= '\xff';	/* a random char */
+			tcp_conn->tc_send_data= pkt; pkt= NULL;
+		}
+		tcp_conn->tc_SND_UNA--;
+		if (tcp_conn->tc_SND_UNA == tcp_conn->tc_ISS)
+		{
+			/* We didn't send anything so far. Retrying the
+			 * SYN is too hard. Decrement ISS and hope
+			 * that the other side doesn't care.
+			 */
+			tcp_conn->tc_ISS--;
+		}
+
+		/* Set tc_transmit_seq and tc_stt to trigger packet */
+		tcp_conn->tc_transmit_seq= tcp_conn->tc_SND_UNA;
+		tcp_conn->tc_stt= curr_time;
+
+		/* Set tc_rt_seq for round trip measurements */
+		tcp_conn->tc_rt_time= curr_time;
+		tcp_conn->tc_rt_seq= tcp_conn->tc_SND_UNA;
+
+		/* Set PSH to make sure that data gets sent */
+		tcp_conn->tc_SND_PSH= tcp_conn->tc_SND_NXT;
+		assert(tcp_check_conn(tcp_conn));
+
+		/* Fall through */
+	}
+
+	rtt= tcp_conn->tc_rtt;
+
+	if (tcp_conn->tc_transmit_seq != tcp_conn->tc_SND_UNA)
+	{
+		/* Some data has been acknowledged since the last time the
+		 * timer was set, set the timer again. */
+		tcp_conn->tc_transmit_seq= tcp_conn->tc_SND_UNA;
+		tcp_conn->tc_stt= 0;
+		tcp_conn->tc_0wnd_to= 0;
+
+		DBLOCK(0x20, printf(
+	"tcp_send_timeout: conn[%d] setting timer to %ld ms (+%ld ms)\n",
+			tcp_conn-tcp_conn_table,
+			(curr_time+rtt)*1000/HZ, rtt*1000/HZ));
+
+		clck_timer(&tcp_conn->tc_transmit_timer,
+			curr_time+rtt, tcp_send_timeout,
+			tcp_conn-tcp_conn_table);
+		return;
+	}
+
+	stt= tcp_conn->tc_stt;
+	if (stt == 0)
+	{
+		/* Some packet arrived but did not acknowledge any data.
+		 * Apparently, the other side is still alive and has a
+		 * reason to transmit. We can asume a zero window.
+		 */
+
+		DBLOCK(0x10, printf("conn[%d] setting zero window timer\n",
+			tcp_conn-tcp_conn_table));
+
+		if (tcp_conn->tc_0wnd_to < TCP_0WND_MIN)
+			tcp_conn->tc_0wnd_to= TCP_0WND_MIN;
+		else if (tcp_conn->tc_0wnd_to < rtt)
+			tcp_conn->tc_0wnd_to= rtt;
+		else
+		{
+			tcp_conn->tc_0wnd_to *= 2;
+			if (tcp_conn->tc_0wnd_to > TCP_0WND_MAX)
+				tcp_conn->tc_0wnd_to= TCP_0WND_MAX;
+		}
+		tcp_conn->tc_stt= curr_time;
+		tcp_conn->tc_rt_seq= 0;
+
+		DBLOCK(0x10, printf(
+	"tcp_send_timeout: conn[%d] setting timer to %ld ms (+%ld ms)\n",
+			tcp_conn-tcp_conn_table,
+			(curr_time+tcp_conn->tc_0wnd_to)*1000/HZ,
+			tcp_conn->tc_0wnd_to*1000/HZ));
+
+		clck_timer(&tcp_conn->tc_transmit_timer,
+			curr_time+tcp_conn->tc_0wnd_to,
+			tcp_send_timeout, tcp_conn-tcp_conn_table);
+		return;
+	}
+	assert(stt <= curr_time);
+
+	DIFBLOCK(0x10, (tcp_conn->tc_fd == 0),
+		printf("conn[%d] timeout in abondoned connection\n",
+		tcp_conn-tcp_conn_table));
+
+	/* At this point, we have do a retransmission, or send a zero window
+	 * probe, which is almost the same.
+	 */
+
+	DBLOCK(0x20, printf("tcp_send_timeout: conn[%d] una= %lu, rtt= %ldms\n",
+		tcp_conn-tcp_conn_table,
+		(unsigned long)tcp_conn->tc_SND_UNA, rtt*1000/HZ));
+
+	/* Update threshold sequence number for retransmission calculation. */
+	if (tcp_Gmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_rt_threshold))
+		tcp_conn->tc_rt_threshold= tcp_conn->tc_SND_TRM;
+
+	tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
+
+	if (tcp_conn->tc_flags & TCF_PMTU &&
+		curr_time > stt+TCP_PMTU_BLACKHOLE)
+	{
+		/* We can't tell the difference between a PMTU blackhole 
+		 * and a broken link. Assume a PMTU blackhole, and switch
+		 * off PMTU discovery.
+		 */
+		DBLOCK(1, printf(
+			"tcp[%d]: PMTU blackhole (or broken link) on route to ",
+			tcp_conn-tcp_conn_table);
+			writeIpAddr(tcp_conn->tc_remaddr);
+			printf(", max mtu = %u\n", tcp_conn->tc_max_mtu););
+		tcp_conn->tc_flags &= ~TCF_PMTU;
+		tcp_conn->tc_mtutim= curr_time;
+		if (tcp_conn->tc_max_mtu > IP_DEF_MTU)
+			tcp_conn->tc_mtu= IP_DEF_MTU;
+	}
+
+	mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
+	mss2= 2*mss;
+
+	if (tcp_conn->tc_snd_cwnd == tcp_conn->tc_SND_UNA)
+		tcp_conn->tc_snd_cwnd++;
+	if (tcp_Gmod4G(tcp_conn->tc_snd_cwnd, tcp_conn->tc_SND_UNA + mss2))
+	{
+		tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + mss2;
+		if (tcp_Gmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_snd_cwnd))
+			tcp_conn->tc_SND_TRM= tcp_conn->tc_snd_cwnd;
+
+		tcp_conn->tc_snd_cthresh /= 2;
+		if (tcp_conn->tc_snd_cthresh < mss2)
+			tcp_conn->tc_snd_cthresh= mss2;
+	}
+
+	if (curr_time-stt > tcp_conn->tc_rt_dead)
+	{
+		tcp_close_connection(tcp_conn, ETIMEDOUT);
+		return;
+	}
+
+	timeout= (curr_time-stt) >> 3;
+	if (timeout < rtt)
+		timeout= rtt;
+	timeout += curr_time;
+
+	DBLOCK(0x20, printf(
+	"tcp_send_timeout: conn[%d] setting timer to %ld ms (+%ld ms)\n",
+		tcp_conn-tcp_conn_table, timeout*1000/HZ,
+		(timeout-curr_time)*1000/HZ));
+
+	clck_timer(&tcp_conn->tc_transmit_timer, timeout,
+		tcp_send_timeout, tcp_conn-tcp_conn_table);
+
+#if 0
+	if (tcp_conn->tc_rt_seq == 0)
+	{
+		printf("tcp_send_timeout: conn[%d]: setting tc_rt_time\n",
+			tcp_conn-tcp_conn_table);
+		tcp_conn->tc_rt_time= curr_time-rtt;
+		tcp_conn->tc_rt_seq= tcp_conn->tc_SND_UNA;
+	}
+#endif
+
+	if (tcp_conn->tc_state == TCS_SYN_SENT ||
+		(curr_time-stt >= tcp_conn->tc_ttl*HZ))
+	{
+		new_ttl= tcp_conn->tc_ttl+1;
+		if (new_ttl> IP_MAX_TTL)
+			new_ttl= IP_MAX_TTL;
+		tcp_conn->tc_ttl= new_ttl;
+	}
+
+	tcp_conn_write(tcp_conn, 0);
+}
+
+
+PUBLIC void tcp_fd_write(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	tcp_fd_t *tcp_fd;
+	int urg, nourg, push;
+	u32_t max_seq;
+	size_t max_trans, write_count;
+	acc_t *data, *send_data;
+
+	assert(tcp_conn->tc_busy);
+	tcp_fd= tcp_conn->tc_fd;
+
+	if ((tcp_fd->tf_flags & TFF_IOCTL_IP) &&
+		!(tcp_fd->tf_flags & TFF_WRITE_IP))
+	{
+		if (tcp_fd->tf_ioreq != NWIOTCPSHUTDOWN)
+			return;
+		DBLOCK(0x10, printf("NWIOTCPSHUTDOWN\n"));
+		if (tcp_conn->tc_state == TCS_CLOSED)
+		{
+			tcp_reply_ioctl (tcp_fd, tcp_conn->tc_error);
+			return;
+		}
+		if (!(tcp_conn->tc_flags & TCF_FIN_SENT))
+		{
+			DBLOCK(0x10, printf("calling tcp_shutdown\n"));
+			tcp_shutdown (tcp_conn);
+		}
+		else
+		{
+			if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
+			{
+				tcp_reply_ioctl (tcp_fd, NW_OK);
+				DBLOCK(0x10, printf("shutdown completed\n"));
+			}
+			else
+			{
+				DBLOCK(0x10,
+					printf("shutdown still inprogress\n"));
+			}
+		}
+		return;
+	}
+
+	assert (tcp_fd->tf_flags & TFF_WRITE_IP);
+	if (tcp_conn->tc_state == TCS_CLOSED)
+	{
+		if (tcp_fd->tf_write_offset)
+		{
+			tcp_reply_write(tcp_fd,
+				tcp_fd->tf_write_offset);
+		}
+		else
+			tcp_reply_write(tcp_fd, tcp_conn->tc_error);
+		return;
+	}
+
+	urg= (tcp_fd->tf_flags & TFF_WR_URG);
+	push= (tcp_fd->tf_flags & TFF_PUSH_DATA);
+
+	max_seq= tcp_conn->tc_SND_UNA + TCP_MAX_SND_WND_SIZE;
+	max_trans= max_seq - tcp_conn->tc_SND_NXT;
+	if (tcp_fd->tf_write_count <= max_trans)
+		write_count= tcp_fd->tf_write_count;
+	else
+		write_count= max_trans;
+	if (write_count)
+	{
+		if (tcp_conn->tc_flags & TCF_BSD_URG)
+		{
+			if (tcp_Gmod4G(tcp_conn->tc_SND_NXT,
+				tcp_conn->tc_SND_UNA))
+			{
+				nourg= tcp_LEmod4G(tcp_conn->tc_SND_UP,
+					tcp_conn->tc_SND_UNA);
+				if ((urg && nourg) || (!urg && !nourg))
+				{
+					DBLOCK(0x20,
+						printf("not sending\n"));
+					return;
+				}
+			}
+		}
+		data= (*tcp_fd->tf_get_userdata)
+			(tcp_fd->tf_srfd, tcp_fd->tf_write_offset,
+			write_count, FALSE);
+
+		if (!data)
+		{
+			if (tcp_fd->tf_write_offset)
+			{
+				tcp_reply_write(tcp_fd,
+					tcp_fd->tf_write_offset);
+			}
+			else
+				tcp_reply_write(tcp_fd, EFAULT);
+			return;
+		}
+		tcp_fd->tf_write_offset += write_count;
+		tcp_fd->tf_write_count -= write_count;
+
+		send_data= tcp_conn->tc_send_data;
+		tcp_conn->tc_send_data= 0;
+		send_data= bf_append(send_data, data);
+		tcp_conn->tc_send_data= send_data;
+		tcp_conn->tc_SND_NXT += write_count;
+		if (urg)
+		{
+			if (tcp_conn->tc_flags & TCF_BSD_URG)
+				tcp_conn->tc_SND_UP= tcp_conn->tc_SND_NXT;
+			else
+				tcp_conn->tc_SND_UP= tcp_conn->tc_SND_NXT-1;
+		}
+		if (push && !tcp_fd->tf_write_count)
+			tcp_conn->tc_SND_PSH= tcp_conn->tc_SND_NXT;
+	}
+	if (!tcp_fd->tf_write_count)
+	{
+		tcp_reply_write(tcp_fd, tcp_fd->tf_write_offset);
+	}
+}
+
+PUBLIC unsigned tcp_sel_write(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	tcp_fd_t *tcp_fd;
+	int urg, nourg;
+	u32_t max_seq;
+	size_t max_trans;
+
+	tcp_fd= tcp_conn->tc_fd;
+
+	if (tcp_conn->tc_state == TCS_CLOSED)
+		return 1;
+	
+	urg= (tcp_fd->tf_flags & TFF_WR_URG);
+
+	max_seq= tcp_conn->tc_SND_UNA + TCP_MAX_SND_WND_SIZE;
+	max_trans= max_seq - tcp_conn->tc_SND_NXT;
+	if (max_trans)
+	{
+		if (tcp_conn->tc_flags & TCF_BSD_URG)
+		{
+			if (tcp_Gmod4G(tcp_conn->tc_SND_NXT,
+				tcp_conn->tc_SND_UNA))
+			{
+				nourg= tcp_LEmod4G(tcp_conn->tc_SND_UP,
+					tcp_conn->tc_SND_UNA);
+				if ((urg && nourg) || (!urg && !nourg))
+				{
+					DBLOCK(0x20,
+						printf("not sending\n"));
+					return 0;
+				}
+			}
+		}
+		return 1;
+	}
+
+	return 0;
+}
+
+PUBLIC void
+tcp_rsel_write(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	tcp_fd_t *tcp_fd;
+
+	if (tcp_sel_write(tcp_conn) == 0)
+		return;
+
+	tcp_fd= tcp_conn->tc_fd;
+	tcp_fd->tf_flags &= ~TFF_SEL_WRITE;
+	if (tcp_fd->tf_select_res)
+		tcp_fd->tf_select_res(tcp_fd->tf_srfd, SR_SELECT_WRITE);
+	else
+		printf("tcp_rsel_write: no select_res\n");
+}
+
+/*
+tcp_shutdown
+*/
+
+PUBLIC void tcp_shutdown(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	switch (tcp_conn->tc_state)
+	{
+	case TCS_CLOSED:
+	case TCS_LISTEN:
+	case TCS_SYN_SENT:
+	case TCS_SYN_RECEIVED:
+		tcp_close_connection(tcp_conn, ENOTCONN);
+		return;
+	}
+
+	if (tcp_conn->tc_flags & TCF_FIN_SENT)
+		return;
+	tcp_conn->tc_flags |= TCF_FIN_SENT;
+	tcp_conn->tc_flags &= ~TCF_NO_PUSH;
+	tcp_conn->tc_SND_NXT++;
+	tcp_conn->tc_SND_PSH= tcp_conn->tc_SND_NXT;
+
+	assert (tcp_check_conn(tcp_conn) ||
+		(tcp_print_conn(tcp_conn), printf("\n"), 0));
+
+	tcp_conn_write(tcp_conn, 1);
+
+	/* Start the timer */
+	tcp_set_send_timer(tcp_conn);
+}
+
+PUBLIC void tcp_set_send_timer(tcp_conn)
+tcp_conn_t *tcp_conn;
+{
+	clock_t curr_time;
+	clock_t rtt;
+
+	assert(tcp_conn->tc_state != TCS_CLOSED);
+	assert(tcp_conn->tc_state != TCS_LISTEN);
+
+	curr_time= get_time();
+	rtt= tcp_conn->tc_rtt;
+
+	DBLOCK(0x20, printf(
+	"tcp_set_send_timer: conn[%d] setting timer to %ld ms (+%ld ms)\n",
+		tcp_conn-tcp_conn_table,
+		(curr_time+rtt)*1000/HZ, rtt*1000/HZ));
+
+	/* Start the timer */
+	clck_timer(&tcp_conn->tc_transmit_timer,
+		curr_time+rtt, tcp_send_timeout, tcp_conn-tcp_conn_table);
+	tcp_conn->tc_stt= curr_time;
+}
+
+/*
+tcp_close_connection
+
+*/
+
+PUBLIC void tcp_close_connection(tcp_conn, error)
+tcp_conn_t *tcp_conn;
+int error;
+{
+	int i;
+	tcp_port_t *tcp_port;
+	tcp_fd_t *tcp_fd;
+	tcp_conn_t *tc;
+
+	assert (tcp_check_conn(tcp_conn) ||
+		(tcp_print_conn(tcp_conn), printf("\n"), 0));
+	assert (tcp_conn->tc_flags & TCF_INUSE);
+
+	tcp_conn->tc_error= error;
+	tcp_port= tcp_conn->tc_port;
+	tcp_fd= tcp_conn->tc_fd;
+	if (tcp_conn->tc_state == TCS_CLOSED)
+		return;
+
+	tcp_conn->tc_state= TCS_CLOSED;
+	DBLOCK(0x10, tcp_print_state(tcp_conn); printf("\n"));
+
+	if (tcp_fd && (tcp_fd->tf_flags & TFF_LISTENQ))
+	{
+		for (i= 0; i<TFL_LISTEN_MAX; i++)
+		{
+			if (tcp_fd->tf_listenq[i] == tcp_conn)
+				break;
+		}
+		assert(i < TFL_LISTEN_MAX);
+		tcp_fd->tf_listenq[i]= NULL;
+
+		assert(tcp_conn->tc_connInprogress);
+		tcp_conn->tc_connInprogress= 0;
+
+		tcp_conn->tc_fd= NULL;
+		tcp_fd= NULL;
+	}
+	else if (tcp_fd)
+	{
+
+		tcp_conn->tc_busy++;
+		assert(tcp_fd->tf_conn == tcp_conn);
+
+		if (tcp_fd->tf_flags & TFF_READ_IP)
+			tcp_fd_read (tcp_conn, 1);
+		assert (!(tcp_fd->tf_flags & TFF_READ_IP));
+		if (tcp_fd->tf_flags & TFF_SEL_READ)
+			tcp_rsel_read (tcp_conn);
+
+		if (tcp_fd->tf_flags & TFF_WRITE_IP)
+		{
+			tcp_fd_write(tcp_conn);
+			tcp_conn_write(tcp_conn, 1);
+		}
+		assert (!(tcp_fd->tf_flags & TFF_WRITE_IP));
+		if (tcp_fd->tf_flags & TFF_IOCTL_IP)
+		{
+			tcp_fd_write(tcp_conn);
+			tcp_conn_write(tcp_conn, 1);
+		}
+		if (tcp_fd->tf_flags & TFF_IOCTL_IP)
+			assert(tcp_fd->tf_ioreq != NWIOTCPSHUTDOWN);
+		if (tcp_fd->tf_flags & TFF_SEL_WRITE) 
+			tcp_rsel_write(tcp_conn);
+
+		if (tcp_conn->tc_connInprogress)
+			tcp_restart_connect(tcp_conn);
+		assert (!tcp_conn->tc_connInprogress);
+		assert (!(tcp_fd->tf_flags & TFF_IOCTL_IP) ||
+			(printf("req= 0x%lx\n",
+			(unsigned long)tcp_fd->tf_ioreq), 0));
+		tcp_conn->tc_busy--;
+	}
+
+	if (tcp_conn->tc_rcvd_data)
+	{
+		bf_afree(tcp_conn->tc_rcvd_data);
+		tcp_conn->tc_rcvd_data= NULL;
+	}
+	tcp_conn->tc_flags &= ~TCF_FIN_RECV;
+	tcp_conn->tc_RCV_LO= tcp_conn->tc_RCV_NXT;
+
+	if (tcp_conn->tc_adv_data)
+	{
+		bf_afree(tcp_conn->tc_adv_data);
+		tcp_conn->tc_adv_data= NULL;
+	}
+
+	if (tcp_conn->tc_send_data)
+	{
+		bf_afree(tcp_conn->tc_send_data);
+		tcp_conn->tc_send_data= NULL;
+		tcp_conn->tc_SND_TRM=
+			tcp_conn->tc_SND_NXT= tcp_conn->tc_SND_UNA;
+	}
+	tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_NXT= tcp_conn->tc_SND_UNA;
+
+	if (tcp_conn->tc_remipopt)
+	{
+		bf_afree(tcp_conn->tc_remipopt);
+		tcp_conn->tc_remipopt= NULL;
+	}
+
+	if (tcp_conn->tc_tcpopt)
+	{
+		bf_afree(tcp_conn->tc_tcpopt);
+		tcp_conn->tc_tcpopt= NULL;
+	}
+
+	if (tcp_conn->tc_frag2send)
+	{
+		bf_afree(tcp_conn->tc_frag2send);
+		tcp_conn->tc_frag2send= NULL;
+	}
+	if (tcp_conn->tc_flags & TCF_MORE2WRITE)
+	{
+		for (tc= tcp_port->tp_snd_head; tc; tc= tc->tc_send_link)
+		{
+			if (tc->tc_send_link == tcp_conn)
+				break;
+		}
+		if (tc == NULL)
+		{
+			assert(tcp_port->tp_snd_head == tcp_conn);
+			tcp_port->tp_snd_head= tcp_conn->tc_send_link;
+		}
+		else
+		{
+			tc->tc_send_link= tcp_conn->tc_send_link;
+			if (tc->tc_send_link == NULL)
+				tcp_port->tp_snd_tail= tc;
+		}
+		tcp_conn->tc_flags &= ~TCF_MORE2WRITE;
+	}
+
+	clck_untimer (&tcp_conn->tc_transmit_timer);
+	tcp_conn->tc_transmit_seq= 0;
+
+					/* clear all flags but TCF_INUSE */
+	tcp_conn->tc_flags &= TCF_INUSE;
+	assert (tcp_check_conn(tcp_conn));
+}
+
+/*
+ * $PchId: tcp_send.c,v 1.32 2005/06/28 14:21:52 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/type.h
===================================================================
--- /trunk/minix/servers/inet/generic/type.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/type.h	(revision 9)
@@ -0,0 +1,21 @@
+/*
+type.h
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef INET_TYPE_H
+#define INET_TYPE_H
+
+typedef struct acc *(*get_userdata_t) ARGS(( int fd, size_t offset,
+	size_t count, int for_ioctl ));
+typedef int (*put_userdata_t) ARGS(( int fd, size_t offset,
+	struct acc *data, int for_ioctl ));
+typedef void (*put_pkt_t) ARGS(( int fd, struct acc *data, size_t datalen ));
+typedef void (*select_res_t) ARGS(( int fd, unsigned ops ));
+
+#endif /* INET_TYPE_H */
+
+/*
+ * $PchId: type.h,v 1.6 2005/06/28 14:22:04 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/udp.c
===================================================================
--- /trunk/minix/servers/inet/generic/udp.c	(revision 9)
+++ /trunk/minix/servers/inet/generic/udp.c	(revision 9)
@@ -0,0 +1,1674 @@
+/*
+udp.c
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "type.h"
+
+#include "assert.h"
+#include "buf.h"
+#include "clock.h"
+#include "icmp_lib.h"
+#include "io.h"
+#include "ip.h"
+#include "sr.h"
+#include "udp.h"
+#include "udp_int.h"
+
+THIS_FILE
+
+FORWARD void read_ip_packets ARGS(( udp_port_t *udp_port ));
+FORWARD void udp_buffree ARGS(( int priority ));
+#ifdef BUF_CONSISTENCY_CHECK
+FORWARD void udp_bufcheck ARGS(( void ));
+#endif
+FORWARD void udp_main ARGS(( udp_port_t *udp_port ));
+FORWARD int udp_select ARGS(( int fd, unsigned operations ));
+FORWARD acc_t *udp_get_data ARGS(( int fd, size_t offset, size_t count, 
+	int for_ioctl ));
+FORWARD int udp_put_data ARGS(( int fd, size_t offset, acc_t *data, 	
+	int for_ioctl ));
+FORWARD int udp_peek ARGS(( udp_fd_t * ));
+FORWARD int udp_sel_read ARGS(( udp_fd_t * ));
+FORWARD void udp_restart_write_port ARGS(( udp_port_t *udp_port ));
+FORWARD void udp_ip_arrived ARGS(( int port, acc_t *pack, size_t pack_size ));
+FORWARD void reply_thr_put ARGS(( udp_fd_t *udp_fd, int reply,
+	int for_ioctl ));
+FORWARD void reply_thr_get ARGS(( udp_fd_t *udp_fd, int reply,
+	int for_ioctl ));
+FORWARD int udp_setopt ARGS(( udp_fd_t *udp_fd ));
+FORWARD udpport_t find_unused_port ARGS(( int fd ));
+FORWARD int is_unused_port ARGS(( Udpport_t port ));
+FORWARD int udp_packet2user ARGS(( udp_fd_t *udp_fd ));
+FORWARD void restart_write_fd ARGS(( udp_fd_t *udp_fd ));
+FORWARD u16_t pack_oneCsum ARGS(( acc_t *pack ));
+FORWARD void udp_rd_enqueue ARGS(( udp_fd_t *udp_fd, acc_t *pack,
+							clock_t exp_tim ));
+FORWARD void hash_fd ARGS(( udp_fd_t *udp_fd ));
+FORWARD void unhash_fd ARGS(( udp_fd_t *udp_fd ));
+
+PUBLIC udp_port_t *udp_port_table;
+PUBLIC udp_fd_t udp_fd_table[UDP_FD_NR];
+
+PUBLIC void udp_prep()
+{
+	udp_port_table= alloc(udp_conf_nr * sizeof(udp_port_table[0]));
+}
+
+PUBLIC void udp_init()
+{
+	udp_fd_t *udp_fd;
+	udp_port_t *udp_port;
+	int i, j, ifno;
+
+	assert (BUF_S >= sizeof(struct nwio_ipopt));
+	assert (BUF_S >= sizeof(struct nwio_ipconf));
+	assert (BUF_S >= sizeof(struct nwio_udpopt));
+	assert (BUF_S >= sizeof(struct udp_io_hdr));
+	assert (UDP_HDR_SIZE == sizeof(udp_hdr_t));
+	assert (UDP_IO_HDR_SIZE == sizeof(udp_io_hdr_t));
+
+	for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
+	{
+		udp_fd->uf_flags= UFF_EMPTY;
+		udp_fd->uf_rdbuf_head= NULL;
+	}
+
+#ifndef BUF_CONSISTENCY_CHECK
+	bf_logon(udp_buffree);
+#else
+	bf_logon(udp_buffree, udp_bufcheck);
+#endif
+
+	for (i= 0, udp_port= udp_port_table; i<udp_conf_nr; i++, udp_port++)
+	{
+		udp_port->up_ipdev= udp_conf[i].uc_port;
+
+		udp_port->up_flags= UPF_EMPTY;
+		udp_port->up_state= UPS_EMPTY;
+		udp_port->up_next_fd= udp_fd_table;
+		udp_port->up_write_fd= NULL;
+		udp_port->up_wr_pack= NULL;
+		udp_port->up_port_any= NULL;
+		for (j= 0; j<UDP_PORT_HASH_NR; j++)
+			udp_port->up_port_hash[j]= NULL;
+
+		ifno= ip_conf[udp_port->up_ipdev].ic_ifno;
+		sr_add_minor(if2minor(ifno, UDP_DEV_OFF),
+			i, udp_open, udp_close, udp_read,
+			udp_write, udp_ioctl, udp_cancel, udp_select);
+
+		udp_main(udp_port);
+	}
+}
+
+PUBLIC int udp_open (port, srfd, get_userdata, put_userdata, put_pkt,
+	select_res)
+int port;
+int srfd;
+get_userdata_t get_userdata;
+put_userdata_t put_userdata;
+put_pkt_t put_pkt;
+select_res_t select_res;
+{
+	int i;
+	udp_fd_t *udp_fd;
+
+	for (i= 0; i<UDP_FD_NR && (udp_fd_table[i].uf_flags & UFF_INUSE);
+		i++);
+
+	if (i>= UDP_FD_NR)
+	{
+		DBLOCK(1, printf("out of fds\n"));
+		return EAGAIN;
+	}
+
+	udp_fd= &udp_fd_table[i];
+
+	udp_fd->uf_flags= UFF_INUSE;
+	udp_fd->uf_port= &udp_port_table[port];
+	udp_fd->uf_srfd= srfd;
+	udp_fd->uf_udpopt.nwuo_flags= UDP_DEF_OPT;
+	udp_fd->uf_get_userdata= get_userdata;
+	udp_fd->uf_put_userdata= put_userdata;
+	udp_fd->uf_select_res= select_res;
+	assert(udp_fd->uf_rdbuf_head == NULL);
+	udp_fd->uf_port_next= NULL;
+
+	return i;
+
+}
+
+PUBLIC int udp_ioctl (fd, req)
+int fd;
+ioreq_t req;
+{
+	udp_fd_t *udp_fd;
+	udp_port_t *udp_port;
+	nwio_udpopt_t *udp_opt;
+	acc_t *opt_acc;
+	int result;
+
+	udp_fd= &udp_fd_table[fd];
+
+assert (udp_fd->uf_flags & UFF_INUSE);
+
+	udp_port= udp_fd->uf_port;
+	udp_fd->uf_flags |= UFF_IOCTL_IP;
+	udp_fd->uf_ioreq= req;
+
+	if (udp_port->up_state != UPS_MAIN)
+		return NW_SUSPEND;
+
+	switch(req)
+	{
+	case NWIOSUDPOPT:
+		result= udp_setopt(udp_fd);
+		break;
+	case NWIOGUDPOPT:
+		opt_acc= bf_memreq(sizeof(*udp_opt));
+assert (opt_acc->acc_length == sizeof(*udp_opt));
+		udp_opt= (nwio_udpopt_t *)ptr2acc_data(opt_acc);
+
+		*udp_opt= udp_fd->uf_udpopt;
+		udp_opt->nwuo_locaddr= udp_fd->uf_port->up_ipaddr;
+		result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, 0, opt_acc,
+			TRUE);
+		if (result == NW_OK)
+			reply_thr_put(udp_fd, NW_OK, TRUE);
+		break;
+	case NWIOUDPPEEK:
+		result= udp_peek(udp_fd);
+		break;
+	default:
+		reply_thr_get(udp_fd, EBADIOCTL, TRUE);
+		result= NW_OK;
+		break;
+	}
+	if (result != NW_SUSPEND)
+		udp_fd->uf_flags &= ~UFF_IOCTL_IP;
+	return result;
+}
+
+PUBLIC int udp_read (fd, count)
+int fd;
+size_t count;
+{
+	udp_fd_t *udp_fd;
+	acc_t *tmp_acc, *next_acc;
+
+	udp_fd= &udp_fd_table[fd];
+	if (!(udp_fd->uf_flags & UFF_OPTSET))
+	{
+		reply_thr_put(udp_fd, EBADMODE, FALSE);
+		return NW_OK;
+	}
+
+	udp_fd->uf_rd_count= count;
+
+	if (udp_fd->uf_rdbuf_head)
+	{
+		if (get_time() <= udp_fd->uf_exp_tim)
+			return udp_packet2user (udp_fd);
+		tmp_acc= udp_fd->uf_rdbuf_head;
+		while (tmp_acc)
+		{
+			next_acc= tmp_acc->acc_ext_link;
+			bf_afree(tmp_acc);
+			tmp_acc= next_acc;
+		}
+		udp_fd->uf_rdbuf_head= NULL;
+	}
+	udp_fd->uf_flags |= UFF_READ_IP;
+	return NW_SUSPEND;
+}
+
+PRIVATE void udp_main(udp_port)
+udp_port_t *udp_port;
+{
+	udp_fd_t *udp_fd;
+	int result, i;
+
+	switch (udp_port->up_state)
+	{
+	case UPS_EMPTY:
+		udp_port->up_state= UPS_SETPROTO;
+
+		udp_port->up_ipfd= ip_open(udp_port->up_ipdev, 
+			udp_port->up_ipdev, udp_get_data, udp_put_data,
+			udp_ip_arrived, 0 /* no select_res */);
+		if (udp_port->up_ipfd < 0)
+		{
+			udp_port->up_state= UPS_ERROR;
+			DBLOCK(1, printf("%s, %d: unable to open ip port\n",
+				__FILE__, __LINE__));
+			return;
+		}
+
+		result= ip_ioctl(udp_port->up_ipfd, NWIOSIPOPT);
+		if (result == NW_SUSPEND)
+			udp_port->up_flags |= UPF_SUSPEND;
+		if (result<0)
+		{
+			return;
+		}
+		if (udp_port->up_state != UPS_GETCONF)
+			return;
+		/* drops through */
+	case UPS_GETCONF:
+		udp_port->up_flags &= ~UPF_SUSPEND;
+
+		result= ip_ioctl(udp_port->up_ipfd, NWIOGIPCONF);
+		if (result == NW_SUSPEND)
+			udp_port->up_flags |= UPF_SUSPEND;
+		if (result<0)
+		{
+			return;
+		}
+		if (udp_port->up_state != UPS_MAIN)
+			return;
+		/* drops through */
+	case UPS_MAIN:
+		udp_port->up_flags &= ~UPF_SUSPEND;
+
+		for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
+		{
+			if (!(udp_fd->uf_flags & UFF_INUSE))
+				continue;
+			if (udp_fd->uf_port != udp_port)
+				continue;
+			if (udp_fd->uf_flags & UFF_IOCTL_IP)
+				udp_ioctl(i, udp_fd->uf_ioreq);
+		}
+		read_ip_packets(udp_port);
+		return;
+	default:
+		DBLOCK(1, printf("udp_port_table[%d].up_state= %d\n",
+			udp_port->up_ipdev, udp_port->up_state));
+		ip_panic(( "unknown state" ));
+		break;
+	}
+}
+
+PRIVATE int udp_select(fd, operations)
+int fd;
+unsigned operations;
+{
+	int i;
+	unsigned resops;
+	udp_fd_t *udp_fd;
+
+	udp_fd= &udp_fd_table[fd];
+	assert (udp_fd->uf_flags & UFF_INUSE);
+
+	resops= 0;
+
+	if (operations & SR_SELECT_READ)
+	{
+		if (udp_sel_read(udp_fd))
+			resops |= SR_SELECT_READ;
+		else if (!(operations & SR_SELECT_POLL))
+			udp_fd->uf_flags |= UFF_SEL_READ;
+	}
+	if (operations & SR_SELECT_WRITE)
+	{
+		/* Should handle special case when the interface is down */
+		resops |= SR_SELECT_WRITE;
+	}
+	if (operations & SR_SELECT_EXCEPTION)
+	{
+		printf("udp_select: not implemented for exceptions\n");
+	}
+	return resops;
+}
+
+PRIVATE acc_t *udp_get_data (port, offset, count, for_ioctl)
+int port;
+size_t offset;
+size_t count;
+int for_ioctl;
+{
+	udp_port_t *udp_port;
+	udp_fd_t *udp_fd;
+	int result;
+
+	udp_port= &udp_port_table[port];
+
+	switch(udp_port->up_state)
+	{
+	case UPS_SETPROTO:
+assert (for_ioctl);
+		if (!count)
+		{
+			result= (int)offset;
+			if (result<0)
+			{
+				udp_port->up_state= UPS_ERROR;
+				break;
+			}
+			udp_port->up_state= UPS_GETCONF;
+			if (udp_port->up_flags & UPF_SUSPEND)
+				udp_main(udp_port);
+			return NULL;
+		}
+		else
+		{
+			struct nwio_ipopt *ipopt;
+			acc_t *acc;
+
+assert (!offset);
+assert (count == sizeof(*ipopt));
+
+			acc= bf_memreq(sizeof(*ipopt));
+			ipopt= (struct nwio_ipopt *)ptr2acc_data(acc);
+			ipopt->nwio_flags= NWIO_COPY | NWIO_EN_LOC | 
+				NWIO_EN_BROAD | NWIO_REMANY | NWIO_PROTOSPEC |
+				NWIO_HDR_O_ANY | NWIO_RWDATALL;
+			ipopt->nwio_proto= IPPROTO_UDP;
+			return acc;
+		}
+	case UPS_MAIN:
+assert (!for_ioctl);
+assert (udp_port->up_flags & UPF_WRITE_IP);
+		if (!count)
+		{
+			result= (int)offset;
+assert (udp_port->up_wr_pack);
+			bf_afree(udp_port->up_wr_pack);
+			udp_port->up_wr_pack= 0;
+			if (udp_port->up_flags & UPF_WRITE_SP)
+			{
+				if (udp_port->up_write_fd)
+				{
+					udp_fd= udp_port->up_write_fd;
+					udp_port->up_write_fd= NULL;
+					udp_fd->uf_flags &= ~UFF_WRITE_IP;
+					reply_thr_get(udp_fd, result, FALSE);
+				}
+				udp_port->up_flags &= ~(UPF_WRITE_SP | 
+					UPF_WRITE_IP);
+				if (udp_port->up_flags & UPF_MORE2WRITE)
+				{
+					udp_restart_write_port(udp_port);
+				}
+			}
+			else
+				udp_port->up_flags &= ~UPF_WRITE_IP;
+		}
+		else
+		{
+			return bf_cut (udp_port->up_wr_pack, offset, count);
+		}
+		break;
+	default:
+		printf("udp_get_data(%d, 0x%x, 0x%x) called but up_state= 0x%x\n",
+			port, offset, count, udp_port->up_state);
+		break;
+	}
+	return NULL;
+}
+
+PRIVATE int udp_put_data (fd, offset, data, for_ioctl)
+int fd;
+size_t offset;
+acc_t *data;
+int for_ioctl;
+{
+	udp_port_t *udp_port;
+	int result;
+
+	udp_port= &udp_port_table[fd];
+
+	switch (udp_port->up_state)
+	{
+	case UPS_GETCONF:
+		if (!data)
+		{
+			result= (int)offset;
+			if (result<0)
+			{
+				udp_port->up_state= UPS_ERROR;
+				return NW_OK;
+			}
+			udp_port->up_state= UPS_MAIN;
+			if (udp_port->up_flags & UPF_SUSPEND)
+				udp_main(udp_port);
+		}
+		else
+		{
+			struct nwio_ipconf *ipconf;
+
+			data= bf_packIffLess(data, sizeof(*ipconf));
+			ipconf= (struct nwio_ipconf *)ptr2acc_data(data);
+assert (ipconf->nwic_flags & NWIC_IPADDR_SET);
+			udp_port->up_ipaddr= ipconf->nwic_ipaddr;
+			bf_afree(data);
+		}
+		break;
+	case UPS_MAIN:
+		assert(0);
+
+		assert (udp_port->up_flags & UPF_READ_IP);
+		if (!data)
+		{
+			result= (int)offset;
+			compare (result, >=, 0);
+			if (udp_port->up_flags & UPF_READ_SP)
+			{
+				udp_port->up_flags &= ~(UPF_READ_SP|
+					UPF_READ_IP);
+				read_ip_packets(udp_port);
+			}
+			else
+				udp_port->up_flags &= ~UPF_READ_IP;
+		}
+		else
+		{
+assert (!offset);	/* This isn't a valid assertion but ip sends only
+			 * whole datagrams up */
+			udp_ip_arrived(fd, data, bf_bufsize(data));
+		}
+		break;
+	default:
+		ip_panic((
+		"udp_put_data(%d, 0x%x, %p) called but up_state= 0x%x\n",
+					fd, offset, data, udp_port->up_state ));
+	}
+	return NW_OK;
+}
+
+PRIVATE int udp_setopt(udp_fd)
+udp_fd_t *udp_fd;
+{
+	udp_fd_t *fd_ptr;
+	nwio_udpopt_t oldopt, newopt;
+	acc_t *data;
+	unsigned int new_en_flags, new_di_flags, old_en_flags, old_di_flags,
+		all_flags, flags;
+	unsigned long new_flags;
+	int i;
+
+	data= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, 0, 
+		sizeof(nwio_udpopt_t), TRUE);
+
+	if (!data)
+		return EFAULT;
+
+	data= bf_packIffLess(data, sizeof(nwio_udpopt_t));
+assert (data->acc_length == sizeof(nwio_udpopt_t));
+
+	newopt= *(nwio_udpopt_t *)ptr2acc_data(data);
+	bf_afree(data);
+	oldopt= udp_fd->uf_udpopt;
+
+	old_en_flags= oldopt.nwuo_flags & 0xffff;
+	old_di_flags= (oldopt.nwuo_flags >> 16) & 0xffff;
+
+	new_en_flags= newopt.nwuo_flags & 0xffff;
+	new_di_flags= (newopt.nwuo_flags >> 16) & 0xffff;
+
+	if (new_en_flags & new_di_flags)
+	{
+		DBLOCK(1, printf("returning EBADMODE\n"));
+
+		reply_thr_get(udp_fd, EBADMODE, TRUE);
+		return NW_OK;
+	}
+
+	/* NWUO_ACC_MASK */
+	if (new_di_flags & NWUO_ACC_MASK)
+	{
+		DBLOCK(1, printf("returning EBADMODE\n"));
+
+		reply_thr_get(udp_fd, EBADMODE, TRUE);
+		return NW_OK;
+		/* access modes can't be disabled */
+	}
+
+	if (!(new_en_flags & NWUO_ACC_MASK))
+		new_en_flags |= (old_en_flags & NWUO_ACC_MASK);
+
+	/* NWUO_LOCPORT_MASK */
+	if (new_di_flags & NWUO_LOCPORT_MASK)
+	{
+		DBLOCK(1, printf("returning EBADMODE\n"));
+
+		reply_thr_get(udp_fd, EBADMODE, TRUE);
+		return NW_OK;
+		/* the loc ports can't be disabled */
+	}
+	if (!(new_en_flags & NWUO_LOCPORT_MASK))
+	{
+		new_en_flags |= (old_en_flags & NWUO_LOCPORT_MASK);
+		newopt.nwuo_locport= oldopt.nwuo_locport;
+	}
+	else if ((new_en_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SEL)
+	{
+		newopt.nwuo_locport= find_unused_port(udp_fd-udp_fd_table);
+	}
+	else if ((new_en_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SET)
+	{
+		if (!newopt.nwuo_locport)
+		{
+			DBLOCK(1, printf("returning EBADMODE\n"));
+
+			reply_thr_get(udp_fd, EBADMODE, TRUE);
+			return NW_OK;
+		}
+	}
+
+	/* NWUO_LOCADDR_MASK */
+	if (!((new_en_flags | new_di_flags) & NWUO_LOCADDR_MASK))
+	{
+		new_en_flags |= (old_en_flags & NWUO_LOCADDR_MASK);
+		new_di_flags |= (old_di_flags & NWUO_LOCADDR_MASK);
+	}
+
+	/* NWUO_BROAD_MASK */
+	if (!((new_en_flags | new_di_flags) & NWUO_BROAD_MASK))
+	{
+		new_en_flags |= (old_en_flags & NWUO_BROAD_MASK);
+		new_di_flags |= (old_di_flags & NWUO_BROAD_MASK);
+	}
+
+	/* NWUO_REMPORT_MASK */
+	if (!((new_en_flags | new_di_flags) & NWUO_REMPORT_MASK))
+	{
+		new_en_flags |= (old_en_flags & NWUO_REMPORT_MASK);
+		new_di_flags |= (old_di_flags & NWUO_REMPORT_MASK);
+		newopt.nwuo_remport= oldopt.nwuo_remport;
+	}
+	
+	/* NWUO_REMADDR_MASK */
+	if (!((new_en_flags | new_di_flags) & NWUO_REMADDR_MASK))
+	{
+		new_en_flags |= (old_en_flags & NWUO_REMADDR_MASK);
+		new_di_flags |= (old_di_flags & NWUO_REMADDR_MASK);
+		newopt.nwuo_remaddr= oldopt.nwuo_remaddr;
+	}
+
+	/* NWUO_RW_MASK */
+	if (!((new_en_flags | new_di_flags) & NWUO_RW_MASK))
+	{
+		new_en_flags |= (old_en_flags & NWUO_RW_MASK);
+		new_di_flags |= (old_di_flags & NWUO_RW_MASK);
+	}
+
+	/* NWUO_IPOPT_MASK */
+	if (!((new_en_flags | new_di_flags) & NWUO_IPOPT_MASK))
+	{
+		new_en_flags |= (old_en_flags & NWUO_IPOPT_MASK);
+		new_di_flags |= (old_di_flags & NWUO_IPOPT_MASK);
+	}
+
+	new_flags= ((unsigned long)new_di_flags << 16) | new_en_flags;
+	if ((new_flags & NWUO_RWDATONLY) && 
+		((new_flags & NWUO_LOCPORT_MASK) == NWUO_LP_ANY || 
+		(new_flags & (NWUO_RP_ANY|NWUO_RA_ANY|NWUO_EN_IPOPT))))
+	{
+		DBLOCK(1, printf("returning EBADMODE\n"));
+
+		reply_thr_get(udp_fd, EBADMODE, TRUE);
+		return NW_OK;
+	}
+
+	/* Check the access modes */
+	if ((new_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SEL ||
+		(new_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SET)
+	{
+		for (i= 0, fd_ptr= udp_fd_table; i<UDP_FD_NR; i++, fd_ptr++)
+		{
+			if (fd_ptr == udp_fd)
+				continue;
+			if (!(fd_ptr->uf_flags & UFF_INUSE))
+				continue;
+			if (fd_ptr->uf_port != udp_fd->uf_port)
+				continue;
+			flags= fd_ptr->uf_udpopt.nwuo_flags;
+			if ((flags & NWUO_LOCPORT_MASK) != NWUO_LP_SEL &&
+				(flags & NWUO_LOCPORT_MASK) != NWUO_LP_SET)
+				continue;
+			if (fd_ptr->uf_udpopt.nwuo_locport !=
+				newopt.nwuo_locport)
+			{
+				continue;
+			}
+			if ((flags & NWUO_ACC_MASK) != 
+				(new_flags & NWUO_ACC_MASK))
+			{
+				DBLOCK(1, printf(
+			"address inuse: new fd= %d, old_fd= %d, port= %u\n",
+					udp_fd-udp_fd_table,
+					fd_ptr-udp_fd_table,
+					newopt.nwuo_locport));
+
+				reply_thr_get(udp_fd, EADDRINUSE, TRUE);
+				return NW_OK;
+			}
+		}
+	}
+
+	if (udp_fd->uf_flags & UFF_OPTSET)
+		unhash_fd(udp_fd);
+
+	newopt.nwuo_flags= new_flags;
+	udp_fd->uf_udpopt= newopt;
+
+	all_flags= new_en_flags | new_di_flags;
+	if ((all_flags & NWUO_ACC_MASK) && (all_flags & NWUO_LOCPORT_MASK) &&
+		(all_flags & NWUO_LOCADDR_MASK) &&
+		(all_flags & NWUO_BROAD_MASK) &&
+		(all_flags & NWUO_REMPORT_MASK) &&
+		(all_flags & NWUO_REMADDR_MASK) &&
+		(all_flags & NWUO_RW_MASK) &&
+		(all_flags & NWUO_IPOPT_MASK))
+		udp_fd->uf_flags |= UFF_OPTSET;
+	else
+	{
+		udp_fd->uf_flags &= ~UFF_OPTSET;
+	}
+
+	if (udp_fd->uf_flags & UFF_OPTSET)
+		hash_fd(udp_fd);
+
+	reply_thr_get(udp_fd, NW_OK, TRUE);
+	return NW_OK;
+}
+
+PRIVATE udpport_t find_unused_port(fd)
+int fd;
+{
+	udpport_t port, nw_port;
+
+	for (port= 0x8000+fd; port < 0xffff-UDP_FD_NR; port+= UDP_FD_NR)
+	{
+		nw_port= htons(port);
+		if (is_unused_port(nw_port))
+			return nw_port;
+	}
+	for (port= 0x8000; port < 0xffff; port++)
+	{
+		nw_port= htons(port);
+		if (is_unused_port(nw_port))
+			return nw_port;
+	}
+	ip_panic(( "unable to find unused port (shouldn't occur)" ));
+	return 0;
+}
+
+/*
+reply_thr_put
+*/
+
+PRIVATE void reply_thr_put(udp_fd, reply, for_ioctl)
+udp_fd_t *udp_fd;
+int reply;
+int for_ioctl;
+{
+	int result;
+
+	result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, reply,
+		(acc_t *)0, for_ioctl);
+	assert(result == NW_OK);
+}
+
+/*
+reply_thr_get
+*/
+
+PRIVATE void reply_thr_get(udp_fd, reply, for_ioctl)
+udp_fd_t *udp_fd;
+int reply;
+int for_ioctl;
+{
+	acc_t *result;
+	result= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, reply,
+		(size_t)0, for_ioctl);
+	assert (!result);
+}
+
+PRIVATE int is_unused_port(port)
+udpport_t port;
+{
+	int i;
+	udp_fd_t *udp_fd;
+
+	for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++,
+		udp_fd++)
+	{
+		if (!(udp_fd->uf_flags & UFF_OPTSET))
+			continue;
+		if (udp_fd->uf_udpopt.nwuo_locport == port)
+			return FALSE;
+	}
+	return TRUE;
+}
+
+PRIVATE void read_ip_packets(udp_port)
+udp_port_t *udp_port;
+{
+	int result;
+
+	do
+	{
+		udp_port->up_flags |= UPF_READ_IP;
+		result= ip_read(udp_port->up_ipfd, UDP_MAX_DATAGRAM);
+		if (result == NW_SUSPEND)
+		{
+			udp_port->up_flags |= UPF_READ_SP;
+			return;
+		}
+assert(result == NW_OK);
+		udp_port->up_flags &= ~UPF_READ_IP;
+	} while(!(udp_port->up_flags & UPF_READ_IP));
+}
+
+
+PRIVATE int udp_peek (udp_fd)
+udp_fd_t *udp_fd;
+{
+	acc_t *pack, *tmp_acc, *next_acc;
+	int result;
+
+	if (!(udp_fd->uf_flags & UFF_OPTSET))
+	{
+		udp_fd->uf_flags &= ~UFF_IOCTL_IP;
+		reply_thr_put(udp_fd, EBADMODE, TRUE);
+		return NW_OK;
+	}
+
+	if (udp_fd->uf_rdbuf_head)
+	{
+		if (get_time() <= udp_fd->uf_exp_tim)
+		{
+			pack= bf_cut(udp_fd->uf_rdbuf_head, 0,
+				sizeof(udp_io_hdr_t));
+			result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
+				(size_t)0, pack, TRUE);
+
+			udp_fd->uf_flags &= ~UFF_IOCTL_IP;
+			result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
+				result, (acc_t *)0, TRUE);
+			assert (result == 0);
+			return result;
+		}
+		tmp_acc= udp_fd->uf_rdbuf_head;
+		while (tmp_acc)
+		{
+			next_acc= tmp_acc->acc_ext_link;
+			bf_afree(tmp_acc);
+			tmp_acc= next_acc;
+		}
+		udp_fd->uf_rdbuf_head= NULL;
+	}
+	udp_fd->uf_flags |= UFF_PEEK_IP;
+	return NW_SUSPEND;
+}
+
+PRIVATE int udp_sel_read (udp_fd)
+udp_fd_t *udp_fd;
+{
+	acc_t *pack, *tmp_acc, *next_acc;
+	int result;
+
+	if (!(udp_fd->uf_flags & UFF_OPTSET))
+		return 1;	/* Read will not block */
+
+	if (udp_fd->uf_rdbuf_head)
+	{
+		if (get_time() <= udp_fd->uf_exp_tim)
+			return 1;
+		
+		tmp_acc= udp_fd->uf_rdbuf_head;
+		while (tmp_acc)
+		{
+			next_acc= tmp_acc->acc_ext_link;
+			bf_afree(tmp_acc);
+			tmp_acc= next_acc;
+		}
+		udp_fd->uf_rdbuf_head= NULL;
+	}
+	return 0;
+}
+
+PRIVATE int udp_packet2user (udp_fd)
+udp_fd_t *udp_fd;
+{
+	acc_t *pack, *tmp_pack;
+	udp_io_hdr_t *hdr;
+	int result, hdr_len;
+	size_t size, transf_size;
+
+	pack= udp_fd->uf_rdbuf_head;
+	udp_fd->uf_rdbuf_head= pack->acc_ext_link;
+
+	size= bf_bufsize (pack);
+
+	if (udp_fd->uf_udpopt.nwuo_flags & NWUO_RWDATONLY)
+	{
+
+		pack= bf_packIffLess (pack, UDP_IO_HDR_SIZE);
+		assert (pack->acc_length >= UDP_IO_HDR_SIZE);
+
+		hdr= (udp_io_hdr_t *)ptr2acc_data(pack);
+#if CONF_UDP_IO_NW_BYTE_ORDER
+		hdr_len= UDP_IO_HDR_SIZE+NTOHS(hdr->uih_ip_opt_len);
+#else
+		hdr_len= UDP_IO_HDR_SIZE+hdr->uih_ip_opt_len;
+#endif
+
+		assert (size>= hdr_len);
+		size -= hdr_len;
+		tmp_pack= bf_cut(pack, hdr_len, size);
+		bf_afree(pack);
+		pack= tmp_pack;
+	}
+
+	if (size>udp_fd->uf_rd_count)
+	{
+		tmp_pack= bf_cut (pack, 0, udp_fd->uf_rd_count);
+		bf_afree(pack);
+		pack= tmp_pack;
+		transf_size= udp_fd->uf_rd_count;
+	}
+	else
+		transf_size= size;
+
+	result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
+		(size_t)0, pack, FALSE);
+
+	if (result >= 0)
+		if (size > transf_size)
+			result= EPACKSIZE;
+		else
+			result= transf_size;
+
+	udp_fd->uf_flags &= ~UFF_READ_IP;
+	result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, result,
+			(acc_t *)0, FALSE);
+	assert (result == 0);
+
+	return result;
+}
+
+PRIVATE void udp_ip_arrived(port, pack, pack_size)
+int port;
+acc_t *pack;
+size_t pack_size;
+{
+	udp_port_t *udp_port;
+	udp_fd_t *udp_fd, *share_fd;
+	acc_t *ip_hdr_acc, *udp_acc, *ipopt_pack, *no_ipopt_pack, *tmp_acc;
+	ip_hdr_t *ip_hdr;
+	udp_hdr_t *udp_hdr;
+	udp_io_hdr_t *udp_io_hdr;
+	size_t ip_hdr_size, udp_size, data_size, opt_size;
+	ipaddr_t src_addr, dst_addr, ipaddr;
+	udpport_t src_port, dst_port;
+	u8_t u16[2];
+	u16_t chksum;
+	unsigned long dst_type, flags;
+	clock_t exp_tim;
+	int i, delivered, hash;
+
+	udp_port= &udp_port_table[port];
+
+	ip_hdr_acc= bf_cut(pack, 0, IP_MIN_HDR_SIZE);
+	ip_hdr_acc= bf_packIffLess(ip_hdr_acc, IP_MIN_HDR_SIZE);
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_acc);
+	ip_hdr_size= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
+	if (ip_hdr_size != IP_MIN_HDR_SIZE)
+	{
+		bf_afree(ip_hdr_acc);
+		ip_hdr_acc= bf_cut(pack, 0, ip_hdr_size);
+		ip_hdr_acc= bf_packIffLess(ip_hdr_acc, ip_hdr_size);
+		ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_acc);
+	}
+
+	pack_size -= ip_hdr_size;
+	if (pack_size < UDP_HDR_SIZE)
+	{
+		if (pack_size == 0 && ip_hdr->ih_proto == 0)
+		{
+			/* IP layer reports new IP address */
+			ipaddr= ip_hdr->ih_src;
+			udp_port->up_ipaddr= ipaddr;
+			DBLOCK(1, printf("udp_ip_arrived: using address ");
+				writeIpAddr(ipaddr); printf("\n"));
+		}
+		else
+			DBLOCK(1, printf("packet too small\n"));
+
+		bf_afree(ip_hdr_acc);
+		bf_afree(pack);
+		return;
+	}
+
+	udp_acc= bf_delhead(pack, ip_hdr_size);
+	pack= NULL;
+
+
+	udp_acc= bf_packIffLess(udp_acc, UDP_HDR_SIZE);
+	udp_hdr= (udp_hdr_t *)ptr2acc_data(udp_acc);
+	udp_size= ntohs(udp_hdr->uh_length);
+	if (udp_size > pack_size)
+	{
+		DBLOCK(1, printf("packet too large\n"));
+
+		bf_afree(ip_hdr_acc);
+		bf_afree(udp_acc);
+		return;
+	}
+
+	src_addr= ip_hdr->ih_src;
+	dst_addr= ip_hdr->ih_dst;
+
+	if (udp_hdr->uh_chksum)
+	{
+		u16[0]= 0;
+		u16[1]= ip_hdr->ih_proto;
+		chksum= pack_oneCsum(udp_acc);
+		chksum= oneC_sum(chksum, (u16_t *)&src_addr, sizeof(ipaddr_t));
+		chksum= oneC_sum(chksum, (u16_t *)&dst_addr, sizeof(ipaddr_t));
+		chksum= oneC_sum(chksum, (u16_t *)u16, sizeof(u16));
+		chksum= oneC_sum(chksum, (u16_t *)&udp_hdr->uh_length, 
+			sizeof(udp_hdr->uh_length));
+		if (~chksum & 0xffff)
+		{
+			DBLOCK(1, printf("checksum error in udp packet\n");
+				printf("src ip_addr= ");
+				writeIpAddr(src_addr);
+				printf(" dst ip_addr= ");
+				writeIpAddr(dst_addr);
+				printf("\n");
+				printf("packet chksum= 0x%x, sum= 0x%x\n",
+					udp_hdr->uh_chksum, chksum));
+
+			bf_afree(ip_hdr_acc);
+			bf_afree(udp_acc);
+			return;
+		}
+	}
+
+	exp_tim= get_time() + UDP_READ_EXP_TIME;
+	src_port= udp_hdr->uh_src_port;
+	dst_port= udp_hdr->uh_dst_port;
+
+	/* Send an ICMP port unreachable if the packet could not be
+	 * delivered.
+	 */
+	delivered= 0;
+
+	if (dst_addr == udp_port->up_ipaddr)
+		dst_type= NWUO_EN_LOC;
+	else
+	{
+		dst_type= NWUO_EN_BROAD;
+
+		/* Don't send ICMP error packets for broadcast packets */
+		delivered= 1;
+	}
+
+	DBLOCK(0x20, printf("udp: got packet from ");
+		writeIpAddr(src_addr);
+		printf(".%u to ", ntohs(src_port));
+		writeIpAddr(dst_addr);
+		printf(".%u\n", ntohs(dst_port)));
+
+	no_ipopt_pack= bf_memreq(UDP_IO_HDR_SIZE);
+	udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(no_ipopt_pack);
+	udp_io_hdr->uih_src_addr= src_addr;
+	udp_io_hdr->uih_dst_addr= dst_addr;
+	udp_io_hdr->uih_src_port= src_port;
+	udp_io_hdr->uih_dst_port= dst_port;
+	data_size = udp_size-UDP_HDR_SIZE;
+#if CONF_UDP_IO_NW_BYTE_ORDER
+	udp_io_hdr->uih_ip_opt_len= HTONS(0);
+	udp_io_hdr->uih_data_len= htons(data_size);
+#else
+	udp_io_hdr->uih_ip_opt_len= 0;
+	udp_io_hdr->uih_data_len= data_size;
+#endif
+	no_ipopt_pack->acc_next= bf_cut(udp_acc, UDP_HDR_SIZE, data_size);
+
+	if (ip_hdr_size == IP_MIN_HDR_SIZE)
+	{
+		ipopt_pack= no_ipopt_pack;
+		ipopt_pack->acc_linkC++;
+	}
+	else
+	{
+		ipopt_pack= bf_memreq(UDP_IO_HDR_SIZE);
+		*(udp_io_hdr_t *)ptr2acc_data(ipopt_pack)= *udp_io_hdr;
+		udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(ipopt_pack);
+		opt_size = ip_hdr_size-IP_MIN_HDR_SIZE;
+#if CONF_UDP_IO_NW_BYTE_ORDER
+		udp_io_hdr->uih_ip_opt_len= htons(opt_size);
+#else
+		udp_io_hdr->uih_ip_opt_len= opt_size;
+#endif
+		tmp_acc= bf_cut(ip_hdr_acc, (size_t)IP_MIN_HDR_SIZE, opt_size);
+		assert(tmp_acc->acc_linkC == 1);
+		assert(tmp_acc->acc_next == NULL);
+		ipopt_pack->acc_next= tmp_acc;
+
+		tmp_acc->acc_next= no_ipopt_pack->acc_next;
+		if (tmp_acc->acc_next)
+			tmp_acc->acc_next->acc_linkC++;
+	}
+
+	hash= dst_port;
+	hash ^= (hash >> 8);
+	hash &= (UDP_PORT_HASH_NR-1);
+
+	for (i= 0; i<2; i++)
+	{
+		share_fd= NULL;
+
+		udp_fd= (i == 0) ? udp_port->up_port_any :
+			udp_port->up_port_hash[hash];
+		for (; udp_fd; udp_fd= udp_fd->uf_port_next)
+		{
+			if (i && udp_fd->uf_udpopt.nwuo_locport != dst_port)
+				continue;
+		
+			assert(udp_fd->uf_flags & UFF_INUSE);
+			assert(udp_fd->uf_flags & UFF_OPTSET);
+		
+			if (udp_fd->uf_port != udp_port)
+				continue;
+
+			flags= udp_fd->uf_udpopt.nwuo_flags;
+			if (!(flags & dst_type))
+				continue;
+
+			if ((flags & NWUO_RP_SET) && 
+				udp_fd->uf_udpopt.nwuo_remport != src_port)
+			{
+				continue;
+			}
+
+			if ((flags & NWUO_RA_SET) && 
+				udp_fd->uf_udpopt.nwuo_remaddr != src_addr)
+			{
+				continue;
+			}
+
+			if (i)
+			{
+				/* Packet is considdered to be delivered */
+				delivered= 1;
+			}
+
+			if ((flags & NWUO_ACC_MASK) == NWUO_SHARED &&
+				(!share_fd || !udp_fd->uf_rdbuf_head))
+			{
+				share_fd= udp_fd;
+				continue;
+			}
+
+			if (flags & NWUO_EN_IPOPT)
+				pack= ipopt_pack;
+			else
+				pack= no_ipopt_pack;
+
+			pack->acc_linkC++;
+			udp_rd_enqueue(udp_fd, pack, exp_tim);
+			if (udp_fd->uf_flags & UFF_READ_IP)
+				udp_packet2user(udp_fd);
+		}
+
+		if (share_fd)
+		{
+			flags= share_fd->uf_udpopt.nwuo_flags;
+			if (flags & NWUO_EN_IPOPT)
+				pack= ipopt_pack;
+			else
+				pack= no_ipopt_pack;
+
+			pack->acc_linkC++;
+			udp_rd_enqueue(share_fd, pack, exp_tim);
+			if (share_fd->uf_flags & UFF_READ_IP)
+				udp_packet2user(share_fd);
+		}
+	}
+
+	if (ipopt_pack)
+		bf_afree(ipopt_pack);
+	if (no_ipopt_pack)
+		bf_afree(no_ipopt_pack);
+
+	if (!delivered)
+	{
+		DBLOCK(0x2, printf("udp: could not deliver packet from ");
+			writeIpAddr(src_addr);
+			printf(".%u to ", ntohs(src_port));
+			writeIpAddr(dst_addr);
+			printf(".%u\n", ntohs(dst_port)));
+
+		pack= bf_append(ip_hdr_acc, udp_acc);
+		ip_hdr_acc= NULL;
+		udp_acc= NULL;
+		icmp_snd_unreachable(udp_port->up_ipdev, pack,
+			ICMP_PORT_UNRCH);
+		return;
+	}
+
+	assert (ip_hdr_acc);
+	bf_afree(ip_hdr_acc);
+	assert (udp_acc);
+	bf_afree(udp_acc);
+}
+
+PUBLIC void udp_close(fd)
+int fd;
+{
+	udp_fd_t *udp_fd;
+	acc_t *tmp_acc, *next_acc;
+
+	udp_fd= &udp_fd_table[fd];
+
+	assert (udp_fd->uf_flags & UFF_INUSE);
+
+	if (udp_fd->uf_flags & UFF_OPTSET)
+		unhash_fd(udp_fd);
+
+	udp_fd->uf_flags= UFF_EMPTY;
+	tmp_acc= udp_fd->uf_rdbuf_head;
+	while (tmp_acc)
+	{
+		next_acc= tmp_acc->acc_ext_link;
+		bf_afree(tmp_acc);
+		tmp_acc= next_acc;
+	}
+	udp_fd->uf_rdbuf_head= NULL;
+}
+
+PUBLIC int udp_write(fd, count)
+int fd;
+size_t count;
+{
+	udp_fd_t *udp_fd;
+	udp_port_t *udp_port;
+
+	udp_fd= &udp_fd_table[fd];
+	udp_port= udp_fd->uf_port;
+
+	if (!(udp_fd->uf_flags & UFF_OPTSET))
+	{
+		reply_thr_get (udp_fd, EBADMODE, FALSE);
+		return NW_OK;
+	}
+
+assert (!(udp_fd->uf_flags & UFF_WRITE_IP));
+
+	udp_fd->uf_wr_count= count;
+
+	udp_fd->uf_flags |= UFF_WRITE_IP;
+
+	restart_write_fd(udp_fd);
+
+	if (udp_fd->uf_flags & UFF_WRITE_IP)
+	{
+		DBLOCK(1, printf("replying NW_SUSPEND\n"));
+
+		return NW_SUSPEND;
+	}
+	else
+	{
+		return NW_OK;
+	}
+}
+
+PRIVATE void restart_write_fd(udp_fd)
+udp_fd_t *udp_fd;
+{
+	udp_port_t *udp_port;
+	acc_t *pack, *ip_hdr_pack, *udp_hdr_pack, *ip_opt_pack, *user_data;
+	udp_hdr_t *udp_hdr;
+	udp_io_hdr_t *udp_io_hdr;
+	ip_hdr_t *ip_hdr;
+	size_t ip_opt_size, user_data_size;
+	unsigned long flags;
+	u16_t chksum;
+	u8_t u16[2];
+	int result;
+
+	udp_port= udp_fd->uf_port;
+
+	if (udp_port->up_flags & UPF_WRITE_IP)
+	{
+		udp_port->up_flags |= UPF_MORE2WRITE;
+		return;
+	}
+
+assert (udp_fd->uf_flags & UFF_WRITE_IP);
+	udp_fd->uf_flags &= ~UFF_WRITE_IP;
+
+assert (!udp_port->up_wr_pack);
+
+	pack= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, 0,
+		udp_fd->uf_wr_count, FALSE);
+	if (!pack)
+	{
+		udp_fd->uf_flags &= ~UFF_WRITE_IP;
+		reply_thr_get (udp_fd, EFAULT, FALSE);
+		return;
+	}
+
+	flags= udp_fd->uf_udpopt.nwuo_flags;
+
+	ip_hdr_pack= bf_memreq(IP_MIN_HDR_SIZE);
+	ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_pack);
+
+	udp_hdr_pack= bf_memreq(UDP_HDR_SIZE);
+	udp_hdr= (udp_hdr_t *)ptr2acc_data(udp_hdr_pack);
+
+	if (flags & NWUO_RWDATALL)
+	{
+		pack= bf_packIffLess(pack, UDP_IO_HDR_SIZE);
+		udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(pack);
+#if CONF_UDP_IO_NW_BYTE_ORDER
+		ip_opt_size= ntohs(udp_io_hdr->uih_ip_opt_len);
+#else
+		ip_opt_size= udp_io_hdr->uih_ip_opt_len;
+#endif
+		if (UDP_IO_HDR_SIZE+ip_opt_size>udp_fd->uf_wr_count)
+		{
+			bf_afree(ip_hdr_pack);
+			bf_afree(udp_hdr_pack);
+			bf_afree(pack);
+			reply_thr_get (udp_fd, EINVAL, FALSE);
+			return;
+		}
+		if (ip_opt_size & 3)
+		{
+			bf_afree(ip_hdr_pack);
+			bf_afree(udp_hdr_pack);
+			bf_afree(pack);
+			reply_thr_get (udp_fd, EFAULT, FALSE);
+			return;
+		}
+		if (ip_opt_size)
+			ip_opt_pack= bf_cut(pack, UDP_IO_HDR_SIZE, ip_opt_size);
+		else
+			ip_opt_pack= 0;
+		user_data_size= udp_fd->uf_wr_count-UDP_IO_HDR_SIZE-
+			ip_opt_size;
+		user_data= bf_cut(pack, UDP_IO_HDR_SIZE+ip_opt_size, 
+			user_data_size);
+		bf_afree(pack);
+	}
+	else
+	{
+		udp_io_hdr= 0;
+		ip_opt_size= 0;
+		user_data_size= udp_fd->uf_wr_count;
+		ip_opt_pack= 0;
+		user_data= pack;
+	}
+
+	ip_hdr->ih_vers_ihl= (IP_MIN_HDR_SIZE+ip_opt_size) >> 2;
+	ip_hdr->ih_tos= UDP_TOS;
+	ip_hdr->ih_flags_fragoff= HTONS(UDP_IP_FLAGS);
+	ip_hdr->ih_ttl= IP_DEF_TTL;
+	ip_hdr->ih_proto= IPPROTO_UDP;
+	if (flags & NWUO_RA_SET)
+	{
+		ip_hdr->ih_dst= udp_fd->uf_udpopt.nwuo_remaddr;
+	}
+	else
+	{
+assert (udp_io_hdr);
+		ip_hdr->ih_dst= udp_io_hdr->uih_dst_addr;
+	}
+
+	if ((flags & NWUO_LOCPORT_MASK) != NWUO_LP_ANY)
+		udp_hdr->uh_src_port= udp_fd->uf_udpopt.nwuo_locport;
+	else
+	{
+assert (udp_io_hdr);
+		udp_hdr->uh_src_port= udp_io_hdr->uih_src_port;
+	}
+
+	if (flags & NWUO_RP_SET)
+		udp_hdr->uh_dst_port= udp_fd->uf_udpopt.nwuo_remport;
+	else
+	{
+assert (udp_io_hdr);
+		udp_hdr->uh_dst_port= udp_io_hdr->uih_dst_port;
+	}
+
+	udp_hdr->uh_length= htons(UDP_HDR_SIZE+user_data_size);
+	udp_hdr->uh_chksum= 0;
+
+	udp_hdr_pack->acc_next= user_data;
+	chksum= pack_oneCsum(udp_hdr_pack);
+	chksum= oneC_sum(chksum, (u16_t *)&udp_fd->uf_port->up_ipaddr,
+		sizeof(ipaddr_t));
+	chksum= oneC_sum(chksum, (u16_t *)&ip_hdr->ih_dst, sizeof(ipaddr_t));
+	u16[0]= 0;
+	u16[1]= IPPROTO_UDP;
+	chksum= oneC_sum(chksum, (u16_t *)u16, sizeof(u16));
+	chksum= oneC_sum(chksum, (u16_t *)&udp_hdr->uh_length, sizeof(u16_t));
+	if (~chksum)
+		chksum= ~chksum;
+	udp_hdr->uh_chksum= chksum;
+	
+	if (ip_opt_pack)
+	{
+		ip_opt_pack= bf_packIffLess(ip_opt_pack, ip_opt_size);
+		ip_opt_pack->acc_next= udp_hdr_pack;
+		udp_hdr_pack= ip_opt_pack;
+	}
+	ip_hdr_pack->acc_next= udp_hdr_pack;
+
+assert (!udp_port->up_wr_pack);
+assert (!(udp_port->up_flags & UPF_WRITE_IP));
+
+	udp_port->up_wr_pack= ip_hdr_pack;
+	udp_port->up_flags |= UPF_WRITE_IP;
+	result= ip_write(udp_port->up_ipfd, bf_bufsize(ip_hdr_pack));
+	if (result == NW_SUSPEND)
+	{
+		udp_port->up_flags |= UPF_WRITE_SP;
+		udp_fd->uf_flags |= UFF_WRITE_IP;
+		udp_port->up_write_fd= udp_fd;
+	}
+	else if (result<0)
+		reply_thr_get(udp_fd, result, FALSE);
+	else
+		reply_thr_get (udp_fd, udp_fd->uf_wr_count, FALSE);
+}
+
+PRIVATE u16_t pack_oneCsum(pack)
+acc_t *pack;
+{
+	u16_t prev;
+	int odd_byte;
+	char *data_ptr;
+	int length;
+	char byte_buf[2];
+
+	assert (pack);
+
+	prev= 0;
+
+	odd_byte= FALSE;
+	for (; pack; pack= pack->acc_next)
+	{
+		
+		data_ptr= ptr2acc_data(pack);
+		length= pack->acc_length;
+
+		if (!length)
+			continue;
+		if (odd_byte)
+		{
+			byte_buf[1]= *data_ptr;
+			prev= oneC_sum(prev, (u16_t *)byte_buf, 2);
+			data_ptr++;
+			length--;
+			odd_byte= FALSE;
+		}
+		if (length & 1)
+		{
+			odd_byte= TRUE;
+			length--;
+			byte_buf[0]= data_ptr[length];
+		}
+		if (!length)
+			continue;
+		prev= oneC_sum (prev, (u16_t *)data_ptr, length);
+	}
+	if (odd_byte)
+	{
+		byte_buf[1]= 0;
+		prev= oneC_sum (prev, (u16_t *)byte_buf, 1);
+	}
+	return prev;
+}
+
+PRIVATE void udp_restart_write_port(udp_port )
+udp_port_t *udp_port;
+{
+	udp_fd_t *udp_fd;
+	int i;
+
+assert (!udp_port->up_wr_pack);
+assert (!(udp_port->up_flags & (UPF_WRITE_IP|UPF_WRITE_SP)));
+
+	while (udp_port->up_flags & UPF_MORE2WRITE)
+	{
+		udp_port->up_flags &= ~UPF_MORE2WRITE;
+
+		for (i= 0, udp_fd= udp_port->up_next_fd; i<UDP_FD_NR;
+			i++, udp_fd++)
+		{
+			if (udp_fd == &udp_fd_table[UDP_FD_NR])
+				udp_fd= udp_fd_table;
+
+			if (!(udp_fd->uf_flags & UFF_INUSE))
+				continue;
+			if (!(udp_fd->uf_flags & UFF_WRITE_IP))
+				continue;
+			if (udp_fd->uf_port != udp_port)
+				continue;
+			restart_write_fd(udp_fd);
+			if (udp_port->up_flags & UPF_WRITE_IP)
+			{
+				udp_port->up_next_fd= udp_fd+1;
+				udp_port->up_flags |= UPF_MORE2WRITE;
+				return;
+			}
+		}
+	}
+}
+
+PUBLIC int udp_cancel(fd, which_operation)
+int fd;
+int which_operation;
+{
+	udp_fd_t *udp_fd;
+
+	DBLOCK(0x10, printf("udp_cancel(%d, %d)\n", fd, which_operation));
+
+	udp_fd= &udp_fd_table[fd];
+
+	switch (which_operation)
+	{
+	case SR_CANCEL_READ:
+assert (udp_fd->uf_flags & UFF_READ_IP);
+		udp_fd->uf_flags &= ~UFF_READ_IP;
+		reply_thr_put(udp_fd, EINTR, FALSE);
+		break;
+	case SR_CANCEL_WRITE:
+assert (udp_fd->uf_flags & UFF_WRITE_IP);
+		udp_fd->uf_flags &= ~UFF_WRITE_IP;
+		if (udp_fd->uf_port->up_write_fd == udp_fd)
+			udp_fd->uf_port->up_write_fd= NULL;
+		reply_thr_get(udp_fd, EINTR, FALSE);
+		break;
+	case SR_CANCEL_IOCTL:
+assert (udp_fd->uf_flags & UFF_IOCTL_IP);
+		udp_fd->uf_flags &= ~UFF_IOCTL_IP;
+		udp_fd->uf_flags &= ~UFF_PEEK_IP;
+		reply_thr_get(udp_fd, EINTR, TRUE);
+		break;
+	default:
+		ip_panic(( "got unknown cancel request" ));
+	}
+	return NW_OK;
+}
+
+PRIVATE void udp_buffree (priority)
+int priority;
+{
+	int i;
+	udp_fd_t *udp_fd;
+	acc_t *tmp_acc;
+
+	if (priority ==  UDP_PRI_FDBUFS_EXTRA)
+	{
+		for (i=0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
+		{
+			while (udp_fd->uf_rdbuf_head &&
+				udp_fd->uf_rdbuf_head->acc_ext_link)
+			{
+				tmp_acc= udp_fd->uf_rdbuf_head;
+				udp_fd->uf_rdbuf_head= tmp_acc->acc_ext_link;
+				bf_afree(tmp_acc);
+			}
+		}
+	}
+
+	if (priority  == UDP_PRI_FDBUFS)
+	{
+		for (i=0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
+		{
+			while (udp_fd->uf_rdbuf_head)
+			{
+				tmp_acc= udp_fd->uf_rdbuf_head;
+				udp_fd->uf_rdbuf_head= tmp_acc->acc_ext_link;
+				bf_afree(tmp_acc);
+			}
+		}
+	}
+}
+
+PRIVATE void udp_rd_enqueue(udp_fd, pack, exp_tim)
+udp_fd_t *udp_fd;
+acc_t *pack;
+clock_t exp_tim;
+{
+	acc_t *tmp_acc;
+	int result;
+
+	if (pack->acc_linkC != 1)
+	{
+		tmp_acc= bf_dupacc(pack);
+		bf_afree(pack);
+		pack= tmp_acc;
+	}
+	pack->acc_ext_link= NULL;
+	if (udp_fd->uf_rdbuf_head == NULL)
+	{
+		udp_fd->uf_exp_tim= exp_tim;
+		udp_fd->uf_rdbuf_head= pack;
+	}
+	else
+		udp_fd->uf_rdbuf_tail->acc_ext_link= pack;
+	udp_fd->uf_rdbuf_tail= pack;
+
+	if (udp_fd->uf_flags & UFF_PEEK_IP)
+	{
+		pack= bf_cut(udp_fd->uf_rdbuf_head, 0,
+			sizeof(udp_io_hdr_t));
+		result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
+			(size_t)0, pack, TRUE);
+
+		udp_fd->uf_flags &= ~UFF_IOCTL_IP;
+		udp_fd->uf_flags &= ~UFF_PEEK_IP;
+		result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
+			result, (acc_t *)0, TRUE);
+		assert (result == 0);
+	}
+
+	if (udp_fd->uf_flags & UFF_SEL_READ)
+	{
+		udp_fd->uf_flags &= ~UFF_SEL_READ;
+		if (udp_fd->uf_select_res)
+			udp_fd->uf_select_res(udp_fd->uf_srfd, SR_SELECT_READ);
+		else
+			printf("udp_rd_enqueue: no select_res\n");
+	}
+}
+
+PRIVATE void hash_fd(udp_fd)
+udp_fd_t *udp_fd;
+{
+	udp_port_t *udp_port;
+	int hash;
+
+	udp_port= udp_fd->uf_port;
+	if ((udp_fd->uf_udpopt.nwuo_flags & NWUO_LOCPORT_MASK) ==
+		NWUO_LP_ANY)
+	{
+		udp_fd->uf_port_next= udp_port->up_port_any;
+		udp_port->up_port_any= udp_fd;
+	}
+	else
+	{
+		hash= udp_fd->uf_udpopt.nwuo_locport;
+		hash ^= (hash >> 8);
+		hash &= (UDP_PORT_HASH_NR-1);
+
+		udp_fd->uf_port_next= udp_port->up_port_hash[hash];
+		udp_port->up_port_hash[hash]= udp_fd;
+	}
+}
+
+PRIVATE void unhash_fd(udp_fd)
+udp_fd_t *udp_fd;
+{
+	udp_port_t *udp_port;
+	udp_fd_t *prev, *curr, **udp_fd_p;
+	int hash;
+
+	udp_port= udp_fd->uf_port;
+	if ((udp_fd->uf_udpopt.nwuo_flags & NWUO_LOCPORT_MASK) ==
+		NWUO_LP_ANY)
+	{
+		udp_fd_p= &udp_port->up_port_any;
+	}
+	else
+	{
+		hash= udp_fd->uf_udpopt.nwuo_locport;
+		hash ^= (hash >> 8);
+		hash &= (UDP_PORT_HASH_NR-1);
+
+		udp_fd_p= &udp_port->up_port_hash[hash];
+	}
+	for (prev= NULL, curr= *udp_fd_p; curr;
+		prev= curr, curr= curr->uf_port_next)
+	{
+		if (curr == udp_fd)
+			break;
+	}
+	assert(curr);
+	if (prev)
+		prev->uf_port_next= curr->uf_port_next;
+	else
+		*udp_fd_p= curr->uf_port_next;
+}
+
+#ifdef BUF_CONSISTENCY_CHECK
+PRIVATE void udp_bufcheck()
+{
+	int i;
+	udp_port_t *udp_port;
+	udp_fd_t *udp_fd;
+	acc_t *tmp_acc;
+
+	for (i= 0, udp_port= udp_port_table; i<udp_conf_nr; i++, udp_port++)
+	{
+		if (udp_port->up_wr_pack)
+			bf_check_acc(udp_port->up_wr_pack);
+	}
+
+	for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
+	{
+		for (tmp_acc= udp_fd->uf_rdbuf_head; tmp_acc; 
+			tmp_acc= tmp_acc->acc_ext_link)
+		{
+			bf_check_acc(tmp_acc);
+		}
+	}
+}
+#endif
+
+/*
+ * $PchId: udp.c,v 1.25 2005/06/28 14:14:44 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/udp.h
===================================================================
--- /trunk/minix/servers/inet/generic/udp.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/udp.h	(revision 9)
@@ -0,0 +1,36 @@
+/*
+udp.h
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef UDP_H
+#define UDP_H
+
+#define UDP_DEF_OPT		NWUO_NOFLAGS
+#define UDP_MAX_DATAGRAM	40000 /* 8192 */
+#define UDP_READ_EXP_TIME	(10L * HZ)
+#define UDP_TOS			0
+#define UDP_IP_FLAGS		0
+
+#define UDP0	0
+
+struct acc;
+
+void udp_prep ARGS(( void ));
+void udp_init ARGS(( void ));
+int udp_open ARGS(( int port, int srfd,
+	get_userdata_t get_userdata, put_userdata_t put_userdata, 
+	put_pkt_t put_pkt, select_res_t select_res ));
+int udp_ioctl ARGS(( int fd, ioreq_t req ));
+int udp_read ARGS(( int fd, size_t count ));
+int udp_write ARGS(( int fd, size_t count ));
+void udp_close ARGS(( int fd ));
+int udp_cancel ARGS(( int fd, int which_operation ));
+
+#endif /* UDP_H */
+
+
+/*
+ * $PchId: udp.h,v 1.9 2005/06/28 14:12:05 philip Exp $
+ */
Index: /trunk/minix/servers/inet/generic/udp_int.h
===================================================================
--- /trunk/minix/servers/inet/generic/udp_int.h	(revision 9)
+++ /trunk/minix/servers/inet/generic/udp_int.h	(revision 9)
@@ -0,0 +1,73 @@
+/*
+generic/udp_int.h
+
+Created:	March 2001 by Philip Homburg <philip@f-mnx.phicoh.com>
+
+Some internals of the UDP module
+*/
+
+#define UDP_FD_NR		(4*IP_PORT_MAX)
+#define UDP_PORT_HASH_NR	16		/* Must be a power of 2 */
+
+typedef struct udp_port
+{
+	int up_flags;
+	int up_state;
+	int up_ipfd;
+	int up_ipdev;
+	acc_t *up_wr_pack;
+	ipaddr_t up_ipaddr;
+	struct udp_fd *up_next_fd;
+	struct udp_fd *up_write_fd;
+	struct udp_fd *up_port_any;
+	struct udp_fd *up_port_hash[UDP_PORT_HASH_NR];
+} udp_port_t;
+
+#define UPF_EMPTY	0x0
+#define UPF_WRITE_IP	0x1
+#define UPF_WRITE_SP	0x2
+#define UPF_READ_IP	0x4
+#define UPF_READ_SP	0x8
+#define UPF_SUSPEND	0x10
+#define UPF_MORE2WRITE	0x20
+
+#define UPS_EMPTY	0
+#define UPS_SETPROTO	1
+#define UPS_GETCONF	2
+#define UPS_MAIN	3
+#define UPS_ERROR	4
+
+typedef struct udp_fd
+{
+	int uf_flags;
+	udp_port_t *uf_port;
+	ioreq_t uf_ioreq;
+	int uf_srfd;
+	nwio_udpopt_t uf_udpopt;
+	get_userdata_t uf_get_userdata;
+	put_userdata_t uf_put_userdata;
+	select_res_t uf_select_res;
+	acc_t *uf_rdbuf_head;
+	acc_t *uf_rdbuf_tail;
+	size_t uf_rd_count;
+	size_t uf_wr_count;
+	clock_t uf_exp_tim;
+	struct udp_fd *uf_port_next;
+} udp_fd_t;
+
+#define UFF_EMPTY	0x0
+#define UFF_INUSE	0x1
+#define UFF_IOCTL_IP	0x2
+#define UFF_READ_IP	0x4
+#define UFF_WRITE_IP	0x8
+#define UFF_OPTSET	0x10
+#define UFF_PEEK_IP	0x20
+#define UFF_SEL_READ	0x40
+#define UFF_SEL_WRITE	0x80
+
+EXTERN udp_port_t *udp_port_table;
+EXTERN udp_fd_t udp_fd_table[UDP_FD_NR];
+
+/*
+ * $PchId: udp_int.h,v 1.4 2004/08/03 11:12:01 philip Exp $
+ */
Index: /trunk/minix/servers/inet/inet.c
===================================================================
--- /trunk/minix/servers/inet/inet.c	(revision 9)
+++ /trunk/minix/servers/inet/inet.c	(revision 9)
@@ -0,0 +1,343 @@
+/*	this file contains the interface of the network software with rest of
+	minix. Furthermore it contains the main loop of the network task.
+
+Copyright 1995 Philip Homburg
+
+The valid messages and their parameters are:
+
+from FS:
+ __________________________________________________________________
+|		|           |         |       |          |         |
+| m_type	|   DEVICE  | PROC_NR |	COUNT |	POSITION | ADDRESS |
+|_______________|___________|_________|_______|__________|_________|
+|		|           |         |       |          |         |
+| NW_OPEN 	| minor dev | proc nr | mode  |          |         |
+|_______________|___________|_________|_______|__________|_________|
+|		|           |         |       |          |         |
+| NW_CLOSE 	| minor dev | proc nr |       |          |         |
+|_______________|___________|_________|_______|__________|_________|
+|		|           |         |       |          |         |
+| NW_IOCTL	| minor dev | proc nr |       |	NWIO..	 | address |
+|_______________|___________|_________|_______|__________|_________|
+|		|           |         |       |          |         |
+| NW_READ	| minor dev | proc nr |	count |          | address |
+|_______________|___________|_________|_______|__________|_________|
+|		|           |         |       |          |         |
+| NW_WRITE	| minor dev | proc nr |	count |          | address |
+|_______________|___________|_________|_______|__________|_________|
+|		|           |         |       |          |         |
+| NW_CANCEL	| minor dev | proc nr |       |          |         |
+|_______________|___________|_________|_______|__________|_________|
+
+from DL_ETH:
+ _______________________________________________________________________
+|		|           |         |          |            |         |
+| m_type	|  DL_PORT  | DL_PROC |	DL_COUNT |  DL_STAT   | DL_TIME |
+|_______________|___________|_________|__________|____________|_________|
+|		|           |         |          |            |         |
+| DL_INIT_REPLY	| minor dev | proc nr | rd_count |  0  | stat |  time   |
+|_______________|___________|_________|__________|____________|_________|
+|		|           |         |          |            |         |
+| DL_TASK_REPLY	| minor dev | proc nr | rd_count | err | stat |  time   |
+|_______________|___________|_________|__________|____________|_________|
+*/
+
+#include "inet.h"
+
+#define _MINIX_SOURCE 1
+
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/svrctl.h>
+
+#include "mq.h"
+#include "qp.h"
+#include "proto.h"
+#include "generic/type.h"
+
+#include "generic/arp.h"
+#include "generic/assert.h"
+#include "generic/buf.h"
+#include "generic/clock.h"
+#include "generic/eth.h"
+#include "generic/event.h"
+#include "generic/ip.h"
+#include "generic/psip.h"
+#include "generic/rand256.h"
+#include "generic/sr.h"
+#include "generic/tcp.h"
+#include "generic/udp.h"
+
+THIS_FILE
+
+#define RANDOM_DEV_NAME	"/dev/random"
+
+int this_proc;		/* Process number of this server. */
+
+#ifdef __minix_vmd
+static int synal_tasknr= ANY;
+#endif
+
+/* Killing Solaris */
+int killer_inet= 0;
+
+#ifdef BUF_CONSISTENCY_CHECK
+extern int inet_buf_debug;
+#endif
+
+_PROTOTYPE( void main, (void) );
+
+FORWARD _PROTOTYPE( void nw_conf, (void) );
+FORWARD _PROTOTYPE( void nw_init, (void) );
+
+PUBLIC void main()
+{
+	mq_t *mq;
+	int r;
+	int source, timerand, fd;
+	struct fssignon device;
+#ifdef __minix_vmd
+	struct systaskinfo info;
+#endif
+	u8_t randbits[32];
+	struct timeval tv;
+
+#if DEBUG
+	printf("Starting inet...\n");
+	printf("%s\n", version);
+#endif
+
+	/* Read configuration. */
+	nw_conf();
+
+	/* Get a random number */
+	timerand= 1;
+	fd= open(RANDOM_DEV_NAME, O_RDONLY | O_NONBLOCK);
+	if (fd != -1)
+	{
+		r= read(fd, randbits, sizeof(randbits));
+		if (r == sizeof(randbits))
+			timerand= 0;
+		else
+		{
+			printf("unable to read random data from %s: %s\n",
+				RANDOM_DEV_NAME, r == -1 ? strerror(errno) :
+				r == 0 ? "EOF" : "not enough data");
+		}
+		close(fd);
+	}
+	else
+	{
+		printf("unable to open random device %s: %s\n",
+			RANDOM_DEV_NAME, strerror(errno));
+	}
+	if (timerand)
+	{
+		printf("using current time for random-number seed\n");
+#ifdef __minix_vmd
+		r= sysutime(UTIME_TIMEOFDAY, &tv);
+#else /* Minix 3 */
+		r= gettimeofday(&tv, NULL);
+#endif
+		if (r == -1)
+		{
+			printf("sysutime failed: %s\n", strerror(errno));
+			exit(1);
+		}
+		memcpy(randbits, &tv, sizeof(tv));
+	}
+	init_rand256(randbits);
+
+#ifdef __minix_vmd
+	if (svrctl(SYSSIGNON, (void *) &info) == -1) pause();
+
+	/* Our new identity as a server. */
+	this_proc = info.proc_nr;
+#else /* Minix 3 */
+
+	/* Our new identity as a server. */
+	if ((this_proc = getprocnr()) < 0)
+		ip_panic(( "unable to get own process nr\n"));
+#endif
+
+	/* Register the device group. */
+	device.dev= ip_dev;
+	device.style= STYLE_CLONE;
+	if (svrctl(FSSIGNON, (void *) &device) == -1) {
+		printf("inet: error %d on registering ethernet devices\n",
+			errno);
+		pause();
+	}
+
+#ifdef BUF_CONSISTENCY_CHECK
+	inet_buf_debug= (getenv("inetbufdebug") && 
+		(strcmp(getenv("inetbufdebug"), "on") == 0));
+	inet_buf_debug= 100;
+	if (inet_buf_debug)
+	{
+		ip_warning(( "buffer consistency check enabled" ));
+	}
+#endif
+
+	if (getenv("killerinet"))
+	{
+		ip_warning(( "killer inet active" ));
+		killer_inet= 1;
+	}
+
+#ifdef __minix_vmd
+	r= sys_findproc(SYN_AL_NAME, &synal_tasknr, 0);
+	if (r != OK)
+		ip_panic(( "unable to find synchronous alarm task: %d\n", r ));
+#endif
+
+	nw_init();
+	while (TRUE)
+	{
+#ifdef BUF_CONSISTENCY_CHECK
+		if (inet_buf_debug)
+		{
+			static int buf_debug_count= 0;
+
+			if (++buf_debug_count >= inet_buf_debug)
+			{
+				buf_debug_count= 0;
+				if (!bf_consistency_check())
+					break;
+			}
+		}
+#endif
+		if (ev_head)
+		{
+			ev_process();
+			continue;
+		}
+		if (clck_call_expire)
+		{
+			clck_expire_timers();
+			continue;
+		}
+		mq= mq_get();
+		if (!mq)
+			ip_panic(("out of messages"));
+
+		r= receive (ANY, &mq->mq_mess);
+		if (r<0)
+		{
+			ip_panic(("unable to receive: %d", r));
+		}
+		reset_time();
+		source= mq->mq_mess.m_source;
+		if (source == FS_PROC_NR)
+		{
+			sr_rec(mq);
+		}
+#ifdef __minix_vmd
+		else if (source == synal_tasknr)
+		{
+			clck_tick (&mq->mq_mess);
+			mq_free(mq);
+		}
+#else /* Minix 3 */
+		else if (mq->mq_mess.m_type == SYN_ALARM)
+		{
+			clck_tick(&mq->mq_mess);
+			mq_free(mq);
+		} 
+		else if (mq->mq_mess.m_type == PROC_EVENT)
+		{
+			/* signaled */ 
+			/* probably SIGTERM */
+			mq_free(mq);
+		} 
+		else if (mq->mq_mess.m_type & NOTIFY_MESSAGE)
+		{
+			/* A driver is (re)started. */
+			eth_check_drivers(&mq->mq_mess);
+			mq_free(mq);
+		}
+#endif
+		else
+		{
+compare(mq->mq_mess.m_type, ==, DL_TASK_REPLY);
+			eth_rec(&mq->mq_mess);
+			mq_free(mq);
+		}
+	}
+	ip_panic(("task is not allowed to terminate"));
+}
+
+PRIVATE void nw_conf()
+{
+	read_conf();
+	eth_prep();
+	arp_prep();
+	psip_prep();
+	ip_prep();
+	tcp_prep();
+	udp_prep();
+}
+
+PRIVATE void nw_init()
+{
+	mq_init();
+	qp_init();
+	bf_init();
+	clck_init();
+	sr_init();
+	eth_init();
+	arp_init();
+	psip_init();
+	ip_init();
+	tcp_init();
+	udp_init();
+}
+
+PUBLIC void panic0(file, line)
+char *file;
+int line;
+{
+	printf("panic at %s, %d: ", file, line);
+}
+
+PUBLIC void inet_panic()
+{
+	printf("\ninet stacktrace: ");
+	stacktrace();
+#ifdef __minix_vmd
+	sys_abort(RBT_PANIC);
+#else /* Minix 3 */
+	(panic)("INET","aborted due to a panic",NO_NUM);
+#endif
+	for(;;);
+}
+
+#if !NDEBUG
+PUBLIC void bad_assertion(file, line, what)
+char *file;
+int line;
+char *what;
+{
+	panic0(file, line);
+	printf("assertion \"%s\" failed", what);
+	panic();
+}
+
+
+PUBLIC void bad_compare(file, line, lhs, what, rhs)
+char *file;
+int line;
+int lhs;
+char *what;
+int rhs;
+{
+	panic0(file, line);
+	printf("compare (%d) %s (%d) failed", lhs, what, rhs);
+	panic();
+}
+#endif /* !NDEBUG */
+
+/*
+ * $PchId: inet.c,v 1.23 2005/06/28 14:27:22 philip Exp $
+ */
Index: /trunk/minix/servers/inet/inet.h
===================================================================
--- /trunk/minix/servers/inet/inet.h	(revision 9)
+++ /trunk/minix/servers/inet/inet.h	(revision 9)
@@ -0,0 +1,118 @@
+/*
+inet/inet.h
+
+Created:	Dec 30, 1991 by Philip Homburg
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef INET__INET_H
+#define INET__INET_H
+
+#define _SYSTEM	1	/* get OK and negative error codes */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __minix_vmd
+
+#include <minix/ansi.h>
+#include <minix/cfg_public.h>
+#include <minix/type.h>
+
+#else /* Assume at least Minix 3.x */
+
+#include <unistd.h>
+#include <sys/ioc_file.h>
+#include <sys/time.h>
+#include <minix/config.h>
+#include <minix/type.h>
+
+#define _NORETURN	/* Should be non empty for GCC */
+
+typedef int ioreq_t;
+
+#endif
+
+#include <minix/const.h>
+#include <minix/com.h>
+#include <minix/syslib.h>
+#include <minix/sysutil.h>
+#include <net/hton.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_hdr.h>
+#include <net/gen/eth_io.h>
+#include <net/gen/in.h>
+#include <net/gen/ip_hdr.h>
+#include <net/gen/ip_io.h>
+#include <net/gen/icmp.h>
+#include <net/gen/icmp_hdr.h>
+#include <net/gen/oneCsum.h>
+#include <net/gen/psip_hdr.h>
+#include <net/gen/psip_io.h>
+#include <net/gen/route.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_hdr.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/udp_io.h>
+
+#include <net/gen/arp_io.h>
+#include <net/ioctl.h>
+
+#include "const.h"
+#include "inet_config.h"
+
+#define PUBLIC
+#define EXTERN	extern
+#define PRIVATE	static
+#define FORWARD	static
+
+#define THIS_FILE static char *this_file= __FILE__;
+
+_PROTOTYPE( void panic0, (char *file, int line) );
+_PROTOTYPE( void inet_panic, (void) ) _NORETURN; 
+
+#define ip_panic(print_list)  \
+	(panic0(this_file, __LINE__), printf print_list, panic())
+#define panic() inet_panic()
+
+#if DEBUG
+#define ip_warning(print_list)  \
+	( \
+		printf("warning at %s, %d: ", this_file, __LINE__), \
+		printf print_list, \
+		printf("\ninet stacktrace: "), \
+		stacktrace() \
+	)
+#else
+#define ip_warning(print_list)	((void) 0)
+#endif
+
+#define DBLOCK(level, code) \
+	do { if ((level) & DEBUG) { where(); code; } } while(0)
+#define DIFBLOCK(level, condition, code) \
+	do { if (((level) & DEBUG) && (condition)) \
+		{ where(); code; } } while(0)
+
+#if _ANSI
+#define ARGS(x) x
+#else /* _ANSI */
+#define ARGS(x) ()
+#endif /* _ANSI */
+
+extern int this_proc;
+extern char version[];
+
+void stacktrace ARGS(( void ));
+
+#endif /* INET__INET_H */
+
+/*
+ * $PchId: inet.h,v 1.16 2005/06/28 14:27:54 philip Exp $
+ */
Index: /trunk/minix/servers/inet/inet_config.c
===================================================================
--- /trunk/minix/servers/inet/inet_config.c	(revision 9)
+++ /trunk/minix/servers/inet/inet_config.c	(revision 9)
@@ -0,0 +1,367 @@
+/*
+inet/inet_config.c
+
+Created:	Nov 11, 1992 by Philip Homburg
+
+Modified:	Apr 07, 2001 by Kees J. Bot
+		Read the configuration file and fill in the xx_conf[] arrays.
+
+Copyright 1995 Philip Homburg
+*/
+
+#define _MINIX_SOURCE 1
+#define _POSIX_SOURCE 1
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <minix/type.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+#include "inet_config.h"
+
+struct eth_conf eth_conf[IP_PORT_MAX];
+struct psip_conf psip_conf[IP_PORT_MAX];
+struct ip_conf ip_conf[IP_PORT_MAX];
+struct tcp_conf tcp_conf[IP_PORT_MAX];
+struct udp_conf udp_conf[IP_PORT_MAX];
+dev_t ip_dev;
+
+int eth_conf_nr;
+int psip_conf_nr;
+int ip_conf_nr;
+int tcp_conf_nr;
+int udp_conf_nr;
+
+int ip_forward_directed_bcast= 0;	/* Default is off */
+
+static u8_t iftype[IP_PORT_MAX];	/* Interface in use as? */
+static int ifdefault= -1;		/* Default network interface. */
+
+static void fatal(char *label)
+{
+	printf("init: %s: %s\n", label, strerror(errno));
+	exit(1);
+}
+
+static void check_rm(char *device)
+/* Check if a device is not among the living. */
+{
+	if (unlink(device) < 0) {
+		if (errno == ENOENT) return;
+		fatal(device);
+	}
+	printf("rm %s\n", device);
+}
+
+static void check_mknod(char *device, mode_t mode, int minor)
+/* Check if a device exists with the proper device number. */
+{
+	struct stat st;
+	dev_t dev;
+
+	dev= (ip_dev & 0xFF00) | minor;
+
+	if (stat(device, &st) < 0) {
+		if (errno != ENOENT) fatal(device);
+	} else {
+		if (S_ISCHR(st.st_mode) && st.st_rdev == dev) return;
+		if (unlink(device) < 0) fatal(device);
+	}
+
+	if (mknod(device, S_IFCHR | mode, dev) < 0) fatal(device);
+	printf("mknod %s c %d %d\n", device, (ip_dev >> 8), minor);
+}
+
+static void check_ln(char *old, char *new)
+/* Check if 'old' and 'new' are still properly linked. */
+{
+	struct stat st_old, st_new;
+
+	if (stat(old, &st_old) < 0) fatal(old);
+	if (stat(new, &st_new) < 0) {
+		if (errno != ENOENT) fatal(new);
+	} else {
+		if (st_new.st_dev == st_old.st_dev
+					&& st_new.st_ino == st_old.st_ino) {
+			return;
+		}
+		if (unlink(new) < 0) fatal(new);
+	}
+
+	if (link(old, new) < 0) fatal(new);
+	printf("ln %s %s\n", old, new);
+}
+
+static void check_dev(int type, int ifno)
+/* Check if the device group with interface number 'ifno' exists and has the
+ * proper device numbers.  If 'type' is -1 then the device group must be
+ * removed.
+ */
+{
+	static struct devlist {
+		char	*defname;
+		mode_t	mode;
+		u8_t	minor_off;
+	} devlist[] = {
+		{	"/dev/eth",	0600,	ETH_DEV_OFF	},
+		{	"/dev/psip",	0600,	PSIP_DEV_OFF	},
+		{	"/dev/ip",	0600,	IP_DEV_OFF	},
+		{	"/dev/tcp",	0666,	TCP_DEV_OFF	},
+		{	"/dev/udp",	0666,	UDP_DEV_OFF	},
+	};
+	struct devlist *dvp;
+	int i;
+	char device[sizeof("/dev/psip99")];
+	char *dp;
+
+	for (i= 0; i < sizeof(devlist) / sizeof(devlist[0]); i++) {
+		dvp= &devlist[i];
+		strcpy(device, dvp->defname);
+		dp= device + strlen(device);
+		if (ifno >= 10) *dp++ = '0' + (ifno / 10);
+		*dp++ = '0' + (ifno % 10);
+		*dp = 0;
+
+		if (type == 0
+			|| (i == 0 && type != NETTYPE_ETH)
+			|| (i == 1 && type != NETTYPE_PSIP)
+		) {
+			check_rm(device);
+			if (ifno == ifdefault) check_rm(dvp->defname);
+		} else {
+			check_mknod(device, dvp->mode,
+				if2minor(ifno, dvp->minor_off));
+			if (ifno == ifdefault) check_ln(device, dvp->defname);
+		}
+	}
+}
+
+static int cfg_fd;
+static char word[16];
+static unsigned line;
+
+static void error(void)
+{
+	printf("inet: error on line %u\n", line);
+	exit(1);
+}
+
+static void token(int need)
+{
+	/* Read a word from the configuration file.  Return a null string on
+	 * EOF.  Return a punctiation as a one character word.  If 'need' is
+	 * true then an actual word is expected at this point, so err out if
+	 * not.
+	 */
+	unsigned char *wp;
+	static unsigned char c= '\n';
+
+	wp= (unsigned char *) word;
+	*wp = 0;
+
+	while (c <= ' ') {
+		if (c == '\n') line++;
+		if (read(cfg_fd, &c, 1) != 1) {
+			if (need) error();
+			return;
+		}
+	}
+
+	do {
+		if (wp < (unsigned char *) word + sizeof(word)-1) *wp++ = c;
+		if (read(cfg_fd, &c, 1) != 1) c= ' ';
+		if (word[0] == ';' || word[0] == '{' || word[0] == '}') {
+			if (need) error();
+			break;
+		}
+	} while (c > ' ' && c != ';' && c != '{' && c != '}');
+	*wp = 0;
+}
+
+static unsigned number(char *str, unsigned max)
+{
+	/* Interpret a string as an unsigned decimal number, no bigger than
+	 * 'max'.  Return this number.
+	 */
+	char *s;
+	unsigned n, d;
+
+	s= str;
+	n= 0;
+	while ((d= (*s - '0')) < 10 && n <= max) {
+		n= n * 10 + d;
+		s++;
+	}
+	if (*s != 0 || n > max) {
+		printf("inet: '%s' is not a number <= %u\n", str, max);
+		error();
+	}
+	return n;
+}
+
+void read_conf(void)
+{
+	int i, j, ifno, type, port, enable;
+	struct eth_conf *ecp;
+	struct psip_conf *pcp;
+	struct ip_conf *icp;
+	struct stat st;
+
+	/* Open the configuration file. */
+	if ((cfg_fd= open(PATH_INET_CONF, O_RDONLY)) == -1)
+		fatal(PATH_INET_CONF);
+
+	ecp= eth_conf;
+	pcp= psip_conf;
+	icp= ip_conf;
+
+	while (token(0), word[0] != 0) {
+		if (strncmp(word, "eth", 3) == 0) {
+			ecp->ec_ifno= ifno= number(word+3, IP_PORT_MAX-1);
+			type= NETTYPE_ETH;
+			port= eth_conf_nr;
+			token(1);
+			if (strcmp(word, "vlan") == 0) {
+				token(1);
+				ecp->ec_vlan= number(word, (1<<12)-1);
+				token(1);
+				if (strncmp(word, "eth", 3) != 0) {
+					printf(
+				"inet: VLAN eth%d can't be built on %s\n",
+						ifno, word);
+					exit(1);
+				}
+				ecp->ec_port= number(word+3, IP_PORT_MAX-1);
+			} else {
+				ecp->ec_task= alloc(strlen(word)+1);
+				strcpy(ecp->ec_task, word);
+				token(1);
+				ecp->ec_port= number(word, IP_PORT_MAX-1);
+			}
+			ecp++;
+			eth_conf_nr++;
+		} else
+		if (strncmp(word, "psip", 4) == 0) {
+			pcp->pc_ifno= ifno= number(word+4, IP_PORT_MAX-1);
+			type= NETTYPE_PSIP;
+			port= psip_conf_nr;
+			pcp++;
+			psip_conf_nr++;
+		} else {
+			printf("inet: Unknown device '%s'\n", word);
+			error();
+		}
+		iftype[ifno]= type;
+		icp->ic_ifno= ifno;
+		icp->ic_devtype= type;
+		icp->ic_port= port;
+		tcp_conf[tcp_conf_nr].tc_port= ip_conf_nr;
+		udp_conf[udp_conf_nr].uc_port= ip_conf_nr;
+
+		enable= 7;	/* 1 = IP, 2 = TCP, 4 = UDP */
+
+		token(0);
+		if (word[0] == '{') {
+			token(0);
+			while (word[0] != '}') {
+				if (strcmp(word, "default") == 0) {
+					if (ifdefault != -1) {
+						printf(
+				"inet: ip%d and ip%d can't both be default\n",
+							ifdefault, ifno);
+						error();
+					}
+					ifdefault= ifno;
+					token(0);
+				} else
+				if (strcmp(word, "no") == 0) {
+					token(1);
+					if (strcmp(word, "ip") == 0) {
+						enable= 0;
+					} else
+					if (strcmp(word, "tcp") == 0) {
+						enable &= ~2;
+					} else
+					if (strcmp(word, "udp") == 0) {
+						enable &= ~4;
+					} else {
+						printf(
+						"inet: Can't do 'no %s'\n",
+							word);
+						exit(1);
+					}
+					token(0);
+				} else {
+					printf("inet: Unknown option '%s'\n",
+						word);
+					exit(1);
+				}
+				if (word[0] == ';') token(0);
+				else
+				if (word[0] != '}') error();
+			}
+			token(0);
+		}
+		if (word[0] != ';' && word[0] != 0) error();
+
+		if (enable & 1) icp++, ip_conf_nr++;
+		if (enable & 2) tcp_conf_nr++;
+		if (enable & 4) udp_conf_nr++;
+	}
+
+	if (ifdefault == -1) {
+		printf("inet: No networks or no default network defined\n");
+		exit(1);
+	}
+
+	/* Translate VLAN network references to port numbers. */
+	for (i= 0; i < eth_conf_nr; i++) {
+		ecp= &eth_conf[i];
+		if (eth_is_vlan(ecp)) {
+			for (j= 0; j < eth_conf_nr; j++) {
+				if (eth_conf[j].ec_ifno == ecp->ec_port
+					&& !eth_is_vlan(&eth_conf[j])
+				) {
+					ecp->ec_port= j;
+					break;
+				}
+			}
+			if (j == eth_conf_nr) {
+				printf(
+				"inet: VLAN eth%d can't be built on eth%d\n",
+					ecp->ec_ifno, ecp->ec_port);
+				exit(1);
+			}
+		}
+	}
+
+	/* Set umask 0 so we can creat mode 666 devices. */
+	(void) umask(0);
+
+	/* See what the device number of /dev/ip is.  That's what we
+	 * used last time for the network devices, so we keep doing so.
+	 */
+	if (stat("/dev/ip", &st) < 0) fatal("/dev/ip");
+	ip_dev= st.st_rdev;
+
+	for (i= 0; i < IP_PORT_MAX; i++) {
+		/* Create network devices. */
+		check_dev(iftype[i], i);
+	}
+}
+
+void *alloc(size_t size)
+{
+	/* Allocate memory on the heap with sbrk(). */
+
+	return sbrk((size + (sizeof(char *) - 1)) & ~(sizeof(char *) - 1));
+}
+
+/*
+ * $PchId: inet_config.c,v 1.10 2003/08/21 09:26:02 philip Exp $
+ */
Index: /trunk/minix/servers/inet/inet_config.h
===================================================================
--- /trunk/minix/servers/inet/inet_config.h	(revision 9)
+++ /trunk/minix/servers/inet/inet_config.h	(revision 9)
@@ -0,0 +1,88 @@
+/*
+inet/inet_config.h
+
+Created:	Nov 11, 1992 by Philip Homburg
+
+Defines values for configurable parameters. The structure definitions for
+configuration information are also here.
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef INET__INET_CONFIG_H
+#define INET__INET_CONFIG_H
+
+/* Inet configuration file. */
+#define PATH_INET_CONF	"/etc/inet.conf"
+
+#define IP_PORT_MAX	32	/* Up to this many network devices */
+extern int eth_conf_nr;		/* Number of ethernets */
+extern int psip_conf_nr;	/* Number of Pseudo IP networks */
+extern int ip_conf_nr;		/* Number of configured IP layers */
+extern int tcp_conf_nr;		/* Number of configured TCP layers */
+extern int udp_conf_nr;		/* Number of configured UDP layers */
+
+extern dev_t ip_dev;		/* Device number of /dev/ip */
+
+struct eth_conf
+{
+	char *ec_task;		/* Kernel ethernet task name if nonnull */
+	u8_t ec_port;		/* Task port (!vlan) or Ethernet port (vlan) */
+	u8_t ec_ifno;		/* Interface number of /dev/eth* */
+	u16_t ec_vlan;		/* VLAN number of this net if task == NULL */
+};
+#define eth_is_vlan(ecp)	((ecp)->ec_task == NULL)
+
+struct psip_conf
+{
+	u8_t pc_ifno;		/* Interface number of /dev/psip* */
+};
+
+struct ip_conf
+{
+	u8_t ic_devtype;	/* Underlying device type: Ethernet / PSIP */
+	u8_t ic_port;		/* Port of underlying device */
+	u8_t ic_ifno;		/* Interface number of /dev/ip*, tcp*, udp* */
+};
+
+struct tcp_conf
+{
+	u8_t tc_port;		/* IP port number */
+};
+
+struct udp_conf
+{
+	u8_t uc_port;		/* IP port number */
+};
+
+/* Types of networks. */
+#define NETTYPE_ETH	1
+#define NETTYPE_PSIP	2
+
+/* To compute the minor device number for a device on an interface. */
+#define if2minor(ifno, dev)	((ifno) * 8 + (dev))
+
+/* Offsets of the minor device numbers within a group per interface. */
+#define ETH_DEV_OFF	0
+#define PSIP_DEV_OFF	0
+#define IP_DEV_OFF	1
+#define TCP_DEV_OFF	2
+#define UDP_DEV_OFF	3
+
+extern struct eth_conf eth_conf[IP_PORT_MAX];
+extern struct psip_conf psip_conf[IP_PORT_MAX];
+extern struct ip_conf ip_conf[IP_PORT_MAX];
+extern struct tcp_conf tcp_conf[IP_PORT_MAX];
+extern struct udp_conf udp_conf[IP_PORT_MAX];
+void read_conf(void);
+extern char *sbrk(int);
+void *alloc(size_t size);
+
+/* Options */
+extern int ip_forward_directed_bcast;
+
+#endif /* INET__INET_CONFIG_H */
+
+/*
+ * $PchId: inet_config.h,v 1.10 2003/08/21 09:24:33 philip Exp $
+ */
Index: /trunk/minix/servers/inet/minix3/queryparam.c
===================================================================
--- /trunk/minix/servers/inet/minix3/queryparam.c	(revision 9)
+++ /trunk/minix/servers/inet/minix3/queryparam.c	(revision 9)
@@ -0,0 +1,151 @@
+/*	queryparam() - allow program parameters to be queried
+ *							Author: Kees J. Bot
+ *								21 Apr 1994
+ */
+#define nil 0
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <minix3/queryparam.h>
+
+#if EXAMPLE
+struct stat st[2];
+
+struct export_param_list ex_st_list[]= {
+	QP_VARIABLE(st),
+	QP_ARRAY(st),
+	QP_FIELD(st_dev, struct stat),
+	QP_FIELD(st_ino, struct stat),
+	...
+	QP_END()
+};
+
+struct buf { block_t b_blocknr; ... } *buf;
+size_t nr_bufs;
+
+struct export_param_list ex_buf_list[]=
+	QP_VECTOR(buf, buf, nr_bufs),
+	QP_FIELD(b_blocknr),
+	...
+	QP_END()
+};
+
+struct export_params ex_st= { ex_st_list, 0 };
+struct export_params ex_buf= { ex_buf_list, 0 };
+#endif
+
+#define between(a, c, z)    ((unsigned) ((c) - (a)) <= (unsigned) ((z) - (a)))
+
+static int isvar(int c)
+{
+	return between('a', c, 'z') || between('A', c, 'Z')
+				|| between('0', c, '9') || c == '_';
+}
+
+static struct export_params *params;
+
+void qp_export(struct export_params *ex_params)
+{
+	/* Add a set of exported parameters. */
+
+	if (ex_params->next == nil) {
+		ex_params->next= params;
+		params= ex_params;
+	}
+}
+
+int queryparam(int qgetc(void), void **poffset, size_t *psize)
+{
+	char *prefix;
+	struct export_params *ep;
+	struct export_param_list *epl;
+	size_t offset= 0;
+	size_t size= -1;
+	size_t n;
+	static size_t retval;
+	int c, firstc;
+
+	firstc= c= (*qgetc)();
+	if (c == '&' || c == '$') c= (*qgetc)();
+	if (!isvar(c)) goto fail;
+
+	if ((ep= params) == nil) goto fail;
+	epl= ep->list;
+
+	while (c != 0 && c != ',') {
+		prefix= "x";
+		n= 0;
+
+		for (;;) {
+			while (epl->name == nil) {
+				if ((ep= ep->next) == nil) goto fail;
+				epl= ep->list;
+			}
+			if (strncmp(prefix, epl->name, n) == 0) {
+				prefix= epl->name;
+				while (prefix[n] != 0 && c == prefix[n]) {
+					n++;
+					c= (*qgetc)();
+				}
+			}
+			if (prefix[n] == 0 && (!isvar(c) || prefix[0] == '[')) {
+				/* Got a match. */
+				break;
+			}
+			epl++;
+		}
+
+		if (prefix[0] == '[') {
+			/* Array reference. */
+			size_t idx= 0, cnt= 1, max= size / epl->size;
+
+			while (between('0', c, '9')) {
+				idx= idx * 10 + (c - '0');
+				if (idx > max) goto fail;
+				c= (*qgetc)();
+			}
+			if (c == ':') {
+				cnt= 0;
+				while (between('0', (c= (*qgetc)()), '9')) {
+					cnt= cnt * 10 + (c - '0');
+				}
+			}
+			if (c != ']') goto fail;
+			if (idx + cnt > max) cnt= max - idx;
+			offset+= idx * epl->size;
+			size= cnt * epl->size;
+			c= (*qgetc)();
+		} else
+		if (epl->size == -1) {
+			/* Vector. */
+			offset= (size_t) * (void **) epl->offset;
+			size= (* (size_t *) epl[1].offset) * epl[1].size;
+		} else {
+			/* Variable or struct field. */
+			offset+= (size_t) epl->offset;
+			if ((size_t) epl->offset > size) goto fail;
+			size-= (size_t) epl->offset;
+			if (size < epl->size) goto fail;
+			size= epl->size;
+		}
+	}
+	if (firstc == '&' || firstc == '$') {
+		retval= firstc == '&' ? offset : size;
+		offset= (size_t) &retval;
+		size= sizeof(retval);
+	}
+	if (c != 0 && c != ',') goto fail;
+	*poffset= (void *) offset;
+	*psize= size;
+	return c != 0;
+fail:
+	while (c != 0 && c != ',') c= (*qgetc)();
+	*poffset= nil;
+	*psize= 0;
+	return c != 0;
+}
+
+/*
+ * $PchId: queryparam.c,v 1.1 2005/06/28 14:30:56 philip Exp $
+ */
Index: /trunk/minix/servers/inet/minix3/queryparam.h
===================================================================
--- /trunk/minix/servers/inet/minix3/queryparam.h	(revision 9)
+++ /trunk/minix/servers/inet/minix3/queryparam.h	(revision 9)
@@ -0,0 +1,45 @@
+/*	queryparam.h - query program parameters		Author: Kees J. Bot
+ *								22 Apr 1994
+ */
+#ifndef _MINIX__QUERYPARAM_H
+#define _MINIX__QUERYPARAM_H
+
+#include <ansi.h>
+
+typedef size_t _mnx_size_t;
+
+struct export_param_list {
+	char	*name;		/* "variable", "[", ".field", or NULL. */
+	void	*offset;	/* Address of a variable or field offset. */
+	size_t	size;		/* Size of the resulting object. */
+};
+
+struct export_params {
+	struct export_param_list *list;	/* List of exported parameters. */
+	struct export_params	 *next;	/* Link several sets of parameters. */
+};
+
+#ifdef __STDC__
+#define qp_stringize(var)	#var
+#define qp_dotstringize(var)	"." #var
+#else
+#define qp_stringize(var)	"var"
+#define qp_dotstringize(var)	".var"
+#endif
+#define QP_VARIABLE(var)	{ qp_stringize(var), &(var), sizeof(var) }
+#define QP_ARRAY(var)		{ "[", 0, sizeof((var)[0]) }
+#define QP_VECTOR(var,ptr,len)	{ qp_stringize(var), &(ptr), -1 },\
+				{ "[", &(len), sizeof(*(ptr)) }
+#define QP_FIELD(field, type)	{ qp_dotstringize(field), \
+					(void *)offsetof(type, field), \
+					sizeof(((type *)0)->field) }
+#define QP_END()		{ 0, 0, 0 }
+
+void qp_export _ARGS((struct export_params *_ex_params));
+int queryparam _ARGS((int (*_qgetc) _ARGS((void)), void **_paddress,
+							_mnx_size_t *_psize));
+_mnx_size_t paramvalue _ARGS((char **_value, void *_address,
+							_mnx_size_t _size));
+#endif /* _MINIX__QUERYPARAM_H */
+
+/* $PchId: queryparam.h,v 1.1 2005/06/28 14:31:26 philip Exp $ */
Index: /trunk/minix/servers/inet/mnx_eth.c
===================================================================
--- /trunk/minix/servers/inet/mnx_eth.c	(revision 9)
+++ /trunk/minix/servers/inet/mnx_eth.c	(revision 9)
@@ -0,0 +1,872 @@
+/*
+inet/mnx_eth.c
+
+Created:	Jan 2, 1992 by Philip Homburg
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "proto.h"
+#include "osdep_eth.h"
+#include "generic/type.h"
+
+#include "generic/assert.h"
+#include "generic/buf.h"
+#include "generic/clock.h"
+#include "generic/eth.h"
+#include "generic/eth_int.h"
+#include "generic/sr.h"
+
+THIS_FILE
+
+static int recv_debug= 0;
+
+FORWARD _PROTOTYPE( void setup_read, (eth_port_t *eth_port) );
+FORWARD _PROTOTYPE( void read_int, (eth_port_t *eth_port, int count) );
+FORWARD _PROTOTYPE( void write_int, (eth_port_t *eth_port) );
+FORWARD _PROTOTYPE( void eth_recvev, (event_t *ev, ev_arg_t ev_arg) );
+FORWARD _PROTOTYPE( void eth_sendev, (event_t *ev, ev_arg_t ev_arg) );
+FORWARD _PROTOTYPE( eth_port_t *find_port, (message *m) );
+FORWARD _PROTOTYPE( void eth_restart, (eth_port_t *eth_port, int tasknr) );
+
+PUBLIC void osdep_eth_init()
+{
+	int i, r, tasknr, rport;
+	struct eth_conf *ecp;
+	eth_port_t *eth_port, *rep;
+	message mess;
+
+	/* First initialize normal ethernet interfaces */
+	for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
+		i<eth_conf_nr; i++, ecp++, eth_port++)
+	{
+		if (eth_is_vlan(ecp))
+			continue;
+#ifdef __minix_vmd
+		r= sys_findproc(ecp->ec_task, &tasknr, 0);
+#else /* Minix 3 */
+		r = _pm_findproc(ecp->ec_task, &tasknr);
+#endif 
+		if (r != OK)
+		{
+			/* Eventually, we expect ethernet drivers to be
+			 * started after INET. So we always end up here. And
+			 * the findproc can be removed.
+			 */
+			printf("eth%d: unable to find task %s: %d\n",
+				i, ecp->ec_task, r);
+			tasknr= ANY;
+		}
+
+ 		eth_port->etp_osdep.etp_port= ecp->ec_port;
+		eth_port->etp_osdep.etp_task= tasknr;
+		ev_init(&eth_port->etp_osdep.etp_recvev);
+
+		mess.m_type= DL_INIT;
+		mess.DL_PORT= eth_port->etp_osdep.etp_port;
+		mess.DL_PROC= this_proc;
+		mess.DL_MODE= DL_NOMODE;
+
+		if (tasknr == ANY)
+			r= ENXIO;
+		else
+		{
+			r= send(eth_port->etp_osdep.etp_task, &mess);
+			if (r<0)
+			{
+				printf(
+		"osdep_eth_init: unable to send to ethernet task, error= %d\n",
+					r);
+			}
+		}
+
+		if (r == OK)
+		{
+			r= receive(eth_port->etp_osdep.etp_task, &mess);
+			if (r<0)
+			{
+				printf(
+	"osdep_eth_init: unable to receive from ethernet task, error= %d\n",
+					r);
+			}
+		}
+
+		if (r == OK)
+		{
+			r= mess.m3_i1;
+			if (r == ENXIO)
+			{
+				printf(
+		"osdep_eth_init: no ethernet device at task=%d,port=%d\n",
+					eth_port->etp_osdep.etp_task, 
+					eth_port->etp_osdep.etp_port);
+			}
+			else if (r < 0)
+			{
+				ip_panic((
+				"osdep_eth_init: DL_INIT returned error %d\n",
+					r));
+			}
+			else if (mess.m3_i1 != eth_port->etp_osdep.etp_port)
+			{
+				ip_panic((
+	"osdep_eth_init: got reply for wrong port (got %d, expected %d)\n",
+					mess.m3_i1,
+					eth_port->etp_osdep.etp_port));
+			}
+		}
+			
+		sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
+			i, eth_open, eth_close, eth_read, 
+			eth_write, eth_ioctl, eth_cancel, eth_select);
+
+		eth_port->etp_flags |= EPF_ENABLED;
+		eth_port->etp_vlan= 0;
+		eth_port->etp_vlan_port= NULL;
+		eth_port->etp_wr_pack= 0;
+		eth_port->etp_rd_pack= 0;
+		if (r == OK)
+		{
+			eth_port->etp_ethaddr= *(ether_addr_t *)mess.m3_ca1;
+			eth_port->etp_flags |= EPF_GOT_ADDR;
+			setup_read (eth_port);
+		}
+	}
+
+	/* And now come the VLANs */
+	for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
+		i<eth_conf_nr; i++, ecp++, eth_port++)
+	{
+		if (!eth_is_vlan(ecp))
+			continue;
+
+ 		eth_port->etp_osdep.etp_port= ecp->ec_port;
+		eth_port->etp_osdep.etp_task= ANY;
+		ev_init(&eth_port->etp_osdep.etp_recvev);
+
+		rport= eth_port->etp_osdep.etp_port;
+		assert(rport >= 0 && rport < eth_conf_nr);
+		rep= &eth_port_table[rport];
+		if (!(rep->etp_flags & EPF_ENABLED))
+		{
+			printf(
+			"eth%d: underlying ethernet device %d not enabled",
+				i, rport);
+			continue;
+		}
+		if (rep->etp_vlan != 0)
+		{
+			printf(
+			"eth%d: underlying ethernet device %d is a VLAN",
+				i, rport);
+			continue;
+		}
+		
+		if (rep->etp_flags & EPF_GOT_ADDR)
+		{
+			eth_port->etp_ethaddr= rep->etp_ethaddr;
+			eth_port->etp_flags |= EPF_GOT_ADDR;
+		}
+
+		sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
+			i, eth_open, eth_close, eth_read, 
+			eth_write, eth_ioctl, eth_cancel, eth_select);
+
+		eth_port->etp_flags |= EPF_ENABLED;
+		eth_port->etp_vlan= ecp->ec_vlan;
+		eth_port->etp_vlan_port= rep;
+		assert(eth_port->etp_vlan != 0);
+		eth_port->etp_wr_pack= 0;
+		eth_port->etp_rd_pack= 0;
+		eth_reg_vlan(rep, eth_port);
+	}
+}
+
+PUBLIC void eth_write_port(eth_port, pack)
+eth_port_t *eth_port;
+acc_t *pack;
+{
+	eth_port_t *loc_port;
+	message mess1, block_msg;
+	int i, pack_size;
+	acc_t *pack_ptr;
+	iovec_t *iovec;
+	u8_t *eth_dst_ptr;
+	int multicast, r;
+	ev_arg_t ev_arg;
+
+	assert(!no_ethWritePort);
+	assert(!eth_port->etp_vlan);
+
+	assert(eth_port->etp_wr_pack == NULL);
+	eth_port->etp_wr_pack= pack;
+
+	iovec= eth_port->etp_osdep.etp_wr_iovec;
+	pack_size= 0;
+	for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr; i++,
+		pack_ptr= pack_ptr->acc_next)
+	{
+		iovec[i].iov_addr= (vir_bytes)ptr2acc_data(pack_ptr);
+		pack_size += iovec[i].iov_size= pack_ptr->acc_length;
+	}
+	if (i>= IOVEC_NR)
+	{
+		pack= bf_pack(pack);		/* packet is too fragmented */
+		eth_port->etp_wr_pack= pack;
+		pack_size= 0;
+		for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr;
+			i++, pack_ptr= pack_ptr->acc_next)
+		{
+			iovec[i].iov_addr= (vir_bytes)ptr2acc_data(pack_ptr);
+			pack_size += iovec[i].iov_size= pack_ptr->acc_length;
+		}
+	}
+	assert (i< IOVEC_NR);
+	assert (pack_size >= ETH_MIN_PACK_SIZE);
+
+	if (i == 1)
+	{
+		/* simple packets can be sent using DL_WRITE instead of 
+		 * DL_WRITEV.
+		 */
+		mess1.DL_COUNT= iovec[0].iov_size;
+		mess1.DL_ADDR= (char *)iovec[0].iov_addr;
+		mess1.m_type= DL_WRITE;
+	}
+	else
+	{
+		mess1.DL_COUNT= i;
+		mess1.DL_ADDR= (char *)iovec;
+		mess1.m_type= DL_WRITEV;
+	}
+	mess1.DL_PORT= eth_port->etp_osdep.etp_port;
+	mess1.DL_PROC= this_proc;
+	mess1.DL_MODE= DL_NOMODE;
+
+	for (;;)
+	{
+		r= sendrec(eth_port->etp_osdep.etp_task, &mess1);
+		if (r != ELOCKED)
+			break;
+
+		/* ethernet task is sending to this task, I hope */
+		r= receive(eth_port->etp_osdep.etp_task, &block_msg);
+		if (r < 0)
+			ip_panic(("unable to receive"));
+
+		loc_port= eth_port;
+		if (loc_port->etp_osdep.etp_port != block_msg.DL_PORT ||
+			loc_port->etp_osdep.etp_task != block_msg.m_source)
+		{
+			loc_port= find_port(&block_msg);
+		}
+		assert(block_msg.DL_STAT & (DL_PACK_SEND|DL_PACK_RECV));
+		if (block_msg.DL_STAT & DL_PACK_SEND)
+		{
+			assert(loc_port != eth_port);
+			loc_port->etp_osdep.etp_sendrepl= block_msg;
+			ev_arg.ev_ptr= loc_port;
+			ev_enqueue(&loc_port->etp_sendev, eth_sendev, ev_arg);
+		}
+		if (block_msg.DL_STAT & DL_PACK_RECV)
+		{
+			if (recv_debug)
+			{
+				printf(
+			"eth_write_port(block_msg): eth%d got DL_PACK_RECV\n",
+					loc_port-eth_port_table);
+			}
+			loc_port->etp_osdep.etp_recvrepl= block_msg;
+			ev_arg.ev_ptr= loc_port;
+			ev_enqueue(&loc_port->etp_osdep.etp_recvev,
+				eth_recvev, ev_arg);
+		}
+	}
+
+	if (r < 0)
+	{
+		printf("eth_write_port: sendrec to %d failed: %d\n",
+			eth_port->etp_osdep.etp_task, r);
+		return;
+	}
+
+	assert(mess1.m_type == DL_TASK_REPLY &&
+		mess1.DL_PORT == eth_port->etp_osdep.etp_port &&
+		mess1.DL_PROC == this_proc);
+	assert((mess1.DL_STAT >> 16) == OK);
+
+	if (mess1.DL_STAT & DL_PACK_RECV)
+	{
+		if (recv_debug)
+		{
+			printf(
+			"eth_write_port(mess1): eth%d got DL_PACK_RECV\n",
+				mess1.DL_PORT);
+		}
+		eth_port->etp_osdep.etp_recvrepl= mess1;
+		ev_arg.ev_ptr= eth_port;
+		ev_enqueue(&eth_port->etp_osdep.etp_recvev, eth_recvev,
+			ev_arg);
+	}
+	if (!(mess1.DL_STAT & DL_PACK_SEND))
+	{
+		/* Packet is not yet sent. */
+		return;
+	}
+
+	/* If the port is in promiscuous mode or the packet is
+	 * broad- or multicast, enqueue the reply packet.
+	 */
+	eth_dst_ptr= (u8_t *)ptr2acc_data(pack);
+	multicast= (*eth_dst_ptr & 1);	/* low order bit indicates multicast */
+	if (multicast || (eth_port->etp_osdep.etp_recvconf & NWEO_EN_PROMISC))
+	{
+		eth_port->etp_osdep.etp_sendrepl= mess1;
+		ev_arg.ev_ptr= eth_port;
+		ev_enqueue(&eth_port->etp_sendev, eth_sendev, ev_arg);
+
+		/* Pretend that we didn't get a reply. */
+		return;
+	}
+
+	/* packet is sent */
+	bf_afree(eth_port->etp_wr_pack);
+	eth_port->etp_wr_pack= NULL;
+}
+
+PUBLIC void eth_rec(m)
+message *m;
+{
+	int i;
+	eth_port_t *loc_port;
+	int stat;
+
+	assert(m->m_type == DL_TASK_REPLY);
+
+	set_time (m->DL_CLCK);
+
+	for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
+	{
+		if (loc_port->etp_osdep.etp_port == m->DL_PORT &&
+			loc_port->etp_osdep.etp_task == m->m_source)
+			break;
+	}
+	if (i == eth_conf_nr)
+	{
+		ip_panic(("message from unknown source: %d:%d",
+			m->m_source, m->DL_PORT));
+	}
+
+	stat= m->DL_STAT & 0xffff;
+
+	assert(stat & (DL_PACK_SEND|DL_PACK_RECV));
+	if (stat & DL_PACK_SEND)
+		write_int(loc_port);
+	if (stat & DL_PACK_RECV)
+	{
+		if (recv_debug)
+		{
+			printf("eth_rec: eth%d got DL_PACK_RECV\n",
+				m->DL_PORT);
+		}
+		read_int(loc_port, m->DL_COUNT);
+	}
+}
+
+PUBLIC void eth_check_drivers(m)
+message *m;
+{
+	int i, r, tasknr;
+	struct eth_conf *ecp;
+	eth_port_t *eth_port;
+	char *drivername;
+
+	tasknr= m->m_source;
+	printf("eth_check_drivers: got a notification from %d\n", tasknr);
+
+	m->m_type= DL_GETNAME;
+	r= sendrec(tasknr, m);
+	if (r != OK)
+	{
+		printf("eth_check_drivers: sendrec to %d failed: %d\n",
+			tasknr, r);
+		return;
+	}
+	if (m->m_type != DL_NAME_REPLY)
+	{
+		printf(
+		"eth_check_drivers: got bad getname reply (%d) from %d\n",
+			m->m_type, tasknr);
+		return;
+	}
+
+	drivername= m->m3_ca1;
+	printf("eth_check_drivers: got name: %s\n", drivername);
+
+	/* Re-init ethernet interfaces */
+	for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
+		i<eth_conf_nr; i++, ecp++, eth_port++)
+	{
+		if (eth_is_vlan(ecp))
+			continue;
+
+		if (strcmp(ecp->ec_task, drivername) != 0)
+		{
+			/* Wrong driver */
+			continue;
+		}
+
+		eth_restart(eth_port, tasknr);
+	}
+}
+
+PUBLIC int eth_get_stat(eth_port, eth_stat)
+eth_port_t *eth_port;
+eth_stat_t *eth_stat;
+{
+	int r;
+	message mess, mlocked;
+
+	assert(!eth_port->etp_vlan);
+
+	mess.m_type= DL_GETSTAT;
+	mess.DL_PORT= eth_port->etp_osdep.etp_port;
+	mess.DL_PROC= this_proc;
+	mess.DL_ADDR= (char *)eth_stat;
+
+	for (;;)
+	{
+		r= sendrec(eth_port->etp_osdep.etp_task, &mess);
+		if (r != ELOCKED)
+			break;
+
+		r= receive(eth_port->etp_osdep.etp_task, &mlocked);
+		assert(r == OK);
+
+		compare(mlocked.m_type, ==, DL_TASK_REPLY);
+		eth_rec(&mlocked);
+	}
+
+	if (r != OK)
+	{
+		printf("eth_get_stat: sendrec to %d failed: %d\n",
+			eth_port->etp_osdep.etp_task, r);
+		return EIO;
+	}
+
+	assert(mess.m_type == DL_TASK_REPLY);
+
+	r= mess.DL_STAT >> 16;
+	assert (r == 0);
+
+	if (mess.DL_STAT)
+	{
+		eth_rec(&mess);
+	}
+	return OK;
+}
+
+PUBLIC void eth_set_rec_conf (eth_port, flags)
+eth_port_t *eth_port;
+u32_t flags;
+{
+	int r;
+	unsigned dl_flags;
+	message mess, repl_mess;
+
+	assert(!eth_port->etp_vlan);
+
+	if (!(eth_port->etp_flags & EPF_GOT_ADDR))
+	{
+		/* We have never seen the device. */
+		printf("eth_set_rec_conf: waiting for device to appear\n");
+		return;
+	}
+
+	eth_port->etp_osdep.etp_recvconf= flags;
+	dl_flags= DL_NOMODE;
+	if (flags & NWEO_EN_BROAD)
+		dl_flags |= DL_BROAD_REQ;
+	if (flags & NWEO_EN_MULTI)
+		dl_flags |= DL_MULTI_REQ;
+	if (flags & NWEO_EN_PROMISC)
+		dl_flags |= DL_PROMISC_REQ;
+
+	mess.m_type= DL_INIT;
+	mess.DL_PORT= eth_port->etp_osdep.etp_port;
+	mess.DL_PROC= this_proc;
+	mess.DL_MODE= dl_flags;
+
+	do
+	{
+		r= sendrec(eth_port->etp_osdep.etp_task, &mess);
+		if (r == ELOCKED)	/* etp_task is sending to this task,
+					   I hope */
+		{
+			if (receive (eth_port->etp_osdep.etp_task, 
+				&repl_mess)< 0)
+			{
+				ip_panic(("unable to receive"));
+			}
+
+			compare(repl_mess.m_type, ==, DL_TASK_REPLY);
+			eth_rec(&repl_mess);
+		}
+	} while (r == ELOCKED);
+	
+	if (r < 0)
+	{
+		printf("eth_set_rec_conf: sendrec to %d failed: %d\n",
+			eth_port->etp_osdep.etp_task, r);
+		return;
+	}
+
+	assert (mess.m_type == DL_INIT_REPLY);
+	if (mess.m3_i1 != eth_port->etp_osdep.etp_port)
+	{
+		ip_panic(("got reply for wrong port"));
+	}
+}
+
+PRIVATE void write_int(eth_port)
+eth_port_t *eth_port;
+{
+	acc_t *pack;
+	int multicast;
+	u8_t *eth_dst_ptr;
+
+	pack= eth_port->etp_wr_pack;
+	eth_port->etp_wr_pack= NULL;
+
+	eth_dst_ptr= (u8_t *)ptr2acc_data(pack);
+	multicast= (*eth_dst_ptr & 1);	/* low order bit indicates multicast */
+	if (multicast || (eth_port->etp_osdep.etp_recvconf & NWEO_EN_PROMISC))
+	{
+		assert(!no_ethWritePort);
+		no_ethWritePort= 1;
+		eth_arrive(eth_port, pack, bf_bufsize(pack));
+		assert(no_ethWritePort);
+		no_ethWritePort= 0;
+	}
+	else
+		bf_afree(pack);
+
+	eth_restart_write(eth_port);
+}
+
+PRIVATE void read_int(eth_port, count)
+eth_port_t *eth_port;
+int count;
+{
+	acc_t *pack, *cut_pack;
+
+	pack= eth_port->etp_rd_pack;
+	eth_port->etp_rd_pack= NULL;
+
+	cut_pack= bf_cut(pack, 0, count);
+	bf_afree(pack);
+
+	assert(!no_ethWritePort);
+	no_ethWritePort= 1;
+	eth_arrive(eth_port, cut_pack, count);
+	assert(no_ethWritePort);
+	no_ethWritePort= 0;
+	
+	eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
+	setup_read(eth_port);
+}
+
+PRIVATE void setup_read(eth_port)
+eth_port_t *eth_port;
+{
+	eth_port_t *loc_port;
+	acc_t *pack, *pack_ptr;
+	message mess1, block_msg;
+	iovec_t *iovec;
+	ev_arg_t ev_arg;
+	int i, r;
+
+	assert(!eth_port->etp_vlan);
+	assert(!(eth_port->etp_flags & (EPF_READ_IP|EPF_READ_SP)));
+
+	do
+	{
+		assert (!eth_port->etp_rd_pack);
+
+		iovec= eth_port->etp_osdep.etp_rd_iovec;
+		pack= bf_memreq (ETH_MAX_PACK_SIZE_TAGGED);
+
+		for (i=0, pack_ptr= pack; i<RD_IOVEC && pack_ptr;
+			i++, pack_ptr= pack_ptr->acc_next)
+		{
+			iovec[i].iov_addr= (vir_bytes)ptr2acc_data(pack_ptr);
+			iovec[i].iov_size= (vir_bytes)pack_ptr->acc_length;
+		}
+		assert (!pack_ptr);
+
+		mess1.m_type= DL_READV;
+		mess1.DL_PORT= eth_port->etp_osdep.etp_port;
+		mess1.DL_PROC= this_proc;
+		mess1.DL_COUNT= i;
+		mess1.DL_ADDR= (char *)iovec;
+
+		for (;;)
+		{
+			if (recv_debug)
+			{
+				printf("eth%d: sending DL_READV\n",
+					mess1.DL_PORT);
+			}
+			r= sendrec(eth_port->etp_osdep.etp_task, &mess1);
+			if (r != ELOCKED)
+				break;
+
+			/* ethernet task is sending to this task, I hope */
+			r= receive(eth_port->etp_osdep.etp_task, &block_msg);
+			if (r < 0)
+				ip_panic(("unable to receive"));
+
+			loc_port= eth_port;
+			if (loc_port->etp_osdep.etp_port != block_msg.DL_PORT ||
+				loc_port->etp_osdep.etp_task !=
+				block_msg.m_source)
+			{
+				loc_port= find_port(&block_msg);
+			}
+			assert(block_msg.DL_STAT &
+				(DL_PACK_SEND|DL_PACK_RECV));
+			if (block_msg.DL_STAT & DL_PACK_SEND)
+			{
+				loc_port->etp_osdep.etp_sendrepl= block_msg;
+				ev_arg.ev_ptr= loc_port;
+				ev_enqueue(&loc_port->etp_sendev, eth_sendev,
+					ev_arg);
+			}
+			if (block_msg.DL_STAT & DL_PACK_RECV)
+			{
+				if (recv_debug)
+				{
+					printf(
+			"setup_read(block_msg): eth%d got DL_PACK_RECV\n",
+						block_msg.DL_PORT);
+				}
+				assert(loc_port != eth_port);
+				loc_port->etp_osdep.etp_recvrepl= block_msg;
+				ev_arg.ev_ptr= loc_port;
+				ev_enqueue(&loc_port->etp_osdep.etp_recvev,
+					eth_recvev, ev_arg);
+			}
+		}
+
+		if (r < 0)
+		{
+			printf("mnx_eth`setup_read: sendrec to %d failed: %d\n",
+				eth_port->etp_osdep.etp_task, r);
+			eth_port->etp_rd_pack= pack;
+			eth_port->etp_flags |= EPF_READ_IP;
+			continue;
+		}
+
+		assert (mess1.m_type == DL_TASK_REPLY &&
+			mess1.DL_PORT == mess1.DL_PORT &&
+			mess1.DL_PROC == this_proc);
+		compare((mess1.DL_STAT >> 16), ==, OK);
+
+		if (mess1.DL_STAT & DL_PACK_RECV)
+		{
+			if (recv_debug)
+			{
+				printf(
+			"setup_read(mess1): eth%d: got DL_PACK_RECV\n",
+					mess1.DL_PORT);
+			}
+			/* packet received */
+			pack_ptr= bf_cut(pack, 0, mess1.DL_COUNT);
+			bf_afree(pack);
+
+			assert(!no_ethWritePort);
+			no_ethWritePort= 1;
+			eth_arrive(eth_port, pack_ptr, mess1.DL_COUNT);
+			assert(no_ethWritePort);
+			no_ethWritePort= 0;
+		}
+		else
+		{
+			/* no packet received */
+			eth_port->etp_rd_pack= pack;
+			eth_port->etp_flags |= EPF_READ_IP;
+		}
+
+		if (mess1.DL_STAT & DL_PACK_SEND)
+		{
+			eth_port->etp_osdep.etp_sendrepl= mess1;
+			ev_arg.ev_ptr= eth_port;
+			ev_enqueue(&eth_port->etp_sendev, eth_sendev, ev_arg);
+		}
+	} while (!(eth_port->etp_flags & EPF_READ_IP));
+	eth_port->etp_flags |= EPF_READ_SP;
+}
+
+PRIVATE void eth_recvev(ev, ev_arg)
+event_t *ev;
+ev_arg_t ev_arg;
+{
+	eth_port_t *eth_port;
+	message *m_ptr;
+
+	eth_port= ev_arg.ev_ptr;
+	assert(ev == &eth_port->etp_osdep.etp_recvev);
+	m_ptr= &eth_port->etp_osdep.etp_recvrepl;
+
+	assert(m_ptr->m_type == DL_TASK_REPLY);
+	assert(eth_port->etp_osdep.etp_port == m_ptr->DL_PORT &&
+		eth_port->etp_osdep.etp_task == m_ptr->m_source);
+
+	assert(m_ptr->DL_STAT & DL_PACK_RECV);
+	m_ptr->DL_STAT &= ~DL_PACK_RECV;
+
+	if (recv_debug)
+	{
+		printf("eth_recvev: eth%d got DL_PACK_RECV\n", m_ptr->DL_PORT);
+	}
+
+	read_int(eth_port, m_ptr->DL_COUNT);
+}
+
+PRIVATE void eth_sendev(ev, ev_arg)
+event_t *ev;
+ev_arg_t ev_arg;
+{
+	eth_port_t *eth_port;
+	message *m_ptr;
+
+	eth_port= ev_arg.ev_ptr;
+	assert(ev == &eth_port->etp_sendev);
+	m_ptr= &eth_port->etp_osdep.etp_sendrepl;
+
+	assert (m_ptr->m_type == DL_TASK_REPLY);
+	assert(eth_port->etp_osdep.etp_port == m_ptr->DL_PORT &&
+		eth_port->etp_osdep.etp_task == m_ptr->m_source);
+
+	assert(m_ptr->DL_STAT & DL_PACK_SEND);
+	m_ptr->DL_STAT &= ~DL_PACK_SEND;
+
+	/* packet is sent */
+	write_int(eth_port);
+}
+
+PRIVATE eth_port_t *find_port(m)
+message *m;
+{
+	eth_port_t *loc_port;
+	int i;
+
+	for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
+	{
+		if (loc_port->etp_osdep.etp_port == m->DL_PORT &&
+			loc_port->etp_osdep.etp_task == m->m_source)
+			break;
+	}
+	assert (i<eth_conf_nr);
+	return loc_port;
+}
+
+static void eth_restart(eth_port, tasknr)
+eth_port_t *eth_port;
+int tasknr;
+{
+	int i, r;
+	unsigned flags, dl_flags;
+	message mess;
+	eth_port_t *loc_port;
+
+	printf("eth_restart: restarting eth%d, task %d, port %d\n",
+		eth_port-eth_port_table, tasknr,
+		eth_port->etp_osdep.etp_port);
+
+	eth_port->etp_osdep.etp_task= tasknr;
+
+	flags= eth_port->etp_osdep.etp_recvconf;
+	dl_flags= DL_NOMODE;
+	if (flags & NWEO_EN_BROAD)
+		dl_flags |= DL_BROAD_REQ;
+	if (flags & NWEO_EN_MULTI)
+		dl_flags |= DL_MULTI_REQ;
+	if (flags & NWEO_EN_PROMISC)
+		dl_flags |= DL_PROMISC_REQ;
+	mess.m_type= DL_INIT;
+	mess.DL_PORT= eth_port->etp_osdep.etp_port;
+	mess.DL_PROC= this_proc;
+	mess.DL_MODE= dl_flags;
+
+	r= sendrec(eth_port->etp_osdep.etp_task, &mess);
+	/* YYY */
+	if (r<0)
+	{
+		printf(
+	"eth_restart: sendrec to ethernet task %d failed: %d\n",
+			eth_port->etp_osdep.etp_task, r);
+		return;
+	}
+
+	if (mess.m3_i1 == ENXIO)
+	{
+		printf(
+	"osdep_eth_init: no ethernet device at task=%d,port=%d\n",
+			eth_port->etp_osdep.etp_task, 
+			eth_port->etp_osdep.etp_port);
+		return;
+	}
+	if (mess.m3_i1 < 0)
+		ip_panic(("osdep_eth_init: DL_INIT returned error %d\n",
+			mess.m3_i1));
+		
+	if (mess.m3_i1 != eth_port->etp_osdep.etp_port)
+	{
+		ip_panic((
+"osdep_eth_init: got reply for wrong port (got %d, expected %d)\n",
+			mess.m3_i1, eth_port->etp_osdep.etp_port));
+	}
+
+	eth_port->etp_flags |= EPF_ENABLED;
+
+	eth_port->etp_ethaddr= *(ether_addr_t *)mess.m3_ca1;
+	if (!(eth_port->etp_flags & EPF_GOT_ADDR))
+	{
+		eth_port->etp_flags |= EPF_GOT_ADDR;
+		eth_restart_ioctl(eth_port);
+
+		/* Also update any VLANs on this device */
+		for (i=0, loc_port= eth_port_table; i<eth_conf_nr;
+			i++, loc_port++)
+		{
+			if (!(loc_port->etp_flags & EPF_ENABLED))
+				continue;
+			if (loc_port->etp_vlan_port != eth_port)
+				continue;
+			 
+			loc_port->etp_ethaddr= eth_port->etp_ethaddr;
+			loc_port->etp_flags |= EPF_GOT_ADDR;
+			eth_restart_ioctl(loc_port);
+		}
+	}
+
+	if (eth_port->etp_wr_pack)
+	{
+		bf_afree(eth_port->etp_wr_pack);
+		eth_port->etp_wr_pack= NULL;
+		eth_restart_write(eth_port);
+	}
+	if (eth_port->etp_rd_pack)
+	{
+		bf_afree(eth_port->etp_rd_pack);
+		eth_port->etp_rd_pack= NULL;
+		eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
+	}
+	setup_read (eth_port);
+}
+
+/*
+ * $PchId: mnx_eth.c,v 1.16 2005/06/28 14:24:37 philip Exp $
+ */
Index: /trunk/minix/servers/inet/mq.c
===================================================================
--- /trunk/minix/servers/inet/mq.c	(revision 9)
+++ /trunk/minix/servers/inet/mq.c	(revision 9)
@@ -0,0 +1,58 @@
+/*
+inet/mq.c
+
+Created:	Jan 3, 1992 by Philip Homburg
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+#include "mq.h"
+#include "generic/assert.h"
+
+THIS_FILE
+
+#define MQ_SIZE		128
+
+PRIVATE mq_t mq_list[MQ_SIZE];
+PRIVATE mq_t *mq_freelist;
+
+void mq_init()
+{
+	int i;
+
+	mq_freelist= NULL;
+	for (i= 0; i<MQ_SIZE; i++)
+	{
+		mq_list[i].mq_next= mq_freelist;
+		mq_freelist= &mq_list[i];
+		mq_list[i].mq_allocated= 0;
+	}
+}
+
+mq_t *mq_get()
+{
+	mq_t *mq;
+
+	mq= mq_freelist;
+	assert(mq != NULL);
+
+	mq_freelist= mq->mq_next;
+	mq->mq_next= NULL;
+	assert(mq->mq_allocated == 0);
+	mq->mq_allocated= 1;
+	return mq;
+}
+
+void mq_free(mq)
+mq_t *mq;
+{
+	mq->mq_next= mq_freelist;
+	mq_freelist= mq;
+	assert(mq->mq_allocated == 1);
+	mq->mq_allocated= 0;
+}
+
+/*
+ * $PchId: mq.c,v 1.7 1998/10/23 20:10:47 philip Exp $
+ */
Index: /trunk/minix/servers/inet/mq.h
===================================================================
--- /trunk/minix/servers/inet/mq.h	(revision 9)
+++ /trunk/minix/servers/inet/mq.h	(revision 9)
@@ -0,0 +1,27 @@
+/*
+inet/mq.h
+
+Created:	Jan 3, 1992 by Philip Homburg
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef INET__MQ_H
+#define INET__MQ_H
+
+typedef struct mq
+{
+	message mq_mess;
+	struct mq *mq_next;
+	int mq_allocated;
+} mq_t;
+
+_PROTOTYPE( mq_t *mq_get, (void) );
+_PROTOTYPE( void mq_free, (mq_t *mq) );
+_PROTOTYPE( void mq_init, (void) );
+
+#endif /* INET__MQ_H */
+
+/*
+ * $PchId: mq.h,v 1.4 1995/11/21 06:40:30 philip Exp $
+ */
Index: /trunk/minix/servers/inet/osdep_eth.h
===================================================================
--- /trunk/minix/servers/inet/osdep_eth.h	(revision 9)
+++ /trunk/minix/servers/inet/osdep_eth.h	(revision 9)
@@ -0,0 +1,33 @@
+/*
+inet/osdep_eth.h
+
+Created:	Dec 30, 1991 by Philip Homburg
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef INET__OSDEP_ETH_H
+#define INET__OSDEP_ETH_H
+
+#include "generic/event.h"
+
+#define IOVEC_NR	16
+#define RD_IOVEC	((ETH_MAX_PACK_SIZE + BUF_S -1)/BUF_S)
+
+typedef struct osdep_eth_port
+{
+	int etp_task;
+	int etp_port;
+	int etp_recvconf;
+	iovec_t etp_wr_iovec[IOVEC_NR];
+	iovec_t etp_rd_iovec[RD_IOVEC];
+	event_t etp_recvev;
+	message etp_sendrepl;
+	message etp_recvrepl;
+} osdep_eth_port_t;
+
+#endif /* INET__OSDEP_ETH_H */
+
+/*
+ * $PchId: osdep_eth.h,v 1.6 2001/04/20 06:39:54 philip Exp $
+ */
Index: /trunk/minix/servers/inet/proto.h
===================================================================
--- /trunk/minix/servers/inet/proto.h	(revision 9)
+++ /trunk/minix/servers/inet/proto.h	(revision 9)
@@ -0,0 +1,28 @@
+/*
+inet/proto.h
+
+Created:	Jan 2, 1992 by Philip Homburg
+
+Copyright 1995 Philip Homburg
+*/
+
+/* clock.c */
+
+_PROTOTYPE( void clck_tick, (message *mess) );
+
+/* mnx_eth.c */
+
+_PROTOTYPE( void eth_rec, (message *m) );
+_PROTOTYPE( void eth_check_drivers, (message *m) );
+
+/* sr.c */
+
+struct mq;
+_PROTOTYPE( void sr_rec, (struct mq *m) );
+
+
+
+
+/*
+ * $PchId: proto.h,v 1.4 1995/11/21 06:36:37 philip Exp $
+ */
Index: /trunk/minix/servers/inet/qp.c
===================================================================
--- /trunk/minix/servers/inet/qp.c	(revision 9)
+++ /trunk/minix/servers/inet/qp.c	(revision 9)
@@ -0,0 +1,174 @@
+/*
+inet/qp.c
+
+Query parameters
+
+Created:	June 1995 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+#include "inet.h"
+
+#include <sys/svrctl.h>
+#ifdef __minix_vmd
+#include <minix/queryparam.h>
+#else /* Minix 3 */
+#include <minix3/queryparam.h>
+#endif
+
+#include "generic/buf.h"
+#include "generic/clock.h"
+#include "generic/event.h"
+#include "generic/type.h"
+#include "generic/sr.h"
+
+#include "generic/tcp_int.h"
+#include "generic/udp_int.h"
+#include "mq.h"
+#include "qp.h"
+#include "sr_int.h"
+
+FORWARD int get_userdata ARGS(( int proc, vir_bytes vaddr, vir_bytes vlen,
+	void *buffer ));
+FORWARD int put_userdata ARGS(( int proc, vir_bytes vaddr, vir_bytes vlen,
+	void *buffer ));
+FORWARD int iqp_getc ARGS(( void ));
+FORWARD void iqp_putc ARGS(( int c ));
+
+PRIVATE struct export_param_list inet_ex_list[]=
+{
+	QP_VARIABLE(sr_fd_table),
+	QP_VARIABLE(ip_dev),
+	QP_VARIABLE(tcp_fd_table),
+	QP_VARIABLE(tcp_conn_table),
+	QP_VARIABLE(tcp_cancel_f),
+	QP_VECTOR(udp_port_table, udp_port_table, ip_conf_nr),
+	QP_VARIABLE(udp_fd_table),
+	QP_END()
+};
+
+PRIVATE struct export_params inet_ex_params= { inet_ex_list, NULL };
+
+PRIVATE struct queryvars {
+	int proc;
+	struct svrqueryparam qpar;
+	char parbuf[256], valbuf[256];
+	char *param, *value;
+	int r;
+} *qvars;
+
+PUBLIC void qp_init()
+{
+	qp_export(&inet_ex_params);
+}
+
+PUBLIC int qp_query(proc, argp)
+int proc;
+vir_bytes argp;
+{
+	/* Return values, sizes, or addresses of variables in MM space. */
+
+	struct queryvars qv;
+	void *addr;
+	size_t n, size;
+	int byte;
+	int more;
+	static char hex[]= "0123456789ABCDEF";
+
+	qv.r= get_userdata(proc, argp, sizeof(qv.qpar), &qv.qpar);
+
+	/* Export these to mq_getc() and mq_putc(). */
+	qvars= &qv;
+	qv.proc= proc;
+	qv.param= qv.parbuf + sizeof(qv.parbuf);
+	qv.value= qv.valbuf;
+
+	do {
+		more= queryparam(iqp_getc, &addr, &size);
+		for (n= 0; n < size; n++) {
+			byte= ((u8_t *) addr)[n];
+			iqp_putc(hex[byte >> 4]);
+			iqp_putc(hex[byte & 0x0F]);
+		}
+		iqp_putc(more ? ',' : 0);
+	} while (more);
+	return qv.r;
+}
+
+
+PRIVATE int iqp_getc()
+{
+	/* Return one character of the names to search for. */
+	struct queryvars *qv= qvars;
+	size_t n;
+
+	if (qv->r != OK || qv->qpar.psize == 0) return 0;
+	if (qv->param == qv->parbuf + sizeof(qv->parbuf)) {
+		/* Need to fill the parameter buffer. */
+		n= sizeof(qv->parbuf);
+		if (qv->qpar.psize < n) n= qv->qpar.psize;
+		qv->r= get_userdata(qv->proc, (vir_bytes) qv->qpar.param, n,
+								qv->parbuf);
+		if (qv->r != OK) return 0;
+		qv->qpar.param+= n;
+		qv->param= qv->parbuf;
+	}
+	qv->qpar.psize--;
+	return (u8_t) *qv->param++;
+}
+
+
+PRIVATE void iqp_putc(c)
+int c;
+{
+	/* Send one character back to the user. */
+	struct queryvars *qv= qvars;
+	size_t n;
+
+	if (qv->r != OK || qv->qpar.vsize == 0) return;
+	*qv->value++= c;
+	qv->qpar.vsize--;
+	if (qv->value == qv->valbuf + sizeof(qv->valbuf)
+					|| c == 0 || qv->qpar.vsize == 0) {
+		/* Copy the value buffer to user space. */
+		n= qv->value - qv->valbuf;
+		qv->r= put_userdata(qv->proc, (vir_bytes) qv->qpar.value, n,
+								qv->valbuf);
+		qv->qpar.value+= n;
+		qv->value= qv->valbuf;
+	}
+}
+
+PRIVATE int get_userdata(proc, vaddr, vlen, buffer)
+int proc;
+vir_bytes vaddr;
+vir_bytes vlen;
+void *buffer;
+{
+#ifdef __minix_vmd
+	return sys_copy(proc, SEG_D, (phys_bytes)vaddr, this_proc, SEG_D,
+		(phys_bytes)buffer, (phys_bytes)vlen);
+#else /* Minix 3 */
+	return sys_vircopy(proc, D, vaddr, SELF, D, (vir_bytes)buffer, vlen);
+#endif
+}
+
+
+PRIVATE int put_userdata(proc, vaddr, vlen, buffer)
+int proc;
+vir_bytes vaddr;
+vir_bytes vlen;
+void *buffer;
+{
+#ifdef __minix_vmd
+	return sys_copy(this_proc, SEG_D, (phys_bytes)buffer,
+		proc, SEG_D, (phys_bytes)vaddr, (phys_bytes)vlen);
+#else /* Minix 3 */
+	return sys_vircopy(SELF, D, (vir_bytes)buffer, proc, D, vaddr, vlen);
+#endif
+}
+
+
+
+/*
+ * $PchId: qp.c,v 1.7 2005/06/28 14:25:25 philip Exp $
+ */
Index: /trunk/minix/servers/inet/qp.h
===================================================================
--- /trunk/minix/servers/inet/qp.h	(revision 9)
+++ /trunk/minix/servers/inet/qp.h	(revision 9)
@@ -0,0 +1,21 @@
+/*
+inet/qp.h
+
+Handle queryparams requests
+
+Created:	June 1995 by Philip Homburg <philip@f-mnx.phicoh.com>
+
+Copyright 1995 Philip Homburg
+*/
+
+#ifndef INET__QP_H
+#define INET__QP_H
+
+void qp_init ARGS(( void ));
+int qp_query ARGS(( int proc, vir_bytes argp ));
+
+#endif /* INET__QP_H */
+
+/*
+ * $PchId: qp.h,v 1.4 2005/01/29 18:08:06 philip Exp $
+ */
Index: /trunk/minix/servers/inet/sha2.c
===================================================================
--- /trunk/minix/servers/inet/sha2.c	(revision 9)
+++ /trunk/minix/servers/inet/sha2.c	(revision 9)
@@ -0,0 +1,1093 @@
+
+/*
+ * sha2.c
+ *
+ * Version 1.0.0beta1
+ *
+ * Written by Aaron D. Gifford <me@aarongifford.com>
+ *
+ * Copyright 2000 Aaron D. Gifford.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+
+#include <sys/types.h>
+/* #include <sys/time.h> */
+/* #include <sys/systm.h> */
+/* #include <machine/endian.h> */
+#include "sha2.h"
+
+/*
+ * ASSERT NOTE:
+ * Some sanity checking code is included using assert().  On my FreeBSD
+ * system, this additional code can be removed by compiling with NDEBUG
+ * defined.  Check your own systems manpage on assert() to see how to
+ * compile WITHOUT the sanity checking code on your system.
+ *
+ * UNROLLED TRANSFORM LOOP NOTE:
+ * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
+ * loop version for the hash transform rounds (defined using macros
+ * later in this file).  Either define on the command line, for example:
+ *
+ *   cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
+ *
+ * or define below:
+ *
+ *   #define SHA2_UNROLL_TRANSFORM
+ *
+ */
+
+#if defined(__bsdi__) || defined(__FreeBSD__)
+#define assert(x)
+#endif
+
+
+/*** SHA-256/384/512 Machine Architecture Definitions *****************/
+/*
+ * SHA2_BYTE_ORDER NOTE:
+ *
+ * Please make sure that your system defines SHA2_BYTE_ORDER.  If your
+ * architecture is little-endian, make sure it also defines
+ * SHA2_LITTLE_ENDIAN and that the two (SHA2_BYTE_ORDER and
+ * SHA2_LITTLE_ENDIAN) are equivilent.
+ *
+ * If your system does not define the above, then you can do so by
+ * hand like this:
+ *
+ *   #define SHA2_LITTLE_ENDIAN 1234
+ *   #define SHA2_BIG_ENDIAN    4321
+ *
+ * And for little-endian machines, add:
+ *
+ *   #define SHA2_BYTE_ORDER SHA2_LITTLE_ENDIAN 
+ *
+ * Or for big-endian machines:
+ *
+ *   #define SHA2_BYTE_ORDER SHA2_BIG_ENDIAN
+ *
+ * The FreeBSD machine this was written on defines BYTE_ORDER
+ * appropriately by including <sys/types.h> (which in turn includes
+ * <machine/endian.h> where the appropriate definitions are actually
+ * made).
+ */
+#if !defined(SHA2_BYTE_ORDER) || (SHA2_BYTE_ORDER != SHA2_LITTLE_ENDIAN && SHA2_BYTE_ORDER != SHA2_BIG_ENDIAN)
+#error Define SHA2_BYTE_ORDER to be equal to either SHA2_LITTLE_ENDIAN or SHA2_BIG_ENDIAN
+#endif
+
+/*
+ * Define the followingsha2_* types to types of the correct length on
+ * the native archtecture.   Most BSD systems and Linux define u_intXX_t
+ * types.  Machines with very recent ANSI C headers, can use the
+ * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H
+ * during compile or in the sha.h header file.
+ *
+ * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t
+ * will need to define these three typedefs below (and the appropriate
+ * ones in sha.h too) by hand according to their system architecture.
+ *
+ * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t
+ * types and pointing out recent ANSI C support for uintXX_t in inttypes.h.
+ */
+#if 0 /*def SHA2_USE_INTTYPES_H*/
+
+typedef uint8_t  sha2_byte;	/* Exactly 1 byte */
+typedef uint32_t sha2_word32;	/* Exactly 4 bytes */
+typedef uint64_t sha2_word64;	/* Exactly 8 bytes */
+
+#else /* SHA2_USE_INTTYPES_H */
+
+typedef u_int8_t  sha2_byte;	/* Exactly 1 byte */
+typedef u_int32_t sha2_word32;	/* Exactly 4 bytes */
+typedef u_int64_t sha2_word64;	/* Exactly 8 bytes */
+
+#endif /* SHA2_USE_INTTYPES_H */
+
+
+/*** SHA-256/384/512 Various Length Definitions ***********************/
+/* NOTE: Most of these are in sha2.h */
+#define SHA256_SHORT_BLOCK_LENGTH	(SHA256_BLOCK_LENGTH - 8)
+#define SHA384_SHORT_BLOCK_LENGTH	(SHA384_BLOCK_LENGTH - 16)
+#define SHA512_SHORT_BLOCK_LENGTH	(SHA512_BLOCK_LENGTH - 16)
+
+
+/*** ENDIAN REVERSAL MACROS *******************************************/
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+#define REVERSE32(w,x)	{ \
+	sha2_word32 tmp = (w); \
+	tmp = (tmp >> 16) | (tmp << 16); \
+	(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
+}
+#define REVERSE64(w,x)	{ \
+	sha2_word64 tmp = (w); \
+	tmp = (tmp >> 32) | (tmp << 32); \
+	tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
+	      ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
+	(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
+	      ((tmp & 0x0000ffff0000ffffULL) << 16); \
+}
+#if MINIX_64BIT
+#undef REVERSE64
+#define REVERSE64(w,x)	{ \
+	u32_t hi, lo; \
+	REVERSE32(ex64hi((w)), lo); \
+	REVERSE32(ex64lo((w)), hi); \
+	(x) = make64(lo, hi); \
+}
+#endif /* MINIX_64BIT */
+#endif /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+
+/*
+ * Macro for incrementally adding the unsigned 64-bit integer n to the
+ * unsigned 128-bit integer (represented using a two-element array of
+ * 64-bit words):
+ */
+#define ADDINC128(w,n)	{ \
+	(w)[0] += (sha2_word64)(n); \
+	if ((w)[0] < (n)) { \
+		(w)[1]++; \
+	} \
+}
+
+/*** THE SIX LOGICAL FUNCTIONS ****************************************/
+/*
+ * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
+ *
+ *   NOTE:  The naming of R and S appears backwards here (R is a SHIFT and
+ *   S is a ROTATION) because the SHA-256/384/512 description document
+ *   (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
+ *   same "backwards" definition.
+ */
+/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
+#define R(b,x) 		((x) >> (b))
+/* 32-bit Rotate-right (used in SHA-256): */
+#define S32(b,x)	(((x) >> (b)) | ((x) << (32 - (b))))
+/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
+#define S64(b,x)	(((x) >> (b)) | ((x) << (64 - (b))))
+
+/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
+#define Ch(x,y,z)	(((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z)	(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+/* Four of six logical functions used in SHA-256: */
+#define Sigma0_256(x)	(S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))
+#define Sigma1_256(x)	(S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))
+#define sigma0_256(x)	(S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))
+#define sigma1_256(x)	(S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))
+
+/* Four of six logical functions used in SHA-384 and SHA-512: */
+#define Sigma0_512(x)	(S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
+#define Sigma1_512(x)	(S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
+#define sigma0_512(x)	(S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7,   (x)))
+#define sigma1_512(x)	(S64(19, (x)) ^ S64(61, (x)) ^ R( 6,   (x)))
+
+/*** INTERNAL FUNCTION PROTOTYPES *************************************/
+/* NOTE: These should not be accessed directly from outside this
+ * library -- they are intended for private internal visibility/use
+ * only.
+ */
+void SHA512_Last(SHA512_CTX*);
+void SHA256_Transform(SHA256_CTX*, const sha2_word32*);
+void SHA512_Transform(SHA512_CTX*, const sha2_word64*);
+
+
+/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
+/* Hash constant words K for SHA-256: */
+const static sha2_word32 K256[64] = {
+	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+/* Initial hash value H for SHA-256: */
+const static sha2_word32 sha256_initial_hash_value[8] = {
+	0x6a09e667UL,
+	0xbb67ae85UL,
+	0x3c6ef372UL,
+	0xa54ff53aUL,
+	0x510e527fUL,
+	0x9b05688cUL,
+	0x1f83d9abUL,
+	0x5be0cd19UL
+};
+
+#if !NO_64BIT
+/* Hash constant words K for SHA-384 and SHA-512: */
+const static sha2_word64 K512[80] = {
+	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+	0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+	0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+	0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+	0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+	0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+	0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+	0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+	0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+	0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+	0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+	0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+	0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+	0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+	0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+	0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+	0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+	0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+	0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+	0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+	0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+	0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+	0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+	0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+	0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+	0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+	0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+	0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+	0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+	0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+	0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+	0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+	0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+	0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+	0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+	0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+	0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+	0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+	0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+	0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+/* Initial hash value H for SHA-384 */
+const static sha2_word64 sha384_initial_hash_value[8] = {
+	0xcbbb9d5dc1059ed8ULL,
+	0x629a292a367cd507ULL,
+	0x9159015a3070dd17ULL,
+	0x152fecd8f70e5939ULL,
+	0x67332667ffc00b31ULL,
+	0x8eb44a8768581511ULL,
+	0xdb0c2e0d64f98fa7ULL,
+	0x47b5481dbefa4fa4ULL
+};
+
+/* Initial hash value H for SHA-512 */
+const static sha2_word64 sha512_initial_hash_value[8] = {
+	0x6a09e667f3bcc908ULL,
+	0xbb67ae8584caa73bULL,
+	0x3c6ef372fe94f82bULL,
+	0xa54ff53a5f1d36f1ULL,
+	0x510e527fade682d1ULL,
+	0x9b05688c2b3e6c1fULL,
+	0x1f83d9abfb41bd6bULL,
+	0x5be0cd19137e2179ULL
+};
+#endif /* !NO_64BIT */
+
+/*
+ * Constant used by SHA256/384/512_End() functions for converting the
+ * digest to a readable hexadecimal character string:
+ */
+static const char *sha2_hex_digits = "0123456789abcdef";
+
+
+/*** SHA-256: *********************************************************/
+void SHA256_Init(SHA256_CTX* context) {
+	if (context == (SHA256_CTX*)0) {
+		return;
+	}
+	bcopy(sha256_initial_hash_value, context->state, SHA256_DIGEST_LENGTH);
+	bzero(context->buffer, SHA256_BLOCK_LENGTH);
+#if MINIX_64BIT
+	context->bitcount= cvu64(0);
+#else /* !MINIX_64BIT */
+	context->bitcount = 0;
+#endif /* MINIX_64BIT */
+}
+
+#ifdef SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-256 round macros: */
+
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
+	REVERSE32(*data++, W256[j]); \
+	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+             K256[j] + W256[j]; \
+	(d) += T1; \
+	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+	j++
+
+
+#else /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
+	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+	     K256[j] + (W256[j] = *data++); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+	j++
+
+#endif /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+
+#define ROUND256(a,b,c,d,e,f,g,h)	\
+	s0 = W256[(j+1)&0x0f]; \
+	s0 = sigma0_256(s0); \
+	s1 = W256[(j+14)&0x0f]; \
+	s1 = sigma1_256(s1); \
+	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
+	     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+	j++
+
+void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
+	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
+	sha2_word32	T1, *W256;
+	int		j;
+
+	W256 = (sha2_word32*)context->buffer;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+		/* Rounds 0 to 15 (unrolled): */
+		ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
+		ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
+		ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
+		ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
+		ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
+		ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
+		ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
+		ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
+	} while (j < 16);
+
+	/* Now for the remaining rounds to 64: */
+	do {
+		ROUND256(a,b,c,d,e,f,g,h);
+		ROUND256(h,a,b,c,d,e,f,g);
+		ROUND256(g,h,a,b,c,d,e,f);
+		ROUND256(f,g,h,a,b,c,d,e);
+		ROUND256(e,f,g,h,a,b,c,d);
+		ROUND256(d,e,f,g,h,a,b,c);
+		ROUND256(c,d,e,f,g,h,a,b);
+		ROUND256(b,c,d,e,f,g,h,a);
+	} while (j < 64);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = 0;
+}
+
+#else /* SHA2_UNROLL_TRANSFORM */
+
+void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
+	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
+	sha2_word32	T1, T2, *W256;
+	int		j;
+
+	W256 = (sha2_word32*)context->buffer;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+		/* Copy data while converting to host byte order */
+		REVERSE32(*data++,W256[j]);
+		/* Apply the SHA-256 compression function to update a..h */
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
+#else /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+		/* Apply the SHA-256 compression function to update a..h with copy */
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
+#endif /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+		T2 = Sigma0_256(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 16);
+
+	do {
+		/* Part of the message block expansion: */
+		s0 = W256[(j+1)&0x0f];
+		s0 = sigma0_256(s0);
+		s1 = W256[(j+14)&0x0f];	
+		s1 = sigma1_256(s1);
+
+		/* Apply the SHA-256 compression function to update a..h */
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + 
+		     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
+		T2 = Sigma0_256(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 64);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#endif /* SHA2_UNROLL_TRANSFORM */
+
+void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
+	unsigned int	freespace, usedspace;
+
+	if (len == 0) {
+		/* Calling with no data is valid - we do nothing */
+		return;
+	}
+
+	/* Sanity check: */
+	assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0);
+
+#if MINIX_64BIT
+	usedspace= rem64u(context->bitcount, SHA256_BLOCK_LENGTH*8)/8;
+#else /* !MINIX_64BIT */
+	usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
+#endif /* MINIX_64BIT */
+	if (usedspace > 0) {
+		/* Calculate how much free space is available in the buffer */
+		freespace = SHA256_BLOCK_LENGTH - usedspace;
+
+		if (len >= freespace) {
+			/* Fill the buffer completely and process it */
+			bcopy(data, &context->buffer[usedspace], freespace);
+#if MINIX_64BIT
+			context->bitcount= add64u(context->bitcount,
+				freespace << 3);
+#else /* !MINIX_64BIT */
+			context->bitcount += freespace << 3;
+#endif /* MINIX_64BIT */
+			len -= freespace;
+			data += freespace;
+			SHA256_Transform(context, (sha2_word32*)context->buffer);
+		} else {
+			/* The buffer is not yet full */
+			bcopy(data, &context->buffer[usedspace], len);
+#if MINIX_64BIT
+			context->bitcount= add64u(context->bitcount, len << 3);
+#else /* !MINIX_64BIT */
+			context->bitcount += len << 3;
+#endif /* MINIX_64BIT */
+			/* Clean up: */
+			usedspace = freespace = 0;
+			return;
+		}
+	}
+	while (len >= SHA256_BLOCK_LENGTH) {
+		/* Process as many complete blocks as we can */
+		SHA256_Transform(context, (const sha2_word32*)data);
+#if MINIX_64BIT
+		context->bitcount= add64u(context->bitcount,
+			SHA256_BLOCK_LENGTH << 3);
+#else /* !MINIX_64BIT */
+		context->bitcount += SHA256_BLOCK_LENGTH << 3;
+#endif /* MINIX_64BIT */
+		len -= SHA256_BLOCK_LENGTH;
+		data += SHA256_BLOCK_LENGTH;
+	}
+	if (len > 0) {
+		/* There's left-overs, so save 'em */
+		bcopy(data, context->buffer, len);
+#if MINIX_64BIT
+		context->bitcount= add64u(context->bitcount, len << 3);
+#else /* !MINIX_64BIT */
+		context->bitcount += len << 3;
+#endif /* MINIX_64BIT */
+	}
+	/* Clean up: */
+	usedspace = freespace = 0;
+}
+
+void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
+	sha2_word32	*d = (sha2_word32*)digest;
+	unsigned int	usedspace;
+
+	/* Sanity check: */
+	assert(context != (SHA256_CTX*)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (sha2_byte*)0) {
+#if MINIX_64BIT
+		usedspace= rem64u(context->bitcount, SHA256_BLOCK_LENGTH*8)/8;
+#else /* !MINIX_64BIT */
+		usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
+#endif /* MINIX_64BIT */
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+		/* Convert FROM host byte order */
+		REVERSE64(context->bitcount,context->bitcount);
+#endif
+		if (usedspace > 0) {
+			/* Begin padding with a 1 bit: */
+			context->buffer[usedspace++] = 0x80;
+
+			if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
+				/* Set-up for the last transform: */
+				bzero(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace);
+			} else {
+				if (usedspace < SHA256_BLOCK_LENGTH) {
+					bzero(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace);
+				}
+				/* Do second-to-last transform: */
+				SHA256_Transform(context, (sha2_word32*)context->buffer);
+
+				/* And set-up for the last transform: */
+				bzero(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
+			}
+		} else {
+			/* Set-up for the last transform: */
+			bzero(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
+
+			/* Begin padding with a 1 bit: */
+			*context->buffer = 0x80;
+		}
+		/* Set the bit count: */
+		*(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
+
+		/* Final transform: */
+		SHA256_Transform(context, (sha2_word32*)context->buffer);
+
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+		{
+			/* Convert TO host byte order */
+			int	j;
+			for (j = 0; j < 8; j++) {
+				REVERSE32(context->state[j],context->state[j]);
+				*d++ = context->state[j];
+			}
+		}
+#else
+		bcopy(context->state, d, SHA256_DIGEST_LENGTH);
+#endif
+	}
+
+	/* Clean up state data: */
+	bzero(context, sizeof(context));
+	usedspace = 0;
+}
+
+char *SHA256_End(SHA256_CTX* context, char buffer[]) {
+	sha2_byte	digest[SHA256_DIGEST_LENGTH], *d = digest;
+	int		i;
+
+	/* Sanity check: */
+	assert(context != (SHA256_CTX*)0);
+
+	if (buffer != (char*)0) {
+		SHA256_Final(digest, context);
+
+		for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+			*buffer++ = sha2_hex_digits[*d & 0x0f];
+			d++;
+		}
+		*buffer = (char)0;
+	} else {
+		bzero(context, sizeof(context));
+	}
+	bzero(digest, SHA256_DIGEST_LENGTH);
+	return buffer;
+}
+
+char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) {
+	SHA256_CTX	context;
+
+	SHA256_Init(&context);
+	SHA256_Update(&context, data, len);
+	return SHA256_End(&context, digest);
+}
+
+#if !NO_64BIT
+
+/*** SHA-512: *********************************************************/
+void SHA512_Init(SHA512_CTX* context) {
+	if (context == (SHA512_CTX*)0) {
+		return;
+	}
+	bcopy(sha512_initial_hash_value, context->state, SHA512_DIGEST_LENGTH);
+	bzero(context->buffer, SHA512_BLOCK_LENGTH);
+	context->bitcount[0] = context->bitcount[1] =  0;
+}
+
+#ifdef SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-512 round macros: */
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
+	REVERSE64(*data++, W512[j]); \
+	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+             K512[j] + W512[j]; \
+	(d) += T1, \
+	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
+	j++
+
+
+#else /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
+	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+             K512[j] + (W512[j] = *data++); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+	j++
+
+#endif /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+
+#define ROUND512(a,b,c,d,e,f,g,h)	\
+	s0 = W512[(j+1)&0x0f]; \
+	s0 = sigma0_512(s0); \
+	s1 = W512[(j+14)&0x0f]; \
+	s1 = sigma1_512(s1); \
+	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
+             (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+	j++
+
+void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
+	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
+	sha2_word64	T1, *W512 = (sha2_word64*)context->buffer;
+	int		j;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+		ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
+		ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
+		ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
+		ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
+		ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
+		ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
+		ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
+		ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
+	} while (j < 16);
+
+	/* Now for the remaining rounds up to 79: */
+	do {
+		ROUND512(a,b,c,d,e,f,g,h);
+		ROUND512(h,a,b,c,d,e,f,g);
+		ROUND512(g,h,a,b,c,d,e,f);
+		ROUND512(f,g,h,a,b,c,d,e);
+		ROUND512(e,f,g,h,a,b,c,d);
+		ROUND512(d,e,f,g,h,a,b,c);
+		ROUND512(c,d,e,f,g,h,a,b);
+		ROUND512(b,c,d,e,f,g,h,a);
+	} while (j < 80);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = 0;
+}
+
+#else /* SHA2_UNROLL_TRANSFORM */
+
+void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
+	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
+	sha2_word64	T1, T2, *W512 = (sha2_word64*)context->buffer;
+	int		j;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+		/* Convert TO host byte order */
+		REVERSE64(*data++, W512[j]);
+		/* Apply the SHA-512 compression function to update a..h */
+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
+#else /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+		/* Apply the SHA-512 compression function to update a..h with copy */
+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
+#endif /* SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN */
+		T2 = Sigma0_512(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 16);
+
+	do {
+		/* Part of the message block expansion: */
+		s0 = W512[(j+1)&0x0f];
+		s0 = sigma0_512(s0);
+		s1 = W512[(j+14)&0x0f];
+		s1 =  sigma1_512(s1);
+
+		/* Apply the SHA-512 compression function to update a..h */
+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
+		     (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
+		T2 = Sigma0_512(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 80);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#endif /* SHA2_UNROLL_TRANSFORM */
+
+void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
+	unsigned int	freespace, usedspace;
+
+	if (len == 0) {
+		/* Calling with no data is valid - we do nothing */
+		return;
+	}
+
+	/* Sanity check: */
+	assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0);
+
+	usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
+	if (usedspace > 0) {
+		/* Calculate how much free space is available in the buffer */
+		freespace = SHA512_BLOCK_LENGTH - usedspace;
+
+		if (len >= freespace) {
+			/* Fill the buffer completely and process it */
+			bcopy(data, &context->buffer[usedspace], freespace);
+			ADDINC128(context->bitcount, freespace << 3);
+			len -= freespace;
+			data += freespace;
+			SHA512_Transform(context, (sha2_word64*)context->buffer);
+		} else {
+			/* The buffer is not yet full */
+			bcopy(data, &context->buffer[usedspace], len);
+			ADDINC128(context->bitcount, len << 3);
+			/* Clean up: */
+			usedspace = freespace = 0;
+			return;
+		}
+	}
+	while (len >= SHA512_BLOCK_LENGTH) {
+		/* Process as many complete blocks as we can */
+		SHA512_Transform(context, (const sha2_word64*)data);
+		ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
+		len -= SHA512_BLOCK_LENGTH;
+		data += SHA512_BLOCK_LENGTH;
+	}
+	if (len > 0) {
+		/* There's left-overs, so save 'em */
+		bcopy(data, context->buffer, len);
+		ADDINC128(context->bitcount, len << 3);
+	}
+	/* Clean up: */
+	usedspace = freespace = 0;
+}
+
+void SHA512_Last(SHA512_CTX* context) {
+	unsigned int	usedspace;
+
+	usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+	/* Convert FROM host byte order */
+	REVERSE64(context->bitcount[0],context->bitcount[0]);
+	REVERSE64(context->bitcount[1],context->bitcount[1]);
+#endif
+	if (usedspace > 0) {
+		/* Begin padding with a 1 bit: */
+		context->buffer[usedspace++] = 0x80;
+
+		if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
+			/* Set-up for the last transform: */
+			bzero(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace);
+		} else {
+			if (usedspace < SHA512_BLOCK_LENGTH) {
+				bzero(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace);
+			}
+			/* Do second-to-last transform: */
+			SHA512_Transform(context, (sha2_word64*)context->buffer);
+
+			/* And set-up for the last transform: */
+			bzero(context->buffer, SHA512_BLOCK_LENGTH - 2);
+		}
+	} else {
+		/* Prepare for final transform: */
+		bzero(context->buffer, SHA512_SHORT_BLOCK_LENGTH);
+
+		/* Begin padding with a 1 bit: */
+		*context->buffer = 0x80;
+	}
+	/* Store the length of input data (in bits): */
+	*(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1];
+	*(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0];
+
+	/* Final transform: */
+	SHA512_Transform(context, (sha2_word64*)context->buffer);
+}
+
+void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
+	sha2_word64	*d = (sha2_word64*)digest;
+
+	/* Sanity check: */
+	assert(context != (SHA512_CTX*)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (sha2_byte*)0) {
+		SHA512_Last(context);
+
+		/* Save the hash data for output: */
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+		{
+			/* Convert TO host byte order */
+			int	j;
+			for (j = 0; j < 8; j++) {
+				REVERSE64(context->state[j],context->state[j]);
+				*d++ = context->state[j];
+			}
+		}
+#else
+		bcopy(context->state, d, SHA512_DIGEST_LENGTH);
+#endif
+	}
+
+	/* Zero out state data */
+	bzero(context, sizeof(context));
+}
+
+char *SHA512_End(SHA512_CTX* context, char buffer[]) {
+	sha2_byte	digest[SHA512_DIGEST_LENGTH], *d = digest;
+	int		i;
+
+	/* Sanity check: */
+	assert(context != (SHA512_CTX*)0);
+
+	if (buffer != (char*)0) {
+		SHA512_Final(digest, context);
+
+		for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+			*buffer++ = sha2_hex_digits[*d & 0x0f];
+			d++;
+		}
+		*buffer = (char)0;
+	} else {
+		bzero(context, sizeof(context));
+	}
+	bzero(digest, SHA512_DIGEST_LENGTH);
+	return buffer;
+}
+
+char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) {
+	SHA512_CTX	context;
+
+	SHA512_Init(&context);
+	SHA512_Update(&context, data, len);
+	return SHA512_End(&context, digest);
+}
+
+
+/*** SHA-384: *********************************************************/
+void SHA384_Init(SHA384_CTX* context) {
+	if (context == (SHA384_CTX*)0) {
+		return;
+	}
+	bcopy(sha384_initial_hash_value, context->state, SHA512_DIGEST_LENGTH);
+	bzero(context->buffer, SHA384_BLOCK_LENGTH);
+	context->bitcount[0] = context->bitcount[1] = 0;
+}
+
+void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) {
+	SHA512_Update((SHA512_CTX*)context, data, len);
+}
+
+void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
+	sha2_word64	*d = (sha2_word64*)digest;
+
+	/* Sanity check: */
+	assert(context != (SHA384_CTX*)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (sha2_byte*)0) {
+		SHA512_Last((SHA512_CTX*)context);
+
+		/* Save the hash data for output: */
+#if SHA2_BYTE_ORDER == SHA2_LITTLE_ENDIAN
+		{
+			/* Convert TO host byte order */
+			int	j;
+			for (j = 0; j < 6; j++) {
+				REVERSE64(context->state[j],context->state[j]);
+				*d++ = context->state[j];
+			}
+		}
+#else
+		bcopy(context->state, d, SHA384_DIGEST_LENGTH);
+#endif
+	}
+
+	/* Zero out state data */
+	bzero(context, sizeof(context));
+}
+
+char *SHA384_End(SHA384_CTX* context, char buffer[]) {
+	sha2_byte	digest[SHA384_DIGEST_LENGTH], *d = digest;
+	int		i;
+
+	/* Sanity check: */
+	assert(context != (SHA384_CTX*)0);
+
+	if (buffer != (char*)0) {
+		SHA384_Final(digest, context);
+
+		for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+			*buffer++ = sha2_hex_digits[*d & 0x0f];
+			d++;
+		}
+		*buffer = (char)0;
+	} else {
+		bzero(context, sizeof(context));
+	}
+	bzero(digest, SHA384_DIGEST_LENGTH);
+	return buffer;
+}
+
+char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) {
+	SHA384_CTX	context;
+
+	SHA384_Init(&context);
+	SHA384_Update(&context, data, len);
+	return SHA384_End(&context, digest);
+}
+
+#endif /* !NO_64BIT */
+
+/*
+ * $PchId: sha2.c,v 1.1 2005/06/28 14:29:23 philip Exp $
+ */
Index: /trunk/minix/servers/inet/sha2.h
===================================================================
--- /trunk/minix/servers/inet/sha2.h	(revision 9)
+++ /trunk/minix/servers/inet/sha2.h	(revision 9)
@@ -0,0 +1,168 @@
+/*	$FreeBSD: src/sys/crypto/sha2/sha2.h,v 1.1.2.1 2001/07/03 11:01:36 ume Exp $	*/
+/*	$KAME: sha2.h,v 1.3 2001/03/12 08:27:48 itojun Exp $	*/
+
+/*
+ * sha2.h
+ *
+ * Version 1.0.0beta1
+ *
+ * Written by Aaron D. Gifford <me@aarongifford.com>
+ *
+ * Copyright 2000 Aaron D. Gifford.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef __SHA2_H__
+#define __SHA2_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*** SHA-256/384/512 Various Length Definitions ***********************/
+#define SHA256_BLOCK_LENGTH		64
+#define SHA256_DIGEST_LENGTH		32
+#define SHA256_DIGEST_STRING_LENGTH	(SHA256_DIGEST_LENGTH * 2 + 1)
+#define SHA384_BLOCK_LENGTH		128
+#define SHA384_DIGEST_LENGTH		48
+#define SHA384_DIGEST_STRING_LENGTH	(SHA384_DIGEST_LENGTH * 2 + 1)
+#define SHA512_BLOCK_LENGTH		128
+#define SHA512_DIGEST_LENGTH		64
+#define SHA512_DIGEST_STRING_LENGTH	(SHA512_DIGEST_LENGTH * 2 + 1)
+
+#ifdef __minix
+#include <assert.h>
+#include <string.h>
+#include <sys/types.h>
+#include <minix/u64.h>
+
+typedef u8_t u_int8_t;	/* 1-byte  (8-bits)  */
+typedef u32_t u_int32_t;	/* 4-bytes (32-bits) */
+typedef u64_t u_int64_t;	/* 8-bytes (64-bits) */
+
+#ifndef __P
+#define __P(x) x
+#endif
+
+#define NO_64BIT	1
+#define MINIX_64BIT	1
+
+#define SHA2_BYTE_ORDER		0x04030201
+#define SHA2_LITTLE_ENDIAN	0x04030201
+#define SHA2_BIG_ENDIAN		0x01020204
+#define bcopy(s,d,l)	(memmove((d),(s),(l)))
+#define bzero(d,l)	(memset((d),'\0',(l)))
+#endif
+
+/*** SHA-256/384/512 Context Structures *******************************/
+/* NOTE: If your architecture does not define either u_intXX_t types or
+ * uintXX_t (from inttypes.h), you may need to define things by hand
+ * for your system:
+ */
+#if 0
+typedef unsigned char u_int8_t;		/* 1-byte  (8-bits)  */
+typedef unsigned int u_int32_t;		/* 4-bytes (32-bits) */
+typedef unsigned long long u_int64_t;	/* 8-bytes (64-bits) */
+#endif
+/*
+ * Most BSD systems already define u_intXX_t types, as does Linux.
+ * Some systems, however, like Compaq's Tru64 Unix instead can use
+ * uintXX_t types defined by very recent ANSI C standards and included
+ * in the file:
+ *
+ *   #include <inttypes.h>
+ *
+ * If you choose to use <inttypes.h> then please define: 
+ *
+ *   #define SHA2_USE_INTTYPES_H
+ *
+ * Or on the command line during compile:
+ *
+ *   cc -DSHA2_USE_INTTYPES_H ...
+ */
+#if 0 /*def SHA2_USE_INTTYPES_H*/
+
+typedef struct _SHA256_CTX {
+	uint32_t	state[8];
+	uint64_t	bitcount;
+	uint8_t	buffer[SHA256_BLOCK_LENGTH];
+} SHA256_CTX;
+typedef struct _SHA512_CTX {
+	uint64_t	state[8];
+	uint64_t	bitcount[2];
+	uint8_t	buffer[SHA512_BLOCK_LENGTH];
+} SHA512_CTX;
+
+#else /* SHA2_USE_INTTYPES_H */
+
+typedef struct _SHA256_CTX {
+	u_int32_t	state[8];
+	u_int64_t	bitcount;
+	u_int8_t	buffer[SHA256_BLOCK_LENGTH];
+} SHA256_CTX;
+typedef struct _SHA512_CTX {
+	u_int64_t	state[8];
+	u_int64_t	bitcount[2];
+	u_int8_t	buffer[SHA512_BLOCK_LENGTH];
+} SHA512_CTX;
+
+#endif /* SHA2_USE_INTTYPES_H */
+
+typedef SHA512_CTX SHA384_CTX;
+
+
+/*** SHA-256/384/512 Function Prototypes ******************************/
+
+void SHA256_Init __P((SHA256_CTX *));
+void SHA256_Update __P((SHA256_CTX*, const u_int8_t*, size_t));
+void SHA256_Final __P((u_int8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*));
+char* SHA256_End __P((SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]));
+char* SHA256_Data __P((const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]));
+
+void SHA384_Init __P((SHA384_CTX*));
+void SHA384_Update __P((SHA384_CTX*, const u_int8_t*, size_t));
+void SHA384_Final __P((u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*));
+char* SHA384_End __P((SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]));
+char* SHA384_Data __P((const u_int8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]));
+
+void SHA512_Init __P((SHA512_CTX*));
+void SHA512_Update __P((SHA512_CTX*, const u_int8_t*, size_t));
+void SHA512_Final __P((u_int8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*));
+char* SHA512_End __P((SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]));
+char* SHA512_Data __P((const u_int8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]));
+
+#ifdef	__cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __SHA2_H__ */
+
+
+/*
+ * $PchId: sha2.h,v 1.1 2005/06/28 14:29:33 philip Exp $
+ */
Index: /trunk/minix/servers/inet/sr.c
===================================================================
--- /trunk/minix/servers/inet/sr.c	(revision 9)
+++ /trunk/minix/servers/inet/sr.c	(revision 9)
@@ -0,0 +1,1145 @@
+/*	this file contains the interface of the network software with the file
+ *	system.
+ *
+ * Copyright 1995 Philip Homburg
+ *
+ * The valid messages and their parameters are:
+ * 
+ * Requests:
+ *
+ *    m_type      NDEV_MINOR   NDEV_PROC    NDEV_REF   NDEV_MODE
+ * -------------------------------------------------------------
+ * | DEV_OPEN    |minor dev  | proc nr   |  fd       |   mode   |
+ * |-------------+-----------+-----------+-----------+----------+
+ * | DEV_CLOSE   |minor dev  | proc nr   |  fd       |          |
+ * |-------------+-----------+-----------+-----------+----------+
+ *
+ *    m_type      NDEV_MINOR   NDEV_PROC    NDEV_REF   NDEV_COUNT NDEV_BUFFER
+ * ---------------------------------------------------------------------------
+ * | DEV_READ    |minor dev  | proc nr   |  fd       |  count    | buf ptr   |
+ * |-------------+-----------+-----------+-----------+-----------+-----------|
+ * | DEV_WRITE   |minor dev  | proc nr   |  fd       |  count    | buf ptr   |
+ * |-------------+-----------+-----------+-----------+-----------+-----------|
+ *
+ *    m_type      NDEV_MINOR   NDEV_PROC    NDEV_REF   NDEV_IOCTL NDEV_BUFFER
+ * ---------------------------------------------------------------------------
+ * | DEV_IOCTL3  |minor dev  | proc nr   |  fd       |  command  | buf ptr   |
+ * |-------------+-----------+-----------+-----------+-----------+-----------|
+ *
+ *    m_type      NDEV_MINOR   NDEV_PROC    NDEV_REF   NDEV_OPERATION
+ * -------------------------------------------------------------------|
+ * | DEV_CANCEL  |minor dev  | proc nr   |  fd       | which operation|
+ * |-------------+-----------+-----------+-----------+----------------|
+ *
+ * Replies:
+ *
+ *    m_type        REP_PROC_NR   REP_STATUS   REP_REF    REP_OPERATION
+ * ----------------------------------------------------------------------|
+ * | DEVICE_REPLY |   proc nr   |  status    |  fd     | which operation |
+ * |--------------+-------------+------------+---------+-----------------|
+ */
+
+#include "inet.h"
+
+#ifndef __minix_vmd /* Minix 3 */
+#include <sys/select.h>
+#endif
+#include <sys/svrctl.h>
+#include <minix/callnr.h>
+
+#include "mq.h"
+#include "qp.h"
+#include "proto.h"
+#include "generic/type.h"
+
+#include "generic/assert.h"
+#include "generic/buf.h"
+#include "generic/event.h"
+#include "generic/sr.h"
+#include "sr_int.h"
+
+#ifndef __minix_vmd /* Minix 3 */
+#define DEV_CANCEL NW_CANCEL
+#define DEVICE_REPLY REVIVE
+#define DEV_IOCTL3 DEV_IOCTL
+#define NDEV_BUFFER ADDRESS
+#define NDEV_COUNT COUNT
+#define NDEV_IOCTL REQUEST
+#define NDEV_MINOR DEVICE
+#define NDEV_PROC IO_ENDPT
+#endif
+
+THIS_FILE
+
+PUBLIC sr_fd_t sr_fd_table[FD_NR];
+
+PRIVATE mq_t *repl_queue, *repl_queue_tail;
+#ifdef __minix_vmd
+PRIVATE cpvec_t cpvec[CPVEC_NR];
+#else /* Minix 3 */
+PRIVATE struct vir_cp_req vir_cp_req[CPVEC_NR];
+#endif
+
+FORWARD _PROTOTYPE ( int sr_open, (message *m) );
+FORWARD _PROTOTYPE ( void sr_close, (message *m) );
+FORWARD _PROTOTYPE ( int sr_rwio, (mq_t *m) );
+FORWARD _PROTOTYPE ( int sr_restart_read, (sr_fd_t *fdp) );
+FORWARD _PROTOTYPE ( int sr_restart_write, (sr_fd_t *fdp) );
+FORWARD _PROTOTYPE ( int sr_restart_ioctl, (sr_fd_t *fdp) );
+FORWARD _PROTOTYPE ( int sr_cancel, (message *m) );
+#ifndef __minix_vmd /* Minix 3 */
+FORWARD _PROTOTYPE ( int sr_select, (message *m) );
+FORWARD _PROTOTYPE ( void sr_status, (message *m) );
+#endif
+FORWARD _PROTOTYPE ( void sr_reply_, (mq_t *m, int reply, int is_revive) );
+FORWARD _PROTOTYPE ( sr_fd_t *sr_getchannel, (int minor));
+FORWARD _PROTOTYPE ( acc_t *sr_get_userdata, (int fd, vir_bytes offset,
+					vir_bytes count, int for_ioctl) );
+FORWARD _PROTOTYPE ( int sr_put_userdata, (int fd, vir_bytes offset,
+						acc_t *data, int for_ioctl) );
+#ifdef __minix_vmd 
+#define sr_select_res 0
+#else /* Minix 3 */
+FORWARD _PROTOTYPE (void sr_select_res, (int fd, unsigned ops) );
+#endif
+FORWARD _PROTOTYPE ( int sr_repl_queue, (int proc, int ref, int operation) );
+FORWARD _PROTOTYPE ( int walk_queue, (sr_fd_t *sr_fd, mq_t **q_head_ptr, 
+	mq_t **q_tail_ptr, int type, int proc_nr, int ref, int first_flag) );
+FORWARD _PROTOTYPE ( void process_req_q, (mq_t *mq, mq_t *tail, 
+							mq_t **tail_ptr) );
+FORWARD _PROTOTYPE ( void sr_event, (event_t *evp, ev_arg_t arg) );
+FORWARD _PROTOTYPE ( int cp_u2b, (int proc, char *src, acc_t **var_acc_ptr,
+								 int size) );
+FORWARD _PROTOTYPE ( int cp_b2u, (acc_t *acc_ptr, int proc, char *dest) );
+
+PUBLIC void sr_init()
+{
+	int i;
+
+	for (i=0; i<FD_NR; i++)
+	{
+		sr_fd_table[i].srf_flags= SFF_FREE;
+		ev_init(&sr_fd_table[i].srf_ioctl_ev);
+		ev_init(&sr_fd_table[i].srf_read_ev);
+		ev_init(&sr_fd_table[i].srf_write_ev);
+	}
+	repl_queue= NULL;
+}
+
+PUBLIC void sr_rec(m)
+mq_t *m;
+{
+	int result;
+	int send_reply, free_mess;
+
+	if (repl_queue)
+	{
+		if (m->mq_mess.m_type == DEV_CANCEL)
+		{
+#ifdef __minix_vmd
+			result= sr_repl_queue(m->mq_mess.NDEV_PROC,
+				m->mq_mess.NDEV_REF, 
+				m->mq_mess.NDEV_OPERATION);
+#else /* Minix 3 */
+			result= sr_repl_queue(m->mq_mess.IO_ENDPT, 0, 0);
+#endif
+			if (result)
+			{
+				mq_free(m);
+				return;	/* canceled request in queue */
+			}
+		}
+#if 0
+		else
+			sr_repl_queue(ANY, 0, 0);
+#endif
+	}
+
+	switch (m->mq_mess.m_type)
+	{
+	case DEV_OPEN:
+		result= sr_open(&m->mq_mess);
+		send_reply= 1;
+		free_mess= 1;
+		break;
+	case DEV_CLOSE:
+		sr_close(&m->mq_mess);
+		result= OK;
+		send_reply= 1;
+		free_mess= 1;
+		break;
+	case DEV_READ:
+	case DEV_WRITE:
+	case DEV_IOCTL3:
+		result= sr_rwio(m);
+		assert(result == OK || result == SUSPEND);
+		send_reply= (result == SUSPEND);
+		free_mess= 0;
+		break;
+	case DEV_CANCEL:
+		result= sr_cancel(&m->mq_mess);
+		assert(result == OK || result == EINTR);
+		send_reply= (result == EINTR);
+		free_mess= 1;
+#ifdef __minix_vmd
+		m->mq_mess.m_type= m->mq_mess.NDEV_OPERATION;
+#else /* Minix 3 */
+		m->mq_mess.m_type= 0;
+#endif
+		break;
+#ifndef __minix_vmd /* Minix 3 */
+	case DEV_SELECT:
+		result= sr_select(&m->mq_mess);
+		send_reply= 1;
+		free_mess= 1;
+		break;
+	case DEV_STATUS:
+		sr_status(&m->mq_mess);
+		send_reply= 0;
+		free_mess= 1;
+		break;
+#endif
+	default:
+		ip_panic(("unknown message, from %d, type %d",
+				m->mq_mess.m_source, m->mq_mess.m_type));
+	}
+	if (send_reply)
+	{
+		sr_reply_(m, result, FALSE /* !is_revive */);
+	}
+	if (free_mess)
+		mq_free(m);
+}
+
+PUBLIC void sr_add_minor(minor, port, openf, closef, readf, writef,
+	ioctlf, cancelf, selectf)
+int minor;
+int port;
+sr_open_t openf;
+sr_close_t closef;
+sr_read_t readf;
+sr_write_t writef;
+sr_ioctl_t ioctlf;
+sr_cancel_t cancelf;
+sr_select_t selectf;
+{
+	sr_fd_t *sr_fd;
+
+	assert (minor>=0 && minor<FD_NR);
+
+	sr_fd= &sr_fd_table[minor];
+
+	assert(!(sr_fd->srf_flags & SFF_INUSE));
+
+	sr_fd->srf_flags= SFF_INUSE | SFF_MINOR;
+	sr_fd->srf_port= port;
+	sr_fd->srf_open= openf;
+	sr_fd->srf_close= closef;
+	sr_fd->srf_write= writef;
+	sr_fd->srf_read= readf;
+	sr_fd->srf_ioctl= ioctlf;
+	sr_fd->srf_cancel= cancelf;
+	sr_fd->srf_select= selectf;
+}
+
+PRIVATE int sr_open(m)
+message *m;
+{
+	sr_fd_t *sr_fd;
+
+	int minor= m->NDEV_MINOR;
+	int i, fd;
+
+	if (minor<0 || minor>FD_NR)
+	{
+		DBLOCK(1, printf("replying EINVAL\n"));
+		return EINVAL;
+	}
+	if (!(sr_fd_table[minor].srf_flags & SFF_MINOR))
+	{
+		DBLOCK(1, printf("replying ENXIO\n"));
+		return ENXIO;
+	}
+	for (i=0; i<FD_NR && (sr_fd_table[i].srf_flags & SFF_INUSE); i++);
+
+	if (i>=FD_NR)
+	{
+		DBLOCK(1, printf("replying ENFILE\n"));
+		return ENFILE;
+	}
+
+	sr_fd= &sr_fd_table[i];
+	*sr_fd= sr_fd_table[minor];
+	sr_fd->srf_flags= SFF_INUSE;
+	fd= (*sr_fd->srf_open)(sr_fd->srf_port, i, sr_get_userdata,
+		sr_put_userdata, 0 /* no put_pkt */, sr_select_res);
+	if (fd<0)
+	{
+		sr_fd->srf_flags= SFF_FREE;
+		DBLOCK(1, printf("replying %d\n", fd));
+		return fd;
+	}
+	sr_fd->srf_fd= fd;
+	return i;
+}
+
+PRIVATE void sr_close(m)
+message *m;
+{
+	sr_fd_t *sr_fd;
+
+	sr_fd= sr_getchannel(m->NDEV_MINOR);
+	assert (sr_fd);
+
+	if (sr_fd->srf_flags & SFF_BUSY)
+		ip_panic(("close on busy channel"));
+
+	assert (!(sr_fd->srf_flags & SFF_MINOR));
+	(*sr_fd->srf_close)(sr_fd->srf_fd);
+	sr_fd->srf_flags= SFF_FREE;
+}
+
+PRIVATE int sr_rwio(m)
+mq_t *m;
+{
+	sr_fd_t *sr_fd;
+	mq_t **q_head_ptr, **q_tail_ptr;
+	int ip_flag, susp_flag, first_flag;
+	int r;
+	ioreq_t request;
+	size_t size;
+
+	sr_fd= sr_getchannel(m->mq_mess.NDEV_MINOR);
+	assert (sr_fd);
+
+	switch(m->mq_mess.m_type)
+	{
+	case DEV_READ:
+		q_head_ptr= &sr_fd->srf_read_q;
+		q_tail_ptr= &sr_fd->srf_read_q_tail;
+		ip_flag= SFF_READ_IP;
+		susp_flag= SFF_READ_SUSP;
+		first_flag= SFF_READ_FIRST;
+		break;
+	case DEV_WRITE:
+		q_head_ptr= &sr_fd->srf_write_q;
+		q_tail_ptr= &sr_fd->srf_write_q_tail;
+		ip_flag= SFF_WRITE_IP;
+		susp_flag= SFF_WRITE_SUSP;
+		first_flag= SFF_WRITE_FIRST;
+		break;
+	case DEV_IOCTL3:
+		q_head_ptr= &sr_fd->srf_ioctl_q;
+		q_tail_ptr= &sr_fd->srf_ioctl_q_tail;
+		ip_flag= SFF_IOCTL_IP;
+		susp_flag= SFF_IOCTL_SUSP;
+		first_flag= SFF_IOCTL_FIRST;
+		break;
+	default:
+		ip_panic(("illegal case entry"));
+	}
+
+	if (sr_fd->srf_flags & ip_flag)
+	{
+		assert(sr_fd->srf_flags & susp_flag);
+		assert(*q_head_ptr);
+
+		(*q_tail_ptr)->mq_next= m;
+		*q_tail_ptr= m;
+		return SUSPEND;
+	}
+	assert(!*q_head_ptr);
+
+	*q_tail_ptr= *q_head_ptr= m;
+	sr_fd->srf_flags |= ip_flag;
+	assert(!(sr_fd->srf_flags & first_flag));
+	sr_fd->srf_flags |= first_flag;
+
+	switch(m->mq_mess.m_type)
+	{
+	case DEV_READ:
+		r= (*sr_fd->srf_read)(sr_fd->srf_fd, 
+			m->mq_mess.NDEV_COUNT);
+		break;
+	case DEV_WRITE:
+		r= (*sr_fd->srf_write)(sr_fd->srf_fd, 
+			m->mq_mess.NDEV_COUNT);
+		break;
+	case DEV_IOCTL3:
+		request= m->mq_mess.NDEV_IOCTL;
+
+		/* There should be a better way to do this... */
+		if (request == NWIOQUERYPARAM)
+		{
+			r= qp_query(m->mq_mess.NDEV_PROC,
+				(vir_bytes)m->mq_mess.NDEV_BUFFER);
+			r= sr_put_userdata(sr_fd-sr_fd_table, r, NULL, 1);
+			assert(r == OK);
+			break;
+		}
+
+		/* And now, we continue with our regular program. */
+		size= (request >> 16) & _IOCPARM_MASK;
+		if (size>MAX_IOCTL_S)
+		{
+			DBLOCK(1, printf("replying EINVAL\n"));
+			r= sr_put_userdata(sr_fd-sr_fd_table, EINVAL, 
+				NULL, 1);
+			assert(r == OK);
+			assert(sr_fd->srf_flags & first_flag);
+			sr_fd->srf_flags &= ~first_flag;
+			return OK;
+		}
+		r= (*sr_fd->srf_ioctl)(sr_fd->srf_fd, request);
+		break;
+	default:
+		ip_panic(("illegal case entry"));
+	}
+
+	assert(sr_fd->srf_flags & first_flag);
+	sr_fd->srf_flags &= ~first_flag;
+
+	assert(r == OK || r == SUSPEND || 
+		(printf("r= %d\n", r), 0));
+	if (r == SUSPEND)
+		sr_fd->srf_flags |= susp_flag;
+	else
+		mq_free(m);
+	return r;
+}
+
+PRIVATE int sr_restart_read(sr_fd)
+sr_fd_t *sr_fd;
+{
+	mq_t *mp;
+	int r;
+
+	mp= sr_fd->srf_read_q;
+	assert(mp);
+
+	if (sr_fd->srf_flags & SFF_READ_IP)
+	{
+		assert(sr_fd->srf_flags & SFF_READ_SUSP);
+		return SUSPEND;
+	}
+	sr_fd->srf_flags |= SFF_READ_IP;
+
+	r= (*sr_fd->srf_read)(sr_fd->srf_fd, 
+		mp->mq_mess.NDEV_COUNT);
+
+	assert(r == OK || r == SUSPEND || 
+		(printf("r= %d\n", r), 0));
+	if (r == SUSPEND)
+		sr_fd->srf_flags |= SFF_READ_SUSP;
+	return r;
+}
+
+PRIVATE int sr_restart_write(sr_fd)
+sr_fd_t *sr_fd;
+{
+	mq_t *mp;
+	int r;
+
+	mp= sr_fd->srf_write_q;
+	assert(mp);
+
+	if (sr_fd->srf_flags & SFF_WRITE_IP)
+	{
+		assert(sr_fd->srf_flags & SFF_WRITE_SUSP);
+		return SUSPEND;
+	}
+	sr_fd->srf_flags |= SFF_WRITE_IP;
+
+	r= (*sr_fd->srf_write)(sr_fd->srf_fd, 
+		mp->mq_mess.NDEV_COUNT);
+
+	assert(r == OK || r == SUSPEND || 
+		(printf("r= %d\n", r), 0));
+	if (r == SUSPEND)
+		sr_fd->srf_flags |= SFF_WRITE_SUSP;
+	return r;
+}
+
+PRIVATE int sr_restart_ioctl(sr_fd)
+sr_fd_t *sr_fd;
+{
+	mq_t *mp;
+	int r;
+
+	mp= sr_fd->srf_ioctl_q;
+	assert(mp);
+
+	if (sr_fd->srf_flags & SFF_IOCTL_IP)
+	{
+		assert(sr_fd->srf_flags & SFF_IOCTL_SUSP);
+		return SUSPEND;
+	}
+	sr_fd->srf_flags |= SFF_IOCTL_IP;
+
+	r= (*sr_fd->srf_ioctl)(sr_fd->srf_fd, 
+		mp->mq_mess.NDEV_COUNT);
+
+	assert(r == OK || r == SUSPEND || 
+		(printf("r= %d\n", r), 0));
+	if (r == SUSPEND)
+		sr_fd->srf_flags |= SFF_IOCTL_SUSP;
+	return r;
+}
+
+PRIVATE int sr_cancel(m)
+message *m;
+{
+	sr_fd_t *sr_fd;
+	int result;
+	int proc_nr, ref, operation;
+
+        result=EINTR;
+	proc_nr=  m->NDEV_PROC;
+#ifdef __minix_vmd
+	ref=  m->NDEV_REF;
+	operation= m->NDEV_OPERATION;
+#else /* Minix 3 */
+	ref=  0;
+	operation= 0;
+#endif
+	sr_fd= sr_getchannel(m->NDEV_MINOR);
+	assert (sr_fd);
+
+#ifdef __minix_vmd
+	if (operation == CANCEL_ANY || operation == DEV_IOCTL3)
+#endif
+	{
+		result= walk_queue(sr_fd, &sr_fd->srf_ioctl_q, 
+			&sr_fd->srf_ioctl_q_tail, SR_CANCEL_IOCTL,
+			proc_nr, ref, SFF_IOCTL_FIRST);
+		if (result != EAGAIN)
+			return result;
+	}
+#ifdef __minix_vmd
+	if (operation == CANCEL_ANY || operation == DEV_READ)
+#endif
+	{
+		result= walk_queue(sr_fd, &sr_fd->srf_read_q, 
+			&sr_fd->srf_read_q_tail, SR_CANCEL_READ,
+			proc_nr, ref, SFF_READ_FIRST);
+		if (result != EAGAIN)
+			return result;
+	}
+#ifdef __minix_vmd
+	if (operation == CANCEL_ANY || operation == DEV_WRITE)
+#endif
+	{
+		result= walk_queue(sr_fd, &sr_fd->srf_write_q, 
+			&sr_fd->srf_write_q_tail, SR_CANCEL_WRITE,
+			proc_nr, ref, SFF_WRITE_FIRST);
+		if (result != EAGAIN)
+			return result;
+	}
+#ifdef __minix_vmd
+	ip_panic((
+"request not found: from %d, type %d, MINOR= %d, PROC= %d, REF= %d OPERATION= %ld",
+		m->m_source, m->m_type, m->NDEV_MINOR,
+		m->NDEV_PROC, m->NDEV_REF, m->NDEV_OPERATION));
+#else /* Minix 3 */
+	ip_panic((
+"request not found: from %d, type %d, MINOR= %d, PROC= %d",
+		m->m_source, m->m_type, m->NDEV_MINOR,
+		m->NDEV_PROC));
+#endif
+}
+
+#ifndef __minix_vmd /* Minix 3 */
+PRIVATE int sr_select(m)
+message *m;
+{
+	sr_fd_t *sr_fd;
+	mq_t **q_head_ptr, **q_tail_ptr;
+	int ip_flag, susp_flag;
+	int r, ops;
+	unsigned m_ops, i_ops;
+	ioreq_t request;
+	size_t size;
+
+	sr_fd= sr_getchannel(m->NDEV_MINOR);
+	assert (sr_fd);
+
+	sr_fd->srf_select_proc= m->m_source;
+
+	m_ops= m->IO_ENDPT;
+	i_ops= 0;
+	if (m_ops & SEL_RD) i_ops |= SR_SELECT_READ;
+	if (m_ops & SEL_WR) i_ops |= SR_SELECT_WRITE;
+	if (m_ops & SEL_ERR) i_ops |= SR_SELECT_EXCEPTION;
+	if (!(m_ops & SEL_NOTIFY)) i_ops |= SR_SELECT_POLL;
+
+	r= (*sr_fd->srf_select)(sr_fd->srf_fd,  i_ops);
+	if (r < 0)
+		return r;
+	m_ops= 0;
+	if (r & SR_SELECT_READ) m_ops |= SEL_RD;
+	if (r & SR_SELECT_WRITE) m_ops |= SEL_WR;
+	if (r & SR_SELECT_EXCEPTION) m_ops |= SEL_ERR;
+
+	return m_ops;
+}
+
+PRIVATE void sr_status(m)
+message *m;
+{
+	int fd, result;
+	unsigned m_ops;
+	sr_fd_t *sr_fd;
+	mq_t *mq;
+
+	mq= repl_queue;
+	if (mq != NULL)
+	{
+		repl_queue= mq->mq_next;
+
+		mq->mq_mess.m_type= DEV_REVIVE;
+		result= send(mq->mq_mess.m_source, &mq->mq_mess);
+		if (result != OK)
+			ip_panic(("unable to send"));
+		mq_free(mq);
+
+		return;
+	}
+
+	for (fd=0, sr_fd= sr_fd_table; fd<FD_NR; fd++, sr_fd++)
+	{
+		if ((sr_fd->srf_flags &
+			(SFF_SELECT_R|SFF_SELECT_W|SFF_SELECT_X)) == 0)
+		{
+			/* Nothing to report */
+			continue;
+		}
+		if (sr_fd->srf_select_proc != m->m_source)
+		{
+			/* Wrong process */
+			continue;
+		}
+
+		m_ops= 0;
+		if (sr_fd->srf_flags & SFF_SELECT_R) m_ops |= SEL_RD;
+		if (sr_fd->srf_flags & SFF_SELECT_W) m_ops |= SEL_WR;
+		if (sr_fd->srf_flags & SFF_SELECT_X) m_ops |= SEL_ERR;
+
+		sr_fd->srf_flags &= ~(SFF_SELECT_R|SFF_SELECT_W|SFF_SELECT_X);
+
+		m->m_type= DEV_IO_READY;
+		m->DEV_MINOR= fd;
+		m->DEV_SEL_OPS= m_ops;
+
+		result= send(m->m_source, m);
+		if (result != OK)
+			ip_panic(("unable to send"));
+		return;
+	}
+
+	m->m_type= DEV_NO_STATUS;
+	result= send(m->m_source, m);
+	if (result != OK)
+		ip_panic(("unable to send"));
+}
+#endif
+
+PRIVATE int walk_queue(sr_fd, q_head_ptr, q_tail_ptr, type, proc_nr, ref,
+	first_flag)
+sr_fd_t *sr_fd;
+mq_t **q_head_ptr;
+mq_t **q_tail_ptr;
+int type;
+int proc_nr;
+int ref;
+int first_flag;
+{
+	mq_t *q_ptr_prv, *q_ptr;
+	int result;
+
+	for(q_ptr_prv= NULL, q_ptr= *q_head_ptr; q_ptr; 
+		q_ptr_prv= q_ptr, q_ptr= q_ptr->mq_next)
+	{
+		if (q_ptr->mq_mess.NDEV_PROC != proc_nr)
+			continue;
+#ifdef __minix_vmd
+		if (q_ptr->mq_mess.NDEV_REF != ref)
+			continue;
+#endif
+		if (!q_ptr_prv)
+		{
+			assert(!(sr_fd->srf_flags & first_flag));
+			sr_fd->srf_flags |= first_flag;
+
+			result= (*sr_fd->srf_cancel)(sr_fd->srf_fd, type);
+			assert(result == OK);
+
+			*q_head_ptr= q_ptr->mq_next;
+			mq_free(q_ptr);
+
+			assert(sr_fd->srf_flags & first_flag);
+			sr_fd->srf_flags &= ~first_flag;
+
+			return OK;
+		}
+		q_ptr_prv->mq_next= q_ptr->mq_next;
+		mq_free(q_ptr);
+		if (!q_ptr_prv->mq_next)
+			*q_tail_ptr= q_ptr_prv;
+		return EINTR;
+	}
+	return EAGAIN;
+}
+
+PRIVATE sr_fd_t *sr_getchannel(minor)
+int minor;
+{
+	sr_fd_t *loc_fd;
+
+	compare(minor, >=, 0);
+	compare(minor, <, FD_NR);
+
+	loc_fd= &sr_fd_table[minor];
+
+	assert (!(loc_fd->srf_flags & SFF_MINOR) &&
+		(loc_fd->srf_flags & SFF_INUSE));
+
+	return loc_fd;
+}
+
+PRIVATE void sr_reply_(mq, status, is_revive)
+mq_t *mq;
+int status;
+int is_revive;
+{
+	int result, proc, ref,operation;
+	message reply, *mp;
+
+	proc= mq->mq_mess.NDEV_PROC;
+#ifdef __minix_vmd
+	ref= mq->mq_mess.NDEV_REF;
+#else /* Minix 3 */
+	ref= 0;
+#endif
+	operation= mq->mq_mess.m_type;
+#ifdef __minix_vmd
+	assert(operation != DEV_CANCEL);
+#endif
+
+	if (is_revive)
+		mp= &mq->mq_mess;
+	else
+		mp= &reply;
+
+	mp->m_type= DEVICE_REPLY;
+	mp->REP_ENDPT= proc;
+	mp->REP_STATUS= status;
+#ifdef __minix_vmd
+	mp->REP_REF= ref;
+	mp->REP_OPERATION= operation;
+#endif
+	if (is_revive)
+	{
+		notify(mq->mq_mess.m_source);
+		result= ELOCKED;
+	}
+	else
+		result= send(mq->mq_mess.m_source, mp);
+
+	if (result == ELOCKED && is_revive)
+	{
+		mq->mq_next= NULL;
+		if (repl_queue)
+			repl_queue_tail->mq_next= mq;
+		else
+			repl_queue= mq;
+		repl_queue_tail= mq;
+		return;
+	}
+	if (result != OK)
+		ip_panic(("unable to send"));
+	if (is_revive)
+		mq_free(mq);
+}
+
+PRIVATE acc_t *sr_get_userdata (fd, offset, count, for_ioctl)
+int fd;
+vir_bytes offset;
+vir_bytes count;
+int for_ioctl;
+{
+	sr_fd_t *loc_fd;
+	mq_t **head_ptr, *m, *mq;
+	int ip_flag, susp_flag, first_flag;
+	int result, suspended, is_revive;
+	char *src;
+	acc_t *acc;
+	event_t *evp;
+	ev_arg_t arg;
+
+	loc_fd= &sr_fd_table[fd];
+
+	if (for_ioctl)
+	{
+		head_ptr= &loc_fd->srf_ioctl_q;
+		evp= &loc_fd->srf_ioctl_ev;
+		ip_flag= SFF_IOCTL_IP;
+		susp_flag= SFF_IOCTL_SUSP;
+		first_flag= SFF_IOCTL_FIRST;
+	}
+	else
+	{
+		head_ptr= &loc_fd->srf_write_q;
+		evp= &loc_fd->srf_write_ev;
+		ip_flag= SFF_WRITE_IP;
+		susp_flag= SFF_WRITE_SUSP;
+		first_flag= SFF_WRITE_FIRST;
+	}
+		
+assert (loc_fd->srf_flags & ip_flag);
+
+	if (!count)
+	{
+		m= *head_ptr;
+		mq= m->mq_next;
+		*head_ptr= mq;
+		result= (int)offset;
+		is_revive= !(loc_fd->srf_flags & first_flag);
+		sr_reply_(m, result, is_revive);
+		suspended= (loc_fd->srf_flags & susp_flag);
+		loc_fd->srf_flags &= ~(ip_flag|susp_flag);
+		if (suspended)
+		{
+			if (mq)
+			{
+				arg.ev_ptr= loc_fd;
+				ev_enqueue(evp, sr_event, arg);
+			}
+		}
+		return NULL;
+	}
+
+	src= (*head_ptr)->mq_mess.NDEV_BUFFER + offset;
+	result= cp_u2b ((*head_ptr)->mq_mess.NDEV_PROC, src, &acc, count);
+
+	return result<0 ? NULL : acc;
+}
+
+PRIVATE int sr_put_userdata (fd, offset, data, for_ioctl)
+int fd;
+vir_bytes offset;
+acc_t *data;
+int for_ioctl;
+{
+	sr_fd_t *loc_fd;
+	mq_t **head_ptr, *m, *mq;
+	int ip_flag, susp_flag, first_flag;
+	int result, suspended, is_revive;
+	char *dst;
+	event_t *evp;
+	ev_arg_t arg;
+
+	loc_fd= &sr_fd_table[fd];
+
+	if (for_ioctl)
+	{
+		head_ptr= &loc_fd->srf_ioctl_q;
+		evp= &loc_fd->srf_ioctl_ev;
+		ip_flag= SFF_IOCTL_IP;
+		susp_flag= SFF_IOCTL_SUSP;
+		first_flag= SFF_IOCTL_FIRST;
+	}
+	else
+	{
+		head_ptr= &loc_fd->srf_read_q;
+		evp= &loc_fd->srf_read_ev;
+		ip_flag= SFF_READ_IP;
+		susp_flag= SFF_READ_SUSP;
+		first_flag= SFF_READ_FIRST;
+	}
+		
+	assert (loc_fd->srf_flags & ip_flag);
+
+	if (!data)
+	{
+		m= *head_ptr;
+		mq= m->mq_next;
+		*head_ptr= mq;
+		result= (int)offset;
+		is_revive= !(loc_fd->srf_flags & first_flag);
+		sr_reply_(m, result, is_revive);
+		suspended= (loc_fd->srf_flags & susp_flag);
+		loc_fd->srf_flags &= ~(ip_flag|susp_flag);
+		if (suspended)
+		{
+			if (mq)
+			{
+				arg.ev_ptr= loc_fd;
+				ev_enqueue(evp, sr_event, arg);
+			}
+		}
+		return OK;
+	}
+
+	dst= (*head_ptr)->mq_mess.NDEV_BUFFER + offset;
+	return cp_b2u (data, (*head_ptr)->mq_mess.NDEV_PROC, dst);
+}
+
+#ifndef __minix_vmd /* Minix 3 */
+PRIVATE void sr_select_res(fd, ops)
+int fd;
+unsigned ops;
+{
+	sr_fd_t *sr_fd;
+
+	sr_fd= &sr_fd_table[fd];
+	
+	if (ops & SR_SELECT_READ) sr_fd->srf_flags |= SFF_SELECT_R;
+	if (ops & SR_SELECT_WRITE) sr_fd->srf_flags |= SFF_SELECT_W;
+	if (ops & SR_SELECT_EXCEPTION) sr_fd->srf_flags |= SFF_SELECT_X;
+
+	notify(sr_fd->srf_select_proc);
+}
+#endif
+
+PRIVATE void process_req_q(mq, tail, tail_ptr)
+mq_t *mq, *tail, **tail_ptr;
+{
+	mq_t *m;
+	int result;
+
+	for(;mq;)
+	{
+		m= mq;
+		mq= mq->mq_next;
+
+		result= sr_rwio(m);
+		if (result == SUSPEND)
+		{
+			if (mq)
+			{
+				(*tail_ptr)->mq_next= mq;
+				*tail_ptr= tail;
+			}
+			return;
+		}
+	}
+	return;
+}
+
+PRIVATE void sr_event(evp, arg)
+event_t *evp;
+ev_arg_t arg;
+{
+	sr_fd_t *sr_fd;
+	int r;
+
+	sr_fd= arg.ev_ptr;
+	if (evp == &sr_fd->srf_write_ev)
+	{
+		while(sr_fd->srf_write_q)
+		{
+			r= sr_restart_write(sr_fd);
+			if (r == SUSPEND)
+				return;
+		}
+		return;
+	}
+	if (evp == &sr_fd->srf_read_ev)
+	{
+		while(sr_fd->srf_read_q)
+		{
+			r= sr_restart_read(sr_fd);
+			if (r == SUSPEND)
+				return;
+		}
+		return;
+	}
+	if (evp == &sr_fd->srf_ioctl_ev)
+	{
+		while(sr_fd->srf_ioctl_q)
+		{
+			r= sr_restart_ioctl(sr_fd);
+			if (r == SUSPEND)
+				return;
+		}
+		return;
+	}
+	ip_panic(("sr_event: unkown event\n"));
+}
+
+PRIVATE int cp_u2b (proc, src, var_acc_ptr, size)
+int proc;
+char *src;
+acc_t **var_acc_ptr;
+int size;
+{
+	static message mess;
+	acc_t *acc;
+	int i;
+
+	acc= bf_memreq(size);
+
+	*var_acc_ptr= acc;
+	i=0;
+
+	while (acc)
+	{
+		size= (vir_bytes)acc->acc_length;
+
+#ifdef __minix_vmd
+		cpvec[i].cpv_src= (vir_bytes)src;
+		cpvec[i].cpv_dst= (vir_bytes)ptr2acc_data(acc);
+		cpvec[i].cpv_size= size;
+#else /* Minix 3 */
+		vir_cp_req[i].count= size;
+		vir_cp_req[i].src.proc_nr_e = proc;
+		vir_cp_req[i].src.segment = D;
+		vir_cp_req[i].src.offset = (vir_bytes) src;
+		vir_cp_req[i].dst.proc_nr_e = this_proc;
+		vir_cp_req[i].dst.segment = D;
+		vir_cp_req[i].dst.offset = (vir_bytes) ptr2acc_data(acc);
+#endif
+
+		src += size;
+		acc= acc->acc_next;
+		i++;
+
+		if (i == CPVEC_NR || acc == NULL)
+		{
+#ifdef __minix_vmd
+			mess.m_type= SYS_VCOPY;
+			mess.m1_i1= proc;
+			mess.m1_i2= this_proc;
+			mess.m1_i3= i;
+			mess.m1_p1= (char *)cpvec;
+#else /* Minix 3 */
+			mess.m_type= SYS_VIRVCOPY;
+			mess.VCP_VEC_SIZE= i;
+			mess.VCP_VEC_ADDR= (char *)vir_cp_req;
+#endif
+			if (sendrec(SYSTASK, &mess) <0)
+				ip_panic(("unable to sendrec"));
+			if (mess.m_type <0)
+			{
+				bf_afree(*var_acc_ptr);
+				*var_acc_ptr= 0;
+				return mess.m_type;
+			}
+			i= 0;
+		}
+	}
+	return OK;
+}
+
+PRIVATE int cp_b2u (acc_ptr, proc, dest)
+acc_t *acc_ptr;
+int proc;
+char *dest;
+{
+	static message mess;
+	acc_t *acc;
+	int i, size;
+
+	acc= acc_ptr;
+	i=0;
+
+	while (acc)
+	{
+		size= (vir_bytes)acc->acc_length;
+
+		if (size)
+		{
+#ifdef __minix_vmd
+			cpvec[i].cpv_src= (vir_bytes)ptr2acc_data(acc);
+			cpvec[i].cpv_dst= (vir_bytes)dest;
+			cpvec[i].cpv_size= size;
+#else /* Minix 3 */
+			vir_cp_req[i].src.proc_nr_e = this_proc;
+			vir_cp_req[i].src.segment = D;
+			vir_cp_req[i].src.offset= (vir_bytes)ptr2acc_data(acc);
+			vir_cp_req[i].dst.proc_nr_e = proc;
+			vir_cp_req[i].dst.segment = D;
+			vir_cp_req[i].dst.offset= (vir_bytes)dest;
+			vir_cp_req[i].count= size;
+#endif
+			i++;
+		}
+
+		dest += size;
+		acc= acc->acc_next;
+
+		if (i == CPVEC_NR || acc == NULL)
+		{
+#ifdef __minix_vmd
+			mess.m_type= SYS_VCOPY;
+			mess.m1_i1= this_proc;
+			mess.m1_i2= proc;
+			mess.m1_i3= i;
+			mess.m1_p1= (char *)cpvec;
+#else /* Minix 3 */
+			mess.m_type= SYS_VIRVCOPY;
+			mess.VCP_VEC_SIZE= i;
+			mess.VCP_VEC_ADDR= (char *) vir_cp_req;
+#endif
+			if (sendrec(SYSTASK, &mess) <0)
+				ip_panic(("unable to sendrec"));
+			if (mess.m_type <0)
+			{
+				bf_afree(acc_ptr);
+				return mess.m_type;
+			}
+			i= 0;
+		}
+	}
+	bf_afree(acc_ptr);
+	return OK;
+}
+
+PRIVATE int sr_repl_queue(proc, ref, operation)
+int proc;
+int ref;
+int operation;
+{
+	mq_t *m, *m_cancel, *m_tmp;
+	int result;
+
+	m_cancel= NULL;
+
+	for (m= repl_queue; m;)
+	{
+#ifdef __minix_vmd
+		if (m->mq_mess.REP_ENDPT == proc && 
+			m->mq_mess.REP_REF ==ref &&
+			(m->mq_mess.REP_OPERATION == operation ||
+				operation == CANCEL_ANY))
+#else /* Minix 3 */
+		if (m->mq_mess.REP_ENDPT == proc)
+#endif
+		{
+assert(!m_cancel);
+			m_cancel= m;
+			m= m->mq_next;
+			continue;
+		}
+		result= send(m->mq_mess.m_source, &m->mq_mess);
+		if (result != OK)
+			ip_panic(("unable to send: %d", result));
+		m_tmp= m;
+		m= m->mq_next;
+		mq_free(m_tmp);
+	}
+	repl_queue= NULL;
+	if (m_cancel)
+	{
+		result= send(m_cancel->mq_mess.m_source, &m_cancel->mq_mess);
+		if (result != OK)
+			ip_panic(("unable to send: %d", result));
+		mq_free(m_cancel);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * $PchId: sr.c,v 1.17 2005/06/28 14:26:16 philip Exp $
+ */
Index: /trunk/minix/servers/inet/sr_int.h
===================================================================
--- /trunk/minix/servers/inet/sr_int.h	(revision 9)
+++ /trunk/minix/servers/inet/sr_int.h	(revision 9)
@@ -0,0 +1,54 @@
+/*
+inet/sr_int.h
+
+SR internals
+
+Created:	Aug 2004 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+#define FD_NR			(16*IP_PORT_MAX)
+
+typedef struct sr_fd
+{
+	int srf_flags;
+	int srf_fd;
+	int srf_port;
+	int srf_select_proc;
+	sr_open_t srf_open;
+	sr_close_t srf_close;
+	sr_write_t srf_write;
+	sr_read_t srf_read;
+	sr_ioctl_t srf_ioctl;
+	sr_cancel_t srf_cancel;
+	sr_select_t srf_select;
+	mq_t *srf_ioctl_q, *srf_ioctl_q_tail;
+	mq_t *srf_read_q, *srf_read_q_tail;
+	mq_t *srf_write_q, *srf_write_q_tail;
+	event_t srf_ioctl_ev;
+	event_t srf_read_ev;
+	event_t srf_write_ev;
+} sr_fd_t;
+
+#	define SFF_FREE		  0x00
+#	define SFF_MINOR	  0x01
+#	define SFF_INUSE	  0x02
+#define SFF_BUSY		  0x1C
+#	define SFF_IOCTL_IP	  0x04
+#	define SFF_READ_IP	  0x08
+#	define SFF_WRITE_IP	  0x10
+#define SFF_SUSPENDED	0x1C0
+#	define SFF_IOCTL_SUSP	  0x40
+#	define SFF_READ_SUSP	  0x80
+#	define SFF_WRITE_SUSP	 0x100
+#define SFF_IOCTL_FIRST		 0x200
+#define SFF_READ_FIRST		 0x400
+#define SFF_WRITE_FIRST		 0x800
+#define SFF_SELECT_R		0x1000
+#define SFF_SELECT_W		0x2000
+#define SFF_SELECT_X		0x4000
+
+EXTERN sr_fd_t sr_fd_table[FD_NR];
+
+/*
+ * $PchId: sr_int.h,v 1.2 2005/06/28 14:28:17 philip Exp $
+ */
Index: /trunk/minix/servers/inet/stacktrace.c
===================================================================
--- /trunk/minix/servers/inet/stacktrace.c	(revision 9)
+++ /trunk/minix/servers/inet/stacktrace.c	(revision 9)
@@ -0,0 +1,35 @@
+/*
+stacktrace.c
+
+Created:	Jan 19, 1993 by Philip Homburg
+
+Copyright 1995 Philip Homburg
+*/
+
+#include "inet.h"
+
+PUBLIC void stacktrace()
+{
+	typedef unsigned int reg_t;
+	reg_t bp, pc, hbp;
+	extern reg_t get_bp ARGS(( void ));
+
+	bp= get_bp();
+	while(bp)
+	{
+		pc= ((reg_t *)bp)[1];
+		hbp= ((reg_t *)bp)[0];
+		printf("0x%lx ", (unsigned long)pc);
+		if (hbp != 0 && hbp <= bp)
+		{
+			printf("???");
+			break;
+		}
+		bp= hbp;
+	}
+	printf("\n");
+}
+
+/*
+ * $PchId: stacktrace.c,v 1.6 1996/05/07 21:11:34 philip Exp $
+ */
Index: /trunk/minix/servers/inet/version.c
===================================================================
--- /trunk/minix/servers/inet/version.c	(revision 9)
+++ /trunk/minix/servers/inet/version.c	(revision 9)
@@ -0,0 +1,11 @@
+/*
+version.c
+*/
+
+#include "inet.h"
+
+char version[]= "inet 0.79, last compiled on " __DATE__ " " __TIME__;
+
+/*
+ * $PchId: version.c,v 1.54 2005/06/28 14:35:01 philip Exp $
+ */
Index: /trunk/minix/servers/init/.depend
===================================================================
--- /trunk/minix/servers/init/.depend	(revision 9)
+++ /trunk/minix/servers/init/.depend	(revision 9)
@@ -0,0 +1,23 @@
+
+init.o:	/usr/include/ansi.h
+init.o:	/usr/include/errno.h
+init.o:	/usr/include/fcntl.h
+init.o:	/usr/include/limits.h
+init.o:	/usr/include/minix/dmap.h
+init.o:	/usr/include/minix/ioctl.h
+init.o:	/usr/include/minix/ipc.h
+init.o:	/usr/include/minix/sys_config.h
+init.o:	/usr/include/minix/type.h
+init.o:	/usr/include/signal.h
+init.o:	/usr/include/stdlib.h
+init.o:	/usr/include/string.h
+init.o:	/usr/include/sys/dir.h
+init.o:	/usr/include/sys/stat.h
+init.o:	/usr/include/sys/svrctl.h
+init.o:	/usr/include/sys/types.h
+init.o:	/usr/include/sys/wait.h
+init.o:	/usr/include/time.h
+init.o:	/usr/include/ttyent.h
+init.o:	/usr/include/unistd.h
+init.o:	/usr/include/utmp.h
+init.o:	init.c
Index: /trunk/minix/servers/init/Makefile
===================================================================
--- /trunk/minix/servers/init/Makefile	(revision 9)
+++ /trunk/minix/servers/init/Makefile	(revision 9)
@@ -0,0 +1,38 @@
+# Makefile for the init program (INIT)
+SERVER = init
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+h = $i/minix
+k = $u/src/kernel
+
+# programs, flags, etc.
+CC =	exec cc
+CFLAGS = -I$i -O -D_MINIX -D_POSIX_SOURCE
+LDFLAGS = -i
+
+OBJ = 	init.o
+
+# build local binary
+all build:	$(SERVER)
+$(SERVER):	$(OBJ)
+	$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(OBJ) -lsysutil
+	install -S 192w $@
+
+# install with other servers
+install:	/usr/sbin/$(SERVER)
+/usr/sbin/$(SERVER):	$(SERVER)
+	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f $(SERVER) *.o *.bak 
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/servers/init/init.c
===================================================================
--- /trunk/minix/servers/init/init.c	(revision 9)
+++ /trunk/minix/servers/init/init.c	(revision 9)
@@ -0,0 +1,460 @@
+/* This process is the father (mother) of all Minix user processes.  When
+ * Minix comes up, this is process number 2, and has a pid of 1.  It
+ * executes the /etc/rc shell file, and then reads the /etc/ttytab file to
+ * determine which terminals need a login process.
+ *
+ * If the files /usr/adm/wtmp and /etc/utmp exist and are writable, init
+ * (with help from login) will maintain login accounting.  Sending a
+ * signal 1 (SIGHUP) to init will cause it to rescan /etc/ttytab and start
+ * up new shell processes if necessary.  It will not, however, kill off
+ * login processes for lines that have been turned off; do this manually.
+ * Signal 15 (SIGTERM) makes init stop spawning new processes, this is
+ * used by shutdown and friends when they are about to close the system
+ * down.
+ */
+
+#include <minix/type.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/svrctl.h>
+#include <ttyent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utmp.h>
+
+/* Command to execute as a response to the three finger salute. */
+char *REBOOT_CMD[] =	{ "shutdown", "now", "CTRL-ALT-DEL", NULL };
+
+/* Associated fake ttytab entry. */
+struct ttyent TT_REBOOT = { "console", "-", REBOOT_CMD, NULL };
+
+char PATH_UTMP[] = "/etc/utmp";		/* current logins */
+char PATH_WTMP[] = "/usr/adm/wtmp";	/* login/logout history */
+
+#define PIDSLOTS	32		/* first this many ttys can be on */
+
+struct slotent {
+  int errct;			/* error count */
+  pid_t pid;			/* pid of login process for this tty line */
+};
+
+#define ERRCT_DISABLE	10	/* disable after this many errors */
+#define NO_PID	0		/* pid value indicating no process */
+
+struct slotent slots[PIDSLOTS];	/* init table of ttys and pids */
+
+int gothup = 0;			/* flag, showing signal 1 was received */
+int gotabrt = 0;		/* flag, showing signal 6 was received */
+int spawn = 1;			/* flag, spawn processes only when set */
+
+void tell(int fd, char *s);
+void report(int fd, char *label);
+void wtmp(int type, int linenr, char *line, pid_t pid);
+void startup(int linenr, struct ttyent *ttyp);
+int execute(char **cmd);
+void onhup(int sig);
+void onterm(int sig);
+void onabrt(int sig);
+
+int main(void)
+{
+  pid_t pid;			/* pid of child process */
+  int fd;			/* generally useful */
+  int linenr;			/* loop variable */
+  int check;			/* check if a new process must be spawned */
+  struct slotent *slotp;	/* slots[] pointer */
+  struct ttyent *ttyp;		/* ttytab entry */
+  struct sigaction sa;
+  struct stat stb;
+
+  if (fstat(0, &stb) < 0) {
+	/* Open standard input, output & error. */
+	(void) open("/dev/null", O_RDONLY);
+	(void) open("/dev/log", O_WRONLY);
+	dup(1);
+  }
+
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = 0;
+
+  /* Hangup: Reexamine /etc/ttytab for newly enabled terminal lines. */
+  sa.sa_handler = onhup;
+  sigaction(SIGHUP, &sa, NULL);
+
+  /* Terminate: Stop spawning login processes, shutdown is near. */
+  sa.sa_handler = onterm;
+  sigaction(SIGTERM, &sa, NULL);
+
+  /* Abort: Sent by the kernel on CTRL-ALT-DEL; shut the system down. */
+  sa.sa_handler = onabrt;
+  sigaction(SIGABRT, &sa, NULL);
+
+  /* Execute the /etc/rc file. */
+  if ((pid = fork()) != 0) {
+	/* Parent just waits. */
+	while (wait(NULL) != pid) {
+		if (gotabrt) reboot(RBT_HALT);
+	}
+  } else {
+#if ! SYS_GETKENV
+	struct sysgetenv sysgetenv;
+#endif
+	char bootopts[16];
+	static char *rc_command[] = { "sh", "/etc/rc", NULL, NULL, NULL };
+	char **rcp = rc_command + 2;
+
+	/* Get the boot options from the boot environment. */
+	sysgetenv.key = "bootopts";
+	sysgetenv.keylen = 8+1;
+	sysgetenv.val = bootopts;
+	sysgetenv.vallen = sizeof(bootopts);
+	if (svrctl(MMGETPARAM, &sysgetenv) == 0) *rcp++ = bootopts;
+	*rcp = "start";
+
+	execute(rc_command);
+	report(2, "sh /etc/rc");
+	_exit(1);	/* impossible, we hope */
+  }
+
+  /* Clear /etc/utmp if it exists. */
+  if ((fd = open(PATH_UTMP, O_WRONLY | O_TRUNC)) >= 0) close(fd);
+
+  /* Log system reboot. */
+  wtmp(BOOT_TIME, 0, NULL, 0);
+
+  /* Main loop. If login processes have already been started up, wait for one
+   * to terminate, or for a HUP signal to arrive. Start up new login processes
+   * for all ttys which don't have them. Note that wait() also returns when
+   * somebody's orphan dies, in which case ignore it.  If the TERM signal is
+   * sent then stop spawning processes, shutdown time is near.
+   */
+
+  check = 1;
+  while (1) {
+	while ((pid = waitpid(-1, NULL, check ? WNOHANG : 0)) > 0) {
+		/* Search to see which line terminated. */
+		for (linenr = 0; linenr < PIDSLOTS; linenr++) {
+			slotp = &slots[linenr];
+			if (slotp->pid == pid) {
+				/* Record process exiting. */
+				wtmp(DEAD_PROCESS, linenr, NULL, pid);
+				slotp->pid = NO_PID;
+				check = 1;
+			}
+		}
+	}
+
+	/* If a signal 1 (SIGHUP) is received, simply reset error counts. */
+	if (gothup) {
+		gothup = 0;
+		for (linenr = 0; linenr < PIDSLOTS; linenr++) {
+			slots[linenr].errct = 0;
+		}
+		check = 1;
+	}
+
+	/* Shut down on signal 6 (SIGABRT). */
+	if (gotabrt) {
+		gotabrt = 0;
+		startup(0, &TT_REBOOT);
+	}
+
+	if (spawn && check) {
+		/* See which lines need a login process started up. */
+		for (linenr = 0; linenr < PIDSLOTS; linenr++) {
+			slotp = &slots[linenr];
+			if ((ttyp = getttyent()) == NULL) break;
+
+			if (ttyp->ty_getty != NULL
+				&& ttyp->ty_getty[0] != NULL
+				&& slotp->pid == NO_PID
+				&& slotp->errct < ERRCT_DISABLE)
+			{
+				startup(linenr, ttyp);
+			}
+		}
+		endttyent();
+	}
+	check = 0;
+  }
+}
+
+void onhup(int sig)
+{
+  gothup = 1;
+  spawn = 1;
+}
+
+void onterm(int sig)
+{
+  spawn = 0;
+}
+
+void onabrt(int sig)
+{
+  static int count;
+
+  if (++count == 2) reboot(RBT_HALT);
+  gotabrt = 1;
+}
+
+void startup(int linenr, struct ttyent *ttyp)
+{
+  /* Fork off a process for the indicated line. */
+
+  struct slotent *slotp;		/* pointer to ttyslot */
+  pid_t pid;				/* new pid */
+  int err[2];				/* error reporting pipe */
+  char line[32];			/* tty device name */
+  int status;
+
+  slotp = &slots[linenr];
+
+  /* Error channel for between fork and exec. */
+  if (pipe(err) < 0) err[0] = err[1] = -1;
+
+  if ((pid = fork()) == -1 ) {
+	report(2, "fork()");
+	sleep(10);
+	return;
+  }
+
+  if (pid == 0) {
+	/* Child */
+	close(err[0]);
+	fcntl(err[1], F_SETFD, fcntl(err[1], F_GETFD) | FD_CLOEXEC);
+
+	/* A new session. */
+	setsid();
+
+	/* Construct device name. */
+	strcpy(line, "/dev/");
+	strncat(line, ttyp->ty_name, sizeof(line) - 6);
+
+	/* Open the line for standard input and output. */
+	close(0);
+	close(1);
+	if (open(line, O_RDWR) < 0 || dup(0) < 0) {
+		write(err[1], &errno, sizeof(errno));
+		_exit(1);
+	}
+
+	if (ttyp->ty_init != NULL && ttyp->ty_init[0] != NULL) {
+		/* Execute a command to initialize the terminal line. */
+
+		if ((pid = fork()) == -1) {
+			report(2, "fork()");
+			errno= 0;
+			write(err[1], &errno, sizeof(errno));
+			_exit(1);
+		}
+
+		if (pid == 0) {
+			alarm(10);
+			execute(ttyp->ty_init);
+			report(2, ttyp->ty_init[0]);
+			_exit(1);
+		}
+
+		while (waitpid(pid, &status, 0) != pid) {}
+		if (status != 0) {
+			tell(2, "init: ");
+			tell(2, ttyp->ty_name);
+			tell(2, ": ");
+			tell(2, ttyp->ty_init[0]);
+			tell(2, ": bad exit status\n");
+			errno = 0;
+			write(err[1], &errno, sizeof(errno));
+			_exit(1);
+		}
+	}
+
+	/* Redirect standard error too. */
+	dup2(0, 2);
+
+	/* Execute the getty process. */
+	execute(ttyp->ty_getty);
+
+	/* Oops, disaster strikes. */
+	fcntl(2, F_SETFL, fcntl(2, F_GETFL) | O_NONBLOCK);
+	if (linenr != 0) report(2, ttyp->ty_getty[0]);
+	write(err[1], &errno, sizeof(errno));
+	_exit(1);
+  }
+
+  /* Parent */
+  if (ttyp != &TT_REBOOT) slotp->pid = pid;
+
+  close(err[1]);
+  if (read(err[0], &errno, sizeof(errno)) != 0) {
+	/* If an errno value goes down the error pipe: Problems. */
+
+	switch (errno) {
+	case ENOENT:
+	case ENODEV:
+	case ENXIO:
+		/* Device nonexistent, no driver, or no minor device. */
+		slotp->errct = ERRCT_DISABLE;
+		close(err[0]);
+		return;
+	case 0:
+		/* Error already reported. */
+		break;
+	default:
+		/* Any other error on the line. */
+		report(2, ttyp->ty_name);
+	}
+	close(err[0]);
+
+	if (++slotp->errct >= ERRCT_DISABLE) {
+		tell(2, "init: ");
+		tell(2, ttyp->ty_name);
+		tell(2, ": excessive errors, shutting down\n");
+	} else {
+		sleep(5);
+	}
+	return;
+  }
+  close(err[0]);
+
+  if (ttyp != &TT_REBOOT) wtmp(LOGIN_PROCESS, linenr, ttyp->ty_name, pid);
+  slotp->errct = 0;
+}
+
+int execute(char **cmd)
+{
+  /* Execute a command with a path search along /sbin:/bin:/usr/sbin:/usr/bin.
+   */
+  static char *nullenv[] = { NULL };
+  char command[128];
+  char *path[] = { "/sbin", "/bin", "/usr/sbin", "/usr/bin" };
+  int i;
+
+  if (cmd[0][0] == '/') {
+	/* A full path. */
+	return execve(cmd[0], cmd, nullenv);
+  }
+
+  /* Path search. */
+  for (i = 0; i < 4; i++) {
+	if (strlen(path[i]) + 1 + strlen(cmd[0]) + 1 > sizeof(command)) {
+		errno= ENAMETOOLONG;
+		return -1;
+	}
+	strcpy(command, path[i]);
+	strcat(command, "/");
+	strcat(command, cmd[0]);
+	execve(command, cmd, nullenv);
+	if (errno != ENOENT) break;
+  }
+  return -1;
+}
+
+void wtmp(type, linenr, line, pid)
+int type;			/* type of entry */
+int linenr;			/* line number in ttytab */
+char *line;			/* tty name (only good on login) */
+pid_t pid;			/* pid of process */
+{
+/* Log an event into the UTMP and WTMP files. */
+
+  struct utmp utmp;		/* UTMP/WTMP User Accounting */
+  int fd;
+
+  /* Clear the utmp record. */
+  memset((void *) &utmp, 0, sizeof(utmp));
+
+  /* Fill in utmp. */
+  switch (type) {
+  case BOOT_TIME:
+	/* Make a special reboot record. */
+	strcpy(utmp.ut_name, "reboot");
+	strcpy(utmp.ut_line, "~");
+	break;
+
+  case LOGIN_PROCESS:
+  	/* A new login, fill in line name. */
+	strncpy(utmp.ut_line, line, sizeof(utmp.ut_line));
+	break;
+
+  case DEAD_PROCESS:
+	/* A logout.  Use the current utmp entry, but make sure it is a
+	 * user process exiting, and not getty or login giving up.
+	 */
+	if ((fd = open(PATH_UTMP, O_RDONLY)) < 0) {
+		if (errno != ENOENT) report(2, PATH_UTMP);
+		return;
+	}
+	if (lseek(fd, (off_t) (linenr+1) * sizeof(utmp), SEEK_SET) == -1
+		|| read(fd, &utmp, sizeof(utmp)) == -1
+	) {
+		report(2, PATH_UTMP);
+		close(fd);
+		return;
+	}
+	close(fd);
+	if (utmp.ut_type != USER_PROCESS) return;
+	strncpy(utmp.ut_name, "", sizeof(utmp.ut_name));
+	break;
+  }
+
+  /* Finish new utmp entry. */
+  utmp.ut_pid = pid;
+  utmp.ut_type = type;
+  utmp.ut_time = time((time_t *) 0);
+
+  switch (type) {
+  case LOGIN_PROCESS:
+  case DEAD_PROCESS:
+	/* Write new entry to utmp. */
+	if ((fd = open(PATH_UTMP, O_WRONLY)) < 0
+		|| lseek(fd, (off_t) (linenr+1) * sizeof(utmp), SEEK_SET) == -1
+		|| write(fd, &utmp, sizeof(utmp)) == -1
+	) {
+		if (errno != ENOENT) report(2, PATH_UTMP);
+	}
+	if (fd != -1) close(fd);
+	break;
+  }
+
+  switch (type) {
+  case BOOT_TIME:
+  case DEAD_PROCESS:
+	/* Add new wtmp entry. */
+	if ((fd = open(PATH_WTMP, O_WRONLY | O_APPEND)) < 0
+		  || write(fd, &utmp, sizeof(utmp)) == -1
+	) {
+		if (errno != ENOENT) report(2, PATH_WTMP);
+	}
+	if (fd != -1) close(fd);
+	break;
+  }
+}
+
+void tell(fd, s)
+int fd;
+char *s;
+{
+	write(fd, s, strlen(s));
+}
+
+void report(fd, label)
+int fd;
+char *label;
+{
+	int err = errno;
+
+	tell(fd, "init: ");
+	tell(fd, label);
+	tell(fd, ": ");
+	tell(fd, strerror(err));
+	tell(fd, "\n");
+	errno= err;
+}
Index: /trunk/minix/servers/is/.depend
===================================================================
--- /trunk/minix/servers/is/.depend	(revision 9)
+++ /trunk/minix/servers/is/.depend	(revision 9)
@@ -0,0 +1,212 @@
+
+dmp.o:	/usr/include/ansi.h
+dmp.o:	/usr/include/errno.h
+dmp.o:	/usr/include/limits.h
+dmp.o:	/usr/include/minix/bitmap.h
+dmp.o:	/usr/include/minix/callnr.h
+dmp.o:	/usr/include/minix/com.h
+dmp.o:	/usr/include/minix/config.h
+dmp.o:	/usr/include/minix/const.h
+dmp.o:	/usr/include/minix/devio.h
+dmp.o:	/usr/include/minix/ipc.h
+dmp.o:	/usr/include/minix/keymap.h
+dmp.o:	/usr/include/minix/sys_config.h
+dmp.o:	/usr/include/minix/syslib.h
+dmp.o:	/usr/include/minix/sysutil.h
+dmp.o:	/usr/include/minix/type.h
+dmp.o:	/usr/include/signal.h
+dmp.o:	/usr/include/stdio.h
+dmp.o:	/usr/include/stdlib.h
+dmp.o:	/usr/include/string.h
+dmp.o:	/usr/include/sys/dir.h
+dmp.o:	/usr/include/sys/types.h
+dmp.o:	/usr/include/unistd.h
+dmp.o:	dmp.c
+dmp.o:	glo.h
+dmp.o:	inc.h
+dmp.o:	proto.h
+
+dmp_ds.o:	../ds/store.h
+dmp_ds.o:	/usr/include/ansi.h
+dmp_ds.o:	/usr/include/errno.h
+dmp_ds.o:	/usr/include/limits.h
+dmp_ds.o:	/usr/include/minix/bitmap.h
+dmp_ds.o:	/usr/include/minix/callnr.h
+dmp_ds.o:	/usr/include/minix/com.h
+dmp_ds.o:	/usr/include/minix/config.h
+dmp_ds.o:	/usr/include/minix/const.h
+dmp_ds.o:	/usr/include/minix/devio.h
+dmp_ds.o:	/usr/include/minix/ipc.h
+dmp_ds.o:	/usr/include/minix/keymap.h
+dmp_ds.o:	/usr/include/minix/sys_config.h
+dmp_ds.o:	/usr/include/minix/syslib.h
+dmp_ds.o:	/usr/include/minix/sysutil.h
+dmp_ds.o:	/usr/include/minix/type.h
+dmp_ds.o:	/usr/include/signal.h
+dmp_ds.o:	/usr/include/stdio.h
+dmp_ds.o:	/usr/include/stdlib.h
+dmp_ds.o:	/usr/include/string.h
+dmp_ds.o:	/usr/include/sys/dir.h
+dmp_ds.o:	/usr/include/sys/types.h
+dmp_ds.o:	/usr/include/unistd.h
+dmp_ds.o:	dmp_ds.c
+dmp_ds.o:	glo.h
+dmp_ds.o:	inc.h
+dmp_ds.o:	proto.h
+
+dmp_fs.o:	../fs/const.h
+dmp_fs.o:	../fs/fproc.h
+dmp_fs.o:	/usr/include/ansi.h
+dmp_fs.o:	/usr/include/errno.h
+dmp_fs.o:	/usr/include/limits.h
+dmp_fs.o:	/usr/include/minix/bitmap.h
+dmp_fs.o:	/usr/include/minix/callnr.h
+dmp_fs.o:	/usr/include/minix/com.h
+dmp_fs.o:	/usr/include/minix/config.h
+dmp_fs.o:	/usr/include/minix/const.h
+dmp_fs.o:	/usr/include/minix/devio.h
+dmp_fs.o:	/usr/include/minix/dmap.h
+dmp_fs.o:	/usr/include/minix/ipc.h
+dmp_fs.o:	/usr/include/minix/keymap.h
+dmp_fs.o:	/usr/include/minix/sys_config.h
+dmp_fs.o:	/usr/include/minix/syslib.h
+dmp_fs.o:	/usr/include/minix/sysutil.h
+dmp_fs.o:	/usr/include/minix/type.h
+dmp_fs.o:	/usr/include/signal.h
+dmp_fs.o:	/usr/include/stdio.h
+dmp_fs.o:	/usr/include/stdlib.h
+dmp_fs.o:	/usr/include/string.h
+dmp_fs.o:	/usr/include/sys/dir.h
+dmp_fs.o:	/usr/include/sys/select.h
+dmp_fs.o:	/usr/include/sys/time.h
+dmp_fs.o:	/usr/include/sys/types.h
+dmp_fs.o:	/usr/include/unistd.h
+dmp_fs.o:	dmp_fs.c
+dmp_fs.o:	glo.h
+dmp_fs.o:	inc.h
+dmp_fs.o:	proto.h
+
+dmp_kernel.o:	../../kernel/config.h
+dmp_kernel.o:	../../kernel/const.h
+dmp_kernel.o:	../../kernel/debug.h
+dmp_kernel.o:	../../kernel/ipc.h
+dmp_kernel.o:	../../kernel/priv.h
+dmp_kernel.o:	../../kernel/proc.h
+dmp_kernel.o:	../../kernel/protect.h
+dmp_kernel.o:	../../kernel/type.h
+dmp_kernel.o:	/usr/include/ansi.h
+dmp_kernel.o:	/usr/include/errno.h
+dmp_kernel.o:	/usr/include/ibm/bios.h
+dmp_kernel.o:	/usr/include/ibm/cpu.h
+dmp_kernel.o:	/usr/include/ibm/interrupt.h
+dmp_kernel.o:	/usr/include/ibm/ports.h
+dmp_kernel.o:	/usr/include/limits.h
+dmp_kernel.o:	/usr/include/minix/bitmap.h
+dmp_kernel.o:	/usr/include/minix/callnr.h
+dmp_kernel.o:	/usr/include/minix/com.h
+dmp_kernel.o:	/usr/include/minix/config.h
+dmp_kernel.o:	/usr/include/minix/const.h
+dmp_kernel.o:	/usr/include/minix/devio.h
+dmp_kernel.o:	/usr/include/minix/endpoint.h
+dmp_kernel.o:	/usr/include/minix/ipc.h
+dmp_kernel.o:	/usr/include/minix/keymap.h
+dmp_kernel.o:	/usr/include/minix/sys_config.h
+dmp_kernel.o:	/usr/include/minix/syslib.h
+dmp_kernel.o:	/usr/include/minix/sysutil.h
+dmp_kernel.o:	/usr/include/minix/type.h
+dmp_kernel.o:	/usr/include/signal.h
+dmp_kernel.o:	/usr/include/stdio.h
+dmp_kernel.o:	/usr/include/stdlib.h
+dmp_kernel.o:	/usr/include/string.h
+dmp_kernel.o:	/usr/include/sys/dir.h
+dmp_kernel.o:	/usr/include/sys/types.h
+dmp_kernel.o:	/usr/include/timers.h
+dmp_kernel.o:	/usr/include/unistd.h
+dmp_kernel.o:	dmp_kernel.c
+dmp_kernel.o:	glo.h
+dmp_kernel.o:	inc.h
+dmp_kernel.o:	proto.h
+
+dmp_pm.o:	../pm/mproc.h
+dmp_pm.o:	/usr/include/ansi.h
+dmp_pm.o:	/usr/include/errno.h
+dmp_pm.o:	/usr/include/limits.h
+dmp_pm.o:	/usr/include/minix/bitmap.h
+dmp_pm.o:	/usr/include/minix/callnr.h
+dmp_pm.o:	/usr/include/minix/com.h
+dmp_pm.o:	/usr/include/minix/config.h
+dmp_pm.o:	/usr/include/minix/const.h
+dmp_pm.o:	/usr/include/minix/devio.h
+dmp_pm.o:	/usr/include/minix/ipc.h
+dmp_pm.o:	/usr/include/minix/keymap.h
+dmp_pm.o:	/usr/include/minix/sys_config.h
+dmp_pm.o:	/usr/include/minix/syslib.h
+dmp_pm.o:	/usr/include/minix/sysutil.h
+dmp_pm.o:	/usr/include/minix/type.h
+dmp_pm.o:	/usr/include/signal.h
+dmp_pm.o:	/usr/include/stdio.h
+dmp_pm.o:	/usr/include/stdlib.h
+dmp_pm.o:	/usr/include/string.h
+dmp_pm.o:	/usr/include/sys/dir.h
+dmp_pm.o:	/usr/include/sys/types.h
+dmp_pm.o:	/usr/include/timers.h
+dmp_pm.o:	/usr/include/unistd.h
+dmp_pm.o:	dmp_pm.c
+dmp_pm.o:	glo.h
+dmp_pm.o:	inc.h
+dmp_pm.o:	proto.h
+
+dmp_rs.o:	../rs/manager.h
+dmp_rs.o:	/usr/include/ansi.h
+dmp_rs.o:	/usr/include/errno.h
+dmp_rs.o:	/usr/include/limits.h
+dmp_rs.o:	/usr/include/minix/bitmap.h
+dmp_rs.o:	/usr/include/minix/callnr.h
+dmp_rs.o:	/usr/include/minix/com.h
+dmp_rs.o:	/usr/include/minix/config.h
+dmp_rs.o:	/usr/include/minix/const.h
+dmp_rs.o:	/usr/include/minix/devio.h
+dmp_rs.o:	/usr/include/minix/ipc.h
+dmp_rs.o:	/usr/include/minix/keymap.h
+dmp_rs.o:	/usr/include/minix/sys_config.h
+dmp_rs.o:	/usr/include/minix/syslib.h
+dmp_rs.o:	/usr/include/minix/sysutil.h
+dmp_rs.o:	/usr/include/minix/type.h
+dmp_rs.o:	/usr/include/signal.h
+dmp_rs.o:	/usr/include/stdio.h
+dmp_rs.o:	/usr/include/stdlib.h
+dmp_rs.o:	/usr/include/string.h
+dmp_rs.o:	/usr/include/sys/dir.h
+dmp_rs.o:	/usr/include/sys/types.h
+dmp_rs.o:	/usr/include/unistd.h
+dmp_rs.o:	dmp_rs.c
+dmp_rs.o:	glo.h
+dmp_rs.o:	inc.h
+dmp_rs.o:	proto.h
+
+main.o:	/usr/include/ansi.h
+main.o:	/usr/include/errno.h
+main.o:	/usr/include/limits.h
+main.o:	/usr/include/minix/bitmap.h
+main.o:	/usr/include/minix/callnr.h
+main.o:	/usr/include/minix/com.h
+main.o:	/usr/include/minix/config.h
+main.o:	/usr/include/minix/const.h
+main.o:	/usr/include/minix/devio.h
+main.o:	/usr/include/minix/ipc.h
+main.o:	/usr/include/minix/keymap.h
+main.o:	/usr/include/minix/sys_config.h
+main.o:	/usr/include/minix/syslib.h
+main.o:	/usr/include/minix/sysutil.h
+main.o:	/usr/include/minix/type.h
+main.o:	/usr/include/signal.h
+main.o:	/usr/include/stdio.h
+main.o:	/usr/include/stdlib.h
+main.o:	/usr/include/string.h
+main.o:	/usr/include/sys/dir.h
+main.o:	/usr/include/sys/types.h
+main.o:	/usr/include/unistd.h
+main.o:	glo.h
+main.o:	inc.h
+main.o:	main.c
+main.o:	proto.h
Index: /trunk/minix/servers/is/Makefile
===================================================================
--- /trunk/minix/servers/is/Makefile	(revision 9)
+++ /trunk/minix/servers/is/Makefile	(revision 9)
@@ -0,0 +1,41 @@
+# Makefile for Information Server (IS)
+SERVER = is
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+k = $u/src/kernel
+p = $u/src/servers/pm
+f = $u/src/servers/fs
+
+# programs, flags, etc.
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsys -lsysutil 
+
+OBJ = main.o dmp.o dmp_kernel.o dmp_pm.o dmp_fs.o dmp_rs.o dmp_ds.o 
+
+# build local binary
+all build:	$(SERVER)
+$(SERVER):	$(OBJ)
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+#	install -S 256w $@
+
+# install with other servers
+install:	$(SERVER)
+	install -o root -c $? /sbin/$(SERVER) 
+
+# clean up local files
+clean:
+	rm -f $(SERVER) *.o *.bak 
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/servers/is/dmp.c
===================================================================
--- /trunk/minix/servers/is/dmp.c	(revision 9)
+++ /trunk/minix/servers/is/dmp.c	(revision 9)
@@ -0,0 +1,102 @@
+/* This file contains information dump procedures. During the initialization 
+ * of the Information Service 'known' function keys are registered at the TTY
+ * server in order to receive a notification if one is pressed. Here, the 
+ * corresponding dump procedure is called.  
+ *
+ * The entry points into this file are
+ *   handle_fkey:	handle a function key pressed notification
+ */
+
+#include "inc.h"
+
+/* Define hooks for the debugging dumps. This table maps function keys
+ * onto a specific dump and provides a description for it.
+ */
+#define NHOOKS 18
+
+struct hook_entry {
+	int key;
+	void (*function)(void);
+	char *name;
+} hooks[NHOOKS] = {
+	{ F1, 	proctab_dmp, "Kernel process table" },
+	{ F2,   memmap_dmp, "Process memory maps" },
+	{ F3,	image_dmp, "System image" },
+	{ F4,	privileges_dmp, "Process privileges" },
+	{ F5,	monparams_dmp, "Boot monitor parameters" },
+	{ F6,	irqtab_dmp, "IRQ hooks and policies" },
+	{ F7,	kmessages_dmp, "Kernel messages" },
+	{ F9,	sched_dmp, "Scheduling queues" },
+	{ F10,	kenv_dmp, "Kernel parameters" },
+	{ F11,	timing_dmp, "Timing details (if enabled)" },
+	{ SF1,	mproc_dmp, "Process manager process table" },
+	{ SF2,	sigaction_dmp, "Signals" },
+	{ SF3,	fproc_dmp, "Filesystem process table" },
+	{ SF4,	dtab_dmp, "Device/Driver mapping" },
+	{ SF5,	mapping_dmp, "Print key mappings" },
+	{ SF6,	rproc_dmp, "Reincarnation server process table" },
+	{ SF7,  holes_dmp, "Memory free list" },
+	{ SF8,  data_store_dmp, "Data store contents" },
+};
+
+/*===========================================================================*
+ *				handle_fkey				     *
+ *===========================================================================*/
+#define pressed(k) ((F1<=(k)&&(k)<=F12 && bit_isset(m->FKEY_FKEYS,((k)-F1+1)))\
+  	|| (SF1<=(k) && (k)<=SF12 && bit_isset(m->FKEY_SFKEYS, ((k)-SF1+1)))) 
+PUBLIC int do_fkey_pressed(m)
+message *m;					/* notification message */
+{
+  int s, h;
+
+  /* The notification message does not convey any information, other
+   * than that some function keys have been pressed. Ask TTY for details.
+   */
+  m->m_type = FKEY_CONTROL;
+  m->FKEY_REQUEST = FKEY_EVENTS;
+  if (OK != (s=sendrec(TTY_PROC_NR, m)))
+      report("IS", "warning, sendrec to TTY failed", s);
+
+  /* Now check which keys were pressed: F1-F12, SF1-SF12. */
+  for(h=0; h < NHOOKS; h++)
+      if(pressed(hooks[h].key))
+          hooks[h].function();
+
+  /* Don't send a reply message. */
+  return(EDONTREPLY);
+}
+
+/*===========================================================================*
+ *				key_name				     *
+ *===========================================================================*/
+PRIVATE char *key_name(int key)
+{
+	static char name[15];
+
+	if(key >= F1 && key <= F12)
+		sprintf(name, " F%d", key - F1 + 1);
+	else if(key >= SF1 && key <= SF12)
+		sprintf(name, "Shift+F%d", key - SF1 + 1);
+	else
+		sprintf(name, "?");
+	return name;
+}
+
+
+/*===========================================================================*
+ *				mapping_dmp				     *
+ *===========================================================================*/
+PUBLIC void mapping_dmp(void)
+{
+  int h;
+
+  printf("Function key mappings for debug dumps in IS server.\n");
+  printf("        Key   Description\n");
+  printf("-------------------------------------");
+  printf("------------------------------------\n");
+
+  for(h=0; h < NHOOKS; h++)
+      printf(" %10s.  %s\n", key_name(hooks[h].key), hooks[h].name);
+  printf("\n");
+}
+
Index: /trunk/minix/servers/is/dmp_ds.c
===================================================================
--- /trunk/minix/servers/is/dmp_ds.c	(revision 9)
+++ /trunk/minix/servers/is/dmp_ds.c	(revision 9)
@@ -0,0 +1,60 @@
+/* This file contains procedures to dump DS data structures.
+ *
+ * The entry points into this file are
+ *   data_store_dmp:   	display DS data store contents 
+ *
+ * Created:
+ *   Oct 18, 2005:	by Jorrit N. Herder
+ */
+
+#include "inc.h"
+#include "../ds/store.h"
+
+PUBLIC struct data_store store[NR_DS_KEYS];
+
+FORWARD _PROTOTYPE( char *s_flags_str, (int flags)		);
+
+/*===========================================================================*
+ *				data_store_dmp				     *
+ *===========================================================================*/
+PUBLIC void data_store_dmp()
+{
+  struct data_store *dsp;
+  int i,j, n=0;
+  static int prev_i=0;
+
+
+  printf("Data Store (DS) contents dump\n");
+
+  getsysinfo(DS_PROC_NR, SI_DATA_STORE, store);
+
+  printf("-slot- -key- -flags- -val_l1- -val_l2-\n");
+
+  for (i=prev_i; i<NR_DS_KEYS; i++) {
+  	dsp = &store[i];
+  	if (! dsp->ds_flags & DS_IN_USE) continue;
+  	if (++n > 22) break;
+  	printf("%3d %8d %s  [%8d] [%8d] \n",
+		i, dsp->ds_key,
+		s_flags_str(dsp->ds_flags),
+		dsp->ds_val_l1,
+		dsp->ds_val_l2
+  	);
+  }
+  if (i >= NR_DS_KEYS) i = 0;
+  else printf("--more--\r");
+  prev_i = i;
+}
+
+
+PRIVATE char *s_flags_str(int flags)
+{
+	static char str[5];
+	str[0] = (flags & DS_IN_USE) ? 'U' : '-';
+	str[1] = (flags & DS_PUBLIC) ? 'P' : '-';
+	str[2] = '-';
+	str[3] = '\0';
+
+	return(str);
+}
+
Index: /trunk/minix/servers/is/dmp_fs.c
===================================================================
--- /trunk/minix/servers/is/dmp_fs.c	(revision 9)
+++ /trunk/minix/servers/is/dmp_fs.c	(revision 9)
@@ -0,0 +1,82 @@
+/* This file contains procedures to dump to FS' data structures.
+ *
+ * The entry points into this file are
+ *   dtab_dump:   	display device <-> driver mappings	  
+ *   fproc_dump:   	display FS process table	  
+ *
+ * Created:
+ *   Oct 01, 2004:	by Jorrit N. Herder
+ */
+
+#include "inc.h"
+#include "../fs/const.h"
+#include "../fs/fproc.h"
+#include <minix/dmap.h>
+
+PUBLIC struct fproc fproc[NR_PROCS];
+PUBLIC struct dmap dmap[NR_DEVICES];
+
+/*===========================================================================*
+ *				fproc_dmp				     *
+ *===========================================================================*/
+PUBLIC void fproc_dmp()
+{
+  struct fproc *fp;
+  int i, n=0;
+  static int prev_i;
+
+  getsysinfo(FS_PROC_NR, SI_PROC_TAB, fproc);
+
+  printf("File System (FS) process table dump\n");
+  printf("-nr- -pid- -tty- -umask- --uid-- --gid-- -ldr- -sus-rev-proc- -cloexec-\n");
+  for (i=prev_i; i<NR_PROCS; i++) {
+  	fp = &fproc[i];
+  	if (fp->fp_pid <= 0) continue;
+  	if (++n > 22) break;
+  	printf("%3d  %4d  %2d/%d  0x%05x %2d (%d)  %2d (%d)  %3d   %3d %3d %4d    0x%05x\n",
+  		i, fp->fp_pid, 
+  		((fp->fp_tty>>MAJOR)&BYTE), ((fp->fp_tty>>MINOR)&BYTE), 
+  		fp->fp_umask,
+  		fp->fp_realuid, fp->fp_effuid, fp->fp_realgid, fp->fp_effgid,
+  		fp->fp_sesldr,
+  		fp->fp_suspended, fp->fp_revived, fp->fp_task,
+  		fp->fp_cloexec
+  	);
+  }
+  if (i >= NR_PROCS) i = 0;
+  else printf("--more--\r");
+  prev_i = i;
+}
+
+/*===========================================================================*
+ *				dmap_flags				     *
+ *===========================================================================*/
+PRIVATE char * dmap_flags(int flags)
+{
+	static char fl[10];
+	strcpy(fl, "---");
+	if(flags & DMAP_MUTABLE) fl[0] = 'M';
+	if(flags & DMAP_BUSY)    fl[1] = 'S';
+	if(flags & DMAP_BABY)    fl[2] = 'B';
+	return fl;
+}
+
+/*===========================================================================*
+ *				dtab_dmp				     *
+ *===========================================================================*/
+PUBLIC void dtab_dmp()
+{
+    int i;
+
+    getsysinfo(FS_PROC_NR, SI_DMAP_TAB, dmap);
+    
+    printf("File System (FS) device <-> driver mappings\n");
+    printf("Major  Driver ept  Flags\n");
+    printf("-----  ----------  -----\n");
+    for (i=0; i<NR_DEVICES; i++) {
+        if (dmap[i].dmap_driver == NONE) continue;
+        printf("%5d  %10d  %s\n",
+		i, dmap[i].dmap_driver, dmap_flags(dmap[i].dmap_flags));
+    }
+}
+
Index: /trunk/minix/servers/is/dmp_kernel.c
===================================================================
--- /trunk/minix/servers/is/dmp_kernel.c	(revision 9)
+++ /trunk/minix/servers/is/dmp_kernel.c	(revision 9)
@@ -0,0 +1,559 @@
+/* Debugging dump procedures for the kernel. */
+
+#include "inc.h"
+#include <timers.h>
+#include <ibm/interrupt.h>
+#include <minix/endpoint.h>
+#include "../../kernel/const.h"
+#include "../../kernel/config.h"
+#include "../../kernel/debug.h"
+#include "../../kernel/type.h"
+#include "../../kernel/proc.h"
+#include "../../kernel/ipc.h"
+
+#define click_to_round_k(n) \
+	((unsigned) ((((unsigned long) (n) << CLICK_SHIFT) + 512) / 1024))
+
+/* Declare some local dump procedures. */
+FORWARD _PROTOTYPE( char *proc_name, (int proc_nr)		);
+FORWARD _PROTOTYPE( char *s_traps_str, (int flags)		);
+FORWARD _PROTOTYPE( char *s_flags_str, (int flags)		);
+FORWARD _PROTOTYPE( char *p_rts_flags_str, (int flags)		);
+
+/* Some global data that is shared among several dumping procedures. 
+ * Note that the process table copy has the same name as in the kernel
+ * so that most macros and definitions from proc.h also apply here.
+ */
+PUBLIC struct proc proc[NR_TASKS + NR_PROCS];
+PUBLIC struct priv priv[NR_SYS_PROCS];
+PUBLIC struct boot_image image[NR_BOOT_PROCS];
+
+/*===========================================================================*
+ *				timing_dmp				     *
+ *===========================================================================*/
+PUBLIC void timing_dmp()
+{
+#if ! DEBUG_TIME_LOCKS
+  printf("Enable the DEBUG_TIME_LOCKS definition in src/kernel/config.h\n");
+#else
+  static struct lock_timingdata timingdata[TIMING_CATEGORIES];
+  int r, c, f, skipped = 0, printed = 0, maxlines = 23, x = 0;
+  static int offsetlines = 0;
+
+  if ((r = sys_getlocktimings(&timingdata[0])) != OK) {
+      report("IS","warning: couldn't get copy of lock timings", r);
+      return;
+  } 
+
+  for(c = 0; c < TIMING_CATEGORIES; c++) {
+	int b;
+	if (!timingdata[c].lock_timings_range[0] || !timingdata[c].binsize)
+		continue;
+	x = printf("%-*s: misses %lu, resets %lu, measurements %lu: ",
+	TIMING_NAME, timingdata[c].names,
+		timingdata[c].misses,
+		timingdata[c].resets,
+		timingdata[c].measurements);
+	for(b = 0; b < TIMING_POINTS; b++) {
+		int w;
+		if (!timingdata[c].lock_timings[b])
+			continue;
+		x += (w = printf(" %5d: %5d", timingdata[c].lock_timings_range[0] +
+			b*timingdata[c].binsize,
+			timingdata[c].lock_timings[b]));
+	 	if (x + w >= 80) { printf("\n"); x = 0; }
+	}
+  	if (x > 0) printf("\n");
+  }
+#endif
+}
+
+/*===========================================================================*
+ *				kmessages_dmp				     *
+ *===========================================================================*/
+PUBLIC void kmessages_dmp()
+{
+  struct kmessages kmess;		/* get copy of kernel messages */
+  char print_buf[KMESS_BUF_SIZE+1];	/* this one is used to print */
+  int start;				/* calculate start of messages */
+  int r;
+
+  /* Try to get a copy of the kernel messages. */
+  if ((r = sys_getkmessages(&kmess)) != OK) {
+      report("IS","warning: couldn't get copy of kmessages", r);
+      return;
+  }
+
+  /* Try to print the kernel messages. First determine start and copy the
+   * buffer into a print-buffer. This is done because the messages in the
+   * copy may wrap (the kernel buffer is circular).
+   */
+  start = ((kmess.km_next + KMESS_BUF_SIZE) - kmess.km_size) % KMESS_BUF_SIZE;
+  r = 0;
+  while (kmess.km_size > 0) {
+  	print_buf[r] = kmess.km_buf[(start+r) % KMESS_BUF_SIZE];
+  	r ++;
+  	kmess.km_size --;
+  }
+  print_buf[r] = 0;		/* make sure it terminates */
+  printf("Dump of all messages generated by the kernel.\n\n"); 
+  printf("%s", print_buf);		/* print the messages */
+}
+
+/*===========================================================================*
+ *				monparams_dmp				     *
+ *===========================================================================*/
+PUBLIC void monparams_dmp()
+{
+  char val[1024];
+  char *e;
+  int r;
+
+  /* Try to get a copy of the boot monitor parameters. */
+  if ((r = sys_getmonparams(val, sizeof(val))) != OK) {
+      report("IS","warning: couldn't get copy of monitor params", r);
+      return;
+  }
+
+  /* Append new lines to the result. */
+  e = val;
+  do {
+	e += strlen(e);
+	*e++ = '\n';
+  } while (*e != 0); 
+
+  /* Finally, print the result. */
+  printf("Dump of kernel environment strings set by boot monitor.\n");
+  printf("\n%s\n", val);
+}
+
+/*===========================================================================*
+ *				irqtab_dmp				     *
+ *===========================================================================*/
+PUBLIC void irqtab_dmp()
+{
+  int i,r;
+  struct irq_hook irq_hooks[NR_IRQ_HOOKS];
+  int irq_actids[NR_IRQ_VECTORS];
+  struct irq_hook *e;	/* irq tab entry */
+  char *irq[] = {
+  	"clock",	/* 00 */
+  	"keyboard",	/* 01 */
+  	"cascade",	/* 02 */
+  	"rs232",	/* 03 */
+  	"rs232",	/* 04 */
+  	"NIC(eth)",	/* 05 */
+  	"floppy",	/* 06 */
+  	"printer",	/* 07 */
+  	"",	/* 08 */
+  	"",	/* 09 */
+  	"",	/* 10 */
+  	"",	/* 11 */
+  	"",	/* 12 */
+  	"",	/* 13 */
+  	"at_wini_0",	/* 14 */
+  	"at_wini_1",	/* 15 */
+  };
+
+  if ((r = sys_getirqhooks(irq_hooks)) != OK) {
+      report("IS","warning: couldn't get copy of irq hooks", r);
+      return;
+  }
+  if ((r = sys_getirqactids(irq_actids)) != OK) {
+      report("IS","warning: couldn't get copy of irq mask", r);
+      return;
+  }
+
+#if 0
+  printf("irq_actids:");
+  for (i= 0; i<NR_IRQ_VECTORS; i++)
+	printf(" [%d] = 0x%08x", i, irq_actids[i]);
+  printf("\n");
+#endif
+
+  printf("IRQ policies dump shows use of kernel's IRQ hooks.\n");
+  printf("-h.id- -proc.nr- -IRQ vector (nr.)- -policy- -notify id-\n");
+  for (i=0; i<NR_IRQ_HOOKS; i++) {
+  	e = &irq_hooks[i];
+  	printf("%3d", i);
+  	if (e->proc_nr_e==NONE) {
+  	    printf("    <unused>\n");
+  	    continue;
+  	}
+  	printf("%10d  ", e->proc_nr_e); 
+  	printf("    %9.9s (%02d) ", irq[e->irq], e->irq); 
+  	printf("  %s", (e->policy & IRQ_REENABLE) ? "reenable" : "    -   ");
+  	printf("   %d", e->notify_id);
+	if (irq_actids[e->irq] & (1 << i))
+		printf("masked");
+	printf("\n");
+  }
+  printf("\n");
+}
+
+/*===========================================================================*
+ *				image_dmp				     *
+ *===========================================================================*/
+PUBLIC void image_dmp()
+{
+  int m, i,j,r;
+  struct boot_image *ip;
+  static char ipc_to[BITCHUNK_BITS*2];
+	
+  if ((r = sys_getimage(image)) != OK) {
+      report("IS","warning: couldn't get copy of image table", r);
+      return;
+  }
+  printf("Image table dump showing all processes included in system image.\n");
+  printf("---name-- -nr- -flags- -traps- -sq- ----pc- -stack- -ipc_to[0]--------\n");
+  for (m=0; m<NR_BOOT_PROCS; m++) { 
+      ip = &image[m];
+        for (i=j=0; i < BITCHUNK_BITS; i++, j++) {
+       	    ipc_to[j] = (ip->ipc_to & (1<<i)) ? '1' : '0';
+       	    if (i % 8 == 7) ipc_to[++j] = ' ';
+       	}
+        ipc_to[j] = '\0';
+      printf("%8s %4d   %s   %s  %3d %7lu %7lu   %s\n",
+          ip->proc_name, ip->proc_nr, 
+	       s_flags_str(ip->flags), s_traps_str(ip->trap_mask), 
+	ip->priority, (long)ip->initial_pc, ip->stksize, ipc_to); 
+  }
+  printf("\n");
+}
+
+/*===========================================================================*
+ *				sched_dmp    				     *
+ *===========================================================================*/
+PUBLIC void sched_dmp()
+{
+  struct proc *rdy_head[NR_SCHED_QUEUES];
+  struct kinfo kinfo;
+  register struct proc *rp;
+  vir_bytes ptr_diff;
+  int r;
+
+  /* First obtain a scheduling information. */
+  if ((r = sys_getschedinfo(proc, rdy_head)) != OK) {
+      report("IS","warning: couldn't get copy of process table", r);
+      return;
+  }
+  /* Then obtain kernel addresses to correct pointer information. */
+  if ((r = sys_getkinfo(&kinfo)) != OK) {
+      report("IS","warning: couldn't get kernel addresses", r);
+      return;
+  }
+
+  /* Update all pointers. Nasty pointer algorithmic ... */
+  ptr_diff = (vir_bytes) proc - (vir_bytes) kinfo.proc_addr;
+  for (r=0;r<NR_SCHED_QUEUES; r++)
+      if (rdy_head[r] != NIL_PROC)
+          rdy_head[r] = 
+              (struct proc *)((vir_bytes) rdy_head[r] + ptr_diff);
+  for (rp=BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++)
+      if (rp->p_nextready != NIL_PROC)
+          rp->p_nextready =
+               (struct proc *)((vir_bytes) rp->p_nextready + ptr_diff);
+
+  /* Now show scheduling queues. */
+  printf("Dumping scheduling queues.\n");
+
+  for (r=0;r<NR_SCHED_QUEUES; r++) {
+      rp = rdy_head[r];
+      if (!rp) continue;
+      printf("%2d: ", r);
+      while (rp != NIL_PROC) {
+          printf("%3d ", rp->p_nr);
+          rp = rp->p_nextready;
+      }
+      printf("\n");
+  }
+  printf("\n");
+}
+
+/*===========================================================================*
+ *				kenv_dmp				     *
+ *===========================================================================*/
+PUBLIC void kenv_dmp()
+{
+    struct kinfo kinfo;
+    struct machine machine;
+    int r;
+    if ((r = sys_getkinfo(&kinfo)) != OK) {
+    	report("IS","warning: couldn't get copy of kernel info struct", r);
+    	return;
+    }
+    if ((r = sys_getmachine(&machine)) != OK) {
+    	report("IS","warning: couldn't get copy of kernel machine struct", r);
+    	return;
+    }
+
+    printf("Dump of kinfo and machine structures.\n\n");
+    printf("Machine structure:\n");
+    printf("- pc_at:      %3d\n", machine.pc_at); 
+    printf("- ps_mca:     %3d\n", machine.ps_mca); 
+    printf("- processor:  %3d\n", machine.processor); 
+    printf("- protected:  %3d\n", machine.prot); 
+    printf("- vdu_ega:    %3d\n", machine.vdu_ega); 
+    printf("- vdu_vga:    %3d\n\n", machine.vdu_vga); 
+    printf("Kernel info structure:\n");
+    printf("- code_base:  %5u\n", kinfo.code_base); 
+    printf("- code_size:  %5u\n", kinfo.code_size); 
+    printf("- data_base:  %5u\n", kinfo.data_base); 
+    printf("- data_size:  %5u\n", kinfo.data_size); 
+    printf("- proc_addr:  %5u\n", kinfo.proc_addr); 
+    printf("- kmem_base:  %5u\n", kinfo.kmem_base); 
+    printf("- kmem_size:  %5u\n", kinfo.kmem_size); 
+    printf("- bootdev_base:  %5u\n", kinfo.bootdev_base); 
+    printf("- bootdev_size:  %5u\n", kinfo.bootdev_size); 
+    printf("- ramdev_base:   %5u\n", kinfo.ramdev_base); 
+    printf("- ramdev_size:   %5u\n", kinfo.ramdev_size); 
+    printf("- params_base:   %5u\n", kinfo.params_base); 
+    printf("- params_size:   %5u\n", kinfo.params_size); 
+    printf("- nr_procs:     %3u\n", kinfo.nr_procs); 
+    printf("- nr_tasks:     %3u\n", kinfo.nr_tasks); 
+    printf("- release:      %.6s\n", kinfo.release); 
+    printf("- version:      %.6s\n", kinfo.version); 
+#if DEBUG_LOCK_CHECK
+    printf("- relocking:    %d\n", kinfo.relocking); 
+#endif
+    printf("\n");
+}
+
+PRIVATE char *s_flags_str(int flags)
+{
+	static char str[10];
+	str[0] = (flags & PREEMPTIBLE) ? 'P' : '-';
+	str[1] = '-';
+	str[2] = (flags & BILLABLE)    ? 'B' : '-';
+	str[3] = (flags & SYS_PROC)    ? 'S' : '-';
+	str[4] = '-';
+	str[5] = '\0';
+
+	return str;
+}
+
+PRIVATE char *s_traps_str(int flags)
+{
+	static char str[10];
+	str[0] = (flags & (1 << ECHO)) ? 'E' : '-';
+	str[1] = (flags & (1 << SEND))  ? 'S' : '-';
+	str[2] = (flags & (1 << RECEIVE))  ? 'R' : '-';
+	str[3] = (flags & (1 << SENDREC))  ? 'B' : '-';
+	str[4] = (flags & (1 << NOTIFY)) ? 'N' : '-';
+	str[5] = '\0';
+
+	return str;
+}
+
+/*===========================================================================*
+ *				privileges_dmp 				     *
+ *===========================================================================*/
+PUBLIC void privileges_dmp()
+{
+  register struct proc *rp;
+  static struct proc *oldrp = BEG_PROC_ADDR;
+  register struct priv *sp;
+  static char ipc_to[NR_SYS_PROCS + 1 + NR_SYS_PROCS/8];
+  int r, i,j, n = 0;
+
+  /* First obtain a fresh copy of the current process and system table. */
+  if ((r = sys_getprivtab(priv)) != OK) {
+      report("IS","warning: couldn't get copy of system privileges table", r);
+      return;
+  }
+  if ((r = sys_getproctab(proc)) != OK) {
+      report("IS","warning: couldn't get copy of process table", r);
+      return;
+  }
+
+  printf("\n--nr-id-name---- -flags- -traps- -ipc_to mask------------------------ \n");
+
+  for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
+	if (isemptyp(rp)) continue;
+	if (++n > 23) break;
+	if (proc_nr(rp) == IDLE) 	printf("(%2d) ", proc_nr(rp));  
+	else if (proc_nr(rp) < 0) 	printf("[%2d] ", proc_nr(rp));
+	else 				printf(" %2d  ", proc_nr(rp));
+        r = -1;
+        for (sp = &priv[0]; sp < &priv[NR_SYS_PROCS]; sp++) 
+            if (sp->s_proc_nr == rp->p_nr) { r ++; break; }
+        if (r == -1 && ! (rp->p_rts_flags & SLOT_FREE)) {
+	    sp = &priv[USER_PRIV_ID];
+        }
+	printf("(%02u) %-7.7s %s   %s  ",
+	       sp->s_id, rp->p_name,
+	       s_flags_str(sp->s_flags), s_traps_str(sp->s_trap_mask) 
+        );
+        for (i=j=0; i < NR_SYS_PROCS; i++, j++) {
+       	    ipc_to[j] = get_sys_bit(sp->s_ipc_to, i) ? '1' : '0';
+       	    if (i % 8 == 7) ipc_to[++j] = ' ';
+       	}
+        ipc_to[j] = '\0';
+
+	printf(" %s \n", ipc_to);
+  }
+  if (rp == END_PROC_ADDR) rp = BEG_PROC_ADDR; else printf("--more--\r");
+  oldrp = rp;
+
+}
+
+/*===========================================================================*
+ *				sendmask_dmp   				     *
+ *===========================================================================*/
+PUBLIC void sendmask_dmp()
+{
+  register struct proc *rp;
+  static struct proc *oldrp = BEG_PROC_ADDR;
+  int r, i,j, n = 0;
+
+  /* First obtain a fresh copy of the current process table. */
+  if ((r = sys_getproctab(proc)) != OK) {
+      report("IS","warning: couldn't get copy of process table", r);
+      return;
+  }
+
+  printf("\n\n");
+  printf("Sendmask dump for process table. User processes (*) don't have [].");
+  printf("\n");
+  printf("The rows of bits indicate to which processes each process may send.");
+  printf("\n\n");
+
+#if DEAD_CODE
+  printf("              ");
+  for (j=proc_nr(BEG_PROC_ADDR); j< INIT_PROC_NR+1; j++) {
+     printf("%3d", j);
+  }
+  printf("  *\n");
+
+  for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
+        if (isemptyp(rp)) continue;
+        if (++n > 20) break;
+
+    	printf("%8s ", rp->p_name);
+	if (proc_nr(rp) == IDLE) 	printf("(%2d) ", proc_nr(rp));  
+	else if (proc_nr(rp) < 0) 	printf("[%2d] ", proc_nr(rp));
+	else 				printf(" %2d  ", proc_nr(rp));
+
+    	for (j=proc_nr(BEG_PROC_ADDR); j<INIT_PROC_NR+2; j++) {
+    	    if (isallowed(rp->p_sendmask, j))	printf(" 1 ");
+    	    else 				printf(" 0 ");
+    	}
+        printf("\n");
+  }
+  if (rp == END_PROC_ADDR) { printf("\n"); rp = BEG_PROC_ADDR; }
+  else printf("--more--\r");
+  oldrp = rp;
+#endif
+}
+
+PRIVATE char *p_rts_flags_str(int flags)
+{
+	static char str[10];
+	str[0] = (flags & NO_MAP) ? 'M' : '-';
+	str[1] = (flags & SENDING)  ? 'S' : '-';
+	str[2] = (flags & RECEIVING)    ? 'R' : '-';
+	str[3] = (flags & SIGNALED)    ? 'I' : '-';
+	str[4] = (flags & SIG_PENDING)    ? 'P' : '-';
+	str[5] = (flags & P_STOP)    ? 'T' : '-';
+	str[6] = '\0';
+
+	return str;
+}
+
+/*===========================================================================*
+ *				proctab_dmp    				     *
+ *===========================================================================*/
+#if (CHIP == INTEL)
+PUBLIC void proctab_dmp()
+{
+/* Proc table dump */
+
+  register struct proc *rp;
+  static struct proc *oldrp = BEG_PROC_ADDR;
+  int r, n = 0;
+  phys_clicks text, data, size;
+
+  /* First obtain a fresh copy of the current process table. */
+  if ((r = sys_getproctab(proc)) != OK) {
+      report("IS","warning: couldn't get copy of process table", r);
+      return;
+  }
+
+  printf("\n-nr-----gen---endpoint--name--- -prior-quant- -user---sys----size-rts flags-\n");
+
+  for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
+	if (isemptyp(rp)) continue;
+	if (++n > 23) break;
+	text = rp->p_memmap[T].mem_phys;
+	data = rp->p_memmap[D].mem_phys;
+	size = rp->p_memmap[T].mem_len
+		+ ((rp->p_memmap[S].mem_phys + rp->p_memmap[S].mem_len) - data);
+	if (proc_nr(rp) == IDLE) 	printf("(%2d) ", proc_nr(rp));  
+	else if (proc_nr(rp) < 0) 	printf("[%2d] ", proc_nr(rp));
+	else 				printf(" %2d  ", proc_nr(rp));
+	printf(" %5d %10d ", _ENDPOINT_G(rp->p_endpoint), rp->p_endpoint);
+	printf(" %-8.8s %02u/%02u %02d/%02u %6lu%6lu %6uK %s",
+	       rp->p_name,
+	       rp->p_priority, rp->p_max_priority,
+	       rp->p_ticks_left, rp->p_quantum_size, 
+	       rp->p_user_time, rp->p_sys_time,
+	       click_to_round_k(size),
+	       p_rts_flags_str(rp->p_rts_flags));
+	if (rp->p_rts_flags & (SENDING|RECEIVING)) {
+		printf(" %-7.7s", proc_name(_ENDPOINT_P(rp->p_getfrom_e)));
+	} 
+	printf("\n");
+  }
+  if (rp == END_PROC_ADDR) rp = BEG_PROC_ADDR; else printf("--more--\r");
+  oldrp = rp;
+}
+#endif				/* (CHIP == INTEL) */
+
+/*===========================================================================*
+ *				memmap_dmp    				     *
+ *===========================================================================*/
+PUBLIC void memmap_dmp()
+{
+  register struct proc *rp;
+  static struct proc *oldrp = proc;
+  int r, n = 0;
+  phys_clicks size;
+
+  /* First obtain a fresh copy of the current process table. */
+  if ((r = sys_getproctab(proc)) != OK) {
+      report("IS","warning: couldn't get copy of process table", r);
+      return;
+  }
+
+  printf("\n-nr/name--- --pc-- --sp-- -----text----- -----data----- ----stack----- --size-\n");
+  for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
+	if (isemptyp(rp)) continue;
+	if (++n > 23) break;
+	size = rp->p_memmap[T].mem_len
+		+ ((rp->p_memmap[S].mem_phys + rp->p_memmap[S].mem_len)
+						- rp->p_memmap[D].mem_phys);
+	printf("%3d %-7.7s%7lx%7lx %4x %4x %4x %4x %4x %4x %4x %4x %4x %5uK\n",
+	       proc_nr(rp),
+	       rp->p_name,
+	       (unsigned long) rp->p_reg.pc,
+	       (unsigned long) rp->p_reg.sp,
+	       rp->p_memmap[T].mem_vir, rp->p_memmap[T].mem_phys, rp->p_memmap[T].mem_len,
+	       rp->p_memmap[D].mem_vir, rp->p_memmap[D].mem_phys, rp->p_memmap[D].mem_len,
+	       rp->p_memmap[S].mem_vir, rp->p_memmap[S].mem_phys, rp->p_memmap[S].mem_len,
+	       click_to_round_k(size));
+  }
+  if (rp == END_PROC_ADDR) rp = proc; 
+  else printf("--more--\r");
+  oldrp = rp;
+}
+
+/*===========================================================================*
+ *				proc_name    				     *
+ *===========================================================================*/
+PRIVATE char *proc_name(proc_nr)
+int proc_nr;
+{
+  if (proc_nr == ANY) return "ANY";
+  return cproc_addr(proc_nr)->p_name;
+}
+
Index: /trunk/minix/servers/is/dmp_pm.c
===================================================================
--- /trunk/minix/servers/is/dmp_pm.c	(revision 9)
+++ /trunk/minix/servers/is/dmp_pm.c	(revision 9)
@@ -0,0 +1,140 @@
+/* This file contains procedures to dump to PM' data structures.
+ *
+ * The entry points into this file are
+ *   mproc_dmp:   	display PM process table	  
+ *
+ * Created:
+ *   May 11, 2005:	by Jorrit N. Herder
+ */
+
+#include "inc.h"
+#include "../pm/mproc.h"
+#include <timers.h> 
+#include <minix/config.h> 
+#include <minix/type.h> 
+
+PUBLIC struct mproc mproc[NR_PROCS];
+
+/*===========================================================================*
+ *				mproc_dmp				     *
+ *===========================================================================*/
+PRIVATE char *flags_str(int flags)
+{
+	static char str[10];
+	str[0] = (flags & WAITING) ? 'W' : '-';
+	str[1] = (flags & ZOMBIE)  ? 'Z' : '-';
+	str[2] = (flags & PAUSED)  ? 'P' : '-';
+	str[3] = (flags & ALARM_ON)  ? 'A' : '-';
+	str[4] = (flags & TRACED)  ? 'T' : '-';
+	str[5] = (flags & STOPPED)  ? 'S' : '-';
+	str[6] = (flags & SIGSUSPENDED)  ? 'U' : '-';
+	str[7] = (flags & REPLY)  ? 'R' : '-';
+	str[8] = (flags & ONSWAP)  ? 'O' : '-';
+	str[9] = (flags & SWAPIN)  ? 'I' : '-';
+	str[10] = (flags & DONT_SWAP)  ? 'D' : '-';
+	str[11] = (flags & PRIV_PROC)  ? 'P' : '-';
+	str[12] = '\0';
+
+	return str;
+}
+
+PUBLIC void mproc_dmp()
+{
+  struct mproc *mp;
+  int i, n=0;
+  static int prev_i = 0;
+
+  printf("Process manager (PM) process table dump\n");
+
+  getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc);
+
+  printf("-process- -nr-prnt- -pid/ppid/grp- -uid--gid- -nice- -flags------\n");
+  for (i=prev_i; i<NR_PROCS; i++) {
+  	mp = &mproc[i];
+  	if (mp->mp_pid == 0 && i != PM_PROC_NR) continue;
+  	if (++n > 22) break;
+  	printf("%8.8s %4d%4d  %4d%4d%4d    ", 
+  		mp->mp_name, i, mp->mp_parent, mp->mp_pid, mproc[mp->mp_parent].mp_pid, mp->mp_procgrp);
+  	printf("%d(%d)  %d(%d)  ",
+  		mp->mp_realuid, mp->mp_effuid, mp->mp_realgid, mp->mp_effgid);
+  	printf(" %3d  %s  ", 
+  		mp->mp_nice, flags_str(mp->mp_flags)); 
+  	printf("\n");
+  }
+  if (i >= NR_PROCS) i = 0;
+  else printf("--more--\r");
+  prev_i = i;
+}
+
+/*===========================================================================*
+ *				sigaction_dmp				     *
+ *===========================================================================*/
+PUBLIC void sigaction_dmp()
+{
+  struct mproc *mp;
+  int i, n=0;
+  static int prev_i = 0;
+  clock_t uptime;
+
+  printf("Process manager (PM) signal action dump\n");
+
+  getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc);
+  getuptime(&uptime);
+
+  printf("-process- -nr- --ignore- --catch- --block- -tomess-- -pending-- -alarm---\n");
+  for (i=prev_i; i<NR_PROCS; i++) {
+  	mp = &mproc[i];
+  	if (mp->mp_pid == 0 && i != PM_PROC_NR) continue;
+  	if (++n > 22) break;
+  	printf("%8.8s  %3d  ", mp->mp_name, i);
+  	printf(" 0x%06x 0x%06x 0x%06x 0x%06x   ", 
+  		mp->mp_ignore, mp->mp_catch, mp->mp_sigmask, mp->mp_sig2mess); 
+  	printf("0x%06x  ", mp->mp_sigpending);
+  	if (mp->mp_flags & ALARM_ON) printf("%8u", mp->mp_timer.tmr_exp_time-uptime);
+  	else printf("       -");
+  	printf("\n");
+  }
+  if (i >= NR_PROCS) i = 0;
+  else printf("--more--\r");
+  prev_i = i;
+}
+
+/*===========================================================================*
+ *				holes_dmp				     *
+ *===========================================================================*/
+PUBLIC void holes_dmp(void)
+{
+	static struct pm_mem_info pmi;
+	int h;
+	int largest_bytes = 0, total_bytes = 0;
+
+	if(getsysinfo(PM_PROC_NR, SI_MEM_ALLOC, &pmi) != OK) {
+		printf("Obtaining memory hole list failed.\n");
+		return;
+	}
+	printf("Available memory stats\n");
+
+	for(h = 0; h < _NR_HOLES; h++) {
+		if(pmi.pmi_holes[h].h_base && pmi.pmi_holes[h].h_len) {
+			int bytes;
+			bytes = (pmi.pmi_holes[h].h_len << CLICK_SHIFT);
+			printf("%08lx: %6d kB\n",
+				pmi.pmi_holes[h].h_base << CLICK_SHIFT, bytes / 1024);
+			if(bytes > largest_bytes) largest_bytes = bytes;
+			total_bytes += bytes;
+		}
+	}
+	printf("\n"
+		"Total memory free:     %7d kB\n"
+		"Largest chunk:         %7d kB\n"
+		"Uncontiguous rest:     %7d kB (%d%% of total free)\n"
+		"Memory high watermark: %7d kB\n",
+		total_bytes/1024,
+		largest_bytes/1024,
+		(total_bytes-largest_bytes)/1024,
+		100*(total_bytes/100-largest_bytes/100)/total_bytes,
+		(pmi.pmi_hi_watermark/1024 << CLICK_SHIFT));
+
+	return;
+}
+
Index: /trunk/minix/servers/is/dmp_rs.c
===================================================================
--- /trunk/minix/servers/is/dmp_rs.c	(revision 9)
+++ /trunk/minix/servers/is/dmp_rs.c	(revision 9)
@@ -0,0 +1,62 @@
+/* This file contains procedures to dump RS data structures.
+ *
+ * The entry points into this file are
+ *   rproc_dump:   	display RS system process table	  
+ *
+ * Created:
+ *   Oct 03, 2005:	by Jorrit N. Herder
+ */
+
+#include "inc.h"
+#include "../rs/manager.h"
+
+PUBLIC struct rproc rproc[NR_SYS_PROCS];
+
+FORWARD _PROTOTYPE( char *s_flags_str, (int flags)		);
+
+/*===========================================================================*
+ *				rproc_dmp				     *
+ *===========================================================================*/
+PUBLIC void rproc_dmp()
+{
+  struct rproc *rp;
+  int i,j, n=0;
+  static int prev_i=0;
+
+  getsysinfo(RS_PROC_NR, SI_PROC_TAB, rproc);
+
+  printf("Reincarnation Server (RS) system process table dump\n");
+  printf("-----proc---pid-flag--dev- -T---checked----alive-starts-backoff-command (argc)-\n");
+  for (i=prev_i; i<NR_SYS_PROCS; i++) {
+  	rp = &rproc[i];
+  	if (! rp->r_flags & RS_IN_USE) continue;
+  	if (++n > 22) break;
+  	printf("%9d %5d %s %3d/%2d %3u %8u %8u %4dx %3d %s (%d)",
+  		rp->r_proc_nr_e, rp->r_pid, 
+		s_flags_str(rp->r_flags),
+  		rp->r_dev_nr, rp->r_dev_style,
+		rp->r_period, 
+		rp->r_check_tm, rp->r_alive_tm,
+		rp->r_restarts, rp->r_backoff,
+		rp->r_cmd,
+		rp->r_argc
+  	);
+	printf("\n");
+  }
+  if (i >= NR_SYS_PROCS) i = 0;
+  else printf("--more--\r");
+  prev_i = i;
+}
+
+
+PRIVATE char *s_flags_str(int flags)
+{
+	static char str[5];
+	str[0] = (flags & RS_IN_USE) 	 ? 'U' : '-';
+	str[1] = (flags & RS_EXITING)    ? 'E' : '-';
+	str[2] = '-';
+	str[3] = '\0';
+
+	return(str);
+}
+
Index: /trunk/minix/servers/is/glo.h
===================================================================
--- /trunk/minix/servers/is/glo.h	(revision 9)
+++ /trunk/minix/servers/is/glo.h	(revision 9)
@@ -0,0 +1,18 @@
+/* Global variables. */
+
+/* Parameters needed to keep diagnostics at IS. */
+#define DIAG_BUF_SIZE 1024
+extern char diag_buf[DIAG_BUF_SIZE];	/* buffer for messages */
+extern int diag_next;			/* next index to be written */
+extern int diag_size;			/* size of all messages */
+
+/* Flag to indicate system-wide panic. */
+extern int sys_panic;		/* if set, shutdown can be done */
+
+/* The parameters of the call are kept here. */
+extern message m_in;		/* the input message itself */
+extern message m_out;		/* the output message used for reply */
+extern int who_e;		/* caller's proc number */
+extern int callnr;		/* system call number */
+extern int dont_reply;		/* normally 0; set to 1 to inhibit reply */
+
Index: /trunk/minix/servers/is/inc.h
===================================================================
--- /trunk/minix/servers/is/inc.h	(revision 9)
+++ /trunk/minix/servers/is/inc.h	(revision 9)
@@ -0,0 +1,33 @@
+/* Header file for the system information server. 
+ *
+ * Created:
+ *    Jul 13, 2004	by Jorrit N. Herder 
+ */
+
+#define _SYSTEM            1    /* get OK and negative error codes */
+#define _MINIX             1	/* tell headers to include MINIX stuff */
+
+#include <ansi.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <errno.h>
+
+#include <minix/callnr.h>
+#include <minix/config.h>
+#include <minix/type.h>
+#include <minix/const.h>
+#include <minix/com.h>
+#include <minix/syslib.h>
+#include <minix/sysutil.h>
+#include <minix/keymap.h>
+#include <minix/bitmap.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "proto.h"
+#include "glo.h"
+
Index: /trunk/minix/servers/is/is.h
===================================================================
--- /trunk/minix/servers/is/is.h	(revision 9)
+++ /trunk/minix/servers/is/is.h	(revision 9)
@@ -0,0 +1,33 @@
+/* Header file for the system information server. 
+ *
+ * Created:
+ *    Jul 13, 2004	by Jorrit N. Herder 
+ */
+
+#define _SYSTEM            1    /* get OK and negative error codes */
+#define _MINIX             1	/* tell headers to include MINIX stuff */
+
+#include <ansi.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <errno.h>
+
+#include <minix/callnr.h>
+#include <minix/config.h>
+#include <minix/type.h>
+#include <minix/const.h>
+#include <minix/com.h>
+#include <minix/syslib.h>
+#include <minix/sysutil.h>
+#include <minix/keymap.h>
+#include <minix/bitmap.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "proto.h"
+#include "glo.h"
+
Index: /trunk/minix/servers/is/main.c
===================================================================
--- /trunk/minix/servers/is/main.c	(revision 9)
+++ /trunk/minix/servers/is/main.c	(revision 9)
@@ -0,0 +1,173 @@
+/* System Information Service. 
+ * This service handles the various debugging dumps, such as the process
+ * table, so that these no longer directly touch kernel memory. Instead, the 
+ * system task is asked to copy some table in local memory. 
+ * 
+ * Created:
+ *   Apr 29, 2004	by Jorrit N. Herder
+ */
+
+#include "inc.h"
+
+/* Set debugging level to 0, 1, or 2 to see no, some, all debug output. */
+#define DEBUG_LEVEL	1
+#define DPRINTF		if (DEBUG_LEVEL > 0) printf
+
+/* Allocate space for the global variables. */
+message m_in;		/* the input message itself */
+message m_out;		/* the output message used for reply */
+int who_e;		/* caller's proc number */
+int callnr;		/* system call number */
+
+extern int errno;	/* error number set by system library */
+
+/* Declare some local functions. */
+FORWARD _PROTOTYPE(void init_server, (int argc, char **argv)		);
+FORWARD _PROTOTYPE(void sig_handler, (void)				);
+FORWARD _PROTOTYPE(void exit_server, (void)				);
+FORWARD _PROTOTYPE(void get_work, (void)				);
+FORWARD _PROTOTYPE(void reply, (int whom, int result)			);
+
+/*===========================================================================*
+ *				main                                         *
+ *===========================================================================*/
+PUBLIC int main(int argc, char **argv)
+{
+/* This is the main routine of this service. The main loop consists of 
+ * three major activities: getting new work, processing the work, and
+ * sending the reply. The loop never terminates, unless a panic occurs.
+ */
+  int result;                 
+  sigset_t sigset;
+
+  /* Initialize the server, then go to work. */
+  init_server(argc, argv);
+
+  /* Main loop - get work and do it, forever. */         
+  while (TRUE) {              
+
+      /* Wait for incoming message, sets 'callnr' and 'who'. */
+      get_work();
+
+      switch (callnr) {
+      case SYS_SIG:
+	  printf("got SYS_SIG message\n");
+	  sigset = m_in.NOTIFY_ARG;
+	  for ( result=0; result< _NSIG; result++) {
+	      if (sigismember(&sigset, result))
+		  printf("signal %d found\n", result);
+	  }
+	  continue;
+      case PROC_EVENT:
+          sig_handler();
+          continue;
+      case FKEY_PRESSED:
+          result = do_fkey_pressed(&m_in);
+          break;
+      case DEV_PING:
+	  notify(m_in.m_source);
+	  continue;
+      default: 
+          report("IS","warning, got illegal request from:", m_in.m_source);
+          result = EINVAL;
+      }
+
+      /* Finally send reply message, unless disabled. */
+      if (result != EDONTREPLY) {
+	  reply(who_e, result);
+      }
+  }
+  return(OK);				/* shouldn't come here */
+}
+
+/*===========================================================================*
+ *				 init_server                                 *
+ *===========================================================================*/
+PRIVATE void init_server(int argc, char **argv)
+{
+/* Initialize the information service. */
+  int fkeys, sfkeys;
+  int i, s;
+  struct sigaction sigact;
+
+  /* Install signal handler. Ask PM to transform signal into message. */
+  sigact.sa_handler = SIG_MESS;
+  sigact.sa_mask = ~0;			/* block all other signals */
+  sigact.sa_flags = 0;			/* default behaviour */
+  if (sigaction(SIGTERM, &sigact, NULL) < 0) 
+      report("IS","warning, sigaction() failed", errno);
+
+  /* Set key mappings. IS takes all of F1-F12 and Shift+F1-F6. */
+  fkeys = sfkeys = 0;
+  for (i=1; i<=12; i++) bit_set(fkeys, i);
+  for (i=1; i<= 8; i++) bit_set(sfkeys, i);
+  if ((s=fkey_map(&fkeys, &sfkeys)) != OK)
+      report("IS", "warning, fkey_map failed:", s);
+}
+
+/*===========================================================================*
+ *				sig_handler                                  *
+ *===========================================================================*/
+PRIVATE void sig_handler()
+{
+  sigset_t sigset;
+  int sig;
+
+  /* Try to obtain signal set from PM. */
+  if (getsigset(&sigset) != 0) return;
+
+  /* Check for known signals. */
+  if (sigismember(&sigset, SIGTERM)) {
+      exit_server();
+  }
+}
+
+/*===========================================================================*
+ *				exit_server                                  *
+ *===========================================================================*/
+PRIVATE void exit_server()
+{
+/* Shut down the information service. */
+  int fkeys, sfkeys;
+  int i,s;
+
+  /* Release the function key mappings requested in init_server(). 
+   * IS took all of F1-F12 and Shift+F1-F6. 
+   */
+  fkeys = sfkeys = 0;
+  for (i=1; i<=12; i++) bit_set(fkeys, i);
+  for (i=1; i<= 7; i++) bit_set(sfkeys, i);
+  if ((s=fkey_unmap(&fkeys, &sfkeys)) != OK)
+      report("IS", "warning, unfkey_map failed:", s);
+
+  /* Done. Now exit. */
+  exit(0);
+}
+
+/*===========================================================================*
+ *				get_work                                     *
+ *===========================================================================*/
+PRIVATE void get_work()
+{
+    int status = 0;
+    status = receive(ANY, &m_in);   /* this blocks until message arrives */
+    if (OK != status)
+        panic("IS","failed to receive message!", status);
+    who_e = m_in.m_source;        /* message arrived! set sender */
+    callnr = m_in.m_type;       /* set function call number */
+}
+
+/*===========================================================================*
+ *				reply					     *
+ *===========================================================================*/
+PRIVATE void reply(who, result)
+int who;                           	/* destination */
+int result;                           	/* report result to replyee */
+{
+    int send_status;
+    m_out.m_type = result;  		/* build reply message */
+    send_status = send(who, &m_out);    /* send the message */
+    if (OK != send_status)
+        panic("IS", "unable to send reply!", send_status);
+}
+
Index: /trunk/minix/servers/is/proto.h
===================================================================
--- /trunk/minix/servers/is/proto.h	(revision 9)
+++ /trunk/minix/servers/is/proto.h	(revision 9)
@@ -0,0 +1,36 @@
+/* Function prototypes. */
+
+/* main.c */
+_PROTOTYPE( int  main, (int argc, char **argv)				);
+
+/* dmp.c */
+_PROTOTYPE( int do_fkey_pressed, (message *m) 				);
+_PROTOTYPE( void mapping_dmp, (void)	 				);
+
+/* dmp_kernel.c */
+_PROTOTYPE( void proctab_dmp, (void)					);
+_PROTOTYPE( void memmap_dmp, (void)					);
+_PROTOTYPE( void privileges_dmp, (void)					);
+_PROTOTYPE( void sendmask_dmp, (void)					);
+_PROTOTYPE( void image_dmp, (void)					);
+_PROTOTYPE( void irqtab_dmp, (void)					);
+_PROTOTYPE( void kmessages_dmp, (void)					);
+_PROTOTYPE( void sched_dmp, (void)					);
+_PROTOTYPE( void monparams_dmp, (void)					);
+_PROTOTYPE( void kenv_dmp, (void)					);
+_PROTOTYPE( void timing_dmp, (void)					);
+
+/* dmp_pm.c */
+_PROTOTYPE( void mproc_dmp, (void)					);
+_PROTOTYPE( void sigaction_dmp, (void)					);
+_PROTOTYPE( void holes_dmp, (void)					);
+
+/* dmp_fs.c */
+_PROTOTYPE( void dtab_dmp, (void)					);
+_PROTOTYPE( void fproc_dmp, (void)					);
+
+/* dmp_rs.c */
+_PROTOTYPE( void rproc_dmp, (void)					);
+
+/* dmp_ds.c */
+_PROTOTYPE( void data_store_dmp, (void)					);
Index: /trunk/minix/servers/pm/.depend
===================================================================
--- /trunk/minix/servers/pm/.depend	(revision 9)
+++ /trunk/minix/servers/pm/.depend	(revision 9)
@@ -0,0 +1,421 @@
+
+alloc.o:	../../kernel/config.h
+alloc.o:	../../kernel/const.h
+alloc.o:	../../kernel/type.h
+alloc.o:	/usr/include/ansi.h
+alloc.o:	/usr/include/errno.h
+alloc.o:	/usr/include/fcntl.h
+alloc.o:	/usr/include/ibm/bios.h
+alloc.o:	/usr/include/ibm/cpu.h
+alloc.o:	/usr/include/ibm/interrupt.h
+alloc.o:	/usr/include/ibm/ports.h
+alloc.o:	/usr/include/limits.h
+alloc.o:	/usr/include/minix/callnr.h
+alloc.o:	/usr/include/minix/com.h
+alloc.o:	/usr/include/minix/config.h
+alloc.o:	/usr/include/minix/const.h
+alloc.o:	/usr/include/minix/devio.h
+alloc.o:	/usr/include/minix/ipc.h
+alloc.o:	/usr/include/minix/sys_config.h
+alloc.o:	/usr/include/minix/syslib.h
+alloc.o:	/usr/include/minix/sysutil.h
+alloc.o:	/usr/include/minix/type.h
+alloc.o:	/usr/include/signal.h
+alloc.o:	/usr/include/stdlib.h
+alloc.o:	/usr/include/string.h
+alloc.o:	/usr/include/sys/dir.h
+alloc.o:	/usr/include/sys/types.h
+alloc.o:	/usr/include/timers.h
+alloc.o:	/usr/include/unistd.h
+alloc.o:	alloc.c
+alloc.o:	const.h
+alloc.o:	glo.h
+alloc.o:	mproc.h
+alloc.o:	pm.h
+alloc.o:	proto.h
+alloc.o:	type.h
+
+break.o:	/usr/include/ansi.h
+break.o:	/usr/include/errno.h
+break.o:	/usr/include/fcntl.h
+break.o:	/usr/include/limits.h
+break.o:	/usr/include/minix/config.h
+break.o:	/usr/include/minix/const.h
+break.o:	/usr/include/minix/devio.h
+break.o:	/usr/include/minix/ipc.h
+break.o:	/usr/include/minix/sys_config.h
+break.o:	/usr/include/minix/syslib.h
+break.o:	/usr/include/minix/sysutil.h
+break.o:	/usr/include/minix/type.h
+break.o:	/usr/include/signal.h
+break.o:	/usr/include/sys/dir.h
+break.o:	/usr/include/sys/types.h
+break.o:	/usr/include/timers.h
+break.o:	/usr/include/unistd.h
+break.o:	break.c
+break.o:	const.h
+break.o:	glo.h
+break.o:	mproc.h
+break.o:	param.h
+break.o:	pm.h
+break.o:	proto.h
+break.o:	type.h
+
+exec.o:	/usr/include/a.out.h
+exec.o:	/usr/include/ansi.h
+exec.o:	/usr/include/errno.h
+exec.o:	/usr/include/fcntl.h
+exec.o:	/usr/include/limits.h
+exec.o:	/usr/include/minix/callnr.h
+exec.o:	/usr/include/minix/com.h
+exec.o:	/usr/include/minix/config.h
+exec.o:	/usr/include/minix/const.h
+exec.o:	/usr/include/minix/devio.h
+exec.o:	/usr/include/minix/endpoint.h
+exec.o:	/usr/include/minix/ipc.h
+exec.o:	/usr/include/minix/sys_config.h
+exec.o:	/usr/include/minix/syslib.h
+exec.o:	/usr/include/minix/sysutil.h
+exec.o:	/usr/include/minix/type.h
+exec.o:	/usr/include/signal.h
+exec.o:	/usr/include/string.h
+exec.o:	/usr/include/sys/dir.h
+exec.o:	/usr/include/sys/stat.h
+exec.o:	/usr/include/sys/types.h
+exec.o:	/usr/include/timers.h
+exec.o:	/usr/include/unistd.h
+exec.o:	const.h
+exec.o:	exec.c
+exec.o:	glo.h
+exec.o:	mproc.h
+exec.o:	param.h
+exec.o:	pm.h
+exec.o:	proto.h
+exec.o:	type.h
+
+forkexit.o:	/usr/include/ansi.h
+forkexit.o:	/usr/include/errno.h
+forkexit.o:	/usr/include/fcntl.h
+forkexit.o:	/usr/include/limits.h
+forkexit.o:	/usr/include/minix/callnr.h
+forkexit.o:	/usr/include/minix/com.h
+forkexit.o:	/usr/include/minix/config.h
+forkexit.o:	/usr/include/minix/const.h
+forkexit.o:	/usr/include/minix/devio.h
+forkexit.o:	/usr/include/minix/ipc.h
+forkexit.o:	/usr/include/minix/sys_config.h
+forkexit.o:	/usr/include/minix/syslib.h
+forkexit.o:	/usr/include/minix/sysutil.h
+forkexit.o:	/usr/include/minix/type.h
+forkexit.o:	/usr/include/signal.h
+forkexit.o:	/usr/include/sys/dir.h
+forkexit.o:	/usr/include/sys/resource.h
+forkexit.o:	/usr/include/sys/types.h
+forkexit.o:	/usr/include/sys/wait.h
+forkexit.o:	/usr/include/timers.h
+forkexit.o:	/usr/include/unistd.h
+forkexit.o:	const.h
+forkexit.o:	forkexit.c
+forkexit.o:	glo.h
+forkexit.o:	mproc.h
+forkexit.o:	param.h
+forkexit.o:	pm.h
+forkexit.o:	proto.h
+forkexit.o:	type.h
+
+getset.o:	/usr/include/ansi.h
+getset.o:	/usr/include/errno.h
+getset.o:	/usr/include/fcntl.h
+getset.o:	/usr/include/limits.h
+getset.o:	/usr/include/minix/callnr.h
+getset.o:	/usr/include/minix/com.h
+getset.o:	/usr/include/minix/config.h
+getset.o:	/usr/include/minix/const.h
+getset.o:	/usr/include/minix/devio.h
+getset.o:	/usr/include/minix/endpoint.h
+getset.o:	/usr/include/minix/ipc.h
+getset.o:	/usr/include/minix/sys_config.h
+getset.o:	/usr/include/minix/syslib.h
+getset.o:	/usr/include/minix/sysutil.h
+getset.o:	/usr/include/minix/type.h
+getset.o:	/usr/include/signal.h
+getset.o:	/usr/include/sys/dir.h
+getset.o:	/usr/include/sys/types.h
+getset.o:	/usr/include/timers.h
+getset.o:	/usr/include/unistd.h
+getset.o:	const.h
+getset.o:	getset.c
+getset.o:	glo.h
+getset.o:	mproc.h
+getset.o:	param.h
+getset.o:	pm.h
+getset.o:	proto.h
+getset.o:	type.h
+
+main.o:	../../kernel/config.h
+main.o:	../../kernel/const.h
+main.o:	../../kernel/priv.h
+main.o:	../../kernel/proc.h
+main.o:	../../kernel/protect.h
+main.o:	../../kernel/type.h
+main.o:	/usr/include/ansi.h
+main.o:	/usr/include/errno.h
+main.o:	/usr/include/fcntl.h
+main.o:	/usr/include/ibm/bios.h
+main.o:	/usr/include/ibm/cpu.h
+main.o:	/usr/include/ibm/interrupt.h
+main.o:	/usr/include/ibm/ports.h
+main.o:	/usr/include/limits.h
+main.o:	/usr/include/minix/callnr.h
+main.o:	/usr/include/minix/com.h
+main.o:	/usr/include/minix/config.h
+main.o:	/usr/include/minix/const.h
+main.o:	/usr/include/minix/devio.h
+main.o:	/usr/include/minix/endpoint.h
+main.o:	/usr/include/minix/ipc.h
+main.o:	/usr/include/minix/keymap.h
+main.o:	/usr/include/minix/sys_config.h
+main.o:	/usr/include/minix/syslib.h
+main.o:	/usr/include/minix/sysutil.h
+main.o:	/usr/include/minix/type.h
+main.o:	/usr/include/signal.h
+main.o:	/usr/include/stdlib.h
+main.o:	/usr/include/string.h
+main.o:	/usr/include/sys/dir.h
+main.o:	/usr/include/sys/resource.h
+main.o:	/usr/include/sys/types.h
+main.o:	/usr/include/timers.h
+main.o:	/usr/include/unistd.h
+main.o:	const.h
+main.o:	glo.h
+main.o:	main.c
+main.o:	mproc.h
+main.o:	param.h
+main.o:	pm.h
+main.o:	proto.h
+main.o:	type.h
+
+misc.o:	../../kernel/config.h
+misc.o:	../../kernel/const.h
+misc.o:	../../kernel/priv.h
+misc.o:	../../kernel/proc.h
+misc.o:	../../kernel/protect.h
+misc.o:	../../kernel/type.h
+misc.o:	/usr/include/ansi.h
+misc.o:	/usr/include/errno.h
+misc.o:	/usr/include/fcntl.h
+misc.o:	/usr/include/ibm/bios.h
+misc.o:	/usr/include/ibm/cpu.h
+misc.o:	/usr/include/ibm/interrupt.h
+misc.o:	/usr/include/ibm/ports.h
+misc.o:	/usr/include/lib.h
+misc.o:	/usr/include/limits.h
+misc.o:	/usr/include/minix/callnr.h
+misc.o:	/usr/include/minix/com.h
+misc.o:	/usr/include/minix/config.h
+misc.o:	/usr/include/minix/const.h
+misc.o:	/usr/include/minix/devio.h
+misc.o:	/usr/include/minix/dmap.h
+misc.o:	/usr/include/minix/ioctl.h
+misc.o:	/usr/include/minix/ipc.h
+misc.o:	/usr/include/minix/sys_config.h
+misc.o:	/usr/include/minix/syslib.h
+misc.o:	/usr/include/minix/sysutil.h
+misc.o:	/usr/include/minix/type.h
+misc.o:	/usr/include/signal.h
+misc.o:	/usr/include/string.h
+misc.o:	/usr/include/sys/dir.h
+misc.o:	/usr/include/sys/resource.h
+misc.o:	/usr/include/sys/svrctl.h
+misc.o:	/usr/include/sys/types.h
+misc.o:	/usr/include/timers.h
+misc.o:	/usr/include/unistd.h
+misc.o:	const.h
+misc.o:	glo.h
+misc.o:	misc.c
+misc.o:	mproc.h
+misc.o:	param.h
+misc.o:	pm.h
+misc.o:	proto.h
+misc.o:	type.h
+
+signal.o:	/usr/include/ansi.h
+signal.o:	/usr/include/errno.h
+signal.o:	/usr/include/fcntl.h
+signal.o:	/usr/include/limits.h
+signal.o:	/usr/include/minix/callnr.h
+signal.o:	/usr/include/minix/com.h
+signal.o:	/usr/include/minix/config.h
+signal.o:	/usr/include/minix/const.h
+signal.o:	/usr/include/minix/devio.h
+signal.o:	/usr/include/minix/endpoint.h
+signal.o:	/usr/include/minix/ipc.h
+signal.o:	/usr/include/minix/sys_config.h
+signal.o:	/usr/include/minix/syslib.h
+signal.o:	/usr/include/minix/sysutil.h
+signal.o:	/usr/include/minix/type.h
+signal.o:	/usr/include/signal.h
+signal.o:	/usr/include/string.h
+signal.o:	/usr/include/sys/dir.h
+signal.o:	/usr/include/sys/ptrace.h
+signal.o:	/usr/include/sys/sigcontext.h
+signal.o:	/usr/include/sys/stat.h
+signal.o:	/usr/include/sys/types.h
+signal.o:	/usr/include/timers.h
+signal.o:	/usr/include/unistd.h
+signal.o:	const.h
+signal.o:	glo.h
+signal.o:	mproc.h
+signal.o:	param.h
+signal.o:	pm.h
+signal.o:	proto.h
+signal.o:	signal.c
+signal.o:	type.h
+
+table.o:	/usr/include/ansi.h
+table.o:	/usr/include/errno.h
+table.o:	/usr/include/fcntl.h
+table.o:	/usr/include/limits.h
+table.o:	/usr/include/minix/callnr.h
+table.o:	/usr/include/minix/config.h
+table.o:	/usr/include/minix/const.h
+table.o:	/usr/include/minix/devio.h
+table.o:	/usr/include/minix/ipc.h
+table.o:	/usr/include/minix/sys_config.h
+table.o:	/usr/include/minix/syslib.h
+table.o:	/usr/include/minix/sysutil.h
+table.o:	/usr/include/minix/type.h
+table.o:	/usr/include/signal.h
+table.o:	/usr/include/sys/dir.h
+table.o:	/usr/include/sys/types.h
+table.o:	/usr/include/timers.h
+table.o:	/usr/include/unistd.h
+table.o:	const.h
+table.o:	glo.h
+table.o:	mproc.h
+table.o:	param.h
+table.o:	pm.h
+table.o:	proto.h
+table.o:	table.c
+table.o:	type.h
+
+time.o:	/usr/include/ansi.h
+time.o:	/usr/include/errno.h
+time.o:	/usr/include/fcntl.h
+time.o:	/usr/include/limits.h
+time.o:	/usr/include/minix/callnr.h
+time.o:	/usr/include/minix/com.h
+time.o:	/usr/include/minix/config.h
+time.o:	/usr/include/minix/const.h
+time.o:	/usr/include/minix/devio.h
+time.o:	/usr/include/minix/ipc.h
+time.o:	/usr/include/minix/sys_config.h
+time.o:	/usr/include/minix/syslib.h
+time.o:	/usr/include/minix/sysutil.h
+time.o:	/usr/include/minix/type.h
+time.o:	/usr/include/signal.h
+time.o:	/usr/include/sys/dir.h
+time.o:	/usr/include/sys/types.h
+time.o:	/usr/include/timers.h
+time.o:	/usr/include/unistd.h
+time.o:	const.h
+time.o:	glo.h
+time.o:	mproc.h
+time.o:	param.h
+time.o:	pm.h
+time.o:	proto.h
+time.o:	time.c
+time.o:	type.h
+
+timers.o:	/usr/include/ansi.h
+timers.o:	/usr/include/errno.h
+timers.o:	/usr/include/fcntl.h
+timers.o:	/usr/include/limits.h
+timers.o:	/usr/include/minix/com.h
+timers.o:	/usr/include/minix/config.h
+timers.o:	/usr/include/minix/const.h
+timers.o:	/usr/include/minix/devio.h
+timers.o:	/usr/include/minix/ipc.h
+timers.o:	/usr/include/minix/sys_config.h
+timers.o:	/usr/include/minix/syslib.h
+timers.o:	/usr/include/minix/sysutil.h
+timers.o:	/usr/include/minix/type.h
+timers.o:	/usr/include/sys/dir.h
+timers.o:	/usr/include/sys/types.h
+timers.o:	/usr/include/timers.h
+timers.o:	/usr/include/unistd.h
+timers.o:	const.h
+timers.o:	glo.h
+timers.o:	pm.h
+timers.o:	proto.h
+timers.o:	timers.c
+timers.o:	type.h
+
+trace.o:	/usr/include/ansi.h
+trace.o:	/usr/include/errno.h
+trace.o:	/usr/include/fcntl.h
+trace.o:	/usr/include/limits.h
+trace.o:	/usr/include/minix/com.h
+trace.o:	/usr/include/minix/config.h
+trace.o:	/usr/include/minix/const.h
+trace.o:	/usr/include/minix/devio.h
+trace.o:	/usr/include/minix/ipc.h
+trace.o:	/usr/include/minix/sys_config.h
+trace.o:	/usr/include/minix/syslib.h
+trace.o:	/usr/include/minix/sysutil.h
+trace.o:	/usr/include/minix/type.h
+trace.o:	/usr/include/signal.h
+trace.o:	/usr/include/sys/dir.h
+trace.o:	/usr/include/sys/ptrace.h
+trace.o:	/usr/include/sys/types.h
+trace.o:	/usr/include/timers.h
+trace.o:	/usr/include/unistd.h
+trace.o:	const.h
+trace.o:	glo.h
+trace.o:	mproc.h
+trace.o:	param.h
+trace.o:	pm.h
+trace.o:	proto.h
+trace.o:	trace.c
+trace.o:	type.h
+
+utility.o:	../../kernel/config.h
+utility.o:	../../kernel/const.h
+utility.o:	../../kernel/priv.h
+utility.o:	../../kernel/proc.h
+utility.o:	../../kernel/protect.h
+utility.o:	../../kernel/type.h
+utility.o:	/usr/include/ansi.h
+utility.o:	/usr/include/errno.h
+utility.o:	/usr/include/fcntl.h
+utility.o:	/usr/include/ibm/bios.h
+utility.o:	/usr/include/ibm/cpu.h
+utility.o:	/usr/include/ibm/interrupt.h
+utility.o:	/usr/include/ibm/ports.h
+utility.o:	/usr/include/limits.h
+utility.o:	/usr/include/minix/callnr.h
+utility.o:	/usr/include/minix/com.h
+utility.o:	/usr/include/minix/config.h
+utility.o:	/usr/include/minix/const.h
+utility.o:	/usr/include/minix/devio.h
+utility.o:	/usr/include/minix/endpoint.h
+utility.o:	/usr/include/minix/ipc.h
+utility.o:	/usr/include/minix/sys_config.h
+utility.o:	/usr/include/minix/syslib.h
+utility.o:	/usr/include/minix/sysutil.h
+utility.o:	/usr/include/minix/type.h
+utility.o:	/usr/include/signal.h
+utility.o:	/usr/include/string.h
+utility.o:	/usr/include/sys/dir.h
+utility.o:	/usr/include/sys/stat.h
+utility.o:	/usr/include/sys/types.h
+utility.o:	/usr/include/timers.h
+utility.o:	/usr/include/unistd.h
+utility.o:	const.h
+utility.o:	glo.h
+utility.o:	mproc.h
+utility.o:	param.h
+utility.o:	pm.h
+utility.o:	proto.h
+utility.o:	type.h
+utility.o:	utility.c
Index: /trunk/minix/servers/pm/Makefile
===================================================================
--- /trunk/minix/servers/pm/Makefile	(revision 9)
+++ /trunk/minix/servers/pm/Makefile	(revision 9)
@@ -0,0 +1,39 @@
+# Makefile for Process Manager (PM)
+SERVER = pm
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+h = $i/minix
+k = $u/src/kernel
+
+# programs, flags, etc.
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+
+OBJ = 	main.o forkexit.o break.o exec.o time.o timers.o \
+	signal.o alloc.o utility.o table.o trace.o getset.o misc.o
+
+# build local binary
+all build:	$(SERVER)
+$(SERVER):	$(OBJ)
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) -lsys -lsysutil -ltimers
+	install -S 256w $@
+
+# install with other servers
+install:	/usr/sbin/$(SERVER)
+/usr/sbin/$(SERVER):	$(SERVER)
+	install -o root -cs $? $@
+
+# clean up local files
+clean:
+	rm -f $(SERVER) *.o *.bak 
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/servers/pm/alloc.c
===================================================================
--- /trunk/minix/servers/pm/alloc.c	(revision 9)
+++ /trunk/minix/servers/pm/alloc.c	(revision 9)
@@ -0,0 +1,445 @@
+/* This file is concerned with allocating and freeing arbitrary-size blocks of
+ * physical memory on behalf of the FORK and EXEC system calls.  The key data
+ * structure used is the hole table, which maintains a list of holes in memory.
+ * It is kept sorted in order of increasing memory address. The addresses
+ * it contains refers to physical memory, starting at absolute address 0
+ * (i.e., they are not relative to the start of PM).  During system
+ * initialization, that part of memory containing the interrupt vectors,
+ * kernel, and PM are "allocated" to mark them as not available and to
+ * remove them from the hole list.
+ *
+ * The entry points into this file are:
+ *   alloc_mem:	allocate a given sized chunk of memory
+ *   free_mem:	release a previously allocated chunk of memory
+ *   mem_init:	initialize the tables when PM start up
+ *   max_hole:	returns the largest hole currently available
+ *   mem_holes_copy: for outsiders who want a copy of the hole-list
+ */
+
+#include "pm.h"
+#include <minix/com.h>
+#include <minix/callnr.h>
+#include <minix/type.h>
+#include <minix/config.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mproc.h"
+#include "../../kernel/const.h"
+#include "../../kernel/config.h"
+#include "../../kernel/type.h"
+
+#define NIL_HOLE (struct hole *) 0
+
+PRIVATE struct hole hole[_NR_HOLES];
+PRIVATE u32_t high_watermark = 0;
+
+PRIVATE struct hole *hole_head;	/* pointer to first hole */
+PRIVATE struct hole *free_slots;/* ptr to list of unused table slots */
+#if ENABLE_SWAP
+PRIVATE int swap_fd = -1;	/* file descriptor of open swap file/device */
+PRIVATE u32_t swap_offset;	/* offset to start of swap area on swap file */
+PRIVATE phys_clicks swap_base;	/* memory offset chosen as swap base */
+PRIVATE phys_clicks swap_maxsize;/* maximum amount of swap "memory" possible */
+PRIVATE struct mproc *in_queue;	/* queue of processes wanting to swap in */
+PRIVATE struct mproc *outswap = &mproc[0]; 	 /* outswap candidate? */
+#else /* ! ENABLE_SWAP */
+#define swap_base ((phys_clicks) -1)
+#endif /* ENABLE_SWAP */
+
+FORWARD _PROTOTYPE( void del_slot, (struct hole *prev_ptr, struct hole *hp) );
+FORWARD _PROTOTYPE( void merge, (struct hole *hp)			    );
+#if ENABLE_SWAP
+FORWARD _PROTOTYPE( int swap_out, (void)				    );
+#else
+#define swap_out()	(0)
+#endif
+
+/*===========================================================================*
+ *				alloc_mem				     *
+ *===========================================================================*/
+PUBLIC phys_clicks alloc_mem(clicks)
+phys_clicks clicks;		/* amount of memory requested */
+{
+/* Allocate a block of memory from the free list using first fit. The block
+ * consists of a sequence of contiguous bytes, whose length in clicks is
+ * given by 'clicks'.  A pointer to the block is returned.  The block is
+ * always on a click boundary.  This procedure is called when memory is
+ * needed for FORK or EXEC.  Swap other processes out if needed.
+ */
+  register struct hole *hp, *prev_ptr;
+  phys_clicks old_base;
+
+  do {
+        prev_ptr = NIL_HOLE;
+	hp = hole_head;
+	while (hp != NIL_HOLE && hp->h_base < swap_base) {
+		if (hp->h_len >= clicks) {
+			/* We found a hole that is big enough.  Use it. */
+			old_base = hp->h_base;	/* remember where it started */
+			hp->h_base += clicks;	/* bite a piece off */
+			hp->h_len -= clicks;	/* ditto */
+
+			/* Remember new high watermark of used memory. */
+			if(hp->h_base > high_watermark)
+				high_watermark = hp->h_base;
+
+			/* Delete the hole if used up completely. */
+			if (hp->h_len == 0) del_slot(prev_ptr, hp);
+
+			/* Return the start address of the acquired block. */
+			return(old_base);
+		}
+
+		prev_ptr = hp;
+		hp = hp->h_next;
+	}
+  } while (swap_out());		/* try to swap some other process out */
+  return(NO_MEM);
+}
+
+/*===========================================================================*
+ *				free_mem				     *
+ *===========================================================================*/
+PUBLIC void free_mem(base, clicks)
+phys_clicks base;		/* base address of block to free */
+phys_clicks clicks;		/* number of clicks to free */
+{
+/* Return a block of free memory to the hole list.  The parameters tell where
+ * the block starts in physical memory and how big it is.  The block is added
+ * to the hole list.  If it is contiguous with an existing hole on either end,
+ * it is merged with the hole or holes.
+ */
+  register struct hole *hp, *new_ptr, *prev_ptr;
+
+  if (clicks == 0) return;
+  if ( (new_ptr = free_slots) == NIL_HOLE) 
+  	panic(__FILE__,"hole table full", NO_NUM);
+  new_ptr->h_base = base;
+  new_ptr->h_len = clicks;
+  free_slots = new_ptr->h_next;
+  hp = hole_head;
+
+  /* If this block's address is numerically less than the lowest hole currently
+   * available, or if no holes are currently available, put this hole on the
+   * front of the hole list.
+   */
+  if (hp == NIL_HOLE || base <= hp->h_base) {
+	/* Block to be freed goes on front of the hole list. */
+	new_ptr->h_next = hp;
+	hole_head = new_ptr;
+	merge(new_ptr);
+	return;
+  }
+
+  /* Block to be returned does not go on front of hole list. */
+  prev_ptr = NIL_HOLE;
+  while (hp != NIL_HOLE && base > hp->h_base) {
+	prev_ptr = hp;
+	hp = hp->h_next;
+  }
+
+  /* We found where it goes.  Insert block after 'prev_ptr'. */
+  new_ptr->h_next = prev_ptr->h_next;
+  prev_ptr->h_next = new_ptr;
+  merge(prev_ptr);		/* sequence is 'prev_ptr', 'new_ptr', 'hp' */
+}
+
+/*===========================================================================*
+ *				del_slot				     *
+ *===========================================================================*/
+PRIVATE void del_slot(prev_ptr, hp)
+/* pointer to hole entry just ahead of 'hp' */
+register struct hole *prev_ptr;
+/* pointer to hole entry to be removed */
+register struct hole *hp;	
+{
+/* Remove an entry from the hole list.  This procedure is called when a
+ * request to allocate memory removes a hole in its entirety, thus reducing
+ * the numbers of holes in memory, and requiring the elimination of one
+ * entry in the hole list.
+ */
+  if (hp == hole_head)
+	hole_head = hp->h_next;
+  else
+	prev_ptr->h_next = hp->h_next;
+
+  hp->h_next = free_slots;
+  hp->h_base = hp->h_len = 0;
+  free_slots = hp;
+}
+
+/*===========================================================================*
+ *				merge					     *
+ *===========================================================================*/
+PRIVATE void merge(hp)
+register struct hole *hp;	/* ptr to hole to merge with its successors */
+{
+/* Check for contiguous holes and merge any found.  Contiguous holes can occur
+ * when a block of memory is freed, and it happens to abut another hole on
+ * either or both ends.  The pointer 'hp' points to the first of a series of
+ * three holes that can potentially all be merged together.
+ */
+  register struct hole *next_ptr;
+
+  /* If 'hp' points to the last hole, no merging is possible.  If it does not,
+   * try to absorb its successor into it and free the successor's table entry.
+   */
+  if ( (next_ptr = hp->h_next) == NIL_HOLE) return;
+  if (hp->h_base + hp->h_len == next_ptr->h_base) {
+	hp->h_len += next_ptr->h_len;	/* first one gets second one's mem */
+	del_slot(hp, next_ptr);
+  } else {
+	hp = next_ptr;
+  }
+
+  /* If 'hp' now points to the last hole, return; otherwise, try to absorb its
+   * successor into it.
+   */
+  if ( (next_ptr = hp->h_next) == NIL_HOLE) return;
+  if (hp->h_base + hp->h_len == next_ptr->h_base) {
+	hp->h_len += next_ptr->h_len;
+	del_slot(hp, next_ptr);
+  }
+}
+
+/*===========================================================================*
+ *				mem_init				     *
+ *===========================================================================*/
+PUBLIC void mem_init(chunks, free)
+struct memory *chunks;		/* list of free memory chunks */
+phys_clicks *free;		/* memory size summaries */
+{
+/* Initialize hole lists.  There are two lists: 'hole_head' points to a linked
+ * list of all the holes (unused memory) in the system; 'free_slots' points to
+ * a linked list of table entries that are not in use.  Initially, the former
+ * list has one entry for each chunk of physical memory, and the second
+ * list links together the remaining table slots.  As memory becomes more
+ * fragmented in the course of time (i.e., the initial big holes break up into
+ * smaller holes), new table slots are needed to represent them.  These slots
+ * are taken from the list headed by 'free_slots'.
+ */
+  int i;
+  register struct hole *hp;
+
+  /* Put all holes on the free list. */
+  for (hp = &hole[0]; hp < &hole[_NR_HOLES]; hp++) {
+	hp->h_next = hp + 1;
+	hp->h_base = hp->h_len = 0;
+  }
+  hole[_NR_HOLES-1].h_next = NIL_HOLE;
+  hole_head = NIL_HOLE;
+  free_slots = &hole[0];
+
+  /* Use the chunks of physical memory to allocate holes. */
+  *free = 0;
+  for (i=NR_MEMS-1; i>=0; i--) {
+  	if (chunks[i].size > 0) {
+		free_mem(chunks[i].base, chunks[i].size);
+		*free += chunks[i].size;
+#if ENABLE_SWAP
+		if (swap_base < chunks[i].base + chunks[i].size) 
+			swap_base = chunks[i].base + chunks[i].size;
+#endif
+	}
+  }
+
+#if ENABLE_SWAP
+  /* The swap area is represented as a hole above and separate of regular
+   * memory.  A hole at the size of the swap file is allocated on "swapon".
+   */
+  swap_base++;				/* make separate */
+  swap_maxsize = 0 - swap_base;		/* maximum we can possibly use */
+#endif
+}
+
+/*===========================================================================*
+ *				mem_holes_copy				     *
+ *===========================================================================*/
+PUBLIC int mem_holes_copy(struct hole *holecopies, size_t *bytes, u32_t *hi)
+{
+	if(*bytes < sizeof(hole)) return ENOSPC;
+	memcpy(holecopies, hole, sizeof(hole));
+	*bytes = sizeof(hole);
+	*hi = high_watermark;
+	return OK;
+}
+
+#if ENABLE_SWAP
+/*===========================================================================*
+ *				swap_on					     *
+ *===========================================================================*/
+PUBLIC int swap_on(file, offset, size)
+char *file;				/* file to swap on */
+u32_t offset, size;			/* area on swap file to use */
+{
+/* Turn swapping on. */
+
+  if (swap_fd != -1) return(EBUSY);	/* already have swap? */
+
+  tell_fs(CHDIR, who_e, FALSE, 0);	/* be like the caller for open() */
+  if ((swap_fd = open(file, O_RDWR)) < 0) return(-errno);
+  swap_offset = offset;
+  size >>= CLICK_SHIFT;
+  if (size > swap_maxsize) size = swap_maxsize;
+  if (size > 0) free_mem(swap_base, (phys_clicks) size);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				swap_off				     *
+ *===========================================================================*/
+PUBLIC int swap_off()
+{
+/* Turn swapping off. */
+  struct mproc *rmp;
+  struct hole *hp, *prev_ptr;
+
+  if (swap_fd == -1) return(OK);	/* can't turn off what isn't on */
+
+  /* Put all swapped out processes on the inswap queue and swap in. */
+  for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
+	if (rmp->mp_flags & ONSWAP) swap_inqueue(rmp);
+  }
+  swap_in();
+
+  /* All in memory? */
+  for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
+	if (rmp->mp_flags & ONSWAP) return(ENOMEM);
+  }
+
+  /* Yes.  Remove the swap hole and close the swap file descriptor. */
+  for (hp = hole_head; hp != NIL_HOLE; prev_ptr = hp, hp = hp->h_next) {
+	if (hp->h_base >= swap_base) {
+		del_slot(prev_ptr, hp);
+		hp = hole_head;
+	}
+  }
+  close(swap_fd);
+  swap_fd = -1;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				swap_inqueue				     *
+ *===========================================================================*/
+PUBLIC void swap_inqueue(rmp)
+register struct mproc *rmp;		/* process to add to the queue */
+{
+/* Put a swapped out process on the queue of processes to be swapped in.  This
+ * happens when such a process gets a signal, or if a reply message must be
+ * sent, like when a process doing a wait() has a child that exits.
+ */
+  struct mproc **pmp;
+
+  if (rmp->mp_flags & SWAPIN) return;	/* already queued */
+
+  
+  for (pmp = &in_queue; *pmp != NULL; pmp = &(*pmp)->mp_swapq) {}
+  *pmp = rmp;
+  rmp->mp_swapq = NULL;
+  rmp->mp_flags |= SWAPIN;
+}
+
+/*===========================================================================*
+ *				swap_in					     *
+ *===========================================================================*/
+PUBLIC void swap_in()
+{
+/* Try to swap in a process on the inswap queue.  We want to send it a message,
+ * interrupt it, or something.
+ */
+  struct mproc **pmp, *rmp;
+  phys_clicks old_base, new_base, size;
+  off_t off;
+  int proc_nr;
+
+  pmp = &in_queue;
+  while ((rmp = *pmp) != NULL) {
+	proc_nr = (rmp - mproc);
+	size = rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len
+		- rmp->mp_seg[D].mem_vir;
+
+	if (!(rmp->mp_flags & SWAPIN)) {
+		/* Guess it got killed.  (Queue is cleaned here.) */
+		*pmp = rmp->mp_swapq;
+		continue;
+	} else
+	if ((new_base = alloc_mem(size)) == NO_MEM) {
+		/* No memory for this one, try the next. */
+		pmp = &rmp->mp_swapq;
+	} else {
+		/* We've found memory.  Update map and swap in. */
+		old_base = rmp->mp_seg[D].mem_phys;
+		rmp->mp_seg[D].mem_phys = new_base;
+		rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + 
+			(rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
+		sys_newmap(rmp->mp_endpoint, rmp->mp_seg);
+		off = swap_offset + ((off_t) (old_base-swap_base)<<CLICK_SHIFT);
+		lseek(swap_fd, off, SEEK_SET);
+		rw_seg(0, swap_fd, rmp->mp_endpoint, D, (phys_bytes)size << CLICK_SHIFT);
+		free_mem(old_base, size);
+		rmp->mp_flags &= ~(ONSWAP|SWAPIN);
+		*pmp = rmp->mp_swapq;
+		check_pending(rmp);	/* a signal may have waked this one */
+	}
+  }
+}
+
+/*===========================================================================*
+ *				swap_out				     *
+ *===========================================================================*/
+PRIVATE int swap_out()
+{
+/* Try to find a process that can be swapped out.  Candidates are those blocked
+ * on a system call that PM handles, like wait(), pause() or sigsuspend().
+ */
+  struct mproc *rmp;
+  struct hole *hp, *prev_ptr;
+  phys_clicks old_base, new_base, size;
+  off_t off;
+  int proc_nr;
+
+  rmp = outswap;
+  do {
+	if (++rmp == &mproc[NR_PROCS]) rmp = &mproc[0];
+
+	/* A candidate? */
+	if (!(rmp->mp_flags & (PAUSED | WAITING | SIGSUSPENDED))) continue;
+
+	/* Already on swap or otherwise to be avoided? */
+	if (rmp->mp_flags & (DONT_SWAP | TRACED | REPLY | ONSWAP)) continue;
+
+	/* Got one, find a swap hole and swap it out. */
+	proc_nr = (rmp - mproc);
+	size = rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len
+		- rmp->mp_seg[D].mem_vir;
+
+	prev_ptr = NIL_HOLE;
+	for (hp = hole_head; hp != NIL_HOLE; prev_ptr = hp, hp = hp->h_next) {
+		if (hp->h_base >= swap_base && hp->h_len >= size) break;
+	}
+	if (hp == NIL_HOLE) continue;	/* oops, not enough swapspace */
+	new_base = hp->h_base;
+	hp->h_base += size;
+	hp->h_len -= size;
+	if (hp->h_len == 0) del_slot(prev_ptr, hp);
+
+	off = swap_offset + ((off_t) (new_base - swap_base) << CLICK_SHIFT);
+	lseek(swap_fd, off, SEEK_SET);
+	rw_seg(1, swap_fd, rmp->mp_endpoint, D, (phys_bytes)size << CLICK_SHIFT);
+	old_base = rmp->mp_seg[D].mem_phys;
+	rmp->mp_seg[D].mem_phys = new_base;
+	rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + 
+		(rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
+	sys_newmap(rmp->mp_endpoint, rmp->mp_seg);
+	free_mem(old_base, size);
+	rmp->mp_flags |= ONSWAP;
+
+	outswap = rmp;		/* next time start here */
+	return(TRUE);
+  } while (rmp != outswap);
+
+  return(FALSE);	/* no candidate found */
+}
+#endif /* SWAP */
Index: /trunk/minix/servers/pm/break.c
===================================================================
--- /trunk/minix/servers/pm/break.c	(revision 9)
+++ /trunk/minix/servers/pm/break.c	(revision 9)
@@ -0,0 +1,177 @@
+/* The MINIX model of memory allocation reserves a fixed amount of memory for
+ * the combined text, data, and stack segments.  The amount used for a child
+ * process created by FORK is the same as the parent had.  If the child does
+ * an EXEC later, the new size is taken from the header of the file EXEC'ed.
+ *
+ * The layout in memory consists of the text segment, followed by the data
+ * segment, followed by a gap (unused memory), followed by the stack segment.
+ * The data segment grows upward and the stack grows downward, so each can
+ * take memory from the gap.  If they meet, the process must be killed.  The
+ * procedures in this file deal with the growth of the data and stack segments.
+ *
+ * The entry points into this file are:
+ *   do_brk:	  BRK/SBRK system calls to grow or shrink the data segment
+ *   adjust:	  see if a proposed segment adjustment is allowed
+ *   size_ok:	  see if the segment sizes are feasible (i86 only)
+ */
+
+#include "pm.h"
+#include <signal.h>
+#include "mproc.h"
+#include "param.h"
+
+#define DATA_CHANGED       1	/* flag value when data segment size changed */
+#define STACK_CHANGED      2	/* flag value when stack size changed */
+
+/*===========================================================================*
+ *				do_brk  				     *
+ *===========================================================================*/
+PUBLIC int do_brk()
+{
+/* Perform the brk(addr) system call.
+ *
+ * The call is complicated by the fact that on some machines (e.g., 8088),
+ * the stack pointer can grow beyond the base of the stack segment without
+ * anybody noticing it.
+ * The parameter, 'addr' is the new virtual address in D space.
+ */
+
+  register struct mproc *rmp;
+  int r;
+  vir_bytes v, new_sp;
+  vir_clicks new_clicks;
+
+  rmp = mp;
+  v = (vir_bytes) m_in.addr;
+  new_clicks = (vir_clicks) ( ((long) v + CLICK_SIZE - 1) >> CLICK_SHIFT);
+  if (new_clicks < rmp->mp_seg[D].mem_vir) {
+	rmp->mp_reply.reply_ptr = (char *) -1;
+	return(ENOMEM);
+  }
+  new_clicks -= rmp->mp_seg[D].mem_vir;
+  if ((r=get_stack_ptr(who_e, &new_sp)) != OK) /* ask kernel for sp value */
+  	panic(__FILE__,"couldn't get stack pointer", r);
+  r = adjust(rmp, new_clicks, new_sp);
+  rmp->mp_reply.reply_ptr = (r == OK ? m_in.addr : (char *) -1);
+  return(r);			/* return new address or -1 */
+}
+
+/*===========================================================================*
+ *				adjust  				     *
+ *===========================================================================*/
+PUBLIC int adjust(rmp, data_clicks, sp)
+register struct mproc *rmp;	/* whose memory is being adjusted? */
+vir_clicks data_clicks;		/* how big is data segment to become? */
+vir_bytes sp;			/* new value of sp */
+{
+/* See if data and stack segments can coexist, adjusting them if need be.
+ * Memory is never allocated or freed.  Instead it is added or removed from the
+ * gap between data segment and stack segment.  If the gap size becomes
+ * negative, the adjustment of data or stack fails and ENOMEM is returned.
+ */
+
+  register struct mem_map *mem_sp, *mem_dp;
+  vir_clicks sp_click, gap_base, lower, old_clicks;
+  int changed, r, ft;
+  long base_of_stack, delta;	/* longs avoid certain problems */
+
+  mem_dp = &rmp->mp_seg[D];	/* pointer to data segment map */
+  mem_sp = &rmp->mp_seg[S];	/* pointer to stack segment map */
+  changed = 0;			/* set when either segment changed */
+
+  if (mem_sp->mem_len == 0) return(OK);	/* don't bother init */
+
+  /* See if stack size has gone negative (i.e., sp too close to 0xFFFF...) */
+  base_of_stack = (long) mem_sp->mem_vir + (long) mem_sp->mem_len;
+  sp_click = sp >> CLICK_SHIFT;	/* click containing sp */
+  if (sp_click >= base_of_stack) return(ENOMEM);	/* sp too high */
+
+  /* Compute size of gap between stack and data segments. */
+  delta = (long) mem_sp->mem_vir - (long) sp_click;
+  lower = (delta > 0 ? sp_click : mem_sp->mem_vir);
+
+  /* Add a safety margin for future stack growth. Impossible to do right. */
+#define SAFETY_BYTES  (384 * sizeof(char *))
+#define SAFETY_CLICKS ((SAFETY_BYTES + CLICK_SIZE - 1) / CLICK_SIZE)
+  gap_base = mem_dp->mem_vir + data_clicks + SAFETY_CLICKS;
+  if (lower < gap_base) return(ENOMEM);	/* data and stack collided */
+
+  /* Update data length (but not data orgin) on behalf of brk() system call. */
+  old_clicks = mem_dp->mem_len;
+  if (data_clicks != mem_dp->mem_len) {
+	mem_dp->mem_len = data_clicks;
+	changed |= DATA_CHANGED;
+  }
+
+  /* Update stack length and origin due to change in stack pointer. */
+  if (delta > 0) {
+	mem_sp->mem_vir -= delta;
+	mem_sp->mem_phys -= delta;
+	mem_sp->mem_len += delta;
+	changed |= STACK_CHANGED;
+  }
+
+  /* Do the new data and stack segment sizes fit in the address space? */
+  ft = (rmp->mp_flags & SEPARATE);
+#if (CHIP == INTEL && _WORD_SIZE == 2)
+  r = size_ok(ft, rmp->mp_seg[T].mem_len, rmp->mp_seg[D].mem_len, 
+       rmp->mp_seg[S].mem_len, rmp->mp_seg[D].mem_vir, rmp->mp_seg[S].mem_vir);
+#else
+  r = (rmp->mp_seg[D].mem_vir + rmp->mp_seg[D].mem_len > 
+          rmp->mp_seg[S].mem_vir) ? ENOMEM : OK;
+#endif
+  if (r == OK) {
+	int r2;
+	if (changed && (r2=sys_newmap(rmp->mp_endpoint, rmp->mp_seg)) != OK)
+  		panic(__FILE__,"couldn't sys_newmap in adjust", r2);
+	return(OK);
+  }
+
+  /* New sizes don't fit or require too many page/segment registers. Restore.*/
+  if (changed & DATA_CHANGED) mem_dp->mem_len = old_clicks;
+  if (changed & STACK_CHANGED) {
+	mem_sp->mem_vir += delta;
+	mem_sp->mem_phys += delta;
+	mem_sp->mem_len -= delta;
+  }
+  return(ENOMEM);
+}
+
+#if (CHIP == INTEL && _WORD_SIZE == 2)
+/*===========================================================================*
+ *				size_ok  				     *
+ *===========================================================================*/
+PUBLIC int size_ok(file_type, tc, dc, sc, dvir, s_vir)
+int file_type;			/* SEPARATE or 0 */
+vir_clicks tc;			/* text size in clicks */
+vir_clicks dc;			/* data size in clicks */
+vir_clicks sc;			/* stack size in clicks */
+vir_clicks dvir;		/* virtual address for start of data seg */
+vir_clicks s_vir;		/* virtual address for start of stack seg */
+{
+/* Check to see if the sizes are feasible and enough segmentation registers
+ * exist.  On a machine with eight 8K pages, text, data, stack sizes of
+ * (32K, 16K, 16K) will fit, but (33K, 17K, 13K) will not, even though the
+ * former is bigger (64K) than the latter (63K).  Even on the 8088 this test
+ * is needed, since the data and stack may not exceed 4096 clicks.
+ * Note this is not used for 32-bit Intel Minix, the test is done in-line.
+ */
+
+  int pt, pd, ps;		/* segment sizes in pages */
+
+  pt = ( (tc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
+  pd = ( (dc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
+  ps = ( (sc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
+
+  if (file_type == SEPARATE) {
+	if (pt > MAX_PAGES || pd + ps > MAX_PAGES) return(ENOMEM);
+  } else {
+	if (pt + pd + ps > MAX_PAGES) return(ENOMEM);
+  }
+
+  if (dvir + dc > s_vir) return(ENOMEM);
+
+  return(OK);
+}
+#endif
+
Index: /trunk/minix/servers/pm/const.h
===================================================================
--- /trunk/minix/servers/pm/const.h	(revision 9)
+++ /trunk/minix/servers/pm/const.h	(revision 9)
@@ -0,0 +1,21 @@
+/* Constants used by the Process Manager. */
+
+#define NO_MEM ((phys_clicks) 0)  /* returned by alloc_mem() with mem is up */
+
+#if (CHIP == INTEL && _WORD_SIZE == 2)
+/* These definitions are used in size_ok and are not needed for 386.
+ * The 386 segment granularity is 1 for segments smaller than 1M and 4096
+ * above that.  
+ */
+#define PAGE_SIZE	  16	/* how many bytes in a page (s.b.HCLICK_SIZE)*/
+#define MAX_PAGES       4096	/* how many pages in the virtual addr space */
+#endif
+
+#define NR_PIDS	       30000	/* process ids range from 0 to NR_PIDS-1.
+				 * (magic constant: some old applications use
+				 * a 'short' instead of pid_t.)
+				 */
+
+#define PM_PID	           0	/* PM's process id number */
+#define INIT_PID	   1	/* INIT's process id number */
+
Index: /trunk/minix/servers/pm/exec.c
===================================================================
--- /trunk/minix/servers/pm/exec.c	(revision 9)
+++ /trunk/minix/servers/pm/exec.c	(revision 9)
@@ -0,0 +1,604 @@
+/* This file handles the EXEC system call.  It performs the work as follows:
+ *    - see if the permissions allow the file to be executed
+ *    - read the header and extract the sizes
+ *    - fetch the initial args and environment from the user space
+ *    - allocate the memory for the new process
+ *    - copy the initial stack from PM to the process
+ *    - read in the text and data segments and copy to the process
+ *    - take care of setuid and setgid bits
+ *    - fix up 'mproc' table
+ *    - tell kernel about EXEC
+ *    - save offset to initial argc (for ps)
+ *
+ * The entry points into this file are:
+ *   do_exec:	 perform the EXEC system call
+ *   rw_seg:	 read or write a segment from or to a file
+ *   find_share: find a process whose text segment can be shared
+ */
+
+#include "pm.h"
+#include <sys/stat.h>
+#include <minix/callnr.h>
+#include <minix/endpoint.h>
+#include <minix/com.h>
+#include <a.out.h>
+#include <signal.h>
+#include <string.h>
+#include "mproc.h"
+#include "param.h"
+
+FORWARD _PROTOTYPE( int new_mem, (struct mproc *sh_mp, vir_bytes text_bytes,
+		vir_bytes data_bytes, vir_bytes bss_bytes,
+		vir_bytes stk_bytes, phys_bytes tot_bytes)		);
+FORWARD _PROTOTYPE( void patch_ptr, (char stack[ARG_MAX], vir_bytes base) );
+FORWARD _PROTOTYPE( int insert_arg, (char stack[ARG_MAX],
+		vir_bytes *stk_bytes, char *arg, int replace)		);
+FORWARD _PROTOTYPE( char *patch_stack, (int fd, char stack[ARG_MAX],
+		vir_bytes *stk_bytes, char *script)			);
+FORWARD _PROTOTYPE( int read_header, (int fd, int *ft, vir_bytes *text_bytes,
+		vir_bytes *data_bytes, vir_bytes *bss_bytes,
+		phys_bytes *tot_bytes, long *sym_bytes, vir_clicks sc,
+		vir_bytes *pc)						);
+
+#define ESCRIPT	(-2000)	/* Returned by read_header for a #! script. */
+#define PTRSIZE	sizeof(char *) /* Size of pointers in argv[] and envp[]. */
+
+/*===========================================================================*
+ *				do_exec					     *
+ *===========================================================================*/
+PUBLIC int do_exec()
+{
+/* Perform the execve(name, argv, envp) call.  The user library builds a
+ * complete stack image, including pointers, args, environ, etc.  The stack
+ * is copied to a buffer inside PM, and then to the new core image.
+ */
+  register struct mproc *rmp;
+  struct mproc *sh_mp;
+  int m, r, r2, fd, ft, sn;
+  static char mbuf[ARG_MAX];	/* buffer for stack and zeroes */
+  static char name_buf[PATH_MAX]; /* the name of the file to exec */
+  char *new_sp, *name, *basename;
+  vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp;
+  phys_bytes tot_bytes;		/* total space for program, including gap */
+  long sym_bytes;
+  vir_clicks sc;
+  struct stat s_buf[2], *s_p;
+  vir_bytes pc;
+
+  /* Do some validity checks. */
+  rmp = mp;
+  stk_bytes = (vir_bytes) m_in.stack_bytes;
+  if (stk_bytes > ARG_MAX) return(ENOMEM);	/* stack too big */
+  if (m_in.exec_len <= 0 || m_in.exec_len > PATH_MAX) return(EINVAL);
+
+  /* Get the exec file name and see if the file is executable. */
+  src = (vir_bytes) m_in.exec_name;
+  dst = (vir_bytes) name_buf;
+  r = sys_datacopy(who_e, (vir_bytes) src,
+		PM_PROC_NR, (vir_bytes) dst, (phys_bytes) m_in.exec_len);
+  if (r != OK) return(r);	/* file name not in user data segment */
+
+  /* Fetch the stack from the user before destroying the old core image. */
+  src = (vir_bytes) m_in.stack_ptr;
+  dst = (vir_bytes) mbuf;
+  r = sys_datacopy(who_e, (vir_bytes) src,
+  			PM_PROC_NR, (vir_bytes) dst, (phys_bytes)stk_bytes);
+  /* can't fetch stack (e.g. bad virtual addr) */
+  if (r != OK) return(EACCES);	
+
+  r = 0;	/* r = 0 (first attempt), or 1 (interpreted script) */
+  name = name_buf;	/* name of file to exec. */
+  do {
+	s_p = &s_buf[r];
+	tell_fs(CHDIR, who_e, FALSE, 0);  /* switch to the user's FS environ */
+	fd = allowed(name, s_p, X_BIT);	/* is file executable? */
+	if (fd < 0)  return(fd);		/* file was not executable */
+
+	/* Read the file header and extract the segment sizes. */
+	sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+
+	m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes, 
+					&tot_bytes, &sym_bytes, sc, &pc);
+	if (m != ESCRIPT || ++r > 1) break;
+  } while ((name = patch_stack(fd, mbuf, &stk_bytes, name_buf)) != NULL);
+
+  if (m < 0) {
+	close(fd);		/* something wrong with header */
+	return(stk_bytes > ARG_MAX ? ENOMEM : ENOEXEC);
+  }
+
+  /* Can the process' text be shared with that of one already running? */
+  sh_mp = find_share(rmp, s_p->st_ino, s_p->st_dev, s_p->st_ctime);
+
+  /* Allocate new memory and release old memory.  Fix map and tell kernel. */
+  r = new_mem(sh_mp, text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes);
+  if (r != OK) {
+	close(fd);		/* insufficient core or program too big */
+	return(r);
+  }
+
+  /* Save file identification to allow it to be shared. */
+  rmp->mp_ino = s_p->st_ino;
+  rmp->mp_dev = s_p->st_dev;
+  rmp->mp_ctime = s_p->st_ctime;
+
+  /* Patch up stack and copy it from PM to new core image. */
+  vsp = (vir_bytes) rmp->mp_seg[S].mem_vir << CLICK_SHIFT;
+  vsp += (vir_bytes) rmp->mp_seg[S].mem_len << CLICK_SHIFT;
+  vsp -= stk_bytes;
+  patch_ptr(mbuf, vsp);
+  src = (vir_bytes) mbuf;
+  r = sys_datacopy(PM_PROC_NR, (vir_bytes) src,
+  			who_e, (vir_bytes) vsp, (phys_bytes)stk_bytes);
+  if (r != OK) panic(__FILE__,"do_exec stack copy err on", who_e);
+
+  /* Read in text and data segments. */
+  if (sh_mp != NULL) {
+	lseek(fd, (off_t) text_bytes, SEEK_CUR);  /* shared: skip text */
+  } else {
+	rw_seg(0, fd, who_e, T, text_bytes);
+  }
+  rw_seg(0, fd, who_e, D, data_bytes);
+
+  close(fd);			/* don't need exec file any more */
+
+  /* Take care of setuid/setgid bits. */
+  if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */
+	if (s_buf[0].st_mode & I_SET_UID_BIT) {
+		rmp->mp_effuid = s_buf[0].st_uid;
+		tell_fs(SETUID, who_e, (int)rmp->mp_realuid, (int)rmp->mp_effuid);
+	}
+	if (s_buf[0].st_mode & I_SET_GID_BIT) {
+		rmp->mp_effgid = s_buf[0].st_gid;
+		tell_fs(SETGID,who_e, (int)rmp->mp_realgid, (int)rmp->mp_effgid);
+	}
+  }
+
+  /* Save offset to initial argc (for ps) */
+  rmp->mp_procargs = vsp;
+
+  /* Fix 'mproc' fields, tell kernel that exec is done,  reset caught sigs. */
+  for (sn = 1; sn <= _NSIG; sn++) {
+	if (sigismember(&rmp->mp_catch, sn)) {
+		sigdelset(&rmp->mp_catch, sn);
+		rmp->mp_sigact[sn].sa_handler = SIG_DFL;
+		sigemptyset(&rmp->mp_sigact[sn].sa_mask);
+	}
+  }
+
+  rmp->mp_flags &= ~SEPARATE;	/* turn off SEPARATE bit */
+  rmp->mp_flags |= ft;		/* turn it on for separate I & D files */
+  new_sp = (char *) vsp;
+
+  tell_fs(EXEC, who_e, 0, 0);	/* allow FS to handle FD_CLOEXEC files */
+
+  /* System will save command line for debugging, ps(1) output, etc. */
+  basename = strrchr(name, '/');
+  if (basename == NULL) basename = name; else basename++;
+  strncpy(rmp->mp_name, basename, PROC_NAME_LEN-1);
+  rmp->mp_name[PROC_NAME_LEN] = '\0';
+  if((r2=sys_exec(who_e, new_sp, basename, pc)) != OK) {
+	panic(__FILE__,"sys_exec failed", r2);
+  }
+
+  /* Cause a signal if this process is traced. */
+  if (rmp->mp_flags & TRACED) check_sig(rmp->mp_pid, SIGTRAP);
+
+  return(SUSPEND);		/* no reply, new program just runs */
+}
+
+/*===========================================================================*
+ *				read_header				     *
+ *===========================================================================*/
+PRIVATE int read_header(fd, ft, text_bytes, data_bytes, bss_bytes, 
+						tot_bytes, sym_bytes, sc, pc)
+int fd;				/* file descriptor for reading exec file */
+int *ft;			/* place to return ft number */
+vir_bytes *text_bytes;		/* place to return text size */
+vir_bytes *data_bytes;		/* place to return initialized data size */
+vir_bytes *bss_bytes;		/* place to return bss size */
+phys_bytes *tot_bytes;		/* place to return total size */
+long *sym_bytes;		/* place to return symbol table size */
+vir_clicks sc;			/* stack size in clicks */
+vir_bytes *pc;			/* program entry point (initial PC) */
+{
+/* Read the header and extract the text, data, bss and total sizes from it. */
+
+  int m, ct;
+  vir_clicks tc, dc, s_vir, dvir;
+  phys_clicks totc;
+  struct exec hdr;		/* a.out header is read in here */
+
+  /* Read the header and check the magic number.  The standard MINIX header 
+   * is defined in <a.out.h>.  It consists of 8 chars followed by 6 longs.
+   * Then come 4 more longs that are not used here.
+   *	Byte 0: magic number 0x01
+   *	Byte 1: magic number 0x03
+   *	Byte 2: normal = 0x10 (not checked, 0 is OK), separate I/D = 0x20
+   *	Byte 3: CPU type, Intel 16 bit = 0x04, Intel 32 bit = 0x10, 
+   *            Motorola = 0x0B, Sun SPARC = 0x17
+   *	Byte 4: Header length = 0x20
+   *	Bytes 5-7 are not used.
+   *
+   *	Now come the 6 longs
+   *	Bytes  8-11: size of text segments in bytes
+   *	Bytes 12-15: size of initialized data segment in bytes
+   *	Bytes 16-19: size of bss in bytes
+   *	Bytes 20-23: program entry point
+   *	Bytes 24-27: total memory allocated to program (text, data + stack)
+   *	Bytes 28-31: size of symbol table in bytes
+   * The longs are represented in a machine dependent order,
+   * little-endian on the 8088, big-endian on the 68000.
+   * The header is followed directly by the text and data segments, and the 
+   * symbol table (if any). The sizes are given in the header. Only the 
+   * text and data segments are copied into memory by exec. The header is 
+   * used here only. The symbol table is for the benefit of a debugger and 
+   * is ignored here.
+   */
+
+  if ((m= read(fd, &hdr, A_MINHDR)) < 2) return(ENOEXEC);
+
+  /* Interpreted script? */
+  if (((char *) &hdr)[0] == '#' && ((char *) &hdr)[1] == '!') return(ESCRIPT);
+
+  if (m != A_MINHDR) return(ENOEXEC);
+
+  /* Check magic number, cpu type, and flags. */
+  if (BADMAG(hdr)) return(ENOEXEC);
+#if (CHIP == INTEL && _WORD_SIZE == 2)
+  if (hdr.a_cpu != A_I8086) return(ENOEXEC);
+#endif
+#if (CHIP == INTEL && _WORD_SIZE == 4)
+  if (hdr.a_cpu != A_I80386) return(ENOEXEC);
+#endif
+  if ((hdr.a_flags & ~(A_NSYM | A_EXEC | A_SEP)) != 0) return(ENOEXEC);
+
+  *ft = ( (hdr.a_flags & A_SEP) ? SEPARATE : 0);    /* separate I & D or not */
+
+  /* Get text and data sizes. */
+  *text_bytes = (vir_bytes) hdr.a_text;	/* text size in bytes */
+  *data_bytes = (vir_bytes) hdr.a_data;	/* data size in bytes */
+  *bss_bytes  = (vir_bytes) hdr.a_bss;	/* bss size in bytes */
+  *tot_bytes  = hdr.a_total;		/* total bytes to allocate for prog */
+  *sym_bytes  = hdr.a_syms;		/* symbol table size in bytes */
+  if (*tot_bytes == 0) return(ENOEXEC);
+
+  if (*ft != SEPARATE) {
+	/* If I & D space is not separated, it is all considered data. Text=0*/
+	*data_bytes += *text_bytes;
+	*text_bytes = 0;
+  }
+  *pc = hdr.a_entry;	/* initial address to start execution */
+
+  /* Check to see if segment sizes are feasible. */
+  tc = ((unsigned long) *text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+  dc = (*data_bytes + *bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+  totc = (*tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+  if (dc >= totc) return(ENOEXEC);	/* stack must be at least 1 click */
+  dvir = (*ft == SEPARATE ? 0 : tc);
+  s_vir = dvir + (totc - sc);
+#if (CHIP == INTEL && _WORD_SIZE == 2)
+  m = size_ok(*ft, tc, dc, sc, dvir, s_vir);
+#else
+  m = (dvir + dc > s_vir) ? ENOMEM : OK;
+#endif
+  ct = hdr.a_hdrlen & BYTE;		/* header length */
+  if (ct > A_MINHDR) lseek(fd, (off_t) ct, SEEK_SET); /* skip unused hdr */
+  return(m);
+}
+
+/*===========================================================================*
+ *				new_mem					     *
+ *===========================================================================*/
+PRIVATE int new_mem(sh_mp, text_bytes, data_bytes,
+	bss_bytes,stk_bytes,tot_bytes)
+struct mproc *sh_mp;		/* text can be shared with this process */
+vir_bytes text_bytes;		/* text segment size in bytes */
+vir_bytes data_bytes;		/* size of initialized data in bytes */
+vir_bytes bss_bytes;		/* size of bss in bytes */
+vir_bytes stk_bytes;		/* size of initial stack segment in bytes */
+phys_bytes tot_bytes;		/* total memory to allocate, including gap */
+{
+/* Allocate new memory and release the old memory.  Change the map and report
+ * the new map to the kernel.  Zero the new core image's bss, gap and stack.
+ */
+
+  register struct mproc *rmp = mp;
+  vir_clicks text_clicks, data_clicks, gap_clicks, stack_clicks, tot_clicks;
+  phys_clicks new_base;
+  phys_bytes bytes, base, bss_offset;
+  int s, r2;
+
+  /* No need to allocate text if it can be shared. */
+  if (sh_mp != NULL) text_bytes = 0;
+
+  /* Allow the old data to be swapped out to make room.  (Which is really a
+   * waste of time, because we are going to throw it away anyway.)
+   */
+  rmp->mp_flags |= WAITING;
+
+  /* Acquire the new memory.  Each of the 4 parts: text, (data+bss), gap,
+   * and stack occupies an integral number of clicks, starting at click
+   * boundary.  The data and bss parts are run together with no space.
+   */
+  text_clicks = ((unsigned long) text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+  data_clicks = (data_bytes + bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+  stack_clicks = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+  tot_clicks = (tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+  gap_clicks = tot_clicks - data_clicks - stack_clicks;
+  if ( (int) gap_clicks < 0) return(ENOMEM);
+
+  /* Try to allocate memory for the new process. */
+  new_base = alloc_mem(text_clicks + tot_clicks);
+  if (new_base == NO_MEM) return(ENOMEM);
+
+  /* We've got memory for the new core image.  Release the old one. */
+  rmp = mp;
+
+  if (find_share(rmp, rmp->mp_ino, rmp->mp_dev, rmp->mp_ctime) == NULL) {
+	/* No other process shares the text segment, so free it. */
+	free_mem(rmp->mp_seg[T].mem_phys, rmp->mp_seg[T].mem_len);
+  }
+  /* Free the data and stack segments. */
+  free_mem(rmp->mp_seg[D].mem_phys,
+   rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);
+
+  /* We have now passed the point of no return.  The old core image has been
+   * forever lost, memory for a new core image has been allocated.  Set up
+   * and report new map.
+   */
+  if (sh_mp != NULL) {
+	/* Share the text segment. */
+	rmp->mp_seg[T] = sh_mp->mp_seg[T];
+  } else {
+	rmp->mp_seg[T].mem_phys = new_base;
+	rmp->mp_seg[T].mem_vir = 0;
+	rmp->mp_seg[T].mem_len = text_clicks;
+  }
+  rmp->mp_seg[D].mem_phys = new_base + text_clicks;
+  rmp->mp_seg[D].mem_vir = 0;
+  rmp->mp_seg[D].mem_len = data_clicks;
+  rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + data_clicks + gap_clicks;
+  rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir + data_clicks + gap_clicks;
+  rmp->mp_seg[S].mem_len = stack_clicks;
+
+#if (CHIP == M68000)
+  rmp->mp_seg[T].mem_vir = 0;
+  rmp->mp_seg[D].mem_vir = rmp->mp_seg[T].mem_len;
+  rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir 
+  	+ rmp->mp_seg[D].mem_len + gap_clicks;
+#endif
+
+  if((r2=sys_newmap(who_e, rmp->mp_seg)) != OK) {
+	/* report new map to the kernel */
+	panic(__FILE__,"sys_newmap failed", r2);
+  }
+
+  /* The old memory may have been swapped out, but the new memory is real. */
+  rmp->mp_flags &= ~(WAITING|ONSWAP|SWAPIN);
+
+  /* Zero the bss, gap, and stack segment. */
+  bytes = (phys_bytes)(data_clicks + gap_clicks + stack_clicks) << CLICK_SHIFT;
+  base = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT;
+  bss_offset = (data_bytes >> CLICK_SHIFT) << CLICK_SHIFT;
+  base += bss_offset;
+  bytes -= bss_offset;
+
+  if ((s=sys_memset(0, base, bytes)) != OK) {
+	panic(__FILE__,"new_mem can't zero", s);
+  }
+
+  return(OK);
+}
+
+/*===========================================================================*
+ *				patch_ptr				     *
+ *===========================================================================*/
+PRIVATE void patch_ptr(stack, base)
+char stack[ARG_MAX];		/* pointer to stack image within PM */
+vir_bytes base;			/* virtual address of stack base inside user */
+{
+/* When doing an exec(name, argv, envp) call, the user builds up a stack
+ * image with arg and env pointers relative to the start of the stack.  Now
+ * these pointers must be relocated, since the stack is not positioned at
+ * address 0 in the user's address space.
+ */
+
+  char **ap, flag;
+  vir_bytes v;
+
+  flag = 0;			/* counts number of 0-pointers seen */
+  ap = (char **) stack;		/* points initially to 'nargs' */
+  ap++;				/* now points to argv[0] */
+  while (flag < 2) {
+	if (ap >= (char **) &stack[ARG_MAX]) return;	/* too bad */
+	if (*ap != NULL) {
+		v = (vir_bytes) *ap;	/* v is relative pointer */
+		v += base;		/* relocate it */
+		*ap = (char *) v;	/* put it back */
+	} else {
+		flag++;
+	}
+	ap++;
+  }
+}
+
+/*===========================================================================*
+ *				insert_arg				     *
+ *===========================================================================*/
+PRIVATE int insert_arg(stack, stk_bytes, arg, replace)
+char stack[ARG_MAX];		/* pointer to stack image within PM */
+vir_bytes *stk_bytes;		/* size of initial stack */
+char *arg;			/* argument to prepend/replace as new argv[0] */
+int replace;
+{
+/* Patch the stack so that arg will become argv[0].  Be careful, the stack may
+ * be filled with garbage, although it normally looks like this:
+ *	nargs argv[0] ... argv[nargs-1] NULL envp[0] ... NULL
+ * followed by the strings "pointed" to by the argv[i] and the envp[i].  The
+ * pointers are really offsets from the start of stack.
+ * Return true iff the operation succeeded.
+ */
+  int offset, a0, a1, old_bytes = *stk_bytes;
+
+  /* Prepending arg adds at least one string and a zero byte. */
+  offset = strlen(arg) + 1;
+
+  a0 = (int) ((char **) stack)[1];	/* argv[0] */
+  if (a0 < 4 * PTRSIZE || a0 >= old_bytes) return(FALSE);
+
+  a1 = a0;			/* a1 will point to the strings to be moved */
+  if (replace) {
+	/* Move a1 to the end of argv[0][] (argv[1] if nargs > 1). */
+	do {
+		if (a1 == old_bytes) return(FALSE);
+		--offset;
+	} while (stack[a1++] != 0);
+  } else {
+	offset += PTRSIZE;	/* new argv[0] needs new pointer in argv[] */
+	a0 += PTRSIZE;		/* location of new argv[0][]. */
+  }
+
+  /* stack will grow by offset bytes (or shrink by -offset bytes) */
+  if ((*stk_bytes += offset) > ARG_MAX) return(FALSE);
+
+  /* Reposition the strings by offset bytes */
+  memmove(stack + a1 + offset, stack + a1, old_bytes - a1);
+
+  strcpy(stack + a0, arg);	/* Put arg in the new space. */
+
+  if (!replace) {
+	/* Make space for a new argv[0]. */
+	memmove(stack + 2 * PTRSIZE, stack + 1 * PTRSIZE, a0 - 2 * PTRSIZE);
+
+	((char **) stack)[0]++;	/* nargs++; */
+  }
+  /* Now patch up argv[] and envp[] by offset. */
+  patch_ptr(stack, (vir_bytes) offset);
+  ((char **) stack)[1] = (char *) a0;	/* set argv[0] correctly */
+  return(TRUE);
+}
+
+/*===========================================================================*
+ *				patch_stack				     *
+ *===========================================================================*/
+PRIVATE char *patch_stack(fd, stack, stk_bytes, script)
+int fd;				/* file descriptor to open script file */
+char stack[ARG_MAX];		/* pointer to stack image within PM */
+vir_bytes *stk_bytes;		/* size of initial stack */
+char *script;			/* name of script to interpret */
+{
+/* Patch the argument vector to include the path name of the script to be
+ * interpreted, and all strings on the #! line.  Returns the path name of
+ * the interpreter.
+ */
+  char *sp, *interp = NULL;
+  int n;
+  enum { INSERT=FALSE, REPLACE=TRUE };
+
+  /* Make script[] the new argv[0]. */
+  if (!insert_arg(stack, stk_bytes, script, REPLACE)) return(NULL);
+
+  if (lseek(fd, 2L, 0) == -1			/* just behind the #! */
+    || (n= read(fd, script, PATH_MAX)) < 0	/* read line one */
+    || (sp= memchr(script, '\n', n)) == NULL)	/* must be a proper line */
+	return(NULL);
+
+  /* Move sp backwards through script[], prepending each string to stack. */
+  for (;;) {
+	/* skip spaces behind argument. */
+	while (sp > script && (*--sp == ' ' || *sp == '\t')) {}
+	if (sp == script) break;
+
+	sp[1] = 0;
+	/* Move to the start of the argument. */
+	while (sp > script && sp[-1] != ' ' && sp[-1] != '\t') --sp;
+
+	interp = sp;
+	if (!insert_arg(stack, stk_bytes, sp, INSERT)) return(NULL);
+  }
+
+  /* Round *stk_bytes up to the size of a pointer for alignment contraints. */
+  *stk_bytes= ((*stk_bytes + PTRSIZE - 1) / PTRSIZE) * PTRSIZE;
+
+  close(fd);
+  return(interp);
+}
+
+/*===========================================================================*
+ *				rw_seg					     *
+ *===========================================================================*/
+PUBLIC void rw_seg(rw, fd, proc_e, seg, seg_bytes0)
+int rw;				/* 0 = read, 1 = write */
+int fd;				/* file descriptor to read from / write to */
+int proc_e;			/* process number (endpoint) */
+int seg;			/* T, D, or S */
+phys_bytes seg_bytes0;		/* how much is to be transferred? */
+{
+/* Transfer text or data from/to a file and copy to/from a process segment.
+ * This procedure is a little bit tricky.  The logical way to transfer a
+ * segment would be block by block and copying each block to/from the user
+ * space one at a time.  This is too slow, so we do something dirty here,
+ * namely send the user space and virtual address to the file system in the
+ * upper 10 bits of the file descriptor, and pass it the user virtual address
+ * instead of a PM address.  The file system extracts these parameters when 
+ * gets a read or write call from the process manager, which is the only 
+ * process that is permitted to use this trick.  The file system then copies 
+ * the whole segment directly to/from user space, bypassing PM completely.
+ *
+ * The byte count on read is usually smaller than the segment count, because
+ * a segment is padded out to a click multiple, and the data segment is only
+ * partially initialized.
+ */
+
+  int bytes, r, proc_n;
+  char *ubuf_ptr;
+  struct mem_map *sp;
+  phys_bytes seg_bytes = seg_bytes0;
+
+  if(pm_isokendpt(proc_e, &proc_n) != OK || proc_n < 0)
+	return;
+
+  sp = &mproc[proc_n].mp_seg[seg];
+
+  ubuf_ptr = (char *) ((vir_bytes) sp->mem_vir << CLICK_SHIFT);
+
+  while (seg_bytes != 0) {
+#define PM_CHUNK_SIZE 8192
+	bytes = MIN((INT_MAX / PM_CHUNK_SIZE) * PM_CHUNK_SIZE, seg_bytes);
+	if(!rw) {
+		r = _read_pm(fd, ubuf_ptr, bytes, seg, proc_e);
+	} else {
+		r = _write_pm(fd, ubuf_ptr, bytes, seg, proc_e);
+	}
+	if (r != bytes) break;
+	ubuf_ptr += bytes;
+	seg_bytes -= bytes;
+  }
+}
+
+/*===========================================================================*
+ *				find_share				     *
+ *===========================================================================*/
+PUBLIC struct mproc *find_share(mp_ign, ino, dev, ctime)
+struct mproc *mp_ign;		/* process that should not be looked at */
+ino_t ino;			/* parameters that uniquely identify a file */
+dev_t dev;
+time_t ctime;
+{
+/* Look for a process that is the file <ino, dev, ctime> in execution.  Don't
+ * accidentally "find" mp_ign, because it is the process on whose behalf this
+ * call is made.
+ */
+  struct mproc *sh_mp;
+  for (sh_mp = &mproc[0]; sh_mp < &mproc[NR_PROCS]; sh_mp++) {
+
+	if (!(sh_mp->mp_flags & SEPARATE)) continue;
+	if (sh_mp == mp_ign) continue;
+	if (sh_mp->mp_ino != ino) continue;
+	if (sh_mp->mp_dev != dev) continue;
+	if (sh_mp->mp_ctime != ctime) continue;
+	return sh_mp;
+  }
+  return(NULL);
+}
Index: /trunk/minix/servers/pm/forkexit.c
===================================================================
--- /trunk/minix/servers/pm/forkexit.c	(revision 9)
+++ /trunk/minix/servers/pm/forkexit.c	(revision 9)
@@ -0,0 +1,312 @@
+/* This file deals with creating processes (via FORK) and deleting them (via
+ * EXIT/WAIT).  When a process forks, a new slot in the 'mproc' table is
+ * allocated for it, and a copy of the parent's core image is made for the
+ * child.  Then the kernel and file system are informed.  A process is removed
+ * from the 'mproc' table when two events have occurred: (1) it has exited or
+ * been killed by a signal, and (2) the parent has done a WAIT.  If the process
+ * exits first, it continues to occupy a slot until the parent does a WAIT.
+ *
+ * The entry points into this file are:
+ *   do_fork:	 perform the FORK system call
+ *   do_pm_exit: perform the EXIT system call (by calling pm_exit())
+ *   pm_exit:	 actually do the exiting
+ *   do_wait:	 perform the WAITPID or WAIT system call
+ */
+
+#include "pm.h"
+#include <sys/wait.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <sys/resource.h>
+#include <signal.h>
+#include "mproc.h"
+#include "param.h"
+
+#define LAST_FEW            2	/* last few slots reserved for superuser */
+
+FORWARD _PROTOTYPE (void cleanup, (register struct mproc *child) );
+
+/*===========================================================================*
+ *				do_fork					     *
+ *===========================================================================*/
+PUBLIC int do_fork()
+{
+/* The process pointed to by 'mp' has forked.  Create a child process. */
+  register struct mproc *rmp;	/* pointer to parent */
+  register struct mproc *rmc;	/* pointer to child */
+  int child_nr, s;
+  phys_clicks prog_clicks, child_base;
+  phys_bytes prog_bytes, parent_abs, child_abs;	/* Intel only */
+  pid_t new_pid;
+  static int next_child;
+  int n = 0, r;
+
+ /* If tables might fill up during FORK, don't even start since recovery half
+  * way through is such a nuisance.
+  */
+  rmp = mp;
+  if ((procs_in_use == NR_PROCS) || 
+  		(procs_in_use >= NR_PROCS-LAST_FEW && rmp->mp_effuid != 0))
+  {
+  	printf("PM: warning, process table is full!\n");
+  	return(EAGAIN);
+  }
+
+  /* Determine how much memory to allocate.  Only the data and stack need to
+   * be copied, because the text segment is either shared or of zero length.
+   */
+  prog_clicks = (phys_clicks) rmp->mp_seg[S].mem_len;
+  prog_clicks += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
+  prog_bytes = (phys_bytes) prog_clicks << CLICK_SHIFT;
+  if ( (child_base = alloc_mem(prog_clicks)) == NO_MEM) return(ENOMEM);
+
+  /* Create a copy of the parent's core image for the child. */
+  child_abs = (phys_bytes) child_base << CLICK_SHIFT;
+  parent_abs = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT;
+  s = sys_abscopy(parent_abs, child_abs, prog_bytes);
+  if (s < 0) panic(__FILE__,"do_fork can't copy", s);
+
+  /* Find a slot in 'mproc' for the child process.  A slot must exist. */
+  do {
+        next_child = (next_child+1) % NR_PROCS;
+	n++;
+  } while((mproc[next_child].mp_flags & IN_USE) && n <= NR_PROCS);
+  if(n > NR_PROCS)
+	panic(__FILE__,"do_fork can't find child slot", NO_NUM);
+  if(next_child < 0 || next_child >= NR_PROCS
+ || (mproc[next_child].mp_flags & IN_USE))
+	panic(__FILE__,"do_fork finds wrong child slot", next_child);
+
+  rmc = &mproc[next_child];
+  /* Set up the child and its memory map; copy its 'mproc' slot from parent. */
+  child_nr = (int)(rmc - mproc);	/* slot number of the child */
+  procs_in_use++;
+  *rmc = *rmp;			/* copy parent's process slot to child's */
+  rmc->mp_parent = who_p;			/* record child's parent */
+  /* inherit only these flags */
+  rmc->mp_flags &= (IN_USE|SEPARATE|PRIV_PROC|DONT_SWAP);
+  rmc->mp_child_utime = 0;		/* reset administration */
+  rmc->mp_child_stime = 0;		/* reset administration */
+
+  /* A separate I&D child keeps the parents text segment.  The data and stack
+   * segments must refer to the new copy.
+   */
+  if (!(rmc->mp_flags & SEPARATE)) rmc->mp_seg[T].mem_phys = child_base;
+  rmc->mp_seg[D].mem_phys = child_base;
+  rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys + 
+			(rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
+  rmc->mp_exitstatus = 0;
+  rmc->mp_sigstatus = 0;
+
+  /* Find a free pid for the child and put it in the table. */
+  new_pid = get_free_pid();
+  rmc->mp_pid = new_pid;	/* assign pid to child */
+
+  /* Tell kernel and file system about the (now successful) FORK. */
+  if((r=sys_fork(who_e, child_nr, &rmc->mp_endpoint)) != OK) {
+  	panic(__FILE__,"do_fork can't sys_fork", r);
+  }
+  tell_fs(FORK, who_e, rmc->mp_endpoint, rmc->mp_pid);
+
+  /* Report child's memory map to kernel. */
+  if((r=sys_newmap(rmc->mp_endpoint, rmc->mp_seg)) != OK) {
+  	panic(__FILE__,"do_fork can't sys_newmap", r);
+  }
+
+  /* Reply to child to wake it up. */
+  setreply(child_nr, 0);		/* only parent gets details */
+  rmp->mp_reply.endpt = rmc->mp_endpoint;	/* child's process number */
+
+  return(new_pid);		 	/* child's pid */
+}
+
+/*===========================================================================*
+ *				do_pm_exit				     *
+ *===========================================================================*/
+PUBLIC int do_pm_exit()
+{
+/* Perform the exit(status) system call. The real work is done by pm_exit(),
+ * which is also called when a process is killed by a signal.
+ */
+  pm_exit(mp, m_in.status);
+  return(SUSPEND);		/* can't communicate from beyond the grave */
+}
+
+/*===========================================================================*
+ *				pm_exit					     *
+ *===========================================================================*/
+PUBLIC void pm_exit(rmp, exit_status)
+register struct mproc *rmp;	/* pointer to the process to be terminated */
+int exit_status;		/* the process' exit status (for parent) */
+{
+/* A process is done.  Release most of the process' possessions.  If its
+ * parent is waiting, release the rest, else keep the process slot and
+ * become a zombie.
+ */
+  register int proc_nr, proc_nr_e;
+  int parent_waiting, right_child, r;
+  pid_t pidarg, procgrp;
+  struct mproc *p_mp;
+  clock_t t[5];
+
+  proc_nr = (int) (rmp - mproc);	/* get process slot number */
+  proc_nr_e = rmp->mp_endpoint;
+
+  /* Remember a session leader's process group. */
+  procgrp = (rmp->mp_pid == mp->mp_procgrp) ? mp->mp_procgrp : 0;
+
+  /* If the exited process has a timer pending, kill it. */
+  if (rmp->mp_flags & ALARM_ON) set_alarm(proc_nr_e, (unsigned) 0);
+
+  /* Do accounting: fetch usage times and accumulate at parent. */
+  if((r=sys_times(proc_nr_e, t)) != OK)
+  	panic(__FILE__,"pm_exit: sys_times failed", r);
+
+  p_mp = &mproc[rmp->mp_parent];			/* process' parent */
+  p_mp->mp_child_utime += t[0] + rmp->mp_child_utime;	/* add user time */
+  p_mp->mp_child_stime += t[1] + rmp->mp_child_stime;	/* add system time */
+
+  /* Tell the kernel the process is no longer runnable to prevent it from 
+   * being scheduled in between the following steps. Then tell FS that it 
+   * the process has exited and finally, clean up the process at the kernel.
+   * This order is important so that FS can tell drivers to cancel requests
+   * such as copying to/ from the exiting process, before it is gone.
+   */
+  sys_nice(proc_nr_e, PRIO_STOP);	/* stop the process */
+  if(proc_nr_e != FS_PROC_NR)		/* if it is not FS that is exiting.. */
+	tell_fs(EXIT, proc_nr_e, 0, 0);  	/* tell FS to free the slot */
+  else
+	printf("PM: FS died\n");
+  if((r=sys_exit(proc_nr_e)) != OK)	/* destroy the process */
+  	panic(__FILE__,"pm_exit: sys_exit failed", r);
+
+  /* Pending reply messages for the dead process cannot be delivered. */
+  rmp->mp_flags &= ~REPLY;
+  
+  /* Release the memory occupied by the child. */
+  if (find_share(rmp, rmp->mp_ino, rmp->mp_dev, rmp->mp_ctime) == NULL) {
+	/* No other process shares the text segment, so free it. */
+	free_mem(rmp->mp_seg[T].mem_phys, rmp->mp_seg[T].mem_len);
+  }
+  /* Free the data and stack segments. */
+  free_mem(rmp->mp_seg[D].mem_phys,
+      rmp->mp_seg[S].mem_vir 
+        + rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);
+
+  /* The process slot can only be freed if the parent has done a WAIT. */
+  rmp->mp_exitstatus = (char) exit_status;
+
+  pidarg = p_mp->mp_wpid;		/* who's being waited for? */
+  parent_waiting = p_mp->mp_flags & WAITING;
+  right_child =				/* child meets one of the 3 tests? */
+	(pidarg == -1 || pidarg == rmp->mp_pid || -pidarg == rmp->mp_procgrp);
+
+  if (parent_waiting && right_child) {
+	cleanup(rmp);			/* tell parent and release child slot */
+  } else {
+	rmp->mp_flags = IN_USE|ZOMBIE;	/* parent not waiting, zombify child */
+	sig_proc(p_mp, SIGCHLD);	/* send parent a "child died" signal */
+  }
+
+  /* If the process has children, disinherit them.  INIT is the new parent. */
+  for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
+	if (rmp->mp_flags & IN_USE && rmp->mp_parent == proc_nr) {
+		/* 'rmp' now points to a child to be disinherited. */
+		rmp->mp_parent = INIT_PROC_NR;
+		parent_waiting = mproc[INIT_PROC_NR].mp_flags & WAITING;
+		if (parent_waiting && (rmp->mp_flags & ZOMBIE)) cleanup(rmp);
+	}
+  }
+
+  /* Send a hangup to the process' process group if it was a session leader. */
+  if (procgrp != 0) check_sig(-procgrp, SIGHUP);
+}
+
+/*===========================================================================*
+ *				do_waitpid				     *
+ *===========================================================================*/
+PUBLIC int do_waitpid()
+{
+/* A process wants to wait for a child to terminate. If a child is already 
+ * waiting, go clean it up and let this WAIT call terminate.  Otherwise, 
+ * really wait. 
+ * A process calling WAIT never gets a reply in the usual way at the end
+ * of the main loop (unless WNOHANG is set or no qualifying child exists).
+ * If a child has already exited, the routine cleanup() sends the reply
+ * to awaken the caller.
+ * Both WAIT and WAITPID are handled by this code.
+ */
+  register struct mproc *rp;
+  int pidarg, options, children;
+
+  /* Set internal variables, depending on whether this is WAIT or WAITPID. */
+  pidarg  = (call_nr == WAIT ? -1 : m_in.pid);	   /* 1st param of waitpid */
+  options = (call_nr == WAIT ?  0 : m_in.sig_nr);  /* 3rd param of waitpid */
+  if (pidarg == 0) pidarg = -mp->mp_procgrp;	/* pidarg < 0 ==> proc grp */
+
+  /* Is there a child waiting to be collected? At this point, pidarg != 0:
+   *	pidarg  >  0 means pidarg is pid of a specific process to wait for
+   *	pidarg == -1 means wait for any child
+   *	pidarg  < -1 means wait for any child whose process group = -pidarg
+   */
+  children = 0;
+  for (rp = &mproc[0]; rp < &mproc[NR_PROCS]; rp++) {
+	if ( (rp->mp_flags & IN_USE) && rp->mp_parent == who_p) {
+		/* The value of pidarg determines which children qualify. */
+		if (pidarg  > 0 && pidarg != rp->mp_pid) continue;
+		if (pidarg < -1 && -pidarg != rp->mp_procgrp) continue;
+
+		children++;		/* this child is acceptable */
+		if (rp->mp_flags & ZOMBIE) {
+			/* This child meets the pid test and has exited. */
+			cleanup(rp);	/* this child has already exited */
+			return(SUSPEND);
+		}
+		if ((rp->mp_flags & STOPPED) && rp->mp_sigstatus) {
+			/* This child meets the pid test and is being traced.*/
+			mp->mp_reply.reply_res2 = 0177|(rp->mp_sigstatus << 8);
+			rp->mp_sigstatus = 0;
+			return(rp->mp_pid);
+		}
+	}
+  }
+
+  /* No qualifying child has exited.  Wait for one, unless none exists. */
+  if (children > 0) {
+	/* At least 1 child meets the pid test exists, but has not exited. */
+	if (options & WNOHANG) return(0);    /* parent does not want to wait */
+	mp->mp_flags |= WAITING;	     /* parent wants to wait */
+	mp->mp_wpid = (pid_t) pidarg;	     /* save pid for later */
+	return(SUSPEND);		     /* do not reply, let it wait */
+  } else {
+	/* No child even meets the pid test.  Return error immediately. */
+	return(ECHILD);			     /* no - parent has no children */
+  }
+}
+
+/*===========================================================================*
+ *				cleanup					     *
+ *===========================================================================*/
+PRIVATE void cleanup(child)
+register struct mproc *child;	/* tells which process is exiting */
+{
+/* Finish off the exit of a process.  The process has exited or been killed
+ * by a signal, and its parent is waiting.
+ */
+  struct mproc *parent = &mproc[child->mp_parent];
+  int exitstatus;
+
+  /* Wake up the parent by sending the reply message. */
+  exitstatus = (child->mp_exitstatus << 8) | (child->mp_sigstatus & 0377);
+  parent->mp_reply.reply_res2 = exitstatus;
+  setreply(child->mp_parent, child->mp_pid);
+  parent->mp_flags &= ~WAITING;		/* parent no longer waiting */
+
+  /* Release the process table entry and reinitialize some field. */
+  child->mp_pid = 0;
+  child->mp_flags = 0;
+  child->mp_child_utime = 0;
+  child->mp_child_stime = 0;
+  procs_in_use--;
+}
+
Index: /trunk/minix/servers/pm/getset.c
===================================================================
--- /trunk/minix/servers/pm/getset.c	(revision 9)
+++ /trunk/minix/servers/pm/getset.c	(revision 9)
@@ -0,0 +1,83 @@
+/* This file handles the 4 system calls that get and set uids and gids.
+ * It also handles getpid(), setsid(), and getpgrp().  The code for each
+ * one is so tiny that it hardly seemed worthwhile to make each a separate
+ * function.
+ */
+
+#include "pm.h"
+#include <minix/callnr.h>
+#include <minix/endpoint.h>
+#include <signal.h>
+#include "mproc.h"
+#include "param.h"
+
+/*===========================================================================*
+ *				do_getset				     *
+ *===========================================================================*/
+PUBLIC int do_getset()
+{
+/* Handle GETUID, GETGID, GETPID, GETPGRP, SETUID, SETGID, SETSID.  The four
+ * GETs and SETSID return their primary results in 'r'.  GETUID, GETGID, and
+ * GETPID also return secondary results (the effective IDs, or the parent
+ * process ID) in 'reply_res2', which is returned to the user.
+ */
+
+  register struct mproc *rmp = mp;
+  int r, proc;
+
+  switch(call_nr) {
+	case GETUID:
+		r = rmp->mp_realuid;
+		rmp->mp_reply.reply_res2 = rmp->mp_effuid;
+		break;
+
+	case GETGID:
+		r = rmp->mp_realgid;
+		rmp->mp_reply.reply_res2 = rmp->mp_effgid;
+		break;
+
+	case GETPID:
+		r = mproc[who_p].mp_pid;
+		rmp->mp_reply.reply_res2 = mproc[rmp->mp_parent].mp_pid;
+		if(pm_isokendpt(m_in.endpt, &proc) == OK && proc >= 0)
+			rmp->mp_reply.reply_res3 = mproc[proc].mp_pid;
+		break;
+
+	case SETEUID:
+	case SETUID:
+		if (rmp->mp_realuid != (uid_t) m_in.usr_id && 
+				rmp->mp_effuid != SUPER_USER)
+			return(EPERM);
+		if(call_nr == SETUID) rmp->mp_realuid = (uid_t) m_in.usr_id;
+		rmp->mp_effuid = (uid_t) m_in.usr_id;
+		tell_fs(SETUID, who_e, rmp->mp_realuid, rmp->mp_effuid);
+		r = OK;
+		break;
+
+	case SETEGID:
+	case SETGID:
+		if (rmp->mp_realgid != (gid_t) m_in.grp_id && 
+				rmp->mp_effuid != SUPER_USER)
+			return(EPERM);
+		if(call_nr == SETGID) rmp->mp_realgid = (gid_t) m_in.grp_id;
+		rmp->mp_effgid = (gid_t) m_in.grp_id;
+		tell_fs(SETGID, who_e, rmp->mp_realgid, rmp->mp_effgid);
+		r = OK;
+		break;
+
+	case SETSID:
+		if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM);
+		rmp->mp_procgrp = rmp->mp_pid;
+		tell_fs(SETSID, who_e, 0, 0);
+		/* fall through */
+
+	case GETPGRP:
+		r = rmp->mp_procgrp;
+		break;
+
+	default:
+		r = EINVAL;
+		break;	
+  }
+  return(r);
+}
Index: /trunk/minix/servers/pm/glo.h
===================================================================
--- /trunk/minix/servers/pm/glo.h	(revision 9)
+++ /trunk/minix/servers/pm/glo.h	(revision 9)
@@ -0,0 +1,22 @@
+/* EXTERN should be extern except in table.c */
+#ifdef _TABLE
+#undef EXTERN
+#define EXTERN
+#endif
+
+/* Global variables. */
+EXTERN struct mproc *mp;	/* ptr to 'mproc' slot of current process */
+EXTERN int procs_in_use;	/* how many processes are marked as IN_USE */
+EXTERN char monitor_params[128*sizeof(char *)];	/* boot monitor parameters */
+EXTERN struct kinfo kinfo;	/* kernel information */
+
+/* The parameters of the call are kept here. */
+EXTERN message m_in;		/* the incoming message itself is kept here. */
+EXTERN int who_p, who_e;	/* caller's proc number, endpoint */
+EXTERN int call_nr;		/* system call number */
+
+extern _PROTOTYPE (int (*call_vec[]), (void) );	/* system call handlers */
+extern char core_name[];	/* file name where core images are produced */
+EXTERN sigset_t core_sset;	/* which signals cause core images */
+EXTERN sigset_t ign_sset;	/* which signals are by default ignored */
+
Index: /trunk/minix/servers/pm/main.c
===================================================================
--- /trunk/minix/servers/pm/main.c	(revision 9)
+++ /trunk/minix/servers/pm/main.c	(revision 9)
@@ -0,0 +1,472 @@
+/* This file contains the main program of the process manager and some related
+ * procedures.  When MINIX starts up, the kernel runs for a little while,
+ * initializing itself and its tasks, and then it runs PM and FS.  Both PM
+ * and FS initialize themselves as far as they can. PM asks the kernel for
+ * all free memory and starts serving requests.
+ *
+ * The entry points into this file are:
+ *   main:	starts PM running
+ *   setreply:	set the reply to be sent to process making an PM system call
+ */
+
+#include "pm.h"
+#include <minix/keymap.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/endpoint.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/resource.h>
+#include <string.h>
+#include "mproc.h"
+#include "param.h"
+
+#include "../../kernel/const.h"
+#include "../../kernel/config.h"
+#include "../../kernel/type.h"
+#include "../../kernel/proc.h"
+
+FORWARD _PROTOTYPE( void get_work, (void)				);
+FORWARD _PROTOTYPE( void pm_init, (void)				);
+FORWARD _PROTOTYPE( int get_nice_value, (int queue)			);
+FORWARD _PROTOTYPE( void get_mem_chunks, (struct memory *mem_chunks) 	);
+FORWARD _PROTOTYPE( void patch_mem_chunks, (struct memory *mem_chunks, 
+	struct mem_map *map_ptr) 	);
+FORWARD _PROTOTYPE( void do_x86_vm, (struct memory mem_chunks[NR_MEMS])	);
+
+#define click_to_round_k(n) \
+	((unsigned) ((((unsigned long) (n) << CLICK_SHIFT) + 512) / 1024))
+
+/*===========================================================================*
+ *				main					     *
+ *===========================================================================*/
+PUBLIC int main()
+{
+/* Main routine of the process manager. */
+  int result, s, proc_nr;
+  struct mproc *rmp;
+  sigset_t sigset;
+
+  pm_init();			/* initialize process manager tables */
+
+  /* This is PM's main loop-  get work and do it, forever and forever. */
+  while (TRUE) {
+	get_work();		/* wait for an PM system call */
+
+	/* Check for system notifications first. Special cases. */
+	if (call_nr == SYN_ALARM) {
+		pm_expire_timers(m_in.NOTIFY_TIMESTAMP);
+		result = SUSPEND;		/* don't reply */
+	} else if (call_nr == SYS_SIG) {	/* signals pending */
+		sigset = m_in.NOTIFY_ARG;
+		if (sigismember(&sigset, SIGKSIG))  {
+			(void) ksig_pending();
+		} 
+		result = SUSPEND;		/* don't reply */
+	}
+	/* Else, if the system call number is valid, perform the call. */
+	else if ((unsigned) call_nr >= NCALLS) {
+		result = ENOSYS;
+	} else {
+		result = (*call_vec[call_nr])();
+	}
+
+	/* Send the results back to the user to indicate completion. */
+	if (result != SUSPEND) setreply(who_p, result);
+
+	swap_in();		/* maybe a process can be swapped in? */
+
+	/* Send out all pending reply messages, including the answer to
+	 * the call just made above.  The processes must not be swapped out.
+	 */
+	for (proc_nr=0, rmp=mproc; proc_nr < NR_PROCS; proc_nr++, rmp++) {
+		/* In the meantime, the process may have been killed by a
+		 * signal (e.g. if a lethal pending signal was unblocked)
+		 * without the PM realizing it. If the slot is no longer in
+		 * use or just a zombie, don't try to reply.
+		 */
+		if ((rmp->mp_flags & (REPLY | ONSWAP | IN_USE | ZOMBIE)) ==
+		   (REPLY | IN_USE)) {
+			if ((s=send(rmp->mp_endpoint, &rmp->mp_reply)) != OK) {
+				printf("PM can't reply to %d (%s)\n",
+					rmp->mp_endpoint, rmp->mp_name);
+				panic(__FILE__, "PM can't reply", NO_NUM);
+			}
+			rmp->mp_flags &= ~REPLY;
+		}
+	}
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *				get_work				     *
+ *===========================================================================*/
+PRIVATE void get_work()
+{
+/* Wait for the next message and extract useful information from it. */
+  if (receive(ANY, &m_in) != OK)
+	panic(__FILE__,"PM receive error", NO_NUM);
+  who_e = m_in.m_source;	/* who sent the message */
+  if(pm_isokendpt(who_e, &who_p) != OK)
+	panic(__FILE__, "PM got message from invalid endpoint", who_e);
+  call_nr = m_in.m_type;	/* system call number */
+
+  /* Process slot of caller. Misuse PM's own process slot if the kernel is
+   * calling. This can happen in case of synchronous alarms (CLOCK) or or 
+   * event like pending kernel signals (SYSTEM).
+   */
+  mp = &mproc[who_p < 0 ? PM_PROC_NR : who_p];
+  if(who_p >= 0 && mp->mp_endpoint != who_e) {
+	panic(__FILE__, "PM endpoint number out of sync with source",
+		mp->mp_endpoint);
+  }
+}
+
+/*===========================================================================*
+ *				setreply				     *
+ *===========================================================================*/
+PUBLIC void setreply(proc_nr, result)
+int proc_nr;			/* process to reply to */
+int result;			/* result of call (usually OK or error #) */
+{
+/* Fill in a reply message to be sent later to a user process.  System calls
+ * may occasionally fill in other fields, this is only for the main return
+ * value, and for setting the "must send reply" flag.
+ */
+  register struct mproc *rmp = &mproc[proc_nr];
+
+  if(proc_nr < 0 || proc_nr >= NR_PROCS)
+      panic(__FILE__,"setreply arg out of range", proc_nr);
+
+  rmp->mp_reply.reply_res = result;
+  rmp->mp_flags |= REPLY;	/* reply pending */
+
+  if (rmp->mp_flags & ONSWAP)
+	swap_inqueue(rmp);	/* must swap this process back in */
+}
+
+/*===========================================================================*
+ *				pm_init					     *
+ *===========================================================================*/
+PRIVATE void pm_init()
+{
+/* Initialize the process manager. 
+ * Memory use info is collected from the boot monitor, the kernel, and
+ * all processes compiled into the system image. Initially this information
+ * is put into an array mem_chunks. Elements of mem_chunks are struct memory,
+ * and hold base, size pairs in units of clicks. This array is small, there
+ * should be no more than 8 chunks. After the array of chunks has been built
+ * the contents are used to initialize the hole list. Space for the hole list
+ * is reserved as an array with twice as many elements as the maximum number
+ * of processes allowed. It is managed as a linked list, and elements of the
+ * array are struct hole, which, in addition to storage for a base and size in 
+ * click units also contain space for a link, a pointer to another element.
+*/
+  int s;
+  static struct boot_image image[NR_BOOT_PROCS];
+  register struct boot_image *ip;
+  static char core_sigs[] = { SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
+			SIGEMT, SIGFPE, SIGUSR1, SIGSEGV, SIGUSR2 };
+  static char ign_sigs[] = { SIGCHLD, SIGWINCH, SIGCONT };
+  static char mess_sigs[] = { SIGTERM, SIGHUP, SIGABRT, SIGQUIT };
+  register struct mproc *rmp;
+  register int i;
+  register char *sig_ptr;
+  phys_clicks total_clicks, minix_clicks, free_clicks;
+  message mess;
+  struct mem_map mem_map[NR_LOCAL_SEGS];
+  struct memory mem_chunks[NR_MEMS];
+
+  /* Initialize process table, including timers. */
+  for (rmp=&mproc[0]; rmp<&mproc[NR_PROCS]; rmp++) {
+	tmr_inittimer(&rmp->mp_timer);
+  }
+
+  /* Build the set of signals which cause core dumps, and the set of signals
+   * that are by default ignored.
+   */
+  sigemptyset(&core_sset);
+  for (sig_ptr = core_sigs; sig_ptr < core_sigs+sizeof(core_sigs); sig_ptr++)
+	sigaddset(&core_sset, *sig_ptr);
+  sigemptyset(&ign_sset);
+  for (sig_ptr = ign_sigs; sig_ptr < ign_sigs+sizeof(ign_sigs); sig_ptr++)
+	sigaddset(&ign_sset, *sig_ptr);
+
+  /* Obtain a copy of the boot monitor parameters and the kernel info struct.  
+   * Parse the list of free memory chunks. This list is what the boot monitor 
+   * reported, but it must be corrected for the kernel and system processes.
+   */
+  if ((s=sys_getmonparams(monitor_params, sizeof(monitor_params))) != OK)
+      panic(__FILE__,"get monitor params failed",s);
+  get_mem_chunks(mem_chunks);
+  if ((s=sys_getkinfo(&kinfo)) != OK)
+      panic(__FILE__,"get kernel info failed",s);
+
+  /* Get the memory map of the kernel to see how much memory it uses. */
+  if ((s=get_mem_map(SYSTASK, mem_map)) != OK)
+  	panic(__FILE__,"couldn't get memory map of SYSTASK",s);
+  minix_clicks = (mem_map[S].mem_phys+mem_map[S].mem_len)-mem_map[T].mem_phys;
+  patch_mem_chunks(mem_chunks, mem_map);
+
+  /* Initialize PM's process table. Request a copy of the system image table 
+   * that is defined at the kernel level to see which slots to fill in.
+   */
+  if (OK != (s=sys_getimage(image))) 
+  	panic(__FILE__,"couldn't get image table: %d\n", s);
+  procs_in_use = 0;				/* start populating table */
+  printf("Building process table:");		/* show what's happening */
+  for (ip = &image[0]; ip < &image[NR_BOOT_PROCS]; ip++) {		
+  	if (ip->proc_nr >= 0) {			/* task have negative nrs */
+  		procs_in_use += 1;		/* found user process */
+
+		/* Set process details found in the image table. */
+		rmp = &mproc[ip->proc_nr];	
+  		strncpy(rmp->mp_name, ip->proc_name, PROC_NAME_LEN); 
+		rmp->mp_parent = RS_PROC_NR;
+		rmp->mp_nice = get_nice_value(ip->priority);
+  		sigemptyset(&rmp->mp_sig2mess);
+  		sigemptyset(&rmp->mp_ignore);	
+  		sigemptyset(&rmp->mp_sigmask);
+  		sigemptyset(&rmp->mp_catch);
+		if (ip->proc_nr == INIT_PROC_NR) {	/* user process */
+  			rmp->mp_procgrp = rmp->mp_pid = INIT_PID;
+			rmp->mp_flags |= IN_USE; 
+		}
+		else {					/* system process */
+  			rmp->mp_pid = get_free_pid();
+			rmp->mp_flags |= IN_USE | DONT_SWAP | PRIV_PROC; 
+  			for (sig_ptr = mess_sigs; 
+				sig_ptr < mess_sigs+sizeof(mess_sigs); 
+				sig_ptr++)
+			sigaddset(&rmp->mp_sig2mess, *sig_ptr);
+		}
+
+		/* Get kernel endpoint identifier. */
+		rmp->mp_endpoint = ip->endpoint;
+
+  		/* Get memory map for this process from the kernel. */
+		if ((s=get_mem_map(ip->proc_nr, rmp->mp_seg)) != OK)
+  			panic(__FILE__,"couldn't get process entry",s);
+		if (rmp->mp_seg[T].mem_len != 0) rmp->mp_flags |= SEPARATE;
+		minix_clicks += rmp->mp_seg[S].mem_phys + 
+			rmp->mp_seg[S].mem_len - rmp->mp_seg[T].mem_phys;
+  		patch_mem_chunks(mem_chunks, rmp->mp_seg);
+
+		/* Tell FS about this system process. */
+		mess.PR_SLOT = ip->proc_nr;
+		mess.PR_PID = rmp->mp_pid;
+		mess.PR_ENDPT = rmp->mp_endpoint;
+  		if (OK != (s=send(FS_PROC_NR, &mess)))
+			panic(__FILE__,"can't sync up with FS", s);
+  		printf(" %s", ip->proc_name);	/* display process name */
+  	}
+  }
+  printf(".\n");				/* last process done */
+
+  /* Override some details. INIT, PM, FS and RS are somewhat special. */
+  mproc[PM_PROC_NR].mp_pid = PM_PID;		/* PM has magic pid */
+  mproc[RS_PROC_NR].mp_parent = INIT_PROC_NR;	/* INIT is root */
+  sigfillset(&mproc[PM_PROC_NR].mp_ignore); 	/* guard against signals */
+
+  /* Tell FS that no more system processes follow and synchronize. */
+  mess.PR_ENDPT = NONE;
+  if (sendrec(FS_PROC_NR, &mess) != OK || mess.m_type != OK)
+	panic(__FILE__,"can't sync up with FS", NO_NUM);
+
+#if ENABLE_BOOTDEV
+  /* Possibly we must correct the memory chunks for the boot device. */
+  if (kinfo.bootdev_size > 0) {
+      mem_map[T].mem_phys = kinfo.bootdev_base >> CLICK_SHIFT;
+      mem_map[T].mem_len = 0;
+      mem_map[D].mem_len = (kinfo.bootdev_size+CLICK_SIZE-1) >> CLICK_SHIFT;
+      patch_mem_chunks(mem_chunks, mem_map);
+  }
+#endif /* ENABLE_BOOTDEV */
+
+  /* Withhold some memory from x86 VM */
+  do_x86_vm(mem_chunks);
+
+  /* Initialize tables to all physical memory and print memory information. */
+  printf("Physical memory:");
+  mem_init(mem_chunks, &free_clicks);
+  total_clicks = minix_clicks + free_clicks;
+  printf(" total %u KB,", click_to_round_k(total_clicks));
+  printf(" system %u KB,", click_to_round_k(minix_clicks));
+  printf(" free %u KB.\n", click_to_round_k(free_clicks));
+}
+
+/*===========================================================================*
+ *				get_nice_value				     *
+ *===========================================================================*/
+PRIVATE int get_nice_value(queue)
+int queue;				/* store mem chunks here */
+{
+/* Processes in the boot image have a priority assigned. The PM doesn't know
+ * about priorities, but uses 'nice' values instead. The priority is between 
+ * MIN_USER_Q and MAX_USER_Q. We have to scale between PRIO_MIN and PRIO_MAX.
+ */ 
+  int nice_val = (queue - USER_Q) * (PRIO_MAX-PRIO_MIN+1) / 
+      (MIN_USER_Q-MAX_USER_Q+1);
+  if (nice_val > PRIO_MAX) nice_val = PRIO_MAX;	/* shouldn't happen */
+  if (nice_val < PRIO_MIN) nice_val = PRIO_MIN;	/* shouldn't happen */
+  return nice_val;
+}
+
+#if _WORD_SIZE == 2
+/* In real mode only 1M can be addressed, and in 16-bit protected we can go
+ * no further than we can count in clicks.  (The 286 is further limited by
+ * its 24 bit address bus, but we can assume in that case that no more than
+ * 16M memory is reported by the BIOS.)
+ */
+#define MAX_REAL	0x00100000L
+#define MAX_16BIT	(0xFFF0L << CLICK_SHIFT)
+#endif
+
+/*===========================================================================*
+ *				get_mem_chunks				     *
+ *===========================================================================*/
+PRIVATE void get_mem_chunks(mem_chunks)
+struct memory *mem_chunks;			/* store mem chunks here */
+{
+/* Initialize the free memory list from the 'memory' boot variable.  Translate
+ * the byte offsets and sizes in this list to clicks, properly truncated. Also
+ * make sure that we don't exceed the maximum address space of the 286 or the
+ * 8086, i.e. when running in 16-bit protected mode or real mode.
+ */
+  long base, size, limit;
+  char *s, *end;			/* use to parse boot variable */ 
+  int i, done = 0;
+  struct memory *memp;
+#if _WORD_SIZE == 2
+  unsigned long max_address;
+  struct machine machine;
+  if (OK != (i=sys_getmachine(&machine)))
+	panic(__FILE__, "sys_getmachine failed", i);
+#endif
+
+  /* Initialize everything to zero. */
+  for (i = 0; i < NR_MEMS; i++) {
+	memp = &mem_chunks[i];		/* next mem chunk is stored here */
+	memp->base = memp->size = 0;
+  }
+  
+  /* The available memory is determined by MINIX' boot loader as a list of 
+   * (base:size)-pairs in boothead.s. The 'memory' boot variable is set in
+   * in boot.s.  The format is "b0:s0,b1:s1,b2:s2", where b0:s0 is low mem,
+   * b1:s1 is mem between 1M and 16M, b2:s2 is mem above 16M. Pairs b1:s1 
+   * and b2:s2 are combined if the memory is adjacent. 
+   */
+  s = find_param("memory");		/* get memory boot variable */
+  for (i = 0; i < NR_MEMS && !done; i++) {
+	memp = &mem_chunks[i];		/* next mem chunk is stored here */
+	base = size = 0;		/* initialize next base:size pair */
+	if (*s != 0) {			/* get fresh data, unless at end */	
+
+	    /* Read fresh base and expect colon as next char. */ 
+	    base = strtoul(s, &end, 0x10);		/* get number */
+	    if (end != s && *end == ':') s = ++end;	/* skip ':' */ 
+	    else *s=0;			/* terminate, should not happen */
+
+	    /* Read fresh size and expect comma or assume end. */ 
+	    size = strtoul(s, &end, 0x10);		/* get number */
+	    if (end != s && *end == ',') s = ++end;	/* skip ',' */
+	    else done = 1;
+	}
+	limit = base + size;	
+#if _WORD_SIZE == 2
+	max_address = machine.protected ? MAX_16BIT : MAX_REAL;
+	if (limit > max_address) limit = max_address;
+#endif
+	base = (base + CLICK_SIZE-1) & ~(long)(CLICK_SIZE-1);
+	limit &= ~(long)(CLICK_SIZE-1);
+	if (limit <= base) continue;
+	memp->base = base >> CLICK_SHIFT;
+	memp->size = (limit - base) >> CLICK_SHIFT;
+  }
+}
+
+/*===========================================================================*
+ *				patch_mem_chunks			     *
+ *===========================================================================*/
+PRIVATE void patch_mem_chunks(mem_chunks, map_ptr)
+struct memory *mem_chunks;			/* store mem chunks here */
+struct mem_map *map_ptr;			/* memory to remove */
+{
+/* Remove server memory from the free memory list. The boot monitor
+ * promises to put processes at the start of memory chunks. The 
+ * tasks all use same base address, so only the first task changes
+ * the memory lists. The servers and init have their own memory
+ * spaces and their memory will be removed from the list. 
+ */
+  struct memory *memp;
+  for (memp = mem_chunks; memp < &mem_chunks[NR_MEMS]; memp++) {
+	if (memp->base == map_ptr[T].mem_phys) {
+		memp->base += map_ptr[T].mem_len + map_ptr[D].mem_len;
+		memp->size -= map_ptr[T].mem_len + map_ptr[D].mem_len;
+	}
+  }
+}
+
+#define PAGE_SIZE	4096
+#define PAGE_TABLE_COVER (1024*PAGE_SIZE)
+/*=========================================================================*
+ *				do_x86_vm				   *
+ *=========================================================================*/
+PRIVATE void do_x86_vm(mem_chunks)
+struct memory mem_chunks[NR_MEMS];
+{
+	phys_bytes high, bytes;
+	phys_clicks clicks, base_click;
+	unsigned pages;
+	int i, r;
+
+	/* Compute the highest memory location */
+	high= 0;
+	for (i= 0; i<NR_MEMS; i++)
+	{
+		if (mem_chunks[i].size == 0)
+			continue;
+		if (mem_chunks[i].base + mem_chunks[i].size > high)
+			high= mem_chunks[i].base + mem_chunks[i].size;
+	}
+
+	high <<= CLICK_SHIFT;
+#if VERBOSE_VM
+	printf("do_x86_vm: found high 0x%x\n", high);
+#endif
+
+	/* The number of pages we need is one for the page directory, enough
+	 * page tables to cover the memory, and one page for alignement.
+	 */
+	pages= 1 + (high + PAGE_TABLE_COVER-1)/PAGE_TABLE_COVER + 1;
+	bytes= pages*PAGE_SIZE;
+	clicks= (bytes + CLICK_SIZE-1) >> CLICK_SHIFT;
+
+#if VERBOSE_VM
+	printf("do_x86_vm: need %d pages\n", pages);
+	printf("do_x86_vm: need %d bytes\n", bytes);
+	printf("do_x86_vm: need %d clicks\n", clicks);
+#endif
+
+	for (i= 0; i<NR_MEMS; i++)
+	{
+		if (mem_chunks[i].size <= clicks)
+			continue;
+		break;
+	}
+	if (i >= NR_MEMS)
+		panic("PM", "not enough memory for VM page tables?", NO_NUM);
+	base_click= mem_chunks[i].base;
+	mem_chunks[i].base += clicks;
+	mem_chunks[i].size -= clicks;
+
+#if VERBOSE_VM
+	printf("do_x86_vm: using 0x%x clicks @ 0x%x\n", clicks, base_click);
+#endif
+	r= sys_vm_setbuf(base_click << CLICK_SHIFT, clicks << CLICK_SHIFT,
+		high);
+	if (r != 0)
+		printf("do_x86_vm: sys_vm_setbuf failed: %d\n", r);
+}
Index: /trunk/minix/servers/pm/misc.c
===================================================================
--- /trunk/minix/servers/pm/misc.c	(revision 9)
+++ /trunk/minix/servers/pm/misc.c	(revision 9)
@@ -0,0 +1,429 @@
+/* Miscellaneous system calls.				Author: Kees J. Bot
+ *								31 Mar 2000
+ * The entry points into this file are:
+ *   do_reboot: kill all processes, then reboot system
+ *   do_procstat: request process status  (Jorrit N. Herder)
+ *   do_getsysinfo: request copy of PM data structure  (Jorrit N. Herder)
+ *   do_getprocnr: lookup process slot number  (Jorrit N. Herder)
+ *   do_allocmem: allocate a chunk of memory  (Jorrit N. Herder)
+ *   do_freemem: deallocate a chunk of memory  (Jorrit N. Herder)
+ *   do_getsetpriority: get/set process priority
+ *   do_svrctl: process manager control
+ */
+
+#include "pm.h"
+#include <minix/callnr.h>
+#include <signal.h>
+#include <sys/svrctl.h>
+#include <sys/resource.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/type.h>
+#include <string.h>
+#include <lib.h>
+#include "mproc.h"
+#include "param.h"
+#include "../../kernel/proc.h"
+
+/*===========================================================================*
+ *				do_allocmem				     *
+ *===========================================================================*/
+PUBLIC int do_allocmem()
+{
+  vir_clicks mem_clicks;
+  phys_clicks mem_base;
+
+  mem_clicks = (m_in.memsize + CLICK_SIZE -1 ) >> CLICK_SHIFT;
+  mem_base = alloc_mem(mem_clicks);
+  if (mem_base == NO_MEM) return(ENOMEM);
+  mp->mp_reply.membase =  (phys_bytes) (mem_base << CLICK_SHIFT);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_freemem				     *
+ *===========================================================================*/
+PUBLIC int do_freemem()
+{
+  vir_clicks mem_clicks;
+  phys_clicks mem_base;
+
+  mem_clicks = (m_in.memsize + CLICK_SIZE -1 ) >> CLICK_SHIFT;
+  mem_base = (m_in.membase + CLICK_SIZE -1 ) >> CLICK_SHIFT;
+  free_mem(mem_base, mem_clicks);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_procstat				     *
+ *===========================================================================*/
+PUBLIC int do_procstat()
+{ 
+  /* For the moment, this is only used to return pending signals to 
+   * system processes that request the PM for their own status. 
+   *
+   * Future use might include the FS requesting for process status of
+   * any user process. 
+   */
+  if (m_in.stat_nr == SELF) {
+      mp->mp_reply.sig_set = mp->mp_sigpending;
+      sigemptyset(&mp->mp_sigpending);
+  } 
+  else {
+      return(ENOSYS);
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_getsysinfo			       	     *
+ *===========================================================================*/
+PUBLIC int do_getsysinfo()
+{
+  struct mproc *proc_addr;
+  vir_bytes src_addr, dst_addr;
+  struct kinfo kinfo;
+  struct loadinfo loadinfo;
+  static struct proc proctab[NR_PROCS+NR_TASKS];
+  size_t len;
+  static struct pm_mem_info pmi;
+  int s, r;
+  size_t holesize;
+
+  switch(m_in.info_what) {
+  case SI_KINFO:			/* kernel info is obtained via PM */
+        sys_getkinfo(&kinfo);
+        src_addr = (vir_bytes) &kinfo;
+        len = sizeof(struct kinfo);
+        break;
+  case SI_PROC_ADDR:			/* get address of PM process table */
+  	proc_addr = &mproc[0];
+  	src_addr = (vir_bytes) &proc_addr;
+  	len = sizeof(struct mproc *);
+  	break; 
+  case SI_PROC_TAB:			/* copy entire process table */
+        src_addr = (vir_bytes) mproc;
+        len = sizeof(struct mproc) * NR_PROCS;
+        break;
+  case SI_KPROC_TAB:			/* copy entire process table */
+	if((r=sys_getproctab(proctab)) != OK)
+		return r;
+	src_addr = (vir_bytes) proctab;
+	len = sizeof(proctab);
+        break;
+  case SI_MEM_ALLOC:
+  	holesize = sizeof(pmi.pmi_holes);
+	if((r=mem_holes_copy(pmi.pmi_holes, &holesize,
+	   &pmi.pmi_hi_watermark)) != OK)
+		return r;
+	src_addr = (vir_bytes) &pmi;
+	len = sizeof(pmi);
+	break;
+  case SI_LOADINFO:			/* loadinfo is obtained via PM */
+        sys_getloadinfo(&loadinfo);
+        src_addr = (vir_bytes) &loadinfo;
+        len = sizeof(struct loadinfo);
+        break;
+  default:
+  	return(EINVAL);
+  }
+
+  dst_addr = (vir_bytes) m_in.info_where;
+  if (OK != (s=sys_datacopy(SELF, src_addr, who_e, dst_addr, len)))
+  	return(s);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_getprocnr			             *
+ *===========================================================================*/
+PUBLIC int do_getprocnr()
+{
+  register struct mproc *rmp;
+  static char search_key[PROC_NAME_LEN+1];
+  int key_len;
+  int s;
+
+  if (m_in.pid >= 0) {			/* lookup process by pid */
+  	for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
+		if ((rmp->mp_flags & IN_USE) && (rmp->mp_pid==m_in.pid)) {
+  			mp->mp_reply.endpt = rmp->mp_endpoint;
+  			return(OK);
+		} 
+	}
+  	return(ESRCH);			
+  } else if (m_in.namelen > 0) {	/* lookup process by name */
+  	key_len = MIN(m_in.namelen, PROC_NAME_LEN);
+ 	if (OK != (s=sys_datacopy(who_e, (vir_bytes) m_in.addr, 
+ 			SELF, (vir_bytes) search_key, key_len))) 
+ 		return(s);
+ 	search_key[key_len] = '\0';	/* terminate for safety */
+  	for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
+		if (((rmp->mp_flags & (IN_USE | ZOMBIE)) == IN_USE) && 
+			strncmp(rmp->mp_name, search_key, key_len)==0) {
+  			mp->mp_reply.endpt = rmp->mp_endpoint;
+  			return(OK);
+		} 
+	}
+  	return(ESRCH);			
+  } else {			/* return own/parent process number */
+  	mp->mp_reply.endpt = who_e;
+	mp->mp_reply.pendpt = mproc[mp->mp_parent].mp_endpoint;
+  }
+
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_reboot				     *
+ *===========================================================================*/
+PUBLIC int do_reboot()
+{
+  char monitor_code[256];		
+  vir_bytes code_addr;
+  int code_size;
+  int abort_flag;
+
+  /* Check permission to abort the system. */
+  if (mp->mp_effuid != SUPER_USER) return(EPERM);
+
+  /* See how the system should be aborted. */
+  abort_flag = (unsigned) m_in.reboot_flag;
+  if (abort_flag >= RBT_INVALID) return(EINVAL); 
+  if (RBT_MONITOR == abort_flag) {
+	int r;
+	if(m_in.reboot_strlen >= sizeof(monitor_code))
+		return EINVAL;
+	if((r = sys_datacopy(who_e, (vir_bytes) m_in.reboot_code,
+		SELF, (vir_bytes) monitor_code, m_in.reboot_strlen)) != OK)
+		return r;
+	code_addr = (vir_bytes) monitor_code;
+	monitor_code[m_in.reboot_strlen] = '\0';
+	code_size = m_in.reboot_strlen + 1;
+  }
+
+  /* Order matters here. When FS is told to reboot, it exits all its
+   * processes, and then would be confused if they're exited again by
+   * SIGKILL. So first kill, then reboot. 
+   */
+
+  check_sig(-1, SIGKILL); 		/* kill all users except init */
+  sys_nice(INIT_PROC_NR, PRIO_STOP);	/* stop init, but keep it around */
+  tell_fs(REBOOT, 0, 0, 0);		/* tell FS to synchronize */
+
+  /* Ask the kernel to abort. All system services, including the PM, will 
+   * get a HARD_STOP notification. Await the notification in the main loop.
+   */
+  sys_abort(abort_flag, PM_PROC_NR, code_addr, code_size);
+  return(SUSPEND);			/* don't reply to caller */
+}
+
+/*===========================================================================*
+ *				do_getsetpriority			     *
+ *===========================================================================*/
+PUBLIC int do_getsetpriority()
+{
+	int arg_which, arg_who, arg_pri;
+	int rmp_nr;
+	struct mproc *rmp;
+
+	arg_which = m_in.m1_i1;
+	arg_who = m_in.m1_i2;
+	arg_pri = m_in.m1_i3;	/* for SETPRIORITY */
+
+	/* Code common to GETPRIORITY and SETPRIORITY. */
+
+	/* Only support PRIO_PROCESS for now. */
+	if (arg_which != PRIO_PROCESS)
+		return(EINVAL);
+
+	if (arg_who == 0)
+		rmp_nr = who_p;
+	else
+		if ((rmp_nr = proc_from_pid(arg_who)) < 0)
+			return(ESRCH);
+
+	rmp = &mproc[rmp_nr];
+
+	if (mp->mp_effuid != SUPER_USER &&
+	   mp->mp_effuid != rmp->mp_effuid && mp->mp_effuid != rmp->mp_realuid)
+		return EPERM;
+
+	/* If GET, that's it. */
+	if (call_nr == GETPRIORITY) {
+		return(rmp->mp_nice - PRIO_MIN);
+	}
+
+	/* Only root is allowed to reduce the nice level. */
+	if (rmp->mp_nice > arg_pri && mp->mp_effuid != SUPER_USER)
+		return(EACCES);
+	
+	/* We're SET, and it's allowed. Do it and tell kernel. */
+	rmp->mp_nice = arg_pri;
+	return sys_nice(rmp->mp_endpoint, arg_pri);
+}
+
+/*===========================================================================*
+ *				do_svrctl				     *
+ *===========================================================================*/
+PUBLIC int do_svrctl()
+{
+  int s, req;
+  vir_bytes ptr;
+#define MAX_LOCAL_PARAMS 2
+  static struct {
+  	char name[30];
+  	char value[30];
+  } local_param_overrides[MAX_LOCAL_PARAMS];
+  static int local_params = 0;
+
+  req = m_in.svrctl_req;
+  ptr = (vir_bytes) m_in.svrctl_argp;
+
+  /* Is the request indeed for the MM? */
+  if (((req >> 8) & 0xFF) != 'M') return(EINVAL);
+
+  /* Control operations local to the PM. */
+  switch(req) {
+  case MMSETPARAM:
+  case MMGETPARAM: {
+      struct sysgetenv sysgetenv;
+      char search_key[64];
+      char *val_start;
+      size_t val_len;
+      size_t copy_len;
+
+      /* Copy sysgetenv structure to PM. */
+      if (sys_datacopy(who_e, ptr, SELF, (vir_bytes) &sysgetenv, 
+              sizeof(sysgetenv)) != OK) return(EFAULT);  
+
+      /* Set a param override? */
+      if (req == MMSETPARAM) {
+  	if (local_params >= MAX_LOCAL_PARAMS) return ENOSPC;
+  	if (sysgetenv.keylen <= 0
+  	 || sysgetenv.keylen >=
+  	 	 sizeof(local_param_overrides[local_params].name)
+  	 || sysgetenv.vallen <= 0
+  	 || sysgetenv.vallen >=
+  	 	 sizeof(local_param_overrides[local_params].value))
+  		return EINVAL;
+  		
+          if ((s = sys_datacopy(who_e, (vir_bytes) sysgetenv.key,
+            SELF, (vir_bytes) local_param_overrides[local_params].name,
+               sysgetenv.keylen)) != OK)
+               	return s;
+          if ((s = sys_datacopy(who_e, (vir_bytes) sysgetenv.val,
+            SELF, (vir_bytes) local_param_overrides[local_params].value,
+              sysgetenv.keylen)) != OK)
+               	return s;
+            local_param_overrides[local_params].name[sysgetenv.keylen] = '\0';
+            local_param_overrides[local_params].value[sysgetenv.vallen] = '\0';
+
+  	local_params++;
+
+  	return OK;
+      }
+
+      if (sysgetenv.keylen == 0) {	/* copy all parameters */
+          val_start = monitor_params;
+          val_len = sizeof(monitor_params);
+      } 
+      else {				/* lookup value for key */
+      	  int p;
+          /* Try to get a copy of the requested key. */
+          if (sysgetenv.keylen > sizeof(search_key)) return(EINVAL);
+          if ((s = sys_datacopy(who_e, (vir_bytes) sysgetenv.key,
+                  SELF, (vir_bytes) search_key, sysgetenv.keylen)) != OK)
+              return(s);
+
+          /* Make sure key is null-terminated and lookup value.
+           * First check local overrides.
+           */
+          search_key[sysgetenv.keylen-1]= '\0';
+          for(p = 0; p < local_params; p++) {
+          	if (!strcmp(search_key, local_param_overrides[p].name)) {
+          		val_start = local_param_overrides[p].value;
+          		break;
+          	}
+          }
+          if (p >= local_params && (val_start = find_param(search_key)) == NULL)
+               return(ESRCH);
+          val_len = strlen(val_start) + 1;
+      }
+
+      /* See if it fits in the client's buffer. */
+      if (val_len > sysgetenv.vallen)
+      	return E2BIG;
+
+      /* Value found, make the actual copy (as far as possible). */
+      copy_len = MIN(val_len, sysgetenv.vallen); 
+      if ((s=sys_datacopy(SELF, (vir_bytes) val_start, 
+              who_e, (vir_bytes) sysgetenv.val, copy_len)) != OK)
+          return(s);
+
+      return OK;
+  }
+
+#if ENABLE_SWAP
+  case MMSWAPON: {
+	struct mmswapon swapon;
+
+	if (mp->mp_effuid != SUPER_USER) return(EPERM);
+
+	if (sys_datacopy(who_e, (phys_bytes) ptr,
+		PM_PROC_NR, (phys_bytes) &swapon,
+		(phys_bytes) sizeof(swapon)) != OK) return(EFAULT);
+
+	return(swap_on(swapon.file, swapon.offset, swapon.size)); }
+
+  case MMSWAPOFF: {
+	if (mp->mp_effuid != SUPER_USER) return(EPERM);
+
+	return(swap_off()); }
+#endif /* SWAP */
+
+  default:
+	return(EINVAL);
+  }
+}
+
+/*===========================================================================*
+ *				_read_pm				     *
+ *===========================================================================*/
+PUBLIC ssize_t _read_pm(fd, buffer, nbytes, seg, ep)
+int fd;
+void *buffer;
+size_t nbytes;
+int seg;
+int ep;
+{
+  message m;
+
+  m.m1_i1 = _PM_SEG_FLAG | fd;
+  m.m1_i2 = nbytes;
+  m.m1_p1 = (char *) buffer;
+  m.m1_p2 = (char *) seg;
+  m.m1_p3 = (char *) ep;
+  return(_syscall(FS_PROC_NR, READ, &m));
+}
+
+/*===========================================================================*
+ *				_write_pm				     *
+ *===========================================================================*/
+PUBLIC ssize_t _write_pm(fd, buffer, nbytes, seg, ep)
+int fd;
+void *buffer;
+size_t nbytes;
+int seg;
+int ep;
+{
+  message m;
+
+  m.m1_i1 = _PM_SEG_FLAG | fd;
+  m.m1_i2 = nbytes;
+  m.m1_p1 = (char *) buffer;
+  m.m1_p2 = (char *) seg;
+  m.m1_p3 = (char *) ep;
+  return(_syscall(FS_PROC_NR, WRITE, &m));
+}
+
Index: /trunk/minix/servers/pm/mproc.h
===================================================================
--- /trunk/minix/servers/pm/mproc.h	(revision 9)
+++ /trunk/minix/servers/pm/mproc.h	(revision 9)
@@ -0,0 +1,76 @@
+/* This table has one slot per process.  It contains all the process management
+ * information for each process.  Among other things, it defines the text, data
+ * and stack segments, uids and gids, and various flags.  The kernel and file
+ * systems have tables that are also indexed by process, with the contents
+ * of corresponding slots referring to the same process in all three.
+ */
+#include <timers.h>
+
+EXTERN struct mproc {
+  struct mem_map mp_seg[NR_LOCAL_SEGS]; /* points to text, data, stack */
+  char mp_exitstatus;		/* storage for status when process exits */
+  char mp_sigstatus;		/* storage for signal # for killed procs */
+  pid_t mp_pid;			/* process id */
+  int mp_endpoint;		/* kernel endpoint id */
+  pid_t mp_procgrp;		/* pid of process group (used for signals) */
+  pid_t mp_wpid;		/* pid this process is waiting for */
+  int mp_parent;		/* index of parent process */
+
+  /* Child user and system times. Accounting done on child exit. */
+  clock_t mp_child_utime;	/* cumulative user time of children */
+  clock_t mp_child_stime;	/* cumulative sys time of children */
+
+  /* Real and effective uids and gids. */
+  uid_t mp_realuid;		/* process' real uid */
+  uid_t mp_effuid;		/* process' effective uid */
+  gid_t mp_realgid;		/* process' real gid */
+  gid_t mp_effgid;		/* process' effective gid */
+
+  /* File identification for sharing. */
+  ino_t mp_ino;			/* inode number of file */
+  dev_t mp_dev;			/* device number of file system */
+  time_t mp_ctime;		/* inode changed time */
+
+  /* Signal handling information. */
+  sigset_t mp_ignore;		/* 1 means ignore the signal, 0 means don't */
+  sigset_t mp_catch;		/* 1 means catch the signal, 0 means don't */
+  sigset_t mp_sig2mess;		/* 1 means transform into notify message */
+  sigset_t mp_sigmask;		/* signals to be blocked */
+  sigset_t mp_sigmask2;		/* saved copy of mp_sigmask */
+  sigset_t mp_sigpending;	/* pending signals to be handled */
+  struct sigaction mp_sigact[_NSIG + 1]; /* as in sigaction(2) */
+  vir_bytes mp_sigreturn; 	/* address of C library __sigreturn function */
+  struct timer mp_timer;	/* watchdog timer for alarm(2) */
+
+  /* Backwards compatibility for signals. */
+  sighandler_t mp_func;		/* all sigs vectored to a single user fcn */
+
+  unsigned mp_flags;		/* flag bits */
+  vir_bytes mp_procargs;        /* ptr to proc's initial stack arguments */
+  struct mproc *mp_swapq;	/* queue of procs waiting to be swapped in */
+  message mp_reply;		/* reply message to be sent to one */
+
+  /* Scheduling priority. */
+  signed int mp_nice;		/* nice is PRIO_MIN..PRIO_MAX, standard 0. */
+
+  char mp_name[PROC_NAME_LEN];	/* process name */
+} mproc[NR_PROCS];
+
+/* Flag values */
+#define IN_USE          0x001	/* set when 'mproc' slot in use */
+#define WAITING         0x002	/* set by WAIT system call */
+#define ZOMBIE          0x004	/* set by EXIT, cleared by WAIT */
+#define PAUSED          0x008	/* set by PAUSE system call */
+#define ALARM_ON        0x010	/* set when SIGALRM timer started */
+#define SEPARATE	0x020	/* set if file is separate I & D space */
+#define	TRACED		0x040	/* set if process is to be traced */
+#define STOPPED		0x080	/* set if process stopped for tracing */
+#define SIGSUSPENDED 	0x100	/* set by SIGSUSPEND system call */
+#define REPLY	 	0x200	/* set if a reply message is pending */
+#define ONSWAP	 	0x400	/* set if data segment is swapped out */
+#define SWAPIN	 	0x800	/* set if on the "swap this in" queue */
+#define DONT_SWAP      0x1000   /* never swap out this process */
+#define PRIV_PROC      0x2000   /* system process, special privileges */
+
+#define NIL_MPROC ((struct mproc *) 0)
+
Index: /trunk/minix/servers/pm/param.h
===================================================================
--- /trunk/minix/servers/pm/param.h	(revision 9)
+++ /trunk/minix/servers/pm/param.h	(revision 9)
@@ -0,0 +1,62 @@
+/* The following names are synonyms for the variables in the input message. */
+#define addr            m1_p1
+#define exec_name	m1_p1
+#define exec_len	m1_i1
+#define func		m6_f1
+#define grp_id		m1_i1
+#define namelen		m1_i2
+#define pid		m1_i1
+#define endpt		m1_i1
+#define pendpt		m1_i2
+#define seconds		m1_i1
+#define sig		m6_i1
+#define stack_bytes	m1_i2
+#define stack_ptr	m1_p2
+#define status		m1_i1
+#define usr_id		m1_i1
+#define request		m2_i2
+#define taddr		m2_l1
+#define data		m2_l2
+#define sig_nr		m1_i2
+#define sig_nsa		m1_p1
+#define sig_osa		m1_p2
+#define sig_ret		m1_p3
+#define stat_nr		m2_i1
+#define sig_set		m2_l1
+#define sig_how		m2_i1
+#define sig_flags	m2_i2
+#define sig_context	m2_p1
+#ifdef _SIGMESSAGE
+#define sig_msg		m1_i1
+#endif
+#define info_what	m1_i1
+#define info_where	m1_p1
+#define reboot_flag	m1_i1
+#define reboot_code	m1_p1
+#define reboot_strlen	m1_i2
+#define svrctl_req	m2_i1
+#define svrctl_argp	m2_p1
+#define stime      	m2_l1
+#define memsize      	m4_l1
+#define membase      	m4_l2
+
+/* The following names are synonyms for the variables in a reply message. */
+#define reply_res	m_type
+#define reply_res2	m2_i1
+#define reply_res3	m2_i2
+#define reply_ptr	m2_p1
+#define reply_mask	m2_l1 	
+#define reply_trace	m2_l2 	
+#define reply_time      m2_l1
+#define reply_utime     m2_l2
+#define reply_t1 	m4_l1
+#define reply_t2 	m4_l2
+#define reply_t3 	m4_l3
+#define reply_t4 	m4_l4
+#define reply_t5 	m4_l5
+
+/* The following names are used to inform the FS about certain events. */
+#define tell_fs_arg1    m1_i1
+#define tell_fs_arg2    m1_i2
+#define tell_fs_arg3    m1_i3
+
Index: /trunk/minix/servers/pm/pm.h
===================================================================
--- /trunk/minix/servers/pm/pm.h	(revision 9)
+++ /trunk/minix/servers/pm/pm.h	(revision 9)
@@ -0,0 +1,26 @@
+/* This is the master header for PM.  It includes some other files
+ * and defines the principal constants.
+ */
+#define _POSIX_SOURCE      1	/* tell headers to include POSIX stuff */
+#define _MINIX             1	/* tell headers to include MINIX stuff */
+#define _SYSTEM            1	/* tell headers that this is the kernel */
+
+/* The following are so basic, all the *.c files get them automatically. */
+#include <minix/config.h>	/* MUST be first */
+#include <ansi.h>		/* MUST be second */
+#include <sys/types.h>
+#include <minix/const.h>
+#include <minix/type.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <minix/syslib.h>
+#include <minix/sysutil.h>
+
+#include <limits.h>
+#include <errno.h>
+
+#include "const.h"
+#include "type.h"
+#include "proto.h"
+#include "glo.h"
Index: /trunk/minix/servers/pm/proto.h
===================================================================
--- /trunk/minix/servers/pm/proto.h	(revision 9)
+++ /trunk/minix/servers/pm/proto.h	(revision 9)
@@ -0,0 +1,119 @@
+/* Function prototypes. */
+
+struct mproc;
+struct stat;
+struct mem_map;
+struct memory;
+
+#include <timers.h>
+
+/* alloc.c */
+_PROTOTYPE( phys_clicks alloc_mem, (phys_clicks clicks)			);
+_PROTOTYPE( void free_mem, (phys_clicks base, phys_clicks clicks)	);
+_PROTOTYPE( void mem_init, (struct memory *chunks, phys_clicks *free)	);
+#if ENABLE_SWAP
+_PROTOTYPE( int swap_on, (char *file, u32_t offset, u32_t size)	);
+_PROTOTYPE( int swap_off, (void)					);
+_PROTOTYPE( void swap_in, (void)					);
+_PROTOTYPE( void swap_inqueue, (struct mproc *rmp)			);
+#else /* !SWAP */
+#define swap_in()			((void)0)
+#define swap_inqueue(rmp)		((void)0)
+#endif /* !SWAP */
+_PROTOTYPE(int mem_holes_copy, (struct hole *, size_t *, u32_t *)	);
+
+/* break.c */
+_PROTOTYPE( int adjust, (struct mproc *rmp,
+			vir_clicks data_clicks, vir_bytes sp)		);
+_PROTOTYPE( int do_brk, (void)						);
+_PROTOTYPE( int size_ok, (int file_type, vir_clicks tc, vir_clicks dc,
+			vir_clicks sc, vir_clicks dvir, vir_clicks s_vir) );
+
+/* devio.c */
+_PROTOTYPE( int do_dev_io, (void) );
+_PROTOTYPE( int do_dev_io, (void) );
+
+/* dmp.c */
+_PROTOTYPE( int do_fkey_pressed, (void)						);
+
+/* exec.c */
+_PROTOTYPE( int do_exec, (void)						);
+_PROTOTYPE( void rw_seg, (int rw, int fd, int proc, int seg,
+						phys_bytes seg_bytes)	);
+_PROTOTYPE( struct mproc *find_share, (struct mproc *mp_ign, Ino_t ino,
+			Dev_t dev, time_t ctime)			);
+
+/* forkexit.c */
+_PROTOTYPE( int do_fork, (void)						);
+_PROTOTYPE( int do_pm_exit, (void)					);
+_PROTOTYPE( int do_waitpid, (void)					);
+_PROTOTYPE( void pm_exit, (struct mproc *rmp, int exit_status)		);
+
+/* getset.c */
+_PROTOTYPE( int do_getset, (void)					);
+
+/* main.c */
+_PROTOTYPE( int main, (void)						);
+
+/* misc.c */
+_PROTOTYPE( int do_reboot, (void)					);
+_PROTOTYPE( int do_procstat, (void)					);
+_PROTOTYPE( int do_getsysinfo, (void)					);
+_PROTOTYPE( int do_getprocnr, (void)					);
+_PROTOTYPE( int do_svrctl, (void)					);
+_PROTOTYPE( int do_allocmem, (void)					);
+_PROTOTYPE( int do_freemem, (void)					);
+_PROTOTYPE( int do_getsetpriority, (void)					);
+_PROTOTYPE( ssize_t _read_pm, (int _fd, void *_buf, size_t _n, int s, int e));
+_PROTOTYPE( ssize_t _write_pm, (int _fd, void *_buf, size_t _n, int s, int e));
+
+
+#if (MACHINE == MACINTOSH)
+_PROTOTYPE( phys_clicks start_click, (void)				);
+#endif
+
+_PROTOTYPE( void setreply, (int proc_nr, int result)			);
+
+/* signal.c */
+_PROTOTYPE( int do_alarm, (void)					);
+_PROTOTYPE( int do_kill, (void)						);
+_PROTOTYPE( int ksig_pending, (void)					);
+_PROTOTYPE( int do_pause, (void)					);
+_PROTOTYPE( int set_alarm, (int proc_nr, int sec)			);
+_PROTOTYPE( int check_sig, (pid_t proc_id, int signo)			);
+_PROTOTYPE( void sig_proc, (struct mproc *rmp, int sig_nr)		);
+_PROTOTYPE( int do_sigaction, (void)					);
+_PROTOTYPE( int do_sigpending, (void)					);
+_PROTOTYPE( int do_sigprocmask, (void)					);
+_PROTOTYPE( int do_sigreturn, (void)					);
+_PROTOTYPE( int do_sigsuspend, (void)					);
+_PROTOTYPE( void check_pending, (struct mproc *rmp)			);
+
+/* time.c */
+_PROTOTYPE( int do_stime, (void)					);
+_PROTOTYPE( int do_time, (void)						);
+_PROTOTYPE( int do_times, (void)					);
+_PROTOTYPE( int do_gettimeofday, (void)					);
+
+/* timers.c */
+_PROTOTYPE( void pm_set_timer, (timer_t *tp, int delta, 
+	tmr_func_t watchdog, int arg));
+_PROTOTYPE( void pm_expire_timers, (clock_t now));
+_PROTOTYPE( void pm_cancel_timer, (timer_t *tp));
+
+/* trace.c */
+_PROTOTYPE( int do_trace, (void)					);
+_PROTOTYPE( void stop_proc, (struct mproc *rmp, int sig_nr)		);
+
+/* utility.c */
+_PROTOTYPE( pid_t get_free_pid, (void)					);
+_PROTOTYPE( int allowed, (char *name_buf, struct stat *s_buf, int mask)	);
+_PROTOTYPE( int no_sys, (void)						);
+_PROTOTYPE( void panic, (char *who, char *mess, int num)		);
+_PROTOTYPE( void tell_fs, (int what, int p1, int p2, int p3)		);
+_PROTOTYPE( int get_stack_ptr, (int proc_nr, vir_bytes *sp)		);
+_PROTOTYPE( int get_mem_map, (int proc_nr, struct mem_map *mem_map)	);
+_PROTOTYPE( char *find_param, (const char *key));
+_PROTOTYPE( int proc_from_pid, (pid_t p));
+_PROTOTYPE( int pm_isokendpt, (int ep, int *proc));
+
Index: /trunk/minix/servers/pm/signal.c
===================================================================
--- /trunk/minix/servers/pm/signal.c	(revision 9)
+++ /trunk/minix/servers/pm/signal.c	(revision 9)
@@ -0,0 +1,703 @@
+/* This file handles signals, which are asynchronous events and are generally
+ * a messy and unpleasant business.  Signals can be generated by the KILL
+ * system call, or from the keyboard (SIGINT) or from the clock (SIGALRM).
+ * In all cases control eventually passes to check_sig() to see which processes
+ * can be signaled.  The actual signaling is done by sig_proc().
+ *
+ * The entry points into this file are:
+ *   do_sigaction:   perform the SIGACTION system call
+ *   do_sigpending:  perform the SIGPENDING system call
+ *   do_sigprocmask: perform the SIGPROCMASK system call
+ *   do_sigreturn:   perform the SIGRETURN system call
+ *   do_sigsuspend:  perform the SIGSUSPEND system call
+ *   do_kill:	perform the KILL system call
+ *   do_alarm:	perform the ALARM system call by calling set_alarm()
+ *   set_alarm:	tell the clock task to start or stop a timer
+ *   do_pause:	perform the PAUSE system call
+ *   ksig_pending: the kernel notified about pending signals
+ *   sig_proc:	interrupt or terminate a signaled process
+ *   check_sig: check which processes to signal with sig_proc()
+ *   check_pending:  check if a pending signal can now be delivered
+ */
+
+#include "pm.h"
+#include <sys/stat.h>
+#include <sys/ptrace.h>
+#include <minix/callnr.h>
+#include <minix/endpoint.h>
+#include <minix/com.h>
+#include <signal.h>
+#include <sys/sigcontext.h>
+#include <string.h>
+#include "mproc.h"
+#include "param.h"
+
+#define CORE_MODE	0777	/* mode to use on core image files */
+#define DUMPED          0200	/* bit set in status when core dumped */
+
+FORWARD _PROTOTYPE( void dump_core, (struct mproc *rmp)			);
+FORWARD _PROTOTYPE( void unpause, (int pro)				);
+FORWARD _PROTOTYPE( void handle_ksig, (int proc_nr, sigset_t sig_map)	);
+FORWARD _PROTOTYPE( void cause_sigalrm, (struct timer *tp)		);
+
+/*===========================================================================*
+ *				do_sigaction				     *
+ *===========================================================================*/
+PUBLIC int do_sigaction()
+{
+  int r;
+  struct sigaction svec;
+  struct sigaction *svp;
+
+  if (m_in.sig_nr == SIGKILL) return(OK);
+  if (m_in.sig_nr < 1 || m_in.sig_nr > _NSIG) return (EINVAL);
+  svp = &mp->mp_sigact[m_in.sig_nr];
+  if ((struct sigaction *) m_in.sig_osa != (struct sigaction *) NULL) {
+	r = sys_datacopy(PM_PROC_NR,(vir_bytes) svp,
+		who_e, (vir_bytes) m_in.sig_osa, (phys_bytes) sizeof(svec));
+	if (r != OK) return(r);
+  }
+
+  if ((struct sigaction *) m_in.sig_nsa == (struct sigaction *) NULL) 
+  	return(OK);
+
+  /* Read in the sigaction structure. */
+  r = sys_datacopy(who_e, (vir_bytes) m_in.sig_nsa,
+		PM_PROC_NR, (vir_bytes) &svec, (phys_bytes) sizeof(svec));
+  if (r != OK) return(r);
+
+  if (svec.sa_handler == SIG_IGN) {
+	sigaddset(&mp->mp_ignore, m_in.sig_nr);
+	sigdelset(&mp->mp_sigpending, m_in.sig_nr);
+	sigdelset(&mp->mp_catch, m_in.sig_nr);
+	sigdelset(&mp->mp_sig2mess, m_in.sig_nr);
+  } else if (svec.sa_handler == SIG_DFL) {
+	sigdelset(&mp->mp_ignore, m_in.sig_nr);
+	sigdelset(&mp->mp_catch, m_in.sig_nr);
+	sigdelset(&mp->mp_sig2mess, m_in.sig_nr);
+  } else if (svec.sa_handler == SIG_MESS) {
+	if (! (mp->mp_flags & PRIV_PROC)) return(EPERM);
+	sigdelset(&mp->mp_ignore, m_in.sig_nr);
+	sigaddset(&mp->mp_sig2mess, m_in.sig_nr);
+	sigdelset(&mp->mp_catch, m_in.sig_nr);
+  } else {
+	sigdelset(&mp->mp_ignore, m_in.sig_nr);
+	sigaddset(&mp->mp_catch, m_in.sig_nr);
+	sigdelset(&mp->mp_sig2mess, m_in.sig_nr);
+  }
+  mp->mp_sigact[m_in.sig_nr].sa_handler = svec.sa_handler;
+  sigdelset(&svec.sa_mask, SIGKILL);
+  mp->mp_sigact[m_in.sig_nr].sa_mask = svec.sa_mask;
+  mp->mp_sigact[m_in.sig_nr].sa_flags = svec.sa_flags;
+  mp->mp_sigreturn = (vir_bytes) m_in.sig_ret;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_sigpending                                *
+ *===========================================================================*/
+PUBLIC int do_sigpending()
+{
+  mp->mp_reply.reply_mask = (long) mp->mp_sigpending;
+  return OK;
+}
+
+/*===========================================================================*
+ *				do_sigprocmask                               *
+ *===========================================================================*/
+PUBLIC int do_sigprocmask()
+{
+/* Note that the library interface passes the actual mask in sigmask_set,
+ * not a pointer to the mask, in order to save a copy.  Similarly,
+ * the old mask is placed in the return message which the library
+ * interface copies (if requested) to the user specified address.
+ *
+ * The library interface must set SIG_INQUIRE if the 'act' argument
+ * is NULL.
+ *
+ * KILL and STOP can't be masked.
+ */
+
+  int i;
+
+  mp->mp_reply.reply_mask = (long) mp->mp_sigmask;
+
+  switch (m_in.sig_how) {
+      case SIG_BLOCK:
+	sigdelset((sigset_t *)&m_in.sig_set, SIGKILL);
+	sigdelset((sigset_t *)&m_in.sig_set, SIGSTOP);
+	for (i = 1; i <= _NSIG; i++) {
+		if (sigismember((sigset_t *)&m_in.sig_set, i))
+			sigaddset(&mp->mp_sigmask, i);
+	}
+	break;
+
+      case SIG_UNBLOCK:
+	for (i = 1; i <= _NSIG; i++) {
+		if (sigismember((sigset_t *)&m_in.sig_set, i))
+			sigdelset(&mp->mp_sigmask, i);
+	}
+	check_pending(mp);
+	break;
+
+      case SIG_SETMASK:
+	sigdelset((sigset_t *) &m_in.sig_set, SIGKILL);
+	sigdelset((sigset_t *) &m_in.sig_set, SIGSTOP);
+	mp->mp_sigmask = (sigset_t) m_in.sig_set;
+	check_pending(mp);
+	break;
+
+      case SIG_INQUIRE:
+	break;
+
+      default:
+	return(EINVAL);
+	break;
+  }
+  return OK;
+}
+
+/*===========================================================================*
+ *				do_sigsuspend                                *
+ *===========================================================================*/
+PUBLIC int do_sigsuspend()
+{
+  mp->mp_sigmask2 = mp->mp_sigmask;	/* save the old mask */
+  mp->mp_sigmask = (sigset_t) m_in.sig_set;
+  sigdelset(&mp->mp_sigmask, SIGKILL);
+  mp->mp_flags |= SIGSUSPENDED;
+  check_pending(mp);
+  return(SUSPEND);
+}
+
+/*===========================================================================*
+ *				do_sigreturn				     *
+ *===========================================================================*/
+PUBLIC int do_sigreturn()
+{
+/* A user signal handler is done.  Restore context and check for
+ * pending unblocked signals.
+ */
+
+  int r;
+
+  mp->mp_sigmask = (sigset_t) m_in.sig_set;
+  sigdelset(&mp->mp_sigmask, SIGKILL);
+
+  r = sys_sigreturn(who_e, (struct sigmsg *) m_in.sig_context);
+  check_pending(mp);
+  return(r);
+}
+
+/*===========================================================================*
+ *				do_kill					     *
+ *===========================================================================*/
+PUBLIC int do_kill()
+{
+/* Perform the kill(pid, signo) system call. */
+
+  return check_sig(m_in.pid, m_in.sig_nr);
+}
+
+/*===========================================================================*
+ *				ksig_pending				     *
+ *===========================================================================*/
+PUBLIC int ksig_pending()
+{
+/* Certain signals, such as segmentation violations originate in the kernel.
+ * When the kernel detects such signals, it notifies the PM to take further 
+ * action. The PM requests the kernel to send messages with the process
+ * slot and bit map for all signaled processes. The File System, for example,
+ * uses this mechanism to signal writing on broken pipes (SIGPIPE). 
+ *
+ * The kernel has notified the PM about pending signals. Request pending
+ * signals until all signals are handled. If there are no more signals,
+ * NONE is returned in the process number field.
+ */ 
+ int proc_nr_e;
+ sigset_t sig_map;
+
+ while (TRUE) {
+   int r;
+   /* get an arbitrary pending signal */
+   if((r=sys_getksig(&proc_nr_e, &sig_map)) != OK)
+  	panic(__FILE__,"sys_getksig failed", r);
+   if (NONE == proc_nr_e) {		/* stop if no more pending signals */
+ 	break;
+   } else {
+ 	int proc_nr_p;
+ 	if(pm_isokendpt(proc_nr_e, &proc_nr_p) != OK)
+  		panic(__FILE__,"sys_getksig strange process", proc_nr_e);
+   	handle_ksig(proc_nr_e, sig_map);	/* handle the received signal */
+	/* If the process still exists to the kernel after the signal
+	 * has been handled ...
+	 */
+        if ((mproc[proc_nr_p].mp_flags & (IN_USE | ZOMBIE)) == IN_USE)
+	   if((r=sys_endksig(proc_nr_e)) != OK)	/* ... tell kernel it's done */
+  		panic(__FILE__,"sys_endksig failed", r);
+   }
+ } 
+ return(SUSPEND);			/* prevents sending reply */
+}
+
+/*===========================================================================*
+ *				handle_ksig				     *
+ *===========================================================================*/
+PRIVATE void handle_ksig(proc_nr_e, sig_map)
+int proc_nr_e;
+sigset_t sig_map;
+{
+  register struct mproc *rmp;
+  int i, proc_nr;
+  pid_t proc_id, id;
+
+  if(pm_isokendpt(proc_nr_e, &proc_nr) != OK || proc_nr < 0)
+	return;
+  rmp = &mproc[proc_nr];
+  if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE)
+	return;
+  proc_id = rmp->mp_pid;
+  mp = &mproc[0];			/* pretend signals are from PM */
+  mp->mp_procgrp = rmp->mp_procgrp;	/* get process group right */
+
+  /* Check each bit in turn to see if a signal is to be sent.  Unlike
+   * kill(), the kernel may collect several unrelated signals for a
+   * process and pass them to PM in one blow.  Thus loop on the bit
+   * map. For SIGINT, SIGWINCH and SIGQUIT, use proc_id 0 to indicate
+   * a broadcast to the recipient's process group.  For SIGKILL, use
+   * proc_id -1 to indicate a systemwide broadcast.
+   */
+  for (i = 1; i <= _NSIG; i++) {
+	if (!sigismember(&sig_map, i)) continue;
+	switch (i) {
+	    case SIGINT:
+	    case SIGQUIT:
+	    case SIGWINCH:
+		id = 0; break;	/* broadcast to process group */
+#if 0
+	    case SIGKILL:
+		id = -1; break;	/* broadcast to all except INIT */
+#endif
+	    default:
+		id = proc_id;
+		break;
+	}
+	check_sig(id, i);
+  }
+}
+
+/*===========================================================================*
+ *				do_alarm				     *
+ *===========================================================================*/
+PUBLIC int do_alarm()
+{
+/* Perform the alarm(seconds) system call. */
+  return(set_alarm(who_e, m_in.seconds));
+}
+
+/*===========================================================================*
+ *				set_alarm				     *
+ *===========================================================================*/
+PUBLIC int set_alarm(proc_nr_e, sec)
+int proc_nr_e;			/* process that wants the alarm */
+int sec;			/* how many seconds delay before the signal */
+{
+/* This routine is used by do_alarm() to set the alarm timer.  It is also used
+ * to turn the timer off when a process exits with the timer still on.
+ */
+  clock_t ticks;	/* number of ticks for alarm */
+  clock_t exptime;	/* needed for remaining time on previous alarm */
+  clock_t uptime;	/* current system time */
+  int remaining;	/* previous time left in seconds */
+  int s;
+  int proc_nr_n;
+
+  if(pm_isokendpt(proc_nr_e, &proc_nr_n) != OK)
+	return EINVAL;
+
+  /* First determine remaining time of previous alarm, if set. */
+  if (mproc[proc_nr_n].mp_flags & ALARM_ON) {
+  	if ( (s=getuptime(&uptime)) != OK) 
+  		panic(__FILE__,"set_alarm couldn't get uptime", s);
+  	exptime = *tmr_exp_time(&mproc[proc_nr_n].mp_timer);
+  	remaining = (int) ((exptime - uptime + (HZ-1))/HZ);
+  	if (remaining < 0) remaining = 0;	
+  } else {
+  	remaining = 0; 
+  }
+
+  /* Tell the clock task to provide a signal message when the time comes.
+   *
+   * Large delays cause a lot of problems.  First, the alarm system call
+   * takes an unsigned seconds count and the library has cast it to an int.
+   * That probably works, but on return the library will convert "negative"
+   * unsigneds to errors.  Presumably no one checks for these errors, so
+   * force this call through.  Second, If unsigned and long have the same
+   * size, converting from seconds to ticks can easily overflow.  Finally,
+   * the kernel has similar overflow bugs adding ticks.
+   *
+   * Fixing this requires a lot of ugly casts to fit the wrong interface
+   * types and to avoid overflow traps.  ALRM_EXP_TIME has the right type
+   * (clock_t) although it is declared as long.  How can variables like
+   * this be declared properly without combinatorial explosion of message
+   * types?
+   */
+  ticks = (clock_t) (HZ * (unsigned long) (unsigned) sec);
+  if ( (unsigned long) ticks / HZ != (unsigned) sec)
+	ticks = LONG_MAX;	/* eternity (really TMR_NEVER) */
+
+  if (ticks != 0) {
+  	pm_set_timer(&mproc[proc_nr_n].mp_timer, ticks,
+		cause_sigalrm, proc_nr_e);
+  	mproc[proc_nr_n].mp_flags |=  ALARM_ON;
+  } else if (mproc[proc_nr_n].mp_flags & ALARM_ON) {
+  	pm_cancel_timer(&mproc[proc_nr_n].mp_timer);
+  	mproc[proc_nr_n].mp_flags &= ~ALARM_ON;
+  }
+  return(remaining);
+}
+
+/*===========================================================================*
+ *				cause_sigalrm				     *
+ *===========================================================================*/
+PRIVATE void cause_sigalrm(tp)
+struct timer *tp;
+{
+  int proc_nr_e, proc_nr_n;
+  register struct mproc *rmp;
+
+  /* get process from timer */
+  if(pm_isokendpt(tmr_arg(tp)->ta_int, &proc_nr_n) != OK) {
+	printf("PM: ignoring timer for invalid endpoint %d\n",
+		tmr_arg(tp)->ta_int);
+	return;
+  }
+
+  rmp = &mproc[proc_nr_n];
+
+  if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) return;
+  if ((rmp->mp_flags & ALARM_ON) == 0) return;
+  rmp->mp_flags &= ~ALARM_ON;
+  check_sig(rmp->mp_pid, SIGALRM);
+}
+
+/*===========================================================================*
+ *				do_pause				     *
+ *===========================================================================*/
+PUBLIC int do_pause()
+{
+/* Perform the pause() system call. */
+
+  mp->mp_flags |= PAUSED;
+  return(SUSPEND);
+}
+
+/*===========================================================================*
+ *				sig_proc				     *
+ *===========================================================================*/
+PUBLIC void sig_proc(rmp, signo)
+register struct mproc *rmp;	/* pointer to the process to be signaled */
+int signo;			/* signal to send to process (1 to _NSIG) */
+{
+/* Send a signal to a process.  Check to see if the signal is to be caught,
+ * ignored, tranformed into a message (for system processes) or blocked.  
+ *  - If the signal is to be transformed into a message, request the KERNEL to
+ * send the target process a system notification with the pending signal as an 
+ * argument. 
+ *  - If the signal is to be caught, request the KERNEL to push a sigcontext 
+ * structure and a sigframe structure onto the catcher's stack.  Also, KERNEL 
+ * will reset the program counter and stack pointer, so that when the process 
+ * next runs, it will be executing the signal handler. When the signal handler 
+ * returns,  sigreturn(2) will be called.  Then KERNEL will restore the signal 
+ * context from the sigcontext structure.
+ * If there is insufficient stack space, kill the process.
+ */
+
+  vir_bytes new_sp;
+  int s;
+  int slot;
+  int sigflags;
+  struct sigmsg sm;
+
+  slot = (int) (rmp - mproc);
+  if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) {
+	printf("PM: signal %d sent to %s process %d\n",
+		signo, (rmp->mp_flags & ZOMBIE) ? "zombie" : "dead", slot);
+	panic(__FILE__,"", NO_NUM);
+  }
+  if ((rmp->mp_flags & TRACED) && signo != SIGKILL) {
+	/* A traced process has special handling. */
+	unpause(slot);
+	stop_proc(rmp, signo);	/* a signal causes it to stop */
+	return;
+  }
+  /* Some signals are ignored by default. */
+  if (sigismember(&rmp->mp_ignore, signo)) { 
+  	return;
+  }
+  if (sigismember(&rmp->mp_sigmask, signo)) {
+	/* Signal should be blocked. */
+	sigaddset(&rmp->mp_sigpending, signo);
+	return;
+  }
+#if ENABLE_SWAP
+  if (rmp->mp_flags & ONSWAP) {
+	/* Process is swapped out, leave signal pending. */
+	sigaddset(&rmp->mp_sigpending, signo);
+	swap_inqueue(rmp);
+	return;
+  }
+#endif
+  sigflags = rmp->mp_sigact[signo].sa_flags;
+  if (sigismember(&rmp->mp_catch, signo)) {
+	if (rmp->mp_flags & SIGSUSPENDED)
+		sm.sm_mask = rmp->mp_sigmask2;
+	else
+		sm.sm_mask = rmp->mp_sigmask;
+	sm.sm_signo = signo;
+	sm.sm_sighandler = (vir_bytes) rmp->mp_sigact[signo].sa_handler;
+	sm.sm_sigreturn = rmp->mp_sigreturn;
+	if ((s=get_stack_ptr(rmp->mp_endpoint, &new_sp)) != OK)
+		panic(__FILE__,"couldn't get new stack pointer (for sig)",s);
+	sm.sm_stkptr = new_sp;
+
+	/* Make room for the sigcontext and sigframe struct. */
+	new_sp -= sizeof(struct sigcontext)
+				 + 3 * sizeof(char *) + 2 * sizeof(int);
+
+	if (adjust(rmp, rmp->mp_seg[D].mem_len, new_sp) != OK)
+		goto doterminate;
+
+	rmp->mp_sigmask |= rmp->mp_sigact[signo].sa_mask;
+	if (sigflags & SA_NODEFER)
+		sigdelset(&rmp->mp_sigmask, signo);
+	else
+		sigaddset(&rmp->mp_sigmask, signo);
+
+	if (sigflags & SA_RESETHAND) {
+		sigdelset(&rmp->mp_catch, signo);
+		rmp->mp_sigact[signo].sa_handler = SIG_DFL;
+	}
+
+	if (OK == (s=sys_sigsend(rmp->mp_endpoint, &sm))) {
+
+		sigdelset(&rmp->mp_sigpending, signo);
+		/* If process is hanging on PAUSE, WAIT, SIGSUSPEND, tty, 
+		 * pipe, etc., release it.
+		 */
+		unpause(slot);
+		return;
+	}
+  	panic(__FILE__, "sys_sigsend failed", s);
+  }
+  else if (sigismember(&rmp->mp_sig2mess, signo)) {
+
+	/* Mark event pending in process slot and send notification. */
+	sigaddset(&rmp->mp_sigpending, signo);
+	notify(rmp->mp_endpoint);
+  	return;
+  }
+
+doterminate:
+  /* Signal should not or cannot be caught.  Take default action. */
+  if (sigismember(&ign_sset, signo)) return;
+
+  rmp->mp_sigstatus = (char) signo;
+  if (sigismember(&core_sset, signo) && slot != FS_PROC_NR) {
+#if ENABLE_SWAP
+	if (rmp->mp_flags & ONSWAP) {
+		/* Process is swapped out, leave signal pending. */
+		sigaddset(&rmp->mp_sigpending, signo);
+		swap_inqueue(rmp);
+		return;
+	}
+#endif
+	/* Switch to the user's FS environment and dump core. */
+	tell_fs(CHDIR, rmp->mp_endpoint, FALSE, 0);
+	dump_core(rmp);
+  }
+  pm_exit(rmp, 0);		/* terminate process */
+}
+
+/*===========================================================================*
+ *				check_sig				     *
+ *===========================================================================*/
+PUBLIC int check_sig(proc_id, signo)
+pid_t proc_id;			/* pid of proc to sig, or 0 or -1, or -pgrp */
+int signo;			/* signal to send to process (0 to _NSIG) */
+{
+/* Check to see if it is possible to send a signal.  The signal may have to be
+ * sent to a group of processes.  This routine is invoked by the KILL system
+ * call, and also when the kernel catches a DEL or other signal.
+ */
+
+  register struct mproc *rmp;
+  int count;			/* count # of signals sent */
+  int error_code;
+
+  if (signo < 0 || signo > _NSIG) return(EINVAL);
+
+  /* Return EINVAL for attempts to send SIGKILL to INIT alone. */
+  if (proc_id == INIT_PID && signo == SIGKILL) return(EINVAL);
+
+  /* Search the proc table for processes to signal.  
+   * (See forkexit.c aboutpid magic.)
+   */
+  count = 0;
+  error_code = ESRCH;
+  for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
+	if (!(rmp->mp_flags & IN_USE)) continue;
+	if ((rmp->mp_flags & ZOMBIE) && signo != 0) continue;
+
+	/* Check for selection. */
+	if (proc_id > 0 && proc_id != rmp->mp_pid) continue;
+	if (proc_id == 0 && mp->mp_procgrp != rmp->mp_procgrp) continue;
+	if (proc_id == -1 && rmp->mp_pid <= INIT_PID) continue;
+	if (proc_id < -1 && rmp->mp_procgrp != -proc_id) continue;
+
+	/* Do not kill servers and drivers when broadcasting SIGKILL. */
+	if (proc_id == -1 && signo == SIGKILL &&
+		(rmp->mp_flags & PRIV_PROC)) continue;
+
+	/* Check for permission. */
+	if (mp->mp_effuid != SUPER_USER
+	    && mp->mp_realuid != rmp->mp_realuid
+	    && mp->mp_effuid != rmp->mp_realuid
+	    && mp->mp_realuid != rmp->mp_effuid
+	    && mp->mp_effuid != rmp->mp_effuid) {
+		error_code = EPERM;
+		continue;
+	}
+
+	count++;
+	if (signo == 0) continue;
+
+	/* 'sig_proc' will handle the disposition of the signal.  The
+	 * signal may be caught, blocked, ignored, or cause process
+	 * termination, possibly with core dump.
+	 */
+	sig_proc(rmp, signo);
+
+	if (proc_id > 0) break;	/* only one process being signaled */
+  }
+
+  /* If the calling process has killed itself, don't reply. */
+  if ((mp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) return(SUSPEND);
+  return(count > 0 ? OK : error_code);
+}
+
+/*===========================================================================*
+ *				check_pending				     *
+ *===========================================================================*/
+PUBLIC void check_pending(rmp)
+register struct mproc *rmp;
+{
+  /* Check to see if any pending signals have been unblocked.  The
+   * first such signal found is delivered.
+   *
+   * If multiple pending unmasked signals are found, they will be
+   * delivered sequentially.
+   *
+   * There are several places in this file where the signal mask is
+   * changed.  At each such place, check_pending() should be called to
+   * check for newly unblocked signals.
+   */
+
+  int i;
+
+  for (i = 1; i <= _NSIG; i++) {
+	if (sigismember(&rmp->mp_sigpending, i) &&
+		!sigismember(&rmp->mp_sigmask, i)) {
+		sigdelset(&rmp->mp_sigpending, i);
+		sig_proc(rmp, i);
+		break;
+	}
+  }
+}
+
+/*===========================================================================*
+ *				unpause					     *
+ *===========================================================================*/
+PRIVATE void unpause(pro)
+int pro;			/* which process number */
+{
+/* A signal is to be sent to a process.  If that process is hanging on a
+ * system call, the system call must be terminated with EINTR.  Possible
+ * calls are PAUSE, WAIT, READ and WRITE, the latter two for pipes and ttys.
+ * First check if the process is hanging on an PM call.  If not, tell FS,
+ * so it can check for READs and WRITEs from pipes, ttys and the like.
+ */
+
+  register struct mproc *rmp;
+
+  rmp = &mproc[pro];
+
+  /* Check to see if process is hanging on a PAUSE, WAIT or SIGSUSPEND call. */
+  if (rmp->mp_flags & (PAUSED | WAITING | SIGSUSPENDED)) {
+	rmp->mp_flags &= ~(PAUSED | WAITING | SIGSUSPENDED);
+	setreply(pro, EINTR);
+	return;
+  }
+
+  /* Process is not hanging on an PM call.  Ask FS to take a look. */
+  tell_fs(UNPAUSE, rmp->mp_endpoint, 0, 0);
+}
+
+/*===========================================================================*
+ *				dump_core				     *
+ *===========================================================================*/
+PRIVATE void dump_core(rmp)
+register struct mproc *rmp;	/* whose core is to be dumped */
+{
+/* Make a core dump on the file "core", if possible. */
+
+  int s, fd, seg, slot;
+  vir_bytes current_sp;
+  long trace_data, trace_off;
+
+  slot = (int) (rmp - mproc);
+
+  /* Can core file be written?  We are operating in the user's FS environment,
+   * so no special permission checks are needed.
+   */
+  if (rmp->mp_realuid != rmp->mp_effuid) return;
+  if ( (fd = open(core_name, O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK,
+						CORE_MODE)) < 0) return;
+  rmp->mp_sigstatus |= DUMPED;
+
+  /* Make sure the stack segment is up to date.
+   * We don't want adjust() to fail unless current_sp is preposterous,
+   * but it might fail due to safety checking.  Also, we don't really want 
+   * the adjust() for sending a signal to fail due to safety checking.  
+   * Maybe make SAFETY_BYTES a parameter.
+   */
+  if ((s=get_stack_ptr(rmp->mp_endpoint, &current_sp)) != OK)
+	panic(__FILE__,"couldn't get new stack pointer (for core)",s);
+  adjust(rmp, rmp->mp_seg[D].mem_len, current_sp);
+
+  /* Write the memory map of all segments to begin the core file. */
+  if (write(fd, (char *) rmp->mp_seg, (unsigned) sizeof rmp->mp_seg)
+      != (unsigned) sizeof rmp->mp_seg) {
+	close(fd);
+	return;
+  }
+
+  /* Write out the whole kernel process table entry to get the regs. */
+  trace_off = 0;
+  while (sys_trace(T_GETUSER, rmp->mp_endpoint, trace_off, &trace_data) == OK) {
+	if (write(fd, (char *) &trace_data, (unsigned) sizeof (long))
+	    != (unsigned) sizeof (long)) {
+		close(fd);
+		return;
+	}
+	trace_off += sizeof (long);
+  }
+
+  /* Loop through segments and write the segments themselves out. */
+  for (seg = 0; seg < NR_LOCAL_SEGS; seg++) {
+	rw_seg(1, fd, rmp->mp_endpoint, seg,
+		(phys_bytes) rmp->mp_seg[seg].mem_len << CLICK_SHIFT);
+  }
+  close(fd);
+}
+
Index: /trunk/minix/servers/pm/table.c
===================================================================
--- /trunk/minix/servers/pm/table.c	(revision 9)
+++ /trunk/minix/servers/pm/table.c	(revision 9)
@@ -0,0 +1,115 @@
+/* This file contains the table used to map system call numbers onto the
+ * routines that perform them.
+ */
+
+#define _TABLE
+
+#include "pm.h"
+#include <minix/callnr.h>
+#include <signal.h>
+#include "mproc.h"
+#include "param.h"
+
+/* Miscellaneous */
+char core_name[] = "core";	/* file name where core images are produced */
+
+_PROTOTYPE (int (*call_vec[NCALLS]), (void) ) = {
+	no_sys,		/*  0 = unused	*/
+	do_pm_exit,	/*  1 = exit	*/
+	do_fork,	/*  2 = fork	*/
+	no_sys,		/*  3 = read	*/
+	no_sys,		/*  4 = write	*/
+	no_sys,		/*  5 = open	*/
+	no_sys,		/*  6 = close	*/
+	do_waitpid,	/*  7 = wait	*/
+	no_sys,		/*  8 = creat	*/
+	no_sys,		/*  9 = link	*/
+	no_sys,		/* 10 = unlink	*/
+	do_waitpid,	/* 11 = waitpid	*/
+	no_sys,		/* 12 = chdir	*/
+	do_time,	/* 13 = time	*/
+	no_sys,		/* 14 = mknod	*/
+	no_sys,		/* 15 = chmod	*/
+	no_sys,		/* 16 = chown	*/
+	do_brk,		/* 17 = break	*/
+	no_sys,		/* 18 = stat	*/
+	no_sys,		/* 19 = lseek	*/
+	do_getset,	/* 20 = getpid	*/
+	no_sys,		/* 21 = mount	*/
+	no_sys,		/* 22 = umount	*/
+	do_getset,	/* 23 = setuid	*/
+	do_getset,	/* 24 = getuid	*/
+	do_stime,	/* 25 = stime	*/
+	do_trace,	/* 26 = ptrace	*/
+	do_alarm,	/* 27 = alarm	*/
+	no_sys,		/* 28 = fstat	*/
+	do_pause,	/* 29 = pause	*/
+	no_sys,		/* 30 = utime	*/
+	no_sys,		/* 31 = (stty)	*/
+	no_sys,		/* 32 = (gtty)	*/
+	no_sys,		/* 33 = access	*/
+	no_sys,		/* 34 = (nice)	*/
+	no_sys,		/* 35 = (ftime)	*/
+	no_sys,		/* 36 = sync	*/
+	do_kill,	/* 37 = kill	*/
+	no_sys,		/* 38 = rename	*/
+	no_sys,		/* 39 = mkdir	*/
+	no_sys,		/* 40 = rmdir	*/
+	no_sys,		/* 41 = dup	*/
+	no_sys,		/* 42 = pipe	*/
+	do_times,	/* 43 = times	*/
+	no_sys,		/* 44 = (prof)	*/
+	no_sys,		/* 45 = unused	*/
+	do_getset,	/* 46 = setgid	*/
+	do_getset,	/* 47 = getgid	*/
+	no_sys,		/* 48 = (signal)*/
+	no_sys,		/* 49 = unused	*/
+	no_sys,		/* 50 = unused	*/
+	no_sys,		/* 51 = (acct)	*/
+	no_sys,		/* 52 = (phys)	*/
+	no_sys,		/* 53 = (lock)	*/
+	no_sys,		/* 54 = ioctl	*/
+	no_sys,		/* 55 = fcntl	*/
+	no_sys,		/* 56 = (mpx)	*/
+	no_sys,		/* 57 = unused	*/
+	no_sys,		/* 58 = unused	*/
+	do_exec,	/* 59 = execve	*/
+	no_sys,		/* 60 = umask	*/
+	no_sys,		/* 61 = chroot	*/
+	do_getset,	/* 62 = setsid	*/
+	do_getset,	/* 63 = getpgrp	*/
+
+	no_sys,		/* 64 = unused */
+	no_sys,		/* 65 = UNPAUSE	*/
+	no_sys, 	/* 66 = unused  */
+	no_sys,		/* 67 = REVIVE	*/
+	no_sys,		/* 68 = TASK_REPLY  */
+	no_sys,		/* 69 = unused	*/
+	no_sys,		/* 70 = unused	*/
+	do_sigaction,	/* 71 = sigaction   */
+	do_sigsuspend,	/* 72 = sigsuspend  */
+	do_sigpending,	/* 73 = sigpending  */
+	do_sigprocmask,	/* 74 = sigprocmask */
+	do_sigreturn,	/* 75 = sigreturn   */
+	do_reboot,	/* 76 = reboot	*/
+	do_svrctl,	/* 77 = svrctl	*/
+	do_procstat,	/* 78 = procstat */
+	do_getsysinfo,	/* 79 = getsysinfo */
+	do_getprocnr,	/* 80 = getprocnr */
+	no_sys, 	/* 81 = unused */
+	no_sys, 	/* 82 = fstatfs */
+	do_allocmem, 	/* 83 = memalloc */
+	do_freemem, 	/* 84 = memfree */
+	no_sys,		/* 85 = select */
+	no_sys,		/* 86 = fchdir */
+	no_sys,		/* 87 = fsync */
+	do_getsetpriority,	/* 88 = getpriority */
+	do_getsetpriority,	/* 89 = setpriority */
+	do_time,	/* 90 = gettimeofday */
+	do_getset,	/* 91 = seteuid	*/
+	do_getset,	/* 92 = setegid	*/
+	no_sys,		/* 93 = truncate */
+	no_sys,		/* 94 = ftruncate */
+};
+/* This should not fail with "array size is negative": */
+extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
Index: /trunk/minix/servers/pm/time.c
===================================================================
--- /trunk/minix/servers/pm/time.c	(revision 9)
+++ /trunk/minix/servers/pm/time.c	(revision 9)
@@ -0,0 +1,84 @@
+/* This file takes care of those system calls that deal with time.
+ *
+ * The entry points into this file are
+ *   do_time:		perform the TIME system call
+ *   do_stime:		perform the STIME system call
+ *   do_times:		perform the TIMES system call
+ */
+
+#include "pm.h"
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <signal.h>
+#include "mproc.h"
+#include "param.h"
+
+PRIVATE time_t boottime;
+
+/*===========================================================================*
+ *				do_time					     *
+ *===========================================================================*/
+PUBLIC int do_time()
+{
+/* Perform the time(tp) system call. This returns the time in seconds since 
+ * 1.1.1970.  MINIX is an astrophysically naive system that assumes the earth 
+ * rotates at a constant rate and that such things as leap seconds do not 
+ * exist.
+ */
+  clock_t uptime;
+  int s;
+
+  if ( (s=getuptime(&uptime)) != OK) 
+  	panic(__FILE__,"do_time couldn't get uptime", s);
+
+  mp->mp_reply.reply_time = (time_t) (boottime + (uptime/HZ));
+  mp->mp_reply.reply_utime = (uptime%HZ)*1000000/HZ;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_stime				     *
+ *===========================================================================*/
+PUBLIC int do_stime()
+{
+/* Perform the stime(tp) system call. Retrieve the system's uptime (ticks 
+ * since boot) and store the time in seconds at system boot in the global
+ * variable 'boottime'.
+ */
+  clock_t uptime;
+  int s;
+
+  if (mp->mp_effuid != SUPER_USER) { 
+      return(EPERM);
+  }
+  if ( (s=getuptime(&uptime)) != OK) 
+      panic(__FILE__,"do_stime couldn't get uptime", s);
+  boottime = (long) m_in.stime - (uptime/HZ);
+
+  /* Also inform FS about the new system time. */
+  tell_fs(STIME, boottime, 0, 0);
+
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_times				     *
+ *===========================================================================*/
+PUBLIC int do_times()
+{
+/* Perform the times(buffer) system call. */
+  register struct mproc *rmp = mp;
+  clock_t t[5];
+  int s;
+
+  if (OK != (s=sys_times(who_e, t)))
+      panic(__FILE__,"do_times couldn't get times", s);
+  rmp->mp_reply.reply_t1 = t[0];		/* user time */
+  rmp->mp_reply.reply_t2 = t[1];		/* system time */
+  rmp->mp_reply.reply_t3 = rmp->mp_child_utime;	/* child user time */
+  rmp->mp_reply.reply_t4 = rmp->mp_child_stime;	/* child system time */
+  rmp->mp_reply.reply_t5 = t[4];		/* uptime since boot */
+
+  return(OK);
+}
+
Index: /trunk/minix/servers/pm/timers.c
===================================================================
--- /trunk/minix/servers/pm/timers.c	(revision 9)
+++ /trunk/minix/servers/pm/timers.c	(revision 9)
@@ -0,0 +1,79 @@
+/* PM watchdog timer management. These functions in this file provide
+ * a convenient interface to the timers library that manages a list of
+ * watchdog timers. All details of scheduling an alarm at the CLOCK task 
+ * are hidden behind this interface.
+ * Only system processes are allowed to set an alarm timer at the kernel. 
+ * Therefore, the PM maintains a local list of timers for user processes
+ * that requested an alarm signal. 
+ * 
+ * The entry points into this file are:
+ *   pm_set_timer:      reset and existing or set a new watchdog timer
+ *   pm_expire_timers:  check for expired timers and run watchdog functions
+ *   pm_cancel_timer:   remove a time from the list of timers
+ *
+ */
+
+#include "pm.h"
+
+#include <timers.h>
+#include <minix/syslib.h>
+#include <minix/com.h>
+
+PRIVATE timer_t *pm_timers = NULL;
+
+/*===========================================================================*
+ *				pm_set_timer				     *
+ *===========================================================================*/
+PUBLIC void pm_set_timer(timer_t *tp, int ticks, tmr_func_t watchdog, int arg)
+{
+	int r;
+	clock_t now, prev_time = 0, next_time;
+
+	if ((r = getuptime(&now)) != OK)
+		panic(__FILE__, "PM couldn't get uptime", NO_NUM);
+
+	/* Set timer argument and add timer to the list. */
+	tmr_arg(tp)->ta_int = arg;
+	prev_time = tmrs_settimer(&pm_timers,tp,now+ticks,watchdog,&next_time);
+
+	/* Reschedule our synchronous alarm if necessary. */
+	if (! prev_time || prev_time > next_time) {
+		if (sys_setalarm(next_time, 1) != OK)
+			panic(__FILE__, "PM set timer couldn't set alarm.", NO_NUM);
+	}
+
+	return;
+}
+
+/*===========================================================================*
+ *				pm_expire_timers			     *
+ *===========================================================================*/
+PUBLIC void pm_expire_timers(clock_t now)
+{
+	clock_t next_time;
+
+	/* Check for expired timers and possibly reschedule an alarm. */
+	tmrs_exptimers(&pm_timers, now, &next_time);
+	if (next_time > 0) {
+		if (sys_setalarm(next_time, 1) != OK)
+			panic(__FILE__, "PM expire timer couldn't set alarm.", NO_NUM);
+	}
+}
+
+/*===========================================================================*
+ *				pm_cancel_timer				     *
+ *===========================================================================*/
+PUBLIC void pm_cancel_timer(timer_t *tp)
+{
+	clock_t next_time, prev_time;
+	prev_time = tmrs_clrtimer(&pm_timers, tp, &next_time);
+
+	/* If the earliest timer has been removed, we have to set the alarm to  
+     * the next timer, or cancel the alarm altogether if the last timer has 
+     * been cancelled (next_time will be 0 then).
+	 */
+	if (prev_time < next_time || ! next_time) {
+		if (sys_setalarm(next_time, 1) != OK)
+			panic(__FILE__, "PM expire timer couldn't set alarm.", NO_NUM);
+	}
+}
Index: /trunk/minix/servers/pm/trace.c
===================================================================
--- /trunk/minix/servers/pm/trace.c	(revision 9)
+++ /trunk/minix/servers/pm/trace.c	(revision 9)
@@ -0,0 +1,116 @@
+/* This file handles the process manager's part of debugging, using the 
+ * ptrace system call. Most of the commands are passed on to the system
+ * task for completion.
+ *
+ * The debugging commands available are:
+ * T_STOP	stop the process 
+ * T_OK		enable tracing by parent for this process
+ * T_GETINS	return value from instruction space 
+ * T_GETDATA	return value from data space 
+ * T_GETUSER	return value from user process table
+ * T_SETINS	set value in instruction space
+ * T_SETDATA	set value in data space
+ * T_SETUSER	set value in user process table 
+ * T_RESUME	resume execution 
+ * T_EXIT	exit
+ * T_STEP	set trace bit 
+ * 
+ * The T_OK and T_EXIT commands are handled here, and the T_RESUME and
+ * T_STEP commands are partially handled here and completed by the system
+ * task. The rest are handled entirely by the system task. 
+ */
+
+#include "pm.h"
+#include <minix/com.h>
+#include <sys/ptrace.h>
+#include <signal.h>
+#include "mproc.h"
+#include "param.h"
+
+#define NIL_MPROC	((struct mproc *) 0)
+
+FORWARD _PROTOTYPE( struct mproc *find_proc, (pid_t lpid) );
+
+/*===========================================================================*
+ *				do_trace  				     *
+ *===========================================================================*/
+PUBLIC int do_trace()
+{
+  register struct mproc *child;
+  int r;
+
+  /* the T_OK call is made by the child fork of the debugger before it execs  
+   * the process to be traced
+   */
+  if (m_in.request == T_OK) {	/* enable tracing by parent for this proc */
+	mp->mp_flags |= TRACED;
+	mp->mp_reply.reply_trace = 0;
+	return(OK);
+  }
+  if ((child=find_proc(m_in.pid))==NIL_MPROC || !(child->mp_flags & STOPPED)) {
+	return(ESRCH);
+  }
+  /* all the other calls are made by the parent fork of the debugger to 
+   * control execution of the child
+   */
+  switch (m_in.request) {
+  case T_EXIT:		/* exit */
+	pm_exit(child, (int) m_in.data);
+	mp->mp_reply.reply_trace = 0;
+	return(OK);
+  case T_RESUME: 
+  case T_STEP: 		/* resume execution */
+	if (m_in.data < 0 || m_in.data > _NSIG) return(EIO);
+	if (m_in.data > 0) {		/* issue signal */
+		child->mp_flags &= ~TRACED;  /* so signal is not diverted */
+		sig_proc(child, (int) m_in.data);
+		child->mp_flags |= TRACED;
+	}
+	child->mp_flags &= ~STOPPED;
+  	break;
+  }
+  r= sys_trace(m_in.request,child->mp_endpoint,m_in.taddr,&m_in.data);
+  if (r != OK) return(r);
+
+  mp->mp_reply.reply_trace = m_in.data;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				find_proc  				     *
+ *===========================================================================*/
+PRIVATE struct mproc *find_proc(lpid)
+pid_t lpid;
+{
+  register struct mproc *rmp;
+
+  for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++)
+	if (rmp->mp_flags & IN_USE && rmp->mp_pid == lpid) return(rmp);
+  return(NIL_MPROC);
+}
+
+/*===========================================================================*
+ *				stop_proc				     *
+ *===========================================================================*/
+PUBLIC void stop_proc(rmp, signo)
+register struct mproc *rmp;
+int signo;
+{
+/* A traced process got a signal so stop it. */
+
+  register struct mproc *rpmp = mproc + rmp->mp_parent;
+  int r;
+
+  r= sys_trace(-1, rmp->mp_endpoint, 0L, (long *) 0);
+  if (r != OK) panic("pm", "sys_trace failed", r);
+ 
+  rmp->mp_flags |= STOPPED;
+  if (rpmp->mp_flags & WAITING) {
+	rpmp->mp_flags &= ~WAITING;	/* parent is no longer waiting */
+	rpmp->mp_reply.reply_res2 = 0177 | (signo << 8);
+	setreply(rmp->mp_parent, rmp->mp_pid);
+  } else {
+	rmp->mp_sigstatus = signo;
+  }
+  return;
+}
Index: /trunk/minix/servers/pm/type.h
===================================================================
--- /trunk/minix/servers/pm/type.h	(revision 9)
+++ /trunk/minix/servers/pm/type.h	(revision 9)
@@ -0,0 +1,5 @@
+/* If there were any type definitions local to the Process Manager, they would
+ * be here.  This file is included only for symmetry with the kernel and File
+ * System, which do have some local type definitions.
+ */
+
Index: /trunk/minix/servers/pm/utility.c
===================================================================
--- /trunk/minix/servers/pm/utility.c	(revision 9)
+++ /trunk/minix/servers/pm/utility.c	(revision 9)
@@ -0,0 +1,239 @@
+/* This file contains some utility routines for PM.
+ *
+ * The entry points are:
+ *   find_param:	look up a boot monitor parameter
+ *   get_free_pid:	get a free process or group id
+ *   allowed:		see if an access is permitted
+ *   no_sys:		called for invalid system call numbers
+ *   panic:		PM has run aground of a fatal error 
+ *   tell_fs:		interface to FS
+ *   get_mem_map:	get memory map of given process
+ *   get_stack_ptr:	get stack pointer of given process	
+ *   proc_from_pid:	return process pointer from pid number
+ */
+
+#include "pm.h"
+#include <sys/stat.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/endpoint.h>
+#include <fcntl.h>
+#include <signal.h>		/* needed only because mproc.h needs it */
+#include "mproc.h"
+#include "param.h"
+
+#include <minix/config.h>
+#include <timers.h>
+#include <string.h>
+#include "../../kernel/const.h"
+#include "../../kernel/config.h"
+#include "../../kernel/type.h"
+#include "../../kernel/proc.h"
+
+/*===========================================================================*
+ *				get_free_pid				     *
+ *===========================================================================*/
+PUBLIC pid_t get_free_pid()
+{
+  static pid_t next_pid = INIT_PID + 1;		/* next pid to be assigned */
+  register struct mproc *rmp;			/* check process table */
+  int t;					/* zero if pid still free */
+
+  /* Find a free pid for the child and put it in the table. */
+  do {
+	t = 0;			
+	next_pid = (next_pid < NR_PIDS ? next_pid + 1 : INIT_PID + 1);
+	for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++)
+		if (rmp->mp_pid == next_pid || rmp->mp_procgrp == next_pid) {
+			t = 1;
+			break;
+		}
+  } while (t);					/* 't' = 0 means pid free */
+  return(next_pid);
+}
+
+/*===========================================================================*
+ *				allowed					     *
+ *===========================================================================*/
+PUBLIC int allowed(name_buf, s_buf, mask)
+char *name_buf;			/* pointer to file name to be EXECed */
+struct stat *s_buf;		/* buffer for doing and returning stat struct*/
+int mask;			/* R_BIT, W_BIT, or X_BIT */
+{
+/* Check to see if file can be accessed.  Return EACCES or ENOENT if the access
+ * is prohibited.  If it is legal open the file and return a file descriptor.
+ */
+  int fd;
+  int save_errno;
+
+  /* Use the fact that mask for access() is the same as the permissions mask.
+   * E.g., X_BIT in <minix/const.h> is the same as X_OK in <unistd.h> and
+   * S_IXOTH in <sys/stat.h>.  tell_fs(DO_CHDIR, ...) has set PM's real ids
+   * to the user's effective ids, so access() works right for setuid programs.
+   */
+  if (access(name_buf, mask) < 0) return(-errno);
+
+  /* The file is accessible but might not be readable.  Make it readable. */
+  tell_fs(SETUID, PM_PROC_NR, (int) SUPER_USER, (int) SUPER_USER);
+
+  /* Open the file and fstat it.  Restore the ids early to handle errors. */
+  fd = open(name_buf, O_RDONLY | O_NONBLOCK);
+  save_errno = errno;		/* open might fail, e.g. from ENFILE */
+  tell_fs(SETUID, PM_PROC_NR, (int) mp->mp_effuid, (int) mp->mp_effuid);
+  if (fd < 0) return(-save_errno);
+  if (fstat(fd, s_buf) < 0) panic(__FILE__,"allowed: fstat failed", NO_NUM);
+
+  /* Only regular files can be executed. */
+  if (mask == X_BIT && (s_buf->st_mode & I_TYPE) != I_REGULAR) {
+	close(fd);
+	return(EACCES);
+  }
+  return(fd);
+}
+
+/*===========================================================================*
+ *				no_sys					     *
+ *===========================================================================*/
+PUBLIC int no_sys()
+{
+/* A system call number not implemented by PM has been requested. */
+
+  return(ENOSYS);
+}
+
+/*===========================================================================*
+ *				panic					     *
+ *===========================================================================*/
+PUBLIC void panic(who, mess, num)
+char *who;			/* who caused the panic */
+char *mess;			/* panic message string */
+int num;			/* number to go with it */
+{
+/* An unrecoverable error has occurred.  Panics are caused when an internal
+ * inconsistency is detected, e.g., a programming error or illegal value of a
+ * defined constant. The process manager decides to exit.
+ */
+  message m;
+  int s;
+
+  /* Switch to primary console and print panic message. */
+  check_sig(mproc[TTY_PROC_NR].mp_pid, SIGTERM);
+  printf("PM panic (%s): %s", who, mess);
+  if (num != NO_NUM) printf(": %d",num);
+  printf("\n");
+   
+  /* Exit PM. */
+  sys_exit(SELF);
+}
+
+/*===========================================================================*
+ *				tell_fs					     *
+ *===========================================================================*/
+PUBLIC void tell_fs(what, p1, p2, p3)
+int what, p1, p2, p3;
+{
+/* This routine is only used by PM to inform FS of certain events:
+ *      tell_fs(CHDIR, slot, dir, 0)
+ *      tell_fs(EXEC, proc, 0, 0)
+ *      tell_fs(EXIT, proc, 0, 0)
+ *      tell_fs(FORK, parent, child, pid)
+ *      tell_fs(SETGID, proc, realgid, effgid)
+ *      tell_fs(SETSID, proc, 0, 0)
+ *      tell_fs(SETUID, proc, realuid, effuid)
+ *      tell_fs(UNPAUSE, proc, signr, 0)
+ *      tell_fs(STIME, time, 0, 0)
+ * Ignore this call if the FS is already dead, e.g. on shutdown.
+ */
+  message m;
+
+  if ((mproc[FS_PROC_NR].mp_flags & (IN_USE|ZOMBIE)) != IN_USE)
+      return;
+
+  m.tell_fs_arg1 = p1;
+  m.tell_fs_arg2 = p2;
+  m.tell_fs_arg3 = p3;
+  _taskcall(FS_PROC_NR, what, &m);
+}
+
+/*===========================================================================*
+ *				find_param				     *
+ *===========================================================================*/
+PUBLIC char *find_param(name)
+const char *name;
+{
+  register const char *namep;
+  register char *envp;
+
+  for (envp = (char *) monitor_params; *envp != 0;) {
+	for (namep = name; *namep != 0 && *namep == *envp; namep++, envp++)
+		;
+	if (*namep == '\0' && *envp == '=') 
+		return(envp + 1);
+	while (*envp++ != 0)
+		;
+  }
+  return(NULL);
+}
+
+/*===========================================================================*
+ *				get_mem_map				     *
+ *===========================================================================*/
+PUBLIC int get_mem_map(proc_nr, mem_map)
+int proc_nr;					/* process to get map of */
+struct mem_map *mem_map;			/* put memory map here */
+{
+  struct proc p;
+  int s;
+
+  if ((s=sys_getproc(&p, proc_nr)) != OK)
+  	return(s);
+  memcpy(mem_map, p.p_memmap, sizeof(p.p_memmap));
+  return(OK);
+}
+
+/*===========================================================================*
+ *				get_stack_ptr				     *
+ *===========================================================================*/
+PUBLIC int get_stack_ptr(proc_nr_e, sp)
+int proc_nr_e;					/* process to get sp of */
+vir_bytes *sp;					/* put stack pointer here */
+{
+  struct proc p;
+  int s;
+
+  if ((s=sys_getproc(&p, proc_nr_e)) != OK)
+  	return(s);
+  *sp = p.p_reg.sp;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				proc_from_pid				     *
+ *===========================================================================*/
+PUBLIC int proc_from_pid(mp_pid)
+pid_t mp_pid;
+{
+	int rmp;
+
+	for (rmp = 0; rmp < NR_PROCS; rmp++)
+		if (mproc[rmp].mp_pid == mp_pid)
+			return rmp;
+
+	return -1;
+}
+
+/*===========================================================================*
+ *				pm_isokendpt			 	     *
+ *===========================================================================*/
+PUBLIC int pm_isokendpt(int endpoint, int *proc)
+{
+	*proc = _ENDPOINT_P(endpoint);
+	if(*proc < -NR_TASKS || *proc >= NR_PROCS)
+		return EINVAL;
+	if(*proc >= 0 && endpoint != mproc[*proc].mp_endpoint)
+		return EDEADSRCDST;
+	if(*proc >= 0 && !(mproc[*proc].mp_flags & IN_USE))
+		return EDEADSRCDST;
+	return OK;
+}
+
Index: /trunk/minix/servers/rs/.depend
===================================================================
--- /trunk/minix/servers/rs/.depend	(revision 9)
+++ /trunk/minix/servers/rs/.depend	(revision 9)
@@ -0,0 +1,84 @@
+
+main.o:	../../kernel/config.h
+main.o:	../../kernel/const.h
+main.o:	../../kernel/type.h
+main.o:	/usr/include/ansi.h
+main.o:	/usr/include/errno.h
+main.o:	/usr/include/ibm/bios.h
+main.o:	/usr/include/ibm/cpu.h
+main.o:	/usr/include/ibm/interrupt.h
+main.o:	/usr/include/ibm/ports.h
+main.o:	/usr/include/limits.h
+main.o:	/usr/include/minix/bitmap.h
+main.o:	/usr/include/minix/callnr.h
+main.o:	/usr/include/minix/com.h
+main.o:	/usr/include/minix/config.h
+main.o:	/usr/include/minix/const.h
+main.o:	/usr/include/minix/devio.h
+main.o:	/usr/include/minix/dmap.h
+main.o:	/usr/include/minix/endpoint.h
+main.o:	/usr/include/minix/ipc.h
+main.o:	/usr/include/minix/keymap.h
+main.o:	/usr/include/minix/sys_config.h
+main.o:	/usr/include/minix/syslib.h
+main.o:	/usr/include/minix/sysutil.h
+main.o:	/usr/include/minix/type.h
+main.o:	/usr/include/signal.h
+main.o:	/usr/include/stdio.h
+main.o:	/usr/include/stdlib.h
+main.o:	/usr/include/string.h
+main.o:	/usr/include/sys/dir.h
+main.o:	/usr/include/sys/types.h
+main.o:	/usr/include/unistd.h
+main.o:	inc.h
+main.o:	main.c
+main.o:	manager.h
+main.o:	proto.h
+
+manager.o:	/usr/include/ansi.h
+manager.o:	/usr/include/errno.h
+manager.o:	/usr/include/limits.h
+manager.o:	/usr/include/minix/bitmap.h
+manager.o:	/usr/include/minix/callnr.h
+manager.o:	/usr/include/minix/com.h
+manager.o:	/usr/include/minix/config.h
+manager.o:	/usr/include/minix/const.h
+manager.o:	/usr/include/minix/devio.h
+manager.o:	/usr/include/minix/dmap.h
+manager.o:	/usr/include/minix/endpoint.h
+manager.o:	/usr/include/minix/ipc.h
+manager.o:	/usr/include/minix/keymap.h
+manager.o:	/usr/include/minix/sys_config.h
+manager.o:	/usr/include/minix/syslib.h
+manager.o:	/usr/include/minix/sysutil.h
+manager.o:	/usr/include/minix/type.h
+manager.o:	/usr/include/signal.h
+manager.o:	/usr/include/stdio.h
+manager.o:	/usr/include/stdlib.h
+manager.o:	/usr/include/string.h
+manager.o:	/usr/include/sys/dir.h
+manager.o:	/usr/include/sys/types.h
+manager.o:	/usr/include/sys/wait.h
+manager.o:	/usr/include/unistd.h
+manager.o:	inc.h
+manager.o:	manager.c
+manager.o:	manager.h
+manager.o:	proto.h
+
+service.o:	/usr/include/ansi.h
+service.o:	/usr/include/errno.h
+service.o:	/usr/include/minix/com.h
+service.o:	/usr/include/minix/config.h
+service.o:	/usr/include/minix/const.h
+service.o:	/usr/include/minix/devio.h
+service.o:	/usr/include/minix/ipc.h
+service.o:	/usr/include/minix/sys_config.h
+service.o:	/usr/include/minix/syslib.h
+service.o:	/usr/include/minix/type.h
+service.o:	/usr/include/stdio.h
+service.o:	/usr/include/stdlib.h
+service.o:	/usr/include/string.h
+service.o:	/usr/include/sys/dir.h
+service.o:	/usr/include/sys/stat.h
+service.o:	/usr/include/sys/types.h
+service.o:	service.c
Index: /trunk/minix/servers/rs/Makefile
===================================================================
--- /trunk/minix/servers/rs/Makefile	(revision 9)
+++ /trunk/minix/servers/rs/Makefile	(revision 9)
@@ -0,0 +1,46 @@
+# Makefile for Reincarnation Server (RS)
+SERVER = rs
+UTIL = service
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+
+# programs, flags, etc.
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+UTIL_LIBS = -lsys 
+LIBS = -lsys -lsysutil 
+
+UTIL_OBJ = service.o
+OBJ = main.o manager.o 
+
+# build local binary
+all build:	$(SERVER) $(UTIL)
+$(UTIL):	$(UTIL_OBJ)
+	$(CC) -o $@ $(LDFLAGS) $(UTIL_OBJ) $(UTIL_LIBS)
+$(SERVER):	$(OBJ)
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+	install -S 16k $@
+
+# install with other servers
+install:	/bin/$(UTIL) /usr/sbin/$(SERVER)
+/bin/$(UTIL):	$(UTIL)
+	install -c $? $@
+/usr/sbin/$(SERVER):	$(SERVER)
+	install -o root -c $? $@
+
+# clean up local files
+clean:
+	rm -f $(UTIL) $(SERVER) *.o *.bak 
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/servers/rs/inc.h
===================================================================
--- /trunk/minix/servers/rs/inc.h	(revision 9)
+++ /trunk/minix/servers/rs/inc.h	(revision 9)
@@ -0,0 +1,37 @@
+/* Header file for the system service manager server. 
+ *
+ * Created:
+ *    Jul 22, 2005	by Jorrit N. Herder 
+ */
+
+#define _SYSTEM            1    /* get OK and negative error codes */
+#define _MINIX             1	/* tell headers to include MINIX stuff */
+
+#define VERBOSE		   0	/* display diagnostics */
+
+#include <ansi.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <minix/callnr.h>
+#include <minix/config.h>
+#include <minix/type.h>
+#include <minix/const.h>
+#include <minix/com.h>
+#include <minix/syslib.h>
+#include <minix/sysutil.h>
+#include <minix/keymap.h>
+#include <minix/bitmap.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "proto.h"
+#include "manager.h"
+
Index: /trunk/minix/servers/rs/main.c
===================================================================
--- /trunk/minix/servers/rs/main.c	(revision 9)
+++ /trunk/minix/servers/rs/main.c	(revision 9)
@@ -0,0 +1,201 @@
+/* Reincarnation Server.  This servers starts new system services and detects
+ * they are exiting.   In case of errors, system services can be restarted.  
+ * The RS server periodically checks the status of all registered services
+ * services to see whether they are still alive.   The system services are 
+ * expected to periodically send a heartbeat message. 
+ * 
+ * Created:
+ *   Jul 22, 2005	by Jorrit N. Herder
+ */
+#include "inc.h"
+#include <minix/dmap.h>
+#include <minix/endpoint.h>
+#include "../../kernel/const.h"
+#include "../../kernel/type.h"
+
+/* Declare some local functions. */
+FORWARD _PROTOTYPE(void init_server, (void)				);
+FORWARD _PROTOTYPE(void sig_handler, (void)				);
+FORWARD _PROTOTYPE(void get_work, (message *m)				);
+FORWARD _PROTOTYPE(void reply, (int whom, int result)			);
+
+/* Data buffers to retrieve info during initialization. */
+PRIVATE struct boot_image image[NR_BOOT_PROCS];
+PUBLIC struct dmap dmap[NR_DEVICES];
+
+/*===========================================================================*
+ *				main                                         *
+ *===========================================================================*/
+PUBLIC int main(void)
+{
+/* This is the main routine of this service. The main loop consists of 
+ * three major activities: getting new work, processing the work, and
+ * sending the reply. The loop never terminates, unless a panic occurs.
+ */
+  message m;					/* request message */
+  int call_nr, who_e,who_p;			/* call number and caller */
+  int result;                 			/* result to return */
+  sigset_t sigset;				/* system signal set */
+  int s;
+
+  /* Initialize the server, then go to work. */
+  init_server();	
+
+  /* Main loop - get work and do it, forever. */         
+  while (TRUE) {              
+
+      /* Wait for request message. */
+      get_work(&m);
+      who_e = m.m_source;
+      who_p = _ENDPOINT_P(who_e);
+      if(who_p < -NR_TASKS || who_p >= NR_PROCS)
+	panic("RS","message from bogus source", who_e);
+
+      call_nr = m.m_type;
+
+      /* Now determine what to do.  Three types of requests are expected: 
+       * - Heartbeat messages (notifications from registered system services)
+       * - System notifications (POSIX signals or synchronous alarm)
+       * - User requests (control messages to manage system services)
+       */
+
+      /* Notification messages are control messages and do not need a reply.
+       * These include heartbeat messages and system notifications.
+       */
+      if (m.m_type & NOTIFY_MESSAGE) {
+          switch (call_nr) {
+          case SYN_ALARM:
+	      do_period(&m);			/* check drivers status */
+	      continue;				
+          case PROC_EVENT:
+	      sig_handler();
+              continue;				
+	  default:				/* heartbeat notification */
+	      if (rproc_ptr[who_p] != NULL)	/* mark heartbeat time */ 
+		  rproc_ptr[who_p]->r_alive_tm = m.NOTIFY_TIMESTAMP;
+	  }
+      }
+
+      /* If this is not a notification message, it is a normal request. 
+       * Handle the request and send a reply to the caller. 
+       */
+      else {	
+          switch(call_nr) {
+          case RS_UP: 		result = do_up(&m); 		break;
+          case RS_DOWN: 	result = do_down(&m); 		break;
+          case RS_REFRESH: 	result = do_refresh(&m); 	break;
+          case RS_RESCUE: 	result = do_rescue(&m); 	break;
+          case RS_SHUTDOWN: 	result = do_shutdown(&m); 	break;
+          case GETSYSINFO: 	result = do_getsysinfo(&m); 	break;
+          default: 
+              printf("Warning, RS got unexpected request %d from %d\n",
+                  m.m_type, m.m_source);
+              result = EINVAL;
+          }
+
+          /* Finally send reply message, unless disabled. */
+          if (result != EDONTREPLY) {
+              reply(who_e, result);
+          }
+      }
+  }
+}
+
+
+/*===========================================================================*
+ *				init_server                                  *
+ *===========================================================================*/
+PRIVATE void init_server(void)
+{
+/* Initialize the reincarnation server. */
+  struct sigaction sa;
+  struct boot_image *ip;
+  int s,t;
+
+  /* Install signal handlers. Ask PM to transform signal into message. */
+  sa.sa_handler = SIG_MESS;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = 0;
+  if (sigaction(SIGCHLD,&sa,NULL)<0) panic("RS","sigaction failed", errno);
+  if (sigaction(SIGTERM,&sa,NULL)<0) panic("RS","sigaction failed", errno);
+
+  /* Initialize the system process table. Use the boot image from the kernel
+   * and the device map from the FS to gather all needed information.
+   */
+  if ((s = sys_getimage(image)) != OK) 
+      panic("RS","warning: couldn't get copy of image table", s);
+  if ((s = getsysinfo(FS_PROC_NR, SI_DMAP_TAB, dmap)) < 0)
+      panic("RS","warning: couldn't get copy of dmap table", errno);
+  
+  /* Now initialize the table with the processes in the system image. 
+   * Prepend /sbin/ to the binaries so that we can actually find them. 
+   */
+  for (s=0; s< NR_BOOT_PROCS; s++) {
+      ip = &image[s];
+      if (ip->proc_nr >= 0) {
+          nr_in_use ++;
+          rproc[s].r_flags = RS_IN_USE;
+          rproc[s].r_proc_nr_e = ip->endpoint;
+          rproc[s].r_pid = getnpid(ip->proc_nr);
+	  for(t=0; t< NR_DEVICES; t++)
+	      if (dmap[t].dmap_driver == ip->proc_nr)
+                  rproc[s].r_dev_nr = t;
+	  strcpy(rproc[s].r_cmd, "/sbin/");
+          strcpy(rproc[s].r_cmd+6, ip->proc_name);
+          rproc[s].r_argc = 1;
+          rproc[s].r_argv[0] = rproc[s].r_cmd;
+          rproc[s].r_argv[1] = NULL;
+      }
+  }
+
+  /* Set alarm to periodically check driver status. */
+  if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
+      panic("RS", "couldn't set alarm", s);
+
+}
+
+/*===========================================================================*
+ *				sig_handler                                  *
+ *===========================================================================*/
+PRIVATE void sig_handler()
+{
+  sigset_t sigset;
+  int sig;
+
+  /* Try to obtain signal set from PM. */
+  if (getsigset(&sigset) != 0) return;
+
+  /* Check for known signals. */
+  if (sigismember(&sigset, SIGCHLD)) do_exit(NULL);
+  if (sigismember(&sigset, SIGTERM)) do_shutdown(NULL);
+}
+
+/*===========================================================================*
+ *				get_work                                     *
+ *===========================================================================*/
+PRIVATE void get_work(m_in)
+message *m_in;				/* pointer to message */
+{
+    int s;				/* receive status */
+    if (OK != (s=receive(ANY, m_in))) 	/* wait for message */
+        panic("RS","receive failed", s);
+}
+
+
+/*===========================================================================*
+ *				reply					     *
+ *===========================================================================*/
+PRIVATE void reply(who, result)
+int who;                           	/* replyee */
+int result;                           	/* report result */
+{
+    message m_out;			/* reply message */
+    int s;				/* send status */
+
+    m_out.m_type = result;  		/* build reply message */
+    if (OK != (s=send(who, &m_out)))    /* send the message */
+        panic("RS", "unable to send reply", s);
+}
+
+
+
Index: /trunk/minix/servers/rs/manager.c
===================================================================
--- /trunk/minix/servers/rs/manager.c	(revision 9)
+++ /trunk/minix/servers/rs/manager.c	(revision 9)
@@ -0,0 +1,458 @@
+/*
+ * Changes:
+ *   Jul 22, 2005:	Created  (Jorrit N. Herder)
+ */
+
+#include "inc.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <minix/dmap.h>
+#include <minix/endpoint.h>
+
+/* Allocate variables. */
+struct rproc rproc[NR_SYS_PROCS];		/* system process table */
+struct rproc *rproc_ptr[NR_PROCS];		/* mapping for fast access */
+int nr_in_use; 					/* number of services */
+extern int errno;				/* error status */
+
+/* Prototypes for internal functions that do the hard work. */
+FORWARD _PROTOTYPE( int start_service, (struct rproc *rp) );
+FORWARD _PROTOTYPE( int stop_service, (struct rproc *rp,int how) );
+
+PRIVATE int shutting_down = FALSE;
+
+#define EXEC_FAILED	49			/* recognizable status */
+
+/*===========================================================================*
+ *					do_up				     *
+ *===========================================================================*/
+PUBLIC int do_up(m_ptr)
+message *m_ptr;					/* request message pointer */
+{
+/* A request was made to start a new system service. Dismember the request 
+ * message and gather all information needed to start the service. Starting
+ * is done by a helper routine.
+ */
+  register struct rproc *rp;			/* system process table */
+  int slot_nr;					/* local table entry */
+  int arg_count;				/* number of arguments */
+  char *cmd_ptr;				/* parse command string */
+  enum dev_style dev_style;			/* device style */
+  int s;					/* status variable */
+
+  /* See if there is a free entry in the table with system processes. */
+  if (nr_in_use >= NR_SYS_PROCS) return(EAGAIN); 
+  for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
+      rp = &rproc[slot_nr];			/* get pointer to slot */
+      if (! rp->r_flags & RS_IN_USE) 		/* check if available */
+	  break;
+  }
+  nr_in_use ++;					/* update administration */
+
+  /* Obtain command name and parameters. This is a space-separated string
+   * that looks like "/sbin/service arg1 arg2 ...". Arguments are optional.
+   */
+  if (m_ptr->RS_CMD_LEN > MAX_COMMAND_LEN) return(E2BIG);
+  if (OK!=(s=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR, 
+  	SELF, (vir_bytes) rp->r_cmd, m_ptr->RS_CMD_LEN))) return(s);
+  rp->r_cmd[m_ptr->RS_CMD_LEN] = '\0';		/* ensure it is terminated */
+  if (rp->r_cmd[0] != '/') return(EINVAL);	/* insist on absolute path */
+
+  /* Build argument vector to be passed to execute call. The format of the
+   * arguments vector is: path, arguments, NULL. 
+   */
+  arg_count = 0;				/* initialize arg count */
+  rp->r_argv[arg_count++] = rp->r_cmd;		/* start with path */
+  cmd_ptr = rp->r_cmd;				/* do some parsing */ 
+  while(*cmd_ptr != '\0') {			/* stop at end of string */
+      if (*cmd_ptr == ' ') {			/* next argument */
+          *cmd_ptr = '\0';			/* terminate previous */
+	  while (*++cmd_ptr == ' ') ; 		/* skip spaces */
+	  if (*cmd_ptr == '\0') break;		/* no arg following */
+	  if (arg_count>MAX_NR_ARGS+1) break;	/* arg vector full */
+          rp->r_argv[arg_count++] = cmd_ptr;	/* add to arg vector */
+      }
+      cmd_ptr ++;				/* continue parsing */
+  }
+  rp->r_argv[arg_count] = NULL;			/* end with NULL pointer */
+  rp->r_argc = arg_count;
+
+  /* Initialize some fields. */
+  rp->r_period = m_ptr->RS_PERIOD;
+  rp->r_dev_nr = m_ptr->RS_DEV_MAJOR;
+  rp->r_dev_style = STYLE_DEV; 
+  rp->r_restarts = -1; 				/* will be incremented */
+  
+  /* All information was gathered. Now try to start the system service. */
+  return(start_service(rp));
+}
+
+
+/*===========================================================================*
+ *				do_down					     *
+ *===========================================================================*/
+PUBLIC int do_down(message *m_ptr)
+{
+  register struct rproc *rp;
+  pid_t pid = (pid_t) m_ptr->RS_PID;
+
+  for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
+      if (rp->r_flags & RS_IN_USE && rp->r_pid == pid) {
+#if VERBOSE
+	  printf("stopping %d (%d)\n", pid, m_ptr->RS_PID);
+#endif
+	  stop_service(rp,RS_EXITING);
+	  return(OK);
+      }
+  }
+#if VERBOSE
+  printf("not found %d (%d)\n", pid, m_ptr->RS_PID);
+#endif
+  return(ESRCH);
+}
+
+
+/*===========================================================================*
+ *				do_refresh				     *
+ *===========================================================================*/
+PUBLIC int do_refresh(message *m_ptr)
+{
+  register struct rproc *rp;
+  pid_t pid = (pid_t) m_ptr->RS_PID;
+
+  for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
+      if (rp->r_flags & RS_IN_USE && rp->r_pid == pid) {
+#if VERBOSE
+	  printf("refreshing %d (%d)\n", pid, m_ptr->RS_PID);
+#endif
+	  stop_service(rp,RS_REFRESHING);
+	  return(OK);
+      }
+  }
+#if VERBOSE
+  printf("not found %d (%d)\n", pid, m_ptr->RS_PID);
+#endif
+  return(ESRCH);
+}
+
+/*===========================================================================*
+ *				do_rescue				     *
+ *===========================================================================*/
+PUBLIC int do_rescue(message *m_ptr)
+{
+  char rescue_dir[MAX_RESCUE_DIR_LEN];
+  int s;
+
+  /* Copy rescue directory from user. */
+  if (m_ptr->RS_CMD_LEN > MAX_RESCUE_DIR_LEN) return(E2BIG);
+  if (OK!=(s=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR, 
+  	SELF, (vir_bytes) rescue_dir, m_ptr->RS_CMD_LEN))) return(s);
+  rescue_dir[m_ptr->RS_CMD_LEN] = '\0';		/* ensure it is terminated */
+  if (rescue_dir[0] != '/') return(EINVAL);	/* insist on absolute path */
+
+  /* Change RS' directory to the rescue directory. Provided that the needed
+   * binaries are in the rescue dir, this makes recovery possible even if the 
+   * (root) file system is no longer available, because no directory lookups
+   * are required. Thus if an absolute path fails, we can try to strip the 
+   * path an see if the command is in the rescue dir. 
+   */
+  if (chdir(rescue_dir) != 0) return(errno);
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_shutdown				     *
+ *===========================================================================*/
+PUBLIC int do_shutdown(message *m_ptr)
+{
+  /* Set flag so that RS server knows services shouldn't be restarted. */
+  shutting_down = TRUE;
+  return(OK);
+}
+
+/*===========================================================================*
+ *				do_exit					     *
+ *===========================================================================*/
+PUBLIC void do_exit(message *m_ptr)
+{
+  register struct rproc *rp;
+  pid_t exit_pid;
+  int exit_status;
+
+#if VERBOSE
+  printf("RS: got SIGCHLD signal, doing wait to get exited child.\n");
+#endif
+
+  /* See which child exited and what the exit status is. This is done in a
+   * loop because multiple childs may have exited, all reported by one 
+   * SIGCHLD signal. The WNOHANG options is used to prevent blocking if, 
+   * somehow, no exited child can be found. 
+   */
+  while ( (exit_pid = waitpid(-1, &exit_status, WNOHANG)) != 0 ) {
+
+#if VERBOSE
+      printf("RS: proc %d, pid %d, ", rp->r_proc_nr_e, exit_pid); 
+      if (WIFSIGNALED(exit_status)) {
+          printf("killed, signal number %d\n", WTERMSIG(exit_status));
+      } 
+      else if (WIFEXITED(exit_status)) {
+          printf("normal exit, status %d\n", WEXITSTATUS(exit_status));
+      }
+#endif
+
+      /* Search the system process table to see who exited. 
+       * This should always succeed. 
+       */
+      for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
+          if ((rp->r_flags & RS_IN_USE) && rp->r_pid == exit_pid) {
+	      int proc;
+	      proc = _ENDPOINT_P(rp->r_proc_nr_e);
+
+              rproc_ptr[proc] = NULL;		/* invalidate */
+
+              if ((rp->r_flags & RS_EXITING) || shutting_down) {
+		  rp->r_flags = 0;			/* release slot */
+		  rproc_ptr[proc] = NULL;
+	      }
+	      else if(rp->r_flags & RS_REFRESHING) {
+		      rp->r_restarts = -1;		/* reset counter */
+		      start_service(rp);		/* direct restart */
+	      }
+              else if (WIFEXITED(exit_status) &&
+		      WEXITSTATUS(exit_status) == EXEC_FAILED) {
+		  rp->r_flags = 0;			/* release slot */
+              }
+	      else {
+#if VERBOSE
+		  printf("Unexpected exit. Restarting %s\n", rp->r_cmd);
+#endif
+                  /* Determine what to do. If this is the first unexpected 
+		   * exit, immediately restart this service. Otherwise use
+		   * a binary exponetial backoff.
+		   */
+                  if (rp->r_restarts > 0) {
+		      rp->r_backoff = 1 << MIN(rp->r_restarts,(BACKOFF_BITS-1));
+		      rp->r_backoff = MIN(rp->r_backoff,MAX_BACKOFF); 
+		  }
+		  else {
+		      start_service(rp);		/* direct restart */
+		  }
+              }
+	      break;
+	  }
+      }
+  }
+}
+
+/*===========================================================================*
+ *				do_period				     *
+ *===========================================================================*/
+PUBLIC void do_period(m_ptr)
+message *m_ptr;
+{
+  register struct rproc *rp;
+  clock_t now = m_ptr->NOTIFY_TIMESTAMP;
+  int s;
+
+  /* Search system services table. Only check slots that are in use. */
+  for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
+      if (rp->r_flags & RS_IN_USE) {
+
+          /* If the service is to be revived (because it repeatedly exited, 
+	   * and was not directly restarted), the binary backoff field is  
+	   * greater than zero. 
+	   */
+	  if (rp->r_backoff > 0) {
+              rp->r_backoff -= 1;
+	      if (rp->r_backoff == 0) {
+		  start_service(rp);
+	      }
+	  }
+
+	  /* If the service was signaled with a SIGTERM and fails to respond,
+	   * kill the system service with a SIGKILL signal.
+	   */
+	  else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T
+	   && rp->r_pid > 0) {
+              kill(rp->r_pid, SIGKILL);		/* terminate */
+	  }
+	
+	  /* There seems to be no special conditions. If the service has a 
+	   * period assigned check its status. 
+	   */
+	  else if (rp->r_period > 0) {
+
+	      /* Check if an answer to a status request is still pending. If 
+	       * the driver didn't respond within time, kill it to simulate 
+	       * a crash. The failure will be detected and the service will 
+	       * be restarted automatically.
+	       */
+              if (rp->r_alive_tm < rp->r_check_tm) { 
+	          if (now - rp->r_alive_tm > 2*rp->r_period &&
+		      rp->r_pid > 0) { 
+#if VERBOSE
+                      printf("RS: service %d reported late\n", rp->r_proc_nr_e); 
+#endif
+                      kill(rp->r_pid, SIGKILL);		/* simulate crash */
+		  }
+	      }
+
+	      /* No answer pending. Check if a period expired since the last
+	       * check and, if so request the system service's status.
+	       */
+	      else if (now - rp->r_check_tm > rp->r_period) {
+#if VERBOSE
+                  printf("RS: status request sent to %d\n", rp->r_proc_nr_e); 
+#endif
+		  notify(rp->r_proc_nr_e);		/* request status */
+		  rp->r_check_tm = now;			/* mark time */
+              }
+          }
+      }
+  }
+
+  /* Reschedule a synchronous alarm for the next period. */
+  if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
+      panic("RS", "couldn't set alarm", s);
+}
+
+
+/*===========================================================================*
+ *				start_service				     *
+ *===========================================================================*/
+PRIVATE int start_service(rp)
+struct rproc *rp;
+{
+/* Try to execute the given system service. Fork a new process. The child
+ * process will be inhibited from running by the NO_PRIV flag. Only let the
+ * child run once its privileges have been set by the parent.
+ */
+  int child_proc_nr_e, child_proc_nr_n;		/* child process slot */
+  pid_t child_pid;				/* child's process id */
+  char *file_only;
+  int s;
+  message m;
+
+  /* Now fork and branch for parent and child process (and check for error). */
+  child_pid = fork();
+  switch(child_pid) {					/* see fork(2) */
+  case -1:						/* fork failed */
+      report("RS", "warning, fork() failed", errno);	/* shouldn't happen */
+      return(errno);					/* return error */
+
+  case 0:						/* child process */
+      /* Try to execute the binary that has an absolute path. If this fails, 
+       * e.g., because the root file system cannot be read, try to strip of
+       * the path, and see if the command is in RS' current working dir.
+       */
+      execve(rp->r_argv[0], rp->r_argv, NULL);		/* POSIX execute */
+      file_only = strrchr(rp->r_argv[0], '/') + 1;
+      execve(file_only, rp->r_argv, NULL);		/* POSIX execute */
+      printf("RS: exec failed for %s: %d\n", rp->r_argv[0], errno);
+      exit(EXEC_FAILED);				/* terminate child */
+
+  default:						/* parent process */
+      child_proc_nr_e = getnprocnr(child_pid);		/* get child slot */ 
+      break;						/* continue below */
+  }
+
+  /* Only the parent process (the RS server) gets to this point. The child
+   * is still inhibited from running because it's privilege structure is
+   * not yet set. First try to set the device driver mapping at the FS.
+   */
+  if (rp->r_dev_nr > 0) {				/* set driver map */
+      if ((s=mapdriver(child_proc_nr_e, rp->r_dev_nr, rp->r_dev_style)) < 0) {
+          report("RS", "couldn't map driver", errno);
+          rp->r_flags |= RS_EXITING;			/* expect exit */
+	  if(child_pid > 0) kill(child_pid, SIGKILL);	/* kill driver */
+	  else report("RS", "didn't kill pid", child_pid);
+	  return(s);					/* return error */
+      }
+  }
+
+  /* The device driver mapping has been set, or the service was not a driver.
+   * Now, set the privilege structure for the child process to let is run.
+   * This should succeed: we tested number in use above.
+   */
+  if ((s = sys_privctl(child_proc_nr_e, SYS_PRIV_INIT, 0, NULL)) < 0) {
+      report("RS","call to SYSTEM failed", s);		/* to let child run */
+      rp->r_flags |= RS_EXITING;			/* expect exit */
+      if(child_pid > 0) kill(child_pid, SIGKILL);	/* kill driver */
+      else report("RS", "didn't kill pid", child_pid);
+      return(s);					/* return error */
+  }
+
+#if VERBOSE
+      printf("RS: started '%s', major %d, pid %d, endpoint %d, proc %d\n", 
+          rp->r_cmd, rp->r_dev_nr, child_pid,
+	  child_proc_nr_e, child_proc_nr_n);
+#endif
+
+  /* The system service now has been successfully started. Update the rest
+   * of the system process table that is maintain by the RS server. The only 
+   * thing that can go wrong now, is that execution fails at the child. If 
+   * that's the case, the child will exit. 
+   */
+  child_proc_nr_n = _ENDPOINT_P(child_proc_nr_e);
+  rp->r_flags = RS_IN_USE;			/* mark slot in use */
+  rp->r_restarts += 1;				/* raise nr of restarts */
+  rp->r_proc_nr_e = child_proc_nr_e;		/* set child details */
+  rp->r_pid = child_pid;
+  rp->r_check_tm = 0;				/* not check yet */
+  getuptime(&rp->r_alive_tm); 			/* currently alive */
+  rp->r_stop_tm = 0;				/* not exiting yet */
+  rproc_ptr[child_proc_nr_n] = rp;		/* mapping for fast access */
+  return(OK);
+}
+
+/*===========================================================================*
+ *				stop_service				     *
+ *===========================================================================*/
+PRIVATE int stop_service(rp,how)
+struct rproc *rp;
+int how;
+{
+  /* Try to stop the system service. First send a SIGTERM signal to ask the
+   * system service to terminate. If the service didn't install a signal 
+   * handler, it will be killed. If it did and ignores the signal, we'll
+   * find out because we record the time here and send a SIGKILL.
+   */
+#if VERBOSE
+  printf("RS tries to stop %s (pid %d)\n", rp->r_cmd, rp->r_pid);
+#endif
+
+  rp->r_flags |= how;				/* what to on exit? */
+  if(rp->r_pid > 0) kill(rp->r_pid, SIGTERM);	/* first try friendly */
+  else report("RS", "didn't kill pid", rp->r_pid);
+  getuptime(&rp->r_stop_tm); 			/* record current time */
+}
+
+
+/*===========================================================================*
+ *				do_getsysinfo				     *
+ *===========================================================================*/
+PUBLIC int do_getsysinfo(m_ptr)
+message *m_ptr;
+{
+  vir_bytes src_addr, dst_addr;
+  int dst_proc;
+  size_t len;
+  int s;
+
+  switch(m_ptr->m1_i1) {
+  case SI_PROC_TAB:
+  	src_addr = (vir_bytes) rproc;
+  	len = sizeof(struct rproc) * NR_SYS_PROCS;
+  	break; 
+  default:
+  	return(EINVAL);
+  }
+
+  dst_proc = m_ptr->m_source;
+  dst_addr = (vir_bytes) m_ptr->m1_p1;
+  if (OK != (s=sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)))
+  	return(s);
+  return(OK);
+}
+
Index: /trunk/minix/servers/rs/manager.h
===================================================================
--- /trunk/minix/servers/rs/manager.h	(revision 9)
+++ /trunk/minix/servers/rs/manager.h	(revision 9)
@@ -0,0 +1,52 @@
+/* This table has one slot per system process.  It contains information for
+ * servers and driver needed by the reincarnation server to keep track of 
+ * each process' status. 
+ */
+
+/* Space reserved for program and arguments. */
+#define MAX_COMMAND_LEN     512		/* maximum argument string length */
+#define MAX_NR_ARGS	      4		/* maximum number of arguments */
+#define MAX_RESCUE_DIR_LEN   64		/* maximum rescue dir length */
+
+/* Definition of the system process table. This table only has entries for
+ * the servers and drivers, and thus is not directly indexed by slot number.
+ */
+extern struct rproc {
+  int r_proc_nr_e;		/* process endpoint number */
+  pid_t r_pid;			/* process id */
+  dev_t r_dev_nr;		/* major device number */
+  int r_dev_style;		/* device style */
+
+  int r_restarts;		/* number of restarts (initially zero) */
+  long r_backoff;		/* number of periods to wait before revive */
+  unsigned r_flags; 		/* status and policy flags */
+
+  long r_period;		/* heartbeat period (or zero) */
+  clock_t r_check_tm;		/* timestamp of last check */
+  clock_t r_alive_tm;		/* timestamp of last heartbeat */
+  clock_t r_stop_tm;		/* timestamp of SIGTERM signal */
+
+  char r_cmd[MAX_COMMAND_LEN];	/* raw command plus arguments */
+  char *r_argv[MAX_NR_ARGS+2];  /* parsed arguments vector */
+  int r_argc;  			/* number of arguments */
+} rproc[NR_SYS_PROCS];
+
+/* Mapping for fast access to the system process table. */ 
+extern struct rproc *rproc_ptr[NR_PROCS];
+extern int nr_in_use;
+
+/* Flag values. */
+#define RS_IN_USE       0x001	/* set when process slot is in use */
+#define RS_EXITING      0x002	/* set when exit is expected */
+#define RS_REFRESHING   0x004	/* set when refresh must be done */
+
+/* Constants determining RS period and binary exponential backoff. */
+#define RS_DELTA_T       60			/* check every T ticks */
+#define BACKOFF_BITS 	(sizeof(long)*8)	/* bits in backoff field */
+#define MAX_BACKOFF     30			/* max backoff in RS_DELTA_T */
+
+/* Magic process table addresses. */
+#define BEG_RPROC_ADDR	(&rproc[0])
+#define END_RPROC_ADDR	(&rproc[NR_SYS_PROCS])
+#define NIL_RPROC ((struct mproc *) 0)
+
Index: /trunk/minix/servers/rs/proto.h
===================================================================
--- /trunk/minix/servers/rs/proto.h	(revision 9)
+++ /trunk/minix/servers/rs/proto.h	(revision 9)
@@ -0,0 +1,16 @@
+/* Function prototypes. */
+
+/* main.c */
+_PROTOTYPE( int main, (void));
+
+/* manager.c */
+_PROTOTYPE( int do_up, (message *m));
+_PROTOTYPE( int do_down, (message *m));
+_PROTOTYPE( int do_refresh, (message *m));
+_PROTOTYPE( int do_rescue, (message *m));
+_PROTOTYPE( int do_shutdown, (message *m));
+_PROTOTYPE( void do_period, (message *m));
+_PROTOTYPE( void do_exit, (message *m));
+_PROTOTYPE( int do_getsysinfo, (message *m));
+
+
Index: /trunk/minix/servers/rs/service.c
===================================================================
--- /trunk/minix/servers/rs/service.c	(revision 9)
+++ /trunk/minix/servers/rs/service.c	(revision 9)
@@ -0,0 +1,278 @@
+/* Utility to start or stop system services.  Requests are sent to the 
+ * reincarnation server that does the actual work. 
+ *
+ * Changes:
+ *   Jul 22, 2005:	Created  (Jorrit N. Herder)
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <minix/config.h>
+#include <minix/com.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/syslib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+/* This array defines all known requests. */
+PRIVATE char *known_requests[] = {
+  "up", 
+  "down",
+  "refresh", 
+  "rescue", 
+  "shutdown", 
+  "catch for illegal requests"
+};
+#define ILLEGAL_REQUEST  sizeof(known_requests)/sizeof(char *)
+
+/* Global error number set for failed system calls. */
+#define OK 0
+extern int errno;
+
+/* Define names for arguments provided to this utility. The first few 
+ * arguments are required and have a known index. Thereafter, some optional
+ * argument pairs like "-args arglist" follow.
+ */
+#define ARG_NAME	0		/* own application name */
+#define ARG_REQUEST	1		/* request to perform */
+#define ARG_PATH	2		/* rescue dir or system service */
+#define ARG_PID		2		/* pid of system service */
+
+#define MIN_ARG_COUNT	2		/* require an action */
+
+#define ARG_ARGS	"-args"		/* list of arguments to be passed */
+#define ARG_DEV		"-dev"		/* major device number for drivers */
+#define ARG_PRIV	"-priv"		/* required privileges */
+#define ARG_PERIOD	"-period"	/* heartbeat period in ticks */
+
+/* The function parse_arguments() verifies and parses the command line 
+ * parameters passed to this utility. Request parameters that are needed
+ * are stored globally in the following variables:
+ */
+PRIVATE int req_type;
+PRIVATE int req_pid;
+PRIVATE char *req_path;
+PRIVATE char *req_args;
+PRIVATE int req_major;
+PRIVATE long req_period;
+PRIVATE char *req_priv;
+
+/* Buffer to build "/command arg1 arg2 ..." string to pass to RS server. */
+PRIVATE char command[4096];	
+
+/* An error occurred. Report the problem, print the usage, and exit. 
+ */
+PRIVATE void print_usage(char *app_name, char *problem) 
+{
+  printf("Warning, %s\n", problem);
+  printf("Usage:\n");
+  printf("    %s up <binary> [%s <args>] [%s <special>] [%s <ticks>]\n", 
+	app_name, ARG_ARGS, ARG_DEV, ARG_PERIOD);
+  printf("    %s down <pid>\n", app_name);
+  printf("    %s refresh <pid>\n", app_name);
+  printf("    %s rescue <dir>\n", app_name);
+  printf("    %s shutdown\n", app_name);
+  printf("\n");
+}
+
+/* A request to the RS server failed. Report and exit. 
+ */
+PRIVATE void failure(int num) 
+{
+  printf("Request to RS failed: %s (%d)\n", strerror(num), num);
+  exit(num);
+}
+
+
+/* Parse and verify correctness of arguments. Report problem and exit if an 
+ * error is found. Store needed parameters in global variables.
+ */
+PRIVATE int parse_arguments(int argc, char **argv)
+{
+  struct stat stat_buf;
+  char *hz;
+  int req_nr;
+  int i;
+
+  /* Verify argument count. */ 
+  if (argc < MIN_ARG_COUNT) {
+      print_usage(argv[ARG_NAME], "wrong number of arguments");
+      exit(EINVAL);
+  }
+
+  /* Verify request type. */
+  for (req_type=0; req_type< ILLEGAL_REQUEST; req_type++) {
+      if (strcmp(known_requests[req_type],argv[ARG_REQUEST])==0) break;
+  }
+  if (req_type == ILLEGAL_REQUEST) {
+      print_usage(argv[ARG_NAME], "illegal request type");
+      exit(ENOSYS);
+  }
+  req_nr = RS_RQ_BASE + req_type;
+
+  if (req_nr == RS_UP) {
+
+      /* Verify argument count. */ 
+      if (argc - 1 < ARG_PATH) {
+          print_usage(argv[ARG_NAME], "action requires a binary to start");
+          exit(EINVAL);
+      }
+
+      /* Verify the name of the binary of the system service. */
+      req_path = argv[ARG_PATH];
+      if (req_path[0] != '/') {
+          print_usage(argv[ARG_NAME], "binary should be absolute path");
+          exit(EINVAL);
+      }
+      if (stat(req_path, &stat_buf) == -1) {
+	  perror(req_path);
+          fprintf(stderr, "couldn't get stat binary\n");
+          exit(errno);
+      }
+      if (! (stat_buf.st_mode & S_IFREG)) {
+          print_usage(argv[ARG_NAME], "binary is not a regular file");
+          exit(EINVAL);
+      }
+
+      /* Check optional arguments that come in pairs like "-args arglist". */
+      for (i=MIN_ARG_COUNT+1; i<argc; i=i+2) {
+          if (! (i+1 < argc)) {
+              print_usage(argv[ARG_NAME], "optional argument not complete");
+              exit(EINVAL);
+          }
+          if (strcmp(argv[i], ARG_ARGS)==0) {
+              req_args = argv[i+1];
+          }
+          else if (strcmp(argv[i], ARG_PERIOD)==0) {
+	      req_period = strtol(argv[i+1], &hz, 10);
+	      if (strcmp(hz,"HZ")==0) req_period *= HZ;
+	      if (req_period < 1) {
+                  print_usage(argv[ARG_NAME], "period is at least be one tick");
+                  exit(EINVAL);
+	      }
+          }
+          else if (strcmp(argv[i], ARG_DEV)==0) {
+              if (stat(argv[i+1], &stat_buf) == -1) {
+                  print_usage(argv[ARG_NAME], "couldn't get status of device");
+                  exit(errno);
+              }
+	      if ( ! (stat_buf.st_mode & (S_IFBLK | S_IFCHR))) {
+                  print_usage(argv[ARG_NAME], "special file is not a device");
+                  exit(EINVAL);
+       	      } 
+              req_major = (stat_buf.st_rdev >> MAJOR) & BYTE;
+          }
+          else if (strcmp(argv[i], ARG_ARGS)==0) {
+              req_priv = argv[i+1];
+          }
+          else {
+              print_usage(argv[ARG_NAME], "unknown optional argument given");
+              exit(EINVAL);
+          }
+      }
+  }
+  else if (req_nr == RS_DOWN || req_nr == RS_REFRESH) {
+
+      /* Verify argument count. */ 
+      if (argc - 1 < ARG_PID) {
+          print_usage(argv[ARG_NAME], "action requires a pid to stop");
+          exit(EINVAL);
+      }
+      if (! (req_pid = atoi(argv[ARG_PID])) > 0) {
+          print_usage(argv[ARG_NAME], "pid must be greater than zero");
+          exit(EINVAL);
+      }
+  } 
+  else if (req_nr == RS_RESCUE) {
+
+      /* Verify argument count. */ 
+      if (argc - 1 < ARG_PATH) {
+          print_usage(argv[ARG_NAME], "action requires rescue directory");
+          exit(EINVAL);
+      }
+      req_path = argv[ARG_PATH];
+      if (req_path[0] != '/') {
+          print_usage(argv[ARG_NAME], "rescue dir should be absolute path");
+          exit(EINVAL);
+      }
+      if (stat(argv[ARG_PATH], &stat_buf) == -1) {
+          print_usage(argv[ARG_NAME], "couldn't get status of directory");
+          exit(errno);
+      }
+      if ( ! (stat_buf.st_mode & S_IFDIR)) {
+          print_usage(argv[ARG_NAME], "file is not a directory");
+          exit(EINVAL);
+      } 
+  } 
+  else if (req_nr == RS_SHUTDOWN) {
+        /* no extra arguments required */
+  }
+
+  /* Return the request number if no error were found. */
+  return(req_nr);
+}
+
+
+/* Main program. 
+ */
+PUBLIC int main(int argc, char **argv)
+{
+  message m;
+  int result;
+  int request;
+  int s;
+
+  /* Verify and parse the command line arguments. All arguments are checked
+   * here. If an error occurs, the problem is reported and exit(2) is called. 
+   * all needed parameters to perform the request are extracted and stored
+   * global variables. 
+   */
+  request = parse_arguments(argc, argv);
+
+  /* Arguments seem fine. Try to perform the request. Only valid requests 
+   * should end up here. The default is used for not yet supported requests. 
+   */
+  switch(request) {
+  case RS_UP:
+      /* Build space-separated command string to be passed to RS server. */
+      strcpy(command, req_path);
+      command[strlen(req_path)] = ' ';
+      strcpy(command+strlen(req_path)+1, req_args);
+
+      /* Build request message and send the request. */
+      m.RS_CMD_ADDR = command;
+      m.RS_CMD_LEN = strlen(command);
+      m.RS_DEV_MAJOR = req_major;
+      m.RS_PERIOD = req_period;
+      if (OK != (s=_taskcall(RS_PROC_NR, request, &m))) 
+          failure(s);
+      result = m.m_type;
+      break;
+  case RS_DOWN:
+  case RS_REFRESH:
+      m.RS_PID = req_pid;
+      if (OK != (s=_taskcall(RS_PROC_NR, request, &m))) 
+          failure(s);
+      break;
+  case RS_RESCUE:
+      m.RS_CMD_ADDR = req_path;
+      m.RS_CMD_LEN = strlen(req_path);
+      if (OK != (s=_taskcall(RS_PROC_NR, request, &m))) 
+          failure(s);
+      break;
+  case RS_SHUTDOWN:
+      if (OK != (s=_taskcall(RS_PROC_NR, request, &m))) 
+          failure(s);
+      break;
+  default:
+      print_usage(argv[ARG_NAME], "request is not yet supported");
+      result = EGENERIC;
+  }
+  return(result);
+}
+
Index: /trunk/minix/servers/sm/Makefile
===================================================================
--- /trunk/minix/servers/sm/Makefile	(revision 9)
+++ /trunk/minix/servers/sm/Makefile	(revision 9)
@@ -0,0 +1,45 @@
+# Makefile for System Process Manager (SM)
+SERVER = sm
+UTIL = service
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+
+# programs, flags, etc.
+CC =	exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+UTIL_LIBS = -lsys 
+LIBS = -lsys -lsysutil 
+
+UTIL_OBJ = service.o
+OBJ = sm.o manager.o 
+
+# build local binary
+all build:	$(SERVER) $(UTIL)
+$(UTIL):	$(UTIL_OBJ)
+	$(CC) -o $@ $(LDFLAGS) $(UTIL_OBJ) $(UTIL_LIBS)
+$(SERVER):	$(OBJ)
+	$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+
+# install with other servers
+install:	/bin/$(UTIL) /usr/sbin/$(SERVER)
+/bin/$(UTIL):	$(UTIL)
+	install -c $? $@
+/usr/sbin/$(SERVER):	$(SERVER)
+	install -o root -c $? $@
+
+# clean up local files
+clean:
+	rm -f $(UTIL) $(SERVER) *.o *.bak 
+
+depend: 
+	/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
Index: /trunk/minix/test/Makefile
===================================================================
--- /trunk/minix/test/Makefile	(revision 9)
+++ /trunk/minix/test/Makefile	(revision 9)
@@ -0,0 +1,78 @@
+# Makefile for the tests.
+
+CC =	exec cc
+CFLAGS= -O -D_MINIX -D_POSIX_SOURCE
+
+OBJ=	test1  test2  test3  test4  test5  test6  test7  test8  test9  \
+	test10        test12 test13 test14 test15 test16 test17 test18 test19 \
+	       test21 test22 test23        test25 test26 test27 test28 test29 \
+	test30 test31 test32        test34 test35 test36 test37 test38 test39 \
+	test40 test41 t10a t11a t11b
+
+BIGOBJ=  test20 test24
+ROOTOBJ= test11 test33
+
+all:	$(OBJ) $(BIGOBJ) $(ROOTOBJ)
+	chmod 755 *.sh run
+
+$(OBJ):
+	$(CC) $(CFLAGS) -o $@ $@.c
+	@install -S 10kw $@
+
+$(BIGOBJ):
+	$(CC) $(CFLAGS) -o $@ $@.c
+	@install -S 32kw $@
+
+$(ROOTOBJ):
+	$(CC) $(CFLAGS) $@.c
+	@install -c -S 10kw -o root -m 4755 a.out $@
+	@rm a.out
+
+clean:	
+	cd select && make clean
+	-rm -rf *.o *.s *.bak test? test?? t10a t11a t11b DIR*
+
+test1:	test1.c
+test2:	test2.c
+test3:	test3.c
+test4:	test4.c
+test5:	test5.c
+test6:	test6.c
+test7:	test7.c
+test8:	test8.c
+test9:	test9.c
+test10:	test10.c
+t10a:	t10a.c
+test11:	test11.c
+t11a:	t11a.c
+t11b:	t11b.c
+test12:	test12.c
+test13:	test13.c
+test14:	test14.c
+test15:	test15.c
+test16:	test16.c
+test17:	test17.c
+test18:	test18.c
+test19:	test19.c
+test20:	test20.c
+test21:	test21.c
+test22:	test22.c
+test23:	test23.c
+test24:	test24.c
+test25:	test25.c
+test26:	test26.c
+test27:	test27.c
+test28:	test28.c
+test29:	test29.c
+test30:	test30.c
+test31:	test31.c
+test32:	test32.c
+test33:	test33.c
+test34:	test34.c
+test35:	test35.c
+test36:	test36.c
+test37:	test37.c
+test38:	test38.c
+test39:	test39.c
+test40:	test40.c
+test41: test41.c
Index: /trunk/minix/test/common.c
===================================================================
--- /trunk/minix/test/common.c	(revision 9)
+++ /trunk/minix/test/common.c	(revision 9)
@@ -0,0 +1,103 @@
+/* Utility routines for Minix tests.
+ * This is designed to be #includ'ed near the top of test programs.  It is
+ * self-contained except for MAX_ERRORS.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+int common_test_nr = -1, errct = 0, subtest;
+
+_PROTOTYPE(void cleanup, (void));
+_PROTOTYPE(void e, (int n));
+_PROTOTYPE(void quit, (void));
+_PROTOTYPE(void rm_rf_dir, (int test_nr));
+_PROTOTYPE(void rm_rf_ppdir, (int test_nr));
+_PROTOTYPE(void start, (int test_nr));
+
+void start(test_nr)
+int test_nr;
+{
+  char buf[64];
+
+  common_test_nr = test_nr;
+  printf("Test %2d ", test_nr);
+  fflush(stdout);		/* since stdout is probably line buffered */
+  sync();
+  rm_rf_dir(test_nr);
+  sprintf(buf, "mkdir DIR_%02d", test_nr);
+  if (system(buf) != 0) {
+	e(666);
+	quit();
+  }
+  sprintf(buf, "DIR_%02d", test_nr);
+  if (chdir(buf) != 0) {
+	e(6666);
+	quit();
+  }
+}
+
+void rm_rf_dir(test_nr)
+int test_nr;
+{
+  char buf[128];
+
+  /* "rm -rf dir" will not work unless all the subdirectories have suitable
+   * permissions.  Minix chmod is not recursive so it is not easy to change
+   * all the permissions.  I had to fix opendir() to stop the bash shell
+   * from hanging when it opendir()s fifos.
+   */
+  sprintf(buf, "chmod 777 DIR_%02d DIR_%02d/* DIR_%02d/*/* >/dev/null 2>&1",
+	  test_nr, test_nr, test_nr);
+  (void) system(buf);		/* usually fails */
+  sprintf(buf, "rm -rf DIR_%02d >/dev/null 2>&1", test_nr);
+  if (system(buf) != 0) printf("Warning: system(\"%s\") failed\n", buf);
+}
+
+void rm_rf_ppdir(test_nr)
+int test_nr;
+{
+/* Attempt to remove everything in the test directory (== the current dir). */
+
+  char buf[128];
+
+  sprintf(buf, "chmod 777 ../DIR_%02d/* ../DIR_%02d/*/* >/dev/null 2>&1",
+	  test_nr, test_nr);
+  (void) system(buf);
+  sprintf(buf, "rm -rf ../DIR_%02d >/dev/null 2>&1", test_nr);
+  if (system(buf) != 0) printf("Warning: system(\"%s\") failed\n", buf);
+}
+
+void e(n)
+int n;
+{
+  if (errct == 0) printf("\n");	/* finish header */
+  printf("Subtest %d,  error %d,  errno %d: %s\n",
+	 subtest, n, errno, strerror(errno));
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	cleanup();
+	exit(1);
+  }
+  errno = 0;			/* don't leave it around to confuse next e() */
+}
+
+void cleanup()
+{
+  if (chdir("..") == 0 && common_test_nr != -1) rm_rf_dir(common_test_nr);
+}
+
+void quit()
+{
+  cleanup();
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/run
===================================================================
--- /trunk/minix/test/run	(revision 9)
+++ /trunk/minix/test/run	(revision 9)
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+# Initialization
+PATH=:/bin:/usr/bin
+export PATH
+
+rm -rf DIR*			# remove any old junk lying around
+passed=`expr 0`			# count number of tests run correctly
+failed=`expr 0`			# count number of tests that failed
+total=`expr 0`			# total number of tests tried
+badones=			# list of tests that failed
+
+# Print test welcome message
+clr
+echo "Running POSIX compliance test suite. There are 43 tests in total."
+echo "The last few tests may take up to 15 minutes each, even on fast"
+echo "systems."
+echo " "
+
+# Run all the tests, keeping track of who failed.
+for i in  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 \
+         21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 \
+	sh1.sh sh2.sh
+do total=`expr $total + 1`
+   if ./test$i
+      then passed=`expr $passed + 1`
+      else failed=`expr $failed + 1`
+           badones=`echo $badones " " $i`
+   fi
+done
+
+# Print results of the tests.
+echo " "
+if test $total = $passed
+   then echo All $passed tests completed without error.
+   else echo Testing completed.  Score:   $passed passed,  $failed failed
+        echo The following tests failed: $badones
+fi
+
+# echo " "
Index: /trunk/minix/test/select/Makefile
===================================================================
--- /trunk/minix/test/select/Makefile	(revision 9)
+++ /trunk/minix/test/select/Makefile	(revision 9)
@@ -0,0 +1,39 @@
+# Makefile for the tests
+
+CC = exec cc
+CFLAGS = -Wall -D_MINIX -D_POSIX_SOURCE
+
+PROG =	speed test00 test01 test02 test03 test04_srv test04_cli test05_srv \
+        test05_cli test06_srv test06_cli test07_srv test07_cli test08_srv \
+        test08_cli test09 test10 test11 test12 test13a test13b test14
+
+all: $(PROG)
+
+$(PROG): 
+	$(CC) $(CFLAGS) -o $@ $@.c -lutil
+
+clean:
+	/usr/bin/rm -f *.o $(PROG)
+
+speed: speed.c
+test00: test00.c
+test01: test01.c
+test02: test02.c
+test03: test03.c
+test04_cli: test04_cli.c
+test04_srv: test04_srv.c
+test05_cli: test05_cli.c
+test05_srv: test05_srv.c
+test06_cli: test06_cli.c
+test06_srv: test06_srv.c
+test07_cli: test07_cli.c
+test07_srv: test07_srv.c
+test08_cli: test08_cli.c
+test08_srv: test08_srv.c
+test09: test09.c
+test10: test10.c
+test11: test11.c
+test12: test12.c
+test13a: test13a.c
+test13b: test13b.c
+test14: test14.c
Index: /trunk/minix/test/select/speed.c
===================================================================
--- /trunk/minix/test/select/speed.c	(revision 9)
+++ /trunk/minix/test/select/speed.c	(revision 9)
@@ -0,0 +1,59 @@
+/*
+ * Test name: speed.c
+ *
+ * Objetive:  Test the time it takes for select to run. 
+ * 
+ * Description: This tests creates a number of udp connections and performs 
+ * a select call waiting on them for reading with timeout of 0.
+ * This is done 10,000 thousands of times and then the average time it takes
+ * is computed
+ *
+ * Jose M. Gomez
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <sys/asynchio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <net/netlib.h>
+#include <time.h>
+
+#define NUMBER 12
+
+void main(void) {
+	char *udp_device;
+	int fd[NUMBER];
+	fd_set fds_write;
+	struct timeval timeout;
+	time_t start_time, end_time;
+	int i;
+
+	FD_ZERO(&fds_write);
+	for (i = 0; i < NUMBER; i++) {
+		fd[i] = open("/dev/tty", O_RDWR);
+		if (fd[i] < 0) {
+			fprintf(stderr, "Error opening tty %d\n", i); 
+			exit(-1);
+		}
+		FD_SET(fd[i], &fds_write);
+	}	
+
+	printf("Select will send 1 msg to terminal and %d to inet: \n", NUMBER);
+	timeout.tv_sec = 0;
+	timeout.tv_usec = 0;
+	/* get initial time */
+	start_time = time(NULL);
+	for (i = 0; i < 32000; i++) {
+		select(NUMBER + 4, NULL, &fds_write, NULL, &timeout); 
+	}
+	/* get final time */
+	end_time = time(NULL);
+	printf("The select call took on average: %f\n", (float)(end_time - start_time) /  32000.0);
+	for (i = 0; i < NUMBER; i++) {
+		close(fd[i]);
+	}
+}
Index: /trunk/minix/test/select/test00.c
===================================================================
--- /trunk/minix/test/select/test00.c	(revision 9)
+++ /trunk/minix/test/select/test00.c	(revision 9)
@@ -0,0 +1,58 @@
+/*
+ * Test name: test00.c
+ *
+ * Objetive: The purpose of this test is to make sure that the bitmap 
+ * manipulation macros work without problems.  
+ *
+ * Description: This tests first fills a fd_set bit by bit, and shows it, then
+ * it clears the fd_set bit by bit as well. 
+ *
+ * Jose M. Gomez
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+int main(int argc, char *argv[]) {
+	fd_set fds;
+	int i,j;	
+
+	FD_ZERO(&fds);
+	for (i=0;i<FD_SETSIZE;i++) {
+		/* see if SET works */
+		FD_SET(i, &fds);
+		if(!FD_ISSET(i, &fds))
+			return 1;
+	}
+	FD_ZERO(&fds);
+	for (i=0;i<FD_SETSIZE;i++) {
+		/* see if ZERO works */
+		if(FD_ISSET(i, &fds))
+			return 1;
+	}
+	for (i=0;i<FD_SETSIZE;i++) {
+		FD_SET(i, &fds);
+		for(j = 0; j <= i; j++)
+			if(!FD_ISSET(j, &fds))
+				return 1;
+		for(; j < FD_SETSIZE; j++) 
+			if(FD_ISSET(j, &fds))
+				return 1;
+	}
+	for (i=0;i<FD_SETSIZE;i++) {
+		FD_CLR(i, &fds);
+		for(j = 0; j <= i; j++)
+			if(FD_ISSET(j, &fds))
+				return 1;
+		for(; j < FD_SETSIZE; j++) 
+			if(!FD_ISSET(j, &fds))
+				return 1;
+	}
+	printf("ok\n");
+	return 0;
+}
Index: /trunk/minix/test/select/test01.c
===================================================================
--- /trunk/minix/test/select/test01.c	(revision 9)
+++ /trunk/minix/test/select/test01.c	(revision 9)
@@ -0,0 +1,74 @@
+/*
+ * Test name: test01.c
+ *
+ * Objective: The purpose of this test is to make sure that the timeout mechanisms
+ * work without errors.
+ * 
+ * Description: Executes a select as if it was a sleep and compares the time it
+ * has been actually sleeping against the specified time in the select call.
+ * Three cases are tested: first, a timeout specified in seconds, second, a timeout in 
+ * microseconds, and third, a timeout with more precision than seconds.
+ *
+ * Jose M. Gomez
+ */
+
+#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#define SECONDS 3
+#define USECONDS 3000000L
+
+int main(void) {
+	int r;
+	time_t start, end;	/* variables for timing */ 
+	struct timeval timeout;	/* timeout structure */
+
+	/* Set timeout for 3 seconds */
+	timeout.tv_sec = SECONDS;
+	timeout.tv_usec = 0;
+   	printf("Sleeping now for %d seconds...\n", SECONDS);
+	/* Record time before starting */
+	start = time(NULL);
+	r = select(0, NULL, NULL, NULL, &timeout); 
+	printf("select return code: %d error: %s\n",
+		r, strerror(errno));
+	end = time(NULL);
+	printf("For a timeout with select of %d seconds, it took %d actual seconds\n",
+		SECONDS, end-start);
+
+	/* Set timeout for 3 seconds , but specified in microseconds */
+
+	timeout.tv_sec = 0;
+	timeout.tv_usec = USECONDS;
+	printf("\n***************************\n");
+   	printf("Sleeping now for %ld microseconds...\n", USECONDS);
+	/* Record time before starting */
+	start = time(NULL);
+	r = select(0, NULL, NULL, NULL, &timeout); 
+	printf("select return code: %d error: %s\n",
+		r, strerror(errno));
+	end = time(NULL);
+	printf("For a timeout with select of %ld useconds, it took %d actual seconds\n",
+		USECONDS, end-start);
+
+	/* Set timeout for 1.5 seconds, but specified in microseconds */
+
+	timeout.tv_sec = 0;
+	timeout.tv_usec = USECONDS/2;
+	printf("\n***************************\n");
+   	printf("Sleeping now for %ld microseconds...\n", USECONDS/2);
+	/* Record time before starting */
+	start = time(NULL);
+	r = select(0, NULL, NULL, NULL, &timeout); 
+	printf("select return code: %d error: %s\n",
+		r, strerror(errno));
+	end = time(NULL);
+	printf("For a timeout with select of %ld useconds, it took %d actual seconds\n",
+		USECONDS/2, end-start);
+	return 0;
+}
Index: /trunk/minix/test/select/test02.c
===================================================================
--- /trunk/minix/test/select/test02.c	(revision 9)
+++ /trunk/minix/test/select/test02.c	(revision 9)
@@ -0,0 +1,112 @@
+/*
+ * Test name: test02.c
+ *
+ * Objetive: The purpose of this test is to make sure that select works
+ * when working with files.
+ *
+ * Description: This tests first creates six dummy files with different
+ * modes and performs select calls on them evaluating the input and resulting
+ * bitmaps. 
+ *
+ * Jose M. Gomez
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+void dump_fdset(fd_set *set) {
+	int i;
+	for (i = 0; i < OPEN_MAX; i++)  
+	if (FD_ISSET(i, set))
+		printf(" %d->1 ", i);
+	else 
+		printf(" %d->0  ", i);
+	printf("\n");
+}
+
+void main(void) {
+	int fd1, fd2, fd3, fd4, fd5, fd6;	/* file descriptors of files */
+	fd_set fds_read, fds_write;
+	int retval;
+
+	/* Creates the dummy files with different modes */
+	fd1 = open("dummy1.txt", O_CREAT | O_RDONLY);
+	if (fd1 < 0) {
+		perror("Error opening file"); 
+		exit(-1);
+	}
+	
+	fd2 = open("dummy2.txt", O_CREAT | O_RDONLY);
+	if (fd2 < 0) {
+		perror("Error opening file");
+		exit(-1);
+	}
+
+	fd3 = open("dummy3.txt", O_CREAT | O_WRONLY);
+	if (fd3 < 0) {
+		perror("Error opening file");
+		exit(-1);
+	}
+
+	fd4 = open("dummy4.txt", O_CREAT | O_WRONLY);
+	if (fd4 < 0) {
+		perror("Error opening file");
+		exit(-1);
+	}
+
+	fd5 = open("dummy5.txt", O_CREAT | O_RDWR);
+	if (fd5 < 0) {
+		perror("Error opening file");
+		exit(-1);
+	}
+
+	fd6 = open("dummy6.txt", O_CREAT | O_RDWR);
+	if (fd6 < 0) {
+		perror("Error opening file");
+		exit(-1);
+	}
+
+	/* Create the fd_set structures */
+	FD_ZERO(&fds_read);
+	FD_ZERO(&fds_write);
+	FD_SET(fd1, &fds_read);		/* fd1 => O_RDONLY */
+	FD_SET(fd2, &fds_read);		/* fd2 => O_RDONLY */
+	FD_SET(fd3, &fds_write);	/* fd3 => O_WRONLY */
+	FD_SET(fd4, &fds_write);	/* fd4 => O_WRONLY */
+	FD_SET(fd5, &fds_read);		/* fd5 => O_RDWR */
+	FD_SET(fd5, &fds_write);	/* fd5 => O_RDWR */
+	FD_SET(fd6, &fds_read);		/* fd6 => O_RDWR */
+	FD_SET(fd6, &fds_write);	/* fd6 => O_RDWR */
+
+	printf("* Dump INPUT fds_read:\n"); 
+	dump_fdset(&fds_read);
+	printf("* Dump INPUT fds_write:\n");
+	dump_fdset(&fds_write);
+
+	retval=select(9, &fds_read, &fds_write, NULL, NULL); 
+	printf("\n***********************\n");
+	printf("After select: \n");
+	printf("Return value: %d\n", retval);
+	printf("* Dump RESULTING fds_read:\n");
+	dump_fdset(&fds_read);
+	printf("* Dump RESULTING fds_write:\n");
+	dump_fdset(&fds_write);	
+	/* close and delete dummy files */
+	close(fd1);
+	close(fd2);
+	close(fd3);
+	close(fd4);
+	close(fd5);
+	close(fd6);
+	unlink("dummy1.txt");
+	unlink("dummy2.txt");
+	unlink("dummy3.txt");
+	unlink("dummy4.txt");
+	unlink("dummy5.txt");
+	unlink("dummy6.txt");
+}
Index: /trunk/minix/test/select/test03.c
===================================================================
--- /trunk/minix/test/select/test03.c	(revision 9)
+++ /trunk/minix/test/select/test03.c	(revision 9)
@@ -0,0 +1,135 @@
+/*
+ * Test name: test02.c
+ *
+ * Objetive: The purpose of this test is to make sure that select works
+ * when working with files.
+ *
+ * Description: This test shows more cases than in test02.c, where every
+ * descriptor is ready. Here in one select call only half of the fd's will
+ * be ready and in the next one none of them will be ready.  
+ *
+ * Jose M. Gomez
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <sys/time.h>
+
+void dump_fdset(fd_set *set) {
+	int i;
+	for (i = 0; i < OPEN_MAX; i++)  
+	if (FD_ISSET(i, set))
+		printf(" %d ", i);
+	printf("\n");
+}
+
+void main(void) {
+	int fd1, fd2, fd3, fd4, fd5, fd6;	/* file descriptors of files */
+	fd_set fds_read, fds_write;		/* bit maps */
+	struct timeval timeout;			/* timeout */
+	int retval;				/* ret value */		
+
+	/* Creates the dummy files with different modes */
+	fd1 = open("dummy1.txt", O_CREAT | O_RDONLY);
+	if (fd1 < 0) {
+		perror("Error opening file"); 
+		exit(-1);
+	}
+	
+	fd2 = open("dummy2.txt", O_CREAT | O_RDONLY);
+	if (fd2 < 0) {
+		perror("Error opening file");
+		exit(-1);
+	}
+
+	fd3 = open("dummy3.txt", O_CREAT | O_WRONLY);
+	if (fd3 < 0) {
+		perror("Error opening file");
+		exit(-1);
+	}
+
+	fd4 = open("dummy4.txt", O_CREAT | O_WRONLY);
+	if (fd4 < 0) {
+		perror("Error opening file");
+		exit(-1);
+	}
+
+	fd5 = open("dummy5.txt", O_CREAT | O_RDWR);
+	if (fd5 < 0) {
+		perror("Error opening file");
+		exit(-1);
+	}
+
+	fd6 = open("dummy6.txt", O_CREAT | O_RDWR);
+	if (fd6 < 0) {
+		perror("Error opening file");
+		exit(-1);
+	}
+
+	/* Create the fd_set structures */
+	FD_ZERO(&fds_read);
+	FD_ZERO(&fds_write);
+	FD_SET(fd1, &fds_write);	/* fd1 => O_RDONLY */
+	FD_SET(fd2, &fds_write);	/* fd2 => O_RDONLY */
+	FD_SET(fd3, &fds_read);		/* fd3 => O_WRONLY */
+	FD_SET(fd4, &fds_read);		/* fd4 => O_WRONLY */
+	FD_SET(fd5, &fds_read);		/* fd5 => O_RDWR */
+	FD_SET(fd5, &fds_write);	/* fd5 => O_RDWR */
+	FD_SET(fd6, &fds_read);		/* fd6 => O_RDWR */
+	FD_SET(fd6, &fds_write);	/* fd6 => O_RDWR */
+
+	printf("* Dump INPUT fds_read:\n"); 
+	dump_fdset(&fds_read);
+	printf("* Dump INPUT fds_write:\n");
+	dump_fdset(&fds_write);
+
+	retval=select(9, &fds_read, &fds_write, NULL, NULL); 
+	printf("\n***********************\n");
+	printf("After select: \n");
+	printf("Return value: %d\n", retval);
+	printf("* Dump RESULTING fds_read:\n");
+	dump_fdset(&fds_read);
+	printf("* Dump RESULTING fds_write:\n");
+	dump_fdset(&fds_write);	
+
+	/* make a select call where none of them are ready (don't use fd5 and fd6) */
+
+	FD_ZERO(&fds_read);
+	FD_ZERO(&fds_write);
+	FD_SET(fd1, &fds_write);	/* fd1 => O_RDONLY */
+	FD_SET(fd2, &fds_write);	/* fd2 => O_RDONLY */
+	FD_SET(fd3, &fds_read);		/* fd3 => O_WRONLY */
+	FD_SET(fd4, &fds_read);		/* fd4 => O_WRONLY */
+
+	/* make a select call where none of them are ready (don't use fd5 and fd6) */
+	/* create a timeout as well */
+	timeout.tv_sec = 5;
+	timeout.tv_usec = 0;
+	retval=select(7, &fds_read, &fds_write, NULL, NULL); 
+	printf("\n***********************\n");
+	printf("After select: \n");
+	printf("Return value: %d\n", retval);
+	printf("* Dump RESULTING fds_read:\n");
+	dump_fdset(&fds_read);
+	printf("* Dump RESULTING fds_write:\n");
+	dump_fdset(&fds_write);	
+
+	/* close and delete dummy files */
+	close(fd1);
+	close(fd2);
+	close(fd3);
+	close(fd4);
+	close(fd5);
+	close(fd6);
+	unlink("dummy1.txt");
+	unlink("dummy2.txt");
+	unlink("dummy3.txt");
+	unlink("dummy4.txt");
+	unlink("dummy5.txt");
+	unlink("dummy6.txt");
+}
Index: /trunk/minix/test/select/test04_cli.c
===================================================================
--- /trunk/minix/test/select/test04_cli.c	(revision 9)
+++ /trunk/minix/test/select/test04_cli.c	(revision 9)
@@ -0,0 +1,148 @@
+/*
+ * Test name: test04_cli.c
+ *
+ * Objective: Test a simple UDP client
+ *
+ * Description: Implements a simple echo client using the UDP protocol. First
+ * it waits until it is possible to write (which is always).
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <net/netlib.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/udp_io.h>
+#include <net/hton.h>
+
+#define PORT 6000L
+
+/* Type for received data */
+typedef struct
+{
+  udp_io_hdr_t header;
+  char data[1024];
+} udp_buffer_t;
+
+int udp_conf(char *host, long port, udp_io_hdr_t *header)
+{
+  /* configures UDP connection */
+  char *udp_device;
+  struct hostent *hp;
+  int netfd;
+  nwio_udpopt_t udpopt;
+  ipaddr_t dirhost;
+  int result;
+  
+  /* get host address */
+  if ((hp = gethostbyname(host)) == (struct hostent*) NULL) 
+  {
+    fprintf(stderr,"Unknown host\n");
+    return(-1);
+  }
+  memcpy((char *)&dirhost, (char *)hp->h_addr, hp->h_length);
+  
+  /* Get UDP device */
+  if (( udp_device = getenv("UDP_DEVICE") ) == NULL) 
+    udp_device = UDP_DEVICE;
+  
+  /* Get UDP connection */ 
+  if ((netfd = open(udp_device, O_RDWR)) < 0) 
+  {
+    fprintf(stderr,"Error opening UDP device\n");
+    return -1;
+  }
+  
+  /* Configure UDP connection */
+  udpopt.nwuo_flags = NWUO_COPY | NWUO_LP_SEL | NWUO_EN_LOC | NWUO_DI_BROAD 
+                   | NWUO_RP_SET | NWUO_RA_SET | NWUO_RWDATALL | NWUO_DI_IPOPT;
+  udpopt.nwuo_remaddr = dirhost;
+  udpopt.nwuo_remport = (udpport_t) htons(port);
+  
+  if ((result = ioctl(netfd, NWIOSUDPOPT, &udpopt) ) <0) 
+  {
+    fprintf(stderr, "Error establishing communication\n");
+    printf("Error:  %d\n",result);
+    close(netfd);
+    return -1;
+  }
+  
+  /* Get configuration for UDP comm */ 
+  if ((result = ioctl(netfd, NWIOGUDPOPT, &udpopt) ) < 0) 
+  {
+    fprintf(stderr,"Error getting configuration\n");
+    printf("Error: %d\n", result);
+    close(netfd);
+    return -1;
+  }
+
+  header->uih_src_addr = udpopt.nwuo_locaddr;
+  header->uih_dst_addr = udpopt.nwuo_remaddr;
+  header->uih_src_port = udpopt.nwuo_locport;
+  header->uih_dst_port = udpopt.nwuo_remport;
+ 
+  return netfd;
+}
+
+int main(int argc,char *argv[]) {
+  int fd;
+  ssize_t data_read;
+  udp_buffer_t buffer_send, buffer_rec;
+  fd_set fds_write;
+  int ret;
+
+  /* Check parameters */
+  if (argc !=2) {
+    fprintf(stderr,"Usage: %s host\n", argv[0]);
+    exit(-1);
+  }
+
+  if ((fd = udp_conf(argv[1], PORT, &buffer_send.header) ) < 0) 
+    exit(-1);	
+
+  /* init fd_set */
+  FD_ZERO(&fds_write);
+  FD_SET(fd, &fds_write);
+
+  while (1) 
+  {
+    /* Wait until it is possible to write with select */
+
+    ret = select(4, NULL, &fds_write, NULL, NULL);
+    if (ret < 0) {
+    	fprintf(stderr, "Error on select waiting for write: %d\n", errno);
+    	exit(-1);
+    }
+    if (!FD_ISSET(fd, &fds_write)) {
+    	fprintf(stderr, "Error: The net connection is not ready for writing (?)\n"); 
+    	exit(-1);
+    }
+
+    /* Get a string and send it */
+    printf("Ready to write...\n");
+    printf("Send data: ");
+    gets(buffer_send.data);
+    write(fd, &buffer_send, sizeof(udp_buffer_t));
+  
+    /* If data sent is exit then break */
+    if (!strcmp(buffer_send.data,"exit")) 
+      break;
+  		
+    /* Get server response */
+    data_read = read(fd, &buffer_rec, sizeof(udp_buffer_t));
+    printf("Received: %s\n\n", buffer_rec.data);
+  }
+  
+  /* Close UDP communication */
+  close(fd);
+}
Index: /trunk/minix/test/select/test04_srv.c
===================================================================
--- /trunk/minix/test/select/test04_srv.c	(revision 9)
+++ /trunk/minix/test/select/test04_srv.c	(revision 9)
@@ -0,0 +1,134 @@
+/*
+ * Test name: test04_srv.c
+ *
+ * Objective: Test a simple UDP server
+ *
+ * Description: Implements a simple echo server using the UDP protocol. Instead
+ * of blocking on read(), it performs a select call first blocking there 
+ * until there is data to be read
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <net/netlib.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/udp_io.h>
+#include <net/hton.h>
+
+#define PORT 6000L
+
+/* type for received data */
+typedef struct 
+{
+  udp_io_hdr_t header;
+  char data[1024];
+} udp_buffer_t;
+
+int udp_conf(long port) {
+
+  char *udp_device;
+  int netfd;
+  nwio_udpopt_t udpopt;
+                            
+  /* Get default UDP device */
+  if ((udp_device = getenv("UDP_DEVICE")) == NULL) 
+    udp_device = UDP_DEVICE;
+                                
+  /* Open UDP connection */ 
+  if ((netfd = open(udp_device, O_RDWR)) < 0) 
+  {
+    fprintf(stderr,"Error opening UDP connection\n");
+    return -1;
+  }               
+                                
+  /* Configure UDP connection */ 
+  udpopt.nwuo_flags = NWUO_COPY | NWUO_LP_SET | NWUO_EN_LOC | NWUO_DI_BROAD 
+                   | NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL | NWUO_DI_IPOPT;
+
+  udpopt.nwuo_locport = (udpport_t) htons(port);
+	                        
+  if ((ioctl(netfd, NWIOSUDPOPT, &udpopt))<0) 
+  {
+    fprintf(stderr,"Error configuring the connection\n");
+    close(netfd);
+    return -1;
+  }               
+	                        
+  /* Get conf options */
+  if ((ioctl(netfd, NWIOGUDPOPT, &udpopt))<0) 
+  {
+    fprintf(stderr,"Error getting the conf\n");
+    close(netfd);
+    return -1;
+  }               
+
+  return netfd;
+}
+
+int main(int argc,char *argv[]) {
+  int fd;
+  ssize_t data_read;
+  udp_buffer_t buffer;
+  ipaddr_t tmp_addr;
+  udpport_t tmp_port;
+  int ret;
+  fd_set fds_read;
+
+  if ((fd = udp_conf(PORT)) < 0) {
+  	fprintf(stderr, "Error configuring UDP connection\n");
+    	exit(-1);	
+  }
+  printf("Waiting for messages on port: %ld\n", PORT);
+  fflush(stdout);
+  /* Initialize fd_set */
+  FD_ZERO(&fds_read);
+  FD_SET(fd, &fds_read);
+
+  while (1) 
+  {
+    /* Wait for data available to be read (no timeout) */
+    ret = select(4, &fds_read, NULL, NULL, NULL);
+    if (ret < 0) {
+    	fprintf(stderr, "Error on select: %d", errno);
+    	exit(-1);
+    }
+    if (!FD_ISSET(fd, &fds_read)) {
+    	printf("Error: network fd is not ready (?)\n");
+    	exit(-1);
+    }
+    printf("Ready to receive...\n");
+    /* Read received data */
+    data_read = read(fd, &buffer, sizeof(udp_buffer_t));
+    printf("Received data: %s\n", buffer.data);
+                                
+    /* Can exit if the received string == exit */
+    if (!strcmp(buffer.data,"exit")) 
+      break; 
+
+    /* Send data back, swap addresses */
+    tmp_addr = buffer.header.uih_src_addr;
+    buffer.header.uih_src_addr = buffer.header.uih_dst_addr;
+    buffer.header.uih_dst_addr = tmp_addr;
+  
+    /* Swap ports */
+    tmp_port = buffer.header.uih_src_port;
+    buffer.header.uih_src_port = buffer.header.uih_dst_port;
+    buffer.header.uih_dst_port = tmp_port;
+  
+    /* Write the same back  */
+    write(fd, &buffer, data_read);             
+  }               
+
+  close(fd);
+}                       
Index: /trunk/minix/test/select/test05_cli.c
===================================================================
--- /trunk/minix/test/select/test05_cli.c	(revision 9)
+++ /trunk/minix/test/select/test05_cli.c	(revision 9)
@@ -0,0 +1,165 @@
+/*
+ * Test name: test05_cli.c
+ *
+ * Objective: Test a impatient UDP client with timeout and incoming data from
+ * network and terminal.
+ *
+ * Description: Implements a echo client using the UDP protocol. It is 
+ * based on test04_cli, but the difference is that it uses timeout and waits
+ * for data both from terminal (stdin) and network connection.
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/asynchio.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <net/netlib.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/udp_io.h>
+#include <net/hton.h>
+
+#define PORT 6000L
+
+/* Type for received data */
+typedef struct
+{
+  udp_io_hdr_t header;
+  char data[1024];
+} udp_buffer_t;
+
+int udp_conf(char *host, long port, udp_io_hdr_t *header)
+{
+  /* configures UDP connection */
+  char *udp_device;
+  struct hostent *hp;
+  int netfd;
+  nwio_udpopt_t udpopt;
+  ipaddr_t dirhost;
+  int result;
+  
+  /* get host address */
+  if ((hp = gethostbyname(host)) == (struct hostent*) NULL) 
+  {
+    fprintf(stderr,"Unknown host\n");
+    return(-1);
+  }
+  memcpy((char *)&dirhost, (char *)hp->h_addr, hp->h_length);
+  
+  /* Get UDP device */
+  if (( udp_device = getenv("UDP_DEVICE") ) == NULL) 
+    udp_device = UDP_DEVICE;
+  
+  /* Get UDP connection */ 
+  if ((netfd = open(udp_device, O_RDWR)) < 0) 
+  {
+    fprintf(stderr,"Error opening UDP device\n");
+    return -1;
+  }
+  
+  /* Configure UDP connection */
+  udpopt.nwuo_flags = NWUO_COPY | NWUO_LP_SEL | NWUO_EN_LOC | NWUO_DI_BROAD 
+                   | NWUO_RP_SET | NWUO_RA_SET | NWUO_RWDATALL | NWUO_DI_IPOPT;
+  udpopt.nwuo_remaddr = dirhost;
+  udpopt.nwuo_remport = (udpport_t) htons(port);
+  
+  if ((result = ioctl(netfd, NWIOSUDPOPT, &udpopt) ) <0) 
+  {
+    fprintf(stderr, "Error establishing communication\n");
+    printf("Error:  %d\n",result);
+    close(netfd);
+    return -1;
+  }
+  
+  /* Get configuration for UDP comm */ 
+  if ((result = ioctl(netfd, NWIOGUDPOPT, &udpopt) ) < 0) 
+  {
+    fprintf(stderr,"Error getting configuration\n");
+    printf("Error: %d\n", result);
+    close(netfd);
+    return -1;
+  }
+
+  header->uih_src_addr = udpopt.nwuo_locaddr;
+  header->uih_dst_addr = udpopt.nwuo_remaddr;
+  header->uih_src_port = udpopt.nwuo_locport;
+  header->uih_dst_port = udpopt.nwuo_remport;
+ 
+  return netfd;
+}
+
+int main(int argc,char *argv[]) {
+  int fd;
+  ssize_t data_read;
+  udp_buffer_t buffer_send, buffer_rec;
+  fd_set fds_read;
+  int ret;
+  struct timeval timeout;
+
+  /* Check parameters */
+  if (argc !=2) {
+    fprintf(stderr,"Usage: %s host\n", argv[0]);
+    exit(-1);
+  }
+
+  if ((fd = udp_conf(argv[1], PORT, &buffer_send.header) ) < 0) 
+    exit(-1);	
+
+  while (1) 
+  {
+
+    /* init fd_set */
+    FD_ZERO(&fds_read);
+    FD_SET(0, &fds_read);
+    FD_SET(fd, &fds_read); 
+
+    /* set timeval */
+    timeout.tv_sec = 5;
+    timeout.tv_usec = 0;
+    printf("Send data: ");
+    fflush(stdout);
+    /* Wait until it is possible to write with select */
+    ret = select(4, &fds_read, NULL, NULL, &timeout);
+    if (ret < 0) {
+    	fprintf(stderr, "Error on select waiting for read: %d\n", errno);
+    	exit(-1);
+    }
+    if (ret == 0) {
+    	printf("\nClient says: Hey! I want to send data!!\n");
+    	fflush(stdout);
+    	continue;
+    }
+    /* if got message from server */
+    if (FD_ISSET(fd, &fds_read)) {
+    	data_read = read(fd, &buffer_rec, sizeof(udp_buffer_t));
+    	printf("Server says: %s\n\n", buffer_rec.data);
+    	fflush(stdout);
+    }
+    /* if got data from terminal */
+    if (FD_ISSET(0, &fds_read)) {
+    	/* Get a string and send it */
+    	gets(buffer_send.data);
+    	write(fd, &buffer_send, sizeof(udp_buffer_t));
+
+    	/* If data sent is exit then break */
+    	if (!strcmp(buffer_send.data,"exit")) 
+      		break;
+    	/* Get server response */
+    	data_read = read(fd, &buffer_rec, sizeof(udp_buffer_t));
+    	printf("Received: %s\n\n", buffer_rec.data);
+    	fflush(stdout);
+    } 
+  }
+  
+  /* Close UDP communication */
+  close(fd);
+}
Index: /trunk/minix/test/select/test05_srv.c
===================================================================
--- /trunk/minix/test/select/test05_srv.c	(revision 9)
+++ /trunk/minix/test/select/test05_srv.c	(revision 9)
@@ -0,0 +1,196 @@
+/*
+ * Test name: test05_srv.c
+ *
+ * Objective: Test an impatient UDP server with timeouts  
+ *
+ * Description: Implements an echo server using the UDP protocol. It is 
+ * based on test04_srv, but it has a timeout value. 
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/asynchio.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <net/netlib.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_hdr.h>
+#include <net/gen/udp_io.h>
+#include <net/hton.h>
+
+#define PORT 6000L
+
+/* type for received data */
+typedef struct 
+{
+  udp_io_hdr_t header;
+  char data[1024];
+} udp_buffer_t;
+
+int udp_conf(long port) {
+
+  char *udp_device;
+  int netfd;
+  nwio_udpopt_t udpopt;
+                            
+  /* Get default UDP device */
+  if ((udp_device = getenv("UDP_DEVICE")) == NULL) 
+    udp_device = UDP_DEVICE;
+                                
+  /* Open UDP connection */ 
+  if ((netfd = open(udp_device, O_RDWR)) < 0) 
+  {
+    fprintf(stderr,"Error opening UDP connection\n");
+    return -1;
+  }               
+                                
+  /* Configure UDP connection */ 
+  udpopt.nwuo_flags = NWUO_COPY | NWUO_LP_SET | NWUO_EN_LOC | NWUO_DI_BROAD 
+                   | NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL | NWUO_DI_IPOPT;
+
+  udpopt.nwuo_locport = (udpport_t) htons(port);
+	                        
+  if ((ioctl(netfd, NWIOSUDPOPT, &udpopt))<0) 
+  {
+    fprintf(stderr,"Error configuring the connection\n");
+    close(netfd);
+    return -1;
+  }               
+	                        
+  /* Get conf options */
+  if ((ioctl(netfd, NWIOGUDPOPT, &udpopt))<0) 
+  {
+    fprintf(stderr,"Error getting the conf\n");
+    close(netfd);
+    return -1;
+  }               
+
+  return netfd;
+}
+
+int main(int argc,char *argv[]) {
+  int fd;
+  ssize_t data_read;
+  udp_buffer_t buffer;
+  ipaddr_t tmp_addr;
+  udpport_t tmp_port;
+  int ret;
+  fd_set fds_read;
+  struct timeval timeout;
+  ipaddr_t client_addr, this_addr;
+  udpport_t client_port; 
+
+  if ((fd = udp_conf(PORT)) < 0) {
+  	fprintf(stderr, "Error configuring UDP connection\n");
+    	exit(-1);	
+  }
+  printf("Waiting for messages on port: %ld\n", PORT);
+  fflush(stdout);
+
+  /* get a first message so we know who is the client and we can harass it
+     afterwards */
+
+  /* Initialize fd_set */
+  FD_ZERO(&fds_read);
+  FD_SET(fd, &fds_read);
+  /* Set timeout structure */
+  timeout.tv_sec = 3;
+  timeout.tv_usec = 0;
+  ret = select(4, &fds_read, NULL, NULL, NULL);
+
+  if (ret < 0) {
+  	fprintf(stderr, "Error in select\n");
+  	exit(-1);
+  }
+  if (!FD_ISSET(fd, &fds_read)) {
+  	fprintf(stderr, "Error: Should be receiving some data from network(?)\n");
+  	exit(-1);
+  }
+  printf("Ready to receive...\n");
+  /* Read received data */
+  data_read = read(fd, &buffer, sizeof(udp_buffer_t));
+  printf("Received data: %s\n", buffer.data);
+                                
+  /* Can exit if the received string == exit */
+  if (!strcmp(buffer.data,"exit")) 
+      	exit(0); 
+
+  /* Send data back, swap addresses */
+  tmp_addr = buffer.header.uih_src_addr;
+  buffer.header.uih_src_addr = buffer.header.uih_dst_addr;
+  buffer.header.uih_dst_addr = tmp_addr;
+  /* save address of both ends */
+  client_addr = tmp_addr;
+  this_addr = buffer.header.uih_src_addr;  
+
+  /* Swap ports */
+  tmp_port = buffer.header.uih_src_port;
+  buffer.header.uih_src_port = buffer.header.uih_dst_port;
+  buffer.header.uih_dst_port = tmp_port;
+  /* save client port */
+  client_port = tmp_port;
+
+  /* Write the same back  */
+  write(fd, &buffer, data_read);             
+
+  while (1) 
+  {
+
+    /* Initialize fd_set */
+    FD_ZERO(&fds_read);
+    FD_SET(fd, &fds_read);
+    /* Set timeout structure */
+    timeout.tv_sec = 3;
+    timeout.tv_usec = 0;
+    /* Wait for data available to be read (timeout) */
+    ret = select(4, &fds_read, NULL, NULL, &timeout);
+    if (ret < 0) {
+    	fprintf(stderr, "Error on select: %d", errno);
+    	exit(-1);
+    }
+    /* if timeout */
+    if (ret == 0) {
+    	/* Send angry msg to client asking for more */
+     	printf("Tired of waiting, send client an angry message\n");
+     	buffer.header.uih_src_addr = this_addr;
+     	buffer.header.uih_dst_addr = client_addr;
+     	buffer.header.uih_src_port = PORT;
+     	buffer.header.uih_dst_port = client_port;
+    	strcpy(buffer.data, "Hey! I want to receive some data!\n");
+    	write(fd, &buffer, sizeof(udp_buffer_t));
+    }
+    /* If receive data from network */
+    if (FD_ISSET(fd, &fds_read)) {
+	printf("Ready to receive...\n");
+    	/* Read received data */
+    	data_read = read(fd, &buffer, sizeof(udp_buffer_t));
+    	printf("Received data: %s\n", buffer.data);
+                                
+    	/* Can exit if the received string == exit */
+    	if (!strcmp(buffer.data,"exit")) 
+      		break; 
+
+    	/* Send data back, swap addresses */
+    	tmp_addr = buffer.header.uih_src_addr;
+    	buffer.header.uih_src_addr = buffer.header.uih_dst_addr;
+    	buffer.header.uih_dst_addr = tmp_addr;
+  
+    	/* Swap ports */
+    	tmp_port = buffer.header.uih_src_port;
+    	buffer.header.uih_src_port = buffer.header.uih_dst_port;
+    	buffer.header.uih_dst_port = tmp_port;
+  
+    	/* Write the same back  */
+    	write(fd, &buffer, data_read);             
+    }
+  }               
+  close(fd);
+}                       
Index: /trunk/minix/test/select/test06_cli.c
===================================================================
--- /trunk/minix/test/select/test06_cli.c	(revision 9)
+++ /trunk/minix/test/select/test06_cli.c	(revision 9)
@@ -0,0 +1,162 @@
+/*
+ * Test name: test06_cli.c
+ *
+ * Objective: Test a simple TCP client
+ *
+ * Description: Implements a simple echo client using the TCP protocol. First
+ * it waits until it is possible to write (which is always).
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <net/netlib.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/hton.h>
+
+#define PORT 6060L
+
+int tcp_connect(char *host, long port)
+{
+  /* creates a tcp connection with specified host and port */
+  char *tcp_device;
+  struct hostent *hp;
+  int netfd;
+  nwio_tcpcl_t tcpcopt;
+  nwio_tcpconf_t tcpconf;
+  ipaddr_t dirhost;
+  int tries;
+  int result;
+  
+  /* get host address */
+  if ((hp = gethostbyname(host)) == (struct hostent*) NULL) 
+  {
+    fprintf(stderr,"Unknown host\n");
+    return(-1);
+  }
+  memcpy((char *)&dirhost, (char *)hp->h_addr, hp->h_length);
+  
+  /* Get default TCP device */
+  if (( tcp_device = getenv("TCP_DEVICE") ) == NULL) 
+    tcp_device = TCP_DEVICE;
+  
+  /* Establish TCP connection */ 
+  if ((netfd = open(tcp_device, O_RDWR)) < 0) 
+  {
+    fprintf(stderr,"Error opening TCP device\n");
+    return -1;
+  }
+  
+  /* Configure TCP connection */
+  tcpconf.nwtc_flags=NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
+  tcpconf.nwtc_remaddr = dirhost;
+  tcpconf.nwtc_remport = (tcpport_t) htons(port);
+  
+  if ((result = ioctl(netfd, NWIOSTCPCONF, &tcpconf) ) <0) 
+  {
+    fprintf(stderr, "Error establishing communication\n");
+    printf("Error:  %d\n",result);
+    close(netfd);
+    return -1;
+  }
+  
+  /* Get configuration for TCP comm */ 
+  if ((result = ioctl(netfd, NWIOGTCPCONF, &tcpconf) ) < 0) 
+  {
+    fprintf(stderr,"Error getting configuration\n");
+    printf("Error: %d\n", result);
+    close(netfd);
+    return -1;
+  }
+
+  /* Establish connection */
+  tcpcopt.nwtcl_flags = 0;
+  tries = 0; 
+  while (tries < 10) {
+  	if ( (result = ioctl(netfd, NWIOTCPCONN, &tcpcopt)) < 0 ) {
+  		if (errno != EAGAIN)
+  		{
+  			fprintf(stderr, "Server is not listening\n");
+  			close(netfd);
+  			return(-1);
+  		}
+  		fprintf(stderr, "Unable to connect\n");
+  		sleep(1);
+  		tries++;
+  	}
+  	else
+  		break;	/* Connection */
+ }
+ /* Check result value */
+ if (result < 0) {
+ 	fprintf(stderr, "Error connecting\n");
+ 	fprintf(stderr, "Error: %d\n", result);
+ 	printf("Number of tries: %d\n", tries);
+ 	printf("Error: %d\n", errno);
+ 	close(netfd);
+ 	return -1;
+ }
+ return netfd;
+}
+
+int main(int argc,char *argv[]) {
+  int fd;
+  ssize_t data_read;
+  char send_buf[1024];
+  char recv_buf[1024];
+  fd_set fds_write;
+  int ret;
+
+  /* Check parameters */
+  if (argc !=2) {
+    fprintf(stderr,"Usage: %s host\n", argv[0]);
+    exit(-1);
+  }
+
+  if ((fd = tcp_connect(argv[1], PORT) ) < 0) 
+    exit(-1);	
+  printf("Connected to server\n");
+  /* init fd_set */
+  FD_ZERO(&fds_write);
+  FD_SET(fd, &fds_write);
+  while (1) 
+  {
+    /* Wait until it is possible to write with select */
+    ret = select(4, NULL, &fds_write, NULL, NULL);
+    if (ret < 0) {
+    	fprintf(stderr, "Error on select waiting for write: %d\n", errno);
+    	exit(-1);
+    }
+    if (!FD_ISSET(fd, &fds_write)) {
+    	fprintf(stderr, "Error: The net connection is not ready for writing (?)\n"); 
+    	exit(-1);
+    }
+    
+    /* Get a string and send it */
+    printf("Ready to write...\n");
+    printf("Send data: ");
+    gets(send_buf);
+    write(fd, &send_buf, strlen(send_buf)+1);
+  
+    /* If data sent is exit then break */
+    if (!strcmp(send_buf,"exit")) 
+      break;
+  		
+    /* Get server response */
+    data_read = read(fd, &recv_buf, 1024);
+    printf("Received: %s\n\n", recv_buf);
+  }
+  
+  /* Close TCP communication */
+  close(fd);
+}
Index: /trunk/minix/test/select/test06_srv.c
===================================================================
--- /trunk/minix/test/select/test06_srv.c	(revision 9)
+++ /trunk/minix/test/select/test06_srv.c	(revision 9)
@@ -0,0 +1,127 @@
+/*
+ * Test name: test06_srv.c
+ *
+ * Objective: Test a simple TCP server
+ *
+ * Description: Implements a simple echo server using the TCP protocol. Instead
+ * of blocking on read(), it performs a select call first blocking there 
+ * until there is data to be read
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <net/netlib.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/hton.h>
+#include <net/gen/inet.h>
+
+#define PORT 6060L
+
+int listen(long port) {
+
+  char *tcp_device;
+  int netfd;
+  nwio_tcpconf_t tcpconf;
+  nwio_tcpcl_t tcplistenopt;
+                            
+  /* Get default UDP device */
+  if ((tcp_device = getenv("TCP_DEVICE")) == NULL) 
+    tcp_device = TCP_DEVICE;
+                                
+  /* Open TCP connection */ 
+  if ((netfd = open(tcp_device, O_RDWR)) < 0) 
+  {
+    fprintf(stderr,"Error opening TCP connection\n");
+    return -1;
+  }               
+                                
+  /* Configure TCP connection */ 
+  tcpconf.nwtc_flags = NWTC_LP_SET | NWTC_UNSET_RA | NWTC_UNSET_RP;
+  tcpconf.nwtc_locport = (tcpport_t) htons(port);
+	                        
+  if ((ioctl(netfd, NWIOSTCPCONF, &tcpconf))<0) 
+  {
+    fprintf(stderr,"Error configuring the connection\n");
+    close(netfd);
+    return -1;
+  }               
+
+  /* Get communication options */
+  if ((ioctl(netfd, NWIOGTCPCONF, &tcpconf)) < 0) {
+    fprintf(stderr, "Error getting configuration\n");
+    close(netfd);
+    return -1;
+   }                
+	                        
+  /* Set conf options */
+  tcplistenopt.nwtcl_flags = 0;
+  printf("Waiting for connections...\n");
+  while ((ioctl(netfd, NWIOTCPLISTEN, &tcplistenopt)) == -1) 
+  {
+    if (errno != EAGAIN)
+    {
+    	fprintf(stderr,"Unable to listen for connections\n");
+    	close(netfd);
+    }
+    sleep(-1);
+  }               
+  return netfd;
+}
+
+int main(int argc,char *argv[]) {
+  int fd;
+  ssize_t data_read;
+  char buffer[1024];
+  int ret;
+  fd_set fds_read;
+
+  if ((fd = listen(PORT)) < 0) {
+    	exit(-1);	
+  }
+  printf("Waiting for messages on port: %ld\n", PORT);
+  fflush(stdout);
+  /* Initialize fd_set */
+  FD_ZERO(&fds_read);
+  FD_SET(fd, &fds_read);
+
+  while (1) 
+  {
+    /* Wait for data available to be read (no timeout) */
+   
+    ret = select(4, &fds_read, NULL, NULL, NULL);
+    if (ret < 0) {
+    	fprintf(stderr, "Error on select: %d\n", errno);
+    	exit(-1);
+    }
+    if (!FD_ISSET(fd, &fds_read)) {
+    	printf("Error: network fd is not ready (?)\n");
+    	exit(-1);
+    }
+    
+    printf("Ready to receive...\n");
+    /* Read received data */
+    data_read = read(fd, &buffer, 1024);
+    printf("Received data: %s\n", buffer);
+                                
+    /* Can exit if the received string == exit */
+    if (!strcmp(buffer,"exit")) 
+      break; 
+
+    /* Write the same back  */
+    write(fd, &buffer, data_read);             
+  }               
+  printf("Connection finished\n");
+  close(fd);
+}                       
Index: /trunk/minix/test/select/test07_cli.c
===================================================================
--- /trunk/minix/test/select/test07_cli.c	(revision 9)
+++ /trunk/minix/test/select/test07_cli.c	(revision 9)
@@ -0,0 +1,182 @@
+/*
+ * Test name: test07_cli.c
+ *
+ * Objective: Test an impatient TCP client with timeout which waits input both 
+ * from the terminal and from the network connection.
+ *
+ * Description: Implements a echo client using the TCP protocol with a timeout
+ * value. It waites for data on both the terminal and the network connection and
+ * prints an angry message asking for more data if there is a timeout.
+ * 
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/asynchio.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <net/netlib.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/hton.h>
+
+#define PORT 6060L
+
+int tcp_connect(char *host, long port)
+{
+  /* creates a tcp connection with specified host and port */
+  char *tcp_device;
+  struct hostent *hp;
+  int netfd;
+  nwio_tcpcl_t tcpcopt;
+  nwio_tcpconf_t tcpconf;
+  ipaddr_t dirhost;
+  int tries;
+  int result;
+  
+  /* get host address */
+  if ((hp = gethostbyname(host)) == (struct hostent*) NULL) 
+  {
+    fprintf(stderr,"Unknown host\n");
+    return(-1);
+  }
+  memcpy((char *)&dirhost, (char *)hp->h_addr, hp->h_length);
+  
+  /* Get default TCP device */
+  if (( tcp_device = getenv("TCP_DEVICE") ) == NULL) 
+    tcp_device = TCP_DEVICE;
+  
+  /* Establish TCP connection */ 
+  if ((netfd = open(tcp_device, O_RDWR)) < 0) 
+  {
+    fprintf(stderr,"Error opening TCP device\n");
+    return -1;
+  }
+  
+  /* Configure TCP connection */
+  tcpconf.nwtc_flags=NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
+  tcpconf.nwtc_remaddr = dirhost;
+  tcpconf.nwtc_remport = (tcpport_t) htons(port);
+  
+  if ((result = ioctl(netfd, NWIOSTCPCONF, &tcpconf) ) <0) 
+  {
+    fprintf(stderr, "Error establishing communication\n");
+    printf("Error:  %d\n",result);
+    close(netfd);
+    return -1;
+  }
+  
+  /* Get configuration for TCP comm */ 
+  if ((result = ioctl(netfd, NWIOGTCPCONF, &tcpconf) ) < 0) 
+  {
+    fprintf(stderr,"Error getting configuration\n");
+    printf("Error: %d\n", result);
+    close(netfd);
+    return -1;
+  }
+
+  /* Establish connection */
+  tcpcopt.nwtcl_flags = 0;
+  tries = 0; 
+  while (tries < 10) {
+  	if ( (result = ioctl(netfd, NWIOTCPCONN, &tcpcopt)) < 0 ) {
+  		if (errno != EAGAIN)
+  		{
+  			fprintf(stderr, "Server is not listening\n");
+  			close(netfd);
+  			return(-1);
+  		}
+  		fprintf(stderr, "Unable to connect\n");
+  		sleep(1);
+  		tries++;
+  	}
+  	else
+  		break;	/* Connection */
+ }
+ /* Check result value */
+ if (result < 0) {
+ 	fprintf(stderr, "Error connecting\n");
+ 	fprintf(stderr, "Error: %d\n", result);
+ 	printf("Number of tries: %d\n", tries);
+ 	printf("Error: %d\n", errno);
+ 	close(netfd);
+ 	return -1;
+ }
+ return netfd;
+}
+
+int main(int argc,char *argv[]) {
+  int fd;
+  ssize_t data_read;
+  char send_buf[1024];
+  char recv_buf[1024];
+  fd_set fds_read;
+  int ret;
+  struct timeval timeout;
+
+  /* Check parameters */
+  if (argc !=2) {
+    fprintf(stderr,"Usage: %s host\n", argv[0]);
+    exit(-1);
+  }
+
+  if ((fd = tcp_connect(argv[1], PORT) ) < 0) 
+    exit(-1);	
+  printf("Connected to server\n");
+
+  while (1) 
+  {
+
+    /* init fd_set */
+    FD_ZERO(&fds_read);
+    FD_SET(0, &fds_read); /* stdin */
+    FD_SET(fd, &fds_read);
+    /* set timeout */
+    timeout.tv_sec = 3;
+    timeout.tv_usec = 0; 
+
+    printf("Send data: ");
+    fflush(stdout);
+    /* Wait until it is possible to read with select */
+    ret = select(4, &fds_read, NULL, NULL, &timeout);
+    if (ret < 0) {
+    	fprintf(stderr, "Error on select waiting for write: %d\n", errno);
+    	exit(-1);
+    }
+    /* timeout */
+    if (ret == 0) {
+    	printf("\nClient says: Hey! I want to send some data!!\n");
+    	continue;
+    }
+    /* handle data from network */
+    if (FD_ISSET(fd, &fds_read)) {
+    	data_read = read(fd, &recv_buf, 1024);
+    	printf("Server says: %s\n\n", recv_buf);	
+    }
+    /* handle data from terminal */ 
+    if (FD_ISSET(0, &fds_read)) {
+    	/* Get a string and send it */
+    	gets(send_buf);
+    	write(fd, &send_buf, strlen(send_buf)+1);
+  
+    	/* If data sent is exit then break */
+    	if (!strcmp(send_buf,"exit")) 
+	      	break;
+  		
+    	/* Get server response */
+    	data_read = read(fd, &recv_buf, 1024);
+    	printf("Received: %s\n\n", recv_buf);
+    }
+  }
+  
+  /* Close TCP communication */
+  close(fd);
+}
Index: /trunk/minix/test/select/test07_srv.c
===================================================================
--- /trunk/minix/test/select/test07_srv.c	(revision 9)
+++ /trunk/minix/test/select/test07_srv.c	(revision 9)
@@ -0,0 +1,137 @@
+/*
+ * Test name: test07_srv.c
+ *
+ * Objective: Test an impatient TCP server with a timeout.
+ *
+ * Description: Implements an echo server using the TCP protocol. It is
+ * based on test06_srv.c but has a timeout for receiving data from a client
+ * and if the time is up it sends an angry message to the client requesting
+ * for more information.
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/wait.h>
+#include <sys/asynchio.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <net/netlib.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/hton.h>
+#include <net/gen/inet.h>
+
+#define PORT 6060L
+
+int listen(long port) {
+
+  char *tcp_device;
+  int netfd;
+  nwio_tcpconf_t tcpconf;
+  nwio_tcpcl_t tcplistenopt;
+                            
+  /* Get default UDP device */
+  if ((tcp_device = getenv("TCP_DEVICE")) == NULL) 
+    tcp_device = TCP_DEVICE;
+                                
+  /* Open TCP connection */ 
+  if ((netfd = open(tcp_device, O_RDWR)) < 0) 
+  {
+    fprintf(stderr,"Error opening TCP connection\n");
+    return -1;
+  }               
+                                
+  /* Configure TCP connection */ 
+  tcpconf.nwtc_flags = NWTC_LP_SET | NWTC_UNSET_RA | NWTC_UNSET_RP;
+  tcpconf.nwtc_locport = (tcpport_t) htons(port);
+	                        
+  if ((ioctl(netfd, NWIOSTCPCONF, &tcpconf))<0) 
+  {
+    fprintf(stderr,"Error configuring the connection\n");
+    close(netfd);
+    return -1;
+  }               
+
+  /* Get communication options */
+  if ((ioctl(netfd, NWIOGTCPCONF, &tcpconf)) < 0) {
+    fprintf(stderr, "Error getting configuration\n");
+    close(netfd);
+    return -1;
+   }                
+	                        
+  /* Set conf options */
+  tcplistenopt.nwtcl_flags = 0;
+  printf("Waiting for connections...\n");
+  while ((ioctl(netfd, NWIOTCPLISTEN, &tcplistenopt)) == -1) 
+  {
+    if (errno != EAGAIN)
+    {
+    	fprintf(stderr,"Unable to listen for connections\n");
+    	close(netfd);
+    }
+    sleep(-1);
+  }               
+  return netfd;
+}
+
+int main(int argc,char *argv[]) {
+  int fd;
+  ssize_t data_read;
+  char buffer[1024];
+  int ret;
+  fd_set fds_read;
+  struct timeval timeout;
+
+  if ((fd = listen(PORT)) < 0) {
+    	exit(-1);	
+  }
+  printf("Waiting for messages on port: %ld\n", PORT);
+  fflush(stdout);
+  while (1) 
+  {
+
+    /* Initialize fd_set */
+    FD_ZERO(&fds_read);
+    FD_SET(fd, &fds_read);
+    /* set timeout */
+    timeout.tv_sec = 3;
+    timeout.tv_usec = 0;
+    /* Wait for data available to be read (no timeout) */
+    ret = select(4, &fds_read, NULL, NULL, &timeout);
+    if (ret < 0) {
+    	fprintf(stderr, "Error on select: %d\n", errno);
+    	exit(-1);
+    }
+    /* timeout */
+    if (ret == 0) {
+    	strcpy(buffer, "I want to get some data!!\n");
+    	write(fd, &buffer, 1024);
+        continue;
+    }
+
+    /* data received from client */
+    if (FD_ISSET(fd, &fds_read)) {
+	printf("Ready to receive...\n");
+    	/* Read received data */
+    	data_read = read(fd, &buffer, 1024);
+    	printf("Received data: %s\n", buffer);
+                                
+    	/* Can exit if the received string == exit */
+    	if (!strcmp(buffer,"exit")) 
+      	   break; 
+
+    	/* Write the same back  */
+    	write(fd, &buffer, data_read);             
+     }               
+  }                       
+  printf("Connection finished\n");
+  close(fd);
+}
Index: /trunk/minix/test/select/test08_cli.c
===================================================================
--- /trunk/minix/test/select/test08_cli.c	(revision 9)
+++ /trunk/minix/test/select/test08_cli.c	(revision 9)
@@ -0,0 +1,183 @@
+/*
+ * Test name: test08_cli.c
+ *
+ * Objective: Test select on urgent data. TCP client. 
+ *
+ * Description: It is based on test06_cli but sends urgent data. 
+ * 
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <net/netlib.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/hton.h>
+
+#define PORT 6060L
+
+int tcp_connect(char *host, long port)
+{
+  /* creates a tcp connection with specified host and port */
+  char *tcp_device;
+  struct hostent *hp;
+  int netfd;
+  nwio_tcpcl_t tcpcl;
+  nwio_tcpopt_t tcpopt;
+  nwio_tcpconf_t tcpconf;
+  ipaddr_t dirhost;
+  int tries;
+  int result;
+  
+  /* get host address */
+  if ((hp = gethostbyname(host)) == (struct hostent*) NULL) 
+  {
+    fprintf(stderr,"Unknown host\n");
+    return(-1);
+  }
+  memcpy((char *)&dirhost, (char *)hp->h_addr, hp->h_length);
+  
+  /* Get default TCP device */
+  if (( tcp_device = getenv("TCP_DEVICE") ) == NULL) 
+    tcp_device = TCP_DEVICE;
+  
+  /* Establish TCP connection */ 
+  if ((netfd = open(tcp_device, O_RDWR)) < 0) 
+  {
+    fprintf(stderr,"Error opening TCP device\n");
+    return -1;
+  }
+  
+  /* Configure TCP connection */
+  tcpconf.nwtc_flags=NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
+  tcpconf.nwtc_remaddr = dirhost;
+  tcpconf.nwtc_remport = (tcpport_t) htons(port);
+  
+  if ((result = ioctl(netfd, NWIOSTCPCONF, &tcpconf) ) <0) 
+  {
+    fprintf(stderr, "Error establishing communication\n");
+    printf("Error:  %d\n",result);
+    close(netfd);
+    return -1;
+  }
+  
+  /* Get configuration for TCP comm */ 
+  if ((result = ioctl(netfd, NWIOGTCPCONF, &tcpconf) ) < 0) 
+  {
+    fprintf(stderr,"Error getting configuration\n");
+    printf("Error: %d\n", result);
+    close(netfd);
+    return -1;
+  }
+
+  /* Establish connection options (send URG data) */
+  tcpopt.nwto_flags = NWTO_SND_URG_MASK;
+
+  /* Set options for TCP comm */ 
+  if ((result = ioctl(netfd, NWIOSTCPOPT, &tcpopt) ) < 0) 
+  {
+    fprintf(stderr,"Error getting configuration\n");
+    printf("Error: %d\n", result);
+    close(netfd);
+    return -1;
+  }
+  
+  /* Get configuration for TCP comm */ 
+  if ((result = ioctl(netfd, NWIOGTCPOPT, &tcpopt) ) < 0) 
+  {
+    fprintf(stderr,"Error getting options\n");
+    printf("Error: %d\n", result);
+    close(netfd);
+    return -1;
+  }
+
+  tcpcl.nwtcl_flags = 0;
+  tries = 0; 
+  while (tries < 10) {
+  	if ( (result = ioctl(netfd, NWIOTCPCONN, &tcpcl)) < 0 ) {
+  		if (errno != EAGAIN)
+  		{
+  			fprintf(stderr, "Server is not listening\n");
+  			close(netfd);
+  			return(-1);
+  		}
+  		fprintf(stderr, "Unable to connect\n");
+  		sleep(1);
+  		tries++;
+  	}
+  	else
+  		break;	/* Connection */
+ }
+ /* Check result value */
+ if (result < 0) {
+ 	fprintf(stderr, "Error connecting\n");
+ 	fprintf(stderr, "Error: %d\n", result);
+ 	printf("Number of tries: %d\n", tries);
+ 	printf("Error: %d\n", errno);
+ 	close(netfd);
+ 	return -1;
+ }
+ return netfd;
+}
+
+int main(int argc,char *argv[]) {
+  int fd;
+  ssize_t data_read;
+  char send_buf[1024];
+  char recv_buf[1024];
+  fd_set fds_write;
+  int ret;
+
+  /* Check parameters */
+  if (argc !=2) {
+    fprintf(stderr,"Usage: %s host\n", argv[0]);
+    exit(-1);
+  }
+
+  if ((fd = tcp_connect(argv[1], PORT) ) < 0) 
+    exit(-1);	
+  printf("Connected to server\n");
+  /* init fd_set */
+  FD_ZERO(&fds_write);
+  FD_SET(fd, &fds_write);
+  while (1) 
+  {
+    /* Wait until it is possible to write with select */
+    ret = select(4, NULL, &fds_write, NULL, NULL);
+    if (ret < 0) {
+    	fprintf(stderr, "Error on select waiting for write: %d\n", errno);
+    	exit(-1);
+    }
+    if (!FD_ISSET(fd, &fds_write)) {
+    	fprintf(stderr, "Error: The net connection is not ready for writing (?)\n"); 
+    	exit(-1);
+    }
+    
+    /* Get a string and send it */
+    printf("Ready to write...\n");
+    printf("Send data: ");
+    gets(send_buf);
+    write(fd, &send_buf, strlen(send_buf)+1);
+  
+    /* If data sent is exit then break */
+    if (!strcmp(send_buf,"exit")) 
+      break;
+  		
+    /* Get server response */
+    data_read = read(fd, &recv_buf, 1024);
+    printf("Received: %s\n\n", recv_buf);
+  }
+  
+  /* Close UDP communication */
+  close(fd);
+}
Index: /trunk/minix/test/select/test08_srv.c
===================================================================
--- /trunk/minix/test/select/test08_srv.c	(revision 9)
+++ /trunk/minix/test/select/test08_srv.c	(revision 9)
@@ -0,0 +1,145 @@
+/*
+ * Test name: test08_srv.c
+ *
+ * Objective: Test a simple TCP server waiting for urgent data.
+ *
+ * Description: Implements a echo TCP server as in test06_srv but waits
+ * for urgent data, using select on exception.
+ * 
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <net/netlib.h>
+#include <net/gen/netdb.h>
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/hton.h>
+#include <net/gen/inet.h>
+
+#define PORT 6060L
+
+int listen(long port) {
+
+  char *tcp_device;
+  int netfd;
+  nwio_tcpconf_t tcpconf;
+  nwio_tcpcl_t tcpcl;
+  nwio_tcpopt_t tcpopt;                     
+                            
+  /* Get default UDP device */
+  if ((tcp_device = getenv("TCP_DEVICE")) == NULL) 
+    tcp_device = TCP_DEVICE;
+                                
+  /* Open TCP connection */ 
+  if ((netfd = open(tcp_device, O_RDWR)) < 0) 
+  {
+    fprintf(stderr,"Error opening TCP connection\n");
+    return -1;
+  }               
+                                
+  /* Configure TCP connection */ 
+  tcpconf.nwtc_flags = NWTC_LP_SET | NWTC_UNSET_RA | NWTC_UNSET_RP;
+  tcpconf.nwtc_locport = (tcpport_t) htons(port);
+	                        
+  if ((ioctl(netfd, NWIOSTCPCONF, &tcpconf))<0) 
+  {
+    fprintf(stderr,"Error configuring the connection\n");
+    close(netfd);
+    return -1;
+  }               
+
+  /* Get communication conf*/
+  if ((ioctl(netfd, NWIOGTCPCONF, &tcpconf)) < 0) {
+    fprintf(stderr, "Error getting configuration\n");
+    close(netfd);
+    return -1;
+   }                
+
+   /* Set comm options */
+  tcpopt.nwto_flags = NWTO_RCV_URG;              
+
+  if ((ioctl(netfd, NWIOSTCPOPT, &tcpopt))<0) 
+  {
+    fprintf(stderr,"Error configuring the connection\n");
+    close(netfd);
+    return -1;
+  } 
+	                        
+  /* Get communication opt*/
+  if ((ioctl(netfd, NWIOGTCPOPT, &tcpopt)) < 0) {
+    fprintf(stderr, "Error getting options\n");
+    close(netfd);
+    return -1;
+   }                
+
+  /* Set conn options */
+  tcpcl.nwtcl_flags = 0;
+  printf("Waiting for connections...\n");
+  while ((ioctl(netfd, NWIOTCPLISTEN, &tcpcl)) == -1) 
+  {
+    if (errno != EAGAIN)
+    {
+    	fprintf(stderr,"Unable to listen for connections\n");
+    	close(netfd);
+    }
+    sleep(-1);
+  }               
+  return netfd;
+}
+
+int main(int argc,char *argv[]) {
+  int fd;
+  ssize_t data_read;
+  char buffer[1024];
+  int ret;
+  fd_set fds_excep;
+
+  if ((fd = listen(PORT)) < 0) {
+    	exit(-1);	
+  }
+  printf("Waiting for messages on port: %ld\n", PORT);
+  fflush(stdout);
+  /* Initialize fd_set */
+  FD_ZERO(&fds_excep);
+  FD_SET(fd, &fds_excep);
+
+  while (1) 
+  {
+    /* Wait for data available to be read (no timeout) */
+  	 
+    ret = select(4, NULL, NULL, &fds_excep, NULL);
+    if (ret < 0) {
+    	fprintf(stderr, "Error on select: %d\n", errno);
+    	exit(-1);
+    }
+    if (!FD_ISSET(fd, &fds_excep)) {
+    	printf("Error: no URG data received (?)\n");
+    	exit(-1);
+    }
+    
+    printf("Ready to receive...\n");
+    /* Read received data */
+    data_read = read(fd, &buffer, 1024);
+    printf("Received data: %s\n", buffer);
+                                
+    /* Can exit if the received string == exit */
+    if (!strcmp(buffer,"exit")) 
+      break; 
+
+    /* Write the same back  */
+    write(fd, &buffer, data_read);             
+  }               
+  printf("Connection finished\n");
+  close(fd);
+}                       
Index: /trunk/minix/test/select/test09.c
===================================================================
--- /trunk/minix/test/select/test09.c	(revision 9)
+++ /trunk/minix/test/select/test09.c	(revision 9)
@@ -0,0 +1,62 @@
+/*
+ * Test name: test09.c
+ *
+ * Objetive: The purpose of this test is to make sure that select works
+ * when working with the terminal.
+ *
+ * Description:  This tests wait entry from stdin using select and displays
+ * it again in stdout when it is ready to write (which is always)
+ * 
+ * Jose M. Gomez
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+void main(void) {
+	fd_set fds_read, fds_write;
+	int retval;
+	char data[1024];
+
+	FD_ZERO(&fds_read);
+	FD_ZERO(&fds_write);
+	FD_SET(0, &fds_read);		/* stdin */
+	FD_SET(1, &fds_write);		/* stdout */
+
+	while(1) {
+		printf("Input some data: ");
+		fflush(stdout);
+		retval=select(3, &fds_read, NULL, NULL, NULL); 
+		if (retval < 0) {
+			fprintf(stderr, "Error while executing select\n");
+			exit(-1);
+		}
+		printf("select retval: %d\n", retval);
+		if (!FD_ISSET(0, &fds_read)) {
+			fprintf(stderr, "Error: stdin not ready (?)\n");
+			exit(-1);
+		}
+		printf("gets..\n");
+		gets(data);
+		printf("gets done..\n");
+		if (!strcmp(data, "exit"))
+			exit(0);
+		printf("Try to write it back\n");
+		retval=select(3, NULL, &fds_write, NULL, NULL);
+		if (retval < 0) {
+			fprintf(stderr, "Error while executing select\n");
+			exit(-1);
+		}
+		if (!FD_ISSET(1, &fds_write)) {
+			fprintf(stderr, "Error: stdout not ready (?)\n");
+			exit(-1);
+		}
+		printf("Data: %s\n", data);
+	}
+}
Index: /trunk/minix/test/select/test10.c
===================================================================
--- /trunk/minix/test/select/test10.c	(revision 9)
+++ /trunk/minix/test/select/test10.c	(revision 9)
@@ -0,0 +1,69 @@
+/*
+ * Test name: test10.c
+ *
+ * Objetive: The purpose of this test is to make sure that select works
+ * when working with the terminal with timeouts
+ *
+ * Description:  This tests wait entry from stdin using select and displays
+ * it again in stdout when it is ready to write (which is always). It has
+ * a timeout value as well.
+ * 
+ * Jose M. Gomez
+ */
+
+#include <time.h>
+#include <sys/types.h>
+#include <sys/asynchio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+
+void main(void) {
+	fd_set fds_read, fds_write;
+	int retval;
+	char data[1024];
+	struct timeval timeout;
+
+	while(1) {
+		timeout.tv_sec = 3;
+		timeout.tv_usec = 0;
+		FD_ZERO(&fds_read);
+		FD_ZERO(&fds_write);
+		FD_SET(0, &fds_read);
+		FD_SET(1, &fds_write);
+		printf("Input some data: ");
+		fflush(stdout);
+		retval=select(3, &fds_read, NULL, NULL, &timeout); 
+		if (retval < 0) {
+			fprintf(stderr, "Error while executing select\n");
+			exit(-1);
+		}
+		if (retval == 0) {
+			printf("\n Hey! Feed me some data!\n");
+			fflush(stdout);
+			continue;
+		}
+		if (!FD_ISSET(0, &fds_read)) {
+			fprintf(stderr, "Error: stdin not ready (?)\n");
+			exit(-1);
+		}
+		gets(data);
+		if (!strcmp(data, "exit"))
+			exit(0);
+		printf("Try to write it back\n");
+		retval=select(3, NULL, &fds_write, NULL, NULL);
+		if (retval < 0) {
+			fprintf(stderr, "Error while executing select\n");
+			exit(-1);
+		}
+		if (!FD_ISSET(1, &fds_write)) {
+			fprintf(stderr, "Error: stdout not ready (?)\n");
+			exit(-1);
+		}
+		printf("Data: %s\n", data);
+	}
+}
Index: /trunk/minix/test/select/test11.c
===================================================================
--- /trunk/minix/test/select/test11.c	(revision 9)
+++ /trunk/minix/test/select/test11.c	(revision 9)
@@ -0,0 +1,162 @@
+/*
+ * Test name: test11.c
+ *
+ * Objetive: The purpose of this test is to make sure that select works
+ * with pipes.
+ *
+ * Description:  The select checks are divided in checks on writing for the
+ * parent process, which has the writing end of the pipe, and checks on reading
+ * and exception on the child process, which has the reading end of pipe. So
+ * when the first process is ready to write to the pipe it will request a string
+ * from the terminal and send it through the pipe. If the string is 'exit' then
+ * the pipe is closed. The child process is blocked in a select checking for read
+ * and exception. If there is data to be read then it will perform the read and
+ * prints the read data. If the pipe is closed (user typed 'exit'), the child 
+ * process finishes. 
+ * 
+ * Jose M. Gomez
+ */
+
+#include <time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/asynchio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <signal.h>
+
+void pipehandler(int sig)
+{
+
+}
+
+void do_child(int data_pipe[]) 
+{
+	/* reads from pipe and prints out the data */
+	char data[2048];
+	int retval;	 
+	fd_set fds_read;
+	fd_set fds_exception;	
+	struct timeval timeout;
+
+	signal(SIGPIPE, pipehandler);
+	signal(SIGUSR1, pipehandler);
+
+	/* first, close the write part of the pipe, since it is not needed */
+	close(data_pipe[1]);
+	
+	while(1) {
+		FD_ZERO(&fds_read);
+		FD_ZERO(&fds_exception);
+		FD_SET(data_pipe[0], &fds_read);
+		FD_SET(data_pipe[0], &fds_exception);
+		timeout.tv_sec = 5;
+		timeout.tv_usec = 0;
+		retval = select(data_pipe[0]+1,  &fds_read, NULL, &fds_exception, &timeout);
+		if (retval == -1) {
+			perror("select");
+			fprintf(stderr, "child: Error in select\n");
+			continue;
+		} else printf("child select: %d\n", retval);
+		if (FD_ISSET(data_pipe[0], &fds_exception)) {
+			printf("child: exception fd set. quitting.\n");
+			break;
+		}
+		if (FD_ISSET(data_pipe[0], &fds_read)) {
+			printf("child: read fd set. reading.\n");
+			if ((retval = read(data_pipe[0], data, sizeof(data))) < 0) {
+				perror("read");
+				fprintf(stderr, "child: couldn't read from pipe\n");
+				exit(-1);
+			}
+			if(retval == 0) {
+				fprintf(stderr, "child: eof on pipe\n");
+				break;
+			}
+			data[retval] = '\0';
+			printf("pid %d Pipe reads (%d): %s\n", getpid(), retval, data);
+		} else printf("child: no fd set\n");
+	}
+	
+	/* probably pipe was broken, or got EOF via the pipe. */
+	exit(0);
+}
+
+void do_parent(int data_pipe[]) 
+{
+	char data[1024];
+	int retval;
+	fd_set fds_write;
+
+	signal(SIGPIPE, pipehandler);
+	signal(SIGUSR1, pipehandler);
+
+	/* first, close the read part of pipe, since it is not needed */
+	close(data_pipe[0]);
+
+	/* now enter a loop of read user input, and writing it to the pipe */
+	while (1) {
+		FD_ZERO(&fds_write);
+		FD_SET(data_pipe[1], &fds_write);
+		printf("pid %d Waiting for pipe ready to write...\n", getpid());
+		retval = select(data_pipe[1]+1, NULL, &fds_write, NULL, NULL);
+		if (retval == -1) {
+			perror("select");
+			fprintf(stderr, "Parent: Error in select\n");
+			exit(-1);
+		}		
+
+		printf("Input data: ");
+		if(!gets(data)) {
+			printf("parent: eof; exiting\n");
+			break;
+		}
+		if (!strcmp(data, "exit"))
+			break;
+		if (!FD_ISSET(data_pipe[1], &fds_write)) {
+			fprintf(stderr, "parent: write fd not set?! retrying\n");
+			continue;
+		}
+		retval = write(data_pipe[1], &data, 1024);
+		if (retval == -1) {
+			perror("write");
+			fprintf(stderr, "Error writing on pipe\n");
+			exit(-1);
+		}
+	}
+
+	/* got exit from user */
+	close(data_pipe[1]);	/* close pipe, let child know we're done */
+	wait(&retval);
+	printf("Child exited with status: %d\n", retval);
+	exit(0);
+}
+
+void main(void) {
+	int pipes[2];
+	int retval;
+	int pid;	
+
+	/* create the pipe */
+	retval = pipe(pipes);
+	if (retval == -1) {
+		perror("pipe");
+		fprintf(stderr, "Error creating the pipe\n");
+		exit(-1);
+	}
+	pid = fork();
+	if (pid == -1) {
+		fprintf(stderr, "Error forking\n");
+		exit(-1);
+	}
+
+	if (pid == 0) /* child proc */
+		do_child(pipes);
+	else
+		do_parent(pipes);
+}
Index: /trunk/minix/test/select/test12.c
===================================================================
--- /trunk/minix/test/select/test12.c	(revision 9)
+++ /trunk/minix/test/select/test12.c	(revision 9)
@@ -0,0 +1,39 @@
+/*
+ * Test name: test12.c
+ *
+ * Objective: The purpose of this check the behaviour when a signal is received
+ * and there is a handler.
+ * 
+ * Description: The program handles SIGHUP and expects the user to actually send
+ * the signal from other terminal with 'kill -1 pid' 
+
+ * Jose M. Gomez
+ */
+
+#include <sys/types.h>
+#include <sys/select.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+
+#define SECONDS 15
+
+void catch_hup(int sig_num)
+{
+	/* don't need to reset signal handler */
+	printf("Received a SIGHUP, inside the handler now\n");
+}
+
+int main(void) {
+	int ret;		/* return value */
+
+	/* set the HUP sginal handler to 'catch_hup' */
+	signal(SIGHUP, catch_hup);
+	/* Get proc_id and print it */
+	printf("Send a signal from other terminal with: kill -1 %d\n", getpid()); 
+   	printf("Blocking now on select...\n", SECONDS);
+	ret = select(0, NULL, NULL, NULL, NULL); 
+	printf("Errno: %d\n", errno);
+}
Index: /trunk/minix/test/select/test13a.c
===================================================================
--- /trunk/minix/test/select/test13a.c	(revision 9)
+++ /trunk/minix/test/select/test13a.c	(revision 9)
@@ -0,0 +1,56 @@
+/*
+ * Test name: test13a.c
+ *
+ * Objective: The purpose of this tests is to show how a select can 
+ * get into a race condition when dealing with signals.
+ * 
+ * Description: The program waits for SIGHUP or input in the terminal          
+ */         
+
+#include <sys/types.h>
+#include <sys/select.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+
+int got_sighup = 0;
+
+void catch_hup(int sig_num)
+{
+	printf("Received a SIGHUP, set global vble \n");
+	got_sighup = 1;
+}
+
+int main(void) {
+	int ret;		/* return value */
+	fd_set read_fds;	
+	char data[1024];
+
+	/* Init read fd_set */
+	FD_ZERO(&read_fds);
+	FD_SET(0, &read_fds);
+
+	/* set the HUP signal handler to 'catch_hup' */
+	signal(SIGHUP, catch_hup);
+
+	/* Get proc_id and print it */
+	printf("Send a signal from other terminal with: kill -1 %d\n", getpid()); 
+	printf("Going to sleep for 5 seconds, if the signal arrives meanwhile\n");
+	printf("the process will be blocked until there is input in the keyboard\n");
+	printf("if the signal arrives after the timeout and while in select, it will\n");
+	printf("behave as it should.\n");
+	printf("Sleeping for 5 secs\n");
+	sleep(5);
+
+   	printf("Blocking now on select...\n");
+	ret = select(1, &read_fds, NULL, NULL, NULL); 
+	if (got_sighup) {
+		printf("We have a sighup signal so exit the program\n");
+		exit(0);
+	}
+	gets(data);
+	printf("Got entry for terminal then, bye\n");
+}
Index: /trunk/minix/test/select/test13b.c
===================================================================
--- /trunk/minix/test/select/test13b.c	(revision 9)
+++ /trunk/minix/test/select/test13b.c	(revision 9)
@@ -0,0 +1,67 @@
+/*
+ * Test name: test13b.c
+ *
+ * Objective: The purpose of this tests is to show how pselect()
+ * solves the situation shown in test13a.c
+ * 
+ * Description: The program waits for SIGHUP or input in the terminal          
+ */         
+
+#include <sys/types.h>
+#include <sys/select.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+
+int got_sighup = 0;
+
+void catch_hup(int sig_num)
+{
+	printf("Received a SIGHUP, set global vble \n");
+	got_sighup = 1;
+}
+
+int main(void) {
+	int ret;		/* return value */
+	fd_set read_fds;	
+	sigset_t sigmask, orig_sigmask;
+	char data[1024];
+
+	/* Init read fd_set */
+	FD_ZERO(&read_fds);
+	FD_SET(0, &read_fds);
+
+	/* set the signal masks */
+	sigemptyset(&sigmask);
+	sigaddset(&sigmask, SIGHUP);
+	sigprocmask( SIG_BLOCK, &sigmask, &orig_sigmask);
+
+	/* set the HUP signal handler to 'catch_hup' */
+	signal(SIGHUP, catch_hup);
+
+	/* Get proc_id and print it */
+	printf("Send a signal from other terminal with: kill -1 %d\n", getpid()); 
+	printf("Going to sleep for 5 seconds, if the signal arrives meanwhile\n");
+	printf("the process will be blocked until there is input in the keyboard\n");
+	printf("if the signal arrives after the timeout and while in select, it will\n");
+	printf("behave as it should.\n");
+	printf("Sleeping for 5 secs\n");
+	sleep(5);
+
+   	printf("Blocking now on select...\n");
+#if 0
+	ret = pselect(1, &read_fds, NULL, NULL, NULL, &orig_sigmask); 
+#else
+	ret = -1;
+#endif
+	if (got_sighup) {
+		printf("We have a sighup signal so exit the program\n");
+		exit(0);
+	}
+	gets(data);
+	printf("Got entry for terminal then, bye\n");
+	
+}
Index: /trunk/minix/test/select/test14.c
===================================================================
--- /trunk/minix/test/select/test14.c	(revision 9)
+++ /trunk/minix/test/select/test14.c	(revision 9)
@@ -0,0 +1,144 @@
+/*
+ * Test name: test14.c
+ *
+ * Objetive: The purpose of this test is to make sure that select works
+ * with ptys.
+ *
+ * Adapted from test11.c (pipe test).
+ * 
+ * Ben Gras
+ */
+#include <time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/asynchio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <signal.h>
+#include <libutil.h>
+char name[100];
+void pipehandler(int sig)
+{
+}
+#define CHILDFD 1
+#define PARENTFD 0
+void do_child(int pty_fds[]) 
+{
+	/* reads from pipe and prints out the data */
+	char data[2048];
+	int retval;	 
+	fd_set fds_read;
+	fd_set fds_exception;	
+	struct timeval timeout;
+	signal(SIGPIPE, pipehandler);
+	signal(SIGUSR1, pipehandler);
+	/* first, close the write part, since it is not needed */
+	close(pty_fds[PARENTFD]);
+	
+	while(1) {
+		FD_ZERO(&fds_read);
+		FD_ZERO(&fds_exception);
+		FD_SET(pty_fds[CHILDFD], &fds_read);
+		FD_SET(pty_fds[CHILDFD], &fds_exception);
+		timeout.tv_sec = 5;
+		timeout.tv_usec = 0;
+		retval = select(pty_fds[CHILDFD]+2,  &fds_read, NULL, &fds_exception, &timeout);
+		if (retval == -1) {
+			perror("select");
+			fprintf(stderr, "child: Error in select\n");
+			continue;
+		} else printf("child select: %d\n", retval);
+		if (FD_ISSET(pty_fds[CHILDFD], &fds_exception)) {
+			printf("child: exception fd set. quitting.\n");
+			break;
+		}
+		if (FD_ISSET(pty_fds[CHILDFD], &fds_read)) {
+			printf("child: read fd set. reading.\n");
+			if ((retval = read(pty_fds[CHILDFD], data, sizeof(data))) < 0) {
+				perror("read");
+				fprintf(stderr, "child: couldn't read from pty\n");
+				exit(-1);
+			}
+			if(retval == 0) {
+				fprintf(stderr, "child: eof on pty\n");
+				break;
+			}
+			data[retval] = '\0';
+			printf("pid %d pty reads (%d): %s\n", getpid(), retval, data);
+		} else printf("child: no fd set\n");
+	}
+	
+	exit(0);
+}
+void do_parent(int pty_fds[]) 
+{
+	char data[1024];
+	int retval;
+	fd_set fds_write;
+	signal(SIGPIPE, pipehandler);
+	signal(SIGUSR1, pipehandler);
+	/* first, close the read part of pty, since it is not needed */
+	close(pty_fds[CHILDFD]);
+	/* now enter a loop of read user input, and writing it to the pty */
+	while (1) {
+		FD_ZERO(&fds_write);
+		FD_SET(pty_fds[PARENTFD], &fds_write);
+		printf("pid %d Waiting for pty ready to write on %s...\n",
+			getpid(), name);
+		retval = select(pty_fds[PARENTFD]+2, NULL, &fds_write, NULL, NULL);
+		if (retval == -1) {
+			perror("select");
+			fprintf(stderr, "Parent: Error in select\n");
+			exit(-1);
+		}		
+		printf("Input data: ");
+		if(!gets(data)) {
+			printf("parent: eof; exiting\n");
+			break;
+		}
+		if (!strcmp(data, "exit"))
+			break;
+		if (!FD_ISSET(pty_fds[PARENTFD], &fds_write)) {
+			fprintf(stderr, "parent: write fd not set?! retrying\n");
+			continue;
+		}
+		retval = write(pty_fds[PARENTFD], data, 1024);
+		if (retval == -1) {
+			perror("write");
+			fprintf(stderr, "Error writing on pty\n");
+			exit(-1);
+		} else printf("wrote %d\n", retval);
+	}
+	/* got exit from user */
+	close(pty_fds[PARENTFD]);	/* close pty, let child know we're done */
+	wait(&retval);
+	printf("Child exited with status: %d\n", retval);
+	exit(0);
+}
+int main(int argc, char *argv[])
+{
+	int ptys[2];
+	int retval;
+	int pid;	
+	if(openpty(&ptys[0], &ptys[1], name, NULL, NULL) < 0) {
+		perror("openpty");
+		return 1;
+	}
+	printf("Using %s\n", name);
+	pid = fork();
+	if (pid == -1) {
+		fprintf(stderr, "Error forking\n");
+		exit(-1);
+	}
+	if (pid == 0) /* child proc */
+		do_child(ptys);
+	else
+		do_parent(ptys);
+	/* not reached */
+	return 0;
+}
Index: /trunk/minix/test/t10a.c
===================================================================
--- /trunk/minix/test/t10a.c	(revision 9)
+++ /trunk/minix/test/t10a.c	(revision 9)
@@ -0,0 +1,8 @@
+#include <stdlib.h>
+
+_PROTOTYPE(int main, (void));
+
+int main()
+{
+  exit(0);
+}
Index: /trunk/minix/test/t11a.c
===================================================================
--- /trunk/minix/test/t11a.c	(revision 9)
+++ /trunk/minix/test/t11a.c	(revision 9)
@@ -0,0 +1,70 @@
+/* t11a */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define MAX_ERROR 4
+
+int errct, subtest=1;
+
+_PROTOTYPE(int main, (int argc, char *argv [], char *envp []));
+_PROTOTYPE(int diff, (char *s1, char *s2));
+_PROTOTYPE(void e, (int n));
+
+int main(argc, argv, envp)
+int argc;
+char *argv[], *envp[];
+{
+/* See if arguments passed ok. */
+
+  char aa[4];
+
+  if (diff(argv[0], "t11a")) e(21);
+  if (diff(argv[1], "arg0")) e(22);
+  if (diff(argv[2], "arg1")) e(23);
+  if (diff(argv[3], "arg2")) e(24);
+  if (diff(envp[0], "spring")) e(25);
+  if (diff(envp[1], "summer")) e(26);
+  if (argc != 4) e(27);
+
+  /* Now see if the files are ok. */
+  if (read(3, aa, 4) != 2) e(28);
+  if (aa[0] != 7 || aa[1] != 9) e(29);
+
+  if (getuid() == 10) e(30);
+  if (geteuid() != 10) e(31);
+  if (getgid() == 20) e(32);
+  if (getegid() != 20) e(33);
+
+  if (open("t1", 0) < 0) e(34);
+  if (open("t2", 0) < 0) e(35);
+  exit(100);
+}
+
+int diff(s1, s2)
+char *s1, *s2;
+{
+  while (1) {
+	if (*s1 == 0 && *s2 == 0) return(0);
+	if (*s1 != *s2) return (1);
+	s1++;
+	s2++;
+  }
+}
+
+void e(n)
+int n;
+{
+  printf("Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+}
Index: /trunk/minix/test/t11b.c
===================================================================
--- /trunk/minix/test/t11b.c	(revision 9)
+++ /trunk/minix/test/t11b.c	(revision 9)
@@ -0,0 +1,55 @@
+/* t11b */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define MAX_ERROR 4
+
+int errct, subtest=1;
+
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(int diff, (char *s1, char *s2));
+_PROTOTYPE(void e, (int n));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+/* See if arguments passed ok. */
+
+  if (diff(argv[0], "t11b")) e(31);
+  if (diff(argv[1], "abc")) e(32);
+  if (diff(argv[2], "defghi")) e(33);
+  if (diff(argv[3], "j")) e(34);
+  if (argv[4] != 0) e(35);
+  if (argc != 4) e(36);
+
+  exit(75);
+}
+
+int diff(s1, s2)
+char *s1, *s2;
+{
+  while (1) {
+	if (*s1 == 0 && *s2 == 0) return(0);
+	if (*s1 != *s2) return (1);
+	s1++;
+	s2++;
+  }
+}
+
+void e(n)
+int n;
+{
+  printf("Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test1.c
===================================================================
--- /trunk/minix/test/test1.c	(revision 9)
+++ /trunk/minix/test/test1.c	(revision 9)
@@ -0,0 +1,148 @@
+/* test 1 */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define SIGNUM 10
+#define MAX_ERROR 4
+#define ITERATIONS 10
+
+_VOLATILE int glov, gct;
+int errct;
+int subtest;
+
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(void test1a, (void));
+_PROTOTYPE(void parent, (void));
+_PROTOTYPE(void child, (int i));
+_PROTOTYPE(void test1b, (void));
+_PROTOTYPE(void parent1, (int childpid));
+_PROTOTYPE(void func, (int s));
+_PROTOTYPE(void child1, (void));
+_PROTOTYPE(void e, (int n));
+_PROTOTYPE(void quit, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+
+  if (argc == 2) m = atoi(argv[1]);
+
+  printf("Test  1 ");
+  fflush(stdout);		/* have to flush for child's benefit */
+
+  system("rm -rf DIR_01; mkdir DIR_01");
+  chdir("DIR_01");
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 00001) test1a();
+	if (m & 00002) test1b();
+  }
+
+  quit();
+  return(-1);			/* impossible */
+}
+
+void test1a()
+{
+  int i, n, pid;
+
+  subtest = 1;
+  n = 4;
+  for (i = 0; i < n; i++) {
+	if ((pid = fork())) {
+		if (pid < 0) {
+			printf("\nTest 1 fork failed\n");
+			exit(1);
+		}
+		parent();
+	} else
+		child(i);
+  }
+}
+
+void parent()
+{
+
+  int n;
+
+  n = getpid();
+  wait(&n);
+}
+
+void child(i)
+int i;
+{
+  int n;
+
+  n = getpid();
+  exit(100+i);
+}
+
+void test1b()
+{
+  int i, k;
+
+  subtest = 2;
+  for (i = 0; i < 4; i++) {
+	glov = 0;
+	signal(SIGNUM, func);
+	if ((k = fork())) {
+		if (k < 0) {
+			printf("Test 1 fork failed\n");
+			exit(1);
+		}
+		parent1(k);
+	} else
+		child1();
+  }
+}
+
+void parent1(childpid)
+int childpid;
+{
+
+  int n;
+
+  for (n = 0; n < 5000; n++);
+  while (kill(childpid, SIGNUM) < 0)	/* null statement */
+	;
+  wait(&n);
+}
+
+void func(s)
+int s;				/* for ANSI */
+{
+  glov++;
+  gct++;
+}
+
+void child1()
+{
+  while (glov == 0);
+  exit(gct);
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test10.c
===================================================================
--- /trunk/minix/test/test10.c	(revision 9)
+++ /trunk/minix/test/test10.c	(revision 9)
@@ -0,0 +1,152 @@
+/* test 10 */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+char *name[] = {"t10a", "t10b", "t10c", "t10d", "t10e", "t10f", "t10g", 
+						      "t10h", "t10i", "t10j"};
+int errct;
+long prog[300];
+int psize;
+
+_PROTOTYPE(int main, (void));
+_PROTOTYPE(void spawn, (int n));
+_PROTOTYPE(void mkfiles, (void));
+_PROTOTYPE(void cr_file, (char *name, int size));
+_PROTOTYPE(void rmfiles, (void));
+_PROTOTYPE(void quit, (void));
+
+int main()
+{
+  int i, n, pid, r;
+
+  printf("Test 10 ");
+  fflush(stdout);		/* have to flush for child's benefit */
+
+  system("rm -rf DIR_10; mkdir DIR_10; cp t10a DIR_10");
+  chdir("DIR_10");
+
+  pid = getpid();
+
+  /* Create files t10b ... t10h */
+  mkfiles();
+
+  if (getpid() == pid)
+	if (fork() == 0) {
+		execl("t10a", (char *) 0);
+		exit(0);
+	}
+  if (getpid() == pid)
+	if (fork() == 0) {
+		execl("t10b", (char *) 0);
+		exit(0);
+	}
+  if (getpid() == pid)
+	if (fork() == 0) {
+		execl("t10c", (char *) 0);
+		exit(0);
+	}
+  if (getpid() == pid)
+	if (fork() == 0) {
+		execl("t10d", (char *) 0);
+		exit(0);
+	}
+
+  srand(100);
+  for (i = 0; i < 60; i++) {
+	r = rand() & 07;
+	spawn(r);
+  }
+
+  for (i = 0; i < 4; i++) wait(&n);
+  rmfiles();
+  quit();
+  return(-1);			/* impossible */
+}
+
+void spawn(n)
+int n;
+{
+  int pid, k;
+
+  if (pid = fork()) {
+	wait(&n);		/* wait for some child (any one) */
+  } else {
+	k = execl(name[n], (char *) 0);
+	errct++;
+	printf("Child execl didn't take. file=%s errno=%d\n", name[n], errno);
+	rmfiles();
+	exit(1);
+	printf("Worse yet, EXIT didn't exit\n");
+  }
+}
+
+void mkfiles()
+{
+  int fd;
+  fd = open("t10a", 0);
+  if (fd < 0) {
+	printf("Can't open t10a\n");
+	exit(1);
+  }
+  psize = read(fd, (char *) prog, 300 * 4);
+  cr_file("t10b", 1600);
+  cr_file("t10c", 1400);
+  cr_file("t10d", 2300);
+  cr_file("t10e", 3100);
+  cr_file("t10f", 2400);
+  cr_file("t10g", 1700);
+  cr_file("t10h", 1500);
+  cr_file("t10i", 4000);
+  cr_file("t10j", 2250);
+  close(fd);
+}
+
+void cr_file(name, size)
+char *name;
+int size;
+
+{
+  int fd;
+
+#if (CHIP == SPARC)
+  size += 4000;
+#endif
+  prog[6] = (long) size;
+  fd = creat(name, 0755);
+  write(fd, (char *) prog, psize);
+  close(fd);
+}
+
+void rmfiles()
+{
+  unlink("t10b");
+  unlink("t10c");
+  unlink("t10d");
+  unlink("t10e");
+  unlink("t10f");
+  unlink("t10g");
+  unlink("t10h");
+  unlink("t10i");
+  unlink("t10j");
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test11.c
===================================================================
--- /trunk/minix/test/test11.c	(revision 9)
+++ /trunk/minix/test/test11.c	(revision 9)
@@ -0,0 +1,224 @@
+/* test 11 */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define ITERATIONS 10
+#define MAX_ERROR 1
+
+int errct, subtest;
+char *envp[3] = {"spring", "summer", 0};
+char *passwd_file = "/etc/passwd";
+
+_PROTOTYPE(int main, (int argc, char *argv[]));
+_PROTOTYPE(void test11a, (void));
+_PROTOTYPE(void test11b, (void));
+_PROTOTYPE(void test11c, (void));
+_PROTOTYPE(void test11d, (void));
+_PROTOTYPE(void e, (int n));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  if (argc == 2) m = atoi(argv[1]);
+
+  printf("Test 11 ");
+  fflush(stdout);		/* have to flush for child's benefit */
+
+  if (geteuid() != 0) {
+	printf("must be setuid root; test aborted\n");
+	exit(1);
+  }
+  if (getuid() == 0) {
+       printf("must be setuid root logged in as someone else; test aborted\n");
+       exit(1);
+  }
+
+/*
+  system("rm -rf DIR_11; mkdir DIR_11");
+  chdir("DIR_11");
+*/
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test11a();
+	if (m & 0002) test11b();
+	if (m & 0004) test11c();
+	if (m & 0010) test11d();
+  }
+  if (errct == 0)
+	printf("ok\n");
+  else
+	printf(" %d errors\n", errct);
+
+/*
+  chdir("..");
+  system("rm -rf DIR_11");
+*/
+  return(0);
+}
+
+void test11a()
+{
+/* Test exec */
+  int n, fd;
+  char aa[4];
+
+  subtest = 1;
+
+  if (fork()) {
+	wait(&n);
+	if (n != 25600) e(1);
+	unlink("t1");
+	unlink("t2");
+  } else {
+	if (chown("t11a", 10, 20) < 0) e(2);
+	chmod("t11a", 0666);
+
+	/* The following call should fail because the mode has no X
+	 * bits on. If a bug lets it unexpectedly succeed, the child
+	 * will print an error message since the arguments are wrong.
+ 	 */
+	execl("t11a", (char *) 0, envp);	/* should fail -- no X bits */
+
+	/* Control should come here after the failed execl(). */
+	chmod("t11a", 06555);
+	if ((fd = creat("t1", 0600)) != 3) e(3);
+	if (close(fd) < 0) e(4);
+	if (open("t1", O_RDWR) != 3) e(5);
+	if (chown("t1", 10, 99) < 0) e(6);
+	if ((fd = creat("t2", 0060)) != 4) e(7);
+	if (close(fd) < 0) e(8);
+	if (open("t2", O_RDWR) != 4) e(9);
+	if (chown("t2", 99, 20) < 0) e(10);
+	if (setgid(6) < 0) e(11);
+	if (setuid(5) < 0) e(12);
+	if (getuid() != 5) e(13);
+	if (geteuid() != 5) e(14);
+	if (getgid() != 6) e(15);
+	if (getegid() != 6) e(16);
+	aa[0] = 3;
+	aa[1] = 5;
+	aa[2] = 7;
+	aa[3] = 9;
+	if (write(3, aa, 4) != 4) e(17);
+	lseek(3, 2L, 0);
+	execle("t11a", "t11a", "arg0", "arg1", "arg2", (char *) 0, envp);
+	e(18);
+	printf("Can't exec t11a\n");
+	exit(3);
+  }
+}
+
+void test11b()
+{
+  int n;
+  char *argv[5];
+
+  subtest = 2;
+  if (fork()) {
+	wait(&n);
+	if (n != (75 << 8)) e(20);
+  } else {
+	/* Child tests execv. */
+	argv[0] = "t11b";
+	argv[1] = "abc";
+	argv[2] = "defghi";
+	argv[3] = "j";
+	argv[4] = 0;
+	execv("t11b", argv);
+	e(19);
+  }
+}
+
+void test11c()
+{
+/* Test getlogin() and cuserid().  This test  MUST run setuid root. */
+
+  int n, etc_uid;
+  uid_t ruid, euid;
+  char *lnamep, *cnamep, *p;
+  char array[L_cuserid], save[L_cuserid], save2[L_cuserid];
+  FILE *stream;
+
+  subtest = 3;
+  errno = -2000;		/* None of these calls set errno. */
+  array[0] = '@';
+  array[1] = '0';
+  save[0] = '#';
+  save[1] = '0';
+  ruid = getuid();
+  euid = geteuid();
+  lnamep = getlogin();
+  strcpy(save, lnamep);
+  cnamep = cuserid(array);
+  strcpy(save2, cnamep);
+
+  /* Because we are setuid root, cuser == array == 'root';  login != 'root' */
+  if (euid != 0) e(1);
+  if (ruid == 0) e(2);
+  if (strcmp(cnamep, "root") != 0) e(3);
+  if (strcmp(array, "root") != 0) e(4);
+  if ( (n = strlen(save)) == 0) e(5);
+  if (strcmp(save, cnamep) == 0) e(6);		/* they must be different */
+  cnamep = cuserid(NULL);
+  if (strcmp(cnamep, save2) != 0) e(7);
+
+  /* Check login against passwd file. First lookup login in /etc/passwd. */
+  if (n == 0) return;		/* if login not found, don't look it up */
+  if ( (stream = fopen(passwd_file, "r")) == NULL) e(8);
+  while (fgets(array, L_cuserid, stream) != NULL) {
+	if (strncmp(array, save, n) == 0) {
+		p = &array[0];		/* hunt for uid */
+		while (*p != ':') p++;
+		p++;
+		while (*p != ':') p++;
+		p++;			/* p now points to uid */
+		etc_uid = atoi(p);
+		if (etc_uid != ruid) e(9);
+		break;			/* 1 entry per login please */
+	}
+  }
+  fclose(stream);
+}
+
+void test11d()
+{
+  int fd;
+  struct stat statbuf;
+
+  subtest = 4;
+  fd = creat("T11.1", 0750);
+  if (fd < 0) e(1);
+  if (chown("T11.1", 8, 1) != 0) e(2);
+  if (chmod("T11.1", 0666) != 0) e(3);
+  if (stat("T11.1", &statbuf) != 0) e(4);
+  if ((statbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) != 0666) e(5);
+  if (close(fd) != 0) e(6);
+  if (unlink("T11.1") != 0) e(7);
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* save errno in case printf clobbers it */
+
+  printf("Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
+  errno = err_num;		/* restore errno, just in case */
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test12.c
===================================================================
--- /trunk/minix/test/test12.c	(revision 9)
+++ /trunk/minix/test/test12.c	(revision 9)
@@ -0,0 +1,55 @@
+/* test 12 */
+
+/* Copyright (C) 1987 by Martin Leisner. All rights reserved. */
+/* Used by permission. */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define NUM_TIMES	1000
+
+int errct = 0;
+
+_PROTOTYPE(int main, (void));
+_PROTOTYPE(void quit, (void));
+
+int main()
+{
+  register int i;
+  int k;
+
+  printf("Test 12 ");
+  fflush(stdout);		/* have to flush for child's benefit */
+
+  system("rm -rf DIR_12; mkdir DIR_12");
+  chdir("DIR_12");
+
+  for (i = 0; i < NUM_TIMES; i++) switch (fork()) {
+	    case 0:	exit(1);	  		break;
+	    case -1:
+		printf("fork broke\n");
+		exit(1);
+	    default:	wait(&k);	  		break;
+	}
+
+  quit();
+  return(-1);			/* impossible */
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test13.c
===================================================================
--- /trunk/minix/test/test13.c	(revision 9)
+++ /trunk/minix/test/test13.c	(revision 9)
@@ -0,0 +1,72 @@
+/* test 13 */
+
+/* File: pipes.c - created by Marty Leisner */
+/* Leisner.Henr         1-Dec-87  8:55:04 */
+
+/* Copyright (C) 1987 by Martin Leisner. All rights reserved. */
+/* Used by permission. */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define BLOCK_SIZE 	1000
+#define NUM_BLOCKS	1000
+
+int errct = 0;
+char buffer[BLOCK_SIZE];
+
+_PROTOTYPE(int main, (void));
+_PROTOTYPE(void quit, (void));
+
+int main()
+{
+  int stat_loc, pipefd[2];
+  register int i;
+  pipe(pipefd);
+
+  printf("Test 13 ");
+  fflush(stdout);		/* have to flush for child's benefit */
+
+  system("rm -rf DIR_13; mkdir DIR_13");
+  chdir("DIR_13");
+
+  pipe(pipefd);
+
+  switch (fork()) {
+      case 0:
+	/* Child code */
+	for (i = 0; i < NUM_BLOCKS; i++)
+	         if (read(pipefd[0], buffer, BLOCK_SIZE) != BLOCK_SIZE) break;
+	exit(0);
+
+      case -1:
+	perror("fork broke");
+	exit(1);
+
+      default:
+	/* Parent code */
+	for (i = 0; i < NUM_BLOCKS; i++) write(pipefd[1], buffer, BLOCK_SIZE);
+	wait(&stat_loc);
+	break;
+  }
+  quit();
+  return(-1);			/* impossible */
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test14.c
===================================================================
--- /trunk/minix/test/test14.c	(revision 9)
+++ /trunk/minix/test/test14.c	(revision 9)
@@ -0,0 +1,79 @@
+/* Test 14. unlinking an open file. */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define TRIALS 100
+#define MAX_ERROR 4
+
+char name[20] = {"TMP14."};
+int errct;
+int subtest = 1;
+
+_PROTOTYPE(int main, (void));
+_PROTOTYPE(void e, (int n));
+_PROTOTYPE(void quit, (void));
+
+int main()
+{
+  int fd0, i, pid;
+
+  printf("Test 14 ");
+  fflush(stdout);
+
+  system("rm -rf DIR_14; mkdir DIR_14");
+  chdir("DIR_14");
+
+  pid = getpid();
+  name[6] = (pid & 037) + 33;
+  name[7] = ((pid * pid) & 037) + 33;
+  name[8] = 0;
+
+  for (i = 0; i < TRIALS; i++) {
+	if ( (fd0 = creat(name, 0777)) < 0) e(1);
+	if (write(fd0, name, 20) != 20) e(2);
+	if (unlink(name) != 0) e(3);
+	if (close(fd0) != 0) e(4);
+  }
+
+  fd0 = creat(name, 0777);
+  write(fd0, name, 20);
+  unlink(name);
+  quit();
+  return(-1);			/* impossible */
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* save errno in case printf clobbers it */
+
+  printf("Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
+  errno = err_num;		/* restore errno, just in case */
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test15.c
===================================================================
--- /trunk/minix/test/test15.c	(revision 9)
+++ /trunk/minix/test/test15.c	(revision 9)
@@ -0,0 +1,704 @@
+/* Test program for string(3) routines.
+ *
+ * Slightly modified from Henry Spencer's original routine.
+ *   - incorporates semantic changes per the ANSI standard (original tests
+ *     can be recovered by defining the symbol NOT_ANSI while compiling,
+ *     except for the change of memcpy() to memmove()).
+ *   - makes additional tests of functions on unaligned buffers and strings.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+_PROTOTYPE( int chdir, (char *_path));		/* from <unistd.h> */
+
+#define	STREQ(a, b)	(strcmp((a), (b)) == 0)
+
+char *it = "<UNSET>";		/* Routine name for message routines. */
+int errct;			/* count errors */
+int waserror = 0;		/* For exit status. */
+
+char uctest[] = "\004\203";	/* For testing signedness of chars. */
+int charsigned;			/* Result. */
+
+_PROTOTYPE(void check, (int thing, int number));
+_PROTOTYPE(void equal, (char *a, char *b, int number));
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(void first, (void));
+_PROTOTYPE(void second, (void));
+_PROTOTYPE(void quit, (void));
+
+/*
+ - check - complain if condition is not true
+ */
+void check(thing, number)
+int thing;
+int number;			/* Test number for error message. */
+{
+  if (!thing) {
+	printf("%s flunked test %d\n", it, number);
+	waserror = 1;
+	errct++;
+  }
+}
+
+/*
+ - equal - complain if first two args don't strcmp as equal
+ */
+void equal(a, b, number)
+char *a;
+char *b;
+int number;			/* Test number for error message. */
+{
+  check(a != NULL && b != NULL && STREQ(a, b), number);
+}
+
+char one[50];
+char two[50];
+
+#ifdef UNIXERR
+#define ERR 1
+#endif
+#ifdef BERKERR
+#define ERR 1
+#endif
+#ifdef ERR
+int f;
+extern char *sys_errlist[];
+extern int sys_nerr;
+#endif
+
+/* ARGSUSED */
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  printf("Test 15 ");
+  fflush(stdout);
+
+  system("rm -rf DIR_15; mkdir DIR_15");
+  chdir("DIR_15");
+  /* First, establish whether chars are signed. */
+  if (uctest[0] < uctest[1])
+	charsigned = 0;
+  else
+	charsigned = 1;
+
+  /* Then, do the rest of the work.  Split into two functions because
+   * some compilers get unhappy about a single immense function. */
+  first();
+  second();
+
+  errct = waserror;
+  quit();
+  return(-1);			/* impossible */
+}
+
+void first()
+{
+  /* Test strcmp first because we use it to test other things. */
+  it = "strcmp";
+  check(strcmp("", "") == 0, 1);/* Trivial case. */
+  check(strcmp("a", "a") == 0, 2);	/* Identity. */
+  check(strcmp("abc", "abc") == 0, 3);	/* Multicharacter. */
+  check(strcmp("abc", "abcd") < 0, 4);	/* Length mismatches. */
+  check(strcmp("abcd", "abc") > 0, 5);
+  check(strcmp("abcd", "abce") < 0, 6);	/* Honest miscompares. */
+  check(strcmp("abce", "abcd") > 0, 7);
+  check(strcmp("a\203", "a") > 0, 8);	/* Tricky if char signed. */
+
+#ifdef NOT_ANSI
+  if (charsigned)
+	check(strcmp("a\203", "a\003") < 0, 9);
+  else
+	check(strcmp("a\203", "a\003") > 0, 9);
+#else
+  check(strcmp("a\203", "a\003") > 0, 9);
+#endif
+
+  check(strcmp("abcd" + 1, "abcd" + 1) == 0, 10);	/* Unaligned tests. */
+  check(strcmp("abcd" + 1, "abce" + 1) < 0, 11);
+  check(strcmp("abcd" + 1, "bcd") == 0, 12);
+  check(strcmp("abce" + 1, "bcd") > 0, 13);
+  check(strcmp("abcd" + 2, "bcd" + 1) == 0, 14);
+  check(strcmp("abcd" + 2, "bce" + 1) < 0, 15);
+
+  /* Test strcpy next because we need it to set up other tests. */
+  it = "strcpy";
+  check(strcpy(one, "abcd") == one, 1);	/* Returned value. */
+  equal(one, "abcd", 2);	/* Basic test. */
+
+  (void) strcpy(one, "x");
+  equal(one, "x", 3);		/* Writeover. */
+  equal(one + 2, "cd", 4);	/* Wrote too much? */
+
+  (void) strcpy(two, "hi there");
+  (void) strcpy(one, two);
+  equal(one, "hi there", 5);	/* Basic test encore. */
+  equal(two, "hi there", 6);	/* Stomped on source? */
+
+  (void) strcpy(one, "");
+  equal(one, "", 7);		/* Boundary condition. */
+
+  (void) strcpy(one, "abcdef" + 1);	/* Unaligned tests. */
+  equal(one, "bcdef", 8);
+  (void) strcpy(one + 1, "*xy" + 1);
+  equal(one, "bxy", 9);
+  equal(one + 4, "f", 10);
+
+  /* Strcat */
+  it = "strcat";
+  (void) strcpy(one, "ijk");
+  check(strcat(one, "lmn") == one, 1);	/* Returned value. */
+  equal(one, "ijklmn", 2);	/* Basic test. */
+
+  (void) strcpy(one, "x");
+  (void) strcat(one, "yz");
+  equal(one, "xyz", 3);		/* Writeover. */
+  equal(one + 4, "mn", 4);	/* Wrote too much? */
+
+  (void) strcpy(one, "gh");
+  (void) strcpy(two, "ef");
+  (void) strcat(one, two);
+  equal(one, "ghef", 5);	/* Basic test encore. */
+  equal(two, "ef", 6);		/* Stomped on source? */
+
+  (void) strcpy(one, "");
+  (void) strcat(one, "");
+  equal(one, "", 7);		/* Boundary conditions. */
+  (void) strcpy(one, "ab");
+  (void) strcat(one, "");
+  equal(one, "ab", 8);
+  (void) strcpy(one, "");
+  (void) strcat(one, "cd");
+  equal(one, "cd", 9);
+
+  /* Strncat - first test it as strcat, with big counts, then test the
+   * count mechanism. */
+  it = "strncat";
+  (void) strcpy(one, "ijk");
+  check(strncat(one, "lmn", 99) == one, 1);	/* Returned value. */
+  equal(one, "ijklmn", 2);	/* Basic test. */
+
+  (void) strcpy(one, "x");
+  (void) strncat(one, "yz", 99);
+  equal(one, "xyz", 3);		/* Writeover. */
+  equal(one + 4, "mn", 4);	/* Wrote too much? */
+
+  (void) strcpy(one, "gh");
+  (void) strcpy(two, "ef");
+  (void) strncat(one, two, 99);
+  equal(one, "ghef", 5);	/* Basic test encore. */
+  equal(two, "ef", 6);		/* Stomped on source? */
+
+  (void) strcpy(one, "");
+  (void) strncat(one, "", 99);
+  equal(one, "", 7);		/* Boundary conditions. */
+  (void) strcpy(one, "ab");
+  (void) strncat(one, "", 99);
+  equal(one, "ab", 8);
+  (void) strcpy(one, "");
+  (void) strncat(one, "cd", 99);
+  equal(one, "cd", 9);
+
+  (void) strcpy(one, "ab");
+  (void) strncat(one, "cdef", 2);
+  equal(one, "abcd", 10);	/* Count-limited. */
+
+  (void) strncat(one, "gh", 0);
+  equal(one, "abcd", 11);	/* Zero count. */
+
+  (void) strncat(one, "gh", 2);
+  equal(one, "abcdgh", 12);	/* Count and length equal. */
+
+  (void) strcpy(one, "abcdefghij");	/* Unaligned tests. */
+  (void) strcpy(one, "abcd");
+  (void) strcpy(one, "abc");
+  (void) strncat(one, "de" + 1, 1);
+  equal(one, "abce", 13);
+  equal(one + 4, "", 14);
+  equal(one + 5, "fghij", 15);
+
+  /* Strncmp - first test as strcmp with big counts, then test count code. */
+  it = "strncmp";
+  check(strncmp("", "", 99) == 0, 1);	/* Trivial case. */
+  check(strncmp("a", "a", 99) == 0, 2);	/* Identity. */
+  check(strncmp("abc", "abc", 99) == 0, 3);	/* Multicharacter. */
+  check(strncmp("abc", "abcd", 99) < 0, 4);	/* Length unequal. */
+  check(strncmp("abcd", "abc", 99) > 0, 5);
+  check(strncmp("abcd", "abce", 99) < 0, 6);	/* Honestly unequal. */
+  check(strncmp("abce", "abcd", 99) > 0, 7);
+  check(strncmp("a\203", "a", 2) > 0, 8);	/* Tricky if '\203' < 0 */
+
+#ifdef NOT_ANSI
+  if (charsigned)
+	check(strncmp("a\203", "a\003", 2) < 0, 9);
+  else
+	check(strncmp("a\203", "a\003", 2) > 0, 9);
+#else
+  check(strncmp("a\203", "a\003", 2) > 0, 9);
+#endif
+
+  check(strncmp("abce", "abcd", 3) == 0, 10);	/* Count limited. */
+  check(strncmp("abce", "abc", 3) == 0, 11);	/* Count == length. */
+  check(strncmp("abcd", "abce", 4) < 0, 12);	/* Nudging limit. */
+  check(strncmp("abc", "def", 0) == 0, 13);	/* Zero count. */
+
+  /* Strncpy - testing is a bit different because of odd semantics */
+  it = "strncpy";
+  check(strncpy(one, "abc", 4) == one, 1);	/* Returned value. */
+  equal(one, "abc", 2);		/* Did the copy go right? */
+
+  (void) strcpy(one, "abcdefgh");
+  (void) strncpy(one, "xyz", 2);
+  equal(one, "xycdefgh", 3);	/* Copy cut by count. */
+
+  (void) strcpy(one, "abcdefgh");
+  (void) strncpy(one, "xyz", 3);/* Copy cut just before NUL. */
+  equal(one, "xyzdefgh", 4);
+
+  (void) strcpy(one, "abcdefgh");
+  (void) strncpy(one, "xyz", 4);/* Copy just includes NUL. */
+  equal(one, "xyz", 5);
+  equal(one + 4, "efgh", 6);	/* Wrote too much? */
+
+  (void) strcpy(one, "abcdefgh");
+  (void) strncpy(one, "xyz", 5);/* Copy includes padding. */
+  equal(one, "xyz", 7);
+  equal(one + 4, "", 8);
+  equal(one + 5, "fgh", 9);
+
+  (void) strcpy(one, "abc");
+  (void) strncpy(one, "xyz", 0);/* Zero-length copy. */
+  equal(one, "abc", 10);
+
+  (void) strncpy(one, "", 2);	/* Zero-length source. */
+  equal(one, "", 11);
+  equal(one + 1, "", 12);
+  equal(one + 2, "c", 13);
+
+  (void) strcpy(one, "hi there");
+  (void) strncpy(two, one, 9);
+  equal(two, "hi there", 14);	/* Just paranoia. */
+  equal(one, "hi there", 15);	/* Stomped on source? */
+
+  /* Strlen */
+  it = "strlen";
+  check(strlen("") == 0, 1);	/* Empty. */
+  check(strlen("a") == 1, 2);	/* Single char. */
+  check(strlen("abcd") == 4, 3);/* Multiple chars. */
+  check(strlen("abcd" + 1) == 3, 4);	/* Unaligned test. */
+
+  /* Strchr */
+  it = "strchr";
+  check(strchr("abcd", 'z') == NULL, 1);	/* Not found. */
+  (void) strcpy(one, "abcd");
+  check(strchr(one, 'c') == one + 2, 2);	/* Basic test. */
+  check(strchr(one, 'd') == one + 3, 3);	/* End of string. */
+  check(strchr(one, 'a') == one, 4);	/* Beginning. */
+  check(strchr(one, '\0') == one + 4, 5);	/* Finding NUL. */
+  (void) strcpy(one, "ababa");
+  check(strchr(one, 'b') == one + 1, 6);	/* Finding first. */
+  (void) strcpy(one, "");
+  check(strchr(one, 'b') == NULL, 7);	/* Empty string. */
+  check(strchr(one, '\0') == one, 8);	/* NUL in empty string. */
+
+  /* Index - just like strchr */
+  it = "index";
+  check(index("abcd", 'z') == NULL, 1);	/* Not found. */
+  (void) strcpy(one, "abcd");
+  check(index(one, 'c') == one + 2, 2);	/* Basic test. */
+  check(index(one, 'd') == one + 3, 3);	/* End of string. */
+  check(index(one, 'a') == one, 4);	/* Beginning. */
+  check(index(one, '\0') == one + 4, 5);	/* Finding NUL. */
+  (void) strcpy(one, "ababa");
+  check(index(one, 'b') == one + 1, 6);	/* Finding first. */
+  (void) strcpy(one, "");
+  check(index(one, 'b') == NULL, 7);	/* Empty string. */
+  check(index(one, '\0') == one, 8);	/* NUL in empty string. */
+
+  /* Strrchr */
+  it = "strrchr";
+  check(strrchr("abcd", 'z') == NULL, 1);	/* Not found. */
+  (void) strcpy(one, "abcd");
+  check(strrchr(one, 'c') == one + 2, 2);	/* Basic test. */
+  check(strrchr(one, 'd') == one + 3, 3);	/* End of string. */
+  check(strrchr(one, 'a') == one, 4);	/* Beginning. */
+  check(strrchr(one, '\0') == one + 4, 5);	/* Finding NUL. */
+  (void) strcpy(one, "ababa");
+  check(strrchr(one, 'b') == one + 3, 6);	/* Finding last. */
+  (void) strcpy(one, "");
+  check(strrchr(one, 'b') == NULL, 7);	/* Empty string. */
+  check(strrchr(one, '\0') == one, 8);	/* NUL in empty string. */
+
+  /* Rindex - just like strrchr */
+  it = "rindex";
+  check(rindex("abcd", 'z') == NULL, 1);	/* Not found. */
+  (void) strcpy(one, "abcd");
+  check(rindex(one, 'c') == one + 2, 2);	/* Basic test. */
+  check(rindex(one, 'd') == one + 3, 3);	/* End of string. */
+  check(rindex(one, 'a') == one, 4);	/* Beginning. */
+  check(rindex(one, '\0') == one + 4, 5);	/* Finding NUL. */
+  (void) strcpy(one, "ababa");
+  check(rindex(one, 'b') == one + 3, 6);	/* Finding last. */
+  (void) strcpy(one, "");
+  check(rindex(one, 'b') == NULL, 7);	/* Empty string. */
+  check(rindex(one, '\0') == one, 8);	/* NUL in empty string. */
+}
+
+void second()
+{
+  /* Strpbrk - somewhat like strchr */
+  it = "strpbrk";
+  check(strpbrk("abcd", "z") == NULL, 1);	/* Not found. */
+  (void) strcpy(one, "abcd");
+  check(strpbrk(one, "c") == one + 2, 2);	/* Basic test. */
+  check(strpbrk(one, "d") == one + 3, 3);	/* End of string. */
+  check(strpbrk(one, "a") == one, 4);	/* Beginning. */
+  check(strpbrk(one, "") == NULL, 5);	/* Empty search list. */
+  check(strpbrk(one, "cb") == one + 1, 6);	/* Multiple search. */
+  (void) strcpy(one, "abcabdea");
+  check(strpbrk(one, "b") == one + 1, 7);	/* Finding first. */
+  check(strpbrk(one, "cb") == one + 1, 8);	/* With multiple search. */
+  check(strpbrk(one, "db") == one + 1, 9);	/* Another variant. */
+  (void) strcpy(one, "");
+  check(strpbrk(one, "bc") == NULL, 10);	/* Empty string. */
+  check(strpbrk(one, "") == NULL, 11);	/* Both strings empty. */
+
+  /* Strstr - somewhat like strchr */
+  it = "strstr";
+  check(strstr("abcd", "z") == NULL, 1);	/* Not found. */
+  check(strstr("abcd", "abx") == NULL, 2);	/* Dead end. */
+  (void) strcpy(one, "abcd");
+  check(strstr(one, "c") == one + 2, 3);	/* Basic test. */
+  check(strstr(one, "bc") == one + 1, 4);	/* Multichar. */
+  check(strstr(one, "d") == one + 3, 5);	/* End of string. */
+  check(strstr(one, "cd") == one + 2, 6);	/* Tail of string. */
+  check(strstr(one, "abc") == one, 7);	/* Beginning. */
+  check(strstr(one, "abcd") == one, 8);	/* Exact match. */
+  check(strstr(one, "abcde") == NULL, 9);	/* Too long. */
+  check(strstr(one, "de") == NULL, 10);	/* Past end. */
+#ifdef NOT_ANSI
+  check(strstr(one, "") == one + 4, 11);	/* Finding empty. */
+#else
+  check(strstr(one, "") == one, 11);	/* Finding empty. */
+#endif
+  (void) strcpy(one, "ababa");
+  check(strstr(one, "ba") == one + 1, 12);	/* Finding first. */
+  (void) strcpy(one, "");
+  check(strstr(one, "b") == NULL, 13);	/* Empty string. */
+  check(strstr(one, "") == one, 14);	/* Empty in empty string. */
+  (void) strcpy(one, "bcbca");
+  check(strstr(one, "bca") == one + 2, 15);	/* False start. */
+  (void) strcpy(one, "bbbcabbca");
+  check(strstr(one, "bbca") == one + 1, 16);	/* With overlap. */
+
+  /* Strspn */
+  it = "strspn";
+  check(strspn("abcba", "abc") == 5, 1);	/* Whole string. */
+  check(strspn("abcba", "ab") == 2, 2);	/* Partial. */
+  check(strspn("abc", "qx") == 0, 3);	/* None. */
+  check(strspn("", "ab") == 0, 4);	/* Null string. */
+  check(strspn("abc", "") == 0, 5);	/* Null search list. */
+
+  /* Strcspn */
+  it = "strcspn";
+  check(strcspn("abcba", "qx") == 5, 1);	/* Whole string. */
+  check(strcspn("abcba", "cx") == 2, 2);	/* Partial. */
+  check(strcspn("abc", "abc") == 0, 3);	/* None. */
+  check(strcspn("", "ab") == 0, 4);	/* Null string. */
+  check(strcspn("abc", "") == 3, 5);	/* Null search list. */
+
+  /* Strtok - the hard one */
+  it = "strtok";
+  (void) strcpy(one, "first, second, third");
+  equal(strtok(one, ", "), "first", 1);	/* Basic test. */
+  equal(one, "first", 2);
+  equal(strtok((char *) NULL, ", "), "second", 3);
+  equal(strtok((char *) NULL, ", "), "third", 4);
+  check(strtok((char *) NULL, ", ") == NULL, 5);
+  (void) strcpy(one, ", first, ");
+  equal(strtok(one, ", "), "first", 6);	/* Extra delims, 1 tok. */
+  check(strtok((char *) NULL, ", ") == NULL, 7);
+  (void) strcpy(one, "1a, 1b; 2a, 2b");
+  equal(strtok(one, ", "), "1a", 8);	/* Changing delim lists. */
+  equal(strtok((char *) NULL, "; "), "1b", 9);
+  equal(strtok((char *) NULL, ", "), "2a", 10);
+  (void) strcpy(two, "x-y");
+  equal(strtok(two, "-"), "x", 11);	/* New string before done. */
+  equal(strtok((char *) NULL, "-"), "y", 12);
+  check(strtok((char *) NULL, "-") == NULL, 13);
+  (void) strcpy(one, "a,b, c,, ,d");
+  equal(strtok(one, ", "), "a", 14);	/* Different separators. */
+  equal(strtok((char *) NULL, ", "), "b", 15);
+  equal(strtok((char *) NULL, " ,"), "c", 16);	/* Permute list too. */
+  equal(strtok((char *) NULL, " ,"), "d", 17);
+  check(strtok((char *) NULL, ", ") == NULL, 18);
+  check(strtok((char *) NULL, ", ") == NULL, 19);	/* Persistence. */
+  (void) strcpy(one, ", ");
+  check(strtok(one, ", ") == NULL, 20);	/* No tokens. */
+  (void) strcpy(one, "");
+  check(strtok(one, ", ") == NULL, 21);	/* Empty string. */
+  (void) strcpy(one, "abc");
+  equal(strtok(one, ", "), "abc", 22);	/* No delimiters. */
+  check(strtok((char *) NULL, ", ") == NULL, 23);
+  (void) strcpy(one, "abc");
+  equal(strtok(one, ""), "abc", 24);	/* Empty delimiter list. */
+  check(strtok((char *) NULL, "") == NULL, 25);
+  (void) strcpy(one, "abcdefgh");
+  (void) strcpy(one, "a,b,c");
+  equal(strtok(one, ","), "a", 26);	/* Basics again... */
+  equal(strtok((char *) NULL, ","), "b", 27);
+  equal(strtok((char *) NULL, ","), "c", 28);
+  check(strtok((char *) NULL, ",") == NULL, 29);
+  equal(one + 6, "gh", 30);	/* Stomped past end? */
+  equal(one, "a", 31);		/* Stomped old tokens? */
+  equal(one + 2, "b", 32);
+  equal(one + 4, "c", 33);
+
+  /* Memcmp */
+  it = "memcmp";
+  check(memcmp("a", "a", 1) == 0, 1);	/* Identity. */
+  check(memcmp("abc", "abc", 3) == 0, 2);	/* Multicharacter. */
+  check(memcmp("abcd", "abce", 4) < 0, 3);	/* Honestly unequal. */
+  check(memcmp("abce", "abcd", 4) > 0, 4);
+  check(memcmp("alph", "beta", 4) < 0, 5);
+
+#ifdef NOT_ANSI
+  if (charsigned)
+	check(memcmp("a\203", "a\003", 2) < 0, 6);
+  else
+	check(memcmp("a\203", "a\003", 2) > 0, 6);
+#else
+  check(memcmp("a\203", "a\003", 2) > 0, 6);
+#endif
+
+  check(memcmp("abce", "abcd", 3) == 0, 7);	/* Count limited. */
+  check(memcmp("abc", "def", 0) == 0, 8);	/* Zero count. */
+
+  check(memcmp("a" + 1, "a" + 1, 1) == 0, 9);	/* Unaligned tests. */
+  check(memcmp("abc" + 1, "bc", 2) == 0, 10);
+  check(memcmp("bc", "abc" + 1, 2) == 0, 11);
+  check(memcmp("abcd" + 1, "abce" + 1, 3) < 0, 12);
+  check(memcmp("abce" + 1, "abcd" + 1, 3) > 0, 13);
+/*
+  check(memcmp("a\203" + 1, "a\003" + 1, 1) > 0, 14);
+*/
+  check(memcmp("abcde" + 1, "abcdf" + 1, 3) == 0, 15);
+
+  /* Memchr */
+  it = "memchr";
+  check(memchr("abcd", 'z', 4) == NULL, 1);	/* Not found. */
+  (void) strcpy(one, "abcd");
+  check( (char *)memchr(one, 'c', 4) == one + 2, 2);	/* Basic test. */
+  check( (char *)memchr(one, 'd', 4) == one + 3, 3);	/* End of string. */
+  check( (char *)memchr(one, 'a', 4) == one, 4);	/* Beginning. */
+  check( (char *)memchr(one, '\0', 5) == one + 4, 5);	/* Finding NUL. */
+  (void) strcpy(one, "ababa");
+  check( (char *)memchr(one, 'b', 5) == one + 1, 6);	/* Finding first. */
+  check( (char *)memchr(one, 'b', 0) == NULL, 7);	/* Zero count. */
+  check( (char *)memchr(one, 'a', 1) == one, 8);	/* Singleton case. */
+  (void) strcpy(one, "a\203b");
+  check( (char *)memchr(one, 0203, 3) == one + 1, 9);	/* Unsignedness. */
+
+  /* Memcpy 
+   * Note that X3J11 says memcpy may fail on overlap. */
+  it = "memcpy";
+  check( (char *)memcpy(one, "abc", 4) == one, 1);	/* Returned value. */
+  equal(one, "abc", 2);		/* Did the copy go right? */
+
+  (void) strcpy(one, "abcdefgh");
+  (void) memcpy(one + 1, "xyz", 2);
+  equal(one, "axydefgh", 3);	/* Basic test. */
+
+  (void) strcpy(one, "abc");
+  (void) memcpy(one, "xyz", 0);
+  equal(one, "abc", 4);		/* Zero-length copy. */
+
+  (void) strcpy(one, "hi there");
+  (void) strcpy(two, "foo");
+  (void) memcpy(two, one, 9);
+  equal(two, "hi there", 5);	/* Just paranoia. */
+  equal(one, "hi there", 6);	/* Stomped on source? */
+
+  (void) strcpy(one, "abcde");	/* Unaligned tests. */
+  (void) memcpy(one + 1, "\0\0\0\0\0", 1);
+  equal(one, "a", 7);
+  equal(one + 2, "cde", 8);
+  (void) memcpy(one + 1, "xyz" + 1, 2);
+  equal(one, "ayzde", 9);
+  (void) memcpy(one + 1, "xyz" + 1, 3);
+  equal(one, "ayz", 10);
+
+  /* Memmove 
+   * Note that X3J11 says memmove must work regardless of overlap. */
+  it = "memmove";
+  check( (char *)memmove(one, "abc", 4) == one, 1);	/* Returned value. */
+  equal(one, "abc", 2);		/* Did the copy go right? */
+
+  (void) strcpy(one, "abcdefgh");
+  (void) memmove(one + 1, "xyz", 2);
+  equal(one, "axydefgh", 3);	/* Basic test. */
+
+  (void) strcpy(one, "abc");
+  (void) memmove(one, "xyz", 0);
+  equal(one, "abc", 4);		/* Zero-length copy. */
+
+  (void) strcpy(one, "hi there");
+  (void) strcpy(two, "foo");
+  (void) memmove(two, one, 9);
+  equal(two, "hi there", 5);	/* Just paranoia. */
+  equal(one, "hi there", 6);	/* Stomped on source? */
+
+  (void) strcpy(one, "abcdefgh");
+  (void) memmove(one + 1, one, 9);
+  equal(one, "aabcdefgh", 7);	/* Overlap, right-to-left. */
+
+  (void) strcpy(one, "abcdefgh");
+  (void) memmove(one + 1, one + 2, 7);
+  equal(one, "acdefgh", 8);	/* Overlap, left-to-right. */
+
+  (void) strcpy(one, "abcdefgh");
+  (void) memmove(one, one, 9);
+  equal(one, "abcdefgh", 9);	/* 100% overlap. */
+
+  (void) strcpy(one, "abcde");	/* Unaligned tests. */
+  (void) memmove(one + 1, "\0\0\0\0\0", 1);
+  equal(one, "a", 10);
+  equal(one + 2, "cde", 11);
+  (void) memmove(one + 1, "xyz" + 1, 2);
+  equal(one, "ayzde", 12);
+  (void) memmove(one + 1, "xyz" + 1, 3);
+  equal(one, "ayz", 13);
+  (void) strcpy(one, "abcdefgh");
+  (void) memmove(one + 2, one + 1, 8);
+  equal(one, "abbcdefgh", 14);
+
+  /* Memccpy - first test like memcpy, then the search part 
+   * The SVID, the only place where memccpy is mentioned, says overlap
+   * might fail, so we don't try it.  Besides, it's hard to see the
+   * rationale for a non-left-to-right memccpy. */
+  it = "memccpy";
+  check(memccpy(one, "abc", 'q', 4) == NULL, 1);	/* Returned value. */
+  equal(one, "abc", 2);		/* Did the copy go right? */
+
+  (void) strcpy(one, "abcdefgh");
+  (void) memccpy(one + 1, "xyz", 'q', 2);
+  equal(one, "axydefgh", 3);	/* Basic test. */
+
+  (void) strcpy(one, "abc");
+  (void) memccpy(one, "xyz", 'q', 0);
+  equal(one, "abc", 4);		/* Zero-length copy. */
+
+  (void) strcpy(one, "hi there");
+  (void) strcpy(two, "foo");
+  (void) memccpy(two, one, 'q', 9);
+  equal(two, "hi there", 5);	/* Just paranoia. */
+  equal(one, "hi there", 6);	/* Stomped on source? */
+
+  (void) strcpy(one, "abcdefgh");
+  (void) strcpy(two, "horsefeathers");
+  check( (char *)memccpy(two, one, 'f', 9) == two + 6, 7);/* Returned value. */
+  equal(one, "abcdefgh", 8);	/* Source intact? */
+  equal(two, "abcdefeathers", 9);	/* Copy correct? */
+
+  (void) strcpy(one, "abcd");
+  (void) strcpy(two, "bumblebee");
+  check((char *)memccpy(two, one, 'a', 4) == two + 1, 10);    /* First char. */
+  equal(two, "aumblebee", 11);
+  check((char *)memccpy(two, one, 'd', 4) == two + 4, 12);     /* Last char. */
+  equal(two, "abcdlebee", 13);
+  (void) strcpy(one, "xyz");
+  check((char *)memccpy(two, one, 'x', 1) == two + 1, 14);     /* Singleton. */
+  equal(two, "xbcdlebee", 15);
+
+  /* Memset */
+  it = "memset";
+  (void) strcpy(one, "abcdefgh");
+  check( (char *) memset(one + 1, 'x', 3) == one + 1, 1);   /* Return value. */
+  equal(one, "axxxefgh", 2);	/* Basic test. */
+
+  (void) memset(one + 2, 'y', 0);
+  equal(one, "axxxefgh", 3);	/* Zero-length set. */
+
+  (void) memset(one + 5, 0, 1);
+  equal(one, "axxxe", 4);	/* Zero fill. */
+  equal(one + 6, "gh", 5);	/* And the leftover. */
+
+  (void) memset(one + 2, 010045, 1);
+  equal(one, "ax\045xe", 6);	/* Unsigned char convert. */
+
+  /* Bcopy - much like memcpy 
+   * Berklix manual is silent about overlap, so don't test it. */
+  it = "bcopy";
+  (void) bcopy("abc", one, 4);
+  equal(one, "abc", 1);		/* Simple copy. */
+
+  (void) strcpy(one, "abcdefgh");
+  (void) bcopy("xyz", one + 1, 2);
+  equal(one, "axydefgh", 2);	/* Basic test. */
+
+  (void) strcpy(one, "abc");
+  (void) bcopy("xyz", one, 0);
+  equal(one, "abc", 3);		/* Zero-length copy. */
+
+  (void) strcpy(one, "hi there");
+  (void) strcpy(two, "foo");
+  (void) bcopy(one, two, 9);
+  equal(two, "hi there", 4);	/* Just paranoia. */
+  equal(one, "hi there", 5);	/* Stomped on source? */
+
+  /* Bzero */
+  it = "bzero";
+  (void) strcpy(one, "abcdef");
+  bzero(one + 2, 2);
+  equal(one, "ab", 1);		/* Basic test. */
+  equal(one + 3, "", 2);
+  equal(one + 4, "ef", 3);
+
+  (void) strcpy(one, "abcdef");
+  bzero(one + 2, 0);
+  equal(one, "abcdef", 4);	/* Zero-length copy. */
+
+  /* Bcmp - somewhat like memcmp */
+  it = "bcmp";
+  check(bcmp("a", "a", 1) == 0, 1);	/* Identity. */
+  check(bcmp("abc", "abc", 3) == 0, 2);	/* Multicharacter. */
+  check(bcmp("abcd", "abce", 4) != 0, 3);	/* Honestly unequal. */
+  check(bcmp("abce", "abcd", 4) != 0, 4);
+  check(bcmp("alph", "beta", 4) != 0, 5);
+  check(bcmp("abce", "abcd", 3) == 0, 6);	/* Count limited. */
+  check(bcmp("abc", "def", 0) == 0, 8);	/* Zero count. */
+
+#ifdef ERR
+  /* Strerror - VERY system-dependent */
+  it = "strerror";
+  f = open("/", O_WRONLY);	/* Should always fail. */
+  check(f < 0 && errno > 0 && errno < sys_nerr, 1);
+  equal(strerror(errno), sys_errlist[errno], 2);
+#ifdef UNIXERR
+  equal(strerror(errno), "Is a directory", 3);
+#endif
+#ifdef BERKERR
+  equal(strerror(errno), "Permission denied", 3);
+#endif
+#endif
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test16.c
===================================================================
--- /trunk/minix/test/test16.c	(revision 9)
+++ /trunk/minix/test/test16.c	(revision 9)
@@ -0,0 +1,251 @@
+/* test 16 */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utime.h>
+#include <stdio.h>
+
+#define MAX_ERROR 4
+
+int errct, subtest, passes;
+
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(void test16a, (void));
+_PROTOTYPE(void get_times, (char *name, time_t *a, time_t *c, time_t *m));
+_PROTOTYPE(void e, (int n));
+_PROTOTYPE(void quit, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m;
+
+  m = (argc == 2 ? atoi(argv[1]) : 0xFFFF);
+
+  system("rm -rf DIR_16; mkdir DIR_16");
+  chdir("DIR_16");
+
+  printf("Test 16 ");
+  fflush(stdout);
+  for (i = 0; i < 4; i++) {
+	if (m & 0001) test16a();
+	passes++;
+  }
+  quit();
+  return(-1);			/* impossible */
+}
+
+void test16a()
+{
+/* Test atime, ctime, and mtime. */
+
+  int fd, fd1, fd2, fd3, fd4;
+  time_t a, c, m, pa, pc, pm, xa, xc, xm, ya, yc, ym, za, zc, zm, ta, tc, tm;
+  time_t wa, wc, wm;
+  char buf[1024];
+  struct stat s;
+
+  subtest = 1;
+  if (passes > 0) return;	/* takes too long to repeat this test */
+
+  if ( (fd = creat("T16.a", 0666)) < 0) e(1);
+  if (write(fd, buf, 1024) != 1024) e(2);
+  if (close(fd) < 0) e(3);
+  sleep(1);			/* wait 1 sec before continuing */
+  if ( (fd = open("T16.a", O_RDONLY)) < 0) e(4);
+  if (read(fd, buf, 3) != 3) e(5);
+  if (close(fd) != 0) e(6);
+  if (stat("T16.a", &s) != 0) e(7);
+  a = s.st_atime;
+  c = s.st_ctime;
+  m = s.st_mtime;
+  if (a == 0) {
+	/* Almost certainly means we are running a V1 file system. */
+	printf(" (atime = 0. Probably V1 file system.  V2 tests skipped.) ");
+	return;
+  }
+
+  /* Many system calls affect atime, ctime, and mtime.  Test them.  They
+   * fall into several groups.  The members of each group can be tested
+   * together.  Start with creat(), mkdir(), and mkfifo, all of which
+   * set all 3 times on the created object, and ctime and mtime of the dir.
+   */
+  if ( (fd = creat("T16.b", 0666)) < 0) e(8);
+  if (close(fd) != 0) e(9);
+  get_times("T16.b", &a, &c, &m);
+  get_times(".", &pa, &pc, &pm);
+  if (a != c) e(10);
+  if (a != m) e(11);
+  if (a != pc) e(12);
+  if (a != pm) e(13);
+  if (unlink("T16.b") < 0) e(14);
+
+  /* Test the times for mkfifo. */
+  if  ( (fd = mkfifo("T16.c", 0666)) != 0) e(15);
+  if (access("T16.c", R_OK | W_OK) != 0) e(16);
+  get_times("T16.c", &a, &c, &m);
+  get_times(".", &pa, &pc, &pm);
+  if (a != c) e(17);
+  if (a != m) e(18);
+  if (a != pc) e(19);
+  if (a != pm) e(20);
+  if (unlink("T16.c") < 0) e(21);
+
+  /* Test the times for mkdir. */
+  if (mkdir("T16.d", 0666) < 0) e(22);
+  get_times("T16.d", &a, &c, &m);
+  get_times(".", &pa, &pc, &pm);
+  if (a != c) e(23);
+  if (a != m) e(24);
+  if (a != pc) e(25);
+  if (a != pm) e(26);
+  sleep(1);
+  if (rmdir("T16.d") < 0) e(27);
+  get_times(".", &xa, &xc, &xm);
+  if (c == xc) e(28);
+  if (m == xm) e(29);
+  if (xc != xm) e(30);
+
+  /* Test open(file, O_TRUNC). */
+  if ( (fd = open("T16.e", O_WRONLY|O_CREAT, 0666)) < 0) e(31);
+  if (write(fd, buf, 1024) != 1024) e(32);
+  if (close(fd) != 0) e(33);
+  get_times("T16.e", &a, &c, &m);
+  get_times(".", &pa, &pc, &pm);
+  sleep(1);
+  if ( (fd = open("T16.e", O_WRONLY|O_TRUNC)) < 0) e(34);
+  get_times("T16.e", &xa, &xc, &xm);
+  get_times(".", &ya, &yc, &ym);
+  if (c != m) e(35);
+  if (pc != pm) e(36);
+  if (c == xc) e(37);
+  if (m == xm) e(38);
+  if (yc != pc) e(39);
+  if (ym != pm) e(40);
+  if (close(fd) != 0) e(41);
+
+  /* Test the times for link/unlink. */
+  get_times("T16.e", &a, &c, &m);
+  get_times(".", &ya, &yc, &ym);
+  sleep(1);
+  if (link("T16.e", "T16.f") != 0) e(42);	/* second link */
+  get_times("T16.e", &xa, &xc, &xm);
+  get_times(".", &pa, &pc, &pm);
+  if (a != xa) e(43);
+  if (m != xm) e(44);
+#ifndef V1_FILESYSTEM
+  if (c == xc) e(45);
+#endif
+  if (ya != pa) e(46);
+  if (yc == pc) e(47);
+  if (ym == pm) e(48);
+  if (yc != ym) e(49);
+  if (pc != pm) e(50);
+  sleep(1);
+  if (unlink("T16.f") != 0) e(46);
+  get_times("T16.e", &a, &c, &m);
+  get_times(".", &ya, &yc, &ym);
+  if (a != xa) e(51);
+  if (m != xm) e(52);
+#ifndef V1_FILESYSTEM
+  if (c == xc) e(53);
+#endif
+  if (pa != ya) e(54);
+  if (pc == yc) e(55);
+  if (pm == ym) e(56);
+  if (yc != ym) e(57);
+  if (unlink("T16.e") != 0) e(58);
+
+  /* Test rename, read, write, chmod, utime. */
+  get_times(".", &pa, &pc, &pm);
+  if ( (fd  = open("T16.g", O_RDWR|O_CREAT)) < 0) e(59);
+  if ( (fd1 = open("T16.h", O_WRONLY|O_CREAT, 0666)) < 0) e(60);
+  if ( (fd2 = open("T16.i", O_WRONLY|O_CREAT, 0666)) < 0) e(61);
+  if ( (fd3 = open("T16.j", O_WRONLY|O_CREAT, 0666)) < 0) e(62);
+  if ( (fd4 = open("T16.k", O_RDWR|O_CREAT, 0666)) < 0) e(63);
+  if (write(fd, buf, 1024) != 1024) e(64);
+  get_times("T16.g", &a, &c, &m);
+  get_times("T16.h", &pa, &pc, &pm);
+  get_times("T16.i", &xa, &xc, &xm);
+  get_times("T16.j", &ya, &yc, &ym);
+  get_times("T16.k", &za, &zc, &zm);
+  get_times(".", &wa, &wc, &wm);
+  sleep(1);
+  lseek(fd, 0L, SEEK_SET);
+  if (read(fd, buf, 35) != 35) e(65);
+  get_times("T16.g", &ta, &tc, &tm);
+  if (a == ta || c != tc || m != tm) e(66);
+  if (write(fd1, buf, 35) != 35) e(67);
+  get_times("T16.h", &ta, &tc, &tm);
+  if (pa != ta || pc == tc || pm == tm) e(69);
+  if (rename("T16.i", "T16.i1") != 0) e(70);
+  get_times("T16.i1", &ta, &tc, &tm);
+  if (xa != ta || xc != tc || xm != tm) e(71);
+  get_times(".", &a, &c, &m);
+  if (a != wa || c == wc || m == wm || wc != wm) e(72);
+  if (chmod("T16.j", 0777) != 0) e(73);
+  get_times("T16.j", &ta, &tc, &tm);
+  if (ya != ta || yc == tc || ym != tm) e(74);
+  if (utime("T16.k", (void *) 0) != 0) e(75);
+  get_times("T16.k", &ta, &tc, &tm);
+  if (za == ta || zc == tc) e(76);
+  if (close(fd) != 0) e(77);
+  if (close(fd1) != 0) e(78);
+  if (close(fd2) != 0) e(79);
+  if (close(fd3) != 0) e(80);
+  if (close(fd4) != 0) e(81);
+  if (unlink("T16.g") != 0) e(82); 
+  if (unlink("T16.h") != 0) e(83); 
+  if (unlink("T16.i1") != 0) e(84); 
+  if (unlink("T16.j") != 0) e(85); 
+  if (unlink("T16.k") != 0) e(86); 
+}
+
+void get_times(name, a, c, m)
+char *name;
+time_t *a, *c, *m;
+{
+  struct stat s;
+
+  if (stat(name, &s) != 0) e(500);
+  *a = s.st_atime;
+  *c = s.st_ctime;
+  *m = s.st_mtime;
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* save errno in case printf clobbers it */
+
+  printf("Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
+  errno = err_num;		/* restore errno, just in case */
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
+
Index: /trunk/minix/test/test17.c
===================================================================
--- /trunk/minix/test/test17.c	(revision 9)
+++ /trunk/minix/test/test17.c	(revision 9)
@@ -0,0 +1,1163 @@
+/* Comment on usage and program: ark!/mnt/rene/prac/os/unix/comment.changes */
+
+/* "const.h", created by Rene Montsma and Menno Wilcke */
+
+#include <sys/types.h>		/* type defs */
+#include <sys/stat.h>		/* struct stat */
+#include <sys/wait.h>
+#include <errno.h>		/* the error-numbers */
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utime.h>
+#include <stdio.h>
+#include <limits.h>
+
+#define NOCRASH 1		/* test11(), 2nd pipe */
+#define PDPNOHANG  1		/* test03(), write_standards() */
+#define MAXERR 2
+
+#define USER_ID   12
+#define GROUP_ID   1
+#define FF        3		/* first free filedes. */
+#define USER      1		/* uid */
+#define GROUP     0		/* gid */
+
+#define ARSIZE   256		/* array size */
+#define PIPESIZE 3584		/* max number of bytes to be written on pipe */
+#define MAXOPEN  (OPEN_MAX-3)		/* maximum number of extra open files */
+#define MAXLINK 0177		/* maximum number of links per file */
+#define LINKCOUNT 5
+#define MASK    0777		/* selects lower nine bits */
+#define END_FILE     0		/* returned by read-call at eof */
+
+#define OK      0
+#define FAIL   -1
+
+#define R       0		/* read (open-call) */
+#define W       1		/* write (open-call) */
+#define RW      2		/* read & write (open-call) */
+
+#define RWX     7		/* read & write & execute (mode) */
+
+#define NIL     ""
+#define UMASK   "umask"
+#define CREAT   "creat"
+#define WRITE   "write"
+#define READ    "read"
+#define OPEN    "open"
+#define CLOSE   "close"
+#define LSEEK   "lseek"
+#define ACCESS  "access"
+#define CHDIR   "chdir"
+#define CHMOD   "chmod"
+#define LINK    "link"
+#define UNLINK  "unlink"
+#define PIPE    "pipe"
+#define STAT    "stat"
+#define FSTAT   "fstat"
+#define DUP     "dup"
+#define UTIME   "utime"
+
+int errct;
+
+char *file[];
+char *fnames[];
+char *dir[];
+
+/* "decl.c", created by Rene Montsma and Menno Wilcke */
+
+/* Used in open_alot, close_alot */
+char *file[20] = {"f0", "f1", "f2", "f3", "f4", "f5", "f6",
+	  "f7", "f8", "f9", "f10", "f11", "f12", "f13",
+	  "f14", "f15", "f16", "f17", "f18", "f19"}, *fnames[8] = {"---", "--x", "-w-", "-wx", "r--",
+								   "r-x", "rw-", "rwx"}, *dir[8] = {"d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x",
+						    "drw-", "drwx"};
+ /* Needed for easy creating and deleting of directories */
+
+/* "test.c", created by Rene Montsma and Menno Wilcke */
+
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(void test, (int mask));
+_PROTOTYPE(void test01, (void));
+_PROTOTYPE(void test02, (void));
+_PROTOTYPE(void test08, (void));
+_PROTOTYPE(void test09, (void));
+_PROTOTYPE(void test10, (void));
+_PROTOTYPE(int link_alot, (char *bigboss));
+_PROTOTYPE(int unlink_alot, (int number));
+_PROTOTYPE(void get_new, (char name []));
+_PROTOTYPE(void test11, (void));
+_PROTOTYPE(void comp_stats, (struct stat *stbf1, struct stat *stbf2));
+_PROTOTYPE(void comp_inodes, (int m, int m1));
+_PROTOTYPE(void e, (char *string));
+_PROTOTYPE(void nlcr, (void));
+_PROTOTYPE(void str, (char *s));
+_PROTOTYPE(void err, (int number, char *scall, char *name));
+_PROTOTYPE(void make_and_fill_dirs, (void));
+_PROTOTYPE(void put_file_in_dir, (char *dirname, int mode));
+_PROTOTYPE(void init_array, (char *a));
+_PROTOTYPE(void clear_array, (char *b));
+_PROTOTYPE(int comp_array, (char *a, char *b, int range));
+_PROTOTYPE(void try_close, (int filedes, char *name));
+_PROTOTYPE(void try_unlink, (char *fname));
+_PROTOTYPE(void Remove, (int fdes, char *fname));
+_PROTOTYPE(int get_mode, (char *name));
+_PROTOTYPE(void check, (char *scall, int number));
+_PROTOTYPE(void put, (int nr));
+_PROTOTYPE(int open_alot, (void));
+_PROTOTYPE(int close_alot, (int number));
+_PROTOTYPE(void clean_up_the_mess, (void));
+_PROTOTYPE(void chmod_8_dirs, (int sw));
+_PROTOTYPE(void quit, (void));
+
+/*****************************************************************************
+ *                              TEST                                         *
+ ****************************************************************************/
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int n, mask;
+
+  sync();
+  if (geteuid() == 0 || getuid() == 0) {
+	printf("Test 17 cannot run as root; test aborted\n");
+	exit(1);
+  }
+
+  system("rm -rf DIR_18; mkdir DIR_18");
+  chdir("DIR_18");
+
+  mask = (argc == 2 ? atoi(argv[1]) : 0xFFFF);
+
+  if (fork()) {
+	printf("Test 17 ");
+	fflush(stdout);
+
+	wait(&n);
+	clean_up_the_mess();
+	quit();
+  } else {
+	test(mask);
+	exit(0);
+  }
+  return(-1);			/* impossible */
+}
+
+void test(mask)
+int mask;
+{
+  umask(0);			/* not honest, but i always forget */
+
+  if (mask & 00001) test01();
+  if (mask & 00002) make_and_fill_dirs();
+  if (mask & 00004) test02();
+  if (mask & 00010) test08();
+  if (mask & 00020) test09();
+  if (mask & 00040) test10();
+  if (mask & 00100) test11();
+  umask(022);
+}				/* test */
+
+/* "t1.c" created by Rene Montsma and Menno Wilcke */
+
+/*****************************************************************************
+ *                              test UMASK                                   *
+ ****************************************************************************/
+void test01()
+{
+  int oldvalue, newvalue, tempvalue;
+  int nr;
+
+  if ((oldvalue = umask(0777)) != 0) err(0, UMASK, NIL);
+
+  /* Special test: only the lower 9 bits (protection bits) may part- *
+   * icipate. ~0777 means: 111 000 000 000. Giving this to umask must*
+   * not change any value.                                           */
+
+  if ((newvalue = umask(~0777)) != 0777) err(1, UMASK, "illegal");
+  if (oldvalue == newvalue) err(11, UMASK, "not change mask");
+
+  if ((tempvalue = umask(0)) != 0) err(2, UMASK, "values");
+
+  /* Now test all possible modes of umask on a file */
+  for (newvalue = MASK; newvalue >= 0; newvalue -= 0111) {
+	tempvalue = umask(newvalue);
+	if (tempvalue != oldvalue) {
+		err(1, UMASK, "illegal");
+		break;		/* no use trying more */
+	} else if ((nr = creat("file01", 0777)) < 0)
+		err(5, CREAT, "'file01'");
+	else {
+		try_close(nr, "'file01'");
+		if (get_mode("file01") != (MASK & ~newvalue))
+			err(7, UMASK, "mode computed");
+		try_unlink("file01");
+	}
+	oldvalue = newvalue;
+  }
+
+  /* The loop has terminated with umask(0) */
+  if ((tempvalue = umask(0)) != 0)
+	err(7, UMASK, "umask may influence rest of tests!");
+}				/* test01 */
+
+/*****************************************************************************
+ *                              test CREAT                                   *
+ ****************************************************************************/
+void test02()
+{
+  int n, n1, mode;
+  char a[ARSIZE], b[ARSIZE];
+  struct stat stbf1;
+
+  mode = 0;
+  /* Create twenty files, check filedes */
+  for (n = 0; n < MAXOPEN; n++) {
+	if (creat(file[n], mode) != FF + n)
+		err(13, CREAT, file[n]);
+	else {
+		if (get_mode(file[n]) != mode)
+			err(7, CREAT, "mode set while creating many files");
+
+		/* Change  mode of file to standard mode, we want to *
+		 * use a lot (20) of files to be opened later, see   *
+		 * open_alot(), close_alot().                        */
+		if (chmod(file[n], 0700) != OK) err(5, CHMOD, file[n]);
+
+	}
+	mode = (mode + 0100) % 01000;
+  }
+
+  /* Already twenty files opened; opening another has to fail */
+  if (creat("file02", 0777) != FAIL)
+	err(9, CREAT, "created");
+  else
+	check(CREAT, EMFILE);
+
+  /* Close all files: seems blunt, but it isn't because we've  *
+   * checked all fd's already                                  */
+  if ((n = close_alot(MAXOPEN)) < MAXOPEN) err(5, CLOSE, "MAXOPEN files");
+
+  /* Creat 1 file twice; check */
+  if ((n = creat("file02", 0777)) < 0)
+	err(5, CREAT, "'file02'");
+  else {
+	init_array(a);
+	if (write(n, a, ARSIZE) != ARSIZE) err(1, WRITE, "bad");
+
+	if ((n1 = creat("file02", 0755)) < 0)	/* receate 'file02' */
+		err(5, CREAT, "'file02' (2nd time)");
+	else {
+		/* Fd should be at the top after recreation */
+		if (lseek(n1, 0L, SEEK_END) != 0)
+			err(11, CREAT, "not truncate file by recreation");
+		else {
+			/* Try to write on recreated file */
+			clear_array(b);
+
+			if (lseek(n1, 0L, SEEK_SET) != 0)
+				err(5, LSEEK, "to top of 2nd fd 'file02'");
+			if (write(n1, a, ARSIZE) != ARSIZE)
+				err(1, WRITE, "(2) bad");
+
+			/* In order to read we've to close and open again */
+			try_close(n1, "'file02'  (2nd creation)");
+			if ((n1 = open("file02", RW)) < 0)
+				err(5, OPEN, "'file02'  (2nd recreation)");
+
+			/* Continue */
+			if (lseek(n1, 0L, SEEK_SET) != 0)
+				err(5, LSEEK, "to top 'file02'(2nd fd) (2)");
+			if (read(n1, b, ARSIZE) != ARSIZE)
+				err(1, READ, "wrong");
+
+			if (comp_array(a, b, ARSIZE) != OK) err(11, CREAT,
+				    "not really truncate file by recreation");
+		}
+		if (get_mode("file02") != 0777)
+			err(11, CREAT, "not maintain mode by recreation");
+		try_close(n1, "recreated 'file02'");
+
+	}
+	Remove(n, "file02");
+  }
+
+  /* Give 'creat' wrong input: dir not searchable */
+  if (creat("drw-/file02", 0777) != FAIL)
+	err(4, CREAT, "'drw-'");
+  else
+	check(CREAT, EACCES);
+
+  /* Dir not writable */
+  if (creat("dr-x/file02", 0777) != FAIL)
+	err(12, CREAT, "'dr-x/file02'");
+  else
+	check(CREAT, EACCES);
+
+  /* File not writable */
+  if (creat("drwx/r-x", 0777) != FAIL)
+	err(11, CREAT, "recreate non-writable file");
+  else
+	check(CREAT, EACCES);
+
+  /* Try to creat a dir */
+  if ((n = creat("dir", 040777)) != FAIL) {
+	if (fstat(n, &stbf1) != OK)
+		err(5, FSTAT, "'dir'");
+	else if (stbf1.st_mode != (mode_t) 0100777)
+				/* cast because mode is negative :-( */
+		err(11, CREAT, "'creat' a new directory");
+	Remove(n, "dir");
+  }
+
+  /* We don't consider it to be a bug when creat * does not accept
+   * tricky modes                */
+
+  /* File is an existing dir */
+  if (creat("drwx", 0777) != FAIL)
+	err(11, CREAT, "create an existing dir!");
+  else
+	check(CREAT, EISDIR);
+}				/* test02 */
+
+void test08()
+{
+  /* Test chdir to searchable dir */
+  if (chdir("drwx") != OK)
+	err(5, CHDIR, "to accessible dir");
+  else if (chdir("..") != OK)
+	err(11, CHDIR, "not return to '..'");
+
+  /* Check the chdir(".") and chdir("..") mechanism */
+  if (chdir("drwx") != OK)
+	err(5, CHDIR, "to 'drwx'");
+  else {
+	if (chdir(".") != OK) err(5, CHDIR, "to working dir (.)");
+
+	/* If we still are in 'drwx' , we should be able to access *
+	 * file 'rwx'.                                              */
+	if (access("rwx", 0) != OK) err(5, CHDIR, "rightly to '.'");
+
+	/* Try to return to previous dir ('/' !!) */
+	if (chdir("././../././d--x/../d--x/././..") != OK)
+		err(5, CHDIR, "to motherdir (..)");
+
+	/* Check whether we are back in '/' */
+	if (chdir("d--x") != OK) err(5, CHDIR, "rightly to  a '..'");
+  }
+
+  /* Return to '..' */
+  if (chdir("..") != OK) err(5, CHDIR, "to '..'");
+
+  if (chdir("././././drwx") != OK)
+	err(11, CHDIR, "not follow a path");
+  else if (chdir("././././..") != OK)
+	err(11, CHDIR, "not return to path");
+
+  /* Try giving chdir wrong parameters */
+  if (chdir("drwx/rwx") != FAIL)
+	err(11, CHDIR, "chdir to a file");
+  else
+	check(CHDIR, ENOTDIR);
+
+  if (chdir("drw-") != FAIL)
+	err(4, CHDIR, "'/drw-'");
+  else
+	check(CHDIR, EACCES);
+
+  /* To be sure: return to root */
+  /* If (chdir("/") != OK) err(5, CHDIR, "to '/' (2nd time)"); */
+}				/* test08 */
+
+/* New page */
+
+/*****************************************************************************
+ *                              test CHMOD                                   *
+ ****************************************************************************/
+void test09()
+{
+  int n;
+
+  /* Prepare file09 */
+  if ((n = creat("drwx/file09", 0644)) != FF) err(5, CREAT, "'drwx/file09'");
+
+  try_close(n, "'file09'");
+
+  /* Try to chmod a file, check and restore old values, check */
+  if (chmod("drwx/file09", 0700) != OK)
+	err(5, CHMOD, "'drwx/file09'");	/* set rwx */
+  else {
+	/* Check protection */
+	if (get_mode("drwx/file09") != 0700) err(7, CHMOD, "mode");
+
+	/* Test if chmod accepts just filenames too */
+	if (chdir("drwx") != OK)
+		err(5, CHDIR, "to '/drwx'");
+	else if (chmod("file09", 0177) != OK)	/* restore oldies */
+		err(5, CHMOD, "'h1'");
+	else
+		/* Check if value has been restored */
+	if (get_mode("../drwx/file09") != 0177)
+		err(7, CHMOD, "restored mode");
+  }
+
+  /* Try setuid and setgid */
+  if ((chmod("file09", 04777) != OK) || (get_mode("file09") != 04777))
+	err(11, CHMOD, "not set uid-bit");
+  if ((chmod("file09", 02777) != OK) || (get_mode("file09") != 02777))
+	err(11, CHMOD, "not set gid-bit");
+
+  /* Remove testfile */
+  try_unlink("file09");
+
+  if (chdir("..") != OK) err(5, CHDIR, "to '..'");
+
+  /* Try to chmod directory */
+  if (chmod("d---", 0777) != OK)
+	err(5, CHMOD, "dir 'd---'");
+  else {
+	if (get_mode("d---") != 0777) err(7, CHMOD, "protection value");
+	if (chmod("d---", 0000) != OK) err(5, CHMOD, "dir 'a' 2nd time");
+
+	/* Check if old value has been restored */
+	if (get_mode("d---") != 0000)
+		err(7, CHMOD, "restored protection value");
+  }
+
+  /* Try to make chmod failures */
+
+  /* We still are in dir root */
+  /* Wrong filename */
+  if (chmod("non-file", 0777) != FAIL)
+	err(3, CHMOD, NIL);
+  else
+	check(CHMOD, ENOENT);
+
+}				/* test 09 */
+
+/* New page */
+
+
+/* "t4.c", created by Rene Montsma and Menno Wilcke */
+
+/*****************************************************************************
+ *                              test LINK/UNLINK                             *
+ ****************************************************************************/
+void test10()
+{
+  int n, n1;
+  char a[ARSIZE], b[ARSIZE], *f, *lf;
+
+  f = "file10";
+  lf = "linkfile10";
+
+  if ((n = creat(f, 0702)) != FF)	/* no other open files */
+	err(13, CREAT, f);
+  else {
+	/* Now link correctly */
+	if (link(f, lf) != OK)
+		err(5, LINK, lf);
+	else if ((n1 = open(lf, RW)) < 0)
+		err(5, OPEN, "'linkfile10'");
+	else {
+		init_array(a);
+		clear_array(b);
+
+		/* Write on 'file10' means being able to    * read
+		 * through linked filedescriptor       */
+		if (write(n, a, ARSIZE) != ARSIZE) err(1, WRITE, "bad");
+		if (read(n1, b, ARSIZE) != ARSIZE) err(1, READ, "bad");
+		if (comp_array(a, b, ARSIZE) != OK) err(8, "r/w", NIL);
+
+		/* Clean up: unlink and close (twice): */
+		Remove(n, f);
+		try_close(n1, "'linkfile10'");
+
+		/* Check if "linkfile" exists and the info    * on it
+		 * is correct ('file' has been deleted) */
+		if ((n1 = open(lf, R)) < 0)
+			err(5, OPEN, "'linkfile10'");
+		else {
+			/* See if 'linkfile' still contains 0..511 ? */
+
+			clear_array(b);
+			if (read(n1, b, ARSIZE) != ARSIZE)
+				err(1, READ, "bad");
+			if (comp_array(a, b, ARSIZE) != OK)
+				err(8, "r/w", NIL);
+
+			try_close(n1, "'linkfile10' 2nd time");
+			try_unlink(lf);
+		}
+	}
+  }
+
+  /* Try if unlink fails with incorrect parameters */
+  /* File does not exist: */
+  if (unlink("non-file") != FAIL)
+	err(2, UNLINK, "name");
+  else
+	check(UNLINK, ENOENT);
+
+  /* Dir can't be written */
+  if (unlink("dr-x/rwx") != FAIL)
+	err(11, UNLINK, "could unlink in non-writable dir.");
+  else
+	check(UNLINK, EACCES);
+
+  /* Try to unlink a dir being user */
+  if (unlink("drwx") != FAIL)
+	err(11, UNLINK, "unlink dir's as user");
+  else
+	check(UNLINK, EPERM);
+
+  /* Try giving link wrong input */
+
+  /* First try if link fails with incorrect parameters * name1 does not
+   * exist.                             */
+  if (link("non-file", "linkfile") != FAIL)
+	err(2, LINK, "1st name");
+  else
+	check(LINK, ENOENT);
+
+  /* Name2 exists already */
+  if (link("drwx/rwx", "drwx/rw-") != FAIL)
+	err(2, LINK, "2nd name");
+  else
+	check(LINK, EEXIST);
+
+  /* Directory of name2 not writable:  */
+  if (link("drwx/rwx", "dr-x/linkfile") != FAIL)
+	err(11, LINK, "link non-writable  file");
+  else
+	check(LINK, EACCES);
+
+  /* Try to link a dir, being a user */
+  if (link("drwx", "linkfile") != FAIL)
+	err(11, LINK, "link a dir without superuser!");
+  else
+	check(LINK, EPERM);
+
+  /* File has too many links */
+  if ((n = link_alot("drwx/rwx")) != LINKCOUNT - 1)	/* file already has one
+							 * link */
+	err(5, LINK, "many files");
+  if (unlink_alot(n) != n) err(5, UNLINK, "all linked files");
+
+}				/* test10 */
+
+int link_alot(bigboss)
+char *bigboss;
+{
+  int i;
+  static char employee[6] = "aaaaa";
+
+  /* Every file has already got 1 link, so link 0176 times */
+  for (i = 1; i < LINKCOUNT; i++) {
+	if (link(bigboss, employee) != OK)
+		break;
+	else
+		get_new(employee);
+  }
+
+  return(i - 1);		/* number of linked files */
+}				/* link_alot */
+
+int unlink_alot(number)
+int number;			/* number of files to be unlinked */
+{
+  int j;
+  static char employee[6] = "aaaaa";
+
+  for (j = 0; j < number; j++) {
+	if (unlink(employee) != OK)
+		break;
+	else
+		get_new(employee);
+  }
+
+  return(j);			/* return number of unlinked files */
+}				/* unlink_alot */
+
+void get_new(name)
+char name[];
+ /* Every call changes string 'name' to a string alphabetically          *
+  * higher. Start with "aaaaa", next value: "aaaab" .                    *
+  * N.B. after "aaaaz" comes "aaabz" and not "aaaba" (not needed).       *
+  * The last possibility will be "zzzzz".                                *
+  * Total # possibilities: 26+25*4 = 126 = MAXLINK -1 (exactly needed)   */
+{
+  int i;
+
+  for (i = 4; i >= 0; i--)
+	if (name[i] != 'z') {
+		name[i]++;
+		break;
+	}
+}				/* get_new */
+
+/* New page */
+
+
+/*****************************************************************************
+ *                              test PIPE                                    *
+ ****************************************************************************/
+void test11()
+{
+  int n, fd[2];
+  char a[ARSIZE], b[ARSIZE];
+
+  if (pipe(fd) != OK)
+	err(13, PIPE, NIL);
+  else {
+	/* Try reading and writing on a pipe */
+	init_array(a);
+	clear_array(b);
+
+	if (write(fd[1], a, ARSIZE) != ARSIZE)
+		err(5, WRITE, "on pipe");
+	else if (read(fd[0], b, (ARSIZE / 2)) != (ARSIZE / 2))
+		err(5, READ, "on pipe (2nd time)");
+	else if (comp_array(a, b, (ARSIZE / 2)) != OK)
+		err(7, PIPE, "values read/written");
+	else if (read(fd[0], b, (ARSIZE / 2)) != (ARSIZE / 2))
+		err(5, READ, "on pipe 2");
+	else if (comp_array(&a[ARSIZE / 2], b, (ARSIZE / 2)) != OK)
+		err(7, PIPE, "pipe created");
+
+	/* Try to let the pipe make a mistake */
+	if (write(fd[0], a, ARSIZE) != FAIL)
+		err(11, WRITE, "write on fd[0]");
+	if (read(fd[1], b, ARSIZE) != FAIL) err(11, READ, "read on fd[1]");
+
+	try_close(fd[1], "'fd[1]'");
+
+	/* Now we shouldn't be able to read, because fd[1] has been closed */
+	if (read(fd[0], b, ARSIZE) != END_FILE) err(2, PIPE, "'fd[1]'");
+
+	try_close(fd[0], "'fd[0]'");
+  }
+  if (pipe(fd) < 0)
+	err(5, PIPE, "2nd time");
+  else {
+	/* Test lseek on a pipe: should fail */
+	if (write(fd[1], a, ARSIZE) != ARSIZE)
+		err(5, WRITE, "on pipe (2nd time)");
+	if (lseek(fd[1], 10L, SEEK_SET) != FAIL)
+		err(11, LSEEK, "lseek on a pipe");
+	else
+		check(PIPE, ESPIPE);
+
+	/* Eat half of the pipe: no writing should be possible */
+	try_close(fd[0], "'fd[0]'  (2nd time)");
+
+	/* This makes UNIX crash: omit it if pdp or VAX */
+#ifndef NOCRASH
+	if (write(fd[1], a, ARSIZE) != FAIL)
+		err(11, WRITE, "write on wrong pipe");
+	else
+		check(PIPE, EPIPE);
+#endif
+	try_close(fd[1], "'fd[1]'  (2nd time)");
+  }
+
+  /* BUG :                                                            *
+   * Here we planned to test if we could write 4K bytes on a pipe.    *
+   * However, this was not possible to implement, because the whole   *
+   * Monix system crashed when we tried to write more then 3584 bytes *
+   * (3.5K) on a pipe. That's why we try to write only 3.5K in the    *
+   * folowing test.                                                   */
+  if (pipe(fd) < 0)
+	err(5, PIPE, "3rd time");
+  else {
+	for (n = 0; n < (PIPESIZE / ARSIZE); n++)
+		if (write(fd[1], a, ARSIZE) != ARSIZE)
+			err(5, WRITE, "on pipe (3rd time) 4K");
+	try_close(fd[1], "'fd[1]' (3rd time)");
+
+	for (n = 0; n < (PIPESIZE / ARSIZE); n++)
+		if (read(fd[0], b, ARSIZE) != ARSIZE)
+			err(5, READ, "from pipe (3rd time) 4K");
+	try_close(fd[0], "'fd[0]' (3rd time)");
+  }
+
+  /* Test opening a lot of files */
+  if ((n = open_alot()) != MAXOPEN) err(5, OPEN, "MAXOPEN files");
+  if (pipe(fd) != FAIL)
+	err(9, PIPE, "open");
+  else
+	check(PIPE, EMFILE);
+  if (close_alot(n) != n) err(5, CLOSE, "all opened files");
+}				/* test11 */
+
+/* New page */
+
+
+void comp_stats(stbf1, stbf2)
+struct stat *stbf1, *stbf2;
+{
+  if (stbf1->st_dev != stbf2->st_dev) err(7, "st/fst", "'dev'");
+  if (stbf1->st_ino != stbf2->st_ino) err(7, "st/fst", "'ino'");
+  if (stbf1->st_mode != stbf2->st_mode) err(7, "st/fst", "'mode'");
+  if (stbf1->st_nlink != stbf2->st_nlink) err(7, "st/fst", "'nlink'");
+  if (stbf1->st_uid != stbf2->st_uid) err(7, "st/fst", "'uid'");
+  if (stbf1->st_gid != stbf2->st_gid) err(7, "st/fst", "'gid'");
+  if (stbf1->st_rdev != stbf2->st_rdev) err(7, "st/fst", "'rdev'");
+  if (stbf1->st_size != stbf2->st_size) err(7, "st/fst", "'size'");
+  if (stbf1->st_atime != stbf2->st_atime) err(7, "st/fst", "'atime'");
+  if (stbf1->st_mtime != stbf2->st_mtime) err(7, "st/fst", "'mtime'");
+}				/* comp_stats */
+
+/* New page */
+
+
+/* "t5.c", created by Rene Montsma and Menno Wilcke */
+
+void comp_inodes(m, m1)
+int m, m1;			/* twee filedes's */
+{
+  struct stat stbf1, stbf2;
+
+  if (fstat(m, &stbf1) == OK)
+	if (fstat(m1, &stbf2) == OK) {
+		if (stbf1.st_ino != stbf2.st_ino)
+			err(7, DUP, "inode number");
+	} else
+		err(100, "comp_inodes", "cannot 'fstat' (m1)");
+  else
+	err(100, "comp_inodes", "cannot 'fstat' (m)");
+}				/* comp_inodes */
+
+/* "support.c", created by Rene Montsma and Menno Wilcke */
+
+/* Err, make_and_fill_dirs, init_array, clear_array, comp_array,
+   try_close, try_unlink, Remove, get_mode, check, open_alot,
+   close_alot, clean_up_the_mess.
+*/
+
+/***********************************************************************
+ *				EXTENDED FIONS			       *
+ **********************************************************************/
+/* First extended functions (i.e. not oldfashioned monixcalls.
+   e(), nlcr(), octal.*/
+
+void e(string)
+char *string;
+{
+  printf("Error: %s ", string);
+}
+
+void nlcr()
+{
+  printf("\n");
+}
+
+void str(s)
+char *s;
+{
+  printf(s);
+}
+
+/*****************************************************************************
+*                                                                            *
+*                               ERR(or) messages                             *
+*                                                                            *
+*****************************************************************************/
+void err(number, scall, name)
+ /* Give nice error messages */
+
+char *scall, *name;
+int number;
+
+{
+  errct++;
+  if (errct > MAXERR) {
+	printf("Too many errors;  test aborted\n");
+	quit();
+  }
+  e("");
+  str("\t");
+  switch (number) {
+      case 0:
+	str(scall);
+	str(": illegal initial value.");
+	break;
+      case 1:
+	str(scall);
+	str(": ");
+	str(name);
+	str(" value returned.");
+	break;
+      case 2:
+	str(scall);
+	str(": accepting illegal ");
+	str(name);
+	str(".");
+	break;
+      case 3:
+	str(scall);
+	str(": accepting non-existing file.");
+	break;
+      case 4:
+	str(scall);
+	str(": could search non-searchable dir (");
+	str(name);
+	str(").");
+	break;
+      case 5:
+	str(scall);
+	str(": cannot ");
+	str(scall);
+	str(" ");
+	str(name);
+	str(".");
+	break;
+      case 7:
+	str(scall);
+	str(": incorrect ");
+	str(name);
+	str(".");
+	break;
+      case 8:
+	str(scall);
+	str(": wrong values.");
+	break;
+      case 9:
+	str(scall);
+	str(": accepting too many ");
+	str(name);
+	str(" files.");
+	break;
+      case 10:
+	str(scall);
+	str(": even a superuser can't do anything!");
+	break;
+      case 11:
+	str(scall);
+	str(": could ");
+	str(name);
+	str(".");
+	break;
+      case 12:
+	str(scall);
+	str(": could write in non-writable dir (");
+	str(name);
+	str(").");
+	break;
+      case 13:
+	str(scall);
+	str(": wrong filedes returned (");
+	str(name);
+	str(").");
+	break;
+      case 100:
+	str(scall);		/* very common */
+	str(": ");
+	str(name);
+	str(".");
+	break;
+      default:	str("errornumber does not exist!\n");
+  }
+  nlcr();
+}				/* err */
+
+/*****************************************************************************
+*                                                                            *
+*                          MAKE_AND_FILL_DIRS                                *
+*                                                                            *
+*****************************************************************************/
+
+void make_and_fill_dirs()
+ /* Create 8 dir.'s: "d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x",     *
+  * "drw-", "drwx".                                     * Then create 8 files
+  * in "drwx", and some needed files in other dirs.  */
+{
+  int mode, i;
+
+  for (i = 0; i < 8; i++) {
+	mkdir(dir[i], 0700);
+	chown(dir[i], USER_ID, GROUP_ID);
+  }
+  setuid(USER_ID);
+  setgid(GROUP_ID);
+
+  for (mode = 0; mode < 8; mode++) put_file_in_dir("drwx", mode);
+
+  put_file_in_dir("d-wx", RWX);
+  put_file_in_dir("dr-x", RWX);
+  put_file_in_dir("drw-", RWX);
+
+  chmod_8_dirs(8);		/* 8 means; 8 different modes */
+
+}				/* make_and_fill_dirs */
+
+void put_file_in_dir(dirname, mode)
+char *dirname;
+int mode;
+ /* Fill directory 'dirname' with file with mode 'mode'.   */
+{
+  int nr;
+
+  if (chdir(dirname) != OK)
+	err(5, CHDIR, "to dirname (put_f_in_dir)");
+  else {
+	/* Creat the file */
+	if ((nr = creat(fnames[mode], mode * 0100)) < 0)
+		err(13, CREAT, fnames[mode]);
+	else
+		try_close(nr, fnames[mode]);
+
+	if (chdir("..") != OK)
+		err(5, CHDIR, "to previous dir (put_f_in_dir)");
+  }
+}				/* put_file_in_dir */
+
+/*****************************************************************************
+*                                                                            *
+*                               MISCELLANEOUS                                *
+*                                                                            *
+*(all about arrays, 'try_close', 'try_unlink', 'Remove', 'get_mode')*
+*                                                                            *
+*****************************************************************************/
+
+void init_array(a)
+char *a;
+{
+  int i;
+
+  i = 0;
+  while (i++ < ARSIZE) *a++ = 'a' + (i % 26);
+}				/* init_array */
+
+void clear_array(b)
+char *b;
+{
+  int i;
+
+  i = 0;
+  while (i++ < ARSIZE) *b++ = '0';
+
+}				/* clear_array */
+
+int comp_array(a, b, range)
+char *a, *b;
+int range;
+{
+  if ((range < 0) || (range > ARSIZE)) {
+	err(100, "comp_array", "illegal range");
+	return(FAIL);
+  } else {
+	while (range-- && (*a++ == *b++));
+	if (*--a == *--b)
+		return(OK);
+	else
+		return(FAIL);
+  }
+}				/* comp_array */
+
+void try_close(filedes, name)
+int filedes;
+char *name;
+{
+  if (close(filedes) != OK) err(5, CLOSE, name);
+}				/* try_close */
+
+void try_unlink(fname)
+char *fname;
+{
+  if (unlink(fname) != 0) err(5, UNLINK, fname);
+}				/* try_unlink */
+
+void Remove(fdes, fname)
+int fdes;
+char *fname;
+{
+  try_close(fdes, fname);
+  try_unlink(fname);
+}				/* Remove */
+
+int get_mode(name)
+char *name;
+{
+  struct stat stbf1;
+
+  if (stat(name, &stbf1) != OK) {
+	err(5, STAT, name);
+	return(stbf1.st_mode);	/* return a mode which will cause *
+				 * error in the calling function  *
+				 * (file/dir bit)                 */
+  } else
+	return(stbf1.st_mode & 07777);	/* take last 4 bits */
+}				/* get_mode */
+
+/*****************************************************************************
+*                                                                            *
+*                                  CHECK                                     *
+*                                                                            *
+*****************************************************************************/
+
+void check(scall, number)
+int number;
+char *scall;
+{
+  if (errno != number) {
+	e(NIL);
+	str("\t");
+	str(scall);
+	str(": bad errno-value: ");
+	put(errno);
+	str(" should have been: ");
+	put(number);
+	nlcr();
+  }
+}				/* check */
+
+void put(nr)
+int nr;
+{
+  switch (nr) {
+      case 0:	str("unused");	  	break;
+      case 1:	str("EPERM");	  	break;
+      case 2:	str("ENOENT");	  	break;
+      case 3:	str("ESRCH");	  	break;
+      case 4:	str("EINTR");	  	break;
+      case 5:	str("EIO");	  	break;
+      case 6:	str("ENXIO");	  	break;
+      case 7:	str("E2BIG");	  	break;
+      case 8:	str("ENOEXEC");	  	break;
+      case 9:	str("EBADF");	  	break;
+      case 10:	str("ECHILD");	  	break;
+      case 11:	str("EAGAIN");	  	break;
+      case 12:	str("ENOMEM");	  	break;
+      case 13:	str("EACCES");	  	break;
+      case 14:	str("EFAULT");	  	break;
+      case 15:	str("ENOTBLK");	  	break;
+      case 16:	str("EBUSY");	  	break;
+      case 17:	str("EEXIST");	  	break;
+      case 18:	str("EXDEV");	  	break;
+      case 19:	str("ENODEV");	  	break;
+      case 20:	str("ENOTDIR");	  	break;
+      case 21:	str("EISDIR");	  	break;
+      case 22:	str("EINVAL");	  	break;
+      case 23:	str("ENFILE");	  	break;
+      case 24:	str("EMFILE");	  	break;
+      case 25:	str("ENOTTY");	  	break;
+      case 26:	str("ETXTBSY");	  	break;
+      case 27:	str("EFBIG");	  	break;
+      case 28:	str("ENOSPC");	  	break;
+      case 29:	str("ESPIPE");	  	break;
+      case 30:	str("EROFS");	  	break;
+      case 31:	str("EMLINK");	  	break;
+      case 32:	str("EPIPE");	  	break;
+      case 33:	str("EDOM");	  	break;
+      case 34:	str("ERANGE");	  	break;
+  }
+}
+
+/*****************************************************************************
+*                                                                            *
+*                                ALOT-functions                              *
+*                                                                            *
+*****************************************************************************/
+
+int open_alot()
+{
+  int i;
+
+  for (i = 0; i < MAXOPEN; i++)
+	if (open(file[i], R) == FAIL) break;
+  if (i == 0) err(5, "open_alot", "at all");
+  return(i);
+}				/* open_alot */
+
+int close_alot(number)
+int number;
+{
+  int i, count = 0;
+
+  if (number > MAXOPEN)
+	err(5, "close_alot", "accept this argument");
+  else
+	for (i = FF; i < number + FF; i++)
+		if (close(i) != OK) count++;
+
+  return(number - count);	/* return number of closed files */
+}				/* close_alot */
+
+/*****************************************************************************
+*                                                                            *
+*                         CLEAN UP THE MESS                                  *
+*                                                                            *
+*****************************************************************************/
+
+void clean_up_the_mess()
+{
+  int i;
+  char dirname[6];
+
+  /* First remove 'a lot' files */
+  for (i = 0; i < MAXOPEN; i++) try_unlink(file[i]);
+
+  /* Unlink the files in dir 'drwx' */
+  if (chdir("drwx") != OK)
+	err(5, CHDIR, "to 'drwx'");
+  else {
+	for (i = 0; i < 8; i++) try_unlink(fnames[i]);
+	if (chdir("..") != OK) err(5, CHDIR, "to '..'");
+  }
+
+  /* Before unlinking files in some dirs, make them writable */
+  chmod_8_dirs(RWX);
+
+  /* Unlink files in other dirs */
+  try_unlink("d-wx/rwx");
+  try_unlink("dr-x/rwx");
+  try_unlink("drw-/rwx");
+
+  /* Unlink dirs */
+  for (i = 0; i < 8; i++) {
+	strcpy(dirname, "d");
+	strcat(dirname, fnames[i]);
+
+	/* 'dirname' contains the directoryname */
+	rmdir(dirname);
+  }
+
+  /* FINISH */
+}				/* clean_up_the_mess */
+
+void chmod_8_dirs(sw)
+int sw;				/* if switch == 8, give all different
+			 * mode,else the same mode */
+{
+  int mode;
+  int i;
+
+  if (sw == 8)
+	mode = 0;
+  else
+	mode = sw;
+
+  for (i = 0; i < 8; i++) {
+	chmod(dir[i], 040000 + mode * 0100);
+	if (sw == 8) mode++;
+  }
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test18.c
===================================================================
--- /trunk/minix/test/test18.c	(revision 9)
+++ /trunk/minix/test/test18.c	(revision 9)
@@ -0,0 +1,1279 @@
+/* test 18 */
+
+/* Comment on usage and program: ark!/mnt/rene/prac/os/unix/comment.changes */
+
+/* "const.h", created by Rene Montsma and Menno Wilcke */
+
+#include <sys/types.h>		/* needed in struct stat */
+#include <sys/stat.h>		/* struct stat */
+#include <sys/wait.h>
+#include <errno.h>		/* the error-numbers */
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <limits.h>
+
+#define NOCRASH 1		/* test11(), 2nd pipe */
+#define PDPNOHANG  1		/* test03(), write_standards() */
+#define MAXERR 5
+
+#define USER_ID   12
+#define GROUP_ID   1
+#define FF        3		/* first free filedes. */
+#define USER      1		/* uid */
+#define GROUP     0		/* gid */
+
+#define ARSIZE   256		/* array size */
+#define PIPESIZE 3584		/* maxnumber of bytes to be written on pipe */
+#define MAXOPEN  (OPEN_MAX-3)	/* maximum number of extra open files */
+#define MAXLINK 0177		/* maximum number of links per file */
+#define MASK    0777		/* selects lower nine bits */
+#define READ_EOF 0		/* returned by read-call at eof */
+
+#define OK      0
+#define FAIL   -1
+
+#define R       0		/* read (open-call) */
+#define W       1		/* write (open-call) */
+#define RW      2		/* read & write (open-call) */
+
+#define RWX     7		/* read & write & execute (mode) */
+
+#define NIL     ""
+#define UMASK   "umask"
+#define CREAT   "creat"
+#define WRITE   "write"
+#define READ    "read"
+#define OPEN    "open"
+#define CLOSE   "close"
+#define LSEEK   "lseek"
+#define ACCESS  "access"
+#define CHDIR   "chdir"
+#define CHMOD   "chmod"
+#define LINK    "link"
+#define UNLINK  "unlink"
+#define PIPE    "pipe"
+#define STAT    "stat"
+#define FSTAT   "fstat"
+#define DUP     "dup"
+#define UTIME   "utime"
+
+int errct;
+
+char *file[];
+char *fnames[];
+char *dir[];
+
+/* "decl.c", created by Rene Montsma and Menno Wilcke */
+
+/* Used in open_alot, close_alot */
+char *file[20] = {"f0", "f1", "f2", "f3", "f4", "f5", "f6",
+	  "f7", "f8", "f9", "f10", "f11", "f12", "f13",
+	  "f14", "f15", "f16", "f17", "f18", "f19"}, *fnames[8] = {"---", "--x", "-w-", "-wx", "r--",
+								   "r-x", "rw-", "rwx"}, *dir[8] = {"d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x",
+						    "drw-", "drwx"};
+ /* Needed for easy creating and deleting of directories */
+
+/* "test.c", created by Rene Montsma and Menno Wilcke */
+
+_PROTOTYPE(int main, (void));
+_PROTOTYPE(void test, (void));
+_PROTOTYPE(void test01, (void));
+_PROTOTYPE(void test02, (void));
+_PROTOTYPE(void test03, (void));
+_PROTOTYPE(void write_standards, (int filedes, char a []));
+_PROTOTYPE(void test04, (void));
+_PROTOTYPE(void read_standards, (int filedes, char a []));
+_PROTOTYPE(void read_more, (int filedes, char a []));
+_PROTOTYPE(void test05, (void));
+_PROTOTYPE(void try_open, (char *fname, int mode, int test));
+_PROTOTYPE(void test06, (void));
+_PROTOTYPE(void test07, (void));
+_PROTOTYPE(void access_standards, (void));
+_PROTOTYPE(void try_access, (char *fname, int mode, int test));
+_PROTOTYPE(void e, (char *string));
+_PROTOTYPE(void nlcr, (void));
+_PROTOTYPE(void str, (char *s));
+_PROTOTYPE(void err, (int number, char *scall, char *name));
+_PROTOTYPE(void make_and_fill_dirs, (void));
+_PROTOTYPE(void put_file_in_dir, (char *dirname, int mode));
+_PROTOTYPE(void init_array, (char *a));
+_PROTOTYPE(void clear_array, (char *b));
+_PROTOTYPE(int comp_array, (char *a, char *b, int range));
+_PROTOTYPE(void try_close, (int filedes, char *name));
+_PROTOTYPE(void try_unlink, (char *fname));
+_PROTOTYPE(void Remove, (int fdes, char *fname));
+_PROTOTYPE(int get_mode, (char *name));
+_PROTOTYPE(void check, (char *scall, int number));
+_PROTOTYPE(void put, (int nr));
+_PROTOTYPE(int open_alot, (void));
+_PROTOTYPE(int close_alot, (int number));
+_PROTOTYPE(void clean_up_the_mess, (void));
+_PROTOTYPE(void chmod_8_dirs, (int sw));
+_PROTOTYPE(void quit, (void));
+
+/*****************************************************************************
+ *                              TEST                                         *
+ ****************************************************************************/
+int main()
+{
+  int n;
+
+  if (geteuid() == 0 || getuid() == 0) {
+	printf("Test 18 cannot run as root; test aborted\n");
+	exit(1);
+  }
+
+  system("rm -rf DIR_18; mkdir DIR_18");
+  chdir("DIR_18");
+
+  if (fork()) {
+	printf("Test 18 ");
+	fflush(stdout);		/* have to flush for child's benefit */
+
+	wait(&n);
+	clean_up_the_mess();
+	quit();
+  } else {
+	test();
+	exit(0);
+  }
+
+  return(0);
+}
+
+void test()
+{
+  umask(0);			/* not honest, but i always forget */
+
+  test01();
+  make_and_fill_dirs();
+  test02();
+  test03();
+  test04();
+  test05();
+  test06();
+  test07();
+  umask(022);
+}				/* test */
+
+/* "t1.c" created by Rene Montsma and Menno Wilcke */
+
+/*****************************************************************************
+ *                              test UMASK                                   *
+ ****************************************************************************/
+void test01()
+{
+  int oldvalue, newvalue, tempvalue;
+  int nr;
+
+  if ((oldvalue = umask(0777)) != 0) err(0, UMASK, NIL);
+
+  /* Special test: only the lower 9 bits (protection bits) may part- *
+   * icipate. ~0777 means: 111 000 000 000. Giving this to umask must*
+   * not change any value.                                           */
+
+  if ((newvalue = umask(~0777)) != 0777) err(1, UMASK, "illegal");
+  if (oldvalue == newvalue) err(11, UMASK, "not change mask");
+
+  if ((tempvalue = umask(0)) != 0) err(2, UMASK, "values");
+
+  /* Now test all possible modes of umask on a file */
+  for (newvalue = MASK; newvalue >= 0; newvalue -= 0111) {
+	tempvalue = umask(newvalue);
+	if (tempvalue != oldvalue) {
+		err(1, UMASK, "illegal");
+		break;		/* no use trying more */
+	} else if ((nr = creat("file01", 0777)) < 0)
+		err(5, CREAT, "'file01'");
+	else {
+		try_close(nr, "'file01'");
+		if (get_mode("file01") != (MASK & ~newvalue))
+			err(7, UMASK, "mode computed");
+		try_unlink("file01");
+	}
+	oldvalue = newvalue;
+  }
+
+  /* The loop has terminated with umask(0) */
+  if ((tempvalue = umask(0)) != 0)
+	err(7, UMASK, "umask may influence rest of tests!");
+}				/* test01 */
+
+/*****************************************************************************
+ *                              test CREAT                                   *
+ ****************************************************************************/
+void test02()
+{
+  int n, n1, mode;
+  char a[ARSIZE], b[ARSIZE];
+  struct stat stbf1;
+
+  mode = 0;
+  /* Create twenty files, check filedes */
+  for (n = 0; n < MAXOPEN; n++) {
+	if (creat(file[n], mode) != FF + n)
+		err(13, CREAT, file[n]);
+	else {
+		if (get_mode(file[n]) != mode)
+			err(7, CREAT, "mode set while creating many files");
+
+		/* Change  mode of file to standard mode, we want to *
+		 * use a lot (20) of files to be opened later, see   *
+		 * open_alot(), close_alot().                        */
+		if (chmod(file[n], 0700) != OK) err(5, CHMOD, file[n]);
+
+	}
+	mode = (mode + 0100) % 01000;
+  }
+
+  /* Already twenty files opened; opening another has to fail */
+  if (creat("file02", 0777) != FAIL)
+	err(9, CREAT, "created");
+  else
+	check(CREAT, EMFILE);
+
+  /* Close all files: seems blunt, but it isn't because we've  *
+   * checked all fd's already                                  */
+  if ((n = close_alot(MAXOPEN)) < MAXOPEN) err(5, CLOSE, "MAXOPEN files");
+
+  /* Creat 1 file twice; check */
+  if ((n = creat("file02", 0777)) < 0)
+	err(5, CREAT, "'file02'");
+  else {
+	init_array(a);
+	if (write(n, a, ARSIZE) != ARSIZE) err(1, WRITE, "bad");
+
+	if ((n1 = creat("file02", 0755)) < 0)	/* receate 'file02' */
+		err(5, CREAT, "'file02' (2nd time)");
+	else {
+		/* Fd should be at the top after recreation */
+		if (lseek(n1, 0L, SEEK_END) != 0)
+			err(11, CREAT, "not truncate file by recreation");
+		else {
+			/* Try to write on recreated file */
+			clear_array(b);
+
+			if (lseek(n1, 0L, SEEK_SET) != 0)
+				err(5, LSEEK, "to top of 2nd fd 'file02'");
+			if (write(n1, a, ARSIZE) != ARSIZE)
+				err(1, WRITE, "(2) bad");
+
+			/* In order to read we've to close and open again */
+			try_close(n1, "'file02'  (2nd creation)");
+			if ((n1 = open("file02", RW)) < 0)
+				err(5, OPEN, "'file02'  (2nd recreation)");
+
+			/* Continue */
+			if (lseek(n1, 0L, SEEK_SET) != 0)
+				err(5, LSEEK, "to top 'file02'(2nd fd) (2)");
+			if (read(n1, b, ARSIZE) != ARSIZE)
+				err(1, READ, "wrong");
+
+			if (comp_array(a, b, ARSIZE) != OK) err(11, CREAT,
+				    "not really truncate file by recreation");
+		}
+		if (get_mode("file02") != 0777)
+			err(11, CREAT, "not maintain mode by recreation");
+		try_close(n1, "recreated 'file02'");
+
+	}
+	Remove(n, "file02");
+  }
+
+  /* Give 'creat' wrong input: dir not searchable */
+  if (creat("drw-/file02", 0777) != FAIL)
+	err(4, CREAT, "'drw-'");
+  else
+	check(CREAT, EACCES);
+
+  /* Dir not writable */
+  if (creat("dr-x/file02", 0777) != FAIL)
+	err(12, CREAT, "'dr-x/file02'");
+  else
+	check(CREAT, EACCES);
+
+  /* File not writable */
+  if (creat("drwx/r-x", 0777) != FAIL)
+	err(11, CREAT, "recreate non-writable file");
+  else
+	check(CREAT, EACCES);
+
+  /* Try to creat a dir */
+  if ((n = creat("dir", 040777)) != FAIL) {
+	if (fstat(n, &stbf1) != OK)
+		err(5, FSTAT, "'dir'");
+	else if (stbf1.st_mode != (mode_t) 0100777)
+				/* Cast because mode is negative :-(.
+				 * HACK DEBUG FIXME: this appears to duplicate
+				 * code in test17.c.
+				 */
+		err(11, CREAT, "'creat' a new directory");
+	Remove(n, "dir");
+  }
+
+  /* We don't consider it to be a bug when creat * does not accept
+   * tricky modes                */
+
+  /* File is an existing dir */
+  if (creat("drwx", 0777) != FAIL)
+	err(11, CREAT, "create an existing dir!");
+  else
+	check(CREAT, EISDIR);
+}				/* test02 */
+
+/*****************************************************************************
+ *                              test WRITE                                   *
+ ****************************************************************************/
+void test03()
+{
+  int n, n1;
+  int fd[2];
+  char a[ARSIZE];
+
+  init_array(a);
+
+  /* Test write after a CREAT */
+  if ((n = creat("file03", 0700)) != FF)	/* 'file03' only open file */
+	err(13, CREAT, "'file03'");
+  else {
+	write_standards(n, a);	/* test simple writes, wrong input too */
+	try_close(n, "'file03'");
+  }
+
+  /* Test write after an OPEN */
+  if ((n = open("file03", W)) < 0)
+	err(5, OPEN, "'file03'");
+  else
+	write_standards(n, a);	/* test simple writes, wrong input too */
+
+  /* Test write after a DUP */
+  if ((n1 = dup(n)) < 0)
+	err(5, DUP, "'file03'");
+  else {
+	write_standards(n1, a);
+	try_close(n1, "duplicated fd 'file03'");
+  }
+
+  /* Remove testfile */
+  Remove(n, "file03");
+
+  /* Test write after a PIPE */
+  if (pipe(fd) < 0)
+	err(5, PIPE, NIL);
+  else {
+	write_standards(fd[1], a);
+	try_close(fd[0], "'fd[0]'");
+	try_close(fd[1], "'fd[1]'");
+  }
+
+  /* Last test: does write check protections ? */
+  if ((n = open("drwx/r--", R)) < 0)
+	err(5, OPEN, "'drwx/r--'");
+  else {
+	if (write(n, a, ARSIZE) != FAIL)
+		err(11, WRITE, "write on non-writ. file");
+	else
+		check(WRITE, EBADF);
+	try_close(n, "'drwx/r--'");
+  }
+}				/* test03 */
+
+void write_standards(filedes, a)
+int filedes;
+char a[];
+{
+
+  /* Write must return written account of numbers */
+  if (write(filedes, a, ARSIZE) != ARSIZE) err(1, WRITE, "bad");
+
+  /* Try giving 'write' wrong input */
+  /* Wrong filedes */
+  if (write(-1, a, ARSIZE) != FAIL)
+	err(2, WRITE, "filedes");
+  else
+	check(WRITE, EBADF);
+
+  /* Wrong length (illegal) */
+#ifndef PDPNOHANG
+  if (write(filedes, a, -ARSIZE) != FAIL)
+	err(2, WRITE, "length");
+  else
+	check(WRITE, EINVAL);	/* EFAULT on vu45 */
+#endif
+}				/* write_standards */
+
+/* "t2.c", created by Rene Montsma and Menno Wilcke */
+
+/*****************************************************************************
+ *                              test READ                                    *
+ ****************************************************************************/
+void test04()
+{
+  int n, n1, fd[2];
+  char a[ARSIZE];
+
+  /* Test read after creat */
+  if ((n = creat("file04", 0700)) != FF)	/* no other open files may be
+					 * left */
+	err(13, CREAT, "'file04'");
+  else {
+	/* Closing and opening needed before writing */
+	try_close(n, "'file04'");
+	if ((n = open("file04", RW)) < 0) err(5, OPEN, "'file04'");
+
+	init_array(a);
+
+	if (write(n, a, ARSIZE) != ARSIZE)
+		err(1, WRITE, "bad");
+	else {
+		if (lseek(n, 0L, SEEK_SET) != 0) err(5, LSEEK, "'file04'");
+		read_standards(n, a);
+		read_more(n, a);
+	}
+	try_close(n, "'file04'");
+  }
+
+  /* Test read after OPEN */
+  if ((n = open("file04", R)) < 0)
+	err(5, OPEN, "'file04'");
+  else {
+	read_standards(n, a);
+	read_more(n, a);
+	try_close(n, "'file04'");
+  }
+
+  /* Test read after DUP */
+  if ((n = open("file04", R)) < 0) err(5, OPEN, "'file04'");
+  if ((n1 = dup(n)) < 0)
+	err(5, DUP, "'file04'");
+  else {
+	read_standards(n1, a);
+	read_more(n1, a);
+	try_close(n1, "duplicated fd 'file04'");
+  }
+
+  /* Remove testfile */
+  Remove(n, "file04");
+
+  /* Test read after pipe */
+  if (pipe(fd) < 0)
+	err(5, PIPE, NIL);
+  else {
+	if (write(fd[1], a, ARSIZE) != ARSIZE) {
+		err(5, WRITE, "'fd[1]'");
+		try_close(fd[1], "'fd[1]'");
+	} else {
+		try_close(fd[1], "'fd[1]'");
+		read_standards(fd[0], a);
+	}
+	try_close(fd[0], "'fd[0]'");
+  }
+
+  /* Last test: try to read a read-protected file */
+  if ((n = open("drwx/-wx", W)) < 0)
+	err(5, OPEN, "'drwx/-wx'");
+  else {
+	if (read(n, a, ARSIZE) != FAIL)
+		err(11, READ, "read a non-read. file");
+	else
+		check(READ, EBADF);
+	try_close(n, "'/drwx/-wx'");
+  }
+}				/* test04 */
+
+void read_standards(filedes, a)
+int filedes;
+char a[];
+{
+  char b[ARSIZE];
+
+  clear_array(b);
+  if (read(filedes, b, ARSIZE) != ARSIZE)
+	err(1, READ, "bad");
+  else if (comp_array(a, b, ARSIZE) != OK)
+	err(7, "read/write", "values");
+  else if (read(filedes, b, ARSIZE) != READ_EOF)
+	err(11, READ, "read beyond endoffile");
+
+  /* Try giving read wrong input: wrong filedes */
+  if (read(FAIL, b, ARSIZE) != FAIL)
+	err(2, READ, "filedes");
+  else
+	check(READ, EBADF);
+
+  /* Wrong length */
+  if (read(filedes, b, -ARSIZE) != FAIL)
+	err(2, READ, "length");
+  else
+	check(READ, EINVAL);
+}				/* read_standards */
+
+void read_more(filedes, a)
+int filedes;
+char a[];
+ /* Separated from read_standards() because the PIPE test * would fail.                                           */
+{
+  int i;
+  char b[ARSIZE];
+
+  if (lseek(filedes, (long) (ARSIZE / 2), SEEK_SET) != ARSIZE / 2)
+	err(5, LSEEK, "to location ARSIZE/2");
+
+  clear_array(b);
+  if (read(filedes, b, ARSIZE) != ARSIZE / 2) err(1, READ, "bad");
+
+  for (i = 0; i < ARSIZE / 2; i++)
+	if (b[i] != a[(ARSIZE / 2) + i])
+		err(7, READ, "from location ARSIZE/2");
+}
+
+/*****************************************************************************
+ *                              test OPEN/CLOSE                              *
+ ****************************************************************************/
+void test05()
+{
+  int n, n1, mode, fd[2];
+  char b[ARSIZE];
+
+  /* Test open after CREAT */
+  if ((n = creat("file05", 0700)) != FF)	/* no other open files left */
+	err(13, CREAT, "'file05'");
+  else {
+	if ((n1 = open("file05", RW)) != FF + 1)
+		err(13, OPEN, "'file05' after creation");
+	try_close(n1, "'file05' (open after creation)");
+
+	try_close(n, "'file05'");
+	if ((n = open("file05", R)) != FF)
+		err(13, OPEN, "after closing");
+	else
+		try_close(n, "'file05' (open after closing)");
+
+	/* Remove testfile */
+	try_unlink("file05");
+  }
+
+  /* Test all possible modes, try_open not only opens file (sometimes) *
+   * but closes files too (when opened)                                */
+  if ((n = creat("file05", 0700)) < 0)	/* no other files left */
+	err(5, CREAT, "'file05' (2nd time)");
+  else {
+	try_close(n, "file05");
+	for (mode = 0; mode <= 0700; mode += 0100) {
+		if (chmod("file05", mode) != OK) err(5, CHMOD, "'file05'");
+
+		if (mode <= 0100) {
+			try_open("file05", R, FAIL);
+			try_open("file05", W, FAIL);
+			try_open("file05", RW, FAIL);
+		} else if (mode >= 0200 && mode <= 0300) {
+			try_open("file05", R, FAIL);
+			try_open("file05", W, FF);
+			try_open("file05", RW, FAIL);
+		} else if (mode >= 0400 && mode <= 0500) {
+			try_open("file05", R, FF);
+			try_open("file05", W, FAIL);
+			try_open("file05", RW, FAIL);
+		} else {
+			try_open("file05", R, FF);
+			try_open("file05", W, FF);
+			try_open("file05", RW, FF);
+		}
+	}
+  }
+
+  /* Test opening existing file */
+  if ((n = open("drwx/rwx", R)) < 0)
+	err(13, OPEN, "existing file");
+  else {			/* test close after DUP */
+	if ((n1 = dup(n)) < 0)
+		err(13, DUP, "'drwx/rwx'");
+	else {
+		try_close(n1, "duplicated fd 'drwx/rwx'");
+
+		if (read(n1, b, ARSIZE) != FAIL)
+			err(11, READ, "on closed dupped fd 'drwx/rwx'");
+		else
+			check(READ, EBADF);
+
+		if (read(n, b, ARSIZE) == FAIL)	/* should read an eof */
+			err(13, READ, "on fd '/drwx/rwx'");
+	}
+	try_close(n, "'drwx/rwx'");
+  }
+
+  /* Test close after PIPE */
+  if (pipe(fd) < 0)
+	err(13, PIPE, NIL);
+  else {
+	try_close(fd[1], "duplicated fd 'fd[1]'");
+
+	/* Fd[1] really should be closed now; check */
+	clear_array(b);
+	if (read(fd[0], b, ARSIZE) != READ_EOF)
+		err(11, READ, "read on empty pipe (and fd[1] was closed)");
+	try_close(fd[0], "duplicated fd 'fd[0]'");
+  }
+
+  /* Try to open a non-existing file */
+  if (open("non-file", R) != FAIL)
+	err(11, OPEN, "open non-executable file");
+  else
+	check(OPEN, ENOENT);
+
+  /* Dir does not exist */
+  if (open("dzzz/file05", R) != FAIL)
+	err(11, OPEN, "open in an non-searchable dir");
+  else
+	check(OPEN, ENOENT);
+
+  /* Dir is not searchable */
+  if (n = open("drw-/rwx", R) != FAIL)
+	err(11, OPEN, "open in an non-searchabledir");
+  else
+	check(OPEN, EACCES);
+
+  /* Unlink testfile */
+  try_unlink("file05");
+
+  /* File is not readable */
+  if (open("drwx/-wx", R) != FAIL)
+	err(11, OPEN, "open unreadable file for reading");
+  else
+	check(OPEN, EACCES);
+
+  /* File is not writable */
+  if (open("drwx/r-x", W) != FAIL)
+	err(11, OPEN, "open unwritable file for writing");
+  else
+	check(OPEN, EACCES);
+
+  /* Try opening more than MAXOPEN  ('extra' (19-8-85)) files */
+  if ((n = open_alot()) != MAXOPEN)
+	err(13, OPEN, "MAXOPEN files");
+  else
+	/* Maximum # of files opened now, another open should fail
+	 * because * all filedescriptors have already been used.                      */
+  if (open("drwx/rwx", RW) != FAIL)
+	err(9, OPEN, "open");
+  else
+	check(OPEN, EMFILE);
+  if (close_alot(n) != n) err(5, CLOSE, "all opened files");
+
+  /* Can close make mistakes ? */
+  if (close(-1) != FAIL)
+	err(2, CLOSE, "filedes");
+  else
+	check(CLOSE, EBADF);
+}				/* test05 */
+
+void try_open(fname, mode, test)
+int mode, test;
+char *fname;
+{
+  int n;
+
+  if ((n = open(fname, mode)) != test)
+	err(11, OPEN, "break through filepermission with an incorrect mode");
+  if (n != FAIL) try_close(n, fname);	/* cleanup */
+}				/* try_open */
+
+/*****************************************************************************
+ *                              test LSEEK                                   *
+ ****************************************************************************/
+void test06()
+{
+  char a[ARSIZE], b[ARSIZE];
+  int fd;
+
+  if ((fd = open("drwx/rwx", RW)) != FF)	/* there should be no */
+	err(13, OPEN, "'drwx/rwx'");	/* other open files   */
+  else {
+	init_array(a);
+	if (write(fd, a, 10) != 10)
+		err(1, WRITE, "bad");
+	else {
+		/* Lseek back to begin file */
+		if (lseek(fd, 0L, SEEK_SET) != 0)
+			err(5, LSEEK, "to begin file");
+		else if (read(fd, b, 10) != 10)
+			err(1, READ, "bad");
+		else if (comp_array(a, b, 10) != OK)
+			err(7, LSEEK, "values r/w after lseek to begin");
+		/* Lseek to endoffile */
+		if (lseek(fd, 0L, SEEK_END) != 10)
+			err(5, LSEEK, "to end of file");
+		else if (read(fd, b, 1) != READ_EOF)
+			err(7, LSEEK, "read at end of file");
+		/* Lseek beyond file */
+		if (lseek(fd, 10L, SEEK_CUR) != 20)
+			err(5, LSEEK, "beyond end of file");
+		else if (write(fd, a, 10) != 10)
+			err(1, WRITE, "bad");
+		else {
+			/* Lseek to begin second write */
+			if (lseek(fd, 20L, SEEK_SET) != 20)
+				err(5, LSEEK, "'/drwx/rwx'");
+			if (read(fd, b, 10) != 10)
+				err(1, READ, "bad");
+			else if (comp_array(a, b, 10) != OK)
+				err(7, LSEEK,
+				 "values read after lseek MAXOPEN");
+		}
+	}
+
+	/* Lseek to position before begin of file */
+	if (lseek(fd, -1L, 0) != FAIL)
+		err(11, LSEEK, "lseek before beginning of file");
+
+	try_close(fd, "'drwx/rwx'");
+  }
+
+  /* Lseek on invalid filediscriptor */
+  if (lseek(-1, 0L, SEEK_SET) != FAIL)
+	err(2, LSEEK, "filedes");
+  else
+	check(LSEEK, EBADF);
+
+}
+
+/* "t3.c", created by Rene Montsma and Menno Wilcke */
+
+/*****************************************************************************
+ *                              test ACCESS                                  *
+ ****************************************************************************/
+void test07()
+{
+  /* Check with proper parameters */
+  if (access("drwx/rwx", RWX) != OK) err(5, ACCESS, "accessible file");
+
+  if (access("./././drwx/././rwx", 0) != OK)
+	err(5, ACCESS, "'/./.(etc)/drwx///rwx'");
+
+  /* Check 8 files with 8 different modes on 8 accesses  */
+  if (chdir("drwx") != OK) err(5, CHDIR, "'drwx'");
+
+  access_standards();
+
+  if (chdir("..") != OK) err(5, CHDIR, "'..'");
+
+  /* Check several wrong combinations */
+  /* File does not exist */
+  if (access("non-file", 0) != FAIL)
+	err(11, ACCESS, "access non-existing file");
+  else
+	check(ACCESS, ENOENT);
+
+  /* Non-searchable dir */
+  if (access("drw-/rwx", 0) != FAIL)
+	err(4, ACCESS, "'drw-'");
+  else
+	check(ACCESS, EACCES);
+
+  /* Searchable dir, but wrong file-mode */
+  if (access("drwx/--x", RWX) != FAIL)
+	err(11, ACCESS, "a non accessible file");
+  else
+	check(ACCESS, EACCES);
+
+}				/* test07 */
+
+void access_standards()
+{
+  int i, mode = 0;
+
+  for (i = 0; i < 8; i++)
+	if (i == 0)
+		try_access(fnames[mode], i, OK);
+	else
+		try_access(fnames[mode], i, FAIL);
+  mode++;
+
+  for (i = 0; i < 8; i++)
+	if (i < 2)
+		try_access(fnames[mode], i, OK);
+	else
+		try_access(fnames[mode], i, FAIL);
+  mode++;
+
+  for (i = 0; i < 8; i++)
+	if (i == 0 || i == 2)
+		try_access(fnames[mode], i, OK);
+	else
+		try_access(fnames[mode], i, FAIL);
+  mode++;
+
+  for (i = 0; i < 8; i++)
+	if (i < 4)
+		try_access(fnames[mode], i, OK);
+	else
+		try_access(fnames[mode], i, FAIL);
+  mode++;
+
+  for (i = 0; i < 8; i++)
+	if (i == 0 || i == 4)
+		try_access(fnames[mode], i, OK);
+	else
+		try_access(fnames[mode], i, FAIL);
+  mode++;
+
+  for (i = 0; i < 8; i++)
+	if (i == 0 || i == 1 || i == 4 || i == 5)
+		try_access(fnames[mode], i, OK);
+	else
+		try_access(fnames[mode], i, FAIL);
+  mode++;
+
+  for (i = 0; i < 8; i++)
+	if (i % 2 == 0)
+		try_access(fnames[mode], i, OK);
+	else
+		try_access(fnames[mode], i, FAIL);
+  mode++;
+
+  for (i = 0; i < 8; i++) try_access(fnames[mode], i, OK);
+}				/* access_standards */
+
+void try_access(fname, mode, test)
+int mode, test;
+char *fname;
+{
+  if (access(fname, mode) != test)
+	err(100, ACCESS, "incorrect access on a file (try_access)");
+}				/* try_access */
+
+/* "support.c", created by Rene Montsma and Menno Wilcke */
+
+/* Err, make_and_fill_dirs, init_array, clear_array, comp_array,
+   try_close, try_unlink, Remove, get_mode, check, open_alot,
+   close_alot, clean_up_the_mess.
+*/
+
+/***********************************************************************
+ *				EXTENDED FIONS			       *
+ **********************************************************************/
+/* First extended functions (i.e. not oldfashioned monixcalls.
+   e(), nlcr(), octal.*/
+
+void e(string)
+char *string;
+{
+  printf("Test program error: %s\n", string);
+  errct++;
+}
+
+void nlcr()
+{
+  printf("\n");
+}
+
+void str(s)
+char *s;
+{
+  printf(s);
+}
+
+/*****************************************************************************
+*                                                                            *
+*                               ERR(or) messages                             *
+*                                                                            *
+*****************************************************************************/
+void err(number, scall, name)
+ /* Give nice error messages */
+
+char *scall, *name;
+int number;
+
+{
+  errct++;
+  if (errct > MAXERR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	quit();
+  }
+  e("");
+  str("\t");
+  switch (number) {
+      case 0:
+	str(scall);
+	str(": illegal initial value.");
+	break;
+      case 1:
+	str(scall);
+	str(": ");
+	str(name);
+	str(" value returned.");
+	break;
+      case 2:
+	str(scall);
+	str(": accepting illegal ");
+	str(name);
+	str(".");
+	break;
+      case 3:
+	str(scall);
+	str(": accepting non-existing file.");
+	break;
+      case 4:
+	str(scall);
+	str(": could search non-searchable dir (");
+	str(name);
+	str(").");
+	break;
+      case 5:
+	str(scall);
+	str(": cannot ");
+	str(scall);
+	str(" ");
+	str(name);
+	str(".");
+	break;
+      case 7:
+	str(scall);
+	str(": incorrect ");
+	str(name);
+	str(".");
+	break;
+      case 8:
+	str(scall);
+	str(": wrong values.");
+	break;
+      case 9:
+	str(scall);
+	str(": accepting too many ");
+	str(name);
+	str(" files.");
+	break;
+      case 10:
+	str(scall);
+	str(": even a superuser can't do anything!");
+	break;
+      case 11:
+	str(scall);
+	str(": could ");
+	str(name);
+	str(".");
+	break;
+      case 12:
+	str(scall);
+	str(": could write in non-writable dir (");
+	str(name);
+	str(").");
+	break;
+      case 13:
+	str(scall);
+	str(": wrong filedes returned (");
+	str(name);
+	str(").");
+	break;
+      case 100:
+	str(scall);		/* very common */
+	str(": ");
+	str(name);
+	str(".");
+	break;
+      default:	str("errornumber does not exist!\n");
+  }
+  nlcr();
+}				/* err */
+
+/*****************************************************************************
+*                                                                            *
+*                          MAKE_AND_FILL_DIRS                                *
+*                                                                            *
+*****************************************************************************/
+
+void make_and_fill_dirs()
+ /* Create 8 dir.'s: "d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x",     *
+  * "drw-", "drwx".                                     * Then create 8 files
+  * in "drwx", and some needed files in other dirs.  */
+{
+  int mode, i;
+
+  for (i = 0; i < 8; i++) {
+	mkdir(dir[i], 0700);
+	chown(dir[i], USER_ID, GROUP_ID);
+  }
+  setuid(USER_ID);
+  setgid(GROUP_ID);
+
+  for (mode = 0; mode < 8; mode++) put_file_in_dir("drwx", mode);
+
+  put_file_in_dir("d-wx", RWX);
+  put_file_in_dir("dr-x", RWX);
+  put_file_in_dir("drw-", RWX);
+
+  chmod_8_dirs(8);		/* 8 means; 8 different modes */
+
+}				/* make_and_fill_dirs */
+
+void put_file_in_dir(dirname, mode)
+char *dirname;
+int mode;
+ /* Fill directory 'dirname' with file with mode 'mode'.   */
+{
+  int nr;
+
+  if (chdir(dirname) != OK)
+	err(5, CHDIR, "to dirname (put_f_in_dir)");
+  else {
+	/* Creat the file */
+	if ((nr = creat(fnames[mode], mode * 0100)) < 0)
+		err(13, CREAT, fnames[mode]);
+	else
+		try_close(nr, fnames[mode]);
+
+	if (chdir("..") != OK)
+		err(5, CHDIR, "to previous dir (put_f_in_dir)");
+  }
+}				/* put_file_in_dir */
+
+/*****************************************************************************
+*                                                                            *
+*                               MISCELLANEOUS                                *
+*                                                                            *
+*(all about arrays, 'try_close', 'try_unlink', 'Remove', 'get_mode')         *
+*                                                                            *
+*****************************************************************************/
+
+void init_array(a)
+char *a;
+{
+  int i;
+
+  i = 0;
+  while (i++ < ARSIZE) *a++ = 'a' + (i % 26);
+}				/* init_array */
+
+void clear_array(b)
+char *b;
+{
+  int i;
+
+  i = 0;
+  while (i++ < ARSIZE) *b++ = '0';
+
+}				/* clear_array */
+
+int comp_array(a, b, range)
+char *a, *b;
+int range;
+{
+  if ((range < 0) || (range > ARSIZE)) {
+	err(100, "comp_array", "illegal range");
+	return(FAIL);
+  } else {
+	while (range-- && (*a++ == *b++));
+	if (*--a == *--b)
+		return(OK);
+	else
+		return(FAIL);
+  }
+}				/* comp_array */
+
+void try_close(filedes, name)
+int filedes;
+char *name;
+{
+  if (close(filedes) != OK) err(5, CLOSE, name);
+}				/* try_close */
+
+void try_unlink(fname)
+char *fname;
+{
+  if (unlink(fname) != 0) err(5, UNLINK, fname);
+}				/* try_unlink */
+
+void Remove(fdes, fname)
+int fdes;
+char *fname;
+{
+  try_close(fdes, fname);
+  try_unlink(fname);
+}				/* Remove */
+
+int get_mode(name)
+char *name;
+{
+  struct stat stbf1;
+
+  if (stat(name, &stbf1) != OK) {
+	err(5, STAT, name);
+	return(stbf1.st_mode);	/* return a mode which will cause *
+				 * error in the calling function  *
+				 * (file/dir bit)                 */
+  } else
+	return(stbf1.st_mode & 07777);	/* take last 4 bits */
+}				/* get_mode */
+
+/*****************************************************************************
+*                                                                            *
+*                                  CHECK                                     *
+*                                                                            *
+*****************************************************************************/
+
+void check(scall, number)
+int number;
+char *scall;
+{
+  if (errno != number) {
+	e(NIL);
+	str("\t");
+	str(scall);
+	str(": bad errno-value: ");
+	put(errno);
+	str(" should have been: ");
+	put(number);
+	nlcr();
+  }
+}				/* check */
+
+void put(nr)
+int nr;
+{
+  switch (nr) {
+      case 0:	str("unused");	  	break;
+      case 1:	str("EPERM");	  	break;
+      case 2:	str("ENOENT");	  	break;
+      case 3:	str("ESRCH");	  	break;
+      case 4:	str("EINTR");	  	break;
+      case 5:	str("EIO");	  	break;
+      case 6:	str("ENXIO");	  	break;
+      case 7:	str("E2BIG");	  	break;
+      case 8:	str("ENOEXEC");	  	break;
+      case 9:	str("EBADF");	  	break;
+      case 10:	str("ECHILD");	  	break;
+      case 11:	str("EAGAIN");	  	break;
+      case 12:	str("ENOMEM");	  	break;
+      case 13:	str("EACCES");	  	break;
+      case 14:	str("EFAULT");	  	break;
+      case 15:	str("ENOTBLK");	  	break;
+      case 16:	str("EBUSY");	  	break;
+      case 17:	str("EEXIST");	  	break;
+      case 18:	str("EXDEV");	  	break;
+      case 19:	str("ENODEV");	  	break;
+      case 20:	str("ENOTDIR");	  	break;
+      case 21:	str("EISDIR");	  	break;
+      case 22:	str("EINVAL");	  	break;
+      case 23:	str("ENFILE");	  	break;
+      case 24:	str("EMFILE");	  	break;
+      case 25:	str("ENOTTY");	  	break;
+      case 26:	str("ETXTBSY");	  	break;
+      case 27:	str("EFBIG");	  	break;
+      case 28:	str("ENOSPC");	  	break;
+      case 29:	str("ESPIPE");	  	break;
+      case 30:	str("EROFS");	  	break;
+      case 31:	str("EMLINK");	  	break;
+      case 32:	str("EPIPE");	  	break;
+      case 33:	str("EDOM");	  	break;
+      case 34:	str("ERANGE");	  	break;
+  }
+}
+
+/*****************************************************************************
+*                                                                            *
+*                                ALOT-functions                              *
+*                                                                            *
+*****************************************************************************/
+
+int open_alot()
+{
+  int i;
+
+  for (i = 0; i < MAXOPEN; i++)
+	if (open(file[i], R) == FAIL) break;
+  if (i == 0) err(5, "open_alot", "at all");
+  return(i);
+}				/* open_alot */
+
+int close_alot(number)
+int number;
+{
+  int i, count = 0;
+
+  if (number > MAXOPEN)
+	err(5, "close_alot", "accept this argument");
+  else
+	for (i = FF; i < number + FF; i++)
+		if (close(i) != OK) count++;
+
+  return(number - count);	/* return number of closed files */
+}				/* close_alot */
+
+/*****************************************************************************
+*                                                                            *
+*                         CLEAN UP THE MESS                                  *
+*                                                                            *
+*****************************************************************************/
+
+void clean_up_the_mess()
+{
+  int i;
+  char dirname[6];
+
+  /* First remove 'alot' files */
+  for (i = 0; i < MAXOPEN; i++) try_unlink(file[i]);
+
+  /* Unlink the files in dir 'drwx' */
+  if (chdir("drwx") != OK)
+	err(5, CHDIR, "to 'drwx'");
+  else {
+	for (i = 0; i < 8; i++) try_unlink(fnames[i]);
+	if (chdir("..") != OK) err(5, CHDIR, "to '..'");
+  }
+
+  /* Before unlinking files in some dirs, make them writable */
+  chmod_8_dirs(RWX);
+
+  /* Unlink files in other dirs */
+  try_unlink("d-wx/rwx");
+  try_unlink("dr-x/rwx");
+  try_unlink("drw-/rwx");
+
+  /* Unlink dirs */
+  for (i = 0; i < 8; i++) {
+	strcpy(dirname, "d");
+	strcat(dirname, fnames[i]);
+	/* 'dirname' contains the directoryname */
+	rmdir(dirname);
+  }
+
+  /* FINISH */
+}				/* clean_up_the_mess */
+
+void chmod_8_dirs(sw)
+int sw;				/* if switch == 8, give all different
+			 * mode,else the same mode */
+{
+  int mode;
+  int i;
+
+  if (sw == 8)
+	mode = 0;
+  else
+	mode = sw;
+
+  for (i = 0; i < 8; i++) {
+	chmod(dir[i], 040000 + mode * 0100);
+	if (sw == 8) mode++;
+  }
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test19.c
===================================================================
--- /trunk/minix/test/test19.c	(revision 9)
+++ /trunk/minix/test/test19.c	(revision 9)
@@ -0,0 +1,521 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define MAX_ERROR 4
+#define NB 30L
+#define NBOUNDS 6
+
+int errct, subtest, passes, pipesigs;
+long t1;
+
+char aa[100];
+char b[4] = {0, 1, 2, 3}, c[4] = {10, 20, 30, 40}, d[4] = {6, 7, 8, 9};
+long bounds[NBOUNDS] = {7, 9, 50, 519, 520, 40000L};
+char buff[30000];
+
+_PROTOTYPE(int main, (int argc, char *argv[]));
+_PROTOTYPE(void test19a, (void));
+_PROTOTYPE(void test19b, (void));
+_PROTOTYPE(void test19c, (void));
+_PROTOTYPE(void test19d, (void));
+_PROTOTYPE(void test19e, (void));
+_PROTOTYPE(void test19f, (void));
+_PROTOTYPE(void test19g, (void));
+_PROTOTYPE(void clraa, (void));
+_PROTOTYPE(void pipecatcher, (int s));
+_PROTOTYPE(void e, (int n));
+_PROTOTYPE(void quit, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m;
+
+  m = (argc == 2 ? atoi(argv[1]) : 0xFFFF);
+
+  if (geteuid() == 0 || getuid() == 0) {
+	printf("Test 19 cannot run as root; test aborted\n");
+	exit(1);
+  }
+
+  system("rm -rf DIR_19; mkdir DIR_19");
+  chdir("DIR_19");
+
+  printf("Test 19 ");
+  fflush(stdout);
+  for (i = 0; i < 4; i++) {
+	if (m & 0001) test19a();
+	if (m & 0002) test19b();
+	if (m & 0004) test19c();
+	if (m & 0010) test19d();
+	if (m & 0020) test19e();
+	if (m & 0040) test19f();
+	if (m & 0100) test19g();
+	passes++;
+  }
+  quit();
+  return(-1);			/* impossible */
+}
+
+void test19a()
+{
+/* Test open with O_CREAT and O_EXCL. */
+
+  int fd;
+
+  subtest = 1;
+  
+  if ( (fd = creat("T19.a1", 0777)) != 3) e(1);	/* create test file */
+  if (close(fd) != 0) e(2);
+  if ( (fd = open("T19.a1", O_RDONLY)) != 3) e(3);
+  if (close(fd) != 0) e(4);
+  if ( (fd = open("T19.a1", O_WRONLY)) != 3) e(5);
+  if (close(fd) != 0) e(6);
+  if ( (fd = open("T19.a1", O_RDWR)) != 3) e(7);
+  if (close(fd) != 0) e(8);
+
+  /* See if O_CREAT actually creates a file. */
+  if ( (fd = open("T19.a2", O_RDONLY)) != -1) e(9);	/* must fail */
+  if ( (fd = open("T19.a2", O_RDONLY | O_CREAT, 0444)) != 3) e(10);
+  if (close(fd) != 0) e(11);
+  if ( (fd = open("T19.a2", O_RDONLY)) != 3) e(12);
+  if (close(fd) != 0) e(13);
+  if ( (fd = open("T19.a2", O_WRONLY)) != -1) e(14);
+  if ( (fd = open("T19.a2", O_RDWR)) != -1) e(15);
+
+  /* See what O_CREAT does on an existing file. */
+  if ( (fd = open("T19.a2", O_RDONLY | O_CREAT, 0777)) != 3) e(16);
+  if (close(fd) != 0) e(17);
+  if ( (fd = open("T19.a2", O_RDONLY)) != 3) e(18);
+  if (close(fd) != 0) e(19);
+  if ( (fd = open("T19.a2", O_WRONLY)) != -1) e(20);
+  if ( (fd = open("T19.a2", O_RDWR)) != -1) e(21);
+
+  /* See if O_EXCL works. */
+  if ( (fd = open("T19.a2", O_RDONLY | O_EXCL)) != 3) e(22);
+  if (close(fd) != 0) e(23);
+  if ( (fd = open("T19.a2", O_WRONLY | O_EXCL)) != -1) e(24);
+  if ( (fd = open("T19.a3", O_RDONLY | O_EXCL)) != -1) e(25);
+  if ( (fd = open("T19.a3", O_RDONLY | O_CREAT | O_EXCL, 0444)) != 3) e(26);
+  if (close(fd) != 0) e(27);
+  errno = 0;
+  if ( (fd = open("T19.a3", O_RDONLY | O_CREAT | O_EXCL, 0444)) != -1) e(28);
+  if (errno != EEXIST) e(29);
+ 
+  if (unlink("T19.a1") != 0) e(30);
+  if (unlink("T19.a2") != 0) e(31);
+  if (unlink("T19.a3") != 0) e(32);
+}
+
+void test19b()
+{
+/* Test open with O_APPEND and O_TRUNC. */
+
+  int fd;
+
+  subtest = 2;
+  
+  if ( (fd = creat("T19.b1", 0777)) != 3) e(1);	/* create test file */
+  if (write(fd, b, 4) != 4) e(2);
+  if (close(fd) != 0) e(3);
+  clraa();
+  if ( (fd = open("T19.b1", O_RDWR | O_APPEND)) != 3) e(4);
+  if (read(fd, aa, 100) != 4) e(5);
+  if (aa[0] != 0 || aa[1] != 1 || aa[2] != 2 || aa[3] != 3) e(6);
+  if (close(fd) != 0) e(7);
+  if ( (fd = open("T19.b1", O_RDWR | O_APPEND)) != 3) e(8);
+  if (write(fd, b, 4) != 4) e(9);
+  if (lseek(fd, 0L, SEEK_SET) != 0L) e(10);
+  clraa();
+  if (read(fd, aa, 100) != 8) e(11);
+  if (aa[4] != 0 || aa[5] != 1 || aa[6] != 2 || aa[7] != 3) e(12);
+  if (close(fd) != 0) e(13);
+
+  if ( (fd = open("T19.b1", O_RDWR | O_TRUNC)) != 3) e(14);
+  if (read(fd, aa, 100) != 0) e(15);
+  if (close(fd) != 0) e(16);
+
+  unlink("T19.b1");
+}
+
+void test19c()
+{
+/* Test program for open(), close(), creat(), read(), write(), lseek(). */
+
+  int i, n, n1, n2;
+
+  subtest = 3;
+  if ((n = creat("foop", 0777)) != 3) e(1);
+  if ((n1 = creat("foop", 0777)) != 4) e(2);
+  if ((n2 = creat("/", 0777)) != -1) e(3);
+  if (close(n) != 0) e(4);
+  if ((n = open("foop", O_RDONLY)) != 3) e(5);
+  if ((n2 = open("nofile", O_RDONLY)) != -1) e(6);
+  if (close(n1) != 0) e(7);
+
+  /* N is the only one open now. */
+  for (i = 0; i < 2; i++) {
+	n1 = creat("File2", 0777);
+	if (n1 != 4) {
+		printf("creat yielded fd=%d, expected 4\n", n1);
+		e(8);
+	}
+	if ((n2 = open("File2", O_RDONLY)) != 5) e(9);
+	if (close(n1) != 0) e(10);
+	if (close(n2) != 0) e(11);
+  }
+  unlink("File2");
+  if (close(n) != 0) e(12);
+
+  /* All files closed now. */
+  for (i = 0; i < 2; i++) {
+	if ((n = creat("foop", 0777)) != 3) e(13);
+	if (close(n) != 0) e(14);
+	if ((n = open("foop", O_RDWR)) != 3) e(15);
+
+	/* Read/write tests */
+	if (write(n, b, 4) != 4) e(16);
+	if (read(n, aa, 4) != 0) e(17);
+	if (lseek(n, 0L, SEEK_SET) != 0L) e(18);
+	if (read(n, aa, 4) != 4) e(19);
+	if (aa[0] != 0 || aa[1] != 1 || aa[2] != 2 || aa[3] != 3) e(20);
+	if (lseek(n, 0L, SEEK_SET) != 0L) e(21);
+	if (lseek(n, 2L, SEEK_CUR) != 2L) e(22);
+	if (read(n, aa, 4) != 2) e(23);
+	if (aa[0] != 2 || aa[1] != 3 || aa[2] != 2 || aa[3] != 3) e(24);
+	if (lseek(n, 2L, SEEK_SET) != 2L) e(25);
+	clraa();
+	if (write(n, c, 4) != 4) e(26);
+	if (lseek(n, 0L, SEEK_SET) != 0L) e(27);
+	if (read(n, aa, 10) != 6) e(28);
+	if (aa[0] != 0 || aa[1] != 1 || aa[2] != 10 || aa[3] != 20) e(29);
+	if (lseek(n, 16L, SEEK_SET) != 16L) e(30);
+	if (lseek(n, 2040L, SEEK_END) != 2046L) e(31);
+	if (read(n, aa, 10) != 0) e(32);
+	if (lseek(n, 0L, SEEK_CUR) != 2046L) e(33);
+	clraa();
+	if (write(n, c, 4) != 4) e(34);
+	if (lseek(n, 0L, SEEK_CUR) != 2050L) e(35);
+	if (lseek(n, 2040L, SEEK_SET) != 2040L) e(36);
+	clraa();
+	if (read(n, aa, 20) != 10) e(37);
+	if (aa[0] != 0 || aa[5] != 0 || aa[6] != 10 || aa[9] != 40) e(38);
+	if (lseek(n, 10239L, SEEK_SET) != 10239L) e(39);
+	if (write(n, d, 2) != 2) e(40);
+	if (lseek(n, -2L, SEEK_END) != 10239L) e(41);
+	if (read(n, aa, 2) != 2) e(42);
+	if (aa[0] != 6 || aa[1] != 7) e(43);
+	if (lseek(n, NB * 1024L - 2L, SEEK_SET) != NB * 1024L - 2L) e(44);
+	if (write(n, b, 4) != 4) e(45);
+	if (lseek(n, 0L, SEEK_SET) != 0L) e(46);
+	if (lseek(n, -6L, SEEK_END) != 1024L * NB - 4) e(47);
+	clraa();
+	if (read(n, aa, 100) != 6) e(48);
+	if (aa[0] != 0 || aa[1] != 0 || aa[3] != 1 || aa[4] != 2|| aa[5] != 3)
+		e(49);
+	if (lseek(n, 20000L, SEEK_SET) != 20000L) e(50);
+	if (write(n, c, 4) != 4) e(51);
+	if (lseek(n, -4L, SEEK_CUR) != 20000L) e(52);
+	if (read(n, aa, 4) != 4) e(53);
+	if (aa[0] != 10 || aa[1] != 20 || aa[2] != 30 || aa[3] != 40) e(54);
+	if (close(n) != 0) e(55);
+	if ((n1 = creat("foop", 0777)) != 3) e(56);
+	if (close(n1) != 0) e(57);
+	unlink("foop");
+
+  }
+}
+
+void test19d()
+{
+/* Test read. */
+
+  int i, fd, pd[2];
+  char bb[100];
+
+  subtest = 4;
+  
+  for (i = 0; i < 100; i++) bb[i] = i;
+  if ( (fd = creat("T19.d1", 0777)) != 3) e(1);	/* create test file */
+  if (write(fd, bb, 100) != 100) e(2);
+  if (close(fd) != 0) e(3);
+  clraa();
+  if ( (fd = open("T19.d1", O_RDONLY)) != 3) e(4);
+  errno = 1000;
+  if (read(fd, aa, 0) != 0) e(5);
+  if (errno != 1000) e(6);
+  if (read(fd, aa, 100) != 100) e(7);
+  if (lseek(fd, 37L, SEEK_SET) != 37L) e(8);
+  if (read(fd, aa, 10) != 10) e(9);
+  if (lseek(fd, 0L, SEEK_CUR) != 47L) e(10);
+  if (read(fd, aa, 100) != 53) e(11);
+  if (aa[0] != 47) e(12);
+  if (read(fd, aa, 1) != 0) e(13);
+  if (close(fd) != 0) e(14);
+
+  /* Read from pipe with no writer open. */
+  if (pipe(pd) != 0) e(15);
+  if (close(pd[1]) != 0) e(16);
+  errno = 2000;
+  if (read(pd[0], aa, 1) != 0) e(17);	/* must return EOF */
+  if (errno != 2000) e(18);
+
+  /* Read from a pipe with O_NONBLOCK set. */
+  if (fcntl(pd[0], F_SETFL, O_NONBLOCK) != 0) e(19);      /* set O_NONBLOCK */
+/*
+  if (read(pd[0], aa, 1) != -1) e(20);
+  if (errno != EAGAIN) e(21);
+*/
+  if (close(pd[0]) != 0) e(19);
+  if (unlink("T19.d1") != 0) e(20);
+}
+
+void test19e()
+{
+/* Test link, unlink, stat, fstat, dup, umask.  */
+
+  int i, j, n, n1, flag;
+  char a[255], b[255];
+  struct stat s, s1;
+
+  subtest = 5;
+  for (i = 0; i < 2; i++) {
+	umask(0);
+
+	if ((n = creat("T3", 0702)) < 0) e(1);
+	if (link("T3", "newT3") < 0) e(2);
+	if ((n1 = open("newT3", O_RDWR)) < 0) e(3);
+	for (j = 0; j < 255; j++) a[j] = j;
+	if (write(n, a, 255) != 255) e(4);
+	if (read(n1, b, 255) != 255) e(5);
+	flag = 0;
+	for (j = 0; j < 255; j++)
+		if (a[j] != b[j]) flag++;
+	if (flag) e(6);
+	if (unlink("T3") < 0) e(7);
+	if (close(n) < 0) e(8);
+	if (close(n1) < 0) e(9);
+	if ((n1 = open("newT3", O_RDONLY)) < 0) e(10);
+	if (read(n1, b, 255) != 255) e(11);
+	flag = 0;
+	for (j = 0; j < 255; j++)
+		if (a[j] != b[j]) flag++;
+	if (flag) e(12);
+
+	/* Now check out stat, fstat. */
+	if (stat("newT3", &s) < 0) e(13);
+	if (s.st_mode != (mode_t) 0100702) e(14);
+				/* The cast was because regular modes are
+				 * negative :-(.  Anyway, the magic number
+				 * should be (S_IFREG | S_IRWXU | S_IWOTH)
+				 * for POSIX.
+				 */
+	if (s.st_nlink != 1) e(15);
+	if (s.st_size != 255L) e(16);
+	if (fstat(n1, &s1) < 0) e(17);
+	if (s.st_dev != s1.st_dev) e(18);
+	if (s.st_ino != s1.st_ino) e(19);
+	if (s.st_mode != s1.st_mode) e(20);
+	if (s.st_nlink != s1.st_nlink) e(21);
+	if (s.st_uid != s1.st_uid) e(22);
+	if (s.st_gid != s1.st_gid) e(23);
+	if (s.st_rdev != s1.st_rdev) e(24);
+	if (s.st_size != s1.st_size) e(25);
+	if (s.st_atime != s1.st_atime) e(26);
+	if (close(n1) < 0) e(27);
+	if (unlink("newT3") < 0) e(28);
+
+	umask(040);
+	if ((n = creat("T3a", 0777)) < 0) e(29);
+	if (stat("T3a", &s) < 0) e(30);
+	if (s.st_mode != (mode_t) 0100737) e(31);	/* negative :-( */
+	if (unlink("T3a") < 0) e(32);
+	if (close(n1) < 0) e(33);
+
+	/* Dup */
+	if ((n = creat("T3b", 0777)) < 0) e(34);
+	if (close(n) < 0) e(35);
+	if ((n = open("T3b", O_RDWR)) < 0) e(36);
+	if ((n1 = dup(n)) != n + 1) e(37);
+	if (write(n, a, 255) != 255) e(38);
+	read(n1, b, 20);
+	if (lseek(n, 0L, SEEK_SET) != 0L) e(39);
+	if ((j = read(n1, b, 512)) != 255) e(40);
+	if (unlink("T3b") < 0) e(41);
+	if (close(n) < 0) e(42);
+	if (close(n1) < 0) e(43);
+
+  }
+}
+
+void test19f()
+{
+/* Test large files to see if indirect block stuff works. */
+
+  int fd, i;
+  long pos;
+
+  subtest = 6;
+
+  if (passes > 0) return;	/* takes too long to repeat this test */
+  for (i = 0; i < NBOUNDS; i ++) {
+	pos = 1024L * bounds[i];
+	fd = creat("T19f", 0777);
+	if (fd < 0) e(10*i+1);
+	if (lseek(fd, pos, 0) < 0) e(10*i+2);
+	if (write(fd, buff, 30720) != 30720) e(10*i+3);
+	if (close(fd) < 0) e(10*i+3);
+	if (unlink("T19f") < 0) e(10*i+4);
+  }
+}
+
+void test19g()
+{
+/* Test POSIX calls for pipe, read, write, lseek and close. */
+
+  int pipefd[2], n, i, fd;
+  char buf[512], buf2[512];
+
+  subtest = 7;
+
+  for (i = 0; i < 512; i++) buf[i] = i % 128;
+
+  if (pipe(pipefd) < 0) e(1);
+  if (write(pipefd[1], buf, 512) != 512) e(2);
+  if (read(pipefd[0], buf2, 512) != 512) e(3);
+  if (close(pipefd[1]) != 0) e(4);
+  if (close(pipefd[1]) >= 0) e(5);
+  if (read(pipefd[0], buf2, 1) != 0) e(6);
+  if (close(pipefd[0]) != 0) e(7);
+
+  /* Test O_NONBLOCK on pipes. */
+  if (pipe(pipefd) < 0) e(8);
+  if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) != 0) e(9);
+  if (read(pipefd[0], buf2, 1) != -1) e(10);
+  if (errno != EAGAIN) e(11);
+  if (close(pipefd[0]) != 0) e(12);
+  if (close(pipefd[1]) != 0) e(13);
+
+  /* Test read and lseek. */
+  if ( (fd = creat("T19.g1", 0777)) != 3) e(14);	/* create test file */
+  if (write(fd, buf, 512) != 512) e(15);
+  errno = 3000;
+  if (read(fd, buf2, 512) != -1) e(16);
+  if (errno != EBADF) e(17);
+  if (close(fd) != 0) e(18);
+  if ( (fd = open("T19.g1", O_RDWR)) != 3) e(19);
+  if (read(fd, buf2, 512) != 512) e(20);
+  if (read(fd, buf2, 512) != 0) e(21);
+  if (lseek(fd, 100L, SEEK_SET) != 100L) e(22);
+  if (read(fd, buf2, 512) != 412) e(23);
+  if (lseek(fd, 1000L, SEEK_SET) != 1000L) e(24);
+
+  /* Test write. */
+  if (lseek(fd, -1000L, SEEK_CUR) != 0) e(25);
+  if (write(fd, buf, 512) != 512) e(26);
+  if (lseek(fd, 2L, SEEK_SET) != 2) e(27);
+  if (write(fd, buf, 3) != 3) e(28);
+  if (lseek(fd, -2L, SEEK_CUR) != 3) e(29);
+  if (write(fd, &buf[30], 1) != 1) e(30);
+  if (lseek(fd, 2L, SEEK_CUR) != 6) e(31);
+  if (write(fd, &buf[60], 1) != 1) e(32);
+  if (lseek(fd, -512L, SEEK_END) != 0) e(33);
+  if (read(fd, buf2, 8) != 8) e(34);
+  errno = 4000;
+  if (buf2[0] != 0 || buf2[1] != 1 || buf2[2] != 0 || buf2[3] != 30) e(35);
+  if (buf2[4] != 2 || buf2[5] != 5 || buf2[6] != 60 || buf2[7] != 7) e(36);
+
+  /* Turn the O_APPEND flag on. */
+  if (fcntl(fd, F_SETFL, O_APPEND) != 0) e(37);
+  if (lseek(fd, 0L, SEEK_SET) != 0) e(38);
+  if (write(fd, &buf[100], 1) != 1) e(39);
+  if (lseek(fd, 0L, SEEK_SET) != 0) e(40);
+  if (read(fd, buf2, 10) != 10) e(41);
+  if (buf2[0] != 0) e(42);
+  if (lseek(fd, -1L, SEEK_END) != 512) e(43);
+  if (read(fd, buf2, 10) != 1) e(44);
+  if (buf2[0] != 100) e(45);
+  if (close(fd) != 0) e(46);
+
+  /* Now try write with O_NONBLOCK. */
+  if (pipe(pipefd) != 0) e(47);
+  if (fcntl(pipefd[1], F_SETFL, O_NONBLOCK) != 0) e(48);
+  if (write(pipefd[1], buf, 512) != 512) e(49);
+  if (write(pipefd[1], buf, 512) != 512) e(50);
+  errno = 0;
+  for (i = 1; i < 20; i++) {
+	n = write(pipefd[1], buf, 512);
+	if (n == 512) continue;
+	if (n != -1 || errno != EAGAIN) {e(51); break;}
+  }
+  if (read(pipefd[0], buf, 512) != 512) e(52);
+  if (close(pipefd[0]) != 0) e(53);
+
+  /* Write to a pipe with no reader.  This should generate a signal. */
+  signal(SIGPIPE, pipecatcher);
+  errno = 0;
+  if (write(pipefd[1], buf, 1) != -1) e(54);
+  if (errno != EPIPE) e(55);
+  if (pipesigs != passes + 1) e(56);	/* we should have had the sig now */
+  if (close(pipefd[1]) != 0) e(57);
+  errno = 0;
+  if (write(100, buf, 512) != -1) e(58);
+  if (errno != EBADF) e(59);
+  if (unlink("T19.g1") != 0) e(60);
+}
+
+void clraa()
+{
+  int i;
+  for (i = 0; i < 100; i++) aa[i] = 0;
+}
+
+void pipecatcher(s)
+int s;				/* it is supposed to have an arg */
+{
+  pipesigs++;
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* save errno in case printf clobbers it */
+
+  printf("Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
+  fflush(stdout);		/* aargh!  Most results go to stdout and are
+				 * messed up by perror going to stderr.
+				 * Should replace perror by printf and strerror
+				 * in all the tests.
+				 */
+  errno = err_num;		/* restore errno, just in case */
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
+
Index: /trunk/minix/test/test2.c
===================================================================
--- /trunk/minix/test/test2.c	(revision 9)
+++ /trunk/minix/test/test2.c	(revision 9)
@@ -0,0 +1,409 @@
+/* test 2 */
+
+#include <sys/types.h>
+#include <sys/times.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdio.h>
+
+#define ITERATIONS 5
+#define MAX_ERROR 4
+
+int is, array[4], parsigs, parcum, sigct, cumsig, errct, subtest;
+int iteration, kk = 0, errct = 0;
+char buf[2048];
+
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(void test2a, (void));
+_PROTOTYPE(void test2b, (void));
+_PROTOTYPE(void test2c, (void));
+_PROTOTYPE(void test2d, (void));
+_PROTOTYPE(void test2e, (void));
+_PROTOTYPE(void test2f, (void));
+_PROTOTYPE(void test2g, (void));
+_PROTOTYPE(void test2h, (void));
+_PROTOTYPE(void sigpip, (int s));
+_PROTOTYPE(void quit, (void));
+_PROTOTYPE(void e, (int n));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+
+  if (argc == 2) m = atoi(argv[1]);
+
+  printf("Test  2 ");
+  fflush(stdout);		/* have to flush for child's benefit */
+
+  system("rm -rf DIR_02; mkdir DIR_02");
+  chdir("DIR_02");
+
+  for (i = 0; i < ITERATIONS; i++) {
+	iteration = i;
+	if (m & 0001) test2a();
+	if (m & 0002) test2b();
+	if (m & 0004) test2c();
+	if (m & 0010) test2d();
+	if (m & 0020) test2e();
+	if (m & 0040) test2f();
+	if (m & 0100) test2g();
+	if (m & 0200) test2h();
+  }
+  subtest = 100;
+  if (cumsig != ITERATIONS) e(101);
+  quit();
+  return(-1);			/* impossible */
+}
+
+void test2a()
+{
+/* Test pipes */
+
+  int fd[2];
+  int n, i, j, q = 0;
+
+  subtest = 1;
+  if (pipe(fd) < 0) {
+	printf("pipe error.  errno= %d\n", errno);
+	errct++;
+	quit();
+  }
+  i = fork();
+  if (i < 0) {
+	printf("fork failed\n");
+	errct++;
+	quit();
+  }
+  if (i != 0) {
+	/* Parent code */
+	close(fd[0]);
+	for (i = 0; i < 2048; i++) buf[i] = i & 0377;
+	for (q = 0; q < 8; q++) {
+		if (write(fd[1], buf, 2048) < 0) {
+			printf("write pipe err.  errno=%d\n", errno);
+			errct++;
+			quit();
+		}
+	}
+	close(fd[1]);
+	wait(&q);
+	if (q != 256 * 58) {
+		printf("wrong exit code %d\n", q);
+		errct++;
+		quit();
+	}
+  } else {
+	/* Child code */
+	close(fd[1]);
+	for (q = 0; q < 32; q++) {
+		n = read(fd[0], buf, 512);
+		if (n != 512) {
+			printf("read yielded %d bytes, not 512\n", n);
+			errct++;
+			quit();
+		}
+		for (j = 0; j < n; j++)
+			if ((buf[j] & 0377) != (kk & 0377)) {
+				printf("wrong data: %d %d %d \n ", 
+						j, buf[j] & 0377, kk & 0377);
+			} else {
+				kk++;
+			}
+	}
+	exit(58);
+  }
+}
+
+void test2b()
+{
+  int fd[2], n;
+  char buf[4];
+
+  subtest = 2;
+  sigct = 0;
+  signal(SIGPIPE, sigpip);
+  pipe(fd);
+  if (fork()) {
+	/* Parent */
+	close(fd[0]);
+	while (sigct == 0) {
+		write(fd[1], buf, 1);
+	}
+	wait(&n);
+  } else {
+	/* Child */
+	close(fd[0]);
+	close(fd[1]);
+	exit(0);
+  }
+}
+
+void test2c()
+{
+  int n;
+
+  subtest = 3;
+  signal(SIGINT, SIG_DFL);
+  is = 0;
+  if ((array[is++] = fork()) > 0) {
+	if ((array[is++] = fork()) > 0) {
+		if ((array[is++] = fork()) > 0) {
+			if ((array[is++] = fork()) > 0) {
+				signal(SIGINT, SIG_IGN);
+				kill(array[0], SIGINT);
+				kill(array[1], SIGINT);
+				kill(array[2], SIGINT);
+				kill(array[3], SIGINT);
+				wait(&n);
+				wait(&n);
+				wait(&n);
+				wait(&n);
+			} else {
+				pause();
+			}
+		} else {
+			pause();
+		}
+	} else {
+		pause();
+	}
+  } else {
+	pause();
+  }
+}
+
+void test2d()
+{
+
+  int pid, stat_loc, s;
+
+  /* Test waitpid. */
+  subtest = 4;
+
+  /* Test waitpid(pid, arg2, 0) */
+  pid = fork();
+  if (pid < 0) e(1);
+  if (pid > 0) {
+	/* Parent. */
+	s = waitpid(pid, &stat_loc, 0);
+	if (s != pid) e(2);
+	if (WIFEXITED(stat_loc) == 0) e(3);
+	if (WIFSIGNALED(stat_loc) != 0) e(4);
+	if (WEXITSTATUS(stat_loc) != 22) e(5);
+  } else {
+	/* Child */
+	exit(22);
+  }
+
+  /* Test waitpid(-1, arg2, 0) */
+  pid = fork();
+  if (pid < 0) e(6);
+  if (pid > 0) {
+	/* Parent. */
+	s = waitpid(-1, &stat_loc, 0);
+	if (s != pid) e(7);
+	if (WIFEXITED(stat_loc) == 0) e(8);
+	if (WIFSIGNALED(stat_loc) != 0) e(9);
+	if (WEXITSTATUS(stat_loc) != 33) e(10);
+  } else {
+	/* Child */
+	exit(33);
+  }
+
+  /* Test waitpid(0, arg2, 0) */
+  pid = fork();
+  if (pid < 0) e(11);
+  if (pid > 0) {
+	/* Parent. */
+	s = waitpid(0, &stat_loc, 0);
+	if (s != pid) e(12);
+	if (WIFEXITED(stat_loc) == 0) e(13);
+	if (WIFSIGNALED(stat_loc) != 0) e(14);
+	if (WEXITSTATUS(stat_loc) != 44) e(15);
+  } else {
+	/* Child */
+	exit(44);
+  }
+
+  /* Test waitpid(0, arg2, WNOHANG) */
+  signal(SIGTERM, SIG_DFL);
+  pid = fork();
+  if (pid < 0) e(16);
+  if (pid > 0) {
+	/* Parent. */
+	s = waitpid(0, &stat_loc, WNOHANG);
+	if (s != 0) e(17);
+	if (kill(pid, SIGTERM) != 0) e(18);
+	if (waitpid(pid, &stat_loc, 0) != pid) e(19);
+	if (WIFEXITED(stat_loc) != 0) e(20);
+	if (WIFSIGNALED(stat_loc) == 0) e(21);
+	if (WTERMSIG(stat_loc) != SIGTERM) e(22);
+  } else {
+	/* Child */
+	pause();
+  }
+
+  /* Test some error conditions. */
+  errno = 9999;
+  if (waitpid(0, &stat_loc, 0) != -1) e(23);
+  if (errno != ECHILD) e(24);
+  errno = 9999;
+  if (waitpid(0, &stat_loc, WNOHANG) != -1) e(25);
+  if (errno != ECHILD) e(26);
+}
+
+void test2e()
+{
+
+  int pid1, pid2, stat_loc, s;
+
+  /* Test waitpid with two children. */
+  subtest = 5;
+  if (iteration > 1) return;		/* slow test, don't do it too much */
+  if ( (pid1 = fork())) {
+	/* Parent. */
+	if ( (pid2 = fork()) ) {
+		/* Parent. Collect second child first. */
+		s = waitpid(pid2, &stat_loc, 0);
+		if (s != pid2) e(1);
+		if (WIFEXITED(stat_loc) == 0) e(2);
+		if (WIFSIGNALED(stat_loc) != 0) e(3);
+		if (WEXITSTATUS(stat_loc) != 222) e(4);
+
+		/* Now collect first child. */
+		s = waitpid(pid1, &stat_loc, 0);
+		if (s != pid1) e(5);
+		if (WIFEXITED(stat_loc) == 0) e(6);
+		if (WIFSIGNALED(stat_loc) != 0) e(7);
+		if (WEXITSTATUS(stat_loc) != 111) e(8);
+	} else {
+		/* Child 2. */
+		sleep(2);		/* child 2 delays before exiting. */
+		exit(222);
+	}
+  } else {
+	/* Child 1. */
+	exit(111);			/* child 1 exits immediately */
+  }
+
+}
+
+void test2f()
+{
+/* test getpid, getppid, getuid, etc. */
+
+  pid_t pid, pid1, ppid, cpid, stat_loc, err;
+
+  subtest = 6;
+  errno = -2000;
+  err = 0;
+  pid = getpid();
+  if ( (pid1 = fork())) {
+	/* Parent.  Do nothing. */
+	if (wait(&stat_loc) != pid1) e(1);
+	if (WEXITSTATUS(stat_loc) != (pid1 & 0377)) e(2);
+  } else {
+	/* Child.  Get ppid. */
+	cpid = getpid();
+	ppid = getppid();
+	if (ppid != pid) err = 3;
+	if (cpid == ppid) err = 4;
+	exit(cpid & 0377);
+  }
+  if (err != 0) e(err);
+}
+
+void test2g()
+{
+/* test time(), times() */
+
+  time_t t1, t2;
+  clock_t t3, t4;
+  struct tms tmsbuf;
+
+  subtest = 7;
+  errno = -7000;
+
+  /* First time(). */
+  t1 = -1;
+  t2 = -2;
+  t1 = time(&t2);
+  if (t1 < 650000000L) e(1);	/* 650000000 is Sept. 1990 */
+  if (t1 != t2) e(2);
+  t1 = -1;
+  t1 = time( (time_t *) NULL);
+  if (t1 < 650000000L) e(3);
+  t3 = times(&tmsbuf);
+  sleep(1);
+  t2 = time( (time_t *) NULL);
+  if (t2 < 0L) e(4);
+  if (t2 - t1 < 1) e(5);
+
+  /* Now times(). */
+  t4 = times(&tmsbuf);
+  if ( t4 == (clock_t) -1) e(6);
+  if (t4 - t3 < CLOCKS_PER_SEC) e(7);
+  if (tmsbuf.tms_utime < 0) e(8);
+  if (tmsbuf.tms_stime < 0) e(9);
+  if (tmsbuf.tms_cutime < 0) e(10);
+  if (tmsbuf.tms_cstime < 0) e(11);
+}
+
+void test2h()
+{
+/* Test getgroups(). */
+
+  gid_t g[10];
+
+  subtest = 8;
+  errno = -8000;
+  if (getgroups(10, g) != 0) e(1);
+  if (getgroups(1, g) != 0) e(2);
+  if (getgroups(0, g) != 0) e(3);
+}
+
+void sigpip(s)
+int s;				/* for ANSI */
+{
+  sigct++;
+  cumsig++;
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(4);
+  }
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* save errno in case printf clobbers it */
+
+  printf("Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
+  errno = err_num;		/* restore errno, just in case */
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors;  test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test20.c
===================================================================
--- /trunk/minix/test/test20.c	(revision 9)
+++ /trunk/minix/test/test20.c	(revision 9)
@@ -0,0 +1,398 @@
+/* test20: fcntl()		Author: Jan-Mark Wams (jms@cs.vu.nl) */
+
+/* Some things have to be checked for ``exec()'' call's. Therefor
+** there is a check routine called ``do_check()'' that will be
+** called if the first argument (``argv[0]'') equals ``DO CHECK.''
+** Note that there is no way the shell (``/bin/sh'') will set
+** ``argv[0]'' to this funny value. (Unless we rename ``test20''
+** to ``DO CHECK'' ;-)
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+
+#define MAX_ERROR	4
+#define ITERATIONS     10
+
+#define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+#define Stat(a,b)	if (stat(a,b) != 0) printf("Can't stat %s\n", a)
+
+int errct = 0;
+int subtest = 1;
+int superuser;
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];		/* Same for path */
+char ToLongName[NAME_MAX + 2];	/* Name of maximum +1 length */
+char ToLongPath[PATH_MAX + 1];	/* Same for path, both too long */
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test20a, (void));
+_PROTOTYPE(void test20b, (void));
+_PROTOTYPE(void test20c, (void));
+_PROTOTYPE(void test20d, (void));
+_PROTOTYPE(int do_check, (void));
+_PROTOTYPE(void makelongnames, (void));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+
+char executable[1024];
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+
+  /* If we have to check things, call do_check(). */
+  if (strcmp(argv[0], "DO CHECK") == 0) exit(do_check());
+
+  /* Get the path of the executable. */
+  strcpy(executable, "../");
+  strcat(executable, argv[0]);
+
+  printf("Test 20 ");
+  fflush(stdout);
+  System("rm -rf DIR_20; mkdir DIR_20");
+  Chdir("DIR_20");
+  makelongnames();
+  superuser = (geteuid() == 0);
+
+  for (i = 0; i < ITERATIONS; i++) {
+	test20a();
+	test20b();
+	test20c();
+	test20d();
+  }
+  quit();
+}
+
+void test20a()
+{				/* Test normal operation. */
+  subtest = 1;
+  System("rm -rf ../DIR_20/*");
+}
+
+void test20b()
+{
+  subtest = 2;
+  System("rm -rf ../DIR_20/*");
+}
+
+void test20c()
+{
+  subtest = 3;
+  System("rm -rf ../DIR_20/*");
+}
+
+/* Open fds 3, 4, 5 and 6. Set FD_CLOEXEC on 5 and 6. Exclusively lock the
+** first 10 bytes of fd no. 3. Shared lock fd no. 7. Lock fd no. 8 after
+** the fork. Do a ``exec()'' call with a funny argv[0] and check the return
+** value.
+*/
+void test20d()
+{				/* Test locks with ``fork()'' and ``exec().'' */
+  int fd3, fd4, fd5, fd6, fd7, fd8;
+  int stat_loc;
+  int do_check_retval;
+  char *argv[2];
+  struct flock fl;
+
+  subtest = 4;
+
+  argv[0] = "DO CHECK";
+  argv[1] = (char *) NULL;
+
+  fl.l_whence = SEEK_SET;
+  fl.l_start = 0;
+  fl.l_len = 10;
+
+  /* Make a dummy files and open them. */
+  System("echo 'Great Balls Of Fire!' > file3");
+  System("echo 'Great Balls Of Fire!' > file4");
+  System("echo 'Great Balls Of Fire!' > file7");
+  System("echo 'Great Balls Of Fire!' > file8");
+  System("echo 'Great Balls Of Fire!' > file");
+  if ((fd3 = open("file3", O_RDWR)) != 3) e(1);
+  if ((fd4 = open("file4", O_RDWR)) != 4) e(2);
+  if ((fd5 = open("file", O_RDWR)) != 5) e(3);
+  if ((fd6 = open("file", O_RDWR)) != 6) e(4);
+  if ((fd7 = open("file7", O_RDWR)) != 7) e(5);
+  if ((fd8 = open("file8", O_RDWR)) != 8) e(6);
+
+  /* Set FD_CLOEXEC flags on fd5 and fd6. */
+  if (fcntl(fd5, F_SETFD, FD_CLOEXEC) == -1) e(7);
+  if (fcntl(fd6, F_SETFD, FD_CLOEXEC) == -1) e(8);
+
+  /* Lock the first ten bytes from fd3 (for writing). */
+  fl.l_type = F_WRLCK;
+  if (fcntl(fd3, F_SETLK, &fl) == -1) e(9);
+
+  /* Lock (for reading) fd7. */
+  fl.l_type = F_RDLCK;
+  if (fcntl(fd7, F_SETLK, &fl) == -1) e(10);
+
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+
+	/* Lock fd8. */
+	fl.l_type = F_WRLCK;
+	if (fcntl(fd8, F_SETLK, &fl) == -1) e(11);
+
+	/* Check the lock on fd3 and fd7. */
+	fl.l_type = F_WRLCK;
+	if (fcntl(fd3, F_GETLK, &fl) == -1) e(12);
+	if (fl.l_type != F_WRLCK) e(13);
+	if (fl.l_pid != getppid()) e(14);
+	fl.l_type = F_WRLCK;
+	if (fcntl(fd7, F_GETLK, &fl) == -1) e(15);
+	if (fl.l_type != F_RDLCK) e(16);
+	if (fl.l_pid != getppid()) e(17);
+
+	/* Check FD_CLOEXEC flags. */
+	if ((fcntl(fd3, F_GETFD) & FD_CLOEXEC) != 0) e(18);
+	if ((fcntl(fd4, F_GETFD) & FD_CLOEXEC) != 0) e(19);
+	if ((fcntl(fd5, F_GETFD) & FD_CLOEXEC) != FD_CLOEXEC) e(20);
+	if ((fcntl(fd6, F_GETFD) & FD_CLOEXEC) != FD_CLOEXEC) e(21);
+	if ((fcntl(fd7, F_GETFD) & FD_CLOEXEC) != 0) e(22);
+	if ((fcntl(fd8, F_GETFD) & FD_CLOEXEC) != 0) e(23);
+
+	execlp(executable + 3, "DO CHECK", (char *) NULL);
+	execlp(executable, "DO CHECK", (char *) NULL);
+	printf("Can't exec %s or %s\n", executable + 3, executable);
+	exit(0);
+
+      default:
+	wait(&stat_loc);
+	if (WIFSIGNALED(stat_loc)) e(24);	/* Alarm? */
+	if (WIFEXITED(stat_loc) == 0) {
+		errct=10000;
+		quit();
+	}
+  }
+
+  /* Check the return value of do_check(). */
+  do_check_retval = WEXITSTATUS(stat_loc);
+  if ((do_check_retval & 0x11) == 0x11) e(25);
+  if ((do_check_retval & 0x12) == 0x12) e(26);
+  if ((do_check_retval & 0x14) == 0x14) e(27);
+  if ((do_check_retval & 0x18) == 0x18) e(28);
+  if ((do_check_retval & 0x21) == 0x21) e(29);
+  if ((do_check_retval & 0x22) == 0x22) e(30);
+  if ((do_check_retval & 0x24) == 0x24) e(31);
+  if ((do_check_retval & 0x28) == 0x28) e(32);
+  if ((do_check_retval & 0x41) == 0x41) e(33);
+  if ((do_check_retval & 0x42) == 0x42) e(34);
+  if ((do_check_retval & 0x44) == 0x44) e(35);
+  if ((do_check_retval & 0x48) == 0x48) e(36);
+  if ((do_check_retval & 0x81) == 0x81) e(37);
+  if ((do_check_retval & 0x82) == 0x82) e(38);
+  if ((do_check_retval & 0x84) == 0x84) e(39);
+  if ((do_check_retval & 0x88) == 0x88) e(40);
+
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+
+	/* Lock fd8. */
+	fl.l_type = F_WRLCK;
+	if (fcntl(fd8, F_SETLK, &fl) == -1) e(41);
+
+	execvp(executable + 3, argv);
+	execvp(executable, argv);
+	printf("Can't exec %s or %s\n", executable + 3, executable);
+	exit(0);
+
+      default:
+	wait(&stat_loc);
+	if (WIFSIGNALED(stat_loc)) e(48);	/* Alarm? */
+  }
+
+  /* Check the return value of do_check(). */
+  do_check_retval = WEXITSTATUS(stat_loc);
+  if ((do_check_retval & 0x11) == 0x11) e(49);
+  if ((do_check_retval & 0x12) == 0x12) e(50);
+  if ((do_check_retval & 0x14) == 0x14) e(51);
+  if ((do_check_retval & 0x18) == 0x18) e(52);
+  if ((do_check_retval & 0x21) == 0x21) e(53);
+  if ((do_check_retval & 0x22) == 0x22) e(54);
+  if ((do_check_retval & 0x24) == 0x24) e(55);
+  if ((do_check_retval & 0x28) == 0x28) e(56);
+  if ((do_check_retval & 0x41) == 0x41) e(57);
+  if ((do_check_retval & 0x42) == 0x42) e(58);
+  if ((do_check_retval & 0x44) == 0x44) e(59);
+  if ((do_check_retval & 0x48) == 0x48) e(60);
+  if ((do_check_retval & 0x81) == 0x81) e(61);
+  if ((do_check_retval & 0x82) == 0x82) e(62);
+  if ((do_check_retval & 0x84) == 0x84) e(63);
+  if ((do_check_retval & 0x88) == 0x88) e(64);
+
+  fl.l_type = F_UNLCK;
+  if (fcntl(fd3, F_SETLK, &fl) == -1) e(65);
+  if (fcntl(fd7, F_SETLK, &fl) == -1) e(66);
+
+  if (close(fd3) != 0) e(67);
+  if (close(fd4) != 0) e(68);
+  if (close(fd5) != 0) e(69);
+  if (close(fd6) != 0) e(70);
+  if (close(fd7) != 0) e(71);
+  if (close(fd8) != 0) e(72);
+
+  System("rm -f ../DIR_20/*\n");
+}
+
+/* This routine checks that fds 0 through 4, 7 and 8 are open and the rest
+** is closed. It also checks if we can lock the first 10 bytes on fd no. 3
+** and 4. It should not be possible to lock fd no. 3, but it should be
+** possible to lock fd no. 4. See ``test20d()'' for usage of this routine.
+*/
+int do_check()
+{
+  int i;
+  int retval = 0;
+  struct flock fl;
+
+  fl.l_whence = SEEK_SET;
+  fl.l_start = 0;
+  fl.l_len = 10;
+
+  /* All std.. are open. */
+  if (fcntl(0, F_GETFD) == -1) retval |= 0x11;
+  if (fcntl(1, F_GETFD) == -1) retval |= 0x11;
+  if (fcntl(2, F_GETFD) == -1) retval |= 0x11;
+
+  /* Fd no. 3, 4, 7 and 8 are open. */
+  if (fcntl(3, F_GETFD) == -1) retval |= 0x12;
+  if (fcntl(4, F_GETFD) == -1) retval |= 0x12;
+  if (fcntl(7, F_GETFD) == -1) retval |= 0x12;
+
+  /* Fd no. 5, 6 and 9 trough OPEN_MAX are closed. */
+  if (fcntl(5, F_GETFD) != -1) retval |= 0x14;
+  if (fcntl(6, F_GETFD) != -1) retval |= 0x14;
+  for (i = 9; i < OPEN_MAX; i++)
+	if (fcntl(i, F_GETFD) != -1) retval |= 0x18;
+
+#if 0
+  /* Fd no. 3 is WRLCKed. */
+  fl.l_type = F_WRLCK;
+  if (fcntl(3, F_SETLK, &fl) != -1) retval |= 0x21;
+  if (errno != EACCES && errno != EAGAIN) retval |= 0x22;
+  fl.l_type = F_RDLCK;
+  if (fcntl(3, F_SETLK, &fl) != -1) retval |= 0x24;
+  if (errno != EACCES && errno != EAGAIN) retval |= 0x22;
+  fl.l_type = F_RDLCK;
+  if (fcntl(3, F_GETLK, &fl) == -1) retval |= 0x28;
+  if (fl.l_type != F_WRLCK) retval |= 0x28;
+  if (fl.l_pid != getpid()) retval |= 0x28;
+  fl.l_type = F_WRLCK;
+  if (fcntl(3, F_GETLK, &fl) == -1) retval |= 0x28;
+  if (fl.l_type != F_WRLCK) retval |= 0x28;
+  if (fl.l_pid != getpid()) retval |= 0x28;
+#endif
+
+  /* Fd no. 4 is not locked. */
+  fl.l_type = F_WRLCK;
+  if (fcntl(4, F_SETLK, &fl) == -1) retval |= 0x41;
+  if (fcntl(4, F_GETLK, &fl) == -1) retval |= 0x42;
+#if 0 /* XXX - see test7.c */
+  if (fl.l_type != F_WRLCK) retval |= 0x42;
+  if (fl.l_pid != getpid()) retval |= 0x42;
+#endif /* 0 */
+
+  /* Fd no. 8 is locked after the fork, it is ours. */
+  fl.l_type = F_WRLCK;
+  if (fcntl(8, F_SETLK, &fl) == -1) retval |= 0x44;
+  if (fcntl(8, F_GETLK, &fl) == -1) retval |= 0x48;
+#if 0 /* XXX - see test7.c */
+  if (fl.l_type != F_WRLCK) retval |= 0x48;
+  if (fl.l_pid != getpid()) retval |= 0x48;
+#endif /* 0 */
+
+#if 0
+  /* Fd no. 7 is RDLCKed. */
+  fl.l_type = F_WRLCK;
+  if (fcntl(7, F_SETLK, &fl) != -1) retval |= 0x81;
+  if (errno != EACCES && errno != EAGAIN) retval |= 0x82;
+  fl.l_type = F_RDLCK;
+  if (fcntl(7, F_SETLK, &fl) == -1) retval |= 0x84;
+  fl.l_type = F_RDLCK;
+  if (fcntl(7, F_GETLK, &fl) == -1) retval |= 0x88;
+  if (fl.l_type != F_UNLCK) retval |= 0x88;
+  fl.l_type = F_WRLCK;
+  if (fcntl(7, F_GETLK, &fl) == -1) retval |= 0x88;
+  if (fl.l_type != F_RDLCK) retval |= 0x88;
+  if (fl.l_pid != getppid()) retval |= 0x88;
+#endif
+
+  return retval;
+}
+
+void makelongnames()
+{
+  register int i;
+
+  memset(MaxName, 'a', NAME_MAX);
+  MaxName[NAME_MAX] = '\0';
+  for (i = 0; i < PATH_MAX - 1; i++) {	/* idem path */
+	MaxPath[i++] = '.';
+	MaxPath[i] = '/';
+  }
+  MaxPath[PATH_MAX - 1] = '\0';
+
+  strcpy(ToLongName, MaxName);	/* copy them Max to ToLong */
+  strcpy(ToLongPath, MaxPath);
+
+  ToLongName[NAME_MAX] = 'a';
+  ToLongName[NAME_MAX + 1] = '\0';	/* extend ToLongName by one too many */
+  ToLongPath[PATH_MAX - 1] = '/';
+  ToLongPath[PATH_MAX] = '\0';	/* inc ToLongPath by one */
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  System("rm -rf DIR_20");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else if (errct < 10000) {
+	printf("%d errors\n", errct);
+	exit(1);
+  } else {
+	printf("errors\n");
+	exit(2);
+  }
+}
Index: /trunk/minix/test/test21.c
===================================================================
--- /trunk/minix/test/test21.c	(revision 9)
+++ /trunk/minix/test/test21.c	(revision 9)
@@ -0,0 +1,685 @@
+/* POSIX test program (21).			Author: Andy Tanenbaum */
+
+/* The following POSIX calls are tested:
+ *
+ *	rename(),  mkdir(),  rmdir()
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define ITERATIONS        1
+#define MAX_ERROR 4
+
+int subtest, errct;
+
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(void test21a, (void));
+_PROTOTYPE(void test21b, (void));
+_PROTOTYPE(void test21c, (void));
+_PROTOTYPE(void test21d, (void));
+_PROTOTYPE(void test21e, (void));
+_PROTOTYPE(void test21f, (void));
+_PROTOTYPE(void test21g, (void));
+_PROTOTYPE(void test21h, (void));
+_PROTOTYPE(void test21i, (void));
+_PROTOTYPE(void test21k, (void));
+_PROTOTYPE(void test21l, (void));
+_PROTOTYPE(void test21m, (void));
+_PROTOTYPE(void test21n, (void));
+_PROTOTYPE(void test21o, (void));
+_PROTOTYPE(int get_link, (char *name));
+_PROTOTYPE(void e, (int n));
+_PROTOTYPE(void quit, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+
+  int i, m = 0xFFFF;
+
+  sync();
+  if (geteuid() == 0 || getuid() == 0) {
+	printf("Test 21 cannot run as root; test aborted\n");
+	exit(1);
+  }
+
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 21 ");
+  fflush(stdout);
+
+  system("rm -rf DIR_21; mkdir DIR_21");
+  chdir("DIR_21");
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 00001) test21a();
+	if (m & 00002) test21b();
+	if (m & 00004) test21c();
+	if (m & 00010) test21d();
+	if (m & 00020) test21e();
+	if (m & 00040) test21f();
+	if (m & 01000) test21g();
+	if (m & 00200) test21h();
+	if (m & 00400) test21i();
+	if (m & 01000) test21k();
+	if (m & 02000) test21l();
+	if (m & 04000) test21m();
+	if (m & 010000) test21n();
+	if (m & 020000) test21o();
+  }
+  quit();
+  return(-1);			/* impossible */
+}
+
+void test21a()
+{
+/* Test rename(). */
+
+  int fd, fd2;
+  char buf[PATH_MAX+1], buf1[PATH_MAX+1], buf2[PATH_MAX+1];
+  struct stat stat1, stat2;
+
+  subtest = 1;
+
+  unlink("A1");			/* get rid of it if it exists */
+  unlink("A2");			/* get rid of it if it exists */
+  unlink("A3");			/* get rid of it if it exists */
+  unlink("A4");			/* get rid of it if it exists */
+  unlink("A5");			/* get rid of it if it exists */
+  unlink("A6");			/* get rid of it if it exists */
+  unlink("A7");			/* get rid of it if it exists */
+
+  /* Basic test.  Rename A1 to A2 and then A2 to A3. */
+  if ( (fd=creat("A1", 0666)) < 0) e(1);
+  if (write(fd, buf, 20) != 20) e(2);
+  if (close(fd) < 0) e(3);
+  if (rename("A1", "A2") < 0) e(4);
+  if ( (fd=open("A2", O_RDONLY)) < 0) e(5);
+  if (rename("A2", "A3") < 0) e(6);
+  if ( (fd2=open("A3", O_RDONLY)) < 0) e(7);
+  if (close(fd) != 0) e(8);
+  if (close(fd2) != 0) e(9);
+  if (unlink("A3") != 0) e(10);
+
+  /* Now get the absolute path name of the current directory using getcwd()
+   * and use it to test RENAME using different combinations of relative and
+   * absolute path names.
+   */
+  if (getcwd(buf, PATH_MAX) == (char *) NULL) e(11);
+  if ( (fd = creat("A4", 0666)) < 0) e(12);
+  if (write(fd, buf, 30) != 30) e(13);
+  if (close(fd) != 0) e(14);
+  strcpy(buf1, buf);
+  strcat(buf1, "/A4");
+  if (rename(buf1, "A5") != 0) e(15);	/* rename(absolute, relative) */
+  if (access("A5", 6) != 0) e(16);	/* use access to see if file exists */
+  strcpy(buf2, buf);
+  strcat(buf2, "/A6");
+  if (rename("A5", buf2) != 0) e(17);	/* rename(relative, absolute) */
+  if (access("A6", 6) != 0) e(18);
+  if (access(buf2, 6) != 0) e(19);
+  strcpy(buf1, buf);
+  strcat(buf1, "/A6");
+  strcpy(buf2, buf);
+  strcat(buf2, "/A7");
+  if (rename(buf1, buf2) != 0) e(20);	/* rename(absolute, absolute) */
+  if (access("A7", 6) != 0) e(21);
+  if (access(buf2, 6) != 0) e(22);
+
+  /* Try renaming using names like "./A8" */
+  if (rename("A7", "./A8") != 0) e(23);
+  if (access("A8", 6) != 0) e(24);
+  if (rename("./A8", "A9") != 0) e(25);
+  if (access("A9", 6) != 0) e(26);
+  if (rename("./A9", "./A10") != 0) e(27);
+  if (access("A10", 6) != 0) e(28);
+  if (access("./A10", 6) != 0) e(29);
+  if (unlink("A10") != 0) e(30);
+
+  /* Now see if directories can be renamed. */
+  if (system("rm -rf ?uzzy scsi") != 0) e(31);
+  if (system("mkdir fuzzy") != 0) e(32);
+  if (rename("fuzzy", "wuzzy") != 0) e(33);
+  if ( (fd=creat("wuzzy/was_a_bear", 0666)) < 0) e(34);
+  if (access("wuzzy/was_a_bear", 6) != 0) e(35);
+  if (unlink("wuzzy/was_a_bear") != 0) e(36);
+  if (close(fd) != 0) e(37);
+  if (rename("wuzzy", "buzzy") != 0) e(38);
+  if (system("rmdir buzzy") != 0) e(39);
+
+  /* Now start testing the case that 'new' exists. */
+  if ( (fd = creat("horse", 0666)) < 0) e(40);
+  if ( (fd2 = creat("sheep", 0666)) < 0) e(41);
+  if (write(fd, buf, PATH_MAX) != PATH_MAX) e(42);
+  if (write(fd2, buf, 23) != 23) e(43);
+  if (stat("horse", &stat1) != 0) e(44);
+  if (rename("horse", "sheep") != 0) e(45);
+  if (stat("sheep", &stat2) != 0) e(46);
+  if (stat1.st_dev != stat2.st_dev) e(47);
+  if (stat1.st_ino != stat2.st_ino) e(48);
+  if (stat2.st_size != PATH_MAX) e(49);
+  if (access("horse", 6) == 0) e(50);
+  if (close(fd) != 0) e(51);
+  if (close(fd2) != 0) e(52);
+  if (rename("sheep", "sheep") != 0) e(53);
+  if (unlink("sheep") != 0) e(54);
+
+  /* Now try renaming something to a directory that already exists. */
+  if (system("mkdir fuzzy wuzzy") != 0) e(55);
+  if ( (fd = creat("fuzzy/was_a_bear", 0666)) < 0) e(56);
+  if (close(fd) != 0) e(57);
+  if (rename("fuzzy", "wuzzy") != 0) e(58);	/* 'new' is empty dir */
+  if (system("mkdir scsi") != 0) e(59);
+  if (rename("scsi", "wuzzy") == 0) e(60);	/* 'new' is full dir */
+  if (errno != EEXIST && errno != ENOTEMPTY) e(61);
+
+  /* Test 14 character names--always tricky. */
+  if (rename("wuzzy/was_a_bear", "wuzzy/was_not_a_bear") != 0) e(62);
+  if (access("wuzzy/was_not_a_bear", 6) != 0) e(63);
+  if (rename("wuzzy/was_not_a_bear", "wuzzy/was_not_a_duck") != 0) e(64);
+  if (access("wuzzy/was_not_a_duck", 6) != 0) e(65);
+  if (rename("wuzzy/was_not_a_duck", "wuzzy/was_a_bird") != 0) e(65);
+  if (access("wuzzy/was_a_bird", 6) != 0) e(66);
+
+  /* Test moves between directories. */
+  if (rename("wuzzy/was_a_bird", "beast") != 0) e(67);
+  if (access("beast", 6) != 0) e(68);
+  if (rename("beast", "wuzzy/was_a_cat") != 0) e(69);
+  if (access("wuzzy/was_a_cat", 6) != 0) e(70);
+
+  /* Test error conditions. 'scsi' and 'wuzzy/was_a_cat' exist now. */
+  if (rename("wuzzy/was_a_cat", "wuzzy/was_a_dog") != 0) e(71);
+  if (access("wuzzy/was_a_dog", 6) != 0) e(72);
+  if (chmod("wuzzy", 0) != 0) e(73);
+
+  errno = 0;
+  if (rename("wuzzy/was_a_dog", "wuzzy/was_a_pig") != -1) e(74);
+  if (errno != EACCES) e(75);
+
+  errno = 0;
+  if (rename("wuzzy/was_a_dog", "doggie") != -1) e(76);
+  if (errno != EACCES) e(77);
+
+  errno = 0;
+  if ( (fd = creat("beast", 0666)) < 0) e(78);
+  if (close(fd) != 0) e(79);
+  if (rename("beast", "wuzzy/was_a_twit") != -1) e(80);
+  if (errno != EACCES) e(81);
+
+  errno = 0;
+  if (rename("beast", "wuzzy") != -1) e(82);
+  if (errno != EISDIR) e(83);
+
+  errno = 0;
+  if (rename("beest", "baste") != -1) e(84);
+  if (errno != ENOENT) e(85);
+
+  errno = 0;
+  if (rename("wuzzy", "beast") != -1) e(86);
+  if (errno != ENOTDIR) e(87);
+
+  /* Test prefix rule. */
+  errno = 0;
+  if (chmod("wuzzy", 0777) != 0) e(88);
+  if (unlink("wuzzy/was_a_dog") != 0) e(89);
+  strcpy(buf1, buf);
+  strcat(buf1, "/wuzzy");
+  if (rename(buf, buf1) != -1) e(90);
+  if (errno != EINVAL) e(91);
+
+  if (system("rm -rf wuzzy beast scsi") != 0) e(92);
+}
+
+  
+
+void test21b()
+{
+/* Test mkdir() and rmdir(). */
+
+  int i;
+  char name[3];
+  struct stat statbuf;
+
+  subtest = 2;
+
+  /* Simple stuff. */
+  if (mkdir("D1", 0700) != 0) e(1);
+  if (stat("D1", &statbuf) != 0) e(2);
+  if (!S_ISDIR(statbuf.st_mode)) e(3);
+  if ( (statbuf.st_mode & 0777) != 0700) e(4);
+  if (rmdir("D1") != 0) e(5);
+
+  /* Make and remove 40 directories.  By doing so, the directory has to
+   * grow to 2 blocks.  That presents plenty of opportunity for bugs.
+   */
+  name[0] = 'D';
+  name[2] = '\0';
+  for (i = 0; i < 40; i++) {
+	name[1] = 'A' + i;
+	if (mkdir(name, 0700 + i%7) != 0) e(10+i);	/* for simplicity */
+  }
+  for (i = 0; i < 40; i++) {
+	name[1] = 'A' + i;
+	if (rmdir(name) != 0) e(50+i);
+  }
+}
+
+void test21c()
+{
+/* Test mkdir() and rmdir(). */
+
+  subtest = 3;
+
+  if (mkdir("D1", 0777) != 0) e(1);
+  if (mkdir("D1/D2", 0777) != 0) e(2);
+  if (mkdir("D1/D2/D3", 0777) != 0) e(3);
+  if (mkdir("D1/D2/D3/D4", 0777) != 0) e(4);
+  if (mkdir("D1/D2/D3/D4/D5", 0777) != 0) e(5);
+  if (mkdir("D1/D2/D3/D4/D5/D6", 0777) != 0) e(6);
+  if (mkdir("D1/D2/D3/D4/D5/D6/D7", 0777) != 0) e(7);
+  if (mkdir("D1/D2/D3/D4/D5/D6/D7/D8", 0777) != 0) e(8);
+  if (mkdir("D1/D2/D3/D4/D5/D6/D7/D8/D9", 0777) != 0) e(9);
+  if (access("D1/D2/D3/D4/D5/D6/D7/D8/D9", 7) != 0) e(10);
+  if (rmdir("D1/D2/D3/D4/D5/D6/D7/D8/D9") != 0) e(11);
+  if (rmdir("D1/D2/D3/D4/D5/D6/D7/D8") != 0) e(12);
+  if (rmdir("D1/D2/D3/D4/D5/D6/D7") != 0) e(13);
+  if (rmdir("D1/D2/D3/D4/D5/D6") != 0) e(11);
+  if (rmdir("D1/D2/D3/D4/D5") != 0) e(13);
+  if (rmdir("D1/D2/D3/D4") != 0) e(14);
+  if (rmdir("D1/D2/D3") != 0) e(15);
+  if (rmdir("D1/D2") != 0) e(16);
+  if (rmdir("D1") != 0) e(17);
+}
+  
+void test21d()
+{
+/* Test making directories with files and directories in them. */
+
+  int fd1, fd2, fd3, fd4, fd5, fd6, fd7, fd8, fd9;
+
+  subtest = 4;
+  
+  if (mkdir("D1", 0777) != 0) e(1);
+  if (mkdir("D1/D2", 0777) != 0) e(2);
+  if (mkdir("./D1/D3", 0777) != 0) e(3);
+  if (mkdir("././D1/D4", 0777) != 0) e(4);
+  if ( (fd1 = creat("D1/D2/x", 0700)) < 0) e(5);
+  if ( (fd2 = creat("D1/D2/y", 0700)) < 0) e(6);
+  if ( (fd3 = creat("D1/D2/z", 0700)) < 0) e(7);
+  if ( (fd4 = creat("D1/D3/x", 0700)) < 0) e(8);
+  if ( (fd5 = creat("D1/D3/y", 0700)) < 0) e(9);
+  if ( (fd6 = creat("D1/D3/z", 0700)) < 0) e(10);
+  if ( (fd7 = creat("D1/D4/x", 0700)) < 0) e(11);
+  if ( (fd8 = creat("D1/D4/y", 0700)) < 0) e(12);
+  if ( (fd9 = creat("D1/D4/z", 0700)) < 0) e(13);
+  if (unlink("D1/D2/z") != 0) e(14);
+  if (unlink("D1/D2/y") != 0) e(15);
+  if (unlink("D1/D2/x") != 0) e(16);
+  if (unlink("D1/D3/x") != 0) e(17);
+  if (unlink("D1/D3/z") != 0) e(18);
+  if (unlink("D1/D3/y") != 0) e(19);
+  if (unlink("D1/D4/y") != 0) e(20);
+  if (unlink("D1/D4/z") != 0) e(21);
+  if (unlink("D1/D4/x") != 0) e(22);
+  if (rmdir("D1/D2") != 0) e(23);
+  if (rmdir("D1/D3") != 0) e(24);
+  if (rmdir("D1/D4") != 0) e(25);
+  if (rmdir("D1") != 0) e(26);
+  if (close(fd1) != 0) e(27);
+  if (close(fd2) != 0) e(28);
+  if (close(fd3) != 0) e(29);
+  if (close(fd4) != 0) e(30);
+  if (close(fd5) != 0) e(31);
+  if (close(fd6) != 0) e(32);
+  if (close(fd7) != 0) e(33);
+  if (close(fd8) != 0) e(34);
+  if (close(fd9) != 0) e(35);
+
+}
+
+void test21e()
+{
+/* Test error conditions. */
+  
+  subtest = 5;
+
+  if (mkdir("D1", 0677) != 0) e(1);
+  errno = 0;
+  if (mkdir("D1/D2", 0777) != -1) e(2);
+  if (errno != EACCES) e(3);
+  if (chmod ("D1", 0577) != 0) e(4);
+  errno = 0;
+  if (mkdir("D1/D2", 0777) != -1) e(5);
+  if (errno != EACCES) e(6);
+  if (chmod ("D1", 0777) != 0) e(7);
+  errno = 0;
+  if (mkdir("D1", 0777) != -1) e(8);
+  if (errno != EEXIST) e(9);
+#if NAME_MAX == 14
+  if (mkdir("D1/ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0777) != 0) e(10);
+  if (access("D1/ABCDEFGHIJKLMN", 7 ) != 0) e(11);
+  if (rmdir("D1/ABCDEFGHIJKLMNOPQ") != 0) e(12);
+  if (access("D1/ABCDEFGHIJKLMN", 7 ) != -1) e(13);
+#endif
+  errno = 0;
+  if (mkdir("D1/D2/x", 0777) != -1) e(14);
+  if (errno != ENOENT) e(15);
+
+  /* A particularly nasty test is when the parent has mode 0.  Although
+   * this is unlikely to work, it had better not muck up the file system
+   */
+  if (mkdir("D1/D2", 0777) != 0) e(16);
+  if (chmod("D1", 0) != 0) e(17);
+  errno = 0;
+  if (rmdir("D1/D2") != -1) e(18);
+  if (errno != EACCES) e(19);
+  if (chmod("D1", 0777) != 0) e(20);
+  if (rmdir("D1/D2") != 0) e(21);
+  if (rmdir("D1") != 0) e(22);
+}
+
+void test21f()
+{
+/* The rename() function affects the link count of all the files and
+ * directories it goes near.  Test to make sure it gets everything ok.
+ * There are four cases:
+ *
+ *   1. rename("d1/file1", "d1/file2");	- rename file without moving it
+ *   2. rename("d1/file1", "d2/file2");	- move a file to another dir
+ *   3. rename("d1/dir1", "d2/dir2");	- rename a dir without moving it
+ *   4. rename("d1/dir1", "d2/dir2");	- move a dir to another dir
+ *
+ * Furthermore, a distinction has to be made when the target file exists
+ * and when it does not exist, giving 8 cases in all.
+ */
+
+  int fd, D1_before, D1_after, x_link, y_link;
+
+  /* Test case 1: renaming a file within the same directory. */
+  subtest = 6;
+  if (mkdir("D1", 0777) != 0) e(1);
+  if ( (fd = creat("D1/x", 0777)) < 0) e(2);
+  if (close(fd) != 0) e(3);
+  D1_before = get_link("D1");
+  x_link = get_link("D1/x");
+  if (rename("D1/x", "D1/y") != 0) e(4);
+  y_link = get_link("D1/y");
+  D1_after = get_link("D1");
+  if (D1_before != 2) e(5);
+  if (D1_after != 2) e(6);
+  if (x_link != 1) e(7);
+  if (y_link != 1) e(8);
+  if (access("D1/y", 7) != 0) e(9);
+  if (unlink("D1/y") != 0) e(10);
+  if (rmdir("D1") != 0) e(11);
+}
+
+void test21g()
+{
+  int fd, D1_before, D1_after, D2_before, D2_after, x_link, y_link;
+
+  /* Test case 2: move a file to a new directory. */
+  subtest = 7;
+  if (mkdir("D1", 0777) != 0) e(1);
+  if (mkdir("D2", 0777) != 0) e(2);
+  if ( (fd = creat("D1/x", 0777)) < 0) e(3);
+  if (close(fd) != 0) e(4);
+  D1_before = get_link("D1");
+  D2_before = get_link("D2");
+  x_link = get_link("D1/x");
+  if (rename("D1/x", "D2/y") != 0) e(5);
+  y_link = get_link("D2/y");
+  D1_after = get_link("D1");
+  D2_after = get_link("D2");
+  if (D1_before != 2) e(6);
+  if (D2_before != 2) e(7);
+  if (D1_after != 2) e(8);
+  if (D2_after != 2) e(9);
+  if (x_link != 1) e(10);
+  if (y_link != 1) e(11);
+  if (access("D2/y", 7) != 0) e(12);
+  if (unlink("D2/y") != 0) e(13);
+  if (rmdir("D1") != 0) e(14);
+  if (rmdir("D2") != 0) e(15);
+}
+
+void test21h()
+{
+  int D1_before, D1_after, x_link, y_link;
+
+  /* Test case 3: renaming a directory within the same directory. */
+  subtest = 8;
+  if (mkdir("D1", 0777) != 0) e(1);
+  if (mkdir("D1/X", 0777) != 0) e(2);
+  D1_before = get_link("D1");
+  x_link = get_link("D1/X");
+  if (rename("D1/X", "D1/Y") != 0) e(3);
+  y_link = get_link("D1/Y");
+  D1_after = get_link("D1");
+  if (D1_before != 3) e(4);
+  if (D1_after != 3) e(5);
+  if (x_link != 2) e(6);
+  if (y_link != 2) e(7);
+  if (access("D1/Y", 7) != 0) e(8);
+  if (rmdir("D1/Y") != 0) e(9);
+  if (get_link("D1") != 2) e(10);
+  if (rmdir("D1") != 0) e(11);
+}
+
+void test21i()
+{
+  int D1_before, D1_after, D2_before, D2_after, x_link, y_link;
+
+  /* Test case 4: move a directory to a new directory. */
+  subtest = 9;
+  if (mkdir("D1", 0777) != 0) e(1);
+  if (mkdir("D2", 0777) != 0) e(2);
+  if (mkdir("D1/X", 0777) != 0) e(3);
+  D1_before = get_link("D1");
+  D2_before = get_link("D2");
+  x_link = get_link("D1/X");
+  if (rename("D1/X", "D2/Y") != 0) e(4);
+  y_link = get_link("D2/Y");
+  D1_after = get_link("D1");
+  D2_after = get_link("D2");
+  if (D1_before != 3) e(5);
+  if (D2_before != 2) e(6);
+  if (D1_after != 2) e(7);
+  if (D2_after != 3) e(8);
+  if (x_link != 2) e(9);
+  if (y_link != 2) e(10);
+  if (access("D2/Y", 7) != 0) e(11);
+  if (rename("D2/Y", "D1/Z") != 0) e(12);
+  if (get_link("D1") != 3) e(13);
+  if (get_link("D2") != 2) e(14);
+  if (rmdir("D1/Z") != 0) e(15);
+  if (get_link("D1") != 2) e(16);
+  if (rmdir("D1") != 0) e(17);
+  if (rmdir("D2") != 0) e(18);
+}
+
+void test21k()
+{
+/* Now test the same 4 cases, except when the target exists. */
+
+  int fd, D1_before, D1_after, x_link, y_link;
+
+  /* Test case 5: renaming a file within the same directory. */
+  subtest = 10;
+  if (mkdir("D1", 0777) != 0) e(1);
+  if ( (fd = creat("D1/x", 0777)) < 0) e(2);
+  if (close(fd) != 0) e(3);
+  if ( (fd = creat("D1/y", 0777)) < 0) e(3);
+  if (close(fd) != 0) e(4);
+  D1_before = get_link("D1");
+  x_link = get_link("D1/x");
+  if (rename("D1/x", "D1/y") != 0) e(5);
+  y_link = get_link("D1/y");
+  D1_after = get_link("D1");
+  if (D1_before != 2) e(6);
+  if (D1_after != 2) e(7);
+  if (x_link != 1) e(8);
+  if (y_link != 1) e(9);
+  if (access("D1/y", 7) != 0) e(10);
+  if (unlink("D1/y") != 0) e(11);
+  if (rmdir("D1") != 0) e(12);
+}
+
+void test21l()
+{
+  int fd, D1_before, D1_after, D2_before, D2_after, x_link, y_link;
+
+  /* Test case 6: move a file to a new directory. */
+  subtest = 11;
+  if (mkdir("D1", 0777) != 0) e(1);
+  if (mkdir("D2", 0777) != 0) e(2);
+  if ( (fd = creat("D1/x", 0777)) < 0) e(3);
+  if (close(fd) != 0) e(4);
+  if ( (fd = creat("D2/y", 0777)) < 0) e(5);
+  if (close(fd) != 0) e(6);
+  D1_before = get_link("D1");
+  D2_before = get_link("D2");
+  x_link = get_link("D1/x");
+  if (rename("D1/x", "D2/y") != 0) e(7);
+  y_link = get_link("D2/y");
+  D1_after = get_link("D1");
+  D2_after = get_link("D2");
+  if (D1_before != 2) e(8);
+  if (D2_before != 2) e(9);
+  if (D1_after != 2) e(10);
+  if (D2_after != 2) e(11);
+  if (x_link != 1) e(12);
+  if (y_link != 1) e(13);
+  if (access("D2/y", 7) != 0) e(14);
+  if (unlink("D2/y") != 0) e(15);
+  if (rmdir("D1") != 0) e(16);
+  if (rmdir("D2") != 0) e(17);
+}
+
+void test21m()
+{
+  int D1_before, D1_after, x_link, y_link;
+
+  /* Test case 7: renaming a directory within the same directory. */
+  subtest = 12;
+  if (mkdir("D1", 0777) != 0) e(1);
+  if (mkdir("D1/X", 0777) != 0) e(2);
+  if (mkdir("D1/Y", 0777) != 0) e(3);
+  D1_before = get_link("D1");
+  x_link = get_link("D1/X");
+  if (rename("D1/X", "D1/Y") != 0) e(4);
+  y_link = get_link("D1/Y");
+  D1_after = get_link("D1");
+  if (D1_before != 4) e(5);
+  if (D1_after != 3) e(6);
+  if (x_link != 2) e(7);
+  if (y_link != 2) e(8);
+  if (access("D1/Y", 7) != 0) e(9);
+  if (rmdir("D1/Y") != 0) e(10);
+  if (get_link("D1") != 2) e(11);
+  if (rmdir("D1") != 0) e(12);
+}
+
+void test21n()
+{
+  int D1_before, D1_after, D2_before, D2_after, x_link, y_link;
+
+  /* Test case 8: move a directory to a new directory. */
+  subtest = 13;
+  if (mkdir("D1", 0777) != 0) e(1);
+  if (mkdir("D2", 0777) != 0) e(2);
+  if (mkdir("D1/X", 0777) != 0) e(3);
+  if (mkdir("D2/Y", 0777) != 0) e(4);
+  D1_before = get_link("D1");
+  D2_before = get_link("D2");
+  x_link = get_link("D1/X");
+  if (rename("D1/X", "D2/Y") != 0) e(5);
+  y_link = get_link("D2/Y");
+  D1_after = get_link("D1");
+  D2_after = get_link("D2");
+  if (D1_before != 3) e(6);
+  if (D2_before != 3) e(7);
+  if (D1_after != 2) e(8);
+  if (D2_after != 3) e(9);
+  if (x_link != 2) e(10);
+  if (y_link != 2) e(11);
+  if (access("D2/Y", 7) != 0) e(12);
+  if (rename("D2/Y", "D1/Z") != 0) e(13);
+  if (get_link("D1") != 3) e(14);
+  if (get_link("D2") != 2) e(15);
+  if (rmdir("D1/Z") != 0) e(16);
+  if (get_link("D1") != 2) e(17);
+  if (rmdir("D1") != 0) e(18);
+  if (rmdir("D2") != 0) e(19);
+}
+
+void test21o()
+{
+  /* Test trying to remove . and .. */
+  subtest = 14;
+  if (mkdir("D1", 0777) != 0) e(1);
+  if (chdir("D1") != 0) e(2);
+  if (rmdir(".") == 0) e(3);
+  if (rmdir("..") == 0) e(4);
+  if (mkdir("D2", 0777) != 0) e(5);
+  if (mkdir("D3", 0777) != 0) e(6);
+  if (mkdir("D4", 0777) != 0) e(7);
+  if (rmdir("D2/../D3/../D4") != 0) e(8);	/* legal way to remove D4 */
+  if (rmdir("D2/../D3/../D2/..") == 0) e(9);	/* removing self is illegal */
+  if (rmdir("D2/../D3/../D2/../..") == 0) e(10);/* removing parent is illegal*/
+  if (rmdir("../D1/../D1/D3") != 0) e(11);	/* legal way to remove D3 */
+  if (rmdir("./D2/../D2") != 0) e(12);		/* legal way to remove D2 */
+  if (chdir("..") != 0) e(13);
+  if (rmdir("D1") != 0) e(14);
+}
+
+int get_link(name)
+char *name;
+{
+  struct stat statbuf;
+
+  if (stat(name, &statbuf) != 0) {
+	printf("Unable to stat %s\n", name);
+	errct++;
+	return(-1);
+  }
+  return(statbuf.st_nlink);
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* save errno in case printf clobbers it */
+
+  printf("Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
+  errno = err_num;		/* restore errno, just in case */
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+}
+
+void quit()
+{
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test22.c
===================================================================
--- /trunk/minix/test/test22.c	(revision 9)
+++ /trunk/minix/test/test22.c	(revision 9)
@@ -0,0 +1,201 @@
+/* test22: umask()		(p) Jan-Mark Wams. email: jms@cs.vu.nl */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <stdio.h>
+
+#define MAX_ERROR 4		/* Stop after ``MAX_ERROR'' errors. */
+#define ITERATIONS 2
+
+#define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+#define Stat(a,b)	if (stat(a,b) != 0) printf("Can't stat %s\n", a)
+
+int errct = 0;			/* Total error counter. */
+int subtest = 1;
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test22a, (void));
+_PROTOTYPE(int mode, (char *filename));
+_PROTOTYPE(int umode, (char *filename));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 22 ");
+  fflush(stdout);
+  system("chmod 777 DIR_22/* DIR_22/*/* > /dev/null 2>&1");
+  System("rm -rf DIR_22; mkdir DIR_22");
+  Chdir("DIR_22");
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test22a();
+  }
+
+  quit();
+}
+
+void test22a()
+{
+  int fd1, fd2;
+  int i, oldmask;
+  int stat_loc;			/* For the wait sys call. */
+
+  subtest = 1;
+
+  system("chmod 777 ../DIR_22/* ../DIR_22/*/* > /dev/null 2>&1");
+  System("rm -rf ../DIR_22/*");
+
+  oldmask = 0123;		/* Set oldmask and umask. */
+  umask(oldmask);		/* Set oldmask and umask. */
+
+  /* Check all the possible values of umask. */
+  for (i = 0000; i <= 0777; i++) {
+	if (oldmask != umask(i)) e(1);	/* set umask() */
+	fd1 = open("open", O_CREAT, 0777);
+	if (fd1 != 3) e(2);	/* test open(), */
+	fd2 = creat("creat", 0777);
+	if (fd2 != 4) e(3);	/* creat(), */
+	if (mkdir("dir", 0777) != 0) e(4);	/* mkdir(), */
+	if (mkfifo("fifo", 0777) != 0) e(5);	/* and mkfifo(). */
+
+	if (umode("open") != i) e(6);	/* see if they have */
+	if (umode("creat") != i) e(7);	/* the proper mode */
+	if (umode("dir") != i) e(8);
+	if (umode("fifo") != i) e(9);
+
+	/* Clean up */
+	if (close(fd1) != 0) e(10);
+	if (close(fd2) != 0) e(11);	/* close fd's and */
+	unlink("open");		/* clean the dir */
+	unlink("creat");
+	rmdir("dir");
+	unlink("fifo");
+	oldmask = i;		/* save current mask */
+  }
+
+  /* Check-reset mask */
+  if (umask(0124) != 0777) e(12);
+
+  /* Check if a umask of 0000 leaves the modes alone. */
+  if (umask(0000) != 0124) e(13);
+  for (i = 0000; i <= 0777; i++) {
+	fd1 = open("open", O_CREAT, i);
+	if (fd1 != 3) e(14);	/* test open(), */
+	fd2 = creat("creat", i);
+	if (fd2 != 4) e(15);	/* creat(), */
+	if (mkdir("dir", i) != 0) e(16);	/* mkdir(), */
+	if (mkfifo("fifo", i) != 0) e(17);	/* and mkfifo(). */
+
+	if (mode("open") != i) e(18);	/* see if they have */
+	if (mode("creat") != i) e(19);	/* the proper mode */
+	if (mode("dir") != i) e(20);
+	if (mode("fifo") != i) e(21);
+
+	/* Clean up */
+	if (close(fd1) != 0) e(22);
+	if (close(fd2) != 0) e(23);
+	if (unlink("open") != 0) e(24);
+	unlink("creat");
+	rmdir("dir");
+	unlink("fifo");
+  }
+
+  /* Check if umask survives a fork() */
+  if (umask(0124) != 0000) e(25);
+  switch (fork()) {
+      case -1:	fprintf(stderr, "Can't fork\n");	break;
+      case 0:
+	mkdir("bar", 0777);	/* child makes a dir */
+	exit(0);
+      default:
+	if (wait(&stat_loc) == -1) e(26);
+  }
+  if (umode("bar") != 0124) e(27);
+  rmdir("bar");
+
+  /* Check if umask in child changes umask in parent. */
+  switch (fork()) {
+      case -1:	fprintf(stderr, "Can't fork\n");	break;
+      case 0:
+	switch (fork()) {
+	    case -1:
+		fprintf(stderr, "Can't fork\n");
+		break;
+	    case 0:
+		if (umask(0432) != 0124) e(28);
+		exit(0);
+	    default:
+		if (wait(&stat_loc) == -1) e(29);
+	}
+	if (umask(0423) != 0124) e(30);
+	exit(0);
+      default:
+	if (wait(&stat_loc) == -1) e(31);
+  }
+  if (umask(0342) != 0124) e(32);
+
+  /* See if extra bits are ignored */
+  if (umask(0xFFFF) != 0342) e(33);
+  if (umask(0xFE00) != 0777) e(34);
+  if (umask(01777) != 0000) e(35);
+  if (umask(0022) != 0777) e(36);
+}
+
+int mode(arg)
+char *arg;
+{				/* return the file mode. */
+  struct stat st;
+  Stat(arg, &st);
+  return st.st_mode & 0777;
+}
+
+int umode(arg)
+char *arg;
+{				/* return the umask used for this file */
+  return 0777 ^ mode(arg);
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  system("chmod 777 ../DIR_22/* ../DIR_22/*/* > /dev/null 2>&1");
+  System("rm -rf DIR_22");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test23.c
===================================================================
--- /trunk/minix/test/test23.c	(revision 9)
+++ /trunk/minix/test/test23.c	(revision 9)
@@ -0,0 +1,415 @@
+/* test23: chdir(), getcwd()	Author: Jan-Mark Wams (jms@cs.vu.nl) */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include <limits.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#define MAX_ERROR 4
+#define ITERATIONS 3
+
+#define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+
+int errct;
+int subtest;
+int superuser;			/* True if we are root. */
+
+char cwd[PATH_MAX];		/* Space for path names. */
+char cwd2[PATH_MAX];
+char buf[PATH_MAX];
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];		/* Same for path */
+char ToLongName[NAME_MAX + 2];	/* Name of maximum +1 length */
+char ToLongPath[PATH_MAX + 1];	/* Same for path, both too long */
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test23a, (void));
+_PROTOTYPE(void test23b, (void));
+_PROTOTYPE(void test23c, (void));
+_PROTOTYPE(void makelongnames, (void));	/* Fill MaxName etc. */
+_PROTOTYPE(char *last_index, (char *string, int ch));
+_PROTOTYPE(char *my_getcwd, (char *buf, int size));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 23 ");
+  fflush(stdout);
+  System("rm -rf DIR_23; mkdir DIR_23");
+  Chdir("DIR_23");
+  makelongnames();
+  superuser = (geteuid() == 0);
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test23a();	/* Test normal operation */
+	if (m & 0002) test23b();	/* Test critical operation */
+	if (m & 0004) test23c();	/* Test error operation */
+  }
+
+  quit();
+}
+
+void test23a()
+{				/* Test normal operation. */
+  register int i;
+
+  subtest = 1;
+
+  System("rm -rf ../DIR_23/*");
+
+  /* Let's do some fiddeling with path names. */
+  if (getcwd(cwd, PATH_MAX) != cwd) e(1);
+  if (chdir(cwd) != 0) e(2);
+  if (getcwd(buf, PATH_MAX) != buf) e(3);
+  if (strcmp(buf, cwd) != 0) e(4);
+  if (chdir(".") != 0) e(5);
+  if (getcwd(buf, PATH_MAX) != buf) e(6);
+  if (strcmp(buf, cwd) != 0) e(7);
+  if (chdir("./././.") != 0) e(8);
+  if (getcwd(buf, PATH_MAX) != buf) e(9);
+  if (strcmp(buf, cwd) != 0) e(10);
+
+  /* Creat a working dir named "foo", remove any previous residues. */
+  System("rm -rf foo");
+  if (mkdir("foo", 0777) != 0) e(11);
+
+  /* Do some more fiddeling with path names. */
+  if (chdir("foo/.././foo/..") != 0) e(12);	/* change to cwd */
+  if (getcwd(buf, PATH_MAX) != buf) e(13);
+  if (strcmp(buf, cwd) != 0) e(13);
+  if (chdir("foo") != 0) e(14);	/* change to foo */
+  if (chdir("..") != 0) e(15);	/* and back again */
+  if (getcwd(buf, PATH_MAX) != buf) e(16);
+  if (strcmp(buf, cwd) != 0) e(17);
+
+  /* Make 30 sub dirs, eg. ./bar/bar/bar/bar/bar...... */
+  System("rm -rf bar");		/* get ridd of bar */
+  for (i = 0; i < 30; i++) {
+	if (mkdir("bar", 0777) != 0) e(18);
+	if (chdir("bar") != 0) e(19);	/* change to bar */
+  }
+  for (i = 0; i < 30; i++) {
+	if (chdir("..") != 0) e(20);	/* and back again */
+	if (rmdir("bar") != 0) e(21);
+  }
+
+  /* Make sure we are back where we started. */
+  if (getcwd(buf, PATH_MAX) != buf) e(22);
+  if (strcmp(buf, cwd) != 0) e(23);
+  System("rm -rf bar");		/* just incase */
+
+  /* Do some normal checks on `Chdir()' and `getcwd()' */
+  if (chdir("/") != 0) e(24);
+  if (getcwd(buf, PATH_MAX) != buf) e(25);
+  if (strcmp(buf, "/") != 0) e(26);
+  if (chdir("..") != 0) e(27);	/* go to parent of / */
+  if (getcwd(buf, PATH_MAX) != buf) e(28);
+  if (strcmp(buf, "/") != 0) e(29);
+  if (chdir(cwd) != 0) e(30);
+  if (getcwd(buf, PATH_MAX) != buf) e(31);
+  if (strcmp(buf, cwd) != 0) e(32);
+  if (chdir("/etc") != 0) e(33);	/* /etc might be on RAM */
+  if (getcwd(buf, PATH_MAX) != buf) e(34);	/* might make a difference */
+  if (strcmp(buf, "/etc") != 0) e(35);
+  if (chdir(cwd) != 0) e(36);
+  if (getcwd(buf, PATH_MAX) != buf) e(37);
+  if (strcmp(buf, cwd) != 0) e(38);
+  if (chdir(".//.//") != 0) e(39);	/* .//.// == current dir */
+  if (getcwd(buf, PATH_MAX) != buf) e(40);
+  if (strcmp(buf, cwd) != 0) e(41);	/* we might be at '/' */
+#ifdef _MINIX
+  /* XXX - my_getcwd() is old rubbish.  It reads the directory directly instead
+   * of through the directory library.  It uses a fixed size buffer instead of
+   * a size related to PATH_MAX, NAME_MAX or the size required.
+   */
+  if (my_getcwd(buf, PATH_MAX) != buf) e(42);	/* get cwd my way */
+  if (strcmp(cwd, buf) != 0) e(43);
+#endif
+  System("rm -rf foo");
+}
+
+void test23b()
+{				/* Test critical values. */
+  subtest = 2;
+
+  System("rm -rf ../DIR_23/*");
+
+  /* Fiddle with the size (2nt) parameter of `getcwd ()'. */
+  if (getcwd(cwd, PATH_MAX) != cwd) e(1);	/* get cwd */
+  if (getcwd(buf, strlen(cwd)) != (char *) 0) e(2);   /* size 1 to small */
+  if (errno != ERANGE) e(3);
+  if (getcwd(buf, PATH_MAX) != buf) e(4);
+  if (strcmp(buf, cwd) != 0) e(5);
+  Chdir(cwd);			/* getcwd might cd / */
+  if (getcwd(buf, strlen(cwd) + 1) != buf) e(6);	/* size just ok */
+  if (getcwd(buf, PATH_MAX) != buf) e(7);
+  if (strcmp(buf, cwd) != 0) e(8);
+
+  /* Let's see how "MaxName" and "ToLongName" are handled. */
+  if (mkdir(MaxName, 0777) != 0) e(9);
+  if (chdir(MaxName) != 0) e(10);
+  if (chdir("..") != 0) e(11);
+  if (rmdir(MaxName) != 0) e(12);
+  if (getcwd(buf, PATH_MAX) != buf) e(13);
+  if (strcmp(buf, cwd) != 0) e(14);
+  if (chdir(MaxPath) != 0) e(15);
+  if (getcwd(buf, PATH_MAX) != buf) e(16);
+  if (strcmp(buf, cwd) != 0) e(17);
+
+  if (chdir(ToLongName) != -1) e(18);
+#ifdef _POSIX_NO_TRUNC
+# if _POSIX_NO_TRUNC - 0 != -1
+  if (errno != ENAMETOOLONG) e(20);
+# else
+  if (errno != ENOENT) e(20);
+# endif
+#else
+# include "error, this case requires dynamic checks and is not handled"
+#endif
+
+  if (getcwd(buf, PATH_MAX) != buf) e(21);
+  if (strcmp(buf, cwd) != 0) e(22);
+  if (chdir(ToLongPath) != -1) e(23);
+  if (errno != ENAMETOOLONG) e(24);
+  if (getcwd(buf, PATH_MAX) != buf) e(25);
+  if (strcmp(buf, cwd) != 0) e(26);
+}
+
+void test23c()
+{				/* Check reaction to errors */
+  subtest = 3;
+
+  System("rm -rf ../DIR_23/*");
+
+  if (getcwd(cwd, PATH_MAX) != cwd) e(1);	/* get cwd */
+
+  /* Creat a working dir named "foo", remove any previous residues. */
+  System("rm -rf foo; mkdir foo");
+
+  /* Check some obviouse errors. */
+  if (chdir("") != -1) e(2);
+  if (errno != ENOENT) e(3);
+  if (getcwd(buf, PATH_MAX) != buf) e(4);
+  if (strcmp(buf, cwd) != 0) e(5);
+  if (getcwd(buf, 0) != (char *) 0) e(6);
+  if (errno != EINVAL) e(7);
+  if (getcwd(buf, PATH_MAX) != buf) e(8);
+  if (strcmp(buf, cwd) != 0) e(9);
+  if (getcwd(buf, 0) != (char *) 0) e(10);
+  if (errno != EINVAL) e(11);
+  if (getcwd(buf, PATH_MAX) != buf) e(12);
+  if (strcmp(buf, cwd) != 0) e(13);
+  if (chdir(cwd) != 0) e(14);	/* getcwd might be buggy. */
+
+  /* Change the mode of foo, and check the effect. */
+  if (chdir("foo") != 0) e(15);	/* change to foo */
+  if (mkdir("bar", 0777) != 0) e(16);	/* make a new dir bar */
+  if (getcwd(cwd2, PATH_MAX) != cwd2) e(17);	/* get the new cwd */
+  if (getcwd(buf, 3) != (char *) 0) e(18);	/* size is too small */
+  if (errno != ERANGE) e(19);
+  if (getcwd(buf, PATH_MAX) != buf) e(20);
+  if (strcmp(buf, cwd2) != 0) e(21);
+  Chdir(cwd2);			/* getcwd() might cd / */
+  System("chmod 377 .");	/* make foo unreadable */
+  if (getcwd(buf, PATH_MAX) != buf) e(22);	/* dir not readable */
+  if (getcwd(buf, PATH_MAX) != buf) e(23);
+  if (strcmp(buf, cwd2) != 0) e(24);
+  if (chdir("bar") != 0) e(25);	/* at .../foo/bar */
+  if (!superuser) {
+	if (getcwd(buf, PATH_MAX) != (char *) 0) e(26);
+	if (errno != EACCES) e(27);
+  }
+  if (superuser) {
+	if (getcwd(buf, PATH_MAX) != buf) e(28);
+  }
+  if (chdir(cwd2) != 0) e(29);
+  if (getcwd(buf, PATH_MAX) != buf) e(30);
+  if (strcmp(buf, cwd2) != 0) e(31);
+  System("chmod 677 .");	/* make foo inaccessable */
+  if (!superuser) {
+	if (getcwd(buf, PATH_MAX) != (char *) 0) e(32);	/* try to get cwd */
+	if (errno != EACCES) e(33);	/* but no access */
+	if (chdir("..") != -1) e(34);	/* try to get back */
+	if (errno != EACCES) e(35);	/* again no access */
+	if (chdir(cwd) != 0) e(36);	/* get back to cwd */
+	/* `Chdir()' might do path optimizing, it shouldn't. */
+	if (chdir("foo/..") != -1) e(37);	/* no op */
+	if (chdir("foo") != -1) e(38);	/* try to cd to foo */
+	if (errno != EACCES) e(39);	/* no have access */
+	if (getcwd(buf, PATH_MAX) != buf) e(40);
+	if (strcmp(buf, cwd) != 0) e(41);
+  }
+  if (superuser) {
+	if (getcwd(buf, PATH_MAX) != buf) e(42);
+	if (strcmp(buf, cwd2) != 0) e(43);
+	if (chdir("..") != 0) e(44);	/* get back to cwd */
+	if (chdir("foo") != 0) e(45);	/* get back to foo */
+	if (chdir(cwd) != 0) e(46);	/* get back to cwd */
+  }
+  if (getcwd(buf, PATH_MAX) != buf) e(47);	/* check we are */
+  if (strcmp(buf, cwd) != 0) e(48);	/* back at cwd. */
+  Chdir(cwd);			/* just in case... */
+
+  if (chdir("/etc/passwd") != -1) e(49);	/* try to change to a file */
+  if (errno != ENOTDIR) e(50);
+  if (getcwd(buf, PATH_MAX) != buf) e(51);
+  if (strcmp(buf, cwd) != 0) e(52);
+  if (chdir("/notexist") != -1) e(53);
+  if (errno != ENOENT) e(54);
+  if (getcwd(buf, PATH_MAX) != buf) e(55);
+  if (strcmp(buf, cwd) != 0) e(56);
+  System("chmod 777 foo");
+  if (chdir("foo") != 0) e(57);
+
+  /* XXX - this comment was botched by 'pretty'. */
+  /* * Since `foo' is the cwd, it should not be removeable but * if it
+   * were, this code would be found here; *
+   * 
+   *  System ("cd .. ; rm -rf foo");	remove foo *  if (chdir (".")
+   * != -1) e();		try go to. *  if (errno != ENOENT) e();
+   * hould not be an entry *  if (chdir ("..") != -1) e();	try
+   * to get back *  if (errno != ENOENT) e();		should not be
+   * an entry *  if (getcwd (buf, PATH_MAX) != (char *)0) e(); don't
+   * know where we are *
+   * 
+   * What should errno be now ? The cwd might be gone if te superuser *
+   * removed the cwd. (Might even have linked it first.) But this *
+   * testing should be done by the test program for `rmdir()'. */
+  if (chdir(cwd) != 0) e(58);
+}
+
+void makelongnames()
+{
+  register int i;
+
+  memset(MaxName, 'a', NAME_MAX);
+  MaxName[NAME_MAX] = '\0';
+  for (i = 0; i < PATH_MAX - 1; i++) {	/* idem path */
+	MaxPath[i++] = '.';
+	MaxPath[i] = '/';
+  }
+  MaxPath[PATH_MAX - 1] = '\0';
+
+  strcpy(ToLongName, MaxName);	/* copy them Max to ToLong */
+  strcpy(ToLongPath, MaxPath);
+
+  ToLongName[NAME_MAX] = 'a';
+  ToLongName[NAME_MAX + 1] = '\0';	/* extend ToLongName by one too many */
+  ToLongPath[PATH_MAX - 1] = '/';
+  ToLongPath[PATH_MAX] = '\0';	/* inc ToLongPath by one */
+}
+
+/* The following code, is take from pwd written by Adri Koppes */
+
+/* My_getcwd() helper. */
+char *last_index(string, ch)
+char *string;
+char ch;
+{
+  register char *retval = '\0';
+
+  while (*string != '\0') {
+	if (*string == ch) retval = string;
+	string++;
+  }
+  return(retval);
+}
+
+char *my_getcwd(buf, size)
+char *buf;
+int size;
+{				/* should be like getcwd() */
+  int sd;
+  register int fd;
+  register char *n;
+  char name[128];
+  struct stat s, st, sk;
+  struct direct d;
+
+  if (size <= 0) return(char *) 0;
+
+  *buf = '\0';
+  *name = '\0';
+  stat(".", &s);
+  do {
+	if ((fd = open("..", O_RDONLY)) < 0) return(char *) 0;
+	st.st_dev = s.st_dev;
+	st.st_ino = s.st_ino;
+	stat("..", &s);
+	Chdir("..");
+	sd = sizeof(struct direct);
+	if (s.st_dev == st.st_dev) {
+		do {
+			if (read(fd, (char *) &d, sd) < sd) return(char *) 0;
+		} while (d.d_ino != st.st_ino);
+	} else {
+		do {
+			if (read(fd, (char *) &d, sd) < sd) return(char *) 0;
+			stat(d.d_name, &sk);
+		} while ((sk.st_dev != st.st_dev) ||
+			 (sk.st_ino != st.st_ino));
+	}
+	close(fd);
+	if (strcmp(".", d.d_name) != 0) {
+		strcat(name, "/");
+		strcat(name, d.d_name);
+	}
+  } while ((s.st_ino != st.st_ino) || (s.st_dev != st.st_dev));
+  if (*name == '\0')
+	strncat(buf, "/", size);
+  else
+	while ((n = last_index(name, '/')) != NULL) {
+		n[NAME_MAX] = '\0';
+		strncat(buf, n, size - strlen(buf));
+		*n = '\0';
+	}
+  strncat(buf, name, size - strlen(buf));
+  buf[size - 1] = '\0';
+  Chdir(buf);			/* get back there */
+  return buf;
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  System("rm -rf DIR_23");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test24.c
===================================================================
--- /trunk/minix/test/test24.c	(revision 9)
+++ /trunk/minix/test/test24.c	(revision 9)
@@ -0,0 +1,399 @@
+/* Test24: opendir, readdir, rewinddir, closedir       Author: Jan-Mark Wams */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void chk_dir, (DIR * dirpntr));
+_PROTOTYPE(void test24a, (void));
+_PROTOTYPE(void test24b, (void));
+_PROTOTYPE(void test24c, (void));
+_PROTOTYPE(void makelongnames, (void));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+
+#define OVERFLOW_DIR_NR	(OPEN_MAX + 1)
+#define MAX_ERROR	4
+#define ITERATIONS 5
+
+#define DIRENT0	((struct dirent *) NULL)
+#define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+
+int errct = 0;
+int subtest = 1;
+int superuser;
+
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];		/* Same for path */
+char ToLongName[NAME_MAX + 2];	/* Name of maximum +1 length */
+char ToLongPath[PATH_MAX + 1];	/* Same for path, both too long */
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 24 ");
+  fflush(stdout);
+  System("rm -rf DIR_24; mkdir DIR_24");
+  Chdir("DIR_24");
+  makelongnames();
+  superuser = (geteuid() == 0);
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test24a();
+	if (m & 0002) test24b();
+	if (m & 0004) test24c();
+  }
+  quit();
+}
+
+void test24a()
+{				/* Test normal operations. */
+  int fd3, fd4, fd5;
+  DIR *dirp;
+  int j, ret, fd, flags;
+  struct stat st1, st2;
+  int stat_loc;
+  time_t time1;
+
+  subtest = 1;
+
+  System("rm -rf ../DIR_24/*");
+
+  if ((fd = dup(0)) != 3) e(1);	/* dup stdin */
+  close(fd);			/* free the fd again */
+  dirp = opendir("/");		/* open "/" */
+  if (dirp == ((DIR *) NULL)) e(2);	/* has to succseed */
+  if ((fd = dup(0)) <= 2) e(3);	/* dup stdin */
+  if (fd > 3) {			/* if opendir() uses fd 3 */
+	flags = fcntl(3, F_GETFD);	/* get fd fags of 3 */
+	if (!(flags & FD_CLOEXEC)) e(4);	/* it should be closed on */
+  }				/* exec..() calls */
+  close(fd);			/* free the fd again */
+  ret = closedir(dirp);		/* close, we don't need it */
+  if (ret == -1) e(5);		/* closedir () unsucces full */
+  if (ret != 0) e(6);		/* should be 0 or -1 */
+  if ((fd = dup(0)) != 3) e(7);	/* see if next fd is same */
+  close(fd);			/* free the fd again */
+
+  System("rm -rf foo; mkdir foo");
+  Chdir("foo");
+  System("touch f1 f2 f3 f4 f5");	/* make f1 .. f5 */
+  System("rm f[24]");		/* creat `holes' in entrys */
+  Chdir("..");
+
+  if ((dirp = opendir("foo")) == ((DIR *) NULL)) e(8);	/* open foo */
+  chk_dir(dirp);		/* test if foo's ok */
+  for (j = 0; j < 10; j++) {
+	errno = j * 47 % 7;	/* there should */
+	if (readdir(dirp) != DIRENT0) e(9);	/* be nomore dir */
+	if (errno != j * 47 % 7) e(10);	/* entrys */
+  }
+  rewinddir(dirp);		/* rewind foo */
+  chk_dir(dirp);		/* test foosok */
+  for (j = 0; j < 10; j++) {
+	errno = j * 23 % 7;	/* there should */
+	if (readdir(dirp) != DIRENT0) e(11);	/* be nomore dir */
+	if (errno != j * 23 % 7) e(12);	/* entrys */
+  }
+  if ((fd4 = creat("foo/f4", 0666)) <= 2) e(13);	/* Open a file. */
+  System("rm foo/f4");		/* Kill entry. */
+  rewinddir(dirp);		/* Rewind foo. */
+  if ((fd3 = open("foo/f3", O_WRONLY)) <= 2) e(14);	/* Open more files. */
+  if ((fd5 = open("foo/f5", O_WRONLY)) <= 2) e(15);
+  if (write(fd3, "Hello", 6) != 6) e(16);
+  if (write(fd4, "Hello", 6) != 6) e(17);	/* write some data */
+  if (close(fd5) != 0) e(18);
+  chk_dir(dirp);
+  for (j = 0; j < 10; j++) {
+	errno = j * 101 % 7;	/* there should */
+	if (readdir(dirp) != DIRENT0) e(19);	/* be nomore dir */
+	if (errno != j * 101 % 7) e(20);	/* entrys */
+  }
+  if (close(fd4) != 0) e(21);	/* shouldn't matter */
+  if (close(fd3) != 0) e(22);	/* when we do this */
+  if (closedir(dirp) != 0) e(23);	/* close foo again */
+
+  Chdir("foo");
+  if ((dirp = opendir(".//")) == ((DIR *) NULL)) e(24);	/* open foo again */
+  Chdir("..");
+  chk_dir(dirp);		/* foosok? */
+  for (j = 0; j < 10; j++) {
+	errno = (j * 101) % 7;	/* there should */
+	if (readdir(dirp) != DIRENT0) e(25);	/* be nomore dir */
+	if (errno != (j * 101) % 7) e(26);	/* entrys */
+  }
+
+  if (closedir(dirp) != 0) e(27);	/* It should be closable */
+
+  stat("foo", &st1);		/* get stat */
+  time(&time1);
+  while (time1 >= time((time_t *)0))
+	;
+  if ((dirp = opendir("foo")) == ((DIR *) NULL)) e(28);	/* open, */
+  if (readdir(dirp) == DIRENT0) e(29);	/* read and */
+  stat("foo", &st2);		/* get new stat */
+  if (st1.st_atime > st2.st_atime) e(30);	/* st_atime check */
+
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	rewinddir(dirp);	/* rewind childs dirp */
+	if (readdir(dirp) == DIRENT0) e(31);	/* read should be ok */
+	if (closedir(dirp) != 0) e(32);	/* close child'd foo */
+	exit(0);		/* 0 stops here */
+      default:
+	if (wait(&stat_loc) == -1) e(33);	/* PARENT wait()'s */
+	break;
+  }
+  if (closedir(dirp) != 0) e(34);	/* close parent's foo */
+}
+
+void test24b()
+{
+/* See what happens with too many dir's open.  Check if file size seems ok, 
+ * and independency.
+ */
+
+  int i, j;			/* i = highest open dir count */
+  DIR *dirp[OVERFLOW_DIR_NR], *dp;
+  struct dirent *dep, *dep1, *dep2;
+  char name[NAME_MAX + 2];	/* buffer for file name, and count */
+  int dot = 0, dotdot = 0;
+
+  subtest = 2;
+
+  System("rm -rf ../DIR_24/*");
+
+  for (i = 0; i < OVERFLOW_DIR_NR; i++) {
+	dirp[i] = opendir("/");
+	if (dirp[i] == ((DIR *) NULL)) {
+		if (errno != EMFILE) e(1);
+		break;
+	}
+  }
+  if (i <= 4) e(2);		/* sounds resanable */
+  if (i >= OVERFLOW_DIR_NR) e(3);	/* might be to small */
+  for (j = 0; j < i; j++) {
+	if (closedir(dirp[(j + 5) % i]) != 0) e(4);	/* neat! */
+  }
+
+  /* Now check if number of bytes in d_name can go up till NAME_MAX */
+  System("rm -rf foo; mkdir foo");
+  Chdir("foo");
+  name[0] = 0;
+  for (i = 0; i <= NAME_MAX; i++) {
+	if (strcat(name, "X") != name) e(5);
+	close(creat(name, 0666));	/* fails once on */
+  }				/* XX..XX, 1 too long */
+  Chdir("..");
+  /* Now change i-th X to Y in name buffer record file of length i. */
+  if ((dp = opendir("foo")) == ((DIR *) NULL)) e(6);
+  while ((dep = readdir(dp)) != DIRENT0) {
+	if (strcmp("..", dep->d_name) == 0)
+		dotdot++;
+	else if (strcmp(".", dep->d_name) == 0)
+		dot++;
+	else
+		name[strlen(dep->d_name)] += 1;	/* 'X' + 1 == 'Y' */
+  }
+  if (closedir(dp) != 0) e(7);
+  for (i = 1; i <= NAME_MAX; i++) {	/* Check if every length */
+	if (name[i] != 'Y') e(8);	/* has been seen once. */
+  }
+
+  /* Check upper and lower bound. */
+  if (name[0] != 'X') e(9);
+  if (name[NAME_MAX + 1] != '\0') e(10);
+
+  /* Now check if two simultaniouse open dirs do the same */
+  if ((dirp[1] = opendir("foo")) == ((DIR *) NULL)) e(11);
+  if ((dirp[2] = opendir("foo")) == ((DIR *) NULL)) e(12);
+  if ((dep1 = readdir(dirp[1])) == DIRENT0) e(13);
+  if ((dep2 = readdir(dirp[2])) == DIRENT0) e(14);
+  if (dep1->d_name == dep2->d_name) e(15);	/* 1 & 2 Should be */
+  strcpy(name, dep2->d_name);	/* differand buffers */
+  if (strcmp(dep1->d_name, name) != 0) e(16);	/* But hold the same */
+  if ((dep1 = readdir(dirp[1])) == DIRENT0) e(17);
+  if ((dep1 = readdir(dirp[1])) == DIRENT0) e(18);	/* lose some entries */
+  if ((dep1 = readdir(dirp[1])) == DIRENT0) e(19);	/* Using dirp 1 has */
+  if (dep1->d_name == dep2->d_name) e(20);	/* no effect on 2 */
+  if (strcmp(dep2->d_name, name) != 0) e(21);
+  rewinddir(dirp[1]);		/* Rewinding dirp 1 */
+  if ((dep2 = readdir(dirp[2])) == DIRENT0) e(22);	/* can't effect 2 */
+  if (strcmp(dep2->d_name, name) == 0) e(23);	/* Must be next */
+  if (closedir(dirp[1]) != 0) e(24);	/* Closing dirp 1 */
+  if ((dep2 = readdir(dirp[2])) == DIRENT0) e(25);	/* can't effect 2 */
+  if (strcmp(dep2->d_name, name) == 0) e(26);	/* Must be next */
+  if (closedir(dirp[2]) != 0) e(27);
+}
+
+void test24c()
+{
+/* Test whether wrong things go wrong right. */
+
+  DIR *dirp;
+
+  subtest = 3;
+
+  System("rm -rf ../DIR_24/*");
+
+  if (opendir("foo/bar/nono") != ((DIR *) NULL)) e(1);	/* nonexistent */
+  if (errno != ENOENT) e(2);
+  System("mkdir foo; chmod 677 foo");	/* foo inaccesable */
+  if (opendir("foo/bar/nono") != ((DIR *) NULL)) e(3);
+  if (superuser) {
+	if (errno != ENOENT) e(4);	/* su has access */
+	System("chmod 377 foo");
+	if ((dirp = opendir("foo")) == ((DIR *) NULL)) e(5);
+	if (closedir(dirp) != 0) e(6);
+  }
+  if (!superuser) {
+	if (errno != EACCES) e(7);	/* we don't ;-) */
+	System("chmod 377 foo");
+	if (opendir("foo") != ((DIR *) NULL)) e(8);
+  }
+  System("chmod 777 foo");
+
+  if (mkdir(MaxName, 0777) != 0) e(9);	/* make longdir */
+  if ((dirp = opendir(MaxName)) == ((DIR *) NULL)) e(10);	/* open it */
+  if (closedir(dirp) != 0) e(11);	/* close it */
+  if (rmdir(MaxName) != 0) e(12);	/* then remove it */
+  if ((dirp = opendir(MaxPath)) == ((DIR *) NULL)) e(13);	/* open '.'  */
+  if (closedir(dirp) != 0) e(14);	/* close it */
+#if 0 /* XXX - anything could happen with the bad pointer */
+  if (closedir(dirp) != -1) e(15);	/* close it again */
+  if (closedir(dirp) != -1) e(16);	/* and again */
+#endif /* 0 */
+  if (opendir(ToLongName) != ((DIR *) NULL)) e(17);	/* is too long */
+#ifdef _POSIX_NO_TRUNC
+# if _POSIX_NO_TRUNC - 0 != -1
+  if (errno != ENAMETOOLONG) e(18);
+# else
+  if (errno != ENOENT) e(19);
+# endif
+#else
+# include "error, this case requires dynamic checks and is not handled"
+#endif
+  if (opendir(ToLongPath) != ((DIR *) NULL)) e(20);	/* path is too long */
+  if (errno != ENAMETOOLONG) e(21);
+  System("touch foo/abc");	/* make a file */
+  if (opendir("foo/abc") != ((DIR *) NULL)) e(22);	/* not a dir */
+  if (errno != ENOTDIR) e(23);
+}
+
+void chk_dir(dirp)		/* dir should contain             */
+DIR *dirp;			/* (`f1', `f3', `f5', `.', `..')  */
+{				/* no more, no less               */
+  int f1 = 0, f2 = 0, f3 = 0, f4 = 0, f5 = 0,	/* counters for all */
+   other = 0, dot = 0, dotdot = 0;	/* possible entrys */
+  int i;
+  struct dirent *dep;
+  char *fname;
+  int oldsubtest = subtest;
+
+  subtest = 4;
+
+  for (i = 0; i < 5; i++) {	/* 3 files and `.' and `..' == 5 entrys */
+	dep = readdir(dirp);
+	if (dep == DIRENT0) {	/* not einough */
+		if (dep == DIRENT0) e(1);
+		break;
+	}
+	fname = dep->d_name;
+	if (strcmp(fname, ".") == 0)
+		dot++;
+	else if (strcmp(fname, "..") == 0)
+		dotdot++;
+	else if (strcmp(fname, "f1") == 0)
+		f1++;
+	else if (strcmp(fname, "f2") == 0)
+		f2++;
+	else if (strcmp(fname, "f3") == 0)
+		f3++;
+	else if (strcmp(fname, "f4") == 0)
+		f4++;
+	else if (strcmp(fname, "f5") == 0)
+		f5++;
+	else
+		other++;
+  }				/* do next dir entry */
+
+  if (dot != 1) e(2);		/* Check the entrys */
+  if (dotdot != 1) e(3);
+  if (f1 != 1) e(4);
+  if (f3 != 1) e(5);
+  if (f5 != 1) e(6);
+  if (f2 != 0) e(7);
+  if (f4 != 0) e(8);
+  if (other != 0) e(9);
+
+  subtest = oldsubtest;
+}
+
+void makelongnames()
+{
+  register int i;
+
+  memset(MaxName, 'a', NAME_MAX);
+  MaxName[NAME_MAX] = '\0';
+  for (i = 0; i < PATH_MAX - 1; i++) {	/* idem path */
+	MaxPath[i++] = '.';
+	MaxPath[i] = '/';
+  }
+  MaxPath[PATH_MAX - 1] = '\0';
+
+  strcpy(ToLongName, MaxName);	/* copy them Max to ToLong */
+  strcpy(ToLongPath, MaxPath);
+
+  ToLongName[NAME_MAX] = 'a';
+  ToLongName[NAME_MAX + 1] = '\0';	/* extend ToLongName by one too many */
+  ToLongPath[PATH_MAX - 1] = '/';
+  ToLongPath[PATH_MAX] = '\0';	/* inc ToLongPath by one */
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  System("rm -rf DIR_24");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test25.c
===================================================================
--- /trunk/minix/test/test25.c	(revision 9)
+++ /trunk/minix/test/test25.c	(revision 9)
@@ -0,0 +1,726 @@
+/* test25: open (), close ()	(p) Jan-Mark Wams. email: jms@cs.vu.nl */
+
+/* Not tested: O_NONBLOCK on special files, supporting it.
+** On a read-only file system, some error reports are to be expected.
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+
+#define MAX_ERROR	4
+#define ITERATIONS	2
+
+#define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+#define Stat(a,b)	if (stat(a,b) != 0) printf("Can't stat %s\n", a)
+#define Creat(f)	if (close(creat(f,0777))!=0) printf("Can't creat %s\n",f)
+#define Report(s,n)	printf("Subtest %d" s,subtest,(n))
+
+int errct = 0;
+int subtest = 1;
+int superuser;
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];		/* Same for path */
+char ToLongName[NAME_MAX + 2];	/* Name of maximum +1 length */
+char ToLongPath[PATH_MAX + 1];	/* Same for path, both too long */
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test25a, (void));
+_PROTOTYPE(void test25b, (void));
+_PROTOTYPE(void test25c, (void));
+_PROTOTYPE(void test25d, (void));
+_PROTOTYPE(void test25e, (void));
+_PROTOTYPE(void makelongnames, (void));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (geteuid() == 0 || getuid() == 0) {
+	printf("Test 25 cannot run as root; test aborted\n");
+	exit(1);
+  }
+
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 25 ");
+  fflush(stdout);
+  System("rm -rf DIR_25; mkdir DIR_25");
+  Chdir("DIR_25");
+  makelongnames();
+  superuser = (geteuid() == 0);
+
+  /* Close all files, the parent might have opened. */
+  for (i = 3; i < 100; i++) close(i);
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 001) test25a();
+	if (m & 002) test25b();
+	if (m & 004) test25c();
+	if (m & 010) test25d();
+	if (m & 020) test25e();
+  }
+  quit();
+}
+
+void test25a()
+{				/* Test fcntl flags. */
+  subtest = 1;
+
+#define EXCLUDE(a,b)	(((a)^(b)) == ((a)|(b)))
+#define ADDIT		(O_APPEND | O_CREAT | O_EXCL | O_NONBLOCK | O_TRUNC)
+
+  /* If this compiles all flags are defined but they have to be or-able. */
+  if (!(EXCLUDE(O_NONBLOCK, O_TRUNC))) e(1);
+  if (!(EXCLUDE(O_EXCL, O_NONBLOCK | O_TRUNC))) e(2);
+  if (!(EXCLUDE(O_CREAT, O_EXCL | O_NONBLOCK | O_TRUNC))) e(3);
+  if (!(EXCLUDE(O_APPEND, O_CREAT | O_EXCL | O_NONBLOCK | O_TRUNC))) e(4);
+  if (!(EXCLUDE(O_RDONLY, ADDIT))) e(5);
+  if (!(EXCLUDE(O_WRONLY, ADDIT))) e(6);
+  if (!(EXCLUDE(O_RDWR, ADDIT))) e(7);
+}
+
+void test25b()
+{				/* Test normal operation. */
+
+#define BUF_SIZE 1024
+
+  int fd1, fd2, fd3, fd4, fd5;
+  char buf[BUF_SIZE];
+  struct stat st1, st2, st3;
+  time_t time1, time2;
+  int stat_loc;
+
+  subtest = 2;
+
+  System("rm -rf ../DIR_25/*");
+
+  System("echo Hello > he");	/* make test files */
+  System("echo Hello > ha");	/* size 6 bytes */
+  System("echo Hello > hi");
+  System("echo Hello > ho");
+
+  /* Check path resolution. Check if lowest fds are returned */
+  if ((fd1 = open("he", O_RDONLY)) != 3) e(1);
+  if (read(fd1, buf, BUF_SIZE) != 6) e(2);
+  if ((fd2 = open("./ha", O_RDONLY)) != 4) e(3);
+  if ((fd3 = open("../DIR_25/he", O_RDWR)) != 5) e(4);
+  if ((fd4 = open("ho", O_WRONLY)) != 6) e(5);
+  if (close(fd4) != 0) e(6);
+  if (close(fd1) != 0) e(7);
+  if ((fd1 = open("./././ho", O_RDWR)) != 3) e(8);
+  if ((fd4 = open("../DIR_25/he", O_RDONLY)) != 6) e(9);
+  if (close(fd2) != 0) e(10);
+  if (close(fd3) != 0) e(11);
+  if ((fd2 = open("ha", O_RDONLY)) != 4) e(12);
+  if ((fd3 = open("/etc/passwd", O_RDONLY)) != 5) e(13);
+  if (close(fd4) != 0) e(14);	/* close all */
+  if (close(fd1) != 0) e(15);
+  if (close(fd3) != 0) e(16);
+
+  /* Check if processes share fd2, and if they have independent new fds */
+  System("rm -rf /tmp/sema.25");
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+
+      case 0:
+	if ((fd1 = open("he", O_WRONLY)) != 3) e(17);
+	if ((fd3 = open("../././DIR_25/ha", O_WRONLY)) != 5) e(18);
+	if ((fd4 = open("../DIR_25/hi", O_WRONLY)) != 6) e(19);
+	if ((fd5 = open("ho", O_WRONLY)) != 7) e(20);
+	system("while test ! -f /tmp/sema.25; do sleep 1; done");  /* parent */
+	if (read(fd2, buf, BUF_SIZE) != 3) e(21);	/* gets Hel */
+	if (strncmp(buf, "lo\n", 3) != 0) e(22);	/* we get lo */
+	if (close(fd1) != 0) e(23);
+	if (close(fd2) != 0) e(24);
+	if (close(fd3) != 0) e(25);
+	if (close(fd4) != 0) e(26);
+	if (close(fd5) != 0) e(27);
+	exit(0);
+
+      default:
+	if ((fd1 = open("ha", O_RDONLY)) != 3) e(28);
+	if ((fd3 = open("./he", O_RDONLY)) != 5) e(29);
+	if ((fd4 = open("../DIR_25/hi", O_RDWR)) != 6) e(30);
+	if ((fd5 = open("ho", O_WRONLY)) != 7) e(31);
+	if (close(fd1) != 0) e(32);
+	if (read(fd2, buf, 3) != 3) e(33);	/* get Hel */
+	Creat("/tmp/sema.25");
+	if (strncmp(buf, "Hel", 3) != 0) e(34);
+	if (close(fd2) != 0) e(35);
+	if (close(fd3) != 0) e(36);
+	if (close(fd4) != 0) e(37);
+	if (close(fd5) != 0) e(38);
+	if (wait(&stat_loc) == -1) e(39);
+	if (stat_loc != 0) e(40);
+  }
+  System("rm -f /tmp/sema.25");
+
+  /* Check if the file status information is updated correctly */
+  Stat("hi", &st1);		/* get info */
+  Stat("ha", &st2);		/* of files */
+  time(&time1);
+  while (time1 >= time((time_t *)0))
+	;			/* wait a sec */
+  if ((fd1 = open("hi", O_RDONLY)) != 3) e(41);	/* open files */
+  if ((fd2 = open("ha", O_WRONLY)) != 4) e(42);
+  if (read(fd1, buf, 1) != 1) e(43);	/* read one */
+  if (close(fd1) != 0) e(44);	/* close one */
+  Stat("hi", &st3);		/* get info */
+  if (st1.st_uid != st3.st_uid) e(45);
+  if (st1.st_gid != st3.st_gid) e(46);	/* should be same */
+  if (st1.st_mode != st3.st_mode) e(47);
+  if (st1.st_size != st3.st_size) e(48);
+  if (st1.st_nlink != st3.st_nlink) e(49);
+  if (st1.st_mtime != st3.st_mtime) e(50);
+  if (st1.st_ctime != st3.st_ctime) e(51);
+#ifndef V1_FILESYSTEM
+  if (st1.st_atime >= st3.st_atime) e(52);	/* except for atime. */
+#endif
+  if (write(fd2, "Howdy\n", 6) != 6) e(53);	/* Update c & mtime. */
+  if ((fd1 = open("ha", O_RDWR)) != 3) e(54);
+  if (read(fd1, buf, 6) != 6) e(55);	/* Update atime. */
+  if (strncmp(buf, "Howdy\n", 6) != 0) e(56);
+  if (close(fd1) != 0) e(57);
+  Stat("ha", &st3);
+  if (st2.st_uid != st3.st_uid) e(58);
+  if (st2.st_gid != st3.st_gid) e(59);	/* should be same */
+  if (st2.st_mode != st3.st_mode) e(60);
+  if (st2.st_nlink != st3.st_nlink) e(61);
+  if (st2.st_ctime >= st3.st_ctime) e(62);
+#ifndef V1_FILESYSTEM
+  if (st2.st_atime >= st3.st_atime) e(63);
+#endif
+  if (st2.st_mtime >= st3.st_mtime) e(64);
+  if (st2.st_size != st3.st_size) e(65);
+  if (close(fd2) != 0) e(66);
+
+  /* Let's see if RDONLY files are read only. */
+  if ((fd1 = open("hi", O_RDONLY)) != 3) e(67);
+  if (write(fd1, " again", 7) != -1) e(68);	/* we can't write */
+  if (errno != EBADF) e(69);	/* a read only fd */
+  if (read(fd1, buf, 7) != 6) e(70);	/* but we can read */
+  if (close(fd1) != 0) e(71);
+
+  /* Let's see if WRONLY files are write only. */
+  if ((fd1 = open("hi", O_WRONLY)) != 3) e(72);
+  if (read(fd1, buf, 7) != -1) e(73);	/* we can't read */
+  if (errno != EBADF) e(74);	/* a write only fd */
+  if (write(fd1, "hELLO", 6) != 6) e(75);	/* but we can write */
+  if (close(fd1) != 0) e(76);
+
+  /* Let's see if files are closable only once. */
+  if (close(fd1) != -1) e(77);
+  if (errno != EBADF) e(78);
+
+  /* Let's see how calling close() with bad fds is handled. */
+  if (close(10) != -1) e(79);
+  if (errno != EBADF) e(80);
+  if (close(111) != -1) e(81);
+  if (errno != EBADF) e(82);
+  if (close(-432) != -1) e(83);
+  if (errno != EBADF) e(84);
+
+  /* Let's see if RDWR files are read & write able. */
+  if ((fd1 = open("hi", O_RDWR)) != 3) e(85);
+  if (read(fd1, buf, 6) != 6) e(86);	/* we can read */
+  if (strncmp(buf, "hELLO", 6) != 0) e(87);	/* and we can write */
+  if (write(fd1, "Hello", 6) != 6) e(88);	/* a read write fd */
+  if (close(fd1) != 0) e(89);
+
+  /* Check if APPENDed files are realy appended */
+  if ((fd1 = open("hi", O_RDWR | O_APPEND)) != 3) e(90);	/* open hi */
+
+  /* An open should set the file offset to 0. */
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 0) e(91);
+
+  /* Writing 0 bytes should not have an effect. */
+  if (write(fd1, "", 0) != 0) e(92);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 0) e(93);	/* the end? */
+
+  /* A seek befor a wirte should not matter with O_APPEND. */
+  Stat("hi", &st1);
+  if (lseek(fd1, (off_t) - 3, SEEK_END) != st1.st_size - 3) e(94);
+
+  /* By writing 1 byte, we force the offset to the end of the file */
+  if (write(fd1, "1", 1) != 1) e(95);
+  Stat("hi", &st1);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(96);
+  if (write(fd1, "2", 1) != 1) e(97);
+  Stat("hi", &st1);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(98);
+  if (write(fd1, "3", 1) != 1) e(99);
+  Stat("hi", &st1);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(100);
+  if (lseek(fd1, (off_t) - 2, SEEK_CUR) <= 0) e(101);
+  if (write(fd1, "4", 1) != 1) e(102);
+
+  /* Since the mode was O_APPEND, the offset should be reset to EOF */
+  Stat("hi", &st1);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(103);
+  if (lseek(fd1, (off_t) - 4, SEEK_CUR) != st1.st_size - 4) e(104);
+  if (read(fd1, buf, BUF_SIZE) != 4) e(105);
+  if (strncmp(buf, "1234", 4) != 0) e(106);
+  if (close(fd1) != 0) e(107);
+
+  /* Check the effect of O_CREAT */
+  Stat("ho", &st1);
+  fd1 = open("ho", O_RDWR | O_CREAT, 0000);
+  if (fd1 != 3) e(108);
+  Stat("ho", &st2);
+  if (memcmp(&st1, &st2, sizeof(struct stat)) != 0) e(109);
+  if (read(fd1, buf, 6) != 6) e(110);
+  if (strncmp(buf, "Hello\n", 6) != 0) e(111);
+  if (write(fd1, "@", 1) != 1) e(112);
+  if (close(fd1) != 0) e(113);
+  (void) umask(0000);
+  fd1 = open("ho", O_RDWR | O_CREAT | O_EXCL, 0777);
+  if (fd1 != -1) e(114);	/* ho exists */
+  System("rm -rf new");
+  time(&time1);
+  while (time1 >= time((time_t *)0))	
+	;
+  fd1 = open("new", O_RDWR | O_CREAT, 0716);
+  if (fd1 != 3) e(115);		/* new file */
+  Stat("new", &st1);
+  time(&time2);
+  while (time2 >= time((time_t *)0))
+	;
+  time(&time2);
+  if (st1.st_uid != geteuid()) e(116);	/* try this as superuser. */
+  if (st1.st_gid != getegid()) e(117);
+  if ((st1.st_mode & 0777) != 0716) e(118);
+  if (st1.st_nlink != 1) e(119);
+  if (st1.st_mtime <= time1) e(120);
+  if (st1.st_mtime >= time2) e(121);
+#ifndef V1_FILESYSTEM
+  if (st1.st_atime != st1.st_mtime) e(122);
+#endif
+  if (st1.st_ctime != st1.st_mtime) e(123);
+  if (st1.st_size != 0) e(124);
+  if (write(fd1, "I'm new in town", 16) != 16) e(125);
+  if (lseek(fd1, (off_t) - 5, SEEK_CUR) != 11) e(126);
+  if (read(fd1, buf, 5) != 5) e(127);
+  if (strncmp(buf, "town", 5) != 0) e(128);
+  if (close(fd1) != 0) e(129);
+
+  /* Let's test the O_TRUNC flag on this new file. */
+  time(&time1);
+  while (time1 >= time((time_t *)0));
+  if ((fd1 = open("new", O_RDWR | O_TRUNC)) != 3) e(130);
+  Stat("new", &st1);
+  time(&time2);
+  while (time2 >= time((time_t *)0));
+  time(&time2);
+  if ((st1.st_mode & 0777) != 0716) e(131);
+  if (st1.st_size != (size_t) 0) e(132);	/* TRUNCed ? */
+  if (st1.st_mtime <= time1) e(133);
+  if (st1.st_mtime >= time2) e(134);
+  if (st1.st_ctime != st1.st_mtime) e(135);
+  if (close(fd1) != 0) e(136);
+
+  /* Test if file permission bits and the file ownership are unchanged. */
+  /* So we will see if `O_CREAT' has no effect if the file exists. */
+  if (superuser) {
+	System("echo > bar; chmod 077 bar");	/* Make bar 077 */
+	System("chown daemon bar");
+	System("chgrp daemon bar");	/* Daemon's bar */
+	fd1 = open("bar", O_RDWR | O_CREAT | O_TRUNC, 0777);	/* knock knock */
+	if (fd1 == -1) e(137);
+	if (write(fd1, "foo", 3) != 3) e(138);	/* rewrite bar */
+	if (close(fd1) != 0) e(139);
+	Stat("bar", &st1);
+	if (st1.st_uid != 1) e(140);	/* bar is still */
+	if (st1.st_gid != 1) e(141);	/* owned by daemon */
+	if ((st1.st_mode & 0777) != 077) e(142);	/* mode still is 077 */
+	if (st1.st_size != (size_t) 3) e(143);	/* 3 bytes long */
+
+	/* We do the whole thing again, but with O_WRONLY */
+	fd1 = open("bar", O_WRONLY | O_CREAT | O_TRUNC, 0777);
+	if (fd1 == -1) e(144);
+	if (write(fd1, "foobar", 6) != 6) e(145);	/* rewrite bar */
+	if (close(fd1) != 0) e(146);
+	Stat("bar", &st1);
+	if (st1.st_uid != 1) e(147);	/* bar is still */
+	if (st1.st_gid != 1) e(148);	/* owned by daemon */
+	if ((st1.st_mode & 0777) != 077) e(149);	/* mode still is 077 */
+	if (st1.st_size != (size_t) 6) e(150);	/* 6 bytes long */
+  }
+}
+
+void test25c()
+{				/* Test normal operation Part two. */
+  int fd1, fd2;
+  char buf[BUF_SIZE];
+  struct stat st;
+  int stat_loc;
+  static int iteration=0;
+
+  subtest = 3;
+  iteration++;
+
+  System("rm -rf ../DIR_25/*");
+
+  /* Fifo file test here. */
+  if (mkfifo("fifo", 0777) != 0) e(1);
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);		/* Give child 20 seconds to live. */
+	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(2);
+	if (read(fd1, buf, BUF_SIZE) != 23) e(3);
+	if (strncmp(buf, "1 2 3 testing testing\n", 23) != 0) e(4);
+	if (close(fd1) != 0) e(5);
+	exit(0);
+      default:
+	if ((fd1 = open("fifo", O_WRONLY)) != 3) e(6);
+	if (write(fd1, "1 2 3 testing testing\n", 23) != 23) e(7);
+	if (close(fd1) != 0) e(8);
+	if (wait(&stat_loc) == -1) e(9);
+	if (stat_loc != 0) e(10);	/* The alarm went off? */
+  }
+
+  /* Try opening for writing with O_NONBLOCK. */
+  fd1 = open("fifo", O_WRONLY | O_NONBLOCK);
+  if (fd1 != -1) e(11);
+  if (errno != ENXIO) e(12);
+  close(fd1);
+
+  /* Try opening for writing with O_NONBLOCK and O_CREAT. */
+  fd1 = open("fifo", O_WRONLY | O_CREAT | O_NONBLOCK, 0777);
+  if (fd1 != -1) e(13);
+  if (errno != ENXIO) e(14);
+  close(fd1);
+
+  /* Both the NONBLOCK and the EXCLusive give raise to error. */
+  fd1 = open("fifo", O_WRONLY | O_CREAT | O_EXCL | O_NONBLOCK, 0777);
+  if (fd1 != -1) e(15);
+  if (errno != EEXIST && errno != ENXIO) e(16);
+  close(fd1);			/* Just in case. */
+
+  /* Try opening for reading with O_NONBLOCK. */
+  fd1 = open("fifo", O_RDONLY | O_NONBLOCK);
+  if (fd1 != 3) e(17);
+  if (close(fd1) != 0) e(18);
+
+/* Nopt runs out of memory. ;-< We just cut out some valid code */
+  /* FIFO's should always append. (They have no file position.) */
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);		/* Give child 20 seconds to live. */
+	if ((fd1 = open("fifo", O_WRONLY)) != 3) e(19);
+	if ((fd2 = open("fifo", O_WRONLY)) != 4) e(20);
+	if (write(fd1, "I did see Elvis.\n", 18) != 18) e(21);
+	if (write(fd2, "I DID.\n", 8) != 8) e(22);
+	if (close(fd2) != 0) e(23);
+	if (close(fd1) != 0) e(24);
+	exit(0);
+      default:
+	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(25);
+	if (read(fd1, buf, 18) != 18) e(26);
+	if (strncmp(buf, "I did see Elvis.\n", 18) != 0) e(27);
+	if (read(fd1, buf, BUF_SIZE) != 8) e(28);
+	if (strncmp(buf, "I DID.\n", 8) != 0) e(29);
+	if (close(fd1) != 0) e(30);
+	if (wait(&stat_loc) == -1) e(31);
+	if (stat_loc != 0) e(32);	/* The alarm went off? */
+  }
+
+  /* O_TRUNC should have no effect on FIFO files. */
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);		/* Give child 20 seconds to live. */
+	if ((fd1 = open("fifo", O_WRONLY)) != 3) e(33);
+	if (write(fd1, "I did see Elvis.\n", 18) != 18) e(34);
+	if ((fd2 = open("fifo", O_WRONLY | O_TRUNC)) != 4) e(35);
+	if (write(fd2, "I DID.\n", 8) != 8) e(36);
+	if (close(fd2) != 0) e(37);
+	if (close(fd1) != 0) e(38);
+	exit(0);
+      default:
+	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(39);
+	if (read(fd1, buf, 18) != 18) e(40);
+	if (strncmp(buf, "I did see Elvis.\n", 18) != 0) e(41);
+	if (read(fd1, buf, BUF_SIZE) != 8) e(42);
+	if (strncmp(buf, "I DID.\n", 8) != 0) e(43);
+	if (close(fd1) != 0) e(44);
+	if (wait(&stat_loc) == -1) e(45);
+	if (stat_loc != 0) e(46);	/* The alarm went off? */
+  }
+
+  /* Closing the last fd should flush all data to the bitbucket. */
+  System("rm -rf /tmp/sema.25");
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+
+      case 0:
+	alarm(20);		/* Give child 20 seconds to live. */
+	if ((fd1 = open("fifo", O_WRONLY)) != 3) e(47);
+	if (write(fd1, "I did see Elvis.\n", 18) != 18) e(48);
+	Creat("/tmp/sema.25");
+	sleep(2);		/* give parent a chance to open */
+	/* this was sleep(1), but that's too short: child also sleeps(1) */
+	if (close(fd1) != 0) e(49);
+	exit(0);
+
+      default:
+	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(50);
+	/* Make `sure' write has closed. */
+	while (stat("/tmp/sema.25", &st) != 0) sleep(1);
+	if (close(fd1) != 0) e(51);
+	if ((fd1 = open("fifo", O_RDONLY | O_NONBLOCK)) != 3) e(52);
+	if (read(fd1, buf, BUF_SIZE) != 18) e(53);
+	if (close(fd1) != 0) e(54);
+	if (wait(&stat_loc) == -1) e(55);
+	if (stat_loc != 0) e(56);	/* The alarm went off? */
+  }
+
+  /* Let's try one too many. */
+  System("rm -rf /tmp/sema.25");
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);		/* Give child 20 seconds to live. */
+	if ((fd1 = open("fifo", O_WRONLY)) != 3) e(57);
+	if (write(fd1, "I did see Elvis.\n", 18) != 18) e(58);
+
+	/* Keep open till second reader is opened. */
+	while (stat("/tmp/sema.25", &st) != 0) sleep(1);
+	if (close(fd1) != 0) e(59);
+	exit(0);
+      default:
+	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(60);
+	if (read(fd1, buf, 2) != 2) e(61);
+	if (strncmp(buf, "I ", 2) != 0) e(62);
+	if (close(fd1) != 0) e(63);
+	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(64);
+
+	/* Signal second reader is open. */
+	Creat("/tmp/sema.25");
+	if (read(fd1, buf, 4) != 4) e(65);
+	if (strncmp(buf, "did ", 4) != 0) e(66);
+	if ((fd2 = open("fifo", O_RDONLY)) != 4) e(67);
+	if (read(fd2, buf, BUF_SIZE) != 12) e(68);
+	if (strncmp(buf, "see Elvis.\n", 12) != 0) e(69);
+	if (close(fd2) != 0) e(70);
+	if (close(fd1) != 0) e(71);
+	if (wait(&stat_loc) == -1) e(72);
+	if (stat_loc != 0) e(73);	/* The alarm went off? */
+  }
+  System("rm -rf fifo /tmp/sema.25");
+
+  /* O_TRUNC should have no effect on directroys. */
+  System("mkdir dir; touch dir/f1 dir/f2 dir/f3");
+  if ((fd1 = open("dir", O_WRONLY | O_TRUNC)) != -1) e(74);
+  if (errno != EISDIR) e(75);
+  close(fd1);
+
+  /* Opening a directory for reading should be possible. */
+  if ((fd1 = open("dir", O_RDONLY)) != 3) e(76);
+  if (close(fd1) != 0) e(77);
+  if (unlink("dir/f1") != 0) e(78);	/* Should still be there. */
+  if (unlink("dir/f2") != 0) e(79);
+  if (unlink("dir/f3") != 0) e(80);
+  if (rmdir("dir") != 0) e(81);
+
+  if (!superuser) {
+	/* Test if O_CREAT is not usable to open files with the wrong mode */
+	(void) umask(0200);	/* nono has no */
+	System("touch nono");	/* write bit */
+	(void) umask(0000);
+	fd1 = open("nono", O_RDWR | O_CREAT, 0777);	/* try to open */
+	if (fd1 != -1) e(82);
+	if (errno != EACCES) e(83);	/* but no access */
+  }
+}
+
+void test25d()
+{
+  int fd;
+
+  subtest = 4;
+
+  System("rm -rf ../DIR_25/*");
+
+  /* Test maximal file name length. */
+  if ((fd = open(MaxName, O_RDWR | O_CREAT, 0777)) != 3) e(1);
+  if (close(fd) != 0) e(2);
+  MaxPath[strlen(MaxPath) - 2] = '/';
+  MaxPath[strlen(MaxPath) - 1] = 'a';	/* make ././.../a */
+  if ((fd = open(MaxPath, O_RDWR | O_CREAT, 0777)) != 3) e(3);
+  if (close(fd) != 0) e(4);
+  MaxPath[strlen(MaxPath) - 1] = '/';	/* make ././.../a */
+}
+
+void test25e()
+{
+  int fd;
+  char *noread = "noread";	/* Name for unreadable file. */
+  char *nowrite = "nowrite";	/* Same for unwritable. */
+  int stat_loc;
+
+  subtest = 5;
+
+  System("rm -rf ../DIR_25/*");
+
+  mkdir("bar", 0777);		/* make bar */
+
+  /* Check if no access on part of path generates the correct error. */
+  System("chmod 677 bar");	/* rw-rwxrwx */
+  if (open("bar/nono", O_RDWR | O_CREAT, 0666) != -1) e(1);
+  if (errno != EACCES) e(2);
+
+  /* Ditto for no write permission. */
+  System("chmod 577 bar");	/* r-xrwxrwx */
+  if (open("bar/nono", O_RDWR | O_CREAT, 0666) != -1) e(3);
+  if (errno != EACCES) e(4);
+
+  /* Clean up bar. */
+  System("rm -rf bar");
+
+  /* Improper flags set on existing file. */
+  System("touch noread; chmod 377 noread");	/* noread */
+  if (open(noread, O_RDONLY) != -1) e(5);
+  if (open(noread, O_RDWR) != -1) e(6);
+  if (open(noread, O_RDWR | O_CREAT, 0777) != -1) e(7);
+  if (open(noread, O_RDWR | O_CREAT | O_TRUNC, 0777) != -1) e(8);
+  if ((fd = open(noread, O_WRONLY)) != 3) e(9);
+  if (close(fd) != 0) e(10);
+  System("touch nowrite; chmod 577 nowrite");	/* nowrite */
+  if (open(nowrite, O_WRONLY) != -1) e(11);
+  if (open(nowrite, O_RDWR) != -1) e(12);
+  if (open(nowrite, O_RDWR | O_CREAT, 0777) != -1) e(13);
+  if (open(nowrite, O_RDWR | O_CREAT | O_TRUNC, 0777) != -1) e(14);
+  if ((fd = open(nowrite, O_RDONLY)) != 3) e(15);
+  if (close(fd) != 0) e(16);
+  if (superuser) {
+	/* If we can make a file ownd by some one else, test access again. */
+	System("chmod 733 noread");
+	System("chown bin noread");
+	System("chgrp system noread");
+	System("chmod 755 nowrite");
+	System("chown bin nowrite");
+	System("chgrp system nowrite");
+	switch (fork()) {
+	    case -1:	printf("Can't fork\n");	break;
+	    case 0:
+		setuid(1);
+		setgid(1);	/* become daemon */
+		if (open(noread, O_RDONLY) != -1) e(17);
+		if (open(noread, O_RDWR) != -1) e(18);
+		if (open(noread, O_RDWR | O_CREAT, 0777) != -1) e(19);
+		fd = open(noread, O_RDWR | O_CREAT | O_TRUNC, 0777);
+		if (fd != -1) e(20);
+		if ((fd = open(noread, O_WRONLY)) != 3) e(21);
+		if (close(fd) != 0) e(22);
+		if (open(nowrite, O_WRONLY) != -1) e(23);
+		if (open(nowrite, O_RDWR) != -1) e(24);
+		if (open(nowrite, O_RDWR | O_CREAT, 0777) != -1) e(25);
+		fd = open(nowrite, O_RDWR | O_CREAT | O_TRUNC, 0777);
+		if (fd != -1) e(26);
+		if ((fd = open(nowrite, O_RDONLY)) != 3) e(27);
+		if (close(fd) != 0) e(28);
+		exit(0);
+	    default:
+		if (wait(&stat_loc) == -1) e(29);
+	}
+  }
+
+  /* Clean up the noread and nowrite files. */
+  System("rm -rf noread nowrite");
+
+  /* Test the O_EXCL flag. */
+  System("echo > exists");
+  if (open("exists", O_RDWR | O_CREAT | O_EXCL, 0777) != -1) e(30);
+  if (errno != EEXIST) e(31);
+  if (open("exists", O_RDONLY | O_CREAT | O_EXCL, 0777) != -1) e(32);
+  if (errno != EEXIST) e(33);
+  if (open("exists", O_WRONLY | O_CREAT | O_EXCL, 0777) != -1) e(34);
+  if (errno != EEXIST) e(35);
+  fd = open("exists", O_RDWR | O_CREAT | O_EXCL | O_TRUNC, 0777);
+  if (fd != -1) e(36);
+  if (errno != EEXIST) e(37);
+  fd = open("exists", O_RDONLY | O_CREAT | O_EXCL | O_TRUNC, 0777);
+  if (fd != -1) e(38);
+  if (errno != EEXIST) e(39);
+  fd = open("exists", O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0777);
+  if (fd != -1) e(40);
+  if (errno != EEXIST) e(41);
+
+  /* Test ToLongName and ToLongPath */
+  if ((fd = open(ToLongName, O_RDWR | O_CREAT, 0777)) != 3) e(45);
+  if (close(fd) != 0) e(46);
+  ToLongPath[PATH_MAX - 2] = '/';
+  ToLongPath[PATH_MAX - 1] = 'a';
+  if ((fd = open(ToLongPath, O_RDWR | O_CREAT, 0777)) != -1) e(47);
+  if (errno != ENAMETOOLONG) e(48);
+  if (close(fd) != -1) e(49);
+  ToLongPath[PATH_MAX - 1] = '/';
+}
+
+void makelongnames()
+{
+  register int i;
+
+  memset(MaxName, 'a', NAME_MAX);
+  MaxName[NAME_MAX] = '\0';
+  for (i = 0; i < PATH_MAX - 1; i++) {	/* idem path */
+	MaxPath[i++] = '.';
+	MaxPath[i] = '/';
+  }
+  MaxPath[PATH_MAX - 1] = '\0';
+
+  strcpy(ToLongName, MaxName);	/* copy them Max to ToLong */
+  strcpy(ToLongPath, MaxPath);
+
+  ToLongName[NAME_MAX] = 'a';
+  ToLongName[NAME_MAX + 1] = '\0';	/* extend ToLongName by one too many */
+  ToLongPath[PATH_MAX - 1] = '/';
+  ToLongPath[PATH_MAX] = '\0';	/* inc ToLongPath by one */
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  System("rm -rf DIR_25");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test26.c
===================================================================
--- /trunk/minix/test/test26.c	(revision 9)
+++ /trunk/minix/test/test26.c	(revision 9)
@@ -0,0 +1,276 @@
+/* test26: lseek()		Author: Jan-Mark Wams (jms@cs.vu.nl) */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+
+#define MAX_ERROR	4
+#define ITERATIONS     10
+
+#define System(cmd)   if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)    if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+#define Stat(a,b)     if (stat(a,b) != 0) printf("Can't stat %s\n", a)
+#define Mkfifo(f)     if (mkfifo(f,0777)!=0) printf("Can't make fifo %s\n", f)
+
+int errct = 0;
+int subtest = 1;
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];		/* Same for path */
+char ToLongName[NAME_MAX + 2];	/* Name of maximum +1 length */
+char ToLongPath[PATH_MAX + 1];	/* Same for path, both too long */
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test26a, (void));
+_PROTOTYPE(void test26b, (void));
+_PROTOTYPE(void test26c, (void));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 26 ");
+  fflush(stdout);
+  System("rm -rf DIR_26; mkdir DIR_26");
+  Chdir("DIR_26");
+
+  for (i = 0; i < 10; i++) {
+	if (m & 0001) test26a();
+	if (m & 0002) test26b();
+	if (m & 0004) test26c();
+  }
+  quit();
+}
+
+void test26a()
+{				/* Test normal operation. */
+  int fd;
+  char buf[20];
+  int i, j;
+  struct stat st;
+
+  subtest = 1;
+  System("rm -rf ../DIR_26/*");
+
+  System("echo -n hihaho > hihaho");
+  if ((fd = open("hihaho", O_RDONLY)) != 3) e(1);
+  if (lseek(fd, (off_t) 3, SEEK_SET) != (off_t) 3) e(2);
+  if (read(fd, buf, 1) != 1) e(3);
+  if (buf[0] != 'a') e(4);
+  if (lseek(fd, (off_t) - 1, SEEK_END) != 5) e(5);
+  if (read(fd, buf, 1) != 1) e(6);
+  if (buf[0] != 'o') e(7);
+
+  /* Seek past end of file. */
+  if (lseek(fd, (off_t) 1000, SEEK_END) != 1006) e(8);
+  if (read(fd, buf, 1) != 0) e(9);
+
+  /* Lseek() should not extend the file. */
+  if (fstat(fd, &st) != 0) e(10);
+  if (st.st_size != (off_t) 6) e(11);
+  if (close(fd) != 0) e(12);
+
+  /* Probeer lseek met write. */
+  if ((fd = open("hihaho", O_WRONLY)) != 3) e(13);
+  if (lseek(fd, (off_t) 3, SEEK_SET) != (off_t) 3) e(14);
+  if (write(fd, "e", 1) != 1) e(15);
+  if (lseek(fd, (off_t) 1000, SEEK_END) != 1006) e(16);
+
+  /* Lseek() should not extend the file. */
+  if (fstat(fd, &st) != 0) e(17);
+  if (st.st_size != (off_t) 6) e(18);
+  if (write(fd, "e", 1) != 1) e(19);
+
+  /* Lseek() and a subsequent write should! */
+  if (fstat(fd, &st) != 0) e(20);
+  if (st.st_size != (off_t) 1007) e(21);
+
+  if (close(fd) != 0) e(22);
+
+  /* Check the file, it should start with hiheho. */
+  if ((fd = open("hihaho", O_RDONLY)) != 3) e(23);
+  if (read(fd, buf, 6) != 6) e(24);
+  if (strncmp(buf, "hiheho", 6) != 0) e(25);
+
+  /* The should be zero bytes and a trailing ``e''. */
+  if (sizeof(buf) < 10) e(26);
+  for (i = 1; i <= 20; i++) {
+	if (read(fd, buf, 10) != 10) e(27);
+	for (j = 0; j < 10; j++)
+		if (buf[j] != '\0') break;
+	if (j != 10) e(28);
+	if (lseek(fd, (off_t) 15, SEEK_CUR) != (off_t) i * 25 + 6) e(29);
+  }
+
+  if (lseek(fd, (off_t) 1006, SEEK_SET) != (off_t) 1006) e(30);
+  if (read(fd, buf, sizeof(buf)) != 1) e(31);
+  if (buf[0] != 'e') e(32);
+
+  if (lseek(fd, (off_t) - 1, SEEK_END) != (off_t) 1006) e(33);
+  if (read(fd, buf, sizeof(buf)) != 1) e(34);
+  if (buf[0] != 'e') e(35);
+
+  /* Closing time. */
+  if (close(fd) != 0) e(36);
+}
+
+void test26b()
+{
+  int fd1, fd2, fd3;
+  int stat_loc;
+
+  subtest = 2;
+  System("rm -rf ../DIR_26/*");
+
+  /* See if childs lseek() is effecting the parent. * See also if
+   * lseeking() on same file messes things up. */
+
+  /* Creat a file of 11 bytes. */
+  if ((fd1 = open("santa", O_WRONLY | O_CREAT, 0777)) != 3) e(1);
+  if (write(fd1, "ho ho ho ho", 11) != 11) e(2);
+  if (close(fd1) != 0) e(3);
+
+  /* Open it multiple times. */
+  if ((fd1 = open("santa", O_RDONLY)) != 3) e(4);
+  if ((fd2 = open("santa", O_WRONLY)) != 4) e(5);
+  if ((fd3 = open("santa", O_RDWR)) != 5) e(6);
+
+  /* Set all offsets different. */
+  if (lseek(fd1, (off_t) 2, SEEK_SET) != 2) e(7);
+  if (lseek(fd2, (off_t) 4, SEEK_SET) != 4) e(8);
+  if (lseek(fd3, (off_t) 7, SEEK_SET) != 7) e(9);
+
+  /* Have a child process do additional offset changes. */
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	if (lseek(fd1, (off_t) 1, SEEK_CUR) != 3) e(10);
+	if (lseek(fd2, (off_t) 5, SEEK_SET) != 5) e(11);
+	if (lseek(fd3, (off_t) - 4, SEEK_END) != 7) e(12);
+	exit(0);
+      default:
+	wait(&stat_loc);
+	if (stat_loc != 0) e(13);	/* Alarm? */
+  }
+
+  /* Check if the new offsets are correct. */
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 3) e(14);
+  if (lseek(fd2, (off_t) 0, SEEK_CUR) != 5) e(15);
+  if (lseek(fd3, (off_t) 0, SEEK_CUR) != 7) e(16);
+
+  /* Close the file. */
+  if (close(fd1) != 0) e(17);
+  if (close(fd2) != 0) e(18);
+  if (close(fd3) != 0) e(19);
+}
+
+void test26c()
+{				/* Test error returns. */
+  int fd;
+  int tube[2];
+  int i, stat_loc;
+
+  subtest = 3;
+  System("rm -rf ../DIR_26/*");
+
+  /* Fifo's can't be lseeked(). */
+  Mkfifo("fifo");
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(3);		/* Try for max 3 secs. */
+	if ((fd = open("fifo", O_RDONLY)) != 3) e(1);
+	if (lseek(fd, (off_t) 0, SEEK_SET) != (off_t) - 1) e(2);
+	if (errno != ESPIPE) e(3);
+	if (close(fd) != 0) e(4);
+	exit(0);
+      default:
+	if ((fd = open("fifo", O_WRONLY)) != 3) e(5);
+	wait(&stat_loc);
+	if (stat_loc != 0) e(6);/* Alarm? */
+	if (close(fd) != 0) e(7);
+  }
+
+  /* Pipes can't be lseeked() eigther. */
+  if (pipe(tube) != 0) e(8);
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(3);		/* Max 3 sconds wait. */
+	if (lseek(tube[0], (off_t) 0, SEEK_SET) != (off_t) - 1) e(9);
+	if (errno != ESPIPE) e(10);
+	if (lseek(tube[1], (off_t) 0, SEEK_SET) != (off_t) - 1) e(11);
+	if (errno != ESPIPE) e(12);
+	exit(0);
+      default:
+	wait(&stat_loc);
+	if (stat_loc != 0) e(14);	/* Alarm? */
+  }
+
+  /* Close the pipe. */
+  if (close(tube[0]) != 0) e(15);
+  if (close(tube[1]) != 0) e(16);
+
+  /* Whence arument invalid. */
+  System("echo -n contact > file");
+  if ((fd = open("file", O_RDWR)) != 3) e(17);
+  for (i = -1000; i < 1000; i++) {
+	if (i == SEEK_SET || i == SEEK_END || i == SEEK_CUR) continue;
+	if (lseek(fd, (off_t) 0, i) != (off_t) -1) e(18);
+	if (errno != EINVAL) e(19);
+  }
+  if (close(fd) != 0) e(20);
+
+  /* EBADF for bad fides. */
+  for (i = -1000; i < 1000; i++) {
+	if (i >= 0 && i < OPEN_MAX) continue;
+	if (lseek(i, (off_t) 0, SEEK_SET) != (off_t) - 1) e(21);
+	if (lseek(i, (off_t) 0, SEEK_END) != (off_t) - 1) e(22);
+	if (lseek(i, (off_t) 0, SEEK_CUR) != (off_t) - 1) e(23);
+  }
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  System("rm -rf DIR_26");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test27.c
===================================================================
--- /trunk/minix/test/test27.c	(revision 9)
+++ /trunk/minix/test/test27.c	(revision 9)
@@ -0,0 +1,348 @@
+/* test27: stat() fstat()	Author: Jan-Mark Wams (jms@cs.vu.nl) */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <limits.h>
+#include <time.h>
+#include <stdio.h>
+
+#define MODE_MASK	(S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID)
+#define MAX_ERROR	4
+#define ITERATIONS      2
+
+#define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+
+int errct = 0;
+int subtest = 1;
+int superuser;
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];
+char ToLongName[NAME_MAX + 2];	/* Name of maximum +1 length */
+char ToLongPath[PATH_MAX + 1];
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test27a, (void));
+_PROTOTYPE(void test27b, (void));
+_PROTOTYPE(void test27c, (void));
+_PROTOTYPE(void makelongnames, (void));
+_PROTOTYPE(void e, (int __n));
+_PROTOTYPE(void quit, (void));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 27 ");
+  fflush(stdout);
+  System("rm -rf DIR_27; mkdir DIR_27");
+  Chdir("DIR_27");
+  superuser = (getuid() == 0);
+  makelongnames();
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test27a();
+	if (m & 0002) test27b();
+	if (m & 0004) test27c();
+  }
+  quit();
+}
+
+void test27a()
+{				/* Test Normal operation. */
+  struct stat st1, st2;
+  time_t time1, time2;
+  int fd, pfd[2];
+
+  subtest = 1;
+
+  time(&time1);			/* get time before */
+  while (time1 >= time((time_t *)0))
+	;			/* Wait for time to change. */
+  System("echo 7bytes > foo; chmod 4750 foo");
+  if (stat("foo", &st1) != 0) e(1);	/* get foo's info */
+  time(&time2);
+  while (time2 >= time((time_t *)0))
+	;			/* Wait for next second. */
+  time(&time2);			/* get time after */
+  if ((st1.st_mode & MODE_MASK) != 04750) e(2);
+  if (st1.st_nlink != 1) e(3);	/* check stat */
+  if (st1.st_uid != geteuid()) e(4);
+#if defined(NGROUPS_MAX) && NGROUPS_MAX == 0
+  if (st1.st_gid != getegid()) e(5);
+#endif /* defined(NGROUPS_MAX) && NGROUPS_MAX == 0 */
+  if (st1.st_size != (size_t) 7) e(6);
+  if (st1.st_atime <= time1) e(7);
+  if (st1.st_atime >= time2) e(8);
+  if (st1.st_ctime <= time1) e(9);
+  if (st1.st_ctime >= time2) e(10);
+  if (st1.st_mtime <= time1) e(11);
+  if (st1.st_mtime >= time2) e(12);
+
+  /* Compair stat and fstat. */
+  System("echo 7bytes > bar");
+  fd = open("bar", O_RDWR | O_APPEND);	/* the bar is open! */
+  if (fd != 3) e(13);		/* should be stderr + 1 */
+  if (stat("bar", &st1) != 0) e(14);	/* get bar's info */
+  if (fstat(fd, &st2) != 0) e(15);	/* get bar's info */
+
+  /* St1 en st2 should be the same. */
+  if (st1.st_dev != st2.st_dev) e(16);
+  if (st1.st_ino != st2.st_ino) e(17);
+  if (st1.st_mode != st2.st_mode) e(18);
+  if (st1.st_nlink != st2.st_nlink) e(19);
+  if (st1.st_uid != st2.st_uid) e(20);
+  if (st1.st_gid != st2.st_gid) e(21);
+  if (st1.st_size != st2.st_size) e(22);
+  if (st1.st_atime != st2.st_atime) e(23);
+  if (st1.st_ctime != st2.st_ctime) e(24);
+  if (st1.st_mtime != st2.st_mtime) e(25);
+  time(&time1);			/* wait a sec. */
+  while (time1 >= time((time_t *)0))
+	;
+  System("chmod 755 bar");	/* chainge mode */
+  System("rm -f foobar; ln bar foobar");	/* chainge # links */
+  if (write(fd, "foo", 4) != 4) e(26);	/* write a bit (or two) */
+  if (stat("bar", &st2) != 0) e(27);	/* get new info */
+  if (st2.st_dev != st1.st_dev) e(28);
+  if (st2.st_ino != st1.st_ino) e(29);	/* compair the fealds */
+  if ((st2.st_mode & MODE_MASK) != 0755) e(30);
+  if (!S_ISREG(st2.st_mode)) e(31);
+  if (st2.st_nlink != st1.st_nlink + 1) e(32);
+  if (st2.st_uid != st1.st_uid) e(33);
+  if (st2.st_gid != st1.st_gid) e(34);
+  if (st2.st_size != (size_t) 11) e(35);
+  if (st2.st_atime != st1.st_atime) e(36);
+  if (st2.st_ctime <= st1.st_ctime) e(37);
+  if (st2.st_mtime <= st1.st_mtime) e(38);
+  if (close(fd) != 0) e(39);	/* sorry the bar is closed */
+
+  /* Check special file. */
+  if (stat("/dev/tty", &st1) != 0) e(40);
+  if (!S_ISCHR(st1.st_mode)) e(41);
+#ifdef _MINIX
+  if (stat("/dev/ram", &st1) != 0) e(42);
+  if (!S_ISBLK(st1.st_mode)) e(43);
+#endif
+
+  /* Check fifos. */
+  time(&time1);
+  while (time1 >= time((time_t *)0))
+	;
+  if (mkfifo("fifo", 0640) != 0) e(44);
+  if (stat("fifo", &st1) != 0) e(45);	/* get fifo's info */
+  time(&time2);
+  while (time2 >= time((time_t *)0))
+	;
+  time(&time2);
+  if (!S_ISFIFO(st1.st_mode)) e(46);
+  if (st1.st_nlink != 1) e(47);	/* check the stat info */
+  if (st1.st_uid != geteuid()) e(48);
+#if defined(NGROUPS_MAX) && NGROUPS_MAX == 0
+  if (st1.st_gid != getegid()) e(49);
+#endif /* defined(NGROUPS_MAX) && NGROUPS_MAX == 0 */
+  if (st1.st_size != (size_t) 0) e(50);
+  if (st1.st_atime <= time1) e(51);
+  if (st1.st_atime >= time2) e(52);
+  if (st1.st_ctime <= time1) e(53);
+  if (st1.st_ctime >= time2) e(54);
+  if (st1.st_mtime <= time1) e(55);
+  if (st1.st_mtime >= time2) e(56);
+
+  /* Note: the st_mode of a fstat on a pipe should contain a isfifo bit. */
+  /* Check pipes. */
+  time(&time1);
+  while (time1 >= time((time_t *)0))
+	;
+  if (pipe(pfd) != 0) e(57);
+  if (fstat(pfd[0], &st1) != 0) e(58);	/* get pipe input info */
+  time(&time2);
+  while (time2 >= time((time_t *)0))
+	;
+  time(&time2);
+  if (!(S_ISFIFO(st1.st_mode))) e(59);	/* check stat struct */
+  if (st1.st_uid != geteuid()) e(60);
+  if (st1.st_gid != getegid()) e(61);
+  if (st1.st_size != (size_t) 0) e(62);
+  if (st1.st_atime <= time1) e(63);
+  if (st1.st_atime >= time2) e(64);
+  if (st1.st_ctime <= time1) e(65);
+  if (st1.st_ctime >= time2) e(66);
+  if (st1.st_mtime <= time1) e(67);
+  if (st1.st_mtime >= time2) e(68);
+  if (fstat(pfd[1], &st1) != 0) e(69);	/* get pipe output info */
+  if (!(S_ISFIFO(st1.st_mode))) e(70);
+  if (st1.st_uid != geteuid()) e(71);
+  if (st1.st_gid != getegid()) e(72);
+  if (st1.st_size != (size_t) 0) e(73);
+  if (st1.st_atime < time1) e(74);
+  if (st1.st_atime > time2) e(75);
+  if (st1.st_ctime < time1) e(76);
+  if (st1.st_ctime > time2) e(77);
+  if (st1.st_mtime < time1) e(78);
+  if (st1.st_mtime > time2) e(79);
+  if (close(pfd[0]) != 0) e(80);
+  if (close(pfd[1]) != 0) e(81);/* close pipe */
+
+  /* Check dirs. */
+  time(&time1);
+  while (time1 >= time((time_t *)0))
+	;
+  System("mkdir dir");
+  if (stat("dir", &st1) != 0) e(82);	/* get dir info */
+  time(&time2);
+  while (time2 >= time((time_t *)0))
+	;
+  time(&time2);
+  if (!(S_ISDIR(st1.st_mode))) e(83);	/* check stat struct */
+  if (st1.st_uid != geteuid()) e(84);
+#if defined(NGROUPS_MAX) && NGROUPS_MAX == 0
+  if (st1.st_gid != getegid()) e(85);
+#endif /* defined(NGROUPS_MAX) && NGROUPS_MAX == 0 */
+  if (st1.st_atime < time1) e(86);
+  if (st1.st_atime > time2) e(87);
+  if (st1.st_ctime < time1) e(88);
+  if (st1.st_ctime > time2) e(89);
+  if (st1.st_mtime < time1) e(90);
+  if (st1.st_mtime > time2) e(91);
+  System("rm -rf ../DIR_27/*");
+}
+
+void test27b()
+{				/* Test maxima. */
+  struct stat st;
+  int fd;
+
+  subtest = 2;
+
+  /* Check stats on maximum length files names. */
+  if (mkdir(MaxName, 0777) != 0) e(1);
+  if (stat(MaxName, &st) != 0) e(2);
+  if ((fd = open(MaxName, O_RDONLY)) != 3) e(3);
+  if (fstat(fd, &st) != 0) e(4);
+  if (close(fd) != 0) e(5);
+  if (rmdir(MaxName) != 0) e(6);
+  if (stat(MaxPath, &st) != 0) e(7);
+  if ((fd = open(MaxPath, O_RDONLY)) != 3) e(8);
+  if (fstat(fd, &st) != 0) e(9);
+  if (close(fd) != 0) e(10);
+  System("rm -rf ../DIR_27/*");
+}
+
+void test27c()
+{				/* Test error response. */
+  struct stat st;
+  int fd, i;
+
+  subtest = 3;
+
+  System("echo Hi > foo");	/* Make a file called foo. */
+  /* Check if a un searchable dir is handled ok. */
+  Chdir("..");			/* cd .. */
+  System("chmod 677 DIR_27");	/* no search permission */
+  if (stat("DIR_27/nono", &st) != -1) e(1);
+  if (superuser) {
+	if (errno != ENOENT) e(2);	/* su has access */
+  }
+  if (!superuser) {
+	if (errno != EACCES) e(3);	/* we don't ;-) */
+  }
+  System("chmod 777 DIR_27");
+  Chdir("DIR_27");		/* back to test dir */
+
+  /* Check on ToLongName etc. */
+#ifdef _POSIX_NO_TRUNC
+# if _POSIX_NO_TRUNC - 0 != -1
+  if (stat(ToLongName, &st) != -1) e(4);	/* name is too long */
+  if (errno != ENAMETOOLONG) e(5);
+# endif
+#else
+# include "error, this case requires dynamic checks and is not handled"
+#endif
+  if (stat(ToLongPath, &st) != -1) e(6);	/* path is too long */
+  if (errno != ENAMETOOLONG) e(7);
+
+  /* Test some common errors. */
+  if (stat("nono", &st) != -1) e(8);	/* nono nonexistent */
+  if (errno != ENOENT) e(9);
+  if (stat("", &st) != -1) e(10);	/* try empty */
+  if (errno != ENOENT) e(11);
+  if (stat("foo/bar", &st) != -1) e(12);	/* foo is a file */
+  if (errno != ENOTDIR) e(13);
+
+  /* Test fstat on file descriptors that are not open. */
+  for (i = 3; i < 6; i++) {
+	if (fstat(i, &st) != -1) e(14);
+	if (errno != EBADF) e(15);
+  }
+
+  /* Test if a just closed file is `fstat()'-able. */
+  if ((fd = open("foo", O_RDONLY)) != 3) e(16);	/* open foo */
+  if (fstat(fd, &st) != 0) e(17);	/* get stat */
+  if (close(fd) != 0) e(18);	/* close it */
+  if (fstat(fd, &st) != -1) e(19);	/* get stat */
+  if (errno != EBADF) e(20);
+  System("rm -rf ../DIR_27/*");
+}
+
+void makelongnames()
+{
+  register int i;
+
+  memset(MaxName, 'a', NAME_MAX);
+  MaxName[NAME_MAX] = '\0';
+  for (i = 0; i < PATH_MAX - 1; i++) {	/* idem path */
+	MaxPath[i++] = '.';
+	MaxPath[i] = '/';
+  }
+  MaxPath[PATH_MAX - 1] = '\0';
+
+  strcpy(ToLongName, MaxName);	/* copy them Max to ToLong */
+  strcpy(ToLongPath, MaxPath);
+
+  ToLongName[NAME_MAX] = 'a';
+  ToLongName[NAME_MAX + 1] = '\0';	/* extend ToLongName by one too many */
+  ToLongPath[PATH_MAX - 1] = '/';
+  ToLongPath[PATH_MAX] = '\0';	/* inc ToLongPath by one */
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  System("rm -rf DIR_27");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test28.c
===================================================================
--- /trunk/minix/test/test28.c	(revision 9)
+++ /trunk/minix/test/test28.c	(revision 9)
@@ -0,0 +1,438 @@
+ /* test28: mkdir() rmdir()	Author: Jan-Mark Wams (jms@cs.vu.nl) */
+
+/*
+** Not tested readonly file systems (EROFS.)
+** Not tested fs full (ENOSPC.)
+** Not really tested EBUSY.
+** Not tested unlinking busy directories.
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <limits.h>
+#include <time.h>
+#include <stdio.h>
+
+#define MAX_ERROR	4
+#define ITERATIONS      2
+
+#define DIRENT0		((struct dirent *) NULL)
+
+#define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+
+int errct = 0;
+int subtest = 1;
+int superuser;
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];
+char ToLongName[NAME_MAX + 2];	/* Name of maximum +1 length */
+char ToLongPath[PATH_MAX + 1];
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test28a, (void));
+_PROTOTYPE(void test28c, (void));
+_PROTOTYPE(void test28b, (void));
+_PROTOTYPE(void makelongnames, (void));
+_PROTOTYPE(void e, (int n));
+_PROTOTYPE(void quit, (void));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 28 ");
+  fflush(stdout);
+  superuser = (getuid() == 0);
+  makelongnames();
+  system("chmod 777 DIR_28/* DIR_28/*/* > /dev/null 2>&1");
+  System("rm -rf DIR_28; mkdir DIR_28");
+  Chdir("DIR_28");
+  umask(0000);			/* no umask */
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test28a();
+	if (m & 0002) test28b();
+	if (m & 0004) test28c();
+  }
+  quit();
+}
+
+void test28a()
+{
+  int mode;			/* used in for loop */
+  struct stat st;
+  time_t time1, time2;
+  DIR *dirp;
+  struct dirent *dep;
+  int dot = 0, dotdot = 0;
+
+  subtest = 1;
+
+  System("rm -rf foo /tmp/foo");/* clean up junk */
+
+  /* Check relative path names */
+  if (mkdir("./foo", 0777) != 0) e(1);	/* make a dir foo */
+  if (mkdir("./foo/bar", 0777) != 0) e(2);	/* make foo/bar */
+  if (rmdir("foo/bar") != 0) e(3);	/* delete bar */
+  if (mkdir("foo/../foo/bar", 0777) != 0) e(4);	/* make bar again */
+  if (rmdir("./foo/bar") != 0) e(5);	/* and remove again */
+
+  /* Foo should be empty (ie. contain only "." and ".." */
+  if ((dirp = opendir("foo")) == (DIR *) NULL) e(6);	/* open foo */
+  if ((dep = readdir(dirp)) == DIRENT0) e(7);	/* get first entry */
+  if (strcmp(dep->d_name, ".") == 0) dot += 1;	/* record what it is */
+  if (strcmp(dep->d_name, "..") == 0) dotdot += 1;
+  if ((dep = readdir(dirp)) == DIRENT0) e(8);	/* get second entry */
+  if (strcmp(dep->d_name, ".") == 0) dot += 1;	/* record again */
+  if (strcmp(dep->d_name, "..") == 0) dotdot += 1;
+  if ((dep = readdir(dirp)) != DIRENT0) e(9);	/* no 3d entry */
+  if (dot == 1 && dotdot != 1) e(10);	/* only . and .. */
+  if (closedir(dirp) != 0) e(11);	/* close foo */
+  if (rmdir("./foo") != 0) e(12);	/* remove dir foo */
+
+  /* Check absolute path names */
+  if (mkdir("/tmp/foo", 0777) != 0) e(13);
+  if (mkdir("/tmp/foo/bar", 0777) != 0) e(14);
+  if (rmdir("/tmp/foo/bar") != 0) e(15);	/* make some dirs */
+  if (rmdir("/tmp/foo") != 0) e(16);
+
+  /* Check the mode arument for mkdir() */
+  for (mode = 0; mode <= 0777; mode++) {
+	if (mkdir("foo", mode) != 0) e(17);	/* make foo */
+	if (stat("foo", &st) != 0) e(18);
+	if ((st.st_mode & 0777) != mode) e(19);	/* check it's mode */
+	if (rmdir("foo") != 0) e(20);	/* and remove it */
+  }
+
+  /* Check the stat */
+  time(&time1);
+  while (time1 >= time((time_t *)0))
+	;
+  if (mkdir("foo", 0765) != 0) e(21);	/* make foo */
+  if (stat("foo", &st) != 0) e(22);
+  time(&time2);
+  while (time2 >= time((time_t *)0))
+	;
+  time(&time2);
+  if (st.st_nlink != 2) e(23);
+  if (st.st_uid != geteuid()) e(24);
+  if (st.st_gid != getegid()) e(25);
+  if (st.st_size < 0) e(26);
+  if ((st.st_mode & 0777) != 0765) e(27);
+  if (st.st_atime <= time1) e(28);
+  if (st.st_atime >= time2) e(29);
+  if (st.st_ctime <= time1) e(30);
+  if (st.st_ctime >= time2) e(31);
+  if (st.st_mtime <= time1) e(32);
+  if (st.st_mtime >= time2) e(33);
+
+  /* Check if parent is updated */
+  if (stat(".", &st) != 0) e(34);
+  time(&time2);
+  while (time2 >= time((time_t *)0))
+	;
+  time(&time2);
+  if (st.st_ctime <= time1) e(35);
+  if (st.st_ctime >= time2) e(36);
+  if (st.st_mtime <= time1) e(37);
+  if (st.st_mtime >= time2) e(38);
+  time(&time1);
+  while (time1 >= time((time_t *)0))
+	;
+  if (rmdir("foo") != 0) e(39);
+  if (stat(".", &st) != 0) e(40);
+  time(&time2);
+  while (time2 >= time((time_t *)0))
+	;
+  time(&time2);
+  if (st.st_ctime <= time1) e(41);
+  if (st.st_ctime >= time2) e(42);
+  if (st.st_mtime <= time1) e(43);
+  if (st.st_mtime >= time2) e(44);
+}
+
+void test28b()
+{				/* Test critical values. */
+  struct stat st;
+  DIR *dirp;
+  struct dirent *dep;
+  int fd;			/* file descriptor */
+  int other = 0, dot = 0, dotdot = 0;	/* dirent counters */
+  int rmdir_result;		/* tmp var */
+  nlink_t nlink;
+  static char bar[20];
+  int stat_loc;
+
+  subtest = 2;
+
+  System("rm -rf ../DIR_28/*");
+
+  /* Check funny but valid path names */
+  if (mkdir("/../../..////.//../tmp/foo/", 0777) != 0) e(1);
+  if (mkdir("/tmp/foo//////..//foo//../foo/bar/", 0777) != 0) e(2);
+  if (rmdir("///tmp/..//tmp/foo/bar//../..//foo/bar") != 0) e(3);
+  if (mkdir("///tmp/foo/foobar//", 0777) != 0) e(4);
+  if (rmdir("/tmp/foo/foobar//") != 0) e(5);
+  if (rmdir("/.././/././/tmp/foo///////////////") != 0) e(6);
+  if (rmdir("/tmp/foo") != -1) e(7);	/* try again */
+
+  /* Test max path ed. */
+  if (mkdir(MaxName, 0777) != 0) e(9);	/* make dir MaxName */
+  if (rmdir(MaxName) != 0) e(10);	/* and remove it */
+  MaxPath[strlen(MaxPath) - 2] = '/';	/* convert MaxPath */
+  MaxPath[strlen(MaxPath) - 1] = 'a';	/* to ././.../a */
+  if (mkdir(MaxPath, 0777) != 0) e(11);	/* it should be */
+  if (rmdir(MaxPath) != 0) e(12);	/* ok */
+
+  /* Test too long path ed. */
+  if (mkdir(ToLongName, 0777) != 0) e(17);	/* Try ToLongName */
+  if (rmdir(ToLongName) != 0) e(18);	/* and remove it */
+  ToLongPath[strlen(ToLongPath) - 2] = '/';	/* make ToLongPath */
+  ToLongPath[strlen(ToLongPath) - 1] = 'a';	/* contain ././.../a */
+  if (mkdir(ToLongPath, 0777) != -1) e(19);	/* it should */
+  if (errno != ENAMETOOLONG) e(20);	/* not be ok */
+  if (rmdir(ToLongPath) != -1) e(21);
+  if (errno != ENAMETOOLONG) e(22);
+
+  if (mkdir("foo", 0777) != 0) e(23);
+  System("touch foo/xyzzy");
+#if 0
+  /* Test what happens if the parent link count > LINK_MAX. */
+  /* This takes too long. */
+  for (nlink = 1; nlink < LINK_MAX; nlink++) {	/* make all */
+  	sprintf(bar, "foo/bar.%d", nlink);
+	if (link("foo/xyzzy", bar) != 0) e(24);
+  }
+  if (stat("foo/xyzzy", &st) != 0) e(25);	/* foo now */
+  if (st.st_nlink != LINK_MAX) e(26);	/* is full */
+  if (link("foo/xyzzy", "nono") != -1) e(27);	/* no more */
+  if (errno != EMLINK) e(28);	/* entrys. */
+  System("rm -rf foo/nono");	/* Just in case. */
+#endif
+
+  /* Test if rmdir removes only empty dirs */
+  if (rmdir("foo") != -1) e(29);/* not empty */
+  if (errno != EEXIST && errno != ENOTEMPTY) e(30);
+  /* Test if rmdir removes a dir with an empty file (it shouldn't.) */
+  System("rm -rf foo");		/* cleanup */
+  if (mkdir("foo", 0777) != 0) e(31);
+  System("> foo/empty");	/* > empty */
+  if (rmdir("foo") != -1) e(32);/* not empty */
+  if (errno != EEXIST && errno != ENOTEMPTY) e(33);
+  if (unlink("foo/empty") != 0) e(34);	/* rm empty */
+
+  /* See what happens if foo is linked. */
+  if (superuser) {
+	if (link("foo", "footoo") != 0) e(35);	/* foo still */
+	if (rmdir("footoo") != 0) e(36);	/* exist */
+	if (chdir("footoo") != -1) e(37);	/* footoo */
+	if (errno != ENOENT) e(38);	/* is gone */
+  }
+#ifdef _MINIX
+  /* Some implementations might allow users to link directories. */
+  if (!superuser) {
+	if (link("foo", "footoo") != -1) e(39);
+	if (errno != EPERM) e(40);
+	if (unlink("foo") != -1) e(41);
+	if (errno != EPERM) e(42);
+  }
+#endif
+
+  /* See if ".." and "." are removed from the dir, and if it is
+   * unwriteable
+   * Note, we can not remove any files in the PARENT
+   * process, because this
+   * will make readdir unpredicatble. (see
+   * 1003.1 page 84 line 30.) However
+   * removal of the directory is
+   * not specified in the standard.
+   */
+  System("rm -rf /tmp/sema[12].07");
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+
+      case 0:
+	alarm(20);
+	if ((fd = open("foo", O_RDONLY)) <= 2) e(43);	/* open */
+	if ((dirp = opendir("foo")) == (DIR *) NULL) e(44);	/* opendir */
+	/* UpA downB */
+	system(">/tmp/sema1.07; while test -f /tmp/sema1.07; do sleep 1;done");
+	while ((dep = readdir(dirp)) != DIRENT0) {
+		if (strcmp(dep->d_name, "..") == 0)
+			dotdot += 1;
+		else if (strcmp(dep->d_name, ".") == 0)
+			dot += 1;
+		else
+			other += 1;
+	}
+	if (dotdot != 0) e(45);	/* no entrys */
+	if (dot != 0) e(46);	/* shoul be */
+	if (other != 0) e(47);	/* left or */
+
+	/* No new files (entrys) are allowed on foo */
+	if (creat("foo/nono", 0777) != -1) e(48);	/* makeable */
+	if (closedir(dirp) != 0) e(49);	/* close foo */
+	system("while test ! -f /tmp/sema2.07; do sleep 1; done");  /* downA */
+	System("rm -f /tmp/sema2.07");	/* clean up */
+
+	/* Foo still exist, so we should be able to get a fstat */
+	if (fstat(fd, &st) != 0) e(50);
+	if (st.st_nlink != (nlink_t) 0) e(51);	/* 0 left */
+	if (close(fd) != 0) e(52);	/* last one */
+	exit(0);
+
+      default:
+	system("while test ! -f /tmp/sema1.07; do sleep 1; done");  /* downA */
+	if (rmdir("foo") != 0) e(53);	/* cleanerup */
+	System("rm -f /tmp/sema1.07");	/* upB */
+	if (chdir("foo") != -1) e(54);	/* it should */
+	if (errno != ENOENT) e(55);	/* be gone */
+	System("> /tmp/sema2.07");	/* upA */
+	if (wait(&stat_loc) == -1) e(56);
+	if (stat_loc != 0) e(57);
+  }
+
+  /* See if foo isn't accessible any more */
+  if (chdir("foo") != -1) e(58);
+  if (errno != ENOENT) e(59);
+
+  /* Let's see if we can get a EBUSSY..... */
+  if (mkdir("foo", 0777) != 0) e(60);	/* mkdir foo */
+  System("rm -f /tmp/sema.07");	/* unness */
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	if (chdir("foo") != 0) e(61);	/* child goes */
+	System("> /tmp/sema.07");	/* upA */
+	system("while test -f /tmp/sema.07; do sleep 1; done");	/* downB */
+	sleep(1);
+	exit(0);
+      default:
+	system("while test ! -f /tmp/sema.07; do sleep 1; done");   /* downA */
+	rmdir_result = rmdir("foo");	/* try remove */
+	if (rmdir_result == -1) {	/* if it failed */
+		if (errno != EBUSY) e(62);	/* foo is busy */
+	} else {
+		if (rmdir_result != 0) e(63);
+		if (rmdir("foo") != -1) e(64);	/* not removable */
+		if (errno != ENOENT) e(65);	/* again. */
+		if (chdir("foo") != -1) e(66);	/* we can't go */
+		if (errno != ENOENT) e(67);	/* there any more */
+		if (mkdir("foo", 0777) != 0) e(68);	/* we can remake foo */
+	}
+	System("rm -f /tmp/sema.07");	/* upB */
+	if (wait(&stat_loc) == -1) e(69);
+	if (stat_loc != 0) e(70);
+  }
+  if (rmdir("foo") != 0) e(71);	/* clean up */
+}
+
+void test28c()
+{				/* Test error handeling. */
+  subtest = 3;
+
+  System("rm -rf ../DIR_28/*");
+  System("rm -rf foo /tmp/foo");/* clean up junk */
+
+  /* Test common errors */
+  if (mkdir("foo", 0777) != 0) e(1);	/* mkdir shouldn't fail */
+  if (mkdir("foo", 0777) != -1) e(2);	/* should fail the 2d time */
+  if (errno != EEXIST) e(3);	/* because it exists already */
+  if (rmdir("foo") != 0) e(4);	/* rmdir shouldn't fail */
+  if (rmdir("foo") != -1) e(5);	/* but it should now because */
+  if (errno != ENOENT) e(6);	/* it's gone the 1st time */
+  /* Test on access etc. */
+  if (mkdir("foo", 0777) != 0) e(7);
+  if (mkdir("foo/bar", 0777) != 0) e(8);
+  if (!superuser) {
+	System("chmod 677 foo");/* make foo inaccesable */
+	if (mkdir("foo/foo", 0777) != -1) e(9);
+	if (errno != EACCES) e(10);
+	if (rmdir("foo/bar") != -1) e(11);
+	if (errno != EACCES) e(12);
+	System("chmod 577 foo");/* make foo unwritable */
+	if (mkdir("foo/foo", 0777) != -1) e(13);
+	if (errno != EACCES) e(14);
+	if (rmdir("foo/bar") != -1) e(15);
+	if (errno != EACCES) e(16);
+	System("chmod 777 foo");/* make foo full accessable */
+  }
+  if (rmdir("foo/bar") != 0) e(17);	/* bar should be removable */
+  if (mkdir("foo/no/foo", 0777) != -1) e(18);	/* Note: "no" doesn't exist */
+  if (errno != ENOENT) e(19);
+  if (mkdir("", 0777) != -1) e(20);	/* empty string isn't ok */
+  if (errno != ENOENT) e(21);
+  if (rmdir("") != -1) e(22);	/* empty string isn't ok */
+  if (errno != ENOENT) e(23);
+  System("> foo/no");		/* make a file "no" */
+  if (mkdir("foo/no/foo", 0777) != -1) e(24);
+  if (errno != ENOTDIR) e(25);	/* note: "no" is not a a dir */
+  if (rmdir("foo/no/foo") != -1) e(26);
+  if (errno != ENOTDIR) e(27);
+  System("rm -rf foo");		/* clean up */
+}
+
+void makelongnames()
+{
+  register int i;
+
+  memset(MaxName, 'a', NAME_MAX);
+  MaxName[NAME_MAX] = '\0';
+  for (i = 0; i < PATH_MAX - 1; i++) {	/* idem path */
+	MaxPath[i++] = '.';
+	MaxPath[i] = '/';
+  }
+  MaxPath[PATH_MAX - 1] = '\0';
+
+  strcpy(ToLongName, MaxName);	/* copy them Max to ToLong */
+  strcpy(ToLongPath, MaxPath);
+
+  ToLongName[NAME_MAX] = 'a';
+  ToLongName[NAME_MAX + 1] = '\0';	/* extend ToLongName by one too many */
+  ToLongPath[PATH_MAX - 1] = '/';
+  ToLongPath[PATH_MAX] = '\0';	/* inc ToLongPath by one */
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  System("rm -rf DIR_28");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test29.c
===================================================================
--- /trunk/minix/test/test29.c	(revision 9)
+++ /trunk/minix/test/test29.c	(revision 9)
@@ -0,0 +1,246 @@
+/* test29: dup() dup2()		Author: Jan-Mark Wams (jms@cs.vu.nl) */
+
+/* The definition of ``dup2()'' is realy a big mess! For:
+**
+** (1) if fildes2 is less than zero or greater than {OPEN_MAX}
+**     errno has to set to [EBADF]. But if fildes2 equals {OPEN_MAX}
+**     errno has to be set to [EINVAL]. And ``fcntl(F_DUPFD...)'' always
+**     returns [EINVAL] if fildes2 is out of range!
+**
+** (2) if the number of file descriptors would exceed {OPEN_MAX}, or no
+**     file descriptors above fildes2 are available, errno has to be set
+**     to [EMFILE]. But this can never occur!
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+
+#define MAX_ERROR	4
+#define ITERATIONS     10
+
+#define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+#define Stat(a,b)	if (stat(a,b) != 0) printf("Can't stat %s\n", a)
+
+#define IS_CLOEXEC(fd)	((fcntl(fd, F_GETFD) & FD_CLOEXEC) == FD_CLOEXEC)
+#define SET_CLOEXEC(fd)	fcntl(fd, F_SETFD, FD_CLOEXEC)
+
+int errct = 0;
+int subtest = 1;
+int superuser;
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];		/* Same for path */
+char ToLongName[NAME_MAX + 2];	/* Name of maximum +1 length */
+char ToLongPath[PATH_MAX + 1];	/* Same for path, both too long */
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test29a, (void));
+_PROTOTYPE(void test29b, (void));
+_PROTOTYPE(void test29c, (void));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 29 ");
+  fflush(stdout);
+  System("rm -rf DIR_29; mkdir DIR_29");
+  Chdir("DIR_29");
+  superuser = (geteuid() == 0);
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test29a();
+	if (m & 0002) test29b();
+	if (m & 0004) test29c();
+  }
+  quit();
+}
+
+void test29a()
+{
+  int fd1, fd2, fd3, fd4, fd5;
+  struct flock flock;
+
+  subtest = 1;
+
+  /* Basic checking. */
+  if ((fd1 = dup(0)) != 3) e(1);
+  if ((fd2 = dup(0)) != 4) e(2);
+  if ((fd3 = dup(0)) != 5) e(3);
+  if ((fd4 = dup(0)) != 6) e(4);
+  if ((fd5 = dup(0)) != 7) e(5);
+  if (close(fd2) != 0) e(6);
+  if (close(fd4) != 0) e(7);
+  if ((fd2 = dup(0)) != 4) e(8);
+  if ((fd4 = dup(0)) != 6) e(9);
+  if (close(fd1) != 0) e(10);
+  if (close(fd3) != 0) e(11);
+  if (close(fd5) != 0) e(12);
+  if ((fd1 = dup(0)) != 3) e(13);
+  if ((fd3 = dup(0)) != 5) e(14);
+  if ((fd5 = dup(0)) != 7) e(15);
+  if (close(fd1) != 0) e(16);
+  if (close(fd2) != 0) e(17);
+  if (close(fd3) != 0) e(18);
+  if (close(fd4) != 0) e(19);
+  if (close(fd5) != 0) e(20);
+
+  /* FD_CLOEXEC should be cleared. */
+  if ((fd1 = dup(0)) != 3) e(21);
+  if (SET_CLOEXEC(fd1) == -1) e(22);
+  if (!IS_CLOEXEC(fd1)) e(23);
+  if ((fd2 = dup(fd1)) != 4) e(24);
+  if ((fd3 = dup(fd2)) != 5) e(25);
+  if (IS_CLOEXEC(fd2)) e(26);
+  if (IS_CLOEXEC(fd3)) e(27);
+  if (SET_CLOEXEC(fd2) == -1) e(28);
+  if (!IS_CLOEXEC(fd2)) e(29);
+  if (IS_CLOEXEC(fd3)) e(30);
+  if (close(fd1) != 0) e(31);
+  if (close(fd2) != 0) e(32);
+  if (close(fd3) != 0) e(33);
+
+  /* Locks should be shared, so we can lock again. */
+  System("echo 'Hallo' > file");
+  if ((fd1 = open("file", O_RDWR)) != 3) e(34);
+  flock.l_whence = SEEK_SET;
+  flock.l_start = 0;
+  flock.l_len = 10;
+  flock.l_type = F_WRLCK;
+  if (fcntl(fd1, F_SETLK, &flock) == -1) e(35);
+  if (fcntl(fd1, F_SETLK, &flock) == -1) e(36);
+  if ((fd2 = dup(fd1)) != 4) e(37);
+  if (fcntl(fd1, F_SETLK, &flock) == -1) e(38);
+  if (fcntl(fd1, F_GETLK, &flock) == -1) e(39);
+#if 0 /* XXX - see test7.c */
+  if (flock.l_type != F_WRLCK) e(40);
+  if (flock.l_pid != getpid()) e(41);
+#endif /* 0 */
+  flock.l_type = F_WRLCK;
+  if (fcntl(fd2, F_GETLK, &flock) == -1) e(42);
+#if 0 /* XXX - see test7.c */
+  if (flock.l_type != F_WRLCK) e(43);
+  if (flock.l_pid != getpid()) e(44);
+#endif /* 0 */
+  if (close(fd1) != 0) e(45);
+  if (close(fd2) != 0) e(46);
+
+  System("rm -rf ../DIR_29/*");
+}
+
+void test29b()
+{
+  int fd;
+  char buf[32];
+
+  subtest = 2;
+
+  /* Test file called ``file''. */
+  System("echo 'Hallo!' > file");
+
+  /* Check dup2() call with the same fds. Should have no effect. */
+  if ((fd = open("file", O_RDONLY)) != 3) e(1);
+  if (read(fd, buf, 2) != 2) e(2);
+  if (strncmp(buf, "Ha", 2) != 0) e(3);
+  if (dup2(fd, fd) != fd) e(4);
+  if (read(fd, buf, 2) != 2) e(5);
+  if (strncmp(buf, "ll", 2) != 0) e(6);
+  if (dup2(fd, fd) != fd) e(7);
+  if (read(fd, buf, 2) != 2) e(8);
+  if (strncmp(buf, "o!", 2) != 0) e(9);
+  if (close(fd) != 0) e(10);
+
+  /* If dup2() call fails, the fildes2 argument has to stay open. */
+  if ((fd = open("file", O_RDONLY)) != 3) e(11);
+  if (read(fd, buf, 2) != 2) e(12);
+  if (strncmp(buf, "Ha", 2) != 0) e(13);
+  if (dup2(OPEN_MAX + 3, fd) != -1) e(14);
+  if (errno != EBADF) e(15);
+  if (read(fd, buf, 2) != 2) e(16);
+  if (strncmp(buf, "ll", 2) != 0) e(17);
+  if (dup2(-4, fd) != -1) e(18);
+  if (errno != EBADF) e(19);
+  if (read(fd, buf, 2) != 2) e(20);
+  if (strncmp(buf, "o!", 2) != 0) e(21);
+  if (close(fd) != 0) e(22);
+
+  System("rm -rf ../DIR_29/*");
+}
+
+void test29c()
+{
+  int i;
+
+  subtest = 3;
+
+  /* Check bad arguments to dup() and dup2(). */
+  for (i = -OPEN_MAX; i < OPEN_MAX * 2; i++) {
+
+	/* ``i'' is a valid and open fd. */
+	if (i >= 0 && i < 3) continue;
+
+	/* If ``i'' is a valid fd it is not open. */
+	if (dup(i) != -1) e(1);
+	if (errno != EBADF) e(2);
+
+	/* ``i'' Is OPEN_MAX. */
+	if (i == OPEN_MAX) {
+		if (dup2(0, i) != -1) e(3);
+		if (errno != EINVAL) e(4);
+	}
+
+	/* ``i'' Is out of range. */
+	if (i < 0 || i > OPEN_MAX) {
+		if (dup2(0, i) != -1) e(5);
+		if (errno != EBADF) e(6);
+	}
+  }
+
+  System("rm -rf ../DIR_29/*");
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  System("rm -rf DIR_29");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test3.c
===================================================================
--- /trunk/minix/test/test3.c	(revision 9)
+++ /trunk/minix/test/test3.c	(revision 9)
@@ -0,0 +1,254 @@
+/* test 3 - library routines rather than system calls */
+
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define ITERATIONS 10
+#define MAX_ERROR 4
+#define SIZE 64
+
+int errct, subtest;
+char el_weirdo[] = "\n\t\\\e@@!!##\e\e\n\n";
+
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(void test3a, (void));
+_PROTOTYPE(void test3b, (void));
+_PROTOTYPE(void test3c, (void));
+_PROTOTYPE(void test3d, (void));
+_PROTOTYPE(void test3e, (void));
+_PROTOTYPE(void quit, (void));
+_PROTOTYPE(void e, (int n));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (geteuid() == 0 || getuid() == 0) {
+	printf("Test  3 cannot run as root; test aborted\n");
+	exit(1);
+  }
+
+  if (argc == 2) m = atoi(argv[1]);
+
+  printf("Test  3 ");
+  fflush(stdout);		/* have to flush for child's benefit */
+
+  system("rm -rf DIR_03; mkdir DIR_03");
+  chdir("DIR_03");
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test3a();
+	if (m & 0002) test3b();
+	if (m & 0004) test3c();
+	if (m & 0010) test3d();
+	if (m & 0020) test3e();
+  }
+  quit();
+  return(-1);			/* impossible */
+
+}
+
+void test3a()
+{
+/* Signal set manipulation. */
+
+  sigset_t s, s1;
+
+  subtest = 1;
+  errno = -1000;		/* None of these calls set errno. */
+  if (sigemptyset(&s) != 0) e(1);
+  if (sigemptyset(&s1) != 0) e(2);
+  if (sigaddset(&s, SIGABRT) != 0) e(3);
+  if (sigaddset(&s, SIGALRM) != 0) e(4);
+  if (sigaddset(&s, SIGFPE ) != 0) e(5);
+  if (sigaddset(&s, SIGHUP ) != 0) e(6);
+  if (sigaddset(&s, SIGILL ) != 0) e(7);
+  if (sigaddset(&s, SIGINT ) != 0) e(8);
+  if (sigaddset(&s, SIGKILL) != 0) e(9);
+  if (sigaddset(&s, SIGPIPE) != 0) e(10);
+  if (sigaddset(&s, SIGQUIT) != 0) e(11);
+  if (sigaddset(&s, SIGSEGV) != 0) e(12);
+  if (sigaddset(&s, SIGTERM) != 0) e(13);
+  if (sigaddset(&s, SIGUSR1) != 0) e(14);
+  if (sigaddset(&s, SIGUSR2) != 0) e(15);
+  
+  if (sigismember(&s, SIGABRT) != 1) e(16);
+  if (sigismember(&s, SIGALRM) != 1) e(17);
+  if (sigismember(&s, SIGFPE ) != 1) e(18);
+  if (sigismember(&s, SIGHUP ) != 1) e(19);
+  if (sigismember(&s, SIGILL ) != 1) e(20);
+  if (sigismember(&s, SIGINT ) != 1) e(21);
+  if (sigismember(&s, SIGKILL) != 1) e(22);
+  if (sigismember(&s, SIGPIPE) != 1) e(23);
+  if (sigismember(&s, SIGQUIT) != 1) e(24);
+  if (sigismember(&s, SIGSEGV) != 1) e(25);
+  if (sigismember(&s, SIGTERM) != 1) e(26);
+  if (sigismember(&s, SIGUSR1) != 1) e(27);
+  if (sigismember(&s, SIGUSR2) != 1) e(28);
+  
+  if (sigdelset(&s, SIGABRT) != 0) e(29);
+  if (sigdelset(&s, SIGALRM) != 0) e(30);
+  if (sigdelset(&s, SIGFPE ) != 0) e(31);
+  if (sigdelset(&s, SIGHUP ) != 0) e(32);
+  if (sigdelset(&s, SIGILL ) != 0) e(33);
+  if (sigdelset(&s, SIGINT ) != 0) e(34);
+  if (sigdelset(&s, SIGKILL) != 0) e(35);
+  if (sigdelset(&s, SIGPIPE) != 0) e(36);
+  if (sigdelset(&s, SIGQUIT) != 0) e(37);
+  if (sigdelset(&s, SIGSEGV) != 0) e(38);
+  if (sigdelset(&s, SIGTERM) != 0) e(39);
+  if (sigdelset(&s, SIGUSR1) != 0) e(40);
+  if (sigdelset(&s, SIGUSR2) != 0) e(41);
+  
+  if (s != s1) e(42);
+
+  if (sigaddset(&s, SIGILL) != 0) e(43);
+  if (s == s1) e(44);  
+
+  if (sigfillset(&s) != 0) e(45);
+  if (sigismember(&s, SIGABRT) != 1) e(46);
+  if (sigismember(&s, SIGALRM) != 1) e(47);
+  if (sigismember(&s, SIGFPE ) != 1) e(48);
+  if (sigismember(&s, SIGHUP ) != 1) e(49);
+  if (sigismember(&s, SIGILL ) != 1) e(50);
+  if (sigismember(&s, SIGINT ) != 1) e(51);
+  if (sigismember(&s, SIGKILL) != 1) e(52);
+  if (sigismember(&s, SIGPIPE) != 1) e(53);
+  if (sigismember(&s, SIGQUIT) != 1) e(54);
+  if (sigismember(&s, SIGSEGV) != 1) e(55);
+  if (sigismember(&s, SIGTERM) != 1) e(56);
+  if (sigismember(&s, SIGUSR1) != 1) e(57);
+  if (sigismember(&s, SIGUSR2) != 1) e(58);
+
+  /* Test error returns. */
+  if (sigaddset(&s, -1) != -1) e(59);
+  if (sigaddset(&s, -1) != -1) e(60);
+  if (sigismember(&s, -1) != -1) e(61);
+  if (sigaddset(&s, 10000) != -1) e(62);
+  if (sigaddset(&s, 10000) != -1) e(63);
+  if (sigismember(&s, 10000) != -1) e(64);
+
+}
+
+void test3b()
+{
+/* Test uname. */
+
+  struct utsname u;		/* contains all kinds of system ids */
+
+  subtest = 2;
+#if 0
+  errno = -2000;		/* None of these calls set errno. */
+  if (uname(&u) != 0) e(1);
+  if (strcmp(u.sysname, "MINIX") != 0
+	&& strcmp(u.sysname, "Minix") != 0) e(2);    /* only one defined */
+#endif
+}
+
+void test3c()
+{
+/* Test getenv.  Asume HOME, PATH, and LOGNAME exist (not strictly required).*/
+
+  char *p, name[SIZE];
+
+  subtest = 3;
+  errno = -3000;		/* None of these calls set errno. */
+  if ( (p = getenv("HOME")) == NULL) e(1);
+  if (*p != '/') e(2);		/* path must be absolute */
+  if ( (p = getenv("PATH")) == NULL) e(3);
+  if ( (p = getenv("LOGNAME")) == NULL) e(5);
+  strcpy(name, p);		/* save it, since getlogin might wipe it out */
+  p = getlogin();
+  if (strcmp(p, name) != 0) e(6);
+
+  /* The following test could fail in a legal POSIX system.  However, if it
+   * does, you deserve it to fail.
+   */
+  if (getenv(el_weirdo) != NULL) e(7);
+}
+
+void test3d()
+{
+/* Test ctermid, ttyname, and isatty. */
+
+  int fd;
+  char *p, name[L_ctermid];
+
+  subtest = 4;
+  errno = -4000;		/* None of these calls set errno. */
+
+  /* Test ctermid first. */
+  if ( (p = ctermid(name)) == NULL) e(1);
+  if (strcmp(p, name) != 0) e(2);
+  if (strncmp(p, "/dev/tty", 8) != 0) e(3);	/* MINIX convention */
+  
+  if ( (p = ttyname(0)) == NULL) e(4);
+  if (strncmp(p, "/dev/tty", 8) != 0 && strcmp(p, "/dev/console") != 0) e(5);
+  if ( (p = ttyname(3)) != NULL) e(6);
+  if (ttyname(5000) != NULL) e(7);
+  if ( (fd = creat("T3a", 0777)) < 0) e(8);
+  if (ttyname(fd) != NULL) e(9);
+
+  if (isatty(0) != 1) e(10);
+  if (isatty(3) != 0) e(11);
+  if (isatty(fd) != 0) e(12);
+  if (close(fd) != 0) e(13);
+  if (ttyname(fd) != NULL) e(14);
+}
+
+void test3e()
+{
+/* Test ctermid, ttyname, and isatty. */
+
+  subtest = 5;
+  errno = -5000;		/* None of these calls set errno. */
+
+  if (sysconf(_SC_ARG_MAX) < _POSIX_ARG_MAX) e(1);
+  if (sysconf(_SC_CHILD_MAX) < _POSIX_CHILD_MAX) e(2);
+  if (sysconf(_SC_NGROUPS_MAX) < 0) e(3);
+  if (sysconf(_SC_OPEN_MAX) < _POSIX_OPEN_MAX) e(4);
+
+  /* The rest are MINIX specific */
+  if (sysconf(_SC_JOB_CONTROL) >= 0) e(5);	/* no job control! */
+}
+
+void quit()
+{
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(4);
+  }
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* save errno in case printf clobbers it */
+
+  printf("Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
+  errno = err_num;		/* restore errno, just in case */
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Test aborted.  Too many errors: ");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test30.c
===================================================================
--- /trunk/minix/test/test30.c	(revision 9)
+++ /trunk/minix/test/test30.c	(revision 9)
@@ -0,0 +1,342 @@
+/* test30: creat() 		(p) Jan-Mark Wams. email: jms@cs.vu.nl */
+
+/*
+** Creat() should be equivalent to:
+**	open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
+** Since we can not look in the source, we can not assume creat() is
+** a mere sysnonym (= a systemcall synonym).
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+
+#define MAX_ERROR	4
+#define ITERATIONS     10
+
+#define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+#define Stat(a,b)	if (stat(a,b) != 0) printf("Can't stat %s\n", a)
+
+int errct = 0;
+int subtest = 1;
+int superuser;
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];		/* Same for path */
+char ToLongName[NAME_MAX + 2];	/* Name of maximum +1 length */
+char ToLongPath[PATH_MAX + 1];	/* Same for path, both too long */
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test30a, (void));
+_PROTOTYPE(void test30b, (void));
+_PROTOTYPE(void test30c, (void));
+_PROTOTYPE(void makelongnames, (void));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 30 ");
+  fflush(stdout);
+  System("rm -rf DIR_30; mkdir DIR_30");
+  Chdir("DIR_30");
+  makelongnames();
+  superuser = (geteuid() == 0);
+
+  umask(0000);
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test30a();
+	if (m & 0002) test30b();
+	if (m & 0004) test30c();
+  }
+  quit();
+}
+
+void test30a()
+{				/* Test normal operation. */
+
+#define BUF_SIZE 1024
+
+  int fd1, fd2;
+  char buf[BUF_SIZE];
+  struct stat st, dirst;
+  time_t time1, time2;
+  int stat_loc, cnt;
+
+  subtest = 1;
+
+  System("rm -rf ../DIR_30/*");
+
+  /* Check if processes have independent new fds */
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	if ((fd1 = creat("myfile", 0644)) != 3) e(1);
+	if (close(fd1) != 0) e(2);
+	exit(0);
+      default:
+	if ((fd1 = creat("myfile", 0644)) != 3) e(3);
+	if (close(fd1) != 0) e(4);
+	if (wait(&stat_loc) == -1) e(5);
+	if (stat_loc != 0) e(6);
+  }
+
+  /* Save the dir status. */
+  Stat(".", &dirst);
+  time(&time1);
+  while (time1 == time((time_t *)0))
+	;
+
+  /* Check if the file status information is updated correctly */
+  cnt = 0;
+  System("rm -rf myfile");
+  do {
+	time(&time1);
+	if ((fd1 = creat("myfile", 0644)) != 3) e(7);
+	Stat("myfile", &st);
+	time(&time2);
+  } while (time1 != time2 && cnt++ < 100);
+  if (cnt >= 100) e(8);
+  if (st.st_uid != geteuid()) e(9);	/* Uid should be set. */
+#if defined(NGROUPS_MAX) && NGROUPS_MAX == 0
+  if (st.st_gid != getegid()) e(10);
+#endif /* defined(NGROUPS_MAX) && NGROUPS_MAX == 0 */
+  if (!S_ISREG(st.st_mode)) e(11);
+  if (st.st_mode & 0777 != 0644) e(12);
+  if (st.st_nlink != 1) e(13);
+  if (st.st_ctime != time1) e(14);	/* All time fields should be updated */
+  if (st.st_atime != time1) e(15);
+  if (st.st_mtime != time1) e(16);
+  if (st.st_size != 0) e(17);	/* File should be trunked. */
+
+  /* Check if c and mtime for "." is updated. */
+  Stat(".", &st);
+  if (st.st_ctime <= dirst.st_ctime) e(18);
+  if (st.st_mtime <= dirst.st_mtime) e(19);
+
+  /* Let's see if cread fds are write only. */
+  if (read(fd1, buf, 7) != -1) e(20);	/* we can't read */
+  if (errno != EBADF) e(21);	/* a write only fd */
+  if (write(fd1, "HELLO", 6) != 6) e(22);	/* but we can write */
+
+  /* No O_APPEND flag should have been used. */
+  if (lseek(fd1, (off_t) 1, SEEK_SET) != 1) e(23);
+  if (write(fd1, "ello", 5) != 5) e(24);
+  Stat("myfile", &st);
+  if (st.st_size != 6) e(25);
+  if (st.st_size == 11) e(26);	/* O_APPEND should make it 11. */
+  if (close(fd1) != 0) e(27);
+
+  /* A creat should set the file offset to 0. */
+  if ((fd1 = creat("myfile", 0644)) != 3) e(28);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 0) e(29);
+  if (close(fd1) != 0) e(30);
+
+  /* Test if file permission bits and the file ownership are unchanged. */
+  /* So we will see if creat() is just an open() if the file exists. */
+  if (superuser) {
+	System("echo > bar; chmod 073 bar");	/* Make bar 073 */
+	if (chown("bar", 1, 1) != 0) e(1137);
+	fd1 = creat("bar", 0777);	/* knock knock */
+	if (fd1 == -1) e(31);
+	Stat("bar", &st);
+	if (st.st_size != (size_t) 0) e(32);	/* empty file. */
+	if (write(fd1, "foo", 3) != 3) e(33);	/* rewrite bar */
+	if (close(fd1) != 0) e(34);
+	Stat("bar", &st);
+	if (st.st_uid != 1) e(35);
+	if (st.st_gid != 1) e(36);
+	if ((st.st_mode & 0777) != 073) e(37);	/* mode still is 077 */
+	if (st.st_size != (size_t) 3) e(38);
+  }
+
+  /* Fifo's should be openable with creat(). */
+  if (mkfifo("fifo", 0644) != 0) e(39);
+
+  /* Creat() should have no effect on FIFO files. */
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);		/* Give child 20 seconds to live. */
+	if ((fd1 = open("fifo", O_WRONLY)) != 3) e(40);
+	if (write(fd1, "I did see Elvis.\n", 18) != 18) e(41);
+	if ((fd2 = creat("fifo", 0644)) != 4) e(42);
+	if (write(fd2, "I DID.\n", 8) != 8) e(43);
+	if (close(fd2) != 0) e(44);
+	if (close(fd1) != 0) e(45);
+	exit(0);
+      default:
+	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(46);
+	if (read(fd1, buf, 18) != 18) e(47);
+	if (strcmp(buf, "I did see Elvis.\n") != 0) e(48);
+	if (strcmp(buf, "I DID.\n") == 0) e(49);
+	if (read(fd1, buf, BUF_SIZE) != 8) e(50);
+	if (strcmp(buf, "I DID.\n") != 0) e(51);
+	if (close(fd1) != 0) e(52);
+	if (wait(&stat_loc) == -1) e(53);
+	if (stat_loc != 0) e(54);	/* The alarm went off? */
+  }
+
+  /* Creat() should have no effect on directroys. */
+  System("mkdir dir; touch dir/f1 dir/f2 dir/f3");
+  if ((fd1 = creat("dir", 0644)) != -1) e(55);
+  if (errno != EISDIR) e(56);
+  close(fd1);
+
+  /* The path should contain only dirs in the prefix. */
+  if ((fd1 = creat("dir/f1/nono", 0644)) != -1) e(57);
+  if (errno != ENOTDIR) e(58);
+  close(fd1);
+
+  /* The path should contain only dirs in the prefix. */
+  if ((fd1 = creat("", 0644)) != -1) e(59);
+  if (errno != ENOENT) e(60);
+  close(fd1);
+  if ((fd1 = creat("dir/noso/nono", 0644)) != -1) e(61);
+  if (errno != ENOENT) e(62);
+  close(fd1);
+
+}
+
+void test30b()
+{
+  int fd;
+
+  subtest = 2;
+
+  System("rm -rf ../DIR_30/*");
+
+  /* Test maximal file name length. */
+  if ((fd = creat(MaxName, 0777)) != 3) e(1);
+  if (close(fd) != 0) e(2);
+  MaxPath[strlen(MaxPath) - 2] = '/';
+  MaxPath[strlen(MaxPath) - 1] = 'a';	/* make ././.../a */
+  if ((fd = creat(MaxPath, 0777)) != 3) e(3);
+  if (close(fd) != 0) e(4);
+  MaxPath[strlen(MaxPath) - 1] = '/';	/* make ././.../a */
+}
+
+void test30c()
+{
+  int fd;
+
+  subtest = 3;
+
+  System("rm -rf ../DIR_30/*");
+
+  if (!superuser) {
+	/* Test if creat is not usable to open files with the wrong mode */
+	System("> nono; chmod 177 nono");
+	fd = creat("nono", 0777);
+	if (fd != -1) e(1);
+	if (errno != EACCES) e(2);
+  }
+  if (mkdir("bar", 0777) != 0) e(3);	/* make bar */
+
+  /* Check if no access on part of path generates the correct error. */
+  System("chmod 577 bar");	/* r-xrwxrwx */
+  if (!superuser) {
+	/* Normal users can't creat without write permision. */
+	if (creat("bar/nono", 0666) != -1) e(4);
+	if (errno != EACCES) e(5);
+	if (creat("bar/../nono", 0666) != -1) e(6);
+	if (errno != EACCES) e(7);
+  }
+  if (superuser) {
+	/* Super user can still creat stuff. */
+	if ((fd = creat("bar/nono", 0666)) != 3) e(8);
+	if (close(fd) != 0) e(9);
+	if (unlink("bar/nono") != 0) e(10);
+  }
+
+  /* Clean up bar. */
+  System("rm -rf bar");
+
+  /* Test ToLongName and ToLongPath */
+#ifdef _POSIX_NO_TRUNC
+# if _POSIX_NO_TRUNC - 0 != -1
+  if ((fd = creat(ToLongName, 0777)) != -1) e(11);
+  if (errno != ENAMETOOLONG) e(12);
+  close(fd);			/* Just in case. */
+# else
+  if ((fd = creat(ToLongName, 0777)) != 3) e(13);
+  if (close(fd) != 0) e(14);
+# endif
+#else
+# include "error, this case requires dynamic checks and is not handled"
+#endif
+  ToLongPath[PATH_MAX - 2] = '/';
+  ToLongPath[PATH_MAX - 1] = 'a';
+  if ((fd = creat(ToLongPath, 0777)) != -1) e(15);
+  if (errno != ENAMETOOLONG) e(16);
+  if (close(fd) != -1) e(17);
+  ToLongPath[PATH_MAX - 1] = '/';
+}
+
+void makelongnames()
+{
+  register int i;
+
+  memset(MaxName, 'a', NAME_MAX);
+  MaxName[NAME_MAX] = '\0';
+  for (i = 0; i < PATH_MAX - 1; i++) {	/* idem path */
+	MaxPath[i++] = '.';
+	MaxPath[i] = '/';
+  }
+  MaxPath[PATH_MAX - 1] = '\0';
+
+  strcpy(ToLongName, MaxName);	/* copy them Max to ToLong */
+  strcpy(ToLongPath, MaxPath);
+
+  ToLongName[NAME_MAX] = 'a';
+  ToLongName[NAME_MAX + 1] = '\0';	/* extend ToLongName by one too many */
+  ToLongPath[PATH_MAX - 1] = '/';
+  ToLongPath[PATH_MAX] = '\0';	/* inc ToLongPath by one */
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  System("rm -rf DIR_30");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test31.c
===================================================================
--- /trunk/minix/test/test31.c	(revision 9)
+++ /trunk/minix/test/test31.c	(revision 9)
@@ -0,0 +1,271 @@
+/* test31: mkfifo()		Author: Jan-Mark Wams (jms@cs.vu.nl) */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+
+#define MAX_ERROR	4
+#define ITERATIONS     10
+
+#define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+#define Stat(a,b)	if (stat(a,b) != 0) printf("Can't stat %s\n", a)
+
+int errct = 0;
+int subtest = 1;
+int superuser;
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];		/* Same for path */
+char ToLongName[NAME_MAX + 2];	/* Name of maximum +1 length */
+char ToLongPath[PATH_MAX + 1];	/* Same for path, both too long */
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test31a, (void));
+_PROTOTYPE(void test31b, (void));
+_PROTOTYPE(void test31c, (void));
+_PROTOTYPE(void makelongnames, (void));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 31 ");
+  fflush(stdout);
+  System("rm -rf DIR_31; mkdir DIR_31");
+  Chdir("DIR_31");
+  makelongnames();
+  superuser = (geteuid() == 0);
+
+  umask(0000);
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test31a();
+	if (m & 0002) test31b();
+	if (m & 0004) test31c();
+  }
+  quit();
+}
+
+void test31a()
+{				/* Test normal operation. */
+
+#define BUF_SIZE 1024
+
+  int fd;
+  char buf[BUF_SIZE];
+  struct stat st, dirst;
+  time_t time1, time2;
+  int stat_loc, cnt;
+
+  subtest = 1;
+
+  System("rm -rf ../DIR_31/*");
+
+  /* Check if the file status information is updated correctly */
+  System("rm -rf fifo");
+  cnt = 0;
+  Stat(".", &dirst);
+  time(&time1);
+  while (time1 == time((time_t *)0))
+	;
+
+  do {
+	time(&time1);
+	if (mkfifo("fifo", 0644) != 0) e(1);
+	Stat("fifo", &st);
+	time(&time2);
+  } while (time1 != time2 && cnt++ < 100);
+
+  if (cnt >= 100) e(2);
+  if (st.st_uid != geteuid()) e(3);	/* Uid should be set. */
+#if defined(NGROUPS_MAX) && NGROUPS_MAX == 0
+  if (st.st_gid != getegid()) e(4);
+#endif /* defined(NGROUPS_MAX) && NGROUPS_MAX == 0 */
+  if (!S_ISFIFO(st.st_mode)) e(5);
+  if (st.st_mode & 0777 != 0644) e(6);
+  if (st.st_nlink != 1) e(7);
+  if (st.st_ctime != time1) e(8);
+  if (st.st_atime != time1) e(9);
+  if (st.st_mtime != time1) e(10);
+  if (st.st_size != 0) e(11);	/* File should be empty. */
+
+  /* Check if status for "." is updated. */
+  Stat(".", &st);
+  if (st.st_ctime <= dirst.st_ctime) e(12);
+  if (st.st_mtime <= dirst.st_mtime) e(13);
+
+  /* Basic checking if a fifo file created with mkfifo() is a pipe. */
+  alarm(10);		/* in case fifo hangs */
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	if ((fd = open("fifo", O_RDONLY)) != 3) e(14);
+	if (read(fd, buf, BUF_SIZE) != 7) e(15);
+	if (strcmp(buf, "banana") != 0) e(16);
+	if (close(fd) != 0) e(17);
+	if ((fd = open("fifo", O_WRONLY)) != 3) e(18);
+	if (write(fd, "thanks", 7) != 7) e(19);
+	if (close(fd) != 0) e(20);
+	exit(0);
+
+      default:
+	if ((fd = open("fifo", O_WRONLY)) != 3) e(21);
+	if (write(fd, "banana", 7) != 7) e(22);
+	if (close(fd) != 0) e(23);
+	if ((fd = open("fifo", O_RDONLY)) != 3) e(24);
+	if (read(fd, buf, BUF_SIZE) != 7) e(25);
+	if (strcmp(buf, "thanks") != 0) e(26);
+	if (close(fd) != 0) e(27);
+	wait(&stat_loc);
+	if (stat_loc != 0) e(28);	/* Alarm? */
+  }
+  alarm(0);
+}
+
+void test31b()
+{
+  subtest = 2;
+
+  System("rm -rf ../DIR_31/*");
+
+  /* Test maximal file name length. */
+  if (mkfifo(MaxName, 0777) != 0) e(1);
+  if (unlink(MaxName) != 0) e(2);
+  MaxPath[strlen(MaxPath) - 2] = '/';
+  MaxPath[strlen(MaxPath) - 1] = 'a';	/* make ././.../a */
+  if (mkfifo(MaxPath, 0777) != 0) e(3);
+  if (unlink(MaxPath) != 0) e(4);
+  MaxPath[strlen(MaxPath) - 1] = '/';	/* make ././.../a */
+}
+
+void test31c()
+{
+  subtest = 3;
+
+  System("rm -rf ../DIR_31/*");
+
+  /* Check if mkfifo() removes, files, fifos, dirs. */
+  if (mkfifo("fifo", 0777) != 0) e(1);
+  System("mkdir dir; > file");
+  if (mkfifo("fifo", 0777) != -1) e(2);
+  if (errno != EEXIST) e(3);
+  if (mkfifo("dir", 0777) != -1) e(4);
+  if (errno != EEXIST) e(5);
+  if (mkfifo("file", 0777) != -1) e(6);
+  if (errno != EEXIST) e(7);
+
+  /* Test empty path. */
+  if (mkfifo("", 0777) != -1) e(8);
+  if (errno != ENOENT) e(9);
+  if (mkfifo("/tmp/noway/out", 0777) != -1) e(10);
+  if (errno != ENOENT) e(11);
+
+  /* Test if path prefix is a directory. */
+  if (mkfifo("/etc/passwd/nono", 0777) != -1) e(12);
+  if (errno != ENOTDIR) e(13);
+
+  mkdir("bar", 0777);		/* make bar */
+
+  /* Check if no access on part of path generates the correct error. */
+  System("chmod 577 bar");	/* r-xrwxrwx */
+  if (!superuser) {
+	if (mkfifo("bar/nono", 0666) != -1) e(14);
+	if (errno != EACCES) e(15);
+  }
+  if (superuser) {
+	if (mkfifo("bar/nono", 0666) != 0) e(14);
+	if (unlink("bar/nono") != 0) e(666);
+  }
+  System("chmod 677 bar");	/* rw-rwxrwx */
+  if (!superuser) {
+	if (mkfifo("bar/../nono", 0666) != -1) e(16);
+	if (errno != EACCES) e(17);
+  }
+  if (unlink("nono") != -1) e(18);
+
+  /* Clean up bar. */
+  System("rm -rf bar");
+
+  /* Test ToLongName and ToLongPath */
+#ifdef _POSIX_NO_TRUNC
+# if _POSIX_NO_TRUNC - 0 != -1
+  if (mkfifo(ToLongName, 0777) != -1) e(19);
+  if (errno != ENAMETOOLONG) e(20);
+# else
+  if (mkfifo(ToLongName, 0777) != 0) e(21);
+# endif
+#else
+# include "error, this case requires dynamic checks and is not handled"
+#endif
+  ToLongPath[PATH_MAX - 2] = '/';
+  ToLongPath[PATH_MAX - 1] = 'a';
+  if (mkfifo(ToLongPath, 0777) != -1) e(22);
+  if (errno != ENAMETOOLONG) e(23);
+  ToLongPath[PATH_MAX - 1] = '/';
+}
+
+void makelongnames()
+{
+  register int i;
+
+  memset(MaxName, 'a', NAME_MAX);
+  MaxName[NAME_MAX] = '\0';
+  for (i = 0; i < PATH_MAX - 1; i++) {	/* idem path */
+	MaxPath[i++] = '.';
+	MaxPath[i] = '/';
+  }
+  MaxPath[PATH_MAX - 1] = '\0';
+
+  strcpy(ToLongName, MaxName);	/* copy them Max to ToLong */
+  strcpy(ToLongPath, MaxPath);
+
+  ToLongName[NAME_MAX] = 'a';
+  ToLongName[NAME_MAX + 1] = '\0';	/* extend ToLongName by one too many */
+  ToLongPath[PATH_MAX - 1] = '/';
+  ToLongPath[PATH_MAX] = '\0';	/* inc ToLongPath by one */
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  System("rm -rf DIR_31");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test32.c
===================================================================
--- /trunk/minix/test/test32.c	(revision 9)
+++ /trunk/minix/test/test32.c	(revision 9)
@@ -0,0 +1,367 @@
+/* test32: rename()		Author: Jan-Mark Wams (jms@cs.vu.nl) */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+
+#define MAX_ERROR	4
+#define ITERATIONS      2
+
+#define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+#define Stat(a,b)	if (stat(a,b) != 0) printf("Can't stat %s\n", a)
+#define Creat(f)	if (close(creat(f,0777))!=0) printf("Can't creat %s\n",f)
+
+int errct = 0;
+int subtest = 1;
+int superuser;
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];		/* Same for path */
+char ToLongName[NAME_MAX + 2];	/* Name of maximum +1 length */
+char ToLongPath[PATH_MAX + 1];	/* Same for path, both too long */
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test32a, (void));
+_PROTOTYPE(void test32b, (void));
+_PROTOTYPE(void test32c, (void));
+_PROTOTYPE(void makelongnames, (void));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 32 ");
+  fflush(stdout);
+  System("rm -rf DIR_32; mkdir DIR_32");
+  Chdir("DIR_32");
+  makelongnames();
+  superuser = (geteuid() == 0);
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test32a();
+	if (m & 0002) test32b();
+	if (m & 0004) test32c();
+  }
+  quit();
+}
+
+#define BUF_SIZE 1024
+
+void test32a()
+{				/* Test normal operation. */
+  struct stat st1, st2;
+  int fd1, fd2;
+  time_t time1, time2, time3;
+  char buf[BUF_SIZE];
+
+  subtest = 1;
+  System("rm -rf ../DIR_32/*");
+
+  /* Test normal file renamal. */
+  System("echo haha > old");
+  Stat("old", &st1);
+  if (rename("old", "new") != 0) e(1);
+  Stat("new", &st2);
+
+  /* The status of new should be the same as old. */
+  if (st1.st_dev != st2.st_dev) e(2);
+  if (st1.st_ino != st2.st_ino) e(3);
+  if (st1.st_mode != st2.st_mode) e(4);
+  if (st1.st_nlink != st2.st_nlink) e(5);
+  if (st1.st_uid != st2.st_uid) e(6);
+  if (st1.st_gid != st2.st_gid) e(7);
+  if (st1.st_rdev != st2.st_rdev) e(8);
+  if (st1.st_size != st2.st_size) e(9);
+  if (st1.st_atime != st2.st_atime) e(10);
+  if (st1.st_mtime != st2.st_mtime) e(11);
+  if (st1.st_ctime != st2.st_ctime) e(12);
+
+  /* If new exists, it should be removed. */
+  System("ln new new2");
+  System("echo foobar > old");
+  Stat("old", &st1);
+  if (rename("old", "new") != 0) e(13);
+  Stat("new", &st2);
+
+  /* The status of new should be the same as old. */
+  if (st1.st_dev != st2.st_dev) e(14);
+  if (st1.st_ino != st2.st_ino) e(15);
+  if (st1.st_mode != st2.st_mode) e(16);
+  if (st1.st_nlink != st2.st_nlink) e(17);
+  if (st1.st_uid != st2.st_uid) e(18);
+  if (st1.st_gid != st2.st_gid) e(19);
+  if (st1.st_rdev != st2.st_rdev) e(20);
+  if (st1.st_size != st2.st_size) e(21);
+  if (st1.st_atime != st2.st_atime) e(22);
+  if (st1.st_mtime != st2.st_mtime) e(23);
+  if (st1.st_ctime != st2.st_ctime) e(24);
+
+  /* The link count on new2 should be one since the old new is removed. */
+  Stat("new2", &st1);
+  if (st1.st_nlink != 1) e(25);
+
+  /* Check if status for "." is updated. */
+  System("> OLD");
+  Stat(".", &st1);
+  time(&time1);
+  while (time1 == time((time_t *)0))
+	;
+  time(&time2);
+  rename("OLD", "NEW");
+  Stat(".", &st2);
+  time(&time3);
+  while (time3 == time((time_t *)0))
+	;
+  time(&time3);
+  if (st1.st_ctime >= st2.st_ctime) e(26);
+  if (st1.st_mtime >= st2.st_mtime) e(27);
+  if (st1.st_ctime > time1) e(28);
+  if (st1.st_mtime > time1) e(29);
+  if (st1.st_ctime >= time2) e(30);
+  if (st1.st_mtime >= time2) e(31);
+  if (st2.st_ctime < time2) e(32);
+  if (st2.st_mtime < time2) e(33);
+  if (st2.st_ctime >= time3) e(34);
+  if (st2.st_mtime >= time3) e(35);
+
+  /* If the new file is removed while it's open it should still be
+   * readable. */
+  System("rm -rf new NEW old OLD");
+  if ((fd1 = creat("new", 0644)) != 3) e(36);
+  if (write(fd1, "Hi there! I am Sammy the string", 33) != 33) e(37);
+  if (close(fd1) != 0) e(38);
+  if ((fd1 = creat("old", 0644)) != 3) e(39);
+  if (write(fd1, "I need a new name", 18) != 18) e(40);
+  if (close(fd1) != 0) e(41);
+  if ((fd1 = open("new", O_RDONLY)) != 3) e(42);
+  if ((fd2 = open("new", O_RDONLY)) != 4) e(43);
+  if (rename("old", "new") != 0) e(44);
+  if (stat("old", &st1) == 0) e(45);
+  if (close(fd1) != 0) e(46);
+  if ((fd1 = open("new", O_RDONLY)) != 3) e(47);
+  if (read(fd2, buf, BUF_SIZE) != 33) e(48);
+  if (strcmp(buf, "Hi there! I am Sammy the string") != 0) e(49);
+  if (read(fd1, buf, BUF_SIZE) != 18) e(50);
+  if (strcmp(buf, "I need a new name") != 0) e(51);
+  if (close(fd1) != 0) e(52);
+  if (close(fd2) != 0) e(53);
+}
+
+void test32b()
+{
+  char MaxPath2[PATH_MAX];	/* Same for path */
+  char MaxName2[NAME_MAX + 1];	/* Name of maximum length */
+  int fd, i;
+  int stat_loc;
+  struct stat st;
+
+  subtest = 2;
+  System("rm -rf ../DIR_32/*");
+
+  /* Test maximal file name length. */
+  if ((fd = creat(MaxName, 0777)) != 3) e(1);
+  if (close(fd) != 0) e(2);
+  strcpy(MaxName2, MaxName);
+  MaxName2[strlen(MaxName2) - 1] ^= 1;
+  if (rename(MaxName, MaxName2) != 0) e(3);
+  if (rename(MaxName2, MaxName) != 0) e(4);
+  MaxName2[strlen(MaxName2) - 1] ^= 2;
+  if (rename(MaxName, MaxName2) != 0) e(5);
+  MaxPath[strlen(MaxPath) - 2] = '/';
+  MaxPath[strlen(MaxPath) - 1] = 'a';	/* make ././.../a */
+  if ((fd = creat(MaxPath, 0777)) != 3) e(6);
+  if (close(fd) != 0) e(7);
+  strcpy(MaxPath2, MaxPath);
+  MaxPath2[strlen(MaxPath2) - 1] ^= 1;
+  if (rename(MaxPath, MaxPath2) != 0) e(8);
+  if (rename(MaxPath2, MaxPath) != 0) e(9);
+  MaxPath2[strlen(MaxPath2) - 1] ^= 2;
+  if (rename(MaxPath, MaxPath2) != 0) e(10);
+  MaxPath[strlen(MaxPath) - 1] = '/';	/* make ././.../a */
+
+  /* Test if linked files are renamable. */
+  System("> foo; ln foo bar");
+  if (rename("foo", "bar") != 0) e(11);
+  if (rename("bar", "foo") != 0) e(12);
+  System("ln foo foobar");
+  if (rename("foo", "foobar") != 0) e(13);
+  if (rename("bar", "foobar") != 0) e(14);
+
+  /* Since the same files have the same links.... */
+  if (rename("bar", "bar") != 0) e(15);
+  if (rename("foo", "foo") != 0) e(16);
+  if (rename("foobar", "foobar") != 0) e(17);
+
+  /* In ``rename(old, new)'' with new existing, there is always an new
+   * entry. */
+  for (i = 0; i < 5; i++) {
+	System("echo old > old");
+	System("echo news > new");
+	switch (fork()) {
+	    case -1:	printf("Can't fork\n");	break;
+	    case 0:
+		alarm(20);
+		sleep(1);
+		rename("old", "new");
+		exit(0);
+	    default:
+		while (stat("old", &st) != 0)
+			if (stat("new", &st) != 0) e(18);
+		wait(&stat_loc);
+		if (stat_loc != 0) e(19);	/* Alarm? */
+	}
+  }
+
+}
+
+void test32c()
+{				/* Test behavior under error contitions. */
+  struct stat st1;
+  int stat_loc;
+
+  subtest = 3;
+  System("rm -rf ../DIR_32/*");
+
+  /* Test if we have access. */
+  system("chmod 777 noacc nowrite > /dev/null 2>/dev/null");
+  system("rm -rf noacc nowrite");
+
+  System("mkdir noacc nowrite");
+  System("> noacc/file");
+  System("> nowrite/file");
+  System("> file");
+  System("chmod 677 noacc");
+  System("chmod 577 nowrite");
+  if (!superuser) {
+	if (rename("noacc/file", "nono") != -1) e(1);
+	if (errno != EACCES) e(2);
+	if (rename("nowrite/file", "nono") != -1) e(3);
+	if (errno != EACCES) e(4);
+	if (rename("file", "noacc/file") != -1) e(5);
+	if (errno != EACCES) e(6);
+	if (rename("file", "nowrite/file") != -1) e(7);
+	if (errno != EACCES) e(8);
+  }
+  if (superuser) {
+	/* Super user heeft access. */
+	if (rename("noacc/file", "noacc/yes") != 0) e(9);
+	if (rename("nowrite/file", "nowrite/yes") != 0) e(10);
+	if (rename("file", "yes") != 0) e(11);
+	if (rename("noacc/yes", "noacc/file") != 0) e(12);
+	if (rename("nowrite/yes", "nowrite/file") != 0) e(13);
+	if (rename("yes", "file") != 0) e(14);
+  }
+  System("chmod 777 noacc nowrite");
+
+  /* If rmdir() doesn't remove a directory, rename() shouldn't eighter. */
+  System("mkdir newdir olddir");
+  System("rm -rf /tmp/sema.11[ab]");
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	switch (fork()) {
+	    case -1:	printf("Can't fork\n");	break;
+	    case 0:
+		/* Child A. */
+		alarm(20);
+		if (chdir("newdir") != 0) e(15);
+		Creat("/tmp/sema.11a");
+		while (stat("/tmp/sema.11a", &st1) == -1) sleep(1);
+		exit(0);
+	    default:
+		wait(&stat_loc);
+		if (stat_loc != 0) e(16);	/* Alarm? */
+	}
+
+	/* Child B. */
+	if (chdir("olddir") != 0) e(17);
+	Creat("/tmp/sema.11b");
+	while (stat("/tmp/sema.11b", &st1) == -1) sleep(1);
+	exit(0);
+      default:
+	/* Wait for child A. It will keep ``newdir'' bussy. */
+	while (stat("/tmp/sema.11a", &st1) == -1) sleep(1);
+	if (rmdir("newdir") == -1) {
+		if (rename("olddir", "newdir") != -1) e(18);
+		if (errno != EBUSY) e(19);
+	}
+	(void) unlink("/tmp/sema.11a");
+
+	/* Wait for child B. It will keep ``olddir'' bussy. */
+	while (stat("/tmp/sema.11b", &st1) == -1) sleep(1);
+	if (rmdir("olddir") == -1) {
+		if (rename("olddir", "newdir") != -1) e(20);
+		if (errno != EBUSY) e(21);
+	}
+	(void) unlink("/tmp/sema.11b");
+	wait(&stat_loc);
+	if (stat_loc != 0) e(22);	/* Alarm? */
+  }
+}
+
+void makelongnames()
+{
+  register int i;
+
+  memset(MaxName, 'a', NAME_MAX);
+  MaxName[NAME_MAX] = '\0';
+  for (i = 0; i < PATH_MAX - 1; i++) {	/* idem path */
+	MaxPath[i++] = '.';
+	MaxPath[i] = '/';
+  }
+  MaxPath[PATH_MAX - 1] = '\0';
+
+  strcpy(ToLongName, MaxName);	/* copy them Max to ToLong */
+  strcpy(ToLongPath, MaxPath);
+
+  ToLongName[NAME_MAX] = 'a';
+  ToLongName[NAME_MAX + 1] = '\0';	/* extend ToLongName by one too many */
+  ToLongPath[PATH_MAX - 1] = '/';
+  ToLongPath[PATH_MAX] = '\0';	/* inc ToLongPath by one */
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  System("rm -rf DIR_32");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test33.c
===================================================================
--- /trunk/minix/test/test33.c	(revision 9)
+++ /trunk/minix/test/test33.c	(revision 9)
@@ -0,0 +1,652 @@
+/* test33: access()		Author: Jan-Mark Wams (jms@cs.vu.nl) */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+
+#define MAX_ERROR      1
+#define ITERATIONS     2
+
+#define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+#define Stat(a,b)	if (stat(a,b) != 0) printf("Can't stat %s\n", a)
+#define Chmod(a,b)	if (chmod(a,b) != 0) printf("Can't chmod %s\n", a)
+#define Mkfifo(f)	if (mkfifo(f,0777)!=0) printf("Can't make fifo %s\n", f)
+
+int errct = 0;
+int subtest = 1;
+int superuser;			/* nonzero if uid == euid (euid == 0 always) */
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];		/* Same for path */
+char ToLongName[NAME_MAX + 2];	/* Name of maximum +1 length */
+char ToLongPath[PATH_MAX + 1];	/* Same for path, both too long */
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test33a, (void));
+_PROTOTYPE(void test33b, (void));
+_PROTOTYPE(void test33c, (void));
+_PROTOTYPE(void test33d, (void));
+_PROTOTYPE(void test_access, (void));
+_PROTOTYPE(void makelongnames, (void));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 33 ");
+  fflush(stdout);
+
+  if (geteuid() != 0) {
+	printf("must be setuid root; test aborted\n");
+	exit(1);
+  }
+  if (getuid() == 0) {
+       printf("must be setuid root logged in as someone else; test aborted\n");
+       exit(1);
+  }
+
+  umask(0000);
+  System("rm -rf DIR_33; mkdir DIR_33");
+  Chdir("DIR_33");
+  makelongnames();
+  superuser = (getuid() == 0);
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test33a();
+	if (m & 0002) test33b();
+	if (m & 0004) test33c();
+	if (m & 0010) test33d();
+  }
+  quit();
+}
+
+void test33a()
+{				/* Test normal operation. */
+  int stat_loc;			/* For the wait(&stat_loc) call. */
+
+  subtest = 1;
+  System("rm -rf ../DIR_33/*");
+
+  /* To test normal access first make some files for real uid. */
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	setuid(getuid());	/* (Re)set the effective ids to the
+				 * real ids. */
+	setgid(getgid());
+	System("> rwx; chmod 700 rwx");
+	System("> rw_; chmod 600 rw_");
+	System("> r_x; chmod 500 r_x");
+	System("> r__; chmod 400 r__");
+	System("> _wx; chmod 300 _wx");
+	System("> _w_; chmod 200 _w_");
+	System("> __x; chmod 100 __x");
+	System("> ___; chmod 000 ___");
+	exit(0);
+
+      default:
+	wait(&stat_loc);
+	if (stat_loc != 0) e(1);/* Alarm? */
+  }
+  test_access();
+
+  /* Let's test access() on directorys. */
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	setuid(getuid());	/* (Re)set the effective ids to the
+				 * real ids. */
+	setgid(getgid());
+	System("rm -rf [_r][_w][_x]");
+	System("mkdir rwx; chmod 700 rwx");
+	System("mkdir rw_; chmod 600 rw_");
+	System("mkdir r_x; chmod 500 r_x");
+	System("mkdir r__; chmod 400 r__");
+	System("mkdir _wx; chmod 300 _wx");
+	System("mkdir _w_; chmod 200 _w_");
+	System("mkdir __x; chmod 100 __x");
+	System("mkdir ___; chmod 000 ___");
+	exit(0);
+
+      default:
+	wait(&stat_loc);
+	if (stat_loc != 0) e(2);/* Alarm? */
+  }
+  test_access();
+
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	setuid(getuid());	/* (Re)set the effective ids to the
+				 * real ids. */
+	setgid(getgid());
+	System("rmdir [_r][_w][_x]");
+	Mkfifo("rwx");
+	System("chmod 700 rwx");
+	Mkfifo("rw_");
+	System("chmod 600 rw_");
+	Mkfifo("r_x");
+	System("chmod 500 r_x");
+	Mkfifo("r__");
+	System("chmod 400 r__");
+	Mkfifo("_wx");
+	System("chmod 300 _wx");
+	Mkfifo("_w_");
+	System("chmod 200 _w_");
+	Mkfifo("__x");
+	System("chmod 100 __x");
+	Mkfifo("___");
+	System("chmod 000 ___");
+	exit(0);
+
+      default:
+	wait(&stat_loc);
+	if (stat_loc != 0) e(3);/* Alarm? */
+  }
+  test_access();
+
+  /* Remove all the fifos. */
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	setuid(getuid());
+	setgid(getgid());
+	System("rm -rf [_r][_w][_x]");
+	exit(0);
+
+      default:
+	wait(&stat_loc);
+	if (stat_loc != 0) e(4);/* Alarm? */
+  }
+}
+
+void test33b()
+{
+  int stat_loc;			/* For the wait(&stat_loc) call. */
+
+  subtest = 2;
+  System("rm -rf ../DIR_33/*");
+
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+
+	/* (Re)set the effective ids to the real ids. */
+	setuid(getuid());
+	setgid(getgid());
+	System("> ______rwx; chmod 007 ______rwx");
+	System("> ________x; chmod 001 ________x");
+	System("> _________; chmod 000 _________");
+	exit(0);
+
+      default:
+	wait(&stat_loc);
+	if (stat_loc != 0) e(1);/* Alarm? */
+  }
+
+  /* If we are superuser, we have access to all. */
+  /* Well, almost, execution access might need at least one X bit. */
+  if (superuser) {
+	if (access("_________", R_OK) != 0) e(2);
+	if (access("_________", W_OK) != 0) e(3);
+	if (access("________x", R_OK) != 0) e(4);
+	if (access("________x", W_OK) != 0) e(5);
+	if (access("________x", X_OK) != 0) e(6);
+	if (access("______rwx", R_OK) != 0) e(7);
+	if (access("______rwx", W_OK) != 0) e(8);
+	if (access("______rwx", X_OK) != 0) e(9);
+  }
+  if (!superuser) {
+	if (access("_________", R_OK) != -1) e(10);
+	if (errno != EACCES) e(11);
+	if (access("_________", W_OK) != -1) e(12);
+	if (errno != EACCES) e(13);
+	if (access("_________", X_OK) != -1) e(14);
+	if (errno != EACCES) e(15);
+	if (access("________x", R_OK) != -1) e(16);
+	if (errno != EACCES) e(17);
+	if (access("________x", W_OK) != -1) e(18);
+	if (errno != EACCES) e(19);
+	if (access("________x", X_OK) != -1) e(20);
+	if (errno != EACCES) e(21);
+	if (access("______rwx", R_OK) != -1) e(22);
+	if (errno != EACCES) e(23);
+	if (access("______rwx", W_OK) != -1) e(24);
+	if (errno != EACCES) e(25);
+	if (access("______rwx", X_OK) != -1) e(26);
+	if (errno != EACCES) e(27);
+  }
+
+  /* If the real uid != effective uid. */
+  if (!superuser) {
+	System("rm -rf [_r][_w][_x]");
+	System("> rwx");
+	Chmod("rwx", 0700);
+	System("> rw_");
+	Chmod("rw_", 0600);
+	System("> r_x");
+	Chmod("r_x", 0500);
+	System("> r__");
+	Chmod("r__", 0400);
+	System("> _wx");
+	Chmod("_wx", 0300);
+	System("> _w_");
+	Chmod("_w_", 0200);
+	System("> __x");
+	Chmod("__x", 0100);
+	System("> ___");
+	Chmod("___", 0000);
+
+	if (access("rwx", F_OK) != 0) e(28);
+	if (access("rwx", R_OK) != -1) e(29);
+	if (errno != EACCES) e(30);
+	if (access("rwx", W_OK) != -1) e(31);
+	if (errno != EACCES) e(32);
+	if (access("rwx", X_OK) != -1) e(33);
+	if (errno != EACCES) e(34);
+
+	if (access("rw_", F_OK) != 0) e(35);
+	if (access("rw_", R_OK) != -1) e(36);
+	if (errno != EACCES) e(37);
+	if (access("rw_", W_OK) != -1) e(38);
+	if (errno != EACCES) e(39);
+	if (access("rw_", X_OK) != -1) e(40);
+	if (errno != EACCES) e(41);
+
+	if (access("r_x", F_OK) != 0) e(42);
+	if (access("r_x", R_OK) != -1) e(43);
+	if (errno != EACCES) e(44);
+	if (access("r_x", W_OK) != -1) e(45);
+	if (errno != EACCES) e(46);
+	if (access("r_x", X_OK) != -1) e(47);
+	if (errno != EACCES) e(48);
+
+	if (access("r__", F_OK) != 0) e(49);
+	if (access("r__", R_OK) != -1) e(50);
+	if (errno != EACCES) e(51);
+	if (access("r__", W_OK) != -1) e(52);
+	if (errno != EACCES) e(53);
+	if (access("r__", X_OK) != -1) e(54);
+	if (errno != EACCES) e(55);
+
+	if (access("_wx", F_OK) != 0) e(56);
+	if (access("_wx", R_OK) != -1) e(57);
+	if (errno != EACCES) e(58);
+	if (access("_wx", W_OK) != -1) e(59);
+	if (errno != EACCES) e(60);
+	if (access("_wx", X_OK) != -1) e(61);
+	if (errno != EACCES) e(62);
+
+	if (access("_w_", F_OK) != 0) e(63);
+	if (access("_w_", R_OK) != -1) e(64);
+	if (errno != EACCES) e(65);
+	if (access("_w_", W_OK) != -1) e(66);
+	if (errno != EACCES) e(67);
+	if (access("_w_", X_OK) != -1) e(68);
+	if (errno != EACCES) e(69);
+
+	if (access("__x", F_OK) != 0) e(70);
+	if (access("__x", R_OK) != -1) e(71);
+	if (errno != EACCES) e(72);
+	if (access("__x", W_OK) != -1) e(73);
+	if (errno != EACCES) e(74);
+	if (access("__x", X_OK) != -1) e(75);
+	if (errno != EACCES) e(76);
+
+	if (access("___", F_OK) != 0) e(77);
+	if (access("___", R_OK) != -1) e(78);
+	if (errno != EACCES) e(79);
+	if (access("___", W_OK) != -1) e(80);
+	if (errno != EACCES) e(81);
+	if (access("___", X_OK) != -1) e(82);
+	if (errno != EACCES) e(83);
+
+	System("rm -rf [_r][_w][_x]");
+  }
+}
+
+void test33c()
+{				/* Test errors returned. */
+  int i;
+
+  subtest = 3;
+  System("rm -rf ../DIR_33/*");
+
+  /* Test what access() does with non existing files. */
+  System("rm -rf nonexist");
+  if (access("noexist", F_OK) != -1) e(1);
+  if (errno != ENOENT) e(2);
+  if (access("noexist", R_OK) != -1) e(3);
+  if (errno != ENOENT) e(4);
+  if (access("noexist", W_OK) != -1) e(5);
+  if (errno != ENOENT) e(6);
+  if (access("noexist", X_OK) != -1) e(7);
+  if (errno != ENOENT) e(8);
+  if (access("noexist", R_OK | W_OK) != -1) e(9);
+  if (errno != ENOENT) e(10);
+  if (access("noexist", R_OK | X_OK) != -1) e(11);
+  if (errno != ENOENT) e(12);
+  if (access("noexist", W_OK | X_OK) != -1) e(13);
+  if (errno != ENOENT) e(14);
+  if (access("noexist", R_OK | W_OK | X_OK) != -1) e(15);
+  if (errno != ENOENT) e(16);
+
+  /* Test access on a nonsearchable path. */
+  if (mkdir("nosearch", 0777) != 0) e(1000);
+  if ( (i = creat("nosearch/file", 0666)) < 0) e(1001);
+  if (close(i) < 0) e(1002);
+  if ( (i = creat("file", 0666) < 0)) e(1003);
+  if (close(i) < 0) e(1004);
+  if (chmod("nosearch/file", 05777) < 0) e(1005);
+  if (chmod("file", 05777) < 0) e(1006);
+  if (chmod("nosearch", 0677) != 0) e(1007);
+  if (access("nosearch/file", F_OK) != 0) e(17);
+
+  /* Test ToLongName and ToLongPath */
+#ifdef _POSIX_NO_TRUNC
+# if _POSIX_NO_TRUNC - 0 != -1
+  if (access(ToLongName, F_OK) != -1) e(23);
+  if (errno != ENAMETOOLONG) e(24);
+# else
+  if (close(creat(ToLongName, 0777)) != 0) e(25);
+  if (access(ToLongName, F_OK) != 0) e(26);
+# endif
+#else
+# include "error, this case requires dynamic checks and is not handled"
+#endif
+  ToLongPath[PATH_MAX - 2] = '/';
+  ToLongPath[PATH_MAX - 1] = 'a';
+  if (access(ToLongPath, F_OK) != -1) e(27);
+  if (errno != ENAMETOOLONG) e(28);
+  ToLongPath[PATH_MAX - 1] = '/';
+
+  /* Test empty strings. */
+  if (access("", F_OK) != -1) e(29);
+  if (errno != ENOENT) e(30);
+  System("rm -rf idonotexist");
+  if (access("idonotexist", F_OK) != -1) e(31);
+  if (errno != ENOENT) e(32);
+
+  /* Test non directorys in prefix of path. */
+  if (access("/etc/passwd/dir/foo", F_OK) != -1) e(33);
+  if (errno != ENOTDIR) e(34);
+  System("rm -rf nodir; > nodir");
+  if (access("nodir/foo", F_OK) != -1) e(35);
+  if (errno != ENOTDIR) e(36);
+
+  /* Test if invalid amode arguments are signaled. */
+  System("> allmod");
+  Chmod("allmod", 05777);
+  for (i = -1025; i < 1025; i++) {
+	if ((mode_t) i != F_OK && ((mode_t) i & ~(R_OK | W_OK | X_OK)) != 0) {
+		if (access("allmod", (mode_t) i) != -1) e(37);
+		if (errno != EINVAL) e(38);
+	} else 
+		if (access("allmod", (mode_t) i) != 0) e(39);
+  }
+}
+
+void test33d()
+{				/* Test access() flags. */
+#define EXCLUDE(a,b)	(((a)^(b)) == ((a)|(b)))
+  subtest = 4;
+  System("rm -rf ../DIR_33/*");
+
+  /* The test are rather strong, stronger that POSIX specifies. */
+  /* The should be OR able, this test tests if all the 1 bits */
+  /* Are in diferent places. This should be what one wants. */
+  if (!EXCLUDE(R_OK, W_OK | X_OK)) e(1);
+  if (!EXCLUDE(W_OK, R_OK | X_OK)) e(2);
+  if (!EXCLUDE(X_OK, R_OK | W_OK)) e(3);
+  if (F_OK == R_OK) e(4);
+  if (F_OK == W_OK) e(5);
+  if (F_OK == X_OK) e(6);
+  if (F_OK == (R_OK | W_OK)) e(7);
+  if (F_OK == (W_OK | X_OK)) e(8);
+  if (F_OK == (R_OK | X_OK)) e(9);
+  if (F_OK == (R_OK | W_OK | X_OK)) e(10);
+}
+
+void test_access()
+{				/* Test all [_r][_w][_x] files. */
+  if (!superuser) {
+	/* Test normal access. */
+	if (access("rwx", F_OK) != 0) e(11);
+	if (access("rwx", R_OK) != 0) e(12);
+	if (access("rwx", W_OK) != 0) e(13);
+	if (access("rwx", X_OK) != 0) e(14);
+	if (access("rwx", R_OK | W_OK) != 0) e(15);
+	if (access("rwx", R_OK | X_OK) != 0) e(16);
+	if (access("rwx", W_OK | X_OK) != 0) e(17);
+	if (access("rwx", R_OK | W_OK | X_OK) != 0) e(18);
+
+	if (access("rw_", F_OK) != 0) e(19);
+	if (access("rw_", R_OK) != 0) e(20);
+	if (access("rw_", W_OK) != 0) e(21);
+	if (access("rw_", X_OK) != -1) e(22);
+	if (errno != EACCES) e(23);
+	if (access("rw_", R_OK | W_OK) != 0) e(24);
+	if (access("rw_", R_OK | X_OK) != -1) e(25);
+	if (errno != EACCES) e(26);
+	if (access("rw_", W_OK | X_OK) != -1) e(27);
+	if (errno != EACCES) e(28);
+	if (access("rw_", R_OK | W_OK | X_OK) != -1) e(29);
+	if (errno != EACCES) e(30);
+
+	if (access("r_x", F_OK) != 0) e(31);
+	if (access("r_x", R_OK) != 0) e(32);
+	if (access("r_x", W_OK) != -1) e(33);
+	if (errno != EACCES) e(34);
+	if (access("r_x", X_OK) != 0) e(35);
+	if (access("r_x", R_OK | W_OK) != -1) e(36);
+	if (errno != EACCES) e(37);
+	if (access("r_x", R_OK | X_OK) != 0) e(38);
+	if (access("r_x", W_OK | X_OK) != -1) e(39);
+	if (errno != EACCES) e(40);
+	if (access("r_x", R_OK | W_OK | X_OK) != -1) e(41);
+	if (errno != EACCES) e(42);
+
+	if (access("r__", F_OK) != 0) e(43);
+	if (access("r__", R_OK) != 0) e(44);
+	if (access("r__", W_OK) != -1) e(45);
+	if (errno != EACCES) e(46);
+	if (access("r__", X_OK) != -1) e(47);
+	if (errno != EACCES) e(48);
+	if (access("r__", R_OK | W_OK) != -1) e(49);
+	if (errno != EACCES) e(50);
+	if (access("r__", R_OK | X_OK) != -1) e(51);
+	if (errno != EACCES) e(52);
+	if (access("r__", W_OK | X_OK) != -1) e(53);
+	if (errno != EACCES) e(54);
+	if (access("r__", R_OK | W_OK | X_OK) != -1) e(55);
+	if (errno != EACCES) e(56);
+
+	if (access("_wx", F_OK) != 0) e(57);
+	if (access("_wx", R_OK) != -1) e(58);
+	if (errno != EACCES) e(59);
+	if (access("_wx", W_OK) != 0) e(60);
+	if (access("_wx", X_OK) != 0) e(61);
+	if (access("_wx", R_OK | W_OK) != -1) e(62);
+	if (errno != EACCES) e(63);
+	if (access("_wx", R_OK | X_OK) != -1) e(64);
+	if (errno != EACCES) e(65);
+	if (access("_wx", W_OK | X_OK) != 0) e(66);
+	if (access("_wx", R_OK | W_OK | X_OK) != -1) e(67);
+	if (errno != EACCES) e(68);
+
+	if (access("_w_", F_OK) != 0) e(69);
+	if (access("_w_", R_OK) != -1) e(70);
+	if (errno != EACCES) e(71);
+	if (access("_w_", W_OK) != 0) e(72);
+	if (access("_w_", X_OK) != -1) e(73);
+	if (errno != EACCES) e(74);
+	if (access("_w_", R_OK | W_OK) != -1) e(75);
+	if (errno != EACCES) e(76);
+	if (access("_w_", R_OK | X_OK) != -1) e(77);
+	if (errno != EACCES) e(78);
+	if (access("_w_", W_OK | X_OK) != -1) e(79);
+	if (errno != EACCES) e(80);
+	if (access("_w_", R_OK | W_OK | X_OK) != -1) e(81);
+	if (errno != EACCES) e(82);
+
+	if (access("__x", F_OK) != 0) e(83);
+	if (access("__x", R_OK) != -1) e(84);
+	if (errno != EACCES) e(85);
+	if (access("__x", W_OK) != -1) e(86);
+	if (errno != EACCES) e(87);
+	if (access("__x", X_OK) != 0) e(88);
+	if (access("__x", R_OK | W_OK) != -1) e(89);
+	if (errno != EACCES) e(90);
+	if (access("__x", R_OK | X_OK) != -1) e(91);
+	if (errno != EACCES) e(92);
+	if (access("__x", W_OK | X_OK) != -1) e(93);
+	if (errno != EACCES) e(94);
+	if (access("__x", R_OK | W_OK | X_OK) != -1) e(95);
+	if (errno != EACCES) e(96);
+
+	if (access("___", F_OK) != 0) e(97);
+	if (access("___", R_OK) != -1) e(98);
+	if (errno != EACCES) e(99);
+	if (access("___", W_OK) != -1) e(100);
+	if (errno != EACCES) e(101);
+	if (access("___", X_OK) != -1) e(102);
+	if (errno != EACCES) e(103);
+	if (access("___", R_OK | W_OK) != -1) e(104);
+	if (errno != EACCES) e(105);
+	if (access("___", R_OK | X_OK) != -1) e(106);
+	if (errno != EACCES) e(107);
+	if (access("___", W_OK | X_OK) != -1) e(108);
+	if (errno != EACCES) e(109);
+	if (access("___", R_OK | W_OK | X_OK) != -1) e(110);
+	if (errno != EACCES) e(111);
+  }
+  if (superuser) {
+	/* Test root access don't test X_OK on [_r][_w]_ files. */
+	if (access("rwx", F_OK) != 0) e(112);
+	if (access("rwx", R_OK) != 0) e(113);
+	if (access("rwx", W_OK) != 0) e(114);
+	if (access("rwx", X_OK) != 0) e(115);
+	if (access("rwx", R_OK | W_OK) != 0) e(116);
+	if (access("rwx", R_OK | X_OK) != 0) e(117);
+	if (access("rwx", W_OK | X_OK) != 0) e(118);
+	if (access("rwx", R_OK | W_OK | X_OK) != 0) e(119);
+
+	if (access("rw_", F_OK) != 0) e(120);
+	if (access("rw_", R_OK) != 0) e(121);
+	if (access("rw_", W_OK) != 0) e(122);
+	if (access("rw_", R_OK | W_OK) != 0) e(123);
+
+	if (access("r_x", F_OK) != 0) e(124);
+	if (access("r_x", R_OK) != 0) e(125);
+	if (access("r_x", W_OK) != 0) e(126);
+	if (access("r_x", X_OK) != 0) e(127);
+	if (access("r_x", R_OK | W_OK) != 0) e(128);
+	if (access("r_x", R_OK | X_OK) != 0) e(129);
+	if (access("r_x", W_OK | X_OK) != 0) e(130);
+	if (access("r_x", R_OK | W_OK | X_OK) != 0) e(131);
+
+	if (access("r__", F_OK) != 0) e(132);
+	if (access("r__", R_OK) != 0) e(133);
+	if (access("r__", W_OK) != 0) e(134);
+	if (access("r__", R_OK | W_OK) != 0) e(135);
+
+	if (access("_wx", F_OK) != 0) e(136);
+	if (access("_wx", R_OK) != 0) e(137);
+	if (access("_wx", W_OK) != 0) e(138);
+	if (access("_wx", X_OK) != 0) e(139);
+	if (access("_wx", R_OK | W_OK) != 0) e(140);
+	if (access("_wx", R_OK | X_OK) != 0) e(141);
+	if (access("_wx", W_OK | X_OK) != 0) e(142);
+	if (access("_wx", R_OK | W_OK | X_OK) != 0) e(143);
+
+	if (access("_w_", F_OK) != 0) e(144);
+	if (access("_w_", R_OK) != 0) e(145);
+	if (access("_w_", W_OK) != 0) e(146);
+	if (access("_w_", R_OK | W_OK) != 0) e(147);
+
+	if (access("__x", F_OK) != 0) e(148);
+	if (access("__x", R_OK) != 0) e(149);
+	if (access("__x", W_OK) != 0) e(150);
+	if (access("__x", X_OK) != 0) e(151);
+	if (access("__x", R_OK | W_OK) != 0) e(152);
+	if (access("__x", R_OK | X_OK) != 0) e(153);
+	if (access("__x", W_OK | X_OK) != 0) e(154);
+	if (access("__x", R_OK | W_OK | X_OK) != 0) e(155);
+
+	if (access("___", F_OK) != 0) e(156);
+	if (access("___", R_OK) != 0) e(157);
+	if (access("___", W_OK) != 0) e(158);
+	if (access("___", R_OK | W_OK) != 0) e(159);
+  }
+}
+
+void makelongnames()
+{
+  register int i;
+
+  memset(MaxName, 'a', NAME_MAX);
+  MaxName[NAME_MAX] = '\0';
+  for (i = 0; i < PATH_MAX - 1; i++) {	/* idem path */
+	MaxPath[i++] = '.';
+	MaxPath[i] = '/';
+  }
+  MaxPath[PATH_MAX - 1] = '\0';
+
+  strcpy(ToLongName, MaxName);	/* copy them Max to ToLong */
+  strcpy(ToLongPath, MaxPath);
+
+  ToLongName[NAME_MAX] = 'a';
+  ToLongName[NAME_MAX + 1] = '\0';	/* extend ToLongName by one too many */
+  ToLongPath[PATH_MAX - 1] = '/';
+  ToLongPath[PATH_MAX] = '\0';	/* inc ToLongPath by one */
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  System("rm -rf DIR_33");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test34.c
===================================================================
--- /trunk/minix/test/test34.c	(revision 9)
+++ /trunk/minix/test/test34.c	(revision 9)
@@ -0,0 +1,668 @@
+/* test34: chmod() chown() 	Author: Jan-Mark Wams (jms@cs.vu.nl) */
+
+/* There is a problem getting valid uids and gids, so we use the passwd
+** file (ie. /etc/passwd). I don't like this, but I see no other way.
+** The read-only-device-error (EROFS) is not checked!
+** Supplementary group IDs are ignored.
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <stdio.h>
+
+#define MAX_ERROR	4
+#define ITERATIONS      4
+#define N 100
+
+#define ALL_RWXB	(S_IRWXU | S_IRWXG | S_IRWXO)
+#define ALL_SETB	(S_ISUID | S_ISGID)
+#define ALL_BITS	(ALL_RWXB | ALL_SETB)
+
+#define System(cmd)   if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)    if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+#define Stat(a,b)     if (stat(a,b) != 0) printf("Can't stat %s\n", a)
+#define Mkfifo(f)     if (mkfifo(f,0777)!=0) printf("Can't make fifo %s\n", f)
+#define Mkdir(f)      if (mkdir(f,0777)!=0) printf("Can't make dir %s\n", f)
+#define Creat(f)      if (close(creat(f,0777))!=0) printf("Can't creat %s\n",f)
+
+/* This program uses /etc/passwd and assumes things about it's contents. */
+#define PASSWD_FILE	"/etc/passwd"
+
+int errct = 0;
+int subtest = 1;
+int superuser;
+int I_can_chown;
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];		/* Same for path */
+char NameTooLong[NAME_MAX + 2];	/* Name of maximum +1 length */
+char PathTooLong[PATH_MAX + 1];	/* Same for path, both too long */
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test34a, (void));
+_PROTOTYPE(void test34b, (void));
+_PROTOTYPE(void test34c, (void));
+_PROTOTYPE(mode_t mode, (char *file_name));
+_PROTOTYPE(void makelongnames, (void));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+_PROTOTYPE(void getids, (uid_t * uid, gid_t * gid));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 34 ");
+  fflush(stdout);
+  (void) system("chmod 777 DIR_34/* > /dev/null 2> /dev/null");
+  System("rm -rf DIR_34; mkdir DIR_34");
+  if (chdir("DIR_34") != 0) {
+	fprintf(stderr, "Can't go to DIR_34\n");
+	system("rm -rf DIR_34");
+	exit(1);
+  }
+  makelongnames();
+  superuser = (geteuid() == (uid_t) 0);
+
+#ifdef _POSIX_CHOWN_RESTRICTED
+  I_can_chown = superuser;
+#else
+  I_can_chown = 1;
+#endif
+
+  umask(0000);
+
+  for (i = 1; i < ITERATIONS; i++) {
+	if (m & 0001) test34a();
+	if (m & 0002) test34b();
+	if (m & 0004) test34c();
+  }
+  quit();
+}
+
+void test34a()
+{				/* Test normal operation. */
+  time_t time1, time2;
+  mode_t mod;
+  struct stat st1, st2;
+  int cnt;
+  uid_t uid, uid2;
+  gid_t gid, gid2;
+  int stat_loc;
+
+  subtest = 1;
+
+  /* Make scratch file. */
+  Creat("foo");
+
+  for (mod = 0; mod <= ALL_BITS; mod++) {
+	if ((mod & ALL_BITS) != mod)	/* If not a valid mod next. */
+		continue;
+	Stat("foo", &st1);
+	if (time(&time1) == (time_t) - 1) e(1);
+	if (chmod("foo", mod) != 0) e(2);
+	Stat("foo", &st2);
+	if (time(&time2) == (time_t) - 1) e(3);
+	if (superuser)
+		if ((st2.st_mode & ALL_BITS) != mod) e(4);
+	if (!superuser)
+		if ((st2.st_mode & ALL_RWXB) != (mod & ALL_RWXB)) e(5);
+
+	/* Test the C time feald. */
+	if (st1.st_ctime > st2.st_ctime) e(6);
+	if (st1.st_ctime > time1) e(7);
+	if (st1.st_ctime > time2) e(8);
+#ifndef V1_FILESYSTEM
+	if (st2.st_ctime < time1) e(9);
+#endif
+	if (st2.st_ctime > time2) e(10);
+	if (st1.st_atime != st2.st_atime) e(11);
+	if (st1.st_mtime != st2.st_mtime) e(12);
+  }				/* End for loop. */
+
+  /* Check if chown(file, geteuid(), getegid()) works. */
+  for (cnt = 0; cnt < 20; cnt++) {
+	/* Set all rights on foo, including the set .id bits. */
+	if (chmod("foo", ALL_BITS) != 0) e(13);
+	Stat("foo", &st1);
+	if (time(&time1) == (time_t) -1) e(14);
+
+	if (chown("foo", geteuid(), getegid()) != 0) e(15);
+	Stat("foo", &st2);
+	if (time(&time2) == (time_t) -1) e(16);
+
+	/* Check ``chown()'' killed the set .id bits. */
+	if (!superuser) {
+		if ((st1.st_mode & ALL_RWXB) != ALL_RWXB) e(17);
+		if ((st2.st_mode & ALL_BITS) != ALL_RWXB) e(18);
+	}
+	if (superuser) {
+		if ((st1.st_mode & ALL_BITS) != ALL_BITS) e(19);
+		if ((st1.st_mode & ALL_RWXB) != ALL_RWXB) e(20);
+	}
+
+	/* Check the timing. */
+	if (st1.st_ctime > st2.st_ctime) e(21);
+	if (st1.st_ctime > time1) e(22);
+	if (st1.st_ctime > time2) e(23);
+#ifndef V1_FILESYSTEM
+	if (st2.st_ctime < time1) e(24);
+#endif
+	if (st2.st_ctime > time2) e(25);
+	if (st1.st_atime != st2.st_atime) e(26);
+	if (st1.st_mtime != st2.st_mtime) e(27);
+  }				/* End for loop. */
+
+  /* Make scratch file. */
+  if (chmod("foo", ALL_RWXB) != 0) e(28);
+
+  if (I_can_chown) {
+	/* Do a 20 tests on a gid and uid. */
+	for (cnt = 0; cnt < 20; cnt++) {
+		/* Get a uid and a gid, test chown. */
+		getids(&uid, &gid);
+		Stat("foo", &st1);
+		if (time(&time1) == (time_t) -1) e(29);
+		if (chown("foo", (uid_t) 0, (gid_t) 0) != 0) e(30);
+		Stat("foo", &st2);
+		if (time(&time2) == (time_t) -1) e(31);
+
+		/* Test the C time field. */
+		if (st1.st_ctime > st2.st_ctime) e(32);
+		if (st1.st_ctime > time1) e(33);
+		if (st1.st_ctime > time2) e(34);
+		if (st2.st_ctime < time1) e(35);
+		if (st2.st_ctime > time2) e(36);
+		if (st1.st_atime != st2.st_atime) e(37);
+		if (st1.st_mtime != st2.st_mtime) e(38);
+
+		/* Do aditional tests. */
+		if (chown("foo", (uid_t) 0, gid) != 0) e(39);
+		if (chown("foo", uid, (gid_t) 0) != 0) e(40);
+		if (chown("foo", uid, gid) != 0) e(41);
+	}
+  }
+  if (superuser) {
+	/* Check if a non-superuser can change a files gid to gid2 *
+	 * if gid2 is the current process gid. */
+	for (cnt = 0; cnt < 5; cnt++) {
+		switch (fork()) {
+		    case -1:
+			printf("Can't fork\n");
+			break;
+		    case 0:
+			alarm(20);
+
+			getids(&uid, &gid);
+			if (uid == 0) {
+				getids(&uid, &gid);
+				if (uid == 0) e(42);
+			}
+			getids(&uid2, &gid2);
+			if (gid == gid2) e(43);
+
+			/* Creat boo and bar for user uid of group gid. */
+			Creat("boo");
+			if (chown("boo", uid, gid) != 0) e(44);
+			if (chmod("boo", ALL_BITS) != 0) e(45);
+			Creat("bar");
+			if (chown("bar", uid, gid) != 0) e(46);
+			if (chmod("bar", ALL_BITS) != 0) e(47);
+
+			/* We now become user uid of group gid2. */
+			setgid(gid2);
+			setuid(uid);
+
+			Stat("bar", &st1);
+			if (time(&time1) == (time_t) -1) e(48);
+			if (chown("bar", uid, gid2) != 0) e(49);
+			Stat("bar", &st2);
+			if (time(&time2) == (time_t) -1) e(50);
+
+			/* Check if the SET_BITS are cleared. */
+			if ((st1.st_mode & ALL_BITS) != ALL_BITS) e(51);
+			if ((st2.st_mode & ALL_BITS) != ALL_RWXB) e(52);
+
+			/* Check the st_times. */
+			if (st1.st_ctime > st2.st_ctime) e(53);
+			if (st1.st_ctime > time1) e(54);
+			if (st1.st_ctime > time2) e(55);
+			if (st2.st_ctime < time1) e(56);
+			if (st2.st_ctime > time2) e(57);
+			if (st1.st_atime != st2.st_atime) e(58);
+			if (st1.st_mtime != st2.st_mtime) e(59);
+
+			Stat("boo", &st1);
+			if (chmod("boo", ALL_BITS) != 0) e(60);
+			Stat("boo", &st2);
+
+			/* Check if the set gid bit is cleared. */
+			if ((st1.st_mode & ALL_RWXB) != ALL_RWXB) e(61);
+			if ((st2.st_mode & S_ISGID) != 0) e(62);
+
+			if (chown("boo", uid, gid2) != 0) e(63);
+			Stat("boo", &st1);
+
+			/* Check if the set uid bit is cleared. */
+			if ((st1.st_mode & S_ISUID) != 0) e(64);
+
+			exit(0);
+		    default:
+			wait(&stat_loc);
+			if (stat_loc != 0) e(65);	/* Alarm? */
+		}
+	}			/* end for loop. */
+  }				/* end if (superuser). */
+  if (chmod("foo", ALL_BITS) != 0) e(66);
+  Stat("foo", &st1);
+  if (chown("foo", geteuid(), getegid()) != 0) e(67);
+  Stat("foo", &st2);
+  if ((st1.st_mode & ALL_BITS) != ALL_BITS) e(68);	/* See intro! */
+  if (superuser)
+	if ((st2.st_mode & ALL_RWXB) != ALL_RWXB) e(69);
+  if (!superuser)
+	if ((st2.st_mode & ALL_BITS) != ALL_RWXB) e(70);
+
+  (void) system("chmod 777 ../DIR_34/* > /dev/null 2> /dev/null");
+  System("rm -rf ../DIR_34/*");
+}
+
+void test34b()
+{
+  time_t time1, time2;
+  mode_t mod;
+  struct stat st1, st2;
+
+  subtest = 2;
+
+  /* Test chmod() and chown() on non regular files and on MaxName and
+   * MaxPath. * Funny, but dirs should also have S_IS.ID bits.
+   */
+  Mkfifo("fifo");
+  Mkdir("dir");
+  Creat(MaxName);
+  MaxPath[strlen(MaxPath) - 2] = '/';
+  MaxPath[strlen(MaxPath) - 1] = 'a';	/* make ././.../a */
+  Creat(MaxPath);
+
+  for (mod = 1; mod <= ALL_BITS; mod <<= 1) {
+	if ((mod & ALL_BITS) != mod) continue;	/* bad mod */
+	Stat("dir", &st1);
+	if (time(&time1) == (time_t) -1) e(1);
+	if (chmod("dir", mod) != 0) e(2);
+	Stat("dir", &st2);
+	if (time(&time2) == (time_t) -1) e(3);
+	if (superuser)
+		if ((st2.st_mode & ALL_BITS) != mod) e(4);
+	if (!superuser)
+		if ((st2.st_mode & ALL_RWXB) != (mod & ALL_RWXB)) e(5);
+
+	/* Test the C time field. */
+	if (st1.st_ctime > st2.st_ctime) e(6);
+	if (st1.st_ctime > time1) e(7);
+	if (st1.st_ctime > time2) e(8);
+#ifndef V1_FILESYSTEM
+	if (st2.st_ctime < time1) e(9);
+#endif
+	if (st2.st_ctime > time2) e(10);
+	if (st1.st_atime != st2.st_atime) e(11);
+	if (st1.st_mtime != st2.st_mtime) e(12);
+
+	Stat("fifo", &st1);
+	if (time(&time1) == (time_t) -1) e(13);
+	if (chmod("fifo", mod) != 0) e(14);
+	Stat("fifo", &st2);
+	if (time(&time2) == (time_t) -1) e(15);
+	if (superuser)
+		if ((st2.st_mode & ALL_BITS) != mod) e(16);
+	if (!superuser)
+		if ((st2.st_mode & ALL_RWXB) != (mod & ALL_RWXB)) e(17);
+
+	/* Test the C time field. */
+	if (st1.st_ctime > st2.st_ctime) e(18);
+	if (st1.st_ctime > time1) e(19);
+	if (st1.st_ctime > time2) e(20);
+#ifndef V1_FILESYSTEM
+	if (st2.st_ctime < time1) e(21);
+#endif
+	if (st2.st_ctime > time2) e(22);
+	if (st1.st_atime != st2.st_atime) e(23);
+	if (st1.st_mtime != st2.st_mtime) e(24);
+
+	Stat(MaxName, &st1);
+	if (time(&time1) == (time_t) -1) e(25);
+	if (chmod(MaxName, mod) != 0) e(26);
+	Stat(MaxName, &st2);
+	if (time(&time2) == (time_t) -1) e(27);
+	if (superuser)
+		if ((st2.st_mode & ALL_BITS) != mod) e(28);
+	if (!superuser)
+		if ((st2.st_mode & ALL_RWXB) != (mod & ALL_RWXB)) e(29);
+
+	/* Test the C time field. */
+	if (st1.st_ctime > st2.st_ctime) e(30);
+	if (st1.st_ctime > time1) e(31);
+	if (st1.st_ctime > time2) e(32);
+#ifndef V1_FILESYSTEM
+	if (st2.st_ctime < time1) e(33);
+#endif
+	if (st2.st_ctime > time2) e(34);
+	if (st1.st_atime != st2.st_atime) e(35);
+	if (st1.st_mtime != st2.st_mtime) e(36);
+
+	Stat(MaxPath, &st1);
+	if (time(&time1) == (time_t) -1) e(37);
+	if (chmod(MaxPath, mod) != 0) e(38);
+	Stat(MaxPath, &st2);
+	if (time(&time2) == (time_t) -1) e(39);
+	if (superuser)
+		if ((st2.st_mode & ALL_BITS) != mod) e(40);
+	if (!superuser)
+		if ((st2.st_mode & ALL_RWXB) != (mod & ALL_RWXB)) e(41);
+
+	/* Test the C time field. */
+	if (st1.st_ctime > st2.st_ctime) e(42);
+	if (st1.st_ctime > time1) e(43);
+	if (st1.st_ctime > time2) e(44);
+#ifndef V1_FILESYSTEM
+	if (st2.st_ctime < time1) e(45);
+#endif
+	if (st2.st_ctime > time2) e(46);
+	if (st1.st_atime != st2.st_atime) e(47);
+	if (st1.st_mtime != st2.st_mtime) e(48);
+  }
+
+  if (chmod("dir", 0777) != 0) e(49);
+  if (chmod("fifo", 0777) != 0) e(50);
+  if (chmod(MaxName, 0777) != 0) e(51);
+  if (chmod(MaxPath, 0777) != 0) e(52);
+
+  (void) system("chmod 777 ../DIR_34/* > /dev/null 2> /dev/null");
+  System("rm -rf ../DIR_34/*");
+}
+
+void test34c()
+{
+  struct stat st;
+  uid_t uid, uid2;
+  gid_t gid, gid2;
+  int stat_loc;
+
+  subtest = 3;
+
+  Mkdir("dir");
+  Creat("dir/try_me");
+
+  /* Disalow search permission and see if chmod() and chown() return
+   * EACCES. 
+   */
+  if (chmod("dir", ALL_BITS & ~S_IXUSR) != 0) e(1);
+  if (!superuser) {
+	if (chmod("dir/try_me", 0) != -1) e(2);
+	if (errno != EACCES) e(3);
+	if (I_can_chown) {
+		if (chown("dir/try_me", geteuid(), getegid()) != -1) e(4);
+		if (errno != EACCES) e(5);
+	}
+  }
+
+  /* Check ENOTDIR. */
+  Mkfifo("fifo");
+  if (chmod("fifo/try_me", 0) != -1) e(6);
+  if (errno != ENOTDIR) e(7);
+  if (chown("fifo/try_me", geteuid(), getegid()) != -1) e(8);
+  if (errno != ENOTDIR) e(9);
+
+  Creat("file");
+  if (chmod("file/try_me", 0) != -1) e(10);
+  if (errno != ENOTDIR) e(11);
+  if (chown("file/try_me", geteuid(), getegid()) != -1) e(12);
+  if (errno != ENOTDIR) e(13);
+
+  /* Check empty path. */
+  if (chmod("", 0) != -1) e(14);
+  if (errno != ENOENT) e(15);
+  if (chown("", geteuid(), getegid()) != -1) e(16);
+  if (errno != ENOENT) e(17);
+
+  /* Check non existing file name. */
+  if (chmod("non_exist", 0) != -1) e(18);
+  if (errno != ENOENT) e(19);
+  if (chown("non_exist", geteuid(), getegid()) != -1) e(20);
+  if (errno != ENOENT) e(21);
+
+  /* Check what we get if we do not have permisson. */
+  if (!superuser) {
+	Stat("/", &st);
+	if (st.st_uid == geteuid()) e(22);
+
+	/* First I had 0, I changed it to st.st_mode 8-). */
+	if (chmod("/", st.st_mode) != -1) e(23);
+	if (errno != EPERM) e(24);
+  }
+  if (!I_can_chown) {
+	Stat("/", &st);
+	if (st.st_uid == geteuid()) e(25);
+	if (chown("/", geteuid(), getegid()) != -1) e(26);
+	if (errno != EPERM) e(27);
+  }
+
+  /* If we are superuser, we can test all id combinations. */
+  if (superuser) {
+	switch (fork()) {
+	    case -1:	printf("Can't fork\n");	break;
+	    case 0:
+		alarm(20);
+
+		getids(&uid, &gid);
+		if (uid == 0) {
+			getids(&uid, &gid);
+			if (uid == 0) e(28);
+		}
+		getids(&uid2, &gid2);
+		if (gid == gid2) e(29);
+		if (uid == uid2) e(30);
+
+		/* Creat boo, owned by root. */
+		Creat("boo");
+		if (chmod("boo", ALL_BITS) != 0) e(31);
+
+		/* Creat boo for user uid2 of group gid2. */
+		Creat("bar");
+		if (chown("bar", uid2, gid2) != 0) e(32);
+		if (chmod("bar", ALL_BITS) != 0) e(33);
+
+		/* Creat my_gid for user uid2 of group gid. */
+		Creat("my_gid");
+		if (chown("my_gid", uid2, gid) != 0) e(34);
+		if (chmod("my_gid", ALL_BITS) != 0) e(35);
+
+		/* Creat my_uid for user uid of uid gid. */
+		Creat("my_uid");
+		if (chown("my_uid", uid, gid) != 0) e(36);
+		if (chmod("my_uid", ALL_BITS) != 0) e(37);
+
+		/* We now become user uid of uid gid. */
+		setgid(gid);
+		setuid(uid);
+
+		if (chown("boo", uid, gid) != -1) e(38);
+		if (errno != EPERM) e(39);
+		if (chown("bar", uid, gid) != -1) e(40);
+		if (errno != EPERM) e(41);
+		if (chown("my_gid", uid, gid) != -1) e(42);
+		if (errno != EPERM) e(43);
+		if (chown("my_uid", uid, gid2) != -1) e(44);
+
+		/* The EPERM is not strict POSIX. */
+		if (errno != EPERM) e(45);
+
+		if (chmod("boo", 0) != -1) e(46);
+		if (errno != EPERM) e(47);
+		if (chmod("bar", 0) != -1) e(48);
+		if (errno != EPERM) e(49);
+		if (chmod("my_gid", 0) != -1) e(50);
+		if (errno != EPERM) e(51);
+
+		exit(0);
+	    default:
+		wait(&stat_loc);
+		if (stat_loc != 0) e(52);	/* Alarm? */
+	}
+  }
+
+  /* Check too long path ed. */
+  Creat(NameTooLong);
+  if (chmod(NameTooLong, 0777) != 0) e(57);
+  if (chown(NameTooLong, geteuid(), getegid()) != 0) e(58);
+
+  /* Make PathTooLong contain ././.../a */
+  PathTooLong[strlen(PathTooLong) - 2] = '/';
+  PathTooLong[strlen(PathTooLong) - 1] = 'a';
+  Creat("a");
+  if (chmod(PathTooLong, 0777) != -1) e(59);
+  if (errno != ENAMETOOLONG) e(60);
+  if (chown(PathTooLong, geteuid(), getegid()) != -1) e(61);
+  if (errno != ENAMETOOLONG) e(62);
+
+  (void) system("chmod 777 ../DIR_34/* > /dev/null 2> /dev/null");
+  System("rm -rf ../DIR_34/*");
+}
+
+void makelongnames()
+{
+  register int i;
+
+  memset(MaxName, 'a', NAME_MAX);
+  MaxName[NAME_MAX] = '\0';
+  for (i = 0; i < PATH_MAX - 1; i++) {	/* idem path */
+	MaxPath[i++] = '.';
+	MaxPath[i] = '/';
+  }
+  MaxPath[PATH_MAX - 1] = '\0';
+
+  strcpy(NameTooLong, MaxName);	/* copy them Max to TooLong */
+  strcpy(PathTooLong, MaxPath);
+
+  NameTooLong[NAME_MAX] = 'a';
+  NameTooLong[NAME_MAX + 1] = '\0';	/* extend NameTooLong by one too many*/
+  PathTooLong[PATH_MAX - 1] = '/';
+  PathTooLong[PATH_MAX] = '\0';	/* inc PathTooLong by one */
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	system("rm -rf DIR_34");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  (void) system("chmod 777 DIR_34/* > /dev/null 2> /dev/null");
+  System("rm -rf DIR_34");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
+
+/* Getids returns a valid uid and gid. Is used PASSWD FILE.
+ * It assumes the following format for a passwd file line:
+ * <user_name>:<passwd>:<uid>:<gid>:<other_stuff>
+ * If no uids and gids can be found, it will only return 0 ids.
+ */
+void getids(r_uid, r_gid)
+uid_t * r_uid;
+gid_t * r_gid;
+{
+  char line[N];
+  char *p;
+  uid_t uid;
+  gid_t gid;
+  FILE *fp;
+  int i;
+
+  static uid_t a_uid[N];	/* Array for uids. */
+  static gid_t a_gid[N];	/* Array for gids. */
+  static int nuid = 0, ngid = 0;/* The number of user & group ids. */
+  static int cuid = 0, cgid = 0;/* The current id index. */
+
+  /* If we don't have any uids go read some from the passwd file. */
+  if (nuid == 0) {
+	a_uid[nuid++] = 0;	/* Root uid and gid. */
+	a_gid[ngid++] = 0;
+	if ((fp = fopen(PASSWD_FILE, "r")) == NULL) {
+		printf("Can't open ");
+		perror(PASSWD_FILE);
+	}
+	while (fp != NULL && fgets(line, sizeof(line), fp) != NULL) {
+		p = strchr(line, ':');
+		if (p != NULL) p = strchr(p + 1, ':');
+		if (p != NULL) {
+			p++;
+			uid = 0;
+			while (isdigit(*p)) {
+				uid *= 10;
+				uid += (uid_t) (*p - '0');
+				p++;
+			}
+			if (*p != ':') continue;
+			p++;
+			gid = 0;
+			while (isdigit(*p)) {
+				gid *= 10;
+				gid += (gid_t) (*p - '0');
+				p++;
+			}
+			if (*p != ':') continue;
+			if (nuid < N) {
+				for (i = 0; i < nuid; i++)
+					if (a_uid[i] == uid) break;
+				if (i == nuid) a_uid[nuid++] = uid;
+			}
+			if (ngid < N) {
+				for (i = 0; i < ngid; i++)
+					if (a_gid[i] == gid) break;
+				if (i == ngid) a_gid[ngid++] = gid;
+			}
+			if (nuid >= N && ngid >= N) break;
+		}
+	}
+	if (fp != NULL) fclose(fp);
+  }
+
+  /* We now have uids and gids in a_uid and a_gid. */
+  if (cuid >= nuid) cuid = 0;
+  if (cgid >= ngid) cgid = 0;
+  *r_uid = a_uid[cuid++];
+  *r_gid = a_gid[cgid++];
+}
Index: /trunk/minix/test/test35.c
===================================================================
--- /trunk/minix/test/test35.c	(revision 9)
+++ /trunk/minix/test/test35.c	(revision 9)
@@ -0,0 +1,414 @@
+/* test35: utime()		Author: Jan-Mark Wams (jms@cs.vu.nl) */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <utime.h>
+#include <errno.h>
+#include <time.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#define MAX_ERROR	1
+#define ITERATIONS     10
+#define N 100
+
+#define System(cmd)   if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)    if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+#define Stat(a,b)     if (stat(a,b) != 0) printf("Can't stat %s\n", a)
+#define Mkfifo(f)     if (mkfifo(f,0777)!=0) printf("Can't make fifo %s\n", f)
+#define Mkdir(f)      if (mkdir(f,0777)!=0) printf("Can't make dir %s\n", f)
+#define Creat(f)      if (close(creat(f,0777))!=0) printf("Can't creat %s\n",f)
+#define Time(t)	      if (time(t) == (time_t)-1) printf("Time error\n")
+#define Chown(f,u,g)  if (chown(f,u,g) != 0) printf("Can't chown %s\n", f)
+#define Chmod(f,m)    if (chmod(f,m) != 0) printf("Can't chmod %s\n", f)
+
+#define PASSWD_FILE 	"/etc/passwd"
+
+int errct = 0;
+int subtest = 1;
+int I_can_chown;
+int superuser;
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];		/* Same for path */
+char NameTooLong[NAME_MAX + 2];	/* Name of maximum +1 length */
+char PathTooLong[PATH_MAX + 1];	/* Same for path, both too long */
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test35a, (void));
+_PROTOTYPE(void test35b, (void));
+_PROTOTYPE(void test35c, (void));
+_PROTOTYPE(void makelongnames, (void));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+_PROTOTYPE(void getids, (uid_t * uid, gid_t * gid));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 35 ");
+  fflush(stdout);
+  System("rm -rf DIR_35; mkdir DIR_35");
+  Chdir("DIR_35");
+  makelongnames();
+  superuser = (geteuid() == 0);
+
+#ifdef _POSIX_CHOWN_RESTRICTED
+# if _POSIX_CHOWN_RESTRICTED - 0 != -1
+  I_can_chown = superuser;
+# else
+  I_can_chown = 1;
+# endif
+#else
+# include "error, this case requires dynamic checks and is not handled"
+#endif
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test35a();
+	if (m & 0002) test35b();
+	if (m & 0004) test35c();
+  }
+  quit();
+}
+
+void test35a()
+{				/* Test normal operation. */
+  struct stat st;
+  struct utimbuf ub;
+  time_t time1, time2;
+  int cnt;
+
+  subtest = 1;
+
+  /* Creat scratch file. */
+  Creat("foo");
+
+  /* Set file times back two seconds. */
+  Stat("foo", &st);
+  ub.actime = st.st_atime - 2;
+  ub.modtime = st.st_mtime - 2;
+  Time(&time1);
+  utime("foo", &ub);
+  Time(&time2);
+  Stat("foo", &st);
+  if (ub.actime != st.st_atime) e(1);
+  if (ub.modtime != st.st_mtime) e(2);
+
+  /* The status changed time sould be changed. */
+#ifndef V1_FILESYSTEM
+  if (st.st_ctime < time1) e(3);
+#endif
+  if (st.st_ctime > time2) e(4);
+
+  /* Add twenty seconds. */
+  Stat("foo", &st);
+  ub.actime = st.st_atime + 20;
+  ub.modtime = st.st_mtime + 20;
+  Time(&time1);
+  utime("foo", &ub);
+  Time(&time2);
+  Stat("foo", &st);
+  if (ub.actime != st.st_atime) e(5);
+  if (ub.modtime != st.st_mtime) e(6);
+  if (st.st_ctime < time1) e(7);
+#ifndef V1_FILESYSTEM
+  if (st.st_ctime > time2) e(8);
+#endif
+
+  /* Try 100 times to do utime in less than one second. */
+  cnt = 0;
+  do {
+	Time(&time1);
+	utime("foo", (struct utimbuf *) NULL);
+	Time(&time2);
+  } while (time1 != time2 && cnt++ < 100);
+  if (time1 == time2) {
+	Stat("foo", &st);
+	Time(&time2);
+	if (st.st_atime != time1) e(9);
+	if (st.st_mtime != time1) e(10);
+  } else {
+	Stat("foo", &st);
+	if (st.st_atime > time2) e(11);
+	if (st.st_mtime > time2) e(12);
+	Time(&time2);
+	if (st.st_atime < time1) e(13);
+	if (st.st_mtime < time1) e(14);
+  }
+  if (st.st_ctime < time1) e(15);
+  if (st.st_ctime > time2) e(16);
+
+  System("rm -rf ../DIR_35/*");
+}
+
+void test35b()
+{
+  subtest = 2;
+
+  /* MaxPath and MaxName checkup. */
+  Creat(MaxName);
+  MaxPath[strlen(MaxPath) - 2] = '/';
+  MaxPath[strlen(MaxPath) - 1] = 'a';	/* make ././.../a */
+  Creat(MaxPath);
+  if (utime(MaxName, NULL) != 0) e(1);
+  if (utime(MaxPath, NULL) != 0) e(2);
+
+  /* The owner doesn't need write permisson to set  times. */
+  Creat("foo");
+  if (chmod("foo", 0) != 0) e(3);
+  if (utime("foo", NULL) != 0) e(4);
+  if (chmod("foo", 0777) != 0) e(5);
+  if (utime("foo", NULL) != 0) e(6);
+
+  System("rm -rf ../DIR_35/*");
+}
+
+void test35c()
+{
+  gid_t gid, gid2;
+  uid_t uid, uid2;
+  struct utimbuf ub;
+  int stat_loc;
+
+  subtest = 3;
+
+  /* Access problems. */
+  Mkdir("bar");
+  Creat("bar/tryme");
+  if (superuser) {
+	Chmod("bar", 0000);	/* No search permisson at all. */
+	if (utime("bar/tryme", NULL) != 0) e(1);
+  }
+  if (!superuser) {
+	Chmod("bar", 0677);	/* No search permisson. */
+	if (utime("bar/tryme", NULL) != -1) e(2);
+	if (errno != EACCES) e(3);
+  }
+  Chmod("bar", 0777);
+
+  if (I_can_chown) {
+	switch (fork()) {
+	    case -1:	printf("Can't fork\n");	break;
+	    case 0:
+		alarm(20);
+
+		/* Get two differend non root uids. */
+		if (superuser) {
+			getids(&uid, &gid);
+			if (uid == 0) getids(&uid, &gid);
+			if (uid == 0) e(4);
+		}
+		if (!superuser) {
+			uid = geteuid();
+			gid = getegid();
+		}
+		getids(&uid2, &gid);
+		if (uid == uid2) getids(&uid2, &gid2);
+		if (uid == uid2) e(5);
+
+		/* Creat a number of files for root, user and user2. */
+		Creat("rootfile");	/* Owned by root. */
+		Chmod("rootfile", 0600);
+		Chown("rootfile", 0, 0);
+		Creat("user2file");	/* Owned by user 2, writeable. */
+		Chmod("user2file", 0020);
+		Chown("user2file", uid2, gid);
+		Creat("user2private");	/* Owned by user 2, privately. */
+		Chmod("user2private", 0600);
+		Chown("user2private", uid2, gid);
+
+		if (superuser) {
+			setgid(gid);
+			setuid(uid);
+		}
+
+		/* We now are user ``uid'' from group ``gid''. */
+		ub.actime = (time_t) 12345L;
+		ub.modtime = (time_t) 12345L;
+
+		if (utime("rootfile", NULL) != -1) e(6);
+		if (errno != EACCES) e(7);
+		if (utime("rootfile", &ub) != -1) e(8);
+		if (errno != EPERM) e(9);
+
+		if (utime("user2file", NULL) != 0) e(10);
+		if (utime("user2file", &ub) != -1) e(11);
+		if (errno != EPERM) e(12);
+
+		if (utime("user2private", NULL) != -1) e(13);
+		if (errno != EACCES) e(14);
+		if (utime("user2private", &ub) != -1) e(15);
+		if (errno != EPERM) e(16);
+
+		exit(errct ? 1 : 0);
+	    default:
+		wait(&stat_loc);
+		if (stat_loc != 0) e(17);	/* Alarm? */
+	}
+  }
+
+  /* Test names that are too long. */
+#ifdef _POSIX_NO_TRUNC
+# if _POSIX_NO_TRUNC - 0 != -1
+  /* Not exist might also be a propper response? */
+  if (utime(NameTooLong, NULL) != -1) e(18);
+  if (errno != ENAMETOOLONG) e(19);
+# else
+  Creat(NameTooLong);
+  if (utime(NameTooLong, NULL) != 0) e(20);
+# endif
+#else
+# include "error, this case requires dynamic checks and is not handled"
+#endif
+
+  /* Make PathTooLong contain ././.../a */
+  PathTooLong[strlen(PathTooLong) - 2] = '/';
+  PathTooLong[strlen(PathTooLong) - 1] = 'a';
+  Creat("a");
+  if (utime(PathTooLong, NULL) != -1) e(21);
+  if (errno != ENAMETOOLONG) e(22);
+
+  /* Non existing file name. */
+  if (utime("nonexist", NULL) != -1) e(23);
+  if (errno != ENOENT) e(24);
+
+  /* Empty file name. */
+  if (utime("", NULL) != -1) e(25);
+  if (errno != ENOENT) e(26);
+
+  System("rm -rf ../DIR_35/*");
+}
+
+void makelongnames()
+{
+  register int i;
+
+  memset(MaxName, 'a', NAME_MAX);
+  MaxName[NAME_MAX] = '\0';
+  for (i = 0; i < PATH_MAX - 1; i++) {	/* idem path */
+	MaxPath[i++] = '.';
+	MaxPath[i] = '/';
+  }
+  MaxPath[PATH_MAX - 1] = '\0';
+
+  strcpy(NameTooLong, MaxName);	/* copy them Max to TooLong */
+  strcpy(PathTooLong, MaxPath);
+
+  NameTooLong[NAME_MAX] = 'a';
+  NameTooLong[NAME_MAX + 1] = '\0';	/* extend NameTooLong by one too many*/
+  PathTooLong[PATH_MAX - 1] = '/';
+  PathTooLong[PATH_MAX] = '\0';	/* inc PathTooLong by one */
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR* > /dev/null 2>/dev/null");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  System("rm -rf DIR_35");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
+
+/* Getids returns a valid uid and gid. Is used PASSWD FILE.
+** It assumes the following format for a passwd file line:
+** <user_name>:<passwd>:<uid>:<gid>:<other_stuff>
+** If no uids and gids can be found, it will only return 0 ids.
+*/
+void getids(r_uid, r_gid)
+uid_t *r_uid;
+gid_t *r_gid;
+{
+  char line[N];
+  char *p;
+  uid_t uid;
+  gid_t gid;
+  FILE *fp;
+  int i;
+
+  static uid_t a_uid[N];	/* Array for uids. */
+  static gid_t a_gid[N];	/* Array for gids. */
+  static int nuid = 0, ngid = 0;/* The number of user & group ids. */
+  static int cuid = 0, cgid = 0;/* The current id index. */
+
+  /* If we don't have any uids go read some from the passwd file. */
+  if (nuid == 0) {
+	a_uid[nuid++] = 0;	/* Root uid and gid. */
+	a_gid[ngid++] = 0;
+	if ((fp = fopen(PASSWD_FILE, "r")) == NULL) {
+		printf("Can't open ");
+		perror(PASSWD_FILE);
+	}
+	while (fp != NULL && fgets(line, sizeof(line), fp) != NULL) {
+		p = strchr(line, ':');
+		if (p != NULL) p = strchr(p + 1, ':');
+		if (p != NULL) {
+			p++;
+			uid = 0;
+			while (isdigit(*p)) {
+				uid *= 10;
+				uid += (uid_t) (*p - '0');
+				p++;
+			}
+			if (*p != ':') continue;
+			p++;
+			gid = 0;
+			while (isdigit(*p)) {
+				gid *= 10;
+				gid += (gid_t) (*p - '0');
+				p++;
+			}
+			if (*p != ':') continue;
+			if (nuid < N) {
+				for (i = 0; i < nuid; i++)
+					if (a_uid[i] == uid) break;
+				if (i == nuid) a_uid[nuid++] = uid;
+			}
+			if (ngid < N) {
+				for (i = 0; i < ngid; i++)
+					if (a_gid[i] == gid) break;
+				if (i == ngid) a_gid[ngid++] = gid;
+			}
+			if (nuid >= N && ngid >= N) break;
+		}
+	}
+	if (fp != NULL) fclose(fp);
+  }
+
+  /* We now have uids and gids in a_uid and a_gid. */
+  if (cuid >= nuid) cuid = 0;
+  if (cgid >= ngid) cgid = 0;
+  *r_uid = a_uid[cuid++];
+  *r_gid = a_gid[cgid++];
+}
Index: /trunk/minix/test/test36.c
===================================================================
--- /trunk/minix/test/test36.c	(revision 9)
+++ /trunk/minix/test/test36.c	(revision 9)
@@ -0,0 +1,244 @@
+/* test36: pathconf() fpathconf()	Author: Jan-mark Wams */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+
+#define MAX_ERROR	4
+#define ITERATIONS     10
+
+#define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+#define Stat(a,b)	if (stat(a,b) != 0) printf("Can't stat %s\n", a)
+
+int errct = 0;
+int subtest = 1;
+int superuser;
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];		/* Same for path */
+char ToLongName[NAME_MAX + 2];	/* Name of maximum +1 length */
+char ToLongPath[PATH_MAX + 1];	/* Same for path, both too long */
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test36a, (void));
+_PROTOTYPE(void test36b, (void));
+_PROTOTYPE(void test36c, (void));
+_PROTOTYPE(void test36d, (void));
+_PROTOTYPE(void makelongnames, (void));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+_PROTOTYPE(int not_provided_option, (int _option));
+_PROTOTYPE(int provided_option, (int _option, int _minimum_value));
+_PROTOTYPE(int variating_option, (int _option, int _minimum_value));
+
+char *testdirs[] = {
+	    "/",
+	    "/etc",
+	    "/tmp",
+	    "/usr",
+	    "/usr/bin",
+	    ".",
+	    NULL
+};
+
+char *testfiles[] = {
+	     "/",
+	     "/etc",
+	     "/etc/passwd",
+	     "/tmp",
+	     "/dev/tty",
+	     "/usr",
+	     "/usr/bin",
+	     ".",
+	     NULL
+};
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 36 ");
+  fflush(stdout);
+  System("rm -rf DIR_36; mkdir DIR_36");
+  Chdir("DIR_36");
+  makelongnames();
+  superuser = (geteuid() == 0);
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test36a();
+	if (m & 0002) test36b();
+	if (m & 0004) test36c();
+	if (m & 0010) test36d();
+  }
+  quit();
+}
+
+void test36a()
+{				/* Test normal operation. */
+  subtest = 1;
+  System("rm -rf ../DIR_36/*");
+
+#ifdef _POSIX_CHOWN_RESTRICTED
+# if _POSIX_CHOWN_RESTRICTED - 0 == -1
+  if (not_provided_option(_PC_CHOWN_RESTRICTED) != 0) e(1);
+# else
+  if (provided_option(_PC_CHOWN_RESTRICTED, 0) != 0) e(2);
+# endif
+#else
+  if (variating_option(_PC_CHOWN_RESTRICTED, 0) != 0) e(3);
+#endif
+
+#ifdef _POSIX_NO_TRUNC
+# if _POSIX_NO_TRUNC - 0 == -1
+  if (not_provided_option(_PC_NO_TRUNC) != 0) e(4);
+# else
+  if (provided_option(_PC_NO_TRUNC, 0) != 0) e(5);
+# endif
+#else
+  if (variating_option(_PC_NO_TRUNC, 0) != 0) e(6);
+#endif
+
+#ifdef _POSIX_VDISABLE
+# if _POSIX_VDISABLE - 0 == -1
+  if (not_provided_option(_PC_VDISABLE) != 0) e(7);
+# else
+  if (provided_option(_PC_VDISABLE, 0) != 0) e(8);
+# endif
+#else
+  if (variating_option(_PC_VDISABLE, 0) != 0) e(9);
+#endif
+
+}
+
+void test36b()
+{
+  subtest = 2;
+  System("rm -rf ../DIR_36/*");
+}
+
+void test36c()
+{
+  subtest = 3;
+  System("rm -rf ../DIR_36/*");
+}
+
+void test36d()
+{
+  subtest = 4;
+  System("rm -rf ../DIR_36/*");
+}
+
+void makelongnames()
+{
+  register int i;
+
+  memset(MaxName, 'a', NAME_MAX);
+  MaxName[NAME_MAX] = '\0';
+  for (i = 0; i < PATH_MAX - 1; i++) {	/* idem path */
+	MaxPath[i++] = '.';
+	MaxPath[i] = '/';
+  }
+  MaxPath[PATH_MAX - 1] = '\0';
+
+  strcpy(ToLongName, MaxName);	/* copy them Max to ToLong */
+  strcpy(ToLongPath, MaxPath);
+
+  ToLongName[NAME_MAX] = 'a';
+  ToLongName[NAME_MAX + 1] = '\0';	/* extend ToLongName by one too many */
+  ToLongPath[PATH_MAX - 1] = '/';
+  ToLongPath[PATH_MAX] = '\0';	/* inc ToLongPath by one */
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  System("rm -rf DIR_36");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
+
+int not_provided_option(option)
+int option;
+{
+  char **p;
+
+  for (p = testfiles; *p != (char *) NULL; p++) {
+	if (pathconf(*p, option) != -1) return printf("*p == %s\n", *p), 1;
+  }
+  return 0;
+}
+
+int provided_option(option, minimum)
+int option, minimum;
+{
+  char **p;
+
+  /* These three options are only defined on directorys. */
+  if (option == _PC_NO_TRUNC
+      || option == _PC_NAME_MAX
+      || option == _PC_PATH_MAX)
+	p = testdirs;
+  else
+	p = testfiles;
+
+  for (; *p != NULL; p++) {
+	if (pathconf(*p, option) < minimum)
+		return printf("*p == %s\n", *p), 1;
+  }
+  return 0;
+}
+
+int variating_option(option, minimum)
+int option, minimum;
+{
+  char **p;
+
+  /* These three options are only defined on directorys. */
+  if (option == _PC_NO_TRUNC
+      || option == _PC_NAME_MAX
+      || option == _PC_PATH_MAX)
+	p = testdirs;
+  else
+	p = testfiles;
+
+  for (; *p != NULL; p++) {
+	if (pathconf(*p, option) < minimum)
+		return printf("*p == %s\n", *p), 1;
+  }
+  return 0;
+}
Index: /trunk/minix/test/test37.c
===================================================================
--- /trunk/minix/test/test37.c	(revision 9)
+++ /trunk/minix/test/test37.c	(revision 9)
@@ -0,0 +1,1049 @@
+/* test 37 - signals */
+
+#include <sys/types.h>
+#include <sys/times.h>
+#ifdef _MINIX
+#include <sys/sigcontext.h>
+#endif
+#include <sys/wait.h>
+#include <errno.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define ITERATIONS 2
+#define SIGS 14
+#define MAX_ERROR 4
+
+int iteration, cumsig, subtest, errct = 0, sig1, sig2;
+
+int sigarray[SIGS] = {SIGHUP, SIGILL, SIGTRAP, SIGABRT, SIGIOT, 
+	      SIGFPE, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM,
+	      SIGTERM};
+
+/* Prototypes produced automatically by mkptypes. */
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(void test37a, (void));
+_PROTOTYPE(void func1, (int sig));
+_PROTOTYPE(void func2, (int sig));
+_PROTOTYPE(void test37b, (void));
+_PROTOTYPE(void catch1, (int signo));
+_PROTOTYPE(void catch2, (int signo));
+_PROTOTYPE(void test37c, (void));
+_PROTOTYPE(void catch3, (int signo));
+_PROTOTYPE(void test37d, (void));
+_PROTOTYPE(void catch4, (int signo));
+_PROTOTYPE(void test37e, (void));
+_PROTOTYPE(void catch5, (int signo));
+_PROTOTYPE(void test37f, (void));
+_PROTOTYPE(void sigint_handler, (int signo));
+_PROTOTYPE(void sigpipe_handler, (int signo));
+_PROTOTYPE(void test37g, (void));
+_PROTOTYPE(void sighup8, (int signo));
+_PROTOTYPE(void sigpip8, (int signo));
+_PROTOTYPE(void sigter8, (int signo));
+_PROTOTYPE(void test37h, (void));
+_PROTOTYPE(void sighup9, (int signo));
+_PROTOTYPE(void sigter9, (int signo));
+_PROTOTYPE(void test37i, (void));
+_PROTOTYPE(void sighup10, (int signo));
+_PROTOTYPE(void sigalrm_handler10, (int signo));
+_PROTOTYPE(void test37j, (void));
+_PROTOTYPE(void test37k, (void));
+_PROTOTYPE(void test37l, (void));
+_PROTOTYPE(void func_m1, (void));
+_PROTOTYPE(void func_m2, (void));
+_PROTOTYPE(void test37m, (void));
+_PROTOTYPE(void longjerr, (void));
+_PROTOTYPE(void catch14, (int signo, int code, struct sigcontext * scp));
+_PROTOTYPE(void test37n, (void));
+_PROTOTYPE(void catch15, (int signo));
+_PROTOTYPE(void test37o, (void));
+_PROTOTYPE(void clearsigstate, (void));
+_PROTOTYPE(void quit, (void));
+_PROTOTYPE(void wait_for, (int pid));
+_PROTOTYPE(void e, (int n));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+
+  if (argc == 2) m = atoi(argv[1]);
+
+  printf("Test 37 ");
+  fflush(stdout);		/* have to flush for child's benefit */
+
+  system("rm -rf DIR_37; mkdir DIR_37");
+  chdir("DIR_37");
+
+  for (i = 0; i < ITERATIONS; i++) {
+	iteration = i;
+	if (m & 0000001) test37a();
+	if (m & 0000002) test37b();
+	if (m & 0000004) test37c();
+	if (m & 0000010) test37d();
+	if (m & 0000020) test37e();
+	if (m & 0000040) test37f();
+	if (m & 0000100) test37g();
+	if (m & 0000200) test37h();
+	if (m & 0000400) test37i();
+	if (m & 0001000) test37j();
+	if (m & 0002000) test37k();
+	if (m & 0004000) test37l();
+	if (m & 0010000) test37m();
+	if (m & 0020000) test37n();
+	if (m & 0040000) test37o();
+  }
+
+  quit();
+  return(-1);			/* impossible */
+}
+
+void test37a()
+{
+/* Test signal set management. */
+
+  sigset_t s;
+
+  subtest = 1;
+  clearsigstate();
+
+  /* Create an empty set and see if any bits are on. */
+  if (sigemptyset(&s) != 0) e(1);
+  if (sigismember(&s, SIGHUP) != 0) e(2);
+  if (sigismember(&s, SIGINT) != 0) e(3);
+  if (sigismember(&s, SIGQUIT) != 0) e(4);
+  if (sigismember(&s, SIGILL) != 0) e(5);
+  if (sigismember(&s, SIGTRAP) != 0) e(6);
+  if (sigismember(&s, SIGABRT) != 0) e(7);
+  if (sigismember(&s, SIGIOT) != 0) e(8);
+  if (sigismember(&s, SIGFPE) != 0) e(10);
+  if (sigismember(&s, SIGKILL) != 0) e(11);
+  if (sigismember(&s, SIGUSR1) != 0) e(12);
+  if (sigismember(&s, SIGSEGV) != 0) e(13);
+  if (sigismember(&s, SIGUSR2) != 0) e(14);
+  if (sigismember(&s, SIGPIPE) != 0) e(15);
+  if (sigismember(&s, SIGALRM) != 0) e(16);
+  if (sigismember(&s, SIGTERM) != 0) e(17);
+
+  /* Create a full set and see if any bits are off. */
+  if (sigfillset(&s) != 0) e(19);
+  if (sigemptyset(&s) != 0) e(20);
+  if (sigfillset(&s) != 0) e(21);
+  if (sigismember(&s, SIGHUP) != 1) e(22);
+  if (sigismember(&s, SIGINT) != 1) e(23);
+  if (sigismember(&s, SIGQUIT) != 1) e(24);
+  if (sigismember(&s, SIGILL) != 1) e(25);
+  if (sigismember(&s, SIGTRAP) != 1) e(26);
+  if (sigismember(&s, SIGABRT) != 1) e(27);
+  if (sigismember(&s, SIGIOT) != 1) e(28);
+  if (sigismember(&s, SIGFPE) != 1) e(30);
+  if (sigismember(&s, SIGKILL) != 1) e(31);
+  if (sigismember(&s, SIGUSR1) != 1) e(32);
+  if (sigismember(&s, SIGSEGV) != 1) e(33);
+  if (sigismember(&s, SIGUSR2) != 1) e(34);
+  if (sigismember(&s, SIGPIPE) != 1) e(35);
+  if (sigismember(&s, SIGALRM) != 1) e(36);
+  if (sigismember(&s, SIGTERM) != 1) e(37);
+
+  /* Create an empty set, then turn on bits individually. */
+  if (sigemptyset(&s) != 0) e(39);
+  if (sigaddset(&s, SIGHUP) != 0) e(40);
+  if (sigaddset(&s, SIGINT) != 0) e(41);
+  if (sigaddset(&s, SIGQUIT) != 0) e(42);
+  if (sigaddset(&s, SIGILL) != 0) e(43);
+  if (sigaddset(&s, SIGTRAP) != 0) e(44);
+
+  /* See if the bits just turned on are indeed on. */
+  if (sigismember(&s, SIGHUP) != 1) e(45);
+  if (sigismember(&s, SIGINT) != 1) e(46);
+  if (sigismember(&s, SIGQUIT) != 1) e(47);
+  if (sigismember(&s, SIGILL) != 1) e(48);
+  if (sigismember(&s, SIGTRAP) != 1) e(49);
+
+  /* The others should be turned off. */
+  if (sigismember(&s, SIGABRT) != 0) e(50);
+  if (sigismember(&s, SIGIOT) != 0) e(51);
+  if (sigismember(&s, SIGFPE) != 0) e(53);
+  if (sigismember(&s, SIGKILL) != 0) e(54);
+  if (sigismember(&s, SIGUSR1) != 0) e(55);
+  if (sigismember(&s, SIGSEGV) != 0) e(56);
+  if (sigismember(&s, SIGUSR2) != 0) e(57);
+  if (sigismember(&s, SIGPIPE) != 0) e(58);
+  if (sigismember(&s, SIGALRM) != 0) e(59);
+  if (sigismember(&s, SIGTERM) != 0) e(60);
+
+  /* Now turn them off and see if all are off. */
+  if (sigdelset(&s, SIGHUP) != 0) e(62);
+  if (sigdelset(&s, SIGINT) != 0) e(63);
+  if (sigdelset(&s, SIGQUIT) != 0) e(64);
+  if (sigdelset(&s, SIGILL) != 0) e(65);
+  if (sigdelset(&s, SIGTRAP) != 0) e(66);
+
+  if (sigismember(&s, SIGHUP) != 0) e(67);
+  if (sigismember(&s, SIGINT) != 0) e(68);
+  if (sigismember(&s, SIGQUIT) != 0) e(69);
+  if (sigismember(&s, SIGILL) != 0) e(70);
+  if (sigismember(&s, SIGTRAP) != 0) e(71);
+  if (sigismember(&s, SIGABRT) != 0) e(72);
+  if (sigismember(&s, SIGIOT) != 0) e(73);
+  if (sigismember(&s, SIGFPE) != 0) e(75);
+  if (sigismember(&s, SIGKILL) != 0) e(76);
+  if (sigismember(&s, SIGUSR1) != 0) e(77);
+  if (sigismember(&s, SIGSEGV) != 0) e(78);
+  if (sigismember(&s, SIGUSR2) != 0) e(79);
+  if (sigismember(&s, SIGPIPE) != 0) e(80);
+  if (sigismember(&s, SIGALRM) != 0) e(81);
+  if (sigismember(&s, SIGTERM) != 0) e(82);
+}
+
+void func1(sig)
+int sig;
+{
+  sig1++;
+}
+
+void func2(sig)
+int sig;
+{
+  sig2++;
+}
+
+void test37b()
+{
+/* Test sigprocmask and sigpending. */
+  int i;
+  pid_t p;
+  sigset_t s, s1, s_empty, s_full, s_ill, s_ill_pip, s_nokill, s_nokill_stop;
+  struct sigaction sa, osa;
+
+  subtest = 2;
+  clearsigstate();
+
+  /* Construct s_ill = {SIGILL} and s_ill_pip {SIGILL | SIGPIP}, etc. */
+  if (sigemptyset(&s_empty) != 0) e(1);
+  if (sigemptyset(&s_ill) != 0) e(2);
+  if (sigemptyset(&s_ill_pip) != 0) e(3);
+  if (sigaddset(&s_ill, SIGILL) != 0) e(4);
+  if (sigaddset(&s_ill_pip, SIGILL) != 0) e(5);
+  if (sigaddset(&s_ill_pip, SIGPIPE) != 0) e(6);
+  if (sigfillset(&s_full) != 0) e(7);
+  s_nokill = s_full;
+  if (sigdelset(&s_nokill, SIGKILL) != 0) e(8);
+  s_nokill_stop = s_nokill;
+  if (sigdelset(&s_nokill_stop, SIGSTOP) != 0) e(8);
+#ifndef _MINIX /* XXX - should unsupported signals be <= _NSIG? */
+  if (SIGSTOP > _NSIG) e(666);
+  if (SIGSTOP <= _NSIG && sigdelset(&s_nokill, SIGSTOP) != 0) e(888);
+#endif /* _MINIX */
+
+  /* Now get most of the signals into default state.  Don't change SIGINT
+  * or SIGQUIT, so this program can be killed.  SIGKILL is also special.
+  */
+  sa.sa_handler = SIG_DFL;
+  sa.sa_mask = s_empty;
+  sa.sa_flags = 0;
+  for (i = 0; i < SIGS; i++) sigaction(i, &sa, &osa);
+
+  /* The second argument may be zero.  See if it wipes out the system. */
+  for (i = 0; i < SIGS; i++) sigaction(i, (struct sigaction *) NULL, &osa);
+
+  /* Install a signal handler. */
+  sa.sa_handler = func1;
+  sa.sa_mask = s_ill;
+  sa.sa_flags = SA_NODEFER | SA_NOCLDSTOP;
+  osa.sa_handler = SIG_IGN;
+  osa.sa_mask = s_empty;
+  osa.sa_flags = 0;
+  if (sigaction(SIGHUP, &sa, &osa) != 0) e(9);
+  if (osa.sa_handler != SIG_DFL) e(10);
+  if (osa.sa_mask != 0) e(11);
+  if (osa.sa_flags != s_empty) e(12);
+
+  /* Replace action and see if old value is read back correctly. */
+  sa.sa_handler = func2;
+  sa.sa_mask = s_ill_pip;
+  sa.sa_flags = SA_RESETHAND | SA_NODEFER;
+  osa.sa_handler = SIG_IGN;
+  osa.sa_mask = s_empty;
+  osa.sa_flags = 0;
+  if (sigaction(SIGHUP, &sa, &osa) != 0) e(13);
+  if (osa.sa_handler != func1) e(14);
+  if (osa.sa_mask != s_ill) e(15);
+  if (osa.sa_flags != SA_NODEFER
+      && osa.sa_flags != (SA_NODEFER | SA_NOCLDSTOP)) e(16);
+
+  /* Replace action once more and check what is read back. */
+  sa.sa_handler = SIG_DFL;
+  sa.sa_mask = s_empty;
+  osa.sa_handler = SIG_IGN;
+  osa.sa_mask = s_empty;
+  osa.sa_flags = 0;
+  if (sigaction(SIGHUP, &sa, &osa) != 0) e(17);
+  if (osa.sa_handler != func2) e(18);
+  if (osa.sa_mask != s_ill_pip) e(19);
+  if (osa.sa_flags != (SA_RESETHAND | SA_NODEFER)) e(20);
+
+  /* Test sigprocmask(SIG_SETMASK, ...). */
+  if (sigprocmask(SIG_SETMASK, &s_full, &s1) != 0) e(18);    /* block all */
+  if (sigemptyset(&s1) != 0) e(19);
+  errno = 0;
+  if (sigprocmask(SIG_SETMASK, &s_empty, &s1) != 0) e(20);   /* block none */
+  if (s1 != s_nokill_stop) e(21);
+  if (sigprocmask(SIG_SETMASK, &s_ill, &s1) != 0) e(22);     /* block SIGILL */
+  errno = 0;
+  if (s1 != s_empty) e(23);
+  if (sigprocmask(SIG_SETMASK, &s_ill_pip, &s1) != 0) e(24); /* SIGILL+PIP */
+  if (s1 != s_ill) e(25);
+  if (sigprocmask(SIG_SETMASK, &s_full, &s1) != 0) e(26);    /* block all */
+  if (s1 != s_ill_pip) e(27);
+
+  /* Test sigprocmask(SIG_UNBLOCK, ...) */
+  if (sigprocmask(SIG_UNBLOCK, &s_ill, &s1) != 0) e(28);
+  if (s1 != s_nokill_stop) e(29);
+  if (sigprocmask(SIG_UNBLOCK, &s_ill_pip, &s1) != 0) e(30);
+  s = s_nokill_stop;
+  if (sigdelset(&s, SIGILL) != 0) e(31);
+  if (s != s1) e(32);
+  if (sigprocmask(SIG_UNBLOCK, &s_empty, &s1) != 0) e(33);
+  s = s_nokill_stop;
+  if (sigdelset(&s, SIGILL) != 0) e(34);
+  if (sigdelset(&s, SIGPIPE) != 0) e(35);
+  if (s != s1) e(36);
+  s1 = s_nokill_stop;
+  if (sigprocmask(SIG_SETMASK, &s_empty, &s1) != 0) e(37);
+  if (s != s1) e(38);
+
+  /* Test sigprocmask(SIG_BLOCK, ...) */
+  if (sigprocmask(SIG_BLOCK, &s_ill, &s1) != 0) e(39);
+  if (s1 != s_empty) e(40);
+  if (sigprocmask(SIG_BLOCK, &s_ill_pip, &s1) != 0) e(41);
+  if (s1 != s_ill) e(42);
+  if (sigprocmask(SIG_SETMASK, &s_full, &s1) != 0) e(43);
+  if (s1 != s_ill_pip) e(44);
+
+  /* Check error condition. */
+  errno = 0;
+  if (sigprocmask(20000, &s_full, &s1) != -1) e(45);
+  if (errno != EINVAL) e(46);
+  if (sigprocmask(SIG_SETMASK, &s_full, &s1) != 0) e(47);
+  if (s1 != s_nokill_stop) e(48);
+
+  /* If second arg is 0, nothing is set. */
+  if (sigprocmask(SIG_SETMASK, (sigset_t *) NULL, &s1) != 0) e(49);
+  if (s1 != s_nokill_stop) e(50);
+  if (sigprocmask(SIG_SETMASK, &s_ill_pip, &s1) != 0) e(51);
+  if (s1 != s_nokill_stop) e(52);
+  if (sigprocmask(SIG_SETMASK, (sigset_t *) NULL, &s1) != 0) e(53);
+  if (s1 != s_ill_pip) e(54);
+  if (sigprocmask(SIG_BLOCK, (sigset_t *) NULL, &s1) != 0) e(55);
+  if (s1 != s_ill_pip) e(56);
+  if (sigprocmask(SIG_UNBLOCK, (sigset_t *) NULL, &s1) != 0) e(57);
+  if (s1 != s_ill_pip) e(58);
+
+  /* Trying to block SIGKILL is not allowed, but is not an error, either. */
+  s = s_empty;
+  if (sigaddset(&s, SIGKILL) != 0) e(59);
+  if (sigprocmask(SIG_BLOCK, &s, &s1) != 0) e(60);
+  if (s1 != s_ill_pip) e(61);
+  if (sigprocmask(SIG_SETMASK, &s_full, &s1) != 0) e(62);
+  if (s1 != s_ill_pip) e(63);
+
+  /* Test sigpending. At this moment, all signals are blocked. */
+  sa.sa_handler = func2;
+  sa.sa_mask = s_empty;
+  if (sigaction(SIGHUP, &sa, &osa) != 0) e(64);
+  p = getpid();
+  kill(p, SIGHUP);		/* send SIGHUP to self */
+  if (sigpending(&s) != 0) e(65);
+  if (sigemptyset(&s1) != 0) e(66);
+  if (sigaddset(&s1, SIGHUP) != 0) e(67);
+  if (s != s1) e(68);
+  sa.sa_handler = SIG_IGN;
+  if (sigaction(SIGHUP, &sa, &osa) != 0) e(69);
+  if (sigpending(&s) != 0) e(70);
+  if (s != s_empty) e(71);
+}
+
+/*---------------------------------------------------------------------------*/
+int x;
+sigset_t glo_vol_set;
+
+void catch1(signo)
+int signo;
+{
+  x = 42;
+}
+
+void catch2(signo)
+int signo;
+{
+  if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, (sigset_t *) &glo_vol_set) != 0)
+	e(1);
+}
+
+/* Verify that signal(2), which is now built on top of sigaction(2), still
+* works.
+*/
+void test37c()
+{
+  pid_t pid;
+  sigset_t sigset_var;
+
+  subtest = 3;
+  clearsigstate();
+  x = 0;
+
+  /* Verify an installed signal handler persists across a fork(2). */
+  if (signal(SIGTERM, catch1) == SIG_ERR) e(1);
+  switch (pid = fork()) {
+      case 0:			/* child */
+	errct = 0;
+	while (x == 0);
+	if (x != 42) e(2);
+	exit(errct == 0 ? 0 : 1);
+      case -1:	e(3);	break;
+      default:			/* parent */
+	sleep(1);
+	if (kill(pid, SIGTERM) != 0) e(4);
+	wait_for(pid);
+	break;
+  }
+
+  /* Verify that the return value is the previous handler. */
+  signal(SIGINT, SIG_IGN);
+  if (signal(SIGINT, catch2) != SIG_IGN) e(5);
+  if (signal(SIGINT, catch1) != catch2) e(6);
+  if (signal(SIGINT, SIG_DFL) != catch1) e(7);
+  if (signal(SIGINT, catch1) != SIG_DFL) e(8);
+  if (signal(SIGINT, SIG_DFL) != catch1) e(9);
+  if (signal(SIGINT, SIG_DFL) != SIG_DFL) e(10);
+  if (signal(SIGINT, catch1) != SIG_DFL) e(11);
+
+  /* Verify that SIG_ERR is correctly generated. */
+  if (signal(_NSIG + 1, catch1) != SIG_ERR) e(12);
+  if (signal(0, catch1) != SIG_ERR) e(13);
+  if (signal(-1, SIG_DFL) != SIG_ERR) e(14);
+
+  /* Verify that caught signals are automatically reset to the default,
+   * and that further instances of the same signal are not blocked here
+   * or in the signal handler.
+   */
+  if (signal(SIGTERM, catch1) == SIG_ERR) e(15);
+  switch ((pid = fork())) {
+      case 0:			/* child */
+	errct = 0;
+	while (x == 0);
+	if (x != 42) e(16);
+	if (sigismember((sigset_t *) &glo_vol_set, SIGTERM)) e(17);
+	if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &sigset_var) != 0) e(18);
+	if (sigismember(&sigset_var, SIGTERM)) e(19);
+
+#if 0
+/* Use this if you have compiled signal() to have the broken SYSV behaviour. */
+	if (signal(SIGTERM, catch1) != SIG_DFL) e(20);
+#else
+	if (signal(SIGTERM, catch1) != catch1) e(20);
+#endif
+	exit(errct == 0 ? 0 : 1);
+      default:			/* parent */
+	sleep(1);
+	if (kill(pid, SIGTERM) != 0) e(21);
+	wait_for(pid);
+	break;
+      case -1:	e(22);	break;
+  }
+}
+
+/*---------------------------------------------------------------------------*/
+/* Test that the signal handler can be invoked recursively with the
+* state being properly saved and restored.
+*/
+
+static int y;
+static int z;
+
+void catch3(signo)
+int signo;
+{
+  if (z == 1) {			/* catching a nested signal */
+	y = 2;
+	return;
+  }
+  z = 1;
+  if (kill(getpid(), SIGHUP) != 0) e(1);
+  while (y != 2);
+  y = 1;
+}
+
+void test37d()
+{
+  struct sigaction act;
+
+  subtest = 4;
+  clearsigstate();
+  y = 0;
+  z = 0;
+
+  act.sa_handler = catch3;
+  act.sa_mask = 0;
+  act.sa_flags = SA_NODEFER;	/* Otherwise, nested occurence of
+				 * SIGINT is blocked. */
+  if (sigaction(SIGHUP, &act, (struct sigaction *) NULL) != 0) e(2);
+  if (kill(getpid(), SIGHUP) != 0) e(3);
+  if (y != 1) e(4);
+}
+
+/*---------------------------------------------------------------------------*/
+
+/* Test that the signal mask in effect for the duration of a signal handler
+* is as specified in POSIX Section 3, lines 718 -724.  Test that the
+* previous signal mask is restored when the signal handler returns.
+*/
+
+void catch4(signo)
+int signo;
+{
+  sigset_t oset;
+  sigset_t set;
+
+  if (sigemptyset(&set) == -1) e(5001);
+  if (sigaddset(&set, SIGTERM) == -1) e(5002);
+  if (sigaddset(&set, SIGHUP) == -1) e(5003);
+  if (sigaddset(&set, SIGINT) == -1) e(5004);
+  if (sigaddset(&set, SIGPIPE) == -1) e(5005);
+  if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &oset) != 0) e(5006);
+  if (oset != set) e(5007);
+}
+
+void test37e()
+{
+  struct sigaction act, oact;
+  sigset_t set, oset;
+
+  subtest = 5;
+  clearsigstate();
+
+  act.sa_handler = catch4;
+  sigemptyset(&act.sa_mask);
+  sigaddset(&act.sa_mask, SIGTERM);
+  sigaddset(&act.sa_mask, SIGHUP);
+  act.sa_flags = 0;
+  if (sigaction(SIGINT, &act, &oact) == -1) e(2);
+
+  if (sigemptyset(&set) == -1) e(3);
+  if (sigaddset(&set, SIGPIPE) == -1) e(4);
+  if (sigprocmask(SIG_SETMASK, &set, &oset) == -1) e(5);
+  if (kill(getpid(), SIGINT) == -1) e(6);
+  if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &oset) == -1) e(7);
+  if (sigemptyset(&set) == -1) e(8);
+  if (sigaddset(&set, SIGPIPE) == -1) e(9);
+  if (set != oset) e(10);
+}
+
+/*---------------------------------------------------------------------------*/
+
+/* Test the basic functionality of sigsuspend(2). */
+
+void catch5(signo)
+int signo;
+{
+  x = 1;
+}
+
+void test37f()
+{
+  sigset_t set;
+  int r;
+  struct sigaction act;
+  pid_t pid;
+
+  subtest = 6;
+  clearsigstate();
+
+  switch (pid = fork()) {
+      case 0:			/* child */
+	errct = 0;
+	sleep(1);
+	if (kill(getppid(), SIGINT) == -1) e(1);
+	exit(errct == 0 ? 0 : 1);
+      case -1:	e(2);	break;
+      default:			/* parent */
+	if (sigemptyset(&act.sa_mask) == -1) e(3);
+	act.sa_flags = 0;
+	act.sa_handler = catch5;
+	if (sigaction(SIGINT, &act, (struct sigaction *) NULL) == -1) e(4);
+
+	if (sigemptyset(&set) == -1) e(5);
+	r = sigsuspend(&set);
+
+	if (r != -1 || errno != EINTR || x != 1) e(6);
+	wait_for(pid);
+	break;
+  }
+}
+
+/*----------------------------------------------------------------------*/
+
+/* Test that sigsuspend() does block the signals specified in its
+* argument, and after sigsuspend returns, the previous signal
+* mask is restored.
+*
+* The child sends two signals to the parent SIGINT and then SIGPIPE,
+* separated by a long delay.  The parent executes sigsuspend() with
+* SIGINT blocked.  It is expected that the parent's SIGPIPE handler
+* will be invoked, then sigsuspend will return restoring the
+* original signal mask, and then the SIGPIPE handler will be
+* invoked.
+*/
+
+void sigint_handler(signo)
+int signo;
+{
+  x = 1;
+  z++;
+}
+
+void sigpipe_handler(signo)
+int signo;
+{
+  x = 2;
+  z++;
+}
+
+void test37g()
+{
+  sigset_t set;
+  int r;
+  struct sigaction act;
+  pid_t pid;
+
+  subtest = 7;
+  clearsigstate();
+  x = 0;
+  z = 0;
+
+  switch (pid = fork()) {
+      case 0:			/* child */
+	errct = 0;
+	sleep(1);
+	if (kill(getppid(), SIGINT) == -1) e(1);
+	sleep(1);
+	if (kill(getppid(), SIGPIPE) == -1) e(2);
+	exit(errct == 0 ? 0 : 1);
+      case -1:	e(3);	break;
+      default:			/* parent */
+	if (sigemptyset(&act.sa_mask) == -1) e(3);
+	act.sa_flags = 0;
+	act.sa_handler = sigint_handler;
+	if (sigaction(SIGINT, &act, (struct sigaction *) NULL) == -1) e(4);
+
+	act.sa_handler = sigpipe_handler;
+	if (sigaction(SIGPIPE, &act, (struct sigaction *) NULL) == -1) e(5);
+
+	if (sigemptyset(&set) == -1) e(6);
+	if (sigaddset(&set, SIGINT) == -1) e(7);
+	r = sigsuspend(&set);
+	if (r != -1) e(8);
+	if (errno != EINTR) e(9);
+	if (z != 2) e(10);
+	if (x != 1) e(11);
+	wait_for(pid);
+	break;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* Test that sigsuspend() does block the signals specified in its
+* argument, and after sigsuspend returns, the previous signal
+* mask is restored.
+*
+* The child sends three signals to the parent: SIGHUP, then SIGPIPE,
+* and then SIGTERM, separated by a long delay.  The parent executes
+* sigsuspend() with SIGHUP and SIGPIPE blocked.  It is expected that
+* the parent's SIGTERM handler will be invoked first, then sigsuspend()
+* will return restoring the original signal mask, and then the other
+* two handlers will be invoked.
+*/
+
+void sighup8(signo)
+int signo;
+{
+  x = 1;
+  z++;
+}
+
+void sigpip8(signo)
+int signo;
+{
+  x = 1;
+  z++;
+}
+
+void sigter8(signo)
+int signo;
+{
+  x = 2;
+  z++;
+}
+
+void test37h()
+{
+  sigset_t set;
+  int r;
+  struct sigaction act;
+  pid_t pid;
+
+  subtest = 8;
+  clearsigstate();
+  x = 0;
+  z = 0;
+
+  switch (pid = fork()) {
+      case 0:			/* child */
+	errct = 0;
+	sleep(1);
+	if (kill(getppid(), SIGHUP) == -1) e(1);
+	sleep(1);
+	if (kill(getppid(), SIGPIPE) == -1) e(2);
+	sleep(1);
+	if (kill(getppid(), SIGTERM) == -1) e(3);
+	exit(errct == 0 ? 0 : 1);
+      case -1:	e(5);	break;
+      default:			/* parent */
+	if (sigemptyset(&act.sa_mask) == -1) e(6);
+	act.sa_flags = 0;
+	act.sa_handler = sighup8;
+	if (sigaction(SIGHUP, &act, (struct sigaction *) NULL) == -1) e(7);
+
+	act.sa_handler = sigpip8;
+	if (sigaction(SIGPIPE, &act, (struct sigaction *) NULL) == -1) e(8);
+
+	act.sa_handler = sigter8;
+	if (sigaction(SIGTERM, &act, (struct sigaction *) NULL) == -1) e(9);
+
+	if (sigemptyset(&set) == -1) e(10);
+	if (sigaddset(&set, SIGHUP) == -1) e(11);
+	if (sigaddset(&set, SIGPIPE) == -1) e(12);
+	r = sigsuspend(&set);
+	if (r != -1) e(13);
+	if (errno != EINTR) e(14);
+	if (z != 3) e(15);
+	if (x != 1) e(16);
+	wait_for(pid);
+	break;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* Block SIGHUP and SIGTERM with sigprocmask(), send ourself SIGHUP
+* and SIGTERM, unblock these signals with sigprocmask, and verify
+* that these signals are delivered.
+*/
+
+void sighup9(signo)
+int signo;
+{
+  y++;
+}
+
+void sigter9(signo)
+int signo;
+{
+  z++;
+}
+
+void test37i()
+{
+  sigset_t set;
+  struct sigaction act;
+
+  subtest = 9;
+  clearsigstate();
+  y = 0;
+  z = 0;
+
+  if (sigemptyset(&act.sa_mask) == -1) e(1);
+  act.sa_flags = 0;
+
+  act.sa_handler = sighup9;
+  if (sigaction(SIGHUP, &act, (struct sigaction *) NULL) == -1) e(2);
+
+  act.sa_handler = sigter9;
+  if (sigaction(SIGTERM, &act, (struct sigaction *) NULL) == -1) e(3);
+
+  if (sigemptyset(&set) == -1) e(4);
+  if (sigaddset(&set, SIGTERM) == -1) e(5);
+  if (sigaddset(&set, SIGHUP) == -1) e(6);
+  if (sigprocmask(SIG_SETMASK, &set, (sigset_t *)NULL) == -1) e(7);
+
+  if (kill(getpid(), SIGHUP) == -1) e(8);
+  if (kill(getpid(), SIGTERM) == -1) e(9);
+  if (y != 0) e(10);
+  if (z != 0) e(11);
+
+  if (sigemptyset(&set) == -1) e(12);
+  if (sigprocmask(SIG_SETMASK, &set, (sigset_t *)NULL) == -1) e(12);
+  if (y != 1) e(13);
+  if (z != 1) e(14);
+}
+
+/*---------------------------------------------------------------------------*/
+
+/* Block SIGINT and then send this signal to ourself.
+*
+* Install signal handlers for SIGALRM and SIGINT.
+*
+* Set an alarm for 6 seconds, then sleep for 7.
+*
+* The SIGALRM should interrupt the sleep, but the SIGINT
+* should remain pending.
+*/
+
+void sighup10(signo)
+int signo;
+{
+  y++;
+}
+
+void sigalrm_handler10(signo)
+int signo;
+{
+  z++;
+}
+
+void test37j()
+{
+  sigset_t set, set2;
+  struct sigaction act;
+
+  subtest = 10;
+  clearsigstate();
+  y = 0;
+  z = 0;
+
+  if (sigemptyset(&act.sa_mask) == -1) e(1);
+  act.sa_flags = 0;
+
+  act.sa_handler = sighup10;
+  if (sigaction(SIGHUP, &act, (struct sigaction *) NULL) == -1) e(2);
+
+  act.sa_handler = sigalrm_handler10;
+  if (sigaction(SIGALRM, &act, (struct sigaction *) NULL) == -1) e(3);
+
+  if (sigemptyset(&set) == -1) e(4);
+  if (sigaddset(&set, SIGHUP) == -1) e(5);
+  if (sigprocmask(SIG_SETMASK, &set, (sigset_t *)NULL) == -1) e(6);
+
+  if (kill(getpid(), SIGHUP) == -1) e(7);
+  if (sigpending(&set) == -1) e(8);
+  if (sigemptyset(&set2) == -1) e(9);
+  if (sigaddset(&set2, SIGHUP) == -1) e(10);
+  if (set2 != set) e(11);
+  alarm(6);
+  sleep(7);
+  if (sigpending(&set) == -1) e(12);
+  if (set != set2) e(13);
+  if (y != 0) e(14);
+  if (z != 1) e(15);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void test37k()
+{
+  subtest = 11;
+}
+void test37l()
+{
+  subtest = 12;
+}
+
+/*---------------------------------------------------------------------------*/
+
+/* Basic test for setjmp/longjmp.  This includes testing that the
+* signal mask is properly restored.
+*/
+
+void test37m()
+{
+  jmp_buf jb;
+  sigset_t ss;
+
+  subtest = 13;
+  clearsigstate();
+
+  ss = 0x32;
+  if (sigprocmask(SIG_SETMASK, &ss, (sigset_t *)NULL) == -1) e(1);
+  if (setjmp(jb)) {
+	if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &ss) == -1) e(2);
+	if (ss != 0x32) e(388);
+	return;
+  }
+  ss = 0x3abc;
+  if (sigprocmask(SIG_SETMASK, &ss, (sigset_t *)NULL) == -1) e(4);
+  longjmp(jb, 1);
+}
+
+void longjerr()
+{
+  e(5);
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* Test for setjmp/longjmp.
+*
+* Catch a signal.  While in signal handler do setjmp/longjmp.
+*/
+
+void catch14(signo, code, scp)
+int signo;
+int code;
+struct sigcontext *scp;
+{
+  jmp_buf jb;
+
+  if (setjmp(jb)) {
+	x++;
+	sigreturn(scp);
+	e(1);
+  }
+  y++;
+  longjmp(jb, 1);
+  e(2);
+}
+
+void test37n()
+{
+  struct sigaction act;
+  typedef _PROTOTYPE( void (*sighandler_t), (int sig) );
+
+  subtest = 14;
+  clearsigstate();
+  x = 0;
+  y = 0;
+
+  act.sa_flags = 0;
+  act.sa_mask = 0;
+  act.sa_handler = (sighandler_t) catch14;	/* fudge */
+  if (sigaction(SIGSEGV, &act, (struct sigaction *) NULL) == -1) e(3);
+  if (kill(getpid(), SIGSEGV) == -1) e(4);
+
+  if (x != 1) e(5);
+  if (y != 1) e(6);
+}
+
+/*---------------------------------------------------------------------------*/
+
+/* Test for setjmp/longjmp.
+ *
+ * Catch a signal.  Longjmp out of signal handler.
+ */
+jmp_buf glo_jb;
+
+void catch15(signo)
+int signo;
+{
+  z++;
+  longjmp(glo_jb, 7);
+  e(1);
+
+}
+
+void test37o()
+{
+  struct sigaction act;
+  int k;
+
+  subtest = 15;
+  clearsigstate();
+  z = 0;
+
+  act.sa_flags = 0;
+  act.sa_mask = 0;
+  act.sa_handler = catch15;
+  if (sigaction(SIGALRM, &act, (struct sigaction *) NULL) == -1) e(2);
+
+  if ((k = setjmp(glo_jb))) {
+	if (z != 1) e(399);
+	if (k != 7) e(4);
+	return;
+  }
+  if (kill(getpid(), SIGALRM) == -1) e(5);
+}
+
+void clearsigstate()
+{
+  int i;
+  sigset_t sigset_var;
+
+  /* Clear the signal state. */
+  for (i = 1; i <= _NSIG; i++) signal(i, SIG_IGN);
+  for (i = 1; i <= _NSIG; i++) signal(i, SIG_DFL);
+  sigfillset(&sigset_var);
+  sigprocmask(SIG_UNBLOCK, &sigset_var, (sigset_t *)NULL);
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(4);
+  }
+}
+
+void wait_for(pid)
+pid_t pid;
+{
+/* Expect exactly one child, and that it exits with 0. */
+
+  int r;
+  int status;
+
+  errno = 0;
+  while (1) {
+	errno = 0;
+	r = wait(&status);
+	if (r == pid) {
+		errno = 0;
+		if (status != 0) e(90);
+		return;
+	}
+	if (r < 0) {
+		e(91);
+		return;
+	}
+	e(92);
+  }
+}
+
+void e(n)
+int n;
+{
+  char msgbuf[80];
+
+  sprintf(msgbuf, "Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
+  perror(msgbuf);
+  if (errct++ > MAX_ERROR) {
+	fprintf(stderr, "Too many errors;  test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test38.c
===================================================================
--- /trunk/minix/test/test38.c	(revision 9)
+++ /trunk/minix/test/test38.c	(revision 9)
@@ -0,0 +1,770 @@
+/* Many of the tests require 1.6.n, n > 16, so we may as well assume that
+ * POSIX signals are implemented.
+ */
+#define SIGACTION
+
+/* test38: read(), write()	Author: Jan-Mark Wams (jms@cs.vu.nl) */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <time.h>
+#include <signal.h>
+#include <stdio.h>
+
+#define MAX_ERROR	4
+#define ITERATIONS      3
+#define BUF_SIZE 1024
+
+#define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+#define Stat(a,b)	if (stat(a,b) != 0) printf("Can't stat %s\n", a)
+
+int errct = 0;
+int subtest = 1;
+int superuser;
+int signumber = 0;
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test38a, (void));
+_PROTOTYPE(void test38b, (void));
+_PROTOTYPE(void test38c, (void));
+_PROTOTYPE(void setsignumber, (int _signumber));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 38 ");
+  fflush(stdout);
+  System("rm -rf DIR_38; mkdir DIR_38");
+  Chdir("DIR_38");
+  superuser = (geteuid() == 0);
+  umask(0000);
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test38a();
+	if (m & 0002) test38b();
+	if (m & 0004) test38c();
+  }
+  quit();
+}
+
+void test38a()
+{				/* Try normal operation. */
+  int fd1;
+  struct stat st1, st2;
+  time_t time1;
+  char buf[BUF_SIZE];
+  int stat_loc;
+  int i, j;
+  int tube[2];
+
+  subtest = 1;
+  System("rm -rf ../DIR_38/*");
+
+  /* Let's open bar. */
+  if ((fd1 = open("bar", O_RDWR | O_CREAT, 0777)) != 3) e(1);
+  Stat("bar", &st1);
+
+  /* Writing nothing should not affect the file at all. */
+  if (write(fd1, "", 0) != 0) e(2);
+  Stat("bar", &st2);
+  if (st1.st_uid != st2.st_uid) e(3);
+  if (st1.st_gid != st2.st_gid) e(4);	/* should be same */
+  if (st1.st_mode != st2.st_mode) e(5);
+  if (st1.st_size != st2.st_size) e(6);
+  if (st1.st_nlink != st2.st_nlink) e(7);
+  if (st1.st_mtime != st2.st_mtime) e(8);
+  if (st1.st_ctime != st2.st_ctime) e(9);
+  if (st1.st_atime != st2.st_atime) e(10);
+
+  /* A write should update some status fields. */
+  time(&time1);
+  while (time1 >= time((time_t *)0))
+	;
+  if (write(fd1, "foo", 4) != 4) e(11);
+  Stat("bar", &st2);
+  if (st1.st_mode != st2.st_mode) e(12);
+  if (st1.st_size >= st2.st_size) e(13);
+  if ((off_t) 4 != st2.st_size) e(14);
+  if (st1.st_nlink != st2.st_nlink) e(15);
+  if (st1.st_mtime >= st2.st_mtime) e(16);
+  if (st1.st_ctime >= st2.st_ctime) e(17);
+  if (st1.st_atime != st2.st_atime) e(18);
+
+  /* Lseeks should not change the file status. */
+  if (lseek(fd1, (off_t) - 2, SEEK_END) != 2) e(19);
+  Stat("bar", &st1);
+  if (st1.st_mode != st2.st_mode) e(20);
+  if (st1.st_size != st2.st_size) e(21);
+  if (st1.st_nlink != st2.st_nlink) e(22);
+  if (st1.st_mtime != st2.st_mtime) e(23);
+  if (st1.st_ctime != st2.st_ctime) e(24);
+  if (st1.st_atime != st2.st_atime) e(25);
+
+  /* Writing should start at the current (2) position. */
+  if (write(fd1, "foo", 4) != 4) e(26);
+  Stat("bar", &st2);
+  if (st1.st_mode != st2.st_mode) e(27);
+  if (st1.st_size >= st2.st_size) e(28);
+  if ((off_t) 6 != st2.st_size) e(29);
+  if (st1.st_nlink != st2.st_nlink) e(30);
+  if (st1.st_mtime > st2.st_mtime) e(31);
+  if (st1.st_ctime > st2.st_ctime) e(32);
+  if (st1.st_atime != st2.st_atime) e(33);
+
+  /* A read of zero bytes should not affect anything. */
+  if (read(fd1, buf, 0) != 0) e(34);
+  Stat("bar", &st1);
+  if (st1.st_uid != st2.st_uid) e(35);
+  if (st1.st_gid != st2.st_gid) e(36);	/* should be same */
+  if (st1.st_mode != st2.st_mode) e(37);
+  if (st1.st_size != st2.st_size) e(38);
+  if (st1.st_nlink != st2.st_nlink) e(39);
+  if (st1.st_mtime != st2.st_mtime) e(40);
+  if (st1.st_ctime != st2.st_ctime) e(41);
+  if (st1.st_atime != st2.st_atime) e(42);
+
+  /* The file now should contain ``fofoo\0'' Let's check that. */
+  if (lseek(fd1, (off_t) 0, SEEK_SET) != 0) e(43);
+  if (read(fd1, buf, BUF_SIZE) != 6) e(44);
+  if (strcmp(buf, "fofoo") != 0) e(45);
+
+  /* Only the Access Time should be updated. */
+  Stat("bar", &st2);
+  if (st1.st_mtime != st2.st_mtime) e(46);
+  if (st1.st_ctime != st2.st_ctime) e(47);
+  if (st1.st_atime >= st2.st_atime) e(48);
+
+  /* A read of zero bytes should do nothing even at the end of the file. */
+  time(&time1);
+  while (time1 >= time((time_t *)0))
+	;
+  if (read(fd1, buf, 0) != 0) e(49);
+  Stat("bar", &st1);
+  if (st1.st_size != st2.st_size) e(50);
+  if (st1.st_mtime != st2.st_mtime) e(51);
+  if (st1.st_ctime != st2.st_ctime) e(52);
+  if (st1.st_atime != st2.st_atime) e(53);
+
+  /* Reading should be done from the current offset. */
+  if (read(fd1, buf, BUF_SIZE) != 0) e(54);
+  if (lseek(fd1, (off_t) 2, SEEK_SET) != 2) e(55);
+  if (read(fd1, buf, BUF_SIZE) != 4) e(56);
+  if (strcmp(buf, "foo") != 0) e(57);
+
+  /* Reading should effect the current file position. */
+  if (lseek(fd1, (off_t) 2, SEEK_SET) != 2) e(58);
+  if (read(fd1, buf, 1) != 1) e(59);
+  if (*buf != 'f') e(60);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 3) e(61);
+  if (read(fd1, buf, 1) != 1) e(62);
+  if (*buf != 'o') e(63);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 4) e(64);
+  if (read(fd1, buf, 1) != 1) e(65);
+  if (*buf != 'o') e(66);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 5) e(67);
+  if (read(fd1, buf, 1) != 1) e(68);
+  if (*buf != '\0') e(69);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 6) e(70);
+
+  /* Read's at EOF should return 0. */
+  if (read(fd1, buf, BUF_SIZE) != 0) e(71);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 6) e(72);
+  if (read(fd1, buf, BUF_SIZE) != 0) e(73);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 6) e(74);
+  if (read(fd1, buf, BUF_SIZE) != 0) e(75);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 6) e(76);
+  if (read(fd1, buf, BUF_SIZE) != 0) e(77);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 6) e(78);
+  if (read(fd1, buf, BUF_SIZE) != 0) e(79);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 6) e(80);
+
+  /* Writing should not always change the file size. */
+  if (lseek(fd1, (off_t) 2, SEEK_SET) != 2) e(81);
+  if (write(fd1, "ba", 2) != 2) e(82);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 4) e(83);
+  Stat("bar", &st1);
+  if (st1.st_size != 6) e(84);
+
+  /* Kill the \0 at the end. */
+  if (lseek(fd1, (off_t) 5, SEEK_SET) != 5) e(85);
+  if (write(fd1, "x", 1) != 1) e(86);
+
+  /* And close the bar. */
+  if (close(fd1) != 0) e(87);
+
+  /* Try some stuff with O_APPEND. Bar contains ``fobaox'' */
+  if ((fd1 = open("bar", O_RDWR | O_APPEND)) != 3) e(88);
+
+  /* No matter what the file position is. Writes should append. */
+  if (lseek(fd1, (off_t) 2, SEEK_SET) != 2) e(89);
+  if (write(fd1, "y", 1) != 1) e(90);
+  Stat("bar", &st1);
+  if (st1.st_size != (off_t) 7) e(91);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 7) e(92);
+  if (lseek(fd1, (off_t) 2, SEEK_SET) != 2) e(93);
+  if (write(fd1, "z", 2) != 2) e(94);
+
+  /* The file should contain ``fobaoxyz\0'' == 9 chars long. */
+  Stat("bar", &st1);
+  if (st1.st_size != (off_t) 9) e(95);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 9) e(96);
+
+  /* Reading on a O_APPEND flag should be from the current offset. */
+  if (lseek(fd1, (off_t) 0, SEEK_SET) != 0) e(97);
+  if (read(fd1, buf, BUF_SIZE) != 9) e(98);
+  if (strcmp(buf, "fobaoxyz") != 0) e(99);
+  if (lseek(fd1, (off_t) 0, SEEK_CUR) != 9) e(100);
+
+  if (close(fd1) != 0) e(101);
+
+  /* Let's test fifo writes. First blocking. */
+  if (mkfifo("fifo", 0777) != 0) e(102);
+
+  /* Read from fifo but no writer. */
+  System("rm -rf /tmp/sema.38a");
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+
+      case 0:
+	alarm(20);
+	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(103);
+	system("> /tmp/sema.38a");
+	system("while test -f /tmp/sema.38a; do sleep 1; done");
+errno =0;
+	if (read(fd1, buf, BUF_SIZE) != 0) e(104);
+	if (read(fd1, buf, BUF_SIZE) != 0) e(105);
+	if (read(fd1, buf, BUF_SIZE) != 0) e(106);
+	if (close(fd1) != 0) e(107);
+	exit(0);
+
+      default:
+	if ((fd1 = open("fifo", O_WRONLY)) != 3) e(108);
+	while (stat("/tmp/sema.38a", &st1) != 0) sleep(1);
+	if (close(fd1) != 0) e(109);
+	unlink("/tmp/sema.38a");
+	if (wait(&stat_loc) == -1) e(110);
+	if (stat_loc != 0) e(111);	/* Alarm? */
+  }
+
+  /* Read from fifo should wait for writer. */
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+
+      case 0:
+	alarm(20);
+	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(112);
+	if (read(fd1, buf, BUF_SIZE) != 10) e(113);
+	if (strcmp(buf, "Hi reader") != 0) e(114);
+	if (close(fd1) != 0) e(115);
+	exit(0);
+
+      default:
+	if ((fd1 = open("fifo", O_WRONLY)) != 3) e(116);
+	sleep(1);
+	if (write(fd1, "Hi reader", 10) != 10) e(117);
+	if (close(fd1) != 0) e(118);
+	if (wait(&stat_loc) == -1) e(119);
+	if (stat_loc != 0) e(120);	/* Alarm? */
+  }
+
+#if DEAD_CODE
+  /* Does this test test what it is supposed to test??? */
+
+  /* Read from fifo should wait for all writers to close. */
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+
+      case 0:
+	alarm(60);
+	switch (fork()) {
+	    case -1:	printf("Can't fork\n");	break;
+	    case 0:
+		alarm(20);
+		if ((fd1 = open("fifo", O_WRONLY)) != 3) e(121);
+		printf("C2 did open\n");
+		if (close(fd1) != 0) e(122);
+		printf("C2 did close\n");
+		exit(0);
+	    default:
+		printf("C1 scheduled\n");
+		if ((fd1 = open("fifo", O_WRONLY)) != 3) e(123);
+		printf("C1 did open\n");
+		sleep(2);
+		if (close(fd1) != 0) e(124);
+		printf("C1 did close\n");
+		sleep(1);
+		if (wait(&stat_loc) == -1) e(125);
+		if (stat_loc != 0) e(126);	/* Alarm? */
+	}
+	exit(stat_loc);
+
+      default: {
+	int wait_status;
+	printf("Parent running\n");
+	sleep(1);				/* open in childs first */
+	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(127);
+	if (read(fd1, buf, BUF_SIZE) != 0) e(128);
+	if (close(fd1) != 0) e(129);
+	printf("Parent closed\n");
+	if ((wait_status=wait(&stat_loc)) == -1) e(130);
+
+      printf("wait_status %d, stat_loc %d:", wait_status, stat_loc);
+      if (WIFSIGNALED(stat_loc)) {
+          printf(" killed, signal number %d\n", WTERMSIG(stat_loc));
+      } 
+      else if (WIFEXITED(stat_loc)) {
+          printf(" normal exit, status %d\n", WEXITSTATUS(stat_loc));
+      }
+
+	if (stat_loc != 0) e(131);	/* Alarm? */
+      }
+  }
+#endif
+
+  /* PIPE_BUF has to have a nice value. */
+  if (PIPE_BUF < 5) e(132);
+  if (BUF_SIZE < 1000) e(133);
+
+  /* Writes of blocks smaller than PIPE_BUF should be atomic. */
+  System("rm -rf /tmp/sema.38b;> /tmp/sema.38b");
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+
+      case 0:
+	alarm(20);
+	switch (fork()) {
+	    case -1:	printf("Can't fork\n");	break;
+
+	    case 0:
+		alarm(20);
+		if ((fd1 = open("fifo", O_WRONLY)) != 3) e(134);
+		for (i = 0; i < 100; i++) write(fd1, "1234 ", 5);
+		system("while test -f /tmp/sema.38b; do sleep 1; done");
+		if (close(fd1) != 0) e(135);
+		exit(0);
+
+	    default:
+		if ((fd1 = open("fifo", O_WRONLY)) != 3) e(136);
+		for (i = 0; i < 100; i++) write(fd1, "1234 ", 5);
+		while (stat("/tmp/sema.38b", &st1) == 0) sleep(1);
+		if (close(fd1) != 0) e(137);
+		if (wait(&stat_loc) == -1) e(138);
+		if (stat_loc != 0) e(139);	/* Alarm? */
+	}
+	exit(stat_loc);
+
+      default:
+	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(140);
+	i = 0;
+	memset(buf, '\0', BUF_SIZE);
+
+	/* Read buffer full or till EOF. */
+	do {
+		j = read(fd1, buf + i, BUF_SIZE - i);
+		if (j > 0) {
+			if (j % 5 != 0) e(141);
+			i += j;
+		}
+	} while (j > 0 && i < 1000);
+
+	/* Signal the children to close write ends. This should not be */
+	/* Necessary. But due to a bug in 1.16.6 this is necessary. */
+	unlink("/tmp/sema.38b");
+	if (j < 0) e(142);
+	if (i != 1000) e(143);
+	if (wait(&stat_loc) == -1) e(144);
+	if (stat_loc != 0) e(145);	/* Alarm? */
+
+	/* Check 200 times 1234. */
+	for (i = 0; i < 200; i++)
+		if (strncmp(buf + (i * 5), "1234 ", 5) != 0) break;
+	if (i != 200) e(146);
+	if (buf[1000] != '\0') e(147);
+	if (buf[1005] != '\0') e(148);
+	if (buf[1010] != '\0') e(149);
+	if (read(fd1, buf, BUF_SIZE) != 0) e(150);
+	if (close(fd1) != 0) e(151);
+  }
+
+  /* Read from pipe should wait for writer. */
+  if (pipe(tube) != 0) e(152);
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	if (close(tube[1]) != 0) e(153);
+	if (read(tube[0], buf, BUF_SIZE) != 10) e(154);
+	if (strcmp(buf, "Hi reader") != 0) e(155);
+	if (close(tube[0]) != 0) e(156);
+	exit(0);
+      default:
+	if (close(tube[0]) != 0) e(157);
+	sleep(1);
+	if (write(tube[1], "Hi reader", 10) != 10) e(158);
+	if (close(tube[1]) != 0) e(159);
+	if (wait(&stat_loc) == -1) e(160);
+	if (stat_loc != 0) e(161);	/* Alarm? */
+  }
+
+  /* Read from pipe should wait for all writers to close. */
+  if (pipe(tube) != 0) e(162);
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	if (close(tube[0]) != 0) e(163);
+	switch (fork()) {
+	    case -1:	printf("Can't fork\n");	break;
+	    case 0:
+		alarm(20);
+		if (close(tube[1]) != 0) e(164);
+		exit(0);
+	    default:
+		sleep(1);
+		if (close(tube[1]) != 0) e(165);
+		if (wait(&stat_loc) == -1) e(166);
+		if (stat_loc != 0) e(167);	/* Alarm? */
+	}
+	exit(stat_loc);
+      default:
+	if (close(tube[1]) != 0) e(168);
+	if (read(tube[0], buf, BUF_SIZE) != 0) e(169);
+	if (close(tube[0]) != 0) e(170);
+	if (wait(&stat_loc) == -1) e(171);
+	if (stat_loc != 0) e(172);	/* Alarm? */
+  }
+
+  /* Writes of blocks smaller than PIPE_BUF should be atomic. */
+  System("rm -rf /tmp/sema.38c;> /tmp/sema.38c");
+  if (pipe(tube) != 0) e(173);
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	if (close(tube[0]) != 0) e(174);
+	switch (fork()) {
+	    case -1:	printf("Can't fork\n");	break;
+	    case 0:
+		alarm(20);
+		for (i = 0; i < 100; i++) write(tube[1], "1234 ", 5);
+		system("while test -f /tmp/sema.38c; do sleep 1; done");
+		if (close(tube[1]) != 0) e(175);
+		exit(0);
+	    default:
+		for (i = 0; i < 100; i++) write(tube[1], "1234 ", 5);
+		while (stat("/tmp/sema.38c", &st1) == 0) sleep(1);
+		if (close(tube[1]) != 0) e(176);
+		if (wait(&stat_loc) == -1) e(177);
+		if (stat_loc != 0) e(178);	/* Alarm? */
+	}
+	exit(stat_loc);
+      default:
+	i = 0;
+	if (close(tube[1]) != 0) e(179);
+	memset(buf, '\0', BUF_SIZE);
+	do {
+		j = read(tube[0], buf + i, BUF_SIZE - i);
+		if (j > 0) {
+			if (j % 5 != 0) e(180);
+			i += j;
+		} else
+			break;	/* EOF seen. */
+	} while (i < 1000);
+	unlink("/tmp/sema.38c");
+	if (j < 0) e(181);
+	if (i != 1000) e(182);
+	if (close(tube[0]) != 0) e(183);
+	if (wait(&stat_loc) == -1) e(184);
+	if (stat_loc != 0) e(185);	/* Alarm? */
+
+	/* Check 200 times 1234. */
+	for (i = 0; i < 200; i++)
+		if (strncmp(buf + (i * 5), "1234 ", 5) != 0) break;
+	if (i != 200) e(186);
+  }
+}
+
+void test38b()
+{
+  int i, fd, stat_loc;
+  char buf[BUF_SIZE];
+  char buf2[BUF_SIZE];
+  struct stat st;
+
+  subtest = 2;
+  System("rm -rf ../DIR_38/*");
+
+  /* Lets try sequential writes. */
+  system("rm -rf /tmp/sema.38d");
+  System("> testing");
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	if ((fd = open("testing", O_WRONLY | O_APPEND)) != 3) e(1);
+	if (write(fd, "one ", 4) != 4) e(2);
+	if (close(fd) != 0) e(3);
+	system("> /tmp/sema.38d");
+	system("while test -f /tmp/sema.38d; do sleep 1; done");
+	if ((fd = open("testing", O_WRONLY | O_APPEND)) != 3) e(4);
+	if (write(fd, "three ", 6) != 6) e(5);
+	if (close(fd) != 0) e(6);
+	system("> /tmp/sema.38d");
+	exit(0);
+      default:
+	while (stat("/tmp/sema.38d", &st) != 0) sleep(1);
+	if ((fd = open("testing", O_WRONLY | O_APPEND)) != 3) e(7);
+	if (write(fd, "two ", 4) != 4) e(8);
+	if (close(fd) != 0) e(9);
+	unlink("/tmp/sema.38d");
+	while (stat("/tmp/sema.38d", &st) != 0) sleep(1);
+	if ((fd = open("testing", O_WRONLY | O_APPEND)) != 3) e(10);
+	if (write(fd, "four", 5) != 5) e(11);
+	if (close(fd) != 0) e(12);
+	if (wait(&stat_loc) == -1) e(13);
+	if (stat_loc != 0) e(14);	/* The alarm went off? */
+	unlink("/tmp/sema.38d");
+  }
+  if ((fd = open("testing", O_RDONLY)) != 3) e(15);
+  if (read(fd, buf, BUF_SIZE) != 19) e(16);
+  if (strcmp(buf, "one two three four") != 0) e(17);
+  if (close(fd) != 0) e(18);
+
+  /* Non written bytes in regular files should be zero. */
+  memset(buf2, '\0', BUF_SIZE);
+  if ((fd = open("bigfile", O_RDWR | O_CREAT, 0644)) != 3) e(19);
+  if (lseek(fd, (off_t) 102400, SEEK_SET) != (off_t) 102400L) e(20);
+  if (read(fd, buf, BUF_SIZE) != 0) e(21);
+  if (write(fd, ".", 1) != 1) e(22);
+  Stat("bigfile", &st);
+  if (st.st_size != (off_t) 102401) e(23);
+  if (lseek(fd, (off_t) 0, SEEK_SET) != 0) e(24);
+  for (i = 0; i < 102400 / BUF_SIZE; i++) {
+	if (read(fd, buf, BUF_SIZE) != BUF_SIZE) e(25);
+	if (memcmp(buf, buf2, BUF_SIZE) != 0) e(26);
+  }
+  if (close(fd) != 0) e(27);
+}
+
+void test38c()
+{				/* Test correct error behavior. */
+  char buf[BUF_SIZE];
+  int fd, tube[2], stat_loc;
+  struct stat st;
+  pid_t pid;
+#ifdef SIGACTION
+  struct sigaction act, oact;
+#else
+#if _ANSI
+  void (*oldfunc) (int);
+#else
+  void (*oldfunc) ();
+#endif
+#endif
+
+  subtest = 3;
+  System("rm -rf ../DIR_38/*");
+
+  /* To test if writing processes on closed pipes are signumbered. */
+#ifdef SIGACTION
+  act.sa_handler = setsignumber;
+  sigemptyset(&act.sa_mask);
+  act.sa_flags = 0;
+  if (sigaction(SIGPIPE, &act, &oact) != 0) e(1);
+#else
+  oldfunc = signal(SIGPIPE, setsignumber);
+#endif
+
+  /* Non valid file descriptors should be an error. */
+  for (fd = -111; fd < 0; fd++) {
+	errno = 0;
+	if (read(fd, buf, BUF_SIZE) != -1) e(2);
+	if (errno != EBADF) e(3);
+  }
+  for (fd = 3; fd < 111; fd++) {
+	errno = 0;
+	if (read(fd, buf, BUF_SIZE) != -1) e(4);
+	if (errno != EBADF) e(5);
+  }
+  for (fd = -111; fd < 0; fd++) {
+	errno = 0;
+	if (write(fd, buf, BUF_SIZE) != -1) e(6);
+	if (errno != EBADF) e(7);
+  }
+  for (fd = 3; fd < 111; fd++) {
+	errno = 0;
+	if (write(fd, buf, BUF_SIZE) != -1) e(8);
+	if (errno != EBADF) e(9);
+  }
+
+  /* Writing a pipe with no readers should trigger SIGPIPE. */
+  if (pipe(tube) != 0) e(10);
+  close(tube[0]);
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	signumber = 0;
+	if (write(tube[1], buf, BUF_SIZE) != -1) e(11);
+	if (errno != EPIPE) e(12);
+	if (signumber != SIGPIPE) e(13);
+	if (close(tube[1]) != 0) e(14);
+	exit(0);
+      default:
+	close(tube[1]);
+	if (wait(&stat_loc) == -1) e(15);
+	if (stat_loc != 0) e(16);	/* Alarm? */
+  }
+
+  /* Writing a fifo with no readers should trigger SIGPIPE. */
+  System("> /tmp/sema.38e");
+  if (mkfifo("fifo", 0666) != 0) e(17);
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	if ((fd = open("fifo", O_WRONLY)) != 3) e(18);
+	system("while test -f /tmp/sema.38e; do sleep 1; done");
+	signumber = 0;
+	if (write(fd, buf, BUF_SIZE) != -1) e(19);
+	if (errno != EPIPE) e(20);
+	if (signumber != SIGPIPE) e(21);
+	if (close(fd) != 0) e(22);
+	exit(0);
+      default:
+	if ((fd = open("fifo", O_RDONLY)) != 3) e(23);
+	if (close(fd) != 0) e(24);
+	unlink("/tmp/sema.38e");
+	if (wait(&stat_loc) == -1) e(25);
+	if (stat_loc != 0) e(26);	/* Alarm? */
+  }
+
+#ifdef SIGACTION
+  /* Restore normal (re)action to SIGPIPE. */
+  if (sigaction(SIGPIPE, &oact, NULL) != 0) e(27);
+#else
+  signal(SIGPIPE, oldfunc);
+#endif
+
+  /* Read from fifo should return -1 and set errno to EAGAIN. */
+  System("rm -rf /tmp/sema.38[fgh]");
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	system("while test ! -f /tmp/sema.38f; do sleep 1; done");
+	System("rm -rf /tmp/sema.38f");
+	if ((fd = open("fifo", O_WRONLY | O_NONBLOCK)) != 3) e(28);
+	close(creat("/tmp/sema.38g", 0666));
+	system("while test ! -f /tmp/sema.38h; do sleep 1; done");
+	if (close(fd) != 0) e(38);
+	System("rm -rf /tmp/sema.38h");
+	exit(0);
+      default:
+	if ((fd = open("fifo", O_RDONLY | O_NONBLOCK)) != 3) e(30);
+	close(creat("/tmp/sema.38f", 0666));
+	system("while test ! -f /tmp/sema.38g; do sleep 1; done");
+	System("rm -rf /tmp/sema.38g");
+	if (read(fd, buf, BUF_SIZE) != -1) e(31);
+	if (errno != EAGAIN) e(32);
+	if (read(fd, buf, BUF_SIZE) != -1) e(33);
+	if (errno != EAGAIN) e(34);
+	if (read(fd, buf, BUF_SIZE) != -1) e(35);
+	if (errno != EAGAIN) e(36);
+	close(creat("/tmp/sema.38h", 0666));
+	while (stat("/tmp/sema.38h", &st) == 0) sleep(1);
+	if (read(fd, buf, BUF_SIZE) != 0) e(37);
+	if (close(fd) != 0) e(38);
+	if (wait(&stat_loc) == -1) e(39);
+	if (stat_loc != 0) e(40);	/* Alarm? */
+  }
+  System("rm -rf fifo");
+
+  /* If a read is interrupted by a SIGNAL. */
+  if (pipe(tube) != 0) e(41);
+  switch (pid = fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+#ifdef SIGACTION
+	act.sa_handler = setsignumber;
+	sigemptyset(&act.sa_mask);
+	act.sa_flags = 0;
+	if (sigaction(SIGUSR1, &act, &oact) != 0) e(42);
+#else
+	oldfunc = signal(SIGUSR1, setsignumber);
+#endif
+	if (read(tube[0], buf, BUF_SIZE) != -1) e(43);
+	if (errno != EINTR) e(44);
+	if (signumber != SIGUSR1) e(45);
+#ifdef SIGACTION
+	/* Restore normal (re)action to SIGPIPE. */
+	if (sigaction(SIGUSR1, &oact, NULL) != 0) e(46);
+#else
+	signal(SIGUSR1, oldfunc);
+#endif
+	close(tube[0]);
+	close(tube[1]);
+	exit(0);
+      default:
+	/* The sleep 1 should give the child time to start the read. */
+	sleep(1);
+	close(tube[0]);
+	kill(pid, SIGUSR1);
+	wait(&stat_loc);
+	if (stat_loc != 0) e(47);	/* Alarm? */
+	close(tube[1]);
+  }
+}
+
+void setsignumber(signum)
+int signum;
+{
+  signumber = signum;
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  Chdir("..");
+  System("rm -rf DIR_38");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test39.c
===================================================================
--- /trunk/minix/test/test39.c	(revision 9)
+++ /trunk/minix/test/test39.c	(revision 9)
@@ -0,0 +1,722 @@
+/* POSIX test program (39).			Author: Andy Tanenbaum */
+
+/* The following POSIX calls are tested:
+ *
+ *	opendir()
+ *	readdir()
+ *	rewinddir()
+ *	closedir()
+ *	chdir()
+ *	getcwd()
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <utime.h>
+#include <stdio.h>
+
+#define DIR_NULL (DIR*) NULL
+#define ITERATIONS         3	/* LINK_MAX is high, so time consuming */
+#define MAX_FD           100	/* must be large enough to cause error */
+#define BUF_SIZE PATH_MAX+20
+#define ERR_CODE          -1	/* error return */
+#define RD_BUF           200
+#define MAX_ERROR          4
+
+char str[] = {"The time has come the walrus said to talk of many things.\n"};
+char str2[] = {"Of ships and shoes and sealing wax, of cabbages and kings.\n"};
+char str3[] = {"Of why the sea is boiling hot and whether pigs have wings\n"};
+
+int subtest, errct;
+
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(void test39a, (void));
+_PROTOTYPE(void checkdir, (DIR *dirp, int t));
+_PROTOTYPE(void test39b, (void));
+_PROTOTYPE(void test39c, (void));
+_PROTOTYPE(void test39d, (void));
+_PROTOTYPE(void test39e, (void));
+_PROTOTYPE(void test39f, (void));
+_PROTOTYPE(void test39g, (void));
+_PROTOTYPE(void test39h, (void));
+_PROTOTYPE(void test39i, (void));
+_PROTOTYPE(void test39j, (void));
+_PROTOTYPE(void e, (int n));
+_PROTOTYPE(void quit, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+
+  int i, m = 0xFFFF;
+
+  sync();
+  if (geteuid() == 0 || getuid() == 0) {
+	printf("Test 39 cannot run as root; test aborted\n");
+	exit(1);
+  }
+
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 39 ");
+  fflush(stdout);
+
+  system("rm -rf DIR_39; mkdir DIR_39");
+  chdir("DIR_39");
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 00001) test39a();	/* test for correct operation */
+	if (m & 00002) test39b();	/* test general error handling */
+	if (m & 00004) test39c();	/* test for EMFILE error */
+	if (m & 00010) test39d();	/* test chdir() and getcwd() */
+	if (m & 00020) test39e();	/* test open() */
+	if (m & 00040) test39f();	/* test umask(), stat(), fstat() */
+	if (m & 00100) test39g();	/* test link() and unlink() */
+	if (m & 00200) test39h();	/* test access() */
+	if (m & 00400) test39i();	/* test chmod() and chown() */
+	if (m & 01000) test39j();	/* test utime() */
+  }
+  quit();
+  return(-1);			/* impossible */
+}
+
+void test39a()
+{
+/* Subtest 1. Correct operation */
+
+  int f1, f2, f3, f4, f5;
+  DIR *dirp;
+
+  /* Remove any residue of previous tests. */
+  subtest = 1;
+
+  system("rm -rf foo");
+
+  /* Create a directory foo with 5 files in it. */
+  mkdir("foo", 0777);
+  if ((f1 = creat("foo/f1", 0666)) < 0) e(1);
+  if ((f2 = creat("foo/f2", 0666)) < 0) e(2);
+  if ((f3 = creat("foo/f3", 0666)) < 0) e(3);
+  if ((f4 = creat("foo/f4", 0666)) < 0) e(4);
+  if ((f5 = creat("foo/f5", 0666)) < 0) e(5);
+
+  /* Now remove 2 files to create holes in the directory. */
+  if (unlink("foo/f2") < 0) e(6);
+  if (unlink("foo/f4") < 0) e(7);
+
+  /* Close the files. */
+  close(f1);
+  close(f2);
+  close(f3);
+  close(f4);
+  close(f5);
+
+  /* Open the directory. */
+  dirp = opendir("./foo");
+  if (dirp == DIR_NULL) e(6);
+
+  /* Read the 5 files from it. */
+  checkdir(dirp, 2); 
+
+  /* Rewind dir and test again. */
+  rewinddir(dirp);
+  checkdir(dirp, 3);
+
+  /* We're done.  Close the directory stream. */
+  if (closedir(dirp) < 0) e(7);
+
+  /* Remove dir for next time. */
+  system("rm -rf foo");
+}
+
+void checkdir(dirp, t)
+DIR *dirp;			/* poinrter to directory stream */
+int t;				/* subtest number to use */
+{
+
+  int i, f1, f2, f3, f4, f5, dot, dotdot, subt;
+  struct dirent *d;
+  char *s;
+
+  /* Save subtest number */
+  subt = subtest;
+  subtest = t;
+
+  /* Clear the counters. */
+  f1 = 0;
+  f2 = 0;
+  f3 = 0;
+  f4 = 0;
+  f5 = 0;
+  dot = 0;
+  dotdot = 0;
+
+  /* Read the directory.  It should contain 5 entries, ".", ".." and 3
+   * files. */
+  for (i = 0; i < 5; i++) {
+	d = readdir(dirp);
+	if (d == (struct dirent *) NULL) {
+		e(1);
+		subtest = subt;	/* restore subtest number */
+		return;
+	}
+	s = d->d_name;
+	if (strcmp(s, ".") == 0) dot++;
+	if (strcmp(s, "..") == 0) dotdot++;
+	if (strcmp(s, "f1") == 0) f1++;
+	if (strcmp(s, "f2") == 0) f2++;
+	if (strcmp(s, "f3") == 0) f3++;
+	if (strcmp(s, "f4") == 0) f4++;
+	if (strcmp(s, "f5") == 0) f5++;
+  }
+
+  /* Check results. */
+  d = readdir(dirp);
+  if (d != (struct dirent *) NULL) e(2);
+  if (f1 != 1 || f3 != 1 || f5 != 1) e(3);
+  if (f2 != 0 || f4 != 0) e(4);
+  if (dot != 1 || dotdot != 1) e(5);
+  subtest = subt;
+  return;
+}
+
+void test39b()
+{
+/* Subtest 4.  Test error handling. */
+
+  int fd;
+  DIR *dirp;
+
+  subtest = 4;
+
+  if (opendir("foo/xyz/---") != DIR_NULL) e(1);
+  if (errno != ENOENT) e(2);
+  if (mkdir("foo", 0777) < 0) e(3);
+  if (chmod("foo", 0) < 0) e(4);
+  if (opendir("foo/xyz/--") != DIR_NULL) e(5);
+  if (errno != EACCES) e(6);
+  if (chmod("foo", 0777) != 0) e(7);
+  if (rmdir("foo") != 0) e(8);
+  if ((fd = creat("abc", 0666)) < 0) e(9);
+  if (close(fd) < 0) e(10);
+  if (opendir("abc/xyz") != DIR_NULL) e(11);
+  if (errno != ENOTDIR) e(12);
+  if ((dirp = opendir(".")) == DIR_NULL) e(13);
+  if (closedir(dirp) != 0) e(14);
+  if (unlink("abc") != 0) e(15);
+
+}
+
+void test39c()
+{
+/* Subtest 5.  See what happens if we open too many directory streams. */
+
+  int i, j;
+  DIR *dirp[MAX_FD];
+
+  subtest = 5;
+
+  for (i = 0; i < MAX_FD; i++) {
+	dirp[i] = opendir(".");
+	if (dirp[i] == (DIR *) NULL) {
+		/* We have hit the limit. */
+		if (errno != EMFILE && errno != ENOMEM) e(1);
+		for (j = 0; j < i; j++) {
+			if (closedir(dirp[j]) != 0) e(2);	/* close */
+		}
+		return;
+	}
+  }
+
+  /* Control should never come here.  This is an error. */
+  e(3);
+  for (i = 0; i < MAX_FD; i++) closedir(dirp[i]);	/* don't check */
+}
+
+void test39d()
+{
+/* Test chdir and getcwd(). */
+
+  int fd;
+  char *s;
+  char base[BUF_SIZE], buf2[BUF_SIZE], tmp[BUF_SIZE];
+
+  subtest = 6;
+
+  if (getcwd(base, BUF_SIZE) == (char *) NULL) e(1); /* get test dir's path */
+  if (system("rm -rf Dir") != 0) e(2);	/* remove residue of previous test */
+  if (mkdir("Dir", 0777) < 0) e(3); 	/* create directory called "Dir" */
+
+  /* Change to Dir and verify that it worked. */
+  if (chdir("Dir") < 0) e(4);	/* go to Dir */
+  s = getcwd(buf2, BUF_SIZE);	/* get full path of Dir */
+  if (s == (char *) NULL) e(5);	/* check for error return */
+  if (s != buf2) e(6);		/* if successful, first arg is returned */
+  strcpy(tmp, base);		/* concatenate base name and "/Dir" */
+  strcat(tmp, "/");
+  strcat(tmp, "Dir");
+  if (strcmp(tmp, s) != 0) e(7);
+
+  /* Change to ".." and verify that it worked. */
+  if (chdir("..") < 0) e(8);
+  if (getcwd(buf2, BUF_SIZE) != buf2) e(9);
+  if (strcmp(buf2, base) != 0) e(10);
+
+  /* Now make calls that do nothing, but do it in a strange way. */
+  if (chdir("Dir/..") < 0) e(11);
+  if (getcwd(buf2, BUF_SIZE) != buf2) e(12);
+  if (strcmp(buf2, base) != 0) e(13);
+
+  if (chdir("Dir/../Dir/..") < 0) e(14);
+  if (getcwd(buf2, BUF_SIZE) != buf2) e(15);
+  if (strcmp(buf2, base) != 0) e(16);
+
+  if (chdir("Dir/../Dir/../Dir/../Dir/../Dir/../Dir/../Dir/..") < 0) e(17);
+  if (getcwd(buf2, BUF_SIZE) != buf2) e(18);
+  if (strcmp(buf2, base) != 0) e(19);
+
+  /* Make Dir unreadable and unsearchable.  Check error message. */
+  if (chmod("Dir", 0) < 0) e(20);
+  if (chdir("Dir") >= 0) e(21);
+  if (errno != EACCES) e(22);
+
+  /* Check error message for bad path. */
+  if (chmod("Dir", 0777) < 0) e(23);
+  if (chdir("Dir/x/y") != ERR_CODE) e(24);
+  if (errno != ENOENT) e(25);
+
+  if ( (fd=creat("Dir/x", 0777)) < 0) e(26);
+  if (close(fd) != 0) e(27);
+  if (chdir("Dir/x/y") != ERR_CODE) e(28);
+  if (errno != ENOTDIR) e(29);  
+
+  /* Check empty string. */
+  if (chdir("") != ERR_CODE) e(30);
+  if (errno != ENOENT) e(31);
+
+  /* Remove the directory. */
+  if (unlink("Dir/x") != 0) e(32);
+  if (system("rmdir Dir") != 0) e(33);
+}
+
+void test39e()
+{
+/* Test open. */
+
+  int fd, bytes, bytes2;
+  char buf[RD_BUF];
+
+  subtest = 7;
+
+  unlink("T39");		/* get rid of it in case it exists */
+
+  /* Create a test file. */
+  bytes = strlen(str);
+  bytes2 = strlen(str2);
+  if ((fd = creat("T39", 0777)) < 0) e(1);
+  if (write(fd, str, bytes) != bytes) e(2);	/* T39 now has 'bytes' bytes */
+  if (close(fd) != 0) e(3);
+
+  /* Test opening a file with O_RDONLY. */
+  if ((fd = open("T39", O_RDONLY)) < 0) e(4);
+  buf[0] = '\0';
+  if (read(fd, buf, RD_BUF) != bytes) e(5);
+  if (strncmp(buf, str, bytes) != 0) e(6);
+  if (close(fd) < 0) e(7);
+
+  /* Test the same thing, only with O_RDWR now. */
+  if ((fd = open("T39", O_RDWR)) < 0) e(8);
+  buf[0] = '\0';
+  if (read(fd, buf, RD_BUF) != bytes) e(9);
+  if (strncmp(buf, str, bytes) != 0) e(10);
+  if (close(fd) < 0) e(11);
+
+  /* Try opening and reading with O_WRONLY.  It should fail. */
+  if ((fd = open("T39", O_WRONLY)) < 0) e(12);
+  buf[0] = '\0';
+  if (read(fd, buf, RD_BUF) >= 0) e(13);
+  if (close(fd) != 0) e(14);
+
+  /* Test O_APPEND. */
+  if ((fd = open("T39", O_RDWR | O_APPEND)) < 0) e(15);
+  if (lseek(fd, 0L, SEEK_SET) < 0) e(16);	/* go to start of file */
+  if ( write(fd, str2, bytes2) != bytes2) e(17); /* write at start of file */
+  if (lseek(fd, 0L, SEEK_SET) < 0) e(18); 	/* go back to start again */
+  if (read(fd, buf, RD_BUF) != bytes + bytes2) e(19); /* read whole file */
+  if (strncmp(buf, str, bytes) != 0) e(20);
+  if (close(fd) != 0) e(21);
+
+  /* Get rid of the file. */
+  if (unlink("T39") < 0) e(22);
+}
+
+void test39f()
+{
+/* Test stat, fstat, umask. */
+  int i, fd;
+  mode_t m1;
+  struct stat stbuf1, stbuf2;
+  time_t t, t1;
+
+  subtest = 8;
+
+  m1 = umask(~0777);
+  if (system("rm -rf foo xxx") != 0) e(1);
+  if ((fd = creat("foo", 0777)) < 0) e(2);
+  if (stat("foo", &stbuf1) < 0) e(3);
+  if (fstat(fd, &stbuf2) < 0) e(4);
+  if (stbuf1.st_mode != stbuf2.st_mode) e(5);
+  if (stbuf1.st_ino != stbuf2.st_ino) e(6);
+  if (stbuf1.st_dev != stbuf2.st_dev) e(7);
+  if (stbuf1.st_nlink != stbuf2.st_nlink) e(8);
+  if (stbuf1.st_uid != stbuf2.st_uid) e(9);
+  if (stbuf1.st_gid != stbuf2.st_gid) e(10);
+  if (stbuf1.st_size != stbuf2.st_size) e(11);
+  if (stbuf1.st_atime != stbuf2.st_atime) e(12);
+  if (stbuf1.st_mtime != stbuf2.st_mtime) e(13);
+  if (stbuf1.st_ctime != stbuf2.st_ctime) e(14);
+
+  if (!S_ISREG(stbuf1.st_mode)) e(15);
+  if (S_ISDIR(stbuf1.st_mode)) e(16);
+  if (S_ISCHR(stbuf1.st_mode)) e(17);
+  if (S_ISBLK(stbuf1.st_mode)) e(18);
+  if (S_ISFIFO(stbuf1.st_mode)) e(19);
+
+  if ((stbuf1.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) != 0777) e(20);
+  if (stbuf1.st_nlink != 1) e(21);
+  if (stbuf1.st_uid != getuid()) e(22);
+  if (stbuf1.st_gid != getgid()) e(23);
+  if (stbuf1.st_size != 0L) e(24);
+
+  /* First unlink, then close -- harder test */
+  if (unlink("foo") < 0) e(25);
+  if (close(fd) < 0) e(26);
+
+  /* Now try umask a bit more. */
+  fd = 0;
+  if ((i = umask(~0704)) != 0) e(27);
+  if ((fd = creat("foo", 0777)) < 0) e(28);
+  if (stat("foo", &stbuf1) < 0) e(29);
+  if (fstat(fd, &stbuf2) < 0) e(30);
+  if (stbuf1.st_mode != stbuf2.st_mode) e(31);
+  if ((stbuf1.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) != 0704) e(32);
+
+  /* First unlink, then close -- harder test */
+  if (unlink("foo") < 0) e(33);
+  if (close(fd) < 0) e(34);
+  if (umask(m1) != 073) e(35);
+
+  /* Test some errors. */
+  if (system("mkdir Dir; date >Dir/x; chmod 666 Dir") != 0) e(36);
+  if (stat("Dir/x", &stbuf1) >= 0) e(37);
+  if (errno != EACCES) e(38);
+  if (stat("......", &stbuf1) >= 0) e(39);
+  if (errno != ENOENT) e(40);
+  if (stat("", &stbuf1) >= 0) e(41);
+  if (errno != ENOENT) e(42);
+  if (stat("xxx/yyy/zzz", &stbuf1) >= 0) e(43);
+  if (errno != ENOENT) e(44);
+  if (fstat(10000, &stbuf1) >= 0) e(45);
+  if (errno != EBADF) e(46);
+  if (chmod("Dir", 0777) != 0) e(47);
+  if (system("rm -rf foo Dir") != 0) e(48);
+
+  /* See if time looks reasonable. */
+  errno = 0;
+  t = time(&t1);		/* current time */
+  if (t < 650000000L) e(49);	/* 650000000 is Sept. 1990 */
+  unlink("T39f");
+  fd = creat("T39f", 0777);
+  if (fd < 0) e(50);
+  if (close(fd) < 0) e(51);
+  if (stat("T39f", &stbuf1) < 0) e(52);
+  if (stbuf1.st_mtime < t) e(53);
+  if (unlink("T39f") < 0) e(54);
+}
+
+void test39g()
+{
+/* Test link and unlink. */
+  int i, fd;
+  struct stat stbuf;
+  char name[20];
+
+  subtest = 9;
+
+  if (system("rm -rf L? L?? Dir; mkdir Dir") != 0) e(1);
+  if ( (fd = creat("L1", 0666)) < 0) e(2);
+  if (fstat(fd, &stbuf) != 0) e(3);
+  if (stbuf.st_nlink != 1) e(4);
+  if (link("L1", "L2") != 0) e(5);
+  if (fstat(fd, &stbuf) != 0) e(6);
+  if (stbuf.st_nlink != 2) e(7);
+  if (unlink("L2") != 0) e(8);
+  if (link("L1", "L2") != 0) e(9);
+  if (unlink("L1") != 0) e(10);
+  if (close(fd) != 0) e(11);
+
+  /* L2 exists at this point. */
+  if ( (fd = creat("L1", 0666)) < 0) e(12);
+  if (stat("L1", &stbuf) != 0) e(13);
+  if (stbuf.st_nlink != 1) e(14);
+  if (link("L1", "Dir/L2") != 0) e(15);
+  if (stat("L1", &stbuf) != 0) e(16);
+  if (stbuf.st_nlink != 2) e(17);
+  if (stat("Dir/L2", &stbuf) != 0) e(18);
+  if (stbuf.st_nlink != 2) e(19);
+
+  /* L1, L2, and Dir/L2 exist at this point. */
+  if (unlink("Dir/L2") != 0) e(20);
+  if (link("L1", "Dir/L2") != 0) e(21);
+  if (unlink("L1") != 0) e(22);
+  if (close(fd) != 0) e(23);
+  if (chdir("Dir") != 0) e(24);
+  if (unlink("L2") != 0) e(25);
+  if (chdir("..") != 0) e(26);
+  
+  /* L2 exists at this point. Test linking to unsearchable dir. */
+  if (link("L2", "Dir/L2") != 0) e(27);
+  if (chmod("Dir", 0666) != 0) e(27);
+  if (link("L2", "Dir/L2") != -1) e(28);
+  if (errno != EACCES) e(29);
+  errno = 0;
+  if (link("Dir/L2", "L3") != -1) e(30);
+  if (errno != EACCES) e(31);
+  if (chmod("Dir", 0777) != 0) e(32);
+  if (unlink("Dir/L2") != 0) e(33);
+  if (unlink("L3") == 0) e(34);
+
+  /* L2 exists at this point. Test linking to unwriteable dir. */
+  if (chmod("Dir", 0555) != 0) e(35);
+  if (link("L2", "Dir/L2") != -1) e(36);
+  if (errno != EACCES) e(37);
+  if (chmod("Dir", 0777) != 0) e(38);
+
+  /* L2 exists at this point.  Test linking mode 0 file. */
+  if (chmod("L2", 0) != 0) e(39);
+  if (link("L2", "L3") != 0) e(40);
+  if (stat("L3", &stbuf) != 0) e(41);
+  if (stbuf.st_nlink != 2) e(42);
+  if (unlink("L2") != 0) e(43);
+
+  /* L3 exists at this point.  Test linking to an existing file. */
+  if ( (fd = creat("L1", 0666)) < 0) e(44);
+  if (link("L1", "L3") != -1) e(45);
+  if (errno != EEXIST) e(46);
+  errno = 0;
+  if (link("L1", "L1") != -1) e(47);
+  if (errno != EEXIST) e(48);
+  if (unlink("L3") != 0) e(49);
+
+  /* L1 exists at this point. Test creating too many links. */
+  for (i = 2; i <= LINK_MAX; i++) {
+	sprintf(name, "Lx%d", i);
+	if (link("L1", name) != 0) e(50);
+  }
+  if (stat("L1", &stbuf) != 0) e(51);
+  if (stbuf.st_nlink != LINK_MAX) e(52);
+  if (link("L1", "L2") != -1) e(53);
+  if (errno != EMLINK) e(54);
+  for (i = 2; i <= LINK_MAX; i++) {
+	sprintf(name, "Lx%d", i);
+	if (unlink(name) != 0) e(55);
+  }
+
+  if (stat("L1", &stbuf) != 0) e(56);
+  if (stbuf.st_nlink != 1) e(57);
+
+  /* L1 exists.  Test ENOENT. */
+  errno = 0;
+  if (link("xx/L1", "L2") != -1) e(58);
+  if (errno != ENOENT) e(59);
+  errno = 0;
+  if (link("L1", "xx/L2") != -1) e(60);
+  if (errno != ENOENT) e(61);
+  errno = 0;
+  if (link("L4", "L5") != -1) e(62);
+  if (errno != ENOENT) e(63);
+  errno = 0;
+  if (link("", "L5") != -1) e(64);
+  if (errno != ENOENT) e(65);
+  errno = 0;
+  if (link("L1", "") != -1) e(66);
+  if (errno != ENOENT) e(67);
+
+  /* L1 exists.  Test ENOTDIR. */
+  errno = 0;
+  if (link("/dev/tty/x", "L2") != -1) e(68);
+  if (errno != ENOTDIR) e(69);
+
+  /* L1 exists.  Test EPERM. */
+  if (link(".", "L2") != -1) e(70);
+  if (errno != EPERM) e(71);
+
+  /* L1 exists. Test unlink. */
+  if (link("L1", "Dir/L1") != 0) e(72);
+  if (chmod("Dir", 0666) != 0) e(73);
+  if (unlink("Dir/L1") != -1) e(74);
+  if (errno != EACCES) e(75);
+  errno = 0;
+  if (chmod("Dir", 0555) != 0) e(76);
+  if (unlink("Dir/L1") != -1) e(77);
+  if (errno != EACCES) e(78);
+
+  if (unlink("L7") != -1) e(79);
+  if (errno != ENOENT) e(80);
+  errno = 0;
+  if (unlink("") != -1) e(81);
+  if (errno != ENOENT) e(82);
+
+  if (unlink("Dir/L1/L2") != -1) e(83);
+  if (errno != ENOTDIR) e(84);
+ 
+  if (chmod("Dir", 0777) != 0) e(85);
+  if (unlink("Dir/L1") != 0) e(86);
+  if (unlink("Dir") != -1) e(87);
+  if (errno != EPERM) e(88);
+  if (unlink("L1") != 0) e(89);
+  if (system("rm -rf Dir") != 0) e(90);
+  if (close(fd) != 0) e(91);  
+}
+
+void test39h()
+{
+/* Test access. */
+
+  int fd;
+
+  subtest = 10;
+  system("rm -rf A1");
+  if ( (fd = creat("A1", 0777)) < 0) e(1);
+  if (close(fd) != 0) e(2);
+  if (access("A1", R_OK) != 0) e(3);
+  if (access("A1", W_OK) != 0) e(4);
+  if (access("A1", X_OK) != 0) e(5);
+  if (access("A1", (R_OK|W_OK|X_OK)) != 0) e(6);
+  
+  if (chmod("A1", 0400) != 0) e(7);
+  if (access("A1", R_OK) != 0) e(8);
+  if (access("A1", W_OK) != -1) e(9);
+  if (access("A1", X_OK) != -1) e(10);
+  if (access("A1", (R_OK|W_OK|X_OK)) != -1) e(11);
+  
+  if (chmod("A1", 0077) != 0) e(12);
+  if (access("A1", R_OK) != -1) e(13);
+  if (access("A1", W_OK) != -1) e(14);
+  if (access("A1", X_OK) != -1) e(15);
+  if (access("A1", (R_OK|W_OK|X_OK)) != -1) e(16);
+  if (errno != EACCES) e(17);
+
+  if (access("", R_OK) != -1) e(18);
+  if (errno != ENOENT) e(19);
+  if (access("./A1/x", R_OK) != -1) e(20);
+  if (errno != ENOTDIR) e(21);
+
+  if (unlink("A1") != 0) e(22);
+}
+
+void test39i()
+{
+/* Test chmod. */
+
+  int fd, i;
+  struct stat stbuf;
+
+  subtest = 11;
+  system("rm -rf A1");
+  if ( (fd = creat("A1", 0777)) < 0) e(1);
+
+  for (i = 0; i < 511; i++) {
+	if (chmod("A1", i) != 0) e(100+i);
+	if (fstat(fd, &stbuf) != 0) e(200+i);
+	if ( (stbuf.st_mode&(S_IRWXU|S_IRWXG|S_IRWXO)) != i) e(300+i);
+  }
+  if (close(fd) != 0) e(2);
+
+  if (chmod("A1/x", 0777) != -1) e(3);
+  if (errno != ENOTDIR) e(4);
+  if (chmod("Axxx", 0777) != -1) e(5);
+  if (errno != ENOENT) e(6);
+  errno = 0;
+  if (chmod ("", 0777) != -1) e(7);
+  if (errno != ENOENT) e(8);
+
+  /* Now perform limited chown tests.  These should work even as non su */
+  i = getuid();
+/* DEBUG -- Not yet implemented 
+  if (chown("A1", i, 0) != 0) e(9);
+  if (chown("A1", i, 1) != 0) e(10);
+  if (chown("A1", i, 2) != 0) e(11);
+  if (chown("A1", i, 3) != 0) e(12);
+  if (chown("A1", i, 4) != 0) e(13);
+  if (chown("A1", i, 0) != 0) e(14);
+*/
+
+  if (unlink("A1") != 0) e(9);
+}
+
+void test39j()
+{
+/* Test utime. */
+
+  int fd;
+  time_t tloc;
+  struct utimbuf times;
+  struct stat stbuf;
+
+  subtest = 12;
+  if (system("rm -rf A2") != 0) e(1);
+  if ( (fd = creat("A2", 0666)) < 0) e(2);
+  times.modtime = 100;
+  if (utime("A2", &times) != 0) e(3);
+  if (stat("A2", &stbuf) != 0) e(4);
+  if (stbuf.st_mtime != 100) e(5);
+
+  tloc = time((time_t *)NULL);		/* get current time */
+  times.modtime = tloc;
+  if (utime("A2", &times) != 0) e(6);
+  if (stat("A2", &stbuf) != 0) e(7);
+  if (stbuf.st_mtime != tloc) e(8);
+  if (close(fd) != 0) e(9);
+  if (unlink("A2") != 0) e(10);
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* save errno in case printf clobbers it */
+
+  printf("Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
+  fflush(stdout);		/* stdout and stderr are mixed horribly */
+  errno = err_num;		/* restore errno, just in case */
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test4.c
===================================================================
--- /trunk/minix/test/test4.c	(revision 9)
+++ /trunk/minix/test/test4.c	(revision 9)
@@ -0,0 +1,103 @@
+/* test 4 */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+pid_t pid0, pid1, pid2, pid3;
+int s, i, fd, nextb, errct = 0;
+char *tempfile = "test4.temp";
+char buf[1024];
+extern int errno;
+
+_PROTOTYPE(int main, (void));
+_PROTOTYPE(void subr, (void));
+_PROTOTYPE(void nofork, (void));
+_PROTOTYPE(void quit, (void));
+
+int main()
+{
+  int k;
+
+  printf("Test  4 ");
+  fflush(stdout);		/* have to flush for child's benefit */
+
+  system("rm -rf DIR_04; mkdir DIR_04");
+  chdir("DIR_04");
+
+  creat(tempfile, 0777);
+  for (k = 0; k < 20; k++) {
+	subr();
+  }
+  unlink(tempfile);
+  quit();
+  return(-1);			/* impossible */
+}
+
+void subr()
+{
+  if ( (pid0 = fork()) != 0) {
+	/* Parent 0 */
+	if (pid0 < 0) nofork();
+	if ( (pid1 = fork()) != 0) {
+		/* Parent 1 */
+		if (pid1 < 0) nofork();
+		if ( (pid2 = fork()) != 0) {
+			/* Parent 2 */
+			if (pid2 < 0) nofork();
+			if ( (pid3 = fork()) != 0) {
+				/* Parent 3 */
+				if (pid3 < 0) nofork();
+				for (i = 0; i < 10000; i++);
+				kill(pid2, 9);
+				kill(pid1, 9);
+				kill(pid0, 9);
+				wait(&s);
+				wait(&s);
+				wait(&s);
+				wait(&s);
+			} else {
+				fd = open(tempfile, O_RDONLY);
+				lseek(fd, 20480L * nextb, 0);
+				for (i = 0; i < 10; i++) read(fd, buf, 1024);
+				nextb++;
+				close(fd);
+				exit(0);
+			}
+		} else {
+			while (1) getpid();
+		}
+	} else {
+		while (1) getpid();
+	}
+  } else {
+	while (1) getpid();
+  }
+}
+
+void nofork()
+{
+  int e = errno;
+  printf("Fork failed: %s (%d)\n",strerror(e),e);
+  exit(1);
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test40.c
===================================================================
--- /trunk/minix/test/test40.c	(revision 9)
+++ /trunk/minix/test/test40.c	(revision 9)
@@ -0,0 +1,340 @@
+/* test40: link() unlink()	Aithor: Jan-Mark Wams (jms@cs.vu.nl) */
+
+/*
+ * Not tested readonly file systems
+ * Not tested fs full
+ * Not tested unlinking bussy files
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+int errct = 0;
+int subtest = 1;
+int superuser;
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];		/* Same for path */
+char ToLongName[NAME_MAX + 2];	/* Name of maximum +1 length */
+char ToLongPath[PATH_MAX + 1];	/* Same for path, both too long */
+
+#define MAX_ERROR 4
+#define ITERATIONS 2		/* LINK_MAX is high, so time consuming. */
+
+#define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
+#define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
+#define Stat(a,b)	if (stat(a,b) != 0) printf("Can't stat %s\n", a)
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test40a, (void));
+_PROTOTYPE(void test40b, (void));
+_PROTOTYPE(void test40c, (void));
+_PROTOTYPE(int stateq, (struct stat *stp1, struct stat *stp2));
+_PROTOTYPE(void makelongnames, (void));
+_PROTOTYPE(void e, (int __n));
+_PROTOTYPE(void quit, (void));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test 40 ");
+  fflush(stdout);
+  System("rm -rf DIR_40; mkdir DIR_40");
+  Chdir("DIR_40");
+  superuser = (getuid() == 0);
+  makelongnames();
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test40a();
+	if (m & 0002) test40b();
+	if (m & 0004) test40c();
+  }
+  quit();
+}
+
+void test40a()
+{				/* Test normal operation. */
+  struct stat st1, st2, st3;
+  time_t time1;
+
+  subtest = 1;
+
+  /* Clean up any residu. */
+  System("rm -rf ../DIR_40/*");
+
+  System("touch foo");		/* make source file */
+  Stat("foo", &st1);		/* get info of foo */
+  Stat(".", &st2);		/* and the cwd */
+  time(&time1);
+  while (time1 >= time((time_t *)0))
+	;			/* wait a sec */
+  if (link("foo", "bar") != 0) e(1);	/* link foo to bar */
+  Stat("foo", &st3);		/* get new status */
+  if (st1.st_nlink + 1 != st3.st_nlink) e(2);	/* link count foo up 1 */
+#ifndef V1_FILESYSTEM
+  if (st1.st_ctime >= st3.st_ctime) e(3);	/* check stattime changed */
+#endif
+  Stat(".", &st1);		/* get parend dir info */
+  if (st2.st_ctime >= st1.st_ctime) e(4);	/* ctime and mtime */
+  if (st2.st_mtime >= st1.st_mtime) e(5);	/* should be updated */
+  Stat("bar", &st2);		/* get info of bar */
+  if (st2.st_nlink != st3.st_nlink) e(6);	/* link count foo == bar */
+  if (st2.st_ino != st3.st_ino) e(7);	/* ino should be same */
+  if (st2.st_mode != st3.st_mode) e(8);	/* check mode same */
+  if (st2.st_uid != st3.st_uid) e(9);	/* check uid same */
+  if (st2.st_gid != st3.st_gid) e(10);	/* check gid same */
+  if (st2.st_size != st3.st_size) e(11);	/* check size */
+  if (st2.st_ctime != st3.st_ctime) e(12);	/* check ctime */
+  if (st2.st_atime != st3.st_atime) e(13);	/* check atime */
+  if (st2.st_mtime != st3.st_mtime) e(14);	/* check mtime */
+  Stat("foo", &st1);		/* get fooinfo */
+  Stat(".", &st2);		/* get dir info */
+  time(&time1);
+  while (time1 >= time((time_t *)0))
+	;			/* wait a sec */
+  if (unlink("bar") != 0) e(15);/* rm bar */
+  if (stat("bar", &st2) != -1) e(16);	/* it's gone */
+  Stat("foo", &st3);		/* get foo again */
+  if (st1.st_nlink != st3.st_nlink + 1) e(17);	/* link count back to normal */
+#ifndef V1_FILESYSTEM
+  if (st1.st_ctime >= st3.st_ctime) e(18);	/* check ctime */
+#endif
+  Stat(".", &st3);		/* get parend dir info */
+  if (st2.st_ctime >= st3.st_ctime) e(19);	/* ctime and mtime */
+  if (st2.st_mtime >= st3.st_mtime) e(20);	/* should be updated */
+}
+
+void test40b()
+{
+  register int nlink;
+  char bar[30];
+  struct stat st, st2;
+
+  subtest = 2;
+
+  /* Clean up any residu. */
+  System("rm -rf ../DIR_40/*");
+
+  /* Test what happens if we make LINK_MAX number of links. */
+  System("touch foo");
+  for (nlink = 2; nlink <= LINK_MAX; nlink++) {
+  	sprintf(bar, "bar.%d", nlink);
+	if (link("foo", bar) != 0) e(2);
+	Stat(bar, &st);
+	if (st.st_nlink != nlink) e(3);
+	Stat("foo", &st);
+	if (st.st_nlink != nlink) e(4);
+  }
+
+  /* Check if we have LINK_MAX links that are all the same. */
+  Stat("foo", &st);
+  if (st.st_nlink != LINK_MAX) e(5);
+  for (nlink = 2; nlink <= LINK_MAX; nlink++) {
+  	sprintf(bar, "bar.%d", nlink);
+	Stat(bar, &st2);
+	if (!stateq(&st, &st2)) e(6);
+  }
+
+  /* Test no more links are possible. */
+  if (link("foo", "nono") != -1) e(7);
+  if (stat("nono", &st) != -1) e(8);
+  Stat("foo", &st);
+  if (st.st_nlink != LINK_MAX) e(9);	/* recheck the number of links */
+
+  /* Now unlink() the bar.### files */
+  for (nlink = LINK_MAX; nlink >= 2; nlink--) {
+  	sprintf(bar, "bar.%d", nlink);
+	Stat(bar, &st);
+	if (st.st_nlink != nlink) e(10);
+	Stat("foo", &st2);
+	if (!stateq(&st, &st2)) e(11);
+	if (unlink(bar) != 0) e(12);
+  }
+  Stat("foo", &st);
+  if (st.st_nlink != 1) e(13);	/* number of links back to 1 */
+
+  /* Test max path ed. */
+  if (link("foo", MaxName) != 0) e(14);	/* link to MaxName */
+  if (unlink(MaxName) != 0) e(15);	/* and remove it */
+  MaxPath[strlen(MaxPath) - 2] = '/';
+  MaxPath[strlen(MaxPath) - 1] = 'a';	/* make ././.../a */
+  if (link("foo", MaxPath) != 0) e(16);	/* it should be */
+  if (unlink(MaxPath) != 0) e(17);	/* (un)linkable */
+
+  System("rm -f ../DIR_40/*");	/* clean cwd */
+}
+
+void test40c()
+{
+  subtest = 3;
+
+  /* Clean up any residu. */
+  System("rm -rf ../DIR_40/*");
+
+  /* Check some simple things. */
+  if (link("bar/nono", "nono") != -1) e(1);	/* nonexistent */
+  if (errno != ENOENT) e(2);
+  Chdir("..");
+  System("touch DIR_40/foo");
+  System("chmod 677 DIR_40");	/* make inaccesable */
+  if (!superuser) {
+	if (unlink("DIR_40/foo") != -1) e(3);
+	if (errno != EACCES) e(4);
+  }
+  if (link("DIR_40/bar/nono", "DIR_40/nono") != -1) e(5); /* nono no be */
+  if (superuser) {
+	if (errno != ENOENT) e(6);	/* su has access */
+  }
+  if (!superuser) {
+	if (errno != EACCES) e(7);	/* we don't ;-) */
+  }
+  System("chmod 577 DIR_40");	/* make unwritable */
+  if (superuser) {
+	if (link("DIR_40/foo", "DIR_40/nono") != 0) e(8);
+	if (unlink("DIR_40/nono") != 0) e(9);
+  }
+  if (!superuser) {
+	if (link("DIR_40/foo", "DIR_40/nono") != -1) e(10);
+	if (errno != EACCES) e(11);
+	if (unlink("DIR_40/foo") != -1) e(12);	/* try to rm foo/foo */
+	if (errno != EACCES) e(13);
+  }
+  System("chmod 755 DIR_40");	/* back to normal */
+  Chdir("DIR_40");
+
+  /* Too-long path and name test */
+  ToLongPath[strlen(ToLongPath) - 2] = '/';
+  ToLongPath[strlen(ToLongPath) - 1] = 'a';	/* make ././.../a */
+  if (link("foo", ToLongPath) != -1) e(18);	/* path is too long */
+  if (errno != ENAMETOOLONG) e(19);
+  if (unlink(ToLongPath) != -1) e(20);	/* path is too long */
+  if (errno != ENAMETOOLONG) e(21);
+  if (link("foo", "foo") != -1) e(22);	/* try linking foo to foo */
+  if (errno != EEXIST) e(23);
+  if (link("foo", "bar") != 0) e(24);	/* make a link to bar */
+  if (link("foo", "bar") != -1) e(25);	/* try linking to bar again */
+  if (errno != EEXIST) e(26);
+  if (link("foo", "bar") != -1) e(27);	/* try linking to bar again */
+  if (errno != EEXIST) e(28);
+  if (unlink("nono") != -1) e(29);	/* try rm <not exist> */
+  if (errno != ENOENT) e(30);
+  if (unlink("") != -1) e(31);	/* try unlinking empty */
+  if (errno != ENOENT) e(32);
+  if (link("foo", "") != -1) e(33);	/* try linking to "" */
+  if (errno != ENOENT) e(34);
+  if (link("", "foo") != -1) e(35);	/* try linking "" */
+  if (errno != ENOENT) e(36);
+  if (link("", "") != -1) e(37);/* try linking "" to "" */
+  if (errno != ENOENT) e(38);
+  if (link("/foo/bar/foo", "a") != -1) e(39);	/* try no existing path */
+  if (errno != ENOENT) e(40);
+  if (link("foo", "/foo/bar/foo") != -1) e(41);	/* try no existing path */
+  if (errno != ENOENT) e(42);
+  if (link("/a/b/c", "/d/e/f") != -1) e(43);	/* try no existing path */
+  if (errno != ENOENT) e(44);
+  if (link("abc", "a") != -1) e(45);	/* try no existing file */
+  if (errno != ENOENT) e(46);
+  if (link("foo/bar", "bar") != -1) e(47);	/* foo is a file */
+  if (errno != ENOTDIR) e(48);
+  if (link("foo", "foo/bar") != -1) e(49);	/* foo is not a dir */
+  if (errno != ENOTDIR) e(50);
+  if (unlink("foo/bar") != -1) e(51);	/* foo still no dir */
+  if (errno != ENOTDIR) e(52);
+  if (!superuser) {
+	if (link(".", "root") != -1) e(55);
+	if (errno != EPERM) e(56);	/* noroot can't */
+	if (unlink("root") != -1) e(57);
+	if (errno != ENOENT) e(58);
+  }
+  if (mkdir("dir", 0777) != 0) e(59);
+  if (superuser) {
+	if (rmdir("dir") != 0) e(63);
+  }
+  if (!superuser) {
+	if (unlink("dir") != -1) e(64);
+	if (errno != EPERM) e(65);	/* that ain't w'rkn */
+	if (rmdir("dir") != 0) e(66);	/* that's the way to do it */
+  }
+}
+
+int stateq(stp1, stp2)
+struct stat *stp1, *stp2;
+{
+  if (stp1->st_dev != stp2->st_dev) return 0;
+  if (stp1->st_ino != stp2->st_ino) return 0;
+  if (stp1->st_mode != stp2->st_mode) return 0;
+  if (stp1->st_nlink != stp2->st_nlink) return 0;
+  if (stp1->st_uid != stp2->st_uid) return 0;
+  if (stp1->st_gid != stp2->st_gid) return 0;
+  if (stp1->st_rdev != stp2->st_rdev) return 0;
+  if (stp1->st_size != stp2->st_size) return 0;
+  if (stp1->st_atime != stp2->st_atime) return 0;
+  if (stp1->st_mtime != stp2->st_mtime) return 0;
+  if (stp1->st_ctime != stp2->st_ctime) return 0;
+  return 1;
+}
+
+void makelongnames()
+{
+  register int i;
+
+  memset(MaxName, 'a', NAME_MAX);
+  MaxName[NAME_MAX] = '\0';
+  for (i = 0; i < PATH_MAX - 1; i++) {	/* idem path */
+	MaxPath[i++] = '.';
+	MaxPath[i] = '/';
+  }
+  MaxPath[PATH_MAX - 1] = '\0';
+
+  strcpy(ToLongName, MaxName);	/* copy them Max to ToLong */
+  strcpy(ToLongPath, MaxPath);
+
+  ToLongName[NAME_MAX] = 'a';
+  ToLongName[NAME_MAX + 1] = '\0';	/* extend ToLongName by one
+					 * too many */
+  ToLongPath[PATH_MAX - 1] = '/';
+  ToLongPath[PATH_MAX] = '\0';	/* inc ToLongPath by one */
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  chdir("..");
+  system("rm -rf DIR_40");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test41.c
===================================================================
--- /trunk/minix/test/test41.c	(revision 9)
+++ /trunk/minix/test/test41.c	(revision 9)
@@ -0,0 +1,38 @@
+
+#include <stdio.h>
+#include <minix/endpoint.h>
+#include <minix/sys_config.h>
+
+int main(int argc, char *argv[])
+{
+	int g, p;
+
+	printf("Test 41 ");
+
+	for(g = 0; g <= _ENDPOINT_MAX_GENERATION; g++) {
+		for(p = -NR_TASKS; p < _NR_PROCS; p++) {
+			int e, mg, mp;
+			e = _ENDPOINT(g, p);
+			mg = _ENDPOINT_G(e);
+			mp = _ENDPOINT_P(e);
+			if(mg != g || mp != p)  {
+				printf("%d != %d || %d != %d\n", mg, g, mp, p);
+				return 1;
+			}
+			if(g == 0 && e != p) {
+				printf("%d != %d and g=0\n", e, p);
+				return 1;
+			}
+			if(e == ANY || e == SELF || e == NONE) {
+				printf("endpoint (%d,%d) is %d; ANY, SELF or NONE\n",
+					g, p, e);
+				return 1;
+			}
+		}
+	}
+
+	printf("ok\n");
+
+	return 0;
+}
+
Index: /trunk/minix/test/test5.c
===================================================================
--- /trunk/minix/test/test5.c	(revision 9)
+++ /trunk/minix/test/test5.c	(revision 9)
@@ -0,0 +1,400 @@
+/* test 5 */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+#define ITERATIONS 2
+#define MAX_ERROR 4
+
+int errct;
+int subtest;
+int zero[1024];
+
+int sigmap[5] = {9, 10, 11};
+
+_PROTOTYPE(int main, (int argc, char *argv[]));
+_PROTOTYPE(void test5a, (void));
+_PROTOTYPE(void parent, (int childpid));
+_PROTOTYPE(void child, (int parpid));
+_PROTOTYPE(void func1, (int s));
+_PROTOTYPE(void func8, (int s));
+_PROTOTYPE(void func10, (int s));
+_PROTOTYPE(void func11, (int s));
+_PROTOTYPE(void test5b, (void));
+_PROTOTYPE(void test5c, (void));
+_PROTOTYPE(void test5d, (void));
+_PROTOTYPE(void test5e, (void));
+_PROTOTYPE(void test5f, (void));
+_PROTOTYPE(void test5g, (void));
+_PROTOTYPE(void funcalrm, (int s));
+_PROTOTYPE(void test5h, (void));
+_PROTOTYPE(void test5i, (void));
+_PROTOTYPE(void ex, (void));
+_PROTOTYPE(void e, (int n));
+_PROTOTYPE(void quit, (void));
+
+#ifdef _ANSI
+void (*Signal(int _sig, void (*_func)(int)))(int);
+#define SIG_ZERO	((void (*)(int))0)	/* default signal handling */
+#else
+sighandler_t Signal();
+/* void (*Signal()) (); */
+#define SIG_ZERO	((void (*)())0)		/* default signal handling */
+#endif
+
+_VOLATILE int childsigs, parsigs, alarms;
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0x7777;
+
+  printf("Test  5 ");
+  fflush(stdout);		/* have to flush for child's benefit */
+
+  system("rm -rf DIR_05; mkdir DIR_05");
+  chdir("DIR_05");
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test5a();
+	if (m & 0002) test5b();
+	if (m & 0004) test5c();
+	if (m & 0010) test5d();
+	if (m & 0020) test5e();
+	if (m & 0040) test5f();
+	if (m & 0100) test5g();
+	if (m & 0200) test5h();
+	if (m & 0400) test5i();
+  }
+  quit();
+  return(-1);			/* impossible */
+}
+
+void test5a()
+{
+  int parpid, childpid, flag, *zp;
+
+  subtest = 0;
+  flag = 0;
+  for (zp = &zero[0]; zp < &zero[1024]; zp++)
+	if (*zp != 0) flag = 1;
+  if (flag) e(0);		/* check if bss is cleared to 0 */
+  if (Signal(1, func1) ==  SIG_ERR) e(1);
+  if (Signal(10, func10) < SIG_ZERO) e(2);
+  parpid = getpid();
+  if (childpid = fork()) {
+	if (childpid < 0) ex();
+	parent(childpid);
+  } else {
+	child(parpid);
+  }
+  if (Signal(1, SIG_DFL) <  SIG_ZERO) e(4);
+  if (Signal(10, SIG_DFL) < SIG_ZERO) e(5);
+}
+
+void parent(childpid)
+int childpid;
+{
+  int i, pid;
+
+  for (i = 0; i < 3; i++) {
+	if (kill(childpid, 1) < 0) e(6);
+	while (parsigs == 0);
+	parsigs--;
+  }
+  if ( (pid = wait(&i)) < 0) e(7);
+  if (i != 256 * 6) e(8);
+}
+
+void child(parpid)
+int parpid;
+{
+
+  int i;
+
+  for (i = 0; i < 3; i++) {
+	while (childsigs == 0);
+	childsigs--;
+	if (kill(parpid, 10) < 0) e(9);
+  }
+  exit(6);
+}
+
+void func1(s)
+int s;				/* for ANSI */
+{
+  if (Signal(1, func1) < SIG_ZERO) e(10);
+  childsigs++;
+}
+
+void func8(s)
+int s;
+{
+}
+
+void func10(s)
+int s;				/* for ANSI */
+{
+  if (Signal(10, func10) < SIG_ZERO) e(11);
+  parsigs++;
+}
+
+void func11(s)
+int s;				/* for ANSI */
+{
+  e(38);
+}
+
+void test5b()
+{
+  int cpid, n, pid;
+
+  subtest = 1;
+  if ((pid = fork())) {
+	if (pid < 0) ex();
+	if ((pid = fork())) {
+		if (pid < 0) ex();
+		if (cpid = fork()) {
+			if (cpid < 0) ex();
+			if (kill(cpid, 9) < 0) e(12);
+			if (wait(&n) < 0) e(13);
+			if (wait(&n) < 0) e(14);
+			if (wait(&n) < 0) e(15);
+		} else {
+			pause();
+			while (1);
+		}
+	} else {
+		exit(0);
+	}
+  } else {
+	exit(0);
+  }
+}
+
+void test5c()
+{
+  int n, i, pid, wpid;
+
+  /* Test exit status codes for processes killed by signals. */
+  subtest = 3;
+  for (i = 0; i < 2; i++) {
+	if (pid = fork()) {
+		if (pid < 0) ex();
+		sleep(2);	/* wait for child to pause */
+		if (kill(pid, sigmap[i]) < 0) {
+			e(20);
+			exit(1);
+		}
+		if ((wpid = wait(&n)) < 0) e(21);
+		if ((n & 077) != sigmap[i]) e(22);
+		if (pid != wpid) e(23);
+	} else {
+		pause();
+		exit(0);
+	}
+  }
+}
+
+void test5d()
+{
+/* Test alarm */
+
+  int i;
+
+  subtest = 4;
+  alarms = 0;
+  for (i = 0; i < 8; i++) {
+	Signal(SIGALRM, funcalrm);
+	alarm(1);
+	pause();
+	if (alarms != i + 1) e(24);
+  }
+}
+
+void test5e()
+{
+/* When a signal knocks a processes out of WAIT or PAUSE, it is supposed to
+ * get EINTR as error status.  Check that.
+ */
+  int n, j;
+
+  subtest = 5;
+  if (Signal(8, func8) < SIG_ZERO) e(25);
+  if (n = fork()) {
+	/* Parent must delay to give child a chance to pause. */
+	if (n < 0) ex();
+	sleep(1);
+	if (kill(n, 8) < 0) e(26);
+	if (wait(&n) < 0) e(27);
+	if (Signal(8, SIG_DFL) < SIG_ZERO) e(28);
+  } else {
+	j = pause();
+	if (errno != EINTR && -errno != EINTR) e(29);
+	exit(0);
+  }
+}
+
+void test5f()
+{
+  int i, j, k, n;
+
+  subtest = 6;
+  if (getuid() != 0) return;
+  n = fork();
+  if (n < 0) ex();
+  if (n) {
+	wait(&i);
+	i = (i >> 8) & 0377;
+	if (i != (n & 0377)) e(30);
+  } else {
+	i = getgid();
+	j = getegid();
+	k = (i + j + 7) & 0377;
+	if (setgid(k) < 0) e(31);
+	if (getgid() != k) e(32);
+	if (getegid() != k) e(33);
+	i = getuid();
+	j = geteuid();
+	k = (i + j + 1) & 0377;
+	if (setuid(k) < 0) e(34);
+	if (getuid() != k) e(35);
+	if (geteuid() != k) e(36);
+	i = getpid() & 0377;
+	if (wait(&j) != -1) e(37);
+	exit(i);
+  }
+}
+
+void test5g()
+{
+  int n;
+
+  subtest = 7;
+  Signal(11, func11);
+  Signal(11, SIG_IGN);
+  n = getpid();
+  if (kill(n, 11) != 0) e(1);
+  Signal(11, SIG_DFL);
+}
+
+void funcalrm(s)
+int s;				/* for ANSI */
+{
+  alarms++;
+}
+
+void test5h()
+{
+/* When a signal knocks a processes out of PIPE, it is supposed to
+ * get EINTR as error status.  Check that.
+ */
+  int n, j, fd[2];
+
+  subtest = 8;
+  unlink("XXX.test5");
+  if (Signal(8, func8) < SIG_ZERO) e(1);
+  pipe(fd);
+  if (n = fork()) {
+	/* Parent must delay to give child a chance to pause. */
+	if (n < 0) ex();
+	while (access("XXX.test5", 0) != 0) /* just wait */ ;
+	sleep(1);
+ 	unlink("XXX.test5");
+	if (kill(n, 8) < 0) e(2);
+	if (wait(&n) < 0) e(3);
+	if (Signal(8, SIG_DFL) < SIG_ZERO) e(4);
+	if (close(fd[0]) != 0) e(5);
+	if (close(fd[1]) != 0) e(6);
+  } else {
+	if (creat("XXX.test5", 0777) < 0) e(7);
+	j = read(fd[0], (char *) &n, 1);
+	if (errno != EINTR) e(8);
+	exit(0);
+  }
+}
+
+void test5i()
+{
+  int fd[2], pid, buf[10], n;
+
+  subtest = 9;
+  pipe(fd);
+  unlink("XXXxxxXXX");
+
+  if ( (pid = fork())) {
+	/* Parent */
+	/* Wait until child has started and has created the XXXxxxXXX file. */
+	while (access("XXXxxxXXX", 0) != 0) /* loop */ ;
+	sleep(1);
+	if (kill(pid, SIGKILL) != 0) e(1);
+	if (wait(&n) < 0) e(2);
+	if (close(fd[0]) != 0) e(3);
+	if (close(fd[1]) != 0) e(4);
+  } else {
+	if (creat("XXXxxxXXX", 0777) < 0) e(5);
+	read(fd[0], (char *) buf, 1);
+	e(5);		/* should be killed by signal and not get here */
+  }
+  unlink("XXXxxxXXX");
+}
+
+void ex()
+{
+  int e = errno;
+  printf("Fork failed: %s (%d)\n", strerror(e), e);
+  exit(1);
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* save errno in case printf clobbers it */
+
+  printf("Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
+  errno = err_num;		/* restore errno, just in case */
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+}
+
+#ifdef _ANSI
+void (*Signal(int a, void (*b)(int)))(int)
+#else
+sighandler_t Signal(a, b)
+int a;
+void (*b)();
+#endif
+{
+  if (signal(a, (void (*) ()) b) == (void (*)()) -1)
+	return(SIG_ERR);
+  else
+	return(SIG_ZERO);
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test6.c
===================================================================
--- /trunk/minix/test/test6.c	(revision 9)
+++ /trunk/minix/test/test6.c	(revision 9)
@@ -0,0 +1,213 @@
+/* test 6 */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define MAX_ERROR 4
+
+int errct;
+int subtest = 1;
+int zilch[5000];
+char curdir[PATH_MAX];
+
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(void test6a, (void));
+_PROTOTYPE(void test6b, (void));
+_PROTOTYPE(void test6c, (void));
+_PROTOTYPE(void e, (int n));
+_PROTOTYPE(void quit, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (geteuid() == 0 || getuid() == 0) {
+	printf("Test  6 cannot run as root; test aborted\n");
+	exit(1);
+  }
+
+  if (argc == 2) m = atoi(argv[1]);
+
+  printf("Test  6 ");
+  fflush(stdout);
+
+  getcwd(curdir, PATH_MAX);
+  system("rm -rf DIR_06; mkdir DIR_06");
+  chdir("DIR_06");
+
+  for (i = 0; i < 70; i++) {
+	if (m & 00001) test6a();
+	if (m & 00002) test6b();
+	if (m & 00004) test6c();
+  }
+
+  quit();
+  return(-1);			/* impossible */
+}
+
+void test6a()
+{
+/* Test sbrk() and brk(). */
+
+  char *addr, *addr2, *addr3;
+  int i, del, click, click2;
+
+  subtest = 1;
+  addr = sbrk(0);
+  addr = sbrk(0);		/* force break to a click boundary */
+  for (i = 0; i < 10; i++) sbrk(7 * i);
+  for (i = 0; i < 10; i++) sbrk(-7 * i);
+  if (sbrk(0) != addr) e(1);
+  sbrk(30);
+  if (brk(addr) != 0) e(2);
+  if (sbrk(0) != addr) e(3);
+
+  del = 0;
+  do {
+	del++;
+	brk(addr + del);
+	addr2 = sbrk(0);
+  } while (addr2 == addr);
+  click = addr2 - addr;
+  sbrk(-1);
+  if (sbrk(0) != addr) e(4);
+  brk(addr);
+  if (sbrk(0) != addr) e(5);
+
+  del = 0;
+  do {
+	del++;
+	brk(addr - del);
+	addr3 = sbrk(0);
+  } while (addr3 == addr);
+  click2 = addr - addr3;
+  sbrk(1);
+  if (sbrk(0) != addr) e(6);
+  brk(addr);
+  if (sbrk(0) != addr) e(8);
+  if (click != click2) e(9);
+
+  brk(addr + 2 * click);
+  if (sbrk(0) != addr + 2 * click) e(10);
+  sbrk(3 * click);
+  if (sbrk(0) != addr + 5 * click) e(11);
+  sbrk(-5 * click);
+  if (sbrk(0) != addr) e(12);
+}
+
+void test6b()
+{
+  int i, err;
+
+  subtest = 2;
+  signal(SIGQUIT, SIG_IGN);
+  err = 0;
+  for (i = 0; i < 5000; i++)
+	if (zilch[i] != 0) err++;
+  if (err > 0) e(1);
+  kill(getpid(), SIGQUIT);
+}
+
+void test6c()
+{
+/* Test mknod, chdir, chmod, chown, access.  */
+
+  int i, j;
+  struct stat s;
+
+  subtest = 3;
+  if (getuid() != 0) return;
+  for (j = 0; j < 2; j++) {
+	umask(0);
+
+	if (chdir("/") < 0) e(1);
+	if (mknod("dir", 040700, 0) < 0) e(2);
+	if (link("/", "/dir/..") < 0) e(3);
+	if (mknod("T3a", 0777, 0) < 0) e(4);
+	if (mknod("/dir/T3b", 0777, 0) < 0) e(5);
+	if (mknod("dir/T3c", 0777, 0) < 0) e(6);
+	if ((i = open("/dir/T3b", 0)) < 0) e(7);
+	if (close(i) < 0) e(8);
+	if ((i = open("dir/T3c", O_RDONLY)) < 0) e(9);
+	if (close(i) < 0) e(10);
+	if (chdir("dir") < 0) e(11);
+	if ((i = open("T3b", 0)) < 0) e(12);
+	if (close(i) < 0) e(13);
+	if ((i = open("../T3a", O_RDONLY)) < 0) e(14);
+	if (close(i) < 0) e(15);
+	if ((i = open("../dir/../dir/../dir/../dir/../dir/T3c", O_RDONLY)) < 0)
+		e(16);
+	if (close(i) < 0) e(17);
+
+	if (chmod("../dir/../dir/../dir/../dir/../T3a", 0123) < 0) e(18);
+	if (stat("../dir/../dir/../dir/../T3a", &s) < 0) e(19);
+	if ((s.st_mode & 077777) != 0123) e(20);
+	if (chmod("../dir/../dir/../T3a", 0456) < 0) e(21);
+	if (stat("../T3a", &s) < 0) e(22);
+	if ((s.st_mode & 077777) != 0456) e(23);
+	if (chown("../dir/../dir/../T3a", 20, 30) < 0) e(24);
+	if (stat("../T3a", &s) < 0) e(25);
+	if (s.st_uid != 20) e(26);
+	if (s.st_gid != 30) e(27);
+
+	if ((i = open("/T3c", O_RDONLY)) >= 0) e(28);
+	if ((i = open("/T3a", O_RDONLY)) < 0) e(29);
+	if (close(i) < 0) e(30);
+
+	if (access("/T3a", 4) < 0) e(31);
+	if (access("/dir/T3b", 4) < 0) e(32);
+	if (access("/dir/T3d", 4) >= 0) e(33);
+
+	if (unlink("T3b") < 0) e(34);
+	if (unlink("T3c") < 0) e(35);
+	if (unlink("..") < 0) e(36);
+	if (chdir("/") < 0) e(37);
+	if (unlink("dir") < 0) e(38);
+	if (unlink("/T3a") < 0) e(39);
+  }
+
+}
+
+void e(n)
+int n;
+{
+
+  int err_num = errno;		/* save errno in case printf clobbers it */
+
+  printf("Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
+  errno = err_num;		/* restore errno, just in case */
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  chdir(curdir);
+  system("rm -rf DIR*");
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test7.c
===================================================================
--- /trunk/minix/test/test7.c	(revision 9)
+++ /trunk/minix/test/test7.c	(revision 9)
@@ -0,0 +1,695 @@
+/* POSIX test program (7).			Author: Andy Tanenbaum */
+
+/* The following POSIX calls are tested:
+ *	pipe(), mkfifo(), fcntl()
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define ITERATIONS        4
+#define MAX_ERROR 4
+#define ITEMS  32
+#define READ   10
+#define WRITE  20
+#define UNLOCK 30
+#define U      70
+#define L      80
+
+char buf[ITEMS] = {0,1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1,0,1,2,3,4,5,6,7,8,9};
+
+int subtest, errct, xfd;
+int whence = SEEK_SET, func_code = F_SETLK;
+extern char **environ;
+
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(void test7a, (void));
+_PROTOTYPE(void test7b, (void));
+_PROTOTYPE(void test7c, (void));
+_PROTOTYPE(void test7d, (void));
+_PROTOTYPE(void test7e, (void));
+_PROTOTYPE(void test7f, (void));
+_PROTOTYPE(void test7g, (void));
+_PROTOTYPE(void test7h, (void));
+_PROTOTYPE(void test7i, (void));
+_PROTOTYPE(void test7j, (void));
+_PROTOTYPE(void cloexec_test, (void));
+_PROTOTYPE(int set, (int how, int first, int last));
+_PROTOTYPE(int locked, (int b));
+_PROTOTYPE(void e, (int n));
+_PROTOTYPE(void sigfunc, (int s));
+_PROTOTYPE(void quit, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+
+  int i, m = 0xFFFF;
+
+  sync();
+
+  if (argc == 2) m = atoi(argv[1]);
+  if (m == 0) cloexec_test();	/* important; do not remove this! */
+  printf("Test  7 ");
+  fflush(stdout);
+
+  system("rm -rf DIR_07; mkdir DIR_07");
+  chdir("DIR_07");
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 00001) test7a();
+	if (m & 00002) test7b();
+	if (m & 00004) test7c();
+	if (m & 00010) test7d();
+	if (m & 00020) test7e();
+	if (m & 00040) test7f();
+	if (m & 00100) test7g();
+	if (m & 00200) test7h();
+	if (m & 00400) test7i();
+	if (m & 01000) test7j();
+  }
+  quit();
+  return(-1);			/* impossible */
+}
+
+void test7a()
+{
+/* Test pipe(). */
+
+  int i, fd[2], ect;
+  char buf2[ITEMS+1];
+
+  /* Create a pipe, write on it, and read it back. */
+  subtest = 1;
+  if (pipe(fd) != 0) e(1);
+  if (write(fd[1], buf, ITEMS) != ITEMS) e(2);
+  buf2[0] = 0;
+  if (read(fd[0], buf2, ITEMS+1) != ITEMS) e(3);
+  ect = 0;
+  for (i = 0; i < ITEMS; i++) if (buf[i] != buf2[i]) ect++;
+  if (ect != 0) e(4);
+  if (close(fd[0]) != 0) e(5);
+  if (close(fd[1]) != 0) e(6);
+
+  /* Error test.  Keep opening pipes until it fails.  Check error code. */
+  errno = 0;
+  while (1) {
+	if (pipe(fd) < 0) break;
+  }
+  if (errno != EMFILE) e(7);
+
+  /* Close all the pipes. */
+  for (i = 3; i < OPEN_MAX; i++) close(i);
+}
+
+void test7b()
+{
+/* Test mkfifo(). */
+
+  int fdr, fdw, status;
+  char buf2[ITEMS+1];
+  int efork;
+
+  /* Create a fifo, write on it, and read it back. */
+  subtest = 2;
+  if (mkfifo("T7.b", 0777) != 0) e(1);
+  switch (fork()) {
+  case -1:
+  	efork = errno;
+  	printf("Fork failed: %s (%d)\n", strerror(efork), efork);
+  	exit(1);
+  case 0:
+	/* Child reads from the fifo. */
+	if ( (fdr = open("T7.b", O_RDONLY)) < 0) e(5);
+	if (read(fdr, buf2, ITEMS+1) != ITEMS) e(6);
+	if (strcmp(buf, buf2) != 0) e(7);
+	if (close(fdr) != 0) e(8);
+	exit(0);
+  default:
+	/* Parent writes on the fifo. */
+	if ( (fdw = open("T7.b", O_WRONLY)) < 0) e(2);
+	if (write(fdw, buf, ITEMS) != ITEMS) e(3);
+	wait(&status);
+	if (close(fdw) != 0) e(4);
+  }
+
+  /* Check some error conditions. */
+  if (mkfifo("T7.b", 0777) != -1) e(9);
+  errno = 0;
+  if (mkfifo("a/b/c", 0777) != -1) e(10);
+  if (errno != ENOENT) e(11);
+  errno = 0;
+  if (mkfifo("", 0777) != -1) e(12);
+  if (errno != ENOENT) e(13);
+  errno = 0;
+  if (mkfifo("T7.b/x", 0777) != -1) e(14);
+  if (errno != ENOTDIR) e(15);
+  if (unlink("T7.b") != 0) e(16);
+
+  /* Now check fifos and the O_NONBLOCK flag. */
+  if (mkfifo("T7.b", 0600) != 0) e(17);
+  errno = 0;
+  if (open("T7.b", O_WRONLY | O_NONBLOCK) != -1) e(18);
+  if (errno != ENXIO) e(19);
+  if ( (fdr = open("T7.b", O_RDONLY | O_NONBLOCK)) < 0) e(20);
+  if (fork()) {
+	/* Parent reads from fdr. */
+	wait(&status);		/* but first make sure writer has already run*/
+	if ( ( (status>>8) & 0377) != 77) e(21);
+	if (read(fdr, buf2, ITEMS+1) != ITEMS) e(22);
+	if (strcmp(buf, buf2) != 0) e(23);
+	if (close(fdr) != 0) e(24);
+  } else {
+	/* Child opens the fifo for writing and writes to it. */
+	if ( (fdw = open("T7.b", O_WRONLY | O_NONBLOCK)) < 0) e(25);
+	if (write(fdw, buf, ITEMS) != ITEMS) e(26);
+	if (close(fdw) != 0) e(27);
+	exit(77);
+  }
+  
+  if (unlink("T7.b") != 0) e(28);
+}
+
+void test7c()
+{
+/* Test fcntl(). */
+
+  int fd, m, s, newfd, newfd2;
+  struct stat stat1, stat2, stat3;
+
+  subtest = 3;
+  errno = -100;
+  if ( (fd = creat("T7.c", 0777)) < 0) e(1);
+
+  /* Turn the per-file-descriptor flags on and off. */
+  if (fcntl(fd, F_GETFD) != 0) e(2);	/* FD_CLOEXEC is initially off */
+  if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) e(3);/* turn it on */
+  if (fcntl(fd, F_GETFD) != FD_CLOEXEC) e(4);	/* should be on now */
+  if (fcntl(fd, F_SETFD, 0) != 0) e(5);		/* turn it off */
+  if (fcntl(fd, F_GETFD) != 0) e(6);		/* should be off now */
+
+  /* Turn the open-file-description flags on and off. Start with O_APPEND. */
+  m = O_WRONLY;
+  if (fcntl(fd, F_GETFL) != m) e(7);	/* O_APPEND, O_NONBLOCK are off */
+  if (fcntl(fd, F_SETFL, O_APPEND) != 0) e(8);	 /* turn on O_APPEND */
+  if (fcntl(fd, F_GETFL) != (O_APPEND | m)) e(9);/* should be on now */
+  if (fcntl(fd, F_SETFL, 0) != 0) e(10);	 /* turn it off */
+  if (fcntl(fd, F_GETFL) != m) e(11);		 /* should be off now */
+  
+  /* Turn the open-file-description flags on and off. Now try O_NONBLOCK.  */
+  if (fcntl(fd, F_SETFL, O_NONBLOCK) != 0) e(12);      /* turn on O_NONBLOCK */
+  if (fcntl(fd, F_GETFL) != (O_NONBLOCK | m)) e(13);   /* should be on now */
+  if (fcntl(fd, F_SETFL, 0) != 0) e(14);	       /* turn it off */
+  if (fcntl(fd, F_GETFL) != m) e(15);		       /* should be off now */
+  
+  /* Now both at once. */
+  if (fcntl(fd, F_SETFL, O_APPEND|O_NONBLOCK) != 0) e(16);
+  if (fcntl(fd, F_GETFL) != (O_NONBLOCK | O_APPEND | m)) e(17);
+  if (fcntl(fd, F_SETFL, 0) != 0) e(18);
+  if (fcntl(fd, F_GETFL) != m) e(19);
+
+  /* Now test F_DUPFD. */
+  if ( (newfd = fcntl(fd, F_DUPFD, 0)) != 4) e(20);	/* 0-4 open */
+  if ( (newfd2 = fcntl(fd, F_DUPFD, 0)) != 5) e(21);	/* 0-5 open */
+  if (close(newfd) != 0) e(22);				/* 0-3, 5 open */
+  if ( (newfd = fcntl(fd, F_DUPFD, 0)) != 4) e(23);	/* 0-5 open */
+  if (close(newfd) != 0) e(24);				/* 0-3, 5 open */
+  if ( (newfd = fcntl(fd, F_DUPFD, 5)) != 6) e(25);	/* 0-3, 5, 6 open */
+  if (close(newfd2) != 0) e(26);			/* 0-3, 6 open */
+  
+  /* O_APPEND should be inherited, but FD_CLOEXEC should be cleared.  Check. */
+  if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) e(26);/* turn FD_CLOEXEC on */
+  if (fcntl(fd, F_SETFL, O_APPEND) != 0) e(27);	 /* turn O_APPEND on */
+  if ( (newfd2 = fcntl(fd, F_DUPFD, 10)) != 10) e(28);	/* 0-3, 6, 10 open */
+  if (fcntl(newfd2, F_GETFD) != 0) e(29);	/* FD_CLOEXEC must be 0 */
+  if (fcntl(newfd2, F_GETFL) != (O_APPEND | m)) e(30);	/* O_APPEND set */
+  if (fcntl(fd, F_SETFD, 0) != 0) e(31);/* turn FD_CLOEXEC off */
+
+  /* Check if newfd and newfd2 are the same inode. */
+  if (fstat(fd, &stat1) != 0) e(32);
+  if (fstat(fd, &stat2) != 0) e(33);
+  if (fstat(fd, &stat3) != 0) e(34);
+  if (stat1.st_dev != stat2.st_dev) e(35);
+  if (stat1.st_dev != stat3.st_dev) e(36);
+  if (stat1.st_ino != stat2.st_ino) e(37);
+  if (stat1.st_ino != stat3.st_ino) e(38);
+
+  /* Now check on the FD_CLOEXEC flag.  Set it for fd (3) and newfd2 (10) */
+  if (fd != 3 || newfd2 != 10 || newfd != 6) e(39);
+  if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) e(40);	/* close 3 on exec */
+  if (fcntl(newfd2, F_SETFD, FD_CLOEXEC) != 0) e(41);	/* close 10 on exec */
+  if (fcntl(newfd, F_SETFD, 0) != 0) e(42);		/* don't close 6 */
+  if (fork()) {
+	wait(&s);		/* parent just waits */
+	if (WEXITSTATUS(s) != 0) e(43);
+  } else {
+	execle("../test7", "test7", "0", (char *) 0, environ);
+	exit(1);		/* the impossible never happens, right? */
+  }
+  
+  /* Finally, close all the files. */
+  if (fcntl(fd, F_SETFD, 0) != 0) e(44);	/* FD_CLOEXEC off */
+  if (fcntl(newfd2, F_SETFD, 0) != 0) e(45);	/* FD_CLOEXEC off */
+  if (close(fd) != 0) e(46);
+  if (close(newfd) != 0) e(47);
+  if (close(newfd2) != 0) e(48);
+}
+
+void test7d()
+{
+/* Test file locking. */
+
+  subtest = 4;
+ 
+  if ( (xfd = creat("T7.d", 0777)) != 3) e(1);
+  close(xfd);
+  if ( (xfd = open("T7.d", O_RDWR)) < 0) e(2);
+  if (write(xfd, buf, ITEMS) != ITEMS) e(3);
+  if (set(WRITE, 0, 3) != 0) e(4);
+  if (set(WRITE, 5, 9) != 0) e(5);
+  if (set(UNLOCK, 0, 3) != 0) e(6);
+  if (set(UNLOCK, 4, 9) != 0) e(7);
+
+  if (set(READ, 1, 4) != 0) e(8);
+  if (set(READ, 4, 7) != 0) e(9);
+  if (set(UNLOCK, 4, 7) != 0) e(10);
+  if (set(UNLOCK, 1, 4) != 0) e(11);
+
+  if (set(WRITE, 0, 3) != 0) e(12);
+  if (set(WRITE, 5, 7) != 0) e(13);
+  if (set(WRITE, 9 ,10) != 0) e(14);
+  if (set(UNLOCK, 0, 4) != 0) e(15);
+  if (set(UNLOCK, 0, 7) != 0) e(16);
+  if (set(UNLOCK, 0, 2000) != 0) e(17);
+
+  if (set(WRITE, 0, 3) != 0) e(18);
+  if (set(WRITE, 5, 7) != 0) e(19);
+  if (set(WRITE, 9 ,10) != 0) e(20);
+  if (set(UNLOCK, 0, 100) != 0) e(21);
+
+  if (set(WRITE, 0, 9) != 0) e(22);
+  if (set(UNLOCK, 8, 9) != 0) e(23);
+  if (set(UNLOCK, 0, 2) != 0) e(24);
+  if (set(UNLOCK, 5, 5) != 0) e(25);
+  if (set(UNLOCK, 4, 6) != 0) e(26);
+  if (set(UNLOCK, 3, 3) != 0) e(27);
+  if (set(UNLOCK, 7, 7) != 0) e(28);
+
+  if (set(WRITE, 0, 10) != 0) e(29);
+  if (set(UNLOCK, 0, 1000) != 0) e(30);
+
+  /* Up until now, all locks have been disjoint.  Now try conflicts. */
+  if (set(WRITE, 0, 4) != 0) e(31);
+  if (set(WRITE, 4, 7) != 0) e(32);	/* owner may lock same byte twice */
+  if (set(WRITE, 5, 10) != 0) e(33);
+  if (set(UNLOCK, 0, 11) != 0) e(34);
+
+  /* File is now unlocked. Length 0 means whole file. */
+  if (set(WRITE, 2, 1) != 0) e(35);	/* this locks whole file */
+  if (set(WRITE, 9,10) != 0) e(36);	/* a process can relock its file */
+  if (set(WRITE, 3, 3) != 0) e(37);
+  if (set(UNLOCK, 0, -1) != 0) e(38);	/* file is now unlocked. */
+
+  /* Test F_GETLK. */
+  if (set(WRITE, 2, 3) != 0) e(39);
+  if (locked(1) != U) e(40);
+  if (locked(2) != L) e(41);
+  if (locked(3) != L) e(42);
+  if (locked(4) != U) e(43);
+  if (set(UNLOCK, 2, 3) != 0) e(44);
+  if (locked(2) != U) e(45);
+  if (locked(3) != U) e(46);
+
+  close(xfd);
+}
+
+void test7e()
+{
+/* Test to see if SETLKW blocks as it should. */
+
+  int pid, s;
+
+  subtest = 5;
+ 
+  if ( (xfd = creat("T7.e", 0777)) != 3) e(1);
+  if (close(xfd) != 0) e(2);
+  if ( (xfd = open("T7.e", O_RDWR)) < 0) e(3);
+  if (write(xfd, buf, ITEMS) != ITEMS) e(4);
+  if (set(WRITE, 0, 3) != 0) e(5);
+
+  if ( (pid = fork()) ) {
+	/* Parent waits until child has started before signaling it. */
+	while (access("T7.e1", 0) != 0) ;
+	unlink("T7.e1");
+	sleep(1);
+	if (kill(pid, SIGKILL) < 0) e(6);
+	if (wait(&s) != pid) e(7);
+  } else {
+	/* Child tries to lock and should block. */
+	if (creat("T7.e1", 0777) < 0) e(8);
+	func_code = F_SETLKW;
+	if (set(WRITE, 0, 3) != 0) e(9);	/* should block */
+	errno = -1000;
+	e(10);			/* process should be killed by signal */
+	exit(0);		/* should never happen */
+  }
+  close(xfd);
+}
+
+void test7f()
+{
+/* Test to see if SETLKW gives EINTR when interrupted. */
+
+  int pid, s;
+
+  subtest = 6;
+ 
+  if ( (xfd = creat("T7.f", 0777)) != 3) e(1);
+  if (close(xfd) != 0) e(2);
+  if ( (xfd = open("T7.f", O_RDWR)) < 0) e(3);
+  if (write(xfd, buf, ITEMS) != ITEMS) e(4);
+  if (set(WRITE, 0, 3) != 0) e(5);
+
+  if ( (pid = fork()) ) {
+	/* Parent waits until child has started before signaling it. */
+	while (access("T7.f1", 0) != 0) ;
+	unlink("T7.f1");
+	sleep(1);
+	if (kill(pid, SIGTERM) < 0) e(6);
+	if (wait(&s) != pid) e(7);
+	if ( (s>>8) != 19) e(8);
+  } else {
+	/* Child tries to lock and should block.
+	 * `signal(SIGTERM, sigfunc);' to set the signal handler is inadequate
+	 * because on systems like BSD the sigaction flags for signal include
+	 * `SA_RESTART' so syscalls are restarted after they have been
+	 * interrupted by a signal.
+	 */
+	struct sigaction sa, osa;
+
+	sa.sa_handler = sigfunc;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = 0;
+	if (sigaction(SIGTERM, &sa, &osa) < 0) e(999);
+	if (creat("T7.f1", 0777) < 0) e(9);
+	func_code = F_SETLKW;
+	if (set(WRITE, 0, 3) != -1) e(10);	/* should block */
+	if (errno != EINTR) e(11);	/* signal should release it */
+	exit(19);
+  }
+  close(xfd);
+}
+
+void test7g()
+{
+/* Test to see if SETLKW unlocks when the needed lock becomes available. */
+
+  int pid, s;
+
+  subtest = 7;
+ 
+  if ( (xfd = creat("T7.g", 0777)) != 3) e(1);
+  if (close(xfd) != 0) e(2);
+  if ( (xfd = open("T7.g", O_RDWR)) < 0) e(3);
+  if (write(xfd, buf, ITEMS) != ITEMS) e(4);
+  if (set(WRITE, 0, 3) != 0) e(5);	/* bytes 0 to 3 are now locked */
+
+  if ( (pid = fork()) ) {
+	/* Parent waits for child to start. */
+	while (access("T7.g1", 0) != 0) ;
+	unlink("T7.g1");
+	sleep(1);
+	if (set(UNLOCK, 0, 3) != 0) e(5);
+	if (wait(&s) != pid) e(6);
+	if ( (s >> 8) != 29) e(7);
+  } else {
+	/* Child tells parent it is alive, then tries to lock and is blocked.*/
+	func_code = F_SETLKW;	
+	if (creat("T7.g1", 0777) < 0) e(8);
+	if (set(WRITE, 3, 3) != 0) e(9);	/* process must block now */
+	if (set(UNLOCK, 3, 3) != 0) e(10);
+	exit(29);
+  }
+  close(xfd);
+}
+
+void test7h()
+{
+/* Test to see what happens if two processed block on the same lock. */
+
+  int pid, pid2, s, w;
+
+  subtest = 8;
+ 
+  if ( (xfd = creat("T7.h", 0777)) != 3) e(1);
+  if (close(xfd) != 0) e(2);
+  if ( (xfd = open("T7.h", O_RDWR)) < 0) e(3);
+  if (write(xfd, buf, ITEMS) != ITEMS) e(4);
+  if (set(WRITE, 0, 3) != 0) e(5);	/* bytes 0 to 3 are now locked */
+
+  if ( (pid = fork()) ) {
+	if ( (pid2 = fork()) ) {
+		/* Parent waits for child to start. */
+		while (access("T7.h1", 0) != 0) ;
+		while (access("T7.h2", 0) != 0) ;
+		unlink("T7.h1");
+		unlink("T7.h2");
+		sleep(1);
+		if (set(UNLOCK, 0, 3) != 0) e(6);
+		w = wait(&s);
+		if (w != pid && w != pid2) e(7);
+		s = s >> 8;
+		if (s != 39 && s != 49) e(8);
+		w = wait(&s);
+		if (w != pid && w != pid2) e(9);
+		s = s >> 8;
+		if (s != 39 && s != 49) e(10);
+	} else {
+		func_code = F_SETLKW;	
+		if (creat("T7.h1", 0777) < 0) e(11);
+		if (set(WRITE, 0, 0) != 0) e(12);	/* block now */
+		if (set(UNLOCK, 0, 0) != 0) e(13);
+		exit(39);
+	}
+  } else {
+	/* Child tells parent it is alive, then tries to lock and is blocked.*/
+	func_code = F_SETLKW;	
+	if (creat("T7.h2", 0777) < 0) e(14);
+	if (set(WRITE, 0, 1) != 0) e(15);	/* process must block now */
+	if (set(UNLOCK, 0, 1) != 0) e(16);
+	exit(49);
+  }
+  close(xfd);
+}
+
+void test7i()
+{
+/* Check error conditions for fcntl(). */
+
+  int tfd, i;
+
+  subtest = 9;
+ 
+  errno = 0;
+  if ( (xfd = creat("T7.i", 0777)) != 3) e(1);
+  if (close(xfd) != 0) e(2);
+  if ( (xfd = open("T7.i", O_RDWR)) < 0) e(3);
+  if (write(xfd, buf, ITEMS) != ITEMS) e(4);
+  if (set(WRITE, 0, 3) != 0) e(5);	/* bytes 0 to 3 are now locked */
+  if (set(WRITE, 0, 0) != 0) e(6);
+  if (errno != 0) e(7);
+  errno = 0;
+  if (set(WRITE, 3, 3) != 0) e(8);
+  if (errno != 0) e(9);
+  tfd = xfd;			/* hold good value */
+  xfd = -99;
+  errno = 0;
+  if (set(WRITE, 0, 0) != -1) e(10);
+  if (errno != EBADF) e(11);
+
+  errno = 0;  
+  if ( (xfd = open("T7.i", O_WRONLY)) < 0) e(12);
+  if (set(READ, 0, 0) != -1) e(13);
+  if (errno != EBADF) e(14);
+  if (close(xfd) != 0) e(15);
+
+  errno = 0;  
+  if ( (xfd = open("T7.i", O_RDONLY)) < 0) e(16);
+  if (set(WRITE, 0, 0) != -1) e(17);
+  if (errno != EBADF) e(18);
+  if (close(xfd) != 0) e(19);
+  xfd = tfd;			/* restore legal xfd value */
+
+  /* Check for EINVAL. */
+  errno = 0;
+  if (fcntl(xfd, F_DUPFD, OPEN_MAX) != -1) e(20);
+  if (errno != EINVAL) e(21);
+  errno = 0;
+  if (fcntl(xfd, F_DUPFD, -1) != -1) e(22);
+  if (errno != EINVAL) e(23);
+
+  xfd = 0;			/* stdin does not support locking */
+  errno = 0;
+  if (set(READ, 0, 0) != -1) e(24);
+  if (errno != EINVAL) e(25);
+  xfd = tfd;
+
+  /* Check ENOLCK. */
+  for (i = 0; i < ITEMS; i++) {
+	if (set(WRITE, i, i) == 0) continue;
+	if (errno != ENOLCK) {
+		e(26);
+		break;
+	}
+  }
+
+  /* Check EMFILE. */
+  for (i = xfd + 1; i < OPEN_MAX; i++) open("T7.i", 0);	/* use up all fds */
+  errno = 0;
+  if (fcntl(xfd, F_DUPFD, 0) != -1) e(27);	/* No fds left */
+  if (errno != EMFILE) e(28);
+
+  for (i = xfd; i < OPEN_MAX; i++) if (close(i) != 0) e(29);
+}
+
+void test7j()
+{
+/* Test file locking with two processes. */
+
+  int s;
+
+  subtest = 10;
+ 
+  if ( (xfd = creat("T7.j", 0777)) != 3) e(1);
+  close(xfd);
+  if ( (xfd = open("T7.j", O_RDWR)) < 0) e(2);
+  if (write(xfd, buf, ITEMS) != ITEMS) e(3);
+  if (set(WRITE, 0, 4) != 0) e(4);	/* lock belongs to parent */
+  if (set(READ, 10, 16) != 0) e(5);	/* lock belongs to parent */
+
+  /* Up until now, all locks have been disjoint.  Now try conflicts. */
+  if (fork()) {
+	/* Parent just waits for child to finish. */
+	wait(&s);
+  } else {
+	/* Child does the testing. */
+	errno = -100;
+	if (set(WRITE, 5, 7) < 0) e(6);	/* should work */
+	if (set(WRITE, 4, 7) >= 0) e(7);	/* child may not lock byte 4 */
+	if (errno != EACCES && errno != EAGAIN) e(8);
+	if (set(WRITE, 5, 9) != 0) e(9);
+	if (set(UNLOCK, 5, 9) != 0) e(10);
+	if (set(READ, 9, 17) < 0) e(11);	/* shared READ lock is ok */
+	exit(0);
+  }
+  close(xfd);
+}
+
+void cloexec_test()
+{
+/* To text whether the FD_CLOEXEC flag actually causes files to be
+ * closed upon exec, we have to exec something.  The test is carried
+ * out by forking, and then having the child exec test7 itself, but
+ * with argument 0.  This is detected, and control comes here.
+ * File descriptors 3 and 10 should be closed here, and 10 open.
+ */
+
+  if (close(3) == 0) e(1001);	/* close should fail; it was closed on exec */
+  if (close(6) != 0) e(1002);	/* close should succeed */
+  if (close(10) == 0) e(1003);	/* close should fail */
+  fflush(stdout);
+  exit(0);
+}
+
+int set(how, first, last)
+int how, first, last;
+{
+  int r;
+  struct flock flock;
+
+  if (how == READ) flock.l_type = F_RDLCK;
+  if (how == WRITE) flock.l_type = F_WRLCK;
+  if (how == UNLOCK) flock.l_type = F_UNLCK;
+  flock.l_whence = whence;
+  flock.l_start = (long) first;
+  flock.l_len = (long) last - (long) first + 1;
+  r = fcntl(xfd, func_code, &flock);
+  if (r != -1) 
+	return(0);
+  else
+	return(-1);
+}
+
+int locked(b)
+int b;
+/* Test to see if byte b is locked.  Return L or U */
+{
+  struct flock flock;
+  pid_t pid;
+  int status;
+
+  flock.l_type = F_WRLCK;
+  flock.l_whence = whence;
+  flock.l_start = (long) b;
+  flock.l_len = 1;
+
+  /* Process' own locks are invisible to F_GETLK, so fork a child to test. */
+  pid = fork();
+  if (pid == 0) {
+	if (fcntl(xfd, F_GETLK, &flock) != 0) e(2000);
+	exit(flock.l_type == F_UNLCK ? U : L);  
+  }
+  if (pid == -1) e(2001);
+  if (fcntl(xfd, F_GETLK, &flock) != 0) e(2002);
+  if (flock.l_type != F_UNLCK) e(2003);
+  if (wait(&status) != pid) e(2004);
+  if (!WIFEXITED(status)) e(2005);
+  return(WEXITSTATUS(status));
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* save errno in case printf clobbers it */
+
+  printf("Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
+  fflush(stdout);
+  errno = err_num;		/* restore errno, just in case */
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+}
+
+void sigfunc(s)
+int s;				/* for ANSI */
+{
+}
+
+void quit()
+{
+
+  chdir("..");
+  system("rm -rf DIR*");
+
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test8.c
===================================================================
--- /trunk/minix/test/test8.c	(revision 9)
+++ /trunk/minix/test/test8.c	(revision 9)
@@ -0,0 +1,265 @@
+/* test8: pipe()		Author: Jan-Mark Wams (jms@cs.vu.nl) */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+
+#define MAX_ERROR	4
+#define ITERATIONS     60
+
+#define Fstat(a,b)	if (fstat(a,b) != 0) printf("Can't fstat %d\n", a)
+#define Time(t)		if (time(t) == (time_t)-1) printf("Time error\n")
+
+int errct = 0;
+int subtest = 1;
+char MaxName[NAME_MAX + 1];	/* Name of maximum length */
+char MaxPath[PATH_MAX];		/* Same for path */
+char ToLongName[NAME_MAX + 2];	/* Name of maximum +1 length */
+char ToLongPath[PATH_MAX + 1];	/* Same for path, both too long */
+
+_PROTOTYPE(void main, (int argc, char *argv[]));
+_PROTOTYPE(void test8a, (void));
+_PROTOTYPE(void test8b, (void));
+_PROTOTYPE(void e, (int number));
+_PROTOTYPE(void quit, (void));
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+  int i, m = 0xFFFF;
+
+  sync();
+  if (argc == 2) m = atoi(argv[1]);
+  printf("Test  8 ");
+  fflush(stdout);
+
+  for (i = 0; i < ITERATIONS; i++) {
+	if (m & 0001) test8a();
+	if (m & 0002) test8b();
+  }
+  quit();
+}
+
+void test8a()
+{				/* Test fcntl flags. */
+  int tube[2], t1[2], t2[2], t3[2];
+  time_t time1, time2;
+  char buf[128];
+  struct stat st1, st2;
+  int stat_loc, flags;
+
+  subtest = 1;
+
+  /* Check if lowest fds are returned. */
+  if (pipe(tube) != 0) e(1);
+  if (tube[0] != 3 && tube[1] != 3) e(2);
+  if (tube[1] != 4 && tube[0] != 4) e(3);
+  if (tube[1] == tube[0]) e(4);
+  if (pipe(t1) != 0) e(5);
+  if (t1[0] != 5 && t1[1] != 5) e(6);
+  if (t1[1] != 6 && t1[0] != 6) e(7);
+  if (t1[1] == t1[0]) e(8);
+  if (close(t1[0]) != 0) e(9);
+  if (close(tube[0]) != 0) e(10);
+  if (pipe(t2) != 0) e(11);
+  if (t2[0] != tube[0] && t2[1] != tube[0]) e(12);
+  if (t2[1] != t1[0] && t2[0] != t1[0]) e(13);
+  if (t2[1] == t2[0]) e(14);
+  if (pipe(t3) != 0) e(15);
+  if (t3[0] != 7 && t3[1] != 7) e(16);
+  if (t3[1] != 8 && t3[0] != 8) e(17);
+  if (t3[1] == t3[0]) e(18);
+  if (close(tube[1]) != 0) e(19);
+  if (close(t1[1]) != 0) e(20);
+  if (close(t2[0]) != 0) e(21);
+  if (close(t2[1]) != 0) e(22);
+  if (close(t3[0]) != 0) e(23);
+  if (close(t3[1]) != 0) e(24);
+
+  /* All time fields should be marked for update. */
+  Time(&time1);
+  if (pipe(tube) != 0) e(25);
+  Fstat(tube[0], &st1);
+  Fstat(tube[1], &st2);
+  Time(&time2);
+  if (st1.st_atime < time1) e(26);
+  if (st1.st_ctime < time1) e(27);
+  if (st1.st_mtime < time1) e(28);
+  if (st1.st_atime > time2) e(29);
+  if (st1.st_ctime > time2) e(30);
+  if (st1.st_mtime > time2) e(31);
+  if (st2.st_atime < time1) e(32);
+  if (st2.st_ctime < time1) e(33);
+  if (st2.st_mtime < time1) e(34);
+  if (st2.st_atime > time2) e(35);
+  if (st2.st_ctime > time2) e(36);
+  if (st2.st_mtime > time2) e(37);
+
+  /* Check the file characteristics. */
+  if ((flags = fcntl(tube[0], F_GETFD)) != 0) e(38);
+  if ((flags & FD_CLOEXEC) != 0) e(39);
+  if ((flags = fcntl(tube[0], F_GETFL)) != 0) e(40);
+  if ((flags & O_RDONLY) != O_RDONLY) e(41);
+  if ((flags & O_NONBLOCK) != 0) e(42);
+  if ((flags & O_RDWR) != 0) e(43);
+  if ((flags & O_WRONLY) != 0) e(44);
+
+  if ((flags = fcntl(tube[1], F_GETFD)) != 0) e(45);
+  if ((flags & FD_CLOEXEC) != 0) e(46);
+  if ((flags = fcntl(tube[1], F_GETFL)) == -1) e(47);
+  if ((flags & O_WRONLY) != O_WRONLY) e(48);
+  if ((flags & O_NONBLOCK) != 0) e(49);
+  if ((flags & O_RDWR) != 0) e(50);
+  if ((flags & O_RDONLY) != 0) e(51);
+
+  /* Check if we can read and write. */
+  switch (fork()) {
+      case -1:	printf("Can't fork\n");	break;
+      case 0:
+	alarm(20);
+	if (close(tube[0]) != 0) e(52);
+	if (write(tube[1], "Hello", 6) != 6) e(53);
+	if (close(tube[1]) != 0) e(54);
+	exit(0);
+      default:
+	if (read(tube[0], buf, sizeof(buf)) != 6) e(55);
+	if (strncmp(buf, "Hello", 6) != 0) e(56);
+	wait(&stat_loc);
+	if (stat_loc != 0) e(57);	/* Alarm? */
+  }
+  if (close(tube[0]) != 0) e(58);
+  if (close(tube[1]) != 0) e(59);
+}
+
+void test8b()
+{
+  int tube[2], child2parent[2], parent2child[2];
+  int i, nchild = 0, nopen = 3, stat_loc;
+  int fd;
+  int forkfailed = 0;
+  char c;
+
+  subtest = 2;
+
+  /* Take all the pipes we can get. */
+  while (nopen < OPEN_MAX - 2) {
+	if (pipe(tube) != 0) {
+		/* We have not reached OPEN_MAX yet, so we have ENFILE. */
+		if (errno != ENFILE) e(1);
+		sleep(2);	/* Wait for others to (maybe) closefiles. */
+		break;
+	}
+	nopen += 2;
+  }
+
+  if (nopen < OPEN_MAX - 2) {
+	if (pipe(tube) != -1) e(2);
+	switch (errno) {
+	    case EMFILE:	/* Errno value is ok. */
+		break;
+	    case ENFILE:	/* No process can open files any more. */
+		switch (fork()) {
+		    case -1:
+			printf("Can't fork\n");
+			break;
+		    case 0:
+			alarm(20);
+			if (open("/", O_RDONLY) != -1) e(3);
+			if (errno != ENFILE) e(4);
+			exit(0);
+		    default:
+			wait(&stat_loc);
+			if (stat_loc != 0) e(5);	/* Alarm? */
+		}
+		break;
+	    default:		/* Wrong value for errno. */
+		e(6);
+	}
+  }
+
+  /* Close all but stdin,out,err. */
+  for (i = 3; i < OPEN_MAX; i++) (void) close(i);
+
+  /* ENFILE test. Have children each grab OPEN_MAX fds. */
+  if (pipe(child2parent) != 0) e(7);
+  if (pipe(parent2child) != 0) e(8);
+  while (!forkfailed && (fd = open("/", O_RDONLY)) != -1) {
+	close(fd);
+	switch (fork()) {
+	    case -1:
+		forkfailed = 1;
+		break;
+	    case 0:
+		alarm(60);
+
+		/* Grab all the fds. */
+		while (pipe(tube) != -1);
+		while (open("/", O_RDONLY) != -1);
+
+		/* Signal parent OPEN_MAX fds gone. */
+		if (write(child2parent[1], "*", 1) != 1) e(9);
+
+		/* Wait for parent befor freeing all the fds. */
+		if (read(parent2child[0], &c, 1) != 1) e(10);
+		exit(0);
+	    default:
+
+		/* Wait for child to grab OPEN_MAX fds. */
+		if (read(child2parent[0], &c, 1) != 1) e(11);
+		nchild++;
+		break;
+	}
+  }
+
+  if (!forkfailed) {
+	if (pipe(tube) != -1) e(12);
+	if (errno != ENFILE) e(13);
+  }
+
+  /* Signal children to die and wait for it. */
+  while (nchild-- > 0) {
+	if (write(parent2child[1], "*", 1) != 1) e(14);
+	wait(&stat_loc);
+	if (stat_loc != 0) e(15);	/* Alarm? */
+  }
+
+  /* Close all but stdin,out,err. */
+  for (i = 3; i < OPEN_MAX; i++) (void) close(i);
+}
+
+void e(n)
+int n;
+{
+  int err_num = errno;		/* Save in case printf clobbers it. */
+
+  printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
+  errno = err_num;
+  perror("");
+  if (errct++ > MAX_ERROR) {
+	printf("Too many errors; test aborted\n");
+	chdir("..");
+	system("rm -rf DIR*");
+	exit(1);
+  }
+  errno = 0;
+}
+
+void quit()
+{
+  if (errct == 0) {
+	printf("ok\n");
+	exit(0);
+  } else {
+	printf("%d errors\n", errct);
+	exit(1);
+  }
+}
Index: /trunk/minix/test/test9.c
===================================================================
--- /trunk/minix/test/test9.c	(revision 9)
+++ /trunk/minix/test/test9.c	(revision 9)
@@ -0,0 +1,273 @@
+/* Test 9 setjmp with register variables.	Author: Ceriel Jacobs */
+
+#include <sys/types.h>
+#include <setjmp.h>
+#include <signal.h>
+
+#define MAX_ERROR 4
+
+#include "common.c"
+
+char *tmpa;
+
+_PROTOTYPE(int main, (int argc, char *argv []));
+_PROTOTYPE(void test9a, (void));
+_PROTOTYPE(void test9b, (void));
+_PROTOTYPE(void test9c, (void));
+_PROTOTYPE(void test9d, (void));
+_PROTOTYPE(void test9e, (void));
+_PROTOTYPE(void test9f, (void));
+_PROTOTYPE(char *addr, (void));
+_PROTOTYPE(void garbage, (void));
+_PROTOTYPE(void  level1, (void));
+_PROTOTYPE(void level2, (void));
+_PROTOTYPE(void dolev, (void));
+_PROTOTYPE(void catch, (int s));
+_PROTOTYPE(void hard, (void));
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  jmp_buf envm;
+  int i, j, m = 0xFFFF;
+
+  start(9);
+  if (argc == 2) m = atoi(argv[1]);
+  for (j = 0; j < 100; j++) {
+	if (m & 00001) test9a();
+	if (m & 00002) test9b();
+	if (m & 00004) test9c();
+	if (m & 00010) test9d();
+	if (m & 00020) test9e();
+	if (m & 00040) test9f();
+  }
+  if (errct) quit();
+  i = 1;
+  if (setjmp(envm) == 0) {
+	i = 2;
+	longjmp(envm, 1);
+  } else {
+	if (i == 2) {
+		/* Correct */
+	} else if (i == 1) {
+		printf("WARNING: The setjmp/longjmp of this machine restore register variables\n\
+to the value they had at the time of the Setjmp\n");
+	} else {
+		printf("Aha, I just found one last error\n");
+		return 1;
+	}
+  }
+  quit();
+  return(-1);			/* impossible */
+}
+
+void test9a()
+{
+  register p;
+
+  subtest = 1;
+  p = 200;
+  garbage();
+  if (p != 200) e(1);
+}
+
+void test9b()
+{
+  register p, q;
+
+  subtest = 2;
+  p = 200;
+  q = 300;
+  garbage();
+  if (p != 200) e(1);
+  if (q != 300) e(2);
+}
+
+void test9c()
+{
+  register p, q, r;
+
+  subtest = 3;
+  p = 200;
+  q = 300;
+  r = 400;
+  garbage();
+  if (p != 200) e(1);
+  if (q != 300) e(2);
+  if (r != 400) e(3);
+}
+
+char buf[512];
+
+void test9d()
+{
+  register char *p;
+
+  subtest = 4;
+  p = &buf[100];
+  garbage();
+  if (p != &buf[100]) e(1);
+}
+
+void test9e()
+{
+  register char *p, *q;
+
+  subtest = 5;
+  p = &buf[100];
+  q = &buf[200];
+  garbage();
+  if (p != &buf[100]) e(1);
+  if (q != &buf[200]) e(2);
+}
+
+void test9f()
+{
+  register char *p, *q, *r;
+
+  subtest = 6;
+  p = &buf[100];
+  q = &buf[200];
+  r = &buf[300];
+  garbage();
+  if (p != &buf[100]) e(1);
+  if (q != &buf[200]) e(2);
+  if (r != &buf[300]) e(3);
+}
+
+jmp_buf env;
+
+/*	return address of local variable.
+  This way we can check that the stack is not polluted.
+*/
+char *
+ addr()
+{
+  char a;
+
+  return &a;
+}
+
+void garbage()
+{
+  register i, j, k;
+  register char *p, *q, *r;
+  char *a;
+
+  p = &buf[300];
+  q = &buf[400];
+  r = &buf[500];
+  i = 10;
+  j = 20;
+  k = 30;
+  switch (setjmp(env)) {
+      case 0:
+	a = addr();
+#ifdef __GNUC__
+	/*
+	 * to defeat the smartness of the GNU C optimizer we pretend we
+	 * use 'a'. Otherwise the optimizer will not detect the looping
+	 * effectuated by setjmp/longjmp, so that it thinks it can get
+	 * rid of the assignment to 'a'.
+	 */
+	srand((unsigned)&a);
+#endif
+	longjmp(env, 1);
+	break;
+      case 1:
+	if (i != 10) e(11);
+	if (j != 20) e(12);
+	if (k != 30) e(13);
+	if (p != &buf[300]) e(14);
+	if (q != &buf[400]) e(15);
+	if (r != &buf[500]) e(16);
+	tmpa = addr();
+	if (a != tmpa) e(17);
+	level1();
+	break;
+      case 2:
+	if (i != 10) e(21);
+	if (j != 20) e(22);
+	if (k != 30) e(23);
+	if (p != &buf[300]) e(24);
+	if (q != &buf[400]) e(25);
+	if (r != &buf[500]) e(26);
+	tmpa = addr();
+	if (a != tmpa) e(27);
+	level2();
+	break;
+      case 3:
+	if (i != 10) e(31);
+	if (j != 20) e(32);
+	if (k != 30) e(33);
+	if (p != &buf[300]) e(34);
+	if (q != &buf[400]) e(35);
+	if (r != &buf[500]) e(36);
+	tmpa = addr();
+	if (a != tmpa) e(37);
+	hard();
+      case 4:
+	if (i != 10) e(41);
+	if (j != 20) e(42);
+	if (k != 30) e(43);
+	if (p != &buf[300]) e(44);
+	if (q != &buf[400]) e(45);
+	if (r != &buf[500]) e(46);
+	tmpa = addr();
+	if (a != tmpa) e(47);
+	return;
+	break;
+      default:	e(100);
+  }
+  e(200);
+}
+
+void level1()
+{
+  register char *p;
+  register i;
+
+  i = 1000;
+  p = &buf[10];
+  i = 200;
+  p = &buf[20];
+  longjmp(env, 2);
+}
+
+void level2()
+{
+  register char *p;
+  register i;
+
+  i = 0200;
+  p = &buf[2];
+  *p = i;
+  dolev();
+}
+
+void dolev()
+{
+  register char *p;
+  register i;
+
+  i = 010;
+  p = &buf[3];
+  *p = i;
+  longjmp(env, 3);
+}
+
+void catch(s)
+int s;
+{
+  longjmp(env, 4);
+}
+
+void hard()
+{
+  register char *p;
+
+  signal(SIGHUP, catch);
+  for (p = buf; p <= &buf[511]; p++) *p = 025;
+  kill(getpid(), SIGHUP);
+}
Index: /trunk/minix/test/testsh1.sh
===================================================================
--- /trunk/minix/test/testsh1.sh	(revision 9)
+++ /trunk/minix/test/testsh1.sh	(revision 9)
@@ -0,0 +1,310 @@
+#!/bin/sh
+
+# Shell script used to test MINIX.
+
+PATH=:/bin:/usr/bin
+export PATH
+
+echo -n "Shell test  1 "
+rm -rf DIR_SH1
+mkdir DIR_SH1
+cd DIR_SH1
+
+f=../test1.c
+if test -r $f; then : ; else echo sh1 cannot read $f; exit 1; fi
+
+#Initial setup
+echo "abcdefghijklmnopqrstuvwxyz" >alpha
+echo "ABCDEFGHIJKLMNOPQRSTUVWXYZ" >ALPHA
+echo "0123456789" >num
+echo "!@#$%^&*()_+=-{}[]:;<>?/.," >special
+cp /etc/rc rc
+cp /etc/passwd passwd
+cat alpha ALPHA num rc passwd special >tmp
+cat tmp tmp tmp >f1
+
+
+#Test cp
+mkdir foo
+cp /etc/rc /etc/passwd foo
+if cmp -s foo/rc /etc/rc ; then : ; else echo Error on cp test 1; fi
+if cmp -s foo/passwd /etc/passwd ; then : ; else echo Error on cp test 2; fi
+rm -rf foo
+
+#Test cat
+cat num num num num num >y
+wc -c y >x1
+echo "     55 y" >x2
+if cmp -s x1 x2; then : ; else echo Error on cat test 1; fi
+cat <y >z
+if cmp -s y z; then : ; else echo Error on cat test 2; fi
+
+#Test ar
+cat passwd >p
+cp passwd q
+if cmp -s p q; then : ; else echo Error on ar test 1; fi
+date >r
+ar r x.a p q r 2>/dev/null
+ar r x.a /usr/bin/cp
+ar r x.a /usr/bin/cat
+rm p q
+mv r R
+ar x x.a
+if cmp -s p /etc/passwd; then : ; else Error on ar test 2; fi
+if cmp -s q /etc/passwd; then : ; else Error on ar test 3; fi
+if cmp -s r R; then : ; else Error on ar test 4; fi
+if cmp -s cp /usr/bin/cp; then : ; else Error on ar test 5; fi
+if cmp -s cat /usr/bin/cat; then : ; else Error on ar test 6; fi
+rm cp cat p q r
+ar d x.a r >/dev/null
+ar x x.a
+if test -r r; then echo Error on ar test 7; fi
+rm -rf p q r R
+
+#Test basename
+if test `basename /usr/ast/foo.c .c` != 'foo'
+   then echo Error on basename test 1
+fi
+
+if test `basename a/b/c/d` != 'd'; then Error on basename test 2; fi
+
+#Test cdiff, sed, and patch
+cp $f x.c			# x.c is a copy $f
+echo "/a/s//#####/g" >s		# create sed script
+sed -f s <x.c >y.c		# y.c is new version of x.c
+cdiff x.c y.c >y		# y is cdiff listing
+patch x.c y  2>/dev/null	# z should be y.c
+if cmp -s x.c y.c; then : ; else echo Error in cdiff test; fi
+rm x.c* y.c s y
+
+#Test comm, grep -v
+ls /etc >x			# x = list of /etc
+grep -v "passwd" x >y		# y = x except for /etc/passwd
+comm -3 x y >z			# should only be 1 line, /etc/passwd
+echo "passwd" >w
+if cmp -s w z; then : else echo Error on comm test 1; fi
+
+comm -13 x y >z			# should be empty
+if test -s z; then echo Error on comm test 2; fi
+rm -rf w x y z
+
+#Test compress
+compress -fc $f >x.c.Z		# compress the test file
+compress -cd x.c.Z >y		# uncompress it
+if cmp -s $f y; then : else echo Error in compress test 1; fi
+rm -rf x.c.Z y
+
+#Test ed
+cp $f x				# copy $f to x
+cat >y <<END
+g/a/s//#####/g
+g/b/s//@@@@@/g
+g/c/s//!!!!!/g
+w
+q
+END
+ed x <y >/dev/null
+cat >y <<END
+g/#####/s//a/g
+g/@@@@@/s//b/g
+g/!!!!!/s//c/g
+w
+q
+END
+ed x <y >/dev/null
+if cmp -s x $f; then : ; else echo Error in ed test 1; fi
+rm x y
+
+#Test expr
+if test `expr 1 + 1` != 2; then echo Error on expr test 1; fi
+if test `expr 10000 - 1` != 9999; then echo Error on expr test 2; fi
+if test `expr 100 '*' 50` != 5000; then echo Error on expr test 3; fi
+if test `expr 120 / 5` != 24; then echo Error on expr test 4; fi
+if test `expr 143 % 7` != 3; then echo Error on expr test 5; fi
+a=100
+a=`expr $a + 1`
+if test $a != '101'; then echo Error on expr test 6; fi
+
+#Test fgrep
+fgrep "abc" alpha >z
+if cmp -s alpha z ; then : else echo Error on fgrep test 1; fi
+fgrep "abc" num >z
+if test -s z; then echo Error on fgrep test 2; fi
+cat alpha num >z
+fgrep "012" z >w
+if cmp -s w num; then : ; else echo Error fgrep test 3; fi
+
+
+#Test find
+date >Rabbit
+echo "Rabbit" >y
+find . -name Rabbit -print >z
+if cmp -s y z; then : else echo Error on find test 1; fi
+find . -name Bunny -print >z
+if test -s z; then echo Error on find test 2; fi
+rm Rabbit y z
+
+#Test grep
+grep "a" alpha >x
+if cmp -s x alpha; then : ; else echo Error on grep test 1; fi
+grep "a" ALPHA >x
+if test -s x; then echo Error on grep test 2; fi
+grep -v "0" alpha >x
+if cmp -s x alpha; then : ; else echo Error on grep test 3; fi
+grep -s "a" alpha >x
+if test -s x; then echo Error on grep test 4; fi
+if grep -s "a" alpha >x; then : else echo Error on grep test 5; fi
+if grep -s "a" ALPHA >x; then echo Error on grep test 6; fi
+
+#Test head
+head -1 f1 >x
+if cmp -s x alpha; then : else echo Error on head test 1; fi
+head -2 f1 >x
+cat alpha ALPHA >y
+if cmp -s x y; then : else echo Error on head test 2; fi
+
+#Test ls
+mkdir FOO
+cp passwd FOO/z
+cp alpha FOO/x
+cp ALPHA FOO/y
+cd FOO
+ls >w
+cat >w1 <<END
+w
+x
+y
+z
+END
+if cmp -s w w1; then : ; else echo Error on ls test 1; fi
+rm *
+cd ..
+rmdir FOO
+
+#Test mkdir/rmdir
+mkdir Foo Bar
+if test -d Foo; then : ; else echo Error on mkdir test 1; fi
+if test -d Bar; then : ; else echo Error on mkdir test 2; fi
+rmdir Foo Bar
+if test -d Foo; then echo Error on mkdir test 3; fi
+if test -d Foo; then echo Error on rmdir test 4; fi
+
+#Test mv
+mkdir MVDIR
+cp $f x
+mv x y
+mv y z
+if cmp -s $f z; then : ; else echo Error on mv test 1; fi
+cp $f x
+mv x MVDIR/y
+if cmp -s $f MVDIR/y; then : ; else echo Error on mv test 2; fi
+
+#Test rev
+rev <f1 | head -1 >ahpla
+echo "zyxwvutsrqponmlkjihgfedcba" >x
+if cmp -s x ahpla; then : ; else echo Error on rev test 1; fi
+rev <$f >x
+rev <x >y
+if cmp -s $f x; then echo Error on rev test 2; fi
+if cmp -s $f y; then : ; else echo error on rev test 3; fi
+
+#Test shar
+cp $f w
+cp alpha x
+cp ALPHA y
+cp num z
+shar w x y z >x1
+rm w x y z
+sh <x1 >/dev/null
+if cmp -s w $f; then : ; else echo Error on shar test 1; fi
+if cmp -s x alpha; then : ; else echo Error on shar test 2; fi
+if cmp -s y ALPHA; then : ; else echo Error on shar test 3; fi
+if cmp -s z num; then : ; else echo Error on shar test 4; fi
+
+#Test sort
+sort <$f >x
+wc <$f >x1
+wc <x >x2
+if cmp -s x1 x2; then : ; else echo Error on sort test 1; fi
+cat >x <<END
+demit 10
+epitonic 40
+apoop 20
+bibelot 3
+comate 4
+END
+cat >y <<END
+apoop 20
+bibelot 3
+comate 4
+demit 10
+epitonic 40
+END
+cat >z <<END
+epitonic 40
+demit 10
+comate 4
+bibelot 3
+apoop 20
+END
+sort <x >x1
+if cmp -s y x1; then : ; else echo Error on sort test 2; fi
+sort -r <x1 >x2
+if cmp -s x2 z; then : ; else echo Error on sort test 3; fi
+sort +1 -n <x |head -1 >y
+echo "bibelot 3" >z
+if cmp -s y z; then : ; else echo Error on sort test 4; fi
+
+#Test tail
+tail -1 f1 >x
+if cmp -s x special; then : ; else echo Error on tail test 1; fi
+
+#Test tsort
+cat >x <<END
+a d
+b e
+c f
+a c
+p z
+k p
+a k
+a b
+b c
+c d
+d e
+e f
+f k
+END
+cat >answer <<END
+a
+b
+c
+d
+e
+f
+k
+p
+z
+END
+tsort <x >y
+if cmp -s y answer; then : ; else echo Error on tsort test 1; fi
+
+#Test uue/uud
+cp $f x
+uue x
+if test -s x.uue; then : ; else echo Error on uue/uud test 1; fi
+rm x
+uud x.uue
+if cmp -s x $f; then : ; else echo Error on uue/uud test 2; fi
+
+compress -fc x >x.Z 2>/dev/null
+uue x.Z
+rm x x.Z
+uud x.uue
+compress -cd x.Z >x
+if cmp -s x $f; then : ; else echo Error on uue/uud test 3; fi
+
+cd ..
+rm -rf DIR_SH1
+
+echo ok
Index: /trunk/minix/test/testsh2.sh
===================================================================
--- /trunk/minix/test/testsh2.sh	(revision 9)
+++ /trunk/minix/test/testsh2.sh	(revision 9)
@@ -0,0 +1,260 @@
+#!/bin/sh
+
+# Shell script #2 used to test MINIX.
+
+PATH=:/bin:/usr/bin
+export PATH
+
+# CC="exec cc -wo -F"		# nonstandard flags for ACK :-(
+CC=cc
+
+ARCH=`arch`
+
+echo -n "Shell test  2 "
+rm -rf DIR_SH2
+mkdir DIR_SH2			# all files are created here
+cd DIR_SH2
+
+cat >file <<END
+The time has come the walrus said to talk of many things
+Of shoes and ships and sealing wax of cabbages and kings
+Of why the sea is boiling hot and whether pigs have wings
+END
+f=file				# scratch file
+
+cat >makefile <<END		# create a makefile
+all:	x.c
+	@$CC x.c >/dev/null 2>&1
+END
+cat >x.c <<END			# create a C program
+#include <stdio.h>
+char s[] = {"MS-DOS: Just say no"};	/* used by strings later */
+main() 
+{
+  int i; 
+  for (i = 15; i < 18; i++) printf("%d\\n",i*i);
+}
+END
+
+cat >answer <<END		# C program should produce these results
+225
+256
+289
+END
+
+make
+if test -f a.out; then : ; else echo Compilation failed; fi
+a.out >x
+if test -f x; then : ; else echo No compiler output; fi
+if cmp -s x answer; then : ; else echo Error in cc test 1; fi
+
+#Test chmod
+echo Hi there folks >x
+if test -r x; then : ; else echo Error on chmod test 1; fi
+chmod 377 x
+if test -r x; then test -w / || echo Error on chmod test 2; fi
+chmod 700 x
+if test -r x; then : ; else echo Error on chmod test 3; fi
+
+#Test cut
+cat >x <<END			# x is a test file with 3 columns
+1 white bunny
+2 gray  rabbits
+3 brown hares
+4 black conies
+END
+
+cat >answer <<END		# after cutting out cols 3-7, we get this
+white
+gray 
+brown
+black
+END
+
+cut -c 3-7 x >y			# extract columns 3-7
+if cmp -s y answer; then : ; else echo Error in cut test 1; fi
+
+#Test dd
+dd if=$f of=x bs=12 count=1 2>/dev/null		# x = bytes 0-11
+dd if=$f of=y bs=6 count=4 skip=2 2>/dev/null	# y = bytes 11-35
+cat x y >z					# z = bytes 0-35
+dd if=$f of=answer bs=9 count=4 2>/dev/null	# answer = bytes 0-35
+if cmp -s z answer; then : ; else echo Error in dd test 1; fi
+
+#Test df			# hard to make a sensible Test here
+rm ?
+df >x
+if test -r x; then : ; else echo Error in df Test 1; fi
+
+#Test du			# see df
+rm ?
+du >x
+if test -r x; then : ; else echo Error in du Test 1; fi
+
+#Test od			
+head -1 $f |od >x		# see if od converts ascii to octal ok
+if [ $ARCH = i86 -o $ARCH = i386 ]
+then
+cat >answer <<END
+0000000 064124 020145 064564 062555 064040 071541 061440 066557
+0000020 020145 064164 020145 060567 071154 071565 071440 064541
+0000040 020144 067564 072040 066141 020153 063157 066440 067141
+0000060 020171 064164 067151 071547 000012
+0000071
+END
+else
+cat >answer <<END
+0000000 052150 062440 072151 066545 020150 060563 020143 067555
+0000020 062440 072150 062440 073541 066162 072563 020163 060551
+0000040 062040 072157 020164 060554 065440 067546 020155 060556
+0000060 074440 072150 064556 063563 005000
+0000071
+END
+fi
+
+if cmp -s x answer; then : ; else echo Error in od test 1; fi
+
+head -1 $f |od -d >x		# see if od converts ascii to decimal ok
+if [ $ARCH = i86 -o $ARCH = i386 ]
+then
+cat >answer <<END
+0000000 26708 08293 26996 25965 26656 29537 25376 28015
+0000020 08293 26740 08293 24951 29292 29557 29472 26977
+0000040 08292 28532 29728 27745 08299 26223 27936 28257
+0000060 08313 26740 28265 29543 00010
+0000071
+END
+else
+cat >answer <<END
+0000000 21608 25888 29801 28005 08296 24947 08291 28525
+0000020 25888 29800 25888 30561 27762 30067 08307 24937
+0000040 25632 29807 08308 24940 27424 28518 08301 24942
+0000060 31008 29800 26990 26483 02560
+0000071
+END
+fi
+
+if cmp -s x answer; then : ; else echo Error in od test 2; fi
+
+#Test paste
+cat >x <<END
+red
+green
+blue
+END
+
+cat >y <<END
+rood
+groen
+blauw
+END
+cat >answer <<END
+red	rood
+green	groen
+blue	blauw
+END
+
+paste x y >z
+if cmp -s z answer; then : ; else echo Error in paste test 1; fi
+
+#Test prep
+echo >x <<END
+"Hi," said Carol, laughing, "How's life?"
+END
+
+echo >answer <<END
+hi
+said
+carol
+laughing
+how's
+life
+END
+
+if cmp -s x answer; then : ; else echo Error in prep test 1; fi
+
+#Test printenv
+printenv >x
+if grep HOME  x >/dev/null; then : ; else echo Error in printenv test 1; fi
+if grep PATH  x >/dev/null; then : ; else echo Error in printenv test 2; fi
+if grep SHELL x >/dev/null; then : ; else echo Error in printenv test 3; fi
+if grep USER  x >/dev/null; then : ; else echo Error in printenv test 4; fi
+
+#Test pwd
+pwd >Pwd_file
+cd `pwd`
+pwd >x
+if test -s Pwd_file;  then : ; else echo Error in pwd test 1; fi
+if cmp -s Pwd_file x; then : ; else echo Error in pwd test 2; fi
+
+#Test strings
+strings a.out | grep "MS-DOS" >x
+cat >answer <<END
+MS-DOS: Just say no
+END
+
+if cmp -s x answer; then : ; else echo Error in strings test 1; fi
+
+#Test sum
+sum $f >x
+cat >answer <<END
+29904     1
+END
+
+if cmp -s x answer; then : ; else echo Error in sum test 1; fi
+
+#Test tee
+cat $f | tee x >/dev/null
+if cmp -s x $f; then : ; else echo Error in tee test 1; fi
+
+#Test true
+if true ; then : ; else echo Error in true test 1; fi
+
+#Test uniq
+cat >x <<END
+100
+200
+200
+300
+END
+
+cat >answer <<END
+100
+200
+300
+END
+
+uniq <x >y
+if cmp -s y answer; then : ; else echo Error in uniq test 1; fi
+
+#Test pipelines
+cat >x <<END
+the big black dog
+the little white cat
+the big white sheep
+the little black cat
+END
+
+cat >answer <<END
+   1 dog
+   1 sheep
+   2 big
+   2 black
+   2 cat
+   2 little
+   2 white
+   4 the
+END
+
+prep x | sort | uniq -c >y1
+sort +1 <y1 >y
+if cmp -s y answer; then : ; else echo Error in pipeline test 1; fi
+
+cat $f $f $f | sort | uniq >x
+sort <$f >y
+if cmp -s x y; then : ; else echo Error in pipeline test 2; fi
+
+cd ..
+rm -rf DIR_SH2
+
+echo ok
Index: /trunk/minix/tools/Makefile
===================================================================
--- /trunk/minix/tools/Makefile	(revision 9)
+++ /trunk/minix/tools/Makefile	(revision 9)
@@ -0,0 +1,100 @@
+# Makefile for the kernel image.
+
+u=/usr
+CC=	exec cc
+CFLAGS=	-O -D_MINIX -D_POSIX_SOURCE
+MDEC=	/usr/mdec
+
+# Specify the programs that are part of the system image.
+PROGRAMS=	../kernel/kernel \
+	../servers/pm/pm \
+	../servers/fs/fs \
+	../servers/rs/rs \
+	../servers/ds/ds \
+	../drivers/tty/tty \
+	../drivers/memory/memory \
+	../drivers/log/log \
+	../servers/init/init
+
+usage:	
+	@echo " " >&2
+	@echo "Master Makefile to create new MINIX configuration." >& 2
+	@echo "Root privileges are required." >&2
+	@echo " " >&2
+	@echo "Usage:" >&2
+	@echo "	make includes   # Install include files" >&2
+	@echo "	make depend     # Generate dependency files" >&2
+	@echo "	make libraries  # Make system libraries" >&2
+	@echo "	make services   # Compile and install all services" >&2
+	@echo "	make fresh      # Make clean, libraries, and services" >&2
+	@echo "	make image      # Make needed services and create boot image" >&2
+	@echo "	make install    # Make image, and install to hard disk" >&2
+	@echo "	make hdboot     # Make image, and install to hard disk" >&2
+	@echo "	make fdboot     # Make image, and install to floppy disk" >&2
+	@echo "	make bootable   # Make hard disk bootable" >&2
+	@echo "	make clean      # Remove all compiler results, except libs" >&2
+	@echo " " >&2
+	@echo "To create a fresh MINIX configuration, try:" >&2
+	@echo "	make clean install      # new boot image" >&2
+	@echo "	make fresh install      # new everything" >&2
+	@echo " " >&2
+
+# create a fresh configuration or system image
+fresh: 
+	cd ../lib && $(MAKE) clean
+	$(MAKE) clean 
+	$(MAKE) libraries services
+
+all: services image
+
+image:  includes
+	cd ../kernel && $(MAKE) 
+	cd ../servers && $(MAKE) image
+	cd ../drivers && $(MAKE) image
+	installboot -image $@ $(PROGRAMS)
+
+image_small:  includes
+	cd ../kernel && $(MAKE) 
+	cd ../servers && $(MAKE) EXTRA_OPTS=-D_MINIX_SMALL=1 image
+	cd ../drivers && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) image
+	installboot -image $@ $(PROGRAMS)
+
+# rebuild the program or system libraries
+includes:
+	cd ../include && $(MAKE) install
+
+depend: includes
+	cd ../ && $(MAKE) depend
+
+services: includes 
+	cd ../kernel && $(MAKE) 
+	cd ../servers && $(MAKE) install
+	cd ../drivers && $(MAKE) install
+
+libraries: includes
+	cd ../lib && $(MAKE) clean
+	cd ../lib && $(MAKE) all
+	cd ../lib && $(MAKE) install
+
+
+# make bootable and place system images
+bootable:
+	exec su root mkboot bootable
+
+hdboot:	image
+	exec sh mkboot $@
+	@sync
+
+fdboot:	image
+	exec su root mkboot $@
+	@sync
+
+install: includes services hdboot
+
+# clean up compile results
+clean:
+	cd ../kernel && $(MAKE) $@
+	cd ../servers && $(MAKE) $@
+	cd ../drivers && $(MAKE) $@
+	rm -rf *.bak image image_small *.iso *.iso.gz cdfdimage rootimage src
+
Index: /trunk/minix/tools/chrootmake.sh
===================================================================
--- /trunk/minix/tools/chrootmake.sh	(revision 9)
+++ /trunk/minix/tools/chrootmake.sh	(revision 9)
@@ -0,0 +1,26 @@
+#!/bin/sh
+set -e
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
+export SHELL=/bin/sh
+cd /usr/src 
+make etcfiles
+su bin -c 'make world install' 
+cd tools 
+rm revision
+rm /boot/image/*
+make install 
+cp /boot/image/* /boot/image_big  # Make big image accessible by this name
+cp ../boot/boot /boot/boot 
+make clean
+make image_small 
+cp image_small /boot 
+cd /usr/src 
+make clean
+# Let man find the manpages
+su bin -c 'makewhatis /usr/man'
+su bin -c 'makewhatis /usr/gnu/man'
+su bin -c 'makewhatis /usr/local/man'
+mv /usr/src/commands /usr/src.commands
+binsizes normal
+exit 0
+
Index: /trunk/minix/tools/fdbootparams
===================================================================
--- /trunk/minix/tools/fdbootparams	(revision 9)
+++ /trunk/minix/tools/fdbootparams	(revision 9)
@@ -0,0 +1,1 @@
+rootdev=c0d0p0s0; ramimagedev=c0d0p0s0; save
Index: /trunk/minix/tools/issue.install
===================================================================
--- /trunk/minix/tools/issue.install	(revision 9)
+++ /trunk/minix/tools/issue.install	(revision 9)
@@ -0,0 +1,17 @@
+
+Welcome to MINIX 3.1.2. The system is now running and many commands work
+normally.  To use MINIX 3.1.2 in a serious way, you need to install it
+to your hard disk, which you can do by typing 'setup' while logged in as
+root.  Then just follow the on-screen directions.
+
+After setup is complete, type 'shutdown' and when the boot monitor
+starts, boot your new system by following the instructions at the end of
+setup.  Keep the CD-ROM in the drive, login as root and type 'packman'
+to begin installing the many software packages available.  After you
+have installed the packages, type 'xdm' to start X Windows if you have
+installed it.
+
+It is strongly recommended that you print and read the 'setup.pdf' file
+on the CD-ROM before staring the installation. The file is also
+available at www.minix3.org/doc under the 'Installation' heading.
+
Index: /trunk/minix/tools/mkboot
===================================================================
--- /trunk/minix/tools/mkboot	(revision 9)
+++ /trunk/minix/tools/mkboot	(revision 9)
@@ -0,0 +1,196 @@
+#!/bin/sh
+#
+#	mkboot 2.0 - make boot floppy, make root device bootable, etc.
+#							Author: Kees J. Bot
+
+trap 'e=$?; rm -f /tmp/mkb.$$; exit $e' 0 2
+
+mdec=/usr/mdec	# bootstraps
+
+# Check arguments.
+case "$#:$1" in
+1:bootable | 1:hdboot | [12]:fdboot | [12]:cdfdboot )
+	action=$1 dev=$2
+	;;
+*)	echo "Usage: $0 [bootable | hdboot | cdfdboot | fdboot [device]] | cdfdboot [device]" >&2
+	exit 1
+esac
+
+# Get the device table.
+. /etc/fstab
+
+# The real root device may be the RAM disk.
+realroot=`printroot -r`
+
+# If it's an initial fstab, pretend root is real root
+if [ $root = "/dev/ROOT" ]
+then	root=$realroot
+fi
+
+case $action in
+bootable | hdboot)
+	# We need the root device.
+
+	if [ $realroot = $root ]
+	then
+		rootdir=
+	else
+		umount $root 2>/dev/null
+		mount $root /mnt || exit
+		rootdir=/mnt
+	fi
+esac
+
+case $action in
+bootable)
+	# Install the boot monitor on the root device and make it bootable.
+	install -cs -m 644 $mdec/boot $rootdir/boot/boot || exit
+	sync
+	installboot -device $root $mdec/bootblock /boot/boot || exit
+	test $realroot != $root && umount $root
+	;;
+hdboot)
+	# Install a new image on the root device.
+	if [ ! -d $rootdir/boot/image ]
+	then
+		 /boot/image is not yet a directory!  Fix it.
+		su root -c \
+		    "exec mv $rootdir/boot/image /M"
+		install -d $rootdir/boot/image
+		su root -c \
+		    "exec mv $rootdir/M $rootdir/boot/image/`uname -r`.`uname -v`"
+	fi
+
+	sh tell_config OS_RELEASE . OS_VERSION >/tmp/mkb.$$
+	version=`sed 's/[" 	]//g;/^$/d' </tmp/mkb.$$`
+
+	revision=`cat revision 2>/dev/null`
+
+	if [ -z "$revision" ]
+	then	rrevision=""
+	else	rrevision=r$revision
+	fi
+
+	oldrev=$revision
+
+	target="${version}r${revision}"
+
+	if [ -z "$revision" ]
+	then
+		revision=0
+		rrevision=""
+	elif [ -f $rootdir/boot/image/$target ]
+	then
+		if [ $rootdir/boot/image/$target -newer image ]
+		then
+			echo "$root:/boot/image/$target is up to date"
+			test $realroot != $root && umount $root
+			exit 0
+		fi
+		revision=`expr $revision + 1`
+		rrevision=r$revision
+	fi
+	target="${version}${rrevision}"
+
+	set -- `ls -t $rootdir/boot/image`
+
+	case $# in
+	0|1|2|3)
+		# Not much there, do not remove a thing.
+		;;
+	*)
+		# Remove the third-newest image in /boot/image, but
+		# only if there's an older one (which is kept). 
+		echo "rm $root:/boot/image/$3"
+		rm -f "$rootdir/boot/image/$3"
+	esac
+
+	# Install the new image.
+	echo "install image $root:/boot/image/$target"
+	install -o root -m 600 image $rootdir/boot/image/$target || exit
+
+	# Save the revision number.
+	test "$revision" != "$oldrev" && echo $revision >revision
+
+	test $realroot != $root && umount $root
+	echo "Done."
+	;;
+fdboot)
+	# fdboot: Make a boot floppy.
+
+	if [ -z "$dev" ]
+	then
+		echo -n \
+"Finish the name of the floppy device to write (by default 'fd0'): /dev/";
+		read dev
+		case "$dev" in
+		'')	dev=/dev/fd0
+			;;
+		/dev/*)
+			;;
+		*)	dev=/dev/$dev
+		esac
+	fi
+
+	# Make a file system.
+	umount $dev 2>/dev/null
+	if mkfs -B 1024 -i 512 $dev
+	then	:
+	else
+		echo "mkfs of $dev failed."
+		exit 1;
+	fi
+
+	# Install /dev, /boot/boot and /boot/image.
+	mount $dev /mnt || exit
+	mkdir -p /mnt/boot/image || exit
+	cpdir /dev /mnt/dev || exit
+	cp -p $mdec/boot /mnt/boot/boot || exit
+	cp -p image /mnt/boot/image/ || exit
+	umount $dev || exit
+
+	# Make bootable and copy the boot parameters.
+	installboot -d $dev $mdec/bootblock /boot/boot || exit
+	pfile=fdbootparams
+	if [ -f $pfile ]
+	then	echo "Using floppy boot parameters from file $pfile."
+		edparams $dev "`cat $pfile`" || exit
+	else	echo "Copying floppy boot parameters from $root."
+		dd if=$root of=$dev skip=1 seek=1 count=1 conv=silent || exit
+	fi
+	edparams $dev 'main(){delay 2000;boot}; save' || exit
+	echo "Test kernel installed on $dev"
+	;;
+
+cdfdboot)
+	# cdfdboot: Make a boot floppy image to go on a CD for booting from.
+	if [ -z "$dev" ]
+	then
+		ramdisk `expr 1440 \* 1024` 2>/dev/null
+		dev=/dev/ram
+	fi
+	umount $dev 2>/dev/null
+	if mkfs -B 1024 -b 1440 -i 512 $dev || exit 1
+	then :
+	else
+		echo "mkfs of $dev failed."
+		exit 1;
+	fi
+
+	# Install /dev, /boot
+	mount $dev /mnt || exit 1
+	mkdir /mnt/dev
+	mkdir /mnt/boot
+	mkdir /mnt/boot/image
+	( cd /mnt/dev && sh /usr/src/commands/scripts/MAKEDEV.sh std )
+	cp -p image image_* /mnt/boot/image || exit 1
+	cp -p ../boot/boot /mnt/boot/boot || exit 1
+	umount $dev || exit 1
+	installboot -d $dev ../boot/bootblock boot/boot || exit 1
+	edparams $dev 'unset bootopts; unset servers; disable=inet; image=/boot/image/image; bootbig(1, Regular MINIX 3 (requires at least 16 MB RAM)) { image=/boot/image/image ; boot } bootsmall(2, Small MINIX 3 (intended for 8 MB systems)) { image=/boot/image/image_small ; boot } cdproberoot=1; unset rootdev; unset leader; leader() { echo \n--- Welcome to MINIX 3. This is the boot monitor. ---\n\nChoose an option from the menu or press ESC if you need to do anything special.\nOtherwise I will boot with my defaults in 10 seconds.\n\n }; bootcd=1; main(){trap 10000 boot; menu; }; save' || exit
+
+	# copy image
+	dd if=$dev of=cdfdimage bs=8192 count=180
+esac
+sync
+exit 0
Index: /trunk/minix/tools/release.sh
===================================================================
--- /trunk/minix/tools/release.sh	(revision 9)
+++ /trunk/minix/tools/release.sh	(revision 9)
@@ -0,0 +1,391 @@
+#!/bin/sh
+
+set -e
+
+PACKAGEDIR=/usr/bigports/Packages
+PACKAGESOURCEDIR=/usr/bigports/Sources
+secs=`expr 32 '*' 64`
+export SHELL=/bin/sh
+
+make_hdimage()
+{
+	dd if=$TMPDISK of=usrimage bs=$BS count=$USRBLOCKS
+
+	rootsize=`stat -size rootimage`
+	usrsize=`stat -size usrimage`
+
+	rootsects=`expr $rootsize / 512`
+	usrsects=`expr $usrsize / 512`
+
+	# installboot -m needs at least 1KB 
+	dd < /dev/zero >tmpimage count=2
+	partition -fm tmpimage 2 81:$rootsects* 0:0 81:$usrsects
+	installboot -m tmpimage /usr/mdec/masterboot
+	dd < tmpimage > subpart count=1
+
+	primsects=`expr 1 + $rootsects + $usrsects`
+	cyl=`expr '(' $primsects ')' / $secs + 1`
+	padsects=`expr $cyl \* $secs - 1 - $primsects`
+
+	{ dd < /dev/zero count=1
+		cat subpart
+		cat rootimage
+		cat usrimage
+		dd < /dev/zero count=$padsects
+	} > hdimage
+	partition -m hdimage 81:`expr $primsects + $padsects`*
+	installboot -m hdimage /usr/mdec/masterboot
+}
+
+hdemu_root_changes()
+{
+	$RELEASEDIR/usr/bin/installboot -d $TMPDISK3 \
+		$RELEASEDIR/usr/mdec/bootblock boot/boot
+	echo \
+'bootcd=2
+disable=inet
+bios_wini=yes
+bios_remap_first=1
+ramimagedev=c0d7p0s0
+bootbig(1, Regular MINIX 3) { image=/boot/image_big; boot }
+bootsmall(2, Small MINIX 3 (<16MB)) {image=/boot/image_small; boot }
+main() { trap 10000 boot ; menu; }
+save'	| $RELEASEDIR/usr/bin/edparams $TMPDISK3
+
+	echo \
+'root=/dev/c0d7p0s0
+usr=/dev/c0d7p0s2
+usr_roflag="-r"' > $RELEASEDIR/etc/fstab
+}
+
+usb_root_changes()
+{
+	$RELEASEDIR/usr/bin/installboot -d $TMPDISK3 \
+		$RELEASEDIR/usr/mdec/bootblock boot/boot
+	echo \
+'bios_wini=yes
+bios_remap_first=1
+rootdev=c0d7p0s0
+save'	| $RELEASEDIR/usr/bin/edparams $TMPDISK3
+
+	echo \
+'root=/dev/c0d7p0s0
+usr=/dev/c0d7p0s2
+' > $RELEASEDIR/etc/fstab
+}
+
+COPYITEMS="usr/bin bin usr/lib"
+RELEASEDIR=/usr/r
+RELEASEPACKAGE=${RELEASEDIR}/usr/install/packages
+RELEASEPACKAGESOURCES=${RELEASEDIR}/usr/install/package-sources
+IMAGE=cdfdimage
+ROOTIMAGE=rootimage
+CDFILES=/usr/tmp/cdreleasefiles
+sh tell_config OS_RELEASE . OS_VERSION >/tmp/rel.$$
+version_pretty=`sed 's/["      ]//g;/^$/d' </tmp/rel.$$`
+version=`sed 's/["      ]//g;/^$/d' </tmp/rel.$$ | tr . _`
+subfn="subreleaseno.$version"
+if [ -f "$subfn" ]
+then	sub="`cat $subfn`"
+else	sub=0
+fi
+echo "`expr $sub + 1`" >$subfn
+IMG_BASE=minix${version}_ide_build$sub
+BS=4096
+
+HDEMU=0
+COPY=0
+CVSTAG=HEAD
+PACKAGES=1
+
+while getopts "pchu?r:" c
+do
+	case "$c" in
+	\?)
+		echo "Usage: $0 [-p] [-c] [-h] [-r <tag>] [-u]" >&2
+		exit 1
+	;;
+	h)
+		echo " * Making HD image"
+		IMG_BASE=minix${version}_bios_build$sub
+		HDEMU=1
+		;;
+	c)
+		echo " * Copying, not CVS"
+		COPY=1
+		;;
+	p)
+		PACKAGES=0
+		;;
+	r)	
+		CVSTAG=$OPTARG
+		;;
+	u)
+		echo " * Making live USB-stick image"
+		IMG_BASE=minix${version}_usb_build$sub
+		HDEMU=1
+		USB=1
+		;;
+	esac
+done
+
+if [ "$USB" -ne 0 ]; then
+	IMG=${IMG_BASE}.img
+else
+	IMG=${IMG_BASE}.iso
+fi
+IMGBZ=${IMG}.bz2
+echo "Making $IMGBZ"
+
+USRMB=400
+
+USRBLOCKS="`expr $USRMB \* 1024 \* 1024 / $BS`"
+USRSECTS="`expr $USRMB \* 1024 \* 2`"
+ROOTKB=4096
+ROOTSECTS="`expr $ROOTKB \* 2`"
+ROOTBLOCKS="`expr $ROOTKB \* 1024 / $BS`"
+
+if [ "$COPY" -ne 1 ]
+then
+	echo "Note: this script wants to do cvs operations, so it's necessary"
+	echo "to have \$CVSROOT set and cvs login done."
+	echo ""
+fi
+
+TD1=.td1
+TD2=.td2
+TD3=.td3
+
+
+if [ -f $TD1 ]
+then    TMPDISK="`cat $TD1`"
+	echo " * Warning: I'm going to overwrite $TMPDISK!"
+else
+        echo "Temporary (sub)partition to use to make the /usr FS image? "
+        echo "I need $USRMB MB. It will be mkfsed!"
+        echo -n "Device: /dev/"
+        read dev || exit 1
+        TMPDISK=/dev/$dev
+fi
+
+if [ -b $TMPDISK ]
+then :
+else	echo "$TMPDISK is not a block device.."
+	exit 1
+fi
+
+echo $TMPDISK >$TD1
+
+if [ -f $TD2 ]
+then    TMPDISK2="`cat $TD2`"
+	echo " * Warning: I'm going to overwrite $TMPDISK2!"
+else
+        echo "Temporary (sub)partition to use for /tmp? "
+        echo "It will be mkfsed!"
+        echo -n "Device: /dev/"
+        read dev || exit 1
+        TMPDISK2=/dev/$dev
+fi
+
+if [ -b $TMPDISK2 ]
+then :
+else	echo "$TMPDISK2 is not a block device.."
+	exit 1
+fi
+
+echo $TMPDISK2 >$TD2
+
+if [ -f $TD3 ]
+then    TMPDISK3="`cat $TD3`"
+	echo " * Warning: I'm going to overwrite $TMPDISK3!"
+else
+        echo "It has to be at least $ROOTKB KB."
+        echo ""
+        echo "Temporary (sub)partition to use to make the root FS image? "
+        echo "It will be mkfsed!"
+        echo -n "Device: /dev/"
+        read dev || exit 1
+        TMPDISK3=/dev/$dev
+fi
+
+if [ -b $TMPDISK3 ]
+then :
+else	echo "$TMPDISK3 is not a block device.."
+	exit 1
+fi
+
+echo $TMPDISK3 >$TD3
+
+umount $TMPDISK || true
+umount $TMPDISK2 || true
+umount $TMPDISK3 || true
+
+if [ $TMPDISK = $TMPDISK2  -o $TMPDISK = $TMPDISK3 -o $TMPDISK2 = $TMPDISK3 ]
+then
+	echo "Temporary devices can't be equal."
+	exit
+fi
+
+echo " * Cleanup old files"
+rm -rf $RELEASEDIR $IMG $IMAGE $ROOTIMAGE $IMGBZ $CDFILES image*
+mkdir -p $CDFILES || exit
+mkdir -p $RELEASEDIR
+mkfs -B $BS -b $ROOTBLOCKS $TMPDISK3 || exit
+mkfs $TMPDISK2 || exit
+echo " * mounting $TMPDISK3 as $RELEASEDIR"
+mount $TMPDISK3 $RELEASEDIR || exit
+mkdir -m 755 $RELEASEDIR/usr
+mkdir -m 1777 $RELEASEDIR/tmp
+mount $TMPDISK2 $RELEASEDIR/tmp
+
+mkfs -B $BS -b $USRBLOCKS $TMPDISK || exit
+echo " * Mounting $TMPDISK as $RELEASEDIR/usr"
+mount $TMPDISK $RELEASEDIR/usr || exit
+mkdir -p $RELEASEDIR/tmp
+mkdir -p $RELEASEDIR/usr/tmp
+mkdir -p $RELEASEPACKAGE
+mkdir -p $RELEASEPACKAGESOURCES
+
+echo " * Transfering $COPYITEMS to $RELEASEDIR"
+( cd / && tar cf - $COPYITEMS ) | ( cd $RELEASEDIR && tar xf - ) || exit 1
+
+if [ -d $PACKAGEDIR -a -d $PACKAGESOURCEDIR -a $PACKAGES -ne 0 ]
+then	echo " * Indexing packages"
+	bintotal=0
+	( cd $PACKAGEDIR
+	  for p in *.tar.bz2
+	  do	echo $p >&2
+		p="`echo $p | sed 's/.tar.bz2//'`"
+		descr="../$p/.descr"
+		if [ -f "$descr" ]
+		then	echo "$p|`cat $descr`"
+		fi
+	  done >List
+	)
+	for d in $PACKAGEDIR $PACKAGESOURCEDIR
+	do	echo Counting size of $d
+		f=$d/SizeMB
+		if [ ! -f $f ]
+		then
+			b="`bzip2 -dc $d/*.bz2 | wc -c`"
+			echo "`expr 1 + $b / 1024 / 1024`" >$f
+		fi
+		echo "`cat $f` MB."
+	done
+	echo " * Transfering $PACKAGEDIR to $RELEASEPACKAGE"
+	cp $PACKAGEDIR/* $RELEASEPACKAGE/
+	echo " * Transfering $PACKAGESOURCEDIR to $RELEASEPACKAGESOURCES"
+	cp $PACKAGESOURCEDIR/* $RELEASEPACKAGESOURCES/ || true
+
+fi
+
+# Make sure compilers and libraries are bin-owned
+chown -R bin $RELEASEDIR/usr/lib
+chmod -R u+w $RELEASEDIR/usr/lib
+
+if [ "$COPY" -ne 1 ]
+then
+	echo " * Doing new cvs export"
+	( cd $RELEASEDIR/usr && mkdir src && cvs export -r$CVSTAG src )
+else
+	( cd .. && make depend && make clean )
+	srcdir=/usr/src
+	( cd $srcdir && tar cf - . ) | ( cd $RELEASEDIR/usr && mkdir src && cd src && tar xf - )
+fi
+
+echo " * Fixups for owners and modes of dirs and files"
+chown -R bin $RELEASEDIR/usr/src 
+chmod -R u+w $RELEASEDIR/usr/src 
+find $RELEASEDIR/usr/src -type d | xargs chmod 755
+find $RELEASEDIR/usr/src -type f | xargs chmod 644
+find $RELEASEDIR/usr/src -name configure | xargs chmod 755
+find $RELEASEDIR/usr/src/commands -name build | xargs chmod 755
+# Bug tracking system not for on cd
+rm -rf $RELEASEDIR/usr/src/doc/bugs
+
+# Make sure the CD knows it's a CD, unless it's not
+if [ "$USB" -eq 0 ]
+then	date >$RELEASEDIR/CD
+fi
+echo " * Chroot build"
+chroot $RELEASEDIR "/bin/sh -x /usr/src/tools/chrootmake.sh" || exit 1
+echo " * Chroot build done"
+# The build process leaves some file in src as root.
+chown -R bin $RELEASEDIR/usr/src*
+cp issue.install $RELEASEDIR/etc/issue
+
+if [ "$USB" -ne 0 ]
+then
+	usb_root_changes
+elif [ "$HDEMU" -ne 0 ]
+then
+	hdemu_root_changes
+fi
+
+echo $version_pretty >$RELEASEDIR/etc/version
+echo " * Counting files"
+extrakb=`du -s $RELEASEDIR/usr/install | awk '{ print $1 }'`
+expr `df $TMPDISK | tail -1 | awk '{ print $4 }'` - $extrakb >$RELEASEDIR/.usrkb
+du -s $RELEASEDIR/usr/src.* | awk '{ t += $1 } END { print t }' >$RELEASEDIR/.extrasrckb
+( for d in $RELEASEDIR/usr/src.*; do find $d; done) | wc -l >$RELEASEDIR/.extrasrcfiles
+find $RELEASEDIR/usr | fgrep -v /install/ | wc -l >$RELEASEDIR/.usrfiles
+find $RELEASEDIR -xdev | wc -l >$RELEASEDIR/.rootfiles
+echo " * Zeroing remainder of temporary areas"
+df $TMPDISK
+df $TMPDISK3
+cp /dev/zero $RELEASEDIR/usr/.x 2>/dev/null || true
+rm $RELEASEDIR/usr/.x
+cp /dev/zero $RELEASEDIR/.x 2>/dev/null || true
+rm $RELEASEDIR/.x
+
+umount $TMPDISK || exit
+umount $TMPDISK2 || exit
+umount $TMPDISK3 || exit
+(cd ../boot && make)
+(cd .. && make depend)
+make clean
+make image || exit 1
+mv image image_big
+make clean
+make image_small || exit 1
+dd if=$TMPDISK3 of=$ROOTIMAGE bs=$BS count=$ROOTBLOCKS
+# Prepare image and image_small for cdfdboot
+mv image_big image
+sh mkboot cdfdboot $TMPDISK3
+cp $IMAGE $CDFILES/bootflop.img
+cp release/cd/* $CDFILES || true
+echo "This is Minix version $version_pretty prepared `date`." >$CDFILES/VERSION.TXT
+
+h_opt=
+bootimage=$IMAGE
+if [ "$HDEMU" -ne 0 ]; then
+	make_hdimage
+	h_opt='-h'
+	bootimage=hdimage
+fi
+
+if [ "$USB" -ne 0 ]; then
+	mv $bootimage $IMG
+else
+	writeisofs -l MINIX -b $bootimage $h_opt $CDFILES $IMG || exit 1
+
+	if [ "$HDEMU" -eq 0 ]
+	then
+		echo "Appending Minix root and usr filesystem"
+		# Pad ISO out to cylinder boundary
+		isobytes=`stat -size $IMG`
+		isosects=`expr $isobytes / 512`
+		isopad=`expr $secs - '(' $isosects % $secs ')'`
+		dd if=/dev/zero count=$isopad >>$IMG
+		# number of sectors
+		isosects=`expr $isosects + $isopad`
+		( cat $IMG $ROOTIMAGE ;
+			dd if=$TMPDISK bs=$BS count=$USRBLOCKS ) >m
+		mv m $IMG
+		# Make CD partition table
+		installboot -m $IMG /usr/mdec/masterboot
+		# Make sure there is no hole..! Otherwise the ISO format is
+		# unreadable.
+		partition -m $IMG 0 81:$isosects 81:$ROOTSECTS 81:$USRSECTS
+	fi
+fi
Index: /trunk/minix/tools/release/cd/README.TXT
===================================================================
--- /trunk/minix/tools/release/cd/README.TXT	(revision 9)
+++ /trunk/minix/tools/release/cd/README.TXT	(revision 9)
@@ -0,0 +1,65 @@
+Welcome to MINIX 3.
+
+MINIX 3 Copyright 2006, 1997, 1987 Vrije Universiteit
+All rights reserved.
+
+------------------------------------------------------------------------
+
+SYSTEM REQUIREMENTS:
+
+Below is a list of minimum system requirements to install the software on this CD.
+
+HARDWARE
+*MINIX 3 OS requires the following hardware:
+	- PC with a Pentium or compatible processor
+	- at least 8 MB of RAM
+	- at least 200 MB of free disk space
+	- IDE CD-ROM drive
+	- IDE hard disk
+	- NOT SUPPORTED: USB and SCSI disks; Some Serial ATA disks work.
+	- For alternative configurations, visit http://www.minix3.org
+
+SOFTWARE
+* This is a live CD-ROM. You can insert it into your computer and boot from it.
+MINIX 3 will start automatically and you can log in as root. It does NOT require
+Windows, Linux, or any other operating system as it is self contained. However,
+to use it effectively, you must install it on your hard disk. Detailed instal-
+lation instructions are given in the SETUP.PDF file. To read this file, you need
+the Adobe Acrobat Reader, available for free at http://www.adobe.com/acrobat.
+The SETUP.PS file contains the same content in PostScript. Please be sure to
+read one of these files before attempting to install MINIX 3 as you must
+partition your hard disk before starting and this subject is discussed in the
+SETUP files. Disk partitioning must be done very carefully to prevent data loss.
+These SETUP files are also available on the MINIX 3 Website: 
+http://www.minix3.org/doc. Please have a printed copy of the SETUP file available
+while you are doing the installation, as it will be very helpful to you then.
+
+WARNING
+* MINIX 3 is an operating system and will overwrite all the data in the
+partition in which it is installed. Be sure to back up all your files
+before installing it.
+
+------------------------------------------------------------------------
+
+CD CONTENTS:
+
+This CD contains:
+
+   - README.TXT      This file
+   - SETUP.PS:       setup guide in PostScript
+   - SETUP.PDF:      setup guide in PDF (requires Adobe Acrobat reader)
+   - PRESZ134.ZIP    Windows utility to resize FAT partitions
+   - BOOTFLOP.IMG    If you cannot boot from CD-ROMs, insert the CD-ROM
+                     anyway, then copy this floppy image raw to a floppy
+                     using RawWrite (ask Google) and boot from the floppy
+
+There are also many invisible files used for installing MINIX 3.
+
+------------------------------------------------------------------------
+
+PRODUCT SUPPORT:
+
+For further technical information about the MINIX software on this CD,
+visit the official MINIX website at
+
+	http://www.minix3.org
Index: /trunk/minix/tools/revision
===================================================================
--- /trunk/minix/tools/revision	(revision 9)
+++ /trunk/minix/tools/revision	(revision 9)
@@ -0,0 +1,1 @@
+0
Index: /trunk/minix/tools/tell_config
===================================================================
--- /trunk/minix/tools/tell_config	(revision 9)
+++ /trunk/minix/tools/tell_config	(revision 9)
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+#	tellconfig - Tell the value of a <minix/config.h> parameter
+#						Author: Kees J. Bot
+
+echo "
+#include <minix/config.h>
+$*
+" >/tmp/tell.$$
+exec </tmp/tell.$$
+rm /tmp/tell.$$
+
+exec cc -P -E -
